Repository: EpicGamesExt/raddebugger Branch: master Commit: 08642d2745da Files: 490 Total size: 28.5 MB Directory structure: gitextract_k3109d9_/ ├── .gitattributes ├── .github/ │ └── workflows/ │ └── builds.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.bat ├── build.sh ├── data/ │ └── logo.rc ├── project.4coder ├── run_tests.bat └── src/ ├── artifact_cache/ │ ├── artifact_cache.c │ └── artifact_cache.h ├── base/ │ ├── base_arena.c │ ├── base_arena.h │ ├── base_command_line.c │ ├── base_command_line.h │ ├── base_context_cracking.h │ ├── base_core.c │ ├── base_core.h │ ├── base_entry_point.c │ ├── base_entry_point.h │ ├── base_hash.c │ ├── base_hash.h │ ├── base_inc.c │ ├── base_inc.h │ ├── base_log.c │ ├── base_log.h │ ├── base_markup.c │ ├── base_markup.h │ ├── base_math.c │ ├── base_math.h │ ├── base_meta.c │ ├── base_meta.h │ ├── base_profile.c │ ├── base_profile.h │ ├── base_strings.c │ ├── base_strings.h │ ├── base_thread_context.c │ ├── base_thread_context.h │ ├── base_threads.c │ └── base_threads.h ├── codeview/ │ ├── codeview.c │ ├── codeview.h │ ├── codeview.mdesk │ ├── codeview_dump.c │ ├── codeview_dump.h │ ├── codeview_parse.c │ ├── codeview_parse.h │ └── generated/ │ ├── codeview.meta.c │ └── codeview.meta.h ├── coff/ │ ├── coff.c │ ├── coff.h │ ├── coff_dump.c │ ├── coff_dump.h │ ├── coff_enum.c │ ├── coff_inc.c │ ├── coff_inc.h │ ├── coff_lib_writer.c │ ├── coff_lib_writer.h │ ├── coff_obj_writer.c │ ├── coff_obj_writer.h │ ├── coff_parse.c │ └── coff_parse.h ├── config/ │ ├── config_bindings.c │ ├── config_bindings.h │ ├── config_core.c │ ├── config_core.h │ ├── config_inc.c │ ├── config_inc.h │ ├── config_panels.c │ └── config_panels.h ├── content/ │ ├── content.c │ └── content.h ├── ctrl/ │ ├── ctrl.mdesk │ ├── ctrl_core.c │ ├── ctrl_core.h │ ├── ctrl_inc.c │ ├── ctrl_inc.h │ └── generated/ │ ├── ctrl.meta.c │ └── ctrl.meta.h ├── dbg_engine/ │ ├── dbg_engine.mdesk │ ├── dbg_engine_core.c │ ├── dbg_engine_core.h │ ├── dbg_engine_inc.c │ ├── dbg_engine_inc.h │ └── generated/ │ ├── dbg_engine.meta.c │ └── dbg_engine.meta.h ├── dbg_info/ │ ├── dbg_info.c │ └── dbg_info.h ├── demon/ │ ├── demon_core.c │ ├── demon_core.h │ ├── demon_core.mdesk │ ├── demon_inc.c │ ├── demon_inc.h │ ├── generated/ │ │ ├── demon.meta.c │ │ └── demon.meta.h │ ├── linux/ │ │ ├── demon_core_linux.c │ │ ├── demon_core_linux.h │ │ ├── demon_os_linux.c │ │ └── demon_os_linux.h │ └── win32/ │ ├── demon_core_win32.c │ └── demon_core_win32.h ├── disasm/ │ ├── disasm.c │ └── disasm.h ├── draw/ │ ├── draw.c │ ├── draw.h │ ├── draw.mdesk │ └── generated/ │ ├── draw.meta.c │ └── draw.meta.h ├── dwarf/ │ ├── dwarf.c │ ├── dwarf.h │ ├── dwarf_coff.c │ ├── dwarf_coff.h │ ├── dwarf_dump.c │ ├── dwarf_dump.h │ ├── dwarf_elf.c │ ├── dwarf_elf.h │ ├── dwarf_expr.c │ ├── dwarf_expr.h │ ├── dwarf_help.c │ ├── dwarf_help.h │ ├── dwarf_inc.c │ ├── dwarf_inc.h │ ├── dwarf_notes.txt │ ├── dwarf_parse.c │ ├── dwarf_parse.h │ ├── dwarf_unwind.c │ ├── dwarf_unwind.h │ ├── eh_dump.c │ ├── eh_dump.h │ ├── eh_frame.c │ └── eh_frame.h ├── elf/ │ ├── elf.c │ ├── elf.h │ ├── elf_dump.c │ ├── elf_dump.h │ ├── elf_parse.c │ └── elf_parse.h ├── eval/ │ ├── eval.mdesk │ ├── eval_core.c │ ├── eval_core.h │ ├── eval_inc.c │ ├── eval_inc.h │ ├── eval_interpret.c │ ├── eval_interpret.h │ ├── eval_ir.c │ ├── eval_ir.h │ ├── eval_parse.c │ ├── eval_parse.h │ ├── eval_types.c │ ├── eval_types.h │ └── generated/ │ ├── eval.meta.c │ └── eval.meta.h ├── eval_visualization/ │ ├── eval_visualization_core.c │ ├── eval_visualization_core.h │ ├── eval_visualization_inc.c │ └── eval_visualization_inc.h ├── file_stream/ │ ├── file_stream.c │ └── file_stream.h ├── font_cache/ │ ├── font_cache.c │ └── font_cache.h ├── font_provider/ │ ├── dwrite/ │ │ ├── font_provider_dwrite.c │ │ └── font_provider_dwrite.h │ ├── font_provider.c │ ├── font_provider.h │ ├── font_provider_inc.c │ ├── font_provider_inc.h │ └── freetype/ │ ├── font_provider_freetype.c │ └── font_provider_freetype.h ├── gnu/ │ ├── gnu.c │ └── gnu.h ├── lib_raddbg_markup/ │ └── raddbg_markup.h ├── lib_rdi/ │ ├── rdi.c │ ├── rdi.h │ ├── rdi_parse.c │ └── rdi_parse.h ├── lib_rdi_make/ │ ├── rdi_make.c │ └── rdi_make.h ├── linker/ │ ├── base_ext/ │ │ ├── base_arena.c │ │ ├── base_arena.h │ │ ├── base_arrays.c │ │ ├── base_arrays.h │ │ ├── base_bit_array.c │ │ ├── base_bit_array.h │ │ ├── base_blake3.c │ │ ├── base_blake3.h │ │ ├── base_core.c │ │ ├── base_core.h │ │ ├── base_crc32.c │ │ ├── base_crc32.h │ │ ├── base_inc.c │ │ ├── base_inc.h │ │ ├── base_strings.c │ │ └── base_strings.h │ ├── codeview_ext/ │ │ ├── codeview.c │ │ └── codeview.h │ ├── hash_table.c │ ├── hash_table.h │ ├── linker.natvis │ ├── lnk.c │ ├── lnk.h │ ├── lnk_cmd_line.c │ ├── lnk_cmd_line.h │ ├── lnk_config.c │ ├── lnk_config.h │ ├── lnk_debug_helper.c │ ├── lnk_debug_helper.h │ ├── lnk_debug_info.c │ ├── lnk_debug_info.h │ ├── lnk_error.c │ ├── lnk_error.h │ ├── lnk_io.c │ ├── lnk_io.h │ ├── lnk_lib.c │ ├── lnk_lib.h │ ├── lnk_log.c │ ├── lnk_log.h │ ├── lnk_obj.c │ ├── lnk_obj.h │ ├── lnk_section_table.c │ ├── lnk_section_table.h │ ├── lnk_symbol_table.c │ ├── lnk_symbol_table.h │ ├── lnk_timer.c │ ├── lnk_timer.h │ ├── pdb_ext/ │ │ ├── msf_builder.c │ │ ├── msf_builder.h │ │ ├── pdb.c │ │ ├── pdb.h │ │ ├── pdb_builder.c │ │ ├── pdb_builder.h │ │ ├── pdb_helpers.c │ │ └── pdb_helpers.h │ ├── rdi/ │ │ ├── rdi_builder.c │ │ ├── rdi_builder.h │ │ ├── rdi_coff.c │ │ ├── rdi_coff.h │ │ ├── rdi_cv.c │ │ ├── rdi_cv.h │ │ └── rdi_overrides.h │ ├── scripts/ │ │ └── obj_paths_from_pdb.py │ └── thread_pool/ │ ├── thread_pool.c │ └── thread_pool.h ├── mdesk/ │ ├── mdesk.c │ └── mdesk.h ├── metagen/ │ ├── metagen.c │ ├── metagen.h │ ├── metagen_base/ │ │ ├── metagen_base_arena.c │ │ ├── metagen_base_arena.h │ │ ├── metagen_base_command_line.c │ │ ├── metagen_base_command_line.h │ │ ├── metagen_base_context_cracking.h │ │ ├── metagen_base_core.c │ │ ├── metagen_base_core.h │ │ ├── metagen_base_entry_point.c │ │ ├── metagen_base_entry_point.h │ │ ├── metagen_base_inc.c │ │ ├── metagen_base_inc.h │ │ ├── metagen_base_log.c │ │ ├── metagen_base_log.h │ │ ├── metagen_base_markup.c │ │ ├── metagen_base_markup.h │ │ ├── metagen_base_math.c │ │ ├── metagen_base_math.h │ │ ├── metagen_base_meta.c │ │ ├── metagen_base_meta.h │ │ ├── metagen_base_profile.c │ │ ├── metagen_base_profile.h │ │ ├── metagen_base_strings.c │ │ ├── metagen_base_strings.h │ │ ├── metagen_base_thread_context.c │ │ └── metagen_base_thread_context.h │ ├── metagen_main.c │ └── metagen_os/ │ ├── core/ │ │ ├── linux/ │ │ │ ├── metagen_os_core_linux.c │ │ │ └── metagen_os_core_linux.h │ │ ├── metagen_os_core.c │ │ ├── metagen_os_core.h │ │ └── win32/ │ │ ├── metagen_os_core_win32.c │ │ └── metagen_os_core_win32.h │ ├── metagen_os_inc.c │ └── metagen_os_inc.h ├── msf/ │ ├── msf.c │ ├── msf.h │ ├── msf_parse.c │ └── msf_parse.h ├── msvc_crt/ │ ├── msvc_crt.c │ └── msvc_crt.h ├── mule/ │ ├── inline_body.cpp │ ├── mule_c.c │ ├── mule_c.h │ ├── mule_hotload_main.c │ ├── mule_hotload_module_main.c │ ├── mule_inline.cpp │ ├── mule_main.cpp │ ├── mule_module.cpp │ ├── mule_o2.cpp │ ├── mule_peb_trample.c │ └── mule_peb_trample_reload.c ├── mutable_text/ │ ├── mutable_text.c │ └── mutable_text.h ├── natvis/ │ └── base.natvis ├── os/ │ ├── core/ │ │ ├── linux/ │ │ │ ├── os_core_linux.c │ │ │ ├── os_core_linux.h │ │ │ ├── os_core_linux_old.c │ │ │ └── os_core_linux_old.h │ │ ├── os_core.c │ │ ├── os_core.h │ │ └── win32/ │ │ ├── os_core_win32.c │ │ └── os_core_win32.h │ ├── gfx/ │ │ ├── generated/ │ │ │ ├── os_gfx.meta.c │ │ │ └── os_gfx.meta.h │ │ ├── linux/ │ │ │ ├── os_gfx_linux.c │ │ │ └── os_gfx_linux.h │ │ ├── os_gfx.c │ │ ├── os_gfx.h │ │ ├── os_gfx.mdesk │ │ ├── stub/ │ │ │ ├── os_gfx_stub.c │ │ │ └── os_gfx_stub.h │ │ └── win32/ │ │ ├── os_gfx_win32.c │ │ └── os_gfx_win32.h │ ├── os_inc.c │ └── os_inc.h ├── pdb/ │ ├── pdb.c │ ├── pdb.h │ ├── pdb_parse.c │ ├── pdb_parse.h │ ├── pdb_stringize.c │ └── pdb_stringize.h ├── pe/ │ ├── dos_program.asm │ ├── pe.c │ ├── pe.h │ ├── pe_make_debug_dir.c │ ├── pe_make_debug_dir.h │ ├── pe_make_export_table.c │ ├── pe_make_export_table.h │ ├── pe_make_import_table.c │ ├── pe_make_import_table.h │ └── pe_section_flags.h ├── radbin/ │ ├── generated/ │ │ ├── radbin.meta.c │ │ └── radbin.meta.h │ ├── radbin.c │ ├── radbin.h │ ├── radbin.mdesk │ └── radbin_main.c ├── raddbg/ │ ├── generated/ │ │ ├── raddbg.meta.c │ │ └── raddbg.meta.h │ ├── raddbg.mdesk │ ├── raddbg_core.c │ ├── raddbg_core.h │ ├── raddbg_eval.c │ ├── raddbg_eval.h │ ├── raddbg_inc.c │ ├── raddbg_inc.h │ ├── raddbg_legacy_config.c │ ├── raddbg_legacy_config.h │ ├── raddbg_main.c │ ├── raddbg_views.c │ ├── raddbg_views.h │ ├── raddbg_widgets.c │ └── raddbg_widgets.h ├── raddump/ │ ├── raddump.c │ ├── raddump.h │ └── raddump_main.c ├── rdi/ │ ├── rdi.mdesk │ ├── rdi_local.c │ └── rdi_local.h ├── rdi_from_coff/ │ ├── rdi_from_coff.c │ └── rdi_from_coff.h ├── rdi_from_dwarf/ │ ├── rdi_from_dwarf.c │ └── rdi_from_dwarf.h ├── rdi_from_elf/ │ ├── rdi_from_elf.c │ └── rdi_from_elf.h ├── rdi_from_pdb/ │ ├── rdi_from_pdb.c │ └── rdi_from_pdb.h ├── rdi_make/ │ ├── rdi_make_local.c │ └── rdi_make_local.h ├── regs/ │ ├── generated/ │ │ ├── regs.meta.c │ │ └── regs.meta.h │ ├── rdi/ │ │ ├── generated/ │ │ │ ├── regs_rdi.meta.c │ │ │ └── regs_rdi.meta.h │ │ ├── regs_rdi.c │ │ ├── regs_rdi.h │ │ └── regs_rdi.mdesk │ ├── regs.c │ ├── regs.h │ └── regs.mdesk ├── render/ │ ├── d3d11/ │ │ ├── generated/ │ │ │ ├── render_d3d11.meta.c │ │ │ └── render_d3d11.meta.h │ │ ├── render_d3d11.c │ │ ├── render_d3d11.h │ │ └── render_d3d11.mdesk │ ├── generated/ │ │ ├── render.meta.c │ │ └── render.meta.h │ ├── opengl/ │ │ ├── generated/ │ │ │ ├── render_opengl.meta.c │ │ │ └── render_opengl.meta.h │ │ ├── linux/ │ │ │ ├── egl/ │ │ │ │ ├── render_opengl_linux_egl.c │ │ │ │ └── render_opengl_linux_egl.h │ │ │ ├── glx/ │ │ │ │ ├── render_opengl_linux_glx.c │ │ │ │ └── render_opengl_linux_glx.h │ │ │ ├── render_opengl_linux.c │ │ │ └── render_opengl_linux.h │ │ ├── render_opengl.c │ │ ├── render_opengl.h │ │ ├── render_opengl.mdesk │ │ └── win32/ │ │ ├── render_opengl_win32.c │ │ └── render_opengl_win32.h │ ├── render_core.c │ ├── render_core.h │ ├── render_core.mdesk │ ├── render_inc.c │ ├── render_inc.h │ └── stub/ │ ├── render_stub.c │ └── render_stub.h ├── scratch/ │ ├── debugstringperf.c │ ├── eval_scratch.c │ ├── parse_inline_sites.c │ ├── ryan_scratch.c │ └── textperf.c ├── stap/ │ ├── stap_parse.c │ ├── stap_parse.h │ └── stap_test.c ├── strip_lib_debug/ │ └── strip_lib_debug.c ├── tester/ │ └── tester_main.c ├── text/ │ ├── generated/ │ │ ├── text.meta.c │ │ └── text.meta.h │ ├── text.c │ ├── text.h │ └── text.mdesk ├── third_party/ │ ├── blake3/ │ │ ├── asm/ │ │ │ ├── LICENSE │ │ │ ├── blake3.c │ │ │ ├── blake3.h │ │ │ ├── blake3_avx2_x86-64_unix.S │ │ │ ├── blake3_avx2_x86-64_windows_msvc.asm │ │ │ ├── blake3_avx512_x86-64_unix.S │ │ │ ├── blake3_avx512_x86-64_windows_msvc.asm │ │ │ ├── blake3_dispatch.c │ │ │ ├── blake3_impl.h │ │ │ ├── blake3_neon.c │ │ │ ├── blake3_portable.c │ │ │ ├── blake3_sse2_x86-64_unix.S │ │ │ ├── blake3_sse2_x86-64_windows_msvc.asm │ │ │ ├── blake3_sse41_x86-64_unix.S │ │ │ └── blake3_sse41_x86-64_windows_msvc.asm │ │ └── c/ │ │ ├── LICENSE │ │ ├── blake3.c │ │ ├── blake3.h │ │ ├── blake3_avx2.c │ │ ├── blake3_avx512.c │ │ ├── blake3_dispatch.c │ │ ├── blake3_impl.h │ │ ├── blake3_neon.c │ │ ├── blake3_portable.c │ │ ├── blake3_sse2.c │ │ └── blake3_sse41.c │ ├── martins_hash/ │ │ ├── md5.h │ │ ├── sha1.h │ │ ├── sha256.h │ │ └── sha512.h │ ├── rad_lzb_simple/ │ │ ├── rad_lzb_simple.c │ │ └── rad_lzb_simple.h │ ├── radsort/ │ │ └── radsort.h │ ├── sinfl/ │ │ └── sinfl.h │ ├── stb/ │ │ ├── stb_image.h │ │ └── stb_sprintf.h │ ├── xxHash/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── SECURITY.md │ │ ├── doc/ │ │ │ ├── README.md │ │ │ ├── xxhash.cry │ │ │ └── xxhash_spec.md │ │ ├── xxh3.h │ │ ├── xxh_x86dispatch.c │ │ ├── xxh_x86dispatch.h │ │ ├── xxhash.c │ │ └── xxhash.h │ └── zydis/ │ ├── zydis.c │ └── zydis.h ├── torture/ │ └── torture.c ├── ui/ │ ├── generated/ │ │ ├── ui.meta.c │ │ └── ui.meta.h │ ├── ui.mdesk │ ├── ui_basic_widgets.c │ ├── ui_basic_widgets.h │ ├── ui_core.c │ ├── ui_core.h │ ├── ui_inc.c │ └── ui_inc.h └── x64/ ├── x64.c └── x64.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.sh text=auto eol=lf ================================================ FILE: .github/workflows/builds.yml ================================================ name: builds on: push: paths-ignore: - '**.md' pull_request: paths-ignore: - '**.md' jobs: build-windows-2022: runs-on: windows-2022 strategy: fail-fast: false matrix: target: - raddbg - radlink - radbin compiler: - msvc - clang mode: - debug - release steps: - name: checkout uses: actions/checkout@v2 - name: build (vs 2022) shell: cmd run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 call build "${{ matrix.target }}" "${{ matrix.compiler }}" "${{ matrix.mode }}" || exit /b 1 run-torture: runs-on: windows-2022 steps: # - name: Install ASAN # shell: cmd # run: | # "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" modify --installPath "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" --quiet --force --norestart --add Microsoft.VisualStudio.Component.VC.ASAN - name: checkout uses: actions/checkout@v2 - name: run-torture shell: cmd run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 call build radlink asan debug no_meta || exit /b 1 call build torture debug no_meta || exit /b 1 cd build torture -l:radlink || exit /b 1 ================================================ FILE: .gitignore ================================================ /build/ /local/ *~ ================================================ FILE: CHANGELOG.md ================================================ # v0.9.24-alpha ## Debugger Changes - Added the ability for the debugger to load, use, and evaluate using debug info, even when not actively debugging. The debugger will now keep a process' debug info loaded, even after the process ends. It stores the set of loaded debug info files in the project configuration file, meaning it will also automatically load the same debug info across many runs. Debug info can also be loaded manually (without ever launching a process) with the `Load Debug Info` command. There is also a new tab, `Debug Info`, which allows viewing and managing the set of loaded debug info files. - Improved the debugger's behavior when used as a drag & drop target, to allow for debug info loading as an option (when relevant), and to better handle the case where many files (potentially of different types) are dropped together. - Improved debug info searching performance and reponsiveness in large projects. - Fixed some crashes and incorrect results with the new `list` view. - Fixed some cases where RDIs did not contain some basic types from their originating PDBs. - Allowed `.` and `->` operators to be used with array types. - Fixed the debugger's treatment of quoted command line arguments when building targets. In previous versions, calling `raddbg main.exe "foo bar baz"` would create a target `main.exe` with arguments `foo bar baz` (dropping the quotes). This is now fixed, such that the target's arguments string will also contain the quotes, and pass them to the target when launched. - Fixed the debugger not correctly responding (through font and UI scale) to DPI changes. - Fixed the debugger incorrectly generating conflicting source line info records in PDB -> RDI conversion, which in some scenarios was preventing source line maps from working (leading to breakpoint resolution failing). - Other small fixes, improvements, and tweaks. # v0.9.23-alpha ## Debugger Changes - Further improved PDB -> RDI conversion performance & memory usage. - Adjusted limits for the amount of PDB -> RDI conversion work that the debugger will kick off, to prevent PDB -> RDI conversion interfering with debuggee performance. - Reintroduced the `list` lens, which gathers all nodes in a linked list, and visualizes them as a flat list of pointers (the same as how an array of pointers is visualized). - Fixed a crash when closing empty Geometry 3D views. (#652, #657) - Fixed the debugger not visualizing `enum` types when evaluated through a bitfield type. (#655) - Fixed the PDB -> RDI conversion not correctly generating location information for function parameters, when the EXE/PDB were built to include support for Edit and Continue (`-ZI` switch). (#656) ## Binary Utility Changes - Fixed a crash when using the `--compress` option, when generating RDI files. # v0.9.22-alpha ## Debugger Changes - Further improved PDB -> RDI conversion performance. - Capped the number of additional threads / processes spawned for PDB -> RDI conversion. - Prioritize PDB -> RDI conversion based on what is actually found to be necessary by the debugger, rather than converting all PDBs in the order in which they're discovered. - Added preliminary support for DWARF -> RDI conversion on Windows. - The debugger now relies on source file checksums to determine whether or not a source file is out-of-date with respect to what was compiled when debug info was produced, rather than just the modification timestamp. - The debugger now will rely on debug info to detect the language of source code files, if it cannot infer from the source file's extension, or view settings. This will enable features like syntax highlighting and hover evaluation in cases like `.inl` files being included in C++ projects. - The debugger now will restore the last focused window when continuing automatically. (#245, #596) - Watch tables have been simplified in that they no longer have a separate column for evaluation types, since this was usually taking a lot more space than it deserved. The type of evaluations is still displayed in watch table cells, and it can always be evaluated directly via `typeof`. - Type evaluations have been simplified in watch tables as well; they no longer have untitled columns for sizes and offsets, this is instead displayed as an extra note by default. Similar behavior to the original behavior can still be obtained using the `columns` view, if needed. - The debugger no longer uses complex `union` types for most registers, and instead just displays the register value plainly. - The hover evaluation UI has been made larger when needed. - The debugger now prefers matching global, function, and type identifiers to the most relevant debug info and module in context; this fixes evaluation in some multi-process debugging contexts. (#581) - Fixed the debugger unnecessarily stripping `enum` type information when accessed through array operators. (#634) - The debugger now understands a standalone `unsigned` keyword as an `unsigned int` type, to match C rules. - The debugger now uses the current working directory to form the working directory for targets specified on the command line, to match behavior when running a command from the command line without the debugger. - Improved call stack computation performance. - Improved debugger memory usage over long periods of time. - Fixed string-pointer comparison not working with not-equal (`!=`) operations. - Fixed a bug which was causing bad debuggee performance on some threads after some interactions with the debugger controller. - Fixed incorrect results when adding two register values. (#642) - Fixed the interpretation of register expressions in visualizers. (#649) - Fixed "forever loading" states in disassembly views in some cases. (#643) - Fixed jittering on window resizing. (#636) - Fixed the bitmap visualizer crashing in some circumstances relating to unsupported bitmap sizes. (#444, #563) - Fixed a crash when an empty `cast()` expression would be evaluated. (#625) - Fixed a crash when an invalid expression would be visualized using the `text` view. (#647) ## Linker Changes - Changed symbol resolution in libaries to match MSVC behavior. - Optimized image building step to reduce memory usage. - Linker memory maps all input files by default to lower memory usage. (`/RAD_MEMORY_MAP_FILES`) - If debug info is available, linker uses it to show file and line number for unresolved relocations. - Improved base relocation build performance for large images, cutting build time by 70%. - Added stubs for `/Brepro`, `/D2`, and /ErrorReport to improve compatability with existing response files - Implemented section garbage collection (`/OPT:REF`) - Fixed bug where thread local variables pointed to incorrect types. - Changed rules for weak and undefined symbols, now weak symbol is not allowed to replace an undefined symbol. - Linker no longer creates thunks for imports that don't require them. ## Binary Utility Changes - The binary utility, like the debugger, now can convert DWARF debug info to RDI files. When both DWARF and PDB info is present, it can now convert both, and produce a single final RDI file with all information. - Textual dumping of RDI files is now done in parallel, massively improving dumping performance. - PDB -> Breakpad conversion performance has now been parallelized to a greater degree, improving performance. ================================================ FILE: LICENSE ================================================ Copyright (c) Epic Games Tools Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # The RAD Debugger Project _**NOTE:** This README does not document usage instructions and tips for the debugger itself, and is intended as a technical overview of the project. The debugger's README, which includes usage instructions and tips, can be found packaged along with debugger releases, or within the `build` folder after a local copy has been built. You can find pre-built release binaries [here](https://github.com/EpicGamesExt/raddebugger/releases)._ The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It currently only supports local-machine Windows x64 debugging with PDBs, with plans to expand and port in the future. In the future we'll expand to also support native Linux debugging and DWARF debug info. The debugger is currently in *ALPHA*. In order to get the debugger bullet-proof, it'd greatly help out if you submitted the issues you find [here](https://github.com/EpicGamesExt/raddebugger/issues), along with any information you can gather, like dump files (along with the build you used), instructions to reproduce, test executables, and so on. In addition to the debugger, we aim to further improve the toolchain with two additional related technologies: **(1)** the RAD Debug Info (RDI) format, and **(2)** the RAD Linker. ## The RAD Debug Info (RDI) Format The RAD Debug Info (RDI) format is our custom debug information format, which the debugger parses and uses, rather than the debug information natively produced by toolchains, like PDB or DWARF. To work with these existing toolchains, we convert PDB (and eventually PE/ELF files with embedded DWARF) into the RDI format on-demand. The RDI format is currently specified in code, in the files within the `src/lib_rdi` folder. In [`rdi.h`](src/lib_rdi/rdi.h) and [`rdi.c`](src/lib_rdi/rdi.c), the types and functions which define the format itself are specified. In [`rdi_parse.h`](src/lib_rdi/rdi_parse.h) and [`rdi_parse.c`](src/lib_rdi/rdi_parse.c), helpers for parsing the format are included. We also have an in-progress library for constructing and serializing RDI data, located within the `src/lib_rdi_make` folder. Our `radbin` utility (accessible through the debugger too, via the `--bin` command line argument) is capable of converting native debug information formats to RDI, and of producing textual dumps of contents stored within RDI files. ## The RAD Linker The RAD Linker is a new performance linker for generating x64 PE/COFF binaries. It is designed to be very fast when creating gigantic executables. It generates standard PDB files for debugging, but it can also (optionally) natively create RAD Debug Info too, which is useful both to eliminate on-demand conversion time when debugging, but also for huge executables that otherwise create broken PDBs that overflow internal 32-bit tables. The RAD Linker is primarily optimized to handle huge linking projects. In our test cases (where debug info is multiple gigabytes), we see 50% faster link times. The command line syntax is fully compatible with MSVC; you can get a full list of implemented switches from `/help`. Our current designed-for use case for the linker is to help with the compile-debug cycle of huge projects. We don't yet have support for link-time-optimizations, but this feature is on the road map. By default, the linker spawns as many threads as there are cores, so if you plan to run multiple linkers in parallel, you can limit the number of thread workers via `/rad_workers`. We also have support for large memory pages, which, when enabled, reduce link time by another 25%. To link with large pages, you need to explicitly request them via `/rad_large_pages`. Large pages are off by default, since Windows support for large pages is a bit buggy; we recommend they only be used in Docker or VM images where the environment is reset after each link. In a standard Windows environment, using large pages otherwise will fragment memory quickly, forcing a reboot. We are working on a Linux port of the linker that will be able to build with large pages robustly. A benchmark of the linker's performance is below: ![AMD Ryzen Threadripper PRO 3995WX 64-Cores, 256 GiB RAM (Windows x64)](https://github.com/user-attachments/assets/a95b382a-76b4-4a4c-b809-b61fe25e667a) --- # Project Development Setup Instructions **NOTE: Currently, only x64 Windows development is supported for the project.** ## 1. Installing the Required Tools (MSVC & Windows SDK) In order to work with the codebase, you'll need the [Microsoft C/C++ Build Tools v15 (2017) or later](https://aka.ms/vs/17/release/vs_BuildTools.exe), for both the Windows SDK and the MSVC compiler and linker. If the Windows SDK is installed (e.g. via installation of the Microsoft C/C++ Build Tools), you may also build with [Clang](https://releases.llvm.org/). ## 2. Build Environment Setup Building the codebase can be done in a terminal which is equipped with the ability to call either MSVC or Clang from command line. This is generally done by calling `vcvarsall.bat x64`, which is included in the Microsoft C/C++ Build Tools. This script is automatically called by the `x64 Native Tools Command Prompt for VS ` variant of the vanilla `cmd.exe`. If you've installed the build tools, this command prompt may be easily located by searching for `Native` from the Windows Start Menu search. You can ensure that the MSVC compiler is accessible from your command line by running: ``` cl ``` If everything is set up correctly, you should have output very similar to the following: ``` Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30151 for x64 Copyright (C) Microsoft Corporation. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] ``` ### 3. Building Within this terminal, `cd` to the root directory of the codebase, and just run the `build.bat` script: ``` build ``` You should see the following output: ``` [debug mode] [msvc compile] [default mode, assuming `raddbg` build] metagen_main.c searching C:\devel\raddebugger/src... 458 files found parsing metadesk... 16 metadesk files parsed gathering tables... 97 tables found generating layer code... raddbg_main.c ``` If everything worked correctly, there will be a `build` folder in the root level of the codebase, and it will contain a freshly-built `raddbg.exe`. This `raddbg.exe` will have been built in **debug mode**, which is not built with optimizations, and may perform worse. To produce a **release mode executable**, run `build.bat` with a `release` argument: ``` build release ``` This build will take significantly longer. By default, `build.bat` only builds the debugger if no arguments (or just `release`) are passed, but additional arguments can be passed to build the RAD Linker, or the `radbin` CLI binary file utility: ``` build radlink release build radbin release ``` --- # Project Roadmap ### The Initial Alpha Battle-Testing Phase The first priority for the project is to ensure that the most crucial components are functioning extremely reliably for local, x64, Windows development. For the debugger, this would include parts like debug info conversion, debug info loading, process control, stepping, evaluation (correct usage of both location info and type info), and a robust frontend which ensures the lower level parts are usable. For the linker, this is a matter of reliability and convergence with existing linker behavior. We feel that we've already come a long way in all of these respects, but given the massive set of possible combinations of languages, build settings, toolchains, used language features, and patterns of generated code, we still expect some issues, and are prioritizing these issues being resolved first. We also hope to continue to improve performance in this phase. For the debugger, this primarily includes frontend performance, introducing caches when economical to do so, and tightening existing systems up. For the linker, it has been mostly tuned thus far for giant projects, and so we'd like to improve linking speed for small-to-mid sized projects as well. For the linker, there are also a number of features to come, like dead-code-elimination (`/opt:ref`), and link-time-optimizations with the help of `clang` (we won't support LTCG from MSVC, since it is undocumented). ### Local x64 Linux Debugging Phase The next priority for the project is to take the rock solid x64 Windows debugging experience, and port all of the relevant pieces to support local x64 Linux debugging also. The debugger has been written to abstract over the parts that need to differ on either Linux or Windows, and this is mainly going to be a task in building out different backends for those abstraction layers. The major parts of this phase are: - Porting the `src/demon` layer to implement the Demon local process control abstraction API. - Implementing an x64 ELF Linux unwinder in the `src/ctrl` layer. - Creating a DWARF-to-RDI converter (in the same way that we've built a PDB-to-RDI converter). A partial implementation of this is in `src/rdi_from_dwarf`. - Porting the `src/render` layer to implement all of the rendering features the frontend needs on a Linux-compatible API (the backend used on Windows is D3D11). - Porting the `src/font_provider` layer to a Linux-compatible font rasterization backend, like FreeType (the backend used on Windows is DirectWrite). - Porting the `src/os` layers to Linux. This includes core operating system abstraction (virtual memory allocation, threading and synchronization primitives, and so on), and graphical operating system abstraction (windows, input events, and so on). Once the above list is complete, and once every part is rock solid, the Windows debugging experience we'll have worked diligently to create will also be available natively on Linux machines. ### And Beyond! There are several directions we might take after these two major phases, like remote debugging, porting to different architectures, further improving the debugger's features (like improving the visualization engine), and so on. But for now, we're mostly focused on those first two phases. --- # Codebase Introduction ## Top-Level Directory Descriptions - `data`: Small binary files which are used when building, either to embed within build artifacts, or to package with them. - `src`: All source code. After setting up the codebase and building, the following directories will also exist: - `build`: All build artifacts. Not checked in to version control. - `local`: Local files, used for local build configuration input files. Not checked in to version control. ## Layer Descriptions The codebase is organized into *layers*. Layers are separated either to isolate certain problems, and to allow inclusion into various builds without needing to pull everything in the codebase into a build. Layers correspond with folders inside of the `src` directory. Sometimes, one folder inside of the `src` directory will include multiple sub-layers, but the structure is intended to be fairly flat. Layers correspond roughly 1-to-1 with *namespaces*. The term "namespaces" in this context does not refer to specific namespace language features, but rather a naming convention for C-style namespaces, which are written in the codebase as a short prefix, usually 1-3 characters, followed by an underscore. These namespaces are used such that the layer to which certain code belongs may be quickly understood by glancing at code. The namespaces are generally quite short to ensure that they aren't much of a hassle to write. Sometimes, multiple sub- layers will share a namespace. A few layers do not have a namespace, but most do. Namespaces are either all-caps or lowercase depending on the context in which they're used. For types, enum values, and some macros, they are capitalized. For functions and global variables, they are lowercase. Layers depend on other layers, but circular dependencies would break the separability and isolation utility of layers (in effect, forming one big layer), so in other words, layers are arranged into a directed acyclic graph. A few layers are built to be used completely independently from the rest of the codebase, as libraries in other codebases and projects. As such, these layers do not depend on any other layers in the codebase. The folders which contain these layers are prefixed with `lib_`, like `lib_rdi`. A list of the layers in the codebase and their associated namespaces is below: - `artifact_cache` (`AC_`): Implements an asynchronously-filled cache of computation artifacts, which are automatically evicted when not accessed. Used for asynchronously streaming and caching process memory and file system contents, as well as asynchronously preparing visualizer data. - `base` (no namespace): Universal, codebase-wide constructs. Strings, math, memory allocators, helper macros, command-line parsing, and so on. Requires no other codebase layers. - `codeview` (`CV_`): Code for parsing and writing the CodeView format. - `coff` (`COFF_`): Code for parsing and writing the COFF (Common Object File Format) file format. - `content` (`C_`): Implements a cache for general data blobs, keyed by a 128-bit hash of the data. Also implements a keying system on top, where keys refer to a unique identity which corresponds to a history of 128-bit hashes. Used as a general data store by other layers. - `ctrl` (`CTRL_`): The debugger's "control system" layer. Implements asynchronous process control, stepping, and breakpoints for all attached processes. Runs in lockstep with attached processes. When it runs, attached processes are halted. When attached processes are running, it is halted. Driven by a debugger frontend on another thread. - `dbg_engine` (`D_`): Implements the core debugger system, without any graphical components. This contains top-level logic for things like stepping, launching, freezing threads, mid-run breakpoint addition, some caches, and so on. - `dbg_info` (`DI_`): Implements asynchronous debug info conversion and loading. Maintains a cache for loaded debug info. Loads RAD Debug Info (RDI) files. Launches separate processes for on-demand conversion to the RDI format if necessary. Also provides various asynchronous operations for using debug info, like fuzzy searching across all records in loaded debug info. - `demon` (`DMN_`): An abstraction layer for local-machine, low-level process control. The abstraction is used to provide a common interface for process control on target platforms. Used to implement part of `ctrl`. - `disasm` (`DASM_`): Implements disassembly generation, including exposing the ability to compute and cache disassembly asynchronously. - `draw` (`DR_`): Implements a high-level graphics drawing API for the debugger's purposes, using the underlying `render` abstraction layer. Provides high-level APIs for various draw commands, but takes care of batching them, and so on. - `dwarf` (`DW_`): Code for parsing the DWARF format. - `eh` (`EH_`): Code for parsing the EH frame format. - `elf` (`ELF_`): Code for parsing the ELF format. - `eval` (`E_`): A compiler for an expression language, built for evaluation of variables, registers, types, and more, from debugger-attached processes, debug info, debugger state, and files. Broken into several phases mostly corresponding to traditional compiler phases: lexer, parser, type-checker, IR generation, and IR evaluation. - `eval_visualization` (`EV_`): Implements the core non-graphical evaluation visualization engine, which can be used to visualize evaluations (provided by the `eval` layer) in a number of ways. Implements core data structures and transforms for watch tables. - `file_stream` (`FS_`): Implements asynchronous file streaming, storing the artifacts inside of the cache implemented by the `content` and `artifact_cache` layers, hot-reloading the contents of files when they change. Allows callers to map file paths to data hashes, which can then be used to obtain the file's data. - `font_cache` (`FNT_`): Implements a cache of rasterized font data, both in CPU-side data for text shaping, and in GPU texture atlases for rasterized glyphs. All cache information is sourced from the `font_provider` abstraction layer. - `font_provider` (`FP_`): An abstraction layer for various font file decoding and font rasterization backends. - `lib_raddbg_markup` (`RADDBG_`): Standalone library for marking up user programs to work with various features in the debugger. Does not depend on `base`, and can be independently relocated to other codebases. - `lib_rdi` (`RDI_`): Standalone library which defines the core RDI types and helper functions for reading and writing the RDI debug info file format. Does not depend on `base`, and can be independently relocated to other codebases. - `lib_rdi_make` (`RDIM_`): Standalone library for constructing RDI debug info data. Does not depend on `base`, and can be independently relocated to other codebases. - `linker` (`LNK_`): The layer which implements the RAD Linker executable itself. - `mdesk` (`MD_`): Code for parsing Metadesk files (stored as `.mdesk`), which is the JSON-like (technically a JSON superset) text format used for the debugger's user and project configuration files and metacode, which is parsed and used to generate code with the `metagen` layer. - `metagen` (`MG_`): A metaprogram which is used to generate primarily code and data tables. Consumes Metadesk files, stored with the extension `.mdesk`, and generates C code which is then included by hand-written C code. Currently, it does not analyze the codebase's hand-written C code, but in principle this is possible. This allows easier & less-error-prone management of large data tables, which are then used to produce e.g. C `enum`s and a number of associated data tables. There are also a number of other generation features, like embedding binary files or complex multi-line strings into source code. - `msf` (`MSF_`): Code for parsing and writing the MSF file format. - `msvc_crt` (`MSCRT_`): Code for parsing that's specific to the MSVC CRT. - `mule` (no namespace): Test executables for battle testing debugger functionality. - `mutable_text` (`MTX_`): Implements an asynchronously-filled-and-mutated cache for text buffers which are mutated across time. In the debugger, this is used to implement the `Output` log. - `natvis` (no namespace): NatVis files for type visualization of the codebase's types in other debuggers. - `os/core` (`OS_`): An abstraction layer providing core, non-graphical functionality from the operating system under an abstract API, which is implemented per-target-operating-system. - `os/gfx` (`OS_`): An abstraction layer, building on `os/core`, providing graphical operating system features under an abstract API, which is implemented per-target-operating-system. - `pdb` (`PDB_`): Code for parsing and writing the PDB file format. - `pe` (`PE_`): Code for parsing and writing the PE (Portable Executable) file format. - `radbin` (`RB_`): The layer implementing the `radbin` binary utility executable. - `raddbg` (`RD_`): The layer which ties everything together for the main graphical debugger executable. Implements the debugger's graphical frontend, all of the debugger-specific UI, the debugger executable's command line interface, and all of the built-in visualizers. - `rdi` (`RDI_`): A layer which includes the `lib_rdi` layer and bundles it with codebase-specific helpers, to easily include the library in codebase programs, and have it be integrated with codebase constructs. - `rdi_from_coff` (`C2R_`): Code for converting information in COFF files to the equivalent RDI data. - `rdi_from_dwarf` (`D2R_`): In-progress code for converting DWARF to the equivalent RDI data. - `rdi_from_elf` (`E2R_`)): Code for converting ELF data to the equivalent RDI data. - `rdi_from_pdb` (`P2R_`): Code for converting PDB data to the equivalent RDI data. - `rdi_make` (`RDIM_`): A layer which includes the `lib_rdi_make` layer and bundles it with codebase-specific helpers, to easily include the library in codebase programs, and have it be integrated with codebase constructs. - `regs` (`REGS_`): Types, helper functions, and metadata for registers on supported architectures. Used in reading/writing registers in `demon`, or in looking up register metadata. - `render` (`R_`): An abstraction layer providing an abstract API for rendering using various GPU APIs under a common interface. Does not implement a high level drawing API - this layer is strictly for minimally abstracting on an as-needed basis. Higher level drawing features are implemented in the `draw` layer. - `scratch` (no namespace): Scratch space for small and transient test programs. - `tester` (no namespace): A program used for automated testing. - `text` (`TXT_`): Implements text processing functions, like parsing line breaks, and lexing and parsing source code. Also offers an API to do this asynchronously. - `third_party` (no namespace): External code from other projects, which some layers in the codebase depend on. All external code is included and built directly within the codebase. - `ui` (`UI_`): Machinery for building graphical user interfaces. Provides a core immediate mode hierarchical user interface data structure building API, and has helper layers for building some higher-level widgets. ================================================ FILE: build.bat ================================================ @echo off setlocal enabledelayedexpansion cd /D "%~dp0" :restart :: --- Usage Notes (2024/1/10) ------------------------------------------------ :: :: This is a central build script for the RAD Debugger project, for use in :: Windows development environments. It takes a list of simple alphanumeric- :: only arguments which control (a) what is built, (b) which compiler & linker :: are used, and (c) extra high-level build options. By default, if no options :: are passed, then the main "raddbg" graphical debugger is built. :: :: Below is a non-exhaustive list of possible ways to use the script: :: `build raddbg` :: `build raddbg clang` :: `build raddbg release` :: `build raddbg asan telemetry` :: `build rdi_from_pdb` :: :: For a full list of possible build targets and their build command lines, :: search for @build_targets in this file. :: :: Below is a list of all possible non-target command line options: :: :: - `asan`: enable address sanitizer :: - `telemetry`: enable RAD telemetry profiling support :: - `spall`: enable spall profiling support :: --- Unpack Arguments ------------------------------------------------------- for %%a in (%*) do set "%%~a=1" if not "%msvc%"=="1" if not "%clang%"=="1" set msvc=1 if not "%release%"=="1" set debug=1 if "%debug%"=="1" set release=0 && echo [debug mode] if "%release%"=="1" set debug=0 && echo [release mode] if "%msvc%"=="1" set clang=0 && echo [msvc compile] if "%clang%"=="1" set msvc=0 && echo [clang compile] if "%~1"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1 if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && set raddbg=1 :: --- Unpack Command Line Build Arguments ------------------------------------ set auto_compile_flags= if "%telemetry%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_TELEMETRY=1 && echo [telemetry profiling enabled] if "%spall%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_SPALL=1 && echo [spall profiling enabled] if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan enabled] if "%opengl%"=="1" set auto_compile_flags=%auto_compile_flags% -DR_BACKEND=R_BACKEND_OPENGL && echo [opengl render backend] if "%dwarf%"=="1" if "%clang%"=="1" set auto_compile_flags=%auto_compile_flags% -gdwarf && echo [dwarf debug info] if "%dwarf%"=="" if "%clang%"=="1" set auto_compile_flags=%auto_compile_flags% -gcodeview if "%pgo%"=="1" ( where llvm-profdata /q || echo llvm-profdata is not in the PATH || exit /b 1 if "%clang%"=="1" ( if "%pgo_run%" == "1" ( call llvm-profdata merge %LLVM_PROFILE_FILE% -output=%~dp0build\build.profdata || exit /b 1 set auto_compile_flags=%auto_compile_flags% -fprofile-use=%~dp0build\build.profdata set pgo_run=0 ) else ( echo [pgo enabled] set auto_compile_flags=%auto_compile_flags% -fprofile-generate -mllvm -vp-counters-per-site=5 set LLVM_PROFILE_FILE=%~dp0build\build.profraw set pgo_run=1 ) ) else ( echo ERROR: PGO build is not supported with current compiler exit /b 1 ) ) :: --- Compile/Link Line Definitions ------------------------------------------ set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%% /NATVIS:"%~dp0\src\natvis\base.natvis" /noexp /nocoffgrpinfo /opt:ref /opt:icf set cl_out= /out: set cl_linker= set clang_common= -I..\src\ -I..\local\ -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-unused-parameter -Wno-writable-strings -Wno-missing-field-initializers -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000 -mcx16 -msha set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% -Xlinker /NATVIS:"%~dp0\src\natvis\base.natvis" -Xlinker /opt:ref -Xlinker /opt:icf set clang_out= -o set clang_linker= -Xlinker :: --- Per-Build Settings ----------------------------------------------------- set link_dll=-DLL set link_icon=logo.res if "%msvc%"=="1" set linker=%cl_linker% if "%clang%"=="1" set linker=%clang_linker% if "%msvc%"=="1" set only_compile=/c if "%clang%"=="1" set only_compile=-c if "%msvc%"=="1" set EHsc=/EHsc if "%clang%"=="1" set EHsc= if "%msvc%"=="1" set no_aslr=/DYNAMICBASE:NO if "%clang%"=="1" set no_aslr=-Wl,/DYNAMICBASE:NO if "%msvc%"=="1" set rc=call rc if "%clang%"=="1" set rc=call llvm-rc :: --- Choose Compile/Link Lines ---------------------------------------------- if "%msvc%"=="1" set compile_debug=%cl_debug% if "%msvc%"=="1" set compile_release=%cl_release% if "%msvc%"=="1" set compile_link=%cl_link% if "%msvc%"=="1" set out=%cl_out% if "%clang%"=="1" set compile_debug=%clang_debug% if "%clang%"=="1" set compile_release=%clang_release% if "%clang%"=="1" set compile_link=%clang_link% if "%clang%"=="1" set out=%clang_out% if "%debug%"=="1" set compile=%compile_debug% if "%release%"=="1" set compile=%compile_release% :: --- Prep Directories ------------------------------------------------------- if not exist build mkdir build if not exist local mkdir local :: --- Produce Logo Icon File ------------------------------------------------- pushd build %rc% /nologo /fo logo.res ..\data\logo.rc || exit /b 1 popd :: --- Get Current Git Commit Id ---------------------------------------------- for /f %%i in ('call git describe --always --dirty') do set compile=%compile% -DBUILD_GIT_HASH=\"%%i\" for /f %%i in ('call git rev-parse HEAD') do set compile=%compile% -DBUILD_GIT_HASH_FULL=\"%%i\" :: --- Build & Run Metaprogram ------------------------------------------------ if "%meta%"=="1" ( echo [doing metagen] pushd build %compile_debug% ..\src\metagen\metagen_main.c %compile_link% %out%metagen.exe || exit /b 1 metagen.exe || exit /b 1 popd ) :: --- Build Everything (@build_targets) -------------------------------------- pushd build if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1 if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1 if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1 if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1 if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1 if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 if "%eval_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\eval_scratch.c %compile_link% %out%eval_scratch.exe || exit /b 1 if "%textperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\textperf.c %compile_link% %out%textperf.exe || exit /b 1 if "%convertperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\convertperf.c %compile_link% %out%convertperf.exe || exit /b 1 if "%debugstringperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\debugstringperf.c %compile_link% %out%debugstringperf.exe || exit /b 1 if "%parse_inline_sites%"=="1" set didbuild=1 && %compile% ..\src\scratch\parse_inline_sites.c %compile_link% %out%parse_inline_sites.exe || exit /b 1 if "%strip_lib_debug%"=="1" set didbuild=1 && %compile% ..\src\strip_lib_debug\strip_lib_debug.c %compile_link% %out%strip_lib_debug.exe || exit /b 1 if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1 if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1 if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1 if "%torture%"=="1" set didbuild=1 && %compile% ..\src\torture\torture.c %compile_link% %out%torture.exe || exit /b1 if "%mule_peb_trample%"=="1" ( set didbuild=1 if exist mule_peb_trample.exe move mule_peb_trample.exe mule_peb_trample_old_%random%.exe if exist mule_peb_trample_new.pdb move mule_peb_trample_new.pdb mule_peb_trample_old_%random%.pdb if exist mule_peb_trample_new.rdi move mule_peb_trample_new.rdi mule_peb_trample_old_%random%.rdi %compile% ..\src\mule\mule_peb_trample.c %compile_link% %out%mule_peb_trample_new.exe || exit /b 1 move mule_peb_trample_new.exe mule_peb_trample.exe ) popd :: --- Warn On No Builds ------------------------------------------------------ if "%didbuild%"=="" ( echo [WARNING] no valid build target specified; must use build target names as arguments to this script, like `build raddbg` or `build rdi_from_pdb`. exit /b 1 ) :: --- PGO Run ---------------------------------------------------------------- if "%pgo_run%"=="1" ( if "%radlink%"=="1" ( pushd local\lyra_pgo call %~dp0build\radlink @lyra.rsp /rad_alt_pch_dir:%~dp0local\lyra_pgo || exit /b 1 popd ) goto restart ) ================================================ FILE: build.sh ================================================ #!/bin/bash set -eu cd "$(dirname "$0")" # --- Unpack Arguments -------------------------------------------------------- for arg in "$@"; do declare $arg='1'; done if [ ! -v gcc ]; then clang=1; fi if [ ! -v release ]; then debug=1; fi if [ -v debug ]; then echo "[debug mode]"; fi if [ -v release ]; then echo "[release mode]"; fi if [ -v clang ]; then compiler="${CC:-clang}"; echo "[clang compile]"; fi if [ -v gcc ]; then compiler="${CC:-gcc}"; echo "[gcc compile]"; fi # --- Unpack Command Line Build Arguments ------------------------------------- auto_compile_flags='' # --- Get Current Git Commit Id ----------------------------------------------- git_hash=$(git describe --always --dirty) git_hash_full=$(git rev-parse HEAD) # --- Compile/Link Line Definitions ------------------------------------------- clang_common="-I../src/ -I/usr/include/freetype2/ -I../local/ -D_GNU_SOURCE -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Wno-for-loop-analysis -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf" clang_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${clang_common} ${auto_compile_flags}" clang_release="$compiler -g -O2 -DBUILD_DEBUG=0 ${clang_common} ${auto_compile_flags}" clang_link="-lpthread -lm -lrt -ldl" clang_out="-o" gcc_common="-I../src/ -I../local/ -g -D_GNU_SOURCE -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -Wall -Wno-missing-braces -Wno-unused-function -Wno-attributes -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-compare-distinct-pointer-types -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf" gcc_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${gcc_common} ${auto_compile_flags}" gcc_release="$compiler -g -O2 -DBUILD_DEBUG=0 ${gcc_common} ${auto_compile_flags}" gcc_link="-lpthread -lm -lrt -ldl" gcc_out="-o" # --- Per-Build Settings ------------------------------------------------------ link_dll="-fPIC" link_os_gfx="-lX11 -lXext" link_render="-lGL -lEGL" link_font_provider="-lfreetype" # --- Choose Compile/Link Lines ----------------------------------------------- if [ -v gcc ]; then compile_debug="$gcc_debug"; fi if [ -v gcc ]; then compile_release="$gcc_release"; fi if [ -v gcc ]; then compile_link="$gcc_link"; fi if [ -v gcc ]; then out="$gcc_out"; fi if [ -v clang ]; then compile_debug="$clang_debug"; fi if [ -v clang ]; then compile_release="$clang_release"; fi if [ -v clang ]; then compile_link="$clang_link"; fi if [ -v clang ]; then out="$clang_out"; fi if [ -v debug ]; then compile="$compile_debug"; fi if [ -v release ]; then compile="$compile_release"; fi # --- Prep Directories -------------------------------------------------------- mkdir -p build mkdir -p local # --- Build & Run Metaprogram ------------------------------------------------- if [ -v meta ] then echo "[doing metagen]" cd build $compile_debug ../src/metagen/metagen_main.c $compile_link $out metagen ./metagen cd .. fi # --- Build Everything (@build_targets) --------------------------------------- cd build if [ -v raddbg ]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c $compile_link $link_os_gfx $link_render $link_font_provider $out raddbg; fi if [ -v radbin ]; then didbuild=1 && $compile ../src/radbin/radbin_main.c $compile_link $out radbin; fi if [ -v radlink ]; then didbuild=1 && $compile ../src/linker/lnk.c $compile_link $out radlink; fi cd .. # --- Warn On No Builds ------------------------------------------------------- if [ ! -v didbuild ] then echo "[WARNING] no valid build target specified; must use build target names as arguments to this script, like \`./build.sh raddbg\` or \`./build.sh rdi_from_pdb\`." exit 1 fi ================================================ FILE: data/logo.rc ================================================ 1 ICON DISCARDABLE "logo.ico" ================================================ FILE: project.4coder ================================================ version(2); project_name = "The RAD Debugger"; indent_width = "2"; default_tab_width = "2"; patterns = { "*.c", "*.cpp", "*.h", "*.inc", "*.hpp", "*.bat", "*.sh", "*.4coder", "*.glsl", "*.bfs", "*.html", "*.txt", "*.md", "*.mdesk", "*.asm", }; blacklist_patterns = { ".*", "metagen_base_*", "metagen_os_*", }; paths = { { .path = ".", .recursive = false, .relative = true, }, { .path = "src", .recursive = true , .relative = true, }, { .path = "local", .recursive = true , .relative = true, }, }; load_paths = { .win = paths, .linux = paths, }; commands = { //- rjf: [raddbg] // .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg meta telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [raddbg wsl] // .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [scratch] .f2 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [textperf] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [tester] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta tester", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: [radbin] // .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: running target .f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f3 = { .win = "wsl ./build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f3 = { .win = "pushd build && raddbg --user:dev.raddbg_user && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f3 = { .win = "C:/devel/raddebugger/build/raddbg.exe --capture --user:C:/devel/raddebugger/build/local_dev.raddbg_user --project:C:/devel/raddebugger/build/local_dev.raddbg_project", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, // .f3 = { .win = "wsl_launch /mnt/c/devel/raddebugger/build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: local target builds .build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_from_pdb = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_from_dwarf = { .win = "build rdi_from_dwarf", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_dump = { .win = "build rdi_dump", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_breakpad_from_pdb = { .win = "build rdi_breakpad_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_ryan_scratch = { .win = "build ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_main = { .win = "build mule_main", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_module = { .win = "build mule_module", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_hotload = { .win = "build mule_hotload", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_peb_trample = { .win = "build mule_peb_trample", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: wsl target builds .build_raddbg_wsl = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_from_pdb_wsl = { .win = "wsl ./build.sh rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_from_dwarf_wsl = { .win = "wsl ./build.sh rdi_from_dwarf", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_dump_wsl = { .win = "wsl ./build.sh rdi_dump", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_rdi_breakpad_from_pdb_wsl = { .win = "wsl ./build.sh rdi_breakpad_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_ryan_scratch_wsl = { .win = "wsl ./build.sh ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_main_wsl = { .win = "wsl ./build.sh mule_main", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_module_wsl = { .win = "wsl ./build.sh mule_module", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_hotload_wsl = { .win = "wsl ./build.sh mule_hotload", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .build_mule_peb_trample_wsl = { .win = "wsl ./build.sh mule_peb_trample", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: local target runs .run_raddbg = { .win = "pushd build && raddbg.exe && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, }; fkey_command = { .F1 = "f1", .F2 = "f2", .F3 = "f3", }; fkey_command_override = { .rjf = { .F1 = "f1", .F2 = "f2", .F3 = "f3", }, }; ================================================ FILE: run_tests.bat ================================================ @echo off setlocal cd /D "%~dp0" echo --- getting test data folder path --------------------------------------------- if not exist .\local\test_data_path.txt ( echo error: You must first store the full path of your test data folder inside of `local/test_data_path.txt`. goto :EOF ) set /p test_data_folder=<.\local\test_data_path.txt echo test data path: %test_data_folder% echo: echo --- building all testing executables ------------------------------------------ call build rdi_from_pdb rdi_dump raddbg radlink tester echo: echo --- running tests ------------------------------------------------------------- pushd build call tester.exe --test_data:%test_data_folder% popd ================================================ FILE: src/artifact_cache/artifact_cache.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Layer Initialization internal void ac_init(void) { Arena *arena = arena_alloc(); ac_shared = push_array(arena, AC_Shared, 1); ac_shared->arena = arena; ac_shared->cache_slots_count = 256; ac_shared->cache_slots = push_array(arena, AC_Cache *, ac_shared->cache_slots_count); ac_shared->cache_stripes = stripe_array_alloc(arena); for EachElement(idx, ac_shared->req_batches) { ac_shared->req_batches[idx].mutex = mutex_alloc(); ac_shared->req_batches[idx].arena = arena_alloc(); } ac_shared->cancel_thread = thread_launch(ac_cancel_thread_entry_point, 0); ac_shared->cancel_thread_semaphore = semaphore_alloc(0, 1, str8_zero()); } //////////////////////////////// //~ rjf: Cache Lookups internal AC_Artifact ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U64 endt_us) { ProfBeginFunction(); AC_RequestBatch *req_batch = &ac_shared->req_batches[params->flags & AC_Flag_HighPriority ? 0 : 1]; //- rjf: create function -> cache AC_Cache *cache = 0; { U64 cache_hash = u64_hash_from_str8(str8_struct(¶ms->create)); U64 cache_slot_idx = cache_hash%ac_shared->cache_slots_count; Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx); for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { RWMutexScope(cache_stripe->rw_mutex, write_mode) { for(AC_Cache *c = ac_shared->cache_slots[cache_slot_idx]; c != 0; c = c->next) { if(c->create == params->create) { cache = c; break; } } if(write_mode && cache == 0) { cache = push_array(cache_stripe->arena, AC_Cache, 1); SLLStackPush(ac_shared->cache_slots[cache_slot_idx], cache); cache->create = params->create; cache->destroy = params->destroy; cache->slots_count = Max(256, params->slots_count); cache->slots = push_array(cache_stripe->arena, AC_Slot, cache->slots_count); cache->stripes = stripe_array_alloc(cache_stripe->arena); } } if(cache != 0) { break; } } } //- rjf: unpack key U64 hash = u64_hash_from_str8(key); U64 slot_idx = hash%cache->slots_count; AC_Slot *slot = &cache->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); //- rjf: cache * key -> existing artifact B32 artifact_is_stale = 1; B32 got_artifact = 0; B32 need_request = 0; AC_Artifact artifact = {0}; RWMutexScope(stripe->rw_mutex, 0) { for(AC_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, key, 0)) { ins_atomic_u64_eval_assign(&n->last_requested_gen, params->gen); B32 is_stale = (n->last_completed_gen != params->gen); if(ins_atomic_u64_eval(&n->completion_count) != 0 && (!is_stale || !(params->flags & AC_Flag_WaitForFresh))) { got_artifact = 1; artifact_is_stale = is_stale; artifact = n->val; access_touch(access, &n->access_pt, stripe->cv); } if(is_stale) { B32 got_task = (ins_atomic_u64_eval_cond_assign(&n->working_count, 1, 0) == 0); need_request = got_task; } break; } } } //- rjf: didn't get artifact we want? -> fall back to slow path if(!got_artifact || need_request) { RWMutexScope(stripe->rw_mutex, 1) for(;;) { B32 out_of_time = (os_now_microseconds() >= endt_us); // rjf: find node in cache AC_Node *node = 0; for(AC_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, key, 0)) { node = n; break; } } // rjf: no node? -> create if(node == 0) { need_request = 1; node = stripe->free; if(node) { stripe->free = node->next; } else { node = push_array_no_zero(stripe->arena, AC_Node, 1); } MemoryZeroStruct(node); DLLPushBack(slot->first, slot->last, node); // TODO(rjf): string allocator for keys node->key = str8_copy(stripe->arena, key); node->working_count = 1; node->evict_threshold_us = params->evict_threshold_us; } node->access_pt.last_time_touched_us = os_now_microseconds(); node->access_pt.last_update_idx_touched = update_tick_idx(); // rjf: request if(need_request) { need_request = 0; MutexScope(req_batch->mutex) { AC_RequestNode *n = push_array(req_batch->arena, AC_RequestNode, 1); if(params->flags & AC_Flag_Wide) { SLLQueuePush(req_batch->first_wide, req_batch->last_wide, n); req_batch->wide_count += 1; } else { SLLQueuePush(req_batch->first_thin, req_batch->last_thin, n); req_batch->thin_count += 1; } n->v.key = str8_copy(req_batch->arena, key); n->v.gen = params->gen; n->v.cancel_signal = &node->cancelled; n->v.create = params->create; } cond_var_broadcast(async_tick_start_cond_var); ins_atomic_u32_eval_assign(&async_loop_again, 1); if(params->flags & AC_Flag_HighPriority) { ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 1); } } // rjf: get value from node, if possible if(!got_artifact && ins_atomic_u64_eval(&node->completion_count) != 0 && ((node->last_completed_gen == params->gen) || !(params->flags & AC_Flag_WaitForFresh) || out_of_time)) { got_artifact = 1; artifact_is_stale = (node->last_completed_gen == params->gen); artifact = node->val; access_touch(access, &node->access_pt, stripe->cv); } // rjf: abort if needed if(out_of_time || got_artifact || is_async_thread) { break; } // rjf: wait for results cond_var_wait_rw(stripe->cv, stripe->rw_mutex, 1, endt_us); } } //- rjf: report staleness if(params->stale_out) { params->stale_out[0] = artifact_is_stale; } ProfEnd(); return artifact; } //////////////////////////////// //~ rjf: Asynchronous Tick internal void ac_async_tick(void) { Temp scratch = scratch_begin(0, 0); ////////////////////////////// //- rjf: enable cancellation scanning // if(lane_idx() == 0) { semaphore_drop(ac_shared->cancel_thread_semaphore); } ////////////////////////////// //- rjf: do eviction pass across all caches // for EachIndex(cache_slot_idx, ac_shared->cache_slots_count) { Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx); RWMutexScope(cache_stripe->rw_mutex, 0) { for EachNode(cache, AC_Cache, ac_shared->cache_slots[cache_slot_idx]) { Rng1U64 slot_range = lane_range(cache->slots_count); for EachInRange(slot_idx, slot_range) { AC_Slot *slot = &cache->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { B32 slot_has_work = 0; RWMutexScope(stripe->rw_mutex, write_mode) { for(AC_Node *n = slot->first, *next = 0; n != 0; n = next) { next = n->next; if(access_pt_is_expired(&n->access_pt, .time = n->evict_threshold_us) && ins_atomic_u64_eval(&n->working_count) == 0) { slot_has_work = 1; if(!write_mode) { break; } else { DLLRemove(slot->first, slot->last, n); n->next = (AC_Node *)stripe->free; stripe->free = n; if(cache->destroy) { cache->destroy(n->val); } } } } } if(!slot_has_work) { break; } } } } } } ////////////////////////////// //- rjf: gather requests // typedef struct RequestBatchTask RequestBatchTask; struct RequestBatchTask { AC_Request *wide; U64 wide_count; AC_Request *thin; U64 thin_count; }; RequestBatchTask *tasks = 0; U64 tasks_count = 0; if(lane_idx() == 0) { tasks_count = 2; tasks = push_array(scratch.arena, RequestBatchTask, tasks_count); for EachElement(task_idx, ac_shared->req_batches) { AC_RequestBatch *batch = &ac_shared->req_batches[task_idx]; MutexScope(batch->mutex) { tasks[task_idx].wide_count = batch->wide_count; tasks[task_idx].thin_count = batch->thin_count; tasks[task_idx].wide = push_array(scratch.arena, AC_Request, tasks[task_idx].wide_count); tasks[task_idx].thin = push_array(scratch.arena, AC_Request, tasks[task_idx].thin_count); { U64 idx = 0; for EachNode(n, AC_RequestNode, batch->first_wide) { MemoryCopyStruct(&tasks[task_idx].wide[idx], &n->v); tasks[task_idx].wide[idx].key = str8_copy(scratch.arena, tasks[task_idx].wide[idx].key); idx += 1; } } { U64 idx = 0; for EachNode(n, AC_RequestNode, batch->first_thin) { MemoryCopyStruct(&tasks[task_idx].thin[idx], &n->v); tasks[task_idx].thin[idx].key = str8_copy(scratch.arena, tasks[task_idx].thin[idx].key); idx += 1; } } arena_clear(batch->arena); batch->first_wide = batch->last_wide = batch->first_thin = batch->last_thin = 0; batch->wide_count = batch->thin_count = 0; } } } lane_sync_u64(&tasks, 0); lane_sync_u64(&tasks_count, 0); lane_sync(); ////////////////////////////// //- rjf: do all requests // for EachIndex(task_idx, tasks_count) { lane_sync(); RequestBatchTask *task = &tasks[task_idx]; //- rjf: set up cancellation signal U64 cancelled = 0; U64 *cancelled_ptr = 0; if(lane_idx() == 0) { cancelled_ptr = &cancelled; } lane_sync_u64(&cancelled_ptr, 0); //- rjf: do all wide requests for this priority U64 done_wide_count = 0; ProfScope("wide requests (p%I64u)", task_idx) { for EachIndex(idx, task->wide_count) { lane_sync(); AC_Request *r = &task->wide[idx]; // rjf: any new higher priority tasks? -> cancel if(lane_idx() == 0) { if(task_idx == 1 && idx != 0 && ins_atomic_u32_eval(&async_loop_again_high_priority)) { ins_atomic_u64_eval_assign(cancelled_ptr, 1); } } lane_sync(); // rjf: cancelled? -> exit if(ins_atomic_u32_eval(cancelled_ptr)) { break; } // rjf: compute val B32 retry = 0; U64 gen = r->gen; AC_Artifact val = r->create(r->key, r->cancel_signal, &retry, &gen); // rjf: retry? -> resubmit request if(retry && lane_idx() == 0 && !ins_atomic_u32_eval(r->cancel_signal)) { AC_RequestBatch *batch = &ac_shared->req_batches[task_idx]; MutexScope(batch->mutex) { AC_RequestNode *n = push_array(batch->arena, AC_RequestNode, 1); SLLQueuePush(batch->first_wide, batch->last_wide, n); batch->wide_count += 1; MemoryCopyStruct(&n->v, r); n->v.key = str8_copy(batch->arena, n->v.key); } ins_atomic_u32_eval_assign(&async_loop_again, 1); } // rjf: create function -> cache AC_Cache *cache = 0; if(!retry && lane_idx() == 0) { U64 cache_hash = u64_hash_from_str8(str8_struct(&r->create)); U64 cache_slot_idx = cache_hash%ac_shared->cache_slots_count; Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx); RWMutexScope(cache_stripe->rw_mutex, 0) { for(AC_Cache *c = ac_shared->cache_slots[cache_slot_idx]; c != 0; c = c->next) { if(c->create == r->create) { cache = c; break; } } } } // rjf: write value into cache if(!retry && lane_idx() == 0) { U64 hash = u64_hash_from_str8(r->key); U64 slot_idx = hash%cache->slots_count; AC_Slot *slot = &cache->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 1) { for(AC_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, r->key, 0)) { n->last_completed_gen = gen; n->val = val; ins_atomic_u64_dec_eval(&n->working_count); ins_atomic_u64_inc_eval(&n->completion_count); } } } cond_var_broadcast(stripe->cv); } // rjf: increment count lane_sync(); done_wide_count += 1; } } lane_sync(); //- rjf: do all thin requests for this priority U64 done_thin_count = 0; ProfScope("thin requests (p%I64u)", task_idx) { U64 req_take_counter = 0; U64 *req_take_counter_ptr = 0; if(lane_idx() == 0) { req_take_counter_ptr = &req_take_counter; } lane_sync_u64(&req_take_counter_ptr, 0); for(;;) { // rjf: any new higher priority tasks? -> cancel if(task_idx == 1 && ins_atomic_u64_eval(req_take_counter_ptr) >= task->thin_count/2 && ins_atomic_u32_eval(&async_loop_again_high_priority)) { ins_atomic_u64_eval_assign(cancelled_ptr, 1); } // rjf: cancelled? -> exit if(ins_atomic_u64_eval(cancelled_ptr)) { break; } // rjf: take next task U64 req_idx = ins_atomic_u64_inc_eval(req_take_counter_ptr) - 1; if(req_idx >= task->thin_count) { break; } AC_Request *r = &task->thin[req_idx]; // rjf: push thin lane ctx U64 thin_lane_ctx_broadcast_memory = 0; LaneCtx thin_lane_ctx = {0, 1, {0}, &thin_lane_ctx_broadcast_memory}; LaneCtx lane_ctx_restore = lane_ctx(thin_lane_ctx); // rjf: compute val B32 retry = 0; U64 gen = r->gen; AC_Artifact val = r->create(r->key, r->cancel_signal, &retry, &gen); // rjf: restore wide lane ctx lane_ctx(lane_ctx_restore); // rjf: retry? -> resubmit request if(retry && !ins_atomic_u32_eval(r->cancel_signal)) { AC_RequestBatch *batch = &ac_shared->req_batches[task_idx]; MutexScope(batch->mutex) { AC_RequestNode *n = push_array(batch->arena, AC_RequestNode, 1); SLLQueuePush(batch->first_thin, batch->last_thin, n); batch->thin_count += 1; MemoryCopyStruct(&n->v, r); n->v.key = str8_copy(batch->arena, n->v.key); } ins_atomic_u32_eval_assign(&async_loop_again, 1); } // rjf: create function -> cache AC_Cache *cache = 0; if(!retry) { U64 cache_hash = u64_hash_from_str8(str8_struct(&r->create)); U64 cache_slot_idx = cache_hash%ac_shared->cache_slots_count; Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx); RWMutexScope(cache_stripe->rw_mutex, 0) { for(AC_Cache *c = ac_shared->cache_slots[cache_slot_idx]; c != 0; c = c->next) { if(c->create == r->create) { cache = c; break; } } } } // rjf: write value into cache if(!retry) { U64 hash = u64_hash_from_str8(r->key); U64 slot_idx = hash%cache->slots_count; AC_Slot *slot = &cache->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 1) { for(AC_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, r->key, 0)) { n->last_completed_gen = gen; n->val = val; ins_atomic_u64_dec_eval(&n->working_count); ins_atomic_u64_inc_eval(&n->completion_count); } } } cond_var_broadcast(stripe->cv); } } lane_sync(); done_thin_count = ins_atomic_u64_eval(req_take_counter_ptr); lane_sync(); } //- rjf: cancelled early, unfinished tasks? -> defer to next tick if(lane_idx() == 0 && task_idx > 0) { B32 need_another_try = (done_wide_count < task->wide_count || done_thin_count < task->thin_count); AC_RequestBatch *batch = &ac_shared->req_batches[task_idx]; MutexScope(batch->mutex) { // rjf: push leftover wide tasks for(U64 idx = done_wide_count; idx < task->wide_count; idx += 1) { AC_Request *r = &task->wide[idx]; AC_RequestNode *n = push_array(batch->arena, AC_RequestNode, 1); SLLQueuePush(batch->first_wide, batch->last_wide, n); batch->wide_count += 1; MemoryCopyStruct(&n->v, r); n->v.key = str8_copy(batch->arena, n->v.key); } // rjf: push leftover thin tasks for(U64 idx = done_thin_count; idx < task->thin_count; idx += 1) { AC_Request *r = &task->thin[idx]; AC_RequestNode *n = push_array(batch->arena, AC_RequestNode, 1); SLLQueuePush(batch->first_thin, batch->last_thin, n); batch->thin_count += 1; MemoryCopyStruct(&n->v, r); n->v.key = str8_copy(batch->arena, n->v.key); } } if(need_another_try) { ins_atomic_u32_eval_assign(&async_loop_again, 1); } } lane_sync(); } lane_sync(); ////////////////////////////// //- rjf: disable cancellation scanning // if(lane_idx() == 0) { semaphore_take(ac_shared->cancel_thread_semaphore, max_U64); } scratch_end(scratch); } //////////////////////////////// //~ rjf: Cancel Thread internal void ac_cancel_thread_entry_point(void *p) { for(;;) { os_sleep_milliseconds(50); semaphore_take(ac_shared->cancel_thread_semaphore, max_U64); { for EachIndex(cache_slot_idx, ac_shared->cache_slots_count) { Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx); RWMutexScope(cache_stripe->rw_mutex, 0) { for EachNode(cache, AC_Cache, ac_shared->cache_slots[cache_slot_idx]) { Rng1U64 slot_range = lane_range(cache->slots_count); for EachInRange(slot_idx, slot_range) { AC_Slot *slot = &cache->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx); for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { B32 slot_has_work = 0; RWMutexScope(stripe->rw_mutex, write_mode) { for(AC_Node *n = slot->first, *next = 0; n != 0; n = next) { next = n->next; if(access_pt_is_expired(&n->access_pt, .time = n->evict_threshold_us) && ins_atomic_u64_eval(&n->working_count) > 0) { slot_has_work = 1; if(!write_mode) { break; } else { n->cancelled = 1; } } } } if(!slot_has_work) { break; } } } } } } } semaphore_drop(ac_shared->cancel_thread_semaphore); } } ================================================ FILE: src/artifact_cache/artifact_cache.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ARTIFACT_CACHE_H #define ARTIFACT_CACHE_H //////////////////////////////// //~ rjf: Artifact Handle Type typedef struct AC_Artifact AC_Artifact; struct AC_Artifact { U64 u64[4]; }; //////////////////////////////// //~ rjf: Artifact Computation Function Types typedef AC_Artifact AC_CreateFunctionType(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); typedef void AC_DestroyFunctionType(AC_Artifact artifact); typedef U32 AC_Flags; typedef enum AC_FlagsEnum { AC_Flag_WaitForFresh = (1<<0), AC_Flag_HighPriority = (1<<1), AC_Flag_Wide = (1<<2), } AC_FlagsEnum; typedef struct AC_ArtifactParams AC_ArtifactParams; struct AC_ArtifactParams { AC_CreateFunctionType *create; AC_DestroyFunctionType *destroy; U64 slots_count; U64 gen; U64 evict_threshold_us; B32 *stale_out; AC_Flags flags; }; //////////////////////////////// //~ rjf: Cache Types typedef struct AC_Request AC_Request; struct AC_Request { String8 key; U64 gen; B32 *cancel_signal; AC_CreateFunctionType *create; }; typedef struct AC_RequestNode AC_RequestNode; struct AC_RequestNode { AC_RequestNode *next; AC_Request v; }; typedef struct AC_Node AC_Node; struct AC_Node { AC_Node *next; AC_Node *prev; // rjf: key/gen/value String8 key; U64 last_requested_gen; U64 last_completed_gen; AC_Artifact val; // rjf: metadata AccessPt access_pt; U64 working_count; U64 completion_count; U64 evict_threshold_us; B32 cancelled; U64 _unused_; }; typedef struct AC_Slot AC_Slot; struct AC_Slot { AC_Node *first; AC_Node *last; }; typedef struct AC_Cache AC_Cache; struct AC_Cache { // rjf: link / key for cache-cache AC_Cache *next; AC_CreateFunctionType *create; AC_DestroyFunctionType *destroy; // rjf: artifact cache U64 slots_count; AC_Slot *slots; StripeArray stripes; }; typedef struct AC_RequestBatch AC_RequestBatch; struct AC_RequestBatch { Mutex mutex; Arena *arena; AC_RequestNode *first_wide; AC_RequestNode *last_wide; AC_RequestNode *first_thin; AC_RequestNode *last_thin; U64 wide_count; U64 thin_count; }; typedef struct AC_Shared AC_Shared; struct AC_Shared { Arena *arena; // rjf: cache cache U64 cache_slots_count; AC_Cache **cache_slots; StripeArray cache_stripes; // rjf: requests AC_RequestBatch req_batches[2]; // 0: high priority, 1: low priority // rjf: cancel thread Thread cancel_thread; Semaphore cancel_thread_semaphore; }; //////////////////////////////// //~ rjf: Globals global AC_Shared *ac_shared = 0; //////////////////////////////// //~ rjf: Layer Initialization internal void ac_init(void); //////////////////////////////// //~ rjf: Cache Lookups internal AC_Artifact ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U64 endt_us); #define ac_artifact_from_key(access, key, create_fn, destroy_fn, endt_us, ...) ac_artifact_from_key_((access), (key), &(AC_ArtifactParams){.create = (create_fn), .destroy = (destroy_fn), .evict_threshold_us = (2000000), __VA_ARGS__}, (endt_us)) //////////////////////////////// //~ rjf: Asynchronous Tick internal void ac_async_tick(void); //////////////////////////////// //~ rjf: Cancel Thread internal void ac_cancel_thread_entry_point(void *p); #endif // ARTIFACT_CACHE_H ================================================ FILE: src/base/base_arena.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Arena Functions //- rjf: arena creation/destruction internal Arena * arena_alloc_(ArenaParams *params) { // rjf: round up reserve/commit sizes U64 reserve_size = params->reserve_size; U64 commit_size = params->commit_size; if(params->flags & ArenaFlag_LargePages) { reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size); } else { reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->page_size); } // rjf: reserve/commit initial block void *base = params->optional_backing_buffer; if(base == 0) { if(params->flags & ArenaFlag_LargePages) { base = os_reserve_large(reserve_size); os_commit_large(base, commit_size); } else { base = os_reserve(reserve_size); os_commit(base, commit_size); } raddbg_annotate_vaddr_range(base, reserve_size, "arena %s:%i", params->allocation_site_file, params->allocation_site_line); } // rjf: panic on arena creation failure #if OS_FEATURE_GRAPHICAL if(Unlikely(base == 0)) { os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_abort(1); } #endif // rjf: extract arena header & fill Arena *arena = (Arena *)base; arena->current = arena; arena->flags = params->flags; arena->cmt_size = params->commit_size; arena->res_size = params->reserve_size; arena->base_pos = 0; arena->pos = ARENA_HEADER_SIZE; arena->cmt = commit_size; arena->res = reserve_size; arena->allocation_site_file = params->allocation_site_file; arena->allocation_site_line = params->allocation_site_line; #if ARENA_FREE_LIST arena->free_last = 0; #endif AsanPoisonMemoryRegion(base, commit_size); AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE); return arena; } internal void arena_release(Arena *arena) { for(Arena *n = arena->current, *prev = 0; n != 0; n = prev) { prev = n->prev; os_release(n, n->res); } } //- rjf: arena push/pop core functions internal void * arena_push(Arena *arena, U64 size, U64 align, B32 zero) { Arena *current = arena->current; U64 pos_pre = AlignPow2(current->pos, align); U64 pos_pst = pos_pre + size; // rjf: chain, if needed if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain)) { Arena *new_block = 0; #if ARENA_FREE_LIST { Arena *prev_block; for(new_block = arena->free_last, prev_block = 0; new_block != 0; prev_block = new_block, new_block = new_block->prev) { if(new_block->res >= AlignPow2(new_block->pos, align) + size) { if(prev_block) { prev_block->prev = new_block->prev; } else { arena->free_last = new_block->prev; } break; } } } #endif if(new_block == 0) { U64 res_size = current->res_size; U64 cmt_size = current->cmt_size; if(size + ARENA_HEADER_SIZE > res_size) { res_size = AlignPow2(size + ARENA_HEADER_SIZE, align); cmt_size = AlignPow2(size + ARENA_HEADER_SIZE, align); } new_block = arena_alloc(.reserve_size = res_size, .commit_size = cmt_size, .flags = current->flags, .allocation_site_file = current->allocation_site_file, .allocation_site_line = current->allocation_site_line); } new_block->base_pos = current->base_pos + current->res; SLLStackPush_N(arena->current, new_block, prev); current = new_block; pos_pre = AlignPow2(current->pos, align); pos_pst = pos_pre + size; } // rjf: compute the size we need to zero U64 size_to_zero = 0; if(zero) { size_to_zero = Min(current->cmt, pos_pst) - pos_pre; } // rjf: commit new pages, if needed if(current->cmt < pos_pst) { U64 cmt_pst_aligned = pos_pst + current->cmt_size-1; cmt_pst_aligned -= cmt_pst_aligned%current->cmt_size; U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res); U64 cmt_size = cmt_pst_clamped - current->cmt; U8 *cmt_ptr = (U8 *)current + current->cmt; if(current->flags & ArenaFlag_LargePages) { os_commit_large(cmt_ptr, cmt_size); } else { os_commit(cmt_ptr, cmt_size); } current->cmt = cmt_pst_clamped; } // rjf: push onto current block void *result = 0; if(current->cmt >= pos_pst) { result = (U8 *)current+pos_pre; current->pos = pos_pst; AsanUnpoisonMemoryRegion(result, size); if(size_to_zero != 0) { MemoryZero(result, size_to_zero); } } // rjf: panic on failure #if OS_FEATURE_GRAPHICAL if(Unlikely(result == 0)) { os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_abort(1); } #endif return result; } internal U64 arena_pos(Arena *arena) { Arena *current = arena->current; U64 pos = current->base_pos + current->pos; return pos; } internal void arena_pop_to(Arena *arena, U64 pos) { U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos); Arena *current = arena->current; #if ARENA_FREE_LIST for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; current->pos = ARENA_HEADER_SIZE; SLLStackPush_N(arena->free_last, current, prev); AsanPoisonMemoryRegion((U8*)current + ARENA_HEADER_SIZE, current->res - ARENA_HEADER_SIZE); } #else for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; os_release(current, current->res); } #endif arena->current = current; U64 new_pos = big_pos - current->base_pos; AssertAlways(new_pos <= current->pos); AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos)); current->pos = new_pos; } //- rjf: arena push/pop helpers internal void arena_clear(Arena *arena) { arena_pop_to(arena, 0); } internal void arena_pop(Arena *arena, U64 amt) { U64 pos_old = arena_pos(arena); U64 pos_new = pos_old; if(amt < pos_old) { pos_new = pos_old - amt; } arena_pop_to(arena, pos_new); } //- rjf: temporary arena scopes internal Temp temp_begin(Arena *arena) { U64 pos = arena_pos(arena); Temp temp = {arena, pos}; return temp; } internal void temp_end(Temp temp) { arena_pop_to(temp.arena, temp.pos); } ================================================ FILE: src/base/base_arena.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ARENA_H #define BASE_ARENA_H //////////////////////////////// //~ rjf: Arena Types #define ARENA_HEADER_SIZE 128 typedef U64 ArenaFlags; enum { ArenaFlag_NoChain = (1<<0), ArenaFlag_LargePages = (1<<1), }; typedef struct ArenaParams ArenaParams; struct ArenaParams { ArenaFlags flags; U64 reserve_size; U64 commit_size; void *optional_backing_buffer; char *allocation_site_file; int allocation_site_line; }; typedef struct Arena Arena; struct Arena { Arena *prev; // previous arena in chain Arena *current; // current arena in chain ArenaFlags flags; U64 cmt_size; U64 res_size; U64 base_pos; U64 pos; U64 cmt; U64 res; char *allocation_site_file; int allocation_site_line; #if ARENA_FREE_LIST Arena *free_last; #endif }; StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check); typedef struct Temp Temp; struct Temp { Arena *arena; U64 pos; }; //////////////////////////////// //~ rjf: Arena Functions global U64 arena_default_reserve_size = MB(64); global U64 arena_default_commit_size = KB(64); global ArenaFlags arena_default_flags = 0; //- rjf: arena creation/destruction internal Arena *arena_alloc_(ArenaParams *params); #define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, .allocation_site_file = __FILE__, .allocation_site_line = __LINE__, __VA_ARGS__}) internal void arena_release(Arena *arena); //- rjf: arena push/pop/pos core functions internal void *arena_push(Arena *arena, U64 size, U64 align, B32 zero); internal U64 arena_pos(Arena *arena); internal void arena_pop_to(Arena *arena, U64 pos); //- rjf: arena push/pop helpers internal void arena_clear(Arena *arena); internal void arena_pop(Arena *arena, U64 amt); //- rjf: temporary arena scopes internal Temp temp_begin(Arena *arena); internal void temp_end(Temp temp); //- rjf: push helper macros #define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align), (0)) #define push_array_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align), (1)) #define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T))) #define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T))) #endif // BASE_ARENA_H ================================================ FILE: src/base/base_command_line.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Command Line Parsing Functions internal CmdLineOpt ** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string) { CmdLineOpt **slot = 0; if(cmd_line->option_table_size != 0) { U64 hash = u64_hash_from_str8(string); U64 bucket = hash % cmd_line->option_table_size; slot = &cmd_line->option_table[bucket]; } return slot; } internal CmdLineOpt * cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string) { CmdLineOpt *result = 0; for(CmdLineOpt *var = *slot; var; var = var->hash_next) { if(str8_match(string, var->string, 0)) { result = var; break; } } return result; } internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var) { SLLQueuePush(list->first, list->last, var); list->count += 1; } internal CmdLineOpt * cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values) { CmdLineOpt *var = 0; CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string); CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string); if(existing_var != 0) { var = existing_var; } else { var = push_array(arena, CmdLineOpt, 1); var->hash_next = *slot; var->hash = u64_hash_from_str8(string); var->string = push_str8_copy(arena, string); var->value_strings = values; StringJoin join = {0}; join.pre = str8_lit(""); join.sep = str8_lit(","); join.post = str8_lit(""); var->value_string = str8_list_join(arena, &var->value_strings, &join); *slot = var; cmd_line_push_opt(&cmd_line->options, var); } return var; } internal CmdLine cmd_line_from_string_list(Arena *arena, String8List command_line) { CmdLine parsed = {0}; parsed.exe_name = command_line.first->string; parsed.option_table_size = 64; parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size); //- rjf: parse options / inputs B32 after_passthrough_option = 0; B32 first_passthrough = 1; for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next) { next = node->next; //- rjf: look at --, -, or / (only on Windows) at the start of an // argument to determine if it's a flag option. all arguments after a // single "--" (with no trailing string on the command line will be // considered as passthrough input strings. B32 is_option = 0; String8 option_name = node->string; if(!after_passthrough_option) { is_option = 1; if(str8_match(node->string, str8_lit("--"), 0)) { after_passthrough_option = 1; is_option = 0; } else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0)) { option_name = str8_skip(option_name, 2); } else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0)) { option_name = str8_skip(option_name, 1); } else if(OperatingSystem_CURRENT == OperatingSystem_Windows && str8_match(str8_prefix(node->string, 1), str8_lit("/"), 0)) { option_name = str8_skip(option_name, 1); } else { is_option = 0; } } //- rjf: string is an option if(is_option) { // rjf: unpack option prefix B32 has_values = 0; U64 value_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0); U64 value_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0); U64 value_signifier_position = Min(value_signifier_position1, value_signifier_position2); String8 value_portion_this_string = str8_skip(option_name, value_signifier_position+1); if(value_signifier_position < option_name.size) { has_values = 1; } option_name = str8_prefix(option_name, value_signifier_position); // rjf: parse option's values String8List values = {0}; if(has_values) { for(String8Node *n = node; n; n = n->next) { next = n->next; String8 string = n->string; if(n == node) { string = value_portion_this_string; } U8 splits[] = { ',' }; String8List values_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0); for(String8Node *sub_val = values_in_this_string.first; sub_val; sub_val = sub_val->next) { str8_list_push(arena, &values, sub_val->string); } if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) && (n != node || value_portion_this_string.size != 0)) { break; } } } // rjf: store cmd_line_insert_opt(arena, &parsed, option_name, values); } //- rjf: default path - treat as a passthrough input else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough) { str8_list_push(arena, &parsed.inputs, node->string); first_passthrough = 0; } } //- rjf: fill argc/argv parsed.argc = command_line.node_count; parsed.argv = push_array(arena, char *, parsed.argc); { U64 idx = 0; for(String8Node *n = command_line.first; n != 0; n = n->next) { parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str; idx += 1; } } return parsed; } internal CmdLineOpt * cmd_line_opt_from_string(CmdLine *cmd_line, String8 name) { return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name); } internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name) { String8List result = {0}; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); if(var != 0) { result = var->value_strings; } return result; } internal String8 cmd_line_string(CmdLine *cmd_line, String8 name) { String8 result = {0}; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); if(var != 0) { result = var->value_string; } return result; } internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); return (var != 0); } internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); return (var != 0 && var->value_strings.node_count > 0); } ================================================ FILE: src/base/base_command_line.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_COMMAND_LINE_H #define BASE_COMMAND_LINE_H //////////////////////////////// //~ rjf: Parsed Command Line Types typedef struct CmdLineOpt CmdLineOpt; struct CmdLineOpt { CmdLineOpt *next; CmdLineOpt *hash_next; U64 hash; String8 string; String8List value_strings; String8 value_string; }; typedef struct CmdLineOptList CmdLineOptList; struct CmdLineOptList { U64 count; CmdLineOpt *first; CmdLineOpt *last; }; typedef struct CmdLine CmdLine; struct CmdLine { String8 exe_name; CmdLineOptList options; String8List inputs; U64 option_table_size; CmdLineOpt **option_table; U64 argc; char **argv; }; //////////////////////////////// //~ rjf: Command Line Parsing Functions internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string); internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string); internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var); internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values); internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments); internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name); internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name); internal String8 cmd_line_string(CmdLine *cmd_line, String8 name); internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name); internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name); #endif // BASE_COMMAND_LINE_H ================================================ FILE: src/base/base_context_cracking.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CONTEXT_CRACKING_H #define BASE_CONTEXT_CRACKING_H //////////////////////////////// //~ rjf: Clang OS/Arch Cracking #if defined(__clang__) # define COMPILER_CLANG 1 # if defined(_WIN32) # define OS_WINDOWS 1 # elif defined(__gnu_linux__) || defined(__linux__) # define OS_LINUX 1 # elif defined(__APPLE__) && defined(__MACH__) # define OS_MAC 1 # else # error This compiler/OS combo is not supported. # endif # if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # define ARCH_X64 1 # elif defined(i386) || defined(__i386) || defined(__i386__) # define ARCH_X86 1 # elif defined(__aarch64__) # define ARCH_ARM64 1 # elif defined(__arm__) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif //////////////////////////////// //~ rjf: MSVC OS/Arch Cracking #elif defined(_MSC_VER) # define COMPILER_MSVC 1 # if _MSC_VER >= 1920 # define COMPILER_MSVC_YEAR 2019 # elif _MSC_VER >= 1910 # define COMPILER_MSVC_YEAR 2017 # elif _MSC_VER >= 1900 # define COMPILER_MSVC_YEAR 2015 # elif _MSC_VER >= 1800 # define COMPILER_MSVC_YEAR 2013 # elif _MSC_VER >= 1700 # define COMPILER_MSVC_YEAR 2012 # elif _MSC_VER >= 1600 # define COMPILER_MSVC_YEAR 2010 # elif _MSC_VER >= 1500 # define COMPILER_MSVC_YEAR 2008 # elif _MSC_VER >= 1400 # define COMPILER_MSVC_YEAR 2005 # else # define COMPILER_MSVC_YEAR 0 # endif # if defined(_WIN32) # define OS_WINDOWS 1 # else # error This compiler/OS combo is not supported. # endif # if defined(_M_AMD64) # define ARCH_X64 1 # elif defined(_M_IX86) # define ARCH_X86 1 # elif defined(_M_ARM64) # define ARCH_ARM64 1 # elif defined(_M_ARM) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif //////////////////////////////// //~ rjf: GCC OS/Arch Cracking #elif defined(__GNUC__) || defined(__GNUG__) # define COMPILER_GCC 1 # if defined(__gnu_linux__) || defined(__linux__) # define OS_LINUX 1 # else # error This compiler/OS combo is not supported. # endif # if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # define ARCH_X64 1 # elif defined(i386) || defined(__i386) || defined(__i386__) # define ARCH_X86 1 # elif defined(__aarch64__) # define ARCH_ARM64 1 # elif defined(__arm__) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif #else # error Compiler not supported. #endif //////////////////////////////// //~ rjf: Arch Cracking #if defined(ARCH_X64) # define ARCH_64BIT 1 #elif defined(ARCH_X86) # define ARCH_32BIT 1 #endif #if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86 # define ARCH_LITTLE_ENDIAN 1 #else # error Endianness of this architecture not understood by context cracker. #endif //////////////////////////////// //~ rjf: Language Cracking #if defined(__cplusplus) # define LANG_CPP 1 #else # define LANG_C 1 #endif //////////////////////////////// //~ rjf: Build Option Cracking #if !defined(BUILD_DEBUG) # define BUILD_DEBUG 1 #endif #if !defined(BUILD_SUPPLEMENTARY_UNIT) # define BUILD_SUPPLEMENTARY_UNIT 0 #endif #if !defined(BUILD_ENTRY_DEFINING_UNIT) # define BUILD_ENTRY_DEFINING_UNIT 1 #endif #if !defined(BUILD_CONSOLE_INTERFACE) # define BUILD_CONSOLE_INTERFACE 0 #endif #if !defined(BUILD_VERSION_MAJOR) # define BUILD_VERSION_MAJOR 0 #endif #if !defined(BUILD_VERSION_MINOR) # define BUILD_VERSION_MINOR 9 #endif #if !defined(BUILD_VERSION_PATCH) # define BUILD_VERSION_PATCH 25 #endif #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) #if BUILD_DEBUG # define BUILD_MODE_STRING_LITERAL_APPEND " [Debug]" #else # define BUILD_MODE_STRING_LITERAL_APPEND "" #endif #if defined(BUILD_GIT_HASH) # define BUILD_GIT_HASH_STRING_LITERAL_APPEND " [" BUILD_GIT_HASH "]" #else # define BUILD_GIT_HASH_STRING_LITERAL_APPEND "" #endif #if !defined(BUILD_TITLE) # define BUILD_TITLE "Untitled" #endif #if !defined(BUILD_RELEASE_PHASE_STRING_LITERAL) # define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" #endif #if !defined(BUILD_ISSUES_LINK_STRING_LITERAL) # define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGamesExt/raddebugger/issues" #endif #define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND //////////////////////////////// //~ rjf: Zero All Undefined Options #if !defined(ARCH_32BIT) # define ARCH_32BIT 0 #endif #if !defined(ARCH_64BIT) # define ARCH_64BIT 0 #endif #if !defined(ARCH_X64) # define ARCH_X64 0 #endif #if !defined(ARCH_X86) # define ARCH_X86 0 #endif #if !defined(ARCH_ARM64) # define ARCH_ARM64 0 #endif #if !defined(ARCH_ARM32) # define ARCH_ARM32 0 #endif #if !defined(COMPILER_MSVC) # define COMPILER_MSVC 0 #endif #if !defined(COMPILER_GCC) # define COMPILER_GCC 0 #endif #if !defined(COMPILER_CLANG) # define COMPILER_CLANG 0 #endif #if !defined(OS_WINDOWS) # define OS_WINDOWS 0 #endif #if !defined(OS_LINUX) # define OS_LINUX 0 #endif #if !defined(OS_MAC) # define OS_MAC 0 #endif #if !defined(LANG_CPP) # define LANG_CPP 0 #endif #if !defined(LANG_C) # define LANG_C 0 #endif //////////////////////////////// //~ rjf: Unsupported Errors #if ARCH_X86 # error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported. #endif #if !ARCH_X64 # error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported. #endif #endif // BASE_CONTEXT_CRACKING_H ================================================ FILE: src/base/base_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Safe Casts internal U16 safe_cast_u16(U32 x) { AssertAlways(x <= max_U16); U16 result = (U16)x; return result; } internal U32 safe_cast_u32(U64 x) { AssertAlways(x <= max_U32); U32 result = (U32)x; return result; } internal S32 safe_cast_s32(S64 x) { AssertAlways(x <= max_S32); S32 result = (S32)x; return result; } //////////////////////////////// //~ rjf: Large Base Type Functions internal U128 u128_zero(void) { U128 v = {0}; return v; } internal U128 u128_make(U64 v0, U64 v1) { U128 v = { .u64 = { v0, v1 }}; return v; } internal B32 u128_match(U128 a, U128 b) { return MemoryMatchStruct(&a, &b); } //////////////////////////////// //~ rjf: Bit Patterns internal U32 u32_from_u64_saturate(U64 x){ U32 x32 = (x > max_U32)?max_U32:(U32)x; return(x32); } internal U64 u64_up_to_pow2(U64 x){ if (x == 0){ x = 1; } else{ x -= 1; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x |= (x >> 32); x += 1; } return(x); } internal S32 extend_sign32(U32 x, U32 size){ U32 high_bit = size * 8; U32 shift = 32 - high_bit; S32 result = ((S32)x << shift) >> shift; return result; } internal S64 extend_sign64(U64 x, U64 size){ U64 high_bit = size * 8; U64 shift = 64 - high_bit; S64 result = ((S64)x << shift) >> shift; return result; } internal F32 inf32(void){ union { U32 u; F32 f; } x; x.u = exponent32; return(x.f); } internal F32 neg_inf32(void){ union { U32 u; F32 f; } x; x.u = sign32 | exponent32; return(x.f); } internal U16 bswap_u16(U16 x) { U16 result = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)); return result; } internal U32 bswap_u32(U32 x) { U32 result = (((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24)); return result; } internal U64 bswap_u64(U64 x) { // TODO(nick): naive bswap, replace with something that is faster like an intrinsic U64 result = (((x & 0xFF00000000000000ULL) >> 56) | ((x & 0x00FF000000000000ULL) >> 40) | ((x & 0x0000FF0000000000ULL) >> 24) | ((x & 0x000000FF00000000ULL) >> 8) | ((x & 0x00000000FF000000ULL) << 8) | ((x & 0x0000000000FF0000ULL) << 24) | ((x & 0x000000000000FF00ULL) << 40) | ((x & 0x00000000000000FFULL) << 56)); return result; } #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) internal U64 count_bits_set32(U32 val) { return __popcnt(val); } internal U64 count_bits_set64(U64 val) { return __popcnt64(val); } internal U64 ctz32(U32 mask) { unsigned long idx; _BitScanForward(&idx, mask); return idx; } internal U64 ctz64(U64 mask) { unsigned long idx; _BitScanForward64(&idx, mask); return idx; } internal U64 clz32(U32 mask) { unsigned long idx; _BitScanReverse(&idx, mask); return 31 - idx; } internal U64 clz64(U64 mask) { unsigned long idx; _BitScanReverse64(&idx, mask); return 63 - idx; } #elif COMPILER_CLANG || COMPILER_GCC internal U64 count_bits_set32(U32 val) { return __builtin_popcount(val); } internal U64 count_bits_set64(U64 val) { return __builtin_popcountll(val); } internal U64 ctz32(U32 val) { return __builtin_ctz(val); } internal U64 clz32(U32 val) { return __builtin_clz(val); } internal U64 ctz64(U64 val) { return __builtin_ctzll(val); } internal U64 clz64(U64 val) { return __builtin_clzll(val); } #else # error "Bit intrinsic functions not defined for this compiler." #endif //////////////////////////////// //~ rjf: Enum -> Sign internal S32 sign_from_side_S32(Side side){ return((side == Side_Min)?-1:1); } internal F32 sign_from_side_F32(Side side){ return((side == Side_Min)?-1.f:1.f); } //////////////////////////////// //~ rjf: Memory Functions internal B32 memory_is_zero(void *ptr, U64 size) { B32 result = 1; // break down size U64 extra = (size&0x7); U64 count8 = (size >> 3); // check with 8-byte stride U64 *p64 = (U64*)ptr; if(result) { for(U64 i = 0; i < count8; i += 1, p64 += 1) { if(*p64 != 0) { result = 0; goto done; } } } // check extra if(result) { U8 *p8 = (U8*)p64; for(U64 i = 0; i < extra; i += 1, p8 += 1) { if(*p8 != 0) { result = 0; goto done; } } } done:; return result; } //////////////////////////////// //~ rjf: Text 2D Coordinate/Range Functions internal TxtPt txt_pt(S64 line, S64 column) { TxtPt p = {0}; p.line = line; p.column = column; return p; } internal B32 txt_pt_match(TxtPt a, TxtPt b) { return a.line == b.line && a.column == b.column; } internal B32 txt_pt_less_than(TxtPt a, TxtPt b) { B32 result = 0; if(a.line < b.line) { result = 1; } else if(a.line == b.line) { result = a.column < b.column; } return result; } internal TxtPt txt_pt_min(TxtPt a, TxtPt b) { TxtPt result = b; if(txt_pt_less_than(a, b)) { result = a; } return result; } internal TxtPt txt_pt_max(TxtPt a, TxtPt b) { TxtPt result = a; if(txt_pt_less_than(a, b)) { result = b; } return result; } internal TxtRng txt_rng(TxtPt min, TxtPt max) { TxtRng range = {0}; if(txt_pt_less_than(min, max)) { range.min = min; range.max = max; } else { range.min = max; range.max = min; } return range; } internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b) { TxtRng result = {0}; result.min = txt_pt_max(a.min, b.min); result.max = txt_pt_min(a.max, b.max); if(txt_pt_less_than(result.max, result.min)) { MemoryZeroStruct(&result); } return result; } internal TxtRng txt_rng_union(TxtRng a, TxtRng b) { TxtRng result = {0}; result.min = txt_pt_min(a.min, b.min); result.max = txt_pt_max(a.max, b.max); return result; } internal B32 txt_rng_contains(TxtRng r, TxtPt pt) { B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) && txt_pt_less_than(pt, r.max)); return result; } //////////////////////////////// //~ rjf: Toolchain/Environment Enum Functions internal U64 bit_size_from_arch(Arch arch) { // TODO(rjf): metacode U64 arch_bitsize = 0; switch(arch) { case Arch_x64: arch_bitsize = 64; break; case Arch_x86: arch_bitsize = 32; break; case Arch_arm64: arch_bitsize = 64; break; case Arch_arm32: arch_bitsize = 32; break; default: break; } return arch_bitsize; } internal U64 byte_size_from_arch(Arch arch) { return bit_size_from_arch(arch) / 8; } internal U64 max_instruction_size_from_arch(Arch arch) { // TODO(rjf): make this real return 64; } //////////////////////////////// //~ rjf: Time Functions internal DenseTime dense_time_from_date_time(DateTime date_time){ DenseTime result = 0; result += date_time.year; result *= 12; result += date_time.mon; result *= 31; result += date_time.day; result *= 24; result += date_time.hour; result *= 60; result += date_time.min; result *= 61; result += date_time.sec; result *= 1000; result += date_time.msec; return(result); } internal DateTime date_time_from_dense_time(DenseTime time){ DateTime result = {0}; result.msec = time%1000; time /= 1000; result.sec = time%61; time /= 61; result.min = time%60; time /= 60; result.hour = time%24; time /= 24; result.day = time%31; time /= 31; result.mon = time%12; time /= 12; Assert(time <= max_U32); result.year = (U32)time; return(result); } internal DateTime date_time_from_micro_seconds(U64 time){ DateTime result = {0}; result.micro_sec = time%1000; time /= 1000; result.msec = time%1000; time /= 1000; result.sec = time%60; time /= 60; result.min = time%60; time /= 60; result.hour = time%24; time /= 24; result.day = time%31; time /= 31; result.mon = time%12; time /= 12; Assert(time <= max_U32); result.year = (U32)time; return(result); } internal DateTime date_time_from_unix_time(U64 unix_time) { DateTime date = {0}; date.year = 1970; date.day = 1 + (unix_time / 86400); date.sec = (U32)unix_time % 60; date.min = (U32)(unix_time / 60) % 60; date.hour = (U32)(unix_time / 3600) % 24; for(;;) { for(date.month = 0; date.month < 12; ++date.month) { U64 c = 0; switch(date.month) { case Month_Jan: c = 31; break; case Month_Feb: { if((date.year % 4 == 0) && ((date.year % 100) != 0 || (date.year % 400) == 0)) { c = 29; } else { c = 28; } } break; case Month_Mar: c = 31; break; case Month_Apr: c = 30; break; case Month_May: c = 31; break; case Month_Jun: c = 30; break; case Month_Jul: c = 31; break; case Month_Aug: c = 31; break; case Month_Sep: c = 30; break; case Month_Oct: c = 31; break; case Month_Nov: c = 30; break; case Month_Dec: c = 31; break; default: InvalidPath; } if(date.day <= c) { goto exit; } date.day -= c; } ++date.year; } exit:; return date; } //////////////////////////////// //~ rjf: Non-Fancy Ring Buffer Reads/Writes internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size) { Assert(src_data_size <= ring_size); { U64 ring_off = ring_pos%ring_size; U64 bytes_before_split = ring_size-ring_off; U64 pre_split_bytes = Min(bytes_before_split, src_data_size); U64 pst_split_bytes = src_data_size-pre_split_bytes; void *pre_split_data = src_data; void *pst_split_data = ((U8 *)src_data + pre_split_bytes); MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes); MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes); } return src_data_size; } internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size) { Assert(read_size <= ring_size); { U64 ring_off = ring_pos%ring_size; U64 bytes_before_split = ring_size-ring_off; U64 pre_split_bytes = Min(bytes_before_split, read_size); U64 pst_split_bytes = read_size-pre_split_bytes; MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes); MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes); } return read_size; } //////////////////////////////// internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value) { if(count > 1 && arr[0] <= value && value < arr[count-1]) { U64 l = 0; U64 r = count - 1; for(; l <= r; ) { U64 m = l + (r - l) / 2; if(arr[m] == value) { return m; } else if(arr[m] < value) { l = m + 1; } else { r = m - 1; } } } else if (count == 1 && arr[0] == value) { return 0; } return max_U64; } //////////////////////////////// internal U64 index_of_zero_u32(U32 *ptr, U64 count) { for (U64 i = 0; i < count; i += 1) { if (ptr[i] == 0) { return i; } } return max_U64; } internal U64 index_of_zero_u64(U64 *ptr, U64 count) { for (U64 i = 0; i < count; i += 1) { if (ptr[i] == 0) { return i; } } return max_U64; } //////////////////////////////// //~ rjf: Third Party Includes #if !BUILD_SUPPLEMENTARY_UNIT #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsign-conversion" #elif defined(_MSC_VER) #pragma warning (push, 0) #endif # define STB_SPRINTF_IMPLEMENTATION # define STB_SPRINTF_STATIC # include "third_party/stb/stb_sprintf.h" #endif #if defined(__clang__) #pragma clang diagnostic pop #elif defined(_MSC_VER) #pragma warning (pop, 0) #endif //////////////////////////////// //~ rjf: String <-> Integer Tables read_only global U8 integer_symbols[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', }; // NOTE(rjf): Includes reverses for uppercase and lowercase hex. read_only global U8 integer_symbol_reverse[128] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; read_only global U8 base64[64] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '$', }; read_only global U8 base64_reverse[128] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, 0xFF,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32, 0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0xFF,0x3E, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0xFF,0xFF,0xFF,0xFF,0xFF, }; ================================================ FILE: src/base/base_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CORE_H #define BASE_CORE_H //////////////////////////////// //~ rjf: Foreign Includes #include #include #include #include #include //////////////////////////////// //~ rjf: Third Party Includes #define STB_SPRINTF_DECORATE(name) raddbg_##name #define STB_SPRINTF_STATIC #include "third_party/stb/stb_sprintf.h" //////////////////////////////// //~ rjf: Codebase Keywords #define internal static #define global static #define local_persist static #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) # pragma section(".rdata$", read) # define read_only __declspec(allocate(".rdata$")) #elif (COMPILER_CLANG && OS_LINUX) # define read_only __attribute__((section(".rodata"))) #else // NOTE(rjf): I don't know of a useful way to do this in GCC land. // __attribute__((section(".rodata"))) looked promising, but it introduces a // strange warning about malformed section attributes, and it doesn't look // like writing to that section reliably produces access violations, strangely // enough. (It does on Clang) # define read_only #endif #if COMPILER_MSVC # define thread_static __declspec(thread) #elif COMPILER_CLANG || COMPILER_GCC # define thread_static __thread #else # error thread_static not defined for this compiler. #endif #if COMPILER_MSVC # define force_inline __forceinline #elif COMPILER_CLANG || COMPILER_GCC # define force_inline __attribute__((always_inline)) #else # error force_inline not defined for this compiler. #endif #if COMPILER_MSVC # define no_inline __declspec(noinline) #elif COMPILER_CLANG || COMPILER_GCC # define no_inline __attribute__((noinline)) #else # error no_inline not defined for this compiler. #endif //////////////////////////////// //~ rjf: Linkage Keyword Macros #if OS_WINDOWS # define shared_function C_LINKAGE __declspec(dllexport) #else # define shared_function C_LINKAGE #endif #if LANG_CPP # define C_LINKAGE_BEGIN extern "C"{ # define C_LINKAGE_END } # define C_LINKAGE extern "C" #else # define C_LINKAGE_BEGIN # define C_LINKAGE_END # define C_LINKAGE #endif //////////////////////////////// //~ rjf: Optimization Settings #if COMPILER_MSVC # define OPTIMIZE_BEGIN _Pragma("optimize(\"\", on)") # define OPTIMIZE_END _Pragma("optimize(\"\", off)") #elif COMPILER_CLANG # define OPTIMIZE_BEGIN _Pragma("clang optimize on") # define OPTIMIZE_END _Pragma("clang optimize off") #elif COMPILER_GCC # define OPTIMIZE_BEGIN _Pragma("GCC push_options") _Pragma("GCC optimize(\"O2\")") # define OPTIMIZE_END _Pragma("GCC pop_options") #else # define OPTIMIZE_BEGIN # define OPTIMIZE_END #endif #if COMPILER_MSVC && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("optimize(\"\", off)") # define NO_OPTIMIZE_END _Pragma("optimize(\"\", on)") #elif COMPILER_CLANG && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("clang optimize off") # define NO_OPTIMIZE_END _Pragma("clang optimize on") #elif COMPILER_GCC && !BUILD_DEBUG # define NO_OPTIMIZE_BEGIN _Pragma("GCC push_options") _Pragma("GCC optimize(\"O0\")") # define NO_OPTIMIZE_END _Pragma("GCC pop_options") #else # define NO_OPTIMIZE_BEGIN # define NO_OPTIMIZE_END #endif //////////////////////////////// //~ rjf: Versions #define Version(major, minor, patch) (U64)((((U64)(major) & 0xffff) << 32) | ((((U64)(minor) & 0xffff) << 16)) | ((((U64)(patch) & 0xffff) << 0))) #define MajorFromVersion(version) (((version) & 0xffff00000000ull) >> 32) #define MinorFromVersion(version) (((version) & 0x0000ffff0000ull) >> 16) #define PatchFromVersion(version) (((version) & 0x00000000ffffull) >> 0) //////////////////////////////// //~ rjf: Units #define KB(n) (((U64)(n)) << 10) #define MB(n) (((U64)(n)) << 20) #define GB(n) (((U64)(n)) << 30) #define TB(n) (((U64)(n)) << 40) #define Thousand(n) ((n)*1000) #define Million(n) ((n)*1000000) #define Billion(n) ((n)*1000000000) //////////////////////////////// //~ rjf: Branch Predictor Hints #if defined(__clang__) # define Expect(expr, val) __builtin_expect((expr), (val)) #else # define Expect(expr, val) (expr) #endif #define Likely(expr) Expect(expr,1) #define Unlikely(expr) Expect(expr,0) //////////////////////////////// //~ rjf: Clamps, Mins, Maxes #define Min(A,B) (((A)<(B))?(A):(B)) #define Max(A,B) (((A)>(B))?(A):(B)) #define ClampTop(A,X) Min(A,X) #define ClampBot(X,B) Max(X,B) #define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X)) //////////////////////////////// //~ rjf: Type -> Alignment #if COMPILER_MSVC # define AlignOf(T) __alignof(T) #elif COMPILER_CLANG # define AlignOf(T) __alignof(T) #elif COMPILER_GCC # define AlignOf(T) __alignof__(T) #else # error AlignOf not defined for this compiler. #endif #if COMPILER_MSVC # define AlignType(x) __declspec(align(x)) #elif COMPILER_CLANG || COMPILER_GCC # define AlignType(x) __attribute__((aligned(x))) #else # error AlignType not defined for this compiler. #endif //////////////////////////////// //~ rjf: Member Offsets #define Member(T,m) (((T*)0)->m) #define OffsetOf(T,m) IntFromPtr(&Member(T,m)) #define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off))) #define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m)) //////////////////////////////// //~ rjf: For-Loop Construct Macros #define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) #define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) #define EachIndex(it, count) (U64 it = 0; it < (count); it += 1) #define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1) #define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1)) #define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) #define EachInRange(it, range) (U64 it = (range).min; it < (range).max; it += 1) #define EachNode(it, T, first) (T *it = first; it != 0; it = it->next) //////////////////////////////// //~ rjf: Memory Operation Macros #define MemoryCopy(dst, src, size) memmove((dst), (src), (size)) #define MemorySet(dst, byte, size) memset((dst), (byte), (size)) #define MemoryCompare(a, b, size) memcmp((a), (b), (size)) #define MemoryStrlen(ptr) strlen(ptr) #define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d))) #define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d)) #define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c)) #define MemoryCopyStr8(dst, s) MemoryCopy(dst, (s).str, (s).size) #define MemoryZero(s,z) memset((s),0,(z)) #define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s))) #define MemoryZeroArray(a) MemoryZero((a),sizeof(a)) #define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c)) #define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0) #define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a))) #define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a)) #define MemoryIsZeroStruct(ptr) memory_is_zero((ptr), sizeof(*(ptr))) #define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) ) #define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) ) //////////////////////////////// //~ rjf: Asserts #if COMPILER_MSVC # define Trap() __debugbreak() #elif COMPILER_CLANG || COMPILER_GCC # define Trap() __builtin_trap() #else # error Unknown trap intrinsic for this compiler. #endif #define AssertAlways(x) do{if(!(x)) {Trap();}}while(0) #if BUILD_DEBUG # define Assert(x) AssertAlways(x) #else # define Assert(x) (void)(x) #endif #define InvalidPath Assert(!"Invalid Path!") #define NotImplemented Assert(!"Not Implemented!") #define NoOp ((void)0) #define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1] //////////////////////////////// //~ rjf: Atomic Operations #if COMPILER_MSVC # include # if ARCH_X64 # define ins_atomic_u128_eval_cond_assign(x,k,c) (B32)InterlockedCompareExchange128((__int64 *)(x), ((__int64 *)&(k))[1], ((__int64 *)&(k))[0], (__int64 *)c) # define ins_atomic_u64_eval(x) *((volatile U64 *)(x)) # define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((__int64 *)(x)) # define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((__int64 *)(x)) # define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((__int64 *)(x),(c)) # define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((__int64 *)(x), c) # define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((__int64 *)(x),(k),(c)) # define ins_atomic_u32_eval(x) *((volatile U32 *)(x)) # define ins_atomic_u32_inc_eval(x) InterlockedIncrement((LONG *)(x)) # define ins_atomic_u32_dec_eval(x) InterlockedDecrement((LONG *)(x)) # define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((LONG *)(x),(c)) # define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((LONG *)(x),(k),(c)) # define ins_atomic_u32_add_eval(x,c) InterlockedAdd((LONG *)(x), (c)) # define ins_atomic_u8_eval_assign(x,c) InterlockedExchange8((CHAR *)(x), (c)) # else # error Atomic intrinsics not defined for this compiler / architecture combination. # endif #elif COMPILER_CLANG || COMPILER_GCC # define ins_atomic_u128_eval_cond_assign(x,k,c) (B32)__atomic_compare_exchange_n((__int128 *)(x),(__int128 *)(c),*(__int128 *)(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST) # define ins_atomic_u64_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) # define ins_atomic_u64_inc_eval(x) (__atomic_fetch_add((U64 *)(x), 1, __ATOMIC_SEQ_CST) + 1) # define ins_atomic_u64_dec_eval(x) (__atomic_fetch_sub((U64 *)(x), 1, __ATOMIC_SEQ_CST) - 1) # define ins_atomic_u64_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST) # define ins_atomic_u64_add_eval(x,c) (__atomic_fetch_add((U64 *)(x), c, __ATOMIC_SEQ_CST) + (c)) # define ins_atomic_u64_eval_cond_assign(x,k,c) ({ U64 _new = (c); __atomic_compare_exchange_n((U64 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) # define ins_atomic_u32_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) # define ins_atomic_u32_inc_eval(x) (__atomic_fetch_add((U32 *)(x), 1, __ATOMIC_SEQ_CST) + 1) # define ins_atomic_u32_dec_eval(x) (__atomic_fetch_sub((U32 *)(x), 1, __ATOMIC_SEQ_CST) - 1) # define ins_atomic_u32_add_eval(x,c) (__atomic_fetch_add((U32 *)(x), c, __ATOMIC_SEQ_CST) + (c)) # define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST) # define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) # define ins_atomic_u8_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST) #else # error Atomic intrinsics not defined for this compiler / architecture. #endif #if ARCH_64BIT # define ins_atomic_ptr_eval_cond_assign(x,k,c) (void *)ins_atomic_u64_eval_cond_assign((U64 *)(x), (U64)(k), (U64)(c)) # define ins_atomic_ptr_eval_assign(x,c) (void *)ins_atomic_u64_eval_assign((U64 *)(x), (U64)(c)) # define ins_atomic_ptr_eval(x) (void *)ins_atomic_u64_eval((U64 *)x) #else # error Atomic intrinsics for pointers not defined for this architecture. #endif //////////////////////////////// //~ rjf: Linked List Building Macros //- rjf: linked list macro helpers #define CheckNil(nil,p) ((p) == 0 || (p) == nil) #define SetNil(nil,p) ((p) = nil) //- rjf: doubly-linked-lists #define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \ ((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\ CheckNil(nil,p) ? \ ((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\ ((p)==(l)) ? \ ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\ (((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p)))) #define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev) #define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next) #define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\ ((n) == (l) ? (l) = (l)->prev : (0)),\ (CheckNil(nil,(n)->prev) ? (0) :\ ((n)->prev->next = (n)->next)),\ (CheckNil(nil,(n)->next) ? (0) :\ ((n)->next->prev = (n)->prev))) //- rjf: singly-linked, doubly-headed lists (queues) #define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ ((f)=(l)=(n),SetNil(nil,(n)->next)):\ ((l)->next=(n),(l)=(n),SetNil(nil,(n)->next))) #define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ ((f)=(l)=(n),SetNil(nil,(n)->next)):\ ((n)->next=(f),(f)=(n))) #define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ (SetNil(nil,f),SetNil(nil,l)):\ ((f)=(f)->next)) //- rjf: singly-linked, singly-headed lists (stacks) #define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) #define SLLStackPop_N(f,next) ((f)=(f)->next) //- rjf: doubly-linked-list helpers #define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev) #define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev) #define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev) #define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev) #define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev) #define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev) #define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev) #define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev) //- rjf: singly-linked, doubly-headed list helpers #define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next) #define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next) //- rjf: singly-linked, singly-headed list helpers #define SLLStackPush(f,n) SLLStackPush_N(f,n,next) #define SLLStackPop(f) SLLStackPop_N(f,next) //////////////////////////////// //~ rjf: Address Sanitizer Markup #if COMPILER_MSVC # if defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # define NO_ASAN __declspec(no_sanitize_address) # else # define NO_ASAN # endif #elif COMPILER_CLANG # if defined(__has_feature) # if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # endif # endif # define NO_ASAN __attribute__((no_sanitize("address"))) #else # define NO_ASAN #endif #if ASAN_ENABLED C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size); C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size); # define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size)) # define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size)) #else # define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) # define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) #endif //////////////////////////////// //~ rjf: Misc. Helper Macros #define Stringify_(S) #S #define Stringify(S) Stringify_(S) #define Glue_(A,B) A##B #define Glue(A,B) Glue_(A,B) #define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) #define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b)) #define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0) #if ARCH_64BIT # define IntFromPtr(ptr) ((U64)(ptr)) #elif ARCH_32BIT # define IntFromPtr(ptr) ((U32)(ptr)) #else # error Missing pointer-to-integer cast for this architecture. #endif #define PtrFromInt(i) (void*)(i) #define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)) #define Compose32Bit(a,b) ((((U32)a) << 16) | ((U32)b)) #define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) #define AlignDownPow2(x,b) ((x)&(~((b) - 1))) #define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1)) #define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0) #define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0) #define ExtractBit(word, idx) (((word) >> (idx)) & 1) #define Extract8(word, pos) (((word) >> ((pos)*8)) & max_U8) #define Extract16(word, pos) (((word) >> ((pos)*16)) & max_U16) #define Extract32(word, pos) (((word) >> ((pos)*32)) & max_U32) #if LANG_CPP # define zero_struct {} #else # define zero_struct {0} #endif #if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015 # define this_function_name "unknown" #else # define this_function_name __func__ #endif //////////////////////////////// //~ rjf: Base Types typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; typedef void VoidProc(void); typedef union U128 U128; union U128 { U8 u8[16]; U16 u16[8]; U32 u32[4]; U64 u64[2]; }; typedef union U256 U256; union U256 { U8 u8[32]; U16 u16[16]; U32 u32[8]; U64 u64[4]; U128 u128[2]; }; typedef union U512 U512; union U512 { U8 u8[64]; U16 u16[32]; U32 u32[16]; U64 u64[8]; U128 u128[4]; U256 u256[2]; }; //////////////////////////////// //~ rjf: Basic Type Structures typedef struct U16Array U16Array; struct U16Array { U64 count; U16 *v; }; typedef struct U32Array U32Array; struct U32Array { U64 count; U32 *v; }; typedef struct U64Array U64Array; struct U64Array { U64 count; U64 *v; }; typedef struct U128Array U128Array; struct U128Array { U64 count; U128 *v; }; //////////////////////////////// //~ rjf: Basic Types & Spaces typedef enum Dimension { Dimension_X, Dimension_Y, Dimension_Z, Dimension_W, } Dimension; typedef enum Side { Side_Invalid = -1, Side_Min, Side_Max, Side_COUNT, } Side; #define side_flip(s) ((Side)(!(s))) typedef enum Axis2 { Axis2_Invalid = -1, Axis2_X, Axis2_Y, Axis2_COUNT, } Axis2; #define axis2_flip(a) ((Axis2)(!(a))) typedef enum Corner { Corner_Invalid = -1, Corner_00, Corner_01, Corner_10, Corner_11, Corner_COUNT } Corner; typedef enum Dir2 { Dir2_Invalid = -1, Dir2_Left, Dir2_Up, Dir2_Right, Dir2_Down, Dir2_COUNT } Dir2; #define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X) #define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) //////////////////////////////// //~ rjf: Toolchain/Environment Enums typedef enum OperatingSystem { OperatingSystem_Null, OperatingSystem_Windows, OperatingSystem_Linux, OperatingSystem_Mac, OperatingSystem_COUNT, #if OS_WINDOWS OperatingSystem_CURRENT = OperatingSystem_Windows, #elif OS_LINUX OperatingSystem_CURRENT = OperatingSystem_Linux, #elif OS_MAC OperatingSystem_CURRENT = OperatingSystem_Mac, #else OperatingSystem_CURRENT = OperatingSystem_Null, #endif } OperatingSystem; typedef enum ExecutableImageKind { ExecutableImageKind_Null, ExecutableImageKind_CoffPe, ExecutableImageKind_Elf32, ExecutableImageKind_Elf64, ExecutableImageKind_Macho, ExecutableImageKind_COUNT } ExecutableImageKind; typedef enum Arch { Arch_Null, Arch_x64, Arch_x86, Arch_arm64, Arch_arm32, Arch_COUNT, } Arch; #if ARCH_X64 # define Arch_CURRENT Arch_x64 #elif ARCH_X86 # define Arch_CURRENT Arch_x86 #elif ARCH_ARM64 # define Arch_CURRENT Arch_arm64 #elif ARCH_ARM32 # define Arch_CURRENT Arch_arm32 #else # define Arch_CURRENT Arch_Null #endif typedef enum Compiler { Compiler_Null, Compiler_msvc, Compiler_gcc, Compiler_clang, Compiler_COUNT, } Compiler; #if COMPILER_MSVC # define Compiler_CURRENT Compiler_msvc #elif COMPILER_GCC # define Compiler_CURRENT Compiler_gcc #elif COMPILER_CLANG # define Compiler_CURRENT Compiler_clang #else # define Compiler_CURRENT Compiler_Null #endif //////////////////////////////// //~ rjf: Text 2D Coordinates & Ranges typedef struct TxtPt TxtPt; struct TxtPt { S64 line; S64 column; }; typedef struct TxtRng TxtRng; struct TxtRng { TxtPt min; TxtPt max; }; //////////////////////////////// //~ rjf: Globally Unique Ids typedef union Guid Guid; union Guid { struct { U32 data1; U16 data2; U16 data3; U8 data4[8]; }; U8 v[16]; }; StaticAssert(sizeof(Guid) == 16, g_guid_size_check); //////////////////////////////// //~ rjf: Basic Constants global U32 sign32 = 0x80000000; global U32 exponent32 = 0x7F800000; global U32 mantissa32 = 0x007FFFFF; global F32 big_golden32 = 1.61803398875f; global F32 small_golden32 = 0.61803398875f; global F32 pi32 = 3.1415926535897f; global F64 machine_epsilon64 = 4.94065645841247e-324; global U64 max_U64 = 0xffffffffffffffffull; global U32 max_U32 = 0xffffffff; global U16 max_U16 = 0xffff; global U8 max_U8 = 0xff; global S64 max_S64 = (S64)0x7fffffffffffffffll; global S32 max_S32 = (S32)0x7fffffff; global S16 max_S16 = (S16)0x7fff; global S8 max_S8 = (S8)0x7f; global S64 min_S64 = (S64)0x8000000000000000ll; global S32 min_S32 = (S32)0x80000000; global S16 min_S16 = (S16)0x8000; global S8 min_S8 = (S8)0x80; global const U32 bitmask1 = 0x00000001; global const U32 bitmask2 = 0x00000003; global const U32 bitmask3 = 0x00000007; global const U32 bitmask4 = 0x0000000f; global const U32 bitmask5 = 0x0000001f; global const U32 bitmask6 = 0x0000003f; global const U32 bitmask7 = 0x0000007f; global const U32 bitmask8 = 0x000000ff; global const U32 bitmask9 = 0x000001ff; global const U32 bitmask10 = 0x000003ff; global const U32 bitmask11 = 0x000007ff; global const U32 bitmask12 = 0x00000fff; global const U32 bitmask13 = 0x00001fff; global const U32 bitmask14 = 0x00003fff; global const U32 bitmask15 = 0x00007fff; global const U32 bitmask16 = 0x0000ffff; global const U32 bitmask17 = 0x0001ffff; global const U32 bitmask18 = 0x0003ffff; global const U32 bitmask19 = 0x0007ffff; global const U32 bitmask20 = 0x000fffff; global const U32 bitmask21 = 0x001fffff; global const U32 bitmask22 = 0x003fffff; global const U32 bitmask23 = 0x007fffff; global const U32 bitmask24 = 0x00ffffff; global const U32 bitmask25 = 0x01ffffff; global const U32 bitmask26 = 0x03ffffff; global const U32 bitmask27 = 0x07ffffff; global const U32 bitmask28 = 0x0fffffff; global const U32 bitmask29 = 0x1fffffff; global const U32 bitmask30 = 0x3fffffff; global const U32 bitmask31 = 0x7fffffff; global const U32 bitmask32 = 0xffffffff; global const U64 bitmask33 = 0x00000001ffffffffull; global const U64 bitmask34 = 0x00000003ffffffffull; global const U64 bitmask35 = 0x00000007ffffffffull; global const U64 bitmask36 = 0x0000000fffffffffull; global const U64 bitmask37 = 0x0000001fffffffffull; global const U64 bitmask38 = 0x0000003fffffffffull; global const U64 bitmask39 = 0x0000007fffffffffull; global const U64 bitmask40 = 0x000000ffffffffffull; global const U64 bitmask41 = 0x000001ffffffffffull; global const U64 bitmask42 = 0x000003ffffffffffull; global const U64 bitmask43 = 0x000007ffffffffffull; global const U64 bitmask44 = 0x00000fffffffffffull; global const U64 bitmask45 = 0x00001fffffffffffull; global const U64 bitmask46 = 0x00003fffffffffffull; global const U64 bitmask47 = 0x00007fffffffffffull; global const U64 bitmask48 = 0x0000ffffffffffffull; global const U64 bitmask49 = 0x0001ffffffffffffull; global const U64 bitmask50 = 0x0003ffffffffffffull; global const U64 bitmask51 = 0x0007ffffffffffffull; global const U64 bitmask52 = 0x000fffffffffffffull; global const U64 bitmask53 = 0x001fffffffffffffull; global const U64 bitmask54 = 0x003fffffffffffffull; global const U64 bitmask55 = 0x007fffffffffffffull; global const U64 bitmask56 = 0x00ffffffffffffffull; global const U64 bitmask57 = 0x01ffffffffffffffull; global const U64 bitmask58 = 0x03ffffffffffffffull; global const U64 bitmask59 = 0x07ffffffffffffffull; global const U64 bitmask60 = 0x0fffffffffffffffull; global const U64 bitmask61 = 0x1fffffffffffffffull; global const U64 bitmask62 = 0x3fffffffffffffffull; global const U64 bitmask63 = 0x7fffffffffffffffull; global const U64 bitmask64 = 0xffffffffffffffffull; global const U32 bit1 = (1<<0); global const U32 bit2 = (1<<1); global const U32 bit3 = (1<<2); global const U32 bit4 = (1<<3); global const U32 bit5 = (1<<4); global const U32 bit6 = (1<<5); global const U32 bit7 = (1<<6); global const U32 bit8 = (1<<7); global const U32 bit9 = (1<<8); global const U32 bit10 = (1<<9); global const U32 bit11 = (1<<10); global const U32 bit12 = (1<<11); global const U32 bit13 = (1<<12); global const U32 bit14 = (1<<13); global const U32 bit15 = (1<<14); global const U32 bit16 = (1<<15); global const U32 bit17 = (1<<16); global const U32 bit18 = (1<<17); global const U32 bit19 = (1<<18); global const U32 bit20 = (1<<19); global const U32 bit21 = (1<<20); global const U32 bit22 = (1<<21); global const U32 bit23 = (1<<22); global const U32 bit24 = (1<<23); global const U32 bit25 = (1<<24); global const U32 bit26 = (1<<25); global const U32 bit27 = (1<<26); global const U32 bit28 = (1<<27); global const U32 bit29 = (1<<28); global const U32 bit30 = (1<<29); global const U32 bit31 = (1<<30); global const U32 bit32 = (1<<31); global const U64 bit33 = (1ull<<32); global const U64 bit34 = (1ull<<33); global const U64 bit35 = (1ull<<34); global const U64 bit36 = (1ull<<35); global const U64 bit37 = (1ull<<36); global const U64 bit38 = (1ull<<37); global const U64 bit39 = (1ull<<38); global const U64 bit40 = (1ull<<39); global const U64 bit41 = (1ull<<40); global const U64 bit42 = (1ull<<41); global const U64 bit43 = (1ull<<42); global const U64 bit44 = (1ull<<43); global const U64 bit45 = (1ull<<44); global const U64 bit46 = (1ull<<45); global const U64 bit47 = (1ull<<46); global const U64 bit48 = (1ull<<47); global const U64 bit49 = (1ull<<48); global const U64 bit50 = (1ull<<49); global const U64 bit51 = (1ull<<50); global const U64 bit52 = (1ull<<51); global const U64 bit53 = (1ull<<52); global const U64 bit54 = (1ull<<53); global const U64 bit55 = (1ull<<54); global const U64 bit56 = (1ull<<55); global const U64 bit57 = (1ull<<56); global const U64 bit58 = (1ull<<57); global const U64 bit59 = (1ull<<58); global const U64 bit60 = (1ull<<59); global const U64 bit61 = (1ull<<60); global const U64 bit62 = (1ull<<61); global const U64 bit63 = (1ull<<62); global const U64 bit64 = (1ull<<63); //////////////////////////////// //~ rjf: Time Types typedef enum WeekDay { WeekDay_Sun, WeekDay_Mon, WeekDay_Tue, WeekDay_Wed, WeekDay_Thu, WeekDay_Fri, WeekDay_Sat, WeekDay_COUNT, } WeekDay; typedef enum Month { Month_Jan, Month_Feb, Month_Mar, Month_Apr, Month_May, Month_Jun, Month_Jul, Month_Aug, Month_Sep, Month_Oct, Month_Nov, Month_Dec, Month_COUNT, } Month; typedef struct DateTime DateTime; struct DateTime { U16 micro_sec; // [0,999] U16 msec; // [0,999] U16 sec; // [0,60] U16 min; // [0,59] U16 hour; // [0,24] U16 day; // [0,30] union { WeekDay week_day; U32 wday; }; union { Month month; U32 mon; }; U32 year; // 1 = 1 CE, 0 = 1 BC }; typedef U64 DenseTime; //////////////////////////////// //~ rjf: File Types typedef U32 FilePropertyFlags; enum { FilePropertyFlag_IsFolder = (1 << 0), }; typedef struct FileProperties FileProperties; struct FileProperties { U64 size; DenseTime modified; DenseTime created; FilePropertyFlags flags; }; //////////////////////////////// //~ rjf: Safe Casts internal U16 safe_cast_u16(U32 x); internal U32 safe_cast_u32(U64 x); internal S32 safe_cast_s32(S64 x); //////////////////////////////// //~ rjf: Large Base Type Functions internal U128 u128_zero(void); internal U128 u128_make(U64 v0, U64 v1); internal B32 u128_match(U128 a, U128 b); //////////////////////////////// //~ rjf: Bit Patterns internal U32 u32_from_u64_saturate(U64 x); internal U64 u64_up_to_pow2(U64 x); internal S32 extend_sign32(U32 x, U32 size); internal S64 extend_sign64(U64 x, U64 size); internal F32 inf32(void); internal F32 neg_inf32(void); internal U16 bswap_u16(U16 x); internal U32 bswap_u32(U32 x); internal U64 bswap_u64(U64 x); #if ARCH_LITTLE_ENDIAN # define from_be_u16(x) bswap_u16(x) # define from_be_u32(x) bswap_u32(x) # define from_be_u64(x) bswap_u64(x) #else # define from_be_u16(x) (x) # define from_be_u32(x) (x) # define from_be_u64(x) (x) #endif internal U64 count_bits_set32(U32 val); internal U64 count_bits_set64(U64 val); internal U64 ctz32(U32 val); internal U64 ctz64(U64 val); internal U64 clz32(U32 val); internal U64 clz64(U64 val); //////////////////////////////// //~ rjf: Enum -> Sign internal S32 sign_from_side_S32(Side side); internal F32 sign_from_side_F32(Side side); //////////////////////////////// //~ rjf: Memory Functions internal B32 memory_is_zero(void *ptr, U64 size); //////////////////////////////// //~ rjf: Text 2D Coordinate/Range Functions internal TxtPt txt_pt(S64 line, S64 column); internal B32 txt_pt_match(TxtPt a, TxtPt b); internal B32 txt_pt_less_than(TxtPt a, TxtPt b); internal TxtPt txt_pt_min(TxtPt a, TxtPt b); internal TxtPt txt_pt_max(TxtPt a, TxtPt b); internal TxtRng txt_rng(TxtPt min, TxtPt max); internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b); internal TxtRng txt_rng_union(TxtRng a, TxtRng b); internal B32 txt_rng_contains(TxtRng r, TxtPt pt); //////////////////////////////// //~ rjf: Toolchain/Environment Enum Functions internal U64 bit_size_from_arch(Arch arch); internal U64 byte_size_from_arch(Arch arch); internal U64 max_instruction_size_from_arch(Arch arch); //////////////////////////////// //~ rjf: Time Functions internal DenseTime dense_time_from_date_time(DateTime date_time); internal DateTime date_time_from_dense_time(DenseTime time); internal DateTime date_time_from_micro_seconds(U64 time); internal DateTime date_time_from_unix_time(U64 unix_time); //////////////////////////////// //~ rjf: Non-Fancy Ring Buffer Reads/Writes internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size); internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size); #define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) #define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) //////////////////////////////// //~ rjf: Sorts #define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function)) //////////////////////////////// internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value); //////////////////////////////// internal U64 index_of_zero_u32(U32 *ptr, U64 count); internal U64 index_of_zero_u64(U64 *ptr, U64 count); #endif // BASE_CORE_H ================================================ FILE: src/base/base_entry_point.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) global U64 global_update_tick_idx = 0; global U64 async_threads_count = 0; global CondVar async_tick_start_cond_var = {0}; global Mutex async_tick_start_mutex = {0}; global Mutex async_tick_stop_mutex = {0}; global B32 async_loop_again = 0; global B32 async_loop_again_high_priority = 0; global B32 global_async_exit = 0; thread_static B32 is_async_thread = 0; internal void main_thread_base_entry_point(int arguments_count, char **arguments) { ThreadNameF("main_thread"); Temp scratch = scratch_begin(0, 0); //- rjf: set up async thread group info async_tick_start_cond_var = cond_var_alloc(); async_tick_start_mutex = mutex_alloc(); async_tick_stop_mutex = mutex_alloc(); //- rjf: set up telemetry #if PROFILE_TELEMETRY local_persist char tm_data[MB(64)]; tmLoadLibrary(TM_RELEASE); tmSetMaxThreadCount(256); tmInitialize(sizeof(tm_data), tm_data); #endif //- rjf: set up spall #if PROFILE_SPALL spall_profile = spall_init_file_ex("spall_capture", 1, 0); #endif //- rjf: parse command line String8List command_line_argument_strings = {0}; { for EachIndex(idx, arguments_count) { str8_list_push(scratch.arena, &command_line_argument_strings, str8_cstring(arguments[idx])); } } CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); //- rjf: begin captures B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture")); if(capture) { ProfBeginCapture(arguments[0]); ProfMsg(BUILD_TITLE); } //- rjf: initialize all included layers #if defined(ARTIFACT_CACHE_H) && !defined(AC_INIT_MANUAL) ac_init(); #endif #if defined(CONTENT_H) && !defined(C_INIT_MANUAL) c_init(); #endif #if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL) fs_init(); #endif #if defined(MUTABLE_TEXT_H) && !defined(MTX_INIT_MANUAL) mtx_init(); #endif #if defined(DBG_INFO_H) && !defined(DI_INIT_MANUAL) di_init(&cmdline); #endif #if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) dmn_init(); #endif #if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL) ctrl_init(); #endif #if defined(OS_GFX_H) && !defined(OS_GFX_INIT_MANUAL) os_gfx_init(); #endif #if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL) fp_init(); #endif #if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL) r_init(&cmdline); #endif #if defined(FONT_CACHE_H) && !defined(FNT_INIT_MANUAL) fnt_init(); #endif #if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL) d_init(); #endif #if defined(RADDBG_CORE_H) && !defined(RD_INIT_MANUAL) rd_init(&cmdline); #endif //- rjf: launch async threads Thread *async_threads = 0; U64 lane_broadcast_val = 0; { U64 num_main_threads = 1; #if defined(CTRL_CORE_H) num_main_threads += 1; #endif U64 num_async_threads = os_get_system_info()->logical_processor_count; U64 num_main_threads_clamped = Min(num_async_threads, num_main_threads); num_async_threads -= num_main_threads_clamped; String8 num_async_threads_string = cmd_line_string(&cmdline, str8_lit("async_thread_count")); if(num_async_threads_string.size != 0) { try_u64_from_str8_c_rules(num_async_threads_string, &num_async_threads); } num_async_threads = Max(1, num_async_threads); Barrier barrier = barrier_alloc(num_async_threads); LaneCtx *lane_ctxs = push_array(scratch.arena, LaneCtx, num_async_threads); async_threads_count = num_async_threads; async_threads = push_array(scratch.arena, Thread, async_threads_count); for EachIndex(idx, num_async_threads) { lane_ctxs[idx].lane_idx = idx; lane_ctxs[idx].lane_count = async_threads_count; lane_ctxs[idx].barrier = barrier; lane_ctxs[idx].broadcast_memory = &lane_broadcast_val; async_threads[idx] = thread_launch(async_thread_entry_point, &lane_ctxs[idx]); } } //- rjf: call into entry point entry_point(&cmdline); //- rjf: join async threads ins_atomic_u32_inc_eval(&global_async_exit); cond_var_broadcast(async_tick_start_cond_var); for EachIndex(idx, async_threads_count) { thread_join(async_threads[idx], max_U64); } //- rjf: end captures if(capture) { ProfEndCapture(); } scratch_end(scratch); } internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params) { TCTX *tctx = tctx_alloc(); tctx_select(tctx); entry_point(params); tctx_release(tctx); } internal U64 update_tick_idx(void) { U64 result = ins_atomic_u64_eval(&global_update_tick_idx); return result; } internal B32 update(void) { ProfTick(0); ins_atomic_u64_inc_eval(&global_update_tick_idx); #if defined(FONT_CACHE_H) fnt_frame(); #endif #if OS_FEATURE_GRAPHICAL B32 result = frame(); #else B32 result = 0; #endif return result; } internal void async_thread_entry_point(void *params) { LaneCtx lctx = *(LaneCtx *)params; lane_ctx(lctx); is_async_thread = 1; ThreadNameF("async_thread_%I64u", lane_idx()); for(;;) { // rjf: wait for signal if we need, otherwise reset loop signal & continue if(lane_idx() == 0) { if(!ins_atomic_u32_eval(&async_loop_again)) { MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+1000000); } ins_atomic_u32_eval_assign(&async_loop_again, 0); ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 0); } lane_sync(); // rjf: do all ticks for all layers ProfScope("async tick") { #if defined(ARTIFACT_CACHE_H) ac_async_tick(); #endif #if defined(CONTENT_H) c_async_tick(); #endif #if defined(FILE_STREAM_H) fs_async_tick(); #endif #if defined(DBG_INFO_H) di_async_tick(); #endif } // rjf: take exit signal; break if set lane_sync(); B32 need_exit = 0; if(lane_idx() == 0) { need_exit = ins_atomic_u32_eval(&global_async_exit); } lane_sync_u64(&need_exit, 0); if(need_exit) { break; } } } ================================================ FILE: src/base/base_entry_point.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ENTRY_POINT_H #define BASE_ENTRY_POINT_H internal void main_thread_base_entry_point(int argc, char **argv); internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params); internal U64 update_tick_idx(void); internal B32 update(void); internal void async_thread_entry_point(void *params); #endif // BASE_ENTRY_POINT_H ================================================ FILE: src/base/base_hash.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: MD5 #include "third_party/martins_hash/md5.h" internal MD5 md5_from_data(String8 data) { md5_ctx ctx = {0}; md5_init(&ctx); md5_update(&ctx, (void*)data.str, data.size); MD5 result = {0}; md5_finish(&ctx, result.u8); return result; } //////////////////////////////// //~ rjf: SHA #include "third_party/martins_hash/sha1.h" #include "third_party/martins_hash/sha256.h" internal SHA1 sha1_from_data(String8 data) { SHA1 result = {0}; { sha1_ctx ctx = {0}; sha1_init(&ctx); sha1_update(&ctx, data.str, data.size); sha1_finish(&ctx, result.u8); } return result; } internal SHA256 sha256_from_data(String8 data) { SHA256 result = {0}; { sha256_ctx ctx = {0}; sha256_init(&ctx); sha256_update(&ctx, data.str, data.size); sha256_finish(&ctx, result.u8); } return result; } ================================================ FILE: src/base/base_hash.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_HASH_H #define BASE_HASH_H //////////////////////////////// //~ rjf: Hash Result Types typedef union MD5 MD5; union MD5 { U8 u8[16]; U16 u16[8]; U32 u32[4]; U64 u64[2]; U128 u128; }; typedef union SHA1 SHA1; union SHA1 { U8 u8[20]; }; typedef union SHA256 SHA256; union SHA256 { U8 u8[32]; U16 u16[16]; U32 u32[8]; U64 u64[4]; U128 u128[2]; U256 u256; }; //////////////////////////////// //~ rjf: MD5 internal MD5 md5_from_data(String8 data); //////////////////////////////// //~ rjf: SHA internal SHA1 sha1_from_data(String8 data); internal SHA256 sha256_from_data(String8 data); #endif // BASE_HASH_H ================================================ FILE: src/base/base_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Base Includes #undef LAYER_COLOR #define LAYER_COLOR 0x3399ccff #include "base_core.c" #include "base_profile.c" #include "base_arena.c" #include "base_math.c" #include "base_strings.c" #include "base_hash.c" #include "base_threads.c" #include "base_thread_context.c" #include "base_command_line.c" #include "base_markup.c" #include "base_meta.c" #include "base_log.c" #include "base_entry_point.c" ================================================ FILE: src/base/base_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_INC_H #define BASE_INC_H //////////////////////////////// //~ rjf: Base Includes #include "base_context_cracking.h" #include "base_core.h" #include "base_profile.h" #include "base_arena.h" #include "base_math.h" #include "base_strings.h" #include "base_hash.h" #include "base_threads.h" #include "base_thread_context.h" #include "base_command_line.h" #include "base_markup.h" #include "base_meta.h" #include "base_log.h" #include "base_entry_point.h" #endif // BASE_INC_H ================================================ FILE: src/base/base_log.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Globals/Thread-Locals C_LINKAGE thread_static Log *log_active; #if !BUILD_SUPPLEMENTARY_UNIT C_LINKAGE thread_static Log *log_active = 0; #endif //////////////////////////////// //~ rjf: Log Creation/Selection internal Log * log_alloc(void) { Arena *arena = arena_alloc(); Log *log = push_array(arena, Log, 1); log->arena = arena; return log; } internal void log_release(Log *log) { arena_release(log->arena); } internal void log_select(Log *log) { log_active = log; } //////////////////////////////// //~ rjf: Log Building/Clearing internal void log_msg(LogMsgKind kind, String8 string) { if(log_active != 0 && log_active->top_scope != 0) { String8 string_copy = push_str8_copy(log_active->arena, string); str8_list_push(log_active->arena, &log_active->top_scope->strings[kind], string_copy); } } internal void log_msgf(LogMsgKind kind, char *fmt, ...) { if(log_active != 0) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); log_msg(kind, string); va_end(args); scratch_end(scratch); } } //////////////////////////////// //~ rjf: Log Scopes internal void log_scope_begin(void) { if(log_active != 0) { U64 pos = arena_pos(log_active->arena); LogScope *scope = push_array(log_active->arena, LogScope, 1); scope->pos = pos; SLLStackPush(log_active->top_scope, scope); } } internal LogScopeResult log_scope_end(Arena *arena) { LogScopeResult result = {0}; if(log_active != 0) { LogScope *scope = log_active->top_scope; if(scope != 0) { SLLStackPop(log_active->top_scope); if(arena != 0) { for EachEnumVal(LogMsgKind, kind) { Temp scratch = scratch_begin(&arena, 1); String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0); result.strings[kind] = indented_from_string(arena, result_unindented); scratch_end(scratch); } } arena_pop_to(log_active->arena, scope->pos); } } return result; } ================================================ FILE: src/base/base_log.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_LOG_H #define BASE_LOG_H //////////////////////////////// //~ rjf: Log Types typedef enum LogMsgKind { LogMsgKind_Info, LogMsgKind_UserError, LogMsgKind_COUNT } LogMsgKind; typedef struct LogScope LogScope; struct LogScope { LogScope *next; U64 pos; String8List strings[LogMsgKind_COUNT]; }; typedef struct LogScopeResult LogScopeResult; struct LogScopeResult { String8 strings[LogMsgKind_COUNT]; }; typedef struct Log Log; struct Log { Arena *arena; LogScope *top_scope; }; //////////////////////////////// //~ rjf: Log Creation/Selection internal Log *log_alloc(void); internal void log_release(Log *log); internal void log_select(Log *log); //////////////////////////////// //~ rjf: Log Building internal void log_msg(LogMsgKind kind, String8 string); internal void log_msgf(LogMsgKind kind, char *fmt, ...); #define log_info(s) log_msg(LogMsgKind_Info, (s)) #define log_infof(...) log_msgf(LogMsgKind_Info, __VA_ARGS__) #define log_user_error(s) log_msg(LogMsgKind_UserError, (s)) #define log_user_errorf(...) log_msgf(LogMsgKind_UserError, __VA_ARGS__) #define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n")) #define LogInfoNamedBlockF(...) DeferLoop((log_infof(__VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n")) //////////////////////////////// //~ rjf: Log Scopes internal void log_scope_begin(void); internal LogScopeResult log_scope_end(Arena *arena); #endif // BASE_LOG_H ================================================ FILE: src/base/base_markup.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void set_thread_name(String8 string) { ProfThreadName("%.*s", str8_varg(string)); os_set_thread_name(string); } internal void set_thread_namef(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); set_thread_name(string); va_end(args); scratch_end(scratch); } ================================================ FILE: src/base/base_markup.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MARKUP_H #define BASE_MARKUP_H #define RADDBG_MARKUP_IMPLEMENTATION #define RADDBG_MARKUP_VSNPRINTF raddbg_vsnprintf #if OS_LINUX # define RADDBG_MARKUP_STUBS #endif #include "lib_raddbg_markup/raddbg_markup.h" #if !defined(LAYER_COLOR) # define LAYER_COLOR 0x404040ff #endif internal void set_thread_name(String8 string); internal void set_thread_namef(char *fmt, ...); #define ThreadNameF(...) (set_thread_namef(__VA_ARGS__), raddbg_thread_color_u32(LAYER_COLOR)) #endif // BASE_MARKUP_H ================================================ FILE: src/base/base_math.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Scalar Math Ops internal F32 mix_1f32(F32 a, F32 b, F32 t) { F32 c = (a + (b-a) * Clamp(0.f, t, 1.f)); return c; } internal F64 mix_1f64(F64 a, F64 b, F64 t) { F64 c = (a + (b-a) * Clamp(0.0, t, 1.0)); return c; } //////////////////////////////// //~ rjf: Vector Ops internal Vec2F32 vec_2f32(F32 x, F32 y) {Vec2F32 v = {x, y}; return v;} internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2F32 scale_2f32(Vec2F32 v, F32 s) {Vec2F32 c = {v.x*s, v.y*s}; return c;} internal F32 dot_2f32(Vec2F32 a, Vec2F32 b) {F32 c = a.x*b.x + a.y*b.y; return c;} internal F32 length_squared_2f32(Vec2F32 v) {F32 c = v.x*v.x + v.y*v.y; return c;} internal F32 length_2f32(Vec2F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y); return c;} internal Vec2F32 normalize_2f32(Vec2F32 v) {v = scale_2f32(v, 1.f/length_2f32(v)); return v;} internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t) {Vec2F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t)}; return c;} internal Vec2S64 vec_2s64(S64 x, S64 y) {Vec2S64 v = {x, y}; return v;} internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2S64 scale_2s64(Vec2S64 v, S64 s) {Vec2S64 c = {v.x*s, v.y*s}; return c;} internal S64 dot_2s64(Vec2S64 a, Vec2S64 b) {S64 c = a.x*b.x + a.y*b.y; return c;} internal S64 length_squared_2s64(Vec2S64 v) {S64 c = v.x*v.x + v.y*v.y; return c;} internal S64 length_2s64(Vec2S64 v) {S64 c = (S64)sqrt_f64((F64)(v.x*v.x + v.y*v.y)); return c;} internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t) {Vec2S64 c = {(S64)mix_1f32((F32)a.x, (F32)b.x, t), (S64)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec2S32 vec_2s32(S32 x, S32 y) {Vec2S32 v = {x, y}; return v;} internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2S32 scale_2s32(Vec2S32 v, S32 s) {Vec2S32 c = {v.x*s, v.y*s}; return c;} internal S32 dot_2s32(Vec2S32 a, Vec2S32 b) {S32 c = a.x*b.x + a.y*b.y; return c;} internal S32 length_squared_2s32(Vec2S32 v) {S32 c = v.x*v.x + v.y*v.y; return c;} internal S32 length_2s32(Vec2S32 v) {S32 c = (S32)sqrt_f32((F32)v.x*(F32)v.x + (F32)v.y*(F32)v.y); return c;} internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t) {Vec2S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec2S16 vec_2s16(S16 x, S16 y) {Vec2S16 v = {x, y}; return v;} internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x+b.x), (S16)(a.y+b.y)}; return c;} internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x-b.x), (S16)(a.y-b.y)}; return c;} internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x*b.x), (S16)(a.y*b.y)}; return c;} internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x/b.x), (S16)(a.y/b.y)}; return c;} internal Vec2S16 scale_2s16(Vec2S16 v, S16 s) {Vec2S16 c = {(S16)(v.x*s), (S16)(v.y*s)}; return c;} internal S16 dot_2s16(Vec2S16 a, Vec2S16 b) {S16 c = a.x*b.x + a.y*b.y; return c;} internal S16 length_squared_2s16(Vec2S16 v) {S16 c = v.x*v.x + v.y*v.y; return c;} internal S16 length_2s16(Vec2S16 v) {S16 c = (S16)sqrt_f32((F32)(v.x*v.x + v.y*v.y)); return c;} internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t) {Vec2S16 c = {(S16)mix_1f32((F32)a.x, (F32)b.x, t), (S16)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z) {Vec3F32 v = {x, y, z}; return v;} internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} internal Vec3F32 scale_3f32(Vec3F32 v, F32 s) {Vec3F32 c = {v.x*s, v.y*s, v.z*s}; return c;} internal F32 dot_3f32(Vec3F32 a, Vec3F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} internal F32 length_squared_3f32(Vec3F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z); return c;} internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;} internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;} internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} internal Vec3F32 xform_3f32(Vec3F32 v, Mat3x3F32 m) { Vec3F32 result; result.x = v.x*m.v[0][0] + v.y*m.v[1][0] + v.z*m.v[2][0]; result.y = v.x*m.v[0][1] + v.y*m.v[1][1] + v.z*m.v[2][1]; result.z = v.x*m.v[0][2] + v.y*m.v[1][2] + v.z*m.v[2][2]; return result; } internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;} internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} internal Vec3S32 scale_3s32(Vec3S32 v, S32 s) {Vec3S32 c = {v.x*s, v.y*s, v.z*s}; return c;} internal S32 dot_3s32(Vec3S32 a, Vec3S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} internal S32 length_squared_3s32(Vec3S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} internal S32 length_3s32(Vec3S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z)); return c;} internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t) {Vec3S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t)}; return c;} internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w) {Vec4F32 v = {x, y, z, w}; return v;} internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} internal Vec4F32 scale_4f32(Vec4F32 v, F32 s) {Vec4F32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} internal F32 dot_4f32(Vec4F32 a, Vec4F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} internal F32 length_squared_4f32(Vec4F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} internal F32 length_4f32(Vec4F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); return c;} internal Vec4F32 normalize_4f32(Vec4F32 v) {v = scale_4f32(v, 1.f/length_4f32(v)); return v;} internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t) {Vec4F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t), mix_1f32(a.w, b.w, t)}; return c;} internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w) {Vec4S32 v = {x, y, z, w}; return v;} internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} internal Vec4S32 scale_4s32(Vec4S32 v, S32 s) {Vec4S32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} internal S32 dot_4s32(Vec4S32 a, Vec4S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} internal S32 length_squared_4s32(Vec4S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} internal S32 length_4s32(Vec4S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)); return c;} internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t) {Vec4S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t), (S32)mix_1f32((F32)a.w, (F32)b.w, t)}; return c;} //////////////////////////////// //~ rjf: Matrix Ops internal Mat3x3F32 mat_3x3f32(F32 diagonal) { Mat3x3F32 result = {0}; result.v[0][0] = diagonal; result.v[1][1] = diagonal; result.v[2][2] = diagonal; return result; } internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta) { Mat3x3F32 mat = mat_3x3f32(1.f); mat.v[2][0] = delta.x; mat.v[2][1] = delta.y; return mat; } internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale) { Mat3x3F32 mat = mat_3x3f32(1.f); mat.v[0][0] = scale.x; mat.v[1][1] = scale.y; return mat; } internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b) { Mat3x3F32 c = {0}; for(int j = 0; j < 3; j += 1) { for(int i = 0; i < 3; i += 1) { c.v[i][j] = (a.v[0][j]*b.v[i][0] + a.v[1][j]*b.v[i][1] + a.v[2][j]*b.v[i][2]); } } return c; } internal Mat4x4F32 mat_4x4f32(F32 diagonal) { Mat4x4F32 result = {0}; result.v[0][0] = diagonal; result.v[1][1] = diagonal; result.v[2][2] = diagonal; result.v[3][3] = diagonal; return result; } internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[3][0] = delta.x; result.v[3][1] = delta.y; result.v[3][2] = delta.z; return result; } internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[0][0] = scale.x; result.v[1][1] = scale.y; result.v[2][2] = scale.z; return result; } internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z) { Mat4x4F32 result = mat_4x4f32(1.f); F32 tan_theta_over_2 = tan_f32(fov / 2); result.v[0][0] = 1.f / tan_theta_over_2; result.v[1][1] = aspect_ratio / tan_theta_over_2; result.v[2][3] = 1.f; result.v[2][2] = -(near_z + far_z) / (near_z - far_z); result.v[3][2] = (2.f * near_z * far_z) / (near_z - far_z); result.v[3][3] = 0.f; return result; } internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[0][0] = 2.f / (right - left); result.v[1][1] = 2.f / (top - bottom); result.v[2][2] = 2.f / (far_z - near_z); result.v[3][3] = 1.f; result.v[3][0] = (left + right) / (left - right); result.v[3][1] = (bottom + top) / (bottom - top); result.v[3][2] = (near_z + far_z) / (near_z - far_z); return result; } internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up) { Mat4x4F32 result; Vec3F32 f = normalize_3f32(sub_3f32(eye, center)); Vec3F32 s = normalize_3f32(cross_3f32(f, up)); Vec3F32 u = cross_3f32(s, f); result.v[0][0] = s.x; result.v[0][1] = u.x; result.v[0][2] = -f.x; result.v[0][3] = 0.0f; result.v[1][0] = s.y; result.v[1][1] = u.y; result.v[1][2] = -f.y; result.v[1][3] = 0.0f; result.v[2][0] = s.z; result.v[2][1] = u.z; result.v[2][2] = -f.z; result.v[2][3] = 0.0f; result.v[3][0] = -dot_3f32(s, eye); result.v[3][1] = -dot_3f32(u, eye); result.v[3][2] = dot_3f32(f, eye); result.v[3][3] = 1.0f; return result; } internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns) { Mat4x4F32 result = mat_4x4f32(1.f); axis = normalize_3f32(axis); F32 sin_theta = sin_f32(turns); F32 cos_theta = cos_f32(turns); F32 cos_value = 1.f - cos_theta; result.v[0][0] = (axis.x * axis.x * cos_value) + cos_theta; result.v[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta); result.v[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta); result.v[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta); result.v[1][1] = (axis.y * axis.y * cos_value) + cos_theta; result.v[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta); result.v[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta); result.v[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta); result.v[2][2] = (axis.z * axis.z * cos_value) + cos_theta; return result; } internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b) { Mat4x4F32 c = {0}; for(int j = 0; j < 4; j += 1) { for(int i = 0; i < 4; i += 1) { c.v[i][j] = (a.v[0][j]*b.v[i][0] + a.v[1][j]*b.v[i][1] + a.v[2][j]*b.v[i][2] + a.v[3][j]*b.v[i][3]); } } return c; } internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale) { for(int j = 0; j < 4; j += 1) { for(int i = 0; i < 4; i += 1) { m.v[i][j] *= scale; } } return m; } internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m) { F32 coef00 = m.v[2][2] * m.v[3][3] - m.v[3][2] * m.v[2][3]; F32 coef02 = m.v[1][2] * m.v[3][3] - m.v[3][2] * m.v[1][3]; F32 coef03 = m.v[1][2] * m.v[2][3] - m.v[2][2] * m.v[1][3]; F32 coef04 = m.v[2][1] * m.v[3][3] - m.v[3][1] * m.v[2][3]; F32 coef06 = m.v[1][1] * m.v[3][3] - m.v[3][1] * m.v[1][3]; F32 coef07 = m.v[1][1] * m.v[2][3] - m.v[2][1] * m.v[1][3]; F32 coef08 = m.v[2][1] * m.v[3][2] - m.v[3][1] * m.v[2][2]; F32 coef10 = m.v[1][1] * m.v[3][2] - m.v[3][1] * m.v[1][2]; F32 coef11 = m.v[1][1] * m.v[2][2] - m.v[2][1] * m.v[1][2]; F32 coef12 = m.v[2][0] * m.v[3][3] - m.v[3][0] * m.v[2][3]; F32 coef14 = m.v[1][0] * m.v[3][3] - m.v[3][0] * m.v[1][3]; F32 coef15 = m.v[1][0] * m.v[2][3] - m.v[2][0] * m.v[1][3]; F32 coef16 = m.v[2][0] * m.v[3][2] - m.v[3][0] * m.v[2][2]; F32 coef18 = m.v[1][0] * m.v[3][2] - m.v[3][0] * m.v[1][2]; F32 coef19 = m.v[1][0] * m.v[2][2] - m.v[2][0] * m.v[1][2]; F32 coef20 = m.v[2][0] * m.v[3][1] - m.v[3][0] * m.v[2][1]; F32 coef22 = m.v[1][0] * m.v[3][1] - m.v[3][0] * m.v[1][1]; F32 coef23 = m.v[1][0] * m.v[2][1] - m.v[2][0] * m.v[1][1]; Vec4F32 fac0 = { coef00, coef00, coef02, coef03 }; Vec4F32 fac1 = { coef04, coef04, coef06, coef07 }; Vec4F32 fac2 = { coef08, coef08, coef10, coef11 }; Vec4F32 fac3 = { coef12, coef12, coef14, coef15 }; Vec4F32 fac4 = { coef16, coef16, coef18, coef19 }; Vec4F32 fac5 = { coef20, coef20, coef22, coef23 }; Vec4F32 vec0 = { m.v[1][0], m.v[0][0], m.v[0][0], m.v[0][0] }; Vec4F32 vec1 = { m.v[1][1], m.v[0][1], m.v[0][1], m.v[0][1] }; Vec4F32 vec2 = { m.v[1][2], m.v[0][2], m.v[0][2], m.v[0][2] }; Vec4F32 vec3 = { m.v[1][3], m.v[0][3], m.v[0][3], m.v[0][3] }; Vec4F32 inv0 = add_4f32(sub_4f32(mul_4f32(vec1, fac0), mul_4f32(vec2, fac1)), mul_4f32(vec3, fac2)); Vec4F32 inv1 = add_4f32(sub_4f32(mul_4f32(vec0, fac0), mul_4f32(vec2, fac3)), mul_4f32(vec3, fac4)); Vec4F32 inv2 = add_4f32(sub_4f32(mul_4f32(vec0, fac1), mul_4f32(vec1, fac3)), mul_4f32(vec3, fac5)); Vec4F32 inv3 = add_4f32(sub_4f32(mul_4f32(vec0, fac2), mul_4f32(vec1, fac4)), mul_4f32(vec2, fac5)); Vec4F32 sign_a = { +1, -1, +1, -1 }; Vec4F32 sign_b = { -1, +1, -1, +1 }; Mat4x4F32 inverse; for(U32 i = 0; i < 4; i += 1) { inverse.v[0][i] = inv0.v[i] * sign_a.v[i]; inverse.v[1][i] = inv1.v[i] * sign_b.v[i]; inverse.v[2][i] = inv2.v[i] * sign_a.v[i]; inverse.v[3][i] = inv3.v[i] * sign_b.v[i]; } Vec4F32 row0 = { inverse.v[0][0], inverse.v[1][0], inverse.v[2][0], inverse.v[3][0] }; Vec4F32 m0 = { m.v[0][0], m.v[0][1], m.v[0][2], m.v[0][3] }; Vec4F32 dot0 = mul_4f32(m0, row0); F32 dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w); F32 one_over_det = 1 / dot1; return scale_4x4f32(inverse, one_over_det); } internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat) { Vec3F32 scale = { length_3f32(v3f32(mat.v[0][0], mat.v[0][1], mat.v[0][2])), length_3f32(v3f32(mat.v[1][0], mat.v[1][1], mat.v[1][2])), length_3f32(v3f32(mat.v[2][0], mat.v[2][1], mat.v[2][2])), }; mat.v[0][0] = scale.x; mat.v[1][0] = 0.f; mat.v[2][0] = 0.f; mat.v[0][1] = 0.f; mat.v[1][1] = scale.y; mat.v[2][1] = 0.f; mat.v[0][2] = 0.f; mat.v[1][2] = 0.f; mat.v[2][2] = scale.z; return mat; } internal Mat4x4F32 transpose_4x4f32(Mat4x4F32 mat) { Mat4x4F32 result = { { mat.v[0][0], mat.v[1][0], mat.v[2][0], mat.v[3][0], mat.v[0][1], mat.v[1][1], mat.v[2][1], mat.v[3][1], mat.v[0][2], mat.v[1][2], mat.v[2][2], mat.v[3][2], mat.v[0][3], mat.v[1][3], mat.v[2][3], mat.v[3][3], } }; return result; } //////////////////////////////// //~ rjf: Range Ops internal Rng1U32 rng_1u32(U32 min, U32 max) {Rng1U32 r = {min, max}; if(r.min > r.max) { Swap(U32, r.min, r.max); } return r;} internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.max += x; return r;} internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;} internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;} internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal U32 dim_1u32(Rng1U32 r) {U32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1S32 rng_1s32(S32 min, S32 max) {Rng1S32 r = {min, max}; if(r.min > r.max) { Swap(S32, r.min, r.max); } return r;} internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.max += x; return r;} internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;} internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;} internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal S32 dim_1s32(Rng1S32 r) {S32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1U64 rng_1u64(U64 min, U64 max) {Rng1U64 r = {min, max}; if(r.min > r.max) { Swap(U64, r.min, r.max); } return r;} internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.max += x; return r;} internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;} internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;} internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;} internal U64 dim_1u64(Rng1U64 r) {U64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1S64 rng_1s64(S64 min, S64 max) {Rng1S64 r = {min, max}; if(r.min > r.max) { Swap(S64, r.min, r.max); } return r;} internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.max += x; return r;} internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;} internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;} internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;} internal S64 dim_1s64(Rng1S64 r) {S64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1F32 rng_1f32(F32 min, F32 max) {Rng1F32 r = {min, max}; if(r.min > r.max) { Swap(F32, r.min, r.max); } return r;} internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.max += x; return r;} internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;} internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;} internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal F32 dim_1f32(Rng1F32 r) {F32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max) {Rng2S16 r = {min, max}; return r;} internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s16(r.min, x); r.max = add_2s16(r.max, x); return r;} internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;} internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;} internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0)), (S16)(((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0))}; return dim;} internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max) {Rng2S32 r = {min, max}; return r;} internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s32(r.min, x); r.max = add_2s32(r.max, x); return r;} internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;} internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max) {Rng2S64 r = {min, max}; return r;} internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s64(r.min, x); r.max = add_2s64(r.max, x); return r;} internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;} internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max) {Rng2F32 r = {min, max}; return r;} internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f32(r.min, x); r.max = add_2f32(r.max, x); return r;} internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;} internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} //////////////////////////////// //~ rjf: Color Operations //- rjf: hsv <-> rgb internal Vec3F32 hsv_from_rgb(Vec3F32 rgb) { F32 c_max = Max(rgb.x, Max(rgb.y, rgb.z)); F32 c_min = Min(rgb.x, Min(rgb.y, rgb.z)); F32 delta = c_max - c_min; F32 h = ((delta == 0.f) ? 0.f : (c_max == rgb.x) ? mod_f32((rgb.y - rgb.z)/delta + 6.f, 6.f) : (c_max == rgb.y) ? (rgb.z - rgb.x)/delta + 2.f : (c_max == rgb.z) ? (rgb.x - rgb.y)/delta + 4.f : 0.f); F32 s = (c_max == 0.f) ? 0.f : (delta/c_max); F32 v = c_max; Vec3F32 hsv = {h/6.f, s, v}; return hsv; } internal Vec3F32 rgb_from_hsv(Vec3F32 hsv) { F32 h = mod_f32(hsv.x * 360.f, 360.f); F32 s = hsv.y; F32 v = hsv.z; F32 c = v*s; F32 x = c*(1.f - abs_f32(mod_f32(h/60.f, 2.f) - 1.f)); F32 m = v - c; F32 r = 0; F32 g = 0; F32 b = 0; if ((h >= 0.f && h < 60.f) || (h >= 360.f && h < 420.f)){ r = c; g = x; b = 0; } else if (h >= 60.f && h < 120.f){ r = x; g = c; b = 0; } else if (h >= 120.f && h < 180.f){ r = 0; g = c; b = x; } else if (h >= 180.f && h < 240.f){ r = 0; g = x; b = c; } else if (h >= 240.f && h < 300.f){ r = x; g = 0; b = c; } else if ((h >= 300.f && h <= 360.f) || (h >= -60.f && h <= 0.f)){ r = c; g = 0; b = x; } Vec3F32 rgb = {r + m, g + m, b + m}; return(rgb); } internal Vec4F32 hsva_from_rgba(Vec4F32 rgba) { Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z); Vec3F32 hsv = hsv_from_rgb(rgb); Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w); return hsva; } internal Vec4F32 rgba_from_hsva(Vec4F32 hsva) { Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); Vec3F32 rgb = rgb_from_hsv(hsv); Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w); return rgba; } //- rjf: srgb <-> linear internal Vec3F32 linear_from_srgb(Vec3F32 srgb) { Vec3F32 result; for EachElement(idx, srgb.v) { result.v[idx] = (srgb.v[idx] < 0.0404482362771082f ? srgb.v[idx] / 12.92f : pow_f32((srgb.v[idx] + 0.055f) / 1.055f, 2.4f)); } return result; } internal Vec3F32 srgb_from_linear(Vec3F32 linear) { Vec3F32 result; for EachElement(idx, linear.v) { result.v[idx] = (0 <= linear.v[idx] && linear.v[idx] < 0.00313066844250063) ? linear.v[idx]*12.92f : 1.05f * pow_f32(linear.v[idx], 1.f/2.4f) - 0.055f; } return result; } internal Vec4F32 linear_from_srgba(Vec4F32 srgba) { Vec4F32 result; result.xyz = linear_from_srgb(srgba.xyz); result.w = srgba.w; return result; } internal Vec4F32 srgba_from_linear(Vec4F32 linear) { Vec4F32 result; result.xyz = srgb_from_linear(linear.xyz); result.w = linear.w; return result; } //- rjf: oklab <-> linear internal Vec3F32 oklab_from_linear(Vec3F32 linear) { F32 l = (0.4122214708f * linear.x + 0.5363325363f * linear.y + 0.0514459929f * linear.z); F32 m = (0.2119034982f * linear.x + 0.6806995451f * linear.y + 0.1073969566f * linear.z); F32 s = (0.0883024619f * linear.x + 0.2817188376f * linear.y + 0.6299787005f * linear.z); F32 l_ = cbrt_f32(l); F32 m_ = cbrt_f32(m); F32 s_ = cbrt_f32(s); Vec3F32 result; result.x = 0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_; result.y = 1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_; result.z = 0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_; return result; } internal Vec3F32 linear_from_oklab(Vec3F32 oklab) { F32 l_ = oklab.x + 0.3963377774f * oklab.y + 0.2158037573f * oklab.z; F32 m_ = oklab.x - 0.1055613458f * oklab.y - 0.0638541728f * oklab.z; F32 s_ = oklab.x - 0.0894841775f * oklab.y - 1.2914855480f * oklab.z; F32 l = l_*l_*l_; F32 m = m_*m_*m_; F32 s = s_*s_*s_; Vec3F32 result; result.x = +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s; result.y = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s; result.z = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s; return result; } internal Vec4F32 oklab_from_lineara(Vec4F32 lineara) { Vec4F32 result; result.xyz = oklab_from_linear(lineara.xyz); result.w = lineara.w; return result; } internal Vec4F32 lineara_from_oklab(Vec4F32 oklab) { Vec4F32 result; result.xyz = linear_from_oklab(oklab.xyz); result.w = oklab.w; return result; } //- rjf: rgba <-> u32 internal U32 u32_from_rgba(Vec4F32 rgba) { U32 result = 0; result |= ((U32)((U8)(rgba.x*255.f))) << 24; result |= ((U32)((U8)(rgba.y*255.f))) << 16; result |= ((U32)((U8)(rgba.z*255.f))) << 8; result |= ((U32)((U8)(rgba.w*255.f))) << 0; return result; } internal Vec4F32 rgba_from_u32(U32 hex) { Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f, ((hex&0x00ff0000)>>16)/255.f, ((hex&0x0000ff00)>> 8)/255.f, ((hex&0x000000ff)>> 0)/255.f); return result; } //////////////////////////////// //~ rjf: List Type Functions internal void rng1u64_list_push_node(Rng1U64List *list, Rng1U64Node *n) { SLLQueuePush(list->first, list->last, n); list->count += 1; } internal Rng1U64Node * rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng) { Rng1U64Node *n = push_array(arena, Rng1U64Node, 1); MemoryCopyStruct(&n->v, &rng); rng1u64_list_push_node(list, n); return n; } internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat) { if(to_concat->first) { if(list->first) { list->last->next = to_concat->first; list->last = to_concat->last; } else { list->first = to_concat->first; list->last = to_concat->last; } MemoryZeroStruct(to_concat); } } internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list) { Rng1U64Array arr = {0}; arr.count = list->count; arr.v = push_array_no_zero(arena, Rng1U64, arr.count); U64 idx = 0; for(Rng1U64Node *n = list->first; n != 0; n = n->next) { arr.v[idx] = n->v; idx += 1; } return arr; } internal U64 rng_1u64_array_bsearch(Rng1U64Array arr, U64 value) { if(arr.count > 0 && arr.v[0].min < value && value < arr.v[arr.count-1].max) { U64 l = 0; U64 r = arr.count - 1; for(; l <= r; ) { U64 m = l + (r - l) / 2; if(contains_1u64(arr.v[m], value)) { return m; } else if(arr.v[m].min < value) { l = m + 1; } else { r = m - 1; } } } else if(arr.count == 1 && contains_1u64(arr.v[0], value)) { return 0; } return max_U64; } internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng) { Rng1S64Node *n = push_array(arena, Rng1S64Node, 1); MemoryCopyStruct(&n->v, &rng); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list) { Rng1S64Array arr = {0}; arr.count = list->count; arr.v = push_array_no_zero(arena, Rng1S64, arr.count); U64 idx = 0; for(Rng1S64Node *n = list->first; n != 0; n = n->next) { arr.v[idx] = n->v; idx += 1; } return arr; } //////////////////////////////// //~ rjf: N -> M Element Subdivision internal Rng1U64 m_range_from_n_idx_m_count(U64 n_idx, U64 n_count, U64 m_count) { U64 main_idxes_per_lane = m_count/n_count; U64 leftover_idxes_count = m_count - main_idxes_per_lane*n_count; U64 leftover_idxes_before_this_lane_count = Min(n_idx, leftover_idxes_count); U64 lane_base_idx = n_idx*main_idxes_per_lane + leftover_idxes_before_this_lane_count; U64 lane_base_idx__clamped = Min(lane_base_idx, m_count); U64 lane_opl_idx = lane_base_idx__clamped + main_idxes_per_lane + ((n_idx < leftover_idxes_count) ? 1 : 0); U64 lane_opl_idx__clamped = Min(lane_opl_idx, m_count); Rng1U64 result = r1u64(lane_base_idx__clamped, lane_opl_idx__clamped); return result; } ================================================ FILE: src/base/base_math.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MATH_H #define BASE_MATH_H //////////////////////////////// //~ rjf: Vector Types //- rjf: 2-vectors typedef union Vec2F32 Vec2F32; union Vec2F32 { struct { F32 x; F32 y; }; F32 v[2]; }; typedef union Vec2S64 Vec2S64; union Vec2S64 { struct { S64 x; S64 y; }; S64 v[2]; }; typedef union Vec2S32 Vec2S32; union Vec2S32 { struct { S32 x; S32 y; }; S32 v[2]; }; typedef union Vec2S16 Vec2S16; union Vec2S16 { struct { S16 x; S16 y; }; S16 v[2]; }; //- rjf: 3-vectors typedef union Vec3F32 Vec3F32; union Vec3F32 { struct { F32 x; F32 y; F32 z; }; struct { Vec2F32 xy; F32 _z0; }; struct { F32 _x0; Vec2F32 yz; }; F32 v[3]; }; typedef union Vec3S32 Vec3S32; union Vec3S32 { struct { S32 x; S32 y; S32 z; }; struct { Vec2S32 xy; S32 _z0; }; struct { S32 _x0; Vec2S32 yz; }; S32 v[3]; }; //- rjf: 4-vectors typedef union Vec4F32 Vec4F32; union Vec4F32 { struct { F32 x; F32 y; F32 z; F32 w; }; struct { Vec2F32 xy; Vec2F32 zw; }; struct { Vec3F32 xyz; F32 _z0; }; struct { F32 _x0; Vec3F32 yzw; }; F32 v[4]; }; typedef union Vec4S32 Vec4S32; union Vec4S32 { struct { S32 x; S32 y; S32 z; S32 w; }; struct { Vec2S32 xy; Vec2S32 zw; }; struct { Vec3S32 xyz; S32 _z0; }; struct { S32 _x0; Vec3S32 yzw; }; S32 v[4]; }; //////////////////////////////// //~ rjf: Matrix Types typedef struct Mat3x3F32 Mat3x3F32; struct Mat3x3F32 { F32 v[3][3]; }; typedef struct Mat4x4F32 Mat4x4F32; struct Mat4x4F32 { F32 v[4][4]; }; //////////////////////////////// //~ rjf: Range Types //- rjf: 1-range typedef union Rng1U32 Rng1U32; union Rng1U32 { struct { U32 min; U32 max; }; U32 v[2]; }; typedef union Rng1S32 Rng1S32; union Rng1S32 { struct { S32 min; S32 max; }; S32 v[2]; }; typedef union Rng1U64 Rng1U64; union Rng1U64 { struct { U64 min; U64 max; }; U64 v[2]; }; typedef union Rng1S64 Rng1S64; union Rng1S64 { struct { S64 min; S64 max; }; S64 v[2]; }; typedef union Rng1F32 Rng1F32; union Rng1F32 { struct { F32 min; F32 max; }; F32 v[2]; }; //- rjf: 2-range (rectangles) typedef union Rng2S16 Rng2S16; union Rng2S16 { struct { Vec2S16 min; Vec2S16 max; }; struct { Vec2S16 p0; Vec2S16 p1; }; struct { S16 x0; S16 y0; S16 x1; S16 y1; }; Vec2S16 v[2]; }; typedef union Rng2S32 Rng2S32; union Rng2S32 { struct { Vec2S32 min; Vec2S32 max; }; struct { Vec2S32 p0; Vec2S32 p1; }; struct { S32 x0; S32 y0; S32 x1; S32 y1; }; Vec2S32 v[2]; }; typedef union Rng2F32 Rng2F32; union Rng2F32 { struct { Vec2F32 min; Vec2F32 max; }; struct { Vec2F32 p0; Vec2F32 p1; }; struct { F32 x0; F32 y0; F32 x1; F32 y1; }; Vec2F32 v[2]; }; typedef union Rng2S64 Rng2S64; union Rng2S64 { struct { Vec2S64 min; Vec2S64 max; }; struct { Vec2S64 p0; Vec2S64 p1; }; struct { S64 x0; S64 y0; S64 x1; S64 y1; }; Vec2S64 v[2]; }; //////////////////////////////// //~ rjf: Range List Types typedef struct Rng1U64Node Rng1U64Node; struct Rng1U64Node { Rng1U64Node *next; Rng1U64 v; }; typedef struct Rng1U64List Rng1U64List; struct Rng1U64List { U64 count; Rng1U64Node *first; Rng1U64Node *last; }; typedef struct Rng1U64Array Rng1U64Array; struct Rng1U64Array { Rng1U64 *v; U64 count; }; typedef struct Rng1S64Node Rng1S64Node; struct Rng1S64Node { Rng1S64Node *next; Rng1S64 v; }; typedef struct Rng1S64List Rng1S64List; struct Rng1S64List { Rng1S64Node *first; Rng1S64Node *last; U64 count; }; typedef struct Rng1S64Array Rng1S64Array; struct Rng1S64Array { Rng1S64 *v; U64 count; }; //////////////////////////////// //~ rjf: Scalar Math Ops #define abs_s64(v) (S64)llabs(v) #define sqrt_f32(v) sqrtf(v) #define cbrt_f32(v) cbrtf(v) #define mod_f32(a, b) fmodf((a), (b)) #define pow_f32(b, e) powf((b), (e)) #define ceil_f32(v) ceilf(v) #define floor_f32(v) floorf(v) #define round_f32(v) roundf(v) #define abs_f32(v) fabsf(v) #define radians_from_turns_f32(v) ((v)*(2*3.1415926535897f)) #define turns_from_radians_f32(v) ((v)/(2*3.1415926535897f)) #define degrees_from_turns_f32(v) ((v)*360.f) #define turns_from_degrees_f32(v) ((v)/360.f) #define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v))) #define radians_from_degrees_f32(v) (radians_from_turns_f32(turns_from_degrees_f32(v))) #define sin_f32(v) sinf(radians_from_turns_f32(v)) #define cos_f32(v) cosf(radians_from_turns_f32(v)) #define tan_f32(v) tanf(radians_from_turns_f32(v)) #define sqrt_f64(v) sqrt(v) #define cbrt_f64(v) cbrt(v) #define mod_f64(a, b) fmod((a), (b)) #define pow_f64(b, e) pow((b), (e)) #define ceil_f64(v) ceil(v) #define floor_f64(v) floor(v) #define round_f64(v) round(v) #define abs_f64(v) fabs(v) #define radians_from_turns_f64(v) ((v)*(2*3.1415926535897)) #define turns_from_radians_f64(v) ((v)/(2*3.1415926535897)) #define degrees_from_turns_f64(v) ((v)*360.0) #define turns_from_degrees_f64(v) ((v)/360.0) #define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v))) #define radians_from_degrees_f64(v) (radians_from_turns_f64(turns_from_degrees_f64(v))) #define sin_f64(v) sin(radians_from_turns_f64(v)) #define cos_f64(v) cos(radians_from_turns_f64(v)) #define tan_f64(v) tan(radians_from_turns_f64(v)) internal F32 mix_1f32(F32 a, F32 b, F32 t); internal F64 mix_1f64(F64 a, F64 b, F64 t); //////////////////////////////// //~ rjf: Vector Ops #define v2f32(x, y) vec_2f32((x), (y)) internal Vec2F32 vec_2f32(F32 x, F32 y); internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 scale_2f32(Vec2F32 v, F32 s); internal F32 dot_2f32(Vec2F32 a, Vec2F32 b); internal F32 length_squared_2f32(Vec2F32 v); internal F32 length_2f32(Vec2F32 v); internal Vec2F32 normalize_2f32(Vec2F32 v); internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t); #define v2s64(x, y) vec_2s64((x), (y)) internal Vec2S64 vec_2s64(S64 x, S64 y); internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 scale_2s64(Vec2S64 v, S64 s); internal S64 dot_2s64(Vec2S64 a, Vec2S64 b); internal S64 length_squared_2s64(Vec2S64 v); internal S64 length_2s64(Vec2S64 v); internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t); #define v2s32(x, y) vec_2s32((x), (y)) internal Vec2S32 vec_2s32(S32 x, S32 y); internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 scale_2s32(Vec2S32 v, S32 s); internal S32 dot_2s32(Vec2S32 a, Vec2S32 b); internal S32 length_squared_2s32(Vec2S32 v); internal S32 length_2s32(Vec2S32 v); internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t); #define v2s16(x, y) vec_2s16((x), (y)) internal Vec2S16 vec_2s16(S16 x, S16 y); internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 scale_2s16(Vec2S16 v, S16 s); internal S16 dot_2s16(Vec2S16 a, Vec2S16 b); internal S16 length_squared_2s16(Vec2S16 v); internal S16 length_2s16(Vec2S16 v); internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t); #define v3f32(x, y, z) vec_3f32((x), (y), (z)) internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z); internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 scale_3f32(Vec3F32 v, F32 s); internal F32 dot_3f32(Vec3F32 a, Vec3F32 b); internal F32 length_squared_3f32(Vec3F32 v); internal F32 length_3f32(Vec3F32 v); internal Vec3F32 normalize_3f32(Vec3F32 v); internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t); internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 xform_3f32(Vec3F32 v, Mat3x3F32 m); #define v3s32(x, y, z) vec_3s32((x), (y), (z)) internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z); internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 scale_3s32(Vec3S32 v, S32 s); internal S32 dot_3s32(Vec3S32 a, Vec3S32 b); internal S32 length_squared_3s32(Vec3S32 v); internal S32 length_3s32(Vec3S32 v); internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t); internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b); #define v4f32(x, y, z, w) vec_4f32((x), (y), (z), (w)) internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w); internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 scale_4f32(Vec4F32 v, F32 s); internal F32 dot_4f32(Vec4F32 a, Vec4F32 b); internal F32 length_squared_4f32(Vec4F32 v); internal F32 length_4f32(Vec4F32 v); internal Vec4F32 normalize_4f32(Vec4F32 v); internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t); #define v4s32(x, y, z, w) vec_4s32((x), (y), (z), (w)) internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w); internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 scale_4s32(Vec4S32 v, S32 s); internal S32 dot_4s32(Vec4S32 a, Vec4S32 b); internal S32 length_squared_4s32(Vec4S32 v); internal S32 length_4s32(Vec4S32 v); internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t); //////////////////////////////// //~ rjf: Matrix Ops internal Mat3x3F32 mat_3x3f32(F32 diagonal); internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta); internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale); internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b); internal Mat4x4F32 mat_4x4f32(F32 diagonal); internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta); internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale); internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z); internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z); internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up); internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns); internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b); internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale); internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m); internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat); internal Mat4x4F32 transpose_4x4f32(Mat4x4F32 mat); //////////////////////////////// //~ rjf: Range Ops #define r1u32(min, max) rng_1u32((min), (max)) internal Rng1U32 rng_1u32(U32 min, U32 max); internal Rng1U32 shift_1u32(Rng1U32 r, U32 x); internal Rng1U32 pad_1u32(Rng1U32 r, U32 x); internal U32 center_1u32(Rng1U32 r); internal B32 contains_1u32(Rng1U32 r, U32 x); internal U32 dim_1u32(Rng1U32 r); internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b); internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b); internal U32 clamp_1u32(Rng1U32 r, U32 v); #define r1s32(min, max) rng_1s32((min), (max)) internal Rng1S32 rng_1s32(S32 min, S32 max); internal Rng1S32 shift_1s32(Rng1S32 r, S32 x); internal Rng1S32 pad_1s32(Rng1S32 r, S32 x); internal S32 center_1s32(Rng1S32 r); internal B32 contains_1s32(Rng1S32 r, S32 x); internal S32 dim_1s32(Rng1S32 r); internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b); internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b); internal S32 clamp_1s32(Rng1S32 r, S32 v); #define r1u64(min, max) rng_1u64((min), (max)) internal Rng1U64 rng_1u64(U64 min, U64 max); internal Rng1U64 shift_1u64(Rng1U64 r, U64 x); internal Rng1U64 pad_1u64(Rng1U64 r, U64 x); internal U64 center_1u64(Rng1U64 r); internal B32 contains_1u64(Rng1U64 r, U64 x); internal U64 dim_1u64(Rng1U64 r); internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b); internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b); internal U64 clamp_1u64(Rng1U64 r, U64 v); #define r1s64(min, max) rng_1s64((min), (max)) internal Rng1S64 rng_1s64(S64 min, S64 max); internal Rng1S64 shift_1s64(Rng1S64 r, S64 x); internal Rng1S64 pad_1s64(Rng1S64 r, S64 x); internal S64 center_1s64(Rng1S64 r); internal B32 contains_1s64(Rng1S64 r, S64 x); internal S64 dim_1s64(Rng1S64 r); internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b); internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b); internal S64 clamp_1s64(Rng1S64 r, S64 v); #define r1f32(min, max) rng_1f32((min), (max)) internal Rng1F32 rng_1f32(F32 min, F32 max); internal Rng1F32 shift_1f32(Rng1F32 r, F32 x); internal Rng1F32 pad_1f32(Rng1F32 r, F32 x); internal F32 center_1f32(Rng1F32 r); internal B32 contains_1f32(Rng1F32 r, F32 x); internal F32 dim_1f32(Rng1F32 r); internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b); internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b); internal F32 clamp_1f32(Rng1F32 r, F32 v); #define r2s16(min, max) rng_2s16((min), (max)) #define r2s16p(x, y, z, w) r2s16(v2s16((x), (y)), v2s16((z), (w))) internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max); internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x); internal Rng2S16 pad_2s16(Rng2S16 r, S16 x); internal Vec2S16 center_2s16(Rng2S16 r); internal B32 contains_2s16(Rng2S16 r, Vec2S16 x); internal Vec2S16 dim_2s16(Rng2S16 r); internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b); internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b); internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v); #define r2s32(min, max) rng_2s32((min), (max)) #define r2s32p(x, y, z, w) r2s32(v2s32((x), (y)), v2s32((z), (w))) internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max); internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x); internal Rng2S32 pad_2s32(Rng2S32 r, S32 x); internal Vec2S32 center_2s32(Rng2S32 r); internal B32 contains_2s32(Rng2S32 r, Vec2S32 x); internal Vec2S32 dim_2s32(Rng2S32 r); internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b); internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b); internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v); #define r2s64(min, max) rng_2s64((min), (max)) #define r2s64p(x, y, z, w) r2s64(v2s64((x), (y)), v2s64((z), (w))) internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max); internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x); internal Rng2S64 pad_2s64(Rng2S64 r, S64 x); internal Vec2S64 center_2s64(Rng2S64 r); internal B32 contains_2s64(Rng2S64 r, Vec2S64 x); internal Vec2S64 dim_2s64(Rng2S64 r); internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b); internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b); internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v); #define r2f32(min, max) rng_2f32((min), (max)) #define r2f32p(x, y, z, w) r2f32(v2f32((x), (y)), v2f32((z), (w))) internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max); internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x); internal Rng2F32 pad_2f32(Rng2F32 r, F32 x); internal Vec2F32 center_2f32(Rng2F32 r); internal B32 contains_2f32(Rng2F32 r, Vec2F32 x); internal Vec2F32 dim_2f32(Rng2F32 r); internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b); internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b); internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v); //////////////////////////////// //~ rjf: Color Operations //- rjf: hsv <-> rgb internal Vec3F32 hsv_from_rgb(Vec3F32 rgb); internal Vec3F32 rgb_from_hsv(Vec3F32 hsv); internal Vec4F32 hsva_from_rgba(Vec4F32 rgba); internal Vec4F32 rgba_from_hsva(Vec4F32 hsva); //- rjf: srgb <-> linear internal Vec3F32 linear_from_srgb(Vec3F32 srgb); internal Vec3F32 srgb_from_linear(Vec3F32 linear); internal Vec4F32 linear_from_srgba(Vec4F32 srgba); internal Vec4F32 srgba_from_linear(Vec4F32 linear); //- rjf: oklab <-> linear internal Vec3F32 oklab_from_linear(Vec3F32 linear); internal Vec3F32 linear_from_oklab(Vec3F32 oklab); internal Vec4F32 oklab_from_lineara(Vec4F32 lineara); internal Vec4F32 lineara_from_oklab(Vec4F32 oklab); //- rjf: rgba <-> u32 internal U32 u32_from_rgba(Vec4F32 rgba); internal Vec4F32 rgba_from_u32(U32 hex); #define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f } //////////////////////////////// //~ rjf: List Type Functions internal void rng1u64_list_push_node(Rng1U64List *list, Rng1U64Node *n); internal Rng1U64Node * rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng); internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat); internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list); internal U64 rng_1u64_array_bsearch(Rng1U64Array arr, U64 value); internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng); internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list); //////////////////////////////// //~ rjf: N -> M Element Subdivision internal Rng1U64 m_range_from_n_idx_m_count(U64 n_idx, U64 n_count, U64 m_count); #endif //BASE_MATH_H ================================================ FILE: src/base/base_meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Type Info Lookups internal Member * member_from_name(Type *type, String8 name) { Member *member = &member_nil; if(type->members != 0 && name.size != 0) { for(U64 idx = 0; idx < type->count; idx += 1) { if(str8_match(type->members[idx].name, name, 0)) { member = &type->members[idx]; break; } } } return member; } //////////////////////////////// //~ rjf: Type Info * Instance Operations internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr) { Temp scratch = scratch_begin(0, 0); typedef struct RebaseTypeTask RebaseTypeTask; struct RebaseTypeTask { RebaseTypeTask *next; Type *type; U8 *ptr; }; RebaseTypeTask start_task = {0, type, data.str}; RebaseTypeTask *first_task = &start_task; RebaseTypeTask *last_task = first_task; for(RebaseTypeTask *t = first_task; t != 0; t = t->next) { switch(t->type->kind) { default:{}break; case TypeKind_Ptr: { *(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr)); }break; case TypeKind_Array: { for(U64 idx = 0; idx < t->type->count; idx += 1) { RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); task->type = t->type->direct; task->ptr = t->ptr + t->type->direct->size * idx; SLLQueuePush(first_task, last_task, task); } }break; case TypeKind_Struct: { for(U64 idx = 0; idx < t->type->count; idx += 1) { Member *member = &t->type->members[idx]; RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); task->type = member->type; task->ptr = t->ptr + member->value; SLLQueuePush(first_task, last_task, task); } }break; } } scratch_end(scratch); } internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; str8_serial_begin(scratch.arena, &strings); { typedef struct SerializeTypeTask SerializeTypeTask; struct SerializeTypeTask { SerializeTypeTask *next; Type *type; U64 count; U8 *src; Type *containing_type; U8 *containing_ptr; B32 is_post_header; }; SerializeTypeTask start_task = {0, type, 1, data.str}; SerializeTypeTask *first_task = &start_task; SerializeTypeTask *last_task = first_task; for(SerializeTypeTask *t = first_task; t != 0; t = t->next) { switch(t->type->kind) { //- rjf: leaf -> just copy the data directly default: if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) { str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); }break; //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise just write as plain data case TypeKind_Ptr: { // rjf: unpack info about this pointer TypeSerializePtrRefInfo *ptr_ref_info = 0; for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) { if(params->ptr_ref_infos[idx].type == t->type->direct) { ptr_ref_info = ¶ms->ptr_ref_infos[idx]; break; } } // rjf: indexification -> subtract base, divide direct size, write index if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size); str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } // rjf: offsetification -> subtract base, write offsets else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base); str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } // rjf: size-by-member (pre-header): still potentially dependent on other members which // delimit our size, so push a new post-header task for pointer. else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type; task->count = t->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; task->is_post_header = 1; SLLQueuePush(first_task, last_task, task); } // rjf: size-by-member (post-header): all flat parts of containing struct have been // iterated, so now we can read the size, & descend to new task to read pointer // destination contents else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) { // rjf: determine count of this pointer U64 count = 0; { Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); } // rjf: push task SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = count; task->src = *(void **)t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); } // rjf: catch-all: write pointer value else { str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); } }break; //- rjf: arrays -> descend to underlying type, + count case TypeKind_Array: { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = t->type->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; //- rjf: struct -> descend to members case TypeKind_Struct: { U64 off = 0; for(U64 idx = 0; idx < t->count; idx += 1) { for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) { if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) { continue; } SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->members[member_idx].type; task->count = 1; task->src = t->src + idx*t->type->size + t->type->members[member_idx].value; task->containing_type = t->type; task->containing_ptr = t->src; SLLQueuePush(first_task, last_task, task); } } }break; //- rjf: enum -> descend to basic type interpretation case TypeKind_Enum: { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = t->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; } } } String8 result = str8_serial_end(arena, &strings); scratch_end(scratch); return result; } internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { String8 result = {0}; result.size = type->size; result.str = push_array(arena, U8, result.size); { Temp scratch = scratch_begin(&arena, 1); typedef struct DeserializeTypeTask DeserializeTypeTask; struct DeserializeTypeTask { DeserializeTypeTask *next; Type *type; U64 count; U8 *dst; Type *containing_type; U8 *containing_ptr; B32 is_post_header; }; U64 read_off = 0; DeserializeTypeTask start_task = {0, type, 1, result.str}; DeserializeTypeTask *first_task = &start_task; DeserializeTypeTask *last_task = first_task; for(DeserializeTypeTask *t = first_task; t != 0; t = t->next) { U8 *t_src = data.str + read_off; switch(t->type->kind) { //- rjf: leaf -> copy the data directly default: if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) { MemoryCopy(t->dst, t_src, t->type->size*t->count); read_off += t->type->size*t->count; }break; //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip case TypeKind_Ptr: { // rjf: unpack info about this pointer TypeSerializePtrRefInfo *ptr_ref_info = 0; for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) { if(params->ptr_ref_infos[idx].type == t->type->direct) { ptr_ref_info = ¶ms->ptr_ref_infos[idx]; break; } } // rjf: indexification -> add base, multiply direct size if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size; MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); read_off += sizeof(ptr_value); } // rjf: offsetification -> subtract base, write offsets else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base; MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); read_off += sizeof(ptr_value); } // rjf: size-by-member (pre-header): still potentially dependent on other members which // delimit our size, so push a new post-header task for pointer. else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type; task->count = t->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; task->is_post_header = 1; SLLQueuePush(first_task, last_task, task); } // rjf: size-by-member (post-header): all flat parts of containing struct have been // iterated, so now we can read the size, & descend to new task to read pointer // destination contents else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) { // rjf: determine count of this pointer U64 count = 0; { Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); } // rjf: allocate buffer for pointer destination; write address into pointer value slot U64 ptr_dest_buffer_size = (count+1)*t->type->direct->size; U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size); MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer)); // rjf: push task DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = count; task->dst = ptr_dest_buffer; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); } // rjf: catch-all: read pointer value else { MemoryCopy(t->dst, t_src, t->type->size*t->count); read_off += t->type->size*t->count; } }break; //- rjf: arrays -> descend to underlying type, + count case TypeKind_Array: { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = t->type->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; //- rjf: struct -> descend to members case TypeKind_Struct: { for(U64 idx = 0; idx < t->count; idx += 1) { for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) { if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) { continue; } DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->members[member_idx].type; task->count = 1; task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value; task->containing_type = t->type; task->containing_ptr = t->dst; SLLQueuePush(first_task, last_task, task); } } }break; //- rjf: enum -> descend to basic type interpretation case TypeKind_Enum: { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = t->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; } } if(params->advance_out != 0) { params->advance_out[0] = read_off; } scratch_end(scratch); } return result; } internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { Temp scratch = scratch_begin(&arena, 1); String8 data_srlz = serialized_from_typed_data(scratch.arena, type, data, params); String8 data_copy = deserialized_from_typed_data(arena, type, data_srlz, params); scratch_end(scratch); return data_copy; } ================================================ FILE: src/base/base_meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_META_H #define BASE_META_H //////////////////////////////// //~ rjf: Meta Markup Features #define EmbedFile(name, path) #define TweakB32(name, default) (TWEAK_##name) #define TweakF32(name, default, min, max) (TWEAK_##name) //////////////////////////////// //~ rjf: Tweak Info Tables typedef struct TweakB32Info TweakB32Info; struct TweakB32Info { String8 name; B32 default_value; B32 *value_ptr; }; typedef struct TweakF32Info TweakF32Info; struct TweakF32Info { String8 name; F32 default_value; Rng1F32 value_range; F32 *value_ptr; }; typedef struct TweakB32InfoTable TweakB32InfoTable; struct TweakB32InfoTable { TweakB32Info *v; U64 count; }; typedef struct TweakF32InfoTable TweakF32InfoTable; struct TweakF32InfoTable { TweakF32Info *v; U64 count; }; typedef struct EmbedInfo EmbedInfo; struct EmbedInfo { String8 name; String8 *data; U128 *hash; }; typedef struct EmbedInfoTable EmbedInfoTable; struct EmbedInfoTable { EmbedInfo *v; U64 count; }; //////////////////////////////// //~ rjf: Type Info Types typedef enum TypeKind { TypeKind_Null, // rjf: leaves TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void, TypeKind_U8, TypeKind_U16, TypeKind_U32, TypeKind_U64, TypeKind_S8, TypeKind_S16, TypeKind_S32, TypeKind_S64, TypeKind_B8, TypeKind_B16, TypeKind_B32, TypeKind_B64, TypeKind_F32, TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64, // rjf: operators TypeKind_Ptr, TypeKind_Array, // rjf: user-defined-types TypeKind_Struct, TypeKind_Union, TypeKind_Enum, TypeKind_COUNT } TypeKind; typedef U32 TypeFlags; enum { TypeFlag_IsPlainText = (1<<0), TypeFlag_IsCodeText = (1<<1), TypeFlag_IsPathText = (1<<2), }; typedef U32 MemberFlags; enum { MemberFlag_DoNotSerialize = (1<<0), }; typedef struct Type Type; typedef struct Member Member; struct Member { String8 name; String8 pretty_name; Type *type; U64 value; MemberFlags flags; }; typedef struct Type Type; struct Type { TypeKind kind; TypeFlags flags; U64 size; Type *direct; String8 name; String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N] U64 count; Member *members; }; //////////////////////////////// //~ rjf: Type Serialization Parameters typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo; struct TypeSerializePtrRefInfo { Type *type; // pointers to this void *indexify_base; // can be indexified using this void *offsetify_base; // can be offsetified using this void *nil_ptr; // is terminal if matching 0 or this }; typedef struct TypeSerializeParams TypeSerializeParams; struct TypeSerializeParams { U64 *advance_out; TypeSerializePtrRefInfo *ptr_ref_infos; U64 ptr_ref_infos_count; }; //////////////////////////////// //~ rjf: Type Name -> Type Info #define type(T) (&T##__type) //////////////////////////////// //~ rjf: Type Info Table Initializer Helpers #define member_lit_comp(S, ti, m, ...) {str8_lit_comp(#m), {0}, (ti), OffsetOf(S, m), __VA_ARGS__} #define struct_members(S) read_only global Member S##__members[] = #define struct_type(S, ...) read_only global Type S##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#S), {0}, ArrayCount(S##__members), S##__members, __VA_ARGS__} #define named_struct_type(name, S, ...) read_only global Type name##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#name), {0}, ArrayCount(name##__members), name##__members, __VA_ARGS__} #define ptr_type(name, ti, ...) read_only global Type name = {TypeKind_Ptr, 0, sizeof(void *), (ti), __VA_ARGS__} //////////////////////////////// //~ rjf: Globals read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil}; read_only global Member member_nil = {{0}, {0}, &type_nil}; //////////////////////////////// //~ rjf: Built-In Types //- rjf: leaves read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")}; read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")}; read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")}; read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")}; read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")}; read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")}; read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")}; read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")}; read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")}; read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")}; read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")}; read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")}; read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")}; read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")}; read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")}; read_only global Type *type_kind_type_table[] = { &type_nil, type(void), type(U8), type(U16), type(U32), type(U64), type(S8), type(S16), type(S32), type(S64), type(B8), type(B16), type(B32), type(B64), type(F32), type(F64), &type_nil, &type_nil, &type_nil, &type_nil, &type_nil, }; //- rjf: Rng1U64 struct_members(Rng1U64) { member_lit_comp(Rng1U64, type(U64), min), member_lit_comp(Rng1U64, type(U64), max), }; struct_type(Rng1U64); //- rjf: String8 ptr_type(String8__str_ptr_type, type(U8), str8_lit_comp("size")); struct_members(String8) { member_lit_comp(String8, &String8__str_ptr_type, str), member_lit_comp(String8, type(U64), size), }; struct_type(String8); //- rjf: String8Node extern Type String8Node__type; Type String8Node__ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &String8Node__type}; Member String8Node__members[] = { {str8_lit_comp("next"), {0}, &String8Node__ptr_type, OffsetOf(String8Node, next)}, {str8_lit_comp("string"), {0}, type(String8), OffsetOf(String8Node, string)}, }; Type String8Node__type = { TypeKind_Struct, 0, sizeof(String8Node), &type_nil, str8_lit_comp("String8Node"), {0}, ArrayCount(String8Node__members), String8Node__members, }; //- rjf: String8List Member String8List__members[] = { {str8_lit_comp("first"), {0}, &String8Node__ptr_type, OffsetOf(String8List, first)}, {str8_lit_comp("last"), {0}, &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize}, {str8_lit_comp("node_count"), {0}, type(U64), OffsetOf(String8List, node_count)}, {str8_lit_comp("total_size"), {0}, type(U64), OffsetOf(String8List, total_size)}, }; Type String8List__type = { TypeKind_Struct, 0, sizeof(String8List), &type_nil, str8_lit_comp("String8List"), {0}, ArrayCount(String8List__members), String8List__members, }; //////////////////////////////// //~ rjf: Type Info Lookups internal Member *member_from_name(Type *type, String8 name); #define EachMember(T, it) (Member *it = (type(T))->members; it != 0 && it < (type(T))->members + (type(T))->count; it += 1) //////////////////////////////// //~ rjf: Type Info * Instance Operations internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr); internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); #define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base)) #define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) #define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str #define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str #endif // BASE_META_H ================================================ FILE: src/base/base_profile.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #if PROFILE_SPALL internal inline void spall_begin(char *fmt, ...) { if(spall_buffer.data == 0) { spall_buffer.length = MB(1); spall_buffer.data = os_reserve(spall_buffer.length); os_commit(spall_buffer.data, spall_buffer.length); spall_buffer_init(&spall_profile, &spall_buffer); } if(spall_pid == 0) { spall_pid = os_get_process_info()->pid; } if(spall_tid == 0) { spall_tid = os_tid(); } Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); spall_buffer_begin_ex(&spall_profile, &spall_buffer, string.str, string.size, os_now_microseconds(), spall_tid, spall_pid); va_end(args); scratch_end(scratch); } #endif ================================================ FILE: src/base/base_profile.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_PROFILE_H #define BASE_PROFILE_H //////////////////////////////// //~ rjf: Zero Settings #if !defined(PROFILE_TELEMETRY) # define PROFILE_TELEMETRY 0 #endif #if !defined(PROFILE_SPALL) # define PROFILE_SPALL 0 #endif //////////////////////////////// //~ rjf: Third Party Includes #if PROFILE_TELEMETRY # include "rad_tm.h" # if OS_WINDOWS # pragma comment(lib, "ws2_32.lib") # pragma comment(lib, "rad_tm_win64.lib") # endif #elif PROFILE_SPALL # include "spall.h" #endif //////////////////////////////// //~ rjf: Telemetry Profile Defines #if PROFILE_TELEMETRY # define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__) # define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0) # define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0) # define ProfTick(...) tmTick(0) # define ProfIsCapturing(...) tmRunning() # define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100) # define ProfEndCapture(...) tmClose(0) # define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0) # define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0) # define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__) # define ProfEndLockWait(...) tmEndWaitForLock(0) # define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__) # define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__) # define ProfColor(color) tmZoneColor((((color) & 0xff000000) >> 24) / 255.f, (((color) & 0x00ff0000) >> 16) / 255.f, (((color) & 0x0000ff00) >> 8) / 255.f) # define ProfBeginV(...) \ if (TM_API_PTR) { \ static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ Temp scratch = scratch_begin(0,0); \ String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \ scratch_end(scratch); \ } # define ProfNoteV(...) \ if (TM_API_PTR) { \ static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ Temp scratch = scratch_begin(0,0); \ String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \ scratch_end(scratch); \ } #endif //////////////////////////////// //~ rjf: Spall Profile Defines #if PROFILE_SPALL global U64 spall_capturing = 0; global SpallProfile spall_profile = {0}; thread_static SpallBuffer spall_buffer = {0}; thread_static U32 spall_tid = 0; thread_static U32 spall_pid = 0; internal inline void spall_begin(char *fmt, ...); # define ProfBegin(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) # define ProfBeginDynamic(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) # define ProfEnd(...) (spall_capturing ? (spall_buffer_end_ex(&spall_profile, &spall_buffer, os_now_microseconds(), spall_tid, spall_pid)), 0 : 0) # define ProfTick(...) # define ProfIsCapturing(...) (!!spall_capturing) # define ProfBeginCapture(...) (spall_capturing = 1) # define ProfEndCapture(...) (spall_capturing = 0, spall_flush(&spall_profile)) # define ProfThreadName(...) # define ProfMsg(...) # define ProfBeginLockWait(...) # define ProfEndLockWait(...) # define ProfLockTake(...) # define ProfLockDrop(...) # define ProfColor(color) # define ProfBeginV(...) # define ProfNoteV(...) #endif //////////////////////////////// //~ rjf: Zeroify Undefined Defines #if !defined(ProfBegin) # define ProfBegin(...) (0) # define ProfBeginDynamic(...) (0) # define ProfEnd(...) (0) # define ProfTick(...) (0) # define ProfIsCapturing(...) (0) # define ProfBeginCapture(...) (0) # define ProfEndCapture(...) (0) # define ProfThreadName(...) (0) # define ProfMsg(...) (0) # define ProfBeginLockWait(...) (0) # define ProfEndLockWait(...) (0) # define ProfLockTake(...) (0) # define ProfLockDrop(...) (0) # define ProfColor(...) (0) # define ProfBeginV(...) (0) # define ProfNoteV(...) (0) #endif //////////////////////////////// //~ rjf: Helper Wrappers #define ProfBeginFunction(...) ProfBegin(this_function_name) #define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd()) #endif // BASE_PROFILE_H ================================================ FILE: src/base/base_strings.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Character Classification & Conversion Functions internal B32 char_is_space(U8 c) { return (c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v'); } internal B32 char_is_upper(U8 c) { return ('A' <= c && c <= 'Z'); } internal B32 char_is_lower(U8 c) { return ('a' <= c && c <= 'z'); } internal B32 char_is_alpha(U8 c) { return (char_is_upper(c) || char_is_lower(c)); } internal B32 char_is_slash(U8 c) { return (c == '/' || c == '\\'); } internal B32 char_is_digit(U8 c, U32 base) { B32 result = 0; if(0 < base && base <= 16) { U8 val = integer_symbol_reverse[c]; if(val < base) { result = 1; } } return result; } internal U8 lower_from_char(U8 c) { if(char_is_upper(c)) { c += ('a' - 'A'); } return c; } internal U8 upper_from_char(U8 c) { if(char_is_lower(c)) { c += ('A' - 'a'); } return c; } internal U8 correct_slash_from_char(U8 c) { if(char_is_slash(c)) { c = '/'; } return c; } //////////////////////////////// //~ rjf: C-String Measurement internal U64 cstring8_length(U8 *c) { U64 length = 0; if(c) { U8 *p = c; for (;*p != 0; p += 1); length = (U64)(p - c); } return length; } internal U64 cstring16_length(U16 *c) { U64 length = 0; if(c) { U16 *p = c; for (;*p != 0; p += 1); length = (U64)(p - c); } return length; } internal U64 cstring32_length(U32 *c) { U64 length = 0; if(c) { U32 *p = c; for (;*p != 0; p += 1); length = (U64)(p - c); } return length; } //////////////////////////////// //~ rjf: String Constructors internal String8 str8(U8 *str, U64 size) { String8 result = {str, size}; return result; } internal String8 str8_range(U8 *first, U8 *one_past_last) { String8 result = {first, (U64)(one_past_last - first)}; return result; } internal String8 str8_zero(void) { String8 result = {0}; return result; } internal String16 str16(U16 *str, U64 size) { String16 result = {str, size}; return result; } internal String16 str16_range(U16 *first, U16 *one_past_last) { String16 result = {first, (U64)(one_past_last - first)}; return result; } internal String16 str16_zero(void) { String16 result = {0}; return result; } internal String32 str32(U32 *str, U64 size) { String32 result = {str, size}; return result; } internal String32 str32_range(U32 *first, U32 *one_past_last) { String32 result = {first, (U64)(one_past_last - first)}; return result; } internal String32 str32_zero(void) { String32 result = {0}; return result; } internal String8 str8_cstring(char *c) { String8 result = {(U8*)c, cstring8_length((U8*)c)}; return result; } internal String16 str16_cstring(U16 *c) { String16 result = {(U16*)c, cstring16_length((U16*)c)}; return result; } internal String32 str32_cstring(U32 *c) { String32 result = {(U32*)c, cstring32_length((U32*)c)}; return result; } internal String8 str8_cstring_capped(void *cstr, void *cap) { char *ptr = (char *)cstr; char *opl = (char *)cap; for (;ptr < opl && *ptr != 0; ptr += 1); U64 size = (U64)(ptr - (char *)cstr); String8 result = str8((U8*)cstr, size); return result; } internal String16 str16_cstring_capped(void *cstr, void *cap) { U16 *ptr = (U16 *)cstr; U16 *opl = (U16 *)cap; for (;ptr < opl && *ptr != 0; ptr += 1); U64 size = (U64)(ptr - (U16 *)cstr); String16 result = str16(cstr, size); return result; } internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap) { U8 *start = raw_start; U8 *ptr = raw_cap; for(; ptr > start; ) { ptr -= 1; if (*ptr == '\0') { break; } } U64 size = (U64)(ptr - start); String8 result = str8(start, size); return result; } //////////////////////////////// //~ rjf: String Stylization internal String8 upper_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = upper_from_char(string.str[idx]); } return string; } internal String8 lower_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = lower_from_char(string.str[idx]); } return string; } internal String8 backslashed_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = char_is_slash(string.str[idx]) ? '\\' : string.str[idx]; } return string; } //////////////////////////////// //~ rjf: String Matching internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags) { B32 result = 0; if(a.size == b.size && flags == 0) { result = MemoryMatch(a.str, b.str, b.size); } else if(a.size == b.size || (flags & StringMatchFlag_RightSideSloppy)) { B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive); B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive); U64 size = Min(a.size, b.size); result = 1; for(U64 i = 0; i < size; i += 1) { U8 at = a.str[i]; U8 bt = b.str[i]; if(case_insensitive) { at = upper_from_char(at); bt = upper_from_char(bt); } if(slash_insensitive) { at = correct_slash_from_char(at); bt = correct_slash_from_char(bt); } if(at != bt) { result = 0; break; } } } return result; } internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags) { U8 *p = string.str + start_pos; U64 stop_offset = Max(string.size + 1, needle.size) - needle.size; U8 *stop_p = string.str + stop_offset; if(needle.size > 0) { U8 *string_opl = string.str + string.size; String8 needle_tail = str8_skip(needle, 1); StringMatchFlags adjusted_flags = flags | StringMatchFlag_RightSideSloppy; U8 needle_first_char_adjusted = needle.str[0]; if(adjusted_flags & StringMatchFlag_CaseInsensitive) { needle_first_char_adjusted = upper_from_char(needle_first_char_adjusted); } for(;p < stop_p; p += 1) { U8 haystack_char_adjusted = *p; if(adjusted_flags & StringMatchFlag_CaseInsensitive) { haystack_char_adjusted = upper_from_char(haystack_char_adjusted); } if(haystack_char_adjusted == needle_first_char_adjusted) { if(str8_match(str8_range(p + 1, string_opl), needle_tail, adjusted_flags)) { break; } } } } U64 result = string.size; if(p < stop_p) { result = (U64)(p - string.str); } return result; } internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags) { U64 result = 0; for(S64 i = string.size - start_pos - needle.size; i >= 0; --i) { String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size)); if(str8_match(haystack, needle, flags)) { result = (U64)i + needle.size; break; } } return result; } internal B32 str8_is_before(String8 a, String8 b) { B32 result = 0; { U64 common_size = Min(a.size, b.size); for(U64 off = 0; off < common_size; off += 1) { if(a.str[off] < b.str[off]) { result = 1; break; } else if(a.str[off] > b.str[off]) { result = 0; break; } else if(off+1 == common_size) { result = (a.size < b.size); } } } return result; } //////////////////////////////// //~ rjf: String Slicing internal String8 str8_substr(String8 str, Rng1U64 range) { range.min = ClampTop(range.min, str.size); range.max = ClampTop(range.max, str.size); str.str += range.min; str.size = dim_1u64(range); return str; } internal String8 str8_prefix(String8 str, U64 size) { str.size = ClampTop(size, str.size); return str; } internal String8 str8_skip(String8 str, U64 amt) { amt = ClampTop(amt, str.size); str.str += amt; str.size -= amt; return str; } internal String8 str8_postfix(String8 str, U64 size) { size = ClampTop(size, str.size); str.str = (str.str + str.size) - size; str.size = size; return str; } internal String8 str8_chop(String8 str, U64 amt) { amt = ClampTop(amt, str.size); str.size -= amt; return str; } internal String8 str8_skip_chop_whitespace(String8 string) { U8 *first = string.str; U8 *opl = first + string.size; for(;first < opl; first += 1) { if(!char_is_space(*first)) { break; } } for(;opl > first;) { opl -= 1; if(!char_is_space(*opl)) { opl += 1; break; } } String8 result = str8_range(first, opl); return result; } internal String8 str8_skip_chop_slashes(String8 string) { U8 *first = string.str; U8 *opl = first + string.size; for(;first < opl; first += 1) { if(!char_is_slash(*first)) { break; } } for(;opl > first;) { opl -= 1; if(!char_is_slash(*opl)) { opl += 1; break; } } String8 result = str8_range(first, opl); return result; } //////////////////////////////// //~ rjf: String Formatting & Copying internal String8 str8_cat(Arena *arena, String8 s1, String8 s2) { String8 str; str.size = s1.size + s2.size; str.str = push_array_no_zero(arena, U8, str.size + 1); MemoryCopy(str.str, s1.str, s1.size); MemoryCopy(str.str + s1.size, s2.str, s2.size); str.str[str.size] = 0; return str; } internal String8 str8_copy(Arena *arena, String8 s) { String8 str; str.size = s.size; str.str = push_array_no_zero(arena, U8, str.size + 1); MemoryCopy(str.str, s.str, s.size); str.str[str.size] = 0; return str; } internal String8 str8fv(Arena *arena, char *fmt, va_list args){ va_list args2; va_copy(args2, args); U32 needed_bytes = raddbg_vsnprintf(0, 0, fmt, args) + 1; String8 result = {0}; result.str = push_array_no_zero(arena, U8, needed_bytes); result.size = raddbg_vsnprintf((char*)result.str, needed_bytes, fmt, args2); result.str[result.size] = 0; va_end(args2); return result; } internal String8 str8f(Arena *arena, char *fmt, ...) { va_list args; va_start(args, fmt); String8 result = push_str8fv(arena, fmt, args); va_end(args); return result; } internal String8 push_cstr(Arena *arena, String8 str) { U64 buffer_size = str.size + 1; U8 *buffer = push_array_no_zero(arena, U8, buffer_size); MemoryCopy(buffer, str.str, str.size); buffer[str.size] = 0; String8 result = str8(buffer, buffer_size); return result; } //////////////////////////////// //~ rjf: String <=> Integer Conversions //- rjf: string -> integer internal S64 sign_from_str8(String8 string, String8 *string_tail) { // count negative signs U64 neg_count = 0; U64 i = 0; for(; i < string.size; i += 1) { if (string.str[i] == '-'){ neg_count += 1; } else if (string.str[i] != '+'){ break; } } // output part of string after signs *string_tail = str8_skip(string, i); // output integer sign S64 sign = (neg_count & 1)?-1:+1; return sign; } internal B32 str8_is_integer(String8 string, U32 radix) { B32 result = 0; if(string.size > 0) { if(1 < radix && radix <= 16) { result = 1; for(U64 i = 0; i < string.size; i += 1) { U8 c = string.str[i]; if(!(c < 0x80) || integer_symbol_reverse[c] >= radix) { result = 0; break; } } } } return result; } internal B32 str8_is_integer_signed(String8 string, U32 radix) { B32 result = 0; String8 sign = str8_prefix(string, 1); if(str8_match(sign, str8_lit("-"), 0)) { result = str8_is_integer(str8_skip(string, 1), radix); } else { result = str8_is_integer(string, radix); } return result; } internal U64 u64_from_str8(String8 string, U32 radix) { U64 x = 0; if(1 < radix && radix <= 16) { for(U64 i = 0; i < string.size; i += 1) { x *= radix; x += integer_symbol_reverse[string.str[i]&0x7F]; } } return x; } internal S64 s64_from_str8(String8 string, U32 radix) { S64 sign = sign_from_str8(string, &string); S64 x = (S64)u64_from_str8(string, radix) * sign; return x; } internal U32 u32_from_str8(String8 string, U32 radix) { U64 x64 = u64_from_str8(string, radix); U32 x32 = safe_cast_u32(x64); return x32; } internal S32 s32_from_str8(String8 string, U32 radix) { S64 x64 = s64_from_str8(string, radix); S32 x32 = safe_cast_s32(x64); return x32; } internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x) { // rjf: unpack radix / prefix size based on string prefix U64 radix = 0; U64 prefix_size = 0; { // hex if(str8_match(str8_prefix(string, 2), str8_lit("0x"), StringMatchFlag_CaseInsensitive)) { radix = 0x10, prefix_size = 2; } // binary else if(str8_match(str8_prefix(string, 2), str8_lit("0b"), StringMatchFlag_CaseInsensitive)) { radix = 2, prefix_size = 2; } // octal else if(str8_match(str8_prefix(string, 1), str8_lit("0"), StringMatchFlag_CaseInsensitive) && string.size > 1) { radix = 010, prefix_size = 1; } // decimal else { radix = 10, prefix_size = 0; } } // rjf: convert if we can String8 integer = str8_skip(string, prefix_size); B32 is_integer = str8_is_integer(integer, radix); if(is_integer) { *x = u64_from_str8(integer, radix); } return is_integer; } internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x) { String8 string_tail = {0}; S64 sign = sign_from_str8(string, &string_tail); U64 x_u64 = 0; B32 is_integer = try_u64_from_str8_c_rules(string_tail, &x_u64); *x = x_u64*sign; return is_integer; } //- rjf: integer -> string internal String8 str8_from_memory_size(Arena *arena, U64 size) { String8 result = {0}; { if(size < KB(1)) { result = push_str8f(arena, "%llu Bytes", size); } else if(size < MB(1)) { result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100); } else if(size < GB(1)) { result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100); } else if(size < TB(1)) { result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100); } else { result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100); } } return result; } internal String8 str8_from_count(Arena *arena, U64 count) { String8 result = {0}; { if(count < 1 * 1000) { result = push_str8f(arena, "%llu", count); } else if(count < 1000000) { U64 frac = ((count * 100) / 1000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac); } else { result = push_str8f(arena, "%lluK", count / 1000); } } else if(count < 1000000000) { U64 frac = ((count * 100) / 1000000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac); } else { result = push_str8f(arena, "%lluM", count / 1000000); } } else { U64 frac = ((count * 100) * 1000000000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac); } else { result = push_str8f(arena, "%lluB", count / 1000000000, frac); } } } return result; } internal String8 str8_from_bits_u32(Arena *arena, U32 x) { U8 c0 = 'a' + ((x >> 28) & 0xf); U8 c1 = 'a' + ((x >> 24) & 0xf); U8 c2 = 'a' + ((x >> 20) & 0xf); U8 c3 = 'a' + ((x >> 16) & 0xf); U8 c4 = 'a' + ((x >> 12) & 0xf); U8 c5 = 'a' + ((x >> 8) & 0xf); U8 c6 = 'a' + ((x >> 4) & 0xf); U8 c7 = 'a' + ((x >> 0) & 0xf); String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7); return result; } internal String8 str8_from_bits_u64(Arena *arena, U64 x) { U8 c0 = 'a' + ((x >> 60) & 0xf); U8 c1 = 'a' + ((x >> 56) & 0xf); U8 c2 = 'a' + ((x >> 52) & 0xf); U8 c3 = 'a' + ((x >> 48) & 0xf); U8 c4 = 'a' + ((x >> 44) & 0xf); U8 c5 = 'a' + ((x >> 40) & 0xf); U8 c6 = 'a' + ((x >> 36) & 0xf); U8 c7 = 'a' + ((x >> 32) & 0xf); U8 c8 = 'a' + ((x >> 28) & 0xf); U8 c9 = 'a' + ((x >> 24) & 0xf); U8 ca = 'a' + ((x >> 20) & 0xf); U8 cb = 'a' + ((x >> 16) & 0xf); U8 cc = 'a' + ((x >> 12) & 0xf); U8 cd = 'a' + ((x >> 8) & 0xf); U8 ce = 'a' + ((x >> 4) & 0xf); U8 cf = 'a' + ((x >> 0) & 0xf); String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf); return result; } internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator) { String8 result = {0}; { // rjf: prefix String8 prefix = {0}; switch(radix) { case 16:{prefix = str8_lit("0x");}break; case 8: {prefix = str8_lit("0o");}break; case 2: {prefix = str8_lit("0b");}break; } // rjf: determine # of chars between separators U8 digit_group_size = 3; switch(radix) { default:break; case 2: case 8: case 16: {digit_group_size = 4;}break; } // rjf: prep U64 needed_leading_0s = 0; { U64 needed_digits = 1; { U64 u64_reduce = u64; for(;;) { u64_reduce /= radix; if(u64_reduce == 0) { break; } needed_digits += 1; } } needed_leading_0s = (min_digits > needed_digits) ? min_digits - needed_digits : 0; U64 needed_separators = 0; if(digit_group_separator != 0) { needed_separators = (needed_digits+needed_leading_0s)/digit_group_size; if(needed_separators > 0 && (needed_digits+needed_leading_0s)%digit_group_size == 0) { needed_separators -= 1; } } result.size = prefix.size + needed_leading_0s + needed_separators + needed_digits; result.str = push_array_no_zero(arena, U8, result.size + 1); result.str[result.size] = 0; } // rjf: fill contents { U64 u64_reduce = u64; U64 digits_until_separator = digit_group_size; for(U64 idx = 0; idx < result.size; idx += 1) { if(digits_until_separator == 0 && digit_group_separator != 0) { result.str[result.size - idx - 1] = digit_group_separator; digits_until_separator = digit_group_size+1; } else { result.str[result.size - idx - 1] = lower_from_char(integer_symbols[u64_reduce%radix]); u64_reduce /= radix; } digits_until_separator -= 1; if(u64_reduce == 0) { break; } } for(U64 leading_0_idx = 0; leading_0_idx < needed_leading_0s; leading_0_idx += 1) { result.str[prefix.size + leading_0_idx] = '0'; } } // rjf: fill prefix if(prefix.size != 0) { MemoryCopy(result.str, prefix.str, prefix.size); } } return result; } internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator) { String8 result = {0}; // TODO(rjf): preeeeetty sloppy... if(s64 < 0) { Temp scratch = scratch_begin(&arena, 1); String8 numeric_part = str8_from_u64(scratch.arena, (U64)(-s64), radix, min_digits, digit_group_separator); result = push_str8f(arena, "-%S", numeric_part); scratch_end(scratch); } else { result = str8_from_u64(arena, (U64)s64, radix, min_digits, digit_group_separator); } return result; } //////////////////////////////// //~ rjf: String <=> Float Conversions internal F64 f64_from_str8(String8 string) { // TODO(rjf): crappy implementation for now that just uses atof. F64 result = 0; if(string.size > 0) { // rjf: find starting pos of numeric string, as well as sign F64 sign = +1.0; if(string.str[0] == '-') { sign = -1.0; } else if(string.str[0] == '+') { sign = 1.0; } // rjf: gather numerics U64 num_valid_chars = 0; char buffer[64]; B32 exp = 0; for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1) { if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.' || string.str[idx] == 'e' || (exp && (string.str[idx] == '+' || string.str[idx] == '-'))) { buffer[num_valid_chars] = string.str[idx]; num_valid_chars += 1; exp = 0; exp = (string.str[idx] == 'e'); } } // rjf: null-terminate (the reason for all of this!!!!!!) buffer[num_valid_chars] = 0; // rjf: do final conversion result = sign * atof(buffer); } return result; } //////////////////////////////// //~ rjf: String List Construction Functions internal String8Node * str8_list_push_node(String8List *list, String8Node *node) { SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size += node->string.size; return node; } internal String8Node * str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string) { SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size += string.size; node->string = string; return node; } internal String8Node * str8_list_push_node_front(String8List *list, String8Node *node) { SLLQueuePushFront(list->first, list->last, node); list->node_count += 1; list->total_size += node->string.size; return node; } internal String8Node * str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string) { SLLQueuePushFront(list->first, list->last, node); list->node_count += 1; list->total_size += string.size; node->string = string; return node; } internal String8Node * str8_list_push(Arena *arena, String8List *list, String8 string) { String8Node *node = push_array_no_zero(arena, String8Node, 1); str8_list_push_node_set_string(list, node, string); return node; } internal String8Node * str8_list_push_front(Arena *arena, String8List *list, String8 string) { String8Node *node = push_array_no_zero(arena, String8Node, 1); str8_list_push_node_front_set_string(list, node, string); return node; } internal void str8_list_concat_in_place(String8List *list, String8List *to_push) { if(to_push->node_count != 0) { if(list->last) { list->node_count += to_push->node_count; list->total_size += to_push->total_size; list->last->next = to_push->first; list->last = to_push->last; } else { *list = *to_push; } MemoryZeroStruct(to_push); } } internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align){ String8Node *node = push_array_no_zero(arena, String8Node, 1); U64 new_size = list->total_size + min; U64 increase_size = 0; if (align > 1){ // NOTE(allen): assert is power of 2 Assert(((align - 1) & align) == 0); U64 mask = align - 1; new_size += mask; new_size &= (~mask); increase_size = new_size - list->total_size; } local_persist const U8 zeroes_buffer[64] = {0}; Assert(increase_size <= ArrayCount(zeroes_buffer)); SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size = new_size; node->string.str = (U8*)zeroes_buffer; node->string.size = increase_size; return(node); } internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...) { va_list args; va_start(args, fmt); String8 string = push_str8fv(arena, fmt, args); String8Node *result = str8_list_push(arena, list, string); va_end(args); return result; } internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...) { va_list args; va_start(args, fmt); String8 string = push_str8fv(arena, fmt, args); String8Node *result = str8_list_push_front(arena, list, string); va_end(args); return result; } internal String8List str8_list_copy(Arena *arena, String8List *list) { String8List result = {0}; for(String8Node *node = list->first; node != 0; node = node->next) { String8Node *new_node = push_array_no_zero(arena, String8Node, 1); String8 new_string = push_str8_copy(arena, node->string); str8_list_push_node_set_string(&result, new_node, new_string); } return result; } //////////////////////////////// //~ rjf: String Splitting & Joining internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags) { String8List list = {0}; B32 keep_empties = (flags & StringSplitFlag_KeepEmpties); U8 *ptr = string.str; U8 *opl = string.str + string.size; for(;ptr < opl;) { U8 *first = ptr; for(;ptr < opl; ptr += 1) { U8 c = *ptr; B32 is_split = 0; for(U64 i = 0; i < split_char_count; i += 1) { if(split_chars[i] == c) { is_split = 1; break; } } if(is_split) { break; } } String8 string = str8_range(first, ptr); if(keep_empties || string.size > 0) { str8_list_push(arena, &list, string); } ptr += 1; } return list; } internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags) { String8List list = str8_split(arena, string, split_chars.str, split_chars.size, flags); return list; } internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params) { StringJoin join = {0}; if(optional_params != 0) { MemoryCopyStruct(&join, optional_params); } U64 sep_count = 0; if(list->node_count > 0) { sep_count = list->node_count - 1; } String8 result; result.size = join.pre.size + join.post.size + sep_count*join.sep.size + list->total_size; U8 *ptr = result.str = push_array_no_zero(arena, U8, result.size + 1); MemoryCopy(ptr, join.pre.str, join.pre.size); ptr += join.pre.size; for(String8Node *node = list->first; node != 0; node = node->next) { MemoryCopy(ptr, node->string.str, node->string.size); ptr += node->string.size; if(node->next != 0) { MemoryCopy(ptr, join.sep.str, join.sep.size); ptr += join.sep.size; } } MemoryCopy(ptr, join.post.str, join.post.size); ptr += join.post.size; *ptr = 0; return result; } //////////////////////////////// //~ rjf: Basic Data Structure Stringification Helpers internal String8List numeric_str8_list_from_data(Arena *arena, U32 radix, String8 data, U64 stride) { String8List strs = {0}; U64 count = data.size/stride; for EachIndex(idx, count) { U64 val = 0; MemoryCopy(&val, data.str + idx*stride, stride); str8_list_push(arena, &strs, str8_from_u64(arena, val, radix, 0, 0)); } return strs; } //////////////////////////////// //~ rjf; String Arrays internal String8Array str8_array_zero(void) { String8Array result = {0}; return result; } internal String8Array str8_array_from_list(Arena *arena, String8List *list) { String8Array array; array.count = list->node_count; array.v = push_array_no_zero(arena, String8, array.count); U64 idx = 0; for(String8Node *n = list->first; n != 0; n = n->next, idx += 1) { array.v[idx] = n->string; } return array; } internal String8Array * str8_array_from_list_arr(Arena *arena, String8List *lists, U64 count) { String8Array *result = push_array(arena, String8Array, count); for (U64 idx = 0; idx < count; idx += 1) { result[idx] = str8_array_from_list(arena, &lists[idx]); } return result; } internal String8Array str8_array_reserve(Arena *arena, U64 count) { String8Array arr; arr.count = 0; arr.v = push_array(arena, String8, count); return arr; } internal String8Array str8_array_copy(Arena *arena, String8Array array) { String8Array result = {0}; result.count = array.count; result.v = push_array(arena, String8, result.count); for EachIndex(idx, result.count) { result.v[idx] = push_str8_copy(arena, array.v[idx]); } return result; } //////////////////////////////// //~ rjf: String Version Helpers internal U64 version_from_str8(String8 string) { U64 result = 0; Temp scratch = scratch_begin(0, 0); U64 version_major = 0; U64 version_minor = 0; U64 version_patch = 0; String8List version_parts = str8_split(scratch.arena, string, (U8 *)".", 1, 0); if(version_parts.first && version_parts.first->next && version_parts.first->next->next) { try_u64_from_str8_c_rules(version_parts.first->string, &version_major); try_u64_from_str8_c_rules(version_parts.first->next->string, &version_minor); try_u64_from_str8_c_rules(version_parts.first->next->next->string, &version_patch); result = Version(version_major, version_minor, version_patch); } scratch_end(scratch); return result; } internal String8 str8_from_version(Arena *arena, U64 version) { U64 version_major = MajorFromVersion(version); U64 version_minor = MinorFromVersion(version); U64 version_patch = PatchFromVersion(version); String8 result = str8f(arena, "%I64d.%I64d.%I64d", version_major, version_minor, version_patch); return result; } //////////////////////////////// //~ rjf: String Path Helpers internal String8 str8_chop_last_slash(String8 string) { if(string.size > 0) { U8 *ptr = string.str + string.size - 1; for(;ptr >= string.str; ptr -= 1) { if(*ptr == '/' || *ptr == '\\') { break; } } if(ptr >= string.str) { string.size = (U64)(ptr - string.str); } else { string.size = 0; } } return string; } internal String8 str8_skip_last_slash(String8 string) { if(string.size > 0) { U8 *ptr = string.str + string.size - 1; for(;ptr >= string.str; ptr -= 1) { if(*ptr == '/' || *ptr == '\\') { break; } } if(ptr >= string.str) { ptr += 1; string.size = (U64)(string.str + string.size - ptr); string.str = ptr; } } return string; } internal String8 str8_chop_last_dot(String8 string) { String8 result = string; U64 p = string.size; for(;p > 0;) { p -= 1; if(string.str[p] == '.') { result = str8_prefix(string, p); break; } } return result; } internal String8 str8_skip_last_dot(String8 string) { String8 result = string; U64 p = string.size; for(;p > 0;) { p -= 1; if(string.str[p] == '.') { result = str8_skip(string, p + 1); break; } } return result; } internal PathStyle path_style_from_str8(String8 string) { PathStyle result = PathStyle_Relative; if(string.size >= 1 && string.str[0] == '/') { result = PathStyle_UnixAbsolute; } else if(string.size >= 2 && char_is_alpha(string.str[0]) && string.str[1] == ':') { if(string.size == 2 || char_is_slash(string.str[2])) { result = PathStyle_WindowsAbsolute; } } return result; } internal String8List str8_split_path(Arena *arena, String8 string) { String8List result = str8_split(arena, string, (U8*)"/\\", 2, 0); return result; } internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style) { Temp scratch = scratch_begin(0, 0); typedef struct String8MetaNode String8MetaNode; struct String8MetaNode { String8MetaNode *next; String8Node *node; }; String8MetaNode *stack = 0; String8MetaNode *free_meta_node = 0; String8Node *first = path->first; MemoryZeroStruct(path); for(String8Node *node = first, *next = 0; node != 0; node = next) { // save next now next = node->next; // cases: if(node == first && style == PathStyle_WindowsAbsolute) { goto save_without_stack; } if(node->string.size == 1 && node->string.str[0] == '.') { goto do_nothing; } if(node->string.size == 2 && node->string.str[0] == '.' && node->string.str[1] == '.') { if(stack != 0) { goto eliminate_stack_top; } else { goto save_without_stack; } } goto save_with_stack; // handlers: save_with_stack: { str8_list_push_node(path, node); String8MetaNode *stack_node = free_meta_node; if(stack_node != 0) { SLLStackPop(free_meta_node); } else { stack_node = push_array_no_zero(scratch.arena, String8MetaNode, 1); } SLLStackPush(stack, stack_node); stack_node->node = node; continue; } save_without_stack: { str8_list_push_node(path, node); continue; } eliminate_stack_top: { path->node_count -= 1; path->total_size -= stack->node->string.size; SLLStackPop(stack); if(stack == 0) { path->last = path->first; } else { path->last = stack->node; } continue; } do_nothing: continue; } scratch_end(scratch); } internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style) { StringJoin params = {0}; switch(style) { case PathStyle_Null:{}break; case PathStyle_Relative: case PathStyle_WindowsAbsolute: { params.sep = str8_lit("/"); }break; case PathStyle_UnixAbsolute: { params.pre = str8_lit("/"); params.sep = str8_lit("/"); }break; } String8 result = str8_list_join(arena, path, ¶ms); return result; } internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string) { String8TxtPtPair pair = {0}; { String8 file_part = {0}; String8 line_part = {0}; String8 col_part = {0}; // rjf: grab file part for(U64 idx = 0; idx <= string.size; idx += 1) { U8 byte = (idx < string.size) ? (string.str[idx]) : 0; U8 next_byte = ((idx+1 < string.size) ? (string.str[idx+1]) : 0); if(byte == ':' && next_byte != '/' && next_byte != '\\') { file_part = str8_prefix(string, idx); line_part = str8_skip(string, idx+1); break; } else if(byte == 0) { file_part = string; break; } } // rjf: grab line/column { U64 colon_pos = str8_find_needle(line_part, 0, str8_lit(":"), 0); if(colon_pos < line_part.size) { col_part = str8_skip(line_part, colon_pos+1); line_part = str8_prefix(line_part, colon_pos); } } // rjf: convert line/column strings to numerics U64 line = 0; U64 column = 0; try_u64_from_str8_c_rules(line_part, &line); try_u64_from_str8_c_rules(col_part, &column); // rjf: fill pair.string = file_part; pair.pt = txt_pt((S64)line, (S64)column); if(pair.pt.line == 0) { pair.pt.line = 1; } if(pair.pt.column == 0) { pair.pt.column = 1; } } return pair; } //////////////////////////////// //~ rjf: Relative <-> Absolute Path internal String8 path_relative_dst_from_absolute_dst_src(Arena *arena, String8 dst, String8 src) { Temp scratch = scratch_begin(&arena, 1); // rjf: gather path parts String8 dst_name = str8_skip_last_slash(dst); String8 src_folder = src; String8 dst_folder = str8_chop_last_slash(dst); String8List src_folders = str8_split_path(scratch.arena, src_folder); String8List dst_folders = str8_split_path(scratch.arena, dst_folder); // rjf: count # of backtracks to get from src -> dest U64 num_backtracks = src_folders.node_count; for(String8Node *src_n = src_folders.first, *bp_n = dst_folders.first; src_n != 0 && bp_n != 0; src_n = src_n->next, bp_n = bp_n->next) { if(str8_match(src_n->string, bp_n->string, path_match_flags_from_os(OperatingSystem_CURRENT))) { num_backtracks -= 1; } else { break; } } // rjf: only build relative string if # of backtracks is not the entire `src`. // if getting to `dst` from `src` requires erasing the entire `src`, then the // only possible way to get to `dst` from `src` is via absolute path. String8 dst_path = {0}; if(num_backtracks >= src_folders.node_count) { dst_path = dst; } else { // rjf: build backtrack parts String8List dst_path_strs = {0}; for(U64 idx = 0; idx < num_backtracks; idx += 1) { str8_list_push(scratch.arena, &dst_path_strs, str8_lit("..")); } // rjf: build parts of dst which are unique from src { B32 unique_from_src = 0; for(String8Node *src_n = src_folders.first, *bp_n = dst_folders.first; bp_n != 0; bp_n = bp_n->next) { if(!unique_from_src && (src_n == 0 || !str8_match(src_n->string, bp_n->string, path_match_flags_from_os(OperatingSystem_CURRENT)))) { unique_from_src = 1; } if(unique_from_src) { str8_list_push(scratch.arena, &dst_path_strs, bp_n->string); } if(src_n != 0) { src_n = src_n->next; } } } // rjf: build file name str8_list_push(scratch.arena, &dst_path_strs, dst_name); // rjf: join StringJoin join = {0}; { join.sep = str8_lit("/"); } dst_path = str8_list_join(arena, &dst_path_strs, &join); } scratch_end(scratch); return dst_path; } internal String8 path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src) { String8 result = dst; PathStyle dst_style = path_style_from_str8(dst); if(dst.size != 0 && dst_style == PathStyle_Relative) { Temp scratch = scratch_begin(&arena, 1); String8 dst_from_src_absolute = push_str8f(scratch.arena, "%S/%S", src, dst); String8List dst_from_src_absolute_parts = str8_split_path(scratch.arena, dst_from_src_absolute); PathStyle dst_from_src_absolute_style = path_style_from_str8(src); str8_path_list_resolve_dots_in_place(&dst_from_src_absolute_parts, dst_from_src_absolute_style); result = str8_path_list_join_by_style(arena, &dst_from_src_absolute_parts, dst_from_src_absolute_style); scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: Path Normalization internal String8List path_normalized_list_from_string(Arena *arena, String8 path_string, PathStyle *style_out) { // rjf: analyze path PathStyle path_style = path_style_from_str8(path_string); String8List path = str8_split_path(arena, path_string); // rjf: resolve dots str8_path_list_resolve_dots_in_place(&path, path_style); // rjf: return if(style_out != 0) { *style_out = path_style; } return path; } internal String8 path_normalized_from_string(Arena *arena, String8 path_string) { Temp scratch = scratch_begin(&arena, 1); PathStyle style = PathStyle_Relative; String8List path = path_normalized_list_from_string(scratch.arena, path_string, &style); String8 result = str8_path_list_join_by_style(arena, &path, style); scratch_end(scratch); return result; } internal B32 path_match_normalized(String8 left, String8 right) { Temp scratch = scratch_begin(0, 0); String8 left_normalized = path_normalized_from_string(scratch.arena, left); String8 right_normalized = path_normalized_from_string(scratch.arena, right); B32 result = str8_match(left_normalized, right_normalized, StringMatchFlag_CaseInsensitive); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Misc. Path Helpers internal PathStyle path_style_from_string(String8 string) { for (U64 i = 0; i < ArrayCount(g_path_style_map); ++i) { if(str8_match(g_path_style_map[i].string, string, StringMatchFlag_CaseInsensitive)) { return g_path_style_map[i].path_style; } } return PathStyle_Null; } internal String8 string_from_path_style(PathStyle style) { Assert(style < ArrayCount(g_path_style_map)); return g_path_style_map[style].string; } internal String8 path_separator_string_from_style(PathStyle style) { String8 result = str8_zero(); switch (style) { case PathStyle_Null: break; case PathStyle_Relative: break; case PathStyle_WindowsAbsolute: result = str8_lit("\\"); break; case PathStyle_UnixAbsolute: result = str8_lit("/"); break; } return result; } internal StringMatchFlags path_match_flags_from_os(OperatingSystem os) { StringMatchFlags flags = StringMatchFlag_SlashInsensitive; switch(os) { default:{}break; case OperatingSystem_Windows: { flags |= StringMatchFlag_CaseInsensitive; }break; case OperatingSystem_Linux: case OperatingSystem_Mac: { // NOTE(rjf): no-op }break; } return flags; } internal String8 path_convert_slashes(Arena *arena, String8 path, PathStyle path_style) { Temp scratch = scratch_begin(&arena, 1); String8List list = str8_split_path(scratch.arena, path); StringJoin join = {0}; join.sep = path_separator_string_from_style(path_style); String8 result = str8_list_join(arena, &list, &join); scratch_end(scratch); return result; } internal String8 path_replace_file_extension(Arena *arena, String8 file_name, String8 ext) { String8 file_name_no_ext = str8_chop_last_dot(file_name); String8 result = str8f(arena, "%S.%S", file_name_no_ext, ext); return result; } //////////////////////////////// //~ rjf: UTF-8 & UTF-16 Decoding/Encoding read_only global U8 utf8_class[32] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5, }; internal UnicodeDecode utf8_decode(U8 *str, U64 max) { UnicodeDecode result = {1, max_U32}; U8 byte = str[0]; U8 byte_class = utf8_class[byte >> 3]; switch(byte_class) { case 1: { result.codepoint = byte; }break; case 2: { if(1 < max) { U8 cont_byte = str[1]; if(utf8_class[cont_byte >> 3] == 0) { result.codepoint = (byte & bitmask5) << 6; result.codepoint |= (cont_byte & bitmask6); result.inc = 2; } } }break; case 3: { if(2 < max) { U8 cont_byte[2] = {str[1], str[2]}; if(utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0) { result.codepoint = (byte & bitmask4) << 12; result.codepoint |= ((cont_byte[0] & bitmask6) << 6); result.codepoint |= (cont_byte[1] & bitmask6); result.inc = 3; } } }break; case 4: { if(3 < max) { U8 cont_byte[3] = {str[1], str[2], str[3]}; if(utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0 && utf8_class[cont_byte[2] >> 3] == 0) { result.codepoint = (byte & bitmask3) << 18; result.codepoint |= ((cont_byte[0] & bitmask6) << 12); result.codepoint |= ((cont_byte[1] & bitmask6) << 6); result.codepoint |= (cont_byte[2] & bitmask6); result.inc = 4; } } } } return result; } internal UnicodeDecode utf16_decode(U16 *str, U64 max) { UnicodeDecode result = {1, max_U32}; result.codepoint = str[0]; result.inc = 1; if(max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000) { result.codepoint = ((str[0] - 0xD800) << 10) | ((str[1] - 0xDC00) + 0x10000); result.inc = 2; } return result; } internal U32 utf8_encode(U8 *str, U32 codepoint) { U32 inc = 0; if(codepoint <= 0x7F) { str[0] = (U8)codepoint; inc = 1; } else if(codepoint <= 0x7FF) { str[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5); str[1] = bit8 | (codepoint & bitmask6); inc = 2; } else if(codepoint <= 0xFFFF) { str[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4); str[1] = bit8 | ((codepoint >> 6) & bitmask6); str[2] = bit8 | ( codepoint & bitmask6); inc = 3; } else if(codepoint <= 0x10FFFF) { str[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3); str[1] = bit8 | ((codepoint >> 12) & bitmask6); str[2] = bit8 | ((codepoint >> 6) & bitmask6); str[3] = bit8 | ( codepoint & bitmask6); inc = 4; } else { str[0] = '?'; inc = 1; } return inc; } internal U32 utf16_encode(U16 *str, U32 codepoint) { U32 inc = 1; if(codepoint == max_U32) { str[0] = (U16)'?'; } else if(codepoint < 0x10000) { str[0] = (U16)codepoint; } else { U32 v = codepoint - 0x10000; str[0] = safe_cast_u16(0xD800 + (v >> 10)); str[1] = safe_cast_u16(0xDC00 + (v & bitmask10)); inc = 2; } return inc; } //////////////////////////////// //~ rjf: Unicode String Conversions internal String8 str8_from_16(Arena *arena, String16 in) { String8 result = str8_zero(); if(in.size) { U64 cap = in.size*3; U8 *str = push_array_no_zero(arena, U8, cap + 1); U16 *ptr = in.str; U16 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf16_decode(ptr, opl - ptr); size += utf8_encode(str + size, consume.codepoint); } str[size] = 0; arena_pop(arena, (cap - size)); result = str8(str, size); } return result; } internal String16 str16_from_8(Arena *arena, String8 in) { String16 result = str16_zero(); if(in.size) { U64 cap = in.size*2; U16 *str = push_array_no_zero(arena, U16, cap + 1); U8 *ptr = in.str; U8 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf8_decode(ptr, opl - ptr); size += utf16_encode(str + size, consume.codepoint); } str[size] = 0; arena_pop(arena, (cap - size)*2); result = str16(str, size); } return result; } internal String8 str8_from_32(Arena *arena, String32 in) { String8 result = str8_zero(); if(in.size) { U64 cap = in.size*4; U8 *str = push_array_no_zero(arena, U8, cap + 1); U32 *ptr = in.str; U32 *opl = ptr + in.size; U64 size = 0; for(;ptr < opl; ptr += 1) { size += utf8_encode(str + size, *ptr); } str[size] = 0; arena_pop(arena, (cap - size)); result = str8(str, size); } return result; } internal String32 str32_from_8(Arena *arena, String8 in) { String32 result = str32_zero(); if(in.size) { U64 cap = in.size; U32 *str = push_array_no_zero(arena, U32, cap + 1); U8 *ptr = in.str; U8 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf8_decode(ptr, opl - ptr); str[size] = consume.codepoint; size += 1; } str[size] = 0; arena_pop(arena, (cap - size)*4); result = str32(str, size); } return result; } //////////////////////////////// //~ rjf: Basic Types & Space Enum -> String Conversions read_only global struct { String8 string; OperatingSystem os; } g_os_enum_map[] = { { str8_lit_comp(""), OperatingSystem_Null }, { str8_lit_comp("Windows"), OperatingSystem_Windows, }, { str8_lit_comp("Linux"), OperatingSystem_Linux, }, { str8_lit_comp("Mac"), OperatingSystem_Mac, }, }; StaticAssert(ArrayCount(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check); internal OperatingSystem operating_system_from_string(String8 string) { for EachElement(idx, g_os_enum_map) { if(str8_match(g_os_enum_map[idx].string, string, StringMatchFlag_CaseInsensitive)) { return g_os_enum_map[idx].os; } } return OperatingSystem_Null; } internal String8 string_from_dimension(Dimension dimension) { read_only local_persist String8 strings[] = { str8_lit_comp("X"), str8_lit_comp("Y"), str8_lit_comp("Z"), str8_lit_comp("W"), }; String8 result = str8_lit("error"); if((U32)dimension < 4) { result = strings[dimension]; } return result; } internal String8 string_from_side(Side side) { local_persist String8 strings[] = { str8_lit_comp("Min"), str8_lit_comp("Max"), }; String8 result = str8_lit("error"); if((U32)side < 2) { result = strings[side]; } return result; } internal String8 string_from_operating_system(OperatingSystem os) { String8 result = g_os_enum_map[OperatingSystem_Null].string; if(os < ArrayCount(g_os_enum_map)) { result = g_os_enum_map[os].string; } return result; } internal String8 string_from_arch(Arch arch) { String8 result = {0}; switch(arch) { case Arch_Null: {result = str8_lit("Null");}break; case Arch_x64: {result = str8_lit("x64");}break; case Arch_x86: {result = str8_lit("x86");}break; case Arch_arm64: {result = str8_lit("arm64");}break; case Arch_arm32: {result = str8_lit("arm32");}break; case Arch_COUNT: {result = str8_lit("Invalid");}break; } return result; } internal String8 string_from_week_day(WeekDay week_day) { read_only local_persist String8 strings[] = { str8_lit_comp("Sun"), str8_lit_comp("Mon"), str8_lit_comp("Tue"), str8_lit_comp("Wed"), str8_lit_comp("Thu"), str8_lit_comp("Fri"), str8_lit_comp("Sat"), }; String8 result = str8_lit("Err"); if((U32)week_day < WeekDay_COUNT) { result = strings[week_day]; } return result; } internal String8 string_from_month(Month month) { read_only local_persist String8 strings[] = { str8_lit_comp("Jan"), str8_lit_comp("Feb"), str8_lit_comp("Mar"), str8_lit_comp("Apr"), str8_lit_comp("May"), str8_lit_comp("Jun"), str8_lit_comp("Jul"), str8_lit_comp("Aug"), str8_lit_comp("Sep"), str8_lit_comp("Oct"), str8_lit_comp("Nov"), str8_lit_comp("Dec"), }; String8 result = str8_lit("Err"); if((U32)month < Month_COUNT) { result = strings[month]; } return result; } internal String8 string_from_date_time(Arena *arena, DateTime *date_time) { char *mon_str = (char*)string_from_month(date_time->month).str; U32 adjusted_hour = date_time->hour%12; if(adjusted_hour == 0) { adjusted_hour = 12; } char *ampm = "am"; if(date_time->hour >= 12) { ampm = "pm"; } String8 result = push_str8f(arena, "%d %s %d, %02d:%02d:%02d %s", date_time->day, mon_str, date_time->year, adjusted_hour, date_time->min, date_time->sec, ampm); return result; } internal String8 string_from_date_time__file_name(Arena *arena, DateTime *date_time) { char *mon_str = (char*)string_from_month(date_time->month).str; String8 result = str8f(arena, "%d-%s-%0d--%02d-%02d-%02d", date_time->year, mon_str, date_time->day, date_time->hour, date_time->min, date_time->sec); return result; } internal String8 string_from_elapsed_time(Arena *arena, DateTime dt) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if(dt.year) { str8_list_pushf(scratch.arena, &list, "%dy", dt.year); str8_list_pushf(scratch.arena, &list, "%um", dt.mon); str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } else if(dt.mon) { str8_list_pushf(scratch.arena, &list, "%um", dt.mon); str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } else if (dt.day) { str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } str8_list_pushf(scratch.arena, &list, "%u:%u:%u:%u ms", dt.hour, dt.min, dt.sec, dt.msec); StringJoin join = { str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }; String8 result = str8_list_join(arena, &list, &join); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: String <-> Globally Unique IDs internal String8 string_from_guid(Arena *arena, Guid guid) { String8 result = str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7]); return result; } internal B32 try_guid_from_string(String8 string, Guid *guid_out) { Temp scratch = scratch_begin(0,0); B32 is_parsed = 0; String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties); if(list.node_count == 5) { String8 data1_str = list.first->string; String8 data2_str = list.first->next->string; String8 data3_str = list.first->next->next->string; String8 data4_hi_str = list.first->next->next->next->string; String8 data4_lo_str = list.first->next->next->next->next->string; if(str8_is_integer(data1_str, 16) && str8_is_integer(data2_str, 16) && str8_is_integer(data3_str, 16) && str8_is_integer(data4_hi_str, 16) && str8_is_integer(data4_lo_str, 16)) { U64 data1 = u64_from_str8(data1_str, 16); U64 data2 = u64_from_str8(data2_str, 16); U64 data3 = u64_from_str8(data3_str, 16); U64 data4_hi = u64_from_str8(data4_hi_str, 16); U64 data4_lo = u64_from_str8(data4_lo_str, 16); if(data1 <= max_U32 && data2 <= max_U16 && data3 <= max_U16 && data4_hi <= max_U16 && data4_lo <= 0xffffffffffff) { guid_out->data1 = (U32)data1; guid_out->data2 = (U16)data2; guid_out->data3 = (U16)data3; U64 data4 = (data4_hi << 48) | data4_lo; MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4)); is_parsed = 1; } } } scratch_end(scratch); return is_parsed; } internal Guid guid_from_string(String8 string) { Guid guid = {0}; try_guid_from_string(string, &guid); return guid; } //////////////////////////////// //~ rjf: Basic Text Indentation internal String8 indented_from_string(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); read_only local_persist U8 indentation_bytes[] = " "; String8List indented_strings = {0}; S64 depth = 0; S64 next_depth = 0; U64 line_begin_off = 0; for(U64 off = 0; off <= string.size; off += 1) { U8 byte = off width_this_line){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); line_range = r1u64(line_range.max+1, candidate_line_range.max); wrapped_indent_level = ClampTop(64, wrap_indent); } else{ line_range = candidate_line_range; } } } if (line_range.min < string.size && line_range.max > line_range.min){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); } return list; } //////////////////////////////// //~ rjf: String <-> Color internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba) { String8 hex_string = str8f(arena, "%02x%02x%02x%02x", (U8)(rgba.x*255.f), (U8)(rgba.y*255.f), (U8)(rgba.z*255.f), (U8)(rgba.w*255.f)); return hex_string; } internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string) { U8 byte_text[8] = {0}; U64 byte_text_idx = 0; for(U64 idx = 0; idx < hex_string.size && byte_text_idx < ArrayCount(byte_text); idx += 1) { if(char_is_digit(hex_string.str[idx], 16)) { byte_text[byte_text_idx] = lower_from_char(hex_string.str[idx]); byte_text_idx += 1; } } U8 byte_vals[4] = {0}; for(U64 idx = 0; idx < 4; idx += 1) { byte_vals[idx] = (U8)u64_from_str8(str8(&byte_text[idx*2], 2), 16); } Vec4F32 rgba = v4f32(byte_vals[0]/255.f, byte_vals[1]/255.f, byte_vals[2]/255.f, byte_vals[3]/255.f); return rgba; } //////////////////////////////// //~ rjf: String Fuzzy Matching internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack) { FuzzyMatchRangeList result = {0}; Temp scratch = scratch_begin(&arena, 1); String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0); result.needle_part_count = needles.node_count; for(String8Node *needle_n = needles.first; needle_n != 0; needle_n = needle_n->next) { U64 find_pos = 0; for(;find_pos < haystack.size;) { find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); B32 is_in_gathered_ranges = 0; for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next) { if(n->range.min <= find_pos && find_pos < n->range.max) { is_in_gathered_ranges = 1; find_pos = n->range.max; break; } } if(!is_in_gathered_ranges) { break; } } if(find_pos < haystack.size) { Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size); FuzzyMatchRangeNode *n = push_array(arena, FuzzyMatchRangeNode, 1); n->range = range; SLLQueuePush(result.first, result.last, n); result.count += 1; result.total_dim += dim_1u64(range); } } scratch_end(scratch); return result; } internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src) { FuzzyMatchRangeList dst = {0}; for(FuzzyMatchRangeNode *src_n = src->first; src_n != 0; src_n = src_n->next) { FuzzyMatchRangeNode *dst_n = push_array(arena, FuzzyMatchRangeNode, 1); SLLQueuePush(dst.first, dst.last, dst_n); dst_n->range = src_n->range; } dst.count = src->count; dst.needle_part_count = src->needle_part_count; dst.total_dim = src->total_dim; return dst; } //////////////////////////////// //~ NOTE(allen): Serialization Helpers internal void str8_serial_begin(Arena *arena, String8List *srl){ String8Node *node = push_array(arena, String8Node, 1); node->string.str = push_array_no_zero(arena, U8, 0); srl->first = srl->last = node; srl->node_count = 1; srl->total_size = 0; } internal String8 str8_serial_end(Arena *arena, String8List *srl){ U64 size = srl->total_size; U8 *out = push_array_no_zero(arena, U8, size); str8_serial_write_to_dst(srl, out); String8 result = str8(out, size); return result; } internal void str8_serial_write_to_dst(String8List *srl, void *out){ U8 *ptr = (U8*)out; for (String8Node *node = srl->first; node != 0; node = node->next){ U64 size = node->string.size; MemoryCopy(ptr, node->string.str, size); ptr += size; } } internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align){ Assert(IsPow2(align)); U64 pos = srl->total_size; U64 new_pos = AlignPow2(pos, align); U64 size = (new_pos - pos); if(size != 0) { U8 *buf = push_array(arena, U8, size); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += size; srl->total_size += size; } else{ str8_list_push(arena, srl, str8(buf, size)); } } return size; } internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size) { void *result = 0; if(size != 0) { U8 *buf = push_array_no_zero(arena, U8, size); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += size; srl->total_size += size; } else{ str8_list_push(arena, srl, str8(buf, size)); } result = buf; } return result; } internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size){ void *result = str8_serial_push_size(arena, srl, size); if(result != 0) { MemoryCopy(result, data, size); } return result; } internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first){ for (String8Node *node = first; node != 0; node = node->next){ str8_serial_push_data(arena, srl, node->string.str, node->string.size); } } internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x){ U8 *buf = push_array_no_zero(arena, U8, 8); MemoryCopy(buf, &x, 8); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += 8; srl->total_size += 8; } else{ str8_list_push(arena, srl, str8(buf, 8)); } } internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x){ U8 *buf = push_array_no_zero(arena, U8, 4); MemoryCopy(buf, &x, 4); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += 4; srl->total_size += 4; } else{ str8_list_push(arena, srl, str8(buf, 4)); } } internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x){ str8_serial_push_data(arena, srl, &x, sizeof(x)); } internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x){ str8_serial_push_data(arena, srl, &x, sizeof(x)); } internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str){ str8_serial_push_data(arena, srl, str.str, str.size); str8_serial_push_u8(arena, srl, 0); } internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str){ str8_serial_push_data(arena, srl, str.str, str.size); } //////////////////////////////// //~ rjf: Deserialization Helpers internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity) { U64 bytes_left = string.size-Min(off, string.size); U64 actually_readable_size = Min(bytes_left, read_size); U64 legally_readable_size = actually_readable_size - actually_readable_size%granularity; if(legally_readable_size > 0) { MemoryCopy(read_dst, string.str+off, legally_readable_size); } return legally_readable_size; } internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val) { U64 cursor = off; for (;;) { U16 val = 0; str8_deserial_read_struct(string, cursor, &val); if (val == scan_val) { break; } cursor += sizeof(val); } return cursor; } internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size) { void *raw_ptr = 0; if (off + size <= string.size) { raw_ptr = string.str + off; } return raw_ptr; } internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out) { U64 cstr_size = 0; if (off < string.size) { U8 *ptr = string.str + off; U8 *cap = string.str + string.size; *cstr_out = str8_cstring_capped(ptr, cap); cstr_size = (cstr_out->size + 1); } return cstr_size; } internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out) { U64 null_off = str8_deserial_find_first_match(string, off, 0); U64 size = null_off - off; U16 *str = (U16 *)str8_deserial_get_raw_ptr(string, off, size); U64 count = size / sizeof(*str); *str_out = str16(str, count); U64 read_size_with_null = size + sizeof(*str); return read_size_with_null; } internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out) { Rng1U64 range = rng_1u64(off, off + size); *block_out = str8_substr(string, range); return block_out->size; } //////////////////////////////// internal int str8_compar(String8 a, String8 b, B32 ignore_case) { int cmp = 0; U64 size = Min(a.size, b.size); if (ignore_case) { for (U64 i = 0; i < size; ++i) { U8 la = lower_from_char(a.str[i]); U8 lb = lower_from_char(b.str[i]); if (la < lb) { cmp = -1; break; } else if (la > lb) { cmp = +1; break; } } } else { for (U64 i = 0; i < size; ++i) { if (a.str[i] < b.str[i]) { cmp = -1; break; } else if (a.str[i] > b.str[i]) { cmp = +1; break; } } } if (cmp == 0) { // shorter prefix must precede longer prefixes if (a.size > b.size) { cmp = +1; } else if (b.size > a.size) { cmp = -1; } } return cmp; } internal int str8_compar_ignore_case(const void *a, const void *b) { return str8_compar(*(String8*)a, *(String8*)b, 1); } internal int str8_compar_case_sensitive(const void *a, const void *b) { return str8_compar(*(String8*)a, *(String8*)b, 0); } internal int str8_is_before_case_sensitive(const void *a, const void *b) { int cmp = str8_compar_case_sensitive(a, b); return cmp < 0; } //////////////////////////////// //~ rjf: Basic String Hashes #if !defined(XXH_IMPLEMENTATION) # define XXH_INLINE_ALL # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal U64 u64_hash_from_seed_str8(U64 seed, String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); return result; } internal U64 u64_hash_from_str8(String8 string) { U64 result = u64_hash_from_seed_str8(5381, string); return result; } internal U128 u128_hash_from_seed_str8(U64 seed, String8 string) { U128 result = {0}; XXH128_hash_t hash = XXH3_128bits_withSeed(string.str, string.size, seed); MemoryCopy(&result, &hash, sizeof(result)); return result; } internal U128 u128_hash_from_str8(String8 string) { U128 result = u128_hash_from_seed_str8(5381, string); return result; } ================================================ FILE: src/base/base_strings.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_STRINGS_H #define BASE_STRINGS_H //////////////////////////////// //~ rjf: String Types typedef struct String8 String8; struct String8 { U8 *str; U64 size; }; typedef struct String16 String16; struct String16 { U16 *str; U64 size; }; typedef struct String32 String32; struct String32 { U32 *str; U64 size; }; //////////////////////////////// //~ rjf: String List & Array Types typedef struct String8Node String8Node; struct String8Node { String8Node *next; String8 string; }; typedef struct String8List String8List; struct String8List { String8Node *first; String8Node *last; U64 node_count; U64 total_size; }; typedef struct String8Array String8Array; struct String8Array { String8 *v; U64 count; U64 total_size; }; //////////////////////////////// //~ rjf: String Matching, Splitting, & Joining Types typedef U32 StringMatchFlags; enum { StringMatchFlag_CaseInsensitive = (1 << 0), StringMatchFlag_RightSideSloppy = (1 << 1), StringMatchFlag_SlashInsensitive = (1 << 2), }; typedef U32 StringSplitFlags; enum { StringSplitFlag_KeepEmpties = (1 << 0), }; typedef enum PathStyle { PathStyle_Null, PathStyle_Relative, PathStyle_WindowsAbsolute, PathStyle_UnixAbsolute, #if OS_WINDOWS PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute #elif OS_LINUX PathStyle_SystemAbsolute = PathStyle_UnixAbsolute #else # error Absolute path style is undefined for this OS. #endif } PathStyle; typedef struct StringJoin StringJoin; struct StringJoin { String8 pre; String8 sep; String8 post; }; //////////////////////////////// //~ rjf: String Pair Types typedef struct String8TxtPtPair String8TxtPtPair; struct String8TxtPtPair { String8 string; TxtPt pt; }; //////////////////////////////// //~ rjf: UTF Decoding Types typedef struct UnicodeDecode UnicodeDecode; struct UnicodeDecode { U32 inc; U32 codepoint; }; //////////////////////////////// //~ rjf: String Fuzzy Matching Types typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode; struct FuzzyMatchRangeNode { FuzzyMatchRangeNode *next; Rng1U64 range; }; typedef struct FuzzyMatchRangeList FuzzyMatchRangeList; struct FuzzyMatchRangeList { FuzzyMatchRangeNode *first; FuzzyMatchRangeNode *last; U64 count; U64 needle_part_count; U64 total_dim; }; //////////////////////////////// //~ rjf: Character Classification & Conversion Functions internal B32 char_is_space(U8 c); internal B32 char_is_upper(U8 c); internal B32 char_is_lower(U8 c); internal B32 char_is_alpha(U8 c); internal B32 char_is_slash(U8 c); internal B32 char_is_digit(U8 c, U32 base); internal U8 lower_from_char(U8 c); internal U8 upper_from_char(U8 c); internal U8 correct_slash_from_char(U8 c); //////////////////////////////// //~ rjf: C-String Measurement internal U64 cstring8_length(U8 *c); internal U64 cstring16_length(U16 *c); internal U64 cstring32_length(U32 *c); //////////////////////////////// //~ rjf: String Constructors #define str8_lit(S) str8((U8*)(S), sizeof(S) - 1) #define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,} #define str8_varg(S) (int)((S).size), ((S).str) #define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C)) #define str8_array_fixed(S) str8((U8*)(S), sizeof(S)) #define str8_struct(S) str8((U8*)(S), sizeof(*(S))) internal String8 str8(U8 *str, U64 size); internal String8 str8_range(U8 *first, U8 *one_past_last); internal String8 str8_zero(void); internal String16 str16(U16 *str, U64 size); internal String16 str16_range(U16 *first, U16 *one_past_last); internal String16 str16_zero(void); internal String32 str32(U32 *str, U64 size); internal String32 str32_range(U32 *first, U32 *one_past_last); internal String32 str32_zero(void); internal String8 str8_cstring(char *c); internal String16 str16_cstring(U16 *c); internal String32 str32_cstring(U32 *c); internal String8 str8_cstring_capped(void *cstr, void *cap); internal String16 str16_cstring_capped(void *cstr, void *cap); internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap); //////////////////////////////// //~ rjf: String Stylization internal String8 upper_from_str8(Arena *arena, String8 string); internal String8 lower_from_str8(Arena *arena, String8 string); internal String8 backslashed_from_str8(Arena *arena, String8 string); //////////////////////////////// //~ rjf: String Matching #define str8_match_lit(a_lit, b, flags) str8_match(str8_lit(a_lit), (b), (flags)) #define str8_match_cstr(a_cstr, b, flags) str8_match(str8_cstring(a_cstr), (b), (flags)) internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags); internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal B32 str8_is_before(String8 a, String8 b); #define str8_ends_with(string, end, flags) str8_match(str8_postfix((string), (end).size), (end), (flags)) //////////////////////////////// //~ rjf: String Slicing internal String8 str8_substr(String8 str, Rng1U64 range); internal String8 str8_prefix(String8 str, U64 size); internal String8 str8_skip(String8 str, U64 amt); internal String8 str8_postfix(String8 str, U64 size); internal String8 str8_chop(String8 str, U64 amt); internal String8 str8_skip_chop_whitespace(String8 string); internal String8 str8_skip_chop_slashes(String8 string); //////////////////////////////// //~ rjf: String Formatting & Copying internal String8 str8_cat(Arena *arena, String8 s1, String8 s2); internal String8 str8_copy(Arena *arena, String8 s); internal String8 str8fv(Arena *arena, char *fmt, va_list args); internal String8 str8f(Arena *arena, char *fmt, ...); // TODO(rjf): remove these once we're ready to convert all usages: #define push_str8_cat(arena, s1, s2) str8_cat((arena), (s1), (s2)) #define push_str8_copy(arena, s) str8_copy((arena), (s)) #define push_str8fv(arena, fmt, args) str8fv((arena), (fmt), (args)) #define push_str8f(arena, ...) str8f((arena), __VA_ARGS__) internal String8 push_cstr(Arena *arena, String8 str); // TODO(rjf): this is unnecessary - this is implied by `push_str8_copy`. need to remove. //////////////////////////////// //~ rjf: String <=> Integer Conversions //- rjf: string -> integer internal S64 sign_from_str8(String8 string, String8 *string_tail); internal B32 str8_is_integer(String8 string, U32 radix); internal B32 str8_is_integer_signed(String8 string, U32 radix); internal U64 u64_from_str8(String8 string, U32 radix); internal S64 s64_from_str8(String8 string, U32 radix); internal U32 u32_from_str8(String8 string, U32 radix); internal S32 s32_from_str8(String8 string, U32 radix); internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x); internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x); //- rjf: integer -> string internal String8 str8_from_memory_size(Arena *arena, U64 size); internal String8 str8_from_count(Arena *arena, U64 count); internal String8 str8_from_bits_u32(Arena *arena, U32 x); internal String8 str8_from_bits_u64(Arena *arena, U64 x); internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator); internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator); //////////////////////////////// //~ rjf: String <=> Float Conversions internal F64 f64_from_str8(String8 string); //////////////////////////////// //~ rjf: String List Construction Functions internal String8Node *str8_list_push_node(String8List *list, String8Node *node); internal String8Node *str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string); internal String8Node *str8_list_push_node_front(String8List *list, String8Node *node); internal String8Node *str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string); internal String8Node *str8_list_push(Arena *arena, String8List *list, String8 string); internal String8Node *str8_list_push_front(Arena *arena, String8List *list, String8 string); internal void str8_list_concat_in_place(String8List *list, String8List *to_push); internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align); internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...); internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...); internal String8List str8_list_copy(Arena *arena, String8List *list); #define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero()) //////////////////////////////// //~ rjf: String Splitting & Joining internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags); internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags); internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params); //////////////////////////////// //~ rjf: Basic Data Stringification Helpers internal String8List numeric_str8_list_from_data(Arena *arena, U32 radix, String8 data, U64 stride); //////////////////////////////// //~ rjf; String Arrays internal String8Array str8_array_zero(void); internal String8Array str8_array_from_list(Arena *arena, String8List *list); internal String8Array str8_array_reserve(Arena *arena, U64 count); internal String8Array str8_array_copy(Arena *arena, String8Array array); //////////////////////////////// //~ rjf: String <-> Version Helpers internal U64 version_from_str8(String8 string); internal String8 str8_from_version(Arena *arena, U64 version); //////////////////////////////// //~ rjf: String Path Helpers global read_only struct { String8 string; PathStyle path_style; } g_path_style_map[] = { { str8_lit_comp(""), PathStyle_Null }, { str8_lit_comp("relative"), PathStyle_Relative }, { str8_lit_comp("windows"), PathStyle_WindowsAbsolute }, { str8_lit_comp("unix"), PathStyle_UnixAbsolute }, { str8_lit_comp("system"), PathStyle_SystemAbsolute }, }; internal String8 str8_chop_last_slash(String8 string); internal String8 str8_skip_last_slash(String8 string); internal String8 str8_chop_last_dot(String8 string); internal String8 str8_skip_last_dot(String8 string); internal PathStyle path_style_from_str8(String8 string); internal String8List str8_split_path(Arena *arena, String8 string); internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style); internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style); internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string); //////////////////////////////// //~ rjf: Relative <-> Absolute Path internal String8 path_relative_dst_from_absolute_dst_src(Arena *arena, String8 dst, String8 src); internal String8 path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src); //////////////////////////////// //~ rjf: Path Normalization internal String8List path_normalized_list_from_string(Arena *arena, String8 path, PathStyle *style_out); internal String8 path_normalized_from_string(Arena *arena, String8 path); internal B32 path_match_normalized(String8 left, String8 right); //////////////////////////////// //~ rjf: Misc. Path Helpers internal PathStyle path_style_from_string(String8 string); internal String8 string_from_path_style(PathStyle style); internal String8 path_separator_string_from_style(PathStyle style); internal StringMatchFlags path_match_flags_from_os(OperatingSystem os); internal String8 path_convert_slashes(Arena *arena, String8 path, PathStyle path_style); internal String8 path_replace_file_extension(Arena *arena, String8 file_name, String8 ext); //////////////////////////////// //~ rjf: UTF-8 & UTF-16 Decoding/Encoding internal UnicodeDecode utf8_decode(U8 *str, U64 max); internal UnicodeDecode utf16_decode(U16 *str, U64 max); internal U32 utf8_encode(U8 *str, U32 codepoint); internal U32 utf16_encode(U16 *str, U32 codepoint); //////////////////////////////// //~ rjf: Unicode String Conversions internal String8 str8_from_16(Arena *arena, String16 in); internal String16 str16_from_8(Arena *arena, String8 in); internal String8 str8_from_32(Arena *arena, String32 in); internal String32 str32_from_8(Arena *arena, String8 in); //////////////////////////////// //~ rjf: Basic Types & Space Enum <-> String Conversions internal OperatingSystem operating_system_from_string(String8 string); internal String8 string_from_dimension(Dimension dimension); internal String8 string_from_side(Side side); internal String8 string_from_operating_system(OperatingSystem os); internal String8 string_from_arch(Arch arch); internal String8 string_from_week_day(WeekDay week_day); internal String8 string_from_month(Month month); internal String8 string_from_date_time(Arena *arena, DateTime *date_time); internal String8 string_from_date_time__file_name(Arena *arena, DateTime *date_time); internal String8 string_from_elapsed_time(Arena *arena, DateTime dt); //////////////////////////////// //~ rjf: String <-> Globally Unique IDs internal String8 string_from_guid(Arena *arena, Guid guid); internal B32 try_guid_from_string(String8 string, Guid *guid_out); internal Guid guid_from_string(String8 string); //////////////////////////////// //~ rjf: Basic Text Indentation internal String8 indented_from_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Text Escaping internal String8 escaped_from_raw_str8(Arena *arena, String8 string); internal String8 raw_from_escaped_str8(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Text Wrapping internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); //////////////////////////////// //~ rjf: String <-> Color internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba); internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string); //////////////////////////////// //~ rjf: String Fuzzy Matching internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack); internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src); //////////////////////////////// //~ NOTE(allen): Serialization Helpers internal void str8_serial_begin(Arena *arena, String8List *srl); internal String8 str8_serial_end(Arena *arena, String8List *srl); internal void str8_serial_write_to_dst(String8List *srl, void *out); internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align); internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size); internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size); internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first); internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x); internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x); internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x); internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x); internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str); internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str); internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str); #define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count)) #define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1) //////////////////////////////// //~ rjf: Deserialization Helpers internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity); internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val); internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size); internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out); internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out); internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out); #define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr))) #define str8_deserial_read_struct(string, off, ptr) str8_deserial_read_array(string, off, ptr, 1) //////////////////////////////// //~ rjf: Basic String Hashes internal U64 u64_hash_from_seed_str8(U64 seed, String8 string); internal U64 u64_hash_from_str8(String8 string); internal U128 u128_hash_from_seed_str8(U64 seed, String8 string); internal U128 u128_hash_from_str8(String8 string); #endif // BASE_STRINGS_H ================================================ FILE: src/base/base_thread_context.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Globals C_LINKAGE thread_static TCTX *tctx_thread_local; #if !BUILD_SUPPLEMENTARY_UNIT C_LINKAGE thread_static TCTX *tctx_thread_local = 0; #endif //////////////////////////////// //~ rjf: Thread Context Functions //- rjf: thread-context allocation & selection internal TCTX * tctx_alloc(void) { Arena *arena = arena_alloc(); TCTX *tctx = push_array(arena, TCTX, 1); tctx->arenas[0] = arena; tctx->arenas[1] = arena_alloc(); tctx->lane_ctx.lane_count = 1; return tctx; } internal void tctx_release(TCTX *tctx) { arena_release(tctx->arenas[1]); arena_release(tctx->arenas[0]); } internal void tctx_select(TCTX *tctx) { tctx_thread_local = tctx; } internal TCTX * tctx_selected(void) { return tctx_thread_local; } //- rjf: scratch arenas internal Arena * tctx_get_scratch(Arena **conflicts, U64 count) { TCTX *tctx = tctx_selected(); Arena *result = 0; Arena **arena_ptr = tctx->arenas; for(U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1) { Arena **conflict_ptr = conflicts; B32 has_conflict = 0; for(U64 j = 0; j < count; j += 1, conflict_ptr += 1) { if(*arena_ptr == *conflict_ptr) { has_conflict = 1; break; } } if(!has_conflict) { result = *arena_ptr; break; } } return result; } //- rjf: lane metadata internal LaneCtx tctx_set_lane_ctx(LaneCtx lane_ctx) { TCTX *tctx = tctx_selected(); LaneCtx restore = tctx->lane_ctx; tctx->lane_ctx = lane_ctx; return restore; } internal void tctx_lane_barrier_wait(void *broadcast_ptr, U64 broadcast_size, U64 broadcast_src_lane_idx) { ProfBeginFunction(); ProfColor(0x00000ff); TCTX *tctx = tctx_selected(); // rjf: doing broadcast -> copy to broadcast memory on source lane U64 broadcast_size_clamped = ClampTop(broadcast_size, sizeof(tctx->lane_ctx.broadcast_memory[0])); if(broadcast_ptr != 0 && lane_idx() == broadcast_src_lane_idx) { MemoryCopy(tctx->lane_ctx.broadcast_memory, broadcast_ptr, broadcast_size_clamped); } // rjf: all cases: barrier os_barrier_wait(tctx->lane_ctx.barrier); // rjf: doing broadcast -> copy from broadcast memory on destination lanes if(broadcast_ptr != 0 && lane_idx() != broadcast_src_lane_idx) { MemoryCopy(broadcast_ptr, tctx->lane_ctx.broadcast_memory, broadcast_size_clamped); } // rjf: doing broadcast -> barrier on all lanes if(broadcast_ptr != 0) { os_barrier_wait(tctx->lane_ctx.barrier); } ProfEnd(); } //- rjf: thread names internal void tctx_set_thread_name(String8 string) { TCTX *tctx = tctx_selected(); U64 size = ClampTop(string.size, sizeof(tctx->thread_name)); MemoryCopy(tctx->thread_name, string.str, size); tctx->thread_name_size = size; } internal String8 tctx_get_thread_name(void) { TCTX *tctx = tctx_selected(); String8 result = str8(tctx->thread_name, tctx->thread_name_size); return result; } //- rjf: thread source-locations internal void tctx_write_srcloc(char *file_name, U64 line_number) { TCTX *tctx = tctx_selected(); tctx->file_name = file_name; tctx->line_number = line_number; } internal void tctx_read_srcloc(char **file_name, U64 *line_number) { TCTX *tctx = tctx_selected(); *file_name = tctx->file_name; *line_number = tctx->line_number; } //////////////////////////////// //~ rjf: Touch Scope Functions internal Access * access_open(void) { if(tctx_thread_local->access_arena == 0) { tctx_thread_local->access_arena = arena_alloc(); } Access *access = tctx_thread_local->free_access; if(access != 0) { SLLStackPop(tctx_thread_local->free_access); } else { access = push_array_no_zero(tctx_thread_local->access_arena, Access, 1); } MemoryZeroStruct(access); return access; } internal void access_close(Access *access) { for(Touch *touch = access->top_touch, *next = 0; touch != 0; touch = next) { next = touch->next; ins_atomic_u64_dec_eval(&touch->pt->access_refcount); if(touch->cv.u64[0] != 0) { cond_var_broadcast(touch->cv); } SLLStackPush(tctx_thread_local->free_touch, touch); } SLLStackPush(tctx_thread_local->free_access, access); } internal void access_touch(Access *access, AccessPt *pt, CondVar cv) { ins_atomic_u64_inc_eval(&pt->access_refcount); ins_atomic_u64_eval_assign(&pt->last_time_touched_us, os_now_microseconds()); ins_atomic_u64_eval_assign(&pt->last_update_idx_touched, update_tick_idx()); Touch *touch = tctx_thread_local->free_touch; if(touch != 0) { SLLStackPop(tctx_thread_local->free_touch); } else { touch = push_array_no_zero(tctx_thread_local->access_arena, Touch, 1); } MemoryZeroStruct(touch); SLLStackPush(access->top_touch, touch); touch->cv = cv; touch->pt = pt; } //- rjf: access points internal B32 access_pt_is_expired_(AccessPt *pt, AccessPtExpireParams *params) { U64 access_refcount = ins_atomic_u64_eval(&pt->access_refcount); U64 last_time_touched_us = ins_atomic_u64_eval(&pt->last_time_touched_us); U64 last_update_idx_touched = ins_atomic_u64_eval(&pt->last_update_idx_touched); B32 result = (access_refcount == 0 && last_time_touched_us + params->time <= os_now_microseconds() && last_update_idx_touched + params->update_idxs <= update_tick_idx()); return result; } ================================================ FILE: src/base/base_thread_context.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_THREAD_CONTEXT_H #define BASE_THREAD_CONTEXT_H //////////////////////////////// //~ rjf: Lane Context typedef struct LaneCtx LaneCtx; struct LaneCtx { U64 lane_idx; U64 lane_count; Barrier barrier; U64 *broadcast_memory; }; //////////////////////////////// //~ rjf: Access Scopes typedef struct AccessPt AccessPt; struct AccessPt { U64 access_refcount; U64 last_time_touched_us; U64 last_update_idx_touched; }; typedef struct AccessPtExpireParams AccessPtExpireParams; struct AccessPtExpireParams { U64 time; U64 update_idxs; }; typedef struct Touch Touch; struct Touch { Touch *next; AccessPt *pt; CondVar cv; }; typedef struct Access Access; struct Access { Access *next; Touch *top_touch; }; //////////////////////////////// //~ rjf: Base Per-Thread State Bundle typedef struct TCTX TCTX; struct TCTX { // rjf: scratch arenas Arena *arenas[2]; // rjf: thread name U8 thread_name[32]; U64 thread_name_size; // rjf: lane context LaneCtx lane_ctx; // rjf: source location info char *file_name; U64 line_number; // rjf: accesses Arena *access_arena; Access *free_access; Touch *free_touch; // rjf: progress U64 *progress_counter_ptr; U64 *progress_target_ptr; }; //////////////////////////////// //~ rjf: Thread Context Functions //- rjf: thread-context allocation & selection internal TCTX *tctx_alloc(void); internal void tctx_release(TCTX *tctx); internal void tctx_select(TCTX *tctx); internal TCTX *tctx_selected(void); //- rjf: scratch arenas internal Arena *tctx_get_scratch(Arena **conflicts, U64 count); #define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count))) #define scratch_end(scratch) temp_end(scratch) //- rjf: lane metadata internal LaneCtx tctx_set_lane_ctx(LaneCtx lane_ctx); internal void tctx_lane_barrier_wait(void *broadcast_ptr, U64 broadcast_size, U64 broadcast_src_lane_idx); #define lane_idx() (tctx_selected()->lane_ctx.lane_idx) #define lane_count() (tctx_selected()->lane_ctx.lane_count) #define lane_from_task_idx(idx) ((idx)%lane_count()) #define lane_ctx(ctx) tctx_set_lane_ctx((ctx)) #define lane_sync() tctx_lane_barrier_wait(0, 0, 0) #define lane_sync_u64(ptr, src_lane_idx) tctx_lane_barrier_wait((ptr), sizeof(*(ptr)), (src_lane_idx)) #define lane_range(count) m_range_from_n_idx_m_count(lane_idx(), lane_count(), (count)) //- rjf: thread names internal void tctx_set_thread_name(String8 name); internal String8 tctx_get_thread_name(void); //- rjf: thread source-locations internal void tctx_write_srcloc(char *file_name, U64 line_number); internal void tctx_read_srcloc(char **file_name, U64 *line_number); #define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__) //- rjf: access scopes internal Access *access_open(void); internal void access_close(Access *access); internal void access_touch(Access *access, AccessPt *pt, CondVar cv); //- rjf: access points internal B32 access_pt_is_expired_(AccessPt *pt, AccessPtExpireParams *params); #define access_pt_is_expired(pt, ...) access_pt_is_expired_((pt), &(AccessPtExpireParams){.time = 2000000, .update_idxs = 2, __VA_ARGS__}) //- rjf: progress counters #define set_progress_ptr(ptr) (tctx_selected()->progress_counter_ptr = (ptr)) #define set_progress_target_ptr(ptr) (tctx_selected()->progress_target_ptr = (ptr)) #define set_progress(val) (tctx_selected()->progress_counter_ptr ? ins_atomic_u64_eval_assign(tctx_selected()->progress_counter_ptr, (val)) : (void)0) #define add_progress(val) (tctx_selected()->progress_counter_ptr ? ins_atomic_u64_add_eval(tctx_selected()->progress_counter_ptr, (val)) : (void)0) #define set_progress_target(val) (tctx_selected()->progress_target_ptr ? ins_atomic_u64_eval_assign(tctx_selected()->progress_target_ptr, (val)) : (void)0) #endif // BASE_THREAD_CONTEXT_H ================================================ FILE: src/base/base_threads.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Thread Functions internal Thread thread_launch(ThreadEntryPointFunctionType *f, void *p) { Thread thread = os_thread_launch(f, p); return thread; } internal B32 thread_join(Thread thread, U64 endt_us) { B32 result = os_thread_join(thread, endt_us); return result; } internal void thread_detach(Thread thread) { os_thread_detach(thread); } //////////////////////////////// //~ rjf: Synchronization Primitive Functions //- rjf: recursive mutexes internal Mutex mutex_alloc(void) {return os_mutex_alloc();} internal void mutex_release(Mutex mutex) {os_mutex_release(mutex);} internal void mutex_take(Mutex mutex) {os_mutex_take(mutex);} internal void mutex_drop(Mutex mutex) {os_mutex_drop(mutex);} //- rjf: reader/writer mutexes internal RWMutex rw_mutex_alloc(void) {return os_rw_mutex_alloc();} internal void rw_mutex_release(RWMutex mutex) {os_rw_mutex_release(mutex);} internal void rw_mutex_take(RWMutex mutex, B32 write_mode) {os_rw_mutex_take(mutex, write_mode);} internal void rw_mutex_drop(RWMutex mutex, B32 write_mode) {os_rw_mutex_drop(mutex, write_mode);} //- rjf: condition variables internal CondVar cond_var_alloc(void) {return os_cond_var_alloc();} internal void cond_var_release(CondVar cv) {os_cond_var_release(cv);} internal B32 cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) {return os_cond_var_wait(cv, mutex, endt_us);} internal B32 cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us) {return os_cond_var_wait_rw(cv, mutex_rw, write_mode, endt_us);} internal void cond_var_signal(CondVar cv) {os_cond_var_signal(cv);} internal void cond_var_broadcast(CondVar cv) {os_cond_var_broadcast(cv);} //- rjf: cross-process semaphores internal Semaphore semaphore_alloc(U32 initial_count, U32 max_count, String8 name) {return os_semaphore_alloc(initial_count, max_count, name);} internal void semaphore_release(Semaphore semaphore) {os_semaphore_release(semaphore);} internal Semaphore semaphore_open(String8 name) {return os_semaphore_open(name);} internal void semaphore_close(Semaphore semaphore) {os_semaphore_close(semaphore);} internal B32 semaphore_take(Semaphore semaphore, U64 endt_us) {return os_semaphore_take(semaphore, endt_us);} internal void semaphore_drop(Semaphore semaphore) {os_semaphore_drop(semaphore);} //- rjf: barriers internal Barrier barrier_alloc(U64 count) {return os_barrier_alloc(count);} internal void barrier_release(Barrier barrier) {os_barrier_release(barrier);} internal void barrier_wait(Barrier barrier) {os_barrier_wait(barrier);} //////////////////////////////// //~ rjf: Table Stripe Functions internal StripeArray stripe_array_alloc(Arena *arena) { StripeArray array = {0}; array.count = os_get_system_info()->logical_processor_count; array.v = push_array(arena, Stripe, array.count); for EachIndex(idx, array.count) { array.v[idx].arena = arena_alloc(); array.v[idx].rw_mutex = rw_mutex_alloc(); array.v[idx].cv = cond_var_alloc(); } return array; } internal void stripe_array_release(StripeArray *stripes) { for EachIndex(idx, stripes->count) { arena_release(stripes->v[idx].arena); rw_mutex_release(stripes->v[idx].rw_mutex); cond_var_release(stripes->v[idx].cv); } } internal Stripe * stripe_from_slot_idx(StripeArray *stripes, U64 slot_idx) { Stripe *stripe = &stripes->v[slot_idx%stripes->count]; return stripe; } ================================================ FILE: src/base/base_threads.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_THREADS_H #define BASE_THREADS_H //////////////////////////////// //~ rjf: Thread Types typedef struct Thread Thread; struct Thread { U64 u64[1]; }; typedef void ThreadEntryPointFunctionType(void *p); //////////////////////////////// //~ rjf: Synchronization Primitive Types typedef struct Mutex Mutex; struct Mutex { U64 u64[1]; }; typedef struct RWMutex RWMutex; struct RWMutex { U64 u64[1]; }; typedef struct CondVar CondVar; struct CondVar { U64 u64[1]; }; typedef struct Semaphore Semaphore; struct Semaphore { U64 u64[1]; }; typedef struct Barrier Barrier; struct Barrier { U64 u64[1]; }; //////////////////////////////// //~ rjf: Table Stripes typedef struct Stripe Stripe; struct Stripe { Arena *arena; RWMutex rw_mutex; CondVar cv; void *free; }; typedef struct StripeArray StripeArray; struct StripeArray { Stripe *v; U64 count; }; //////////////////////////////// //~ rjf: Thread Functions internal Thread thread_launch(ThreadEntryPointFunctionType *f, void *p); internal B32 thread_join(Thread thread, U64 endt_us); internal void thread_detach(Thread thread); //////////////////////////////// //~ rjf: Synchronization Primitive Functions //- rjf: recursive mutexes internal Mutex mutex_alloc(void); internal void mutex_release(Mutex mutex); internal void mutex_take(Mutex mutex); internal void mutex_drop(Mutex mutex); //- rjf: reader/writer mutexes internal RWMutex rw_mutex_alloc(void); internal void rw_mutex_release(RWMutex mutex); internal void rw_mutex_take(RWMutex mutex, B32 write_mode); internal void rw_mutex_drop(RWMutex mutex, B32 write_mode); #define rw_mutex_take_r(m) rw_mutex_take((m), (0)) #define rw_mutex_take_w(m) rw_mutex_take((m), (1)) #define rw_mutex_drop_r(m) rw_mutex_drop((m), (0)) #define rw_mutex_drop_w(m) rw_mutex_drop((m), (1)) //- rjf: condition variables internal CondVar cond_var_alloc(void); internal void cond_var_release(CondVar cv); // returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout internal B32 cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us); internal B32 cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us); #define cond_var_wait_rw_r(cv, m, endt) cond_var_wait_rw((cv), (m), (0), (endt)) #define cond_var_wait_rw_w(cv, m, endt) cond_var_wait_rw((cv), (m), (1), (endt)) internal void cond_var_signal(CondVar cv); internal void cond_var_broadcast(CondVar cv); //- rjf: cross-process semaphores internal Semaphore semaphore_alloc(U32 initial_count, U32 max_count, String8 name); internal void semaphore_release(Semaphore semaphore); internal Semaphore semaphore_open(String8 name); internal void semaphore_close(Semaphore semaphore); internal B32 semaphore_take(Semaphore semaphore, U64 endt_us); internal void semaphore_drop(Semaphore semaphore); //- rjf: barriers internal Barrier barrier_alloc(U64 count); internal void barrier_release(Barrier barrier); internal void barrier_wait(Barrier barrier); //- rjf: scope macros #define MutexScope(mutex) DeferLoop(mutex_take(mutex), mutex_drop(mutex)) #define RWMutexScope(mutex, write_mode) DeferLoop(rw_mutex_take((mutex), (write_mode)), rw_mutex_drop((mutex), (write_mode))) #define MutexScopeR(mutex) DeferLoop(rw_mutex_take_r(mutex), rw_mutex_drop_r(mutex)) #define MutexScopeW(mutex) DeferLoop(rw_mutex_take_w(mutex), rw_mutex_drop_w(mutex)) #define MutexScopeRWPromote(mutex) DeferLoop((rw_mutex_drop_r(mutex), rw_mutex_take_w(mutex)), (rw_mutex_drop_w(mutex), rw_mutex_take_r(mutex))) //////////////////////////////// //~ rjf: Table Stripe Functions internal StripeArray stripe_array_alloc(Arena *arena); internal void stripe_array_release(StripeArray *stripes); internal Stripe *stripe_from_slot_idx(StripeArray *stripes, U64 slot_idx); #endif // BASE_THREADS_H ================================================ FILE: src/codeview/codeview.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ Generated Code #include "generated/codeview.meta.c" //////////////////////////////// internal CV_Arch cv_arch_from_coff_machine(COFF_MachineType machine) { CV_Arch arch = 0; switch(machine) { case COFF_MachineType_X64: arch = CV_Arch_X64; break; case COFF_MachineType_X86: arch = CV_Arch_8086; break; case COFF_MachineType_Am33: arch = CV_Arch_AM33; break; case COFF_MachineType_Arm: NotImplemented; break; case COFF_MachineType_Arm64: arch = CV_Arch_ARM64; break; case COFF_MachineType_ArmNt: arch = CV_Arch_ARMNT; break; case COFF_MachineType_Ebc: arch = CV_Arch_EBC; break; case COFF_MachineType_Ia64: arch = CV_Arch_IA64; break; case COFF_MachineType_M32R: arch = CV_Arch_M32R; break; case COFF_MachineType_Mips16: arch = CV_Arch_MIPS16; break; case COFF_MachineType_MipsFpu: NotImplemented; break; case COFF_MachineType_MipsFpu16: NotImplemented; break; case COFF_MachineType_PowerPc: NotImplemented; break; case COFF_MachineType_PowerPcFp: arch = CV_Arch_PPCFP; break; case COFF_MachineType_R4000: NotImplemented; break; case COFF_MachineType_RiscV32: NotImplemented; break; case COFF_MachineType_RiscV64: NotImplemented; break; case COFF_MachineType_RiscV128: NotImplemented; break; case COFF_MachineType_Sh3: arch = CV_Arch_SH3; break; case COFF_MachineType_Sh3Dsp: arch = CV_Arch_SH3DSP; break; case COFF_MachineType_Sh4: arch = CV_Arch_SH4; break; case COFF_MachineType_Sh5: NotImplemented; break; case COFF_MachineType_Thumb: arch = CV_Arch_THUMB; break; case COFF_MachineType_WceMipsV2: NotImplemented; break; } return arch; } internal U64 cv_size_from_reg(CV_Arch arch, CV_Reg reg) { switch(arch) { case CV_Arch_8086: return cv_size_from_reg_x86(reg); case CV_Arch_X64 : return cv_size_from_reg_x64(reg); default: NotImplemented; } return 0; } internal B32 cv_is_reg_sp(CV_Arch arch, CV_Reg reg) { switch(arch) { case CV_Arch_8086: return reg == CV_Regx86_ESP; case CV_Arch_X64: return reg == CV_Regx64_RSP; default: NotImplemented; } return 0; } internal U64 cv_size_from_reg_x86(CV_Reg reg) { switch(reg) { #define X(NAME, CODE, RDI_NAME, BYTE_POS, BYTE_SIZE) case CV_Regx86_##NAME: return BYTE_SIZE; CV_Reg_X86_XList(X) #undef X } return 0; } internal U64 cv_size_from_reg_x64(CV_Reg reg) { switch(reg) { #define X(NAME, CODE, RDI_NAME, BYTE_POS, BYTE_SIZE) case CV_Regx64_##NAME: return BYTE_SIZE; CV_Reg_X64_XList(X) #undef X } return 0; } internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param) { CV_EncodedFramePtrReg fp_reg = 0; if(is_local_param) { fp_reg = CV_FrameprocFlags_Extract_ParamBasePointer(frameproc->flags); } else { fp_reg = CV_FrameprocFlags_Extract_LocalBasePointer(frameproc->flags); } return fp_reg; } internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg) { CV_Reg fp_reg = 0; switch (arch) { case CV_Arch_8086: { switch (encoded_reg) { case CV_EncodedFramePtrReg_None : break; case CV_EncodedFramePtrReg_StackPtr: AssertAlways(!"TODO: not tested, this is a guess"); fp_reg = CV_Regx86_ESP; break; case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx86_EBP; break; case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx86_EBX; break; default: InvalidPath; } } break; case CV_Arch_X64: { switch (encoded_reg) { case CV_EncodedFramePtrReg_None : break; case CV_EncodedFramePtrReg_StackPtr: fp_reg = CV_Regx64_RSP; break; case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx64_RBP; break; case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx64_R13; break; default: InvalidPath; } } break; default: NotImplemented; } return fp_reg; } internal U32 cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg) { U32 r = 0; switch (arch) { case CV_Arch_8086: { switch (encoded_frame_reg) { case 0: r = 0; break; case 1: r = CV_AllReg_VFRAME; break; case 2: r = CV_Regx86_EBP; break; case 3: r = CV_Regx86_EBX; break; } } break; case CV_Arch_X64: { switch (encoded_frame_reg) { case 0: r = 0; break; case 1: r = CV_Regx64_RSP; break; case 2: r = CV_Regx64_RBP; break; case 3: r = CV_Regx64_R13; break; } } break; default: NotImplemented; } return r; } //////////////////////////////// //~ rjf: Enum -> String internal String8 cv_string_from_inline_range_kind(CV_InlineRangeKind kind) { switch (kind) { case CV_InlineRangeKind_Expr: return str8_lit("Expr"); case CV_InlineRangeKind_Stmt: return str8_lit("Stmt"); } return str8_zero(); } internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source) { switch (ti_source) { case CV_TypeIndexSource_NULL: return str8_lit(""); break; case CV_TypeIndexSource_TPI: return str8_lit("TPI"); break; case CV_TypeIndexSource_IPI: return str8_lit("IPI"); break; case CV_TypeIndexSource_COUNT: break; } return str8_zero(); } internal String8 cv_string_from_language(CV_Language x) { switch (x) { #define X(_n,_i) case _i: return str8_lit(Stringify(_n)); CV_LanguageXList(X) #undef X } return str8_zero(); } internal String8 cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id) { String8 result = str8_zero(); switch (arch) { case CV_Arch_8086: { switch (id) { #define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break; CV_Reg_X86_XList(X) #undef X } } break; case CV_Arch_X64: { switch (id) { #define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break; CV_Reg_X64_XList(X) #undef X } } break; default: NotImplemented; break; } if (result.size == 0) { result = push_str8f(arena, "%x", id); } return result; } internal String8 cv_string_from_member_access(CV_MemberAccess x) { switch (x) { case CV_MemberAccess_Null: break; case CV_MemberAccess_Private: return str8_lit("Private"); case CV_MemberAccess_Protected: return str8_lit("Protected"); case CV_MemberAccess_Public: return str8_lit("Public"); } return str8_zero(); } internal String8 cv_string_from_method_prop(CV_MethodProp x) { switch (x) { case CV_MethodProp_Vanilla: return str8_lit("Vanilla"); case CV_MethodProp_Virtual: return str8_lit("Virtual"); case CV_MethodProp_Static: return str8_lit("Static"); case CV_MethodProp_Friend: return str8_lit("Friend"); case CV_MethodProp_Intro: return str8_lit("Intro"); case CV_MethodProp_PureVirtual: return str8_lit("PureVirtual"); case CV_MethodProp_PureIntro: return str8_lit("PureIntro"); } return str8_zero(); } internal String8 cv_string_from_hfa(CV_HFAKind x) { switch (x) { case CV_HFAKind_None: return str8_lit("None"); case CV_HFAKind_Float: return str8_lit("Float"); case CV_HFAKind_Double: return str8_lit("Double"); case CV_HFAKind_Other: return str8_lit("Other"); } return str8_zero(); } internal String8 cv_string_from_mcom(CV_MoComUDTKind x) { switch (x) { case CV_MoComUDTKind_None: return str8_lit("None"); case CV_MoComUDTKind_Ref: return str8_lit("Ref"); case CV_MoComUDTKind_Value: return str8_lit("Value"); case CV_MoComUDTKind_Interface: return str8_lit("Interface"); } return str8_zero(); } internal String8 cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x) { switch (x) { case CV_InlineBinaryAnnotation_Null: break; case CV_InlineBinaryAnnotation_CodeOffset: return str8_lit("CodeOffset"); case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: return str8_lit("ChangeCodeOffsetBase"); case CV_InlineBinaryAnnotation_ChangeCodeOffset: return str8_lit("ChangeCodeOffset"); case CV_InlineBinaryAnnotation_ChangeCodeLength: return str8_lit("ChangeCodeLength"); case CV_InlineBinaryAnnotation_ChangeFile: return str8_lit("ChangeFile"); case CV_InlineBinaryAnnotation_ChangeLineOffset: return str8_lit("ChangeLineOffset"); case CV_InlineBinaryAnnotation_ChangeLineEndDelta: return str8_lit("ChangeLineEndDelta"); case CV_InlineBinaryAnnotation_ChangeRangeKind: return str8_lit("ChangeRangeKind"); case CV_InlineBinaryAnnotation_ChangeColumnStart: return str8_lit("ChangeColumnStart"); case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: return str8_lit("ChangeColumnEndDelta"); case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: return str8_lit("ChangeCodeOffsetAndLineOffset"); case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: return str8_lit("ChangeCodeLengthAndCodeOffset"); case CV_InlineBinaryAnnotation_ChangeColumnEnd: return str8_lit("ChangeColumnEnd"); } return str8_zero(); } internal String8 cv_string_from_thunk_ordinal(CV_ThunkOrdinal x) { switch (x) { case CV_ThunkOrdinal_NoType: return str8_lit("NoType"); case CV_ThunkOrdinal_Adjustor: return str8_lit("Adjustor"); case CV_ThunkOrdinal_VCall: return str8_lit("VCall"); case CV_ThunkOrdinal_PCode: return str8_lit("PCode"); case CV_ThunkOrdinal_Load: return str8_lit("Load"); case CV_ThunkOrdinal_TrampIncremental: return str8_lit("TrampIncremental"); case CV_ThunkOrdinal_TrampBranchIsland: return str8_lit("TrampBranchIsland"); } return str8_zero(); } internal String8 cv_string_from_frame_cookie_kind(CV_FrameCookieKind x) { switch (x) { case CV_FrameCookieKind_Copy: return str8_lit("Copy"); case CV_FrameCookieKind_XorSP: return str8_lit("XorSP"); case CV_FrameCookieKind_XorBP: return str8_lit("XorR13"); } return str8_zero(); } internal String8 cv_string_from_generic_style(CV_GenericStyle x) { switch (x) { case CV_GenericStyle_VOID: return str8_lit("VOID"); case CV_GenericStyle_REG: return str8_lit("REG"); case CV_GenericStyle_ICAN: return str8_lit("ICAN"); case CV_GenericStyle_ICAF: return str8_lit("ICAF"); case CV_GenericStyle_IRAN: return str8_lit("IRAN"); case CV_GenericStyle_IRAF: return str8_lit("IRAF"); case CV_GenericStyle_UNUSED: return str8_lit("UNUSED"); } return str8_zero(); } internal String8 cv_string_from_trampoline_kind(CV_TrampolineKind x) { switch (x) { case CV_TrampolineKind_Incremental: return str8_lit("Incremental"); case CV_TrampolineKind_BranchIsland: return str8_lit("BranchIsland"); } return str8_zero(); } internal String8 cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x) { switch (x) { case CV_VirtualTableShape_Near: return str8_lit("Near"); case CV_VirtualTableShape_Far: return str8_lit("Far"); case CV_VirtualTableShape_Thin: return str8_lit("Thin"); case CV_VirtualTableShape_Outer: return str8_lit("Outer"); case CV_VirtualTableShape_Meta: return str8_lit("Meta"); case CV_VirtualTableShape_Near32: return str8_lit("Near32"); case CV_VirtualTableShape_Far32: return str8_lit("Far32"); } return str8_zero(); } internal String8 cv_string_from_call_kind(CV_CallKind x) { switch (x) { case CV_CallKind_NearC: return str8_lit("NearC"); case CV_CallKind_FarC: return str8_lit("FarC"); case CV_CallKind_NearPascal: return str8_lit("NearPascal"); case CV_CallKind_FarPascal: return str8_lit("FarPascal"); case CV_CallKind_NearFast: return str8_lit("NearFast"); case CV_CallKind_FarFast: return str8_lit("FarFast"); case CV_CallKind_UNUSED: return str8_lit("UNUSED"); case CV_CallKind_NearStd: return str8_lit("NearStd"); case CV_CallKind_FarStd: return str8_lit("FarStd"); case CV_CallKind_NearSys: return str8_lit("NearSys"); case CV_CallKind_FarSys: return str8_lit("FarSys"); case CV_CallKind_This: return str8_lit("This"); case CV_CallKind_Mips: return str8_lit("Mips"); case CV_CallKind_Generic: return str8_lit("Generic"); case CV_CallKind_Alpha: return str8_lit("Alpha"); case CV_CallKind_PPC: return str8_lit("PPC"); case CV_CallKind_HitachiSuperH: return str8_lit("HitachiSuperH"); case CV_CallKind_Arm: return str8_lit("Arm"); case CV_CallKind_AM33: return str8_lit("AM33"); case CV_CallKind_TriCore: return str8_lit("TriCore"); case CV_CallKind_HitachiSuperH5: return str8_lit("HitachiSuperH5"); case CV_CallKind_M32R: return str8_lit("M32R"); case CV_CallKind_Clr: return str8_lit("Clr"); case CV_CallKind_Inline: return str8_lit("Inline"); case CV_CallKind_NearVector: return str8_lit("NearVector"); } return str8_zero(); } internal String8 cv_string_from_member_pointer_kind(CV_MemberPointerKind x) { switch (x) { case CV_MemberPointerKind_Undef: return str8_lit("Undef"); case CV_MemberPointerKind_DataSingle: return str8_lit("DataSingle"); case CV_MemberPointerKind_DataMultiple: return str8_lit("DataMultiple"); case CV_MemberPointerKind_DataVirtual: return str8_lit("DataVirtual"); case CV_MemberPointerKind_DataGeneral: return str8_lit("DataGeneral"); case CV_MemberPointerKind_FuncSingle: return str8_lit("FuncSingle"); case CV_MemberPointerKind_FuncMultiple: return str8_lit("FuncMultiple"); case CV_MemberPointerKind_FuncGeneral: return str8_lit("FuncGeneral"); } return str8_zero(); } internal String8 cv_string_from_pointer_kind(CV_PointerKind x) { switch (x) { case CV_PointerKind_Near: return str8_lit("Near"); case CV_PointerKind_Far: return str8_lit("Far"); case CV_PointerKind_Huge: return str8_lit("Huge"); case CV_PointerKind_BaseSeg: return str8_lit("BaseSeg"); case CV_PointerKind_BaseVal: return str8_lit("BaseVal"); case CV_PointerKind_BaseSegVal: return str8_lit("BaseSegVal"); case CV_PointerKind_BaseAddr: return str8_lit("BaseAddr"); case CV_PointerKind_BaseSegAddr: return str8_lit("BaseSegAddr"); case CV_PointerKind_BaseType: return str8_lit("BaseType"); case CV_PointerKind_BaseSelf: return str8_lit("BaseSelf"); case CV_PointerKind_Near32: return str8_lit("Near32"); case CV_PointerKind_Far32: return str8_lit("Far32"); case CV_PointerKind_64: return str8_lit("64Bit"); } return str8_zero(); } internal String8 cv_string_from_pointer_mode(CV_PointerMode x) { switch (x) { case CV_PointerMode_Ptr: return str8_lit("Ptr"); case CV_PointerMode_LRef: return str8_lit("LRef"); case CV_PointerMode_PtrMem: return str8_lit("PtrMem"); case CV_PointerMode_PtrMethod: return str8_lit("PtrMethod"); case CV_PointerMode_RRef: return str8_lit("RRef"); } return str8_zero(); } internal String8 cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x) { switch (x) { case CV_C13ChecksumKind_Null: break; case CV_C13ChecksumKind_MD5: return str8_lit("MD5"); case CV_C13ChecksumKind_SHA1: return str8_lit("SHA1"); case CV_C13ChecksumKind_SHA256: return str8_lit("SHA256"); } return str8_zero(); } internal String8 cv_string_from_label_kind(Arena *arena, CV_LabelKind x) { switch (x) { case CV_LabelKind_Near: return str8_lit("Near"); case CV_LabelKind_Far: return str8_lit("Far"); } return push_str8f(arena, "%#x", x); } internal String8 cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x) { switch (x) { #define X(_N, _ID) case CV_C13SubSectionKind_##_N: return str8_lit(Stringify(_N)); CV_C13SubSectionKindXList(X) #undef X } return str8_zero(); } internal String8 cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_ModifierFlag_Const) { str8_list_pushf(scratch.arena, &list, "Const"); } if (x & CV_ModifierFlag_Volatile) { str8_list_pushf(scratch.arena, &list, "Volatile"); } if (x & CV_ModifierFlag_Unaligned) { str8_list_pushf(scratch.arena, &list, "Unaligned"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_PointerAttrib_IsFlat) { x &= ~CV_PointerAttrib_IsFlat; str8_list_pushf(scratch.arena, &list, "IsFlat"); } if (x & CV_PointerAttrib_Volatile) { x &= ~CV_PointerAttrib_Volatile; str8_list_pushf(scratch.arena, &list, "Volatile"); } if (x & CV_PointerAttrib_Const) { x &= ~CV_PointerAttrib_Const; str8_list_pushf(scratch.arena, &list, "Const"); } if (x & CV_PointerAttrib_Unaligned) { x &= ~CV_PointerAttrib_Unaligned; str8_list_pushf(scratch.arena, &list, "Unaligned"); } if (x & CV_PointerAttrib_Restricted) { x &= ~CV_PointerAttrib_Restricted; str8_list_pushf(scratch.arena, &list, "Restricted"); } if (x & CV_PointerAttrib_MOCOM) { x &= ~CV_PointerAttrib_MOCOM; str8_list_pushf(scratch.arena, &list, "MOCOM"); } if (x & CV_PointerAttrib_LRef) { x &= ~CV_PointerAttrib_LRef; str8_list_pushf(scratch.arena, &list, "LRef"); } if (x & CV_PointerAttrib_RRef) { x &= ~CV_PointerAttrib_RRef; str8_list_pushf(scratch.arena, &list, "RRef"); } CV_PointerKind kind = CV_PointerAttribs_Extract_Kind(x); CV_PointerMode mode = CV_PointerAttribs_Extract_Mode(x); U64 size = CV_PointerAttribs_Extract_Size(x); x &= ~(0x1f|(0x7<<5)|(0x3f<<13)); if (kind) { String8 kind_str = cv_string_from_pointer_kind(kind); str8_list_pushf(scratch.arena, &list, "Kind=%S", kind_str); } if (mode) { String8 mode_str = cv_string_from_pointer_mode(mode); str8_list_pushf(scratch.arena, &list, "Mode=%S", mode_str); } if (size) { str8_list_pushf(scratch.arena, &list, "Size=%llu", size); } if (x != 0) { str8_list_pushf(scratch.arena, &list, "Unknown=%x", x); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_FunctionAttrib_CxxReturnUDT) { str8_list_pushf(scratch.arena, &list, "CxxReturnUDT"); } if (x & CV_FunctionAttrib_Constructor) { str8_list_pushf(scratch.arena, &list, "Constructor"); } if (x & CV_FunctionAttrib_ConstructorVBase) { str8_list_pushf(scratch.arena, &list, "ConstructorVBase"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_export_flags(Arena *arena, CV_ExportFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_ExportFlag_Constant) { str8_list_pushf(scratch.arena, &list, "Constant"); } if (x & CV_ExportFlag_Data) { str8_list_pushf(scratch.arena, &list, "Data"); } if (x & CV_ExportFlag_Private) { str8_list_pushf(scratch.arena, &list, "Private"); } if (x & CV_ExportFlag_NoName) { str8_list_pushf(scratch.arena, &list, "NoName"); } if (x & CV_ExportFlag_Ordinal) { str8_list_pushf(scratch.arena, &list, "Ordinal"); } if (x & CV_ExportFlag_Forwarder) { str8_list_pushf(scratch.arena, &list, "Forwarder"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x) { Temp scratch = scratch_begin(&arena,1); String8List list = {0}; if (x & CV_SepcodeFlag_IsLexicalScope) { str8_list_pushf(scratch.arena, &list, "IsLexicalScope"); } if (x & CV_SepcodeFlag_ReturnsToParent) { str8_list_pushf(scratch.arena, &list, "ReturnsToParent"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_Pub32Flag_Code) { str8_list_pushf(scratch.arena, &list, "Code"); } if (x & CV_Pub32Flag_Function) { str8_list_pushf(scratch.arena, &list, "Function"); } if (x & CV_Pub32Flag_ManagedCode) { str8_list_pushf(scratch.arena, &list, "ManagedCode"); } if (x & CV_Pub32Flag_MSIL) { str8_list_pushf(scratch.arena, &list, "MSIL"); } String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_GenericFlags_CSTYLE) { str8_list_pushf(scratch.arena, &list, "CSTYLE"); } if (x & CV_GenericFlags_RSCLEAN) { str8_list_pushf(scratch.arena, &list, "RSCLEAN"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_FrameprocFlag_UsesAlloca) { str8_list_pushf(scratch.arena, &list, "UsesAlloca"); } if (x & CV_FrameprocFlag_UsesSetJmp) { str8_list_pushf(scratch.arena, &list, "UsesSetJmp"); } if (x & CV_FrameprocFlag_UsesLongJmp) { str8_list_pushf(scratch.arena, &list, "UsesLongJmp"); } if (x & CV_FrameprocFlag_UsesInlAsm) { str8_list_pushf(scratch.arena, &list, "UsesInlAsm"); } if (x & CV_FrameprocFlag_UsesEH) { str8_list_pushf(scratch.arena, &list, "UsesEH"); } if (x & CV_FrameprocFlag_Inline) { str8_list_pushf(scratch.arena, &list, "Inline"); } if (x & CV_FrameprocFlag_HasSEH) { str8_list_pushf(scratch.arena, &list, "HasSEH"); } if (x & CV_FrameprocFlag_Naked) { str8_list_pushf(scratch.arena, &list, "Naked"); } if (x & CV_FrameprocFlag_HasSecurityChecks) { str8_list_pushf(scratch.arena, &list, "HasSecurityChecks"); } if (x & CV_FrameprocFlag_AsyncEH) { str8_list_pushf(scratch.arena, &list, "AsyncEH"); } if (x & CV_FrameprocFlag_GSNoStackOrdering) { str8_list_pushf(scratch.arena, &list, "GSNoStackOrdering"); } if (x & CV_FrameprocFlag_WasInlined) { str8_list_pushf(scratch.arena, &list, "WasInlined"); } if (x & CV_FrameprocFlag_GSCheck) { str8_list_pushf(scratch.arena, &list, "GSCheck"); } if (x & CV_FrameprocFlag_SafeBuffers) { str8_list_pushf(scratch.arena, &list, "SafeBuffers"); } if (x & CV_FrameprocFlag_PogoOn) { str8_list_pushf(scratch.arena, &list, "PogoOn"); } if (x & CV_FrameprocFlag_PogoCountsValid) { str8_list_pushf(scratch.arena, &list, "PogoCountsValid"); } if (x & CV_FrameprocFlag_OptSpeed) { str8_list_pushf(scratch.arena, &list, "OptSpeed"); } if (x & CV_FrameprocFlag_HasCFG) { str8_list_pushf(scratch.arena, &list, "HasCFG"); } if (x & CV_FrameprocFlag_HasCFW) { str8_list_pushf(scratch.arena, &list, "HasCFW"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_type_props(Arena *arena, CV_TypeProps32 x) { Temp scratch = scratch_begin(&arena, 1); U32 hfa = CV_TypeProps_Extract_HFA(x); U32 mcom = CV_TypeProps_Extract_MOCOM(x); String8 hfa_str = cv_string_from_hfa(hfa); String8 mcom_str = cv_string_from_mcom(mcom); String8 flags_str; { String8List list = {0}; if (x & CV_TypeProp_Packed) { x &= ~CV_TypeProp_Packed; str8_list_pushf(scratch.arena, &list, "Packed"); } if (x & CV_TypeProp_HasConstructorsDestructors) { x &= ~CV_TypeProp_HasConstructorsDestructors; str8_list_pushf(scratch.arena, &list, "HasConstructorsDestructors"); } if (x & CV_TypeProp_OverloadedOperators) { x &= ~CV_TypeProp_OverloadedOperators; str8_list_pushf(scratch.arena, &list, "OverloadedOperators"); } if (x & CV_TypeProp_IsNested) { x &= ~CV_TypeProp_IsNested; str8_list_pushf(scratch.arena, &list, "IsNested"); } if (x & CV_TypeProp_ContainsNested) { x &= ~CV_TypeProp_ContainsNested; str8_list_pushf(scratch.arena, &list, "ContainsNested"); } if (x & CV_TypeProp_OverloadedAssignment) { x &= ~CV_TypeProp_OverloadedAssignment; str8_list_pushf(scratch.arena, &list, "OverloadedAssignment"); } if (x & CV_TypeProp_OverloadedCasting) { x &= ~CV_TypeProp_OverloadedCasting; str8_list_pushf(scratch.arena, &list, "OverloadedCasting"); } if (x & CV_TypeProp_FwdRef) { x &= ~CV_TypeProp_FwdRef; str8_list_pushf(scratch.arena, &list, "FwdRef"); } if (x & CV_TypeProp_Scoped) { x &= ~CV_TypeProp_Scoped; str8_list_pushf(scratch.arena, &list, "Scoped"); } if (x & CV_TypeProp_HasUniqueName) { x &= ~CV_TypeProp_HasUniqueName; str8_list_pushf(scratch.arena, &list, "HasUniqueName"); } if (x & CV_TypeProp_Sealed) { x &= ~CV_TypeProp_Sealed; str8_list_pushf(scratch.arena, &list, "Sealed"); } if (x & CV_TypeProp_Intrinsic) { x &= ~CV_TypeProp_Intrinsic; str8_list_pushf(scratch.arena, &list, "Intrinsic"); } if (x != 0) { str8_list_pushf(scratch.arena, &list, "%x", x); } flags_str = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ") }); if (hfa) { str8_list_pushf(scratch.arena, &list, "HFA = %S", hfa_str); } if (mcom) { str8_list_pushf(scratch.arena, &list, "MCOM = %S", mcom_str); } } String8 result = push_str8f(arena, "%S", flags_str); scratch_end(scratch); return result; } internal String8 cv_string_from_local_flags(Arena *arena, CV_LocalFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_LocalFlag_Param) { str8_list_pushf(scratch.arena, &list, "Param"); } if (x & CV_LocalFlag_AddrTaken) { str8_list_pushf(scratch.arena, &list, "AddrTaken"); } if (x & CV_LocalFlag_Compgen) { str8_list_pushf(scratch.arena, &list, "Compgen"); } if (x & CV_LocalFlag_Aggregate) { str8_list_pushf(scratch.arena, &list, "Aggregate"); } if (x & CV_LocalFlag_PartOfAggregate) { str8_list_pushf(scratch.arena, &list, "PartOfAggregate"); } if (x & CV_LocalFlag_Aliased) { str8_list_pushf(scratch.arena, &list, "Aliased"); } if (x & CV_LocalFlag_Alias) { str8_list_pushf(scratch.arena, &list, "Alias"); } if (x & CV_LocalFlag_Retval) { str8_list_pushf(scratch.arena, &list, "Retval"); } if (x & CV_LocalFlag_OptOut) { str8_list_pushf(scratch.arena, &list, "OptOut"); } if (x & CV_LocalFlag_Global) { str8_list_pushf(scratch.arena, &list, "Global"); } if (x & CV_LocalFlag_Static) { str8_list_pushf(scratch.arena, &list, "Static"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (x & CV_ProcFlag_NoFPO) { x &= ~CV_ProcFlag_NoFPO; str8_list_pushf(scratch.arena, &list, "NoFPO"); } if (x & CV_ProcFlag_IntReturn) { x &= ~CV_ProcFlag_IntReturn; str8_list_pushf(scratch.arena, &list, "IntReturn"); } if (x & CV_ProcFlag_FarReturn) { x &= ~CV_ProcFlag_FarReturn; str8_list_pushf(scratch.arena, &list, "FarReturn"); } if (x & CV_ProcFlag_NeverReturn) { x &= ~CV_ProcFlag_NeverReturn; str8_list_pushf(scratch.arena, &list, "NeverReturn"); } if (x & CV_ProcFlag_NotReached) { x &= ~CV_ProcFlag_NotReached; str8_list_pushf(scratch.arena, &list, "NotReached"); } if (x & CV_ProcFlag_CustomCall) { x &= ~CV_ProcFlag_CustomCall; str8_list_pushf(scratch.arena, &list, "CustomCall"); } if (x & CV_ProcFlag_NoInline) { x &= ~CV_ProcFlag_NoInline; str8_list_pushf(scratch.arena, &list, "NoInline"); } if (x & CV_ProcFlag_OptDbgInfo) { x &= ~CV_ProcFlag_OptDbgInfo; str8_list_pushf(scratch.arena, &list, "OptDbgInfo"); } if (x != 0) { str8_list_pushf(scratch.arena, &list, "%#x", x); } String8 result; if (list.node_count == 0) { result = str8_lit("None"); } else { result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); } temp_end(scratch); return result; } internal String8 cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x) { (void)arena; String8 result = str8_lit("None"); if (x == CV_RangeAttrib_Maybe) { result = str8_lit("Maybe"); } return result; } internal String8 cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x) { (void)arena; String8 result = str8_lit("None"); if (x == CV_DefrangeRegisterRelFlag_SpilledOutUDTMember) { result = str8_lit("SpilledOutUDTMember"); } return result; } internal String8 cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs attribs) { Temp scratch = scratch_begin(&arena, 1); U32 access = CV_FieldAttribs_Extract_Access(attribs); U32 mprop = CV_FieldAttribs_Extract_MethodProp(attribs); attribs &= ~(0x3 | 0x7); String8 access_str = cv_string_from_member_access(access); String8 mprop_str = cv_string_from_method_prop(mprop); String8List list = {0}; { if (attribs & CV_FieldAttrib_Pseudo) { attribs &= ~CV_FieldAttrib_Pseudo; str8_list_pushf(scratch.arena, &list, "Pseudo"); } if (attribs & CV_FieldAttrib_NoInherit) { attribs &= ~CV_FieldAttrib_NoInherit; str8_list_pushf(scratch.arena, &list, "NoInherit"); } if (attribs & CV_FieldAttrib_NoConstruct) { attribs &= ~CV_FieldAttrib_NoConstruct; str8_list_pushf(scratch.arena, &list, "NoConstruct"); } if (attribs & CV_FieldAttrib_CompilerGenated) { attribs &= ~CV_FieldAttrib_CompilerGenated; str8_list_pushf(scratch.arena, &list, "CompilerGenerated"); } if (attribs & CV_FieldAttrib_Sealed) { attribs &= ~CV_FieldAttrib_Sealed; str8_list_pushf(scratch.arena, &list, "Sealed"); } if (attribs) { str8_list_pushf(scratch.arena, &list, "Unknown: %x", attribs); } } if (access) { str8_list_pushf(scratch.arena, &list, "%S", access_str); } if (mprop) { str8_list_pushf(scratch.arena, &list, "%S", mprop_str); } String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype) { String8 result = str8_zero(); if (itype < min_itype) { String8 n = cv_type_name_from_basic_type((CV_BasicType)itype); if (n.size) { Temp scratch = scratch_begin(&arena, 1); U64 type = CV_BasicTypeFromTypeId(itype); char *type_str = "???"; switch (type) { case CV_BasicType_NOTYPE: type_str = "NOTYPE"; break; case CV_BasicType_ABS: type_str = "ABS"; break; case CV_BasicType_SEGMENT: type_str = "SEGMENT"; break; case CV_BasicType_VOID: type_str = "VOID"; break; case CV_BasicType_CURRENCY: type_str = "CURRENCY"; break; case CV_BasicType_NBASICSTR: type_str = "NBASICSTR"; break; case CV_BasicType_FBASICSTR: type_str = "FBASICSTR"; break; case CV_BasicType_NOTTRANS: type_str = "NOTTRANS"; break; case CV_BasicType_HRESULT: type_str = "HRESULT"; break; case CV_BasicType_CHAR: type_str = "CHAR"; break; case CV_BasicType_SHORT: type_str = "SHORT"; break; case CV_BasicType_LONG: type_str = "LONG"; break; case CV_BasicType_QUAD: type_str = "QUAD"; break; case CV_BasicType_OCT: type_str = "OCT"; break; case CV_BasicType_UCHAR: type_str = "UCHAR"; break; case CV_BasicType_USHORT: type_str = "USHORT"; break; case CV_BasicType_ULONG: type_str = "ULONG"; break; case CV_BasicType_UQUAD: type_str = "UQUAD"; break; case CV_BasicType_UOCT: type_str = "UOCT"; break; case CV_BasicType_BOOL8: type_str = "BOOL8"; break; case CV_BasicType_BOOL16: type_str = "BOOL16"; break; case CV_BasicType_BOOL32: type_str = "BOOL32"; break; case CV_BasicType_BOOL64: type_str = "BOOL64"; break; case CV_BasicType_FLOAT32: type_str = "FLOAT32"; break; case CV_BasicType_FLOAT64: type_str = "FLOAT64"; break; case CV_BasicType_FLOAT80: type_str = "FLOAT80"; break; case CV_BasicType_FLOAT128: type_str = "FLOAT128"; break; case CV_BasicType_FLOAT48: type_str = "FLOAT48"; break; case CV_BasicType_FLOAT32PP: type_str = "FLOAT32PP"; break; case CV_BasicType_FLOAT16: type_str = "FLOAT16"; break; case CV_BasicType_COMPLEX32: type_str = "COMPLEX32"; break; case CV_BasicType_COMPLEX64: type_str = "COMPLEX64"; break; case CV_BasicType_COMPLEX80: type_str = "COMPLEX80"; break; case CV_BasicType_COMPLEX128: type_str = "COMPLEX128"; break; case CV_BasicType_BIT: type_str = "BIT"; break; case CV_BasicType_PASCHAR: type_str = "PASCHAR"; break; case CV_BasicType_BOOL32FF: type_str = "BOOL32FF"; break; case CV_BasicType_INT8: type_str = "INT8"; break; case CV_BasicType_UINT8: type_str = "UINT8"; break; case CV_BasicType_RCHAR: type_str = "RCHAR"; break; case CV_BasicType_WCHAR: type_str = "WCHAR"; break; case CV_BasicType_INT16: type_str = "INT16"; break; case CV_BasicType_UINT16: type_str = "UINT16"; break; case CV_BasicType_INT32: type_str = "INT32"; break; case CV_BasicType_UINT32: type_str = "UINT32"; break; case CV_BasicType_INT64: type_str = "INT64"; break; case CV_BasicType_UINT64: type_str = "UINT64"; break; case CV_BasicType_INT128: type_str = "INT128"; break; case CV_BasicType_UINT128: type_str = "UINT128"; break; case CV_BasicType_CHAR16: type_str = "CHAR16"; break; case CV_BasicType_CHAR32: type_str = "CHAR32"; break; case CV_BasicType_CHAR8: type_str = "CHAR8"; break; case CV_BasicType_PTR: type_str = "PTR"; break; } U64 ptr = CV_BasicPointerKindFromTypeId(itype); char *ptr_str = ""; switch (ptr) { case 0x1: ptr_str = "P"; break; case 0x2: ptr_str = "PF"; break; case 0x3: ptr_str = "PH"; break; case 0x4: ptr_str = "32P"; break; case 0x5: ptr_str = "32PF"; break; case 0x6: ptr_str = "64P"; break; } n = upper_from_str8(scratch.arena, n); result = push_str8f(arena, "T_%s%s(%x)", ptr_str, type_str, itype); scratch_end(scratch); } else { result = push_str8f(arena, "%x", itype); } } else { result = push_str8f(arena, "%x", itype); } return result; } internal String8 cv_string_from_itemid(Arena *arena, CV_ItemId itemid) { String8 result = push_str8f(arena, "%x", itemid); return result; } internal String8 cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type) { String8 str = cv_string_from_sym_kind(symbol_type); String8 result = push_str8f(arena, "S_%S", str); return result; } internal String8 cv_string_from_symbol_kind(Arena *arena, CV_SymKind kind) { String8 str = cv_string_from_sym_kind(kind); String8 result = push_str8f(arena, "S_%S", str); return result; } internal String8 cv_string_from_leaf_name(Arena *arena, U32 leaf_type) { String8 str = cv_string_from_leaf_kind(leaf_type); String8 result = push_str8f(arena, "LF_%S", str); return result; } internal String8 cv_string_sec_off(Arena *arena, U32 sec, U32 off) { return push_str8f(arena, "%04x:%08x", sec, off); } ================================================ FILE: src/codeview/codeview.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_H #define CODEVIEW_H // https://github.com/microsoft/microsoft-pdb/blob/master/include/cvinfo.h //////////////////////////////// //~ rjf: CodeView Format Shared Types #define CV_MinComplexTypeIndex 0x1000 #define CV_TypeIndex_Max max_U32 typedef U32 CV_TypeIndex; typedef CV_TypeIndex CV_TypeId; typedef CV_TypeIndex CV_ItemId; #define CV_ModIndex_Max max_U16 #define CV_ModIndex_Invalid CV_ModIndex_Max typedef U16 CV_ModIndex; typedef U16 CV_SectionIndex; typedef U16 CV_Reg; read_only global CV_TypeId cv_type_id_variadic = 0xFFFFFFFF; //////////////////////////////// //~ rjf: Generated Code #include "generated/codeview.meta.h" //////////////////////////////// //~ Aligns #define CV_LeafAlign 4 #define CV_SymbolAlign 1 #define CV_C13SubSectionAlign 4 #define CV_FileCheckSumsAlign 4 //////////////////////////////// //~ rjf: Registers // X(NAME, CODE, (RDI_RegCode_X86) NAME, BYTE_POS, BYTE_SIZE) #define CV_Reg_X86_XList(X) \ X(NONE, 0, nil, 0, 0) \ X(AL, 1, eax, 0, 1) \ X(CL, 2, ecx, 0, 1) \ X(DL, 3, edx, 0, 1) \ X(BL, 4, ebx, 0, 1) \ X(AH, 5, eax, 1, 1) \ X(CH, 6, ecx, 1, 1) \ X(DH, 7, edx, 1, 1) \ X(BH, 8, ebx, 1, 1) \ X(AX, 9, eax, 0, 2) \ X(CX, 10, ecx, 0, 2) \ X(DX, 11, edx, 0, 2) \ X(BX, 12, ebx, 0, 2) \ X(SP, 13, esp, 0, 2) \ X(BP, 14, ebp, 0, 2) \ X(SI, 15, esi, 0, 2) \ X(DI, 16, edi, 0, 2) \ X(EAX, 17, eax, 0, 4) \ X(ECX, 18, ecx, 0, 4) \ X(EDX, 19, edx, 0, 4) \ X(EBX, 20, ebx, 0, 4) \ X(ESP, 21, esp, 0, 4) \ X(EBP, 22, ebp, 0, 4) \ X(ESI, 23, esi, 0, 4) \ X(EDI, 24, edi, 0, 4) \ X(ES, 25, es, 0, 2) \ X(CS, 26, cs, 0, 2) \ X(SS, 27, ss, 0, 2) \ X(DS, 28, ds, 0, 2) \ X(FS, 29, fs, 0, 2) \ X(GS, 30, gs, 0, 2) \ X(IP, 31, eip, 0, 2) \ X(FLAGS, 32, eflags, 0, 2) \ X(EIP, 33, eip, 0, 4) \ X(EFLAGS, 34, eflags, 0, 4) \ X(MM0, 146, fpr0, 0, 8) \ X(MM1, 147, fpr1, 0, 8) \ X(MM2, 148, fpr2, 0, 8) \ X(MM3, 149, fpr3, 0, 8) \ X(MM4, 150, fpr4, 0, 8) \ X(MM5, 151, fpr5, 0, 8) \ X(MM6, 152, fpr6, 0, 8) \ X(MM7, 153, fpr7, 0, 8) \ X(XMM0, 154, ymm0, 0, 16) \ X(XMM1, 155, ymm1, 0, 16) \ X(XMM2, 156, ymm2, 0, 16) \ X(XMM3, 157, ymm3, 0, 16) \ X(XMM4, 158, ymm4, 0, 16) \ X(XMM5, 159, ymm5, 0, 16) \ X(XMM6, 160, ymm6, 0, 16) \ X(XMM7, 161, ymm7, 0, 16) \ X(XMM00, 162, ymm0, 0, 4) \ X(XMM01, 163, ymm0, 4, 4) \ X(XMM02, 164, ymm0, 8, 4) \ X(XMM03, 165, ymm0, 12, 4) \ X(XMM10, 166, ymm1, 0, 4) \ X(XMM11, 167, ymm1, 4, 4) \ X(XMM12, 168, ymm1, 8, 4) \ X(XMM13, 169, ymm1, 12, 4) \ X(XMM20, 170, ymm2, 0, 4) \ X(XMM21, 171, ymm2, 4, 4) \ X(XMM22, 172, ymm2, 8, 4) \ X(XMM23, 173, ymm2, 12, 4) \ X(XMM30, 174, ymm3, 0, 4) \ X(XMM31, 175, ymm3, 4, 4) \ X(XMM32, 176, ymm3, 8, 4) \ X(XMM33, 177, ymm3, 12, 4) \ X(XMM40, 178, ymm4, 0, 4) \ X(XMM41, 179, ymm4, 4, 4) \ X(XMM42, 180, ymm4, 8, 4) \ X(XMM43, 181, ymm4, 12, 4) \ X(XMM50, 182, ymm5, 0, 4) \ X(XMM51, 183, ymm5, 4, 4) \ X(XMM52, 184, ymm5, 8, 4) \ X(XMM53, 185, ymm5, 12, 4) \ X(XMM60, 186, ymm6, 0, 4) \ X(XMM61, 187, ymm6, 4, 4) \ X(XMM62, 188, ymm6, 8, 4) \ X(XMM63, 189, ymm6, 12, 4) \ X(XMM70, 190, ymm7, 0, 4) \ X(XMM71, 191, ymm7, 4, 4) \ X(XMM72, 192, ymm7, 8, 4) \ X(XMM73, 193, ymm7, 12, 4) \ X(XMM0L, 194, ymm0, 0, 8) \ X(XMM1L, 195, ymm1, 0, 8) \ X(XMM2L, 196, ymm2, 0, 8) \ X(XMM3L, 197, ymm3, 0, 8) \ X(XMM4L, 198, ymm4, 0, 8) \ X(XMM5L, 199, ymm5, 0, 8) \ X(XMM6L, 200, ymm6, 0, 8) \ X(XMM7L, 201, ymm7, 0, 8) \ X(XMM0H, 202, ymm0, 8, 8) \ X(XMM1H, 203, ymm1, 8, 8) \ X(XMM2H, 204, ymm2, 8, 8) \ X(XMM3H, 205, ymm3, 8, 8) \ X(XMM4H, 206, ymm4, 8, 8) \ X(XMM5H, 207, ymm5, 8, 8) \ X(XMM6H, 208, ymm6, 8, 8) \ X(XMM7H, 209, ymm7, 8, 8) \ X(YMM0, 252, ymm0, 0, 32) \ X(YMM1, 253, ymm1, 0, 32) \ X(YMM2, 254, ymm2, 0, 32) \ X(YMM3, 255, ymm3, 0, 32) \ X(YMM4, 256, ymm4, 0, 32) \ X(YMM5, 257, ymm5, 0, 32) \ X(YMM6, 258, ymm6, 0, 32) \ X(YMM7, 259, ymm7, 0, 32) \ X(YMM0H, 260, ymm0, 16, 16) \ X(YMM1H, 261, ymm1, 16, 16) \ X(YMM2H, 262, ymm2, 16, 16) \ X(YMM3H, 263, ymm3, 16, 16) \ X(YMM4H, 264, ymm4, 16, 16) \ X(YMM5H, 265, ymm5, 16, 16) \ X(YMM6H, 266, ymm6, 16, 16) \ X(YMM7H, 267, ymm7, 16, 16) \ X(YMM0I0, 268, ymm0, 0, 8) \ X(YMM0I1, 269, ymm0, 8, 8) \ X(YMM0I2, 270, ymm0, 16, 8) \ X(YMM0I3, 271, ymm0, 24, 8) \ X(YMM1I0, 272, ymm1, 0, 8) \ X(YMM1I1, 273, ymm1, 8, 8) \ X(YMM1I2, 274, ymm1, 16, 8) \ X(YMM1I3, 275, ymm1, 24, 8) \ X(YMM2I0, 276, ymm2, 0, 8) \ X(YMM2I1, 277, ymm2, 8, 8) \ X(YMM2I2, 278, ymm2, 16, 8) \ X(YMM2I3, 279, ymm2, 24, 8) \ X(YMM3I0, 280, ymm3, 0, 8) \ X(YMM3I1, 281, ymm3, 8, 8) \ X(YMM3I2, 282, ymm3, 16, 8) \ X(YMM3I3, 283, ymm3, 24, 8) \ X(YMM4I0, 284, ymm4, 0, 8) \ X(YMM4I1, 285, ymm4, 8, 8) \ X(YMM4I2, 286, ymm4, 16, 8) \ X(YMM4I3, 287, ymm4, 24, 8) \ X(YMM5I0, 288, ymm5, 0, 8) \ X(YMM5I1, 289, ymm5, 8, 8) \ X(YMM5I2, 290, ymm5, 16, 8) \ X(YMM5I3, 291, ymm5, 24, 8) \ X(YMM6I0, 292, ymm6, 0, 8) \ X(YMM6I1, 293, ymm6, 8, 8) \ X(YMM6I2, 294, ymm6, 16, 8) \ X(YMM6I3, 295, ymm6, 24, 8) \ X(YMM7I0, 296, ymm7, 0, 8) \ X(YMM7I1, 297, ymm7, 8, 8) \ X(YMM7I2, 298, ymm7, 16, 8) \ X(YMM7I3, 299, ymm7, 24, 8) \ X(YMM0F0, 300, ymm0, 0, 4) \ X(YMM0F1, 301, ymm0, 4, 4) \ X(YMM0F2, 302, ymm0, 8, 4) \ X(YMM0F3, 303, ymm0, 12, 4) \ X(YMM0F4, 304, ymm0, 16, 4) \ X(YMM0F5, 305, ymm0, 20, 4) \ X(YMM0F6, 306, ymm0, 24, 4) \ X(YMM0F7, 307, ymm0, 28, 4) \ X(YMM1F0, 308, ymm1, 0, 4) \ X(YMM1F1, 309, ymm1, 4, 4) \ X(YMM1F2, 310, ymm1, 8, 4) \ X(YMM1F3, 311, ymm1, 12, 4) \ X(YMM1F4, 312, ymm1, 16, 4) \ X(YMM1F5, 313, ymm1, 20, 4) \ X(YMM1F6, 314, ymm1, 24, 4) \ X(YMM1F7, 315, ymm1, 28, 4) \ X(YMM2F0, 316, ymm2, 0, 4) \ X(YMM2F1, 317, ymm2, 4, 4) \ X(YMM2F2, 318, ymm2, 8, 4) \ X(YMM2F3, 319, ymm2, 12, 4) \ X(YMM2F4, 320, ymm2, 16, 4) \ X(YMM2F5, 321, ymm2, 20, 4) \ X(YMM2F6, 322, ymm2, 24, 4) \ X(YMM2F7, 323, ymm2, 28, 4) \ X(YMM3F0, 324, ymm3, 0, 4) \ X(YMM3F1, 325, ymm3, 4, 4) \ X(YMM3F2, 326, ymm3, 8, 4) \ X(YMM3F3, 327, ymm3, 12, 4) \ X(YMM3F4, 328, ymm3, 16, 4) \ X(YMM3F5, 329, ymm3, 20, 4) \ X(YMM3F6, 330, ymm3, 24, 4) \ X(YMM3F7, 331, ymm3, 28, 4) \ X(YMM4F0, 332, ymm4, 0, 4) \ X(YMM4F1, 333, ymm4, 4, 4) \ X(YMM4F2, 334, ymm4, 8, 4) \ X(YMM4F3, 335, ymm4, 12, 4) \ X(YMM4F4, 336, ymm4, 16, 4) \ X(YMM4F5, 337, ymm4, 20, 4) \ X(YMM4F6, 338, ymm4, 24, 4) \ X(YMM4F7, 339, ymm4, 28, 4) \ X(YMM5F0, 340, ymm5, 0, 4) \ X(YMM5F1, 341, ymm5, 4, 4) \ X(YMM5F2, 342, ymm5, 8, 4) \ X(YMM5F3, 343, ymm5, 12, 4) \ X(YMM5F4, 344, ymm5, 16, 4) \ X(YMM5F5, 345, ymm5, 20, 4) \ X(YMM5F6, 346, ymm5, 24, 4) \ X(YMM5F7, 347, ymm5, 28, 4) \ X(YMM6F0, 348, ymm6, 0, 4) \ X(YMM6F1, 349, ymm6, 4, 4) \ X(YMM6F2, 350, ymm6, 8, 4) \ X(YMM6F3, 351, ymm6, 12, 4) \ X(YMM6F4, 352, ymm6, 16, 4) \ X(YMM6F5, 353, ymm6, 20, 4) \ X(YMM6F6, 354, ymm6, 24, 4) \ X(YMM6F7, 355, ymm6, 28, 4) \ X(YMM7F0, 356, ymm7, 0, 4) \ X(YMM7F1, 357, ymm7, 4, 4) \ X(YMM7F2, 358, ymm7, 8, 4) \ X(YMM7F3, 359, ymm7, 12, 4) \ X(YMM7F4, 360, ymm7, 16, 4) \ X(YMM7F5, 361, ymm7, 20, 4) \ X(YMM7F6, 362, ymm7, 24, 4) \ X(YMM7F7, 363, ymm7, 28, 4) \ X(YMM0D0, 364, ymm0, 0, 8) \ X(YMM0D1, 365, ymm0, 8, 8) \ X(YMM0D2, 366, ymm0, 16, 8) \ X(YMM0D3, 367, ymm0, 24, 8) \ X(YMM1D0, 368, ymm1, 0, 8) \ X(YMM1D1, 369, ymm1, 8, 8) \ X(YMM1D2, 370, ymm1, 16, 8) \ X(YMM1D3, 371, ymm1, 24, 8) \ X(YMM2D0, 372, ymm2, 0, 8) \ X(YMM2D1, 373, ymm2, 8, 8) \ X(YMM2D2, 374, ymm2, 16, 8) \ X(YMM2D3, 375, ymm2, 24, 8) \ X(YMM3D0, 376, ymm3, 0, 8) \ X(YMM3D1, 377, ymm3, 8, 8) \ X(YMM3D2, 378, ymm3, 16, 8) \ X(YMM3D3, 379, ymm3, 24, 8) \ X(YMM4D0, 380, ymm4, 0, 8) \ X(YMM4D1, 381, ymm4, 8, 8) \ X(YMM4D2, 382, ymm4, 16, 8) \ X(YMM4D3, 383, ymm4, 24, 8) \ X(YMM5D0, 384, ymm5, 0, 8) \ X(YMM5D1, 385, ymm5, 8, 8) \ X(YMM5D2, 386, ymm5, 16, 8) \ X(YMM5D3, 387, ymm5, 24, 8) \ X(YMM6D0, 388, ymm6, 0, 8) \ X(YMM6D1, 389, ymm6, 8, 8) \ X(YMM6D2, 390, ymm6, 16, 8) \ X(YMM6D3, 391, ymm6, 24, 8) \ X(YMM7D0, 392, ymm7, 0, 8) \ X(YMM7D1, 393, ymm7, 8, 8) \ X(YMM7D2, 394, ymm7, 16, 8) \ X(YMM7D3, 395, ymm7, 24, 8) typedef U16 CV_Regx86; typedef enum CV_Regx86Enum { #define X(CVN,C,RDN,BP,BZ) CV_Regx86_##CVN = C, CV_Reg_X86_XList(X) #undef X } CV_Regx86Enum; // X(NAME, CODE, (RDI_RegisterCode_X64) NAME, BYTE_POS, BYTE_SIZE) #define CV_Reg_X64_XList(X) \ X(NONE, 0, nil, 0, 0) \ X(AL, 1, rax, 0, 1) \ X(CL, 2, rcx, 0, 1) \ X(DL, 3, rdx, 0, 1) \ X(BL, 4, rbx, 0, 1) \ X(AH, 5, rax, 1, 1) \ X(CH, 6, rcx, 1, 1) \ X(DH, 7, rdx, 1, 1) \ X(BH, 8, rbx, 1, 1) \ X(AX, 9, rax, 0, 2) \ X(CX, 10, rcx, 0, 2) \ X(DX, 11, rdx, 0, 2) \ X(BX, 12, rbx, 0, 2) \ X(SP, 13, rsp, 0, 2) \ X(BP, 14, rbp, 0, 2) \ X(SI, 15, rsi, 0, 2) \ X(DI, 16, rdi, 0, 2) \ X(EAX, 17, rax, 0, 4) \ X(ECX, 18, rcx, 0, 4) \ X(EDX, 19, rdx, 0, 4) \ X(EBX, 20, rbx, 0, 4) \ X(ESP, 21, rsp, 0, 4) \ X(EBP, 22, rbp, 0, 4) \ X(ESI, 23, rsi, 0, 4) \ X(EDI, 24, rdi, 0, 4) \ X(ES, 25, es, 0, 2) \ X(CS, 26, cs, 0, 2) \ X(SS, 27, ss, 0, 2) \ X(DS, 28, ds, 0, 2) \ X(FS, 29, fs, 0, 2) \ X(GS, 30, gs, 0, 2) \ X(FLAGS, 32, rflags, 0, 2) \ X(RIP, 33, rip, 0, 8) \ X(EFLAGS, 34, rflags, 0, 4) \ /* TODO: possibly missing control registers in x64 definitions? */ \ X(CR0, 80, nil, 0, 0) \ X(CR1, 81, nil, 0, 0) \ X(CR2, 82, nil, 0, 0) \ X(CR3, 83, nil, 0, 0) \ X(CR4, 84, nil, 0, 0) \ X(CR8, 88, nil, 0, 0) \ X(DR0, 90, dr0, 0, 4) \ X(DR1, 91, dr1, 0, 4) \ X(DR2, 92, dr2, 0, 4) \ X(DR3, 93, dr3, 0, 4) \ X(DR4, 94, dr4, 0, 4) \ X(DR5, 95, dr5, 0, 4) \ X(DR6, 96, dr6, 0, 4) \ X(DR7, 97, dr7, 0, 4) \ /* TODO: possibly missing debug registers 8-15 in x64 definitions? */ \ X(DR8, 98, nil, 0, 0) \ X(DR9, 99, nil, 0, 0) \ X(DR10, 100, nil, 0, 0) \ X(DR11, 101, nil, 0, 0) \ X(DR12, 102, nil, 0, 0) \ X(DR13, 103, nil, 0, 0) \ X(DR14, 104, nil, 0, 0) \ X(DR15, 105, nil, 0, 0) \ /* TODO: possibly missing ~whatever these are~ in x64 definitions? */ \ X(GDTR, 110, nil, 0, 0) \ X(GDTL, 111, nil, 0, 0) \ X(IDTR, 112, nil, 0, 0) \ X(IDTL, 113, nil, 0, 0) \ X(LDTR, 114, nil, 0, 0) \ X(TR, 115, nil, 0, 0) \ X(ST0, 128, st0, 0, 10) \ X(ST1, 129, st1, 0, 10) \ X(ST2, 130, st2, 0, 10) \ X(ST3, 131, st3, 0, 10) \ X(ST4, 132, st4, 0, 10) \ X(ST5, 133, st5, 0, 10) \ X(ST6, 134, st6, 0, 10) \ X(ST7, 135, st7, 0, 10) \ /* TODO: possibly missing these, or not sure how they map to our x64 definitions? */ \ X(CTRL, 136, nil, 0, 0) \ X(STAT, 137, nil, 0, 0) \ X(TAG, 138, nil, 0, 0) \ X(FPIP, 139, nil, 0, 0) \ X(FPCS, 140, nil, 0, 0) \ X(FPDO, 141, nil, 0, 0) \ X(FPDS, 142, nil, 0, 0) \ X(ISEM, 143, nil, 0, 0) \ X(FPEIP, 144, nil, 0, 0) \ X(FPEDO, 145, nil, 0, 0) \ X(MM0, 146, fpr0, 0, 8) \ X(MM1, 147, fpr1, 0, 8) \ X(MM2, 148, fpr2, 0, 8) \ X(MM3, 149, fpr3, 0, 8) \ X(MM4, 150, fpr4, 0, 8) \ X(MM5, 151, fpr5, 0, 8) \ X(MM6, 152, fpr6, 0, 8) \ X(MM7, 153, fpr7, 0, 8) \ X(XMM0, 154, zmm0, 0, 16) \ X(XMM1, 155, zmm1, 0, 16) \ X(XMM2, 156, zmm2, 0, 16) \ X(XMM3, 157, zmm3, 0, 16) \ X(XMM4, 158, zmm4, 0, 16) \ X(XMM5, 159, zmm5, 0, 16) \ X(XMM6, 160, zmm6, 0, 16) \ X(XMM7, 161, zmm7, 0, 16) \ X(XMM0_0, 162, zmm0, 0, 4) \ X(XMM0_1, 163, zmm0, 4, 4) \ X(XMM0_2, 164, zmm0, 8, 4) \ X(XMM0_3, 165, zmm0, 12, 4) \ X(XMM1_0, 166, zmm1, 0, 4) \ X(XMM1_1, 167, zmm1, 4, 4) \ X(XMM1_2, 168, zmm1, 8, 4) \ X(XMM1_3, 169, zmm1, 12, 4) \ X(XMM2_0, 170, zmm2, 0, 4) \ X(XMM2_1, 171, zmm2, 4, 4) \ X(XMM2_2, 172, zmm2, 8, 4) \ X(XMM2_3, 173, zmm2, 12, 4) \ X(XMM3_0, 174, zmm3, 0, 4) \ X(XMM3_1, 175, zmm3, 4, 4) \ X(XMM3_2, 176, zmm3, 8, 4) \ X(XMM3_3, 177, zmm3, 12, 4) \ X(XMM4_0, 178, zmm4, 0, 4) \ X(XMM4_1, 179, zmm4, 4, 4) \ X(XMM4_2, 180, zmm4, 8, 4) \ X(XMM4_3, 181, zmm4, 12, 4) \ X(XMM5_0, 182, zmm5, 0, 4) \ X(XMM5_1, 183, zmm5, 4, 4) \ X(XMM5_2, 184, zmm5, 8, 4) \ X(XMM5_3, 185, zmm5, 12, 4) \ X(XMM6_0, 186, zmm6, 0, 4) \ X(XMM6_1, 187, zmm6, 4, 4) \ X(XMM6_2, 188, zmm6, 8, 4) \ X(XMM6_3, 189, zmm6, 12, 4) \ X(XMM7_0, 190, zmm7, 0, 4) \ X(XMM7_1, 191, zmm7, 4, 4) \ X(XMM7_2, 192, zmm7, 8, 4) \ X(XMM7_3, 193, zmm7, 12, 4) \ X(XMM0L, 194, zmm0, 0, 8) \ X(XMM1L, 195, zmm1, 0, 8) \ X(XMM2L, 196, zmm2, 0, 8) \ X(XMM3L, 197, zmm3, 0, 8) \ X(XMM4L, 198, zmm4, 0, 8) \ X(XMM5L, 199, zmm5, 0, 8) \ X(XMM6L, 200, zmm6, 0, 8) \ X(XMM7L, 201, zmm7, 0, 8) \ X(XMM0H, 202, zmm0, 8, 8) \ X(XMM1H, 203, zmm1, 8, 8) \ X(XMM2H, 204, zmm2, 8, 8) \ X(XMM3H, 205, zmm3, 8, 8) \ X(XMM4H, 206, zmm4, 8, 8) \ X(XMM5H, 207, zmm5, 8, 8) \ X(XMM6H, 208, zmm6, 8, 8) \ X(XMM7H, 209, zmm7, 8, 8) \ X(MXCSR, 211, mxcsr, 0, 4) \ X(EMM0L, 220, zmm0, 0, 8) \ X(EMM1L, 221, zmm1, 0, 8) \ X(EMM2L, 222, zmm2, 0, 8) \ X(EMM3L, 223, zmm3, 0, 8) \ X(EMM4L, 224, zmm4, 0, 8) \ X(EMM5L, 225, zmm5, 0, 8) \ X(EMM6L, 226, zmm6, 0, 8) \ X(EMM7L, 227, zmm7, 0, 8) \ X(EMM0H, 228, zmm0, 8, 8) \ X(EMM1H, 229, zmm1, 8, 8) \ X(EMM2H, 230, zmm2, 8, 8) \ X(EMM3H, 231, zmm3, 8, 8) \ X(EMM4H, 232, zmm4, 8, 8) \ X(EMM5H, 233, zmm5, 8, 8) \ X(EMM6H, 234, zmm6, 8, 8) \ X(EMM7H, 235, zmm7, 8, 8) \ X(MM00, 236, fpr0, 0, 4) \ X(MM01, 237, fpr0, 4, 4) \ X(MM10, 238, fpr1, 0, 4) \ X(MM11, 239, fpr1, 4, 4) \ X(MM20, 240, fpr2, 0, 4) \ X(MM21, 241, fpr2, 4, 4) \ X(MM30, 242, fpr3, 0, 4) \ X(MM31, 243, fpr3, 4, 4) \ X(MM40, 244, fpr4, 0, 4) \ X(MM41, 245, fpr4, 4, 4) \ X(MM50, 246, fpr5, 0, 4) \ X(MM51, 247, fpr5, 4, 4) \ X(MM60, 248, fpr6, 0, 4) \ X(MM61, 249, fpr6, 4, 4) \ X(MM70, 250, fpr7, 0, 4) \ X(MM71, 251, fpr7, 4, 4) \ X(XMM8, 252, zmm8, 0, 16) \ X(XMM9, 253, zmm9, 0, 16) \ X(XMM10, 254, zmm10, 0, 16) \ X(XMM11, 255, zmm11, 0, 16) \ X(XMM12, 256, zmm12, 0, 16) \ X(XMM13, 257, zmm13, 0, 16) \ X(XMM14, 258, zmm14, 0, 16) \ X(XMM15, 259, zmm15, 0, 16) \ X(XMM8_0, 260, zmm8, 0, 16) \ X(XMM8_1, 261, zmm8, 4, 16) \ X(XMM8_2, 262, zmm8, 8, 16) \ X(XMM8_3, 263, zmm8, 12, 16) \ X(XMM9_0, 264, zmm9, 0, 4) \ X(XMM9_1, 265, zmm9, 4, 4) \ X(XMM9_2, 266, zmm9, 8, 4) \ X(XMM9_3, 267, zmm9, 12, 4) \ X(XMM10_0, 268, zmm10, 0, 4) \ X(XMM10_1, 269, zmm10, 4, 4) \ X(XMM10_2, 270, zmm10, 8, 4) \ X(XMM10_3, 271, zmm10, 12, 4) \ X(XMM11_0, 272, zmm11, 0, 4) \ X(XMM11_1, 273, zmm11, 4, 4) \ X(XMM11_2, 274, zmm11, 8, 4) \ X(XMM11_3, 275, zmm11, 12, 4) \ X(XMM12_0, 276, zmm12, 0, 4) \ X(XMM12_1, 277, zmm12, 4, 4) \ X(XMM12_2, 278, zmm12, 8, 4) \ X(XMM12_3, 279, zmm12, 12, 4) \ X(XMM13_0, 280, zmm13, 0, 4) \ X(XMM13_1, 281, zmm13, 4, 4) \ X(XMM13_2, 282, zmm13, 8, 4) \ X(XMM13_3, 283, zmm13, 12, 4) \ X(XMM14_0, 284, zmm14, 0, 4) \ X(XMM14_1, 285, zmm14, 4, 4) \ X(XMM14_2, 286, zmm14, 8, 4) \ X(XMM14_3, 287, zmm14, 12, 4) \ X(XMM15_0, 288, zmm15, 0, 4) \ X(XMM15_1, 289, zmm15, 4, 4) \ X(XMM15_2, 290, zmm15, 8, 4) \ X(XMM15_3, 291, zmm15, 12, 4) \ X(XMM8L, 292, zmm8, 0, 8) \ X(XMM9L, 293, zmm9, 0, 8) \ X(XMM10L, 294, zmm10, 0, 8) \ X(XMM11L, 295, zmm11, 0, 8) \ X(XMM12L, 296, zmm12, 0, 8) \ X(XMM13L, 297, zmm13, 0, 8) \ X(XMM14L, 298, zmm14, 0, 8) \ X(XMM15L, 299, zmm15, 0, 8) \ X(XMM8H, 300, zmm8, 8, 8) \ X(XMM9H, 301, zmm9, 8, 8) \ X(XMM10H, 302, zmm10, 8, 8) \ X(XMM11H, 303, zmm11, 8, 8) \ X(XMM12H, 304, zmm12, 8, 8) \ X(XMM13H, 305, zmm13, 8, 8) \ X(XMM14H, 306, zmm14, 8, 8) \ X(XMM15H, 307, zmm15, 8, 8) \ X(EMM8L, 308, zmm8, 0, 8) \ X(EMM9L, 309, zmm9, 0, 8) \ X(EMM10L, 310, zmm10, 0, 8) \ X(EMM11L, 311, zmm11, 0, 8) \ X(EMM12L, 312, zmm12, 0, 8) \ X(EMM13L, 313, zmm13, 0, 8) \ X(EMM14L, 314, zmm14, 0, 8) \ X(EMM15L, 315, zmm15, 0, 8) \ X(EMM8H, 316, zmm8, 8, 8) \ X(EMM9H, 317, zmm9, 8, 8) \ X(EMM10H, 318, zmm10, 8, 8) \ X(EMM11H, 319, zmm11, 8, 8) \ X(EMM12H, 320, zmm12, 8, 8) \ X(EMM13H, 321, zmm13, 8, 8) \ X(EMM14H, 322, zmm14, 8, 8) \ X(EMM15H, 323, zmm15, 8, 8) \ X(SIL, 324, rsi, 0, 1) \ X(DIL, 325, rdi, 0, 1) \ X(BPL, 326, rbp, 0, 1) \ X(SPL, 327, rsp, 0, 1) \ X(RAX, 328, rax, 0, 8) \ X(RBX, 329, rbx, 0, 8) \ X(RCX, 330, rcx, 0, 8) \ X(RDX, 331, rdx, 0, 8) \ X(RSI, 332, rsi, 0, 8) \ X(RDI, 333, rdi, 0, 8) \ X(RBP, 334, rbp, 0, 8) \ X(RSP, 335, rsp, 0, 8) \ X(R8, 336, r8, 0, 8) \ X(R9, 337, r9, 0, 8) \ X(R10, 338, r10, 0, 8) \ X(R11, 339, r11, 0, 8) \ X(R12, 340, r12, 0, 8) \ X(R13, 341, r13, 0, 8) \ X(R14, 342, r14, 0, 8) \ X(R15, 343, r15, 0, 8) \ X(R8B, 344, r8, 0, 1) \ X(R9B, 345, r9, 0, 1) \ X(R10B, 346, r10, 0, 1) \ X(R11B, 347, r11, 0, 1) \ X(R12B, 348, r12, 0, 1) \ X(R13B, 349, r13, 0, 1) \ X(R14B, 350, r14, 0, 1) \ X(R15B, 351, r15, 0, 1) \ X(R8W, 352, r8, 0, 2) \ X(R9W, 353, r9, 0, 2) \ X(R10W, 354, r10, 0, 2) \ X(R11W, 355, r11, 0, 2) \ X(R12W, 356, r12, 0, 2) \ X(R13W, 357, r13, 0, 2) \ X(R14W, 358, r14, 0, 2) \ X(R15W, 359, r15, 0, 2) \ X(R8D, 360, r8, 0, 4) \ X(R9D, 361, r9, 0, 4) \ X(R10D, 362, r10, 0, 4) \ X(R11D, 363, r11, 0, 4) \ X(R12D, 364, r12, 0, 4) \ X(R13D, 365, r13, 0, 4) \ X(R14D, 366, r14, 0, 4) \ X(R15D, 367, r15, 0, 4) \ X(YMM0, 368, zmm0, 0, 32) \ X(YMM1, 369, zmm1, 0, 32) \ X(YMM2, 370, zmm2, 0, 32) \ X(YMM3, 371, zmm3, 0, 32) \ X(YMM4, 372, zmm4, 0, 32) \ X(YMM5, 373, zmm5, 0, 32) \ X(YMM6, 374, zmm6, 0, 32) \ X(YMM7, 375, zmm7, 0, 32) \ X(YMM8, 376, zmm8, 0, 32) \ X(YMM9, 377, zmm9, 0, 32) \ X(YMM10, 378, zmm10, 0, 32) \ X(YMM11, 379, zmm11, 0, 32) \ X(YMM12, 380, zmm12, 0, 32) \ X(YMM13, 381, zmm13, 0, 32) \ X(YMM14, 382, zmm14, 0, 32) \ X(YMM15, 383, zmm15, 0, 32) \ X(YMM0H, 384, zmm0, 16, 32) \ X(YMM1H, 385, zmm1, 16, 32) \ X(YMM2H, 386, zmm2, 16, 32) \ X(YMM3H, 387, zmm3, 16, 32) \ X(YMM4H, 388, zmm4, 16, 32) \ X(YMM5H, 389, zmm5, 16, 32) \ X(YMM6H, 390, zmm6, 16, 32) \ X(YMM7H, 391, zmm7, 16, 32) \ X(YMM8H, 392, zmm8, 16, 32) \ X(YMM9H, 393, zmm9, 16, 32) \ X(YMM10H, 394, zmm10, 16, 32) \ X(YMM11H, 395, zmm11, 16, 32) \ X(YMM12H, 396, zmm12, 16, 32) \ X(YMM13H, 397, zmm13, 16, 32) \ X(YMM14H, 398, zmm14, 16, 32) \ X(YMM15H, 399, zmm15, 16, 32) \ X(XMM0IL, 400, zmm0, 0, 8) \ X(XMM1IL, 401, zmm1, 0, 8) \ X(XMM2IL, 402, zmm2, 0, 8) \ X(XMM3IL, 403, zmm3, 0, 8) \ X(XMM4IL, 404, zmm4, 0, 8) \ X(XMM5IL, 405, zmm5, 0, 8) \ X(XMM6IL, 406, zmm6, 0, 8) \ X(XMM7IL, 407, zmm7, 0, 8) \ X(XMM8IL, 408, zmm8, 0, 8) \ X(XMM9IL, 409, zmm9, 0, 8) \ X(XMM10IL, 410, zmm10, 0, 8) \ X(XMM11IL, 411, zmm11, 0, 8) \ X(XMM12IL, 412, zmm12, 0, 8) \ X(XMM13IL, 413, zmm13, 0, 8) \ X(XMM14IL, 414, zmm14, 0, 8) \ X(XMM15IL, 415, zmm15, 0, 8) \ X(XMM0IH, 416, zmm0, 8, 8) \ X(XMM1IH, 417, zmm1, 8, 8) \ X(XMM2IH, 418, zmm2, 8, 8) \ X(XMM3IH, 419, zmm3, 8, 8) \ X(XMM4IH, 420, zmm4, 8, 8) \ X(XMM5IH, 421, zmm5, 8, 8) \ X(XMM6IH, 422, zmm6, 8, 8) \ X(XMM7IH, 423, zmm7, 8, 8) \ X(XMM8IH, 424, zmm8, 8, 8) \ X(XMM9IH, 425, zmm9, 8, 8) \ X(XMM10IH, 426, zmm10, 8, 8) \ X(XMM11IH, 427, zmm11, 8, 8) \ X(XMM12IH, 428, zmm12, 8, 8) \ X(XMM13IH, 429, zmm13, 8, 8) \ X(XMM14IH, 430, zmm14, 8, 8) \ X(XMM15IH, 431, zmm15, 8, 8) \ X(YMM0I0, 432, zmm0, 0, 8) \ X(YMM0I1, 433, zmm0, 8, 8) \ X(YMM0I2, 434, zmm0, 16, 8) \ X(YMM0I3, 435, zmm0, 24, 8) \ X(YMM1I0, 436, zmm1, 0, 8) \ X(YMM1I1, 437, zmm1, 8, 8) \ X(YMM1I2, 438, zmm1, 16, 8) \ X(YMM1I3, 439, zmm1, 24, 8) \ X(YMM2I0, 440, zmm2, 0, 8) \ X(YMM2I1, 441, zmm2, 8, 8) \ X(YMM2I2, 442, zmm2, 16, 8) \ X(YMM2I3, 443, zmm2, 24, 8) \ X(YMM3I0, 444, zmm3, 0, 8) \ X(YMM3I1, 445, zmm3, 8, 8) \ X(YMM3I2, 446, zmm3, 16, 8) \ X(YMM3I3, 447, zmm3, 24, 8) \ X(YMM4I0, 448, zmm4, 0, 8) \ X(YMM4I1, 449, zmm4, 8, 8) \ X(YMM4I2, 450, zmm4, 16, 8) \ X(YMM4I3, 451, zmm4, 24, 8) \ X(YMM5I0, 452, zmm5, 0, 8) \ X(YMM5I1, 453, zmm5, 8, 8) \ X(YMM5I2, 454, zmm5, 16, 8) \ X(YMM5I3, 455, zmm5, 24, 8) \ X(YMM6I0, 456, zmm6, 0, 8) \ X(YMM6I1, 457, zmm6, 8, 8) \ X(YMM6I2, 458, zmm6, 16, 8) \ X(YMM6I3, 459, zmm6, 24, 8) \ X(YMM7I0, 460, zmm7, 0, 8) \ X(YMM7I1, 461, zmm7, 8, 8) \ X(YMM7I2, 462, zmm7, 16, 8) \ X(YMM7I3, 463, zmm7, 24, 8) \ X(YMM8I0, 464, zmm8, 0, 8) \ X(YMM8I1, 465, zmm8, 8, 8) \ X(YMM8I2, 466, zmm8, 16, 8) \ X(YMM8I3, 467, zmm8, 24, 8) \ X(YMM9I0, 468, zmm9, 0, 8) \ X(YMM9I1, 469, zmm9, 8, 8) \ X(YMM9I2, 470, zmm9, 16, 8) \ X(YMM9I3, 471, zmm9, 24, 8) \ X(YMM10I0, 472, zmm10, 0, 8) \ X(YMM10I1, 473, zmm10, 8, 8) \ X(YMM10I2, 474, zmm10, 16, 8) \ X(YMM10I3, 475, zmm10, 24, 8) \ X(YMM11I0, 476, zmm11, 0, 8) \ X(YMM11I1, 477, zmm11, 8, 8) \ X(YMM11I2, 478, zmm11, 16, 8) \ X(YMM11I3, 479, zmm11, 24, 8) \ X(YMM12I0, 480, zmm12, 0, 8) \ X(YMM12I1, 481, zmm12, 8, 8) \ X(YMM12I2, 482, zmm12, 16, 8) \ X(YMM12I3, 483, zmm12, 24, 8) \ X(YMM13I0, 484, zmm13, 0, 8) \ X(YMM13I1, 485, zmm13, 8, 8) \ X(YMM13I2, 486, zmm13, 16, 8) \ X(YMM13I3, 487, zmm13, 24, 8) \ X(YMM14I0, 488, zmm14, 0, 8) \ X(YMM14I1, 489, zmm14, 8, 8) \ X(YMM14I2, 490, zmm14, 16, 8) \ X(YMM14I3, 491, zmm14, 24, 8) \ X(YMM15I0, 492, zmm15, 0, 8) \ X(YMM15I1, 493, zmm15, 8, 8) \ X(YMM15I2, 494, zmm15, 16, 8) \ X(YMM15I3, 495, zmm15, 24, 8) \ X(YMM0F0, 496, zmm0, 0, 4) \ X(YMM0F1, 497, zmm0, 4, 4) \ X(YMM0F2, 498, zmm0, 8, 4) \ X(YMM0F3, 499, zmm0, 12, 4) \ X(YMM0F4, 500, zmm0, 16, 4) \ X(YMM0F5, 501, zmm0, 20, 4) \ X(YMM0F6, 502, zmm0, 24, 4) \ X(YMM0F7, 503, zmm0, 28, 4) \ X(YMM1F0, 504, zmm1, 0, 4) \ X(YMM1F1, 505, zmm1, 4, 4) \ X(YMM1F2, 506, zmm1, 8, 4) \ X(YMM1F3, 507, zmm1, 12, 4) \ X(YMM1F4, 508, zmm1, 16, 4) \ X(YMM1F5, 509, zmm1, 20, 4) \ X(YMM1F6, 510, zmm1, 24, 4) \ X(YMM1F7, 511, zmm1, 28, 4) \ X(YMM2F0, 512, zmm2, 0, 4) \ X(YMM2F1, 513, zmm2, 4, 4) \ X(YMM2F2, 514, zmm2, 8, 4) \ X(YMM2F3, 515, zmm2, 12, 4) \ X(YMM2F4, 516, zmm2, 16, 4) \ X(YMM2F5, 517, zmm2, 20, 4) \ X(YMM2F6, 518, zmm2, 24, 4) \ X(YMM2F7, 519, zmm2, 28, 4) \ X(YMM3F0, 520, zmm3, 0, 4) \ X(YMM3F1, 521, zmm3, 4, 4) \ X(YMM3F2, 522, zmm3, 8, 4) \ X(YMM3F3, 523, zmm3, 12, 4) \ X(YMM3F4, 524, zmm3, 16, 4) \ X(YMM3F5, 525, zmm3, 20, 4) \ X(YMM3F6, 526, zmm3, 24, 4) \ X(YMM3F7, 527, zmm3, 28, 4) \ X(YMM4F0, 528, zmm4, 0, 4) \ X(YMM4F1, 529, zmm4, 4, 4) \ X(YMM4F2, 530, zmm4, 8, 4) \ X(YMM4F3, 531, zmm4, 12, 4) \ X(YMM4F4, 532, zmm4, 16, 4) \ X(YMM4F5, 533, zmm4, 20, 4) \ X(YMM4F6, 534, zmm4, 24, 4) \ X(YMM4F7, 535, zmm4, 28, 4) \ X(YMM5F0, 536, zmm5, 0, 4) \ X(YMM5F1, 537, zmm5, 4, 4) \ X(YMM5F2, 538, zmm5, 8, 4) \ X(YMM5F3, 539, zmm5, 12, 4) \ X(YMM5F4, 540, zmm5, 16, 4) \ X(YMM5F5, 541, zmm5, 20, 4) \ X(YMM5F6, 542, zmm5, 24, 4) \ X(YMM5F7, 543, zmm5, 28, 4) \ X(YMM6F0, 544, zmm6, 0, 4) \ X(YMM6F1, 545, zmm6, 4, 4) \ X(YMM6F2, 546, zmm6, 8, 4) \ X(YMM6F3, 547, zmm6, 12, 4) \ X(YMM6F4, 548, zmm6, 16, 4) \ X(YMM6F5, 549, zmm6, 20, 4) \ X(YMM6F6, 550, zmm6, 24, 4) \ X(YMM6F7, 551, zmm6, 28, 4) \ X(YMM7F0, 552, zmm7, 0, 4) \ X(YMM7F1, 553, zmm7, 4, 4) \ X(YMM7F2, 554, zmm7, 8, 4) \ X(YMM7F3, 555, zmm7, 12, 4) \ X(YMM7F4, 556, zmm7, 16, 4) \ X(YMM7F5, 557, zmm7, 20, 4) \ X(YMM7F6, 558, zmm7, 24, 4) \ X(YMM7F7, 559, zmm7, 28, 4) \ X(YMM8F0, 560, zmm8, 0, 4) \ X(YMM8F1, 561, zmm8, 4, 4) \ X(YMM8F2, 562, zmm8, 8, 4) \ X(YMM8F3, 563, zmm8, 12, 4) \ X(YMM8F4, 564, zmm8, 16, 4) \ X(YMM8F5, 565, zmm8, 20, 4) \ X(YMM8F6, 566, zmm8, 24, 4) \ X(YMM8F7, 567, zmm8, 28, 4) \ X(YMM9F0, 568, zmm9, 0, 4) \ X(YMM9F1, 569, zmm9, 4, 4) \ X(YMM9F2, 570, zmm9, 8, 4) \ X(YMM9F3, 571, zmm9, 12, 4) \ X(YMM9F4, 572, zmm9, 16, 4) \ X(YMM9F5, 573, zmm9, 20, 4) \ X(YMM9F6, 574, zmm9, 24, 4) \ X(YMM9F7, 575, zmm9, 28, 4) \ X(YMM10F0, 576, zmm10, 0, 4) \ X(YMM10F1, 577, zmm10, 4, 4) \ X(YMM10F2, 578, zmm10, 8, 4) \ X(YMM10F3, 579, zmm10, 12, 4) \ X(YMM10F4, 580, zmm10, 16, 4) \ X(YMM10F5, 581, zmm10, 20, 4) \ X(YMM10F6, 582, zmm10, 24, 4) \ X(YMM10F7, 583, zmm10, 28, 4) \ X(YMM11F0, 584, zmm11, 0, 4) \ X(YMM11F1, 585, zmm11, 4, 4) \ X(YMM11F2, 586, zmm11, 8, 4) \ X(YMM11F3, 587, zmm11, 12, 4) \ X(YMM11F4, 588, zmm11, 16, 4) \ X(YMM11F5, 589, zmm11, 20, 4) \ X(YMM11F6, 590, zmm11, 24, 4) \ X(YMM11F7, 591, zmm11, 28, 4) \ X(YMM12F0, 592, zmm12, 0, 4) \ X(YMM12F1, 593, zmm12, 4, 4) \ X(YMM12F2, 594, zmm12, 8, 4) \ X(YMM12F3, 595, zmm12, 12, 4) \ X(YMM12F4, 596, zmm12, 16, 4) \ X(YMM12F5, 597, zmm12, 20, 4) \ X(YMM12F6, 598, zmm12, 24, 4) \ X(YMM12F7, 599, zmm12, 28, 4) \ X(YMM13F0, 600, zmm13, 0, 4) \ X(YMM13F1, 601, zmm13, 4, 4) \ X(YMM13F2, 602, zmm13, 8, 4) \ X(YMM13F3, 603, zmm13, 12, 4) \ X(YMM13F4, 604, zmm13, 16, 4) \ X(YMM13F5, 605, zmm13, 20, 4) \ X(YMM13F6, 606, zmm13, 24, 4) \ X(YMM13F7, 607, zmm13, 28, 4) \ X(YMM14F0, 608, zmm14, 0, 4) \ X(YMM14F1, 609, zmm14, 4, 4) \ X(YMM14F2, 610, zmm14, 8, 4) \ X(YMM14F3, 611, zmm14, 12, 4) \ X(YMM14F4, 612, zmm14, 16, 4) \ X(YMM14F5, 613, zmm14, 20, 4) \ X(YMM14F6, 614, zmm14, 24, 4) \ X(YMM14F7, 615, zmm14, 28, 4) \ X(YMM15F0, 616, zmm15, 0, 4) \ X(YMM15F1, 617, zmm15, 4, 4) \ X(YMM15F2, 618, zmm15, 8, 4) \ X(YMM15F3, 619, zmm15, 12, 4) \ X(YMM15F4, 620, zmm15, 16, 4) \ X(YMM15F5, 621, zmm15, 20, 4) \ X(YMM15F6, 622, zmm15, 24, 4) \ X(YMM15F7, 623, zmm15, 28, 4) \ X(YMM0D0, 624, zmm0, 0, 8) \ X(YMM0D1, 625, zmm0, 8, 8) \ X(YMM0D2, 626, zmm0, 16, 8) \ X(YMM0D3, 627, zmm0, 24, 8) \ X(YMM1D0, 628, zmm1, 0, 8) \ X(YMM1D1, 629, zmm1, 8, 8) \ X(YMM1D2, 630, zmm1, 16, 8) \ X(YMM1D3, 631, zmm1, 24, 8) \ X(YMM2D0, 632, zmm2, 0, 8) \ X(YMM2D1, 633, zmm2, 8, 8) \ X(YMM2D2, 634, zmm2, 16, 8) \ X(YMM2D3, 635, zmm2, 24, 8) \ X(YMM3D0, 636, zmm3, 0, 8) \ X(YMM3D1, 637, zmm3, 8, 8) \ X(YMM3D2, 638, zmm3, 16, 8) \ X(YMM3D3, 639, zmm3, 24, 8) \ X(YMM4D0, 640, zmm4, 0, 8) \ X(YMM4D1, 641, zmm4, 8, 8) \ X(YMM4D2, 642, zmm4, 16, 8) \ X(YMM4D3, 643, zmm4, 24, 8) \ X(YMM5D0, 644, zmm5, 0, 8) \ X(YMM5D1, 645, zmm5, 8, 8) \ X(YMM5D2, 646, zmm5, 16, 8) \ X(YMM5D3, 647, zmm5, 24, 8) \ X(YMM6D0, 648, zmm6, 0, 8) \ X(YMM6D1, 649, zmm6, 8, 8) \ X(YMM6D2, 650, zmm6, 16, 8) \ X(YMM6D3, 651, zmm6, 24, 8) \ X(YMM7D0, 652, zmm7, 0, 8) \ X(YMM7D1, 653, zmm7, 8, 8) \ X(YMM7D2, 654, zmm7, 16, 8) \ X(YMM7D3, 655, zmm7, 24, 8) \ X(YMM8D0, 656, zmm8, 0, 8) \ X(YMM8D1, 657, zmm8, 8, 8) \ X(YMM8D2, 658, zmm8, 16, 8) \ X(YMM8D3, 659, zmm8, 24, 8) \ X(YMM9D0, 660, zmm9, 0, 8) \ X(YMM9D1, 661, zmm9, 8, 8) \ X(YMM9D2, 662, zmm9, 16, 8) \ X(YMM9D3, 663, zmm9, 24, 8) \ X(YMM10D0, 664, zmm10, 0, 8) \ X(YMM10D1, 665, zmm10, 8, 8) \ X(YMM10D2, 666, zmm10, 16, 8) \ X(YMM10D3, 667, zmm10, 24, 8) \ X(YMM11D0, 668, zmm11, 0, 8) \ X(YMM11D1, 669, zmm11, 8, 8) \ X(YMM11D2, 670, zmm11, 16, 8) \ X(YMM11D3, 671, zmm11, 24, 8) \ X(YMM12D0, 672, zmm12, 0, 8) \ X(YMM12D1, 673, zmm12, 8, 8) \ X(YMM12D2, 674, zmm12, 16, 8) \ X(YMM12D3, 675, zmm12, 24, 8) \ X(YMM13D0, 676, zmm13, 0, 8) \ X(YMM13D1, 677, zmm13, 8, 8) \ X(YMM13D2, 678, zmm13, 16, 8) \ X(YMM13D3, 679, zmm13, 24, 8) \ X(YMM14D0, 680, zmm14, 0, 8) \ X(YMM14D1, 681, zmm14, 8, 8) \ X(YMM14D2, 682, zmm14, 16, 8) \ X(YMM14D3, 683, zmm14, 24, 8) \ X(YMM15D0, 684, zmm15, 0, 8) \ X(YMM15D1, 685, zmm15, 8, 8) \ X(YMM15D2, 686, zmm15, 16, 8) \ X(YMM15D3, 687, zmm15, 24, 8) \ X(XMM16, 694, zmm16, 0, 16) \ X(XMM17, 695, zmm17, 0, 16) \ X(XMM18, 696, zmm18, 0, 16) \ X(XMM19, 697, zmm19, 0, 16) \ X(XMM20, 698, zmm20, 0, 16) \ X(XMM21, 699, zmm21, 0, 16) \ X(XMM22, 700, zmm22, 0, 16) \ X(XMM23, 701, zmm23, 0, 16) \ X(XMM24, 702, zmm24, 0, 16) \ X(XMM25, 703, zmm25, 0, 16) \ X(XMM26, 704, zmm26, 0, 16) \ X(XMM27, 705, zmm27, 0, 16) \ X(XMM28, 706, zmm28, 0, 16) \ X(XMM29, 707, zmm29, 0, 16) \ X(XMM30, 708, zmm30, 0, 16) \ X(XMM31, 709, zmm31, 0, 16) \ X(YMM16, 710, zmm16, 0, 32) \ X(YMM17, 711, zmm17, 0, 32) \ X(YMM18, 712, zmm18, 0, 32) \ X(YMM19, 713, zmm19, 0, 32) \ X(YMM20, 714, zmm20, 0, 32) \ X(YMM21, 715, zmm21, 0, 32) \ X(YMM22, 716, zmm22, 0, 32) \ X(YMM23, 717, zmm23, 0, 32) \ X(YMM24, 718, zmm24, 0, 32) \ X(YMM25, 719, zmm25, 0, 32) \ X(YMM26, 720, zmm26, 0, 32) \ X(YMM27, 721, zmm27, 0, 32) \ X(YMM28, 722, zmm28, 0, 32) \ X(YMM29, 723, zmm29, 0, 32) \ X(YMM30, 724, zmm30, 0, 32) \ X(YMM31, 725, zmm31, 0, 32) \ X(ZMM0, 726, zmm0, 0, 64) \ X(ZMM1, 727, zmm1, 0, 64) \ X(ZMM2, 728, zmm2, 0, 64) \ X(ZMM3, 729, zmm3, 0, 64) \ X(ZMM4, 730, zmm4, 0, 64) \ X(ZMM5, 731, zmm5, 0, 64) \ X(ZMM6, 732, zmm6, 0, 64) \ X(ZMM7, 733, zmm7, 0, 64) \ X(ZMM8, 734, zmm8, 0, 64) \ X(ZMM9, 735, zmm9, 0, 64) \ X(ZMM10, 736, zmm10, 0, 64) \ X(ZMM11, 737, zmm11, 0, 64) \ X(ZMM12, 738, zmm12, 0, 64) \ X(ZMM13, 739, zmm13, 0, 64) \ X(ZMM14, 740, zmm14, 0, 64) \ X(ZMM15, 741, zmm15, 0, 64) \ X(ZMM16, 742, zmm16, 0, 64) \ X(ZMM17, 743, zmm17, 0, 64) \ X(ZMM18, 744, zmm18, 0, 64) \ X(ZMM19, 745, zmm19, 0, 64) \ X(ZMM20, 746, zmm20, 0, 64) \ X(ZMM21, 747, zmm21, 0, 64) \ X(ZMM22, 748, zmm22, 0, 64) \ X(ZMM23, 749, zmm23, 0, 64) \ X(ZMM24, 750, zmm24, 0, 64) \ X(ZMM25, 751, zmm25, 0, 64) \ X(ZMM26, 752, zmm26, 0, 64) \ X(ZMM27, 753, zmm27, 0, 64) \ X(ZMM28, 754, zmm28, 0, 64) \ X(ZMM29, 755, zmm29, 0, 64) \ X(ZMM30, 756, zmm30, 0, 64) \ X(ZMM31, 757, zmm31, 0, 64) \ X(K0, 758, k0, 0, 8) \ X(K1, 759, k1, 0, 8) \ X(K2, 760, k2, 0, 8) \ X(K3, 761, k3, 0, 8) \ X(K4, 762, k4, 0, 8) \ X(K5, 763, k5, 0, 8) \ X(K6, 764, k6, 0, 8) \ X(K7, 765, k7, 0, 8) \ X(ZMM0H, 766, zmm0, 32, 32) \ X(ZMM1H, 767, zmm1, 32, 32) \ X(ZMM2H, 768, zmm2, 32, 32) \ X(ZMM3H, 769, zmm3, 32, 32) \ X(ZMM4H, 770, zmm4, 32, 32) \ X(ZMM5H, 771, zmm5, 32, 32) \ X(ZMM6H, 772, zmm6, 32, 32) \ X(ZMM7H, 773, zmm7, 32, 32) \ X(ZMM8H, 774, zmm8, 32, 32) \ X(ZMM9H, 775, zmm9, 32, 32) \ X(ZMM10H, 776, zmm10, 32, 32) \ X(ZMM11H, 777, zmm11, 32, 32) \ X(ZMM12H, 778, zmm12, 32, 32) \ X(ZMM13H, 779, zmm13, 32, 32) \ X(ZMM14H, 780, zmm14, 32, 32) \ X(ZMM15H, 781, zmm15, 32, 32) typedef U16 CV_Regx64; typedef enum CV_Regx64Enum { #define X(CVN,C,RDN,BP,BZ) CV_Regx64_##CVN = C, CV_Reg_X64_XList(X) #undef X } CV_Regx64Enum; #define CV_SignatureXList(X) \ X(C6, 0) \ X(C7, 1) \ X(C11, 2) \ X(C13, 4) \ X(RESERVED, 5) typedef U32 CV_Signature; typedef enum CV_SignatureEnum { #define X(N,c) CV_Signature_##N = c, CV_SignatureXList(X) #undef X } CV_SignatureEnum; #define CV_LanguageXList(X) \ X(C, 0x00) \ X(CXX, 0x01) \ X(FORTRAN, 0x02) \ X(MASM, 0x03) \ X(PASCAL, 0x04) \ X(BASIC, 0x05) \ X(COBOL, 0x06) \ X(LINK, 0x07) \ X(CVTRES, 0x08) \ X(CVTPGD, 0x09) \ X(CSHARP, 0x0A) \ X(VB, 0x0B) \ X(ILASM, 0x0C) \ X(JAVA, 0x0D) \ X(JSCRIPT, 0x0E) \ X(MSIL, 0x0F) \ X(HLSL, 0x10) typedef U16 CV_Language; typedef enum CV_LanguageEnum { #define X(N,c) CV_Language_##N = c, CV_LanguageXList(X) #undef X } CV_LanguageEnum; #pragma pack(push, 1) //////////////////////////////// //~ rjf: CodeView Format "Sym" and "Leaf" Header Type #define CV_LeafSize_Max max_U16 typedef U16 CV_LeafSize; #define CV_SymSize_Max max_U16 typedef U16 CV_SymSize; typedef struct CV_RecHeader CV_RecHeader; struct CV_RecHeader { U16 size; U16 kind; }; //////////////////////////////// //~ rjf: CodeView Format "Sym" Types // // (per-compilation-unit info, variables, procedures, etc.) // typedef U8 CV_ProcFlags; enum { CV_ProcFlag_NoFPO = (1 << 0), CV_ProcFlag_IntReturn = (1 << 1), CV_ProcFlag_FarReturn = (1 << 2), CV_ProcFlag_NeverReturn = (1 << 3), CV_ProcFlag_NotReached = (1 << 4), CV_ProcFlag_CustomCall = (1 << 5), CV_ProcFlag_NoInline = (1 << 6), CV_ProcFlag_OptDbgInfo = (1 << 7), }; typedef U16 CV_LocalFlags; enum { CV_LocalFlag_Param = (1 << 0), CV_LocalFlag_AddrTaken = (1 << 1), CV_LocalFlag_Compgen = (1 << 2), CV_LocalFlag_Aggregate = (1 << 3), CV_LocalFlag_PartOfAggregate = (1 << 4), CV_LocalFlag_Aliased = (1 << 5), CV_LocalFlag_Alias = (1 << 6), CV_LocalFlag_Retval = (1 << 7), CV_LocalFlag_OptOut = (1 << 8), CV_LocalFlag_Global = (1 << 9), CV_LocalFlag_Static = (1 << 10), }; typedef struct CV_LocalVarAttr CV_LocalVarAttr; struct CV_LocalVarAttr { U32 off; U16 seg; CV_LocalFlags flags; }; //- (SymKind: COMPILE) typedef U32 CV_CompileFlags; #define CV_CompileFlags_Extract_Language(f) (((f) )&0xFF) #define CV_CompileFlags_Extract_FloatPrec(f) (((f)>> 8)&0x03) #define CV_CompileFlags_Extract_FloatPkg(f) (((f)>>10)&0x03) #define CV_CompileFlags_Extract_AmbientData(f) (((f)>>12)&0x07) #define CV_CompileFlags_Extract_AmbientCode(f) (((f)>>15)&0x07) #define CV_CompileFlags_Extract_Mode(f) (((f)>>18)&0x01) typedef struct CV_SymCompile CV_SymCompile; struct CV_SymCompile { U8 machine; CV_CompileFlags flags; // U8[] ver_str (null terminated) }; //- (SymKind: SSEARCH) typedef struct CV_SymStartSearch CV_SymStartSearch; struct CV_SymStartSearch { U32 start_symbol; U16 segment; }; //- (SymKind: END) (empty) //- (SymKind: RETURN) typedef U8 CV_GenericStyle; typedef enum CV_GenericStyleEnum { CV_GenericStyle_VOID, CV_GenericStyle_REG, // "return data is in register" CV_GenericStyle_ICAN, // "indirect caller allocated near" CV_GenericStyle_ICAF, // "indirect caller allocated far" CV_GenericStyle_IRAN, // "indirect returnee allocated near" CV_GenericStyle_IRAF, // "indirect returnee allocated far" CV_GenericStyle_UNUSED, } CV_GenericStyleEnum; typedef U16 CV_GenericFlags; enum { CV_GenericFlags_CSTYLE = (1 << 0), CV_GenericFlags_RSCLEAN = (1 << 1), // "returnee stack cleanup" }; typedef struct CV_SymReturn CV_SymReturn; struct CV_SymReturn { CV_GenericFlags flags; CV_GenericStyle style; }; //- (SymKind: SLINK32) typedef struct CV_SymSLink32 CV_SymSLink32; struct CV_SymSLink32 { U32 frame_size; U32 offset; U16 reg; }; //- (SymKind: OEM) typedef struct CV_SymOEM CV_SymOEM; struct CV_SymOEM { Guid id; CV_TypeId itype; // padding align(4) }; //- (SymKind: VFTABLE32) typedef struct CV_SymVPath32 CV_SymVPath32; struct CV_SymVPath32 { CV_TypeId root; CV_TypeId path; U32 off; U16 seg; }; //- (SymKind: FRAMEPROC) typedef U8 CV_EncodedFramePtrReg; typedef enum CV_EncodedFramePtrRegEnum { CV_EncodedFramePtrReg_None, CV_EncodedFramePtrReg_StackPtr, CV_EncodedFramePtrReg_FramePtr, CV_EncodedFramePtrReg_BasePtr, } CV_EncodedFramePtrRegEnum; typedef U32 CV_FrameprocFlags; enum { CV_FrameprocFlag_UsesAlloca = (1 << 0), CV_FrameprocFlag_UsesSetJmp = (1 << 1), CV_FrameprocFlag_UsesLongJmp = (1 << 2), CV_FrameprocFlag_UsesInlAsm = (1 << 3), CV_FrameprocFlag_UsesEH = (1 << 4), CV_FrameprocFlag_Inline = (1 << 5), CV_FrameprocFlag_HasSEH = (1 << 6), CV_FrameprocFlag_Naked = (1 << 7), CV_FrameprocFlag_HasSecurityChecks = (1 << 8), CV_FrameprocFlag_AsyncEH = (1 << 9), CV_FrameprocFlag_GSNoStackOrdering = (1 << 10), CV_FrameprocFlag_WasInlined = (1 << 11), CV_FrameprocFlag_GSCheck = (1 << 12), CV_FrameprocFlag_SafeBuffers = (1 << 13), // LocalBasePointer: 14,15 // ParamBasePointer: 16,17 CV_FrameprocFlag_PogoOn = (1 << 18), CV_FrameprocFlag_PogoCountsValid = (1 << 19), CV_FrameprocFlag_OptSpeed = (1 << 20), CV_FrameprocFlag_HasCFG = (1 << 21), CV_FrameprocFlag_HasCFW = (1 << 22), }; #define CV_FrameprocFlags_Extract_LocalBasePointer(f) (((f) >> 14)&3) #define CV_FrameprocFlags_Extract_ParamBasePointer(f) (((f) >> 16)&3) typedef struct CV_SymFrameproc CV_SymFrameproc; struct CV_SymFrameproc { U32 frame_size; U32 pad_size; U32 pad_off; U32 save_reg_size; U32 eh_off; CV_SectionIndex eh_sec; CV_FrameprocFlags flags; }; //- (SymKind: ANNOTATION) typedef struct CV_SymAnnotation CV_SymAnnotation; struct CV_SymAnnotation { U32 off; U16 seg; U16 count; // U8[] annotation (null terminated) }; //- (SymKind: OBJNAME) typedef struct CV_SymObjName CV_SymObjName; struct CV_SymObjName { U32 sig; // U8[] name (null terminated) }; //- (SymKind: THUNK32) typedef U8 CV_ThunkOrdinal; typedef enum CV_ThunkOrdinalEnum { CV_ThunkOrdinal_NoType, CV_ThunkOrdinal_Adjustor, CV_ThunkOrdinal_VCall, CV_ThunkOrdinal_PCode, CV_ThunkOrdinal_Load, CV_ThunkOrdinal_TrampIncremental, CV_ThunkOrdinal_TrampBranchIsland, } CV_ThunkOrdinalEnum; typedef struct CV_SymThunk32 CV_SymThunk32; struct CV_SymThunk32 { U32 parent; U32 end; U32 next; U32 off; U16 sec; U16 len; CV_ThunkOrdinal ord; // U8[] name (null terminated) // U8[] variant (null terminated) }; //- (SymKind: BLOCK32) typedef struct CV_SymBlock32 CV_SymBlock32; struct CV_SymBlock32 { U32 parent; U32 end; U32 len; U32 off; U16 sec; // U8[] name (null terminated) }; //- (SymKind: LABEL32) typedef struct CV_SymLabel32 CV_SymLabel32; struct CV_SymLabel32 { U32 off; U16 sec; CV_ProcFlags flags; // U8[] name (null terminated) }; //- (SymKind: REGISTER) typedef struct CV_SymRegister CV_SymRegister; struct CV_SymRegister { CV_TypeId itype; U16 reg; // U8[] name (null terminated) }; //- (SymKind: CONSTANT) typedef struct CV_SymConstant CV_SymConstant; struct CV_SymConstant { CV_TypeId itype; // CV_Numeric num // U8[] name (null terminated) }; //- (SymKind: UDT) typedef struct CV_SymUDT CV_SymUDT; struct CV_SymUDT { CV_TypeId itype; // U8[] name (null terminated) }; //- (SymKind: MANYREG) typedef struct CV_SymManyreg CV_SymManyreg; struct CV_SymManyreg { CV_TypeId itype; U8 count; // U8[count] regs; }; //- (SymKind: BPREL32) typedef struct CV_SymBPRel32 CV_SymBPRel32; struct CV_SymBPRel32 { U32 off; CV_TypeId itype; // U8[] name (null terminated) }; //- (SymKind: LDATA32, GDATA32) typedef struct CV_SymData32 CV_SymData32; struct CV_SymData32 { CV_TypeId itype; U32 off; CV_SectionIndex sec; // U8[] name (null terminated) }; //- (SymKind: PUB32) typedef U32 CV_Pub32Flags; enum { CV_Pub32Flag_Code = (1 << 0), CV_Pub32Flag_Function = (1 << 1), CV_Pub32Flag_ManagedCode = (1 << 2), CV_Pub32Flag_MSIL = (1 << 3), }; typedef struct CV_SymPub32 CV_SymPub32; struct CV_SymPub32 { CV_Pub32Flags flags; U32 off; CV_SectionIndex sec; // U8[] name (null terminated) }; //- (SymKind: LPROC32, GPROC32) typedef struct CV_SymProc32 CV_SymProc32; struct CV_SymProc32 { U32 parent; U32 end; U32 next; U32 len; U32 dbg_start; U32 dbg_end; CV_TypeId itype; U32 off; U16 sec; CV_ProcFlags flags; // U8[] name (null terminated) }; //- (SymKind: REGREL32) typedef struct CV_SymRegrel32 CV_SymRegrel32; struct CV_SymRegrel32 { U32 reg_off; CV_TypeId itype; CV_Reg reg; // U8[] name (null terminated) }; //- (SymKind: LTHREAD32, GTHREAD32) typedef struct CV_SymThread32 CV_SymThread32; struct CV_SymThread32 { CV_TypeId itype; U32 tls_off; U16 tls_seg; // U8[] name (null terminated) }; //- (SymKind: COMPILE2) typedef U32 CV_Compile2Flags; #define CV_Compile2Flags_Extract_Language(f) (((f) )&0xFF) #define CV_Compile2Flags_Extract_EditAndContinue(f) (((f)>> 8)&0x01) #define CV_Compile2Flags_Extract_NoDbgInfo(f) (((f)>> 9)&0x01) #define CV_Compile2Flags_Extract_LTCG(f) (((f)>>10)&0x01) #define CV_Compile2Flags_Extract_NoDataAlign(f) (((f)>>11)&0x01) #define CV_Compile2Flags_Extract_ManagedPresent(f) (((f)>>12)&0x01) #define CV_Compile2Flags_Extract_SecurityChecks(f) (((f)>>13)&0x01) #define CV_Compile2Flags_Extract_HotPatch(f) (((f)>>14)&0x01) #define CV_Compile2Flags_Extract_CVTCIL(f) (((f)>>15)&0x01) #define CV_Compile2Flags_Extract_MSILModule(f) (((f)>>16)&0x01) typedef struct CV_SymCompile2 CV_SymCompile2; struct CV_SymCompile2 { CV_Compile2Flags flags; CV_Arch machine; U16 ver_fe_major; U16 ver_fe_minor; U16 ver_fe_build; U16 ver_major; U16 ver_minor; U16 ver_build; // U8[] ver_str (null terminated) }; //- (SymKind: MANYREG2) typedef struct CV_SymManyreg2 CV_SymManyreg2; struct CV_SymManyreg2 { CV_TypeId itype; U16 count; // U16[count] regs; }; //- (SymKind: LOCALSLOT) typedef struct CV_SymSlot CV_SymSlot; struct CV_SymSlot { U32 slot_index; CV_TypeId itype; // U8[] name (null terminated) }; //- (SymKind: MANFRAMEREL, ATTR_FRAMEREL) typedef struct CV_SymAttrFrameRel CV_SymAttrFrameRel; struct CV_SymAttrFrameRel { U32 off; CV_TypeId itype; CV_LocalVarAttr attr; // U8[] name (null terminated) }; //- (SymKind: MANREGISTER, ATTR_REGISTER) typedef struct CV_SymAttrReg CV_SymAttrReg; struct CV_SymAttrReg { CV_TypeId itype; CV_LocalVarAttr attr; U16 reg; // U8[] name (null terminated) }; //- (SymKind: MANMANYREG, ATTR_MANYREG) typedef struct CV_SymAttrManyReg CV_SymAttrManyReg; struct CV_SymAttrManyReg { CV_TypeId itype; CV_LocalVarAttr attr; U8 count; // U8[count] regs // U8[] name (null terminated) }; //- (SymKind: MANREGREL, ATTR_REGREL) typedef struct CV_SymAttrRegRel CV_SymAttrRegRel; struct CV_SymAttrRegRel { U32 off; CV_TypeId itype; U16 reg; CV_LocalVarAttr attr; // U8[] name (null terminated) }; //- (SymKind: UNAMESPACE) typedef struct CV_SymUNamespace CV_SymUNamespace; struct CV_SymUNamespace { // *** "dummy" is the first character of name - it should not be skipped! // *** It is placed here so the C compiler will accept this struct. // *** The actual fixed size part of this record has a size of zero. U8 dummy; // U8[] name (null terminated) }; //- (SymKind: PROCREF, DATAREF, LPROCREF) typedef struct CV_SymRef2 CV_SymRef2; struct CV_SymRef2 { U32 suc_name; U32 sym_off; CV_ModIndex imod; // U8[] name (null terminated) }; //- (SymKind: TRAMPOLINE) typedef U16 CV_TrampolineKind; typedef enum CV_TrampolineKindEnum { CV_TrampolineKind_Incremental, CV_TrampolineKind_BranchIsland, } CV_TrampolineKindEnum; typedef struct CV_SymTrampoline CV_SymTrampoline; struct CV_SymTrampoline { CV_TrampolineKind kind; U16 thunk_size; U32 thunk_sec_off; U32 target_sec_off; CV_SectionIndex thunk_sec; CV_SectionIndex target_sec; }; //- (SymKind: SEPCODE) typedef U32 CV_SepcodeFlags; enum { CV_SepcodeFlag_IsLexicalScope = (1 << 0), CV_SepcodeFlag_ReturnsToParent = (1 << 1), }; typedef struct CV_SymSepcode CV_SymSepcode; struct CV_SymSepcode { U32 parent; U32 end; U32 len; CV_SepcodeFlags flags; U32 sec_off; U32 sec_parent_off; U16 sec; U16 sec_parent; }; //- (SymKind: SECTION) typedef struct CV_SymSection CV_SymSection; struct CV_SymSection { U16 sec_index; U8 align; U8 pad; U32 rva; U32 size; U32 characteristics; // U8[] name (null terminated) }; //- (SymKind: COFFGROUP) typedef struct CV_SymCoffGroup CV_SymCoffGroup; struct CV_SymCoffGroup { U32 size; U32 characteristics; U32 off; U16 sec; // U8[] name (null terminated) }; //- (SymKind: EXPORT) typedef U16 CV_ExportFlags; enum { CV_ExportFlag_Constant = (1 << 0), CV_ExportFlag_Data = (1 << 1), CV_ExportFlag_Private = (1 << 2), CV_ExportFlag_NoName = (1 << 3), CV_ExportFlag_Ordinal = (1 << 4), CV_ExportFlag_Forwarder = (1 << 5), }; typedef struct CV_SymExport CV_SymExport; struct CV_SymExport { U16 ordinal; CV_ExportFlags flags; // U8[] name (null terminated) }; //- (SymKind: CALLSITEINFO) typedef struct CV_SymCallSiteInfo CV_SymCallSiteInfo; struct CV_SymCallSiteInfo { U32 off; U16 sec; U16 pad; CV_TypeId itype; }; //- (SymKind: FRAMECOOKIE) typedef U8 CV_FrameCookieKind; typedef enum CV_FrameCookieKindEnum { CV_FrameCookieKind_Copy, CV_FrameCookieKind_XorSP, CV_FrameCookieKind_XorBP, CV_FrameCookieKind_XorR13, } CV_FrameCookieKindEnum; typedef struct CV_SymFrameCookie CV_SymFrameCookie; struct CV_SymFrameCookie { U32 off; CV_Reg reg; CV_FrameCookieKind kind; U8 flags; }; //- (SymKind: DISCARDED) typedef U8 CV_DiscardedKind; typedef enum CV_DiscardedKindEnum { CV_DiscardedKind_Unknown, CV_DiscardedKind_NotSelected, CV_DiscardedKind_NotReferenced, } CV_DiscardedKindEnum; typedef struct CV_SymDiscarded CV_SymDiscarded; struct CV_SymDiscarded { CV_DiscardedKind kind; U32 file_id; U32 file_ln; // U8[] data (rest of data) }; //- (SymKind: COMPILE3) typedef U32 CV_Compile3Flags; enum { CV_Compile3Flag_EC = (1 << 8), CV_Compile3Flag_NoDbgInfo = (1 << 9), CV_Compile3Flag_LTCG = (1 << 10), CV_Compile3Flag_NoDataAlign = (1 << 11), CV_Compile3Flag_ManagedPresent = (1 << 12), CV_Compile3Flag_SecurityChecks = (1 << 13), CV_Compile3Flag_HotPatch = (1 << 14), CV_Compile3Flag_CVTCIL = (1 << 15), CV_Compile3Flag_MSILModule = (1 << 16), CV_Compile3Flag_SDL = (1 << 17), CV_Compile3Flag_PGO = (1 << 18), CV_Compile3Flag_EXP = (1 << 19), CV_Compile3Flag_Language_Shift = 0, CV_Compile3Flag_Language_Mask = 0xff, }; typedef U32 CV_Compile3Flags; #define CV_Compile3Flags_Extract_Language(f) (((f) )&0xFF) #define CV_Compile3Flags_Extract_EditAndContinue(f) (((f)>> 9)&0x01) #define CV_Compile3Flags_Extract_NoDbgInfo(f) (((f)>>10)&0x01) #define CV_Compile3Flags_Extract_LTCG(f) (((f)>>11)&0x01) #define CV_Compile3Flags_Extract_NoDataAlign(f) (((f)>>12)&0x01) #define CV_Compile3Flags_Extract_ManagedPresent(f) (((f)>>13)&0x01) #define CV_Compile3Flags_Extract_SecurityChecks(f) (((f)>>14)&0x01) #define CV_Compile3Flags_Extract_HotPatch(f) (((f)>>15)&0x01) #define CV_Compile3Flags_Extract_CVTCIL(f) (((f)>>16)&0x01) #define CV_Compile3Flags_Extract_MSILModule(f) (((f)>>17)&0x01) #define CV_Compile3Flags_Extract_SDL(f) (((f)>>18)&0x01) #define CV_Compile3Flags_Extract_PGO(f) (((f)>>19)&0x01) #define CV_Compile3Flags_Extract_EXP(f) (((f)>>20)&0x01) typedef struct CV_SymCompile3 CV_SymCompile3; struct CV_SymCompile3 { CV_Compile3Flags flags; CV_Arch machine; U16 ver_fe_major; U16 ver_fe_minor; U16 ver_fe_build; U16 ver_feqfe; U16 ver_major; U16 ver_minor; U16 ver_build; U16 ver_qfe; // U8[] ver_str (null terminated) }; //- (SymKind: ENVBLOCK) typedef struct CV_SymEnvBlock CV_SymEnvBlock; struct CV_SymEnvBlock { U8 flags; // U8[][] rgsz (sequence null terminated strings) }; //- (SymKind: LOCAL) typedef struct CV_SymLocal CV_SymLocal; struct CV_SymLocal { CV_TypeId itype; CV_LocalFlags flags; // U8[] name (null terminated) }; //- DEFRANGE typedef struct CV_LvarAddrRange CV_LvarAddrRange; struct CV_LvarAddrRange { U32 off; U16 sec; U16 len; }; typedef struct CV_LvarAddrGap CV_LvarAddrGap; struct CV_LvarAddrGap { U16 off; U16 len; }; typedef U16 CV_RangeAttribs; enum { CV_RangeAttrib_Maybe = (1 << 0), }; //- (SymKind: DEFRANGE) typedef struct CV_SymDefrange CV_SymDefrange; struct CV_SymDefrange { U32 program; CV_LvarAddrRange range; // variable-width: CV_LvarAddrGap gaps; }; //- (SymKind: DEFRANGE_SUBFIELD) typedef struct CV_SymDefrangeSubfield CV_SymDefrangeSubfield; struct CV_SymDefrangeSubfield { U32 program; U32 off_in_parent; CV_LvarAddrRange range; // CV_LvarAddrGap[] gaps (rest of data) }; //- (SymKind: DEFRANGE_REGISTER) typedef struct CV_SymDefrangeRegister CV_SymDefrangeRegister; struct CV_SymDefrangeRegister { CV_Reg reg; CV_RangeAttribs attribs; CV_LvarAddrRange range; // CV_LvarAddrGap[] gaps (rest of data) }; //- (SymKind: DEFRANGE_FRAMEPOINTER_REL) typedef struct CV_SymDefrangeFramepointerRel CV_SymDefrangeFramepointerRel; struct CV_SymDefrangeFramepointerRel { S32 off; CV_LvarAddrRange range; // CV_LvarAddrGap[] gaps (rest of data) }; //- (SymKind: DEFRANGE_SUBFIELD_REGISTER) #define CV_DefrangeSubfieldRegister_Extract_ParentOffset(x) ((x) & 0x1FFF) typedef struct CV_SymDefrangeSubfieldRegister CV_SymDefrangeSubfieldRegister; struct CV_SymDefrangeSubfieldRegister { CV_Reg reg; CV_RangeAttribs attribs; U32 field_offset; CV_LvarAddrRange range; // CV_LvarAddrGap[] gaps (rest of data) }; //- (SymKind: DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE) typedef struct CV_SymDefrangeFramepointerRelFullScope CV_SymDefrangeFramepointerRelFullScope; struct CV_SymDefrangeFramepointerRelFullScope { S32 off; }; //- (SymKind: DEFRANGE_REGISTER_REL) typedef U16 CV_DefrangeRegisterRelFlags; enum { CV_DefrangeRegisterRelFlag_SpilledOutUDTMember = (1 << 0), }; #define CV_DefrangeRegisterRelFlag_Extract_OffsetParent(f) (((f)>>4)&0xFFF) typedef struct CV_SymDefrangeRegisterRel CV_SymDefrangeRegisterRel; struct CV_SymDefrangeRegisterRel { CV_Reg reg; CV_DefrangeRegisterRelFlags flags; S32 reg_off; CV_LvarAddrRange range; // CV_LvarAddGap[] gaps (rest of data) }; //- (SymKind: BUILDINFO) typedef struct CV_SymBuildInfo CV_SymBuildInfo; struct CV_SymBuildInfo { CV_ItemId id; }; //- (SymKind: INLINESITE) typedef U32 CV_InlineBinaryAnnotation; typedef enum CV_InlineBinaryAnnotationEnum { CV_InlineBinaryAnnotation_Null, CV_InlineBinaryAnnotation_CodeOffset, CV_InlineBinaryAnnotation_ChangeCodeOffsetBase, CV_InlineBinaryAnnotation_ChangeCodeOffset, CV_InlineBinaryAnnotation_ChangeCodeLength, CV_InlineBinaryAnnotation_ChangeFile, CV_InlineBinaryAnnotation_ChangeLineOffset, CV_InlineBinaryAnnotation_ChangeLineEndDelta, CV_InlineBinaryAnnotation_ChangeRangeKind, CV_InlineBinaryAnnotation_ChangeColumnStart, CV_InlineBinaryAnnotation_ChangeColumnEndDelta, CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset, CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset, CV_InlineBinaryAnnotation_ChangeColumnEnd } CV_InlineBinaryAnnotationEnum; typedef U32 CV_InlineRangeKind; typedef enum CV_InlineRangeKindEnum { CV_InlineRangeKind_Expr, CV_InlineRangeKind_Stmt } CV_InlineRangeKindEnum; typedef struct CV_SymInlineSite CV_SymInlineSite; struct CV_SymInlineSite { U32 parent; U32 end; CV_ItemId inlinee; // U8 annotations[] (rest of data) }; //- (SymKind: INLINESITE2) typedef struct CV_SymInlineSite2 CV_SymInlineSite2; struct CV_SymInlineSite2 { U32 parent_off; U32 end_off; CV_ItemId inlinee; U32 invocations; // U8 annotations[] (rest of data) }; //- (SymKind: INLINESITE_END) (empty) //- (SymKind: FILESTATIC) typedef struct CV_SymFileStatic CV_SymFileStatic; struct CV_SymFileStatic { CV_TypeId itype; U32 mod_offset; CV_LocalFlags flags; // U8[] name (null terminated) }; //- (SymKind: ARMSWITCHTABLE) typedef U16 CV_ArmSwitchKind; typedef enum CV_ArmSwitchKindEnum { CV_ArmSwitchKind_INT1, CV_ArmSwitchKind_UINT1, CV_ArmSwitchKind_INT2, CV_ArmSwitchKind_UINT2, CV_ArmSwitchKind_INT4, CV_ArmSwitchKind_UINT5, CV_ArmSwitchKind_POINTER, CV_ArmSwitchKind_UINT1SHL1, CV_ArmSwitchKind_UINT2SHL1, CV_ArmSwitchKind_INT1SSHL1, CV_ArmSwitchKind_INT2SSHL1, } CV_ArmSwitchKindEnum; typedef struct CV_SymArmSwitchTable CV_SymArmSwitchTable; struct CV_SymArmSwitchTable { U32 off_base; U16 sec_base; CV_ArmSwitchKind kind; U32 off_branch; U32 off_table; U16 sec_branch; U16 sec_table; U32 entry_count; }; //- (SymKind: CALLEES, CALLERS) typedef struct CV_SymFunctionList CV_SymFunctionList; struct CV_SymFunctionList { U32 count; // CV_TypeId[count] funcs // U32[clamp(count, rest_of_data/4)] invocations }; //- (SymKind: POGODATA) typedef struct CV_SymPogoInfo CV_SymPogoInfo; struct CV_SymPogoInfo { U32 invocations; U64 dynamic_inst_count; U32 static_inst_count; U32 post_inline_static_inst_count; }; //- (SymKind: HEAPALLOCSITE) typedef struct CV_SymHeapAllocSite CV_SymHeapAllocSite; struct CV_SymHeapAllocSite { U32 off; U16 sec; U16 call_inst_len; CV_TypeId itype; }; //- (SymKind: MOD_TYPEREF) typedef U32 CV_ModTypeRefFlags; enum { CV_ModTypeRefFlag_None = (1 << 0), CV_ModTypeRefFlag_RefTMPCT = (1 << 1), CV_ModTypeRefFlag_OwnTMPCT = (1 << 2), CV_ModTypeRefFlag_OwnTMR = (1 << 3), CV_ModTypeRefFlag_OwnTM = (1 << 4), CV_ModTypeRefFlag_RefTM = (1 << 5), }; typedef struct CV_SymModTypeRef CV_SymModTypeRef; struct CV_SymModTypeRef { CV_ModTypeRefFlags flags; // contain stream number or module index depending on flags (undocumented) U32 word0; U32 word1; }; //- (SymKind: REF_MINIPDB) typedef U16 CV_RefMiniPdbFlags; enum { CV_RefMiniPdbFlag_Local = (1 << 0), CV_RefMiniPdbFlag_Data = (1 << 1), CV_RefMiniPdbFlag_UDT = (1 << 2), CV_RefMiniPdbFlag_Label = (1 << 3), CV_RefMiniPdbFlag_Const = (1 << 4), }; typedef struct CV_SymRefMiniPdb CV_SymRefMiniPdb; struct CV_SymRefMiniPdb { U32 data; CV_ModIndex imod; CV_RefMiniPdbFlags flags; // U8[] name (null terminated) }; //- (SymKind: FASTLINK) typedef U16 CV_FastLinkFlags; enum { CV_FastLinkFlag_IsGlobalData = (1 << 0), CV_FastLinkFlag_IsData = (1 << 1), CV_FastLinkFlag_IsUDT = (1 << 2), // 3 ~ unknown/unused CV_FastLinkFlag_IsConst = (1 << 4), // 5 ~ unknown/unused CV_FastLinkFlag_IsNamespace = (1 << 6), }; typedef struct CV_SymFastLink CV_SymFastLink; struct CV_SymFastLink { CV_TypeId itype; CV_FastLinkFlags flags; // U8[] name (null terminated) }; //- (SymKind: INLINEES) typedef struct CV_SymInlinees CV_SymInlinees; struct CV_SymInlinees { U32 count; // U32[count] desc; }; //////////////////////////////// //~ rjf: CodeView Format "Leaf" Types // // (type info) // #define CV_TypeId_Variadic 0 #define CV_BasicPointerKindXList(X) \ X(VALUE, 0x0) \ X(16BIT, 0x1) \ X(FAR_16BIT, 0x2) \ X(HUGE_16BIT, 0x3) \ X(32BIT, 0x4) \ X(16_32BIT, 0x5) \ X(64BIT, 0x6) typedef U8 CV_BasicPointerKind; typedef enum { #define X(N,c) CV_BasicPointerKind_##N = c, CV_BasicPointerKindXList(X) #undef X } CV_BasicPointerKindEnum; #define CV_BasicTypeFromTypeId(x) ((x)&0xFF) #define CV_BasicPointerKindFromTypeId(x) (((x)>>8)&0xFF) typedef U8 CV_HFAKind; typedef enum CV_HFAKindEnum { CV_HFAKind_None, CV_HFAKind_Float, CV_HFAKind_Double, CV_HFAKind_Other } CV_HFAKindEnum; typedef U8 CV_MoComUDTKind; typedef enum CV_MoComUDTKindEnum { CV_MoComUDTKind_None, CV_MoComUDTKind_Ref, CV_MoComUDTKind_Value, CV_MoComUDTKind_Interface } CV_MoComUDTKindEnum; typedef U16 CV_TypeProps; typedef U32 CV_TypeProps32; enum { CV_TypeProp_Packed = (1 << 0), CV_TypeProp_HasConstructorsDestructors = (1 << 1), CV_TypeProp_OverloadedOperators = (1 << 2), CV_TypeProp_IsNested = (1 << 3), CV_TypeProp_ContainsNested = (1 << 4), CV_TypeProp_OverloadedAssignment = (1 << 5), CV_TypeProp_OverloadedCasting = (1 << 6), CV_TypeProp_FwdRef = (1 << 7), CV_TypeProp_Scoped = (1 << 8), CV_TypeProp_HasUniqueName = (1 << 9), CV_TypeProp_Sealed = (1 << 10), // HFA: 11,12 CV_TypeProp_Intrinsic = (1 << 13), // MOCOM: 14,15 }; #define CV_TypeProps_Extract_HFA(f) (((f)>>11)&0x3) #define CV_TypeProps_Extract_MOCOM(f) (((f)>>14)&0x3) typedef U8 CV_PointerKind; typedef enum CV_PointerKindEnum { CV_PointerKind_Near, // 16 bit CV_PointerKind_Far, // 16:16 bit CV_PointerKind_Huge, // 16:16 bit CV_PointerKind_BaseSeg, CV_PointerKind_BaseVal, CV_PointerKind_BaseSegVal, CV_PointerKind_BaseAddr, CV_PointerKind_BaseSegAddr, CV_PointerKind_BaseType, CV_PointerKind_BaseSelf, CV_PointerKind_Near32, // 32 bit CV_PointerKind_Far32, // 16:32 bit CV_PointerKind_64, // 64 bit } CV_PointerKindEnum; typedef U8 CV_PointerMode; typedef enum CV_PointerModeEnum { CV_PointerMode_Ptr, CV_PointerMode_LRef, CV_PointerMode_PtrMem, CV_PointerMode_PtrMethod, CV_PointerMode_RRef, } CV_PointerModeEnum; typedef U16 CV_MemberPointerKind; typedef enum CV_MemberPointerKindEnum { CV_MemberPointerKind_Undef, CV_MemberPointerKind_DataSingle, CV_MemberPointerKind_DataMultiple, CV_MemberPointerKind_DataVirtual, CV_MemberPointerKind_DataGeneral, CV_MemberPointerKind_FuncSingle, CV_MemberPointerKind_FuncMultiple, CV_MemberPointerKind_FuncVirtual, CV_MemberPointerKind_FuncGeneral, } CV_MemberPointerKindEnum; typedef U32 CV_VirtualTableShape; typedef enum CV_VirtualTableShapeEnum { CV_VirtualTableShape_Near, // 16 bit ptr CV_VirtualTableShape_Far, // 16:16 bit ptr CV_VirtualTableShape_Thin, // ??? CV_VirtualTableShape_Outer, // address point displacment to outermost class entry[-1] CV_VirtualTableShape_Meta, // far pointer to metaclass descriptor entry[-2] CV_VirtualTableShape_Near32, // 32 bit ptr CV_VirtualTableShape_Far32, // ??? } CV_VirtualTableShapeEnum; typedef U8 CV_MethodProp; enum { CV_MethodProp_Vanilla, CV_MethodProp_Virtual, CV_MethodProp_Static, CV_MethodProp_Friend, CV_MethodProp_Intro, CV_MethodProp_PureVirtual, CV_MethodProp_PureIntro, }; typedef U8 CV_MemberAccess; typedef enum CV_MemberAccessEnum { CV_MemberAccess_Null, CV_MemberAccess_Private, CV_MemberAccess_Protected, CV_MemberAccess_Public } CV_MemberAccessEnum; typedef U16 CV_FieldAttribs; enum { // Access: 0,1 // MethodProp: [2:4] CV_FieldAttrib_Pseudo = (1<<5), CV_FieldAttrib_NoInherit = (1<<6), CV_FieldAttrib_NoConstruct = (1<<7), CV_FieldAttrib_CompilerGenated = (1<<8), CV_FieldAttrib_Sealed = (1<<9), }; #define CV_FieldAttribs_Extract_Access(f) ((f)&0x3) #define CV_FieldAttribs_Extract_MethodProp(f) (((f)>>2)&0x7) typedef U16 CV_LabelKind; typedef enum CV_LabelKindEnum { CV_LabelKind_Near = 0, CV_LabelKind_Far = 4, } CV_LabelKindEnum; typedef U8 CV_FunctionAttribs; enum { CV_FunctionAttrib_CxxReturnUDT = (1<<0), CV_FunctionAttrib_Constructor = (1<<1), CV_FunctionAttrib_ConstructorVBase = (1<<2), }; typedef U8 CV_CallKind; typedef enum CV_CallKindEnum { CV_CallKind_NearC, CV_CallKind_FarC, CV_CallKind_NearPascal, CV_CallKind_FarPascal, CV_CallKind_NearFast, CV_CallKind_FarFast, CV_CallKind_UNUSED, CV_CallKind_NearStd, CV_CallKind_FarStd, CV_CallKind_NearSys, CV_CallKind_FarSys, CV_CallKind_This, CV_CallKind_Mips, CV_CallKind_Generic, CV_CallKind_Alpha, CV_CallKind_PPC, CV_CallKind_HitachiSuperH, CV_CallKind_Arm, CV_CallKind_AM33, CV_CallKind_TriCore, CV_CallKind_HitachiSuperH5, CV_CallKind_M32R, CV_CallKind_Clr, CV_CallKind_Inline, CV_CallKind_NearVector, } CV_CallKindEnum; //- (LeafKind: PRECOMP) typedef struct CV_LeafPreComp CV_LeafPreComp; struct CV_LeafPreComp { U32 start_index; U32 count; U32 sig; // U8[] name (null terminated) }; //- (LeafKind; END_PRECOMP) typedef struct CV_LeafEndPreComp CV_LeafEndPreComp; struct CV_LeafEndPreComp { U32 sig; }; //- (LeafKind: TYPESERVER) typedef struct CV_LeafTypeServer CV_LeafTypeServer; struct CV_LeafTypeServer { U32 sig; U32 age; // U8[] name (null terminated) }; //- (LeafKind: TYPESERVER2) typedef struct CV_LeafTypeServer2 CV_LeafTypeServer2; struct CV_LeafTypeServer2 { Guid sig70; U32 age; // U8[] name (null terminated) }; //- (LeafKind: SKIP) typedef struct CV_LeafSkip CV_LeafSkip; struct CV_LeafSkip { CV_TypeId itype; }; //- (LeafKind: VTSHAPE) typedef struct CV_LeafVTShape CV_LeafVTShape; struct CV_LeafVTShape { U16 count; // U4[count] shapes (CV_VirtualTableShape) }; //- (LeafKind: LABEL) typedef struct CV_LeafLabel CV_LeafLabel; struct CV_LeafLabel { CV_LabelKind kind; }; //- (LeafKind: MODIFIER) typedef U16 CV_ModifierFlags; enum { CV_ModifierFlag_Const = (1 << 0), CV_ModifierFlag_Volatile = (1 << 1), CV_ModifierFlag_Unaligned = (1 << 2), }; typedef struct CV_LeafModifier CV_LeafModifier; struct CV_LeafModifier { CV_TypeId itype; CV_ModifierFlags flags; }; //- (LeafKind: POINTER) typedef U32 CV_PointerAttribs; enum { // Kind: [0:4] // Mode: [5:7] CV_PointerAttrib_IsFlat = (1 << 8), CV_PointerAttrib_Volatile = (1 << 9), CV_PointerAttrib_Const = (1 << 10), CV_PointerAttrib_Unaligned = (1 << 11), CV_PointerAttrib_Restricted = (1 << 12), // Size: [13,18] CV_PointerAttrib_MOCOM = (1 << 19), CV_PointerAttrib_LRef = (1 << 21), CV_PointerAttrib_RRef = (1 << 22) }; #define CV_PointerAttribs_Extract_Kind(a) ((a)&0x1F) #define CV_PointerAttribs_Extract_Mode(a) (((a)>>5)&0x7) #define CV_PointerAttribs_Extract_Size(a) (((a)>>13)&0x3F) typedef struct CV_LeafPointer CV_LeafPointer; struct CV_LeafPointer { CV_TypeId itype; CV_PointerAttribs attribs; }; //- (LeafKind: PROCEDURE) typedef struct CV_LeafProcedure CV_LeafProcedure; struct CV_LeafProcedure { CV_TypeId ret_itype; CV_CallKind call_kind; CV_FunctionAttribs attribs; U16 arg_count; CV_TypeId arg_itype; }; //- (LeafKind: MFUNCTION) typedef struct CV_LeafMFunction CV_LeafMFunction; struct CV_LeafMFunction { CV_TypeId ret_itype; CV_TypeId class_itype; CV_TypeId this_itype; CV_CallKind call_kind; CV_FunctionAttribs attribs; U16 arg_count; CV_TypeId arg_itype; S32 this_adjust; }; //- (LeafKind: ARGLIST) typedef struct CV_LeafArgList CV_LeafArgList; struct CV_LeafArgList { U32 count; // CV_TypeId[count] itypes; }; //- (LeafKind: BITFIELD) typedef struct CV_LeafBitField CV_LeafBitField; struct CV_LeafBitField { CV_TypeId itype; U8 len; U8 pos; }; //- (LeafKind: METHODLIST) // ("jagged" array of these vvvvvvvv) typedef struct CV_LeafMethodListMember CV_LeafMethodListMember; struct CV_LeafMethodListMember { CV_FieldAttribs attribs; U16 pad; CV_TypeId itype; // U32 vbaseoff (when Intro or PureIntro) }; //- (LeafKind: INDEX) typedef struct CV_LeafIndex CV_LeafIndex; struct CV_LeafIndex { U16 pad; CV_TypeId itype; }; //- (LeafKind: ARRAY) typedef struct CV_LeafArray CV_LeafArray; struct CV_LeafArray { CV_TypeId entry_itype; CV_TypeId index_itype; // CV_Numeric count }; //- (LeafKind: CLASS, STRUCTURE, INTERFACE) typedef struct CV_LeafStruct CV_LeafStruct; struct CV_LeafStruct { U16 count; CV_TypeProps props; CV_TypeId field_itype; CV_TypeId derived_itype; CV_TypeId vshape_itype; // CV_Numeric size // U8[] name (null terminated) // U8[] unique_name (null terminated) }; //- (LeafKind: UNION) typedef struct CV_LeafUnion CV_LeafUnion; struct CV_LeafUnion { U16 count; CV_TypeProps props; CV_TypeId field_itype; // CV_Numeric size // U8[] name (null terminated) // U8[] unique_name (null terminated) }; //- (LeafKind: ENUM) typedef struct CV_LeafEnum CV_LeafEnum; struct CV_LeafEnum { U16 count; CV_TypeProps props; CV_TypeId base_itype; CV_TypeId field_itype; // U8[] name (null terminated) // U8[] unique_name (null terminated) }; //- (LeafKind: ALIAS) typedef struct CV_LeafAlias CV_LeafAlias; struct CV_LeafAlias { CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafKind: MEMBER) typedef struct CV_LeafMember CV_LeafMember; struct CV_LeafMember { CV_FieldAttribs attribs; CV_TypeId itype; // CV_Numeric offset // U8[] name (null terminated) }; //- (LeafKind: STMEMBER) typedef struct CV_LeafStMember CV_LeafStMember; struct CV_LeafStMember { CV_FieldAttribs attribs; CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafKind: METHOD) typedef struct CV_LeafMethod CV_LeafMethod; struct CV_LeafMethod { U16 count; CV_TypeId list_itype; // U8[] name (null terminated) }; //- (LeafKind: ONEMETHOD) typedef struct CV_LeafOneMethod CV_LeafOneMethod; struct CV_LeafOneMethod { CV_FieldAttribs attribs; CV_TypeId itype; // U32 vbaseoff (when Intro or PureIntro) // U8[] name (null terminated) }; //- (LeafKind: ENUMERATE) typedef struct CV_LeafEnumerate CV_LeafEnumerate; struct CV_LeafEnumerate { CV_FieldAttribs attribs; // CV_Numeric val // U8[] name (null terminated) }; //- (LeafKind: NESTTYPE) typedef struct CV_LeafNestType CV_LeafNestType; struct CV_LeafNestType { U16 pad; CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafKind: NESTTYPEEX) typedef struct CV_LeafNestTypeEx CV_LeafNestTypeEx; struct CV_LeafNestTypeEx { CV_FieldAttribs attribs; CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafKind: BCLASS) typedef struct CV_LeafBClass CV_LeafBClass; struct CV_LeafBClass { CV_FieldAttribs attribs; CV_TypeId itype; // CV_Numeric offset }; //- (LeafKind: VBCLASS, IVBCLASS) typedef struct CV_LeafVBClass CV_LeafVBClass; struct CV_LeafVBClass { CV_FieldAttribs attribs; CV_TypeId itype; CV_TypeId vbptr_itype; // CV_Numeric vbptr_off // CV_Numeric vtable_off }; //- (LeafKind: VFUNCTAB) typedef struct CV_LeafVFuncTab CV_LeafVFuncTab; struct CV_LeafVFuncTab { U16 pad; CV_TypeId itype; }; //- (LeafKind: VFUNCOFF) typedef struct CV_LeafVFuncOff CV_LeafVFuncOff; struct CV_LeafVFuncOff { U16 pad; CV_TypeId itype; U32 off; }; //- (LeafKind: VFTABLE) typedef struct CV_LeafVFTable CV_LeafVFTable; struct CV_LeafVFTable { CV_TypeId owner_itype; CV_TypeId base_table_itype; U32 offset_in_object_layout; U32 names_len; // U8[] names (multiple null terminated strings) }; //- (LeafKind: VFTPATH) typedef struct CV_LeafVFPath CV_LeafVFPath; struct CV_LeafVFPath { U32 count; // CV_TypeId[count] base; }; //- (LeafKind: CLASS2, STRUCT2) typedef struct CV_LeafStruct2 CV_LeafStruct2; struct CV_LeafStruct2 { // NOTE: still reverse engineering this - if you find docs please help! CV_TypeProps32 props; CV_TypeId field_itype; CV_TypeId derived_itype; CV_TypeId vshape_itype; U16 unknown; // count for something? (possibly CV_Numeric) // CV_Numeric size // U8[] name (null terminated) // U8[] unique_name (null terminated) }; //- (LeafIDKind: FUNC_ID) typedef struct CV_LeafFuncId CV_LeafFuncId; struct CV_LeafFuncId { CV_ItemId scope_string_id; CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafIDKind: MFUNC_ID) typedef struct CV_LeafMFuncId CV_LeafMFuncId; struct CV_LeafMFuncId { CV_TypeId owner_itype; CV_TypeId itype; // U8[] name (null terminated) }; //- (LeafIDKind: STRING_ID) typedef struct CV_LeafStringId CV_LeafStringId; struct CV_LeafStringId { CV_ItemId substr_list_id; // U8[] string (null terminated) }; //- (LeafIDKind: BUILDINFO) typedef enum CV_BuildInfoIndexEnum { CV_BuildInfoIndex_BuildDirectory = 0, CV_BuildInfoIndex_CompilerExecutable = 1, CV_BuildInfoIndex_TargetSourceFile = 2, CV_BuildInfoIndex_CombinedPdb = 3, CV_BuildInfoIndex_CompileArguments = 4, } CV_BuildInfoIndexEnum; typedef struct CV_LeafBuildInfo CV_LeafBuildInfo; struct CV_LeafBuildInfo { U16 count; // CV_ItemId[count] items }; //- (LeafIDKind: SUBSTR_LIST) typedef struct CV_LeafSubstrList CV_LeafSubstrList; struct CV_LeafSubstrList { U32 count; // CV_ItemId[count] items }; //- (LeafIDKind: UDT_SRC_LINE) typedef struct CV_LeafUDTSrcLine CV_LeafUDTSrcLine; struct CV_LeafUDTSrcLine { CV_TypeId udt_itype; CV_ItemId src_string_id; U32 line; }; //- (LeafIDKind: UDT_MOD_SRC_LINE) typedef struct CV_LeafUDTModSrcLine CV_LeafUDTModSrcLine; struct CV_LeafUDTModSrcLine { CV_TypeId udt_itype; CV_ItemId src_string_id; U32 line; CV_ModIndex imod; }; //////////////////////////////// //~ CodeView Format C13 Line Info Types #define CV_C13SubSectionKind_IgnoreFlag 0x80000000 #define CV_C13SubSectionKindXList(X) \ X(Symbols, 0xF1) \ X(Lines, 0xF2) \ X(StringTable, 0xF3) \ X(FileChksms, 0xF4) \ X(FrameData, 0xF5) \ X(InlineeLines, 0xF6) \ X(CrossScopeImports, 0xF7) \ X(CrossScopeExports, 0xF8) \ X(IlLines, 0xF9) \ X(FuncMDTokenMap, 0xFA) \ X(TypeMDTokenMap, 0xFB) \ X(MergedAssemblyInput, 0xFC) \ X(CoffSymbolRVA, 0xFD) \ X(XfgHashType, 0xFF) \ X(XfgHashVirtual, 0x100) typedef U32 CV_C13SubSectionKind; typedef enum CV_C13SubSectionKindEnum { #define X(N,c) CV_C13SubSectionKind_##N = c, CV_C13SubSectionKindXList(X) #undef X } CV_C13SubSectionKindEnum; typedef struct CV_C13SubSectionHeader CV_C13SubSectionHeader; struct CV_C13SubSectionHeader { CV_C13SubSectionKind kind; U32 size; }; //- FileChksms sub-section typedef U8 CV_C13ChecksumKind; typedef enum CV_C13ChecksumKindEnum { CV_C13ChecksumKind_Null, CV_C13ChecksumKind_MD5, CV_C13ChecksumKind_SHA1, CV_C13ChecksumKind_SHA256, } CV_C13ChecksumKindEnum; typedef struct CV_C13Checksum CV_C13Checksum; struct CV_C13Checksum { U32 name_off; U8 len; CV_C13ChecksumKind kind; }; //- Lines sub-section typedef U16 CV_C13SubSecLinesFlags; enum { CV_C13SubSecLinesFlag_HasColumns = (1 << 0) }; typedef struct CV_C13SubSecLinesHeader CV_C13SubSecLinesHeader; struct CV_C13SubSecLinesHeader { U32 sec_off; CV_SectionIndex sec; CV_C13SubSecLinesFlags flags; U32 len; }; typedef struct CV_C13File CV_C13File; struct CV_C13File { U32 file_off; U32 num_lines; U32 block_size; // CV_C13Line[num_lines] lines; // CV_C13Column[num_lines] columns; (if HasColumns) }; typedef U32 CV_C13LineFlags; #define CV_C13LineFlags_Extract_LineNumber(f) ((f)&0xFFFFFF) #define CV_C13LineFlags_Extract_DeltaToEnd(f) (((f)>>24)&0x7F) #define CV_C13LineFlags_Extract_Statement(f) (((f)>>31)&0x1) typedef struct CV_C13Line CV_C13Line; struct CV_C13Line { U32 off; CV_C13LineFlags flags; }; typedef struct CV_C13Column CV_C13Column; struct CV_C13Column { U16 start; U16 end; }; //- FrameData sub-section typedef U32 CV_C13FrameDataFlags; enum { CV_C13FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), CV_C13FrameDataFlag_HasExceptionHandling = (1 << 1), CV_C13FrameDataFlag_HasIsFuncStart = (1 << 2), }; typedef struct CV_C13FrameData CV_C13FrameData; struct CV_C13FrameData { U32 start_voff; U32 code_size; U32 local_size; U32 params_size; U32 max_stack_size; U32 frame_func; U16 prolog_size; U16 saved_reg_size; CV_C13FrameDataFlags flags; }; //- InlineLines sub-section typedef U32 CV_C13InlineeLinesSig; enum { CV_C13InlineeLinesSig_NORMAL, CV_C13InlineeLinesSig_EXTRA_FILES, }; typedef struct CV_C13InlineeSourceLineHeader CV_C13InlineeSourceLineHeader; struct CV_C13InlineeSourceLineHeader { CV_ItemId inlinee; // LF_FUNC_ID or LF_MFUNC_ID U32 file_off; // offset into FileChksms sub-section U32 first_source_ln; // base source line number for binary annotations // if sig set to CV_C13InlineeLinesSig_EXTRA_FILES // U32 extra_file_count; // U32 files[]; }; #pragma pack(pop) //////////////////////////////// //~ Type Index Helper enum CV_TypeIndexSource { CV_TypeIndexSource_NULL, CV_TypeIndexSource_TPI, CV_TypeIndexSource_IPI, CV_TypeIndexSource_COUNT }; typedef enum CV_TypeIndexSource CV_TypeIndexSource; typedef struct CV_TypeIndexInfo CV_TypeIndexInfo; struct CV_TypeIndexInfo { struct CV_TypeIndexInfo *next; U64 offset; CV_TypeIndexSource source; }; typedef struct CV_TypeIndexInfoList CV_TypeIndexInfoList; struct CV_TypeIndexInfoList { U64 count; CV_TypeIndexInfo *first; CV_TypeIndexInfo *last; }; typedef struct CV_TypeIndexArray CV_TypeIndexArray; struct CV_TypeIndexArray { U32 count; CV_TypeIndex *v; }; //////////////////////////////// internal CV_Arch cv_arch_from_coff_machine(COFF_MachineType machine); internal U64 cv_size_from_reg_x86(CV_Reg reg); internal U64 cv_size_from_reg_x64(CV_Reg reg); internal U64 cv_size_from_reg(CV_Arch arch, CV_Reg reg); internal B32 cv_is_reg_sp(CV_Arch arch, CV_Reg reg); internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param); internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg); internal U32 cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg); //////////////////////////////// //~ rjf: Enum -> String internal String8 cv_string_from_inline_range_kind(CV_InlineRangeKind kind); internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source); internal String8 cv_string_from_language(CV_Language x); internal String8 cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id); internal String8 cv_string_from_member_access(CV_MemberAccess x); internal String8 cv_string_from_method_prop(CV_MethodProp x); internal String8 cv_string_from_hfa(CV_HFAKind x); internal String8 cv_string_from_mcom(CV_MoComUDTKind x); internal String8 cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x); internal String8 cv_string_from_thunk_ordinal(CV_ThunkOrdinal x); internal String8 cv_string_from_frame_cookie_kind(CV_FrameCookieKind x); internal String8 cv_string_from_generic_style(CV_GenericStyle x); internal String8 cv_string_from_trampoline_kind(CV_TrampolineKind x); internal String8 cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x); internal String8 cv_string_from_call_kind(CV_CallKind x); internal String8 cv_string_from_member_pointer_kind(CV_MemberPointerKind x); internal String8 cv_string_from_pointer_kind(CV_PointerKind x); internal String8 cv_string_from_pointer_mode(CV_PointerMode x); internal String8 cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x); internal String8 cv_string_from_label_kind(Arena *arena, CV_LabelKind x); internal String8 cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x); internal String8 cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x); internal String8 cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x); internal String8 cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x); internal String8 cv_string_from_export_flags(Arena *arena, CV_ExportFlags x); internal String8 cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x); internal String8 cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x); internal String8 cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x); internal String8 cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x); internal String8 cv_string_from_type_props(Arena *arena, CV_TypeProps32 x); internal String8 cv_string_from_local_flags(Arena *arena, CV_LocalFlags x); internal String8 cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x); internal String8 cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x); internal String8 cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x); internal String8 cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs attribs); internal String8 cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype); internal String8 cv_string_from_itemid(Arena *arena, CV_ItemId itemid); internal String8 cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type); internal String8 cv_string_from_symbol_kind(Arena *arena, CV_SymKind kind); internal String8 cv_string_from_leaf_name(Arena *arena, U32 leaf_type); internal String8 cv_string_sec_off(Arena *arena, U32 sec, U32 off); #endif // CODEVIEW_H ================================================ FILE: src/codeview/codeview.mdesk ================================================ //////////////////////////////// //~ rjf: CV Numerics @table(name val) CV_NumericKindTable: { {CHAR 0x8000} {SHORT 0x8001} {USHORT 0x8002} {LONG 0x8003} {ULONG 0x8004} {FLOAT32 0x8005} {FLOAT64 0x8006} {FLOAT80 0x8007} {FLOAT128 0x8008} {QUADWORD 0x8009} {UQUADWORD 0x800a} {FLOAT48 0x800b} {COMPLEX32 0x800c} {COMPLEX64 0x800d} {COMPLEX80 0x800e} {COMPLEX128 0x800f} {VARSTRING 0x8010} {OCTWORD 0x8017} {UOCTWORD 0x8018} {DECIMAL 0x8019} {DATE 0x801a} {UTF8STRING 0x801b} {FLOAT16 0x801c} } @enum(U16) CV_NumericKind: { @expand(CV_NumericKindTable a) `$(a.name) = $(a.val)` } @enum2string_switch(CV_NumericKind) cv_string_from_numeric_kind: { @expand(CV_NumericKindTable a) `case CV_NumericKind_$(a.name):{result = str8_lit("$(a.name)");}break`; } //////////////////////////////// //~ rjf: CV Architectures @table(name val) CV_ArchTable: { {8080 0x00} {8086 0x01} {80286 0x02} {80386 0x03} {80486 0x04} {PENTIUM 0x05} {PENTIUMII 0x06} {PENTIUMIII 0x07} {MIPS 0x10} {MIPS16 0x11} {MIPS32 0x12} {MIPS64 0x13} {MIPSI 0x14} {MIPSII 0x15} {MIPSIII 0x16} {MIPSIV 0x17} {MIPSV 0x18} {M68000 0x20} {M68010 0x21} {M68020 0x22} {M68030 0x23} {M68040 0x24} {ALPHA 0x30} {ALPHA_21164 0x31} {ALPHA_21164A 0x32} {ALPHA_21264 0x33} {ALPHA_21364 0x34} {PPC601 0x40} {PPC603 0x41} {PPC604 0x42} {PPC620 0x43} {PPCFP 0x44} {PPCBE 0x45} {SH3 0x50} {SH3E 0x51} {SH3DSP 0x52} {SH4 0x53} {SHMEDIA 0x54} {ARM3 0x60} {ARM4 0x61} {ARM4T 0x62} {ARM5 0x63} {ARM5T 0x64} {ARM6 0x65} {ARM_XMAC 0x66} {ARM_WMMX 0x67} {ARM7 0x68} {OMNI 0x70} {IA64_1 0x80} {IA64_2 0x81} {CEE 0x90} {AM33 0xA0} {M32R 0xB0} {TRICORE 0xC0} {X64 0xD0} {EBC 0xE0} {THUMB 0xF0} {ARMNT 0xF4} {ARM64 0xF6} {D3D11_SHADER 0x100} } @enum(U16) CV_Arch: { @expand(CV_ArchTable a) `$(a.name) = $(a.val)`, `IA64 = CV_Arch_IA64_1`, `PENTIUMPRO = CV_Arch_PENTIUMII`, `MIPSR4000 = CV_Arch_MIPS`, `ALPHA_21064 = CV_Arch_ALPHA`, `AMD64 = CV_Arch_X64`, } @enum2string_switch(CV_Arch) cv_string_from_arch: { @expand(CV_ArchTable a) `case CV_Arch_$(a.name):{result = str8_lit("$(a.name)");}break`; } //////////////////////////////// //~ rjf: CV Registers @table(name val) CV_AllRegTable: { {ERR 30000} {TEB 30001} {TIMER 30002} {EFAD1 30003} {EFAD2 30004} {EFAD3 30005} {VFRAME 30006} {HANDLE 30007} {PARAMS 30008} {LOCALS 30009} {TID 30010} {ENV 30011} {CMDLN 30012} } @enum(U16) CV_AllReg: { @expand(CV_AllRegTable a) `$(a.name) = $(a.val)` } //////////////////////////////// //~ rjf: CV Sym Kinds @table(name header_type_name val) CV_SymKindTable: { {COMPILE Compile 0x0001} {REGISTER_16t - 0x0002} {CONSTANT_16t - 0x0003} {UDT_16t - 0x0004} {SSEARCH StartSearch 0x0005} {END - 0x0006} {SKIP - 0x0007} {CVRESERVE - 0x0008} {OBJNAME_ST - 0x0009} {ENDARG - 0x000a} {COBOLUDT_16t - 0x000b} {MANYREG_16t - 0x000c} {RETURN Return 0x000d} {ENTRYTHIS - 0x000e} {BPREL16 - 0x0100} {LDATA16 - 0x0101} {GDATA16 - 0x0102} {PUB16 - 0x0103} {LPROC16 - 0x0104} {GPROC16 - 0x0105} {THUNK16 - 0x0106} {BLOCK16 - 0x0107} {WITH16 - 0x0108} {LABEL16 - 0x0109} {CEXMODEL16 - 0x010a} {VFTABLE16 - 0x010b} {REGREL16 - 0x010c} {BPREL32_16t - 0x0200} {LDATA32_16t - 0x0201} {GDATA32_16t - 0x0202} {PUB32_16t - 0x0203} {LPROC32_16t - 0x0204} {GPROC32_16t - 0x0205} {THUNK32_ST - 0x0206} {BLOCK32_ST - 0x0207} {WITH32_ST - 0x0208} {LABEL32_ST - 0x0209} {CEXMODEL32 - 0x020a} {VFTABLE32_16t - 0x020b} {REGREL32_16t - 0x020c} {LTHREAD32_16t - 0x020d} {GTHREAD32_16t - 0x020e} {SLINK32 SLink32 0x020f} {LPROCMIPS_16t - 0x0300} {GPROCMIPS_16t - 0x0301} {PROCREF_ST - 0x0400} {DATAREF_ST - 0x0401} {ALIGN - 0x0402} {LPROCREF_ST - 0x0403} {OEM OEM 0x0404} {TI16_MAX - 0x1000} {CONSTANT_ST - 0x1002} {UDT_ST - 0x1003} {COBOLUDT_ST - 0x1004} {MANYREG_ST - 0x1005} {BPREL32_ST - 0x1006} {LDATA32_ST - 0x1007} {GDATA32_ST - 0x1008} {PUB32_ST - 0x1009} {LPROC32_ST - 0x100a} {GPROC32_ST - 0x100b} {VFTABLE32 VPath32 0x100c} {REGREL32_ST - 0x100d} {LTHREAD32_ST - 0x100e} {GTHREAD32_ST - 0x100f} {LPROCMIPS_ST - 0x1010} {GPROCMIPS_ST - 0x1011} {FRAMEPROC Frameproc 0x1012} {COMPILE2_ST - 0x1013} {MANYREG2_ST - 0x1014} {LPROCIA64_ST - 0x1015} {GPROCIA64_ST - 0x1016} {LOCALSLOT_ST - 0x1017} {PARAMSLOT_ST - 0x1018} {ANNOTATION Annotation 0x1019} {GMANPROC_ST - 0x101a} {LMANPROC_ST - 0x101b} {RESERVED1 - 0x101c} {RESERVED2 - 0x101d} {RESERVED3 - 0x101e} {RESERVED4 - 0x101f} {LMANDATA_ST - 0x1020} {GMANDATA_ST - 0x1021} {MANFRAMEREL_ST - 0x1022} {MANREGISTER_ST - 0x1023} {MANSLOT_ST - 0x1024} {MANMANYREG_ST - 0x1025} {MANREGREL_ST - 0x1026} {MANMANYREG2_ST - 0x1027} {MANTYPREF - 0x1028} {UNAMESPACE_ST - 0x1029} {ST_MAX - 0x1100} {OBJNAME ObjName 0x1101} {THUNK32 Thunk32 0x1102} {BLOCK32 Block32 0x1103} {WITH32 - 0x1104} {LABEL32 Label32 0x1105} {REGISTER Register 0x1106} {CONSTANT Constant 0x1107} {UDT UDT 0x1108} {COBOLUDT - 0x1109} {MANYREG Manyreg 0x110a} {BPREL32 BPRel32 0x110b} {LDATA32 Data32 0x110c} {GDATA32 Data32 0x110d} {PUB32 Pub32 0x110e} {LPROC32 Proc32 0x110f} {GPROC32 Proc32 0x1110} {REGREL32 Regrel32 0x1111} {LTHREAD32 Thread32 0x1112} {GTHREAD32 Thread32 0x1113} {LPROCMIPS - 0x1114} {GPROCMIPS - 0x1115} {COMPILE2 Compile2 0x1116} {MANYREG2 Manyreg2 0x1117} {LPROCIA64 - 0x1118} {GPROCIA64 - 0x1119} {LOCALSLOT Slot 0x111a} {PARAMSLOT - 0x111b} {LMANDATA - 0x111c} {GMANDATA - 0x111d} {MANFRAMEREL AttrFrameRel 0x111e} {MANREGISTER AttrReg 0x111f} {MANSLOT - 0x1120} {MANMANYREG AttrManyReg 0x1121} {MANREGREL AttrRegRel 0x1122} {MANMANYREG2 - 0x1123} {UNAMESPACE UNamespace 0x1124} {PROCREF Ref2 0x1125} {DATAREF Ref2 0x1126} {LPROCREF Ref2 0x1127} {ANNOTATIONREF - 0x1128} {TOKENREF - 0x1129} {GMANPROC - 0x112a} {LMANPROC - 0x112b} {TRAMPOLINE Trampoline 0x112c} {MANCONSTANT - 0x112d} {ATTR_FRAMEREL AttrFrameRel 0x112e} {ATTR_REGISTER AttrReg 0x112f} {ATTR_REGREL AttrRegRel 0x1130} {ATTR_MANYREG AttrManyReg 0x1131} {SEPCODE Sepcode 0x1132} {DEFRANGE_2005 - 0x1134} {DEFRANGE2_2005 - 0x1135} {SECTION Section 0x1136} {COFFGROUP CoffGroup 0x1137} {EXPORT Export 0x1138} {CALLSITEINFO CallSiteInfo 0x1139} {FRAMECOOKIE FrameCookie 0x113a} {DISCARDED Discarded 0x113b} {COMPILE3 Compile3 0x113c} {ENVBLOCK EnvBlock 0x113d} {LOCAL Local 0x113e} {DEFRANGE - 0x113f} {DEFRANGE_SUBFIELD DefrangeSubfield 0x1140} {DEFRANGE_REGISTER DefrangeRegister 0x1141} {DEFRANGE_FRAMEPOINTER_REL DefrangeFramepointerRel 0x1142} {DEFRANGE_SUBFIELD_REGISTER DefrangeSubfieldRegister 0x1143} {DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE DefrangeFramepointerRelFullScope 0x1144} {DEFRANGE_REGISTER_REL DefrangeRegisterRel 0x1145} {LPROC32_ID - 0x1146} {GPROC32_ID - 0x1147} {LPROCMIPS_ID - 0x1148} {GPROCMIPS_ID - 0x1149} {LPROCIA64_ID - 0x114a} {GPROCIA64_ID - 0x114b} {BUILDINFO BuildInfo 0x114c} {INLINESITE InlineSite 0x114d} {INLINESITE_END - 0x114e} {PROC_ID_END - 0x114f} {DEFRANGE_HLSL - 0x1150} {GDATA_HLSL - 0x1151} {LDATA_HLSL - 0x1152} {FILESTATIC FileStatic 0x1153} {LPROC32_DPC - 0x1155} {LPROC32_DPC_ID - 0x1156} {DEFRANGE_DPC_PTR_TAG - 0x1157} {DPC_SYM_TAG_MAP - 0x1158} {ARMSWITCHTABLE - 0x1159} {CALLEES FunctionList 0x115a} {CALLERS FunctionList 0x115b} {POGODATA PogoInfo 0x115c} {INLINESITE2 InlineSite2 0x115d} {HEAPALLOCSITE HeapAllocSite 0x115e} {MOD_TYPEREF ModTypeRef 0x115f} {REF_MINIPDB RefMiniPdb 0x1160} {PDBMAP - 0x1161} {GDATA_HLSL32 - 0x1162} {LDATA_HLSL32 - 0x1163} {GDATA_HLSL32_EX - 0x1164} {LDATA_HLSL32_EX - 0x1165} {FASTLINK FastLink 0x1167} {INLINEES Inlinees 0x1168} } @enum(U16) CV_SymKind: { @expand(CV_SymKindTable a) `$(a.name) = $(a.val)` } @enum2string_switch(CV_SymKind) cv_string_from_sym_kind: { @expand(CV_SymKindTable a) `case CV_SymKind_$(a.name):{result = str8_lit("$(a.name)");}break`; } @gen(functions) { `internal U64 cv_header_struct_size_from_sym_kind(CV_SymKind v);`; } @gen(functions) @c_file { `internal U64`; `cv_header_struct_size_from_sym_kind(CV_SymKind v)`; `{`; `U64 result = 0;`; `switch(v)`; `{`; `default:{}break;`; @expand(CV_SymKindTable a) `$(a.header_type_name != "-" -> "case CV_SymKind_"..a.name..":{result = sizeof(CV_Sym"..a.header_type_name..");}break;")`; `}`; `return result;`; `}`; } //////////////////////////////// //~ rjf: CV Basic Types @table(name val type_name) CV_BasicTypeTable: { {NOTYPE 0x00 "" } {ABS 0x01 "" } {SEGMENT 0x02 "" } {VOID 0x03 "void" } {CURRENCY 0x04 "" } {NBASICSTR 0x05 "" } {FBASICSTR 0x06 "" } {NOTTRANS 0x07 "" } {HRESULT 0x08 "HRESULT" } {CHAR 0x10 "CHAR" } {SHORT 0x11 "SHORT" } {LONG 0x12 "LONG" } {QUAD 0x13 "QUAD" } {OCT 0x14 "OCT" } {UCHAR 0x20 "UCHAR" } {USHORT 0x21 "USHORT" } {ULONG 0x22 "ULONG" } {UQUAD 0x23 "UQUAD" } {UOCT 0x24 "UOCT" } {BOOL8 0x30 "BOOL8" } {BOOL16 0x31 "BOOL16" } {BOOL32 0x32 "BOOL32" } {BOOL64 0x33 "BOOL64" } {FLOAT32 0x40 "FLOAT32" } {FLOAT64 0x41 "FLOAT64" } {FLOAT80 0x42 "FLOAT80" } {FLOAT128 0x43 "FLOAT128" } {FLOAT48 0x44 "FLOAT48" } {FLOAT32PP 0x45 "FLOAT32PP" } {FLOAT16 0x46 "FLOAT16" } {COMPLEX32 0x50 "ComplexF32" } {COMPLEX64 0x51 "ComplexF64" } {COMPLEX80 0x52 "ComplexF80" } {COMPLEX128 0x53 "ComplexF128" } {BIT 0x60 "" } {PASCHAR 0x61 "" } {BOOL32FF 0x62 "BOOL32FF" } {INT8 0x68 "int8" } {UINT8 0x69 "uint8" } {RCHAR 0x70 "char" } {WCHAR 0x71 "WCHAR" } {INT16 0x72 "int16" } {UINT16 0x73 "uint16" } {INT32 0x74 "int32" } {UINT32 0x75 "uint32" } {INT64 0x76 "int64" } {UINT64 0x77 "uint64" } {INT128 0x78 "int128" } {UINT128 0x79 "uint128" } {CHAR16 0x7a "char16" } {CHAR32 0x7b "char32" } {CHAR8 0x7c "char" } {PTR 0xf0 "PTR" } } @enum(U8) CV_BasicType: { @expand(CV_BasicTypeTable a) `$(a.name) = $(a.val)` } @enum2string_switch(CV_BasicType) cv_string_from_basic_type: { @expand(CV_BasicTypeTable a) `case CV_BasicType_$(a.name):{result = str8_lit("$(a.name)");}break` } @enum2string_switch(CV_BasicType) cv_type_name_from_basic_type: { @expand(CV_BasicTypeTable a) `case CV_BasicType_$(a.name):{result = str8_lit("$(a.type_name)");}break` } //////////////////////////////// //~ rjf: CV Leaf Kinds @table(name header_type_name val) CV_LeafKindTable: { {NOTYPE - 0x0000} {MODIFIER_16t - 0x0001} {POINTER_16t - 0x0002} {ARRAY_16t - 0x0003} {CLASS_16t - 0x0004} {STRUCTURE_16t - 0x0005} {UNION_16t - 0x0006} {ENUM_16t - 0x0007} {PROCEDURE_16t - 0x0008} {MFUNCTION_16t - 0x0009} {VTSHAPE VTShape 0x000a} {COBOL0_16t - 0x000b} {COBOL1 - 0x000c} {BARRAY_16t - 0x000d} {LABEL Label 0x000e} {NULL - 0x000f} {NOTTRAN - 0x0010} {DIMARRAY_16t - 0x0011} {VFTPATH_16t - 0x0012} {PRECOMP_16t - 0x0013} {ENDPRECOMP - 0x0014} {OEM_16t - 0x0015} {TYPESERVER_ST - 0x0016} {SKIP_16t - 0x0200} {ARGLIST_16t - 0x0201} {DEFARG_16t - 0x0202} {LIST - 0x0203} {FIELDLIST_16t - 0x0204} {DERIVED_16t - 0x0205} {BITFIELD_16t - 0x0206} {METHODLIST_16t - 0x0207} {DIMCONU_16t - 0x0208} {DIMCONLU_16t - 0x0209} {DIMVARU_16t - 0x020a} {DIMVARLU_16t - 0x020b} {REFSYM - 0x020c} {BCLASS_16t - 0x0400} {VBCLASS_16t - 0x0401} {IVBCLASS_16t - 0x0402} {ENUMERATE_ST - 0x0403} {FRIENDFCN_16t - 0x0404} {INDEX_16t - 0x0405} {MEMBER_16t - 0x0406} {STMEMBER_16t - 0x0407} {METHOD_16t - 0x0408} {NESTTYPE_16t - 0x0409} {VFUNCTAB_16t - 0x040a} {FRIENDCLS_16t - 0x040b} {ONEMETHOD_16t - 0x040c} {VFUNCOFF_16t - 0x040d} {TI16_MAX - 0x1000} {MODIFIER Modifier 0x1001} {POINTER Pointer 0x1002} {ARRAY_ST - 0x1003} {CLASS_ST - 0x1004} {STRUCTURE_ST - 0x1005} {UNION_ST - 0x1006} {ENUM_ST - 0x1007} {PROCEDURE Procedure 0x1008} {MFUNCTION MFunction 0x1009} {COBOL0 - 0x100a} {BARRAY - 0x100b} {DIMARRAY_ST - 0x100c} {VFTPATH VFPath 0x100d} {PRECOMP_ST - 0x100e} {OEM - 0x100f} {ALIAS_ST - 0x1010} {OEM2 - 0x1011} {SKIP Skip 0x1200} {ARGLIST ArgList 0x1201} {DEFARG_ST - 0x1202} {FIELDLIST - 0x1203} {DERIVED - 0x1204} {BITFIELD BitField 0x1205} {METHODLIST MethodListMember 0x1206} {DIMCONU - 0x1207} {DIMCONLU - 0x1208} {DIMVARU - 0x1209} {DIMVARLU - 0x120a} {BCLASS BClass 0x1400} {VBCLASS VBClass 0x1401} {IVBCLASS - 0x1402} {FRIENDFCN_ST - 0x1403} {INDEX Index 0x1404} {MEMBER_ST - 0x1405} {STMEMBER_ST - 0x1406} {METHOD_ST - 0x1407} {NESTTYPE_ST - 0x1408} {VFUNCTAB VFuncTab 0x1409} {FRIENDCLS - 0x140a} {ONEMETHOD_ST - 0x140b} {VFUNCOFF VFuncOff 0x140c} {NESTTYPEEX_ST - 0x140d} {MEMBERMODIFY_ST - 0x140e} {MANAGED_ST - 0x140f} {ST_MAX - 0x1500} {TYPESERVER TypeServer 0x1501} {ENUMERATE Enumerate 0x1502} {ARRAY Array 0x1503} {CLASS Struct 0x1504} {STRUCTURE Struct 0x1505} {UNION Union 0x1506} {ENUM Enum 0x1507} {DIMARRAY - 0x1508} {PRECOMP PreComp 0x1509} {ALIAS Alias 0x150a} {DEFARG - 0x150b} {FRIENDFCN - 0x150c} {MEMBER Member 0x150d} {STMEMBER StMember 0x150e} {METHOD Method 0x150f} {NESTTYPE NestType 0x1510} {ONEMETHOD OneMethod 0x1511} {NESTTYPEEX NestTypeEx 0x1512} {MEMBERMODIFY - 0x1513} {MANAGED - 0x1514} {TYPESERVER2 TypeServer2 0x1515} {STRIDED_ARRAY - 0x1516} {HLSL - 0x1517} {MODIFIER_EX - 0x1518} {INTERFACE Struct 0x1519} {BINTERFACE - 0x151a} {VECTOR - 0x151b} {MATRIX - 0x151c} {VFTABLE - 0x151d} {FUNC_ID FuncId 0x1601} {MFUNC_ID MFuncId 0x1602} {BUILDINFO BuildInfo 0x1603} {SUBSTR_LIST SubstrList 0x1604} {STRING_ID StringId 0x1605} {UDT_SRC_LINE UDTSrcLine 0x1606} {UDT_MOD_SRC_LINE UDTModSrcLine 0x1607} {CLASS2 Struct2 0x1608} {STRUCT2 Struct2 0x1609} } @enum(U16) CV_LeafKind: { @expand(CV_LeafKindTable a) `$(a.name) = $(a.val)`; } @enum2string_switch(CV_LeafKind) cv_string_from_leaf_kind: { @expand(CV_LeafKindTable a) `case CV_LeafKind_$(a.name):{result = str8_lit("$(a.name)");}break`; } @gen(functions) { `internal U64 cv_header_struct_size_from_leaf_kind(CV_LeafKind v);`; } @gen(functions) @c_file { `internal U64`; `cv_header_struct_size_from_leaf_kind(CV_LeafKind v)`; `{`; `U64 result = 0;`; `switch(v)`; `{`; `default:{}break;`; @expand(CV_LeafKindTable a) `$(a.header_type_name != "-" -> "case CV_LeafKind_"..a.name..":{result = sizeof(CV_Leaf"..a.header_type_name..");}break;")`; `}`; `return result;`; `}`; } ================================================ FILE: src/codeview/codeview_dump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 cv_string_from_numeric(Arena *arena, CV_NumericParsed num) { String8 result = str8_zero(); switch (num.kind) { case CV_NumericKind_FLOAT16: NotImplemented; break; // TODO: format float16 case CV_NumericKind_FLOAT32: result = push_str8f(arena, "%f", (F64)(*(F32*)num.val)); break; case CV_NumericKind_FLOAT48: NotImplemented; break; // TODO: format float48 case CV_NumericKind_FLOAT64: result = push_str8f(arena, "%f", *(F64*)num.val); break; case CV_NumericKind_FLOAT80: NotImplemented; break; // TODO: format float80 case CV_NumericKind_FLOAT128: NotImplemented; break; // TODO: format float128 case CV_NumericKind_CHAR: result = push_str8f(arena, "%d", *(S8 *)num.val); break; case CV_NumericKind_SHORT: result = push_str8f(arena, "%d", *(S16*)num.val); break; case CV_NumericKind_LONG: result = push_str8f(arena, "%d", *(S32*)num.val); break; case CV_NumericKind_QUADWORD: result = push_str8f(arena, "%lld", *(S64*)num.val); break; case CV_NumericKind_USHORT: result = push_str8f(arena, "%u", *(U16*)num.val); break; case CV_NumericKind_ULONG: result = push_str8f(arena, "%u", *(U32*)num.val); break; case CV_NumericKind_UQUADWORD: result = push_str8f(arena, "%llu", *(U64*)num.val); break; } return result; } ================================================ FILE: src/codeview/codeview_dump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_DUMP_H #define CODEVIEW_DUMP_H internal String8 cv_string_from_numeric(Arena *arena, CV_NumericParsed num); #endif // CODEVIEW_DUMP_H ================================================ FILE: src/codeview/codeview_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- Hasher internal U64 cv_hash_from_string(String8 string) { U64 result = 5381; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + string.str[i]; } return result; } internal U64 cv_hash_from_item_id(CV_ItemId item_id) { U64 result = cv_hash_from_string(str8_struct(&item_id)); return result; } //- Numeric Decoder internal CV_NumericParsed cv_numeric_from_data_range(U8 *first, U8 *opl) { CV_NumericParsed result = {0}; if(first + 2 <= opl) { U16 x = *(U16*)first; if(x < 0x8000) { result.kind = CV_NumericKind_USHORT; result.val = first; result.encoded_size = 2; } else { U64 val_size = 0; switch(x) { case CV_NumericKind_CHAR: val_size = 1; break; case CV_NumericKind_SHORT: case CV_NumericKind_USHORT: val_size = 2; break; case CV_NumericKind_LONG: case CV_NumericKind_ULONG: val_size = 4; break; case CV_NumericKind_FLOAT32: val_size = 4; break; case CV_NumericKind_FLOAT64: val_size = 8; break; case CV_NumericKind_FLOAT80: val_size = 10; break; case CV_NumericKind_FLOAT128: val_size = 16; break; case CV_NumericKind_QUADWORD: case CV_NumericKind_UQUADWORD: val_size = 8; break; case CV_NumericKind_FLOAT48: val_size = 6; break; case CV_NumericKind_COMPLEX32: val_size = 8; break; case CV_NumericKind_COMPLEX64: val_size = 16; break; case CV_NumericKind_COMPLEX80: val_size = 20; break; case CV_NumericKind_COMPLEX128:val_size = 32; break; case CV_NumericKind_VARSTRING: val_size = 0; break; // TODO: ??? case CV_NumericKind_OCTWORD: case CV_NumericKind_UOCTWORD: val_size = 16; break; case CV_NumericKind_DECIMAL: val_size = 0; break; // TODO: ??? case CV_NumericKind_DATE: val_size = 0; break; // TODO: ??? case CV_NumericKind_UTF8STRING:val_size = 0; break; // TODO: ??? case CV_NumericKind_FLOAT16: val_size = 2; break; } if(first + 2 + val_size <= opl) { result.kind = x; result.val = (first + 2); result.encoded_size = 2 + val_size; } } } return result; } internal U64 cv_read_numeric(String8 data, U64 offset, CV_NumericParsed *out) { *out = cv_numeric_from_data_range(data.str + offset, data.str + data.size); return out->encoded_size; } internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num) { B32 result = 0; switch(num->kind) { case CV_NumericKind_USHORT: case CV_NumericKind_ULONG: case CV_NumericKind_UQUADWORD: { result = 1; }break; } return result; } internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num) { B32 result = 0; switch(num->kind) { case CV_NumericKind_CHAR: case CV_NumericKind_SHORT: case CV_NumericKind_LONG: case CV_NumericKind_QUADWORD: { result = 1; }break; } return result; } internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num) { B32 result = 0; switch(num->kind) { case CV_NumericKind_FLOAT32: case CV_NumericKind_FLOAT64: { result = 1; }break; } return result; } internal U64 cv_u64_from_numeric(CV_NumericParsed *num) { U64 result = 0; switch(num->kind) { case CV_NumericKind_CHAR: {result = (U64)(S64)*(S8*)num->val;}break; case CV_NumericKind_SHORT: {result = (U64)(S64)*(S16*)num->val;}break; case CV_NumericKind_LONG: {result = (U64)(S64)*(S32*)num->val;}break; case CV_NumericKind_QUADWORD: {result = (U64)(S64)*(S64*)num->val;}break; case CV_NumericKind_USHORT: {result = *(U16*)num->val;}break; case CV_NumericKind_ULONG: {result = *(U32*)num->val;}break; case CV_NumericKind_UQUADWORD:{result = *(U64*)num->val;}break; } return result; } internal S64 cv_s64_from_numeric(CV_NumericParsed *num) { S64 result = 0; switch(num->kind) { case CV_NumericKind_CHAR: {result = *(S8*)num->val;}break; case CV_NumericKind_SHORT: {result = *(S16*)num->val;}break; case CV_NumericKind_LONG: {result = *(S32*)num->val;}break; case CV_NumericKind_QUADWORD: {result = *(S64*)num->val;}break; } return(result); } internal F64 cv_f64_from_numeric(CV_NumericParsed *num) { F64 result = 0; switch(num->kind) { case CV_NumericKind_FLOAT32:{result = *(F32*)num->val;}break; case CV_NumericKind_FLOAT64:{result = *(F64*)num->val;}break; } return(result); } //- Inline Site Binary Annot Decoder internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) { U64 cursor = offset; // rjf: read header U8 header = 0; cursor += str8_deserial_read_struct(data, cursor, &header); // rjf: decode value U32 value = 0; { // 1 byte if((header & 0x80) == 0) { value = header; } // 2 bytes else if((header & 0xC0) == 0x80 && cursor+1 <= data.size) { U8 second_byte; cursor += str8_deserial_read_struct(data, cursor, &second_byte); value = ((header & 0x3F) << 8) | second_byte; } // 4 bytes else if((header & 0xE0) == 0xC0 && cursor+3 <= data.size) { U8 second_byte, third_byte, fourth_byte; cursor += str8_deserial_read_struct(data, cursor, &second_byte); cursor += str8_deserial_read_struct(data, cursor, &third_byte); cursor += str8_deserial_read_struct(data, cursor, &fourth_byte); value = (((U32)header & 0x1F) << 24) | ((U32)second_byte << 16) | ((U32)third_byte << 8) | (U32)fourth_byte; } // bad encode else if((header & 0xE0) == 0xE0) { value = max_U32; } } // rjf: output results if(out_value) { *out_value = value; } U64 read_size = cursor - offset; return read_size; } internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) { U32 value; U64 read_size = cv_decode_inline_annot_u32(data, offset, &value); if(value & 1) { value = -(value >> 1); } else { value = value >> 1; } *out_value = (S32)value; return read_size; } internal S32 cv_inline_annot_signed_from_unsigned_operand(U32 value) { if(value & 1) { value = -(value >> 1); } else { value = value >> 1; } S32 result = (S32)value; return result; } internal CV_C13InlineSiteDecoder cv_c13_inline_site_decoder_init(U32 file_off, U32 first_source_ln, U32 parent_voff) { CV_C13InlineSiteDecoder decoder = {0}; decoder.parent_voff = parent_voff; decoder.file_off = file_off; decoder.ln = (S32)first_source_ln; decoder.cn = 1; decoder.ln_changed = 1; return decoder; } internal CV_C13InlineSiteDecoderStep cv_c13_inline_site_decoder_step(CV_C13InlineSiteDecoder *decoder, String8 binary_annots) { CV_C13InlineSiteDecoderStep result = {0}; for (; decoder->cursor < binary_annots.size && result.flags == 0; ) { U32 op = CV_InlineBinaryAnnotation_Null; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &op); switch (op) { case CV_InlineBinaryAnnotation_Null: { decoder->cursor = binary_annots.size; // this is last run, append range with left over code bytes decoder->code_length = decoder->code_offset - decoder->code_offset_lo; decoder->code_length_changed = 1; } break; case CV_InlineBinaryAnnotation_CodeOffset: { decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_offset); decoder->code_offset_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: { AssertAlways(!"TODO: test case"); // U32 delta = 0; // decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &delta); // decoder->code_offset_base = decoder->code_offset; // decoder->code_offset_end = decoder->code_offset + delta; // decoder->code_offset += delta; } break; case CV_InlineBinaryAnnotation_ChangeCodeOffset: { U32 delta = 0; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &delta); decoder->code_offset += delta; if (!decoder->code_offset_lo_changed) { decoder->code_offset_lo = decoder->code_offset; decoder->code_offset_lo_changed = 1; } decoder->code_offset_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeCodeLength: { decoder->code_length = 0; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_length); decoder->code_length_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeFile: { U32 old_file_off = decoder->file_off; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->file_off); decoder->file_off_changed = old_file_off != decoder->file_off; // Compiler isn't obligated to terminate code sequence before chaning files, // so we have to always force emit code range on file change. decoder->code_length_changed = decoder->file_off_changed; } break; case CV_InlineBinaryAnnotation_ChangeLineOffset: { S32 delta = 0; decoder->cursor += cv_decode_inline_annot_s32(binary_annots, decoder->cursor, &delta); decoder->ln += delta; decoder->ln_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeLineEndDelta: { AssertAlways(!"TODO: test case"); // S32 end_delta = 1; // decoder->cursor += cv_decode_inline_annot_s32(binary_annots, decoder->cursor, &end_delta); // decoder->ln += end_delta; } break; case CV_InlineBinaryAnnotation_ChangeRangeKind: { AssertAlways(!"TODO: test case"); // decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &range_kind); } break; case CV_InlineBinaryAnnotation_ChangeColumnStart: { AssertAlways(!"TODO: test case"); // S32 delta; // decoder->cursor += cv_decode_inline_annot_s32(binary_annots, decoder->cursor, &delta); // decoder->cn += delta; } break; case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: { AssertAlways(!"TODO: test case"); // S32 end_delta; // decoder->cursor += cv_decode_inline_annot_s32(binary_annots, decoder->cursor, &end_delta); // decoder->cn += end_delta; } break; case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: { U32 code_offset_and_line_offset = 0; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &code_offset_and_line_offset); S32 line_delta = cv_inline_annot_signed_from_unsigned_operand(code_offset_and_line_offset >> 4); U32 code_delta = (code_offset_and_line_offset & 0xf); decoder->code_offset += code_delta; decoder->ln += line_delta; if (!decoder->code_offset_lo_changed) { decoder->code_offset_lo = decoder->code_offset; decoder->code_offset_lo_changed = 1; } decoder->code_offset_changed = 1; decoder->ln_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: { U32 offset_delta = 0; decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &decoder->code_length); decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &offset_delta); decoder->code_offset += offset_delta; if (!decoder->code_offset_lo_changed) { decoder->code_offset_lo = decoder->code_offset; decoder->code_offset_lo_changed = 1; } decoder->code_offset_changed = 1; decoder->code_length_changed = 1; } break; case CV_InlineBinaryAnnotation_ChangeColumnEnd: { AssertAlways(!"TODO: test case"); // U32 column_end = 0; // decoder->cursor += cv_decode_inline_annot_u32(binary_annots, decoder->cursor, &column_end); } break; } U64 line_code_offset = decoder->code_offset; if (decoder->code_length_changed) { // compute upper bound of the range U64 code_offset_hi = decoder->code_offset + decoder->code_length; // can last code range be extended to cover current sequence too? if (decoder->last_range.max == decoder->parent_voff + decoder->code_offset_lo) { decoder->last_range.max = decoder->parent_voff + code_offset_hi; result.flags |= CV_C13InlineSiteDecoderStepFlag_ExtendLastRange; result.range = decoder->last_range; } else { decoder->last_range = rng_1u64(decoder->parent_voff + decoder->code_offset_lo, decoder->parent_voff + code_offset_hi); decoder->file_last_range = decoder->last_range; result.flags |= CV_C13InlineSiteDecoderStepFlag_EmitRange; result.range = decoder->last_range; } // update state decoder->code_offset_lo = code_offset_hi; decoder->code_offset += decoder->code_length; decoder->code_offset_lo_changed = 0; decoder->code_length_changed = 0; decoder->code_length = 0; } if (decoder->file_off_changed || (decoder->file_count == 0)) { result.flags |= CV_C13InlineSiteDecoderStepFlag_EmitFile; result.file_off = decoder->file_off; // update state decoder->file_last_range = decoder->last_range; decoder->file_off_changed = 0; decoder->file_count += 1; decoder->file_line_count = 0; } if (decoder->code_offset_changed && decoder->ln_changed) { if (decoder->file_line_count == 0 || decoder->file_last_ln != decoder->ln) { result.flags |= CV_C13InlineSiteDecoderStepFlag_EmitLine; result.ln = decoder->ln; result.cn = decoder->cn; result.line_voff = decoder->parent_voff + line_code_offset; result.line_voff_end = decoder->last_range.max; // update state decoder->file_line_count += 1; decoder->file_last_ln = decoder->ln; } // update state decoder->code_offset_changed = 0; decoder->ln_changed = 0; } } return result; } //- Symbol/Leaf Helpers internal B32 cv_is_udt_name_anon(String8 name) { // corresponds to fUDTAnon from dbi/tm.cpp:817 B32 is_anon = str8_match_lit("", name, 0) || str8_match_lit("__unnamed", name, 0) || str8_match_lit("::", name, StringMatchFlag_RightSideSloppy) || str8_match_lit("::__unnamed", name, StringMatchFlag_RightSideSloppy); return is_anon; } internal B32 cv_is_udt(CV_LeafKind kind) { B32 is_udt = kind == CV_LeafKind_CLASS || kind == CV_LeafKind_STRUCTURE || kind == CV_LeafKind_CLASS2 || kind == CV_LeafKind_STRUCT2 || kind == CV_LeafKind_INTERFACE || kind == CV_LeafKind_UNION || kind == CV_LeafKind_ENUM || kind == CV_LeafKind_UDT_MOD_SRC_LINE || kind == CV_LeafKind_UDT_SRC_LINE || kind == CV_LeafKind_ALIAS; return is_udt; } internal B32 cv_is_global_symbol(CV_SymKind kind) { B32 is_global_symbol = kind == CV_SymKind_CONSTANT || kind == CV_SymKind_GDATA16 || kind == CV_SymKind_GDATA32_16t || kind == CV_SymKind_GDATA32_ST || kind == CV_SymKind_GDATA32 || kind == CV_SymKind_GTHREAD32_16t || kind == CV_SymKind_GTHREAD32_ST || kind == CV_SymKind_GTHREAD32; return is_global_symbol; } internal B32 cv_is_typedef(CV_SymKind kind) { B32 is_typedef = kind == CV_SymKind_UDT_16t || kind == CV_SymKind_UDT_ST || kind == CV_SymKind_UDT; return is_typedef; } internal B32 cv_is_scope_symbol(CV_SymKind kind) { B32 is_scope = kind == CV_SymKind_GPROC32 || kind == CV_SymKind_LPROC32 || kind == CV_SymKind_BLOCK32 || kind == CV_SymKind_THUNK32 || kind == CV_SymKind_INLINESITE || kind == CV_SymKind_INLINESITE2 || kind == CV_SymKind_WITH32 || kind == CV_SymKind_SEPCODE || kind == CV_SymKind_GPROC32_ID || kind == CV_SymKind_LPROC32_ID; return is_scope; } internal B32 cv_is_end_symbol(CV_SymKind kind) { B32 is_end = kind == CV_SymKind_END || kind == CV_SymKind_PROC_ID_END || kind == CV_SymKind_INLINESITE_END; return is_end; } internal B32 cv_is_leaf_type_server(CV_LeafKind kind) { B32 is_type_server = kind == CV_LeafKind_TYPESERVER || kind == CV_LeafKind_TYPESERVER2 || kind == CV_LeafKind_TYPESERVER_ST; return is_type_server; } internal B32 cv_is_leaf_pch(CV_LeafKind kind) { B32 is_pch = kind == CV_LeafKind_PRECOMP || kind == CV_LeafKind_PRECOMP_ST || kind == CV_LeafKind_PRECOMP_16t; return is_pch; } internal CV_TypeIndexSource cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind) { CV_TypeIndexSource source; if(leaf_kind == CV_LeafKind_FUNC_ID || leaf_kind == CV_LeafKind_MFUNC_ID || leaf_kind == CV_LeafKind_BUILDINFO || leaf_kind == CV_LeafKind_SUBSTR_LIST || leaf_kind == CV_LeafKind_STRING_ID || leaf_kind == CV_LeafKind_UDT_SRC_LINE || leaf_kind == CV_LeafKind_UDT_MOD_SRC_LINE) { source = CV_TypeIndexSource_IPI; } else if(leaf_kind == CV_LeafKind_NOTYPE) { source = CV_TypeIndexSource_NULL; } else { source = CV_TypeIndexSource_TPI; } return source; } internal CV_TypeIndexInfo * cv_symbol_type_index_info_push(Arena *arena, CV_TypeIndexInfoList *list, CV_TypeIndexSource source, U64 offset) { CV_TypeIndexInfo *info = push_array_no_zero(arena, CV_TypeIndexInfo, 1); info->next = 0; info->offset = offset; info->source = source; SLLQueuePush(list->first, list->last, info); list->count += 1; return info; } internal CV_TypeIndexInfoList cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data) { CV_TypeIndexInfoList list = {0}; switch (kind) { case CV_SymKind_BUILDINFO: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymBuildInfo, id)); } break; case CV_SymKind_GDATA32: case CV_SymKind_LDATA32: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymData32, itype)); } break; case CV_SymKind_LPROC32_ID: case CV_SymKind_GPROC32_ID: case CV_SymKind_LPROC32_DPC_ID: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymProc32, itype)); } break; case CV_SymKind_GPROC32: case CV_SymKind_LPROC32: case CV_SymKind_LPROC32_DPC: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymProc32, itype)); } break; case CV_SymKind_UDT: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymUDT, itype)); } break; case CV_SymKind_GTHREAD32: case CV_SymKind_LTHREAD32: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymThread32, itype)); } break; case CV_SymKind_FILESTATIC: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymFileStatic, itype)); } break; case CV_SymKind_LOCAL: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymLocal, itype)); } break; case CV_SymKind_REGREL32: case CV_SymKind_BPREL32: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymRegrel32, itype)); } break; case CV_SymKind_REGISTER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymRegister, itype)); } break; case CV_SymKind_CONSTANT: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymConstant, itype)); } break; case CV_SymKind_CALLSITEINFO: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymCallSiteInfo, itype)); } break; case CV_SymKind_CALLERS: case CV_SymKind_CALLEES: case CV_SymKind_INLINEES: { Assert(data.size >= sizeof(CV_SymFunctionList)); CV_SymFunctionList *func_list = (CV_SymFunctionList*)data.str; for (U64 i = 0; i < func_list->count; ++i) { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_SymFunctionList) + i * sizeof(CV_TypeIndex)); } } break; case CV_SymKind_INLINESITE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymInlineSite, inlinee)); } break; case CV_SymKind_HEAPALLOCSITE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymHeapAllocSite, itype)); } break; } return list; } internal CV_TypeIndexInfoList cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data) { CV_TypeIndexInfoList list = {0}; switch (leaf_kind) { case CV_LeafKind_NOTYPE: case CV_LeafKind_VTSHAPE: case CV_LeafKind_LABEL: case CV_LeafKind_NULL: case CV_LeafKind_NOTTRAN: { // no type indices } break; case CV_LeafKind_MODIFIER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafModifier, itype)); } break; case CV_LeafKind_POINTER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafPointer, itype)); CV_LeafPointer *ptr = (CV_LeafPointer *)data.str; CV_PointerKind ptr_kind = CV_PointerAttribs_Extract_Kind(ptr->attribs); if (ptr_kind == CV_PointerKind_BaseType) { // TODO: add CV_LeafPointerBaseType cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafPointer) + 0); } else { CV_PointerMode ptr_mode = CV_PointerAttribs_Extract_Mode(ptr->attribs); if (ptr_mode == CV_PointerMode_PtrMem || ptr_mode == CV_PointerMode_PtrMethod) { // TODO: add type for the CvLeafPointerMember to syms_cv.mc cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafPointer) + 0); } } } break; case CV_LeafKind_ARRAY: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafArray, entry_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafArray, index_itype)); } break; case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: case CV_LeafKind_INTERFACE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, field_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, derived_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, vshape_itype)); } break; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, field_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, derived_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, vshape_itype)); } break; case CV_LeafKind_UNION: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUnion, field_itype)); } break; case CV_LeafKind_ALIAS: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafAlias, itype)); } break; case CV_LeafKind_FUNC_ID: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafFuncId, scope_string_id)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafFuncId, itype)); } break; case CV_LeafKind_MFUNC_ID: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFuncId, owner_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFuncId, itype)); } break; case CV_LeafKind_STRING_ID: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafStringId, substr_list_id)); } break; case CV_LeafKind_UDT_SRC_LINE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUDTSrcLine, udt_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafUDTSrcLine, src_string_id)); } break; case CV_LeafKind_UDT_MOD_SRC_LINE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUDTModSrcLine, udt_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafUDTModSrcLine, src_string_id)); } break; case CV_LeafKind_BUILDINFO: { Assert(data.size >= sizeof(CV_LeafBuildInfo)); CV_LeafBuildInfo *build_info = (CV_LeafBuildInfo *)data.str; for (U16 i = 0; i < build_info->count; ++i) { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_LeafBuildInfo) + i * sizeof(CV_ItemId)); } } break; case CV_LeafKind_ENUM: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafEnum, base_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafEnum, field_itype)); } break; case CV_LeafKind_PROCEDURE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafProcedure, ret_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafProcedure, arg_itype)); } break; case CV_LeafKind_MFUNCTION: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, ret_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, class_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, this_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, arg_itype)); } break; case CV_LeafKind_VFTABLE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFTable, owner_itype)); cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFTable, base_table_itype)); } break; case CV_LeafKind_VFTPATH: { Assert(sizeof(CV_LeafVFPath) <= data.size); CV_LeafVFPath *vfpath = (CV_LeafVFPath *)data.str; for (U32 i = 0; i < vfpath->count; ++i) { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafVFPath) + i * sizeof(CV_TypeId)); } } break; case CV_LeafKind_TYPESERVER: case CV_LeafKind_TYPESERVER2: case CV_LeafKind_TYPESERVER_ST: { // no type indices } break; case CV_LeafKind_SKIP: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafSkip, itype)); } break; case CV_LeafKind_SUBSTR_LIST: { Assert(sizeof(CV_LeafArgList) <= data.size); CV_LeafArgList *arg_list = (CV_LeafArgList*)data.str; for (U32 i = 0; i < arg_list->count; ++i) { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_LeafArgList) + i * sizeof(CV_TypeIndex)); } } break; case CV_LeafKind_ARGLIST: { Assert(sizeof(CV_LeafArgList) <= data.size); CV_LeafArgList *arg_list = (CV_LeafArgList*)data.str; for (U32 i = 0; i < arg_list->count; ++i) { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafArgList) + i * sizeof(CV_TypeIndex)); } } break; case CV_LeafKind_LIST: case CV_LeafKind_FIELDLIST: { for (U64 cursor = 0; cursor < data.size; ) { CV_LeafKind list_member_kind = 0; U64 read_size = str8_deserial_read_struct(data, cursor, &list_member_kind); if(read_size != sizeof(list_member_kind)) { Assert(!"malformed LF_FIELDLIST"); break; } cursor += read_size; switch (list_member_kind) { default: Assert(!"TODO: handle malformed field member"); break; case CV_LeafKind_INDEX: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafIndex, itype)); cursor += sizeof(CV_LeafIndex); } break; case CV_LeafKind_MEMBER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMember, itype)); cursor += sizeof(CV_LeafMember); CV_NumericParsed size; cursor += cv_read_numeric(data, cursor, &size); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_STMEMBER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafStMember, itype)); cursor += sizeof(CV_LeafStMember); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_METHOD: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMethod, list_itype)); cursor += sizeof(CV_LeafMethod); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_ONEMETHOD: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafOneMethod, itype)); CV_LeafOneMethod onemethod; cursor += str8_deserial_read_struct(data, cursor, &onemethod); CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(onemethod.attribs); if(prop == CV_MethodProp_PureIntro || prop == CV_MethodProp_Intro) { cursor += sizeof(U32); // virtoff } String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_ENUMERATE: { // no type index cursor += sizeof(CV_LeafEnumerate); CV_NumericParsed value; cursor += cv_read_numeric(data, cursor, &value); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_NESTTYPE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafNestType, itype)); cursor += sizeof(CV_LeafNestType); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_NESTTYPEEX: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafNestTypeEx, itype)); cursor += sizeof(CV_LeafNestTypeEx); String8 name; cursor += str8_deserial_read_cstr(data, cursor, &name); } break; case CV_LeafKind_BCLASS: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafBClass, itype)); cursor += sizeof(CV_LeafBClass); CV_NumericParsed offset; cursor += cv_read_numeric(data, cursor, &offset); } break; case CV_LeafKind_VBCLASS: case CV_LeafKind_IVBCLASS: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVBClass, itype)); cursor += sizeof(CV_LeafVBClass); CV_NumericParsed virtual_base_pointer; cursor += cv_read_numeric(data, cursor, &virtual_base_pointer); CV_NumericParsed virtual_base_offset; cursor += cv_read_numeric(data, cursor, &virtual_base_offset); } break; case CV_LeafKind_VFUNCTAB: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVFuncTab, itype)); cursor += sizeof(CV_LeafVFuncTab); } break; case CV_LeafKind_VFUNCOFF: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVFuncOff, itype)); cursor += sizeof(CV_LeafVFuncOff); } break; } cursor = AlignPow2(cursor, 4); } } break; case CV_LeafKind_METHOD: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMethod, list_itype)); } break; case CV_LeafKind_METHODLIST: { for (U64 cursor = 0; cursor < data.size; ) { // read method CV_LeafMethodListMember method; U64 read_size = str8_deserial_read_struct(data, cursor, &method); // error check read if (read_size != sizeof(method)) { Assert(!"malformed LF_METHODLIST"); break; } // push type index offset cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMethodListMember, itype)); // take into account intro virtual offset CV_MethodProp mprop = CV_FieldAttribs_Extract_MethodProp(method.attribs); if (mprop == CV_MethodProp_Intro || mprop == CV_MethodProp_PureIntro) { read_size += sizeof(U32); } // advance cursor += read_size; } } break; case CV_LeafKind_ONEMETHOD: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafOneMethod, itype)); } break; case CV_LeafKind_BITFIELD: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafBitField, itype)); } break; case CV_LeafKind_PRECOMP: case CV_LeafKind_REFSYM: { // no type indices } break; case CV_LeafKind_INDEX: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafIndex, itype)); } break; case CV_LeafKind_MEMBER: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMember, itype)); } break; case CV_LeafKind_VFUNCTAB: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFuncTab, itype)); } break; case CV_LeafKind_VFUNCOFF: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFuncOff, itype)); } break; case CV_LeafKind_NESTTYPE: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestType, itype)); } break; case CV_LeafKind_NESTTYPEEX: { cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestTypeEx, itype)); } break; default: { NotImplemented; } break; } return list; } internal CV_TypeIndexInfoList cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data) { CV_TypeIndexInfoList list = {0}; U64 cursor = 0; // first four bytes are always signature CV_C13InlineeLinesSig sig = max_U32; cursor += str8_deserial_read_struct(raw_data, cursor, &sig); while(cursor < raw_data.size) { // read header CV_C13InlineeSourceLineHeader *header = (CV_C13InlineeSourceLineHeader *) str8_deserial_get_raw_ptr(raw_data, cursor, sizeof(CV_C13InlineeSourceLineHeader)); // store type index offset cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, cursor + OffsetOf(CV_C13InlineeSourceLineHeader, inlinee)); // advance past header cursor += sizeof(*header); // skip extra files B32 has_extra_files = (sig == CV_C13InlineeLinesSig_EXTRA_FILES); if (has_extra_files) { U32 file_count = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &file_count); cursor += /* file id: */ sizeof(U32) * file_count; } } return list; } internal String8Array cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data) { String8Array result; if(ti_list.count > 0) { result.count = ti_list.count + 1; result.v = push_array_no_zero(arena, String8, result.count); U64 cursor = 0; U64 ti_idx = 0; for(CV_TypeIndexInfo *ti_info = ti_list.first; ti_info != 0; ti_info = ti_info->next, ++ti_idx) { result.v[ti_idx].size = ti_info->offset - cursor; result.v[ti_idx].str = data.str + cursor; cursor = ti_info->offset + sizeof(CV_TypeIndex); } result.v[result.count-1].size = data.size - cursor; result.v[result.count-1].str = data.str + cursor; } else { result.count = 1; result.v = push_array_no_zero(arena, String8, 1); result.v[0] = data; } return result; } internal U64 cv_name_offset_from_symbol(CV_SymKind kind, String8 data) { U64 offset = data.size; switch (kind) { case CV_SymKind_COMPILE: break; case CV_SymKind_OBJNAME: break; case CV_SymKind_THUNK32: { offset = sizeof(CV_SymThunk32); } break; case CV_SymKind_LABEL32: { offset = sizeof(CV_SymLabel32); } break; case CV_SymKind_REGISTER: { offset = sizeof(CV_SymRegister); } break; case CV_SymKind_CONSTANT: { offset = sizeof(CV_SymConstant); CV_NumericParsed size; offset += cv_read_numeric(data, offset, &size); } break; case CV_SymKind_UDT: { offset = sizeof(CV_SymUDT); } break; case CV_SymKind_BPREL32: { offset = sizeof(CV_SymBPRel32); } break; case CV_SymKind_LDATA32: case CV_SymKind_GDATA32: { offset = sizeof(CV_SymData32); } break; case CV_SymKind_PUB32: { offset = sizeof(CV_SymPub32); } break; case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: case CV_SymKind_LPROC32_ID: case CV_SymKind_GPROC32_ID: { offset = sizeof(CV_SymProc32); } break; case CV_SymKind_REGREL32: { offset = sizeof(CV_SymRegrel32); } break; case CV_SymKind_LTHREAD32: case CV_SymKind_GTHREAD32: { offset = sizeof(CV_SymData32); } break; case CV_SymKind_COMPILE2: break; case CV_SymKind_LOCALSLOT: { offset = sizeof(CV_SymSlot); } break; case CV_SymKind_PROCREF: case CV_SymKind_LPROCREF: case CV_SymKind_DATAREF: { offset = sizeof(CV_SymRef2); } break; case CV_SymKind_TRAMPOLINE: break; case CV_SymKind_LOCAL: { offset = sizeof(CV_SymLocal); } break; default: InvalidPath; } return offset; } internal String8 cv_name_from_symbol(CV_SymKind kind, String8 data) { U64 buf_off = cv_name_offset_from_symbol(kind, data); U8 *buf_ptr = data.str + buf_off; U8 *buf_opl = data.str + data.size; String8 name = str8_cstring_capped(buf_ptr, buf_opl); return name; } internal CV_UDTInfo cv_get_udt_info(CV_LeafKind kind, String8 data) { String8 name = str8_zero(); String8 unique_name = str8_zero(); CV_TypeProps props = 0; switch(kind) { case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: case CV_LeafKind_INTERFACE: { U64 cursor = 0; CV_LeafStruct udt; cursor += str8_deserial_read_struct(data, cursor, &udt); props = udt.props; CV_NumericParsed size; cursor += cv_read_numeric(data, cursor, &size); cursor += str8_deserial_read_cstr(data, cursor, &name); if (udt.props & CV_TypeProp_HasUniqueName) { cursor += str8_deserial_read_cstr(data, cursor, &unique_name); } } break; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { U64 cursor = 0; CV_LeafStruct2 udt; cursor += str8_deserial_read_struct(data, cursor, &udt); props = udt.props; CV_NumericParsed size; cursor += cv_read_numeric(data, cursor, &size); cursor += str8_deserial_read_cstr(data, cursor, &name); if (udt.props & CV_TypeProp_HasUniqueName) { cursor += str8_deserial_read_cstr(data, cursor, &unique_name); } } break; case CV_LeafKind_UNION: { U64 cursor = 0; CV_LeafUnion udt; cursor += str8_deserial_read_struct(data, cursor, &udt); CV_NumericParsed size; cursor += cv_read_numeric(data, cursor, &size); props = udt.props; cursor += str8_deserial_read_cstr(data, cursor, &name); if(udt.props & CV_TypeProp_HasUniqueName) { cursor += str8_deserial_read_cstr(data, cursor, &unique_name); } } break; case CV_LeafKind_ENUM: { U64 cursor = 0; CV_LeafEnum udt; cursor += str8_deserial_read_struct(data, cursor, &udt); props = udt.props; cursor += str8_deserial_read_cstr(data, cursor, &name); if(udt.props & CV_TypeProp_HasUniqueName) { cursor += str8_deserial_read_cstr(data, cursor, &unique_name); } } break; // dbi/tpi.cpp:1332 case CV_LeafKind_UDT_SRC_LINE: { CV_LeafUDTSrcLine *src_line = str8_deserial_get_raw_ptr(data, 0, sizeof(CV_LeafUDTSrcLine)); name = str8_struct(&src_line->udt_itype); } break; case CV_LeafKind_UDT_MOD_SRC_LINE: { CV_LeafUDTModSrcLine *mod_src_line = str8_deserial_get_raw_ptr(data, 0, sizeof(CV_LeafUDTModSrcLine)); name = str8_struct(&mod_src_line->udt_itype); } break; case CV_LeafKind_ALIAS: { str8_deserial_read_cstr(data, 0, &name); } break; default: { InvalidPath; } break; } CV_UDTInfo info = {0}; info.name = name; info.unique_name = unique_name; info.props = props; return info; } internal String8 cv_name_from_udt_info(CV_UDTInfo udt_info) { if (udt_info.props & CV_TypeProp_HasUniqueName) { return udt_info.unique_name; } return udt_info.name; } //- rjf: record range stream parsing internal CV_RecRangeStream* cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align) { Assert(1 <= sym_align && IsPow2OrZero(sym_align)); CV_RecRangeStream *result = push_array(arena, CV_RecRangeStream, 1); U8 *data = sym_data.str; U64 cursor = 0; U64 cap = sym_data.size; for(;cursor + sizeof(CV_RecHeader) <= cap;) { // setup a new chunk CV_RecRangeChunk *cur_chunk = push_array_aligned(arena, CV_RecRangeChunk, 1, 64); SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk); U64 partial_count = 0; for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1) { // compute cap CV_RecHeader *hdr = (CV_RecHeader*)(data + cursor); U64 symbol_cap_unclamped = cursor + 2 + hdr->size; U64 symbol_cap = ClampTop(symbol_cap_unclamped, cap); // push on range cur_chunk->ranges[partial_count].off = cursor + 2; cur_chunk->ranges[partial_count].hdr = *hdr; // update cursor U32 next_pos = AlignPow2(symbol_cap, sym_align); cursor = next_pos; } result->total_count += partial_count; } return result; } internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream) { U64 total_count = stream->total_count; CV_RecRange *ranges = push_array_no_zero_aligned(arena, CV_RecRange, total_count, 8); U64 idx = 0; for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next) { U64 copy_count_raw = total_count - idx; U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); idx += copy_count; } CV_RecRangeArray result = {0}; result.ranges = ranges; result.count = total_count; return result; } //- rjf: sym stream parsing internal CV_SymParsed * cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align) { Assert(1 <= sym_align && IsPow2OrZero(sym_align)); ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); //- rjf: gather symbols CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, sym_data, sym_align); //- rjf: convert to result, fill basics CV_SymParsed *result = push_array(arena, CV_SymParsed, 1); result->data = sym_data; result->sym_align = sym_align; result->sym_ranges = cv_rec_range_array_from_stream(arena, stream); //- rjf: extract top-level-info { CV_RecRange *range = result->sym_ranges.ranges; CV_RecRange *opl = range + result->sym_ranges.count; for(;range < opl; range += 1) { U8 *first = sym_data.str + range->off + 2; U64 cap = range->hdr.size - 2; switch(range->hdr.kind) { case CV_SymKind_COMPILE: if(sizeof(CV_SymCompile) <= cap) { CV_SymCompile *compile = (CV_SymCompile*)first; String8 ver_str = str8_cstring_capped((char*)(compile + 1), (char *)(first + cap)); result->info.arch = compile->machine; result->info.language = CV_CompileFlags_Extract_Language(compile->flags);; result->info.compiler_name = ver_str; }break; case CV_SymKind_COMPILE2: if(sizeof(CV_SymCompile2) <= cap) { CV_SymCompile2 *compile2 = (CV_SymCompile2*)first; String8 ver_str = str8_cstring_capped((char*)(compile2 + 1), (char*)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile2->ver_major, compile2->ver_minor, compile2->ver_build); result->info.arch = compile2->machine; result->info.language = CV_Compile2Flags_Extract_Language(compile2->flags);; result->info.compiler_name = compiler_name; }break; case CV_SymKind_COMPILE3: if(sizeof(CV_SymCompile3) <= cap) { CV_SymCompile3 *compile3 = (CV_SymCompile3*)first; String8 ver_str = str8_cstring_capped((char*)(compile3 + 1), (char *)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile3->ver_major, compile3->ver_minor, compile3->ver_build); result->info.arch = compile3->machine; result->info.language = CV_Compile3Flags_Extract_Language(compile3->flags);; result->info.compiler_name = compiler_name; }break; } } } scratch_end(scratch); ProfEnd(); return result; } //- rjf: leaf stream parsing internal CV_LeafParsed * cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // gather up symbols CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, leaf_data, 1); // convert to result CV_LeafParsed *result = push_array(arena, CV_LeafParsed, 1); result->data = leaf_data; result->itype_first = itype_first; result->itype_opl = itype_first + stream->total_count; result->leaf_ranges = cv_rec_range_array_from_stream(arena, stream); scratch_end(scratch); ProfEnd(); return result; } internal CV_C13Parsed * cv_c13_parsed_from_data(Arena *arena, String8 c13_data, String8 strtbl, COFF_SectionHeaderArray sections) { ProfBeginFunction(); ////////////////////////////// //- rjf: gather c13 sub-sections // CV_C13SubSectionNode *file_chksms = 0; CV_C13SubSectionNode *first = 0; CV_C13SubSectionNode *last = 0; U64 count = 0; { U32 cursor = 0; for(; cursor + sizeof(CV_C13SubSectionHeader) <= c13_data.size;) { // read header CV_C13SubSectionHeader *hdr = (CV_C13SubSectionHeader*)(c13_data.str + cursor); // get sub section info U32 sub_section_off = cursor + sizeof(*hdr); U32 sub_section_size_raw = hdr->size; U32 after_sub_section_off_unclamped = sub_section_off + sub_section_size_raw; U32 after_sub_section_off = ClampTop(after_sub_section_off_unclamped, c13_data.size); U32 sub_section_size = after_sub_section_off - sub_section_off; // emit sub section if(!(hdr->kind & CV_C13SubSectionKind_IgnoreFlag)) { CV_C13SubSectionNode *node = push_array(arena, CV_C13SubSectionNode, 1); SLLQueuePush(first, last, node); count += 1; node->kind = hdr->kind; node->off = sub_section_off; node->size = sub_section_size; if(hdr->kind == CV_C13SubSectionKind_FileChksms) { file_chksms = node; } } // move cursor cursor = AlignPow2(after_sub_section_off, 4); } } ////////////////////////////// //- rjf: parse each sub-section // U64 inlinee_lines_parsed_slots_count = 4096; CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots = push_array(arena, CV_C13InlineeLinesParsedNode *, inlinee_lines_parsed_slots_count); for(CV_C13SubSectionNode *node = first; node != 0; node = node->next) { U8 *first = c13_data.str + node->off; U32 cap = node->size; switch(node->kind) { default:{}break; ////////////////////////// //- rjf: line info sub-section // case CV_C13SubSectionKind_Lines: if(sizeof(CV_C13SubSecLinesHeader) <= cap) { // read header U32 read_off = 0; U64 read_off_opl = node->size; CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off); read_off += sizeof(*hdr); // rjf: extract section index U32 sec_idx = hdr->sec; // rjf: bad section index -> skip if(sec_idx < 1 || sections.count < sec_idx) { continue; } // extract top level info B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns); U64 secrel_off = hdr->sec_off; U64 secrel_opl = secrel_off + hdr->len; U64 sec_base_off = sections.v[sec_idx - 1].voff; // read files for(;read_off+sizeof(CV_C13File) <= read_off_opl;) { // rjf: grab next file header CV_C13File *file = (CV_C13File*)(first + read_off); U32 file_off = file->file_off; U32 line_count_unclamped = file->num_lines; U32 block_size = file->block_size; // file_name / checksum from file_off String8 file_name = {0}; CV_C13ChecksumKind checksum_kind = CV_C13ChecksumKind_Null; String8 checksum_value = {0}; if(file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off); U32 name_off = checksum->name_off; file_name = str8_cstring_capped((char*)(strtbl.str + name_off), (char*)(strtbl.str + strtbl.size)); checksum_kind = checksum->kind; checksum_value = str8_skip(c13_data, file_chksms->off + file_off + sizeof(*checksum)); checksum_value.size = Min(checksum->len, checksum_value.size); } // array layouts U32 line_item_size = sizeof(CV_C13Line); if (has_cols){ line_item_size += sizeof(CV_C13Column); } U32 line_array_off = read_off + sizeof(*file); U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; U32 line_count = ClampTop(line_count_unclamped, line_count_max); U32 col_array_off = line_array_off + line_count*sizeof(CV_C13Line); // parse lines U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); U32 *line_nums = push_array_no_zero(arena, U32, line_count); { CV_C13Line *line_ptr = (CV_C13Line*)(first + line_array_off); CV_C13Line *line_opl = line_ptr + line_count; // TODO(allen): check order correctness here U32 i = 0; for (; line_ptr < line_opl; line_ptr += 1, i += 1){ voffs[i] = line_ptr->off + secrel_off + sec_base_off; line_nums[i] = CV_C13LineFlags_Extract_LineNumber(line_ptr->flags); } voffs[i] = secrel_opl + sec_base_off; } // emit parsed lines CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; lines_parsed->sec_idx = sec_idx; lines_parsed->file_off = file_off; lines_parsed->secrel_base_off = secrel_off; lines_parsed->file_name = file_name; lines_parsed->checksum_kind = checksum_kind; lines_parsed->checksum = checksum_value; lines_parsed->voffs = voffs; lines_parsed->line_nums = line_nums; lines_parsed->line_count = line_count; SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); // rjf: advance read_off += sizeof(*file); read_off += line_item_size*line_count; } }break; ////////////////////////// //- rjf: inlinee line info sub-section // case CV_C13SubSectionKind_InlineeLines: if(sizeof(CV_C13InlineeLinesSig) <= cap) { // rjf: read sig U32 read_off = 0; U64 read_off_opl = node->size; CV_C13InlineeLinesSig *sig = (CV_C13InlineeLinesSig *)(first + read_off); read_off += sizeof(*sig); // rjf: read source lines for(;read_off + sizeof(CV_C13InlineeSourceLineHeader) <= read_off_opl;) { // rjf: read next header CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(first + read_off); read_off += sizeof(*hdr); // rjf: file_off -> file_name String8 file_name = {0}; CV_C13ChecksumKind checksum_kind = CV_C13ChecksumKind_Null; String8 checksum_value = {0}; if(hdr->file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off); U32 name_off = checksum->name_off; file_name = str8_cstring_capped((char*)(strtbl.str + name_off), (char*)(strtbl.str + strtbl.size)); checksum_kind = checksum->kind; checksum_value = str8_skip(c13_data, file_chksms->off + hdr->file_off + sizeof(*checksum)); checksum_value.size = Min(checksum->len, checksum_value.size); } // rjf: parse extra files U32 extra_file_count = 0; U32 *extra_files = 0; if(*sig == CV_C13InlineeLinesSig_EXTRA_FILES && read_off+sizeof(U32) <= read_off_opl) { U32 *extra_file_count_ptr = (U32 *)(first + read_off); read_off += sizeof(*extra_file_count_ptr); U32 max_extra_file_count = (read_off_opl-read_off)/sizeof(U32); extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count); extra_files = (U32 *)(first + read_off); read_off += sizeof(*extra_files)*extra_file_count; } // rjf: push node for this inlinee lines parsed into this subsection's list CV_C13InlineeLinesParsedNode *n = push_array(arena, CV_C13InlineeLinesParsedNode, 1); SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n); n->v.inlinee = hdr->inlinee; n->v.file_off = hdr->file_off; n->v.file_name = file_name; n->v.checksum_kind = checksum_kind; n->v.checksum = checksum_value; n->v.first_source_ln = hdr->first_source_ln; n->v.extra_file_count = extra_file_count; n->v.extra_files = extra_files; // rjf: push node into inlinee parse hash table U64 hash = cv_hash_from_item_id(hdr->inlinee); U64 slot_idx = hash%inlinee_lines_parsed_slots_count; SLLStackPush_N(inlinee_lines_parsed_slots[slot_idx], n, hash_next); } }break; } } ////////////////////////////// //- rjf: fill output // CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1); result->data = c13_data; result->first_sub_section = first; result->last_sub_section = last; result->sub_section_count = count; result->file_chksms_sub_section = file_chksms; result->inlinee_lines_parsed_slots = inlinee_lines_parsed_slots; result->inlinee_lines_parsed_slots_count = inlinee_lines_parsed_slots_count; ProfEnd(); return result; } ================================================ FILE: src/codeview/codeview_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_PARSE_H #define CODEVIEW_PARSE_H //////////////////////////////// //~ CodeView Common Parser Types // CV_Numeric layout // x: U16 // buf: U8[] // case (x < 0x8000): kind=U16 val=x // case (x >= 0x8000): kind=x val=buf typedef struct CV_NumericParsed CV_NumericParsed; struct CV_NumericParsed { CV_NumericKind kind; U8 *val; U64 encoded_size; }; typedef struct CV_RecRange CV_RecRange; struct CV_RecRange { U32 off; CV_RecHeader hdr; }; #define CV_REC_RANGE_CHUNK_SIZE 511 typedef struct CV_RecRangeChunk CV_RecRangeChunk; struct CV_RecRangeChunk { struct CV_RecRangeChunk *next; CV_RecRange ranges[CV_REC_RANGE_CHUNK_SIZE]; }; typedef struct CV_RecRangeStream CV_RecRangeStream; struct CV_RecRangeStream { CV_RecRangeChunk *first_chunk; CV_RecRangeChunk *last_chunk; U64 total_count; }; typedef struct CV_RecRangeArray CV_RecRangeArray; struct CV_RecRangeArray { CV_RecRange *ranges; U64 count; }; //////////////////////////////// //~ CodeView Sym Parser Types typedef struct CV_SymTopLevelInfo CV_SymTopLevelInfo; struct CV_SymTopLevelInfo { CV_Arch arch; CV_Language language; String8 compiler_name; }; typedef struct CV_SymParsed CV_SymParsed; struct CV_SymParsed { // source information String8 data; U64 sym_align; // sym index derived from source CV_RecRangeArray sym_ranges; // top-level info derived from the syms CV_SymTopLevelInfo info; }; //////////////////////////////// //~ CodeView Leaf Parser Types typedef struct CV_LeafParsed CV_LeafParsed; struct CV_LeafParsed { // source information String8 data; CV_TypeId itype_first; CV_TypeId itype_opl; // leaf index derived from source CV_RecRangeArray leaf_ranges; }; //////////////////////////////// //~ CodeView C13 Info Parser Types typedef struct CV_C13InlineSiteDecoder CV_C13InlineSiteDecoder; struct CV_C13InlineSiteDecoder { U64 cursor; U64 parent_voff; CV_InlineRangeKind range_kind; U32 code_length; U32 code_offset; U32 file_off; S32 ln; S32 cn; U64 code_offset_lo; B32 code_offset_changed; B32 code_offset_lo_changed; B32 code_length_changed; B32 ln_changed; B32 file_off_changed; Rng1U64 last_range; U32 file_count; Rng1U64 file_last_range; U64 file_line_count; U64 file_last_ln; }; typedef U32 CV_C13InlineSiteDecoderStepFlags; enum { CV_C13InlineSiteDecoderStepFlag_EmitRange = (1 << 0), CV_C13InlineSiteDecoderStepFlag_ExtendLastRange = (1 << 1), CV_C13InlineSiteDecoderStepFlag_EmitFile = (1 << 2), CV_C13InlineSiteDecoderStepFlag_EmitLine = (1 << 3), }; typedef struct CV_C13InlineSiteDecoderStep CV_C13InlineSiteDecoderStep; struct CV_C13InlineSiteDecoderStep { CV_C13InlineSiteDecoderStepFlags flags; Rng1U64 range; U64 line_voff; U64 line_voff_end; U64 ln; U64 cn; U32 file_off; }; typedef struct CV_C13LinesParsed CV_C13LinesParsed; struct CV_C13LinesParsed { // raw info U32 sec_idx; U32 file_off; U64 secrel_base_off; // parsed info String8 file_name; CV_C13ChecksumKind checksum_kind; String8 checksum; U64 *voffs; // [line_count + 1] U32 *line_nums; // [line_count] U16 *col_nums; // [2*line_count] U32 line_count; }; typedef struct CV_C13LinesParsedNode CV_C13LinesParsedNode; struct CV_C13LinesParsedNode { CV_C13LinesParsedNode *next; CV_C13LinesParsed v; }; typedef struct CV_C13InlineeLinesParsed CV_C13InlineeLinesParsed; struct CV_C13InlineeLinesParsed { CV_ItemId inlinee; U32 file_off; String8 file_name; CV_C13ChecksumKind checksum_kind; String8 checksum; U32 first_source_ln; U32 extra_file_count; U32 *extra_files; }; typedef struct CV_C13InlineeLinesParsedNode CV_C13InlineeLinesParsedNode; struct CV_C13InlineeLinesParsedNode { CV_C13InlineeLinesParsedNode *next; CV_C13InlineeLinesParsedNode *hash_next; CV_C13InlineeLinesParsed v; }; typedef struct CV_C13SubSectionNode CV_C13SubSectionNode; struct CV_C13SubSectionNode { struct CV_C13SubSectionNode *next; CV_C13SubSectionKind kind; U32 off; U32 size; CV_C13LinesParsedNode *lines_first; CV_C13LinesParsedNode *lines_last; CV_C13InlineeLinesParsedNode *inlinee_lines_first; CV_C13InlineeLinesParsedNode *inlinee_lines_last; }; typedef struct CV_C13Parsed CV_C13Parsed; struct CV_C13Parsed { // rjf: source data String8 data; // rjf: full sub-section list CV_C13SubSectionNode *first_sub_section; CV_C13SubSectionNode *last_sub_section; U64 sub_section_count; // rjf: fastpath to file checksums section CV_C13SubSectionNode *file_chksms_sub_section; // rjf: fastpath to map inlinee CV_ItemId -> CV_InlineeLinesParsed quickly CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots; U64 inlinee_lines_parsed_slots_count; }; typedef struct CV_UDTInfo CV_UDTInfo; struct CV_UDTInfo { String8 name; String8 unique_name; CV_TypeProps props; }; //////////////////////////////// //~ CodeView Compound Types typedef struct CV_TypeIdArray CV_TypeIdArray; struct CV_TypeIdArray { CV_TypeId *itypes; U64 count; }; //////////////////////////////// //- Hasher internal U64 cv_hash_from_string(String8 string); internal U64 cv_hash_from_item_id(CV_ItemId item_id); //- Numeric Decoder internal CV_NumericParsed cv_numeric_from_data_range(U8 *first, U8 *opl); internal U64 cv_read_numeric(String8 data, U64 offset, CV_NumericParsed *out); internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); internal U64 cv_u64_from_numeric(CV_NumericParsed *num); internal S64 cv_s64_from_numeric(CV_NumericParsed *num); internal F64 cv_f64_from_numeric(CV_NumericParsed *num); //- Inlinee Lines Binary Annot Decoder internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value); internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value); internal S32 cv_inline_annot_signed_from_unsigned_operand(U32 value); internal CV_C13InlineSiteDecoder cv_c13_inline_site_decoder_init(U32 file_off, U32 first_source_ln, U32 parent_voff); internal CV_C13InlineSiteDecoderStep cv_c13_inline_site_decoder_step(CV_C13InlineSiteDecoder *decoder, String8 binary_annots); //- Symbol/Leaf Helpers internal B32 cv_is_udt_name_anon(String8 name); internal B32 cv_is_global_symbol(CV_SymKind kind); internal B32 cv_is_typedef(CV_SymKind kind); internal B32 cv_is_scope_symbol(CV_SymKind kind); internal B32 cv_is_end_symbol(CV_SymKind kind); internal B32 cv_is_udt(CV_LeafKind kind); internal B32 cv_is_leaf_type_server(CV_LeafKind kind); internal B32 cv_is_leaf_pch(CV_LeafKind kind); internal CV_TypeIndexSource cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind); internal CV_TypeIndexInfoList cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data); internal CV_TypeIndexInfoList cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data); internal CV_TypeIndexInfoList cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data); internal String8Array cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data); internal U64 cv_name_offset_from_symbol(CV_SymKind kind, String8 data); internal String8 cv_name_from_symbol(CV_SymKind kind, String8 data); internal CV_UDTInfo cv_get_udt_info(CV_LeafKind kind, String8 data); internal String8 cv_name_from_udt_info(CV_UDTInfo udt_info); //- rjf: record range stream parsing internal CV_RecRangeStream * cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); //- rjf: sym stream parsing internal CV_SymParsed * cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); //- rjf: leaf stream parsing internal CV_LeafParsed * cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); internal CV_C13Parsed * cv_c13_parsed_from_data(Arena *arena, String8 c13_data, String8 strtbl, COFF_SectionHeaderArray sections); #endif // CODEVIEW_PARSE_H ================================================ FILE: src/codeview/generated/codeview.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE internal String8 cv_string_from_numeric_kind(CV_NumericKind v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_NumericKind_CHAR:{result = str8_lit("CHAR");}break; case CV_NumericKind_SHORT:{result = str8_lit("SHORT");}break; case CV_NumericKind_USHORT:{result = str8_lit("USHORT");}break; case CV_NumericKind_LONG:{result = str8_lit("LONG");}break; case CV_NumericKind_ULONG:{result = str8_lit("ULONG");}break; case CV_NumericKind_FLOAT32:{result = str8_lit("FLOAT32");}break; case CV_NumericKind_FLOAT64:{result = str8_lit("FLOAT64");}break; case CV_NumericKind_FLOAT80:{result = str8_lit("FLOAT80");}break; case CV_NumericKind_FLOAT128:{result = str8_lit("FLOAT128");}break; case CV_NumericKind_QUADWORD:{result = str8_lit("QUADWORD");}break; case CV_NumericKind_UQUADWORD:{result = str8_lit("UQUADWORD");}break; case CV_NumericKind_FLOAT48:{result = str8_lit("FLOAT48");}break; case CV_NumericKind_COMPLEX32:{result = str8_lit("COMPLEX32");}break; case CV_NumericKind_COMPLEX64:{result = str8_lit("COMPLEX64");}break; case CV_NumericKind_COMPLEX80:{result = str8_lit("COMPLEX80");}break; case CV_NumericKind_COMPLEX128:{result = str8_lit("COMPLEX128");}break; case CV_NumericKind_VARSTRING:{result = str8_lit("VARSTRING");}break; case CV_NumericKind_OCTWORD:{result = str8_lit("OCTWORD");}break; case CV_NumericKind_UOCTWORD:{result = str8_lit("UOCTWORD");}break; case CV_NumericKind_DECIMAL:{result = str8_lit("DECIMAL");}break; case CV_NumericKind_DATE:{result = str8_lit("DATE");}break; case CV_NumericKind_UTF8STRING:{result = str8_lit("UTF8STRING");}break; case CV_NumericKind_FLOAT16:{result = str8_lit("FLOAT16");}break; } return result; } internal String8 cv_string_from_arch(CV_Arch v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_Arch_8080:{result = str8_lit("8080");}break; case CV_Arch_8086:{result = str8_lit("8086");}break; case CV_Arch_80286:{result = str8_lit("80286");}break; case CV_Arch_80386:{result = str8_lit("80386");}break; case CV_Arch_80486:{result = str8_lit("80486");}break; case CV_Arch_PENTIUM:{result = str8_lit("PENTIUM");}break; case CV_Arch_PENTIUMII:{result = str8_lit("PENTIUMII");}break; case CV_Arch_PENTIUMIII:{result = str8_lit("PENTIUMIII");}break; case CV_Arch_MIPS:{result = str8_lit("MIPS");}break; case CV_Arch_MIPS16:{result = str8_lit("MIPS16");}break; case CV_Arch_MIPS32:{result = str8_lit("MIPS32");}break; case CV_Arch_MIPS64:{result = str8_lit("MIPS64");}break; case CV_Arch_MIPSI:{result = str8_lit("MIPSI");}break; case CV_Arch_MIPSII:{result = str8_lit("MIPSII");}break; case CV_Arch_MIPSIII:{result = str8_lit("MIPSIII");}break; case CV_Arch_MIPSIV:{result = str8_lit("MIPSIV");}break; case CV_Arch_MIPSV:{result = str8_lit("MIPSV");}break; case CV_Arch_M68000:{result = str8_lit("M68000");}break; case CV_Arch_M68010:{result = str8_lit("M68010");}break; case CV_Arch_M68020:{result = str8_lit("M68020");}break; case CV_Arch_M68030:{result = str8_lit("M68030");}break; case CV_Arch_M68040:{result = str8_lit("M68040");}break; case CV_Arch_ALPHA:{result = str8_lit("ALPHA");}break; case CV_Arch_ALPHA_21164:{result = str8_lit("ALPHA_21164");}break; case CV_Arch_ALPHA_21164A:{result = str8_lit("ALPHA_21164A");}break; case CV_Arch_ALPHA_21264:{result = str8_lit("ALPHA_21264");}break; case CV_Arch_ALPHA_21364:{result = str8_lit("ALPHA_21364");}break; case CV_Arch_PPC601:{result = str8_lit("PPC601");}break; case CV_Arch_PPC603:{result = str8_lit("PPC603");}break; case CV_Arch_PPC604:{result = str8_lit("PPC604");}break; case CV_Arch_PPC620:{result = str8_lit("PPC620");}break; case CV_Arch_PPCFP:{result = str8_lit("PPCFP");}break; case CV_Arch_PPCBE:{result = str8_lit("PPCBE");}break; case CV_Arch_SH3:{result = str8_lit("SH3");}break; case CV_Arch_SH3E:{result = str8_lit("SH3E");}break; case CV_Arch_SH3DSP:{result = str8_lit("SH3DSP");}break; case CV_Arch_SH4:{result = str8_lit("SH4");}break; case CV_Arch_SHMEDIA:{result = str8_lit("SHMEDIA");}break; case CV_Arch_ARM3:{result = str8_lit("ARM3");}break; case CV_Arch_ARM4:{result = str8_lit("ARM4");}break; case CV_Arch_ARM4T:{result = str8_lit("ARM4T");}break; case CV_Arch_ARM5:{result = str8_lit("ARM5");}break; case CV_Arch_ARM5T:{result = str8_lit("ARM5T");}break; case CV_Arch_ARM6:{result = str8_lit("ARM6");}break; case CV_Arch_ARM_XMAC:{result = str8_lit("ARM_XMAC");}break; case CV_Arch_ARM_WMMX:{result = str8_lit("ARM_WMMX");}break; case CV_Arch_ARM7:{result = str8_lit("ARM7");}break; case CV_Arch_OMNI:{result = str8_lit("OMNI");}break; case CV_Arch_IA64_1:{result = str8_lit("IA64_1");}break; case CV_Arch_IA64_2:{result = str8_lit("IA64_2");}break; case CV_Arch_CEE:{result = str8_lit("CEE");}break; case CV_Arch_AM33:{result = str8_lit("AM33");}break; case CV_Arch_M32R:{result = str8_lit("M32R");}break; case CV_Arch_TRICORE:{result = str8_lit("TRICORE");}break; case CV_Arch_X64:{result = str8_lit("X64");}break; case CV_Arch_EBC:{result = str8_lit("EBC");}break; case CV_Arch_THUMB:{result = str8_lit("THUMB");}break; case CV_Arch_ARMNT:{result = str8_lit("ARMNT");}break; case CV_Arch_ARM64:{result = str8_lit("ARM64");}break; case CV_Arch_D3D11_SHADER:{result = str8_lit("D3D11_SHADER");}break; } return result; } internal String8 cv_string_from_sym_kind(CV_SymKind v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_SymKind_COMPILE:{result = str8_lit("COMPILE");}break; case CV_SymKind_REGISTER_16t:{result = str8_lit("REGISTER_16t");}break; case CV_SymKind_CONSTANT_16t:{result = str8_lit("CONSTANT_16t");}break; case CV_SymKind_UDT_16t:{result = str8_lit("UDT_16t");}break; case CV_SymKind_SSEARCH:{result = str8_lit("SSEARCH");}break; case CV_SymKind_END:{result = str8_lit("END");}break; case CV_SymKind_SKIP:{result = str8_lit("SKIP");}break; case CV_SymKind_CVRESERVE:{result = str8_lit("CVRESERVE");}break; case CV_SymKind_OBJNAME_ST:{result = str8_lit("OBJNAME_ST");}break; case CV_SymKind_ENDARG:{result = str8_lit("ENDARG");}break; case CV_SymKind_COBOLUDT_16t:{result = str8_lit("COBOLUDT_16t");}break; case CV_SymKind_MANYREG_16t:{result = str8_lit("MANYREG_16t");}break; case CV_SymKind_RETURN:{result = str8_lit("RETURN");}break; case CV_SymKind_ENTRYTHIS:{result = str8_lit("ENTRYTHIS");}break; case CV_SymKind_BPREL16:{result = str8_lit("BPREL16");}break; case CV_SymKind_LDATA16:{result = str8_lit("LDATA16");}break; case CV_SymKind_GDATA16:{result = str8_lit("GDATA16");}break; case CV_SymKind_PUB16:{result = str8_lit("PUB16");}break; case CV_SymKind_LPROC16:{result = str8_lit("LPROC16");}break; case CV_SymKind_GPROC16:{result = str8_lit("GPROC16");}break; case CV_SymKind_THUNK16:{result = str8_lit("THUNK16");}break; case CV_SymKind_BLOCK16:{result = str8_lit("BLOCK16");}break; case CV_SymKind_WITH16:{result = str8_lit("WITH16");}break; case CV_SymKind_LABEL16:{result = str8_lit("LABEL16");}break; case CV_SymKind_CEXMODEL16:{result = str8_lit("CEXMODEL16");}break; case CV_SymKind_VFTABLE16:{result = str8_lit("VFTABLE16");}break; case CV_SymKind_REGREL16:{result = str8_lit("REGREL16");}break; case CV_SymKind_BPREL32_16t:{result = str8_lit("BPREL32_16t");}break; case CV_SymKind_LDATA32_16t:{result = str8_lit("LDATA32_16t");}break; case CV_SymKind_GDATA32_16t:{result = str8_lit("GDATA32_16t");}break; case CV_SymKind_PUB32_16t:{result = str8_lit("PUB32_16t");}break; case CV_SymKind_LPROC32_16t:{result = str8_lit("LPROC32_16t");}break; case CV_SymKind_GPROC32_16t:{result = str8_lit("GPROC32_16t");}break; case CV_SymKind_THUNK32_ST:{result = str8_lit("THUNK32_ST");}break; case CV_SymKind_BLOCK32_ST:{result = str8_lit("BLOCK32_ST");}break; case CV_SymKind_WITH32_ST:{result = str8_lit("WITH32_ST");}break; case CV_SymKind_LABEL32_ST:{result = str8_lit("LABEL32_ST");}break; case CV_SymKind_CEXMODEL32:{result = str8_lit("CEXMODEL32");}break; case CV_SymKind_VFTABLE32_16t:{result = str8_lit("VFTABLE32_16t");}break; case CV_SymKind_REGREL32_16t:{result = str8_lit("REGREL32_16t");}break; case CV_SymKind_LTHREAD32_16t:{result = str8_lit("LTHREAD32_16t");}break; case CV_SymKind_GTHREAD32_16t:{result = str8_lit("GTHREAD32_16t");}break; case CV_SymKind_SLINK32:{result = str8_lit("SLINK32");}break; case CV_SymKind_LPROCMIPS_16t:{result = str8_lit("LPROCMIPS_16t");}break; case CV_SymKind_GPROCMIPS_16t:{result = str8_lit("GPROCMIPS_16t");}break; case CV_SymKind_PROCREF_ST:{result = str8_lit("PROCREF_ST");}break; case CV_SymKind_DATAREF_ST:{result = str8_lit("DATAREF_ST");}break; case CV_SymKind_ALIGN:{result = str8_lit("ALIGN");}break; case CV_SymKind_LPROCREF_ST:{result = str8_lit("LPROCREF_ST");}break; case CV_SymKind_OEM:{result = str8_lit("OEM");}break; case CV_SymKind_TI16_MAX:{result = str8_lit("TI16_MAX");}break; case CV_SymKind_CONSTANT_ST:{result = str8_lit("CONSTANT_ST");}break; case CV_SymKind_UDT_ST:{result = str8_lit("UDT_ST");}break; case CV_SymKind_COBOLUDT_ST:{result = str8_lit("COBOLUDT_ST");}break; case CV_SymKind_MANYREG_ST:{result = str8_lit("MANYREG_ST");}break; case CV_SymKind_BPREL32_ST:{result = str8_lit("BPREL32_ST");}break; case CV_SymKind_LDATA32_ST:{result = str8_lit("LDATA32_ST");}break; case CV_SymKind_GDATA32_ST:{result = str8_lit("GDATA32_ST");}break; case CV_SymKind_PUB32_ST:{result = str8_lit("PUB32_ST");}break; case CV_SymKind_LPROC32_ST:{result = str8_lit("LPROC32_ST");}break; case CV_SymKind_GPROC32_ST:{result = str8_lit("GPROC32_ST");}break; case CV_SymKind_VFTABLE32:{result = str8_lit("VFTABLE32");}break; case CV_SymKind_REGREL32_ST:{result = str8_lit("REGREL32_ST");}break; case CV_SymKind_LTHREAD32_ST:{result = str8_lit("LTHREAD32_ST");}break; case CV_SymKind_GTHREAD32_ST:{result = str8_lit("GTHREAD32_ST");}break; case CV_SymKind_LPROCMIPS_ST:{result = str8_lit("LPROCMIPS_ST");}break; case CV_SymKind_GPROCMIPS_ST:{result = str8_lit("GPROCMIPS_ST");}break; case CV_SymKind_FRAMEPROC:{result = str8_lit("FRAMEPROC");}break; case CV_SymKind_COMPILE2_ST:{result = str8_lit("COMPILE2_ST");}break; case CV_SymKind_MANYREG2_ST:{result = str8_lit("MANYREG2_ST");}break; case CV_SymKind_LPROCIA64_ST:{result = str8_lit("LPROCIA64_ST");}break; case CV_SymKind_GPROCIA64_ST:{result = str8_lit("GPROCIA64_ST");}break; case CV_SymKind_LOCALSLOT_ST:{result = str8_lit("LOCALSLOT_ST");}break; case CV_SymKind_PARAMSLOT_ST:{result = str8_lit("PARAMSLOT_ST");}break; case CV_SymKind_ANNOTATION:{result = str8_lit("ANNOTATION");}break; case CV_SymKind_GMANPROC_ST:{result = str8_lit("GMANPROC_ST");}break; case CV_SymKind_LMANPROC_ST:{result = str8_lit("LMANPROC_ST");}break; case CV_SymKind_RESERVED1:{result = str8_lit("RESERVED1");}break; case CV_SymKind_RESERVED2:{result = str8_lit("RESERVED2");}break; case CV_SymKind_RESERVED3:{result = str8_lit("RESERVED3");}break; case CV_SymKind_RESERVED4:{result = str8_lit("RESERVED4");}break; case CV_SymKind_LMANDATA_ST:{result = str8_lit("LMANDATA_ST");}break; case CV_SymKind_GMANDATA_ST:{result = str8_lit("GMANDATA_ST");}break; case CV_SymKind_MANFRAMEREL_ST:{result = str8_lit("MANFRAMEREL_ST");}break; case CV_SymKind_MANREGISTER_ST:{result = str8_lit("MANREGISTER_ST");}break; case CV_SymKind_MANSLOT_ST:{result = str8_lit("MANSLOT_ST");}break; case CV_SymKind_MANMANYREG_ST:{result = str8_lit("MANMANYREG_ST");}break; case CV_SymKind_MANREGREL_ST:{result = str8_lit("MANREGREL_ST");}break; case CV_SymKind_MANMANYREG2_ST:{result = str8_lit("MANMANYREG2_ST");}break; case CV_SymKind_MANTYPREF:{result = str8_lit("MANTYPREF");}break; case CV_SymKind_UNAMESPACE_ST:{result = str8_lit("UNAMESPACE_ST");}break; case CV_SymKind_ST_MAX:{result = str8_lit("ST_MAX");}break; case CV_SymKind_OBJNAME:{result = str8_lit("OBJNAME");}break; case CV_SymKind_THUNK32:{result = str8_lit("THUNK32");}break; case CV_SymKind_BLOCK32:{result = str8_lit("BLOCK32");}break; case CV_SymKind_WITH32:{result = str8_lit("WITH32");}break; case CV_SymKind_LABEL32:{result = str8_lit("LABEL32");}break; case CV_SymKind_REGISTER:{result = str8_lit("REGISTER");}break; case CV_SymKind_CONSTANT:{result = str8_lit("CONSTANT");}break; case CV_SymKind_UDT:{result = str8_lit("UDT");}break; case CV_SymKind_COBOLUDT:{result = str8_lit("COBOLUDT");}break; case CV_SymKind_MANYREG:{result = str8_lit("MANYREG");}break; case CV_SymKind_BPREL32:{result = str8_lit("BPREL32");}break; case CV_SymKind_LDATA32:{result = str8_lit("LDATA32");}break; case CV_SymKind_GDATA32:{result = str8_lit("GDATA32");}break; case CV_SymKind_PUB32:{result = str8_lit("PUB32");}break; case CV_SymKind_LPROC32:{result = str8_lit("LPROC32");}break; case CV_SymKind_GPROC32:{result = str8_lit("GPROC32");}break; case CV_SymKind_REGREL32:{result = str8_lit("REGREL32");}break; case CV_SymKind_LTHREAD32:{result = str8_lit("LTHREAD32");}break; case CV_SymKind_GTHREAD32:{result = str8_lit("GTHREAD32");}break; case CV_SymKind_LPROCMIPS:{result = str8_lit("LPROCMIPS");}break; case CV_SymKind_GPROCMIPS:{result = str8_lit("GPROCMIPS");}break; case CV_SymKind_COMPILE2:{result = str8_lit("COMPILE2");}break; case CV_SymKind_MANYREG2:{result = str8_lit("MANYREG2");}break; case CV_SymKind_LPROCIA64:{result = str8_lit("LPROCIA64");}break; case CV_SymKind_GPROCIA64:{result = str8_lit("GPROCIA64");}break; case CV_SymKind_LOCALSLOT:{result = str8_lit("LOCALSLOT");}break; case CV_SymKind_PARAMSLOT:{result = str8_lit("PARAMSLOT");}break; case CV_SymKind_LMANDATA:{result = str8_lit("LMANDATA");}break; case CV_SymKind_GMANDATA:{result = str8_lit("GMANDATA");}break; case CV_SymKind_MANFRAMEREL:{result = str8_lit("MANFRAMEREL");}break; case CV_SymKind_MANREGISTER:{result = str8_lit("MANREGISTER");}break; case CV_SymKind_MANSLOT:{result = str8_lit("MANSLOT");}break; case CV_SymKind_MANMANYREG:{result = str8_lit("MANMANYREG");}break; case CV_SymKind_MANREGREL:{result = str8_lit("MANREGREL");}break; case CV_SymKind_MANMANYREG2:{result = str8_lit("MANMANYREG2");}break; case CV_SymKind_UNAMESPACE:{result = str8_lit("UNAMESPACE");}break; case CV_SymKind_PROCREF:{result = str8_lit("PROCREF");}break; case CV_SymKind_DATAREF:{result = str8_lit("DATAREF");}break; case CV_SymKind_LPROCREF:{result = str8_lit("LPROCREF");}break; case CV_SymKind_ANNOTATIONREF:{result = str8_lit("ANNOTATIONREF");}break; case CV_SymKind_TOKENREF:{result = str8_lit("TOKENREF");}break; case CV_SymKind_GMANPROC:{result = str8_lit("GMANPROC");}break; case CV_SymKind_LMANPROC:{result = str8_lit("LMANPROC");}break; case CV_SymKind_TRAMPOLINE:{result = str8_lit("TRAMPOLINE");}break; case CV_SymKind_MANCONSTANT:{result = str8_lit("MANCONSTANT");}break; case CV_SymKind_ATTR_FRAMEREL:{result = str8_lit("ATTR_FRAMEREL");}break; case CV_SymKind_ATTR_REGISTER:{result = str8_lit("ATTR_REGISTER");}break; case CV_SymKind_ATTR_REGREL:{result = str8_lit("ATTR_REGREL");}break; case CV_SymKind_ATTR_MANYREG:{result = str8_lit("ATTR_MANYREG");}break; case CV_SymKind_SEPCODE:{result = str8_lit("SEPCODE");}break; case CV_SymKind_DEFRANGE_2005:{result = str8_lit("DEFRANGE_2005");}break; case CV_SymKind_DEFRANGE2_2005:{result = str8_lit("DEFRANGE2_2005");}break; case CV_SymKind_SECTION:{result = str8_lit("SECTION");}break; case CV_SymKind_COFFGROUP:{result = str8_lit("COFFGROUP");}break; case CV_SymKind_EXPORT:{result = str8_lit("EXPORT");}break; case CV_SymKind_CALLSITEINFO:{result = str8_lit("CALLSITEINFO");}break; case CV_SymKind_FRAMECOOKIE:{result = str8_lit("FRAMECOOKIE");}break; case CV_SymKind_DISCARDED:{result = str8_lit("DISCARDED");}break; case CV_SymKind_COMPILE3:{result = str8_lit("COMPILE3");}break; case CV_SymKind_ENVBLOCK:{result = str8_lit("ENVBLOCK");}break; case CV_SymKind_LOCAL:{result = str8_lit("LOCAL");}break; case CV_SymKind_DEFRANGE:{result = str8_lit("DEFRANGE");}break; case CV_SymKind_DEFRANGE_SUBFIELD:{result = str8_lit("DEFRANGE_SUBFIELD");}break; case CV_SymKind_DEFRANGE_REGISTER:{result = str8_lit("DEFRANGE_REGISTER");}break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL:{result = str8_lit("DEFRANGE_FRAMEPOINTER_REL");}break; case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER:{result = str8_lit("DEFRANGE_SUBFIELD_REGISTER");}break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:{result = str8_lit("DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE");}break; case CV_SymKind_DEFRANGE_REGISTER_REL:{result = str8_lit("DEFRANGE_REGISTER_REL");}break; case CV_SymKind_LPROC32_ID:{result = str8_lit("LPROC32_ID");}break; case CV_SymKind_GPROC32_ID:{result = str8_lit("GPROC32_ID");}break; case CV_SymKind_LPROCMIPS_ID:{result = str8_lit("LPROCMIPS_ID");}break; case CV_SymKind_GPROCMIPS_ID:{result = str8_lit("GPROCMIPS_ID");}break; case CV_SymKind_LPROCIA64_ID:{result = str8_lit("LPROCIA64_ID");}break; case CV_SymKind_GPROCIA64_ID:{result = str8_lit("GPROCIA64_ID");}break; case CV_SymKind_BUILDINFO:{result = str8_lit("BUILDINFO");}break; case CV_SymKind_INLINESITE:{result = str8_lit("INLINESITE");}break; case CV_SymKind_INLINESITE_END:{result = str8_lit("INLINESITE_END");}break; case CV_SymKind_PROC_ID_END:{result = str8_lit("PROC_ID_END");}break; case CV_SymKind_DEFRANGE_HLSL:{result = str8_lit("DEFRANGE_HLSL");}break; case CV_SymKind_GDATA_HLSL:{result = str8_lit("GDATA_HLSL");}break; case CV_SymKind_LDATA_HLSL:{result = str8_lit("LDATA_HLSL");}break; case CV_SymKind_FILESTATIC:{result = str8_lit("FILESTATIC");}break; case CV_SymKind_LPROC32_DPC:{result = str8_lit("LPROC32_DPC");}break; case CV_SymKind_LPROC32_DPC_ID:{result = str8_lit("LPROC32_DPC_ID");}break; case CV_SymKind_DEFRANGE_DPC_PTR_TAG:{result = str8_lit("DEFRANGE_DPC_PTR_TAG");}break; case CV_SymKind_DPC_SYM_TAG_MAP:{result = str8_lit("DPC_SYM_TAG_MAP");}break; case CV_SymKind_ARMSWITCHTABLE:{result = str8_lit("ARMSWITCHTABLE");}break; case CV_SymKind_CALLEES:{result = str8_lit("CALLEES");}break; case CV_SymKind_CALLERS:{result = str8_lit("CALLERS");}break; case CV_SymKind_POGODATA:{result = str8_lit("POGODATA");}break; case CV_SymKind_INLINESITE2:{result = str8_lit("INLINESITE2");}break; case CV_SymKind_HEAPALLOCSITE:{result = str8_lit("HEAPALLOCSITE");}break; case CV_SymKind_MOD_TYPEREF:{result = str8_lit("MOD_TYPEREF");}break; case CV_SymKind_REF_MINIPDB:{result = str8_lit("REF_MINIPDB");}break; case CV_SymKind_PDBMAP:{result = str8_lit("PDBMAP");}break; case CV_SymKind_GDATA_HLSL32:{result = str8_lit("GDATA_HLSL32");}break; case CV_SymKind_LDATA_HLSL32:{result = str8_lit("LDATA_HLSL32");}break; case CV_SymKind_GDATA_HLSL32_EX:{result = str8_lit("GDATA_HLSL32_EX");}break; case CV_SymKind_LDATA_HLSL32_EX:{result = str8_lit("LDATA_HLSL32_EX");}break; case CV_SymKind_FASTLINK:{result = str8_lit("FASTLINK");}break; case CV_SymKind_INLINEES:{result = str8_lit("INLINEES");}break; } return result; } internal String8 cv_string_from_basic_type(CV_BasicType v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_BasicType_NOTYPE:{result = str8_lit("NOTYPE");}break; case CV_BasicType_ABS:{result = str8_lit("ABS");}break; case CV_BasicType_SEGMENT:{result = str8_lit("SEGMENT");}break; case CV_BasicType_VOID:{result = str8_lit("VOID");}break; case CV_BasicType_CURRENCY:{result = str8_lit("CURRENCY");}break; case CV_BasicType_NBASICSTR:{result = str8_lit("NBASICSTR");}break; case CV_BasicType_FBASICSTR:{result = str8_lit("FBASICSTR");}break; case CV_BasicType_NOTTRANS:{result = str8_lit("NOTTRANS");}break; case CV_BasicType_HRESULT:{result = str8_lit("HRESULT");}break; case CV_BasicType_CHAR:{result = str8_lit("CHAR");}break; case CV_BasicType_SHORT:{result = str8_lit("SHORT");}break; case CV_BasicType_LONG:{result = str8_lit("LONG");}break; case CV_BasicType_QUAD:{result = str8_lit("QUAD");}break; case CV_BasicType_OCT:{result = str8_lit("OCT");}break; case CV_BasicType_UCHAR:{result = str8_lit("UCHAR");}break; case CV_BasicType_USHORT:{result = str8_lit("USHORT");}break; case CV_BasicType_ULONG:{result = str8_lit("ULONG");}break; case CV_BasicType_UQUAD:{result = str8_lit("UQUAD");}break; case CV_BasicType_UOCT:{result = str8_lit("UOCT");}break; case CV_BasicType_BOOL8:{result = str8_lit("BOOL8");}break; case CV_BasicType_BOOL16:{result = str8_lit("BOOL16");}break; case CV_BasicType_BOOL32:{result = str8_lit("BOOL32");}break; case CV_BasicType_BOOL64:{result = str8_lit("BOOL64");}break; case CV_BasicType_FLOAT32:{result = str8_lit("FLOAT32");}break; case CV_BasicType_FLOAT64:{result = str8_lit("FLOAT64");}break; case CV_BasicType_FLOAT80:{result = str8_lit("FLOAT80");}break; case CV_BasicType_FLOAT128:{result = str8_lit("FLOAT128");}break; case CV_BasicType_FLOAT48:{result = str8_lit("FLOAT48");}break; case CV_BasicType_FLOAT32PP:{result = str8_lit("FLOAT32PP");}break; case CV_BasicType_FLOAT16:{result = str8_lit("FLOAT16");}break; case CV_BasicType_COMPLEX32:{result = str8_lit("COMPLEX32");}break; case CV_BasicType_COMPLEX64:{result = str8_lit("COMPLEX64");}break; case CV_BasicType_COMPLEX80:{result = str8_lit("COMPLEX80");}break; case CV_BasicType_COMPLEX128:{result = str8_lit("COMPLEX128");}break; case CV_BasicType_BIT:{result = str8_lit("BIT");}break; case CV_BasicType_PASCHAR:{result = str8_lit("PASCHAR");}break; case CV_BasicType_BOOL32FF:{result = str8_lit("BOOL32FF");}break; case CV_BasicType_INT8:{result = str8_lit("INT8");}break; case CV_BasicType_UINT8:{result = str8_lit("UINT8");}break; case CV_BasicType_RCHAR:{result = str8_lit("RCHAR");}break; case CV_BasicType_WCHAR:{result = str8_lit("WCHAR");}break; case CV_BasicType_INT16:{result = str8_lit("INT16");}break; case CV_BasicType_UINT16:{result = str8_lit("UINT16");}break; case CV_BasicType_INT32:{result = str8_lit("INT32");}break; case CV_BasicType_UINT32:{result = str8_lit("UINT32");}break; case CV_BasicType_INT64:{result = str8_lit("INT64");}break; case CV_BasicType_UINT64:{result = str8_lit("UINT64");}break; case CV_BasicType_INT128:{result = str8_lit("INT128");}break; case CV_BasicType_UINT128:{result = str8_lit("UINT128");}break; case CV_BasicType_CHAR16:{result = str8_lit("CHAR16");}break; case CV_BasicType_CHAR32:{result = str8_lit("CHAR32");}break; case CV_BasicType_CHAR8:{result = str8_lit("CHAR8");}break; case CV_BasicType_PTR:{result = str8_lit("PTR");}break; } return result; } internal String8 cv_type_name_from_basic_type(CV_BasicType v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_BasicType_NOTYPE:{result = str8_lit("");}break; case CV_BasicType_ABS:{result = str8_lit("");}break; case CV_BasicType_SEGMENT:{result = str8_lit("");}break; case CV_BasicType_VOID:{result = str8_lit("void");}break; case CV_BasicType_CURRENCY:{result = str8_lit("");}break; case CV_BasicType_NBASICSTR:{result = str8_lit("");}break; case CV_BasicType_FBASICSTR:{result = str8_lit("");}break; case CV_BasicType_NOTTRANS:{result = str8_lit("");}break; case CV_BasicType_HRESULT:{result = str8_lit("HRESULT");}break; case CV_BasicType_CHAR:{result = str8_lit("CHAR");}break; case CV_BasicType_SHORT:{result = str8_lit("SHORT");}break; case CV_BasicType_LONG:{result = str8_lit("LONG");}break; case CV_BasicType_QUAD:{result = str8_lit("QUAD");}break; case CV_BasicType_OCT:{result = str8_lit("OCT");}break; case CV_BasicType_UCHAR:{result = str8_lit("UCHAR");}break; case CV_BasicType_USHORT:{result = str8_lit("USHORT");}break; case CV_BasicType_ULONG:{result = str8_lit("ULONG");}break; case CV_BasicType_UQUAD:{result = str8_lit("UQUAD");}break; case CV_BasicType_UOCT:{result = str8_lit("UOCT");}break; case CV_BasicType_BOOL8:{result = str8_lit("BOOL8");}break; case CV_BasicType_BOOL16:{result = str8_lit("BOOL16");}break; case CV_BasicType_BOOL32:{result = str8_lit("BOOL32");}break; case CV_BasicType_BOOL64:{result = str8_lit("BOOL64");}break; case CV_BasicType_FLOAT32:{result = str8_lit("FLOAT32");}break; case CV_BasicType_FLOAT64:{result = str8_lit("FLOAT64");}break; case CV_BasicType_FLOAT80:{result = str8_lit("FLOAT80");}break; case CV_BasicType_FLOAT128:{result = str8_lit("FLOAT128");}break; case CV_BasicType_FLOAT48:{result = str8_lit("FLOAT48");}break; case CV_BasicType_FLOAT32PP:{result = str8_lit("FLOAT32PP");}break; case CV_BasicType_FLOAT16:{result = str8_lit("FLOAT16");}break; case CV_BasicType_COMPLEX32:{result = str8_lit("ComplexF32");}break; case CV_BasicType_COMPLEX64:{result = str8_lit("ComplexF64");}break; case CV_BasicType_COMPLEX80:{result = str8_lit("ComplexF80");}break; case CV_BasicType_COMPLEX128:{result = str8_lit("ComplexF128");}break; case CV_BasicType_BIT:{result = str8_lit("");}break; case CV_BasicType_PASCHAR:{result = str8_lit("");}break; case CV_BasicType_BOOL32FF:{result = str8_lit("BOOL32FF");}break; case CV_BasicType_INT8:{result = str8_lit("int8");}break; case CV_BasicType_UINT8:{result = str8_lit("uint8");}break; case CV_BasicType_RCHAR:{result = str8_lit("char");}break; case CV_BasicType_WCHAR:{result = str8_lit("WCHAR");}break; case CV_BasicType_INT16:{result = str8_lit("int16");}break; case CV_BasicType_UINT16:{result = str8_lit("uint16");}break; case CV_BasicType_INT32:{result = str8_lit("int32");}break; case CV_BasicType_UINT32:{result = str8_lit("uint32");}break; case CV_BasicType_INT64:{result = str8_lit("int64");}break; case CV_BasicType_UINT64:{result = str8_lit("uint64");}break; case CV_BasicType_INT128:{result = str8_lit("int128");}break; case CV_BasicType_UINT128:{result = str8_lit("uint128");}break; case CV_BasicType_CHAR16:{result = str8_lit("char16");}break; case CV_BasicType_CHAR32:{result = str8_lit("char32");}break; case CV_BasicType_CHAR8:{result = str8_lit("char");}break; case CV_BasicType_PTR:{result = str8_lit("PTR");}break; } return result; } internal String8 cv_string_from_leaf_kind(CV_LeafKind v) { String8 result = str8_lit(""); switch(v) { default:{}break; case CV_LeafKind_NOTYPE:{result = str8_lit("NOTYPE");}break; case CV_LeafKind_MODIFIER_16t:{result = str8_lit("MODIFIER_16t");}break; case CV_LeafKind_POINTER_16t:{result = str8_lit("POINTER_16t");}break; case CV_LeafKind_ARRAY_16t:{result = str8_lit("ARRAY_16t");}break; case CV_LeafKind_CLASS_16t:{result = str8_lit("CLASS_16t");}break; case CV_LeafKind_STRUCTURE_16t:{result = str8_lit("STRUCTURE_16t");}break; case CV_LeafKind_UNION_16t:{result = str8_lit("UNION_16t");}break; case CV_LeafKind_ENUM_16t:{result = str8_lit("ENUM_16t");}break; case CV_LeafKind_PROCEDURE_16t:{result = str8_lit("PROCEDURE_16t");}break; case CV_LeafKind_MFUNCTION_16t:{result = str8_lit("MFUNCTION_16t");}break; case CV_LeafKind_VTSHAPE:{result = str8_lit("VTSHAPE");}break; case CV_LeafKind_COBOL0_16t:{result = str8_lit("COBOL0_16t");}break; case CV_LeafKind_COBOL1:{result = str8_lit("COBOL1");}break; case CV_LeafKind_BARRAY_16t:{result = str8_lit("BARRAY_16t");}break; case CV_LeafKind_LABEL:{result = str8_lit("LABEL");}break; case CV_LeafKind_NULL:{result = str8_lit("NULL");}break; case CV_LeafKind_NOTTRAN:{result = str8_lit("NOTTRAN");}break; case CV_LeafKind_DIMARRAY_16t:{result = str8_lit("DIMARRAY_16t");}break; case CV_LeafKind_VFTPATH_16t:{result = str8_lit("VFTPATH_16t");}break; case CV_LeafKind_PRECOMP_16t:{result = str8_lit("PRECOMP_16t");}break; case CV_LeafKind_ENDPRECOMP:{result = str8_lit("ENDPRECOMP");}break; case CV_LeafKind_OEM_16t:{result = str8_lit("OEM_16t");}break; case CV_LeafKind_TYPESERVER_ST:{result = str8_lit("TYPESERVER_ST");}break; case CV_LeafKind_SKIP_16t:{result = str8_lit("SKIP_16t");}break; case CV_LeafKind_ARGLIST_16t:{result = str8_lit("ARGLIST_16t");}break; case CV_LeafKind_DEFARG_16t:{result = str8_lit("DEFARG_16t");}break; case CV_LeafKind_LIST:{result = str8_lit("LIST");}break; case CV_LeafKind_FIELDLIST_16t:{result = str8_lit("FIELDLIST_16t");}break; case CV_LeafKind_DERIVED_16t:{result = str8_lit("DERIVED_16t");}break; case CV_LeafKind_BITFIELD_16t:{result = str8_lit("BITFIELD_16t");}break; case CV_LeafKind_METHODLIST_16t:{result = str8_lit("METHODLIST_16t");}break; case CV_LeafKind_DIMCONU_16t:{result = str8_lit("DIMCONU_16t");}break; case CV_LeafKind_DIMCONLU_16t:{result = str8_lit("DIMCONLU_16t");}break; case CV_LeafKind_DIMVARU_16t:{result = str8_lit("DIMVARU_16t");}break; case CV_LeafKind_DIMVARLU_16t:{result = str8_lit("DIMVARLU_16t");}break; case CV_LeafKind_REFSYM:{result = str8_lit("REFSYM");}break; case CV_LeafKind_BCLASS_16t:{result = str8_lit("BCLASS_16t");}break; case CV_LeafKind_VBCLASS_16t:{result = str8_lit("VBCLASS_16t");}break; case CV_LeafKind_IVBCLASS_16t:{result = str8_lit("IVBCLASS_16t");}break; case CV_LeafKind_ENUMERATE_ST:{result = str8_lit("ENUMERATE_ST");}break; case CV_LeafKind_FRIENDFCN_16t:{result = str8_lit("FRIENDFCN_16t");}break; case CV_LeafKind_INDEX_16t:{result = str8_lit("INDEX_16t");}break; case CV_LeafKind_MEMBER_16t:{result = str8_lit("MEMBER_16t");}break; case CV_LeafKind_STMEMBER_16t:{result = str8_lit("STMEMBER_16t");}break; case CV_LeafKind_METHOD_16t:{result = str8_lit("METHOD_16t");}break; case CV_LeafKind_NESTTYPE_16t:{result = str8_lit("NESTTYPE_16t");}break; case CV_LeafKind_VFUNCTAB_16t:{result = str8_lit("VFUNCTAB_16t");}break; case CV_LeafKind_FRIENDCLS_16t:{result = str8_lit("FRIENDCLS_16t");}break; case CV_LeafKind_ONEMETHOD_16t:{result = str8_lit("ONEMETHOD_16t");}break; case CV_LeafKind_VFUNCOFF_16t:{result = str8_lit("VFUNCOFF_16t");}break; case CV_LeafKind_TI16_MAX:{result = str8_lit("TI16_MAX");}break; case CV_LeafKind_MODIFIER:{result = str8_lit("MODIFIER");}break; case CV_LeafKind_POINTER:{result = str8_lit("POINTER");}break; case CV_LeafKind_ARRAY_ST:{result = str8_lit("ARRAY_ST");}break; case CV_LeafKind_CLASS_ST:{result = str8_lit("CLASS_ST");}break; case CV_LeafKind_STRUCTURE_ST:{result = str8_lit("STRUCTURE_ST");}break; case CV_LeafKind_UNION_ST:{result = str8_lit("UNION_ST");}break; case CV_LeafKind_ENUM_ST:{result = str8_lit("ENUM_ST");}break; case CV_LeafKind_PROCEDURE:{result = str8_lit("PROCEDURE");}break; case CV_LeafKind_MFUNCTION:{result = str8_lit("MFUNCTION");}break; case CV_LeafKind_COBOL0:{result = str8_lit("COBOL0");}break; case CV_LeafKind_BARRAY:{result = str8_lit("BARRAY");}break; case CV_LeafKind_DIMARRAY_ST:{result = str8_lit("DIMARRAY_ST");}break; case CV_LeafKind_VFTPATH:{result = str8_lit("VFTPATH");}break; case CV_LeafKind_PRECOMP_ST:{result = str8_lit("PRECOMP_ST");}break; case CV_LeafKind_OEM:{result = str8_lit("OEM");}break; case CV_LeafKind_ALIAS_ST:{result = str8_lit("ALIAS_ST");}break; case CV_LeafKind_OEM2:{result = str8_lit("OEM2");}break; case CV_LeafKind_SKIP:{result = str8_lit("SKIP");}break; case CV_LeafKind_ARGLIST:{result = str8_lit("ARGLIST");}break; case CV_LeafKind_DEFARG_ST:{result = str8_lit("DEFARG_ST");}break; case CV_LeafKind_FIELDLIST:{result = str8_lit("FIELDLIST");}break; case CV_LeafKind_DERIVED:{result = str8_lit("DERIVED");}break; case CV_LeafKind_BITFIELD:{result = str8_lit("BITFIELD");}break; case CV_LeafKind_METHODLIST:{result = str8_lit("METHODLIST");}break; case CV_LeafKind_DIMCONU:{result = str8_lit("DIMCONU");}break; case CV_LeafKind_DIMCONLU:{result = str8_lit("DIMCONLU");}break; case CV_LeafKind_DIMVARU:{result = str8_lit("DIMVARU");}break; case CV_LeafKind_DIMVARLU:{result = str8_lit("DIMVARLU");}break; case CV_LeafKind_BCLASS:{result = str8_lit("BCLASS");}break; case CV_LeafKind_VBCLASS:{result = str8_lit("VBCLASS");}break; case CV_LeafKind_IVBCLASS:{result = str8_lit("IVBCLASS");}break; case CV_LeafKind_FRIENDFCN_ST:{result = str8_lit("FRIENDFCN_ST");}break; case CV_LeafKind_INDEX:{result = str8_lit("INDEX");}break; case CV_LeafKind_MEMBER_ST:{result = str8_lit("MEMBER_ST");}break; case CV_LeafKind_STMEMBER_ST:{result = str8_lit("STMEMBER_ST");}break; case CV_LeafKind_METHOD_ST:{result = str8_lit("METHOD_ST");}break; case CV_LeafKind_NESTTYPE_ST:{result = str8_lit("NESTTYPE_ST");}break; case CV_LeafKind_VFUNCTAB:{result = str8_lit("VFUNCTAB");}break; case CV_LeafKind_FRIENDCLS:{result = str8_lit("FRIENDCLS");}break; case CV_LeafKind_ONEMETHOD_ST:{result = str8_lit("ONEMETHOD_ST");}break; case CV_LeafKind_VFUNCOFF:{result = str8_lit("VFUNCOFF");}break; case CV_LeafKind_NESTTYPEEX_ST:{result = str8_lit("NESTTYPEEX_ST");}break; case CV_LeafKind_MEMBERMODIFY_ST:{result = str8_lit("MEMBERMODIFY_ST");}break; case CV_LeafKind_MANAGED_ST:{result = str8_lit("MANAGED_ST");}break; case CV_LeafKind_ST_MAX:{result = str8_lit("ST_MAX");}break; case CV_LeafKind_TYPESERVER:{result = str8_lit("TYPESERVER");}break; case CV_LeafKind_ENUMERATE:{result = str8_lit("ENUMERATE");}break; case CV_LeafKind_ARRAY:{result = str8_lit("ARRAY");}break; case CV_LeafKind_CLASS:{result = str8_lit("CLASS");}break; case CV_LeafKind_STRUCTURE:{result = str8_lit("STRUCTURE");}break; case CV_LeafKind_UNION:{result = str8_lit("UNION");}break; case CV_LeafKind_ENUM:{result = str8_lit("ENUM");}break; case CV_LeafKind_DIMARRAY:{result = str8_lit("DIMARRAY");}break; case CV_LeafKind_PRECOMP:{result = str8_lit("PRECOMP");}break; case CV_LeafKind_ALIAS:{result = str8_lit("ALIAS");}break; case CV_LeafKind_DEFARG:{result = str8_lit("DEFARG");}break; case CV_LeafKind_FRIENDFCN:{result = str8_lit("FRIENDFCN");}break; case CV_LeafKind_MEMBER:{result = str8_lit("MEMBER");}break; case CV_LeafKind_STMEMBER:{result = str8_lit("STMEMBER");}break; case CV_LeafKind_METHOD:{result = str8_lit("METHOD");}break; case CV_LeafKind_NESTTYPE:{result = str8_lit("NESTTYPE");}break; case CV_LeafKind_ONEMETHOD:{result = str8_lit("ONEMETHOD");}break; case CV_LeafKind_NESTTYPEEX:{result = str8_lit("NESTTYPEEX");}break; case CV_LeafKind_MEMBERMODIFY:{result = str8_lit("MEMBERMODIFY");}break; case CV_LeafKind_MANAGED:{result = str8_lit("MANAGED");}break; case CV_LeafKind_TYPESERVER2:{result = str8_lit("TYPESERVER2");}break; case CV_LeafKind_STRIDED_ARRAY:{result = str8_lit("STRIDED_ARRAY");}break; case CV_LeafKind_HLSL:{result = str8_lit("HLSL");}break; case CV_LeafKind_MODIFIER_EX:{result = str8_lit("MODIFIER_EX");}break; case CV_LeafKind_INTERFACE:{result = str8_lit("INTERFACE");}break; case CV_LeafKind_BINTERFACE:{result = str8_lit("BINTERFACE");}break; case CV_LeafKind_VECTOR:{result = str8_lit("VECTOR");}break; case CV_LeafKind_MATRIX:{result = str8_lit("MATRIX");}break; case CV_LeafKind_VFTABLE:{result = str8_lit("VFTABLE");}break; case CV_LeafKind_FUNC_ID:{result = str8_lit("FUNC_ID");}break; case CV_LeafKind_MFUNC_ID:{result = str8_lit("MFUNC_ID");}break; case CV_LeafKind_BUILDINFO:{result = str8_lit("BUILDINFO");}break; case CV_LeafKind_SUBSTR_LIST:{result = str8_lit("SUBSTR_LIST");}break; case CV_LeafKind_STRING_ID:{result = str8_lit("STRING_ID");}break; case CV_LeafKind_UDT_SRC_LINE:{result = str8_lit("UDT_SRC_LINE");}break; case CV_LeafKind_UDT_MOD_SRC_LINE:{result = str8_lit("UDT_MOD_SRC_LINE");}break; case CV_LeafKind_CLASS2:{result = str8_lit("CLASS2");}break; case CV_LeafKind_STRUCT2:{result = str8_lit("STRUCT2");}break; } return result; } internal U64 cv_header_struct_size_from_sym_kind(CV_SymKind v) { U64 result = 0; switch(v) { default:{}break; case CV_SymKind_COMPILE:{result = sizeof(CV_SymCompile);}break; case CV_SymKind_SSEARCH:{result = sizeof(CV_SymStartSearch);}break; case CV_SymKind_RETURN:{result = sizeof(CV_SymReturn);}break; case CV_SymKind_SLINK32:{result = sizeof(CV_SymSLink32);}break; case CV_SymKind_OEM:{result = sizeof(CV_SymOEM);}break; case CV_SymKind_VFTABLE32:{result = sizeof(CV_SymVPath32);}break; case CV_SymKind_FRAMEPROC:{result = sizeof(CV_SymFrameproc);}break; case CV_SymKind_ANNOTATION:{result = sizeof(CV_SymAnnotation);}break; case CV_SymKind_OBJNAME:{result = sizeof(CV_SymObjName);}break; case CV_SymKind_THUNK32:{result = sizeof(CV_SymThunk32);}break; case CV_SymKind_BLOCK32:{result = sizeof(CV_SymBlock32);}break; case CV_SymKind_LABEL32:{result = sizeof(CV_SymLabel32);}break; case CV_SymKind_REGISTER:{result = sizeof(CV_SymRegister);}break; case CV_SymKind_CONSTANT:{result = sizeof(CV_SymConstant);}break; case CV_SymKind_UDT:{result = sizeof(CV_SymUDT);}break; case CV_SymKind_MANYREG:{result = sizeof(CV_SymManyreg);}break; case CV_SymKind_BPREL32:{result = sizeof(CV_SymBPRel32);}break; case CV_SymKind_LDATA32:{result = sizeof(CV_SymData32);}break; case CV_SymKind_GDATA32:{result = sizeof(CV_SymData32);}break; case CV_SymKind_PUB32:{result = sizeof(CV_SymPub32);}break; case CV_SymKind_LPROC32:{result = sizeof(CV_SymProc32);}break; case CV_SymKind_GPROC32:{result = sizeof(CV_SymProc32);}break; case CV_SymKind_REGREL32:{result = sizeof(CV_SymRegrel32);}break; case CV_SymKind_LTHREAD32:{result = sizeof(CV_SymThread32);}break; case CV_SymKind_GTHREAD32:{result = sizeof(CV_SymThread32);}break; case CV_SymKind_COMPILE2:{result = sizeof(CV_SymCompile2);}break; case CV_SymKind_MANYREG2:{result = sizeof(CV_SymManyreg2);}break; case CV_SymKind_LOCALSLOT:{result = sizeof(CV_SymSlot);}break; case CV_SymKind_MANFRAMEREL:{result = sizeof(CV_SymAttrFrameRel);}break; case CV_SymKind_MANREGISTER:{result = sizeof(CV_SymAttrReg);}break; case CV_SymKind_MANMANYREG:{result = sizeof(CV_SymAttrManyReg);}break; case CV_SymKind_MANREGREL:{result = sizeof(CV_SymAttrRegRel);}break; case CV_SymKind_UNAMESPACE:{result = sizeof(CV_SymUNamespace);}break; case CV_SymKind_PROCREF:{result = sizeof(CV_SymRef2);}break; case CV_SymKind_DATAREF:{result = sizeof(CV_SymRef2);}break; case CV_SymKind_LPROCREF:{result = sizeof(CV_SymRef2);}break; case CV_SymKind_TRAMPOLINE:{result = sizeof(CV_SymTrampoline);}break; case CV_SymKind_ATTR_FRAMEREL:{result = sizeof(CV_SymAttrFrameRel);}break; case CV_SymKind_ATTR_REGISTER:{result = sizeof(CV_SymAttrReg);}break; case CV_SymKind_ATTR_REGREL:{result = sizeof(CV_SymAttrRegRel);}break; case CV_SymKind_ATTR_MANYREG:{result = sizeof(CV_SymAttrManyReg);}break; case CV_SymKind_SEPCODE:{result = sizeof(CV_SymSepcode);}break; case CV_SymKind_SECTION:{result = sizeof(CV_SymSection);}break; case CV_SymKind_COFFGROUP:{result = sizeof(CV_SymCoffGroup);}break; case CV_SymKind_EXPORT:{result = sizeof(CV_SymExport);}break; case CV_SymKind_CALLSITEINFO:{result = sizeof(CV_SymCallSiteInfo);}break; case CV_SymKind_FRAMECOOKIE:{result = sizeof(CV_SymFrameCookie);}break; case CV_SymKind_DISCARDED:{result = sizeof(CV_SymDiscarded);}break; case CV_SymKind_COMPILE3:{result = sizeof(CV_SymCompile3);}break; case CV_SymKind_ENVBLOCK:{result = sizeof(CV_SymEnvBlock);}break; case CV_SymKind_LOCAL:{result = sizeof(CV_SymLocal);}break; case CV_SymKind_DEFRANGE_SUBFIELD:{result = sizeof(CV_SymDefrangeSubfield);}break; case CV_SymKind_DEFRANGE_REGISTER:{result = sizeof(CV_SymDefrangeRegister);}break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL:{result = sizeof(CV_SymDefrangeFramepointerRel);}break; case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER:{result = sizeof(CV_SymDefrangeSubfieldRegister);}break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:{result = sizeof(CV_SymDefrangeFramepointerRelFullScope);}break; case CV_SymKind_DEFRANGE_REGISTER_REL:{result = sizeof(CV_SymDefrangeRegisterRel);}break; case CV_SymKind_BUILDINFO:{result = sizeof(CV_SymBuildInfo);}break; case CV_SymKind_INLINESITE:{result = sizeof(CV_SymInlineSite);}break; case CV_SymKind_FILESTATIC:{result = sizeof(CV_SymFileStatic);}break; case CV_SymKind_CALLEES:{result = sizeof(CV_SymFunctionList);}break; case CV_SymKind_CALLERS:{result = sizeof(CV_SymFunctionList);}break; case CV_SymKind_POGODATA:{result = sizeof(CV_SymPogoInfo);}break; case CV_SymKind_INLINESITE2:{result = sizeof(CV_SymInlineSite2);}break; case CV_SymKind_HEAPALLOCSITE:{result = sizeof(CV_SymHeapAllocSite);}break; case CV_SymKind_MOD_TYPEREF:{result = sizeof(CV_SymModTypeRef);}break; case CV_SymKind_REF_MINIPDB:{result = sizeof(CV_SymRefMiniPdb);}break; case CV_SymKind_FASTLINK:{result = sizeof(CV_SymFastLink);}break; case CV_SymKind_INLINEES:{result = sizeof(CV_SymInlinees);}break; } return result; } internal U64 cv_header_struct_size_from_leaf_kind(CV_LeafKind v) { U64 result = 0; switch(v) { default:{}break; case CV_LeafKind_VTSHAPE:{result = sizeof(CV_LeafVTShape);}break; case CV_LeafKind_LABEL:{result = sizeof(CV_LeafLabel);}break; case CV_LeafKind_MODIFIER:{result = sizeof(CV_LeafModifier);}break; case CV_LeafKind_POINTER:{result = sizeof(CV_LeafPointer);}break; case CV_LeafKind_PROCEDURE:{result = sizeof(CV_LeafProcedure);}break; case CV_LeafKind_MFUNCTION:{result = sizeof(CV_LeafMFunction);}break; case CV_LeafKind_VFTPATH:{result = sizeof(CV_LeafVFPath);}break; case CV_LeafKind_SKIP:{result = sizeof(CV_LeafSkip);}break; case CV_LeafKind_ARGLIST:{result = sizeof(CV_LeafArgList);}break; case CV_LeafKind_BITFIELD:{result = sizeof(CV_LeafBitField);}break; case CV_LeafKind_METHODLIST:{result = sizeof(CV_LeafMethodListMember);}break; case CV_LeafKind_BCLASS:{result = sizeof(CV_LeafBClass);}break; case CV_LeafKind_VBCLASS:{result = sizeof(CV_LeafVBClass);}break; case CV_LeafKind_INDEX:{result = sizeof(CV_LeafIndex);}break; case CV_LeafKind_VFUNCTAB:{result = sizeof(CV_LeafVFuncTab);}break; case CV_LeafKind_VFUNCOFF:{result = sizeof(CV_LeafVFuncOff);}break; case CV_LeafKind_TYPESERVER:{result = sizeof(CV_LeafTypeServer);}break; case CV_LeafKind_ENUMERATE:{result = sizeof(CV_LeafEnumerate);}break; case CV_LeafKind_ARRAY:{result = sizeof(CV_LeafArray);}break; case CV_LeafKind_CLASS:{result = sizeof(CV_LeafStruct);}break; case CV_LeafKind_STRUCTURE:{result = sizeof(CV_LeafStruct);}break; case CV_LeafKind_UNION:{result = sizeof(CV_LeafUnion);}break; case CV_LeafKind_ENUM:{result = sizeof(CV_LeafEnum);}break; case CV_LeafKind_PRECOMP:{result = sizeof(CV_LeafPreComp);}break; case CV_LeafKind_ALIAS:{result = sizeof(CV_LeafAlias);}break; case CV_LeafKind_MEMBER:{result = sizeof(CV_LeafMember);}break; case CV_LeafKind_STMEMBER:{result = sizeof(CV_LeafStMember);}break; case CV_LeafKind_METHOD:{result = sizeof(CV_LeafMethod);}break; case CV_LeafKind_NESTTYPE:{result = sizeof(CV_LeafNestType);}break; case CV_LeafKind_ONEMETHOD:{result = sizeof(CV_LeafOneMethod);}break; case CV_LeafKind_NESTTYPEEX:{result = sizeof(CV_LeafNestTypeEx);}break; case CV_LeafKind_TYPESERVER2:{result = sizeof(CV_LeafTypeServer2);}break; case CV_LeafKind_INTERFACE:{result = sizeof(CV_LeafStruct);}break; case CV_LeafKind_FUNC_ID:{result = sizeof(CV_LeafFuncId);}break; case CV_LeafKind_MFUNC_ID:{result = sizeof(CV_LeafMFuncId);}break; case CV_LeafKind_BUILDINFO:{result = sizeof(CV_LeafBuildInfo);}break; case CV_LeafKind_SUBSTR_LIST:{result = sizeof(CV_LeafSubstrList);}break; case CV_LeafKind_STRING_ID:{result = sizeof(CV_LeafStringId);}break; case CV_LeafKind_UDT_SRC_LINE:{result = sizeof(CV_LeafUDTSrcLine);}break; case CV_LeafKind_UDT_MOD_SRC_LINE:{result = sizeof(CV_LeafUDTModSrcLine);}break; case CV_LeafKind_CLASS2:{result = sizeof(CV_LeafStruct2);}break; case CV_LeafKind_STRUCT2:{result = sizeof(CV_LeafStruct2);}break; } return result; } ================================================ FILE: src/codeview/generated/codeview.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef CODEVIEW_META_H #define CODEVIEW_META_H typedef U16 CV_NumericKind; typedef enum CV_NumericKindEnum { CV_NumericKind_CHAR = 0x8000, CV_NumericKind_SHORT = 0x8001, CV_NumericKind_USHORT = 0x8002, CV_NumericKind_LONG = 0x8003, CV_NumericKind_ULONG = 0x8004, CV_NumericKind_FLOAT32 = 0x8005, CV_NumericKind_FLOAT64 = 0x8006, CV_NumericKind_FLOAT80 = 0x8007, CV_NumericKind_FLOAT128 = 0x8008, CV_NumericKind_QUADWORD = 0x8009, CV_NumericKind_UQUADWORD = 0x800a, CV_NumericKind_FLOAT48 = 0x800b, CV_NumericKind_COMPLEX32 = 0x800c, CV_NumericKind_COMPLEX64 = 0x800d, CV_NumericKind_COMPLEX80 = 0x800e, CV_NumericKind_COMPLEX128 = 0x800f, CV_NumericKind_VARSTRING = 0x8010, CV_NumericKind_OCTWORD = 0x8017, CV_NumericKind_UOCTWORD = 0x8018, CV_NumericKind_DECIMAL = 0x8019, CV_NumericKind_DATE = 0x801a, CV_NumericKind_UTF8STRING = 0x801b, CV_NumericKind_FLOAT16 = 0x801c, } CV_NumericKindEnum; typedef U16 CV_Arch; typedef enum CV_ArchEnum { CV_Arch_8080 = 0x00, CV_Arch_8086 = 0x01, CV_Arch_80286 = 0x02, CV_Arch_80386 = 0x03, CV_Arch_80486 = 0x04, CV_Arch_PENTIUM = 0x05, CV_Arch_PENTIUMII = 0x06, CV_Arch_PENTIUMIII = 0x07, CV_Arch_MIPS = 0x10, CV_Arch_MIPS16 = 0x11, CV_Arch_MIPS32 = 0x12, CV_Arch_MIPS64 = 0x13, CV_Arch_MIPSI = 0x14, CV_Arch_MIPSII = 0x15, CV_Arch_MIPSIII = 0x16, CV_Arch_MIPSIV = 0x17, CV_Arch_MIPSV = 0x18, CV_Arch_M68000 = 0x20, CV_Arch_M68010 = 0x21, CV_Arch_M68020 = 0x22, CV_Arch_M68030 = 0x23, CV_Arch_M68040 = 0x24, CV_Arch_ALPHA = 0x30, CV_Arch_ALPHA_21164 = 0x31, CV_Arch_ALPHA_21164A = 0x32, CV_Arch_ALPHA_21264 = 0x33, CV_Arch_ALPHA_21364 = 0x34, CV_Arch_PPC601 = 0x40, CV_Arch_PPC603 = 0x41, CV_Arch_PPC604 = 0x42, CV_Arch_PPC620 = 0x43, CV_Arch_PPCFP = 0x44, CV_Arch_PPCBE = 0x45, CV_Arch_SH3 = 0x50, CV_Arch_SH3E = 0x51, CV_Arch_SH3DSP = 0x52, CV_Arch_SH4 = 0x53, CV_Arch_SHMEDIA = 0x54, CV_Arch_ARM3 = 0x60, CV_Arch_ARM4 = 0x61, CV_Arch_ARM4T = 0x62, CV_Arch_ARM5 = 0x63, CV_Arch_ARM5T = 0x64, CV_Arch_ARM6 = 0x65, CV_Arch_ARM_XMAC = 0x66, CV_Arch_ARM_WMMX = 0x67, CV_Arch_ARM7 = 0x68, CV_Arch_OMNI = 0x70, CV_Arch_IA64_1 = 0x80, CV_Arch_IA64_2 = 0x81, CV_Arch_CEE = 0x90, CV_Arch_AM33 = 0xA0, CV_Arch_M32R = 0xB0, CV_Arch_TRICORE = 0xC0, CV_Arch_X64 = 0xD0, CV_Arch_EBC = 0xE0, CV_Arch_THUMB = 0xF0, CV_Arch_ARMNT = 0xF4, CV_Arch_ARM64 = 0xF6, CV_Arch_D3D11_SHADER = 0x100, CV_Arch_IA64 = CV_Arch_IA64_1, CV_Arch_PENTIUMPRO = CV_Arch_PENTIUMII, CV_Arch_MIPSR4000 = CV_Arch_MIPS, CV_Arch_ALPHA_21064 = CV_Arch_ALPHA, CV_Arch_AMD64 = CV_Arch_X64, } CV_ArchEnum; typedef U16 CV_AllReg; typedef enum CV_AllRegEnum { CV_AllReg_ERR = 30000, CV_AllReg_TEB = 30001, CV_AllReg_TIMER = 30002, CV_AllReg_EFAD1 = 30003, CV_AllReg_EFAD2 = 30004, CV_AllReg_EFAD3 = 30005, CV_AllReg_VFRAME = 30006, CV_AllReg_HANDLE = 30007, CV_AllReg_PARAMS = 30008, CV_AllReg_LOCALS = 30009, CV_AllReg_TID = 30010, CV_AllReg_ENV = 30011, CV_AllReg_CMDLN = 30012, } CV_AllRegEnum; typedef U16 CV_SymKind; typedef enum CV_SymKindEnum { CV_SymKind_COMPILE = 0x0001, CV_SymKind_REGISTER_16t = 0x0002, CV_SymKind_CONSTANT_16t = 0x0003, CV_SymKind_UDT_16t = 0x0004, CV_SymKind_SSEARCH = 0x0005, CV_SymKind_END = 0x0006, CV_SymKind_SKIP = 0x0007, CV_SymKind_CVRESERVE = 0x0008, CV_SymKind_OBJNAME_ST = 0x0009, CV_SymKind_ENDARG = 0x000a, CV_SymKind_COBOLUDT_16t = 0x000b, CV_SymKind_MANYREG_16t = 0x000c, CV_SymKind_RETURN = 0x000d, CV_SymKind_ENTRYTHIS = 0x000e, CV_SymKind_BPREL16 = 0x0100, CV_SymKind_LDATA16 = 0x0101, CV_SymKind_GDATA16 = 0x0102, CV_SymKind_PUB16 = 0x0103, CV_SymKind_LPROC16 = 0x0104, CV_SymKind_GPROC16 = 0x0105, CV_SymKind_THUNK16 = 0x0106, CV_SymKind_BLOCK16 = 0x0107, CV_SymKind_WITH16 = 0x0108, CV_SymKind_LABEL16 = 0x0109, CV_SymKind_CEXMODEL16 = 0x010a, CV_SymKind_VFTABLE16 = 0x010b, CV_SymKind_REGREL16 = 0x010c, CV_SymKind_BPREL32_16t = 0x0200, CV_SymKind_LDATA32_16t = 0x0201, CV_SymKind_GDATA32_16t = 0x0202, CV_SymKind_PUB32_16t = 0x0203, CV_SymKind_LPROC32_16t = 0x0204, CV_SymKind_GPROC32_16t = 0x0205, CV_SymKind_THUNK32_ST = 0x0206, CV_SymKind_BLOCK32_ST = 0x0207, CV_SymKind_WITH32_ST = 0x0208, CV_SymKind_LABEL32_ST = 0x0209, CV_SymKind_CEXMODEL32 = 0x020a, CV_SymKind_VFTABLE32_16t = 0x020b, CV_SymKind_REGREL32_16t = 0x020c, CV_SymKind_LTHREAD32_16t = 0x020d, CV_SymKind_GTHREAD32_16t = 0x020e, CV_SymKind_SLINK32 = 0x020f, CV_SymKind_LPROCMIPS_16t = 0x0300, CV_SymKind_GPROCMIPS_16t = 0x0301, CV_SymKind_PROCREF_ST = 0x0400, CV_SymKind_DATAREF_ST = 0x0401, CV_SymKind_ALIGN = 0x0402, CV_SymKind_LPROCREF_ST = 0x0403, CV_SymKind_OEM = 0x0404, CV_SymKind_TI16_MAX = 0x1000, CV_SymKind_CONSTANT_ST = 0x1002, CV_SymKind_UDT_ST = 0x1003, CV_SymKind_COBOLUDT_ST = 0x1004, CV_SymKind_MANYREG_ST = 0x1005, CV_SymKind_BPREL32_ST = 0x1006, CV_SymKind_LDATA32_ST = 0x1007, CV_SymKind_GDATA32_ST = 0x1008, CV_SymKind_PUB32_ST = 0x1009, CV_SymKind_LPROC32_ST = 0x100a, CV_SymKind_GPROC32_ST = 0x100b, CV_SymKind_VFTABLE32 = 0x100c, CV_SymKind_REGREL32_ST = 0x100d, CV_SymKind_LTHREAD32_ST = 0x100e, CV_SymKind_GTHREAD32_ST = 0x100f, CV_SymKind_LPROCMIPS_ST = 0x1010, CV_SymKind_GPROCMIPS_ST = 0x1011, CV_SymKind_FRAMEPROC = 0x1012, CV_SymKind_COMPILE2_ST = 0x1013, CV_SymKind_MANYREG2_ST = 0x1014, CV_SymKind_LPROCIA64_ST = 0x1015, CV_SymKind_GPROCIA64_ST = 0x1016, CV_SymKind_LOCALSLOT_ST = 0x1017, CV_SymKind_PARAMSLOT_ST = 0x1018, CV_SymKind_ANNOTATION = 0x1019, CV_SymKind_GMANPROC_ST = 0x101a, CV_SymKind_LMANPROC_ST = 0x101b, CV_SymKind_RESERVED1 = 0x101c, CV_SymKind_RESERVED2 = 0x101d, CV_SymKind_RESERVED3 = 0x101e, CV_SymKind_RESERVED4 = 0x101f, CV_SymKind_LMANDATA_ST = 0x1020, CV_SymKind_GMANDATA_ST = 0x1021, CV_SymKind_MANFRAMEREL_ST = 0x1022, CV_SymKind_MANREGISTER_ST = 0x1023, CV_SymKind_MANSLOT_ST = 0x1024, CV_SymKind_MANMANYREG_ST = 0x1025, CV_SymKind_MANREGREL_ST = 0x1026, CV_SymKind_MANMANYREG2_ST = 0x1027, CV_SymKind_MANTYPREF = 0x1028, CV_SymKind_UNAMESPACE_ST = 0x1029, CV_SymKind_ST_MAX = 0x1100, CV_SymKind_OBJNAME = 0x1101, CV_SymKind_THUNK32 = 0x1102, CV_SymKind_BLOCK32 = 0x1103, CV_SymKind_WITH32 = 0x1104, CV_SymKind_LABEL32 = 0x1105, CV_SymKind_REGISTER = 0x1106, CV_SymKind_CONSTANT = 0x1107, CV_SymKind_UDT = 0x1108, CV_SymKind_COBOLUDT = 0x1109, CV_SymKind_MANYREG = 0x110a, CV_SymKind_BPREL32 = 0x110b, CV_SymKind_LDATA32 = 0x110c, CV_SymKind_GDATA32 = 0x110d, CV_SymKind_PUB32 = 0x110e, CV_SymKind_LPROC32 = 0x110f, CV_SymKind_GPROC32 = 0x1110, CV_SymKind_REGREL32 = 0x1111, CV_SymKind_LTHREAD32 = 0x1112, CV_SymKind_GTHREAD32 = 0x1113, CV_SymKind_LPROCMIPS = 0x1114, CV_SymKind_GPROCMIPS = 0x1115, CV_SymKind_COMPILE2 = 0x1116, CV_SymKind_MANYREG2 = 0x1117, CV_SymKind_LPROCIA64 = 0x1118, CV_SymKind_GPROCIA64 = 0x1119, CV_SymKind_LOCALSLOT = 0x111a, CV_SymKind_PARAMSLOT = 0x111b, CV_SymKind_LMANDATA = 0x111c, CV_SymKind_GMANDATA = 0x111d, CV_SymKind_MANFRAMEREL = 0x111e, CV_SymKind_MANREGISTER = 0x111f, CV_SymKind_MANSLOT = 0x1120, CV_SymKind_MANMANYREG = 0x1121, CV_SymKind_MANREGREL = 0x1122, CV_SymKind_MANMANYREG2 = 0x1123, CV_SymKind_UNAMESPACE = 0x1124, CV_SymKind_PROCREF = 0x1125, CV_SymKind_DATAREF = 0x1126, CV_SymKind_LPROCREF = 0x1127, CV_SymKind_ANNOTATIONREF = 0x1128, CV_SymKind_TOKENREF = 0x1129, CV_SymKind_GMANPROC = 0x112a, CV_SymKind_LMANPROC = 0x112b, CV_SymKind_TRAMPOLINE = 0x112c, CV_SymKind_MANCONSTANT = 0x112d, CV_SymKind_ATTR_FRAMEREL = 0x112e, CV_SymKind_ATTR_REGISTER = 0x112f, CV_SymKind_ATTR_REGREL = 0x1130, CV_SymKind_ATTR_MANYREG = 0x1131, CV_SymKind_SEPCODE = 0x1132, CV_SymKind_DEFRANGE_2005 = 0x1134, CV_SymKind_DEFRANGE2_2005 = 0x1135, CV_SymKind_SECTION = 0x1136, CV_SymKind_COFFGROUP = 0x1137, CV_SymKind_EXPORT = 0x1138, CV_SymKind_CALLSITEINFO = 0x1139, CV_SymKind_FRAMECOOKIE = 0x113a, CV_SymKind_DISCARDED = 0x113b, CV_SymKind_COMPILE3 = 0x113c, CV_SymKind_ENVBLOCK = 0x113d, CV_SymKind_LOCAL = 0x113e, CV_SymKind_DEFRANGE = 0x113f, CV_SymKind_DEFRANGE_SUBFIELD = 0x1140, CV_SymKind_DEFRANGE_REGISTER = 0x1141, CV_SymKind_DEFRANGE_FRAMEPOINTER_REL = 0x1142, CV_SymKind_DEFRANGE_SUBFIELD_REGISTER = 0x1143, CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, CV_SymKind_DEFRANGE_REGISTER_REL = 0x1145, CV_SymKind_LPROC32_ID = 0x1146, CV_SymKind_GPROC32_ID = 0x1147, CV_SymKind_LPROCMIPS_ID = 0x1148, CV_SymKind_GPROCMIPS_ID = 0x1149, CV_SymKind_LPROCIA64_ID = 0x114a, CV_SymKind_GPROCIA64_ID = 0x114b, CV_SymKind_BUILDINFO = 0x114c, CV_SymKind_INLINESITE = 0x114d, CV_SymKind_INLINESITE_END = 0x114e, CV_SymKind_PROC_ID_END = 0x114f, CV_SymKind_DEFRANGE_HLSL = 0x1150, CV_SymKind_GDATA_HLSL = 0x1151, CV_SymKind_LDATA_HLSL = 0x1152, CV_SymKind_FILESTATIC = 0x1153, CV_SymKind_LPROC32_DPC = 0x1155, CV_SymKind_LPROC32_DPC_ID = 0x1156, CV_SymKind_DEFRANGE_DPC_PTR_TAG = 0x1157, CV_SymKind_DPC_SYM_TAG_MAP = 0x1158, CV_SymKind_ARMSWITCHTABLE = 0x1159, CV_SymKind_CALLEES = 0x115a, CV_SymKind_CALLERS = 0x115b, CV_SymKind_POGODATA = 0x115c, CV_SymKind_INLINESITE2 = 0x115d, CV_SymKind_HEAPALLOCSITE = 0x115e, CV_SymKind_MOD_TYPEREF = 0x115f, CV_SymKind_REF_MINIPDB = 0x1160, CV_SymKind_PDBMAP = 0x1161, CV_SymKind_GDATA_HLSL32 = 0x1162, CV_SymKind_LDATA_HLSL32 = 0x1163, CV_SymKind_GDATA_HLSL32_EX = 0x1164, CV_SymKind_LDATA_HLSL32_EX = 0x1165, CV_SymKind_FASTLINK = 0x1167, CV_SymKind_INLINEES = 0x1168, } CV_SymKindEnum; typedef U8 CV_BasicType; typedef enum CV_BasicTypeEnum { CV_BasicType_NOTYPE = 0x00, CV_BasicType_ABS = 0x01, CV_BasicType_SEGMENT = 0x02, CV_BasicType_VOID = 0x03, CV_BasicType_CURRENCY = 0x04, CV_BasicType_NBASICSTR = 0x05, CV_BasicType_FBASICSTR = 0x06, CV_BasicType_NOTTRANS = 0x07, CV_BasicType_HRESULT = 0x08, CV_BasicType_CHAR = 0x10, CV_BasicType_SHORT = 0x11, CV_BasicType_LONG = 0x12, CV_BasicType_QUAD = 0x13, CV_BasicType_OCT = 0x14, CV_BasicType_UCHAR = 0x20, CV_BasicType_USHORT = 0x21, CV_BasicType_ULONG = 0x22, CV_BasicType_UQUAD = 0x23, CV_BasicType_UOCT = 0x24, CV_BasicType_BOOL8 = 0x30, CV_BasicType_BOOL16 = 0x31, CV_BasicType_BOOL32 = 0x32, CV_BasicType_BOOL64 = 0x33, CV_BasicType_FLOAT32 = 0x40, CV_BasicType_FLOAT64 = 0x41, CV_BasicType_FLOAT80 = 0x42, CV_BasicType_FLOAT128 = 0x43, CV_BasicType_FLOAT48 = 0x44, CV_BasicType_FLOAT32PP = 0x45, CV_BasicType_FLOAT16 = 0x46, CV_BasicType_COMPLEX32 = 0x50, CV_BasicType_COMPLEX64 = 0x51, CV_BasicType_COMPLEX80 = 0x52, CV_BasicType_COMPLEX128 = 0x53, CV_BasicType_BIT = 0x60, CV_BasicType_PASCHAR = 0x61, CV_BasicType_BOOL32FF = 0x62, CV_BasicType_INT8 = 0x68, CV_BasicType_UINT8 = 0x69, CV_BasicType_RCHAR = 0x70, CV_BasicType_WCHAR = 0x71, CV_BasicType_INT16 = 0x72, CV_BasicType_UINT16 = 0x73, CV_BasicType_INT32 = 0x74, CV_BasicType_UINT32 = 0x75, CV_BasicType_INT64 = 0x76, CV_BasicType_UINT64 = 0x77, CV_BasicType_INT128 = 0x78, CV_BasicType_UINT128 = 0x79, CV_BasicType_CHAR16 = 0x7a, CV_BasicType_CHAR32 = 0x7b, CV_BasicType_CHAR8 = 0x7c, CV_BasicType_PTR = 0xf0, } CV_BasicTypeEnum; typedef U16 CV_LeafKind; typedef enum CV_LeafKindEnum { CV_LeafKind_NOTYPE = 0x0000, CV_LeafKind_MODIFIER_16t = 0x0001, CV_LeafKind_POINTER_16t = 0x0002, CV_LeafKind_ARRAY_16t = 0x0003, CV_LeafKind_CLASS_16t = 0x0004, CV_LeafKind_STRUCTURE_16t = 0x0005, CV_LeafKind_UNION_16t = 0x0006, CV_LeafKind_ENUM_16t = 0x0007, CV_LeafKind_PROCEDURE_16t = 0x0008, CV_LeafKind_MFUNCTION_16t = 0x0009, CV_LeafKind_VTSHAPE = 0x000a, CV_LeafKind_COBOL0_16t = 0x000b, CV_LeafKind_COBOL1 = 0x000c, CV_LeafKind_BARRAY_16t = 0x000d, CV_LeafKind_LABEL = 0x000e, CV_LeafKind_NULL = 0x000f, CV_LeafKind_NOTTRAN = 0x0010, CV_LeafKind_DIMARRAY_16t = 0x0011, CV_LeafKind_VFTPATH_16t = 0x0012, CV_LeafKind_PRECOMP_16t = 0x0013, CV_LeafKind_ENDPRECOMP = 0x0014, CV_LeafKind_OEM_16t = 0x0015, CV_LeafKind_TYPESERVER_ST = 0x0016, CV_LeafKind_SKIP_16t = 0x0200, CV_LeafKind_ARGLIST_16t = 0x0201, CV_LeafKind_DEFARG_16t = 0x0202, CV_LeafKind_LIST = 0x0203, CV_LeafKind_FIELDLIST_16t = 0x0204, CV_LeafKind_DERIVED_16t = 0x0205, CV_LeafKind_BITFIELD_16t = 0x0206, CV_LeafKind_METHODLIST_16t = 0x0207, CV_LeafKind_DIMCONU_16t = 0x0208, CV_LeafKind_DIMCONLU_16t = 0x0209, CV_LeafKind_DIMVARU_16t = 0x020a, CV_LeafKind_DIMVARLU_16t = 0x020b, CV_LeafKind_REFSYM = 0x020c, CV_LeafKind_BCLASS_16t = 0x0400, CV_LeafKind_VBCLASS_16t = 0x0401, CV_LeafKind_IVBCLASS_16t = 0x0402, CV_LeafKind_ENUMERATE_ST = 0x0403, CV_LeafKind_FRIENDFCN_16t = 0x0404, CV_LeafKind_INDEX_16t = 0x0405, CV_LeafKind_MEMBER_16t = 0x0406, CV_LeafKind_STMEMBER_16t = 0x0407, CV_LeafKind_METHOD_16t = 0x0408, CV_LeafKind_NESTTYPE_16t = 0x0409, CV_LeafKind_VFUNCTAB_16t = 0x040a, CV_LeafKind_FRIENDCLS_16t = 0x040b, CV_LeafKind_ONEMETHOD_16t = 0x040c, CV_LeafKind_VFUNCOFF_16t = 0x040d, CV_LeafKind_TI16_MAX = 0x1000, CV_LeafKind_MODIFIER = 0x1001, CV_LeafKind_POINTER = 0x1002, CV_LeafKind_ARRAY_ST = 0x1003, CV_LeafKind_CLASS_ST = 0x1004, CV_LeafKind_STRUCTURE_ST = 0x1005, CV_LeafKind_UNION_ST = 0x1006, CV_LeafKind_ENUM_ST = 0x1007, CV_LeafKind_PROCEDURE = 0x1008, CV_LeafKind_MFUNCTION = 0x1009, CV_LeafKind_COBOL0 = 0x100a, CV_LeafKind_BARRAY = 0x100b, CV_LeafKind_DIMARRAY_ST = 0x100c, CV_LeafKind_VFTPATH = 0x100d, CV_LeafKind_PRECOMP_ST = 0x100e, CV_LeafKind_OEM = 0x100f, CV_LeafKind_ALIAS_ST = 0x1010, CV_LeafKind_OEM2 = 0x1011, CV_LeafKind_SKIP = 0x1200, CV_LeafKind_ARGLIST = 0x1201, CV_LeafKind_DEFARG_ST = 0x1202, CV_LeafKind_FIELDLIST = 0x1203, CV_LeafKind_DERIVED = 0x1204, CV_LeafKind_BITFIELD = 0x1205, CV_LeafKind_METHODLIST = 0x1206, CV_LeafKind_DIMCONU = 0x1207, CV_LeafKind_DIMCONLU = 0x1208, CV_LeafKind_DIMVARU = 0x1209, CV_LeafKind_DIMVARLU = 0x120a, CV_LeafKind_BCLASS = 0x1400, CV_LeafKind_VBCLASS = 0x1401, CV_LeafKind_IVBCLASS = 0x1402, CV_LeafKind_FRIENDFCN_ST = 0x1403, CV_LeafKind_INDEX = 0x1404, CV_LeafKind_MEMBER_ST = 0x1405, CV_LeafKind_STMEMBER_ST = 0x1406, CV_LeafKind_METHOD_ST = 0x1407, CV_LeafKind_NESTTYPE_ST = 0x1408, CV_LeafKind_VFUNCTAB = 0x1409, CV_LeafKind_FRIENDCLS = 0x140a, CV_LeafKind_ONEMETHOD_ST = 0x140b, CV_LeafKind_VFUNCOFF = 0x140c, CV_LeafKind_NESTTYPEEX_ST = 0x140d, CV_LeafKind_MEMBERMODIFY_ST = 0x140e, CV_LeafKind_MANAGED_ST = 0x140f, CV_LeafKind_ST_MAX = 0x1500, CV_LeafKind_TYPESERVER = 0x1501, CV_LeafKind_ENUMERATE = 0x1502, CV_LeafKind_ARRAY = 0x1503, CV_LeafKind_CLASS = 0x1504, CV_LeafKind_STRUCTURE = 0x1505, CV_LeafKind_UNION = 0x1506, CV_LeafKind_ENUM = 0x1507, CV_LeafKind_DIMARRAY = 0x1508, CV_LeafKind_PRECOMP = 0x1509, CV_LeafKind_ALIAS = 0x150a, CV_LeafKind_DEFARG = 0x150b, CV_LeafKind_FRIENDFCN = 0x150c, CV_LeafKind_MEMBER = 0x150d, CV_LeafKind_STMEMBER = 0x150e, CV_LeafKind_METHOD = 0x150f, CV_LeafKind_NESTTYPE = 0x1510, CV_LeafKind_ONEMETHOD = 0x1511, CV_LeafKind_NESTTYPEEX = 0x1512, CV_LeafKind_MEMBERMODIFY = 0x1513, CV_LeafKind_MANAGED = 0x1514, CV_LeafKind_TYPESERVER2 = 0x1515, CV_LeafKind_STRIDED_ARRAY = 0x1516, CV_LeafKind_HLSL = 0x1517, CV_LeafKind_MODIFIER_EX = 0x1518, CV_LeafKind_INTERFACE = 0x1519, CV_LeafKind_BINTERFACE = 0x151a, CV_LeafKind_VECTOR = 0x151b, CV_LeafKind_MATRIX = 0x151c, CV_LeafKind_VFTABLE = 0x151d, CV_LeafKind_FUNC_ID = 0x1601, CV_LeafKind_MFUNC_ID = 0x1602, CV_LeafKind_BUILDINFO = 0x1603, CV_LeafKind_SUBSTR_LIST = 0x1604, CV_LeafKind_STRING_ID = 0x1605, CV_LeafKind_UDT_SRC_LINE = 0x1606, CV_LeafKind_UDT_MOD_SRC_LINE = 0x1607, CV_LeafKind_CLASS2 = 0x1608, CV_LeafKind_STRUCT2 = 0x1609, } CV_LeafKindEnum; internal String8 cv_string_from_numeric_kind(CV_NumericKind v); internal String8 cv_string_from_arch(CV_Arch v); internal String8 cv_string_from_sym_kind(CV_SymKind v); internal String8 cv_string_from_basic_type(CV_BasicType v); internal String8 cv_type_name_from_basic_type(CV_BasicType v); internal String8 cv_string_from_leaf_kind(CV_LeafKind v); internal U64 cv_header_struct_size_from_sym_kind(CV_SymKind v); internal U64 cv_header_struct_size_from_leaf_kind(CV_LeafKind v); #endif // CODEVIEW_META_H ================================================ FILE: src/coff/coff.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags) { U32 align = 0; U32 align_index = COFF_SectionFlags_ExtractAlign(flags); switch (align_index) { default: break; case COFF_SectionAlign_1Bytes: align = 1; break; case COFF_SectionAlign_2Bytes: align = 2; break; case COFF_SectionAlign_4Bytes: align = 4; break; case COFF_SectionAlign_8Bytes: align = 8; break; case COFF_SectionAlign_16Bytes: align = 16; break; case COFF_SectionAlign_32Bytes: align = 32; break; case COFF_SectionAlign_64Bytes: align = 64; break; case COFF_SectionAlign_128Bytes: align = 128; break; case COFF_SectionAlign_256Bytes: align = 256; break; case COFF_SectionAlign_512Bytes: align = 512; break; case COFF_SectionAlign_1024Bytes: align = 1024; break; case COFF_SectionAlign_2048Bytes: align = 2048; break; case COFF_SectionAlign_4096Bytes: align = 4096; break; case COFF_SectionAlign_8192Bytes: align = 8192; break; } return align; } internal COFF_SectionFlags coff_section_flag_from_align_size(U64 align) { COFF_SectionFlags flags = 0; switch (align) { case 0: flags = COFF_SectionAlign_None; break; case 1: flags = COFF_SectionAlign_1Bytes; break; case 2: flags = COFF_SectionAlign_2Bytes; break; case 4: flags = COFF_SectionAlign_4Bytes; break; case 8: flags = COFF_SectionAlign_8Bytes; break; case 16: flags = COFF_SectionAlign_16Bytes; break; case 32: flags = COFF_SectionAlign_32Bytes; break; case 64: flags = COFF_SectionAlign_64Bytes; break; case 128: flags = COFF_SectionAlign_128Bytes; break; case 256: flags = COFF_SectionAlign_256Bytes; break; case 512: flags = COFF_SectionAlign_512Bytes; break; case 1024: flags = COFF_SectionAlign_1024Bytes; break; case 2048: flags = COFF_SectionAlign_2048Bytes; break; case 4096: flags = COFF_SectionAlign_4096Bytes; break; case 8192: flags = COFF_SectionAlign_8192Bytes; break; } flags <<= COFF_SectionFlag_AlignShift; return flags; } internal String8 coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header) { String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name)); if (name.str[0] == '/') { String8 name_off_str = str8_skip(name, 1); U64 name_off = u64_from_str8(name_off_str, 10); name = str8_cstring_capped(string_table.str + name_off, string_table.str+string_table.size); } return name; } internal void coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_out) { // dollar sign has multiple interpretations that depend on the type of the section. // 1. when section contains code/data it indicates section precedence // 2. when section starts with .debug it indicates type of data inside the section // T: Types // S: Symbols // P: Precompiled types // F: FPO data // H: Clang extension produced with /debug:ghash, array of type hashes *name_out = full_name; *postfix_out = str8_lit(""); for (U64 i = 0; i < full_name.size; ++i) { if (full_name.str[i] == '$') { *name_out = str8(full_name.str, i); *postfix_out = str8(full_name.str + i, full_name.size - i); break; } } } internal String8 coff_read_symbol_name(String8 string_table, COFF_SymbolName *name) { String8 name_str = str8_lit(""); if (name->long_name.zeroes == 0) { str8_deserial_read_cstr(string_table, name->long_name.string_table_offset, &name_str); } else { U32 i; for (i = 0; i < sizeof(name->short_name); ++i) { if (name->short_name[i] == '\0') { break; } } name_str = str8(name->short_name, i); } return name_str; } internal U64 coff_is_addr_reloc(COFF_MachineType machine, U32 type) { U64 is_addr = 0; switch (machine) { case COFF_MachineType_Unknown: is_addr = 0; break; case COFF_MachineType_X64: { if (type == COFF_Reloc_X64_Addr32) is_addr = 4; else if (type == COFF_Reloc_X64_Addr64) is_addr = 8; } break; default: NotImplemented; break; } return is_addr; } internal U64 coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x) { switch (x) { case COFF_Reloc_X64_Abs: return 4; case COFF_Reloc_X64_Addr64: return 8; case COFF_Reloc_X64_Addr32: return 4; case COFF_Reloc_X64_Addr32Nb: return 4; case COFF_Reloc_X64_Rel32: return 4; case COFF_Reloc_X64_Rel32_1: return 4; case COFF_Reloc_X64_Rel32_2: return 4; case COFF_Reloc_X64_Rel32_3: return 4; case COFF_Reloc_X64_Rel32_4: return 4; case COFF_Reloc_X64_Rel32_5: return 4; case COFF_Reloc_X64_Section: return 2; case COFF_Reloc_X64_SecRel: return 4; case COFF_Reloc_X64_SRel32: return 4; case COFF_Reloc_X64_SecRel7: case COFF_Reloc_X64_Token: case COFF_Reloc_X64_Pair: case COFF_Reloc_X64_SSpan32: NotImplemented; break; } return 0; } internal U64 coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x) { switch (x) { case COFF_Reloc_X86_Abs: return 4; case COFF_Reloc_X86_Dir16: return 2; case COFF_Reloc_X86_Rel16: return 2; case COFF_Reloc_X86_Dir32: return 4; case COFF_Reloc_X86_Dir32Nb: return 4; case COFF_Reloc_X86_Seg12: return 0; case COFF_Reloc_X86_Section: return 2; case COFF_Reloc_X86_SecRel: return 4; case COFF_Reloc_X86_Token: return 4; case COFF_Reloc_X86_SecRel7: return 1; case COFF_Reloc_X86_Rel32: return 4; case COFF_Reloc_X86_Unknown0: case COFF_Reloc_X86_Unknown2: case COFF_Reloc_X86_Unknown3: case COFF_Reloc_X86_Unknown4: case COFF_Reloc_X86_Unknown6: case COFF_Reloc_X86_Unknown7: case COFF_Reloc_X86_Unknown8: case COFF_Reloc_X86_Unknown9: NotImplemented; break; } return 0; } internal U64 coff_apply_size_from_reloc(COFF_MachineType machine, COFF_RelocType x) { switch (machine) { case COFF_MachineType_X64: return coff_apply_size_from_reloc_x64(x); case COFF_MachineType_X86: return coff_apply_size_from_reloc_x86(x); default: NotImplemented; } return 0; } internal COFF_RelocValue coff_pick_reloc_value_x64(COFF_Reloc_X64 type, U64 image_base, U64 reloc_virtual_offset, U32 symbol_section_number, U32 symbol_section_offset, S64 symbol_virtual_offset) { U64 reloc_value_size = 0; S64 reloc_value = 0; switch (type) { case COFF_Reloc_X64_Abs: {} break; case COFF_Reloc_X64_Addr64: { reloc_value_size = 8; reloc_value = symbol_virtual_offset + (S64)image_base; } break; case COFF_Reloc_X64_Addr32: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset + (S64)image_base); } break; case COFF_Reloc_X64_Addr32Nb: { reloc_value_size = 4; reloc_value = symbol_virtual_offset; } break; case COFF_Reloc_X64_Rel32: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 0)); } break; case COFF_Reloc_X64_Rel32_1: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 1)); } break; case COFF_Reloc_X64_Rel32_2: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 2)); } break; case COFF_Reloc_X64_Rel32_3: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 3)); } break; case COFF_Reloc_X64_Rel32_4: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 4)); } break; case COFF_Reloc_X64_Rel32_5: { reloc_value_size = 4; reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5)); } break; case COFF_Reloc_X64_Section: { reloc_value_size = 4; reloc_value = symbol_section_number; } break; case COFF_Reloc_X64_SecRel: { reloc_value_size = 4; reloc_value = symbol_section_offset; } break; case COFF_Reloc_X64_SecRel7: case COFF_Reloc_X64_Token: case COFF_Reloc_X64_SRel32: case COFF_Reloc_X64_Pair: case COFF_Reloc_X64_SSpan32: case COFF_Reloc_X64_Unknown_11: { NotImplemented; } break; } COFF_RelocValue result = {0}; result.size = reloc_value_size; result.value = reloc_value; return result; } internal String8 coff_make_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size) { Assert(name.size < 16); Assert(user_id < 10000); Assert(group_id < 10000); Assert(mode < 10000); Assert(size < 1000000000); Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; str8_list_pushf(scratch.arena, &list, "%-16.*s", str8_varg(name)); str8_list_pushf(scratch.arena, &list, "%-12u", time_stamp); str8_list_pushf(scratch.arena, &list, "%-6u", user_id); str8_list_pushf(scratch.arena, &list, "%-6u", group_id); str8_list_pushf(scratch.arena, &list, "%-8u", mode); str8_list_pushf(scratch.arena, &list, "%-10u", size); str8_list_pushf(scratch.arena, &list, "`\n"); String8 result = str8_list_join(arena, &list, 0); Assert(result.size == sizeof(COFF_ArchiveMemberHeader)); scratch_end(scratch); return result; } internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name) { U64 buffer_size = sizeof(hint) + (name.size + 1); U8 *buffer = push_array(arena, U8, buffer_size); *(U16*)buffer = hint; MemoryCopy(buffer + sizeof(hint), name.str, name.size); buffer[buffer_size - 1] = 0; String8 result = str8(buffer, buffer_size); return result; } internal U32 coff_make_ordinal32(U16 hint) { U32 ordinal = (1 << 31) | hint; return ordinal; } internal U64 coff_make_ordinal64(U16 hint) { U64 ordinal = (1ULL << 63) | hint; return ordinal; } internal String8 coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint) { String8 ordinal_data = {0}; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: { U64 *ordinal = push_array(arena, U64, 1); *ordinal = coff_make_ordinal64(hint); ordinal_data = str8_struct(ordinal); } break; case COFF_MachineType_X86: { U32 *ordinal = push_array(arena, U32, 1); *ordinal = coff_make_ordinal32(hint); ordinal_data = str8_struct(ordinal); } break; default: { NotImplemented; } break; } return ordinal_data; } internal String8 coff_make_import_header(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType type) { COFF_ImportHeaderFlags flags = 0; flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift; flags |= import_by << COFF_ImportHeader_ImportByShift; COFF_ImportHeader header = {0}; header.sig1 = COFF_MachineType_Unknown; header.sig2 = max_U16; header.version = 0; header.machine = machine; header.time_stamp = time_stamp; header.data_size = safe_cast_u32(name.size + dll_name.size + 2); header.hint_or_ordinal = hint_or_ordinal; header.flags = flags; // alloc memory U64 buffer_size = sizeof(header) + header.data_size; U8 *buffer = push_array_no_zero(arena, U8, buffer_size); // copy header MemoryCopy(buffer, &header, sizeof(header)); // copy function name U8 *func_name = buffer + sizeof(header); MemoryCopy(func_name, name.str, name.size); func_name[name.size] = 0; // copy dll name U8 *dll_name_buffer = buffer + sizeof(header) + name.size + 1; MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size); dll_name_buffer[dll_name.size] = 0; String8 import_data = str8(buffer, buffer_size); return import_data; } internal U8 coff_code_align_byte_from_machine(COFF_MachineType machine) { U8 align_byte = 0; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: case COFF_MachineType_X86: { align_byte = 0xCC; } break; default: { NotImplemented; } break; } return align_byte; } internal U16 coff_default_align_from_machine(COFF_MachineType machine) { U16 align = 0; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: { align = 16; } break; default: { NotImplemented; } break; } return align; } internal U64 coff_word_size_from_machine(COFF_MachineType machine) { U64 result = 0; switch (machine) { case COFF_MachineType_X64: result = 8; break; case COFF_MachineType_X86: result = 4; break; } return result; } internal U64 coff_default_exe_base_from_machine(COFF_MachineType machine) { U64 exe_base = 0; switch (coff_word_size_from_machine(machine)) { case 4: exe_base = 0x400000; break; case 8: exe_base = 0x140000000; break; } return exe_base; } internal U64 coff_default_dll_base_from_machine(COFF_MachineType machine) { U64 dll_base = 0; switch (coff_word_size_from_machine(machine)) { case 4: dll_base = 0x10000000; break; case 8: dll_base = 0x180000000; break; } return dll_base; } internal Arch arch_from_coff_machine(COFF_MachineType machine) { Arch result = Arch_Null; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: result = Arch_x86; break; case COFF_MachineType_X64: result = Arch_x64; break; case COFF_MachineType_Arm: result = Arch_arm32; break; case COFF_MachineType_Arm64: result = Arch_arm64; break; } return result; } internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff) { U64 foff = 0; for(U64 sect_idx = 0; sect_idx < section_count; sect_idx += 1) { COFF_SectionHeader *sect = §ions[sect_idx]; if(sect->voff <= voff && voff < sect->voff+sect->vsize) { if(!(sect->flags & COFF_SectionFlag_CntUninitializedData)) { foff = sect->foff + (voff - sect->voff); } break; } } return foff; } //////////////////////////////// //~ rjf: Enum -> String internal String8 coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp) { String8 result; if (time_stamp == 0) { result = str8_lit("0"); } else if (time_stamp >= max_U32) { result = str8_lit("-1"); } else { DateTime dt = date_time_from_unix_time(time_stamp); result = string_from_date_time(arena, &dt); } return result; } global read_only struct { String8 string; COFF_MachineType machine; } g_coff_machine_map[] = { { str8_lit_comp(""), COFF_MachineType_Unknown }, { str8_lit_comp("X86"), COFF_MachineType_X86 }, { str8_lit_comp("Amd64"), COFF_MachineType_X64 }, { str8_lit_comp("X64"), COFF_MachineType_X64 }, { str8_lit_comp("Am33"), COFF_MachineType_Am33 }, { str8_lit_comp("Arm"), COFF_MachineType_Arm }, { str8_lit_comp("Arm64"), COFF_MachineType_Arm64 }, { str8_lit_comp("ArmNt"), COFF_MachineType_ArmNt }, { str8_lit_comp("Ebc"), COFF_MachineType_Ebc }, { str8_lit_comp("Ia64"), COFF_MachineType_Ia64 }, { str8_lit_comp("M32r"), COFF_MachineType_M32R }, { str8_lit_comp("Mips16"), COFF_MachineType_Mips16 }, { str8_lit_comp("MipsFpu"), COFF_MachineType_MipsFpu }, { str8_lit_comp("MipsFpu16"), COFF_MachineType_MipsFpu16 }, { str8_lit_comp("PowerPc"), COFF_MachineType_PowerPc }, { str8_lit_comp("PowerPcFp"), COFF_MachineType_PowerPcFp }, { str8_lit_comp("R4000"), COFF_MachineType_R4000 }, { str8_lit_comp("RiscV32"), COFF_MachineType_RiscV32 }, { str8_lit_comp("RiscV64"), COFF_MachineType_RiscV64 }, { str8_lit_comp("Sh3"), COFF_MachineType_Sh3 }, { str8_lit_comp("Sh3Dsp"), COFF_MachineType_Sh3Dsp }, { str8_lit_comp("Sh4"), COFF_MachineType_Sh4 }, { str8_lit_comp("Sh5"), COFF_MachineType_Sh5 }, { str8_lit_comp("Thumb"), COFF_MachineType_Thumb }, { str8_lit_comp("WceMipsV2"), COFF_MachineType_WceMipsV2 }, }; global read_only struct { char * name; COFF_ImportType type; } g_coff_import_header_type_map[] = { { "Code", COFF_ImportHeader_Code }, { "Data", COFF_ImportHeader_Data }, { "Const", COFF_ImportHeader_Const }, }; internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType type) { String8 result = str8_zero(); switch (type) { case COFF_ComdatSelect_Null: result = str8_lit("Null"); break; case COFF_ComdatSelect_NoDuplicates: result = str8_lit("NoDuplicates"); break; case COFF_ComdatSelect_Any: result = str8_lit("Any"); break; case COFF_ComdatSelect_SameSize: result = str8_lit("SameSize"); break; case COFF_ComdatSelect_ExactMatch: result = str8_lit("ExactMatch"); break; case COFF_ComdatSelect_Associative: result = str8_lit("Associative"); break; case COFF_ComdatSelect_Largest: result = str8_lit("Largest"); break; } return result; } internal String8 coff_string_from_machine_type(COFF_MachineType machine) { for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) { if (g_coff_machine_map[i].machine == machine) { return g_coff_machine_map[i].string; } } return str8_zero(); } internal String8 coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (flags & COFF_FileHeaderFlag_RelocStripped) { str8_list_pushf(scratch.arena, &list, "Relocs Stripped"); } if (flags & COFF_FileHeaderFlag_ExecutableImage) { str8_list_pushf(scratch.arena, &list, "Executable"); } if (flags & COFF_FileHeaderFlag_LineNumbersStripped) { str8_list_pushf(scratch.arena, &list, "Line Numbers Stripped"); } if (flags & COFF_FileHeaderFlag_SymbolsStripped) { str8_list_pushf(scratch.arena, &list, "Symbols Stripped"); } if (flags & COFF_FileHeaderFlag_LargeAddressAware) { str8_list_pushf(scratch.arena, &list, "Large Address Aware"); } if (flags & COFF_FileHeaderFlag_32BitMachine) { str8_list_pushf(scratch.arena, &list, "32-Bit Machine"); } if (flags & COFF_FileHeaderFlag_DebugStripped) { str8_list_pushf(scratch.arena, &list, "Debug Stripped"); } if (flags & COFF_FileHeaderFlag_RemovableRunFromSwap) { str8_list_pushf(scratch.arena, &list, "Removeable Run From Swap"); } if (flags & COFF_FileHeaderFlag_NetRunFromSwap) { str8_list_pushf(scratch.arena, &list, "Net Run From Swap"); } if (flags & COFF_FileHeaderFlag_System) { str8_list_pushf(scratch.arena, &list, "System"); } if (flags & COFF_FileHeaderFlag_Dll) { str8_list_pushf(scratch.arena, &list, "DLL"); } if (flags & COFF_FileHeaderFlag_UpSystemOnly) { str8_list_pushf(scratch.arena, &list, "Up System Only"); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (flags & COFF_SectionFlag_TypeNoPad) { str8_list_pushf(scratch.arena, &list, "TypeNoPad"); } if (flags & COFF_SectionFlag_CntCode) { str8_list_pushf(scratch.arena, &list, "CntCode"); } if (flags & COFF_SectionFlag_CntInitializedData) { str8_list_pushf(scratch.arena, &list, "CntInitializedData"); } if (flags & COFF_SectionFlag_CntUninitializedData) { str8_list_pushf(scratch.arena, &list, "CntUninitializedData"); } if (flags & COFF_SectionFlag_LnkOther) { str8_list_pushf(scratch.arena, &list, "LnkOther"); } if (flags & COFF_SectionFlag_LnkInfo) { str8_list_pushf(scratch.arena, &list, "LnkInfo"); } if (flags & COFF_SectionFlag_LnkCOMDAT) { str8_list_pushf(scratch.arena, &list, "LnkCOMDAT"); } if (flags & COFF_SectionFlag_GpRel) { str8_list_pushf(scratch.arena, &list, "GpRel"); } if (flags & COFF_SectionFlag_Mem16Bit) { str8_list_pushf(scratch.arena, &list, "Mem16Bit"); } if (flags & COFF_SectionFlag_MemLocked) { str8_list_pushf(scratch.arena, &list, "MemLocked"); } if (flags & COFF_SectionFlag_MemPreload) { str8_list_pushf(scratch.arena, &list, "MemPreload"); } if (flags & COFF_SectionFlag_LnkNRelocOvfl) { str8_list_pushf(scratch.arena, &list, "LnkNRelocOvfl"); } if (flags & COFF_SectionFlag_MemDiscardable) { str8_list_pushf(scratch.arena, &list, "MemDiscardable"); } if (flags & COFF_SectionFlag_MemNotCached) { str8_list_pushf(scratch.arena, &list, "MemNotCached"); } if (flags & COFF_SectionFlag_MemNotPaged) { str8_list_pushf(scratch.arena, &list, "MemNotPaged"); } if (flags & COFF_SectionFlag_MemShared) { str8_list_pushf(scratch.arena, &list, "MemShared"); } if (flags & COFF_SectionFlag_MemExecute) { str8_list_pushf(scratch.arena, &list, "MemExecute"); } if (flags & COFF_SectionFlag_MemRead) { str8_list_pushf(scratch.arena, &list, "MemRead"); } if (flags & COFF_SectionFlag_MemWrite) { str8_list_pushf(scratch.arena, &list, "MemWrite"); } U64 align = coff_align_size_from_section_flags(flags); if (align) { str8_list_pushf(scratch.arena, &list, "Align=%u", align); } if (!list.node_count) { str8_list_pushf(scratch.arena, &list, "None"); } StringJoin join = {0}; join.sep = str8_lit(", "); String8 result = str8_list_join(arena, &list, &join); scratch_end(scratch); return result; } internal String8 coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (flags & COFF_ResourceMemoryFlag_Moveable) { flags &= COFF_ResourceMemoryFlag_Moveable; str8_list_pushf(scratch.arena, &list, "Moveable"); } if (flags & COFF_ResourceMemoryFlag_Pure) { flags &= COFF_ResourceMemoryFlag_Pure; str8_list_pushf(scratch.arena, &list, "Pure"); } if (flags & COFF_ResourceMemoryFlag_Discardable) { flags &= COFF_ResourceMemoryFlag_Discardable; str8_list_pushf(scratch.arena, &list, "Discardable"); } if (flags != 0) { str8_list_pushf(scratch.arena, &list, "%#x", flags); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 coff_string_from_import_header_type(COFF_ImportType type) { for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) { if (g_coff_import_header_type_map[i].type == type) { return str8_cstring(g_coff_import_header_type_map[i].name); } } return str8(0,0); } internal String8 coff_string_from_sym_dtype(COFF_SymDType x) { switch (x) { case COFF_SymDType_Null: return str8_lit("Null"); case COFF_SymDType_Ptr : return str8_lit("Ptr"); case COFF_SymDType_Func: return str8_lit("Func"); case COFF_SymDType_Array: return str8_lit("Array"); } return str8_zero(); } internal String8 coff_string_from_sym_type(COFF_SymType x) { switch (x) { case COFF_SymType_Null: return str8_lit("Null"); case COFF_SymType_Void: return str8_lit("Void"); case COFF_SymType_Char: return str8_lit("Char"); case COFF_SymType_Short: return str8_lit("Short"); case COFF_SymType_Int: return str8_lit("Int"); case COFF_SymType_Long: return str8_lit("Long"); case COFF_SymType_Float: return str8_lit("Float"); case COFF_SymType_Double: return str8_lit("Double"); case COFF_SymType_Struct: return str8_lit("Struct"); case COFF_SymType_Union: return str8_lit("Union"); case COFF_SymType_Enum: return str8_lit("Enum"); case COFF_SymType_MemberOfEnumeration: return str8_lit("MOE"); case COFF_SymType_Byte: return str8_lit("Byte"); case COFF_SymType_Word: return str8_lit("Word"); case COFF_SymType_UInt: return str8_lit("UInt"); case COFF_SymType_DWord: return str8_lit("DWord"); } return str8_zero(); } internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x) { switch (x) { case COFF_SymStorageClass_Null: break; case COFF_SymStorageClass_EndOfFunction: return str8_lit("EndOfFunction"); case COFF_SymStorageClass_Automatic: return str8_lit("Automatic"); case COFF_SymStorageClass_External: return str8_lit("External"); case COFF_SymStorageClass_Static: return str8_lit("Static"); case COFF_SymStorageClass_Register: return str8_lit("Register"); case COFF_SymStorageClass_ExternalDef: return str8_lit("Def"); case COFF_SymStorageClass_Label: return str8_lit("Label"); case COFF_SymStorageClass_UndefinedLabel: return str8_lit("UndefinedLabel"); case COFF_SymStorageClass_MemberOfStruct: return str8_lit("Struct"); case COFF_SymStorageClass_Argument: return str8_lit("Argument"); case COFF_SymStorageClass_StructTag: return str8_lit("Tag"); case COFF_SymStorageClass_MemberOfUnion: return str8_lit("Union"); case COFF_SymStorageClass_UnionTag: return str8_lit("Tag"); case COFF_SymStorageClass_TypeDefinition: return str8_lit("Definition"); case COFF_SymStorageClass_UndefinedStatic: return str8_lit("Static"); case COFF_SymStorageClass_EnumTag: return str8_lit("Tag"); case COFF_SymStorageClass_MemberOfEnum: return str8_lit("Enum"); case COFF_SymStorageClass_RegisterParam: return str8_lit("Param"); case COFF_SymStorageClass_BitField: return str8_lit("Field"); case COFF_SymStorageClass_Block: return str8_lit("Block"); case COFF_SymStorageClass_Function: return str8_lit("Function"); case COFF_SymStorageClass_EndOfStruct: return str8_lit("Struct"); case COFF_SymStorageClass_File: return str8_lit("File"); case COFF_SymStorageClass_Section: return str8_lit("Section"); case COFF_SymStorageClass_WeakExternal: return str8_lit("External"); case COFF_SymStorageClass_CLRToken: return str8_lit("Token"); } return str8_zero(); } internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x) { switch (x) { case COFF_WeakExt_NoLibrary: return str8_lit("NoLibrary"); case COFF_WeakExt_SearchLibrary: return str8_lit("SearchLibrary"); case COFF_WeakExt_SearchAlias: return str8_lit("SearchAlias"); } return str8_zero(); } internal String8 coff_string_from_reloc_x86(COFF_Reloc_X86 x) { switch (x) { case COFF_Reloc_X86_Abs: return str8_lit("Abs"); case COFF_Reloc_X86_Dir16: return str8_lit("Dir16"); case COFF_Reloc_X86_Rel16: return str8_lit("Rel16"); case COFF_Reloc_X86_Unknown0: return str8_lit("Unknown0"); case COFF_Reloc_X86_Unknown2: return str8_lit("Unknown2"); case COFF_Reloc_X86_Unknown3: return str8_lit("Unknown3"); case COFF_Reloc_X86_Dir32: return str8_lit("Dir32"); case COFF_Reloc_X86_Dir32Nb: return str8_lit("Dir32Nb"); case COFF_Reloc_X86_Seg12: return str8_lit("Seg12"); case COFF_Reloc_X86_Section: return str8_lit("Section"); case COFF_Reloc_X86_SecRel: return str8_lit("SecRel"); case COFF_Reloc_X86_Token: return str8_lit("Token"); case COFF_Reloc_X86_SecRel7: return str8_lit("SecRel7"); case COFF_Reloc_X86_Unknown4: return str8_lit("Unknown4"); case COFF_Reloc_X86_Unknown5: return str8_lit("Unknown5"); case COFF_Reloc_X86_Unknown6: return str8_lit("Unknown6"); case COFF_Reloc_X86_Unknown7: return str8_lit("Unknown7"); case COFF_Reloc_X86_Unknown8: return str8_lit("Unknown8"); case COFF_Reloc_X86_Unknown9: return str8_lit("Unknown9"); case COFF_Reloc_X86_Rel32: return str8_lit("Rel32"); } return str8_zero(); } internal String8 coff_string_from_reloc_x64(COFF_Reloc_X64 x) { switch (x) { case COFF_Reloc_X64_Abs: return str8_lit("Abs"); case COFF_Reloc_X64_Addr64: return str8_lit("Addr64"); case COFF_Reloc_X64_Addr32: return str8_lit("Addr32"); case COFF_Reloc_X64_Addr32Nb: return str8_lit("Addr32Nb"); case COFF_Reloc_X64_Rel32: return str8_lit("Rel32"); case COFF_Reloc_X64_Rel32_1: return str8_lit("Rel32_1"); case COFF_Reloc_X64_Rel32_2: return str8_lit("Rel32_2"); case COFF_Reloc_X64_Rel32_3: return str8_lit("Rel32_3"); case COFF_Reloc_X64_Rel32_4: return str8_lit("Rel32_4"); case COFF_Reloc_X64_Rel32_5: return str8_lit("Rel32_5"); case COFF_Reloc_X64_Section: return str8_lit("Section"); case COFF_Reloc_X64_SecRel: return str8_lit("SecRel"); case COFF_Reloc_X64_SecRel7: return str8_lit("SecRel7"); case COFF_Reloc_X64_Token: return str8_lit("Token"); case COFF_Reloc_X64_SRel32: return str8_lit("SRel32"); case COFF_Reloc_X64_Pair: return str8_lit("Pair"); case COFF_Reloc_X64_SSpan32: return str8_lit("SSpan32"); } return str8_zero(); } internal String8 coff_string_from_reloc_arm(COFF_Reloc_Arm x) { switch (x) { case COFF_Reloc_Arm_Abs: return str8_lit("Abs"); case COFF_Reloc_Arm_Addr32: return str8_lit("Addr32"); case COFF_Reloc_Arm_Addr32Nb: return str8_lit("Addr32Nb"); case COFF_Reloc_Arm_Branch24: return str8_lit("Branch24"); case COFF_Reloc_Arm_Branch11: return str8_lit("Branch11"); case COFF_Reloc_Arm_Unknown1: return str8_lit("Unknown1"); case COFF_Reloc_Arm_Unknown2: return str8_lit("Unknown2"); case COFF_Reloc_Arm_Unknown3: return str8_lit("Unknown3"); case COFF_Reloc_Arm_Unknown4: return str8_lit("Unknown4"); case COFF_Reloc_Arm_Unknown5: return str8_lit("Unknown5"); case COFF_Reloc_Arm_Rel32: return str8_lit("Rel32"); case COFF_Reloc_Arm_Section: return str8_lit("Section"); case COFF_Reloc_Arm_SecRel: return str8_lit("SecRel"); case COFF_Reloc_Arm_Mov32: return str8_lit("Mov32"); case COFF_Reloc_Arm_ThumbMov32: return str8_lit("ThumbMov32"); case COFF_Reloc_Arm_ThumbBranch20: return str8_lit("ThumbBranch20"); case COFF_Reloc_Arm_Unused: return str8_lit("Unused"); case COFF_Reloc_Arm_ThumbBranch24: return str8_lit("ThumbBranch24"); case COFF_Reloc_Arm_ThumbBlx23: return str8_lit("ThumbBlx23"); case COFF_Reloc_Arm_Pair: return str8_lit("Pair"); } return str8_zero(); } internal String8 coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x) { switch (x) { case COFF_Reloc_Arm64_Abs: return str8_lit("Abs"); case COFF_Reloc_Arm64_Addr32: return str8_lit("Addr32"); case COFF_Reloc_Arm64_Addr32Nb: return str8_lit("Addr32Nb"); case COFF_Reloc_Arm64_Branch26: return str8_lit("Branch26"); case COFF_Reloc_Arm64_PageBaseRel21: return str8_lit("PageBaseRel21"); case COFF_Reloc_Arm64_Rel21: return str8_lit("Rel21"); case COFF_Reloc_Arm64_PageOffset12a: return str8_lit("PageOffset12a"); case COFF_Reloc_Arm64_SecRel: return str8_lit("SecRel"); case COFF_Reloc_Arm64_SecRelLow12a: return str8_lit("SecRelLow12a"); case COFF_Reloc_Arm64_SecRelHigh12a: return str8_lit("SecRelHigh12a"); case COFF_Reloc_Arm64_SecRelLow12l: return str8_lit("SecRelLow12l"); case COFF_Reloc_Arm64_Token: return str8_lit("Token"); case COFF_Reloc_Arm64_Section: return str8_lit("Section"); case COFF_Reloc_Arm64_Addr64: return str8_lit("Addr64"); case COFF_Reloc_Arm64_Branch19: return str8_lit("Branch19"); case COFF_Reloc_Arm64_Branch14: return str8_lit("Branch14"); case COFF_Reloc_Arm64_Rel32: return str8_lit("Rel32"); } return str8_zero(); } internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x) { switch (machine) { case COFF_MachineType_X86: return coff_string_from_reloc_x86(x); case COFF_MachineType_X64: return coff_string_from_reloc_x64(x); case COFF_MachineType_Arm: return coff_string_from_reloc_arm(x); case COFF_MachineType_Arm64: return coff_string_from_reloc_arm64(x); } return str8_zero(); } internal COFF_MachineType coff_machine_from_string(String8 string) { for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) { if (str8_match(g_coff_machine_map[i].string, string, StringMatchFlag_CaseInsensitive)) { return g_coff_machine_map[i].machine; } } return COFF_MachineType_Unknown; } internal COFF_ImportType coff_import_header_type_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) { if (str8_match(str8_cstring(g_coff_import_header_type_map[i].name), name, StringMatchFlag_CaseInsensitive)) { return g_coff_import_header_type_map[i].type; } } return COFF_ImportType_Invalid; } ================================================ FILE: src/coff/coff.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_H #define COFF_H //////////////////////////////// //~ rjf: COFF Format Types read_only global U8 g_coff_big_header_magic[] = { 0xc7, 0xa1, 0xba, 0xd1, 0xee, 0xba, 0xa9, 0x4b, 0xaf, 0x20, 0xfa, 0xf6, 0x6a, 0xa4, 0xdc, 0xb8 }; read_only global U8 g_coff_res_magic[] = { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; read_only global U8 g_coff_archive_sig[8] = "!\n"; read_only global U8 g_coff_thin_archive_sig[8] = "!\n"; #pragma pack(push, 1) #define COFF_TimeStamp_Max max_U32 typedef U32 COFF_TimeStamp; typedef U16 COFF_FileHeaderFlags; enum { COFF_FileHeaderFlag_RelocStripped = (1 << 0), COFF_FileHeaderFlag_ExecutableImage = (1 << 1), COFF_FileHeaderFlag_LineNumbersStripped = (1 << 2), COFF_FileHeaderFlag_SymbolsStripped = (1 << 3), COFF_FileHeaderFlag_Reserved0 = (1 << 4), COFF_FileHeaderFlag_LargeAddressAware = (1 << 5), COFF_FileHeaderFlag_Reserved1 = (1 << 6), COFF_FileHeaderFlag_Reserved2 = (1 << 7), COFF_FileHeaderFlag_32BitMachine = (1 << 8), COFF_FileHeaderFlag_DebugStripped = (1 << 9), COFF_FileHeaderFlag_RemovableRunFromSwap = (1 << 10), COFF_FileHeaderFlag_NetRunFromSwap = (1 << 11), COFF_FileHeaderFlag_System = (1 << 12), COFF_FileHeaderFlag_Dll = (1 << 13), COFF_FileHeaderFlag_UpSystemOnly = (1 << 14), COFF_FileHeaderFlag_BytesReservedHi = (1 << 15) }; typedef U16 COFF_MachineType; enum { COFF_MachineType_Unknown = 0x0, COFF_MachineType_X86 = 0x14c, COFF_MachineType_X64 = 0x8664, COFF_MachineType_Am33 = 0x1d3, COFF_MachineType_Arm = 0x1c0, COFF_MachineType_Arm64 = 0xaa64, COFF_MachineType_ArmNt = 0x1c4, COFF_MachineType_Ebc = 0xebc, COFF_MachineType_Ia64 = 0x200, COFF_MachineType_M32R = 0x9041, COFF_MachineType_Mips16 = 0x266, COFF_MachineType_MipsFpu = 0x366, COFF_MachineType_MipsFpu16 = 0x466, COFF_MachineType_PowerPc = 0x1f0, COFF_MachineType_PowerPcFp = 0x1f1, COFF_MachineType_R4000 = 0x166, COFF_MachineType_RiscV32 = 0x5032, COFF_MachineType_RiscV64 = 0x5064, COFF_MachineType_RiscV128 = 0x5128, COFF_MachineType_Sh3 = 0x1a2, COFF_MachineType_Sh3Dsp = 0x1a3, COFF_MachineType_Sh4 = 0x1a6, COFF_MachineType_Sh5 = 0x1a8, COFF_MachineType_Thumb = 0x1c2, COFF_MachineType_WceMipsV2 = 0x169 }; typedef struct COFF_FileHeader { COFF_MachineType machine; U16 section_count; COFF_TimeStamp time_stamp; U32 symbol_table_foff; U32 symbol_count; U16 optional_header_size; COFF_FileHeaderFlags flags; } COFF_FileHeader; typedef struct COFF_BigObjHeader { U16 sig1; // COFF_MachineType_Unknown U16 sig2; // max_U16 U16 version; // 2 COFF_MachineType machine; COFF_TimeStamp time_stamp; U8 magic[16]; // g_coff_big_header_magic U8 unused[16]; U32 section_count; U32 symbol_table_foff; U32 symbol_count; } COFF_BigObjHeader; typedef U32 COFF_SectionAlign; enum { COFF_SectionAlign_None = 0x0, COFF_SectionAlign_1Bytes = 0x1, COFF_SectionAlign_2Bytes = 0x2, COFF_SectionAlign_4Bytes = 0x3, COFF_SectionAlign_8Bytes = 0x4, COFF_SectionAlign_16Bytes = 0x5, COFF_SectionAlign_32Bytes = 0x6, COFF_SectionAlign_64Bytes = 0x7, COFF_SectionAlign_128Bytes = 0x8, COFF_SectionAlign_256Bytes = 0x9, COFF_SectionAlign_512Bytes = 0xa, COFF_SectionAlign_1024Bytes = 0xb, COFF_SectionAlign_2048Bytes = 0xc, COFF_SectionAlign_4096Bytes = 0xd, COFF_SectionAlign_8192Bytes = 0xe }; typedef U32 COFF_SectionFlags; enum { COFF_SectionFlag_TypeNoPad = (1 << 3), COFF_SectionFlag_CntCode = (1 << 5), COFF_SectionFlag_CntInitializedData = (1 << 6), COFF_SectionFlag_CntUninitializedData = (1 << 7), COFF_SectionFlag_LnkOther = (1 << 8), COFF_SectionFlag_LnkInfo = (1 << 9), COFF_SectionFlag_LnkRemove = (1 << 11), COFF_SectionFlag_LnkCOMDAT = (1 << 12), COFF_SectionFlag_GpRel = (1 << 15), COFF_SectionFlag_Mem16Bit = (1 << 17), COFF_SectionFlag_MemLocked = (1 << 18), COFF_SectionFlag_MemPreload = (1 << 19), COFF_SectionFlag_AlignShift = 20, COFF_SectionFlag_AlignMask = 0xf, COFF_SectionFlag_Align1Bytes = (COFF_SectionAlign_1Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align2Bytes = (COFF_SectionAlign_2Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align4Bytes = (COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align8Bytes = (COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align16Bytes = (COFF_SectionAlign_16Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align32Bytes = (COFF_SectionAlign_32Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align64Bytes = (COFF_SectionAlign_64Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align128Bytes = (COFF_SectionAlign_128Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align256Bytes = (COFF_SectionAlign_256Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align512Bytes = (COFF_SectionAlign_512Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align1024Bytes = (COFF_SectionAlign_1024Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align2048Bytes = (COFF_SectionAlign_2048Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align4096Bytes = (COFF_SectionAlign_4096Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_Align8192Bytes = (COFF_SectionAlign_8192Bytes << COFF_SectionFlag_AlignShift), COFF_SectionFlag_LnkNRelocOvfl = (1 << 24), COFF_SectionFlag_MemDiscardable = (1 << 25), COFF_SectionFlag_MemNotCached = (1 << 26), COFF_SectionFlag_MemNotPaged = (1 << 27), COFF_SectionFlag_MemShared = (1 << 28), COFF_SectionFlag_MemExecute = (1 << 29), COFF_SectionFlag_MemRead = (1 << 30), COFF_SectionFlag_MemWrite = (1 << 31) }; #define COFF_SectionFlags_ExtractAlign(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_AlignShift) & COFF_SectionFlag_AlignMask) #define COFF_SectionFlags_LnkFlags ((COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift) | COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkOther | COFF_SectionFlag_LnkRemove | COFF_SectionFlag_LnkNRelocOvfl) typedef struct COFF_SectionHeader { U8 name[8]; U32 vsize; U32 voff; U32 fsize; U32 foff; U32 relocs_foff; U32 lines_foff; U16 reloc_count; U16 line_count; COFF_SectionFlags flags; } COFF_SectionHeader; //////////////////////////////// typedef U8 COFF_SymType; enum { COFF_SymType_Null, COFF_SymType_Void, COFF_SymType_Char, COFF_SymType_Short, COFF_SymType_Int, COFF_SymType_Long, COFF_SymType_Float, COFF_SymType_Double, COFF_SymType_Struct, COFF_SymType_Union, COFF_SymType_Enum, COFF_SymType_MemberOfEnumeration, COFF_SymType_Byte, COFF_SymType_Word, COFF_SymType_UInt, COFF_SymType_DWord }; typedef U8 COFF_SymStorageClass; enum { COFF_SymStorageClass_Null = 0x00, COFF_SymStorageClass_Automatic = 0x01, COFF_SymStorageClass_External = 0x02, COFF_SymStorageClass_Static = 0x03, COFF_SymStorageClass_Register = 0x04, COFF_SymStorageClass_ExternalDef = 0x05, COFF_SymStorageClass_Label = 0x06, COFF_SymStorageClass_UndefinedLabel = 0x07, COFF_SymStorageClass_MemberOfStruct = 0x08, COFF_SymStorageClass_Argument = 0x09, COFF_SymStorageClass_StructTag = 0x0a, COFF_SymStorageClass_MemberOfUnion = 0x0b, COFF_SymStorageClass_UnionTag = 0x0c, COFF_SymStorageClass_TypeDefinition = 0x0d, COFF_SymStorageClass_UndefinedStatic = 0x0e, COFF_SymStorageClass_EnumTag = 0x0f, COFF_SymStorageClass_MemberOfEnum = 0x10, COFF_SymStorageClass_RegisterParam = 0x11, COFF_SymStorageClass_BitField = 0x12, COFF_SymStorageClass_Block = 0x64, COFF_SymStorageClass_Function = 0x65, COFF_SymStorageClass_EndOfStruct = 0x66, COFF_SymStorageClass_File = 0x67, COFF_SymStorageClass_Section = 0x68, COFF_SymStorageClass_WeakExternal = 0x69, COFF_SymStorageClass_CLRToken = 0x6b, COFF_SymStorageClass_EndOfFunction = 0xff }; typedef U8 COFF_SymDType; enum { COFF_SymDType_Null = 0x00, COFF_SymDType_Ptr = 0x10, COFF_SymDType_Func = 0x20, COFF_SymDType_Array = 0x30 }; // Special values for section number field in coff symbol #define COFF_Symbol_UndefinedSection 0 #define COFF_Symbol_AbsSection32 ((U32)-1) #define COFF_Symbol_DebugSection32 ((U32)-2) #define COFF_Symbol_AbsSection16 ((U16)-1) #define COFF_Symbol_DebugSection16 ((U16)-2) typedef union COFF_SymbolName { U8 short_name[8]; struct { // if this field is filled with zeroes we have a long name, // which means name is stored in the string table // and we need to use the offset to look it up... U32 zeroes; U32 string_table_offset; } long_name; } COFF_SymbolName; #define COFF_SymbolType_IsFunc(x) ((x).u.lsb == COFF_SymType_Null && (x).u.msb == COFF_SymDType_Func) typedef union COFF_SymbolType { struct { COFF_SymDType msb; COFF_SymType lsb; } u; U16 v; } COFF_SymbolType; typedef struct COFF_Symbol16 { COFF_SymbolName name; U32 value; U16 section_number; COFF_SymbolType type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; } COFF_Symbol16; typedef struct COFF_Symbol32 { COFF_SymbolName name; U32 value; U32 section_number; COFF_SymbolType type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; } COFF_Symbol32; typedef U32 COFF_WeakExtType; enum { COFF_WeakExt_Null = 0, COFF_WeakExt_NoLibrary = 1, COFF_WeakExt_SearchLibrary = 2, COFF_WeakExt_SearchAlias = 3, COFF_WeakExt_AntiDependency = 4, // search libraries only if the default symbol is weak, even if the weak symbol points to itself }; // storage class: External typedef struct COFF_SymbolFuncDef { U32 tag_index; U32 total_size; U32 ptr_to_ln; U32 ptr_to_next_func; U8 unused[2]; } COFF_SymbolFuncDef; // storage class: Function typedef struct COFF_SymbolFunc { U8 unused[4]; U16 ln; U8 unused2[2]; U32 ptr_to_next_func; U8 unused3[2]; } COFF_SymbolFunc; // storage class: WeakExternal typedef struct COFF_SymbolWeakExt { U32 tag_index; COFF_WeakExtType characteristics; U8 unused[10]; } COFF_SymbolWeakExt; typedef struct COFF_SymbolFile { U8 name[18]; } COFF_SymbolFile; typedef U8 COFF_ComdatSelectType; enum { COFF_ComdatSelect_Null = 0, COFF_ComdatSelect_NoDuplicates = 1, // Only one symbol is allowed to be in global symbol table, otherwise multiply defintion error is thrown. COFF_ComdatSelect_Any = 2, // Select any symbol, even if there are multiple definitions. (we default to first declaration) COFF_ComdatSelect_SameSize = 3, // Sections that symbols reference must match in size, otherwise multiply definition error is thrown. COFF_ComdatSelect_ExactMatch = 4, // Sections that symbols reference must have identical checksums, otherwise multiply defintion error is thrown. COFF_ComdatSelect_Associative = 5, // Symbols with associative type form a chain of sections are related to each other. (next link is indicated in COFF_SecDef in 'number') COFF_ComdatSelect_Largest = 6 // Linker selects section with largest size. }; // provides information about section to which symbol refers to. // storage class: Static typedef struct COFF_SymbolSecDef { U32 length; U16 number_of_relocations; U16 number_of_ln; U32 check_sum; U16 number_lo; // low 16 bits of one-based section index COFF_ComdatSelectType selection; U8 unused; U16 number_hi; } COFF_SymbolSecDef; //////////////////////////////// typedef U16 COFF_RelocType; typedef COFF_RelocType COFF_Reloc_X64; enum { COFF_Reloc_X64_Abs = 0x0, COFF_Reloc_X64_Addr64 = 0x1, COFF_Reloc_X64_Addr32 = 0x2, COFF_Reloc_X64_Addr32Nb = 0x3, // NB => No Base COFF_Reloc_X64_Rel32 = 0x4, COFF_Reloc_X64_Rel32_1 = 0x5, COFF_Reloc_X64_Rel32_2 = 0x6, COFF_Reloc_X64_Rel32_3 = 0x7, COFF_Reloc_X64_Rel32_4 = 0x8, COFF_Reloc_X64_Rel32_5 = 0x9, COFF_Reloc_X64_Section = 0xA, COFF_Reloc_X64_SecRel = 0xB, COFF_Reloc_X64_SecRel7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token COFF_Reloc_X64_Token = 0xD, COFF_Reloc_X64_SRel32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR COFF_Reloc_X64_Pair = 0xF, COFF_Reloc_X64_SSpan32 = 0x10, COFF_Reloc_X64_Unknown_11 = 0x11, COFF_Reloc_X64_Last = COFF_Reloc_X64_Unknown_11, }; typedef COFF_RelocType COFF_Reloc_X86; enum { COFF_Reloc_X86_Abs = 0x0, // relocation is ignored COFF_Reloc_X86_Dir16 = 0x1, // no support COFF_Reloc_X86_Rel16 = 0x2, // no support COFF_Reloc_X86_Unknown0 = 0x3, COFF_Reloc_X86_Unknown2 = 0x4, COFF_Reloc_X86_Unknown3 = 0x5, COFF_Reloc_X86_Dir32 = 0x6, // 32-bit virtual address COFF_Reloc_X86_Dir32Nb = 0x7, // 32-bit virtual offset COFF_Reloc_X86_Seg12 = 0x9, // no support COFF_Reloc_X86_Section = 0xa, // 16-bit section index, used for debug info purposes COFF_Reloc_X86_SecRel = 0xb, // 32-bit offset from start of a section COFF_Reloc_X86_Token = 0xc, // CLR token? (for managed languages) COFF_Reloc_X86_SecRel7 = 0xd, // 7-bit offset from the base of the section that contains the target. COFF_Reloc_X86_Unknown4 = 0xe, COFF_Reloc_X86_Unknown5 = 0xf, COFF_Reloc_X86_Unknown6 = 0x10, COFF_Reloc_X86_Unknown7 = 0x11, COFF_Reloc_X86_Unknown8 = 0x12, COFF_Reloc_X86_Unknown9 = 0x13, COFF_Reloc_X86_Rel32 = 0x14 }; typedef COFF_RelocType COFF_Reloc_Arm; enum { COFF_Reloc_Arm_Abs = 0x0, COFF_Reloc_Arm_Addr32 = 0x1, COFF_Reloc_Arm_Addr32Nb = 0x2, COFF_Reloc_Arm_Branch24 = 0x3, COFF_Reloc_Arm_Branch11 = 0x4, COFF_Reloc_Arm_Unknown1 = 0x5, COFF_Reloc_Arm_Unknown2 = 0x6, COFF_Reloc_Arm_Unknown3 = 0x7, COFF_Reloc_Arm_Unknown4 = 0x8, COFF_Reloc_Arm_Unknown5 = 0x9, COFF_Reloc_Arm_Rel32 = 0xa, COFF_Reloc_Arm_Section = 0xe, COFF_Reloc_Arm_SecRel = 0xf, COFF_Reloc_Arm_Mov32 = 0x10, COFF_Reloc_Arm_ThumbMov32 = 0x11, COFF_Reloc_Arm_ThumbBranch20 = 0x12, COFF_Reloc_Arm_Unused = 0x13, COFF_Reloc_Arm_ThumbBranch24 = 0x14, COFF_Reloc_Arm_ThumbBlx23 = 0x15, COFF_Reloc_Arm_Pair = 0x16 }; typedef COFF_RelocType COFF_Reloc_Arm64; enum { COFF_Reloc_Arm64_Abs = 0x0, COFF_Reloc_Arm64_Addr32 = 0x1, COFF_Reloc_Arm64_Addr32Nb = 0x2, COFF_Reloc_Arm64_Branch26 = 0x3, COFF_Reloc_Arm64_PageBaseRel21 = 0x4, COFF_Reloc_Arm64_Rel21 = 0x5, COFF_Reloc_Arm64_PageOffset12a = 0x6, COFF_Reloc_Arm64_SecRel = 0x8, COFF_Reloc_Arm64_SecRelLow12a = 0x9, COFF_Reloc_Arm64_SecRelHigh12a = 0xa, COFF_Reloc_Arm64_SecRelLow12l = 0xb, COFF_Reloc_Arm64_Token = 0xc, COFF_Reloc_Arm64_Section = 0xd, COFF_Reloc_Arm64_Addr64 = 0xe, COFF_Reloc_Arm64_Branch19 = 0xf, COFF_Reloc_Arm64_Branch14 = 0x10, COFF_Reloc_Arm64_Rel32 = 0x11 }; typedef struct COFF_Reloc { U32 apply_off; // section relative offset where relocation is placed U32 isymbol; // zero based index into coff symbol table COFF_RelocType type; // relocation type that depends on the arch } COFF_Reloc; //////////////////////////////// #define COFF_ResourceAlign 4u typedef struct COFF_ResourceHeaderPrefix { U32 data_size; U32 header_size; } COFF_ResourceHeaderPrefix; typedef U16 COFF_ResourceMemoryFlags; enum { COFF_ResourceMemoryFlag_Moveable = 0x10, COFF_ResourceMemoryFlag_Pure = 0x20, COFF_ResourceMemoryFlag_PreLoad = 0x40, COFF_ResourceMemoryFlag_Discardable = 0x1000 }; typedef struct COFF_ResourceDataEntry { U32 data_voff; U32 data_size; U32 code_page; U32 reserved; } COFF_ResourceDataEntry; typedef struct COFF_ResourceDirTable { U32 characteristics; COFF_TimeStamp time_stamp; U16 major_version; U16 minor_version; U16 name_entry_count; U16 id_entry_count; } COFF_ResourceDirTable; #define COFF_Resource_SubDirFlag (1u << 31u) typedef struct COFF_ResourceDirEntry { union { U32 offset; U32 id; } name; union { U32 data_entry_offset; U32 sub_dir_offset; } id; } COFF_ResourceDirEntry; //////////////////////////////// #define COFF_Archive_MemberAlign 2 #define COFF_Archive_MaxShortNameSize 15 typedef struct COFF_ArchiveMemberHeader { U8 name[16]; U8 date[12]; U8 user_id[6]; U8 group_id[6]; U8 mode[8]; U8 size[10]; U8 end[2]; } COFF_ArchiveMemberHeader; #define COFF_ImportType_Invalid max_U16 typedef U16 COFF_ImportType; enum { COFF_ImportHeader_Code = 0, COFF_ImportHeader_Data = 1, COFF_ImportHeader_Const = 2 }; typedef U32 COFF_ImportByType; enum { COFF_ImportBy_Ordinal = 0, COFF_ImportBy_Name = 1, COFF_ImportBy_NameNoPrefix = 2, COFF_ImportBy_Undecorate = 3 }; typedef U16 COFF_ImportHeaderFlags; enum { COFF_ImportHeader_TypeShift = 0, COFF_ImportHeader_TypeMask = 3, COFF_ImportHeader_ImportByShift = 2, COFF_ImportHeader_ImportByMask = 3, }; #define COFF_ImportHeader_ExtractType(x) (((x) >> COFF_ImportHeader_TypeShift ) & COFF_ImportHeader_TypeMask ) #define COFF_ImportHeader_ExtractImportBy(x) (((x) >> COFF_ImportHeader_ImportByShift) & COFF_ImportHeader_ImportByMask) typedef struct COFF_ImportHeader { U16 sig1; // COFF_MachineType_Unknown U16 sig2; // max_U16 U16 version; // 0 COFF_MachineType machine; COFF_TimeStamp time_stamp; U32 data_size; U16 hint_or_ordinal; COFF_ImportHeaderFlags flags; // char *func_name; // char *dll_name; } COFF_ImportHeader; #pragma pack(pop) typedef struct COFF_RelocValue { U64 size; S64 value; } COFF_RelocValue; //////////////////////////////// // Section internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags); internal COFF_SectionFlags coff_section_flag_from_align_size (U64 align); internal String8 coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header); internal void coff_parse_section_name (String8 full_name, String8 *name_out, String8 *postfix_out); //////////////////////////////// // Symbol internal String8 coff_read_symbol_name(String8 string_table, COFF_SymbolName *name); //////////////////////////////// // Reloc internal U64 coff_is_addr_reloc(COFF_MachineType machine, U32 type); internal U64 coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x); internal U64 coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x); internal COFF_RelocValue coff_pick_reloc_value_x64(COFF_Reloc_X64 type, U64 image_base, U64 reloc_virtual_offset, U32 symbol_section_number, U32 symbol_section_offset, S64 symbol_virtual_offset); //////////////////////////////// // Import internal U32 coff_make_ordinal32(U16 hint); internal U64 coff_make_ordinal64(U16 hint); internal String8 coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint); internal String8 coff_make_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size); internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name); internal String8 coff_make_import_header(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType type); //////////////////////////////// // Misc internal U16 coff_default_align_from_machine (COFF_MachineType machine); internal U8 coff_code_align_byte_from_machine (COFF_MachineType machine); internal U64 coff_word_size_from_machine (COFF_MachineType machine); internal U64 coff_default_exe_base_from_machine(COFF_MachineType machine); internal U64 coff_default_dll_base_from_machine(COFF_MachineType machine); internal Arch arch_from_coff_machine(COFF_MachineType machine); internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff); //////////////////////////////// //~ rjf: Enum <=> String internal String8 coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp); internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType type); internal String8 coff_string_from_machine_type(COFF_MachineType machine); internal String8 coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags); internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags); internal String8 coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags); internal String8 coff_string_from_import_header_type(COFF_ImportType type); internal String8 coff_string_from_sym_dtype(COFF_SymDType x); internal String8 coff_string_from_sym_type(COFF_SymType x); internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x); internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x); internal String8 coff_string_from_reloc_x86(COFF_Reloc_X86 x); internal String8 coff_string_from_reloc_x64(COFF_Reloc_X64 x); internal String8 coff_string_from_reloc_arm(COFF_Reloc_Arm x); internal String8 coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x); internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x); internal COFF_MachineType coff_machine_from_string(String8 string); internal COFF_ImportType coff_import_header_type_from_string(String8 name); #endif // COFF_H ================================================ FILE: src/coff/coff_dump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #if 0 internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header.time_stamp); rd_printf("Name : %S" , header.name ); rd_printf("Time Stamp: (%#x) %S" , header.time_stamp, time_stamp ); rd_printf("User ID : %u" , header.user_id ); rd_printf("Group ID : %u" , header.group_id); rd_printf("Mode : %S" , header.mode ); rd_printf("Data : [%#llx-%#llx)", header.data_range.min, header.data_range.max); scratch_end(scratch); } internal void coff_print_section_table(Arena *arena, String8List *out, String8 indent, String8 string_table, COFF_Symbol32Array symbol_table, U64 section_count, COFF_SectionHeader *section_table) { Temp scratch = scratch_begin(&arena, 1); String8 *symlinks = push_array(scratch.arena, String8, section_count); for (U64 i = 0; i < symbol_table.count; ++i) { COFF_Symbol32 *symbol = symbol_table.v+i; COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); if (interp == COFF_SymbolValueInterp_Regular && symbol->aux_symbol_count == 0 && (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static)) { if (symbol->section_number > 0 && symbol->section_number <= symbol_table.count) { COFF_SectionHeader *header = section_table+(symbol->section_number-1); if (header->flags & COFF_SectionFlag_LnkCOMDAT) { symlinks[symbol->section_number-1] = coff_read_symbol_name(string_table, &symbol->name); } } } i += symbol->aux_symbol_count; } if (section_count) { rd_printf("# Section Table"); rd_indent(); rd_printf("%-4s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-5s %-10s %s", "No.", "Name", "VirtSize", "VirtOff", "FileSize", "FileOff", "RelocOff", "LinesOff", "RelocCnt", "LineCnt", "Align", "Flags", "Symlink"); for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = section_table+i; String8 name = str8_cstring_capped(header->name, header->name+sizeof(header->name)); String8 full_name = coff_name_from_section_header(string_table, header); String8 align; { U64 align_size = coff_align_size_from_section_flags(header->flags); align = push_str8f(scratch.arena, "%u", align_size); } String8 flags; { String8List mem_flags = {0}; if (header->flags & COFF_SectionFlag_MemRead) { str8_list_pushf(scratch.arena, &mem_flags, "r"); } if (header->flags & COFF_SectionFlag_MemWrite) { str8_list_pushf(scratch.arena, &mem_flags, "w"); } if (header->flags & COFF_SectionFlag_MemExecute) { str8_list_pushf(scratch.arena, &mem_flags, "x"); } String8List cnt_flags = {0}; if (header->flags & COFF_SectionFlag_CntCode) { str8_list_pushf(scratch.arena, &cnt_flags, "c"); } if (header->flags & COFF_SectionFlag_CntInitializedData) { str8_list_pushf(scratch.arena, &cnt_flags, "d"); } if (header->flags & COFF_SectionFlag_CntUninitializedData) { str8_list_pushf(scratch.arena, &cnt_flags, "u"); } String8List mem_extra_flags = {0}; if (header->flags & COFF_SectionFlag_MemShared) { str8_list_pushf(scratch.arena, &mem_flags, "s"); } if (header->flags & COFF_SectionFlag_Mem16Bit) { str8_list_pushf(scratch.arena, &mem_extra_flags, "h"); } if (header->flags & COFF_SectionFlag_MemLocked) { str8_list_pushf(scratch.arena, &mem_extra_flags, "l"); } if (header->flags & COFF_SectionFlag_MemDiscardable) { str8_list_pushf(scratch.arena, &mem_extra_flags, "d"); } if (header->flags & COFF_SectionFlag_MemNotCached) { str8_list_pushf(scratch.arena, &mem_extra_flags, "c"); } if (header->flags & COFF_SectionFlag_MemNotPaged) { str8_list_pushf(scratch.arena, &mem_extra_flags, "p"); } String8List lnk_flags = {0}; if (header->flags & COFF_SectionFlag_LnkRemove) { str8_list_pushf(scratch.arena, &lnk_flags, "r"); } if (header->flags & COFF_SectionFlag_LnkCOMDAT) { str8_list_pushf(scratch.arena, &lnk_flags, "c"); } if (header->flags & COFF_SectionFlag_LnkOther) { str8_list_pushf(scratch.arena, &lnk_flags, "o"); } if (header->flags & COFF_SectionFlag_LnkInfo) { str8_list_pushf(scratch.arena, &lnk_flags, "i"); } if (header->flags & COFF_SectionFlag_LnkNRelocOvfl) { str8_list_pushf(scratch.arena, &lnk_flags, "f"); } String8List other_flags = {0}; if (header->flags & COFF_SectionFlag_TypeNoPad) { str8_list_pushf(scratch.arena, &other_flags, "n"); } if (header->flags & COFF_SectionFlag_GpRel) { str8_list_pushf(scratch.arena, &other_flags, "g"); } String8 mem = str8_list_join(scratch.arena, &mem_flags, 0); String8 cnt = str8_list_join(scratch.arena, &cnt_flags, 0); String8 lnk = str8_list_join(scratch.arena, &lnk_flags, 0); String8 ext = str8_list_join(scratch.arena, &mem_extra_flags, 0); String8 oth = str8_list_join(scratch.arena, &other_flags, 0); String8List f = {0}; str8_list_push(scratch.arena, &f, mem); str8_list_push(scratch.arena, &f, cnt); str8_list_push(scratch.arena, &f, ext); str8_list_push(scratch.arena, &f, lnk); str8_list_push(scratch.arena, &f, oth); flags = str8_list_join(scratch.arena, &f, &(StringJoin){ .sep = str8_lit("-") }); if (!flags.size) { flags = str8_lit("none"); } } String8List l = {0}; str8_list_pushf(scratch.arena, &l, "%-4x", i+1 ); str8_list_pushf(scratch.arena, &l, "%-8S", name ); str8_list_pushf(scratch.arena, &l, "%08x", header->vsize ); str8_list_pushf(scratch.arena, &l, "%08x", header->voff ); str8_list_pushf(scratch.arena, &l, "%08x", header->fsize ); str8_list_pushf(scratch.arena, &l, "%08x", header->foff ); str8_list_pushf(scratch.arena, &l, "%08x", header->relocs_foff); str8_list_pushf(scratch.arena, &l, "%08x", header->lines_foff ); str8_list_pushf(scratch.arena, &l, "%08x", header->reloc_count); str8_list_pushf(scratch.arena, &l, "%08x", header->line_count ); str8_list_pushf(scratch.arena, &l, "%-5S", align ); str8_list_pushf(scratch.arena, &l, "%-10S", flags ); if (symlinks[i].size > 0) { str8_list_pushf(scratch.arena, &l, "%S", symlinks[i]); } else { str8_list_pushf(scratch.arena, &l, "[no symlink]"); } String8 line = str8_list_join(scratch.arena, &l, &(StringJoin){ .sep = str8_lit(" "), }); rd_printf("%S", line); if (full_name.size != name.size) { rd_indent(); rd_printf("Full Name: %S", full_name); rd_unindent(); } } rd_newline(); rd_printf("Flags:"); rd_indent(); rd_printf("r = MemRead w = MemWrite x = MemExecute"); rd_printf("c = CntCode d = InitializedData u = UninitializedData"); rd_printf("s = MemShared h = Mem16bit l = MemLocked d = MemDiscardable c = MemNotCached p = MemNotPaged"); rd_printf("r = LnkRemove c = LnkComdat o = LnkOther i = LnkInfo f = LnkNRelocOvfl"); rd_printf("g = GpRel n = TypeNoPad"); rd_unindent(); rd_unindent(); rd_newline(); } scratch_end(scratch); } internal void coff_disasm_sections(Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections) { if (section_count) { for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { COFF_SectionHeader *sect = sections+sect_idx; if (sect->flags & COFF_SectionFlag_CntCode) { U64 sect_off = is_obj ? sect->foff : sect->voff; U64 sect_size = is_obj ? sect->fsize : sect->vsize; String8 raw_code = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); U64 sect_number = sect_idx+1; RD_MarkerArray markers = section_markers[sect_number]; rd_printf("# Disassembly [Section No. %#llx]", sect_number); rd_indent(); rd_print_disasm(arena, out, indent, arch_from_coff_machine(machine), image_base, sect_off, markers.count, markers.v, raw_code); rd_unindent(); } } } } internal void coff_raw_data_sections(Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *section_table) { if (section_count) { for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { COFF_SectionHeader *sect = section_table+sect_idx; if (sect->fsize > 0) { U64 sect_size = is_obj ? sect->fsize : sect->vsize; String8 raw_sect = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); RD_MarkerArray markers = section_markers[sect_idx]; rd_printf("# Raw Data [Section No. %#llx]", (sect_idx+1)); rd_indent(); rd_print_raw_data(arena, out, indent, 32, markers.count, markers.v, raw_sect); rd_unindent(); rd_newline(); } } } } internal void coff_print_relocs(Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 string_table, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols) { Temp scratch = scratch_begin(&arena, 1); B32 print_header = 1; for (U64 sect_idx = 0; sect_idx < sect_count; ++sect_idx) { COFF_SectionHeader *sect_header = sect_headers+sect_idx; COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(raw_data, sect_header); if (reloc_info.count) { if (print_header) { print_header = 0; rd_printf("# Relocations"); rd_indent(); } rd_printf("## Section %llx", sect_idx); rd_indent(); rd_printf("%-4s %-8s %-16s %-16s %-8s %-7s", "No.", "Offset", "Type", "ApplyTo", "SymIdx", "SymName"); for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; ++reloc_idx) { COFF_Reloc *reloc = (COFF_Reloc*)(raw_data.str + reloc_info.array_off) + reloc_idx; String8 type = coff_string_from_reloc(machine, reloc->type); U64 apply_size = coff_apply_size_from_reloc(machine, reloc->type); U64 apply_foff = sect_header->foff + reloc->apply_off; if (apply_foff + apply_size > raw_data.size) { rd_errorf("out of bounds apply file offset %#llx in relocation %#llx", apply_foff, reloc_idx); break; } U64 raw_apply; AssertAlways(apply_size <= sizeof(raw_apply)); MemoryCopy(&raw_apply, raw_data.str + apply_foff, apply_size); S64 apply = extend_sign64(raw_apply, apply_size); if (reloc->isymbol > symbols.count) { rd_errorf("out of bounds symbol index %u in relocation %#llx", reloc->isymbol, reloc_idx); break; } COFF_Symbol32 *symbol = symbols.v+reloc->isymbol; String8 symbol_name = coff_read_symbol_name(string_table, &symbol->name); String8List line = {0}; str8_list_pushf(scratch.arena, &line, "%-4x", reloc_idx ); str8_list_pushf(scratch.arena, &line, "%08x", reloc->apply_off); str8_list_pushf(scratch.arena, &line, "%-16S", type ); str8_list_pushf(scratch.arena, &line, "%016x", apply ); str8_list_pushf(scratch.arena, &line, "%S", symbol_name ); String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", l); } rd_unindent(); } } if (!print_header) { rd_unindent(); } rd_newline(); scratch_end(scratch); } internal void coff_print_symbol_table(Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, String8 string_table, COFF_Symbol32Array symbols) { Temp scratch = scratch_begin(&arena, 1); if (symbols.count) { rd_printf("# Symbol Table"); rd_indent(); rd_printf("%-4s %-8s %-10s %-4s %-4s %-4s %-16s %-20s", "No.", "Value", "SectNum", "Aux", "Msb", "Lsb", "Storage", "Name"); for (U64 i = 0; i < symbols.count; ++i) { COFF_Symbol32 *symbol = &symbols.v[i]; String8 name = coff_read_symbol_name(string_table, &symbol->name); String8 msb = coff_string_from_sym_dtype(symbol->type.u.msb); String8 lsb = coff_string_from_sym_type(symbol->type.u.lsb); String8 storage_class = coff_string_from_sym_storage_class(symbol->storage_class); String8 section_number; switch (symbol->section_number) { case COFF_Symbol_UndefinedSection: section_number = str8_lit("Undef"); break; case COFF_Symbol_AbsSection32: section_number = str8_lit("Abs"); break; case COFF_Symbol_DebugSection32: section_number = str8_lit("Debug"); break; default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break; } String8List line = {0}; str8_list_pushf(scratch.arena, &line, "%-4x", i ); str8_list_pushf(scratch.arena, &line, "%08x", symbol->value ); str8_list_pushf(scratch.arena, &line, "%-10S", section_number ); str8_list_pushf(scratch.arena, &line, "%-4u", symbol->aux_symbol_count); str8_list_pushf(scratch.arena, &line, "%-4S", msb ); str8_list_pushf(scratch.arena, &line, "%-4S", lsb ); str8_list_pushf(scratch.arena, &line, "%-16S", storage_class ); str8_list_pushf(scratch.arena, &line, "%S", name ); String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep = str8_lit(" ")}); rd_printf("%S", l); rd_indent(); for (U64 k=i+1, c = i+symbol->aux_symbol_count; k <= c; ++k) { void *raw_aux = &symbols.v[k]; switch (symbol->storage_class) { case COFF_SymStorageClass_External: { COFF_SymbolFuncDef *func_def = (COFF_SymbolFuncDef*)&symbols.v[k]; rd_printf("Tag Index %#x, Total Size %#x, Line Numbers %#x, Next Function %#x", func_def->tag_index, func_def->total_size, func_def->ptr_to_ln, func_def->ptr_to_next_func); } break; case COFF_SymStorageClass_Function: { COFF_SymbolFunc *func = raw_aux; rd_printf("Ordinal Line Number %#x, Next Function %#x", func->ln, func->ptr_to_next_func); } break; case COFF_SymStorageClass_WeakExternal: { COFF_SymbolWeakExt *weak = raw_aux; String8 type = coff_string_from_weak_ext_type(weak->characteristics); rd_printf("Tag Index %#x, Characteristics %S", weak->tag_index, type); } break; case COFF_SymStorageClass_File: { COFF_SymbolFile *file = raw_aux; String8 name = str8_cstring_capped(file->name, file->name+sizeof(file->name)); rd_printf("Name %S", name); } break; case COFF_SymStorageClass_Static: { COFF_SymbolSecDef *sd = raw_aux; String8 selection = coff_string_from_comdat_select_type(sd->selection); U32 number = sd->number_lo; if (is_big_obj) { number |= (U32)sd->number_hi << 16; } if (number) { rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x, Section %x, Selection %S", sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum, number, selection); } else { rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x", sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum); } } break; default: { rd_printf("???"); } break; } } i += symbol->aux_symbol_count; rd_unindent(); } rd_unindent(); rd_newline(); } scratch_end(scratch); } internal void coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); String8 machine = coff_string_from_machine_type(header->machine); rd_printf("# Big Obj"); rd_indent(); rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp); rd_printf("Machine : %#x (%S)", header->machine, machine ); rd_printf("Section Count: %u", header->section_count ); rd_printf("Symbol Table : %#x", header->symbol_table_foff); rd_printf("Symbol Count : %u", header->symbol_count ); rd_unindent(); scratch_end(scratch); } internal void coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); String8 machine = coff_string_from_machine_type(header->machine); String8 flags = coff_string_from_flags(scratch.arena, header->flags); rd_printf("# COFF File Header"); rd_indent(); rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp ); rd_printf("Machine : %#x %S", header->machine, machine ); rd_printf("Section Count : %u", header->section_count ); rd_printf("Symbol Table : %#x", header->symbol_table_foff ); rd_printf("Symbol Count : %u", header->symbol_count ); rd_printf("Optional Header Size: %#x (%m)", header->optional_header_size, header->optional_header_size); rd_printf("Flags : %#x (%S)", header->flags, flags ); rd_unindent(); scratch_end(scratch); } internal void coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header) { Temp scratch = scratch_begin(&arena, 1); String8 machine = coff_string_from_machine_type(header->machine); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp); rd_printf("# Import"); rd_indent(); rd_printf("Version : %u", header->version ); rd_printf("Machine : %S", machine ); rd_printf("Time Stamp: %#x (%S)", header->time_stamp, time_stamp ); rd_printf("Data Size : %#x (%m)", header->data_size, header->data_size); rd_printf("Hint : %u", header->hint_or_ordinal); rd_printf("Type : %u", header->type ); rd_printf("Import By : %u", header->import_by ); rd_printf("Function : %S", header->func_name ); rd_printf("DLL : %S", header->dll_name ); rd_unindent(); scratch_end(scratch); } internal void coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) { Temp scratch = scratch_begin(&arena, 1); COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); String8 raw_header = str8_substr(raw_data, header_info.header_range); String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); COFF_BigObjHeader *big_obj = (COFF_BigObjHeader *)raw_header.str; COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_32(scratch.arena, raw_data, header_info.symbol_table_range.min, big_obj->symbol_count); if (opts & RD_Option_Headers) { coff_print_big_obj_header(arena, out, indent, big_obj); rd_newline(); } if (opts & RD_Option_Sections) { Rng1U64 sect_headers_range = rng_1u64(sizeof(*big_obj), sizeof(*big_obj) + sizeof(COFF_SectionHeader)*big_obj->section_count); Rng1U64 symbols_range = rng_1u64(big_obj->symbol_table_foff, big_obj->symbol_table_foff + sizeof(COFF_Symbol32)*big_obj->symbol_count); if (sect_headers_range.max > raw_data.size) { rd_errorf("not enough bytes to read big obj section headers"); goto exit; } if (big_obj->symbol_count) { if (symbols_range.max > raw_data.size) { rd_errorf("not enough bytes to read big obj symbol table"); goto exit; } if (contains_1u64(symbols_range, sect_headers_range.min) || contains_1u64(symbols_range, sect_headers_range.max)) { rd_errorf("section headers and symbol table ranges overlap"); goto exit; } } coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, big_obj->section_count, section_table); rd_newline(); } if (opts & RD_Option_Relocs) { coff_print_relocs(arena, out, indent, raw_data, raw_string_table, big_obj->machine, big_obj->section_count, section_table, symbol_table); rd_newline(); } if (opts & RD_Option_Symbols) { coff_print_symbol_table(arena, out, indent, raw_data, 1, raw_string_table, symbol_table); rd_newline(); } exit:; scratch_end(scratch); } internal void coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts) { Temp scratch = scratch_begin(&arena, 1); COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data); String8 raw_header = str8_substr(raw_data, header_info.header_range); String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range); String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range); COFF_FileHeader *header = (COFF_FileHeader *)raw_header.str; COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_16(scratch.arena, raw_data, header_info.symbol_table_range.min, header->symbol_count); Arch arch = arch_from_coff_machine(header->machine); if (opts & RD_Option_Headers) { coff_print_file_header(arena, out, indent, header); rd_newline(); } if (opts & RD_Option_Sections) { Rng1U64 sect_headers_range = rng_1u64(sizeof(*header), sizeof(*header) + sizeof(COFF_SectionHeader)*header->section_count); Rng1U64 symbols_range = rng_1u64(header->symbol_table_foff, header->symbol_table_foff + sizeof(COFF_Symbol16)*header->symbol_count); if (sect_headers_range.max > raw_data.size) { rd_errorf("not enough bytes to read obj section headers"); goto exit; } if (header->symbol_count) { if (symbols_range.max > raw_data.size) { rd_errorf("not enough bytes to read obj symbol table"); goto exit; } if (contains_1u64(symbols_range, sect_headers_range.min) || contains_1u64(symbols_range, sect_headers_range.max)) { rd_errorf("section headers and symbol table ranges overlap"); goto exit; } } coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, header->section_count, section_table); rd_newline(); } if (opts & RD_Option_Relocs) { coff_print_relocs(arena, out, indent, raw_data, raw_string_table, header->machine, header->section_count, section_table, symbol_table); rd_newline(); } if (opts & RD_Option_Symbols) { coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbol_table); rd_newline(); } RD_MarkerArray *section_markers = 0; if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) { section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, header->section_count, symbol_table); } if (opts & RD_Option_Rawdata) { coff_raw_data_sections(arena, out, indent, raw_data, 1, section_markers, header->section_count, section_table); } if (opts & RD_Option_Disasm) { coff_disasm_sections(arena, out, indent, raw_data, header->machine, 0, 1, section_markers, header->section_count, section_table); rd_newline(); } if (opts & RD_Option_Codeview) { cv_format_debug_sections(arena, out, indent, raw_data, raw_string_table, header->section_count, section_table); } if (opts & RD_Option_Dwarf) { DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table); dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); } exit:; scratch_end(scratch); } internal void coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts) { Temp scratch = scratch_begin(&arena, 1); COFF_ArchiveParse archive_parse = coff_archive_parse_from_data(raw_archive); if (archive_parse.error.size) { rd_errorf("%S", archive_parse.error); return; } COFF_ArchiveFirstMember first_member = archive_parse.first_member; { rd_printf("# First Header"); rd_indent(); rd_printf("Symbol Count : %u", first_member.symbol_count); rd_printf("String Table Size: %#llx (%M)", first_member.string_table.size, first_member.string_table.size); rd_printf("Members:"); rd_indent(); String8List string_table = str8_split_by_string_chars(scratch.arena, first_member.string_table, str8_lit("\0"), 0); if (string_table.node_count == first_member.member_offset_count) { String8Node *string_n = string_table.first; for (U64 i = 0; i < string_table.node_count; ++i, string_n = string_n->next) { U32 offset = from_be_u32(first_member.member_offsets[i]); rd_printf("[%4u] %#08x %S", i, offset, string_n->string); } } else { rd_errorf("Member offset count (%llu) doesn't match string table count (%llu)", first_member.member_offset_count); } rd_unindent(); rd_unindent(); rd_newline(); } if (archive_parse.has_second_header) { COFF_ArchiveSecondMember second_member = archive_parse.second_member; rd_printf("# Second Header"); rd_indent(); rd_printf("Member Count : %u", second_member.member_count); rd_printf("Symbol Count : %u", second_member.symbol_count); rd_printf("String Table Size: %#llx (%M)", second_member.string_table.size, second_member.string_table.size); String8List string_table = str8_split_by_string_chars(scratch.arena, second_member.string_table, str8_lit("\0"), 0); rd_printf("Members:"); rd_indent(); if (second_member.symbol_index_count == second_member.symbol_count) { String8Node *string_n = string_table.first; for (U64 i = 0; i < second_member.symbol_count; ++i, string_n = string_n->next) { U16 symbol_number = second_member.symbol_indices[i]; if (symbol_number > 0 && symbol_number <= second_member.member_offset_count) { U16 symbol_idx = symbol_number - 1; U32 member_offset = second_member.member_offsets[i]; rd_printf("[%4u] %#08x %S", i, member_offset, string_n->string); } else { rd_errorf("[%4u] Out of bounds symbol number %u", i, symbol_number); break; } } } else { rd_errorf("Symbol index count %u doesn't match symbol count %u", second_member.symbol_index_count, second_member.symbol_count); } rd_unindent(); rd_unindent(); rd_newline(); } if (archive_parse.has_long_names && opts & RD_Option_LongNames) { rd_printf("# Long Names"); rd_indent(); String8List long_names = str8_split_by_string_chars(scratch.arena, archive_parse.long_names, str8_lit("\0"), 0); U64 name_idx = 0; for (String8Node *name_n = long_names.first; name_n != 0; name_n = name_n->next, ++name_idx) { U64 offset = (U64)(name_n->string.str - archive_parse.long_names.str); rd_printf("[%-4u] %#08x %S", name_idx, offset, name_n->string); } rd_unindent(); rd_newline(); } U64 member_offset_count = 0; U32 *member_offsets = 0; if (archive_parse.has_second_header) { member_offset_count = archive_parse.second_member.member_offset_count; member_offsets = archive_parse.second_member.member_offsets; } else { HashTable *ht = hash_table_init(scratch.arena, 0x1000); for (U64 i = 0; i < archive_parse.first_member.member_offset_count; ++i) { U32 member_offset = from_be_u32(archive_parse.first_member.member_offsets[i]); if (!hash_table_search_u32(ht, member_offset)) { hash_table_push_u32_raw(scratch.arena, ht, member_offset, 0); } } member_offset_count = ht->count; member_offsets = keys_from_hash_table_u32(scratch.arena, ht); radsort(member_offsets, member_offset_count, u32_is_before); } rd_printf("# Members"); rd_indent(); for (U64 i = 0; i < member_offset_count; ++i) { U64 next_member_offset = i+1 < member_offset_count ? member_offsets[i+1] : raw_archive.size; U64 member_offset = member_offsets[i]; String8 raw_member = str8_substr(raw_archive, rng_1u64(member_offset, next_member_offset)); COFF_ArchiveMember member = coff_archive_member_from_data(raw_member); COFF_DataType member_type = coff_data_type_from_data(member.data); rd_printf("Member @ %#llx", member_offset); rd_indent(); if (opts & RD_Option_Headers) { coff_print_archive_member_header(arena, out, indent, member.header, archive_parse.long_names); rd_newline(); } switch (member_type) { case COFF_DataType_Obj: { coff_print_obj(arena, out, indent, member.data, opts); } break; case COFF_DataType_BigObj: { coff_print_big_obj(arena, out, indent, member.data, opts); } break; case COFF_DataType_Import: { if (opts & RD_Option_Headers) { COFF_ParsedArchiveImportHeader header = {0}; U64 parse_size = coff_parse_import(member.data, 0, &header); if (parse_size) { coff_print_import(arena, out, indent, &header); } else { rd_errorf("not enough bytes to parse import header"); } } } break; case COFF_DataType_Null: { rd_errorf("unknown member format", member_offset); } break; } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); } #endif ================================================ FILE: src/coff/coff_dump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_DUMP_H #define COFF_DUMP_H #if 0 internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names); internal void coff_print_section_table (Arena *arena, String8List *out, String8 indent, String8 string_table, COFF_Symbol32Array symbols, U64 sect_count, COFF_SectionHeader *sect_headers); internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); internal void coff_print_relocs (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 string_table, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols); internal void coff_print_symbol_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, String8 string_table, COFF_Symbol32Array symbols); internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header); internal void coff_print_file_header (Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header); internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header); internal void coff_print_big_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); internal void coff_print_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); internal void coff_print_archive (Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts); #endif #endif // COFF_DUMP_H ================================================ FILE: src/coff/coff_enum.c ================================================ ================================================ FILE: src/coff/coff_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "coff/coff.c" #include "coff/coff_parse.c" #include "coff/coff_dump.c" ================================================ FILE: src/coff/coff_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_INC_H #define COFF_INC_H #include "coff/coff.h" #include "coff/coff_parse.h" #include "coff/coff_dump.h" #endif // COFF_INC_H ================================================ FILE: src/coff/coff_lib_writer.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal COFF_LibWriterSymbolNode * coff_lib_writer_symbol_list_push(Arena *arena, COFF_LibWriterSymbolList *list, COFF_LibWriterSymbol symbol) { COFF_LibWriterSymbolNode *node = push_array_no_zero(arena, COFF_LibWriterSymbolNode, 1); node->next = 0; node->data = symbol; SLLQueuePush(list->first, list->last, node); list->count += 1; return node; } internal COFF_LibWriterMemberNode * coff_lib_writer_member_list_push(Arena *arena, COFF_LibWriterMemberList *list, COFF_LibWriterMember member) { COFF_LibWriterMemberNode *node = push_array_no_zero(arena, COFF_LibWriterMemberNode, 1); node->next = 0; node->data = member; SLLQueuePush(list->first, list->last, node); list->count += 1; return node; } internal COFF_LibWriterSymbol * coff_lib_writer_symbol_array_from_list(Arena *arena, COFF_LibWriterSymbolList list) { COFF_LibWriterSymbol *arr = push_array_no_zero(arena, COFF_LibWriterSymbol, list.count + 2); COFF_LibWriterSymbol *ptr = arr + 1; for (COFF_LibWriterSymbolNode *i = list.first; i != 0; i = i->next, ptr += 1) { *ptr = i->data; } MemoryZeroStruct(&arr[0]); MemoryZeroStruct(&arr[list.count+1]); return arr; } internal COFF_LibWriterMember * coff_lib_writer_member_array_from_list(Arena *arena, COFF_LibWriterMemberList list) { COFF_LibWriterMember *arr = push_array_no_zero(arena, COFF_LibWriterMember, list.count); COFF_LibWriterMember *ptr = arr; for (COFF_LibWriterMemberNode *i = list.first; i != 0; i = i->next, ptr += 1) { ptr->name = push_str8_copy(arena, i->data.name); ptr->data = push_str8_copy(arena, i->data.data); } return arr; } internal int coff_lib_writer_symbol_name_compar(const void *raw_a, const void *raw_b) { const COFF_LibWriterSymbol *sa = raw_a; const COFF_LibWriterSymbol *sb = raw_b; return str8_compar_case_sensitive(&sa->name, &sb->name); } internal int coff_lib_writer_symbol_is_before_name(void *raw_a, void *raw_b) { return coff_lib_writer_symbol_name_compar(raw_a, raw_b) < 0; } internal int coff_lib_writer_symbol_is_before_member_idx(void *raw_a, void *raw_b) { COFF_LibWriterSymbol *a = raw_a, *b = raw_b; return a->member_idx < b->member_idx; } internal void coff_lib_writer_symbol_array_sort_on_name(COFF_LibWriterSymbol *arr, U64 count) { Assert(count >= 2); radsort(arr + 1, count - 2, coff_lib_writer_symbol_is_before_name); } internal void coff_lib_writer_symbol_array_sort_on_member_idx(COFF_LibWriterSymbol *arr, U64 count) { Assert(count >= 2); radsort(arr + 1, count - 2, coff_lib_writer_symbol_is_before_member_idx); } internal COFF_LibWriter * coff_lib_writer_alloc(void) { Arena *arena = arena_alloc(); COFF_LibWriter *writer = push_array(arena, COFF_LibWriter, 1); writer->arena = arena; return writer; } internal void coff_lib_writer_release(COFF_LibWriter **writer_ptr) { arena_release((*writer_ptr)->arena); *writer_ptr = 0; } internal U64 coff_lib_writer_push_obj(COFF_LibWriter *writer, String8 obj_path, String8 obj_data) { U64 member_idx = writer->member_list.count; // push obj member COFF_LibWriterMember member = { .name = obj_path, .data = obj_data }; COFF_LibWriterMemberNode *member_node = coff_lib_writer_member_list_push(writer->arena, &writer->member_list, member); // push external symbols COFF_FileHeaderInfo obj_header = coff_file_header_info_from_data(obj_data); String8 string_table = str8_substr(obj_data, obj_header.string_table_range); String8 symbol_table = str8_substr(obj_data, obj_header.symbol_table_range); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj_header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = coff_parse_symbol(obj_header, string_table, symbol_table, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); if (interp == COFF_SymbolValueInterp_Regular || interp == COFF_SymbolValueInterp_Common || interp == COFF_SymbolValueInterp_Abs) { if (symbol.storage_class == COFF_SymStorageClass_External) { COFF_LibWriterSymbol lib_symbol = { .name = symbol.name, .member_idx = member_idx }; coff_lib_writer_symbol_list_push(writer->arena, &writer->symbol_list, lib_symbol); } } } return member_idx; } internal void coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType import_type) { U64 member_idx = lib_writer->member_list.count; String8 member_data = coff_make_import_header(lib_writer->arena, machine, time_stamp, dll_name, import_by, name, hint_or_ordinal, import_type); COFF_LibWriterMember member = { .name = dll_name, .data = member_data }; COFF_LibWriterMemberNode *member_node = coff_lib_writer_member_list_push(lib_writer->arena, &lib_writer->member_list, member); if (name.size) { switch (import_type) { case COFF_ImportHeader_Code: { COFF_LibWriterSymbol thunk_symbol = {0}; thunk_symbol.name = push_str8_copy(lib_writer->arena, name); thunk_symbol.member_idx = member_idx; coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, thunk_symbol); COFF_LibWriterSymbol imp_symbol = {0}; imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name); imp_symbol.member_idx = member_idx; coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol); } break; case COFF_ImportHeader_Data: { COFF_LibWriterSymbol imp_symbol = {0}; imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name); imp_symbol.member_idx = member_idx; coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol); } break; case COFF_ImportHeader_Const: { NotImplemented; } break; default: { InvalidPath; } break; } } } internal String8 coff_lib_writer_serialize(Arena *arena, COFF_LibWriter *lib_writer, COFF_TimeStamp time_stamp, U16 mode, B32 emit_second_member) { Temp scratch = scratch_begin(&arena, 1); // member lists -> arrays U64 member_count = lib_writer->member_list.count; COFF_LibWriterMember *member_array = coff_lib_writer_member_array_from_list(scratch.arena, lib_writer->member_list); // serialize members U64 *member_offsets = push_array_no_zero(scratch.arena, U64, member_count); String8List long_names_list = {0}; String8List member_data_list = {0}; { HashTable *name_ht = hash_table_init(scratch.arena, 1024); for EachIndex(member_idx, member_count) { COFF_LibWriterMember *member = &member_array[member_idx]; // make member name String8 name; U64 name_with_slash_size = member->name.size + 1; if (name_with_slash_size > COFF_Archive_MaxShortNameSize) { // have we seen this member name before? if (!hash_table_search_string_string(name_ht, member->name, &name)) { name = push_str8f(scratch.arena, "/%u", long_names_list.total_size); str8_list_pushf(scratch.arena, &long_names_list, "%S/\n", member->name); hash_table_push_string_string(scratch.arena, name_ht, member->name, name); } } else { name = push_str8f(scratch.arena, "%S/", member->name); } member_offsets[member_idx] = member_data_list.total_size; String8 member_data = member->data; String8 member_header = coff_make_lib_member_header(scratch.arena, name, time_stamp, 0, 0, mode, member_data.size); str8_list_push(scratch.arena, &member_data_list, member_header); str8_list_push(scratch.arena, &member_data_list, member_data); { U64 pad_size = AlignPadPow2(member_data_list.total_size, COFF_Archive_MemberAlign); U8 *pad = push_array(scratch.arena, U8, pad_size); str8_list_push(scratch.arena, &member_data_list, str8(pad, pad_size)); } } } // write long names member if (long_names_list.total_size) { String8 header = coff_make_lib_member_header(scratch.arena, str8_lit("//"), time_stamp, 0, 0, mode, long_names_list.total_size); String8 data = str8_list_join(scratch.arena, &long_names_list, 0); U64 member_offset = member_data_list.total_size + data.size + header.size; { U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign); U8 *pad = push_array(scratch.arena, U8, pad_size); str8_list_push_front(scratch.arena, &member_data_list, str8(pad, pad_size)); } str8_list_push_front(scratch.arena, &member_data_list, data); str8_list_push_front(scratch.arena, &member_data_list, header); } // compute size for symbol string table U32 name_buffer_size = 0; for (COFF_LibWriterSymbolNode *node = lib_writer->symbol_list.first; node != 0; node = node->next) { name_buffer_size += node->data.name.size; name_buffer_size += 1; // null } // compute members base offset U64 members_base_offset; { U64 sizeof_first_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * lib_writer->symbol_list.count + name_buffer_size; U64 sizeof_second_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * member_count + sizeof(U32) + sizeof(U16) * lib_writer->symbol_list.count + name_buffer_size; U64 sizeof_long_names = sizeof(COFF_ArchiveMemberHeader) + long_names_list.total_size; sizeof_first_header = AlignPow2(sizeof_first_header, COFF_Archive_MemberAlign); sizeof_second_header = AlignPow2(sizeof_second_header, COFF_Archive_MemberAlign); sizeof_long_names = AlignPow2(sizeof_long_names, COFF_Archive_MemberAlign); members_base_offset = sizeof(g_coff_archive_sig); members_base_offset += sizeof_first_header; if (emit_second_member) { members_base_offset += sizeof_second_header; } if (long_names_list.total_size) { members_base_offset += sizeof_long_names; } } // write second linker member if (emit_second_member) { U64 symbols_count; COFF_LibWriterSymbol *symbols; { U64 symbols_count_with_null = lib_writer->symbol_list.count + 2; COFF_LibWriterSymbol *symbols_with_null = coff_lib_writer_symbol_array_from_list(scratch.arena, lib_writer->symbol_list); coff_lib_writer_symbol_array_sort_on_name(symbols_with_null, symbols_count_with_null); symbols_count = symbols_count_with_null - 2; symbols = symbols_with_null + 1; } // write symbol name buffer U8 *name_buffer = push_array_no_zero(scratch.arena, U8, name_buffer_size); { U64 name_cursor = 0; for EachIndex(symbol_idx, symbols_count) { COFF_LibWriterSymbol *symbol = &symbols[symbol_idx]; MemoryCopy(name_buffer + name_cursor, symbol->name.str, symbol->name.size); name_buffer[name_cursor + symbol->name.size] = '\0'; name_cursor += symbol->name.size + 1; } } U32 member_count32 = safe_cast_u32(member_count); U32 symbol_count32 = safe_cast_u32(symbols_count); U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, member_count); U16 *member_idx16_arr = push_array_no_zero(scratch.arena, U16, symbols_count); // write member offset array for EachIndex(member_idx, member_count) { U64 member_offset = members_base_offset + member_offsets[member_idx]; U32 member_off32 = safe_cast_u32(member_offset); member_off32_arr[member_idx] = member_off32; } // write member offset indices for each symbol for EachIndex(symbol_idx, symbols_count) { // member offset indices are 1-based U64 member_idx = symbols[symbol_idx].member_idx + 1; U16 member_idx16 = safe_cast_u16(member_idx); member_idx16_arr[symbol_idx] = member_idx16; } // layout second member data String8List second_member_data_list = {0}; str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&member_count32)); str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_off32_arr, member_count)); str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&symbol_count32)); str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_idx16_arr, symbols_count)); str8_list_push(scratch.arena, &second_member_data_list, str8(name_buffer, name_buffer_size)); String8 member_data = str8_list_join(scratch.arena, &second_member_data_list, 0); String8 member_header = coff_make_lib_member_header(scratch.arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size); U64 member_offset = member_data_list.total_size + member_data.size + member_header.size; { U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign); U8 *pad = push_array(scratch.arena, U8, pad_size); str8_list_push_front(scratch.arena, &member_data_list, str8(pad, pad_size)); } str8_list_push_front(scratch.arena, &member_data_list, member_data); str8_list_push_front(scratch.arena, &member_data_list, member_header); } // write first linker member (obsolete, but kept for compatability reasons) { U64 symbols_count; COFF_LibWriterSymbol *symbols; { U64 symbols_count_with_null = lib_writer->symbol_list.count + 2; COFF_LibWriterSymbol *symbols_with_null = coff_lib_writer_symbol_array_from_list(scratch.arena, lib_writer->symbol_list); coff_lib_writer_symbol_array_sort_on_member_idx(symbols_with_null, symbols_count_with_null); symbols_count = symbols_count_with_null - 2; symbols = symbols_with_null + 1; } // write symbol name buffer U8 *name_buffer = push_array_no_zero(scratch.arena, U8, name_buffer_size); { U64 name_cursor = 0; for EachIndex(symbol_idx, symbols_count) { COFF_LibWriterSymbol *symbol = &symbols[symbol_idx]; MemoryCopy(name_buffer + name_cursor, symbol->name.str, symbol->name.size); name_buffer[name_cursor + symbol->name.size] = '\0'; name_cursor += symbol->name.size + 1; } } U32 symbol_count_be = from_be_u32(symbols_count); U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, symbols_count); for EachIndex(symbol_idx, symbols_count) { COFF_LibWriterSymbol *symbol = &symbols[symbol_idx]; // write big endian member offset U64 member_offset = members_base_offset + member_offsets[symbol->member_idx]; U32 member_off32 = from_be_u32(safe_cast_u32(member_offset)); member_off32_arr[symbol_idx] = member_off32; } // layout first member data String8List first_member_data_list = {0}; str8_list_push(scratch.arena, &first_member_data_list, str8_struct(&symbol_count_be)); str8_list_push(scratch.arena, &first_member_data_list, str8_array(member_off32_arr, symbols_count)); str8_list_push(scratch.arena, &first_member_data_list, str8(name_buffer, name_buffer_size)); String8 member_data = str8_list_join(scratch.arena, &first_member_data_list, 0); String8 member_header = coff_make_lib_member_header(scratch.arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size); U64 member_offset = sizeof(g_coff_archive_sig) + member_header.size + member_data.size; { U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign); U8 *pad = push_array(scratch.arena, U8, pad_size); str8_list_push_front(scratch.arena, &member_data_list, str8(pad, pad_size)); } str8_list_push_front(scratch.arena, &member_data_list, member_data); str8_list_push_front(scratch.arena, &member_data_list, member_header); } // archive signature str8_list_push_front(scratch.arena, &member_data_list, str8_struct(&g_coff_archive_sig)); String8 raw_lib = str8_list_join(arena, &member_data_list, 0); scratch_end(scratch); return raw_lib; } ================================================ FILE: src/coff/coff_lib_writer.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_LIB_WRITER_H #define COFF_LIB_WRITER_H typedef struct COFF_LibWriterMember { String8 name; String8 data; } COFF_LibWriterMember; typedef struct COFF_LibWriterMemberNode { COFF_LibWriterMember data; struct COFF_LibWriterMemberNode *next; } COFF_LibWriterMemberNode; typedef struct COFF_LibWriterMemberList { U64 count; COFF_LibWriterMemberNode *first; COFF_LibWriterMemberNode *last; } COFF_LibWriterMemberList; typedef struct COFF_LibWriterSymbol { String8 name; U64 member_idx; } COFF_LibWriterSymbol; typedef struct COFF_LibWriterSymbolNode { COFF_LibWriterSymbol data; struct COFF_LibWriterSymbolNode *next; } COFF_LibWriterSymbolNode; typedef struct COFF_LibWriterSymbolList { U64 count; COFF_LibWriterSymbolNode *first; COFF_LibWriterSymbolNode *last; } COFF_LibWriterSymbolList; typedef struct COFF_LibWriter { Arena *arena; COFF_LibWriterMemberList member_list; COFF_LibWriterSymbolList symbol_list; } COFF_LibWriter; //////////////////////////////// internal COFF_LibWriterSymbolNode * coff_lib_writer_symbol_list_push(Arena *arena, COFF_LibWriterSymbolList *list, COFF_LibWriterSymbol symbol); internal COFF_LibWriterMemberNode * coff_lib_writer_member_list_push(Arena *arena, COFF_LibWriterMemberList *list, COFF_LibWriterMember member); internal COFF_LibWriterSymbol * coff_lib_writer_symbol_array_from_list(Arena *arena, COFF_LibWriterSymbolList list); internal COFF_LibWriterMember * coff_lib_writer_member_array_from_list(Arena *arena, COFF_LibWriterMemberList list); internal void coff_lib_writer_symbol_array_sort_on_name(COFF_LibWriterSymbol *arr, U64 count); internal void coff_lib_writer_symbol_array_sort_on_member_idx(COFF_LibWriterSymbol *arr, U64 count); internal COFF_LibWriter * coff_lib_writer_alloc(void); internal void coff_lib_writer_release(COFF_LibWriter **writer_ptr); internal U64 coff_lib_writer_push_obj(COFF_LibWriter *writer, String8 obj_path, String8 obj_data); internal void coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType import_type); internal String8 coff_lib_writer_serialize(Arena *arena, COFF_LibWriter *lib_writer, COFF_TimeStamp time_stamp, U16 mode, B32 emit_second_member); #endif // COFF_LIB_WRITER_H ================================================ FILE: src/coff/coff_obj_writer.c ================================================ internal COFF_ObjWriter* coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine) { Arena *arena = arena_alloc(); COFF_ObjWriter *obj_writer = push_array(arena, COFF_ObjWriter, 1); obj_writer->arena = arena; obj_writer->time_stamp = time_stamp; obj_writer->machine = machine; return obj_writer; } internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer) { arena_release((*obj_writer)->arena); *obj_writer = 0; } internal String8 coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer) { Temp scratch = scratch_begin(&arena, 1); String8List srl = {0}; String8List string_table = {0}; U32 *string_table_size = push_array(scratch.arena, U32, 1); *string_table_size = sizeof(*string_table_size); str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size)); // // assing section numbers // U64 obj_sections_count; COFF_ObjSection **obj_sections; { obj_sections_count = obj_writer->sect_count; obj_sections = push_array(scratch.arena, COFF_ObjSection *, obj_writer->sect_count); U64 sect_idx = 0; for (COFF_ObjSectionNode *sect_n = obj_writer->sect_first; sect_n != 0; sect_n = sect_n->next, sect_idx += 1) { COFF_ObjSection *sect = §_n->v; sect->section_number = sect_idx+1; obj_sections[sect_idx] = sect; } } AssertAlways(obj_sections_count <= max_U16); // // serialize symbol table // String8List symbol_table = {0}; { { U64 symbol_idx = 0; for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) { COFF_ObjSymbol *s = &symbol_n->v; // assign symbol index s->idx = symbol_idx++; symbol_idx += s->aux_symbols.node_count; } } U64 symbol_idx = 0; for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) { COFF_ObjSymbol *s = &symbol_n->v; COFF_Symbol16 *d = push_array(scratch.arena, COFF_Symbol16, 1); str8_list_push(scratch.arena, &symbol_table, str8_struct(d)); COFF_SymbolName name = {0}; // long name if (s->name.size > sizeof(name.short_name)) { U64 string_table_offset = string_table.total_size; str8_list_push(scratch.arena, &string_table, s->name); str8_list_push(scratch.arena, &string_table, str8_lit("\0")); name.long_name.zeroes = 0; name.long_name.string_table_offset = safe_cast_u32(string_table_offset); } // short name else { MemoryCopyStr8(name.short_name, s->name); MemoryZeroTyped(name.short_name + s->name.size, sizeof(name.short_name) - s->name.size); } // symbol header AssertAlways(s->aux_symbols.node_count <= max_U8); d->name = name; d->value = s->value; switch (s->loc.type) { case COFF_SymbolLocation_Null: break; case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break; case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break; case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break; case COFF_SymbolLocation_Common: d->section_number = COFF_Symbol_UndefinedSection; break; } d->type = s->type; d->storage_class = s->storage_class; d->aux_symbol_count = 0; U64 start_symbol_idx = symbol_idx; if (s->storage_class == COFF_SymStorageClass_WeakExternal) { if (s->aux_symbols.node_count > 0) { COFF_ObjSymbolWeak *s_weak = (COFF_ObjSymbolWeak *)s->aux_symbols.first->string.str; COFF_SymbolWeakExt *d_weak = push_array(scratch.arena, COFF_SymbolWeakExt, 1); d_weak->tag_index = s_weak->tag ? s_weak->tag->idx : max_U32; d_weak->characteristics = s_weak->characteristics; str8_list_push(scratch.arena, &symbol_table, str8_struct(d_weak)); symbol_idx += 1; } } else if (s->storage_class == COFF_SymStorageClass_Static) { if (s->aux_symbols.node_count > 0) { Assert(s->loc.type == COFF_SymbolLocation_Section); COFF_ObjSection *sect = s->loc.u.section; COFF_ObjSymbolSecDef *s_sd = (COFF_ObjSymbolSecDef *)s->aux_symbols.first->string.str; COFF_SymbolSecDef *d_sd = push_array(scratch.arena, COFF_SymbolSecDef, 1); d_sd->length = safe_cast_u32(sect->data.total_size); d_sd->number_of_relocations = (U16)sect->reloc_count; d_sd->check_sum = 0; d_sd->number_lo = s_sd->selection == COFF_ComdatSelect_Associative ? safe_cast_u16(s_sd->associate->section_number) : 0; d_sd->selection = s_sd->selection; str8_list_push(scratch.arena, &symbol_table, str8_struct(d_sd)); symbol_idx += 1; } } U8 processed_aux_symbol_count = (U8)(symbol_idx - start_symbol_idx); for (U64 aux_idx = processed_aux_symbol_count; aux_idx < s->aux_symbols.node_count; aux_idx += 1) { COFF_Symbol16 *a = push_array(scratch.arena, COFF_Symbol16, 1); str8_list_push(scratch.arena, &symbol_table, str8_struct(a)); } d->aux_symbol_count = (U8)s->aux_symbols.node_count; } } // // file header // COFF_FileHeader *file_header = push_array(scratch.arena, COFF_FileHeader, 1); file_header->machine = obj_writer->machine; file_header->section_count = obj_sections_count; file_header->time_stamp = obj_writer->time_stamp; file_header->symbol_table_foff = 0; file_header->symbol_count = safe_cast_u32(symbol_table.node_count); file_header->optional_header_size = 0; file_header->flags = 0; str8_list_push(scratch.arena, &srl, str8_struct(file_header)); // // section table // COFF_SectionHeader *sectab = push_array(scratch.arena, COFF_SectionHeader, obj_sections_count); str8_list_push(scratch.arena, &srl, str8_array(sectab, obj_sections_count)); { for (U64 sect_idx = 0; sect_idx < obj_sections_count; sect_idx += 1) { COFF_ObjSection *s = obj_sections[sect_idx]; COFF_SectionHeader *d = §ab[sect_idx]; // section name String8 sect_name = s->name; if (sect_name.size > sizeof(d->name)) { U64 sect_name_off = string_table.total_size; str8_list_push(scratch.arena, &string_table, push_cstr(scratch.arena, sect_name)); sect_name = push_str8f(scratch.arena, "/%u", sect_name_off); AssertAlways(sect_name.size <= sizeof(d->name)); } // alloc zero nodes for (String8Node *data_n = s->data.first; data_n != 0; data_n = data_n->next) { if (data_n->string.str == 0 && data_n->string.size > 0) { data_n->string = str8(push_array(scratch.arena, U8, data_n->string.size), data_n->string.size); } } // section data U64 data_foff = 0; U64 data_size = 0; if (s->data.total_size > 0) { data_foff = srl.total_size; data_size = s->data.total_size; str8_list_concat_in_place(&srl, &s->data); } // section relocs U64 relocs_foff = 0; if (s->reloc_count) { AssertAlways(s->reloc_count <= max_U16); COFF_Reloc *relocs = push_array(scratch.arena, COFF_Reloc, s->reloc_count); U64 reloc_idx = 0; for (COFF_ObjRelocNode *reloc_n = s->reloc_first; reloc_n != 0; reloc_n = reloc_n->next, reloc_idx += 1) { COFF_ObjReloc *rs = &reloc_n->v; COFF_Reloc *rd = &relocs[reloc_idx]; rd->apply_off = rs->apply_off; rd->isymbol = rs->symbol->idx; rd->type = rs->type; } relocs_foff = srl.total_size; str8_list_push(scratch.arena, &srl, str8_array(relocs, s->reloc_count)); } // section header MemoryCopyStr8(d->name, sect_name); MemoryZeroTyped(d->name + sect_name.size, sizeof(d->name) - sect_name.size); d->vsize = 0; d->voff = 0; d->fsize = data_size; d->foff = data_foff; d->relocs_foff = relocs_foff; d->lines_foff = 0; d->reloc_count = safe_cast_u32(s->reloc_count); d->line_count = 0; d->flags = s->flags; } } // // symbol table // if (symbol_table.total_size || string_table.total_size > sizeof(*string_table_size)) { file_header->symbol_table_foff = srl.total_size; str8_list_concat_in_place(&srl, &symbol_table); } // // string table // if (string_table.total_size) { *string_table_size = safe_cast_u32(string_table.total_size); str8_list_concat_in_place(&srl, &string_table); } // // join // String8 obj = str8_list_join(arena, &srl, 0); scratch_end(scratch); return obj; } internal COFF_ObjSection * coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data) { COFF_ObjSectionNode *sect_n = push_array(obj_writer->arena, COFF_ObjSectionNode, 1); SLLQueuePush(obj_writer->sect_first, obj_writer->sect_last, sect_n); obj_writer->sect_count += 1; COFF_ObjSection *sect = §_n->v; sect->name = name; sect->flags = flags; if (data.size) { str8_list_push(obj_writer->arena, §->data, data); } return sect; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class) { COFF_ObjSymbolNode *n = push_array(obj_writer->arena, COFF_ObjSymbolNode, 1); SLLQueuePush(obj_writer->symbol_first, obj_writer->symbol_last, n); obj_writer->symbol_count += 1; COFF_ObjSymbol *s = &n->v; s->name = name; s->value = value; s->loc = loc; s->type = type; s->storage_class = storage_class; return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section) { COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Section; loc.u.section = section; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, COFF_SymStorageClass_External); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section) { COFF_SymbolType type = { .u.msb = COFF_SymDType_Func }; COFF_SymbolLocation loc = { .type = COFF_SymbolLocation_Section, .u.section = section }; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_External); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section) { COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Section; loc.u.section = section; COFF_SymbolType symtype = {0}; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, off, loc, symtype, COFF_SymStorageClass_Static); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection) { COFF_ObjSymbol *s = coff_obj_writer_push_symbol_static(obj_writer, section->name, 0, section); COFF_ObjSymbolSecDef *sd = push_array(obj_writer->arena, COFF_ObjSymbolSecDef, 1); sd->selection = selection; str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(sd)); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_associative(COFF_ObjWriter *obj_writer, COFF_ObjSection *head, COFF_ObjSection *associate) { COFF_ObjSymbol *s = coff_obj_writer_push_symbol_static(obj_writer, head->name, 0, head); COFF_ObjSymbolSecDef *sd = push_array(obj_writer->arena, COFF_ObjSymbolSecDef, 1); sd->selection = COFF_ComdatSelect_Associative; sd->associate = associate; str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(sd)); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_weak(COFF_ObjWriter *obj_writer, String8 name, COFF_WeakExtType characteristics, COFF_ObjSymbol *tag) { COFF_SymbolLocation loc = {0}; COFF_SymbolType symtype = {0}; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, COFF_Symbol_UndefinedSection, loc, symtype, COFF_SymStorageClass_WeakExternal); COFF_ObjSymbolWeak *weak_ext = push_array(obj_writer->arena, COFF_ObjSymbolWeak, 1); weak_ext->tag = tag; weak_ext->characteristics = characteristics; str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(weak_ext)); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymStorageClass storage_class) { COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Abs; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, storage_class); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef(COFF_ObjWriter *obj_writer, String8 name) { COFF_SymbolType type = {0}; COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Undef; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_func(COFF_ObjWriter *obj_writer, String8 name) { COFF_SymbolType type = {0}; type.u.msb = COFF_SymDType_Func; COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Undef; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_sect(COFF_ObjWriter *obj_writer, String8 name, U32 value) { COFF_SymbolType type = {0}; COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Undef; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_Section); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_ObjSection *sect) { COFF_SymbolType type = {0}; COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Section; loc.u.section = sect; // strip align flags COFF_SectionFlags expected_flags = sect->flags & ~(COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift); COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, expected_flags, loc, type, COFF_SymStorageClass_Section); return s; } internal COFF_ObjSymbol * coff_obj_writer_push_symbol_common(COFF_ObjWriter *obj_writer, String8 name, U32 size) { COFF_SymbolType type = {0}; COFF_SymbolLocation loc = {0}; loc.type = COFF_SymbolLocation_Common; COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, size, loc, type, COFF_SymStorageClass_External); return s; } internal void coff_obj_writer_set_default_symbol(COFF_ObjSymbol *weak_symbol, COFF_ObjSymbol *default_symbol) { AssertAlways(weak_symbol->storage_class == COFF_SymStorageClass_WeakExternal); COFF_ObjSymbolWeak *w = (COFF_ObjSymbolWeak *)weak_symbol->aux_symbols.first->string.str; w->tag = default_symbol; } internal COFF_ObjReloc* coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType type) { COFF_ObjRelocNode *reloc_n = push_array(obj_writer->arena, COFF_ObjRelocNode, 1); SLLQueuePush(sect->reloc_first, sect->reloc_last, reloc_n); sect->reloc_count += 1; COFF_ObjReloc *reloc = &reloc_n->v; reloc->apply_off = apply_off; reloc->symbol = symbol; reloc->type = type; return reloc; } internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_addr32(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol) { COFF_RelocType reloc_type = 0; switch (obj_writer->machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32; break; default: { NotImplemented; } break; } return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type); } internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_addr(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol) { COFF_RelocType reloc_type = 0; switch (obj_writer->machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr64; break; default: { NotImplemented; } break; } return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type); } internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_voff(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol) { COFF_RelocType reloc_type = 0; switch (obj_writer->machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32Nb; break; default: { NotImplemented; } break; } return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type); } internal void coff_obj_writer_push_directive(COFF_ObjWriter *obj_writer, String8 directive) { if (obj_writer->drectve_sect == 0) { local_persist const U8 bom_sig[] = { ' ', ' ', ' ' }; obj_writer->drectve_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".drectve"), COFF_SectionFlag_LnkInfo|COFF_SectionFlag_LnkRemove|COFF_SectionFlag_Align1Bytes, str8_array_fixed(bom_sig)); } String8List *data = &obj_writer->drectve_sect->data; str8_list_push(obj_writer->arena, data, directive); str8_list_pushf(obj_writer->arena, data, " "); } internal int coff_obj_section_is_before(void *raw_a, void *raw_b) { COFF_ObjSection **a = raw_a; COFF_ObjSection **b = raw_b; return (*a)->section_number < (*b)->section_number; } ================================================ FILE: src/coff/coff_obj_writer.h ================================================ #ifndef COFF_OBJ_WRITER_H #define COFF_OBJ_WRITER_H typedef enum { COFF_SymbolLocation_Null, COFF_SymbolLocation_Section, COFF_SymbolLocation_Abs, COFF_SymbolLocation_Undef, COFF_SymbolLocation_Common, } COFF_SymbolLocationType; typedef struct COFF_SymbolLocation { COFF_SymbolLocationType type; union { struct COFF_ObjSection *section; } u; } COFF_SymbolLocation; typedef struct COFF_ObjSymbolWeak { struct COFF_ObjSymbol *tag; COFF_WeakExtType characteristics; } COFF_ObjSymbolWeak; typedef struct COFF_ObjSymbolSecDef { COFF_ComdatSelectType selection; struct COFF_ObjSection *associate; } COFF_ObjSymbolSecDef; typedef struct COFF_ObjSymbol { String8 name; U32 value; COFF_SymbolLocation loc; COFF_SymbolType type; COFF_SymStorageClass storage_class; String8List aux_symbols; U32 idx; } COFF_ObjSymbol; typedef struct COFF_ObjSymbolNode { struct COFF_ObjSymbolNode *next; COFF_ObjSymbol v; } COFF_ObjSymbolNode; typedef struct COFF_ObjReloc { U32 apply_off; COFF_ObjSymbol *symbol; COFF_RelocType type; } COFF_ObjReloc; typedef struct COFF_ObjRelocNode { struct COFF_ObjRelocNode *next; COFF_ObjReloc v; } COFF_ObjRelocNode; typedef struct COFF_ObjSection { String8 name; String8List data; COFF_SectionFlags flags; U64 reloc_count; COFF_ObjRelocNode *reloc_first; COFF_ObjRelocNode *reloc_last; U32 section_number; } COFF_ObjSection; typedef struct COFF_ObjSectionNode { struct COFF_ObjSectionNode *next; COFF_ObjSection v; } COFF_ObjSectionNode; typedef struct COFF_ObjWriter { Arena *arena; COFF_TimeStamp time_stamp; COFF_MachineType machine; U64 symbol_count; COFF_ObjSymbolNode *symbol_first; COFF_ObjSymbolNode *symbol_last; U64 sect_count; COFF_ObjSectionNode *sect_first; COFF_ObjSectionNode *sect_last; COFF_ObjSection *drectve_sect; } COFF_ObjWriter; //////////////////////////////// internal COFF_ObjWriter * coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine); internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer); internal String8 coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer); internal COFF_ObjSection * coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data); internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_associative(COFF_ObjWriter *obj_writer, COFF_ObjSection *head, COFF_ObjSection *associate); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_weak(COFF_ObjWriter *obj_writer, String8 name, COFF_WeakExtType characteristics, COFF_ObjSymbol *tag); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymStorageClass storage_class); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef(COFF_ObjWriter *obj_writer, String8 name); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_func(COFF_ObjWriter *obj_writer, String8 name); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_sect(COFF_ObjWriter *obj_writer, String8 name, U32 value); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_ObjSection *sect); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_common(COFF_ObjWriter *obj_writer, String8 name, U32 size); internal void coff_obj_writer_set_default_symbol(COFF_ObjSymbol *weak_symbol, COFF_ObjSymbol *default_symbol); internal COFF_ObjReloc * coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType reloc_type); internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_addr32(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol); internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_addr(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol); internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_voff(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol); internal void coff_obj_writer_push_directive(COFF_ObjWriter *obj_writer, String8 directive); #endif // COFF_OBJ_WRITER_H ================================================ FILE: src/coff/coff_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 coff_is_big_obj(String8 raw_coff) { B32 is_big_obj = 0; if (raw_coff.size >= sizeof(COFF_BigObjHeader)) { COFF_BigObjHeader *file_header32 = (COFF_BigObjHeader*)(raw_coff.str); is_big_obj = file_header32->sig1 == COFF_MachineType_Unknown && file_header32->sig2 == max_U16 && file_header32->version >= 2 && MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0; } return is_big_obj; } internal B32 coff_is_obj(String8 raw_coff) { B32 is_obj = 0; if (raw_coff.size >= sizeof(COFF_FileHeader)) { COFF_FileHeader *header = (COFF_FileHeader*)(raw_coff.str); // validate machine B32 is_machine_type_valid = 0; switch (header->machine) { case COFF_MachineType_Unknown: case COFF_MachineType_X86: case COFF_MachineType_X64: case COFF_MachineType_Am33: case COFF_MachineType_Arm: case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: case COFF_MachineType_Ebc: case COFF_MachineType_Ia64: case COFF_MachineType_M32R: case COFF_MachineType_Mips16: case COFF_MachineType_MipsFpu:case COFF_MachineType_MipsFpu16: case COFF_MachineType_PowerPc:case COFF_MachineType_PowerPcFp: case COFF_MachineType_R4000: case COFF_MachineType_RiscV32: case COFF_MachineType_RiscV64:case COFF_MachineType_RiscV128: case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp: case COFF_MachineType_Sh4: case COFF_MachineType_Sh5: case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2: { is_machine_type_valid = 1; }break; } if (is_machine_type_valid) { // validate section count U64 section_count = header->section_count; U64 section_hdr_opl_off = sizeof(*header) + section_count*sizeof(COFF_SectionHeader); if (raw_coff.size >= section_hdr_opl_off) { COFF_SectionHeader *section_hdrs = (COFF_SectionHeader*)(raw_coff.str + sizeof(*header)); COFF_SectionHeader *section_hdr_opl = section_hdrs + section_count; // validate section ranges B32 is_sect_range_valid = 1; for (COFF_SectionHeader *sec_hdr = section_hdrs; sec_hdr < section_hdr_opl; sec_hdr += 1) { if (!(sec_hdr->flags & COFF_SectionFlag_CntUninitializedData)) { U64 min = sec_hdr->foff; U64 max = min + sec_hdr->fsize; if (sec_hdr->fsize > 0 && !(section_hdr_opl_off <= min && min <= max && max <= raw_coff.size)) { is_sect_range_valid = 0; break; } } } if (is_sect_range_valid) { // validate symbol table U64 symbol_table_off = header->symbol_table_foff; U64 symbol_table_size = sizeof(COFF_Symbol16)*header->symbol_count; U64 symbol_table_opl_off = symbol_table_off + symbol_table_size; // don't validate symbol table when there is none if (symbol_table_off == 0 && symbol_table_size == 0) { symbol_table_off = section_hdr_opl_off; symbol_table_opl_off = section_hdr_opl_off; } is_obj = (section_hdr_opl_off <= symbol_table_off && symbol_table_off <= symbol_table_opl_off && symbol_table_opl_off <= raw_coff.size); } } } } return is_obj; } internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff) { COFF_FileHeaderInfo info = {0}; if (coff_is_big_obj(raw_coff)) { COFF_BigObjHeader *header32 = (COFF_BigObjHeader*)raw_coff.str; info.is_big_obj = 1; info.machine = header32->machine; info.section_count_no_null = header32->section_count; info.symbol_count = header32->symbol_count; info.symbol_size = sizeof(COFF_Symbol32); info.header_range = rng_1u64(0, sizeof(COFF_BigObjHeader)); info.section_table_range = rng_1u64(info.header_range.max, info.header_range.max + sizeof(COFF_SectionHeader) * header32->section_count); info.symbol_table_range = rng_1u64(header32->symbol_table_foff, header32->symbol_table_foff + sizeof(COFF_Symbol32) * header32->symbol_count); info.string_table_range = rng_1u64(info.symbol_table_range.max, raw_coff.size); } else if (coff_is_obj(raw_coff)) { COFF_FileHeader *header16 = (COFF_FileHeader*)raw_coff.str; info.is_big_obj = 0; info.machine = header16->machine; info.section_count_no_null = header16->section_count; info.symbol_count = header16->symbol_count; info.symbol_size = sizeof(COFF_Symbol16); info.header_range = rng_1u64(0, sizeof(COFF_FileHeader)); info.section_table_range = rng_1u64(info.header_range.max, info.header_range.max + sizeof(COFF_SectionHeader) * header16->section_count); info.symbol_table_range = rng_1u64(header16->symbol_table_foff, header16->symbol_table_foff + sizeof(COFF_Symbol16) * header16->symbol_count); info.string_table_range = rng_1u64(info.symbol_table_range.max, raw_coff.size); } return info; } internal COFF_SectionHeader ** coff_section_table_from_data(Arena *arena, String8 data, Rng1U64 section_table_range) { U64 section_count = dim_1u64(section_table_range) / sizeof(COFF_SectionHeader); COFF_SectionHeader **section_table = push_array_no_zero(arena, COFF_SectionHeader *, section_count+1); section_table[0] = push_array(arena, COFF_SectionHeader, 1); for (U64 i = 0; i < section_count; ++i) { section_table[i+1] = str8_deserial_get_raw_ptr(data, section_table_range.min + i*sizeof(COFF_SectionHeader), sizeof(COFF_SectionHeader)); } return section_table; } internal COFF_ParsedSymbol coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32) { COFF_ParsedSymbol result = {0}; result.name = coff_read_symbol_name(string_table, &sym32->name); result.value = sym32->value; result.section_number = sym32->section_number; result.type = sym32->type; result.storage_class = sym32->storage_class; result.aux_symbol_count = sym32->aux_symbol_count; result.raw_symbol = sym32; return result; } internal COFF_ParsedSymbol coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16) { COFF_ParsedSymbol result = {0}; result.name = coff_read_symbol_name(string_table, &sym16->name); result.value = sym16->value; if (sym16->section_number == COFF_Symbol_DebugSection16) { result.section_number = COFF_Symbol_DebugSection32; } else if (sym16->section_number == COFF_Symbol_AbsSection16) { result.section_number = COFF_Symbol_AbsSection32; } else { result.section_number = (U32)sym16->section_number; } result.type = sym16->type; result.storage_class = sym16->storage_class; result.aux_symbol_count = sym16->aux_symbol_count; result.raw_symbol = sym16; return result; } internal COFF_ParsedSymbol coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx) { COFF_ParsedSymbol symbol; if (header.is_big_obj) { symbol = coff_parse_symbol32(string_table, (COFF_Symbol32 *)symbol_table.str + symbol_idx); } else { symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx); } return symbol; } internal COFF_Symbol32Array coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count) { COFF_Symbol32Array result = {0}; result.count = symbol_count; result.v = push_array_no_zero_aligned(arena, COFF_Symbol32, result.count, 8); Rng1U64 sym16_arr_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count); String8 raw_sym16_arr = str8_substr(raw_coff, sym16_arr_range); COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)raw_sym16_arr.str; for (U64 isymbol = 0, count = raw_sym16_arr.size / sizeof(COFF_Symbol16); isymbol < count; isymbol += 1) { COFF_Symbol16 *sym16 = &sym16_arr[isymbol]; COFF_Symbol32 *sym32 = &result.v[isymbol]; sym32->name = sym16->name; sym32->value = sym16->value; if (sym16->section_number == COFF_Symbol_DebugSection16) { sym32->section_number = COFF_Symbol_DebugSection32; } else if (sym16->section_number == COFF_Symbol_AbsSection16) { sym32->section_number = COFF_Symbol_AbsSection32; } else { sym32->section_number = (U32)sym16->section_number; } sym32->type.v = sym16->type.v; sym32->storage_class = sym16->storage_class; sym32->aux_symbol_count = sym16->aux_symbol_count; // copy aux symbols for (U64 iaux = isymbol+1, iaux_hi = Min(count, iaux+sym16->aux_symbol_count); iaux < iaux_hi; iaux += 1) { COFF_Symbol16 *aux16 = sym16_arr + iaux; COFF_Symbol32 *aux32 = result.v + iaux; // 32bit COFF uses 16bit aux symbols MemoryCopy(aux32, aux16, sizeof(COFF_Symbol16)); MemoryZero((U8 *)aux32 + sizeof(COFF_Symbol16), sizeof(COFF_Symbol32)-sizeof(COFF_Symbol16)); } // take into account aux symbols isymbol += sym32->aux_symbol_count; } return result; } internal COFF_Symbol32Array coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count) { COFF_Symbol32Array result; result.count = symbol_count; result.v = (COFF_Symbol32 *)(data.str + symbol_array_off); return result; } internal COFF_Symbol32Array coff_symbol_array_from_data(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count, U64 symbol_size) { COFF_Symbol32Array result = {0}; switch (symbol_size) { case sizeof(COFF_Symbol16): result = coff_symbol_array_from_data_16(arena, data, symbol_array_off, symbol_count); break; case sizeof(COFF_Symbol32): result = coff_symbol_array_from_data_32(arena, data, symbol_array_off, symbol_count); break; } return result; } internal COFF_Symbol16Node * coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol) { COFF_Symbol16Node *node = push_array(arena, COFF_Symbol16Node, 1); node->next = 0; node->data = symbol; SLLQueuePush(list->first, list->last, node); list->count += 1; return node; } internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class) { if (storage_class == COFF_SymStorageClass_Section && section_number == COFF_Symbol_UndefinedSection) { return COFF_SymbolValueInterp_Undefined; } if (storage_class == COFF_SymStorageClass_External && value == 0 && section_number == COFF_Symbol_UndefinedSection) { return COFF_SymbolValueInterp_Undefined; } if (storage_class == COFF_SymStorageClass_External && value != 0 && section_number == COFF_Symbol_UndefinedSection) { return COFF_SymbolValueInterp_Common; } if (section_number == COFF_Symbol_AbsSection32) { return COFF_SymbolValueInterp_Abs; } if (section_number == COFF_Symbol_DebugSection32) { return COFF_SymbolValueInterp_Debug; } if (storage_class == COFF_SymStorageClass_WeakExternal) { return COFF_SymbolValueInterp_Weak; } return COFF_SymbolValueInterp_Regular; } internal COFF_SymbolValueInterpType coff_interp_from_parsed_symbol(COFF_ParsedSymbol symbol) { return coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); } internal B32 coff_is_undefined_data_symbol(COFF_ParsedSymbol symbol) { COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); return interp == COFF_SymbolValueInterp_Undefined && symbol.storage_class == COFF_SymStorageClass_External; } internal void coff_parse_secdef(COFF_ParsedSymbol symbol, B32 is_big_obj, COFF_ComdatSelectType *selection_out, U32 *number_out, U32 *length_out, U32 *check_sum_out) { Assert(coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class) == COFF_SymbolValueInterp_Regular); Assert(symbol.aux_symbol_count > 0); if (is_big_obj) { COFF_SymbolSecDef *sd = (COFF_SymbolSecDef *)((COFF_Symbol32 *)symbol.raw_symbol + 1); if (selection_out) *selection_out = sd->selection; if (length_out) *length_out = sd->length; if (check_sum_out) *check_sum_out = sd->check_sum; if (number_out) *number_out = Compose32Bit(sd->number_hi, sd->number_lo); } else { COFF_SymbolSecDef *sd = (COFF_SymbolSecDef *)((COFF_Symbol16 *)symbol.raw_symbol + 1); if (selection_out) *selection_out = sd->selection; if (length_out) *length_out = sd->length; if (check_sum_out) *check_sum_out = sd->check_sum; if (number_out) *number_out = sd->number_lo; } } internal COFF_SymbolWeakExt * coff_parse_weak_tag(COFF_ParsedSymbol symbol, B32 is_big_obj) { Assert(coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class) == COFF_SymbolValueInterp_Weak); Assert(symbol.aux_symbol_count > 0); void *tag; if (is_big_obj) { tag = (COFF_SymbolWeakExt *)((COFF_Symbol32 *)symbol.raw_symbol + 1); } else { tag = (COFF_SymbolWeakExt *)((COFF_Symbol16 *)symbol.raw_symbol + 1); } return tag; } internal COFF_RelocNode * coff_reloc_list_push(Arena *arena, COFF_RelocList *list, COFF_Reloc reloc) { COFF_RelocNode *node = push_array(arena, COFF_RelocNode, 1); node->data = reloc; SLLQueuePush(list->first, list->last, node); ++list->count; return node; } internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header) { COFF_RelocInfo result = {0}; if (header->flags & COFF_SectionFlag_LnkNRelocOvfl && header->reloc_count == max_U16) { COFF_Reloc counter; U64 read_size = str8_deserial_read_struct(data, header->relocs_foff, &counter); if (read_size == sizeof(counter) && counter.apply_off > 0) { result.array_off = header->relocs_foff + sizeof(COFF_Reloc); result.count = counter.apply_off - 1; // exclude counter entry } } else { result.array_off = header->relocs_foff; result.count = header->reloc_count; } return result; } internal String8 coff_resource_string_from_str16(Arena *arena, String16 string) { AssertAlways(string.size <= max_U16); U16 size16 = (U16)string.size; U16 *buffer = push_array_no_zero(arena, U16, size16 + 1); MemoryCopy(buffer + 0, &size16, sizeof(size16)); MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0])); return str8_array(buffer, size16 + 1); } internal String8 coff_resource_string_from_str8(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); String16 string16 = str16_from_8(scratch.arena, string); String8 result = coff_resource_string_from_str16(arena, string16); scratch_end(scratch); return result; } internal String8 coff_resource_number_from_u16(Arena *arena, U16 number) { U16 *buffer = push_array_no_zero(arena, U16, 2); buffer[0] = max_U16; buffer[1] = number; return str8_array(buffer, 2); } internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID16 *id_16) { COFF_ResourceID id = {0}; id.type = id_16->type; switch (id_16->type) { case COFF_ResourceIDType_Null: break; case COFF_ResourceIDType_Number: { id.u.number = id_16->u.number; } break; case COFF_ResourceIDType_String: { id.u.string = str8_from_16(arena, id_16->u.string); } break; default: InvalidPath; } return id; } internal U64 coff_read_resource_id_utf16(String8 raw_res, U64 off, COFF_ResourceID16 *id_out) { U64 cursor = off; U16 flag = 0; str8_deserial_read_struct(raw_res, cursor, &flag); if (flag == max_U16) { id_out->type = COFF_ResourceIDType_Number; cursor += sizeof(flag); cursor += str8_deserial_read_struct(raw_res, cursor, &id_out->u.number); } else { id_out->type = COFF_ResourceIDType_String; cursor += str8_deserial_read_windows_utf16_string16(raw_res, cursor, &id_out->u.string); } U64 read_size = cursor - off; read_size = AlignPow2(read_size, COFF_ResourceAlign); return read_size; } internal U64 coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *res_out) { String8 raw_header = str8_skip(raw_res, off); U64 header_cursor = 0; // prefix COFF_ResourceHeaderPrefix prefix = {0}; header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix); Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix)); raw_header = str8_prefix(raw_header, prefix.header_size); // header COFF_ResourceID16 type_16 = {0}; COFF_ResourceID16 name_16 = {0}; header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &type_16); header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &name_16); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->data_version); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->memory_flags); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->language_id); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics); Assert(prefix.header_size == header_cursor); // convert utf-16 resource ids to utf-8 res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16); res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16); // read data U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data); Assert(prefix.data_size == data_read_size); // compute read size U64 read_size = Max(prefix.header_size, sizeof(prefix)) + AlignPow2(prefix.data_size, COFF_ResourceAlign); return read_size; } internal COFF_ParsedResourceList coff_resource_list_from_data(Arena *arena, String8 data) { COFF_ParsedResourceList list = {0}; U64 cursor; for (cursor = 0 ; cursor < data.size; ) { COFF_ParsedResourceNode *node = push_array(arena, COFF_ParsedResourceNode, 1); cursor += coff_read_resource(arena, data, cursor, &node->data); SLLQueuePush(list.first, list.last, node); ++list.count; } Assert(cursor == data.size); return list; } internal String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id) { String8 result = str8_zero(); switch (id.type) { case COFF_ResourceIDType_Null: break; case COFF_ResourceIDType_Number: { result = coff_resource_number_from_u16(arena, id.u.number); } break; case COFF_ResourceIDType_String: { result = coff_resource_string_from_str8(arena, id.u.string); } break; default: InvalidPath; } return result; } internal String8 coff_write_resource(Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1); String8 packed_type = coff_write_resource_id(scratch.arena, type); String8 packed_name = coff_write_resource_id(scratch.arena, name); // prefix + header str8_list_push(scratch.arena, &list, str8_struct(prefix)); str8_list_push(scratch.arena, &list, packed_type); str8_list_push(scratch.arena, &list, packed_name); str8_list_push(scratch.arena, &list, str8_struct(&data_version)); str8_list_push(scratch.arena, &list, str8_struct(&memory_flags)); str8_list_push(scratch.arena, &list, str8_struct(&language_id)); str8_list_push(scratch.arena, &list, str8_struct(&version)); str8_list_push(scratch.arena, &list, str8_struct(&characteristics)); prefix->data_size = safe_cast_u32(data.size); prefix->header_size = safe_cast_u32(list.total_size); // data str8_list_push(scratch.arena, &list, data); // magic str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic)); // align U64 align_size = AlignPow2(list.total_size, COFF_ResourceAlign) - list.total_size; U8 *align = push_array(scratch.arena, U8, align_size); str8_list_push(scratch.arena, &list, str8(align, align_size)); // join String8 res = str8_list_join(arena, &list, 0); scratch_end(scratch); return res; } internal int coff_resource_id_compar(void *raw_a, void *raw_b) { int cmp; COFF_ResourceID *a = raw_a; COFF_ResourceID *b = raw_b; if (a->type == b->type) { switch (a->type) { default: case COFF_ResourceIDType_Null: cmp = 0; break; case COFF_ResourceIDType_Number: cmp = MemoryCompare(&a->u.number, &b->u.number, sizeof(a->u.number)); break; case COFF_ResourceIDType_String: cmp = strncmp((char *)a->u.string.str, (char *)b->u.string.str, Min(a->u.string.size, b->u.string.size)); break; } } else { cmp = a->type < b->type ? -1 : a->type > b->type ? +1 : 0; } return cmp; } internal B32 coff_is_import(String8 raw_archive_member) { B32 is_import = 0; if (raw_archive_member.size >= sizeof(U16)*2) { U16 *sig1 = (U16*)raw_archive_member.str; U16 *sig2 = sig1 + 1; is_import = *sig1 == COFF_MachineType_Unknown && *sig2 == 0xffff; } return is_import; } internal COFF_DataType coff_data_type_from_data(String8 raw_archive_member) { B32 is_big_obj = coff_is_big_obj(raw_archive_member); if (is_big_obj) { return COFF_DataType_BigObj; } B32 is_import = coff_is_import(raw_archive_member); if (is_import) { return COFF_DataType_Import; } return COFF_DataType_Obj; } internal B32 coff_is_regular_archive(String8 raw_archive) { B32 is_archive = 0; U8 sig[sizeof(g_coff_archive_sig)]; if (str8_deserial_read_struct(raw_archive, 0, &sig) == sizeof(sig)) { is_archive = MemoryCompare(&sig[0], &g_coff_archive_sig[0], sizeof(g_coff_archive_sig)) == 0; } return is_archive; } internal B32 coff_is_thin_archive(String8 raw_archive) { B32 is_archive = 0; U8 sig[sizeof(g_coff_thin_archive_sig)]; if (str8_deserial_read_struct(raw_archive, 0, &sig) == sizeof(sig)) { is_archive = MemoryCompare(&sig[0], &g_coff_thin_archive_sig[0], sizeof(g_coff_thin_archive_sig)) == 0; } return is_archive; } internal COFF_ArchiveType coff_archive_type_from_data(String8 raw_archive) { if (coff_is_regular_archive(raw_archive)) { return COFF_Archive_Regular; } else if (coff_is_thin_archive(raw_archive)) { return COFF_Archive_Thin; } return COFF_Archive_Null; } internal U64 coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArchiveMemberHeader *header_out) { COFF_ArchiveMemberHeader *header = str8_deserial_get_raw_ptr(raw_archive, offset, sizeof(*header)); if (header) { String8 name = str8_skip_chop_whitespace(str8_cstring_capped(header->name, header->name + sizeof(header->name) )); String8 date = str8_skip_chop_whitespace(str8_cstring_capped(header->date, header->date + sizeof(header->date) )); String8 user_id = str8_skip_chop_whitespace(str8_cstring_capped(header->user_id, header->user_id + sizeof(header->user_id) )); String8 group_id = str8_skip_chop_whitespace(str8_cstring_capped(header->group_id, header->group_id + sizeof(header->group_id))); String8 mode = str8_skip_chop_whitespace(str8_cstring_capped(header->mode, header->mode + sizeof(header->mode) )); String8 size = str8_skip_chop_whitespace(str8_cstring_capped(header->size, header->size + sizeof(header->size) )); String8 end = str8_cstring_capped(header->end, header->end + sizeof(header->end)); U32 data_size = u32_from_str8(size, 10); U64 data_off = offset + sizeof(COFF_ArchiveMemberHeader); header_out->name = name; header_out->time_stamp = u32_from_str8(date, 10); header_out->user_id = u32_from_str8(user_id, 10); header_out->group_id = u32_from_str8(group_id, 10); header_out->mode = mode; header_out->is_end_correct = str8_match_lit("`\n", end, 0); header_out->data_range = rng_1u64(data_off, data_off + data_size); return sizeof(*header); } return 0; } internal COFF_ArchiveFirstMember coff_parse_first_archive_member(COFF_ArchiveMember *member) { Assert(str8_match_lit("/", member->header.name, 0)); U64 cursor = 0; U32 symbol_count = 0; cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); symbol_count = from_be_u32(symbol_count); Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U32)); cursor += dim_1u64(member_offsets_range); Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); cursor += dim_1u64(string_table_range); String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); U32 *member_offsets = (U32 *)raw_member_offsets.str; U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); COFF_ArchiveFirstMember result = {0}; result.symbol_count = symbol_count; result.member_offset_count = member_offset_count; result.member_offsets = member_offsets; result.string_table = str8_substr(member->data, string_table_range); return result; } internal COFF_ArchiveSecondMember coff_parse_second_archive_member(COFF_ArchiveMember *member) { COFF_ArchiveSecondMember result = {0}; if (str8_match_lit("/", member->header.name, 0)) { U64 cursor = 0; U32 member_count = 0; cursor += str8_deserial_read_struct(member->data, cursor, &member_count); Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + member_count * sizeof(U32)); cursor += dim_1u64(member_offsets_range); U32 symbol_count = 0; cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); Rng1U64 symbol_indices_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U16)); cursor += dim_1u64(symbol_indices_range); Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); String8 raw_indices = str8_substr(member->data, symbol_indices_range); U32 *member_offsets = (U32 *)raw_member_offsets.str; U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); U16 *symbol_indices = (U16 *)raw_indices.str; U64 symbol_index_count = raw_indices.size / sizeof(symbol_indices[0]); result.member_count = member_count; result.symbol_count = symbol_count; result.member_offsets = member_offsets; result.member_offset_count = member_offset_count; result.symbol_indices = symbol_indices; result.symbol_index_count = symbol_index_count; result.string_table = str8_substr(member->data, string_table_range); } return result; } internal String8 coff_decode_raw_member_name(String8 long_names, String8 name) { String8 result = name; if (name.size > 0 && name.str[0] == '/') { String8 offset_str = str8(name.str + 1, name.size - 1); U64 offset = u64_from_str8(offset_str, 10); if (offset < long_names.size) { U8 *ptr = long_names.str + offset; U8 *opl = long_names.str + long_names.size; for (; ptr < opl; ++ptr) { if (*ptr == '\0' || *ptr == '\n') { break; } } result = str8_range(long_names.str + offset, ptr); } } return result; } internal String8 coff_decode_member_name(String8 long_names, String8 name) { String8 member_name = coff_decode_raw_member_name(long_names, name); String8 slash = str8_lit("/"); if (str8_ends_with(member_name, slash, 0)) { member_name = str8_chop(member_name, slash.size); } return member_name; } internal U64 coff_parse_import(String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImportHeader *header_out) { COFF_ImportHeader *header = str8_deserial_get_raw_ptr(raw_archive_member, offset, sizeof(*header)); if (header) { Rng1U64 data_range = rng_1u64(offset + sizeof(*header), offset + sizeof(*header) + header->data_size); String8 raw_data = str8_substr(raw_archive_member, data_range); U64 data_cursor = 0; header_out->version = header->version; header_out->machine = header->machine; header_out->time_stamp = header->time_stamp; header_out->data_size = header->data_size; header_out->hint_or_ordinal = header->hint_or_ordinal; header_out->type = COFF_ImportHeader_ExtractType(header->flags); header_out->import_by = COFF_ImportHeader_ExtractImportBy(header->flags); data_cursor += str8_deserial_read_cstr(raw_data, data_cursor, &header_out->func_name); data_cursor += str8_deserial_read_cstr(raw_data, data_cursor, &header_out->dll_name); Assert(header_out->func_name.size + header_out->dll_name.size + /* nulls */ 2 == header_out->data_size); U64 read_size = sizeof(*header) + header->data_size; return read_size; } return 0; } internal COFF_ArchiveMember coff_archive_member_from_offset(String8 raw_archive, U64 offset) { COFF_ArchiveMember member = {0}; coff_regular_archive_member_iter_next(raw_archive, &offset, &member); return member; } internal COFF_ArchiveMember coff_archive_member_from_data(String8 raw_archive_member) { return coff_archive_member_from_offset(raw_archive_member, 0); } internal COFF_ParsedArchiveImportHeader coff_archive_import_from_data(String8 raw_archive_member) { COFF_ParsedArchiveImportHeader header = {0}; coff_parse_import(raw_archive_member, 0, &header); return header; } internal U64 coff_regular_archive_member_iter_init(String8 raw_archive) { U64 cursor = raw_archive.size; if (coff_is_regular_archive(raw_archive)) { cursor = sizeof(g_coff_archive_sig); } return cursor; } internal B32 coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out) { B32 is_parsed = 0; member_out->header.is_end_correct = 0; U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header); if (member_out->header.is_end_correct) { member_out->offset = *offset; member_out->data = str8_substr(raw_archive, member_out->header.data_range); U64 read_size = AlignPow2(header_size + dim_1u64(member_out->header.data_range), COFF_Archive_MemberAlign); *offset += read_size; is_parsed = 1; } return is_parsed; } internal U64 coff_thin_archive_member_iter_init(String8 raw_archive) { U64 cursor = raw_archive.size; if (coff_is_thin_archive(raw_archive)) { cursor = sizeof(g_coff_thin_archive_sig); } return cursor; } internal B32 coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out) { B32 is_parsed = 0; member_out->header.is_end_correct = 0; U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header); if (member_out->header.is_end_correct) { Rng1U64 data_in_archive_range = {0}; if (str8_match_lit("/", member_out->header.name, 0) || str8_match_lit("//", member_out->header.name, 0)) { data_in_archive_range = member_out->header.data_range; } member_out->offset = *offset; member_out->data = str8_substr(raw_archive, data_in_archive_range); U64 read_size = AlignPow2(header_size + dim_1u64(data_in_archive_range), COFF_Archive_MemberAlign); *offset += read_size; is_parsed = 1; } return is_parsed; } internal void coff_archive_member_list_push_node(COFF_ArchiveMemberList *list, COFF_ArchiveMemberNode *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal COFF_ArchiveParse coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) { String8 error = str8_zero(); B32 has_second_header = 0; B32 has_long_names = 0; COFF_ArchiveMember first_header = {0}; COFF_ArchiveMember second_header = {0}; COFF_ArchiveMember long_names_member = {0}; COFF_ArchiveMemberNode *ptr = member_list.first; if (ptr) { if (str8_match_lit("/", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { first_header = ptr->data; ptr = ptr->next; } else { error = str8_lit("first header doesn't have correct end"); } } } else { error = str8_lit("missing first header"); } if (!error.size && ptr) { if (str8_match_lit("/", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { second_header = ptr->data; ptr = ptr->next; has_second_header = 1; } else { error = str8_lit("second header doesn't have correct end"); } } } if (!error.size && ptr) { if (str8_match_lit("//", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { long_names_member = ptr->data; ptr = ptr->next; has_long_names; } else { error = str8_lit("long names header doesn't have correct end"); } } } COFF_ArchiveParse parse = {0}; parse.has_second_header = has_second_header; parse.has_long_names = has_long_names; parse.first_member = coff_parse_first_archive_member(&first_header); parse.second_member = coff_parse_second_archive_member(&second_header); parse.long_names = long_names_member.data; parse.error = error; return parse; } internal COFF_ArchiveParse coff_regular_archive_parse_from_data(String8 raw_archive) { COFF_ArchiveMemberList list = {0}; COFF_ArchiveMemberNode node_arr[3] = {0}; U64 cursor = coff_regular_archive_member_iter_init(raw_archive); for (U64 i = 0; i < ArrayCount(node_arr); ++i) { COFF_ArchiveMemberNode *node = &node_arr[i]; if (!coff_regular_archive_member_iter_next(raw_archive, &cursor, &node->data)) { break; } coff_archive_member_list_push_node(&list, node); } return coff_archive_parse_from_member_list(list); } internal COFF_ArchiveParse coff_thin_archive_parse_from_data(String8 raw_archive) { COFF_ArchiveMemberList list = {0}; COFF_ArchiveMemberNode node_arr[3] = {0}; U64 cursor = coff_thin_archive_member_iter_init(raw_archive); for (U64 i = 0; i < ArrayCount(node_arr); i += 1) { COFF_ArchiveMemberNode *node = &node_arr[i]; if (!coff_thin_archive_member_iter_next(raw_archive, &cursor, &node->data)) { break; } coff_archive_member_list_push_node(&list, node); } return coff_archive_parse_from_member_list(list); } internal COFF_ArchiveParse coff_archive_parse_from_data(String8 raw_archive) { COFF_ArchiveType type = coff_archive_type_from_data(raw_archive); switch (type) { case COFF_Archive_Null: break; case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive); case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive); } COFF_ArchiveParse null_parse = {0}; return null_parse; } ================================================ FILE: src/coff/coff_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_PARSE_H #define COFF_PARSE_H typedef struct COFF_FileHeaderInfo { B32 is_big_obj; COFF_MachineType machine; U64 header_size; U64 section_count_no_null; U64 symbol_size; U64 symbol_count; Rng1U64 header_range; Rng1U64 section_table_range; Rng1U64 symbol_table_range; Rng1U64 string_table_range; } COFF_FileHeaderInfo; //////////////////////////////// typedef struct COFF_SectionHeaderArray { U64 count; COFF_SectionHeader *v; } COFF_SectionHeaderArray; //////////////////////////////// typedef struct COFF_Symbol16Node { struct COFF_Symbol16Node *next; COFF_Symbol16 data; } COFF_Symbol16Node; typedef struct COFF_Symbol16List { U64 count; COFF_Symbol16Node *first; COFF_Symbol16Node *last; } COFF_Symbol16List; typedef struct COFF_Symbol32Array { U64 count; COFF_Symbol32 *v; } COFF_Symbol32Array; typedef struct COFF_ParsedSymbol { String8 name; U64 value; U32 section_number; COFF_SymbolType type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; void *raw_symbol; } COFF_ParsedSymbol; typedef U32 COFF_SymbolValueInterpType; enum { COFF_SymbolValueInterp_Regular, // symbol has section and offset. COFF_SymbolValueInterp_Weak, // symbol is overridable. COFF_SymbolValueInterp_Undefined, // symbol doesn't have a reference section. COFF_SymbolValueInterp_Common, // symbol has no section but still has size. COFF_SymbolValueInterp_Abs, // symbol has an absolute (non-relocatable) value and is not an address. COFF_SymbolValueInterp_Debug // symbol is used to provide general type of debugging information. }; //////////////////////////////// typedef struct COFF_RelocNode { struct COFF_RelocNode *next; COFF_Reloc data; } COFF_RelocNode; typedef struct COFF_RelocList { U64 count; COFF_RelocNode *first; COFF_RelocNode *last; } COFF_RelocList; typedef struct COFF_RelocArray { U64 count; COFF_Reloc *v; } COFF_RelocArray; typedef struct COFF_RelocInfo { U64 array_off; U64 count; } COFF_RelocInfo; //////////////////////////////// typedef U32 COFF_ResourceIDType; enum COFF_ResourceIDTypeEnum { COFF_ResourceIDType_Null, COFF_ResourceIDType_Number, COFF_ResourceIDType_String, COFF_ResourceIDType_Count }; typedef struct COFF_ResourceID16 { COFF_ResourceIDType type; union { U16 number; String16 string; } u; } COFF_ResourceID16; typedef struct COFF_ResourceID { COFF_ResourceIDType type; union { U16 number; String8 string; } u; } COFF_ResourceID; typedef struct COFF_ParsedResource { COFF_ResourceID type; COFF_ResourceID name; U32 data_version; COFF_ResourceMemoryFlags memory_flags; U16 language_id; U32 version; U32 characteristics; String8 data; } COFF_ParsedResource; typedef struct COFF_ParsedResourceNode { struct COFF_ParsedResourceNode *next; COFF_ParsedResource data; } COFF_ParsedResourceNode; typedef struct COFF_ParsedResourceList { U64 count; COFF_ParsedResourceNode *first; COFF_ParsedResourceNode *last; } COFF_ParsedResourceList; //////////////////////////////// typedef enum { COFF_DataType_Null, COFF_DataType_Obj, COFF_DataType_BigObj, COFF_DataType_Import } COFF_DataType; typedef enum { COFF_Archive_Null, COFF_Archive_Regular, COFF_Archive_Thin } COFF_ArchiveType; typedef struct COFF_ParsedArchiveMemberHeader { String8 name; // padded to 16 bytes with spaces COFF_TimeStamp time_stamp; U32 user_id; // unix artifact that does not have meaning on windows U32 group_id; // unix artifact that does not have meaning on windows String8 mode; // octal representation the members file mode B32 is_end_correct; // set to true if found correct signature after header Rng1U64 data_range; } COFF_ParsedArchiveMemberHeader; typedef struct COFF_ParsedArchiveImportHeader { B32 is_sig_correct; U16 version; COFF_MachineType machine; COFF_TimeStamp time_stamp; U32 data_size; U16 hint_or_ordinal; COFF_ImportType type; COFF_ImportByType import_by; String8 func_name; String8 dll_name; } COFF_ParsedArchiveImportHeader; typedef struct COFF_ArchiveMember { COFF_ParsedArchiveMemberHeader header; U64 offset; String8 data; } COFF_ArchiveMember; typedef struct COFF_ArchiveFirstMember { U32 symbol_count; U64 member_offset_count; U32 *member_offsets; String8 string_table; } COFF_ArchiveFirstMember; typedef struct COFF_ArchiveSecondMember { U32 member_count; U32 symbol_count; U64 member_offset_count; U32 *member_offsets; U64 symbol_index_count; U16 *symbol_indices; String8 string_table; } COFF_ArchiveSecondMember; typedef struct COFF_ArchiveMemberNode { struct COFF_ArchiveMemberNode *next; COFF_ArchiveMember data; } COFF_ArchiveMemberNode; typedef struct COFF_ArchiveMemberList { U64 count; COFF_ArchiveMemberNode *first; COFF_ArchiveMemberNode *last; } COFF_ArchiveMemberList; typedef struct COFF_ArchiveParse { B32 has_second_header; B32 has_long_names; COFF_ArchiveFirstMember first_member; COFF_ArchiveSecondMember second_member; String8 long_names; String8 error; } COFF_ArchiveParse; //////////////////////////////// // Obj Header internal B32 coff_is_big_obj(String8 raw_coff); internal B32 coff_is_obj (String8 raw_coff); internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff); //////////////////////////////// // Section internal COFF_SectionHeader ** coff_section_table_from_data(Arena *arena, String8 data, Rng1U64 section_table_range); //////////////////////////////// // Symbol internal COFF_ParsedSymbol coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32); internal COFF_ParsedSymbol coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16); internal COFF_ParsedSymbol coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx); internal COFF_Symbol32Array coff_symbol_array_from_data_16(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count); internal COFF_Symbol32Array coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count); internal COFF_Symbol32Array coff_symbol_array_from_data (Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count, U64 symbol_size); internal COFF_Symbol16Node *coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol); internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class); internal COFF_SymbolValueInterpType coff_interp_from_parsed_symbol(COFF_ParsedSymbol symbol); internal B32 coff_is_undefined_data_symbol(COFF_ParsedSymbol symbol); internal void coff_parse_secdef(COFF_ParsedSymbol symbol, B32 is_big_obj, COFF_ComdatSelectType *selection_out, U32 *number_out, U32 *length_out, U32 *check_sum_out); internal COFF_SymbolWeakExt * coff_parse_weak_tag(COFF_ParsedSymbol symbol, B32 is_big_obj); //////////////////////////////// // Reloc internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header); //////////////////////////////// // Resource internal String8 coff_resource_string_from_str16 (Arena *arena, String16 string); internal String8 coff_resource_string_from_str8 (Arena *arena, String8 string); internal String8 coff_resource_number_from_u16 (Arena *arena, U16 number); internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID16 *id_16); internal U64 coff_read_resource_id_utf16 (String8 raw_res, U64 off, COFF_ResourceID16 *id_out); internal U64 coff_read_resource (Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *res_out); internal COFF_ParsedResourceList coff_resource_list_from_data(Arena *arena, String8 data); internal String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id); internal String8 coff_write_resource (Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data); internal int coff_resource_id_compar(void *raw_a, void *raw_b); // COFF_ResourceID //////////////////////////////// // Archive internal B32 coff_is_import (String8 raw_archive_member); internal COFF_DataType coff_data_type_from_data (String8 raw_archive_member); internal B32 coff_is_regular_archive (String8 raw_archive); internal B32 coff_is_thin_archive (String8 raw_archive); internal COFF_ArchiveType coff_archive_type_from_data(String8 raw_archive); internal U64 coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArchiveMemberHeader *header_out); internal COFF_ArchiveFirstMember coff_parse_first_archive_member (COFF_ArchiveMember *member); internal COFF_ArchiveSecondMember coff_parse_second_archive_member(COFF_ArchiveMember *member); internal String8 coff_decode_raw_member_name (String8 long_names, String8 name); internal String8 coff_decode_member_name (String8 long_names, String8 name); internal U64 coff_parse_import (String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImportHeader *header_out); internal COFF_ArchiveMember coff_archive_member_from_offset(String8 raw_archive, U64 offset); internal COFF_ArchiveMember coff_archive_member_from_data (String8 raw_archive_member); internal COFF_ParsedArchiveImportHeader coff_archive_import_from_data (String8 raw_archive_member); internal U64 coff_regular_archive_member_iter_init(String8 raw_archive); internal B32 coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out); internal U64 coff_thin_archive_member_iter_init(String8 raw_archive); internal B32 coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out); internal COFF_ArchiveParse coff_regular_archive_parse_from_member_list(COFF_ArchiveMemberList list); internal COFF_ArchiveParse coff_thin_archive_parse_from_data (String8 raw_archive); internal COFF_ArchiveParse coff_regular_archive_parse_from_data (String8 raw_archive); internal COFF_ArchiveParse coff_archive_parse_from_data (String8 raw_archive); #endif // COFF_PARSE_H ================================================ FILE: src/config/config_bindings.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal CFG_KeyMap * cfg_key_map_from_cfg(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); CFG_KeyMap *key_map = push_array(arena, CFG_KeyMap, 1); { key_map->name_slots_count = 4096; key_map->name_slots = push_array(arena, CFG_KeyMapSlot, key_map->name_slots_count); key_map->binding_slots_count = 4096; key_map->binding_slots = push_array(arena, CFG_KeyMapSlot, key_map->binding_slots_count); //- rjf: gather & parse all explicitly stored keybinding sets CFG_NodePtrList keybindings_cfg_list = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("keybindings")); for(CFG_NodePtrNode *n = keybindings_cfg_list.first; n != 0; n = n->next) { CFG_Node *keybindings_root = n->v; for(CFG_Node *keybinding = keybindings_root->first; keybinding != &cfg_nil_node; keybinding = keybinding->next) { String8 name = {0}; CFG_Binding binding = {0}; for(CFG_Node *child = keybinding->first; child != &cfg_nil_node; child = child->next) { if(0){} else if(str8_match(child->string, str8_lit("ctrl"), 0)) { binding.modifiers |= OS_Modifier_Ctrl; } else if(str8_match(child->string, str8_lit("alt"), 0)) { binding.modifiers |= OS_Modifier_Alt; } else if(str8_match(child->string, str8_lit("shift"), 0)) { binding.modifiers |= OS_Modifier_Shift; } else { OS_Key key = OS_Key_Null; for EachEnumVal(OS_Key, k) { if(str8_match(child->string, os_g_key_cfg_string_table[k], StringMatchFlag_CaseInsensitive)) { key = k; break; } } if(key != OS_Key_Null) { binding.key = key; } else { name = child->string; } } } if(name.size != 0) { U64 name_hash = d_hash_from_string(name); U64 binding_hash = d_hash_from_string(str8_struct(&binding)); U64 name_slot_idx = name_hash%key_map->name_slots_count; U64 binding_slot_idx = binding_hash%key_map->binding_slots_count; CFG_KeyMapNode *n = push_array(arena, CFG_KeyMapNode, 1); n->cfg_id = keybinding->id; n->name = push_str8_copy(arena, name); n->binding = binding; SLLQueuePush_N(key_map->name_slots[name_slot_idx].first, key_map->name_slots[name_slot_idx].last, n, name_hash_next); SLLQueuePush_N(key_map->binding_slots[binding_slot_idx].first, key_map->binding_slots[binding_slot_idx].last, n, binding_hash_next); } } } } scratch_end(scratch); return key_map; } internal CFG_KeyMapNodePtrList cfg_key_map_node_ptr_list_from_name(Arena *arena, CFG_KeyMap *key_map, String8 string) { CFG_KeyMapNodePtrList list = {0}; { U64 hash = d_hash_from_string(string); U64 slot_idx = hash%key_map->name_slots_count; for(CFG_KeyMapNode *n = key_map->name_slots[slot_idx].first; n != 0; n = n->name_hash_next) { if(str8_match(n->name, string, 0)) { CFG_KeyMapNodePtr *ptr = push_array(arena, CFG_KeyMapNodePtr, 1); ptr->v = n; SLLQueuePush(list.first, list.last, ptr); list.count += 1; } } } return list; } internal CFG_KeyMapNodePtrList cfg_key_map_node_ptr_list_from_binding(Arena *arena, CFG_KeyMap *key_map, CFG_Binding binding) { CFG_KeyMapNodePtrList list = {0}; { U64 hash = d_hash_from_string(str8_struct(&binding)); U64 slot_idx = hash%key_map->binding_slots_count; for(CFG_KeyMapNode *n = key_map->binding_slots[slot_idx].first; n != 0; n = n->binding_hash_next) { if(MemoryMatchStruct(&binding, &n->binding)) { CFG_KeyMapNodePtr *ptr = push_array(arena, CFG_KeyMapNodePtr, 1); ptr->v = n; SLLQueuePush(list.first, list.last, ptr); list.count += 1; } } } return list; } ================================================ FILE: src/config/config_bindings.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CONFIG_BINDINGS_H #define CONFIG_BINDINGS_H typedef struct CFG_Binding CFG_Binding; struct CFG_Binding { OS_Key key; OS_Modifiers modifiers; }; typedef struct CFG_KeyMapNode CFG_KeyMapNode; struct CFG_KeyMapNode { CFG_KeyMapNode *name_hash_next; CFG_KeyMapNode *binding_hash_next; CFG_ID cfg_id; String8 name; CFG_Binding binding; }; typedef struct CFG_KeyMapNodePtr CFG_KeyMapNodePtr; struct CFG_KeyMapNodePtr { CFG_KeyMapNodePtr *next; CFG_KeyMapNode *v; }; typedef struct CFG_KeyMapNodePtrList CFG_KeyMapNodePtrList; struct CFG_KeyMapNodePtrList { CFG_KeyMapNodePtr *first; CFG_KeyMapNodePtr *last; U64 count; }; typedef struct CFG_KeyMapSlot CFG_KeyMapSlot; struct CFG_KeyMapSlot { CFG_KeyMapNode *first; CFG_KeyMapNode *last; }; typedef struct CFG_KeyMap CFG_KeyMap; struct CFG_KeyMap { U64 name_slots_count; CFG_KeyMapSlot *name_slots; U64 binding_slots_count; CFG_KeyMapSlot *binding_slots; }; internal CFG_KeyMap *cfg_key_map_from_cfg(Arena *arena); internal CFG_KeyMapNodePtrList cfg_key_map_node_ptr_list_from_name(Arena *arena, CFG_KeyMap *key_map, String8 string); internal CFG_KeyMapNodePtrList cfg_key_map_node_ptr_list_from_binding(Arena *arena, CFG_KeyMap *key_map, CFG_Binding binding); #endif // CONFIG_BINDINGS_H ================================================ FILE: src/config/config_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: ID Functions internal void cfg_id_list_push(Arena *arena, CFG_IDList *list, CFG_ID id) { CFG_IDNode *n = push_array(arena, CFG_IDNode, 1); SLLQueuePush(list->first, list->last, n); list->count += 1; n->v = id; } internal CFG_IDList cfg_id_list_copy(Arena *arena, CFG_IDList *src) { CFG_IDList dst = {0}; for EachNode(n, CFG_IDNode, src->first) { cfg_id_list_push(arena, &dst, n->v); } return dst; } //////////////////////////////// //~ rjf: Node Pointer Data Structure Functions internal void cfg_node_ptr_list_push(Arena *arena, CFG_NodePtrList *list, CFG_Node *node) { CFG_NodePtrNode *n = push_array(arena, CFG_NodePtrNode, 1); DLLPushBack(list->first, list->last, n); list->count += 1; n->v = node; } internal void cfg_node_ptr_list_push_front(Arena *arena, CFG_NodePtrList *list, CFG_Node *node) { CFG_NodePtrNode *n = push_array(arena, CFG_NodePtrNode, 1); DLLPushFront(list->first, list->last, n); list->count += 1; n->v = node; } internal CFG_NodePtrArray cfg_node_ptr_array_from_list(Arena *arena, CFG_NodePtrList *list) { CFG_NodePtrArray array = {0}; array.count = list->count; array.v = push_array_no_zero(arena, CFG_Node *, array.count); { U64 idx = 0; for EachNode(n, CFG_NodePtrNode, list->first) { array.v[idx] = n->v; idx += 1; } } return array; } //////////////////////////////// //~ rjf: Schema Data Structure Functions internal void cfg_schema_table_insert(Arena *arena, CFG_SchemaTable *table, String8 name, MD_Node *schema) { U64 hash = u64_hash_from_str8(name); U64 slot_idx = hash%table->slots_count; CFG_SchemaNode *node = 0; for(CFG_SchemaNode *n = table->slots[slot_idx]; n != 0; n = n->next) { if(str8_match(n->name, name, 0)) { node = n; break; } } if(node == 0) { node = push_array(arena, CFG_SchemaNode, 1); node->name = str8_copy(arena, name); node->schema = schema; SLLStackPush(table->slots[slot_idx], node); } } internal MD_Node * cfg_schema_from_name(CFG_SchemaTable *table, String8 name) { MD_Node *result = &md_nil_node; { U64 hash = u64_hash_from_str8(name); U64 slot_idx = hash%table->slots_count; CFG_SchemaNode *node = 0; for(CFG_SchemaNode *n = table->slots[slot_idx]; n != 0; n = n->next) { if(str8_match(n->name, name, 0)) { result = n->schema; break; } } } return result; } internal MD_NodePtrList cfg_schemas_from_name(Arena *arena, CFG_SchemaTable *table, String8 name) { MD_NodePtrList result = {0}; { Temp scratch = scratch_begin(&arena, 1); String8List tasks = {0}; String8Node seed_task = {0, name}; str8_list_push_node(&tasks, &seed_task); for EachNode(task, String8Node, tasks.first) { MD_Node *schema = cfg_schema_from_name(table, task->string); if(!md_node_is_nil(schema)) { md_node_ptr_list_push_front(arena, &result, schema); for MD_EachNode(tag, schema->first_tag) { if(str8_match(tag->string, str8_lit("inherit"), 0)) { str8_list_push(scratch.arena, &tasks, tag->first->string); } } } } scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: Config Reading Functions //- rjf: context selection internal void cfg_ctx_select(CFG_Ctx *ctx) { cfg_ctx = ctx; } //- rjf: tree navigations internal U64 cfg_change_gen(void) { U64 result = 0; if(cfg_ctx != 0) { result = cfg_ctx->change_gen; } return result; } internal CFG_Node * cfg_node_root(void) { CFG_Node *result = &cfg_nil_node; if(cfg_ctx != 0) { result = cfg_ctx->root; } return result; } internal CFG_Node * cfg_node_from_id(CFG_ID id) { CFG_Node *result = &cfg_nil_node; if(id != 0 && id == cfg_ctx->last_accessed_id && id == cfg_ctx->last_accessed->id) { result = cfg_ctx->last_accessed; } else { U64 hash = u64_hash_from_str8(str8_struct(&id)); U64 slot_idx = hash%cfg_ctx->id_slots_count; for(CFG_NodePtrNode *n = cfg_ctx->id_slots[slot_idx].first; n != 0; n = n->next) { if(n->v->id == id) { result = n->v; break; } } } cfg_ctx->last_accessed_id = id; cfg_ctx->last_accessed = result; return result; } internal CFG_Node * cfg_node_child_from_string(CFG_Node *parent, String8 string) { CFG_Node *child = &cfg_nil_node; if(string.size != 0) { for(CFG_Node *c = parent->first; c != &cfg_nil_node; c = c->next) { if(str8_match(c->string, string, 0)) { child = c; break; } } } return child; } internal CFG_Node * cfg_node_child_from_string_or_parent(CFG_Node *parent, String8 string) { CFG_Node *result = cfg_node_child_from_string(parent, string); if(result == &cfg_nil_node) { result = parent; } return result; } internal CFG_NodePtrList cfg_node_child_list_from_string(Arena *arena, CFG_Node *parent, String8 string) { CFG_NodePtrList result = {0}; for(CFG_Node *child = parent->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, string, 0)) { cfg_node_ptr_list_push(arena, &result, child); } } return result; } internal CFG_NodePtrList cfg_node_top_level_list_from_string(Arena *arena, String8 string) { CFG_NodePtrList result = {0}; for(CFG_Node *bucket = cfg_ctx->root->first; bucket != &cfg_nil_node; bucket = bucket->next) { for(CFG_Node *tln = bucket->first; tln != &cfg_nil_node; tln = tln->next) { if(str8_match(tln->string, string, 0)) { cfg_node_ptr_list_push(arena, &result, tln); } } } return result; } internal CFG_NodeRec cfg_node_rec__depth_first(CFG_Node *root, CFG_Node *node) { CFG_NodeRec rec = {&cfg_nil_node}; if(node->first != &cfg_nil_node) { rec.next = node->first; rec.push_count = 1; } else for(CFG_Node *p = node; p != root; p = p->parent, rec.pop_count += 1) { if(p->next != &cfg_nil_node) { rec.next = p->next; break; } } return rec; } //- rjf: serialization internal String8 cfg_string_from_tree(Arena *arena, CFG_SchemaTable *schema_table, String8 root_path, CFG_Node *root) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; { typedef struct NestTask NestTask; struct NestTask { NestTask *next; CFG_Node *cfg; MD_Node *schema; B32 is_simple; }; NestTask *top_nest_task = 0; CFG_NodeRec rec = {0}; for(CFG_Node *c = root; c != &cfg_nil_node; c = rec.next) { // rjf: look up parent's schemas MD_NodePtrList schemas = {0}; if(top_nest_task != 0) { CFG_Node *parent = top_nest_task->cfg; schemas = cfg_schemas_from_name(scratch.arena, schema_table, parent->string); } // rjf: look up child schema MD_Node *c_schema = &md_nil_node; for(MD_NodePtrNode *n = schemas.first; n != 0 && c_schema == &md_nil_node; n = n->next) { c_schema = md_child_from_string(n->v, c->string, 0); } // rjf: push name of this node if(c->string.size != 0 || c->first == &cfg_nil_node) { // rjf: extract the textualized form for this string (we may need to escape / relativize) String8 c_serialized_string = c->string; { MD_Node *c_schema = &md_nil_node; if(top_nest_task != 0) { c_schema = top_nest_task->schema; } // rjf: paths -> relativize if(!md_node_has_tag(c_schema->first, str8_lit("no_relativize"), 0)) { if(str8_match(c_schema->first->string, str8_lit("path"), 0)) { String8 path_absolute = c->string; String8 path_relative = path_relative_dst_from_absolute_dst_src(arena, path_absolute, root_path); c_serialized_string = path_relative; } else if(str8_match(c_schema->first->string, str8_lit("path_pt"), 0)) { String8 value = c->string; String8TxtPtPair parts = str8_txt_pt_pair_from_string(value); String8 path_relative = path_relative_dst_from_absolute_dst_src(scratch.arena, parts.string, root_path); c_serialized_string = push_str8f(arena, "%S:%I64d:%I64d", path_relative, parts.pt.line, parts.pt.column); } } // rjf: all strings -> escape c_serialized_string = escaped_from_raw_str8(arena, c_serialized_string); } // rjf: generate all strings for this node's string String8List c_name_strings = {0}; { B32 name_can_be_pushed_standalone = 0; { Temp temp = temp_begin(scratch.arena); MD_TokenizeResult c_name_tokenize = md_tokenize_from_text(temp.arena, c_serialized_string); name_can_be_pushed_standalone = (c_name_tokenize.tokens.count == 1 && c_name_tokenize.tokens.v[0].flags & (MD_TokenFlag_Identifier| MD_TokenFlag_Numeric| MD_TokenFlag_StringLiteral| MD_TokenFlag_Symbol)); temp_end(temp); } if(name_can_be_pushed_standalone) { str8_list_push(scratch.arena, &c_name_strings, c_serialized_string); } else { str8_list_push(scratch.arena, &c_name_strings, str8_lit("\"")); str8_list_push(scratch.arena, &c_name_strings, c_serialized_string); str8_list_push(scratch.arena, &c_name_strings, str8_lit("\"")); } } // rjf: if we're in a simple nesting task, then just break children by space if(top_nest_task != 0 && top_nest_task->is_simple) { str8_list_push(scratch.arena, &strings, str8_lit(" ")); } // rjf: join c's strings with main string list str8_list_concat_in_place(&strings, &c_name_strings); } // rjf: grab next recursion rec = cfg_node_rec__depth_first(root, c); // rjf: push a new nesting task before descending to children if(c->first != &cfg_nil_node) { B32 is_simple_children_list = 1; for(CFG_Node *child = c->first; child != &cfg_nil_node; child = child->next) { if(child->first != &cfg_nil_node && child != c->last) { is_simple_children_list = 0; break; } } NestTask *task = push_array(scratch.arena, NestTask, 1); task->cfg = c; task->schema = c_schema; task->is_simple = is_simple_children_list; SLLStackPush(top_nest_task, task); } // rjf: tree navigations -> encode hierarchy if(rec.push_count > 0) { if(top_nest_task->is_simple && c->string.size != 0) { str8_list_push(scratch.arena, &strings, str8_lit(":")); } else { if(c->string.size != 0) { str8_list_push(scratch.arena, &strings, str8_lit(":\n")); } str8_list_push(scratch.arena, &strings, str8_lit("{")); } } else { for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1, SLLStackPop(top_nest_task)) { if(top_nest_task->is_simple) { if(top_nest_task->cfg->string.size == 0) { str8_list_push(scratch.arena, &strings, str8_lit(" }")); } } else { str8_list_push(scratch.arena, &strings, str8_lit("\n}")); } } } if(!top_nest_task || top_nest_task->is_simple == 0) { str8_list_push(scratch.arena, &strings, str8_lit("\n")); } } } String8 result_unindented = str8_list_join(scratch.arena, &strings, 0); String8 result = indented_from_string(arena, result_unindented); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Config Writing Functions //- rjf: state creation / destroying internal CFG_State * cfg_state_alloc(void) { Arena *arena = arena_alloc(); CFG_State *state = push_array(arena, CFG_State, 1); state->arena = arena; state->ctx.id_slots_count = 4096; state->ctx.id_slots = push_array(arena, CFG_NodePtrSlot, state->ctx.id_slots_count); state->ctx.root = cfg_node_alloc(state); return state; } internal void cfg_state_release(CFG_State *state) { arena_release(state->arena); } //- rjf: state -> ctx internal CFG_Ctx * cfg_state_ctx(CFG_State *state) { CFG_Ctx *ctx = &state->ctx; return ctx; } //- rjf: string allocations internal U64 cfg_string_bucket_num_from_size(U64 size) { U64 bucket_num = 0; if(size > 0) { for EachElement(idx, cfg_string_bucket_chunk_sizes) { if(size <= cfg_string_bucket_chunk_sizes[idx]) { bucket_num = idx+1; break; } } } return bucket_num; } internal String8 cfg_string_alloc(CFG_State *state, String8 string) { //- rjf: allocate node CFG_StringChunkNode *node = 0; { U64 bucket_num = cfg_string_bucket_num_from_size(string.size); if(bucket_num == ArrayCount(cfg_string_bucket_chunk_sizes)) { CFG_StringChunkNode *best_node = 0; CFG_StringChunkNode *best_node_prev = 0; U64 best_node_size = max_U64; { for(CFG_StringChunkNode *n = state->free_string_chunks[bucket_num-1], *prev = 0; n != 0; (prev = n, n = n->next)) { if(n->size >= string.size && n->size < best_node_size) { best_node = n; best_node_prev = prev; best_node_size = n->size; } } } if(best_node != 0) { node = best_node; if(best_node_prev) { best_node_prev->next = best_node->next; } else { state->free_string_chunks[bucket_num-1] = best_node->next; } } else { U64 chunk_size = u64_up_to_pow2(string.size); node = (CFG_StringChunkNode *)push_array(state->arena, U8, chunk_size); } } else if(bucket_num != 0) { node = state->free_string_chunks[bucket_num-1]; if(node != 0) { SLLStackPop(state->free_string_chunks[bucket_num-1]); } else { node = (CFG_StringChunkNode *)push_array(state->arena, U8, cfg_string_bucket_chunk_sizes[bucket_num-1]); } } } //- rjf: fill node String8 result = {0}; if(node != 0) { result.str = (U8 *)node; result.size = string.size; MemoryCopy(result.str, string.str, result.size); } return result; } internal void cfg_string_release(CFG_State *state, String8 string) { U64 bucket_num = cfg_string_bucket_num_from_size(string.size); if(1 <= bucket_num && bucket_num <= ArrayCount(cfg_string_bucket_chunk_sizes)) { U64 bucket_idx = bucket_num-1; CFG_StringChunkNode *node = (CFG_StringChunkNode *)string.str; SLLStackPush(state->free_string_chunks[bucket_idx], node); node->size = u64_up_to_pow2(string.size); } } //- rjf: tree building internal CFG_Node * cfg_node_alloc(CFG_State *state) { state->ctx.change_gen += 1; // rjf: allocate CFG_Node *result = state->free; { if(result) { SLLStackPop(state->free); } else { result = push_array_no_zero(state->arena, CFG_Node, 1); } } // rjf: generate ID & fill state->id_gen += 1; MemoryZeroStruct(result); result->first = result->last = result->next = result->prev = result->parent = &cfg_nil_node; result->id = state->id_gen; // rjf: store to ID -> cfg map { CFG_NodePtrNode *cfg_id_node = state->free_id_node; if(cfg_id_node != 0) { SLLStackPop(state->free_id_node); } else { cfg_id_node = push_array(state->arena, CFG_NodePtrNode, 1); } U64 hash = u64_hash_from_str8(str8_struct(&result->id)); U64 slot_idx = hash%state->ctx.id_slots_count; DLLPushBack(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, cfg_id_node); cfg_id_node->v = result; } return result; } internal void cfg_node_release(CFG_State *state, CFG_Node *node) { state->ctx.change_gen += 1; Temp scratch = scratch_begin(0, 0); // rjf: unhook from context cfg_node_unhook(state, node->parent, node); // rjf: gather root & all descendants CFG_NodePtrList nodes = {0}; for(CFG_Node *c = node; c != &cfg_nil_node; c = cfg_node_rec__depth_first(node, c).next) { cfg_node_ptr_list_push(scratch.arena, &nodes, c); } // rjf: release all nodes for(CFG_NodePtrNode *n = nodes.first; n != 0; n = n->next) { CFG_Node *c = n->v; cfg_string_release(state, c->string); SLLStackPush(state->free, c); c->first = c->last = c->prev = c->parent = 0; c->id = 0; c->string = str8_zero(); U64 hash = u64_hash_from_str8(str8_struct(&c->id)); U64 slot_idx = hash%state->ctx.id_slots_count; for(CFG_NodePtrNode *n = state->ctx.id_slots[slot_idx].first; n != 0; n = n->next) { if(n->v == c) { DLLRemove(state->ctx.id_slots[slot_idx].first, state->ctx.id_slots[slot_idx].last, n); SLLStackPush(state->free_id_node, n); break; } } } scratch_end(scratch); } internal void cfg_node_release_all_children(CFG_State *state, CFG_Node *node) { for(CFG_Node *child = node->first, *next = &cfg_nil_node; child != &cfg_nil_node; child = next) { next = child->next; cfg_node_release(state, child); } } internal CFG_Node * cfg_node_new(CFG_State *state, CFG_Node *parent, String8 string) { CFG_Node *node = cfg_node_alloc(state); cfg_node_insert_child(state, parent, parent->last, node); cfg_node_equip_string(state, node, string); return node; } internal CFG_Node * cfg_node_newf(CFG_State *state, CFG_Node *parent, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); CFG_Node *result = cfg_node_new(state, parent, string); va_end(args); scratch_end(scratch); return result; } internal CFG_Node * cfg_node_new_replace(CFG_State *state, CFG_Node *parent, String8 string) { Temp scratch = scratch_begin(0, 0); string = push_str8_copy(scratch.arena, string); for(CFG_Node *child = parent->first->next, *next = &cfg_nil_node; child != &cfg_nil_node; child = next) { next = child->next; cfg_node_release(state, child); } if(parent->first == &cfg_nil_node) { cfg_node_new(state, parent, str8_zero()); } CFG_Node *child = parent->first; cfg_node_equip_string(state, child, string); scratch_end(scratch); return child; } internal CFG_Node * cfg_node_new_replacef(CFG_State *state, CFG_Node *parent, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); CFG_Node *result = cfg_node_new_replace(state, parent, string); va_end(args); scratch_end(scratch); return result; } internal CFG_Node * cfg_node_deep_copy(CFG_State *state, CFG_Node *src_root) { CFG_NodeRec rec = {0}; CFG_Node *dst_root = &cfg_nil_node; CFG_Node *dst_parent = &cfg_nil_node; for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next) { CFG_Node *dst = cfg_node_new(state, dst_parent, src->string); if(dst_root == &cfg_nil_node) { dst_root = dst; } rec = cfg_node_rec__depth_first(src_root, src); if(rec.push_count > 0) { dst_parent = dst; } else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1) { dst_parent = dst_parent->parent; } } return dst_root; } internal void cfg_node_equip_string(CFG_State *state, CFG_Node *node, String8 string) { cfg_string_release(state, node->string); node->string = cfg_string_alloc(state, string); state->ctx.change_gen += 1; } internal void cfg_node_equip_stringf(CFG_State *state, CFG_Node *node, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); cfg_node_equip_string(state, node, string); va_end(args); scratch_end(scratch); } internal void cfg_node_insert_child(CFG_State *state, CFG_Node *parent, CFG_Node *prev_child, CFG_Node *new_child) { if(parent != &cfg_nil_node) { if(new_child->parent != &cfg_nil_node) { cfg_node_unhook(state, new_child->parent, new_child); } DLLInsert_NPZ(&cfg_nil_node, parent->first, parent->last, prev_child, new_child, next, prev); new_child->parent = parent; } } internal void cfg_node_unhook(CFG_State *state, CFG_Node *parent, CFG_Node *child) { if(child != &cfg_nil_node && parent == child->parent && parent != &cfg_nil_node) { DLLRemove_NPZ(&cfg_nil_node, parent->first, parent->last, child, next, prev); child->parent = &cfg_nil_node; } } internal CFG_Node * cfg_node_child_from_string_or_alloc(CFG_State *state, CFG_Node *parent, String8 string) { CFG_Node *node = cfg_node_child_from_string(parent, string); if(node == &cfg_nil_node) { node = cfg_node_new(state, parent, string); } return node; } //- rjf: deserialization internal CFG_NodePtrList cfg_node_ptr_list_from_string(Arena *arena, CFG_State *state, CFG_SchemaTable *schema_table, String8 root_path, String8 string) { CFG_NodePtrList result = {0}; Temp scratch = scratch_begin(&arena, 1); //- rjf: parse the string as metadesk MD_Node *root = md_tree_from_string(scratch.arena, string); //- rjf: iterate the top-level metadesk trees, generate new cfg trees for each for MD_EachNode(tln, root->first) { CFG_Node *dst_root_n = &cfg_nil_node; CFG_Node *dst_active_parent_n = &cfg_nil_node; MD_NodeRec rec = {0}; for(MD_Node *src_n = tln; !md_node_is_nil(src_n); src_n = rec.next) { // rjf: lookup schema for this string MD_Node *schema = &md_nil_node; { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, schema_table, dst_active_parent_n->parent->string); for(MD_NodePtrNode *n = schemas.first; n != 0 && schema == &md_nil_node; n = n->next) { schema = md_child_from_string(n->v, dst_active_parent_n->string, 0); } } // rjf: extract & transform metadesk node's string (it is raw textual data, so we need to // go escaped -> raw, and derelativize paths) String8 dst_n_string = {0}; { String8 src_n_string = src_n->string; String8 src_n_string__raw = raw_from_escaped_str8(scratch.arena, src_n_string); if(!md_node_has_tag(schema->first, str8_lit("no_relativize"), 0)) { if(str8_match(schema->first->string, str8_lit("path"), 0)) { src_n_string__raw = path_absolute_dst_from_relative_dst_src(scratch.arena, src_n_string__raw, root_path); } else if(str8_match(schema->first->string, str8_lit("path_pt"), 0)) { String8TxtPtPair parts = str8_txt_pt_pair_from_string(src_n_string__raw); src_n_string__raw = push_str8f(scratch.arena, "%S:%I64d:%I64d", path_absolute_dst_from_relative_dst_src(scratch.arena, parts.string, root_path), parts.pt.line, parts.pt.column); } } dst_n_string = src_n_string__raw; } // rjf: allocate, fill, & insert new cfg for this metadesk node CFG_Node *dst_n = cfg_node_alloc(state); cfg_node_equip_string(state, dst_n, dst_n_string); if(dst_active_parent_n != &cfg_nil_node) { cfg_node_insert_child(state, dst_active_parent_n, dst_active_parent_n->last, dst_n); } // rjf: recurse rec = md_node_rec_depth_first_pre(src_n, tln); if(dst_active_parent_n == &cfg_nil_node) { dst_root_n = dst_n; } if(rec.push_count > 0) { dst_active_parent_n = dst_n; } else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1) { dst_active_parent_n = dst_active_parent_n->parent; } } cfg_node_ptr_list_push(arena, &result, dst_root_n); } scratch_end(scratch); return result; } ================================================ FILE: src/config/config_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CONFIG_CORE_H #define CONFIG_CORE_H //////////////////////////////// //~ rjf: IDs typedef U64 CFG_ID; typedef struct CFG_IDNode CFG_IDNode; struct CFG_IDNode { CFG_IDNode *next; CFG_ID v; }; typedef struct CFG_IDList CFG_IDList; struct CFG_IDList { CFG_IDNode *first; CFG_IDNode *last; U64 count; }; //////////////////////////////// //~ rjf: Tree Types typedef struct CFG_Node CFG_Node; struct CFG_Node { CFG_Node *first; CFG_Node *last; CFG_Node *next; CFG_Node *prev; CFG_Node *parent; CFG_ID id; String8 string; }; typedef struct CFG_NodePtrNode CFG_NodePtrNode; struct CFG_NodePtrNode { CFG_NodePtrNode *next; CFG_NodePtrNode *prev; CFG_Node *v; }; typedef struct CFG_NodePtrSlot CFG_NodePtrSlot; struct CFG_NodePtrSlot { CFG_NodePtrNode *first; CFG_NodePtrNode *last; }; typedef struct CFG_NodePtrList CFG_NodePtrList; struct CFG_NodePtrList { CFG_NodePtrNode *first; CFG_NodePtrNode *last; U64 count; }; typedef struct CFG_NodePtrArray CFG_NodePtrArray; struct CFG_NodePtrArray { CFG_Node **v; U64 count; }; typedef struct CFG_NodeRec CFG_NodeRec; struct CFG_NodeRec { CFG_Node *next; S32 push_count; S32 pop_count; }; //////////////////////////////// //~ rjf: String Allocator read_only global U64 cfg_string_bucket_chunk_sizes[] = { 16, 64, 256, 1024, 4096, 16384, 65536, 0xffffffffffffffffull, }; typedef struct CFG_StringChunkNode CFG_StringChunkNode; struct CFG_StringChunkNode { CFG_StringChunkNode *next; U64 size; }; //////////////////////////////// //~ rjf: Config State Bundles typedef struct CFG_Ctx CFG_Ctx; struct CFG_Ctx { CFG_Node *root; U64 id_slots_count; CFG_NodePtrSlot *id_slots; U64 change_gen; CFG_ID last_accessed_id; CFG_Node *last_accessed; }; typedef struct CFG_State CFG_State; struct CFG_State { Arena *arena; CFG_Node *free; CFG_NodePtrNode *free_id_node; CFG_StringChunkNode *free_string_chunks[ArrayCount(cfg_string_bucket_chunk_sizes)]; U64 id_gen; CFG_Ctx ctx; }; //////////////////////////////// //~ rjf: Schema Table typedef struct CFG_SchemaNode CFG_SchemaNode; struct CFG_SchemaNode { CFG_SchemaNode *next; String8 name; MD_Node *schema; }; typedef struct CFG_SchemaTable CFG_SchemaTable; struct CFG_SchemaTable { CFG_SchemaNode **slots; U64 slots_count; }; //////////////////////////////// //~ rjf: Globals read_only global CFG_Node cfg_nil_node = { &cfg_nil_node, &cfg_nil_node, &cfg_nil_node, &cfg_nil_node, &cfg_nil_node, }; thread_static CFG_Ctx *cfg_ctx = 0; //////////////////////////////// //~ rjf: ID Functions internal void cfg_id_list_push(Arena *arena, CFG_IDList *list, CFG_ID id); internal CFG_IDList cfg_id_list_copy(Arena *arena, CFG_IDList *src); //////////////////////////////// //~ rjf: Node Pointer Data Structure Functions internal void cfg_node_ptr_list_push(Arena *arena, CFG_NodePtrList *list, CFG_Node *node); internal void cfg_node_ptr_list_push_front(Arena *arena, CFG_NodePtrList *list, CFG_Node *node); #define cfg_node_ptr_list_first(list) ((list)->count ? (list)->first->v : &cfg_nil_node) #define cfg_node_ptr_list_last(list) ((list)->count ? (list)->last->v : &cfg_nil_node) internal CFG_NodePtrArray cfg_node_ptr_array_from_list(Arena *arena, CFG_NodePtrList *list); //////////////////////////////// //~ rjf: Schema Data Structure Functions internal void cfg_schema_table_insert(Arena *arena, CFG_SchemaTable *table, String8 name, MD_Node *schema); internal MD_Node *cfg_schema_from_name(CFG_SchemaTable *table, String8 name); internal MD_NodePtrList cfg_schemas_from_name(Arena *arena, CFG_SchemaTable *table, String8 name); //////////////////////////////// //~ rjf: Config Reading Functions //- rjf: context selection internal void cfg_ctx_select(CFG_Ctx *ctx); //- rjf: tree navigations internal U64 cfg_change_gen(void); internal CFG_Node *cfg_node_root(void); internal CFG_Node *cfg_node_from_id(CFG_ID id); internal CFG_Node *cfg_node_child_from_string(CFG_Node *parent, String8 string); internal CFG_Node *cfg_node_child_from_string_or_parent(CFG_Node *parent, String8 string); internal CFG_NodePtrList cfg_node_child_list_from_string(Arena *arena, CFG_Node *parent, String8 string); internal CFG_NodePtrList cfg_node_top_level_list_from_string(Arena *arena, String8 string); internal CFG_NodeRec cfg_node_rec__depth_first(CFG_Node *root, CFG_Node *node); //- rjf: serialization internal String8 cfg_string_from_tree(Arena *arena, CFG_SchemaTable *schema_table, String8 root_path, CFG_Node *root); //////////////////////////////// //~ rjf: Config Writing Functions //- rjf: state creation / destroying internal CFG_State *cfg_state_alloc(void); internal void cfg_state_release(CFG_State *state); //- rjf: state -> ctx internal CFG_Ctx *cfg_state_ctx(CFG_State *state); //- rjf: string allocations internal U64 cfg_string_bucket_num_from_size(U64 size); internal String8 cfg_string_alloc(CFG_State *state, String8 string); internal void cfg_string_release(CFG_State *state, String8 string); //- rjf: tree building internal CFG_Node *cfg_node_alloc(CFG_State *state); internal void cfg_node_release(CFG_State *state, CFG_Node *node); internal void cfg_node_release_all_children(CFG_State *state, CFG_Node *node); internal CFG_Node *cfg_node_new(CFG_State *state, CFG_Node *parent, String8 string); internal CFG_Node *cfg_node_newf(CFG_State *state, CFG_Node *parent, char *fmt, ...); internal CFG_Node *cfg_node_new_replace(CFG_State *state, CFG_Node *parent, String8 string); internal CFG_Node *cfg_node_new_replacef(CFG_State *state, CFG_Node *parent, char *fmt, ...); internal CFG_Node *cfg_node_deep_copy(CFG_State *state, CFG_Node *src_root); internal void cfg_node_equip_string(CFG_State *state, CFG_Node *node, String8 string); internal void cfg_node_equip_stringf(CFG_State *state, CFG_Node *node, char *fmt, ...); internal void cfg_node_insert_child(CFG_State *state, CFG_Node *parent, CFG_Node *prev_child, CFG_Node *new_child); internal void cfg_node_unhook(CFG_State *state, CFG_Node *parent, CFG_Node *child); internal CFG_Node *cfg_node_child_from_string_or_alloc(CFG_State *state, CFG_Node *parent, String8 string); //- rjf: deserialization internal CFG_NodePtrList cfg_node_ptr_list_from_string(Arena *arena, CFG_State *state, CFG_SchemaTable *schema_table, String8 root_path, String8 string); #endif // CONFIG_CORE_H ================================================ FILE: src/config/config_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "config_core.c" #include "config_panels.c" #if defined(OS_GFX_H) # include "config_bindings.c" #endif ================================================ FILE: src/config/config_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CONFIG_INC_H #define CONFIG_INC_H #include "config_core.h" #include "config_panels.h" #if defined(OS_GFX_H) # include "config_bindings.h" #endif #endif // CONFIG_INC_H ================================================ FILE: src/config/config_panels.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal CFG_Node * cfg_window_from_cfg(CFG_Node *cfg) { CFG_Node *result = &cfg_nil_node; for(CFG_Node *c = cfg; c != &cfg_nil_node; c = c->parent) { if(c->parent->parent == cfg_node_root() && str8_match(c->string, str8_lit("window"), 0)) { result = c; break; } } return result; } internal CFG_PanelTree cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root) { Temp scratch = scratch_begin(&arena, 1); CFG_Node *wcfg = cfg_window_from_cfg(cfg_root); CFG_Node *src_root = cfg_node_child_from_string(wcfg, str8_lit("panels")); CFG_PanelNode *dst_root = &cfg_nil_panel_node; CFG_PanelNode *dst_focused = &cfg_nil_panel_node; { Axis2 active_split_axis = cfg_node_child_from_string(wcfg, str8_lit("split_x")) != &cfg_nil_node ? Axis2_X : Axis2_Y; CFG_NodeRec rec = {0}; CFG_PanelNode *dst_active_parent = &cfg_nil_panel_node; for(CFG_Node *src = src_root; src != &cfg_nil_node; src = rec.next) { // rjf: build a panel node CFG_PanelNode *dst = push_array(arena, CFG_PanelNode, 1); MemoryCopyStruct(dst, &cfg_nil_panel_node); dst->parent = dst_active_parent; if(dst_active_parent != &cfg_nil_panel_node) { DLLPushBack_NPZ(&cfg_nil_panel_node, dst_active_parent->first, dst_active_parent->last, dst, next, prev); dst_active_parent->child_count += 1; } if(dst_root == &cfg_nil_panel_node) { dst_root = dst; } // rjf: extract cfg info B32 panel_has_children = 0; dst->cfg = src; dst->pct_of_parent = (src == src_root ? 1.f : (F32)f64_from_str8(src->string)); dst->tab_side = (cfg_node_child_from_string(src, str8_lit("tabs_on_bottom")) != &cfg_nil_node ? Side_Max : Side_Min); dst->split_axis = active_split_axis; for(CFG_Node *src_child = src->first; src_child != &cfg_nil_node; src_child = src_child->next) { MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_child->string); if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric) { panel_has_children = 1; } else if(str8_match(src_child->string, str8_lit("tabs_on_bottom"), 0)) { // NOTE(rjf): skip - this is a panel option. } else if(str8_match(src_child->string, str8_lit("selected"), 0)) { dst_focused = dst; } else if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Identifier) { cfg_node_ptr_list_push(arena, &dst->tabs, src_child); if(cfg_node_child_from_string(src_child, str8_lit("selected")) != &cfg_nil_node) { dst->selected_tab = src_child; } } } // rjf: recurse rec = cfg_node_rec__depth_first(src_root, src); if(!panel_has_children) { MemoryZeroStruct(&rec); rec.next = &cfg_nil_node; for(CFG_Node *p = src; p != src_root && p != &cfg_nil_node; p = p->parent, rec.pop_count += 1) { if(p->next != &cfg_nil_node) { rec.next = p->next; break; } } } if(rec.push_count > 0) { dst_active_parent = dst; active_split_axis = axis2_flip(active_split_axis); } else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1) { dst_active_parent = dst_active_parent->parent; active_split_axis = axis2_flip(active_split_axis); } } } scratch_end(scratch); CFG_PanelTree tree = {dst_root, dst_focused}; return tree; } internal CFG_PanelNodeRec cfg_panel_node_rec__depth_first(CFG_PanelNode *root, CFG_PanelNode *panel, U64 sib_off, U64 child_off) { CFG_PanelNodeRec rec = {&cfg_nil_panel_node}; if(*MemberFromOffset(CFG_PanelNode **, panel, child_off) != &cfg_nil_panel_node) { rec.next = *MemberFromOffset(CFG_PanelNode **, panel, child_off); rec.push_count += 1; } else for(CFG_PanelNode *p = panel; p != &cfg_nil_panel_node && p != root; p = p->parent, rec.pop_count += 1) { if(*MemberFromOffset(CFG_PanelNode **, p, sib_off) != &cfg_nil_panel_node) { rec.next = *MemberFromOffset(CFG_PanelNode **, p, sib_off); break; } } return rec; } internal CFG_PanelNode * cfg_panel_node_from_tree_cfg(CFG_PanelNode *root, CFG_Node *cfg) { CFG_PanelNode *result = &cfg_nil_panel_node; for(CFG_PanelNode *p = root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(root, p).next) { if(p->cfg == cfg) { result = p; break; } } return result; } internal Rng2F32 cfg_target_rect_from_panel_node_child(Rng2F32 parent_rect, CFG_PanelNode *parent, CFG_PanelNode *panel) { Rng2F32 rect = parent_rect; if(parent != &cfg_nil_panel_node) { Vec2F32 parent_rect_size = dim_2f32(parent_rect); Axis2 axis = parent->split_axis; rect.p1.v[axis] = rect.p0.v[axis]; for(CFG_PanelNode *child = parent->first; child != &cfg_nil_panel_node; child = child->next) { rect.p1.v[axis] += parent_rect_size.v[axis] * child->pct_of_parent; if(child == panel) { break; } rect.p0.v[axis] = rect.p1.v[axis]; } //rect.p0.v[axis] += parent_rect_size.v[axis] * panel->off_pct_of_parent.v[axis]; //rect.p0.v[axis2_flip(axis)] += parent_rect_size.v[axis2_flip(axis)] * panel->off_pct_of_parent.v[axis2_flip(axis)]; } rect.x0 = round_f32(rect.x0); rect.x1 = round_f32(rect.x1); rect.y0 = round_f32(rect.y0); rect.y1 = round_f32(rect.y1); return rect; } internal Rng2F32 cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_PanelNode *panel) { Temp scratch = scratch_begin(0, 0); // rjf: count ancestors U64 ancestor_count = 0; for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent) { ancestor_count += 1; } // rjf: gather ancestors CFG_PanelNode **ancestors = push_array(scratch.arena, CFG_PanelNode *, ancestor_count); { U64 ancestor_idx = 0; for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent) { ancestors[ancestor_idx] = p; ancestor_idx += 1; } } // rjf: go from highest ancestor => panel and calculate rect Rng2F32 parent_rect = root_rect; for(S64 ancestor_idx = (S64)ancestor_count-1; 0 <= ancestor_idx && ancestor_idx < ancestor_count; ancestor_idx -= 1) { CFG_PanelNode *ancestor = ancestors[ancestor_idx]; CFG_PanelNode *parent = ancestor->parent; if(parent != &cfg_nil_panel_node) { parent_rect = cfg_target_rect_from_panel_node_child(parent_rect, parent, ancestor); } } // rjf: calculate final rect Rng2F32 rect = cfg_target_rect_from_panel_node_child(parent_rect, panel->parent, panel); scratch_end(scratch); return rect; } ================================================ FILE: src/config/config_panels.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CONFIG_PANELS_H #define CONFIG_PANELS_H typedef struct CFG_PanelNode CFG_PanelNode; struct CFG_PanelNode { // rjf: links data CFG_PanelNode *first; CFG_PanelNode *last; CFG_PanelNode *next; CFG_PanelNode *prev; CFG_PanelNode *parent; U64 child_count; CFG_Node *cfg; // rjf: split data Axis2 split_axis; F32 pct_of_parent; // rjf: tab params Side tab_side; // rjf: which tabs are attached CFG_NodePtrList tabs; CFG_Node *selected_tab; }; typedef struct CFG_PanelTree CFG_PanelTree; struct CFG_PanelTree { CFG_PanelNode *root; CFG_PanelNode *focused; }; typedef struct CFG_PanelNodeRec CFG_PanelNodeRec; struct CFG_PanelNodeRec { CFG_PanelNode *next; S32 push_count; S32 pop_count; }; read_only global CFG_PanelNode cfg_nil_panel_node = { &cfg_nil_panel_node, &cfg_nil_panel_node, &cfg_nil_panel_node, &cfg_nil_panel_node, &cfg_nil_panel_node, 0, &cfg_nil_node, .selected_tab = &cfg_nil_node, }; internal CFG_Node *cfg_window_from_cfg(CFG_Node *cfg); internal CFG_PanelTree cfg_panel_tree_from_cfg(Arena *arena, CFG_Node *cfg_root); internal CFG_PanelNodeRec cfg_panel_node_rec__depth_first(CFG_PanelNode *root, CFG_PanelNode *panel, U64 sib_off, U64 child_off); #define cfg_panel_node_rec__depth_first_pre(root, p) cfg_panel_node_rec__depth_first((root), (p), OffsetOf(CFG_PanelNode, next), OffsetOf(CFG_PanelNode, first)) #define cfg_panel_node_rec__depth_first_pre_rev(root, p) cfg_panel_node_rec__depth_first((root), (p), OffsetOf(CFG_PanelNode, prev), OffsetOf(CFG_PanelNode, last)) internal CFG_PanelNode *cfg_panel_node_from_tree_cfg(CFG_PanelNode *root, CFG_Node *cfg); internal Rng2F32 cfg_target_rect_from_panel_node_child(Rng2F32 parent_rect, CFG_PanelNode *parent, CFG_PanelNode *panel); internal Rng2F32 cfg_target_rect_from_panel_node(Rng2F32 root_rect, CFG_PanelNode *root, CFG_PanelNode *panel); #endif // CONFIG_PANELS_H ================================================ FILE: src/content/content.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0x684123ff //////////////////////////////// //~ rjf: Basic Helpers internal C_ID c_id_make(U64 u64_0, U64 u64_1) { C_ID id; id.u128[0].u64[0] = u64_0; id.u128[0].u64[1] = u64_1; return id; } internal B32 c_id_match(C_ID a, C_ID b) { B32 result = MemoryMatchStruct(&a, &b); return result; } internal C_Key c_key_make(C_Root root, C_ID id) { C_Key key = {root, 0, id}; return key; } internal B32 c_key_match(C_Key a, C_Key b) { return (MemoryMatchStruct(&a.root, &b.root) && c_id_match(a.id, b.id)); } //////////////////////////////// //~ rjf: Main Layer Initialization internal void c_init(void) { Arena *arena = arena_alloc(); c_shared = push_array(arena, C_Shared, 1); c_shared->arena = arena; c_shared->blob_slots_count = 16384; c_shared->blob_stripes_count = Min(c_shared->blob_slots_count, os_get_system_info()->logical_processor_count); c_shared->blob_slots = push_array(arena, C_BlobSlot, c_shared->blob_slots_count); c_shared->blob_stripes = push_array(arena, C_Stripe, c_shared->blob_stripes_count); c_shared->blob_stripes_free_nodes = push_array(arena, C_BlobNode *, c_shared->blob_stripes_count); for(U64 idx = 0; idx < c_shared->blob_stripes_count; idx += 1) { C_Stripe *stripe = &c_shared->blob_stripes[idx]; stripe->arena = arena_alloc(); stripe->rw_mutex = rw_mutex_alloc(); stripe->cv = cond_var_alloc(); } c_shared->key_slots_count = 4096; c_shared->key_stripes_count = Min(c_shared->key_slots_count, os_get_system_info()->logical_processor_count); c_shared->key_slots = push_array(arena, C_KeySlot, c_shared->key_slots_count); c_shared->key_stripes = push_array(arena, C_Stripe, c_shared->key_stripes_count); c_shared->key_stripes_free_nodes = push_array(arena, C_KeyNode *, c_shared->key_stripes_count); for(U64 idx = 0; idx < c_shared->key_stripes_count; idx += 1) { C_Stripe *stripe = &c_shared->key_stripes[idx]; stripe->arena = arena_alloc(); stripe->rw_mutex = rw_mutex_alloc(); stripe->cv = cond_var_alloc(); } c_shared->root_slots_count = 4096; c_shared->root_stripes_count = Min(c_shared->root_slots_count, os_get_system_info()->logical_processor_count); c_shared->root_slots = push_array(arena, C_RootSlot, c_shared->root_slots_count); c_shared->root_stripes = push_array(arena, C_Stripe, c_shared->root_stripes_count); c_shared->root_stripes_free_nodes = push_array(arena, C_RootNode *, c_shared->root_stripes_count); for(U64 idx = 0; idx < c_shared->root_stripes_count; idx += 1) { C_Stripe *stripe = &c_shared->root_stripes[idx]; stripe->arena = arena_alloc(); stripe->rw_mutex = rw_mutex_alloc(); stripe->cv = cond_var_alloc(); } } //////////////////////////////// //~ rjf: Root Allocation/Deallocation internal C_Root c_root_alloc(void) { C_Root root = {0}; root.u64[0] = ins_atomic_u64_inc_eval(&c_shared->root_id_gen); U64 slot_idx = root.u64[0]%c_shared->root_slots_count; U64 stripe_idx = slot_idx%c_shared->root_stripes_count; C_RootSlot *slot = &c_shared->root_slots[slot_idx]; C_Stripe *stripe = &c_shared->root_stripes[stripe_idx]; MutexScopeW(stripe->rw_mutex) { C_RootNode *node = c_shared->root_stripes_free_nodes[stripe_idx]; if(node != 0) { SLLStackPop(c_shared->root_stripes_free_nodes[stripe_idx]); } else { node = push_array(stripe->arena, C_RootNode, 1); } DLLPushBack(slot->first, slot->last, node); node->root = root; node->arena = arena_alloc(); } return root; } internal void c_root_release(C_Root root) { //- rjf: unpack root U64 slot_idx = root.u64[0]%c_shared->root_slots_count; U64 stripe_idx = slot_idx%c_shared->root_stripes_count; C_RootSlot *slot = &c_shared->root_slots[slot_idx]; C_Stripe *stripe = &c_shared->root_stripes[stripe_idx]; //- rjf: release root node, grab its arena / ID list Arena *root_arena = 0; C_RootIDChunkList root_ids = {0}; MutexScopeW(stripe->rw_mutex) { for(C_RootNode *n = slot->first; n != 0; n = n->next) { if(MemoryMatchStruct(&root, &n->root)) { DLLRemove(slot->first, slot->last, n); root_arena = n->arena; root_ids = n->ids; SLLStackPush(c_shared->root_stripes_free_nodes[stripe_idx], n); break; } } } //- rjf: release all IDs for(C_RootIDChunkNode *id_chunk_n = root_ids.first; id_chunk_n != 0; id_chunk_n = id_chunk_n->next) { for EachIndex(chunk_idx, id_chunk_n->count) { C_ID id = id_chunk_n->v[chunk_idx]; C_Key key = c_key_make(root, id); c_close_key(key); } } } //////////////////////////////// //~ rjf: Cache Submission internal U128 c_submit_data(C_Key key, Arena **data_arena, String8 data) { //- rjf: unpack key U64 key_hash = u64_hash_from_str8(str8_struct(&key)); U64 key_slot_idx = key_hash%c_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%c_shared->key_stripes_count; C_KeySlot *key_slot = &c_shared->key_slots[key_slot_idx]; C_Stripe *key_stripe = &c_shared->key_stripes[key_stripe_idx]; //- rjf: hash data, unpack hash U128 hash = u128_hash_from_str8(data); U64 slot_idx = hash.u64[1]%c_shared->blob_slots_count; U64 stripe_idx = slot_idx%c_shared->blob_stripes_count; C_BlobSlot *slot = &c_shared->blob_slots[slot_idx]; C_Stripe *stripe = &c_shared->blob_stripes[stripe_idx]; //- rjf: commit to (hash -> data) cache ProfScope("commit to (hash -> data) cache") RWMutexScope(stripe->rw_mutex, 1) { // rjf: find existing node C_BlobNode *node = 0; for(C_BlobNode *n = slot->first; n != 0; n = n->next) { if(u128_match(n->hash, hash)) { node = n; break; } } // rjf: release duplicate data if node already exists if(node != 0 && data_arena != 0 && *data_arena != 0) { arena_release(*data_arena); } // rjf: allocate node if needed if(node == 0) { node = c_shared->blob_stripes_free_nodes[stripe_idx]; if(node) { SLLStackPop(c_shared->blob_stripes_free_nodes[stripe_idx]); } else { node = push_array_no_zero(stripe->arena, C_BlobNode, 1); } MemoryZeroStruct(node); node->hash = hash; if(data_arena != 0) { node->arena = *data_arena; } node->data = data; DLLPushBack(slot->first, slot->last, node); } // rjf: bump key ref count node->key_ref_count += 1; // rjf "steal" arena from caller if(data_arena != 0) { *data_arena = 0; } } //- rjf: commit to (key -> list(hash)) cache U128 key_expired_hash = {0}; ProfScope("commit to (key -> list(hash)) cache") RWMutexScope(key_stripe->rw_mutex, 1) { // rjf: find existing key C_KeyNode *key_node = 0; for(C_KeyNode *n = key_slot->first; n != 0; n = n->next) { if(c_key_match(n->key, key)) { key_node = n; break; } } // rjf: create key node if it doesn't exist B32 key_is_new = 0; if(!key_node) { key_is_new = 1; key_node = c_shared->key_stripes_free_nodes[key_stripe_idx]; if(key_node) { SLLStackPop(c_shared->key_stripes_free_nodes[key_stripe_idx]); } else { key_node = push_array_no_zero(key_stripe->arena, C_KeyNode, 1); } MemoryZeroStruct(key_node); key_node->key = key; DLLPushBack(key_slot->first, key_slot->last, key_node); } // rjf: push hash into key's history if(key_node) { if(key_node->hash_history_gen >= C_KEY_HASH_HISTORY_STRONG_REF_COUNT) { key_expired_hash = key_node->hash_history[(key_node->hash_history_gen-C_KEY_HASH_HISTORY_STRONG_REF_COUNT)%ArrayCount(key_node->hash_history)]; } key_node->hash_history[key_node->hash_history_gen%ArrayCount(key_node->hash_history)] = hash; key_node->hash_history_gen += 1; } // rjf: key is new -> add this key to the associated root if(key_is_new) { U64 root_hash = u64_hash_from_str8(str8_struct(&key.root)); U64 root_slot_idx = root_hash%c_shared->root_slots_count; U64 root_stripe_idx = root_slot_idx%c_shared->root_stripes_count; C_RootSlot *root_slot = &c_shared->root_slots[root_slot_idx]; C_Stripe *root_stripe = &c_shared->root_stripes[root_stripe_idx]; RWMutexScope(root_stripe->rw_mutex, 1) { for(C_RootNode *n = root_slot->first; n != 0; n = n->next) { if(MemoryMatchStruct(&n->root, &key.root)) { C_RootIDChunkNode *chunk = n->ids.last; if(chunk == 0 || chunk->count >= chunk->cap) { chunk = push_array(n->arena, C_RootIDChunkNode, 1); SLLQueuePush(n->ids.first, n->ids.last, chunk); n->ids.chunk_count += 1; chunk->cap = 1024; chunk->v = push_array_no_zero(n->arena, C_ID, chunk->cap); } chunk->v[chunk->count] = key.id; chunk->count += 1; n->ids.total_count += 1; break; } } } } } //- rjf: decrement key ref count of expired hash if(!u128_match(key_expired_hash, u128_zero())) ProfScope("decrement key ref count of expired hash") { U64 old_hash_slot_idx = key_expired_hash.u64[1]%c_shared->blob_slots_count; U64 old_hash_stripe_idx = old_hash_slot_idx%c_shared->blob_stripes_count; C_BlobSlot *old_hash_slot = &c_shared->blob_slots[old_hash_slot_idx]; C_Stripe *old_hash_stripe = &c_shared->blob_stripes[old_hash_stripe_idx]; RWMutexScope(old_hash_stripe->rw_mutex, 0) { for(C_BlobNode *n = old_hash_slot->first; n != 0; n = n->next) { if(u128_match(n->hash, key_expired_hash)) { ins_atomic_u64_dec_eval(&n->key_ref_count); break; } } } } return hash; } //////////////////////////////// //~ rjf: Key Closing internal void c_close_key(C_Key key) { U64 key_hash = u64_hash_from_str8(str8_struct(&key)); U64 key_slot_idx = key_hash%c_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%c_shared->key_stripes_count; C_KeySlot *key_slot = &c_shared->key_slots[key_slot_idx]; C_Stripe *key_stripe = &c_shared->key_stripes[key_stripe_idx]; RWMutexScope(key_stripe->rw_mutex, 1) { for(C_KeyNode *n = key_slot->first; n != 0; n = n->next) { if(c_key_match(n->key, key)) { for(U64 history_idx = 0; history_idx < C_KEY_HASH_HISTORY_STRONG_REF_COUNT && history_idx < n->hash_history_gen; history_idx += 1) { U128 hash = n->hash_history[(n->hash_history_gen-1-history_idx) % ArrayCount(n->hash_history)]; U64 hash_slot_idx = hash.u64[1]%c_shared->blob_slots_count; U64 hash_stripe_idx = hash_slot_idx%c_shared->blob_stripes_count; C_BlobSlot *hash_slot = &c_shared->blob_slots[hash_slot_idx]; C_Stripe *hash_stripe = &c_shared->blob_stripes[hash_stripe_idx]; MutexScopeR(hash_stripe->rw_mutex) { for(C_BlobNode *n = hash_slot->first; n != 0; n = n->next) { if(u128_match(n->hash, hash)) { ins_atomic_u64_dec_eval(&n->key_ref_count); break; } } } } DLLRemove(key_slot->first, key_slot->last, n); SLLStackPush(c_shared->key_stripes_free_nodes[key_stripe_idx], n); break; } } } } //////////////////////////////// //~ rjf: Downstream Accesses internal void c_hash_downstream_inc(U128 hash) { U64 slot_idx = hash.u64[1]%c_shared->blob_slots_count; U64 stripe_idx = slot_idx%c_shared->blob_stripes_count; C_BlobSlot *slot = &c_shared->blob_slots[slot_idx]; C_Stripe *stripe = &c_shared->blob_stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) { for(C_BlobNode *n = slot->first; n != 0; n = n->next) { if(u128_match(hash, n->hash)) { ins_atomic_u64_inc_eval(&n->downstream_ref_count); break; } } } } internal void c_hash_downstream_dec(U128 hash) { U64 slot_idx = hash.u64[1]%c_shared->blob_slots_count; U64 stripe_idx = slot_idx%c_shared->blob_stripes_count; C_BlobSlot *slot = &c_shared->blob_slots[slot_idx]; C_Stripe *stripe = &c_shared->blob_stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) { for(C_BlobNode *n = slot->first; n != 0; n = n->next) { if(u128_match(hash, n->hash)) { ins_atomic_u64_dec_eval(&n->downstream_ref_count); break; } } } } //////////////////////////////// //~ rjf: Cache Lookup internal U128 c_hash_from_key(C_Key key, U64 rewind_count) { U128 result = {0}; U64 key_hash = u64_hash_from_str8(str8_struct(&key)); U64 key_slot_idx = key_hash%c_shared->key_slots_count; U64 key_stripe_idx = key_slot_idx%c_shared->key_stripes_count; C_KeySlot *key_slot = &c_shared->key_slots[key_slot_idx]; C_Stripe *key_stripe = &c_shared->key_stripes[key_stripe_idx]; RWMutexScope(key_stripe->rw_mutex, 0) { for(C_KeyNode *n = key_slot->first; n != 0; n = n->next) { if(c_key_match(n->key, key) && n->hash_history_gen > 0 && n->hash_history_gen-1 >= rewind_count) { result = n->hash_history[(n->hash_history_gen-1-rewind_count)%ArrayCount(n->hash_history)]; break; } } } return result; } internal String8 c_data_from_hash(Access *access, U128 hash) { ProfBeginFunction(); String8 result = {0}; U64 slot_idx = hash.u64[1]%c_shared->blob_slots_count; U64 stripe_idx = slot_idx%c_shared->blob_stripes_count; C_BlobSlot *slot = &c_shared->blob_slots[slot_idx]; C_Stripe *stripe = &c_shared->blob_stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) { for(C_BlobNode *n = slot->first; n != 0; n = n->next) { if(u128_match(n->hash, hash)) { result = n->data; access_touch(access, &n->access_pt, stripe->cv); break; } } } ProfEnd(); return result; } //////////////////////////////// //~ rjf: Asynchronous Tick internal void c_async_tick(void) { ProfBeginFunction(); //- rjf: garbage collect blobs { Rng1U64 range = lane_range(c_shared->blob_slots_count); for EachInRange(slot_idx, range) { U64 stripe_idx = slot_idx%c_shared->blob_stripes_count; C_BlobSlot *slot = &c_shared->blob_slots[slot_idx]; C_Stripe *stripe = &c_shared->blob_stripes[stripe_idx]; for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { B32 slot_has_work = 0; RWMutexScope(stripe->rw_mutex, write_mode) { for(C_BlobNode *n = slot->first, *next = 0; n != 0; n = next) { next = n->next; U64 key_ref_count = ins_atomic_u64_eval(&n->key_ref_count); U64 downstream_ref_count = ins_atomic_u64_eval(&n->downstream_ref_count); if(access_pt_is_expired(&n->access_pt, .time = 5000000) && key_ref_count == 0 && downstream_ref_count == 0) { slot_has_work = 1; if(!write_mode) { break; } else { DLLRemove(slot->first, slot->last, n); SLLStackPush(c_shared->blob_stripes_free_nodes[stripe_idx], n); if(n->arena != 0) { arena_release(n->arena); } } } } } if(!slot_has_work) { break; } } } } ProfEnd(); } ================================================ FILE: src/content/content.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CONTENT_H #define CONTENT_H //////////////////////////////// //~ NOTE(rjf): Hash Store Notes (2025/05/18) // // The hash store is a general-purpose data cache. It offers three layers of // caching: (a) content (hash of data), (b) key (unique identity correllated // with history of hashes), and (c) root (bucket for many keys, manually // allocated / deallocated). // // (a) The "content" level of cache access is a simply hash(data) -> data // mapping. This bypasses all identity/key/root mechanisms and provides a // way to just talk about unique (and deduplicated) blobs of data. // // (b) The "key" level of cache access is used to encode a history of hashes // for some unique "identity", where the "identity" is a concept managed // by the user. One example of an identity would be a particular address // range inside of some process to which the debugger is attached. Another // might be a range inside of some file. // // (c) The "root" level is to provide a top-level allocation/deallocation // mechanism for a large set of keys. It also provides an extra level of // key uniqueness. For instance, each process to which the debugger is // attached might have its own root, and each key might correspond to a // particular address range within that process. This way, when the // process ends, all of its keys can be easily destroyed using a single // deallocation of the root. // // The way this might be generally used inside of the debugger would be that // some evaluation - let's say it's some variable `x` - is mapped (via debug // info) to some address range. If `x` is a `char[4096]`, then it might map // to some address range [&x, &x + 4096). This, together with the process // within which `x` is evaluated, forms both a `root` (for the process) and // a `key` (for the address range). Some asynchronous memory streaming system // can then, together with the root and key, read memory for that range, then // submit that data to the hash store, correllating with the root and key // combo. //////////////////////////////// //~ rjf: Key Types typedef struct C_Root C_Root; struct C_Root { U64 u64[1]; }; typedef struct C_ID C_ID; struct C_ID { U128 u128[1]; }; typedef struct C_Key C_Key; struct C_Key { C_Root root; U64 _padding_; C_ID id; }; //////////////////////////////// //~ rjf: Cache Stripe Type typedef struct C_Stripe C_Stripe; struct C_Stripe { Arena *arena; RWMutex rw_mutex; CondVar cv; }; //////////////////////////////// //~ rjf: Root Cache Types typedef struct C_RootIDChunkNode C_RootIDChunkNode; struct C_RootIDChunkNode { C_RootIDChunkNode *next; C_ID *v; U64 count; U64 cap; }; typedef struct C_RootIDChunkList C_RootIDChunkList; struct C_RootIDChunkList { C_RootIDChunkNode *first; C_RootIDChunkNode *last; U64 chunk_count; U64 total_count; }; typedef struct C_RootNode C_RootNode; struct C_RootNode { C_RootNode *next; C_RootNode *prev; Arena *arena; C_Root root; C_RootIDChunkList ids; }; typedef struct C_RootSlot C_RootSlot; struct C_RootSlot { C_RootNode *first; C_RootNode *last; }; //////////////////////////////// //~ rjf: Key Cache Types #define C_KEY_HASH_HISTORY_COUNT 64 #define C_KEY_HASH_HISTORY_STRONG_REF_COUNT 2 typedef struct C_KeyNode C_KeyNode; struct C_KeyNode { C_KeyNode *next; C_KeyNode *prev; C_Key key; U128 hash_history[C_KEY_HASH_HISTORY_COUNT]; U64 hash_history_gen; }; typedef struct C_KeySlot C_KeySlot; struct C_KeySlot { C_KeyNode *first; C_KeyNode *last; }; //////////////////////////////// //~ rjf: Content Blob Cache Types typedef struct C_BlobNode C_BlobNode; struct C_BlobNode { C_BlobNode *next; C_BlobNode *prev; U128 hash; Arena *arena; String8 data; AccessPt access_pt; U64 key_ref_count; U64 downstream_ref_count; }; typedef struct C_BlobSlot C_BlobSlot; struct C_BlobSlot { C_BlobNode *first; C_BlobNode *last; }; //////////////////////////////// //~ rjf: Shared State typedef struct C_Shared C_Shared; struct C_Shared { Arena *arena; // rjf: main data blob cache U64 blob_slots_count; U64 blob_stripes_count; C_BlobSlot *blob_slots; C_Stripe *blob_stripes; C_BlobNode **blob_stripes_free_nodes; // rjf: key cache U64 key_slots_count; U64 key_stripes_count; C_KeySlot *key_slots; C_Stripe *key_stripes; C_KeyNode **key_stripes_free_nodes; // rjf: root cache U64 root_slots_count; U64 root_stripes_count; C_RootSlot *root_slots; C_Stripe *root_stripes; C_RootNode **root_stripes_free_nodes; U64 root_id_gen; }; //////////////////////////////// //~ rjf: Globals global C_Shared *c_shared = 0; //////////////////////////////// //~ rjf: Basic Helpers internal C_ID c_id_make(U64 u64_0, U64 u64_1); internal B32 c_id_match(C_ID a, C_ID b); internal C_Key c_key_make(C_Root root, C_ID id); internal B32 c_key_match(C_Key a, C_Key b); //////////////////////////////// //~ rjf: Main Layer Initialization internal void c_init(void); //////////////////////////////// //~ rjf: Root Allocation/Deallocation internal C_Root c_root_alloc(void); internal void c_root_release(C_Root root); //////////////////////////////// //~ rjf: Cache Submission internal U128 c_submit_data(C_Key key, Arena **data_arena, String8 data); //////////////////////////////// //~ rjf: Key Closing internal void c_close_key(C_Key key); //////////////////////////////// //~ rjf: Downstream Accesses internal void c_hash_downstream_inc(U128 hash); internal void c_hash_downstream_dec(U128 hash); //////////////////////////////// //~ rjf: Cache Lookups internal U128 c_hash_from_key(C_Key key, U64 rewind_count); internal String8 c_data_from_hash(Access *access, U128 hash); //////////////////////////////// //~ rjf: Asynchronous Tick internal void c_async_tick(void); #endif // CONTENT_H ================================================ FILE: src/ctrl/ctrl.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Entity Kinds @table(name code_name display_string) CTRL_EntityKindTable: { {Root root "Root" } {Machine machine "Machine" } {Process process "Process" } {Thread thread "Thread" } {Module module "Module" } {EntryPoint entry_point "Entry Point" } {DebugInfoPath debug_info_path "Debug Info Path" } {PendingThreadName pending_thread_name "Pending Thread Name" } {PendingThreadColor pending_thread_color "Pending Thread Color" } {Breakpoint breakpoint "Breakpoint" } {AddressRangeAnnotation address_range_annotation "Address Range Annotation" } } @enum CTRL_EntityKind: { Null, @expand(CTRL_EntityKindTable a) `$(a.name)`, COUNT, } @data(String8) ctrl_entity_kind_code_name_table: { `{0}`, @expand(CTRL_EntityKindTable a) `str8_lit_comp("$(a.code_name)")` } @data(String8) ctrl_entity_kind_display_string_table: { `{0}`, @expand(CTRL_EntityKindTable a) `str8_lit_comp("$(a.display_name)")` } //////////////////////////////// //~ rjf: Exception Codes @table(name lower_name code default display_string) CTRL_ExceptionCodeKindTable: { {Win32CtrlC win32_ctrl_c 0x40010005 1 "(Win32) Control-C" } {Win32CtrlBreak win32_ctrl_break 0x40010008 1 "(Win32) Control-Break" } {Win32WinRTOriginateError win32_win_rt_originate_error 0x40080201 0 "(Win32) WinRT Originate Error" } {Win32WinRTTransformError win32_win_rt_transform_error 0x40080202 0 "(Win32) WinRT Transform Error" } {Win32RPCCallCancelled win32_rpc_call_cancelled 0x0000071a 0 "(Win32) RPC Call Cancelled" } {Win32DatatypeMisalignment win32_datatype_misalignment 0x80000002 0 "(Win32) Data Type Misalignment" } {Win32AccessViolation win32_access_violation 0xc0000005 1 "(Win32) Access Violation" } {Win32InPageError win32_in_page_error 0xc0000006 0 "(Win32) In Page Error" } {Win32InvalidHandle win32_invalid_handle 0xc0000008 1 "(Win32) Invalid Handle Specified" } {Win32NotEnoughQuota win32_not_enough_quota 0xc0000017 0 "(Win32) Not Enough Quota" } {Win32IllegalInstruction win32_illegal_instruction 0xc000001d 0 "(Win32) Illegal Instruction" } {Win32CannotContinueException win32_cannot_continue_exception 0xc0000025 0 "(Win32) Cannot Continue From Exception" } {Win32InvalidExceptionDisposition win32_invalid_exception_disposition 0xc0000026 0 "(Win32) Invalid Exception Disposition Returned By Handler" } {Win32ArrayBoundsExceeded win32_array_bounds_exceeded 0xc000008c 0 "(Win32) Array Bounds Exceeded" } {Win32FloatingPointDenormalOperand win32_floating_point_denormal_operand 0xc000008d 0 "(Win32) Floating-Point Denormal Operand" } {Win32FloatingPointDivisionByZero win32_floating_point_division_by_zero 0xc000008e 0 "(Win32) Floating-Point Division By Zero" } {Win32FloatingPointInexactResult win32_floating_point_inexact_result 0xc000008f 0 "(Win32) Floating-Point Inexact Result" } {Win32FloatingPointInvalidOperation win32_floating_point_invalid_operation 0xc0000090 0 "(Win32) Floating-Point Invalid Operation" } {Win32FloatingPointOverflow win32_floating_point_overflow 0xc0000091 0 "(Win32) Floating-Point Overflow" } {Win32FloatingPointStackCheck win32_floating_point_stack_check 0xc0000092 0 "(Win32) Floating-Point Stack Check" } {Win32FloatingPointUnderflow win32_floating_point_underflow 0xc0000093 0 "(Win32) Floating-Point Underflow" } {Win32IntegerDivisionByZero win32_integer_division_by_zero 0xc0000094 0 "(Win32) Integer Division By Zero" } {Win32IntegerOverflow win32_integer_overflow 0xc0000095 0 "(Win32) Integer Overflow" } {Win32PrivilegedInstruction win32_privileged_instruction 0xc0000096 0 "(Win32) Privileged Instruction" } {Win32StackOverflow win32_stack_overflow 0xc00000fd 0 "(Win32) Stack Overflow" } {Win32UnableToLocateDLL win32_unable_to_locate_dll 0xc0000135 0 "(Win32) Unable To Locate DLL" } {Win32OrdinalNotFound win32_ordinal_not_found 0xc0000138 0 "(Win32) Ordinal Not Found" } {Win32EntryPointNotFound win32_entry_point_not_found 0xc0000139 0 "(Win32) Entry Point Not Found" } {Win32DLLInitializationFailed win32_dll_initialization_failed 0xc0000142 0 "(Win32) DLL Initialization Failed" } {Win32FloatingPointSSEMultipleFaults win32_floating_point_sse_multiple_faults 0xc00002b4 0 "(Win32) Floating Point SSE Multiple Faults" } {Win32FloatingPointSSEMultipleTraps win32_floating_point_sse_multiple_traps 0xc00002b5 0 "(Win32) Floating Point SSE Multiple Traps" } {Win32AssertionFailed win32_assertion_failed 0xc0000420 1 "(Win32) Assertion Failed" } {Win32ModuleNotFound win32_module_not_found 0xc06d007e 0 "(Win32) Module Not Found" } {Win32ProcedureNotFound win32_procedure_not_found 0xc06d007f 0 "(Win32) Procedure Not Found" } {Win32SanitizerErrorDetected win32_sanitizer_error_detected 0xe073616e 1 "(Win32) Sanitizer Error Detected" } {Win32SanitizerRawAccessViolation win32_sanitizer_raw_access_violation 0xe0736171 0 "(Win32) Sanitizer Raw Access Violation" } {Win32DirectXDebugLayer win32_directx_debug_layer 0x0000087a 1 "(Win32) DirectX Debug Layer" } } @enum CTRL_ExceptionCodeKind: { Null, @expand(CTRL_ExceptionCodeKindTable a) `$(a.name)`, COUNT, } @data(U32) ctrl_exception_code_kind_code_table: { `0`; @expand(CTRL_ExceptionCodeKindTable a) `$(a.code)`; } @data(String8) ctrl_exception_code_kind_display_string_table: { `{0}`; @expand(CTRL_ExceptionCodeKindTable a) `str8_lit_comp("$(a.display_string)")`; } @data(String8) ctrl_exception_code_kind_lowercase_code_string_table: { `{0}`; @expand(CTRL_ExceptionCodeKindTable a) `str8_lit_comp("$(a.lower_name)")`; } @data(B8) ctrl_exception_code_kind_default_enable_table: { `0`; @expand(CTRL_ExceptionCodeKindTable a) `$(a.default)`; } //////////////////////////////// //~ rjf: Exception Sub-Codes @table(name, value) CTRL_ExceptionSubCodeKindTable: { { W32_FAST_FAIL_LEGACY_GS_VIOLATION 0 } { W32_FAST_FAIL_VTGUARD_CHECK_FAILURE 1 } { W32_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE 2 } { W32_FAST_FAIL_CORRUPT_LIST_ENTRY 3 } { W32_FAST_FAIL_INCORRECT_STACK 4 } { W32_FAST_FAIL_INVALID_ARG 5 } { W32_FAST_FAIL_GS_COOKIE_INIT 6 } { W32_FAST_FAIL_FATAL_APP_EXIT 7 } { W32_FAST_FAIL_RANGE_CHECK_FAILURE 8 } { W32_FAST_FAIL_UNSAFE_REGISTRY_ACCESS 9 } { W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE 10 } { W32_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE 11 } { W32_FAST_FAIL_INVALID_FIBER_SWITCH 12 } { W32_FAST_FAIL_INVALID_SET_OF_CONTEXT 13 } { W32_FAST_FAIL_INVALID_REFERENCE_COUNT 14 } { W32_FAST_FAIL_INVALID_JUMP_BUFFER 18 } { W32_FAST_FAIL_MRDATA_MODIFIED 19 } { W32_FAST_FAIL_CERTIFICATION_FAILURE 20 } { W32_FAST_FAIL_INVALID_EXCEPTION_CHAIN 21 } { W32_FAST_FAIL_CRYPTO_LIBRARY 22 } { W32_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT 23 } { W32_FAST_FAIL_INVALID_IMAGE_BASE 24 } { W32_FAST_FAIL_DLOAD_PROTECTION_FAILURE 25 } { W32_FAST_FAIL_UNSAFE_EXTENSION_CALL 26 } { W32_FAST_FAIL_DEPRECATED_SERVICE_INVOKED 27 } { W32_FAST_FAIL_INVALID_BUFFER_ACCESS 28 } { W32_FAST_FAIL_INVALID_BALANCED_TREE 29 } { W32_FAST_FAIL_INVALID_NEXT_THREAD 30 } { W32_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED 31 } { W32_FAST_FAIL_APCS_DISABLED 32 } { W32_FAST_FAIL_INVALID_IDLE_STATE 33 } { W32_FAST_FAIL_MRDATA_PROTECTION_FAILURE 34 } { W32_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION 35 } { W32_FAST_FAIL_INVALID_LOCK_STATE 36 } { W32_FAST_FAIL_GUARD_JUMPTABLE 37 } { W32_FAST_FAIL_INVALID_LONGJUMP_TARGET 38 } { W32_FAST_FAIL_INVALID_DISPATCH_CONTEXT 39 } { W32_FAST_FAIL_INVALID_THREAD 40 } { W32_FAST_FAIL_INVALID_SYSCALL_NUMBER 41 } { W32_FAST_FAIL_INVALID_FILE_OPERATION 42 } { W32_FAST_FAIL_LPAC_ACCESS_DENIED 43 } { W32_FAST_FAIL_GUARD_SS_FAILURE 44 } { W32_FAST_FAIL_LOADER_CONTINUITY_FAILURE 45 } { W32_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE 46 } { W32_FAST_FAIL_INVALID_CONTROL_STACK 47 } { W32_FAST_FAIL_SET_CONTEXT_DENIED 48 } { W32_FAST_FAIL_INVALID_IAT 49 } { W32_FAST_FAIL_HEAP_METADATA_CORRUPTION 50 } { W32_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION 51 } { W32_FAST_FAIL_LOW_LABEL_ACCESS_DENIED 52 } { W32_FAST_FAIL_ENCLAVE_CALL_FAILURE 53 } { W32_FAST_FAIL_UNHANDLED_LSS_EXCEPTON 54 } { W32_FAST_FAIL_ADMINLESS_ACCESS_DENIED 55 } { W32_FAST_FAIL_UNEXPECTED_CALL 56 } { W32_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS 57 } { W32_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR 58 } { W32_FAST_FAIL_FLAGS_CORRUPTION 59 } { W32_FAST_FAIL_VEH_CORRUPTION 60 } { W32_FAST_FAIL_ETW_CORRUPTION 61 } { W32_FAST_FAIL_RIO_ABORT 62 } { W32_FAST_FAIL_INVALID_PFN 63 } { W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG 64 } { W32_FAST_FAIL_CAST_GUARD 65 } { W32_FAST_FAIL_HOST_VISIBILITY_CHANGE 66 } { W32_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST 67 } { W32_FAST_FAIL_PATCH_CALLBACK_FAILED 68 } { W32_FAST_FAIL_NTDLL_PATCH_FAILED 69 } { W32_FAST_FAIL_INVALID_FLS_DATA 70 } } ================================================ FILE: src/ctrl/ctrl_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "generated/ctrl.meta.c" //////////////////////////////// //~ rjf: Basic Type Functions #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal U64 ctrl_hash_from_string(String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, 5381); return result; } internal U64 ctrl_hash_from_handle(CTRL_Handle handle) { U64 buf[] = {handle.machine_id, handle.dmn_handle.u64[0]}; U64 hash = ctrl_hash_from_string(str8((U8 *)buf, sizeof(buf))); return hash; } internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind) { CTRL_EventCause cause = CTRL_EventCause_Null; switch(event_kind) { default:{}break; case DMN_EventKind_Error: {cause = CTRL_EventCause_Error;}break; case DMN_EventKind_Exception:{cause = CTRL_EventCause_InterruptedByException;}break; case DMN_EventKind_Trap: {cause = CTRL_EventCause_InterruptedByTrap;}break; case DMN_EventKind_Halt: {cause = CTRL_EventCause_InterruptedByHalt;}break; } return cause; } internal CTRL_ExceptionKind ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind) { CTRL_ExceptionKind result = CTRL_ExceptionKind_Null; switch(kind) { default:{}break; case DMN_ExceptionKind_MemoryRead: {result = CTRL_ExceptionKind_MemoryRead;}break; case DMN_ExceptionKind_MemoryWrite: {result = CTRL_ExceptionKind_MemoryWrite;}break; case DMN_ExceptionKind_MemoryExecute: {result = CTRL_ExceptionKind_MemoryExecute;}break; case DMN_ExceptionKind_CppThrow: {result = CTRL_ExceptionKind_CppThrow;}break; } return result; } internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind) { String8 result = {0}; switch(kind) { default:{}break; case CTRL_EventKind_Null: { result = str8_lit("Null");}break; case CTRL_EventKind_Error: { result = str8_lit("Error");}break; case CTRL_EventKind_Started: { result = str8_lit("Started");}break; case CTRL_EventKind_Stopped: { result = str8_lit("Stopped");}break; case CTRL_EventKind_NewProc: { result = str8_lit("NewProc");}break; case CTRL_EventKind_NewThread: { result = str8_lit("NewThread");}break; case CTRL_EventKind_NewModule: { result = str8_lit("NewModule");}break; case CTRL_EventKind_EndProc: { result = str8_lit("EndProc");}break; case CTRL_EventKind_EndThread: { result = str8_lit("EndThread");}break; case CTRL_EventKind_EndModule: { result = str8_lit("EndModule");}break; case CTRL_EventKind_ModuleDebugInfoPathChange: { result = str8_lit("ModuleDebugInfoPathChange");}break; case CTRL_EventKind_DebugString: { result = str8_lit("DebugString");}break; case CTRL_EventKind_ThreadName: { result = str8_lit("ThreadName");}break; case CTRL_EventKind_MemReserve: { result = str8_lit("MemReserve");}break; case CTRL_EventKind_MemCommit: { result = str8_lit("MemCommit");}break; case CTRL_EventKind_MemDecommit: { result = str8_lit("MemDecommit");}break; case CTRL_EventKind_MemRelease: { result = str8_lit("MemRelease");}break; } return result; } internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind) { String8 result = {0}; switch(kind) { default:{}break; case CTRL_MsgKind_Launch: {result = str8_lit("Launch");}break; case CTRL_MsgKind_Attach: {result = str8_lit("Attach");}break; case CTRL_MsgKind_Kill: {result = str8_lit("Kill");}break; case CTRL_MsgKind_KillAll: {result = str8_lit("KillAll");}break; case CTRL_MsgKind_Detach: {result = str8_lit("Detach");}break; case CTRL_MsgKind_Run: {result = str8_lit("Run");}break; case CTRL_MsgKind_SingleStep: {result = str8_lit("SingleStep");}break; case CTRL_MsgKind_SetUserEntryPoints: {result = str8_lit("SetUserEntryPoints");}break; case CTRL_MsgKind_SetModuleDebugInfoPath: {result = str8_lit("SetModuleDebugInfoPath");}break; } return result; } internal CTRL_EntityKind ctrl_entity_kind_from_string(String8 string) { CTRL_EntityKind result = CTRL_EntityKind_Null; for EachNonZeroEnumVal(CTRL_EntityKind, k) { if(str8_match(ctrl_entity_kind_code_name_table[k], string, 0)) { result = k; break; } } return result; } internal DMN_TrapFlags ctrl_dmn_trap_flags_from_user_breakpoint_flags(CTRL_UserBreakpointFlags flags) { DMN_TrapFlags result = 0; if(flags & CTRL_UserBreakpointFlag_BreakOnWrite) { result |= DMN_TrapFlag_BreakOnWrite; } if(flags & CTRL_UserBreakpointFlag_BreakOnRead) { result |= DMN_TrapFlag_BreakOnRead; } if(flags & CTRL_UserBreakpointFlag_BreakOnExecute) { result |= DMN_TrapFlag_BreakOnExecute; } return result; } internal CTRL_UserBreakpointFlags ctrl_user_breakpoint_flags_from_dmn_trap_flags(DMN_TrapFlags flags) { CTRL_UserBreakpointFlags result = 0; if(flags & DMN_TrapFlag_BreakOnWrite) { result |= CTRL_UserBreakpointFlag_BreakOnWrite; } if(flags & DMN_TrapFlag_BreakOnRead) { result |= CTRL_UserBreakpointFlag_BreakOnRead; } if(flags & DMN_TrapFlag_BreakOnExecute) { result |= CTRL_UserBreakpointFlag_BreakOnExecute; } return result; } //////////////////////////////// //~ rjf: Machine/Handle Pair Type Functions internal CTRL_Handle ctrl_handle_zero(void) { CTRL_Handle handle = {0}; return handle; } internal CTRL_Handle ctrl_handle_make(CTRL_MachineID machine_id, DMN_Handle dmn_handle) { CTRL_Handle handle = {machine_id, dmn_handle}; return handle; } internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b) { B32 result = (a.machine_id == b.machine_id && dmn_handle_match(a.dmn_handle, b.dmn_handle)); return result; } internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair) { CTRL_HandleNode *n = push_array(arena, CTRL_HandleNode, 1); MemoryCopyStruct(&n->v, pair); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src) { CTRL_HandleList dst = {0}; for(CTRL_HandleNode *n = src->first; n != 0; n = n->next) { ctrl_handle_list_push(arena, &dst, &n->v); } return dst; } internal CTRL_HandleArray ctrl_handle_array_from_list(Arena *arena, CTRL_HandleList *src) { CTRL_HandleArray array = {0}; array.count = src->count; array.v = push_array_no_zero(arena, CTRL_Handle, array.count); { U64 idx = 0; for(CTRL_HandleNode *n = src->first; n != 0; n = n->next, idx += 1) { array.v[idx] = n->v; } } return array; } internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle) { String8 result = push_str8f(arena, "$%I64x$%I64x", handle.machine_id, handle.dmn_handle.u64[0]); return result; } internal CTRL_Handle ctrl_handle_from_string(String8 string) { CTRL_Handle handle = {0}; { Temp scratch = scratch_begin(0, 0); U8 split = '$'; String8List parts = str8_split(scratch.arena, string, &split, 1, 0); if(parts.first && parts.first->next) { CTRL_MachineID machine_id = u64_from_str8(parts.first->string, 16); DMN_Handle dmn_handle = {0}; dmn_handle.u64[0] = u64_from_str8(parts.first->next->string, 16); handle.machine_id = machine_id; handle.dmn_handle = dmn_handle; } scratch_end(scratch); } return handle; } //////////////////////////////// //~ rjf: Trap Type Functions internal void ctrl_trap_list_push(Arena *arena, CTRL_TrapList *list, CTRL_Trap *trap) { CTRL_TrapNode *node = push_array(arena, CTRL_TrapNode, 1); MemoryCopyStruct(&node->v, trap); SLLQueuePush(list->first, list->last, node); list->count += 1; } internal CTRL_TrapList ctrl_trap_list_copy(Arena *arena, CTRL_TrapList *src) { CTRL_TrapList dst = {0}; for(CTRL_TrapNode *src_n = src->first; src_n != 0; src_n = src_n->next) { ctrl_trap_list_push(arena, &dst, &src_n->v); } return dst; } //////////////////////////////// //~ rjf: User Breakpoint Type Functions internal void ctrl_user_breakpoint_list_push(Arena *arena, CTRL_UserBreakpointList *list, CTRL_UserBreakpoint *bp) { CTRL_UserBreakpointNode *n = push_array(arena, CTRL_UserBreakpointNode, 1); MemoryCopyStruct(&n->v, bp); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal CTRL_UserBreakpointList ctrl_user_breakpoint_list_copy(Arena *arena, CTRL_UserBreakpointList *src) { CTRL_UserBreakpointList dst = {0}; for(CTRL_UserBreakpointNode *src_n = src->first; src_n != 0; src_n = src_n->next) { CTRL_UserBreakpoint dst_bp = zero_struct; MemoryCopyStruct(&dst_bp, &src_n->v); dst_bp.string = push_str8_copy(arena, src_n->v.string); dst_bp.condition = push_str8_copy(arena, src_n->v.condition); ctrl_user_breakpoint_list_push(arena, &dst, &dst_bp); } return dst; } //////////////////////////////// //~ rjf: Message Type Functions //- rjf: deep copying internal void ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src) { MemoryCopyStruct(dst, src); dst->path = push_str8_copy(arena, src->path); dst->entry_points = str8_list_copy(arena, &src->entry_points); dst->cmd_line_string_list = str8_list_copy(arena, &src->cmd_line_string_list); dst->env_string_list = str8_list_copy(arena, &src->env_string_list); dst->traps = ctrl_trap_list_copy(arena, &src->traps); dst->user_bps = ctrl_user_breakpoint_list_copy(arena, &src->user_bps); } //- rjf: list building internal CTRL_Msg * ctrl_msg_list_push(Arena *arena, CTRL_MsgList *list) { CTRL_MsgNode *n = push_array(arena, CTRL_MsgNode, 1); SLLQueuePush(list->first, list->last, n); list->count += 1; CTRL_Msg *msg = &n->v; return msg; } internal CTRL_MsgList ctrl_msg_list_deep_copy(Arena *arena, CTRL_MsgList *src) { CTRL_MsgList dst = {0}; for(CTRL_MsgNode *n = src->first; n != 0; n = n->next) { CTRL_Msg *src_msg = &n->v; CTRL_Msg *dst_msg = ctrl_msg_list_push(arena, &dst); ctrl_msg_deep_copy(arena, dst_msg, src_msg); } return dst; } internal void ctrl_msg_list_concat_in_place(CTRL_MsgList *dst, CTRL_MsgList *src) { if(dst->last && src->first) { dst->last->next = src->first; dst->last = src->last; dst->count += src->count; } else if(src->first) { MemoryCopyStruct(dst, src); } MemoryZeroStruct(src); } //- rjf: serialization internal String8 ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs) { Temp scratch = scratch_begin(&arena, 1); String8List msgs_srlzed = {0}; str8_serial_begin(scratch.arena, &msgs_srlzed); { // rjf: write message count str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msgs->count); // rjf: write all message data for(CTRL_MsgNode *msg_n = msgs->first; msg_n != 0; msg_n = msg_n->next) { CTRL_Msg *msg = &msg_n->v; // rjf: write flat parts str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->kind); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->run_flags); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->msg_id); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->entity); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->parent); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->entity_id); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->exit_code); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->env_inherit); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->debug_subprocesses); str8_serial_push_array (scratch.arena, &msgs_srlzed, &msg->exception_code_filters[0], ArrayCount(msg->exception_code_filters)); // rjf: write path string str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->path.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, msg->path.str, msg->path.size); // rjf: write entry point string list str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->entry_points.node_count); for(String8Node *n = msg->entry_points.first; n != 0; n = n->next) { str8_serial_push_struct(scratch.arena, &msgs_srlzed, &n->string.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, n->string.str, n->string.size); } // rjf: write command line string list str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->cmd_line_string_list.node_count); for(String8Node *n = msg->cmd_line_string_list.first; n != 0; n = n->next) { str8_serial_push_struct(scratch.arena, &msgs_srlzed, &n->string.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, n->string.str, n->string.size); } // rjf: write environment string list str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->env_string_list.node_count); for(String8Node *n = msg->env_string_list.first; n != 0; n = n->next) { str8_serial_push_struct(scratch.arena, &msgs_srlzed, &n->string.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, n->string.str, n->string.size); } // rjf: write stdout/stderr/stdin paths str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->stdout_path.size); str8_serial_push_string(scratch.arena, &msgs_srlzed, msg->stdout_path); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->stderr_path.size); str8_serial_push_string(scratch.arena, &msgs_srlzed, msg->stderr_path); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->stdin_path.size); str8_serial_push_string(scratch.arena, &msgs_srlzed, msg->stdin_path); // rjf: write trap list str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->traps.count); for(CTRL_TrapNode *n = msg->traps.first; n != 0; n = n->next) { CTRL_Trap *trap = &n->v; str8_serial_push_struct(scratch.arena, &msgs_srlzed, &trap->flags); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &trap->vaddr); } // rjf: write user breakpoint list str8_serial_push_struct(scratch.arena, &msgs_srlzed, &msg->user_bps.count); for(CTRL_UserBreakpointNode *n = msg->user_bps.first; n != 0; n = n->next) { CTRL_UserBreakpoint *bp = &n->v; str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->kind); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->flags); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->id); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->string.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, bp->string.str, bp->string.size); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->pt); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->size); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->condition.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, bp->condition.str, bp->condition.size); } } } String8 string = str8_serial_end(arena, &msgs_srlzed); scratch_end(scratch); return string; } internal CTRL_MsgList ctrl_msg_list_from_serialized_string(Arena *arena, String8 string) { CTRL_MsgList msgs = {0}; { U64 read_off = 0; // rjf: read message count U64 msg_count = 0; read_off += str8_deserial_read_struct(string, read_off, &msg_count); // rjf: read data for all messages for(U64 msg_idx = 0; msg_idx < msg_count; msg_idx += 1) { // rjf: construct message CTRL_MsgNode *msg_node = push_array(arena, CTRL_MsgNode, 1); SLLQueuePush(msgs.first, msgs.last, msg_node); msgs.count += 1; CTRL_Msg *msg = &msg_node->v; // rjf: read flat data read_off += str8_deserial_read_struct(string, read_off, &msg->kind); read_off += str8_deserial_read_struct(string, read_off, &msg->run_flags); read_off += str8_deserial_read_struct(string, read_off, &msg->msg_id); read_off += str8_deserial_read_struct(string, read_off, &msg->entity); read_off += str8_deserial_read_struct(string, read_off, &msg->parent); read_off += str8_deserial_read_struct(string, read_off, &msg->entity_id); read_off += str8_deserial_read_struct(string, read_off, &msg->exit_code); read_off += str8_deserial_read_struct(string, read_off, &msg->env_inherit); read_off += str8_deserial_read_struct(string, read_off, &msg->debug_subprocesses); read_off += str8_deserial_read_array (string, read_off, &msg->exception_code_filters[0], ArrayCount(msg->exception_code_filters)); // rjf: read path string read_off += str8_deserial_read_struct(string, read_off, &msg->path.size); msg->path.str = push_array_no_zero(arena, U8, msg->path.size); read_off += str8_deserial_read(string, read_off, msg->path.str, msg->path.size, 1); // rjf: read entry point string list U64 entry_point_list_string_count = 0; read_off += str8_deserial_read_struct(string, read_off, &entry_point_list_string_count); for(U64 idx = 0; idx < entry_point_list_string_count; idx += 1) { String8 str = {0}; read_off += str8_deserial_read_struct(string, read_off, &str.size); str.str = push_array_no_zero(arena, U8, str.size); read_off += str8_deserial_read(string, read_off, str.str, str.size, 1); str8_list_push(arena, &msg->entry_points, str); } // rjf: read command line string list U64 cmd_line_string_count = 0; read_off += str8_deserial_read_struct(string, read_off, &cmd_line_string_count); for(U64 idx = 0; idx < cmd_line_string_count; idx += 1) { String8 cmd_line_str = {0}; read_off += str8_deserial_read_struct(string, read_off, &cmd_line_str.size); cmd_line_str.str = push_array_no_zero(arena, U8, cmd_line_str.size); read_off += str8_deserial_read(string, read_off, cmd_line_str.str, cmd_line_str.size, 1); str8_list_push(arena, &msg->cmd_line_string_list, cmd_line_str); } // rjf: read environment string list U64 env_string_count = 0; read_off += str8_deserial_read_struct(string, read_off, &env_string_count); for(U64 idx = 0; idx < env_string_count; idx += 1) { String8 env_str = {0}; read_off += str8_deserial_read_struct(string, read_off, &env_str.size); env_str.str = push_array_no_zero(arena, U8, env_str.size); read_off += str8_deserial_read(string, read_off, env_str.str, env_str.size, 1); str8_list_push(arena, &msg->env_string_list, env_str); } // rjf: read stdout/stderr/stdin paths read_off += str8_deserial_read_struct(string, read_off, &msg->stdout_path.size); msg->stdout_path.str = push_array(arena, U8, msg->stdout_path.size); read_off += str8_deserial_read(string, read_off, msg->stdout_path.str, msg->stdout_path.size, 1); read_off += str8_deserial_read_struct(string, read_off, &msg->stderr_path.size); msg->stderr_path.str = push_array(arena, U8, msg->stderr_path.size); read_off += str8_deserial_read(string, read_off, msg->stderr_path.str, msg->stderr_path.size, 1); read_off += str8_deserial_read_struct(string, read_off, &msg->stdin_path.size); msg->stdin_path.str = push_array(arena, U8, msg->stdin_path.size); read_off += str8_deserial_read(string, read_off, msg->stdin_path.str, msg->stdin_path.size, 1); // rjf: read trap list U64 trap_count = 0; read_off += str8_deserial_read_struct(string, read_off, &trap_count); for(U64 idx = 0; idx < trap_count; idx += 1) { CTRL_TrapNode *n = push_array(arena, CTRL_TrapNode, 1); SLLQueuePush(msg->traps.first, msg->traps.last, n); msg->traps.count += 1; CTRL_Trap *trap = &n->v; read_off += str8_deserial_read_struct(string, read_off, &trap->flags); read_off += str8_deserial_read_struct(string, read_off, &trap->vaddr); } // rjf: read user breakpoint list U64 user_bp_count = 0; read_off += str8_deserial_read_struct(string, read_off, &user_bp_count); for(U64 idx = 0; idx < user_bp_count; idx += 1) { CTRL_UserBreakpointNode *n = push_array(arena, CTRL_UserBreakpointNode, 1); SLLQueuePush(msg->user_bps.first, msg->user_bps.last, n); msg->user_bps.count += 1; CTRL_UserBreakpoint *bp = &n->v; read_off += str8_deserial_read_struct(string, read_off, &bp->kind); read_off += str8_deserial_read_struct(string, read_off, &bp->flags); read_off += str8_deserial_read_struct(string, read_off, &bp->id); read_off += str8_deserial_read_struct(string, read_off, &bp->string.size); bp->string.str = push_array_no_zero(arena, U8, bp->string.size); read_off += str8_deserial_read(string, read_off, bp->string.str, bp->string.size, 1); read_off += str8_deserial_read_struct(string, read_off, &bp->pt); read_off += str8_deserial_read_struct(string, read_off, &bp->size); read_off += str8_deserial_read_struct(string, read_off, &bp->condition.size); bp->condition.str = push_array_no_zero(arena, U8, bp->condition.size); read_off += str8_deserial_read(string, read_off, bp->condition.str, bp->condition.size, 1); } } } return msgs; } //////////////////////////////// //~ rjf: Event Type Functions //- rjf: list building internal CTRL_Event * ctrl_event_list_push(Arena *arena, CTRL_EventList *list) { CTRL_EventNode *n = push_array(arena, CTRL_EventNode, 1); SLLQueuePush(list->first, list->last, n); list->count += 1; CTRL_Event *event = &n->v; return event; } internal void ctrl_event_list_concat_in_place(CTRL_EventList *dst, CTRL_EventList *to_push) { if(dst->last == 0) { MemoryCopyStruct(dst, to_push); } else if(to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->count += to_push->count; } MemoryZeroStruct(to_push); } //- rjf: serialization internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event, U64 max) { Temp scratch = scratch_begin(&arena, 1); String8List srl = {0}; str8_serial_begin(scratch.arena, &srl); { str8_serial_push_struct(scratch.arena, &srl, &event->kind); str8_serial_push_struct(scratch.arena, &srl, &event->cause); str8_serial_push_struct(scratch.arena, &srl, &event->exception_kind); str8_serial_push_struct(scratch.arena, &srl, &event->msg_id); str8_serial_push_struct(scratch.arena, &srl, &event->entity); str8_serial_push_struct(scratch.arena, &srl, &event->parent); str8_serial_push_struct(scratch.arena, &srl, &event->arch); str8_serial_push_struct(scratch.arena, &srl, &event->u64_code); str8_serial_push_struct(scratch.arena, &srl, &event->entity_id); str8_serial_push_struct(scratch.arena, &srl, &event->vaddr_rng); str8_serial_push_struct(scratch.arena, &srl, &event->rip_vaddr); str8_serial_push_struct(scratch.arena, &srl, &event->stack_base); str8_serial_push_struct(scratch.arena, &srl, &event->tls_root); str8_serial_push_struct(scratch.arena, &srl, &event->timestamp); str8_serial_push_struct(scratch.arena, &srl, &event->exception_code); str8_serial_push_struct(scratch.arena, &srl, &event->rgba); str8_serial_push_struct(scratch.arena, &srl, &event->bp_flags); String8 string = event->string; string.size = Min(string.size, max-srl.total_size); str8_serial_push_struct(scratch.arena, &srl, &string.size); str8_serial_push_data(scratch.arena, &srl, string.str, string.size); } String8 string = str8_serial_end(arena, &srl); scratch_end(scratch); return string; } internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string) { CTRL_Event event = zero_struct; { U64 read_off = 0; read_off += str8_deserial_read_struct(string, read_off, &event.kind); read_off += str8_deserial_read_struct(string, read_off, &event.cause); read_off += str8_deserial_read_struct(string, read_off, &event.exception_kind); read_off += str8_deserial_read_struct(string, read_off, &event.msg_id); read_off += str8_deserial_read_struct(string, read_off, &event.entity); read_off += str8_deserial_read_struct(string, read_off, &event.parent); read_off += str8_deserial_read_struct(string, read_off, &event.arch); read_off += str8_deserial_read_struct(string, read_off, &event.u64_code); read_off += str8_deserial_read_struct(string, read_off, &event.entity_id); read_off += str8_deserial_read_struct(string, read_off, &event.vaddr_rng); read_off += str8_deserial_read_struct(string, read_off, &event.rip_vaddr); read_off += str8_deserial_read_struct(string, read_off, &event.stack_base); read_off += str8_deserial_read_struct(string, read_off, &event.tls_root); read_off += str8_deserial_read_struct(string, read_off, &event.timestamp); read_off += str8_deserial_read_struct(string, read_off, &event.exception_code); read_off += str8_deserial_read_struct(string, read_off, &event.rgba); read_off += str8_deserial_read_struct(string, read_off, &event.bp_flags); read_off += str8_deserial_read_struct(string, read_off, &event.string.size); event.string.str = push_array_no_zero(arena, U8, event.string.size); read_off += str8_deserial_read(string, read_off, event.string.str, event.string.size, 1); } return event; } //////////////////////////////// //~ rjf: Entity Type Functions //- rjf: entity list data structures internal void ctrl_entity_list_push(Arena *arena, CTRL_EntityList *list, CTRL_Entity *entity) { CTRL_EntityNode *n = push_array(arena, CTRL_EntityNode, 1); n->v = entity; SLLQueuePush(list->first, list->last, n); list->count += 1; } internal CTRL_EntityList ctrl_entity_list_from_handle_list(Arena *arena, CTRL_EntityCtx *ctx, CTRL_HandleList *list) { CTRL_EntityList result = {0}; for(CTRL_HandleNode *n = list->first; n != 0; n = n->next) { CTRL_Entity *entity = ctrl_entity_from_handle(ctx, n->v); ctrl_entity_list_push(arena, &result, entity); } return result; } //- rjf: entity array data structure internal CTRL_EntityArray ctrl_entity_array_from_list(Arena *arena, CTRL_EntityList *list) { CTRL_EntityArray result = {0}; result.count = list->count; result.v = push_array_no_zero(arena, CTRL_Entity *, result.count); U64 idx = 0; for(CTRL_EntityNode *n = list->first; n != 0; n = n->next, idx += 1) { result.v[idx] = n->v; } return result; } //- rjf: entity context (entity group read-only) functions internal CTRL_Entity * ctrl_entity_from_handle(CTRL_EntityCtx *ctx, CTRL_Handle handle) { CTRL_Entity *entity = &ctrl_entity_nil; if(!ctrl_handle_match(handle, ctrl_handle_zero())) { U64 hash = ctrl_hash_from_handle(handle); U64 slot_idx = hash%ctx->hash_slots_count; CTRL_EntityHashSlot *slot = &ctx->hash_slots[slot_idx]; CTRL_EntityHashNode *node = 0; for(CTRL_EntityHashNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->entity->handle, handle)) { entity = n->entity; break; } } } return entity; } internal CTRL_Entity * ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind) { CTRL_Entity *result = &ctrl_entity_nil; for(CTRL_Entity *child = parent->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == kind) { result = child; break; } } return result; } internal CTRL_Entity * ctrl_entity_ancestor_from_kind(CTRL_Entity *entity, CTRL_EntityKind kind) { CTRL_Entity *result = &ctrl_entity_nil; for(CTRL_Entity *p = entity->parent; p != &ctrl_entity_nil; p = p->parent) { if(p->kind == kind) { result = p; break; } } return result; } internal CTRL_Entity * ctrl_process_from_entity(CTRL_Entity *entity) { CTRL_Entity *result = &ctrl_entity_nil; if(entity->kind == CTRL_EntityKind_Process) { result = entity; } else { result = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); } return result; } internal CTRL_Entity * ctrl_module_from_process_vaddr(CTRL_Entity *process, U64 vaddr) { CTRL_Entity *result = &ctrl_entity_nil; for(CTRL_Entity *child = process->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == CTRL_EntityKind_Module && contains_1u64(child->vaddr_range, vaddr)) { result = child; break; } } return result; } internal DI_Key ctrl_dbgi_key_from_module(CTRL_Entity *module) { CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp); return dbgi_key; } internal CTRL_Entity * ctrl_module_from_thread_candidates(CTRL_EntityCtx *ctx, CTRL_Entity *thread, CTRL_EntityList *candidates) { CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); U64 thread_rip_vaddr = ctrl_rip_from_thread(ctx, thread->handle); CTRL_Entity *src_module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr); CTRL_Entity *module = &ctrl_entity_nil; for(CTRL_EntityNode *n = candidates->first; n != 0; n = n->next) { CTRL_Entity *candidate_module = n->v; CTRL_Entity *candidate_process = ctrl_entity_ancestor_from_kind(candidate_module, CTRL_EntityKind_Process); if(candidate_process == process) { module = candidate_module; } if(candidate_module == src_module) { break; } } return module; } internal U64 ctrl_vaddr_from_voff(CTRL_Entity *module, U64 voff) { U64 result = voff + module->vaddr_range.min; return result; } internal U64 ctrl_voff_from_vaddr(CTRL_Entity *module, U64 vaddr) { U64 result = vaddr - module->vaddr_range.min; return result; } internal Rng1U64 ctrl_vaddr_range_from_voff_range(CTRL_Entity *module, Rng1U64 voff_range) { U64 dim = dim_1u64(voff_range); U64 min = ctrl_vaddr_from_voff(module, voff_range.min); Rng1U64 result = {min, min+dim}; return result; } internal Rng1U64 ctrl_voff_range_from_vaddr_range(CTRL_Entity *module, Rng1U64 vaddr_range) { U64 dim = dim_1u64(vaddr_range); U64 min = ctrl_voff_from_vaddr(module, vaddr_range.min); Rng1U64 result = {min, min+dim}; return result; } internal B32 ctrl_entity_tree_is_frozen(CTRL_Entity *root) { B32 is_frozen = 1; for(CTRL_Entity *e = root; e != &ctrl_entity_nil; e = ctrl_entity_rec_depth_first_pre(e, root).next) { if(e->kind == CTRL_EntityKind_Thread && !e->is_frozen) { is_frozen = 0; break; } } return is_frozen; } //- rjf: entity ctx r/w store state functions internal CTRL_EntityCtxRWStore * ctrl_entity_ctx_rw_store_alloc(void) { Arena *arena = arena_alloc(); CTRL_EntityCtxRWStore *store = push_array(arena, CTRL_EntityCtxRWStore, 1); store->arena = arena; store->ctx.hash_slots_count = 1024; store->ctx.hash_slots = push_array(arena, CTRL_EntityHashSlot, store->ctx.hash_slots_count); CTRL_Entity *root = store->ctx.root = ctrl_entity_alloc(store, &ctrl_entity_nil, CTRL_EntityKind_Root, Arch_Null, ctrl_handle_zero(), 0); CTRL_Entity *local_machine = ctrl_entity_alloc(store, root, CTRL_EntityKind_Machine, Arch_CURRENT, ctrl_handle_make(CTRL_MachineID_Local, dmn_handle_zero()), 0); Temp scratch = scratch_begin(0, 0); String8 local_machine_name = push_str8f(scratch.arena, "This PC (%S)", os_get_system_info()->machine_name); ctrl_entity_equip_string(store, local_machine, local_machine_name); scratch_end(scratch); return store; } internal void ctrl_entity_ctx_rw_store_release(CTRL_EntityCtxRWStore *store) { arena_release(store->arena); } //- rjf: string allocation/deletion internal U64 ctrl_name_bucket_num_from_string_size(U64 size) { U64 bucket_num = 0; if(size > 0) { for EachElement(idx, ctrl_entity_string_bucket_chunk_sizes) { if(size <= ctrl_entity_string_bucket_chunk_sizes[idx]) { bucket_num = idx+1; break; } } } return bucket_num; } internal String8 ctrl_entity_string_alloc(CTRL_EntityCtxRWStore *store, String8 string) { //- rjf: allocate node CTRL_EntityStringChunkNode *node = 0; { U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size); if(bucket_num == ArrayCount(ctrl_entity_string_bucket_chunk_sizes)) { CTRL_EntityStringChunkNode *best_node = 0; CTRL_EntityStringChunkNode *best_node_prev = 0; U64 best_node_size = max_U64; { for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_num-1], *prev = 0; n != 0; (prev = n, n = n->next)) { if(n->size >= string.size && n->size < best_node_size) { best_node = n; best_node_prev = prev; best_node_size = n->size; } } } if(best_node != 0) { node = best_node; if(best_node_prev) { best_node_prev->next = best_node->next; } else { store->free_string_chunks[bucket_num-1] = best_node->next; } } else { U64 chunk_size = u64_up_to_pow2(string.size); node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, chunk_size); } } else if(bucket_num != 0) { node = store->free_string_chunks[bucket_num-1]; if(node != 0) { SLLStackPop(store->free_string_chunks[bucket_num-1]); } else { node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, ctrl_entity_string_bucket_chunk_sizes[bucket_num-1]); } } } //- rjf: fill node String8 result = {0}; if(node != 0) { result.str = (U8 *)node; result.size = string.size; MemoryCopy(result.str, string.str, result.size); } return result; } internal void ctrl_entity_string_release(CTRL_EntityCtxRWStore *store, String8 string) { U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size); if(1 <= bucket_num && bucket_num <= ArrayCount(ctrl_entity_string_bucket_chunk_sizes)) { U64 bucket_idx = bucket_num-1; CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str; SLLStackPush(store->free_string_chunks[bucket_idx], node); node->size = u64_up_to_pow2(string.size); } } //- rjf: entity construction/deletion internal CTRL_Entity * ctrl_entity_alloc(CTRL_EntityCtxRWStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Arch arch, CTRL_Handle handle, U64 id) { CTRL_Entity *entity = &ctrl_entity_nil; { // rjf: allocate entity = store->free; { if(entity != 0) { SLLStackPop(store->free); } else { entity = push_array_no_zero(store->arena, CTRL_Entity, 1); } MemoryZeroStruct(entity); } // rjf: fill { entity->kind = kind; entity->arch = arch; entity->handle = handle; entity->id = id; entity->parent = parent; entity->next = entity->prev = entity->first = entity->last = &ctrl_entity_nil; if(parent != &ctrl_entity_nil) { DLLPushBack_NPZ(&ctrl_entity_nil, parent->first, parent->last, entity, next, prev); } } // rjf: insert into hash map { U64 hash = ctrl_hash_from_handle(handle); U64 slot_idx = hash%store->ctx.hash_slots_count; CTRL_EntityHashSlot *slot = &store->ctx.hash_slots[slot_idx]; CTRL_EntityHashNode *node = 0; for(CTRL_EntityHashNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->entity->handle, handle)) { node = n; break; } } if(node == 0) { node = store->hash_node_free; if(node != 0) { SLLStackPop(store->hash_node_free); } else { node = push_array_no_zero(store->arena, CTRL_EntityHashNode, 1); } MemoryZeroStruct(node); DLLPushBack(slot->first, slot->last, node); node->entity = entity; } } // rjf: bump counters store->ctx.entity_kind_counts[kind] += 1; store->ctx.entity_kind_alloc_gens[kind] += 1; } return entity; } internal void ctrl_entity_release(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity) { // rjf: unhook root if(entity->parent != &ctrl_entity_nil) { DLLRemove_NPZ(&ctrl_entity_nil, entity->parent->first, entity->parent->last, entity, next, prev); } // rjf: walk every entity in this tree, free each if(entity != &ctrl_entity_nil) { Temp scratch = scratch_begin(0, 0); typedef struct Task Task; struct Task { Task *next; CTRL_Entity *e; }; Task start_task = {0, entity}; Task *first_task = &start_task; Task *last_task = &start_task; for(Task *t = first_task; t != 0; t = t->next) { for(CTRL_Entity *child = t->e->first; child != &ctrl_entity_nil; child = child->next) { Task *t = push_array(scratch.arena, Task, 1); t->e = child; SLLQueuePush(first_task, last_task, t); } // rjf: free entity SLLStackPush(store->free, t->e); // rjf: remove from hash map { U64 hash = ctrl_hash_from_handle(t->e->handle); U64 slot_idx = hash%store->ctx.hash_slots_count; CTRL_EntityHashSlot *slot = &store->ctx.hash_slots[slot_idx]; CTRL_EntityHashNode *node = 0; for(CTRL_EntityHashNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->entity->handle, t->e->handle)) { DLLRemove(slot->first, slot->last, n); SLLStackPush(store->hash_node_free, n); break; } } } // rjf: dec counter store->ctx.entity_kind_counts[t->e->kind] -= 1; store->ctx.entity_kind_alloc_gens[t->e->kind] += 1; } scratch_end(scratch); } } //- rjf: entity equipment internal void ctrl_entity_equip_string(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity, String8 string) { if(entity->string.size != 0) { ctrl_entity_string_release(store, entity->string); } entity->string = ctrl_entity_string_alloc(store, string); } //- rjf: accelerated entity context lookups internal CTRL_EntityCtxLookupAccel * ctrl_thread_entity_ctx_lookup_accel(void) { if(ctrl_entity_ctx_lookup_accel == 0) { Arena *arena = arena_alloc(); ctrl_entity_ctx_lookup_accel = push_array(arena, CTRL_EntityCtxLookupAccel, 1); ctrl_entity_ctx_lookup_accel->arena = arena; for EachEnumVal(CTRL_EntityKind, k) { ctrl_entity_ctx_lookup_accel->entity_kind_arrays_arenas[k] = arena_alloc(); } } return ctrl_entity_ctx_lookup_accel; } internal CTRL_EntityArray ctrl_entity_array_from_kind(CTRL_EntityCtx *ctx, CTRL_EntityKind kind) { CTRL_EntityCtxLookupAccel *accel = ctrl_thread_entity_ctx_lookup_accel(); if(accel->entity_kind_arrays_gens[kind] != ctx->entity_kind_alloc_gens[kind]) { Temp scratch = scratch_begin(0, 0); CTRL_EntityList entities = {0}; for(CTRL_Entity *e = ctx->root; e != &ctrl_entity_nil; e = ctrl_entity_rec_depth_first_pre(e, ctx->root).next) { if(e->kind == kind) { ctrl_entity_list_push(scratch.arena, &entities, e); } } accel->entity_kind_arrays_gens[kind] = ctx->entity_kind_alloc_gens[kind]; arena_clear(accel->entity_kind_arrays_arenas[kind]); accel->entity_kind_arrays[kind] = ctrl_entity_array_from_list(accel->entity_kind_arrays_arenas[kind], &entities); scratch_end(scratch); } return accel->entity_kind_arrays[kind]; } internal CTRL_EntityList ctrl_modules_from_dbgi_key(Arena *arena, CTRL_EntityCtx *ctx, DI_Key dbgi_key) { CTRL_EntityList list = {0}; CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(ctx, CTRL_EntityKind_Module); for EachIndex(idx, all_modules.count) { CTRL_Entity *module = all_modules.v[idx]; DI_Key module_dbgi_key = ctrl_dbgi_key_from_module(module); if(di_key_match(module_dbgi_key, dbgi_key)) { ctrl_entity_list_push(arena, &list, module); } } return list; } internal CTRL_Entity * ctrl_thread_from_id(CTRL_EntityCtx *ctx, U64 id) { CTRL_Entity *thread = &ctrl_entity_nil; CTRL_EntityArray threads = ctrl_entity_array_from_kind(ctx, CTRL_EntityKind_Thread); for EachIndex(idx, threads.count) { if(threads.v[idx]->id == id) { thread = threads.v[idx]; } } return thread; } //- rjf: entity tree iteration internal CTRL_EntityRec ctrl_entity_rec_depth_first(CTRL_Entity *entity, CTRL_Entity *subtree_root, U64 sib_off, U64 child_off) { CTRL_EntityRec result = {0}; result.next = &ctrl_entity_nil; if((*MemberFromOffset(CTRL_Entity **, entity, child_off)) != &ctrl_entity_nil) { result.next = *MemberFromOffset(CTRL_Entity **, entity, child_off); result.push_count = 1; } else for(CTRL_Entity *parent = entity; parent != subtree_root && parent != &ctrl_entity_nil; parent = parent->parent) { if(parent != subtree_root && (*MemberFromOffset(CTRL_Entity **, parent, sib_off)) != &ctrl_entity_nil) { result.next = *MemberFromOffset(CTRL_Entity **, parent, sib_off); break; } result.pop_count += 1; } return result; } //- rjf: applying events to entity caches internal void ctrl_entity_store_apply_events(CTRL_EntityCtxRWStore *store, CTRL_EventList *list) { //- rjf: scan events & construct entities for(CTRL_EventNode *n = list->first; n != 0; n = n->next) { CTRL_Event *event = &n->v; switch(event->kind) { default:{}break; //- rjf: processes case CTRL_EventKind_NewProc: { CTRL_Entity *machine = ctrl_entity_from_handle(&store->ctx, ctrl_handle_make(event->entity.machine_id, dmn_handle_zero())); CTRL_Entity *process = ctrl_entity_alloc(store, machine, CTRL_EntityKind_Process, event->arch, event->entity, (U64)event->entity_id); }break; case CTRL_EventKind_EndProc: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->entity); ctrl_entity_release(store, process); for(CTRL_Entity *entry = store->ctx.root->first, *next = &ctrl_entity_nil; entry != &ctrl_entity_nil; entry = next) { next = entry->next; if(entry->kind == CTRL_EntityKind_EntryPoint && entry->id == process->id) { ctrl_entity_release(store, entry); } } }break; //- rjf: threads case CTRL_EventKind_NewThread: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *thread = ctrl_entity_alloc(store, process, CTRL_EntityKind_Thread, event->arch, event->entity, (U64)event->entity_id); CTRL_Entity *first_thread = ctrl_entity_child_from_kind(process, CTRL_EntityKind_Thread); if(first_thread == thread) { ctrl_entity_equip_string(store, thread, str8_lit("main_thread")); } CTRL_EntityArray pending_thread_names = ctrl_entity_array_from_kind(&store->ctx, CTRL_EntityKind_PendingThreadName); for EachIndex(idx, pending_thread_names.count) { CTRL_Entity *entity = pending_thread_names.v[idx]; if(entity->id == event->entity_id) { ctrl_entity_equip_string(store, thread, entity->string); ctrl_entity_release(store, entity); break; } } CTRL_EntityArray pending_thread_colors = ctrl_entity_array_from_kind(&store->ctx, CTRL_EntityKind_PendingThreadColor); for EachIndex(idx, pending_thread_colors.count) { CTRL_Entity *entity = pending_thread_colors.v[idx]; if(entity->id == event->entity_id) { thread->rgba = entity->rgba; ctrl_entity_release(store, entity); break; } } thread->stack_base = event->stack_base; ctrl_rip_from_thread(&store->ctx, event->entity); }break; case CTRL_EventKind_EndThread: { CTRL_Entity *thread = ctrl_entity_from_handle(&store->ctx, event->entity); ctrl_entity_release(store, thread); }break; case CTRL_EventKind_ThreadName: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *thread = &ctrl_entity_nil; if(event->entity_id == 0) { thread = ctrl_entity_from_handle(&store->ctx, event->entity); } else { thread = ctrl_thread_from_id(&store->ctx, event->entity_id); } if(thread != &ctrl_entity_nil) { ctrl_entity_equip_string(store, thread, event->string); } else { CTRL_Entity *pending_name = ctrl_entity_alloc(store, process, CTRL_EntityKind_PendingThreadName, Arch_Null, ctrl_handle_zero(), event->entity_id); ctrl_entity_equip_string(store, pending_name, event->string); } }break; case CTRL_EventKind_ThreadColor: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *thread = &ctrl_entity_nil; if(event->entity_id == 0) { thread = ctrl_entity_from_handle(&store->ctx, event->entity); } else { thread = ctrl_thread_from_id(&store->ctx, event->entity_id); } if(thread != &ctrl_entity_nil) { thread->rgba = event->rgba; } else { CTRL_Entity *pending = ctrl_entity_alloc(store, process, CTRL_EntityKind_PendingThreadColor, Arch_Null, ctrl_handle_zero(), event->entity_id); pending->rgba = event->rgba; } }break; case CTRL_EventKind_ThreadFrozen: { CTRL_Entity *thread = ctrl_entity_from_handle(&store->ctx, event->entity); thread->is_frozen = 1; }break; case CTRL_EventKind_ThreadThawed: { CTRL_Entity *thread = ctrl_entity_from_handle(&store->ctx, event->entity); thread->is_frozen = 0; }break; //- rjf: modules case CTRL_EventKind_NewModule: { Temp scratch = scratch_begin(0, 0); CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *module = ctrl_entity_alloc(store, process, CTRL_EntityKind_Module, event->arch, event->entity, event->vaddr_rng.min); ctrl_entity_equip_string(store, module, event->string); module->timestamp = event->timestamp; module->vaddr_range = event->vaddr_rng; CTRL_Entity *first_module = ctrl_entity_child_from_kind(process, CTRL_EntityKind_Module); if(first_module == module) { ctrl_entity_equip_string(store, process, str8_skip_last_slash(event->string)); } scratch_end(scratch); }break; case CTRL_EventKind_EndModule: { CTRL_Entity *module = ctrl_entity_from_handle(&store->ctx, event->entity); ctrl_entity_release(store, module); }break; case CTRL_EventKind_ModuleDebugInfoPathChange: { Temp scratch = scratch_begin(0, 0); CTRL_Entity *module = ctrl_entity_from_handle(&store->ctx, event->entity); CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); if(debug_info_path == &ctrl_entity_nil) { debug_info_path = ctrl_entity_alloc(store, module, CTRL_EntityKind_DebugInfoPath, Arch_Null, ctrl_handle_zero(), 0); } ctrl_entity_equip_string(store, debug_info_path, path_normalized_from_string(scratch.arena, event->string)); debug_info_path->timestamp = event->timestamp; scratch_end(scratch); }break; //- rjf: dynamic, program-created breakpoints case CTRL_EventKind_SetBreakpoint: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *bp = ctrl_entity_alloc(store, process, CTRL_EntityKind_Breakpoint, Arch_Null, ctrl_handle_zero(), 0); bp->vaddr_range = event->vaddr_rng; bp->bp_flags = event->bp_flags; }break; case CTRL_EventKind_UnsetBreakpoint: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); for(CTRL_Entity *child = process->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == CTRL_EntityKind_Breakpoint && child->vaddr_range.min == event->vaddr_rng.min && child->vaddr_range.max == event->vaddr_rng.max && child->bp_flags == event->bp_flags) { ctrl_entity_release(store, child); break; } } }break; //- rjf: address range annotations case CTRL_EventKind_SetVAddrRangeNote: { CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); CTRL_Entity *annotation = ctrl_entity_alloc(store, process, CTRL_EntityKind_AddressRangeAnnotation, Arch_Null, ctrl_handle_zero(), 0); annotation->vaddr_range = event->vaddr_rng; ctrl_entity_equip_string(store, annotation, event->string); }break; } } } //////////////////////////////// //~ rjf: Main Layer Initialization internal void ctrl_init(void) { Arena *arena = arena_alloc(); ctrl_state = push_array(arena, CTRL_State, 1); ctrl_state->arena = arena; for(Arch arch = (Arch)0; arch < Arch_COUNT; arch = (Arch)(arch+1)) { String8 *reg_names = regs_reg_code_string_table_from_arch(arch); U64 reg_count = regs_reg_code_count_from_arch(arch); String8 *alias_names = regs_alias_code_string_table_from_arch(arch); U64 alias_count = regs_alias_code_count_from_arch(arch); ctrl_state->arch_string2reg_tables[arch] = e_string2num_map_make(ctrl_state->arena, 256); ctrl_state->arch_string2alias_tables[arch] = e_string2num_map_make(ctrl_state->arena, 256); for(U64 idx = 1; idx < reg_count; idx += 1) { e_string2num_map_insert(ctrl_state->arena, &ctrl_state->arch_string2reg_tables[arch], reg_names[idx], idx); } for(U64 idx = 1; idx < alias_count; idx += 1) { e_string2num_map_insert(ctrl_state->arena, &ctrl_state->arch_string2alias_tables[arch], alias_names[idx], idx); } } ctrl_state->thread_reg_cache.slots_count = 1024; ctrl_state->thread_reg_cache.slots = push_array(arena, CTRL_ThreadRegCacheSlot, ctrl_state->thread_reg_cache.slots_count); ctrl_state->thread_reg_cache.stripes_count = os_get_system_info()->logical_processor_count; ctrl_state->thread_reg_cache.stripes = push_array(arena, CTRL_ThreadRegCacheStripe, ctrl_state->thread_reg_cache.stripes_count); for(U64 idx = 0; idx < ctrl_state->thread_reg_cache.stripes_count; idx += 1) { ctrl_state->thread_reg_cache.stripes[idx].arena = arena_alloc(); ctrl_state->thread_reg_cache.stripes[idx].rw_mutex = rw_mutex_alloc(); } ctrl_state->module_image_info_cache.slots_count = 1024; ctrl_state->module_image_info_cache.slots = push_array(arena, CTRL_ModuleImageInfoCacheSlot, ctrl_state->module_image_info_cache.slots_count); ctrl_state->module_image_info_cache.stripes_count = os_get_system_info()->logical_processor_count; ctrl_state->module_image_info_cache.stripes = push_array(arena, CTRL_ModuleImageInfoCacheStripe, ctrl_state->module_image_info_cache.stripes_count); for(U64 idx = 0; idx < ctrl_state->module_image_info_cache.stripes_count; idx += 1) { ctrl_state->module_image_info_cache.stripes[idx].arena = arena_alloc(); ctrl_state->module_image_info_cache.stripes[idx].rw_mutex = rw_mutex_alloc(); } ctrl_state->u2c_ring_size = KB(64); ctrl_state->u2c_ring_base = push_array_no_zero(arena, U8, ctrl_state->u2c_ring_size); ctrl_state->u2c_ring_mutex = mutex_alloc(); ctrl_state->u2c_ring_cv = cond_var_alloc(); ctrl_state->c2u_ring_size = KB(64); ctrl_state->c2u_ring_max_string_size = ctrl_state->c2u_ring_size/2; ctrl_state->c2u_ring_base = push_array_no_zero(arena, U8, ctrl_state->c2u_ring_size); ctrl_state->c2u_ring_mutex = mutex_alloc(); ctrl_state->c2u_ring_cv = cond_var_alloc(); { Temp scratch = scratch_begin(0, 0); String8 user_program_data_path = os_get_process_info()->user_program_data_path; String8 user_data_folder = push_str8f(scratch.arena, "%S/raddbg/logs", user_program_data_path); os_make_directory(user_data_folder); ctrl_state->ctrl_thread_log_path = push_str8f(ctrl_state->arena, "%S/ctrl_thread.raddbg_log", user_data_folder); os_write_data_to_file_path(ctrl_state->ctrl_thread_log_path, str8_zero()); scratch_end(scratch); } ctrl_state->ctrl_thread_entity_ctx_rw_mutex = rw_mutex_alloc(); ctrl_state->ctrl_thread_entity_store = ctrl_entity_ctx_rw_store_alloc(); ctrl_state->ctrl_thread_eval_cache = e_cache_alloc(); ctrl_state->ctrl_thread_msg_process_arena = arena_alloc(); ctrl_state->dmn_event_arena = arena_alloc(); ctrl_state->user_entry_point_arena = arena_alloc(); ctrl_state->dbg_dir_arena = arena_alloc(); for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)0; k < CTRL_ExceptionCodeKind_COUNT; k = (CTRL_ExceptionCodeKind)(k+1)) { if(ctrl_exception_code_kind_default_enable_table[k]) { ctrl_state->exception_code_filters[k/64] |= 1ull<<(k%64); } } ctrl_state->ctrl_thread_log = log_alloc(); ctrl_state->ctrl_thread = thread_launch(ctrl_thread__entry_point, 0); } //////////////////////////////// //~ rjf: Wakeup Callback Registration internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook) { ctrl_state->wakeup_hook = wakeup_hook; } //////////////////////////////// //~ rjf: Thread Register Functions //- rjf: thread register cache reading internal void * ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle handle) { CTRL_ThreadRegCache *cache = &ctrl_state->thread_reg_cache; CTRL_Entity *thread_entity = ctrl_entity_from_handle(ctx, handle); Arch arch = thread_entity->arch; U64 reg_block_size = regs_block_size_from_arch(arch); U64 hash = ctrl_hash_from_handle(handle); U64 slot_idx = hash%cache->slots_count; U64 stripe_idx = slot_idx%cache->stripes_count; CTRL_ThreadRegCacheSlot *slot = &cache->slots[slot_idx]; CTRL_ThreadRegCacheStripe *stripe = &cache->stripes[stripe_idx]; void *result = push_array(arena, U8, reg_block_size); MutexScopeW(stripe->rw_mutex) { // rjf: find existing node CTRL_ThreadRegCacheNode *node = 0; for(CTRL_ThreadRegCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->handle, handle)) { node = n; break; } } // rjf: allocate existing node if(!node) { node = push_array(stripe->arena, CTRL_ThreadRegCacheNode, 1); DLLPushBack(slot->first, slot->last, node); node->handle = handle; node->block_size = reg_block_size; node->block = push_array(stripe->arena, U8, reg_block_size); } // rjf: copy from node if(node) { U64 current_reg_gen = ctrl_reg_gen(); B32 need_stale = 1; if(node->reg_gen != current_reg_gen && dmn_thread_read_reg_block(handle.dmn_handle, result)) { if(node != 0) { need_stale = 0; node->reg_gen = current_reg_gen; MemoryCopy(node->block, result, reg_block_size); } } if(need_stale) { MemoryCopy(result, node->block, reg_block_size); } } } return result; } internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle) { U64 result = dmn_tls_root_vaddr_from_thread(handle.dmn_handle); return result; } internal U64 ctrl_rip_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle) { Temp scratch = scratch_begin(0, 0); CTRL_Entity *thread_entity = ctrl_entity_from_handle(ctx, handle); Arch arch = thread_entity->arch; void *block = ctrl_reg_block_from_thread(scratch.arena, ctx, handle); U64 result = regs_rip_from_arch_block(arch, block); scratch_end(scratch); return result; } internal U64 ctrl_rsp_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle) { Temp scratch = scratch_begin(0, 0); CTRL_Entity *thread_entity = ctrl_entity_from_handle(ctx, handle); Arch arch = thread_entity->arch; void *block = ctrl_reg_block_from_thread(scratch.arena, ctx, handle); U64 result = regs_rsp_from_arch_block(arch, block); scratch_end(scratch); return result; } //- rjf: thread register writing internal B32 ctrl_thread_write_reg_block(CTRL_Handle thread, void *block) { // TODO(rjf): @callstacks immediately reflect this in the call stack cache B32 good = dmn_thread_write_reg_block(thread.dmn_handle, block); if(good) { ins_atomic_u64_inc_eval(&ctrl_state->reg_gen); } return good; } //////////////////////////////// //~ rjf: Module Image Info Functions //- rjf: cache lookups internal PE_IntelPdata * ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_Handle module_handle, U64 voff) { PE_IntelPdata *first_pdata = 0; { U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module_handle)) { PE_IntelPdata *pdatas = n->pdatas; U64 pdatas_count = n->pdatas_count; if(n->pdatas_count != 0 && voff >= n->pdatas[0].voff_first) { // NOTE(rjf): // // binary search: // find max index s.t. pdata_array[index].voff_first <= voff // we assume (i < j) -> (pdata_array[i].voff_first < pdata_array[j].voff_first) U64 index = pdatas_count; U64 min = 0; U64 opl = pdatas_count; for(;;) { U64 mid = (min + opl)/2; PE_IntelPdata *pdata = pdatas + mid; if(voff < pdata->voff_first) { opl = mid; } else if(pdata->voff_first < voff) { min = mid; } else { index = mid; break; } if(min + 1 >= opl) { index = min; break; } } // rjf: if we are in range fill result { PE_IntelPdata *pdata = pdatas + index; if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last) { first_pdata = push_array(arena, PE_IntelPdata, 1); MemoryCopyStruct(first_pdata, pdata); } } } break; } } } return first_pdata; } internal U64 ctrl_entry_point_voff_from_module(CTRL_Handle module_handle) { U64 result = 0; U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module_handle)) { result = n->entry_point_voff; break; } } return result; } internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_Handle module_handle) { Rng1U64 result = {0}; U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module_handle)) { result = n->tls_vaddr_range; break; } } return result; } internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle) { String8 result = {0}; U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module_handle)) { result = push_str8_copy(arena, n->initial_debug_info_path); break; } } return result; } internal String8 ctrl_raddbg_data_from_module(Arena *arena, CTRL_Handle module_handle) { String8 result = {0}; U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module_handle)) { result = push_str8_copy(arena, n->raddbg_data); break; } } return result; } //////////////////////////////// //~ Process Info Functions internal Arch ctrl_arch_from_process_handle(CTRL_Handle process_handle) { CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_Entity *process_entity = ctrl_entity_from_handle(entity_ctx, process_handle); return process_entity->arch; } //////////////////////////////// //~ rjf: Unwinding Functions //- rjf: unwind deep copier internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Arch arch, CTRL_Unwind *src) { CTRL_Unwind dst = {0}; { dst.flags = src->flags; dst.frames.count = src->frames.count; dst.frames.v = push_array(arena, CTRL_UnwindFrame, dst.frames.count); MemoryCopy(dst.frames.v, src->frames.v, sizeof(dst.frames.v[0])*dst.frames.count); U64 block_size = regs_block_size_from_arch(arch); for(U64 idx = 0; idx < dst.frames.count; idx += 1) { dst.frames.v[idx].regs = push_array_no_zero(arena, U8, block_size); MemoryCopy(dst.frames.v[idx].regs, src->frames.v[idx].regs, block_size); } } return dst; } //- DWARF typedef struct { CTRL_Handle process_handle; U64 endt_us; } CTRL_MemoryReadContextDwarfX64; internal DW_MEM_READ(ctrl_unwind_mem_read_dwarf_x64) { CTRL_MemoryReadContextDwarfX64 *ctx = ud; B32 is_stale = 0; B32 is_read = ctrl_process_memory_read(ctx->process_handle, r1u64(addr, addr + size), &is_stale, buffer, ctx->endt_us); DW_UnwindStatus status = DW_UnwindStatus_Fail; if(is_stale && is_read) { status = DW_UnwindStatus_Maybe; } else if(is_read) { status = DW_UnwindStatus_Ok; } return status; } internal DW_REG_READ(ctrl_unwind_reg_read_dwarf_x64) { // map DWARF register to -> the internal register REGS_RegBlockX64 *regs = ud; U64 reg_size = 0; void *reg_bytes = 0; switch(reg_id) { #define X(_N, _ID, _MAP_N, ...) case _ID: { reg_size = sizeof(regs->_MAP_N); reg_bytes = ®s->_MAP_N; } break; DW_Regs_X64_XList(X) #undef X default: { InvalidPath; } break; } // copy out register value DW_UnwindStatus status = DW_UnwindStatus_Fail; if(reg_size > 0) { AssertAlways(reg_size == buffer_max); MemoryCopy(buffer, reg_bytes, reg_size); status = DW_UnwindStatus_Ok; } return status; } internal DW_REG_WRITE(ctrl_unwind_reg_write_dwarf_x64) { // map DWARF register to -> the internal register REGS_RegBlockX64 *regs = ud; U64 reg_size = 0; void *reg_bytes = 0; switch(reg_id) { #define X(_N, _ID, _MAP_N, ...) case _ID: { reg_size = sizeof(regs->_MAP_N); reg_bytes = ®s->_MAP_N; } break; DW_Regs_X64_XList(X) #undef X default: { InvalidPath; } break; } // write value to the register DW_UnwindStatus status = DW_UnwindStatus_Fail; if(reg_size > 0) { AssertAlways(value_size <= reg_size); MemoryCopy(reg_bytes, value, value_size); status = DW_UnwindStatus_Ok; } return status; } internal CTRL_UnwindStepResult ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, Arch arch, void *regs, U64 endt_us) { Temp scratch = scratch_begin(0, 0); CTRL_UnwindStepResult result = { .flags = CTRL_UnwindFlag_Error }; // gather context for virtual stack unwinder U64 cfi_rebase = 0; B32 is_unwind_eh = 0; String8 unwind_data = {0}; EH_FrameHdr eh_frame_hdr = {0}; EH_PtrCtx eh_ptr_ctx = {0}; { U64 hash = ctrl_hash_from_handle(module_handle); U64 slot_idx = hash % ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx % ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeR(stripe->rw_mutex) for EachNode(n, CTRL_ModuleImageInfoCacheNode, slot->first) { if(ctrl_handle_match(n->module, module_handle)) { cfi_rebase = n->cfi_rebase; is_unwind_eh = n->is_unwind_eh; unwind_data = n->dwarf_unwind_data; eh_frame_hdr = n->eh_frame_hdr; eh_ptr_ctx = n->eh_ptr_ctx; break; } } } // grab IP U64 ip = regs_rip_from_arch_block(arch, regs); // use .eh_frame_hdr to quickly locate nearest FDE U64 fde_addr = eh_find_nearest_fde(eh_frame_hdr, &eh_ptr_ctx, ip); if(fde_addr != max_U64) { // parse call frame info DW_CIE cie = {0}; DW_FDE fde = {0}; B32 is_cfi_parsed = 0; if(is_unwind_eh) { B32 is_stale = 0; // extract FDE info Rng1U64 fde_vrange = {0}; DW_Format fde_format = DW_Format_Null; String8 fde_data = {0}; U64 cie_addr = 0; { // parse FDE length U32 first_four_bytes = 0; if(!ctrl_process_memory_read_struct(process_handle, fde_addr, &is_stale, &first_four_bytes, endt_us)) { goto eh_parse_exit; } if(first_four_bytes == max_U32) { U64 length = 0; if(!ctrl_process_memory_read_struct(process_handle, fde_addr + sizeof(first_four_bytes), &is_stale, &length, endt_us)) { goto eh_parse_exit; } fde_vrange = r1u64(fde_addr, fde_addr + sizeof(first_four_bytes) + length); fde_format = DW_Format_64Bit; } else { fde_vrange = r1u64(fde_addr, fde_addr + sizeof(first_four_bytes) + first_four_bytes); fde_format = DW_Format_32Bit; } // read out whole FDE void *fde_raw = push_array(scratch.arena, U8, dim_1u64(fde_vrange)); if(!ctrl_process_memory_read(process_handle, fde_vrange, &is_stale, fde_raw, endt_us)) { goto eh_parse_exit; } fde_data = str8(fde_raw, dim_1u64(fde_vrange)); // compute CIE address U64 cie_delta_off = fde_format == DW_Format_32Bit ? 4 : 12; U64 cie_delta = 0; U64 cie_delta_size = str8_deserial_read_dwarf_uint(fde_data, cie_delta_off, fde_format, &cie_delta); if (cie_delta_size == 0) { goto eh_parse_exit; } cie_addr = (fde_addr + cie_delta_off) - cie_delta; } // extract CIE info Rng1U64 cie_vrange = {0}; DW_Format cie_format = DW_Format_Null; String8 cie_data = {0}; { // parse CIE length U32 first_four_bytes = 0; if(!ctrl_process_memory_read_struct(process_handle, cie_addr, &is_stale, &first_four_bytes, endt_us)) { goto eh_parse_exit; } if(first_four_bytes == max_U32) { U64 length = 0; if(!ctrl_process_memory_read_struct(process_handle, cie_addr + sizeof(first_four_bytes), &is_stale, &length, endt_us)) { goto eh_parse_exit; } cie_vrange = r1u64(cie_addr, cie_addr + sizeof(first_four_bytes) + length); cie_format = DW_Format_64Bit; } else { cie_vrange = r1u64(cie_addr, cie_addr + sizeof(first_four_bytes) + first_four_bytes); cie_format = DW_Format_32Bit; } // read out whole CIE void *cie_raw = push_array(scratch.arena, U8, dim_1u64(cie_vrange)); if(!ctrl_process_memory_read(process_handle, cie_vrange, &is_stale, cie_raw, endt_us)) { goto eh_parse_exit; } cie_data = str8(cie_raw, dim_1u64(cie_vrange)); } // parse CIE and FDE if(eh_parse_cie(cie_data, cie_format, arch, cie_vrange.min, &eh_ptr_ctx, &cie)) { is_cfi_parsed = eh_parse_fde(fde_data, fde_format, fde_vrange.min, &cie, &eh_ptr_ctx, &fde); } eh_parse_exit:; if(is_stale) { result.flags = CTRL_UnwindFlag_Stale; } } else { is_cfi_parsed = dw_parse_cfi(unwind_data, fde_addr, arch, &cie, &fde); } if(is_cfi_parsed && contains_1u64(fde.pc_range, ip)) { // setup pointer decoder ops DW_DecodePtr *decode_ptr_func = 0; void *decode_ptr_ctx = 0; if(is_unwind_eh) { EH_DecodePtrCtx *decode_ptr_ctx_eh = push_array(scratch.arena, EH_DecodePtrCtx, 1); decode_ptr_ctx_eh->ptr_ctx = &eh_ptr_ctx; decode_ptr_ctx_eh->addr_enc = cie.ext[EH_CIE_Ext_AddrEnc]; decode_ptr_func = eh_decode_ptr; decode_ptr_ctx = decode_ptr_ctx_eh; } else { decode_ptr_func = dw_decode_ptr_debug_frame; decode_ptr_ctx = &cie; } // find register rules for IP DW_CFI_Row *cfi_row = dw_cfi_row_from_pc(scratch.arena, arch, &cie, &fde, decode_ptr_func, decode_ptr_ctx, ip); if(cfi_row) { // setup machine ops void *mem_read_ctx = 0; void *reg_read_ctx = 0; void *reg_write_ctx = 0; DW_MemRead *mem_read_func = 0; DW_RegRead *reg_read_func = 0; DW_RegWrite *reg_write_func = 0; switch(arch) { case Arch_Null: break; case Arch_x64: { CTRL_MemoryReadContextDwarfX64 *mem_read_ctx_x64 = push_array(scratch.arena, CTRL_MemoryReadContextDwarfX64, 1); mem_read_ctx_x64->process_handle = process_handle; mem_read_ctx_x64->endt_us = endt_us; mem_read_ctx = mem_read_ctx_x64; reg_read_ctx = regs; reg_write_ctx = regs; mem_read_func = ctrl_unwind_mem_read_dwarf_x64; reg_read_func = ctrl_unwind_reg_read_dwarf_x64; reg_write_func = ctrl_unwind_reg_write_dwarf_x64; }break; case Arch_x86: case Arch_arm64: case Arch_arm32: { NotImplemented; }break; default: { InvalidPath; } break; } // apply register rules to the context DW_UnwindStatus cfi_uw_status = dw_cfi_apply_register_rules(arch, &cie, cfi_row, mem_read_func, mem_read_ctx, reg_read_func, reg_read_ctx, reg_write_func, reg_write_ctx); // last frame typically has undefined rule for IP if(cfi_row->regs[cie.ret_addr_reg].rule == DW_CFI_RegisterRule_Undefined) { regs_arch_block_write_rip(arch, regs, 0); } // translate unwind status code to control layer's result flags switch(cfi_uw_status) { case DW_UnwindStatus_Ok: { result.flags &= ~(CTRL_UnwindFlag_Error|CTRL_UnwindFlag_Stale); }break; case DW_UnwindStatus_Fail: { result.flags |= CTRL_UnwindFlag_Error; }break; case DW_UnwindStatus_Maybe: { result.flags &= ~CTRL_UnwindFlag_Error; result.flags |= CTRL_UnwindFlag_Stale; }break; default: { InvalidPath; } break; } } } } else { // TODO: if IP does not have FDE, does this mean function is a leaf? } scratch_end(scratch); return result; } //- rjf: [x64] internal REGS_Reg64 * ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg) { local_persist REGS_Reg64 dummy = {0}; REGS_Reg64 *result = &dummy; switch(gpr_reg) { case PE_UnwindGprRegX64_RAX:{result = ®s->rax;}break; case PE_UnwindGprRegX64_RCX:{result = ®s->rcx;}break; case PE_UnwindGprRegX64_RDX:{result = ®s->rdx;}break; case PE_UnwindGprRegX64_RBX:{result = ®s->rbx;}break; case PE_UnwindGprRegX64_RSP:{result = ®s->rsp;}break; case PE_UnwindGprRegX64_RBP:{result = ®s->rbp;}break; case PE_UnwindGprRegX64_RSI:{result = ®s->rsi;}break; case PE_UnwindGprRegX64_RDI:{result = ®s->rdi;}break; case PE_UnwindGprRegX64_R8 :{result = ®s->r8 ;}break; case PE_UnwindGprRegX64_R9 :{result = ®s->r9 ;}break; case PE_UnwindGprRegX64_R10:{result = ®s->r10;}break; case PE_UnwindGprRegX64_R11:{result = ®s->r11;}break; case PE_UnwindGprRegX64_R12:{result = ®s->r12;}break; case PE_UnwindGprRegX64_R13:{result = ®s->r13;}break; case PE_UnwindGprRegX64_R14:{result = ®s->r14;}break; case PE_UnwindGprRegX64_R15:{result = ®s->r15;}break; } return result; } internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_Handle process_handle, CTRL_Handle module_handle, U64 module_base_vaddr, REGS_RegBlockX64 *regs, U64 endt_us) { B32 is_stale = 0; B32 is_good = 1; Temp scratch = scratch_begin(0, 0); ////////////////////////////// //- rjf: unpack parameters // U64 rip_voff = regs->rip.u64 - module_base_vaddr; ////////////////////////////// //- rjf: rip_voff -> first pdata // PE_IntelPdata *first_pdata = ctrl_intel_pdata_from_module_voff(scratch.arena, module_handle, rip_voff); ////////////////////////////// //- rjf: pdata -> detect if in epilog // B32 has_pdata_and_in_epilog = 0; if(first_pdata) ProfScope("pdata -> detect if in epilog") { // NOTE(allen): There are restrictions placed on how an epilog is allowed // to be formed (https://docs.microsoft.com/en-us/cpp/build/prolog-and-epilog?view=msvc-160) // Here we interpret machine code directly according to the rules // given there to determine if the code we're looking at looks like an epilog. //- rjf: set up parsing state B32 is_epilog = 0; B32 keep_parsing = 1; U64 read_vaddr = regs->rip.u64; U64 read_vaddr_opl = read_vaddr + 256; //- rjf: check first instruction { B32 inst_good = 0; U8 inst[4] = {0}; if(read_vaddr + sizeof(inst) <= read_vaddr_opl) { inst_good = ctrl_process_memory_read(process_handle, r1u64(read_vaddr, read_vaddr+sizeof(inst)), &is_stale, inst, endt_us); inst_good = inst_good && !is_stale; } if(!inst_good) { keep_parsing = 0; } else if((inst[0] & 0xF8) == 0x48) { switch(inst[1]) { // rjf: add $nnnn,%rsp case 0x81: { if(inst[0] == 0x48 && inst[2] == 0xC4) { read_vaddr += 7; } else { keep_parsing = 0; } }break; // rjf: add $n,%rsp case 0x83: { if(inst[0] == 0x48 && inst[2] == 0xC4) { read_vaddr += 4; } else { keep_parsing = 0; } }break; // rjf: lea n(reg),%rsp case 0x8D: { if((inst[0] & 0x06) == 0 && ((inst[2] >> 3) & 0x07) == 0x04 && (inst[2] & 0x07) != 0x04) { U8 imm_size = (inst[2] >> 6); // rjf: 1-byte immediate if(imm_size == 1) { read_vaddr += 4; } // rjf: 4-byte immediate else if(imm_size == 2) { read_vaddr += 7; } // rjf: other case else { keep_parsing = 0; } } else { keep_parsing = 0; } }break; } } } //- rjf: continue parsing instructions for(;keep_parsing;) { // rjf: read next instruction byte B32 inst_byte_good = 0; U8 inst_byte = 0; if(read_vaddr + sizeof(inst_byte) <= read_vaddr_opl) { inst_byte_good = ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); } if(!inst_byte_good || is_stale) { keep_parsing = 0; } // rjf: when (... I don't know ...) rely on the next byte B32 check_inst_byte_good = inst_byte_good; U64 check_vaddr = read_vaddr; U8 check_inst_byte = inst_byte; if(inst_byte_good && (inst_byte & 0xF0) == 0x40) { check_vaddr = read_vaddr + 1; if(read_vaddr + sizeof(check_inst_byte) <= read_vaddr_opl) { check_inst_byte_good = ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &check_inst_byte, endt_us); } if(!check_inst_byte_good || is_stale) { keep_parsing = 0; } } // rjf: check instruction byte if(check_inst_byte_good) { switch(check_inst_byte) { // rjf: pop case 0x58:case 0x59:case 0x5A:case 0x5B: case 0x5C:case 0x5D:case 0x5E:case 0x5F: { read_vaddr = check_vaddr + 1; }break; // rjf: ret case 0xC2: case 0xC3: { is_epilog = 1; keep_parsing = 0; }break; // rjf: jmp nnnn case 0xE9: { U64 imm_vaddr = check_vaddr + 1; S32 imm = 0; B32 imm_good = 0; if(read_vaddr + sizeof(imm) <= read_vaddr_opl) { imm_good = ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us); } if(!imm_good || is_stale) { keep_parsing = 0; } if(imm_good) { U64 next_vaddr = (U64)(imm_vaddr + sizeof(imm) + imm); U64 next_voff = next_vaddr - module_base_vaddr; // TODO(rjf): verify that this offset is from module base vaddr, not section if(!(first_pdata->voff_first <= next_voff && next_voff < first_pdata->voff_one_past_last)) { keep_parsing = 0; } else { read_vaddr = next_vaddr; } } // TODO(allen): why isn't this just the end of the epilog? }break; // rjf: rep; ret (for amd64 prediction bug) case 0xF3: { U8 next_inst_byte = 0; B32 next_inst_byte_good = 0; if(read_vaddr + sizeof(next_inst_byte) <= read_vaddr_opl) { next_inst_byte_good = ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &next_inst_byte, endt_us); } if(next_inst_byte_good) { is_epilog = (next_inst_byte == 0xC3); } keep_parsing = 0; }break; default:{keep_parsing = 0;}break; } } } has_pdata_and_in_epilog = is_epilog; } ////////////////////////////// //- rjf: pdata & in epilog -> epilog unwind // if(first_pdata && has_pdata_and_in_epilog) ProfScope("pdata & in epilog -> epilog unwind") { U64 read_vaddr = regs->rip.u64; for(B32 keep_parsing = 1;keep_parsing != 0;) { //- rjf: assume no more parsing after this instruction keep_parsing = 0; //- rjf: read next instruction byte U8 inst_byte = 0; is_good = is_good && ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); is_good = is_good && !is_stale; read_vaddr += 1; //- rjf: extract rex from instruction byte U8 rex = 0; if((inst_byte & 0xF0) == 0x40) { rex = inst_byte & 0xF; // rex prefix is_good = is_good && ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &inst_byte, endt_us); is_good = is_good && !is_stale; read_vaddr += 1; } //- rjf: parse remainder of instruction switch(inst_byte) { // rjf: pop case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: { // rjf: read value at rsp U64 sp = regs->rsp.u64; U64 value = 0; if(!ctrl_process_memory_read_struct(process_handle, sp, &is_stale, &value, endt_us) || is_stale) { is_good = 0; break; } // rjf: modify registers PE_UnwindGprRegX64 gpr_reg = (inst_byte - 0x58) + (rex & 1)*8; REGS_Reg64 *reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, gpr_reg); reg->u64 = value; regs->rsp.u64 = sp + 8; // rjf: not a final instruction, so keep mparsing keep_parsing = 1; }break; // rjf: add $nnnn,%rsp case 0x81: { // rjf: skip one byte (we already know what it is in this scenario) read_vaddr += 1; // rjf: read the 4-byte immediate S32 imm = 0; if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || is_stale) { is_good = 0; break; } read_vaddr += 4; // rjf: update stack pointer regs->rsp.u64 = (U64)(regs->rsp.u64 + imm); // rjf: not a final instruction; keep parsing keep_parsing = 1; }break; // rjf: add $n,%rsp case 0x83: { // rjf: skip one byte (we already know what it is in this scenario) read_vaddr += 1; // rjf: read the 4-byte immediate S8 imm = 0; if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || is_stale) { is_good = 0; break; } read_vaddr += 1; // rjf: update stack pointer regs->rsp.u64 = (U64)(regs->rsp.u64 + imm); // rjf: not a final instruction; keep parsing keep_parsing = 1; }break; // rjf: lea imm8/imm32,$rsp case 0x8D: { // rjf: read source register U8 modrm = 0; if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &modrm, endt_us) || is_stale) { is_good = 0; break; } read_vaddr += 1; PE_UnwindGprRegX64 gpr_reg = (modrm & 7) + (rex & 1)*8; REGS_Reg64 *reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, gpr_reg); U64 reg_value = reg->u64; // rjf: read immediate S32 imm = 0; { // rjf: read 1-byte immediate if((modrm >> 6) == 1) { S8 imm8 = 0; if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm8, endt_us) || is_stale) { is_good = 0; break; } read_vaddr += 1; imm = (S32)imm8; } // rjf: read 4-byte immediate else { if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || is_stale) { is_good = 0; break; } read_vaddr += 4; } } // rjf: update stack pointer regs->rsp.u64 = (U64)(reg_value + imm); // rjf: not a final instruction; keep parsing keep_parsing = 1; }break; // rjf: ret $nn case 0xC2: { // rjf: read new ip U64 sp = regs->rsp.u64; U64 new_ip = 0; if(!ctrl_process_memory_read_struct(process_handle, sp, &is_stale, &new_ip, endt_us) || is_stale) { is_good = 0; break; } // rjf: read 2-byte immediate & advance stack pointer U16 imm = 0; if(!ctrl_process_memory_read_struct(process_handle, read_vaddr, &is_stale, &imm, endt_us) || is_stale) { is_good = 0; break; } U64 new_sp = sp + 8 + imm; // rjf: commit registers regs->rip.u64 = new_ip; regs->rsp.u64 = new_sp; }break; // rjf: ret / rep; ret case 0xF3: { // Assert(!"Hit me!"); }break; case 0xC3: { // rjf: read new ip U64 sp = regs->rsp.u64; U64 new_ip = 0; if(!ctrl_process_memory_read_struct(process_handle, sp, &is_stale, &new_ip, endt_us) || is_stale) { is_good = 0; break; } // rjf: advance stack pointer U64 new_sp = sp + 8; // rjf: commit registers regs->rip.u64 = new_ip; regs->rsp.u64 = new_sp; }break; // rjf: jmp nnnn case 0xE9: { // Assert(!"Hit Me"); // TODO(allen): general idea: read the immediate, move the ip, leave the sp, done // we don't have any cases to exercise this right now. no guess implementation! }break; // rjf: Sjmp n case 0xEB: { // Assert(!"Hit Me"); // TODO(allen): general idea: read the immediate, move the ip, leave the sp, done // we don't have any cases to exercise this right now. no guess implementation! }break; } } } ////////////////////////////// //- rjf: pdata & not in epilog -> xdata unwind // B32 xdata_unwind_did_machframe = 0; if(first_pdata && !has_pdata_and_in_epilog) ProfScope("pdata & not in epilog -> xdata unwind") { //- rjf: get frame reg B32 bad_frame_reg_info = 0; REGS_Reg64 *frame_reg = 0; U64 frame_off = 0; { U64 unwind_info_off = first_pdata->voff_unwind_info; PE_UnwindInfo unwind_info = {0}; if(!ctrl_process_memory_read_struct(process_handle, module_base_vaddr+unwind_info_off, &is_stale, &unwind_info, endt_us) || is_stale) { is_good = 0; } U32 frame_reg_id = PE_UNWIND_INFO_REG_FROM_FRAME(unwind_info.frame); U64 frame_off_val = PE_UNWIND_INFO_OFF_FROM_FRAME(unwind_info.frame); if(frame_reg_id != 0) { frame_reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, frame_reg_id); bad_frame_reg_info = (frame_reg == 0); // NOTE(rjf): frame_reg should never be 0 at this point, in valid exe } frame_off = frame_off_val; } //- rjf: iterate pdatas, apply opcodes PE_IntelPdata *last_pdata = 0; PE_IntelPdata *pdata = first_pdata; if(!bad_frame_reg_info) for(B32 keep_parsing = 1; keep_parsing && pdata != last_pdata;) { //- rjf: unpack unwind info & codes B32 good_unwind_info = 1; U64 unwind_info_off = pdata->voff_unwind_info; PE_UnwindInfo unwind_info = {0}; good_unwind_info = good_unwind_info && ctrl_process_memory_read_struct(process_handle, module_base_vaddr+unwind_info_off, &is_stale, &unwind_info, endt_us); PE_UnwindCode *unwind_codes = push_array(scratch.arena, PE_UnwindCode, unwind_info.codes_num); good_unwind_info = good_unwind_info && ctrl_process_memory_read(process_handle, r1u64(module_base_vaddr+unwind_info_off+sizeof(unwind_info), module_base_vaddr+unwind_info_off+sizeof(unwind_info)+sizeof(PE_UnwindCode)*unwind_info.codes_num), &is_stale, unwind_codes, endt_us); good_unwind_info = good_unwind_info && !is_stale; //- rjf: bad unwind info -> abort if(!good_unwind_info) { is_good = 0; break; } //- rjf: unpack frame base U64 frame_base = regs->rsp.u64; if(frame_reg != 0) { U64 raw_frame_base = frame_reg->u64; U64 adjusted_frame_base = raw_frame_base - frame_off*16; frame_base = adjusted_frame_base; } //- rjf: apply opcodes PE_UnwindCode *code_ptr = unwind_codes; PE_UnwindCode *code_opl = unwind_codes + unwind_info.codes_num; for(PE_UnwindCode *next_code_ptr = 0; code_ptr < code_opl; code_ptr = next_code_ptr) { // rjf: unpack opcode info U32 op_code = PE_UNWIND_OPCODE_FROM_FLAGS(code_ptr->flags); U32 op_info = PE_UNWIND_INFO_FROM_FLAGS(code_ptr->flags); U32 slot_count = pe_slot_count_from_unwind_op_code(op_code); if(op_code == PE_UnwindOpCode_ALLOC_LARGE && op_info == 1) { slot_count += 1; } // rjf: detect bad slot counts if(slot_count == 0 || code_ptr+slot_count > code_opl) { keep_parsing = 0; is_good = 0; break; } // rjf: set next op code pointer next_code_ptr = code_ptr + slot_count; // rjf: interpret this op code U64 code_voff = pdata->voff_first + code_ptr->off_in_prolog; if(code_voff <= rip_voff) { switch(op_code) { case PE_UnwindOpCode_PUSH_NONVOL: { // rjf: read value from stack pointer U64 rsp = regs->rsp.u64; U64 value = 0; if(!ctrl_process_memory_read_struct(process_handle, rsp, &is_stale, &value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } // rjf: advance stack ptr U64 new_rsp = rsp + 8; // rjf: commit registers REGS_Reg64 *reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); reg->u64 = value; regs->rsp.u64 = new_rsp; }break; case PE_UnwindOpCode_ALLOC_LARGE: { // rjf: read alloc size U64 size = 0; if(op_info == 0) { size = code_ptr[1].u16*8; } else if(op_info == 1) { size = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); } else { keep_parsing = 0; is_good = 0; break; } // rjf: advance stack pointer U64 rsp = regs->rsp.u64; U64 new_rsp = rsp + size; // rjf: advance stack pointer regs->rsp.u64 = new_rsp; }break; case PE_UnwindOpCode_ALLOC_SMALL: { // rjf: advance stack pointer regs->rsp.u64 += op_info*8 + 8; }break; case PE_UnwindOpCode_SET_FPREG: { // rjf: put stack pointer back to the frame base regs->rsp.u64 = frame_base; }break; case PE_UnwindOpCode_SAVE_NONVOL: { // rjf: read value from frame base U64 off = code_ptr[1].u16*8; U64 addr = frame_base + off; U64 value = 0; if(!ctrl_process_memory_read_struct(process_handle, addr, &is_stale, &value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } // rjf: commit to register REGS_Reg64 *reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); reg->u64 = value; }break; case PE_UnwindOpCode_SAVE_NONVOL_FAR: { // rjf: read value from frame base U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); U64 addr = frame_base + off; U64 value = 0; if(!ctrl_process_memory_read_struct(process_handle, addr, &is_stale, &value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } // rjf: commit to register REGS_Reg64 *reg = ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(regs, op_info); reg->u64 = value; }break; case PE_UnwindOpCode_EPILOG: { keep_parsing = 1; }break; case PE_UnwindOpCode_SPARE_CODE: { // TODO(rjf): ??? keep_parsing = 0; is_good = 0; }break; case PE_UnwindOpCode_SAVE_XMM128: { // rjf: read new register values U8 buf[16]; U64 off = code_ptr[1].u16*16; U64 addr = frame_base + off; if(!ctrl_process_memory_read(process_handle, r1u64(addr, addr+sizeof(buf)), &is_stale, buf, endt_us)) { keep_parsing = 0; is_good = 0; break; } // rjf: commit to register void *xmm_reg = (®s->zmm0) + op_info; MemoryCopy(xmm_reg, buf, sizeof(buf)); }break; case PE_UnwindOpCode_SAVE_XMM128_FAR: { // rjf: read new register values U8 buf[16]; U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); U64 addr = frame_base + off; if(!ctrl_process_memory_read(process_handle, r1u64(addr, addr+16), &is_stale, buf, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } // rjf: commit to register void *xmm_reg = (®s->zmm0) + op_info; MemoryCopy(xmm_reg, buf, sizeof(buf)); }break; case PE_UnwindOpCode_PUSH_MACHFRAME: { // NOTE(rjf): this was found by stepping through kernel code after an exception was // thrown, encountered in the exception_stepping_tests (after the throw) in mule_main if(op_info > 1) { keep_parsing = 0; is_good = 0; break; } // rjf: read values U64 sp_og = regs->rsp.u64; U64 sp_adj = sp_og; if(op_info == 1) { sp_adj += 8; } U64 ip_value = 0; if(!ctrl_process_memory_read_struct(process_handle, sp_adj, &is_stale, &ip_value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } U64 sp_after_ip = sp_adj + 8; U16 ss_value = 0; if(!ctrl_process_memory_read_struct(process_handle, sp_after_ip, &is_stale, &ss_value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } U64 sp_after_ss = sp_after_ip + 8; U64 rflags_value = 0; if(!ctrl_process_memory_read_struct(process_handle, sp_after_ss, &is_stale, &rflags_value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } U64 sp_after_rflags = sp_after_ss + 8; U64 sp_value = 0; if(!ctrl_process_memory_read_struct(process_handle, sp_after_rflags, &is_stale, &sp_value, endt_us) || is_stale) { keep_parsing = 0; is_good = 0; break; } // rjf: commit registers regs->rip.u64 = ip_value; regs->ss.u16 = ss_value; regs->rflags.u64 = rflags_value; regs->rsp.u64 = sp_value; // rjf: mark machine frame xdata_unwind_did_machframe = 1; }break; } } } //- rjf: iterate to next pdata if(keep_parsing) { U32 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(unwind_info.header); if(!(flags & PE_UnwindInfoFlag_CHAINED)) { break; } U64 code_count_rounded = AlignPow2(unwind_info.codes_num, sizeof(PE_UnwindCode)); U64 code_size = code_count_rounded*sizeof(PE_UnwindCode); U64 chained_pdata_off = unwind_info_off + sizeof(PE_UnwindInfo) + code_size; last_pdata = pdata; pdata = push_array(scratch.arena, PE_IntelPdata, 1); if(!ctrl_process_memory_read_struct(process_handle, module_base_vaddr+chained_pdata_off, &is_stale, pdata, endt_us) || is_stale) { is_good = 0; break; } } } } ////////////////////////////// //- rjf: no pdata, or didn't do machframe in xdata unwind -> unwind by reading stack pointer // if(!first_pdata || (!has_pdata_and_in_epilog && !xdata_unwind_did_machframe)) ProfScope("no pdata, or didn't do machframe in xdata unwind -> unwind by reading stack pointer") { // rjf: read rip from stack pointer U64 rsp = regs->rsp.u64; U64 new_rip = 0; if(!ctrl_process_memory_read_struct(process_handle, rsp, &is_stale, &new_rip, endt_us) || is_stale) { is_good = 0; } // rjf: commit registers if(is_good) { U64 new_rsp = rsp + 8; regs->rip.u64 = new_rip; regs->rsp.u64 = new_rsp; } } ////////////////////////////// //- rjf: fill & return // scratch_end(scratch); CTRL_UnwindStepResult result = {0}; if(!is_good) {result.flags |= CTRL_UnwindFlag_Error;} if(is_stale) {result.flags |= CTRL_UnwindFlag_Stale;} return result; } //- rjf: abstracted unwind step internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_Handle process, CTRL_Handle module, U64 module_base_vaddr, Arch arch, void *reg_block, U64 endt_us) { CTRL_UnwindStepResult result = {0}; result = ctrl_unwind_step__dwarf(process, module, arch, reg_block, endt_us); if(result.flags == CTRL_UnwindFlag_Error && ~result.flags & CTRL_UnwindFlag_Stale) { switch(arch) { default:{}break; case Arch_x64: { result = ctrl_unwind_step__pe_x64(process, module, module_base_vaddr, (REGS_RegBlockX64 *)reg_block, endt_us); }break; } } return result; } //- rjf: abstracted full unwind internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle thread, U64 endt_us) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); CTRL_Unwind unwind = {0}; unwind.flags |= CTRL_UnwindFlag_Error; //- rjf: unpack args CTRL_Entity *thread_entity = ctrl_entity_from_handle(ctx, thread); CTRL_Entity *process_entity = thread_entity->parent; Arch arch = thread_entity->arch; U64 arch_reg_block_size = regs_block_size_from_arch(arch); //- rjf: grab initial register block void *regs_block = ctrl_reg_block_from_thread(scratch.arena, ctx, thread); B32 regs_block_good = (arch != Arch_Null && regs_block != 0); //- rjf: loop & unwind CTRL_UnwindFrameNode *first_frame_node = 0; CTRL_UnwindFrameNode *last_frame_node = 0; U64 frame_node_count = 0; if(regs_block_good) { unwind.flags = 0; for(;;) { // rjf: regs -> rip*module U64 rip = regs_rip_from_arch_block(arch, regs_block); U64 rsp = regs_rsp_from_arch_block(arch, regs_block); CTRL_Entity *module = &ctrl_entity_nil; for(CTRL_Entity *m = process_entity->first; m != &ctrl_entity_nil; m = m->next) { if(m->kind == CTRL_EntityKind_Module && contains_1u64(m->vaddr_range, rip)) { module = m; break; } } // rjf: cancel on 0 rip/rsp if(rsp == 0 && rip == 0) { break; } // rjf: valid step -> push frame CTRL_UnwindFrameNode *frame_node = push_array(scratch.arena, CTRL_UnwindFrameNode, 1); CTRL_UnwindFrame *frame = &frame_node->v; frame->regs = push_array_no_zero(arena, U8, arch_reg_block_size); MemoryCopy(frame->regs, regs_block, arch_reg_block_size); DLLPushBack(first_frame_node, last_frame_node, frame_node); frame_node_count += 1; // rjf: unwind one step CTRL_UnwindStepResult step = ctrl_unwind_step(process_entity->handle, module->handle, module->vaddr_range.min, arch, regs_block, endt_us); unwind.flags |= step.flags; if(step.flags & CTRL_UnwindFlag_Error || regs_rsp_from_arch_block(arch, regs_block) == 0 || regs_rip_from_arch_block(arch, regs_block) == 0 || (regs_rsp_from_arch_block(arch, regs_block) == rsp && regs_rip_from_arch_block(arch, regs_block) == rip)) { break; } } } //- rjf: bake frames list into result array { unwind.frames.count = frame_node_count; unwind.frames.v = push_array(arena, CTRL_UnwindFrame, unwind.frames.count); U64 idx = 0; for(CTRL_UnwindFrameNode *n = first_frame_node; n != 0; n = n->next, idx += 1) { unwind.frames.v[idx] = n->v; } } scratch_end(scratch); ProfEnd(); return unwind; } //////////////////////////////// //~ rjf: Call Stack Building Functions internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, CTRL_Entity *process, CTRL_Unwind *base_unwind) { Temp scratch = scratch_begin(&arena, 1); Access *access = access_open(); Arch arch = process->arch; CTRL_CallStack result = {0}; { typedef struct FrameNode FrameNode; struct FrameNode { FrameNode *next; CTRL_CallStackFrame v; }; //- rjf: gather all frames FrameNode *first_frame = 0; FrameNode *last_frame = 0; U64 frame_count = 0; for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1) { // rjf: unpack CTRL_UnwindFrame *src = &base_unwind->frames.v[base_frame_idx]; U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); // rjf: build inline frames (minus parent & inline depth) FrameNode *first_inline_frame = 0; FrameNode *last_inline_frame = 0; U64 inline_frame_count = 0; for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) { FrameNode *dst_inline = push_array(scratch.arena, FrameNode, 1); if(first_inline_frame == 0) { first_inline_frame = dst_inline; } last_inline_frame = dst_inline; SLLQueuePush(first_frame, last_frame, dst_inline); dst_inline->v.unwind_count = base_frame_idx; dst_inline->v.regs = src->regs; frame_count += 1; inline_frame_count += 1; } // rjf: build concrete frame FrameNode *dst_base = push_array(scratch.arena, FrameNode, 1); SLLQueuePush(first_frame, last_frame, dst_base); dst_base->v.unwind_count = base_frame_idx; dst_base->v.regs = src->regs; frame_count += 1; // rjf: hook up inline frames to point to concrete frame, and to account for inline depth U64 inline_frame_idx = 0; for(FrameNode *inline_frame = first_inline_frame; inline_frame != 0; inline_frame = inline_frame->next, inline_frame_idx += 1) { inline_frame->v.inline_depth = inline_frame_count - inline_frame_idx; if(inline_frame == last_inline_frame) { break; } } } //- rjf: package result.frames_count = frame_count; result.frames = push_array(arena, CTRL_CallStackFrame, result.frames_count); result.concrete_frames_count = base_unwind->frames.count; result.concrete_frames = push_array(arena, CTRL_CallStackFrame *, result.concrete_frames_count); { U64 idx = 0; U64 concrete_idx = 0; for(FrameNode *n = first_frame; n != 0; n = n->next, idx += 1) { MemoryCopyStruct(&result.frames[idx], &n->v); if(n->v.inline_depth == 0 && concrete_idx < result.concrete_frames_count) { result.concrete_frames[concrete_idx] = &result.frames[idx]; concrete_idx += 1; } } } } access_close(access); scratch_end(scratch); return result; } internal CTRL_CallStackFrame * ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth) { CTRL_CallStackFrame *f = 0; { U64 base_frame_idx = 0; for(U64 idx = 0; idx < call_stack->frames_count; idx += 1) { if(call_stack->frames[idx].inline_depth == 0) { if(base_frame_idx == unwind_count) { f = &call_stack->frames[idx]; break; } base_frame_idx += 1; } } if(f != 0 && call_stack->frames + inline_depth < f) { f -= inline_depth; } } return f; } //////////////////////////////// //~ rjf: Halting All Attached Processes internal void ctrl_halt(void) { dmn_halt(0, 0); } //////////////////////////////// //~ rjf: Shared Accessor Functions //- rjf: generation counters internal U64 ctrl_run_gen(void) { U64 result = ins_atomic_u64_eval(&ctrl_state->run_gen); return result; } internal U64 ctrl_mem_gen(void) { U64 result = ins_atomic_u64_eval(&ctrl_state->mem_gen); return result; } internal U64 ctrl_reg_gen(void) { U64 result = ins_atomic_u64_eval(&ctrl_state->reg_gen); return result; } //- rjf: name -> register/alias hash tables, for eval internal E_String2NumMap * ctrl_string2reg_from_arch(Arch arch) { return &ctrl_state->arch_string2reg_tables[arch]; } internal E_String2NumMap * ctrl_string2alias_from_arch(Arch arch) { return &ctrl_state->arch_string2alias_tables[arch]; } //////////////////////////////// //~ rjf: Control-Thread Functions //- rjf: user -> control thread communication internal B32 ctrl_u2c_push_msgs(CTRL_MsgList *msgs, U64 endt_us) { Temp scratch = scratch_begin(0, 0); String8 msgs_srlzed_baked = ctrl_serialized_string_from_msg_list(scratch.arena, msgs); B32 good = 0; MutexScope(ctrl_state->u2c_ring_mutex) for(;;) { U64 unconsumed_size = (ctrl_state->u2c_ring_write_pos-ctrl_state->u2c_ring_read_pos); U64 available_size = ctrl_state->u2c_ring_size-unconsumed_size; U64 needed_size = sizeof(msgs_srlzed_baked.size) + msgs_srlzed_baked.size; if(available_size >= needed_size) { ctrl_state->u2c_ring_write_pos += ring_write_struct(ctrl_state->u2c_ring_base, ctrl_state->u2c_ring_size, ctrl_state->u2c_ring_write_pos, &msgs_srlzed_baked.size); ctrl_state->u2c_ring_write_pos += ring_write(ctrl_state->u2c_ring_base, ctrl_state->u2c_ring_size, ctrl_state->u2c_ring_write_pos, msgs_srlzed_baked.str, msgs_srlzed_baked.size); good = 1; break; } if(os_now_microseconds() >= endt_us) { break; } cond_var_wait(ctrl_state->u2c_ring_cv, ctrl_state->u2c_ring_mutex, endt_us); } if(good) { cond_var_broadcast(ctrl_state->u2c_ring_cv); } scratch_end(scratch); return good; } internal CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); String8 msgs_srlzed_baked = {0}; MutexScope(ctrl_state->u2c_ring_mutex) for(;;) { U64 unconsumed_size = (ctrl_state->u2c_ring_write_pos-ctrl_state->u2c_ring_read_pos); if(unconsumed_size >= sizeof(U64)) { U64 size_to_decode = 0; ctrl_state->u2c_ring_read_pos += ring_read_struct(ctrl_state->u2c_ring_base, ctrl_state->u2c_ring_size, ctrl_state->u2c_ring_read_pos, &size_to_decode); msgs_srlzed_baked.size = size_to_decode; msgs_srlzed_baked.str = push_array_no_zero(scratch.arena, U8, msgs_srlzed_baked.size); ctrl_state->u2c_ring_read_pos += ring_read(ctrl_state->u2c_ring_base, ctrl_state->u2c_ring_size, ctrl_state->u2c_ring_read_pos, msgs_srlzed_baked.str, size_to_decode); break; } cond_var_wait(ctrl_state->u2c_ring_cv, ctrl_state->u2c_ring_mutex, max_U64); } cond_var_broadcast(ctrl_state->u2c_ring_cv); CTRL_MsgList msgs = ctrl_msg_list_from_serialized_string(arena, msgs_srlzed_baked); scratch_end(scratch); return msgs; } //- rjf: control -> user thread communication internal void ctrl_c2u_push_events(CTRL_EventList *events) { if(events->count != 0) ProfScope("ctrl_c2u_push_events") { MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { ctrl_entity_store_apply_events(ctrl_state->ctrl_thread_entity_store, events); } for(CTRL_EventNode *n = events->first; n != 0; n = n ->next) { Temp scratch = scratch_begin(0, 0); String8 event_srlzed = ctrl_serialized_string_from_event(scratch.arena, &n->v, ctrl_state->c2u_ring_size-sizeof(U64)); MutexScope(ctrl_state->c2u_ring_mutex) for(;;) { U64 unconsumed_size = (ctrl_state->c2u_ring_write_pos-ctrl_state->c2u_ring_read_pos); U64 available_size = ctrl_state->c2u_ring_size-unconsumed_size; U64 needed_size = sizeof(event_srlzed.size) + event_srlzed.size; if(available_size >= needed_size) { ctrl_state->c2u_ring_write_pos += ring_write_struct(ctrl_state->c2u_ring_base, ctrl_state->c2u_ring_size, ctrl_state->c2u_ring_write_pos, &event_srlzed.size); ctrl_state->c2u_ring_write_pos += ring_write(ctrl_state->c2u_ring_base, ctrl_state->c2u_ring_size, ctrl_state->c2u_ring_write_pos, event_srlzed.str, event_srlzed.size); break; } cond_var_wait(ctrl_state->c2u_ring_cv, ctrl_state->c2u_ring_mutex, os_now_microseconds()+100); } cond_var_broadcast(ctrl_state->c2u_ring_cv); if(ctrl_state->wakeup_hook != 0) { ctrl_state->wakeup_hook(); } scratch_end(scratch); } } } internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); CTRL_EventList events = {0}; MutexScope(ctrl_state->c2u_ring_mutex) for(;;) { U64 unconsumed_size = (ctrl_state->c2u_ring_write_pos-ctrl_state->c2u_ring_read_pos); if(unconsumed_size >= sizeof(U64)) { U64 size_to_decode = 0; ctrl_state->c2u_ring_read_pos += ring_read_struct(ctrl_state->c2u_ring_base, ctrl_state->c2u_ring_size, ctrl_state->c2u_ring_read_pos, &size_to_decode); String8 event_srlzed = {0}; event_srlzed.size = size_to_decode; event_srlzed.str = push_array_no_zero(scratch.arena, U8, event_srlzed.size); ctrl_state->c2u_ring_read_pos += ring_read(ctrl_state->c2u_ring_base, ctrl_state->c2u_ring_size, ctrl_state->c2u_ring_read_pos, event_srlzed.str, event_srlzed.size); CTRL_Event *new_event = ctrl_event_list_push(arena, &events); *new_event = ctrl_event_from_serialized_string(arena, event_srlzed); } else { break; } } cond_var_broadcast(ctrl_state->c2u_ring_cv); scratch_end(scratch); ProfEnd(); return events; } //- rjf: entry point internal void ctrl_thread__entry_point(void *p) { ThreadNameF("ctrl_thread"); ProfBeginFunction(); DMN_CtrlCtx *ctrl_ctx = dmn_ctrl_begin(); log_select(ctrl_state->ctrl_thread_log); //- rjf: loop Temp scratch = scratch_begin(0, 0); for(;;) { temp_end(scratch); log_scope_begin(); //- rjf: get next messages CTRL_MsgList msgs = ctrl_u2c_pop_msgs(scratch.arena); //- rjf: process messages DMN_CtrlExclusiveAccessScope { ins_atomic_u64_eval_assign(&ctrl_state->ctrl_thread_run_state, 1); for(CTRL_MsgNode *msg_n = msgs.first; msg_n != 0; msg_n = msg_n->next) { CTRL_Msg *msg = &msg_n->v; { log_infof("user2ctrl_msg:{kind:\"%S\"}\n", ctrl_string_from_msg_kind(msg->kind)); } //- rjf: reset per-message state ProfScope("reset per-message state") { arena_clear(ctrl_state->ctrl_thread_msg_process_arena); ctrl_state->module_req_cache_slots_count = 4096; ctrl_state->module_req_cache_slots = push_array(ctrl_state->ctrl_thread_msg_process_arena, CTRL_ModuleReqCacheNode *, ctrl_state->module_req_cache_slots_count); MemoryZeroStruct(&ctrl_state->msg_user_bp_touched_files); MemoryZeroStruct(&ctrl_state->msg_user_bp_touched_symbols); MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters); } //- rjf: gather all touched symbols by user breakpoints { Temp scratch = scratch_begin(0, 0); for(CTRL_UserBreakpointNode *n = msg->user_bps.first; n != 0; n = n->next) { if(n->v.kind != CTRL_UserBreakpointKind_Expression) { continue; } E_Parse addr_parse = e_push_parse_from_string(scratch.arena, n->v.string); E_Parse cnd_parse = e_push_parse_from_string(scratch.arena, n->v.condition); E_Expr *exprs[] = {addr_parse.expr, cnd_parse.expr}; for EachElement(idx, exprs) { typedef struct ExprWalkTask ExprWalkTask; struct ExprWalkTask { ExprWalkTask *next; E_Expr *expr; }; ExprWalkTask start_task = {0, exprs[idx]}; ExprWalkTask *first_task = &start_task; for(ExprWalkTask *t = first_task; t != 0; t = t->next) { E_Expr *expr = t->expr; if(expr->ref != &e_expr_nil) { expr = expr->ref; } if(expr->kind == E_ExprKind_LeafIdentifier) { str8_list_push(ctrl_state->ctrl_thread_msg_process_arena, &ctrl_state->msg_user_bp_touched_symbols, expr->string); } if(expr->next != &e_expr_nil) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); task->expr = expr->next; task->next = t->next; t->next = task; } if(expr->first != &e_expr_nil) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); task->expr = expr->first; task->next = t->next; t->next = task; } } } } scratch_end(scratch); } //- rjf: gather all touched files by user breakpoints for(CTRL_UserBreakpointNode *n = msg->user_bps.first; n != 0; n = n->next) { if(n->v.kind != CTRL_UserBreakpointKind_FileNameAndLineColNumber) { continue; } str8_list_push(ctrl_state->ctrl_thread_msg_process_arena, &ctrl_state->msg_user_bp_touched_files, n->v.string); } //- rjf: process message switch(msg->kind) { case CTRL_MsgKind_Null: case CTRL_MsgKind_COUNT:{}break; //- rjf: target operations case CTRL_MsgKind_Launch: {ctrl_thread__launch (ctrl_ctx, msg);}break; case CTRL_MsgKind_Attach: {ctrl_thread__attach (ctrl_ctx, msg);}break; case CTRL_MsgKind_Kill: {ctrl_thread__kill (ctrl_ctx, msg);}break; case CTRL_MsgKind_KillAll: {ctrl_thread__kill_all (ctrl_ctx, msg);}break; case CTRL_MsgKind_Detach: {ctrl_thread__detach (ctrl_ctx, msg);}break; case CTRL_MsgKind_Run: {ctrl_thread__run (ctrl_ctx, msg);}break; case CTRL_MsgKind_SingleStep: {ctrl_thread__single_step (ctrl_ctx, msg);}break; //- rjf: configuration case CTRL_MsgKind_SetUserEntryPoints: { arena_clear(ctrl_state->user_entry_point_arena); MemoryZeroStruct(&ctrl_state->user_entry_points); for(String8Node *n = msg->entry_points.first; n != 0; n = n->next) { str8_list_push(ctrl_state->user_entry_point_arena, &ctrl_state->user_entry_points, n->string); } }break; case CTRL_MsgKind_SetModuleDebugInfoPath: { CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; String8 path = msg->path; CTRL_Entity *module = ctrl_entity_from_handle(entity_ctx, msg->entity); CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key old_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp); di_close(old_dbgi_key, 0); MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path_normalized_from_string(scratch.arena, path)); } U64 new_dbgi_timestamp = os_properties_from_file_path(path).modified; debug_info_path->timestamp = new_dbgi_timestamp; DI_Key new_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, new_dbgi_timestamp); di_open(new_dbgi_key); CTRL_EventList evts = {0}; CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts); evt->kind = CTRL_EventKind_ModuleDebugInfoPathChange; evt->entity = msg->entity; evt->string = path; evt->timestamp = new_dbgi_timestamp; ctrl_c2u_push_events(&evts); }break; case CTRL_MsgKind_FreezeThread: { CTRL_EventList evts = {0}; CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts); evt->kind = CTRL_EventKind_ThreadFrozen; evt->entity = msg->entity; ctrl_c2u_push_events(&evts); }break; case CTRL_MsgKind_ThawThread: { CTRL_EventList evts = {0}; CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts); evt->kind = CTRL_EventKind_ThreadThawed; evt->entity = msg->entity; ctrl_c2u_push_events(&evts); }break; } } ins_atomic_u64_eval_assign(&ctrl_state->ctrl_thread_run_state, 0); } ins_atomic_u64_inc_eval(&ctrl_state->run_gen); ins_atomic_u64_inc_eval(&ctrl_state->mem_gen); ins_atomic_u64_inc_eval(&ctrl_state->reg_gen); //- rjf: update thread register cache ProfScope("update thread register cache") { CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_EntityArray threads = ctrl_entity_array_from_kind(entity_ctx, CTRL_EntityKind_Thread); REGS_RegBlockX64 *blocks = push_array(scratch.arena, REGS_RegBlockX64, threads.count); { for EachIndex(idx, threads.count) { Temp scratch = scratch_begin(0, 0); ctrl_reg_block_from_thread(scratch.arena, entity_ctx, threads.v[idx]->handle); scratch_end(scratch); } } } //- rjf: gather & output logs ctrl_thread__end_and_flush_log(); } scratch_end(scratch); ProfEnd(); } //- rjf: breakpoint resolution internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out) { if(user_bps->first == 0) { return; } ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); Access *access = eval_scope->access; CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_Entity *module_entity = ctrl_entity_from_handle(entity_ctx, module); CTRL_Entity *debug_info_path_entity = ctrl_entity_child_from_kind(module_entity, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module_entity); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); U64 base_vaddr = module_entity->vaddr_range.min; for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next) { CTRL_UserBreakpoint *bp = &n->v; switch(bp->kind) { default:{}break; //- rjf: file:line-based breakpoints case CTRL_UserBreakpointKind_FileNameAndLineColNumber: { // rjf: unpack & normalize TxtPt pt = bp->pt; String8 filename = bp->string; String8 filename_normalized = push_str8_copy(scratch.arena, filename); for(U64 idx = 0; idx < filename_normalized.size; idx += 1) { filename_normalized.str[idx] = lower_from_char(filename_normalized.str[idx]); filename_normalized.str[idx] = correct_slash_from_char(filename_normalized.str[idx]); } // rjf: filename -> src_id U32 src_id = 0; { RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); if(mapptr != 0) { RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, filename_normalized.str, filename_normalized.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { src_id = ids[0]; } } } } // rjf: src_id * pt -> push if(src_id != 0) { RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, pt.line, &voff_count); for(U32 i = 0; i < voff_count; i += 1) { U64 vaddr = voffs[i] + base_vaddr; DMN_Trap trap = {process.dmn_handle, vaddr, (U64)bp}; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } } }break; //- rjf: expression-based breakpoints case CTRL_UserBreakpointKind_Expression: { String8 expr = bp->string; E_Value value = e_value_from_string(expr); if(value.u64 != 0 || bp->flags != 0) { DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp}; trap.flags = ctrl_dmn_trap_flags_from_user_breakpoint_flags(bp->flags); trap.size = bp->size; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } }break; } } scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out) { for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next) { CTRL_UserBreakpoint *bp = &n->v; if(bp->kind == CTRL_UserBreakpointKind_Expression) { String8 expr = bp->string; E_Value value = e_value_from_string(expr); if(value.u64 != 0 || bp->flags != 0) { DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp}; trap.flags = ctrl_dmn_trap_flags_from_user_breakpoint_flags(bp->flags); trap.size = bp->size; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } } } } internal void ctrl_thread__append_program_defined_bp_traps(Arena *arena, CTRL_Entity *bp, DMN_TrapChunkList *traps_out) { CTRL_Entity *process = bp->parent; DMN_Trap trap = { .process = process->handle.dmn_handle, .vaddr = bp->vaddr_range.min, .id = ((U64)bp|bit64), .flags = ctrl_dmn_trap_flags_from_user_breakpoint_flags(bp->bp_flags), .size = (U32)dim_1u64(bp->vaddr_range), }; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } //- rjf: module lifetime open/close work internal DW_MEM_READ(ctrl_dmn_mem_read) { U64 read = dmn_process_read(((CTRL_Handle *)ud)->dmn_handle, r1u64(addr, addr + size), buffer); return read == size ? DW_UnwindStatus_Ok : DW_UnwindStatus_Fail; } internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path, Rng1U64 elf_phdr_vrange, U64 elf_phdr_entsize) { Temp scratch = scratch_begin(0,0); Arena *arena = arena_alloc(); U64 entry_point_voff = 0; Rng1U64 tls_vaddr_range = {0}; U32 rdi_dbg_time = 0; Guid rdi_dbg_guid = {0}; String8 exe_dbg_path = {0}; String8 rdi_dbg_path = {0}; String8 raddbg_data = {0}; Rng1U64 raddbg_section_voff_range = r1u64(0, 0); Rng1U64 raddbg_is_attached_section_voff_range = r1u64(0, 0); PE_IntelPdata *pdatas = 0; U64 pdatas_count = 0; U32 pdb_dbg_time = 0; U32 pdb_dbg_age = 0; Guid pdb_dbg_guid = {0}; String8 pdb_dbg_path = {0}; U64 cfi_rebase = 0; B32 is_unwind_eh = 0; EH_FrameHdr eh_frame_hdr = {0}; EH_PtrCtx eh_ptr_ctx = { .pc_vaddr = max_U64, .text_vaddr = max_U64, .data_vaddr = max_U64, .func_vaddr = max_U64, .ptr_align = 0 }; // read module's signature bytes U64 module_sig_size = Max(elf_magic_string.size, sizeof(PE_DosMagic)); U8 *module_sig_bytes = push_array(scratch.arena, U8, module_sig_size); dmn_process_read(process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + module_sig_size), module_sig_bytes); ////////////////////////////// //- parse PE module // PE_DosMagic dos_magic = *(PE_DosMagic *)module_sig_bytes; if(dos_magic == PE_DOS_MAGIC) { ProfScope("unpack relevant PE info") { B32 is_valid = 1; //- rjf: read DOS header PE_DosHeader dos_header = {0}; if(is_valid) { if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min, &dos_header) || dos_header.magic != PE_DOS_MAGIC) { is_valid = 0; } } //- rjf: read PE magic U32 pe_magic = 0; if(is_valid) { if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dos_header.coff_file_offset, &pe_magic) || pe_magic != PE_MAGIC) { is_valid = 0; } } //- rjf: read COFF header U64 file_header_off = dos_header.coff_file_offset + sizeof(pe_magic); COFF_FileHeader file_header = {0}; if(is_valid) { if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + file_header_off, &file_header)) { is_valid = 0; } } //- rjf: unpack range of optional extension header U32 opt_ext_size = file_header.optional_header_size; Rng1U64 opt_ext_off_range = r1u64(file_header_off + sizeof(COFF_FileHeader), file_header_off + sizeof(COFF_FileHeader) + opt_ext_size); //- rjf: read optional header U64 entry_point = 0; U32 data_dir_count = 0; if(opt_ext_size > 0) { // rjf: read magic number U16 opt_ext_magic = 0; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &opt_ext_magic); // rjf: read info U32 reported_data_dir_offset = 0; U32 reported_data_dir_count = 0; switch(opt_ext_magic) { case PE_PE32_MAGIC: { PE_OptionalHeader32 pe_optional = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); entry_point = pe_optional.entry_point_va; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; }break; case PE_PE32PLUS_MAGIC: { PE_OptionalHeader32Plus pe_optional = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); entry_point = pe_optional.entry_point_va; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; }break; } // rjf: find number of data directories U32 data_dir_max = (opt_ext_size - reported_data_dir_offset) / sizeof(PE_DataDirectory); data_dir_count = ClampTop(reported_data_dir_count, data_dir_max); // rjf: grab pdatas from exceptions section if(data_dir_count > PE_DataDirectoryIndex_EXCEPTIONS) { PE_DataDirectory dir = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_EXCEPTIONS, &dir); Rng1U64 pdatas_voff_range = r1u64((U64)dir.virt_off, (U64)dir.virt_off + (U64)dir.virt_size); pdatas_count = dim_1u64(pdatas_voff_range)/sizeof(PE_IntelPdata); pdatas = push_array(arena, PE_IntelPdata, pdatas_count); dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + pdatas_voff_range.min, vaddr_range.min + pdatas_voff_range.max), pdatas); } // rjf: extract tls header PE_TLSHeader64 tls_header = {0}; if(data_dir_count > PE_DataDirectoryIndex_TLS) { PE_DataDirectory dir = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_TLS, &dir); Rng1U64 tls_voff_range = r1u64((U64)dir.virt_off, (U64)dir.virt_off + (U64)dir.virt_size); switch(file_header.machine) { default:{}break; case COFF_MachineType_X86: { PE_TLSHeader32 tls_header32 = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + tls_voff_range.min, &tls_header32); tls_header.raw_data_start = (U64)tls_header32.raw_data_start; tls_header.raw_data_end = (U64)tls_header32.raw_data_end; tls_header.index_address = (U64)tls_header32.index_address; tls_header.callbacks_address = (U64)tls_header32.callbacks_address; tls_header.zero_fill_size = (U64)tls_header32.zero_fill_size; tls_header.characteristics = (U64)tls_header32.characteristics; }break; case COFF_MachineType_X64: { dmn_process_read_struct(process.dmn_handle, vaddr_range.min + tls_voff_range.min, &tls_header); }break; } } // rjf: extract sections U64 sec_array_off = opt_ext_off_range.max; U64 sec_count = file_header.section_count; COFF_SectionHeader *sec = push_array(scratch.arena, COFF_SectionHeader, sec_count); dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + sec_array_off, vaddr_range.min + sec_array_off + sec_count*sizeof(COFF_SectionHeader)), sec); // rjf: grab entry point vaddr entry_point_voff = entry_point; // rjf: calculate TLS vaddr range tls_vaddr_range = r1u64(tls_header.index_address, tls_header.index_address+sizeof(U32)); // rjf: grab data about debug info if(data_dir_count > PE_DataDirectoryIndex_DEBUG) { // rjf: read data dir PE_DataDirectory dir = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DEBUG, &dir); U64 dbg_dir_count = dir.virt_size / sizeof(PE_DebugDirectory); for(U64 dbg_dir_idx = 0; dbg_dir_idx < dbg_dir_count; dbg_dir_idx += 1) { // rjf: read debug directory U64 dir_addr = vaddr_range.min + dir.virt_off + dbg_dir_idx * sizeof(PE_DebugDirectory); PE_DebugDirectory dbg_data = {0}; dmn_process_read_struct(process.dmn_handle, dir_addr, &dbg_data); // rjf: extract external file info from codeview header if(dbg_data.type == PE_DebugDirectoryType_CODEVIEW) { U32 cv_magic = 0; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv_magic); switch(cv_magic) { default:break; case PE_CODEVIEW_PDB20_MAGIC: { PE_CvHeaderPDB20 cv; U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min+dbg_data.voff, &cv); if(read_size == sizeof(cv)) { pdb_dbg_time = cv.time_stamp; pdb_dbg_age = cv.age; pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 cv; U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { pdb_dbg_guid = cv.guid; pdb_dbg_age = cv.age; pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI cv; U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); if(read_size == sizeof(cv)) { rdi_dbg_guid = cv.guid; rdi_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); } }break; } } } } // rjf: look for DWARF debug info { U64 symbol_array_off = file_header.symbol_table_foff; U64 symbol_count = file_header.symbol_count; if(symbol_array_off != 0) { exe_dbg_path = path; } } // rjf: extract copy of module's raddbg data { for EachIndex(idx, sec_count) { String8 section_name = str8_cstring((char *)sec[idx].name); if(str8_match(section_name, str8_lit(".raddbg"), 0)) { raddbg_section_voff_range.min = sec[idx].voff; raddbg_section_voff_range.max = sec[idx].voff + sec[idx].vsize; } else if(str8_match(section_name, str8_lit(".rdbgia"), 0)) { raddbg_is_attached_section_voff_range.min = sec[idx].voff; raddbg_is_attached_section_voff_range.max = sec[idx].voff + sec[idx].vsize; } } raddbg_data.size = dim_1u64(raddbg_section_voff_range); raddbg_data.str = push_array(arena, U8, raddbg_data.size); dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + raddbg_section_voff_range.min, vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str); } // rjf: if we have a "raddbg is attached" section, mark the first byte as 1, to signify attachment if(raddbg_is_attached_section_voff_range.max != raddbg_is_attached_section_voff_range.min) { U8 new_value = 1; dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value); } } } } ////////////////////////////// //- parse ELF module // else if(str8_match(str8(module_sig_bytes, elf_magic_string.size), elf_magic_string, 0)) { U64 e_entry = 0; ELF_Type e_type = ELF_Type_None; { U8 *elf_sig = dmn_process_read_raw(scratch.arena, process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(elf_sig[0]) * ELF_Identifier_Max)); if(elf_sig == 0) { goto elf_exit; } switch(elf_sig[ELF_Identifier_Class]) { default: case ELF_Class_None:{}break; case ELF_Class_32: { NotImplemented; }break; case ELF_Class_64: { ELF_Hdr64 *ehdr = dmn_process_read_raw(scratch.arena, process.dmn_handle, rng_1u64(vaddr_range.min, vaddr_range.min + sizeof(*ehdr))); if(ehdr == 0) { goto elf_exit; } e_entry = ehdr->e_entry; e_type = ehdr->e_type; }break; } } if(e_type == ELF_Type_Dyn) { cfi_rebase = vaddr_range.min; } // find and parse .eh_frame_hdr Rng1U64 eh_frame_hdr_vrange = {0}; String8 eh_frame_hdr_data = {0}; { void *phdrs_raw = dmn_process_read_raw(scratch.arena, process.dmn_handle, elf_phdr_vrange); if(phdrs_raw == 0) { goto elf_exit; } if(elf_phdr_entsize == sizeof(ELF_Phdr32)) { NotImplemented; } else if(elf_phdr_entsize == sizeof(ELF_Phdr64)) { U64 elf_phcount = dim_1u64(elf_phdr_vrange) / elf_phdr_entsize; ELF_Phdr64 *phdrs64 = phdrs_raw; for EachIndex(phdr_idx, elf_phcount) { ELF_Phdr64 *phdr = phdrs64 + phdr_idx; if(phdr->p_type == ELF_PType_GnuEHFrame) { eh_frame_hdr_vrange = r1u64(cfi_rebase + phdr->p_vaddr, cfi_rebase + phdr->p_vaddr + phdr->p_memsz); eh_frame_hdr_data = dmn_process_read_block(arena, process.dmn_handle, eh_frame_hdr_vrange); is_unwind_eh = 1; break; } } } } // parse .eh_frame_hdr Arch arch = ctrl_arch_from_process_handle(process); eh_ptr_ctx.pc_vaddr = eh_frame_hdr_vrange.min; eh_ptr_ctx.data_vaddr = eh_frame_hdr_vrange.min; eh_frame_hdr = eh_parse_frame_hdr(eh_frame_hdr_data, byte_size_from_arch(arch), &eh_ptr_ctx); // set entry point if (e_entry != 0) { entry_point_voff = e_entry - vaddr_range.min; } // TODO: is there a way to detect DWARF in runtime ELF? if(1) { exe_dbg_path = path; } elf_exit:; } ////////////////////////////// //- rjf: pick default initial debug info path // String8 initial_debug_info_path = str8_zero(); { String8 exe_folder = str8_chop_last_slash(path); String8List dbg_path_candidates = {0}; // //~ TODO(rjf): @linux_port PLEASE READ RYAN vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // // TODO(rjf): trying "exe_folder/embedded_path" as the first option is only a valid // heuristic on Windows, because we know that two absolute paths concatted together // are necessarily invalid. however, on Linux, this is not the case - you could stitch // two paths together and get a third path that is completely valid. so, in that case, // we will need to infer if the path is relative, and then use either the embedded // path as-is, or the exe-relative-path accordingly, depending on that. // if(rdi_dbg_path.size != 0) { str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S/%S", exe_folder, rdi_dbg_path); str8_list_push(scratch.arena, &dbg_path_candidates, rdi_dbg_path); } if(exe_dbg_path.size != 0) { str8_list_push(scratch.arena, &dbg_path_candidates, path); } if(pdb_dbg_path.size != 0) { str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S/%S", exe_folder, pdb_dbg_path); str8_list_push(scratch.arena, &dbg_path_candidates, pdb_dbg_path); } str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S.pdb", str8_chop_last_dot(path)); str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S.pdb", path); str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S.rdi", str8_chop_last_dot(path)); str8_list_pushf(scratch.arena, &dbg_path_candidates, "%S.rdi", path); for(String8Node *n = dbg_path_candidates.first; n != 0; n = n->next) { String8 candidate_path = n->string; FileProperties props = os_properties_from_file_path(candidate_path); if(props.modified != 0 && props.size != 0) { initial_debug_info_path = push_str8_copy(arena, path_normalized_from_string(scratch.arena, candidate_path)); break; } } } ////////////////////////////// //- rjf: insert info into cache // { U64 hash = ctrl_hash_from_handle(module); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeW(stripe->rw_mutex) { CTRL_ModuleImageInfoCacheNode *node = 0; for EachNode(n, CTRL_ModuleImageInfoCacheNode, slot->first) { if(ctrl_handle_match(n->module, module)) { node = n; break; } } if(!node) { node = push_array(arena, CTRL_ModuleImageInfoCacheNode, 1); DLLPushBack(slot->first, slot->last, node); node->module = module; node->arena = arena; node->pdatas = pdatas; node->pdatas_count = pdatas_count; node->cfi_rebase = cfi_rebase; node->is_unwind_eh = is_unwind_eh; node->eh_frame_hdr = eh_frame_hdr; node->eh_ptr_ctx = eh_ptr_ctx; node->entry_point_voff = entry_point_voff; node->initial_debug_info_path = initial_debug_info_path; } } } scratch_end(scratch); } internal void ctrl_thread__module_close(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range) { ////////////////////////////// //- rjf: evict module image info from cache // Rng1U64 raddbg_section_voff_range = {0}; { U64 hash = ctrl_hash_from_handle(module); U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; MutexScopeW(stripe->rw_mutex) { CTRL_ModuleImageInfoCacheNode *node = 0; for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->module, module)) { node = n; break; } } if(node) { raddbg_section_voff_range = node->raddbg_section_voff_range; DLLRemove(slot->first, slot->last, node); arena_release(node->arena); } } } ////////////////////////////// //- rjf: write 0 into first byte of raddbg data section, to signify detachment // if(raddbg_section_voff_range.max != raddbg_section_voff_range.min) { U8 new_value = 0; dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_section_voff_range.min, &new_value); } } //- rjf: attached process running/event gathering internal DMN_Event * ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof) { ProfBeginFunction(); DMN_Event *event = push_array(arena, DMN_Event, 1); Temp scratch = scratch_begin(&arena, 1); CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; //- rjf: loop -> try to get event, run, repeat U64 spoof_old_ip_value = 0; ProfScope("loop -> try to get event, run, repeat") for(B32 got_event = 0; got_event == 0;) { //- rjf: get next event ProfScope("get next event") { // rjf: grab first event DMN_EventNode *next_event_node = ctrl_state->first_dmn_event_node; // rjf: log event if(next_event_node != 0) { DMN_Event *ev = &next_event_node->v; LogInfoNamedBlockF("dmn_event") { log_infof("kind: %S\n", dmn_event_kind_string_table[ev->kind]); log_infof("exception_kind: %S\n", dmn_exception_kind_string_table[ev->exception_kind]); log_infof("process: [%I64u]\n", ev->process.u64[0]); log_infof("thread: [%I64u]\n", ev->thread.u64[0]); log_infof("module: [%I64u]\n", ev->module.u64[0]); log_infof("arch: %S\n", string_from_arch(ev->arch)); log_infof("address: 0x%I64x\n", ev->address); log_infof("string: \"%S\"\n", ev->string); log_infof("ip_vaddr: 0x%I64x\n", ev->instruction_pointer); } } // rjf: determine if we should filter B32 should_filter_event = 0; if(next_event_node != 0) { DMN_Event *ev = &next_event_node->v; switch(ev->kind) { default:{}break; case DMN_EventKind_Exception: { // NOTE(rjf): first chance exceptions -> try ignoring should_filter_event = (ev->exception_repeated == 0 && (spoof == 0 || ev->instruction_pointer != spoof->new_ip_value)); // rjf: exception code -> kind CTRL_ExceptionCodeKind code_kind = CTRL_ExceptionCodeKind_Null; if(should_filter_event) { for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)0; k < CTRL_ExceptionCodeKind_COUNT; k = (CTRL_ExceptionCodeKind)(k+1)) { if(ctrl_exception_code_kind_code_table[k] == ev->code) { code_kind = k; break; } } } // rjf: exception code kind -> shouldn't stop? if so, do not filter if(should_filter_event) { B32 shouldnt_filter = !!(ctrl_state->exception_code_filters[code_kind/64] & (1ull<<(code_kind%64))); if(should_filter_event && shouldnt_filter) { should_filter_event = 0; } } // rjf: special case: be gracious with ASan modules or symbols if // they do their cute little 0xc0000005 exception trick... if(!should_filter_event && ev->code == 0xc0000005 && (spoof == 0 || ev->instruction_pointer != spoof->new_ip_value)) { Access *access = access_open(); CTRL_Entity *process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, ev->process)); CTRL_Entity *module = &ctrl_entity_nil; for(CTRL_Entity *child = process->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == CTRL_EntityKind_Module) { module = child; break; } } if(module != &ctrl_entity_nil) { // rjf: determine base address of asan shadow space U64 asan_shadow_base_vaddr = 0; B32 asan_shadow_variable_exists_but_is_zero = 0; DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, max_U64); RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); { RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, unparsed_map, &map); String8 name = str8_lit("__asan_shadow_memory_dynamic_address"); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, ids[0]); U64 global_var_voff = global_var->voff; U64 global_var_vaddr = global_var->voff + module->vaddr_range.min; Arch arch = process->arch; U64 addr_size = bit_size_from_arch(arch)/8; dmn_process_read(ev->process, r1u64(global_var_vaddr, global_var_vaddr+addr_size), &asan_shadow_base_vaddr); asan_shadow_variable_exists_but_is_zero = (asan_shadow_base_vaddr == 0); } } } // rjf: determine if this was a read/write to the shadow space B32 violation_in_shadow_space = 0; if(asan_shadow_base_vaddr != 0) { U64 asan_shadow_space_size = TB(128)/8; if(asan_shadow_base_vaddr <= ev->address && ev->address < asan_shadow_base_vaddr+asan_shadow_space_size) { violation_in_shadow_space = 1; } } // rjf: filter event if this violation occurred in asan's shadow space if(violation_in_shadow_space || asan_shadow_variable_exists_but_is_zero) { should_filter_event = 1; } } access_close(access); } }break; } } // rjf: good event & unfiltered? -> pop from queue & grab as result if(next_event_node != 0 && !should_filter_event) { got_event = 1; SLLQueuePop(ctrl_state->first_dmn_event_node, ctrl_state->last_dmn_event_node); MemoryCopyStruct(event, &next_event_node->v); event->string = push_str8_copy(arena, event->string); run_ctrls->ignore_previous_exception = 1; } // rjf: good event but filtered? pop from queue if(next_event_node != 0 && should_filter_event) { SLLQueuePop(ctrl_state->first_dmn_event_node, ctrl_state->last_dmn_event_node); run_ctrls->ignore_previous_exception = 0; } } //- rjf: no event -> dmn_ctrl_run for a new one if(got_event == 0) ProfScope("no event -> dmn_ctrl_run for a new one") { // rjf: prep spoof B32 do_spoof = (spoof != 0 && dmn_handle_match(run_ctrls->single_step_thread, dmn_handle_zero())); U64 size_of_spoof = 0; if(do_spoof) ProfScope("prep spoof") { CTRL_Entity *spoof_process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, spoof->process)); Arch arch = spoof_process->arch; size_of_spoof = bit_size_from_arch(arch)/8; dmn_process_read(spoof_process->handle.dmn_handle, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); } // rjf: set spoof if(do_spoof) ProfScope("set spoof") { dmn_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof->new_ip_value); } // rjf: run for new events ProfScope("run for new events") { LogInfoNamedBlockF("dmn_ctrl_run") { log_infof("single_step_thread: [0x%I64x]\n", run_ctrls->single_step_thread); log_infof("ignore_previous_exception: %i\n", !!run_ctrls->ignore_previous_exception); log_infof("run_entities_are_unfrozen: %i\n", !!run_ctrls->run_entities_are_unfrozen); log_infof("run_entities_are_processes: %i\n", !!run_ctrls->run_entities_are_processes); log_infof("run_entity_count: %I64u\n", run_ctrls->run_entity_count); LogInfoNamedBlockF("run_entities") for(U64 idx = 0; idx < run_ctrls->run_entity_count; idx += 1) { log_infof("[0x%I64x]\n", run_ctrls->run_entities[idx]); } log_infof("trap_count: %I64u\n", run_ctrls->traps.trap_count); LogInfoNamedBlockF("traps") for(DMN_TrapChunkNode *n = run_ctrls->traps.first; n != 0; n = n->next) { for(U64 idx = 0; idx < n->count; idx += 1) { log_infof("{process:[0x%I64x], vaddr:0x%I64x, id:0x%I64x}\n", n->v[idx].process.u64[0], n->v[idx].vaddr, n->v[idx].id); } } } DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls); ins_atomic_u64_inc_eval(&ctrl_state->mem_gen); ins_atomic_u64_inc_eval(&ctrl_state->reg_gen); ins_atomic_u64_inc_eval(&ctrl_state->run_gen); for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next) { DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node; if(dst_n != 0) { SLLStackPop(ctrl_state->free_dmn_event_node); } else { dst_n = push_array(ctrl_state->dmn_event_arena, DMN_EventNode, 1); } MemoryCopyStruct(&dst_n->v, &src_n->v); dst_n->v.string = push_str8_copy(ctrl_state->dmn_event_arena, dst_n->v.string); SLLQueuePush(ctrl_state->first_dmn_event_node, ctrl_state->last_dmn_event_node, dst_n); } } // rjf: unset spoof if(do_spoof) ProfScope("unset spoof") { dmn_process_write(spoof->process, r1u64(spoof->vaddr, spoof->vaddr+size_of_spoof), &spoof_old_ip_value); } } } //- rjf: irrespective of what event came back, we should ALWAYS check the // spoof's thread and see if it hit the spoof address, because we may have // simply been sent other debug events first if(spoof != 0) { CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, spoof->thread)); Arch arch = thread->arch; void *regs_block = push_array(scratch.arena, U8, regs_block_size_from_arch(arch)); dmn_thread_read_reg_block(spoof->thread, regs_block); U64 spoof_thread_rip = regs_rip_from_arch_block(arch, regs_block); if(spoof_thread_rip == spoof->new_ip_value) { regs_arch_block_write_rip(arch, regs_block, spoof_old_ip_value); ctrl_thread_write_reg_block(ctrl_handle_make(CTRL_MachineID_Local, spoof->thread), regs_block); } } //- rjf: push ctrl events associated with this demon event CTRL_EventList evts = {0}; ProfScope("push ctrl events associated with this demon event") switch(event->kind) { default:{}break; case DMN_EventKind_CreateProcess: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_NewProc; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->arch = event->arch; out_evt->entity_id = event->code; ctrl_state->process_counter += 1; }break; case DMN_EventKind_CreateThread: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_NewThread; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->arch = event->arch; out_evt->entity_id = event->code; out_evt->stack_base = dmn_stack_base_vaddr_from_thread(event->thread); out_evt->tls_root = dmn_tls_root_vaddr_from_thread(event->thread); out_evt->rip_vaddr = event->instruction_pointer; out_evt->string = event->string; }break; case DMN_EventKind_LoadModule: { CTRL_Handle process_handle = ctrl_handle_make(CTRL_MachineID_Local, event->process); CTRL_Handle module_handle = ctrl_handle_make(CTRL_MachineID_Local, event->module); CTRL_Event *out_evt1 = ctrl_event_list_push(scratch.arena, &evts); String8 module_path = path_normalized_from_string(scratch.arena, event->string); U64 exe_timestamp = os_properties_from_file_path(module_path).modified; ctrl_thread__module_open(process_handle, module_handle, r1u64(event->address, event->address+event->size), module_path, event->elf_phdr_vrange, event->elf_phdr_entsize); out_evt1->kind = CTRL_EventKind_NewModule; out_evt1->msg_id = msg->msg_id; out_evt1->entity = module_handle; out_evt1->parent = process_handle; out_evt1->arch = event->arch; out_evt1->entity_id = event->code; out_evt1->vaddr_rng = r1u64(event->address, event->address+event->size); out_evt1->rip_vaddr = event->address; out_evt1->timestamp = exe_timestamp; out_evt1->string = module_path; CTRL_Event *out_evt2 = ctrl_event_list_push(scratch.arena, &evts); String8 initial_debug_info_path = ctrl_initial_debug_info_path_from_module(scratch.arena, module_handle); U64 debug_info_timestamp = os_properties_from_file_path(initial_debug_info_path).modified; out_evt2->kind = CTRL_EventKind_ModuleDebugInfoPathChange; out_evt2->msg_id = msg->msg_id; out_evt2->entity = module_handle; out_evt2->parent = process_handle; out_evt2->timestamp = debug_info_timestamp; out_evt2->string = initial_debug_info_path; DI_Key initial_dbgi_key = di_key_from_path_timestamp(initial_debug_info_path, debug_info_timestamp); di_open(initial_dbgi_key); }break; case DMN_EventKind_ExitProcess: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_EndProc; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->u64_code = event->code; ctrl_state->process_counter -= 1; }break; case DMN_EventKind_ExitThread: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_EndThread; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->entity_id = event->code; }break; case DMN_EventKind_UnloadModule: ProfScope("unload module %.*s", str8_varg(event->string)) { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); CTRL_Handle module_handle = ctrl_handle_make(CTRL_MachineID_Local, event->module); CTRL_Entity *module_ent = ctrl_entity_from_handle(entity_ctx, module_handle); CTRL_Entity *process_ent = ctrl_process_from_entity(module_ent); String8 module_path = event->string; ctrl_thread__module_close(process_ent->handle, module_handle, module_ent->vaddr_range); out_evt->kind = CTRL_EventKind_EndModule; out_evt->msg_id = msg->msg_id; out_evt->entity = module_handle; out_evt->string = module_path; DI_Key dbgi_key = ctrl_dbgi_key_from_module(module_ent); di_close(dbgi_key, 0); }break; case DMN_EventKind_DebugString: { U64 num_strings = (event->string.size + ctrl_state->c2u_ring_max_string_size-1) / ctrl_state->c2u_ring_max_string_size; for(U64 string_idx = 0; string_idx < num_strings; string_idx += 1) { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_DebugString; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->string = str8_substr(event->string, r1u64(string_idx*ctrl_state->c2u_ring_max_string_size, (string_idx+1)*ctrl_state->c2u_ring_max_string_size)); } }break; case DMN_EventKind_SetThreadName: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_ThreadName; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->string = event->string; out_evt->entity_id = event->code; }break; case DMN_EventKind_SetThreadColor: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_ThreadColor; out_evt->msg_id = msg->msg_id; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->entity_id = event->code; out_evt->rgba = event->user_data; }break; case DMN_EventKind_SetVAddrRangeNote: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_SetVAddrRangeNote; out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->msg_id = msg->msg_id; out_evt->vaddr_rng = r1u64(event->address, event->address + event->size); out_evt->string = event->string; }break; case DMN_EventKind_SetBreakpoint: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_SetBreakpoint; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->vaddr_rng = r1u64(event->address, event->address+event->size); out_evt->bp_flags = ctrl_user_breakpoint_flags_from_dmn_trap_flags(event->flags); }break; case DMN_EventKind_UnsetBreakpoint: { // TODO(rjf): this needs to be reflected in the resolved trap list too!!!!!!!! CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); out_evt->kind = CTRL_EventKind_UnsetBreakpoint; out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread); out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); out_evt->vaddr_rng = r1u64(event->address, event->address+event->size); out_evt->bp_flags = ctrl_user_breakpoint_flags_from_dmn_trap_flags(event->flags); }break; } ctrl_c2u_push_events(&evts); //- rjf: if this is the first process in a session, clear the debug directory // cache state if(ctrl_state->process_counter == 1 && event->kind == DMN_EventKind_CreateProcess) { arena_clear(ctrl_state->dbg_dir_arena); ctrl_state->dbg_dir_root = push_array(ctrl_state->dbg_dir_arena, CTRL_DbgDirNode, 1); } //- rjf: out of queued up demon events -> clear event arena if(ctrl_state->first_dmn_event_node == 0) { ctrl_state->free_dmn_event_node = 0; arena_clear(ctrl_state->dmn_event_arena); } scratch_end(scratch); ProfEnd(); return(event); } //- rjf: eval helpers internal U64 ctrl_eval_space_gen(E_Space space) { U64 result = 0; switch(space.kind) { default:{}break; case CTRL_EvalSpaceKind_Entity: { result = ctrl_mem_gen(); }break; } return result; } internal B32 ctrl_eval_space_read(E_Space space, void *out, Rng1U64 range) { B32 result = 0; switch(space.kind) { default:{}break; //- rjf: intra-entity reads (process memory or thread registers) case CTRL_EvalSpaceKind_Entity: { CTRL_Entity *entity = (CTRL_Entity *)space.u64_0; switch(entity->kind) { default:{}break; case CTRL_EntityKind_Process: { U64 read_size = dmn_process_read(entity->handle.dmn_handle, range, out); result = (read_size == dim_1u64(range)); }break; case CTRL_EntityKind_Thread: { Temp scratch = scratch_begin(0, 0); CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; U64 regs_size = regs_block_size_from_arch(entity->arch); void *regs = ctrl_reg_block_from_thread(scratch.arena, entity_ctx, entity->handle); Rng1U64 legal_range = r1u64(0, regs_size); Rng1U64 read_range = intersect_1u64(legal_range, range); U64 read_size = dim_1u64(read_range); MemoryCopy(out, (U8 *)regs + read_range.min, read_size); result = (read_size == dim_1u64(range)); scratch_end(scratch); }break; } }break; } return result; } //- rjf: control thread eval scopes internal CTRL_EvalScope * ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, CTRL_Entity *thread) { ProfBeginFunction(); CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_EvalScope *scope = push_array(arena, CTRL_EvalScope, 1); scope->access = access_open(); ////////////////////////////// //- rjf: unpack thread // Arch arch = thread->arch; U64 thread_rip_vaddr = dmn_rip_from_thread(thread->handle.dmn_handle); CTRL_Entity *process = ctrl_process_from_entity(thread); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr); U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr); ////////////////////////////// //- rjf: gather evaluation debug infos & modules // U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]); E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count); E_Module *eval_modules_primary = &eval_modules[0]; eval_modules_primary->vaddr_range = r1u64(0, max_U64); U64 eval_dbg_infos_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]); E_DbgInfo *eval_dbg_infos = push_array(arena, E_DbgInfo, eval_dbg_infos_count); E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0]; MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil); { U64 eval_module_idx = 0; U64 eval_dbg_info_idx = 0; for(CTRL_Entity *machine = entity_ctx->root->first; machine != &ctrl_entity_nil; machine = machine->next) { if(machine->kind != CTRL_EntityKind_Machine) { continue; } for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next) { if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *mod = process->first; mod != &ctrl_entity_nil; mod = mod->next) { if(mod->kind != CTRL_EntityKind_Module) { continue; } DI_Key dbgi_key = ctrl_dbgi_key_from_module(mod); //- rjf: try to obtain this module's RDI RDI_Parsed *rdi = di_rdi_from_key(scope->access, dbgi_key, 0, 0); //- rjf: if this RDI is not yet ready => determine if we need to wait for it // // (we *always* wait for the initial module) // B32 rdi_is_necessary = 1; if(user_bps->count == 0) { rdi_is_necessary = 0; } else if(rdi == &rdi_parsed_nil) ProfScope("determine if RDI is necessary") { // rjf: find cached result U64 hash = ctrl_hash_from_handle(mod->handle); U64 slot_idx = hash%ctrl_state->module_req_cache_slots_count; CTRL_ModuleReqCacheNode *slot = ctrl_state->module_req_cache_slots[slot_idx]; CTRL_ModuleReqCacheNode *node = 0; for(CTRL_ModuleReqCacheNode *n = slot; n != 0; n = n->next) { if(ctrl_handle_match(n->module, mod->handle)) { node = n; break; } } // rjf: cached? -> take cached result if(node != 0) { rdi_is_necessary = node->required; } // rjf: not cached -> compute & store else ProfScope("cache miss") { CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath); OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, debug_info_path->string); ProfScope("determine if %.*s is necessary", str8_varg(debug_info_path->string)) { //- rjf: determine if file is PDB B32 file_is_pdb = 0; if(!file_is_pdb) { U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe); if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe))) { file_is_pdb = 1; } } if(!file_is_pdb) { U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe); if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe))) { file_is_pdb = 1; } } //- rjf: file is PDB -> do thin parse & lookup of all breakpoint files/symbols. // if any are found in the PDB, then this RDI is necessary. if(file_is_pdb) { FileProperties props = os_properties_from_file(file); OS_Handle map = os_file_map_open(OS_AccessFlag_Read, file); void *file_base = os_file_map_view_open(map, OS_AccessFlag_Read, r1u64(0, props.size)); String8 file_data = str8(file_base, props.size); { rdi_is_necessary = pdb_has_symbol_or_file_ref(file_data, ctrl_state->msg_user_bp_touched_symbols, ctrl_state->msg_user_bp_touched_files); } os_file_map_view_close(map, file_base, r1u64(0, props.size)); os_file_map_close(map); } } os_file_close(file); node = push_array(ctrl_state->ctrl_thread_msg_process_arena, CTRL_ModuleReqCacheNode, 1); node->next = slot; ctrl_state->module_req_cache_slots[slot_idx] = node; node->module = mod->handle; node->required = rdi_is_necessary; } } //- rjf: if this RDI is necessary, but we do not have it => wait for it forever if(rdi == &rdi_parsed_nil && rdi_is_necessary) ProfScope("RDI is necessary -> wait") { rdi = di_rdi_from_key(scope->access, dbgi_key, 1, max_U64); } //- rjf: fill debug info eval_dbg_infos[eval_dbg_info_idx].dbgi_key = dbgi_key; eval_dbg_infos[eval_dbg_info_idx].rdi = rdi; if(mod == module) { eval_dbg_infos_primary = &eval_dbg_infos[eval_dbg_info_idx]; } eval_dbg_info_idx += 1; //- rjf: fill evaluation module info eval_modules[eval_module_idx].arch = arch; eval_modules[eval_module_idx].dbg_info_num= (U32)eval_dbg_info_idx; eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range; eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity); eval_modules[eval_module_idx].space.u64_0 = (U64)process; if(mod == module) { eval_modules_primary = &eval_modules[eval_module_idx]; } eval_module_idx += 1; } } } } ////////////////////////////// //- rjf: select evaluation cache // e_select_cache(ctrl_state->ctrl_thread_eval_cache); ////////////////////////////// //- rjf: build base evaluation context // { E_BaseCtx *ctx = &scope->base_ctx; //- rjf: fill instruction pointer info ctx->thread_ip_vaddr = thread_rip_vaddr; ctx->thread_ip_voff = thread_rip_voff; ctx->thread_arch = thread->arch; ctx->thread_reg_space = e_space_make(CTRL_EvalSpaceKind_Entity); ctx->thread_reg_space.u64_0 = (U64)thread; //- rjf: fill debug infos ctx->dbg_infos = eval_dbg_infos; ctx->dbg_infos_count = eval_dbg_infos_count; ctx->primary_dbg_info = eval_dbg_infos_primary; //- rjf: fill modules ctx->modules = eval_modules; ctx->modules_count = eval_modules_count; ctx->primary_module = eval_modules_primary; //- rjf: fill space hooks ctx->space_gen = ctrl_eval_space_gen; ctx->space_read = ctrl_eval_space_read; } e_select_base_ctx(&scope->base_ctx); ////////////////////////////// //- rjf: build IR evaluation context // { E_IRCtx *ctx = &scope->ir_ctx; ctx->regs_map = ctrl_string2reg_from_arch(arch); ctx->reg_alias_map = ctrl_string2alias_from_arch(arch); ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff); ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff); ctx->macro_map = push_array(arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(arena, 512); ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1); ctx->auto_hook_map[0] = e_auto_hook_map_make(arena, 512); } e_select_ir_ctx(&scope->ir_ctx); ////////////////////////////// //- rjf: build eval interpretation context // { E_InterpretCtx *ctx = &scope->interpret_ctx; ctx->primary_space = eval_modules_primary->space; ctx->reg_arch = eval_modules_primary->arch; ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity); ctx->reg_space.u64_0 = (U64)thread; ctx->module_base = push_array(arena, U64, 1); ctx->module_base[0]= module->vaddr_range.min; ctx->frame_base = push_array(arena, U64, 1); // TODO(rjf): need to compute this out here somehow... ctx->frame_base[0] = ; ctx->tls_base = push_array(arena, U64, 1); } e_select_interpret_ctx(&scope->interpret_ctx, eval_dbg_infos_primary->rdi, thread_rip_voff); ProfEnd(); return scope; } internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope) { access_close(scope->access); } //- rjf: log flusher internal void ctrl_thread__end_and_flush_log(void) { Temp scratch = scratch_begin(0, 0); LogScopeResult log = log_scope_end(scratch.arena); os_append_data_to_file_path(ctrl_state->ctrl_thread_log_path, log.strings[LogMsgKind_Info]); if(log.strings[LogMsgKind_UserError].size != 0) { CTRL_EventList evts = {0}; CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts); evt->kind = CTRL_EventKind_Error; evt->string = log.strings[LogMsgKind_UserError]; ctrl_c2u_push_events(&evts); } scratch_end(scratch); } //- rjf: msg kind implementations internal void ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { Temp scratch = scratch_begin(0, 0); //- rjf: produce full stdout/stderr/stdin paths String8 stdout_path = path_absolute_dst_from_relative_dst_src(scratch.arena, msg->stdout_path, msg->path); String8 stdin_path = path_absolute_dst_from_relative_dst_src(scratch.arena, msg->stdin_path, msg->path); String8 stderr_path = path_absolute_dst_from_relative_dst_src(scratch.arena, msg->stderr_path, msg->path); //- rjf: obtain stdout/stderr/stdin handles OS_Handle stdout_handle = {0}; OS_Handle stderr_handle = {0}; OS_Handle stdin_handle = {0}; if(stdout_path.size != 0) { OS_Handle f = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path); os_file_close(f); stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, msg->stdout_path); } if(stderr_path.size != 0) { OS_Handle f = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stderr_path); os_file_close(f); stderr_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, msg->stderr_path); } if(stdin_path.size != 0) { stdin_handle = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdin_path); } //- rjf: launch OS_ProcessLaunchParams params = {0}; { params.cmd_line = msg->cmd_line_string_list; params.path = msg->path; params.env = msg->env_string_list; params.inherit_env = msg->env_inherit; params.debug_subprocesses = msg->debug_subprocesses; params.stdout_file = stdout_handle; params.stderr_file = stderr_handle; params.stdin_file = stdin_handle; } U32 id = dmn_ctrl_launch(ctrl_ctx, ¶ms); //- rjf: close stdout/stderr/stdin files os_file_close(stdout_handle); os_file_close(stderr_handle); os_file_close(stdin_handle); //- rjf: record (id -> entry points), so that we know custom entry points for this PID CTRL_EntityCtxRWStore *entity_ctx_rw_store = ctrl_state->ctrl_thread_entity_store; MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { for(String8Node *n = msg->entry_points.first; n != 0; n = n->next) { String8 string = n->string; CTRL_Entity *entry = ctrl_entity_alloc(entity_ctx_rw_store, entity_ctx_rw_store->ctx.root, CTRL_EntityKind_EntryPoint, Arch_Null, ctrl_handle_zero(), (U64)id); ctrl_entity_equip_string(entity_ctx_rw_store, entry, string); } } scratch_end(scratch); } internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); //- rjf: attach B32 attach_successful = dmn_ctrl_attach(ctrl_ctx, msg->entity_id); //- rjf: run to handshake if(attach_successful) { DMN_Handle unfrozen_process = {0}; DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities_are_processes = 1; for(B32 done = 0; done == 0;) { DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); switch(event->kind) { default:{}break; case DMN_EventKind_CreateProcess: { unfrozen_process = event->process; run_ctrls.run_entities = &unfrozen_process; run_ctrls.run_entity_count = 1; }break; case DMN_EventKind_Halt: case DMN_EventKind_Exception: case DMN_EventKind_Error: case DMN_EventKind_HandshakeComplete: { done = 1; }break; } } } //- rjf: record stop { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = CTRL_EventCause_Finished; event->msg_id = msg->msg_id; event->entity_id = !!attach_successful * msg->entity_id; ctrl_c2u_push_events(&evts); } scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); DMN_Handle process = msg->entity.dmn_handle; U32 exit_code = msg->exit_code; //- rjf: send kill B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, process, exit_code); //- rjf: wait for process to be dead CTRL_EventCause cause = CTRL_EventCause_Finished; if(kill_worked) { DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities_are_processes = 1; run_ctrls.run_entities = &process; run_ctrls.run_entity_count = 1; for(B32 done = 0; done == 0;) { DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); switch(event->kind) { default:{}break; case DMN_EventKind_ExitProcess: if(dmn_handle_match(event->process, process)) { done = 1; }break; case DMN_EventKind_Error:{done = 1; cause = CTRL_EventCause_Error;}break; case DMN_EventKind_Halt: {done = 1; cause = CTRL_EventCause_InterruptedByHalt;}break; } } } //- rjf: record stop { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = cause; event->msg_id = msg->msg_id; if(kill_worked) { event->entity = msg->entity; } ctrl_c2u_push_events(&evts); } scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); U32 exit_code = msg->exit_code; CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; //- rjf: gather all currently existing processes CTRL_EntityArray initial_processes = ctrl_entity_array_from_kind(entity_ctx, CTRL_EntityKind_Process); typedef struct Task Task; struct Task { Task *next; Task *prev; CTRL_Entity *process; }; Task *first_task = 0; Task *last_task = 0; for EachIndex(idx, initial_processes.count) { CTRL_Entity *entity = initial_processes.v[idx]; Task *t = push_array(scratch.arena, Task, 1); t->process = entity; DLLPushBack(first_task, last_task, t); } //- rjf: kill processes as needed, wait for all processes to be dead CTRL_EventCause cause = CTRL_EventCause_Finished; if(first_task != 0) { DMN_RunCtrls run_ctrls = {0}; for(B32 done = 0; !done;) { // rjf: kill remaining processes for(Task *t = first_task, *next = 0; t != 0; t = next) { next = t->next; B32 kill_worked = dmn_ctrl_kill(ctrl_ctx, t->process->handle.dmn_handle, exit_code); if(kill_worked) { DLLRemove(first_task, last_task, t); } } // rjf: get next event DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); // rjf: process event switch(event->kind) { default:{}break; case DMN_EventKind_CreateProcess: { CTRL_Entity *new_process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->process)); Task *t = push_array(scratch.arena, Task, 1); t->process = new_process; DLLPushBack(first_task, last_task, t); }break; case DMN_EventKind_Error:{done = 1; cause = CTRL_EventCause_Error;}break; case DMN_EventKind_Halt: {done = 1; cause = CTRL_EventCause_InterruptedByHalt;}break; } // rjf: end if all processes are gone CTRL_EntityArray processes = ctrl_entity_array_from_kind(entity_ctx, CTRL_EntityKind_Process); if(processes.count == 0) { done = 1; } } } //- rjf: record stop { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = cause; event->msg_id = msg->msg_id; ctrl_c2u_push_events(&evts); } scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); DMN_Handle process = msg->entity.dmn_handle; //- rjf: detach B32 detach_worked = dmn_ctrl_detach(ctrl_ctx, process); //- rjf: wait for process to be dead if(detach_worked) { DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities_are_processes = 1; run_ctrls.run_entities = &process; run_ctrls.run_entity_count = 1; for(B32 done = 0; done == 0;) { DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); if(event->kind == DMN_EventKind_ExitProcess && dmn_handle_match(event->process, process)) { done = 1; } if(event->kind == DMN_EventKind_Halt) { done = 1; } } } //- rjf: record stop { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = CTRL_EventCause_Finished; event->msg_id = msg->msg_id; if(detach_worked) { event->entity = msg->entity; } ctrl_c2u_push_events(&evts); } scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); DMN_Event *stop_event = 0; CTRL_EventCause stop_cause = CTRL_EventCause_Null; CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_Handle target_thread = msg->entity; CTRL_Handle target_process = msg->parent; CTRL_Entity *target_process_entity = ctrl_entity_from_handle(entity_ctx, target_process); U64 spoof_ip_vaddr = 911; log_infof("ctrl_thread__run:\n{\n"); ////////////////////////////// //- rjf: gather all initial breakpoints // DMN_TrapChunkList user_traps = {0}; { CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, target_thread); CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread); for(CTRL_Entity *machine = entity_ctx->root->first; machine != &ctrl_entity_nil; machine = machine->next) { if(machine->kind != CTRL_EntityKind_Machine) { continue; } for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next) { if(process->kind != CTRL_EntityKind_Process) { continue; } // rjf: resolve module-dependent user bps for(CTRL_Entity *module = process->first; module != &ctrl_entity_nil; module = module->next) { if(module->kind != CTRL_EntityKind_Module) { continue; } ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, process->handle, module->handle, &msg->user_bps, &user_traps); } // rjf: push process-declared breakpoins for(CTRL_Entity *bp = process->first; bp != &ctrl_entity_nil; bp = bp->next) { if(bp->kind != CTRL_EntityKind_Breakpoint) { continue; } ctrl_thread__append_program_defined_bp_traps(scratch.arena, bp, &user_traps); } // rjf: push virtual-address user breakpoints per-process ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, process->handle, &msg->user_bps, &user_traps); } } ctrl_thread__eval_scope_end(eval_scope); } ////////////////////////////// //- rjf: read initial stack-pointer-check value // // This MUST happen before any threads move, including single-stepping stuck // threads, because otherwise, their stack pointer may change, if single-stepping // causes e.g. entrance into a function via a call instruction. // U64 sp_check_value = dmn_rsp_from_thread(target_thread.dmn_handle); log_infof("sp_check_value := 0x%I64x\n", sp_check_value); ////////////////////////////// //- rjf: single step "stuck threads" // // "Stuck threads" are threads that are already on a User BP and would hit // it immediately if resumed with all User BPs enabled. To get them "unstuck" // we just need to single step them to get them off their current instruction. // // This only applies to threads OTHER THAN the target thread. If the target // thread is on a user breakpoint, then we need to let trap net logic run, // which may include features put on a trap net trap at the same address as // the user breakpoint. // B32 target_thread_is_on_user_bp_and_trap_net_trap = 0; if(stop_event == 0) { // rjf: gather stuck threads DMN_HandleList stuck_threads = {0}; for(CTRL_Entity *machine = entity_ctx->root->first; machine != &ctrl_entity_nil; machine = machine->next) { if(machine->kind != CTRL_EntityKind_Machine) { continue; } for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next) { if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *thread = process->first; thread != &ctrl_entity_nil; thread = thread->next) { if(thread->kind != CTRL_EntityKind_Thread) { continue; } U64 rip = dmn_rip_from_thread(thread->handle.dmn_handle); // rjf: determine if thread is frozen B32 thread_is_frozen = thread->is_frozen; // rjf: not frozen? -> check if stuck & gather if so if(!thread_is_frozen) { for(DMN_TrapChunkNode *n = user_traps.first; n != 0; n = n->next) { B32 is_on_user_bp = 0; for(DMN_Trap *trap_ptr = n->v; trap_ptr < n->v+n->count; trap_ptr += 1) { if(dmn_handle_match(trap_ptr->process, process->handle.dmn_handle) && trap_ptr->vaddr == rip) { is_on_user_bp = 1; } } B32 is_on_net_trap = 0; for(CTRL_TrapNode *n = msg->traps.first; n != 0; n = n->next) { if(n->v.vaddr == rip) { is_on_net_trap = 1; } } if(is_on_user_bp && (!is_on_net_trap || !dmn_handle_match(thread->handle.dmn_handle, target_thread.dmn_handle))) { dmn_handle_list_push(scratch.arena, &stuck_threads, thread->handle.dmn_handle); } if(is_on_user_bp && is_on_net_trap && dmn_handle_match(thread->handle.dmn_handle, target_thread.dmn_handle)) { target_thread_is_on_user_bp_and_trap_net_trap = 1; } } } } } } // rjf: actually step stuck threads for(DMN_HandleNode *node = stuck_threads.first; node != 0; node = node->next) { DMN_Handle thread = node->v; U64 thread_pre_rip = dmn_rip_from_thread(thread); U64 thread_post_rip = thread_pre_rip; for(B32 done = 0; !done;) { log_infof("single_step_stuck_thread([0x%I64x])\n", thread.u64[0]); DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities = &thread; run_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { run_ctrls.single_step_thread = thread; } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; case DMN_EventKind_ExitThread: if(dmn_handle_match(event->thread, thread)) { stop_cause = CTRL_EventCause_Error; goto stop; }break; case DMN_EventKind_Error: stop_cause = CTRL_EventCause_Error; goto stop; case DMN_EventKind_Exception: stop_cause = CTRL_EventCause_InterruptedByException; goto stop; case DMN_EventKind_Trap: stop_cause = CTRL_EventCause_InterruptedByTrap; goto stop; case DMN_EventKind_Halt: stop_cause = CTRL_EventCause_InterruptedByHalt; goto stop; stop:; { stop_event = event; done = 1; }break; case DMN_EventKind_SingleStep: { done = dmn_handle_match(node->v, event->thread); }break; } } } } ////////////////////////////// //- rjf: gather frozen threads // CTRL_EntityList frozen_threads = {0}; for(CTRL_Entity *machine = entity_ctx->root->first; machine != &ctrl_entity_nil; machine = machine->next) { if(machine->kind != CTRL_EntityKind_Machine) { continue; } for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next) { if(process->kind != CTRL_EntityKind_Process) { continue; } for(CTRL_Entity *thread = process->first; thread != &ctrl_entity_nil; thread = thread->next) { if(thread->is_frozen) { ctrl_entity_list_push(scratch.arena, &frozen_threads, thread); } } } } ////////////////////////////// //- rjf: resolve trap net // DMN_TrapChunkList trap_net_traps = {0}; for(CTRL_TrapNode *node = msg->traps.first; node != 0; node = node->next) { DMN_Trap trap = {target_process.dmn_handle, node->v.vaddr}; dmn_trap_chunk_list_push(scratch.arena, &trap_net_traps, 256, &trap); } ////////////////////////////// //- rjf: join user breakpoints and trap net traps // DMN_TrapChunkList joined_traps = {0}; { dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &user_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &trap_net_traps); } ////////////////////////////// //- rjf: record start // if(stop_event == 0) { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Started; ctrl_c2u_push_events(&evts); } ////////////////////////////// //- rjf: run loop // if(stop_event == 0) { B32 spoof_mode = 0; CTRL_Spoof spoof = {0}; DMN_TrapChunkList entry_traps = {0}; for(U64 run_loop_idx = 0;; run_loop_idx += 1) { ////////////////////////// //- rjf: choose low level traps // DMN_TrapChunkList *trap_list = &joined_traps; if(spoof_mode) { trap_list = &user_traps; } ////////////////////////// //- rjf: choose spoof // CTRL_Spoof *run_spoof = 0; if(spoof_mode) { run_spoof = &spoof; } ////////////////////////// //- rjf: setup run controls // DMN_RunCtrls run_ctrls = {0}; if(run_loop_idx == 0) { run_ctrls.priority_thread = target_thread.dmn_handle; } run_ctrls.ignore_previous_exception = 1; run_ctrls.run_entity_count = frozen_threads.count; run_ctrls.run_entities = push_array(scratch.arena, DMN_Handle, run_ctrls.run_entity_count); run_ctrls.run_entities_are_unfrozen = 0; { U64 idx = 0; for(CTRL_EntityNode *n = frozen_threads.first; n != 0; n = n->next) { run_ctrls.run_entities[idx] = n->v->handle.dmn_handle; idx += 1; } } run_ctrls.traps = *trap_list; ////////////////////////// //- rjf: get next run-related event // log_infof("get_next_event:\n{\n"); DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, run_spoof); log_infof("}\n\n"); ////////////////////////// //- rjf: determine event handling // B32 launch_done_first_module = 0; B32 hard_stop = 0; CTRL_EventCause hard_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); B32 use_stepping_logic = 0; switch(event->kind) { default:{}break; case DMN_EventKind_Error: case DMN_EventKind_Halt: case DMN_EventKind_SingleStep: case DMN_EventKind_Trap: { hard_stop = 1; log_infof("step_rule: unexpected -> hard_stop\n"); }break; case DMN_EventKind_Exception: case DMN_EventKind_Breakpoint: { use_stepping_logic = 1; log_infof("step_rule: exception/breakpoint -> stepping_logic\n"); }break; case DMN_EventKind_CreateProcess: { CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, &ctrl_entity_nil); { DMN_TrapChunkList new_traps = {0}; ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps); log_infof("step_rule: create_process -> resolve traps\n"); log_infof("new_traps:\n{\n"); for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next) { for(U64 idx = 0; idx < n->count; idx += 1) { DMN_Trap *trap = &n->v[idx]; log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr); } } log_infof("}\n\n"); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps); } ctrl_thread__eval_scope_end(eval_scope); }break; case DMN_EventKind_LoadModule: { CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->thread)); CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread); { DMN_TrapChunkList new_traps = {0}; ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps); log_infof("step_rule: load_module -> resolve traps\n"); log_infof("new_traps:\n{\n"); for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next) { for(U64 idx = 0; idx < n->count; idx += 1) { DMN_Trap *trap = &n->v[idx]; log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr); } } log_infof("}\n\n"); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps); } ctrl_thread__eval_scope_end(eval_scope); }break; case DMN_EventKind_SetBreakpoint: { CTRL_Entity *bp = &ctrl_entity_nil; { CTRL_Entity *process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->process)); for(CTRL_Entity *child = process->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == CTRL_EntityKind_Breakpoint && child->vaddr_range.min == event->address && child->vaddr_range.max == event->address + event->size && child->bp_flags == ctrl_user_breakpoint_flags_from_dmn_trap_flags(event->flags)) { bp = child; break; } } } if(bp != &ctrl_entity_nil) { DMN_TrapChunkList new_traps = {0}; ctrl_thread__append_program_defined_bp_traps(scratch.arena, bp, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps); dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps); } }break; } ////////////////////////// //- rjf: on launches, detect entry points, place traps // if(msg->run_flags & CTRL_RunFlag_StopOnEntryPoint && !launch_done_first_module && event->kind == DMN_EventKind_HandshakeComplete) { launch_done_first_module = 1; Access *access = access_open(); //- rjf: unpack process/module info CTRL_Entity *process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->process)); CTRL_Entity *module = ctrl_entity_child_from_kind(process, CTRL_EntityKind_Module); U64 module_base_vaddr = module->vaddr_range.min; DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, max_U64); RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, unparsed_map, &map); //- rjf: add traps for user-specified entry points on this message, if specified B32 entries_found = 0; if(!entries_found) { for(String8Node *n = msg->entry_points.first; n != 0; n = n->next) { U32 procedure_id = 0; { String8 name = n->string; RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } } //- rjf: add traps for module-baked entry points, if specified if(!entries_found) { String8 raddbg_data = ctrl_raddbg_data_from_module(scratch.arena, module->handle); U8 split_char = 0; String8List raddbg_data_text_parts = str8_split(scratch.arena, raddbg_data, &split_char, 1, 0); for(String8Node *text_n = raddbg_data_text_parts.first; text_n != 0; text_n = text_n->next) { String8 text = text_n->string; MD_Node *root = md_tree_from_string(scratch.arena, text); if(str8_match(root->first->string, str8_lit("entry_point"), 0)) { String8 name = root->first->first->string; U32 procedure_id = 0; { RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } } } //- rjf: add traps for PID-correllated entry points if(!entries_found) { for(CTRL_Entity *e = entity_ctx->root->first; e != &ctrl_entity_nil; e = e->next) { if(e->id == process->id) { U32 procedure_id = 0; { String8 name = e->string; RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } } } //- rjf: add traps for all custom user entry points if(!entries_found) { for(String8Node *n = ctrl_state->user_entry_points.first; n != 0; n = n->next) { U32 procedure_id = 0; { String8 name = n->string; RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); break; } } } //- rjf: add traps for all high-level entry points if(!entries_found) { String8 hi_entry_points[] = { str8_lit("WinMain"), str8_lit("wWinMain"), str8_lit("main"), str8_lit("wmain"), }; for(U64 idx = 0; idx < ArrayCount(hi_entry_points); idx += 1) { U32 procedure_id = 0; { String8 name = hi_entry_points[idx]; RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } } //- rjf: add trap for PE header entry if(!entries_found) { U64 voff = ctrl_entry_point_voff_from_module(module->handle); if(voff != 0) { DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } //- rjf: add traps for all low-level entry points if(!entries_found) { String8 lo_entry_points[] = { str8_lit("WinMainCRTStartup"), str8_lit("wWinMainCRTStartup"), str8_lit("mainCRTStartup"), str8_lit("wmainCRTStartup"), }; for(U64 idx = 0; idx < ArrayCount(lo_entry_points); idx += 1) { U32 procedure_id = 0; { String8 name = lo_entry_points[idx]; RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { procedure_id = ids[0]; } } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; DMN_Trap trap = {process->handle.dmn_handle, module_base_vaddr + voff}; dmn_trap_chunk_list_push(scratch.arena, &entry_traps, 256, &trap); } } } //- rjf: no entry point found -> done if(entry_traps.trap_count == 0) { hard_stop = 1; } //- rjf: found entry points -> add to joined traps dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &entry_traps); access_close(access); } ////////////////////////// //- rjf: unpack info about thread attached to event // CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->thread)); CTRL_Entity *process = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->process)); Arch arch = thread->arch; U64 thread_rip_vaddr = dmn_rip_from_thread(event->thread); CTRL_Entity *module = &ctrl_entity_nil; { for(CTRL_Entity *m = process->first; m != &ctrl_entity_nil; m = m->next) { if(m->kind == CTRL_EntityKind_Module && contains_1u64(m->vaddr_range, thread_rip_vaddr)) { module = m; break; } } } ////////////////////////// //- rjf: extract module-dependent info // U64 thread_rip_voff = thread_rip_vaddr - module->vaddr_range.min; ////////////////////////// //- rjf: stepping logic // //{ ////////////////////////// //- rjf: handle if hitting a spoof // B32 exception_stop = 0; B32 hit_spoof = 0; if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Exception) { if(spoof_mode && dmn_handle_match(target_process.dmn_handle, event->process) && dmn_handle_match(target_thread.dmn_handle, event->thread) && spoof.new_ip_value == event->address) { hit_spoof = 1; log_infof("hit_spoof\n"); } else { exception_stop = 1; use_stepping_logic = 0; } } //- rjf: handle spoof hit if(hit_spoof) { log_infof("exit_spoof_mode\n"); // rjf: clear spoof mode spoof_mode = 0; MemoryZeroStruct(&spoof); // rjf: skip remainder of handling use_stepping_logic = 0; } //- rjf: for breakpoint events, gather bp info B32 hit_entry = 0; B32 hit_user_bp = 0; B32 hit_trap_net_bp = 0; B32 hit_conditional_bp_but_filtered = 0; CTRL_TrapFlags hit_trap_flags = 0; if(!hard_stop && use_stepping_logic && event->kind == DMN_EventKind_Breakpoint) ProfScope("for breakpoint events, gather bp info") { Temp temp = temp_begin(scratch.arena); String8List conditions = {0}; // rjf: entry breakpoints for(DMN_TrapChunkNode *n = entry_traps.first; n != 0; n = n->next) { DMN_Trap *trap = n->v; DMN_Trap *opl = n->v + n->count; for(;trap < opl; trap += 1) { if(dmn_handle_match(trap->process, event->process) && trap->vaddr == event->instruction_pointer) { hit_entry = 1; } } } // rjf: user breakpoints { if(event->user_data != 0) { hit_user_bp = 1; } for(DMN_TrapChunkNode *n = user_traps.first; n != 0; n = n->next) { DMN_Trap *trap = n->v; DMN_Trap *opl = n->v + n->count; for(;trap < opl; trap += 1) { if(dmn_handle_match(trap->process, event->process) && trap->vaddr == event->instruction_pointer && (!dmn_handle_match(event->thread, target_thread.dmn_handle) || !target_thread_is_on_user_bp_and_trap_net_trap)) { CTRL_UserBreakpoint *user_bp = (CTRL_UserBreakpoint *)trap->id; hit_user_bp = 1; if(user_bp != 0 && !(trap->id & bit64) && user_bp->condition.size != 0) { str8_list_push(temp.arena, &conditions, user_bp->condition); } } } } } // rjf: programmatic user breakpoints (we do not have state for it, // but the target program(s) did something breakpoint-like, and we // want to treat it as if we did) if(event->address != 0) { hit_user_bp = 1; } // rjf: evaluate hit stop conditions if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions") { CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, &msg->user_bps, thread); for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next) { // rjf: evaluate E_Eval eval = zero_struct; ProfScope("evaluate expression") { eval = e_eval_from_string(condition_n->string); } // rjf: interpret evaluation if(eval.code == E_InterpretationCode_Good && eval.value.u64 == 0) { hit_user_bp = 0; hit_conditional_bp_but_filtered = 1; log_infof("conditional_breakpoint_hit: 'condition eval'd to 0, and so filtered'\n"); } else { hit_user_bp = 1; hit_conditional_bp_but_filtered = 0; log_infof("conditional_breakpoint_hit: 'conditional eval'd to nonzero, hit'\n"); break; } } ctrl_thread__eval_scope_end(eval_scope); } // rjf: gather trap net hits ProfScope("gather trap net hits") { if(!hit_user_bp && dmn_handle_match(event->process, target_process.dmn_handle)) { for(CTRL_TrapNode *node = msg->traps.first; node != 0; node = node->next) { if(node->v.vaddr == event->instruction_pointer) { hit_trap_net_bp = 1; hit_trap_flags |= node->v.flags; } } } } log_infof("user_breakpoint_hit: %i\n", hit_user_bp); log_infof("entry_point_hit: %i\n", hit_entry); temp_end(temp); } //- rjf: hit conditional user bp but filtered -> single step B32 cond_bp_single_step_stop = 0; CTRL_EventCause cond_bp_single_step_stop_cause = CTRL_EventCause_Null; if(hit_conditional_bp_but_filtered) LogInfoNamedBlockF("conditional_bp_hit_single_step") { DMN_Handle thread = event->thread; U64 thread_pre_rip = dmn_rip_from_thread(thread); U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; !single_step_done;) { DMN_RunCtrls single_step_ctrls = {0}; single_step_ctrls.run_entities_are_unfrozen = 1; single_step_ctrls.run_entities = &thread; single_step_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { single_step_ctrls.single_step_thread = thread; } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; case DMN_EventKind_Error: case DMN_EventKind_Exception: case DMN_EventKind_Halt: case DMN_EventKind_Trap: { cond_bp_single_step_stop = 1; single_step_done = 1; use_stepping_logic = 0; cond_bp_single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; case DMN_EventKind_SingleStep: { single_step_done = dmn_handle_match(event->thread, thread); cond_bp_single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } } } //- rjf: hit entry points on *any thread* cause a stop, if this msg says as such B32 entry_stop = 0; if(msg->run_flags & CTRL_RunFlag_StopOnEntryPoint && hit_entry) { entry_stop = 1; use_stepping_logic = 0; } //- rjf: user breakpoints on *any thread* cause a stop B32 user_bp_stop = 0; if(!hard_stop && use_stepping_logic && hit_user_bp) { user_bp_stop = 1; use_stepping_logic = 0; } //- rjf: trap net on off-target threads are ignored B32 step_past_trap_net = 0; if(!hard_stop && use_stepping_logic && hit_trap_net_bp) { if(!dmn_handle_match(event->thread, target_thread.dmn_handle)) { step_past_trap_net = 1; use_stepping_logic = 0; } } //- rjf: trap net on on-target threads trigger trap net logic B32 use_trap_net_logic = 0; if(!hard_stop && use_stepping_logic && hit_trap_net_bp) { if(dmn_handle_match(event->thread, target_thread.dmn_handle)) { use_trap_net_logic = 1; } } //- rjf: trap net logic: stack pointer check B32 stack_pointer_matches = 0; if(use_trap_net_logic) { U64 sp = dmn_rsp_from_thread(target_thread.dmn_handle); stack_pointer_matches = (sp == sp_check_value); } //- rjf: trap net logic: single step after hit B32 single_step_stop = 0; CTRL_EventCause single_step_stop_cause = CTRL_EventCause_Null; if(!hard_stop && use_trap_net_logic) { if(hit_trap_flags & CTRL_TrapFlag_SingleStepAfterHit) LogInfoNamedBlockF("trap_net__single_step_after_hit") { U64 thread_pre_rip = dmn_rip_from_thread(target_thread.dmn_handle); U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { DMN_RunCtrls single_step_ctrls = {0}; single_step_ctrls.run_entities_are_unfrozen = 1; single_step_ctrls.run_entities = &target_thread.dmn_handle; single_step_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { single_step_ctrls.single_step_thread = target_thread.dmn_handle; } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); thread_post_rip = dmn_rip_from_thread(target_thread.dmn_handle); switch(event->kind) { default:{}break; case DMN_EventKind_Error: case DMN_EventKind_Exception: case DMN_EventKind_Halt: case DMN_EventKind_Trap: { single_step_stop = 1; single_step_done = 1; use_stepping_logic = 0; use_trap_net_logic = 0; single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; case DMN_EventKind_SingleStep: { single_step_done = dmn_handle_match(event->thread, target_thread.dmn_handle); single_step_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } } } } //- rjf: trap net logic: begin spoof mode B32 begin_spoof_mode = 0; if(!hard_stop && use_trap_net_logic) { if(hit_trap_flags & CTRL_TrapFlag_BeginSpoofMode) LogInfoNamedBlockF("trap_net__begin_spoof_mode") { // rjf: setup spoof mode begin_spoof_mode = 1; U64 spoof_sp = dmn_rsp_from_thread(target_thread.dmn_handle); spoof_mode = 1; spoof.process = target_process.dmn_handle; spoof.thread = target_thread.dmn_handle; spoof.vaddr = spoof_sp; spoof.new_ip_value = spoof_ip_vaddr; log_infof("spoof:{process:[0x%I64x], thread:[0x%I64x], vaddr:0x%I64x, new_ip_value:0x%I64x}\n", spoof.process.u64[0], spoof.thread.u64[0], spoof.vaddr, spoof.new_ip_value); } } //- rjf: trap net logic: save stack pointer B32 save_stack_pointer = 0; if(!hard_stop && use_trap_net_logic) { if(hit_trap_flags & CTRL_TrapFlag_SaveStackPointer) { if(stack_pointer_matches) LogInfoNamedBlockF("trap_net__save_sp") { save_stack_pointer = 1; sp_check_value = dmn_rsp_from_thread(target_thread.dmn_handle); log_infof("sp_check_value = 0x%I64x\n", sp_check_value); } } } //- rjf: trap net logic: end stepping B32 trap_net_stop = 0; if(!hard_stop && use_trap_net_logic) { if(hit_trap_flags & CTRL_TrapFlag_EndStepping) LogInfoNamedBlockF("trap_net__end_step") { if((hit_trap_flags & CTRL_TrapFlag_IgnoreStackPointerCheck) || stack_pointer_matches) { trap_net_stop = 1; use_trap_net_logic = 0; } } } //} // //- rjf: stepping logic //////////////////////////////// //- rjf: handle step past trap net B32 step_past_trap_net_stop = 0; CTRL_EventCause step_past_trap_net_stop_cause = CTRL_EventCause_Null; if(step_past_trap_net) LogInfoNamedBlockF("trap_net__single_step_past_trap_net") { DMN_Handle thread = event->thread; U64 thread_pre_rip = dmn_rip_from_thread(thread); U64 thread_post_rip = thread_pre_rip; for(B32 single_step_done = 0; single_step_done == 0;) { DMN_RunCtrls single_step_ctrls = {0}; single_step_ctrls.run_entities_are_unfrozen = 1; single_step_ctrls.run_entities = &thread; single_step_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { single_step_ctrls.single_step_thread = thread; } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &single_step_ctrls, 0); thread_post_rip = dmn_rip_from_thread(thread); switch(event->kind) { default:{}break; case DMN_EventKind_Error: case DMN_EventKind_Exception: case DMN_EventKind_Halt: case DMN_EventKind_Trap: { step_past_trap_net_stop = 1; single_step_done = 1; step_past_trap_net_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; case DMN_EventKind_SingleStep: { single_step_done = dmn_handle_match(event->thread, thread); step_past_trap_net_stop_cause = ctrl_event_cause_from_dmn_event_kind(event->kind); }break; } } } //- rjf: loop exit condition CTRL_EventCause stage_stop_cause = CTRL_EventCause_Null; if(hard_stop) { stage_stop_cause = hard_stop_cause; } else if(cond_bp_single_step_stop) { stage_stop_cause = cond_bp_single_step_stop_cause; } else if(single_step_stop) { stage_stop_cause = single_step_stop_cause; } else if(step_past_trap_net_stop) { stage_stop_cause = step_past_trap_net_stop_cause; } else if(exception_stop) { stage_stop_cause = CTRL_EventCause_InterruptedByException; } else if(user_bp_stop) { stage_stop_cause = CTRL_EventCause_UserBreakpoint; } else if(entry_stop) { stage_stop_cause = CTRL_EventCause_EntryPoint; } else if(trap_net_stop) { stage_stop_cause = CTRL_EventCause_Finished; } log_infof("stop_cause: %i\n", stage_stop_cause); if(stage_stop_cause != CTRL_EventCause_Null) { stop_event = event; stop_cause = stage_stop_cause; break; } } } ////////////////////////////// //- rjf: record stop // if(stop_event != 0) { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = stop_cause; event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread); event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process); event->exception_code = stop_event->code; event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind); event->vaddr_rng = r1u64(stop_event->address, stop_event->address); event->rip_vaddr = stop_event->instruction_pointer; if(stop_cause == CTRL_EventCause_UserBreakpoint && stop_event->user_data != 0) { if(!(stop_event->user_data & bit64)) { CTRL_UserBreakpoint *user_bp = (CTRL_UserBreakpoint *)stop_event->user_data; event->u64_code = user_bp->id; } } ctrl_c2u_push_events(&evts); } log_infof("}\n\n"); scratch_end(scratch); ProfEnd(); } internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); //- rjf: record start { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Started; ctrl_c2u_push_events(&evts); } //- rjf: single step DMN_Handle thread = msg->entity.dmn_handle; B32 thread_is_valid = !dmn_handle_match(thread, dmn_handle_zero()); DMN_Event *stop_event = 0; CTRL_EventCause stop_cause = CTRL_EventCause_Null; if(thread_is_valid) { U64 thread_pre_rip = dmn_rip_from_thread(thread); U64 thread_post_rip = thread_pre_rip; for(B32 done = 0; done == 0;) { DMN_RunCtrls run_ctrls = {0}; run_ctrls.run_entities_are_unfrozen = 1; run_ctrls.run_entities = &thread; run_ctrls.run_entity_count = 1; if(thread_post_rip == thread_pre_rip) { run_ctrls.single_step_thread = msg->entity.dmn_handle; } DMN_Event *event = ctrl_thread__next_dmn_event(scratch.arena, ctrl_ctx, msg, &run_ctrls, 0); thread_post_rip = dmn_rip_from_thread(msg->entity.dmn_handle); switch(event->kind) { default:{}break; case DMN_EventKind_Error: {stop_cause = CTRL_EventCause_Error;}goto end_single_step; case DMN_EventKind_Exception: {stop_cause = CTRL_EventCause_InterruptedByException;}goto end_single_step; case DMN_EventKind_Halt: {stop_cause = CTRL_EventCause_InterruptedByHalt;}goto end_single_step; case DMN_EventKind_Trap: {stop_cause = CTRL_EventCause_InterruptedByTrap;}goto end_single_step; case DMN_EventKind_Breakpoint: {stop_cause = CTRL_EventCause_UserBreakpoint;}goto end_single_step; case DMN_EventKind_SingleStep: {stop_cause = CTRL_EventCause_Finished;}goto end_single_step; end_single_step: { stop_event = event; done = 1; }break; } } } //- rjf: record stop { CTRL_EventList evts = {0}; CTRL_Event *event = ctrl_event_list_push(scratch.arena, &evts); event->kind = CTRL_EventKind_Stopped; event->cause = stop_cause; if(stop_event != 0) { event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread); event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process); event->exception_code = stop_event->code; event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind); event->vaddr_rng = r1u64(stop_event->address, stop_event->address); event->rip_vaddr = stop_event->instruction_pointer; } ctrl_c2u_push_events(&evts); } scratch_end(scratch); ProfEnd(); } //////////////////////////////// //~ rjf: Process Memory Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { AC_Artifact artifact = {0}; { //- rjf: unpack key CTRL_Handle process = {0}; Rng1U64 vaddr_range = {0}; B32 zero_terminated = 0; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &process); key_read_off += str8_deserial_read_struct(key, key_read_off, &vaddr_range); key_read_off += str8_deserial_read_struct(key, key_read_off, &zero_terminated); } //- rjf: clamp vaddr range Rng1U64 vaddr_range_clamped = vaddr_range; { vaddr_range_clamped.max = Max(vaddr_range_clamped.max, vaddr_range_clamped.min); U64 max_size_cap = Min(max_U64-vaddr_range_clamped.min, GB(1)); vaddr_range_clamped.max = Min(vaddr_range_clamped.max, vaddr_range_clamped.min+max_size_cap); } //- rjf: do read U64 range_size = dim_1u64(vaddr_range_clamped); Arena *range_arena = 0; void *range_base = 0; U64 zero_terminated_size = 0; U64 pre_read_mem_gen = ctrl_mem_gen(); B32 pre_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state); if(range_size != 0) { // rjf: set up arena U64 page_size = os_get_system_info()->page_size; // TODO(rjf): @page_size_from_process U64 arena_size = AlignPow2(range_size + ARENA_HEADER_SIZE, page_size); range_arena = arena_alloc(.reserve_size = range_size+ARENA_HEADER_SIZE, .commit_size = range_size+ARENA_HEADER_SIZE); // rjf: if we got an arena -> push buffer & read if(range_arena != 0) { // rjf: read as much as possible range_base = push_array_no_zero(range_arena, U8, range_size); U64 bytes_read = 0; U64 retry_count = 0; U64 retry_limit = range_size > page_size ? 64 : 0; for(Rng1U64 vaddr_range_clamped_retry = vaddr_range_clamped; retry_count <= retry_limit; retry_count += 1) { bytes_read = dmn_process_read(process.dmn_handle, vaddr_range_clamped_retry, range_base); if(bytes_read == 0 && vaddr_range_clamped_retry.max > vaddr_range_clamped_retry.min) { U64 diff = (vaddr_range_clamped_retry.max-vaddr_range_clamped_retry.min)/2; vaddr_range_clamped_retry.max -= diff; vaddr_range_clamped_retry.max = AlignDownPow2(vaddr_range_clamped_retry.max, page_size); if(diff == 0) { break; } } else { break; } } // rjf: if we read nothing, release arena if(bytes_read == 0) { arena_release(range_arena); range_base = 0; range_arena = 0; } // rjf: if we only got a partial read, zero the rest else if(bytes_read < range_size) { MemoryZero((U8 *)range_base + bytes_read, range_size-bytes_read); } // rjf: determine final size; zero terminate if needed; pop any unneeded bytes if zero-terminating zero_terminated_size = bytes_read; if(zero_terminated && range_base != 0) { for(U64 idx = 0; idx < bytes_read; idx += 1) { if(((U8 *)range_base)[idx] == 0) { zero_terminated_size = idx; break; } } U64 bytes_overkill = (bytes_read - zero_terminated_size); arena_pop(range_arena, bytes_overkill); } } } U64 post_read_mem_gen = ctrl_mem_gen(); B32 post_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state); //- rjf: form content key C_Key content_key = {0}; { content_key.id.u128[0] = u128_hash_from_str8(key); } //- rjf: determine if we have any history for this key B32 key_has_history = 0; { U128 last_hash = c_hash_from_key(content_key, 0); if(!u128_match(last_hash, u128_zero())) { key_has_history = 1; } } //- rjf: read successful, OR we have no history -> submit to hash store U128 hash = {0}; if((zero_terminated_size > 0 || !key_has_history) && range_base != 0 && range_size != 0 && pre_read_mem_gen == post_read_mem_gen) { hash = c_submit_data(content_key, &range_arena, str8((U8 *)range_base, zero_terminated_size)); gen_out[0] = pre_read_mem_gen; } //- rjf: wakeup on new submissions if(!u128_match(u128_zero(), hash)) { if(ctrl_state->wakeup_hook != 0) { ctrl_state->wakeup_hook(); } } //- rjf: always release leftover arenas if(range_arena != 0) { arena_release(range_arena); } //- rjf: retry on mem gen "tearing", and if the range is non-empty if(pre_read_mem_gen != post_read_mem_gen && range_size != 0) { retry_out[0] = 1; } //- rjf: bundle content key as artifact StaticAssert(sizeof(content_key) == sizeof(artifact), artifact_key_size_check); MemoryCopyStruct(&artifact, &content_key); } return artifact; } internal void ctrl_memory_artifact_destroy(AC_Artifact artifact) { C_Key key = {0}; MemoryCopyStruct(&key, &artifact); c_close_key(key); } internal C_Key ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, B32 wait_for_fresh, U64 endt_us, B32 *out_is_stale) { ProfBeginFunction(); #pragma pack(push, 1) struct { CTRL_Handle process; Rng1U64 vaddr_range; B32 zero_terminated; } key_data = {process, vaddr_range, zero_terminated}; #pragma pack(pop) String8 key = str8_struct(&key_data); Access *access = access_open(); AC_Artifact artifact = ac_artifact_from_key(access, key, ctrl_memory_artifact_create, ctrl_memory_artifact_destroy, endt_us, .flags = AC_Flag_HighPriority | (wait_for_fresh ? AC_Flag_WaitForFresh : 0), .gen = ctrl_mem_gen(), .slots_count = 2048, .stale_out = out_is_stale, .evict_threshold_us = 10000000); C_Key content_key = {0}; MemoryCopyStruct(&content_key, &artifact); access_close(access); ProfEnd(); return content_key; } //- rjf: process memory reading helpers internal CTRL_ProcessMemorySlice ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, B32 wait_for_fresh, U64 endt_us) { ProfBeginFunction(); CTRL_ProcessMemorySlice result = {0}; if(range.max > range.min && dim_1u64(range) <= MB(256) && range.min <= 0x000FFFFFFFFFFFFFull && range.max <= 0x000FFFFFFFFFFFFFull) { Temp scratch = scratch_begin(&arena, 1); Access *access = access_open(); //- rjf: unpack address range, prepare per-touched-page info U64 page_size = KB(4); Rng1U64 page_range = r1u64(AlignDownPow2(range.min, page_size), AlignPow2(range.max, page_size)); U64 page_count = dim_1u64(page_range)/page_size; U128 *page_hashes = push_array(scratch.arena, U128, page_count); U128 *page_last_hashes = push_array(scratch.arena, U128, page_count); //- rjf: gather hashes & last-hashes for each page ProfScope("gather hashes & last-hashes for each page") { for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) { U64 page_base_vaddr = page_range.min + page_idx*page_size; B32 page_is_stale = 0; C_Key page_key = ctrl_key_from_process_vaddr_range(process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0, wait_for_fresh, endt_us, &page_is_stale); U128 page_hash = c_hash_from_key(page_key, 0); U128 page_last_hash = c_hash_from_key(page_key, 1); result.stale = (result.stale || page_is_stale); page_hashes[page_idx] = page_hash; page_last_hashes[page_idx] = page_last_hash; } } //- rjf: setup output buffers void *read_out = push_array(arena, U8, dim_1u64(range)); U64 *byte_bad_flags = push_array(arena, U64, (dim_1u64(range)+63)/64); U64 *byte_changed_flags = push_array(arena, U64, (dim_1u64(range)+63)/64); //- rjf: iterate pages, fill output ProfScope("iterate pages, fill output") { U64 write_off = 0; for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) { // rjf: read data for this page String8 data = c_data_from_hash(access, page_hashes[page_idx]); Rng1U64 data_vaddr_range = r1u64(page_range.min + page_idx*page_size, page_range.min + page_idx*page_size+data.size); // rjf: skip/chop bytes which are irrelevant for the actual requested read String8 in_range_data = data; if(page_idx == page_count-1 && data_vaddr_range.max > range.max) { in_range_data = str8_chop(in_range_data, data_vaddr_range.max-range.max); } if(page_idx == 0 && range.min > data_vaddr_range.min) { in_range_data = str8_skip(in_range_data, range.min-data_vaddr_range.min); } // rjf: write this chunk MemoryCopy((U8*)read_out+write_off, in_range_data.str, in_range_data.size); // rjf; if this page's data doesn't fill the entire range, mark // missing bytes as bad if(data.size < page_size) ProfScope("mark missing bytes as bad") { Rng1U64 invalid_range = r1u64(data_vaddr_range.min+data.size, data_vaddr_range.min + page_size); Rng1U64 in_range_invalid_range = intersect_1u64(invalid_range, range); for(U64 invalid_vaddr = in_range_invalid_range.min; invalid_vaddr < in_range_invalid_range.max; invalid_vaddr += 1) { U64 idx_in_range = invalid_vaddr - range.min; byte_bad_flags[idx_in_range/64] |= (1ull<<(idx_in_range%64)); } } // rjf: if this page's hash & last_hash don't match, diff each byte & // fill out changed flags if(!u128_match(page_hashes[page_idx], page_last_hashes[page_idx])) ProfScope("hashes don't match; diff each byte") { String8 last_data = c_data_from_hash(access, page_last_hashes[page_idx]); String8 in_range_last_data = last_data; if(page_idx == page_count-1 && data_vaddr_range.max > range.max) { in_range_last_data = str8_chop(in_range_last_data, data_vaddr_range.max-range.max); } if(page_idx == 0 && range.min > data_vaddr_range.min) { in_range_last_data = str8_skip(in_range_last_data, range.min-data_vaddr_range.min); } for(U64 idx = 0; idx < in_range_data.size; idx += 1) { U8 last_byte = idx < in_range_last_data.size ? in_range_last_data.str[idx] : 0; U8 now_byte = idx < in_range_data.size ? in_range_data.str[idx] : 0; if(last_byte != now_byte) { U64 idx_in_read_out = write_off+idx; byte_changed_flags[idx_in_read_out/64] |= (1ull<<(idx_in_read_out%64)); } } } // rjf: increment past this chunk U64 bytes_to_skip = page_size; if(page_idx == 0 && range.min > data_vaddr_range.min) { bytes_to_skip -= (range.min-data_vaddr_range.min); } write_off += bytes_to_skip; } } //- rjf: fill result result.data.str = (U8*)read_out; result.data.size = dim_1u64(range); result.byte_bad_flags = byte_bad_flags; result.byte_changed_flags = byte_changed_flags; if(byte_bad_flags != 0) { for(U64 idx = 0; idx < (dim_1u64(range)+63)/64; idx += 1) { result.any_byte_bad = result.any_byte_bad || !!result.byte_bad_flags[idx]; } } if(byte_changed_flags != 0) { for(U64 idx = 0; idx < (dim_1u64(range)+63)/64; idx += 1) { result.any_byte_changed = result.any_byte_changed || !!result.byte_changed_flags[idx]; } } access_close(access); scratch_end(scratch); } ProfEnd(); return result; } internal B32 ctrl_process_memory_read(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us) { Temp scratch = scratch_begin(0, 0); U64 needed_size = dim_1u64(range); CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process, range, 0, endt_us); B32 good = (slice.data.size >= needed_size && !slice.any_byte_bad); if(good) { MemoryCopy(out, slice.data.str, needed_size); } if(slice.stale && is_stale_out) { *is_stale_out = 1; } scratch_end(scratch); return good; } //- rjf: process memory writing internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src) { ProfBeginFunction(); B32 result = dmn_process_write(process.dmn_handle, range, src); //- rjf: success -> bump generation if(result) { ins_atomic_u64_inc_eval(&ctrl_state->mem_gen); } //- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless // writes within calling frame's "view" of the memory, at the expense of a small amount of // time. if(result) { U64 endt_us = os_now_microseconds()+10000; U64 page_size = os_get_system_info()->page_size; // TODO(rjf): @page_size_from_process Rng1U64 page_range = r1u64(range.min/page_size, (range.max+page_size-1)/page_size); for EachInRange(page_idx, page_range) { Temp scratch = scratch_begin(0, 0); CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process, r1u64(page_idx*page_size, (page_idx+1)*page_size), 1, endt_us); scratch_end(scratch); if(!slice.stale || os_now_microseconds() >= endt_us) { break; } } } ProfEnd(); return result; } //////////////////////////////// //~ rjf: Call Stack Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { AC_Artifact artifact = {0}; { Temp scratch = scratch_begin(0, 0); //- rjf: unpack key CTRL_Handle thread_handle = {0}; str8_deserial_read_struct(key, 0, &thread_handle); //- rjf: produce mini entity context for just this call stack build CTRL_EntityCtx *entity_ctx = push_array(scratch.arena, CTRL_EntityCtx, 1); MutexScopeR(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { CTRL_EntityCtx *src_ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_EntityCtx *dst_ctx = entity_ctx; { dst_ctx->root = &ctrl_entity_nil; dst_ctx->hash_slots_count = 1024; dst_ctx->hash_slots = push_array(scratch.arena, CTRL_EntityHashSlot, dst_ctx->hash_slots_count); MemoryCopyArray(dst_ctx->entity_kind_counts, src_ctx->entity_kind_counts); MemoryCopyArray(dst_ctx->entity_kind_alloc_gens, src_ctx->entity_kind_alloc_gens); } CTRL_Entity *src_thread = ctrl_entity_from_handle(src_ctx, thread_handle); CTRL_Entity *src_process = ctrl_process_from_entity(src_thread); { CTRL_EntityRec rec = {0}; CTRL_Entity *dst_parent = &ctrl_entity_nil; for(CTRL_Entity *src_e = src_process; src_e != &ctrl_entity_nil; src_e = rec.next) { rec = ctrl_entity_rec_depth_first_pre(src_e, src_process); // rjf: determine if we need this entity B32 need_this_entity = (ctrl_handle_match(thread_handle, src_e->handle) || src_e->kind == CTRL_EntityKind_Module || src_e->kind == CTRL_EntityKind_Process); // rjf: copy this entity CTRL_Entity *dst_e = &ctrl_entity_nil; if(need_this_entity) { dst_e = push_array(scratch.arena, CTRL_Entity, 1); { dst_e->first = dst_e->last = dst_e->next = dst_e->prev = &ctrl_entity_nil; dst_e->parent = dst_parent; dst_e->kind = src_e->kind; dst_e->arch = src_e->arch; dst_e->is_frozen = src_e->is_frozen; dst_e->is_soloed = src_e->is_soloed; dst_e->rgba = src_e->rgba; dst_e->handle = src_e->handle; dst_e->id = src_e->id; dst_e->vaddr_range = src_e->vaddr_range; dst_e->stack_base = src_e->stack_base; dst_e->timestamp = src_e->timestamp; dst_e->bp_flags = src_e->bp_flags; dst_e->string = push_str8_copy(scratch.arena, src_e->string); } if(dst_parent == &ctrl_entity_nil) { dst_ctx->root = dst_e; } else { DLLPushBack_NPZ(&ctrl_entity_nil, dst_parent->first, dst_parent->last, dst_e, next, prev); } } // rjf: insert into hash map if(dst_e != &ctrl_entity_nil) { U64 hash = ctrl_hash_from_handle(dst_e->handle); U64 slot_idx = hash%dst_ctx->hash_slots_count; CTRL_EntityHashSlot *slot = &dst_ctx->hash_slots[slot_idx]; CTRL_EntityHashNode *node = 0; for(CTRL_EntityHashNode *n = slot->first; n != 0; n = n->next) { if(ctrl_handle_match(n->entity->handle, dst_e->handle)) { node = n; break; } } if(node == 0) { node = push_array(scratch.arena, CTRL_EntityHashNode, 1); MemoryZeroStruct(node); DLLPushBack(slot->first, slot->last, node); node->entity = dst_e; } } // rjf: push/pop if(rec.push_count) { dst_parent = dst_e; } else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1) { dst_parent = dst_parent->parent; } } } } //- rjf: compute call stack CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, thread_handle); B32 good = 1; B32 retry = 0; Arena *arena = 0; CTRL_CallStack *call_stack = 0; if(thread != &ctrl_entity_nil) { good = 0; arena = arena_alloc(); call_stack = push_array(arena, CTRL_CallStack, 1); CTRL_Entity *process = ctrl_process_from_entity(thread); U64 pre_reg_gen = 0; U64 post_reg_gen = 0; U64 pre_mem_gen = 0; U64 post_mem_gen = 0; CTRL_Unwind unwind = {0}; { pre_reg_gen = ctrl_reg_gen(); pre_mem_gen = ctrl_mem_gen(); unwind = ctrl_unwind_from_thread(arena, entity_ctx, thread_handle, os_now_microseconds()+5000); if(unwind.flags == 0) { good = 1; call_stack[0] = ctrl_call_stack_from_unwind(arena, process, &unwind); } if(unwind.flags & CTRL_UnwindFlag_Stale) { retry = 1; } post_reg_gen = ctrl_reg_gen(); post_mem_gen = ctrl_mem_gen(); } if(pre_reg_gen != post_reg_gen || pre_mem_gen != post_mem_gen) { good = 0; retry = 1; } if(!good) { arena_release(arena); } } //- rjf: broadcast update if(good && ctrl_state->wakeup_hook != 0) { ctrl_state->wakeup_hook(); } //- rjf: bundle call stack as artifact if(good) { artifact.u64[0] = (U64)arena; artifact.u64[1] = (U64)call_stack; } //- rjf: mark retry retry_out[0] = retry; scratch_end(scratch); } return artifact; } internal void ctrl_call_stack_artifact_destroy(AC_Artifact artifact) { Arena *arena = (Arena *)artifact.u64[0]; if(arena != 0) { arena_release(arena); } } internal CTRL_CallStack ctrl_call_stack_from_thread(Access *access, CTRL_Handle thread_handle, B32 high_priority, U64 endt_us) { CTRL_CallStack result = {0}; { AC_Artifact artifact = ac_artifact_from_key(access, str8_struct(&thread_handle), ctrl_call_stack_artifact_create, ctrl_call_stack_artifact_destroy, endt_us, .gen = ctrl_mem_gen() + ctrl_reg_gen(), .evict_threshold_us = 10000000, .flags = high_priority ? AC_Flag_HighPriority : 0); if(artifact.u64[1] != 0) { MemoryCopyStruct(&result, (CTRL_CallStack *)artifact.u64[1]); } } return result; } //////////////////////////////// //~ rjf: Call Stack Tree Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_call_stack_tree_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { Temp scratch = scratch_begin(0, 0); Access *access = access_open(); //- rjf: gather list of all thread handles U64 threads_count = 0; CTRL_Handle *threads = 0; CTRL_Handle *threads_processes = 0; Arch *threads_arches = 0; MutexScopeR(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) { CTRL_EntityCtx *ctx = &ctrl_state->ctrl_thread_entity_store->ctx; CTRL_EntityArray thread_entities = ctrl_entity_array_from_kind(ctx, CTRL_EntityKind_Thread); threads_count = thread_entities.count; threads = push_array(scratch.arena, CTRL_Handle, threads_count); threads_processes = push_array(scratch.arena, CTRL_Handle, threads_count); threads_arches = push_array(scratch.arena, Arch, threads_count); for EachIndex(idx, threads_count) { threads[idx] = thread_entities.v[idx]->handle; threads_processes[idx] = thread_entities.v[idx]->parent->handle; threads_arches[idx] = thread_entities.v[idx]->arch; } } //- rjf: gather all callstacks B32 stale = 0; U64 pre_mem_gen = ctrl_mem_gen(); U64 pre_reg_gen = ctrl_reg_gen(); CTRL_CallStack *call_stacks = push_array(scratch.arena, CTRL_CallStack, threads_count); { for EachIndex(idx, threads_count) { call_stacks[idx] = ctrl_call_stack_from_thread(access, threads[idx], 0, 0); if(call_stacks[idx].concrete_frames_count == 0) { stale = 1; break; } } } U64 post_mem_gen = ctrl_mem_gen(); U64 post_reg_gen = ctrl_reg_gen(); stale = (stale || pre_mem_gen != post_mem_gen || pre_reg_gen != post_reg_gen); //- rjf: build call stack tree Arena *arena = 0; CTRL_CallStackTree *tree = 0; if(!stale) { U64 id_gen = 0; arena = arena_alloc(); tree = push_array(arena, CTRL_CallStackTree, 1); tree->root = push_array(arena, CTRL_CallStackTreeNode, 1); MemoryCopyStruct(tree->root, &ctrl_call_stack_tree_node_nil); tree->root->id = id_gen; tree->slots_count = Max(1, threads_count); tree->slots = push_array(arena, CTRL_CallStackTreeNode *, tree->slots_count); id_gen += 1; for EachIndex(thread_idx, threads_count) { CTRL_Handle thread = threads[thread_idx]; CTRL_Handle process = threads_processes[thread_idx]; Arch arch = threads_arches[thread_idx]; CTRL_CallStack call_stack = call_stacks[thread_idx]; CTRL_CallStackTreeNode *thread_node = tree->root; for EachIndex(frame_idx, call_stack.frames_count) { U64 vaddr = regs_rip_from_arch_block(arch, call_stack.frames[frame_idx].regs); U64 depth = call_stack.frames[frame_idx].inline_depth; CTRL_CallStackTreeNode *next_node = &ctrl_call_stack_tree_node_nil; for(CTRL_CallStackTreeNode *child = thread_node->first; child != &ctrl_call_stack_tree_node_nil; child = child->next) { if(ctrl_handle_match(child->process, process) && child->vaddr == vaddr && child->depth == depth) { next_node = child; break; } } if(next_node == &ctrl_call_stack_tree_node_nil) { next_node = push_array(arena, CTRL_CallStackTreeNode, 1); MemoryCopyStruct(next_node, &ctrl_call_stack_tree_node_nil); next_node->id = id_gen; SLLStackPush_N(tree->slots[next_node->id%tree->slots_count], next_node, hash_next); id_gen += 1; SLLQueuePush_NZ(&ctrl_call_stack_tree_node_nil, thread_node->first, thread_node->last, next_node, next); next_node->parent = thread_node; thread_node->child_count += 1; } thread_node = next_node; } ctrl_handle_list_push(arena, &thread_node->threads, &thread); for(CTRL_CallStackTreeNode *n = thread_node; n != &ctrl_call_stack_tree_node_nil; n = n->parent) { n->all_descendant_threads_count += 1; } } } //- rjf: produce artifact AC_Artifact artifact = {0}; { artifact.u64[0] = (U64)arena; artifact.u64[1] = (U64)tree; } //- rjf: retry on stale if(stale) { retry_out[0] = 1; } access_close(access); scratch_end(scratch); return artifact; } internal void ctrl_call_stack_tree_artifact_destroy(AC_Artifact artifact) { Arena *arena = (Arena *)artifact.u64[0]; if(arena != 0) { arena_release(arena); } } internal CTRL_CallStackTree ctrl_call_stack_tree(Access *access, U64 endt_us) { CTRL_CallStackTree result = {&ctrl_call_stack_tree_node_nil}; { AC_Artifact artifact = ac_artifact_from_key(access, str8_zero(), ctrl_call_stack_tree_artifact_create, ctrl_call_stack_tree_artifact_destroy, endt_us); if(artifact.u64[1] != 0) { MemoryCopyStruct(&result, (CTRL_CallStackTree *)artifact.u64[1]); } } return result; } ================================================ FILE: src/ctrl/ctrl_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CTRL_CORE_H #define CTRL_CORE_H //////////////////////////////// //~ rjf: ID Types typedef U64 CTRL_MsgID; typedef U64 CTRL_MachineID; #define CTRL_MachineID_Local (1) //////////////////////////////// //~ rjf: User Breakpoint Types typedef U32 CTRL_UserBreakpointFlags; enum { CTRL_UserBreakpointFlag_BreakOnWrite = (1<<0), CTRL_UserBreakpointFlag_BreakOnRead = (1<<1), CTRL_UserBreakpointFlag_BreakOnExecute = (1<<2), }; typedef enum CTRL_UserBreakpointKind { CTRL_UserBreakpointKind_Null, CTRL_UserBreakpointKind_FileNameAndLineColNumber, CTRL_UserBreakpointKind_Expression, CTRL_UserBreakpointKind_COUNT } CTRL_UserBreakpointKind; typedef struct CTRL_UserBreakpoint CTRL_UserBreakpoint; struct CTRL_UserBreakpoint { CTRL_UserBreakpointKind kind; CTRL_UserBreakpointFlags flags; U64 id; String8 string; TxtPt pt; U64 size; String8 condition; }; typedef struct CTRL_UserBreakpointNode CTRL_UserBreakpointNode; struct CTRL_UserBreakpointNode { CTRL_UserBreakpointNode *next; CTRL_UserBreakpoint v; }; typedef struct CTRL_UserBreakpointList CTRL_UserBreakpointList; struct CTRL_UserBreakpointList { CTRL_UserBreakpointNode *first; CTRL_UserBreakpointNode *last; U64 count; }; //////////////////////////////// //~ rjf: Entity Handle Types typedef struct CTRL_Handle CTRL_Handle; struct CTRL_Handle { CTRL_MachineID machine_id; DMN_Handle dmn_handle; }; typedef struct CTRL_HandleNode CTRL_HandleNode; struct CTRL_HandleNode { CTRL_HandleNode *next; CTRL_Handle v; }; typedef struct CTRL_HandleList CTRL_HandleList; struct CTRL_HandleList { CTRL_HandleNode *first; CTRL_HandleNode *last; U64 count; }; typedef struct CTRL_HandleArray CTRL_HandleArray; struct CTRL_HandleArray { CTRL_Handle *v; U64 count; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/ctrl.meta.h" //////////////////////////////// //~ rjf: Entity Types typedef struct CTRL_Entity CTRL_Entity; struct CTRL_Entity { CTRL_Entity *first; CTRL_Entity *last; CTRL_Entity *next; CTRL_Entity *prev; CTRL_Entity *parent; CTRL_EntityKind kind; Arch arch; B32 is_frozen; B32 is_soloed; U32 rgba; CTRL_Handle handle; U64 id; Rng1U64 vaddr_range; U64 stack_base; U64 timestamp; CTRL_UserBreakpointFlags bp_flags; String8 string; }; typedef struct CTRL_EntityNode CTRL_EntityNode; struct CTRL_EntityNode { CTRL_EntityNode *next; CTRL_Entity *v; }; typedef struct CTRL_EntityList CTRL_EntityList; struct CTRL_EntityList { CTRL_EntityNode *first; CTRL_EntityNode *last; U64 count; }; typedef struct CTRL_EntityArray CTRL_EntityArray; struct CTRL_EntityArray { CTRL_Entity **v; U64 count; }; typedef struct CTRL_EntityRec CTRL_EntityRec; struct CTRL_EntityRec { CTRL_Entity *next; S32 push_count; S64 pop_count; }; typedef struct CTRL_EntityHashNode CTRL_EntityHashNode; struct CTRL_EntityHashNode { CTRL_EntityHashNode *next; CTRL_EntityHashNode *prev; CTRL_Entity *entity; }; typedef struct CTRL_EntityHashSlot CTRL_EntityHashSlot; struct CTRL_EntityHashSlot { CTRL_EntityHashNode *first; CTRL_EntityHashNode *last; }; typedef struct CTRL_EntityStringChunkNode CTRL_EntityStringChunkNode; struct CTRL_EntityStringChunkNode { CTRL_EntityStringChunkNode *next; U64 size; }; read_only global U64 ctrl_entity_string_bucket_chunk_sizes[] = { 16, 64, 256, 1024, 4096, 16384, 65536, 0xffffffffffffffffull, }; typedef struct CTRL_EntityCtx CTRL_EntityCtx; struct CTRL_EntityCtx { CTRL_Entity *root; U64 hash_slots_count; CTRL_EntityHashSlot *hash_slots; U64 entity_kind_counts[CTRL_EntityKind_COUNT]; U64 entity_kind_alloc_gens[CTRL_EntityKind_COUNT]; }; typedef struct CTRL_EntityCtxRWStore CTRL_EntityCtxRWStore; struct CTRL_EntityCtxRWStore { Arena *arena; CTRL_EntityCtx ctx; CTRL_Entity *free; CTRL_EntityHashNode *hash_node_free; CTRL_EntityStringChunkNode *free_string_chunks[ArrayCount(ctrl_entity_string_bucket_chunk_sizes)]; }; typedef struct CTRL_EntityCtxLookupAccel CTRL_EntityCtxLookupAccel; struct CTRL_EntityCtxLookupAccel { Arena *arena; Arena *entity_kind_arrays_arenas[CTRL_EntityKind_COUNT]; CTRL_EntityArray entity_kind_arrays[CTRL_EntityKind_COUNT]; U64 entity_kind_arrays_gens[CTRL_EntityKind_COUNT]; }; //////////////////////////////// //~ rjf: Unwind Types typedef U32 CTRL_UnwindFlags; enum { CTRL_UnwindFlag_Error = (1<<0), CTRL_UnwindFlag_Stale = (1<<1), }; typedef struct CTRL_UnwindStepResult CTRL_UnwindStepResult; struct CTRL_UnwindStepResult { CTRL_UnwindFlags flags; }; typedef struct CTRL_UnwindFrame CTRL_UnwindFrame; struct CTRL_UnwindFrame { void *regs; }; typedef struct CTRL_UnwindFrameNode CTRL_UnwindFrameNode; struct CTRL_UnwindFrameNode { CTRL_UnwindFrameNode *next; CTRL_UnwindFrameNode *prev; CTRL_UnwindFrame v; }; typedef struct CTRL_UnwindFrameArray CTRL_UnwindFrameArray; struct CTRL_UnwindFrameArray { CTRL_UnwindFrame *v; U64 count; }; typedef struct CTRL_Unwind CTRL_Unwind; struct CTRL_Unwind { CTRL_UnwindFrameArray frames; CTRL_UnwindFlags flags; }; //////////////////////////////// //~ rjf: Call Stack Types typedef struct CTRL_CallStackFrame CTRL_CallStackFrame; struct CTRL_CallStackFrame { U64 unwind_count; U64 inline_depth; void *regs; }; typedef struct CTRL_CallStack CTRL_CallStack; struct CTRL_CallStack { CTRL_CallStackFrame *frames; U64 frames_count; CTRL_CallStackFrame **concrete_frames; U64 concrete_frames_count; }; //////////////////////////////// //~ rjf: Call Stack Tree Types typedef struct CTRL_CallStackTreeNode CTRL_CallStackTreeNode; struct CTRL_CallStackTreeNode { CTRL_CallStackTreeNode *hash_next; CTRL_CallStackTreeNode *first; CTRL_CallStackTreeNode *last; CTRL_CallStackTreeNode *next; CTRL_CallStackTreeNode *parent; U64 child_count; U64 id; CTRL_Handle process; U64 vaddr; U64 depth; CTRL_HandleList threads; U64 all_descendant_threads_count; }; typedef struct CTRL_CallStackTree CTRL_CallStackTree; struct CTRL_CallStackTree { CTRL_CallStackTreeNode *root; U64 slots_count; CTRL_CallStackTreeNode **slots; }; //////////////////////////////// //~ rjf: Trap Types typedef U32 CTRL_TrapFlags; enum { CTRL_TrapFlag_IgnoreStackPointerCheck = (1<<0), CTRL_TrapFlag_SingleStepAfterHit = (1<<1), CTRL_TrapFlag_SaveStackPointer = (1<<2), CTRL_TrapFlag_BeginSpoofMode = (1<<3), CTRL_TrapFlag_EndStepping = (1<<4), }; typedef struct CTRL_Trap CTRL_Trap; struct CTRL_Trap { CTRL_TrapFlags flags; U64 vaddr; }; typedef struct CTRL_TrapNode CTRL_TrapNode; struct CTRL_TrapNode { CTRL_TrapNode *next; CTRL_Trap v; }; typedef struct CTRL_TrapList CTRL_TrapList; struct CTRL_TrapList { CTRL_TrapNode *first; CTRL_TrapNode *last; U64 count; }; typedef struct CTRL_Spoof CTRL_Spoof; struct CTRL_Spoof { DMN_Handle process; DMN_Handle thread; U64 vaddr; U64 new_ip_value; }; //////////////////////////////// //~ rjf: Evaluation Spaces typedef U64 CTRL_EvalSpaceKind; enum { CTRL_EvalSpaceKind_Entity = E_SpaceKind_FirstUserDefined, CTRL_EvalSpaceKind_FirstUserDefined, }; //////////////////////////////// //~ rjf: Message Types typedef enum CTRL_MsgKind { CTRL_MsgKind_Null, CTRL_MsgKind_Launch, CTRL_MsgKind_Attach, CTRL_MsgKind_Kill, CTRL_MsgKind_KillAll, CTRL_MsgKind_Detach, CTRL_MsgKind_Run, CTRL_MsgKind_SingleStep, CTRL_MsgKind_SetUserEntryPoints, CTRL_MsgKind_SetModuleDebugInfoPath, CTRL_MsgKind_FreezeThread, CTRL_MsgKind_ThawThread, CTRL_MsgKind_COUNT, } CTRL_MsgKind; typedef U32 CTRL_RunFlags; enum { CTRL_RunFlag_StopOnEntryPoint = (1<<0), }; typedef struct CTRL_Msg CTRL_Msg; struct CTRL_Msg { CTRL_MsgKind kind; CTRL_RunFlags run_flags; CTRL_MsgID msg_id; CTRL_Handle entity; CTRL_Handle parent; U32 entity_id; U32 exit_code; B32 env_inherit; B32 debug_subprocesses; U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]; String8 path; String8List entry_points; String8List cmd_line_string_list; String8List env_string_list; String8 stdout_path; String8 stderr_path; String8 stdin_path; CTRL_TrapList traps; CTRL_UserBreakpointList user_bps; }; typedef struct CTRL_MsgNode CTRL_MsgNode; struct CTRL_MsgNode { CTRL_MsgNode *next; CTRL_Msg v; }; typedef struct CTRL_MsgList CTRL_MsgList; struct CTRL_MsgList { CTRL_MsgNode *first; CTRL_MsgNode *last; U64 count; }; //////////////////////////////// //~ rjf: Event Types typedef enum CTRL_EventKind { CTRL_EventKind_Null, CTRL_EventKind_Error, //- rjf: starts/stops CTRL_EventKind_Started, CTRL_EventKind_Stopped, //- rjf: entity creation/deletion CTRL_EventKind_NewProc, CTRL_EventKind_NewThread, CTRL_EventKind_NewModule, CTRL_EventKind_EndProc, CTRL_EventKind_EndThread, CTRL_EventKind_EndModule, //- rjf: thread freeze state changes CTRL_EventKind_ThreadFrozen, CTRL_EventKind_ThreadThawed, //- rjf: debug info changes CTRL_EventKind_ModuleDebugInfoPathChange, //- rjf: debug strings / decorations / markup CTRL_EventKind_DebugString, CTRL_EventKind_ThreadName, CTRL_EventKind_ThreadColor, CTRL_EventKind_SetBreakpoint, CTRL_EventKind_UnsetBreakpoint, CTRL_EventKind_SetVAddrRangeNote, //- rjf: memory CTRL_EventKind_MemReserve, CTRL_EventKind_MemCommit, CTRL_EventKind_MemDecommit, CTRL_EventKind_MemRelease, CTRL_EventKind_COUNT } CTRL_EventKind; typedef enum CTRL_EventCause { CTRL_EventCause_Null, CTRL_EventCause_Error, CTRL_EventCause_Finished, CTRL_EventCause_EntryPoint, CTRL_EventCause_UserBreakpoint, CTRL_EventCause_InterruptedByTrap, CTRL_EventCause_InterruptedByException, CTRL_EventCause_InterruptedByHalt, CTRL_EventCause_COUNT } CTRL_EventCause; typedef enum CTRL_ExceptionKind { CTRL_ExceptionKind_Null, CTRL_ExceptionKind_MemoryRead, CTRL_ExceptionKind_MemoryWrite, CTRL_ExceptionKind_MemoryExecute, CTRL_ExceptionKind_CppThrow, CTRL_ExceptionKind_COUNT } CTRL_ExceptionKind; typedef struct CTRL_Event CTRL_Event; struct CTRL_Event { CTRL_EventKind kind; CTRL_EventCause cause; CTRL_ExceptionKind exception_kind; CTRL_MsgID msg_id; CTRL_Handle entity; CTRL_Handle parent; Arch arch; U64 u64_code; U32 entity_id; Rng1U64 vaddr_rng; U64 rip_vaddr; U64 stack_base; U64 tls_root; U64 timestamp; U32 exception_code; U32 rgba; CTRL_UserBreakpointFlags bp_flags; String8 string; }; typedef struct CTRL_EventNode CTRL_EventNode; struct CTRL_EventNode { CTRL_EventNode *next; CTRL_Event v; }; typedef struct CTRL_EventList CTRL_EventList; struct CTRL_EventList { CTRL_EventNode *first; CTRL_EventNode *last; U64 count; }; //////////////////////////////// //~ rjf: Process Memory Types typedef struct CTRL_ProcessMemorySlice CTRL_ProcessMemorySlice; struct CTRL_ProcessMemorySlice { String8 data; U64 *byte_bad_flags; U64 *byte_changed_flags; B32 stale; B32 any_byte_bad; B32 any_byte_changed; }; //////////////////////////////// //~ rjf: Thread Register Cache Types typedef struct CTRL_ThreadRegCacheNode CTRL_ThreadRegCacheNode; struct CTRL_ThreadRegCacheNode { CTRL_ThreadRegCacheNode *next; CTRL_ThreadRegCacheNode *prev; CTRL_Handle handle; U64 block_size; void *block; U64 reg_gen; }; typedef struct CTRL_ThreadRegCacheSlot CTRL_ThreadRegCacheSlot; struct CTRL_ThreadRegCacheSlot { CTRL_ThreadRegCacheNode *first; CTRL_ThreadRegCacheNode *last; }; typedef struct CTRL_ThreadRegCacheStripe CTRL_ThreadRegCacheStripe; struct CTRL_ThreadRegCacheStripe { Arena *arena; RWMutex rw_mutex; }; typedef struct CTRL_ThreadRegCache CTRL_ThreadRegCache; struct CTRL_ThreadRegCache { U64 slots_count; CTRL_ThreadRegCacheSlot *slots; U64 stripes_count; CTRL_ThreadRegCacheStripe *stripes; }; //////////////////////////////// //~ rjf: Module Image Info Cache Types typedef struct CTRL_ModuleImageInfoCacheNode CTRL_ModuleImageInfoCacheNode; struct CTRL_ModuleImageInfoCacheNode { CTRL_ModuleImageInfoCacheNode *next; CTRL_ModuleImageInfoCacheNode *prev; CTRL_Handle module; Arena *arena; PE_IntelPdata *pdatas; U64 pdatas_count; U64 cfi_rebase; B32 is_unwind_eh; String8 dwarf_unwind_data; EH_FrameHdr eh_frame_hdr; EH_PtrCtx eh_ptr_ctx; U64 entry_point_voff; Rng1U64 tls_vaddr_range; String8 initial_debug_info_path; Rng1U64 raddbg_section_voff_range; String8 raddbg_data; }; typedef struct CTRL_ModuleImageInfoCacheSlot CTRL_ModuleImageInfoCacheSlot; struct CTRL_ModuleImageInfoCacheSlot { CTRL_ModuleImageInfoCacheNode *first; CTRL_ModuleImageInfoCacheNode *last; }; typedef struct CTRL_ModuleImageInfoCacheStripe CTRL_ModuleImageInfoCacheStripe; struct CTRL_ModuleImageInfoCacheStripe { Arena *arena; RWMutex rw_mutex; }; typedef struct CTRL_ModuleImageInfoCache CTRL_ModuleImageInfoCache; struct CTRL_ModuleImageInfoCache { U64 slots_count; CTRL_ModuleImageInfoCacheSlot *slots; U64 stripes_count; CTRL_ModuleImageInfoCacheStripe *stripes; }; //////////////////////////////// //~ rjf: Touched Debug Info Directory Cache typedef struct CTRL_DbgDirNode CTRL_DbgDirNode; struct CTRL_DbgDirNode { CTRL_DbgDirNode *first; CTRL_DbgDirNode *last; CTRL_DbgDirNode *next; CTRL_DbgDirNode *prev; CTRL_DbgDirNode *parent; String8 name; U64 search_count; U64 child_count; U64 module_direct_count; }; //////////////////////////////// //~ rjf: Control Thread Evaluation Scopes typedef struct CTRL_EvalScope CTRL_EvalScope; struct CTRL_EvalScope { Access *access; E_BaseCtx base_ctx; E_IRCtx ir_ctx; E_InterpretCtx interpret_ctx; }; //////////////////////////////// //~ rjf: Module Requirement Cache Types typedef struct CTRL_ModuleReqCacheNode CTRL_ModuleReqCacheNode; struct CTRL_ModuleReqCacheNode { CTRL_ModuleReqCacheNode *next; CTRL_Handle module; B32 required; }; //////////////////////////////// //~ rjf: Wakeup Hook Function Types #define CTRL_WAKEUP_FUNCTION_DEF(name) void name(void) typedef CTRL_WAKEUP_FUNCTION_DEF(CTRL_WakeupFunctionType); //////////////////////////////// //~ rjf: Main State Types typedef struct CTRL_State CTRL_State; struct CTRL_State { Arena *arena; CTRL_WakeupFunctionType *wakeup_hook; // rjf: name -> register/alias hash tables for eval E_String2NumMap arch_string2reg_tables[Arch_COUNT]; E_String2NumMap arch_string2alias_tables[Arch_COUNT]; // rjf: caches CTRL_ThreadRegCache thread_reg_cache; CTRL_ModuleImageInfoCache module_image_info_cache; // rjf: generations U64 run_gen; U64 mem_gen; U64 reg_gen; // rjf: user -> ctrl msg ring buffer U64 u2c_ring_size; U8 *u2c_ring_base; U64 u2c_ring_write_pos; U64 u2c_ring_read_pos; Mutex u2c_ring_mutex; CondVar u2c_ring_cv; // rjf: ctrl -> user event ring buffer U64 c2u_ring_size; U64 c2u_ring_max_string_size; U8 *c2u_ring_base; U64 c2u_ring_write_pos; U64 c2u_ring_read_pos; Mutex c2u_ring_mutex; CondVar c2u_ring_cv; // rjf: ctrl thread state U64 ctrl_thread_run_state; String8 ctrl_thread_log_path; Thread ctrl_thread; Log *ctrl_thread_log; RWMutex ctrl_thread_entity_ctx_rw_mutex; CTRL_EntityCtxRWStore *ctrl_thread_entity_store; E_Cache *ctrl_thread_eval_cache; Arena *ctrl_thread_msg_process_arena; Arena *dmn_event_arena; DMN_EventNode *first_dmn_event_node; DMN_EventNode *last_dmn_event_node; DMN_EventNode *free_dmn_event_node; Arena *user_entry_point_arena; String8List user_entry_points; U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]; U64 process_counter; Arena *dbg_dir_arena; CTRL_DbgDirNode *dbg_dir_root; U64 module_req_cache_slots_count; CTRL_ModuleReqCacheNode **module_req_cache_slots; String8List msg_user_bp_touched_files; String8List msg_user_bp_touched_symbols; }; //////////////////////////////// //~ rjf: Globals global CTRL_State *ctrl_state = 0; read_only global CTRL_Entity ctrl_entity_nil = { &ctrl_entity_nil, &ctrl_entity_nil, &ctrl_entity_nil, &ctrl_entity_nil, &ctrl_entity_nil, }; read_only global CTRL_CallStackTreeNode ctrl_call_stack_tree_node_nil = { 0, &ctrl_call_stack_tree_node_nil, &ctrl_call_stack_tree_node_nil, &ctrl_call_stack_tree_node_nil, &ctrl_call_stack_tree_node_nil, }; thread_static CTRL_EntityCtxLookupAccel *ctrl_entity_ctx_lookup_accel = 0; //////////////////////////////// //~ rjf: Logging Markup #define CTRL_CtrlThreadLogScope DeferLoop(log_scope_begin(), ctrl_thread__end_and_flush_log()) //////////////////////////////// //~ rjf: Basic Type Functions internal U64 ctrl_hash_from_string(String8 string); internal U64 ctrl_hash_from_handle(CTRL_Handle handle); internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind); internal CTRL_ExceptionKind ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind); internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind); internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind); internal CTRL_EntityKind ctrl_entity_kind_from_string(String8 string); internal DMN_TrapFlags ctrl_dmn_trap_flags_from_user_breakpoint_flags(CTRL_UserBreakpointFlags flags); internal CTRL_UserBreakpointFlags ctrl_user_breakpoint_flags_from_dmn_trap_flags(DMN_TrapFlags flags); //////////////////////////////// //~ rjf: Handle Type Functions internal CTRL_Handle ctrl_handle_zero(void); internal CTRL_Handle ctrl_handle_make(CTRL_MachineID machine_id, DMN_Handle dmn_handle); internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b); internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair); internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src); internal CTRL_HandleArray ctrl_handle_array_from_list(Arena *arena, CTRL_HandleList *src); internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle); internal CTRL_Handle ctrl_handle_from_string(String8 string); //////////////////////////////// //~ rjf: Trap Type Functions internal void ctrl_trap_list_push(Arena *arena, CTRL_TrapList *list, CTRL_Trap *trap); internal CTRL_TrapList ctrl_trap_list_copy(Arena *arena, CTRL_TrapList *src); //////////////////////////////// //~ rjf: User Breakpoint Type Functions internal void ctrl_user_breakpoint_list_push(Arena *arena, CTRL_UserBreakpointList *list, CTRL_UserBreakpoint *bp); internal CTRL_UserBreakpointList ctrl_user_breakpoint_list_copy(Arena *arena, CTRL_UserBreakpointList *src); //////////////////////////////// //~ rjf: Message Type Functions //- rjf: deep copying internal void ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src); //- rjf: list building internal CTRL_Msg *ctrl_msg_list_push(Arena *arena, CTRL_MsgList *list); internal CTRL_MsgList ctrl_msg_list_deep_copy(Arena *arena, CTRL_MsgList *src); internal void ctrl_msg_list_concat_in_place(CTRL_MsgList *dst, CTRL_MsgList *src); //- rjf: serialization internal String8 ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs); internal CTRL_MsgList ctrl_msg_list_from_serialized_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Event Type Functions //- rjf: list building internal CTRL_Event *ctrl_event_list_push(Arena *arena, CTRL_EventList *list); internal void ctrl_event_list_concat_in_place(CTRL_EventList *dst, CTRL_EventList *to_push); //- rjf: serialization internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event, U64 max); internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Entity Type Functions //- rjf: entity list data structures internal void ctrl_entity_list_push(Arena *arena, CTRL_EntityList *list, CTRL_Entity *entity); internal CTRL_EntityList ctrl_entity_list_from_handle_list(Arena *arena, CTRL_EntityCtx *ctx, CTRL_HandleList *list); #define ctrl_entity_list_first(list) ((list)->first ? (list)->first->v : &ctrl_entity_nil) //- rjf: entity array data structure internal CTRL_EntityArray ctrl_entity_array_from_list(Arena *arena, CTRL_EntityList *list); #define ctrl_entity_array_first(array) ((array)->count != 0 ? (array)->v[0] : &ctrl_entity_nil) //- rjf: entity context (entity group read-only) functions internal CTRL_Entity *ctrl_entity_from_handle(CTRL_EntityCtx *ctx, CTRL_Handle handle); internal CTRL_Entity *ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind); internal CTRL_Entity *ctrl_entity_ancestor_from_kind(CTRL_Entity *entity, CTRL_EntityKind kind); internal CTRL_Entity *ctrl_process_from_entity(CTRL_Entity *entity); internal CTRL_Entity *ctrl_module_from_process_vaddr(CTRL_Entity *process, U64 vaddr); internal DI_Key ctrl_dbgi_key_from_module(CTRL_Entity *module); internal CTRL_Entity *ctrl_module_from_thread_candidates(CTRL_EntityCtx *ctx, CTRL_Entity *thread, CTRL_EntityList *candidates); internal U64 ctrl_vaddr_from_voff(CTRL_Entity *module, U64 voff); internal U64 ctrl_voff_from_vaddr(CTRL_Entity *module, U64 vaddr); internal Rng1U64 ctrl_vaddr_range_from_voff_range(CTRL_Entity *module, Rng1U64 voff_range); internal Rng1U64 ctrl_voff_range_from_vaddr_range(CTRL_Entity *module, Rng1U64 vaddr_range); internal B32 ctrl_entity_tree_is_frozen(CTRL_Entity *root); //- rjf: entity tree iteration internal CTRL_EntityRec ctrl_entity_rec_depth_first(CTRL_Entity *entity, CTRL_Entity *subtree_root, U64 sib_off, U64 child_off); #define ctrl_entity_rec_depth_first_pre(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, next), OffsetOf(CTRL_Entity, first)) #define ctrl_entity_rec_depth_first_post(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, prev), OffsetOf(CTRL_Entity, last)) //- rjf: entity ctx r/w store state functions internal CTRL_EntityCtxRWStore *ctrl_entity_ctx_rw_store_alloc(void); internal void ctrl_entity_ctx_rw_store_release(CTRL_EntityCtxRWStore *store); //- rjf: string allocation/deletion internal U64 ctrl_name_bucket_num_from_string_size(U64 size); internal String8 ctrl_entity_string_alloc(CTRL_EntityCtxRWStore *store, String8 string); internal void ctrl_entity_string_release(CTRL_EntityCtxRWStore *store, String8 string); //- rjf: entity construction/deletion internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityCtxRWStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Arch arch, CTRL_Handle handle, U64 id); internal void ctrl_entity_release(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity); //- rjf: entity equipment internal void ctrl_entity_equip_string(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity, String8 string); //- rjf: accelerated entity context lookups internal CTRL_EntityCtxLookupAccel *ctrl_thread_entity_ctx_lookup_accel(void); internal CTRL_EntityArray ctrl_entity_array_from_kind(CTRL_EntityCtx *ctx, CTRL_EntityKind kind); internal CTRL_EntityList ctrl_modules_from_dbgi_key(Arena *arena, CTRL_EntityCtx *ctx, DI_Key dbgi_key); internal CTRL_Entity *ctrl_thread_from_id(CTRL_EntityCtx *ctx, U64 id); //- rjf: applying events to entity caches internal void ctrl_entity_store_apply_events(CTRL_EntityCtxRWStore *store, CTRL_EventList *list); //////////////////////////////// //~ rjf: Main Layer Initialization internal void ctrl_init(void); //////////////////////////////// //~ rjf: Wakeup Callback Registration internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook); //////////////////////////////// //~ rjf: Thread Register Functions //- rjf: thread register cache reading internal void *ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle handle); internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle); internal U64 ctrl_rip_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle); internal U64 ctrl_rsp_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle); //- rjf: thread register writing internal B32 ctrl_thread_write_reg_block(CTRL_Handle thread, void *block); //////////////////////////////// //~ rjf: Module Image Info Functions //- rjf: cache lookups internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_Handle module_handle, U64 voff); internal U64 ctrl_entry_point_voff_from_module(CTRL_Handle module_handle); internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_Handle module_handle); internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle); internal String8 ctrl_raddbg_data_from_module(Arena *arena, CTRL_Handle module_handle); //////////////////////////////// //~ Process Info Functions internal Arch ctrl_arch_from_process_handle(CTRL_Handle process_handle); //////////////////////////////// //~ rjf: Unwinding Functions //- rjf: unwind deep copier internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Arch arch, CTRL_Unwind *src); //- DWARF internal CTRL_UnwindStepResult ctrl_unwind_step__dwarf(CTRL_Handle process_handle, CTRL_Handle module_handle, Arch arch, void *regs, U64 endt_us); //- rjf: [x64] internal REGS_Reg64 *ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg); internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_Handle process_handle, CTRL_Handle module_handle, U64 module_base_vaddr, REGS_RegBlockX64 *regs, U64 endt_us); //- rjf: abstracted unwind step internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_Handle process, CTRL_Handle module, U64 module_base_vaddr, Arch arch, void *reg_block, U64 endt_us); //- rjf: abstracted full unwind internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle thread, U64 endt_us); //////////////////////////////// //~ rjf: Call Stack Building Functions internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, CTRL_Entity *process, CTRL_Unwind *base_unwind); internal CTRL_CallStackFrame *ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth); //////////////////////////////// //~ rjf: Halting All Attached Processes internal void ctrl_halt(void); //////////////////////////////// //~ rjf: Shared Accessor Functions //- rjf: generation counters internal U64 ctrl_run_gen(void); internal U64 ctrl_mem_gen(void); internal U64 ctrl_reg_gen(void); //- rjf: name -> register/alias hash tables, for eval internal E_String2NumMap *ctrl_string2reg_from_arch(Arch arch); internal E_String2NumMap *ctrl_string2alias_from_arch(Arch arch); //////////////////////////////// //~ rjf: Control-Thread Functions //- rjf: user -> control thread communication internal B32 ctrl_u2c_push_msgs(CTRL_MsgList *msgs, U64 endt_us); internal CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena); //- rjf: control -> user thread communication internal void ctrl_c2u_push_events(CTRL_EventList *events); internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena); //- rjf: entry point internal void ctrl_thread__entry_point(void *p); //- rjf: breakpoint resolution internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out); internal void ctrl_thread__append_program_defined_bp_traps(Arena *arena, CTRL_Entity *bp, DMN_TrapChunkList *traps_out); //- rjf: module lifetime open/close work internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path, Rng1U64 elf_phdr_vrange, U64 elf_phdr_entsize); internal void ctrl_thread__module_close(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range); //- rjf: attached process running/event gathering internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof); //- rjf: eval helpers internal U64 ctrl_eval_space_gen(E_Space space); internal B32 ctrl_eval_space_read(E_Space space, void *out, Rng1U64 vaddr_range); //- rjf: control thread eval scopes internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, CTRL_Entity *thread); internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope); //- rjf: log flusher internal void ctrl_thread__end_and_flush_log(void); //- rjf: msg kind implementations internal void ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__attach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__kill(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__kill_all(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__detach(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg); //////////////////////////////// //~ rjf: Process Memory Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_memory_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void ctrl_memory_artifact_destroy(AC_Artifact artifact); internal C_Key ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, B32 wait_for_fresh, U64 endt_us, B32 *out_is_stale); //- rjf: process memory reading helpers internal CTRL_ProcessMemorySlice ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, B32 wait_for_fresh, U64 endt_us); internal B32 ctrl_process_memory_read(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us); #define ctrl_process_memory_read_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_process_memory_read((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us)) //- rjf: process memory writing internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src); //////////////////////////////// //~ rjf: Call Stack Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void ctrl_call_stack_artifact_destroy(AC_Artifact artifact); internal CTRL_CallStack ctrl_call_stack_from_thread(Access *access, CTRL_Handle thread_handle, B32 high_priority, U64 endt_us); //////////////////////////////// //~ rjf: Call Stack Tree Artifact Cache Hooks / Lookups internal AC_Artifact ctrl_call_stack_tree_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void ctrl_call_stack_tree_artifact_destroy(AC_Artifact artifact); internal CTRL_CallStackTree ctrl_call_stack_tree(Access *access, U64 endt_us); #endif // CTRL_CORE_H ================================================ FILE: src/ctrl/ctrl_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0x969696ff #include "ctrl_core.c" ================================================ FILE: src/ctrl/ctrl_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CTRL_INC_H #define CTRL_INC_H //////////////////////////////// //~ NOTE(rjf): Control Layer Overview (2023/8/29) // // This layer's purpose is to provide access to the asynchronously-running, low // level parts of a debugger, running on the debugger client. This primarily // consists of process control, using the Demon layer (the lower level // abstraction layer for process control, across multiple OSes), but including // higher-level concepts, like stepping, breakpoint resolution, conditional // breakpoint evaluation, and so on. Right now, this just includes process // control *local to the debugger client machine*. But in the future, this can // also include communication to multiple target machines, all running their // own process controller, using the Demon layer. // // This part of a debugger must run asynchronously to prevent blocking the UI - // ideally our debugger is designed such that, if targets are running, the // debugger frontend is still usable for a variety of purposes. So, in short, // the asynchronously-running "control thread", implemented by this layer, is // tasked with communicating with a separately executing "user thread". This // communication happens in two directions - `user -> ctrl`, and the reverse, // `ctrl -> user`. // // In the case of `user -> ctrl` communication, this is done with a ring buffer // of "messages" (`CTRL_Msg`), pushed via `ctrl_u2c_push_msgs`. These messages // include commands like: launching targets, attaching to targets, killing // targets, detaching from targets, stepping/running, or single stepping. // // In the case of `ctrl -> user` communication, this is done with a ring buffer // of "events" (`CTRL_Event`), popped via `ctrl_c2u_pop_events`. These events // include information about what happened during the execution of targets - // including: process/module/thread creation, process/module/thread deletion, // debug strings, thread name events, memory allocation events, and stop events // (where stops can be caused by: user breakpoints, traps set for stepping, // exceptions, halts, or errors). // // The various stepping algorithms are implemented with two concepts: (a) the // "trap net", and (b) "spoofs". // // A "trap net" is a term which refers to a set of addresses paired with a set // of behavioral flags. Before targets run, trap instructions are written to // these addresses. After targets stop, these addresses are reset to their // original bytes. These trap instructions cause the debugger's targets to // stop executing, and based on which behavioral flags are associated with // the instruction causing the stop, the control thread may adjust parameters // used for running, then continue execution, or it will not resume target // execution, and will report stopped events. These behavioral flags can // include: single-stepping the stopped thread to execute the instruction at // the trap location, saving a stack pointer "check value" (where this check // value is compared against when making decisions about whether to continue // running or not), and so on. It's complicated to unpack why exactly these // behaviors are useful, but the TL;DR of it is that they are used for a // variety of stepping behaviors. For example, when doing a "step into" step, // a `call` instruction can have a trap set at it, and will be marked with // a "single-step-after" trap flag, as well as the "end stepping" trap flag, // such that the step operation will complete after the `call` has executed. // // A "spoof" is a feature the control layer uses to detect when some thread // returns from a particular sub-callstack. This is useful when implementing // "step over" in functions that may be recursive. In short, unlike a trap, // which writes a trap instruction (like `int3`) into an instruction stream, // a spoof overwrites a *return address* on some thread's *stack*. This return // address is not a valid address for executing code -- it is simply a value // that the debugger can recognize, such that it is notified when the thread // returns from some level in a callstack. When the thread exits some function, // it will return to the "spoofed" address, and it will immediately hit an // exception, because the spoofed address will not be a valid address for // code execution. At that point, the debugger can move the thread back to // the pre-spoof return address, and resume execution. #include "ctrl_core.h" #endif // CTRL_INC_H ================================================ FILE: src/ctrl/generated/ctrl.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 ctrl_entity_kind_code_name_table[12] = { {0}, str8_lit_comp("root"), str8_lit_comp("machine"), str8_lit_comp("process"), str8_lit_comp("thread"), str8_lit_comp("module"), str8_lit_comp("entry_point"), str8_lit_comp("debug_info_path"), str8_lit_comp("pending_thread_name"), str8_lit_comp("pending_thread_color"), str8_lit_comp("breakpoint"), str8_lit_comp("address_range_annotation"), }; String8 ctrl_entity_kind_display_string_table[12] = { {0}, str8_lit_comp("Root"), str8_lit_comp("Machine"), str8_lit_comp("Process"), str8_lit_comp("Thread"), str8_lit_comp("Module"), str8_lit_comp("EntryPoint"), str8_lit_comp("DebugInfoPath"), str8_lit_comp("PendingThreadName"), str8_lit_comp("PendingThreadColor"), str8_lit_comp("Breakpoint"), str8_lit_comp("AddressRangeAnnotation"), }; U32 ctrl_exception_code_kind_code_table[38] = { 0, 0x40010005, 0x40010008, 0x40080201, 0x40080202, 0x0000071a, 0x80000002, 0xc0000005, 0xc0000006, 0xc0000008, 0xc0000017, 0xc000001d, 0xc0000025, 0xc0000026, 0xc000008c, 0xc000008d, 0xc000008e, 0xc000008f, 0xc0000090, 0xc0000091, 0xc0000092, 0xc0000093, 0xc0000094, 0xc0000095, 0xc0000096, 0xc00000fd, 0xc0000135, 0xc0000138, 0xc0000139, 0xc0000142, 0xc00002b4, 0xc00002b5, 0xc0000420, 0xc06d007e, 0xc06d007f, 0xe073616e, 0xe0736171, 0x0000087a, }; String8 ctrl_exception_code_kind_display_string_table[38] = { {0}, str8_lit_comp("(Win32) Control-C"), str8_lit_comp("(Win32) Control-Break"), str8_lit_comp("(Win32) WinRT Originate Error"), str8_lit_comp("(Win32) WinRT Transform Error"), str8_lit_comp("(Win32) RPC Call Cancelled"), str8_lit_comp("(Win32) Data Type Misalignment"), str8_lit_comp("(Win32) Access Violation"), str8_lit_comp("(Win32) In Page Error"), str8_lit_comp("(Win32) Invalid Handle Specified"), str8_lit_comp("(Win32) Not Enough Quota"), str8_lit_comp("(Win32) Illegal Instruction"), str8_lit_comp("(Win32) Cannot Continue From Exception"), str8_lit_comp("(Win32) Invalid Exception Disposition Returned By Handler"), str8_lit_comp("(Win32) Array Bounds Exceeded"), str8_lit_comp("(Win32) Floating-Point Denormal Operand"), str8_lit_comp("(Win32) Floating-Point Division By Zero"), str8_lit_comp("(Win32) Floating-Point Inexact Result"), str8_lit_comp("(Win32) Floating-Point Invalid Operation"), str8_lit_comp("(Win32) Floating-Point Overflow"), str8_lit_comp("(Win32) Floating-Point Stack Check"), str8_lit_comp("(Win32) Floating-Point Underflow"), str8_lit_comp("(Win32) Integer Division By Zero"), str8_lit_comp("(Win32) Integer Overflow"), str8_lit_comp("(Win32) Privileged Instruction"), str8_lit_comp("(Win32) Stack Overflow"), str8_lit_comp("(Win32) Unable To Locate DLL"), str8_lit_comp("(Win32) Ordinal Not Found"), str8_lit_comp("(Win32) Entry Point Not Found"), str8_lit_comp("(Win32) DLL Initialization Failed"), str8_lit_comp("(Win32) Floating Point SSE Multiple Faults"), str8_lit_comp("(Win32) Floating Point SSE Multiple Traps"), str8_lit_comp("(Win32) Assertion Failed"), str8_lit_comp("(Win32) Module Not Found"), str8_lit_comp("(Win32) Procedure Not Found"), str8_lit_comp("(Win32) Sanitizer Error Detected"), str8_lit_comp("(Win32) Sanitizer Raw Access Violation"), str8_lit_comp("(Win32) DirectX Debug Layer"), }; String8 ctrl_exception_code_kind_lowercase_code_string_table[38] = { {0}, str8_lit_comp("win32_ctrl_c"), str8_lit_comp("win32_ctrl_break"), str8_lit_comp("win32_win_rt_originate_error"), str8_lit_comp("win32_win_rt_transform_error"), str8_lit_comp("win32_rpc_call_cancelled"), str8_lit_comp("win32_datatype_misalignment"), str8_lit_comp("win32_access_violation"), str8_lit_comp("win32_in_page_error"), str8_lit_comp("win32_invalid_handle"), str8_lit_comp("win32_not_enough_quota"), str8_lit_comp("win32_illegal_instruction"), str8_lit_comp("win32_cannot_continue_exception"), str8_lit_comp("win32_invalid_exception_disposition"), str8_lit_comp("win32_array_bounds_exceeded"), str8_lit_comp("win32_floating_point_denormal_operand"), str8_lit_comp("win32_floating_point_division_by_zero"), str8_lit_comp("win32_floating_point_inexact_result"), str8_lit_comp("win32_floating_point_invalid_operation"), str8_lit_comp("win32_floating_point_overflow"), str8_lit_comp("win32_floating_point_stack_check"), str8_lit_comp("win32_floating_point_underflow"), str8_lit_comp("win32_integer_division_by_zero"), str8_lit_comp("win32_integer_overflow"), str8_lit_comp("win32_privileged_instruction"), str8_lit_comp("win32_stack_overflow"), str8_lit_comp("win32_unable_to_locate_dll"), str8_lit_comp("win32_ordinal_not_found"), str8_lit_comp("win32_entry_point_not_found"), str8_lit_comp("win32_dll_initialization_failed"), str8_lit_comp("win32_floating_point_sse_multiple_faults"), str8_lit_comp("win32_floating_point_sse_multiple_traps"), str8_lit_comp("win32_assertion_failed"), str8_lit_comp("win32_module_not_found"), str8_lit_comp("win32_procedure_not_found"), str8_lit_comp("win32_sanitizer_error_detected"), str8_lit_comp("win32_sanitizer_raw_access_violation"), str8_lit_comp("win32_directx_debug_layer"), }; B8 ctrl_exception_code_kind_default_enable_table[38] = { 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, }; C_LINKAGE_END ================================================ FILE: src/ctrl/generated/ctrl.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef CTRL_META_H #define CTRL_META_H typedef enum CTRL_EntityKind { CTRL_EntityKind_Null, CTRL_EntityKind_Root, CTRL_EntityKind_Machine, CTRL_EntityKind_Process, CTRL_EntityKind_Thread, CTRL_EntityKind_Module, CTRL_EntityKind_EntryPoint, CTRL_EntityKind_DebugInfoPath, CTRL_EntityKind_PendingThreadName, CTRL_EntityKind_PendingThreadColor, CTRL_EntityKind_Breakpoint, CTRL_EntityKind_AddressRangeAnnotation, CTRL_EntityKind_COUNT, } CTRL_EntityKind; typedef enum CTRL_ExceptionCodeKind { CTRL_ExceptionCodeKind_Null, CTRL_ExceptionCodeKind_Win32CtrlC, CTRL_ExceptionCodeKind_Win32CtrlBreak, CTRL_ExceptionCodeKind_Win32WinRTOriginateError, CTRL_ExceptionCodeKind_Win32WinRTTransformError, CTRL_ExceptionCodeKind_Win32RPCCallCancelled, CTRL_ExceptionCodeKind_Win32DatatypeMisalignment, CTRL_ExceptionCodeKind_Win32AccessViolation, CTRL_ExceptionCodeKind_Win32InPageError, CTRL_ExceptionCodeKind_Win32InvalidHandle, CTRL_ExceptionCodeKind_Win32NotEnoughQuota, CTRL_ExceptionCodeKind_Win32IllegalInstruction, CTRL_ExceptionCodeKind_Win32CannotContinueException, CTRL_ExceptionCodeKind_Win32InvalidExceptionDisposition, CTRL_ExceptionCodeKind_Win32ArrayBoundsExceeded, CTRL_ExceptionCodeKind_Win32FloatingPointDenormalOperand, CTRL_ExceptionCodeKind_Win32FloatingPointDivisionByZero, CTRL_ExceptionCodeKind_Win32FloatingPointInexactResult, CTRL_ExceptionCodeKind_Win32FloatingPointInvalidOperation, CTRL_ExceptionCodeKind_Win32FloatingPointOverflow, CTRL_ExceptionCodeKind_Win32FloatingPointStackCheck, CTRL_ExceptionCodeKind_Win32FloatingPointUnderflow, CTRL_ExceptionCodeKind_Win32IntegerDivisionByZero, CTRL_ExceptionCodeKind_Win32IntegerOverflow, CTRL_ExceptionCodeKind_Win32PrivilegedInstruction, CTRL_ExceptionCodeKind_Win32StackOverflow, CTRL_ExceptionCodeKind_Win32UnableToLocateDLL, CTRL_ExceptionCodeKind_Win32OrdinalNotFound, CTRL_ExceptionCodeKind_Win32EntryPointNotFound, CTRL_ExceptionCodeKind_Win32DLLInitializationFailed, CTRL_ExceptionCodeKind_Win32FloatingPointSSEMultipleFaults, CTRL_ExceptionCodeKind_Win32FloatingPointSSEMultipleTraps, CTRL_ExceptionCodeKind_Win32AssertionFailed, CTRL_ExceptionCodeKind_Win32ModuleNotFound, CTRL_ExceptionCodeKind_Win32ProcedureNotFound, CTRL_ExceptionCodeKind_Win32SanitizerErrorDetected, CTRL_ExceptionCodeKind_Win32SanitizerRawAccessViolation, CTRL_ExceptionCodeKind_Win32DirectXDebugLayer, CTRL_ExceptionCodeKind_COUNT, } CTRL_ExceptionCodeKind; C_LINKAGE_BEGIN extern String8 ctrl_entity_kind_code_name_table[12]; extern String8 ctrl_entity_kind_display_string_table[12]; extern U32 ctrl_exception_code_kind_code_table[38]; extern String8 ctrl_exception_code_kind_display_string_table[38]; extern String8 ctrl_exception_code_kind_lowercase_code_string_table[38]; extern B8 ctrl_exception_code_kind_default_enable_table[38]; C_LINKAGE_END #endif // CTRL_META_H ================================================ FILE: src/dbg_engine/dbg_engine.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Built-In Command Tables @table(name ui_vis ipc_docs_vis text_pt_vis text_rng_vis q_expr q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_floating q_required canonical_icon string display_name desc search_tags ctx_filter) // / | | | | | | \___ _________________________________/ | | | | | | // / | | | | | | \ / | | | | | | D_CmdTable: // | | | | | | | | | | | | | | { //- rjf: low-level target control operations {LaunchAndRun 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" "" } {LaunchAndStepInto 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 PlayStepForward "launch_and_step_into" "Launch and Step Into" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" "" } {Kill 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" "" } {KillAll 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" "" } {Detach 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" "" } {Continue 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" "" } {StepIntoInst 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" "" } {StepOverInst 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" "" } {StepIntoLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" "" } {StepOverLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" "" } {StepOut 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" "" } {Halt 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" "" } {SoftHaltRefresh 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" "" } {SetThreadIP 0 1 0 0 "" Vaddr null Nil Null 0 0 0 0 1 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" "" } //- rjf: high-level composite target control operations {RunToLine 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" "$text_pt," } {Run 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" "" } {Restart 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" "" } {StepInto 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" "" } {StepOver 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" "" } //- rjf: debug control context management operations {FreezeThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" "" } {ThawThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" "" } {FreezeProcess 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" "" } {ThawProcess 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" "" } {FreezeMachine 0 1 0 0 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" "" } {ThawMachine 0 1 0 0 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" "" } {FreezeLocalMachine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" "" } {ThawLocalMachine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" "" } {FreezeEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Unlocked "freeze_entity" "Freeze Entity" "Freezes an entity." "" "" } {ThawEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Locked "thaw_entity" "Thaw Entity" "Thaws an entity." "" "" } //- rjf: entity decoration {SetEntityColor 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" "" } {SetEntityName 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" "" } //- rjf: attaching {Attach 1 1 0 0 "query:unattached_processes" PID null Nil Null 0 0 0 0 0 1 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" "" } } @enum D_CmdKind: { Null, @expand(D_CmdTable, a) `$(a.name)`, COUNT, } //////////////////////////////// //~ rjf: Developer Toggles @table(name) D_DevToggleTable: { {always_refresh} {simulate_lag} {draw_ui_text_pos} {draw_ui_focus_debug} {draw_ui_box_heatmap} {eval_compiler_tooltips} {eval_watch_key_tooltips} {cmd_context_tooltips} {updating_indicator} } @gen { @expand(D_DevToggleTable a) `global B32 DEV_$(a.name) = 0;` } @gen { `struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =`; `{`; @expand(D_DevToggleTable a) `{&DEV_$(a.name), str8_lit_comp("$(a.name)")},` `};`; } ================================================ FILE: src/dbg_engine/dbg_engine_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0x4d9ae3ff //////////////////////////////// //~ rjf: Generated Code #include "dbg_engine/generated/dbg_engine.meta.c" //////////////////////////////// //~ rjf: Basic Helpers #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal U64 d_hash_from_seed_string(U64 seed, String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); return result; } internal U64 d_hash_from_string(String8 string) { return d_hash_from_seed_string(5381, string); } internal U64 d_hash_from_seed_string__case_insensitive(U64 seed, String8 string) { U64 result = seed; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + lower_from_char(string.str[i]); } return result; } internal U64 d_hash_from_string__case_insensitive(String8 string) { return d_hash_from_seed_string__case_insensitive(5381, string); } //////////////////////////////// //~ rjf: Breakpoints internal D_BreakpointArray d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src) { D_BreakpointArray dst = {0}; dst.count = src->count; dst.v = push_array(arena, D_Breakpoint, dst.count); MemoryCopy(dst.v, src->v, sizeof(dst.v[0])*dst.count); for(U64 idx = 0; idx < dst.count; idx += 1) { dst.v[idx].file_path = push_str8_copy(arena, dst.v[idx].file_path); dst.v[idx].vaddr_expr = push_str8_copy(arena, dst.v[idx].vaddr_expr); dst.v[idx].condition = push_str8_copy(arena, dst.v[idx].condition); } return dst; } //////////////////////////////// //~ rjf: Path Map Application internal String8List d_possible_path_overrides_from_maps_path(Arena *arena, D_PathMapArray *path_maps, String8 file_path) { // NOTE(rjf): This path, given some target file path, scans all file path map // overrides, and collects the set of file paths which could've redirected // to the target file path given the set of file path maps. // // For example, if I have a rule saying D:/devel/ maps to C:/devel/, and I // feed in C:/devel/foo/bar.txt, then this path will construct // D:/devel/foo/bar.txt, as a possible option. // // It will also preserve C:/devel/foo/bar.txt in the resultant list, so that // overrideless files still work through this path, and both redirected // files and non-redirected files can go through the same path. // String8List result = {0}; str8_list_push(arena, &result, file_path); Temp scratch = scratch_begin(&arena, 1); PathStyle pth_style = PathStyle_Relative; String8List pth_parts = path_normalized_list_from_string(scratch.arena, file_path, &pth_style); { for(U64 idx = 0; idx < path_maps->count; idx += 1) { //- rjf: unpack link D_PathMap *map = &path_maps->v[idx]; PathStyle src_style = PathStyle_Relative; PathStyle dst_style = PathStyle_Relative; String8List src_parts = path_normalized_list_from_string(scratch.arena, map->src, &src_style); String8List dst_parts = path_normalized_list_from_string(scratch.arena, map->dst, &dst_style); //- rjf: determine if this link can possibly redirect to the target file path B32 dst_redirects_to_pth = 0; String8Node *non_redirected_pth_first = 0; if(dst_style == pth_style && dst_parts.first != 0 && pth_parts.first != 0) { dst_redirects_to_pth = 1; String8Node *dst_n = dst_parts.first; String8Node *pth_n = pth_parts.first; for(;dst_n != 0 && pth_n != 0; dst_n = dst_n->next, pth_n = pth_n->next) { if(!str8_match(dst_n->string, pth_n->string, StringMatchFlag_CaseInsensitive)) { dst_redirects_to_pth = 0; break; } non_redirected_pth_first = pth_n->next; } } //- rjf: if this link can redirect to this path via `src` -> `dst`, compute // possible full source path, by taking `src` and appending non-redirected // suffix (which did not show up in `dst`) if(dst_redirects_to_pth) { String8List candidate_parts = src_parts; for(String8Node *p = non_redirected_pth_first; p != 0; p = p->next) { str8_list_push(scratch.arena, &candidate_parts, p->string); } StringJoin join = {0}; join.sep = str8_lit("/"); String8 candidate_path = str8_list_join(arena, &candidate_parts, &join); str8_list_push(arena, &result, candidate_path); } } } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Debug Info Extraction Type Pure Functions internal D_LineList d_line_list_copy(Arena *arena, D_LineList *list) { D_LineList dst = {0}; for(D_LineNode *src_n = list->first; src_n != 0; src_n = src_n->next) { D_LineNode *dst_n = push_array(arena, D_LineNode, 1); MemoryCopyStruct(dst_n, src_n); dst_n->v.file_path = push_str8_copy(arena, dst_n->v.file_path); SLLQueuePush(dst.first, dst.last, dst_n); dst.count += 1; } return dst; } //////////////////////////////// //~ rjf: Command Type Functions //- rjf: command parameters internal D_CmdParams d_cmd_params_copy(Arena *arena, D_CmdParams *src) { D_CmdParams dst = {0}; MemoryCopyStruct(&dst, src); dst.file_path = push_str8_copy(arena, dst.file_path); dst.targets.v = push_array(arena, D_Target, dst.targets.count); MemoryCopy(dst.targets.v, src->targets.v, sizeof(D_Target)*dst.targets.count); for(U64 idx = 0; idx < dst.targets.count; idx += 1) { D_Target *target = &dst.targets.v[idx]; target->exe = push_str8_copy(arena, target->exe); target->args = push_str8_copy(arena, target->args); target->working_directory = push_str8_copy(arena, target->working_directory); target->custom_entry_point_name = push_str8_copy(arena, target->custom_entry_point_name); target->env = str8_list_copy(arena, &target->env); } return dst; } //- rjf: command lists internal void d_cmd_list_push_new(Arena *arena, D_CmdList *cmds, D_CmdKind kind, D_CmdParams *params) { D_CmdNode *n = push_array(arena, D_CmdNode, 1); n->cmd.kind = kind; n->cmd.params = d_cmd_params_copy(arena, params); DLLPushBack(cmds->first, cmds->last, n); cmds->count += 1; } //////////////////////////////// //~ rjf: Stepping "Trap Net" Builders // NOTE(rjf): Stepping Algorithm Overview (2024/01/17) // // The basic idea behind all stepping algorithms in the debugger are setting up // a "trap net". A "trap net" is just a collection of high-level traps that are // meant to "catch" a thread after letting it run. This trap net is submitted // when the debugger frontend sends a "run" command (it is just empty if doing // an actual 'run' or 'continue'). The debugger control thread then uses this // trap net to program a state machine, to appropriately respond to a variety // of debug events which it is passed from the OS. // // These are "high-level traps" because they can have specific behavioral info // attached to them. These are encoded via the `CTRL_TrapFlags` type, which // allow expression of the following behaviors: // // - end-stepping: when this trap is hit, it will end the stepping operation, // and the target will not continue. // - ignore-stack-pointer-check: when a trap in the trap net is hit, it will // by-default be ignored if the thread's stack pointer has changed. this // flag disables that behavior, for when the stack pointer is expected to // change (e.g. step-out). // - single-step-after-hit: when a trap with this flag is hit, the debugger // will immediately single-step the thread which hit it. // - save-stack-pointer: when a trap with this flag is hit, it will rewrite // the stack pointer which is used to compare against, when deciding // whether or not to filter a trap (based on stack pointer changes). // - begin-spoof-mode: this enables "spoof mode". "spoof mode" is a special // mode that disables the trap net entirely, and lets the thread run // freely - but it catches the thread not with a trap, but a false return // address. the debugger will overwrite a specific return address on the // stack. this address will be overwritten with an address which does NOT // point to a valid page, such that when the thread returns out of a // particular call frame, the debugger will receive a debug event, at // which point it can move the thread back to the correct return address, // and resume with the trap net enabled. this is used in "step over" // operations, because it avoids target <-> debugger "roundtrips" (e.g. // target being stopped, debugger being called with debug events, then // target resumes when debugger's control thread is done running) for // recursions. (it doesn't make a difference with non-recursive calls, // but the debugger can't detect the difference). // // Each stepping command prepares its trap net differently. // // --- Instruction Step Into -------------------------------------------------- // In this case, no trap net is prepared, and only a low-level single-step is // performed. // // --- Instruction Step Over -------------------------------------------------- // To build a trap net for an instruction-level step-over, the next instruction // at the thread's current instruction pointer is decoded. If it is a call // instruction, or if it is a repeating instruction, then a trap with the // 'end-stepping' behavior is placed at the instruction immediately following // the 'call' instruction. // // --- Line Step Into --------------------------------------------------------- // For a source-line step-into, the thread's instruction pointer is first used // to look up into the debug info's line info, to find the machine code in the // thread's current source line. Every instruction in this range is decoded. // Traps are then built in the following way: // // - 'call' instruction -> if can decode call destination address, place // "end-stepping | ignore-stack-pointer-check" trap at destination. if // can't, "end-stepping | single-step-after | ignore-stack-pointer-check" // trap at call. // - 'jmp' (both unconditional & conditional) -> if can decode jump destination // address, AND if jump leaves the line, place "end-stepping | ignore- // stack-pointer-check" trap at destination. if can't, "end-stepping | // single-step-after | ignore-stack-pointer-check" trap at jmp. if jump // stays within the line, do nothing. // - 'return' -> place "end-stepping | single-step-after" trap at return inst. // - "end-stepping" trap is placed at the first address after the line, to // catch all steps which simply proceed linearly through the instruction // stream. // // --- Line Step Over --------------------------------------------------------- // For a source-line step-over, the thread's instruction pointer is first used // to look up into the debug info's line info, to find the machine code in the // thread's current source line. Every instruction in this range is decoded. // Traps are then built in the following way: // // - 'call' instruction -> place "single-step-after | begin-spoof-mode" trap at // call instruction. // - 'jmp' (both unconditional & conditional) -> if can decode jump destination // address, AND if jump leaves the line, place "end-stepping" trap at // destination. if can't, "end-stepping | single-step-after" trap at jmp. // if jump stays within the line, do nothing. // - 'return' -> place "end-stepping | single-step-after" trap at return inst. // - "end-stepping" trap is placed at the first address after the line, to // catch all steps which simply proceed linearly through the instruction // stream. // - for any instructions which may change the stack pointer, traps are placed // at them with the "save-stack-pointer | single-step-after" behaviors. internal D_TrapNet d_trap_net_from_thread__step_over_inst(Arena *arena, CTRL_Entity *thread) { Temp scratch = scratch_begin(&arena, 1); D_TrapNet result = {0}; // rjf: thread => unpacked info CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); Arch arch = thread->arch; U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); // rjf: ip => machine code String8 machine_code = {0}; { Rng1U64 rng = r1u64(ip_vaddr, ip_vaddr+max_instruction_size_from_arch(arch)); CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, rng, 0, os_now_microseconds()+5000); machine_code = machine_code_slice.data; } // rjf: build traps if machine code was read successfully if(machine_code.size != 0) { result.good_read = 1; // rjf: decode instruction DASM_Inst inst = dasm_inst_from_code(scratch.arena, arch, ip_vaddr, machine_code, DASM_Syntax_Intel); // rjf: call => run until call returns if(inst.flags & DASM_InstFlag_Call || inst.flags & DASM_InstFlag_Repeats) { CTRL_Trap trap = {CTRL_TrapFlag_EndStepping, ip_vaddr+inst.size}; ctrl_trap_list_push(arena, &result.traps, &trap); } } scratch_end(scratch); return result; } internal D_TrapNet d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread) { Temp scratch = scratch_begin(&arena, 1); log_infof("step_over_line:\n{\n"); D_TrapNet result = {0}; // rjf: thread => info Arch arch = thread->arch; U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); log_infof("ip_vaddr: 0x%I64x\n", ip_vaddr); log_infof("dbgi_key: {0x%I64x, 0x%I64x}\n", dbgi_key.u64[0], dbgi_key.u64[1]); // rjf: ip => line vaddr range Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = ctrl_voff_from_vaddr(module, ip_vaddr); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, ip_voff); Rng1U64 line_voff_rng = {0}; if(lines.first != 0) { line_voff_rng = lines.first->v.voff_range; line_vaddr_rng = ctrl_vaddr_range_from_voff_range(module, line_voff_rng); log_infof("line: {%S:%I64i}\n", lines.first->v.file_path, lines.first->v.pt.line); } log_infof("voff_range: {0x%I64x, 0x%I64x}\n", line_voff_rng.min, line_voff_rng.max); log_infof("vaddr_range: {0x%I64x, 0x%I64x}\n", line_vaddr_rng.min, line_vaddr_rng.max); } // rjf: opl line_vaddr_rng -> 0xf00f00 or 0xfeefee? => include in line vaddr range // // MSVC exports line info at these line numbers when /JMC (Just My Code) debugging // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = ctrl_voff_from_vaddr(module, line_vaddr_rng.max); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, opl_line_voff_rng); if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee)) { line_vaddr_rng.max = ctrl_vaddr_from_voff(module, lines.first->v.voff_range.max); } } // rjf: line vaddr range => did we find anything successfully? B32 good_line_info = (line_vaddr_rng.max != 0); // rjf: line vaddr range => line's machine code String8 machine_code = {0}; B32 good_machine_code = 0; if(good_line_info) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, 0, os_now_microseconds()+50000); machine_code = machine_code_slice.data; good_machine_code = (machine_code.size >= dim_1u64(line_vaddr_rng) && !machine_code_slice.any_byte_bad); LogInfoNamedBlockF("machine_code_slice") { log_infof("stale: %i\n", machine_code_slice.stale); log_infof("any_byte_bad: %i\n", machine_code_slice.any_byte_bad); log_infof("any_byte_changed: %i\n", machine_code_slice.any_byte_changed); log_infof("bytes:\n[\n"); for(U64 idx = 0; idx < machine_code_slice.data.size; idx += 1) { log_infof("0x%x,", machine_code_slice.data.str[idx]); if(idx%16 == 15 || idx+1 == machine_code_slice.data.size) { log_infof("\n"); } } log_infof("]\n"); } } // rjf: machine code => ctrl flow analysis DASM_CtrlFlowInfo ctrl_flow_info = {0}; if(good_machine_code) { ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Call| DASM_InstFlag_Branch| DASM_InstFlag_UnconditionalJump| DASM_InstFlag_ChangesStackPointer| DASM_InstFlag_Return, arch, line_vaddr_rng.min, machine_code); LogInfoNamedBlockF("ctrl_flow_info") { LogInfoNamedBlockF("exit_points") for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { log_infof("{vaddr:0x%I64x, jump_dest_vaddr:0x%I64x, inst_flags:%x}\n", n->v.vaddr, n->v.jump_dest_vaddr, n->v.inst_flags); } } } // rjf: push traps for all exit points if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { DASM_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; B32 add = 1; U64 trap_addr = point->vaddr; // rjf: branches/jumps/returns => single-step & end, OR trap @ destination. if(point->inst_flags & (DASM_InstFlag_Branch| DASM_InstFlag_UnconditionalJump| DASM_InstFlag_Return)) { flags |= (CTRL_TrapFlag_SingleStepAfterHit|CTRL_TrapFlag_EndStepping); // rjf: omit if this jump stays inside of this line if(contains_1u64(line_vaddr_rng, point->jump_dest_vaddr)) { add = 0; } // rjf: trap @ destination, if we can - we can avoid a single-step this way. if(point->jump_dest_vaddr != 0) { trap_addr = point->jump_dest_vaddr; flags &= ~CTRL_TrapFlag_SingleStepAfterHit; } } // rjf: call => place spoof at return spot in stack, single-step after hitting else if(point->inst_flags & DASM_InstFlag_Call) { flags |= (CTRL_TrapFlag_BeginSpoofMode|CTRL_TrapFlag_SingleStepAfterHit); } // rjf: instruction changes stack pointer => save off the stack pointer, single-step over, keep stepping else if(point->inst_flags & DASM_InstFlag_ChangesStackPointer) { flags |= (CTRL_TrapFlag_SingleStepAfterHit|CTRL_TrapFlag_SaveStackPointer); } // rjf: add if appropriate if(add) { CTRL_Trap trap = {flags, trap_addr}; ctrl_trap_list_push(arena, &result.traps, &trap); } } // rjf: push trap for natural linear flow if(good_line_info && good_machine_code) { CTRL_Trap trap = {CTRL_TrapFlag_EndStepping, line_vaddr_rng.max}; ctrl_trap_list_push(arena, &result.traps, &trap); } // rjf: store goodness if(good_machine_code) { result.good_line_info = good_line_info; result.good_read = good_machine_code; } // rjf: log LogInfoNamedBlockF("traps") for(CTRL_TrapNode *n = result.traps.first; n != 0; n = n->next) { log_infof("{flags:0x%x, vaddr:0x%I64x}\n", n->v.flags, n->v.vaddr); } scratch_end(scratch); log_infof("}\n\n"); return result; } internal D_TrapNet d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread) { Temp scratch = scratch_begin(&arena, 1); D_TrapNet result = {0}; // rjf: thread => info Arch arch = thread->arch; U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); // rjf: ip => line vaddr range Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = ctrl_voff_from_vaddr(module, ip_vaddr); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, ip_voff); Rng1U64 line_voff_rng = {0}; if(lines.first != 0) { line_voff_rng = lines.first->v.voff_range; line_vaddr_rng = ctrl_vaddr_range_from_voff_range(module, line_voff_rng); } } // rjf: opl line_vaddr_rng -> 0xf00f00 or 0xfeefee? => include in line vaddr range // // MSVC exports line info at these line numbers when /JMC (Just My Code) debugging // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = ctrl_voff_from_vaddr(module, line_vaddr_rng.max); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, opl_line_voff_rng); if(lines.first != 0 && (lines.first->v.pt.line == 0xf00f00 || lines.first->v.pt.line == 0xfeefee)) { line_vaddr_rng.max = ctrl_vaddr_from_voff(module, lines.first->v.voff_range.max); } } // rjf: line vaddr range => did we find anything successfully? B32 good_line_info = (line_vaddr_rng.max != 0); // rjf: line vaddr range => line's machine code String8 machine_code = {0}; B32 good_machine_code = 0; if(good_line_info) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, 0, os_now_microseconds()+5000); machine_code = machine_code_slice.data; good_machine_code = (machine_code.size >= dim_1u64(line_vaddr_rng) && !machine_code_slice.any_byte_bad); } // rjf: machine code => ctrl flow analysis DASM_CtrlFlowInfo ctrl_flow_info = {0}; if(good_machine_code) { ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Call| DASM_InstFlag_Branch| DASM_InstFlag_UnconditionalJump| DASM_InstFlag_ChangesStackPointer| DASM_InstFlag_Return, arch, line_vaddr_rng.min, machine_code); } // rjf: determine last DASM_CtrlFlowPoint *last_call_point = 0; if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { if(n->v.inst_flags & DASM_InstFlag_Call) { last_call_point = &n->v; } } // rjf: push traps for all exit points if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { DASM_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; B32 add = 1; U64 trap_addr = point->vaddr; // rjf: if this is not the last call instruction in the control flow, // and if we have no line info for this address, then do not add. if(point != last_call_point && point->inst_flags & DASM_InstFlag_Call && point->jump_dest_vaddr != 0) { U64 jump_dest_vaddr = point->jump_dest_vaddr; CTRL_Entity *jump_dest_module = ctrl_module_from_process_vaddr(process, jump_dest_vaddr); U64 jump_dest_voff = ctrl_voff_from_vaddr(jump_dest_module, jump_dest_vaddr); DI_Key jump_dest_dbgi_key = ctrl_dbgi_key_from_module(jump_dest_module); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, jump_dest_dbgi_key, jump_dest_voff); if(lines.count == 0) { add = 0; } } // rjf: branches/jumps/returns => single-step & end, OR trap @ destination. if(point->inst_flags & (DASM_InstFlag_Call| DASM_InstFlag_Branch| DASM_InstFlag_UnconditionalJump| DASM_InstFlag_Return)) { flags |= (CTRL_TrapFlag_SingleStepAfterHit|CTRL_TrapFlag_EndStepping|CTRL_TrapFlag_IgnoreStackPointerCheck); // rjf: omit if this jump stays inside of this line if(contains_1u64(line_vaddr_rng, point->jump_dest_vaddr)) { add = 0; } // rjf: trap @ destination, if we can - we can avoid a single-step this way. if(point->jump_dest_vaddr != 0) { trap_addr = point->jump_dest_vaddr; flags &= ~CTRL_TrapFlag_SingleStepAfterHit; } } // rjf: instruction changes stack pointer => save off the stack pointer, single-step over, keep stepping else if(point->inst_flags & DASM_InstFlag_ChangesStackPointer) { flags |= (CTRL_TrapFlag_SingleStepAfterHit|CTRL_TrapFlag_SaveStackPointer); } // rjf: add if appropriate if(add) { CTRL_Trap trap = {flags, trap_addr}; ctrl_trap_list_push(arena, &result.traps, &trap); } } // rjf: push trap for natural linear flow if(good_line_info && good_machine_code) { CTRL_Trap trap = {CTRL_TrapFlag_EndStepping, line_vaddr_rng.max}; ctrl_trap_list_push(arena, &result.traps, &trap); } // rjf: store goodness { result.good_line_info = good_line_info; result.good_read = good_machine_code; } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Debug Info Lookups //- rjf: voff -> line info internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff) { Temp scratch = scratch_begin(&arena, 1); Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, 0); D_LineList result = {0}; { //- rjf: gather line tables typedef struct LineTableNode LineTableNode; struct LineTableNode { LineTableNode *next; RDI_ParsedLineTable parsed_line_table; }; LineTableNode start_line_table = {0}; RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); RDI_LineTable *unit_line_table = rdi_line_table_from_unit(rdi, unit); rdi_parsed_from_line_table(rdi, unit_line_table, &start_line_table.parsed_line_table); LineTableNode *top_line_table = 0; RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); { for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) { RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); if(inline_site->line_table_idx != 0) { LineTableNode *n = push_array(scratch.arena, LineTableNode, 1); SLLStackPush(top_line_table, n); RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); rdi_parsed_from_line_table(rdi, line_table, &n->parsed_line_table); } } } SLLStackPush(top_line_table, &start_line_table); //- rjf: gather lines in each line table Rng1U64 shallowest_voff_range = {0}; for(LineTableNode *line_table_n = top_line_table; line_table_n != 0; line_table_n = line_table_n->next) { RDI_ParsedLineTable parsed_line_table = line_table_n->parsed_line_table; U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); if(line_info_idx < parsed_line_table.count) { RDI_Line *line = &parsed_line_table.lines[line_info_idx]; RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8List path_parts = {0}; for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(rdi, FilePathNodes, file->file_path_node_idx); fpn != rdi_element_from_name_idx(rdi, FilePathNodes, 0); fpn = rdi_element_from_name_idx(rdi, FilePathNodes, fpn->parent_path_node)) { String8 path_part = {0}; path_part.str = rdi_string_from_idx(rdi, fpn->name_string_idx, &path_part.size); str8_list_push_front(scratch.arena, &path_parts, path_part); } StringJoin join = {0}; join.sep = str8_lit("/"); String8 file_normalized_full_path = str8_list_join(arena, &path_parts, &join); D_LineNode *n = push_array(arena, D_LineNode, 1); SLLQueuePush(result.first, result.last, n); result.count += 1; if(line->file_idx != 0 && file_normalized_full_path.size != 0) { n->v.file_path = file_normalized_full_path; } n->v.pt = txt_pt(line->line_num, column ? column->col_first : 1); n->v.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); n->v.dbgi_key = dbgi_key; if(line_table_n == top_line_table) { shallowest_voff_range = n->v.voff_range; } } } //- rjf: clamp all lines from all tables by shallowest (most unwound) range for(D_LineNode *n = result.first; n != 0; n = n->next) { n->v.voff_range = intersect_1u64(n->v.voff_range, shallowest_voff_range); } } access_close(access); scratch_end(scratch); return result; } //- rjf: file:line -> line info // TODO(rjf): this depends on file path maps, needs to move internal D_LineListArray d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range) { D_LineListArray array = {0}; { array.count = dim_1s64(line_num_range)+1; array.v = push_array(arena, D_LineList, array.count); di_key_list_push(arena, &array.dbgi_keys, dbgi_key); } Temp scratch = scratch_begin(&arena, 1); U64 *lines_num_voffs = push_array(scratch.arena, U64, array.count); Access *access = access_open(); String8List overrides = rd_possible_overrides_from_file_path(scratch.arena, file_path); for(String8Node *override_n = overrides.first; override_n != 0; override_n = override_n->next) { String8 file_path = override_n->string; String8 file_path_normalized = lower_from_str8(scratch.arena, path_normalized_from_string(scratch.arena, file_path)); // rjf: binary -> rdi RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); // rjf: file_path_normalized * rdi -> src_id B32 good_src_id = 0; U32 src_id = 0; if(rdi != &rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id") { RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { good_src_id = 1; src_id = ids[0]; } } } // rjf: good src-id -> look up line info for visible range if(good_src_id) ProfScope("good src-id -> look up line info for visible range") { RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U64 line_idx = 0; for(S64 line_num = line_num_range.min; line_num <= line_num_range.max; line_num += 1, line_idx += 1) { D_LineList *list = &array.v[line_idx]; U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); if(lines_num_voffs[line_idx] < 8) ProfScope("iterate voffs (%i)", voff_count) for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); if(unit_line_info.voffs != 0) { Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; D_LineNode *n = push_array(arena, D_LineNode, 1); n->v.voff_range = range; n->v.pt.line = (S64)actual_line; n->v.pt.column = 1; n->v.dbgi_key = dbgi_key; SLLQueuePush(list->first, list->last, n); list->count += 1; lines_num_voffs[line_idx] += 1; if(lines_num_voffs[line_idx] >= 8) { break; } } } } } } access_close(access); scratch_end(scratch); return array; } internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range) { D_LineListArray array = {0}; { array.count = dim_1s64(line_num_range)+1; array.v = push_array(arena, D_LineList, array.count); } Temp scratch = scratch_begin(&arena, 1); U64 *lines_num_voffs = push_array(scratch.arena, U64, array.count); DI_KeyArray dbgi_keys = di_push_all_loaded_keys(scratch.arena); String8List overrides = rd_possible_overrides_from_file_path(scratch.arena, file_path); for(String8Node *override_n = overrides.first; override_n != 0; override_n = override_n->next) { String8 file_path = override_n->string; String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); for EachIndex(idx, dbgi_keys.count) { Access *access = access_open(); // rjf: binary -> rdi DI_Key key = dbgi_keys.v[idx]; RDI_Parsed *rdi = di_rdi_from_key(access, key, 1, 0); // rjf: file_path_normalized * rdi -> src_id B32 good_src_id = 0; U32 src_id = 0; if(rdi != &rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id") { RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { good_src_id = 1; src_id = ids[0]; } } } // rjf: good src-id -> look up line info for visible range if(good_src_id) ProfScope("good src-id -> look up line info for visible range") { RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U64 line_idx = 0; for(S64 line_num = line_num_range.min; line_num <= line_num_range.max; line_num += 1, line_idx += 1) { D_LineList *list = &array.v[line_idx]; U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, u32_from_u64_saturate((U64)line_num), &voff_count); if(lines_num_voffs[line_idx] < 8) ProfScope("iterate voffs (%i)", voff_count) for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); if(unit_line_info.voffs != 0) { Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; D_LineNode *n = push_array(arena, D_LineNode, 1); n->v.voff_range = range; n->v.pt.line = (S64)actual_line; n->v.pt.column = 1; n->v.dbgi_key = key; SLLQueuePush(list->first, list->last, n); list->count += 1; lines_num_voffs[line_idx] += 1; if(lines_num_voffs[line_idx] >= 8) { break; } } } } } // rjf: good src id -> push to relevant dbgi keys if(good_src_id) { di_key_list_push(arena, &array.dbgi_keys, key); } access_close(access); } } scratch_end(scratch); return array; } internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num) { D_LineListArray array = d_lines_array_from_dbgi_key_file_path_line_range(arena, dbgi_key, file_path, r1s64(line_num, line_num+1)); D_LineList list = {0}; if(array.count != 0) { list = array.v[0]; } return list; } internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num) { D_LineListArray array = d_lines_array_from_file_path_line_range(arena, file_path, r1s64(line_num, line_num+1)); D_LineList list = {0}; if(array.count != 0) { list = array.v[0]; } return list; } //////////////////////////////// //~ rjf: Process/Thread/Module Info Lookups internal U64 d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr) { ProfBeginFunction(); U64 base_vaddr = 0; Temp scratch = scratch_begin(0, 0); if(!d_ctrl_targets_running()) { //- rjf: unpack module info CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); Rng1U64 tls_vaddr_range = ctrl_tls_vaddr_range_from_module(module->handle); U64 addr_size = bit_size_from_arch(process->arch)/8; //- rjf: read module's TLS index U64 tls_index = 0; if(addr_size != 0) { CTRL_ProcessMemorySlice tls_index_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, tls_vaddr_range, 0, 0); if(tls_index_slice.data.size >= addr_size) { tls_index = *(U64 *)tls_index_slice.data.str; } } //- rjf: PE path if(addr_size != 0) { U64 thread_info_addr = root_vaddr; U64 tls_addr_off = tls_index*addr_size; U64 tls_addr_array = 0; CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0, 0); String8 tls_addr_array_data = tls_addr_array_slice.data; if(tls_addr_array_data.size >= 8) { MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64)); } CTRL_ProcessMemorySlice result_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0, 0); String8 result_data = result_slice.data; if(result_data.size >= 8) { MemoryCopy(&base_vaddr, result_data.str, sizeof(U64)); } } //- rjf: non-PE path (not implemented) #if 0 if(!bin_is_pe) { // TODO(rjf): not supported. old code from the prototype that Nick had sketched out: // TODO(nick): This code works only if the linked c runtime library is glibc. // Implement CRT detection here. U64 dtv_addr = UINT64_MAX; demon_read_memory(process->demon_handle, &dtv_addr, thread_info_addr, addr_size); /* union delta_thread_vector { size_t counter; struct { void *value; void *to_free; } pointer; }; */ U64 dtv_size = 16; U64 dtv_count = 0; demon_read_memory(process->demon_handle, &dtv_count, dtv_addr - dtv_size, addr_size); if (tls_index > 0 && tls_index < dtv_count) { demon_read_memory(process->demon_handle, &result, dtv_addr + dtv_size*tls_index, addr_size); } } #endif } scratch_end(scratch); ProfEnd(); return base_vaddr; } //////////////////////////////// //~ rjf: Target Controls //- rjf: stopped info from the control thread internal CTRL_Event d_ctrl_last_stop_event(void) { return d_state->ctrl_last_stop_event; } //////////////////////////////// //~ rjf: Main State Accessors/Mutators //- rjf: frame data internal U64 d_frame_index(void) { return d_state->frame_index; } //- rjf: control state internal D_RunKind d_ctrl_last_run_kind(void) { return d_state->ctrl_last_run_kind; } internal U64 d_ctrl_last_run_frame_idx(void) { return d_state->ctrl_last_run_frame_idx; } internal B32 d_ctrl_targets_running(void) { return d_state->ctrl_is_running; } //- rjf: active entity based queries internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena) { DI_KeyList dbgis = {0}; CTRL_EntityArray modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module); for EachIndex(idx, modules.count) { CTRL_Entity *module = modules.v[idx]; DI_Key key = ctrl_dbgi_key_from_module(module); di_key_list_push(arena, &dbgis, key); } return dbgis; } //- rjf: per-run caches internal U64 d_query_cached_rip_from_thread(CTRL_Entity *thread) { U64 result = d_query_cached_rip_from_thread_unwind(thread, 0); return result; } internal U64 d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count) { U64 result = 0; if(unwind_count == 0) { result = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); } else { Access *access = access_open(); CTRL_CallStack callstack = ctrl_call_stack_from_thread(access, thread->handle, 1, 0); if(callstack.concrete_frames_count != 0) { result = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[unwind_count%callstack.concrete_frames_count]->regs); } access_close(access); } return result; } internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr) { U64 result = 0; for(U64 cache_idx = 0; cache_idx < ArrayCount(d_state->tls_base_caches); cache_idx += 1) { D_RunTLSBaseCache *cache = &d_state->tls_base_caches[(d_state->tls_base_cache_gen+cache_idx)%ArrayCount(d_state->tls_base_caches)]; if(cache_idx == 0 && cache->slots_count == 0) { cache->slots_count = 256; cache->slots = push_array(cache->arena, D_RunTLSBaseCacheSlot, cache->slots_count); } else if(cache->slots_count == 0) { break; } CTRL_Handle handle = process->handle; U64 hash = d_hash_from_seed_string(d_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr)); U64 slot_idx = hash%cache->slots_count; D_RunTLSBaseCacheSlot *slot = &cache->slots[slot_idx]; D_RunTLSBaseCacheNode *node = 0; for(D_RunTLSBaseCacheNode *n = slot->first; n != 0; n = n->hash_next) { if(ctrl_handle_match(n->process, handle) && n->root_vaddr == root_vaddr && n->rip_vaddr == rip_vaddr) { node = n; break; } } if(node == 0) { U64 tls_base_vaddr = d_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); if(tls_base_vaddr != 0) { node = push_array(cache->arena, D_RunTLSBaseCacheNode, 1); SLLQueuePush_N(slot->first, slot->last, node, hash_next); node->process = handle; node->root_vaddr = root_vaddr; node->rip_vaddr = rip_vaddr; node->tls_base_vaddr = tls_base_vaddr; } } if(node != 0 && node->tls_base_vaddr != 0) { result = node->tls_base_vaddr; break; } } return result; } internal E_String2NumMap * d_query_cached_locals_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff) { ProfBeginFunction(); E_String2NumMap *map = &e_string2num_map_nil; for(U64 cache_idx = 0; cache_idx < ArrayCount(d_state->locals_caches); cache_idx += 1) { D_RunLocalsCache *cache = &d_state->locals_caches[(d_state->locals_cache_gen+cache_idx)%ArrayCount(d_state->locals_caches)]; if(cache_idx == 0 && cache->table_size == 0) { cache->table_size = 256; cache->table = push_array(cache->arena, D_RunLocalsCacheSlot, cache->table_size); } else if(cache->table_size == 0) { break; } U64 hash = u64_hash_from_str8(str8_struct(&dbgi_key)); U64 slot_idx = hash % cache->table_size; D_RunLocalsCacheSlot *slot = &cache->table[slot_idx]; D_RunLocalsCacheNode *node = 0; for(D_RunLocalsCacheNode *n = slot->first; n != 0; n = n->hash_next) { if(di_key_match(n->dbgi_key, dbgi_key) && n->voff == voff) { node = n; break; } } if(node == 0) { Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, 0); E_String2NumMap *map = e_push_locals_map_from_rdi_voff(cache->arena, rdi, voff); if(map->slots_count != 0) { node = push_array(cache->arena, D_RunLocalsCacheNode, 1); node->dbgi_key = dbgi_key; node->voff = voff; node->locals_map = map; SLLQueuePush_N(slot->first, slot->last, node, hash_next); } access_close(access); } if(node != 0 && node->locals_map->slots_count != 0) { map = node->locals_map; break; } } ProfEnd(); return map; } internal E_String2NumMap * d_query_cached_member_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff) { ProfBeginFunction(); E_String2NumMap *map = &e_string2num_map_nil; for(U64 cache_idx = 0; cache_idx < ArrayCount(d_state->member_caches); cache_idx += 1) { D_RunLocalsCache *cache = &d_state->member_caches[(d_state->member_cache_gen+cache_idx)%ArrayCount(d_state->member_caches)]; if(cache_idx == 0 && cache->table_size == 0) { cache->table_size = 256; cache->table = push_array(cache->arena, D_RunLocalsCacheSlot, cache->table_size); } else if(cache->table_size == 0) { break; } U64 hash = u64_hash_from_str8(str8_struct(&dbgi_key)); U64 slot_idx = hash % cache->table_size; D_RunLocalsCacheSlot *slot = &cache->table[slot_idx]; D_RunLocalsCacheNode *node = 0; for(D_RunLocalsCacheNode *n = slot->first; n != 0; n = n->hash_next) { if(di_key_match(n->dbgi_key, dbgi_key) && n->voff == voff) { node = n; break; } } if(node == 0) { Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, 0); E_String2NumMap *map = e_push_member_map_from_rdi_voff(cache->arena, rdi, voff); if(map->slots_count != 0) { node = push_array(cache->arena, D_RunLocalsCacheNode, 1); node->dbgi_key = dbgi_key; node->voff = voff; node->locals_map = map; SLLQueuePush_N(slot->first, slot->last, node, hash_next); } access_close(access); } if(node != 0 && node->locals_map->slots_count != 0) { map = node->locals_map; break; } } ProfEnd(); return map; } //- rjf: top-level command dispatch internal void d_push_cmd(D_CmdKind kind, D_CmdParams *params) { d_cmd_list_push_new(d_state->cmds_arena, &d_state->cmds, kind, params); } //- rjf: command iteration internal B32 d_next_cmd(D_Cmd **cmd) { D_CmdNode *start_node = d_state->cmds.first; if(cmd[0] != 0) { start_node = CastFromMember(D_CmdNode, cmd, cmd[0]); start_node = start_node->next; } cmd[0] = 0; if(start_node != 0) { cmd[0] = &start_node->cmd; } return !!cmd[0]; } //////////////////////////////// //~ rjf: Main Layer Top-Level Calls #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal void d_init(void) { Arena *arena = arena_alloc(); d_state = push_array(arena, D_State, 1); d_state->arena = arena; d_state->cmds_arena = arena_alloc(); d_state->output_log_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); c_submit_data(d_state->output_log_key, 0, str8_zero()); d_state->ctrl_entity_store = ctrl_entity_ctx_rw_store_alloc(); d_state->ctrl_stop_arena = arena_alloc(); d_state->ctrl_msg_arena = arena_alloc(); // rjf: set up caches for(U64 idx = 0; idx < ArrayCount(d_state->tls_base_caches); idx += 1) { d_state->tls_base_caches[idx].arena = arena_alloc(); } for(U64 idx = 0; idx < ArrayCount(d_state->locals_caches); idx += 1) { d_state->locals_caches[idx].arena = arena_alloc(); } for(U64 idx = 0; idx < ArrayCount(d_state->member_caches); idx += 1) { d_state->member_caches[idx].arena = arena_alloc(); } // rjf: set up run state d_state->ctrl_last_run_arena = arena_alloc(); } internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); D_EventList result = {0}; d_state->frame_index += 1; ////////////////////////////// //- rjf: sync with ctrl thread // ProfScope("sync with ctrl thread") { //- rjf: grab next reggen/memgen U64 new_mem_gen = ctrl_mem_gen(); U64 new_reg_gen = ctrl_reg_gen(); //- rjf: consume & process events CTRL_EventList events = ctrl_c2u_pop_events(scratch.arena); ctrl_entity_store_apply_events(d_state->ctrl_entity_store, &events); for(CTRL_EventNode *event_n = events.first; event_n != 0; event_n = event_n->next) { CTRL_Event *event = &event_n->v; log_infof("ctrl_event:\n{\n"); log_infof("kind: \"%S\"\n", ctrl_string_from_event_kind(event->kind)); log_infof("entity_id: %u\n", event->entity_id); switch(event->kind) { default:{}break; //- rjf: errors case CTRL_EventKind_Error: { log_user_error(event->string); }break; //- rjf: starts/stops case CTRL_EventKind_Started: { d_state->ctrl_is_running = 1; d_state->ctrl_thread_run_state = 1; }break; case CTRL_EventKind_Stopped: { B32 should_snap = !(d_state->ctrl_soft_halt_issued); d_state->ctrl_is_running = 0; d_state->ctrl_thread_run_state = 0; d_state->ctrl_soft_halt_issued = 0; // rjf: exception or unexpected trap -> push error if(event->cause == CTRL_EventCause_InterruptedByException || event->cause == CTRL_EventCause_InterruptedByTrap) { log_user_error(str8_zero()); } // rjf: gather stop info { arena_clear(d_state->ctrl_stop_arena); MemoryCopyStruct(&d_state->ctrl_last_stop_event, event); d_state->ctrl_last_stop_event.string = push_str8_copy(d_state->ctrl_stop_arena, d_state->ctrl_last_stop_event.string); } // rjf: push stop event to caller, if this is not a soft-halt if(should_snap) { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, event->entity); D_EventCause cause = D_EventCause_Null; switch(event->cause) { default:{}break; case CTRL_EventCause_InterruptedByHalt: { if(should_snap) { cause = D_EventCause_Halt; } else { cause = D_EventCause_SoftHalt; } }break; case CTRL_EventCause_UserBreakpoint: {cause = D_EventCause_UserBreakpoint;}break; } D_EventNode *n = push_array(arena, D_EventNode, 1); SLLQueuePush(result.first, result.last, n); result.count += 1; D_Event *evt = &n->v; evt->kind = D_EventKind_Stop; evt->cause = cause; evt->thread = thread->kind == CTRL_EntityKind_Thread ? thread->handle : ctrl_handle_zero(); evt->vaddr = event->rip_vaddr; evt->id = event->u64_code; } }break; //- rjf: entity creation/deletion case CTRL_EventKind_NewProc: { // rjf: the first process? -> clear session output CTRL_EntityArray existing_processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(existing_processes.count == 1) { MTX_Op op = {r1u64(0, 0xffffffffffffffffull), str8_lit("[new session]\n")}; mtx_push_op(d_state->output_log_key, op); } }break; case CTRL_EventKind_EndProc: { D_EventNode *n = push_array(arena, D_EventNode, 1); SLLQueuePush(result.first, result.last, n); result.count += 1; D_Event *evt = &n->v; evt->kind = D_EventKind_ProcessEnd; evt->code = event->u64_code; }break; case CTRL_EventKind_NewModule: { D_EventNode *n = push_array(arena, D_EventNode, 1); SLLQueuePush(result.first, result.last, n); result.count += 1; D_Event *evt = &n->v; evt->kind = D_EventKind_ModuleLoad; evt->module = event->entity; }break; //- rjf: debug strings case CTRL_EventKind_DebugString: { MTX_Op op = {r1u64(max_U64, max_U64), event->string}; mtx_push_op(d_state->output_log_key, op); }break; //- rjf: memory case CTRL_EventKind_MemReserve:{}break; case CTRL_EventKind_MemCommit:{}break; case CTRL_EventKind_MemDecommit:{}break; case CTRL_EventKind_MemRelease:{}break; } log_infof("}\n\n"); } //- rjf: clear tls base cache if((d_state->tls_base_cache_reggen_idx != new_reg_gen || d_state->tls_base_cache_memgen_idx != new_mem_gen) && !d_ctrl_targets_running()) { d_state->tls_base_cache_gen += 1; D_RunTLSBaseCache *cache = &d_state->tls_base_caches[d_state->tls_base_cache_gen%ArrayCount(d_state->tls_base_caches)]; arena_clear(cache->arena); cache->slots_count = 0; cache->slots = 0; d_state->tls_base_cache_reggen_idx = new_reg_gen; d_state->tls_base_cache_memgen_idx = new_mem_gen; } //- rjf: clear locals cache if(d_state->locals_cache_reggen_idx != new_reg_gen && !d_ctrl_targets_running()) { d_state->locals_cache_gen += 1; D_RunLocalsCache *cache = &d_state->locals_caches[d_state->locals_cache_gen%ArrayCount(d_state->locals_caches)]; arena_clear(cache->arena); cache->table_size = 0; cache->table = 0; d_state->locals_cache_reggen_idx = new_reg_gen; } //- rjf: clear members cache if(d_state->member_cache_reggen_idx != new_reg_gen && !d_ctrl_targets_running()) { d_state->member_cache_gen += 1; D_RunLocalsCache *cache = &d_state->member_caches[d_state->member_cache_gen%ArrayCount(d_state->member_caches)]; arena_clear(cache->arena); cache->table_size = 0; cache->table = 0; d_state->member_cache_reggen_idx = new_reg_gen; } } ////////////////////////////// //- rjf: hash ctrl parameterization state // U128 ctrl_param_state_hash = {0}; { // rjf: build data strings of all param data String8List strings = {0}; { CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread); for EachIndex(idx, threads.count) { CTRL_Entity *thread = threads.v[idx]; if(thread->is_frozen) { str8_list_push(scratch.arena, &strings, str8_struct(&thread->id)); str8_list_push(scratch.arena, &strings, str8_struct(&thread->is_frozen)); } } for(U64 idx = 0; idx < breakpoints->count; idx += 1) { D_Breakpoint *bp = &breakpoints->v[idx]; str8_list_push(scratch.arena, &strings, bp->file_path); str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt)); str8_list_push(scratch.arena, &strings, bp->vaddr_expr); str8_list_push(scratch.arena, &strings, bp->condition); } } // rjf: join & hash to produce result String8 string = str8_list_join(scratch.arena, &strings, 0); XXH128_hash_t hash = XXH3_128bits(string.str, string.size); MemoryCopy(&ctrl_param_state_hash, &hash, sizeof(ctrl_param_state_hash)); } ////////////////////////////// //- rjf: if ctrl thread is running, and our ctrl parameterization // state hash has changed since the last run, we should soft- // halt-refresh to inform the ctrl thread about the updated // state // if(d_ctrl_targets_running() && !u128_match(ctrl_param_state_hash, d_state->ctrl_last_run_param_state_hash)) { d_cmd(D_CmdKind_SoftHaltRefresh); } ////////////////////////////// //- rjf: process top-level commands // D_CmdList deferred_cmds = {0}; CTRL_MsgList ctrl_msgs = {0}; ProfScope("process top-level commands") { D_BreakpointArray run_extra_bps = {0}; for(D_Cmd *cmd = 0; d_next_cmd(&cmd);) { // rjf: unpack command D_CmdParams *params = &cmd->params; // rjf: prep ctrl running arguments B32 need_run = 0; D_RunKind run_kind = D_RunKind_Run; CTRL_Entity *run_thread = &ctrl_entity_nil; CTRL_RunFlags run_flags = 0; CTRL_TrapList run_traps = {0}; // rjf: process command switch(cmd->kind) { default:{}break; //- rjf: low-level target control operations case D_CmdKind_LaunchAndRun: case D_CmdKind_LaunchAndStepInto: { // rjf: get list of targets to launch D_TargetArray *targets_to_launch = ¶ms->targets; // rjf: no targets => assume all active targets if(targets_to_launch->count == 0) { targets_to_launch = targets; } // rjf: launch if(targets_to_launch->count != 0) { for(U64 idx = 0; idx < targets_to_launch->count; idx += 1) { // rjf: unpack target D_Target *target = &targets_to_launch->v[idx]; String8 exe = str8_skip_chop_whitespace(target->exe); String8 args = str8_skip_chop_whitespace(target->args); String8 working_directory = str8_skip_chop_whitespace(target->working_directory); String8 custom_entry_point_name = str8_skip_chop_whitespace(target->custom_entry_point_name); String8 stdout_path = str8_skip_chop_whitespace(target->stdout_path); String8 stderr_path = str8_skip_chop_whitespace(target->stderr_path); String8 stdin_path = str8_skip_chop_whitespace(target->stdin_path); String8List env = target->env; if(working_directory.size == 0) { working_directory = os_get_current_path(scratch.arena); } // rjf: build launch options String8List cmdln_strings = {0}; { str8_list_push(scratch.arena, &cmdln_strings, exe); { U64 start_split_idx = 0; B32 quoted = 0; for(U64 idx = 0; idx <= args.size; idx += 1) { U8 byte = idx < args.size ? args.str[idx] : 0; if(byte == '"') { quoted ^= 1; } B32 splitter_found = (!quoted && (byte == 0 || char_is_space(byte))); if(splitter_found) { String8 string = str8_substr(args, r1u64(start_split_idx, idx)); if(string.size > 0) { str8_list_push(scratch.arena, &cmdln_strings, string); } start_split_idx = idx+1; } } } } // rjf: push message to launch { CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = CTRL_MsgKind_Launch; msg->path = working_directory; msg->cmd_line_string_list = cmdln_strings; msg->stdout_path = stdout_path; msg->stderr_path = stderr_path; msg->stdin_path = stdin_path; msg->debug_subprocesses = target->debug_subprocesses; msg->env_inherit = 1; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); str8_list_push(scratch.arena, &msg->entry_points, custom_entry_point_name); msg->env_string_list = env; } } // rjf: run need_run = 1; run_kind = D_RunKind_Run; run_thread = &ctrl_entity_nil; run_flags = (cmd->kind == D_CmdKind_LaunchAndStepInto) ? CTRL_RunFlag_StopOnEntryPoint : 0; } // rjf: no targets -> error if(targets_to_launch->count == 0) { log_user_error(str8_lit("No active targets exist; cannot launch. You must select a target first.")); } }break; case D_CmdKind_Kill: { CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->process); if(process == &ctrl_entity_nil) { log_user_error(str8_lit("Cannot kill; no process was specified.")); } else { CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = CTRL_MsgKind_Kill; msg->exit_code = 1; msg->entity = process->handle; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); } }break; case D_CmdKind_KillAll: { CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = CTRL_MsgKind_KillAll; msg->exit_code = 1; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); }break; case D_CmdKind_Detach: { CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->process); if(process == &ctrl_entity_nil) { log_user_error(str8_lit("Cannot detach; no process specified.")); } else { CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = CTRL_MsgKind_Detach; msg->entity = process->handle; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); } }break; case D_CmdKind_Continue: { B32 good_to_run = 0; CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread); if(threads.count > 0) { for EachIndex(idx, threads.count) { CTRL_Entity *thread = threads.v[idx]; if(!thread->is_frozen) { good_to_run = 1; break; } } if(good_to_run) { need_run = 1; run_kind = D_RunKind_Run; run_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread); } else { log_user_error(str8_lit("Cannot run with all threads frozen.")); } } }break; case D_CmdKind_StepIntoInst: case D_CmdKind_StepOverInst: case D_CmdKind_StepIntoLine: case D_CmdKind_StepOverLine: case D_CmdKind_StepOut: { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread); if(thread == &ctrl_entity_nil) { log_user_error(str8_lit("Must have a selected thread to step.")); } else if(d_ctrl_targets_running()) { if(d_ctrl_last_run_kind() == D_RunKind_Run) { log_user_error(str8_lit("Must halt before stepping.")); } } else if(thread->is_frozen) { log_user_error(str8_lit("Must thaw selected thread before stepping.")); } else { D_TrapNet trap_net = {0}; switch(cmd->kind) { default: break; case D_CmdKind_StepIntoInst: {trap_net.good_read = 1;}break; case D_CmdKind_StepOverInst: {trap_net = d_trap_net_from_thread__step_over_inst(scratch.arena, thread);}break; case D_CmdKind_StepIntoLine: {trap_net = d_trap_net_from_thread__step_into_line(scratch.arena, thread);}break; case D_CmdKind_StepOverLine: {trap_net = d_trap_net_from_thread__step_over_line(scratch.arena, thread);}break; case D_CmdKind_StepOut: { Access *access = access_open(); // rjf: thread => call stack CTRL_CallStack callstack = ctrl_call_stack_from_thread(access, thread->handle, 1, os_now_microseconds()+10000); // rjf: use first unwind frame to generate trap if(callstack.concrete_frames_count > 1) { U64 vaddr = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[1]->regs); CTRL_Trap trap = {CTRL_TrapFlag_EndStepping|CTRL_TrapFlag_IgnoreStackPointerCheck, vaddr}; ctrl_trap_list_push(scratch.arena, &trap_net.traps, &trap); trap_net.good_read = 1; } else { log_user_error(str8_lit("Could not find the return address of the current callstack frame successfully.")); } access_close(access); }break; } B32 good_trap_net = (trap_net.good_read || !trap_net.good_line_info); if(good_trap_net && trap_net.traps.count != 0) { need_run = 1; run_kind = D_RunKind_Step; run_thread = thread; run_flags = 0; run_traps = trap_net.traps; } else if(good_trap_net && trap_net.traps.count == 0) { need_run = 1; run_kind = D_RunKind_SingleStep; run_thread = thread; run_flags = 0; run_traps = trap_net.traps; } else if(!good_trap_net && params->retry_idx < 100) { D_CmdParams params_copy = *params; params_copy.retry_idx += 1; d_cmd_list_push_new(scratch.arena, &deferred_cmds, cmd->kind, ¶ms_copy); } else if(!good_trap_net) { log_user_error(str8_lit("Could not successfully step.")); } } }break; case D_CmdKind_Halt: if(d_ctrl_targets_running()) { ctrl_halt(); }break; case D_CmdKind_SoftHaltRefresh: if(d_ctrl_targets_running()) { need_run = 1; run_kind = d_state->ctrl_last_run_kind; run_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, d_state->ctrl_last_run_thread_handle); run_flags = d_state->ctrl_last_run_flags; run_traps = d_state->ctrl_last_run_traps; }break; case D_CmdKind_SetThreadIP: { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread); U64 vaddr = params->vaddr; void *block = ctrl_reg_block_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, thread->handle); regs_arch_block_write_rip(thread->arch, block, vaddr); B32 result = ctrl_thread_write_reg_block(thread->handle, block); (void)result; }break; //- rjf: high-level composite target control operations case D_CmdKind_RunToLine: { run_extra_bps.count = 1; run_extra_bps.v = push_array(scratch.arena, D_Breakpoint, 1); if(params->file_path.size != 0) { run_extra_bps.v[0].file_path = params->file_path; run_extra_bps.v[0].pt = params->cursor; } else if(params->vaddr != 0) { run_extra_bps.v[0].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr); } d_cmd(D_CmdKind_Run); }break; case D_CmdKind_Run: { CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(processes.count != 0) { d_cmd(D_CmdKind_Continue, .machine = params->machine, .process = params->process, .thread = params->thread); } else if(!d_ctrl_targets_running()) { d_cmd(D_CmdKind_LaunchAndRun); } }break; case D_CmdKind_Restart: { CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(processes.count != 0) { d_cmd(D_CmdKind_KillAll); } d_cmd(D_CmdKind_LaunchAndRun); }break; case D_CmdKind_StepInto: case D_CmdKind_StepOver: { CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(processes.count != 0) { D_CmdKind step_cmd_kind = (cmd->kind == D_CmdKind_StepInto ? D_CmdKind_StepIntoLine : D_CmdKind_StepOverLine); B32 prefer_disasm = params->prefer_disasm; if(prefer_disasm) { step_cmd_kind = (cmd->kind == D_CmdKind_StepInto ? D_CmdKind_StepIntoInst : D_CmdKind_StepOverInst); } d_cmd(step_cmd_kind, .thread = params->thread); } else if(!d_ctrl_targets_running()) { d_cmd(D_CmdKind_LaunchAndStepInto, .targets = *targets); } }break; //- rjf: debug control context management operations case D_CmdKind_FreezeThread: case D_CmdKind_ThawThread: case D_CmdKind_FreezeProcess: case D_CmdKind_ThawProcess: case D_CmdKind_FreezeMachine: case D_CmdKind_ThawMachine: { D_CmdKind disptch_kind = ((cmd->kind == D_CmdKind_FreezeThread || cmd->kind == D_CmdKind_FreezeProcess || cmd->kind == D_CmdKind_FreezeMachine) ? D_CmdKind_FreezeEntity : D_CmdKind_ThawEntity); d_push_cmd(disptch_kind, params); }break; case D_CmdKind_FreezeLocalMachine: { CTRL_MachineID machine_id = CTRL_MachineID_Local; d_cmd(D_CmdKind_FreezeMachine, .entity = ctrl_handle_make(machine_id, dmn_handle_zero())); }break; case D_CmdKind_ThawLocalMachine: { CTRL_MachineID machine_id = CTRL_MachineID_Local; d_cmd(D_CmdKind_ThawMachine, .entity = ctrl_handle_make(machine_id, dmn_handle_zero())); }break; case D_CmdKind_FreezeEntity: case D_CmdKind_ThawEntity: { B32 should_freeze = (cmd->kind == D_CmdKind_FreezeEntity); CTRL_Entity *root = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity); for(CTRL_Entity *e = root; e != &ctrl_entity_nil; e = ctrl_entity_rec_depth_first_pre(e, root).next) { if(e->kind == CTRL_EntityKind_Thread) { e->is_frozen = should_freeze; CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = (should_freeze ? CTRL_MsgKind_FreezeThread : CTRL_MsgKind_ThawThread); msg->entity = e->handle; } } if(d_ctrl_targets_running()) { need_run = 1; run_kind = d_state->ctrl_last_run_kind; run_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, d_state->ctrl_last_run_thread_handle); run_flags = d_state->ctrl_last_run_flags; run_traps = d_state->ctrl_last_run_traps; } }break; //- rjf: entity decoration case D_CmdKind_SetEntityColor: { CTRL_Entity *entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity); entity->rgba = params->rgba; }break; case D_CmdKind_SetEntityName: { CTRL_Entity *entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity); ctrl_entity_equip_string(d_state->ctrl_entity_store, entity, params->string); }break; //- rjf: attaching case D_CmdKind_Attach: { U32 pid = params->pid; if(pid != 0) { CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); msg->kind = CTRL_MsgKind_Attach; msg->entity_id = pid; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); } }break; } // rjf: do run if needed if(need_run) { // rjf: compute hash of all run-parameterization entities, store { d_state->ctrl_last_run_param_state_hash = ctrl_param_state_hash; } // rjf: push & fill run message CTRL_Msg *msg = ctrl_msg_list_push(scratch.arena, &ctrl_msgs); { CTRL_Entity *process = ctrl_entity_ancestor_from_kind(run_thread, CTRL_EntityKind_Process); msg->kind = (run_kind == D_RunKind_Run || run_kind == D_RunKind_Step) ? CTRL_MsgKind_Run : CTRL_MsgKind_SingleStep; msg->run_flags = run_flags; msg->entity = run_thread->handle; msg->parent = process->handle; MemoryCopyArray(msg->exception_code_filters, exception_code_filters); MemoryCopyStruct(&msg->traps, &run_traps); D_BreakpointArray *bp_batches[] = { breakpoints, &run_extra_bps, }; for(U64 batch_idx = 0; batch_idx < ArrayCount(bp_batches); batch_idx += 1) { D_BreakpointArray *batch_breakpoints = bp_batches[batch_idx]; for(U64 idx = 0; idx < batch_breakpoints->count; idx += 1) { // rjf: unpack user breakpoint entity D_Breakpoint *bp = &batch_breakpoints->v[idx]; // rjf: d -> ctrl flags CTRL_UserBreakpointFlags ctrl_bp_flags = 0; if(bp->flags & D_BreakpointFlag_BreakOnWrite) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnWrite; } if(bp->flags & D_BreakpointFlag_BreakOnRead) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnRead; } if(bp->flags & D_BreakpointFlag_BreakOnExecute) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnExecute; } // rjf: textual location -> add breakpoints for all possible override locations if(bp->file_path.size != 0 && bp->pt.line != 0) { String8List overrides = d_possible_path_overrides_from_maps_path(scratch.arena, path_maps, bp->file_path); for(String8Node *n = overrides.first; n != 0; n = n->next) { CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_FileNameAndLineColNumber}; ctrl_user_bp.flags = ctrl_bp_flags; ctrl_user_bp.id = bp->id; ctrl_user_bp.string = n->string; ctrl_user_bp.pt = bp->pt; ctrl_user_bp.condition = bp->condition; ctrl_user_bp.size = bp->size; ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp); } } // rjf: virtual address expression -> add expression breakpoint else if(bp->vaddr_expr.size != 0) { CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_Expression}; ctrl_user_bp.flags = ctrl_bp_flags; ctrl_user_bp.id = bp->id; ctrl_user_bp.string = bp->vaddr_expr; ctrl_user_bp.condition = bp->condition; ctrl_user_bp.size = bp->size; ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp); } } } } // rjf: copy run traps to scratch (needed, if run_traps can be `d_state->ctrl_last_run_traps`) CTRL_TrapList run_traps_copy = ctrl_trap_list_copy(scratch.arena, &run_traps); D_BreakpointArray run_extra_bps_copy = d_breakpoint_array_copy(scratch.arena, &run_extra_bps); // rjf: store last run info arena_clear(d_state->ctrl_last_run_arena); d_state->ctrl_last_run_kind = run_kind; d_state->ctrl_last_run_frame_idx = d_frame_index(); d_state->ctrl_last_run_thread_handle = run_thread->handle; d_state->ctrl_last_run_flags = run_flags; d_state->ctrl_last_run_traps = ctrl_trap_list_copy(d_state->ctrl_last_run_arena, &run_traps_copy); d_state->ctrl_last_run_extra_bps = d_breakpoint_array_copy(d_state->ctrl_last_run_arena, &run_extra_bps_copy); d_state->ctrl_is_running = 1; } } } ////////////////////////////// //- rjf: clear command batch // { arena_clear(d_state->cmds_arena); MemoryZeroStruct(&d_state->cmds); } ////////////////////////////// //- rjf: push deferred commands // for EachNode(n, D_CmdNode, deferred_cmds.first) { d_cmd_list_push_new(d_state->cmds_arena, &d_state->cmds, n->cmd.kind, &n->cmd.params); } ////////////////////////////// //- rjf: push new control messages to queue - try to send queue to control, // clear queue if successful (if not, we'll just keep them around until // the next tick) // { CTRL_MsgList msgs_copy = ctrl_msg_list_deep_copy(d_state->ctrl_msg_arena, &ctrl_msgs); ctrl_msg_list_concat_in_place(&d_state->ctrl_msgs, &msgs_copy); if(d_state->ctrl_msgs.count != 0) { if(!d_state->ctrl_soft_halt_issued && d_state->ctrl_thread_run_state) { d_state->ctrl_soft_halt_issued = 1; ctrl_halt(); } if(ctrl_u2c_push_msgs(&d_state->ctrl_msgs, os_now_microseconds()+100)) { MemoryZeroStruct(&d_state->ctrl_msgs); arena_clear(d_state->ctrl_msg_arena); } } } ProfEnd(); scratch_end(scratch); return result; } ================================================ FILE: src/dbg_engine/dbg_engine_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBG_ENGINE_CORE_H #define DBG_ENGINE_CORE_H //////////////////////////////// //~ rjf: Tick Input Types typedef struct D_Target D_Target; struct D_Target { String8 exe; String8 args; String8 working_directory; String8 custom_entry_point_name; String8 stdout_path; String8 stderr_path; String8 stdin_path; B32 debug_subprocesses; String8List env; }; typedef struct D_TargetArray D_TargetArray; struct D_TargetArray { D_Target *v; U64 count; }; typedef U32 D_BreakpointFlags; enum { D_BreakpointFlag_BreakOnWrite = (1<<0), D_BreakpointFlag_BreakOnRead = (1<<1), D_BreakpointFlag_BreakOnExecute = (1<<2), }; typedef struct D_Breakpoint D_Breakpoint; struct D_Breakpoint { D_BreakpointFlags flags; U64 id; String8 file_path; TxtPt pt; String8 vaddr_expr; String8 condition; U64 size; }; typedef struct D_BreakpointArray D_BreakpointArray; struct D_BreakpointArray { D_Breakpoint *v; U64 count; }; typedef struct D_PathMap D_PathMap; struct D_PathMap { String8 src; String8 dst; }; typedef struct D_PathMapArray D_PathMapArray; struct D_PathMapArray { D_PathMap *v; U64 count; }; //////////////////////////////// //~ rjf: Trap Nets typedef struct D_TrapNet D_TrapNet; struct D_TrapNet { CTRL_TrapList traps; B32 good_line_info; B32 good_read; }; //////////////////////////////// //~ rjf: Tick Output Types typedef enum D_EventKind { D_EventKind_Null, D_EventKind_ModuleLoad, D_EventKind_ProcessEnd, D_EventKind_Stop, D_EventKind_COUNT } D_EventKind; typedef enum D_EventCause { D_EventCause_Null, D_EventCause_UserBreakpoint, D_EventCause_Halt, D_EventCause_SoftHalt, D_EventCause_COUNT } D_EventCause; typedef struct D_Event D_Event; struct D_Event { D_EventKind kind; D_EventCause cause; CTRL_Handle module; CTRL_Handle thread; U64 vaddr; U64 code; U64 id; }; typedef struct D_EventNode D_EventNode; struct D_EventNode { D_EventNode *next; D_Event v; }; typedef struct D_EventList D_EventList; struct D_EventList { D_EventNode *first; D_EventNode *last; U64 count; }; //////////////////////////////// //~ rjf: Line Info Types typedef struct D_Line D_Line; struct D_Line { String8 file_path; TxtPt pt; Rng1U64 voff_range; DI_Key dbgi_key; }; typedef struct D_LineNode D_LineNode; struct D_LineNode { D_LineNode *next; D_Line v; }; typedef struct D_LineList D_LineList; struct D_LineList { D_LineNode *first; D_LineNode *last; U64 count; }; typedef struct D_LineListArray D_LineListArray; struct D_LineListArray { D_LineList *v; U64 count; DI_KeyList dbgi_keys; }; //////////////////////////////// //~ rjf: Debug Engine Control Communication Types typedef enum D_RunKind { D_RunKind_Run, D_RunKind_SingleStep, D_RunKind_Step, D_RunKind_COUNT } D_RunKind; //////////////////////////////// //~ rjf: Generated Code #include "dbg_engine/generated/dbg_engine.meta.h" //////////////////////////////// //~ rjf: Command Types typedef struct D_CmdParams D_CmdParams; struct D_CmdParams { CTRL_Handle machine; CTRL_Handle process; CTRL_Handle thread; CTRL_Handle entity; String8 string; String8 file_path; TxtPt cursor; U64 vaddr; B32 prefer_disasm; U32 pid; U32 rgba; D_TargetArray targets; U64 retry_idx; }; typedef struct D_Cmd D_Cmd; struct D_Cmd { D_CmdKind kind; D_CmdParams params; }; typedef struct D_CmdNode D_CmdNode; struct D_CmdNode { D_CmdNode *next; D_CmdNode *prev; D_Cmd cmd; }; typedef struct D_CmdList D_CmdList; struct D_CmdList { D_CmdNode *first; D_CmdNode *last; U64 count; }; //////////////////////////////// //~ rjf: Main State Caches //- rjf: per-run tls-base-vaddr cache typedef struct D_RunTLSBaseCacheNode D_RunTLSBaseCacheNode; struct D_RunTLSBaseCacheNode { D_RunTLSBaseCacheNode *hash_next; CTRL_Handle process; U64 root_vaddr; U64 rip_vaddr; U64 tls_base_vaddr; }; typedef struct D_RunTLSBaseCacheSlot D_RunTLSBaseCacheSlot; struct D_RunTLSBaseCacheSlot { D_RunTLSBaseCacheNode *first; D_RunTLSBaseCacheNode *last; }; typedef struct D_RunTLSBaseCache D_RunTLSBaseCache; struct D_RunTLSBaseCache { Arena *arena; U64 slots_count; D_RunTLSBaseCacheSlot *slots; }; //- rjf: per-run locals cache typedef struct D_RunLocalsCacheNode D_RunLocalsCacheNode; struct D_RunLocalsCacheNode { D_RunLocalsCacheNode *hash_next; DI_Key dbgi_key; U64 voff; E_String2NumMap *locals_map; }; typedef struct D_RunLocalsCacheSlot D_RunLocalsCacheSlot; struct D_RunLocalsCacheSlot { D_RunLocalsCacheNode *first; D_RunLocalsCacheNode *last; }; typedef struct D_RunLocalsCache D_RunLocalsCache; struct D_RunLocalsCache { Arena *arena; U64 table_size; D_RunLocalsCacheSlot *table; }; //////////////////////////////// //~ rjf: Main State Types typedef struct D_State D_State; struct D_State { // rjf: top-level state Arena *arena; U64 frame_index; // rjf: commands Arena *cmds_arena; D_CmdList cmds; // rjf: output log key C_Key output_log_key; // rjf: per-run caches U64 tls_base_cache_reggen_idx; U64 tls_base_cache_memgen_idx; D_RunTLSBaseCache tls_base_caches[2]; U64 tls_base_cache_gen; U64 locals_cache_reggen_idx; D_RunLocalsCache locals_caches[2]; U64 locals_cache_gen; U64 member_cache_reggen_idx; D_RunLocalsCache member_caches[2]; U64 member_cache_gen; // rjf: user -> ctrl driving state Arena *ctrl_last_run_arena; D_RunKind ctrl_last_run_kind; U64 ctrl_last_run_frame_idx; CTRL_Handle ctrl_last_run_thread_handle; CTRL_RunFlags ctrl_last_run_flags; CTRL_TrapList ctrl_last_run_traps; D_BreakpointArray ctrl_last_run_extra_bps; U128 ctrl_last_run_param_state_hash; B32 ctrl_is_running; B32 ctrl_thread_run_state; B32 ctrl_soft_halt_issued; Arena *ctrl_msg_arena; CTRL_MsgList ctrl_msgs; // rjf: ctrl -> user reading state CTRL_EntityCtxRWStore *ctrl_entity_store; Arena *ctrl_stop_arena; CTRL_Event ctrl_last_stop_event; }; //////////////////////////////// //~ rjf: Globals global D_State *d_state = 0; //////////////////////////////// //~ rjf: Basic Helpers internal U64 d_hash_from_seed_string(U64 seed, String8 string); internal U64 d_hash_from_string(String8 string); internal U64 d_hash_from_seed_string__case_insensitive(U64 seed, String8 string); internal U64 d_hash_from_string__case_insensitive(String8 string); //////////////////////////////// //~ rjf: Breakpoints internal D_BreakpointArray d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src); //////////////////////////////// //~ rjf: Path Map Application internal String8List d_possible_path_overrides_from_maps_path(Arena *arena, D_PathMapArray *path_maps, String8 file_path); //////////////////////////////// //~ rjf: Debug Info Extraction Type Pure Functions internal D_LineList d_line_list_copy(Arena *arena, D_LineList *list); //////////////////////////////// //~ rjf: Command Type Functions //- rjf: command parameters internal D_CmdParams d_cmd_params_copy(Arena *arena, D_CmdParams *src); //- rjf: command lists internal void d_cmd_list_push_new(Arena *arena, D_CmdList *cmds, D_CmdKind kind, D_CmdParams *params); //////////////////////////////// //~ rjf: Stepping "Trap Net" Builders internal D_TrapNet d_trap_net_from_thread__step_over_inst(Arena *arena, CTRL_Entity *thread); internal D_TrapNet d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread); internal D_TrapNet d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread); //////////////////////////////// //~ rjf: Debug Info Lookups //- rjf: voff -> line info internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key dbgi_key, U64 voff); //- rjf: file:line -> line info // TODO(rjf): this depends on file path maps, needs to move // TODO(rjf): need to clean this up & dedup internal D_LineListArray d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, String8 file_path, Rng1S64 line_num_range); internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 line_num_range); internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num); internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num); //////////////////////////////// //~ rjf: Process/Thread/Module Info Lookups internal U64 d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr); //////////////////////////////// //~ rjf: Target Controls //- rjf: stopped info from the control thread internal CTRL_Event d_ctrl_last_stop_event(void); //////////////////////////////// //~ rjf: Main State Accessors/Mutators //- rjf: frame data internal U64 d_frame_index(void); //- rjf: control state internal D_RunKind d_ctrl_last_run_kind(void); internal U64 d_ctrl_last_run_frame_idx(void); internal B32 d_ctrl_targets_running(void); //- rjf: active entity based queries internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena); //- rjf: per-run caches internal U64 d_query_cached_rip_from_thread(CTRL_Entity *thread); internal U64 d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count); internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr); internal E_String2NumMap *d_query_cached_locals_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff); internal E_String2NumMap *d_query_cached_member_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff); //- rjf: top-level command dispatch internal void d_push_cmd(D_CmdKind kind, D_CmdParams *params); #define d_cmd(kind, ...) d_push_cmd((kind), &(D_CmdParams){.thread = {0}, __VA_ARGS__}) //- rjf: command iteration internal B32 d_next_cmd(D_Cmd **cmd); //////////////////////////////// //~ rjf: Main Layer Top-Level Calls internal void d_init(void); internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]); #endif // DBG_ENGINE_CORE_H ================================================ FILE: src/dbg_engine/dbg_engine_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "dbg_engine_core.c" ================================================ FILE: src/dbg_engine/dbg_engine_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBG_ENGINE_INC_H #define DBG_ENGINE_INC_H #include "dbg_engine_core.h" #endif // DBG_ENGINE_INC_H ================================================ FILE: src/dbg_engine/generated/dbg_engine.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE ================================================ FILE: src/dbg_engine/generated/dbg_engine.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef DBG_ENGINE_META_H #define DBG_ENGINE_META_H typedef enum D_CmdKind { D_CmdKind_Null, D_CmdKind_LaunchAndRun, D_CmdKind_LaunchAndStepInto, D_CmdKind_Kill, D_CmdKind_KillAll, D_CmdKind_Detach, D_CmdKind_Continue, D_CmdKind_StepIntoInst, D_CmdKind_StepOverInst, D_CmdKind_StepIntoLine, D_CmdKind_StepOverLine, D_CmdKind_StepOut, D_CmdKind_Halt, D_CmdKind_SoftHaltRefresh, D_CmdKind_SetThreadIP, D_CmdKind_RunToLine, D_CmdKind_Run, D_CmdKind_Restart, D_CmdKind_StepInto, D_CmdKind_StepOver, D_CmdKind_FreezeThread, D_CmdKind_ThawThread, D_CmdKind_FreezeProcess, D_CmdKind_ThawProcess, D_CmdKind_FreezeMachine, D_CmdKind_ThawMachine, D_CmdKind_FreezeLocalMachine, D_CmdKind_ThawLocalMachine, D_CmdKind_FreezeEntity, D_CmdKind_ThawEntity, D_CmdKind_SetEntityColor, D_CmdKind_SetEntityName, D_CmdKind_Attach, D_CmdKind_COUNT, } D_CmdKind; global B32 DEV_always_refresh = 0; global B32 DEV_simulate_lag = 0; global B32 DEV_draw_ui_text_pos = 0; global B32 DEV_draw_ui_focus_debug = 0; global B32 DEV_draw_ui_box_heatmap = 0; global B32 DEV_eval_compiler_tooltips = 0; global B32 DEV_eval_watch_key_tooltips = 0; global B32 DEV_cmd_context_tooltips = 0; global B32 DEV_updating_indicator = 0; struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] = { {&DEV_always_refresh, str8_lit_comp("always_refresh")}, {&DEV_simulate_lag, str8_lit_comp("simulate_lag")}, {&DEV_draw_ui_text_pos, str8_lit_comp("draw_ui_text_pos")}, {&DEV_draw_ui_focus_debug, str8_lit_comp("draw_ui_focus_debug")}, {&DEV_draw_ui_box_heatmap, str8_lit_comp("draw_ui_box_heatmap")}, {&DEV_eval_compiler_tooltips, str8_lit_comp("eval_compiler_tooltips")}, {&DEV_eval_watch_key_tooltips, str8_lit_comp("eval_watch_key_tooltips")}, {&DEV_cmd_context_tooltips, str8_lit_comp("cmd_context_tooltips")}, {&DEV_updating_indicator, str8_lit_comp("updating_indicator")}, }; #endif // DBG_ENGINE_META_H ================================================ FILE: src/dbg_info/dbg_info.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal DI_Key di_key_zero(void) { DI_Key key = {0}; return key; } internal B32 di_key_match(DI_Key a, DI_Key b) { B32 result = MemoryMatchStruct(&a, &b); return result; } internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key key) { DI_KeyNode *n = push_array(arena, DI_KeyNode, 1); n->v = key; SLLQueuePush(list->first, list->last, n); list->count += 1; } internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list) { DI_KeyArray array = {0}; array.count = list->count; array.v = push_array(arena, DI_Key, array.count); U64 idx = 0; for EachNode(n, DI_KeyNode, list->first) { array.v[idx] = n->v; idx += 1; } return array; } //////////////////////////////// //~ rjf: Main Layer Initialization internal void di_init(CmdLine *cmdline) { Arena *arena = arena_alloc(); di_shared = push_array(arena, DI_Shared, 1); di_shared->arena = arena; di_shared->key2path_slots_count = 4096; di_shared->key2path_slots = push_array(arena, DI_KeySlot, di_shared->key2path_slots_count); di_shared->key2path_stripes = stripe_array_alloc(arena); di_shared->path2key_slots_count = 4096; di_shared->path2key_slots = push_array(arena, DI_KeySlot, di_shared->path2key_slots_count); di_shared->path2key_stripes = stripe_array_alloc(arena); di_shared->slots_count = 4096; di_shared->slots = push_array(arena, DI_Slot, di_shared->slots_count); di_shared->stripes = stripe_array_alloc(arena); for EachElement(idx, di_shared->req_batches) { di_shared->req_batches[idx].mutex = mutex_alloc(); di_shared->req_batches[idx].arena = arena_alloc(); } U64 signal_pid = 0; String8 signal_pid_string = cmd_line_string(cmdline, str8_lit("signal_pid")); B32 has_parent = 1; if(!try_u64_from_str8_c_rules(signal_pid_string, &signal_pid)) { has_parent = 0; signal_pid = os_get_process_info()->pid; } U64 signal_code = 0; String8 signal_code_string = cmd_line_string(cmdline, str8_lit("signal_code")); try_u64_from_str8_c_rules(signal_code_string, &signal_code); di_shared->conversion_completion_code = signal_code; di_shared->conversion_completion_lock_semaphore_name = str8f(arena, "conversion_completion_lock_pid_%I64u", signal_pid); di_shared->conversion_completion_signal_semaphore_name = str8f(arena, "conversion_completion_signal_pid_%I64u", signal_pid); di_shared->conversion_completion_shared_memory_name = str8f(arena, "conversion_completion_shared_memory_pid_%I64u", signal_pid); if(has_parent) { di_shared->conversion_completion_lock_semaphore = semaphore_open(di_shared->conversion_completion_lock_semaphore_name); di_shared->conversion_completion_signal_semaphore = semaphore_open(di_shared->conversion_completion_signal_semaphore_name); di_shared->conversion_completion_shared_memory = os_shared_memory_open(di_shared->conversion_completion_shared_memory_name); } else { di_shared->conversion_completion_lock_semaphore = semaphore_alloc(1, 1, di_shared->conversion_completion_lock_semaphore_name); di_shared->conversion_completion_signal_semaphore = semaphore_alloc(0, 65536, di_shared->conversion_completion_signal_semaphore_name); di_shared->conversion_completion_shared_memory = os_shared_memory_alloc(KB(4), di_shared->conversion_completion_shared_memory_name); di_shared->conversion_completion_signal_receiver_thread = thread_launch(di_conversion_completion_signal_receiver_thread_entry_point, 0); } di_shared->conversion_completion_shared_memory_base = (U64 *)os_shared_memory_view_open(di_shared->conversion_completion_shared_memory, r1u64(0, KB(4))); di_shared->completion_mutex = mutex_alloc(); di_shared->completion_arena = arena_alloc(); di_shared->event_mutex = mutex_alloc(); di_shared->event_arena = arena_alloc(); } //////////////////////////////// //~ rjf: Path * Timestamp Cache Submission & Lookup internal DI_Key di_key_from_path_timestamp(String8 path, U64 min_timestamp) { //- rjf: unpack key U64 hash = u64_hash_from_str8(path); U64 slot_idx = hash%di_shared->path2key_slots_count; DI_KeySlot *slot = &di_shared->path2key_slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->path2key_stripes, slot_idx); //- rjf: look up key, create if needed DI_Key key = {0}; for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { // rjf: look up node, with this write mode, to find existing key computation B32 found = 0; RWMutexScope(stripe->rw_mutex, write_mode) { DI_KeyPathNode *node = 0; for(DI_KeyPathNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->path, path, 0) && min_timestamp <= n->min_timestamp) { found = 1; node = n; key = node->key; break; } } if(!found && write_mode) { node = stripe->free; if(node) { stripe->free = node->next; } else { node = push_array(stripe->arena, DI_KeyPathNode, 1); } node->path = str8_copy(stripe->arena, path); node->min_timestamp = min_timestamp; node->key = key; DLLPushBack(slot->first, slot->last, node); } } // rjf: found the key? abort if(found) { break; } // rjf: didn't find the key on our read lookup? compute the key before entering // write mode if(!found && !write_mode) { B32 made_key = 0; //- rjf: try to make key from file's contents if(!made_key) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); FileProperties props = os_properties_from_file(file); if(min_timestamp <= props.modified) { //- rjf: PDB magic => use GUID for key if(!made_key) { B32 is_pdb = 0; if(!is_pdb) { read_only local_persist char msf_msf20_magic[] = "Microsoft C/C++ program database 2.00\r\n\x1aJG\0\0"; U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe); if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe))) { is_pdb = 1; } } if(!is_pdb) { read_only local_persist char msf_msf70_magic[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"; U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe); if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe))) { is_pdb = 1; } } if(is_pdb) { // TODO(rjf) } } } os_file_close(file); } //- rjf: fallback: hash from path/timestamp if(!made_key) { made_key = 1; U128 hash = u128_hash_from_seed_str8(min_timestamp, path); MemoryCopy(&key, &hash, Min(sizeof(hash), sizeof(key))); } //- rjf: made key -> store in (key -> path/timestamp) table if(made_key) { U64 key_hash = u64_hash_from_str8(str8_struct(&key)); U64 key_slot_idx = key_hash%di_shared->key2path_slots_count; DI_KeySlot *key_slot = &di_shared->key2path_slots[key_slot_idx]; Stripe *key_stripe = stripe_from_slot_idx(&di_shared->key2path_stripes, key_slot_idx); RWMutexScope(key_stripe->rw_mutex, 1) { DI_KeyPathNode *node = 0; for EachNode(n, DI_KeyPathNode, key_slot->first) { if(di_key_match(n->key, key)) { node = n; break; } } if(node == 0) { node = key_stripe->free; if(node != 0) { key_stripe->free = node->next; } else { node = push_array(key_stripe->arena, DI_KeyPathNode, 1); } DLLPushBack(key_slot->first, key_slot->last, node); node->path = str8_copy(key_stripe->arena, path); node->min_timestamp = min_timestamp; node->key = key; } } } } } return key; } //////////////////////////////// //~ rjf: Debug Info Opening / Closing internal void di_open(DI_Key key) { //- rjf: unpack key U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%di_shared->slots_count; DI_Slot *slot = &di_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->stripes, slot_idx); //- rjf: bump this key's node's refcount; create if needed B32 node_is_new = 0; RWMutexScope(stripe->rw_mutex, 1) { DI_Node *node = 0; for(DI_Node *n = slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key)) { node = n; break; } } if(node == 0) { node_is_new = 1; node = stripe->free; if(node) { stripe->free = node->next; } else { node = push_array_no_zero(stripe->arena, DI_Node, 1); } MemoryZeroStruct(node); DLLPushBack(slot->first, slot->last, node); node->key = key; node->batch_request_counts[1] = 1; } node->refcount += 1; } //- rjf: if new, submit low-priority request to load this key if(node_is_new) { DI_RequestBatch *batch = &di_shared->req_batches[1]; MutexScope(batch->mutex) { DI_RequestNode *n = push_array(batch->arena, DI_RequestNode, 1); SLLQueuePush(batch->first, batch->last, n); n->v.key = key; batch->count += 1; } cond_var_broadcast(async_tick_start_cond_var); ins_atomic_u32_eval_assign(&async_loop_again, 1); } } internal void di_close(DI_Key key, B32 force_closed) { //- rjf: unpack key U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%di_shared->slots_count; DI_Slot *slot = &di_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->stripes, slot_idx); //- rjf: decrement this key's node's refcount; remove if needed B32 node_released = 0; OS_Handle file = {0}; OS_Handle file_map = {0}; FileProperties file_props = {0}; void *file_base = 0; Arena *arena = 0; RWMutexScope(stripe->rw_mutex, 1) { DI_Node *node = 0; for(DI_Node *n = slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key) && ins_atomic_u64_eval(&n->completion_count) > 0) { node = n; break; } } if(node) { if(force_closed) { node->refcount = 0; } else { node->refcount -= 1; } if(node->refcount == 0) { for(;;) { if(access_pt_is_expired(&node->access_pt, .time = 0, .update_idxs = 0)) { node_released = 1; DLLRemove(slot->first, slot->last, node); node->next = stripe->free; stripe->free = node; file = node->file; file_map = node->file_map; file_props = node->file_props; file_base = node->file_base; arena = node->arena; break; } cond_var_wait_rw(stripe->cv, stripe->rw_mutex, 1, max_U64); } } } } //- rjf: release node's resources if needed if(node_released) { ins_atomic_u64_dec_eval(&di_shared->load_count); ins_atomic_u64_inc_eval(&di_shared->load_gen); os_file_map_view_close(file_map, file_base, r1u64(0, file_props.size)); os_file_map_close(file_map); os_file_close(file); if(arena != 0) { arena_release(arena); } } } //////////////////////////////// //~ rjf: Debug Info Lookups internal U64 di_load_gen(void) { U64 result = ins_atomic_u64_eval(&di_shared->load_gen); return result; } internal U64 di_load_count(void) { U64 result = ins_atomic_u64_eval(&di_shared->load_count); return result; } internal DI_KeyArray di_push_all_loaded_keys(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); DI_KeyList list = {0}; { for EachIndex(slot_idx, di_shared->key2path_slots_count) { DI_KeySlot *slot = &di_shared->key2path_slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->key2path_stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 0) { for(DI_KeyPathNode *n = slot->first; n != 0; n = n->next) { DI_KeyNode *dst_n = push_array(scratch.arena, DI_KeyNode, 1); SLLQueuePush(list.first, list.last, dst_n); list.count += 1; dst_n->v = n->key; } } } } DI_KeyArray array = {0}; array.count = list.count; array.v = push_array(arena, DI_Key, array.count); { U64 idx = 0; for EachNode(n, DI_KeyNode, list.first) { array.v[idx] = n->v; idx += 1; } } scratch_end(scratch); return array; } internal RDI_Parsed * di_rdi_from_key(Access *access, DI_Key key, B32 high_priority, U64 endt_us) { RDI_Parsed *rdi = &rdi_parsed_nil; { U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%di_shared->slots_count; DI_Slot *slot = &di_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 0) for(;;) { // rjf: try to grab current results B32 found = 0; B32 need_hi_request = 0; B32 grabbed = 0; for(DI_Node *n = slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key) && ins_atomic_u64_eval(&n->refcount) > 0) { found = 1; if(high_priority && ins_atomic_u64_eval_cond_assign(&n->batch_request_counts[0], 1, 0) == 0) { need_hi_request = 1; } if(ins_atomic_u64_eval(&n->completion_count) > 0) { grabbed = 1; rdi = &n->rdi; access_touch(access, &n->access_pt, stripe->cv); } break; } } // rjf: push high-priority request if needed if(need_hi_request) { DI_RequestBatch *batch = &di_shared->req_batches[0]; MutexScope(batch->mutex) { DI_RequestNode *n = push_array(batch->arena, DI_RequestNode, 1); SLLQueuePush(batch->first, batch->last, n); n->v.key = key; batch->count += 1; } cond_var_broadcast(async_tick_start_cond_var); ins_atomic_u32_eval_assign(&async_loop_again, 1); ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 1); } // rjf: found current results, or out-of-time? abort if(grabbed || os_now_microseconds() >= endt_us) { break; } // rjf: wait on stripe change cond_var_wait_rw(stripe->cv, stripe->rw_mutex, 0, endt_us); } } return rdi; } //////////////////////////////// //~ rjf: Events internal DI_EventList di_get_events(Arena *arena) { DI_EventList dst = {0}; MutexScope(di_shared->event_mutex) { for EachNode(src_n, DI_EventNode, di_shared->events.first) { DI_EventNode *dst_n = push_array(arena, DI_EventNode, 1); MemoryCopyStruct(&dst_n->v, &src_n->v); dst_n->v.string = str8_copy(arena, dst_n->v.string); SLLQueuePush(dst.first, dst.last, dst_n); dst.count += 1; } MemoryZeroStruct(&di_shared->events); arena_clear(di_shared->event_arena); } return dst; } //////////////////////////////// //~ rjf: Asynchronous Tick internal void di_async_tick(void) { Temp scratch = scratch_begin(0, 0); ////////////////////////////// //- rjf: do single-lane update: pop requests, update tasks, gather RDI paths to parse wide // typedef struct ParseTask ParseTask; struct ParseTask { DI_Key key; String8 rdi_path; }; ParseTask *parse_tasks = 0; U64 parse_tasks_count = 0; if(lane_idx() == 0) { typedef struct ParseTaskNode ParseTaskNode; struct ParseTaskNode { ParseTaskNode *next; ParseTask v; }; ParseTaskNode *first_parse_task = 0; ParseTaskNode *last_parse_task = 0; //////////////////////////// //- rjf: pop all requests, high priority first // DI_RequestNode *first_req[2] = {0}; DI_RequestNode *last_req[2] = {0}; for EachElement(idx, di_shared->req_batches) { DI_RequestBatch *b = &di_shared->req_batches[idx]; MutexScope(b->mutex) { for EachNode(n, DI_RequestNode, b->first) { DI_RequestNode *n_copy = push_array(scratch.arena, DI_RequestNode, 1); MemoryCopyStruct(&n_copy->v, &n->v); SLLQueuePush(first_req[idx], last_req[idx], n_copy); } arena_clear(b->arena); b->first = b->last = 0; b->count = 0; } } //////////////////////////// //- rjf: gather all completions // DI_LoadCompletion *first_completion = 0; DI_LoadCompletion *last_completion = 0; MutexScope(di_shared->completion_mutex) { for EachNode(c, DI_LoadCompletion, di_shared->first_completion) { DI_LoadCompletion *dst_c = push_array(scratch.arena, DI_LoadCompletion, 1); SLLQueuePush(first_completion, last_completion, dst_c); dst_c->code = c->code; } arena_clear(di_shared->completion_arena); di_shared->first_completion = di_shared->last_completion = 0; } //////////////////////////// //- rjf: generate load tasks for all unique requests // for EachElement(priority_idx, first_req) { for EachNode(n, DI_RequestNode, first_req[priority_idx]) { // rjf: unpack request DI_Key key = n->v.key; // rjf: determine if this request is a duplicate B32 request_is_duplicate = 1; { U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%di_shared->slots_count; DI_Slot *slot = &di_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 0) { for(DI_Node *n = slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key) && ins_atomic_u64_eval(&n->completion_count) == 0) { request_is_duplicate = (ins_atomic_u64_eval_cond_assign(&n->working_count, 1, 0) != 0); break; } } } } // rjf: if not a duplicate, create new task if(!request_is_duplicate) { DI_LoadTask *t = di_shared->free_load_task; if(t) { SLLStackPop(di_shared->free_load_task); } else { t = push_array_no_zero(di_shared->arena, DI_LoadTask, 1); } MemoryZeroStruct(t); DLLPushBack(di_shared->first_load_task[priority_idx], di_shared->last_load_task[priority_idx], t); t->key = key; } } } //////////////////////////// //- rjf: update tasks: configure, launch if we can, & retire if we can // for EachElement(priority_idx, di_shared->first_load_task) { for(DI_LoadTask *t = di_shared->first_load_task[priority_idx], *next = 0; t != 0; t = next) { next = t->next; //- rjf: unpack key DI_Key key = t->key; U64 key_hash = u64_hash_from_str8(str8_struct(&key)); U64 key_slot_idx = key_hash%di_shared->key2path_slots_count; DI_KeySlot *key_slot = &di_shared->key2path_slots[key_slot_idx]; Stripe *key_stripe = stripe_from_slot_idx(&di_shared->key2path_stripes, key_slot_idx); //- rjf: get key's O.G. path String8 og_path = {0}; U64 og_min_timestamp = 0; RWMutexScope(key_stripe->rw_mutex, 0) { for(DI_KeyPathNode *n = key_slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key)) { og_path = str8_copy(scratch.arena, n->path); og_min_timestamp = n->min_timestamp; break; } } } //- rjf: analyze O.G. debug info if(!t->og_analyzed) { t->og_analyzed = 1; OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, og_path); FileProperties props = os_properties_from_file(file); t->og_size = props.size; U64 rdi_magic_maybe = 0; if(os_file_read_struct(file, 0, &rdi_magic_maybe) == 8 && rdi_magic_maybe == RDI_MAGIC_CONSTANT) { t->og_is_rdi = 1; } os_file_close(file); } U64 og_size = t->og_size; B32 og_is_rdi = t->og_is_rdi; B32 og_is_good = (og_size > 0); //- rjf: compute key's RDI path String8 rdi_path = {0}; { if(og_is_rdi) { rdi_path = og_path; } else { rdi_path = str8f(scratch.arena, "%S.rdi", str8_chop_last_dot(og_path)); } } //- rjf: determine if RDI is stale if(!t->rdi_analyzed) { t->rdi_analyzed = 1; OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, rdi_path); FileProperties props = os_properties_from_file(file); if(props.modified < og_min_timestamp) { t->rdi_is_stale = 1; } else { t->rdi_is_stale = 1; RDI_Header header = {0}; if(os_file_read_struct(file, 0, &header) == sizeof(header)) { t->rdi_is_stale = (header.encoding_version != RDI_ENCODING_VERSION); } } os_file_close(file); } B32 rdi_is_stale = t->rdi_is_stale; //- rjf: calculate thread counts for conversion processes if(!og_is_rdi && rdi_is_stale && t->thread_count == 0) { U64 thread_count = 1; U64 max_thread_count = os_get_system_info()->logical_processor_count/2; if(priority_idx > 0) { max_thread_count = Max(1, max_thread_count/2); } { if(0){} else if(og_size <= MB(4)) {thread_count = 1;} else if(og_size <= MB(256)) {thread_count = max_thread_count/4;} else if(og_size <= MB(512)) {thread_count = max_thread_count/3;} else if(og_size <= GB(1)) {thread_count = max_thread_count/2;} else {thread_count = max_thread_count;} } thread_count = Max(1, thread_count); t->thread_count = thread_count; } //- rjf: determine if there are threads available B32 threads_available = 0; { U64 max_threads = os_get_system_info()->logical_processor_count/2; U64 current_threads = di_shared->conversion_thread_count; U64 needed_threads = (current_threads + t->thread_count); threads_available = (max_threads >= needed_threads); } //- rjf: if this conversion will overwrite an RDI we already have in cache, // then we need to evict the old one from the cache. B32 ready_to_launch_conversion = (threads_available && !og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI_LoadTaskStatus_Active); if(ready_to_launch_conversion) { U64 path2key_hash = u64_hash_from_str8(og_path); U64 path2key_slot_idx = path2key_hash%di_shared->path2key_slots_count; DI_KeySlot *path2key_slot = &di_shared->path2key_slots[path2key_slot_idx]; Stripe *path2key_stripe = stripe_from_slot_idx(&di_shared->path2key_stripes, path2key_slot_idx); RWMutexScope(path2key_stripe->rw_mutex, 0) { // NOTE(rjf): we need to iterate from last -> first, since we want to evict the // most recent key. for(DI_KeyPathNode *n = path2key_slot->last; n != 0; n = n->prev) { if(str8_match(n->path, og_path, 0) && !di_key_match(key, n->key)) { di_close(n->key, 1); } } } } //- rjf: launch conversion processes if(og_is_good && ready_to_launch_conversion) { B32 should_compress = 0; OS_ProcessLaunchParams params = {0}; params.path = os_get_process_info()->binary_path; params.inherit_env = 1; params.consoleless = 1; str8_list_pushf(scratch.arena, ¶ms.cmd_line, "raddbg"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--bin"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--quiet"); if(should_compress) { str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--compress"); } // str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--capture"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--rdi"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--out:%S", rdi_path); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--thread_count:%I64u", t->thread_count); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--signal_pid:%I64u", (U64)os_get_process_info()->pid); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--signal_code:%I64u", (U64)t); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "%S", og_path); ProfMsg("launch creation for %.*s", str8_varg(rdi_path)); t->process = os_process_launch(¶ms); t->status = DI_LoadTaskStatus_Active; di_shared->conversion_process_count += 1; di_shared->conversion_thread_count += t->thread_count; // rjf: send event MutexScope(di_shared->event_mutex) { DI_EventNode *n = push_array(di_shared->event_arena, DI_EventNode, 1); SLLQueuePush(di_shared->events.first, di_shared->events.last, n); di_shared->events.count += 1; n->v.kind = DI_EventKind_ConversionStarted; n->v.string = str8_copy(di_shared->event_arena, rdi_path); } } //- rjf: if active & process has completed, mark as done { U64 exit_code = 0; if(t->status == DI_LoadTaskStatus_Active) { B32 task_is_done = 0; for(DI_LoadCompletion *c = first_completion; c != 0; c = c->next) { if(c->code == (U64)t) { task_is_done = 1; break; } } if(!task_is_done) { task_is_done = os_process_join(t->process, 0, 0); } if(task_is_done) { t->status = DI_LoadTaskStatus_Done; di_shared->conversion_process_count -= 1; di_shared->conversion_thread_count -= t->thread_count; } } } //- rjf: ready to launch, but bad O.G. file -> just immediately mark as done if(!og_is_good && ready_to_launch_conversion) { t->status = DI_LoadTaskStatus_Done; } //- rjf: if the RDI for this task is not stale, then we're already done - mark this // task as done & prepped for storing into the cache if(!rdi_is_stale) { t->status = DI_LoadTaskStatus_Done; } //- rjf: if the RDI for this task *is* stale, but the O.G. path is actually RDI, // then we can't actually re-convert to produce a non-stale RDI. in this case, just // mark as done. if(rdi_is_stale && og_is_rdi) { t->status = DI_LoadTaskStatus_Done; } //- rjf: if task is done, retire & recycle task; gather path to load if(t->status == DI_LoadTaskStatus_Done) { if(!os_handle_match(t->process, os_handle_zero())) MutexScope(di_shared->event_mutex) { DI_EventNode *n = push_array(di_shared->event_arena, DI_EventNode, 1); SLLQueuePush(di_shared->events.first, di_shared->events.last, n); di_shared->events.count += 1; n->v.kind = DI_EventKind_ConversionEnded; n->v.string = str8_copy(di_shared->event_arena, rdi_path); } DLLRemove(di_shared->first_load_task[priority_idx], di_shared->last_load_task[priority_idx], t); SLLStackPush(di_shared->free_load_task, t); ParseTaskNode *n = push_array(scratch.arena, ParseTaskNode, 1); n->v.key = key; n->v.rdi_path = rdi_path; SLLQueuePush(first_parse_task, last_parse_task, n); parse_tasks_count += 1; } } } //////////////////////////// //- rjf: join all parse tasks // parse_tasks = push_array(scratch.arena, ParseTask, parse_tasks_count); { U64 idx = 0; for EachNode(n, ParseTaskNode, first_parse_task) { parse_tasks[idx] = n->v; idx += 1; } } } lane_sync_u64(&parse_tasks, 0); lane_sync_u64(&parse_tasks_count, 0); lane_sync(); ////////////////////////////// //- rjf: do wide load of all prepped RDIs // U64 parse_task_take_counter = 0; U64 *parse_task_take_counter_ptr = 0; if(lane_idx() == 0) { parse_task_take_counter_ptr = &parse_task_take_counter; } lane_sync_u64(&parse_task_take_counter_ptr, 0); { for(;;) { //- rjf: take next task U64 parse_task_idx = ins_atomic_u64_inc_eval(parse_task_take_counter_ptr) - 1; if(parse_task_idx >= parse_tasks_count) { break; } //- rjf: unpack task DI_Key key = parse_tasks[parse_task_idx].key; String8 rdi_path = parse_tasks[parse_task_idx].rdi_path; ProfBegin("parse %.*s", str8_varg(rdi_path)); //- rjf: open file OS_Handle file = {0}; OS_Handle file_map = {0}; FileProperties file_props = {0}; void *file_base = 0; { file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, rdi_path); file_map = os_file_map_open(OS_AccessFlag_Read, file); file_props = os_properties_from_file(file); file_base = os_file_map_view_open(file_map, OS_AccessFlag_Read, r1u64(0, file_props.size)); } //- rjf: do initial parse of rdi RDI_Parsed rdi_parsed_maybe_compressed = rdi_parsed_nil; { RDI_ParseStatus parse_status = rdi_parse((U8 *)file_base, file_props.size, &rdi_parsed_maybe_compressed); (void)parse_status; } //- rjf: decompress & re-parse, if necessary Arena *rdi_parsed_arena = 0; RDI_Parsed rdi_parsed = rdi_parsed_maybe_compressed; { U64 decompressed_size = rdi_decompressed_size_from_parsed(&rdi_parsed_maybe_compressed); if(decompressed_size > file_props.size) { rdi_parsed_arena = arena_alloc(); U8 *decompressed_data = push_array_no_zero(rdi_parsed_arena, U8, decompressed_size); rdi_decompress_parsed(decompressed_data, decompressed_size, &rdi_parsed_maybe_compressed); RDI_ParseStatus parse_status = rdi_parse(decompressed_data, decompressed_size, &rdi_parsed); (void)parse_status; } } //- rjf: commit parsed info to cache { ProfMsg("commit %.*s", str8_varg(rdi_path)); U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%di_shared->slots_count; DI_Slot *slot = &di_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&di_shared->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 1) { DI_Node *node = 0; for(DI_Node *n = slot->first; n != 0; n = n->next) { if(di_key_match(n->key, key)) { node = n; break; } } if(node) { node->file = file; node->file_map = file_map; node->file_props = file_props; node->file_base = file_base; node->arena = rdi_parsed_arena; MemoryCopyStruct(&node->rdi, &rdi_parsed); node->completion_count += 1; node->working_count -= 1; if(node->rdi.raw_data_size != 0) { ins_atomic_u64_inc_eval(&di_shared->load_gen); } ins_atomic_u64_inc_eval(&di_shared->load_count); } else { if(rdi_parsed_arena != 0) { arena_release(rdi_parsed_arena); } os_file_map_view_close(file_map, file_base, r1u64(0, file_props.size)); os_file_map_close(file_map); os_file_close(file); } } cond_var_broadcast(stripe->cv); } ProfEnd(); } } lane_sync(); scratch_end(scratch); } //////////////////////////////// //~ rjf: Conversion Completion Signal Receiver Thread internal void di_signal_completion(void) { semaphore_take(di_shared->conversion_completion_lock_semaphore, max_U64); di_shared->conversion_completion_shared_memory_base[0] = di_shared->conversion_completion_code; semaphore_drop(di_shared->conversion_completion_lock_semaphore); semaphore_drop(di_shared->conversion_completion_signal_semaphore); } internal void di_conversion_completion_signal_receiver_thread_entry_point(void *p) { ThreadNameF("di_conversion_completion_signal_receiver_thread"); for(;;) { if(semaphore_take(di_shared->conversion_completion_signal_semaphore, max_U64)) { // rjf: get the next retired code U64 retired_code = 0; semaphore_take(di_shared->conversion_completion_lock_semaphore, max_U64); retired_code = di_shared->conversion_completion_shared_memory_base[0]; semaphore_drop(di_shared->conversion_completion_lock_semaphore); // rjf: push completion record MutexScope(di_shared->completion_mutex) { DI_LoadCompletion *c = push_array(di_shared->completion_arena, DI_LoadCompletion, 1); SLLQueuePush(di_shared->first_completion, di_shared->last_completion, c); c->code = retired_code; } // rjf: signal async system to resume ProfMsg("signal conversion completion"); ins_atomic_u32_eval_assign(&async_loop_again, 1); ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 1); cond_var_broadcast(async_tick_start_cond_var); } } } //////////////////////////////// //~ rjf: Search Artifact Cache Hooks / Lookups internal AC_Artifact di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { ProfBeginFunction(); Access *access = access_open(); Temp scratch = scratch_begin(0, 0); AC_Artifact artifact = {0}; { //- rjf: unpack key RDI_SectionKind section_kind = RDI_SectionKind_NULL; String8 query = {0}; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, §ion_kind); key_read_off += str8_deserial_read_struct(key, key_read_off, &query.size); query.str = push_array(scratch.arena, U8, query.size); key_read_off += str8_deserial_read(key, key_read_off, query.str, query.size, 1); } //- rjf: gather all debug info keys we'll search on DI_KeyArray keys = {0}; ProfScope("gather all debug info keys we'll search on") { if(lane_idx() == 0) { keys = di_push_all_loaded_keys(scratch.arena); } lane_sync_u64(&keys.v, 0); lane_sync_u64(&keys.count, 0); } //- rjf: map all debug info keys -> RDIs RDI_Parsed **rdis = 0; ProfScope("map all debug info keys -> RDIs") { if(lane_idx() == 0) { rdis = push_array(scratch.arena, RDI_Parsed *, keys.count); } lane_sync_u64(&rdis, 0); { Rng1U64 range = lane_range(keys.count); for EachInRange(idx, range) { rdis[idx] = di_rdi_from_key(access, keys.v[idx], 0, 0); } } } lane_sync(); //- rjf: do wide search on all lanes Arena *arena = arena_alloc(); Arena **arenas = 0; U64 arenas_count = lane_count(); if(lane_idx() == 0) { arenas = push_array(arena, Arena *, arenas_count); } lane_sync_u64(&arenas, 0); arenas[lane_idx()] = arena; DI_SearchItemChunkList *lanes_items = 0; ProfScope("do wide search on all lanes") { if(lane_idx() == 0) { lanes_items = push_array(scratch.arena, DI_SearchItemChunkList, lane_count()); } lane_sync_u64(&lanes_items, 0); { DI_SearchItemChunkList *lane_items = &lanes_items[lane_idx()]; for EachIndex(rdi_idx, keys.count) { DI_Key key = keys.v[rdi_idx]; RDI_Parsed *rdi = rdis[rdi_idx]; // rjf: unpack table info U64 element_count = 0; void *table_base = rdi_section_raw_table_from_kind(rdi, section_kind, &element_count); U64 element_size = rdi_section_element_size_table[section_kind]; // rjf: determine name string index offset, depending on table kind U64 element_name_idx_off = 0; switch(section_kind) { default:{}break; case RDI_SectionKind_Procedures: { element_name_idx_off = OffsetOf(RDI_Procedure, name_string_idx); }break; case RDI_SectionKind_GlobalVariables: { element_name_idx_off = OffsetOf(RDI_GlobalVariable, name_string_idx); }break; case RDI_SectionKind_ThreadVariables: { element_name_idx_off = OffsetOf(RDI_ThreadVariable, name_string_idx); }break; case RDI_SectionKind_UDTs: { // NOTE(rjf): name must be determined from self_type_idx }break; case RDI_SectionKind_SourceFiles: { // NOTE(rjf): name must be determined from file path node chain }break; } Rng1U64 range = lane_range(element_count); for EachInRange(idx, range) { //- rjf: every so often, check if we need to cancel, and cancel if(idx%10000 == 0 && !!ins_atomic_u32_eval(cancel_signal)) { break; } //- rjf: get element, map to string; if empty, continue to next element void *element = (U8 *)table_base + element_size*idx; String8 name = {0}; switch(section_kind) { case RDI_SectionKind_UDTs: { RDI_UDT *udt = (RDI_UDT *)element; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); name.str = rdi_string_from_idx(rdi, type_node->user_defined.name_string_idx, &name.size); name = str8_copy(arena, name); }break; case RDI_SectionKind_SourceFiles: { Temp scratch = scratch_begin(&arena, 1); RDI_SourceFile *file = (RDI_SourceFile *)element; String8List path_parts = {0}; for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(rdi, FilePathNodes, file->file_path_node_idx); fpn != rdi_element_from_name_idx(rdi, FilePathNodes, 0); fpn = rdi_element_from_name_idx(rdi, FilePathNodes, fpn->parent_path_node)) { String8 path_part = {0}; path_part.str = rdi_string_from_idx(rdi, fpn->name_string_idx, &path_part.size); str8_list_push_front(scratch.arena, &path_parts, path_part); } StringJoin join = {0}; join.sep = str8_lit("/"); name = str8_list_join(arena, &path_parts, &join); scratch_end(scratch); }break; default: { U32 name_idx = *(U32 *)((U8 *)element + element_name_idx_off); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, name_idx, &name_size); name = str8(name_base, name_size); }break; } if(name.size == 0) { continue; } //- rjf: fuzzy match against query FuzzyMatchRangeList matches = fuzzy_match_find(arena, query, name); //- rjf: collect if(matches.count == matches.needle_part_count) { DI_SearchItemChunk *chunk = lane_items->last; if(chunk == 0 || chunk->count >= chunk->cap) { chunk = push_array(scratch.arena, DI_SearchItemChunk, 1); chunk->base_idx = lane_items->total_count; chunk->cap = 1024; chunk->count = 0; chunk->v = push_array_no_zero(scratch.arena, DI_SearchItem, chunk->cap); SLLQueuePush(lane_items->first, lane_items->last, chunk); lane_items->chunk_count += 1; } chunk->v[chunk->count].idx = idx; chunk->v[chunk->count].key = key; chunk->v[chunk->count].match_ranges = matches; chunk->v[chunk->count].missed_size = (name.size > matches.total_dim) ? (name.size-matches.total_dim) : 0; chunk->count += 1; lane_items->total_count += 1; } } } } } lane_sync(); //- rjf: join all lane chunk lists DI_SearchItemChunkList *all_items = &lanes_items[0]; if(lane_idx() == 0) ProfScope("join all lane chunk lists") { for(U64 lidx = 1; lidx < lane_count(); lidx += 1) { DI_SearchItemChunkList *dst = all_items; DI_SearchItemChunkList *to_push = &lanes_items[lidx]; for EachNode(n, DI_SearchItemChunk, to_push->first) { n->base_idx += dst->total_count; } if(dst->first && to_push->first) { dst->last->next = to_push->first; dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; } else if(dst->first == 0) { MemoryCopyStruct(dst, to_push); } MemoryZeroStruct(to_push); } } lane_sync(); //- rjf: decide if we cancelled B32 cancelled = 0; if(lane_idx() == 0 && !!ins_atomic_u32_eval(cancel_signal)) { cancelled = 1; } lane_sync_u64(&cancelled, 0); //- rjf: produce sort records typedef struct SortRecord SortRecord; struct SortRecord { U64 key; DI_SearchItem *item; }; U64 sort_records_count = all_items->total_count; SortRecord *sort_records = 0; SortRecord *sort_records__swap = 0; if(!cancelled) ProfScope("produce sort records") { if(lane_idx() == 0) { sort_records = push_array_no_zero(scratch.arena, SortRecord, sort_records_count); } if(lane_idx() == lane_from_task_idx(1)) { sort_records__swap = push_array_no_zero(scratch.arena, SortRecord, sort_records_count); } lane_sync_u64(&sort_records, 0); lane_sync_u64(&sort_records__swap, lane_from_task_idx(1)); for EachNode(n, DI_SearchItemChunk, all_items->first) { Rng1U64 range = lane_range(n->count); U64 dst_idx = n->base_idx + range.min; for EachInRange(n_idx, range) { DI_SearchItem *item = &n->v[n_idx]; sort_records[dst_idx].item = item; sort_records[dst_idx].key = (((item->missed_size & 0xffffffffull) << 32) | (u64_hash_from_seed_str8(item->idx, str8_struct(&key)) & 0xffffffffull)); dst_idx += 1; } } } lane_sync(); //- rjf: sort records if(!cancelled) ProfScope("sort records") { //- rjf: set up common data U64 bits_per_digit = 8; U64 digits_count = 64 / bits_per_digit; U64 num_possible_values_per_digit = 1 << bits_per_digit; U32 **lanes_digit_counts = 0; U32 **lanes_digit_offsets = 0; if(lane_idx() == 0) { lanes_digit_counts = push_array(scratch.arena, U32 *, lane_count()); lanes_digit_offsets = push_array(scratch.arena, U32 *, lane_count()); } lane_sync_u64(&lanes_digit_counts, 0); lane_sync_u64(&lanes_digit_offsets, 0); //- rjf: set up this lane lanes_digit_counts[lane_idx()] = push_array(scratch.arena, U32, num_possible_values_per_digit); lanes_digit_offsets[lane_idx()] = push_array(scratch.arena, U32, num_possible_values_per_digit); SortRecord *src = sort_records; SortRecord *dst = sort_records__swap; U64 count = sort_records_count; //- rjf: do all per-digit sorts for EachIndex(digit_idx, digits_count) { // rjf: count digit value occurrences per-lane { U32 *digit_counts = lanes_digit_counts[lane_idx()]; MemoryZero(digit_counts, sizeof(digit_counts[0])*num_possible_values_per_digit); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { SortRecord *r = &src[idx]; U16 digit_value = (U16)(U8)(r->key >> (digit_idx*bits_per_digit)); digit_counts[digit_value] += 1; } } lane_sync(); // rjf: compute thread * digit value *relative* offset table { Rng1U64 range = lane_range(num_possible_values_per_digit); for EachInRange(value_idx, range) { U64 layout_off = 0; for EachIndex(lane_idx, lane_count()) { lanes_digit_offsets[lane_idx][value_idx] = layout_off; layout_off += lanes_digit_counts[lane_idx][value_idx]; } } } lane_sync(); // rjf: convert relative offsets -> absolute offsets if(lane_idx() == 0) { U64 last_off = 0; U64 num_of_nonzero_digit = 0; for EachIndex(value_idx, num_possible_values_per_digit) { for EachIndex(lane_idx, lane_count()) { lanes_digit_offsets[lane_idx][value_idx] += last_off; } last_off = lanes_digit_offsets[lane_count()-1][value_idx] + lanes_digit_counts[lane_count()-1][value_idx]; } // NOTE(rjf): required that: (last_off == element_count) } lane_sync(); // rjf: move { U32 *lane_digit_offsets = lanes_digit_offsets[lane_idx()]; Rng1U64 range = lane_range(count); for EachInRange(idx, range) { SortRecord *src_r = &src[idx]; U16 digit_value = (U16)(U8)(src_r->key >> (digit_idx*bits_per_digit)); U64 dst_off = lane_digit_offsets[digit_value]; lane_digit_offsets[digit_value] += 1; MemoryCopyStruct(&dst[dst_off], src_r); } } lane_sync(); // rjf: swap { SortRecord *swap = src; src = dst; dst = swap; } } } lane_sync(); //- rjf: produce final array DI_SearchItemArray items = {0}; if(!cancelled) ProfScope("produce final array") { if(lane_idx() == 0) { items.count = all_items->total_count; items.v = push_array_no_zero(arena, DI_SearchItem, items.count); } lane_sync_u64(&items.count, 0); lane_sync_u64(&items.v, 0); Rng1U64 range = lane_range(sort_records_count); for EachInRange(idx, range) { SortRecord *record = &sort_records[idx]; DI_SearchItem *dst_item = &items.v[idx]; MemoryCopyStruct(dst_item, record->item); } } lane_sync(); //- rjf: bundle as artifact if(!cancelled) { artifact.u64[0] = (U64)arenas; artifact.u64[1] = arenas_count; artifact.u64[2] = (U64)items.v; artifact.u64[3] = items.count; } //- rjf: release results on cancel else { arena_release(arena); } } scratch_end(scratch); access_close(access); ProfEnd(); return artifact; } internal void di_search_artifact_destroy(AC_Artifact artifact) { Temp scratch = scratch_begin(0, 0); Arena **arenas = (Arena **)artifact.u64[0]; U64 arenas_count = artifact.u64[1]; Arena **arenas_copy = push_array(scratch.arena, Arena *, arenas_count); MemoryCopy(arenas_copy, arenas, sizeof(Arena *) * arenas_count); for EachIndex(idx, arenas_count) { if(arenas_copy[idx]) { arena_release(arenas_copy[idx]); } } scratch_end(scratch); } internal DI_SearchItemArray di_search_item_array_from_target_query(Access *access, RDI_SectionKind target, String8 query, U64 endt_us, B32 *stale_out) { DI_SearchItemArray result = {0}; { Temp scratch = scratch_begin(0, 0); // rjf: form key String8List key_parts = {0}; str8_list_push(scratch.arena, &key_parts, str8_struct(&target)); str8_list_push(scratch.arena, &key_parts, str8_struct(&query.size)); str8_list_push(scratch.arena, &key_parts, query); String8 key = str8_list_join(scratch.arena, &key_parts, 0); // rjf: get artifact AC_Artifact artifact = ac_artifact_from_key(access, key, di_search_artifact_create, di_search_artifact_destroy, endt_us, .gen = di_load_gen(), .flags = AC_Flag_Wide, .evict_threshold_us = 100000, .stale_out = stale_out); // rjf: unpack artifact result.v = (DI_SearchItem *)artifact.u64[2]; result.count = artifact.u64[3]; scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: Match Artifact Cache Hooks / Lookups internal AC_Artifact di_match_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); //- rjf: unpack key U64 index = 0; String8 name = {0}; DI_Key preferred_key = {0}; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &index); key_read_off += str8_deserial_read_struct(key, key_read_off, &preferred_key); key_read_off += str8_deserial_read_struct(key, key_read_off, &name.size); name.str = push_array_no_zero(scratch.arena, U8, name.size); key_read_off += str8_deserial_read(key, key_read_off, name.str, name.size, 1); } //- rjf: get all loaded keys DI_KeyArray dbgi_keys = di_push_all_loaded_keys(scratch.arena); //- rjf: take cancellation signal B32 cancelled = 0; if(lane_idx() == 0) { cancelled = ins_atomic_u32_eval(cancel_signal); } lane_sync_u64(&cancelled, 0); //- rjf: wide search across all debug infos DI_Match *lane_matches = 0; if(!cancelled) { if(lane_idx() == 0) { lane_matches = push_array(scratch.arena, DI_Match, lane_count()); } lane_sync_u64(&lane_matches, 0); { read_only local_persist RDI_NameMapKind name_map_kinds[] = { RDI_NameMapKind_GlobalVariables, RDI_NameMapKind_ThreadVariables, RDI_NameMapKind_Constants, RDI_NameMapKind_Procedures, RDI_NameMapKind_Types, }; read_only local_persist RDI_SectionKind name_map_section_kinds[] = { RDI_SectionKind_GlobalVariables, RDI_SectionKind_ThreadVariables, RDI_SectionKind_Constants, RDI_SectionKind_Procedures, RDI_SectionKind_TypeNodes, }; Rng1U64 range = lane_range(dbgi_keys.count); for EachInRange(dbgi_idx, range) { Access *access = access_open(); { DI_Key dbgi_key = dbgi_keys.v[dbgi_idx]; RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); for EachElement(name_map_kind_idx, name_map_kinds) { RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]); RDI_ParsedNameMap parsed_name_map = {0}; rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *map_node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size); U32 num = 0; U32 *run = rdi_matches_from_map_node(rdi, map_node, &num); if(num != 0) { lane_matches[lane_idx()].key = dbgi_key; lane_matches[lane_idx()].section_kind = name_map_section_kinds[name_map_kind_idx]; lane_matches[lane_idx()].idx = run[num-1]; } } } access_close(access); } } } lane_sync(); //- rjf: pick match DI_Match match = {0}; if(lane_matches != 0) { for EachIndex(idx, lane_count()) { if(lane_matches[idx].idx != 0) { match = lane_matches[idx]; if(di_key_match(di_key_zero(), preferred_key) || di_key_match(match.key, preferred_key)) { break; } } } } //- rjf: package as artifact AC_Artifact artifact = {0}; { StaticAssert(ArrayCount(artifact.u64) >= 4, artifact_size_check); artifact.u64[0] = match.key.u64[0]; artifact.u64[1] = match.key.u64[1]; artifact.u64[2] = match.section_kind; artifact.u64[3] = match.idx; } lane_sync(); scratch_end(scratch); ProfEnd(); return artifact; } internal DI_Match di_match_from_string(String8 string, U64 index, DI_Key preferred_dbgi_key, U64 endt_us) { DI_Match result = {0}; Access *access = access_open(); Temp scratch = scratch_begin(0, 0); { String8List key_parts = {0}; str8_list_push(scratch.arena, &key_parts, str8_struct(&index)); str8_list_push(scratch.arena, &key_parts, str8_struct(&preferred_dbgi_key)); str8_list_push(scratch.arena, &key_parts, str8_struct(&string.size)); str8_list_push(scratch.arena, &key_parts, string); String8 key = str8_list_join(scratch.arena, &key_parts, 0); U64 dbgi_count = di_load_count(); B32 wide = (dbgi_count > 256); AC_Artifact artifact = ac_artifact_from_key(access, key, di_match_artifact_create, 0, endt_us, .flags = wide ? AC_Flag_Wide : 0, .gen = di_load_gen(), .evict_threshold_us = wide ? 20000000 : 10000000); result.key.u64[0] = artifact.u64[0]; result.key.u64[1] = artifact.u64[1]; result.section_kind = artifact.u64[2]; result.idx = artifact.u64[3]; } scratch_end(scratch); access_close(access); return result; } ================================================ FILE: src/dbg_info/dbg_info.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBG_INFO_H #define DBG_INFO_H //////////////////////////////// //~ rjf: Unique Debug Info Key typedef struct DI_Key DI_Key; struct DI_Key { U64 u64[2]; }; typedef struct DI_KeyNode DI_KeyNode; struct DI_KeyNode { DI_KeyNode *next; DI_Key v; }; typedef struct DI_KeyList DI_KeyList; struct DI_KeyList { DI_KeyNode *first; DI_KeyNode *last; U64 count; }; typedef struct DI_KeyArray DI_KeyArray; struct DI_KeyArray { DI_Key *v; U64 count; }; //////////////////////////////// //~ rjf: Debug Info Path / Timestamp => Key Cache Types typedef struct DI_KeyPathNode DI_KeyPathNode; struct DI_KeyPathNode { DI_KeyPathNode *next; DI_KeyPathNode *prev; String8 path; U64 min_timestamp; DI_Key key; }; typedef struct DI_KeySlot DI_KeySlot; struct DI_KeySlot { DI_KeyPathNode *first; DI_KeyPathNode *last; }; //////////////////////////////// //~ rjf: Debug Info Cache Types typedef struct DI_Node DI_Node; struct DI_Node { // rjf: links DI_Node *next; DI_Node *prev; // rjf: key DI_Key key; // rjf: value OS_Handle file; OS_Handle file_map; void *file_base; FileProperties file_props; Arena *arena; RDI_Parsed rdi; // rjf: metadata AccessPt access_pt; U64 refcount; U64 batch_request_counts[2]; U64 working_count; U64 completion_count; }; typedef struct DI_Slot DI_Slot; struct DI_Slot { DI_Node *first; DI_Node *last; }; //////////////////////////////// //~ rjf: Requests typedef struct DI_Request DI_Request; struct DI_Request { DI_Key key; }; typedef struct DI_RequestNode DI_RequestNode; struct DI_RequestNode { DI_RequestNode *next; DI_Request v; }; typedef struct DI_RequestBatch DI_RequestBatch; struct DI_RequestBatch { Mutex mutex; Arena *arena; DI_RequestNode *first; DI_RequestNode *last; U64 count; }; //////////////////////////////// //~ rjf: Load Tasks typedef enum DI_LoadTaskStatus { DI_LoadTaskStatus_Null, DI_LoadTaskStatus_Active, DI_LoadTaskStatus_Done, } DI_LoadTaskStatus; typedef struct DI_LoadTask DI_LoadTask; struct DI_LoadTask { DI_LoadTask *next; DI_LoadTask *prev; DI_Key key; DI_LoadTaskStatus status; B32 og_analyzed; B32 og_is_rdi; U64 og_size; B32 rdi_analyzed; B32 rdi_is_stale; U64 thread_count; OS_Handle process; }; typedef struct DI_LoadCompletion DI_LoadCompletion; struct DI_LoadCompletion { DI_LoadCompletion *next; U64 code; }; //////////////////////////////// //~ rjf: Search Types typedef struct DI_SearchItem DI_SearchItem; struct DI_SearchItem { U64 idx; DI_Key key; U64 missed_size; FuzzyMatchRangeList match_ranges; }; typedef struct DI_SearchItemChunk DI_SearchItemChunk; struct DI_SearchItemChunk { DI_SearchItemChunk *next; U64 base_idx; DI_SearchItem *v; U64 count; U64 cap; }; typedef struct DI_SearchItemChunkList DI_SearchItemChunkList; struct DI_SearchItemChunkList { DI_SearchItemChunk *first; DI_SearchItemChunk *last; U64 chunk_count; U64 total_count; }; typedef struct DI_SearchItemArray DI_SearchItemArray; struct DI_SearchItemArray { DI_SearchItem *v; U64 count; }; //////////////////////////////// //~ rjf: Match Types typedef struct DI_Match DI_Match; struct DI_Match { DI_Key key; RDI_SectionKind section_kind; U32 idx; }; //////////////////////////////// //~ rjf: Events typedef enum DI_EventKind { DI_EventKind_Null, DI_EventKind_ConversionStarted, DI_EventKind_ConversionEnded, DI_EventKind_COUNT } DI_EventKind; typedef struct DI_Event DI_Event; struct DI_Event { DI_EventKind kind; String8 string; }; typedef struct DI_EventNode DI_EventNode; struct DI_EventNode { DI_EventNode *next; DI_Event v; }; typedef struct DI_EventList DI_EventList; struct DI_EventList { DI_EventNode *first; DI_EventNode *last; U64 count; }; //////////////////////////////// //~ rjf: Shared State typedef struct DI_Shared DI_Shared; struct DI_Shared { Arena *arena; U64 load_gen; U64 load_count; // rjf: key -> path cache U64 key2path_slots_count; DI_KeySlot *key2path_slots; StripeArray key2path_stripes; // rjf: path -> key cache U64 path2key_slots_count; DI_KeySlot *path2key_slots; StripeArray path2key_stripes; // rjf: debug info cache U64 slots_count; DI_Slot *slots; StripeArray stripes; // rjf: requests DI_RequestBatch req_batches[2]; // [0] -> high priority, [1] -> low priority // rjf: conversion tasks DI_LoadTask *first_load_task[2]; DI_LoadTask *last_load_task[2]; DI_LoadTask *free_load_task; U64 conversion_process_count; U64 conversion_thread_count; // rjf: conversion completion receiving thread U64 conversion_completion_code; String8 conversion_completion_lock_semaphore_name; String8 conversion_completion_signal_semaphore_name; String8 conversion_completion_shared_memory_name; Semaphore conversion_completion_lock_semaphore; Semaphore conversion_completion_signal_semaphore; OS_Handle conversion_completion_shared_memory; U64 *conversion_completion_shared_memory_base; Thread conversion_completion_signal_receiver_thread; // rjf: completion batch Mutex completion_mutex; Arena *completion_arena; DI_LoadCompletion *first_completion; DI_LoadCompletion *last_completion; // rjf: events Mutex event_mutex; Arena *event_arena; DI_EventList events; }; //////////////////////////////// //~ rjf: Globals global DI_Shared *di_shared = 0; //////////////////////////////// //~ rjf: Helpers internal DI_Key di_key_zero(void); internal B32 di_key_match(DI_Key a, DI_Key b); internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key key); internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list); //////////////////////////////// //~ rjf: Main Layer Initialization internal void di_init(CmdLine *cmdline); //////////////////////////////// //~ rjf: Path * Timestamp Cache Submission & Lookup internal DI_Key di_key_from_path_timestamp(String8 path, U64 min_timestamp); //////////////////////////////// //~ rjf: Debug Info Opening / Closing internal void di_open(DI_Key key); internal void di_close(DI_Key key, B32 force_closed); //////////////////////////////// //~ rjf: Debug Info Lookups internal U64 di_load_gen(void); internal U64 di_load_count(void); internal DI_KeyArray di_push_all_loaded_keys(Arena *arena); internal RDI_Parsed *di_rdi_from_key(Access *access, DI_Key key, B32 high_priority, U64 endt_us); //////////////////////////////// //~ rjf: Events internal DI_EventList di_get_events(Arena *arena); //////////////////////////////// //~ rjf: Asynchronous Tick internal void di_async_tick(void); //////////////////////////////// //~ rjf: Conversion Completion Signal Receiver Thread internal void di_signal_completion(void); internal void di_conversion_completion_signal_receiver_thread_entry_point(void *p); //////////////////////////////// //~ rjf: Search Artifact Cache Hooks / Lookups internal AC_Artifact di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void di_search_artifact_destroy(AC_Artifact artifact); internal DI_SearchItemArray di_search_item_array_from_target_query(Access *access, RDI_SectionKind target, String8 query, U64 endt_us, B32 *stale_out); //////////////////////////////// //~ rjf: Match Artifact Cache Hooks / Lookups internal AC_Artifact di_match_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal DI_Match di_match_from_string(String8 string, U64 index, DI_Key preferred_dbgi_key, U64 endt_us); #endif // DBG_INFO_H ================================================ FILE: src/demon/demon_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "generated/demon.meta.c" //////////////////////////////// //~ rjf: Basic Type Functions (Helpers, Implemented Once) //- rjf: handles internal DMN_Handle dmn_handle_zero(void) { DMN_Handle h = {0}; return h; } internal B32 dmn_handle_match(DMN_Handle a, DMN_Handle b) { return a.u32[0] == b.u32[0] && a.u32[1] == b.u32[1]; } //- rjf: trap chunk lists internal void dmn_trap_chunk_list_push(Arena *arena, DMN_TrapChunkList *list, U64 cap, DMN_Trap *trap) { DMN_TrapChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, DMN_TrapChunkNode, 1); node->cap = cap; node->v = push_array_no_zero(arena, DMN_Trap, node->cap); SLLQueuePush(list->first, list->last, node); list->node_count += 1; } MemoryCopyStruct(&node->v[node->count], trap); node->count += 1; list->trap_count += 1; } internal void dmn_trap_chunk_list_concat_in_place(DMN_TrapChunkList *dst, DMN_TrapChunkList *to_push) { if(dst->last == 0) { MemoryCopyStruct(dst, to_push); } else if(to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->node_count += to_push->node_count; dst->trap_count += to_push->trap_count; } MemoryZeroStruct(to_push); } internal void dmn_trap_chunk_list_concat_shallow_copy(Arena *arena, DMN_TrapChunkList *dst, DMN_TrapChunkList *to_push) { for(DMN_TrapChunkNode *src_n = to_push->first; src_n != 0; src_n = src_n->next) { DMN_TrapChunkNode *dst_n = push_array(arena, DMN_TrapChunkNode, 1); dst_n->v = src_n->v; dst_n->cap = src_n->cap; dst_n->count = src_n->count; SLLQueuePush(dst->first, dst->last, dst_n); dst->node_count += 1; dst->trap_count += dst_n->count; } } //- rjf: handle lists internal void dmn_handle_list_push(Arena *arena, DMN_HandleList *list, DMN_Handle handle) { DMN_HandleNode *node = push_array(arena, DMN_HandleNode, 1); SLLQueuePush(list->first, list->last, node); node->v = handle; list->count += 1; } internal DMN_HandleArray dmn_handle_array_from_list(Arena *arena, DMN_HandleList *list) { DMN_HandleArray array = {0}; array.count = list->count; array.handles = push_array_no_zero(arena, DMN_Handle, array.count); U64 idx = 0; for(DMN_HandleNode *n = list->first; n != 0; n = n->next, idx += 1) { array.handles[idx] = n->v; } return array; } internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *src) { DMN_HandleArray dst = {0}; dst.count = src->count; dst.handles = push_array_no_zero(arena, DMN_Handle, dst.count); MemoryCopy(dst.handles, src->handles, sizeof(DMN_Handle)*dst.count); return dst; } //- rjf: event list building internal DMN_Event * dmn_event_list_push(Arena *arena, DMN_EventList *list) { DMN_EventNode *n = push_array(arena, DMN_EventNode, 1); SLLQueuePush(list->first, list->last, n); list->count += 1; DMN_Event *result = &n->v; return result; } //////////////////////////////// //~ rjf: Thread Reading Helper Functions (Helpers, Implemented Once) internal U64 dmn_rip_from_thread(DMN_Handle thread) { U64 result = 0; Temp scratch = scratch_begin(0, 0); { Arch arch = dmn_arch_from_thread(thread); U64 reg_block_size = regs_block_size_from_arch(arch); void *reg_block = push_array(scratch.arena, U8, reg_block_size); dmn_thread_read_reg_block(thread, reg_block); result = regs_rip_from_arch_block(arch, reg_block); } scratch_end(scratch); return result; } internal U64 dmn_rsp_from_thread(DMN_Handle thread) { U64 result = 0; Temp scratch = scratch_begin(0, 0); { Arch arch = dmn_arch_from_thread(thread); U64 reg_block_size = regs_block_size_from_arch(arch); void *reg_block = push_array(scratch.arena, U8, reg_block_size); dmn_thread_read_reg_block(thread, reg_block); result = regs_rsp_from_arch_block(arch, reg_block); } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr) { Temp scratch = scratch_begin(&arena, 1); String8List block_list = {0}; for(U64 cursor = addr, stride = 256; ; cursor += stride) { U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride); U64 read_size = dmn_process_read(process, r1u64(cursor, cursor + stride), raw_block); String8 block = str8_cstring_capped(raw_block, raw_block + read_size); str8_list_push(scratch.arena, &block_list, block); if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0)) { break; } } String8 result = str8_list_join(arena, &block_list, 0); scratch_end(scratch); return result; } internal String8 dmn_process_read_block(Arena *arena, DMN_Handle process, Rng1U64 vrange) { String8 block = {0}; void *raw = dmn_process_read_raw(arena, process, vrange); if(raw) { block = str8(raw, dim_1u64(vrange)); } return block; } internal void * dmn_process_read_raw(Arena *arena, DMN_Handle process, Rng1U64 vrange) { Temp temp = temp_begin(arena); void *buffer = push_array(arena, U8, dim_1u64(vrange)); U64 read_size = dmn_process_read(process, vrange, buffer); if(read_size != dim_1u64(vrange)) { buffer = 0; temp_end(temp); } return buffer; } ================================================ FILE: src/demon/demon_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_H #define DEMON_CORE_H //////////////////////////////// //~ rjf: Control-Thread-Only Context // // An instance of this struct must ONLY be returned by dmn_ctrl_begin, and only // used by the thread which called it. All APIs which can ONLY run on the // control thread, which blocks to control & receive events, will take this // parameter. All other APIs can be called from any thread. typedef struct DMN_CtrlCtx DMN_CtrlCtx; struct DMN_CtrlCtx { U64 u64[1]; }; //////////////////////////////// //~ rjf: Handle Types typedef union DMN_Handle DMN_Handle; union DMN_Handle { U32 u32[2]; U64 u64[1]; }; typedef struct DMN_HandleNode DMN_HandleNode; struct DMN_HandleNode { DMN_HandleNode *next; DMN_Handle v; }; typedef struct DMN_HandleList DMN_HandleList; struct DMN_HandleList { DMN_HandleNode *first; DMN_HandleNode *last; U64 count; }; typedef struct DMN_HandleArray DMN_HandleArray; struct DMN_HandleArray { DMN_Handle *handles; U64 count; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/demon.meta.h" //////////////////////////////// //~ rjf: Event Types typedef struct DMN_Event DMN_Event; struct DMN_Event { DMN_EventKind kind; DMN_ErrorKind error_kind; DMN_MemoryEventKind memory_kind; DMN_ExceptionKind exception_kind; DMN_Handle process; DMN_Handle thread; DMN_Handle module; Arch arch; U64 address; U64 size; String8 string; U32 code; // code gives pid & tid on CreateProcess and CreateThread (respectfully) U32 flags; // DMN_TrapFlags, if `DMN_EventKind_SetBreakpoint` S32 signo; S32 sigcode; Rng1U64 elf_phdr_vrange; U64 elf_phdr_entsize; U64 instruction_pointer; U64 stack_pointer; U64 user_data; B32 exception_repeated; }; typedef struct DMN_EventNode DMN_EventNode; struct DMN_EventNode { DMN_EventNode *next; DMN_Event v; }; typedef struct DMN_EventList DMN_EventList; struct DMN_EventList { DMN_EventNode *first; DMN_EventNode *last; U64 count; }; //////////////////////////////// //~ rjf: Run Control Types typedef U32 DMN_TrapFlags; enum { DMN_TrapFlag_BreakOnWrite = (1<<0), DMN_TrapFlag_BreakOnRead = (1<<1), DMN_TrapFlag_BreakOnExecute = (1<<2), }; typedef struct DMN_Trap DMN_Trap; struct DMN_Trap { DMN_Handle process; U64 vaddr; U64 id; DMN_TrapFlags flags; U32 size; }; typedef struct DMN_TrapChunkNode DMN_TrapChunkNode; struct DMN_TrapChunkNode { DMN_TrapChunkNode *next; DMN_Trap *v; U64 cap; U64 count; }; typedef struct DMN_TrapChunkList DMN_TrapChunkList; struct DMN_TrapChunkList { DMN_TrapChunkNode *first; DMN_TrapChunkNode *last; U64 node_count; U64 trap_count; }; typedef struct DMN_ActiveTrap DMN_ActiveTrap; struct DMN_ActiveTrap { DMN_Trap *trap; U8 swap_byte; DMN_ActiveTrap *next; }; typedef struct DMN_RunCtrls DMN_RunCtrls; struct DMN_RunCtrls { DMN_Handle priority_thread; DMN_Handle single_step_thread; B8 ignore_previous_exception; B8 run_entities_are_unfrozen; B8 run_entities_are_processes; DMN_Handle *run_entities; U64 run_entity_count; DMN_TrapChunkList traps; }; //////////////////////////////// //~ rjf: System Process Listing Types typedef struct DMN_ProcessIter DMN_ProcessIter; struct DMN_ProcessIter { U64 v[2]; }; typedef struct DMN_ProcessInfo DMN_ProcessInfo; struct DMN_ProcessInfo { String8 name; U32 pid; }; //////////////////////////////// //~ rjf: Basic Type Functions (Helpers, Implemented Once) //- rjf: handles internal DMN_Handle dmn_handle_zero(void); internal B32 dmn_handle_match(DMN_Handle a, DMN_Handle b); //- rjf: trap chunk lists internal void dmn_trap_chunk_list_push(Arena *arena, DMN_TrapChunkList *list, U64 cap, DMN_Trap *trap); internal void dmn_trap_chunk_list_concat_in_place(DMN_TrapChunkList *dst, DMN_TrapChunkList *to_push); internal void dmn_trap_chunk_list_concat_shallow_copy(Arena *arena, DMN_TrapChunkList *dst, DMN_TrapChunkList *to_push); //- rjf: handle lists internal void dmn_handle_list_push(Arena *arena, DMN_HandleList *list, DMN_Handle handle); internal DMN_HandleArray dmn_handle_array_from_list(Arena *arena, DMN_HandleList *list); internal DMN_HandleArray dmn_handle_array_copy(Arena *arena, DMN_HandleArray *src); //- rjf: event list building internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list); //////////////////////////////// //~ rjf: Thread Reading Helper Functions (Helpers, Implemented Once) internal U64 dmn_rip_from_thread(DMN_Handle thread); internal U64 dmn_rsp_from_thread(DMN_Handle thread); //////////////////////////////// //~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr); internal String8 dmn_process_read_block(Arena *arena, DMN_Handle process, Rng1U64 vrange); internal void * dmn_process_read_raw(Arena *arena, DMN_Handle process, Rng1U64 vrange); //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) internal void dmn_init(void); //////////////////////////////// //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS) internal DMN_CtrlCtx *dmn_ctrl_begin(void); internal void dmn_ctrl_exclusive_access_begin(void); internal void dmn_ctrl_exclusive_access_end(void); #define DMN_CtrlExclusiveAccessScope DeferLoop(dmn_ctrl_exclusive_access_begin(), dmn_ctrl_exclusive_access_end()) internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params); internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid); internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code); internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process); internal DMN_EventList dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls); //////////////////////////////// //~ rjf: @dmn_os_hooks Halting (Implemented Per-OS) internal void dmn_halt(U64 code, U64 user_data); //////////////////////////////// //~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS) //- rjf: non-blocking-control-thread access barriers internal B32 dmn_access_open(void); internal void dmn_access_close(void); #define DMN_AccessScope DeferLoopChecked(dmn_access_open(), dmn_access_close()) //- rjf: processes internal U64 dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size); internal void dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size); internal void dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size); internal void dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size); internal void dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags); internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst); internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src); #define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) //- rjf: threads internal Arch dmn_arch_from_thread(DMN_Handle handle); internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle); internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle); internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block); internal B32 dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block); //- rjf: system process listing internal void dmn_process_iter_begin(DMN_ProcessIter *iter); internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out); internal void dmn_process_iter_end(DMN_ProcessIter *iter); #endif // DEMON_CORE_H ================================================ FILE: src/demon/demon_core.mdesk ================================================ //////////////////////////////// //~ rjf: Event Kind Tables @table(name) DMN_EventKindTable: { {Null} {Error} {HandshakeComplete} {CreateProcess} {ExitProcess} {CreateThread} {ExitThread} {LoadModule} {UnloadModule} {Breakpoint} {Trap} {SingleStep} {Exception} {Halt} {Memory} {DebugString} {SetThreadName} {SetThreadColor} {SetBreakpoint} {UnsetBreakpoint} {SetVAddrRangeNote} } @table(name) DMN_ErrorKindTable: { {Null} {NotAttached} {UnexpectedFailure} {InvalidHandle} } @table(name) DMN_MemoryEventKindTable: { {Null} {Commit} {Reserve} {Decommit} {Release} } @table(name) DMN_ExceptionKindTable: { {Null} {MemoryRead} {MemoryWrite} {MemoryExecute} {CppThrow} } //////////////////////////////// //~ rjf: Generators @enum DMN_EventKind: { @expand(DMN_EventKindTable a) `$(a.name)`, COUNT } @data(String8) dmn_event_kind_string_table: { @expand(DMN_EventKindTable a) `str8_lit_comp("$(a.name)")` } @enum DMN_ErrorKind: { @expand(DMN_ErrorKindTable a) `$(a.name)`, COUNT } @enum DMN_MemoryEventKind: { @expand(DMN_MemoryEventKindTable a) `$(a.name)`, COUNT } @enum DMN_ExceptionKind: { @expand(DMN_ExceptionKindTable a) `$(a.name)`, COUNT } @data(String8) dmn_exception_kind_string_table: { @expand(DMN_ExceptionKindTable a) `str8_lit_comp("$(a.name)")` } ================================================ FILE: src/demon/demon_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "demon/demon_core.c" #if OS_WINDOWS # include "demon/win32/demon_core_win32.c" #elif OS_LINUX # include "demon/linux/demon_core_linux.c" #else # error Demon layer backend not defined for this operating system. #endif ================================================ FILE: src/demon/demon_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_INC_H #define DEMON_INC_H #include "demon/demon_core.h" #if OS_WINDOWS # include "demon/win32/demon_core_win32.h" #elif OS_LINUX # include "demon/linux/demon_core_linux.h" #else # error Demon layer backend not defined for this operating system. #endif #endif // DEMON_INC_H ================================================ FILE: src/demon/generated/demon.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 dmn_event_kind_string_table[21] = { str8_lit_comp("Null"), str8_lit_comp("Error"), str8_lit_comp("HandshakeComplete"), str8_lit_comp("CreateProcess"), str8_lit_comp("ExitProcess"), str8_lit_comp("CreateThread"), str8_lit_comp("ExitThread"), str8_lit_comp("LoadModule"), str8_lit_comp("UnloadModule"), str8_lit_comp("Breakpoint"), str8_lit_comp("Trap"), str8_lit_comp("SingleStep"), str8_lit_comp("Exception"), str8_lit_comp("Halt"), str8_lit_comp("Memory"), str8_lit_comp("DebugString"), str8_lit_comp("SetThreadName"), str8_lit_comp("SetThreadColor"), str8_lit_comp("SetBreakpoint"), str8_lit_comp("UnsetBreakpoint"), str8_lit_comp("SetVAddrRangeNote"), }; String8 dmn_exception_kind_string_table[5] = { str8_lit_comp("Null"), str8_lit_comp("MemoryRead"), str8_lit_comp("MemoryWrite"), str8_lit_comp("MemoryExecute"), str8_lit_comp("CppThrow"), }; C_LINKAGE_END ================================================ FILE: src/demon/generated/demon.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef DEMON_META_H #define DEMON_META_H typedef enum DMN_EventKind { DMN_EventKind_Null, DMN_EventKind_Error, DMN_EventKind_HandshakeComplete, DMN_EventKind_CreateProcess, DMN_EventKind_ExitProcess, DMN_EventKind_CreateThread, DMN_EventKind_ExitThread, DMN_EventKind_LoadModule, DMN_EventKind_UnloadModule, DMN_EventKind_Breakpoint, DMN_EventKind_Trap, DMN_EventKind_SingleStep, DMN_EventKind_Exception, DMN_EventKind_Halt, DMN_EventKind_Memory, DMN_EventKind_DebugString, DMN_EventKind_SetThreadName, DMN_EventKind_SetThreadColor, DMN_EventKind_SetBreakpoint, DMN_EventKind_UnsetBreakpoint, DMN_EventKind_SetVAddrRangeNote, DMN_EventKind_COUNT, } DMN_EventKind; typedef enum DMN_ErrorKind { DMN_ErrorKind_Null, DMN_ErrorKind_NotAttached, DMN_ErrorKind_UnexpectedFailure, DMN_ErrorKind_InvalidHandle, DMN_ErrorKind_COUNT, } DMN_ErrorKind; typedef enum DMN_MemoryEventKind { DMN_MemoryEventKind_Null, DMN_MemoryEventKind_Commit, DMN_MemoryEventKind_Reserve, DMN_MemoryEventKind_Decommit, DMN_MemoryEventKind_Release, DMN_MemoryEventKind_COUNT, } DMN_MemoryEventKind; typedef enum DMN_ExceptionKind { DMN_ExceptionKind_Null, DMN_ExceptionKind_MemoryRead, DMN_ExceptionKind_MemoryWrite, DMN_ExceptionKind_MemoryExecute, DMN_ExceptionKind_CppThrow, DMN_ExceptionKind_COUNT, } DMN_ExceptionKind; C_LINKAGE_BEGIN extern String8 dmn_event_kind_string_table[21]; extern String8 dmn_exception_kind_string_table[5]; C_LINKAGE_END #endif // DEMON_META_H ================================================ FILE: src/demon/linux/demon_core_linux.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal DMN_LNX_EntityNode * dmn_lnx_entity_list_push(Arena *arena, DMN_LNX_EntityList *list, DMN_LNX_Entity *v) { DMN_LNX_EntityNode *n = push_array(arena, DMN_LNX_EntityNode, 1); n->v = v; SLLQueuePush(list->first, list->last, n); list->count += 1; return n; } //- rjf: file descriptor memory reading/writing helpers internal U64 dmn_lnx_size_from_fd(int memory_fd, U64 cap) { U8 temp[4096]; size_t cursor = 0; while(cursor < cap) { ssize_t actual_read = pread(memory_fd, temp, sizeof(temp), cursor); if(actual_read < 0) { if(errno == EINTR) { continue; } break; } if(actual_read == 0) { break; } cursor += (U64)actual_read; } return (U64)cursor; } internal U64 dmn_lnx_read(int memory_fd, Rng1U64 range, void *dst) { size_t cursor = 0, size = dim_1u64(range); while(cursor < size) { size_t to_read = size - cursor; ssize_t actual_read = pread(memory_fd, (U8 *)dst + cursor, to_read, range.min + cursor); if(actual_read < 0) { if(errno == EINTR) { continue; } break; } if(actual_read == 0) { break; } cursor += actual_read; } return (U64)cursor; } internal B32 dmn_lnx_write(int memory_fd, Rng1U64 range, void *src) { B32 result = 1; U8 *ptr = (U8 *)src; U8 *opl = ptr + dim_1u64(range); U64 cursor = range.min; for(;ptr < opl;) { size_t to_write = (size_t)(opl - ptr); ssize_t actual_write = pwrite(memory_fd, ptr, to_write, cursor); if(actual_write == -1) { result = 0; break; } ptr += actual_write; cursor += actual_write; } return result; } internal String8 dmn_lnx_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size) { String8 result = {0}; U64 string_size = 0; for(U64 vaddr = base_vaddr; string_size < cap_size; vaddr += 1, string_size += 1) { char byte = 0; if(pread(memory_fd, &byte, sizeof(byte), vaddr) == 0) { break; } if(byte == '\0' || byte == '\n') { break; } } if(string_size != 0) { char *buf = push_array_no_zero(arena, char, string_size+1); pread(memory_fd, buf, string_size, base_vaddr); buf[string_size] = '\0'; result = str8((U8 *)buf, string_size); } return result; } internal String8 dmn_lnx_read_string(Arena *arena, int memory_fd, U64 vaddr) { return dmn_lnx_read_string_capped(arena, memory_fd, vaddr, 4096); } //////////////////////////////// //~ Runtime Struct Helpers internal B32 dmn_lnx_read_ehdr(int memory_fd, U64 addr, ELF_Hdr64 *ehdr_out) { B32 is_read = 0; U8 e_ident[ELF_Identifier_Max] = {0}; U64 e_ident_size = dmn_lnx_read(memory_fd, r1u64(addr, addr + sizeof(e_ident)), &e_ident); if(e_ident_size == sizeof(e_ident)) { if(str8_match(str8_prefix(str8_array_fixed(e_ident), elf_magic_string.size), elf_magic_string, 0)) { switch(e_ident[ELF_Identifier_Class]) { default:{InvalidPath;}break; case ELF_Class_None: {}break; case ELF_Class_32: { ELF_Hdr32 ehdr32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &ehdr32)) { *ehdr_out = elf_hdr64_from_hdr32(ehdr32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, ehdr_out); }break; } } } return is_read; } internal B32 dmn_lnx_read_phdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out) { B32 is_read = 0; switch (elf_class) { case ELF_Class_None: break; case ELF_Class_32: { ELF_Phdr32 phdr32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &phdr32)) { *phdr_out = elf_phdr64_from_phdr32(phdr32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, phdr_out); }break; default:{NotImplemented;}break; } return is_read; } internal B32 dmn_lnx_read_shdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out) { B32 is_read = 0; switch (elf_class) { case ELF_Class_None: break; case ELF_Class_32: { ELF_Shdr32 shdr32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &shdr32)) { *shdr_out = elf_shdr64_from_shdr32(shdr32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, shdr_out); }break; default:{NotImplemented;}break; } return is_read; } internal B32 dmn_lnx_read_linkmap(int memory_fd, U64 addr, ELF_Class elf_class, GNU_LinkMap64 *linkmap_out) { B32 is_read = 0; switch(elf_class) { case ELF_Class_None: {}break; case ELF_Class_32: { // TODO(rjf): endianness GNU_LinkMap32 linkmap32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &linkmap32)) { *linkmap_out = gnu_linkmap64_from_linkmap32(linkmap32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, linkmap_out); }break; default:{NotImplemented;}break; } return is_read; } internal B32 dmn_lnx_read_dynamic(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out) { B32 is_read = 0; switch(elf_class) { case ELF_Class_None:{}break; case ELF_Class_32: { ELF_Dyn32 dyn32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &dyn32)) { *dyn_out = elf_dyn64_from_dyn32(dyn32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, dyn_out); }break; default:{NotImplemented;}break; } return is_read; } internal B32 dmn_lnx_read_symbol(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out) { B32 is_read = 0; switch(elf_class) { case ELF_Class_None:{}break; case ELF_Class_32: { ELF_Sym32 symbol32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &symbol32)) { *symbol_out = elf_sym64_from_sym32(symbol32); is_read = 1; } }break; case ELF_Class_64: { is_read = dmn_lnx_read_struct(memory_fd, addr, symbol_out); }break; default:{NotImplemented;}break; } return is_read; } internal B32 dmn_lnx_read_r_debug(int memory_fd, U64 addr, Arch arch, GNU_RDebugInfo64 *rdebug_out) { B32 is_read = 0; switch(gnu_rdebug_info_size_from_arch(arch)) { case 0: {} break; case sizeof(GNU_RDebugInfo32): { GNU_RDebugInfo32 rdebug32 = {0}; if(dmn_lnx_read_struct(memory_fd, addr, &rdebug32)) { *rdebug_out = gnu_rdebug_info64_from_rdebug_info32(rdebug32); is_read = 1; } }break; case sizeof(GNU_RDebugInfo64): { is_read = dmn_lnx_read_struct(memory_fd, addr, rdebug_out); }break; default:{InvalidPath;}break; } Assert(is_read); return is_read; } //- rjf: pid => info extraction internal String8 dmn_lnx_exe_path_from_pid(Arena *arena, pid_t pid) { Temp scratch = scratch_begin(&arena, 1); String8 exe_link_path = str8f(scratch.arena, "/proc/%d/exe", pid); String8List parts = {0}; int readlink_result = 0; for(S64 r = 0, cap = PATH_MAX; r < 4; cap *= 2, r += 1) { U8 *buffer = push_array(arena, U8, cap); readlink_result = readlink((char *)exe_link_path.str, (char *)buffer, cap); if(readlink_result < 0) { break; } str8_list_push(scratch.arena, &parts, str8(buffer, readlink_result)); if(readlink_result < cap) { break; } } String8 result = str8_list_join(arena, &parts, 0); scratch_end(scratch); return result; } internal ELF_Hdr64 dmn_lnx_ehdr_from_pid(pid_t pid) { Temp scratch = scratch_begin(0, 0); B32 is_read = 0; ELF_Hdr64 exe = {0}; String8 exe_path = dmn_lnx_exe_path_from_pid(scratch.arena, pid); if(exe_path.size != 0) { int exe_fd = open((char *)exe_path.str, O_RDONLY|O_CLOEXEC); if(exe_fd != -1) { is_read = dmn_lnx_read_ehdr(exe_fd, 0, &exe); close(exe_fd); } } Assert(is_read); scratch_end(scratch); return exe; } internal DMN_LNX_ProcessAuxv dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class) { Temp scratch = scratch_begin(0, 0); DMN_LNX_ProcessAuxv result = {0}; // rjf: open aux data String8 auxv_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid); int auxv_fd = open((char*)auxv_path.str, O_RDONLY|O_CLOEXEC); // rjf: scan aux data if(auxv_fd >= 0) { for(;;) { // rjf: read next aux ELF_Auxv64 auxv = {0}; switch(elf_class) { case ELF_Class_None:{}break; case ELF_Class_32: { ELF_Auxv32 auxv32 = {0}; if(read(auxv_fd, &auxv32, sizeof(auxv32)) != sizeof(auxv32)) { goto brkloop; } auxv = elf_auxv64_from_auxv32(auxv32); }break; case ELF_Class_64: { if(read(auxv_fd, &auxv, sizeof(auxv)) != sizeof(auxv)) { goto brkloop; } }break; default:{NotImplemented;}break; } // rjf: fill result switch(auxv.a_type) { default:{}break; case ELF_AuxType_Null: goto brkloop; break; case ELF_AuxType_Base: result.base = auxv.a_val; break; case ELF_AuxType_Phnum: result.phnum = auxv.a_val; break; case ELF_AuxType_Phent: result.phent = auxv.a_val; break; case ELF_AuxType_Phdr: result.phdr = auxv.a_val; break; case ELF_AuxType_ExecFn: result.execfn = auxv.a_val; break; case ELF_AuxType_Pagesz: result.pagesz = auxv.a_val; break; } } brkloop:; close(auxv_fd); } scratch_end(scratch); return result; } internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum) { DMN_LNX_PhdrInfo result = { .range.min = max_U64 }; // rjf: scan table for(U64 ph_cursor = e_phaddr, ph_opl = (e_phaddr + e_phentsize * e_phnum); ph_cursor < ph_opl; ph_cursor += e_phentsize) { ELF_Phdr64 phdr = {0}; if(!dmn_lnx_read_phdr(memory_fd, ph_cursor, elf_class, &phdr)) { Assert(0 && "unable to read a program header"); } // rjf: save switch(phdr.p_type) { default:{}break; case ELF_PType_Dynamic: { result.dynamic = rebase + phdr.p_vaddr; }break; case ELF_PType_Load: { U64 min = rebase + phdr.p_vaddr; U64 max = rebase + phdr.p_vaddr + phdr.p_memsz; result.range.min = Min(result.range.min, min); result.range.max = Max(result.range.max, max); }break; } } return result; } internal DMN_LNX_DynamicInfo dmn_lnx_dynamic_info_from_memory(int memory_fd, ELF_Class elf_class, U64 rebase, U64 dynamic_vaddr) { DMN_LNX_DynamicInfo dynamic_info = {0}; for(U64 dynamic_cursor = dynamic_vaddr; ; dynamic_cursor += elf_dyn_size_from_class(elf_class)) { // rjf: read next dyn entry ELF_Dyn64 dyn = {0}; if(!dmn_lnx_read_dynamic(memory_fd, dynamic_cursor, elf_class, &dyn)) { Assert(0 && "unable to read dynamic"); } // rjf: break on zero if(dyn.tag == ELF_DynTag_Null) { break; } // extract reuiqred values out of dynamic section if(dyn.tag == ELF_DynTag_Strtab) { dynamic_info.strtab_vaddr = rebase + dyn.val; } else if(dyn.tag == ELF_DynTag_Strsz) { dynamic_info.strtab_size = dyn.val; } else if(dyn.tag == ELF_DynTag_Symtab) { dynamic_info.symtab_vaddr = rebase + dyn.val; } else if(dyn.tag == ELF_DynTag_Syment) { dynamic_info.symtab_entry_size = dyn.val; } else if(dyn.tag == ELF_DynTag_Hash) { dynamic_info.hash_vaddr = rebase + dyn.val; } else if(dyn.tag == ELF_DynTag_GNU_Hash) { dynamic_info.gnu_hash_vaddr = rebase + dyn.val; } } return dynamic_info; } internal U64 dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase) { Temp scratch = scratch_begin(0, 0); U64 rdebug_vaddr = 0; // load DL's header ELF_Hdr64 ehdr = {0}; if(!dmn_lnx_read_ehdr(memory_fd, loader_vbase, &ehdr)) { Assert(0 && "failed to read interp's header"); goto exit; } U64 rebase = ehdr.e_type == ELF_Type_Dyn ? loader_vbase : 0; ELF_Class elf_class = ehdr.e_ident[ELF_Identifier_Class]; // find dynamic program header U64 dynamic_vaddr = max_U64; for EachIndex(phdr_idx, ehdr.e_phnum) { U64 phdr_vaddr = loader_vbase + ehdr.e_phoff + phdr_idx * ehdr.e_phentsize; ELF_Phdr64 phdr = {0}; if(!dmn_lnx_read_phdr(memory_fd, phdr_vaddr, elf_class, &phdr)) { Assert(0 && "failed to read program header"); goto exit; } if(phdr.p_type == ELF_PType_Dynamic) { dynamic_vaddr = rebase + phdr.p_offset; break; } } // extract necessary info out of dynamic program header DMN_LNX_DynamicInfo dynamic_info = dmn_lnx_dynamic_info_from_memory(memory_fd, elf_class, rebase, dynamic_vaddr); // extract symbol table count from available options U64 symbol_count = 0; if(dynamic_info.hash_vaddr) { U64 hash_entry_size = 4; if(elf_class == ELF_Class_64 && (ehdr.e_machine == ELF_MachineKind_ALPHA || ehdr.e_machine == ELF_MachineKind_S390 || ehdr.e_machine == ELF_MachineKind_S390_OLD)) { hash_entry_size = 8; } U64 chain_count = 0; if(dmn_lnx_read(memory_fd, r1u64(dynamic_info.hash_vaddr, dynamic_info.hash_vaddr + hash_entry_size), &chain_count) == hash_entry_size) { symbol_count = chain_count; } else { Assert(0 && "failed to read hash table's chain count out of HASH"); } } else { // TODO: extract count from GNU_HASH NotImplemented; } // scan symbol table for the rendezvous symbol if(dynamic_info.symtab_vaddr && dynamic_info.symtab_entry_size && symbol_count) { for EachIndex(symbol_idx, symbol_count) { ELF_Sym64 symbol = {0}; if(!dmn_lnx_read_symbol(memory_fd, dynamic_info.symtab_vaddr + symbol_idx * dynamic_info.symtab_entry_size, elf_class, &symbol)) { Assert(0 && "failed to read symbol table"); break; } Temp temp = temp_begin(scratch.arena); String8 symbol_name = {0}; if(symbol.st_name < dynamic_info.strtab_size) { U64 cap = dynamic_info.strtab_size - symbol.st_name; symbol_name = dmn_lnx_read_string_capped(temp.arena, memory_fd, dynamic_info.strtab_vaddr + symbol.st_name, cap); } if(str8_match(symbol_name, str8_lit("_r_debug"), 0)) { ELF_SymType symbol_type = ELF_ST_TYPE(symbol.st_info); if(symbol_type == ELF_SymType_Object && symbol.st_size > 0) { rdebug_vaddr = rebase + symbol.st_value; break; } } temp_end(temp); } } exit:; scratch_end(scratch); return rdebug_vaddr; } //////////////////////////////// //~ SDT Probes internal DMN_LNX_ProbeList dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base) { Temp scratch = scratch_begin(&arena, 1); DMN_LNX_ProbeList probes = {0}; ELF_Hdr64 ehdr = {0}; if(!dmn_lnx_read_ehdr(fd, offset, &ehdr)) { goto exit; } U64 strtab_shdr_offset = offset + ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize; ELF_Shdr64 strtab_shdr = {0}; if(!dmn_lnx_read_shdr(fd, strtab_shdr_offset, ehdr.e_ident[ELF_Identifier_Class], &strtab_shdr)) { goto exit; } B32 found_probes = 0; B32 found_probes_base = 0; ELF_Shdr64 text_shdr = {0}; ELF_Shdr64 stapsdt_base_shdr = {0}; ELF_Shdr64 stapsdt_shdr = {0}; for(U64 shdr_off = offset + ehdr.e_shoff, shdr_opl = shdr_off + ehdr.e_shentsize * ehdr.e_shnum; shdr_off < shdr_opl; shdr_off += ehdr.e_shentsize) { ELF_Shdr64 shdr = {0}; if(!dmn_lnx_read_shdr(fd, shdr_off, ehdr.e_ident[ELF_Identifier_Class], &shdr)) { goto exit; } if(shdr.sh_type == ELF_ShType_Note) { U64 name_offset = offset + strtab_shdr.sh_offset + shdr.sh_name; U64 name_cap = offset + strtab_shdr.sh_offset + strtab_shdr.sh_size; String8 name = dmn_lnx_read_string_capped(scratch.arena, fd, name_offset, name_cap); if(str8_match(name, str8_lit(".note.stapsdt"), 0)) { stapsdt_shdr = shdr; found_probes = 1; } } else if(shdr.sh_type == ELF_ShType_ProgBits) { U64 name_offset = offset + strtab_shdr.sh_offset + shdr.sh_name; U64 name_cap = offset + strtab_shdr.sh_offset + strtab_shdr.sh_size; String8 name = dmn_lnx_read_string_capped(scratch.arena, fd, name_offset, name_cap); if(str8_match(name, str8_lit(".stapsdt.base"), 0)) { stapsdt_base_shdr = shdr; found_probes_base = 1; } else if(str8_match(name, str8_lit(".text"), 0)) { text_shdr = shdr; } } if(found_probes && found_probes_base) { break; } } if(!found_probes || !found_probes_base) { goto exit; } U64 probes_base = stapsdt_base_shdr.sh_addr; Rng1U64 note_range = shift_1u64(r1u64(stapsdt_shdr.sh_offset, stapsdt_shdr.sh_offset + stapsdt_shdr.sh_size), offset); void *raw_note = push_array(arena, U8, stapsdt_shdr.sh_size); U64 note_read_size = dmn_lnx_read(fd, note_range, raw_note); if(note_read_size != dim_1u64(note_range)) { goto exit; } Arch arch = arch_from_elf_machine(ehdr.e_machine); ELF_NoteList note = elf_parse_note(scratch.arena, str8(raw_note, dim_1u64(note_range)), ehdr.e_ident[ELF_Identifier_Class], ehdr.e_machine); for EachNode(n, ELF_NoteNode, note.first) { ELF_Note *note = &n->v; if(!str8_match(note->owner, str8_lit("stapsdt"), 0)) { continue; } if(note->type != ELF_NoteType_STapSdt) { continue; } DMN_LNX_Probe probe = {0}; { U64 cursor = 0; U64 addr_size = ehdr.e_ident[ELF_Identifier_Class] == ELF_Class_64 ? 8 : 4; U64 pc = 0; U64 pc_size = str8_deserial_read(note->desc, cursor, &pc, addr_size, addr_size); if (pc_size == 0) { goto exit; } cursor += pc_size; U64 base_addr = 0; U64 base_addr_size = str8_deserial_read(note->desc, cursor, &base_addr, addr_size, addr_size); if (base_addr_size == 0) { goto exit; } cursor += base_addr_size; U64 semaphore = 0; U64 semaphore_size = str8_deserial_read(note->desc, cursor, &semaphore, addr_size, addr_size); if (semaphore_size == 0) { goto exit; } cursor += semaphore_size; String8 provider = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += provider.size + 1; if (cursor > note->desc.size) { goto exit; } String8 name = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += name.size + 1; if (cursor > note->desc.size) { goto exit; } String8 args = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += args.size + 1; if (cursor > note->desc.size) { goto exit; } U64 probe_rebase = image_base + (base_addr - probes_base); probe.provider = provider; probe.name = name; probe.args = stap_arg_array_from_string(arena, arch, args); probe.pc = pc + probe_rebase; probe.semaphore = semaphore ? semaphore + probe_rebase : 0; } DMN_LNX_ProbeNode *n = push_array(arena, DMN_LNX_ProbeNode, 1); n->v = probe; SLLQueuePush(probes.first, probes.last, n); probes.count += 1; } exit:; scratch_end(scratch); return probes; } //////////////////////////////// //~ STAP internal STAP_MEMORY_READ(dmn_lnx_stap_memory_read) { DMN_LNX_Entity *process = raw_ctx; U64 bytes_read = dmn_lnx_read(process->fd, r1u64(addr, addr + read_size), buffer); return bytes_read == read_size; } //////////////////////////////// //~ rjf: Entity Functions internal DMN_LNX_Entity * dmn_lnx_entity_alloc(DMN_LNX_Entity *parent, DMN_LNX_EntityKind kind) { DMN_LNX_Entity *entity = dmn_lnx_state->free_entity; if(entity != 0) { SLLStackPop(dmn_lnx_state->free_entity); } else { entity = push_array(dmn_lnx_state->entities_arena, DMN_LNX_Entity, 1); dmn_lnx_state->entities_count += 1; } U32 gen = entity->gen; MemoryCopyStruct(entity, &dmn_lnx_nil_entity); entity->gen += 1; if(parent != &dmn_lnx_nil_entity) { DLLPushBack_NPZ(&dmn_lnx_nil_entity, parent->first, parent->last, entity, next, prev); entity->parent = parent; } entity->kind = kind; return entity; } internal void dmn_lnx_entity_release(DMN_LNX_Entity *entity) { if(entity->parent != &dmn_lnx_nil_entity) { DLLRemove_NPZ(&dmn_lnx_nil_entity, entity->parent->first, entity->parent->last, entity, next, prev); entity->parent = &dmn_lnx_nil_entity; } { Temp scratch = scratch_begin(0, 0); DMN_LNX_EntityNode start_task = {0, entity}; DMN_LNX_EntityNode *first_task = &start_task; for(DMN_LNX_EntityNode *t = first_task; t != 0; t = t->next) { SLLStackPush(dmn_lnx_state->free_entity, t->v); for(DMN_LNX_Entity *child = t->v->first; child != &dmn_lnx_nil_entity; child = child->next) { DMN_LNX_EntityNode *task = push_array(scratch.arena, DMN_LNX_EntityNode, 1); task->next = t->next; t->next = task; task->v = child; } } scratch_end(scratch); } } internal DMN_Handle dmn_lnx_handle_from_entity(DMN_LNX_Entity *entity) { DMN_Handle handle = {0}; U64 index = (U64)(entity - dmn_lnx_state->entities_base); if(index <= 0xffffffffu) { handle.u32[0] = index; handle.u32[1] = entity->gen; } return handle; } internal DMN_LNX_Entity * dmn_lnx_entity_from_handle(DMN_Handle handle) { DMN_LNX_Entity *result = &dmn_lnx_nil_entity; U64 index = (U64)handle.u32[0]; if(index < dmn_lnx_state->entities_count && dmn_lnx_state->entities_base[index].gen == handle.u32[1]) { result = &dmn_lnx_state->entities_base[index]; } return result; } internal DMN_LNX_Entity * dmn_lnx_thread_from_pid(pid_t pid) { DMN_LNX_Entity *result = &dmn_lnx_nil_entity; if(pid != 0) { for EachIndex(idx, dmn_lnx_state->entities_count) { if(dmn_lnx_state->entities_base[idx].kind == DMN_LNX_EntityKind_Thread && (pid_t)dmn_lnx_state->entities_base[idx].id == pid) { result = &dmn_lnx_state->entities_base[idx]; break; } } } return result; } internal U64 dmn_lnx_thread_read_ip(DMN_LNX_Entity *thread) { U64 ip = 0; if(thread->reg_block) { ip = regs_rip_from_arch_block(thread->arch, thread->reg_block); } Assert(ip); return ip; } internal U64 dmn_lnx_thread_read_sp(DMN_LNX_Entity *thread) { U64 sp = 0; if(thread->reg_block) { sp = regs_rsp_from_arch_block(thread->arch, thread->reg_block); } Assert(sp); return sp; } internal B32 dmn_lnx_thread_write_ip(DMN_LNX_Entity *thread, U64 ip) { B32 is_ip_written = 0; if(thread->reg_block) { REGS_RegBlockX64 *reg_block = thread->reg_block; regs_arch_block_write_rip(thread->arch, reg_block, ip); is_ip_written = dmn_lnx_thread_write_reg_block(thread, reg_block); } Assert(is_ip_written); return is_ip_written; } internal B32 dmn_lnx_thread_write_sp(DMN_LNX_Entity *thread, U64 sp) { B32 is_sp_written = 0; if(thread->reg_block) { REGS_RegBlockX64 *reg_block = thread->reg_block; regs_arch_block_write_rsp(thread->arch, reg_block, sp); is_sp_written = dmn_lnx_thread_write_reg_block(thread, reg_block); } Assert(is_sp_written); return is_sp_written; } internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block) { AssertAlways(gettid() == thread->parent->tracer_tid); B32 result = 0; switch(thread->arch) { case Arch_Null: case Arch_COUNT:{}break; case Arch_x86: case Arch_arm64: case Arch_arm32: {NotImplemented;}break; //////////////////////////// //- rjf: [x64] // case Arch_x64: { DMN_LNX_Entity *process = thread->parent; pid_t tid = (pid_t)thread->id; REGS_RegBlockX64 *dst = reg_block; //- rjf: read GPR B32 got_gpr = 0; { DMN_LNX_UserX64 ctx = {0}; int ptrace_result = ptrace(PTRACE_GETREGSET, tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_len = sizeof(ctx), .iov_base = &ctx }); if(ptrace_result != -1) { got_gpr = 1; DMN_LNX_UserX64 *src = &ctx; dst->rax.u64 = src->regs.rax; dst->rcx.u64 = src->regs.rcx; dst->rdx.u64 = src->regs.rdx; dst->rbx.u64 = src->regs.rbx; dst->rsp.u64 = src->regs.rsp; dst->rbp.u64 = src->regs.rbp; dst->rsi.u64 = src->regs.rsi; dst->rdi.u64 = src->regs.rdi; dst->r8.u64 = src->regs.r8; dst->r9.u64 = src->regs.r9; dst->r10.u64 = src->regs.r10; dst->r11.u64 = src->regs.r11; dst->r12.u64 = src->regs.r12; dst->r13.u64 = src->regs.r13; dst->r14.u64 = src->regs.r14; dst->r15.u64 = src->regs.r15; dst->cs.u16 = src->regs.cs; dst->ds.u16 = src->regs.ds; dst->es.u16 = src->regs.es; dst->fs.u16 = src->regs.fs; dst->gs.u16 = src->regs.gs; dst->ss.u16 = src->regs.ss; dst->fsbase.u64 = src->regs.fsbase; dst->gsbase.u64 = src->regs.gsbase; dst->rip.u64 = src->regs.rip; dst->rflags.u64 = src->regs.rflags; } else { Assert(0 && "failed to get gprs"); } } //- rjf: read FPR B32 got_fpr = 0; if(got_gpr) { Temp scratch = scratch_begin(0, 0); X64_XSave *xsave = 0; X64_FXSave *fxsave = 0; // get xsave if(x64_is_xsave_supported()) { void *xsave_raw = push_array(scratch.arena, U8, process->xsave_size); int ptrace_result = ptrace(PTRACE_GETREGSET, tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_len = process->xsave_size, .iov_base = xsave_raw }); if(ptrace_result != -1) { xsave = xsave_raw; fxsave = &xsave->fxsave; } else { Assert(0 && "failed to get xsave"); } } // get fxsave if (fxsave == 0) { fxsave = push_array(scratch.arena, X64_FXSave, 1); int ptrace_result = ptrace(PTRACE_GETREGSET, tid, (void *)NT_FPREGSET, &(struct iovec){ .iov_len = sizeof(*fxsave), .iov_base = fxsave }); if(ptrace_result != -1) { fxsave = 0; } else { Assert(0 && "failed to get fxsave"); } } // copy fxsave registers if(fxsave) { X64_FXSave *src = fxsave; // copy x87 registers dst->fcw.u16 = src->fcw; dst->fsw.u16 = src->fsw; dst->ftw.u16 = x64_xsave_tag_word_from_real_tag_word(src->ftw); dst->fop.u16 = src->fop; dst->fip.u64 = src->b64.fip; dst->fdp.u64 = src->b64.fdp; dst->mxcsr.u32 = src->mxcsr; dst->mxcsr_mask.u32 = src->mxcsr_mask; for EachIndex(i, 8) { MemoryCopy(&dst->st0 + i, src->st_space + i, sizeof(REGS_Reg80)); } // SSE registers are always available in x64 { U128 *xmm_d = fxsave->xmm_space; REGS_Reg512 *zmm_s = &dst->zmm0; for EachIndex(i, 16) { MemoryCopy(&zmm_s[i], &xmm_d[i], sizeof(*xmm_d)); } } } // copy xsave registers if(xsave) { if(xsave->header.xstate_bv & X64_XStateComponentFlag_AVX) { AssertAlways(process->xsave_layout.avx_offset + 16*sizeof(REGS_Reg128) <= process->xsave_size); REGS_Reg128 *avx_s = (REGS_Reg128 *)((U8 *)xsave + process->xsave_layout.avx_offset); REGS_Reg512 *zmm_d = &dst->zmm0; for EachIndex(n, 16) { MemoryCopy(&zmm_d[n].v[16], &avx_s[n], sizeof(REGS_Reg128)); } } if(xsave->header.xstate_bv & X64_XStateComponentFlag_OPMASK) { AssertAlways(process->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process->xsave_size); REGS_Reg64 *kmask_s = (REGS_Reg64 *)((U8 *)xsave + process->xsave_layout.opmask_offset); REGS_Reg64 *kmask_d = &dst->k0; for EachIndex(n, 8) { MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(REGS_Reg64)); } } if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM_H) { AssertAlways(process->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process->xsave_size); REGS_Reg256 *avx512h_s = (REGS_Reg256 *)((U8 *)xsave + process->xsave_layout.zmm_h_offset); REGS_Reg512 *zmmh_d = &dst->zmm0; for EachIndex(n, 16) { MemoryCopy(&zmmh_d[n].v[32], &avx512h_s[n], sizeof(REGS_Reg256)); } } if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM) { AssertAlways(process->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process->xsave_size); REGS_Reg512 *avx512_s = (REGS_Reg512 *)((U8 *)xsave + process->xsave_layout.zmm_offset); REGS_Reg512 *zmm_d = &dst->zmm16; for EachIndex(n, 16) { MemoryCopy(&zmm_d[n], &avx512_s[n], sizeof(REGS_Reg512)); } } if(xsave->header.xstate_bv & X64_XStateComponentFlag_CETU) { AssertAlways(process->xsave_layout.cet_u_offset + sizeof(U64)*2 <= process->xsave_size); U64 *cet_u = (U64 *)((U8 *)xsave + process->xsave_layout.cet_u_offset); dst->cetmsr.u64 = cet_u[0]; dst->cetssp.u64 = cet_u[1]; } } got_fpr = (xsave || fxsave); scratch_end(scratch); } //- rjf: read debug registers B32 got_debug = 0; if(got_fpr) { got_debug = 1; REGS_Reg64 *dr_d = &dst->dr0; for EachIndex(n, 8) { if(n != 4 && n != 5) { U64 offset = OffsetOf(DMN_LNX_UserX64, u_debugreg[n]); errno = 0; long peek_result = ptrace(PTRACE_PEEKUSER, tid, PtrFromInt(offset), 0); if(errno == 0) { dr_d[n].u64 = (U64)peek_result; } else { got_debug = 0; } } } } result = got_debug; }break; } return result; } internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread, void *reg_block) { AssertAlways(gettid() == thread->parent->tracer_tid); B32 result = 0; switch(thread->arch) { case Arch_Null: case Arch_COUNT:{}break; case Arch_arm64: case Arch_arm32: case Arch_x86: {NotImplemented;}break; //////////////////////////// //- rjf: [x64] // case Arch_x64: { DMN_LNX_Entity *process = thread->parent; pid_t tid = (pid_t)thread->id; REGS_RegBlockX64 *src = reg_block; //- rjf: write GPR B32 did_gpr = 0; { DMN_LNX_UserX64 dst = {0}; dst.regs.rax = src->rax.u64; dst.regs.rcx = src->rcx.u64; dst.regs.rdx = src->rdx.u64; dst.regs.rbx = src->rbx.u64; dst.regs.rsp = src->rsp.u64; dst.regs.rbp = src->rbp.u64; dst.regs.rsi = src->rsi.u64; dst.regs.rdi = src->rdi.u64; dst.regs.r8 = src->r8.u64; dst.regs.r9 = src->r9.u64; dst.regs.r10 = src->r10.u64; dst.regs.r11 = src->r11.u64; dst.regs.r12 = src->r12.u64; dst.regs.r13 = src->r13.u64; dst.regs.r14 = src->r14.u64; dst.regs.r15 = src->r15.u64; dst.regs.cs = src->cs.u16; dst.regs.ds = src->ds.u16; dst.regs.es = src->es.u16; dst.regs.fs = src->fs.u16; dst.regs.gs = src->gs.u16; dst.regs.ss = src->ss.u16; dst.regs.fsbase = src->fsbase.u64; dst.regs.gsbase = src->gsbase.u64; dst.regs.rip = src->rip.u64; dst.regs.rflags = src->rflags.u64; did_gpr = ptrace(PTRACE_SETREGSET, tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_base = &dst, .iov_len = sizeof(dst) }) >= 0; } B32 did_fpr = 0; if(did_gpr) { Temp scratch = scratch_begin(0, 0); int xsave_result = -1; int fxsave_result = -1; X64_FXSave dst_fxsave = {0}; { dst_fxsave.fcw = src->fcw.u16; dst_fxsave.fsw = src->fsw.u16; dst_fxsave.ftw = src->ftw.u16; dst_fxsave.fop = src->fop.u16; dst_fxsave.b64.fip = src->fip.u64; dst_fxsave.b64.fdp = src->fdp.u64; dst_fxsave.mxcsr = src->mxcsr.u32; dst_fxsave.mxcsr_mask = src->mxcsr_mask.u32; REGS_Reg128 *st_d = (REGS_Reg128 *)dst_fxsave.st_space; REGS_Reg80 *st_s = &src->st0; for EachIndex(n, 8) { MemoryCopy(&st_d[n], &st_s[n], sizeof(REGS_Reg80)); } REGS_Reg128 *xmm_d = (REGS_Reg128 *)dst_fxsave.xmm_space; REGS_Reg512 *xmm_s = &src->zmm0; for EachIndex(n, 16) { MemoryCopy(&xmm_d[n], &xmm_s[n], sizeof(REGS_Reg128)); } } if(x64_is_xsave_supported()) { U8 *xsave_raw = push_array(scratch.arena, U8, process->xsave_size); int xsave_get = ptrace(PTRACE_GETREGSET, tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_base = xsave_raw, .iov_len = process->xsave_size }); AssertAlways(xsave_get >= 0); X64_XSave *dst = (X64_XSave *)xsave_raw; dst->fxsave = dst_fxsave; if(process->xsave_layout.avx_offset) { if(process->xsave_layout.avx_offset + sizeof(REGS_Reg128) * 16 <= process->xsave_size) { REGS_Reg128 *avx_d = (REGS_Reg128 *)(xsave_raw + process->xsave_layout.avx_offset); REGS_Reg512 *zmm_s = &src->zmm0; for EachIndex(n, 16) { MemoryCopy(&avx_d[n], &zmm_s[n].v[16], sizeof(REGS_Reg128)); } } } if(process->xsave_layout.opmask_offset) { if(process->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process->xsave_size) { REGS_Reg64 *kmask_d = (REGS_Reg64 *)(xsave_raw + process->xsave_layout.opmask_offset); REGS_Reg64 *kmask_s = &src->k0; for EachIndex(n, 8) { MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(REGS_Reg64)); } } else { Assert(0 && "invalid xsave size"); } } if(process->xsave_layout.zmm_h_offset) { if(process->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process->xsave_size) { REGS_Reg256 *avx512h_d = (REGS_Reg256 *)(xsave_raw + process->xsave_layout.zmm_h_offset); REGS_Reg512 *zmmh_s = &src->zmm0; for EachIndex(n, 16) { MemoryCopy(&avx512h_d[n], &zmmh_s[n].v[32], sizeof(REGS_Reg256)); } } else { Assert(0 && "invalid xsave size"); } } if(process->xsave_layout.zmm_offset) { if(process->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process->xsave_size) { REGS_Reg512 *avx512_d = (REGS_Reg512 *)(xsave_raw + process->xsave_layout.zmm_offset); REGS_Reg512 *zmm_s = &src->zmm16; for EachIndex(n, 16) { MemoryCopy(&avx512_d[n], &zmm_s[n], sizeof(REGS_Reg512)); } } else { Assert(0 && "invalid xsave size"); } } if(process->xsave_layout.cet_u_offset) { if(process->xsave_layout.cet_u_offset + sizeof(REGS_Reg64) * 2 <= process->xsave_size) { REGS_Reg64 *cet_u = (REGS_Reg64 *)(xsave_raw + process->xsave_layout.cet_u_offset); cet_u[0] = src->cetmsr; cet_u[1] = src->cetssp; } else { Assert(0 && "invalid xsave size"); } } // xsave xsave_result = ptrace(PTRACE_SETREGSET, tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_base = dst, .iov_len = process->xsave_size }); Assert(xsave_result >= 0); } // fallback to fxsave if(xsave_result < 0) { fxsave_result = ptrace(PTRACE_SETREGSET, tid, (void *)NT_FPREGSET, &(struct iovec){ .iov_base = &dst_fxsave, sizeof(dst_fxsave) }); Assert(fxsave_result >= 0); } // rjf: good finish requires xsave or fxsave did_fpr = (xsave_result >= 0 || fxsave_result >= 0); scratch_end(scratch); } //- rjf: write debug registers B32 did_dbg = 0; if(did_fpr) { did_dbg = 1; src->dr7.u64 |= (1 << 10); REGS_Reg64 *dr_s = &src->dr0; for EachIndex(n, 8) { if(n != 4 && n != 5) { U64 offset = OffsetOf(DMN_LNX_UserX64, u_debugreg[n]); int poke_result = ptrace(PTRACE_POKEUSER, tid, PtrFromInt(offset), dr_s[n].u64); if(poke_result < 0) { did_dbg = 0; break; } } } } result = (did_dbg); }break; } return result; } internal B32 dmn_lnx_set_single_step_flag(DMN_LNX_Entity *thread, B32 is_on) { B32 is_flag_set = 0; switch(thread->arch) { case Arch_COUNT: case Arch_Null: {} break; case Arch_x64: { REGS_RegBlockX64 *reg_block = thread->reg_block; if(is_on) { reg_block->rflags.u64 |= X64_RFlag_Trap; } else { reg_block->rflags.u64 &= ~X64_RFlag_Trap; } is_flag_set = dmn_lnx_thread_write_reg_block(thread, thread->reg_block); }break; case Arch_x86: case Arch_arm32: case Arch_arm64: { NotImplemented; }break; } Assert(is_flag_set); return is_flag_set; } internal void dmn_lnx_process_loaded_modules(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, U64 name_space_id, U64 new_link_map_vaddr) { GNU_LinkMap64 map = {0}; for(U64 map_vaddr = new_link_map_vaddr; map_vaddr != 0; map_vaddr = map.next_vaddr) { // read out new link map item if(!dmn_lnx_read_linkmap(process->fd, map_vaddr, process->dl_class, &map)) { goto exit; } // was module with this base already registered? DMN_LNX_Entity *module = hash_table_search_u64_raw(process->loaded_modules_ht, map.addr_vaddr); if(module) { continue; } // parse out module's ELF header ELF_Hdr64 module_ehdr = {0}; if(!dmn_lnx_read_ehdr(process->fd, map.addr_vaddr, &module_ehdr)) { goto exit; } // gather info about module U64 module_rebase = module_ehdr.e_type == ELF_Type_Dyn ? map.addr_vaddr : 0; U64 module_phdr_vaddr = module_rebase + module_ehdr.e_phoff; DMN_LNX_PhdrInfo module_phdr_info = dmn_lnx_phdr_info_from_memory(process->fd, module_ehdr.e_ident[ELF_Identifier_Class], module_rebase, module_phdr_vaddr, module_ehdr.e_phentsize, module_ehdr.e_phnum); String8 module_name = dmn_lnx_read_string(process->arena, process->fd, map.name_vaddr); // fill out module module = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Module); module->id = map.name_vaddr; module->base_vaddr = map.addr_vaddr; // push load event if(!str8_match(module_name, str8_lit("linux-vdso.so.1"), 0)) { DMN_Event *e = dmn_event_list_push(arena, events); e->kind = DMN_EventKind_LoadModule; e->process = dmn_lnx_handle_from_entity(process); e->module = dmn_lnx_handle_from_entity(module); e->arch = arch_from_elf_machine(module_ehdr.e_machine); e->address = map.addr_vaddr; e->size = dim_1u64(module_phdr_info.range); e->string = module_name; e->elf_phdr_vrange = r1u64(module_phdr_vaddr, module_phdr_vaddr + module_ehdr.e_phentsize * module_ehdr.e_phnum); e->elf_phdr_entsize = module_ehdr.e_phentsize; } // create mapping for base -> module hash_table_push_u64_raw(process->arena, process->loaded_modules_ht, map.addr_vaddr, module); } exit:; } internal void dmn_lnx_process_unloaded_modules(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, U64 name_space_id, U64 rdebug_vaddr) { Temp scratch = scratch_begin(&arena, 1); B32 is_unmap_complete_finished = 0; GNU_RDebugInfo64 rdebug = {0}; if(!dmn_lnx_read_r_debug(process->fd, rdebug_vaddr, process->arch, &rdebug)) { goto exit; } if(rdebug.r_version != 1) { goto exit; } // flag every module as inactive for(DMN_LNX_Entity *module = process->first; module != &dmn_lnx_nil_entity; module = module->next) { if(module->kind != DMN_LNX_EntityKind_Module) {continue;} module->is_live = 0; } // loop over modules in the link map and mark live modules GNU_LinkMap64 map = {0}; for(U64 map_vaddr = rdebug.r_map; map_vaddr != 0; map_vaddr = map.next_vaddr) { if(dmn_lnx_read_linkmap(process->fd, map_vaddr, process->dl_class, &map)) { DMN_LNX_Entity *module = hash_table_search_u64_raw(process->loaded_modules_ht, map.addr_vaddr); if(module) { module->is_live = 1; } else { Assert(0 && "unknown module is being unloaded"); } } else { Assert(0 && "unable to read Link Map"); } } // unload inactive modules DMN_HandleList to_release = {0}; for(DMN_LNX_Entity *module = process->first; module != &dmn_lnx_nil_entity; module = module->next) { if(module->kind != DMN_LNX_EntityKind_Module) {continue;} if(module->is_live) {continue;} dmn_handle_list_push(scratch.arena, &to_release, dmn_lnx_handle_from_entity(module)); } // push events and clean up internal structures for EachNode(n, DMN_HandleNode, to_release.first) { DMN_LNX_Entity *module = dmn_lnx_entity_from_handle(n->v); DMN_Event *e = dmn_event_list_push(dmn_lnx_state->deferred_events_arena, &dmn_lnx_state->deferred_events); e->kind = DMN_EventKind_UnloadModule; e->process = dmn_lnx_handle_from_entity(process); e->module = dmn_lnx_handle_from_entity(module); e->string = dmn_lnx_read_string(arena, process->fd, module->id); hash_table_purge_u64(process->loaded_modules_ht, module->base_vaddr); dmn_lnx_entity_release(module); } is_unmap_complete_finished = 1; exit:; Assert(is_unmap_complete_finished); scratch_end(scratch); } //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) internal void dmn_init(void) { Arena *arena = arena_alloc(); dmn_lnx_state = push_array(arena, DMN_LNX_State, 1); dmn_lnx_state->arena = arena; dmn_lnx_state->deferred_events_arena = arena_alloc(); dmn_lnx_state->entities_arena = arena_alloc(.reserve_size = GB(32), .commit_size = KB(64), .flags = ArenaFlag_NoChain); dmn_lnx_state->entities_base = push_array(dmn_lnx_state->entities_arena, DMN_LNX_Entity, 0); dmn_lnx_entity_alloc(&dmn_lnx_nil_entity, DMN_LNX_EntityKind_Root); dmn_lnx_state->access_mutex = mutex_alloc(); } //////////////////////////////// //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS) internal DMN_CtrlCtx * dmn_ctrl_begin(void) { DMN_CtrlCtx *ctx = (DMN_CtrlCtx *)1; dmn_lnx_ctrl_thread = 1; return ctx; } internal void dmn_ctrl_exclusive_access_begin(void) { MutexScope(dmn_lnx_state->access_mutex) { dmn_lnx_state->access_run_state = 1; } } internal void dmn_ctrl_exclusive_access_end(void) { MutexScope(dmn_lnx_state->access_mutex) { dmn_lnx_state->access_run_state = 0; } } internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params) { Temp scratch = scratch_begin(0, 0); //- rjf: unpack command line char **argv = 0; int argc = 0; { argc = (int)(params->cmd_line.node_count); argv = push_array(scratch.arena, char *, argc+1); { U64 idx = 0; for(String8Node *n = params->cmd_line.first; n != 0; n = n->next, idx += 1) { argv[idx] = (char *)push_str8_copy(scratch.arena, n->string).str; } } } //- rjf: unpack path char *path = (char *)push_str8_copy(scratch.arena, params->path).str; //- rjf: unpack environment char **env = 0; { env = push_array(scratch.arena, char *, params->env.node_count+1); { U64 idx = 0; for(String8Node *n = params->env.first; n != 0; n = n->next, idx += 1) { env[idx] = (char *)push_str8_copy(scratch.arena, n->string).str; } } } //- rjf: create & set up new process if(argv != 0 && argv[0] != 0) { pid_t pid = 0; int ptrace_result = 0; int chdir_result = 0; B32 error__need_child_kill = 0; // open temp pipes to communicate with child process int pipe_fds[2] = {0}; if (pipe(&pipe_fds[0]) < 0) { InvalidPath; } //- rjf: fork pid = fork(); if(pid == -1) { goto error; } //- rjf: child process -> execute actual target if(pid == 0) { // wait for parent seize char b; read(pipe_fds[0], &b, sizeof(b)); // set current working directory to tracee chdir_result = chdir(path); if(chdir_result == -1) { goto error; } // replace process with target execve(argv[0], argv, env); // execve failed -- exit abort(); } //- rjf: parent process if(pid != 0) { enum LaunchStatus { LaunchStatus_Null, LaunchStatus_FailBeforePtrace, LaunchStatus_FailAfterPtrace, LaunchStatus_Success, }; enum LaunchStatus launch_status = LaunchStatus_FailBeforePtrace; { int s = 0; // seize process if (ptrace(PTRACE_SEIZE, pid, 0, 0) < 0) { Assert(0 && "seize failed"); goto launch_error; } // interrupt process launch_status = LaunchStatus_FailAfterPtrace; if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) < 0) { Assert(0 && "interrupt failed"); goto launch_error; } if (waitpid(pid, &s, __WALL|__WNOTHREAD) < 0) { Assert(0 && "interrupt wait failed"); goto launch_error; } // entry read if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } // resume child char b = 1; if (write(pipe_fds[1], &b, sizeof(b)) < 0) { Assert(0 && "resume child failed"); goto launch_error; } // exit read if (waitpid(pid, &s, __WALL|__WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } // entry chdir if (waitpid(pid, &s, __WALL|__WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } // exit chdir if (waitpid(pid, &s, __WALL|__WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } // entry execv if (waitpid(pid, &s, __WALL|__WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } // exit execve if (waitpid(pid, &s, __WALL | __WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) { Assert(0 && "syscall failed"); goto launch_error; } if (waitpid(pid, &s, __WALL | __WNOTHREAD) < 0) { Assert(0 && "wait failed"); goto launch_error; } uintptr_t trace_options = PTRACE_O_TRACEEXIT | PTRACE_O_EXITKILL | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEVFORKDONE; int setoptions_result = ptrace(PTRACE_SETOPTIONS, pid, 0, PtrFromInt(trace_options)); if (setoptions_result == -1) { Assert(0 && "failed to set options"); error__need_child_kill = 1; goto launch_error; } launch_status = LaunchStatus_Success; launch_error:; } //- rjf: respond to launch status appropriately switch(launch_status) { //- rjf: no understood handling path default:{}break; //- rjf: failure, after ptrace => we need to explicitly obtain the // result code & exit the process, otherwise it will become a zombie, // since it is ptrace'd. case LaunchStatus_FailAfterPtrace: { B32 cleanup_good = 0; int detach_result = ptrace(PTRACE_DETACH, pid, 0, (void*)SIGCONT); if(detach_result != -1) { int status_cleanup = 0; pid_t wait_id_cleanup = waitpid(pid, &status_cleanup, __WALL); if(wait_id_cleanup == pid) { cleanup_good = 1; } } if(cleanup_good) { // TODO(rjf): child initialization failed, but we at least cleaned it up. } else { // TODO(rjf): child initialization failed, *and* we couldn't clean it up, so we've created // yet-another zombie. } }break; //- rjf: successful launch case LaunchStatus_Success: { ELF_Hdr64 exe_ehdr = dmn_lnx_ehdr_from_pid(pid); int memory_fd = open((char*)str8f(scratch.arena, "/proc/%d/mem", pid).str, O_RDWR|O_CLOEXEC); DMN_LNX_ProcessAuxv auxv = dmn_lnx_auxv_from_pid(pid, exe_ehdr.e_ident[ELF_Identifier_Class]); Arch arch = arch_from_elf_machine(exe_ehdr.e_machine); U64 rdebug_vaddr = dmn_lnx_rdebug_vaddr_from_memory(memory_fd, auxv.base); U64 rdebug_brk_vaddr = rdebug_vaddr + gnu_r_brk_offset_from_arch(arch); ELF_Class dl_class; { ELF_Hdr64 ehdr = {0}; if(!dmn_lnx_read_ehdr(memory_fd, auxv.base, &ehdr)) { Assert(0 && "failed to read interp's header"); } dl_class = ehdr.e_ident[ELF_Identifier_Class]; } U64 xcr0 = 0; U64 xsave_size = 0; X64_XSaveLayout xsave_layout = {0}; if(arch == Arch_x64) { X64_XSave xsave = {0}; if(ptrace(PTRACE_GETREGSET, pid, (void*)NT_X86_XSTATE, &(struct iovec){.iov_base = &xsave, .iov_len = sizeof(xsave) }) >= 0) { // Linux stores xcr0 bits in fxstate padding, // see https://github.com/torvalds/linux/blob/6548d364a3e850326831799d7e3ea2d7bb97ba08/arch/x86/include/asm/user.h#L25 xcr0 = *(U64 *)((U8 *)&xsave + 464); xsave_size = x64_get_xsave_size(); xsave_layout = x64_get_xsave_layout(xcr0); } else { Assert(0 && "failed to get xstate"); } } String8 dl_path = {0}; { int maps_fd = open((char *)str8f(scratch.arena, "/proc/%d/maps", pid).str, O_RDONLY|O_CLOEXEC); if(maps_fd != -1) { struct stat st = {0}; if(fstat(maps_fd, &st) != -1) { U64 maps_size = dmn_lnx_size_from_fd(maps_fd, MB(1)); U8 *maps_ptr = push_array(scratch.arena, U8, maps_size); U64 read_size = dmn_lnx_read(maps_fd, r1u64(0, maps_size), maps_ptr); if(read_size == maps_size) { String8 maps = str8(maps_ptr, maps_size); String8List parts = {0}; { for(U64 cursor = 0, part_off = 0; cursor < maps.size; cursor += 1) { if(maps.str[cursor] == '\\') { cursor += 1; continue; } if(maps.str[cursor] == ' ' || maps.str[cursor] == '\n' || cursor + 1 >= maps.size) { String8 p = str8_substr(maps, r1u64(part_off, cursor)); if(p.size > 0) { str8_list_push(scratch.arena, &parts, p); } part_off = cursor + 1; } } } for(String8Node *n = parts.first; n != 0; ) { String8 vrange_str = n->string; n = n->next; if(n == 0) { break; } String8 perms_str = n->string; n = n->next; if(n == 0) { break; } String8 offset_str = n->string; n = n->next; if(n == 0) { break; } String8 dev_str = n->string; n = n->next; if(n == 0) { break; } String8 inode_str = n->string; n = n->next; if(n == 0) { break; } String8 path = n->string; n = n->next; if(n == 0) { break; } String8List vaddr_list = str8_split_by_string_chars(scratch.arena, vrange_str, str8_lit("-"), 0); if(vaddr_list.node_count != 2) { break; } U64 lo_vaddr = u64_from_str8(vaddr_list.first->string, 16); if(lo_vaddr == auxv.base) { dl_path = push_str8_copy(scratch.arena, path); break; } } } } close(maps_fd); } } AssertAlways(dl_path.size); // alloc arena for the process Arena *process_arena = arena_alloc(); DMN_LNX_Probe **known_probes = push_array(process_arena, DMN_LNX_Probe *, DMN_LNX_ProbeType_Count); { DMN_LNX_ProbeList probes = {0}; int dl_fd = open((char *)dl_path.str, O_RDONLY|O_CLOEXEC); if(dl_fd >= 0) { probes = dmn_lnx_read_probes(process_arena, dl_fd, 0, auxv.base); close(dl_fd); } for EachNode(n, DMN_LNX_ProbeNode, probes.first) { DMN_LNX_Probe *p = &n->v; if(str8_match(p->provider, str8_lit("rtld"), 0)) { #define X(_N,_A,_S) if(str8_match(p->name, str8_lit(_S), 0)) { AssertAlways(p->args.count == _A); known_probes[DMN_LNX_ProbeType_##_N] = p; continue ; } DMN_LNX_Probe_XList #undef X } } } // install DL probes U64 probe_vaddrs[DMN_LNX_ProbeType_Count] = {0}; for EachIndex(i, DMN_LNX_ProbeType_Count) { if(known_probes[i] == 0) { continue; } U8 og_byte = 0; if(!dmn_lnx_read_struct(memory_fd, known_probes[i]->pc, &og_byte)) { Assert(0 && "failed to read original byte"); } Assert(og_byte == 0x90); U8 trap = 0xcc; if(!dmn_lnx_write_struct(memory_fd, known_probes[i]->pc, &trap)) { Assert(0 && "failed to install probe"); } probe_vaddrs[i] = known_probes[i]->pc; } // make process entity & push create event DMN_LNX_Entity *process = &dmn_lnx_nil_entity; { process = dmn_lnx_entity_alloc(dmn_lnx_state->entities_base, DMN_LNX_EntityKind_Process); process->arch = arch; process->id = pid; process->fd = memory_fd; process->tracer_tid = gettid(); process->rdebug_vaddr = rdebug_vaddr; process->rdebug_brk_vaddr = rdebug_brk_vaddr; process->expect_rdebug_data_breakpoint = rdebug_vaddr != 0; process->dl_class = dl_class; process->arena = process_arena; process->loaded_modules_ht = hash_table_init(process_arena, 0x1000); process->probes = known_probes; process->xcr0 = xcr0; process->xsave_size = Max(xsave_size, sizeof(X64_XSave)); process->xsave_layout = xsave_layout; MemoryCopyTyped(&process->probe_vaddrs[0], &probe_vaddrs[0], DMN_LNX_ProbeType_Count); { DMN_Event *e = dmn_event_list_push(dmn_lnx_state->deferred_events_arena, &dmn_lnx_state->deferred_events); e->kind = DMN_EventKind_CreateProcess; e->process = dmn_lnx_handle_from_entity(process); e->arch = process->arch; e->code = pid; } } // make thread entity & push create event DMN_LNX_Entity *main_thread = &dmn_lnx_nil_entity; { main_thread = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Thread); main_thread->id = pid; main_thread->arch = process->arch; main_thread->reg_block = push_array(process->arena, U8, regs_block_size_from_arch(process->arch)); dmn_lnx_thread_read_reg_block(main_thread, main_thread->reg_block); { DMN_Event *e = dmn_event_list_push(dmn_lnx_state->deferred_events_arena, &dmn_lnx_state->deferred_events); e->kind = DMN_EventKind_CreateThread; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(main_thread); e->arch = main_thread->arch; e->code = main_thread->id; } } // make main module & push load module event { U64 base_vaddr = (auxv.phdr & ~(auxv.pagesz-1)); U64 rebase = exe_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; DMN_LNX_PhdrInfo phdr_info = dmn_lnx_phdr_info_from_memory(memory_fd, exe_ehdr.e_ident[ELF_Identifier_Class], rebase, auxv.phdr, auxv.phent, auxv.phnum); DMN_LNX_Entity *module = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Module); module->id = auxv.execfn; module->base_vaddr = base_vaddr; DMN_Event *e = dmn_event_list_push(dmn_lnx_state->deferred_events_arena, &dmn_lnx_state->deferred_events); e->kind = DMN_EventKind_LoadModule; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(main_thread); e->module = dmn_lnx_handle_from_entity(module); e->arch = process->arch; e->address = base_vaddr; e->size = dim_1u64(phdr_info.range); e->string = dmn_lnx_read_string(dmn_lnx_state->deferred_events_arena, process->fd, auxv.execfn); e->elf_phdr_vrange = r1u64(auxv.phdr, auxv.phdr + auxv.phent * auxv.phnum); e->elf_phdr_entsize = auxv.phent; hash_table_push_u64_raw(process->arena, process->loaded_modules_ht, 0, module); hash_table_push_u64_raw(process->arena, process->loaded_modules_ht, base_vaddr, module); } // rjf: handshake event { DMN_Event *e = dmn_event_list_push(dmn_lnx_state->deferred_events_arena, &dmn_lnx_state->deferred_events); e->kind = DMN_EventKind_HandshakeComplete; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(main_thread); e->arch = process->arch; } }break; } } //- rjf: error case goto success; error:; { if(error__need_child_kill) { // TODO(rjf) } } //- rjf: success success:; // clean up pipes close(pipe_fds[0]); close(pipe_fds[1]); } scratch_end(scratch); return 0; } internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid) { return 0; } internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code) { B32 result = 0; DMN_LNX_Entity *process_entity = dmn_lnx_entity_from_handle(process); if(process_entity != &dmn_lnx_nil_entity && kill(process_entity->id, SIGKILL) != -1) { result = 1; } return result; } internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process) { B32 result = 0; DMN_LNX_Entity *process_entity = dmn_lnx_entity_from_handle(process); if(process_entity != &dmn_lnx_nil_entity && ptrace(PTRACE_DETACH, process_entity->id, 0, 0) != -1) { result = 1; } return result; } internal void dmn_lnx_wait_for_events(Arena *arena, DMN_EventList *evts, pid_t tid, B32 wait_for_group_stop, DMN_ActiveTrap *active_traps) { for(B32 done = 0; !done;) { //- rjf: wait for next event int status = 0; pid_t wait_id = waitpid(tid, &status, __WALL|__WNOTHREAD); if(status == -1 && errno == EINTR) {continue;} // wait interrupted, try again if(status == -1) {InvalidPath;} // TODO: graceful exit //- rjf: unpack event int wifexited = WIFEXITED(status); int wifsignaled = WIFSIGNALED(status); int wifstopped = WIFSTOPPED(status); int wstopsig = WSTOPSIG(status); int ptrace_event_code = (status>>16); DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id); DMN_LNX_Entity *process = thread->parent; //printf("waitpid - pid %d wifexited %d, wifsignaled %d, wifstopped %d, wstopsig %d\n", wait_id, wifexited, wifsignaled, wifstopped, wstopsig); // update thread registers if(thread != &dmn_lnx_nil_entity) { if (!dmn_lnx_thread_read_reg_block(thread, thread->reg_block)) { Assert(0 && "failed to update thread's registers"); } } DMN_EventKind e_kind = DMN_EventKind_Null; U64 exit_code = max_U64; U64 address = 0; DMN_Trap *hit_user_trap = 0; pid_t new_pid = 0; B32 is_group_stop = 0; //- rjf: WIFEXITED(status) -> thread exit if(wifexited) { e_kind = DMN_EventKind_ExitThread; } //- rjf: WIFEXITED(status) -> thread exit w/ exit code else if(wifsignaled) { e_kind = DMN_EventKind_ExitThread; exit_code = WTERMSIG(status); } //- rjf: SIGTRAP:PTRACE_EVENT_EXIT else if(wifstopped && wstopsig == SIGTRAP && ptrace_event_code == PTRACE_EVENT_EXIT) { // TODO(rjf): verify e_kind = DMN_EventKind_ExitThread; } //- rjf: SIGTRAP:PTRACE_EVENT_CLONE else if(wifstopped && (status >> 8) == (SIGTRAP | PTRACE_EVENT_CLONE << 8)) { if(ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_pid) >= 0) { e_kind = DMN_EventKind_CreateThread; } else { Assert(0 && "failed to get new tid"); } } //- rjf: SIGTRAP:PTRACE_EVENT_FORK, or SIGTRAP:PTRACE_EVENT_VFORK else if(wifstopped && wstopsig == SIGTRAP && (ptrace_event_code == PTRACE_EVENT_FORK || ptrace_event_code == PTRACE_EVENT_VFORK)) { } // group stop else if(wifstopped && wstopsig == SIGTRAP && status >> 16 == PTRACE_EVENT_STOP) { is_group_stop = 1; } //- rjf: SIGTRAP else if(wifstopped && wstopsig == SIGTRAP) { // translate signal code to DEMON event kind siginfo_t siginfo = {0}; if(ptrace(PTRACE_GETSIGINFO, wait_id, 0, &siginfo) < 0) { Assert(0 && "failed to get signal info"); } switch(siginfo.si_code) { case DMN_LNX_SigTrapCode_Brkpt: { e_kind = DMN_EventKind_Breakpoint; }break; case DMN_LNX_SigTrapCode_Trace: { e_kind = DMN_EventKind_SingleStep; }break; case DMN_LNX_SigTrapCode_HwBkpt: { if(thread->arch == Arch_Null) { } else if(thread->arch == Arch_x64) { REGS_RegBlockX64 *regs_x64 = thread->reg_block; if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B0) { address = regs_x64->dr0.u64; e_kind = DMN_EventKind_Breakpoint; } else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B1) { address = regs_x64->dr1.u64; e_kind = DMN_EventKind_Breakpoint; } else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B2) { address = regs_x64->dr2.u64; e_kind = DMN_EventKind_Breakpoint; } else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B3) { address = regs_x64->dr3.u64; e_kind = DMN_EventKind_Breakpoint; } } else { NotImplemented; } }break; case SI_KERNEL: { e_kind = DMN_EventKind_Breakpoint; }break; case DMN_LNX_SigTrapCode_Unk: {NotImplemented;}break; case DMN_LNX_SigTrapCode_Perf: {NotImplemented;}break; default: {InvalidPath;} break; } } //- rjf: WSTOPSIG(status) is SIGSTOP else if(wifstopped && wstopsig == SIGSTOP) { // // TODO(rjf): how do we tell the following apart?: // - SIGSTOP All-Stop // - SIGSTOP Halt // - SIGSTOP "User" // // we are currently just assuming that, if we've queried a SIGSTOP to halt, then // the first one that comes back is our "dummy" sigstop. this is likely not // necessarily true. // if(thread->expecting_dummy_sigstop) { thread->expecting_dummy_sigstop = 0; done = 0; } else if(dmn_lnx_state->has_halt_injection) { e_kind = DMN_EventKind_Halt; } else { // TODO(rjf): study this case; old notes: // // a signal we don't want to mess with (except to record that it // happened maybe) we should "hand it back" } } //- rjf: WSTOPSIG(status) is an unrecoverable exception (unless user does something to fix state first) else if(wifstopped) { e_kind = DMN_EventKind_Exception; } else { Assert(0 && "unexpected stop code"); } dmn_lnx_state->last_event_kind = e_kind; dmn_lnx_state->last_stop_pid = wait_id; dmn_lnx_state->last_sig_code = wstopsig; if(wait_for_group_stop) { if(is_group_stop) { done = 1; } } else { done = 1; } if(e_kind == DMN_EventKind_Breakpoint) { U64 ip = dmn_lnx_thread_read_ip(thread); for EachNode(active_trap, DMN_ActiveTrap, active_traps) { if(active_trap->trap->vaddr == ip-1) { hit_user_trap = active_trap->trap; break; } } } // is this a probe trap? if(e_kind == DMN_EventKind_Breakpoint) { // find which probe was triggered U64 ip = dmn_lnx_thread_read_ip(thread); DMN_LNX_ProbeType probe_type = DMN_LNX_ProbeType_Null; for EachIndex(i, ArrayCount(process->probe_vaddrs)) { if(process->probe_vaddrs[i] == ip-1) { probe_type = i; break; } } if(probe_type == DMN_LNX_ProbeType_InitComplete) { U64 name_space_id = 0, rdebug_addr = 0; DMN_LNX_Probe *probe = process->probes[DMN_LNX_ProbeType_InitComplete]; if(stap_read_arg_u(probe->args.v[0], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { if(stap_read_arg_u(probe->args.v[1], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_addr)) { GNU_RDebugInfo64 rdebug = {0}; if(dmn_lnx_read_r_debug(process->fd, rdebug_addr, process->arch, &rdebug)) { if(rdebug.r_version == 1) { dmn_lnx_process_loaded_modules(arena, evts, process, name_space_id, rdebug.r_map); } else { Assert(0 && "unexpected version number"); } } else { Assert(0 && "failed to read rdebug"); } } else { Assert(0 && "failed to parse second argument"); } } else { Assert(0 && "failed to parse first argument"); } } else if(probe_type == DMN_LNX_ProbeType_RelocComplete) { U64 name_space_id = 0, new_link_map_addr = 0; DMN_LNX_Probe *probe = process->probes[DMN_LNX_ProbeType_RelocComplete]; if(stap_read_arg_u(probe->args.v[0], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { if(stap_read_arg_u(probe->args.v[2], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &new_link_map_addr)) { dmn_lnx_process_loaded_modules(arena, evts, process, name_space_id, new_link_map_addr); } else { Assert(0 && "failed to parse third argument"); } } else { Assert(0 && "failed to parse first argument"); } } else if(probe_type == DMN_LNX_ProbeType_UnmapComplete) { // read probe's arguments U64 name_space_id = 0, rdebug_vaddr = 0; DMN_LNX_Probe *probe = process->probes[DMN_LNX_ProbeType_UnmapComplete]; if(stap_read_arg_u(probe->args.v[0], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { if(stap_read_arg_u(probe->args.v[1], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_vaddr)) { dmn_lnx_process_unloaded_modules(arena, evts, process, name_space_id, rdebug_vaddr); } else { Assert(0 && "failed to read second argument"); } } else { Assert(0 && "failed to read first argument"); } } if(probe_type != DMN_LNX_ProbeType_Null) {break;} } // rollback IP on user traps if(hit_user_trap) { U64 ip = dmn_lnx_thread_read_ip(thread); dmn_lnx_thread_write_ip(thread, ip - 1); } switch(e_kind) { case DMN_EventKind_COUNT: case DMN_EventKind_Null: break; case DMN_EventKind_Error: case DMN_EventKind_HandshakeComplete: case DMN_EventKind_LoadModule: case DMN_EventKind_UnloadModule: {InvalidPath;}break; case DMN_EventKind_Trap: case DMN_EventKind_Memory: case DMN_EventKind_SetThreadName: case DMN_EventKind_SetThreadColor: case DMN_EventKind_SetBreakpoint: case DMN_EventKind_UnsetBreakpoint: case DMN_EventKind_SetVAddrRangeNote: case DMN_EventKind_DebugString: { NotImplemented; }break; case DMN_EventKind_SingleStep: { // clear single step flag dmn_lnx_set_single_step_flag(thread, 0); DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = e_kind; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); e->instruction_pointer = dmn_lnx_thread_read_ip(thread); }break; case DMN_EventKind_Breakpoint: { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = e_kind; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); e->instruction_pointer = dmn_lnx_thread_read_ip(thread); }break; case DMN_EventKind_Halt: { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_Halt; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); }break; case DMN_EventKind_Exception: { // TODO(rjf): possible cases: // SIGABRT // SIGFPE // SIGSEGV // SIGILL DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_Exception; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); e->instruction_pointer = dmn_lnx_thread_read_ip(thread); e->signo = wstopsig; }break; case DMN_EventKind_CreateProcess: { NotImplemented; }break; case DMN_EventKind_ExitProcess: { // rjf: generate exit-thread / unload-module events for(DMN_LNX_Entity *child = process->first; child != &dmn_lnx_nil_entity; child = child->next) { switch(child->kind) { default:{}break; case DMN_LNX_EntityKind_Thread: { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_ExitThread; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(child); }break; case DMN_LNX_EntityKind_Module: { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_UnloadModule; e->process = dmn_lnx_handle_from_entity(process); e->module = dmn_lnx_handle_from_entity(child); // TODO(rjf): e->string = ...; }break; } } // rjf: generate exit process event { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_ExitProcess; e->process = dmn_lnx_handle_from_entity(process); e->code = exit_code; } // rjf: eliminate entity tree dmn_lnx_entity_release(process); }break; case DMN_EventKind_CreateThread: { DMN_LNX_Entity *thread = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Thread); thread->id = new_pid; thread->arch = process->arch; thread->reg_block = push_array(process->arena, U8, regs_block_size_from_arch(process->arch)); dmn_lnx_thread_read_reg_block(thread, thread->reg_block); DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_CreateThread; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); e->arch = thread->arch; e->code = thread->id; }break; case DMN_EventKind_ExitThread: { DMN_Event *e = dmn_event_list_push(arena, evts); e->kind = DMN_EventKind_ExitThread; e->process = dmn_lnx_handle_from_entity(process); e->thread = dmn_lnx_handle_from_entity(thread); dmn_lnx_entity_release(thread); }break; } } } internal DMN_EventList dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { Temp scratch = scratch_begin(&arena, 1); DMN_EventList evts = {0}; //////////////////////////// //- rjf: push any deferred events // { for EachNode(n, DMN_EventNode, dmn_lnx_state->deferred_events.first) { DMN_Event *e_src = &n->v; DMN_Event *e_dst = dmn_event_list_push(arena, &evts); MemoryCopyStruct(e_dst, e_src); e_dst->string = str8_copy(arena, e_dst->string); } MemoryZeroStruct(&dmn_lnx_state->deferred_events); arena_clear(dmn_lnx_state->deferred_events_arena); } //////////////////////////// //- rjf: no processes, no output events -> not attached // if(evts.count == 0 && dmn_lnx_state->entities_base->first == &dmn_lnx_nil_entity) { DMN_Event *e = dmn_event_list_push(arena, &evts); e->kind = DMN_EventKind_Error; e->error_kind = DMN_ErrorKind_NotAttached; } //////////////////////////// //- rjf: determine if we need to wait for new events // B32 need_wait_on_events = (evts.count == 0); //////////////////////////// //- rjf: write all traps into memory // DMN_ActiveTrap *active_trap_first = 0, *active_trap_last = 0; ProfScope("write all traps into memory") { HashTable *ht = hash_table_init(scratch.arena, ctrls->traps.trap_count); for EachNode(n, DMN_TrapChunkNode, ctrls->traps.first) { for EachIndex(n_idx, n->count) { DMN_Trap *trap = n->v+n_idx; if(trap->flags == 0) { DMN_ActiveTrap *is_set = hash_table_search_u64_raw(ht, trap->vaddr); if(is_set) { continue; } U8 swap_byte = 0; if(dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &swap_byte) > 0) { U8 int3 = 0xCC; if(dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &int3)) { DMN_ActiveTrap *active_trap = push_array(scratch.arena, DMN_ActiveTrap, 1); active_trap->trap = trap; active_trap->swap_byte = swap_byte; SLLQueuePush(active_trap_first, active_trap_last, active_trap); hash_table_push_u64_raw(scratch.arena, ht, trap->vaddr, active_trap); } else { Assert(0 && "failed to write trap"); } } else { Assert(0 && "failed to read original byte"); } } } } } //////////////////////////// //- enable single stepping if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) { DMN_LNX_Entity *single_step_thread = dmn_lnx_entity_from_handle(ctrls->single_step_thread); dmn_lnx_set_single_step_flag(single_step_thread, 1); } //////////////////////////// //- rjf: gather all threads which we should run // DMN_LNX_EntityList run_threads = {0}; if(need_wait_on_events) ProfScope("gather all threads which we should run") { //- rjf: scan all processes for(DMN_LNX_Entity *process = dmn_lnx_state->entities_base->first; process != &dmn_lnx_nil_entity; process = process->next) { if(process->kind != DMN_LNX_EntityKind_Process) { continue; } //- rjf: determine if this process is frozen B32 process_is_frozen = 0; if(ctrls->run_entities_are_processes) { for EachIndex(idx, ctrls->run_entity_count) { if(dmn_handle_match(ctrls->run_entities[idx], dmn_lnx_handle_from_entity(process))) { process_is_frozen = 1; break; } } } //- rjf: scan all threads in this process for(DMN_LNX_Entity *thread = process->first; thread != &dmn_lnx_nil_entity; thread = thread->next) { if(thread->kind != DMN_LNX_EntityKind_Thread) { continue; } //- rjf: determine if this thread is frozen B32 is_frozen = 0; { // rjf: single-step? freeze if not the single-step thread. if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread)) { is_frozen = !dmn_handle_match(dmn_lnx_handle_from_entity(thread), ctrls->single_step_thread); } // rjf: not single-stepping? determine based on run controls freezing info else { if(ctrls->run_entities_are_processes) { is_frozen = process_is_frozen; } else { for EachIndex(idx, ctrls->run_entity_count) { if(dmn_handle_match(ctrls->run_entities[idx], dmn_lnx_handle_from_entity(thread))) { is_frozen = 1; break; } } } if(ctrls->run_entities_are_unfrozen) { is_frozen ^= 1; } } } //- rjf: add to list if(!is_frozen) { dmn_lnx_entity_list_push(scratch.arena, &run_threads, thread); } } } } //////////////////////////// //- rjf: resume all threads we need to run // DMN_LNX_EntityList ran_threads = {0}; for EachNode(n, DMN_LNX_EntityNode, run_threads.first) { DMN_LNX_Entity *thread = n->v; // update registers if(!dmn_lnx_thread_write_reg_block(thread, thread->reg_block)) { Assert(0 && "failed to write thread's registers"); } // pass signal to the child process void *sig_code = 0; if(dmn_lnx_state->last_event_kind == DMN_EventKind_Exception && dmn_lnx_state->last_stop_pid == thread->id) { sig_code = (void *)(uintptr_t)dmn_lnx_state->last_sig_code; } // resume thread if (ptrace(PTRACE_CONT, (pid_t)thread->id, 0, (void *)sig_code) < 0) { Assert(0 && "failed to resume a thread"); } dmn_lnx_entity_list_push(scratch.arena, &ran_threads, thread); } //////////////////////////// //- rjf: loop: wait for next stop, produce debug events // if(need_wait_on_events) { dmn_lnx_wait_for_events(arena, &evts, -1, 0, active_trap_first); } //////////////////////////// //- rjf: stop all threads // { B32 was_interrupt_issued = 0; for EachNode(n, DMN_LNX_EntityNode, ran_threads.first) { if(n->v->id != dmn_lnx_state->last_stop_pid) { if(ptrace(PTRACE_INTERRUPT, n->v->id, 0, 0) >= 0) { was_interrupt_issued = 1; } else { Assert(0 && "failed to interrupt thread"); } } } if(was_interrupt_issued) { dmn_lnx_wait_for_events(arena, &evts, -1, 1, active_trap_first); } } // update registers for EachNode(n, DMN_LNX_EntityNode, ran_threads.first) { dmn_lnx_thread_read_reg_block(n->v, n->v->reg_block); } ////////////////////////// //- rjf: restore original memory at trap locations // ProfScope("restore original memory at trap locations") { for EachNode(active_trap, DMN_ActiveTrap, active_trap_first) { if(!dmn_process_write_struct(active_trap->trap->process, active_trap->trap->vaddr, &active_trap->swap_byte)) { Assert(0 && "failed to restore original memory"); } } } scratch_end(scratch); return evts; } //////////////////////////////// //~ rjf: @dmn_os_hooks Halting (Implemented Per-OS) internal void dmn_halt(U64 code, U64 user_data) { if(!dmn_lnx_state->has_halt_injection) { DMN_LNX_Entity *process = dmn_lnx_state->entities_base->first; if(process != &dmn_lnx_nil_entity) { union sigval sv = {0}; if(sigqueue(process->id, SIGSTOP, sv) != -1) { dmn_lnx_state->has_halt_injection = 1; dmn_lnx_state->halt_code = code; dmn_lnx_state->halt_user_data = user_data; } } } } //////////////////////////////// //~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS) //- rjf: non-blocking-control-thread access barriers internal B32 dmn_access_open(void) { B32 result = 0; if(dmn_lnx_ctrl_thread) { result = 1; } else { mutex_take(dmn_lnx_state->access_mutex); result = !dmn_lnx_state->access_run_state; } return result; } internal void dmn_access_close(void) { if(!dmn_lnx_ctrl_thread) { mutex_drop(dmn_lnx_state->access_mutex); } } //- rjf: processes internal U64 dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size) { return 0; } internal void dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size) { } internal void dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size) { } internal void dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size) { } internal void dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags) { } internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst) { DMN_LNX_Entity *entity = dmn_lnx_entity_from_handle(process); U64 result = dmn_lnx_read(entity->fd, range, dst); return result; } internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src) { DMN_LNX_Entity *entity = dmn_lnx_entity_from_handle(process); B32 result = dmn_lnx_write(entity->fd, range, src); return result; } //- rjf: threads internal Arch dmn_arch_from_thread(DMN_Handle handle) { DMN_LNX_Entity *thread = dmn_lnx_entity_from_handle(handle); return thread->arch; } internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle) { return 0; } internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle) { return 0; } internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block) { B32 result = 0; DMN_AccessScope { DMN_LNX_Entity *thread = dmn_lnx_entity_from_handle(handle); U64 reg_block_size = regs_block_size_from_arch(thread->arch); if(thread == &dmn_lnx_nil_entity) { MemoryZero(reg_block, reg_block_size); } else { MemoryCopy(reg_block, thread->reg_block, reg_block_size); } result = 1; } return result; } internal B32 dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block) { B32 result = 0; DMN_AccessScope { DMN_LNX_Entity *thread = dmn_lnx_entity_from_handle(handle); U64 reg_block_size = regs_block_size_from_arch(thread->arch); if(thread == &dmn_lnx_nil_entity) { MemoryZero(reg_block, reg_block_size); } else { MemoryCopy(thread->reg_block, reg_block, reg_block_size); } result = 1; } return result; } //- rjf: system process listing internal void dmn_process_iter_begin(DMN_ProcessIter *iter) { DIR *dir = opendir("/proc"); MemoryZeroStruct(iter); iter->v[0] = IntFromPtr(dir); } internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out) { // rjf: scan for the next process ID in the directory B32 got_pid = 0; String8 pid_string = {0}; { DIR *dir = (DIR*)PtrFromInt(iter->v[0]); if(dir != 0 && iter->v[1] == 0) { for(;;) { // rjf: get next entry struct dirent *d = readdir(dir); if(d == 0) { break; } // rjf: check file name is integer String8 file_name = str8_cstring((char*)d->d_name); B32 is_integer = str8_is_integer(file_name, 10); // rjf: break on integers (which represent processes) if(is_integer) { got_pid = 1; pid_string = file_name; break; } } } } // rjf: if we found a process id, map id => info B32 result = 0; if(got_pid) { pid_t pid = u64_from_str8(pid_string, 10); String8 name = dmn_lnx_exe_path_from_pid(arena, pid); if(name.size == 0) { name = str8_lit("(unknown process)"); } info_out->name = name; info_out->pid = pid; result = 1; } return result; } internal void dmn_process_iter_end(DMN_ProcessIter *iter) { DIR *dir = (DIR*)PtrFromInt(iter->v[0]); if(dir != 0) { closedir(dir); } MemoryZeroStruct(iter); } ================================================ FILE: src/demon/linux/demon_core_linux.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_LINUX_H #define DEMON_CORE_LINUX_H //////////////////////////////// //~ rjf: Includes #include #include #include //////////////////////////////// //~ SIGTRAP codes enum { DMN_LNX_SigTrapCode_Brkpt = 1, DMN_LNX_SigTrapCode_Trace = 2, DMN_LNX_SigTrapCode_Branch = 3, DMN_LNX_SigTrapCode_HwBkpt = 4, DMN_LNX_SigTrapCode_Unk = 5, DMN_LNX_SigTrapCode_Perf = 6 } DMN_LNX_SigTrapCode; //////////////////////////////// //~ rjf: Register Layouts // // These are defined in , but only for one architecture at a time typedef struct DMN_LNX_UserX64 DMN_LNX_UserX64; struct DMN_LNX_UserX64 { struct { U64 r15; U64 r14; U64 r13; U64 r12; U64 rbp; U64 rbx; U64 r11; U64 r10; U64 r9; U64 r8; U64 rax; U64 rcx; U64 rdx; U64 rsi; U64 rdi; U64 orig_rax; U64 rip; U64 cs; U64 rflags; U64 rsp; U64 ss; U64 fsbase; U64 gsbase; U64 ds; U64 es; U64 fs; U64 gs; } regs; S32 u_fpvalid, _pad0; X64_FXSave i387; U64 u_tsize, u_dsize, u_ssize, start_code, start_stack; U64 signal; S32 reserved, _pad1; U64 u_ar0, u_fpstate; U64 magic; U8 u_comm[32]; U64 u_debugreg[8]; }; StaticAssert(sizeof(DMN_LNX_UserX64) == 912, g_dmn_lnx_user_x64_size_check); //////////////////////////////// //~ SDT Probes typedef struct DMN_LNX_Probe DMN_LNX_Probe; struct DMN_LNX_Probe { String8 provider; String8 name; String8 args_string; STAP_ArgArray args; U64 pc; U64 semaphore; }; typedef struct DMN_LNX_ProbeNode DMN_LNX_ProbeNode; struct DMN_LNX_ProbeNode { DMN_LNX_Probe v; DMN_LNX_ProbeNode *next; }; typedef struct DMN_LNX_ProbeList DMN_LNX_ProbeList; struct DMN_LNX_ProbeList { U64 count; DMN_LNX_ProbeNode *first; DMN_LNX_ProbeNode *last; }; #define DMN_LNX_Probe_XList \ X(InitStart, 2, "init_start") \ X(InitComplete, 2, "init_complete") \ X(RelocStart, 2, "reloc_start") \ X(RelocComplete, 3, "reloc_complete") \ X(MapStart, 2, "map_start") \ X(MapComplete, 3, "map_complete") \ X(UnmapStart, 2, "unmap_start") \ X(UnmapComplete, 2, "unmap_complete") \ X(LongJmp, 3, "longjmp") \ X(LongJmpTarget, 3, "longjmp_target") \ X(SetJmp, 3, "setjmp") typedef enum { DMN_LNX_ProbeType_Null, #define X(_N,...) DMN_LNX_ProbeType_##_N, DMN_LNX_Probe_XList #undef X DMN_LNX_ProbeType_Count, } DMN_LNX_ProbeType; //////////////////////////////// //~ rjf: Process Info Extraction Types typedef struct DMN_LNX_ProcessAuxv DMN_LNX_ProcessAuxv; struct DMN_LNX_ProcessAuxv { U64 base; U64 phnum; U64 phent; U64 phdr; U64 execfn; U64 pagesz; }; typedef struct DMN_LNX_PhdrInfo DMN_LNX_PhdrInfo; struct DMN_LNX_PhdrInfo { Rng1U64 range; U64 dynamic; }; typedef struct DMN_LNX_DynamicInfo DMN_LNX_DynamicInfo; struct DMN_LNX_DynamicInfo { U64 hash_vaddr; U64 gnu_hash_vaddr; U64 strtab_vaddr; U64 strtab_size; U64 symtab_vaddr; U64 symtab_entry_size; }; //////////////////////////////// //~ rjf: Entity Types typedef enum DMN_LNX_EntityKind { DMN_LNX_EntityKind_Null, DMN_LNX_EntityKind_Root, DMN_LNX_EntityKind_Process, DMN_LNX_EntityKind_Thread, DMN_LNX_EntityKind_Module, DMN_LNX_EntityKind_COUNT } DMN_LNX_EntityKind; typedef struct DMN_LNX_Entity DMN_LNX_Entity; struct DMN_LNX_Entity { DMN_LNX_Entity *first; DMN_LNX_Entity *last; DMN_LNX_Entity *next; DMN_LNX_Entity *prev; DMN_LNX_Entity *parent; DMN_LNX_EntityKind kind; U32 gen; Arch arch; U64 id; // process Arena *arena; int fd; pid_t tracer_tid; B32 expect_rdebug_data_breakpoint; U64 rdebug_vaddr; U64 rdebug_brk_vaddr; ELF_Class dl_class; HashTable *loaded_modules_ht; DMN_LNX_Probe **probes; U64 probe_vaddrs[DMN_LNX_ProbeType_Count]; // process x64 U64 xcr0; U64 xsave_size; X64_XSaveLayout xsave_layout; // thread B32 expecting_dummy_sigstop; void *reg_block; // module U64 base_vaddr; U64 phvaddr; U64 phentsize; U64 phcount; B8 is_live; }; typedef struct DMN_LNX_EntityNode DMN_LNX_EntityNode; struct DMN_LNX_EntityNode { DMN_LNX_EntityNode *next; DMN_LNX_Entity *v; }; typedef struct DMN_LNX_EntityList DMN_LNX_EntityList; struct DMN_LNX_EntityList { U64 count; DMN_LNX_EntityNode *first; DMN_LNX_EntityNode *last; }; //////////////////////////////// //~ rjf: Main State Bundle typedef struct DMN_LNX_State DMN_LNX_State; struct DMN_LNX_State { Arena *arena; // rjf: access locking mechanism Mutex access_mutex; B32 access_run_state; // rjf: deferred events Arena *deferred_events_arena; DMN_EventList deferred_events; // rjf: entity storage Arena *entities_arena; DMN_LNX_Entity *entities_base; U64 entities_count; DMN_LNX_Entity *free_entity; // rjf: halting mechanism B32 has_halt_injection; U64 halt_code; U64 halt_user_data; DMN_EventKind last_event_kind; pid_t last_stop_pid; int last_sig_code; }; read_only global DMN_LNX_Entity dmn_lnx_nil_entity = {&dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity}; global DMN_LNX_State *dmn_lnx_state = 0; thread_static B32 dmn_lnx_ctrl_thread = 0; //////////////////////////////// //~ rjf: Helpers internal DMN_LNX_EntityNode * dmn_lnx_entity_list_push(Arena *arena, DMN_LNX_EntityList *list, DMN_LNX_Entity *v); //- rjf: file descriptor memory reading/writing helpers internal U64 dmn_lnx_read(int memory_fd, Rng1U64 range, void *dst); internal B32 dmn_lnx_write(int memory_fd, Rng1U64 range, void *src); #define dmn_lnx_read_struct(fd, vaddr, ptr) dmn_lnx_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr)) #define dmn_lnx_write_struct(fd, vaddr, ptr) dmn_lnx_write((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr)) internal String8 dmn_lnx_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size); internal String8 dmn_lnx_read_string(Arena *arena, int memory_fd, U64 base_vaddr); //////////////////////////////// //~ Runtime Struct Helpers internal B32 dmn_lnx_read_ehdr(int memory_fd, U64 addr, ELF_Hdr64 *ehdr_out); internal B32 dmn_lnx_read_phdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out); internal B32 dmn_lnx_read_shdr(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out); internal B32 dmn_lnx_read_linkmap(int memory_fd, U64 addr, ELF_Class elf_class, GNU_LinkMap64 *link_map_out); internal B32 dmn_lnx_read_dynamic(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out); internal B32 dmn_lnx_read_symbol(int memory_fd, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out); internal B32 dmn_lnx_read_r_debug(int memory_fd, U64 addr, Arch arch, GNU_RDebugInfo64 *rdebug_out); //- rjf: pid => info extraction internal String8 dmn_lnx_exe_path_from_pid(Arena *arena, pid_t pid); internal ELF_Hdr64 dmn_lnx_ehdr_from_pid(pid_t pid); internal DMN_LNX_ProcessAuxv dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class); //- ELF/GNU info from memory internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum); internal DMN_LNX_DynamicInfo dmn_lnx_dynamic_info_from_memory(int memory_fd, ELF_Class elf_Class, U64 rebase, U64 dynamic_vaddr); internal U64 dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vaddr); //////////////////////////////// //~ rjf: Entity Functions internal DMN_LNX_Entity *dmn_lnx_entity_alloc(DMN_LNX_Entity *parent, DMN_LNX_EntityKind kind); internal void dmn_lnx_entity_release(DMN_LNX_Entity *entity); internal DMN_Handle dmn_lnx_handle_from_entity(DMN_LNX_Entity *entity); internal DMN_LNX_Entity *dmn_lnx_entity_from_handle(DMN_Handle handle); internal DMN_LNX_Entity *dmn_lnx_thread_from_pid(pid_t pid); internal U64 dmn_lnx_thread_read_ip(DMN_LNX_Entity *thread); internal U64 dmn_lnx_thread_read_sp(DMN_LNX_Entity *thread); internal B32 dmn_lnx_thread_write_ip(DMN_LNX_Entity *thread, U64 ip); internal B32 dmn_lnx_thread_write_sp(DMN_LNX_Entity *thread, U64 sp); internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block); internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread, void *reg_block); //////////////////////////////// internal B32 dmn_lnx_set_single_step_flag(DMN_LNX_Entity *thread, B32 is_on); #endif // DEMON_CORE_LINUX_H ================================================ FILE: src/demon/linux/demon_os_linux.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO(allen): run controls: ignore_previous_exception //////////////////////////////// //~ allen: Elf Parsing Code #include "syms/syms_elf_inc.c" //////////////////////////////// //~ rjf: Globals global B32 demon_lnx_already_has_halt_injection = false; global U64 demon_lnx_halt_code = 0; global U64 demon_lnx_halt_user_data = 0; global B32 demon_lnx_new_process_pending = false; global Arena *demon_lnx_event_arena = 0; global DEMON_EventList demon_lnx_queued_events = {0}; global U32 demon_lnx_ptrace_options = (PTRACE_O_TRACEEXIT| PTRACE_O_EXITKILL| PTRACE_O_TRACEFORK| PTRACE_O_TRACEVFORK| PTRACE_O_TRACECLONE); //////////////////////////////// //~ rjf: Helpers internal DEMON_LNX_ThreadExt* demon_lnx_thread_ext(DEMON_Entity *entity){ DEMON_LNX_ThreadExt *result = (DEMON_LNX_ThreadExt*)&entity->ext; return(result); } internal B32 demon_lnx_attach_pid(Arena *arena, pid_t pid, DEMON_LNX_AttachNode **new_node){ B32 result = false; int attach_result = ptrace(PTRACE_ATTACH, pid, 0, 0); if (attach_result == -1){ // TODO(allen): attach denied } else{ // return a new attachment node as soon as the ptrace exists. we use these nodes // for cleanup on failure *and* for initializing on success. either way we need // to see all new attachments whether or not they fully initialized correctly. DEMON_LNX_AttachNode *proc_attachment = push_array_no_zero(arena, DEMON_LNX_AttachNode, 1); proc_attachment->next = 0; proc_attachment->pid = pid; *new_node = proc_attachment; int status = 0; pid_t wait_id = waitpid(pid, &status, __WALL); // NOTE(allen): if wait_id != pid we don't know what that means; study that case before // deciding how error handling around it works. if (wait_id == pid){ int setoptions_result = ptrace(PTRACE_SETOPTIONS, pid, 0, PtrFromInt(demon_lnx_ptrace_options)); if (setoptions_result == -1){ // TODO(allen): setup failed } else{ result = true; } } } return(result); } internal String8 demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid){ // get symbolic path Temp scratch = scratch_begin(&arena, 1); String8 exe_symbol_path = push_str8f(scratch.arena, "/proc/%d/exe", pid); // try to read the link for a bit Temp restore_point = temp_begin(arena); B32 got_final_result = false; U8 *buffer = 0; int size = 0; S64 cap = PATH_MAX; for (S64 r = 0; r < 4; cap *= 2, r += 1){ temp_end(restore_point); buffer = push_array_no_zero(arena, U8, cap); size = readlink((char*)exe_symbol_path.str, (char*)buffer, cap); if (size < cap){ got_final_result = true; break; } } // finalize result String8 result = {0}; if (!got_final_result || size == -1){ temp_end(restore_point); } else{ arena_pop(arena, (cap - size - 1)); result = str8(buffer, size + 1); } scratch_end(scratch); return(result); } internal int demon_lnx_open_memory_fd_for_pid(pid_t pid){ Temp scratch = scratch_begin(0, 0); String8 memory_path = push_str8f(scratch.arena, "/proc/%i/mem", pid); int result = open((char*)memory_path.str, O_RDWR|O_CLOEXEC); scratch_end(scratch); return(result); } internal Arch demon_lnx_arch_from_pid(pid_t pid){ Temp scratch = scratch_begin(0, 0); Arch result = Arch_Null; // exe path String8 exe_path = demon_lnx_executable_path_from_pid(scratch.arena, pid); // handle to exe int exe_fd = -1; if (exe_path.size != 0){ exe_fd = open((char*)exe_path.str, O_RDONLY|O_CLOEXEC); } // elf identification B32 is_elf = false; U8 e_ident[SYMS_ElfIdentifier_NIDENT] = {0}; if (exe_fd >= 0){ if (pread(exe_fd, e_ident, sizeof(e_ident), 0) == sizeof(e_ident)){ is_elf = (e_ident[SYMS_ElfIdentifier_MAG0] == 0x7f && e_ident[SYMS_ElfIdentifier_MAG1] == 'E' && e_ident[SYMS_ElfIdentifier_MAG2] == 'L' && e_ident[SYMS_ElfIdentifier_MAG3] == 'F'); } } // elf class U8 elf_class = 0; if (is_elf){ elf_class = e_ident[SYMS_ElfIdentifier_CLASS]; } // exe header data SYMS_ElfEhdr64 ehdr = {0}; switch (elf_class){ case 1: { SYMS_ElfEhdr32 ehdr32 = {0}; if (pread(exe_fd, &ehdr32, sizeof(ehdr32), 0) == sizeof(ehdr32)){ ehdr = syms_elf_ehdr64_from_ehdr32(ehdr32); } }break; case 2: { pread(exe_fd, &ehdr, sizeof(ehdr), 0); }break; } // determine machine type switch (ehdr.e_machine){ case SYMS_ElfMachineKind_386: { result = Arch_x86; }break; case SYMS_ElfMachineKind_ARM: { result = Arch_arm32; }break; case SYMS_ElfMachineKind_X86_64: { result = Arch_x64; }break; case SYMS_ElfMachineKind_AARCH64: { result = Arch_arm64; }break; } scratch_end(scratch); return(result); } internal DEMON_LNX_ProcessAux demon_lnx_aux_from_pid(pid_t pid, Arch arch){ DEMON_LNX_ProcessAux result = {0}; B32 addr_32bit = (arch == Arch_x86 || arch == Arch_arm32); // open aux data Temp scratch = scratch_begin(0, 0); String8 auxv_symbol_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid); int aux_fd = open((char*)auxv_symbol_path.str, O_RDONLY|O_CLOEXEC); // scan aux data if (aux_fd >= 0){ for (;;){ result.filled = true; // read next aux U64 type = 0; U64 val = 0; if (addr_32bit){ SYMS_ElfAuxv32 aux; if (read(aux_fd, &aux, sizeof(aux)) != sizeof(aux)){ goto brkloop; } type = aux.a_type; val = aux.a_val; } else{ SYMS_ElfAuxv64 aux; if (read(aux_fd, &aux, sizeof(aux)) != sizeof(aux)){ goto brkloop; } type = aux.a_type; val = aux.a_val; } // place value in result switch (type){ default:break; case SYMS_ElfAuxType_NULL: goto brkloop; break; case SYMS_ElfAuxType_PHNUM: result.phnum = val; break; case SYMS_ElfAuxType_PHENT: result.phent = val; break; case SYMS_ElfAuxType_PHDR: result.phdr = val; break; case SYMS_ElfAuxType_EXECFN: result.execfn = val; break; } } brkloop:; close(aux_fd); } scratch_end(scratch); return(result); } internal DEMON_LNX_PhdrInfo demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, U64 phvaddr, U64 phentsize, U64 phcount){ DEMON_LNX_PhdrInfo result = {0}; result.range.min = max_U64; // how much phdr will we read? U64 phdr_size_expected = (is_32bit?sizeof(SYMS_ElfPhdr32):sizeof(SYMS_ElfPhdr64)); U64 phdr_stride = (phentsize?phentsize:phdr_size_expected); U64 phdr_read_size = ClampTop(phdr_stride, phdr_size_expected); // scan table U64 va = phvaddr; for (U64 i = 0; i < phcount; i += 1, va += phdr_stride){ // get type and range SYMS_ElfPKind p_type = 0; U64 p_vaddr = 0; U64 p_memsz = 0; if (is_32bit){ SYMS_ElfPhdr32 phdr32 = {0}; demon_lnx_read_memory(memory_fd, &phdr32, va, phdr_read_size); p_type = phdr32.p_type; p_vaddr = phdr32.p_vaddr; p_memsz = phdr32.p_memsz; } else{ SYMS_ElfPhdr64 phdr64 = {0}; demon_lnx_read_memory(memory_fd, &phdr64, va, phdr_read_size); p_type = phdr64.p_type; p_vaddr = phdr64.p_vaddr; p_memsz = phdr64.p_memsz; } // save useful info switch (p_type){ case SYMS_ElfPKind_Dynamic: { result.dynamic = p_vaddr; }break; case SYMS_ElfPKind_Load: { U64 min = p_vaddr; U64 max = p_vaddr + p_memsz; result.range.min = Min(result.range.min, min); result.range.max = Max(result.range.max, max); }break; } } return(result); } internal DEMON_LNX_ModuleNode* demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process){ Arch arch = (Arch)process->arch; B32 is_32bit = (arch == Arch_x86 || arch == Arch_arm32); int memory_fd = (int)process->ext_u64; // aux from pid DEMON_LNX_ProcessAux aux = demon_lnx_aux_from_pid((pid_t)process->id, arch); // extract info from program headers DEMON_LNX_PhdrInfo phdr_info = demon_lnx_phdr_info_from_memory(memory_fd, is_32bit, aux.phdr, aux.phent, aux.phnum); // linkmap first from memory space & dyn address U64 first_linkmap_va = 0; if (phdr_info.dynamic != 0){ U64 off = phdr_info.dynamic; for (;;){ SYMS_ElfDyn64 dyn = {0}; if (is_32bit){ SYMS_ElfDyn32 dyn32 = {0}; demon_lnx_read_memory(memory_fd, &dyn32, off, sizeof(dyn32)); dyn.tag = dyn32.tag; dyn.val = dyn32.val; off += sizeof(dyn32); } else{ demon_lnx_read_memory(memory_fd, &dyn, off, sizeof(dyn)); off += sizeof(dyn); } if (dyn.tag == SYMS_ElfDynTag_NULL){ break; } if (dyn.tag == SYMS_ElfDynTag_PLTGOT){ // True for x86 and x64 // vas[0] virtual address of .dynamic // vas[2] callback for resolving function address of relocation and if successful jumps to it. // // Code that sets up PLTGOT is in glibc/sysdeps/x86_64/dl_machine.h -> elf_machine_runtime_setup U64 vas_off = dyn.val; U64 vas[3] = {0}; demon_lnx_read_memory(memory_fd, vas, vas_off, sizeof(vas)); first_linkmap_va = vas[1]; break; } } } // setup output list DEMON_LNX_ModuleNode *first = 0; DEMON_LNX_ModuleNode *last = 0; // main module { DEMON_LNX_ModuleNode *node = push_array(arena, DEMON_LNX_ModuleNode, 1); SLLQueuePush(first, last, node); node->vaddr = phdr_info.range.min; node->size = phdr_info.range.max - phdr_info.range.min; node->name = aux.execfn; } // iterate link maps if (first_linkmap_va != 0){ U64 linkmap_va = first_linkmap_va; for (;;){ SYMS_ElfLinkMap64 linkmap = {0}; if (is_32bit){ // TOOD(nick): endian awarness SYMS_ElfLinkMap32 linkmap32 = {0}; demon_lnx_read_memory(memory_fd, &linkmap32, linkmap_va, sizeof(linkmap32)); linkmap.base = linkmap32.base; linkmap.name = linkmap32.name; linkmap.ld = linkmap32.ld; linkmap.next = linkmap32.next; } else{ demon_lnx_read_memory(memory_fd, &linkmap, linkmap_va, sizeof(linkmap)); } if (linkmap.base != 0){ // find phdrs for this module SYMS_U64 phvaddr = 0; SYMS_U64 phentsize = 0; SYMS_U64 phcount = 0; if (is_32bit){ SYMS_ElfEhdr32 ehdr = {0}; demon_lnx_read_memory(memory_fd, &ehdr, linkmap.base, sizeof(ehdr)); phvaddr = ehdr.e_phoff + linkmap.base; phentsize = ehdr.e_phentsize; phcount = ehdr.e_phnum; } else{ SYMS_ElfEhdr64 ehdr = {0}; demon_lnx_read_memory(memory_fd, &ehdr, linkmap.base, sizeof(ehdr)); phvaddr = ehdr.e_phoff + linkmap.base; phentsize = ehdr.e_phentsize; phcount = ehdr.e_phnum; } // extract info from phdrs DEMON_LNX_PhdrInfo module_phdr_info = demon_lnx_phdr_info_from_memory(memory_fd, is_32bit, phvaddr, phentsize, phcount); // save module node DEMON_LNX_ModuleNode *node = push_array(arena, DEMON_LNX_ModuleNode, 1); SLLQueuePush(first, last, node); node->vaddr = linkmap.base; node->size = module_phdr_info.range.max - module_phdr_info.range.min; node->name = linkmap.name; } linkmap_va = linkmap.next; if (linkmap_va == 0){ break; } } } return(first); } internal U64 demon_lnx_read_memory(int memory_fd, void *dst, U64 src, U64 size){ U64 bytes_read = 0; U8 *ptr = (U8*)dst; U8 *opl = ptr + size; U64 cursor = src; for (;ptr < opl;){ size_t to_read = (size_t)(opl - ptr); ssize_t actual_read = pread(memory_fd, ptr, to_read, cursor); if (actual_read == -1){ break; } ptr += actual_read; cursor += actual_read; bytes_read += actual_read; } return(bytes_read); } internal B32 demon_lnx_write_memory(int memory_fd, U64 dst, void *src, U64 size){ B32 result = true; U8 *ptr = (U8*)src; U8 *opl = ptr + size; U64 cursor = dst; for (;ptr < opl;){ size_t to_write = (size_t)(opl - ptr); ssize_t actual_write = pwrite(memory_fd, ptr, to_write, cursor); if (actual_write == -1){ result = false; break; } ptr += actual_write; cursor += actual_write; } return(result); } internal String8 demon_lnx_read_memory_str(Arena *arena, int memory_fd, U64 address){ // TODO(allen): this could be done better with a demon_lnx_read_memory // that returns a read amount instead of a success/fail. // scan piece by piece Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; U64 max_cap = 256; U64 cap = max_cap; U64 read_p = address; for (;;){ U8 *block = push_array(scratch.arena, U8, cap); for (;cap > 0;){ if (demon_lnx_read_memory(memory_fd, block, read_p, cap)){ break; } cap /= 2; } read_p += cap; U64 block_opl = 0; for (;block_opl < cap; block_opl += 1){ if (block[block_opl] == 0){ break; } } if (block_opl > 0){ str8_list_push(scratch.arena, &list, str8(block, block_opl)); } if (block_opl < cap || cap == 0){ break; } } // assemble results String8 result = str8_list_join(arena, &list, 0); scratch_end(scratch); return(result); } internal void demon_lnx_regs_x64_from_usr_regs_x64(SYMS_RegX64 *dst, DEMON_LNX_UserRegsX64 *src){ dst->rax.u64 = src->rax; dst->rcx.u64 = src->rcx; dst->rdx.u64 = src->rdx; dst->rbx.u64 = src->rbx; dst->rsp.u64 = src->rsp; dst->rbp.u64 = src->rbp; dst->rsi.u64 = src->rsi; dst->rdi.u64 = src->rdi; dst->r8.u64 = src->r8; dst->r9.u64 = src->r9; dst->r10.u64 = src->r10; dst->r11.u64 = src->r11; dst->r12.u64 = src->r12; dst->r13.u64 = src->r13; dst->r14.u64 = src->r14; dst->r15.u64 = src->r15; dst->cs.u16 = src->cs; dst->ds.u16 = src->ds; dst->es.u16 = src->es; dst->fs.u16 = src->fs; dst->gs.u16 = src->gs; dst->ss.u16 = src->ss; dst->fsbase.u64 = src->fsbase; dst->gsbase.u64 = src->gsbase; dst->rip.u64 = src->rip; dst->rflags.u64 = src->rflags; } internal void demon_lnx_usr_regs_x64_from_regs_x64(DEMON_LNX_UserRegsX64 *dst, SYMS_RegX64 *src){ dst->rax = src->rax.u64; dst->rcx = src->rcx.u64; dst->rdx = src->rdx.u64; dst->rbx = src->rbx.u64; dst->rsp = src->rsp.u64; dst->rbp = src->rbp.u64; dst->rsi = src->rsi.u64; dst->rdi = src->rdi.u64; dst->r8 = src->r8.u64; dst->r9 = src->r9.u64; dst->r10 = src->r10.u64; dst->r11 = src->r11.u64; dst->r12 = src->r12.u64; dst->r13 = src->r13.u64; dst->r14 = src->r14.u64; dst->r15 = src->r15.u64; dst->cs = src->cs.u16; dst->ds = src->ds.u16; dst->es = src->es.u16; dst->fs = src->fs.u16; dst->gs = src->gs.u16; dst->ss = src->ss.u16; dst->fsbase = src->fsbase.u64; dst->gsbase = src->gsbase.u64; dst->rip = src->rip.u64; dst->rflags = src->rflags.u64; } //////////////////////////////// internal String8 demon_lnx_read_int_string(Arena *arena, int fd, int radix){ String8 integer = str8(0,0); int to_read = 0; int to_seek = 0; for (;;){ char b = 0; if (read(fd, &b, sizeof(b)) == 0){ break; } to_seek += 1; if ( ! char_is_digit(b, radix)){ break; } to_read += 1; } if (lseek(fd, -to_seek, SEEK_CUR) != -1) { char *buf = push_array_no_zero(arena, char, to_read + 1); read(fd, buf, to_read); buf[to_read] = '\0'; integer = str8((U8*)buf, (U64)to_read); } return(integer); } internal U64 demon_lnx_read_u64(int fd, int radix){ Temp scratch = scratch_begin(0, 0); String8 integer = demon_lnx_read_int_string(scratch.arena, fd, radix); U64 result = u64_from_str8(integer, radix); scratch_end(scratch); return(result); } internal S64 demon_lnx_read_s64(int fd, int radix){ Temp scratch = scratch_begin(0, 0); String8 integer = demon_lnx_read_int_string(scratch.arena, fd, radix); S64 result = s64_from_str8(integer, radix); scratch_end(scratch); return(result); } internal B32 demon_lnx_read_expect(int fd, char expect){ char got = 0; read(fd, &got, sizeof(got)); B32 result = (got == expect); if (!result){ lseek(fd, -1, SEEK_CUR); } return(result); } internal int demon_lnx_read_whitespace(int fd){ int whitespace_size = 0; for (;;){ if (!demon_lnx_read_expect(fd, ' ')){ if (!demon_lnx_read_expect(fd, '\t')){ break; } } whitespace_size += 1; } return whitespace_size; } internal String8 demon_lnx_read_string(Arena *arena, int fd){ String8 result = str8(0,0); int to_read = 0; int to_seek = 0; for (;;){ char b = 0; if (read(fd, &b, sizeof(b)) == 0) { break; } to_seek += 1; if (b == '\0' || b == '\n'){ break; } to_read += 1; } if (to_seek > 0 && lseek(fd, -to_seek, SEEK_CUR) != -1){ char *buf = push_array_no_zero(arena, char, to_read + 1); read(fd, buf, to_read); buf[to_read] = '\0'; result = str8((U8*)buf, to_read); } return(result); } internal int demon_lnx_open_maps(pid_t pid){ Temp scratch = scratch_begin(0, 0); String8 path = push_str8f(scratch.arena, "/proc/%d/maps", pid); int maps = open((char*)path.str, O_RDONLY|O_CLOEXEC); scratch_end(scratch); return(maps); } internal B32 demon_lnx_next_map(Arena *arena, int maps, DEMON_LNX_MapsEntry *entry_out){ B32 is_parsed = false; MemoryZeroStruct(entry_out); do{ U64 address_lo = 0; U64 address_hi = 0; DEMON_LNX_PermFlags perms = 0; U64 offset = 0; U64 dev_major = 0; U64 dev_minor = 0; U64 inode = 0; String8 pathname = str8(0,0); // address range address_lo = demon_lnx_read_u64(maps, 16); if (!demon_lnx_read_expect(maps, '-')){ break; } address_hi = demon_lnx_read_u64(maps, 16); if (demon_lnx_read_whitespace(maps) == 0){ break; } // permission flags char b; if (read(maps, &b, sizeof(b)) == 0){ break; } if (b=='r'){ perms |= DEMON_LNX_PermFlags_Read; } if (read(maps, &b, sizeof(b)) == 0){ break; } if (b=='w'){ perms |= DEMON_LNX_PermFlags_Write; } if (read(maps, &b, sizeof(b)) == 0){ break; } if (b=='x'){ perms |= DEMON_LNX_PermFlags_Exec; } if (read(maps, &b, sizeof(b)) == 0){ break; } if (b == 'p'){ perms |= DEMON_LNX_PermFlags_Private; } if (demon_lnx_read_whitespace(maps) == 0){ break; } // offset offset = demon_lnx_read_u64(maps, 16); if (demon_lnx_read_whitespace(maps) == 0){ break; } // dev dev_major = demon_lnx_read_u64(maps, 10); if (!demon_lnx_read_expect(maps, ':')){ break; } dev_minor = demon_lnx_read_u64(maps, 10); if (demon_lnx_read_whitespace(maps) == 0){ break; } // inode inode = demon_lnx_read_u64(maps, 10); if (demon_lnx_read_whitespace(maps) == 10){ break; } // pathname pathname = demon_lnx_read_string(arena, maps); // emit entry if en b = 0; read(maps, &b, sizeof(b)); if (b != '\n' && b != '\0') { break; } // fill result entry_out->address_lo = address_lo; entry_out->address_hi = address_hi; entry_out->perms = perms; entry_out->offset = offset; entry_out->dev_major = (U32)dev_major; entry_out->dev_minor = (U32)dev_minor; entry_out->inode = inode; entry_out->pathname = pathname; entry_out->type = DEMON_LNX_MapsEntryType_Null; entry_out->stack_tid = 0; if (str8_match(pathname, str8_lit("/"), StringMatchFlag_RightSideSloppy)){ entry_out->type = DEMON_LNX_MapsEntryType_Path; } else if (str8_match(pathname, str8_lit("[heap]"), 0)){ entry_out->type = DEMON_LNX_MapsEntryType_Heap; } else if (str8_match(pathname, str8_lit("[stack]"), 0)){ entry_out->type = DEMON_LNX_MapsEntryType_Stack; } else if (str8_match(pathname, str8_lit("[stack:"), StringMatchFlag_RightSideSloppy)){ entry_out->type = DEMON_LNX_MapsEntryType_Stack; String8 tid = str8_substr(pathname, r1u64(7, pathname.size - 8)); entry_out->stack_tid = (pid_t)u64_from_str8(tid, 10); } is_parsed = true; }while(0); return(is_parsed); } //////////////////////////////// //~ rjf: @demon_os_hooks Main Layer Initialization internal void demon_os_init(void){ demon_lnx_event_arena = arena_alloc(); } //////////////////////////////// //~ rjf: @demon_os_hooks Running/Halting internal DEMON_EventList demon_os_run(Arena *arena, DEMON_OS_RunCtrls *controls){ DEMON_EventList result = {0}; if (demon_ent_root == 0){ demon_push_event(arena, &result, DEMON_EventKind_NotInitialized); } else if (demon_ent_root->first == 0 && !demon_lnx_new_process_pending){ demon_push_event(arena, &result, DEMON_EventKind_NotAttached); } else{ Temp scratch = scratch_begin(&arena, 1); // use queued events if there are any if (demon_lnx_queued_events.first != 0){ // copy event queue for (DEMON_Event *node = demon_lnx_queued_events.first; node != 0; node = node->next){ DEMON_Event *copy = push_array_no_zero(arena, DEMON_Event, 1); MemoryCopyStruct(copy, node); SLLQueuePush(result.first, result.last, copy); } result.count = demon_lnx_queued_events.count; // zero stored queue MemoryZeroStruct(&demon_lnx_queued_events); arena_clear(demon_lnx_event_arena); } // get the single step thread (if any) DEMON_Entity *single_step_thread = controls->single_step_thread; // do setup B32 did_setup = false; U8 *trap_swap_bytes = 0; if (result.first == 0){ // TODO(allen): per-Arch implementation of single steps // set single step bit if (single_step_thread != 0){ switch (single_step_thread->arch){ case Arch_x86: { // TODO(allen): possibly buggy SYMS_RegX86 regs = {0}; demon_os_read_regs_x86(single_step_thread, ®s); regs.eflags.u32 |= 0x100; demon_os_write_regs_x86(single_step_thread, ®s); }break; case Arch_x64: { // TODO(allen): possibly buggy SYMS_RegX64 regs = {0}; demon_os_read_regs_x64(single_step_thread, ®s); regs.rflags.u64 |= 0x100; demon_os_write_regs_x64(single_step_thread, ®s); }break; } } // TODO(allen): per-Arch implementation of traps trap_swap_bytes = push_array_no_zero(scratch.arena, U8, controls->trap_count); { DEMON_OS_Trap *trap = controls->traps; for (U64 i = 0; i < controls->trap_count; i += 1, trap += 1){ if (demon_os_read_memory(trap->process, trap_swap_bytes + i, trap->address, 1)){ U8 int3 = 0xCC; demon_os_write_memory(trap->process, trap->address, &int3, 1); } else{ trap_swap_bytes[i] = 0xCC; } } } did_setup = true; } // do run B32 did_run = false; if (did_setup){ // continue non-frozen threads DEMON_LNX_EntityNode *resume_threads = 0; for (DEMON_Entity *process = demon_ent_root->first; process != 0; process = process->next){ if (process->kind == DEMON_EntityKind_Process){ // determine if this process is frozen B32 process_is_frozen = false; if (controls->run_entities_are_processes){ for (U64 i = 0; i < controls->run_entity_count; i += 1){ if (controls->run_entities[i] == process){ process_is_frozen = true; break; } } } for (DEMON_Entity *thread = process->first; thread != 0; thread = thread->next){ if (thread->kind == DEMON_EntityKind_Thread){ // determine if this thread is frozen B32 is_frozen = false; if (controls->single_step_thread != 0 && controls->single_step_thread != thread){ is_frozen = true; } else{ if (controls->run_entities_are_processes){ is_frozen = process_is_frozen; } else{ for (U64 i = 0; i < controls->run_entity_count; i += 1){ if (controls->run_entities[i] == thread){ is_frozen = true; break; } } } if (controls->run_entities_are_unfrozen){ is_frozen = !is_frozen; } } // continue if not frozen if (!is_frozen){ errno = 0; ptrace(PTRACE_CONT, (pid_t)thread->id, 0, 0); DEMON_LNX_EntityNode *thread_node = push_array_no_zero(scratch.arena, DEMON_LNX_EntityNode, 1); SLLStackPush(resume_threads, thread_node); thread_node->entity = thread; } } } } } // get next stop wait_for_stop: B32 did_dummy_stop = false; int status = 0; pid_t wait_id = waitpid(-1, &status, __WALL); // increment demon time demon_time += 1; // handle devent DEMON_Entity *thread = demon_ent_map_entity_from_id(DEMON_EntityKind_Thread, wait_id); if (thread == 0){ if (wait_id >= 0){ // TODO(allen): this isn't a great situation! From what I can tell there's no // options that I am super happy with for going from unknown tid -> pid. // We can parse it out of /proc//status; but I don't want to do that until // I'm forced to, because it seems like this shouldn't happen if the ptrace // API works correctly and we don't have any bugs in our demon entity system. } } else{ B32 thread_exit = false; U64 exit_code = 0; DEMON_Entity *process = thread->parent; // NOTE(allen): hitting this assert should never ever be possible, if our entities // are wired up correctly. it doesn't matter what ptrace or waitpid are doing. Assert(process != 0); // read register info U64 instruction_pointer = 0; union{ SYMS_RegX86 x86; SYMS_RegX64 x64; } regs = {0}; switch (thread->arch){ case Arch_x86: { demon_os_read_regs_x86(thread, ®s.x86); instruction_pointer = regs.x86.eip.u32; }break; case Arch_x64: { demon_os_read_regs_x64(thread, ®s.x64); instruction_pointer = regs.x64.rip.u64; }break; } // check stop status if (WIFEXITED(status)){ thread_exit = true; } if (WIFSIGNALED(status)){ exit_code = WTERMSIG(status); thread_exit = true; } // extra event list DEMON_EventList stop_events = {0}; if (WIFSTOPPED(status)){ switch (WSTOPSIG(status)){ case SIGTRAP: { switch (status >> 8){ case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { // TODO(allen): (not sure actually, study this part) thread_exit = true; }break; case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): { // new thread coming unsigned long new_tid = 0; int get_message_result = ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_tid); if (get_message_result == -1){ // TODO(allen): this isn't right, time to give up on getting this process. // this will likely lead to getting unrecognized wait_id s later. So we need // this stuff in the log to make sense of it still. } else{ // thread entity DEMON_Entity *new_thread = demon_ent_new(process, DEMON_EntityKind_Thread, new_tid); demon_thread_count += 1; DEMON_LNX_ThreadExt *thread_ext = demon_lnx_thread_ext(new_thread); thread_ext->expecting_dummy_sigstop = true; // thread event DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_CreateThread); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(new_thread); } }break; case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): { // new process coming unsigned long new_pid = 0; int get_message_result = ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_pid); if (get_message_result == -1){ // TODO(allen): this isn't right, time to give up on getting this process. // this will likely lead to getting unrecognized wait_id s later. So we need // this stuff in the log to make sense of it still. } else{ Arch arch = demon_lnx_arch_from_pid(new_pid); // process entity DEMON_Entity *new_process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, new_pid); new_process->arch = arch; new_process->ext_u64 = demon_lnx_open_memory_fd_for_pid(new_pid); demon_lnx_new_process_pending = false; // thread entity DEMON_Entity *new_thread = demon_ent_new(new_process, DEMON_EntityKind_Thread, new_pid); demon_thread_count += 1; DEMON_LNX_ThreadExt *thread_ext = demon_lnx_thread_ext(new_thread); thread_ext->expecting_dummy_sigstop = true; // process event { DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_CreateProcess); e->process = demon_ent_handle_from_ptr(new_process); } // thread event { DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_CreateThread); e->process = demon_ent_handle_from_ptr(new_process); e->thread = demon_ent_handle_from_ptr(new_thread); } } }break; default: { // check single step DEMON_EventKind e_kind = DEMON_EventKind_Trap; if (thread == single_step_thread){ e_kind = DEMON_EventKind_SingleStep; } // check bp if (e_kind == DEMON_EventKind_Trap){ DEMON_OS_Trap *trap = controls->traps; for (U64 i = 0; i < controls->trap_count; i += 1, trap += 1){ if (trap->process == process && trap->address == instruction_pointer - 1){ e_kind = DEMON_EventKind_Breakpoint; break; } } } // adjust ip after breakpoint if (e_kind == DEMON_EventKind_Breakpoint){ // TODO(allen): possibly buggy switch (thread->arch){ case Arch_x86: { instruction_pointer -= 1; regs.x86.eip.u32 = instruction_pointer; demon_os_write_regs_x86(thread, ®s.x86); }break; case Arch_x64: { instruction_pointer -= 1; regs.x64.rip.u64 = instruction_pointer; demon_os_write_regs_x64(thread, ®s.x64); }break; } } // event DEMON_Event *e = demon_push_event(arena, &stop_events, e_kind); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); e->instruction_pointer = instruction_pointer; }break; } }break; case SIGSTOP: { // TODO(allen): we need to figure out how we want to tell apart: // SIGSTOP All-Stop, SIGSTOP Halt, SIGSTOP "User" // what we're doing right now == big-time race conditions DEMON_LNX_ThreadExt *thread_ext = demon_lnx_thread_ext(thread); if (thread_ext->expecting_dummy_sigstop){ thread_ext->expecting_dummy_sigstop = false; did_dummy_stop = true; } else if (demon_lnx_already_has_halt_injection){ DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_Halt); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); e->instruction_pointer = instruction_pointer; } else{ // TODO(allen): a signal we don't want to mess with (except to record that it happened maybe) // we should "hand it back" } }break; default: { #if 0 // these are a little special. the program cannot continue after these // unless the user first does something to change the state (move the IP, change a variable, w/e) case SIGABRT:case SIGFPE:case SIGSEGV: #endif // event DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_Exception); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); e->instruction_pointer = instruction_pointer; e->signo = WSTOPSIG(status); }break; } } // entity cleanup if (thread_exit){ if (thread->id == process->id){ // generate events for threads & modules for (DEMON_Entity *entity = process->first; entity != 0; entity = entity->next){ if (entity->kind == DEMON_EntityKind_Thread){ DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_ExitThread); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(entity); } else{ DEMON_Event *e = demon_push_event(arena, &result, DEMON_EventKind_UnloadModule); e->process = demon_ent_handle_from_ptr(process); e->module = demon_ent_handle_from_ptr(entity); } } // exit event DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_ExitProcess); e->process = demon_ent_handle_from_ptr(process); e->code = exit_code; // free entity demon_ent_release_root_and_children(process); } else{ // exit event DEMON_Event *e = demon_push_event(arena, &stop_events, DEMON_EventKind_ExitThread); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); e->code = exit_code; // free entity demon_ent_release_root_and_children(thread); } } // update all module lists (for each process ...) DEMON_EventList module_change_events = {0}; for (DEMON_Entity *proc_node = demon_ent_root->first; proc_node != 0; proc_node = proc_node->next){ DEMON_LNX_ModuleNode *first_module = demon_lnx_module_list_from_process(scratch.arena, proc_node); DEMON_LNX_EntityNode *first_unloaded = 0; DEMON_LNX_EntityNode *last_unloaded = 0; // compute the delta (mark known modules, save list of unloaded modules) for (DEMON_Entity *entity = proc_node->first; entity != 0; entity = entity->next){ if (entity->kind == DEMON_EntityKind_Module){ U64 base = entity->id; U64 name = entity->ext_u64; B32 still_exists = false; for (DEMON_LNX_ModuleNode *module_node = first_module; module_node != 0; module_node = module_node->next){ if (module_node->vaddr == base && module_node->name == name){ module_node->already_known = true; still_exists = true; break; } } if (!still_exists){ DEMON_LNX_EntityNode *node = push_array_no_zero(scratch.arena, DEMON_LNX_EntityNode, 1); SLLQueuePush(first_unloaded, last_unloaded, node); node->entity = entity; } } } // handle unloads for (DEMON_LNX_EntityNode *unloaded_node = first_unloaded; unloaded_node != 0; unloaded_node = unloaded_node->next){ DEMON_Entity *module = unloaded_node->entity; // event { DEMON_Event *e = demon_push_event(arena, &module_change_events, DEMON_EventKind_UnloadModule); e->process = demon_ent_handle_from_ptr(proc_node); e->module = demon_ent_handle_from_ptr(module); } // free entity demon_ent_release_root_and_children(module); } // handle loads for (DEMON_LNX_ModuleNode *module_node = first_module; module_node != 0; module_node = module_node->next){ if (!module_node->already_known){ // entity DEMON_Entity *module = demon_ent_new(proc_node, DEMON_EntityKind_Module, module_node->vaddr); demon_module_count += 1; module->ext_u64 = module_node->name; // event { DEMON_Event *e = demon_push_event(arena, &module_change_events, DEMON_EventKind_LoadModule); e->process = demon_ent_handle_from_ptr(proc_node); e->module = demon_ent_handle_from_ptr(module); e->address = module_node->vaddr; e->size = module_node->size; } } } } // concat the events list (with module changes first) result.count = module_change_events.count + stop_events.count; result.first = module_change_events.first; result.last = module_change_events.last; if (stop_events.first != 0){ if (result.first != 0){ result.last->next = stop_events.first; result.last = stop_events.last; } else{ result.first = stop_events.first; result.last = stop_events.last; } } } // do we have a reason to keep going? B32 skip_this_stop = false; if (did_dummy_stop && result.count == 0){ skip_this_stop = true; } // ignore this stop, resume and wait again if (skip_this_stop){ if (wait_id != 0){ ptrace(PTRACE_CONT, (pid_t)wait_id, 0, 0); } goto wait_for_stop; } // stop all running threads for (DEMON_LNX_EntityNode *node = resume_threads; node != 0; node = node->next){ DEMON_Entity *thread = node->entity; pid_t thread_id = (pid_t)thread->id; if (thread_id != wait_id){ union sigval sv = {0}; sigqueue(thread_id, SIGSTOP, sv); DEMON_LNX_ThreadExt *thread_ext = demon_lnx_thread_ext(thread); thread_ext->expecting_dummy_sigstop = true; } } did_run = true; } // cleanup if (did_run){ // TODO(allen): per-Arch // unset traps { DEMON_OS_Trap *trap = controls->traps; for (U64 i = 0; i < controls->trap_count; i += 1, trap += 1){ U8 og_byte = trap_swap_bytes[i]; if (og_byte != 0xCC){ demon_os_write_memory(trap->process, trap->address, &og_byte, 1); } } } // TODO(allen): per-Arch // unset single step bit // the single step bit is automatically unset whenever we single step // but if *something else* happened, it will still be there ready to // confound us later; so here we're just being sure it's taken out. if (single_step_thread != 0){ // TODO(allen): possibly buggy switch (single_step_thread->arch){ case Arch_x86: { SYMS_RegX86 regs = {0}; demon_os_read_regs_x86(single_step_thread, ®s); regs.eflags.u32 &= ~0x100; demon_os_write_regs_x86(single_step_thread, ®s); }break; case Arch_x64: { SYMS_RegX64 regs = {0}; demon_os_read_regs_x64(single_step_thread, ®s); regs.rflags.u64 &= ~0x100; demon_os_write_regs_x64(single_step_thread, ®s); }break; } } } scratch_end(scratch); } return(result); } internal void demon_os_halt(U64 code, U64 user_data){ if (demon_ent_root != 0 && !demon_lnx_already_has_halt_injection){ DEMON_Entity *process = demon_ent_root->first; if (process != 0){ demon_lnx_already_has_halt_injection = true; demon_lnx_halt_code = code; demon_lnx_halt_user_data = user_data; union sigval sv = {0}; if (sigqueue(process->id, SIGSTOP, sv) == -1){ demon_lnx_already_has_halt_injection = false; } } } } // NOTE(allen): siginfo hint from old code: #if 0 { switch (siginfo.si_code){ // SI_KERNEL (hit int3; 0xCC) case 0x80: { // TODO(allen): breakpoint event }break; // TRAP_UNK, TRAP_HWBKPT, TRAP_BRKPT, TRAP_TRACE case 0x5: case 0x4: case 0x1: case 0x2: { // TODO(allen): breakpoint event (?) }break; case 0x3: case 0x0: { // TODO(allen): do nothing I guess? }break; } } #endif //////////////////////////////// //~ rjf: @demon_os_hooks Target Process Launching/Attaching/Killing/Detaching/Halting internal U32 demon_os_launch_process(OS_LaunchOptions *options){ U32 result = 0; Temp scratch = scratch_begin(0, 0); // arrange options char *binary = 0; char **args = 0; if (options->cmd_line.node_count > 0){ args = push_array_no_zero(scratch.arena, char*, options->cmd_line.node_count + 1); char **arg_ptr = args; for (String8Node *node = options->cmd_line.first; node != 0; node = node->next, arg_ptr += 1){ String8 string = push_str8_copy(scratch.arena, node->string); *arg_ptr = (char*)string.str; } *arg_ptr = 0; binary = args[0]; } char *path = 0; { String8 string = push_str8_copy(scratch.arena, options->path); path = (char*)string.str; } char **env = 0; if (options->env.node_count > 0){ env = push_array_no_zero(scratch.arena, char*, options->env.node_count + 1); char **env_ptr = env; for (String8Node *node = options->env.first; node != 0; node = node->next, env_ptr += 1){ String8 string = push_str8_copy(scratch.arena, node->string); *env_ptr = (char*)string.str; } *env_ptr = 0; } // fork if (binary != 0){ pid_t pid = fork(); if (pid == -1){ // TODO(allen): fork error } else if (pid == 0){ // NOTE(allen): child process int ptrace_result = ptrace(PTRACE_TRACEME, 0, 0, 0); if (ptrace_result != -1){ int chdir_result = chdir(path); if (chdir_result != -1){ execve(binary, args, env); } } // failed to init fully; abort so the parent can clean up the child abort(); } else{ // NOTE(allen): parent process // wait for child int status = 0; pid_t wait_id = waitpid(pid, &status, __WALL); // determine child launch status enum{ LaunchCode_Null, LaunchCode_FailBeforePtrace, LaunchCode_FailAfterPtrace, LaunchCode_Success, }; U32 launch_result = LaunchCode_Null; // NOTE(allen): if wait_id != pid we don't know what that means; study that case before // deciding how error handling around it works. if (wait_id == pid){ if (WIFSTOPPED(status)){ if (WSTOPSIG(status) == SIGTRAP){ launch_result = LaunchCode_Success; } else{ launch_result = LaunchCode_FailAfterPtrace; } } else{ launch_result = LaunchCode_FailBeforePtrace; } } // handle launch result switch (launch_result){ default: { // TODO(allen): error that we do not understand }break; case LaunchCode_FailBeforePtrace: { // TODO(allen): child ptrace init failed }break; case LaunchCode_FailAfterPtrace: { // need to specifically pull the exit status out of the child // or it will sit around as a zombie forever since it is ptraced. B32 cleanup_good = false; int detach_result = ptrace(PTRACE_DETACH, pid, 0, (void*)SIGCONT); if (detach_result != -1){ int status_cleanup = 0; pid_t wait_id_cleanup = waitpid(pid, &status_cleanup, __WALL); if (wait_id_cleanup == pid){ cleanup_good = true; } } if (cleanup_good){ // TODO(allen): child init failed } else{ // TODO(allen): child init failed; something went wrong and a process may have leaked } }break; case LaunchCode_Success: { int setoptions_result = ptrace(PTRACE_SETOPTIONS, pid, 0, PtrFromInt(demon_lnx_ptrace_options)); if (setoptions_result == -1){ // TODO(allen): ptrace setup failed; need to kill the child and clean it up } else{ result = pid; Arch arch = demon_lnx_arch_from_pid(pid); // process entity DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, pid); demon_proc_count += 1; process->arch = arch; process->ext_u64 = demon_lnx_open_memory_fd_for_pid(pid); // thread entity DEMON_Entity *thread = demon_ent_new(process, DEMON_EntityKind_Thread, pid); demon_thread_count += 1; // process event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_CreateProcess); e->process = demon_ent_handle_from_ptr(process); } // thread event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_CreateThread); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); } // get module list DEMON_LNX_ModuleNode *module_list = demon_lnx_module_list_from_process(scratch.arena, process); // for each module ... for (DEMON_LNX_ModuleNode *node = module_list; node != 0; node = node->next){ // module entity DEMON_Entity *module = demon_ent_new(process, DEMON_EntityKind_Module, node->vaddr); demon_module_count += 1; module->ext_u64 = node->name; // event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_LoadModule); e->process = demon_ent_handle_from_ptr(process); e->module = demon_ent_handle_from_ptr(module); e->address = node->vaddr; e->size = node->size; } } // handshake event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_HandshakeComplete); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); } } }break; } } } scratch_end(scratch); return(result); } internal B32 demon_os_attach_process(U32 pid){ B32 result = false; Temp scratch = scratch_begin(0, 0); DEMON_LNX_AttachNode *attachments = 0; DEMON_LNX_AttachNode *the_process = 0; // TODO(allen): double check that this logic only lets us // "attach" when pid is the id of the main thread of a process. // attach this process B32 attached_proc = false; if (kill(pid, 0) == -1){ // TODO(allen): process does not exist } else{ attached_proc = demon_lnx_attach_pid(scratch.arena, pid, &the_process); if (the_process != 0){ SLLStackPush(attachments, the_process); } } // open thread list if (attached_proc){ String8 threads_path = push_str8f(scratch.arena, "/proc/%d/task", pid); DIR *proc_dir = opendir((char*)threads_path.str); if (proc_dir == 0){ // TODO(allen): could not read proc threads somehow; no good! } else{ // attach all threads B32 attached_all_threads = true; for (;;){ struct dirent *entry = readdir(proc_dir); if (entry == 0){ break; } String8 name = str8_cstring(entry->d_name); if (str8_is_integer(name, 10)){ pid_t tid = u64_from_str8(name, 10); if (tid != pid){ DEMON_LNX_AttachNode *new_attachment = 0; B32 attached_this_thread = demon_lnx_attach_pid(scratch.arena, tid, &new_attachment); if (new_attachment != 0){ SLLStackPush(attachments, new_attachment); } if (!attached_this_thread){ attached_all_threads = false; break; } } } } closedir(proc_dir); if (attached_all_threads){ result = true; } } } // initialize new entities on success if (result){ Arch arch = demon_lnx_arch_from_pid(the_process->pid); // process entity DEMON_Entity *process = demon_ent_new(demon_ent_root, DEMON_EntityKind_Process, the_process->pid); demon_proc_count += 1; process->arch = arch; process->ext_u64 = demon_lnx_open_memory_fd_for_pid(the_process->pid); // process event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_CreateProcess); e->process = demon_ent_handle_from_ptr(process); } // TODO(allen): happens on windows here? for (DEMON_LNX_AttachNode *node = attachments; node != 0; node = node->next){ DEMON_Entity *thread = demon_ent_new(process, DEMON_EntityKind_Thread, node->pid); demon_thread_count += 1; // thread event { DEMON_Event *e = demon_push_event(demon_lnx_event_arena, &demon_lnx_queued_events, DEMON_EventKind_CreateThread); e->process = demon_ent_handle_from_ptr(process); e->thread = demon_ent_handle_from_ptr(thread); } } // TODO(allen): sync modules in process } // cleanup on failure else{ for (DEMON_LNX_AttachNode *node = attachments; node != 0; node = node->next){ ptrace(PTRACE_DETACH, node->pid, 0, (void*)SIGCONT); } } scratch_end(scratch); return(result); } internal B32 demon_os_kill_process(DEMON_Entity *process, U32 exit_code){ B32 result = false; if (process != 0){ if (kill(process->id, SIGKILL) != -1){ result = true; } } return(result); } internal B32 demon_os_detach_process(DEMON_Entity *process){ B32 result = false; if (process != 0){ int detach_result = ptrace(PTRACE_DETACH, process->id, 0, 0); result = (detach_result != -1); } return(0); } //////////////////////////////// //~ rjf: @demon_os_hooks Entity Functions //- rjf: cleanup internal void demon_os_entity_cleanup(DEMON_Entity *entity) { // NOTE(rjf): no-op } //- rjf: introspection internal String8 demon_os_full_path_from_module(Arena *arena, DEMON_Entity *module){ DEMON_Entity *process = module->parent; int memory_fd = (int)process->ext_u64; U64 name_va = module->ext_u64; String8 result = demon_lnx_read_memory_str(arena, memory_fd, name_va); return(result); } internal U64 demon_os_stack_base_vaddr_from_thread(DEMON_Entity *thread){ Temp scratch = scratch_begin(0, 0); U64 stack_base = 0; DEMON_Entity *process = thread->parent; // id for main thread is zero B32 is_main_thread = (thread->id == process->id); pid_t match_tid = is_main_thread ? 0 : thread->id; // open /proc/$pid/maps int maps = demon_lnx_open_maps(process->id); // look for entry with stack markings and matching thread id for (;;){ DEMON_LNX_MapsEntry e; Temp temp = temp_begin(scratch.arena); if (!demon_lnx_next_map(temp.arena, maps, &e)){ break; } if (e.type == DEMON_LNX_MapsEntryType_Stack && e.stack_tid == match_tid){ stack_base = e.address_lo; break; } temp_end(temp); } scratch_end(scratch); return(stack_base); } internal U64 demon_os_tls_root_vaddr_from_thread(DEMON_Entity *thread){ U64 result = 0; switch (thread->arch){ case Arch_x64: case Arch_x86: { U32 fsbase = 0; pid_t tid = (pid_t)thread->id; if (ptrace(PT_GETFSBASE, tid, (void*)&fsbase, 0) != -1){ result = (U64)fsbase; } if (thread->arch == Arch_x64){ result += 8; } else{ result += 4; } }break; } return(result); } //- rjf: target process memory allocation/protection internal U64 demon_os_reserve_memory(DEMON_Entity *process, U64 size){ U64 result = 0; NotImplemented; return(result); } internal void demon_os_set_memory_protect_flags(DEMON_Entity *process, U64 page_vaddr, U64 size, DEMON_MemoryProtectFlags flags){ NotImplemented; } internal void demon_os_release_memory(DEMON_Entity *process, U64 vaddr, U64 size){ NotImplemented; } //- rjf: target process memory reading/writing internal U64 demon_os_read_memory(DEMON_Entity *process, void *dst, U64 src_address, U64 size){ int memory_fd = (int)process->ext_u64; U64 result = demon_lnx_read_memory(memory_fd, dst, src_address, size); return(result); } internal B32 demon_os_write_memory(DEMON_Entity *process, U64 dst_address, void *src, U64 size){ int memory_fd = (int)process->ext_u64; B32 result = demon_lnx_write_memory(memory_fd, dst_address, src, size); return(result); } //- rjf: thread registers reading/writing internal B32 demon_os_read_regs_x86(DEMON_Entity *thread, SYMS_RegX86 *dst){ B32 result = false; NotImplemented; return(result); } internal B32 demon_os_write_regs_x86(DEMON_Entity *thread, SYMS_RegX86 *src){ B32 result = false; NotImplemented; return(result); } internal B32 demon_os_read_regs_x64(DEMON_Entity *thread, SYMS_RegX64 *dst){ pid_t tid = (pid_t)thread->id; // gpr B32 got_gpr = false; DEMON_LNX_UserX64 ctx = {0}; struct iovec iov_gpr = {0}; iov_gpr.iov_len = sizeof(ctx); iov_gpr.iov_base = &ctx; if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &iov_gpr) != -1){ demon_lnx_regs_x64_from_usr_regs_x64(dst, &ctx.regs); got_gpr = true; } // fpr B32 got_fpr = false; if (got_gpr){ B32 got_xsave = false; { U8 xsave_buffer[KB(4)]; struct iovec iov_xsave = {0}; iov_xsave.iov_len = sizeof(xsave_buffer); iov_xsave.iov_base = xsave_buffer; if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_X86_XSTATE, &iov_xsave) != -1){ SYMS_XSave *xsave = (SYMS_XSave*)xsave_buffer; syms_x64_regs__set_full_regs_from_xsave_legacy(dst, &xsave->legacy); // TODO(allen): this is a lie; ymm can technically move around // we need some more low-level-assembly-fu to do this hardcore. B32 has_ymm_registers = ((xsave->header.xstate_bv & 4) != 0); if (has_ymm_registers){ syms_x64_regs__set_full_regs_from_xsave_avx_extension(dst, xsave->ymmh); } got_xsave = true; } } B32 got_fxsave = false; if (!got_xsave){ SYMS_XSaveLegacy fxsave = {0}; struct iovec iov_fxsave = {0}; iov_fxsave.iov_len = sizeof(fxsave); iov_fxsave.iov_base = &fxsave; if (ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, &iov_fxsave) != -1){ syms_x64_regs__set_full_regs_from_xsave_legacy(dst, &fxsave); got_fxsave = true; } } if (got_xsave || got_fxsave){ got_fpr = true; } } // debug B32 got_debug = false; if (got_fpr){ got_debug = true; SYMS_Reg32 *dr_d = &dst->dr0; for (U32 i = 0; i < 8; i += 1, dr_d += 1){ if (i != 4 && i != 5){ U64 offset = OffsetOf(DEMON_LNX_UserX64, u_debugreg[i]); errno = 0; int peek_result = ptrace(PTRACE_PEEKUSER, tid, PtrFromInt(offset), 0); if (errno == 0){ dr_d->u32 = (U32)peek_result; } else{ got_debug = false; } } } } // got everything B32 result = got_debug; return(result); } internal B32 demon_os_write_regs_x64(DEMON_Entity *thread, SYMS_RegX64 *src){ pid_t tid = (pid_t)thread->id; // gpr DEMON_LNX_UserX64 ctx = {0}; demon_lnx_usr_regs_x64_from_regs_x64(&ctx.regs, src); struct iovec iov_gpr = {0}; iov_gpr.iov_base = &ctx; iov_gpr.iov_len = sizeof(ctx); int gpr_result = ptrace(PTRACE_SETREGSET, tid, (void*)NT_PRSTATUS, &iov_gpr); B32 gpr_success = (gpr_result != -1); // fpr int xsave_result = 0; int fxsave_result = 0; { U8 xsave_buffer[KB(4)] = {0}; SYMS_XSave *xsave = (SYMS_XSave*)xsave_buffer; syms_x64_regs__set_xsave_legacy_from_full_regs(&xsave->legacy, src); xsave->header.xstate_bv = 7; // TODO(allen): this is a lie; ymm can technically move around // we need some more low-level-assembly-fu to do this hardcore. syms_x64_regs__set_xsave_avx_extension_from_full_regs(xsave->ymmh, src); { struct iovec iov_xsave = {0}; iov_xsave.iov_base = &xsave; iov_xsave.iov_len = sizeof(xsave); xsave_result = ptrace(PTRACE_SETREGSET, tid, (void*)NT_X86_XSTATE, &iov_xsave); } if (xsave_result == -1){ struct iovec iov_fxsave = {0}; iov_fxsave.iov_base = &xsave->legacy; iov_fxsave.iov_len = sizeof(xsave->legacy); fxsave_result = ptrace(PTRACE_SETREGSET, tid, (void*)NT_FPREGSET, &iov_fxsave); } } B32 fpr_success = (xsave_result != -1 || fxsave_result != -1); // debug B32 dr_success = true; { SYMS_Reg32 *dr_s = &src->dr0; for (U32 i = 0; i < 8; i += 1, dr_s += 1){ if (i != 4 && i != 5){ U64 offset = OffsetOf(DEMON_LNX_UserX64, u_debugreg[i]); errno = 0; int poke_result = ptrace(PTRACE_POKEUSER, tid, PtrFromInt(offset), dr_s->u32); if (poke_result == -1){ dr_success = false; } } } } // assemble result B32 result = (gpr_success && fpr_success && dr_success); return(result); } //////////////////////////////// //~ rjf: @demon_os_hooks Process Listing internal void demon_os_proc_iter_begin(DEMON_ProcessIter *iter){ DIR *dir = opendir("/proc"); MemoryZeroStruct(iter); iter->v[0] = IntFromPtr(dir); } internal B32 demon_os_proc_iter_next(Arena *arena, DEMON_ProcessIter *iter, DEMON_ProcessInfo *info_out){ // scan for a process id B32 got_pid = false; String8 pid_string = {0}; DIR *dir = (DIR*)PtrFromInt(iter->v[0]); if (dir != 0 && iter->v[1] == 0){ for (;;){ struct dirent *d = readdir(dir); if (d == 0){ break; } // check file name is integer String8 file_name = str8_cstring((char*)d->d_name); B32 is_integer = str8_is_integer(file_name, 10); // break on integers (which represent processes) if (is_integer){ got_pid = true; pid_string = file_name; break; } } } // mark iterator dead if nothing found if (!got_pid){ iter->v[1] = 1; } // if got process id convert pid -> process info B32 result = false; if (got_pid){ // determine the name we will report pid_t pid = u64_from_str8(pid_string, 10); String8 name = demon_lnx_executable_path_from_pid(arena, pid); if (name.size == 0){ name = str8_lit(""); } // finish conversion info_out->name = name; info_out->pid = pid; result = true; } return(result); } internal void demon_os_proc_iter_end(DEMON_ProcessIter *iter){ DIR *dir = (DIR*)PtrFromInt(iter->v[0]); if (dir != 0){ closedir(dir); } MemoryZeroStruct(iter); } ================================================ FILE: src/demon/linux/demon_os_linux.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_OS_LINUX_H #define DEMON_OS_LINUX_H // TODO(allen): Potential Upgrades: // // memory fd upgrade - Right now for each process we hold open a file // descriptor for the process's memory (/proc/%d/mem) for the entire lifetime // of the process; it could be opened and closed with some kind of LRU cache // to put a finite cap on the number of handles the demon holds // //////////////////////////////// //~ NOTE(allen): Get The Linux Includes #include #include #include #include #include #include #include //////////////////////////////// //~ NOTE(allen): Linux Demon Types //- entities // Demon Linux Entity Extensions // Process: ext_u64 set to memory file descriptor // Thread : ext_u64 cast to DEMON_LNX_ThreadExt // Module : ext_u64 set to U64 (address of name) struct DEMON_LNX_ThreadExt{ B32 expecting_dummy_sigstop; }; StaticAssert(sizeof(DEMON_LNX_ThreadExt) <= sizeof(Member(DEMON_Entity, ext_u64)), check_demon_lnx_thread_ext); //- helpers struct DEMON_LNX_AttachNode{ DEMON_LNX_AttachNode *next; pid_t pid; }; struct DEMON_LNX_ProcessAux{ B32 filled; U64 phnum; U64 phent; U64 phdr; U64 execfn; }; struct DEMON_LNX_PhdrInfo{ Rng1U64 range; U64 dynamic; }; struct DEMON_LNX_ModuleNode{ DEMON_LNX_ModuleNode *next; U64 vaddr; U64 size; U64 name; U64 already_known; }; struct DEMON_LNX_EntityNode{ DEMON_LNX_EntityNode *next; DEMON_Entity *entity; }; //////////////////////////////// //~ NOTE(allen): Linux Demon Register Layouts // these are defined in but only for one architecture at a time // (and we can't really trick it into giving us both in any obvious way) // we define them here so that we have them all "at once" struct DEMON_LNX_UserRegsX64{ U64 r15; U64 r14; U64 r13; U64 r12; U64 rbp; U64 rbx; U64 r11; U64 r10; U64 r9; U64 r8; U64 rax; U64 rcx; U64 rdx; U64 rsi; U64 rdi; U64 orig_rax; U64 rip; U64 cs; U64 rflags; U64 rsp; U64 ss; U64 fsbase; U64 gsbase; U64 ds; U64 es; U64 fs; U64 gs; }; struct DEMON_LNX_UserX64{ DEMON_LNX_UserRegsX64 regs; S32 u_fpvalid, _pad0; SYMS_XSaveLegacy i387; U64 u_tsize, u_dsize, u_ssize, start_code, start_stack; U64 signal; S32 reserved, _pad1; U64 u_ar0, u_fpstate; U64 magic; U8 u_comm[32]; U64 u_debugreg[8]; }; struct DEMON_LNX_UserRegsX86{ U32 ebx; U32 ecx; U32 edx; U32 esi; U32 edi; U32 ebp; U32 eax; U32 ds; U32 es; U32 fs; U32 gs; U32 orig_eax; U32 eip; U32 cs; U32 eflags; U32 sp; U32 ss; }; struct DEMON_LNX_UserX86{ DEMON_LNX_UserRegsX86 regs; S32 u_fpvalid; SYMS_FSave i387; U32 u_tsize, u_dsize, u_ssize, start_code, start_stack; S32 signal, reserved; U32 u_ar0, u_fpstate; U32 magic; U8 u_comm[32]; U32 u_debugreg[8]; }; //////////////////////////////// enum { DEMON_LNX_PermFlags_Read = (1 << 0), DEMON_LNX_PermFlags_Write = (1 << 1), DEMON_LNX_PermFlags_Exec = (1 << 2), DEMON_LNX_PermFlags_Private = (1 << 3) }; typedef int DEMON_LNX_PermFlags; enum { DEMON_LNX_MapsEntryType_Null, DEMON_LNX_MapsEntryType_Path, DEMON_LNX_MapsEntryType_Heap, DEMON_LNX_MapsEntryType_Stack, DEMON_LNX_MapsEntryType_VDSO, }; typedef int DEMON_LNX_MapsEntryType; struct DEMON_LNX_MapsEntry { U64 address_lo; U64 address_hi; DEMON_LNX_PermFlags perms; U64 offset; U32 dev_major; U32 dev_minor; U64 inode; String8 pathname; DEMON_LNX_MapsEntryType type; pid_t stack_tid; }; //////////////////////////////// //~ rjf: Helpers internal DEMON_LNX_ThreadExt* demon_lnx_thread_ext(DEMON_Entity *entity); internal B32 demon_lnx_attach_pid(Arena *arena, pid_t pid, DEMON_LNX_AttachNode **new_node); internal String8 demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid); internal int demon_lnx_open_memory_fd_for_pid(pid_t pid); internal Arch demon_lnx_arch_from_pid(pid_t pid); internal DEMON_LNX_ProcessAux demon_lnx_aux_from_pid(pid_t pid, Arch arch); internal DEMON_LNX_PhdrInfo demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, U64 phvaddr, U64 phstride, U64 phcount); internal DEMON_LNX_ModuleNode* demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process); internal U64 demon_lnx_read_memory(int memory_fd, void *dst, U64 src, U64 size); internal B32 demon_lnx_write_memory(int memory_fd, U64 dst, void *src, U64 size); internal String8 demon_lnx_read_memory_str(Arena *arena, int memory_fd, U64 address); internal void demon_lnx_regs_x64_from_usr_regs_x64(SYMS_RegX64 *dst, DEMON_LNX_UserRegsX64 *src); internal void demon_lnx_usr_regs_x64_from_regs_x64(DEMON_LNX_UserRegsX64 *dst, SYMS_RegX64 *src); internal String8 demon_lnx_read_int_string(int fd); internal B32 demon_lnx_read_expect(int fd, char expect); internal int demon_lnx_read_whitespace(int fd); internal String8 demon_lnx_read_string(Arena *arena, int fd); internal int demon_lnx_open_maps(pid_t pid); internal B32 demon_lnx_next_map(Arena *arena, int maps, DEMON_LNX_MapsEntry *entry_out); #endif //DEMON_OS_LINUX_H ================================================ FILE: src/demon/win32/demon_core_win32.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Basic Helpers internal U64 dmn_w32_hash_from_string(String8 string) { U64 result = 5381; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + string.str[i]; } return result; } internal U64 dmn_w32_hash_from_id(U64 id) { return dmn_w32_hash_from_string(str8_struct(&id)); } //////////////////////////////// //~ rjf: Entity Helpers //- rjf: entity <-> handle internal DMN_Handle dmn_w32_handle_from_entity(DMN_W32_Entity *entity) { U32 idx = (U32)(entity - dmn_w32_shared->entities_base); U32 gen = entity->gen; DMN_Handle handle = {idx, gen}; return handle; } internal DMN_W32_Entity * dmn_w32_entity_from_handle(DMN_Handle handle) { U32 idx = handle.u32[0]; U32 gen = handle.u32[1]; DMN_W32_Entity *entity = dmn_w32_shared->entities_base + idx; if(entity->gen != gen) { entity = &dmn_w32_entity_nil; } return entity; } //- rjf: entity allocation/deallocation internal DMN_W32_Entity * dmn_w32_entity_alloc(DMN_W32_Entity *parent, DMN_W32_EntityKind kind, U64 id) { // rjf: allocate DMN_W32_Entity *e = dmn_w32_shared->entities_first_free; { U32 gen = 0; if(e != 0) { SLLStackPop(dmn_w32_shared->entities_first_free); gen = e->gen; } else { e = push_array_no_zero(dmn_w32_shared->entities_arena, DMN_W32_Entity, 1); dmn_w32_shared->entities_count += 1; } MemoryZeroStruct(e); e->gen = gen+1; } // rjf: fill { e->kind = kind; e->id = id; e->parent = parent; e->next = e->prev = e->first = e->last = &dmn_w32_entity_nil; if(parent != &dmn_w32_entity_nil) { DLLPushBack_NPZ(&dmn_w32_entity_nil, parent->first, parent->last, e, next, prev); } } // rjf: insert into id -> entity map if(id != 0) { U64 hash = dmn_w32_hash_from_id(id); U64 slot_idx = hash%dmn_w32_shared->entities_id_hash_slots_count; DMN_W32_EntityIDHashSlot *slot = &dmn_w32_shared->entities_id_hash_slots[slot_idx]; DMN_W32_EntityIDHashNode *node = 0; for(DMN_W32_EntityIDHashNode *n = slot->first; n != 0; n = n->next) { if(n->id == id) { node = n; break; } } if(node == 0) { node = dmn_w32_shared->entities_id_hash_node_free; if(node != 0) { SLLStackPop(dmn_w32_shared->entities_id_hash_node_free); } else { node = push_array(dmn_w32_shared->arena, DMN_W32_EntityIDHashNode, 1); } DLLPushBack(slot->first, slot->last, node); } node->id = id; node->entity = e; } return e; } internal void dmn_w32_entity_release(DMN_W32_Entity *entity) { // rjf: unhook root if(entity->parent != &dmn_w32_entity_nil) { DLLRemove_NPZ(&dmn_w32_entity_nil, entity->parent->first, entity->parent->last, entity, next, prev); } // rjf: walk every entity in this tree, free each if(entity != &dmn_w32_entity_nil) { Temp scratch = scratch_begin(0, 0); typedef struct Task Task; struct Task { Task *next; DMN_W32_Entity *e; }; Task start_task = {0, entity}; Task *first_task = &start_task; Task *last_task = &start_task; for(Task *t = first_task; t != 0; t = t->next) { for(DMN_W32_Entity *child = t->e->first; child != &dmn_w32_entity_nil; child = child->next) { Task *t = push_array(scratch.arena, Task, 1); t->e = child; SLLQueuePush(first_task, last_task, t); } // rjf: free entity SLLStackPush(dmn_w32_shared->entities_first_free, t->e); t->e->gen += 1; if(t->e->kind == DMN_W32_EntityKind_Module) { CloseHandle(t->e->handle); } t->e->kind = DMN_W32_EntityKind_Null; // rjf: remove from id -> entity map if(t->e->id != 0) { U64 hash = dmn_w32_hash_from_id(t->e->id); U64 slot_idx = hash%dmn_w32_shared->entities_id_hash_slots_count; DMN_W32_EntityIDHashSlot *slot = &dmn_w32_shared->entities_id_hash_slots[slot_idx]; DMN_W32_EntityIDHashNode *node = 0; for(DMN_W32_EntityIDHashNode *n = slot->first; n != 0; n = n->next) { if(n->id == t->e->id && n->entity == t->e) { DLLRemove(slot->first, slot->last, n); SLLStackPush(dmn_w32_shared->entities_id_hash_node_free, n); break; } } } } scratch_end(scratch); } } //- rjf: kind*id -> entity internal DMN_W32_Entity * dmn_w32_entity_from_kind_id(DMN_W32_EntityKind kind, U64 id) { DMN_W32_Entity *result = &dmn_w32_entity_nil; U64 hash = dmn_w32_hash_from_id(id); U64 slot_idx = hash%dmn_w32_shared->entities_id_hash_slots_count; DMN_W32_EntityIDHashSlot *slot = &dmn_w32_shared->entities_id_hash_slots[slot_idx]; DMN_W32_EntityIDHashNode *node = 0; for(DMN_W32_EntityIDHashNode *n = slot->first; n != 0; n = n->next) { if(n->entity->kind == kind && n->id == id) { node = n; break; } } if(node != 0) { result = node->entity; } return result; } //////////////////////////////// //~ rjf: Module Info Extraction internal String8 dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module) { Temp scratch = scratch_begin(&arena, 1); //- rjf: extract path from module String16 path16 = {0}; String8 path8 = {0}; { // rjf: handle -> full path if(module->handle != 0) { DWORD cap16 = GetFinalPathNameByHandleW(module->handle, 0, 0, VOLUME_NAME_DOS); U16 *buffer16 = push_array_no_zero(scratch.arena, U16, cap16); DWORD size16 = GetFinalPathNameByHandleW(module->handle, (WCHAR*)buffer16, cap16, VOLUME_NAME_DOS); path16 = str16(buffer16, size16); } // rjf: fallback (main module only): process -> full path if(path16.size == 0 && module->module.is_main) { DMN_W32_Entity *process = module->parent; DWORD size = KB(4); U16 *buf = push_array_no_zero(scratch.arena, U16, size); if(QueryFullProcessImageNameW(process->handle, 0, (WCHAR*)buf, &size)) { path16 = str16(buf, size); } } // rjf: fallback (any module - no guarantee): address_of_name -> full path if(path16.size == 0 && module->module.address_of_name_pointer != 0) { DMN_W32_Entity *process = module->parent; U64 ptr_size = bit_size_from_arch(process->arch)/8; U64 name_pointer = 0; if(dmn_w32_process_read(process->handle, r1u64(module->module.address_of_name_pointer, module->module.address_of_name_pointer+ptr_size), &name_pointer)) { if(name_pointer != 0) { if(module->module.name_is_unicode) { path16 = dmn_w32_read_memory_str16(scratch.arena, process->handle, name_pointer); } else { path8 = dmn_w32_read_memory_str(scratch.arena, process->handle, name_pointer); } } } } } // rjf: produce finalized result String8 result = {0}; { if(path16.size > 0) { // rjf: skip the extended path thing if necessary if(path16.size >= 4 && path16.str[0] == L'\\' && path16.str[1] == L'\\' && path16.str[2] == L'?' && path16.str[3] == L'\\') { path16.size -= 4; path16.str += 4; } // rjf: convert to UTF-8 result = str8_from_16(arena, path16); } else { // rjf: skip the extended path thing if necessary if (path8.size >= 4 && path8.str[0] == L'\\' && path8.str[1] == L'\\' && path8.str[2] == L'?' && path8.str[3] == L'\\') { path8.size -= 4; path8.str += 4; } // rjf: copy to output arena result = push_str8_copy(arena, path8); } } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Win32-Level Process/Thread Reads/Writes //- rjf: processes internal U64 dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst) { U64 bytes_read = 0; U8 *ptr = (U8*)dst; U8 *opl = ptr + dim_1u64(range); U64 cursor = range.min; for(;ptr < opl;) { SIZE_T to_read = (SIZE_T)(opl - ptr); SIZE_T actual_read = 0; if(!ReadProcessMemory(process, (LPCVOID)cursor, ptr, to_read, &actual_read)) { DWORD error = GetLastError(); log_infof("'Win32 ReadProcessMemory failure': { [0x%I64x, 0x%I64x), code: %i }\n", range.min, range.max, error); // NOTE(rjf): I have discovered that `actual_read` is *NOT* guaranteed to have // a usable value if `ReadProcessMemory` fails! // bytes_read += actual_read; (void)error; break; } ptr += actual_read; cursor += actual_read; bytes_read += actual_read; } return bytes_read; } internal B32 dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src) { B32 result = 1; U8 *ptr = (U8*)src; U8 *opl = ptr + dim_1u64(range); U64 cursor = range.min; for(;ptr < opl;) { SIZE_T to_write = (SIZE_T)(opl - ptr); SIZE_T actual_write = 0; if(!WriteProcessMemory(process, (LPVOID)cursor, ptr, to_write, &actual_write)) { result = 0; break; } ptr += actual_write; cursor += actual_write; } return result; } internal String8 dmn_w32_read_memory_str(Arena *arena, HANDLE process_handle, U64 address) { // TODO(rjf): @rewrite // // OLD: this could be done better with a demon_w32_read_memory // that returns a read amount instead of a success/fail. // // (dmn_w32_process_read now does this, so we can switch to it) // scan piece by piece Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; U64 max_cap = 256; U64 cap = max_cap; U64 read_p = address; for (;;){ U8 *block = push_array(scratch.arena, U8, cap); for (;cap > 0;){ if (dmn_w32_process_read(process_handle, r1u64(read_p, read_p+cap), block)){ break; } cap /= 2; } read_p += cap; U64 block_opl = 0; for (;block_opl < cap; block_opl += 1){ if (block[block_opl] == 0){ break; } } if (block_opl > 0){ str8_list_push(scratch.arena, &list, str8(block, block_opl)); } if (block_opl < cap || cap == 0){ break; } } // assemble results String8 result = str8_list_join(arena, &list, 0); scratch_end(scratch); return(result); } internal String16 dmn_w32_read_memory_str16(Arena *arena, HANDLE process_handle, U64 address) { // TODO(rjf): @rewrite // // OLD: this could be done better with a demon_w32_read_memory // that returns a read amount instead of a success/fail. // // (dmn_w32_process_read now does this, so we can switch to it) // scan piece by piece Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; U64 max_cap = 256; U64 cap = max_cap; U64 read_p = address; for (;;){ U8 *block = push_array(scratch.arena, U8, cap); for (;cap > 1;){ if (dmn_w32_process_read(process_handle, r1u64(read_p, read_p+cap), block)){ break; } cap /= 2; } read_p += cap; U16 *block16 = (U16*)block; (void)block16; U64 block_opl = 0; for (;block_opl < cap; block_opl += 2){ if (*(U16*)(block + block_opl) == 0){ break; } } if (block_opl > 0){ str8_list_push(scratch.arena, &list, str8(block, block_opl)); } if (block_opl < cap || cap == 0){ break; } } // assemble results String8 joined = str8_list_join(arena, &list, 0); String16 result = {(U16*)joined.str, joined.size/2}; scratch_end(scratch); return(result); } internal DMN_W32_ImageInfo dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr) { // rjf: find PE offset U32 pe_offset = 0; { U64 dos_magic_off = base_vaddr; U16 dos_magic = 0; dmn_w32_process_read_struct(process, dos_magic_off, &dos_magic); if(dos_magic == PE_DOS_MAGIC) { U64 pe_offset_off = base_vaddr + OffsetOf(PE_DosHeader, coff_file_offset); dmn_w32_process_read_struct(process, pe_offset_off, &pe_offset); } } // rjf: get COFF header B32 got_coff_header = 0; U64 coff_header_off = 0; COFF_FileHeader coff_header = {0}; if(pe_offset > 0) { U64 pe_magic_off = base_vaddr + pe_offset; U32 pe_magic = 0; dmn_w32_process_read_struct(process, pe_magic_off, &pe_magic); if(pe_magic == PE_MAGIC) { coff_header_off = pe_magic_off + sizeof(pe_magic); if(dmn_w32_process_read_struct(process, coff_header_off, &coff_header)) { got_coff_header = 1; } } } // rjf: get arch and size DMN_W32_ImageInfo result = zero_struct; if(got_coff_header) { U64 optional_size_off = 0; Arch arch = Arch_Null; switch(coff_header.machine) { case COFF_MachineType_X86: { arch = Arch_x86; optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image); }break; case COFF_MachineType_X64: { arch = Arch_x64; optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image); }break; default: {}break; } if(arch != Arch_Null) { U64 optional_off = coff_header_off + sizeof(coff_header); U32 size = 0; if(dmn_w32_process_read_struct(process, optional_off+optional_size_off, &size) >= sizeof(size)) { result.arch = arch; result.size = size; } } } return result; } //- rjf: threads internal U16 dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave) { U16 result = 0; U32 top = (fxsave->StatusWord >> 11) & 7; for(U32 fpr = 0; fpr < 8; fpr += 1) { U32 tag = 3; if(fxsave->TagWord & (1 << fpr)) { U32 st = (fpr - top)&7; REGS_Reg80 *fp = (REGS_Reg80*)&fxsave->FloatRegisters[st*16]; U16 exponent = fp->sign1_exp15 & bitmask15; U64 integer_part = fp->int1_frac63 >> 63; U64 fraction_part = fp->int1_frac63 & bitmask63; // tag: 0 - normal; 1 - zero; 2 - special tag = 2; if(exponent == 0) { if(integer_part == 0 && fraction_part == 0) { tag = 1; } } else if(exponent != bitmask15 && integer_part != 0) { tag = 0; } } result |= tag << (2 * fpr); } return result; } internal U16 dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw) { U16 compact = 0; for(U32 fpr = 0; fpr < 8; fpr++) { U32 tag = (ftw >> (fpr * 2)) & 3; if(tag != 3) { compact |= (1 << fpr); } } return compact; } internal B32 dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block) { B32 result = 0; ProfBeginFunction(); switch(arch) { //////////////////////////// //- rjf: unimplemented win32/arch combos // case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; //////////////////////////// //- rjf: x86 // case Arch_x86: { REGS_RegBlockX86 *dst = (REGS_RegBlockX86 *)reg_block; //- rjf: get thread context WOW64_CONTEXT ctx = {0}; ctx.ContextFlags = DMN_W32_CTX_X86_ALL; if(!Wow64GetThreadContext(thread, (WOW64_CONTEXT *)&ctx)) { break; } result = 1; //- rjf: convert WOW64_CONTEXT -> REGS_RegBlockX86 XSAVE_FORMAT *fxsave = (XSAVE_FORMAT *)ctx.ExtendedRegisters; dst->eax.u32 = ctx.Eax; dst->ebx.u32 = ctx.Ebx; dst->ecx.u32 = ctx.Ecx; dst->edx.u32 = ctx.Edx; dst->esi.u32 = ctx.Esi; dst->edi.u32 = ctx.Edi; dst->esp.u32 = ctx.Esp; dst->ebp.u32 = ctx.Ebp; dst->eip.u32 = ctx.Eip; dst->cs.u16 = ctx.SegCs; dst->ds.u16 = ctx.SegDs; dst->es.u16 = ctx.SegEs; dst->fs.u16 = ctx.SegFs; dst->gs.u16 = ctx.SegGs; dst->ss.u16 = ctx.SegSs; dst->dr0.u32 = ctx.Dr0; dst->dr1.u32 = ctx.Dr1; dst->dr2.u32 = ctx.Dr2; dst->dr3.u32 = ctx.Dr3; dst->dr6.u32 = ctx.Dr6; dst->dr7.u32 = ctx.Dr7; // NOTE(rjf): this bit is "supposed to always be 1", according to old info. // may need to be investigated. dst->eflags.u32 = ctx.EFlags | 0x2; dst->fcw.u16 = fxsave->ControlWord; dst->fsw.u16 = fxsave->StatusWord; dst->ftw.u16 = dmn_w32_real_tag_word_from_xsave(fxsave); dst->fop.u16 = fxsave->ErrorOpcode; dst->fip.u32 = fxsave->ErrorOffset; dst->fcs.u16 = fxsave->ErrorSelector; dst->fdp.u32 = fxsave->DataOffset; dst->fds.u16 = fxsave->DataSelector; dst->mxcsr.u32 = fxsave->MxCsr; dst->mxcsr_mask.u32 = fxsave->MxCsr_Mask; { M128A *float_s = fxsave->FloatRegisters; REGS_Reg80 *float_d = &dst->fpr0; for(U32 n = 0; n < 8; n += 1, float_s += 1, float_d += 1) { MemoryCopy(float_d, float_s, sizeof(*float_d)); } } { M128A *xmm_s = fxsave->XmmRegisters; REGS_Reg256 *xmm_d = &dst->ymm0; for(U32 n = 0; n < 8; n += 1, xmm_s += 1, xmm_d += 1) { MemoryCopy(xmm_d, xmm_s, sizeof(*xmm_s)); } } //- rjf: read FS/GS base WOW64_LDT_ENTRY ldt = {0}; if(Wow64GetThreadSelectorEntry(thread, ctx.SegFs, &ldt)) { U32 base = (ldt.BaseLow) | (ldt.HighWord.Bytes.BaseMid << 16) | (ldt.HighWord.Bytes.BaseHi << 24); dst->fsbase.u32 = base; } if(Wow64GetThreadSelectorEntry(thread, ctx.SegGs, &ldt)) { U32 base = (ldt.BaseLow) | (ldt.HighWord.Bytes.BaseMid << 16) | (ldt.HighWord.Bytes.BaseHi << 24); dst->gsbase.u32 = base; } }break; //////////////////////////// //- rjf: x64 // case Arch_x64: { Temp scratch = scratch_begin(0, 0); REGS_RegBlockX64 *dst = (REGS_RegBlockX64 *)reg_block; //- rjf: unpack info about available features U32 feature_mask = GetEnabledXStateFeatures(); B32 xstate_enabled = (feature_mask & (XSTATE_MASK_AVX | XSTATE_MASK_AVX512 | XSTATE_MASK_CET_U)) != 0; //- rjf: set up context CONTEXT *ctx = 0; U32 ctx_flags = DMN_W32_CTX_X64_ALL | (xstate_enabled ? DMN_W32_CTX_INTEL_XSTATE : 0); DWORD size = 0; InitializeContext(0, ctx_flags, 0, &size); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { void *ctx_memory = push_array(scratch.arena, U8, size); if(!InitializeContext(ctx_memory, ctx_flags, &ctx, &size)) { ctx = 0; } } //- rjf: unpack features available on this context if (xstate_enabled) { SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX | XSTATE_MASK_AVX512 | XSTATE_MASK_CET_U); } //- rjf: get thread context if(!GetThreadContext(thread, ctx)) { ctx = 0; } //- rjf: bad context -> abort if(ctx == 0) { break; } result = 1; DWORD64 xstate_mask = 0; GetXStateFeaturesMask(ctx, &xstate_mask); //- rjf: convert context -> REGS_RegBlockX64 XSAVE_FORMAT *xsave = &ctx->FltSave; dst->rax.u64 = ctx->Rax; dst->rcx.u64 = ctx->Rcx; dst->rdx.u64 = ctx->Rdx; dst->rbx.u64 = ctx->Rbx; dst->rsp.u64 = ctx->Rsp; dst->rbp.u64 = ctx->Rbp; dst->rsi.u64 = ctx->Rsi; dst->rdi.u64 = ctx->Rdi; dst->r8.u64 = ctx->R8; dst->r9.u64 = ctx->R9; dst->r10.u64 = ctx->R10; dst->r11.u64 = ctx->R11; dst->r12.u64 = ctx->R12; dst->r13.u64 = ctx->R13; dst->r14.u64 = ctx->R14; dst->r15.u64 = ctx->R15; dst->rip.u64 = ctx->Rip; dst->cs.u16 = ctx->SegCs; dst->ds.u16 = ctx->SegDs; dst->es.u16 = ctx->SegEs; dst->fs.u16 = ctx->SegFs; dst->gs.u16 = ctx->SegGs; dst->ss.u16 = ctx->SegSs; dst->dr0.u64 = ctx->Dr0; dst->dr1.u64 = ctx->Dr1; dst->dr2.u64 = ctx->Dr2; dst->dr3.u64 = ctx->Dr3; dst->dr6.u64 = ctx->Dr6; dst->dr7.u64 = ctx->Dr7; // NOTE(rjf): this bit is "supposed to always be 1", according to old info. // may need to be investigated. dst->rflags.u64 = ctx->EFlags | 0x2; dst->fcw.u16 = xsave->ControlWord; dst->fsw.u16 = xsave->StatusWord; dst->ftw.u16 = dmn_w32_real_tag_word_from_xsave(xsave); dst->fop.u16 = xsave->ErrorOpcode; dst->fcs.u16 = xsave->ErrorSelector; dst->fds.u16 = xsave->DataSelector; dst->fip.u64 = xsave->ErrorOffset; dst->fdp.u64 = xsave->DataOffset; dst->mxcsr.u32 = xsave->MxCsr; dst->mxcsr_mask.u32 = xsave->MxCsr_Mask; { M128A *float_s = xsave->FloatRegisters; REGS_Reg80 *float_d = &dst->fpr0; for(U32 n = 0; n < 8; n += 1, float_s += 1, float_d += 1) { MemoryCopy(float_d, float_s, sizeof(*float_d)); } } // SSE registers are always available in x64 { M128A *xmm_s = xsave->XmmRegisters; REGS_Reg512 *zmm_d = &dst->zmm0; for(U32 n = 0; n < 16; n += 1, xmm_s += 1, zmm_d += 1) { MemoryCopy(zmm_d, xmm_s, sizeof(*xmm_s)); } } // AVX if(xstate_mask & XSTATE_MASK_AVX) { DWORD avx_length = 0; U8* avx_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX, &avx_length); Assert(avx_length == 16 * sizeof(REGS_Reg128)); REGS_Reg512 *zmm_d = &dst->zmm0; for(U32 n = 0; n < 16; n += 1, avx_s += sizeof(REGS_Reg128), zmm_d += 1) { MemoryCopy(&zmm_d->v[16], avx_s, sizeof(REGS_Reg128)); } } else { REGS_Reg512 *zmm_d = &dst->zmm0; for(U32 n = 0; n < 16; n += 1, zmm_d += 1) { MemoryZero(&zmm_d->v[16], sizeof(REGS_Reg128)); } } // AVX-512 if(xstate_mask & XSTATE_MASK_AVX512) { DWORD kmask_length = 0; U64* kmask_s = (U64*)LocateXStateFeature(ctx, XSTATE_AVX512_KMASK, &kmask_length); Assert(kmask_length == 8 * sizeof(U64)); REGS_Reg64 *kmask_d = &dst->k0; for(U32 n = 0; n < 8; n += 1, kmask_s += 1, kmask_d += 1) { MemoryCopy(kmask_d, kmask_s, sizeof(*kmask_s)); } DWORD avx512h_length = 0; U8* avx512h_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM_H, &avx512h_length); Assert(avx512h_length == 16 * sizeof(REGS_Reg256)); REGS_Reg512 *zmmh_d = &dst->zmm0; for(U32 n = 0; n < 16; n += 1, avx512h_s += sizeof(REGS_Reg256), zmmh_d += 1) { MemoryCopy(&zmmh_d->v[32], avx512h_s, sizeof(REGS_Reg256)); } DWORD avx512_length = 0; U8* avx512_s = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM, &avx512_length); Assert(avx512_length == 16 * sizeof(REGS_Reg512)); REGS_Reg512 *zmm_d = &dst->zmm16; for(U32 n = 0; n < 16; n += 1, avx512_s += sizeof(REGS_Reg512), zmm_d += 1) { MemoryCopy(zmm_d, avx512_s, sizeof(REGS_Reg512)); } } else { REGS_Reg64 *kmask_d = &dst->k0; for(U32 n = 0; n < 8; n += 1, kmask_d += 1) { MemoryZero(kmask_d, sizeof(*kmask_d)); } REGS_Reg512 *zmmh_d = &dst->zmm0; for(U32 n = 0; n < 16; n += 1, zmmh_d += 1) { MemoryZero(&zmmh_d->v[32], sizeof(REGS_Reg256)); } REGS_Reg512 *zmm_d = &dst->zmm16; for(U32 n = 0; n < 16; n += 1, zmm_d += 1) { MemoryZero(zmm_d, sizeof(*zmm_d)); } } // CET / Shadow Stack if(xstate_mask & XSTATE_MASK_CET_U) { DWORD cet_length = 0; XSAVE_CET_U_FORMAT *cet = LocateXStateFeature(ctx, XSTATE_CET_U, &cet_length); if (cet_length == sizeof(*cet)) { dst->cetmsr.u64 = cet->Ia32CetUMsr; dst->cetssp.u64 = cet->Ia32Pl3SspMsr; } } scratch_end(scratch); }break; } ProfEnd(); return result; } internal B32 dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block) { B32 result = 0; ProfBeginFunction(); switch(arch) { //////////////////////////// //- rjf: unimplemented win32/arch combos // case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; //////////////////////////// //- rjf: x86 // case Arch_x86: { REGS_RegBlockX86 *src = (REGS_RegBlockX86 *)reg_block; //- rjf: convert REGS_RegBlockX86 -> WOW64_CONTEXT WOW64_CONTEXT ctx = {0}; XSAVE_FORMAT *fxsave = (XSAVE_FORMAT*)ctx.ExtendedRegisters; ctx.ContextFlags = DMN_W32_CTX_X86_ALL; ctx.Eax = src->eax.u32; ctx.Ebx = src->ebx.u32; ctx.Ecx = src->ecx.u32; ctx.Edx = src->edx.u32; ctx.Esi = src->esi.u32; ctx.Edi = src->edi.u32; ctx.Esp = src->esp.u32; ctx.Ebp = src->ebp.u32; ctx.Eip = src->eip.u32; ctx.SegCs = src->cs.u16; ctx.SegDs = src->ds.u16; ctx.SegEs = src->es.u16; ctx.SegFs = src->fs.u16; ctx.SegGs = src->gs.u16; ctx.SegSs = src->ss.u16; ctx.Dr0 = src->dr0.u32; ctx.Dr1 = src->dr1.u32; ctx.Dr2 = src->dr2.u32; ctx.Dr3 = src->dr3.u32; ctx.Dr6 = src->dr6.u32; ctx.Dr7 = src->dr7.u32; ctx.EFlags = src->eflags.u32; fxsave->ControlWord = src->fcw.u16; fxsave->StatusWord = src->fsw.u16; fxsave->TagWord = dmn_w32_xsave_tag_word_from_real_tag_word(src->ftw.u16); fxsave->ErrorOpcode = src->fop.u16; fxsave->ErrorSelector = src->fcs.u16; fxsave->DataSelector = src->fds.u16; fxsave->ErrorOffset = src->fip.u32; fxsave->DataOffset = src->fdp.u32; fxsave->MxCsr = src->mxcsr.u32 & src->mxcsr_mask.u32; fxsave->MxCsr_Mask = src->mxcsr_mask.u32; { M128A *float_d = fxsave->FloatRegisters; REGS_Reg80 *float_s = &src->fpr0; for(U32 n = 0; n < 8; n += 1, float_s += 1, float_d += 1) { MemoryCopy(float_d, float_s, 10); } } { M128A *xmm_d = fxsave->XmmRegisters; REGS_Reg256 *xmm_s = &src->ymm0; for(U32 n = 0; n < 8; n += 1, xmm_d += 1, xmm_s += 1) { MemoryCopy(xmm_d, xmm_s, sizeof(*xmm_d)); } } //- rjf: set thread context B32 result = 0; if(Wow64SetThreadContext(thread, &ctx)) { result = 1; } }break; //////////////////////////// //- rjf: x64 // case Arch_x64: { Temp scratch = scratch_begin(0, 0); REGS_RegBlockX64 *src = (REGS_RegBlockX64 *)reg_block; //- rjf: unpack info about available features U32 feature_mask = GetEnabledXStateFeatures(); B32 xstate_enabled = (feature_mask & (XSTATE_MASK_AVX | XSTATE_MASK_AVX512)) != 0; //- rjf: set up context CONTEXT *ctx = 0; U32 ctx_flags = DMN_W32_CTX_X64_ALL | (xstate_enabled ? DMN_W32_CTX_INTEL_XSTATE : 0); DWORD size = 0; InitializeContext(0, ctx_flags, 0, &size); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { void *ctx_memory = push_array(scratch.arena, U8, size); if(!InitializeContext(ctx_memory, ctx_flags, &ctx, &size)) { ctx = 0; } } //- rjf: unpack features available on this context if (xstate_enabled) { SetXStateFeaturesMask(ctx, XSTATE_MASK_AVX | XSTATE_MASK_AVX512); } //- rjf: bad context -> abort if(ctx == 0) { break; } //- rjf: convert REGS_RegBlockX64 -> CONTEXT XSAVE_FORMAT *fxsave = &ctx->FltSave; ctx->ContextFlags = ctx_flags; ctx->MxCsr = src->mxcsr.u32 & src->mxcsr_mask.u32; ctx->Rax = src->rax.u64; ctx->Rcx = src->rcx.u64; ctx->Rdx = src->rdx.u64; ctx->Rbx = src->rbx.u64; ctx->Rsp = src->rsp.u64; ctx->Rbp = src->rbp.u64; ctx->Rsi = src->rsi.u64; ctx->Rdi = src->rdi.u64; ctx->R8 = src->r8.u64; ctx->R9 = src->r9.u64; ctx->R10 = src->r10.u64; ctx->R11 = src->r11.u64; ctx->R12 = src->r12.u64; ctx->R13 = src->r13.u64; ctx->R14 = src->r14.u64; ctx->R15 = src->r15.u64; ctx->Rip = src->rip.u64; ctx->SegCs = src->cs.u16; ctx->SegDs = src->ds.u16; ctx->SegEs = src->es.u16; ctx->SegFs = src->fs.u16; ctx->SegGs = src->gs.u16; ctx->SegSs = src->ss.u16; ctx->Dr0 = src->dr0.u64; ctx->Dr1 = src->dr1.u64; ctx->Dr2 = src->dr2.u64; ctx->Dr3 = src->dr3.u64; ctx->Dr6 = src->dr6.u64; ctx->Dr7 = src->dr7.u64; ctx->EFlags = src->rflags.u64; fxsave->ControlWord = src->fcw.u16; fxsave->StatusWord = src->fsw.u16; fxsave->TagWord = dmn_w32_xsave_tag_word_from_real_tag_word(src->ftw.u16); fxsave->ErrorOpcode = src->fop.u16; fxsave->ErrorSelector = src->fcs.u16; fxsave->DataSelector = src->fds.u16; fxsave->ErrorOffset = src->fip.u64; fxsave->DataOffset = src->fdp.u64; { M128A *float_d = fxsave->FloatRegisters; REGS_Reg80 *float_s = &src->fpr0; for(U32 n = 0; n < 8; n += 1, float_s += 1, float_d += 1) { MemoryCopy(float_d, float_s, 10); } } // SSE registers are always available in x64 { M128A *xmm_d = fxsave->XmmRegisters; REGS_Reg512 *zmm_s = &src->zmm0; for(U32 n = 0; n < 16; n += 1, xmm_d += 1, zmm_s += 1) { MemoryCopy(xmm_d, zmm_s, sizeof(*xmm_d)); } } // AVX if(feature_mask & XSTATE_MASK_AVX) { DWORD avx_length = 0; U8* avx_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX, &avx_length); Assert(avx_length == 16 * sizeof(REGS_Reg128)); REGS_Reg512 *zmm_s = &src->zmm0; for(U32 n = 0; n < 16; n += 1, avx_d += sizeof(REGS_Reg128), zmm_s += 1) { MemoryCopy(avx_d, &zmm_s->v[16], sizeof(REGS_Reg128)); } } // AVX-512 if(feature_mask & XSTATE_MASK_AVX512) { DWORD kmask_length = 0; U64* kmask_d = (U64*)LocateXStateFeature(ctx, XSTATE_AVX512_KMASK, &kmask_length); Assert(kmask_length == 8 * sizeof(*kmask_d)); REGS_Reg64 *kmask_s = &src->k0; for(U32 n = 0; n < 8; n += 1, kmask_s += 1, kmask_d += 1) { MemoryCopy(kmask_d, kmask_s, sizeof(*kmask_d)); } DWORD avx512h_length = 0; U8* avx512h_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM_H, &avx512h_length); Assert(avx512h_length == 16 * sizeof(REGS_Reg256)); REGS_Reg512 *zmmh_s = &src->zmm0; for(U32 n = 0; n < 16; n += 1, avx512h_d += sizeof(REGS_Reg256), zmmh_s += 1) { MemoryCopy(avx512h_d, &zmmh_s->v[32], sizeof(REGS_Reg256)); } DWORD avx512_length = 0; U8* avx512_d = (U8*)LocateXStateFeature(ctx, XSTATE_AVX512_ZMM, &avx512_length); Assert(avx512_length == 16 * sizeof(REGS_Reg512)); REGS_Reg512 *zmm_s = &src->zmm16; for(U32 n = 0; n < 16; n += 1, avx512_d += sizeof(REGS_Reg512), zmm_s += 1) { MemoryCopy(avx512_d, zmm_s, sizeof(REGS_Reg512)); } } //- rjf: set thread context if(SetThreadContext(thread, ctx)) { result = 1; } scratch_end(scratch); }break; } ProfEnd(); return result; } //- rjf: remote thread injection internal DWORD dmn_w32_inject_thread(HANDLE process, U64 start_address) { LPTHREAD_START_ROUTINE start = (LPTHREAD_START_ROUTINE)start_address; DWORD thread_id = 0; HANDLE thread = CreateRemoteThread(process, 0, 0, start, 0, 0, &thread_id); if(thread != 0) { CloseHandle(thread); } return thread_id; } //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) internal void dmn_init(void) { Arena *arena = arena_alloc(); dmn_w32_shared = push_array(arena, DMN_W32_Shared, 1); dmn_w32_shared->arena = arena; dmn_w32_shared->access_mutex = mutex_alloc(); dmn_w32_shared->detach_arena = arena_alloc(); dmn_w32_shared->entities_arena = arena_alloc(.reserve_size = GB(8), .commit_size = KB(64)); dmn_w32_shared->entities_base = dmn_w32_entity_alloc(&dmn_w32_entity_nil, DMN_W32_EntityKind_Root, 0); dmn_w32_shared->entities_id_hash_slots_count = 4096; dmn_w32_shared->entities_id_hash_slots = push_array(arena, DMN_W32_EntityIDHashSlot, dmn_w32_shared->entities_id_hash_slots_count); // rjf: load Windows 10+ GetThreadDescription API { dmn_w32_GetThreadDescription = (DMN_W32_GetThreadDescriptionFunctionType *)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetThreadDescription"); } // rjf: setup environment variables { WCHAR *this_proc_env = GetEnvironmentStringsW(); U64 start_idx = 0; for(U64 idx = 0;; idx += 1) { if(this_proc_env[idx] == 0) { if(start_idx == idx) { break; } else { String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx); String8 string = str8_from_16(dmn_w32_shared->arena, string16); str8_list_push(dmn_w32_shared->arena, &dmn_w32_shared->env_strings, string); start_idx = idx+1; } } } } } //////////////////////////////// //~ rjf: @dmn_os_hooks Blocking Control Thread Operations (Implemented Per-OS) internal DMN_CtrlCtx * dmn_ctrl_begin(void) { DMN_CtrlCtx *ctx = (DMN_CtrlCtx *)1; dmn_w32_ctrl_thread = 1; return ctx; } internal void dmn_ctrl_exclusive_access_begin(void) { MutexScope(dmn_w32_shared->access_mutex) { dmn_w32_shared->access_run_state = 1; } } internal void dmn_ctrl_exclusive_access_end(void) { MutexScope(dmn_w32_shared->access_mutex) { dmn_w32_shared->access_run_state = 0; } } internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params) { Temp scratch = scratch_begin(0, 0); U32 result = 0; DMN_AccessScope { //- rjf: produce exe / arguments string String8 cmd = {0}; if(params->cmd_line.first != 0) { String8List args = {0}; String8 exe_path = params->cmd_line.first->string; String8List exe_path_parts = str8_split_path(scratch.arena, exe_path); exe_path = str8_list_join(scratch.arena, &exe_path_parts, &(StringJoin){.sep = str8_lit("\\")}); str8_list_pushf(scratch.arena, &args, "\"%S\"", exe_path); for(String8Node *n = params->cmd_line.first->next; n != 0; n = n->next) { str8_list_push(scratch.arena, &args, n->string); } StringJoin join_params = {0}; join_params.sep = str8_lit(" "); cmd = str8_list_join(scratch.arena, &args, &join_params); } //- rjf: produce environment strings String8 env = {0}; { String8List all_opts = params->env; if(params->inherit_env != 0) { MemoryZeroStruct(&all_opts); str8_list_push(scratch.arena, &all_opts, str8_lit("_NO_DEBUG_HEAP=1")); for(String8Node *n = params->env.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } for(String8Node *n = dmn_w32_shared->env_strings.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } } StringJoin join_params2 = {0}; join_params2.sep = str8_lit("\0"); join_params2.post = str8_lit("\0"); env = str8_list_join(scratch.arena, &all_opts, &join_params2); } //- rjf: produce utf-16 strings String16 cmd16 = str16_from_8(scratch.arena, cmd); String16 dir16 = str16_from_8(scratch.arena, params->path); String16 env16 = str16_from_8(scratch.arena, env); //- rjf: launch DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT; if(params->debug_subprocesses) { creation_flags |= DEBUG_PROCESS; } else { creation_flags |= DEBUG_ONLY_THIS_PROCESS; } BOOL inherit_handles = 0; STARTUPINFOW startup_info = {sizeof(startup_info)}; if(!os_handle_match(params->stdout_file, os_handle_zero())) { HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0]; startup_info.hStdOutput = stdout_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stderr_file, os_handle_zero())) { HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0]; startup_info.hStdError = stderr_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stdin_file, os_handle_zero())) { HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0]; startup_info.hStdInput = stdin_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } PROCESS_INFORMATION process_info = {0}; if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, creation_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info)) { // check if we are 32-bit app, and just close it immediately BOOL is_wow = 0; IsWow64Process(process_info.hProcess, &is_wow); if(is_wow) { log_user_errorf("Only 64-bit applications can be debugged currently."); DebugActiveProcessStop(process_info.dwProcessId); TerminateProcess(process_info.hProcess,0xffffffff); } else { result = process_info.dwProcessId; dmn_w32_shared->new_process_pending = 1; } CloseHandle(process_info.hProcess); CloseHandle(process_info.hThread); } else { DWORD error = GetLastError(); LPWSTR message = 0; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL), (LPWSTR)&message, 0, 0); String8 message8 = message ? str8_from_16(scratch.arena, str16_cstring(message)) : str8_lit("unknown error"); LocalFree(message); log_user_errorf("There was an error starting %S: %S", params->cmd_line.first->string, message8); } } scratch_end(scratch); return result; } internal B32 dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid) { B32 result = 0; DMN_AccessScope if(DebugActiveProcess((DWORD)pid)) { result = 1; dmn_w32_shared->new_process_pending = 1; #if 0 // TODO(rjf): JIT debugging info { typedef struct JIT_DEBUG_INFO JIT_DEBUG_INFO; struct JIT_DEBUG_INFO { DWORD dwSize; DWORD dwProcessorArchitecture; DWORD dwThreadID; DWORD dwReserved0; ULONG64 lpExceptionAddress; ULONG64 lpExceptionRecord; ULONG64 lpContextRecord; }; } #endif } return result; } internal B32 dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code) { B32 result = 0; DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); if(TerminateProcess(process_entity->handle, exit_code)) { result = 1; } } return result; } internal B32 dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process) { B32 result = 0; DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); // rjf: resume threads for(DMN_W32_Entity *child = process_entity->first; child != &dmn_w32_entity_nil; child = child->next) { if(child->kind == DMN_W32_EntityKind_Thread) { DWORD resume_result = ResumeThread(child->handle); (void)resume_result; } } // rjf: detach { DWORD pid = (DWORD)process_entity->id; if(DebugActiveProcessStop(pid)) { result = 1; } } // rjf: push into list of processes to generate events for later if(result != 0) { dmn_handle_list_push(dmn_w32_shared->detach_arena, &dmn_w32_shared->detach_processes, process); } } return result; } internal DMN_EventList dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { DMN_EventList events = {0}; dmn_access_open(); ////////////////////////////// //- rjf: determine event generation path // typedef enum DMN_W32_EventGenPath { DMN_W32_EventGenPath_NotAttached, DMN_W32_EventGenPath_Run, DMN_W32_EventGenPath_DetachProcesses, } DMN_W32_EventGenPath; DMN_W32_EventGenPath event_gen_path = DMN_W32_EventGenPath_Run; if(dmn_w32_shared->detach_processes.first != 0) { event_gen_path = DMN_W32_EventGenPath_DetachProcesses; } else { B32 any_processes_live = dmn_w32_shared->new_process_pending; if(!any_processes_live) { for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; process != &dmn_w32_entity_nil; process = process->next) { if(process->kind == DMN_W32_EntityKind_Process) { any_processes_live = 1; break; } } } if(!any_processes_live) { event_gen_path = DMN_W32_EventGenPath_NotAttached; } } ////////////////////////////// //- rjf: produce debug events // switch(event_gen_path) { //////////////////////////// //- rjf: produce not-attached error events // case DMN_W32_EventGenPath_NotAttached: { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_Error; e->error_kind = DMN_ErrorKind_NotAttached; }break; //////////////////////////// //- rjf: produce debug events from regular running // case DMN_W32_EventGenPath_Run: { Temp scratch = scratch_begin(&arena, 1); ////////////////////////// //- rjf: get single step thread's context (x64 single-step-set fast path) // CONTEXT *single_step_thread_ctx = 0; if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); Arch arch = thread->arch; switch(arch) { default:{}break; case Arch_x64: { U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; DWORD size = 0; InitializeContext(0, ctx_flags, 0, &size); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { void *ctx_memory = push_array(scratch.arena, U8, size); if(!InitializeContext(ctx_memory, ctx_flags, &single_step_thread_ctx, &size)) { single_step_thread_ctx = 0; } } }break; } } ////////////////////////// //- rjf: set single step bit // if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("set single step bit") { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); Arch arch = thread->arch; switch(arch) { //- rjf: unimplemented win32/arch combos case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; //- rjf: x86 case Arch_x86: { REGS_RegBlockX86 regs = {0}; dmn_thread_read_reg_block(ctrls->single_step_thread, ®s); regs.eflags.u32 |= 0x100; dmn_thread_write_reg_block(ctrls->single_step_thread, ®s); }break; //- rjf: x64 case Arch_x64: { if(!GetThreadContext(thread->handle, single_step_thread_ctx)) { single_step_thread_ctx = 0; } if(single_step_thread_ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; U64 new_rflags = rflags | 0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); } }break; } } ////////////////////////// //- rjf: write all traps into memory // U8 *trap_swap_bytes = push_array_no_zero(scratch.arena, U8, ctrls->traps.trap_count); ProfScope("write all traps into memory") { U64 trap_idx = 0; for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1) { DMN_Trap *trap = n->v+n_idx; if(trap->flags == 0) { trap_swap_bytes[trap_idx] = 0xCC; dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr+1), trap_swap_bytes+trap_idx); U8 int3 = 0xCC; dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &int3); } } } } ////////////////////////// //- rjf: gather all flagged traps, bucketed by process // typedef struct DMN_FlaggedTrapTask DMN_FlaggedTrapTask; struct DMN_FlaggedTrapTask { DMN_FlaggedTrapTask *next; DMN_Handle process; DMN_TrapChunkList traps; }; DMN_FlaggedTrapTask *first_flagged_trap_task = 0; DMN_FlaggedTrapTask *last_flagged_trap_task= 0; for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count; n_idx += 1) { DMN_Trap *trap = n->v+n_idx; if(trap->flags != 0) { DMN_FlaggedTrapTask *task = 0; for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next) { if(dmn_handle_match(t->process, trap->process)) { task = t; break; } } if(task == 0) { task = push_array(scratch.arena, DMN_FlaggedTrapTask, 1); SLLQueuePush(first_flagged_trap_task, last_flagged_trap_task, task); task->process = trap->process; } B32 already_in_task = 0; for(DMN_TrapChunkNode *n = task->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count; n_idx += 1) { if(n->v[n_idx].id == trap->id) { already_in_task = 1; goto end_look_for_existing_trap_in_task; } } } end_look_for_existing_trap_in_task:; if(!already_in_task) { dmn_trap_chunk_list_push(scratch.arena, &task->traps, 8, trap); } } } } ////////////////////////// //- rjf: write all debug register states, for flagged-traps // ProfScope("write all debug register states, for flagged-traps") { //- rjf: for each flagged trap task, iterate all threads in the // associated process, and prepare debug registers accordingly for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next) { DMN_Handle process = t->process; DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); for(DMN_W32_Entity *child = process_entity->first; child != &dmn_w32_entity_nil; child = child->next) { if(child->kind == DMN_W32_EntityKind_Thread) { switch(child->arch) { default:{}break; //- rjf: x64 case Arch_x64: { REGS_RegBlockX64 regs = {0}; dmn_w32_thread_read_reg_block(child->arch, child->handle, ®s); { U64 trap_idx = 0; for(DMN_TrapChunkNode *n = t->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count && trap_idx < 4; n_idx += 1, trap_idx += 1) { DMN_Trap *trap = &n->v[n_idx]; REGS_Reg64 *addr_reg = ®s.dr0; switch(trap_idx) { default:{}break; case 0:{addr_reg = ®s.dr0;}break; case 1:{addr_reg = ®s.dr1;}break; case 2:{addr_reg = ®s.dr2;}break; case 3:{addr_reg = ®s.dr3;}break; } addr_reg->u64 = trap->vaddr; regs.dr7.u64 |= bit9|bit10|bit11; regs.dr7.u64 |= (1ull << (trap_idx*2)); // NOTE(rjf): global-enable regs.dr7.u64 |= (1ull << (trap_idx*2+1)); regs.dr7.u64 &= ~((U64)(bit17|bit18|bit19|bit20) << (trap_idx*4)); regs.dr7.u64 &= ~((U64)(bit15|bit16)); switch(trap->flags) { case DMN_TrapFlag_BreakOnExecute: default:{}break; case DMN_TrapFlag_BreakOnWrite: case DMN_TrapFlag_BreakOnWrite|DMN_TrapFlag_BreakOnExecute: { regs.dr7.u64 |= ((U64)bit17) << (trap_idx*4); }break; case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite|DMN_TrapFlag_BreakOnExecute: case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite: case DMN_TrapFlag_BreakOnRead: { regs.dr7.u64 |= (((U64)bit17) << (trap_idx*4)); regs.dr7.u64 |= (((U64)bit18) << (trap_idx*4)); }break; } switch(trap->size) { case 1: default:{}break; case 2: { regs.dr7.u64 |= (((U64)bit19) << (trap_idx*4)); }break; case 4: { regs.dr7.u64 |= (((U64)bit19) << (trap_idx*4)); regs.dr7.u64 |= (((U64)bit20) << (trap_idx*4)); }break; case 8: { regs.dr7.u64 |= (((U64)bit20) << (trap_idx*4)); }break; } } } } dmn_w32_thread_write_reg_block(child->arch, child->handle, ®s); }break; } } } } } ////////////////////////// //- rjf: produce list of threads which will run // DMN_W32_EntityNode *first_run_thread = 0; DMN_W32_EntityNode *last_run_thread = 0; ProfScope("produce list of threads which will run") { //- rjf: scan all processes for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; process != &dmn_w32_entity_nil; process = process->next) { if(process->kind != DMN_W32_EntityKind_Process) {continue;} //- rjf: determine if this process is frozen B32 process_is_frozen = 0; if(ctrls->run_entities_are_processes) { for(U64 idx = 0; idx < ctrls->run_entity_count; idx += 1) { if(dmn_handle_match(ctrls->run_entities[idx], dmn_w32_handle_from_entity(process))) { process_is_frozen = 1; break; } } } //- rjf: scan all threads in this process for(DMN_W32_Entity *thread = process->first; thread != &dmn_w32_entity_nil; thread = thread->next) { if(thread->kind != DMN_W32_EntityKind_Thread) {continue;} //- rjf: determine if this thread is frozen B32 is_frozen = 0; { // rjf: single-step? freeze if not the single-step thread. if(!dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread)) { is_frozen = !dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->single_step_thread); } // rjf: not single-stepping? determine based on run controls freezing info else { if(ctrls->run_entities_are_processes) { is_frozen = process_is_frozen; } else for(U64 idx = 0; idx < ctrls->run_entity_count; idx += 1) { if(dmn_handle_match(ctrls->run_entities[idx], dmn_w32_handle_from_entity(thread))) { is_frozen = 1; break; } } if(ctrls->run_entities_are_unfrozen) { is_frozen ^= 1; } } } //- rjf: disregard all other rules if this is the halter thread if(dmn_w32_shared->halter_tid == thread->id) { is_frozen = 0; } //- rjf: add to list if(!is_frozen) { DMN_W32_EntityNode *n = push_array(scratch.arena, DMN_W32_EntityNode, 1); n->v = thread; SLLQueuePush(first_run_thread, last_run_thread, n); } } } } ////////////////////////// //- rjf: loop, consume win32 debug events until we produce the relevant demon events // B32 priority_mode = !dmn_handle_match(dmn_handle_zero(), ctrls->priority_thread); B32 did_priority_mode = priority_mode; B32 do_threads_resume = 1; DMN_W32_EntityNode *first_ran_thread = 0; DMN_W32_EntityNode *last_ran_thread = 0; U64 begin_time = os_now_microseconds(); String8List debug_strings = {0}; DMN_Event *debug_strings_event = 0; for(B32 keep_going = 1; keep_going;) { keep_going = 0; //////////////////////// //- rjf: resume threads that we want to run // // if priority mode? => first, just resume priority thread // if not? => resume all non-priority threads // if(do_threads_resume) ProfScope("resume threads that we want to run") { do_threads_resume = 0; for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next) { DMN_W32_Entity *thread = n->v; B32 thread_is_priority = dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->priority_thread); if((priority_mode && !thread_is_priority) || (!priority_mode && did_priority_mode && thread_is_priority)) { continue; } DWORD resume_result = ResumeThread(thread->handle); DMN_W32_EntityNode *n = push_array(scratch.arena, DMN_W32_EntityNode, 1); SLLQueuePush(first_ran_thread, last_ran_thread, n); n->v = thread; switch(resume_result) { case 0xffffffffu: { // TODO(rjf): error - unknown cause. need to do GetLastError, FormatMessage }break; default: { DWORD desired_counter = 0; DWORD current_counter = resume_result - 1; if(current_counter != desired_counter) { // NOTE(rjf): Warning. The user has manually suspended this thread, // so even though from Demon's perspective it thinks this thread // should run, it will not, because the user has manually called // SuspendThread or used CREATE_SUSPENDED or whatever. } }break; } if(priority_mode && thread_is_priority) { break; } } } //////////////////////// //- rjf: choose win32 resume code // DWORD resume_code = DBG_CONTINUE; { if(dmn_w32_shared->exception_not_handled && !ctrls->ignore_previous_exception) { log_infof("using DBG_EXCEPTION_NOT_HANDLED\n"); resume_code = DBG_EXCEPTION_NOT_HANDLED; } else { log_infof("using DBG_CONTINUE\n"); } dmn_w32_shared->exception_not_handled = 0; } //////////////////////// //- rjf: inform windows that we're resuming, run, & obtain next debug event // DEBUG_EVENT evt = {0}; B32 evt_good = 0; ProfScope("inform windows that we're resuming, run, & obtain next debug event") { B32 resume_good = 1; if(dmn_w32_shared->resume_needed) { dmn_w32_shared->resume_needed = 0; resume_good = !!ContinueDebugEvent(dmn_w32_shared->resume_pid, dmn_w32_shared->resume_tid, resume_code); DWORD error = GetLastError(); dmn_w32_shared->resume_needed = 0; dmn_w32_shared->resume_tid = 0; dmn_w32_shared->resume_pid = 0; } if(resume_good) { DWORD wait_ms = 100; if(priority_mode) { wait_ms = 30; } evt_good = !!WaitForDebugEvent(&evt, wait_ms); if(evt_good) { dmn_w32_shared->resume_needed = 1; dmn_w32_shared->resume_pid = evt.dwProcessId; dmn_w32_shared->resume_tid = evt.dwThreadId; } else { DWORD err = GetLastError(); (void)err; keep_going = 1; } if(priority_mode) { priority_mode = 0; do_threads_resume = 1; } } } //////////////////////// //- rjf: process the new event // if(evt_good) ProfScope("process the new event") { switch(evt.dwDebugEventCode) { ////////////////////// //- rjf: process was created // case CREATE_PROCESS_DEBUG_EVENT: { // rjf: zero out "process pending" state dmn_w32_shared->new_process_pending = 0; // rjf: unpack event HANDLE process_handle = evt.u.CreateProcessInfo.hProcess; HANDLE thread_handle = evt.u.CreateProcessInfo.hThread; HANDLE module_handle = evt.u.CreateProcessInfo.hFile; U64 tls_base = (U64)evt.u.CreateProcessInfo.lpThreadLocalBase; U64 module_base = (U64)evt.u.CreateProcessInfo.lpBaseOfImage; U64 module_name_vaddr = (U64)evt.u.CreateProcessInfo.lpImageName; B32 module_name_is_unicode = (evt.u.CreateProcessInfo.fUnicode != 0); DMN_W32_ImageInfo image_info = dmn_w32_image_info_from_process_base_vaddr(process_handle, module_base); // rjf: create entities (thread/module are implied for initial - they are not reported by win32) DMN_W32_Entity *process = dmn_w32_entity_alloc(dmn_w32_shared->entities_base, DMN_W32_EntityKind_Process, evt.dwProcessId); DMN_W32_Entity *thread = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Thread, evt.dwThreadId); DMN_W32_Entity *module = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Module, module_base); { process->handle = process_handle; process->arch = image_info.arch; thread->handle = thread_handle; thread->arch = image_info.arch; thread->thread.thread_local_base = tls_base; module->handle = module_handle; module->module.vaddr_range = r1u64(module_base, image_info.size); module->module.is_main = 1; module->module.address_of_name_pointer = module_name_vaddr; module->module.name_is_unicode = module_name_is_unicode; } // rjf: put thread into suspended state, so it matches expected initial state SuspendThread(thread_handle); // rjf: set up per-process injected code (to run halter threads on & // generate debug events) { U8 injection_code[DMN_W32_INJECTED_CODE_SIZE]; MemorySet(injection_code, 0xCC, DMN_W32_INJECTED_CODE_SIZE); injection_code[0] = 0xC3; U64 injection_size = DMN_W32_INJECTED_CODE_SIZE + sizeof(DMN_W32_InjectedBreak); U64 injection_address = (U64)VirtualAllocEx(process_handle, 0, injection_size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE); dmn_w32_process_write(process_handle, r1u64(injection_address, injection_address+sizeof(injection_code)), injection_code); process->proc.injection_address = injection_address; } // rjf: generate events { // rjf: create process { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_CreateProcess; e->process = dmn_w32_handle_from_entity(process); e->arch = image_info.arch; e->code = evt.dwProcessId; } // rjf: create thread { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_CreateThread; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); e->arch = image_info.arch; e->code = evt.dwThreadId; } // rjf: load module { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_LoadModule; e->process = dmn_w32_handle_from_entity(process); e->module = dmn_w32_handle_from_entity(module); e->arch = image_info.arch; e->address = module_base; e->size = image_info.size; e->string = dmn_w32_full_path_from_module(arena, module); } } }break; ////////////////////// //- rjf: process exited // case EXIT_PROCESS_DEBUG_EVENT: { DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); // rjf: if this was the process we were going to resume, then we will // just not resume, and wait for another debug event if(evt.dwProcessId == dmn_w32_shared->resume_pid) { dmn_w32_shared->resume_needed = 0; dmn_w32_shared->resume_tid = 0; dmn_w32_shared->resume_pid = 0; } // rjf: generate events for children for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next) { switch(child->kind) { default:{}break; case DMN_W32_EntityKind_Thread: { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_ExitThread; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(child); }break; case DMN_W32_EntityKind_Module: { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_UnloadModule; e->process = dmn_w32_handle_from_entity(process); e->module = dmn_w32_handle_from_entity(child); e->string = dmn_w32_full_path_from_module(arena, child); }break; } } // rjf: generate event for process { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_ExitProcess; e->process = dmn_w32_handle_from_entity(process); e->code = evt.u.ExitProcess.dwExitCode; } // rjf: release entity storage dmn_w32_entity_release(process); // rjf: detach DebugActiveProcessStop(evt.dwProcessId); }break; ////////////////////// //- rjf: thread was created // case CREATE_THREAD_DEBUG_EVENT: { DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); // rjf: create thread entity DMN_W32_Entity *thread = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Thread, evt.dwThreadId); { thread->handle = evt.u.CreateThread.hThread; thread->arch = process->arch; thread->thread.thread_local_base = (U64)evt.u.CreateThread.lpThreadLocalBase; } // rjf: suspend thread immediately upon creation, to match with expected suspension state DWORD sus_result = SuspendThread(thread->handle); (void)sus_result; // rjf: unpack thread name String8 thread_name = {0}; if(dmn_w32_GetThreadDescription != 0) { WCHAR *thread_name_w = 0; HRESULT hr = dmn_w32_GetThreadDescription(thread->handle, &thread_name_w); if(SUCCEEDED(hr)) { thread_name = str8_from_16(arena, str16_cstring((U16 *)thread_name_w)); LocalFree(thread_name_w); } } // rjf: determine if this is a "halter thread" - the threads we spawn to halt processes B32 is_halter = (evt.dwThreadId == dmn_w32_shared->halter_tid); // rjf: generate events for non-halter threads if(!is_halter) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_CreateThread; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); e->arch = thread->arch; e->code = evt.dwThreadId; e->string = thread_name; } }break; ////////////////////// //- rjf: thread exited // case EXIT_THREAD_DEBUG_EVENT: { DMN_W32_Entity *thread = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Thread, evt.dwThreadId); DMN_W32_Entity *process = thread->parent; // rjf: determine if this is the halter thread B32 is_halter = (evt.dwThreadId == dmn_w32_shared->halter_tid); // rjf: generate a halt event if this thread is the halter if(is_halter) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_Halt; dmn_w32_shared->halter_process = dmn_handle_zero(); dmn_w32_shared->halter_tid = 0; keep_going = 0; } // rjf: if this thread is *not* the halter, then generate a regular exit-thread event if(!is_halter) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_ExitThread; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); e->code = evt.u.ExitThread.dwExitCode; } // rjf: release entity storage dmn_w32_entity_release(thread); }break; ////////////////////// //- rjf: DLL was loaded // case LOAD_DLL_DEBUG_EVENT: { DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); // rjf: extract image info U64 module_base = (U64)evt.u.LoadDll.lpBaseOfDll; DMN_W32_ImageInfo image_info = dmn_w32_image_info_from_process_base_vaddr(process->handle, module_base); // rjf: create module entity DMN_W32_Entity *module = dmn_w32_entity_alloc(process, DMN_W32_EntityKind_Module, module_base); { module->handle = evt.u.LoadDll.hFile; module->arch = image_info.arch; module->module.vaddr_range = r1u64(module_base, module_base+image_info.size); module->module.address_of_name_pointer = (U64)evt.u.LoadDll.lpImageName; module->module.name_is_unicode = (evt.u.LoadDll.fUnicode != 0); } // rjf: generate event { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_LoadModule; e->process = dmn_w32_handle_from_entity(process); e->module = dmn_w32_handle_from_entity(module); e->arch = module->arch; e->address = module_base; e->size = image_info.size; e->string = dmn_w32_full_path_from_module(arena, module); } }break; ////////////////////// //- rjf: DLL was unloaded // case UNLOAD_DLL_DEBUG_EVENT: { U64 module_base = (U64)evt.u.UnloadDll.lpBaseOfDll; DMN_W32_Entity *module = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Module, module_base); DMN_W32_Entity *process = module->parent; // rjf: generate event { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_UnloadModule; e->process = dmn_w32_handle_from_entity(process); e->module = dmn_w32_handle_from_entity(module); e->string = dmn_w32_full_path_from_module(arena, module); } // rjf: release entity storage dmn_w32_entity_release(module); }break; ////////////////////// //- rjf: exception was hit // case EXCEPTION_DEBUG_EVENT: { //- NOTE(rjf): Notes on multithreaded breakpoint events // (2021/11/1): // // When many threads are simultaneously running, multiple threads // may hit a trap "at the same time". When this happens there will be // multiple events in an internal queue that we cannot see. If there // is another event in the queue we will not see it until we call // ContinueDebugEvent again, in a subsequent call to demon_os_run. // // When we get a trap event, the instruction pointer stored // in the event will have the address of the int 3 instruction that // was hit. Our RIP register, however, will be one byte past that. // So, to get the behavior we want, we need to set the RIP register // back to the address of the int 3. // // To deal with the fact that we may get breakpoint events later that // were actually from this run what we do is: // // #1. If we get a trap event, and it corresponds to a user submitted // trap, then we treat it is a breakpoint event. // #2. If we get a trap event, and it does NOT correspond to a user // trap in this call: // #A. If the actual unmodified instruction byte is NOT an int 3, // then this is a queued event from a previous run that is no // longer applicable and we skip it. // #B. If the actual unmodified instruction is an int 3, then this // becomes a trap event and we do not reset RIP. //- NOTE(rjf): Further notes on MULTITHREADED STEPPING ACCESS VIOLATION // EVENTS! @rjf @rjf @rjf // (2024/05/29): // // Just adding another comment here to document that the above long // comment went completely unnoticed by me during a pass over demon, // and I had removed the proper rollback stuff here without reading // the above comment. So this comment just serves to make that // original comment even heftier. //- NOTE(rjf): The exception record struct has a 32-bit version and a // 64-bit version. We only currently handle the 64-bit version. //- rjf: unpack DMN_W32_Entity *thread = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Thread, evt.dwThreadId); DMN_W32_Entity *process = thread->parent; EXCEPTION_DEBUG_INFO *edi = &evt.u.Exception; EXCEPTION_RECORD *exception = &edi->ExceptionRecord; U64 instruction_pointer = (U64)exception->ExceptionAddress; //- rjf: determine if this is the first breakpoint in a process // (breakpoint notifying us that the debugger is attached) B32 first_bp = 0; if(!process->proc.did_first_bp && exception->ExceptionCode == DMN_W32_EXCEPTION_BREAKPOINT) { process->proc.did_first_bp = 1; first_bp = 1; } //- rjf: determine if this exception is a trap B32 is_trap = (!first_bp && (exception->ExceptionCode == DMN_W32_EXCEPTION_BREAKPOINT || exception->ExceptionCode == DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN)); //- rjf: check if this trap is a usage-code-specified trap or something else B32 hit_user_trap = 0; U64 user_trap_id = 0; if(is_trap) { for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next) { for(U64 idx = 0; idx < n->count; idx += 1) { if(dmn_handle_match(n->v[idx].process, dmn_w32_handle_from_entity(process)) && n->v[idx].vaddr == instruction_pointer) { hit_user_trap = 1; user_trap_id = n->v[idx].id; break; } } } } //- rjf: check if trap is explicit in the actual code memory B32 hit_explicit_trap = 0; if(is_trap && !hit_user_trap) { U8 instruction_byte = 0; if(dmn_w32_process_read_struct(process->handle, instruction_pointer, &instruction_byte)) { hit_explicit_trap = (instruction_byte == 0xCC || instruction_byte == 0xCD); } } //- rjf: determine whether to roll back instruction pointer B32 should_do_rollback = (hit_user_trap || (is_trap && !hit_explicit_trap)); //- rjf: roll back thread's instruction pointer if(should_do_rollback) ProfScope("roll back thread's instruction pointer") { switch(thread->arch) { //- rjf: default, general path default: { Temp temp = temp_begin(scratch.arena); U64 regs_block_size = regs_block_size_from_arch(thread->arch); void *regs_block = push_array(scratch.arena, U8, regs_block_size); if(dmn_w32_thread_read_reg_block(thread->arch, thread->handle, regs_block)) { regs_arch_block_write_rip(thread->arch, regs_block, instruction_pointer); dmn_w32_thread_write_reg_block(thread->arch, thread->handle, regs_block); } temp_end(temp); }break; //- rjf: x64 (fastpath) case Arch_x64: { CONTEXT *ctx = 0; U32 ctx_flags = DMN_W32_CTX_X64|DMN_W32_CTX_INTEL_CONTROL; DWORD size = 0; InitializeContext(0, ctx_flags, 0, &size); if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { void *ctx_memory = push_array(scratch.arena, U8, size); if(!InitializeContext(ctx_memory, ctx_flags, &ctx, &size)) { ctx = 0; } } if(!GetThreadContext(thread->handle, ctx)) { ctx = 0; } if(ctx != 0) { U64 rip = ctx->Rip; U64 new_rip = instruction_pointer; ctx->Rip = new_rip; SetThreadContext(thread->handle, ctx); } }break; } } //- rjf: not a user trap, not an explicit trap, then it's a trap that // this thread hit previously but has since skipped B32 hit_previous_trap = (is_trap && !hit_user_trap && !hit_explicit_trap); //- rjf: determine whether to skip this event B32 skip_event = (hit_previous_trap); //- rjf: generate event if(!skip_event) { // rjf: fill top-level info DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_Exception; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); e->code = exception->ExceptionCode; e->flags = exception->ExceptionFlags; e->instruction_pointer = (U64)exception->ExceptionAddress; e->user_data = user_trap_id; //- rjf: fill according to exception code switch(exception->ExceptionCode) { //- rjf: fill breakpoint event info case DMN_W32_EXCEPTION_BREAKPOINT: { DMN_EventKind report_event_kind = DMN_EventKind_Trap; if(first_bp) { report_event_kind = DMN_EventKind_HandshakeComplete; } else if(hit_user_trap) { report_event_kind = DMN_EventKind_Breakpoint; } e->kind = report_event_kind; }break; //- rjf: fill stack buffer overrun event info case DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN: { e->kind = DMN_EventKind_Trap; if(exception->ExceptionInformation[0] == DMN_W32_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS) { // TODO(rjf): this is a shadow stack violation - this can imply that the spoof was hit. // need to handle this correctly in the ctrl layer when stepping w/ a spoof set. // // @shadow_stack_step } }break; //- rjf: fill single-step event info case DMN_W32_EXCEPTION_SINGLE_STEP: { e->kind = DMN_EventKind_SingleStep; // NOTE(rjf): data breakpoints are reported via single-steps // over the instructions which caused the breakpoint to be // hit - so if we have data breakpoints set, we need to // check this thread's debug registers, to determine if this // is a regular single-step or a data breakpoint hit. { // rjf: first determine the flagged trap index U64 flagged_trap_idx = 0; switch(thread->arch) { default:{NotImplemented;}break; case Arch_x64: { REGS_RegBlockX64 regs = {0}; dmn_w32_thread_read_reg_block(thread->arch, thread->handle, ®s); if(regs.dr6.u64 & 0xF) { e->kind = DMN_EventKind_Breakpoint; if(0){} else if(regs.dr7.u64 & (1ull<<0) && regs.dr6.u64 & (1ull<<0)) { flagged_trap_idx = 0; e->address = regs.dr0.u64; } else if(regs.dr7.u64 & (1ull<<2) && regs.dr6.u64 & (1ull<<1)) { flagged_trap_idx = 1; e->address = regs.dr1.u64; } else if(regs.dr7.u64 & (1ull<<4) && regs.dr6.u64 & (1ull<<2)) { flagged_trap_idx = 2; e->address = regs.dr2.u64; } else if(regs.dr7.u64 & (1ull<<8) && regs.dr6.u64 & (1ull<<3)) { flagged_trap_idx = 3; e->address = regs.dr3.u64; } } }break; } // rjf: find the flagged trap task for this thread's process DMN_W32_Entity *process = thread->parent; DMN_FlaggedTrapTask *task = 0; for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next) { if(dmn_handle_match(t->process, dmn_w32_handle_from_entity(process))) { task = t; break; } } // rjf: find the trap DMN_Trap *trap = 0; if(task != 0) { U64 trap_idx = 0; for(DMN_TrapChunkNode *n = task->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1) { if(trap_idx == flagged_trap_idx) { trap = &n->v[n_idx]; goto break_search_for_flagged_trap; } } } break_search_for_flagged_trap:; } // rjf: fill event based on trap if(trap != 0) { e->user_data = trap->id; } } }break; //- rjf: fill throw info case DMN_W32_EXCEPTION_THROW: { U64 exception_sp = 0; U64 exception_ip = 0; if(exception->NumberParameters >= 3) { exception_sp = (U64)exception->ExceptionInformation[1]; exception_ip = (U64)exception->ExceptionInformation[2]; } e->stack_pointer = exception_sp; e->exception_kind = DMN_ExceptionKind_CppThrow; e->exception_repeated = (edi->dwFirstChance == 0); dmn_w32_shared->exception_not_handled = (edi->dwFirstChance != 0); }break; //- rjf: fill access violation info case DMN_W32_EXCEPTION_ACCESS_VIOLATION: case DMN_W32_EXCEPTION_IN_PAGE_ERROR: { U64 exception_address = 0; DMN_ExceptionKind exception_kind = DMN_ExceptionKind_Null; if(exception->NumberParameters >= 2) { switch(exception->ExceptionInformation[0]) { case 0: exception_kind = DMN_ExceptionKind_MemoryRead; break; case 1: exception_kind = DMN_ExceptionKind_MemoryWrite; break; case 8: exception_kind = DMN_ExceptionKind_MemoryExecute; break; } exception_address = exception->ExceptionInformation[1]; } e->address = exception_address; e->exception_kind = exception_kind; e->exception_repeated = (edi->dwFirstChance == 0); dmn_w32_shared->exception_not_handled = (edi->dwFirstChance != 0); }break; //- rjf: fill set-thread-name info case DMN_W32_EXCEPTION_SET_THREAD_NAME: if(exception->NumberParameters >= 2) { U64 thread_name_address = exception->ExceptionInformation[1]; DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); String8List thread_name_strings = {0}; { U64 read_addr = thread_name_address; U64 total_string_size = 0; for(;total_string_size < KB(4);) { U8 *buffer = push_array(scratch.arena, U8, 256); B32 good_read = dmn_w32_process_read(process->handle, r1u64(read_addr, read_addr+256), buffer); if(good_read) { U64 size = 256; for(U64 idx = 0; idx < 256; idx += 1) { if(buffer[idx] == 0) { size = idx; break; } } String8 string_part = str8(buffer, size); str8_list_push(scratch.arena, &thread_name_strings, string_part); total_string_size += size; read_addr += size; if(size < 256) { break; } } else { break; } } } e->kind = DMN_EventKind_SetThreadName; e->string = str8_list_join(arena, &thread_name_strings, 0); if(exception->NumberParameters > 2) { e->code = exception->ExceptionInformation[2]; } }break; //- rjf: fill set-thread-color info case DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR: { e->kind = DMN_EventKind_SetThreadColor; e->code = exception->ExceptionInformation[0]; e->user_data = exception->ExceptionInformation[1]; }break; //- rjf: fill set-data-breakpoint info case DMN_W32_EXCEPTION_RADDBG_SET_BREAKPOINT: { U64 vaddr = exception->ExceptionInformation[0]; U64 size = exception->ExceptionInformation[1]; U64 read = exception->ExceptionInformation[2]; U64 write = exception->ExceptionInformation[3]; U64 exec = exception->ExceptionInformation[4]; U64 set = exception->ExceptionInformation[5]; e->kind = set ? DMN_EventKind_SetBreakpoint : DMN_EventKind_UnsetBreakpoint; e->address = vaddr; e->size = size; if(read) { e->flags |= DMN_TrapFlag_BreakOnRead; } if(write) { e->flags |= DMN_TrapFlag_BreakOnWrite; } if(exec) { e->flags |= DMN_TrapFlag_BreakOnExecute; } }break; //- rjf: fill set-vaddr-range-note info case DMN_W32_EXCEPTION_RADDBG_SET_VADDR_RANGE_NOTE: { U64 vaddr = exception->ExceptionInformation[0]; U64 size = exception->ExceptionInformation[1]; U64 name_vaddr = exception->ExceptionInformation[2]; U64 name_size = exception->ExceptionInformation[3]; U8 *name_buffer = push_array(arena, U8, name_size); dmn_w32_process_read(process->handle, r1u64(name_vaddr, name_vaddr+name_size), name_buffer), e->kind = DMN_EventKind_SetVAddrRangeNote; e->address = vaddr; e->size = size; e->string = str8(name_buffer, name_size); }break; //- rjf: unhandled exception case default: { e->exception_repeated = (edi->dwFirstChance == 0); dmn_w32_shared->exception_not_handled = (edi->dwFirstChance != 0); }break; } } }break; ////////////////////// //- rjf: output debug string was gathered // case OUTPUT_DEBUG_STRING_EVENT: { // rjf: unpack event DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); DMN_W32_Entity *thread = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Thread, evt.dwThreadId); U64 string_address = (U64)evt.u.DebugString.lpDebugStringData; U64 string_size = (U64)evt.u.DebugString.nDebugStringLength; // rjf: read memory U8 *buffer = push_array_no_zero(scratch.arena, U8, string_size + 1); dmn_w32_process_read(process->handle, r1u64(string_address, string_address+string_size), buffer); buffer[string_size] = 0; // rjf: extract into string String8 debug_string = str8(buffer, string_size); if(debug_string.size != 0 && buffer[string_size-1] == 0) { debug_string.size -= 1; } // rjf: make debug string event debug_strings_event = dmn_event_list_push(arena, &events); debug_strings_event->kind = DMN_EventKind_DebugString; // rjf: push into debug strings str8_list_push(scratch.arena, &debug_strings, debug_string); keep_going = 1; // rjf: exit loop, given sufficient amount of text if(debug_strings.total_size >= KB(4)) { keep_going = 0; } }break; ////////////////////// //- rjf: a "rip event" - a "system debugging error". // case RIP_EVENT: { DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId); DMN_W32_Entity *thread = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Thread, evt.dwThreadId); DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_Exception; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); }break; ////////////////////// //- rjf: default case - some kind of debugging event that we don't currently consume. // default: { NoOp; }break; } } //////////////////////// //- rjf: exit loop after a little while, so we keep pumping e.g. debug strings // if(os_now_microseconds() >= begin_time+100000 && debug_strings.total_size != 0) { keep_going = 0; } } //////////////////////// //- rjf: send out event for any remaining debug strings // if(debug_strings.total_size != 0 && debug_strings_event != 0) { String8 debug_strings_joined = str8_list_join(arena, &debug_strings, 0); debug_strings_event->string = debug_strings_joined; } //////////////////////// //- rjf: suspend threads which ran // ProfScope("suspend threads which ran") { for(DMN_W32_EntityNode *n = first_ran_thread; n != 0; n = n->next) { DMN_W32_Entity *thread = n->v; if(thread->kind != DMN_W32_EntityKind_Thread) { continue; } DWORD suspend_result = SuspendThread(thread->handle); switch(suspend_result) { case 0xffffffffu: { // TODO(rjf): error - unknown cause. need to do do GetLastError, FormatMessage // // NOTE(rjf): this can happen when the event is EXIT_THREAD_DEBUG_EVENT // or EXIT_PROCESS_DEBUG_EVENT. after such an event, SuspendThread // gives error code 5 (access denied). this has no adverse effects, but // if we want to start reporting errors we should take care to avoid // calling SuspendThread in that case. }break; default: { DWORD desired_counter = 1; DWORD current_counter = suspend_result + 1; if(current_counter != desired_counter) { // NOTE(rjf): Warning. We've suspended to something higher than 1. // In this case, it means the user probably created the thread in // a suspended state, or they called SuspendThread. } }break; } } } //////////////////////// //- rjf: gather new thread-names // ProfScope("gather new thread names") if(dmn_w32_GetThreadDescription != 0) { for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first; process != &dmn_w32_entity_nil; process = process->next) { if(process->kind != DMN_W32_EntityKind_Process) { continue; } for(DMN_W32_Entity *thread = process->first; thread != &dmn_w32_entity_nil; thread = thread->next) { if(thread->kind != DMN_W32_EntityKind_Thread) { continue; } if(thread->thread.last_name_hash == 0 || thread->thread.name_gather_time_us+1000000 <= os_now_microseconds()) { String8 name = {0}; { WCHAR *thread_name_w = 0; HRESULT hr = dmn_w32_GetThreadDescription(thread->handle, &thread_name_w); if(SUCCEEDED(hr)) { name = str8_from_16(scratch.arena, str16_cstring((U16 *)thread_name_w)); LocalFree(thread_name_w); } } U64 name_hash = dmn_w32_hash_from_string(name); if(name.size != 0 && name_hash != thread->thread.last_name_hash) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_SetThreadName; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(thread); e->string = push_str8_copy(arena, name); } thread->thread.name_gather_time_us = os_now_microseconds(); thread->thread.last_name_hash = name_hash; } } } } ////////////////////////// //- rjf: restore original memory at trap locations // ProfScope("restore original memory at trap locations") { U64 trap_idx = 0; for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next) { for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1) { DMN_Trap *trap = n->v+n_idx; if(trap->flags == 0) { U8 og_byte = trap_swap_bytes[trap_idx]; if(og_byte != 0xCC) { dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &og_byte); } } } } } ////////////////////////// //- rjf: clear all debug register states, for flagged-traps // ProfScope("clear all debug register states, for flagged-traps") { for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next) { DMN_Handle process = t->process; DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); for(DMN_W32_Entity *child = process_entity->first; child != &dmn_w32_entity_nil; child = child->next) { if(child->kind == DMN_W32_EntityKind_Thread) { switch(child->arch) { default:{}break; //- rjf: x64 case Arch_x64: { REGS_RegBlockX64 regs = {0}; dmn_w32_thread_read_reg_block(child->arch, child->handle, ®s); regs.dr7.u64 = 0; dmn_w32_thread_write_reg_block(child->arch, child->handle, ®s); }break; } } } } } ////////////////////////// //- rjf: unset single step bit // if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) ProfScope("unset single step bit") { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(ctrls->single_step_thread); Arch arch = thread->arch; switch(arch) { //- rjf: unimplemented win32/arch combos case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; //- rjf: x86/64 case Arch_x86: { REGS_RegBlockX86 regs = {0}; dmn_thread_read_reg_block(ctrls->single_step_thread, ®s); regs.eflags.u32 &= ~0x100; dmn_thread_write_reg_block(ctrls->single_step_thread, ®s); }break; case Arch_x64: { if(!GetThreadContext(thread->handle, single_step_thread_ctx)) { single_step_thread_ctx = 0; } if(single_step_thread_ctx != 0) { U64 rflags = single_step_thread_ctx->EFlags|0x2; U64 new_rflags = rflags & ~0x100; single_step_thread_ctx->EFlags = new_rflags; SetThreadContext(thread->handle, single_step_thread_ctx); } }break; } } scratch_end(scratch); }break; //////////////////////////// //- rjf: produce debug events from queued up detached processes // case DMN_W32_EventGenPath_DetachProcesses: { for(DMN_HandleNode *n = dmn_w32_shared->detach_processes.first; n != 0; n = n->next) { DMN_W32_Entity *process = dmn_w32_entity_from_handle(n->v); // rjf: push exit thread events for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next) { if(child->kind == DMN_W32_EntityKind_Thread) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_ExitThread; e->process = dmn_w32_handle_from_entity(process); e->thread = dmn_w32_handle_from_entity(child); } } // rjf: push unload module events for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next) { if(child->kind == DMN_W32_EntityKind_Module) { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_UnloadModule; e->process = dmn_w32_handle_from_entity(process); e->module = dmn_w32_handle_from_entity(child); e->string = dmn_w32_full_path_from_module(arena, child); } } // rjf: push exit process event { DMN_Event *e = dmn_event_list_push(arena, &events); e->kind = DMN_EventKind_ExitProcess; e->process = dmn_w32_handle_from_entity(process); } // rjf: free process dmn_w32_entity_release(process); } // rjf: reset queued up detached processes MemoryZeroStruct(&dmn_w32_shared->detach_processes); arena_clear(dmn_w32_shared->detach_arena); }break; } dmn_access_close(); return events; } //////////////////////////////// //~ rjf: @dmn_os_hooks Halting (Implemented Per-OS) internal void dmn_halt(U64 code, U64 user_data) { if(dmn_handle_match(dmn_handle_zero(), dmn_w32_shared->halter_process)) { DMN_W32_Entity *process = &dmn_w32_entity_nil; for(DMN_W32_Entity *entity = dmn_w32_shared->entities_base->first; entity != &dmn_w32_entity_nil; entity = entity->next) { if(entity->kind == DMN_W32_EntityKind_Process) { process = entity; break; } } if(process != &dmn_w32_entity_nil) { dmn_w32_shared->halter_process = dmn_w32_handle_from_entity(process); DMN_W32_InjectedBreak injection = {code, user_data}; U64 data_injection_address = process->proc.injection_address + DMN_W32_INJECTED_CODE_SIZE; dmn_w32_process_write_struct(process->handle, data_injection_address, &injection); dmn_w32_shared->halter_tid = dmn_w32_inject_thread(process->handle, process->proc.injection_address); } } } //////////////////////////////// //~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS) //- rjf: non-blocking-control-thread access barriers internal B32 dmn_access_open(void) { B32 result = 0; if(dmn_w32_ctrl_thread) { result = 1; } else { mutex_take(dmn_w32_shared->access_mutex); result = !dmn_w32_shared->access_run_state; } return result; } internal void dmn_access_close(void) { if(!dmn_w32_ctrl_thread) { mutex_drop(dmn_w32_shared->access_mutex); } } //- rjf: processes internal U64 dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size) { U64 result = 0; DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); result = (U64)VirtualAllocEx(process_entity->handle, (void *)vaddr, size, MEM_RESERVE, PAGE_READWRITE); if(result == 0) { result = (U64)VirtualAllocEx(process_entity->handle, 0, size, MEM_RESERVE, PAGE_READWRITE); } } return result; } internal void dmn_process_memory_commit(DMN_Handle process, U64 vaddr, U64 size) { DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); (U64)VirtualAllocEx(process_entity->handle, (void *)vaddr, size, MEM_COMMIT, PAGE_READWRITE); } } internal void dmn_process_memory_decommit(DMN_Handle process, U64 vaddr, U64 size) { DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); VirtualFreeEx(process_entity->handle, (void *)vaddr, size, MEM_DECOMMIT); } } internal void dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size) { DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); VirtualFreeEx(process_entity->handle, (void *)vaddr, 0, MEM_RELEASE); } } internal void dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags) { DMN_AccessScope { DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process); DWORD old_flags = 0; DWORD new_flags = PAGE_NOACCESS; switch(flags) { default:{}break; case OS_AccessFlag_Execute:{new_flags = PAGE_EXECUTE;}break; case OS_AccessFlag_Execute|OS_AccessFlag_Read:{new_flags = PAGE_EXECUTE_READ;}break; case OS_AccessFlag_Execute|OS_AccessFlag_Read|OS_AccessFlag_Write:{new_flags = PAGE_EXECUTE_READWRITE;}break; case OS_AccessFlag_Read:{new_flags = PAGE_READONLY;}break; case OS_AccessFlag_Read|OS_AccessFlag_Write:{new_flags = PAGE_READWRITE;}break; } VirtualProtectEx(process_entity->handle, (void *)vaddr, size, new_flags, &old_flags); } } internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst) { U64 result = 0; DMN_AccessScope { DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process); result = dmn_w32_process_read(entity->handle, range, dst); } return result; } internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src) { B32 result = 0; DMN_AccessScope { DMN_W32_Entity *entity = dmn_w32_entity_from_handle(process); result = dmn_w32_process_write(entity->handle, range, src); } return result; } //- rjf: threads internal Arch dmn_arch_from_thread(DMN_Handle handle) { Arch arch = Arch_Null; DMN_AccessScope { DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle); arch = entity->arch; } return arch; } internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle) { U64 result = 0; DMN_AccessScope { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); if(thread->kind == DMN_W32_EntityKind_Thread) { DMN_W32_Entity *process = thread->parent; U64 tlb = thread->thread.thread_local_base; switch(thread->arch) { case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; case Arch_x64: { U64 stack_base_addr = tlb + 0x8; dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+8), &result); }break; case Arch_x86: { U64 stack_base_addr = tlb + 0x4; dmn_w32_process_read(process->handle, r1u64(stack_base_addr, stack_base_addr+4), &result); }break; } } } return result; } internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle) { U64 result = 0; DMN_AccessScope { DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle); if(entity->kind == DMN_W32_EntityKind_Thread) { result = entity->thread.thread_local_base; switch(entity->arch) { case Arch_Null: case Arch_COUNT: {}break; case Arch_arm64: case Arch_arm32: {NotImplemented;}break; case Arch_x64: { result += 88; }break; case Arch_x86: { result += 44; }break; } } } return result; } internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block) { B32 result = 0; DMN_AccessScope { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); result = dmn_w32_thread_read_reg_block(thread->arch, thread->handle, reg_block); } return result; } internal B32 dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block) { B32 result = 0; DMN_AccessScope { DMN_W32_Entity *thread = dmn_w32_entity_from_handle(handle); result = dmn_w32_thread_write_reg_block(thread->arch, thread->handle, reg_block); } return result; } //- rjf: system process listing internal void dmn_process_iter_begin(DMN_ProcessIter *iter) { MemoryZeroStruct(iter); iter->v[0] = (U64)CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); } internal B32 dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out) { B32 result = 0; //- rjf: get the next process entry PROCESSENTRY32W process_entry = {sizeof(process_entry)}; HANDLE snapshot = (HANDLE)iter->v[0]; if(iter->v[1] == 0) { if(Process32FirstW(snapshot, &process_entry)) { result = 1; } } else { if(Process32NextW(snapshot, &process_entry)) { result = 1; } } //- rjf: increment counter iter->v[1] += 1; //- rjf: convert to process info if(result) { info_out->name = str8_from_16(arena, str16_cstring((U16*)process_entry.szExeFile)); info_out->pid = (U32)process_entry.th32ProcessID; } return result; } internal void dmn_process_iter_end(DMN_ProcessIter *iter) { CloseHandle((HANDLE)iter->v[0]); MemoryZeroStruct(iter); } ================================================ FILE: src/demon/win32/demon_core_win32.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_WIN32_H #define DEMON_CORE_WIN32_H //////////////////////////////// //~ rjf: Windows Includes #define WIN32_LEAN_AND_MEAN #include #include #include //////////////////////////////// //~ rjf: Win32 Exception Codes #define DMN_W32_EXCEPTION_BREAKPOINT 0x80000003u #define DMN_W32_EXCEPTION_SINGLE_STEP 0x80000004u #define DMN_W32_EXCEPTION_LONG_JUMP 0x80000026u #define DMN_W32_EXCEPTION_ACCESS_VIOLATION 0xC0000005u #define DMN_W32_EXCEPTION_ARRAY_BOUNDS_EXCEEDED 0xC000008Cu #define DMN_W32_EXCEPTION_DATA_TYPE_MISALIGNMENT 0x80000002u #define DMN_W32_EXCEPTION_GUARD_PAGE_VIOLATION 0x80000001u #define DMN_W32_EXCEPTION_FLT_DENORMAL_OPERAND 0xC000008Du #define DMN_W32_EXCEPTION_FLT_DEVIDE_BY_ZERO 0xC000008Eu #define DMN_W32_EXCEPTION_FLT_INEXACT_RESULT 0xC000008Fu #define DMN_W32_EXCEPTION_FLT_INVALID_OPERATION 0xC0000090u #define DMN_W32_EXCEPTION_FLT_OVERFLOW 0xC0000091u #define DMN_W32_EXCEPTION_FLT_STACK_CHECK 0xC0000092u #define DMN_W32_EXCEPTION_FLT_UNDERFLOW 0xC0000093u #define DMN_W32_EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094u #define DMN_W32_EXCEPTION_INT_OVERFLOW 0xC0000095u #define DMN_W32_EXCEPTION_PRIVILEGED_INSTRUCTION 0xC0000096u #define DMN_W32_EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001Du #define DMN_W32_EXCEPTION_IN_PAGE_ERROR 0xC0000006u #define DMN_W32_EXCEPTION_INVALID_DISPOSITION 0xC0000026u #define DMN_W32_EXCEPTION_NONCONTINUABLE 0xC0000025u #define DMN_W32_EXCEPTION_STACK_OVERFLOW 0xC00000FDu #define DMN_W32_EXCEPTION_INVALID_HANDLE 0xC0000008u #define DMN_W32_EXCEPTION_UNWIND_CONSOLIDATE 0x80000029u #define DMN_W32_EXCEPTION_DLL_NOT_FOUND 0xC0000135u #define DMN_W32_EXCEPTION_ORDINAL_NOT_FOUND 0xC0000138u #define DMN_W32_EXCEPTION_ENTRY_POINT_NOT_FOUND 0xC0000139u #define DMN_W32_EXCEPTION_DLL_INIT_FAILED 0xC0000142u #define DMN_W32_EXCEPTION_CONTROL_C_EXIT 0xC000013Au #define DMN_W32_EXCEPTION_FLT_MULTIPLE_FAULTS 0xC00002B4u #define DMN_W32_EXCEPTION_FLT_MULTIPLE_TRAPS 0xC00002B5u #define DMN_W32_EXCEPTION_NAT_CONSUMPTION 0xC00002C9u #define DMN_W32_EXCEPTION_HEAP_CORRUPTION 0xC0000374u #define DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN 0xC0000409u #define DMN_W32_EXCEPTION_INVALID_CRUNTIME_PARAM 0xC0000417u #define DMN_W32_EXCEPTION_ASSERT_FAILURE 0xC0000420u #define DMN_W32_EXCEPTION_NO_MEMORY 0xC0000017u #define DMN_W32_EXCEPTION_THROW 0xE06D7363u #define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u #define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u #define DMN_w32_EXCEPTION_CLR 0xE0434352u #define DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR 0x00524144u #define DMN_W32_EXCEPTION_RADDBG_SET_BREAKPOINT 0x00524145u #define DMN_W32_EXCEPTION_RADDBG_SET_VADDR_RANGE_NOTE 0x00524156u //////////////////////////////// //~ rjf: Win32 Exception ExceptionInformation Codes // // used as a subcode, apparently in all cases, for DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN. // need to somehow pipe this through & interpret it correctly in outer layers... @fastfail #define DMN_W32_FAST_FAIL_LEGACY_GS_VIOLATION 0 #define DMN_W32_FAST_FAIL_VTGUARD_CHECK_FAILURE 1 #define DMN_W32_FAST_FAIL_STACK_COOKIE_CHECK_FAILURE 2 #define DMN_W32_FAST_FAIL_CORRUPT_LIST_ENTRY 3 #define DMN_W32_FAST_FAIL_INCORRECT_STACK 4 #define DMN_W32_FAST_FAIL_INVALID_ARG 5 #define DMN_W32_FAST_FAIL_GS_COOKIE_INIT 6 #define DMN_W32_FAST_FAIL_FATAL_APP_EXIT 7 #define DMN_W32_FAST_FAIL_RANGE_CHECK_FAILURE 8 #define DMN_W32_FAST_FAIL_UNSAFE_REGISTRY_ACCESS 9 #define DMN_W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE 10 #define DMN_W32_FAST_FAIL_GUARD_WRITE_CHECK_FAILURE 11 #define DMN_W32_FAST_FAIL_INVALID_FIBER_SWITCH 12 #define DMN_W32_FAST_FAIL_INVALID_SET_OF_CONTEXT 13 #define DMN_W32_FAST_FAIL_INVALID_REFERENCE_COUNT 14 #define DMN_W32_FAST_FAIL_INVALID_JUMP_BUFFER 18 #define DMN_W32_FAST_FAIL_MRDATA_MODIFIED 19 #define DMN_W32_FAST_FAIL_CERTIFICATION_FAILURE 20 #define DMN_W32_FAST_FAIL_INVALID_EXCEPTION_CHAIN 21 #define DMN_W32_FAST_FAIL_CRYPTO_LIBRARY 22 #define DMN_W32_FAST_FAIL_INVALID_CALL_IN_DLL_CALLOUT 23 #define DMN_W32_FAST_FAIL_INVALID_IMAGE_BASE 24 #define DMN_W32_FAST_FAIL_DLOAD_PROTECTION_FAILURE 25 #define DMN_W32_FAST_FAIL_UNSAFE_EXTENSION_CALL 26 #define DMN_W32_FAST_FAIL_DEPRECATED_SERVICE_INVOKED 27 #define DMN_W32_FAST_FAIL_INVALID_BUFFER_ACCESS 28 #define DMN_W32_FAST_FAIL_INVALID_BALANCED_TREE 29 #define DMN_W32_FAST_FAIL_INVALID_NEXT_THREAD 30 #define DMN_W32_FAST_FAIL_GUARD_ICALL_CHECK_SUPPRESSED 31 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_APCS_DISABLED 32 #define DMN_W32_FAST_FAIL_INVALID_IDLE_STATE 33 #define DMN_W32_FAST_FAIL_MRDATA_PROTECTION_FAILURE 34 #define DMN_W32_FAST_FAIL_UNEXPECTED_HEAP_EXCEPTION 35 #define DMN_W32_FAST_FAIL_INVALID_LOCK_STATE 36 #define DMN_W32_FAST_FAIL_GUARD_JUMPTABLE 37 // Known to compiler, must retain value 37 #define DMN_W32_FAST_FAIL_INVALID_LONGJUMP_TARGET 38 #define DMN_W32_FAST_FAIL_INVALID_DISPATCH_CONTEXT 39 #define DMN_W32_FAST_FAIL_INVALID_THREAD 40 #define DMN_W32_FAST_FAIL_INVALID_SYSCALL_NUMBER 41 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_INVALID_FILE_OPERATION 42 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_LPAC_ACCESS_DENIED 43 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_GUARD_SS_FAILURE 44 #define DMN_W32_FAST_FAIL_LOADER_CONTINUITY_FAILURE 45 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_GUARD_EXPORT_SUPPRESSION_FAILURE 46 #define DMN_W32_FAST_FAIL_INVALID_CONTROL_STACK 47 #define DMN_W32_FAST_FAIL_SET_CONTEXT_DENIED 48 #define DMN_W32_FAST_FAIL_INVALID_IAT 49 #define DMN_W32_FAST_FAIL_HEAP_METADATA_CORRUPTION 50 #define DMN_W32_FAST_FAIL_PAYLOAD_RESTRICTION_VIOLATION 51 #define DMN_W32_FAST_FAIL_LOW_LABEL_ACCESS_DENIED 52 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_ENCLAVE_CALL_FAILURE 53 #define DMN_W32_FAST_FAIL_UNHANDLED_LSS_EXCEPTON 54 #define DMN_W32_FAST_FAIL_ADMINLESS_ACCESS_DENIED 55 // Telemetry, nonfatal #define DMN_W32_FAST_FAIL_UNEXPECTED_CALL 56 #define DMN_W32_FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS 57 #define DMN_W32_FAST_FAIL_UNEXPECTED_HOST_BEHAVIOR 58 #define DMN_W32_FAST_FAIL_FLAGS_CORRUPTION 59 #define DMN_W32_FAST_FAIL_VEH_CORRUPTION 60 #define DMN_W32_FAST_FAIL_ETW_CORRUPTION 61 #define DMN_W32_FAST_FAIL_RIO_ABORT 62 #define DMN_W32_FAST_FAIL_INVALID_PFN 63 #define DMN_W32_FAST_FAIL_GUARD_ICALL_CHECK_FAILURE_XFG 64 #define DMN_W32_FAST_FAIL_CAST_GUARD 65 // Known to compiler, must retain value 65 #define DMN_W32_FAST_FAIL_HOST_VISIBILITY_CHANGE 66 #define DMN_W32_FAST_FAIL_KERNEL_CET_SHADOW_STACK_ASSIST 67 #define DMN_W32_FAST_FAIL_PATCH_CALLBACK_FAILED 68 #define DMN_W32_FAST_FAIL_NTDLL_PATCH_FAILED 69 #define DMN_W32_FAST_FAIL_INVALID_FLS_DATA 70 #define DMN_W32_FAST_FAIL_INVALID_FAST_FAIL_CODE 0xFFFFFFFF //////////////////////////////// //~ rjf: Win32 Register Codes #define DMN_W32_CTX_X86 0x00010000 #define DMN_W32_CTX_X64 0x00100000 #define DMN_W32_CTX_INTEL_CONTROL 0x0001 // segss, rsp, segcs, rip, and rflags #define DMN_W32_CTX_INTEL_INTEGER 0x0002 // rax, rcx, rdx, rbx, rbp, rsi, rdi, and r8-r15 #define DMN_W32_CTX_INTEL_SEGMENTS 0x0004 // segds, seges, segfs, and seggs #define DMN_W32_CTX_INTEL_FLOATS 0x0008 // xmm0-xmm15 #define DMN_W32_CTX_INTEL_DEBUG 0x0010 // dr0-dr3 and dr6-dr7 #define DMN_W32_CTX_INTEL_EXTENDED 0x0020 #define DMN_W32_CTX_INTEL_XSTATE 0x0040 #define DMN_W32_CTX_X86_ALL (DMN_W32_CTX_X86 | \ DMN_W32_CTX_INTEL_CONTROL | DMN_W32_CTX_INTEL_INTEGER | \ DMN_W32_CTX_INTEL_SEGMENTS | DMN_W32_CTX_INTEL_DEBUG | \ DMN_W32_CTX_INTEL_EXTENDED) #define DMN_W32_CTX_X64_ALL (DMN_W32_CTX_X64 | \ DMN_W32_CTX_INTEL_CONTROL | DMN_W32_CTX_INTEL_INTEGER | \ DMN_W32_CTX_INTEL_SEGMENTS | DMN_W32_CTX_INTEL_FLOATS | \ DMN_W32_CTX_INTEL_DEBUG) //////////////////////////////// //~ rjf: Per-Entity State typedef enum DMN_W32_EntityKind { DMN_W32_EntityKind_Null, DMN_W32_EntityKind_Root, DMN_W32_EntityKind_Process, DMN_W32_EntityKind_Thread, DMN_W32_EntityKind_Module, DMN_W32_EntityKind_COUNT } DMN_W32_EntityKind; typedef struct DMN_W32_Entity DMN_W32_Entity; struct DMN_W32_Entity { DMN_W32_Entity *first; DMN_W32_Entity *last; DMN_W32_Entity *next; DMN_W32_Entity *prev; DMN_W32_Entity *parent; DMN_W32_EntityKind kind; U32 gen; U64 id; HANDLE handle; Arch arch; union { struct { U64 injection_address; B32 did_first_bp; } proc; struct { U64 thread_local_base; U64 last_name_hash; U64 name_gather_time_us; } thread; struct { Rng1U64 vaddr_range; U64 address_of_name_pointer; B32 is_main; B32 name_is_unicode; } module; }; }; typedef struct DMN_W32_EntityNode DMN_W32_EntityNode; struct DMN_W32_EntityNode { DMN_W32_EntityNode *next; DMN_W32_Entity *v; }; typedef struct DMN_W32_EntityIDHashNode DMN_W32_EntityIDHashNode; struct DMN_W32_EntityIDHashNode { DMN_W32_EntityIDHashNode *next; DMN_W32_EntityIDHashNode *prev; U64 id; DMN_W32_Entity *entity; }; typedef struct DMN_W32_EntityIDHashSlot DMN_W32_EntityIDHashSlot; struct DMN_W32_EntityIDHashSlot { DMN_W32_EntityIDHashNode *first; DMN_W32_EntityIDHashNode *last; }; //////////////////////////////// //~ rjf: Injection Types typedef struct DMN_W32_InjectedBreak DMN_W32_InjectedBreak; struct DMN_W32_InjectedBreak { U64 code; U64 user_data; }; #define DMN_W32_INJECTED_CODE_SIZE 32 //////////////////////////////// //~ rjf: Image Info Types typedef struct DMN_W32_ImageInfo DMN_W32_ImageInfo; struct DMN_W32_ImageInfo { Arch arch; U32 size; }; //////////////////////////////// //~ rjf: Dynamically-Loaded Win32 Function Types typedef HRESULT DMN_W32_GetThreadDescriptionFunctionType(HANDLE hThread, WCHAR **ppszThreadDescription); //////////////////////////////// //~ rjf: Shared State Bundle typedef struct DMN_W32_Shared DMN_W32_Shared; struct DMN_W32_Shared { // rjf: top-level info Arena *arena; String8List env_strings; // rjf: access locking mechanism Mutex access_mutex; B32 access_run_state; // rjf: detaching info Arena *detach_arena; DMN_HandleList detach_processes; // rjf: entity state Arena *entities_arena; DMN_W32_Entity *entities_base; DMN_W32_Entity *entities_first_free; U64 entities_count; DMN_W32_EntityIDHashSlot *entities_id_hash_slots; U64 entities_id_hash_slots_count; DMN_W32_EntityIDHashNode *entities_id_hash_node_free; // rjf: launch state B32 new_process_pending; // rjf: run results B32 resume_needed; U32 resume_pid; U32 resume_tid; B32 exception_not_handled; // rjf: halting info DMN_Handle halter_process; U32 halter_tid; }; //////////////////////////////// //~ rjf: Globals global DMN_W32_Shared *dmn_w32_shared = 0; global DMN_W32_Entity dmn_w32_entity_nil = {&dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil, &dmn_w32_entity_nil}; global DMN_W32_GetThreadDescriptionFunctionType *dmn_w32_GetThreadDescription = 0; thread_static B32 dmn_w32_ctrl_thread = 0; //////////////////////////////// //~ rjf: Basic Helpers internal U64 dmn_w32_hash_from_string(String8 string); internal U64 dmn_w32_hash_from_id(U64 id); //////////////////////////////// //~ rjf: Entity Helpers //- rjf: entity <-> handle internal DMN_Handle dmn_w32_handle_from_entity(DMN_W32_Entity *entity); internal DMN_W32_Entity *dmn_w32_entity_from_handle(DMN_Handle handle); //- rjf: entity allocation/deallocation internal DMN_W32_Entity *dmn_w32_entity_alloc(DMN_W32_Entity *parent, DMN_W32_EntityKind kind, U64 id); internal void dmn_w32_entity_release(DMN_W32_Entity *entity); //- rjf: kind*id -> entity internal DMN_W32_Entity *dmn_w32_entity_from_kind_id(DMN_W32_EntityKind kind, U64 id); //////////////////////////////// //~ rjf: Module Info Extraction internal String8 dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module); //////////////////////////////// //~ rjf: Win32-Level Process/Thread Reads/Writes //- rjf: processes internal U64 dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst); internal B32 dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src); internal String8 dmn_w32_read_memory_str(Arena *arena, HANDLE process_handle, U64 address); internal String16 dmn_w32_read_memory_str16(Arena *arena, HANDLE process_handle, U64 address); #define dmn_w32_process_read_struct(process, vaddr, ptr) dmn_w32_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_w32_process_write_struct(process, vaddr, ptr) dmn_w32_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) internal DMN_W32_ImageInfo dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr); //- rjf: threads internal U16 dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave); internal U16 dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw); internal B32 dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block); internal B32 dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block); //- rjf: remote thread injection internal DWORD dmn_w32_inject_thread(HANDLE process, U64 start_address); #endif // DEMON_CORE_WIN32_H ================================================ FILE: src/disasm/disasm.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xe34cd4ff //////////////////////////////// //~ rjf: Instruction Decoding/Disassembling Type Functions #if !defined(ZYDIS_H) #include "third_party/zydis/zydis.h" #include "third_party/zydis/zydis.c" #endif internal DASM_Inst dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, String8 code, DASM_Syntax syntax) { DASM_Inst inst = {0}; switch(arch) { default:{}break; //- rjf: x86/x64 disassembly case Arch_x86: case Arch_x64: { // rjf: determine zydis formatter style ZydisFormatterStyle style = ZYDIS_FORMATTER_STYLE_INTEL; switch(syntax) { default:{}break; case DASM_Syntax_Intel:{style = ZYDIS_FORMATTER_STYLE_INTEL;}break; case DASM_Syntax_ATT: {style = ZYDIS_FORMATTER_STYLE_ATT;}break; } // rjf: disassemble one instruction ZydisDisassembledInstruction zinst = {0}; ZyanStatus status = ZydisDisassemble(ZYDIS_MACHINE_MODE_LONG_64, vaddr, code.str, code.size, &zinst, style); // rjf: analyze DASM_InstFlags flags = 0; U64 jump_dest_vaddr = 0; { ZydisDecodedOperand *first_visible_op = (zinst.info.operand_count_visible > 0 ? &zinst.operands[0] : 0); ZydisDecodedOperand *first_op = (zinst.info.operand_count > 0 ? &zinst.operands[0] : 0); ZydisDecodedOperand *second_op = (zinst.info.operand_count > 1 ? &zinst.operands[1] : 0); if(first_visible_op != 0 && (first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM8 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM32 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM64 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16_32_64 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM32_32_64 || first_visible_op->encoding == ZYDIS_OPERAND_ENCODING_JIMM16_32_32)) { ZydisCalcAbsoluteAddress(&zinst.info, first_visible_op, vaddr, &jump_dest_vaddr); } if(first_op != 0 && second_op != 0 && first_op->type == ZYDIS_OPERAND_TYPE_REGISTER && (first_op->reg.value == ZYDIS_REGISTER_RSP || first_op->reg.value == ZYDIS_REGISTER_ESP || first_op->reg.value == ZYDIS_REGISTER_SP)) { flags |= DASM_InstFlag_ChangesStackPointer; if(second_op->type != ZYDIS_OPERAND_TYPE_IMMEDIATE) { flags |= DASM_InstFlag_ChangesStackPointerVariably; } } if(zinst.info.attributes & (ZYDIS_ATTRIB_HAS_REP| ZYDIS_ATTRIB_HAS_REPE| ZYDIS_ATTRIB_HAS_REPZ| ZYDIS_ATTRIB_HAS_REPNZ| ZYDIS_ATTRIB_HAS_REPNE)) { flags |= DASM_InstFlag_Repeats; } switch(zinst.info.mnemonic) { case ZYDIS_MNEMONIC_CALL: { flags |= DASM_InstFlag_Call; }break; case ZYDIS_MNEMONIC_JB: case ZYDIS_MNEMONIC_JBE: case ZYDIS_MNEMONIC_JCXZ: case ZYDIS_MNEMONIC_JECXZ: case ZYDIS_MNEMONIC_JKNZD: case ZYDIS_MNEMONIC_JKZD: case ZYDIS_MNEMONIC_JL: case ZYDIS_MNEMONIC_JLE: case ZYDIS_MNEMONIC_JNB: case ZYDIS_MNEMONIC_JNBE: case ZYDIS_MNEMONIC_JNL: case ZYDIS_MNEMONIC_JNLE: case ZYDIS_MNEMONIC_JNO: case ZYDIS_MNEMONIC_JNP: case ZYDIS_MNEMONIC_JNS: case ZYDIS_MNEMONIC_JNZ: case ZYDIS_MNEMONIC_JO: case ZYDIS_MNEMONIC_JP: case ZYDIS_MNEMONIC_JRCXZ: case ZYDIS_MNEMONIC_JS: case ZYDIS_MNEMONIC_JZ: case ZYDIS_MNEMONIC_LOOP: case ZYDIS_MNEMONIC_LOOPE: case ZYDIS_MNEMONIC_LOOPNE: { flags |= DASM_InstFlag_Branch; }break; case ZYDIS_MNEMONIC_JMP: { flags |= DASM_InstFlag_UnconditionalJump; }break; case ZYDIS_MNEMONIC_RET: { flags |= DASM_InstFlag_Return; }break; case ZYDIS_MNEMONIC_PUSH: case ZYDIS_MNEMONIC_POP: { flags |= DASM_InstFlag_ChangesStackPointer; }break; default: { flags |= DASM_InstFlag_NonFlow; }break; } } // rjf: convert { inst.flags = flags; inst.size = zinst.info.length; inst.string = push_str8_copy(arena, str8_cstring(zinst.text)); inst.jump_dest_vaddr = jump_dest_vaddr; } }break; } return inst; } //////////////////////////////// //~ rjf: Control Flow Analysis internal DASM_CtrlFlowInfo dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code) { Temp scratch = scratch_begin(&arena, 1); DASM_CtrlFlowInfo info = {0}; for(U64 offset = 0; offset < code.size;) { DASM_Inst inst = dasm_inst_from_code(scratch.arena, arch, vaddr+offset, str8_skip(code, offset), DASM_Syntax_Intel); U64 inst_vaddr = vaddr+offset; offset += inst.size; info.total_size += inst.size; if(inst.flags & exit_points_mask) { DASM_CtrlFlowPoint point = {0}; point.inst_flags = inst.flags; point.vaddr = inst_vaddr; point.jump_dest_vaddr = inst.jump_dest_vaddr; DASM_CtrlFlowPointNode *node = push_array(arena, DASM_CtrlFlowPointNode, 1); node->v = point; SLLQueuePush(info.exit_points.first, info.exit_points.last, node); info.exit_points.count += 1; } } scratch_end(scratch); return info; } //////////////////////////////// //~ rjf: Parameter Type Functions internal B32 dasm_params_match(DASM_Params *a, DASM_Params *b) { B32 result = (a->vaddr == b->vaddr && a->arch == b->arch && a->style_flags == b->style_flags && a->syntax == b->syntax && a->base_vaddr == b->base_vaddr && di_key_match(a->dbgi_key, b->dbgi_key)); return result; } //////////////////////////////// //~ rjf: Line Type Functions internal void dasm_line_chunk_list_push(Arena *arena, DASM_LineChunkList *list, U64 cap, DASM_Line *inst) { DASM_LineChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, DASM_LineChunkNode, 1); node->v = push_array_no_zero(arena, DASM_Line, cap); node->cap = cap; SLLQueuePush(list->first, list->last, node); list->node_count += 1; } MemoryCopyStruct(&node->v[node->count], inst); node->count += 1; list->line_count += 1; } internal DASM_LineArray dasm_line_array_from_chunk_list(Arena *arena, DASM_LineChunkList *list) { DASM_LineArray array = {0}; array.count = list->line_count; array.v = push_array_no_zero(arena, DASM_Line, array.count); U64 idx = 0; for(DASM_LineChunkNode *n = list->first; n != 0; n = n->next) { MemoryCopy(array.v+idx, n->v, sizeof(DASM_Line)*n->count); idx += n->count; } return array; } internal U64 dasm_line_array_idx_from_code_off__linear_scan(DASM_LineArray *array, U64 off) { U64 result = 0; for(U64 idx = 0; idx < array->count; idx += 1) { U64 next_off = (idx+1 < array->count ? array->v[idx+1].code_off : max_U64); if(array->v[idx].code_off <= off && off < next_off) { result = idx; if(!(array->v[idx].flags & DASM_LineFlag_Decorative)) { break; } } } return result; } internal U64 dasm_line_array_code_off_from_idx(DASM_LineArray *array, U64 idx) { U64 off = 0; if(idx < array->count) { off = array->v[idx].code_off; } return off; } //////////////////////////////// //~ rjf: Artifact Cache Hooks / Lookups typedef struct DASM_Artifact DASM_Artifact; struct DASM_Artifact { Arena *arena; DASM_Info info; U128 data_hash; }; internal AC_Artifact dasm_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { DASM_Artifact *artifact = 0; if(lane_idx() == 0) { Temp scratch = scratch_begin(0, 0); Access *access = access_open(); //- rjf: unpack key U128 hash = {0}; DASM_Params params = {0}; U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &hash); key_read_off += str8_deserial_read_struct(key, key_read_off, ¶ms); String8 data = c_data_from_hash(access, hash); //- rjf: get dbg info B32 stale = 0; RDI_Parsed *rdi = &rdi_parsed_nil; if(!di_key_match(params.dbgi_key, di_key_zero())) { rdi = di_rdi_from_key(access, params.dbgi_key, 0, 0); stale = (stale || (rdi == &rdi_parsed_nil)); } //- rjf: data * arch * addr * dbg -> decode artifacts DASM_LineChunkList line_list = {0}; String8List inst_strings = {0}; switch(params.arch) { default:{}break; //- rjf: x86/x64 decoding case Arch_x64: case Arch_x86: { // rjf: disassemble RDI_SourceFile *last_file = &rdi_nil_element_union.source_file; RDI_Line *last_line = 0; for(U64 off = 0; off < data.size;) { // rjf: disassemble one instruction DASM_Inst inst = dasm_inst_from_code(scratch.arena, params.arch, params.vaddr+off, str8_skip(data, off), params.syntax); if(inst.size == 0) { break; } // rjf: push strings derived from voff -> line info if(params.style_flags & (DASM_StyleFlag_SourceFilesNames|DASM_StyleFlag_SourceLines) && rdi != &rdi_parsed_nil) { U64 voff = (params.vaddr+off) - params.base_vaddr; U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); if(file != last_file) { if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx != 0 && file_normalized_full_path.size != 0) { String8 inst_string = push_str8f(scratch.arena, "> %S", file_normalized_full_path); DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst); str8_list_push(scratch.arena, &inst_strings, inst_string); } if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx == 0) { String8 inst_string = str8_lit(">"); DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst); str8_list_push(scratch.arena, &inst_strings, inst_string); } last_file = file; } if(line && line != last_line && file->normal_full_path_string_idx != 0 && params.style_flags & DASM_StyleFlag_SourceLines && file_normalized_full_path.size != 0) { FileProperties props = os_properties_from_file_path(file_normalized_full_path); if(props.modified != 0) { // TODO(rjf): need redirection path - this may map to a different path on the local machine, // need frontend to communicate path remapping info to this layer C_Key key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64), 0); TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path); U64 endt_us = max_U64; U128 hash = {0}; TXT_TextInfo text_info = txt_text_info_from_key_lang(access, key, lang_kind, &hash); stale = (stale || u128_match(hash, u128_zero())); if(0 < line->line_num && line->line_num < text_info.lines_count) { String8 data = c_data_from_hash(access, hash); String8 line_text = str8_skip_chop_whitespace(str8_substr(data, text_info.lines_ranges[line->line_num-1])); if(line_text.size != 0) { String8 inst_string = push_str8f(scratch.arena, "> %S", line_text); DASM_Line inst = {u32_from_u64_saturate(off), DASM_LineFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &inst); str8_list_push(scratch.arena, &inst_strings, inst_string); } } } last_line = line; } } } // rjf: push line String8 addr_part = {0}; if(params.style_flags & DASM_StyleFlag_Addresses) { addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &rdi_parsed_nil ? " " : "", params.vaddr+off); } String8 code_bytes_part = {0}; if(params.style_flags & DASM_StyleFlag_CodeBytes) { String8List code_bytes_strings = {0}; str8_list_push(scratch.arena, &code_bytes_strings, str8_lit("{")); for(U64 byte_idx = 0; byte_idx < inst.size || byte_idx < 16; byte_idx += 1) { if(byte_idx < inst.size) { str8_list_pushf(scratch.arena, &code_bytes_strings, "%02x%s ", (U32)data.str[off+byte_idx], byte_idx == inst.size-1 ? "}" : ""); } else if(byte_idx < 8) { str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" ")); } } str8_list_push(scratch.arena, &code_bytes_strings, str8_lit(" ")); code_bytes_part = str8_list_join(scratch.arena, &code_bytes_strings, 0); } String8 symbol_part = {0}; if(inst.jump_dest_vaddr != 0 && rdi != &rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames) { RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, inst.jump_dest_vaddr-params.base_vaddr); if(scope_idx != 0) { RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); RDI_U32 procedure_idx = scope->proc_idx; RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); String8 procedure_name = {0}; procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); if(procedure_name.size != 0) { symbol_part = push_str8f(scratch.arena, " (%S)", procedure_name); } } } String8 inst_string = push_str8f(scratch.arena, "%S%S%S%S", addr_part, code_bytes_part, inst.string, symbol_part); DASM_Line line = {u32_from_u64_saturate(off), 0, inst.jump_dest_vaddr, r1u64(inst_strings.total_size + inst_strings.node_count, inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_line_chunk_list_push(scratch.arena, &line_list, 1024, &line); str8_list_push(scratch.arena, &inst_strings, inst_string); // rjf: increment off += inst.size; } }break; } //- rjf: artifacts -> value bundle Arena *info_arena = 0; DASM_Info info = {0}; if(!stale) { //- rjf: produce joined text Arena *text_arena = arena_alloc(); StringJoin text_join = {0}; text_join.sep = str8_lit("\n"); String8 text = str8_list_join(text_arena, &inst_strings, &text_join); //- rjf: produce unique key for this disassembly's text C_Key text_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); //- rjf: submit text data to hash store U128 text_hash = c_submit_data(text_key, &text_arena, text); //- rjf: produce value bundle info_arena = arena_alloc(); info.text_key = text_key; info.lines = dasm_line_array_from_chunk_list(info_arena, &line_list); } //- rjf: if stale, retry if(stale) { retry_out[0] = 1; } //- rjf: mark dependency on data hash c_hash_downstream_inc(hash); //- rjf: fill result if(info_arena != 0) { artifact = push_array(info_arena, DASM_Artifact, 1); artifact->arena = info_arena; artifact->info = info; artifact->data_hash = hash; } access_close(access); scratch_end(scratch); } lane_sync_u64(&artifact, 0); AC_Artifact result = {0}; result.u64[0] = (U64)artifact; return result; } internal void dasm_artifact_destroy(AC_Artifact artifact) { DASM_Artifact *dasm_artifact = (DASM_Artifact *)artifact.u64[0]; if(dasm_artifact == 0) { return; } c_close_key(dasm_artifact->info.text_key); c_hash_downstream_dec(dasm_artifact->data_hash); arena_release(dasm_artifact->arena); } internal DASM_Info dasm_info_from_hash_params(Access *access, U128 hash, DASM_Params *params) { DASM_Info info = {0}; { Temp scratch = scratch_begin(0, 0); // rjf: form key String8List key_parts = {0}; str8_list_push(scratch.arena, &key_parts, str8_struct(&hash)); str8_list_push(scratch.arena, &key_parts, str8_struct(params)); String8 key = str8_list_join(scratch.arena, &key_parts, 0); // rjf: get info AC_Artifact artifact = ac_artifact_from_key(access, key, dasm_artifact_create, dasm_artifact_destroy, 0, .gen = fs_change_gen(), .flags = AC_Flag_Wide); DASM_Artifact *dasm_artifact = (DASM_Artifact *)artifact.u64[0]; if(dasm_artifact) { info = dasm_artifact->info; } scratch_end(scratch); } return info; } internal DASM_Info dasm_info_from_key_params(Access *access, C_Key key, DASM_Params *params, U128 *hash_out) { DASM_Info result = {0}; for(U64 rewind_idx = 0; rewind_idx < C_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) { U128 hash = c_hash_from_key(key, rewind_idx); result = dasm_info_from_hash_params(access, hash, params); if(result.lines.count != 0) { if(hash_out) { *hash_out = hash; } break; } } return result; } ================================================ FILE: src/disasm/disasm.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DISASM_H #define DISASM_H //////////////////////////////// //~ rjf: Disassembly Syntax Types typedef enum DASM_Syntax { DASM_Syntax_Intel, DASM_Syntax_ATT, DASM_Syntax_COUNT } DASM_Syntax; //////////////////////////////// //~ rjf: Disassembly Instruction Info Types typedef U32 DASM_InstFlags; enum { DASM_InstFlag_Call = (1<<0), DASM_InstFlag_Branch = (1<<1), DASM_InstFlag_UnconditionalJump = (1<<2), DASM_InstFlag_Return = (1<<3), DASM_InstFlag_NonFlow = (1<<4), DASM_InstFlag_Repeats = (1<<5), DASM_InstFlag_ChangesStackPointer = (1<<6), DASM_InstFlag_ChangesStackPointerVariably = (1<<7), }; typedef struct DASM_Inst DASM_Inst; struct DASM_Inst { DASM_InstFlags flags; U32 size; String8 string; U64 jump_dest_vaddr; }; //////////////////////////////// //~ rjf: Control Flow Analysis Types typedef struct DASM_CtrlFlowPoint DASM_CtrlFlowPoint; struct DASM_CtrlFlowPoint { U64 vaddr; U64 jump_dest_vaddr; DASM_InstFlags inst_flags; }; typedef struct DASM_CtrlFlowPointNode DASM_CtrlFlowPointNode; struct DASM_CtrlFlowPointNode { DASM_CtrlFlowPointNode *next; DASM_CtrlFlowPoint v; }; typedef struct DASM_CtrlFlowPointList DASM_CtrlFlowPointList; struct DASM_CtrlFlowPointList { DASM_CtrlFlowPointNode *first; DASM_CtrlFlowPointNode *last; U64 count; }; typedef struct DASM_CtrlFlowInfo DASM_CtrlFlowInfo; struct DASM_CtrlFlowInfo { DASM_CtrlFlowPointList exit_points; U64 total_size; }; //////////////////////////////// //~ rjf: Disassembly Text Decoration Types typedef U32 DASM_StyleFlags; enum { DASM_StyleFlag_Addresses = (1<<0), DASM_StyleFlag_CodeBytes = (1<<1), DASM_StyleFlag_SourceFilesNames = (1<<2), DASM_StyleFlag_SourceLines = (1<<3), DASM_StyleFlag_SymbolNames = (1<<4), }; //////////////////////////////// //~ rjf: Disassembling Parameters Bundle typedef struct DASM_Params DASM_Params; struct DASM_Params { U64 vaddr; Arch arch; DASM_StyleFlags style_flags; DASM_Syntax syntax; U64 base_vaddr; DI_Key dbgi_key; }; //////////////////////////////// //~ rjf: Disassembly Request Bundle typedef struct DASM_Request DASM_Request; struct DASM_Request { C_Root root; U128 hash; DASM_Params params; }; typedef struct DASM_RequestNode DASM_RequestNode; struct DASM_RequestNode { DASM_RequestNode *next; DASM_Request v; }; //////////////////////////////// //~ rjf: Disassembly Text Line Types typedef U32 DASM_LineFlags; enum { DASM_LineFlag_Decorative = (1<<0), }; typedef struct DASM_Line DASM_Line; struct DASM_Line { U32 code_off; DASM_LineFlags flags; U64 addr; Rng1U64 text_range; }; typedef struct DASM_LineChunkNode DASM_LineChunkNode; struct DASM_LineChunkNode { DASM_LineChunkNode *next; DASM_Line *v; U64 cap; U64 count; }; typedef struct DASM_LineChunkList DASM_LineChunkList; struct DASM_LineChunkList { DASM_LineChunkNode *first; DASM_LineChunkNode *last; U64 node_count; U64 line_count; }; typedef struct DASM_LineArray DASM_LineArray; struct DASM_LineArray { DASM_Line *v; U64 count; }; //////////////////////////////// //~ rjf: Value Bundle Type typedef struct DASM_Info DASM_Info; struct DASM_Info { C_Key text_key; DASM_LineArray lines; }; //////////////////////////////// //~ rjf: Instruction Decoding/Disassembling Type Functions internal DASM_Inst dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, String8 code, DASM_Syntax syntax); //////////////////////////////// //~ rjf: Control Flow Analysis internal DASM_CtrlFlowInfo dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code); //////////////////////////////// //~ rjf: Parameter Type Functions internal B32 dasm_params_match(DASM_Params *a, DASM_Params *b); //////////////////////////////// //~ rjf: Line Type Functions internal void dasm_line_chunk_list_push(Arena *arena, DASM_LineChunkList *list, U64 cap, DASM_Line *line); internal DASM_LineArray dasm_line_array_from_chunk_list(Arena *arena, DASM_LineChunkList *list); internal U64 dasm_line_array_idx_from_code_off__linear_scan(DASM_LineArray *array, U64 off); internal U64 dasm_line_array_code_off_from_idx(DASM_LineArray *array, U64 idx); //////////////////////////////// //~ rjf: Artifact Cache Hooks / Lookups internal AC_Artifact dasm_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void dasm_artifact_destroy(AC_Artifact artifact); internal DASM_Info dasm_info_from_hash_params(Access *access, U128 hash, DASM_Params *params); internal DASM_Info dasm_info_from_key_params(Access *access, C_Key key, DASM_Params *params, U128 *hash_out); #endif // DISASM_H ================================================ FILE: src/draw/draw.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #define DR_StackPushImpl(name_upper, name_lower, type, val) \ DR_Bucket *bucket = dr_top_bucket();\ type old_val = bucket->top_##name_lower->v;\ DR_##name_upper##Node *node = push_array(dr_thread_ctx->arena, DR_##name_upper##Node, 1);\ node->v = (val);\ SLLStackPush(bucket->top_##name_lower, node);\ bucket->stack_gen += 1;\ return old_val #define DR_StackPopImpl(name_upper, name_lower, type) \ DR_Bucket *bucket = dr_top_bucket();\ type popped_val = bucket->top_##name_lower->v;\ SLLStackPop(bucket->top_##name_lower);\ bucket->stack_gen += 1;\ return popped_val #define DR_StackTopImpl(name_upper, name_lower, type) \ DR_Bucket *bucket = dr_top_bucket();\ type top_val = bucket->top_##name_lower->v;\ return top_val #include "generated/draw.meta.c" //////////////////////////////// //~ rjf: Basic Helpers internal U64 dr_hash_from_string(String8 string) { U64 result = 5381; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + string.str[i]; } return result; } //////////////////////////////// //~ rjf: Fancy String Type Functions internal void dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str) { DR_FStrNode *n = push_array_no_zero(arena, DR_FStrNode, 1); MemoryCopyStruct(&n->v, str); SLLQueuePush(list->first, list->last, n); list->node_count += 1; list->total_size += str->string.size; } internal void dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string) { DR_FStr fstr = {string, *params}; if(!fnt_tag_match(fnt_tag_zero(), overrides->font)) { fstr.params.font = overrides->font; } if(overrides->raster_flags != 0) { fstr.params.raster_flags = overrides->raster_flags; } if(overrides->color.x != 0 || overrides->color.y != 0 || overrides->color.z != 0 || overrides->color.w != 0) { fstr.params.color = overrides->color; } if(overrides->size != 0) { fstr.params.size = overrides->size; } if(overrides->underline_thickness != 0) { fstr.params.underline_thickness = overrides->underline_thickness; } if(overrides->strikethrough_thickness != 0) { fstr.params.strikethrough_thickness = overrides->strikethrough_thickness; } dr_fstrs_push(arena, list, &fstr); } internal void dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push) { if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->node_count += to_push->node_count; dst->total_size += to_push->total_size; } else if(to_push->first != 0) { MemoryCopyStruct(dst, to_push); } MemoryZeroStruct(to_push); } internal DR_FStrList dr_fstrs_copy(Arena *arena, DR_FStrList *src) { DR_FStrList dst = {0}; for(DR_FStrNode *src_n = src->first; src_n != 0; src_n = src_n->next) { DR_FStr fstr = src_n->v; fstr.string = push_str8_copy(arena, fstr.string); dr_fstrs_push(arena, &dst, &fstr); } return dst; } internal String8 dr_string_from_fstrs(Arena *arena, DR_FStrList *list) { String8 result = {0}; { Temp scratch = scratch_begin(&arena, 1); String8List parts = {0}; for(DR_FStrNode *n = list->first; n != 0; n = n->next) { if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)) { str8_list_push(scratch.arena, &parts, n->v.string); } } result = str8_list_join(arena, &parts, 0); result = str8_skip_chop_whitespace(result); scratch_end(scratch); } return result; } internal FuzzyMatchRangeList dr_fuzzy_match_find_from_fstrs(Arena *arena, DR_FStrList *fstrs, String8 needle) { Temp scratch = scratch_begin(&arena, 1); String8 fstrs_string = {0}; fstrs_string.size = fstrs->total_size; fstrs_string.str = push_array(arena, U8, fstrs_string.size); { // TODO(rjf): the fact that we only increment on non-icon portions is super weird? // we are only doing that because of the rendering of the fuzzy matches, so maybe // once that is straightened out, we can fix the code here too... U64 off = 0; for(DR_FStrNode *n = fstrs->first; n != 0; n = n->next) { if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)) { MemoryCopy(fstrs_string.str + off, n->v.string.str, n->v.string.size); off += n->v.string.size; } } } FuzzyMatchRangeList ranges = fuzzy_match_find(arena, needle, fstrs_string); scratch_end(scratch); return ranges; } internal DR_FRunList dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs) { DR_FRunList run_list = {0}; F32 base_align_px = 0; for(DR_FStrNode *n = strs->first; n != 0; n = n->next) { DR_FRunNode *dst_n = push_array(arena, DR_FRunNode, 1); dst_n->v.run = fnt_run_from_string(n->v.params.font, n->v.params.size, base_align_px, tab_size_px, n->v.params.raster_flags, n->v.string); dst_n->v.color = n->v.params.color; dst_n->v.underline_thickness = n->v.params.underline_thickness; dst_n->v.strikethrough_thickness = n->v.params.strikethrough_thickness; dst_n->v.icon = (fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font)); SLLQueuePush(run_list.first, run_list.last, dst_n); run_list.node_count += 1; run_list.dim.x += dst_n->v.run.dim.x; run_list.dim.y = Max(run_list.dim.y, dst_n->v.run.dim.y); base_align_px += dst_n->v.run.dim.x; } return run_list; } internal Vec2F32 dr_dim_from_fstrs(F32 tab_size_px, DR_FStrList *fstrs) { Temp scratch = scratch_begin(0, 0); DR_FRunList fruns = dr_fruns_from_fstrs(scratch.arena, tab_size_px, fstrs); Vec2F32 dim = fruns.dim; scratch_end(scratch); return dim; } //////////////////////////////// //~ rjf: Top-Level API // // (Frame boundaries) internal void dr_begin_frame(FNT_Tag icon_font) { if(dr_thread_ctx == 0) { Arena *arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(8)); dr_thread_ctx = push_array(arena, DR_ThreadCtx, 1); dr_thread_ctx->arena = arena; dr_thread_ctx->arena_frame_start_pos = arena_pos(arena); } arena_pop_to(dr_thread_ctx->arena, dr_thread_ctx->arena_frame_start_pos); dr_thread_ctx->free_bucket_selection = 0; dr_thread_ctx->top_bucket = 0; dr_thread_ctx->icon_font = icon_font; } internal void dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket) { r_window_submit(os_window, r_window, &bucket->passes); } //////////////////////////////// //~ rjf: Bucket Construction & Selection API // // (Bucket: Handle to sequence of many render passes, constructed by this layer) internal DR_Bucket * dr_bucket_make(void) { DR_Bucket *bucket = push_array(dr_thread_ctx->arena, DR_Bucket, 1); DR_BucketStackInits(bucket); return bucket; } internal void dr_push_bucket(DR_Bucket *bucket) { DR_BucketSelectionNode *node = dr_thread_ctx->free_bucket_selection; if(node) { SLLStackPop(dr_thread_ctx->free_bucket_selection); } else { node = push_array(dr_thread_ctx->arena, DR_BucketSelectionNode, 1); } SLLStackPush(dr_thread_ctx->top_bucket, node); node->bucket = bucket; } internal void dr_pop_bucket(void) { DR_BucketSelectionNode *node = dr_thread_ctx->top_bucket; SLLStackPop(dr_thread_ctx->top_bucket); SLLStackPush(dr_thread_ctx->free_bucket_selection, node); } internal DR_Bucket * dr_top_bucket(void) { DR_Bucket *bucket = 0; if(dr_thread_ctx->top_bucket != 0) { bucket = dr_thread_ctx->top_bucket->bucket; } return bucket; } //////////////////////////////// //~ rjf: Bucket Stacks // // (Pushing/popping implicit draw parameters) // NOTE(rjf): (The implementation of the push/pop/top functions is auto-generated) //////////////////////////////// //~ rjf: Draw Calls // // (Apply to the calling thread's currently selected bucket) //- rjf: rectangles internal inline R_Rect2DInst * dr_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *bucket = dr_top_bucket(); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI); R_PassParams_UI *params = pass->params_ui; R_BatchGroup2DList *rects = ¶ms->rects; R_BatchGroup2DNode *node = rects->last; if(node == 0 || bucket->stack_gen != bucket->last_cmd_stack_gen) { node = push_array(arena, R_BatchGroup2DNode, 1); SLLQueuePush(rects->first, rects->last, node); rects->count += 1; node->batches = r_batch_list_make(sizeof(R_Rect2DInst)); node->params.tex = r_handle_zero(); node->params.tex_sample_kind = bucket->top_tex2d_sample_kind->v; node->params.xform = bucket->top_xform2d->v; node->params.clip = bucket->top_clip->v; node->params.transparency = bucket->top_transparency->v; } R_Rect2DInst *inst = (R_Rect2DInst *)r_batch_list_push_inst(arena, &node->batches, 256); inst->dst = dst; inst->src = r2f32p(0, 0, 0, 0); inst->colors[Corner_00] = color; inst->colors[Corner_01] = color; inst->colors[Corner_10] = color; inst->colors[Corner_11] = color; inst->corner_radii[Corner_00] = corner_radius; inst->corner_radii[Corner_01] = corner_radius; inst->corner_radii[Corner_10] = corner_radius; inst->corner_radii[Corner_11] = corner_radius; inst->border_thickness = border_thickness; inst->edge_softness = edge_softness; inst->white_texture_override = 1.f; inst->shear = 0.f; bucket->last_cmd_stack_gen = bucket->stack_gen; return inst; } //- rjf: images internal inline R_Rect2DInst * dr_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *bucket = dr_top_bucket(); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_UI); R_PassParams_UI *params = pass->params_ui; R_BatchGroup2DList *rects = ¶ms->rects; R_BatchGroup2DNode *node = rects->last; if(node != 0 && bucket->stack_gen == bucket->last_cmd_stack_gen && r_handle_match(node->params.tex, r_handle_zero())) { node->params.tex = texture; } else if(node == 0 || bucket->stack_gen != bucket->last_cmd_stack_gen || !r_handle_match(texture, node->params.tex)) { node = push_array(arena, R_BatchGroup2DNode, 1); SLLQueuePush(rects->first, rects->last, node); rects->count += 1; node->batches = r_batch_list_make(sizeof(R_Rect2DInst)); node->params.tex = texture; node->params.tex_sample_kind = bucket->top_tex2d_sample_kind->v; node->params.xform = bucket->top_xform2d->v; node->params.clip = bucket->top_clip->v; node->params.transparency = bucket->top_transparency->v; } R_Rect2DInst *inst = (R_Rect2DInst *)r_batch_list_push_inst(arena, &node->batches, 256); inst->dst = dst; inst->src = src; inst->colors[Corner_00] = color; inst->colors[Corner_01] = color; inst->colors[Corner_10] = color; inst->colors[Corner_11] = color; inst->corner_radii[Corner_00] = corner_radius; inst->corner_radii[Corner_01] = corner_radius; inst->corner_radii[Corner_10] = corner_radius; inst->corner_radii[Corner_11] = corner_radius; inst->border_thickness = border_thickness; inst->edge_softness = edge_softness; inst->white_texture_override = 0.f; inst->shear = 0.f; bucket->last_cmd_stack_gen = bucket->stack_gen; return inst; } //- rjf: blurs internal R_PassParams_Blur * dr_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *bucket = dr_top_bucket(); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Blur); R_PassParams_Blur *params = pass->params_blur; params->rect = rect; params->clip = dr_top_clip(); params->blur_size = blur_size; params->corner_radii[Corner_00] = corner_radius; params->corner_radii[Corner_01] = corner_radius; params->corner_radii[Corner_10] = corner_radius; params->corner_radii[Corner_11] = corner_radius; return params; } //- rjf: 3d rendering pass params internal R_PassParams_Geo3D * dr_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *bucket = dr_top_bucket(); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D); R_PassParams_Geo3D *params = pass->params_geo3d; params->viewport = viewport; params->view = view; params->projection = projection; return params; } //- rjf: meshes internal R_Mesh3DInst * dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *bucket = dr_top_bucket(); R_Pass *pass = r_pass_from_kind(arena, &bucket->passes, R_PassKind_Geo3D); R_PassParams_Geo3D *params = pass->params_geo3d; // rjf: mesh batch map not made yet -> make if(params->mesh_batches.slots_count == 0) { params->mesh_batches.slots_count = 64; params->mesh_batches.slots = push_array(arena, R_BatchGroup3DMapNode *, params->mesh_batches.slots_count); } // rjf: hash batch group 3d params U64 hash = 0; U64 slot_idx = 0; { U64 buffer[] = { mesh_vertices.u64[0], mesh_vertices.u64[1], mesh_indices.u64[0], mesh_indices.u64[1], (U64)mesh_geo_topology, (U64)mesh_geo_vertex_flags, albedo_tex.u64[0], albedo_tex.u64[1], (U64)dr_top_tex2d_sample_kind(), }; hash = dr_hash_from_string(str8((U8 *)buffer, sizeof(buffer))); slot_idx = hash%params->mesh_batches.slots_count; } // rjf: map hash -> existing batch group node R_BatchGroup3DMapNode *node = 0; { for(R_BatchGroup3DMapNode *n = params->mesh_batches.slots[slot_idx]; n != 0; n = n->next) { if(n->hash == hash) { node = n; break; } } } // rjf: no batch group node? -> make one if(node == 0) { node = push_array(arena, R_BatchGroup3DMapNode, 1); SLLStackPush(params->mesh_batches.slots[slot_idx], node); node->hash = hash; node->batches = r_batch_list_make(sizeof(R_Mesh3DInst)); node->params.mesh_vertices = mesh_vertices; node->params.mesh_indices = mesh_indices; node->params.mesh_geo_topology = mesh_geo_topology; node->params.mesh_geo_vertex_flags = mesh_geo_vertex_flags; node->params.albedo_tex = albedo_tex; node->params.albedo_tex_sample_kind = dr_top_tex2d_sample_kind(); node->params.xform = mat_4x4f32(1.f); } // rjf: push new instance to batch group R_Mesh3DInst *inst = (R_Mesh3DInst *)r_batch_list_push_inst(arena, &node->batches, 256); inst->xform = inst_xform; return inst; } //- rjf: collating one pre-prepped bucket into parent bucket internal void dr_sub_bucket(DR_Bucket *bucket) { Arena *arena = dr_thread_ctx->arena; DR_Bucket *src = bucket; DR_Bucket *dst = dr_top_bucket(); Rng2F32 dst_clip = dr_top_clip(); B32 dst_clip_is_set = !(dst_clip.x0 == 0 && dst_clip.x1 == 0 && dst_clip.y0 == 0 && dst_clip.y1 == 0); for(R_PassNode *n = src->passes.first; n != 0; n = n->next) { R_Pass *src_pass = &n->v; R_Pass *dst_pass = r_pass_from_kind(arena, &dst->passes, src_pass->kind); switch(dst_pass->kind) { default:{dst_pass->params = src_pass->params;}break; case R_PassKind_UI: { R_PassParams_UI *src_ui = src_pass->params_ui; R_PassParams_UI *dst_ui = dst_pass->params_ui; for(R_BatchGroup2DNode *src_group_n = src_ui->rects.first; src_group_n != 0; src_group_n = src_group_n->next) { R_BatchGroup2DNode *dst_group_n = push_array(arena, R_BatchGroup2DNode, 1); SLLQueuePush(dst_ui->rects.first, dst_ui->rects.last, dst_group_n); dst_ui->rects.count += 1; MemoryCopyStruct(&dst_group_n->params, &src_group_n->params); dst_group_n->batches = src_group_n->batches; dst_group_n->params.xform = dr_top_xform2d(); B32 clip_is_set = !(dst_group_n->params.clip.x0 == 0 && dst_group_n->params.clip.y0 == 0 && dst_group_n->params.clip.x1 == 0 && dst_group_n->params.clip.y1 == 0); if(clip_is_set) { Rng2F32 og_clip = dst_group_n->params.clip; Mat3x3F32 xform = dst_group_n->params.xform; dst_group_n->params.clip = r2f32(xform_3f32(v3f32(og_clip.x0, og_clip.y0, 1), xform).xy, xform_3f32(v3f32(og_clip.x1, og_clip.y1, 1), xform).xy); } if(dst_clip_is_set) { dst_group_n->params.clip = clip_is_set ? intersect_2f32(dst_clip, dst_group_n->params.clip) : dst_clip; } } }break; } } } //////////////////////////////// //~ rjf: Draw Call Helpers //- rjf: text internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run) { //- rjf: total advance > max? -> enable trailer B32 trailer_enabled = (list->dim.x > max_x && trailer_run.dim.x < max_x); //- rjf: draw runs F32 advance = 0; B32 trailer_found = 0; Vec4F32 last_color = {0}; U64 byte_off = 0; for(DR_FRunNode *n = list->first; n != 0; n = n->next) { DR_FRun *fr = &n->v; Rng1F32 pixel_range = {0}; { pixel_range.min = 100000; pixel_range.max = 0; } FNT_Piece *piece_first = fr->run.pieces.v; FNT_Piece *piece_opl = piece_first + fr->run.pieces.count; F32 pre_advance = advance; last_color = fr->color; for(FNT_Piece *piece = piece_first; piece < piece_opl; piece += 1) { if(trailer_enabled && advance + piece->advance > (max_x - trailer_run.dim.x)) { trailer_found = 1; break; } if(!trailer_enabled && advance + piece->advance > max_x) { goto end_draw; } R_Handle texture = piece->texture; Rng2F32 src = r2f32p((F32)piece->subrect.x0, (F32)piece->subrect.y0, (F32)piece->subrect.x1, (F32)piece->subrect.y1); Vec2F32 size = dim_2f32(src); Rng2F32 dst = r2f32p(p.x + piece->offset.x + advance, p.y + piece->offset.y, p.x + piece->offset.x + advance + size.x, p.y + piece->offset.y + size.y); if(!r_handle_match(texture, r_handle_zero())) { dr_img(dst, src, texture, fr->color, 0, 0, 0); // dr_rect(dst, v4f32(0, 1, 0, 0.5f), 0, 1.f, 0.f); } advance += piece->advance; pixel_range.min = Min(pre_advance, pixel_range.min); pixel_range.max = Max(advance, pixel_range.max); } if(fr->underline_thickness > 0) { dr_rect(r2f32p(p.x + pixel_range.min, p.y+fr->run.descent+fr->run.descent/8, p.x + pixel_range.max, p.y+fr->run.descent+fr->run.descent/8+fr->underline_thickness), fr->color, 0, 0, 0.8f); } if(fr->strikethrough_thickness > 0) { dr_rect(r2f32p(p.x+pre_advance, p.y+fr->run.descent - fr->run.ascent/2, p.x+advance, p.y+fr->run.descent - fr->run.ascent/2 + fr->strikethrough_thickness), fr->color, 0, 0, 1.f); } if(trailer_found) { break; } } end_draw:; //- rjf: draw trailer if(trailer_found) { FNT_Piece *piece_first = trailer_run.pieces.v; FNT_Piece *piece_opl = piece_first + trailer_run.pieces.count; F32 pre_advance = advance; Vec4F32 trailer_piece_color = last_color; for(FNT_Piece *piece = piece_first; piece < piece_opl; piece += 1) { R_Handle texture = piece->texture; Rng2F32 src = r2f32p((F32)piece->subrect.x0, (F32)piece->subrect.y0, (F32)piece->subrect.x1, (F32)piece->subrect.y1); Vec2F32 size = dim_2f32(src); Rng2F32 dst = r2f32p(p.x + piece->offset.x + advance, p.y + piece->offset.y, p.x + piece->offset.x + advance + size.x, p.y + piece->offset.y + size.y); if(!r_handle_match(texture, r_handle_zero())) { dr_img(dst, src, texture, trailer_piece_color, 0, 0, 0); trailer_piece_color.w *= 0.5f; } advance += piece->advance; } } } internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color) { for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next) { Rng1U64 byte_range = match_n->range; Rng1F32 pixel_range = {0}; { pixel_range.min = 100000; pixel_range.max = 0; } F32 last_piece_end_pad = 0; U64 byte_off = 0; F32 advance = 0; F32 ascent = 0; F32 descent = 0; for(DR_FRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next) { DR_FRun *fr = &fr_n->v; FNT_Run *run = &fr->run; ascent = run->ascent; descent = run->descent; for(U64 piece_idx = 0; piece_idx < run->pieces.count; piece_idx += 1) { FNT_Piece *piece = &run->pieces.v[piece_idx]; if(contains_1u64(byte_range, byte_off)) { F32 pre_advance = advance + piece->offset.x; F32 post_advance = advance + piece->advance; pixel_range.min = Min(pre_advance, pixel_range.min); pixel_range.max = Max(post_advance, pixel_range.max); } if(!fr->icon) { byte_off += piece->decode_size; } advance += piece->advance; } } if(pixel_range.min < pixel_range.max) { Rng2F32 rect = r2f32p(p.x + pixel_range.min - ascent/4.f, p.y - descent - ascent - ascent/8.f, p.x + pixel_range.max + ascent/4.f, p.y - descent - ascent + ascent/8.f + list->dim.y); rect.x0 = Min(rect.x0, p.x+max_x); rect.x1 = Min(rect.x1, p.x+max_x); dr_rect(rect, color, (descent+ascent)/4.f, 0, 1.f); } } } internal void dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run) { F32 advance = 0; FNT_Piece *piece_first = run.pieces.v; FNT_Piece *piece_opl = piece_first + run.pieces.count; for(FNT_Piece *piece = piece_first; piece < piece_opl; piece += 1) { R_Handle texture = piece->texture; Rng2F32 src = r2f32p((F32)piece->subrect.x0, (F32)piece->subrect.y0, (F32)piece->subrect.x1, (F32)piece->subrect.y1); Vec2F32 size = dim_2f32(src); Rng2F32 dst = r2f32p(p.x + piece->offset.x + advance, p.y + piece->offset.y, p.x + piece->offset.x + advance + size.x, p.y + piece->offset.y + size.y); if(size.x != 0 && size.y != 0 && !r_handle_match(texture, r_handle_zero())) { dr_img(dst, src, texture, color, 0, 0, 0); } advance += piece->advance; } } internal void dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string) { Temp scratch = scratch_begin(0, 0); FNT_Run run = fnt_run_from_string(font, size, base_align_px, tab_size_px, flags, string); dr_text_run(p, color, run); scratch_end(scratch); } ================================================ FILE: src/draw/draw.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DRAW_H #define DRAW_H //////////////////////////////// //~ rjf: Fancy String Types typedef struct DR_FStrParams DR_FStrParams; struct DR_FStrParams { FNT_Tag font; FNT_RasterFlags raster_flags; Vec4F32 color; F32 size; F32 underline_thickness; F32 strikethrough_thickness; }; typedef struct DR_FStr DR_FStr; struct DR_FStr { String8 string; DR_FStrParams params; }; typedef struct DR_FStrNode DR_FStrNode; struct DR_FStrNode { DR_FStrNode *next; DR_FStr v; }; typedef struct DR_FStrList DR_FStrList; struct DR_FStrList { DR_FStrNode *first; DR_FStrNode *last; U64 node_count; U64 total_size; }; typedef struct DR_FRun DR_FRun; struct DR_FRun { FNT_Run run; Vec4F32 color; F32 underline_thickness; F32 strikethrough_thickness; B32 icon; }; typedef struct DR_FRunNode DR_FRunNode; struct DR_FRunNode { DR_FRunNode *next; DR_FRun v; }; typedef struct DR_FRunList DR_FRunList; struct DR_FRunList { DR_FRunNode *first; DR_FRunNode *last; U64 node_count; Vec2F32 dim; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/draw.meta.h" //////////////////////////////// //~ rjf: Draw Bucket Types typedef struct DR_Bucket DR_Bucket; struct DR_Bucket { R_PassList passes; U64 stack_gen; U64 last_cmd_stack_gen; DR_BucketStackDecls; }; //////////////////////////////// //~ rjf: Thread Context typedef struct DR_BucketSelectionNode DR_BucketSelectionNode; struct DR_BucketSelectionNode { DR_BucketSelectionNode *next; DR_Bucket *bucket; }; typedef struct DR_ThreadCtx DR_ThreadCtx; struct DR_ThreadCtx { Arena *arena; U64 arena_frame_start_pos; FNT_Tag icon_font; DR_BucketSelectionNode *top_bucket; DR_BucketSelectionNode *free_bucket_selection; }; //////////////////////////////// //~ rjf: Globals thread_static DR_ThreadCtx *dr_thread_ctx = 0; //////////////////////////////// //~ rjf: Basic Helpers internal U64 dr_hash_from_string(String8 string); //////////////////////////////// //~ rjf: Fancy String Type Functions internal void dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str); internal void dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string); #define dr_fstrs_push_new(arena, list, params, string, ...) dr_fstrs_push_new_((arena), (list), (params), &(DR_FStrParams){.size = 0, __VA_ARGS__}, (string)) internal void dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push); internal DR_FStrList dr_fstrs_copy(Arena *arena, DR_FStrList *src); internal String8 dr_string_from_fstrs(Arena *arena, DR_FStrList *list); internal FuzzyMatchRangeList dr_fuzzy_match_find_from_fstrs(Arena *arena, DR_FStrList *fstrs, String8 needle); internal DR_FRunList dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs); internal Vec2F32 dr_dim_from_fstrs(F32 tab_size_px, DR_FStrList *fstrs); //////////////////////////////// //~ rjf: Top-Level API // // (Frame boundaries & bucket submission) internal void dr_begin_frame(FNT_Tag icon_font); internal void dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket); //////////////////////////////// //~ rjf: Bucket Construction & Selection API // // (Bucket: Handle to sequence of many render passes, constructed by this layer) internal DR_Bucket *dr_bucket_make(void); internal void dr_push_bucket(DR_Bucket *bucket); internal void dr_pop_bucket(void); internal DR_Bucket *dr_top_bucket(void); #define DR_BucketScope(b) DeferLoop(dr_push_bucket(b), dr_pop_bucket()) //////////////////////////////// //~ rjf: Bucket Stacks // // (Pushing/popping implicit draw parameters) internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v); internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v); internal Rng2F32 dr_push_clip(Rng2F32 v); internal F32 dr_push_transparency(F32 v); internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void); internal Mat3x3F32 dr_pop_xform2d(void); internal Rng2F32 dr_pop_clip(void); internal F32 dr_pop_transparency(void); internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void); internal Mat3x3F32 dr_top_xform2d(void); internal Rng2F32 dr_top_clip(void); internal F32 dr_top_transparency(void); #define DR_Tex2DSampleKindScope(v) DeferLoop(dr_push_tex2d_sample_kind(v), dr_pop_tex2d_sample_kind()) #define DR_XForm2DScope(v) DeferLoop(dr_push_xform2d(v), dr_pop_xform2d()) #define DR_ClipScope(v) DeferLoop(dr_push_clip(v), dr_pop_clip()) #define DR_TransparencyScope(v) DeferLoop(dr_push_transparency(v), dr_pop_transparency()) //////////////////////////////// //~ rjf: Core Draw Calls // // (Apply to the calling thread's currently selected bucket) //- rjf: rectangles internal inline R_Rect2DInst *dr_rect(Rng2F32 dst, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness); //- rjf: images internal inline R_Rect2DInst *dr_img(Rng2F32 dst, Rng2F32 src, R_Handle texture, Vec4F32 color, F32 corner_radius, F32 border_thickness, F32 edge_softness); //- rjf: blurs internal R_PassParams_Blur *dr_blur(Rng2F32 rect, F32 blur_size, F32 corner_radius); //- rjf: 3d rendering pass params internal R_PassParams_Geo3D *dr_geo3d_begin(Rng2F32 viewport, Mat4x4F32 view, Mat4x4F32 projection); //- rjf: meshes internal R_Mesh3DInst *dr_mesh(R_Handle mesh_vertices, R_Handle mesh_indices, R_GeoTopologyKind mesh_geo_topology, R_GeoVertexFlags mesh_geo_vertex_flags, R_Handle albedo_tex, Mat4x4F32 inst_xform); //- rjf: collating one pre-prepped bucket into parent bucket internal void dr_sub_bucket(DR_Bucket *bucket); //////////////////////////////// //~ rjf: Draw Call Helpers //- rjf: text internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run); internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color); internal void dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run); internal void dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string); #endif // DRAW_H ================================================ FILE: src/draw/draw.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name, name_lower, type, default_init) DR_StackTable: { {Tex2DSampleKind tex2d_sample_kind R_Tex2DSampleKind `R_Tex2DSampleKind_Nearest` } {XForm2D xform2d Mat3x3F32 `{1, 0, 0, 0, 1, 0, 0, 0, 1}` } {Clip clip Rng2F32 `{0}` } {Transparency transparency F32 `0` } } @gen { @expand(DR_StackTable a) `typedef struct DR_$(a.name)Node DR_$(a.name)Node; struct DR_$(a.name)Node {DR_$(a.name)Node *next; $(a.type) v;};`; } @gen { `#define DR_BucketStackDecls struct{\\`; @expand(DR_StackTable a) `DR_$(a.name)Node *top_$(a.name_lower);\\`; `}`; } @gen { @expand(DR_StackTable a) `read_only global DR_$(a.name)Node dr_nil_$(a.name_lower) = {0, $(a.default_init)};`; } @gen { `#define DR_BucketStackInits(b) do{\\`; @expand(DR_StackTable a) `(b)->top_$(a.name_lower) = &dr_nil_$(a.name_lower);\\`; `}while(0)`; } @gen { `#if 0`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_push_$(a.name_lower)($(a.type) v);`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_pop_$(a.name_lower)(void);`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_top_$(a.name_lower)(void);`; `#endif`; } @gen @c_file { @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_push_$(a.name_lower)($(a.type) v) {DR_StackPushImpl($(a.name), $(a.name_lower), $(a.type), v);}`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_pop_$(a.name_lower)(void) {DR_StackPopImpl($(a.name), $(a.name_lower), $(a.type));}`; @expand(DR_StackTable a) `internal $(a.type) $(=>35) dr_top_$(a.name_lower)(void) {DR_StackTopImpl($(a.name), $(a.name_lower), $(a.type));}`; } @gen { `#if 0`; @expand(DR_StackTable a) `#define DR_$(a.name)Scope(v) $(=>35) DeferLoop(dr_push_$(a.name_lower)(v), dr_pop_$(a.name_lower)())`; `#endif`; } ================================================ FILE: src/draw/generated/draw.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v) {DR_StackPushImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind, v);} internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v) {DR_StackPushImpl(XForm2D, xform2d, Mat3x3F32, v);} internal Rng2F32 dr_push_clip(Rng2F32 v) {DR_StackPushImpl(Clip, clip, Rng2F32, v);} internal F32 dr_push_transparency(F32 v) {DR_StackPushImpl(Transparency, transparency, F32, v);} internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void) {DR_StackPopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);} internal Mat3x3F32 dr_pop_xform2d(void) {DR_StackPopImpl(XForm2D, xform2d, Mat3x3F32);} internal Rng2F32 dr_pop_clip(void) {DR_StackPopImpl(Clip, clip, Rng2F32);} internal F32 dr_pop_transparency(void) {DR_StackPopImpl(Transparency, transparency, F32);} internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void) {DR_StackTopImpl(Tex2DSampleKind, tex2d_sample_kind, R_Tex2DSampleKind);} internal Mat3x3F32 dr_top_xform2d(void) {DR_StackTopImpl(XForm2D, xform2d, Mat3x3F32);} internal Rng2F32 dr_top_clip(void) {DR_StackTopImpl(Clip, clip, Rng2F32);} internal F32 dr_top_transparency(void) {DR_StackTopImpl(Transparency, transparency, F32);} ================================================ FILE: src/draw/generated/draw.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef DRAW_META_H #define DRAW_META_H typedef struct DR_Tex2DSampleKindNode DR_Tex2DSampleKindNode; struct DR_Tex2DSampleKindNode {DR_Tex2DSampleKindNode *next; R_Tex2DSampleKind v;}; typedef struct DR_XForm2DNode DR_XForm2DNode; struct DR_XForm2DNode {DR_XForm2DNode *next; Mat3x3F32 v;}; typedef struct DR_ClipNode DR_ClipNode; struct DR_ClipNode {DR_ClipNode *next; Rng2F32 v;}; typedef struct DR_TransparencyNode DR_TransparencyNode; struct DR_TransparencyNode {DR_TransparencyNode *next; F32 v;}; #define DR_BucketStackDecls struct{\ DR_Tex2DSampleKindNode *top_tex2d_sample_kind;\ DR_XForm2DNode *top_xform2d;\ DR_ClipNode *top_clip;\ DR_TransparencyNode *top_transparency;\ } read_only global DR_Tex2DSampleKindNode dr_nil_tex2d_sample_kind = {0, R_Tex2DSampleKind_Nearest}; read_only global DR_XForm2DNode dr_nil_xform2d = {0, {1, 0, 0, 0, 1, 0, 0, 0, 1}}; read_only global DR_ClipNode dr_nil_clip = {0, {0}}; read_only global DR_TransparencyNode dr_nil_transparency = {0, 0}; #define DR_BucketStackInits(b) do{\ (b)->top_tex2d_sample_kind = &dr_nil_tex2d_sample_kind;\ (b)->top_xform2d = &dr_nil_xform2d;\ (b)->top_clip = &dr_nil_clip;\ (b)->top_transparency = &dr_nil_transparency;\ }while(0) #if 0 internal R_Tex2DSampleKind dr_push_tex2d_sample_kind(R_Tex2DSampleKind v); internal Mat3x3F32 dr_push_xform2d(Mat3x3F32 v); internal Rng2F32 dr_push_clip(Rng2F32 v); internal F32 dr_push_transparency(F32 v); internal R_Tex2DSampleKind dr_pop_tex2d_sample_kind(void); internal Mat3x3F32 dr_pop_xform2d(void); internal Rng2F32 dr_pop_clip(void); internal F32 dr_pop_transparency(void); internal R_Tex2DSampleKind dr_top_tex2d_sample_kind(void); internal Mat3x3F32 dr_top_xform2d(void); internal Rng2F32 dr_top_clip(void); internal F32 dr_top_transparency(void); #endif #if 0 #define DR_Tex2DSampleKindScope(v) DeferLoop(dr_push_tex2d_sample_kind(v), dr_pop_tex2d_sample_kind()) #define DR_XForm2DScope(v) DeferLoop(dr_push_xform2d(v), dr_pop_xform2d()) #define DR_ClipScope(v) DeferLoop(dr_push_clip(v), dr_pop_clip()) #define DR_TransparencyScope(v) DeferLoop(dr_push_transparency(v), dr_pop_transparency()) #endif #endif // DRAW_META_H ================================================ FILE: src/dwarf/dwarf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 dw_reg_size_from_code_x86(DW_Reg reg_code) { switch (reg_code) { #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX86_##reg_name_dw: return reg_size; DW_Regs_X86_XList(X) #undef X } return 0; } internal U64 dw_reg_pos_from_code_x86(DW_Reg reg_code) { switch (reg_code) { #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX86_##reg_name_dw: return reg_pos; DW_Regs_X86_XList(X) #undef X } return max_U64; } internal U64 dw_reg_size_from_code_x64(DW_Reg reg_code) { switch (reg_code) { #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_size; DW_Regs_X64_XList(X) #undef X } return 0; } internal U64 dw_reg_pos_from_code_x64(DW_Reg reg_code) { switch (reg_code) { #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_pos; DW_Regs_X64_XList(X) #undef X } return max_U64; } internal U64 dw_reg_size_from_code(Arch arch, DW_Reg reg_code) { switch (arch) { case Arch_Null: break; case Arch_x86: return dw_reg_size_from_code_x86(reg_code); case Arch_x64: return dw_reg_size_from_code_x64(reg_code); default: NotImplemented; break; } return 0; } internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code) { switch (arch) { case Arch_Null: break; case Arch_x86: return dw_reg_pos_from_code_x86(reg_code); case Arch_x64: return dw_reg_pos_from_code_x64(reg_code); default: NotImplemented; break; } return max_U64; } internal U64 dw_reg_count_from_arch(Arch arch) { switch (arch) { default: { NotImplemented; } // fall-through case Arch_Null: return 0; case Arch_x86: return DW_RegX86_Last; case Arch_x64: return DW_RegX64_Last; } } internal U64 dw_reg_max_size_from_arch(Arch arch) { local_persist U64 max_size = 0; if (max_size == 0) { U64 max_idx = dw_reg_count_from_arch(arch); for EachIndex(reg_idx, max_idx) { U64 reg_size = dw_reg_size_from_code(arch, reg_idx); max_size = Max(max_size, reg_size); } } return max_size; } internal U64 dw_sp_from_arch(Arch arch) { switch (arch) { default: NotImplemented; case Arch_Null: return 0; case Arch_x86: return DW_RegX86_Esp; case Arch_x64: return DW_RegX64_Rsp; } } internal DW_AttribClass dw_attrib_class_from_attrib_v2(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_V2_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_v3(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_V3_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_v4(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_V4_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_v5(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_V5_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_gnu(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_GNU_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_llvm(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_LLVM_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_apple(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_APPLE_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib_mips(DW_AttribKind k) { switch (k) { #define X(_N,_C) case DW_AttribKind_##_N: return _C; DW_AttribKind_ClassFlags_MIPS_XList(X) #undef X } return DW_AttribClass_Null; } internal DW_AttribClass dw_attrib_class_from_attrib(DW_Version ver, DW_Ext ext, DW_AttribKind k) { DW_AttribClass result = DW_AttribClass_Null; while (ext) { U64 z = 64-clz64(ext); if (z == 0) { break; } U64 flag = 1 << (z-1); ext &= ~flag; switch (flag) { case DW_Ext_Null: break; case DW_Ext_GNU: result = dw_attrib_class_from_attrib_gnu(k); break; case DW_Ext_LLVM: result = dw_attrib_class_from_attrib_llvm(k); break; case DW_Ext_APPLE: result = dw_attrib_class_from_attrib_apple(k); break; case DW_Ext_MIPS: result = dw_attrib_class_from_attrib_mips(k); break; default: InvalidPath; break; } if (result != DW_AttribClass_Null) { break; } } if (result == DW_AttribClass_Null) { switch (ver) { case DW_Version_Null: break; case DW_Version_1: AssertAlways(!"DWARF V1 is not supported"); break; case DW_Version_2: result = dw_attrib_class_from_attrib_v2(k); break; case DW_Version_3: result = dw_attrib_class_from_attrib_v3(k); break; case DW_Version_4: result = dw_attrib_class_from_attrib_v4(k); break; case DW_Version_5: result = dw_attrib_class_from_attrib_v5(k); break; default: InvalidPath; break; } } return result; } internal DW_AttribClass dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k) { #define X(_N,_C) case DW_Form_##_N: return _C; switch (k) { DW_Form_AttribClass_GNU_XList(X) } switch (ver) { case DW_Version_5: { switch (k) { DW_Form_AttribClass_V5_XList(X) } } break; case DW_Version_4: { switch (k) { DW_Form_AttribClass_V4_XList(X) } } break; case DW_Version_3: { switch (k) { DW_Form_AttribClass_V2_XList(X) } } break; case DW_Version_2: { switch (k) { DW_Form_AttribClass_V2_XList(X) } } break; case DW_Version_1: { } break; case DW_Version_Null: break; } #undef X return DW_AttribClass_Null; } internal B32 dw_are_attrib_class_and_form_kind_compatible(DW_Version ver, DW_AttribClass attrib_class, DW_FormKind form_kind) { DW_AttribClass compat_flags = dw_attrib_class_from_form_kind(ver, form_kind); B32 are_compat = (attrib_class & compat_flags) != 0; return are_compat; } internal String8 dw_name_string_from_section_kind(DW_SectionKind k) { String8 result = {0}; switch(k) { #define X(_N,_L,_M,_D) case DW_Section_##_N:{result = str8_lit(_L);}break; DW_SectionKind_XList(X) #undef X } return result; } internal String8 dw_mach_name_string_from_section_kind(DW_SectionKind k) { String8 result = {0}; switch(k) { #define X(_N,_L,_M,_D) case DW_Section_##_N:{result = str8_lit(_M);}break; DW_SectionKind_XList(X) #undef X } return result; } internal String8 dw_dwo_name_string_from_section_kind(DW_SectionKind k) { String8 result = {0}; switch(k) { #define X(_N,_L,_M,_D) case DW_Section_##_N:{result = str8_lit(_D);}break; DW_SectionKind_XList(X) #undef X } return result; } internal U64 dw_size_from_format(DW_Format format) { U64 result = 0; switch(format) { default:{}break; case DW_Format_32Bit: result = 4; break; case DW_Format_64Bit: result = 8; break; } return result; } internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, DW_AttribKind attrib_kind, DW_FormKind form_kind) { // NOTE(rjf): DWARF's spec specifies two mappings: // (DW_AttribKind) => List(DW_AttribClass) // (DW_FormKind) => List(DW_AttribClass) // // This function's purpose is to find the overlapping class between an // DW_AttribKind and DW_FormKind. DW_AttribClass attrib_class = dw_attrib_class_from_attrib(ver, ext, attrib_kind); DW_AttribClass form_class = dw_attrib_class_from_form_kind(ver, form_kind); if(attrib_class == DW_AttribClass_Null || form_class == DW_AttribClass_Null) { attrib_class = dw_attrib_class_from_attrib(DW_Version_Last, ext, attrib_kind); form_class = dw_attrib_class_from_form_kind(DW_Version_Last, form_kind); } DW_AttribClass result = DW_AttribClass_Null; if(attrib_class != DW_AttribClass_Null && form_class != DW_AttribClass_Null) { result = DW_AttribClass_Undefined; for(U32 i = 0; i < 32; ++i) { U32 n = 1u << i; if((attrib_class & n) != 0 && (form_class & n) != 0) { result = ((DW_AttribClass) n); break; } } } return result; } internal U64 dw_pick_default_lower_bound(DW_Language lang) { U64 lower_bound = max_U64; switch (lang) { case DW_Language_Null: break; case DW_Language_C89: case DW_Language_C: case DW_Language_CPlusPlus: case DW_Language_C99: case DW_Language_CPlusPlus03: case DW_Language_CPlusPlus11: case DW_Language_C11: case DW_Language_CPlusPlus14: case DW_Language_Java: case DW_Language_ObjC: case DW_Language_ObjCPlusPlus: case DW_Language_UPC: case DW_Language_D: case DW_Language_Python: case DW_Language_OpenCL: case DW_Language_Go: case DW_Language_Haskell: case DW_Language_OCaml: case DW_Language_Rust: case DW_Language_Swift: case DW_Language_Dylan: case DW_Language_RenderScript: case DW_Language_BLISS: lower_bound = 0; break; case DW_Language_Ada83: case DW_Language_Cobol74: case DW_Language_Cobol85: case DW_Language_Fortran77: case DW_Language_Fortran90: case DW_Language_Pascal83: case DW_Language_Modula2: case DW_Language_Ada95: case DW_Language_Fortran95: case DW_Language_PLI: case DW_Language_Modula3: case DW_Language_Julia: case DW_Language_Fortran03: case DW_Language_Fortran08: lower_bound = 1; default: NotImplemented; break; } return lower_bound; } internal U64 dw_operand_count_from_expr_op(DW_ExprOp op) { switch (op) { #define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _OPER_COUNT; DW_Expr_V3_XList(X) DW_Expr_V4_XList(X) DW_Expr_V5_XList(X) DW_Expr_GNU_XList(X) #undef X default: { NotImplemented; } break; } return 0; } internal U64 dw_pop_count_from_expr_op(DW_ExprOp op) { switch (op) { #define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _POP_COUNT; DW_Expr_V3_XList(X) DW_Expr_V4_XList(X) DW_Expr_V5_XList(X) DW_Expr_GNU_XList(X) #undef X default: { NotImplemented; } break; } return 0; } internal U64 dw_push_count_from_expr_op(DW_ExprOp op) { switch (op) { #define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _PUSH_COUNT; DW_Expr_V3_XList(X) DW_Expr_V4_XList(X) DW_Expr_V5_XList(X) DW_Expr_GNU_XList(X) #undef X default: { NotImplemented; } break; } return 0; } internal U64 dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode) { switch (opcode) { #define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; } DW_CFA_Kind_XList(X) #undef X default: { NotImplemented; } break; } return 0; } internal B32 dw_is_cfa_expr_opcode_invalid(DW_ExprOp opcode) { B32 is_invalid = 0; switch (opcode) { case DW_ExprOp_Addrx: case DW_ExprOp_Call2: case DW_ExprOp_Call4: case DW_ExprOp_CallRef: case DW_ExprOp_ConstType: case DW_ExprOp_Constx: case DW_ExprOp_Convert: case DW_ExprOp_DerefType: case DW_ExprOp_RegvalType: case DW_ExprOp_Reinterpret: case DW_ExprOp_PushObjectAddress: case DW_ExprOp_CallFrameCfa: { is_invalid = 1; } break; default: break; } return is_invalid; } internal B32 dw_is_new_row_cfa_opcode(DW_CFA_Opcode opcode) { B32 is_new_row_op = 0; switch (opcode) { case DW_CFA_SetLoc: case DW_CFA_AdvanceLoc: case DW_CFA_AdvanceLoc1: case DW_CFA_AdvanceLoc2: case DW_CFA_AdvanceLoc4: { is_new_row_op = 1; } break; default: break; } return is_new_row_op; } internal DW_CFA_OperandType * dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode) { switch (opcode) { #define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; } DW_CFA_Kind_XList(X) #undef X default: { NotImplemented; } break; } return 0; } //////////////////////////////// //~ rjf: String <=> Enum internal String8 dw_string_from_format(DW_Format format) { switch (format) { case DW_Format_Null: return str8_zero(); case DW_Format_32Bit: return str8_lit("DWARF32"); case DW_Format_64Bit: return str8_lit("DWARF64"); } return str8_zero(); } internal String8 dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op) { String8 result = {0}; #define X(_N,...) case DW_ExprOp_##_N: result = str8_lit(Stringify(_N)); goto exit; if (ext & DW_Ext_GNU) { switch (op) { DW_Expr_GNU_XList(X); } } switch (ver) { case DW_Version_5: { switch (op) { DW_Expr_V5_XList(X) } } // fall-through case DW_Version_4: { switch (op) { DW_Expr_V4_XList(X) } } // fall-through case DW_Version_3: case DW_Version_2: case DW_Version_1: { switch (op) { DW_Expr_V3_XList(X) } } // fall-through case DW_Version_Null: break; } #undef X result = push_str8f(arena, "%x", op); exit:; return result; } internal String8 dw_string_from_tag_kind(Arena *arena, DW_TagKind kind) { switch (kind) { case DW_TagKind_Null: return str8_lit("Null"); #define X(_N,_ID) case DW_TagKind_##_N: return str8_lit(Stringify(_N)); DW_TagKind_V3_XList(X) DW_TagKind_V5_XList(X) DW_TagKind_GNU_XList(X) #undef X } return push_str8f(arena, "%llx", kind); } internal String8 dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKind kind) { #define X(_N,...) case DW_AttribKind_##_N:{result = str8_lit(Stringify(_N));}break; String8 result = {0}; //- rjf: try extensions if(result.size != 0) { while(ext) { U64 z = 64-clz64(ext); if(z == 0) { break; } U64 flag = 1 << (z-1); ext &= ~flag; switch(flag) { default:{}break; case DW_Ext_Null: break; case DW_Ext_GNU: switch (kind) { DW_AttribKind_GNU_XList(X) } break; case DW_Ext_LLVM: switch (kind) { DW_AttribKind_LLVM_XList(X) } break; case DW_Ext_APPLE: switch (kind) { DW_AttribKind_APPLE_XList(X) } break; case DW_Ext_MIPS: switch (kind) { DW_AttribKind_MIPS_XList(X) } break; } } } //- rjf: try version if(result.size == 0) { for(U64 retry = 0; retry < 2; retry += 1) { DW_Version version = retry ? DW_Version_5 : ver; switch(version) { case DW_Version_5: { switch(kind) { DW_AttribKind_V5_XList(X) } } // fall-through case DW_Version_4: { switch(kind) { DW_AttribKind_V4_XList(X) } } // fall-through case DW_Version_3: { switch(kind) { DW_AttribKind_V3_XList(X) } } // fall-through case DW_Version_2: { switch(kind) { DW_AttribKind_V2_XList(X) } } // fall-through case DW_Version_1: {}break; case DW_Version_Null:{}break; default:{}break; } } } //- rjf: fallback if(result.size == 0) { result = push_str8f(arena, "#%u", kind); } #undef X return result; } internal String8 dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind) { #define X(_N,...) case DW_Form_##_N: return str8_lit(Stringify(_N)); switch (ver) { case DW_Version_5: { switch (kind) { DW_Form_V5_XList(X) } } // fall-through case DW_Version_4: { switch (kind) { DW_Form_V4_XList(X) } } // fall-through case DW_Version_3: case DW_Version_2: { switch (kind) { DW_Form_V2_XList(X) } } // fall-through case DW_Version_Null: break; } #undef X String8 result = push_str8f(arena, "%x", kind); return result; } internal String8 dw_string_from_language(Arena *arena, DW_Language kind) { switch (kind) { #define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N)); DW_Language_XList(X) #undef X } return push_str8f(arena, "%x", kind); } internal String8 dw_string_from_inl(Arena *arena, DW_InlKind kind) { switch (kind) { #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); DW_Inl_XList(X) #undef X } return push_str8f(arena, "%x", kind); } internal String8 dw_string_from_access_kind(Arena *arena, DW_AccessKind kind) { switch (kind) { #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); DW_AccessKind_XList(X) #undef X } return push_str8f(arena, "%llx", kind); } internal String8 dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind) { switch (kind) { #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); DW_CallingConventionKind_XList(X) #undef X } return push_str8f(arena, "%llx", kind); } internal String8 dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind) { switch (kind) { #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); DW_ATE_XList(X) #undef X } return push_str8f(arena, "%llx", kind); } internal String8 dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind) { switch (kind) { #define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N)); DW_StdOpcode_XList(X) #undef X } return push_str8f(arena, "%x", kind); } internal String8 dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind) { switch (kind) { #define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N)); DW_ExtOpcode_XList(X) #undef X default: InvalidPath; break; } return push_str8f(arena, "%x", kind); } internal String8 dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind) { NotImplemented; return str8_zero(); } internal String8 dw_string_from_section_kind(Arena *arena, DW_SectionKind kind) { NotImplemented; return str8_zero(); } internal String8 dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind) { NotImplemented; return str8_zero(); } internal String8 dw_string_from_register(Arena *arena, Arch arch, U64 reg_id) { String8 reg_str = str8_zero(); switch (arch) { case Arch_Null: break; case Arch_x86: { switch (reg_id) { #define X(_N, _ID, ...) case DW_RegX86_##_N: reg_str = str8_lit(Stringify(_N)); break; DW_Regs_X86_XList(X) #undef X } } break; case Arch_x64: { switch (reg_id) { #define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break; DW_Regs_X64_XList(X) #undef X } } break; case Arch_arm32: NotImplemented; break; case Arch_arm64: NotImplemented; break; default: InvalidPath; break; } if (reg_str.size == 0) { reg_str = push_str8f(arena, "%#llx", reg_id); } return reg_str; } internal String8 dw_string_from_cfa_opcode(DW_CFA_Opcode opcode) { switch (opcode) { #define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME)); DW_CFA_Kind_XList(X) #undef X default: InvalidPath; break; } return str8_zero(); } ================================================ FILE: src/dwarf/dwarf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_H #define DWARF_H typedef U16 DW_Version; typedef enum DW_VersionEnum { DW_Version_Null, DW_Version_1, DW_Version_2, DW_Version_3, DW_Version_4, DW_Version_5, DW_Version_Last = DW_Version_5 } DW_VersionEnum; typedef U64 DW_Ext; typedef enum DW_ExtEnum { DW_Ext_Null, DW_Ext_GNU = (1 << 0), DW_Ext_LLVM = (1 << 1), DW_Ext_APPLE = (1 << 2), DW_Ext_MIPS = (1 << 3), DW_Ext_All = DW_Ext_GNU|DW_Ext_LLVM|DW_Ext_APPLE|DW_Ext_MIPS, } DW_ExtEnum; #define DW_FormatFromSize(size) ((size) >= max_U32 ? DW_Format_64Bit : DW_Format_32Bit) typedef enum DW_Format { DW_Format_Null, DW_Format_32Bit, DW_Format_64Bit } DW_Format; #define DW_SentinelFromSize(address_size) ((address_size) == 4 ? max_U32 : (address_size) == 8 ? max_U64 : 0) #define DW_SectionKind_XList(X )\ X(Null, "", "", "" )\ X(Abbrev, ".debug_abbrev", "__debug_abbrev", ".debug_abbrev.dwo" )\ X(ARanges, ".debug_aranges", "__debug_aranges", ".debug_aranges.dwo" )\ X(Frame, ".debug_frame", "__debug_frame", ".debug_frame.dwo" )\ X(Info, ".debug_info", "__debug_info", ".debug_info.dwo" )\ X(Line, ".debug_line", "__debug_line", ".debug_line.dwo" )\ X(Loc, ".debug_loc", "__debug_loc", ".debug_loc.dwo" )\ X(MacInfo, ".debug_macinfo", "__debug_macinfo", ".debug_macinfo.dwo" )\ X(PubNames, ".debug_pubnames", "__debug_pubnames", ".debug_pubnames.dwo" )\ X(PubTypes, ".debug_pubtypes", "__debug_pubtypes", ".debug_pubtypes.dwo" )\ X(Ranges, ".debug_ranges", "__debug_ranges", ".debug_ranges.dwo" )\ X(Str, ".debug_str", "__debug_str", ".debug_str.dwo" )\ X(Addr, ".debug_addr", "__debug_addr", ".debug_addr.dwo" )\ X(LocLists, ".debug_loclists", "__debug_loclists", ".debug_loclists.dwo" )\ X(RngLists, ".debug_rnglists", "__debug_rnglists", ".debug_rnglists.dwo" )\ X(StrOffsets, ".debug_str_offsets", "__debug_str_offsets", ".debug_str_offsets.dwo")\ X(LineStr, ".debug_line_str", "__debug_line_str", ".debug_line_str.dwo" )\ X(Names, ".debug_names", "__debug_names", ".debug_names.dwo" ) typedef U64 DW_SectionKind; typedef enum DW_SectionKindEnum { #define X(_N,...) DW_Section_##_N, DW_SectionKind_XList(X) #undef X DW_Section_Count } DW_SectionKindEnum; #define DW_Language_XList(X) \ X(Null, 0x00) \ X(C89, 0x01) \ X(C, 0x02) \ X(Ada83, 0x03) \ X(CPlusPlus, 0x04) \ X(Cobol74, 0x05) \ X(Cobol85, 0x06) \ X(Fortran77, 0x07) \ X(Fortran90, 0x08) \ X(Pascal83, 0x09) \ X(Modula2, 0x0A) \ X(Java, 0x0B) \ X(C99, 0x0C) \ X(Ada95, 0x0D) \ X(Fortran95, 0x0E) \ X(PLI, 0x0F) \ X(ObjC, 0x10) \ X(ObjCPlusPlus, 0x11) \ X(UPC, 0x12) \ X(D, 0x13) \ X(Python, 0x14) \ X(OpenCL, 0x15) \ X(Go, 0x16) \ X(Modula3, 0x17) \ X(Haskell, 0x18) \ X(CPlusPlus03, 0x19) \ X(CPlusPlus11, 0x1a) \ X(OCaml, 0x1b) \ X(Rust, 0x1c) \ X(C11, 0x1d) \ X(Swift, 0x1e) \ X(Julia, 0x1f) \ X(Dylan, 0x20) \ X(CPlusPlus14, 0x21) \ X(Fortran03, 0x22) \ X(Fortran08, 0x23) \ X(RenderScript, 0x24) \ X(BLISS, 0x25) \ X(MipsAssembler, 0x8001) \ X(GoogleRenderScript, 0x8E57) \ X(SunAssembler, 0x9001) \ X(BorlandDelphi, 0xB000) typedef U32 DW_Language; typedef enum DW_LanguageEnum { #define X(_N, _ID) DW_Language_##_N = _ID, DW_Language_XList(X) #undef X DW_Language_UserLo = 0x8000, DW_Language_UserHi = 0xffff, } DW_LanguageEnum; #define DW_Inl_XList(X) \ X(NotInlined, 0) \ X(Inlined, 1) \ X(DeclaredNotInlined, 2) \ X(DeclaredInlined, 3) typedef U32 DW_InlKind; typedef enum DW_InlKindEnum { #define X(_N,_ID) DW_Inl_##_N = _ID, DW_Inl_XList(X) #undef X } DW_InlKindEnum; #define DW_StdOpcode_XList(X) \ X(ExtendedOpcode, 0x00) \ X(Copy, 0x01) \ X(AdvancePc, 0x02) \ X(AdvanceLine, 0x03) \ X(SetFile, 0x04) \ X(SetColumn, 0x05) \ X(NegateStmt, 0x06) \ X(SetBasicBlock, 0x07) \ X(ConstAddPc, 0x08) \ X(FixedAdvancePc, 0x09) \ X(SetPrologueEnd, 0x0A) \ X(SetEpilogueBegin, 0x0B) \ X(SetIsa, 0x0C) \ typedef enum DW_StdOpcode { #define X(_N,_ID) DW_StdOpcode_##_N = _ID, DW_StdOpcode_XList(X) #undef X } DW_StdOpcode; #define DW_ExtOpcode_XList(X) \ X(Undefined, 0x00) \ X(EndSequence, 0x01) \ X(SetAddress, 0x02) \ X(DefineFile, 0x03) \ X(SetDiscriminator, 0x04) \ X(UserLo, 0x80) \ X(UserHi, 0xff) typedef enum DW_ExtOpcode { #define X(_N,_ID) DW_ExtOpcode_##_N = _ID, DW_ExtOpcode_XList(X) #undef X } DW_ExtOpcode; #define DW_IDCaseKind_XList(X) \ X(CaseSensitive, 0x00) \ X(UpCase, 0x01) \ X(DownCase, 0x02) \ X(CaseInsensitive, 0x03) typedef U64 DW_IDCaseKind; typedef enum DW_IDCaseKindEnum { #define X(_N,_ID) DW_IDCase_##_N = _ID, DW_IDCaseKind_XList(X) #undef X } DW_IDCaseKindEnum; #define DW_TagKind_V3_XList(X) \ X(ArrayType, 0x01) \ X(ClassType, 0x02) \ X(EntryPoint, 0x03) \ X(EnumerationType, 0x04) \ X(FormalParameter, 0x05) \ X(ImportedDeclaration, 0x08) \ X(Label, 0x0a) \ X(LexicalBlock, 0x0b) \ X(Member, 0x0d) \ X(PointerType, 0x0f) \ X(ReferenceType, 0x10) \ X(CompileUnit, 0x11) \ X(StringType, 0x12) \ X(StructureType, 0x13) \ X(SubroutineType, 0x15) \ X(Typedef, 0x16) \ X(UnionType, 0x17) \ X(UnspecifiedParameters, 0x18) \ X(Variant, 0x19) \ X(CommonBlock, 0x1a) \ X(CommonInclusion, 0x1b) \ X(Inheritance, 0x1c) \ X(InlinedSubroutine, 0x1d) \ X(Module, 0x1e) \ X(PtrToMemberType, 0x1f) \ X(SetType, 0x20) \ X(SubrangeType, 0x21) \ X(WithStmt, 0x22) \ X(AccessDeclaration, 0x23) \ X(BaseType, 0x24) \ X(CatchBlock, 0x25) \ X(ConstType, 0x26) \ X(Constant, 0x27) \ X(Enumerator, 0x28) \ X(FileType, 0x29) \ X(Friend, 0x2a) \ X(NameList, 0x2b) \ X(NameListItem, 0x2c) \ X(PackedType, 0x2d) \ X(SubProgram, 0x2e) \ X(TemplateTypeParameter, 0x2f) \ X(TemplateValueParameter, 0x30) \ X(ThrownType, 0x31) \ X(TryBlock, 0x32) \ X(VariantPart, 0x33) \ X(Variable, 0x34) \ X(VolatileType, 0x35) \ X(DwarfProcedure, 0x36) \ X(RestrictType, 0x37) \ X(InterfaceType, 0x38) \ X(Namespace, 0x39) \ X(ImportedModule, 0x3a) \ X(UnspecifiedType, 0x3b) \ X(PartialUnit, 0x3c) \ X(ImportedUnit, 0x3d) \ X(Condition, 0x3f) \ X(SharedType, 0x40) #define DW_TagKind_V5_XList(X) \ X(TypeUnit, 0x41) \ X(RValueReferenceType, 0x42) \ X(TemplateAlias, 0x43) \ X(CoarrayType, 0x44) \ X(GenericSubrange, 0x45) \ X(DynamicType, 0x46) \ X(AtomicType, 0x47) \ X(CallSite, 0x48) \ X(CallSiteParameter, 0x49) \ X(SkeletonUnit, 0x4A) \ X(ImmutableType, 0x4B) #define DW_TagKind_GNU_XList(X) \ X(GNU_CallSite, 0x4109) \ X(GNU_CallSiteParameter, 0x410a) typedef U64 DW_TagKind; typedef enum DW_TagKindEnum { DW_TagKind_Null, #define X(_N,_ID) DW_TagKind_##_N = _ID, DW_TagKind_V3_XList(X) DW_TagKind_V5_XList(X) DW_TagKind_GNU_XList(X) #undef X DW_TagKind_UserLo = 0x4080, DW_TagKind_UserHi = 0xffff } DW_TagKindEnum; //- Attrib Class Encodings #define DW_AttribClass_V3_XList(X) \ X(Null, 0) \ X(Undefined, 1) \ X(Address, 2) \ X(Block, 3) \ X(Const, 4) \ X(ExprLoc, 5) \ X(Flag, 6) \ X(LinePtr, 7) \ X(LocListPtr, 8) \ X(MacPtr, 9) \ X(RngListPtr, 10) \ X(Reference, 11) \ X(String, 12) #define DW_AttribClass_V4_XList(X) \ X(LocList, 13) \ X(RngList, 14) #define DW_AttribClass_V5_XList(X) \ X(StrOffsetsPtr, 15) \ X(AddrPtr, 16) typedef U32 DW_AttribClass; typedef enum DW_AttribClassEnum { #define X(_N,_ID) DW_AttribClass_##_N = (1 << _ID), DW_AttribClass_V3_XList(X) DW_AttribClass_V4_XList(X) DW_AttribClass_V5_XList(X) #undef X } DW_AttribClassEnum; //- Form Encodings #define DW_Form_V2_XList(X) \ X(Addr, 0x1) \ X(Block2, 0x3) \ X(Block4, 0x4) \ X(Data2, 0x5) \ X(Data4, 0x6) \ X(Data8, 0x7) \ X(String, 0x8) \ X(Block, 0x9) \ X(Block1, 0xa) \ X(Data1, 0xb) \ X(Flag, 0xc) \ X(SData, 0xd) \ X(Strp, 0xe) \ X(UData, 0xf) \ X(RefAddr, 0x10) \ X(Ref1, 0x11) \ X(Ref2, 0x12) \ X(Ref4, 0x13) \ X(Ref8, 0x14) \ X(RefUData, 0x15) \ X(Indirect, 0x16) #define DW_Form_AttribClass_V2_XList(X) \ X(Addr, DW_AttribClass_Address) \ X(Block2, DW_AttribClass_Block) \ X(Block4, DW_AttribClass_Block) \ X(Data2, DW_AttribClass_Const) \ X(Data4, DW_AttribClass_Const) \ X(Data8, DW_AttribClass_Const) \ X(String, DW_AttribClass_String) \ X(Block, DW_AttribClass_Block) \ X(Block1, DW_AttribClass_Block) \ X(Data1, DW_AttribClass_Const) \ X(Flag, DW_AttribClass_Flag) \ X(SData, DW_AttribClass_Const) \ X(Strp, DW_AttribClass_String) \ X(UData, DW_AttribClass_Const) \ X(RefAddr, DW_AttribClass_Reference) \ X(Ref1, DW_AttribClass_Reference) \ X(Ref2, DW_AttribClass_Reference) \ X(Ref4, DW_AttribClass_Reference) \ X(Ref8, DW_AttribClass_Reference) \ X(RefUData, DW_AttribClass_Reference) \ X(Indirect, DW_AttribClass_Null) #define DW_Form_V4_XList(X) \ X(SecOffset, 0x17) \ X(ExprLoc, 0x18) \ X(FlagPresent, 0x19) \ X(RefSig8, 0x20) #define DW_Form_AttribClass_V4_XList(X) \ X(Addr, DW_AttribClass_Address) \ X(Block2, DW_AttribClass_Block) \ X(Block4, DW_AttribClass_Block) \ X(Data2, DW_AttribClass_Const) \ X(Data4, DW_AttribClass_Const) \ X(Data8, DW_AttribClass_Const) \ X(String, DW_AttribClass_String) \ X(Block, DW_AttribClass_Block) \ X(Block1, DW_AttribClass_Block) \ X(Data1, DW_AttribClass_Const) \ X(Flag, DW_AttribClass_Flag) \ X(SData, DW_AttribClass_Const) \ X(Strp, DW_AttribClass_String) \ X(UData, DW_AttribClass_Const) \ X(RefAddr, DW_AttribClass_Reference) \ X(Ref1, DW_AttribClass_Reference) \ X(Ref2, DW_AttribClass_Reference) \ X(Ref4, DW_AttribClass_Reference) \ X(Ref8, DW_AttribClass_Reference) \ X(RefUData, DW_AttribClass_Reference) \ X(Indirect, DW_AttribClass_Null) \ X(SecOffset, DW_AttribClass_LinePtr|DW_AttribClass_LocListPtr|DW_AttribClass_MacPtr|DW_AttribClass_RngListPtr) \ X(ExprLoc, DW_AttribClass_ExprLoc) \ X(FlagPresent, DW_AttribClass_Flag) \ X(RefSig8, DW_AttribClass_Reference) #define DW_Form_V5_XList(X) \ X(Strx, 0x1a) \ X(Addrx, 0x1b) \ X(RefSup4, 0x1c) \ X(StrpSup, 0x1d) \ X(Data16, 0x1e) \ X(LineStrp, 0x1f) \ X(ImplicitConst, 0x21) \ X(LocListx, 0x22) \ X(RngListx, 0x23) \ X(RefSup8, 0x24) \ X(Strx1, 0x25) \ X(Strx2, 0x26) \ X(Strx3, 0x27) \ X(Strx4, 0x28) \ X(Addrx1, 0x29) \ X(Addrx2, 0x2a) \ X(Addrx3, 0x2b) \ X(Addrx4, 0x2c) #define DW_Form_AttribClass_V5_XList(X) \ X(Addr, DW_AttribClass_Address) \ X(Block2, DW_AttribClass_Block) \ X(Block4, DW_AttribClass_Block) \ X(Data2, DW_AttribClass_Const) \ X(Data4, DW_AttribClass_Const) \ X(Data8, DW_AttribClass_Const) \ X(String, DW_AttribClass_String) \ X(Block, DW_AttribClass_Block) \ X(Block1, DW_AttribClass_Block) \ X(Data1, DW_AttribClass_Const) \ X(Flag, DW_AttribClass_Flag) \ X(SData, DW_AttribClass_Const) \ X(Strp, DW_AttribClass_String) \ X(UData, DW_AttribClass_Const) \ X(RefAddr, DW_AttribClass_Reference) \ X(Ref1, DW_AttribClass_Reference) \ X(Ref2, DW_AttribClass_Reference) \ X(Ref4, DW_AttribClass_Reference) \ X(Ref8, DW_AttribClass_Reference) \ X(RefUData, DW_AttribClass_Reference) \ X(Indirect, DW_AttribClass_Null) \ X(SecOffset, DW_AttribClass_AddrPtr| \ DW_AttribClass_LinePtr| \ DW_AttribClass_LocList| \ DW_AttribClass_LocListPtr| \ DW_AttribClass_MacPtr| \ DW_AttribClass_RngList| \ DW_AttribClass_RngListPtr| \ DW_AttribClass_StrOffsetsPtr) \ X(ExprLoc, DW_AttribClass_ExprLoc) \ X(FlagPresent, DW_AttribClass_Flag) \ X(RefSig8, DW_AttribClass_Reference) \ X(Strx, DW_AttribClass_String) \ X(Addrx, DW_AttribClass_Address) \ X(RefSup4, DW_AttribClass_Reference) \ X(StrpSup, DW_AttribClass_String) \ X(Data16, DW_AttribClass_Const) \ X(LineStrp, DW_AttribClass_String) \ X(ImplicitConst, DW_AttribClass_Const) \ X(LocListx, DW_AttribClass_LocListPtr) \ X(RngListx, DW_AttribClass_RngList) \ X(RefSup8, DW_AttribClass_Reference) \ X(Strx1, DW_AttribClass_String) \ X(Strx2, DW_AttribClass_String) \ X(Strx3, DW_AttribClass_String) \ X(Strx4, DW_AttribClass_String) \ X(Addrx1, DW_AttribClass_Address) \ X(Addrx2, DW_AttribClass_Address) \ X(Addrx3, DW_AttribClass_Address) \ X(Addrx4, DW_AttribClass_Address) #define DW_Form_GNU_XList(X) \ X(GNU_AddrIndex, 0x1f01) \ X(GNU_StrIndex, 0x1f02) \ X(GNU_RefAlt, 0x1f20) \ X(GNU_StrpAlt, 0x1f21) #define DW_Form_AttribClass_GNU_XList(X) \ X(GNU_AddrIndex, DW_AttribClass_Undefined) \ X(GNU_StrIndex, DW_AttribClass_Undefined) \ X(GNU_RefAlt, DW_AttribClass_Undefined) \ X(GNU_StrpAlt, DW_AttribClass_String) typedef U64 DW_FormKind; typedef enum DW_FormEnum { DW_Form_Null, #define X(_N, _ID) DW_Form_##_N = _ID, DW_Form_V2_XList(X) DW_Form_V4_XList(X) DW_Form_V5_XList(X) DW_Form_GNU_XList(X) #undef X } DW_FormEnum; //- Attributes DWARF2 #define DW_AttribKind_V2_XList(X) \ X(Sibling, 0x1) \ X(Location, 0x2) \ X(Name, 0x3) \ X(Ordering, 0x9) \ X(ByteSize, 0xB) \ X(BitOffset, 0xC) \ X(BitSize, 0xD) \ X(StmtList, 0x10) \ X(LowPc, 0x11) \ X(HighPc, 0x12) \ X(Language, 0x13) \ X(Discr, 0x15) \ X(DiscrValue, 0x16) \ X(Visibility, 0x17) \ X(Import, 0x18) \ X(StringLength, 0x19) \ X(CommonReference, 0x1a) \ X(CompDir, 0x1b) \ X(ConstValue, 0x1c) \ X(ContainingType, 0x1d) \ X(DefaultValue, 0x1e) \ X(Inline, 0x20) \ X(IsOptional, 0x21) \ X(LowerBound, 0x22) \ X(Producer, 0x25) \ X(Prototyped, 0x27) \ X(ReturnAddr, 0x2a) \ X(StartScope, 0x2c) \ X(BitStride, 0x2e) \ X(UpperBound, 0x2f) \ X(AbstractOrigin, 0x31) \ X(Accessibility, 0x32) \ X(AddressClass, 0x33) \ X(Artificial, 0x34) \ X(BaseTypes, 0x35) \ X(CallingConvention, 0x36) \ X(Count, 0x37) \ X(DataMemberLocation, 0x38) \ X(DeclColumn, 0x39) \ X(DeclFile, 0x3a) \ X(DeclLine, 0x3b) \ X(Declaration, 0x3c) \ X(DiscrList, 0x3d) \ X(Encoding, 0x3e) \ X(External, 0x3f) \ X(FrameBase, 0x40) \ X(Friend, 0x41) \ X(IdentifierCase, 0x42) \ X(MacroInfo, 0x43) \ X(NameListItem, 0x44) \ X(Priority, 0x45) \ X(Segment, 0x46) \ X(Specification, 0x47) \ X(StaticLink, 0x48) \ X(Type, 0x49) \ X(UseLocation, 0x4a) \ X(VariableParameter, 0x4b) \ X(Virtuality, 0x4c) \ X(VTableElemLocation, 0x4d) #define DW_AttribKind_ClassFlags_V2_XList(X) \ X(Sibling, DW_AttribClass_Reference) \ X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Name, DW_AttribClass_String) \ X(Ordering, DW_AttribClass_Const) \ X(ByteSize, DW_AttribClass_Const) \ X(BitOffset, DW_AttribClass_Const) \ X(BitSize, DW_AttribClass_Const) \ X(StmtList, DW_AttribClass_Const) \ X(LowPc, DW_AttribClass_Address) \ X(HighPc, DW_AttribClass_Address) \ X(Language, DW_AttribClass_Const) \ X(Discr, DW_AttribClass_Reference) \ X(DiscrValue, DW_AttribClass_Const) \ X(Visibility, DW_AttribClass_Const) \ X(Import, DW_AttribClass_Reference) \ X(StringLength, DW_AttribClass_Block|DW_AttribClass_Const) \ X(CommonReference, DW_AttribClass_Reference) \ X(CompDir, DW_AttribClass_String) \ X(ConstValue, DW_AttribClass_String|DW_AttribClass_Const|DW_AttribClass_Block) \ X(ContainingType, DW_AttribClass_Reference) \ X(DefaultValue, DW_AttribClass_Reference) \ X(Inline, DW_AttribClass_Const) \ X(IsOptional, DW_AttribClass_Flag) \ X(LowerBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ X(Producer, DW_AttribClass_String) \ X(Prototyped, DW_AttribClass_Flag) \ X(ReturnAddr, DW_AttribClass_Block|DW_AttribClass_Const) \ X(StartScope, DW_AttribClass_Const) \ X(BitStride, DW_AttribClass_Const) /* dwarf-v1 DW_AttribKind_stride_size*/ \ X(UpperBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ X(AbstractOrigin, DW_AttribClass_Reference) \ X(Accessibility, DW_AttribClass_Const) \ X(AddressClass, DW_AttribClass_Const) \ X(Artificial, DW_AttribClass_Flag) \ X(BaseTypes, DW_AttribClass_Reference) \ X(CallingConvention, DW_AttribClass_Const) \ X(Count, DW_AttribClass_Const|DW_AttribClass_Reference) \ X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Reference) \ X(DeclColumn, DW_AttribClass_Const) \ X(DeclFile, DW_AttribClass_Const) \ X(DeclLine, DW_AttribClass_Const) \ X(Declaration, DW_AttribClass_Flag) \ X(DiscrList, DW_AttribClass_Block) \ X(Encoding, DW_AttribClass_Const) \ X(External, DW_AttribClass_Flag) \ X(FrameBase, DW_AttribClass_Block|DW_AttribClass_Const) \ X(Friend, DW_AttribClass_Reference) \ X(IdentifierCase, DW_AttribClass_Const) \ X(MacroInfo, DW_AttribClass_Const) \ X(NameListItem, DW_AttribClass_Block) \ X(Priority, DW_AttribClass_Reference) \ X(Segment, DW_AttribClass_Block|DW_AttribClass_Const) \ X(Specification, DW_AttribClass_Reference) \ X(StaticLink, DW_AttribClass_Block|DW_AttribClass_Const) \ X(Type, DW_AttribClass_Reference) \ X(UseLocation, DW_AttribClass_Block|DW_AttribClass_Const) \ X(VariableParameter, DW_AttribClass_Flag) \ X(Virtuality, DW_AttribClass_Const) \ X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_Reference) //- Attributes DWARF3 #define DW_AttribKind_V3_XList(X) \ X(Allocated, 0x4e) \ X(Associated, 0x4f) \ X(DataLocation, 0x50) \ X(ByteStride, 0x51) \ X(EntryPc, 0x52) \ X(UseUtf8, 0x53) \ X(Extension, 0x54) \ X(Ranges, 0x55) \ X(Trampoline, 0x56) \ X(CallColumn, 0x57) \ X(CallFile, 0x58) \ X(CallLine, 0x59) \ X(Description, 0x5a) \ X(BinaryScale, 0x5b) \ X(DecimalScale, 0x5c) \ X(Small, 0x5d) \ X(DecimalSign, 0x5e) \ X(DigitCount, 0x5f) \ X(PictureString, 0x60) \ X(Mutable, 0x61) \ X(ThreadsScaled, 0x62) \ X(Explicit, 0x63) \ X(ObjectPointer, 0x64) \ X(Endianity, 0x65) \ X(Elemental, 0x66) \ X(Pure, 0x67) \ X(Recursive, 0x68) #define DW_AttribKind_ClassFlags_V3_XList(X) \ X(Sibling, DW_AttribClass_Reference) \ X(Location, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(Name, DW_AttribClass_String) \ X(Ordering, DW_AttribClass_Const) \ X(ByteSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(BitOffset, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(BitSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(StmtList, DW_AttribClass_LinePtr) \ X(LowPc, DW_AttribClass_Address) \ X(HighPc, DW_AttribClass_Address) \ X(Language, DW_AttribClass_Const) \ X(Discr, DW_AttribClass_Reference) \ X(DiscrValue, DW_AttribClass_Const) \ X(Visibility, DW_AttribClass_Const) \ X(Import, DW_AttribClass_Reference) \ X(StringLength, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(CommonReference, DW_AttribClass_Reference) \ X(CompDir, DW_AttribClass_String) \ X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ X(ContainingType, DW_AttribClass_Reference) \ X(DefaultValue, DW_AttribClass_Reference) \ X(Inline, DW_AttribClass_Const) \ X(IsOptional, DW_AttribClass_Flag) \ X(LowerBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(Producer, DW_AttribClass_String) \ X(Prototyped, DW_AttribClass_Flag) \ X(ReturnAddr, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(StartScope, DW_AttribClass_Const) \ X(BitStride, DW_AttribClass_Const) \ X(UpperBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(AbstractOrigin, DW_AttribClass_Reference) \ X(Accessibility, DW_AttribClass_Const) \ X(AddressClass, DW_AttribClass_Const) \ X(Artificial, DW_AttribClass_Flag) \ X(BaseTypes, DW_AttribClass_Reference) \ X(CallingConvention, DW_AttribClass_Const) \ X(Count, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_LocListPtr) \ X(DeclColumn, DW_AttribClass_Const) \ X(DeclFile, DW_AttribClass_Const) \ X(DeclLine, DW_AttribClass_Const) \ X(Declaration, DW_AttribClass_Flag) \ X(DiscrList, DW_AttribClass_Block) \ X(Encoding, DW_AttribClass_Const) \ X(External, DW_AttribClass_Flag) \ X(FrameBase, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(Friend, DW_AttribClass_Reference) \ X(IdentifierCase, DW_AttribClass_Const) \ X(MacroInfo, DW_AttribClass_MacPtr) \ X(NameListItem, DW_AttribClass_Block) \ X(Priority, DW_AttribClass_Reference) \ X(Segment, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(Specification, DW_AttribClass_Reference) \ X(StaticLink, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(Type, DW_AttribClass_Reference) \ X(UseLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(VariableParameter, DW_AttribClass_Flag) \ X(Virtuality, DW_AttribClass_Const) \ X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ X(Allocated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(Associated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(DataLocation, DW_AttribClass_Block) \ X(ByteStride, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ X(EntryPc, DW_AttribClass_Address) \ X(UseUtf8, DW_AttribClass_Flag) \ X(Extension, DW_AttribClass_Reference) \ X(Ranges, DW_AttribClass_RngListPtr) \ X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ X(CallColumn, DW_AttribClass_Const) \ X(CallFile, DW_AttribClass_Const) \ X(CallLine, DW_AttribClass_Const) \ X(Description, DW_AttribClass_String) \ X(BinaryScale, DW_AttribClass_Const) \ X(DecimalScale, DW_AttribClass_Const) \ X(Small, DW_AttribClass_Reference) \ X(DecimalSign, DW_AttribClass_Const) \ X(DigitCount, DW_AttribClass_Const) \ X(PictureString, DW_AttribClass_String) \ X(Mutable, DW_AttribClass_Flag) \ X(ThreadsScaled, DW_AttribClass_Flag) \ X(Explicit, DW_AttribClass_Flag) \ X(ObjectPointer, DW_AttribClass_Reference) \ X(Endianity, DW_AttribClass_Const) \ X(Elemental, DW_AttribClass_Flag) \ X(Pure, DW_AttribClass_Flag) \ X(Recursive, DW_AttribClass_Flag) //- Attributes DWARF4 #define DW_AttribKind_V4_XList(X) \ X(Signature, 0x69) \ X(MainSubProgram, 0x6a) \ X(DataBitOffset, 0x6b) \ X(ConstExpr, 0x6c) \ X(EnumClass, 0x6d) \ X(LinkageName, 0x6e) #define DW_AttribKind_ClassFlags_V4_XList(X) \ X(Sibling, DW_AttribClass_Reference) \ X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Name, DW_AttribClass_String) \ X(Ordering, DW_AttribClass_Const) \ X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(StmtList, DW_AttribClass_LinePtr) \ X(LowPc, DW_AttribClass_Address) \ X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ X(Language, DW_AttribClass_Const) \ X(Discr, DW_AttribClass_Reference) \ X(DiscrValue, DW_AttribClass_Const) \ X(Visibility, DW_AttribClass_Const) \ X(Import, DW_AttribClass_Reference) \ X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(CommonReference, DW_AttribClass_Reference) \ X(CompDir, DW_AttribClass_String) \ X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ X(ContainingType, DW_AttribClass_Reference) \ X(DefaultValue, DW_AttribClass_Reference) \ X(Inline, DW_AttribClass_Const) \ X(IsOptional, DW_AttribClass_Flag) \ X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(Producer, DW_AttribClass_String) \ X(Prototyped, DW_AttribClass_Flag) \ X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(AbstractOrigin, DW_AttribClass_Reference) \ X(Accessibility, DW_AttribClass_Const) \ X(AddressClass, DW_AttribClass_Const) \ X(Artificial, DW_AttribClass_Flag) \ X(BaseTypes, DW_AttribClass_Reference) \ X(CallingConvention, DW_AttribClass_Const) \ X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(DeclColumn, DW_AttribClass_Const) \ X(DeclFile, DW_AttribClass_Const) \ X(DeclLine, DW_AttribClass_Const) \ X(Declaration, DW_AttribClass_Flag) \ X(DiscrList, DW_AttribClass_Block) \ X(Encoding, DW_AttribClass_Const) \ X(External, DW_AttribClass_Flag) \ X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Friend, DW_AttribClass_Reference) \ X(IdentifierCase, DW_AttribClass_Const) \ X(MacroInfo, DW_AttribClass_MacPtr) \ X(NameListItem, DW_AttribClass_Reference) \ X(Priority, DW_AttribClass_Reference) \ X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Specification, DW_AttribClass_Reference) \ X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Type, DW_AttribClass_Reference) \ X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(VariableParameter, DW_AttribClass_Flag) \ X(Virtuality, DW_AttribClass_Const) \ X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(DataLocation, DW_AttribClass_ExprLoc) \ X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(EntryPc, DW_AttribClass_Address) \ X(UseUtf8, DW_AttribClass_Flag) \ X(Extension, DW_AttribClass_Reference) \ X(Ranges, DW_AttribClass_RngListPtr) \ X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ X(CallColumn, DW_AttribClass_Const) \ X(CallFile, DW_AttribClass_Const) \ X(CallLine, DW_AttribClass_Const) \ X(Description, DW_AttribClass_String) \ X(BinaryScale, DW_AttribClass_Const) \ X(DecimalScale, DW_AttribClass_Const) \ X(Small, DW_AttribClass_Reference) \ X(DecimalSign, DW_AttribClass_Const) \ X(DigitCount, DW_AttribClass_Const) \ X(PictureString, DW_AttribClass_String) \ X(Mutable, DW_AttribClass_Flag) \ X(ThreadsScaled, DW_AttribClass_Flag) \ X(Explicit, DW_AttribClass_Flag) \ X(ObjectPointer, DW_AttribClass_Reference) \ X(Endianity, DW_AttribClass_Const) \ X(Elemental, DW_AttribClass_Flag) \ X(Pure, DW_AttribClass_Flag) \ X(Recursive, DW_AttribClass_Flag) \ X(Signature, DW_AttribClass_Reference) \ X(MainSubProgram, DW_AttribClass_Flag) \ X(DataBitOffset, DW_AttribClass_Const) \ X(ConstExpr, DW_AttribClass_Flag) \ X(EnumClass, DW_AttribClass_Flag) \ X(LinkageName, DW_AttribClass_String) //- Attributes DWARF5 #define DW_AttribKind_V5_XList(X) \ X(StringLengthBitSize, 0x6f) \ X(StringLengthByteSize, 0x70) \ X(Rank, 0x71) \ X(StrOffsetsBase, 0x72) \ X(AddrBase, 0x73) \ X(RngListsBase, 0x74) \ X(DwoName, 0x76) \ X(Reference, 0x77) \ X(RValueReference, 0x78) \ X(Macros, 0x79) \ X(CallAllCalls, 0x7a) \ X(CallAllSourceCalls, 0x7b) \ X(CallAllTailCalls, 0x7c) \ X(CallReturnPc, 0x7d) \ X(CallValue, 0x7e) \ X(CallOrigin, 0x7f) \ X(CallParameter, 0x80) \ X(CallPc, 0x81) \ X(CallTailCall, 0x82) \ X(CallTarget, 0x83) \ X(CallTargetClobbered, 0x84) \ X(CallDataLocation, 0x85) \ X(CallDataValue, 0x86) \ X(NoReturn, 0x87) \ X(Alignment, 0x88) \ X(ExportSymbols, 0x89) \ X(Deleted, 0x8a) \ X(Defaulted, 0x8b) \ X(LocListsBase, 0x8c) #define DW_AttribKind_ClassFlags_V5_XList(X) \ X(Sibling, DW_AttribClass_Reference) \ X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(Name, DW_AttribClass_String) \ X(Ordering, DW_AttribClass_Const) \ X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(StmtList, DW_AttribClass_LinePtr) \ X(LowPc, DW_AttribClass_Address) \ X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ X(Language, DW_AttribClass_Const) \ X(Discr, DW_AttribClass_Reference) \ X(DiscrValue, DW_AttribClass_Const) \ X(Visibility, DW_AttribClass_Const) \ X(Import, DW_AttribClass_Reference) \ X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(CommonReference, DW_AttribClass_Reference) \ X(CompDir, DW_AttribClass_String) \ X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ X(ContainingType, DW_AttribClass_Reference) \ X(DefaultValue, DW_AttribClass_Reference) \ X(Inline, DW_AttribClass_Const) \ X(IsOptional, DW_AttribClass_Flag) \ X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(Producer, DW_AttribClass_String) \ X(Prototyped, DW_AttribClass_Flag) \ X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(AbstractOrigin, DW_AttribClass_Reference) \ X(Accessibility, DW_AttribClass_Const) \ X(AddressClass, DW_AttribClass_Const) \ X(Artificial, DW_AttribClass_Flag) \ X(BaseTypes, DW_AttribClass_Reference) \ X(CallingConvention, DW_AttribClass_Const) \ X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(DeclColumn, DW_AttribClass_Const) \ X(DeclFile, DW_AttribClass_Const) \ X(DeclLine, DW_AttribClass_Const) \ X(Declaration, DW_AttribClass_Flag) \ X(DiscrList, DW_AttribClass_Block) \ X(Encoding, DW_AttribClass_Const) \ X(External, DW_AttribClass_Flag) \ X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(Friend, DW_AttribClass_Reference) \ X(IdentifierCase, DW_AttribClass_Const) \ X(MacroInfo, DW_AttribClass_MacPtr) \ X(NameListItem, DW_AttribClass_Reference) \ X(Priority, DW_AttribClass_Reference) \ X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(Specification, DW_AttribClass_Reference) \ X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(Type, DW_AttribClass_Reference) \ X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(VariableParameter, DW_AttribClass_Flag) \ X(Virtuality, DW_AttribClass_Const) \ X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(DataLocation, DW_AttribClass_ExprLoc) \ X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ X(EntryPc, DW_AttribClass_Address|DW_AttribClass_Const) \ X(UseUtf8, DW_AttribClass_Flag) \ X(Extension, DW_AttribClass_Reference) \ X(Ranges, DW_AttribClass_RngList) \ X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ X(CallColumn, DW_AttribClass_Const) \ X(CallFile, DW_AttribClass_Const) \ X(CallLine, DW_AttribClass_Const) \ X(Description, DW_AttribClass_String) \ X(BinaryScale, DW_AttribClass_Const) \ X(DecimalScale, DW_AttribClass_Const) \ X(Small, DW_AttribClass_Reference) \ X(DecimalSign, DW_AttribClass_Const) \ X(DigitCount, DW_AttribClass_Const) \ X(PictureString, DW_AttribClass_String) \ X(Mutable, DW_AttribClass_Flag) \ X(ThreadsScaled, DW_AttribClass_Flag) \ X(Explicit, DW_AttribClass_Flag) \ X(ObjectPointer, DW_AttribClass_Reference) \ X(Endianity, DW_AttribClass_Const) \ X(Elemental, DW_AttribClass_Flag) \ X(Pure, DW_AttribClass_Flag) \ X(Recursive, DW_AttribClass_Flag) \ X(Signature, DW_AttribClass_Reference) \ X(MainSubProgram, DW_AttribClass_Flag) \ X(DataBitOffset, DW_AttribClass_Const) \ X(ConstExpr, DW_AttribClass_Flag) \ X(EnumClass, DW_AttribClass_Flag) \ X(LinkageName, DW_AttribClass_String) \ X(StringLengthBitSize, DW_AttribClass_Const) \ X(StringLengthByteSize, DW_AttribClass_Const) \ X(Rank, DW_AttribClass_Const|DW_AttribClass_ExprLoc) \ X(StrOffsetsBase, DW_AttribClass_StrOffsetsPtr) \ X(AddrBase, DW_AttribClass_AddrPtr) \ X(RngListsBase, DW_AttribClass_RngListPtr) \ X(DwoName, DW_AttribClass_String) \ X(Reference, DW_AttribClass_Flag) \ X(RValueReference, DW_AttribClass_Flag) \ X(Macros, DW_AttribClass_MacPtr) \ X(CallAllCalls, DW_AttribClass_Flag) \ X(CallAllSourceCalls, DW_AttribClass_Flag) \ X(CallAllTailCalls, DW_AttribClass_Flag) \ X(CallReturnPc, DW_AttribClass_Address) \ X(CallValue, DW_AttribClass_ExprLoc) \ X(CallOrigin, DW_AttribClass_ExprLoc) \ X(CallParameter, DW_AttribClass_Reference) \ X(CallPc, DW_AttribClass_Address) \ X(CallTailCall, DW_AttribClass_Flag) \ X(CallTarget, DW_AttribClass_ExprLoc) \ X(CallTargetClobbered, DW_AttribClass_ExprLoc) \ X(CallDataLocation, DW_AttribClass_ExprLoc) \ X(CallDataValue, DW_AttribClass_ExprLoc) \ X(NoReturn, DW_AttribClass_Flag) \ X(Alignment, DW_AttribClass_Const) \ X(ExportSymbols, DW_AttribClass_Flag) \ X(Deleted, DW_AttribClass_Flag) \ X(Defaulted, DW_AttribClass_Const) \ X(LocListsBase, DW_AttribClass_LocListPtr) //- Attributes GNU #define DW_AttribKind_GNU_XList(X) \ X(GNU_Vector, 0x2107) \ X(GNU_GuardedBy, 0x2108) \ X(GNU_PtGuardedBy, 0x2109) \ X(GNU_Guarded, 0x210a) \ X(GNU_PtGuarded, 0x210b) \ X(GNU_LocksExcluded, 0x210c) \ X(GNU_ExclusiveLocksRequired, 0x210d) \ X(GNU_SharedLocksRequired, 0x210e) \ X(GNU_OdrSignature, 0x210f) \ X(GNU_TemplateName, 0x2110) \ X(GNU_CallSiteValue, 0x2111) \ X(GNU_CallSiteDataValue, 0x2112) \ X(GNU_CallSiteTarget, 0x2113) \ X(GNU_CallSiteTargetClobbered, 0x2114) \ X(GNU_TailCall, 0x2115) \ X(GNU_AllTailCallsSites, 0x2116) \ X(GNU_AllCallSites, 0x2117) \ X(GNU_AllSourceCallSites, 0x2118) \ X(GNU_Macros, 0x2119) \ X(GNU_Deleted, 0x211a) \ X(GNU_DwoName, 0x2130) \ X(GNU_DwoId, 0x2131) \ X(GNU_RangesBase, 0x2132) \ X(GNU_AddrBase, 0x2133) \ X(GNU_PubNames, 0x2134) \ X(GNU_PubTypes, 0x2135) \ X(GNU_Discriminator, 0x2136) \ X(GNU_LocViews, 0x2137) \ X(GNU_EntryView, 0x2138) \ X(GNU_DescriptiveType, 0x2302) \ X(GNU_Numerator, 0x2303) \ X(GNU_Denominator, 0x2304) \ X(GNU_Bias, 0x2305) #define DW_AttribKind_ClassFlags_GNU_XList(X) \ X(GNU_Vector, DW_AttribClass_Flag) \ X(GNU_GuardedBy, DW_AttribClass_Undefined) \ X(GNU_PtGuardedBy, DW_AttribClass_Undefined) \ X(GNU_Guarded, DW_AttribClass_Undefined) \ X(GNU_PtGuarded, DW_AttribClass_Undefined) \ X(GNU_LocksExcluded, DW_AttribClass_Undefined) \ X(GNU_ExclusiveLocksRequired, DW_AttribClass_Undefined) \ X(GNU_SharedLocksRequired, DW_AttribClass_Undefined) \ X(GNU_OdrSignature, DW_AttribClass_Undefined) \ X(GNU_TemplateName, DW_AttribClass_Undefined) \ X(GNU_CallSiteValue, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteDataValue, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteTarget, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteTargetClobbered, DW_AttribClass_ExprLoc) \ X(GNU_TailCall, DW_AttribClass_Flag) \ X(GNU_AllTailCallsSites, DW_AttribClass_Flag) \ X(GNU_AllCallSites, DW_AttribClass_Flag) \ X(GNU_AllSourceCallSites, DW_AttribClass_Flag) \ X(GNU_Macros, DW_AttribClass_Flag) \ X(GNU_Deleted, DW_AttribClass_Undefined) \ X(GNU_DwoName, DW_AttribClass_String) \ X(GNU_DwoId, DW_AttribClass_Const) \ X(GNU_RangesBase, DW_AttribClass_Undefined) \ X(GNU_AddrBase, DW_AttribClass_AddrPtr) \ X(GNU_PubNames, DW_AttribClass_Flag) \ X(GNU_PubTypes, DW_AttribClass_Undefined) \ X(GNU_Discriminator, DW_AttribClass_Const) \ X(GNU_LocViews, DW_AttribClass_Undefined) \ X(GNU_EntryView, DW_AttribClass_Undefined) \ X(GNU_DescriptiveType, DW_AttribClass_Undefined) \ X(GNU_Numerator, DW_AttribClass_Undefined) \ X(GNU_Denominator, DW_AttribClass_Undefined) \ X(GNU_Bias, DW_AttribClass_Undefined) //- Attributes LLVM #define DW_AttribKind_LLVM_XList(X) \ X(LLVM_IncludePath, 0x3e00) \ X(LLVM_ConfigMacros, 0x3e01) \ X(LLVM_SysRoot, 0x3e02) \ X(LLVM_TagOffset, 0x3e03) \ X(LLVM_ApiNotes, 0x3e07) #define DW_AttribKind_ClassFlags_LLVM_XList(X) \ X(LLVM_IncludePath, DW_AttribClass_String) \ X(LLVM_ConfigMacros, DW_AttribClass_String) \ X(LLVM_SysRoot, DW_AttribClass_String) \ X(LLVM_TagOffset, DW_AttribClass_Undefined) \ X(LLVM_ApiNotes, DW_AttribClass_String) //- Attributes Apple #define DW_AttribKind_APPLE_XList(X) \ X(APPLE_Optimized, 0x3fe1) \ X(APPLE_Flags, 0x3fe2) \ X(APPLE_Isa, 0x3fe3) \ X(APPLE_Block, 0x3fe4) \ X(APPLE_MajorRuntimeVers, 0x3fe5) \ X(APPLE_RuntimeClass, 0x3fe6) \ X(APPLE_OmitFramePtr, 0x3fe7) \ X(APPLE_PropertyName, 0x3fe8) \ X(APPLE_PropertyGetter, 0x3fe9) \ X(APPLE_PropertySetter, 0x3fea) \ X(APPLE_PropertyAttribute, 0x3feb) \ X(APPLE_ObjcCompleteType, 0x3fec) \ X(APPLE_Property, 0x3fed) \ X(APPLE_ObjDirect, 0x3fee) \ X(APPLE_Sdk, 0x3fef) #define DW_AttribKind_ClassFlags_APPLE_XList(X) \ X(APPLE_Optimized, DW_AttribClass_Flag) \ X(APPLE_Flags, DW_AttribClass_Flag) \ X(APPLE_Isa, DW_AttribClass_Flag) \ X(APPLE_Block, DW_AttribClass_Undefined) \ X(APPLE_MajorRuntimeVers, DW_AttribClass_Undefined) \ X(APPLE_RuntimeClass, DW_AttribClass_Undefined) \ X(APPLE_OmitFramePtr, DW_AttribClass_Flag) \ X(APPLE_PropertyName, DW_AttribClass_Undefined) \ X(APPLE_PropertyGetter, DW_AttribClass_Undefined) \ X(APPLE_PropertySetter, DW_AttribClass_Undefined) \ X(APPLE_PropertyAttribute, DW_AttribClass_Undefined) \ X(APPLE_ObjcCompleteType, DW_AttribClass_Undefined) \ X(APPLE_Property, DW_AttribClass_Undefined) \ X(APPLE_ObjDirect, DW_AttribClass_Undefined) \ X(APPLE_Sdk, DW_AttribClass_String) //- Attributes MIPS #define DW_AttribKind_MIPS_XList(X) \ X(MIPS_Fde, 0x2001) \ X(MIPS_LoopBegin, 0x2002) \ X(MIPS_TailLoopBegin, 0x2003) \ X(MIPS_EpilogBegin, 0x2004) \ X(MIPS_LoopUnrollFactor, 0x2005) \ X(MIPS_SoftwarePipelineDepth, 0x2006) \ X(MIPS_LinkageName, 0x2007) \ X(MIPS_Stride, 0x2008) \ X(MIPS_AbstractName, 0x2009) \ X(MIPS_CloneOrigin, 0x200a) \ X(MIPS_HasInlines, 0x200b) \ X(MIPS_StrideByte, 0x200c) \ X(MIPS_StrideElem, 0x200d) \ X(MIPS_PtrDopeType, 0x200e) \ X(MIPS_AllocatableDopeType, 0x200f) \ X(MIPS_AssumedShapeDopeType, 0x2010) \ X(MIPS_AssumedSize, 0x2011) #define DW_AttribKind_ClassFlags_MIPS_XList(X) \ X(MIPS_Fde, DW_AttribClass_Block) \ X(MIPS_LoopBegin, DW_AttribClass_Block) \ X(MIPS_TailLoopBegin, DW_AttribClass_Block) \ X(MIPS_EpilogBegin, DW_AttribClass_Block) \ X(MIPS_LoopUnrollFactor, DW_AttribClass_Block) \ X(MIPS_SoftwarePipelineDepth, DW_AttribClass_Block) \ X(MIPS_LinkageName, DW_AttribClass_String) \ X(MIPS_Stride, DW_AttribClass_Block) \ X(MIPS_AbstractName, DW_AttribClass_String) \ X(MIPS_CloneOrigin, DW_AttribClass_String) \ X(MIPS_HasInlines, DW_AttribClass_Reference) \ X(MIPS_StrideByte, DW_AttribClass_Reference) \ X(MIPS_StrideElem, DW_AttribClass_Reference) \ X(MIPS_PtrDopeType, DW_AttribClass_Reference) \ X(MIPS_AllocatableDopeType, DW_AttribClass_Reference) \ X(MIPS_AssumedShapeDopeType, DW_AttribClass_Reference) \ X(MIPS_AssumedSize, DW_AttribClass_Reference) typedef U32 DW_AttribKind; typedef enum DW_AttribKindEnum { DW_AttribKind_Null, #define X(_N,_ID,...) DW_AttribKind_##_N = _ID, DW_AttribKind_V2_XList(X) DW_AttribKind_V3_XList(X) DW_AttribKind_V4_XList(X) DW_AttribKind_V5_XList(X) DW_AttribKind_GNU_XList(X) DW_AttribKind_LLVM_XList(X) DW_AttribKind_APPLE_XList(X) DW_AttribKind_MIPS_XList(X) #undef X DW_AttribKind_UserLo = 0x2000, DW_AttribKind_UserHi = 0x3fff } DW_AttribKindEnum; #define DW_ATE_XList(X) \ X(Null, 0x00) \ X(Address, 0x01) \ X(Boolean, 0x02) \ X(ComplexFloat, 0x03) \ X(Float, 0x04) \ X(Signed, 0x05) \ X(SignedChar, 0x06) \ X(Unsigned, 0x07) \ X(UnsignedChar, 0x08) \ X(ImaginaryFloat, 0x09) \ X(PackedDecimal, 0x0A) \ X(NumericString, 0x0B) \ X(Edited, 0x0C) \ X(SignedFixed, 0x0D) \ X(UnsignedFixed, 0x0E) \ X(DecimalFloat, 0x0F) \ X(Utf, 0x10) \ X(Ucs, 0x11) \ X(Ascii, 0x12) typedef U64 DW_ATE; typedef enum DW_ATEEnum { #define X(_N,_ID) DW_ATE_##_N = _ID, DW_ATE_XList(X) #undef X } DW_ATEnum; #define DW_CallingConventionKind_XList(X) \ X(Normal, 0x0) \ X(Program, 0x1) \ X(NoCall, 0x3) \ X(PassByValue, 0x4) \ X(PassByReference, 0x5) typedef U64 DW_CallingConventionKind; typedef enum DW_CallingConventionKindEnum { #define X(_N,_ID) DW_CallingConventionKind_##_N = _ID, DW_CallingConventionKind_XList(X) #undef X } DW_CallingConventionKindEnum; #define DW_AccessKind_XList(X) \ X(Public, 0x00) \ X(Private, 0x01) \ X(Protected, 0x02) typedef U64 DW_AccessKind; typedef enum DW_AccessKindEnum { #define X(_N,_ID) DW_AccessKind_##_N = _ID, DW_AccessKind_XList(X) #undef X } DW_AccessKindEnum; #define DW_VirtualityKind_XList(X) \ X(None, 0x00) \ X(Virtual, 0x01) \ X(PureVirtual, 0x02) typedef U64 DW_VirtualityKind; typedef enum DW_VirtualityEnum { #define X(_N,_ID) DW_VirtualityKind_##_N = _ID, DW_VirtualityKind_XList(X) #undef X } DW_VirtualityEnum; #define DW_RngListEntryKind(X) \ X(EndOfList, 0x00) \ X(BaseAddressx, 0x01) \ X(StartxEndx, 0x02) \ X(StartxLength, 0x03) \ X(OffsetPair, 0x04) \ X(BaseAddress, 0x05) \ X(StartEnd, 0x06) \ X(StartLength, 0x07) typedef U8 DW_RLE; typedef enum DW_RLE_Enum { #define X(_N,_ID) DW_RLE_##_N = _ID, DW_RngListEntryKind(X) #undef X } DW_RLE_Enum; #define DW_LocListEntry_XList(X) \ X(EndOfList, 0x00) \ X(BaseAddressx, 0x01) \ X(StartxEndx, 0x02) \ X(StartxLength, 0x03) \ X(OffsetPair, 0x04) \ X(DefaultLocation, 0x05) \ X(BaseAddress, 0x06) \ X(StartEnd, 0x07) \ X(StartLength, 0x08) #define DW_LocListEntry_GNU_XList(X) \ X(GNU_ViewPair, 0x9) typedef U8 DW_LLE; typedef enum DW_LLE_Enum { #define X(_N,_ID) DW_LLE_##_N = _ID, DW_LocListEntry_XList(X) #undef X } DW_LLEEnum; #define DW_AddrClass_XList(X) \ X(None, 0) \ X(Near16, 1) \ X(Far16, 2) \ X(Huge16, 3) \ X(Near32, 4) \ X(Far32, 5) typedef U64 DW_AddrClass; typedef enum DW_AddrClassEnum { #define X(_N, _ID) DW_AddrClassKind_##_N = _ID, DW_AddrClass_XList(X) #undef X } DW_AddrClassEnum; #define DW_CompUnitKind_XList(X) \ X(Reserved, 0) \ X(Compile, 1) \ X(Type, 2) \ X(Partial, 3) \ X(Skeleton, 4) \ X(SplitCompile, 5) \ X(SplitType, 6) typedef U8 DW_CompUnitKind; typedef enum DW_CompUnitKindEnum { #define X(_N, _ID) DW_CompUnitKind_##_N = _ID, DW_CompUnitKind_XList(X) #undef X DW_CompUnitKind_UserLo = 0x80, DW_CompUnitKind_UserHi = 0xff } DW_CompUnitKindEnum; #define DW_LNCT_XList(X) \ X(Path, 0x1) \ X(DirectoryIndex, 0x2) \ X(TimeStamp, 0x3) \ X(Size, 0x4) \ X(MD5, 0x5) \ X(LLVM_Source, 0x2001) typedef U64 DW_LNCT; typedef enum DW_LNCTEnum { #define X(_N, _ID) DW_LNCT_##_N = _ID, DW_LNCT_XList(X) #undef X DW_LNCT_UserLo = 0x2000, DW_LNCT_UserHi = 0x3fff } DW_LNCTEnum; //////////////////////////////// // CFA typedef enum { DW_CFA_OperandType_Null, DW_CFA_OperandType_Value, DW_CFA_OperandType_Register, DW_CFA_OperandType_Expression, } DW_CFA_OperandType; // (opcode name, opcode id, operand count, operand types) #define DW_CFA_Kind_XList(X) \ X(Nop, 0x0) \ X(SetLoc, 0x1, DW_CFA_OperandType_Value) \ X(AdvanceLoc1, 0x2, DW_CFA_OperandType_Value) \ X(AdvanceLoc2, 0x3, DW_CFA_OperandType_Value) \ X(AdvanceLoc4, 0x4, DW_CFA_OperandType_Value) \ X(OffsetExt, 0x5, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(RestoreExt, 0x6) \ X(Undefined, 0x7, DW_CFA_OperandType_Register) \ X(SameValue, 0x8, DW_CFA_OperandType_Register) \ X(Register, 0x9, DW_CFA_OperandType_Register) \ X(RememberState, 0xa) \ X(RestoreState, 0xb) \ X(DefCfa, 0xc, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(DefCfaRegister, 0xd, DW_CFA_OperandType_Register) \ X(DefCfaOffset, 0xe, DW_CFA_OperandType_Value) \ X(DefCfaExpr, 0xf, DW_CFA_OperandType_Expression) \ X(Expr, 0x10, DW_CFA_OperandType_Expression) \ X(OffsetExtSf, 0x11, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(DefCfaSf, 0x12, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(DefCfaOffsetSf, 0x13, DW_CFA_OperandType_Value) \ X(ValOffset, 0x14, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(ValOffsetSf, 0x15, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(ValExpr, 0x16, DW_CFA_OperandType_Register, DW_CFA_OperandType_Expression) \ X(AdvanceLoc, 0x40, DW_CFA_OperandType_Value) \ X(Offset, 0x80, DW_CFA_OperandType_Register, DW_CFA_OperandType_Value) \ X(Restore, 0xc0, DW_CFA_OperandType_Register) #define DW_CFA_OperandMax 2 #define DW_CFA_Mask_OpcodeHi 0xc0 #define DW_CFA_Mask_Operand 0x3f typedef U8 DW_CFA_Opcode; typedef enum DW_CFA_Enum { #define X(_N, _ID, ...) DW_CFA_##_N = _ID, DW_CFA_Kind_XList(X) #undef X } DW_CFA_Enum; //////////////////////////////// // Expression Opcodes // (opcode name, opcode id, operand count, pop count, push count) #define DW_Expr_V3_XList(X) \ X(Null, 0x00, 0, 0, 0) \ X(Addr, 0x03, 1, 0, 1) \ X(Deref, 0x06, 0, 1, 1) \ X(Const1U, 0x08, 1, 0, 1) \ X(Const1S, 0x09, 1, 0, 1) \ X(Const2U, 0x0a, 1, 0, 1) \ X(Const2S, 0x0b, 1, 0, 1) \ X(Const4U, 0x0c, 1, 0, 1) \ X(Const4S, 0x0d, 1, 0, 1) \ X(Const8U, 0x0e, 1, 0, 1) \ X(Const8S, 0x0f, 1, 0, 1) \ X(ConstU, 0x10, 1, 0, 1) \ X(ConstS, 0x11, 1, 0, 1) \ X(Dup, 0x12, 0, 0, 1) \ X(Drop, 0x13, 0, 1, 0) \ X(Over, 0x14, 0, 0, 1) \ X(Pick, 0x15, 1, 0, 1) \ X(Swap, 0x16, 0, 0, 0) \ X(Rot, 0x17, 0, 0, 0) \ X(XDeref, 0x18, 0, 2, 1) \ X(Abs, 0x19, 0, 1, 1) \ X(And, 0x1a, 0, 2, 1) \ X(Div, 0x1b, 0, 2, 1) \ X(Minus, 0x1c, 0, 2, 1) \ X(Mod, 0x1d, 0, 2, 1) \ X(Mul, 0x1e, 0, 2, 1) \ X(Neg, 0x1f, 0, 1, 1) \ X(Not, 0x20, 0, 1, 1) \ X(Or, 0x21, 0, 2, 1) \ X(Plus, 0x22, 0, 2, 1) \ X(PlusUConst, 0x23, 1, 1, 1) \ X(Shl, 0x24, 0, 2, 1) \ X(Shr, 0x25, 0, 2, 1) \ X(Shra, 0x26, 0, 2, 1) \ X(Xor, 0x27, 0, 2, 1) \ X(Bra, 0x28, 1, 1, 0) \ X(Eq, 0x29, 0, 2, 1) \ X(Ge, 0x2a, 0, 2, 1) \ X(Gt, 0x2b, 0, 2, 1) \ X(Le, 0x2c, 0, 2, 1) \ X(Lt, 0x2d, 0, 2, 1) \ X(Ne, 0x2e, 0, 2, 1) \ X(Skip, 0x2f, 1, 0, 0) \ X(Lit0, 0x30, 0, 0, 0) \ X(Lit1, 0x31, 0, 0, 0) \ X(Lit2, 0x32, 0, 0, 0) \ X(Lit3, 0x33, 0, 0, 0) \ X(Lit4, 0x34, 0, 0, 0) \ X(Lit5, 0x35, 0, 0, 0) \ X(Lit6, 0x36, 0, 0, 0) \ X(Lit7, 0x37, 0, 0, 0) \ X(Lit8, 0x38, 0, 0, 0) \ X(Lit9, 0x39, 0, 0, 0) \ X(Lit10, 0x3a, 0, 0, 0) \ X(Lit11, 0x3b, 0, 0, 0) \ X(Lit12, 0x3c, 0, 0, 0) \ X(Lit13, 0x3d, 0, 0, 0) \ X(Lit14, 0x3e, 0, 0, 0) \ X(Lit15, 0x3f, 0, 0, 0) \ X(Lit16, 0x40, 0, 0, 0) \ X(Lit17, 0x41, 0, 0, 0) \ X(Lit18, 0x42, 0, 0, 0) \ X(Lit19, 0x43, 0, 0, 0) \ X(Lit20, 0x44, 0, 0, 0) \ X(Lit21, 0x45, 0, 0, 0) \ X(Lit22, 0x46, 0, 0, 0) \ X(Lit23, 0x47, 0, 0, 0) \ X(Lit24, 0x48, 0, 0, 0) \ X(Lit25, 0x49, 0, 0, 0) \ X(Lit26, 0x4a, 0, 0, 0) \ X(Lit27, 0x4b, 0, 0, 0) \ X(Lit28, 0x4c, 0, 0, 0) \ X(Lit29, 0x4d, 0, 0, 0) \ X(Lit30, 0x4e, 0, 0, 0) \ X(Lit31, 0x4f, 0, 0, 0) \ X(Reg0, 0x50, 0, 0, 1) \ X(Reg1, 0x51, 0, 0, 1) \ X(Reg2, 0x52, 0, 0, 1) \ X(Reg3, 0x53, 0, 0, 1) \ X(Reg4, 0x54, 0, 0, 1) \ X(Reg5, 0x55, 0, 0, 1) \ X(Reg6, 0x56, 0, 0, 1) \ X(Reg7, 0x57, 0, 0, 1) \ X(Reg8, 0x58, 0, 0, 1) \ X(Reg9, 0x59, 0, 0, 1) \ X(Reg10, 0x5a, 0, 0, 1) \ X(Reg11, 0x5b, 0, 0, 1) \ X(Reg12, 0x5c, 0, 0, 1) \ X(Reg13, 0x5d, 0, 0, 1) \ X(Reg14, 0x5e, 0, 0, 1) \ X(Reg15, 0x5f, 0, 0, 1) \ X(Reg16, 0x60, 0, 0, 1) \ X(Reg17, 0x61, 0, 0, 1) \ X(Reg18, 0x62, 0, 0, 1) \ X(Reg19, 0x63, 0, 0, 1) \ X(Reg20, 0x64, 0, 0, 1) \ X(Reg21, 0x65, 0, 0, 1) \ X(Reg22, 0x66, 0, 0, 1) \ X(Reg23, 0x67, 0, 0, 1) \ X(Reg24, 0x68, 0, 0, 1) \ X(Reg25, 0x69, 0, 0, 1) \ X(Reg26, 0x6a, 0, 0, 1) \ X(Reg27, 0x6b, 0, 0, 1) \ X(Reg28, 0x6c, 0, 0, 1) \ X(Reg29, 0x6d, 0, 0, 1) \ X(Reg30, 0x6e, 0, 0, 1) \ X(Reg31, 0x6f, 0, 0, 1) \ X(BReg0, 0x70, 1, 0, 1) \ X(BReg1, 0x71, 1, 0, 1) \ X(BReg2, 0x72, 1, 0, 1) \ X(BReg3, 0x73, 1, 0, 1) \ X(BReg4, 0x74, 1, 0, 1) \ X(BReg5, 0x75, 1, 0, 1) \ X(BReg6, 0x76, 1, 0, 1) \ X(BReg7, 0x77, 1, 0, 1) \ X(BReg8, 0x78, 1, 0, 1) \ X(BReg9, 0x79, 1, 0, 1) \ X(BReg10, 0x7a, 1, 0, 1) \ X(BReg11, 0x7b, 1, 0, 1) \ X(BReg12, 0x7c, 1, 0, 1) \ X(BReg13, 0x7d, 1, 0, 1) \ X(BReg14, 0x7e, 1, 0, 1) \ X(BReg15, 0x7f, 1, 0, 1) \ X(BReg16, 0x80, 1, 0, 1) \ X(BReg17, 0x81, 1, 0, 1) \ X(BReg18, 0x82, 1, 0, 1) \ X(BReg19, 0x83, 1, 0, 1) \ X(BReg20, 0x84, 1, 0, 1) \ X(BReg21, 0x85, 1, 0, 1) \ X(BReg22, 0x86, 1, 0, 1) \ X(BReg23, 0x87, 1, 0, 1) \ X(BReg24, 0x88, 1, 0, 1) \ X(BReg25, 0x89, 1, 0, 1) \ X(BReg26, 0x8a, 1, 0, 1) \ X(BReg27, 0x8b, 1, 0, 1) \ X(BReg28, 0x8c, 1, 0, 1) \ X(BReg29, 0x8d, 1, 0, 1) \ X(BReg30, 0x8e, 1, 0, 1) \ X(BReg31, 0x8f, 1, 0, 1) \ X(RegX, 0x90, 1, 0, 1) \ X(FBReg, 0x91, 1, 0, 1) \ X(BRegX, 0x92, 2, 0, 1) \ X(Piece, 0x93, 1, 0, 0) \ X(DerefSize, 0x94, 1, 1, 1) \ X(XDerefSize, 0x95, 1, 2, 1) \ X(Nop, 0x96, 0, 0, 0) \ X(PushObjectAddress, 0x97, 0, 0, 1) \ X(Call2, 0x98, 1, 0, 0) \ X(Call4, 0x99, 1, 0, 0) \ X(CallRef, 0x9a, 1, 0, 0) \ X(FormTlsAddress, 0x9b, 0, 0, 1) \ X(CallFrameCfa, 0x9c, 0, 0, 1) \ X(BitPiece, 0x9d, 2, 0, 0) #define DW_Expr_V4_XList(X) \ X(ImplicitValue, 0x9e, 2, 0, 1) \ X(StackValue, 0x9f, 0, 0, 0) #define DW_Expr_V5_XList(X) \ X(ImplicitPointer, 0xa0, 2, 0, 1) \ X(Addrx, 0xa1, 1, 0, 1) \ X(Constx, 0xa2, 1, 0, 1) \ X(EntryValue, 0xa3, 2, 0, 0) \ X(ConstType, 0xa4, 3, 0, 1) \ X(RegvalType, 0xa5, 2, 0, 1) \ X(DerefType, 0xa6, 2, 1, 1) \ X(XDerefType, 0xa7, 2, 2, 1) \ X(Convert, 0xa8, 1, 1, 1) \ X(Reinterpret, 0xa9, 1, 1, 1) #define DW_Expr_GNU_XList(X) \ X(GNU_PushTlsAddress, 0xe0, 0, 0, 1) \ X(GNU_UnInit, 0xf0, 0, 0, 0) \ X(GNU_ImplicitPointer, 0xf2, 2, 0, 1) \ X(GNU_EntryValue, 0xf3, 2, 0, 0) \ X(GNU_ConstType, 0xf4, 3, 0, 1) \ X(GNU_RegvalType, 0xf5, 2, 0, 1) \ X(GNU_DerefType, 0xf6, 2, 1, 1) \ X(GNU_Convert, 0xf7, 1, 1, 1) \ X(GNU_ParameterRef, 0xfa, 1, 0, 0) \ X(GNU_AddrIndex, 0xfb, 0, 0, 1) \ X(GNU_ConstIndex, 0xfc, 1, 0, 1) typedef U8 DW_ExprOp; typedef enum DW_ExprOpEnum { #define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) DW_ExprOp_##_N = _ID, DW_Expr_V3_XList(X) DW_Expr_V4_XList(X) DW_Expr_V5_XList(X) DW_Expr_GNU_XList(X) #undef X } DW_ExprOpEnum; //- Regs #define DW_Regs_X86_XList(X) \ X(Eax, 0, eax, 0, 4) \ X(Ecx, 1, ecx, 0, 4) \ X(Edx, 2, edx, 0, 4) \ X(Ebx, 3, ebx, 0, 4) \ X(Esp, 4, esp, 0, 4) \ X(Ebp, 5, ebp, 0, 4) \ X(Esi, 6, esi, 0, 4) \ X(Edi, 7, edi, 0, 4) \ X(Eip, 8, eip, 0, 4) \ X(Eflags, 9, eflags, 0, 4) \ X(Trapno, 10, nil, 0, 0) \ X(St0, 11, st0, 0, 10) \ X(St1, 12, st1, 0, 10) \ X(St2, 13, st2, 0, 10) \ X(St3, 14, st3, 0, 10) \ X(St4, 15, st4, 0, 10) \ X(St5, 16, st5, 0, 10) \ X(St6, 17, st6, 0, 10) \ X(St7, 18, st7, 0, 10) \ X(Xmm0, 21, ymm0, 0, 16) \ X(Xmm1, 22, ymm1, 0, 16) \ X(Xmm2, 23, ymm2, 0, 16) \ X(Xmm3, 24, ymm3, 0, 16) \ X(Xmm4, 25, ymm4, 0, 16) \ X(Xmm5, 26, ymm5, 0, 16) \ X(Xmm6, 27, ymm6, 0, 16) \ X(Xmm7, 28, ymm7, 0, 16) \ X(Mm0, 29, fpr0, 0, 8) \ X(Mm1, 30, fpr1, 0, 8) \ X(Mm2, 31, fpr2, 0, 8) \ X(Mm3, 32, fpr3, 0, 8) \ X(Mm4, 33, fpr4, 0, 8) \ X(Mm5, 34, fpr5, 0, 8) \ X(Mm6, 35, fpr6, 0, 8) \ X(Mm7, 36, fpr7, 0, 8) \ X(Fcw, 37, fcw, 0, 2) \ X(Fsw, 38, fsw, 0, 2) \ X(Mxcsr, 39, mxcsr, 0, 4) \ X(Es, 40, es, 0, 2) \ X(Cs, 41, cs, 0, 2) \ X(Ss, 42, ss, 0, 2) \ X(Ds, 43, ds, 0, 2) \ X(Fs, 44, fs, 0, 2) \ X(Gs, 45, gs, 0, 2) \ X(Tr, 48, tr, 0, 0) \ X(Ldtr, 49, ldtr, 0, 0) #define DW_Regs_X64_XList(X) \ X(Rax, 0, rax, 0, 8) \ X(Rdx, 1, rdx, 0, 8) \ X(Rcx, 2, rcx, 0, 8) \ X(Rbx, 3, rbx, 0, 8) \ X(Rsi, 4, rsi, 0, 8) \ X(Rdi, 5, rdi, 0, 8) \ X(Rbp, 6, rbp, 0, 8) \ X(Rsp, 7, rsp, 0, 8) \ X(R8, 8, r8, 0, 8) \ X(R9, 9, r9, 0, 8) \ X(R10, 10, r10, 0, 8) \ X(R11, 11, r11, 0, 8) \ X(R12, 12, r12, 0, 8) \ X(R13, 13, r13, 0, 8) \ X(R14, 14, r14, 0, 8) \ X(R15, 15, r15, 0, 8) \ X(Rip, 16, rip, 0, 8) \ X(Xmm0, 17, zmm0, 0, 16) \ X(Xmm1, 18, zmm1, 0, 16) \ X(Xmm2, 19, zmm2, 0, 16) \ X(Xmm3, 20, zmm3, 0, 16) \ X(Xmm4, 21, zmm4, 0, 16) \ X(Xmm5, 22, zmm5, 0, 16) \ X(Xmm6, 23, zmm6, 0, 16) \ X(Xmm7, 24, zmm7, 0, 16) \ X(Xmm8, 25, zmm8, 0, 16) \ X(Xmm9, 26, zmm9, 0, 16) \ X(Xmm10, 27, zmm10, 0, 16) \ X(Xmm11, 28, zmm11, 0, 16) \ X(Xmm12, 29, zmm12, 0, 16) \ X(Xmm13, 30, zmm13, 0, 16) \ X(Xmm14, 31, zmm14, 0, 16) \ X(Xmm15, 32, zmm15, 0, 16) \ X(Xmm16, 67, zmm16, 0, 16) \ X(Xmm17, 68, zmm17, 0, 16) \ X(Xmm18, 69, zmm18, 0, 16) \ X(Xmm19, 70, zmm19, 0, 16) \ X(Xmm20, 71, zmm20, 0, 16) \ X(Xmm21, 72, zmm21, 0, 16) \ X(Xmm22, 73, zmm22, 0, 16) \ X(Xmm23, 74, zmm23, 0, 16) \ X(Xmm24, 75, zmm24, 0, 16) \ X(Xmm25, 76, zmm25, 0, 16) \ X(Xmm26, 77, zmm26, 0, 16) \ X(Xmm27, 78, zmm27, 0, 16) \ X(Xmm28, 79, zmm28, 0, 16) \ X(Xmm29, 80, zmm29, 0, 16) \ X(Xmm30, 81, zmm30, 0, 16) \ X(Xmm31, 82, zmm31, 0, 16) \ X(St0, 33, st0, 0, 10) \ X(St1, 34, st1, 0, 10) \ X(St2, 35, st2, 0, 10) \ X(St3, 36, st3, 0, 10) \ X(St4, 37, st4, 0, 10) \ X(St5, 38, st5, 0, 10) \ X(St6, 39, st6, 0, 10) \ X(St7, 40, st7, 0, 10) \ X(Mm0, 41, fpr0, 0, 8) \ X(Mm1, 42, fpr1, 0, 8) \ X(Mm2, 43, fpr2, 0, 8) \ X(Mm3, 44, fpr3, 0, 8) \ X(Mm4, 45, fpr4, 0, 8) \ X(Mm5, 46, fpr5, 0, 8) \ X(Mm6, 47, fpr6, 0, 8) \ X(Mm7, 48, fpr7, 0, 8) \ X(Rflags, 49, rflags, 0, 4) \ X(Es, 50, es, 0, 2) \ X(Cs, 51, cs, 0, 2) \ X(Ss, 52, ss, 0, 2) \ X(Ds, 53, ds, 0, 2) \ X(Fs, 54, fs, 0, 2) \ X(Gs, 55, gs, 0, 2) \ X(FsBase, 58, fsbase, 0, 0) \ X(GsBase, 59, gsbase, 0, 0) \ X(Tr, 62, tr, 0, 0) \ X(Ldtr, 63, ldtr, 0, 0) typedef U32 DW_Reg; typedef DW_Reg DW_RegX86; typedef enum DW_RegX86Enum { #define X(_N,_ID,...) DW_RegX86_##_N = _ID, DW_Regs_X86_XList(X) #undef X DW_RegX86_Last } DW_RegX86Enum; typedef DW_Reg DW_RegX64; typedef enum DW_RegX64Enum { #define X(_N,_ID,...) DW_RegX64_##_N = _ID, DW_Regs_X64_XList(X) #undef X DW_RegX64_Last } DW_RegX64Enum; //////////////////////////////// internal U64 dw_reg_size_from_code_x86(DW_Reg reg_code); internal U64 dw_reg_pos_from_code_x86(DW_Reg reg_code); internal U64 dw_reg_size_from_code_x64(DW_Reg reg_code); internal U64 dw_reg_pos_from_code_x64(DW_Reg reg_code); internal U64 dw_reg_size_from_code(Arch arch, DW_Reg reg_code); internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code); internal U64 dw_reg_count_from_arch(Arch arch); internal U64 dw_reg_max_size_from_arch(Arch arch); internal U64 dw_sp_from_arch(Arch arch); //- Attrib Class Encodings // Speced Encodings internal DW_AttribClass dw_attrib_class_from_attrib_v2(DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_v3(DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_v4(DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_v5(DW_AttribKind k); // Extensions internal DW_AttribClass dw_attrib_class_from_attrib_gnu (DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_llvm (DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_apple(DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib_mips (DW_AttribKind k); internal DW_AttribClass dw_attrib_class_from_attrib(DW_Version ver, DW_Ext ext, DW_AttribKind v); //- Form Class Encodings internal DW_AttribClass dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k); internal B32 dw_are_attrib_class_and_form_kind_compatible(DW_Version ver, DW_AttribClass attrib_class, DW_FormKind form_kind); //- Section Names internal String8 dw_name_string_from_section_kind (DW_SectionKind k); internal String8 dw_mach_name_string_from_section_kind(DW_SectionKind k); internal String8 dw_dwo_name_string_from_section_kind (DW_SectionKind k); //////////////////////////////// internal U64 dw_size_from_format(DW_Format format); //////////////////////////////// internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, DW_AttribKind attrib, DW_FormKind form_kind); internal U64 dw_pick_default_lower_bound(DW_Language lang); internal U64 dw_operand_count_from_expr_op(DW_ExprOp op); internal U64 dw_pop_count_from_expr_op(DW_ExprOp op); internal U64 dw_push_count_from_expr_op(DW_ExprOp op); //////////////////////////////// //~ CFA internal U64 dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode); internal B32 dw_is_cfa_expr_opcode_invalid(DW_ExprOp opcode); internal B32 dw_is_new_row_cfa_opcode(DW_CFA_Opcode opcode); internal DW_CFA_OperandType * dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode); //////////////////////////////// //~ rjf: String <=> Enum internal String8 dw_string_from_format(DW_Format format); internal String8 dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op); internal String8 dw_string_from_tag_kind(Arena *arena, DW_TagKind kind); internal String8 dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKind kind); internal String8 dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind); internal String8 dw_string_from_language(Arena *arena, DW_Language kind); internal String8 dw_string_from_inl(Arena *arena, DW_InlKind kind); internal String8 dw_string_from_access_kind(Arena *arena, DW_AccessKind kind); internal String8 dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind); internal String8 dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind); internal String8 dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind); internal String8 dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind); internal String8 dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind); internal String8 dw_string_from_section_kind(Arena *arena, DW_SectionKind kind); internal String8 dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind); internal String8 dw_string_from_register(Arena *arena, Arch arch, U64 reg_id); internal String8 dw_string_from_cfa_opcode(DW_CFA_Opcode opcode); #endif // DWARF_H ================================================ FILE: src/dwarf/dwarf_coff.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 dw_is_dwarf_present_coff_section_table(String8 string_table, U64 section_count, COFF_SectionHeader *section_table) { B32 is_dwarf_present = 0; for EachIndex(idx, section_count) { COFF_SectionHeader *header = §ion_table[idx]; String8 name = coff_name_from_section_header(string_table, header); DW_SectionKind s = dw_section_kind_from_string(name); if(s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); } is_dwarf_present = s != DW_Section_Null; if(is_dwarf_present) { break; } } return is_dwarf_present; } internal DW_Input dw_input_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table) { DW_Input input = {0}; B32 sect_status[ArrayCount(input.sec)] = {0}; for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ion_table[i]; Rng1U64 raw_data_range = rng_1u64(header->foff, header->foff + header->fsize); String8 name = coff_name_from_section_header(string_table, header); DW_SectionKind s = dw_section_kind_from_string(name); B32 is_dwo = 0; if (s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); is_dwo = 1; } if (s != DW_Section_Null) { if (sect_status[s]) { Assert(!"too many debug sections with identical name, picking first"); } else { sect_status[s] = 1; DW_Section *d = &input.sec[s]; d->name = push_str8_copy(arena, name); d->data = str8_substr(raw_image, raw_data_range); d->is_dwo = is_dwo; } } } return input; } ================================================ FILE: src/dwarf/dwarf_coff.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_COFF_H #define DWARF_COFF_H internal B32 dw_is_dwarf_present_coff_section_table(String8 string_table, U64 section_count, COFF_SectionHeader *section_table); internal DW_Input dw_input_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table); #endif // DWARF_COFF_H ================================================ FILE: src/dwarf/dwarf_dump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Stringification Helpers internal String8 dw_string_from_reg_off(Arena *arena, Arch arch, DW_Reg reg_idx, S64 reg_off) { Temp scratch = scratch_begin(&arena, 1); String8 reg_str = dw_string_from_register(scratch.arena, arch, reg_idx); String8 result; if (reg_off != 0) { result = push_str8f(arena, "%S%+lld", reg_str, reg_off); } else { result = reg_str; } scratch_end(scratch); return result; } internal String8 dw_string_from_reg(Arena *arena, Arch arch, DW_Reg reg_idx) { return dw_string_from_reg_off(arena, arch, reg_idx, 0); } internal String8List dw_string_list_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 addr_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format) { Temp scratch = scratch_begin(&arena, 1); String8List result = {0}; for (U64 cursor = 0; cursor < raw_data.size; ) { U8 op = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &op); String8 op_value = str8_zero(); U64 size_param = 0; B32 is_signed = 0; switch (op) { case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { U64 x = op - DW_ExprOp_Lit0; op_value = push_str8f(scratch.arena, "%llu", x); } break; case DW_ExprOp_Const1U:size_param = 1; goto const_n; case DW_ExprOp_Const2U:size_param = 2; goto const_n; case DW_ExprOp_Const4U:size_param = 4; goto const_n; case DW_ExprOp_Const8U:size_param = 8; goto const_n; case DW_ExprOp_Const1S:size_param = 1; is_signed = 1; goto const_n; case DW_ExprOp_Const2S:size_param = 2; is_signed = 1; goto const_n; case DW_ExprOp_Const4S:size_param = 4; is_signed = 1; goto const_n; case DW_ExprOp_Const8S:size_param = 8; is_signed = 1; goto const_n; const_n: { if (is_signed) { S64 x = 0; cursor += str8_deserial_read(raw_data, cursor, &x, size_param, 1); x = extend_sign64(x, size_param); op_value = push_str8f(scratch.arena, "%lld", x); } else { U64 x = 0; cursor += str8_deserial_read(raw_data, cursor, &x, size_param, 1); op_value = push_str8f(scratch.arena, "%llu", x); } } break; case DW_ExprOp_Addr: { U64 addr = 0; cursor += str8_deserial_read(raw_data, cursor, &addr, addr_size, 1); op_value = push_str8f(scratch.arena, "%#llx", addr); } break; case DW_ExprOp_ConstU: { U64 x = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%llu", x); } break; case DW_ExprOp_ConstS: { S64 x = 0; cursor += str8_deserial_read_sleb128(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%lld", x); } break; case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { U64 reg_idx = op - DW_ExprOp_Reg0; op_value = dw_string_from_reg_off(scratch.arena, arch, reg_idx, 0); } break; case DW_ExprOp_RegX: { U64 reg_idx = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); op_value = dw_string_from_reg_off(scratch.arena, arch, reg_idx, 0); } break; case DW_ExprOp_ImplicitValue: { U64 value_size = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &value_size); Rng1U64 value_range = rng_1u64(cursor, cursor + value_size); String8 value_data = str8_substr(raw_data, value_range); cursor += value_size; String8List value_strings = numeric_str8_list_from_data(scratch.arena, 16, value_data, 1); op_value = str8_list_join(scratch.arena, &value_strings, &(StringJoin){.pre = str8_lit("{ "), .sep = str8_lit(", "), .post = str8_lit(" }")}); } break; case DW_ExprOp_Piece: { U64 size = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &size); op_value = push_str8f(scratch.arena, "%u", size); } break; case DW_ExprOp_BitPiece: { U64 bit_size = 0, bit_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &bit_size); cursor += str8_deserial_read_uleb128(raw_data, cursor, &bit_off); op_value = push_str8f(scratch.arena, "bit size %llu, bit offset %llu", bit_size, bit_off); } break; case DW_ExprOp_Pick: { U8 stack_idx = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &stack_idx); op_value = push_str8f(scratch.arena, "stack index %u", stack_idx); } break; case DW_ExprOp_PlusUConst: { U64 addend = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &addend); op_value = push_str8f(arena, "addend %llu", addend); } break; case DW_ExprOp_Skip: { S16 x = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%+d bytes", x); } break; case DW_ExprOp_Bra: { S16 x = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%+d", x); } break; case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { U64 reg_idx = op - DW_ExprOp_BReg0; S64 reg_off = 0; cursor += str8_deserial_read_sleb128(raw_data, cursor, ®_off); op_value = dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off); } break; case DW_ExprOp_FBReg: { S64 reg_off = 0; cursor += str8_deserial_read_sleb128(raw_data, cursor, ®_off); op_value = push_str8f(scratch.arena, "offset %lld", reg_off); } break; case DW_ExprOp_BRegX: { U64 reg_idx = 0; S64 reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_sleb128(raw_data, cursor, ®_off); op_value = dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off); } break; case DW_ExprOp_XDerefSize: case DW_ExprOp_DerefSize: { U8 x = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%u", x); } break; case DW_ExprOp_Call2: { U16 x = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &x); op_value = push_str8f(scratch.arena, "%u", x); } break; case DW_ExprOp_Call4: { U32 x = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &x); op_value = push_str8f(arena, "%u", x); } break; case DW_ExprOp_CallRef: { U64 x = 0; cursor += str8_deserial_read_dwarf_uint(raw_data, cursor, format, &x); op_value = push_str8f(scratch.arena, "%llu", x); } break; case DW_ExprOp_ImplicitPointer: case DW_ExprOp_GNU_ImplicitPointer: { U64 info_off = 0; cursor += str8_deserial_read_dwarf_uint(raw_data, cursor, format, &info_off); S64 ptr = 0; cursor += str8_deserial_read_sleb128(raw_data, cursor, &ptr); op_value = push_str8f(scratch.arena, ".debug_info+%#llx, ptr %llx", info_off, ptr); } break; case DW_ExprOp_Convert: case DW_ExprOp_GNU_Convert: { U64 type_cu_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &type_cu_off); op_value = push_str8f(scratch.arena, "TypeCuOff %#llx", cu_base + type_cu_off); } break; case DW_ExprOp_GNU_ParameterRef: { // TODO: always 4 bytes? U32 cu_off = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &cu_off); op_value = push_str8f(scratch.arena, "CuOff %#x", cu_base + cu_off); } break; case DW_ExprOp_DerefType: case DW_ExprOp_GNU_DerefType: { U8 deref_size = 0; U64 type_cu_off = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &deref_size); cursor += str8_deserial_read_uleb128(raw_data, cursor, &type_cu_off); op_value = push_str8f(scratch.arena, "%#x, TypeCuOff %#llx", deref_size, cu_base + type_cu_off); } break; case DW_ExprOp_ConstType: case DW_ExprOp_GNU_ConstType: { U64 type_cu_off = 0; U8 const_value_size = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &type_cu_off); cursor += str8_deserial_read_struct(raw_data, cursor, &const_value_size); Rng1U64 const_value_range = rng_1u64(cursor, cursor + const_value_size); String8 const_value_data = str8_substr(raw_data, const_value_range); String8List const_value_strings = numeric_str8_list_from_data(scratch.arena, 16, const_value_data, 1); String8 const_value_str = str8_list_join(scratch.arena, &const_value_strings, &(StringJoin){.sep = str8_lit(", ")}); op_value = push_str8f(scratch.arena, "TypeCuOff %#llx, Const Value { %S }", cu_base + type_cu_off, const_value_str); cursor += const_value_size; } break; case DW_ExprOp_RegvalType: case DW_ExprOp_GNU_RegvalType: { U64 reg_idx = 0, type_cu_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_uleb128(raw_data, cursor, &type_cu_off); op_value = push_str8f(scratch.arena, "%S, TypeCuOff %#llx", dw_string_from_register(scratch.arena, arch, reg_idx), cu_base + type_cu_off); } break; case DW_ExprOp_EntryValue: case DW_ExprOp_GNU_EntryValue: { U64 block_size = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &block_size); Rng1U64 block_range = rng_1u64(cursor, cursor + block_size); String8 block_data = str8_substr(raw_data, block_range); String8List block_expr = dw_string_list_from_expression(scratch.arena, block_data, cu_base, addr_size, arch, ver, ext, format); op_value = str8_list_join(scratch.arena, &block_expr, &(StringJoin){.pre = str8_lit("{ "), .sep = str8_lit(","), .post = str8_lit(" }")}); cursor += block_size; } break; case DW_ExprOp_Addrx: { U64 addr = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &addr); op_value = push_str8f(scratch.arena, "%#llx", addr); } break; case DW_ExprOp_CallFrameCfa: case DW_ExprOp_FormTlsAddress: case DW_ExprOp_PushObjectAddress: case DW_ExprOp_Nop: case DW_ExprOp_Eq: case DW_ExprOp_Ge: case DW_ExprOp_Gt: case DW_ExprOp_Le: case DW_ExprOp_Lt: case DW_ExprOp_Ne: case DW_ExprOp_Shl: case DW_ExprOp_Shr: case DW_ExprOp_Shra: case DW_ExprOp_Xor: case DW_ExprOp_XDeref: case DW_ExprOp_Abs: case DW_ExprOp_And: case DW_ExprOp_Div: case DW_ExprOp_Minus: case DW_ExprOp_Mod: case DW_ExprOp_Mul: case DW_ExprOp_Neg: case DW_ExprOp_Not: case DW_ExprOp_Or: case DW_ExprOp_Plus: case DW_ExprOp_Rot: case DW_ExprOp_Swap: case DW_ExprOp_Deref: case DW_ExprOp_Dup: case DW_ExprOp_Drop: case DW_ExprOp_Over: case DW_ExprOp_StackValue: { // no operands } break; } String8 opcode_str = dw_string_from_expr_op(scratch.arena, ver, ext, op); if (op_value.size == 0) { str8_list_pushf(arena, &result, "DW_OP_%S", opcode_str); } else { str8_list_pushf(arena, &result, "DW_OP_%S = %S", opcode_str, op_value); } } scratch_end(scratch); return result; } internal String8 dw_string_from_expression(Arena *arena, String8 expr, U64 cu_base, U64 addr_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format) { Temp scratch = scratch_begin(&arena, 1); String8List list = dw_string_list_from_expression(scratch.arena, expr, cu_base, addr_size, arch, ver, ext, format); String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); return result; } internal String8List dw_string_list_from_cfi_program(Arena *arena, U64 cu_base, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format, U64 pc_begin, DW_CIE *cie, DW_DecodePtr *decode_ptr_func, void *deocde_ptr_ud, String8 program) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; U64 reg_max = dw_reg_count_from_arch(arch); U64 pc = pc_begin; for (U64 cursor = 0, inst_size; cursor < program.size; cursor += inst_size) { // unpack instruction DW_CFA_Inst inst = {0}; DW_CFA_ParseErrorCode error_code = dw_parse_cfa_inst(str8_skip(program, cursor), cie->code_align_factor, cie->data_align_factor, 0, 0, &inst_size, &inst); if (error_code == DW_CFA_ParseErrorCode_End) { break; } if (error_code != DW_CFA_ParseErrorCode_NewInst) { str8_list_pushf(arena, &list, "ERROR: failed to unpack CFA instruction @ 0x%I64", cursor); break; } // error check operands DW_CFA_OperandType *operand_types = dw_operand_types_from_cfa_op(inst.opcode); U64 operand_count = dw_operand_count_from_cfa_opcode(inst.opcode); for EachIndex(operand_idx, operand_count) { switch (operand_types[operand_idx]) { case DW_CFA_OperandType_Null: break; case DW_CFA_OperandType_Value: break; case DW_CFA_OperandType_Register: { if (inst.operands[operand_idx].u64 >= reg_max) { str8_list_pushf(arena, &list, "ERROR: DW_CFA_%S @ 0x%I64x has an invalid register", dw_string_from_cfa_opcode(inst.opcode), cursor); } } break; case DW_CFA_OperandType_Expression: { DW_Expr expr = dw_expr_from_data(scratch.arena, format, cie->address_size, inst.operands[operand_idx].block); for EachNode(inst, DW_ExprInst, expr.first) { if (dw_is_cfa_expr_opcode_invalid(inst->opcode)) { String8 expr_opcode_str = dw_string_from_expr_op(scratch.arena, ver, ext, inst->opcode); str8_list_pushf(arena, &list, "ERROR: Exrepssion in DW_CFA_%S @ 0x%I64x has an invalid opcode DW_ExprOp_%S", expr_opcode_str); } } } break; default: { InvalidPath; } break; } } // format operands String8 operand_str = str8_lit("???"); switch (inst.opcode) { case DW_CFA_Nop: { operand_str = str8_zero(); } break; case DW_CFA_SetLoc: { operand_str = str8f(arena, "0x%X", inst.operands[0].u64); pc = inst.operands[0].u64; } break; case DW_CFA_AdvanceLoc1: { U64 delta = inst.operands[0].u64; pc += delta; operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); } break; case DW_CFA_AdvanceLoc2: { U64 delta = inst.operands[0].u64; pc += delta; operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); } break; case DW_CFA_AdvanceLoc4: { U64 delta = inst.operands[0].u64; pc += delta; operand_str = str8f(arena, "%+u `PC 0x%I64x`", delta, pc); } break; case DW_CFA_OffsetExt: { U64 reg = inst.operands[0].u64; S64 offset = (S64)inst.operands[1].u64; operand_str = dw_string_from_reg_off(arena, arch, reg, offset); } break; case DW_CFA_RestoreExt: { operand_str = str8_zero(); } break; case DW_CFA_Undefined: { operand_str = str8f(arena, "%I64u", inst.operands[0].u64); } break; case DW_CFA_SameValue: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); } break; case DW_CFA_Register: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); } break; case DW_CFA_RememberState: { operand_str = str8_zero(); } break; case DW_CFA_RestoreState: { operand_str = str8_zero(); } break; case DW_CFA_DefCfa: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].u64); } break; case DW_CFA_DefCfaRegister: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); } break; case DW_CFA_DefCfaOffset: { operand_str = str8f(arena, "+%I64u", inst.operands[0].u64); } break; case DW_CFA_DefCfaExpr: { operand_str = dw_string_from_expression(arena, inst.operands[0].block, cu_base, cie->address_size, arch, ver, ext, format); } break; case DW_CFA_Expr: { String8 reg_str = dw_string_from_reg_off(scratch.arena, arch, inst.operands[0].u64, 0); String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); operand_str = str8f(arena, "%S expression %S", reg_str, expr_str); } break; case DW_CFA_OffsetExtSf: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); } break; case DW_CFA_DefCfaSf: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, inst.operands[1].s64); } break; case DW_CFA_DefCfaOffsetSf: { operand_str = str8_zero(); } break; case DW_CFA_ValOffset: { operand_str = str8f(arena, "value 0x%llx, offset %+I64d", inst.operands[0].u64, inst.operands[1].u64); } break; case DW_CFA_ValOffsetSf: { operand_str = str8f(arena, "value %llu, offset %+I64d", inst.operands[0].u64, inst.operands[1].s64); } break; case DW_CFA_ValExpr: { String8 expr_str = dw_string_from_expression(scratch.arena, inst.operands[1].block, cu_base, cie->address_size, arch, ver, ext, format); operand_str = str8f(arena, "value +%I64u, expression %S", inst.operands[0].u64, expr_str); } break; case DW_CFA_AdvanceLoc: { U64 delta = inst.operands[0].u64; pc += delta; operand_str = str8f(arena, "+%I64u `PC 0x%I64x`", delta, pc); } break; case DW_CFA_Offset: { U64 reg = inst.operands[0].u64; S64 offset = (S64)inst.operands[1].u64; operand_str = dw_string_from_reg_off(arena, arch, reg, offset); } break; case DW_CFA_Restore: { operand_str = dw_string_from_reg_off(arena, arch, inst.operands[0].u64, 0); } break; default: { str8_list_pushf(arena, &list, "ERROR: unknown CFA opcode 0x%I64u", inst.opcode); } goto exit; } if (operand_str.size) { str8_list_pushf(arena, &list, "DW_CFA_%S: %S", dw_string_from_cfa_opcode(inst.opcode), operand_str); } else { str8_list_pushf(arena, &list, "DW_CFA_%S", dw_string_from_cfa_opcode(inst.opcode)); } } exit:; scratch_end(scratch); return list; } internal String8 dw_string_from_cfa(Arena *arena, Arch arch, U64 address_size, DW_Version version, DW_Ext ext, DW_Format format, DW_CFA cfa) { String8 cfa_str = str8_lit("???"); switch (cfa.rule) { case DW_CFA_Rule_Null: {} break; case DW_CFA_Rule_RegOff: { cfa_str = dw_string_from_reg_off(arena, arch, cfa.reg, cfa.off); } break; case DW_CFA_Rule_Expression: { cfa_str = dw_string_from_expression(arena, cfa.expr, max_U64, address_size, arch, version, ext, format); } break; default: { InvalidPath; } break; } return cfa_str; } internal String8 dw_string_from_cfi_row(Arena *arena, Arch arch, U64 address_size, DW_Version version, DW_Ext ext, DW_Format format, DW_CFI_Row *row) { Temp scratch = scratch_begin(&arena, 1); String8List cfi_regs_list = {0}; U64 reg_count = dw_reg_count_from_arch(arch); for EachIndex(reg_idx, reg_count) { DW_CFI_Register *cfi_reg = &row->regs[reg_idx]; String8 rule_str = str8_lit("???"); switch (cfi_reg->rule) { case DW_CFI_RegisterRule_Undefined: { rule_str = str8f(scratch.arena, "Undefined(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); } break; case DW_CFI_RegisterRule_SameValue: { rule_str = str8_zero(); } break; case DW_CFI_RegisterRule_Offset: { rule_str = str8f(scratch.arena, "[CFA%+I64d]", cfi_reg->n); } break; case DW_CFI_RegisterRule_ValOffset: { rule_str = str8f(scratch.arena, "Val(CFA%+I64d)", cfi_reg->n); } break; case DW_CFI_RegisterRule_Register: { rule_str = str8f(scratch.arena, "Register(%S)", dw_string_from_reg(scratch.arena, arch, cfi_reg->n)); } break; case DW_CFI_RegisterRule_Expression: { rule_str = str8f(scratch.arena, "Expression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); } break; case DW_CFI_RegisterRule_ValExpression: { rule_str = str8f(scratch.arena, "ValExpression(%S)", dw_string_from_expression(scratch.arena, cfi_reg->expr, max_U64, address_size, arch, version, ext, format)); } break; case DW_CFI_RegisterRule_Architectural: { rule_str = str8_lit("???"); } break; default: { InvalidPath; } break; } if (rule_str.size) { str8_list_pushf(scratch.arena, &cfi_regs_list, "%S: %S", dw_string_from_reg(scratch.arena, arch, reg_idx), rule_str); } } String8 string = str8_list_join(arena, &cfi_regs_list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return string; } internal String8 dw_single_line_string_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format) { Temp scratch = scratch_begin(&arena, 1); String8List list = dw_string_list_from_expression(scratch.arena, raw_data, cu_base, address_size, arch, ver, ext, format); String8 expression = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return expression; } #if 0 internal String8 w_string_from_eh_ptr_enc(Arena *arena, EH_PtrEnc enc) { U8 type = enc & EH_PtrEnc_TypeMask; String8 type_str = str8_lit("NULL"); switch (type) { case EH_PtrEnc_Ptr: type_str = str8_lit("PTR"); break; case EH_PtrEnc_ULEB128: type_str = str8_lit("ULEB128"); break; case EH_PtrEnc_UData2: type_str = str8_lit("UDATA2"); break; case EH_PtrEnc_UData4: type_str = str8_lit("UDATA4"); break; case EH_PtrEnc_UData8: type_str = str8_lit("UDATA8"); break; case EH_PtrEnc_Signed: type_str = str8_lit("SIGNED"); break; case EH_PtrEnc_SLEB128: type_str = str8_lit("SLEB128"); break; case EH_PtrEnc_SData2: type_str = str8_lit("SDATA2"); break; case EH_PtrEnc_SData4: type_str = str8_lit("SDATA4"); break; case EH_PtrEnc_SData8: type_str = str8_lit("SDATA8"); break; } U8 modifier = enc & EH_PtrEnc_ModifyMask; String8 modifier_str = str8_lit("NULL"); switch (modifier) { case EH_PtrEnc_PcRel: modifier_str = str8_lit("PCREL"); break; case EH_PtrEnc_TextRel: modifier_str = str8_lit("TEXTREL"); break; case EH_PtrEnc_DataRel: modifier_str = str8_lit("DATAREL"); break; case EH_PtrEnc_FuncRel: modifier_str = str8_lit("FUNCREL"); break; } String8 indir_str = str8_lit(""); if (enc & EH_PtrEnc_Indirect) { indir_str = str8_lit("(INDIRECT)"); } return push_str8f(arena, "Type: %S, Modifier: %S %S", type_str, modifier_str, indir_str); } internal void dw_print_eh_frame(Arena *arena, String8List *out, String8 indent, String8 raw_eh_frame, Arch arch, DW_Version ver, DW_Ext ext, EH_PtrCtx *ptr_ctx) { Temp scratch = scratch_begin(&arena, 1); DW_CIE cie = {0}; for (U64 cursor = 0; cursor < raw_eh_frame.size; ) { U64 header_offset = cursor; U64 length = 0; // doesn't include bytes for size cursor += dw_based_range_read_length(raw_eh_frame.str, rng_1u64(0,raw_eh_frame.size), cursor, &length); if (length == 0) { break; // encountered exit marker } U64 entry_start = cursor; U64 entry_end = cursor + length; U32 entry_id = 0; // always 4-bytes, even when length is encoded as 64-bit integer cursor += str8_deserial_read_struct(raw_eh_frame, cursor, &entry_id); // TODO: fix the freaking EH_PtrEnc_PCREL encoding. // it assumes "frame_base" points to the first byte of .eh_frame // but here base is start of ELF and we use range to select .eh_frame // bytes to read, which breaks parsing. String8 raw_frame = str8_substr(raw_eh_frame, rng_1u64(cursor, cursor + length - sizeof(entry_id))); Rng1U64 cfi_range = rng_1u64(0,0); // CIE if (entry_id == 0) { dw_unwind_parse_cie_x64(raw_frame.str, rng_1u64(0,raw_frame.size), ptr_ctx, 0, &cie); cfi_range = cie.cfi_range; rd_printf("CIE @ 0x%X, Length %u", header_offset, length); rd_indent(); rd_printf("LSDA Encoding: %S", dw_string_from_eh_ptr_enc(scratch.arena, cie.lsda_encoding)); rd_printf("Address Encoding: %S", dw_string_from_eh_ptr_enc(scratch.arena, cie.addr_encoding)); rd_printf("Augmentation: %S", cie.augmentation); rd_printf("Code Align Factor: %llu", cie.code_align_factor); rd_printf("Data Align Factor: %lld", cie.data_align_factor); rd_printf("Return Address Register: %u", cie.ret_addr_reg); rd_printf("Handler IP: %#llx", cie.handler_ip); rd_unindent(); } // FDE else { DW_FDE fde = {0}; dw_unwind_parse_fde_x64(raw_eh_frame.str, rng_1u64(0,raw_eh_frame.size), ptr_ctx, &cie, 0, &fde); cfi_range = fde.cfi_range; // calc parent CIE offset AssertAlways(entry_start >= entry_id); U64 cie_offset = entry_start - entry_id; NotImplemented; // TODO: syms_safe_sub_u64(range.min + entry_start, entry_id); rd_printf("FDE @ %#llx, Length %u, Parent CIE @ %#llx", header_offset, length, cie_offset); rd_indent(); rd_printf("IP Range: %#llx-%#llx", fde.ip_voff_range.min, fde.ip_voff_range.max); rd_printf("LSDA IP: %#llx", fde.lsda_ip); rd_unindent(); } // print CFI program rd_printf("CFI Program:"); rd_indent(); DW_Format format = DW_FormatFromSize(length); String8 raw_cfi = str8_substr(raw_eh_frame, cfi_range); dw_string_from_cfi_program(scratch.arena, out, indent, raw_cfi, &cie, ptr_ctx, arch, ver, ext, format); rd_unindent(); rd_newline(); // advance to next entry cursor = entry_end; } scratch_end(scratch); } internal void dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed) { #if 0 DW_Section info = input->sec[DW_Section_Info]; DW_Section loc = input->sec[DW_Section_Loc]; if (loc.data.size == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", input->sec[DW_Section_Loc].name); rd_indent(); // TODO: warn about overlaps in ranges Rng1U64List cu_range_list = dw_comp_unit_ranges_from_info(scratch.arena, info); // parse debug_info for attributes with LOCLIST and store .debug_loc offsets U64List *loc_lists = push_array(scratch.arena, U64List, cu_range_list.count); U64 *address_sizes = push_array(scratch.arena, U64, cu_range_list.count); U64 *address_bases = push_array(scratch.arena, U64, cu_range_list.count); U64 *cu_bases = push_array(scratch.arena, U64, cu_range_list.count); DW_Version *ver_arr = push_array(scratch.arena, DW_Version, cu_range_list.count); DW_Ext *ext_arr = push_array(scratch.arena, DW_Ext, cu_range_list.count); U64 comp_idx = 0; for (Rng1U64Node *cu_range_n = cu_range_list.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++comp_idx) { Temp comp_temp = temp_begin(arena); Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_comp_unit_from_info_off(comp_temp.arena, input, cu_range.min, relaxed); // store info about comp unit address_sizes[comp_idx] = cu.address_size; address_bases[comp_idx] = cu.base_addr; ver_arr[comp_idx] = cu.version; cu_bases[comp_idx] = cu_range_n->v.min; // parse tags for (U64 info_off = cu.tags_range.min; info_off < cu.tags_range.max; /* empty */) { Temp tag_temp = temp_begin(scratch.arena); DW_Tag tag = dw_tag_from_info_offset_cu(tag_temp.arena, input, &cu, ext_arr[comp_idx], info_off); // parse attribs for (DW_AttribNode *attrib_node = tag.attribs.first; attrib_node != 0; attrib_node = attrib_node->next) { DW_Attrib *attrib = &attrib_node->v; B32 is_sect_offset = attrib->value_class == DW_AttribClass_LocListPtr || (attrib->value_class == DW_AttribClass_LocList && attrib->form_kind == DW_Form_SecOffset); B32 is_sect_index = attrib->value_class == DW_AttribClass_LocList && attrib->form_kind == DW_Form_LocListx; if (is_sect_offset) { u64_list_push(scratch.arena, &loc_lists[comp_idx], attrib->value.v[0]); } else if (is_sect_index) { // TODO: support for section indexing } } // advance to next tag info_off = tag.next_info_off; temp_end(tag_temp); } temp_end(comp_temp); } void *base = dw_base_from_sec(input, DW_Section_Loc); Rng1U64 range = dw_range_from_sec(input, DW_Section_Loc); rd_printf(".debug_loc"); rd_indent(); rd_printf("%-8s %-8s %-8s %s", "Offset", "Min", "Max", "Expression"); for (U32 comp_idx = 0; comp_idx < cu_range_list.count; ++comp_idx) { Temp locs_temp = temp_begin(scratch.arena); DW_Version ver = ver_arr[comp_idx]; DW_Ext ext = ext_arr[comp_idx]; U64Array locs = u64_array_from_list(locs_temp.arena, &loc_lists[comp_idx]); u64_array_sort(locs.count, locs.v); U64Array locs_set = remove_duplicates_u64_array(locs_temp.arena, locs); U64 address_size = address_sizes[comp_idx]; U64 base_selector = (address_size == 8) ? max_U64 : max_U32; for (U64 loc_idx = 0; loc_idx < locs_set.count; ++loc_idx) { U64 base_address = address_bases[comp_idx]; for (U64 cursor = locs_set.v[loc_idx]; cursor < dim_1u64(range); /* empty */) { Temp range_temp = temp_begin(arena); String8List list = {0}; // offset str8_list_pushf(range_temp.arena, &list, "%08llx", cursor); // parse entry U64 v0 = 0, v1 = 0; cursor += dw_based_range_read(base, range, cursor, address_size, &v0); cursor += dw_based_range_read(base, range, cursor, address_size, &v1); B32 is_list_end = v0 == 0 && v1 == 0; if (is_list_end) { str8_list_pushf(range_temp.arena, &list, ""); } else if (v0 == base_selector) { base_address = v1; } else { U16 expr_size = 0; cursor += dw_based_range_read_struct(base, range, cursor, &expr_size); Rng1U64 expr_range = rng_1u64(range.min+cursor, range.min+cursor+expr_size); cursor += expr_size; // format dwarf expression B32 is_dwarf64 = (address_size == 8); String8 raw_expr = str8((U8*)base+expr_range.min, dim_1u64(expr_range)); String8 expression = dw_single_line_string_from_expression(range_temp.arena, raw_expr, cu_bases[comp_idx], address_size, arch, ver, ext, input->sec[DW_Section_Loc].mode); // push entry U64 min = base_address + v0; U64 max = base_address + v1; str8_list_pushf(range_temp.arena, &list, "%08llx %08llx %S", min, max, expression); } // print entry String8 print = str8_list_join(range_temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); // cleanup temp temp_end(range_temp); // exit check if (is_list_end) { break; } } } temp_end(locs_temp); } rd_unindent(); rd_unindent(); scratch_end(scratch); #endif } internal void dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed) { NotImplemented; #if 0 DW_Section ranges = input->sec[DW_Section_Ranges]; void *base = dw_base_from_sec(input, DW_Section_Ranges); Rng1U64 range = dw_range_from_sec(input, DW_Section_Ranges); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); Rng1U64List cu_range_list = dw_comp_unit_ranges_from_info(scratch.arena, sections->v[DW_Section_Info]); // parse debug_info for attributes with LOCLIST and store .debug_loc offsets U64List *loc_lists = push_array(scratch.arena, U64List, cu_range_list.count); U64 *address_sizes = push_array(scratch.arena, U64, cu_range_list.count); U64 *address_bases = push_array(scratch.arena, U64, cu_range_list.count); { U64 comp_idx = 0; for (Rng1U64Node *cu_range_n = cu_range_list.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++comp_idx) { Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_comp_unit_from_info_offset(scratch.arena, sections, cu_range.min, relaxed); // store info about comp unit address_sizes[comp_idx] = cu.address_size; address_bases[comp_idx] = cu.base_addr; // parse tags for (U64 info_off = cu.tags_range.min; info_off < cu.tags_range.max; /* empty */) { DW_Tag tag = dw_tag_from_info_offset_cu(scratch.arena, sections, &cu, info_off); // parse attribs for (DW_AttribNode *attrib_node = tag.attribs.first; attrib_node != 0; attrib_node = attrib_node->next) { DW_Attrib *attrib = &attrib_node->v; B32 is_sect_offset = attrib->value_class == DW_AttribClass_RngListPtr || (attrib->value_class == DW_AttribClass_RngList && attrib->form_kind == DW_Form_SecOffset); B32 is_sect_index = attrib->value_class == DW_AttribClass_RngList && attrib->form_kind == DW_Form_RngListx; if (is_sect_offset) { u64_list_push(scratch.arena, &loc_lists[comp_idx], attrib->value.v[0]); } else if (is_sect_index) { // TODO: support for section indexing } } info_off = tag.next_info_off; } } } rd_printf("# %S", sections->v[DW_Section_Ranges].name); rd_indent(); rd_printf("%-8s %-8s %-8s", "Offset", "Min", "Max"); for (U32 comp_idx = 0; comp_idx < cu_range_list.count; ++comp_idx) { U64Array locs = u64_array_from_list(scratch.arena, &loc_lists[comp_idx]); u64_array_sort(locs.count, locs.v); U64Array locs_set = remove_duplicates_u64_array(scratch.arena, locs); U64 address_size = address_sizes[comp_idx]; U64 base_selector = (address_size == 8) ? max_U64 : max_U32; for (U64 loc_idx = 0; loc_idx < locs_set.count; ++loc_idx) { U64 base_address = address_bases[comp_idx]; for (U64 cursor = locs_set.v[loc_idx]; cursor < dim_1u64(range); /* empty */) { Temp range_temp = temp_begin(scratch.arena); String8List list = {0}; // offset str8_list_pushf(range_temp.arena, &list, "%08llx", cursor); // parse entry U64 v0 = 0, v1 = 0; cursor += dw_based_range_read(base, range, cursor, address_size, &v0); cursor += dw_based_range_read(base, range, cursor, address_size, &v1); B32 is_list_end = v0 == 0 && v1 == 0; if (is_list_end) { str8_list_pushf(range_temp.arena, &list, ""); } else if (v0 == base_selector) { base_address = v1; } else { // push entry U64 min = base_address + v0; U64 max = base_address + v1; str8_list_pushf(range_temp.arena, &list, "%08llx %08llx", min, max); } // print entry String8 print = str8_list_join(range_temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); temp_end(range_temp); // exit check if (is_list_end) { break; } } } } #endif } internal void dw_print_debug_aranges(Arena *arena, String8List *out, String8 indent, DW_Input *input) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_ARanges); Rng1U64 range = dw_range_from_sec(sections, DW_Section_ARanges); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_ARanges].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_length = 0; DW_Version version = 0; U64 debug_info_offset = 0; U8 address_size = 0; U8 segment_selector_size = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; cursor += dw_based_range_read_struct(base, range, cursor, &version); B32 is_dwarf64 = unit_length >= max_U32; U64 int_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); cursor += dw_based_range_read(base, range, cursor, int_size, &debug_info_offset); cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { cursor += tuple_size - bytes_too_far_past_boundary; } rd_printf("Unit length: %llu", unit_length); rd_printf("Version: %u", version); rd_printf("Debug info offset: %#llx", debug_info_offset); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); if (version != DW_Version_2) { rd_warningf("Version value must be 2 (DWARF5 sepc, Feb 13, 2017)"); } rd_indent(); rd_printf("%-8s %-8s", "Offset", "Range"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); String8List list = {0}; str8_list_pushf(temp.arena, &list, "%08llx", cursor); U64 segment_selector = 0; U64 address = 0; U64 length = 0; cursor += dw_based_range_read(base, range, cursor, segment_selector_size, &segment_selector); cursor += dw_based_range_read(base, range, cursor, address_size, &address); cursor += dw_based_range_read(base, range, cursor, address_size, &length); if (segment_selector == 0 && address == 0 && length == 0) { str8_list_pushf(temp.arena, &list, ""); } else { if (segment_selector != 0) { str8_list_pushf(temp.arena, &list, "%02llu:", segment_selector); } str8_list_pushf(temp.arena, &list, "%llx-%llx", address, address+length); } String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ") }); rd_printf("%S", print); temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } internal void dw_print_debug_addr(Arena *arena, String8List *out, String8 indent, DW_Input *input) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_Addr); Rng1U64 range = dw_range_from_sec(sections, DW_Section_Addr); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_Addr].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_length = 0; DW_Version version = 0; U8 address_size = 0; U8 segment_selector_size = 0; U64 unit_offset = cursor; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; cursor += dw_based_range_read_struct(base, range, cursor, &version); cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { cursor += tuple_size - bytes_too_far_past_boundary; } rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); if (version != DW_Version_2) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } rd_indent(); rd_printf("%-8s %-8s", "Offset", "Address"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); String8List list = {0}; str8_list_pushf(temp.arena, &list, "%08X", cursor); U64 segment_selector = 0; U64 address = 0; cursor += dw_based_range_read(base, range, cursor, segment_selector_size, &segment_selector); cursor += dw_based_range_read(base, range, cursor, address_size, &address); if (segment_selector == 0 && address == 0) { str8_list_pushf(temp.arena, &list, ""); } else { if (segment_selector != 0) { str8_list_pushf(temp.arena, &list, "%02u:", segment_selector); } str8_list_pushf(temp.arena, &list, "%llx", address); } String8 print = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } internal U64 dw_based_range_read_address(void *base, Rng1U64 range, U64 offset, Rng1U64Array segment_ranges, U8 segment_selector_size, U8 address_size, U64 *address_out) { U64 read_offset = offset; // read segment U64 segment_selector = 0; read_offset += dw_based_range_read(base, range, read_offset, segment_selector_size, &segment_selector); // read address U64 address = 0; read_offset += dw_based_range_read(base, range, read_offset, address_size, &address); // apply segment offset B32 is_address_segment_relative = segment_selector_size > 0; if (is_address_segment_relative) { if (segment_selector < segment_ranges.count) { address += segment_ranges.v[segment_selector].min; } else { Assert(!"invalid segment selector"); } } U64 read_size = (read_offset - offset); return read_size; } internal void dw_print_debug_loclists(Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_virtual_ranges, Arch arch) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_LocLists); Rng1U64 range = dw_range_from_sec(sections, DW_Section_LocLists); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_LocLists].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; DW_Version version = 0; U8 address_size = 0; U8 segment_selector_size = 0; U32 offset_entry_count = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); cursor += dw_based_range_read_struct(base, range, cursor, &offset_entry_count); U64 past_header_offset = cursor; B32 is_dwarf64 = unit_length > max_U32; U64 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); rd_printf("Offset entry count: %u", offset_entry_count); if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } if (offset_entry_count > 0) { rd_printf("Offsets:"); rd_indent(); rd_printf("%-8s %-8s", "Index", "Offset"); for (U64 offset_idx = 0; offset_idx < offset_entry_count; ++offset_idx) { U64 offset = 0; cursor += dw_based_range_read(base, range, cursor, offset_size, &offset); rd_printf("%-8llu %llx", offset_idx, offset+past_header_offset); } rd_unindent(); } rd_printf("Locations:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "Location"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); String8List list = {0}; str8_list_pushf(temp.arena, &list, "%08llx", cursor); U8 kind = 0; cursor += dw_based_range_read_struct(base, range, cursor, &kind); str8_list_pushf(temp.arena, &list, "DW_LLE_%S", dw_string_from_loc_list_entry_kind(temp.arena, kind)); B32 has_loc_desc = 0; switch (kind) { case DW_LocListEntryKind_EndOfList: break; case DW_LocListEntryKind_DefaultLocation: { has_loc_desc = 1; } break; case DW_LocListEntryKind_BaseAddress: { U64 base_address = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &base_address); str8_list_pushf(temp.arena, &list, "%llx", base_address); } break; case DW_LocListEntryKind_StartLength: { U64 start = 0; U64 length = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); cursor += dw_based_range_read_uleb128(base, range, cursor, &length); str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); } break; case DW_LocListEntryKind_StartEnd: { U64 start = 0; U64 end = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &end); str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); } break; case DW_LocListEntryKind_BaseAddressX: { U64 base_addressx = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); str8_list_pushf(temp.arena, &list, "%llx", base_addressx); } break; case DW_LocListEntryKind_StartXEndX: { U64 startx = 0; U64 endx = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); } break; case DW_LocListEntryKind_OffsetPair: { U64 a = 0; U64 b = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &a); cursor += dw_based_range_read_uleb128(base, range, cursor, &b); str8_list_pushf(temp.arena, &list, "%llx, %llx", a, b); U8 expr_length = 0; cursor += dw_based_range_read_struct(base, range, cursor, &expr_length); String8 raw_expr = str8((U8*)base+cursor, expr_length); cursor += expr_length; // TODO: we need actual cu base to format expression correctly NotImplemented; String8 expression = dw_single_line_string_from_expression(temp.arena, raw_expr, 0, address_size, arch, version, DW_Ext_Null, is_dwarf64); str8_list_pushf(temp.arena, &list, "(%S)", expression); } break; case DW_LocListEntryKind_StartXLength: { U64 startx = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); U64 length = 0; if (version < DW_Version_5) { // pre-standard length cursor += dw_based_range_read(base, range, cursor, sizeof(U32), &length); } else { cursor += dw_based_range_read_uleb128(base, range, cursor, &length); } } break; } String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } internal void dw_print_debug_rnglists(Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_ranges) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_RngLists); Rng1U64 range = dw_range_from_sec(sections, DW_Section_RngLists); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_RngLists].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; DW_Version version = 0; U8 address_size = 0; U8 segment_selector_size = 0; U32 offset_entry_count = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); cursor += dw_based_range_read_struct(base, range, cursor, &offset_entry_count); U64 past_header_offset = cursor; B32 is_dwarf64 = unit_length > max_U32; U64 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); rd_printf("Offset entry count: %u", offset_entry_count); if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } if (offset_entry_count > 0) { rd_printf("Offsets:"); rd_indent(); rd_printf("%-8s %-8s", "Index", "Offset"); for (U64 offset_idx = 0; offset_idx < offset_entry_count; ++offset_idx) { U64 offset = 0; cursor += dw_based_range_read(base, range, cursor, offset_size, &offset); rd_printf("%-8llu %llx", offset_idx, offset+past_header_offset); } rd_unindent(); } rd_printf("Ranges:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "Range"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(scratch.arena); String8List list = {0}; // offset str8_list_pushf(temp.arena, &list, "%08llx", cursor); // opcode mnemonic U8 kind = 0; cursor += dw_based_range_read_struct(base, range, cursor, &kind); str8_list_pushf(temp.arena, &list, "DW_RLE_%S", dw_string_from_rng_list_entry_kind(temp.arena, kind)); // operand switch (kind) { case DW_RngListEntryKind_EndOfList: { // empty } break; case DW_RngListEntryKind_BaseAddressX: { U64 base_addressx = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); str8_list_pushf(temp.arena, &list, "%llx", base_addressx); } break; case DW_RngListEntryKind_BaseAddress: { U64 base_address = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &base_address); str8_list_pushf(temp.arena, &list, "%llx", base_address); } break; case DW_RngListEntryKind_OffsetPair: { U64 min = 0; U64 max = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &min); cursor += dw_based_range_read_uleb128(base, range, cursor, &max); str8_list_pushf(temp.arena, &list, "%llx, %llx", min, max); } break; case DW_RngListEntryKind_StartxLength: { U64 startx = 0; U64 length = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); cursor += dw_based_range_read_uleb128(base, range, cursor, &length); str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, length); } break; case DW_RngListEntryKind_StartxEndx: { U64 startx = 0; U64 endx = 0; cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); } break; case DW_RngListEntryKind_StartEnd: { U64 start = 0; U64 end = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &end); str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); } break; case DW_RngListEntryKind_StartLength: { U64 start = 0; U64 length = 0; cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); cursor += dw_based_range_read_uleb128(base, range, cursor, &length); str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); } break; } // output row String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } internal void dw_format_string_table(Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_SectionKind sec) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, sec); Rng1U64 range = dw_range_from_sec(sections, sec); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[sec].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; DW_Version version = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); if (version != DW_Version_2) { rd_warningf("Version value must be 2"); } B32 is_dwarf64 = unit_length > max_U32; U32 sec_offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); U64 debug_info_offset = 0, debug_info_length = 0; cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &debug_info_offset); cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &debug_info_length); rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Debug info offset: %#llx", debug_info_offset); rd_printf("Debug info length: %#llx", debug_info_length); rd_printf("Entries:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "String"); for (; cursor < unit_opl; ) { U64 info_offset = 0; cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &info_offset); String8 string = dw_based_range_read_string(base, range, cursor); cursor += (string.size + 1); rd_printf("%08llx %S", info_offset, string); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } internal void dw_print_debug_pubnames(Arena *arena, String8List *out, String8 indent, DW_Input *input) { dw_format_string_table(arena, out, indent, input, DW_Section_PubNames); } internal void dw_print_debug_pubtypes(Arena *arena, String8List *out, String8 indent, DW_Input *input) { dw_format_string_table(arena, out, indent, input, DW_Section_PubTypes); } internal void dw_print_debug_line_str(Arena *arena, String8List *out, String8 indent, DW_Input *input) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_LineStr); Rng1U64 range = dw_range_from_sec(sections, DW_Section_LineStr); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_LineStr].name); rd_indent(); rd_printf("%-8s %-8s", "Offset", "String"); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 offset = cursor; String8 string = dw_based_range_read_string(base, range, cursor); cursor += (string.size + 1); rd_printf("%08llX %S", offset, string); } rd_unindent(); scratch_end(scratch); #endif } internal void dw_print_debug_str_offsets(Arena *arena, String8List *out, String8 indent, DW_Input *input) { NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_StrOffsets); Rng1U64 range = dw_range_from_sec(sections, DW_Section_StrOffsets); void *debug_str_base = dw_base_from_sec(sections, DW_Section_Str); Rng1U64 debug_str_range = dw_range_from_sec(sections, DW_Section_Str); if (dim_1u64(range) == 0) { return; } Temp scratch = scratch_begin(&arena, 1); rd_printf("# %S", sections->v[DW_Section_StrOffsets].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; DW_Version version = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } U16 padding = 0; cursor += dw_based_range_read_struct(base, range, cursor, &padding); if (padding != 0) { rd_warningf("unexpected padding byte"); } B32 is_dwarf64 = unit_length > max_U32; U32 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); rd_printf("Unit @ %#llX, length %lld", unit_offset, unit_length); rd_printf("Version: %d", version); rd_printf("Padding: %d", padding); rd_indent(); rd_printf("%-8s %-8s", "@", "Offset"); for (; cursor < unit_opl; ) { U64 read_at = cursor; U64 offset = 0; cursor += dw_based_range_read(base, range, cursor, offset_size, &offset); rd_printf("%08llx %08llx", read_at, offset); if (dim_1u64(debug_str_range) > 0) { String8 string = dw_based_range_read_string(debug_str_base, debug_str_range, offset); rd_printf(" %S", string); } rd_newline(); } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); #endif } #endif //////////////////////////////// //~ rjf: Dump Entry Point internal String8 dw_string_from_attrib_value(Arena *arena, DW_Input *input, Arch arch, DW_CompUnit *unit, DW_LineVMHeader *line_vm, DW_Attrib *attrib) { Temp scratch = scratch_begin(&arena, 1); String8List attrib_fmt = {0}; // rjf: log attrib's value based on vlass DW_AttribClass value_class = dw_value_class_from_attrib(unit, attrib); switch(value_class) { default: {str8_list_pushf(scratch.arena, &attrib_fmt, "`unknown value class`");}break; case DW_AttribClass_Undefined: {str8_list_pushf(scratch.arena, &attrib_fmt, "`undefined value class`");}break; case DW_AttribClass_Address: {str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", dw_address_from_attrib(input, unit, attrib));}break; case DW_AttribClass_Const: {str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", dw_const_u64_from_attrib(input, unit, attrib));}break; case DW_AttribClass_Block: { String8 block = dw_block_from_attrib(input, unit, attrib); String8List block_strs = numeric_str8_list_from_data(scratch.arena, 16, block, 1); String8 block_str = str8_list_join(scratch.arena, &block_strs, &(StringJoin){.sep = str8_lit(", ")}); str8_list_pushf(scratch.arena, &attrib_fmt, "{ %S }", block_str); }break; case DW_AttribClass_ExprLoc: { String8 exprloc = dw_exprloc_from_attrib(input, unit, attrib); String8 exprloc_str = dw_single_line_string_from_expression(scratch.arena, exprloc, unit->info_range.min, unit->address_size, arch, unit->version, unit->ext, unit->format); str8_list_pushf(scratch.arena, &attrib_fmt, "{ %S }", exprloc_str); }break; case DW_AttribClass_Flag: { B32 flag = dw_flag_from_attrib(input, unit, attrib); str8_list_pushf(scratch.arena, &attrib_fmt, "%llu (%s)", flag, flag == 0 ? "false" : "true"); }break; case DW_AttribClass_LinePtr: case DW_AttribClass_LocListPtr: case DW_AttribClass_MacPtr: case DW_AttribClass_RngListPtr: case DW_AttribClass_RngList: case DW_AttribClass_StrOffsetsPtr: case DW_AttribClass_AddrPtr: { if(attrib->form_kind == DW_Form_SecOffset) { str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", attrib->form.sec_offset); } else { str8_list_pushf(scratch.arena, &attrib_fmt, "`unexpected form kind %S`", dw_string_from_form_kind(scratch.arena, unit->version, attrib->form_kind)); } }break; case DW_AttribClass_Reference: { if(attrib->form_kind == DW_Form_Ref1 || attrib->form_kind == DW_Form_Ref2 || attrib->form_kind == DW_Form_Ref4 || attrib->form_kind == DW_Form_Ref8 || attrib->form_kind == DW_Form_RefUData) { U64 info_off = unit->info_range.min + attrib->form.ref; str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", info_off); if(!contains_1u64(unit->info_range, info_off)) { str8_list_pushf(scratch.arena, &attrib_fmt, ": `(out of this unit's bounds)`"); } } else { str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x", attrib->form.ref); } }break; case DW_AttribClass_String: { if(attrib->form_kind == DW_Form_Strp || attrib->form_kind == DW_Form_LineStrp || attrib->form_kind == DW_Form_StrpSup) { str8_list_pushf(scratch.arena, &attrib_fmt, "0x%I64x ", attrib->form.sec_offset); } String8 string = dw_string_from_attrib(input, unit, attrib); str8_list_pushf(scratch.arena, &attrib_fmt, "\"%S\"", string); }break; } // rjf: extend attrib's value with enum info { String8 enum_info = {0}; switch(attrib->attrib_kind) { case DW_AttribKind_Language: { DW_Language lang = dw_const_u64_from_attrib(input, unit, attrib); enum_info = dw_string_from_language(scratch.arena, lang); }break; case DW_AttribKind_DeclFile: { U64 file_idx = dw_const_u64_from_attrib(input, unit, attrib); DW_LineFile *file = dw_file_from_attrib(unit, line_vm, attrib); if(file != 0) { enum_info = dw_path_from_file(scratch.arena, line_vm, file); } }break; case DW_AttribKind_DeclLine: { enum_info = str8f(scratch.arena, "%I64u", dw_const_u64_from_attrib(input, unit, attrib)); }break; case DW_AttribKind_Inline: { DW_InlKind inl = dw_const_u64_from_attrib(input, unit, attrib); enum_info = dw_string_from_inl(scratch.arena, inl); }break; case DW_AttribKind_Accessibility: { DW_AccessKind access = dw_const_u64_from_attrib(input, unit, attrib); enum_info = dw_string_from_access_kind(scratch.arena, access); }break; case DW_AttribKind_CallingConvention: { DW_CallingConventionKind calling_convetion = dw_const_u64_from_attrib(input, unit, attrib); enum_info = dw_string_from_calling_convetion(scratch.arena, calling_convetion); }break; case DW_AttribKind_Encoding: { DW_ATE encoding = dw_const_u64_from_attrib(input, unit, attrib); enum_info = dw_string_from_attrib_type_encoding(scratch.arena, encoding); }break; } if(enum_info.size) { str8_list_pushf(scratch.arena, &attrib_fmt, " `%S`", enum_info); } } String8 result = str8_list_join(arena, &attrib_fmt, 0); scratch_end(scratch); return result; } internal String8List dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubsetFlags subset_flags) { String8List strings = {0}; String8 indent = str8_lit(" "); #define dump(str) str8_list_push(arena, &strings, (str)) #define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__) #define DumpSubset(name) if(subset_flags & DW_DumpSubsetFlag_##name) DeferLoop(dumpf("// %S\n\n", dw_name_title_from_dump_subset_table[DW_DumpSubset_##name]), dump(str8_lit("\n"))) Temp scratch = scratch_begin(&arena, 1); Rng1U64Array segment_vranges = {0}; DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input); B32 relaxed = 1; DW_CompUnit *cu_arr; { DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input); Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data); Rng1U64Array cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); cu_arr = push_array(scratch.arena, DW_CompUnit, cu_ranges.count); for EachIndex(cu_idx, cu_ranges.count) { cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, input, lu_input, cu_ranges.v[cu_idx].min, relaxed); } } ////////////////////////////// //- rjf: dump .debug_info // DumpSubset(DebugInfo) { Rng1U64List unit_ranges_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data); Rng1U64Array unit_ranges = rng1u64_array_from_list(scratch.arena, &unit_ranges_list); for EachIndex(unit_idx, unit_ranges.count) { Temp unit_temp = temp_begin(scratch.arena); //- rjf: unpack unit Rng1U64 unit_range = unit_ranges.v[unit_idx]; DW_CompUnit *unit = &cu_arr[unit_idx]; String8 unit_dir = dw_string_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_CompDir ); String8 unit_name = dw_string_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_Name ); String8 stmt_list = dw_line_ptr_from_tag_attrib_kind(input, unit, unit->tag, DW_AttribKind_StmtList); DW_LineVMHeader line_vm = {0}; dw_read_line_vm_header(unit_temp.arena, stmt_list, 0, input, unit_dir, unit_name, unit->address_size, unit->str_offsets_lu, &line_vm); //- rjf: log top-level unit info dumpf("unit: // compile_unit[%I64u]\n{\n", unit_idx); dumpf(" version: %u\n", unit->version); dumpf(" address_size: %I64u\n", unit->address_size); dumpf(" abbrev_off: 0x%I64x\n", unit->abbrev_off); dumpf(" info_range: [0x%I64x, 0x%I64x) // (%M)\n", unit->info_range.min, unit->info_range.max, dim_1u64(unit->info_range)); //- rjf: log tags S64 tag_depth = 0; U64 tag_idx = 0; for(U64 info_off = unit->first_tag_info_off; info_off < unit->info_range.max; tag_idx += 1) { Temp tag_temp = temp_begin(scratch.arena); // rjf: unpack tag String8 tag_indent = str8_prefix(indent, (tag_depth+1)*2); U64 tag_info_off = info_off; DW_Tag tag = {0}; info_off += dw_read_tag_cu(tag_temp.arena, input, unit, tag_info_off, &tag); // rjf: log top-level tag info dumpf("%Stag: // info_off: 0x%I64x, abbrev_id: %I64u, compile_unit[%I64u].tag[%I64u]\n%S{\n", tag_indent, tag_info_off, tag.abbrev_id, unit_idx, tag_idx, tag_indent); dumpf("%S kind: %S\n", tag_indent, dw_string_from_tag_kind(tag_temp.arena, tag.kind)); // log attribs { // compute columns' max widths U64 attrib_name_max_size = 0, form_kind_max_size = 0, value_max_size = 0; for EachNode(attrib_n, DW_AttribNode, tag.attribs.first) { Temp attrib_temp = temp_begin(tag_temp.arena); attrib_name_max_size = Max(attrib_name_max_size, dw_string_from_attrib_kind(attrib_temp.arena, unit->version, unit->ext, attrib_n->v.attrib_kind).size); form_kind_max_size = Max(form_kind_max_size, dw_string_from_form_kind(attrib_temp.arena, unit->version, attrib_n->v.form_kind).size); value_max_size = Max(value_max_size, dw_string_from_attrib_value(attrib_temp.arena, input, arch, unit, &line_vm, &attrib_n->v).size); temp_end(attrib_temp); } value_max_size = Min(120, value_max_size); // log for EachNode(attrib_n, DW_AttribNode, tag.attribs.first) { DW_Attrib *attrib = &attrib_n->v; Temp attrib_temp = temp_begin(tag_temp.arena); String8 attrib_kind_str = dw_string_from_attrib_kind(attrib_temp.arena, unit->version, unit->ext, attrib->attrib_kind); String8 form_kind_str = dw_string_from_form_kind(attrib_temp.arena, unit->version, attrib->form_kind); String8 value_str = dw_string_from_attrib_value(attrib_temp.arena, input, arch, unit, &line_vm, attrib); dumpf("%S attrib: { kind: %S, %.*sform_kind: %S, %.*svalue: %S, %.*s} // info_off: 0x%I64x\n", tag_indent, attrib_kind_str, attrib_name_max_size - attrib_kind_str.size, indent.str, form_kind_str, form_kind_max_size - form_kind_str.size, indent.str, value_str, value_str.size < value_max_size ? value_max_size - value_str.size: 0, indent.str, attrib->info_off, unit_idx, tag_idx); temp_end(attrib_temp); } } // rjf: log tag closes if(!tag.has_children || tag.abbrev_id == 0) { dumpf("%S}\n", tag_indent); } // rjf: indent/unindent if(tag.has_children) { tag_depth += 1; } if(!tag.abbrev_id) { tag_depth -= 1; } temp_end(tag_temp); } temp_end(unit_temp); dumpf("} // compile_unit[/%u]\n\n", unit_idx); } } ////////////////////////////// //- rjf: dump .debug_abbrev // DumpSubset(DebugAbbrev) { Temp scratch = scratch_begin(&arena, 1); DW_Section abbrev = input->sec[DW_Section_Abbrev]; S64 depth = 0; U64 idx = 0; for(U64 cursor = 0; cursor < abbrev.data.size; idx += 1) { // rjf: read id & advance U64 id_off = cursor; U64 id = 0; cursor += str8_deserial_read_uleb128(abbrev.data, cursor, &id); if(id == 0) { continue; } // rjf: unpack abbrev U64 tag = 0; U8 has_children = 0; cursor += str8_deserial_read_uleb128(abbrev.data, cursor, &tag); cursor += str8_deserial_read_struct(abbrev.data, cursor, &has_children); // rjf: log abbrev Temp temp = temp_begin(scratch.arena); dumpf("abbrev: // abbrev[%I64u]\n{\n", idx); dumpf(" offset: 0x%I64x\n", id_off); dumpf(" id: %I64u\n", id); dumpf(" tag_kind: %S\n", dw_string_from_tag_kind(temp.arena, tag)); dumpf(" has_children: %s\n", has_children ? "true" : "false"); for(;;) { U64 attrib_off = cursor; U64 attrib_id = 0, form_id = 0; cursor += str8_deserial_read_uleb128(abbrev.data, cursor, &attrib_id); cursor += str8_deserial_read_uleb128(abbrev.data, cursor, &form_id); if(attrib_id == 0) { break; } String8 attrib_str = dw_string_from_attrib_kind(temp.arena, DW_Version_Last, DW_Ext_All, attrib_id); String8 form_str = dw_string_from_form_kind(temp.arena, DW_Version_Last, form_id); dumpf(" attrib: { offset: 0x%I64x, kind: %S, form_kind: %S }\n", attrib_off, attrib_str, form_str); } dumpf("}\n"); temp_end(temp); } scratch_end(scratch); } ////////////////////////////// //- rjf: dump .debug_line // DumpSubset(DebugLine) { Rng1U64List unit_ranges_list = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Line].data); Rng1U64Array unit_ranges = rng1u64_array_from_list(scratch.arena, &unit_ranges_list); for EachIndex(unit_idx, unit_ranges.count) { Temp unit_temp = temp_begin(scratch.arena); // rjf: unpack unit String8 raw_lines = str8_substr(input->sec[DW_Section_Line].data, unit_ranges.v[unit_idx]); DW_CompUnit *cu = &cu_arr[unit_idx]; String8 cu_stmt_list = dw_line_ptr_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_StmtList); String8 cu_dir = dw_string_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_CompDir); String8 cu_name = dw_string_from_tag_attrib_kind(input, cu, cu->tag, DW_AttribKind_Name); DW_LineVMHeader line_vm = {0}; U64 line_vm_size = dw_read_line_vm_header(unit_temp.arena, raw_lines, 0, input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu, &line_vm); if(line_vm_size == 0) { continue; } // rjf: begin logging line table dumpf("line_table: // line_table[%I64u]\n{\n", unit_idx); // rjf: log line table header DeferLoop(dumpf(" header:\n {\n"), dumpf(" }\n\n")) { String8List opcode_length_strings = numeric_str8_list_from_data(unit_temp.arena, 16, str8(line_vm.opcode_lens, line_vm.num_opcode_lens), 1); String8 opcode_lengths_string = str8_list_join(arena, &opcode_length_strings, &(StringJoin){.sep = str8_lit(", ")}); dumpf(" version: %u\n", line_vm.version ); dumpf(" line_table_off: 0x%I64x\n", line_vm.unit_range.min ); dumpf(" line_table_size: %I64u\n", dim_1u64(line_vm.unit_range) ); dumpf(" address_size: %u\n", line_vm.address_size ); dumpf(" segment_selector_size: %u\n", line_vm.segment_selector_size); dumpf(" header_length: %I64u\n", line_vm.header_length ); dumpf(" min_instruction_length: %u\n", line_vm.min_inst_len ); dumpf(" max_ops_for_instruction: %u\n", line_vm.max_ops_for_inst ); dumpf(" default_is_stmt: %u\n", line_vm.default_is_stmt ); dumpf(" line_base: %d\n", line_vm.line_base ); dumpf(" line_range: %u\n", line_vm.line_range ); dumpf(" opcode_base: %u\n", line_vm.opcode_base ); dumpf(" opcode_lengths: %S\n", opcode_lengths_string ); } // rjf: log directory table DeferLoop(dumpf(" directory_table:\n {\n"), dumpf(" }\n\n")) { dumpf(" // %-4s %-8s\n", "no.", "name"); for EachIndex(dir_idx, line_vm.dir_table.count) { dumpf(" { %-4llu %S }\n", dir_idx, line_vm.dir_table.v[dir_idx]); } } // rjf: log file table DeferLoop(dumpf(" file_table:\n {\n"), dumpf(" }\n\n")) { dumpf(" // %-4s %-8s %-8s %-33s %-8s %-8s\n", "no.", "dir_idx", "time", "md5", "size", "name"); for EachIndex(file_idx, line_vm.file_table.count) { DW_LineFile *file = &line_vm.file_table.v[file_idx]; dumpf(" { %-4llu %-8llu %-8llu %016llx-%016llx %-8llu %S }\n", file_idx, file->dir_idx, file->modify_time, file->md5_digest.u64[1], file->md5_digest.u64[0], file->file_size, file->file_name); } } // rjf: log opcodes DeferLoop(dumpf(" opcodes:\n {\n"), dumpf(" }\n\n")) { String8 opcodes = str8_skip(raw_lines, line_vm_size); B32 end_of_seq = 0; DW_LineVMState vm_state = {0}; dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); for(U64 cursor = 0; cursor < opcodes.size;) { Temp opcode_temp = temp_begin(unit_temp.arena); String8List opcode_fmt = {0}; // opcode offset str8_list_pushf(opcode_temp.arena, &opcode_fmt, "[%08llx]", cursor); // parse opcode U8 opcode = 0; cursor += str8_deserial_read_struct(opcodes, cursor, &opcode); // push opcode id String8 opcode_str = dw_string_from_std_opcode(opcode_temp.arena, opcode); str8_list_push(arena, &opcode_fmt, opcode_str); // format operands switch(opcode) { default: { if(opcode >= line_vm.opcode_base) { U32 adjusted_opcode = 0; U32 op_advance = 0; S32 line_advance = 0; U64 addr_advance = 0; if(line_vm.line_range > 0 && line_vm.max_ops_for_inst > 0) { adjusted_opcode = (U32)(opcode - line_vm.opcode_base); op_advance = adjusted_opcode / line_vm.line_range; line_advance = (S32)line_vm.line_base + ((S32)adjusted_opcode) % (S32)line_vm.line_range; addr_advance = line_vm.min_inst_len * ((vm_state.op_index+op_advance) / line_vm.max_ops_for_inst); } vm_state.address += addr_advance; vm_state.op_index = (vm_state.op_index + op_advance) % line_vm.max_ops_for_inst; vm_state.line = (U32)((S32)vm_state.line + line_advance); vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; vm_state.discriminator = 0; end_of_seq = 0; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance line by %d, advance address by %lld", line_advance, addr_advance); } else { if(opcode > 0 && opcode <= line_vm.num_opcode_lens) { str8_list_pushf(opcode_temp.arena, &opcode_fmt, "skip operands:"); U64 num_operands = line_vm.opcode_lens[opcode - 1]; for(U8 i = 0; i < num_operands; i += 1) { U64 operand = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &operand); str8_list_pushf(opcode_temp.arena, &opcode_fmt, " %llx", operand); } } } }break; case DW_StdOpcode_Copy: { str8_list_pushf(opcode_temp.arena, &opcode_fmt, "Line = %u, Column = %u, Address = %#llx", vm_state.line, vm_state.column, vm_state.address); end_of_seq = 0; vm_state.discriminator = 0; vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; }break; case DW_StdOpcode_AdvancePc: { U64 advance = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &advance); dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %#llx ; current address %#llx", advance, vm_state.address); }break; case DW_StdOpcode_AdvanceLine: { S64 advance = 0; cursor += str8_deserial_read_sleb128(opcodes, cursor, &advance); vm_state.line += advance; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %lld ; current line %u", advance, vm_state.line); }break; case DW_StdOpcode_SetFile: { U64 file_idx = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_idx); vm_state.file_index = file_idx; String8 path = dw_path_from_file_idx(opcode_temp.arena, &line_vm, file_idx); str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu \"%S\"", file_idx, path); }break; case DW_StdOpcode_SetColumn: { U64 column = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &column); vm_state.column = column; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", column); }break; case DW_StdOpcode_NegateStmt: { vm_state.is_stmt = !vm_state.is_stmt; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "is_stmt = %u", vm_state.is_stmt); }break; case DW_StdOpcode_SetBasicBlock: { vm_state.basic_block = 1; }break; case DW_StdOpcode_ConstAddPc: { U64 advance = (0xffu - line_vm.opcode_base)/line_vm.line_range; dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%lld ; address %#llx", advance, vm_state.address); }break; case DW_StdOpcode_FixedAdvancePc: { U64 operand = 0; cursor += str8_deserial_read_struct(opcodes, cursor, &operand); vm_state.address += operand; vm_state.op_index = 0; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", operand); }break; case DW_StdOpcode_SetPrologueEnd: { vm_state.prologue_end = 1; }break; case DW_StdOpcode_SetEpilogueBegin: { vm_state.epilogue_begin = 1; }break; case DW_StdOpcode_SetIsa: { U64 v = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &v); vm_state.isa = v; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", v); }break; case DW_StdOpcode_ExtendedOpcode: { U64 length = 0; U8 ext_opcode = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &length); U64 opcode_end = cursor + length; cursor += str8_deserial_read_struct(opcodes, cursor, &ext_opcode); String8 ext_opcode_str = dw_string_from_ext_opcode(opcode_temp.arena, ext_opcode); //str8_list_pushf(opcode_temp.arena, &opcode_fmt, "length: %u", length); str8_list_push(opcode_temp.arena, &opcode_fmt, ext_opcode_str); switch(ext_opcode) { case DW_ExtOpcode_EndSequence: { vm_state.end_sequence = 1; dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); end_of_seq = 1; }break; case DW_ExtOpcode_SetAddress: { U64 address = 0; cursor += str8_deserial_read(opcodes, cursor, &address, line_vm.address_size, line_vm.address_size); vm_state.address = address; vm_state.op_index = 0; str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%#llx", address); }break; case DW_ExtOpcode_DefineFile: { String8 file_name = {0}; cursor += str8_deserial_read_cstr(opcodes, cursor, &file_name); U64 dir_idx = 0, modify_time = 0, file_size = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &dir_idx); cursor += str8_deserial_read_uleb128(opcodes, cursor, &modify_time); cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_size); str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%S Dir: %llu, Time: %llu, Size: %llu", file_name, dir_idx, modify_time, file_size); }break; case DW_ExtOpcode_SetDiscriminator: { U64 v = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &v); vm_state.discriminator = v; str8_list_pushf(arena, &opcode_fmt, "%llu", v); }break; } cursor = opcode_end; }break; } String8 string = str8_list_join(opcode_temp.arena, &opcode_fmt, &(StringJoin){.sep=str8_lit(" ")}); dumpf("%S\n", string); temp_end(opcode_temp); } } temp_end(unit_temp); } } ////////////////////////////// //- rjf: dump .debug_str // DumpSubset(DebugStr) DeferLoop(dumpf("strings:\n{\n"), dumpf("}\n\n")) { String8 data = input->sec[DW_Section_Str].data; for(U64 cursor = 0, read_size = 0; cursor < data.size; cursor += read_size) { String8 string = {0}; read_size = str8_deserial_read_cstr(data, cursor, &string); dumpf(" { 0x%08I64x %llu \"%S\" }\n", cursor, string.size, string); } } ////////////////////////////// //~ dump .debug_frame DumpSubset(DebugFrame) { HashTable *cie_ht = hash_table_init(scratch.arena, 0x2000); String8 debug_frame = input->sec[DW_Section_Frame].data; U64 addr_size = byte_size_from_arch(arch); // make offset -> CIE hash table for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); if (desc.type == DW_DescriptorEntryType_CIE) { String8 raw_cie = str8_substr(debug_frame, desc.entry_range); U64 restore_pos = arena_pos(scratch.arena); DW_CIE *cie = push_array(scratch.arena, DW_CIE, 1); if (dw_parse_cie(raw_cie, desc.format, arch, cie)) { hash_table_push_u64_raw(scratch.arena, cie_ht, cursor, cie); } else { arena_pop_to(scratch.arena, restore_pos); } } } for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); String8 raw_desc = str8_substr(debug_frame, desc.entry_range); switch (desc.type) { case DW_DescriptorEntryType_Null: {} break; case DW_DescriptorEntryType_CIE: { DW_CIE cie = {0}; if (dw_parse_cie(raw_desc, desc.format, arch, &cie)) { String8List init_insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, DW_Version_5, DW_Ext_All, cie.format, 0, &cie, dw_decode_ptr_debug_frame, &cie, cie.insts); dumpf("CIE: // entry range: %r\n", desc.entry_range); dumpf("{\n"); dumpf(" Format: %S\n", dw_string_from_format(desc.format)); dumpf(" Version: %u\n", cie.version); dumpf(" Aug string: \"%S\"\n", cie.aug_string); dumpf(" Code align: %I64u\n", cie.code_align_factor); dumpf(" Data align: %I64d\n", cie.data_align_factor); dumpf(" Return addr reg: %u\n", cie.ret_addr_reg); if (cie.version > DW_Version_3) { dumpf(" Address size: %u\n", cie.address_size); dumpf(" Segment selector size: %u\n", cie.segment_selector_size); } dumpf(" Initial Insturction:\n"); dumpf(" {\n"); for EachNode(n, String8Node, init_insts_str_list.first) { dumpf(" %S\n", n->string); } dumpf(" }\n"); dumpf("}\n"); } else { dumpf("ERROR: unable to parse CIE @ %I64x\n", desc.entry_range.min); } } break; case DW_DescriptorEntryType_FDE: { DW_DescriptorEntry cie_desc = {0}; U64 cie_desc_size = dw_parse_descriptor_entry_header(debug_frame, desc.cie_pointer, &cie_desc); String8 cie_data = str8_substr(debug_frame, cie_desc.entry_range); DW_CIE cie = {0}; dw_parse_cie(cie_data, cie_desc.format, arch, &cie); DW_FDE fde = {0}; if (dw_parse_fde(raw_desc, desc.format, &cie, &fde)) { DW_Version version = DW_Version_5; DW_Ext ext = DW_Ext_All; String8List insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, version, ext, fde.format, fde.pc_range.min, &cie, dw_decode_ptr_debug_frame, &cie, fde.insts); dumpf("FDE: // entry range: %r\n", desc.entry_range); dumpf("{\n"); { dumpf(" Format: %S\n", dw_string_from_format(fde.format)); dumpf(" CIE pointer: 0x%I64x\n", fde.cie_pointer); dumpf(" PC range: %r\n", fde.pc_range); dumpf(" Instructions:\n"); dumpf(" {\n"); for EachNode(n, String8Node, insts_str_list.first) { dumpf(" %S\n", n->string); } dumpf(" }\n"); } dumpf(" Unwind:\n"); dumpf(" {\n"); DW_CFI_Unwind *cfi_unwind = dw_cfi_unwind_init(scratch.arena, arch, &cie, &fde, dw_decode_ptr_debug_frame, &cie); do { String8 cfa_str = dw_string_from_cfa(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row->cfa); String8 cfi_regs_str = dw_string_from_cfi_row(scratch.arena, arch, cie.address_size, version, ext, fde.format, cfi_unwind->row); dumpf(" { PC: 0x%I64x, CFA: %-7S, Rules: { %S }\n", cfi_unwind->pc, cfa_str, cfi_regs_str); } while (dw_cfi_next_row(scratch.arena, cfi_unwind)); dumpf(" }\n"); dumpf("}\n"); } else { dumpf("ERROR: unable to parse FDE @ %I64x\n", desc.entry_range.min); } } break; } } } ////////////////////////////// //- rjf: dump .debug_loc // DumpSubset(DebugLoc) { // dw_print_debug_loc(arena, out, indent, input, arch, image_type, relaxed); } ////////////////////////////// //- rjf: dump .debug_ranges // DumpSubset(DebugRanges) { // dw_print_debug_ranges(arena, out, indent, input, arch, image_type, relaxed); } ////////////////////////////// //- rjf: dump .debug_aranges // DumpSubset(DebugARanges) { // dw_print_debug_aranges(arena, out, indent, input); } ////////////////////////////// //- rjf: dump .debug_addr // DumpSubset(DebugAddr) { // dw_print_debug_addr(arena, out, indent, input); } ////////////////////////////// //- rjf: dump .debug_loclists // DumpSubset(DebugLocLists) { // dw_print_debug_loclists(arena, out, indent, input, segment_vranges, arch); } ////////////////////////////// //- rjf: dump .debug_rnglists // DumpSubset(DebugRngLists) { // dw_print_debug_rnglists(arena, out, indent, input, segment_vranges); } ////////////////////////////// //- rjf: dump .debug_pubnames // DumpSubset(DebugPubNames) { // dw_print_debug_pubnames(arena, out, indent, input); } ////////////////////////////// //- rjf: dump .debug_pubtypes // DumpSubset(DebugPubTypes) { // dw_print_debug_pubtypes(arena, out, indent, input); } ////////////////////////////// //- rjf: dump .debug_linestr // DumpSubset(DebugLineStr) { // dw_print_debug_line_str(arena, out, indent, input); } ////////////////////////////// //- rjf: dump .debug_stroffs // DumpSubset(DebugStrOffsets) { // dw_print_debug_str_offsets(arena, out, indent, input); } scratch_end(scratch); #undef DumpSubset #undef dumpf #undef dump return strings; } ================================================ FILE: src/dwarf/dwarf_dump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_DUMP_H #define DWARF_DUMP_H //////////////////////////////// //~ rjf: Dump Subset Types #define DW_DumpSubset_XList \ X(DebugInfo, debug_info, "DEBUG INFO") \ X(DebugAbbrev, debug_abbrev, "DEBUG ABBREV") \ X(DebugLine, debug_line, "DEBUG LINE") \ X(DebugStr, debug_str, "DEBUG STR") \ X(DebugLoc, debug_loc, "DEBUG LOC") \ X(DebugRanges, debug_ranges, "DEBUG RANGES") \ X(DebugARanges, debug_aranges, "DEBUG ARANGES") \ X(DebugAddr, debug_addr, "DEBUG ADDR") \ X(DebugLocLists, debug_loclists, "DEBUG LOCLISTS") \ X(DebugRngLists, debug_rnglists, "DEBUG RNGLISTS") \ X(DebugPubNames, debug_pubnames, "DEBUG PUBNAMES") \ X(DebugPubTypes, debug_pubtypes, "DEBUG PUBTYPES") \ X(DebugLineStr, debug_linestr, "DEBUG LINESTR") \ X(DebugStrOffsets, debug_stroff, "DEBUG STROFF") \ X(DebugFrame, debug_frame, "DEBUG FRAME") \ typedef enum DW_DumpSubset { #define X(name, name_lower, title) DW_DumpSubset_##name, DW_DumpSubset_XList #undef X } DW_DumpSubset; typedef U32 DW_DumpSubsetFlags; enum { #define X(name, name_lower, title) DW_DumpSubsetFlag_##name = (1<shdrs.count) { ELF_Shdr64 *shdr = &bin->shdrs.v[idx]; if(shdr->sh_type != ELF_ShType_ProgBits) { continue; } String8 name = elf_name_from_shdr64(data, bin, shdr); DW_SectionKind s = dw_section_kind_from_string(name); if(s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); } is_dwarf_present = (s != DW_Section_Null); if(is_dwarf_present) { break; } } return is_dwarf_present; } #define SINFL_IMPLEMENTATION #include "third_party/sinfl/sinfl.h" internal DW_Input dw_input_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin) { DW_Input result = {0}; B32 is_section_present[ArrayCount(result.sec)] = {0}; for(U64 section_idx = 1; section_idx < bin->shdrs.count; section_idx += 1) { ELF_Shdr64 *shdr = &bin->shdrs.v[section_idx]; if(shdr->sh_type != ELF_ShType_ProgBits) { continue; } // skip BSS sections //- rjf: unpack section String8 section_name = elf_name_from_shdr64(data, bin, shdr); DW_SectionKind section_kind = dw_section_kind_from_string(section_name); String8 section_data__maybe_compressed = str8_substr(data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size)); B32 is_dwo = 0; if(section_kind == DW_Section_Null) { section_kind = dw_section_dwo_kind_from_string(section_name); is_dwo = (section_kind != DW_Section_Null); } if(section_kind == DW_Section_Null) { continue; } // skip unknown sections if(is_section_present[section_kind]) { continue; } // skip duplicate sections //- rjf: decompress section data if needed String8 section_data__uncompressed = {0}; if(!(shdr->sh_flags & ELF_Shf_Compressed)) { section_data__uncompressed = section_data__maybe_compressed; } else { // rjf: read compressed-section header ELF_Chdr64 chdr64 = {0}; U64 chdr_size = 0; if(ELF_HdrIs64Bit(bin->hdr.e_ident)) { chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr64); } else if(ELF_HdrIs32Bit(bin->hdr.e_ident)) { ELF_Chdr32 chdr32 = {0}; chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32); if(chdr_size == sizeof(chdr32)) { chdr64 = elf_chdr64_from_chdr32(chdr32); } } // rjf: decompress { String8 section_data__compressed_contents = str8_skip(section_data__maybe_compressed, chdr_size); switch(chdr64.ch_type) { case ELF_CompressType_None: { section_data__uncompressed = section_data__compressed_contents; }break; case ELF_CompressType_ZLib: { U8 *section_data_uncompressed_buffer = push_array_no_zero_aligned(arena, U8, chdr64.ch_size, chdr64.ch_addr_align); U64 section_data_uncompressed_size = zsinflate(section_data_uncompressed_buffer, chdr64.ch_size, section_data__compressed_contents.str, section_data__compressed_contents.size); section_data__uncompressed = str8(section_data_uncompressed_buffer, section_data_uncompressed_size); }break; case ELF_CompressType_ZStd: { NotImplemented; }break; default: { NotImplemented; }break; } } } //- rjf: store is_section_present[section_kind] = 1; DW_Section *d = &result.sec[section_kind]; d->name = push_str8_copy(arena, section_name); d->data = section_data__uncompressed; d->is_dwo = is_dwo; } return result; } ================================================ FILE: src/dwarf/dwarf_elf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_ELF_H #define DWARF_ELF_H internal B32 dw_is_dwarf_present_from_elf_bin(String8 raw_image, ELF_Bin *bin); internal DW_Input dw_input_from_elf_bin(Arena *arena, String8 raw_image, ELF_Bin *bin); #endif // DWARF_ELF_H ================================================ FILE: src/dwarf/dwarf_expr.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- analyzers #if 0 internal DW_SimpleLoc dw_expr__analyze_fast(void *base, Rng1U64 range, U64 text_section_base) { DW_SimpleLoc result = {DW_SimpleLocKind_Empty}; String8 expr_data = str8((U8*)data+range.min, (U8*)data+range.max); U8 op = 0; if (str8_deserial_read_struct(expr_data, 0, &op)) { // step params U64 size_param = 0; B32 is_signed = 0; // step U64 step_cursor = 1; switch (op) { //// literal encodings //// case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { U64 x = op - DW_ExprOp_Lit0; result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; case DW_ExprOp_Const1U:size_param = 1; goto const_n; case DW_ExprOp_Const2U:size_param = 2; goto const_n; case DW_ExprOp_Const4U:size_param = 4; goto const_n; case DW_ExprOp_Const8U:size_param = 8; goto const_n; case DW_ExprOp_Const1S:size_param = 1; is_signed = 1; goto const_n; case DW_ExprOp_Const2S:size_param = 2; is_signed = 1; goto const_n; case DW_ExprOp_Const4S:size_param = 4; is_signed = 1; goto const_n; case DW_ExprOp_Const8S:size_param = 8; is_signed = 1; goto const_n; const_n: { U64 x = 0; step_cursor += dw_based_range_read(base, range, step_cursor, size_param, &x); if (is_signed) { x = extend_sign64(x, size_param); } result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; case DW_ExprOp_Addr: { U64 offset = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 8, &offset); U64 x = text_section_base + offset; result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; case DW_ExprOp_ConstU: { U64 x = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &x); result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; case DW_ExprOp_ConstS: { U64 x = 0; step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, (S64*)&x); result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; //// register location descriptions //// case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { U64 reg_idx = op - DW_ExprOp_Reg0; result.kind = DW_SimpleLocKind_Register; result.reg_idx = reg_idx; } break; case DW_ExprOp_RegX: { U64 reg_idx = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, ®_idx); result.kind = DW_SimpleLocKind_Register; result.reg_idx = reg_idx; } break; //// implicit location descriptions //// case DW_ExprOp_ImplicitValue: { U64 size = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &size); if (step_cursor + size <= range.max) { result.kind = DW_SimpleLocKind_ValueLong; result.val_long.str = (U8*)base + range.min + step_cursor; result.val_long.size = size; } step_cursor += size; } break; case DW_ExprOp_StackValue: { // this op pops from the value stack, so if it comes first the dwarf expression is bad. result.kind = DW_SimpleLocKind_Fail; result.fail_kind = DW_LocFailKind_BadData; } break; //// composite location descriptions //// // if the first and only op is a piece, the expression is empty case DW_ExprOp_Piece: { U64 size = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &size); result.kind = DW_SimpleLocKind_Empty; } break; case DW_ExprOp_BitPiece: { U64 bit_size = 0, bit_off = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &bit_size); step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &bit_off); result.kind = DW_SimpleLocKind_Empty; } break; //// final fallback //// default: { result.kind = DW_SimpleLocKind_Fail; result.fail_kind = DW_LocFailKind_TooComplicated; } break; } // check this was the whole expression if (range.min + step_cursor < range.max) { result.kind = DW_SimpleLocKind_Fail; result.fail_kind = DW_LocFailKind_TooComplicated; } } return result; } internal DW_ExprAnalysis dw_expr__analyze_details(void *in_base, Rng1U64 in_range, DW_ExprMachineCallConfig *call_config) { Temp scratch = scratch_begin(0, 0); DW_ExprAnalysis result = {0}; // are we resolving calls? B32 has_call_func = (call_config != 0 && call_config->func != 0); // tasks DW_ExprAnalysisTask *unfinished_tasks = 0; DW_ExprAnalysisTask *finished_tasks = 0; // convert range input to string String8 in_data = str8((U8*)in_base + in_range.min, in_range.max - in_range.min); // put input task onto the list { DW_ExprAnalysisTask *new_task = push_array(scratch.arena, DW_ExprAnalysisTask, 1); new_task->p = max_U64; new_task->data = in_data; SLLStackPush(unfinished_tasks, new_task); } // state for checking implicit locations B32 last_was_implicit_loc = 0; // task loop for (;;) { // get next task to handle DW_ExprAnalysisTask *task = unfinished_tasks; if (task == 0) { break; } String8 task_data = task->data; U8 *task_base = task_data.str; Rng1U64 task_range = rng_1u64(0, task_data.size); // move the task to finished now SLLStackPop(unfinished_tasks); SLLStackPush(finished_tasks, task); // analysis loop for (U64 cursor = 0;;) { // decode op U64 op_offset = cursor; U8 op = 0; if (dw_based_range_read(task_base, task_range, op_offset, 1, &op)) { U64 after_op_off = cursor + 1; // require piece op after 'implicit' location descriptions if (last_was_implicit_loc) { if (op != DW_ExprOp_Piece && op != DW_ExprOp_BitPiece) { result.flags |= DW_ExprFlag_BadData; goto finish; } } // step params U64 size_param = 0; B32 is_signed = 0; // step U64 step_cursor = after_op_off; switch (op) { //// literal encodings //// case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: break; case DW_ExprOp_Const1U:size_param = 1; goto const_n; case DW_ExprOp_Const2U:size_param = 2; goto const_n; case DW_ExprOp_Const4U:size_param = 4; goto const_n; case DW_ExprOp_Const8U:size_param = 8; goto const_n; case DW_ExprOp_Const1S:size_param = 1; is_signed = 1; goto const_n; case DW_ExprOp_Const2S:size_param = 2; is_signed = 1; goto const_n; case DW_ExprOp_Const4S:size_param = 4; is_signed = 1; goto const_n; case DW_ExprOp_Const8S:size_param = 8; is_signed = 1; goto const_n; const_n: { U64 x = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, size_param, &x); } break; case DW_ExprOp_Addr: { U64 offset = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, 8, &offset); result.flags |= DW_ExprFlag_UsesTextBase; } break; case DW_ExprOp_ConstU: { U64 x = 0; step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, &x); } break; case DW_ExprOp_ConstS: { U64 x = 0; step_cursor += dw_based_range_read_sleb128(task_base, task_range, step_cursor, (S64*)&x); } break; //// register based addressing //// case DW_ExprOp_FBReg: { S64 offset = 0; step_cursor += dw_based_range_read_sleb128(task_base, task_range, step_cursor, &offset); result.flags |= DW_ExprFlag_UsesFrameBase; } break; case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { S64 offset = 0; step_cursor += dw_based_range_read_sleb128(task_base, task_range, step_cursor, &offset); result.flags |= DW_ExprFlag_UsesRegisters; } break; case DW_ExprOp_BRegX: { U64 reg_idx = 0; S64 offset = 0; step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, ®_idx); step_cursor += dw_based_range_read_sleb128(task_base, task_range, step_cursor, &offset); result.flags |= DW_ExprFlag_UsesRegisters; } break; //// stack operations //// case DW_ExprOp_Dup: case DW_ExprOp_Drop: break; case DW_ExprOp_Pick: { U64 idx = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, 1, &idx); } break; case DW_ExprOp_Over: case DW_ExprOp_Swap: case DW_ExprOp_Rot: break; case DW_ExprOp_Deref: { result.flags |= DW_ExprFlag_UsesMemory; } break; case DW_ExprOp_DerefSize: { U64 size = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, 1, &size); result.flags |= DW_ExprFlag_UsesMemory; } break; case DW_ExprOp_XDeref: case DW_ExprOp_XDerefSize: { result.flags |= DW_ExprFlag_NotSupported; } goto finish; case DW_ExprOp_PushObjectAddress: { result.flags |= DW_ExprFlag_UsesObjectAddress; } break; case DW_ExprOp_GNU_PushTlsAddress: case DW_ExprOp_FormTlsAddress: { result.flags |= DW_ExprFlag_UsesTLSAddress; } break; case DW_ExprOp_CallFrameCfa: { result.flags |= DW_ExprFlag_UsesCFA; } break; //// arithmetic and logical operations //// case DW_ExprOp_Abs: case DW_ExprOp_And: case DW_ExprOp_Div: case DW_ExprOp_Minus: case DW_ExprOp_Mod: case DW_ExprOp_Mul: case DW_ExprOp_Neg: case DW_ExprOp_Not: case DW_ExprOp_Or: case DW_ExprOp_Plus: break; case DW_ExprOp_PlusUConst: { U64 y = 0; step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, &y); } break; case DW_ExprOp_Shl: case DW_ExprOp_Shr: case DW_ExprOp_Shra: case DW_ExprOp_Xor: break; //// control flow operations //// case DW_ExprOp_Le: case DW_ExprOp_Ge: case DW_ExprOp_Eq: case DW_ExprOp_Lt: case DW_ExprOp_Gt: case DW_ExprOp_Ne: break; case DW_ExprOp_Skip: case DW_ExprOp_Bra: { S16 d = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, 2, &d); result.flags |= DW_ExprFlag_NonLinearFlow; } break; case DW_ExprOp_Call2:size_param = 2; goto callN; case DW_ExprOp_Call4:size_param = 4; goto callN; callN: { U64 p = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, size_param, &p); result.flags |= DW_ExprFlag_UsesCallResolution|DW_ExprFlag_NonLinearFlow; // add to task list if (has_call_func) { DW_ExprAnalysisTask *existing = dw_expr__analysis_task_from_p(unfinished_tasks, p); if (existing == 0) { existing = dw_expr__analysis_task_from_p(finished_tasks, p);; } if (existing == 0) { DW_ExprAnalysisTask *new_task = push_array(scratch.arena, DW_ExprAnalysisTask, 1); new_task->p = p; new_task->data = call_config->func(call_config->user_ptr, p); SLLStackPush(unfinished_tasks, new_task); } } } break; case DW_ExprOp_CallRef: { result.flags |= DW_ExprFlag_NotSupported; } goto finish; //// special operations //// case DW_ExprOp_Nop:break; //// register location descriptions //// case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { last_was_implicit_loc = 1; } break; case DW_ExprOp_RegX: { U64 reg_idx = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, size_param, ®_idx); last_was_implicit_loc = 1; } break; //// implicit location descriptions //// case DW_ExprOp_ImplicitValue: { U64 size = 0; step_cursor += dw_based_range_read(task_base, task_range, step_cursor, size_param, &size); if (step_cursor + size > task_range.max) { result.flags |= DW_ExprFlag_BadData; goto finish; } step_cursor += size; last_was_implicit_loc = 1; } break; case DW_ExprOp_StackValue: { last_was_implicit_loc = 1; } break; //// composite location descriptions //// case DW_ExprOp_Piece: { U64 size = 0; step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, &size); result.flags |= DW_ExprFlag_UsesComposite; last_was_implicit_loc = 0; } break; case DW_ExprOp_BitPiece: { U64 bit_size = 0; U64 bit_off = 0; step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, &bit_size); step_cursor += dw_based_range_read_uleb128(task_base, task_range, step_cursor, &bit_off); result.flags |= DW_ExprFlag_UsesComposite; last_was_implicit_loc = 0; } break; //// final fallback //// default: { result.flags |= DW_ExprFlag_NotSupported; } goto finish; } // increment cursor cursor = step_cursor; } // check for end of task if (cursor < task_data.size) { goto finish_task; } } finish_task:; } finish:; scratch_end(scratch); return result; } #endif //- full eval internal DW_Location dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_ExprMachineConfig *config) { #if 0 Temp scratch = scratch_begin(&arena_optional, 1); DW_Location result = {0}; // setup stack DW_ExprStack stack = dw_expr__stack_make(scratch.arena); // adjust expr range void *expr_ptr = (U8*)expr_base + expr_range.min; U64 expr_size = expr_range.max - expr_range.min; // setup call stack DW_ExprCallStack call_stack = {0}; dw_expr__call_push(scratch.arena, &call_stack, expr_ptr, expr_size); // state variables DW_SimpleLoc stashed_loc = {DW_SimpleLocKind_Address}; // run loop U64 max_step_count = config->max_step_count; U64 step_counter = 0; for (;;) { // check top of stack DW_ExprCall *call = dw_expr__call_top(&call_stack); if (call == 0) { goto finish; } // grab top of stack details void *base = call->ptr; Rng1U64 range = rng_1u64(0, call->size); U64 cursor = call->cursor; // decode op U64 op_offset = cursor; U8 op = 0; if (dw_based_range_read(base, range, op_offset, 1, &op)) { U64 after_op_off = cursor + 1; // require piece op after 'implicit' location descriptions if (stashed_loc.kind != DW_SimpleLocKind_Address) { if (op != DW_ExprOp_Piece && op != DW_ExprOp_BitPiece) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_BadData; goto finish; } } // step params U64 size_param = 0; B32 is_signed = 0; // step U64 step_cursor = after_op_off; switch (op) { //// literal encodings //// case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { U64 x = op - DW_ExprOp_Lit0; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Const1U:size_param = 1; goto const_n; case DW_ExprOp_Const2U:size_param = 2; goto const_n; case DW_ExprOp_Const4U:size_param = 4; goto const_n; case DW_ExprOp_Const8U:size_param = 8; goto const_n; case DW_ExprOp_Const1S:size_param = 1; is_signed = 1; goto const_n; case DW_ExprOp_Const2S:size_param = 2; is_signed = 1; goto const_n; case DW_ExprOp_Const4S:size_param = 4; is_signed = 1; goto const_n; case DW_ExprOp_Const8S:size_param = 8; is_signed = 1; goto const_n; const_n: { U64 x = 0; step_cursor += dw_based_range_read(base, range, step_cursor, size_param, &x); if (is_signed) { x = extend_sign64(x, size_param); } dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Addr: { U64 offset = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 8, &offset); // earlier versions of GCC emit TLS offset with DW_ExprOp_Addr. B32 is_text_relative; { U8 next_op = 0; dw_based_range_read_struct(base, range, step_cursor, &next_op); is_text_relative = (next_op != DW_ExprOp_GNU_PushTlsAddress); } U64 addr = offset; if (is_text_relative) { if (config->text_section_base != 0) { addr += *config->text_section_base; } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingTextBase; goto finish; } } dw_expr__stack_push(scratch.arena, &stack, addr); } break; case DW_ExprOp_ConstU: { U64 x = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &x); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_ConstS: { U64 x = 0; step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, (S64*)&x); dw_expr__stack_push(scratch.arena, &stack, x); } break; //// register based addressing //// case DW_ExprOp_FBReg: { S64 offset = 0; step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, &offset); if (config->frame_base != 0) { U64 x = *config->frame_base + offset; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingFrameBase; goto finish; } } break; case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { S64 offset = 0; step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, &offset); U64 reg_idx = op - DW_ExprOp_BReg0; DW_RegsX64 *regs = config->regs; if (regs != 0) { if (reg_idx < ArrayCount(regs->r)) { U64 x = regs->r[reg_idx] + offset; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_BadData; stashed_loc.fail_data = op_offset; goto finish; } } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingRegisters; goto finish; } } break; case DW_ExprOp_BRegX: { U64 reg_idx = 0; S64 offset = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, ®_idx); step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, &offset); DW_RegsX64 *regs = config->regs; if (regs != 0) { if (reg_idx < ArrayCount(regs->r)) { U64 x = regs->r[reg_idx] + offset; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_BadData; stashed_loc.fail_data = op_offset; goto finish; } } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingRegisters; goto finish; } } break; //// stack operations //// case DW_ExprOp_Dup: { U64 x = dw_expr__stack_pick(&stack, 0); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Drop: { dw_expr__stack_pop(&stack); } break; case DW_ExprOp_Pick: { U64 idx = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 1, &idx); U64 x = dw_expr__stack_pick(&stack, idx); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Over: { U64 x = dw_expr__stack_pick(&stack, 1); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Swap: { U64 a = dw_expr__stack_pop(&stack); U64 b = dw_expr__stack_pop(&stack); dw_expr__stack_push(scratch.arena, &stack, b); dw_expr__stack_push(scratch.arena, &stack, a); } break; case DW_ExprOp_Rot: { U64 a = dw_expr__stack_pop(&stack); U64 b = dw_expr__stack_pop(&stack); U64 c = dw_expr__stack_pop(&stack); dw_expr__stack_push(scratch.arena, &stack, a); dw_expr__stack_push(scratch.arena, &stack, c); dw_expr__stack_push(scratch.arena, &stack, b); } break; case DW_ExprOp_Deref: { U64 addr = dw_expr__stack_pop(&stack); B32 read_success = 0; if (config->read_memory) { U64 x = 0; if (config->read_memory(addr, sizeof(x), &x, config->read_memory_ud) == sizeof(x)) { dw_expr__stack_push(scratch.arena, &stack, x); read_success = 1; } } if (!read_success) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingMemory; stashed_loc.fail_data = addr; goto finish; } } break; case DW_ExprOp_DerefSize: { U64 raw_size = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 1, &raw_size); U64 size = ClampTop(raw_size, 8); U64 addr = dw_expr__stack_pop(&stack); B32 read_success = 0; if (config->read_memory) { U64 x = 0; if (config->read_memory(addr, size, &x, config->read_memory_ud) == sizeof(x)) { dw_expr__stack_push(scratch.arena, &stack, x); read_success = 1; } } if (!read_success) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingMemory; stashed_loc.fail_data = addr; goto finish; } } break; case DW_ExprOp_XDeref: case DW_ExprOp_XDerefSize: { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_NotSupported; goto finish; } break; case DW_ExprOp_PushObjectAddress: { if (config->object_address != 0) { U64 x = *config->object_address; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingObjectAddress; goto finish; } } break; // NOTE: pop offset from stack, convert it to TLS address, then push it back. case DW_ExprOp_GNU_PushTlsAddress: case DW_ExprOp_FormTlsAddress: { S64 s = (S64)dw_expr__stack_pop(&stack); if (config->tls_address != 0) { U64 x = *config->tls_address + s; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingTLSAddress; goto finish; } } break; case DW_ExprOp_CallFrameCfa: { if (config->cfa != 0) { U64 x = *config->cfa; dw_expr__stack_push(scratch.arena, &stack, x); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingCFA; goto finish; } } break; //// arithmetic and logical operations //// case DW_ExprOp_Abs: { S64 s = (S64)dw_expr__stack_pop(&stack); S64 x = abs_s64(s); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_And: { U64 x = dw_expr__stack_pop(&stack); U64 y = dw_expr__stack_pop(&stack); dw_expr__stack_push(scratch.arena, &stack, x&y); } break; case DW_ExprOp_Div: { S64 d = (S64)dw_expr__stack_pop(&stack); S64 n = (S64)dw_expr__stack_pop(&stack); S64 x = (d == 0)?0:n/d; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Minus: { U64 b = dw_expr__stack_pop(&stack); U64 a = dw_expr__stack_pop(&stack); U64 x = a - b; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Mod: { S64 d = (S64)dw_expr__stack_pop(&stack); S64 n = (S64)dw_expr__stack_pop(&stack); S64 x = (d == 0)?0:n%d; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Mul: { U64 b = dw_expr__stack_pop(&stack); U64 a = dw_expr__stack_pop(&stack); U64 x = a*b; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Neg: { S64 s = (S64)dw_expr__stack_pop(&stack); S64 x = -s; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Not: { U64 y = dw_expr__stack_pop(&stack); U64 x = ~y; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Or: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = y | z; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Plus: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = y + z; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_PlusUConst: { U64 y = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &y); U64 z = dw_expr__stack_pop(&stack); U64 x = y + z; dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Shl: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = 0; if (y < 64) { x = z << y; } dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Shr: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = 0; if (y < 64) { x = z >> y; } dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Shra: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = 0; if (y < 64) { x = z >> y; // sign extensions if (y > 0 && (z & (1ull << 63))) { x |= ~((1 << (64 - y)) - 1); } } dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Xor: { U64 y = dw_expr__stack_pop(&stack); U64 z = dw_expr__stack_pop(&stack); U64 x = y ^ z; dw_expr__stack_push(scratch.arena, &stack, x); } break; //// control flow operations //// case DW_ExprOp_Le: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a <= b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Ge: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a >= b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Eq: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a == b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Lt: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a < b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Gt: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a > b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Ne: { S64 b = (S64)dw_expr__stack_pop(&stack); S64 a = (S64)dw_expr__stack_pop(&stack); U64 x = (a != b); dw_expr__stack_push(scratch.arena, &stack, x); } break; case DW_ExprOp_Skip: { S16 d = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 2, &d); step_cursor = step_cursor + d; } break; case DW_ExprOp_Bra: { S16 d = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 2, &d); U64 b = dw_expr__stack_pop(&stack); if (b != 0) { step_cursor = step_cursor + d; } } break; case DW_ExprOp_Call2: { U16 p = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 2, &p); if (config->call.func != 0) { String8 sub_data = config->call.func(config->call.user_ptr, p); dw_expr__call_push(scratch.arena, &call_stack, sub_data.str, sub_data.size); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingCallResolution; goto finish; } } break; case DW_ExprOp_Call4: { U32 p = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 4, &p); if (config->call.func != 0) { String8 sub_data = config->call.func(config->call.user_ptr, p); dw_expr__call_push(scratch.arena, &call_stack, sub_data.str, sub_data.size); } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingCallResolution; goto finish; } } break; case DW_ExprOp_CallRef: { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_NotSupported; goto finish; } break; //// special operations //// case DW_ExprOp_Nop:break; //// register location descriptions //// case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { U64 reg_idx = op - DW_ExprOp_Reg0; stashed_loc.kind = DW_SimpleLocKind_Register; stashed_loc.reg_idx = reg_idx; } break; case DW_ExprOp_RegX: { U64 reg_idx = 0; step_cursor += dw_based_range_read(base, range, step_cursor, size_param, ®_idx); stashed_loc.kind = DW_SimpleLocKind_Register; stashed_loc.reg_idx = reg_idx; } break; //// implicit location descriptions //// case DW_ExprOp_ImplicitValue: { U64 size = 0; step_cursor += dw_based_range_read(base, range, step_cursor, size_param, &size); if (step_cursor + size <= range.max) { void *data = (U8*)base + range.min + step_cursor; stashed_loc.kind = DW_SimpleLocKind_ValueLong; stashed_loc.val_long.str = (U8*)data; stashed_loc.val_long.size = size; } else { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_BadData; goto finish; } step_cursor += size; } break; case DW_ExprOp_StackValue: { U64 x = dw_expr__stack_pop(&stack); stashed_loc.kind = DW_SimpleLocKind_Value; stashed_loc.val = x; } break; //// composite location descriptions //// case DW_ExprOp_Piece: case DW_ExprOp_BitPiece: { if (arena_optional == 0) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingArenaForComposite; goto finish; } else { // determine this piece's size & offset U64 bit_size = 0; U64 bit_off = 0; B32 is_bit_loc = 0; switch (op) { case DW_ExprOp_Piece: { U64 size = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &size); bit_size = size*8; } break; case DW_ExprOp_BitPiece: { step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &bit_size); step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, &bit_off); is_bit_loc = 1; } break; } // determine this piece's location information DW_SimpleLoc piece_loc = stashed_loc; if (piece_loc.kind == DW_SimpleLocKind_Address) { if (dw_expr__stack_is_empty(&stack)) { piece_loc.kind = DW_SimpleLocKind_Empty; } else { U64 x = dw_expr__stack_pop(&stack); piece_loc.addr = x; } } // push the piece DW_Piece *piece = push_array(arena_optional, DW_Piece, 1); SLLQueuePush(result.first_piece, result.last_piece, piece); piece->loc = piece_loc; piece->bit_size = bit_size; piece->bit_off = bit_off; piece->is_bit_loc = is_bit_loc; // zero the stached loc MemoryZeroStruct(&stashed_loc); } } break; //// final fallback //// default: { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_NotSupported; goto finish; } break; } // increment cursor cursor = step_cursor; } // advance cursor or finish call if (cursor < call->size) { call->cursor = cursor; } else { dw_expr__call_pop(&call_stack); } // advance step counter step_counter += 1; if (step_counter == max_step_count) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_TimeOut; goto finish; } } finish:; // non-piece location { DW_SimpleLoc loc = stashed_loc; if (result.first_piece == 0) { // normal location resolution loc = stashed_loc; if (loc.kind == DW_SimpleLocKind_Address) { if (dw_expr__stack_is_empty(&stack)) { loc.kind = DW_SimpleLocKind_Empty; } else { U64 x = dw_expr__stack_pop(&stack); loc.addr = x; } } } // non-piece location resolution after composite else { // change the default kind to empty if (loc.kind == DW_SimpleLocKind_Address) { loc.kind = DW_SimpleLocKind_Empty; } // the non-piece should either be empty or fail if (loc.kind != DW_SimpleLocKind_Empty && loc.kind != DW_SimpleLocKind_Fail) { loc.kind = DW_SimpleLocKind_Fail; loc.fail_kind = DW_LocFailKind_BadData; } } result.non_piece_loc = loc; } // clear stack scratch_end(scratch); return result; #endif DW_Location result = {0}; return result; } //- dw expr val stack internal DW_ExprStack dw_expr__stack_make(Arena *arena) { DW_ExprStack result = {0}; return result; } internal void dw_expr__stack_push(Arena *arena, DW_ExprStack *stack, U64 x) { DW_ExprStackNode *node = stack->free_nodes; if (node == 0) { SLLStackPop(stack->free_nodes); } else { node = push_array(arena, DW_ExprStackNode, 1); } SLLStackPush(stack->stack, node); node->val = x; stack->count += 1; } internal U64 dw_expr__stack_pop(DW_ExprStack *stack) { U64 result = 0; DW_ExprStackNode *node = stack->stack; if (node != 0) { SLLStackPop(stack->stack); stack->count -= 1; result = node->val; } return result; } internal U64 dw_expr__stack_pick(DW_ExprStack *stack, U64 idx) { U64 result = 0; if (idx < stack->count) { U64 counter = idx; DW_ExprStackNode *node = stack->stack; for (;node != 0 && counter > 0; node = node->next, counter -= 1); if (counter == 0 && node != 0) { result = node->val; } } return result; } internal B32 dw_expr__stack_is_empty(DW_ExprStack *stack) { B32 result = (stack->count == 0); return result; } //- dw expr call stack internal DW_ExprCall* dw_expr__call_top(DW_ExprCallStack *stack) { DW_ExprCall *call = stack->stack; return call; } internal void dw_expr__call_push(Arena *arena, DW_ExprCallStack *stack, void *ptr, U64 size) { DW_ExprCall *call = 0; if (call != 0) { SLLStackPop(stack->free_calls); } else { call = push_array(arena, DW_ExprCall, 1); } MemoryZeroStruct(call); SLLStackPush(stack->stack, call); stack->depth += 1; } internal void dw_expr__call_pop(DW_ExprCallStack *stack) { DW_ExprCall *top = stack->stack; if (top != 0) { SLLStackPop(stack->stack); SLLStackPush(stack->free_calls, top); } } //- analysis tasks internal DW_ExprAnalysisTask* dw_expr__analysis_task_from_p(DW_ExprAnalysisTask *first, U64 p) { DW_ExprAnalysisTask *result = 0; for (DW_ExprAnalysisTask *task = first; task != 0; task = task->next) { if (task->p == p) { result = task; break; } } return result; } ================================================ FILE: src/dwarf/dwarf_expr.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_EXPR_H #define DWARF_EXPR_H //////////////////////////////// //~ Dwarf Register Layout typedef struct DW_RegsX64 { union { struct { U64 rax; U64 rdx; U64 rcx; U64 rbx; U64 rsi; U64 rdi; U64 rbp; U64 rsp; U64 r8; U64 r9; U64 r10; U64 r11; U64 r12; U64 r13; U64 r14; U64 r15; U64 rip; }; U64 r[17]; }; } DW_RegsX64; //////////////////////////////// //~ Dwarf Expression Eval Types #define DW_READ_MEMORY_SIG(name) U64 name(U64 addr, U64 size, void *out, void *ud) typedef DW_READ_MEMORY_SIG(DW_ReadMemorySig); //- machine configuration types typedef String8 DW_ExprResolveCallFunc(void *call_user_ptr, U64 p); typedef struct DW_ExprMachineCallConfig { void *user_ptr; DW_ExprResolveCallFunc *func; } DW_ExprMachineCallConfig; typedef struct DW_ExprMachineConfig { U64 max_step_count; // (read only in the eval functions) DW_ReadMemorySig *read_memory; void *read_memory_ud; DW_RegsX64 *regs; U64 *text_section_base; U64 *frame_base; U64 *object_address; U64 *tls_address; U64 *cfa; DW_ExprMachineCallConfig call; } DW_ExprMachineConfig; //- detail analysis types typedef U32 DW_ExprFlags; enum { DW_ExprFlag_UsesTextBase = (1 << 0), DW_ExprFlag_UsesMemory = (1 << 1), DW_ExprFlag_UsesRegisters = (1 << 2), DW_ExprFlag_UsesFrameBase = (1 << 3), DW_ExprFlag_UsesObjectAddress = (1 << 4), DW_ExprFlag_UsesTLSAddress = (1 << 5), DW_ExprFlag_UsesCFA = (1 << 6), DW_ExprFlag_UsesCallResolution = (1 << 7), DW_ExprFlag_UsesComposite = (1 << 8), DW_ExprFlag_NotSupported = (1 << 16), DW_ExprFlag_BadData = (1 << 17), DW_ExprFlag_NonLinearFlow = (1 << 18) }; typedef struct DW_ExprAnalysis { DW_ExprFlags flags; } DW_ExprAnalysis; typedef struct DW_ExprAnalysisTask { struct DW_ExprAnalysisTask *next; U64 p; String8 data; } DW_ExprAnalysisTask; //- location types typedef enum DW_SimpleLocKind { DW_SimpleLocKind_Address, DW_SimpleLocKind_Register, DW_SimpleLocKind_Value, DW_SimpleLocKind_ValueLong, DW_SimpleLocKind_Empty, DW_SimpleLocKind_Fail, } DW_SimpleLocKind; typedef enum DW_LocFailKind { // Interpreting Fail Kinds // // BadData: the evaluator detected that the dwarf expression operation is incorrectly formed // NotSupported: the evaluator does not support a dwarf feature that was found in the dwarf expression // TimeOut: the evaluator hit the maximum step count // TooComplicated: used by analyzer when it the expression uses features outside of the analyzer's scope // Missing*: the dwarf machine config was missing necessary information to finish the evaluation DW_LocFailKind_BadData, DW_LocFailKind_NotSupported, DW_LocFailKind_TimeOut, DW_LocFailKind_TooComplicated, DW_LocFailKind_MissingTextBase, DW_LocFailKind_MissingMemory, DW_LocFailKind_MissingRegisters, DW_LocFailKind_MissingFrameBase, DW_LocFailKind_MissingObjectAddress, DW_LocFailKind_MissingTLSAddress, DW_LocFailKind_MissingCFA, DW_LocFailKind_MissingCallResolution, DW_LocFailKind_MissingArenaForComposite, } DW_LocFailKind; typedef struct DW_SimpleLoc { DW_SimpleLocKind kind; union { U64 addr; U64 reg_idx; U64 val; String8 val_long; struct { DW_LocFailKind fail_kind; U64 fail_data; }; }; } DW_SimpleLoc; typedef struct DW_Piece { // Hint for Interpreting Pieces // // src = decode(loc, is_bit_loc, bit_size); // dst |= (src >> bit_off) << bit_cursor; // bit_cursor += bit_size; struct DW_Piece *next; DW_SimpleLoc loc; U64 bit_size; U64 bit_off; B32 is_bit_loc; } DW_Piece; typedef struct DW_Location { // Interpreting a Dwarf Location // // CASE (any number of pieces, fail in the non-piece): // this is how errors are reported, error information is in the non-piece // the 'fail' location kind should never show up in a piece // if there are any pieces they can be treated as correct information that // was successfully decoded before the error was encountered // // CASE (no pieces, empty non-piece): // the data is completely optimized out and unrecoverable // // CASE (no pieces, non-empty non-piece): // the size of the data is not known by the location, but something in the // surrounding context of the location (eg type info) should know the size // // CASE (one-or-more pieces, empty non-piece): // the data is described by the pieces // // CASE (one-or-more pieces, non-empty non-fail non-piece): // this is supposed to be impossible; the non-piece either carries an error // or *all* of the location information about the data, there should never // be a mix of piece-based location and non-piece-based location data. DW_Piece *first_piece; DW_Piece *last_piece; U64 count; DW_SimpleLoc non_piece_loc; } DW_Location; //- full evaluator state types typedef struct DW_ExprStackNode { struct DW_ExprStackNode *next; U64 val; } DW_ExprStackNode; typedef struct DW_ExprStack { DW_ExprStackNode *stack; DW_ExprStackNode *free_nodes; U64 count; } DW_ExprStack; typedef struct DW_ExprCall { struct DW_ExprCall *next; void *ptr; U64 size; U64 cursor; } DW_ExprCall; typedef struct DW_ExprCallStack { DW_ExprCall *stack; DW_ExprCall *free_calls; U64 depth; } DW_ExprCallStack; //////////////////////////////// //~ Dwarf Expression Analysis & Eval Functions //- analyzers // This analyzer provides the most simplified dwarf expression // decoding. If the expression consists of a single op that can be interpreted // as a valid dwarf expression, then it represents that expression as a simple // location. // // If there is a single 'piece' op that is represeted here as an empty simple // location, losing whatever additional size information from the piece. // // If there is an op that requires the machine configuration data the analyzer // fails with "too complicated" - unless the required configuration data is the // text section base which this analyzer treats as a non-optional parameter and // always decodes successfully. // // If the expression contains more than one op than the analyzer fails with // "too complicated". internal DW_SimpleLoc dw_expr__analyze_fast(void *base, Rng1U64 range, U64 text_section_base); // This analyzer does a one-pass scan through the expression to // help a caller determine what to expect before doing a full evaluation which // has to maintain value stacks, perform more checks, and execute any loops // that may appear in the expression, etc. // // For each piece of data that can be equipped to a machine config there is a // 'Uses' flag in the analysis. A user can use these flags to determine what to // prepare and equip before a full eval. This can be a lot more efficient than // always preparing everything, or iteratively equipping and retrying after // each failure. // // The analysis can also catch some cases of bad data and unsupported features. // These flags are useful for short circuit style optimizations, but they are // not definitive, some bad data can only be caught by the full evaluator. // Sometimes the full evaluator might miss bad data that this analyzer will see // if control flow in the evaluator completely skips the bad data. A forgiving // interpretation of dwarf expression data would only rely on the results of // the full evaluator. A more strict interpretation would consider it an error // if either this analyzer or the evaluator finds bad data. // // The analyzer also determines if there is any possibility for non-linear // flow. Jumps, branches, and call ops all create non-linear flow. An // expression that doesn't have non-linear flow is trivially gauranteed to // terminate and therefore a good candidate for conversion to a human readable // expression. // // The call config is optional (may be null). If is provided the analysis // includes features seen in all of the expressions that might be reached by // call ops from the initial expression. internal DW_ExprAnalysis dw_expr__analyze_details(void *base, Rng1U64 range, DW_ExprMachineCallConfig *call_config); //- full eval internal DW_Location dw_expr__eval(Arena *arena_optional, void *base, Rng1U64 range, DW_ExprMachineConfig *config); //- dw expr val stack internal DW_ExprStack dw_expr__stack_make(Arena *arena); internal void dw_expr__stack_push(Arena *arena, DW_ExprStack *stack, U64 x); internal U64 dw_expr__stack_pop(DW_ExprStack *stack); internal U64 dw_expr__stack_pick(DW_ExprStack *stack, U64 idx); internal B32 dw_expr__stack_is_empty(DW_ExprStack *stack); //- dw expr call stack internal DW_ExprCall* dw_expr__call_top(DW_ExprCallStack *stack); internal void dw_expr__call_push(Arena *arena, DW_ExprCallStack *stack, void *ptr, U64 size); internal void dw_expr__call_pop(DW_ExprCallStack *stack); //- analysis tasks internal DW_ExprAnalysisTask* dw_expr__analysis_task_from_p(DW_ExprAnalysisTask *first, U64 p); #endif //DWARF_EXPR_H ================================================ FILE: src/dwarf/dwarf_help.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal DW_CallFrameInfo dw_call_frame_info_from_data(Arena *arena, Arch arch, U64 rebase, String8 debug_frame) { Temp scratch = scratch_begin(&arena, 1); // count CIE and FDE entries U64 cie_count = 0, fde_count = 0; for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); if (desc_size == 0) { break; } if (desc.type == DW_DescriptorEntryType_CIE) { cie_count += 1; } else if (desc.type == DW_DescriptorEntryType_FDE) { fde_count += 1; } } // parse CIEs and build (offset -> CIE) hash table HashTable *cie_ht = hash_table_init(scratch.arena, (U64)(cie_count * 1.3)); DW_CIE *cie = push_array(arena, DW_CIE, cie_count); U64 parse_cie_count = 0; for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); if (desc_size == 0) { break; } if (desc.type == DW_DescriptorEntryType_CIE) { if (dw_parse_cie(str8_skip(debug_frame, cursor), desc.format, arch, &cie[parse_cie_count])) { hash_table_push_u64_raw(scratch.arena, cie_ht, cursor, &cie[parse_cie_count]); parse_cie_count += 1; } } } // parse FDEs DW_FDE *fde = push_array(arena, DW_FDE, fde_count); U64 parse_fde_count = 0; for (U64 cursor = 0, desc_size; cursor < debug_frame.size; cursor += desc_size) { DW_DescriptorEntry desc = {0}; desc_size = dw_parse_descriptor_entry_header(debug_frame, cursor, &desc); if (desc_size == 0) { break; } if (desc.type == DW_DescriptorEntryType_FDE) { DW_CIE *cie = hash_table_search_u64_raw(cie_ht, desc.cie_pointer); if (dw_parse_fde(str8_skip(debug_frame, cursor), desc.format, cie, &fde[parse_fde_count])) { fde[parse_fde_count].pc_range.min += rebase; fde[parse_fde_count].pc_range.max += rebase; parse_fde_count += 1; } } } // fill out result DW_CallFrameInfo cfi = {0}; cfi.cie_count = parse_cie_count; cfi.fde_count = parse_fde_count; cfi.cie = cie; cfi.fde = fde; scratch_end(scratch); return cfi; } ================================================ FILE: src/dwarf/dwarf_help.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_HELP_H #define DWARF_HELP_H typedef struct DW_CallFrameInfo { U64 cie_count; U64 fde_count; DW_CIE *cie; DW_FDE *fde; } DW_CallFrameInfo; internal DW_CallFrameInfo dw_call_frame_info_from_data(Arena *arena, Arch arch, U64 rebase, String8 debug_frame); #endif // DWARF_HELP_H ================================================ FILE: src/dwarf/dwarf_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "dwarf/dwarf.c" #include "dwarf/dwarf_expr.c" #include "dwarf/dwarf_parse.c" #include "dwarf/dwarf_coff.c" #include "dwarf/dwarf_elf.c" #include "dwarf/dwarf_unwind.c" #include "dwarf/dwarf_dump.c" #include "dwarf/dwarf_help.c" #include "dwarf/eh_frame.c" #include "dwarf/eh_dump.c" ================================================ FILE: src/dwarf/dwarf_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_INC_H #define DWARF_INC_H #include "dwarf/dwarf.h" #include "dwarf/dwarf_expr.h" #include "dwarf/dwarf_parse.h" #include "dwarf/dwarf_coff.h" #include "dwarf/dwarf_elf.h" #include "dwarf/dwarf_unwind.h" #include "dwarf/dwarf_dump.h" #include "dwarf/dwarf_help.h" #include "dwarf/eh_frame.h" #include "dwarf/eh_dump.h" #endif // DWARF_INC_H ================================================ FILE: src/dwarf/dwarf_notes.txt ================================================ --- DWARF NOTES --------------------------------------------------------------- DWARF V4 Spec: http://www.dwarfstd.org/doc/DWARF4.pdf DWARF V5 Spec: http://www.dwarfstd.org/doc/DWARF5.pdf ------------------------------------------------------------------------------- $ (2021/04/30) On .debug_pubtypes, .debug_pubnames, and .debug_names: .debug_pubtypes and .debug_pubnames are tables that map from a string (the name of a type or function respectively) to an offset into .debug_info, which is the offset of the Debug Information Entry (DIE, in DWARF terminology) of the info associated with the string. THESE TWO SECTIONS ARE OPTIONAL. They don't show up in every DWARF-holding file, and so they cannot be relied upon as acceleration structures. But we're going to support parsing them, to make things a bit nicer in cases where they are present. DWARF doesn't have much in the way of acceler- ation structures built in, so our rationale is that we should take anything we can get to make the format a bit more in some subset of the possible cases. .debug_names is a DWARF V5 section that is intended to replace .debug_pubtypes and .debug_pubnames. However, even in cases when DWARF V5 is produced at the time of writing this, we have not found .debug_names sections being produced. We did not exhaustively test all compilers and configurations, but it seems that it is not well-supported at all by major compilers, and there's a very low probability that a user will have that section, so our current thinking is that there's no point in supporting it right now. ------------------------------------------------------------------------------- $ (2021/04/30) On producing DWARF V5 with Clang: https://lists.llvm.org/pipermail/llvm-dev/2018-August/125068.html By default it looks like (at the time of writing this) that Clang, by default, will produce DWARF V4. To produce DWARF V5, however, you can use the -gdwarf-5 option. Even when that option is used, it seems that some features of V5 are not used (for example, .debug_names). The above link also says that this will produce .debug_names, but it doesn't as of Clang 10. ------------------------------------------------------------------------------- ================================================ FILE: src/dwarf/dwarf_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 str8_deserial_read_dwarf_packed_size(String8 string, U64 off, U64 *size_out) { U64 bytes_read = 0; if(str8_deserial_read(string, off, size_out, sizeof(U32), sizeof(U32))) { if(*size_out == max_U32) { if(str8_deserial_read_struct(string, off+sizeof(U32), size_out)) { bytes_read = sizeof(U32) + sizeof(U64); } } else { *size_out &= (U64)max_U32; bytes_read = sizeof(U32); } } return bytes_read; } internal U64 str8_deserial_read_dwarf_uint(String8 string, U64 off, DW_Format format, U64 *uint_out) { U64 bytes_read = 0; switch(format) { case DW_Format_Null: break; case DW_Format_32Bit: { *uint_out &= (U64)max_U32; bytes_read = str8_deserial_read(string, off, uint_out, sizeof(U32), sizeof(U32)); }break; case DW_Format_64Bit: { bytes_read = str8_deserial_read_struct(string, off, uint_out); }break; } return bytes_read; } internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out) { U64 value = 0; U64 shift = 0; U64 cursor = off; for(;;) { U8 byte = 0; U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); if(bytes_read != sizeof(byte)) { break; } U8 val = byte & 0x7fu; value |= ((U64)val) << shift; cursor += bytes_read; shift += 7u; if((byte & 0x80u) == 0) { break; } } if(value_out != 0) { *value_out = value; } U64 bytes_read = cursor - off; return bytes_read; } internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out) { U64 value = 0; U64 shift = 0; U64 cursor = off; for(;;) { U8 byte = 0; U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); if(bytes_read != sizeof(byte)) { break; } U8 val = byte & 0x7fu; value |= ((U64)val) << shift; cursor += bytes_read; shift += 7u; if((byte & 0x80u) == 0) { if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0) { value |= -(S64)(1ull << shift); } break; } } if(value_out != 0) { *value_out = value; } U64 bytes_read = cursor - off; return bytes_read; } internal U64 str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 count, U64 **arr_out) { Temp temp = temp_begin(arena); U64 *arr = push_array(arena, U64, count); U64 i, cursor; for (i = 0, cursor = off; i < count; ++i) { U64 read_size = str8_deserial_read_uleb128(string, cursor, &arr[i]); if (read_size == 0) { break; } cursor += read_size; } U64 bytes_read = 0; if (i == count) { *arr_out = arr; bytes_read = cursor - off; } else { temp_end(temp); *arr_out = 0; } return bytes_read; } internal U64 str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 count, S64 **arr_out) { Temp temp = temp_begin(arena); S64 *arr = push_array(arena, S64, count); U64 i, cursor; for (i = 0, cursor = off; i < count; ++i) { U64 read_size = str8_deserial_read_sleb128(string, cursor, &arr[i]); if (read_size == 0) { break; } cursor += read_size; } U64 bytes_read = 0; if (i == count) { *arr_out = arr; bytes_read = cursor - off; } else { temp_end(temp); *arr_out = 0; } return bytes_read; } internal DW_SectionKind dw_section_kind_from_string(String8 string) { DW_SectionKind s = DW_Section_Null; #define X(_K,_L,_M,_W) \ if (str8_match_lit(_L, string, 0)) { s = DW_Section_##_K; } \ if (str8_match_lit(_M, string, 0)) { s = DW_Section_##_K; } DW_SectionKind_XList(X) #undef X return s; } internal DW_SectionKind dw_section_dwo_kind_from_string(String8 string) { DW_SectionKind s = DW_Section_Null; #define X(_K,_L,_M,_W) \ if (str8_match_lit(_W, string, 0)) { s = DW_Section_##_K; } DW_SectionKind_XList(X) #undef X return s; } internal Rng1U64List dw_unit_ranges_from_data(Arena *arena, String8 data) { Rng1U64List result = {0}; for(U64 cursor = 0; cursor < data.size;) { // rjf: read CU size; bad read -> terminate U64 cu_size = 0; U64 cu_size_size = str8_deserial_read_dwarf_packed_size(data, cursor, &cu_size); if(cu_size_size == 0) { break; } // rjf: push if(cu_size > 0) { rng1u64_list_push(arena, &result, rng_1u64(cursor, cursor+cu_size+cu_size_size)); } // rjf: advance cursor += cu_size_size; cursor += cu_size; } return result; } internal U64 dw_read_list_unit_header_addr(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); if (version_size) { if (version >= DW_Version_5) { U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &address_size); if (address_size_size && address_size) { U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size + address_size_size, &segment_selector_size); if (segment_selector_size_size) { header_size = unit_length_size + version_size + address_size_size + segment_selector_size_size; lu_out->version = version; lu_out->segment_selector_size = segment_selector_size; lu_out->address_size = address_size; lu_out->entry_size = segment_selector_size + address_size; lu_out->entries = str8_skip(unit_data, header_size); } } } } } return header_size; } internal U64 dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); if (version >= DW_Version_5) { U16 padding = 0; U64 padding_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &padding); if (padding_size && padding == 0) { header_size = unit_length_size + version_size + padding_size; lu_out->version = version; lu_out->address_size = 0; lu_out->segment_selector_size = 0; lu_out->entry_size = dw_size_from_format(DW_FormatFromSize(unit_length)); lu_out->entries = str8_skip(unit_data, header_size); } } } return header_size; } internal U64 dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); if (version >= DW_Version_5) { U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &address_size); if (address_size_size && address_size > 0) { U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size + address_size_size, &segment_selector_size); if (segment_selector_size_size) { U32 offset_entry_count = 0; U64 offset_entry_count_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size + address_size_size + segment_selector_size, &offset_entry_count); if (offset_entry_count_size) { header_size = unit_length_size + version_size + address_size_size + segment_selector_size_size + offset_entry_count_size; lu_out->version = version; lu_out->address_size = address_size; lu_out->segment_selector_size = segment_selector_size; lu_out->entry_size = dw_size_from_format(DW_FormatFromSize(unit_length)); lu_out->entries = str8_skip(unit_data, header_size); } } } } } return header_size; } internal DW_ListUnitInput dw_list_unit_input_from_input(Arena *arena, DW_Input *input) { Temp scratch = scratch_begin(&arena, 1); DW_ListUnitInput result = {0}; DW_Section debug_addr = input->sec[DW_Section_Addr]; { String8 data = debug_addr.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); result.addr_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.addr_count = unit_ranges.count; result.addrs = push_array(arena, DW_ListUnit, unit_ranges.count); for (U64 unit_idx = 0; unit_idx < result.addr_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(debug_addr.data, result.addr_ranges.v[unit_idx]); dw_read_list_unit_header_addr(unit_data, &result.addrs[unit_idx]); } } DW_Section debug_str_offsets = input->sec[DW_Section_StrOffsets]; { String8 data = debug_str_offsets.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); result.str_offset_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.str_offset_count = unit_ranges.count; result.str_offsets = push_array(arena, DW_ListUnit, unit_ranges.count); for (U64 unit_idx = 0; unit_idx < result.str_offset_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.str_offset_ranges.v[unit_idx]); dw_read_list_unit_header_str_offsets(unit_data, &result.str_offsets[unit_idx]); } } DW_Section debug_rnglists = input->sec[DW_Section_RngLists]; { String8 data = debug_rnglists.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); result.rnglist_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.rnglist_count = unit_ranges.count; result.rnglists = push_array(arena, DW_ListUnit, unit_ranges.count); for (U64 unit_idx = 0; unit_idx < result.rnglist_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.rnglist_ranges.v[unit_idx]); dw_read_list_unit_header_list(unit_data, &result.rnglists[unit_idx]); } } DW_Section debug_loclists = input->sec[DW_Section_LocLists]; { String8 data = debug_loclists.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); result.loclist_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.loclist_count = unit_ranges.count; result.loclists = push_array(arena, DW_ListUnit, unit_ranges.count); for (U64 unit_idx = 0; unit_idx < result.loclist_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.loclist_ranges.v[unit_idx]); dw_read_list_unit_header_list(unit_data, &result.loclists[unit_idx]); } } scratch_end(scratch); return result; } internal U64 dw_offset_from_list_unit(DW_ListUnit *lu, U64 index) { U64 offset; U64 entry_off = index * lu->entry_size; if (entry_off + lu->entry_size <= lu->entries.size) { offset = 0; MemoryCopy(&offset, lu->entries.str + entry_off, lu->entry_size); } else { offset = max_U64; } return offset; } internal U64 dw_addr_from_list_unit(DW_ListUnit *lu, U64 index) { U64 seg = 0; U64 addr = max_U64; U64 entry_count = lu->entries.size / lu->entry_size; if (index < entry_count) { U64 seg_off = lu->entry_size * index; U64 addr_off = seg_off + lu->segment_selector_size; MemoryCopy(&seg, lu->entries.str + seg_off, lu->segment_selector_size); MemoryCopy(&addr, lu->entries.str + addr_off, lu->address_size); // TODO: segment-based addressing AssertAlways(seg == 0); } else { Assert(!"out of bounds index"); } return addr; } internal U64 dw_read_abbrev_tag(String8 data, U64 offset, DW_Abbrev *out_abbrev) { U64 total_bytes_read = 0; //- rjf: parse ID U64 id_off = offset; U64 sub_kind_off = id_off; U64 id = 0; { U64 bytes_read = str8_deserial_read_uleb128(data, id_off, &id); sub_kind_off += bytes_read; total_bytes_read += bytes_read; } //- rjf: parse sub-kind U64 sub_kind = 0; U64 next_off = sub_kind_off; if(id != 0) { U64 bytes_read = str8_deserial_read_uleb128(data, sub_kind_off, &sub_kind); next_off += bytes_read; total_bytes_read += bytes_read; } //- rjf: parse whether this tag has children U8 has_children = 0; if(id != 0) { total_bytes_read += str8_deserial_read_struct(data, next_off, &has_children); } //- rjf: fill abbrev if(out_abbrev != 0) { DW_Abbrev abbrev = {0}; abbrev.kind = DW_Abbrev_Tag; abbrev.sub_kind = sub_kind; abbrev.id = id; if(has_children) { abbrev.flags |= DW_AbbrevFlag_HasChildren; } *out_abbrev = abbrev; } return total_bytes_read; } internal U64 dw_read_abbrev_attrib(String8 data, U64 offset, DW_Abbrev *out_abbrev) { U64 total_bytes_read = 0; //- rjf: parse ID U64 id_off = offset; U64 sub_kind_off = id_off; U64 id = 0; { U64 bytes_read = str8_deserial_read_uleb128(data, id_off, &id); sub_kind_off += bytes_read; total_bytes_read += bytes_read; } //- rjf: parse sub-kind (form-kind) U64 sub_kind = 0; U64 next_off = sub_kind_off; { U64 bytes_read = str8_deserial_read_uleb128(data, sub_kind_off, &sub_kind); next_off += bytes_read; total_bytes_read += bytes_read; } //- rjf: parse implicit const U64 implicit_const = 0; if(sub_kind == DW_Form_ImplicitConst) { U64 bytes_read = str8_deserial_read_uleb128(data, next_off, &implicit_const); total_bytes_read += bytes_read; } //- rjf: fill abbrev if(out_abbrev != 0) { DW_Abbrev abbrev = {0}; abbrev.kind = DW_Abbrev_Attrib; abbrev.sub_kind = sub_kind; abbrev.id = id; if(sub_kind == DW_Form_ImplicitConst) { abbrev.flags |= DW_AbbrevFlag_HasImplicitConst; abbrev.const_value = implicit_const; } *out_abbrev = abbrev; } return total_bytes_read; } internal DW_AbbrevTable dw_make_abbrev_table(Arena *arena, String8 abbrev_data, U64 abbrev_offset) { //- rjf: count the tags we have U64 tag_count = 0; for(U64 abbrev_read_off = abbrev_offset;;) { DW_Abbrev tag; { U64 bytes_read = dw_read_abbrev_tag(abbrev_data, abbrev_read_off, &tag); abbrev_read_off += bytes_read; if(bytes_read == 0 || tag.id == 0) { break; } } for(;;) { DW_Abbrev attrib = {0}; U64 bytes_read = dw_read_abbrev_attrib(abbrev_data, abbrev_read_off, &attrib); abbrev_read_off += bytes_read; if(bytes_read == 0 || attrib.id == 0) { break; } } tag_count += 1; } //- rjf: build table DW_AbbrevTable table = {0}; table.count = tag_count; table.entries = push_array(arena, DW_AbbrevTableEntry, table.count); MemorySet(table.entries, 0, sizeof(DW_AbbrevTableEntry)*table.count); U64 tag_idx = 0; for(U64 abbrev_read_off = abbrev_offset;;) { U64 tag_abbrev_off = abbrev_read_off; DW_Abbrev tag; { U64 bytes_read = dw_read_abbrev_tag(abbrev_data, abbrev_read_off, &tag); abbrev_read_off += bytes_read; if(bytes_read == 0 || tag.id == 0) { break; } } // rjf: insert this tag into the table { table.entries[tag_idx].id = tag.id; table.entries[tag_idx].off = tag_abbrev_off; tag_idx += 1; } for(;;) { DW_Abbrev attrib = {0}; U64 bytes_read = dw_read_abbrev_attrib(abbrev_data, abbrev_read_off, &attrib); abbrev_read_off += bytes_read; if(bytes_read == 0 || attrib.id == 0) { break; } } tag_count += 1; } return table; } internal U64 dw_abbrev_offset_from_abbrev_id(DW_AbbrevTable table, U64 abbrev_id) { U64 abbrev_offset = max_U64; if (table.count > 0) { for (S64 l = 0, r = (S64)table.count - 1; l <= r; ) { S64 m = l + (r - l) / 2; if (abbrev_id > table.entries[m].id) { l = m + 1; } else if (abbrev_id < table.entries[m].id) { r = m - 1; } else { abbrev_offset = table.entries[m].off; break; } } } return abbrev_offset; } internal U64 dw_read_form(String8 data, U64 off, DW_Version version, DW_Format unit_format, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_Form *form_out) { U64 bytes_read = 0; DW_Form form = {0}; switch (form_kind) { case DW_Form_Null: break; case DW_Form_Addr: { bytes_read = str8_deserial_read_block(data, off, address_size, &form.addr); } break; case DW_Form_Block2: { U16 size = 0; U64 size_size = str8_deserial_read_struct(data, off, &size); if (size_size) { U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); if (block_size) { bytes_read = size_size + block_size; } } } break; case DW_Form_Block4: { U32 size = 0; U64 size_size = str8_deserial_read_struct(data, off, &size); if (size_size) { U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); if (block_size) { bytes_read = size_size + block_size; } } } break; case DW_Form_Data2: { bytes_read = str8_deserial_read_block(data, off, sizeof(U16), &form.data); } break; case DW_Form_Data4: { bytes_read = str8_deserial_read_block(data, off, sizeof(U32), &form.data); } break; case DW_Form_Data8: { bytes_read = str8_deserial_read_block(data, off, sizeof(U64), &form.data); } break; case DW_Form_String: { bytes_read = str8_deserial_read_cstr(data, off, &form.string); } break; case DW_Form_Block: { U64 size = 0; U64 size_size = str8_deserial_read_uleb128(data, off, &size); if (size_size) { U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); if (block_size) { bytes_read = size_size + block_size; } } } break; case DW_Form_Block1: { U8 size = 0; U64 size_size = str8_deserial_read_struct(data, off, &size); if (size_size) { U64 block_size = str8_deserial_read_block(data, off, size, &form.block); if (block_size == size) { bytes_read = size_size + block_size; } } } break; case DW_Form_Data1: { bytes_read = str8_deserial_read_block(data, off, sizeof(U8), &form.data); } break; case DW_Form_Flag: { bytes_read = str8_deserial_read_struct(data, off, &form.flag); } break; case DW_Form_SData: { bytes_read = str8_deserial_read_sleb128(data, off, &form.sdata); } break; case DW_Form_UData: { bytes_read = str8_deserial_read_uleb128(data, off, &form.udata); } break; case DW_Form_RefAddr: { if (version < DW_Version_3) { bytes_read = str8_deserial_read(data, off, &form.ref, address_size, address_size); } else { bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.ref); } } break; case DW_Form_GNU_RefAlt: { bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.ref); } break; case DW_Form_Ref1: { bytes_read = str8_deserial_read(data, off, &form.ref, 1, 1); } break; case DW_Form_Ref2: { bytes_read = str8_deserial_read(data, off, &form.ref, 2, 2); } break; case DW_Form_Ref4: { bytes_read = str8_deserial_read(data, off, &form.ref, 4, 4); } break; case DW_Form_Ref8: { bytes_read = str8_deserial_read(data, off, &form.ref, 8, 8); } break; case DW_Form_RefUData: { bytes_read = str8_deserial_read_uleb128(data, off, &form.ref); } break; case DW_Form_SecOffset: case DW_Form_LineStrp: case DW_Form_GNU_StrpAlt: case DW_Form_Strp: { bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.sec_offset); } break; case DW_Form_ExprLoc: { U64 expr_size = 0; U64 expr_size_size = str8_deserial_read_uleb128(data, off, &expr_size); if (expr_size_size) { if (str8_deserial_read_block(data, off + expr_size_size, expr_size, &form.exprloc)) { bytes_read = expr_size_size + expr_size; } } } break; case DW_Form_FlagPresent: { form.flag = 1; } break; case DW_Form_RefSig8: { //U64 ref = 0; //bytes_read = str8_deserial_read_struct(data, off, &ref); NotImplemented; } break; case DW_Form_Addrx: case DW_Form_RngListx: case DW_Form_Strx: { bytes_read = str8_deserial_read_uleb128(data, off, &form.xval); } break; case DW_Form_RefSup4: { //U32 ref_sup4 = 0; //bytes_read = str8_deserial_read_struct(data, off, &ref_sup4); NotImplemented; } break; case DW_Form_StrpSup: { bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.strp_sup); } break; case DW_Form_Data16: { bytes_read = str8_deserial_read_block(data, off, 16, &form.data); } break; case DW_Form_ImplicitConst: { // Special case. // Unlike other forms that have their values stored in the .debug_info section, // This one defines it's value in the .debug_abbrev section. form.implicit_const = implicit_const; } break; case DW_Form_LocListx: { bytes_read = str8_deserial_read_uleb128(data, off, &form.xval); } break; case DW_Form_RefSup8: { NotImplemented; } break; case DW_Form_Strx1: { bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); } break; case DW_Form_Strx2: { bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); } break; case DW_Form_Strx3: { bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); } break; case DW_Form_Strx4: { bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); } break; case DW_Form_Addrx1: { bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); } break; case DW_Form_Addrx2: { bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); } break; case DW_Form_Addrx3: { bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); } break; case DW_Form_Addrx4: { bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); } break; default: InvalidPath; break; } if (form_out) { *form_out = form; } return bytes_read; } internal U64 dw_read_tag(Arena *arena, String8 tag_data, U64 tag_off, U64 tag_base, DW_AbbrevTable abbrev_table, String8 abbrev_data, DW_Version version, DW_Format unit_format, U64 address_size, DW_Tag *tag_out) { U64 tag_cursor = tag_off; // read tag abbrev id U64 tag_abbrev_id = 0; U64 tag_abbrev_id_size = str8_deserial_read_uleb128(tag_data, tag_cursor, &tag_abbrev_id); Assert(tag_abbrev_id_size); tag_cursor += tag_abbrev_id_size; // read tag abbrev U64 abbrev_cursor = dw_abbrev_offset_from_abbrev_id(abbrev_table, tag_abbrev_id); DW_Abbrev tag_abbrev = {0}; U64 tag_abbrev_size = dw_read_abbrev_tag(abbrev_data, abbrev_cursor, &tag_abbrev); // read attribs DW_AttribList attribs = {0}; if (tag_abbrev_size > 0) { abbrev_cursor += tag_abbrev_size; for (; tag_cursor < tag_data.size && abbrev_cursor < abbrev_data.size; ) { U64 attrib_tag_cursor = tag_cursor; U64 attrib_abbrev_off = abbrev_cursor; // read attrib abbrev DW_Abbrev attrib_abbrev = {0}; abbrev_cursor += dw_read_abbrev_attrib(abbrev_data, abbrev_cursor, &attrib_abbrev); if (attrib_abbrev.id == 0) { break; } DW_AttribKind attrib_kind = (DW_AttribKind)attrib_abbrev.id; DW_FormKind form_kind = (DW_FormKind)attrib_abbrev.sub_kind; // special case, allows producer to embed form in .debug_info if (form_kind == DW_Form_Indirect) { U64 form_kind_size = str8_deserial_read_uleb128(tag_data, tag_cursor, &form_kind); if (form_kind_size == 0) { Assert(!"unable to read indirect form kind"); break; } tag_cursor += form_kind_size; } // read form value DW_Form form = {0}; tag_cursor += dw_read_form(tag_data, tag_cursor, version, unit_format, address_size, form_kind, attrib_abbrev.const_value, &form); // fill out node DW_AttribNode *attrib_n = push_array(arena, DW_AttribNode, 1); attrib_n->v.info_off = tag_base + attrib_tag_cursor; attrib_n->v.abbrev_off = attrib_abbrev_off; attrib_n->v.abbrev_id = attrib_abbrev.id; attrib_n->v.attrib_kind = attrib_kind; attrib_n->v.form_kind = form_kind; attrib_n->v.form = form; // push node to list SLLQueuePush(attribs.first, attribs.last, attrib_n); ++attribs.count; } } // fill out tag tag_out->abbrev_id = tag_abbrev_id; tag_out->has_children = !!(tag_abbrev.flags & DW_AbbrevFlag_HasChildren); tag_out->kind = (DW_TagKind)tag_abbrev.sub_kind; tag_out->attribs = attribs; tag_out->info_off = tag_base + tag_off; U64 bytes_read = tag_cursor - tag_off; return bytes_read; } internal U64 dw_read_tag_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 info_off, DW_Tag *tag_out) { String8 tag_data = str8_substr(input->sec[DW_Section_Info].data, cu->info_range); U64 tag_off = info_off - cu->info_range.min; return dw_read_tag(arena, tag_data, tag_off, cu->info_range.min, cu->abbrev_table, cu->abbrev_data, cu->version, cu->format, cu->address_size, tag_out); } internal B32 dw_try_u64_from_const_value(U64 type_byte_size, DW_ATE type_encoding, String8 const_value, U64 *value_out) { B32 is_parsed = 0; if (const_value.size <= type_byte_size) { U64 value_size = Min(type_byte_size, const_value.size); if (value_size <= sizeof(*value_out)) { MemoryZeroStruct(value_out); MemoryCopy(value_out, const_value.str, value_size); if (type_encoding == DW_ATE_Signed || type_encoding == DW_ATE_SignedChar) { *value_out = extend_sign64(*value_out, value_size); } is_parsed = 1; } else { Assert(!"out value overflow"); } } return is_parsed; } internal U64 dw_u64_from_const_value(String8 const_value) { U64 result = 0; B32 is_converted = dw_try_u64_from_const_value(sizeof(U64), DW_ATE_Unsigned, const_value, &result); Assert(is_converted); // TODO: error handling return result; } internal U64 dw_interp_sec_offset(DW_FormKind form_kind, DW_Form form) { U64 sec_offset = 0; if (form_kind == DW_Form_SecOffset) { sec_offset = form.sec_offset; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return sec_offset; } internal String8 dw_interp_exprloc(DW_FormKind form_kind, DW_Form form) { String8 expr = {0}; if (form_kind == DW_Form_ExprLoc) { expr = form.exprloc; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return expr; } internal U128 dw_interp_const_u128(DW_FormKind form_kind, DW_Form form) { AssertAlways(form.data.size <= sizeof(U128)); U128 result = {0}; MemoryCopy(&result.u64[0], form.data.str, form.data.size); return result; } internal U64 dw_interp_const64(U64 type_byte_size, DW_ATE type_encoding, DW_FormKind form_kind, DW_Form form) { U64 result = max_U64; if (form_kind == DW_Form_Data1 || form_kind == DW_Form_Data2 || form_kind == DW_Form_Data4 || form_kind == DW_Form_Data8 || form_kind == DW_Form_Data16) { if (form.data.size <= sizeof(result)) { if (!dw_try_u64_from_const_value(type_byte_size, type_encoding, form.data, &result)) { Assert(!"unable to decode data"); } } else { Assert(!"unable to cast U128 to U64"); } } else if (form_kind == DW_Form_UData) { result = form.udata; } else if (form_kind == DW_Form_SData) { result = form.sdata; } else if (form_kind == DW_Form_ImplicitConst) { result = form.implicit_const; } else if (form_kind == DW_Form_Null) { // skip } else { AssertAlways(!"unexpected form"); } return result; } internal U64 dw_interp_const_u64(DW_FormKind form_kind, DW_Form form) { return dw_interp_const64(sizeof(U64), DW_ATE_Unsigned, form_kind, form); } internal U32 dw_interp_const_u32(DW_FormKind form_kind, DW_Form form) { U64 const64 = dw_interp_const_u64(form_kind, form); U32 const32 = safe_cast_u32(const64); return const32; } internal S64 dw_interp_const_s64(DW_FormKind form_kind, DW_Form form) { U64 const_u64 = dw_interp_const_u64(form_kind, form); S64 const_s64 = (S64)const_u64; return const_s64; } internal S32 dw_interp_const_s32(DW_FormKind form_kind, DW_Form form) { U32 const_u32 = dw_interp_const_u32(form_kind, form); S32 const_s32 = (S32)const_u32; return const_s32; } internal U64 dw_interp_address(U64 address_size, U64 base_addr, DW_ListUnit *addr_lu, DW_FormKind form_kind, DW_Form form) { U64 address = 0; if (form_kind == DW_Form_Addr) { if (!dw_try_u64_from_const_value(address_size, DW_ATE_Address, form.addr, &address)) { AssertAlways(!"unable to decode address"); } } else if (form_kind == DW_Form_Addrx || form_kind == DW_Form_Addrx1 || form_kind == DW_Form_Addrx2 || form_kind == DW_Form_Addrx3 || form_kind == DW_Form_Addrx4) { address = dw_addr_from_list_unit(addr_lu, form.xval); } else if (form_kind == DW_Form_SecOffset) { if (addr_lu->segment_selector_size > 0) { AssertAlways(!"TODO: support for segmented address space"); } if (form.sec_offset + addr_lu->segment_selector_size + addr_lu->address_size <= addr_lu->entries.size) { MemoryCopy(&address, addr_lu->entries.str + form.sec_offset, addr_lu->address_size); } else { Assert(!"out of bounds .debug_addr offset"); } } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return address; } internal String8 dw_interp_block(DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { NotImplemented; return str8_zero(); } internal String8 dw_interp_string(DW_Input *input, DW_Format unit_format, DW_ListUnit *str_offsets, DW_FormKind form_kind, DW_Form form) { String8 string = {0}; if (form_kind == DW_Form_String) { string = form.string; } else if (form_kind == DW_Form_Strp) { U64 bytes_read = str8_deserial_read_cstr(input->sec[DW_Section_Str].data, form.sec_offset, &string); Assert(bytes_read > 0); } else if (form_kind == DW_Form_LineStrp) { U64 bytes_read = str8_deserial_read_cstr(input->sec[DW_Section_LineStr].data, form.sec_offset, &string); Assert(bytes_read > 0); } else if (form_kind == DW_Form_StrpSup) { U64 bytes_read = str8_deserial_read_cstr(input->sec[DW_Section_Str].data, form.strp_sup, &string); Assert(bytes_read > 0); } else if (form_kind == DW_Form_Strx || form_kind == DW_Form_Strx1 || form_kind == DW_Form_Strx2 || form_kind == DW_Form_Strx3 || form_kind == DW_Form_Strx4) { U64 sec_offset = dw_offset_from_list_unit(str_offsets, form.xval); if (sec_offset < input->sec[DW_Section_Str].data.size) { U64 bytes_read = str8_deserial_read_cstr(input->sec[DW_Section_Str].data, sec_offset, &string); Assert(bytes_read > 0); } else { AssertAlways(!"unable to translate index to offset"); } } else if (form_kind == DW_Form_GNU_StrpAlt) { NotImplemented; } else if (form_kind == DW_Form_GNU_StrIndex) { NotImplemented; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return string; } internal String8 dw_interp_line_ptr(DW_Input *input, DW_FormKind form_kind, DW_Form form) { String8 result = {0}; if (form_kind == DW_Form_SecOffset) { result = str8_skip(input->sec[DW_Section_Line].data, form.sec_offset); } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return result; } internal DW_LineFile * dw_interp_file(DW_LineVMHeader *line_vm, DW_FormKind form_kind, DW_Form form) { DW_LineFile *result = 0; U64 file_idx = dw_interp_const_u64(form_kind, form); if (file_idx < line_vm->file_table.count) { result = &line_vm->file_table.v[file_idx]; } else { Assert(!"out of bounds file index"); } return result; } internal DW_Reference dw_interp_ref(DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { DW_Reference ref = {0}; if (form_kind == DW_Form_Ref1 || form_kind == DW_Form_Ref2 || form_kind == DW_Form_Ref4 || form_kind == DW_Form_Ref8 || form_kind == DW_Form_RefUData) { ref.cu = cu; ref.info_off = form.ref; } else if (form_kind == DW_Form_RefAddr) { NotImplemented; } else if (form_kind == DW_Form_RefSig8) { NotImplemented; } else if (form_kind == DW_Form_RefSup4 || form_kind == DW_Form_RefSup8) { NotImplemented; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return ref; } internal DW_LocList dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { DW_LocList loclist = {0}; if (cu->version < DW_Version_5) { if (form_kind == DW_Form_SecOffset) { U64 sec_offset = max_U64; if (form_kind == DW_Form_SecOffset) { sec_offset = form.sec_offset; } else if (form_kind == DW_Form_Data8 || form_kind == DW_Form_Data4 || form_kind == DW_Form_Data2 || form_kind == DW_Form_Data1) { if (!dw_try_u64_from_const_value(form.data.size, DW_ATE_Unsigned, form.data, &sec_offset)) { Assert(!"unable to extract section offset"); } } else if (form_kind == DW_Form_Null) { Assert(!"unexpected form"); } String8 sec = str8_skip(input->sec[DW_Section_Loc].data, sec_offset); U64 base_addr = cu->low_pc; U64 base_sel = DW_SentinelFromSize(cu->address_size); for (U64 cursor = 0; cursor < sec.size; ) { U64 range_min = 0; U64 range_min_off = cursor; U64 range_min_size = str8_deserial_read(sec, range_min_off, &range_min, cu->address_size, cu->address_size); if (range_min_size == 0) { break; } U64 range_max = 0; U64 range_max_off = cursor + cu->address_size; U64 range_max_size = str8_deserial_read(sec, range_max_off, &range_max, cu->address_size, cu->address_size); if (range_max_size == 0) { break; } cursor += cu->address_size * 2; // series terminator if (range_min == 0 && range_max == 0) { break; } // set new base address else if (range_min == base_sel) { base_addr = range_max; } // location else { U16 expr_size = 0; U64 expr_size_size = str8_deserial_read_struct(sec, cursor, &expr_size); if (expr_size_size == 0) { Assert(!"unable to read expression size"); break; } cursor += expr_size_size; Assert(cursor + expr_size <= sec.size); Rng1U64 expr_range = rng_1u64(cursor, ClampTop(cursor + expr_size, sec.size)); DW_LocNode *loc_n = push_array(arena, DW_LocNode, 1); loc_n->v.range = rng_1u64(base_addr + range_min, base_addr + range_max); loc_n->v.expr = str8_substr(sec, expr_range); SLLQueuePush(loclist.first, loclist.last, loc_n); ++loclist.count; // advance past expression cursor += expr_size; } } } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } } else { DW_Version version = DW_Version_Null; String8 raw_lle = {0}; if (form_kind == DW_Form_SecOffset) { // offset is from beginning of the section U64 sec_offset = form.sec_offset; raw_lle = str8_skip(input->sec[DW_Section_LocLists].data, sec_offset); } else if (form_kind == DW_Form_LocListx) { // offset is from beginning of the entries U64 entries_off = dw_offset_from_list_unit(cu->loclists_lu, form.xval); raw_lle = str8_skip(cu->loclists_lu->entries, entries_off); version = cu->loclists_lu->version; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } for (U64 cursor = 0, keep_parsing = 1, base_addr = cu->low_pc; cursor < raw_lle.size && keep_parsing; ) { DW_LLE kind = DW_LLE_EndOfList; cursor += str8_deserial_read_struct(raw_lle, cursor, &kind); Rng1U64 range = {0}; switch (kind) { default: Assert(!"unknown kind"); case DW_LLE_EndOfList: { keep_parsing = 0; } break; case DW_LLE_BaseAddressx: { if (!cu->addr_lu) { keep_parsing = 0; break; } U64 addrx = 0; U64 addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &addrx); if (addrx_size == 0) { keep_parsing = 0; break; } U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); if (base_addr_new == max_U64) { InvalidPath; break; } base_addr = base_addr_new; cursor += addrx_size; } break; case DW_LLE_StartxEndx: { U64 start_addrx = 0; U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); if (start_addrx_size == 0) { keep_parsing = 0; break; } U64 end_addrx = 0; U64 end_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor + start_addrx_size, &end_addrx); if (end_addrx_size == 0) { keep_parsing = 0; break; } cursor += start_addrx_size; cursor += end_addrx_size; U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); U64 end = dw_addr_from_list_unit(cu->addr_lu, end_addrx); Assert(start != max_U64); Assert(end != max_U64); range = rng_1u64(start, end); } break; case DW_LLE_StartxLength: { U64 start_addrx = 0; U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); if (start_addrx_size == 0) { keep_parsing = 0; break; } // parse pre-standard & standard length U64 length_off = cursor + start_addrx_size; U64 length = 0; U64 length_size = str8_deserial_read_uleb128(raw_lle, length_off, &length); if (length_size == 0) { keep_parsing = 0; break; } cursor += start_addrx_size; cursor += length_size; if (cu->addr_lu) { U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); Assert(start < max_U64); range = rng_1u64(start, start + length); } else { Assert(!".debug_addr section is missing -- unable to interpret address index"); } } break; case DW_LLE_OffsetPair: { U64 start = 0; U64 start_size = str8_deserial_read_uleb128(raw_lle, cursor, &start); if (start_size == 0) { keep_parsing = 0; break; } U64 end = 0; U64 end_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &end); if (end_size == 0) { keep_parsing = 0; break; } cursor += start_size; cursor += end_size; range = rng_1u64(base_addr + start, base_addr + end); } break; case DW_LLE_DefaultLocation: { // no range int x = 0; } break; case DW_LLE_BaseAddress: { U64 base_addr_size = str8_deserial_read(raw_lle, cursor, &base_addr, cu->address_size, cu->address_size); if (base_addr_size == 0) { keep_parsing = 0; break; } cursor += base_addr_size; } break; case DW_LLE_StartEnd: { U64 start = 0; U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); if (start_size == 0) { keep_parsing = 0; break; } U64 end = 0; U64 end_size = str8_deserial_read(raw_lle, cursor + start_size, &end, cu->address_size, cu->address_size); if (end_size == 0) { keep_parsing = 0; break; } cursor += start_size; cursor += end_size; range = rng_1u64(start, end); } break; case DW_LLE_StartLength: { U64 start = 0; U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); if (start_size == 0) { keep_parsing = 0; break; } U64 length = 0; U64 length_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &length); if (length_size == 0) { keep_parsing = 0; break; } cursor += start_size; cursor += length_size; range = rng_1u64(start, start + length); } break; } B32 has_expr = keep_parsing && kind != DW_LLE_BaseAddressx && kind != DW_LLE_BaseAddress; if (has_expr) { U64 expr_size = 0; U64 expr_size_size = str8_deserial_read_uleb128(raw_lle, cursor, &expr_size); if (expr_size_size == 0) { keep_parsing = 0; break; } String8 expr = {0}; U64 expr_read_size = str8_deserial_read_block(raw_lle, cursor + expr_size_size, expr_size, &expr); if (expr_read_size != expr_size) { keep_parsing = 0; break; } cursor += expr_size_size; cursor += expr_size; DW_LocNode *loc_n = push_array(arena, DW_LocNode, 1); loc_n->v.range = range; loc_n->v.expr = expr; SLLQueuePush(loclist.first, loclist.last, loc_n); ++loclist.count; } } } return loclist; } internal B32 dw_interp_flag(DW_FormKind form_kind, DW_Form form) { B32 flag = 0; if (form_kind == DW_Form_Flag || form_kind == DW_Form_FlagPresent) { flag = form.flag; } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } return flag; } internal Rng1U64List dw_interp_rnglist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { Rng1U64List rnglist = {0}; if (cu->version < DW_Version_5) { // decode section offset U64 sec_offset = max_U64; if (form_kind == DW_Form_SecOffset) { sec_offset = form.sec_offset; } else if (form_kind == DW_Form_Data8 || form_kind == DW_Form_Data4 || form_kind == DW_Form_Data2 || form_kind == DW_Form_Data1) { if (!dw_try_u64_from_const_value(form.data.size, DW_ATE_Unsigned, form.data, &sec_offset)) { Assert(!"unable to extract section offset"); } } else if (form_kind != DW_Form_Null) { Assert(!"unexpected form"); } String8 sec = str8_skip(input->sec[DW_Section_Ranges].data, sec_offset); U64 base_addr = cu->low_pc; U64 base_sel = DW_SentinelFromSize(cu->address_size); for (U64 cursor = 0; cursor < sec.size; ) { U64 range_min = 0; U64 range_min_off = cursor; U64 range_min_size = str8_deserial_read(sec, range_min_off, &range_min, cu->address_size, cu->address_size); if (range_min_size == 0) { break; } U64 range_max = 0; U64 range_max_off = cursor + cu->address_size; U64 range_max_size = str8_deserial_read(sec, range_max_off, &range_max, cu->address_size, cu->address_size); if (range_max_size == 0) { break; } cursor += cu->address_size * 2; // series terminator if (range_min == 0 && range_max == 0) { break; } // set new base address else if (range_min == base_sel) { base_addr = range_max; } // range else { Rng1U64 range = rng_1u64(base_addr + range_min, base_addr + range_max); rng1u64_list_push(arena, &rnglist, range); } } } else { String8 raw_rle = {0}; if (form_kind == DW_Form_SecOffset) { // offset is from beginning of the section U64 sec_offset = form.sec_offset; raw_rle = str8_skip(input->sec[DW_Section_RngLists].data, sec_offset); } else if (form_kind == DW_Form_RngListx) { // offset is from beginning of the entries U64 sec_offset = dw_offset_from_list_unit(cu->rnglists_lu, form.xval); raw_rle = str8_skip(cu->rnglists_lu->entries, sec_offset); } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } U64 rle_invalid_value = DW_SentinelFromSize(cu->address_size); U64 base_addr = cu->low_pc; for (U64 cursor = 0, keep_parsing = 1; cursor < raw_rle.size && keep_parsing; ) { DW_RLE kind = DW_RLE_EndOfList; cursor += str8_deserial_read_struct(raw_rle, cursor, &kind); Rng1U64 range = rng_1u64(rle_invalid_value, rle_invalid_value); switch (kind) { default: case DW_RLE_EndOfList: { keep_parsing = 0; } break; case DW_RLE_BaseAddressx: { U64 addrx = 0; U64 addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &addrx); if (addrx_size == 0) { keep_parsing = 0; break; } if (cu->addr_lu == 0) { keep_parsing = 0; break; } U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); if (base_addr_new < max_U64) { base_addr = base_addr_new; cursor += addrx_size; } else { keep_parsing = 0; Assert(!"invalid addrx"); } } break; case DW_RLE_StartxLength: { U64 start_addrx = 0; U64 start_addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &start_addrx); if (start_addrx_size == 0) { keep_parsing = 0; break; } U64 length = 0; U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_addrx_size, &length); if (length_size == 0) { keep_parsing = 0; break; } cursor += start_addrx_size; cursor += length_size; if (cu->addr_lu) { U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); AssertAlways(start < max_U64); range = rng_1u64(start, start + length); } } break; case DW_RLE_OffsetPair: { U64 offset_start, offset_end = 0; U64 offset_start_size = str8_deserial_read_uleb128(raw_rle, cursor, &offset_start); if (offset_start_size == 0) { keep_parsing = 0; break; } U64 offset_end_size = str8_deserial_read_uleb128(raw_rle, cursor + offset_start_size, &offset_end); if (offset_end_size == 0) { keep_parsing = 0; break; } cursor += offset_start_size; cursor += offset_end_size; range = rng_1u64(base_addr + offset_start, base_addr + offset_end); } break; case DW_RLE_BaseAddress: { U64 base_addr_size = str8_deserial_read(raw_rle, cursor, &base_addr, cu->address_size, cu->address_size); if (base_addr_size == 0) { keep_parsing = 0; break; } cursor += base_addr_size; } break; case DW_RLE_StartEnd: { U64 start = 0, end = 0; U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); if (start_size == 0) { keep_parsing = 0; break; } U64 end_size = str8_deserial_read(raw_rle, cursor + start_size, &end, cu->address_size, cu->address_size); if (end_size == 0) { keep_parsing = 0; break; } cursor += start_size; cursor += end_size; range = rng_1u64(start, end); } break; case DW_RLE_StartLength: { U64 start = 0, length = 0; U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); if (start_size == 0) { keep_parsing = 0; break; } U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_size, &length); if (length_size == 0) { keep_parsing = 0; break; } cursor += start_size; cursor += length_size; range = rng_1u64(start, start + length); } break; } if (range.min != rle_invalid_value) { rng1u64_list_push(arena, &rnglist, range); } } } return rnglist; } internal String8 dw_interp_secptr(DW_Input *input, DW_SectionKind section, DW_FormKind form_kind, DW_Form form) { String8 secptr = {0}; if (form_kind == DW_Form_SecOffset) { String8 sect = input->sec[section].data; Rng1U64 range = rng_1u64(form.sec_offset, sect.size); secptr = str8_substr(sect, range); } else if (form_kind != DW_Form_Null) { Assert(!"unexpected form"); } return secptr; } internal String8 dw_interp_addrptr(DW_Input *input, DW_FormKind form_kind, DW_Form form) { return dw_interp_secptr(input, DW_Section_Addr, form_kind, form); } internal String8 dw_interp_str_offsets_ptr(DW_Input *input, DW_FormKind form_kind, DW_Form form) { return dw_interp_secptr(input, DW_Section_StrOffsets, form_kind, form); } internal String8 dw_interp_rnglists_ptr(DW_Input *input, DW_FormKind form_kind, DW_Form form) { return dw_interp_secptr(input, DW_Section_RngLists, form_kind, form); } internal String8 dw_interp_loclists_ptr(DW_Input *input, DW_FormKind form_kind, DW_Form form) { return dw_interp_secptr(input, DW_Section_LocLists, form_kind, form); } internal DW_AttribClass dw_value_class_from_attrib(DW_CompUnit *cu, DW_Attrib *attrib) { return dw_pick_attrib_value_class(cu->version, cu->ext, attrib->attrib_kind, attrib->form_kind); } internal String8 dw_exprloc_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_ExprLoc || value_class == DW_AttribClass_Block); return dw_interp_exprloc(attrib->form_kind, attrib->form); } internal U128 dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_const_u128(attrib->form_kind, attrib->form); } internal U64 dw_const_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_const_u64(attrib->form_kind, attrib->form); } internal U32 dw_const_u32_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_const_u32(attrib->form_kind, attrib->form); } internal S64 dw_const_s64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_const_s64(attrib->form_kind, attrib->form); } internal S32 dw_const_s32_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_const_s32(attrib->form_kind, attrib->form); } internal B32 dw_flag_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Flag); return dw_interp_flag(attrib->form_kind, attrib->form); } internal U64 dw_address_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Address || value_class == DW_AttribClass_AddrPtr); DW_FormKind form_kind = attrib->form_kind; DW_Form form = attrib->form; if (value_class == DW_AttribClass_AddrPtr) { if (attrib->form_kind == DW_Form_SecOffset) { } else { AssertAlways(!"unexpected form"); } form_kind = DW_Form_Addr; form.addr = dw_interp_addrptr(input, attrib->form_kind, attrib->form); } return dw_interp_address(cu->address_size, cu->low_pc, cu->addr_lu, form_kind, form); } internal String8 dw_block_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Block); return dw_interp_block(input, cu, attrib->form_kind, attrib->form); } internal String8 dw_string_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_String || value_class == DW_AttribClass_StrOffsetsPtr); return dw_interp_string(input, cu->format, cu->str_offsets_lu, attrib->form_kind, attrib->form); } internal String8 dw_line_ptr_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_LinePtr); return dw_interp_line_ptr(input, attrib->form_kind, attrib->form); } internal DW_LineFile * dw_file_from_attrib(DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const); return dw_interp_file(line_vm, attrib->form_kind, attrib->form); } internal DW_Reference dw_ref_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Reference); return dw_interp_ref(input, cu, attrib->form_kind, attrib->form); } internal DW_LocList dw_loclist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_LocList || value_class == DW_AttribClass_LocListPtr); return dw_interp_loclist(arena, input, cu, attrib->form_kind, attrib->form); } internal Rng1U64List dw_rnglist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) { Rng1U64List rnglist = {0}; DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); if (value_class == DW_AttribClass_RngListPtr || value_class == DW_AttribClass_RngList) { rnglist = dw_interp_rnglist(arena, input, cu, attrib->form_kind, attrib->form); } else if (value_class != DW_AttribClass_Null) { Assert(!"unexpected value class"); } return rnglist; } internal DW_Attrib * dw_attrib_from_tag_(DW_Tag tag, DW_AttribKind kind) { local_persist read_only DW_Attrib null_attrib; DW_Attrib *attrib = &null_attrib; for (DW_AttribNode *attrib_n = tag.attribs.first; attrib_n != 0; attrib_n = attrib_n->next) { if (attrib_n->v.attrib_kind == kind) { attrib = &attrib_n->v; break; } } return attrib; } internal DW_Attrib * dw_attrib_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { DW_Attrib *attrib = dw_attrib_from_tag_(tag, kind); if (attrib->attrib_kind == DW_AttribKind_Null) { if (cu && cu->tag_ht) { DW_Attrib *ao_attrib = dw_attrib_from_tag_(tag, DW_AttribKind_AbstractOrigin); if (ao_attrib->attrib_kind == DW_AttribKind_AbstractOrigin) { DW_Reference ref = dw_interp_ref(input, cu, ao_attrib->form_kind, ao_attrib->form); DW_TagNode *ref_tag = dw_tag_node_from_info_off(ref.cu, ref.info_off); attrib = dw_attrib_from_tag_(ref_tag->tag, kind); } } } return attrib; } internal B32 dw_tag_has_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); B32 has_attrib = attrib->attrib_kind != DW_AttribKind_Null; return has_attrib; } internal String8 dw_exprloc_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_exprloc_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal String8 dw_block_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_block_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal U128 dw_const_u128_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_const_u128_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal U64 dw_const_u64_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_const_u64_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal U32 dw_const_u32_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_const_u32_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal U64 dw_address_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_address_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal String8 dw_string_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_string_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal String8 dw_line_ptr_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_line_ptr_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal DW_Reference dw_ref_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_ref_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal DW_LocList dw_loclist_from_tag_attrib_kind(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_loclist_from_attrib(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal Rng1U64List dw_rnglist_from_tag_attrib_kind(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_rnglist_from_attrib(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal B32 dw_flag_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { return dw_flag_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind)); } internal DW_LineFile * dw_file_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind) { return dw_file_from_attrib(cu, line_vm, dw_attrib_from_tag(input, cu, tag, kind)); } internal B32 dw_try_byte_size_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, U64 *byte_size_out) { B32 has_byte_size = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ByteSize); B32 has_bit_size = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_BitSize ); if (has_byte_size && has_bit_size) { Assert(!"ill formated byte size"); } if (has_byte_size) { *byte_size_out = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ByteSize); return 1; } else if (has_bit_size) { U64 bit_size = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_BitSize); *byte_size_out = bit_size / 8; return 1; } return 0; } internal U64 dw_byte_size_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag) { U64 byte_size = max_U64; dw_try_byte_size_from_tag(input, cu, tag, &byte_size); return byte_size; } internal U32 dw_byte_size_32_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag) { U32 byte_size32 = 0; U64 byte_size64; if (dw_try_byte_size_from_tag(input, cu, tag, &byte_size64)) { byte_size32 = safe_cast_u32(byte_size64); } return byte_size32; } internal U64 dw_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { U64 result = 0; DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); DW_AttribClass attrib_class = dw_value_class_from_attrib(cu, attrib); if (attrib_class == DW_AttribClass_Const || attrib_class == DW_AttribClass_Block) { if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Type)) { Temp scratch = scratch_begin(0,0); DW_Reference type_ref = dw_ref_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Type); DW_Tag type_tag = {0}; dw_read_tag_cu(scratch.arena, input, type_ref.cu, type_ref.info_off, &type_tag); U64 type_byte_size = dw_byte_size_from_tag(input, cu, type_tag); DW_ATE type_encoding = dw_const_u64_from_tag_attrib_kind(input, type_ref.cu, type_tag, DW_AttribKind_Encoding); if (type_encoding == DW_ATE_Unsigned || type_encoding == DW_ATE_UnsignedChar) { result = dw_interp_const64(type_byte_size, type_encoding, attrib->form_kind, attrib->form); } scratch_end(scratch); } else { result = dw_interp_const_u64(attrib->form_kind, attrib->form); } } else if (attrib_class == DW_AttribClass_Address) { result = dw_address_from_attrib(input, cu, attrib); } else if (attrib_class == DW_AttribClass_Reference) { NotImplemented; } else if (attrib_class != DW_AttribClass_Null) { AssertAlways(!"unexpected attrib class"); } return result; } internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed) { DW_CompUnit cu = {0}; String8 info_data = input->sec[DW_Section_Info].data; // read unit size in bytes U64 length = 0; U64 length_size = str8_deserial_read_dwarf_packed_size(info_data, offset, &length); if (length_size) { // compute unit range Rng1U64 range = rng_1u64(offset, offset + length_size + length); String8 data = str8_substr(info_data, range); U64 cursor = length_size; // read version DW_Version version = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &version); cursor += version_size; if (version_size) { DW_Format format = DW_FormatFromSize(length); B32 is_header_ok = 0; U64 abbrev_base = max_U64; U8 address_size = 0; DW_CompUnitKind unit_kind = DW_CompUnitKind_Reserved; U64 spec_dwo_id = max_U64; switch (version) { default: case DW_Version_Null: case DW_Version_1: break; case DW_Version_2: { U32 abbrev_base32 = 0; U64 abbrev_base_off = cursor; U64 abbrev_base_size = str8_deserial_read_struct(data, abbrev_base_off, &abbrev_base32); if (!abbrev_base_size) { break; } U64 address_size_off = abbrev_base_off + abbrev_base_size; U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); if (!address_size_size) { break; } abbrev_base = abbrev_base32; cursor = address_size_off + address_size_size; is_header_ok = 1; } break; case DW_Version_3: case DW_Version_4: { U64 abbrev_base_off = cursor; U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); if (!abbrev_base_size) { break; } U64 address_size_off = abbrev_base_off + abbrev_base_size; U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); if (!address_size_size) { break; } cursor = address_size_off + address_size_size; is_header_ok = 1; } break; case DW_Version_5: { U64 unit_kind_off = cursor; U64 unit_kind_size = str8_deserial_read_struct(data, unit_kind_off, &unit_kind); if (unit_kind_size == 0) { break; } U64 address_size_off = unit_kind_off + unit_kind_size; U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); if (!address_size_size) { break; } U64 abbrev_base_off = address_size_off + address_size_size; U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); if (!abbrev_base_size) { break; } U64 spec_dwo_id_off = abbrev_base_off + abbrev_base_size; U64 spec_dwo_id_size = 0; if (unit_kind == DW_CompUnitKind_Skeleton || input->sec[DW_Section_Info].is_dwo) { spec_dwo_id_size = str8_deserial_read_struct(data, spec_dwo_id_off, &spec_dwo_id); if (!spec_dwo_id_size) { break; } } cursor = spec_dwo_id_off + spec_dwo_id_size; is_header_ok = 1; } break; } if (is_header_ok) { Temp temp = temp_begin(arena); // TODO: cache abbrev tables with identical offsets String8 abbrev_data = input->sec[DW_Section_Abbrev].data; DW_AbbrevTable abbrev_table = dw_make_abbrev_table(arena, abbrev_data, abbrev_base); DW_Tag cu_tag = {0}; dw_read_tag(arena, data, cursor, range.min, abbrev_table, abbrev_data, version, format, address_size, &cu_tag); // TODO: handle these unit types Assert(cu_tag.kind != DW_TagKind_SkeletonUnit); Assert(cu_tag.kind != DW_TagKind_TypeUnit); if (cu_tag.kind == DW_TagKind_CompileUnit || cu_tag.kind == DW_TagKind_PartialUnit) { // fetch attribs for list sections DW_Attrib *addr_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_AddrBase ); DW_Attrib *str_offsets_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_StrOffsetsBase); DW_Attrib *rnglists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_RngListsBase ); DW_Attrib *loclists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LocListsBase ); // interp attribs as section offsets U64 addr_sec_off = dw_interp_sec_offset(addr_base_attrib->form_kind, addr_base_attrib->form ); U64 str_offsets_sec_off = dw_interp_sec_offset(str_offsets_base_attrib->form_kind, str_offsets_base_attrib->form); U64 rnglists_sec_off = dw_interp_sec_offset(rnglists_base_attrib->form_kind, rnglists_base_attrib->form ); U64 loclists_sec_off = dw_interp_sec_offset(loclists_base_attrib->form_kind, loclists_base_attrib->form ); // map section offset to unit index U64 addr_lu_idx = rng_1u64_array_bsearch(lu_input.addr_ranges, addr_sec_off ); U64 str_offsets_lu_idx = rng_1u64_array_bsearch(lu_input.str_offset_ranges, str_offsets_sec_off); U64 rnglists_lu_idx = rng_1u64_array_bsearch(lu_input.rnglist_ranges, rnglists_sec_off ); U64 loclists_lu_idx = rng_1u64_array_bsearch(lu_input.loclist_ranges, loclists_sec_off ); // map index to unit DW_ListUnit *addr_lu = addr_lu_idx < lu_input.addr_count ? &lu_input.addrs[addr_lu_idx] : 0; DW_ListUnit *str_offsets_lu = str_offsets_lu_idx < lu_input.str_offset_count ? &lu_input.str_offsets[str_offsets_lu_idx] : 0; DW_ListUnit *rnglists_lu = rnglists_lu_idx < lu_input.rnglist_count ? &lu_input.rnglists[rnglists_lu_idx] : 0; DW_ListUnit *loclists_lu = loclists_lu_idx < lu_input.loclist_count ? &lu_input.loclists[loclists_lu_idx] : 0; // find compile unit base address DW_Attrib *low_pc_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LowPc); U64 low_pc = dw_interp_address(address_size, max_U64, addr_lu, low_pc_attrib->form_kind, low_pc_attrib->form); // fill out compile unit cu.ext = DW_Ext_All; cu.kind = unit_kind; cu.version = version; cu.format = format; cu.address_size = address_size; cu.abbrev_off = abbrev_base; cu.info_range = range; cu.first_tag_info_off = range.min + cursor; cu.abbrev_table = abbrev_table; cu.abbrev_data = abbrev_data; cu.addr_lu = addr_lu; cu.str_offsets_lu = str_offsets_lu; cu.rnglists_lu = rnglists_lu; cu.loclists_lu = loclists_lu; cu.low_pc = low_pc; cu.tag = cu_tag; } else { // unexpected tag, release memory and exit temp_end(temp); } } } } return cu; } internal void dw_tag_tree_from_data(Arena *arena, String8 info_data, String8 abbrev_data, DW_CompUnit *cu, DW_TagNode *parent, U64 *cursor, U64 *tag_count) { while (*cursor < info_data.size) { // read tag DW_Tag tag = {0}; U64 tag_size = dw_read_tag(arena, info_data, *cursor, cu->info_range.min, cu->abbrev_table, abbrev_data, cu->version, cu->format, cu->address_size, &tag); if (tag_size == 0) { break; } *cursor += tag_size; // is this sentinel tag? if (tag.kind == DW_TagKind_Null) { break; } // normal tag DW_TagNode *tag_n = push_array(arena, DW_TagNode, 1); tag_n->tag = tag; SLLQueuePush_N(parent->first_child, parent->last_child, tag_n, sibling); // update tag count *tag_count += 1; if (tag.has_children) { dw_tag_tree_from_data(arena, info_data, abbrev_data, cu, tag_n, cursor, tag_count); } } } internal DW_TagTree dw_tag_tree_from_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu) { String8 abbrev_data = input->sec[DW_Section_Abbrev].data; String8 info_data = str8_substr(input->sec[DW_Section_Info].data, cu->info_range); DW_TagNode root = {0}; U64 cursor = cu->first_tag_info_off; U64 tag_count = 0; dw_tag_tree_from_data(arena, info_data, abbrev_data, cu, &root, &cursor, &tag_count); DW_TagTree result = {0}; result.root = root.first_child; result.tag_count = tag_count; return result; } internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree) { Temp scratch = scratch_begin(&arena, 1); struct Frame { struct Frame *next; DW_TagNode *node; }; struct Frame *free_frames = 0; struct Frame *stack = push_array(scratch.arena, struct Frame, 1); stack->node = tag_tree.root; HashTable *ht = hash_table_init(arena, (U64)((F64)tag_tree.tag_count * 1.3)); while (stack) { while (stack->node) { hash_table_push_u64_raw(arena, ht, stack->node->tag.info_off, stack->node); if (stack->node->first_child) { struct Frame *frame = free_frames; if (frame) { SLLStackPop(free_frames); MemoryZeroStruct(frame); } else { frame = push_array(scratch.arena, struct Frame, 1); } frame->node = stack->node->first_child; SLLStackPush(stack, frame); } else { stack->node = stack->node->sibling; } } // recycle free frame struct Frame *frame = stack; SLLStackPop(stack); SLLStackPush(free_frames, frame); if (stack) { stack->node = stack->node->sibling; } } scratch_end(scratch); return ht; } internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off) { DW_TagNode *tag_node = hash_table_search_u64_raw(cu->tag_ht, info_off); return tag_node; } internal DW_LineVMFileArray dw_line_vm_file_array_from_list(Arena *arena, DW_LineVMFileList list) { DW_LineVMFileArray result = {0}; result.count = 0; result.v = push_array(arena, DW_LineFile, list.node_count); for (DW_LineVMFileNode *src = list.first; src != 0; src = src->next) { DW_LineFile *dst = &result.v[result.count++]; dst->file_name = push_str8_copy(arena, src->file.file_name); dst->dir_idx = src->file.dir_idx; dst->modify_time = src->file.modify_time; dst->file_size = src->file.file_size; } return result; } internal U64 dw_read_line_file(String8 data, U64 off, DW_Input *input, DW_Version version, DW_Format format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, DW_LineFile *line_file_out) { MemoryZeroStruct(line_file_out); U64 cursor = off; for (U64 enc_idx = 0; enc_idx < enc_count; ++enc_idx) { DW_LNCT lnct = enc_arr[enc_idx*2 + 0]; DW_FormKind form_kind = enc_arr[enc_idx*2 + 1]; DW_Form form = {0}; U64 bytes_read = 0; switch (lnct) { case DW_LNCT_Path: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->file_name = dw_interp_string(input, format, str_offsets, form_kind, form); } break; case DW_LNCT_DirectoryIndex: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->dir_idx = dw_interp_const_u64(form_kind, form); } break; case DW_LNCT_TimeStamp: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->modify_time = dw_interp_const_u64(form_kind, form); } break; case DW_LNCT_Size: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->file_size = dw_interp_const_u64(form_kind, form); } break; case DW_LNCT_MD5: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->md5_digest = dw_interp_const_u128(form_kind, form); } break; case DW_LNCT_LLVM_Source: { if (ext & DW_Ext_LLVM) { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); line_file_out->source = dw_interp_string(input, format, str_offsets, form_kind, form); } else { Assert(!"extension not supported"); } } break; default: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); Assert(!"unexpected LNTC encoding"); } break; } Assert(bytes_read); cursor += bytes_read; } U64 bytes_read = cursor - off; return bytes_read; } internal U64 dw_read_line_file_array(Arena *arena, String8 data, U64 off, DW_Input *input, DW_Version version, DW_Format format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, U64 table_count, DW_LineVMFileArray *table_out) { Temp temp = temp_begin(arena); table_out->count = table_count; table_out->v = push_array(arena, DW_LineFile, table_count); U64 i, cursor; for (i = 0, cursor = off; i < table_count; ++i) { U64 bytes_read = dw_read_line_file(data, cursor, input, version, format, ext, address_size, str_offsets, enc_count, enc_arr, &table_out->v[i]); if (bytes_read == 0) { break; } cursor += bytes_read; } U64 bytes_read = 0; if (i == table_count) { bytes_read = cursor - off; } else { temp_end(temp); table_out->count = 0; table_out->v = 0; } return bytes_read; } internal U64 dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out) { Temp scratch = scratch_begin(&arena, 1); U64 bytes_read = 0; // read unit length U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(line_data, line_off, &unit_length); U64 unit_opl = line_off + unit_length_size + unit_length; Rng1U64 unit_range = rng_1u64(line_off, unit_opl); DW_Format format = DW_FormatFromSize(unit_length); U64 unit_cursor = unit_length_size; String8 unit_data = str8_substr(line_data, unit_range); // read unit version DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); if (version_size == 0) { goto exit; } unit_cursor += version_size; // read DWARF5 address & segment selector U8 address_size = 0; U8 segsel_size = 0; if (version == DW_Version_5) { U64 address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &address_size); if (address_size_size == 0) { goto exit; } unit_cursor += address_size_size; U64 segsel_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &segsel_size); if (segsel_size_size == 0) { goto exit; } unit_cursor += segsel_size_size; } else { address_size = cu_address_size; } // read header length U64 header_length = 0; U64 header_length_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, format, &header_length); if (header_length_size == 0) { goto exit; } unit_cursor += header_length_size; // read min instruction length U8 min_inst_len = 0; U64 min_inst_len_size = str8_deserial_read_struct(unit_data, unit_cursor, &min_inst_len); if (min_inst_len_size == 0) { goto exit; } unit_cursor += min_inst_len_size; // read max operands for instruction U8 max_ops_for_inst = 1; if (version > DW_Version_3) { U64 max_ops_for_inst_size = str8_deserial_read_struct(unit_data, unit_cursor, &max_ops_for_inst); if (max_ops_for_inst_size == 0) { goto exit; } unit_cursor += max_ops_for_inst_size; } Assert(max_ops_for_inst > 0); U8 default_is_stmt = 0; U64 default_is_stmt_size = str8_deserial_read_struct(unit_data, unit_cursor, &default_is_stmt); if (default_is_stmt_size == 0) { goto exit; } unit_cursor += default_is_stmt_size; S8 line_base = 0; U64 line_base_size = str8_deserial_read_struct(unit_data, unit_cursor, &line_base); if (line_base_size == 0) { goto exit; } unit_cursor += line_base_size; U8 line_range = 0; U64 line_range_size = str8_deserial_read_struct(unit_data, unit_cursor, &line_range); if (line_range_size == 0) { goto exit; } unit_cursor += line_range_size; U8 opcode_base = 0; U64 opcode_base_size = str8_deserial_read_struct(unit_data, unit_cursor, &opcode_base); if (opcode_base_size == 0) { goto exit; } unit_cursor += opcode_base_size; U64 num_opcode_lens = opcode_base > 0 ? opcode_base - 1 : 0; U8 *opcode_lens = str8_deserial_get_raw_ptr(unit_data, unit_cursor, num_opcode_lens * sizeof(opcode_lens[0])); if (opcode_lens == 0) { goto exit; } unit_cursor += num_opcode_lens * sizeof(opcode_lens[0]); DW_LineVMFileArray dir_table = {0}; DW_LineVMFileArray file_table = {0}; if (version < DW_Version_5) { // read directory table DW_LineVMFileList dir_list = {0}; { // compile directory is always first in the table DW_LineVMFileNode *node = push_array(scratch.arena, DW_LineVMFileNode, 1); node->file.file_name = cu_dir; SLLQueuePush(dir_list.first, dir_list.last, node); ++dir_list.node_count; } // parse additional directories for (; unit_cursor < unit_data.size; ) { String8 dir = {0}; unit_cursor += str8_deserial_read_cstr(unit_data, unit_cursor, &dir); if (dir.size == 0) { break; } DW_LineVMFileNode *node = push_array(scratch.arena, DW_LineVMFileNode, 1); node->file.file_name = dir; SLLQueuePush(dir_list.first, dir_list.last, node); ++dir_list.node_count; } DW_LineVMFileList file_list = {0}; { // compile unit name is always first in the file table { DW_LineVMFileNode *node = push_array(scratch.arena, DW_LineVMFileNode, 1); node->file.file_name = cu_name; SLLQueuePush(file_list.first, file_list.last, node); ++file_list.node_count; } // read file table for (; unit_cursor < unit_data.size; ) { String8 file_name = {0}; unit_cursor += str8_deserial_read_cstr(unit_data, unit_cursor, &file_name); if (file_name.size == 0) { break; } U64 dir_index = 0; U64 dir_index_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &dir_index); if (dir_index_size == 0) { goto exit; } unit_cursor += dir_index_size; U64 modify_time = 0; U64 modify_time_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &modify_time); if (modify_time_size == 0) { goto exit; } unit_cursor += modify_time_size; U64 file_size = 0; U64 file_size_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &file_size); if (file_size_size == 0) { goto exit; } unit_cursor += file_size_size; DW_LineVMFileNode *node = push_array(scratch.arena, DW_LineVMFileNode, 1); node->file.file_name = file_name; node->file.dir_idx = dir_index; node->file.modify_time = modify_time; node->file.file_size = file_size; SLLQueuePush(file_list.first, file_list.last, node); ++file_list.node_count; } } // list -> array dir_table = dw_line_vm_file_array_from_list(arena, dir_list); file_table = dw_line_vm_file_array_from_list(arena, file_list); } // DWARF5 else { // directory table { // read table entry encoding count U8 enc_count = 0; U64 enc_count_size = str8_deserial_read_struct(unit_data, unit_cursor, &enc_count); if (enc_count_size == 0) { goto exit; } unit_cursor += enc_count_size; // read table entry encodings U64 *enc_arr = 0; U64 enc_arr_size = str8_deserial_read_uleb128_array(scratch.arena, unit_data, unit_cursor, enc_count*2, &enc_arr); if (enc_arr_size == 0) { goto exit; } unit_cursor += enc_arr_size; // read table count U64 table_count = 0; U64 table_count_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &table_count); if (table_count_size == 0) { goto exit; } unit_cursor += table_count_size; // read table U64 table_size = dw_read_line_file_array(arena, unit_data, unit_cursor, input, version, format, DW_Ext_All, address_size, cu_str_offsets, enc_count, enc_arr, table_count, &dir_table); if (table_size == 0) { goto exit; } unit_cursor += table_size; } // file table { // read table entry encoding count U8 enc_count = 0; U64 enc_count_size = str8_deserial_read_struct(unit_data, unit_cursor, &enc_count); if (enc_count == 0) { goto exit; } unit_cursor += enc_count_size; // read table entry encodings U64 *enc_arr = 0; U64 enc_arr_size = str8_deserial_read_uleb128_array(scratch.arena, unit_data, unit_cursor, enc_count*2, &enc_arr); if (enc_arr_size == 0) { goto exit; } unit_cursor += enc_arr_size; // read table count U64 table_count = 0; U64 table_count_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &table_count); if (table_count_size == 0) { goto exit; } unit_cursor += table_count_size; // read table U64 file_table_size = dw_read_line_file_array(arena, unit_data, unit_cursor, input, version, format, DW_Ext_All, address_size, cu_str_offsets, enc_count, enc_arr, table_count, &file_table); if (file_table_size == 0) { goto exit; } unit_cursor += file_table_size; } } if (header_out) { header_out->unit_range = unit_range; header_out->version = version; header_out->address_size = address_size; header_out->segment_selector_size = segsel_size; header_out->header_length = header_length; header_out->min_inst_len = min_inst_len; header_out->max_ops_for_inst = max_ops_for_inst; header_out->default_is_stmt = default_is_stmt; header_out->line_base = line_base; header_out->line_range = line_range; header_out->opcode_base = opcode_base; header_out->num_opcode_lens = num_opcode_lens; header_out->opcode_lens = opcode_lens; header_out->dir_table = dir_table; header_out->file_table = file_table; } bytes_read = unit_cursor; exit:; scratch_end(scratch); return bytes_read; } internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt) { state->address = 0; state->op_index = 0; state->file_index = 1; state->line = 1; state->column = 0; state->is_stmt = default_is_stmt; state->basic_block = 0; state->prologue_end = 0; state->epilogue_begin = 0; state->isa = 0; state->discriminator = 0; } internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst) { U64 op_index = state->op_index + advance; state->address += min_inst_len*(op_index/max_ops_for_inst); state->op_index = op_index % max_ops_for_inst; } internal DW_LineSeqNode * dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl) { DW_LineSeqNode *new_seq = push_array(arena, DW_LineSeqNode, 1); SLLQueuePush(parsed_tbl->first_seq, parsed_tbl->last_seq, new_seq); parsed_tbl->seq_count += 1; return new_seq; } internal DW_LineNode * dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_state, B32 start_of_sequence) { DW_LineSeqNode *seq = tbl->last_seq; if(seq == 0 || start_of_sequence) { seq = dw_push_line_seq(arena, tbl); } DW_LineNode *n = push_array(arena, DW_LineNode, 1); n->v.file_index = vm_state->file_index; n->v.line = vm_state->line; n->v.column = vm_state->column; n->v.address = vm_state->address; SLLQueuePush(seq->first, seq->last, n); seq->count += 1; return n; } internal String8 dw_path_from_file(Arena *arena, DW_LineVMHeader *vm, DW_LineFile *file) { Temp scratch = scratch_begin(&arena, 1); String8 dir = vm->dir_table.v[file->dir_idx].file_name; PathStyle style = path_style_from_str8(dir); if (style == PathStyle_Null || style == PathStyle_Relative) { style = path_style_from_str8(file->file_name); } String8List path_list = {0}; if (str8_match_lit("..", dir, StringMatchFlag_RightSideSloppy)) { String8List comp_dir_list = str8_split_path(scratch.arena, vm->dir_table.v[0].file_name); str8_list_concat_in_place(&path_list, &comp_dir_list); } String8List dir_list = str8_split_path(scratch.arena, dir); str8_list_concat_in_place(&path_list, &dir_list); str8_list_push(scratch.arena, &path_list, file->file_name); str8_path_list_resolve_dots_in_place(&path_list, style); String8 path = str8_path_list_join_by_style(arena, &path_list, style); scratch_end(scratch); return path; } internal String8 dw_path_from_file_idx(Arena *arena, DW_LineVMHeader *vm, U64 file_idx) { return dw_path_from_file(arena, vm, &vm->file_table.v[file_idx]); } internal DW_LineTableParseResult dw_parsed_line_table_from_data(Arena *arena, String8 unit_data, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets) { DW_LineVMHeader vm_header = {0}; U64 vm_header_size = dw_read_line_vm_header(arena, unit_data, 0, input, cu_dir, cu_name, cu_address_size, cu_str_offsets, &vm_header); U64 unit_cursor = vm_header_size; U64 unit_cursor_opl = Min(unit_data.size, vm_header.unit_range.max); //- rjf: prep state for VM DW_LineVMState vm_state = {0}; dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); //- rjf: VM loop; build output list DW_LineTableParseResult result = {.vm_header = vm_header}; B32 end_of_seq = 0; B32 error = 0; for(;!error && unit_cursor < unit_cursor_opl;) { //- rjf: parse opcode U8 opcode = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &opcode); //- rjf: do opcode action switch(opcode) { //- rjf: special opcode cases default: { if(opcode >= vm_header.opcode_base) { U32 adjusted_opcode = (U32)(opcode - vm_header.opcode_base); U32 op_advance = adjusted_opcode / vm_header.line_range; S32 line_inc = (S32)vm_header.line_base + ((S32)adjusted_opcode) % (S32)vm_header.line_range; // TODO: can we just call dw_advance_line_vm_state_pc U64 addr_inc = vm_header.min_inst_len * ((vm_state.op_index+op_advance) / vm_header.max_ops_for_inst); vm_state.address += addr_inc; vm_state.op_index = (vm_state.op_index + op_advance) % vm_header.max_ops_for_inst; vm_state.line = (U32)((S32)vm_state.line + line_inc); vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; vm_state.discriminator = 0; if(vm_state.is_stmt) { dw_push_line(arena, &result, &vm_state, end_of_seq); } end_of_seq = 0; #if 0 // NOTE(rjf): DWARF has dummy lines at the end of groups of line ranges, where we'd like // to break line info into sequences. if(vm_state.line == 0) { end_of_seq = 1; } #endif } // Skipping unknown opcode. This is a valid case and // it works because compiler stores operand lengths. else { if(0 < opcode && opcode <= vm_header.num_opcode_lens) { U8 num_operands = vm_header.opcode_lens[opcode - 1]; for(U8 i = 0; i < num_operands; i += 1) { U64 operand = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &operand); } } else { error = 1; goto exit; } } }break; //- standard opcodes case DW_StdOpcode_Copy: { if(vm_state.is_stmt) { dw_push_line(arena, &result, &vm_state, end_of_seq); } end_of_seq = 0; vm_state.discriminator = 0; vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; }break; case DW_StdOpcode_AdvancePc: { U64 advance = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &advance); dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); }break; case DW_StdOpcode_AdvanceLine: { S64 s = 0; unit_cursor += str8_deserial_read_sleb128(unit_data, unit_cursor, &s); vm_state.line += s; }break; case DW_StdOpcode_SetFile: { U64 file_index = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_index); vm_state.file_index = file_index; }break; case DW_StdOpcode_SetColumn: { U64 column = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &column); vm_state.column = column; }break; case DW_StdOpcode_NegateStmt: { vm_state.is_stmt = !vm_state.is_stmt; }break; case DW_StdOpcode_SetBasicBlock: { vm_state.basic_block = 1; }break; case DW_StdOpcode_ConstAddPc: { U64 advance = (0xffu - vm_header.opcode_base) / vm_header.line_range; dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); }break; case DW_StdOpcode_FixedAdvancePc: { U16 operand = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &operand); vm_state.address += operand; vm_state.op_index = 0; }break; case DW_StdOpcode_SetPrologueEnd: { vm_state.prologue_end = 1; }break; case DW_StdOpcode_SetEpilogueBegin: { vm_state.epilogue_begin = 1; }break; case DW_StdOpcode_SetIsa: { U64 v = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); vm_state.isa = v; }break; //- extended opcodes case DW_StdOpcode_ExtendedOpcode: { U64 length = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &length); U64 extended_opl = unit_cursor + length; U8 extended_opcode = 0; unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &extended_opcode); switch(extended_opcode) { default:{}break; case DW_ExtOpcode_EndSequence: { vm_state.end_sequence = 1; if(vm_state.is_stmt) { dw_push_line(arena, &result, &vm_state, 0); } dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); end_of_seq = 1; }break; case DW_ExtOpcode_SetAddress: { U64 address = 0; unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, vm_header.address_size, vm_header.address_size); vm_state.address = address; vm_state.op_index = 0; }break; case DW_ExtOpcode_DefineFile: { String8 file_name = {0}; U64 dir_index = 0; U64 modify_time = 0; U64 file_size = 0; unit_cursor += str8_deserial_read_cstr(unit_data, unit_cursor, &file_name); unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &dir_index); unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &modify_time); unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_size); // TODO(rjf): Not fully implemented. By the DWARF V4 spec, the above is // all that needs to be parsed, but the rest of the work that needs to // happen here---allowing this file to be used by further opcodes---is // not implemented. // // See the DWARF V4 spec (June 10, 2010), page 122. error = 1; }break; case DW_ExtOpcode_SetDiscriminator: { U64 v = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); vm_state.discriminator = v; }break; } unit_cursor = extended_opl; }break; } } exit:; return result; } internal DW_PubStringsTable dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_SectionKind section_kind) { Temp scratch = scratch_begin(&arena, 1); DW_PubStringsTable names_table = {0}; names_table.size = 16384; names_table.buckets = push_array(arena, DW_PubStringsBucket*, names_table.size); String8 section_data = input->sec[section_kind].data; for(U64 cursor = 0; cursor < section_data.size; ) { U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(section_data, cursor, &unit_length); if (unit_length_size == 0) { break; } cursor += unit_length_size; U64 cursor_opl = Min(cursor + unit_length, section_data.size); if (cursor >= cursor_opl) { break; } DW_Version unit_version = 0; cursor += str8_deserial_read_struct(section_data, cursor, &unit_version); if (cursor >= cursor_opl) { break; } DW_Format format = DW_FormatFromSize(unit_length); U64 debug_info_off = 0; cursor += str8_deserial_read_dwarf_uint(section_data, cursor, format, &debug_info_off); if (cursor >= cursor_opl) { break; } U64 debug_info_length = 0; cursor += str8_deserial_read_dwarf_packed_size(section_data, cursor, &debug_info_length); if (cursor >= cursor_opl) { break; } U64 off_size = dw_size_from_format(format); for (; (cursor + off_size) <= cursor_opl;) { U64 info_off = 0; U64 info_off_size = str8_deserial_read_dwarf_uint(section_data, cursor, format, &info_off); cursor += info_off_size; if (info_off_size == 0 || info_off == 0) { break; } String8 string = {0}; cursor += str8_deserial_read_cstr(section_data, cursor, &string); U64 hash = u64_hash_from_str8(string); U64 bucket_idx = hash % names_table.size; DW_PubStringsBucket *bucket = push_array(arena, DW_PubStringsBucket, 1); bucket->next = names_table.buckets[bucket_idx]; bucket->string = string; bucket->info_off = info_off; bucket->cu_info_off = debug_info_off; names_table.buckets[bucket_idx] = bucket; } } scratch_end(scratch); return names_table; } internal DW_Expr dw_expr_from_data(Arena *arena, DW_Format format, U64 addr_size, String8 data) { DW_Expr expr = {0}; for (U64 cursor = 0; cursor < data.size; ) { U64 inst_start = cursor; DW_ExprOp opcode = 0; cursor += str8_deserial_read_struct(data, cursor, &opcode); DW_ExprOperand operands[4] = {0}; switch (opcode) { case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { // implicit operands } break; case DW_ExprOp_Const1U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; case DW_ExprOp_Const2U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); } break; case DW_ExprOp_Const4U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; case DW_ExprOp_Const8U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u64); } break; case DW_ExprOp_Const1S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s8); } break; case DW_ExprOp_Const2S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; case DW_ExprOp_Const4S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s32); } break; case DW_ExprOp_Const8S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s64); } break; case DW_ExprOp_ConstU: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_ConstS: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; case DW_ExprOp_Addr: { cursor += str8_deserial_read(data, cursor, &operands[0].u64, addr_size, addr_size); } break; case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { // implicit operands } break; case DW_ExprOp_RegX: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_ImplicitValue: { U64 value_size = 0; String8 value = {0}; cursor += str8_deserial_read_uleb128(data, cursor, &value_size); cursor += str8_deserial_read_block(data, cursor, value_size, &operands[0].block); } break; case DW_ExprOp_Piece: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_BitPiece: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); } break; case DW_ExprOp_Pick: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; case DW_ExprOp_PlusUConst: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_Skip: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; case DW_ExprOp_Bra: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; case DW_ExprOp_BRegX: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); } break; case DW_ExprOp_FBReg: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; case DW_ExprOp_Deref: { // no operands } break; case DW_ExprOp_DerefSize: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; case DW_ExprOp_XDerefSize: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; case DW_ExprOp_Call2: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); } break; case DW_ExprOp_Call4: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; case DW_ExprOp_CallRef: { cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); } break; case DW_ExprOp_ImplicitPointer: case DW_ExprOp_GNU_ImplicitPointer: { cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); } break; case DW_ExprOp_Convert: case DW_ExprOp_GNU_Convert: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_GNU_ParameterRef: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; case DW_ExprOp_DerefType: case DW_ExprOp_GNU_DerefType: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); } break; case DW_ExprOp_XDerefType: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); } break; case DW_ExprOp_ConstType: case DW_ExprOp_GNU_ConstType: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); cursor += str8_deserial_read_struct(data, cursor, &operands[1].u8); cursor += str8_deserial_read_block(data, cursor, operands[1].u8, &operands[2].block); } break; case DW_ExprOp_RegvalType: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); } break; case DW_ExprOp_EntryValue: case DW_ExprOp_GNU_EntryValue: { U64 entry_value_expr_size = 0; cursor += str8_deserial_read_uleb128(data, cursor, &entry_value_expr_size); cursor += str8_deserial_read_block(data, cursor, entry_value_expr_size, &operands[0].block); } break; case DW_ExprOp_Addrx: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_Constx: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_CallFrameCfa: case DW_ExprOp_FormTlsAddress: case DW_ExprOp_PushObjectAddress: case DW_ExprOp_Nop: case DW_ExprOp_Eq: case DW_ExprOp_Ge: case DW_ExprOp_Gt: case DW_ExprOp_Le: case DW_ExprOp_Lt: case DW_ExprOp_Ne: case DW_ExprOp_Shl: case DW_ExprOp_Shr: case DW_ExprOp_Shra: case DW_ExprOp_Xor: case DW_ExprOp_XDeref: case DW_ExprOp_Abs: case DW_ExprOp_And: case DW_ExprOp_Div: case DW_ExprOp_Minus: case DW_ExprOp_Mod: case DW_ExprOp_Mul: case DW_ExprOp_Neg: case DW_ExprOp_Not: case DW_ExprOp_Or: case DW_ExprOp_Plus: case DW_ExprOp_Rot: case DW_ExprOp_Swap: case DW_ExprOp_Dup: case DW_ExprOp_Drop: case DW_ExprOp_Over: case DW_ExprOp_StackValue: case DW_ExprOp_GNU_PushTlsAddress: { // no operands } break; case DW_ExprOp_GNU_AddrIndex: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; case DW_ExprOp_GNU_ConstIndex: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; default: { InvalidPath; } break; } U64 operand_count = dw_operand_count_from_expr_op(opcode); DW_ExprInst *inst = push_array(arena, DW_ExprInst, 1); inst->opcode = opcode; inst->size = cursor - inst_start; inst->operands = push_array(arena, DW_ExprOperand, operand_count); MemoryCopy(inst->operands, operands, operand_count * sizeof(DW_ExprOperand)); DLLPushBack(expr.first, expr.last, inst); expr.count += 1; } return expr; } internal void dw_cfa_inst_list_push_node(DW_CFA_InstList *list, DW_CFA_InstNode *n) { SLLQueuePush(list->first, list->last, n); list->count += 1; } internal DW_CFA_InstNode * dw_cfa_inst_list_push(Arena *arena, DW_CFA_InstList *list, DW_CFA_Inst v) { DW_CFA_InstNode *n = push_array(arena, DW_CFA_InstNode, 1); n->v = v; dw_cfa_inst_list_push_node(list, n); return n; } internal U64 dw_read_debug_frame_ptr(String8 data, DW_CIE *cie, U64 *ptr_out) { U64 read_size = 0; if (cie->segment_selector_size) { NotImplemented; } else { read_size = str8_deserial_read(data, 0, ptr_out, cie->address_size, cie->address_size); } return read_size; } internal U64 dw_parse_descriptor_entry_header(String8 data, U64 off, DW_DescriptorEntry *desc_out) { U32 first_four_bytes = 0; str8_deserial_read_struct(data, off, &first_four_bytes); DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit; U64 length = 0; U64 length_size = str8_deserial_read_dwarf_packed_size(data, off, &length); if (length_size == 0) { goto exit; } Rng1U64 entry_range = rng_1u64(off, off + length_size + length); String8 entry_data = str8_substr(data, entry_range); U64 id = 0; U64 id_size = str8_deserial_read_dwarf_uint(entry_data, length_size, format, &id); if (id_size == 0) { goto exit; } U64 id_type = format == DW_Format_32Bit ? max_U32 : max_U64; desc_out->format = format; desc_out->type = (id == id_type) ? DW_DescriptorEntryType_CIE : DW_DescriptorEntryType_FDE; desc_out->entry_range = entry_range; desc_out->cie_pointer = id; desc_out->cie_pointer_off = length_size; exit:; return length + length_size; } internal B32 dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 4 : 12; U64 cie_id = 0; U64 cie_id_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_id); if (cie_id_size == 0) { goto exit; } cursor += cie_id_size; U8 version = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &version); if (version_size == 0) { goto exit; } cursor += version_size; String8 aug_string = {0}; U64 aug_string_size = str8_deserial_read_cstr(data, cursor, &aug_string); if (aug_string_size == 0) { goto exit; } cursor += aug_string_size; U8 address_size = 0; U8 segment_selector_size = 0; if (version >= DW_Version_4) { U64 address_size_size = str8_deserial_read_struct(data, cursor, &address_size); if (address_size_size == 0) { goto exit; } cursor += address_size_size; U64 segment_selector_size_size = str8_deserial_read_struct(data, cursor, &segment_selector_size); if (segment_selector_size_size == 0) { goto exit; } cursor += segment_selector_size; } else { address_size = byte_size_from_arch(arch); } U64 code_align_factor = 0; U64 code_align_factor_size = str8_deserial_read_uleb128(data, cursor, &code_align_factor); if (code_align_factor_size == 0) { goto exit; } cursor += code_align_factor_size; S64 data_align_factor = 0; U64 data_align_factor_size = str8_deserial_read_sleb128(data, cursor, &data_align_factor); if (data_align_factor_size == 0) { goto exit; } cursor += data_align_factor_size; U64 ret_addr_reg = 0; U64 ret_addr_reg_size = 0; if (version == DW_Version_1) { ret_addr_reg_size = str8_deserial_read(data, cursor, &ret_addr_reg, sizeof(U8), sizeof(U8)); } else { ret_addr_reg_size = str8_deserial_read_uleb128(data, cursor, &ret_addr_reg); } if (ret_addr_reg_size == 0) { goto exit; } cursor += ret_addr_reg_size; if (aug_string.size > 0) { goto exit; } cie_out->insts = str8_skip(data, cursor); cie_out->aug_string = aug_string; cie_out->code_align_factor = code_align_factor; cie_out->data_align_factor = data_align_factor; cie_out->ret_addr_reg = ret_addr_reg; cie_out->format = format; cie_out->version = version; cie_out->address_size = address_size; cie_out->segment_selector_size = segment_selector_size; is_parsed = 1; exit:; return is_parsed; } internal B32 dw_parse_fde(String8 data, DW_Format format, DW_CIE *cie, DW_FDE *fde_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 4 : 12; // extract CIE pointer U64 cie_pointer = 0; U64 cie_pointer_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_pointer); if (cie_pointer_size == 0) { goto exit; } cursor += cie_pointer_size; // extract address of first instruction U64 pc_begin = 0; U64 pc_begin_size = dw_read_debug_frame_ptr(str8_skip(data, cursor), cie, &pc_begin); if (pc_begin_size == 0) { goto exit; } cursor += pc_begin_size; // extract instruction range size U64 pc_range = 0; U64 pc_range_size = dw_read_debug_frame_ptr(str8_skip(data, cursor), cie, &pc_range); if (pc_range_size == 0) { goto exit; } cursor += pc_range_size; // parse augmentation data String8 aug_data = str8_substr(data, rng_1u64(cursor, cursor + cie->aug_data.size)); cursor += cie->aug_data.size; // commit values to out fde_out->format = format; fde_out->cie_pointer = cie_pointer; fde_out->pc_range = rng_1u64(pc_begin, pc_begin + pc_range); fde_out->insts = str8_skip(data, cursor); is_parsed = 1; exit:; return is_parsed; } internal B32 dw_parse_cfi(String8 data, U64 fde_offset, Arch arch, DW_CIE *cie_out, DW_FDE *fde_out) { B32 is_parsed = 0; DW_DescriptorEntry fde_desc = {0}; dw_parse_descriptor_entry_header(data, fde_offset, &fde_desc); if (fde_desc.type == DW_DescriptorEntryType_FDE) { U64 cie_pointer_off = fde_desc.format == DW_Format_32Bit ? 4 : 12; U64 cie_pointer = 0; U64 cie_pointer_size = str8_deserial_read_dwarf_uint(data, fde_offset + cie_pointer_off, fde_desc.format, &cie_pointer); if (cie_pointer_size) { DW_DescriptorEntry cie_desc = {0}; dw_parse_descriptor_entry_header(data, cie_pointer, &cie_desc); if (cie_desc.type == DW_DescriptorEntryType_CIE) { if (dw_parse_cie(str8_substr(data, cie_desc.entry_range), cie_desc.format, arch, cie_out)) { if (dw_parse_fde(str8_substr(data, fde_desc.entry_range), fde_desc.format, cie_out, fde_out)) { is_parsed = 1; } } } } } return is_parsed; } internal DW_CFA_ParseErrorCode dw_parse_cfa_inst(String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud, U64 *bytes_read_out, DW_CFA_Inst *inst_out) { *bytes_read_out = 0; DW_CFA_ParseErrorCode error_code = DW_CFA_ParseErrorCode_End; U64 cursor = 0; // read opcode DW_CFA_Opcode raw_opcode = 0; U64 raw_opcode_size = str8_deserial_read_struct(data, cursor, &raw_opcode); if (raw_opcode_size == 0) { goto exit; } cursor += raw_opcode_size; // decode opcode implicit operand U64 opcode = raw_opcode & ~DW_CFA_Mask_OpcodeHi; U64 implicit_operand = 0; if ((raw_opcode & DW_CFA_Mask_OpcodeHi) != 0) { opcode = raw_opcode & DW_CFA_Mask_OpcodeHi; implicit_operand = raw_opcode & DW_CFA_Mask_Operand; } // decode operands DW_CFA_Operand operands[DW_CFA_OperandMax] = {0}; switch (opcode) { case DW_CFA_SetLoc: { U64 address_size = decode_ptr_func(str8_skip(data, cursor), decode_ptr_ud, &operands[0].u64); if (address_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += address_size; } break; case DW_CFA_AdvanceLoc: { operands[0].u64 = implicit_operand * code_align_factor; } break; case DW_CFA_AdvanceLoc1: { U8 delta = 0; U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += delta_size; operands[0].u64 = delta * code_align_factor; } break; case DW_CFA_AdvanceLoc2: { U16 delta = 0; U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += delta_size; operands[0].u64 = delta * code_align_factor; } break; case DW_CFA_AdvanceLoc4: { U32 delta = 0; U64 delta_size = str8_deserial_read_struct(data, cursor, &delta); if (delta_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } operands[0].u64 = delta * code_align_factor; } break; case DW_CFA_DefCfa: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = reg; operands[1].u64 = offset; } break; case DW_CFA_DefCfaSf: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; S64 offset = 0; U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = reg; operands[1].s64 = offset * data_align_factor; } break; case DW_CFA_DefCfaRegister: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; operands[0].u64 = reg; } break; case DW_CFA_DefCfaOffset: { U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = offset; } break; case DW_CFA_DefCfaOffsetSf: { U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = offset * data_align_factor; } break; case DW_CFA_DefCfaExpr: { U64 expr_size = 0; U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += expr_size_size; if (cursor + expr_size > data.size) { goto exit; } String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); operands[0].block = expr; cursor += expr_size; } break; case DW_CFA_Undefined: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; operands[0].u64 = reg; } break; case DW_CFA_SameValue: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; operands[0].u64 = reg; } break; case DW_CFA_Offset: { U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = implicit_operand; operands[1].s64 = (S64)offset * data_align_factor; } break; case DW_CFA_OffsetExt: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = reg; operands[1].u64 = offset * data_align_factor; } break; case DW_CFA_OffsetExtSf: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; S64 offset = 0; U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = reg; operands[1].s64 = offset * data_align_factor; } break; case DW_CFA_ValOffset: { U64 val = 0; U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += val_size; U64 offset = 0; U64 offset_size = str8_deserial_read_uleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = val; operands[1].u64 = offset * data_align_factor; } break; case DW_CFA_ValOffsetSf: { U64 val = 0; U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); if (val_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += val_size; S64 offset = 0; U64 offset_size = str8_deserial_read_sleb128(data, cursor, &offset); if (offset_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += offset_size; operands[0].u64 = val; operands[1].s64 = offset; } break; case DW_CFA_Register: { U64 dst_reg = 0; U64 dst_reg_size = str8_deserial_read_uleb128(data, cursor, &dst_reg); if (dst_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += dst_reg_size; U64 src_reg = 0; U64 src_reg_size = str8_deserial_read_uleb128(data, cursor, &src_reg); if (src_reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += src_reg_size; operands[0].u64 = dst_reg; operands[1].u64 = src_reg; } break; case DW_CFA_Expr: { U64 reg = 0; U64 reg_size = str8_deserial_read_uleb128(data, cursor, ®); if (reg_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += reg_size; U64 expr_size = 0; U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += expr_size_size; if (cursor + expr_size > data.size) { goto exit; } String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); cursor += expr_size; operands[0].u64 = reg; operands[1].block = expr; } break; case DW_CFA_ValExpr: { U64 val = 0; U64 val_size = str8_deserial_read_uleb128(data, cursor, &val); if (val_size == 0) { goto exit; } cursor += val_size; U64 expr_size = 0; U64 expr_size_size = str8_deserial_read_uleb128(data, cursor, &expr_size); if (expr_size_size == 0) { error_code = DW_CFA_ParseErrorCode_OutOfData; goto exit; } cursor += expr_size_size; if (cursor + expr_size > data.size) { goto exit; } String8 expr = str8_prefix(str8_skip(data, cursor), expr_size); cursor += expr_size; operands[0].u64 = val; operands[1].block = expr; } break; case DW_CFA_Restore: { operands[0].u64 = implicit_operand; } break; case DW_CFA_RestoreExt: {} break; case DW_CFA_RememberState: {} break; case DW_CFA_RestoreState: {} break; case DW_CFA_Nop: {} break; default: { NotImplemented; goto exit; } break; } // fill out output inst_out->opcode = opcode; MemoryCopyTyped(&inst_out->operands[0], &operands[0], DW_CFA_OperandMax); *bytes_read_out = cursor; error_code = DW_CFA_ParseErrorCode_NewInst; exit:; return error_code; } internal DW_CFA_InstList dw_parse_cfa_inst_list(Arena *arena, String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud) { U64 pos = arena_pos(arena); DW_CFA_InstList list = {0}; for (U64 cursor = 0, inst_size;; cursor += inst_size) { DW_CFA_Inst inst = {0}; DW_CFA_ParseErrorCode error_code = dw_parse_cfa_inst(str8_skip(data, cursor), code_align_factor, data_align_factor, decode_ptr_func, decode_ptr_ud, &inst_size, &inst); if (error_code == DW_CFA_ParseErrorCode_End) { break; } if (error_code != DW_CFA_ParseErrorCode_NewInst) { MemoryZeroStruct(&list); arena_pop_to(arena, pos); break; } dw_cfa_inst_list_push(arena, &list, inst); } return list; } internal DW_DECODE_PTR(dw_decode_ptr_debug_frame) { return dw_read_debug_frame_ptr(data, ud, ptr_out); } ================================================ FILE: src/dwarf/dwarf_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_PARSE_H #define DWARF_PARSE_H typedef struct DW_Section DW_Section; struct DW_Section { String8 name; String8 data; B32 is_dwo; }; typedef struct DW_Input DW_Input; struct DW_Input { DW_Section sec[DW_Section_Count]; DW_Section sup[DW_Section_Count]; }; typedef struct DW_ListUnit DW_ListUnit; struct DW_ListUnit { DW_Version version; U64 address_size; U64 segment_selector_size; U64 entry_size; String8 entries; }; typedef struct DW_ListUnitInput DW_ListUnitInput; struct DW_ListUnitInput { U64 addr_count; U64 str_offset_count; U64 rnglist_count; U64 loclist_count; Rng1U64Array addr_ranges; Rng1U64Array str_offset_ranges; Rng1U64Array rnglist_ranges; Rng1U64Array loclist_ranges; DW_ListUnit *addrs; DW_ListUnit *str_offsets; DW_ListUnit *rnglists; DW_ListUnit *loclists; }; typedef struct DW_AbbrevTableEntry DW_AbbrevTableEntry; struct DW_AbbrevTableEntry { U64 id; U64 off; }; typedef struct DW_AbbrevTable DW_AbbrevTable; struct DW_AbbrevTable { U64 count; DW_AbbrevTableEntry *entries; }; typedef enum DW_AbbrevKind { DW_Abbrev_Null, DW_Abbrev_Tag, DW_Abbrev_Attrib, DW_Abbrev_AttribSequenceEnd, DW_Abbrev_DIEBegin, DW_Abbrev_DIEEnd, } DW_AbbrevKind; typedef U32 DW_AbbrevFlags; enum { DW_AbbrevFlag_HasImplicitConst = (1 << 0), DW_AbbrevFlag_HasChildren = (1 << 1), }; typedef struct DW_Abbrev DW_Abbrev; struct DW_Abbrev { DW_AbbrevKind kind; U64 sub_kind; U64 id; U64 const_value; DW_AbbrevFlags flags; }; typedef union DW_Form { String8 addr; String8 block; String8 data; String8 string; String8 exprloc; B8 flag; S64 sdata; U64 udata; U64 sec_offset; U64 ref; U64 strp_sup; U64 xval; U64 addrx; U64 strx; U64 rnglistx; U64 ptr; U64 implicit_const; } DW_Form; typedef struct DW_Attrib DW_Attrib; struct DW_Attrib { U64 info_off; U64 abbrev_off; U64 abbrev_id; DW_AttribKind attrib_kind; DW_FormKind form_kind; DW_Form form; }; typedef struct DW_AttribNode DW_AttribNode; struct DW_AttribNode { DW_AttribNode *next; DW_Attrib v; }; typedef struct DW_AttribList DW_AttribList; struct DW_AttribList { DW_AttribNode *first; DW_AttribNode *last; U64 count; }; typedef struct DW_Tag DW_Tag; struct DW_Tag { B32 has_children; U64 abbrev_id; DW_TagKind kind; DW_AttribList attribs; U64 info_off; U8 v[1]; }; typedef struct DW_TagNode DW_TagNode; struct DW_TagNode { DW_Tag tag; DW_TagNode *sibling; DW_TagNode *first_child; DW_TagNode *last_child; }; typedef struct DW_Loc DW_Loc; struct DW_Loc { Rng1U64 range; String8 expr; }; typedef struct DW_LocNode DW_LocNode; struct DW_LocNode { DW_LocNode *next; DW_Loc v; }; typedef struct DW_LocList DW_LocList; struct DW_LocList { DW_LocNode *first; DW_LocNode *last; U64 count; }; typedef struct DW_CompUnit DW_CompUnit; struct DW_CompUnit { DW_Ext ext; DW_CompUnitKind kind; DW_Version version; DW_Format format; U64 address_size; U64 abbrev_off; Rng1U64 info_range; U64 first_tag_info_off; DW_AbbrevTable abbrev_table; String8 abbrev_data; DW_ListUnit *addr_lu; DW_ListUnit *str_offsets_lu; DW_ListUnit *rnglists_lu; DW_ListUnit *loclists_lu; U64 low_pc; U64 dwo_id; DW_Tag tag; HashTable *tag_ht; }; typedef struct DW_TagTree { DW_TagNode *root; U64 tag_count; } DW_TagTree; typedef struct DW_LineFile { String8 file_name; U64 dir_idx; U64 modify_time; U64 file_size; U128 md5_digest; String8 source; } DW_LineFile; typedef struct DW_LineVMFileNode { struct DW_LineVMFileNode *next; DW_LineFile file; } DW_LineVMFileNode; typedef struct DW_LineVMFileList { U64 node_count; DW_LineVMFileNode *first; DW_LineVMFileNode *last; } DW_LineVMFileList; typedef struct DW_LineVMFileArray { U64 count; DW_LineFile *v; } DW_LineVMFileArray; typedef struct DW_LineVMHeader { Rng1U64 unit_range; DW_Version version; U8 address_size; // Duplicates size from the compilation unit but is needed to support stripped exe that just have .debug_line and .debug_line_str. U8 segment_selector_size; U64 header_length; U8 min_inst_len; U8 max_ops_for_inst; U8 default_is_stmt; S8 line_base; U8 line_range; U8 opcode_base; U64 num_opcode_lens; U8 *opcode_lens; DW_LineVMFileArray dir_table; DW_LineVMFileArray file_table; } DW_LineVMHeader; typedef struct DW_LineVMState { U64 address; // Address of a machine instruction. U32 op_index; // This is used by the VLIW instructions to indicate index of operation inside the instruction. // Line table doesn't contain full path to a file, instead // DWARF encodes path as two indices. First index will point into a directory // table, and second points into a file name table. U32 file_index; U32 line; U32 column; B32 is_stmt; // Indicates that "address" points to place suitable for a breakpoint. B32 basic_block; // Indicates that the "address" is inside a basic block. // Indicates that "address" points to place where function starts. // Usually prologue is the place where compiler emits instructions to // prepare stack for a function. B32 prologue_end; B32 epilogue_begin; // Indicates that "address" points to section where function exits and unwinds stack. U64 isa; // Instruction set that is used. U64 discriminator; // Arbitrary id that indicates to which block these instructions belong. B32 end_sequence; // Indicates that "address" points to the first instruction in the instruction block that follows. } DW_LineVMState; typedef struct DW_Line { U64 file_index; U32 line; U32 column; U64 address; } DW_Line; typedef struct DW_LineNode { struct DW_LineNode *next; DW_Line v; } DW_LineNode; typedef struct DW_LineSeqNode { struct DW_LineSeqNode *next; U64 count; DW_LineNode *first; DW_LineNode *last; } DW_LineSeqNode; typedef struct DW_LineTableParseResult { DW_LineVMHeader vm_header; U64 seq_count; DW_LineSeqNode *first_seq; DW_LineSeqNode *last_seq; } DW_LineTableParseResult; //////////////////////////////// // .debug_pubnames and .debug_pubtypes typedef struct DW_PubStringsBucket { struct DW_PubStringsBucket *next; String8 string; U64 info_off; U64 cu_info_off; } DW_PubStringsBucket; typedef struct DW_PubStringsTable { U64 size; DW_PubStringsBucket **buckets; } DW_PubStringsTable; typedef struct DW_Reference { DW_CompUnit *cu; U64 info_off; } DW_Reference; //////////////////////////////// //~ Expression typedef union DW_ExprOperand { U8 u8; U16 u16; U32 u32; U64 u64; S8 s8; S16 s16; S32 s32; S64 s64; String8 block; } DW_ExprOperand; typedef struct DW_ExprInst { DW_ExprOp opcode; DW_ExprOperand *operands; U64 size; struct DW_ExprInst *next; struct DW_ExprInst *prev; } DW_ExprInst; typedef struct DW_Expr { U64 count; DW_ExprInst *first; DW_ExprInst *last; } DW_Expr; //////////////////////////////// // .debug_frame typedef enum { DW_DescriptorEntryType_Null, DW_DescriptorEntryType_CIE, DW_DescriptorEntryType_FDE } DW_DescriptorEntryType; typedef struct DW_DescriptorEntry { DW_DescriptorEntryType type; DW_Format format; Rng1U64 entry_range; U64 cie_pointer_off; U64 cie_pointer; } DW_DescriptorEntry; typedef struct DW_CIE { String8 insts; String8 aug_string; String8 aug_data; U64 code_align_factor; S64 data_align_factor; U64 ret_addr_reg; U64 ext[4]; DW_Format format; U8 version; U8 address_size; U8 segment_selector_size; } DW_CIE; typedef struct DW_FDE { DW_Format format; U64 cie_pointer; Rng1U64 pc_range; String8 insts; } DW_FDE; typedef union DW_CFA_Operand { U64 u64; S64 s64; String8 block; } DW_CFA_Operand; typedef enum { DW_CFA_ParseErrorCode_NewInst, DW_CFA_ParseErrorCode_End, DW_CFA_ParseErrorCode_OutOfData } DW_CFA_ParseErrorCode; typedef struct DW_CFA_Inst { DW_CFA_Opcode opcode; DW_CFA_Operand operands[DW_CFA_OperandMax]; } DW_CFA_Inst; typedef struct DW_CFA_InstNode { DW_CFA_Inst v; struct DW_CFA_InstNode *next; } DW_CFA_InstNode; typedef struct DW_CFA_InstList { U64 count; DW_CFA_InstNode *first; DW_CFA_InstNode *last; } DW_CFA_InstList; #define DW_DECODE_PTR(name) U64 name(String8 data, void *ud, U64 *ptr_out) typedef DW_DECODE_PTR(DW_DecodePtr); // deserial helpers internal U64 str8_deserial_read_dwarf_packed_size(String8 string, U64 off, U64 *size_out); internal U64 str8_deserial_read_dwarf_uint (String8 string, U64 off, DW_Format format, U64 *uint_out); internal U64 str8_deserial_read_uleb128 (String8 string, U64 off, U64 *value_out); internal U64 str8_deserial_read_sleb128 (String8 string, U64 off, S64 *value_out); internal U64 str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 count, U64 **arr_out); internal U64 str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 count, S64 **arr_out); internal Rng1U64List dw_unit_ranges_from_data(Arena *arena, String8 data); // list units internal U64 dw_read_list_unit_header_addr (String8 unit_data, DW_ListUnit *lu_out); internal U64 dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out); internal U64 dw_read_list_unit_header_list (String8 unit_data, DW_ListUnit *lu_out); internal DW_ListUnitInput dw_list_unit_input_from_input(Arena *arena, DW_Input *input); internal U64 dw_offset_from_list_unit(DW_ListUnit *lu, U64 index); internal U64 dw_addr_from_list_unit (DW_ListUnit *lu, U64 index); // abbrev table internal U64 dw_read_abbrev_tag (String8 data, U64 offset, DW_Abbrev *out_abbrev); internal U64 dw_read_abbrev_attrib(String8 data, U64 offset, DW_Abbrev *out_abbrev); internal DW_AbbrevTable dw_make_abbrev_table(Arena *arena, String8 abbrev_data, U64 start_abbrev_off); internal U64 dw_abbrev_offset_from_abbrev_id(DW_AbbrevTable table, U64 abbrev_id); // form and tag internal U64 dw_read_form(String8 data, U64 off, DW_Version version, DW_Format unit_format, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_Form *form_out); internal U64 dw_read_tag (Arena *arena, String8 tag_data, U64 tag_off, U64 tag_base, DW_AbbrevTable abbrev_table, String8 abbrev_data, DW_Version version, DW_Format unit_format, U64 address_size, DW_Tag *tag_out); internal U64 dw_read_tag_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 info_off, DW_Tag *tag_out); // attrib interp internal U64 dw_interp_sec_offset(DW_FormKind form_kind, DW_Form form); internal String8 dw_interp_exprloc (DW_FormKind form_kind, DW_Form form); internal U128 dw_interp_const_u128(DW_FormKind form_kind, DW_Form form); internal U64 dw_interp_const_u64 (DW_FormKind form_kind, DW_Form form); internal U32 dw_interp_const_u32 (DW_FormKind form_kind, DW_Form form); internal S64 dw_interp_const_s64 (DW_FormKind form_kind, DW_Form form); internal S32 dw_interp_const_s32 (DW_FormKind form_kind, DW_Form form); internal B32 dw_interp_flag (DW_FormKind form_kind, DW_Form form); internal U64 dw_interp_address (U64 address_size, U64 base_addr, DW_ListUnit *addr_xlist, DW_FormKind form_kind, DW_Form form); internal String8 dw_interp_block (DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form); internal String8 dw_interp_string (DW_Input *input, DW_Format unit_format, DW_ListUnit *str_offsets, DW_FormKind form_kind, DW_Form form); internal String8 dw_interp_line_ptr (DW_Input *input, DW_FormKind form_kind, DW_Form form); internal DW_LineFile * dw_interp_file (DW_LineVMHeader *line_vm, DW_FormKind form_kind, DW_Form form); internal DW_Reference dw_interp_ref (DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form); internal DW_LocList dw_interp_loclist (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form); internal Rng1U64List dw_interp_rnglist (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form); internal String8 dw_exprloc_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal U128 dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal U64 dw_const_u64_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal U32 dw_const_u32_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal S64 dw_const_s64_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal S32 dw_const_s32_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal B32 dw_flag_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal U64 dw_address_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal String8 dw_block_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal String8 dw_string_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal String8 dw_line_ptr_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal DW_LineFile * dw_file_from_attrib (DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *attrib); internal DW_Reference dw_ref_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal DW_LocList dw_loclist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal Rng1U64List dw_rnglist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib); internal String8 dw_exprloc_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal U128 dw_const_u128_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal U64 dw_const_u64_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal U32 dw_const_u32_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal B32 dw_flag_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal U64 dw_address_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal String8 dw_block_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal String8 dw_string_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal String8 dw_line_ptr_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal String8 dw_line_ptr_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal DW_LineFile * dw_file_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind); internal DW_Reference dw_ref_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal DW_LocList dw_loclist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal Rng1U64List dw_rnglist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); // compile unit internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed); internal DW_TagTree dw_tag_tree_from_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu); internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree); internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off); // line info internal U64 dw_read_line_file(String8 line_data, U64 line_off, DW_Input *input, DW_Version unit_version, DW_Format unit_format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, DW_LineFile *line_file_out); internal U64 dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out); internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt); internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst); internal DW_LineSeqNode * dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl); internal DW_LineNode * dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_state, B32 start_of_sequence); internal String8 dw_path_from_file(Arena *arena, DW_LineVMHeader *vm, DW_LineFile *file); internal String8 dw_path_from_file_idx(Arena *arena, DW_LineVMHeader *vm, U64 file_idx); internal DW_LineTableParseResult dw_parsed_line_table_from_data(Arena *arena, String8 unit_data, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets); // helper for .debug_pubtypes and .debug_pubnames internal DW_PubStringsTable dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_SectionKind section_kind); // expression internal DW_Expr dw_expr_from_data(Arena *arena, DW_Format format, U64 addr_size, String8 data); // debug frame internal void dw_cfa_inst_list_push_node(DW_CFA_InstList *list, DW_CFA_InstNode *n); internal DW_CFA_InstNode * dw_cfa_inst_list_push(Arena *arena, DW_CFA_InstList *list, DW_CFA_Inst v); internal U64 dw_read_debug_frame_ptr(String8 data, DW_CIE *cie, U64 *ptr_out); internal U64 dw_parse_descriptor_entry_header(String8 data, U64 off, DW_DescriptorEntry *desc_out); internal B32 dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out); internal B32 dw_parse_fde(String8 data, DW_Format format, DW_CIE *cie, DW_FDE *fde_out); internal B32 dw_parse_cfi(String8 data, U64 fde_offset, Arch arch, DW_CIE *cie_out, DW_FDE *fde_out); internal DW_CFA_ParseErrorCode dw_parse_cfa_inst(String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud, U64 *bytes_read_out, DW_CFA_Inst *inst_out); internal DW_CFA_InstList dw_parse_cfa_inst_list(Arena *arena, String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud); #endif // DWARF_PARSE_H ================================================ FILE: src/dwarf/dwarf_unwind.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal DW_CFI_Row * dw_make_cfi_row(Arena *arena, U64 reg_count) { DW_CFI_Row *row = push_array(arena, DW_CFI_Row, 1); row->regs = push_array(arena, DW_CFI_Register, reg_count); for EachIndex(reg_idx, reg_count) { row->regs[reg_idx].rule = DW_CFI_RegisterRule_SameValue; } return row; } internal void dw_memcpy_cfi_row(DW_CFI_Row *dst, DW_CFI_Row *src, U64 reg_count) { dst->cfa = src->cfa; MemoryCopyTyped(dst->regs, src->regs, reg_count); } internal DW_CFI_Row * dw_copy_cfi_row(Arena *arena, DW_CFI_Row *row, U64 reg_count) { DW_CFI_Row *new_row = dw_make_cfi_row(arena, reg_count); dw_memcpy_cfi_row(new_row, row, reg_count); return new_row; } internal DW_CFI_Unwind * dw_cfi_unwind_init(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud) { Temp scratch = scratch_begin(&arena, 1); DW_CFI_Unwind *uw = push_array(arena, DW_CFI_Unwind, 1); uw->insts = dw_parse_cfa_inst_list(arena, fde->insts, cie->code_align_factor, cie->data_align_factor, decode_ptr_func, decode_ptr_ud); uw->cie = cie; uw->fde = fde; uw->pc = fde->pc_range.min; uw->arch = arch; uw->reg_count = dw_reg_count_from_arch(arch); // setup initial register rules DW_CFA_InstList initial_insts = dw_parse_cfa_inst_list(scratch.arena, cie->insts, cie->code_align_factor, cie->data_align_factor, decode_ptr_func, decode_ptr_ud); uw->row = dw_make_cfi_row(arena, uw->reg_count); uw->curr_inst = initial_insts.first; if (!dw_cfi_next_row(arena, uw)) { AssertAlways(0 && "unable to interpret initial row instructions"); } // make first row from initial rules uw->initial_row = uw->row; uw->row = dw_copy_cfi_row(arena, uw->initial_row, uw->reg_count); uw->curr_inst = uw->insts.first; scratch_end(scratch); return uw; } internal B32 dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw) { B32 is_row_valid = 0; DW_CFA_InstNode *row_inst = uw->curr_inst; // skip leading nops while (uw->curr_inst) { if (uw->curr_inst->v.opcode != DW_CFA_Nop) { break; } uw->curr_inst = uw->curr_inst->next; } while (uw->curr_inst) { DW_CFA_Inst *inst = &uw->curr_inst->v; // validate register operands DW_CFA_OperandType *operand_types = dw_operand_types_from_cfa_op(inst->opcode); U64 operand_count = dw_operand_count_from_cfa_opcode(inst->opcode); for EachIndex(operand_idx, operand_count) { if (operand_types[operand_idx] == DW_CFA_OperandType_Register) { if (inst->operands[operand_idx].u64 >= uw->reg_count) { goto exit; } } } switch (inst->opcode) { // Row Creation Instructions case DW_CFA_SetLoc: { uw->pc = inst->operands[0].u64; } break; case DW_CFA_AdvanceLoc: case DW_CFA_AdvanceLoc1: case DW_CFA_AdvanceLoc2: case DW_CFA_AdvanceLoc4: { uw->pc += inst->operands[0].u64; } break; // CFA Definition Instructions case DW_CFA_DefCfa: case DW_CFA_DefCfaSf: { U64 reg = inst->operands[0].u64; S64 off = inst->operands[1].s64; uw->row->cfa.rule = DW_CFA_Rule_RegOff; uw->row->cfa.reg = reg; uw->row->cfa.off = off; } break; case DW_CFA_DefCfaRegister: { // TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; } U64 reg = inst->operands[0].u64; uw->row->cfa.reg = reg; } break; case DW_CFA_DefCfaOffset: case DW_CFA_DefCfaOffsetSf: { // TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; } uw->row->cfa.off = inst->operands[0].s64; } break; case DW_CFA_DefCfaExpr: { uw->row->cfa.rule = DW_CFA_Rule_Expression; uw->row->cfa.expr = inst->operands[0].block; } break; // Register Rule Instructions case DW_CFA_Undefined: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_Undefined; } break; case DW_CFA_SameValue: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_SameValue; } break; case DW_CFA_Offset: case DW_CFA_OffsetExt: case DW_CFA_OffsetExtSf: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_Offset; uw->row->regs[reg].n = inst->operands[1].s64; } break; case DW_CFA_ValOffset: case DW_CFA_ValOffsetSf: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValOffset; uw->row->regs[reg].n = inst->operands[1].s64; } break; case DW_CFA_Register: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_Register; uw->row->regs[reg].n = inst->operands[1].s64; } break; case DW_CFA_Expr: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_Expression; uw->row->regs[reg].expr = inst->operands[1].block; } break; case DW_CFA_ValExpr: { U64 reg = inst->operands[0].u64; uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValExpression; uw->row->regs[reg].expr = inst->operands[1].block; } break; case DW_CFA_Restore: case DW_CFA_RestoreExt: { U64 reg = inst->operands[0].u64; uw->row->regs[reg] = uw->initial_row->regs[reg]; } break; // Row State Instructions case DW_CFA_RememberState: { DW_CFI_Row *new_row = dw_copy_cfi_row(arena, uw->row, uw->reg_count); SLLStackPush(uw->row, new_row); } break; case DW_CFA_RestoreState: { if (uw->row == 0) { goto exit; } // TODO: report error: unbalanced number of pushes and pops DW_CFI_Row *free_row = uw->row; SLLStackPop(uw->row); SLLStackPush(uw->free_rows, free_row); } break; case DW_CFA_Nop: {} break; default: { NotImplemented; } break; // TODO: report error: unknown CFA opcode } uw->curr_inst = uw->curr_inst->next; if (uw->curr_inst) { if (dw_is_new_row_cfa_opcode(uw->curr_inst->v.opcode)) { break; } } } is_row_valid = row_inst != 0; exit:; return is_row_valid; } internal DW_CFI_Row * dw_cfi_row_from_pc(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ctx, U64 pc) { Temp scratch = scratch_begin(&arena, 1); B32 is_row_found = 0; U64 reg_count = dw_reg_count_from_arch(arch); DW_CFI_Unwind *uw = dw_cfi_unwind_init(scratch.arena, arch, cie, fde, decode_ptr_func, decode_ptr_ctx); DW_CFI_Row *row = dw_copy_cfi_row(scratch.arena, uw->row, uw->reg_count); U64 prev_pc = uw->pc; while (dw_cfi_next_row(scratch.arena, uw)) { if (prev_pc <= pc && pc < uw->pc) { is_row_found = 1; break; } dw_memcpy_cfi_row(row, uw->row, uw->reg_count); prev_pc = uw->pc; } // handle last row if (!is_row_found) { if (contains_1u64(fde->pc_range, pc)) { row = uw->row; is_row_found = 1; } } // copy out final row DW_CFI_Row *result = 0; if (is_row_found) { result = dw_copy_cfi_row(arena, row, reg_count); } scratch_end(scratch); return result; } internal DW_UnwindStatus dw_cfi_apply_register_rules(Arch arch, DW_CIE *cie, DW_CFI_Row *row, DW_MemRead *mem_read_func, void *mem_read_ud, DW_RegRead *reg_read_func, void *reg_read_ud, DW_RegWrite *reg_write_func, void *reg_write_ud) { Temp scratch = scratch_begin(0,0); DW_UnwindStatus unwind_status = DW_UnwindStatus_Ok; // establish CFA U64 cfa = 0; switch (row->cfa.rule) { case DW_CFA_Rule_Null: break; case DW_CFA_Rule_RegOff: { // TODO: report error (invalid register read) U64 cfa_reg_value = 0; U64 reg_size = dw_reg_size_from_code(arch, row->cfa.reg); AssertAlways(reg_size <= sizeof(cfa_reg_value)); unwind_status = reg_read_func(row->cfa.reg, &cfa_reg_value, reg_size, reg_read_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } cfa = cfa_reg_value + row->cfa.off; } break; case DW_CFA_Rule_Expression: { // TODO: evaluate expression } break; } U64 max_reg_size = dw_reg_max_size_from_arch(arch); void *reg_buffer = push_array(scratch.arena, U8, max_reg_size); U64 reg_count = dw_reg_count_from_arch(arch); for EachIndex(reg_idx, reg_count) { DW_CFI_Register *reg = &row->regs[reg_idx]; switch (reg->rule) { case DW_CFI_RegisterRule_Undefined: {} break; case DW_CFI_RegisterRule_SameValue: {} break; case DW_CFI_RegisterRule_Offset: { // read register value from memory U64 addr = cfa + reg->n; U64 reg_size = dw_reg_size_from_code(arch, reg_idx); unwind_status = mem_read_func(addr, reg_size, reg_buffer, mem_read_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } // write register value to the thread context unwind_status = reg_write_func(reg_idx, reg_buffer, reg_size, reg_write_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } } break; case DW_CFI_RegisterRule_ValOffset: { // compute register value U64 reg_value = cfa + reg->n; // write register value to the thread context U64 reg_size = dw_reg_size_from_code(arch, reg_idx); unwind_status = reg_write_func(reg_idx, ®_value, reg_size, reg_write_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } } break; case DW_CFI_RegisterRule_Register: { // read register value from another register U64 reg_size = dw_reg_size_from_code(arch, reg_idx); unwind_status = reg_read_func(reg->n, reg_buffer, reg_size, reg_read_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } // write register value to the thread context unwind_status = reg_write_func(reg_idx, reg_buffer, reg_size, reg_write_ud); if (unwind_status != DW_UnwindStatus_Ok) { goto exit; } } break; case DW_CFI_RegisterRule_Expression: { // TODO: evaluate expression NotImplemented; } break; case DW_CFI_RegisterRule_ValExpression: { // TODO: evaluate expression NotImplemented; } break; case DW_CFI_RegisterRule_Architectural: { NotImplemented; } break; default: { InvalidPath; } break; } } // update stack pointer U64 sp = dw_sp_from_arch(arch); reg_write_func(sp, &cfa, sizeof(cfa), reg_write_ud); exit:; scratch_end(scratch); return unwind_status; } ================================================ FILE: src/dwarf/dwarf_unwind.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_UNWIND_H #define DWARF_UNWIND_H typedef enum DW_CFI_RegisterRule { DW_CFI_RegisterRule_Undefined, DW_CFI_RegisterRule_SameValue, DW_CFI_RegisterRule_Offset, DW_CFI_RegisterRule_ValOffset, DW_CFI_RegisterRule_Register, DW_CFI_RegisterRule_Expression, DW_CFI_RegisterRule_ValExpression, DW_CFI_RegisterRule_Architectural } DW_CFI_RegisterRule; typedef enum DW_CFA_Rule { DW_CFA_Rule_Null, DW_CFA_Rule_RegOff, DW_CFA_Rule_Expression } DW_CFA_Rule; typedef struct DW_CFA { DW_CFA_Rule rule; union { struct { DW_Reg reg; S64 off; }; String8 expr; }; } DW_CFA; typedef struct DW_CFI_Register { DW_CFI_RegisterRule rule; union { S64 n; String8 expr; }; } DW_CFI_Register; typedef struct DW_CFI_Row { DW_CFA cfa; DW_CFI_Register *regs; struct DW_CFI_Row *next; } DW_CFI_Row; typedef struct DW_CFI_Unwind { DW_CFA_InstList insts; DW_CIE *cie; DW_FDE *fde; DW_CFI_Row *initial_row; DW_CFI_Row *row; DW_CFA_InstNode *curr_inst; DW_CFI_Row *free_rows; U64 pc; Arch arch; U64 reg_count; } DW_CFI_Unwind; typedef enum { DW_UnwindStatus_Ok, DW_UnwindStatus_Fail, DW_UnwindStatus_Maybe } DW_UnwindStatus; #define DW_REG_READ(name) DW_UnwindStatus name(DW_Reg reg_id, void *buffer, U64 buffer_max, void *ud) typedef DW_REG_READ(DW_RegRead); #define DW_REG_WRITE(name) DW_UnwindStatus name(DW_Reg reg_id, void *value, U64 value_size, void *ud) typedef DW_REG_WRITE(DW_RegWrite); #define DW_MEM_READ(name) DW_UnwindStatus name(U64 addr, U64 size, void *buffer, void *ud) typedef DW_MEM_READ(DW_MemRead); //////////////////////////////// internal DW_CFI_Row * dw_make_cfi_row(Arena *arena, U64 reg_count); internal DW_CFI_Row * dw_copy_cfi_row(Arena *arena, DW_CFI_Row *row, U64 reg_count); internal DW_CFI_Unwind * dw_cfi_unwind_init(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud); internal B32 dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw); internal DW_CFI_Row * dw_cfi_row_from_pc(Arena *arena, Arch arch, struct DW_CIE *cie, struct DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ctx, U64 pc); internal DW_UnwindStatus dw_cfi_apply_register_rules(Arch arch, DW_CIE *cie, DW_CFI_Row *row, DW_MemRead *mem_read_func, void *mem_read_ud, DW_RegRead *reg_read_func, void *reg_read_ud, DW_RegWrite *reg_write_func, void *reg_write_ud); #endif // DWARF_UNWIND_H ================================================ FILE: src/dwarf/eh_dump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8List eh_dump_list_from_data(Arena *arena, Arch arch, U64 eh_frame_hdr_vaddr, U64 eh_frame_vaddr, String8 eh_frame_hdr, String8 eh_frame, EH_DumpSubsetFlags subset_flags) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; #define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__) EH_PtrCtx ptr_ctx = { .data_vaddr = eh_frame_hdr_vaddr }; EH_FrameHdr hdr = eh_parse_frame_hdr(eh_frame_hdr, byte_size_from_arch(arch), &ptr_ctx); DW_Ext ext = DW_Ext_All; if (subset_flags & EH_DumpSubsetFlag_EhFrameHdr) { dumpf("eh_frame_hdr:\n"); dumpf("{\n"); dumpf(" version: %u\n", hdr.version); dumpf(" eh_frame_ptr_enc: %S\n", eh_string_from_ptr_enc(scratch.arena, hdr.eh_frame_ptr_enc)); dumpf(" table_enc: %S\n", eh_string_from_ptr_enc(scratch.arena, hdr.table_enc)); dumpf(" fde_count: %llu\n", hdr.fde_count); if (hdr.eh_frame_ptr_enc != EH_PtrEnc_Omit) { dumpf(" eh_frame_ptr: 0x%I64x\n", hdr.eh_frame_ptr); } dumpf(" Entries:\n"); dumpf(" {\n"); for (U64 cursor = 0; cursor < hdr.table.size; ) { U64 entry_off = cursor; U64 pc = 0; U64 pc_size = eh_parse_ptr(hdr.table, cursor, cursor, &ptr_ctx, hdr.table_enc, &pc); if (pc_size == 0) { break; } cursor += pc_size; U64 fde_addr = 0; U64 fde_addr_size = eh_parse_ptr(hdr.table, cursor, cursor, &ptr_ctx, hdr.table_enc, &fde_addr); if (fde_addr_size == 0) { break; } cursor += fde_addr_size; U64 fde_offset = fde_addr - eh_frame_vaddr; dumpf(" { off=0x%04I64x, pc=0x%I64x, fde=0x%I64x }\n", entry_off, pc, fde_offset); } dumpf(" }\n"); dumpf("}\n"); } if (subset_flags & EH_DumpSubsetFlag_EhFrame) { dumpf(".eh_frame:\n"); dumpf("{\n"); for (U64 cursor = 0; cursor < eh_frame.size; ) { DW_DescriptorEntry desc = {0}; U64 desc_size = eh_parse_descriptor_entry_header(eh_frame, cursor, &desc); if (desc_size == 0) { break; } switch (desc.type) { case DW_DescriptorEntryType_Null: break; case DW_DescriptorEntryType_CIE: { String8 cie_data = str8_substr(eh_frame, desc.entry_range); DW_CIE cie = {0}; if (eh_parse_cie(cie_data, desc.format, arch, eh_frame_vaddr + cursor, &ptr_ctx, &cie)) { String8List init_insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, DW_Version_5, ext, cie.format, 0, &cie, eh_decode_ptr, &ptr_ctx, cie.insts); dumpf(" CIE: // entry range: %r\n", desc.entry_range); dumpf(" {\n"); dumpf(" Format: %S\n", dw_string_from_format(desc.format)); dumpf(" Version: %u\n", cie.version); dumpf(" Aug string: \"%S\"\n", cie.aug_string); dumpf(" Code align: %I64u\n", cie.code_align_factor); dumpf(" Data align: %I64d\n", cie.data_align_factor); dumpf(" Return addr reg: %u\n", cie.ret_addr_reg); if (cie.version > DW_Version_3) { dumpf(" Address size: %u\n", cie.address_size); dumpf(" Segment selector size: %u\n", cie.segment_selector_size); } dumpf(" Initial Insturction:\n"); dumpf(" {\n"); for EachNode(n, String8Node, init_insts_str_list.first) { dumpf(" %S\n", n->string); } dumpf(" }\n"); dumpf(" }\n"); } else { dumpf("ERROR: unable to parse CIE @ %I64x\n", desc.entry_range.min); } } break; case DW_DescriptorEntryType_FDE: { U64 cie_offset = desc.cie_pointer_off - desc.cie_pointer; DW_CIE cie = {0}; { DW_DescriptorEntry cie_desc = {0}; eh_parse_descriptor_entry_header(eh_frame, cie_offset, &cie_desc); if (cie_desc.type == DW_DescriptorEntryType_CIE) { String8 cie_data = str8_substr(eh_frame, cie_desc.entry_range); eh_parse_cie(cie_data, cie_desc.format, arch, eh_frame_vaddr + cie_offset, &ptr_ctx, &cie); } } String8 fde_raw = str8_substr(eh_frame, desc.entry_range); DW_FDE fde = {0}; if (eh_parse_fde(fde_raw, desc.format, eh_frame_vaddr + cursor, &cie, &ptr_ctx, &fde)) { String8List insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, hdr.version, ext, fde.format, 0, &cie, eh_decode_ptr, &ptr_ctx, fde.insts); dumpf(" FDE: // entry range: %r\n", desc.entry_range); dumpf(" {\n"); { dumpf(" Format: %S\n", dw_string_from_format(fde.format)); dumpf(" CIE: 0x%I64x\n", cie_offset); dumpf(" PC range: %r\n", fde.pc_range); dumpf(" Instructions:\n"); dumpf(" {\n"); for EachNode(n, String8Node, insts_str_list.first) { dumpf(" %S\n", n->string); } dumpf(" }\n"); dumpf(" Unwind:\n"); dumpf(" {\n"); DW_CFI_Unwind *cfi_unwind = dw_cfi_unwind_init(scratch.arena, arch, &cie, &fde, eh_decode_ptr, &ptr_ctx); do { String8 cfa_str = dw_string_from_cfa(scratch.arena, arch, cie.address_size, hdr.version, ext, fde.format, cfi_unwind->row->cfa); String8 cfi_row_str = dw_string_from_cfi_row(scratch.arena, arch, cie.address_size, hdr.version, ext, fde.format, cfi_unwind->row); dumpf(" { PC: 0x%I64x, CFA: %-7S, Rules: { %S }\n", cfi_unwind->pc, cfa_str, cfi_row_str); } while (dw_cfi_next_row(scratch.arena, cfi_unwind)); dumpf(" }\n"); } } else { dumpf("ERROR: unable to parse FDE @ %I64x\n", desc.entry_range.min); } dumpf(" }\n"); } break; } cursor += desc_size; } dumpf("}\n"); } #undef dumpf scratch_end(scratch); return strings; } ================================================ FILE: src/dwarf/eh_dump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EH_FRAME_DUMP_H #define EH_FRAME_DUMP_H //////////////////////////////// //~ Dump Subset Types #define EH_DumpSubset_XList \ X(EhFrameHdr, eh_frame_hdr, ".eh_frame_hdr") \ X(EhFrame, eh_frame, ".eh_frame") typedef enum EH_DumpSubset { #define X(name, name_lower, title) EH_DumpSubset_##name, EH_DumpSubset_XList #undef X } EH_DumpSubset; typedef U32 EH_DumpSubsetFlags; enum { #define X(name, name_lower, title) EH_DumpSubsetFlag_##name = (1<ptr_align); encoding = EH_PtrEnc_Ptr; } // decode pointer value U64 decode_size = 0; U64 raw_ptr_size = 0; U64 raw_ptr = 0; switch (encoding & EH_PtrEnc_TypeMask) { default: { InvalidPath; } break; case EH_PtrEnc_Ptr : { raw_ptr_size = 8; } goto ufixed; case EH_PtrEnc_UData2: { raw_ptr_size = 2; } goto ufixed; case EH_PtrEnc_UData4: { raw_ptr_size = 4; } goto ufixed; case EH_PtrEnc_UData8: { raw_ptr_size = 8; } goto ufixed; ufixed: { decode_size += str8_deserial_read(frame_base, ptr_off, &raw_ptr, raw_ptr_size, raw_ptr_size); } break; // TODO: Signed is actually just a flag that indicates this int is negavite. // There shouldn't be a read for Signed. // For instance, (EH_PtrEnc_UData2 | EH_PtrEnc_Signed) == EH_PtrEnc_SData etc. case EH_PtrEnc_Signed: { raw_ptr_size = 8; } goto sfixed; case EH_PtrEnc_SData2: { raw_ptr_size = 2; } goto sfixed; case EH_PtrEnc_SData4: { raw_ptr_size = 4; } goto sfixed; case EH_PtrEnc_SData8: { raw_ptr_size = 8; } goto sfixed; sfixed: { decode_size += str8_deserial_read(frame_base, ptr_off, &raw_ptr, raw_ptr_size, raw_ptr_size); raw_ptr = extend_sign64(raw_ptr, raw_ptr_size); } break; case EH_PtrEnc_ULEB128: { decode_size += str8_deserial_read_uleb128(frame_base, ptr_off, &raw_ptr); } break; case EH_PtrEnc_SLEB128: { decode_size += str8_deserial_read_sleb128(frame_base, ptr_off, (S64*)&raw_ptr); } break; } // apply relative bases if (decode_size > 0) { U64 ptr = raw_ptr; switch (encoding & EH_PtrEnc_ModifierMask) { case 0: break; case EH_PtrEnc_PcRel: { ptr = pc + raw_ptr; } break; case EH_PtrEnc_TextRel: { ptr = ptr_ctx->text_vaddr + raw_ptr; } break; case EH_PtrEnc_DataRel: { ptr = ptr_ctx->data_vaddr + raw_ptr; } break; case EH_PtrEnc_FuncRel: { Assert(!"TODO: need a sample to verify implementation"); ptr = ptr_ctx->func_vaddr + raw_ptr; } break; default: { InvalidPath; } break; } if (ptr_out) { *ptr_out = ptr; } } return decode_size; } internal EH_FrameHdr eh_parse_frame_hdr(String8 data, U64 address_size, EH_PtrCtx *ptr_ctx) { EH_FrameHdr header = {0}; U64 cursor = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &header.version); if (version_size == 0) { goto exit; } cursor += version_size; if (header.version == 1) { U64 eh_frame_ptr_enc_size = str8_deserial_read_struct(data, cursor, &header.eh_frame_ptr_enc); if (eh_frame_ptr_enc_size == 0) { goto exit; } cursor += eh_frame_ptr_enc_size; U64 fde_count_enc_size = str8_deserial_read_struct(data, cursor, &header.fde_count_enc); if (fde_count_enc_size == 0) { goto exit; } cursor += fde_count_enc_size; U64 table_enc_size = str8_deserial_read_struct(data, cursor, &header.table_enc); if (table_enc_size == 0) { goto exit; } cursor += table_enc_size; cursor += eh_parse_ptr(data, cursor, cursor, ptr_ctx, header.eh_frame_ptr_enc, &header.eh_frame_ptr); cursor += eh_parse_ptr(data, cursor, cursor, ptr_ctx, header.fde_count_enc, &header.fde_count); switch (header.table_enc & EH_PtrEnc_TypeMask) { case EH_PtrEnc_Ptr: { header.field_byte_size = address_size; } break; case EH_PtrEnc_ULEB128: { InvalidPath; } break; // TODO: when loading module convert these to UData8 case EH_PtrEnc_UData2: { header.field_byte_size = 2; } break; case EH_PtrEnc_UData4: { header.field_byte_size = 4; } break; case EH_PtrEnc_UData8: { header.field_byte_size = 8; } break; case EH_PtrEnc_Signed: { header.field_byte_size = address_size; } break; case EH_PtrEnc_SLEB128: { InvalidPath; } break; // TODO: when loading module convert these to UData8 case EH_PtrEnc_SData2: { header.field_byte_size = 2; } break; case EH_PtrEnc_SData4: { header.field_byte_size = 4; } break; case EH_PtrEnc_SData8: { header.field_byte_size = 8; } break; default: { InvalidPath; } break; } header.entry_byte_size = header.field_byte_size * 2; header.table = str8_skip(data, cursor); AssertAlways(header.table.size == header.entry_byte_size * header.fde_count); } else { Assert(0 && "unknown version"); } exit:; return header; } internal U64 eh_parse_aug_data(String8 aug_string, String8 aug_data, U64 pc, EH_PtrCtx *ptr_ctx, EH_Augmentation *aug_out) { // TODO: // Handle "eh" param, it indicates presence of EH Data field. // On 32bit arch it is a 4-byte and on 64-bit 8-byte value. // Reference: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html // Reference doc doesn't clarify structure for EH Data though U64 cursor = 0; U64 aug_data_size = 0; EH_AugFlags aug_flags = 0; EH_PtrEnc lsda_encoding = EH_PtrEnc_Omit; EH_PtrEnc addr_encoding = EH_PtrEnc_UData8; EH_PtrEnc handler_encoding = EH_PtrEnc_Omit; U64 handler_ip = 0; if (str8_match(str8_prefix(aug_string, 1), str8_lit("z"), 0)) { cursor = str8_deserial_read_uleb128(aug_data, cursor, &aug_data_size); for (U8 *ptr = aug_string.str+1; ptr < (aug_string.str+aug_string.size); ptr += 1) { switch (*ptr) { case 'L': { cursor += str8_deserial_read_struct(aug_data, cursor, &lsda_encoding); aug_flags |= EH_AugFlag_HasLSDA; } break; case 'P': { cursor += str8_deserial_read_struct(aug_data, cursor, &handler_encoding); cursor += eh_parse_ptr(aug_data, cursor, pc + cursor, ptr_ctx, handler_encoding, &handler_ip); aug_flags |= EH_AugFlag_HasHandler; } break; case 'R': { cursor += str8_deserial_read_struct(aug_data, cursor, &addr_encoding); aug_flags |= EH_AugFlag_HasAddrEnc; } break; case 'S': { aug_flags |= EH_AugFlag_SignalFrame; } break; default: { Assert(!"failed to parse augmentation string"); goto exit; } break; } } } if (aug_out) { aug_out->handler_ip = handler_ip; aug_out->handler_encoding = handler_encoding; aug_out->lsda_encoding = handler_encoding; aug_out->addr_encoding = addr_encoding; aug_out->flags = aug_flags; aug_out->size = aug_data_size; } exit:; U64 parse_size = cursor; return parse_size; } internal U64 eh_parse_descriptor_entry_header(String8 data, U64 off, DW_DescriptorEntry *desc_out) { U32 first_four_bytes = 0; str8_deserial_read_struct(data, off, &first_four_bytes); DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit; U64 length = 0; U64 length_size = str8_deserial_read_dwarf_packed_size(data, off, &length); if (length_size == 0) { goto exit; } Rng1U64 entry_range = rng_1u64(off, off + length_size + length); String8 entry_data = str8_substr(data, entry_range); U64 id = 0; U64 id_size = str8_deserial_read_dwarf_uint(entry_data, length_size, format, &id); if (id_size == 0) { goto exit; } desc_out->format = format; desc_out->type = (id == 0) ? DW_DescriptorEntryType_CIE : DW_DescriptorEntryType_FDE; desc_out->entry_range = entry_range; desc_out->cie_pointer = id; desc_out->cie_pointer_off = off + length_size; exit:; return length + length_size; } internal B32 eh_parse_cie(String8 data, DW_Format format, Arch arch, U64 pc, EH_PtrCtx *ptr_ctx, DW_CIE *cie_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 4 : 12; U64 cie_id = 0; U64 cie_id_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_id); if (cie_id_size == 0) { goto exit; } cursor += cie_id_size; U8 version = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &version); if (version_size == 0) { goto exit; } cursor += version_size; String8 aug_string = {0}; String8 aug_data = {0}; EH_Augmentation aug = {0}; U64 code_align_factor = 0; S64 data_align_factor = 0; U64 ret_addr_reg = max_U64; if (version == 1) { U64 aug_string_size = str8_deserial_read_cstr(data, cursor, &aug_string); if (aug_string_size == 0) { goto exit; } cursor += aug_string_size; U64 eh_data = 0; if (str8_match(aug_string, str8_lit("eh"), 0)) { U64 arch_byte_size = byte_size_from_arch(arch); cursor += str8_deserial_read(data, cursor, &eh_data, arch_byte_size, arch_byte_size); } U64 code_align_factor_size = str8_deserial_read_uleb128(data, cursor, &code_align_factor); if (code_align_factor_size == 0) { goto exit; } cursor += code_align_factor_size; U64 data_align_factor_size = str8_deserial_read_sleb128(data, cursor, &data_align_factor); if (data_align_factor_size == 0) { goto exit; } cursor += data_align_factor_size; ret_addr_reg = 0; U64 ret_addr_reg_size = str8_deserial_read(data, cursor, &ret_addr_reg, sizeof(U8), sizeof(U8)); if (ret_addr_reg_size == 0) { goto exit; } cursor += ret_addr_reg_size; U64 aug_data_size = eh_parse_aug_data(aug_string, str8_skip(data, cursor), pc + cursor, ptr_ctx, &aug); aug_data = str8_substr(data, r1u64(cursor, cursor + aug.size)); cursor += aug_data_size; } else { Assert(0 && "unexpected version"); } cie_out->insts = str8_skip(data, cursor); cie_out->aug_string = aug_string; cie_out->aug_data = aug_data; cie_out->code_align_factor = code_align_factor; cie_out->data_align_factor = data_align_factor; cie_out->ret_addr_reg = ret_addr_reg; cie_out->format = format; cie_out->version = version; cie_out->address_size = byte_size_from_arch(arch); cie_out->segment_selector_size = 0; cie_out->ext[EH_CIE_Ext_LSDAEnc] = EH_PtrEnc_Omit; cie_out->ext[EH_CIE_Ext_AddrEnc] = EH_PtrEnc_Omit; cie_out->ext[EH_CIE_Ext_HandlerEnc] = EH_PtrEnc_Omit; if (aug.flags & EH_AugFlag_HasLSDA) { cie_out->ext[EH_CIE_Ext_LSDAEnc] = aug.lsda_encoding; } if (aug.flags & EH_AugFlag_HasAddrEnc) { cie_out->ext[EH_CIE_Ext_AddrEnc] = aug.addr_encoding; } if (aug.flags & EH_AugFlag_HasHandler) { cie_out->ext[EH_CIE_Ext_HandlerEnc] = aug.handler_encoding; cie_out->ext[EH_CIE_Ext_HandlerIp ] = aug.handler_ip; } is_parsed = 1; exit:; return is_parsed; } internal B32 eh_parse_fde(String8 data, DW_Format format, U64 pc, DW_CIE *cie, EH_PtrCtx *ptr_ctx, DW_FDE *fde_out) { B32 is_parsed = 0; U64 cursor = format == DW_Format_32Bit ? 8 : 20; U64 pc_begin = 0; U64 pc_delta = 0; EH_PtrEnc addr_enc = cie->ext[EH_CIE_Ext_AddrEnc]; if (addr_enc != EH_PtrEnc_Omit) { U64 pc_begin_size = eh_parse_ptr(data, cursor, pc + cursor, ptr_ctx, addr_enc, &pc_begin); if (pc_begin_size == 0) { goto exit; } cursor += pc_begin_size; U64 pc_delta_size = eh_parse_ptr(data, cursor, pc + cursor, ptr_ctx, addr_enc & EH_PtrEnc_TypeMask, &pc_delta); if (pc_delta_size == 0) { goto exit; } cursor += pc_delta_size; } if (cursor + cie->aug_data.size > data.size) { goto exit; } cursor += cie->aug_data.size; fde_out->format = format; fde_out->pc_range = rng_1u64(pc_begin, pc_begin + pc_delta); fde_out->insts = str8_skip(data, cursor); is_parsed = 1; exit:; return is_parsed; } internal U64 eh_find_nearest_fde(EH_FrameHdr header, EH_PtrCtx *ptr_ctx, U64 pc) { U64 fde_addr = max_U64; U64 fde_idx = max_U64; if (header.version == 1) { if (header.fde_count > 0) { U64 first = 0; U64 first_size = eh_parse_ptr(header.table, 0, ptr_ctx->pc_vaddr, ptr_ctx, header.table_enc, &first); AssertAlways(first_size); if (first == pc) { fde_idx = 0; goto exit; } if (first > pc) { goto exit; } U64 last_off = header.table.size - header.entry_byte_size; U64 last = 0; U64 last_size = eh_parse_ptr(header.table, last_off, ptr_ctx->pc_vaddr + last_off, ptr_ctx, header.table_enc, &last); AssertAlways(last_size); if (last <= pc) { fde_idx = header.fde_count - 1; goto exit; } U64 l = 0; U64 r = header.fde_count - 1; while (l <= r) { U64 m = l + (r - l) / 2; U64 m_pc_off = m * header.entry_byte_size; U64 m_pc = 0; U64 m_pc_size = eh_parse_ptr(header.table, m_pc_off, ptr_ctx->pc_vaddr + m_pc_off, ptr_ctx, header.table_enc, &m_pc); Assert(m_pc_size); if (m_pc > pc) { r = m - 1; } else if (m_pc < pc) { l = m + 1; } else { fde_idx = m; goto exit; } } fde_idx = l > 0 ? l-1 : 0; } } exit:; if (fde_idx < header.fde_count) { U64 fde_addr_off = (fde_idx * header.entry_byte_size) + header.field_byte_size; U64 fde_addr_size = eh_parse_ptr(header.table, fde_addr_off, ptr_ctx->pc_vaddr + fde_addr_off, ptr_ctx, header.table_enc, &fde_addr); Assert(fde_addr_size); } return fde_addr; } internal int eh_frame_hdr_entry_sort(void *raw_a, void *raw_b) { return ((EH_FrameHdrEntry *)raw_a)->addr < ((EH_FrameHdrEntry *)raw_b)->addr; } internal String8 eh_frame_hdr_from_call_frame_info(Arena *arena, U64 fde_count, U64 *fde_offsets, DW_FDE *fde) { Temp scratch = scratch_begin(&arena, 1); // make .eh_frame_hdr String8List srl = {0}; str8_serial_begin(scratch.arena, &srl); str8_serial_push_u8(scratch.arena, &srl, 1); // version str8_serial_push_u8(scratch.arena, &srl, EH_PtrEnc_Omit); // omit eh_frame_ptr field str8_serial_push_u8(scratch.arena, &srl, EH_PtrEnc_UData8); // fde_count encoding str8_serial_push_u8(scratch.arena, &srl, EH_PtrEnc_UData8); // table encoding str8_serial_push_u64(scratch.arena, &srl, fde_count); // fde_count String8 header = str8_serial_end(scratch.arena, &srl); // alloc buffer for output U64 buffer_size = header.size + sizeof(EH_FrameHdrEntry) * fde_count; U8 *buffer = push_array(arena, U8, buffer_size); // copy header MemoryCopyStr8(buffer, header); // write the table EH_FrameHdrEntry *table = (EH_FrameHdrEntry *)(buffer + header.size); for EachIndex(fde_idx, fde_count) { table[fde_idx].addr = fde[fde_idx].pc_range.min; table[fde_idx].fde_offset = fde_offsets[fde_idx]; } radsort(table, fde_count, eh_frame_hdr_entry_sort); String8 eh_frame_hdr = str8(buffer, buffer_size); scratch_end(scratch); return eh_frame_hdr; } internal DW_DECODE_PTR(eh_decode_ptr) { EH_DecodePtrCtx *ctx = ud; return eh_parse_ptr(data, 0, ctx->ptr_ctx->pc_vaddr, ctx->ptr_ctx, ctx->addr_enc, ptr_out); } internal String8 eh_string_from_ptr_enc_type(EH_PtrEnc type) { switch (type) { case EH_PtrEnc_Ptr: return str8_lit("Ptr"); case EH_PtrEnc_ULEB128: return str8_lit("ULEB128"); case EH_PtrEnc_UData2: return str8_lit("UData2"); case EH_PtrEnc_UData4: return str8_lit("UData4"); case EH_PtrEnc_UData8: return str8_lit("UData8"); case EH_PtrEnc_Signed: return str8_lit("Signed"); case EH_PtrEnc_SLEB128: return str8_lit("SLEB128"); case EH_PtrEnc_SData2: return str8_lit("SData2"); case EH_PtrEnc_SData4: return str8_lit("SData4"); case EH_PtrEnc_SData8: return str8_lit("SData8"); } return str8_zero(); } internal String8 eh_string_from_ptr_enc_modifier(EH_PtrEnc modifier) { switch (modifier) { case EH_PtrEnc_PcRel: return str8_lit("PcRel"); case EH_PtrEnc_TextRel: return str8_lit("TextRel"); case EH_PtrEnc_DataRel: return str8_lit("DataRel"); case EH_PtrEnc_FuncRel: return str8_lit("FuncRel"); case EH_PtrEnc_Aligned: return str8_lit("Aligned"); } return str8_zero(); } internal String8 eh_string_from_ptr_enc(Arena *arena, EH_PtrEnc enc) { String8 type_str = eh_string_from_ptr_enc_type(enc & EH_PtrEnc_TypeMask); String8 modifer_str = eh_string_from_ptr_enc_modifier(enc & EH_PtrEnc_ModifierMask); String8 indir_str = enc & EH_PtrEnc_Indirect ? str8_lit("Indirect") : str8_zero(); String8 result = str8f(arena, "Type: %S, Modifier %S (%S)", type_str, modifer_str, indir_str); return result; } ================================================ FILE: src/dwarf/eh_frame.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EH_FRAME_H #define EH_FRAME_H //////////////////////////////// //~ Format typedef U8 EH_PtrEnc; enum { EH_PtrEnc_Ptr = 0x00, // Pointer sized unsigned value EH_PtrEnc_ULEB128 = 0x01, // Unsigned LE base-128 value EH_PtrEnc_UData2 = 0x02, // Unsigned 16-bit value EH_PtrEnc_UData4 = 0x03, // Unsigned 32-bit value EH_PtrEnc_UData8 = 0x04, // Unsigned 64-bit value EH_PtrEnc_Signed = 0x08, // Signed pointer EH_PtrEnc_SLEB128 = 0x09, // Signed LE base-128 value EH_PtrEnc_SData2 = 0x0A, // Signed 16-bit value EH_PtrEnc_SData4 = 0x0B, // Signed 32-bit value EH_PtrEnc_SData8 = 0x0C, // Signed 64-bit value EH_PtrEnc_TypeMask = 0x0F, }; enum { EH_PtrEnc_PcRel = 0x10, // Value is relative to the current program counter. EH_PtrEnc_TextRel = 0x20, // Value is relative to the .text section. EH_PtrEnc_DataRel = 0x30, // Value is relative to the .got or .eh_frame_hdr section. EH_PtrEnc_FuncRel = 0x40, // Value is relative to the function. EH_PtrEnc_Aligned = 0x50, // Value is aligned to an address unit sized boundary. EH_PtrEnc_ModifierMask = 0x70, }; enum { EH_PtrEnc_Indirect = 0x80, // Value is stored in virtual memory. EH_PtrEnc_Omit = 0xFF, }; typedef struct EH_PtrCtx { U64 pc_vaddr; // address where pointer is being read U64 text_vaddr; // base address of section with instructions (used for encoding pointer on SH and IA64) U64 data_vaddr; // base address of data section (used for encoding pointer on x86-64) U64 func_vaddr; // base address of function where IP is located U64 ptr_align; } EH_PtrCtx; typedef U8 EH_AugFlags; enum { EH_AugFlag_HasLSDA = (1 << 0), EH_AugFlag_HasHandler = (1 << 1), EH_AugFlag_HasAddrEnc = (1 << 2), EH_AugFlag_SignalFrame = (1 << 3), }; typedef struct EH_Augmentation { EH_AugFlags flags; U64 handler_ip; EH_PtrEnc handler_encoding; EH_PtrEnc lsda_encoding; EH_PtrEnc addr_encoding; U64 size; } EH_Augmentation; //////////////////////////////// //~ Parser enum { EH_CIE_Ext_AddrEnc, EH_CIE_Ext_LSDAEnc, EH_CIE_Ext_HandlerEnc, EH_CIE_Ext_HandlerIp, } EH_CIE_Ext; typedef struct EH_FrameHdrEntry { U64 addr; U64 fde_offset; } EH_FrameHdrEntry; typedef struct EH_FrameHdr { U8 version; EH_PtrEnc eh_frame_ptr_enc; EH_PtrEnc fde_count_enc; EH_PtrEnc table_enc; U64 field_byte_size; U64 entry_byte_size; U64 fde_count; U64 eh_frame_ptr; String8 table; } EH_FrameHdr; typedef struct EH_DecodePtrCtx { EH_PtrEnc addr_enc; EH_PtrCtx *ptr_ctx; } EH_DecodePtrCtx; //////////////////////////////// internal U64 eh_parse_ptr(String8 frame_base, U64 off, U64 pc, EH_PtrCtx *ptr_ctx, EH_PtrEnc encoding, U64 *ptr_out); internal EH_FrameHdr eh_parse_frame_hdr(String8 data, U64 address_size, EH_PtrCtx *ptr_ctx); internal U64 eh_parse_aug_data(String8 aug_string, String8 aug_data, U64 pc, EH_PtrCtx *ptr_ctx, EH_Augmentation *aug_out); internal B32 eh_parse_cie(String8 data, DW_Format format, Arch arch, U64 pc, EH_PtrCtx *ptr_ctx, DW_CIE *cie_out); internal B32 eh_parse_fde(String8 data, DW_Format format, U64 pc, DW_CIE *cie, EH_PtrCtx *ptr_ctx, DW_FDE *fde_out); internal U64 eh_find_nearest_fde(EH_FrameHdr header, EH_PtrCtx *ptr_ctx, U64 pc); internal String8 eh_frame_hdr_from_call_frame_info(Arena *arena, U64 fde_count, U64 *fde_offsets, struct DW_FDE *fde); //////////////////////////////// //~ Enum -> String internal String8 eh_string_from_ptr_enc_type(EH_PtrEnc type); internal String8 eh_string_from_ptr_enc_modifier(EH_PtrEnc modifier); internal String8 eh_string_from_ptr_enc(Arena *arena, EH_PtrEnc enc); #endif // EH_FRAME_H ================================================ FILE: src/elf/elf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: 32 => 64 bit conversions internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32) { ELF_Hdr64 h64 = {0}; MemoryCopy(h64.e_ident, h32.e_ident, sizeof(h64.e_ident)); h64.e_type = h32.e_type; h64.e_machine = h32.e_machine; h64.e_version = h32.e_version; h64.e_entry = (U64)h32.e_entry; h64.e_phoff = (U64)h32.e_phoff; h64.e_shoff = (U64)h32.e_shoff; h64.e_flags = h32.e_flags; h64.e_ehsize = h32.e_ehsize; h64.e_phentsize = h32.e_phentsize; h64.e_phnum = h32.e_phnum; h64.e_shentsize = h32.e_shentsize; h64.e_shnum = h32.e_shnum; h64.e_shstrndx = h32.e_shstrndx; return h64; } internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32) { ELF_Shdr64 h64 = {0}; h64.sh_name = h32.sh_name; h64.sh_type = h32.sh_type; h64.sh_flags = (U64)h32.sh_flags; h64.sh_addr = (U64)h32.sh_addr; h64.sh_offset = (U64)h32.sh_offset; h64.sh_size = (U64)h32.sh_size; h64.sh_link = h32.sh_link; h64.sh_info = h32.sh_info; h64.sh_addralign = (U64)h32.sh_addralign; h64.sh_entsize = (U64)h32.sh_entsize; return h64; } internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32) { ELF_Phdr64 h64 = {0}; h64.p_type = h32.p_type; h64.p_flags = h32.p_flags; h64.p_offset = (U64)h32.p_offset; h64.p_vaddr = (U64)h32.p_vaddr; h64.p_paddr = (U64)h32.p_paddr; h64.p_filesz = (U64)h32.p_filesz; h64.p_memsz = (U64)h32.p_memsz; h64.p_align = (U64)h32.p_align; return h64; } internal ELF_Dyn64 elf_dyn64_from_dyn32(ELF_Dyn32 h32) { ELF_Dyn64 h64 = {0}; h64.tag = (U64)h32.tag; h64.val = (U64)h32.val; return h64; } internal ELF_Sym64 elf_sym64_from_sym32(ELF_Sym32 sym32) { ELF_Sym64 sym64 = {0}; sym64.st_name = sym32.st_name; sym64.st_value = sym32.st_value; sym64.st_size = sym32.st_size; sym64.st_info = sym32.st_info; sym64.st_other = sym32.st_other; sym64.st_shndx = sym32.st_shndx; return sym64; } internal ELF_Rel64 elf_rel64_from_rel32(ELF_Rel32 rel32) { U32 sym = ELF32_R_SYM(rel32.r_info); U32 type = ELF32_R_TYPE(rel32.r_info); ELF_Rel64 rel64 = {0}; rel64.r_info = ELF64_R_INFO(sym, type); rel64.r_offset = rel32.r_offset; return rel64; } internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32) { U32 sym = ELF32_R_SYM(rela32.r_info); U32 type = ELF32_R_TYPE(rela32.r_info); ELF_Rela64 rela64 = {0}; rela64.r_offset = rela32.r_info; rela64.r_info = ELF64_R_INFO(sym, type); rela64.r_addend = rela32.r_addend; return rela64; } internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32) { ELF_Chdr64 chdr64 = {0}; chdr64.ch_type = chdr32.ch_type; chdr64.ch_size = chdr32.ch_size; chdr64.ch_addr_align = chdr32.ch_addr_align; return chdr64; } internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32) { ELF_Auxv64 auxv64 = {0}; auxv64.a_type = auxv32.a_type; auxv64.a_val = auxv32.a_val; return auxv64; } //////////////////////////////// internal String8 elf_string_from_class(Arena *arena, ELF_Class v) { switch (v) { case ELF_Class_None: return str8_lit("None"); case ELF_Class_32: return str8_lit("32Bit"); case ELF_Class_64: return str8_lit("64Bit"); } return push_str8f(arena, "%#x", v); } //////////////////////////////// internal Arch arch_from_elf_machine(ELF_MachineKind e_machine) { Arch arch = Arch_Null; switch (e_machine) { case ELF_MachineKind_None: arch = Arch_Null; break; case ELF_MachineKind_AARCH64: arch = Arch_arm32; break; case ELF_MachineKind_ARM: arch = Arch_arm32; break; case ELF_MachineKind_386: arch = Arch_x86; break; case ELF_MachineKind_X86_64: arch = Arch_x64; break; default: NotImplemented; break; } return arch; } //////////////////////////////// internal U64 elf_phdr_size_from_class(ELF_Class elf_class) { U64 result = 0; switch (elf_class) { case ELF_Class_None: break; case ELF_Class_32: { result = sizeof(ELF_Phdr32); } break; case ELF_Class_64: { result = sizeof(ELF_Phdr64); } break; default: { NotImplemented; } break; } return result; } internal U64 elf_dyn_size_from_class(ELF_Class elf_class) { U64 result = 0; switch (elf_class) { case ELF_Class_None: break; case ELF_Class_32: { result = sizeof(ELF_Dyn32); } break; case ELF_Class_64: { result = sizeof(ELF_Dyn64); } break; default: { NotImplemented; } break; } return result; } ================================================ FILE: src/elf/elf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ELF_H #define ELF_H typedef U8 ELF_Class; enum { ELF_Class_None = 0, ELF_Class_32 = 1, ELF_Class_64 = 2, ELF_Class_Count = 3 }; typedef U8 ELF_OsAbi; enum { ELF_OsAbi_None, ELF_OsAbi_SYSV, ELF_OsAbi_HPUX, ELF_OsAbi_NETBSD, ELF_OsAbi_GNU, ELF_OsAbi_LINUX, ELF_OsAbi_SOLARIS, ELF_OsAbi_IRIX, ELF_OsAbi_FREEBSD, ELF_OsAbi_TRU64, ELF_OsAbi_ARM = 97, ELF_OsAbi_STANDALONE = 255, }; typedef U8 ELF_Version; enum { ELF_Version_None, ELF_Version_Current, }; typedef U16 ELF_MachineKind; enum { ELF_MachineKind_None = 0, ELF_MachineKind_M32 = 1, ELF_MachineKind_SPARC = 2, ELF_MachineKind_386 = 3, ELF_MachineKind_68K = 4, ELF_MachineKind_88K = 5, ELF_MachineKind_IAMCU = 6, ELF_MachineKind_860 = 7, ELF_MachineKind_MIPS = 8, ELF_MachineKind_S370 = 9, ELF_MachineKind_MIPS_RS3_LE = 10, // 11-14 reserved ELF_MachineKind_PARISC = 15, // 16 reserved ELF_MachineKind_VPP500 = 17, ELF_MachineKind_SPARC32PLUS = 18, // nick: Sun's "v8plus" ELF_MachineKind_INTEL960 = 19, ELF_MachineKind_PPC = 20, ELF_MachineKind_PPC64 = 21, ELF_MachineKind_S390 = 22, ELF_MachineKind_SPU = 23, // 24-35 reserved ELF_MachineKind_V800 = 36, ELF_MachineKind_FR20 = 37, ELF_MachineKind_RH32 = 38, ELF_MachineKind_MCORE = 39, ELF_MachineKind_ARM = 40, ELF_MachineKind_SH = 42, ELF_MachineKind_ALPHA = 41, ELF_MachineKind_SPARCV9 = 43, ELF_MachineKind_TRICORE = 44, ELF_MachineKind_ARC = 45, ELF_MachineKind_H8_300 = 46, ELF_MachineKind_H8_300H = 47, ELF_MachineKind_H8S = 48, ELF_MachineKind_H8_500 = 49, ELF_MachineKind_IA_64 = 50, ELF_MachineKind_MIPS_X = 51, ELF_MachineKind_COLDFILE = 52, ELF_MachineKind_68HC12 = 53, ELF_MachineKind_MMA = 54, ELF_MachineKind_PCP = 55, ELF_MachineKind_NCPU = 56, ELF_MachineKind_NDR1 = 57, ELF_MachineKind_STARCORE = 58, ELF_MachineKind_ME16 = 59, ELF_MachineKind_ST100 = 60, ELF_MachineKind_TINYJ = 61, ELF_MachineKind_X86_64 = 62, ELF_MachineKind_AARCH64 = 183, ELF_MachineKind_TI_C6000 = 140, ELF_MachineKind_L1OM = 180, ELF_MachineKind_K1OM = 181, ELF_MachineKind_RISCV = 243, ELF_MachineKind_S390_OLD = 0xA390, }; typedef U8 ELF_Data; enum { ELF_Data_None = 0, ELF_Data_2LSB = 1, ELF_Data_2MSB = 2, }; typedef U16 ELF_Type; enum { ELF_Type_None = 0, ELF_Type_Rel = 1, ELF_Type_Exec = 2, ELF_Type_Dyn = 3, ELF_Type_Core = 4, ELF_Type_LoOs = 0xfe00, ELF_Type_HiOs = 0xff00, ELF_Type_LoProc = 0xff00, ELF_Type_HiProc = 0xffff }; typedef U32 ELF_PType; enum { ELF_PType_Null = 0, ELF_PType_Load = 1, ELF_PType_Dynamic = 2, ELF_PType_Interp = 3, ELF_PType_Note = 4, ELF_PType_ShLib = 5, ELF_PType_PHdr = 6, ELF_PType_Tls = 7, ELF_PType_LoOs = 0x60000000, ELF_PType_HiOs = 0x6fffffff, ELF_PType_LowProc = 0x70000000, ELF_PType_HighProc = 0x7fffffff, ELF_PType_GnuEHFrame = ELF_PType_LoOs + 0x474E550, // segment with .eh_frame_hdr ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e551, // frame unwind information ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e552, // stack flags ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e553, // read-only after relocations }; typedef U32 ELF_PFlag; enum { ELF_PFlag_Exec = (1 << 0), ELF_PFlag_Write = (1 << 1), ELF_PFlag_Read = (1 << 2), }; typedef U32 ELF_ShType; enum { ELF_ShType_Null = 0, ELF_ShType_ProgBits = 1, ELF_ShType_Symtab = 2, ELF_ShType_Strtab = 3, ELF_ShType_Rela = 4, ELF_ShType_Hash = 5, ELF_ShType_Dynamic = 6, ELF_ShType_Note = 7, ELF_ShType_NoBits = 8, ELF_ShType_Rel = 9, ELF_ShType_Shlib = 10, ELF_ShType_Dynsym = 11, ELF_ShType_InitArray = 14, ELF_ShType_FiniArray = 15, // Array of ptrs to init functions ELF_ShType_PreinitArray = 16, // Array of ptrs to finish functions ELF_ShType_Group = 17, // Array of ptrs to pre-init funcs ELF_ShType_SymtabShndx = 18, // Section contains a section group ELF_ShType_GNU_IncrementalInputs = 0x6fff4700, // Indices for SHN_XINDEX entries ELF_ShType_GNU_Attributes = 0x6ffffff5, // Incremental build data ELF_ShType_GNU_Hash = 0x6ffffff6, // Object attributes ELF_ShType_GNU_LibList = 0x6ffffff7, // GNU style symbol hash table ELF_ShType_SUNW_verdef = 0x6ffffffd, ELF_ShType_SUNW_verneed = 0x6ffffffe, // Versions defined by file ELF_ShType_SUNW_versym = 0x6fffffff, // Versions needed by file // Symbol versions ELF_ShType_GNU_verdef = ELF_ShType_SUNW_verdef, ELF_ShType_GNU_verneed = ELF_ShType_SUNW_verneed, ELF_ShType_GNU_versym = ELF_ShType_SUNW_versym, ELF_ShType_Proc, ELF_ShType_User, }; typedef U32 ELF_SectionIndex; enum { ELF_SectionIndex_Undef = 0, // Symbol with section index is undefined and must be resolved by the link editor ELF_SectionIndex_Abs = 0xfff1, // Symbol has absolute value and wont change after relocations ELF_SectionIndex_Common = 0xfff2, // This symbol indicates to linker to allocate the storage at address multiple of st_value ELF_SectionIndex_LoReserve = 0xff00, ELF_SectionIndex_HiReserve = 0xffff, // Processor specific ELF_SectionIndex_LoProc = ELF_SectionIndex_LoReserve, ELF_SectionIndex_HiProc = 0xff1f, // Reserved for OS ELF_SectionIndex_LoOs = 0xff20, ELF_SectionIndex_HiOs = 0xff3f, ELF_SectionIndex_IA64_ASNI_Common = ELF_SectionIndex_LoProc, ELF_SectionIndex_X8664_LCommon = 0xff02, ELF_SectionIndex_MIPS_SCommon = 0xff03, ELF_SectionIndex_TIC6X_Common = ELF_SectionIndex_LoReserve, ELF_SectionIndex_MIPS_SUndefined = 0xff04, }; typedef U32 ELF_SectionFlags; enum { ELF_Shf_Write = (1 << 0), ELF_Shf_Alloc = (1 << 1), ELF_Shf_ExecInstr = (1 << 2), ELF_Shf_Merge = (1 << 4), ELF_Shf_Strings = (1 << 5), ELF_Shf_InfoLink = (1 << 6), ELF_Shf_LinkOrder = (1 << 7), ELF_Shf_OsNonConforming = (1 << 8), ELF_Shf_Group = (1 << 9), ELF_Shf_Tls = (1 << 10), ELF_Shf_Compressed = (1 << 11), ELF_Shf_MaskOs_Shift = 16, ELF_Shf_MaskOs_Mask = 0xff, ELF_Shf_AMD64Large = (1 << 28), ELF_Shf_Ordered = (1 << 30), ELF_Shf_Exclude = (1 << 31), ELF_Shf_MaskProc_Shift = 28, ELF_Shf_MaskProc_Mask = 0xf, }; #define ELF_SectionFlag_Extract_MaskOs(f) (U8)(((f) >> ELF_SectionFlag_MaskOs_Shift) & ELF_SectionFlag_MaskOs_Mask) #define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask) typedef U32 ELF_AuxType; enum { ELF_AuxType_Null = 0, ELF_AuxType_Phdr = 3, // program headers ELF_AuxType_Phent = 4, // size of a program header ELF_AuxType_Phnum = 5, // number of program headers ELF_AuxType_Pagesz = 6, // system page size ELF_AuxType_Base = 7, // interpreter base address ELF_AuxType_Flags = 8, ELF_AuxType_Entry = 9, // program entry point ELF_AuxType_Uid = 11, ELF_AuxType_Euid = 12, ELF_AuxType_Gid = 13, ELF_AuxType_Egid = 14, ELF_AuxType_Platform = 15, ELF_AuxType_Hwcap = 16, ELF_AuxType_Clktck = 17, ELF_AuxType_DCacheBSize = 19, ELF_AuxType_ICacheBSize = 20, ELF_AuxType_UCacheBSize = 21, ELF_AuxType_IgnorePPC = 22, ELF_AuxType_Secure = 23, ELF_AuxType_BasePlatform = 24, ELF_AuxType_Random = 25, ELF_AuxType_Hwcap2 = 26, // addres to 16 random bytes ELF_AuxType_ExecFn = 31, ELF_AuxType_SysInfo = 32, // file name of executable ELF_AuxType_SysInfoEhdr = 33, ELF_AuxType_L1I_CacheSize = 40, ELF_AuxType_L1I_CacheGeometry = 41, ELF_AuxType_L1D_CacheSize = 42, ELF_AuxType_L1D_CacheGeometry = 43, ELF_AuxType_L2_CacheSize = 44, ELF_AuxType_L2_CacheGeometry = 45, ELF_AuxType_L3_CacheSize = 46, ELF_AuxType_L3_CacheGeometry = 47, }; typedef U32 ELF_DynTag; enum { ELF_DynTag_Null = 0, ELF_DynTag_Needed = 1, ELF_DynTag_PltRelsz = 2, ELF_DynTag_PltGot = 3, ELF_DynTag_Hash = 4, ELF_DynTag_Strtab = 5, ELF_DynTag_Symtab = 6, ELF_DynTag_Rela = 7, ELF_DynTag_Relasz = 8, ELF_DynTag_Relaent = 9, ELF_DynTag_Strsz = 10, ELF_DynTag_Syment = 11, ELF_DynTag_Init = 12, ELF_DynTag_Fini = 13, ELF_DynTag_SoName = 14, ELF_DynTag_RPath = 15, ELF_DynTag_Symbolic = 16, ELF_DynTag_Rel = 17, ELF_DynTag_Relsz = 18, ELF_DynTag_Relent = 19, ELF_DynTag_Pltrel = 20, ELF_DynTag_Debug = 21, ELF_DynTag_TextRel = 22, ELF_DynTag_JmpRel = 23, ELF_DynTag_BindNow = 24, ELF_DynTag_InitArray = 25, ELF_DynTag_FiniArray = 26, ELF_DynTag_InitArraysz = 27, ELF_DynTag_FIniArraysz = 28, ELF_DynTag_RunPath = 29, ELF_DynTag_Flags = 30, ELF_DynTag_PreInitArray = 32, ELF_DynTag_PreInitArraysz = 33, ELF_DynTag_SymtabShndx = 34, ELF_DynTag_LoOs = 0x6000000D, ELF_DynTag_HiOs = 0x6ffff000, ELF_DynTag_ValRngLo = 0x6ffffd00, ELF_DynTag_GNU_PreLinked = 0x6ffffdf5, ELF_DynTag_GNU_Conflictsz = 0x6ffffdf6, ELF_DynTag_GNU_LibListsz = 0x6ffffdf7, ELF_DynTag_Checksum = 0x6ffffdf8, ELF_DynTag_Pltpadsz = 0x6ffffdf9, ELF_DynTag_Moveent = 0x6ffffdfa, ELF_DynTag_Movesz = 0x6ffffdfb, ELF_DynTag_Feature = 0x6ffffdfc, ELF_DynTag_PosFlag_1 = 0x6ffffdfd, ELF_DynTag_SymInSz = 0x6ffffdfe, ELF_DynTag_SymInEnt = 0x6ffffdff, ELF_DynTag_ValRngHi = ELF_DynTag_SymInEnt, ELF_DynTag_AddrRngLo = 0x6ffffe00, ELF_DynTag_GNU_Hash = 0x6ffffef5, ELF_DynTag_TlsDescPlt = 0x6ffffef6, ELF_DynTag_TlsDescGot = 0x6ffffef7, ELF_DynTag_GNU_Conflict = 0x6ffffef8, ELF_DynTag_GNU_LibList = 0x6ffffef9, ELF_DynTag_Config = 0x6ffffefa, ELF_DynTag_DepAudit = 0x6ffffefb, ELF_DynTag_Audit = 0x6ffffefc, ELF_DynTag_PltPad = 0x6ffffefd, ELF_DynTag_MoveTab = 0x6ffffefe, ELF_DynTag_SymInfo = 0x6ffffeff, ELF_DynTag_AddrRngHi = ELF_DynTag_SymInfo, ELF_DynTag_RelaCount = 0x6ffffff9, ELF_DynTag_RelCount = 0x6ffffffa, ELF_DynTag_Flags_1 = 0x6ffffffb, ELF_DynTag_VerDef = 0x6ffffffc, ELF_DynTag_VerDefNum = 0x6ffffffd, ELF_DynTag_VerNeed = 0x6ffffffe, ELF_DynTag_VerNeedNum = 0x6fffffff, ELF_DynTag_VerSym = 0x6ffffff0, ELF_DynTag_LoProc = 0x70000000, ELF_DynTag_HiProc = 0x7fffffff, }; typedef U32 ELF_DynFlag; enum { ELF_DynFlag_Origin = (1 << 0), ELF_DynFlag_Symbolic = (1 << 1), ELF_DynFlag_TextTel = (1 << 2), ELF_DynFlag_BindNow = (1 << 3), ELF_DynFlag_StaticTls = (1 << 4), }; typedef U32 ELF_DynFeatureFlag; enum { ELF_DynFeatureFlag_ParInit = (1 << 0), ELF_DynFeatureFlag_ConfExp = (1 << 1), }; typedef U8 ELF_SymBind; enum { // the same name may exists in multiple files without interfering with each other. ELF_SymBind_Local = 0, // Visible to all objects that are linked together. ELF_SymBind_Global = 1, // If there is a global symbol with identical name linker doesn't issue an error. ELF_SymBind_Weak = 2, ELF_SymBind_LoProc = 13, ELF_SymBind_HiProc = 15, }; typedef U8 ELF_SymType; enum { ELF_SymType_NoType = 0, // Type is not specified. ELF_SymType_Object = 1, // Symbol is associated with data object, such as a variable, an array, etc. ELF_SymType_Func = 2, // Symbol is associated with a function. ELF_SymType_Section = 3, // Symbol is used to relocate sections and normally have LOCAL binding. ELF_SymType_File = 4, // Gives name of the source file associated with object. ELF_SymType_Common = 5, ELF_SymType_Tls = 6, ELF_SymType_LoProc = 13, ELF_SymType_HiProc = 15, }; typedef U8 ELF_SymVisibility; enum { ELF_SymVisibility_Default = 0, ELF_SymVisibility_Internal = 1, ELF_SymVisibility_Hidden = 2, ELF_SymVisibility_Protected = 3, }; typedef U32 ELF_RelocI386; enum { ELF_RelocI386_None = 0, ELF_RelocI386_32 = 1, ELF_RelocI386_PC32 = 2, ELF_RelocI386_GOT32 = 3, ELF_RelocI386_PLT32 = 4, ELF_RelocI386_Copy = 5, ELF_RelocI386_GlobDat = 6, ELF_RelocI386_JumpSlot = 7, ELF_RelocI386_Relative = 8, ELF_RelocI386_GotOff = 9, ELF_RelocI386_GotPc = 10, ELF_RelocI386_32Plt = 11, ELF_RelocI386_Tls_tpoff = 14, ELF_RelocI386_Tls_ie = 15, ELF_RelocI386_Tls_gotie = 16, ELF_RelocI386_Tls_le = 17, ELF_RelocI386_Tls_gd = 18, ELF_RelocI386_Tls_ldm = 19, ELF_RelocI386_16 = 20, ELF_RelocI386_PC16 = 21, ELF_RelocI386_8 = 22, ELF_RelocI386_Pc8 = 23, ELF_RelocI386_TlsGd32 = 24, ELF_RelocI386_TlsGdPush = 25, ELF_RelocI386_TlsGdCall = 26, ELF_RelocI386_TlsGdPop = 27, ELF_RelocI386_TlsLdm32 = 28, ELF_RelocI386_TlsLdmPush = 29, ELF_RelocI386_TlsLdmCall = 30, ELF_RelocI386_TlsLdmPop = 31, ELF_RelocI386_TlsLdo32 = 32, ELF_RelocI386_TlsIe32 = 33, ELF_RelocI386_TlsLe32 = 34, ELF_RelocI386_TlsDtpmod32 = 35, ELF_RelocI386_TlsDtpoff32 = 36, ELF_RelocI386_TlsTpoff32 = 37, // 38 is not taken ELF_RelocI386_TlsGotDesc = 39, ELF_RelocI386_TlsDescCall = 40, ELF_RelocI386_TlsDesc = 41, ELF_RelocI386_IRelative = 42, ELF_RelocI386_Gotx32x = 43, ELF_RelocI386_UsedByIntel200 = 200, ELF_RelocI386_GNU_VTInherit = 250, ELF_RelocI386_GNU_VTEntry = 251, }; typedef U32 ELF_RelocX8664; enum { ELF_RelocX8664_None = 0, ELF_RelocX8664_64 = 1, ELF_RelocX8664_Pc32 = 2, ELF_RelocX8664_Got32 = 3, ELF_RelocX8664_Plt32 = 4, ELF_RelocX8664_Copy = 5, ELF_RelocX8664_GlobDat = 6, ELF_RelocX8664_JumpSlot = 7, ELF_RelocX8664_Relative = 8, ELF_RelocX8664_GotPcRel = 9, ELF_RelocX8664_32 = 10, ELF_RelocX8664_32S = 11, ELF_RelocX8664_16 = 12, ELF_RelocX8664_Pc16 = 13, ELF_RelocX8664_8 = 14, ELF_RelocX8664_Pc8 = 15, ELF_RelocX8664_DtpMod64 = 16, ELF_RelocX8664_DtpOff64 = 17, ELF_RelocX8664_TpOff64 = 18, ELF_RelocX8664_TlsGd = 19, ELF_RelocX8664_TlsLd = 20, ELF_RelocX8664_DtpOff32 = 21, ELF_RelocX8664_GotTpOff = 22, ELF_RelocX8664_TpOff32 = 23, ELF_RelocX8664_Pc64 = 24, ELF_RelocX8664_GotOff64 = 25, ELF_RelocX8664_GotPc32 = 26, ELF_RelocX8664_Got64 = 27, ELF_RelocX8664_GotPcRel64 = 28, ELF_RelocX8664_GotPc64 = 29, ELF_RelocX8664_GotPlt64 = 30, ELF_RelocX8664_PltOff64 = 31, ELF_RelocX8664_Size32 = 32, ELF_RelocX8664_Size64 = 33, ELF_RelocX8664_GotPc32TlsDesc = 34, ELF_RelocX8664_TlsDescCall = 35, ELF_RelocX8664_TlsDesc = 36, ELF_RelocX8664_IRelative = 37, ELF_RelocX8664_Relative64 = 38, ELF_RelocX8664_Pc32Bnd = 39, ELF_RelocX8664_Plt32Bnd = 40, ELF_RelocX8664_GotPcRelx = 41, ELF_RelocX8664_RexGotPcRelx = 42, ELF_RelocX8664_GNU_VTInherit = 250, ELF_RelocX8664_GNU_VTEntry = 251, }; typedef U32 ELF_ExternalVerFlag; enum { ELF_ExternalVerFlag_Base = (1 << 0), ELF_ExternalVerFlag_Weak = (1 << 1), ELF_ExternalVerFlag_Info = (1 << 2), }; typedef U32 ELF_NoteType; enum { ELF_NoteType_STapSdt = 3, // System Tap probes }; #define ELF_HdrIs64Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_64) #define ELF_HdrIs32Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_32) typedef enum ELF_Identifier { ELF_Identifier_Mag0 = 0, ELF_Identifier_Mag1 = 1, ELF_Identifier_Mag2 = 2, ELF_Identifier_Mag3 = 3, ELF_Identifier_Class = 4, ELF_Identifier_Data = 5, ELF_Identifier_Version = 6, ELF_Identifier_OsAbi = 7, ELF_Identfiier_AbiBersion = 8, ELF_Identifier_Max = 16, } ELF_Identifier; read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'}; read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)}; typedef struct ELF_Hdr64 { U8 e_ident[ELF_Identifier_Max]; ELF_Type e_type; ELF_MachineKind e_machine; U32 e_version; U64 e_entry; U64 e_phoff; U64 e_shoff; U32 e_flags; U16 e_ehsize; U16 e_phentsize; U16 e_phnum; U16 e_shentsize; U16 e_shnum; U16 e_shstrndx; } ELF_Hdr64; typedef struct ELF_Hdr32 { U8 e_ident[ELF_Identifier_Max]; ELF_Type e_type; ELF_MachineKind e_machine; U32 e_version; U32 e_entry; U32 e_phoff; U32 e_shoff; U32 e_flags; U16 e_ehsize; U16 e_phentsize; U16 e_phnum; U16 e_shentsize; U16 e_shnum; U16 e_shstrndx; } ELF_Hdr32; typedef struct ELF_Shdr64 { U32 sh_name; ELF_ShType sh_type; U64 sh_flags; U64 sh_addr; U64 sh_offset; U64 sh_size; U32 sh_link; U32 sh_info; U64 sh_addralign; U64 sh_entsize; } ELF_Shdr64; typedef struct ELF_Shdr32 { U32 sh_name; ELF_ShType sh_type; U32 sh_flags; U32 sh_addr; U32 sh_offset; U32 sh_size; U32 sh_link; U32 sh_info; U32 sh_addralign; U32 sh_entsize; } ELF_Shdr32; typedef struct ELF_Phdr64 { U32 p_type; U32 p_flags; U64 p_offset; U64 p_vaddr; U64 p_paddr; U64 p_filesz; U64 p_memsz; U64 p_align; } ELF_Phdr64; typedef struct ELF_Phdr32 { U32 p_type; U32 p_offset; U32 p_vaddr; U32 p_paddr; U32 p_filesz; U32 p_memsz; U32 p_flags; U32 p_align; } ELF_Phdr32; //////////////////////////////// // Auxiliary Vectors // these appear in /proc//auxv of a process, they are not in elf files typedef struct ELF_Auxv32 { U32 a_type; U32 a_val; } ELF_Auxv32; typedef struct ELF_Auxv64 { U64 a_type; U64 a_val; } ELF_Auxv64; //////////////////////////////// // Dynamic Structures // these appear in the virtual address space of a process, they are not in elf files typedef struct ELF_Dyn32 { U32 tag; U32 val; } ELF_Dyn32; typedef struct ELF_Dyn64 { U64 tag; U64 val; } ELF_Dyn64; //////////////////////////////// // Imports and Exports typedef struct { U32 st_name; // Holds index into files string table. U32 st_value; // Depending on the context, this may be address, size, etc. U32 st_size; // Data size in bytes. Zero when size is unknown. U8 st_info; // Contains symbols type and binding. U8 st_other; // Reserved for future use, currenly zero. U16 st_shndx; // Section index to which symbol is relevant. } ELF_Sym32; typedef struct { U32 st_name; U8 st_info; U8 st_other; U16 st_shndx; U64 st_value; U64 st_size; } ELF_Sym64; #define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF)) #define ELF_ST_BIND(x) ((x) >> 4) #define ELF_ST_TYPE(x) ((x) & 0xF) #define ELF_ST_VISIBILITY(v) ((v) & 0x3) typedef struct { U32 r_offset; U32 r_info; } ELF_Rel32; typedef struct { U32 r_offset; U32 r_info; S32 r_addend; } ELF_Rela32; typedef struct { U64 r_offset; U64 r_info; } ELF_Rel64; typedef struct { U64 r_offset; U64 r_info; S64 r_addend; } ELF_Rela64; #define ELF32_R_SYM(x) ((x) >> 8) #define ELF32_R_TYPE(x) ((x) & 0xFF) #define ELF64_R_INFO(s,t) (((U64)(s) << 32) | (U64)t) #define ELF64_R_SYM(x) ((x) >> 32) #define ELF64_R_TYPE(x) ((x) & 0xffffffff) // This flag is set to indicate that symbol is not available outside shared object #define ELF_EXTERNAL_VERSYM_HIDDEN 0x8000 #define ELF_EXTERNAL_VERSYM_MASK 0x7FFF // Appears in .gnu.verdef (SHT_GNU_verdef) typedef struct { U16 vd_version; U16 vd_flags; U16 vd_ndx; U16 vd_cnt; U32 vd_hash; U32 vd_aux; U32 vd_next; } ELF_ExternalVerdef; // Appears in .gnu.verdef (SHT_GNU_verdef) typedef struct { U32 vda_name; U32 vda_next; } ELF_ExternalVerdaux; // Appears in .gnu.verneed (SHT_GNU_verneed) typedef struct { U16 vn_version; U16 vn_cnt; U32 vn_file; U32 vn_aux; U32 vn_next; } ELF_ExternalVerneed; // Appears in .gnu.verneed (SHT_GNU_verneed) typedef struct { U32 vna_hash; U16 vna_flags; U16 vna_other; U32 vna_name; U32 vna_next; } ELF_ExternalVernaux; // Appears in .gnu.version (SHT_GNU_versym) typedef struct { U16 vs_vers; } ELF_ExternalVersym; //////////////////////////////// // Extensions typedef U8 ELF_CompressType; enum ELF_CompressTypeEnum { ELF_CompressType_None = 0, ELF_CompressType_ZLib = 1, ELF_CompressType_ZStd = 2, ELF_CompressType_LoOs = 0x60000000, ELF_CompressType_HiOs = 0x6fffffff, ELF_CompressType_LoProc = 0x70000000, ELF_CompressType_HiProc = 0x7fffffff, }; typedef struct ELF_Chdr32 { U32 ch_type; U32 ch_size; U32 ch_addr_align; } ELF_Chdr32; typedef struct ELF_Chdr64 { U32 ch_type; U32 ch_reserved; U64 ch_size; U64 ch_addr_align; } ELF_Chdr64; //////////////////////////////// internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32); internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32); internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32); internal ELF_Dyn64 elf_dyn64_from_dyn32 (ELF_Dyn32 h32); internal ELF_Sym64 elf_sym64_from_sym32 (ELF_Sym32 sym32); internal ELF_Rel64 elf_rel64_from_rel32 (ELF_Rel32 rel32); internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32); internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32); internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32); //////////////////////////////// internal String8 elf_string_from_class(Arena *arena, ELF_Class v); //////////////////////////////// internal Arch arch_from_elf_machine(ELF_MachineKind machine); //////////////////////////////// internal U64 elf_phdr_size_from_class(ELF_Class elf_class); internal U64 elf_dyn_size_from_class(ELF_Class elf_class); #endif // ELF_H ================================================ FILE: src/elf/elf_dump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8List elf_dump_note(Arena *arena, String8 raw_notes, ELF_Class elf_class, ELF_MachineKind e_machine) { Temp scratch = scratch_begin(&arena, 1); B32 is_bad_parse = 1; String8List strings = {0}; U64 cursor = 0; for (;cursor < raw_notes.size;) { U32 owner_size; U64 owner_size_size = str8_deserial_read_struct(raw_notes, cursor, &owner_size); if (owner_size_size == 0) { goto exit; } cursor += owner_size_size; U32 desc_size; U64 desc_size_size = str8_deserial_read_struct(raw_notes, cursor, &desc_size); if (desc_size_size == 0) { goto exit; } cursor += desc_size_size; ELF_NoteType note_type; U64 type_size = str8_deserial_read_struct(raw_notes, cursor, ¬e_type); if (type_size == 0) { goto exit; } cursor += type_size; if (cursor + owner_size > raw_notes.size) { goto exit; } String8 owner = str8_cstring_capped(raw_notes.str + cursor, raw_notes.str + cursor + owner_size); cursor += owner_size; if (cursor + desc_size > raw_notes.size) { goto exit; } String8 raw_desc = str8_substr(raw_notes, r1u64(cursor, cursor + desc_size)); cursor += desc_size; cursor = AlignPow2(cursor, 4); String8List desc_fmt = {0}; String8 note_type_str = {0}; if (str8_match(owner, str8_lit("GNU"), StringMatchFlag_CaseInsensitive)) { // format description switch (note_type) { case GNU_NoteType_Abi: { U64 desc_cursor = 0; GNU_AbiTag os = 0; U64 os_size = str8_deserial_read_struct(raw_desc, desc_cursor, &os); if (os_size == 0) { goto exit; } cursor += os_size; U32 major = 0; U64 major_size = str8_deserial_read_struct(raw_desc, desc_cursor, &major); if (major_size == 0) { goto exit; } cursor += major_size; U32 minor = 0; U64 minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &minor); if (minor_size == 0) { goto exit; } cursor += minor_size; U32 sub_minor = 0; U64 sub_minor_size = str8_deserial_read_struct(raw_desc, desc_cursor, &sub_minor); if (sub_minor_size == 0) { goto exit; } cursor += sub_minor_size; String8 os_str = gnu_string_from_abi_tag(os); if (os_str.size == 0) os_str = str8f(scratch.arena, "0x%x", os); str8_list_pushf(scratch.arena, &desc_fmt, "OS: %S, ABI: %u.%u.%u", os_str, major, minor, sub_minor); } break; case GNU_NoteType_BuildId: { String8List build_id = {0}; for EachIndex(desc_cursor, desc_size) { U8 v = 0; U64 v_size = str8_deserial_read_struct(raw_desc, desc_cursor, &v); if (v_size == 0) { goto exit; } desc_cursor += v_size; str8_list_pushf(scratch.arena, &build_id, "%02x", v); } String8 build_id_str = str8_list_join(scratch.arena, &build_id, 0); str8_list_pushf(scratch.arena, &desc_fmt, "Build ID: %S", build_id_str); } break; case GNU_NoteType_PropertyType0: { U64 align = elf_class == ELF_Class_64 ? 8 : 4; for (U64 desc_cursor = 0; desc_cursor < raw_desc.size; ) { GNU_Property type = 0; U64 type_size = str8_deserial_read_struct(raw_desc, desc_cursor, &type); if (type_size == 0) { goto exit; } desc_cursor += type_size; U32 size = 0; U64 size_size = str8_deserial_read_struct(raw_desc, desc_cursor, &size); if (size_size == 0) { goto exit; } desc_cursor += size_size; U32 flags = 0; if (size == 4) { U64 flags_size = str8_deserial_read_struct(raw_desc, desc_cursor, &flags); if (flags_size == 0) { goto exit; } desc_cursor += flags_size; } switch (e_machine) { case ELF_MachineKind_None: break; case ELF_MachineKind_X86_64: { String8 features = gnu_string_from_property_flags_x86(scratch.arena, type, flags); str8_list_pushf(scratch.arena, &desc_fmt, "x86 features: %S", features); } break; default: NotImplemented; break; } desc_cursor = AlignPow2(desc_cursor, align); } } break; default: NotImplemented; break; } note_type_str = gnu_string_from_note_type(note_type); } else if (str8_match(owner, str8_lit("stapsdt"), StringMatchFlag_CaseInsensitive)) { if (note_type == ELF_NoteType_STapSdt) { U64 desc_cursor = 0; U64 addr_size = elf_class == ELF_Class_64 ? 8 : 4; U64 pc = 0; U64 pc_size = str8_deserial_read(raw_desc, desc_cursor, &pc, addr_size, addr_size); if (pc_size == 0) { goto exit; } desc_cursor += pc_size; U64 base_addr = 0; U64 base_addr_size = str8_deserial_read(raw_desc, desc_cursor, &base_addr, addr_size, addr_size); if (base_addr_size == 0) { goto exit; } desc_cursor += base_addr_size; U64 semaphore = 0; U64 semaphore_size = str8_deserial_read(raw_desc, desc_cursor, &semaphore, addr_size, addr_size); if (semaphore_size == 0) { goto exit; } desc_cursor += semaphore_size; String8 provider = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += provider.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } String8 probe = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += probe.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } String8 args = str8_cstring_capped(raw_desc.str + desc_cursor, raw_desc.str + raw_desc.size); desc_cursor += args.size + 1; if (desc_cursor > raw_desc.size) { goto exit; } str8_list_pushf(scratch.arena, &desc_fmt, "Provider: %S", provider); str8_list_pushf(scratch.arena, &desc_fmt, "Probe: %S", probe); str8_list_pushf(scratch.arena, &desc_fmt, "PC: 0x%I64x", pc); str8_list_pushf(scratch.arena, &desc_fmt, "Base: 0x%I64x", base_addr); str8_list_pushf(scratch.arena, &desc_fmt, "Semaphore: 0x%I64x", semaphore); str8_list_pushf(scratch.arena, &desc_fmt, "Arguments: %S", args); note_type_str = str8_lit("NT_STAPSDT"); } } if (note_type_str.size == 0) note_type_str = str8f(scratch.arena, "0x%x", note_type); str8_list_pushf(arena, &strings, "{"); str8_list_pushf(arena, &strings, " Owner: %S", owner); str8_list_pushf(arena, &strings, " Data Size: 0x%x", desc_size); str8_list_pushf(arena, &strings, " Type: %S", note_type_str); if (desc_fmt.node_count) { str8_list_pushf(arena, &strings, " Description:"); str8_list_pushf(arena, &strings, " {"); for EachNode(n, String8Node, desc_fmt.first) { str8_list_pushf(arena, &strings, " %S", n->string); } str8_list_pushf(arena, &strings, " }"); } str8_list_pushf(arena, &strings, "}"); } is_bad_parse = 0; exit:; if (is_bad_parse) { str8_list_pushf(arena, &strings, "ERROR: unable to parse data @ 0x%Ix64", cursor); } scratch_end(scratch); return strings; } internal String8List elf_dump(Arena *arena, String8 raw_elf, ELF_DumpSubsetFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; ELF_Bin elf = elf_bin_from_data(scratch.arena, raw_elf); if (flags & ELF_DumpSubsetFlag_Note) { for EachIndex(sect_idx, elf.shdrs.count) { ELF_Shdr64 *shdr = &elf.shdrs.v[sect_idx]; if (shdr->sh_type == ELF_ShType_Note) { String8 raw_notes = str8_substr(raw_elf, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size)); String8 shdr_name = elf_name_from_shdr64(raw_elf, &elf, shdr); str8_list_pushf(scratch.arena, &strings, "//"); str8_list_pushf(scratch.arena, &strings, "// %S", shdr_name); str8_list_pushf(scratch.arena, &strings, "//"); String8List note_strings = elf_dump_note(scratch.arena, raw_notes, elf.hdr.e_ident[ELF_Identifier_Class], elf.hdr.e_machine); str8_list_concat_in_place(&strings, ¬e_strings); } } } String8 out = str8_list_join(arena, &strings, &(StringJoin){.sep=str8_lit("\n"), .post=str8_lit("\n")}); String8List result = {0}; str8_list_push(arena, &result, out); scratch_end(scratch); return result; } ================================================ FILE: src/elf/elf_dump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ELF_DUMP_H #define ELF_DUMP_H #define ELF_DumpSubset_XList \ X(Note, note, "NOTE") typedef U32 ELF_DumpSubset; enum { #define X(name, name_lower, title) ELF_DumpSubset_##name, ELF_DumpSubset_XList #undef X }; typedef U32 ELF_DumpSubsetFlags; enum { #define X(name, name_lower, title) ELF_DumpSubsetFlag_##name = (1 << ELF_DumpSubset_##name), ELF_DumpSubset_XList #undef X ELF_DumpSubsetFlag_All = ~0, }; internal String8List elf_dump(Arena *arena, String8 raw_elf, ELF_DumpSubsetFlags flags); #endif // ELF_DUMP_H ================================================ FILE: src/elf/elf_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- rjf: top-level binary parsing internal ELF_Bin elf_bin_from_data(Arena *arena, String8 data) { ELF_Bin bin = {0}; if(str8_match(str8_prefix(data, elf_magic_string.size), elf_magic_string, 0) && data.size >= ELF_Identifier_Max) { //- rjf: parse sig/header U8 sig[ELF_Identifier_Max] = {0}; str8_deserial_read(data, 0, &sig[0], sizeof(sig), 1); switch(sig[ELF_Identifier_Class]) { default: case ELF_Class_None:{}break; case ELF_Class_32: { ELF_Hdr32 hdr32 = {0}; U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr32); if(hdr_size == sizeof(hdr32)) { bin.hdr = elf_hdr64_from_hdr32(hdr32); U64 shstr_off = hdr32.e_shoff + hdr32.e_shentsize*hdr32.e_shstrndx; ELF_Shdr32 shdr = {0}; U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr); if(shdr_size == sizeof(shdr)) { bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size); } } }break; case ELF_Class_64: { ELF_Hdr64 hdr64 = {0}; U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr64); if(hdr_size == sizeof(hdr64)) { bin.hdr = hdr64; U64 shstr_off = hdr64.e_shoff + hdr64.e_shentsize*hdr64.e_shstrndx; ELF_Shdr64 shdr = {0}; U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr); if(shdr_size == sizeof(shdr)) { bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size); } } }break; } //- rjf: gather all shdrs { ELF_Hdr64 *hdr = &bin.hdr; bin.shdrs.count = hdr->e_shnum; bin.shdrs.v = push_array(arena, ELF_Shdr64, hdr->e_shnum); Rng1U64 shdr_range = rng_1u64(hdr->e_shoff, hdr->e_shoff + hdr->e_shentsize*hdr->e_shnum); String8 shdr_data = str8_substr(data, shdr_range); for EachIndex(shdr_idx, hdr->e_shnum) { switch(hdr->e_ident[ELF_Identifier_Class]) { default: case ELF_Class_None: {}break; case ELF_Class_32: { ELF_Shdr32 shdr32 = {0}; str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr32), &shdr32); bin.shdrs.v[shdr_idx] = elf_shdr64_from_shdr32(shdr32); }break; case ELF_Class_64: { str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr64), &bin.shdrs.v[shdr_idx]); }break; } } } //- rjf: gather all phdrs { ELF_Hdr64 *hdr = &bin.hdr; bin.phdrs.count = hdr->e_phnum; bin.phdrs.v = push_array(arena, ELF_Phdr64, hdr->e_phnum); Rng1U64 phdr_range = rng_1u64(hdr->e_phoff, hdr->e_phoff + hdr->e_phentsize*hdr->e_phnum); String8 phdr_data = str8_substr(data, phdr_range); for EachIndex(phdr_idx, hdr->e_phnum) { switch(hdr->e_ident[ELF_Identifier_Class]) { default: case ELF_Class_None: {}break; case ELF_Class_32: { ELF_Phdr32 phdr32 = {0}; str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr32), &phdr32); bin.phdrs.v[phdr_idx] = elf_phdr64_from_phdr32(phdr32); }break; case ELF_Class_64: { str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr64), &bin.phdrs.v[phdr_idx]); }break; } } } } return bin; } //- rjf: extra bin info extraction internal String8 elf_name_from_shdr64(String8 data, ELF_Bin *bin, ELF_Shdr64 *shdr) { String8 sh_names = str8_substr(data, bin->sh_name_range); String8 name = {0}; str8_deserial_read_cstr(sh_names, shdr->sh_name, &name); return name; } internal U64 elf_base_addr_from_bin(ELF_Bin *bin) { U64 base_vaddr = 0; for EachIndex(phdr_idx, bin->phdrs.count) { ELF_Phdr64 *phdr = &bin->phdrs.v[phdr_idx]; if(phdr->p_type == ELF_PType_Load && (base_vaddr == 0 || phdr->p_vaddr < base_vaddr)) { base_vaddr = phdr->p_vaddr; } } return base_vaddr; } internal ELF_GnuDebugLink elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin) { ELF_GnuDebugLink result = {0}; for EachIndex(idx, bin->shdrs.count) { ELF_Shdr64 *shdr = &bin->shdrs.v[idx]; String8 name = elf_name_from_shdr64(raw_data, bin, shdr); if(str8_match(name, str8_lit(".gnu_debuglink"), 0)) { Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size); String8 data = str8_substr(raw_data, raw_data_range); String8 path = {0}; U32 checksum = 0; { U64 cursor = 0; cursor += str8_deserial_read_cstr(data, cursor, &path); cursor = AlignPow2(cursor, 4); cursor += str8_deserial_read_struct(data, cursor, &checksum); } result.path = path; result.checksum = checksum; break; } } return result; } internal ELF_NoteList elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine) { ELF_NoteList result = {0}; for (U64 cursor = 0; cursor < raw_note.size; ) { U32 owner_size; U64 owner_size_size = str8_deserial_read_struct(raw_note, cursor, &owner_size); if (owner_size_size == 0) { goto exit; } cursor += owner_size_size; U32 desc_size; U64 desc_size_size = str8_deserial_read_struct(raw_note, cursor, &desc_size); if (desc_size_size == 0) { goto exit; } cursor += desc_size_size; ELF_NoteType type; U64 type_size = str8_deserial_read_struct(raw_note, cursor, &type); if (type_size == 0) { goto exit; } cursor += type_size; if (cursor + owner_size > raw_note.size) { goto exit; } String8 owner = str8_cstring_capped(raw_note.str + cursor, raw_note.str + cursor + owner_size); cursor += owner_size; if (cursor + desc_size > raw_note.size) { goto exit; } String8 desc = str8_substr(raw_note, r1u64(cursor, cursor + desc_size)); cursor += desc_size; cursor = AlignPow2(cursor, 4); ELF_NoteNode *n = push_array(arena, ELF_NoteNode, 1); n->v.owner = owner; n->v.desc = desc; n->v.type = type; SLLQueuePush(result.first, result.last, n); result.count += 1; } exit:; return result; } ================================================ FILE: src/elf/elf_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ELF_PARSE_H #define ELF_PARSE_H //////////////////////////////// //~ rjf: Parsed Structure Types typedef struct ELF_Shdr64Array ELF_Shdr64Array; struct ELF_Shdr64Array { U64 count; ELF_Shdr64 *v; }; typedef struct ELF_Phdr64Array ELF_Phdr64Array; struct ELF_Phdr64Array { U64 count; ELF_Phdr64 *v; }; typedef struct ELF_Bin ELF_Bin; struct ELF_Bin { ELF_Hdr64 hdr; Rng1U64 sh_name_range; ELF_Shdr64Array shdrs; ELF_Phdr64Array phdrs; }; typedef struct ELF_GnuDebugLink ELF_GnuDebugLink; struct ELF_GnuDebugLink { String8 path; U32 checksum; }; typedef struct ELF_Note ELF_Note; struct ELF_Note { String8 owner; ELF_NoteType type; String8 desc; }; typedef struct ELF_NoteNode ELF_NoteNode; struct ELF_NoteNode { ELF_Note v; ELF_NoteNode *next; }; typedef struct ELF_NoteList ELF_NoteList; struct ELF_NoteList { U64 count; ELF_NoteNode *first; ELF_NoteNode *last; }; //////////////////////////////// //~ rjf: Parsing Functions //- rjf: top-level binary parsing internal ELF_Bin elf_bin_from_data(Arena *arena, String8 data); //- rjf: extra bin info extraction internal B32 elf_is_dwarf_present_from_bin(String8 data, ELF_Bin *bin); internal String8 elf_name_from_shdr64(String8 raw_data, ELF_Bin *bin, ELF_Shdr64 *shdr); internal U64 elf_base_addr_from_bin(ELF_Bin *bin); internal ELF_GnuDebugLink elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin); internal ELF_NoteList elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine); #endif // ELF_PARSE_H ================================================ FILE: src/eval/eval.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name) E_TokenKindTable: { {Null} {Identifier} {Numeric} {StringLiteral} {CharLiteral} {Symbol} } @table(name basic_string basic_byte_size) // NOTE(rjf): basic_byte_size == 0xFF? => address sized E_TypeKindTable: { {Null "" 0 } {Void "void" 0 } {Handle "HANDLE" 0xFF } {HResult "HRESULT" 4 } {Char8 "char8" 1 } {Char16 "char16" 2 } {Char32 "char32" 4 } {UChar8 "uchar8" 1 } {UChar16 "uchar16" 2 } {UChar32 "uchar32" 4 } {U8 "uint8" 1 } {U16 "uint16" 2 } {U32 "uint32" 4 } {U64 "uint64" 8 } {U128 "uint128" 16 } {U256 "uint256" 32 } {U512 "uint512" 64 } {S8 "int8" 1 } {S16 "int16" 2 } {S32 "int32" 4 } {S64 "int64" 8 } {S128 "int128" 16 } {S256 "int256" 32 } {S512 "int512" 64 } {Bool "bool" 1 } {F16 "float16" 2 } {F32 "float32" 4 } {F32PP "float32PP" 4 } {F48 "float48" 6 } {F64 "float64" 8 } {F80 "float80" 10 } {F128 "float128" 16 } {ComplexF32 "complex_float32" 8 } {ComplexF64 "complex_float64" 16 } {ComplexF80 "complex_float80" 20 } {ComplexF128 "complex_float128" 32 } {Modifier "modifier" 0 } {Ptr "ptr" 0 } {LRef "lref" 0 } {RRef "rref" 0 } {Array "array" 0 } {Function "function" 0 } {Method "method" 0 } {MemberPtr "member_ptr" 0 } {Struct "struct" 0 } {Class "class" 0 } {Union "union" 0 } {Enum "enum" 0 } {Alias "typedef" 0 } {IncompleteStruct "struct" 0 } {IncompleteUnion "union" 0 } {IncompleteClass "class" 0 } {IncompleteEnum "enum" 0 } {Bitfield "bitfield" 0 } {Variadic "variadic" 0 } {Set "set" 0 } {Lens "lens" 0 } {LensSpec "lens_spec" 0 } {MetaExpr "meta_expr" 0 } {MetaDisplayName "meta_display_name" 0 } {MetaDescription "meta_description" 0 } } @table(name op_kind precedence op_pre op_sep op_pos op_chain) E_ExprKindTable: { { Nil Null 0 "" "" "" "" } { Ref Null 0 "" "" "" "" } { ArrayIndex Null 0 "" "[" "]" "" } { MemberAccess Null 0 "" "." "" "" } { Deref UnaryPrefix 2 "*" "" "" "" } { Address UnaryPrefix 2 "&" "" "" "" } { Cast Null 1 "cast(" ")" "" "" } { Sizeof UnaryPrefix 1 "sizeof " "" "" "" } { Typeof UnaryPrefix 1 "typeof " "" "" "" } { Symbolof UnaryPrefix 1 "symbolof " "" "" "" } { ByteSwap UnaryPrefix 1 "bswap " "" "" "" } { Pos UnaryPrefix 2 "+" "" "" "" } { Neg UnaryPrefix 2 "-" "" "" "" } { LogNot UnaryPrefix 2 "!" "" "" "" } { BitNot UnaryPrefix 2 "~" "" "" "" } { Mul Binary 3 "" " * " "" "" } { Div Binary 3 "" " / " "" "" } { Mod Binary 3 "" " % " "" "" } { Add Binary 4 "" " + " "" "" } { Sub Binary 4 "" " - " "" "" } { LShift Binary 5 "" " << " "" "" } { RShift Binary 5 "" " >> " "" "" } { Less Binary 6 "" " < " "" "" } { LsEq Binary 6 "" " <= " "" "" } { Grtr Binary 6 "" " > " "" "" } { GrEq Binary 6 "" " >= " "" "" } { EqEq Binary 7 "" " == " "" "" } { NtEq Binary 7 "" " != " "" "" } { BitAnd Binary 8 "" " & " "" "" } { BitXor Binary 9 "" " ^ " "" "" } { BitOr Binary 10 "" " | " "" "" } { LogAnd Binary 11 "" " && " "" "" } { LogOr Binary 12 "" " || " "" "" } { Ternary Null 0 "" " ? " "" " : "} { Call Null 15 "" "(" ")" ", "} { LeafBytecode Null 0 "" "" "" "" } { LeafStringLiteral Null 0 "" "" "" "" } { LeafU64 Null 0 "" "" "" "" } { LeafF64 Null 0 "" "" "" "" } { LeafF32 Null 0 "" "" "" "" } { LeafIdentifier Null 0 "" "" "" "" } { LeafOffset Null 0 "" "" "" "" } { LeafValue Null 0 "" "" "" "" } { LeafFilePath Null 0 "" "" "" "" } { TypeIdent Null 0 "" "" "" "" } { Ptr Null 0 "" "" "" "" } { Array Null 0 "" "" "" "" } { Func Null 0 "" "" "" "" } { Unsigned Null 0 "unsigned " "" "" "" } { Define Binary 13 "" " = " "" "" } } @table(name display_string) E_InterpretationCodeTable: { { Good "" } { DivideByZero "Cannot divide by zero." } { BadOp "Invalid operation." } { BadOpTypes "Invalid operation types." } { BadMemRead "Failed memory read." } { BadRegRead "Failed register read." } { BadFrameBase "Invalid frame base address." } { BadModuleBase "Invalid module base address." } { BadTLSBase "Invalid thread-local storage base address." } { InsufficientStackSpace "Insufficient evaluation machine stack space." } { MalformedBytecode "Malformed bytecode." } } @enum E_TokenKind: { @expand(E_TokenKindTable a) `$(a.name)`, COUNT, } @data(String8) e_token_kind_strings: { @expand(E_TokenKindTable a) `str8_lit_comp("$(a.name)")` } @enum E_TypeKind: { @expand(E_TypeKindTable a) `$(a.name)`, COUNT, `FirstBasic = E_TypeKind_Void`, `LastBasic = E_TypeKind_ComplexF128`, `FirstInteger = E_TypeKind_Char8`, `LastInteger = E_TypeKind_S512`, `FirstSigned1 = E_TypeKind_Char8`, `LastSigned1 = E_TypeKind_Char32`, `FirstSigned2 = E_TypeKind_S8`, `LastSigned2 = E_TypeKind_S512`, `FirstIncomplete = E_TypeKind_IncompleteStruct`, `LastIncomplete = E_TypeKind_IncompleteEnum`, `FirstMeta = E_TypeKind_MetaExpr`, `LastMeta = E_TypeKind_MetaDescription`, } @data(String8) e_type_kind_basic_string_table: { @expand(E_TypeKindTable a) `str8_lit_comp("$(a.basic_string)")`; } @data(U8) e_type_kind_basic_byte_size_table: { @expand(E_TypeKindTable a) `$(a.basic_byte_size)`; } @enum(U32) E_ExprKind: { @expand(E_ExprKindTable a) `$(a.name)`, COUNT, } @data(String8) e_expr_kind_strings: { @expand(E_ExprKindTable a) `str8_lit_comp("$(a.name)")` } @data(E_OpInfo) e_expr_kind_op_info_table: { @expand(E_ExprKindTable a) `{ E_OpKind_$(a.op_kind), $(a.precedence), str8_lit_comp("$(a.op_pre)"), str8_lit_comp("$(a.op_sep)"), str8_lit_comp("$(a.op_pos)"), str8_lit_comp("$(a.op_chain)") }` } @enum E_InterpretationCode: { @expand(E_InterpretationCodeTable a) `$(a.name)`, COUNT, } @data(String8) e_interpretation_code_display_strings: { @expand(E_InterpretationCodeTable a) `str8_lit_comp("$(a.display_string)")` } ================================================ FILE: src/eval/eval_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "eval/generated/eval.meta.c" //////////////////////////////// //~ rjf: Basic Helpers #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal U64 e_hash_from_string(U64 seed, String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); return result; } //////////////////////////////// //~ rjf: Expr Kind Enum Functions internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind) { RDI_EvalOp result = RDI_EvalOp_Stop; switch(kind) { case E_ExprKind_Neg: result = RDI_EvalOp_Neg; break; case E_ExprKind_LogNot: result = RDI_EvalOp_LogNot; break; case E_ExprKind_BitNot: result = RDI_EvalOp_BitNot; break; case E_ExprKind_Mul: result = RDI_EvalOp_Mul; break; case E_ExprKind_Div: result = RDI_EvalOp_Div; break; case E_ExprKind_Mod: result = RDI_EvalOp_Mod; break; case E_ExprKind_Add: result = RDI_EvalOp_Add; break; case E_ExprKind_Sub: result = RDI_EvalOp_Sub; break; case E_ExprKind_LShift: result = RDI_EvalOp_LShift; break; case E_ExprKind_RShift: result = RDI_EvalOp_RShift; break; case E_ExprKind_Less: result = RDI_EvalOp_Less; break; case E_ExprKind_LsEq: result = RDI_EvalOp_LsEq; break; case E_ExprKind_Grtr: result = RDI_EvalOp_Grtr; break; case E_ExprKind_GrEq: result = RDI_EvalOp_GrEq; break; case E_ExprKind_EqEq: result = RDI_EvalOp_EqEq; break; case E_ExprKind_NtEq: result = RDI_EvalOp_NtEq; break; case E_ExprKind_BitAnd: result = RDI_EvalOp_BitAnd; break; case E_ExprKind_BitXor: result = RDI_EvalOp_BitXor; break; case E_ExprKind_BitOr: result = RDI_EvalOp_BitOr; break; case E_ExprKind_LogAnd: result = RDI_EvalOp_LogAnd; break; case E_ExprKind_LogOr: result = RDI_EvalOp_LogOr; break; } return result; } internal B32 e_expr_kind_is_comparison(E_ExprKind kind) { B32 result = 0; switch(kind) { default:{}break; case E_ExprKind_EqEq: case E_ExprKind_NtEq: case E_ExprKind_Less: case E_ExprKind_Grtr: case E_ExprKind_LsEq: case E_ExprKind_GrEq: { result = 1; }break; } return result; } //////////////////////////////// //~ rjf: Key Type Functions internal B32 e_key_match(E_Key a, E_Key b) { B32 result = (a.u64 == b.u64); return result; } internal E_Key e_key_zero(void) { E_Key key = {0}; return key; } //////////////////////////////// //~ rjf: Type Key Type Functions internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key) { E_TypeKeyNode *n = push_array(arena, E_TypeKeyNode, 1); n->v = key; SLLQueuePush(list->first, list->last, n); list->count += 1; } internal void e_type_key_list_push_front(Arena *arena, E_TypeKeyList *list, E_TypeKey key) { E_TypeKeyNode *n = push_array(arena, E_TypeKeyNode, 1); n->v = key; SLLQueuePushFront(list->first, list->last, n); list->count += 1; } internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src) { E_TypeKeyList dst = {0}; for(E_TypeKeyNode *n = src->first; n != 0; n = n->next) { e_type_key_list_push(arena, &dst, n->v); } return dst; } //////////////////////////////// //~ rjf: Message Functions internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, Rng1U64 range, String8 text) { E_Msg *msg = push_array(arena, E_Msg, 1); SLLQueuePush(msgs->first, msgs->last, msg); msgs->count += 1; msgs->max_kind = Max(kind, msgs->max_kind); msg->kind = kind; msg->range = range; msg->text = text; } internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, Rng1U64 range, char *fmt, ...) { va_list args; va_start(args, fmt); String8 text = push_str8fv(arena, fmt, args); va_end(args); e_msg(arena, msgs, kind, range, text); } internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push) { if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->count += to_push->count; dst->max_kind = Max(dst->max_kind, to_push->max_kind); } else if(to_push->first != 0) { MemoryCopyStruct(dst, to_push); } MemoryZeroStruct(to_push); } internal E_MsgList e_msg_list_copy(Arena *arena, E_MsgList *src) { E_MsgList dst = {0}; for(E_Msg *msg = src->first; msg != 0; msg = msg->next) { e_msg(arena, &dst, msg->kind, msg->range, msg->text); } return dst; } //////////////////////////////// //~ rjf: Space Functions internal E_Space e_space_make(E_SpaceKind kind) { E_Space space = {0}; space.kind = kind; return space; } internal B32 e_space_match(E_Space a, E_Space b) { B32 result = MemoryMatchStruct(&a, &b); return result; } //////////////////////////////// //~ rjf: Map Functions //- rjf: string -> num internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count) { E_String2NumMap map = {0}; map.slots_count = slot_count; map.slots = push_array(arena, E_String2NumMapSlot, map.slots_count); return map; } internal void e_string2num_map_insert(Arena *arena, E_String2NumMap *map, String8 string, U64 num) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; E_String2NumMapNode *existing_node = 0; for(E_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0) && node->num == num) { existing_node = node; break; } } if(existing_node == 0) { E_String2NumMapNode *node = push_array(arena, E_String2NumMapNode, 1); SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next); SLLQueuePush_N(map->first, map->last, node, order_next); node->string = push_str8_copy(arena, string); node->num = num; map->node_count += 1; } } internal U64 e_num_from_string(E_String2NumMap *map, String8 string) { U64 num = 0; if(map->slots_count != 0) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; E_String2NumMapNode *existing_node = 0; for(E_String2NumMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0)) { existing_node = node; break; } } if(existing_node != 0) { num = existing_node->num; } } return num; } internal E_String2NumMapNodeArray e_string2num_map_node_array_from_map(Arena *arena, E_String2NumMap *map) { E_String2NumMapNodeArray result = {0}; result.count = map->node_count; result.v = push_array(arena, E_String2NumMapNode *, result.count); U64 idx = 0; for(E_String2NumMapNode *n = map->first; n != 0; n = n->order_next, idx += 1) { result.v[idx] = n; } return result; } internal int e_string2num_map_node_qsort_compare__num_ascending(E_String2NumMapNode **a, E_String2NumMapNode **b) { int result = 0; if(a[0]->num < b[0]->num) { result = -1; } else if(a[0]->num > b[0]->num) { result = +1; } return result; } internal void e_string2num_map_node_array_sort__in_place(E_String2NumMapNodeArray *array) { quick_sort(array->v, array->count, sizeof(array->v[0]), e_string2num_map_node_qsort_compare__num_ascending); } //- rjf: string -> expr internal E_String2ExprMap e_string2expr_map_make(Arena *arena, U64 slot_count) { E_String2ExprMap map = {0}; map.slots_count = slot_count; map.slots = push_array(arena, E_String2ExprMapSlot, map.slots_count); return map; } internal void e_string2expr_map_insert(Arena *arena, E_String2ExprMap *map, String8 string, E_Expr *expr) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; E_String2ExprMapNode *existing_node = 0; for(E_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0)) { existing_node = node; break; } } if(existing_node == 0) { E_String2ExprMapNode *node = push_array(arena, E_String2ExprMapNode, 1); SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next); node->string = push_str8_copy(arena, string); existing_node = node; existing_node->expr = expr; } } internal void e_string2expr_map_inc_poison(E_String2ExprMap *map, String8 string) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; for(E_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0)) { node->poison_count += 1; break; } } } internal void e_string2expr_map_dec_poison(E_String2ExprMap *map, String8 string) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; for(E_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0) && node->poison_count > 0) { node->poison_count -= 1; break; } } } internal E_Expr * e_string2expr_map_lookup(E_String2ExprMap *map, String8 string) { E_Expr *expr = &e_expr_nil; if(map->slots_count != 0) { U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; E_String2ExprMapNode *existing_node = 0; for(E_String2ExprMapNode *node = map->slots[slot_idx].first; node != 0; node = node->hash_next) { if(str8_match(node->string, string, 0) && node->poison_count == 0) { existing_node = node; break; } } if(existing_node != 0) { expr = existing_node->expr; } } return expr; } //- rjf: string -> type-key internal E_String2TypeKeyMap e_string2typekey_map_make(Arena *arena, U64 slots_count) { E_String2TypeKeyMap map = {0}; map.slots_count = slots_count; map.slots = push_array(arena, E_String2TypeKeySlot, map.slots_count); return map; } internal void e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key) { E_String2TypeKeyNode *n = push_array(arena, E_String2TypeKeyNode, 1); U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n); n->string = push_str8_copy(arena, string); n->key = key; } internal E_TypeKey e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string) { E_TypeKey key = zero_struct; U64 hash = e_hash_from_string(5381, string); U64 slot_idx = hash%map->slots_count; for(E_String2TypeKeyNode *n = map->slots[slot_idx].first; n != 0; n = n->next) { if(str8_match(n->string, string, 0)) { key = n->key; break; } } return key; } //- rjf: auto hooks internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count) { E_AutoHookMap map = {0}; map.slots_count = slots_count; map.slots = push_array(arena, E_AutoHookSlot, map.slots_count); return map; } internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params) { // rjf: get type key E_TypeKey type_key = params->type_key; if(params->type_pattern.size != 0) { E_Parse parse = e_push_parse_from_string(arena, params->type_pattern); type_key = e_type_key_from_expr(parse.expr); } // rjf: extract type pattern E_Pattern pattern = {0}; if(e_type_key_match(e_type_key_zero(), type_key)) { U64 start_string_off = 0; for(U64 off = 0; off <= params->type_pattern.size; off += 1) { U8 byte = (off < params->type_pattern.size ? params->type_pattern.str[off] : 0); if(byte == 0 || byte == '?') { String8 new_part = str8_substr(params->type_pattern, r1u64(start_string_off, off)); if(new_part.size != 0) { E_PatternPart *p = push_array(arena, E_PatternPart, 1); SLLQueuePush(pattern.first_part, pattern.last_part, p); p->string = new_part; pattern.count += 1; } } if(byte == '?') { E_PatternPart *p = push_array(arena, E_PatternPart, 1); SLLQueuePush(pattern.first_part, pattern.last_part, p); pattern.count += 1; if(off+1 < params->type_pattern.size && params->type_pattern.str[off+1] == '{') { off += 2; String8 wildcard_inst_names_string = str8_skip(params->type_pattern, off); wildcard_inst_names_string = str8_prefix(wildcard_inst_names_string, str8_find_needle(wildcard_inst_names_string, 0, str8_lit("}"), 0)); if(wildcard_inst_names_string.size != 0) { Temp scratch = scratch_begin(&arena, 1); U8 wildcard_inst_name_split_char = ','; String8List wildcard_inst_names = str8_split(scratch.arena, wildcard_inst_names_string, &wildcard_inst_name_split_char, 1, 0); for(String8Node *n = wildcard_inst_names.first; n != 0; n = n->next) { str8_list_push(arena, &p->wildcard_inst_names, str8_skip_chop_whitespace(n->string)); } scratch_end(scratch); off += wildcard_inst_names_string.size; } } start_string_off = off+1; } } } // rjf: if the type key is nonzero, *or* we have type patterns, then insert // into map accordingly if(!e_type_key_match(e_type_key_zero(), type_key) || pattern.count != 0) { E_AutoHookNode *node = push_array(arena, E_AutoHookNode, 1); node->type_string = str8_skip_chop_whitespace(e_type_string_from_key(arena, type_key)); node->type_pattern = pattern; node->expr_string = push_str8_copy(arena, params->tag_expr_string); if(!e_type_key_match(e_type_key_zero(), type_key)) { U64 hash = e_hash_from_string(5381, node->type_string); U64 slot_idx = hash%map->slots_count; SLLQueuePush_N(map->slots[slot_idx].first, map->slots[slot_idx].last, node, hash_next); } else { SLLQueuePush_N(map->first_pattern, map->last_pattern, node, pattern_order_next); } } } //////////////////////////////// //~ rjf: Debug-Info-Driven Map Building Functions internal E_String2NumMap * e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) { Temp scratch = scratch_begin(&arena, 1); //- rjf: gather scopes to walk typedef struct Task Task; struct Task { Task *next; RDI_Scope *scope; }; Task *first_task = 0; Task *last_task = 0; //- rjf: voff -> tightest scope RDI_Scope *tightest_scope = 0; { U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; SLLQueuePush(first_task, last_task, task); tightest_scope = scope; } //- rjf: voff-1 -> scope if(voff > 0) { U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff-1); RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); if(scope != tightest_scope) { Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; SLLQueuePush(first_task, last_task, task); } } //- rjf: tightest scope -> walk up the tree & build tasks for each parent scope if(tightest_scope != 0) { RDI_Scope *nil_scope = rdi_element_from_name_idx(rdi, Scopes, 0); for(RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, tightest_scope->parent_scope_idx); scope != 0 && scope != nil_scope; scope = rdi_element_from_name_idx(rdi, Scopes, scope->parent_scope_idx)) { Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; SLLQueuePush(first_task, last_task, task); } } //- rjf: build blank map E_String2NumMap *map = push_array(arena, E_String2NumMap, 1); *map = e_string2num_map_make(arena, 1024); //- rjf: accumulate locals for all tasks for(Task *task = first_task; task != 0; task = task->next) { RDI_Scope *scope = task->scope; if(scope != 0) { U32 local_opl_idx = scope->local_first + scope->local_count; for(U32 local_idx = scope->local_first; local_idx < local_opl_idx; local_idx += 1) { RDI_Local *local_var = rdi_element_from_name_idx(rdi, Locals, local_idx); U64 local_name_size = 0; U8 *local_name_str = rdi_string_from_idx(rdi, local_var->name_string_idx, &local_name_size); String8 name = push_str8_copy(arena, str8(local_name_str, local_name_size)); e_string2num_map_insert(arena, map, name, (U64)local_idx+1); } } } scratch_end(scratch); return map; } internal E_String2NumMap * e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) { //- rjf: voff -> tightest scope U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); RDI_Scope *tightest_scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); //- rjf: tightest scope -> procedure U32 proc_idx = tightest_scope->proc_idx; RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); //- rjf: procedure -> udt U32 udt_idx = procedure->container_idx; RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); //- rjf: build blank map E_String2NumMap *map = push_array(arena, E_String2NumMap, 1); *map = e_string2num_map_make(arena, 64); //- rjf: udt -> fill member map if(!(udt->flags & RDI_UDTFlag_EnumMembers)) { U64 data_member_num = 1; for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { RDI_Member *m = rdi_element_from_name_idx(rdi, Members, member_idx); if(m->kind == RDI_MemberKind_DataField) { String8 name = {0}; name.str = rdi_string_from_idx(rdi, m->name_string_idx, &name.size); e_string2num_map_insert(arena, map, name, data_member_num); data_member_num += 1; } } } return map; } //////////////////////////////// //~ rjf: Cache Creation & Selection internal E_Cache * e_cache_alloc(void) { Arena *arena = arena_alloc(); E_Cache *cache = push_array(arena, E_Cache, 1); cache->arena = arena; cache->arena_eval_start_pos = arena_pos(arena); return cache; } internal void e_cache_release(E_Cache *cache) { arena_release(cache->arena); } internal void e_select_cache(E_Cache *cache) { e_cache = cache; } //////////////////////////////// //~ rjf: Evaluation Phase Markers internal void e_select_base_ctx(E_BaseCtx *ctx) { //- rjf: select base context if(ctx->modules == 0) { ctx->modules = &e_module_nil; } if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; } if(ctx->dbg_infos == 0) { ctx->dbg_infos = &e_dbg_info_nil; } if(ctx->primary_dbg_info == 0) { ctx->primary_dbg_info = &e_dbg_info_nil; } e_base_ctx = ctx; //- rjf: reset the evaluation cache arena_pop_to(e_cache->arena, e_cache->arena_eval_start_pos); e_cache->key_id_gen = 0; e_cache->key_slots_count = 4096; e_cache->key_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->key_slots_count); e_cache->string_slots_count = 4096; e_cache->string_slots = push_array(e_cache->arena, E_CacheSlot, e_cache->string_slots_count); e_cache->free_parent_node = 0; e_cache->top_parent_node = 0; e_cache->cons_id_gen = 0; e_cache->cons_content_slots_count = 256; e_cache->cons_key_slots_count = 256; e_cache->cons_content_slots = push_array(e_cache->arena, E_ConsTypeSlot, e_cache->cons_content_slots_count); e_cache->cons_key_slots = push_array(e_cache->arena, E_ConsTypeSlot, e_cache->cons_key_slots_count); e_cache->member_cache_slots_count = 256; e_cache->member_cache_slots = push_array(e_cache->arena, E_MemberCacheSlot, e_cache->member_cache_slots_count); e_cache->enum_val_cache_slots_count = 256; e_cache->enum_val_cache_slots = push_array(e_cache->arena, E_EnumValCacheSlot, e_cache->enum_val_cache_slots_count); e_cache->type_cache_slots_count = 1024; e_cache->type_cache_slots = push_array(e_cache->arena, E_TypeCacheSlot, e_cache->type_cache_slots_count); e_cache->file_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file"), .irext = E_TYPE_IREXT_FUNCTION_NAME(file), .access = E_TYPE_ACCESS_FUNCTION_NAME(file), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(file), .range= E_TYPE_EXPAND_RANGE_FUNCTION_NAME(file), }); e_cache->folder_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder"), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(folder), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(folder), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder), }); e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_dbg_info->rdi, e_base_ctx->thread_ip_voff); e_cache->used_expr_map = push_array(e_cache->arena, E_UsedExprMap, 1); e_cache->used_expr_map->slots_count = 64; e_cache->used_expr_map->slots = push_array(e_cache->arena, E_UsedExprSlot, e_cache->used_expr_map->slots_count); e_cache->type_auto_hook_cache_map = push_array(e_cache->arena, E_TypeAutoHookCacheMap, 1); e_cache->type_auto_hook_cache_map->slots_count = 256; e_cache->type_auto_hook_cache_map->slots = push_array(e_cache->arena, E_TypeAutoHookCacheSlot, e_cache->type_auto_hook_cache_map->slots_count); e_cache->string_id_gen = 0; e_cache->string_id_map = push_array(e_cache->arena, E_StringIDMap, 1); e_cache->string_id_map->id_slots_count = 1024; e_cache->string_id_map->id_slots = push_array(e_cache->arena, E_StringIDSlot, e_cache->string_id_map->id_slots_count); e_cache->string_id_map->hash_slots_count = 1024; e_cache->string_id_map->hash_slots = push_array(e_cache->arena, E_StringIDSlot, e_cache->string_id_map->hash_slots_count); } internal void e_select_ir_ctx(E_IRCtx *ctx) { if(ctx->regs_map == 0) { ctx->regs_map = &e_string2num_map_nil; } if(ctx->reg_alias_map == 0) { ctx->reg_alias_map = &e_string2num_map_nil; } if(ctx->locals_map == 0) { ctx->locals_map = &e_string2num_map_nil; } if(ctx->member_map == 0) { ctx->member_map = &e_string2num_map_nil; } if(ctx->macro_map == 0) { ctx->macro_map = push_array(e_cache->arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(e_cache->arena, 512); } e_ir_ctx = ctx; } //////////////////////////////// //~ rjf: Context Accessors internal E_DbgInfo * e_dbg_info_from_module(E_Module *module) { E_DbgInfo *result = &e_dbg_info_nil; if(0 < module->dbg_info_num && module->dbg_info_num <= e_base_ctx->dbg_infos_count) { result = &e_base_ctx->dbg_infos[module->dbg_info_num-1]; } return result; } internal E_DbgInfo * e_dbg_info_from_type_key(E_TypeKey type_key) { E_DbgInfo *result = &e_dbg_info_nil; if(type_key.kind == E_TypeKeyKind_Ext && 0 < type_key.u32[2] && type_key.u32[2] <= e_base_ctx->dbg_infos_count) { result = &e_base_ctx->dbg_infos[type_key.u32[2]-1]; } return result; } //////////////////////////////// //~ rjf: Cache Accessing Functions //- rjf: parent key stack internal E_Key e_parent_key_push(E_Key key) { E_Key top = {0}; if(e_cache->top_parent_node != 0) { top = e_cache->top_parent_node->key; } E_CacheParentNode *n = e_cache->free_parent_node; if(n != 0) { SLLStackPop(e_cache->free_parent_node); } else { n = push_array(e_cache->arena, E_CacheParentNode, 1); } SLLStackPush(e_cache->top_parent_node, n); n->key = key; return top; } internal E_Key e_parent_key_pop(void) { E_CacheParentNode *n = e_cache->top_parent_node; SLLStackPop(e_cache->top_parent_node); SLLStackPush(e_cache->free_parent_node, n); E_Key popped = n->key; return popped; } //- rjf: key construction internal E_Key e_key_from_string(String8 string) { E_Key parent_key = {0}; if(e_cache->top_parent_node) { parent_key = e_cache->top_parent_node->key; } U64 hash = e_hash_from_string(parent_key.u64, string); U64 slot_idx = hash%e_cache->string_slots_count; E_CacheSlot *slot = &e_cache->string_slots[slot_idx]; E_CacheNode *node = 0; for(E_CacheNode *n = slot->first; n != 0; n = n->string_next) { if(e_key_match(parent_key, n->bundle.parent_key) && str8_match(n->bundle.string, string, 0) && (n->bundle.interpretation.space.kind == E_SpaceKind_Null || e_space_gen(n->bundle.interpretation.space) == n->bundle.space_gen)) { node = n; break; } } if(node == 0) { e_cache->key_id_gen += 1; E_Key key = {e_cache->key_id_gen}; U64 key_hash = e_hash_from_string(5381, str8_struct(&key)); U64 key_slot_idx = key_hash%e_cache->key_slots_count; E_CacheSlot *key_slot = &e_cache->key_slots[key_slot_idx]; node = push_array(e_cache->arena, E_CacheNode, 1); SLLQueuePush_N(slot->first, slot->last, node, string_next); SLLQueuePush_N(key_slot->first, key_slot->last, node, key_next); node->bundle.key = key; node->bundle.parent_key = parent_key; node->bundle.string = push_str8_copy(e_cache->arena, string); } return node->bundle.key; } internal E_Key e_key_from_stringf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); E_Key result = e_key_from_string(string); va_end(args); scratch_end(scratch); return result; } internal E_Key e_key_from_expr(E_Expr *expr) { Temp scratch = scratch_begin(0, 0); String8 string = e_string_from_expr(scratch.arena, expr, str8_zero()); E_Key key = e_key_from_string(string); scratch_end(scratch); return key; } //- rjf: base key -> node helper internal E_CacheBundle * e_cache_bundle_from_key(E_Key key) { U64 hash = e_hash_from_string(5381, str8_struct(&key)); U64 slot_idx = hash%e_cache->key_slots_count; E_CacheSlot *slot = &e_cache->key_slots[slot_idx]; E_CacheNode *node = 0; for(E_CacheNode *n = slot->first; n != 0; n = n->key_next) { if(e_key_match(n->bundle.key, key)) { node = n; break; } } E_CacheBundle *bundle = &e_cache_bundle_nil; if(node != 0) { bundle = &node->bundle; } return bundle; } //- rjf: bundle -> pipeline stage outputs internal E_Parse e_parse_from_bundle(E_CacheBundle *bundle) { if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Parse)) { bundle->flags |= E_CacheBundleFlag_Parse; bundle->parse = e_push_parse_from_string(e_cache->arena, bundle->string); E_MsgList msgs_copy = e_msg_list_copy(e_cache->arena, &bundle->parse.msgs); e_msg_list_concat_in_place(&bundle->msgs, &msgs_copy); } E_Parse parse = bundle->parse; return parse; } internal E_IRTreeAndType e_irtree_from_bundle(E_CacheBundle *bundle) { if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_IRTree)) { bundle->flags |= E_CacheBundleFlag_IRTree; E_IRTreeAndType parent = e_irtree_from_key(bundle->parent_key); E_Parse parse = e_parse_from_bundle(bundle); ProfScope("irtree generation for '%.*s'", str8_varg(bundle->string)) { bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, &parent, &e_default_identifier_resolution_rule, 0, 0, parse.expr); } E_MsgList msgs_copy = e_msg_list_copy(e_cache->arena, &bundle->irtree.msgs); e_msg_list_concat_in_place(&bundle->msgs, &msgs_copy); } E_IRTreeAndType result = bundle->irtree; return result; } internal String8 e_bytecode_from_bundle(E_CacheBundle *bundle) { if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Bytecode)) { bundle->flags |= E_CacheBundleFlag_Bytecode; Temp scratch = scratch_begin(0, 0); E_IRTreeAndType irtree = e_irtree_from_bundle(bundle); E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree.root); bundle->bytecode = e_bytecode_from_oplist(e_cache->arena, &oplist); scratch_end(scratch); } String8 result = bundle->bytecode; return result; } internal E_Interpretation e_interpretation_from_bundle(E_CacheBundle *bundle) { if(bundle != &e_cache_bundle_nil && !(bundle->flags & E_CacheBundleFlag_Interpret)) { bundle->flags |= E_CacheBundleFlag_Interpret; String8 bytecode = e_bytecode_from_bundle(bundle); E_Interpretation interpret = e_interpret(bytecode); if(E_InterpretationCode_Good < interpret.code && interpret.code < E_InterpretationCode_COUNT) { e_msg(e_cache->arena, &bundle->msgs, E_MsgKind_InterpretationError, r1u64(0, 0), e_interpretation_code_display_strings[interpret.code]); } bundle->interpretation = interpret; bundle->space_gen = e_space_gen(interpret.space); } E_Interpretation interpret = bundle->interpretation; return interpret; } //- rjf: key -> full expression string internal String8 e_full_expr_string_from_key(Arena *arena, E_Key key) { E_CacheBundle *bundle = e_cache_bundle_from_key(key); String8 result = push_str8_copy(arena, bundle->string); if(!e_key_match(bundle->parent_key, e_key_zero())) { Temp scratch = scratch_begin(&arena, 1); //- NOTE(rjf): any individual eval does not contain all information for // reconstructing an entire "flattened" expression string. this is because // one evaluation may be e.g. `$.x`, in the context of `foobar`, and so // the full thing is evaluated as equivalent to `foobar.x`. In that case, // `foobar` is referred to via the "parent key" of the evaluation for // `$.x`. // // because parents may themselves have parents, e.g. `$.x` in the context // of `$` in the context of `foobar`, we need to apply the parent // expression strings to each parent. // // we do this in order, from oldest ancestor to the passed-in evaluation // key, so we gather the fully-resolved string at the end of the chain. //- rjf: gather the entire chain of parents (in order of deepest ancestor -> shallowest) typedef struct ParentResolveTask ParentResolveTask; struct ParentResolveTask { ParentResolveTask *next; E_CacheBundle *bundle; }; ParentResolveTask start_task = {0, bundle}; ParentResolveTask *first_task = &start_task; ParentResolveTask *last_task = first_task; for(ParentResolveTask *t = first_task, *next = 0; t != 0; (t = next, next = 0)) { if(!e_key_match(t->bundle->parent_key, e_key_zero())) { ParentResolveTask *task = push_array(scratch.arena, ParentResolveTask, 1); SLLQueuePushFront(first_task, last_task, task); task->bundle = e_cache_bundle_from_key(t->bundle->parent_key); next = task; } } //- rjf: walk the chain of tasks, from deepest -> shallowest, producing a // more fully resolved string at each step String8 parent_string = {0}; for(ParentResolveTask *t = first_task; t != 0; t = t->next) { E_Parse parse = e_parse_from_bundle(t->bundle); parent_string = e_string_from_expr(scratch.arena, parse.expr, parent_string); } //- rjf: take final string as result result = push_str8_copy(arena, parent_string); scratch_end(scratch); } return result; } //- rjf: comprehensive bundle internal E_Eval e_eval_from_bundle(E_CacheBundle *bundle) { E_Eval eval = { .key = bundle->key, .parent_key= bundle->parent_key, .string = bundle->string, .expr = e_parse_from_bundle(bundle).expr, .irtree = e_irtree_from_bundle(bundle), .bytecode = e_bytecode_from_bundle(bundle), .msgs = bundle->msgs, }; E_Interpretation interpretation = e_interpretation_from_bundle(bundle); eval.code = interpretation.code; eval.value = interpretation.value; eval.space = interpretation.space; return eval; } internal E_Eval e_value_eval_from_eval(E_Eval eval) { ProfBeginFunction(); if(eval.irtree.mode == E_Mode_Offset) { E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind type_kind = e_type_kind_from_key(type_key); if(type_kind == E_TypeKind_Array) { eval.irtree.mode = E_Mode_Value; } else { U64 type_byte_size = e_type_byte_size_from_key(type_key); Rng1U64 value_vaddr_range = r1u64(eval.value.u64, eval.value.u64 + type_byte_size); MemoryZeroStruct(&eval.value); if(!e_type_key_match(type_key, e_type_key_zero()) && type_byte_size <= sizeof(E_Value) && e_space_read(eval.space, &eval.value, value_vaddr_range)) { eval.irtree.mode = E_Mode_Value; // rjf: mask&shift, for bitfields if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64)) { E_Type *type = e_type_from_key(type_key); U64 valid_bits_mask = 0; for(U64 idx = 0; idx < type->count; idx += 1) { valid_bits_mask |= (1ull<> type->off; eval.value.u64 = eval.value.u64 & valid_bits_mask; eval.irtree.type_key = type->direct_type_key; } // rjf: manually sign-extend switch(type_kind) { default: break; case E_TypeKind_Char8: case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break; case E_TypeKind_Char16: case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break; case E_TypeKind_Char32: case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break; } } } } ProfEnd(); return eval; } //- rjf: type key -> auto hooks internal E_AutoHookMatchList e_push_auto_hook_matches_from_type_key(Arena *arena, E_TypeKey type_key) { ProfBeginFunction(); E_AutoHookMatchList matches = {0}; if(e_ir_ctx != 0) { Temp scratch = scratch_begin(&arena, 1); E_AutoHookMap *map = e_ir_ctx->auto_hook_map; String8 type_string = str8_skip_chop_whitespace(e_type_string_from_key(scratch.arena, type_key)); //////////////////////////// //- rjf: gather exact-type-key-matches from the map // if(map != 0 && map->slots_count != 0) { U64 hash = e_hash_from_string(5381, type_string); U64 slot_idx = hash%map->slots_count; for(E_AutoHookNode *n = map->slots[slot_idx].first; n != 0; n = n->hash_next) { if(str8_match(n->type_string, type_string, 0)) { E_AutoHookMatch *match = push_array(arena, E_AutoHookMatch, 1); SLLQueuePush(matches.first, matches.last, match); match->expr = e_parse_from_string(n->expr_string).expr; matches.count += 1; } } } //////////////////////////// //- rjf: gather fuzzy matches from all patterns in the map // if(map != 0 && map->first_pattern != 0) { for(E_AutoHookNode *auto_hook_node = map->first_pattern; auto_hook_node != 0; auto_hook_node = auto_hook_node->pattern_order_next) { //////////////////////// //- rjf: determine if this pattern fits this type's string; gather wildcard instances // E_AutoHookWildcardInst *first_wildcard_inst = 0; E_AutoHookWildcardInst *last_wildcard_inst = 0; B32 fits_this_type_string = 1; { U64 scan_pos = 0; for(E_PatternPart *part = auto_hook_node->type_pattern.first_part; part != 0 && fits_this_type_string; part = part->next) { String8 pattern_string = part->string; //- rjf: skip whitespace for(;scan_pos < type_string.size;) { if(char_is_space(type_string.str[scan_pos])) { scan_pos += 1; } else { break; } } //- rjf: no pattern string -> wildcard. skip wildcard portion if(pattern_string.size == 0) { String8 terminator_pattern_string = part->next ? part->next->string : str8_zero(); U64 brace_nest_depth = 0; U64 paren_nest_depth = 0; U64 angle_nest_depth = 0; U64 brack_nest_depth = 0; U64 start_inst_off = scan_pos; String8Node *wildcard_inst_name_node = part->wildcard_inst_names.first; for(B32 done = 0; !done && scan_pos < type_string.size; scan_pos += 1) { if(0){} else if(type_string.str[scan_pos] == '{') { brace_nest_depth += 1; } else if(type_string.str[scan_pos] == '(') { paren_nest_depth += 1; } else if(type_string.str[scan_pos] == '<') { angle_nest_depth += 1; } else if(type_string.str[scan_pos] == '[') { brack_nest_depth += 1; } else if(type_string.str[scan_pos] == '}' && brace_nest_depth > 0) { brace_nest_depth -= 1; } else if(type_string.str[scan_pos] == ')' && paren_nest_depth > 0) { paren_nest_depth -= 1; } else if(type_string.str[scan_pos] == '>' && angle_nest_depth > 0) { angle_nest_depth -= 1; } else if(type_string.str[scan_pos] == ']' && brack_nest_depth > 0) { brack_nest_depth -= 1; } else if(part->next == 0) { done = 1; scan_pos = type_string.size; } else if(str8_match(terminator_pattern_string, str8_skip(type_string, scan_pos), StringMatchFlag_RightSideSloppy)) { done = 1; } if((type_string.str[scan_pos] == ',' || done) && brace_nest_depth == 0 && paren_nest_depth == 0 && angle_nest_depth == 0 && brack_nest_depth == 0) { String8 wildcard_inst_string = str8_skip_chop_whitespace(str8_substr(type_string, r1u64(start_inst_off, scan_pos))); start_inst_off = scan_pos+1; E_AutoHookWildcardInst *inst = push_array(arena, E_AutoHookWildcardInst, 1); SLLQueuePush(first_wildcard_inst, last_wildcard_inst, inst); inst->name = wildcard_inst_name_node ? wildcard_inst_name_node->string : str8_zero(); inst->inst_expr = e_parse_from_string(wildcard_inst_string).expr; if(wildcard_inst_name_node) { wildcard_inst_name_node = wildcard_inst_name_node->next; } } if(done) { break; } } } //- rjf: pattern string -> find next occurrence. else if(pattern_string.size != 0) { if(!str8_match(str8_substr(type_string, r1u64(scan_pos, scan_pos+pattern_string.size)), pattern_string, 0)) { fits_this_type_string = 0; } else { scan_pos += pattern_string.size; } } } if(fits_this_type_string && scan_pos < type_string.size) { fits_this_type_string = 0; } } //////////////////////// //- rjf: push match if this type fits // if(fits_this_type_string) { E_AutoHookMatch *match = push_array(arena, E_AutoHookMatch, 1); SLLQueuePush(matches.first, matches.last, match); match->expr = e_parse_from_string(auto_hook_node->expr_string).expr; match->first_wildcard_inst = first_wildcard_inst; match->last_wildcard_inst = last_wildcard_inst; matches.count += 1; } } } scratch_end(scratch); } ProfEnd(); return matches; } internal E_AutoHookMatchList e_auto_hook_matches_from_type_key(E_TypeKey type_key) { E_AutoHookMatchList matches = {0}; { U64 hash = e_hash_from_string(5381, str8_struct(&type_key)); U64 slot_idx = hash%e_cache->type_auto_hook_cache_map->slots_count; E_TypeAutoHookCacheNode *node = 0; for(E_TypeAutoHookCacheNode *n = e_cache->type_auto_hook_cache_map->slots[slot_idx].first; n != 0; n = n->next) { if(e_type_key_match(n->key, type_key)) { node = n; } } if(node == 0) { node = push_array(e_cache->arena, E_TypeAutoHookCacheNode, 1); SLLQueuePush(e_cache->type_auto_hook_cache_map->slots[slot_idx].first, e_cache->type_auto_hook_cache_map->slots[slot_idx].last, node); node->key = type_key; node->matches = e_push_auto_hook_matches_from_type_key(e_cache->arena, type_key); } matches = node->matches; } return matches; } //- rjf: string IDs internal U64 e_id_from_string(String8 string) { U64 hash = e_hash_from_string(5381, string); U64 hash_slot_idx = hash%e_cache->string_id_map->hash_slots_count; E_StringIDNode *node = 0; for(E_StringIDNode *n = e_cache->string_id_map->hash_slots[hash_slot_idx].first; n != 0; n = n->hash_next) { if(str8_match(n->string, string, 0)) { node = n; break; } } if(node == 0) { e_cache->string_id_gen += 1; U64 id = e_cache->string_id_gen; U64 id_slot_idx = id%e_cache->string_id_map->id_slots_count; node = push_array(e_cache->arena, E_StringIDNode, 1); SLLQueuePush_N(e_cache->string_id_map->hash_slots[hash_slot_idx].first, e_cache->string_id_map->hash_slots[hash_slot_idx].last, node, hash_next); SLLQueuePush_N(e_cache->string_id_map->id_slots[id_slot_idx].first, e_cache->string_id_map->hash_slots[id_slot_idx].last, node, id_next); node->id = id; node->string = push_str8_copy(e_cache->arena, string); } U64 result = node->id; return result; } internal String8 e_string_from_id(U64 id) { U64 id_slot_idx = id%e_cache->string_id_map->id_slots_count; E_StringIDNode *node = 0; for(E_StringIDNode *n = e_cache->string_id_map->id_slots[id_slot_idx].first; n != 0; n = n->id_next) { if(n->id == id) { node = n; break; } } String8 result = {0}; if(node != 0) { result = node->string; } return result; } //////////////////////////////// //~ rjf: Key Extension Functions internal E_Key e_key_wrap(E_Key key, String8 string) { e_parent_key_push(key); E_Key result = e_key_from_string(string); e_parent_key_pop(); return result; } internal E_Key e_key_wrapf(E_Key key, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); E_Key result = e_key_wrap(key, string); va_end(args); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Eval Info Extraction internal Rng1U64 e_range_from_eval(E_Eval eval) { // rjf: choose base offset U64 base_offset = 0; { E_Eval base_off_eval = eval; if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(base_off_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)))) { base_off_eval = e_value_eval_from_eval(base_off_eval); } base_offset = base_off_eval.value.u64; } // rjf: choose size U64 size = KB(16); { E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind type_kind = e_type_kind_from_key(type_key); if(type_kind == E_TypeKind_Ptr) { E_Eval ptee_eval = e_eval_wrapf(eval, "*$"); U64 ptee_size = e_type_byte_size_from_key(ptee_eval.irtree.type_key); if(ptee_size > 8) { size = ptee_size; } } else if(eval.irtree.mode == E_Mode_Offset) { size = e_type_byte_size_from_key(type_key); } } Rng1U64 result = r1u64(base_offset, base_offset+size); return result; } //////////////////////////////// //~ rjf: Debug Functions internal String8 e_debug_log_from_expr_string(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); char *indent_spaces = " "; String8List strings = {0}; //- rjf: begin expression String8 expr_text = string; str8_list_pushf(scratch.arena, &strings, "`%S`\n", expr_text); //- rjf: parse E_Parse parse = e_push_parse_from_string(scratch.arena, expr_text); { typedef struct Task Task; struct Task { Task *next; E_Expr *expr; S32 indent; }; E_TokenArray tokens = parse.tokens; str8_list_pushf(scratch.arena, &strings, " tokens:\n"); for EachIndex(idx, tokens.count) { E_Token token = tokens.v[idx]; String8 token_string = str8_substr(expr_text, token.range); str8_list_pushf(scratch.arena, &strings, " %S: `%S`\n", e_token_kind_strings[token.kind], token_string); } str8_list_pushf(scratch.arena, &strings, " expr:\n"); Task start_task = {0, parse.expr, 2}; Task *first_task = &start_task; for(Task *t = first_task; t != 0; t = t->next) { E_Expr *expr = t->expr; str8_list_pushf(scratch.arena, &strings, "%.*s%S", (int)t->indent*4, indent_spaces, e_expr_kind_strings[expr->kind]); switch(expr->kind) { default:{}break; case E_ExprKind_LeafU64: { str8_list_pushf(scratch.arena, &strings, " (%I64u)", expr->value.u64); }break; case E_ExprKind_LeafIdentifier: { str8_list_pushf(scratch.arena, &strings, " (`%S`)", expr->string); }break; } str8_list_pushf(scratch.arena, &strings, "\n"); Task *last_task = t; for(E_Expr *child = expr->first; child != &e_expr_nil; child = child->next) { Task *task = push_array(scratch.arena, Task, 1); task->next = last_task->next; last_task->next = task; task->expr = child; task->indent = t->indent+1; last_task = task; } } } //- rjf: type E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, &e_default_identifier_resolution_rule, 0, 0, parse.expr); { str8_list_pushf(scratch.arena, &strings, " type:\n"); S32 indent = 2; for(E_TypeKey type_key = irtree.type_key; !e_type_key_match(e_type_key_zero(), type_key); type_key = e_type_key_direct(type_key), indent += 1) { E_Type *type = e_push_type_from_key(scratch.arena, type_key); str8_list_pushf(scratch.arena, &strings, "%.*s%S\n", (int)indent*4, indent_spaces, e_type_kind_basic_string_table[type->kind]); } } //- rjf: irtree { typedef struct Task Task; struct Task { Task *next; E_IRNode *irnode; S32 indent; }; str8_list_pushf(scratch.arena, &strings, " ir_tree:\n"); Task start_task = {0, irtree.root, 2}; Task *first_task = &start_task; for(Task *t = first_task; t != 0; t = t->next) { E_IRNode *irnode = t->irnode; str8_list_pushf(scratch.arena, &strings, "%.*s", (int)t->indent*4, indent_spaces); switch(irnode->op) { default:{}break; #define X(name) case RDI_EvalOp_##name:{str8_list_pushf(scratch.arena, &strings, #name);}break; RDI_EvalOp_XList #undef X } if(irnode->value.u64 != 0) { str8_list_pushf(scratch.arena, &strings, " (%I64u)", irnode->value.u64); } str8_list_pushf(scratch.arena, &strings, "\n"); Task *last_task = t; for(E_IRNode *child = irnode->first; child != &e_irnode_nil; child = child->next) { Task *task = push_array(scratch.arena, Task, 1); task->next = last_task->next; last_task->next = task; task->irnode = child; task->indent = t->indent+1; last_task = task; } } } str8_list_pushf(scratch.arena, &strings, "\n"); String8 result = str8_list_join(arena, &strings, 0); scratch_end(scratch); return result; } ================================================ FILE: src/eval/eval_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_CORE_H #define EVAL_CORE_H //////////////////////////////// //~ rjf: Evaluation Key Type typedef struct E_Key E_Key; struct E_Key { U64 u64; }; //////////////////////////////// //~ rjf: Messages typedef enum E_MsgKind { E_MsgKind_Null, E_MsgKind_MalformedInput, E_MsgKind_MissingInfo, E_MsgKind_ResolutionFailure, E_MsgKind_InterpretationError, E_MsgKind_COUNT } E_MsgKind; typedef struct E_Msg E_Msg; struct E_Msg { E_Msg *next; E_MsgKind kind; Rng1U64 range; String8 text; }; typedef struct E_MsgList E_MsgList; struct E_MsgList { E_Msg *first; E_Msg *last; E_MsgKind max_kind; U64 count; }; //////////////////////////////// //~ rjf: Register-Sized Value Type typedef union E_Value E_Value; union E_Value { U512 u512; U256 u256; U128 u128; U64 u64; U32 u32; U16 u16; U8 u8; S64 s64; S32 s32; S16 s16; S8 s8; F64 f64; F32 f32; }; //////////////////////////////// //~ rjf: Bytecode Operation Types enum { E_IRExtKind_Bytecode = RDI_EvalOp_COUNT, E_IRExtKind_SetSpace, E_IRExtKind_COUNT }; typedef struct E_Op E_Op; struct E_Op { E_Op *next; RDI_EvalOp opcode; E_Value value; String8 string; }; typedef struct E_OpList E_OpList; struct E_OpList { E_Op *first; E_Op *last; U64 op_count; U64 encoded_size; }; //////////////////////////////// //~ rjf: Operator Info typedef enum E_OpKind { E_OpKind_Null, E_OpKind_UnaryPrefix, E_OpKind_Binary, } E_OpKind; typedef struct E_OpInfo E_OpInfo; struct E_OpInfo { E_OpKind kind; S64 precedence; String8 pre; String8 sep; String8 post; String8 chain; }; //////////////////////////////// //~ rjf: Evaluation Spaces // // NOTE(rjf): Evaluations occur within the context of a "space". Each "space" // refers to a different offset/address-space, but it's a bit looser of a // concept than just address space, since it can also refer to offsets into // a register block, and it is also used to refer to spaces of unique IDs for // key-value stores, e.g. for information in the debugger. // // Effectively, when considering the result of an evaluation, you use the // value for understanding a key *into* a space, e.g. 1+2 -> 3, in a null // space, or &foo, in the space of PID: 1234. typedef U64 E_SpaceKind; enum { E_SpaceKind_Null, E_SpaceKind_File, E_SpaceKind_FileSystem, E_SpaceKind_HashStoreKey, E_SpaceKind_FirstUserDefined, }; typedef struct E_Space E_Space; struct E_Space { E_SpaceKind kind; union { U64 u64s[3]; struct { U64 u64_0; U128 u128; }; }; }; //////////////////////////////// //~ rjf: Implicit Type Graph Key Types typedef enum E_TypeKeyKind { E_TypeKeyKind_Null, E_TypeKeyKind_Basic, E_TypeKeyKind_Ext, E_TypeKeyKind_Cons, E_TypeKeyKind_Reg, E_TypeKeyKind_RegAlias, } E_TypeKeyKind; typedef struct E_TypeKey E_TypeKey; struct E_TypeKey { E_TypeKeyKind kind; U32 u32[3]; // [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias) // [1] -> Type Index In Debug Info (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons) // [2] -> Debug Info Number (Ext) }; typedef struct E_TypeKeyNode E_TypeKeyNode; struct E_TypeKeyNode { E_TypeKeyNode *next; E_TypeKey v; }; typedef struct E_TypeKeyList E_TypeKeyList; struct E_TypeKeyList { E_TypeKeyNode *first; E_TypeKeyNode *last; U64 count; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/eval.meta.h" //////////////////////////////// //~ rjf: Token Types typedef struct E_Token E_Token; struct E_Token { E_TokenKind kind; Rng1U64 range; }; typedef struct E_TokenChunkNode E_TokenChunkNode; struct E_TokenChunkNode { E_TokenChunkNode *next; E_Token *v; U64 count; U64 cap; }; typedef struct E_TokenChunkList E_TokenChunkList; struct E_TokenChunkList { E_TokenChunkNode *first; E_TokenChunkNode *last; U64 node_count; U64 total_count; }; typedef struct E_TokenArray E_TokenArray; struct E_TokenArray { E_Token *v; U64 count; }; //////////////////////////////// //~ rjf: Evaluation Modes typedef enum E_Mode { E_Mode_Null, E_Mode_Value, E_Mode_Offset, } E_Mode; //////////////////////////////// //~ rjf: Expression Tree Types typedef struct E_Expr E_Expr; struct E_Expr { E_Expr *first; E_Expr *last; E_Expr *next; E_Expr *prev; E_Expr *ref; Rng1U64 range; E_ExprKind kind; E_Mode mode; E_Space space; E_TypeKey type_key; E_Value value; String8 string; String8 qualifier; String8 bytecode; }; typedef struct E_ExprChain E_ExprChain; struct E_ExprChain { E_Expr *first; E_Expr *last; }; typedef struct E_ExprNode E_ExprNode; struct E_ExprNode { E_ExprNode *next; E_Expr *v; }; typedef struct E_ExprList E_ExprList; struct E_ExprList { E_ExprNode *first; E_ExprNode *last; U64 count; }; typedef struct E_Parse E_Parse; struct E_Parse { E_TokenArray tokens; E_Token *last_token; E_Expr *expr; E_Expr *last_expr; E_MsgList msgs; }; //////////////////////////////// //~ rjf: IR Tree Types typedef struct E_IRNode E_IRNode; struct E_IRNode { E_IRNode *first; E_IRNode *last; E_IRNode *next; RDI_EvalOp op; E_Space space; String8 string; E_Value value; }; typedef struct E_IRTreeAndType E_IRTreeAndType; struct E_IRTreeAndType { E_IRNode *root; E_TypeKey type_key; void *user_data; E_Mode mode; B32 auto_hook; E_MsgList msgs; E_IRTreeAndType *prev; }; //////////////////////////////// //~ rjf: Bytecode Interpretation Types typedef struct E_Interpretation E_Interpretation; struct E_Interpretation { E_Value value; E_Space space; E_InterpretationCode code; }; //////////////////////////////// //~ rjf: Evaluation Artifact Bundle typedef struct E_Eval E_Eval; struct E_Eval { E_Key key; E_Key parent_key; String8 string; E_Expr *expr; E_IRTreeAndType irtree; String8 bytecode; E_InterpretationCode code; E_Value value; E_Space space; E_MsgList msgs; }; //////////////////////////////// //~ rjf: Full Extracted Type Information Types typedef enum E_MemberKind { E_MemberKind_Null, E_MemberKind_DataField, E_MemberKind_StaticData, E_MemberKind_Method, E_MemberKind_StaticMethod, E_MemberKind_VirtualMethod, E_MemberKind_VTablePtr, E_MemberKind_Base, E_MemberKind_VirtualBase, E_MemberKind_NestedType, E_MemberKind_Padding, E_MemberKind_COUNT } E_MemberKind; typedef U32 E_TypeFlags; enum { E_TypeFlag_Const = (1<<0), E_TypeFlag_Volatile = (1<<1), E_TypeFlag_Restrict = (1<<2), E_TypeFlag_IsPlainText = (1<<3), E_TypeFlag_IsCodeText = (1<<4), E_TypeFlag_IsPathText = (1<<5), E_TypeFlag_IsNotText = (1<<6), E_TypeFlag_IsNotEditable = (1<<7), E_TypeFlag_EditableChildren = (1<<8), E_TypeFlag_InheritedByMembers = (1<<9), E_TypeFlag_InheritedByElements = (1<<10), E_TypeFlag_ArrayLikeExpansion = (1<<11), E_TypeFlag_StubSingleLineExpansion = (1<<12), }; typedef struct E_Member E_Member; struct E_Member { E_MemberKind kind; E_TypeKey type_key; String8 name; U64 off; E_TypeKeyList inheritance_key_chain; }; typedef struct E_MemberNode E_MemberNode; struct E_MemberNode { E_MemberNode *next; E_Member v; }; typedef struct E_MemberList E_MemberList; struct E_MemberList { E_MemberNode *first; E_MemberNode *last; U64 count; }; typedef struct E_MemberArray E_MemberArray; struct E_MemberArray { E_Member *v; U64 count; }; typedef struct E_EnumVal E_EnumVal; struct E_EnumVal { String8 name; U64 val; }; typedef struct E_EnumValNode E_EnumValNode; struct E_EnumValNode { E_EnumValNode *next; E_EnumVal v; }; typedef struct E_EnumValList E_EnumValList; struct E_EnumValList { E_EnumValNode *first; E_EnumValNode *last; U64 count; }; typedef struct E_EnumValArray E_EnumValArray; struct E_EnumValArray { E_EnumVal *v; U64 count; }; typedef struct E_IRExt E_IRExt; struct E_IRExt { void *user_data; }; typedef struct E_TypeExpandInfo E_TypeExpandInfo; struct E_TypeExpandInfo { void *user_data; U64 expr_count; }; #define E_TYPE_IREXT_FUNCTION_SIG(name) E_IRExt name(Arena *arena, E_Expr *expr, E_IRTreeAndType *irtree) #define E_TYPE_IREXT_FUNCTION_NAME(name) e_type_irext__##name #define E_TYPE_IREXT_FUNCTION_DEF(name) internal E_TYPE_IREXT_FUNCTION_SIG(E_TYPE_IREXT_FUNCTION_NAME(name)) typedef E_TYPE_IREXT_FUNCTION_SIG(E_TypeIRExtFunctionType); #define E_TYPE_ACCESS_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_IRTreeAndType *overridden, E_Expr *expr, E_IRTreeAndType *lhs_irtree) #define E_TYPE_ACCESS_FUNCTION_NAME(name) e_type_access__##name #define E_TYPE_ACCESS_FUNCTION_DEF(name) internal E_TYPE_ACCESS_FUNCTION_SIG(E_TYPE_ACCESS_FUNCTION_NAME(name)) typedef E_TYPE_ACCESS_FUNCTION_SIG(E_TypeAccessFunctionType); #define E_TYPE_EXPAND_INFO_FUNCTION_SIG(name) E_TypeExpandInfo name(Arena *arena, E_Eval eval, String8 filter) #define E_TYPE_EXPAND_INFO_FUNCTION_NAME(name) e_type_expand_info__##name #define E_TYPE_EXPAND_INFO_FUNCTION_DEF(name) internal E_TYPE_EXPAND_INFO_FUNCTION_SIG(E_TYPE_EXPAND_INFO_FUNCTION_NAME(name)) typedef E_TYPE_EXPAND_INFO_FUNCTION_SIG(E_TypeExpandInfoFunctionType); #define E_TYPE_EXPAND_RANGE_FUNCTION_SIG(name) void name(Arena *arena, void *user_data, E_Eval eval, String8 filter, Rng1U64 idx_range, E_Eval *evals_out) #define E_TYPE_EXPAND_RANGE_FUNCTION_NAME(name) e_type_expand_range__##name #define E_TYPE_EXPAND_RANGE_FUNCTION_DEF(name) internal E_TYPE_EXPAND_RANGE_FUNCTION_SIG(E_TYPE_EXPAND_RANGE_FUNCTION_NAME(name)) typedef E_TYPE_EXPAND_RANGE_FUNCTION_SIG(E_TypeExpandRangeFunctionType); #define E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(void *user_data, U64 num) #define E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name) e_type_expand_id_from_num__##name #define E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(name) internal E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_SIG(E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name)) typedef E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_SIG(E_TypeExpandIDFromNumFunctionType); #define E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(void *user_data, U64 id) #define E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name) e_type_expand_num_from_id__##name #define E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(name) internal E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_SIG(E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name)) typedef E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_SIG(E_TypeExpandNumFromIDFunctionType); typedef struct E_TypeExpandRule E_TypeExpandRule; struct E_TypeExpandRule { E_TypeExpandInfoFunctionType *info; E_TypeExpandRangeFunctionType *range; E_TypeExpandIDFromNumFunctionType *id_from_num; E_TypeExpandNumFromIDFunctionType *num_from_id; }; typedef struct E_Type E_Type; struct E_Type { E_TypeKind kind; E_TypeFlags flags; String8 name; U64 byte_size; U64 count; U64 depth; U32 off; Arch arch; E_TypeKey direct_type_key; E_TypeKey owner_type_key; E_TypeKey *param_type_keys; E_Member *members; E_EnumVal *enum_vals; E_Expr **args; E_TypeIRExtFunctionType *irext; E_TypeAccessFunctionType *access; E_TypeExpandRule expand; }; //////////////////////////////// //~ rjf: Constructed Type Types typedef struct E_ConsTypeParams E_ConsTypeParams; struct E_ConsTypeParams { Arch arch; E_TypeKind kind; E_TypeFlags flags; String8 name; E_TypeKey direct_key; U64 count; U64 depth; E_Member *members; E_EnumVal *enum_vals; E_Expr **args; E_TypeIRExtFunctionType *irext; E_TypeAccessFunctionType *access; E_TypeExpandRule expand; }; typedef struct E_ConsTypeNode E_ConsTypeNode; struct E_ConsTypeNode { E_ConsTypeNode *key_next; E_ConsTypeNode *content_next; E_TypeKey key; E_ConsTypeParams params; U64 byte_size; }; typedef struct E_ConsTypeSlot E_ConsTypeSlot; struct E_ConsTypeSlot { E_ConsTypeNode *first; E_ConsTypeNode *last; }; //////////////////////////////// //~ rjf: Debug Info typedef struct E_DbgInfo E_DbgInfo; struct E_DbgInfo { DI_Key dbgi_key; RDI_Parsed *rdi; }; //////////////////////////////// //~ rjf: Modules typedef struct E_Module E_Module; struct E_Module { Rng1U64 vaddr_range; U32 dbg_info_num; Arch arch; E_Space space; }; //////////////////////////////// //~ rjf: String -> Num typedef struct E_String2NumMapNode E_String2NumMapNode; struct E_String2NumMapNode { E_String2NumMapNode *order_next; E_String2NumMapNode *hash_next; String8 string; U64 num; }; typedef struct E_String2NumMapNodeArray E_String2NumMapNodeArray; struct E_String2NumMapNodeArray { E_String2NumMapNode **v; U64 count; }; typedef struct E_String2NumMapSlot E_String2NumMapSlot; struct E_String2NumMapSlot { E_String2NumMapNode *first; E_String2NumMapNode *last; }; typedef struct E_String2NumMap E_String2NumMap; struct E_String2NumMap { U64 slots_count; U64 node_count; E_String2NumMapSlot *slots; E_String2NumMapNode *first; E_String2NumMapNode *last; }; //////////////////////////////// //~ rjf: String -> Expr typedef struct E_String2ExprMapNode E_String2ExprMapNode; struct E_String2ExprMapNode { E_String2ExprMapNode *hash_next; String8 string; E_Expr *expr; U64 poison_count; }; typedef struct E_String2ExprMapSlot E_String2ExprMapSlot; struct E_String2ExprMapSlot { E_String2ExprMapNode *first; E_String2ExprMapNode *last; }; typedef struct E_String2ExprMap E_String2ExprMap; struct E_String2ExprMap { U64 slots_count; E_String2ExprMapSlot *slots; }; //////////////////////////////// //~ rjf: String -> Type Key Map Data Structure typedef struct E_String2TypeKeyNode E_String2TypeKeyNode; struct E_String2TypeKeyNode { E_String2TypeKeyNode *next; String8 string; E_TypeKey key; }; typedef struct E_String2TypeKeySlot E_String2TypeKeySlot; struct E_String2TypeKeySlot { E_String2TypeKeyNode *first; E_String2TypeKeyNode *last; }; typedef struct E_String2TypeKeyMap E_String2TypeKeyMap; struct E_String2TypeKeyMap { U64 slots_count; E_String2TypeKeySlot *slots; }; //////////////////////////////// //~ rjf: Type Pattern -> Hook Key Data Structure (Type Views) typedef struct E_PatternPart E_PatternPart; struct E_PatternPart { E_PatternPart *next; String8 string; String8List wildcard_inst_names; }; typedef struct E_Pattern E_Pattern; struct E_Pattern { E_PatternPart *first_part; E_PatternPart *last_part; U64 count; }; typedef struct E_AutoHookWildcardInst E_AutoHookWildcardInst; struct E_AutoHookWildcardInst { E_AutoHookWildcardInst *next; String8 name; E_Expr *inst_expr; }; typedef struct E_AutoHookMatch E_AutoHookMatch; struct E_AutoHookMatch { E_AutoHookMatch *next; E_Expr *expr; E_AutoHookWildcardInst *first_wildcard_inst; E_AutoHookWildcardInst *last_wildcard_inst; }; typedef struct E_AutoHookMatchList E_AutoHookMatchList; struct E_AutoHookMatchList { E_AutoHookMatch *first; E_AutoHookMatch *last; U64 count; }; typedef struct E_AutoHookNode E_AutoHookNode; struct E_AutoHookNode { E_AutoHookNode *hash_next; E_AutoHookNode *pattern_order_next; String8 type_string; E_Pattern type_pattern; String8 expr_string; }; typedef struct E_AutoHookSlot E_AutoHookSlot; struct E_AutoHookSlot { E_AutoHookNode *first; E_AutoHookNode *last; }; typedef struct E_AutoHookMap E_AutoHookMap; struct E_AutoHookMap { U64 slots_count; E_AutoHookSlot *slots; E_AutoHookNode *first_pattern; E_AutoHookNode *last_pattern; }; typedef struct E_AutoHookParams E_AutoHookParams; struct E_AutoHookParams { E_TypeKey type_key; String8 type_pattern; String8 tag_expr_string; }; //////////////////////////////// //~ rjf: Evaluation Context typedef U64 E_SpaceGenFunction(E_Space space); typedef B32 E_SpaceRWFunction(E_Space space, void *out, Rng1U64 offset_range); //- rjf: base context typedef struct E_BaseCtx E_BaseCtx; struct E_BaseCtx { // rjf: instruction pointer info U64 thread_ip_vaddr; U64 thread_ip_voff; E_Space thread_reg_space; Arch thread_arch; U64 thread_unwind_count; // rjf: debug infos E_DbgInfo *dbg_infos; U64 dbg_infos_count; E_DbgInfo *primary_dbg_info; // rjf: modules E_Module *modules; U64 modules_count; E_Module *primary_module; // rjf: space hooks E_SpaceGenFunction *space_gen; E_SpaceRWFunction *space_read; E_SpaceRWFunction *space_write; }; //- rjf: ir generation context typedef struct E_IRCtx E_IRCtx; struct E_IRCtx { E_String2NumMap *regs_map; E_String2NumMap *reg_alias_map; E_String2NumMap *locals_map; // (within `primary_module`) E_String2NumMap *member_map; // (within `primary_module`) E_String2ExprMap *macro_map; E_AutoHookMap *auto_hook_map; }; //////////////////////////////// //~ rjf: Core Evaluation Cache Types //- rjf: unpacked type cache typedef struct E_TypeCacheNode E_TypeCacheNode; struct E_TypeCacheNode { E_TypeCacheNode *next; E_TypeKey key; E_Type *type; }; typedef struct E_TypeCacheSlot E_TypeCacheSlot; struct E_TypeCacheSlot { E_TypeCacheNode *first; E_TypeCacheNode *last; }; //- rjf: member lookup cache types typedef struct E_MemberHashNode E_MemberHashNode; struct E_MemberHashNode { E_MemberHashNode *next; U64 member_idx; }; typedef struct E_MemberHashSlot E_MemberHashSlot; struct E_MemberHashSlot { E_MemberHashNode *first; E_MemberHashNode *last; }; typedef struct E_MemberFilterNode E_MemberFilterNode; struct E_MemberFilterNode { E_MemberFilterNode *next; String8 filter; E_MemberArray members_filtered; }; typedef struct E_MemberFilterSlot E_MemberFilterSlot; struct E_MemberFilterSlot { E_MemberFilterNode *first; E_MemberFilterNode *last; }; typedef struct E_MemberCacheNode E_MemberCacheNode; struct E_MemberCacheNode { E_MemberCacheNode *next; E_TypeKey key; E_MemberArray members; U64 member_hash_slots_count; E_MemberHashSlot *member_hash_slots; U64 member_filter_slots_count; E_MemberFilterSlot *member_filter_slots; }; typedef struct E_MemberCacheSlot E_MemberCacheSlot; struct E_MemberCacheSlot { E_MemberCacheNode *first; E_MemberCacheNode *last; }; //- rjf: enum val lookup cache types typedef struct E_EnumValHashNode E_EnumValHashNode; struct E_EnumValHashNode { E_EnumValHashNode *next; U64 val_idx; }; typedef struct E_EnumValHashSlot E_EnumValHashSlot; struct E_EnumValHashSlot { E_EnumValHashNode *first; E_EnumValHashNode *last; }; typedef struct E_EnumValFilterNode E_EnumValFilterNode; struct E_EnumValFilterNode { E_EnumValFilterNode *next; String8 filter; E_EnumValArray vals_filtered; }; typedef struct E_EnumValFilterSlot E_EnumValFilterSlot; struct E_EnumValFilterSlot { E_EnumValFilterNode *first; E_EnumValFilterNode *last; }; typedef struct E_EnumValCacheNode E_EnumValCacheNode; struct E_EnumValCacheNode { E_EnumValCacheNode *next; E_TypeKey key; U64 val_hash_slots_count; E_EnumValHashSlot *val_hash_slots; U64 val_filter_slots_count; E_EnumValFilterSlot *val_filter_slots; }; typedef struct E_EnumValCacheSlot E_EnumValCacheSlot; struct E_EnumValCacheSlot { E_EnumValCacheNode *first; E_EnumValCacheNode *last; }; //- rjf: used expression map typedef struct E_UsedExprNode E_UsedExprNode; struct E_UsedExprNode { E_UsedExprNode *next; E_UsedExprNode *prev; E_Expr *expr; }; typedef struct E_UsedExprSlot E_UsedExprSlot; struct E_UsedExprSlot { E_UsedExprNode *first; E_UsedExprNode *last; }; typedef struct E_UsedExprMap E_UsedExprMap; struct E_UsedExprMap { U64 slots_count; E_UsedExprSlot *slots; }; //- rjf: type key -> auto hook expression list cache typedef struct E_TypeAutoHookCacheNode E_TypeAutoHookCacheNode; struct E_TypeAutoHookCacheNode { E_TypeAutoHookCacheNode *next; E_TypeKey key; E_AutoHookMatchList matches; }; typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot; struct E_TypeAutoHookCacheSlot { E_TypeAutoHookCacheNode *first; E_TypeAutoHookCacheNode *last; }; typedef struct E_TypeAutoHookCacheMap E_TypeAutoHookCacheMap; struct E_TypeAutoHookCacheMap { U64 slots_count; E_TypeAutoHookCacheSlot *slots; }; //- rjf: string ID cache typedef struct E_StringIDNode E_StringIDNode; struct E_StringIDNode { E_StringIDNode *hash_next; E_StringIDNode *id_next; U64 id; String8 string; }; typedef struct E_StringIDSlot E_StringIDSlot; struct E_StringIDSlot { E_StringIDNode *first; E_StringIDNode *last; }; typedef struct E_StringIDMap E_StringIDMap; struct E_StringIDMap { U64 id_slots_count; E_StringIDSlot *id_slots; U64 hash_slots_count; E_StringIDSlot *hash_slots; }; //- rjf: cache evaluation bundles typedef U32 E_CacheBundleFlags; enum { E_CacheBundleFlag_Parse = (1<<0), E_CacheBundleFlag_IRTree = (1<<1), E_CacheBundleFlag_Bytecode = (1<<2), E_CacheBundleFlag_Interpret = (1<<3), }; typedef struct E_CacheBundle E_CacheBundle; struct E_CacheBundle { E_CacheBundleFlags flags; E_Key key; E_Key parent_key; String8 string; E_Parse parse; E_IRTreeAndType irtree; String8 bytecode; E_Interpretation interpretation; U64 space_gen; E_MsgList msgs; }; typedef struct E_CacheNode E_CacheNode; struct E_CacheNode { E_CacheNode *string_next; E_CacheNode *key_next; E_CacheBundle bundle; }; typedef struct E_CacheLookup E_CacheLookup; struct E_CacheLookup { E_CacheNode *node; U64 hash; }; typedef struct E_CacheSlot E_CacheSlot; struct E_CacheSlot { E_CacheNode *first; E_CacheNode *last; }; //- rjf: parent stack typedef struct E_CacheParentNode E_CacheParentNode; struct E_CacheParentNode { E_CacheParentNode *next; E_Key key; }; //- rjf: main cache state type typedef struct E_Cache E_Cache; struct E_Cache { //- rjf: root arena Arena *arena; U64 arena_eval_start_pos; //- rjf: key ID generation counter U64 key_id_gen; //- rjf: key -> bundle, string -> bundle tables U64 key_slots_count; E_CacheSlot *key_slots; U64 string_slots_count; E_CacheSlot *string_slots; //- rjf: parent stack E_CacheParentNode *top_parent_node; E_CacheParentNode *free_parent_node; //- rjf: unpacked context RDI_Procedure *thread_ip_procedure; //- rjf: [types] JIT-constructed types tables U64 cons_id_gen; U64 cons_content_slots_count; U64 cons_key_slots_count; E_ConsTypeSlot *cons_content_slots; E_ConsTypeSlot *cons_key_slots; //- rjf: [types] build-in constructed type keys E_TypeKey file_type_key; E_TypeKey folder_type_key; //- rjf: [types] member cache table U64 member_cache_slots_count; E_MemberCacheSlot *member_cache_slots; //- rjf: [types] enum val cache table U64 enum_val_cache_slots_count; E_EnumValCacheSlot *enum_val_cache_slots; //- rjf: [types] unpacked type cache U64 type_cache_slots_count; E_TypeCacheSlot *type_cache_slots; //- rjf: [ir] ir gen options B32 disallow_autohooks; B32 disallow_chained_fastpaths; E_AutoHookWildcardInst *first_wildcard_inst; E_AutoHookWildcardInst *last_wildcard_inst; //- rjf: [ir] ir caches E_UsedExprMap *used_expr_map; E_TypeAutoHookCacheMap *type_auto_hook_cache_map; //- rjf: [ir] string ID cache U64 string_id_gen; E_StringIDMap *string_id_map; }; //////////////////////////////// //~ rjf: Generated Code #include "eval/generated/eval.meta.h" //////////////////////////////// //~ rjf: Globals read_only global E_String2NumMap e_string2num_map_nil = {0}; read_only global E_String2ExprMap e_string2expr_map_nil = {0}; read_only global E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil}; read_only global E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil}; read_only global E_Eval e_eval_nil = {{0}, {0}, {0}, &e_expr_nil, {&e_irnode_nil}}; read_only global E_DbgInfo e_dbg_info_nil = {{0}, &rdi_parsed_nil}; read_only global E_Module e_module_nil = {0}; read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}}; thread_static E_BaseCtx *e_base_ctx = 0; thread_static E_IRCtx *e_ir_ctx = 0; thread_static E_Cache *e_cache = 0; //////////////////////////////// //~ rjf: Basic Helpers internal U64 e_hash_from_string(U64 seed, String8 string); #define e_value_u64(v) (E_Value){.u64 = (v)} //////////////////////////////// //~ rjf: Expr Kind Enum Functions internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind); internal B32 e_expr_kind_is_comparison(E_ExprKind kind); //////////////////////////////// //~ rjf: Key Type Functions internal B32 e_key_match(E_Key a, E_Key b); internal E_Key e_key_zero(void); //////////////////////////////// //~ rjf: Type Key Type Functions internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key); internal void e_type_key_list_push_front(Arena *arena, E_TypeKeyList *list, E_TypeKey key); internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src); //////////////////////////////// //~ rjf: Message Functions internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, Rng1U64 range, String8 text); internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, Rng1U64 range, char *fmt, ...); internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push); internal E_MsgList e_msg_list_copy(Arena *arena, E_MsgList *src); //////////////////////////////// //~ rjf: Space Functions internal E_Space e_space_make(E_SpaceKind kind); internal B32 e_space_match(E_Space a, E_Space b); //////////////////////////////// //~ rjf: Map Functions //- rjf: string -> num internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count); internal void e_string2num_map_insert(Arena *arena, E_String2NumMap *map, String8 string, U64 num); internal U64 e_num_from_string(E_String2NumMap *map, String8 string); internal E_String2NumMapNodeArray e_string2num_map_node_array_from_map(Arena *arena, E_String2NumMap *map); internal int e_string2num_map_node_qsort_compare__num_ascending(E_String2NumMapNode **a, E_String2NumMapNode **b); internal void e_string2num_map_node_array_sort__in_place(E_String2NumMapNodeArray *array); //- rjf: string -> expr internal E_String2ExprMap e_string2expr_map_make(Arena *arena, U64 slot_count); internal void e_string2expr_map_insert(Arena *arena, E_String2ExprMap *map, String8 string, E_Expr *expr); internal void e_string2expr_map_inc_poison(E_String2ExprMap *map, String8 string); internal void e_string2expr_map_dec_poison(E_String2ExprMap *map, String8 string); internal E_Expr *e_string2expr_map_lookup(E_String2ExprMap *map, String8 string); //- rjf: string -> type-key internal E_String2TypeKeyMap e_string2typekey_map_make(Arena *arena, U64 slots_count); internal void e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key); internal E_TypeKey e_string2typekey_map_lookup(E_String2TypeKeyMap *map, String8 string); //- rjf: auto hooks internal E_AutoHookMap e_auto_hook_map_make(Arena *arena, U64 slots_count); internal void e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams *params); #define e_auto_hook_map_insert_new(arena, map, ...) e_auto_hook_map_insert_new_((arena), (map), &(E_AutoHookParams){.type_key = zero_struct, __VA_ARGS__}) //////////////////////////////// //~ rjf: Debug-Info-Driven Map Building Functions internal E_String2NumMap *e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff); internal E_String2NumMap *e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff); //////////////////////////////// //~ rjf: Cache Creation & Selection internal E_Cache *e_cache_alloc(void); internal void e_cache_release(E_Cache *cache); internal void e_select_cache(E_Cache *cache); //////////////////////////////// //~ rjf: Evaluation Phase Markers internal void e_select_base_ctx(E_BaseCtx *ctx); internal void e_select_ir_ctx(E_IRCtx *ctx); //////////////////////////////// //~ rjf: Context Accessors internal E_DbgInfo *e_dbg_info_from_module(E_Module *module); internal E_DbgInfo *e_dbg_info_from_type_key(E_TypeKey type_key); //////////////////////////////// //~ rjf: Base Cache Accessing Functions // // The cache uses a unique keying mechanism to refer to some evaluation at // many layers of analysis. // // key // ________________________________________________ // / / | \ // text -> expression -> ir tree and type -> interpretation result // // Each one of these calls refers to one stage in this pipeline. The cache will // only compute what is needed on-demand. If you ask for the full evaluation, // which is a bundle of artifacts at all layers of analysis, then all stages // will be computed. // // One wrinkle here is that the IR tree generation stage is implicitly // parameterized by the "overridden" IR tree - this is to enable "parent // expressions", e.g. `$.x`, or simply `x` assuming `foo` has such a member, // in the context of some struct `foo` evaluates to the same thing as `foo.x`. // So even though the primary API shape is based around singular keys, the // "parent key stack" also implicitly parameterizes all of these (partly // because it is not relevant in 99% of cases). //- rjf: parent key stack internal E_Key e_parent_key_push(E_Key key); internal E_Key e_parent_key_pop(void); #define E_ParentKey(key) DeferLoop(e_parent_key_push(key), e_parent_key_pop()) //- rjf: key construction internal E_Key e_key_from_string(String8 string); internal E_Key e_key_from_stringf(char *fmt, ...); internal E_Key e_key_from_expr(E_Expr *expr); //- rjf: base key -> bundle helper internal E_CacheBundle *e_cache_bundle_from_key(E_Key key); //- rjf: bundle -> pipeline stage outputs internal E_Parse e_parse_from_bundle(E_CacheBundle *bundle); internal E_IRTreeAndType e_irtree_from_bundle(E_CacheBundle *bundle); internal String8 e_bytecode_from_bundle(E_CacheBundle *bundle); internal E_Interpretation e_interpretation_from_bundle(E_CacheBundle *bundle); #define e_parse_from_key(key) e_parse_from_bundle(e_cache_bundle_from_key(key)) #define e_irtree_from_key(key) e_irtree_from_bundle(e_cache_bundle_from_key(key)) #define e_bytecode_from_key(key) e_bytecode_from_bundle(e_cache_bundle_from_key(key)) #define e_interpretation_from_key(key) e_interpretation_from_bundle(e_cache_bundle_from_key(key)) //- rjf: key -> full expression string internal String8 e_full_expr_string_from_key(Arena *arena, E_Key key); //- rjf: comprehensive bundle internal E_Eval e_eval_from_bundle(E_CacheBundle *bundle); internal E_Eval e_value_eval_from_eval(E_Eval eval); #define e_eval_from_key(key) e_eval_from_bundle(e_cache_bundle_from_key(key)) #define e_value_from_key(key) (e_value_eval_from_eval(e_eval_from_key(key)).value) //- rjf: string-based helpers #define e_parse_from_string(string) e_parse_from_bundle(e_cache_bundle_from_key(e_key_from_string(string))) #define e_irtree_from_string(string) e_irtree_from_bundle(e_cache_bundle_from_key(e_key_from_string(string))) #define e_bytecode_from_string(string) e_bytecode_from_bundle(e_cache_bundle_from_key(e_key_from_string(string))) #define e_interpretation_from_string(string) e_interpretation_from_bundle(e_cache_bundle_from_key(e_key_from_string(string))) #define e_eval_from_string(string) e_eval_from_key(e_key_from_string(string)) #define e_eval_from_stringf(...) e_eval_from_key(e_key_from_stringf(__VA_ARGS__)) #define e_value_from_string(string) e_value_eval_from_eval(e_eval_from_string(string)).value #define e_value_from_stringf(...) e_value_eval_from_eval(e_eval_from_stringf(__VA_ARGS__)).value //- rjf: expr-based helpers #define e_eval_from_expr(expr) e_eval_from_key(e_key_from_expr(expr)) #define e_value_from_expr(expr) e_value_eval_from_eval(e_eval_from_expr(expr)).value //- rjf: type key -> auto hooks internal E_AutoHookMatchList e_push_auto_hook_matches_from_type_key(Arena *arena, E_TypeKey type_key); internal E_AutoHookMatchList e_auto_hook_matches_from_type_key(E_TypeKey type_key); //- rjf: string IDs internal U64 e_id_from_string(String8 string); internal String8 e_string_from_id(U64 id); //////////////////////////////// //~ rjf: Key Extension Functions internal E_Key e_key_wrap(E_Key key, String8 string); internal E_Key e_key_wrapf(E_Key key, char *fmt, ...); //- rjf: eval-based helpers #define e_eval_wrap(eval, string) e_eval_from_key(e_key_wrap((eval).key, (string))) #define e_eval_wrapf(eval, ...) e_eval_from_key(e_key_wrapf((eval).key, __VA_ARGS__)) //////////////////////////////// //~ rjf: Eval Info Extraction internal Rng1U64 e_range_from_eval(E_Eval eval); //////////////////////////////// //~ rjf: Debug Functions internal String8 e_debug_log_from_expr_string(Arena *arena, String8 string); #endif // EVAL_CORE_H ================================================ FILE: src/eval/eval_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "eval/eval_core.c" #include "eval/eval_types.c" #include "eval/eval_parse.c" #include "eval/eval_ir.c" #include "eval/eval_interpret.c" ================================================ FILE: src/eval/eval_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_INC_H #define EVAL_INC_H #include "eval/eval_core.h" #include "eval/eval_types.h" #include "eval/eval_parse.h" #include "eval/eval_ir.h" #include "eval/eval_interpret.h" #endif // EVAL_INC_H ================================================ FILE: src/eval/eval_interpret.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs) internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff) { e_interpret_ctx = ctx; // compute and apply frame base if(primary_rdi != 0) { E_Interpretation frame_base = { .code = ~0 }; RDI_Procedure *proc = rdi_procedure_from_voff(primary_rdi, ip_voff); for(U64 loc_block_idx = proc->frame_base_location_first; loc_block_idx < proc->frame_base_location_opl; loc_block_idx += 1) { RDI_LocationBlock *block = rdi_element_from_name_idx(primary_rdi, LocationBlocks, loc_block_idx); if (block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) { U64 all_location_data_size = 0; U8 *all_location_data = rdi_table_from_name(primary_rdi, LocationData, &all_location_data_size); if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) { RDI_LocationKind loc_kind = *(RDI_LocationKind *)(all_location_data + block->location_data_off); if(loc_kind == RDI_LocationKind_ValBytecodeStream || loc_kind == RDI_LocationKind_AddrBytecodeStream) { U8 *bytecode_ptr = all_location_data + block->location_data_off + sizeof(RDI_LocationKind); U8 *bytecode_opl = all_location_data + all_location_data_size; U64 bytecode_size = rdi_size_from_bytecode_stream(bytecode_ptr, bytecode_opl); String8 bytecode = str8(bytecode_ptr, bytecode_size); frame_base = e_interpret(bytecode); } else if(loc_kind != RDI_LocationKind_NULL) { NotImplemented; } } break; } } if(frame_base.code == E_InterpretationCode_Good) { *ctx->frame_base = frame_base.value.u64; } else { ctx->frame_base = 0; } } } //////////////////////////////// //~ rjf: Space Reading Helpers internal U64 e_space_gen(E_Space space) { U64 result = 0; if(e_base_ctx->space_gen != 0) { result = e_base_ctx->space_gen(space); } return result; } internal B32 e_space_read(E_Space space, void *out, Rng1U64 range) { ProfBeginFunction(); B32 result = 0; { switch(space.kind) { //- rjf: reads from hash store key case E_SpaceKind_HashStoreKey: { C_Root root = {space.u64_0}; C_ID id = {space.u128}; C_Key key = c_key_make(root, id); U128 hash = c_hash_from_key(key, 0); Access *access = access_open(); { String8 data = c_data_from_hash(access, hash); Rng1U64 legal_range = r1u64(0, data.size); Rng1U64 read_range = intersect_1u64(range, legal_range); if(read_range.min < read_range.max) { result = 1; MemoryCopy(out, data.str + read_range.min, dim_1u64(read_range)); } } access_close(access); }break; //- rjf: file reads case E_SpaceKind_File: { // rjf: unpack space/path U64 file_path_string_id = space.u64_0; String8 file_path = e_string_from_id(file_path_string_id); // rjf: find containing chunk range U64 chunk_size = KB(4); Rng1U64 containing_range = range; containing_range.min -= containing_range.min%chunk_size; containing_range.max += chunk_size-1; containing_range.max -= containing_range.max%chunk_size; // rjf: map to hash C_Key key = fs_key_from_path_range(file_path, containing_range, 0); U128 hash = c_hash_from_key(key, 0); // rjf: look up from hash store Access *access = access_open(); { String8 data = c_data_from_hash(access, hash); Rng1U64 legal_range = r1u64(containing_range.min, containing_range.min + data.size); Rng1U64 read_range = intersect_1u64(range, legal_range); if(read_range.min < read_range.max) { result = 1; MemoryCopy(out, data.str + read_range.min - containing_range.min, dim_1u64(read_range)); } } access_close(access); }break; //- rjf: default -> use hooks default: if(e_base_ctx->space_read != 0) { result = e_base_ctx->space_read(space, out, range); }break; } } ProfEnd(); return result; } internal B32 e_space_write(E_Space space, void *in, Rng1U64 range) { ProfBeginFunction(); B32 result = 0; if(e_base_ctx->space_write != 0) { switch(space.kind) { default: { result = e_base_ctx->space_write(space, in, range); }break; } } ProfEnd(); return result; } //////////////////////////////// //~ rjf: Interpretation Functions internal E_Interpretation e_interpret(String8 bytecode) { E_Interpretation result = {0}; Temp scratch = scratch_begin(0, 0); //- rjf: allocate stack & "registers" U64 stack_cap = 128; // TODO(rjf): scan bytecode; determine maximum stack depth E_Value *stack = push_array_no_zero(scratch.arena, E_Value, stack_cap); U64 stack_count = 0; E_Space selected_space = {0}; if(bytecode.size != 0) { selected_space = e_interpret_ctx->primary_space; } //- rjf: iterate bytecode & perform ops U8 *ptr = bytecode.str; U8 *opl = bytecode.str + bytecode.size; for(;ptr < opl;) { // rjf: consume next opcode RDI_EvalOp op = (RDI_EvalOp)*ptr; U16 ctrlbits = 0; if(op < RDI_EvalOp_COUNT) { ctrlbits = rdi_eval_op_ctrlbits_table[op]; } else switch(op) { case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break; default: { result.code = E_InterpretationCode_BadOp; goto done; }break; } ptr += 1; // rjf: decode E_Value imm = {0}; { U32 decode_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); U8 *next_ptr = ptr + decode_size; if(next_ptr > opl) { result.code = E_InterpretationCode_BadOp; goto done; } // TODO(rjf): guarantee 8 bytes padding after the end of serialized // bytecode; read 8 bytes and mask MemoryCopy(&imm, ptr, decode_size); ptr = next_ptr; } // rjf: unpack imm -> type group & arithmetic width RDI_EvalTypeGroup type_group = (RDI_EvalTypeGroup)imm.u512.u8[0]; U64 op_arithmetic_size = (U64)imm.u512.u8[1]; // rjf: pop E_Value *svals = 0; { U32 pop_count = RDI_POPN_FROM_CTRLBITS(ctrlbits); if(pop_count > stack_count) { result.code = E_InterpretationCode_BadOp; goto done; } if(pop_count <= stack_count) { stack_count -= pop_count; svals = stack + stack_count; } } // rjf: interpret op, given decodes/pops E_Value nval = {0}; switch(op) { case E_IRExtKind_SetSpace: { MemoryCopy(&selected_space, &imm, sizeof(selected_space)); }break; case RDI_EvalOp_Stop: { goto done; }break; case RDI_EvalOp_Noop: { // do nothing }break; case RDI_EvalOp_Cond: if(svals[0].u64) { ptr += imm.u64; }break; case RDI_EvalOp_Skip: { ptr += imm.u64; }break; case RDI_EvalOp_MemRead: { U64 addr = svals[0].u64; U64 size = imm.u64; B32 good_read = e_space_read(selected_space, &nval, r1u64(addr, addr+size)); if(!good_read) { result.code = E_InterpretationCode_BadMemRead; goto done; } }break; case RDI_EvalOp_RegRead: { U8 rdi_reg_code = (imm.u64&0x0000FF)>>0; U8 byte_size = (imm.u64&0x00FF00)>>8; U8 byte_off = (imm.u64&0xFF0000)>>16; REGS_RegCode base_reg_code = regs_reg_code_from_arch_rdi_code(e_interpret_ctx->reg_arch, rdi_reg_code); REGS_Rng rng = regs_reg_code_rng_table_from_arch(e_interpret_ctx->reg_arch)[base_reg_code]; U64 off = (U64)rng.byte_off + byte_off; U64 size = (U64)byte_size; B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size)); if(!good_read) { result.code = E_InterpretationCode_BadRegRead; goto done; } }break; case RDI_EvalOp_RegReadDyn: { U64 off = svals[0].u64; U64 size = bit_size_from_arch(e_interpret_ctx->reg_arch)/8; B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size)); if(!good_read) { result.code = E_InterpretationCode_BadRegRead; goto done; } }break; case RDI_EvalOp_FrameOff: { if(e_interpret_ctx->frame_base != 0) { nval.u64 = *e_interpret_ctx->frame_base + imm.u64; } else { result.code = E_InterpretationCode_BadFrameBase; goto done; } }break; case RDI_EvalOp_ModuleOff: { if(e_interpret_ctx->module_base != 0) { nval.u64 = *e_interpret_ctx->module_base + imm.u64; } else { result.code = E_InterpretationCode_BadModuleBase; goto done; } }break; case RDI_EvalOp_TLSOff: { if(e_interpret_ctx->tls_base != 0) { nval.u64 = *e_interpret_ctx->tls_base + imm.u64; } else { result.code = E_InterpretationCode_BadTLSBase; goto done; } }break; case RDI_EvalOp_ConstU8: case RDI_EvalOp_ConstU16: case RDI_EvalOp_ConstU32: case RDI_EvalOp_ConstU64: case RDI_EvalOp_ConstU128: { nval = imm; }break; case RDI_EvalOp_ConstString: { MemoryCopy(&nval, ptr, imm.u64); ptr += imm.u64; }break; case RDI_EvalOp_Abs: { if(type_group == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32; if(svals[0].f32 < 0) { nval.f32 = -svals[0].f32; } } else if(type_group == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64; if(svals[0].f64 < 0) { nval.f64 = -svals[0].f64; } } else { nval.s64 = svals[0].s64; if(svals[0].s64 < 0) { nval.s64 = -svals[0].s64; } } }break; case RDI_EvalOp_Neg: { if(type_group == RDI_EvalTypeGroup_F32) { nval.f32 = -svals[0].f32; } else if(type_group == RDI_EvalTypeGroup_F64) { nval.f64 = -svals[0].f64; } else { nval.u64 = (~svals[0].u64) + 1; } }break; case RDI_EvalOp_Add: { if(type_group == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32 + svals[1].f32; } else if(type_group == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64 + svals[1].f64; } else { nval.u64 = svals[0].u64 + svals[1].u64; } }break; case RDI_EvalOp_Sub: { if(type_group == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32 - svals[1].f32; } else if(type_group == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64 - svals[1].f64; } else { nval.u64 = svals[0].u64 - svals[1].u64; } }break; case RDI_EvalOp_Mul: { if(type_group == RDI_EvalTypeGroup_F32) { nval.f32 = svals[0].f32*svals[1].f32; } else if(type_group == RDI_EvalTypeGroup_F64) { nval.f64 = svals[0].f64*svals[1].f64; } else { nval.u64 = svals[0].u64*svals[1].u64; } }break; case RDI_EvalOp_Div: { if(type_group == RDI_EvalTypeGroup_F32) { if(svals[1].f32 != 0.f) { nval.f32 = svals[0].f32/svals[1].f32; } else { result.code = E_InterpretationCode_DivideByZero; goto done; } } else if(type_group == RDI_EvalTypeGroup_F64) { if(svals[1].f64 != 0.) { nval.f64 = svals[0].f64/svals[1].f64; } else { result.code = E_InterpretationCode_DivideByZero; goto done; } } else if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { if(svals[1].u64 != 0) { nval.u64 = svals[0].u64/svals[1].u64; } else { result.code = E_InterpretationCode_DivideByZero; goto done; } } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_Mod: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { if(svals[1].u64 != 0) { nval.u64 = svals[0].u64%svals[1].u64; } } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_LShift: { if(type_group == RDI_EvalTypeGroup_U) { switch(op_arithmetic_size) { default:{}break; case 1:{nval.u8 = svals[0].u8 << svals[1].u8;}break; case 2:{nval.u16 = svals[0].u16 << svals[1].u16;}break; case 4:{nval.u32 = svals[0].u32 << svals[1].u32;}break; case 8:{nval.u64 = svals[0].u64 << svals[1].u64;}break; } } else if(type_group == RDI_EvalTypeGroup_S) { switch(op_arithmetic_size) { default:{}break; case 1:{nval.s8 = svals[0].s8 << svals[1].s8;}break; case 2:{nval.s16 = svals[0].s16 << svals[1].s16;}break; case 4:{nval.s32 = svals[0].s32 << svals[1].s32;}break; case 8:{nval.s64 = svals[0].s64 << svals[1].s64;}break; } } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_RShift: { if(type_group == RDI_EvalTypeGroup_U) { switch(op_arithmetic_size) { default:{}break; case 1:{nval.u8 = svals[0].u8 >> svals[1].u8;}break; case 2:{nval.u16 = svals[0].u16 >> svals[1].u16;}break; case 4:{nval.u32 = svals[0].u32 >> svals[1].u32;}break; case 8:{nval.u64 = svals[0].u64 >> svals[1].u64;}break; } } else if(type_group == RDI_EvalTypeGroup_S) { switch(op_arithmetic_size) { default:{}break; case 1:{nval.s8 = svals[0].s8 >> svals[1].s8;}break; case 2:{nval.s16 = svals[0].s16 >> svals[1].s16;}break; case 4:{nval.s32 = svals[0].s32 >> svals[1].s32;}break; case 8:{nval.s64 = svals[0].s64 >> svals[1].s64;}break; } } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_BitAnd: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64&svals[1].u64; } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_BitOr: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64|svals[1].u64; } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_BitXor: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = svals[0].u64^svals[1].u64; } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_BitNot: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = ~svals[0].u64; } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_LogAnd: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].u64 && svals[1].u64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_LogOr: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].u64 || svals[1].u64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_LogNot: { if(type_group == RDI_EvalTypeGroup_U || type_group == RDI_EvalTypeGroup_S) { nval.u64 = (!svals[0].u64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_EqEq: { B32 result = MemoryMatchArray(svals[0].u512.u64, svals[1].u512.u64); nval.u64 = !!result; }break; case RDI_EvalOp_NtEq: { B32 result = MemoryMatchArray(svals[0].u512.u64, svals[1].u512.u64); nval.u64 = !result; }break; case RDI_EvalOp_LsEq: { if(type_group == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 <= svals[1].f32); } else if(type_group == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 <= svals[1].f64); } else if(type_group == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 <= svals[1].u64); } else if(type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 <= svals[1].s64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_GrEq: { if(type_group == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 >= svals[1].f32); } else if(type_group == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 >= svals[1].f64); } else if(type_group == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 >= svals[1].u64); } else if(type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 >= svals[1].s64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_Less: { if(type_group == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 < svals[1].f32); } else if(type_group == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 < svals[1].f64); } else if(type_group == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 < svals[1].u64); } else if(type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 < svals[1].s64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_Grtr: { if(type_group == RDI_EvalTypeGroup_F32) { nval.u64 = (svals[0].f32 > svals[1].f32); } else if(type_group == RDI_EvalTypeGroup_F64) { nval.u64 = (svals[0].f64 > svals[1].f64); } else if(type_group == RDI_EvalTypeGroup_U) { nval.u64 = (svals[0].u64 > svals[1].u64); } else if(type_group == RDI_EvalTypeGroup_S) { nval.u64 = (svals[0].s64 > svals[1].s64); } else { result.code = E_InterpretationCode_BadOpTypes; goto done; } }break; case RDI_EvalOp_Trunc: { if(0 < imm.u64) { U64 mask = 0; if(imm.u64 < 64) { mask = max_U64 >> (64 - imm.u64); } nval.u64 = svals[0].u64&mask; } }break; case RDI_EvalOp_TruncSigned: { if(0 < imm.u64) { U64 mask = 0; if(imm.u64 < 64) { mask = max_U64 >> (64 - imm.u64); } U64 high = 0; if(svals[0].u64 & (1 << (imm.u64 - 1))) { high = ~mask; } nval.u64 = high|(svals[0].u64&mask); } }break; case RDI_EvalOp_Convert: { U32 in = imm.u64&0xFF; U32 out = (imm.u64 >> 8)&0xFF; if(in != out) { switch(in + out*RDI_EvalTypeGroup_COUNT) { case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT: { nval.u64 = (U64)svals[0].f32; }break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT: { nval.u64 = (U64)svals[0].f64; }break; case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT: { nval.s64 = (S64)svals[0].f32; }break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT: { nval.s64 = (S64)svals[0].f64; }break; case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].u64; }break; case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].s64; }break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].f64; }break; case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].u64; }break; case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].s64; }break; case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].f32; }break; } } }break; case RDI_EvalOp_Pick: { if(stack_count > imm.u64) { nval = stack[stack_count - imm.u64 - 1]; } else { result.code = E_InterpretationCode_BadOp; goto done; } }break; case RDI_EvalOp_Pop: { // do nothing - the pop is handled by the control bits }break; case RDI_EvalOp_Insert: { if(stack_count > imm.u64) { if(imm.u64 > 0) { E_Value tval = stack[stack_count - 1]; E_Value *dst = stack + stack_count - 1 - imm.u64; E_Value *shift = dst + 1; MemoryCopy(shift, dst, imm.u64*sizeof(E_Value)); *dst = tval; } } else { result.code = E_InterpretationCode_BadOp; goto done; } }break; case RDI_EvalOp_ValueRead: { U64 bytes_to_read = imm.u64; U64 offset = svals[0].u64; if(offset + bytes_to_read <= sizeof(E_Value)) { E_Value src_val = svals[1]; MemoryCopy(&nval.u512.u64[0], (U8 *)(&src_val.u512.u64[0]) + offset, bytes_to_read); } }break; case RDI_EvalOp_ByteSwap: { U64 byte_size = imm.u64; switch(byte_size) { default: { result.code = E_InterpretationCode_BadOp; goto done; }break; case 2:{nval.u16 = bswap_u16(svals[0].u16);}break; case 4:{nval.u32 = bswap_u32(svals[0].u32);}break; case 8:{nval.u64 = bswap_u64(svals[0].u64);}break; } }break; case RDI_EvalOp_CallSiteValue: { NotImplemented; }break; case RDI_EvalOp_PartialValue: { NotImplemented; }break; case RDI_EvalOp_PartialValueBit: { NotImplemented; }break; case RDI_EvalOp_Swap: { // TODO: add support for pushing multiple values onto the stack NotImplemented; }break; } // rjf: push { U64 push_count = RDI_PUSHN_FROM_CTRLBITS(ctrlbits); if(push_count == 1) { if(stack_count < stack_cap) { stack[stack_count] = nval; stack_count += 1; } else { result.code = E_InterpretationCode_InsufficientStackSpace; goto done; } } } } done:; if(stack_count >= 1) { result.value = stack[0]; } result.space = selected_space; scratch_end(scratch); return result; } ================================================ FILE: src/eval/eval_interpret.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_INTERPRET_H #define EVAL_INTERPRET_H //////////////////////////////// //~ rjf: Interpretation Context typedef struct E_InterpretCtx E_InterpretCtx; struct E_InterpretCtx { E_Space primary_space; Arch reg_arch; E_Space reg_space; U64 reg_unwind_count; U64 *module_base; U64 *frame_base; U64 *tls_base; }; //////////////////////////////// //~ rjf: Globals thread_static E_InterpretCtx *e_interpret_ctx = 0; //////////////////////////////// //~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs) internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff); //////////////////////////////// //~ rjf: Space Reading Helpers internal U64 e_space_gen(E_Space space); internal B32 e_space_read(E_Space space, void *out, Rng1U64 range); internal B32 e_space_write(E_Space space, void *in, Rng1U64 range); //////////////////////////////// //~ rjf: Interpretation Functions internal E_Interpretation e_interpret(String8 bytecode); #endif // EVAL_INTERPRET_H ================================================ FILE: src/eval/eval_ir.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: IR-ization Functions //- rjf: op list functions internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, E_Value value) { U16 ctrlbits = rdi_eval_op_ctrlbits_table[opcode]; U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); E_Op *node = push_array_no_zero(arena, E_Op, 1); node->opcode = opcode; node->value = value; SLLQueuePush(list->first, list->last, node); list->op_count += 1; list->encoded_size += 1 + p_size; } internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x) { if(0){} else if(x <= 0xFF) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU8, e_value_u64(x)); } else if(x <= 0xFFFF) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU16, e_value_u64(x)); } else if(x <= 0xFFFFFFFF) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU32, e_value_u64(x)); } else { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU64, e_value_u64(x)); } } internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x) { if(-0x80 <= x && x <= 0x7F) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU8, e_value_u64((U64)x)); e_oplist_push_op(arena, list, RDI_EvalOp_TruncSigned, e_value_u64(8)); } else if(-0x8000 <= x && x <= 0x7FFF) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU16, e_value_u64((U64)x)); e_oplist_push_op(arena, list, RDI_EvalOp_TruncSigned, e_value_u64(16)); } else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU32, e_value_u64((U64)x)); e_oplist_push_op(arena, list, RDI_EvalOp_TruncSigned, e_value_u64(32)); } else { e_oplist_push_op(arena, list, RDI_EvalOp_ConstU64, e_value_u64((U64)x)); } } internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode) { E_Op *node = push_array_no_zero(arena, E_Op, 1); node->opcode = E_IRExtKind_Bytecode; node->string = bytecode; SLLQueuePush(list->first, list->last, node); list->op_count += 1; list->encoded_size += bytecode.size; } internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space) { E_Op *node = push_array_no_zero(arena, E_Op, 1); node->opcode = E_IRExtKind_SetSpace; StaticAssert(sizeof(E_Space) <= sizeof(E_Value), space_size_check); MemoryCopy(&node->value, &space, sizeof(space)); SLLQueuePush(list->first, list->last, node); list->op_count += 1; list->encoded_size += 1 + sizeof(space); } internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string) { RDI_EvalOp opcode = RDI_EvalOp_ConstString; U16 ctrlbits = rdi_eval_op_ctrlbits_table[opcode]; U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); E_Op *node = push_array_no_zero(arena, E_Op, 1); node->opcode = opcode; node->string = string; node->value.u64 = Min(string.size, 64); SLLQueuePush(list->first, list->last, node); list->op_count += 1; list->encoded_size += 1 + p_size + node->value.u64; } internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push) { if(to_push->first && dst->first) { dst->last->next = to_push->first; dst->last = to_push->last; dst->op_count += to_push->op_count; dst->encoded_size += to_push->encoded_size; } else if(!dst->first) { MemoryCopyStruct(dst, to_push); } MemoryZeroStruct(to_push); } //- rjf: ir tree core building helpers internal E_IRNode * e_push_irnode(Arena *arena, RDI_EvalOp op) { E_IRNode *n = push_array(arena, E_IRNode, 1); n->first = n->last = n->next = &e_irnode_nil; n->op = op; return n; } internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child) { if(parent != &e_irnode_nil && child != &e_irnode_nil) { SLLQueuePush_NZ(&e_irnode_nil, parent->first, parent->last, child, next); } } //- rjf: ir subtree building helpers internal E_IRNode * e_irtree_const_u(Arena *arena, U64 v) { // rjf: choose op RDI_EvalOp op = RDI_EvalOp_ConstU64; if (v < 0x100) { op = RDI_EvalOp_ConstU8; } else if(v < 0x10000) { op = RDI_EvalOp_ConstU16; } else if(v < 0x100000000) { op = RDI_EvalOp_ConstU32; } // rjf: build E_IRNode *n = e_push_irnode(arena, op); n->value.u64 = v; return n; } internal E_IRNode * e_irtree_leaf_u128(Arena *arena, U128 u128) { E_IRNode *n = e_push_irnode(arena, RDI_EvalOp_ConstU128); n->value.u128 = u128; return n; } internal E_IRNode * e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c) { E_IRNode *n = e_push_irnode(arena, op); n->value.u64 = group; e_irnode_push_child(n, c); return n; } internal E_IRNode * e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, U64 operand_size, E_IRNode *l, E_IRNode *r) { E_IRNode *n = e_push_irnode(arena, op); n->value.u512.u8[0] = (U8)group; n->value.u512.u8[1] = (U8)operand_size; e_irnode_push_child(n, l); e_irnode_push_child(n, r); return n; } internal E_IRNode * e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, U64 operand_size, E_IRNode *l, E_IRNode *r) { E_IRNode *n = e_irtree_binary_op(arena, op, RDI_EvalTypeGroup_U, operand_size, l, r); return n; } internal E_IRNode * e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r) { E_IRNode *n = e_push_irnode(arena, RDI_EvalOp_Cond); e_irnode_push_child(n, c); e_irnode_push_child(n, l); e_irnode_push_child(n, r); return n; } internal E_IRNode * e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode) { E_IRNode *n = e_push_irnode(arena, E_IRExtKind_Bytecode); n->string = bytecode; return n; } internal E_IRNode * e_irtree_string_literal(Arena *arena, String8 string) { E_IRNode *root = e_push_irnode(arena, RDI_EvalOp_ConstString); root->string = string; return root; } internal E_IRNode * e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c) { E_IRNode *root = e_push_irnode(arena, E_IRExtKind_SetSpace); StaticAssert(sizeof(E_Space) <= sizeof(E_Value), space_size_check); MemoryCopy(&root->value, &space, sizeof(space)); e_irnode_push_child(root, c); return root; } internal E_IRNode * e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key) { E_IRNode *result = &e_irnode_nil; U64 byte_size = e_type_byte_size_from_key(type_key); byte_size = Min(64, byte_size); // rjf: build the read node E_IRNode *read_node = e_push_irnode(arena, RDI_EvalOp_MemRead); read_node->value.u64 = byte_size; e_irnode_push_child(read_node, c); // rjf: build a signed trunc node if needed U64 bit_size = byte_size << 3; E_IRNode *with_trunc = read_node; E_TypeKind kind = e_type_kind_from_key(type_key); if(bit_size < 64 && e_type_kind_is_signed(kind)) { with_trunc = e_push_irnode(arena, RDI_EvalOp_TruncSigned); with_trunc->value.u64 = bit_size; e_irnode_push_child(with_trunc, read_node); } // rjf: fill result = with_trunc; return result; } internal E_IRNode * e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in) { E_IRNode *n = e_push_irnode(arena, RDI_EvalOp_Convert); n->value.u64 = in | (out << 8); e_irnode_push_child(n, c); return n; } internal E_IRNode * e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key) { E_IRNode *result = c; U64 byte_size = e_type_byte_size_from_key(type_key); if(byte_size < 64) { RDI_EvalOp op = RDI_EvalOp_Trunc; E_TypeKind kind = e_type_kind_from_key(type_key); if(e_type_kind_is_signed(kind)) { op = RDI_EvalOp_TruncSigned; } U64 bit_size = byte_size << 3; result = e_push_irnode(arena, op); result->value.u64 = bit_size; e_irnode_push_child(result, c); } return result; } internal E_IRNode * e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in) { E_IRNode *result = c; E_TypeKind in_kind = e_type_kind_from_key(in); E_TypeKind out_kind = e_type_kind_from_key(out); U8 in_group = e_type_group_from_kind(in_kind); U8 out_group = e_type_group_from_kind(out_kind); U32 conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group); if(conversion_rule == RDI_EvalConversionKind_Legal) { result = e_irtree_convert_lo(arena, result, out_group, in_group); } U64 in_byte_size = e_type_byte_size_from_key(in); U64 out_byte_size = e_type_byte_size_from_key(out); if(out_byte_size < in_byte_size && e_type_kind_is_integer(out_kind)) { result = e_irtree_trunc(arena, result, out); } return result; } internal E_IRNode * e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key) { E_IRNode *result = tree; if(from_mode == E_Mode_Offset) { result = e_irtree_mem_read_type(arena, tree, type_key); } if(e_type_kind_from_key(type_key) == E_TypeKind_Bitfield) { E_Type *type = e_type_from_key(type_key); if(type->byte_size <= sizeof(U64)) { U64 valid_bits_mask = 0; for(U64 idx = 0; idx < type->count; idx += 1) { valid_bits_mask |= (1ull<byte_size, result, e_irtree_const_u(arena, type->off)); result = e_irtree_binary_op_u(arena, RDI_EvalOp_BitAnd, type->byte_size, result, e_irtree_const_u(arena, valid_bits_mask)); } } return result; } //- rjf: rule tag poison checking internal B32 e_expr_is_poisoned(E_Expr *expr) { B32 tag_is_poisoned = 0; U64 hash = e_hash_from_string(5381, str8_struct(&expr)); U64 slot_idx = hash%e_cache->used_expr_map->slots_count; for(E_UsedExprNode *n = e_cache->used_expr_map->slots[slot_idx].first; n != 0; n = n->next) { if(n->expr == expr) { tag_is_poisoned = 1; break; } } return tag_is_poisoned; } internal void e_expr_poison(E_Expr *expr) { U64 hash = e_hash_from_string(5381, str8_struct(&expr)); U64 slot_idx = hash%e_cache->used_expr_map->slots_count; E_UsedExprNode *n = push_array(e_cache->arena, E_UsedExprNode, 1); n->expr = expr; DLLPushBack(e_cache->used_expr_map->slots[slot_idx].first, e_cache->used_expr_map->slots[slot_idx].last, n); } internal void e_expr_unpoison(E_Expr *expr) { U64 hash = e_hash_from_string(5381, str8_struct(&expr)); U64 slot_idx = hash%e_cache->used_expr_map->slots_count; for(E_UsedExprNode *n = e_cache->used_expr_map->slots[slot_idx].first; n != 0; n = n->next) { if(n->expr == expr) { DLLRemove(e_cache->used_expr_map->slots[slot_idx].first, e_cache->used_expr_map->slots[slot_idx].last, n); break; } } } //- rjf: top-level irtree/type extraction E_TYPE_ACCESS_FUNCTION_DEF(default) { Temp scratch = scratch_begin(&arena, 1); E_IRTreeAndType result = {&e_irnode_nil}; switch(expr->kind) { default:{}break; //- rjf: member accessing (. operator) case E_ExprKind_MemberAccess: { // rjf: unpack left/right expressions E_Expr *exprl = expr->first; E_Expr *exprr = exprl->next; E_IRTreeAndType l = *lhs_irtree; E_TypeKey l_restype = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums); E_TypeKind l_restype_kind = e_type_kind_from_key(l_restype); E_TypeKey check_type_key = l_restype; E_TypeKind check_type_kind = l_restype_kind; if(l_restype_kind == E_TypeKind_Ptr || l_restype_kind == E_TypeKind_LRef || l_restype_kind == E_TypeKind_RRef || l_restype_kind == E_TypeKind_Array) { check_type_key = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_All); check_type_kind = e_type_kind_from_key(check_type_key); } e_msg_list_concat_in_place(&result.msgs, &l.msgs); // rjf: look up member E_Member member = zero_struct; B32 r_found = 0; E_TypeKey r_type = zero_struct; U64 r_value = 0; String8 r_query_name = {0}; B32 r_is_constant_value = 0; { Temp scratch = scratch_begin(&arena, 1); E_Member match = e_type_member_from_key_name__cached(check_type_key, exprr->string); member = match; if(match.kind != E_MemberKind_Null) { r_found = 1; r_type = match.type_key; r_value = match.off; } if(match.kind == E_MemberKind_Null) { E_Type *type = e_type_from_key(check_type_key); String8 lookup_string = exprr->string; String8 lookup_string_append_1 = push_str8f(scratch.arena, "%S_%S", type->name, lookup_string); String8 lookup_string_append_2 = push_str8f(scratch.arena, "%S%S", type->name, lookup_string); E_EnumVal enum_val = {0}; if(enum_val.name.size == 0) { enum_val = e_type_enum_val_from_key_name__cached(check_type_key, lookup_string); } if(enum_val.name.size == 0) { enum_val = e_type_enum_val_from_key_name__cached(check_type_key, lookup_string_append_1); } if(enum_val.name.size == 0) { enum_val = e_type_enum_val_from_key_name__cached(check_type_key, lookup_string_append_2); } if(enum_val.name.size != 0) { r_found = 1; r_type = check_type_key; r_value = enum_val.val; r_is_constant_value = 1; } } scratch_end(scratch); } // rjf: bad conditions? -> error if applicable, exit if(exprr->kind != E_ExprKind_LeafIdentifier) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprl->range, "Expected member name."); break; } else if(!r_found) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprr->range, "Could not find a member named `%S`.", exprr->string); break; } else if(l.root == &e_irnode_nil || e_type_key_match(e_type_key_zero(), check_type_key)) { break; } else if(check_type_kind != E_TypeKind_Struct && check_type_kind != E_TypeKind_Class && check_type_kind != E_TypeKind_Union && check_type_kind != E_TypeKind_Enum) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprl->range, "Cannot perform member access on this type."); break; } // rjf: generate { // rjf: build tree E_IRNode *new_tree = l.root; E_TypeKey new_tree_type = r_type; E_Mode mode = l.mode; if(e_type_kind_is_pointer_or_ref(l_restype_kind)) { new_tree = e_irtree_resolve_to_value(arena, l.mode, new_tree, l_restype); if(l.mode != E_Mode_Null) { mode = E_Mode_Offset; } } if(r_value != 0 && !r_is_constant_value) { E_IRNode *const_tree = e_irtree_const_u(arena, r_value); new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, e_type_byte_size_from_key(new_tree_type), new_tree, const_tree); } else if(r_is_constant_value) { new_tree = e_irtree_const_u(arena, r_value); mode = E_Mode_Value; } // rjf: fill result.root = new_tree; result.type_key = r_type; result.mode = mode; } }break; //- rjf: indexing ([] operator) case E_ExprKind_ArrayIndex: { // rjf: unpack left/right expressions E_Expr *exprl = expr->first; E_Expr *exprr = exprl->next; E_IRTreeAndType l = *lhs_irtree; E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, overridden, &e_default_identifier_resolution_rule, 0, 1, exprr); e_msg_list_concat_in_place(&result.msgs, &r.msgs); E_TypeKey l_restype = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey r_restype = e_type_key_unwrap(r.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind l_restype_kind = e_type_kind_from_key(l_restype); E_TypeKind r_restype_kind = e_type_kind_from_key(r_restype); E_TypeKey direct_type = e_type_key_unwrap(l_restype, E_TypeUnwrapFlag_All & ~(E_TypeUnwrapFlag_Enums|E_TypeUnwrapFlag_Aliases)); U64 direct_type_size = e_type_byte_size_from_key(direct_type); // rjf: bad conditions? -> error if applicable, exit if(r.root->op == 0) { break; } else if(l_restype_kind != E_TypeKind_Ptr && l_restype_kind != E_TypeKind_Array && l_restype_kind != E_TypeKind_LRef && l_restype_kind != E_TypeKind_RRef) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprl->range, "Cannot index into this type."); break; } else if(!e_type_kind_is_integer(r_restype_kind)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprr->range, "Cannot index with this type."); break; } else if(l_restype_kind == E_TypeKind_Ptr && direct_type_size == 0) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprr->range, "Cannot index into pointers of zero-sized types."); break; } else if(l_restype_kind == E_TypeKind_Array && direct_type_size == 0) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprr->range, "Cannot index into arrays of zero-sized types."); break; } // rjf: generate E_IRNode *new_tree = &e_irnode_nil; E_Mode mode = l.mode; { // rjf: reading from an array value -> read from stack value if(l.mode == E_Mode_Value && l_restype_kind == E_TypeKind_Array) { // rjf: ops to compute the offset E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); if(direct_type_size > 1) { E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, 8, offset_tree, const_tree); } // rjf: ops to push stack value, push offset, + read from stack value new_tree = e_push_irnode(arena, RDI_EvalOp_ValueRead); new_tree->value.u64 = direct_type_size; e_irnode_push_child(new_tree, offset_tree); e_irnode_push_child(new_tree, l.root); } // rjf: all other cases -> read from base offset else { // rjf: ops to compute the offset E_IRNode *offset_tree = e_irtree_resolve_to_value(arena, r.mode, r.root, r_restype); if(direct_type_size > 1) { E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); offset_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, 8, offset_tree, const_tree); } // rjf: ops to compute the base offset (resolve to value if addr-of-pointer) E_IRNode *base_tree = l.root; if(e_type_kind_is_pointer_or_ref(l_restype_kind) && l.mode != E_Mode_Value) { base_tree = e_irtree_resolve_to_value(arena, l.mode, base_tree, l_restype); } // rjf: ops to compute the final address new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, 8, offset_tree, base_tree); if(mode != E_Mode_Null) { mode = E_Mode_Offset; } } } // rjf: fill result.root = new_tree; result.type_key = direct_type; result.mode = mode; }break; } scratch_end(scratch); return result; } internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_IdentifierResolutionRule *identifier_resolution_rule, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); E_TypeKeyList inherited_lenses = {0}; E_IRTreeAndType result = {&e_irnode_nil}; ////////////////////////////// //- rjf: apply all ir-generation steps // typedef struct Task Task; struct Task { Task *next; E_Expr *expr; E_AutoHookWildcardInst *first_wildcard_inst; E_AutoHookWildcardInst *last_wildcard_inst; E_IRTreeAndType *overridden; }; Task start_task = {0, root_expr, 0}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) { E_Expr *expr = t->expr; E_IRTreeAndType *parent = t->overridden ? t->overridden : root_parent; //- rjf: poison the expression we are about to use, so we don't recursively use it e_expr_poison(expr); //- rjf: push stack elements E_AutoHookWildcardInst *first_wildcard_inst_restore = e_cache->first_wildcard_inst; E_AutoHookWildcardInst *last_wildcard_inst_restore = e_cache->last_wildcard_inst; if(t->first_wildcard_inst) { e_cache->first_wildcard_inst = t->first_wildcard_inst; } if(t->last_wildcard_inst) { e_cache->last_wildcard_inst = t->last_wildcard_inst; } //- rjf: do expr -> irtree generation for this expression if(expr->kind == E_ExprKind_Ref) { expr = expr->ref; } E_ExprKind kind = expr->kind; switch(kind) { default:{}break; //- rjf: member accesses & array indexing expressions case E_ExprKind_MemberAccess: case E_ExprKind_ArrayIndex: { // rjf: unpack left-hand-side E_Expr *lhs = expr->first; // rjf: try left-hand-side, first *without* autohooks, then *with* autohooks. for(B32 autohooks_enabled = 0; autohooks_enabled < 2; autohooks_enabled += 1) { E_IRTreeAndType lhs_irtree_try = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, !autohooks_enabled, 1, lhs); for(E_IRTreeAndType *lhs_irtree_try_chain = &lhs_irtree_try; lhs_irtree_try_chain != 0; lhs_irtree_try_chain = lhs_irtree_try_chain->prev) { // rjf: pick access hook based on type E_Type *lhs_type = e_type_from_key(lhs_irtree_try_chain->type_key); E_TypeAccessFunctionType *lhs_access = lhs_type->access; for(E_Type *lens_type = lhs_type; lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set; lens_type = e_type_from_key(lens_type->direct_type_key)) { if(lens_type->access != 0) { lhs_access = lens_type->access; break; } } if(lhs_access == 0) { lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default); } // rjf: call into hook to do access E_IRTreeAndType new_result_maybe = lhs_access(arena, parent, expr, lhs_irtree_try_chain); // rjf: if we got a valid result -> gather info from this irtree if(new_result_maybe.root != &e_irnode_nil) { E_TypeKey k = lhs_irtree_try_chain->type_key; E_TypeKind kind = e_type_kind_from_key(k); for(;kind == E_TypeKind_Lens;) { E_Type *lens_type = e_type_from_key(k); if((lens_type->flags & E_TypeFlag_InheritedByMembers && expr->kind == E_ExprKind_MemberAccess) || (lens_type->flags & E_TypeFlag_InheritedByElements && expr->kind == E_ExprKind_ArrayIndex)) { e_type_key_list_push_front(scratch.arena, &inherited_lenses, k); } k = e_type_key_direct(k); kind = e_type_kind_from_key(k); } e_msg_list_concat_in_place(&result.msgs, &lhs_irtree_try_chain->msgs); } // rjf: if we got a valid result -> we're done if(new_result_maybe.root != &e_irnode_nil) { result = new_result_maybe; break; } else if(new_result_maybe.msgs.count != 0 && result.msgs.count == 0) { result = new_result_maybe; } } if(result.root != &e_irnode_nil) { break; } } // rjf: invalid generation, chain of member accesses all stemming from // a single leaf identifier -> try to join as single string & resolve it // that way if(result.root == &e_irnode_nil) { B32 is_ident_chain = 1; for(E_Expr *l = lhs; l != &e_expr_nil; l = l->first) { if(l->kind != E_ExprKind_MemberAccess && l->kind != E_ExprKind_LeafIdentifier) { is_ident_chain = 0; break; } } if(is_ident_chain) { String8List parts = {0}; str8_list_push_front(scratch.arena, &parts, lhs->next->string); for(E_Expr *l = lhs; l != &e_expr_nil; l = l->first) { if(l->kind == E_ExprKind_LeafIdentifier) { str8_list_push_front(scratch.arena, &parts, l->string); } else if(l->kind == E_ExprKind_MemberAccess) { str8_list_push_front(scratch.arena, &parts, l->first->next->string); } } String8 full_qualified_name = str8_list_join(scratch.arena, &parts, &(StringJoin){.sep = str8_lit(".")}); E_Expr *leaf_expr_name = e_push_expr(scratch.arena, E_ExprKind_LeafIdentifier, r1u64(0, 0)); leaf_expr_name->string = full_qualified_name; E_IRTreeAndType new_result_maybe = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, disallow_autohooks, leaf_expr_name); if(new_result_maybe.root != &e_irnode_nil) { result = new_result_maybe; } } } }break; //- rjf: dereference case E_ExprKind_Deref: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); E_TypeKey r_type_direct = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_All & ~E_TypeUnwrapFlag_Enums); U64 r_type_direct_size = e_type_byte_size_from_key(r_type_direct); // rjf: bad conditions? -> error if applicable, exit if(r_tree.root->op == 0) { break; } else if(r_type_direct_size == 0 && (r_type_kind == E_TypeKind_Ptr || r_type_kind == E_TypeKind_LRef || r_type_kind == E_TypeKind_RRef)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->range, "Cannot dereference pointers of zero-sized types."); break; } else if(r_type_direct_size == 0 && r_type_kind == E_TypeKind_Array) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->range, "Cannot dereference arrays of zero-sized types."); break; } else if(r_type_kind != E_TypeKind_Array && r_type_kind != E_TypeKind_Ptr && r_type_kind != E_TypeKind_LRef && r_type_kind != E_TypeKind_RRef) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->range, "Cannot dereference this type."); break; } // rjf: generate { E_IRNode *new_tree = r_tree.root; if(r_tree.mode != E_Mode_Value && (r_type_kind == E_TypeKind_Ptr || r_type_kind == E_TypeKind_LRef || r_type_kind == E_TypeKind_RRef)) { new_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); } result.root = new_tree; result.type_key = r_type_direct; result.mode = E_Mode_Null; if(r_tree.mode != E_Mode_Null) { result.mode = E_Mode_Offset; } } }break; //- rjf: address-of case E_ExprKind_Address: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = r_tree.type_key; E_TypeKey r_type_unwrapped = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_AllDecorative & (~E_TypeUnwrapFlag_Enums)); E_TypeKind r_type_unwrapped_kind = e_type_kind_from_key(r_type_unwrapped); // rjf: bad conditions? -> error if applicable, exit if(r_tree.root->op == 0) { break; } else if(e_type_key_match(e_type_key_zero(), r_type_unwrapped)) { break; } // rjf: generate result.root = r_tree.root; result.type_key = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, r_type_unwrapped, 1, 0); result.mode = E_Mode_Value; }break; //- rjf: cast case E_ExprKind_Cast: { // rjf: unpack operands E_Expr *cast_type_expr = expr->first; E_Expr *casted_expr = cast_type_expr->next; E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, cast_type_expr); e_msg_list_concat_in_place(&result.msgs, &cast_irtree.msgs); E_TypeKey cast_type = cast_irtree.type_key; E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); E_TypeKey cast_type_unwrapped = e_type_key_unwrap(cast_irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind cast_type_unwrapped_kind = e_type_kind_from_key(cast_type_unwrapped); U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type); E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, casted_expr); e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); E_TypeKey casted_type = e_type_key_unwrap(casted_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type); E_TypeKey casted_type_unwrapped = e_type_key_unwrap(casted_type, E_TypeUnwrapFlag_Bitfields|E_TypeUnwrapFlag_AllDecorative); E_TypeKind casted_type_unwrapped_kind = e_type_kind_from_key(casted_type_unwrapped); U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type); U8 in_group = e_type_group_from_kind(casted_type_unwrapped_kind); U8 out_group = e_type_group_from_kind(cast_type_unwrapped_kind); RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group); // rjf: bad conditions? -> error if applicable, exit if(casted_tree.root->op == 0) { break; } else if(cast_type_kind == E_TypeKind_Null) { break; } else if(conversion_rule != RDI_EvalConversionKind_Noop && conversion_rule != RDI_EvalConversionKind_Legal) { String8 text = str8_lit("Unknown cast conversion rule."); if(conversion_rule < RDI_EvalConversionKind_COUNT) { text.str = rdi_explanation_string_from_eval_conversion_kind(conversion_rule, &text.size); } e_msg(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, text); break; } // rjf: generate { E_IRNode *in_tree = e_irtree_resolve_to_value(arena, casted_tree.mode, casted_tree.root, casted_type); E_IRNode *new_tree = in_tree; if(conversion_rule == RDI_EvalConversionKind_Legal) { new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group); } if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_unwrapped_kind)) { new_tree = e_irtree_trunc(arena, in_tree, cast_type); } if(e_type_kind_is_signed(cast_type_unwrapped_kind) && e_type_kind_is_integer(casted_type_unwrapped_kind) && !e_type_kind_is_signed(casted_type_unwrapped_kind)) { new_tree = e_irtree_trunc(arena, in_tree, cast_type); } result.root = new_tree; result.type_key = cast_type; result.mode = E_Mode_Value; } }break; //- rjf: sizeof case E_ExprKind_Sizeof: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_TypeKey r_type = zero_struct; E_Space space = r_expr->space; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 1, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); r_type = r_tree.type_key; // rjf: bad conditions? -> error if applicable, exit if(e_type_key_match(r_type, e_type_key_zero())) { break; } else if(e_type_kind_from_key(r_type) == E_TypeKind_Null) { break; } // rjf: generate { U64 r_type_byte_size = e_type_byte_size_from_key(r_type); result.root = e_irtree_const_u(arena, r_type_byte_size); result.type_key = e_type_key_basic(E_TypeKind_U64); result.mode = E_Mode_Value; } }break; //- rjf: typeof case E_ExprKind_Typeof: { // rjf: evaluate operand tree E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 1, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); // rjf: find the first non-autohook result E_TypeKey type_key = r_tree.type_key; for(E_IRTreeAndType *t = &r_tree; t != 0; t = t->prev) { type_key = t->type_key; if(t->auto_hook == 0) { break; } } // rjf: fill output result.root = e_irtree_const_u(arena, 0); result.type_key = type_key; result.mode = E_Mode_Null; }break; //- rjf: symbolof case E_ExprKind_Symbolof: { E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_tree.type_key); E_OpList oplist = e_oplist_from_irtree(scratch.arena, r_value_tree); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpretation = e_interpret(bytecode); E_Module *module = &e_module_nil; for EachIndex(idx, e_base_ctx->modules_count) { E_Module *m = &e_base_ctx->modules[idx]; if(e_space_match(interpretation.space, m->space) && contains_1u64(m->vaddr_range, interpretation.value.u64)) { module = m; break; } } if(module != &e_module_nil) { E_DbgInfo *dbg_info = e_dbg_info_from_module(module); U64 voff = interpretation.value.u64 - module->vaddr_range.min; U64 new_vaddr = 0; RDI_Procedure *p = rdi_procedure_from_voff(dbg_info->rdi, voff); RDI_GlobalVariable *g = rdi_global_variable_from_voff(dbg_info->rdi, voff); U32 type_idx = 0; if(p->name_string_idx != 0) { type_idx = p->type_idx; new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(dbg_info->rdi, p); } else if(g->name_string_idx != 0) { type_idx = g->type_idx; new_vaddr = module->vaddr_range.min + g->voff; } if(type_idx != 0) { RDI_TypeNode *t = rdi_element_from_name_idx(dbg_info->rdi, TypeNodes, type_idx); result.root = e_irtree_const_u(arena, new_vaddr); result.mode = E_Mode_Value; result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, module->dbg_info_num); } } }break; //- rjf: byteswap case E_ExprKind_ByteSwap: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); U64 r_type_size = e_type_byte_size_from_key(r_type); // rjf: bad conditions? -> error if applicable, exit if(!e_type_kind_is_integer(r_type_kind) || (r_type_size != 8 && r_type_size != 4 && r_type_size != 2)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Byteswapping this type is not supported."); break; } // rjf: generate { E_IRNode *node = e_push_irnode(arena, RDI_EvalOp_ByteSwap); E_IRNode *rhs = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); e_irnode_push_child(node, rhs); node->value.u64 = r_type_size; result.root = node; result.mode = E_Mode_Value; result.type_key = r_type; } }break; //- rjf: unary operations case E_ExprKind_Pos: { result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); }break; case E_ExprKind_Neg: case E_ExprKind_BitNot: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); E_TypeKey r_type_promoted = e_type_key_promote(r_type); RDI_EvalOp op = e_opcode_from_expr_kind(kind); // rjf: bad conditions? -> error if applicable, exit if(r_tree.root->op == 0) { break; } else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Cannot use this operator on this type."); break; } // rjf: generate { E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); result.root = new_tree; result.type_key = r_type_promoted; result.mode = E_Mode_Value; } }break; case E_ExprKind_LogNot: { // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); E_TypeKey r_type_promoted = e_type_key_basic(E_TypeKind_Bool); RDI_EvalOp op = e_opcode_from_expr_kind(kind); // rjf: bad conditions? -> error if applicable, exit if(r_tree.root->op == 0) { break; } else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Cannot use this operator on this type."); break; } // rjf: generate { E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); result.root = new_tree; result.type_key = r_type_promoted; result.mode = E_Mode_Value; } }break; //- rjf: binary operations case E_ExprKind_Mul: case E_ExprKind_Div: case E_ExprKind_Mod: case E_ExprKind_Add: case E_ExprKind_Sub: case E_ExprKind_LShift: case E_ExprKind_RShift: case E_ExprKind_Less: case E_ExprKind_LsEq: case E_ExprKind_Grtr: case E_ExprKind_GrEq: case E_ExprKind_EqEq: case E_ExprKind_NtEq: case E_ExprKind_BitAnd: case E_ExprKind_BitXor: case E_ExprKind_BitOr: case E_ExprKind_LogAnd: case E_ExprKind_LogOr: { // rjf: unpack operands RDI_EvalOp op = e_opcode_from_expr_kind(kind); B32 is_comparison = e_expr_kind_is_comparison(kind); E_Expr *l_expr = expr->first; E_Expr *r_expr = l_expr->next; E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, l_expr); E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey l_type = e_type_key_unwrap(l_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind l_type_kind = e_type_kind_from_key(l_type); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); U64 l_type_size = e_type_byte_size_from_key(l_type); U64 r_type_size = e_type_byte_size_from_key(r_type); U64 op_operand_size = Max(l_type_size, r_type_size); // rjf: resolve complex types to simple arithmetic tyeps if(l_type_kind == E_TypeKind_Bitfield) { l_tree.root = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_tree.type_key); l_type = e_type_key_unwrap(e_type_key_direct(l_tree.type_key), E_TypeUnwrapFlag_AllDecorative); l_type_kind = e_type_kind_from_key(r_type); l_tree.mode = E_Mode_Value; } if(r_type_kind == E_TypeKind_Bitfield) { r_tree.root = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_tree.type_key); r_type = e_type_key_unwrap(e_type_key_direct(r_tree.type_key), E_TypeUnwrapFlag_AllDecorative); r_type_kind = e_type_kind_from_key(r_type); r_tree.mode = E_Mode_Value; } if(l_type.kind == E_TypeKeyKind_Reg) { l_type_kind = E_TypeKind_U64; l_type = e_type_key_basic(l_type_kind); } if(r_type.kind == E_TypeKeyKind_Reg) { r_type_kind = E_TypeKind_U64; r_type = e_type_key_basic(r_type_kind); } // rjf: unpack info about resolved types B32 l_is_pointer = (l_type_kind == E_TypeKind_Ptr); B32 l_is_decay = (l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Offset); B32 l_is_pointer_like = (l_is_pointer || l_is_decay); B32 r_is_pointer = (r_type_kind == E_TypeKind_Ptr); B32 r_is_decay = (r_type_kind == E_TypeKind_Array && r_tree.mode == E_Mode_Offset); B32 r_is_pointer_like = (r_is_pointer || r_is_decay); RDI_EvalTypeGroup l_type_group = e_type_group_from_kind(l_type_kind); RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); // rjf: bad conditions? -> error if applicable, exit if(l_tree.root->op == 0 || r_tree.root->op == 0) { break; } // rjf: determine arithmetic path #define E_ArithPath_Normal 0 #define E_ArithPath_PtrAdd 1 #define E_ArithPath_PtrSub 2 #define E_ArithPath_PtrArrayCompare 3 #define E_ArithPath_TypeCompare 4 B32 ptr_arithmetic_mul_rptr = 0; U32 arith_path = E_ArithPath_Normal; if(kind == E_ExprKind_Add) { if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) { arith_path = E_ArithPath_PtrAdd; } if(l_is_pointer_like && e_type_kind_is_integer(l_type_kind)) { arith_path = E_ArithPath_PtrAdd; ptr_arithmetic_mul_rptr = 1; } } else if(kind == E_ExprKind_Sub) { if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) { arith_path = E_ArithPath_PtrAdd; } if(l_is_pointer_like && r_is_pointer_like) { E_TypeKey l_type_direct = e_type_key_unwrap(l_type, E_TypeUnwrapFlag_All); E_TypeKey r_type_direct = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_All); U64 l_type_direct_byte_size = e_type_byte_size_from_key(l_type_direct); U64 r_type_direct_byte_size = e_type_byte_size_from_key(r_type_direct); if(l_type_direct_byte_size == r_type_direct_byte_size) { arith_path = E_ArithPath_PtrSub; } } } else if(kind == E_ExprKind_EqEq || kind == E_ExprKind_NtEq) { if(l_type_kind == E_TypeKind_Array && (r_type_kind == E_TypeKind_Ptr || r_is_decay)) { arith_path = E_ArithPath_PtrArrayCompare; } if(r_type_kind == E_TypeKind_Array && (l_type_kind == E_TypeKind_Ptr || l_is_decay)) { arith_path = E_ArithPath_PtrArrayCompare; } if(l_tree.mode == E_Mode_Null && r_tree.mode == E_Mode_Null) { arith_path = E_ArithPath_TypeCompare; } } // rjf: generate according to arithmetic path switch(arith_path) { //- rjf: normal arithmetic case E_ArithPath_Normal: { // rjf: bad conditions? -> error if applicable, exit if(!rdi_eval_op_typegroup_are_compatible(op, l_type_group) || !rdi_eval_op_typegroup_are_compatible(op, r_type_group)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Cannot use this operator on this type."); break; } // rjf: generate { E_TypeKey final_type_key = is_comparison ? e_type_key_basic(E_TypeKind_Bool) : l_type; E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); l_value_tree = e_irtree_convert_hi(arena, l_value_tree, l_type, l_type); r_value_tree = e_irtree_convert_hi(arena, r_value_tree, l_type, r_type); E_IRNode *new_tree = e_irtree_binary_op(arena, op, l_type_group, op_operand_size, l_value_tree, r_value_tree); result.root = new_tree; result.type_key = final_type_key; result.mode = E_Mode_Value; } }break; //- rjf: pointer addition case E_ArithPath_PtrAdd: { // rjf: map l/r to ptr/int E_IRTreeAndType *ptr_tree = &l_tree; E_IRTreeAndType *int_tree = &r_tree; U64 ptr_size = l_type_size; B32 ptr_is_decay = l_is_decay; if(ptr_arithmetic_mul_rptr) { ptr_tree = &r_tree; ptr_size = r_type_size; int_tree = &l_tree; ptr_is_decay = r_is_decay; } // rjf: unpack type E_TypeKey direct_type = e_type_key_unwrap(ptr_tree->type_key, E_TypeUnwrapFlag_All); U64 direct_type_size = e_type_byte_size_from_key(direct_type); // rjf: generate { E_IRNode *ptr_root = ptr_tree->root; if(!ptr_is_decay) { ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_root, ptr_tree->type_key); } E_IRNode *int_root = int_tree->root; int_root = e_irtree_resolve_to_value(arena, int_tree->mode, int_root, int_tree->type_key); if(direct_type_size > 1) { E_IRNode *const_root = e_irtree_const_u(arena, direct_type_size); int_root = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, ptr_size, int_root, const_root); } E_TypeKey ptr_type = ptr_tree->type_key; if(ptr_is_decay) { ptr_type = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, direct_type, 1, 0); } E_IRNode *new_root = e_irtree_binary_op_u(arena, op, ptr_size, ptr_root, int_root); result.root = new_root; result.type_key = ptr_type; result.mode = E_Mode_Value; } }break; //- rjf: pointer subtraction case E_ArithPath_PtrSub: { // rjf: unpack type E_TypeKey direct_type = e_type_key_unwrap(l_type, E_TypeUnwrapFlag_All); U64 direct_type_size = e_type_byte_size_from_key(direct_type); // rjf: generate E_IRNode *l_root = l_tree.root; E_IRNode *r_root = r_tree.root; if(!l_is_decay) { l_root = e_irtree_resolve_to_value(arena, l_tree.mode, l_root, l_type); } if(!r_is_decay) { r_root = e_irtree_resolve_to_value(arena, r_tree.mode, r_root, r_type); } E_IRNode *op_tree = e_irtree_binary_op_u(arena, op, l_type_size, l_root, r_root); E_IRNode *new_tree = op_tree; if(direct_type_size > 1) { E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Div, l_type_size, new_tree, const_tree); } result.root = new_tree; result.type_key = e_type_key_basic(E_TypeKind_U64); result.mode = E_Mode_Value; }break; //- rjf: pointer array comparison case E_ArithPath_PtrArrayCompare: { // rjf: map l/r to pointer/array B32 ptr_is_decay = l_is_decay; E_IRTreeAndType *ptr_tree = &l_tree; E_IRTreeAndType *arr_tree = &r_tree; U64 ptr_size = l_type_size; if(l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Value) { ptr_is_decay = r_is_decay; ptr_tree = &r_tree; arr_tree = &l_tree; ptr_size = r_type_size; } // rjf: resolve pointer to value, sized same as array E_IRNode *ptr_root = ptr_tree->root; E_IRNode *arr_root = arr_tree->root; if(!ptr_is_decay) { ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_tree->root, ptr_tree->type_key); } // rjf: read from pointer into value, to compare with array E_IRNode *mem_root = e_irtree_mem_read_type(arena, ptr_root, arr_tree->type_key); // rjf: generate result.root = e_irtree_binary_op(arena, op, RDI_EvalTypeGroup_Other, ptr_size, mem_root, arr_root); result.type_key = e_type_key_basic(E_TypeKind_Bool); result.mode = E_Mode_Value; }break; //- rjf: type comparison case E_ArithPath_TypeCompare: { result.root = e_irtree_const_u(arena, !!e_type_match(l_type, r_type)); result.type_key = e_type_key_basic(E_TypeKind_Bool); result.mode = E_Mode_Value; }break; } }break; //- rjf: ternary operators case E_ExprKind_Ternary: { // rjf: unpack operands E_Expr *c_expr = expr->first; E_Expr *l_expr = c_expr->next; E_Expr *r_expr = l_expr->next; E_IRTreeAndType c_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, c_expr); E_IRTreeAndType l_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, l_expr); E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, r_expr); e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey c_type = e_type_key_unwrap(c_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey l_type = e_type_key_unwrap(l_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind c_type_kind = e_type_kind_from_key(c_type); E_TypeKind l_type_kind = e_type_kind_from_key(l_type); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); // rjf: bad conditions? -> error if applicable, exit if(c_tree.root->op == 0 || l_tree.root->op == 0 || r_tree.root->op == 0) { break; } else if(!e_type_kind_is_integer(c_type_kind) && c_type_kind != E_TypeKind_Bool) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Conditional term must be an integer or boolean type."); } // rjf: determine the resultant type - if the left/right types match, then we // can just pick the left type, and defer 100% of our interpretation. however, // if the types do *not* match, then we need to pre-emptively evaluate the // condition, and pick the result based on that. B32 ternary_is_dynamic = 0; E_TypeKey result_type = l_type; if(!e_type_match(l_type, r_type)) { ternary_is_dynamic = 1; } // rjf: generate dynamic ternary if(ternary_is_dynamic) { E_IRNode *c_value_tree = e_irtree_resolve_to_value(arena, c_tree.mode, c_tree.root, c_type); E_OpList oplist = e_oplist_from_irtree(scratch.arena, c_value_tree); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpretation = e_interpret(bytecode); if(interpretation.value.u64 != 0) { result = l_tree; } else { result = r_tree; } } // rjf: generate static ternary else { E_IRNode *c_value_tree = e_irtree_resolve_to_value(arena, c_tree.mode, c_tree.root, c_type); E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); l_value_tree = e_irtree_convert_hi(arena, l_value_tree, result_type, l_type); r_value_tree = e_irtree_convert_hi(arena, r_value_tree, result_type, r_type); E_IRNode *new_tree = e_irtree_conditional(arena, c_value_tree, l_value_tree, r_value_tree); result.root = new_tree; result.type_key = result_type; result.mode = E_Mode_Value; } }break; //- rjf: call case E_ExprKind_Call: { B32 strip_lenses = 0; E_Expr *lhs = expr->first; E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_callable_identifier_resolution_rule, disallow_autohooks, 1, lhs); e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs); E_TypeKey lhs_type_key = lhs_irtree.type_key; E_Type *lhs_type = e_type_from_key(lhs_type_key); // rjf: calling a type? -> treat as a cast of that type if(lhs_irtree.mode == E_Mode_Null && lhs_type != &e_type_nil && lhs_type->kind != E_TypeKind_Lens && lhs_type->kind != E_TypeKind_LensSpec) { E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first->next); e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); E_TypeKey cast_type = lhs_irtree.type_key; E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); E_TypeKey cast_type_unwrapped = e_type_key_unwrap(lhs_irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind cast_type_unwrapped_kind = e_type_kind_from_key(cast_type_unwrapped); U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type); E_TypeKey casted_type = casted_tree.type_key; E_TypeKey casted_type_unwrapped = e_type_key_unwrap(casted_type, E_TypeUnwrapFlag_Bitfields|E_TypeUnwrapFlag_AllDecorative); E_TypeKind casted_type_unwrapped_kind = e_type_kind_from_key(casted_type_unwrapped); U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type); U8 in_group = e_type_group_from_kind(casted_type_unwrapped_kind); U8 out_group = e_type_group_from_kind(cast_type_unwrapped_kind); RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group); // rjf: bad conditions? -> error if applicable, exit if(casted_tree.root->op == 0) { break; } else if(cast_type_kind == E_TypeKind_Null) { break; } else if(conversion_rule != RDI_EvalConversionKind_Noop && conversion_rule != RDI_EvalConversionKind_Legal) { String8 text = str8_lit("Unknown cast conversion rule."); if(conversion_rule < RDI_EvalConversionKind_COUNT) { text.str = rdi_explanation_string_from_eval_conversion_kind(conversion_rule, &text.size); } e_msg(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, text); break; } // rjf: generate { E_IRNode *in_tree = e_irtree_resolve_to_value(arena, casted_tree.mode, casted_tree.root, casted_type); E_IRNode *new_tree = in_tree; if(conversion_rule == RDI_EvalConversionKind_Legal) { new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group); } if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_unwrapped_kind)) { new_tree = e_irtree_trunc(arena, in_tree, cast_type); } if(e_type_kind_is_signed(cast_type_unwrapped_kind) && e_type_kind_is_integer(casted_type_unwrapped_kind) && !e_type_kind_is_signed(casted_type_unwrapped_kind)) { new_tree = e_irtree_trunc(arena, in_tree, cast_type); } result.root = new_tree; result.type_key = cast_type; result.mode = E_Mode_Value; } } // rjf: calling an unresolved leaf-identifier member access, and we can determine // that that identifer maps to a type? -> generate a call expression with the // left-hand-side of the dot operator as the first argument. this is a fast path // which prevents paren nesting in simple cases, to easily chain multiple // calls - for example, bin(2).digits(4) else if(lhs->kind == E_ExprKind_MemberAccess && lhs->first->next != &e_expr_nil) { E_Expr *callee = e_expr_ref(arena, lhs->first->next); E_Expr *first_arg = e_expr_ref(arena, lhs->first); E_Expr *call = e_push_expr(arena, E_ExprKind_Call, r1u64(0, 0)); e_expr_push_child(call, callee); e_expr_push_child(call, first_arg); for(E_Expr *arg = lhs->next; arg != &e_expr_nil; arg = arg->next) { e_expr_push_child(call, e_expr_copy(arena, arg)); } if(str8_match(callee->ref->string, str8_lit("raw"), 0)) { strip_lenses = 1; disallow_autohooks = 1; } result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, call); // NOTE(rjf): we do not want to accumulate messages from the original left-hand-side evaluation in this case, because // this path only occurs if the member access fails specifically. } // rjf: calling a lens? -> generate IR for the first argument; if enabled, wrap // the type in a lens type, which preserves the name & arguments of the lens call // expression else if(lhs_type->kind == E_TypeKind_LensSpec) { // rjf: is "raw"? -> disable hooks if(str8_match(lhs_type->name, str8_lit("raw"), 0)) { strip_lenses = 1; disallow_autohooks = 1; } // rjf: generate result via first argument to lens result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, lhs->next); // rjf: if not raw, wrap resultant type with lens type if(!strip_lenses) { Temp scratch = scratch_begin(&arena, 1); // rjf: count extra arguments U64 arg_count = 0; for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next) { arg_count += 1; } // rjf: flatten extra arguments E_Expr **args = push_array(scratch.arena, E_Expr *, arg_count); { U64 idx = 0; for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next, idx += 1) { args[idx] = arg; } } // rjf: patch resultant type with a lens w/ args, pointing to the original type { result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .flags = lhs_type->flags, .count = arg_count, .args = args, .direct_key = result.type_key, .name = lhs_type->name, .irext = lhs_type->irext, .access = lhs_type->access, .expand = lhs_type->expand); } scratch_end(scratch); } } // rjf: calling any other type? -> not valid else { e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->range, "Calling this type is not supported."); } // rjf: strip overrides and lenses if needed if(strip_lenses) { if(t->overridden) { E_MsgList existing_msgs = result.msgs; for(E_IRTreeAndType *prev = t->overridden; prev != 0; prev = prev->prev) { result = *prev; } E_MsgList overridden_msgs = e_msg_list_copy(arena, &result.msgs); result.msgs = existing_msgs; e_msg_list_concat_in_place(&result.msgs, &overridden_msgs); } result.type_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_Lenses|E_TypeUnwrapFlag_Meta); } }break; //- rjf: leaf bytecode case E_ExprKind_LeafBytecode: { E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->bytecode); new_tree->space = expr->space; E_TypeKey final_type_key = expr->type_key; result.root = new_tree; result.type_key = final_type_key; result.mode = expr->mode; }break; //- rjf: leaf string literal case E_ExprKind_LeafStringLiteral: { String8 string = expr->string; E_TypeKey type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_UChar8), string.size, 0); E_IRNode *new_tree = e_irtree_string_literal(arena, string); result.root = new_tree; result.type_key = type_key; result.mode = E_Mode_Value; }break; //- rjf: leaf U64s case E_ExprKind_LeafU64: { U64 val = expr->value.u64; E_IRNode *new_tree = e_irtree_const_u(arena, val); E_TypeKey type_key = zero_struct; if(0){} else if(val <= max_S32){type_key = e_type_key_basic(E_TypeKind_S32);} else if(val <= max_S64){type_key = e_type_key_basic(E_TypeKind_S64);} else {type_key = e_type_key_basic(E_TypeKind_U64);} result.root = new_tree; result.type_key = type_key; result.mode = E_Mode_Value; }break; //- rjf: leaf F64s case E_ExprKind_LeafF64: { U64 val = expr->value.u64; E_IRNode *new_tree = e_irtree_const_u(arena, val); result.root = new_tree; result.type_key = e_type_key_basic(E_TypeKind_F64); result.mode = E_Mode_Value; }break; //- rjf: leaf F32s case E_ExprKind_LeafF32: { U32 val = expr->value.u32; E_IRNode *new_tree = e_irtree_const_u(arena, val); result.root = new_tree; result.type_key = e_type_key_basic(E_TypeKind_F32); result.mode = E_Mode_Value; }break; //- rjf: leaf identifiers case E_ExprKind_LeafIdentifier: { Temp scratch = scratch_begin(&arena, 1); String8 qualifier = expr->qualifier; String8 string = expr->string; String8 string__redirected = string; B32 string_mapped = 0; B32 string_is_implicit_member_name = 0; E_TypeKey mapped_type_key = zero_struct; E_Module *mapped_location_block_module = &e_module_nil; RDI_LocationBlock *mapped_location_block = 0; E_Mode mapped_bytecode_mode = E_Mode_Offset; E_Space mapped_bytecode_space = zero_struct; String8 mapped_bytecode = {0}; void *mapped_user_data = 0; B32 generated = 0; //- rjf: iterate identifier resolution rule paths, try to resolve // identifier in that order. for(U64 path_idx = 0; !generated && path_idx < identifier_resolution_rule->count; path_idx += 1) { //- rjf: try to map identifier via this path E_IdentifierResolutionPath path = identifier_resolution_rule->paths[path_idx]; ProfScope("identifier resolution %i", path) switch(path) { default:{}break; //- rjf: try to map name as a wildcard instance case E_IdentifierResolutionPath_WildcardInst: if(!generated && qualifier.size == 0 && !string_mapped && e_cache->first_wildcard_inst != 0) { for(E_AutoHookWildcardInst *inst = e_cache->first_wildcard_inst; inst != 0; inst = inst->next) { if(str8_match(inst->name, string, 0)) { generated = 1; result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, inst->inst_expr); break; } } }break; //- rjf: try to map name as parent expression signifier ('$') case E_IdentifierResolutionPath_ParentExpr: if(qualifier.size == 0 && !string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) { E_IRTreeAndType *parent_irtree = parent; { for(E_IRTreeAndType *prev = parent_irtree; prev != 0; prev = prev->prev) { parent_irtree = prev; if(prev->root != &e_irnode_nil) { break; } } } string_mapped = 1; generated = 1; disallow_autohooks = 1; E_OpList oplist = e_oplist_from_irtree(scratch.arena, parent_irtree->root); String8 bytecode = e_bytecode_from_oplist(arena, &oplist); result.root = e_irtree_bytecode_no_copy(arena, bytecode); result.type_key = parent_irtree->type_key; result.mode = parent_irtree->mode; result.auto_hook = parent_irtree->auto_hook; E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); e_msg_list_concat_in_place(&result.msgs, &msgs); result.prev = parent_irtree->prev; } break; //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) case E_IdentifierResolutionPath_ParentExprMember: if(qualifier.size == 0 && !string_mapped && parent != 0 && parent->root != &e_irnode_nil) { for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev) { E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string); E_IRTreeAndType access_parent = {&e_irnode_nil}; E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev->prev ? prev->prev : &access_parent, &e_default_identifier_resolution_rule, 1, 1, access); if(access_irtree.root != &e_irnode_nil) { string_mapped = 1; E_OpList oplist = e_oplist_from_irtree(scratch.arena, access_irtree.root); mapped_type_key = access_irtree.type_key; mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = access_irtree.mode; e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); if(!prev->auto_hook) { break; } } } }break; //- rjf: try to map name as member of `this` - if found, string__redirected := "this", and turn // on later implicit-member-lookup generation case E_IdentifierResolutionPath_ImplicitThisMember: if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) { E_Module *module = e_base_ctx->primary_module; E_DbgInfo *dbg_info = e_dbg_info_from_module(module); RDI_Parsed *rdi = dbg_info->rdi; RDI_Procedure *procedure = e_cache->thread_ip_procedure; RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module->dbg_info_num); E_Member member = e_type_member_from_key_name__cached(container_type_key, string); if(member.kind != E_MemberKind_Null) { string_is_implicit_member_name = 1; string__redirected = str8_lit("this"); } }break; //- rjf: try locals case E_IdentifierResolutionPath_Local: if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) { E_Module *module = e_base_ctx->primary_module; E_DbgInfo *dbg_info = e_dbg_info_from_module(module); RDI_Parsed *rdi = dbg_info->rdi; U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected); if(local_num != 0) { RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1); // rjf: extract local's type key RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module->dbg_info_num); // rjf: extract local's location block B32 got_location_block = 0; U64 ip_voff = e_base_ctx->thread_ip_voff; for(U32 loc_block_idx = local->location_first; loc_block_idx < local->location_opl; loc_block_idx += 1) { RDI_LocationBlock *block = rdi_element_from_name_idx(rdi, LocationBlocks, loc_block_idx); if(block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) { mapped_location_block_module = module; mapped_location_block = block; got_location_block = 1; } } // rjf: no location block -> error if(!got_location_block) { e_msgf(arena, &result.msgs, E_MsgKind_MissingInfo, expr->range, "Could not find location info for `%S`.", string__redirected); } } }break; //- rjf: built-in constants case E_IdentifierResolutionPath_BuiltInConstants: { // rjf: "true" if(!string_mapped && str8_match(string, str8_lit("true"), 0)) { string_mapped = 1; E_OpList oplist = {0}; e_oplist_push_uconst(arena, &oplist, 1); mapped_type_key = e_type_key_basic(E_TypeKind_Bool); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; } // rjf: "false" if(!string_mapped && str8_match(string, str8_lit("false"), 0)) { string_mapped = 1; E_OpList oplist = {0}; e_oplist_push_uconst(arena, &oplist, 0); mapped_type_key = e_type_key_basic(E_TypeKind_Bool); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; } }break; //- rjf: built-in types case E_IdentifierResolutionPath_BuiltInTypes: { mapped_type_key = e_leaf_builtin_type_key_from_name(string); string_mapped = !e_type_key_match(mapped_type_key, e_type_key_zero()); }break; //- rjf: debug info matches case E_IdentifierResolutionPath_DebugInfoMatch: { if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("symbol"), 0))) { Access *access = access_open(); // rjf: find match DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0); if(match.idx == 0) { String8List namespaceified_strings = {0}; { E_Module *module = e_base_ctx->primary_module; E_DbgInfo *dbg_info = e_dbg_info_from_module(module); RDI_Parsed *rdi = dbg_info->rdi; RDI_Procedure *procedure = e_cache->thread_ip_procedure; U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); String8 containing_procedure_name = str8(name_ptr, name_size); U64 last_past_scope_resolution_pos = 0; for(;;) { U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2; U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1; U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos); if(past_next_scope_resolution_pos >= containing_procedure_name.size) { break; } String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos); String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string); str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string); last_past_scope_resolution_pos = past_next_scope_resolution_pos; } } for(String8Node *n = namespaceified_strings.first; n != 0; n = n->next) { match = di_match_from_string(n->string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0); if(match.idx != 0) { break; } } } // rjf: match -> RDI RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0); // rjf: find dbg info from rdi E_DbgInfo *dbg_info = &e_dbg_info_nil; U32 dbg_info_num = 0; for EachIndex(idx, e_base_ctx->dbg_infos_count) { if(e_base_ctx->dbg_infos[idx].rdi == rdi) { dbg_info = &e_base_ctx->dbg_infos[idx]; dbg_info_num = idx+1; break; } } // rjf: find module from dbgi key E_Module *module = &e_module_nil; for EachIndex(idx, e_base_ctx->modules_count) { if(e_base_ctx->modules[idx].dbg_info_num == dbg_info_num) { module = &e_base_ctx->modules[idx]; if(module == e_base_ctx->primary_module || e_space_match(module->space, e_base_ctx->primary_module->space)) { break; } } } // rjf: form result if(match.idx != 0 && dbg_info != &e_dbg_info_nil) { switch(match.section_kind) { default:{}break; case RDI_SectionKind_GlobalVariables: { RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match.idx); U32 type_idx = global_var->type_idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); E_OpList oplist = {0}; e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); string_mapped = 1; mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = module->space; }break; case RDI_SectionKind_ThreadVariables: { RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match.idx); U32 type_idx = thread_var->type_idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); E_OpList oplist = {0}; e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); string_mapped = 1; mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = module->space; }break; case RDI_SectionKind_Constants: { RDI_Constant *constant = rdi_element_from_name_idx(rdi, Constants, match.idx); U32 type_idx = constant->type_idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); RDI_U32 constant_value_off = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx); RDI_U32 constant_value_size = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx+1) - constant_value_off; if(constant_value_size <= 8) { RDI_U64 constant_value_data_size = 0; RDI_U8 *constant_value_data = rdi_table_from_name(rdi, ConstantValueData, &constant_value_data_size); if(0 <= constant_value_off && constant_value_off + constant_value_size <= constant_value_data_size) { RDI_U64 value = 0; MemoryCopy(&value, constant_value_data+constant_value_off, constant_value_size); E_OpList oplist = {0}; e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value)); string_mapped = 1; mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; mapped_bytecode_space = module->space; break; } } }break; case RDI_SectionKind_Procedures: { RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match.idx); RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); U32 type_idx = procedure->type_idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); E_OpList oplist = {0}; e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); string_mapped = 1; mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; mapped_bytecode_space = module->space; }break; case RDI_SectionKind_TypeNodes: { U32 type_idx = match.idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num); string_mapped = 1; }break; } } access_close(access); } }break; //- rjf: try registers case E_IdentifierResolutionPath_Registers: if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) { U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string); if(reg_num != 0) { string_mapped = 1; REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[reg_num]; E_OpList oplist = {0}; e_oplist_push_uconst(arena, &oplist, reg_rng.byte_off); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = e_base_ctx->thread_reg_space; REGS_UsageKind reg_usage_kind = regs_reg_code_usage_kind_table_from_arch(e_base_ctx->primary_module->arch)[reg_num]; if(0){} else if(reg_usage_kind == REGS_UsageKind_Normal && reg_rng.byte_size == 1) {mapped_type_key = e_type_key_basic(E_TypeKind_U8);} else if(reg_usage_kind == REGS_UsageKind_Normal && reg_rng.byte_size == 2) {mapped_type_key = e_type_key_basic(E_TypeKind_U16);} else if(reg_usage_kind == REGS_UsageKind_Normal && reg_rng.byte_size == 4) {mapped_type_key = e_type_key_basic(E_TypeKind_U32);} else if(reg_usage_kind == REGS_UsageKind_Normal && reg_rng.byte_size == 8) {mapped_type_key = e_type_key_basic(E_TypeKind_U64);} else { mapped_type_key = e_type_key_reg(e_base_ctx->primary_module->arch, reg_num); } } }break; //- rjf: try register aliases case E_IdentifierResolutionPath_RegisterAliases: if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) { U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string); if(alias_num != 0) { string_mapped = 1; REGS_Slice alias_slice = regs_alias_code_slice_table_from_arch(e_base_ctx->primary_module->arch)[alias_num]; REGS_Rng alias_reg_rng = regs_reg_code_rng_table_from_arch(e_base_ctx->primary_module->arch)[alias_slice.code]; E_OpList oplist = {0}; e_oplist_push_uconst(arena, &oplist, alias_reg_rng.byte_off + alias_slice.byte_off); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = e_base_ctx->thread_reg_space; REGS_UsageKind reg_usage_kind = regs_alias_code_usage_kind_table_from_arch(e_base_ctx->primary_module->arch)[alias_num]; if(0){} else if(reg_usage_kind == REGS_UsageKind_Normal && alias_slice.byte_size == 1) {mapped_type_key = e_type_key_basic(E_TypeKind_U8);} else if(reg_usage_kind == REGS_UsageKind_Normal && alias_slice.byte_size == 2) {mapped_type_key = e_type_key_basic(E_TypeKind_U16);} else if(reg_usage_kind == REGS_UsageKind_Normal && alias_slice.byte_size == 4) {mapped_type_key = e_type_key_basic(E_TypeKind_U32);} else if(reg_usage_kind == REGS_UsageKind_Normal && alias_slice.byte_size == 8) {mapped_type_key = e_type_key_basic(E_TypeKind_U64);} else { mapped_type_key = e_type_key_reg_alias(e_base_ctx->primary_module->arch, alias_num); } } }break; //- rjf: try macros case E_IdentifierResolutionPath_Macros: { if(!generated) { E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, string); if(macro_expr != &e_expr_nil) { generated = 1; e_string2expr_map_inc_poison(e_ir_ctx->macro_map, string); result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, macro_expr); e_string2expr_map_dec_poison(e_ir_ctx->macro_map, string); } } }break; } //- rjf: mapped to location block -> extract or produce bytecode for this mapping if(!generated && mapped_location_block != 0) { E_Module *module = mapped_location_block_module; E_DbgInfo *dbg_info = e_dbg_info_from_module(module); E_Space space = module->space; Arch arch = module->arch; RDI_Parsed *rdi = dbg_info->rdi; RDI_LocationBlock *block = mapped_location_block; U64 all_location_data_size = 0; U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) { RDI_LocationKind loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); switch(loc_kind) { default:{}break; case RDI_LocationKind_ValBytecodeStream: {mapped_bytecode_mode = E_Mode_Value;}goto bytecode_stream; case RDI_LocationKind_AddrBytecodeStream:{mapped_bytecode_mode = E_Mode_Offset;}goto bytecode_stream; bytecode_stream:; { string_mapped = 1; U64 bytecode_size = 0; U64 off_first = block->location_data_off + sizeof(RDI_LocationKind); U64 off_opl = all_location_data_size; for(U64 off = off_first, next_off = off_opl; off < all_location_data_size; off = next_off) { next_off = off_opl; U8 op = all_location_data[off]; if(op == 0) { break; } U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); bytecode_size += (1 + p_size); next_off = (off + 1 + p_size); } mapped_bytecode = str8(all_location_data + off_first, bytecode_size); }break; case RDI_LocationKind_AddrRegPlusU16: if(block->location_data_off + sizeof(RDI_LocationRegPlusU16) <= all_location_data_size) { string_mapped = 1; RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); E_OpList oplist = {0}; U64 byte_size = bit_size_from_arch(arch)/8; U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = space; }break; case RDI_LocationKind_AddrAddrRegPlusU16: { string_mapped = 1; RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); E_OpList oplist = {0}; U64 byte_size = bit_size_from_arch(arch)/8; U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); e_oplist_push_op(arena, &oplist, RDI_EvalOp_MemRead, e_value_u64(bit_size_from_arch(arch)/8)); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Offset; mapped_bytecode_space = space; }break; case RDI_LocationKind_ValReg: if(block->location_data_off + sizeof(RDI_LocationReg) <= all_location_data_size) { string_mapped = 1; RDI_LocationReg loc = *(RDI_LocationReg *)(all_location_data + block->location_data_off); REGS_RegCode regs_reg_code = regs_reg_code_from_arch_rdi_code(arch, loc.reg_code); REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(arch)[regs_reg_code]; E_OpList oplist = {0}; U64 byte_size = (U64)reg_rng.byte_size; U64 byte_pos = 0; U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, byte_pos); e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = E_Mode_Value; mapped_bytecode_space = space; }break; } } } //- rjf: generate IR trees for bytecode if(!generated && mapped_bytecode.size != 0) { generated = 1; E_IRNode *root = e_irtree_bytecode_no_copy(arena, mapped_bytecode); root->space = mapped_bytecode_space; result.root = root; result.type_key = mapped_type_key; result.mode = mapped_bytecode_mode; } //- rjf: generate nil-IR trees w/ type for types if(!generated && !e_type_key_match(e_type_key_zero(), mapped_type_key)) { generated = 1; result.root = e_irtree_const_u(arena, 0); result.type_key = mapped_type_key; result.mode = E_Mode_Null; } } //- rjf: extend generated result, if result was generated by an implicit member access if(generated && string_is_implicit_member_name) { E_Expr *access = e_expr_irext_member_access(arena, &e_expr_nil, &result, string); result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, access); } //- rjf: error on failure-to-generate if(!generated && !str8_match(string, str8_lit("$"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_ResolutionFailure, expr->range, "`%S` could not be found.", string); } scratch_end(scratch); }break; //- rjf: leaf offsets case E_ExprKind_LeafOffset: { E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU64); new_tree->value = expr->value; new_tree->space = expr->space; result.root = new_tree; result.type_key = expr->type_key; result.mode = E_Mode_Offset; }break; //- rjf: leaf values case E_ExprKind_LeafValue: { E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU128); new_tree->value = expr->value; new_tree->space = expr->space; result.root = new_tree; result.type_key = expr->type_key; result.mode = E_Mode_Value; }break; //- rjf: leaf file paths case E_ExprKind_LeafFilePath: { Temp scratch = scratch_begin(&arena, 1); String8 file_path = expr->string; FileProperties props = os_properties_from_file_path(file_path); if(!str8_match(expr->qualifier, str8_lit("folder"), 0) && !(props.flags & FilePropertyFlag_IsFolder) && file_path.size != 0) { E_Space space = e_space_make(E_SpaceKind_FileSystem); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(file_path))); result.type_key = e_cache->file_type_key; result.mode = E_Mode_Value; } else { String8 folder_path = str8_chop_last_slash(file_path); props = os_properties_from_file_path(folder_path); if(props.flags & FilePropertyFlag_IsFolder || folder_path.size == 0 || str8_match(folder_path, str8_lit("/"), StringMatchFlag_SlashInsensitive)) { E_Space space = e_space_make(E_SpaceKind_FileSystem); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(folder_path))); result.type_key = e_cache->folder_type_key; result.mode = E_Mode_Value; } } scratch_end(scratch); }break; //- rjf: types case E_ExprKind_TypeIdent: { result.root = e_irtree_const_u(arena, 0); result.root->space = expr->space; result.type_key = expr->type_key; result.mode = E_Mode_Null; }break; case E_ExprKind_Unsigned: { E_IRTreeAndType direct_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = direct_irtree; E_TypeKey direct_type_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); if(e_type_kind_is_signed(direct_type_kind)) { E_TypeKind new_kind = direct_type_kind; switch(direct_type_kind) { default:{}break; case E_TypeKind_Char8: {new_kind = E_TypeKind_UChar8;}break; case E_TypeKind_Char16:{new_kind = E_TypeKind_UChar16;}break; case E_TypeKind_Char32:{new_kind = E_TypeKind_UChar32;}break; case E_TypeKind_S8:{new_kind = E_TypeKind_U8;}break; case E_TypeKind_S16:{new_kind = E_TypeKind_U16;}break; case E_TypeKind_S32:{new_kind = E_TypeKind_U32;}break; case E_TypeKind_S64:{new_kind = E_TypeKind_U64;}break; case E_TypeKind_S128:{new_kind = E_TypeKind_U128;}break; case E_TypeKind_S256:{new_kind = E_TypeKind_U256;}break; case E_TypeKind_S512:{new_kind = E_TypeKind_U512;}break; } result.type_key = e_type_key_basic(new_kind); } else { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->first->range, "Cannot apply an `unsigned` modifier to this type."); } }break; case E_ExprKind_Ptr: { E_IRTreeAndType ptee_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = ptee_irtree; result.type_key = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, result.type_key, 1, 0); }break; case E_ExprKind_Array: { E_IRTreeAndType element_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first); result = element_irtree; result.type_key = e_type_key_cons_array(result.type_key, expr->value.u64, 0); }break; case E_ExprKind_Func: { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Function type expressions are currently not supported."); }break; //- rjf: definitions case E_ExprKind_Define: { E_Expr *lhs = expr->first; E_Expr *rhs = lhs->next; result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, rhs); if(lhs->kind != E_ExprKind_LeafIdentifier) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->range, "Left side of assignment must be an unused identifier."); } }break; } //- rjf: check chained expressions for simple wrappers if(!disallow_chained_fastpaths) { local_persist struct { String8 shorthand; String8 full_name; } shorthand_lens_pair_table[] = { {str8_lit_comp("x"), str8_lit_comp("hex")}, {str8_lit_comp("b"), str8_lit_comp("bin")}, {str8_lit_comp("o"), str8_lit_comp("oct")}, {str8_lit_comp("d"), str8_lit_comp("dec")}, }; E_Expr *first_chained = expr->next; for(E_Expr *chained_expr = first_chained; chained_expr != &e_expr_nil; chained_expr = chained_expr->next) { B32 matches_shorthand = 0; if(chained_expr->kind == E_ExprKind_LeafIdentifier) { for EachElement(shorthand_idx, shorthand_lens_pair_table) { if(str8_match(chained_expr->string, shorthand_lens_pair_table[shorthand_idx].shorthand, 0)) { String8 full_name = shorthand_lens_pair_table[shorthand_idx].full_name; result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .direct_key = result.type_key, .name = full_name); matches_shorthand = 1; break; } } } if(!matches_shorthand) { E_TypeKind type_kind = e_type_kind_from_key(e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_AllDecorative)); if(e_type_kind_is_pointer_or_ref(type_kind) || type_kind == E_TypeKind_Array) { E_Expr *lens_spec_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, str8_lit("array")); E_TypeKey lens_spec_type_key = lens_spec_expr->type_key; E_Type *lens_spec_type = e_type_from_key(lens_spec_type_key); result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .flags = lens_spec_type->flags, .count = 1, .args = &chained_expr, .direct_key = result.type_key, .name = lens_spec_type->name, .irext = lens_spec_type->irext, .access = lens_spec_type->access, .expand = lens_spec_type->expand); } } } } //- rjf: if the evaluated type has a hook for an extra layer of ir extension, // call into it E_Type *type = e_type_from_key(result.type_key); { E_TypeIRExtFunctionType *irext = type->irext; for(E_Type *t = type; t->kind == E_TypeKind_Lens || t->kind == E_TypeKind_Set; t = e_type_from_key(t->direct_type_key)) { if(t->irext != 0) { irext = t->irext; break; } } if(irext != 0 && result.user_data == 0) { E_IRExt ext = irext(arena, expr, &result); result.user_data = ext.user_data; } } //- rjf: if the evaluated type has a virtual table pointer, then we must // pre-emptively evaluate this ir tree, and determine a more resolved type. if(!disallow_autohooks && result.mode != E_Mode_Null) { E_TypeKey type_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_Modifiers); if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(type_key))) { E_TypeKey ptee_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_All); E_TypeKind ptee_kind = e_type_kind_from_key(ptee_key); if(ptee_kind == E_TypeKind_Struct || ptee_kind == E_TypeKind_Class) { E_Type *ptee_type = e_type_from_key(ptee_key); B32 has_vtable = 0; for(U64 idx = 0; idx < ptee_type->count; idx += 1) { if(ptee_type->members[idx].kind == E_MemberKind_VirtualMethod) { has_vtable = 1; break; } } if(has_vtable) { E_IRNode *class_base_value_tree = e_irtree_resolve_to_value(scratch.arena, result.mode, result.root, result.type_key); E_OpList oplist = e_oplist_from_irtree(scratch.arena, class_base_value_tree); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpret = e_interpret(bytecode); U64 class_base_vaddr = interpret.value.u64; U64 vtable_vaddr = 0; U64 addr_size = e_type_byte_size_from_key(type_key); if(e_space_read(interpret.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size))) { Arch arch = e_base_ctx->primary_module->arch; U32 dbg_info_num = 0; RDI_Parsed *rdi = 0; U64 module_base = 0; for(U64 idx = 0; idx < e_base_ctx->modules_count; idx += 1) { if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vtable_vaddr)) { E_DbgInfo *dbg_info = e_dbg_info_from_module(&e_base_ctx->modules[idx]); arch = e_base_ctx->modules[idx].arch; module_base = e_base_ctx->modules[idx].vaddr_range.min; dbg_info_num = e_base_ctx->modules[idx].dbg_info_num; rdi = dbg_info->rdi; break; } } if(rdi != 0) { U64 vtable_voff = vtable_vaddr - module_base; U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff); RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx); if(global_var->link_flags & RDI_LinkFlag_TypeScoped) { RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx); RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, dbg_info_num); E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0); result.type_key = ptr_to_derived_type_key; } } } } } } } //- rjf: equip previous task's irtree if(parent != 0 && parent->root != &e_irnode_nil) { E_IRTreeAndType *new_chain = push_array(arena, E_IRTreeAndType, 1); MemoryCopyStruct(new_chain, parent); E_IRTreeAndType *first_chain = 0; E_IRTreeAndType *last_chain = 0; if(result.prev) { for(E_IRTreeAndType *p = result.prev; p != 0; p = p->prev) { E_IRTreeAndType *p_copy = push_array(arena, E_IRTreeAndType, 1); MemoryCopyStruct(p_copy, p); SLLQueuePush_N(first_chain, last_chain, p_copy, prev); } SLLQueuePushFront_N(first_chain, last_chain, new_chain, prev); result.prev = first_chain; } else { result.prev = new_chain; } } //- rjf: mark this result as an auto-hook, if we have an override if(t->overridden) { result.auto_hook = 1; } //- rjf: restore stack elements e_cache->first_wildcard_inst = first_wildcard_inst_restore; e_cache->last_wildcard_inst = last_wildcard_inst_restore; //- rjf: find any auto hooks according to this generation's type if(!disallow_autohooks && result.mode != E_Mode_Null) { E_AutoHookMatchList matches = e_auto_hook_matches_from_type_key(result.type_key); for(E_AutoHookMatch *match = matches.first; match != 0; match = match->next) { B32 e_is_poisoned = e_expr_is_poisoned(match->expr); if(!e_is_poisoned) { Task *task = push_array(scratch.arena, Task, 1); SLLQueuePush(first_task, last_task, task); task->expr = match->expr; task->first_wildcard_inst = match->first_wildcard_inst; task->last_wildcard_inst = match->last_wildcard_inst; task->overridden = push_array(scratch.arena, E_IRTreeAndType, 1); task->overridden[0] = result; goto end_autohook_find; } } end_autohook_find:; } } ////////////////////////////// //- rjf: unpoison the tags we used // for(Task *t = first_task; t != 0; t = t->next) { e_expr_unpoison(t->expr); } ////////////////////////////// //- rjf: apply inherited lenses to the resultant type // if(inherited_lenses.count != 0) { E_Type *result_type = e_type_from_key(result.type_key); for(E_TypeKeyNode *n = inherited_lenses.first; n != 0; n = n->next) { E_Type *src_type = e_type_from_key(n->v); E_TypeKey dst_type_key = e_type_key_cons(.kind = src_type->kind, .flags = src_type->flags, .name = src_type->name, .count = src_type->count, .args = src_type->args, .irext = src_type->irext, .access = src_type->access, .expand = src_type->expand, .direct_key = result.type_key); result.type_key = dst_type_key; } } scratch_end(scratch); ProfEnd(); return result; } //- rjf: irtree -> linear ops/bytecode internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out) { U32 op = root->op; { E_Space zero_space = zero_struct; if(!e_space_match(root->space, zero_space) && !e_space_match(root->space, *current_space)) { *current_space = root->space; e_oplist_push_set_space(arena, out, root->space); } } switch(op) { case RDI_EvalOp_Stop: case RDI_EvalOp_Skip: { // TODO: error - invalid ir-tree op }break; case E_IRExtKind_Bytecode: { e_oplist_push_bytecode(arena, out, root->string); }break; case E_IRExtKind_SetSpace: { E_Space space = {0}; MemoryCopy(&space, &root->value, sizeof(space)); e_oplist_push_set_space(arena, out, space); for(E_IRNode *child = root->first; child != &e_irnode_nil; child = child->next) { e_append_oplist_from_irtree(arena, child, current_space, out); } }break; case RDI_EvalOp_Cond: { // rjf: generate oplists for each child E_OpList prt_cond = e_oplist_from_irtree(arena, root->first); E_OpList prt_left = e_oplist_from_irtree(arena, root->first->next); E_OpList prt_right = e_oplist_from_irtree(arena, root->first->next->next); // rjf: put together like so: // 1. , Op_Cond (sizeof(2)) // 2. , Op_Skip (sizeof(3)) // 3. // rjf: modify prt_right in place to create step 2 e_oplist_push_op(arena, &prt_right, RDI_EvalOp_Skip, e_value_u64(prt_left.encoded_size)); // rjf: merge 1 into out e_oplist_concat_in_place(out, &prt_cond); e_oplist_push_op(arena, out, RDI_EvalOp_Cond, e_value_u64(prt_right.encoded_size)); // rjf: merge 2 into out e_oplist_concat_in_place(out, &prt_right); // rjf: merge 3 into out e_oplist_concat_in_place(out, &prt_left); }break; case RDI_EvalOp_ConstString: { e_oplist_push_string_literal(arena, out, root->string); }break; default: { if(op >= RDI_EvalOp_COUNT) { // TODO: error - invalid ir-tree op } else { // rjf: append ops for all children U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; U64 child_count = RDI_POPN_FROM_CTRLBITS(ctrlbits); U64 idx = 0; for(E_IRNode *child = root->first; child != &e_irnode_nil && idx < child_count; child = child->next, idx += 1) { e_append_oplist_from_irtree(arena, child, current_space, out); } // rjf: emit op to compute this node e_oplist_push_op(arena, out, (RDI_EvalOp)root->op, root->value); } }break; } } internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root) { E_OpList ops = {0}; E_Space space = e_interpret_ctx->primary_space; e_append_oplist_from_irtree(arena, root, &space, &ops); return ops; } internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist) { // rjf: allocate buffer U64 size = oplist->encoded_size; U8 *str = push_array_no_zero(arena, U8, size); // rjf: iterate loose op nodes; fill buffer U8 *ptr = str; U8 *opl = str + size; for(E_Op *op = oplist->first; op != 0; op = op->next) { U32 opcode = op->opcode; switch(opcode) { default: { // rjf: compute bytecode advance U16 ctrlbits = rdi_eval_op_ctrlbits_table[opcode]; U64 extra_byte_count = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); U8 *next_ptr = ptr + 1 + extra_byte_count; Assert(next_ptr <= opl); // rjf: fill bytecode ptr[0] = opcode; MemoryCopy(ptr + 1, &op->value.u512.u8[0], extra_byte_count); // rjf: advance ptr = next_ptr; }break; case RDI_EvalOp_ConstString: { // rjf: compute bytecode advance U8 *next_ptr = ptr + 2 + op->value.u64; Assert(next_ptr <= opl); // rjf: fill ptr[0] = opcode; ptr[1] = (U8)op->value.u64; MemoryCopy(ptr+2, op->string.str, op->value.u64); // rjf: advance ptr = next_ptr; }break; case E_IRExtKind_Bytecode: { // rjf: compute bytecode advance U64 size = op->string.size; U8 *next_ptr = ptr + size; Assert(next_ptr <= opl); // rjf: fill bytecode MemoryCopy(ptr, op->string.str, size); // rjf: advance ptr = next_ptr; }break; case E_IRExtKind_SetSpace: { // rjf: compute bytecode advance U64 extra_byte_count = sizeof(E_Space); U8 *next_ptr = ptr + 1 + extra_byte_count; Assert(next_ptr <= opl); // rjf: fill bytecode ptr[0] = opcode; MemoryCopy(ptr + 1, &op->value.u128, extra_byte_count); // rjf: advance ptr = next_ptr; }break; } } // rjf: fill result String8 result = {0}; result.size = size; result.str = str; return result; } //- rjf: leaf-bytecode expression extensions internal E_Expr * e_expr_irext_member_access(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, String8 member_name) { E_Expr *root = e_push_expr(arena, E_ExprKind_MemberAccess, r1u64(0, 0)); E_Expr *lhs_bytecode = e_push_expr(arena, E_ExprKind_LeafBytecode, lhs->range); E_OpList lhs_oplist = e_oplist_from_irtree(arena, lhs_irtree->root); lhs_bytecode->string = e_string_from_expr(arena, lhs, str8_zero()); lhs_bytecode->qualifier = lhs->qualifier; lhs_bytecode->space = lhs->space; lhs_bytecode->mode = lhs_irtree->mode; lhs_bytecode->type_key = lhs_irtree->type_key; lhs_bytecode->bytecode = e_bytecode_from_oplist(arena, &lhs_oplist); E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, r1u64(0, 0)); rhs->string = push_str8_copy(arena, member_name); e_expr_push_child(root, lhs_bytecode); e_expr_push_child(root, rhs); return root; } ================================================ FILE: src/eval/eval_ir.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_IR_H #define EVAL_IR_H //////////////////////////////// //~ rjf: Identifier Resolution Rule Types typedef enum E_IdentifierResolutionPath { E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, E_IdentifierResolutionPath_ParentExprMember, E_IdentifierResolutionPath_ImplicitThisMember, E_IdentifierResolutionPath_Local, E_IdentifierResolutionPath_DebugInfoMatch, E_IdentifierResolutionPath_BuiltInConstants, E_IdentifierResolutionPath_BuiltInTypes, E_IdentifierResolutionPath_Registers, E_IdentifierResolutionPath_RegisterAliases, E_IdentifierResolutionPath_Macros, } E_IdentifierResolutionPath; typedef struct E_IdentifierResolutionRule E_IdentifierResolutionRule; struct E_IdentifierResolutionRule { E_IdentifierResolutionPath *paths; U64 count; }; //////////////////////////////// //~ rjf: IR State typedef struct E_IRCacheNode E_IRCacheNode; struct E_IRCacheNode { E_IRCacheNode *next; E_Expr *expr; E_IRNode *overridden_node; E_IRTreeAndType irtree; }; typedef struct E_IRCacheSlot E_IRCacheSlot; struct E_IRCacheSlot { E_IRCacheNode *first; E_IRCacheNode *last; }; typedef struct E_IRState E_IRState; struct E_IRState { Arena *arena; U64 arena_eval_start_pos; // rjf: ir context E_IRCtx *ctx; // rjf: unpacked ctx RDI_Procedure *thread_ip_procedure; // rjf: overridden irtree E_IRTreeAndType *overridden_irtree; B32 disallow_autohooks; B32 disallow_chained_fastpaths; // rjf: caches E_UsedExprMap *used_expr_map; E_TypeAutoHookCacheMap *type_auto_hook_cache_map; U64 string_id_gen; E_StringIDMap *string_id_map; U64 ir_cache_slots_count; E_IRCacheSlot *ir_cache_slots; }; //////////////////////////////// //~ rjf: Globals E_IdentifierResolutionPath e_default_identifier_resolution_paths[] = { E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, E_IdentifierResolutionPath_ParentExprMember, E_IdentifierResolutionPath_ImplicitThisMember, E_IdentifierResolutionPath_Local, E_IdentifierResolutionPath_BuiltInConstants, E_IdentifierResolutionPath_BuiltInTypes, E_IdentifierResolutionPath_DebugInfoMatch, E_IdentifierResolutionPath_Registers, E_IdentifierResolutionPath_RegisterAliases, E_IdentifierResolutionPath_Macros, }; E_IdentifierResolutionRule e_default_identifier_resolution_rule = { e_default_identifier_resolution_paths, ArrayCount(e_default_identifier_resolution_paths), }; E_IdentifierResolutionPath e_callable_identifier_resolution_paths[] = { E_IdentifierResolutionPath_Macros, E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, E_IdentifierResolutionPath_ParentExprMember, E_IdentifierResolutionPath_ImplicitThisMember, E_IdentifierResolutionPath_Local, E_IdentifierResolutionPath_BuiltInConstants, E_IdentifierResolutionPath_BuiltInTypes, E_IdentifierResolutionPath_DebugInfoMatch, E_IdentifierResolutionPath_Registers, E_IdentifierResolutionPath_RegisterAliases, }; E_IdentifierResolutionRule e_callable_identifier_resolution_rule = { e_callable_identifier_resolution_paths, ArrayCount(e_callable_identifier_resolution_paths), }; //////////////////////////////// //~ rjf: IR-ization Functions //- rjf: op list functions internal void e_oplist_push_op(Arena *arena, E_OpList *list, RDI_EvalOp opcode, E_Value value); internal void e_oplist_push_uconst(Arena *arena, E_OpList *list, U64 x); internal void e_oplist_push_sconst(Arena *arena, E_OpList *list, S64 x); internal void e_oplist_push_bytecode(Arena *arena, E_OpList *list, String8 bytecode); internal void e_oplist_push_set_space(Arena *arena, E_OpList *list, E_Space space); internal void e_oplist_push_string_literal(Arena *arena, E_OpList *list, String8 string); internal void e_oplist_concat_in_place(E_OpList *dst, E_OpList *to_push); //- rjf: ir tree core building helpers internal E_IRNode *e_push_irnode(Arena *arena, RDI_EvalOp op); internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child); //- rjf: ir subtree building helpers internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v); internal E_IRNode *e_irtree_leaf_u128(Arena *arena, U128 u128); internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c); internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, U64 operand_size, E_IRNode *l, E_IRNode *r); internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, U64 operand_size, E_IRNode *l, E_IRNode *r); internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l, E_IRNode *r); internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode); internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string); internal E_IRNode *e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c); internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key); internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in); internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key); internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in); internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key); //- rjf: expression poison checking internal B32 e_expr_is_poisoned(E_Expr *expr); internal void e_expr_poison(E_Expr *expr); internal void e_expr_unpoison(E_Expr *expr); //- rjf: top-level irtree/type extraction E_TYPE_ACCESS_FUNCTION_DEF(default); internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_IdentifierResolutionRule *identifier_resolution_rule, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr); //- rjf: irtree -> linear ops/bytecode internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out); internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root); internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist); //- rjf: leaf-bytecode expression extensions internal E_Expr *e_expr_irext_member_access(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, String8 member_name); #endif // EVAL_IR_H ================================================ FILE: src/eval/eval_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Lexing/Parsing Data Tables global read_only String8 e_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("->"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("=>"), }; global read_only S64 e_max_precedence = 15; //////////////////////////////// //~ rjf: Tokenization Functions internal E_Token e_token_zero(void) { E_Token t = zero_struct; return t; } internal void e_token_chunk_list_push(Arena *arena, E_TokenChunkList *list, U64 chunk_size, E_Token *token) { E_TokenChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, E_TokenChunkNode, 1); SLLQueuePush(list->first, list->last, node); node->cap = chunk_size; node->v = push_array_no_zero(arena, E_Token, node->cap); list->node_count += 1; } MemoryCopyStruct(&node->v[node->count], token); node->count += 1; list->total_count += 1; } internal E_TokenArray e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list) { E_TokenArray array = {0}; array.count = list->total_count; array.v = push_array_no_zero(arena, E_Token, array.count); U64 idx = 0; for(E_TokenChunkNode *node = list->first; node != 0; node = node->next) { MemoryCopy(array.v+idx, node->v, sizeof(E_Token)*node->count); idx += node->count; } return array; } internal E_TokenArray e_token_array_from_text(Arena *arena, String8 text) { Temp scratch = scratch_begin(&arena, 1); //- rjf: lex loop E_TokenChunkList tokens = {0}; U64 active_token_start_idx = 0; E_TokenKind active_token_kind = E_TokenKind_Null; B32 active_token_kind_started_with_tick = 0; B32 escaped = 0; B32 exp = 0; for(U64 idx = 0, advance = 0; idx <= text.size; idx += advance) { U8 byte = (idx+0 < text.size) ? text.str[idx+0] : 0; U8 byte_next = (idx+1 < text.size) ? text.str[idx+1] : 0; U8 byte_next2= (idx+2 < text.size) ? text.str[idx+2] : 0; advance = 1; B32 token_formed = 0; U64 token_end_idx_pad = 0; switch(active_token_kind) { //- rjf: no active token -> seek token starter default: { if(char_is_alpha(byte) || byte == '_' || byte == '`' || byte == '$') { active_token_kind = E_TokenKind_Identifier; active_token_start_idx = idx; active_token_kind_started_with_tick = (byte == '`'); } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(byte_next, 10))) { active_token_kind = E_TokenKind_Numeric; active_token_start_idx = idx; } else if(byte == '"') { active_token_kind = E_TokenKind_StringLiteral; active_token_start_idx = idx; } else if(byte == '\'') { active_token_kind = E_TokenKind_CharLiteral; active_token_start_idx = idx; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { active_token_kind = E_TokenKind_Symbol; active_token_start_idx = idx; } }break; //- rjf: active tokens -> seek enders case E_TokenKind_Identifier: { if(byte == ':' && byte_next == ':' && (char_is_alpha(byte_next2) || byte_next2 == '_' || byte_next2 == '<')) { // NOTE(rjf): encountering C++-style namespaces - skip over scope resolution symbol // & keep going. advance = 2; } else if((byte == '\'' || byte == '`') && active_token_kind_started_with_tick) { // NOTE(rjf): encountering ` -> ' or ` -> ` style identifier escapes active_token_kind_started_with_tick = 0; advance = 1; } else if(byte == '<') { // NOTE(rjf): encountering C++-style templates - try to find ender. if no ender found, // assume this is an operator & just consume the identifier part. S64 nest = 1; for(U64 idx2 = idx+1; idx2 <= text.size; idx2 += 1) { if(idx2 < text.size && text.str[idx2] == '<') { nest += 1; } else if(idx2 < text.size && text.str[idx2] == '>') { nest -= 1; if(nest == 0) { advance = (idx2+1-idx); break; } } else if(idx2 == text.size && nest != 0) { token_formed = 1; advance = 0; break; } } } else if(!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && !active_token_kind_started_with_tick && byte != '@' && byte != '$') { advance = 0; token_formed = 1; } }break; case E_TokenKind_Numeric: { if(exp && (byte == '+' || byte == '-')){} else if(!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '.' && byte != ':') { advance = 0; token_formed = 1; } else { exp = 0; exp = (byte == 'e'); } }break; case E_TokenKind_StringLiteral: { if(escaped == 0 && byte == '\\') { escaped = 1; } else if(escaped) { escaped = 0; } else if(escaped == 0 && byte == '"') { advance = 1; token_formed = 1; token_end_idx_pad = 1; } }break; case E_TokenKind_CharLiteral: { if(escaped == 0 && byte == '\\') { escaped = 1; } else if(escaped) { escaped = 0; } else if(escaped == 0 && byte == '\'') { advance = 1; token_formed = 1; token_end_idx_pad = 1; } }break; case E_TokenKind_Symbol: { if(byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|') { advance = 0; token_formed = 1; } }break; } //- rjf: token formed -> push new formed token(s) if(token_formed) { // rjf: non-symbols *or* symbols of only 1-length can be immediately // pushed as a token if(active_token_kind != E_TokenKind_Symbol || idx==active_token_start_idx+1) { E_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+token_end_idx_pad)}; e_token_chunk_list_push(scratch.arena, &tokens, 256, &token); } // rjf: symbolic strings matching `--` mean the remainder of the string // is reserved for external usage. the rest of the stream should not // be tokenized. else if(idx == active_token_start_idx+2 && text.str[active_token_start_idx] == '-' && text.str[active_token_start_idx+1] == '-') { break; } // rjf: if we got a symbol string of N>1 characters, then we need to // apply the maximum-munch rule, and produce M<=N tokens, where each // formed token is the maximum size possible, given the legal // >1-length symbol strings. else { U64 advance2 = 0; for(U64 idx2 = active_token_start_idx; idx2 < idx; idx2 += advance2) { advance2 = 1; for(U64 multichar_symbol_idx = 0; multichar_symbol_idx < ArrayCount(e_multichar_symbol_strings); multichar_symbol_idx += 1) { String8 multichar_symbol_string = e_multichar_symbol_strings[multichar_symbol_idx]; String8 part_of_token = str8_substr(text, r1u64(idx2, idx2+multichar_symbol_string.size)); if(str8_match(part_of_token, multichar_symbol_string, 0)) { advance2 = multichar_symbol_string.size; break; } } E_Token token = {active_token_kind, r1u64(idx2, idx2+advance2)}; e_token_chunk_list_push(scratch.arena, &tokens, 256, &token); } } // rjf: reset for subsequent tokens. active_token_kind = E_TokenKind_Null; } } //- rjf: chunk list -> array & return E_TokenArray array = e_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return array; } internal E_TokenArray e_token_array_make_first_opl(E_Token *first, E_Token *opl) { E_TokenArray array = {first, (U64)(opl-first)}; return array; } //////////////////////////////// //~ rjf: Expression Tree Building Functions internal E_Expr * e_push_expr(Arena *arena, E_ExprKind kind, Rng1U64 range) { E_Expr *e = push_array(arena, E_Expr, 1); e->first = e->last = e->next = e->prev = e->ref = &e_expr_nil; e->range = range; e->kind = kind; return e; } internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child) { DLLInsert_NPZ(&e_expr_nil, parent->first, parent->last, prev, child, next, prev); } internal void e_expr_push_child(E_Expr *parent, E_Expr *child) { DLLPushBack_NPZ(&e_expr_nil, parent->first, parent->last, child, next, prev); } internal void e_expr_remove_child(E_Expr *parent, E_Expr *child) { DLLRemove_NPZ(&e_expr_nil, parent->first, parent->last, child, next, prev); } internal E_Expr * e_expr_ref(Arena *arena, E_Expr *ref) { E_Expr *expr = e_push_expr(arena, E_ExprKind_Ref, ref->range); expr->ref = ref; return expr; } internal E_Expr * e_expr_copy(Arena *arena, E_Expr *src) { E_Expr *result = &e_expr_nil; Temp scratch = scratch_begin(&arena, 1); if(src != &e_expr_nil) { typedef struct Task Task; struct Task { Task *next; E_Expr *dst_parent; E_Expr *src; B32 is_ref; B32 is_sib; }; Task start_task = {0, &e_expr_nil, src}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) { E_Expr *dst = e_push_expr(arena, t->src->kind, t->src->range); dst->mode = t->src->mode; dst->space = t->src->space; dst->type_key = t->src->type_key; dst->value = t->src->value; dst->string = push_str8_copy(arena, t->src->string); dst->bytecode = push_str8_copy(arena, t->src->bytecode); dst->qualifier = push_str8_copy(arena, t->src->qualifier); if(t->dst_parent == &e_expr_nil) { result = dst; } else if(t->is_ref) { t->dst_parent->ref = dst; } else if(t->is_sib) { t->dst_parent->next = dst; dst->prev = t->dst_parent; } else { e_expr_push_child(t->dst_parent, dst); } if(t->src->next != &e_expr_nil) { Task *task = push_array(scratch.arena, Task, 1); task->dst_parent = dst; task->src = t->src->next; task->is_sib = 1; SLLQueuePush(first_task, last_task, task); } if(t->src->ref != &e_expr_nil) { Task *task = push_array(scratch.arena, Task, 1); task->dst_parent = dst; task->src = t->src->ref; task->is_ref = 1; SLLQueuePush(first_task, last_task, task); } for(E_Expr *src_child = t->src->first; src_child != &e_expr_nil; src_child = src_child->next) { Task *task = push_array(scratch.arena, Task, 1); task->dst_parent = dst; task->src = src_child; SLLQueuePush(first_task, last_task, task); } } } scratch_end(scratch); return result; } internal void e_expr_list_push(Arena *arena, E_ExprList *list, E_Expr *expr) { E_ExprNode *n = push_array(arena, E_ExprNode, 1); n->v = expr; SLLQueuePush(list->first, list->last, n); list->count +=1; } //////////////////////////////// //~ rjf: Expression Tree -> String Conversions internal void e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string, String8List *out) { switch(expr->kind) { default: { E_OpInfo *op_info = &e_expr_kind_op_info_table[expr->kind]; String8 seps[] = { op_info->pre, op_info->sep, op_info->post, }; U64 sep_idx = 0; for(E_Expr *child = expr->first;; child = child->next) { if(sep_idx == ArrayCount(seps)-1 && child != &e_expr_nil) { str8_list_push(arena, out, op_info->chain); } else { str8_list_push(arena, out, seps[sep_idx]); sep_idx += 1; } if(child == &e_expr_nil) { break; } E_OpInfo *child_op_info = &e_expr_kind_op_info_table[child->kind]; B32 need_parens = (child_op_info->precedence > op_info->precedence); if(need_parens) { str8_list_pushf(arena, out, "("); } e_append_strings_from_expr(arena, child, parent_expr_string, out); if(need_parens) { str8_list_pushf(arena, out, ")"); } } }break; case E_ExprKind_LeafBytecode: case E_ExprKind_LeafIdentifier: { if(str8_match(expr->string, str8_lit("$"), 0) && parent_expr_string.size != 0) { str8_list_push(arena, out, parent_expr_string); } else { str8_list_push(arena, out, expr->string); } }break; case E_ExprKind_LeafStringLiteral: { str8_list_pushf(arena, out, "\"%S\"", expr->string); }break; case E_ExprKind_LeafU64: { str8_list_pushf(arena, out, "%I64u", expr->value.u64); }break; case E_ExprKind_LeafOffset: { str8_list_pushf(arena, out, "0x%I64x", expr->value.u64); }break; case E_ExprKind_LeafFilePath: { str8_list_pushf(arena, out, "file:\"%S\"", escaped_from_raw_str8(arena, expr->string)); }break; case E_ExprKind_LeafF64: { str8_list_pushf(arena, out, "%f", expr->value.f64); }break; case E_ExprKind_LeafF32: { str8_list_pushf(arena, out, "%f", expr->value.f32); }break; case E_ExprKind_TypeIdent: { String8 type_string = e_type_string_from_key(arena, expr->type_key); str8_list_push(arena, out, type_string); }break; case E_ExprKind_Ref: { e_append_strings_from_expr(arena, expr->ref, parent_expr_string, out); }break; } } internal String8 e_string_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string) { String8List strings = {0}; e_append_strings_from_expr(arena, expr, parent_expr_string, &strings); String8 result = str8_list_join(arena, &strings, 0); return result; } //////////////////////////////// //~ rjf: Parsing Functions internal E_TypeKey e_leaf_builtin_type_key_from_name(String8 name) { E_TypeKey result = {0}; if(0){} #define BuiltInType_XList \ BasicCase("uint8", U8)\ BasicCase("uint8_t", U8)\ BasicCase("uchar", UChar8)\ BasicCase("uchar8", UChar8)\ BasicCase("uint16", U16)\ BasicCase("uint16_t", U16)\ BasicCase("uchar16", UChar16)\ BasicCase("uint32", U32)\ BasicCase("uint32_t", U32)\ BasicCase("uchar32", UChar32)\ BasicCase("uint64", U64)\ BasicCase("uint64_t", U64)\ BasicCase("uint128", U128)\ BasicCase("uint128_t", U128)\ BasicCase("uint256", U256)\ BasicCase("uint256_t", U256)\ BasicCase("uint512", U512)\ BasicCase("uint512_t", U512)\ BasicCase("int8", S8)\ BasicCase("int8_t", S8)\ BasicCase("char", Char8)\ BasicCase("char8", Char8)\ BasicCase("int16", S16)\ BasicCase("int16_t", S16)\ BasicCase("char16", Char16)\ BasicCase("int32", S32)\ BasicCase("int32_t", S32)\ BasicCase("char32", Char32)\ BasicCase("int64", S64)\ BasicCase("int64_t", S64)\ BasicCase("int128", S128)\ BasicCase("int128_t", S128)\ BasicCase("int256", S256)\ BasicCase("int256_t", S256)\ BasicCase("int512", S512)\ BasicCase("int512_t", S512)\ BasicCase("void", Void)\ BasicCase("bool", Bool)\ BasicCase("float", F32)\ BasicCase("float32", F32)\ BasicCase("double", F64)\ BasicCase("float64", F64) #define BasicCase(str, kind) else if(str8_match(name, str8_lit(str), 0)) {result = e_type_key_basic(E_TypeKind_##kind);} BuiltInType_XList #undef BasicCase return result; } internal E_TypeKey e_leaf_type_key_from_name(String8 name) { E_TypeKey key = e_leaf_builtin_type_key_from_name(name); if(!e_type_key_match(e_type_key_zero(), key)) { DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0); if(match.section_kind == RDI_SectionKind_TypeNodes) { Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0); for EachIndex(idx, e_base_ctx->dbg_infos_count) { E_DbgInfo *dbg_info = &e_base_ctx->dbg_infos[idx]; if(dbg_info->rdi == rdi) { U32 type_idx = match.idx; RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)idx+1); break; } } access_close(access); } } return key; } internal E_TypeKey e_type_key_from_expr(E_Expr *expr) { E_TypeKey result = zero_struct; E_ExprKind kind = expr->kind; switch(kind) { // TODO(rjf): do we support E_ExprKind_Func here? default:{}break; case E_ExprKind_LeafIdentifier: { result = e_leaf_type_key_from_name(expr->string); }break; case E_ExprKind_TypeIdent: { result = expr->type_key; }break; case E_ExprKind_Ptr: { E_TypeKey direct_type_key = e_type_key_from_expr(expr->first); result = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, direct_type_key, 1, 0); }break; case E_ExprKind_Array: { E_Expr *child_expr = expr->first; E_TypeKey direct_type_key = e_type_key_from_expr(child_expr); result = e_type_key_cons_array(direct_type_key, expr->value.u64, 0); }break; } return result; } internal E_Parse e_push_type_parse_from_text_tokens(Arena *arena, String8 text, E_TokenArray tokens) { E_Parse parse = {tokens, 0, &e_expr_nil, &e_expr_nil}; E_Token *token_it = tokens.v; //- rjf: parse unsigned marker B32 unsigned_marker = 0; { E_Token token = e_token_at_it(token_it, &tokens); if(token.kind == E_TokenKind_Identifier) { String8 token_string = str8_substr(text, token.range); if(str8_match(token_string, str8_lit("unsigned"), 0)) { token_it += 1; unsigned_marker = 1; } } } //- rjf: parse base type { E_Token token = e_token_at_it(token_it, &tokens); if(token.kind == E_TokenKind_Identifier) { String8 token_string = str8_substr(text, token.range); if(token_string.size >= 2 && token_string.str[0] == '`' && token_string.str[token_string.size-1] == '`') { token_string = str8_substr(token_string, r1u64(1, token_string.size-1)); } E_TypeKey type_key = e_leaf_type_key_from_name(token_string); if(!e_type_key_match(e_type_key_zero(), type_key)) { token_it += 1; // rjf: apply unsigned marker to base type if(unsigned_marker) switch(e_type_kind_from_key(type_key)) { default:{}break; case E_TypeKind_Char8: {type_key = e_type_key_basic(E_TypeKind_UChar8);}break; case E_TypeKind_Char16:{type_key = e_type_key_basic(E_TypeKind_UChar16);}break; case E_TypeKind_Char32:{type_key = e_type_key_basic(E_TypeKind_UChar32);}break; case E_TypeKind_S8: {type_key = e_type_key_basic(E_TypeKind_U8);}break; case E_TypeKind_S16: {type_key = e_type_key_basic(E_TypeKind_U16);}break; case E_TypeKind_S32: {type_key = e_type_key_basic(E_TypeKind_U32);}break; case E_TypeKind_S64: {type_key = e_type_key_basic(E_TypeKind_U64);}break; case E_TypeKind_S128:{type_key = e_type_key_basic(E_TypeKind_U128);}break; case E_TypeKind_S256:{type_key = e_type_key_basic(E_TypeKind_U256);}break; case E_TypeKind_S512:{type_key = e_type_key_basic(E_TypeKind_U512);}break; } // rjf: construct leaf type parse.expr = e_push_expr(arena, E_ExprKind_TypeIdent, token.range); parse.expr->type_key = type_key; } } } //- rjf: parse extensions if(parse.expr != &e_expr_nil) { for(;;) { E_Token token = e_token_at_it(token_it, &tokens); if(token.kind != E_TokenKind_Symbol) { break; } String8 token_string = str8_substr(text, token.range); if(str8_match(token_string, str8_lit("*"), 0)) { token_it += 1; E_Expr *ptee = parse.expr; parse.expr = e_push_expr(arena, E_ExprKind_Ptr, token.range); e_expr_push_child(parse.expr, ptee); } else { break; } } } //- rjf: fill parse & end parse.last_token = token_it; return parse; } internal E_Parse e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray tokens, S64 max_precedence, U64 max_chain_count) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); E_Token *it = tokens.v; E_Token *it_opl = tokens.v + tokens.count; E_Parse result = {tokens, 0, &e_expr_nil, &e_expr_nil}; ////////////////////////////// //- rjf: parse chain of expressions // for(U64 chain_count = 0; it < it_opl && chain_count < max_chain_count;) { //////////////////////////// //- rjf: exit on symbols callers may be waiting on // { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Symbol && (str8_match(token_string, str8_lit(")"), 0) || str8_match(token_string, str8_lit("]"), 0) || str8_match(token_string, str8_lit(":"), 0) || str8_match(token_string, str8_lit("?"), 0))) { break; } } //////////////////////////// //- rjf: skip commas, semicolons, etc. // for(;it < it_opl;) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Symbol && (str8_match(token_string, str8_lit(","), 0) || str8_match(token_string, str8_lit(";"), 0))) { it += 1; } else { break; } } //////////////////////////// //- rjf: parse atom, gather prefix unary tasks // typedef struct PrefixUnaryTask PrefixUnaryTask; struct PrefixUnaryTask { PrefixUnaryTask *next; E_ExprKind kind; Rng1U64 range; E_Expr *cast_type_expr; }; PrefixUnaryTask *first_prefix_unary = 0; PrefixUnaryTask *last_prefix_unary = 0; E_Expr *atom = &e_expr_nil; B32 atom_is_maybe_cast = 0; for(B32 done = 0; !done && it < it_opl;) { ////////////////////////// //- rjf: prefix unary operators // { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); S64 prefix_unary_precedence = 0; E_ExprKind prefix_unary_kind = 0; E_Expr *prefix_unary_cast_expr = &e_expr_nil; // rjf: try op table for EachNonZeroEnumVal(E_ExprKind, k) { E_OpInfo *op_info = &e_expr_kind_op_info_table[k]; if(op_info->kind == E_OpKind_UnaryPrefix && str8_match(str8_skip_chop_whitespace(op_info->pre), token_string, 0)) { prefix_unary_precedence = op_info->precedence; prefix_unary_kind = k; break; } } // rjf: if we found a symbolic prefix unary operator, but we are // looking for a casted expression, then we need to abort this // path. C-style casts are only legal in very simple and unambiguous // cases, e.g. (x)123, but they cannot be made legal in more // complex cases like (x) * y, because this is fundamentally ambiguous // (the meaning / tree shape / etc. is entirely different depending on // the type / mode of `x`). // // because of things like hover-evaluation we do actually want to // support basic C-style casts. but past a certain point of complexity, // we will simply require usage of the explicit `cast` operator. // if(prefix_unary_precedence != 0 && atom_is_maybe_cast) { break; } // rjf: try 'unsigned' marker if(str8_match(token_string, str8_lit("unsigned"), 0)) { prefix_unary_kind = E_ExprKind_Unsigned; prefix_unary_precedence = 2; } // rjf: try explicit cast if(str8_match(token_string, str8_lit("cast"), 0)) { // rjf: consume cast & open paren E_Token open_paren_maybe = e_token_at_it(it+1, &tokens); String8 open_paren_maybe_string = str8_substr(text, open_paren_maybe.range); if(!str8_match(open_paren_maybe_string, str8_lit("("), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected `(` following `cast`."); goto end_cast_parse; } it += 2; // rjf: parse type expression E_Parse type_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); e_msg_list_concat_in_place(&result.msgs, &type_parse.msgs); it = type_parse.last_token; // rjf: expect ) E_Token close_paren_maybe = e_token_at_it(it, &tokens); String8 close_paren_maybe_string = str8_substr(text, close_paren_maybe.range); if(close_paren_maybe.kind != E_TokenKind_Symbol || !str8_match(close_paren_maybe_string, str8_lit(")"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing `)`."); } // rjf: require type if(type_parse.expr == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected type in `cast(...)`."); } // rjf: fill prefix unary info else { prefix_unary_kind = E_ExprKind_Cast; prefix_unary_precedence = 2; prefix_unary_cast_expr = type_parse.expr; } end_cast_parse:; } // rjf: push prefix unary if we got one if(prefix_unary_precedence != 0) { PrefixUnaryTask *prefix_unary_task = push_array(scratch.arena, PrefixUnaryTask, 1); prefix_unary_task->kind = prefix_unary_kind; prefix_unary_task->range = token.range; prefix_unary_task->cast_type_expr = prefix_unary_cast_expr; SLLQueuePush(first_prefix_unary, last_prefix_unary, prefix_unary_task); it += 1; } } ////////////////////////// //- rjf: try to parse an atom // if(atom == &e_expr_nil || atom_is_maybe_cast) { B32 got_new_atom = 0; E_Expr *maybe_cast = atom_is_maybe_cast ? atom : &e_expr_nil; atom_is_maybe_cast = 0; //////////////////////// //- rjf: consume resolution qualifiers // String8 resolution_qualifier = {0}; { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Identifier) { E_Token next_token = e_token_at_it(it+1, &tokens); String8 next_token_string = str8_substr(text, next_token.range); if(next_token.range.min == token.range.max && next_token.kind == E_TokenKind_Symbol && str8_match(next_token_string, str8_lit(":"), 0)) { it += 2; resolution_qualifier = token_string; } } } //////////////////////// //- rjf: descent to nested expression (...) // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("("), 0)) { // rjf: skip ( it += 1; // rjf: parse () contents E_Parse nested_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs); atom = nested_parse.expr; it = nested_parse.last_token; atom_is_maybe_cast = 1; got_new_atom = 1; // rjf: expect ) E_Token close_paren_maybe = e_token_at_it(it, &tokens); String8 close_paren_maybe_string = str8_substr(text, close_paren_maybe.range); if(close_paren_maybe.kind != E_TokenKind_Symbol || !str8_match(close_paren_maybe_string, str8_lit(")"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing `)`."); } // rjf: consume ) else { it += 1; } } } //////////////////////// //- rjf: descent to assembly-style dereference sub-expression [...] // if(atom == &e_expr_nil && !got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("["), 0)) { // rjf: skip [ it += 1; // rjf: parse [] contents E_Parse nested_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs); atom = nested_parse.expr; it = nested_parse.last_token; got_new_atom = 1; // rjf: build cast-to-U64*, and dereference operators if(nested_parse.expr == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected expression following `[`."); } else { E_Expr *type = e_push_expr(arena, E_ExprKind_TypeIdent, token.range); type->type_key = e_type_key_cons_ptr(e_base_ctx->primary_module->arch, e_type_key_basic(E_TypeKind_U64), 1, 0); E_Expr *casted = atom; E_Expr *cast = e_push_expr(arena, E_ExprKind_Cast, token.range); e_expr_push_child(cast, type); e_expr_push_child(cast, casted); atom = e_push_expr(arena, E_ExprKind_Deref, token.range); e_expr_push_child(atom, cast); } // rjf: expect ] E_Token close_paren_maybe = e_token_at_it(it, &tokens); String8 close_paren_maybe_string = str8_substr(text, close_paren_maybe.range); if(close_paren_maybe.kind != E_TokenKind_Symbol || !str8_match(close_paren_maybe_string, str8_lit("]"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing `]`."); } // rjf: consume ) else { it += 1; } } } //////////////////////// //- rjf: leaf identifier // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); // rjf: skip no-op prefix keywords if(token.kind == E_TokenKind_Identifier && (str8_match(token_string, str8_lit("struct"), 0) || str8_match(token_string, str8_lit("union"), 0) || str8_match(token_string, str8_lit("enum"), 0) || str8_match(token_string, str8_lit("class"), 0) || str8_match(token_string, str8_lit("typename"), 0))) { it += 1; token = e_token_at_it(it, &tokens); token_string = str8_substr(text, token.range); } // rjf: build identifier atom if(token.kind == E_TokenKind_Identifier) { String8 identifier_string = token_string; if(identifier_string.size >= 2 && identifier_string.str[0] == '`' && identifier_string.str[identifier_string.size-1] == '`') { identifier_string = str8_skip(str8_chop(identifier_string, 1), 1); } atom = e_push_expr(arena, E_ExprKind_LeafIdentifier, token.range); atom->string = identifier_string; it += 1; got_new_atom = 1; } } //////////////////////// //- rjf: leaf numeric // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_Numeric) { U64 dot_pos = str8_find_needle(token_string, 0, str8_lit("."), 0); it += 1; // rjf: no . => integral if(dot_pos == token_string.size) { U64 val = 0; try_u64_from_str8_c_rules(token_string, &val); atom = e_push_expr(arena, E_ExprKind_LeafU64, token.range); atom->value.u64 = val; } // rjf: presence of . => double or float if(dot_pos < token_string.size) { F64 val = f64_from_str8(token_string); U64 f_pos = str8_find_needle(token_string, 0, str8_lit("f"), StringMatchFlag_CaseInsensitive); // rjf: presence of f after . => f32 if(f_pos < token_string.size) { atom = e_push_expr(arena, E_ExprKind_LeafF32, token.range); atom->value.f32 = val; } // rjf: no f => f64 else { atom = e_push_expr(arena, E_ExprKind_LeafF64, token.range); atom->value.f64 = val; } } got_new_atom = 1; } } //////////////////////// //- rjf: leaf char literal // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_CharLiteral) { it += 1; if(token_string.size > 1 && token_string.str[0] == '\'' && token_string.str[1] != '\'') { String8 char_literal_escaped = str8_skip(str8_chop(token_string, 1), 1); String8 char_literal_raw = raw_from_escaped_str8(scratch.arena, char_literal_escaped); U8 char_val = char_literal_raw.size > 0 ? char_literal_raw.str[0] : 0; atom = e_push_expr(arena, E_ExprKind_LeafU64, token.range); atom->value.u64 = (U64)char_val; got_new_atom = 1; } else { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Malformed character literal."); } } } //////////////////////// //- rjf: filesystem-qualified leaf string literal // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_StringLiteral && (str8_match(resolution_qualifier, str8_lit("file"), 0) || str8_match(resolution_qualifier, str8_lit("folder"), 0))) { String8 string_value_escaped = str8_chop(str8_skip(token_string, 1), 1); String8 string_value_raw = raw_from_escaped_str8(arena, string_value_escaped); atom = e_push_expr(arena, E_ExprKind_LeafFilePath, token.range); atom->string = string_value_raw; it += 1; got_new_atom = 1; } } //////////////////////// //- rjf: leaf string literal // if(!got_new_atom) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); if(token.kind == E_TokenKind_StringLiteral) { String8 string_value_escaped = str8_chop(str8_skip(token_string, 1), 1); String8 string_value_raw = raw_from_escaped_str8(arena, string_value_escaped); atom = e_push_expr(arena, E_ExprKind_LeafStringLiteral, token.range); atom->string = string_value_raw; it += 1; got_new_atom = 1; } } //////////////////////// //- rjf: upgrade atom w/ qualifier // if(atom != &e_expr_nil && resolution_qualifier.size != 0) { atom->qualifier = resolution_qualifier; } //////////////////////// //- rjf: got new atom, but we had a potential cast atom? -> gather cast operator // if(got_new_atom && maybe_cast != &e_expr_nil) { PrefixUnaryTask *prefix_unary_task = push_array(scratch.arena, PrefixUnaryTask, 1); prefix_unary_task->kind = E_ExprKind_Cast; prefix_unary_task->range = maybe_cast->range; prefix_unary_task->cast_type_expr = maybe_cast; SLLQueuePush(first_prefix_unary, last_prefix_unary, prefix_unary_task); } } //////////////////////// //- rjf: if our atom is not potentially a cast, *or* if we simply did not get an atom, // then we need to stop parsing at this stage. // done = (!atom_is_maybe_cast || atom == &e_expr_nil); } //////////////////////////// //- rjf: upgrade atom w/ postfix unaries // if(atom != &e_expr_nil) for(;it < it_opl;) { E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); B32 is_postfix_unary = 0; // rjf: dot/arrow operator if(max_precedence >= 1 && token.kind == E_TokenKind_Symbol && (str8_match(token_string, str8_lit("."), 0) || str8_match(token_string, str8_lit("->"), 0))) { is_postfix_unary = 1; // rjf: advance past operator it += 1; // rjf: look for member name E_Token member_name_maybe = e_token_at_it(it, &tokens); String8 member_name_maybe_string = str8_substr(text, member_name_maybe.range); B32 member_name_is_good = (member_name_maybe.kind == E_TokenKind_Identifier); // rjf: build dot-operator tree E_Expr *lhs = atom; E_Expr *rhs = &e_expr_nil; if(member_name_is_good) { rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, member_name_maybe.range); rhs->string = member_name_maybe_string; } atom = e_push_expr(arena, E_ExprKind_MemberAccess, token.range); e_expr_push_child(atom, lhs); if(member_name_is_good) { e_expr_push_child(atom, rhs); } // rjf: no identifier after `.`? -> error if(member_name_is_good) { it += 1; } else { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing member name after `%S`.", token_string); } } // rjf: array index if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("["), 0)) { is_postfix_unary = 1; // rjf: advance past [ it += 1; // rjf: parse indexing expression E_Parse idx_expr_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); e_msg_list_concat_in_place(&result.msgs, &idx_expr_parse.msgs); it = idx_expr_parse.last_token; // rjf: valid indexing expression => produce index expr if(idx_expr_parse.expr != &e_expr_nil) { E_Expr *array_expr = atom; E_Expr *index_expr = idx_expr_parse.expr; atom = e_push_expr(arena, E_ExprKind_ArrayIndex, token.range); e_expr_push_child(atom, array_expr); e_expr_push_child(atom, index_expr); } // rjf: expect ] { E_Token close_brace_maybe = e_token_at_it(it, &tokens); String8 close_brace_maybe_string = str8_substr(text, close_brace_maybe.range); if(close_brace_maybe.kind != E_TokenKind_Symbol || !str8_match(close_brace_maybe_string, str8_lit("]"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Unclosed `[`."); } else { it += 1; } } } // rjf: calls if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("("), 0)) { is_postfix_unary = 1; // rjf: skip ( it += 1; // rjf: parse all argument expressions E_Expr *callee_expr = atom; E_Expr *call_expr = e_push_expr(arena, E_ExprKind_Call, token.range); call_expr->string = callee_expr->string; e_expr_push_child(call_expr, callee_expr); E_Parse args_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, max_U64); e_msg_list_concat_in_place(&result.msgs, &args_parse.msgs); it = args_parse.last_token; if(args_parse.expr != &e_expr_nil) { call_expr->last->next = args_parse.expr; args_parse.expr->prev = call_expr->last; for(E_Expr *arg = args_parse.expr; arg != &e_expr_nil; arg = arg->next) { call_expr->last = arg; } } atom = call_expr; // rjf: expect ) { E_Token close_paren_maybe = e_token_at_it(it, &tokens); String8 close_paren_maybe_string = str8_substr(text, close_paren_maybe.range); if(close_paren_maybe.kind != E_TokenKind_Symbol || !str8_match(close_paren_maybe_string, str8_lit(")"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Unclosed `(`."); call_expr->range.max = text.size; } else { call_expr->range = union_1u64(call_expr->range, close_paren_maybe.range); it += 1; } } } // rjf: "as" style casts if(token.kind == E_TokenKind_Identifier && str8_match(token_string, str8_lit("as"), 0)) { it += 1; // rjf: parse type expression E_Parse type_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); e_msg_list_concat_in_place(&result.msgs, &type_parse.msgs); it = type_parse.last_token; // rjf: require type if(type_parse.expr == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected type following `as`."); } // rjf: build cast expr else { E_Expr *rhs = atom; atom = e_push_expr(arena, E_ExprKind_Cast, token.range); e_expr_push_child(atom, type_parse.expr); e_expr_push_child(atom, rhs); } } // rjf: quit if this doesn't look like any patterns of postfix unary we know if(!is_postfix_unary) { break; } } //////////////////////////// //- rjf: no atom, just single `unsigned` prefix unary? -> unsigned int type expr // if(atom == &e_expr_nil && first_prefix_unary != 0 && first_prefix_unary->kind == E_ExprKind_Unsigned) { atom = e_push_expr(arena, E_ExprKind_LeafIdentifier, first_prefix_unary->cast_type_expr->range); atom->string = str8_lit("int"); } //////////////////////////// //- rjf: upgrade `atom` w/ previously parsed prefix unaries // if(atom != &e_expr_nil) { for(PrefixUnaryTask *prefix_unary = first_prefix_unary; prefix_unary != 0; prefix_unary = prefix_unary->next) { if(prefix_unary->kind == E_ExprKind_Cast) { E_Expr *rhs = atom; atom = e_push_expr(arena, prefix_unary->kind, prefix_unary->range); e_expr_push_child(atom, prefix_unary->cast_type_expr); e_expr_push_child(atom, rhs); } else { E_Expr *rhs = atom; atom = e_push_expr(arena, prefix_unary->kind, prefix_unary->range); e_expr_push_child(atom, rhs); } } } else if(first_prefix_unary != 0) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, last_prefix_unary->range, "Missing expression."); } //////////////////////////// //- rjf: parse complex operators to further extend `atom` // if(atom != &e_expr_nil) for(;it < it_opl;) { E_Token *start_it = it; E_Token token = e_token_at_it(it, &tokens); String8 token_string = str8_substr(text, token.range); //- rjf: parse binaries { // rjf: first try to find a matching binary operator S64 binary_precedence = 0; E_ExprKind binary_kind = 0; for EachNonZeroEnumVal(E_ExprKind, k) { E_OpInfo *op_info = &e_expr_kind_op_info_table[k]; if(op_info->kind == E_OpKind_Binary && str8_match(str8_skip_chop_whitespace(op_info->sep), token_string, 0)) { binary_precedence = op_info->precedence; binary_kind = k; break; } } // rjf: if we got a valid binary precedence, and it's not to be handled by // a caller, then we need to parse the right-hand-side with a tighter // precedence if(binary_precedence != 0 && binary_precedence <= max_precedence) { E_Parse rhs_expr_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it+1, it_opl), binary_precedence-1, 1); e_msg_list_concat_in_place(&result.msgs, &rhs_expr_parse.msgs); E_Expr *rhs = rhs_expr_parse.expr; it = rhs_expr_parse.last_token; if(rhs == &e_expr_nil && binary_kind == E_ExprKind_Mul) { // NOTE(rjf): C-style pointer syntax is shared with multiplication. // carving out a special case here to allow "unfinished *s" to be // treated as pointers instead. E_Expr *ptee = atom; atom = e_push_expr(arena, E_ExprKind_Ptr, token.range); e_expr_push_child(atom, ptee); } else if(rhs == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Missing right-hand-side of `%S`.", token_string); } else { E_Expr *lhs = atom; atom = e_push_expr(arena, binary_kind, token.range); e_expr_push_child(atom, lhs); e_expr_push_child(atom, rhs); } } } //- rjf: parse ternaries { if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("?"), 0) && 13 <= max_precedence) { it += 1; // rjf: parse middle expression E_Parse middle_expr_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); it = middle_expr_parse.last_token; E_Expr *middle_expr = middle_expr_parse.expr; e_msg_list_concat_in_place(&result.msgs, &middle_expr_parse.msgs); if(middle_expr_parse.expr == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected expression after `?`."); } // rjf: expect : B32 got_colon = 0; E_Token colon_token = zero_struct; String8 colon_token_string = {0}; { E_Token colon_token_maybe = e_token_at_it(it, &tokens); String8 colon_token_maybe_string = str8_substr(text, colon_token_maybe.range); if(colon_token_maybe.kind != E_TokenKind_Symbol || !str8_match(colon_token_maybe_string, str8_lit(":"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Expected `:` after `?`."); } else { got_colon = 1; colon_token = colon_token_maybe; colon_token_string = colon_token_maybe_string; it += 1; } } // rjf: parse rhs E_Parse rhs_expr_parse = e_push_parse_from_string_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), e_max_precedence, 1); if(got_colon) { it = rhs_expr_parse.last_token; e_msg_list_concat_in_place(&result.msgs, &rhs_expr_parse.msgs); if(rhs_expr_parse.expr == &e_expr_nil) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, colon_token.range, "Expected expression after `:`."); } } // rjf: build ternary if(atom != &e_expr_nil && middle_expr_parse.expr != &e_expr_nil && rhs_expr_parse.expr != &e_expr_nil) { E_Expr *lhs = atom; E_Expr *mhs = middle_expr_parse.expr; E_Expr *rhs = rhs_expr_parse.expr; atom = e_push_expr(arena, E_ExprKind_Ternary, token.range); e_expr_push_child(atom, lhs); e_expr_push_child(atom, mhs); e_expr_push_child(atom, rhs); } } } // rjf: if we parsed nothing successfully, we're done if(it == start_it) { break; } } //- rjf: store parsed atom to expression chain - if we didn't get an expression, break if(atom != &e_expr_nil) { DLLPushBack_NPZ(&e_expr_nil, result.expr, result.last_expr, atom, next, prev); chain_count += 1; } else { break; } } //- rjf: fill result & return result.last_token = it; scratch_end(scratch); ProfEnd(); return result; } internal E_Parse e_push_parse_from_string(Arena *arena, String8 text) { Temp scratch = scratch_begin(&arena, 1); E_TokenArray tokens = e_token_array_from_text(scratch.arena, text); E_Parse parse = e_push_parse_from_string_tokens__prec(arena, text, tokens, e_max_precedence, max_U64); scratch_end(scratch); return parse; } ================================================ FILE: src/eval/eval_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_PARSE_H #define EVAL_PARSE_H //////////////////////////////// //~ rjf: Tokenization Functions #define e_token_at_it(it, arr) (((arr)->v <= (it) && (it) < (arr)->v+(arr)->count) ? (*(it)) : e_token_zero()) internal E_Token e_token_zero(void); internal void e_token_chunk_list_push(Arena *arena, E_TokenChunkList *list, U64 chunk_size, E_Token *token); internal E_TokenArray e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list); internal E_TokenArray e_token_array_from_text(Arena *arena, String8 text); internal E_TokenArray e_token_array_make_first_opl(E_Token *first, E_Token *opl); //////////////////////////////// //~ rjf: Expression Tree Building Functions internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, Rng1U64 range); internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child); internal void e_expr_push_child(E_Expr *parent, E_Expr *child); internal void e_expr_remove_child(E_Expr *parent, E_Expr *child); internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref); internal E_Expr *e_expr_copy(Arena *arena, E_Expr *src); internal void e_expr_list_push(Arena *arena, E_ExprList *list, E_Expr *expr); //////////////////////////////// //~ rjf: Expression Tree -> String Conversions internal void e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string, String8List *out); internal String8 e_string_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string); //////////////////////////////// //~ rjf: Parsing Functions internal E_TypeKey e_leaf_builtin_type_key_from_name(String8 name); internal E_TypeKey e_leaf_type_key_from_name(String8 name); internal E_TypeKey e_type_key_from_expr(E_Expr *expr); internal E_Parse e_push_type_parse_from_text_tokens(Arena *arena, String8 text, E_TokenArray tokens); internal E_Parse e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray tokens, S64 max_precedence, U64 max_chain_count); internal E_Parse e_push_parse_from_string(Arena *arena, String8 text); #endif // EVAL_PARSE_H ================================================ FILE: src/eval/eval_types.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Type Kind Enum Functions internal E_TypeKind e_type_kind_from_base(TypeKind kind) { E_TypeKind result = E_TypeKind_Null; switch(kind) { default:{}break; case TypeKind_Void: {result = E_TypeKind_Void;}break; case TypeKind_U8: {result = E_TypeKind_U8;}break; case TypeKind_U16: {result = E_TypeKind_U16;}break; case TypeKind_U32: {result = E_TypeKind_U32;}break; case TypeKind_U64: {result = E_TypeKind_U64;}break; case TypeKind_S8: {result = E_TypeKind_S8;}break; case TypeKind_S16: {result = E_TypeKind_S16;}break; case TypeKind_S32: {result = E_TypeKind_S32;}break; case TypeKind_S64: {result = E_TypeKind_S64;}break; case TypeKind_B8: {result = E_TypeKind_S8;}break; case TypeKind_B16: {result = E_TypeKind_S16;}break; case TypeKind_B32: {result = E_TypeKind_S32;}break; case TypeKind_B64: {result = E_TypeKind_S64;}break; case TypeKind_F32: {result = E_TypeKind_F32;}break; case TypeKind_F64: {result = E_TypeKind_F64;}break; case TypeKind_Ptr: {result = E_TypeKind_Ptr;}break; case TypeKind_Array: {result = E_TypeKind_Array;}break; case TypeKind_Struct:{result = E_TypeKind_Struct;}break; case TypeKind_Union: {result = E_TypeKind_Union;}break; case TypeKind_Enum: {result = E_TypeKind_Enum;}break; } return result; } internal E_TypeKind e_type_kind_from_rdi(RDI_TypeKind kind) { E_TypeKind result = E_TypeKind_Null; switch(kind) { default:{}break; case RDI_TypeKind_Void: {result = E_TypeKind_Void;}break; case RDI_TypeKind_Handle: {result = E_TypeKind_Handle;}break; case RDI_TypeKind_HResult: {result = E_TypeKind_HResult;}break; case RDI_TypeKind_Char8: {result = E_TypeKind_Char8;}break; case RDI_TypeKind_Char16: {result = E_TypeKind_Char16;}break; case RDI_TypeKind_Char32: {result = E_TypeKind_Char32;}break; case RDI_TypeKind_UChar8: {result = E_TypeKind_UChar8;}break; case RDI_TypeKind_UChar16: {result = E_TypeKind_UChar16;}break; case RDI_TypeKind_UChar32: {result = E_TypeKind_UChar32;}break; case RDI_TypeKind_U8: {result = E_TypeKind_U8;}break; case RDI_TypeKind_U16: {result = E_TypeKind_U16;}break; case RDI_TypeKind_U32: {result = E_TypeKind_U32;}break; case RDI_TypeKind_U64: {result = E_TypeKind_U64;}break; case RDI_TypeKind_U128: {result = E_TypeKind_U128;}break; case RDI_TypeKind_U256: {result = E_TypeKind_U256;}break; case RDI_TypeKind_U512: {result = E_TypeKind_U512;}break; case RDI_TypeKind_S8: {result = E_TypeKind_S8;}break; case RDI_TypeKind_S16: {result = E_TypeKind_S16;}break; case RDI_TypeKind_S32: {result = E_TypeKind_S32;}break; case RDI_TypeKind_S64: {result = E_TypeKind_S64;}break; case RDI_TypeKind_S128: {result = E_TypeKind_S128;}break; case RDI_TypeKind_S256: {result = E_TypeKind_S256;}break; case RDI_TypeKind_S512: {result = E_TypeKind_S512;}break; case RDI_TypeKind_Bool: {result = E_TypeKind_Bool;}break; case RDI_TypeKind_F16: {result = E_TypeKind_F16;}break; case RDI_TypeKind_F32: {result = E_TypeKind_F32;}break; case RDI_TypeKind_F32PP: {result = E_TypeKind_F32PP;}break; case RDI_TypeKind_F48: {result = E_TypeKind_F48;}break; case RDI_TypeKind_F64: {result = E_TypeKind_F64;}break; case RDI_TypeKind_F80: {result = E_TypeKind_F80;}break; case RDI_TypeKind_F128: {result = E_TypeKind_F128;}break; case RDI_TypeKind_ComplexF32: {result = E_TypeKind_ComplexF32;}break; case RDI_TypeKind_ComplexF64: {result = E_TypeKind_ComplexF64;}break; case RDI_TypeKind_ComplexF80: {result = E_TypeKind_ComplexF80;}break; case RDI_TypeKind_ComplexF128: {result = E_TypeKind_ComplexF128;}break; case RDI_TypeKind_Modifier: {result = E_TypeKind_Modifier;}break; case RDI_TypeKind_Ptr: {result = E_TypeKind_Ptr;}break; case RDI_TypeKind_LRef: {result = E_TypeKind_LRef;}break; case RDI_TypeKind_RRef: {result = E_TypeKind_RRef;}break; case RDI_TypeKind_Array: {result = E_TypeKind_Array;}break; case RDI_TypeKind_Function: {result = E_TypeKind_Function;}break; case RDI_TypeKind_Method: {result = E_TypeKind_Method;}break; case RDI_TypeKind_MemberPtr: {result = E_TypeKind_MemberPtr;}break; case RDI_TypeKind_Struct: {result = E_TypeKind_Struct;}break; case RDI_TypeKind_Class: {result = E_TypeKind_Class;}break; case RDI_TypeKind_Union: {result = E_TypeKind_Union;}break; case RDI_TypeKind_Enum: {result = E_TypeKind_Enum;}break; case RDI_TypeKind_Alias: {result = E_TypeKind_Alias;}break; case RDI_TypeKind_IncompleteStruct: {result = E_TypeKind_IncompleteStruct;}break; case RDI_TypeKind_IncompleteUnion: {result = E_TypeKind_IncompleteUnion;}break; case RDI_TypeKind_IncompleteClass: {result = E_TypeKind_IncompleteClass;}break; case RDI_TypeKind_IncompleteEnum: {result = E_TypeKind_IncompleteEnum;}break; case RDI_TypeKind_Bitfield: {result = E_TypeKind_Bitfield;}break; case RDI_TypeKind_Variadic: {result = E_TypeKind_Variadic;}break; } return result; } internal E_MemberKind e_member_kind_from_rdi(RDI_MemberKind kind) { E_MemberKind result = E_MemberKind_Null; switch(kind) { default:{}break; case RDI_MemberKind_DataField: {result = E_MemberKind_DataField;}break; case RDI_MemberKind_StaticData: {result = E_MemberKind_StaticData;}break; case RDI_MemberKind_Method: {result = E_MemberKind_Method;}break; case RDI_MemberKind_StaticMethod: {result = E_MemberKind_StaticMethod;}break; case RDI_MemberKind_VirtualMethod: {result = E_MemberKind_VirtualMethod;}break; case RDI_MemberKind_VTablePtr: {result = E_MemberKind_VTablePtr;}break; case RDI_MemberKind_Base: {result = E_MemberKind_Base;}break; case RDI_MemberKind_VirtualBase: {result = E_MemberKind_VirtualBase;}break; case RDI_MemberKind_NestedType: {result = E_MemberKind_NestedType;}break; } return result; } internal RDI_EvalTypeGroup e_type_group_from_kind(E_TypeKind kind) { RDI_EvalTypeGroup result = 0; switch(kind) { default:{}break; case E_TypeKind_Null: case E_TypeKind_Void: case E_TypeKind_F16: case E_TypeKind_F32PP: case E_TypeKind_F48: case E_TypeKind_F80: case E_TypeKind_F128: case E_TypeKind_ComplexF32: case E_TypeKind_ComplexF64: case E_TypeKind_ComplexF80: case E_TypeKind_ComplexF128: case E_TypeKind_Modifier: case E_TypeKind_Array: case E_TypeKind_Struct: case E_TypeKind_Class: case E_TypeKind_Union: case E_TypeKind_Enum: case E_TypeKind_Alias: case E_TypeKind_IncompleteStruct: case E_TypeKind_IncompleteClass: case E_TypeKind_IncompleteUnion: case E_TypeKind_IncompleteEnum: case E_TypeKind_Bitfield: case E_TypeKind_Variadic: {result = RDI_EvalTypeGroup_Other;}break; case E_TypeKind_Handle: case E_TypeKind_UChar8: case E_TypeKind_UChar16: case E_TypeKind_UChar32: case E_TypeKind_U8: case E_TypeKind_U16: case E_TypeKind_U32: case E_TypeKind_U64: case E_TypeKind_U128: case E_TypeKind_U256: case E_TypeKind_U512: case E_TypeKind_Ptr: case E_TypeKind_LRef: case E_TypeKind_RRef: case E_TypeKind_Function: case E_TypeKind_Method: case E_TypeKind_MemberPtr: {result = RDI_EvalTypeGroup_U;}break; case E_TypeKind_Char8: case E_TypeKind_Char16: case E_TypeKind_Char32: case E_TypeKind_S8: case E_TypeKind_S16: case E_TypeKind_S32: case E_TypeKind_S64: case E_TypeKind_S128: case E_TypeKind_S256: case E_TypeKind_S512: case E_TypeKind_Bool: {result = RDI_EvalTypeGroup_S;}break; case E_TypeKind_F32:{result = RDI_EvalTypeGroup_F32;}break; case E_TypeKind_F64:{result = RDI_EvalTypeGroup_F64;}break; } return result; } internal B32 e_type_kind_is_integer(E_TypeKind kind) { B32 result = (E_TypeKind_FirstInteger <= kind && kind <= E_TypeKind_LastInteger); return result; } internal B32 e_type_kind_is_signed(E_TypeKind kind) { B32 result = ((E_TypeKind_FirstSigned1 <= kind && kind <= E_TypeKind_LastSigned1) || (E_TypeKind_FirstSigned2 <= kind && kind <= E_TypeKind_LastSigned2)); return result; } internal B32 e_type_kind_is_basic_or_enum(E_TypeKind kind) { B32 result = ((E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) || kind == E_TypeKind_Enum); return result; } internal B32 e_type_kind_is_pointer_or_ref(E_TypeKind kind) { B32 result = (kind == E_TypeKind_Ptr || kind == E_TypeKind_LRef || kind == E_TypeKind_RRef); return result; } //////////////////////////////// //~ rjf: Member Functions internal void e_member_list_push(Arena *arena, E_MemberList *list, E_Member *member) { E_MemberNode *n = push_array(arena, E_MemberNode, 1); MemoryCopyStruct(&n->v, member); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal E_MemberArray e_member_array_from_list(Arena *arena, E_MemberList *list) { E_MemberArray array = {0}; array.count = list->count; array.v = push_array(arena, E_Member, array.count); { U64 idx = 0; for(E_MemberNode *n = list->first; n != 0; n = n->next, idx += 1) { MemoryCopyStruct(&array.v[idx], &n->v); } } return array; } //////////////////////////////// //~ rjf: Enum Value Functions internal void e_enum_val_list_push(Arena *arena, E_EnumValList *list, E_EnumVal *enum_val) { E_EnumValNode *n = push_array(arena, E_EnumValNode, 1); MemoryCopyStruct(&n->v, enum_val); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal E_EnumValArray e_enum_val_array_from_list(Arena *arena, E_EnumValList *list) { E_EnumValArray array = {0}; array.count = list->count; array.v = push_array(arena, E_EnumVal, array.count); { U64 idx = 0; for(E_EnumValNode *n = list->first; n != 0; n = n->next, idx += 1) { MemoryCopyStruct(&array.v[idx], &n->v); } } return array; } //////////////////////////////// //~ rjf: Type Operation Functions //- rjf: key constructors internal E_TypeKey e_type_key_zero(void) { E_TypeKey k = zero_struct; return k; } internal E_TypeKey e_type_key_basic(E_TypeKind kind) { E_TypeKey key = {E_TypeKeyKind_Basic}; key.u32[0] = (U32)kind; return key; } internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num) { E_TypeKey key = {E_TypeKeyKind_Ext}; key.u32[0] = (U32)kind; if(E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) { key.kind = E_TypeKeyKind_Basic; } else { key.u32[1] = type_idx; key.u32[2] = rdi_num; } return key; } internal E_TypeKey e_type_key_reg(Arch arch, REGS_RegCode code) { E_TypeKey key = {E_TypeKeyKind_Reg}; key.u32[0] = (U32)arch; key.u32[1] = (U32)code; return key; } internal E_TypeKey e_type_key_reg_alias(Arch arch, REGS_AliasCode code) { E_TypeKey key = {E_TypeKeyKind_RegAlias}; key.u32[0] = (U32)arch; key.u32[1] = (U32)code; return key; } //- rjf: constructed type construction internal U64 e_hash_from_cons_type_params(E_ConsTypeParams *params) { U32 buffer[] = { (U32)params->kind, (U32)params->direct_key.kind, params->direct_key.u32[0], params->direct_key.u32[1], params->direct_key.u32[2], (U32)((params->count & 0x00000000ffffffffull)>> 0), (U32)((params->count & 0xffffffff00000000ull)>> 32), (U32)((params->depth & 0x00000000ffffffffull)>> 0), (U32)((params->depth & 0xffffffff00000000ull)>> 32), }; U64 hash = e_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer))); hash = e_hash_from_string(hash, params->name); return hash; } internal B32 e_cons_type_params_match(E_ConsTypeParams *l, E_ConsTypeParams *r) { B32 result = (l->kind != E_TypeKind_Lens && l->kind == r->kind && l->flags == r->flags && str8_match(l->name, r->name, 0) && e_type_key_match(l->direct_key, r->direct_key) && l->count == r->count && l->depth == r->depth); if(result && l->members != 0 && r->members != 0) { for(U64 idx = 0; idx < l->count; idx += 1) { if(l->members[idx].kind != r->members[idx].kind || !e_type_key_match(l->members[idx].type_key, r->members[idx].type_key) || !str8_match(l->members[idx].name, r->members[idx].name, 0) || l->members[idx].off != r->members[idx].off) { result = 0; break; } } } if(result && l->enum_vals != 0 && r->enum_vals != 0) { for(U64 idx = 0; idx < l->count; idx += 1) { if(l->enum_vals[idx].val != r->enum_vals[idx].val || !str8_match(l->enum_vals[idx].name, r->enum_vals[idx].name, 0)) { result = 0; break; } } } return result; } internal E_TypeKey e_type_key_cons_(E_ConsTypeParams *params) { U64 content_hash = e_hash_from_cons_type_params(params); U64 content_slot_idx = content_hash%e_cache->cons_content_slots_count; E_ConsTypeSlot *content_slot = &e_cache->cons_content_slots[content_slot_idx]; E_ConsTypeNode *node = 0; for(E_ConsTypeNode *n = content_slot->first; n != 0; n = n->content_next) { if(e_cons_type_params_match(params, &n->params)) { node = n; break; } } E_TypeKey result = zero_struct; if(node == 0) { E_TypeKey key = {E_TypeKeyKind_Cons}; key.u32[0] = (U32)params->kind; key.u32[1] = (U32)e_cache->cons_id_gen; e_cache->cons_id_gen += 1; U64 key_hash = e_hash_from_string(5381, str8_struct(&key)); U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count; E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx]; E_ConsTypeNode *node = push_array(e_cache->arena, E_ConsTypeNode, 1); SLLQueuePush_N(content_slot->first, content_slot->last, node, content_next); SLLQueuePush_N(key_slot->first, key_slot->last, node, key_next); node->key = key; MemoryCopyStruct(&node->params, params); node->params.name = push_str8_copy(e_cache->arena, params->name); if(node->params.expand.info != 0) { if(node->params.expand.range == 0) {node->params.expand.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(default);} if(node->params.expand.id_from_num == 0) {node->params.expand.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity);} if(node->params.expand.num_from_id == 0) {node->params.expand.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity);} } if(params->members != 0) { node->params.members = push_array(e_cache->arena, E_Member, params->count); MemoryCopy(node->params.members, params->members, sizeof(E_Member)*params->count); for(U64 idx = 0; idx < node->params.count; idx += 1) { node->params.members[idx].name = push_str8_copy(e_cache->arena, node->params.members[idx].name); node->params.members[idx].inheritance_key_chain = e_type_key_list_copy(e_cache->arena, &node->params.members[idx].inheritance_key_chain); U64 opl_off = (node->params.members[idx].off + e_type_byte_size_from_key(node->params.members[idx].type_key)); node->byte_size = Max(node->byte_size, opl_off); } } else if(params->enum_vals != 0) { node->params.enum_vals = push_array(e_cache->arena, E_EnumVal, params->count); MemoryCopy(node->params.enum_vals, params->enum_vals, sizeof(E_EnumVal)*params->count); for(U64 idx = 0; idx < node->params.count; idx += 1) { node->params.enum_vals[idx].name = push_str8_copy(e_cache->arena, node->params.enum_vals[idx].name); } node->byte_size = e_type_byte_size_from_key(node->params.direct_key); } else if(params->args != 0) { node->params.args = push_array(e_cache->arena, E_Expr *, params->count); for EachIndex(idx, params->count) { node->params.args[idx] = e_expr_copy(e_cache->arena, params->args[idx]); } } else switch(params->kind) { default: { node->byte_size = e_type_byte_size_from_key(node->params.direct_key); }break; case E_TypeKind_Ptr: { node->byte_size = bit_size_from_arch(node->params.arch)/8; }break; case E_TypeKind_Array: { U64 ptee_size = e_type_byte_size_from_key(node->params.direct_key); node->byte_size = ptee_size * node->params.count; }break; } result = key; } else { result = node->key; } return result; } //- rjf: constructed type helpers internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count, E_TypeFlags flags) { E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_Array, .direct_key = element_type_key, .count = count, .flags = flags); return key; } internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags) { E_TypeKey key = e_type_key_cons(.arch = arch, .kind = E_TypeKind_Ptr, .flags = flags, .direct_key = element_type_key, .count = count); return key; } internal E_TypeKey e_type_key_cons_meta_expr(E_TypeKey type_key, String8 expr) { E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_MetaExpr, .direct_key = type_key, .name = expr); return key; } internal E_TypeKey e_type_key_cons_meta_display_name(E_TypeKey type_key, String8 name) { E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_MetaDisplayName, .direct_key = type_key, .name = name); return key; } internal E_TypeKey e_type_key_cons_meta_description(E_TypeKey type_key, String8 desc) { E_TypeKey key = e_type_key_cons(.kind = E_TypeKind_MetaDescription, .direct_key = type_key, .name = desc); return key; } internal E_TypeKey e_type_key_cons_base(Type *type) { E_TypeKey result = e_type_key_zero(); switch(type->kind) { default: if(TypeKind_FirstLeaf <= type->kind && type->kind <= TypeKind_LastLeaf) { E_TypeKind kind = e_type_kind_from_base(type->kind); result = e_type_key_basic(kind); }break; case TypeKind_Ptr: { E_TypeKey direct_type = e_type_key_cons_base(type->direct); E_TypeFlags flags = 0; if(type->flags & TypeFlag_IsPlainText){ flags |= E_TypeFlag_IsPlainText; } if(type->flags & TypeFlag_IsCodeText) { flags |= E_TypeFlag_IsCodeText; } if(type->flags & TypeFlag_IsPathText) { flags |= E_TypeFlag_IsPathText; } result = e_type_key_cons_ptr(Arch_CURRENT, direct_type, 1, flags); }break; case TypeKind_Array: { E_TypeKey direct_type = e_type_key_cons_base(type->direct); result = e_type_key_cons_array(direct_type, type->count, 0); }break; case TypeKind_Struct: { Temp scratch = scratch_begin(0, 0); E_MemberList members = {0}; for(U64 idx = 0; idx < type->count; idx += 1) { E_TypeKey member_type_key = e_type_key_cons_base(type->members[idx].type); e_member_list_push_new(scratch.arena, &members, .name = type->members[idx].name, .off = type->members[idx].value, .type_key = member_type_key); } E_MemberArray members_array = e_member_array_from_list(scratch.arena, &members); result = e_type_key_cons(.arch = Arch_CURRENT, .kind = E_TypeKind_Struct, .name = type->name, .members = members_array.v, .count = members_array.count); scratch_end(scratch); }break; } return result; } internal E_TypeKey e_type_key_file(void) { E_TypeKey key = e_cache->file_type_key; return key; } internal E_TypeKey e_type_key_folder(void) { E_TypeKey key = e_cache->folder_type_key; return key; } //- rjf: basic type key functions internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r) { B32 result = MemoryMatchStruct(&l, &r); return result; } //- rjf: type key -> info extraction internal U64 e_hash_from_type(E_Type *type) { U64 hash = 0; if(type != &e_type_nil) { Temp scratch = scratch_begin(0, 0); String8List strings = {0}; str8_serial_begin(scratch.arena, &strings); str8_serial_push_struct(scratch.arena, &strings, &type->kind); str8_serial_push_struct(scratch.arena, &strings, &type->flags); str8_serial_push_string(scratch.arena, &strings, type->name); str8_serial_push_struct(scratch.arena, &strings, &type->byte_size); str8_serial_push_struct(scratch.arena, &strings, &type->count); str8_serial_push_struct(scratch.arena, &strings, &type->off); String8 direct_type_string = e_type_string_from_key(scratch.arena, type->direct_type_key); String8 owner_type_string = e_type_string_from_key(scratch.arena, type->owner_type_key); U64 direct_hash = e_hash_from_string(5381, direct_type_string); U64 owner_hash = e_hash_from_string(5381, owner_type_string); str8_serial_push_struct(scratch.arena, &strings, &direct_hash); str8_serial_push_struct(scratch.arena, &strings, &owner_hash); if(type->param_type_keys != 0) { for EachIndex(idx, type->count) { String8 param_type_string = e_type_string_from_key(scratch.arena, type->param_type_keys[idx]); U64 param_type_hash = e_hash_from_string(5381, param_type_string); str8_serial_push_struct(scratch.arena, &strings, ¶m_type_hash); } } else if(type->members != 0) { for EachIndex(idx, type->count) { String8 member_type_string = e_type_string_from_key(scratch.arena, type->members[idx].type_key); U64 member_type_hash = e_hash_from_string(5381, member_type_string); str8_serial_push_struct(scratch.arena, &strings, &type->members[idx].off); str8_serial_push_struct(scratch.arena, &strings, &member_type_hash); } } String8 string = str8_serial_end(scratch.arena, &strings); hash = e_hash_from_string(5381, string); scratch_end(scratch); } return hash; } internal E_TypeKind e_type_kind_from_key(E_TypeKey key) { E_TypeKind kind = E_TypeKind_Null; switch(key.kind) { default:{}break; case E_TypeKeyKind_Basic: {kind = (E_TypeKind)key.u32[0];}break; case E_TypeKeyKind_Ext: {kind = (E_TypeKind)key.u32[0];}break; case E_TypeKeyKind_Cons: {kind = (E_TypeKind)key.u32[0];}break; case E_TypeKeyKind_Reg: {kind = E_TypeKind_Union;}break; case E_TypeKeyKind_RegAlias:{kind = E_TypeKind_Union;}break; } return kind; } internal U64 e_type_byte_size_from_key(E_TypeKey key) { ProfBeginFunction(); U64 result = 0; switch(key.kind) { default:{}break; case E_TypeKeyKind_Basic: { E_TypeKind kind = (E_TypeKind)key.u32[0]; result = e_type_kind_basic_byte_size_table[kind]; }break; case E_TypeKeyKind_Ext: { U64 type_node_idx = key.u32[1]; U32 rdi_num = key.u32[2]; if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count) { RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi; RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx); result = rdi_type->byte_size; } }break; case E_TypeKeyKind_Cons: { U64 key_hash = e_hash_from_string(5381, str8_struct(&key)); U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count; E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx]; for(E_ConsTypeNode *node = key_slot->first; node != 0; node = node->key_next) { if(e_type_key_match(node->key, key)) { result = node->byte_size; break; } } }break; } ProfEnd(); return result; } internal E_Type * e_push_type_from_key(Arena *arena, E_TypeKey key) { ProfBeginFunction(); E_Type *type = &e_type_nil; U64 reg_byte_count = 0; { switch(key.kind) { default:{}break; //- rjf: basic type keys case E_TypeKeyKind_Basic: { E_TypeKind kind = (E_TypeKind)key.u32[0]; if(E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) { type = push_array(arena, E_Type, 1); type->kind = kind; type->name = e_type_kind_basic_string_table[kind]; type->byte_size = e_type_kind_basic_byte_size_table[kind]; } }break; //- rjf: constructed type keys case E_TypeKeyKind_Cons: { U64 key_hash = e_hash_from_string(5381, str8_struct(&key)); U64 key_slot_idx = key_hash%e_cache->cons_key_slots_count; E_ConsTypeSlot *key_slot = &e_cache->cons_key_slots[key_slot_idx]; for(E_ConsTypeNode *node = key_slot->first; node != 0; node = node->key_next) { if(e_type_key_match(node->key, key)) { type = push_array(arena, E_Type, 1); type->kind = e_type_kind_from_key(node->key); type->flags = node->params.flags; type->name = push_str8_copy(arena, node->params.name); type->direct_type_key = node->params.direct_key; type->count = node->params.count; type->depth = node->params.depth; type->arch = node->params.arch; type->irext = node->params.irext; type->access = node->params.access; type->expand = node->params.expand; type->byte_size = node->byte_size; switch(type->kind) { default:{}break; case E_TypeKind_Lens: { type->args = push_array(arena, E_Expr *, type->count); MemoryCopy(type->args, node->params.args, sizeof(E_Expr *)*type->count); for EachIndex(idx, type->count) { type->args[idx] = e_expr_copy(arena, type->args[idx]); } }break; case E_TypeKind_Struct: case E_TypeKind_Union: case E_TypeKind_Class: { type->members = push_array(arena, E_Member, type->count); MemoryCopy(type->members, node->params.members, sizeof(E_Member)*type->count); for(U64 idx = 0; idx < type->count; idx += 1) { U64 opl_byte = type->members[idx].off + e_type_byte_size_from_key(type->members[idx].type_key); type->byte_size = Max(type->byte_size, opl_byte); } }break; case E_TypeKind_Enum: { type->enum_vals = push_array(arena, E_EnumVal, type->count); MemoryCopy(type->enum_vals, node->params.enum_vals, sizeof(E_EnumVal)*type->count); }break; } } } }break; //- rjf: external (rdi) type keys case E_TypeKeyKind_Ext: { U64 type_node_idx = key.u32[1]; U32 rdi_num = key.u32[2]; if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count) { RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi; RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); Arch arch = arch_from_rdi_arch(tli->arch); RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx); if(rdi_type->kind != RDI_TypeKind_NULL) { E_TypeKind kind = e_type_kind_from_rdi(rdi_type->kind); //- rjf: record types => unpack name * members & produce if(RDI_TypeKind_FirstRecord <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastRecord) { // rjf: unpack name String8 name = {0}; name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: unpack UDT info RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx); // rjf: unpack members E_Member *members = 0; U32 members_count = 0; { members_count = udt->member_count; members = push_array(arena, E_Member, members_count); if(members_count != 0) { for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx); E_TypeKind member_type_kind = E_TypeKind_Null; RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx); member_type_kind = e_type_kind_from_rdi(member_type->kind); E_Member *dst = &members[member_idx-udt->member_first]; dst->kind = e_member_kind_from_rdi(src->kind); dst->type_key = e_type_key_ext(member_type_kind, src->type_idx, rdi_num); dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); dst->off = (U64)src->off; } } } // rjf: produce type = push_array(arena, E_Type, 1); type->kind = kind; type->name = push_str8_copy(arena, name); type->byte_size = (U64)rdi_type->byte_size; type->count = members_count; type->arch = arch; type->members = members; } //- rjf: enum types => unpack name * values & produce else if(rdi_type->kind == RDI_TypeKind_Enum) { // rjf: unpack name String8 name = {0}; name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: unpack direct type E_TypeKey direct_type_key = zero_struct; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num); } // rjf: unpack members E_EnumVal *enum_vals = 0; U32 enum_vals_count = 0; { U32 udt_idx = rdi_type->user_defined.udt_idx; RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); enum_vals_count = udt->member_count; enum_vals = push_array(arena, E_EnumVal, enum_vals_count); for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx); E_EnumVal *dst = &enum_vals[member_idx-udt->member_first]; dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); dst->val = src->val; } } // rjf: produce type = push_array(arena, E_Type, 1); type->kind = kind; type->name = push_str8_copy(arena, name); type->byte_size = (U64)rdi_type->byte_size; type->count = enum_vals_count; type->arch = arch; type->enum_vals = enum_vals; type->direct_type_key = direct_type_key; } //- rjf: constructed types else if(RDI_TypeKind_FirstConstructed <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastConstructed) { // rjf: unpack direct type B32 direct_type_is_good = 0; E_TypeKey direct_type_key = zero_struct; U64 direct_type_byte_size = 0; if(rdi_type->constructed.direct_type_idx < type_node_idx) { RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx); E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->constructed.direct_type_idx, rdi_num); direct_type_is_good = 1; direct_type_byte_size = (U64)direct_type_node->byte_size; } // rjf: construct based on kind switch(rdi_type->kind) { case RDI_TypeKind_Modifier: { E_TypeFlags flags = 0; if(rdi_type->flags & RDI_TypeModifierFlag_Const) { flags |= E_TypeFlag_Const; } if(rdi_type->flags & RDI_TypeModifierFlag_Volatile) { flags |= E_TypeFlag_Volatile; } if(rdi_type->flags & RDI_TypeModifierFlag_Restrict) { flags |= E_TypeFlag_Restrict; } type = push_array(arena, E_Type, 1); type->kind = kind; type->direct_type_key = direct_type_key; type->byte_size = direct_type_byte_size; type->flags = flags; type->arch = arch; }break; case RDI_TypeKind_Ptr: case RDI_TypeKind_LRef: case RDI_TypeKind_RRef: { type = push_array(arena, E_Type, 1); type->kind = kind; type->direct_type_key = direct_type_key; type->byte_size = bit_size_from_arch(arch)/8; type->count = 1; type->arch = arch; }break; case RDI_TypeKind_Array: { type = push_array(arena, E_Type, 1); type->kind = kind; type->direct_type_key = direct_type_key; type->count = rdi_type->constructed.count; type->byte_size = direct_type_byte_size * type->count; type->arch = arch; }break; case RDI_TypeKind_Function: { U32 count = rdi_type->constructed.count; U32 idx_run_first = rdi_type->constructed.param_idx_run_first; U32 check_count = 0; U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count); if(check_count == count) { type = push_array(arena, E_Type, 1); type->kind = kind; type->byte_size = bit_size_from_arch(arch)/8; type->direct_type_key = direct_type_key; type->count = count; type->param_type_keys = push_array(arena, E_TypeKey, type->count); type->arch = arch; for(U32 idx = 0; idx < type->count; idx += 1) { U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind); type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num); } else { break; } } } }break; case RDI_TypeKind_Method: { // NOTE(rjf): for methods, the `direct` type points at the owner type. // the return type, instead of being encoded via the `direct` type, is // encoded via the first parameter. U32 count = rdi_type->constructed.count; U32 idx_run_first = rdi_type->constructed.param_idx_run_first; U32 check_count = 0; U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count); if(check_count == count) { type = push_array(arena, E_Type, 1); type->kind = kind; type->byte_size = bit_size_from_arch(arch)/8; type->owner_type_key = direct_type_key; type->count = count; type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count); type->arch = arch; for(U32 idx = 0; idx < type->count; idx += 1) { U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind); type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num); } else { break; } } if(type->count > 0) { type->direct_type_key = type->param_type_keys[0]; type->count -= 1; type->param_type_keys += 1; } } }break; case RDI_TypeKind_MemberPtr: { // rjf: unpack owner type E_TypeKey owner_type_key = zero_struct; if(rdi_type->constructed.owner_type_idx < type_node_idx) { RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx); E_TypeKind owner_type_kind = e_type_kind_from_rdi(owner_type_node->kind); owner_type_key = e_type_key_ext(owner_type_kind, rdi_type->constructed.owner_type_idx, rdi_num); } type = push_array(arena, E_Type, 1); type->kind = kind; type->byte_size = bit_size_from_arch(arch)/8; type->owner_type_key = owner_type_key; type->direct_type_key = direct_type_key; type->arch = arch; }break; } } //- rjf: alias types else if(rdi_type->kind == RDI_TypeKind_Alias) { // rjf: unpack name String8 name = {0}; name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: unpack direct type E_TypeKey direct_type_key = zero_struct; U64 direct_type_byte_size = 0; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num); direct_type_byte_size = direct_type_node->byte_size; } // rjf: produce type = push_array(arena, E_Type, 1); type->kind = kind; type->name = push_str8_copy(arena, name); type->byte_size = direct_type_byte_size; type->direct_type_key = direct_type_key; type->arch = arch; } //- rjf: bitfields else if(RDI_TypeKind_Bitfield == rdi_type->kind) { // rjf: unpack direct type E_TypeKey direct_type_key = zero_struct; U64 direct_type_byte_size = 0; if(rdi_type->bitfield.direct_type_idx < type_node_idx) { RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx); E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind); direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->bitfield.direct_type_idx, rdi_num); direct_type_byte_size = direct_type_node->byte_size; } // rjf: produce type = push_array(arena, E_Type, 1); type->kind = kind; type->byte_size = direct_type_byte_size; type->direct_type_key = direct_type_key; type->off = (U32)rdi_type->bitfield.off; type->count = (U64)rdi_type->bitfield.size; type->arch = arch; } //- rjf: incomplete types else if(RDI_TypeKind_FirstIncomplete <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastIncomplete) { // rjf: unpack name String8 name = {0}; name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: produce type = push_array(arena, E_Type, 1); type->kind = kind; type->name = push_str8_copy(arena, name); type->arch = arch; } } } }break; //- rjf: reg type keys case E_TypeKeyKind_Reg: { Arch arch = (Arch)key.u32[0]; REGS_RegCode code = (REGS_RegCode)key.u32[1]; REGS_Rng rng = regs_reg_code_rng_table_from_arch(arch)[code]; reg_byte_count = (U64)rng.byte_size; }goto build_reg_type; case E_TypeKeyKind_RegAlias: { Arch arch = (Arch)key.u32[0]; REGS_AliasCode code = (REGS_AliasCode)key.u32[1]; REGS_Slice slice = regs_alias_code_slice_table_from_arch(arch)[code]; reg_byte_count = (U64)slice.byte_size; }goto build_reg_type; build_reg_type: { Temp scratch = scratch_begin(&arena, 1); type = push_array(arena, E_Type, 1); type->kind = E_TypeKind_Union; type->name = push_str8f(arena, "reg_%I64u_bit", reg_byte_count*8); type->byte_size = (U64)reg_byte_count; type->arch = (Arch)key.u32[0]; // rjf: build register type members E_MemberList members = {0}; { // rjf: build exact-sized members { if(type->byte_size == 16) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u128"); mem->type_key = e_type_key_basic(E_TypeKind_U128); } if(type->byte_size == 8) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u64"); mem->type_key = e_type_key_basic(E_TypeKind_U64); } if(type->byte_size == 4) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u32"); mem->type_key = e_type_key_basic(E_TypeKind_U32); } if(type->byte_size == 2) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u16"); mem->type_key = e_type_key_basic(E_TypeKind_U16); } if(type->byte_size == 1) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u8"); mem->type_key = e_type_key_basic(E_TypeKind_U8); } } // rjf: build arrays for subdivisions { if(type->byte_size > 16 && type->byte_size%16 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u128s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U128), reg_byte_count/16, 0); } if(type->byte_size > 8 && type->byte_size%8 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u64s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U64), reg_byte_count/8, 0); } if(type->byte_size > 4 && type->byte_size%4 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u32s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U32), reg_byte_count/4, 0); } if(type->byte_size > 2 && type->byte_size%2 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u16s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U16), reg_byte_count/2, 0); } if(type->byte_size > 1) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("u8s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), reg_byte_count, E_TypeFlag_IsNotText); } if(type->byte_size > 4 && type->byte_size%4 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("f32s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F32), reg_byte_count/4, 0); } if(type->byte_size > 8 && type->byte_size%8 == 0) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); SLLQueuePush(members.first, members.last, n); members.count += 1; E_Member *mem = &n->v; mem->kind = E_MemberKind_DataField; mem->name = str8_lit("f64s"); mem->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_F64), reg_byte_count/8, 0); } } } // rjf: commit members type->count = members.count; type->members = push_array_no_zero(arena, E_Member, members.count); U64 idx = 0; for(E_MemberNode *n = members.first; n != 0; n = n->next, idx += 1) { MemoryCopyStruct(&type->members[idx], &n->v); } scratch_end(scratch); }break; } } ProfEnd(); return type; } internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b) { int result = 0; if(a->kind < b->kind) { result = -1; } else if(a->kind > b->kind) { result = +1; } else if(a->off < b->off) { result = -1; } else if(a->off > b->off) { result = +1; } return result; } internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key) { Temp scratch = scratch_begin(&arena, 1); E_TypeKind root_type_kind = e_type_kind_from_key(key); //- rjf: walk type tree; gather members list E_MemberList members_list = {0}; B32 members_need_offset_sort = 0; { E_Type *root_type = e_type_from_key(key); typedef struct Task Task; struct Task { Task *next; U64 base_off; E_TypeKeyList inheritance_chain; E_TypeKey type_key; E_Type *type; }; Task start_task = {0, 0, {0}, key, root_type}; Task *first_task = &start_task; Task *last_task = &start_task; for(Task *task = first_task; task != 0; task = task->next) { E_Type *type = task->type; if(type->members != 0) { U64 last_member_off = 0; for(U64 member_idx = 0; member_idx < type->count; member_idx += 1) { if(type->members[member_idx].name.size != 0 && type->members[member_idx].kind == E_MemberKind_DataField) { E_MemberNode *n = push_array(scratch.arena, E_MemberNode, 1); MemoryCopyStruct(&n->v, &type->members[member_idx]); n->v.off += task->base_off; n->v.inheritance_key_chain = task->inheritance_chain; SLLQueuePush(members_list.first, members_list.last, n); members_list.count += 1; members_need_offset_sort = members_need_offset_sort || (type->members[member_idx].kind == E_MemberKind_DataField && n->v.off < last_member_off); members_need_offset_sort = members_need_offset_sort || (type->members[member_idx].kind != E_MemberKind_DataField); last_member_off = n->v.off; } else if(type->members[member_idx].kind == E_MemberKind_Base) { Task *t = push_array(scratch.arena, Task, 1); t->base_off = type->members[member_idx].off + task->base_off; t->inheritance_chain = e_type_key_list_copy(scratch.arena, &task->inheritance_chain); e_type_key_list_push(scratch.arena, &t->inheritance_chain, type->members[member_idx].type_key); t->type_key = type->members[member_idx].type_key; t->type = e_type_from_key(type->members[member_idx].type_key); SLLQueuePush(first_task, last_task, t); members_need_offset_sort = 1; } } } } } //- rjf: convert to array E_MemberArray members = {0}; { members.count = members_list.count; members.v = push_array(arena, E_Member, members.count); U64 idx = 0; for(E_MemberNode *n = members_list.first; n != 0; n = n->next) { MemoryCopyStruct(&members.v[idx], &n->v); members.v[idx].name = push_str8_copy(arena, members.v[idx].name); members.v[idx].inheritance_key_chain = e_type_key_list_copy(arena, &members.v[idx].inheritance_key_chain); idx += 1; } } //- rjf: sort array by offset if needed if(members_need_offset_sort && (root_type_kind == E_TypeKind_Struct || root_type_kind == E_TypeKind_Class) && key.kind != E_TypeKeyKind_Cons) { quick_sort(members.v, members.count, sizeof(E_Member), e_type_qsort_compare_members_offset); } //- rjf: find all padding instances typedef struct PaddingNode PaddingNode; struct PaddingNode { PaddingNode *next; U64 off; U64 size; U64 prev_member_idx; }; PaddingNode *first_padding = 0; PaddingNode *last_padding = 0; U64 padding_count = 0; if((root_type_kind == E_TypeKind_Struct || root_type_kind == E_TypeKind_Class) && key.kind != E_TypeKeyKind_Cons) { for(U64 idx = 0; idx < members.count; idx += 1) { E_Member *member = &members.v[idx]; if(idx+1 < members.count) { U64 member_byte_size = e_type_byte_size_from_key(member->type_key); Rng1U64 member_byte_range = r1u64(member->off, member->off + member_byte_size); if(member[1].off > member_byte_range.max) { PaddingNode *n = push_array(scratch.arena, PaddingNode, 1); SLLQueuePush(first_padding, last_padding, n); n->off = member_byte_range.max; n->size = member[1].off - member_byte_range.max; n->prev_member_idx = idx; padding_count += 1; } } } } //- rjf: produce new members array, if we have any padding if(padding_count != 0) { E_MemberArray new_members = {0}; new_members.count = members.count + padding_count; new_members.v = push_array(arena, E_Member, new_members.count); MemoryCopy(new_members.v, members.v, sizeof(E_Member)*members.count); U64 padding_idx = 0; for(PaddingNode *n = first_padding; n != 0; n = n->next) { if(members.count+padding_idx > n->prev_member_idx+1) { MemoryCopy(new_members.v + n->prev_member_idx + padding_idx + 2, new_members.v + n->prev_member_idx + padding_idx + 1, sizeof(E_Member) * (members.count + padding_idx - (n->prev_member_idx + padding_idx + 1))); } E_Member *padding_member = &new_members.v[n->prev_member_idx+padding_idx+1]; MemoryZeroStruct(padding_member); padding_member->kind = E_MemberKind_Padding; padding_member->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), n->size, E_TypeFlag_IsNotText); padding_member->off = n->off; padding_member->name = push_str8f(arena, "$padding_%I64u", padding_idx); padding_idx += 1; } members = new_members; } scratch_end(scratch); return members; } internal E_TypeExpandRule * e_expand_rule_from_type_key(E_TypeKey key) { E_TypeExpandRule *rule = &e_type_expand_rule__default; { E_Type *type = e_type_from_key(e_type_key_unwrap(key, E_TypeUnwrapFlag_Meta)); if(type->expand.info != 0) { rule = &type->expand; } for(E_Type *lens_type = type; lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set; lens_type = e_type_from_key(e_type_key_unwrap(lens_type->direct_type_key, E_TypeUnwrapFlag_Meta))) { if(lens_type->expand.info != 0) { rule = &lens_type->expand; break; } } } return rule; } //- rjf: type key traversal internal E_TypeKey e_type_key_direct(E_TypeKey key) { E_TypeKey result = zero_struct; switch(key.kind) { default:{}break; case E_TypeKeyKind_Ext: case E_TypeKeyKind_Cons: { E_Type *type = e_type_from_key(key); result = type->direct_type_key; }break; } return result; } internal E_TypeKey e_type_key_owner(E_TypeKey key) { E_TypeKey result = zero_struct; switch(key.kind) { default:{}break; case E_TypeKeyKind_Ext: case E_TypeKeyKind_Cons: { E_Type *type = e_type_from_key(key); result = type->owner_type_key; }break; } return result; } internal E_TypeKey e_type_key_promote(E_TypeKey key) { E_TypeKey result = key; E_TypeKind kind = e_type_kind_from_key(key); if(kind == E_TypeKind_Bool || kind == E_TypeKind_S8 || kind == E_TypeKind_S16 || kind == E_TypeKind_U8 || kind == E_TypeKind_U16) { result = e_type_key_basic(E_TypeKind_S32); } return result; } internal E_TypeKey e_type_key_unwrap(E_TypeKey key, E_TypeUnwrapFlags flags) { E_TypeKey result = key; E_TypeKind kind = e_type_kind_from_key(result); B32 did_ptr = 0; for(;;) { B32 done = 0; switch(kind) { default:{done = 1;}break; case E_TypeKind_Modifier: {done = !(flags & E_TypeUnwrapFlag_Modifiers);}break; case E_TypeKind_Lens: {done = !(flags & E_TypeUnwrapFlag_Lenses);}break; case E_TypeKind_MetaDisplayName: case E_TypeKind_MetaDescription: case E_TypeKind_MetaExpr: {done = !(flags & E_TypeUnwrapFlag_Meta);}break; case E_TypeKind_Enum: {done = !(flags & E_TypeUnwrapFlag_Enums);}break; case E_TypeKind_Alias: {done = !(flags & E_TypeUnwrapFlag_Aliases);}break; case E_TypeKind_Bitfield: {done = !(flags & E_TypeUnwrapFlag_Bitfields);}break; case E_TypeKind_Array: case E_TypeKind_Ptr: case E_TypeKind_RRef: case E_TypeKind_LRef: case E_TypeKind_MemberPtr: { done = (did_ptr || !(flags & E_TypeUnwrapFlag_Pointers)); did_ptr = 1; }break; } if(done) { break; } result = e_type_key_direct(result); kind = e_type_kind_from_key(result); } return result; } //- rjf: type comparisons internal B32 e_type_match(E_TypeKey l, E_TypeKey r) { // rjf: unpack parameters E_TypeKey lu = e_type_key_unwrap(l, E_TypeUnwrapFlag_AllDecorative); E_TypeKey ru = e_type_key_unwrap(r, E_TypeUnwrapFlag_AllDecorative); // rjf: exact key matches -> match B32 result = e_type_key_match(lu, ru); // rjf: if keys don't match, type *contents* could still match, // so we need to unpack the type info & compare if(!result) { E_TypeKind luk = e_type_kind_from_key(lu); E_TypeKind ruk = e_type_kind_from_key(ru); if(luk == ruk) { switch(luk) { default: { if(e_type_kind_is_basic_or_enum(luk)) { result = 1; } else { result = 0; } }break; case E_TypeKind_Ptr: case E_TypeKind_LRef: case E_TypeKind_RRef: { E_TypeKey lud = e_type_key_direct(lu); E_TypeKey rud = e_type_key_direct(ru); result = e_type_match(lud, rud); }break; case E_TypeKind_MemberPtr: { E_TypeKey lud = e_type_key_direct(lu); E_TypeKey rud = e_type_key_direct(ru); E_TypeKey luo = e_type_key_owner(lu); E_TypeKey ruo = e_type_key_owner(ru); result = (e_type_match(lud, rud) && e_type_match(luo, ruo)); }break; case E_TypeKind_Array: { E_Type *lt = e_type_from_key(l); E_Type *rt = e_type_from_key(r); if(lt->count == rt->count && e_type_match(lt->direct_type_key, rt->direct_type_key)) { result = 1; } }break; case E_TypeKind_Function: { E_Type *lt = e_type_from_key(l); E_Type *rt = e_type_from_key(r); if(lt->count == rt->count && e_type_match(lt->direct_type_key, rt->direct_type_key)) { B32 params_match = 1; E_TypeKey *lp = lt->param_type_keys; E_TypeKey *rp = rt->param_type_keys; U64 count = lt->count; for(U64 i = 0; i < count; i += 1, lp += 1, rp += 1) { if(!e_type_match(*lp, *rp)) { params_match = 0; break; } } result = params_match; } }break; case E_TypeKind_Method: { E_Type *lt = e_type_from_key(l); E_Type *rt = e_type_from_key(r); if(lt->count == rt->count && e_type_match(lt->direct_type_key, rt->direct_type_key) && e_type_match(lt->owner_type_key, rt->owner_type_key)) { B32 params_match = 1; E_TypeKey *lp = lt->param_type_keys; E_TypeKey *rp = rt->param_type_keys; U64 count = lt->count; for(U64 i = 0; i < count; i += 1, lp += 1, rp += 1) { if(!e_type_match(*lp, *rp)) { params_match = 0; break; } } result = params_match; } }break; } } } return result; } //- rjf: key -> string internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return) { String8 keyword = {0}; E_TypeKind kind = e_type_kind_from_key(key); switch(kind) { default: { E_Type *type = e_type_from_key(key); str8_list_pushf(arena, out, "%S ", type->name); }break; case E_TypeKind_Bitfield: { E_Type *type = e_type_from_key(key); e_type_lhs_string_from_key(arena, type->direct_type_key, out, prec, skip_return); str8_list_pushf(arena, out, ": %I64u", type->count); }break; case E_TypeKind_Modifier: { E_Type *type = e_type_from_key(key); E_TypeKey direct = type->direct_type_key; e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); if(type->flags & E_TypeFlag_Const) { str8_list_push(arena, out, str8_lit("const ")); } if(type->flags & E_TypeFlag_Volatile) { str8_list_push(arena, out, str8_lit("volatile ")); } if(type->flags & E_TypeFlag_Restrict) { str8_list_push(arena, out, str8_lit("restrict ")); } }break; case E_TypeKind_Variadic: { str8_list_push(arena, out, str8_lit("...")); }break; case E_TypeKind_Struct: case E_TypeKind_Union: case E_TypeKind_Enum: case E_TypeKind_Class: case E_TypeKind_Alias: { E_Type *type = e_type_from_key(key); str8_list_pushf(arena, out, "%S ", type->name); }break; case E_TypeKind_IncompleteStruct: keyword = str8_lit("struct"); goto fwd_udt; case E_TypeKind_IncompleteUnion: keyword = str8_lit("union"); goto fwd_udt; case E_TypeKind_IncompleteEnum: keyword = str8_lit("enum"); goto fwd_udt; case E_TypeKind_IncompleteClass: keyword = str8_lit("class"); goto fwd_udt; fwd_udt:; { E_Type *type = e_type_from_key(key); str8_list_push(arena, out, keyword); str8_list_push(arena, out, str8_lit(" ")); str8_list_pushf(arena, out, "%S ", type->name); }break; case E_TypeKind_Array: { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, 2, skip_return); if(prec == 1) { str8_list_push(arena, out, str8_lit("(")); } }break; case E_TypeKind_Function: { if(!skip_return) { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, 2, 0); } if(prec == 1) { str8_list_push(arena, out, str8_lit("(")); } }break; case E_TypeKind_Lens: { E_Type *type = e_type_from_key(key); str8_list_pushf(arena, out, "%S(", type->name); E_TypeKey direct = e_type_key_direct(key); String8 direct_string = e_type_string_from_key(arena, direct); str8_list_push(arena, out, direct_string); for EachIndex(idx, type->count) { String8 string = e_string_from_expr(arena, type->args[idx], str8_zero()); str8_list_pushf(arena, out, ", "); str8_list_push(arena, out, string); } str8_list_pushf(arena, out, ")"); }break; case E_TypeKind_Ptr: { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); str8_list_push(arena, out, str8_lit("*")); E_Type *type = e_type_from_key(key); if(type->count != 1) { str8_list_pushf(arena, out, ".%I64u", type->count); } }break; case E_TypeKind_LRef: { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); str8_list_push(arena, out, str8_lit("&")); }break; case E_TypeKind_RRef: { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); str8_list_push(arena, out, str8_lit("&&")); }break; case E_TypeKind_MemberPtr: { E_Type *type = e_type_from_key(key); E_TypeKey direct = type->direct_type_key; e_type_lhs_string_from_key(arena, direct, out, 1, skip_return); E_Type *container = e_type_from_key(type->owner_type_key); if(container->kind != E_TypeKind_Null) { str8_list_push(arena, out, push_str8_copy(arena, container->name)); } else { str8_list_push(arena, out, str8_lit("")); } str8_list_push(arena, out, str8_lit("::*")); }break; case E_TypeKind_MetaExpr: case E_TypeKind_MetaDisplayName: case E_TypeKind_MetaDescription: { E_TypeKey direct = e_type_key_direct(key); e_type_lhs_string_from_key(arena, direct, out, prec, skip_return); }break; } } internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec) { E_TypeKind kind = e_type_kind_from_key(key); switch(kind) { default:{}break; case E_TypeKind_Bitfield: { E_TypeKey direct = e_type_key_direct(key); e_type_rhs_string_from_key(arena, direct, out, prec); }break; case E_TypeKind_Modifier: case E_TypeKind_Ptr: case E_TypeKind_LRef: case E_TypeKind_RRef: case E_TypeKind_MemberPtr: { E_TypeKey direct = e_type_key_direct(key); e_type_rhs_string_from_key(arena, direct, out, 1); }break; case E_TypeKind_Array: { E_Type *type = e_type_from_key(key); if(prec == 1) { str8_list_push(arena, out, str8_lit(")")); } String8 count_str = str8_from_u64(arena, type->count, 10, 0, 0); str8_list_push(arena, out, str8_lit("[")); str8_list_push(arena, out, count_str); str8_list_push(arena, out, str8_lit("]")); E_TypeKey direct = e_type_key_direct(key); e_type_rhs_string_from_key(arena, direct, out, 2); }break; case E_TypeKind_Function: { E_Type *type = e_type_from_key(key); if(prec == 1) { str8_list_push(arena, out, str8_lit(")")); } if(type->count == 0) { str8_list_push(arena, out, str8_lit("(void)")); } else { str8_list_push(arena, out, str8_lit("(")); U64 param_count = type->count; E_TypeKey *param_type_keys = type->param_type_keys; for(U64 param_idx = 0; param_idx < param_count; param_idx += 1) { E_TypeKey param_type_key = param_type_keys[param_idx]; String8 param_str = e_type_string_from_key(arena, param_type_key); String8 param_str_trimmed = str8_skip_chop_whitespace(param_str); str8_list_push(arena, out, param_str_trimmed); if(param_idx+1 < param_count) { str8_list_push(arena, out, str8_lit(", ")); } } str8_list_push(arena, out, str8_lit(")")); } E_TypeKey direct = e_type_key_direct(key); e_type_rhs_string_from_key(arena, direct, out, 2); }break; case E_TypeKind_MetaExpr: { E_TypeKey direct = e_type_key_direct(key); e_type_rhs_string_from_key(arena, direct, out, prec); }break; } } internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; e_type_lhs_string_from_key(scratch.arena, key, &list, 0, 0); e_type_rhs_string_from_key(scratch.arena, key, &list, 0); String8 result = str8_list_join(arena, &list, 0); result = str8_skip_chop_whitespace(result); scratch_end(scratch); return result; } internal E_TypeKey e_default_expansion_type_from_key(E_TypeKey root_key) { E_TypeKey type_key = zero_struct; B32 hit_1ptr = 0; for(E_TypeKey key = root_key; !e_type_key_match(e_type_key_zero(), key); key = e_type_key_direct(key)) { B32 done = 1; E_TypeKind kind = e_type_kind_from_key(key); //- rjf: if we have pointers which point to a single thing (count = 1), // or we have a lens, or we have a modifier node, then we will defer to // the next type in the chain. // // if this pointer points to N things (count > 1), then we can use it for // array-like expansion. // if(e_type_kind_is_pointer_or_ref(kind)) { E_Type *type = e_type_from_key(key); if(!e_type_key_match(e_type_key_basic(E_TypeKind_Void), type->direct_type_key)) { if(type->count == 1 && hit_1ptr) { type_key = key; } else if(type->count == 1 && !hit_1ptr) { hit_1ptr = 1; done = 0; } else if(type->count > 1) { type_key = key; } } } //- rjf: if we have lenses or modifiers in the type chain, then we will // defer to the next type in the chain. // // NOTE(rjf): while it may seem like a lens type needs to do something // different, because lenses sometimes want to define their own expansion // rules, they would've redirected to an entirely different expansion // hook. if we are in the default expansion hook, then the lenses do not // impact the expansion at all (e.g. they are for other cosmetic things, // like visualizers or integer radix changes), and so in that case we // want to ignore them. // else if(kind == E_TypeKind_Lens || kind == E_TypeKind_Modifier || kind == E_TypeKind_Alias) { done = 0; } //- rjf: if we have meta-expression tags in the type chain, defer // to the next type in the chain. else if(E_TypeKind_FirstMeta <= kind && kind <= E_TypeKind_LastMeta) { done = 0; } //- rjf: if we've reached a struct-like, then we can use that for // struct-like expansion. else if(kind == E_TypeKind_Struct || kind == E_TypeKind_Union || kind == E_TypeKind_Class || kind == E_TypeKind_Set) { type_key = key; } //- rjf: if we've reached an enum-like, then we can use that for // enum-like expansion. else if(kind == E_TypeKind_Enum) { type_key = key; } //- rjf: if we've reached an array, then we can use that for array-like // expansion. else if(kind == E_TypeKind_Array) { type_key = key; } //- rjf: if we're done, then just break. if(done) { break; } } return type_key; } //////////////////////////////// //~ rjf: Cache Lookups internal E_Type * e_type_from_key(E_TypeKey key) { E_Type *type = &e_type_nil; { U64 hash = e_hash_from_string(5381, str8_struct(&key)); U64 slot_idx = hash%e_cache->type_cache_slots_count; E_TypeCacheNode *node = 0; for(E_TypeCacheNode *n = e_cache->type_cache_slots[slot_idx].first; n != 0; n = n->next) { if(e_type_key_match(key, n->key)) { node = n; break; } } if(node == 0) { node = push_array(e_cache->arena, E_TypeCacheNode, 1); node->key = key; node->type = e_push_type_from_key(e_cache->arena, key); SLLQueuePush(e_cache->type_cache_slots[slot_idx].first, e_cache->type_cache_slots[slot_idx].last, node); } type = node->type; } return type; } //- rjf: member lookups internal E_MemberCacheNode * e_member_cache_node_from_type_key(E_TypeKey key) { U64 hash = e_hash_from_string(5381, str8_struct(&key)); U64 slot_idx = hash%e_cache->member_cache_slots_count; E_MemberCacheSlot *slot = &e_cache->member_cache_slots[slot_idx]; E_MemberCacheNode *node = 0; for(E_MemberCacheNode *n = slot->first; n != 0; n = n->next) { if(e_type_key_match(n->key, key)) { node = n; break; } } if(node == 0) { node = push_array(e_cache->arena, E_MemberCacheNode, 1); SLLQueuePush(slot->first, slot->last, node); node->key = key; node->members = e_type_data_members_from_key(e_cache->arena, key); node->member_hash_slots_count = node->members.count; node->member_hash_slots = push_array(e_cache->arena, E_MemberHashSlot, node->member_hash_slots_count); node->member_filter_slots_count = 16; node->member_filter_slots = push_array(e_cache->arena, E_MemberFilterSlot, node->member_filter_slots_count); for EachIndex(idx, node->members.count) { U64 hash = e_hash_from_string(5381, node->members.v[idx].name); U64 slot_idx = hash%node->member_hash_slots_count; E_MemberHashNode *n = push_array(e_cache->arena, E_MemberHashNode, 1); SLLQueuePush(node->member_hash_slots[slot_idx].first, node->member_hash_slots[slot_idx].last, n); n->member_idx = idx; } } return node; } internal E_MemberArray e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter) { E_MemberArray members = {0}; E_MemberCacheNode *node = e_member_cache_node_from_type_key(key); if(node != 0) { if(filter.size == 0) { members = node->members; } else { U64 hash = e_hash_from_string(5381, filter); U64 slot_idx = hash%node->member_filter_slots_count; E_MemberFilterSlot *slot = &node->member_filter_slots[slot_idx]; E_MemberFilterNode *filter_node = 0; for(E_MemberFilterNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->filter, filter, 0)) { filter_node = n; break; } } if(filter_node == 0) { Temp scratch = scratch_begin(0, 0); filter_node = push_array(e_cache->arena, E_MemberFilterNode, 1); filter_node->filter = push_str8_copy(e_cache->arena, filter); E_MemberList member_list__filtered = {0}; for EachIndex(idx, node->members.count) { E_Member *member = &node->members.v[idx]; FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, member->name); if(matches.count == matches.needle_part_count) { e_member_list_push(scratch.arena, &member_list__filtered, member); } } filter_node->members_filtered = e_member_array_from_list(e_cache->arena, &member_list__filtered); scratch_end(scratch); } members = filter_node->members_filtered; } } return members; } internal E_MemberArray e_type_data_members_from_key__cached(E_TypeKey key) { E_MemberArray members = {0}; E_MemberCacheNode *node = e_member_cache_node_from_type_key(key); if(node != 0) { members = node->members; } return members; } internal E_Member e_type_member_from_key_name__cached(E_TypeKey key, String8 name) { E_Member result = {0}; E_MemberCacheNode *node = e_member_cache_node_from_type_key(key); if(node != 0 && node->member_hash_slots_count != 0) { U64 hash = e_hash_from_string(5381, name); U64 slot_idx = hash%node->member_hash_slots_count; for(E_MemberHashNode *n = node->member_hash_slots[slot_idx].first; n != 0; n = n->next) { if(str8_match(node->members.v[n->member_idx].name, name, 0)) { result = node->members.v[n->member_idx]; break; } } } return result; } //- rjf: enum val lookups internal E_EnumValCacheNode * e_enum_val_cache_node_from_type_key(E_TypeKey key) { U64 hash = e_hash_from_string(5381, str8_struct(&key)); U64 slot_idx = hash%e_cache->enum_val_cache_slots_count; E_EnumValCacheSlot *slot = &e_cache->enum_val_cache_slots[slot_idx]; E_EnumValCacheNode *node = 0; for(E_EnumValCacheNode *n = slot->first; n != 0; n = n->next) { if(e_type_key_match(n->key, key)) { node = n; break; } } if(node == 0) { node = push_array(e_cache->arena, E_EnumValCacheNode, 1); SLLQueuePush(slot->first, slot->last, node); node->key = key; E_Type *type = e_type_from_key(key); if(type->kind == E_TypeKind_Enum) { node->val_hash_slots_count = type->count; node->val_hash_slots = push_array(e_cache->arena, E_EnumValHashSlot, node->val_hash_slots_count); node->val_filter_slots_count = 16; node->val_filter_slots = push_array(e_cache->arena, E_EnumValFilterSlot, node->val_filter_slots_count); for EachIndex(idx, type->count) { U64 hash = e_hash_from_string(5381, type->enum_vals[idx].name); U64 slot_idx = hash%node->val_hash_slots_count; E_EnumValHashNode *n = push_array(e_cache->arena, E_EnumValHashNode, 1); SLLQueuePush(node->val_hash_slots[slot_idx].first, node->val_hash_slots[slot_idx].last, n); n->val_idx = idx; } } } return node; } internal E_EnumValArray e_type_enum_vals_from_key_filter__cached(E_TypeKey key, String8 filter) { E_EnumValArray enum_vals = {0}; E_EnumValCacheNode *node = e_enum_val_cache_node_from_type_key(key); if(node != 0) { if(filter.size == 0) { E_Type *type = e_type_from_key(key); if(type->kind == E_TypeKind_Enum) { enum_vals.v = type->enum_vals; enum_vals.count = type->count; } } else { U64 hash = e_hash_from_string(5381, filter); U64 slot_idx = hash%node->val_filter_slots_count; E_EnumValFilterSlot *slot = &node->val_filter_slots[slot_idx]; E_EnumValFilterNode *filter_node = 0; for(E_EnumValFilterNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->filter, filter, 0)) { filter_node = n; break; } } if(filter_node == 0) { Temp scratch = scratch_begin(0, 0); filter_node = push_array(e_cache->arena, E_EnumValFilterNode, 1); filter_node->filter = push_str8_copy(e_cache->arena, filter); E_Type *type = e_type_from_key(key); E_EnumValList enum_val_list__filtered = {0}; if(type->kind == E_TypeKind_Enum) { for EachIndex(idx, type->count) { E_EnumVal *enum_val = &type->enum_vals[idx]; FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, enum_val->name); if(matches.count == matches.needle_part_count) { e_enum_val_list_push(scratch.arena, &enum_val_list__filtered, enum_val); } } } filter_node->vals_filtered = e_enum_val_array_from_list(e_cache->arena, &enum_val_list__filtered); scratch_end(scratch); } enum_vals = filter_node->vals_filtered; } } return enum_vals; } internal E_EnumValArray e_type_enum_vals_from_key__cached(E_TypeKey key) { E_EnumValArray enum_vals = e_type_enum_vals_from_key_filter__cached(key, str8_zero()); return enum_vals; } internal E_EnumVal e_type_enum_val_from_key_name__cached(E_TypeKey key, String8 name) { E_EnumVal result = {0}; E_EnumValCacheNode *node = e_enum_val_cache_node_from_type_key(key); if(node != 0 && node->val_hash_slots_count != 0) { Temp scratch = scratch_begin(0, 0); E_Type *type = e_type_from_key(key); String8 name_qualified_0 = push_str8f(scratch.arena, "%S%S", type->name, name); String8 name_qualified_1 = push_str8f(scratch.arena, "%S_%S", type->name, name); U64 hash = e_hash_from_string(5381, name); U64 slot_idx = hash%node->val_hash_slots_count; for(E_EnumValHashNode *n = node->val_hash_slots[slot_idx].first; n != 0; n = n->next) { if(str8_match(type->enum_vals[n->val_idx].name, name, 0) || str8_match(type->enum_vals[n->val_idx].name, name_qualified_0, 0) || str8_match(type->enum_vals[n->val_idx].name, name_qualified_1, 0)) { result = type->enum_vals[n->val_idx]; break; } } scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: (Built-In Type Hooks) Default Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(default) { E_TypeExpandInfo result = {0}; { //- rjf: try to extract a struct-like type key, enum-like, or array-like // type key, for expansion E_TypeKey expand_type_key = e_default_expansion_type_from_key(eval.irtree.type_key); //- rjf: struct type? -> use the struct type for expansion B32 did_expansion = 0; if(!did_expansion) { E_TypeKind struct_type_kind = e_type_kind_from_key(expand_type_key); if(struct_type_kind == E_TypeKind_Struct || struct_type_kind == E_TypeKind_Class || struct_type_kind == E_TypeKind_Union) { E_MemberArray data_members = e_type_data_members_from_key_filter__cached(expand_type_key, filter); result.expr_count = data_members.count; did_expansion = 1; } } //- rjf: array-like type? -> use the array-like for expansion if(!did_expansion) { E_TypeKind array_type_kind = e_type_kind_from_key(expand_type_key); if(array_type_kind == E_TypeKind_Array || array_type_kind == E_TypeKind_Ptr || array_type_kind == E_TypeKind_RRef || array_type_kind == E_TypeKind_LRef) { E_Type *array_type = e_type_from_key(expand_type_key); result.expr_count = array_type->count; did_expansion = 1; } } //- rjf: enum-like type? -> use the enum-like for expansion if(!did_expansion) { E_TypeKind enum_type_kind = e_type_kind_from_key(expand_type_key); if(enum_type_kind == E_TypeKind_Enum) { E_EnumValArray enum_vals = e_type_enum_vals_from_key_filter__cached(expand_type_key, filter); result.expr_count = enum_vals.count; did_expansion = 1; } } } return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default) { Temp scratch = scratch_begin(&arena, 1); { //- rjf: try to extract a struct-like type key, enum-like, or array-like // type key, for expansion E_TypeKey expand_type_key = e_default_expansion_type_from_key(eval.irtree.type_key); E_TypeKind expand_type_kind = e_type_kind_from_key(expand_type_key); //- rjf: struct case -> the lookup-range will return a range of members if(expand_type_kind == E_TypeKind_Struct || expand_type_kind == E_TypeKind_Class || expand_type_kind == E_TypeKind_Union) { E_MemberArray data_members = e_type_data_members_from_key_filter__cached(expand_type_key, filter); Rng1U64 legal_idx_range = r1u64(0, data_members.count); Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { U64 member_idx = idx + read_range.min; String8 member_name = data_members.v[member_idx].name; evals_out[idx] = e_eval_wrapf(eval, "$.%S", member_name); } } //- rjf: enum case -> the lookup-range will return a range of enum constants else if(expand_type_kind == E_TypeKind_Enum) { E_Type *type = e_type_from_key(expand_type_key); E_EnumValArray enum_vals = e_type_enum_vals_from_key_filter__cached(expand_type_key, filter); Rng1U64 legal_idx_range = r1u64(0, enum_vals.count); Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { U64 val_idx = idx + read_range.min; String8 member_name = enum_vals.v[val_idx].name; String8 sufficient_suffix = member_name; if(str8_match(sufficient_suffix, type->name, StringMatchFlag_RightSideSloppy)) { sufficient_suffix = str8_skip(sufficient_suffix, type->name.size); if(str8_match(sufficient_suffix, str8_lit("_"), StringMatchFlag_RightSideSloppy)) { sufficient_suffix = str8_skip(sufficient_suffix, 1); } } evals_out[idx] = e_eval_wrapf(eval, "$.%S", sufficient_suffix); } } //- rjf: ptr case -> the lookup-range will return a range of dereferences else if(expand_type_kind == E_TypeKind_Ptr || expand_type_kind == E_TypeKind_LRef || expand_type_kind == E_TypeKind_RRef || expand_type_kind == E_TypeKind_Array || expand_type_kind == E_TypeKind_Set) { U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", idx_range.min + idx); } } } scratch_end(scratch); } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity) { return num; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity) { return id; } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `rows` lens typedef struct E_RowsAccel E_RowsAccel; struct E_RowsAccel { E_Eval *root_evals; Rng1U64 *root_evals_ranges; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(rows) { E_Type *type = e_type_from_key(eval.irtree.type_key); E_RowsAccel *accel = push_array(arena, E_RowsAccel, 1); accel->root_evals = push_array(arena, E_Eval, type->count); accel->root_evals_ranges = push_array(arena, Rng1U64, type->count); E_ParentKey(eval.key) { for EachIndex(idx, type->count) { accel->root_evals[idx] = e_eval_from_expr(type->args[idx]); accel->root_evals_ranges[idx] = r1u64(idx, idx+1); } } E_TypeExpandInfo info = {accel, type->count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(rows) { E_RowsAccel *accel = (E_RowsAccel *)user_data; U64 out_idx = 0; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { evals_out[out_idx] = accel->root_evals[idx]; } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `omit` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(omit) { E_Type *type = e_type_from_key(eval.irtree.type_key); String8Array allowed_children_array = {0}; { Temp scratch = scratch_begin(&arena, 1); String8List allowed_children = {0}; { E_Eval eval_stripped = e_eval_wrapf(eval, "q:raw($)"); E_TypeExpandRule *expand_rule = e_expand_rule_from_type_key(eval_stripped.irtree.type_key); E_TypeExpandInfo expand_info = expand_rule->info(scratch.arena, eval_stripped, filter); if(expand_info.expr_count < 4096) { E_Eval *evals = push_array(scratch.arena, E_Eval, expand_info.expr_count); for EachIndex(idx, expand_info.expr_count) { evals[idx] = e_eval_nil; } expand_rule->range(scratch.arena, expand_info.user_data, eval_stripped, filter, r1u64(0, expand_info.expr_count), evals); for EachIndex(idx, expand_info.expr_count) { if(evals[idx].expr->kind == E_ExprKind_MemberAccess) { String8 name = evals[idx].expr->first->next->string; B32 name_is_allowed = 1; for EachIndex(arg_idx, type->count) { if(str8_match(type->args[arg_idx]->string, name, 0)) { name_is_allowed = 0; break; } } if(name_is_allowed) { str8_list_push(scratch.arena, &allowed_children, push_str8_copy(arena, name)); } } } } } allowed_children_array = str8_array_from_list(arena, &allowed_children); scratch_end(scratch); } String8Array *ext = push_array(arena, String8Array, 1); *ext = allowed_children_array; E_TypeExpandInfo info = {ext, ext->count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(omit) { String8Array *ext = (String8Array *)user_data; U64 out_idx = 0; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { String8 name = ext->v[idx]; if(name.size != 0) { evals_out[out_idx] = e_eval_wrapf(eval, "$.%S", name); } } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `sequence` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(sequence) { E_TypeExpandInfo info = {0, e_value_eval_from_eval(eval).value.u64}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(sequence) { U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { evals_out[idx] = e_eval_from_stringf("%I64u", idx_range.min + idx); } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `array` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(array) { E_Type *type = e_type_from_key(eval.irtree.type_key); U64 count = 1; if(type->args != 0 && type->count > 0) E_ParentKey(eval.key) { E_Key count_key = e_key_from_expr(type->args[0]); E_Value count_value = e_value_from_key(count_key); count = count_value.u64; } E_TypeExpandInfo info = {0, count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array) { U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", idx_range.min + idx); } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `list` lens internal AC_Artifact e_list_gather_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { Temp scratch = scratch_begin(0, 0); //- rjf: unpack key // TODO(rjf): this needs to take any `E_Space`, once eval has been upgraded. CTRL_Handle process = {0}; U64 base_off = 0; U64 member_element_off = 0; U64 member_size = 0; E_SpaceRWFunction *space_read = 0; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &process); key_read_off += str8_deserial_read_struct(key, key_read_off, &base_off); key_read_off += str8_deserial_read_struct(key, key_read_off, &member_element_off); key_read_off += str8_deserial_read_struct(key, key_read_off, &member_size); key_read_off += str8_deserial_read_struct(key, key_read_off, &space_read); } //- rjf: gather chain typedef struct HitOffsetNode HitOffsetNode; struct HitOffsetNode { HitOffsetNode *next; U64 off; }; typedef struct OffsetChunk OffsetChunk; struct OffsetChunk { OffsetChunk *next; U64 *v; U64 count; U64 cap; }; OffsetChunk *first_chunk = 0; OffsetChunk *last_chunk = 0; U64 total_count = 0; B32 retry = 0; { U64 hit_slots_count = 4096; HitOffsetNode **hit_slots = push_array(scratch.arena, HitOffsetNode *, hit_slots_count); for(U64 off = base_off, next_off = 0;; off = next_off) { //- rjf: see if we've cycled B32 hit_cycle = 0; { U64 hash = u64_hash_from_str8(str8_struct(&off)); U64 slot_idx = hash%hit_slots_count; for(HitOffsetNode *n = hit_slots[slot_idx]; n != 0; n = n->next) { if(n->off == off) { hit_cycle = 1; break; } } } //- rjf: terminate loop B32 terminated = (hit_cycle || off == 0); if(terminated) { break; } //- rjf: another node -> push offset to chunk list OffsetChunk *chunk = last_chunk; if(chunk == 0 || chunk->count >= chunk->cap) { chunk = push_array(scratch.arena, OffsetChunk, 1); SLLQueuePush(first_chunk, last_chunk, chunk); chunk->cap = 1024; chunk->v = push_array_no_zero(scratch.arena, U64, chunk->cap); } chunk->v[chunk->count] = off; chunk->count += 1; total_count += 1; //- rjf: record this offset in our hit-offset table { U64 hash = u64_hash_from_str8(str8_struct(&off)); U64 slot_idx = hash%hit_slots_count; HitOffsetNode *n = push_array(scratch.arena, HitOffsetNode, 1); n->off = off; SLLStackPush(hit_slots[slot_idx], n); } //- rjf: read next offset, advance B32 read_stale = 0; B32 read_good = ctrl_process_memory_read(process, r1u64(off + member_element_off, off + member_element_off + member_size), &read_stale, &next_off, 0); if(read_stale) { retry = 1; } if(!read_good) { break; } } } //- rjf: retry if(retry) { retry_out[0] = 1; } //- rjf: flatten Arena *arena = 0; U64 node_offs_count = 0; U64 *node_offs = 0; if(!retry && total_count != 0) { arena = arena_alloc(); node_offs_count = total_count; node_offs = push_array_no_zero(arena, U64, node_offs_count); { U64 idx = 0; for EachNode(n, OffsetChunk, first_chunk) { MemoryCopy(node_offs + idx, n->v, n->count * sizeof(n->v[0])); idx += n->count; } } } //- rjf: package AC_Artifact artifact = {0}; { artifact.u64[0] = (U64)arena; artifact.u64[1] = (U64)node_offs; artifact.u64[2] = node_offs_count; } scratch_end(scratch); return artifact; } internal void e_list_gather_artifact_destroy(AC_Artifact artifact) { Arena *arena = (Arena *)artifact.u64[0]; if(arena != 0) { arena_release(arena); } } typedef struct E_ListIRExt E_ListIRExt; struct E_ListIRExt { U64 *offs; U64 offs_count; }; E_TYPE_IREXT_FUNCTION_DEF(list) { E_IRExt result = {0}; E_Type *type = e_type_from_key(irtree->type_key); //- rjf: get member encoding the link to the next node E_Member next_link_member = {0}; { E_TypeKey node_type_key = e_type_key_unwrap(irtree->type_key, E_TypeUnwrapFlag_All); // rjf: try explicitly-passed name if(next_link_member.kind == E_MemberKind_Null && type->args != 0 && type->count > 0 && type->args[0]->kind == E_ExprKind_LeafIdentifier) { String8 name = type->args[0]->string; next_link_member = e_type_member_from_key_name__cached(node_type_key, name); } // rjf: try `next` if(next_link_member.kind == E_MemberKind_Null) { next_link_member = e_type_member_from_key_name__cached(node_type_key, str8_lit("next")); } // rjf: try `prev` if(next_link_member.kind == E_MemberKind_Null) { next_link_member = e_type_member_from_key_name__cached(node_type_key, str8_lit("prev")); } // rjf: try any pointer to the same type if(next_link_member.kind == E_MemberKind_Null) { E_Type *node_type = e_type_from_key(node_type_key); if(node_type->members != 0) { for EachIndex(idx, node_type->count) { if(node_type->members[idx].kind != E_MemberKind_DataField) { continue; } E_TypeKey member_type_key = node_type->members[idx].type_key; E_TypeKey member_type_key_undecorated = e_type_key_unwrap(member_type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey member_ptee_type_key = e_type_key_unwrap(member_type_key_undecorated, E_TypeUnwrapFlag_All); if(e_type_kind_from_key(member_type_key_undecorated) == E_TypeKind_Ptr && e_type_key_match(member_ptee_type_key, node_type_key)) { next_link_member = node_type->members[idx]; break; } } } } } //- rjf: generate expansion info E_TypeExpandInfo info = {0, 0}; if(next_link_member.kind != E_MemberKind_DataField) { // TODO(rjf): error reporting } else { Temp scratch = scratch_begin(&arena, 1); Access *access = access_open(); // rjf: evaluate first offset E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation base_off_interpret = e_interpret(bytecode); // rjf: get artifact #pragma pack(push, 1) struct { CTRL_Handle process; U64 base_off; U64 member_element_off; U64 member_size; E_SpaceRWFunction *space_read; } key_data = { // TODO(rjf): we cannot use `rd_` here - only doing this because the base eval layer does not // support what we need yet... rd_ctrl_entity_from_eval_space(base_off_interpret.space)->handle, base_off_interpret.value.u64, next_link_member.off, e_type_byte_size_from_key(next_link_member.type_key), e_base_ctx->space_read, }; #pragma pack(pop) AC_Artifact gather_artifact = ac_artifact_from_key(access, str8_struct(&key_data), e_list_gather_artifact_create, e_list_gather_artifact_destroy, 0, .gen = e_space_gen(base_off_interpret.space)); U64 *offs = (U64 *)gather_artifact.u64[1]; U64 offs_count = gather_artifact.u64[2]; // rjf: fill info from artifact E_ListIRExt *ext = push_array(arena, E_ListIRExt, 1); ext->offs = offs; ext->offs_count = offs_count; result.user_data = ext; access_close(access); scratch_end(scratch); } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(list) { E_ListIRExt *ext = (E_ListIRExt *)eval.irtree.user_data; U64 count = 0; if(ext != 0) { count = ext->offs_count; } E_TypeExpandInfo info = {0, count}; return info; } E_TYPE_ACCESS_FUNCTION_DEF(list) { E_IRTreeAndType result = {&e_irnode_nil}; E_ListIRExt *ext = (E_ListIRExt *)lhs_irtree->user_data; if(ext != 0 && expr->kind == E_ExprKind_ArrayIndex) { Temp scratch = scratch_begin(&arena, 1); // rjf: compute index E_Expr *rhs_expr = expr->last; E_IRTreeAndType rhs_irtree = e_push_irtree_and_type_from_expr(scratch.arena, overridden, &e_default_identifier_resolution_rule, 0, 0, rhs_expr); E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); E_Interpretation rhs_interpret = e_interpret(rhs_bytecode); U64 idx = rhs_interpret.value.u64; // rjf: get offset U64 off = 0; if(idx < ext->offs_count) { off = ext->offs[idx]; } // rjf: generate IR tree to compute this offset w/ the node type result.root = e_irtree_const_u(arena, off); result.type_key = e_type_key_unwrap(lhs_irtree->type_key, E_TypeUnwrapFlag_AllDecorative); result.mode = E_Mode_Offset; scratch_end(scratch); } return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(list) { U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", idx_range.min + idx); } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `slice` lens typedef struct E_SliceIRExt E_SliceIRExt; struct E_SliceIRExt { E_Member *base_ptr_member; E_Member *opl_ptr_member; E_Member *count_member; }; typedef struct E_SliceAccel E_SliceAccel; struct E_SliceAccel { Arch arch; U64 count; U64 base_ptr_vaddr; E_TypeKey element_type_key; }; E_TYPE_IREXT_FUNCTION_DEF(slice) { E_SliceIRExt *ext = push_array(arena, E_SliceIRExt, 1); { Temp scratch = scratch_begin(&arena, 1); // rjf: build info from struct type E_TypeKey struct_type_key = e_type_key_unwrap(irtree->type_key, E_TypeUnwrapFlag_All); E_TypeKind type_kind = e_type_kind_from_key(struct_type_key); if(type_kind == E_TypeKind_Struct || type_kind == E_TypeKind_Class) { // rjf: unpack members E_MemberArray members = e_type_data_members_from_key__cached(struct_type_key); // rjf: choose base pointer & count members E_Member *base_ptr_member = 0; E_Member *opl_ptr_member = 0; E_Member *count_member = 0; for(U64 idx = 0; idx < members.count; idx += 1) { E_Member *member = &members.v[idx]; E_TypeKey member_type = e_type_key_unwrap(member->type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind member_type_kind = e_type_kind_from_key(member_type); if(count_member == 0 && e_type_kind_is_integer(member_type_kind)) { count_member = member; } if(base_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind)) { base_ptr_member = &members.v[idx]; } else if(base_ptr_member != 0 && opl_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind)) { opl_ptr_member = &members.v[idx]; } if(count_member != 0 && base_ptr_member != 0) { break; } else if(base_ptr_member != 0 && opl_ptr_member != 0) { break; } } // rjf: fill extension ext->base_ptr_member = base_ptr_member; ext->opl_ptr_member = opl_ptr_member; ext->count_member = count_member; } scratch_end(scratch); } E_IRExt result = {ext}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(slice) { E_IRTreeAndType result = {&e_irnode_nil}; E_SliceIRExt *ext = (E_SliceIRExt *)lhs_irtree->user_data; switch(expr->kind) { default: case E_ExprKind_MemberAccess: { result = E_TYPE_ACCESS_FUNCTION_NAME(default)(arena, overridden, expr, lhs_irtree); }break; case E_ExprKind_ArrayIndex: if(ext->base_ptr_member != 0) { Temp scratch = scratch_begin(&arena, 1); U64 addr_size = e_type_byte_size_from_key(ext->base_ptr_member->type_key); // rjf: compute ir tree for struct base E_IRNode *struct_base_tree = &e_irnode_nil; { E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree->root); String8 lhs_bytecode = e_bytecode_from_oplist(arena, &lhs_oplist); struct_base_tree = e_irtree_bytecode_no_copy(arena, lhs_bytecode); if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(lhs_irtree->type_key, E_TypeUnwrapFlag_AllDecorative)))) { struct_base_tree = e_irtree_resolve_to_value(arena, lhs_irtree->mode, lhs_irtree->root, lhs_irtree->type_key); } } // rjf: compute ir tree for base pointer value calculation E_IRNode *base_ptr_tree = &e_irnode_nil; if(struct_base_tree != &e_irnode_nil) { base_ptr_tree = struct_base_tree; if(ext->base_ptr_member->off != 0) { base_ptr_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, addr_size, struct_base_tree, e_irtree_const_u(arena, ext->base_ptr_member->off)); } base_ptr_tree = e_irtree_mem_read_type(arena, base_ptr_tree, ext->base_ptr_member->type_key); } // rjf: compute ir tree for adding to the base ptr member E_IRNode *idxed_base_tree = &e_irnode_nil; if(base_ptr_tree != &e_irnode_nil) { E_IRTreeAndType idx_irtree = e_push_irtree_and_type_from_expr(arena, 0, &e_default_identifier_resolution_rule, 0, 1, expr->first->next); E_IRNode *idx_root = e_irtree_resolve_to_value(arena, idx_irtree.mode, idx_irtree.root, idx_irtree.type_key); E_IRNode *off_root = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, addr_size, idx_root, e_irtree_const_u(arena, e_type_byte_size_from_key(e_type_key_unwrap(ext->base_ptr_member->type_key, E_TypeUnwrapFlag_All)))); idxed_base_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Add, addr_size, base_ptr_tree, off_root); } // rjf: form final result result.root = idxed_base_tree; result.type_key = e_type_key_unwrap(ext->base_ptr_member->type_key, E_TypeUnwrapFlag_All); result.mode = E_Mode_Offset; scratch_end(scratch); }break; } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(slice) { E_SliceIRExt *accel = (E_SliceIRExt *)eval.irtree.user_data; U64 count = 0; { if(accel->count_member != 0) { count = e_value_eval_from_eval(e_eval_wrapf(eval, "$.%S", accel->count_member->name)).value.u64; } else if(accel->opl_ptr_member != 0 && accel->base_ptr_member != 0) { count = e_value_eval_from_eval(e_eval_wrapf(eval, "raw($.%S) - raw($.%S)", accel->opl_ptr_member->name, accel->base_ptr_member->name)).value.u64; } } E_TypeExpandInfo info = {0, count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(slice) { U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", idx_range.min + idx); } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `folder` type typedef struct E_FolderAccel E_FolderAccel; struct E_FolderAccel { String8 folder_path; String8Array folders; String8Array files; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder) { E_TypeExpandInfo info = {0}; { Temp scratch = scratch_begin(&arena, 1); //- rjf: evaluate lhs file path ID U64 lhs_string_id = eval.value.u64; String8 folder_path = e_string_from_id(lhs_string_id); //- rjf: compute filter - omit common prefixes (common parent paths) String8 local_filter = filter; { U64 folder_pos_in_filter = str8_find_needle(filter, 0, folder_path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); if(folder_pos_in_filter < filter.size) { local_filter = str8_skip(local_filter, folder_pos_in_filter+folder_path.size); local_filter = str8_skip_chop_slashes(local_filter); } else { MemoryZeroStruct(&local_filter); } } //- rjf: gather & filter files in this folder String8List folder_paths = {0}; String8List file_paths = {0}; { OS_FileIter *iter = os_file_iter_begin(scratch.arena, folder_path, 0); for(OS_FileInfo info = {0}; os_file_iter_next(scratch.arena, iter, &info);) { FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, local_filter, info.name); if(matches.count == matches.needle_part_count) { if(info.props.flags & FilePropertyFlag_IsFolder) { str8_list_push(scratch.arena, &folder_paths, push_str8_copy(arena, info.name)); } else { str8_list_push(scratch.arena, &file_paths, push_str8_copy(arena, info.name)); } } } os_file_iter_end(iter); } //- rjf: build accelerator E_FolderAccel *accel = push_array(arena, E_FolderAccel, 1); accel->folder_path = push_str8_copy(arena, folder_path); accel->folders = str8_array_from_list(arena, &folder_paths); accel->files = str8_array_from_list(arena, &file_paths); info.user_data = accel; info.expr_count = accel->folders.count + accel->files.count; scratch_end(scratch); } return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(folder) { E_FolderAccel *accel = (E_FolderAccel *)user_data; U64 out_idx = 0; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { Temp scratch = scratch_begin(&arena, 1); String8 path_expr_string = {0}; if(0 <= idx && idx < accel->folders.count) { String8 folder_name = accel->folders.v[idx - 0]; String8 folder_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", folder_name); path_expr_string = push_str8f(arena, "folder:\"%S/\"", escaped_from_raw_str8(scratch.arena, folder_path)); } else if(accel->folders.count <= idx && idx < accel->folders.count + accel->files.count) { String8 file_name = accel->files.v[idx - accel->folders.count]; String8 file_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", file_name); path_expr_string = push_str8f(arena, "file:\"%S\"", escaped_from_raw_str8(scratch.arena, file_path)); } evals_out[out_idx] = e_eval_from_string(path_expr_string); scratch_end(scratch); } } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(folder) { U64 id = 0; E_FolderAccel *accel = (E_FolderAccel *)user_data; String8 name = {0}; if(0 < num && num <= accel->folders.count) { name = accel->folders.v[num-1]; } else if(accel->folders.count < num && num <= accel->folders.count+accel->files.count) { name = accel->files.v[num-accel->folders.count-1]; } id = e_hash_from_string(5381, name); return id; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(folder) { U64 num = 0; E_FolderAccel *accel = (E_FolderAccel *)user_data; for(U64 idx = 0; idx < accel->folders.count+accel->files.count; idx += 1) { String8 name = {0}; if(0 <= idx && idx < accel->folders.count) { name = accel->folders.v[idx]; } else if(accel->folders.count <= idx && idx < accel->folders.count+accel->files.count) { name = accel->files.v[idx-accel->folders.count]; } U64 hash = e_hash_from_string(5381, name); if(hash == id) { num = idx+1; break; } } return num; } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `file` type typedef struct E_FileAccel E_FileAccel; struct E_FileAccel { String8 file_path; FileProperties props; String8Array fields; }; E_TYPE_IREXT_FUNCTION_DEF(file) { E_IRTreeAndType result = *irtree; E_FileAccel *accel = push_array(arena, E_FileAccel, 1); { Temp scratch = scratch_begin(&arena, 1); //- rjf: evaluate lhs file path ID E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); E_Interpretation lhs_interp = e_interpret(lhs_bytecode); E_Value lhs_value = lhs_interp.value; U64 lhs_string_id = lhs_value.u64; //- rjf: get file path String8 file_path = e_string_from_id(lhs_string_id); //- rjf: build field list String8List fields = {0}; str8_list_pushf(arena, &fields, "size"); str8_list_pushf(arena, &fields, "last_modified_time"); str8_list_pushf(arena, &fields, "creation_time"); str8_list_pushf(arena, &fields, "data"); //- rjf: fill accel accel->file_path = push_str8_copy(arena, file_path); accel->props = os_properties_from_file_path(file_path); accel->fields = str8_array_from_list(arena, &fields); scratch_end(scratch); } E_IRExt ext = {accel}; return ext; } E_TYPE_ACCESS_FUNCTION_DEF(file) { E_IRTreeAndType result = {&e_irnode_nil}; E_FileAccel *accel = (E_FileAccel *)lhs_irtree->user_data; if(expr->kind == E_ExprKind_MemberAccess) { E_Expr *rhs = expr->first->next; String8 member_name = rhs->string; if(str8_match(member_name, str8_lit("size"), 0)) { E_Space space = e_space_make(E_SpaceKind_FileSystem); space.u64_0 = e_id_from_string(accel->file_path); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.size)); result.type_key = e_type_key_basic(E_TypeKind_U64); result.mode = E_Mode_Value; } else if(str8_match(member_name, str8_lit("last_modified_time"), 0)) { E_Space space = e_space_make(E_SpaceKind_FileSystem); space.u64_0 = e_id_from_string(accel->file_path); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.modified)); result.type_key = e_type_key_basic(E_TypeKind_U64); result.mode = E_Mode_Value; } else if(str8_match(member_name, str8_lit("creation_time"), 0)) { E_Space space = e_space_make(E_SpaceKind_FileSystem); space.u64_0 = e_id_from_string(accel->file_path); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.created)); result.type_key = e_type_key_basic(E_TypeKind_U64); result.mode = E_Mode_Value; } else if(str8_match(member_name, str8_lit("data"), 0)) { E_Space space = e_space_make(E_SpaceKind_File); space.u64_0 = e_id_from_string(accel->file_path); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), accel->props.size, 0); result.mode = E_Mode_Offset; } } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(file) { E_FileAccel *accel = (E_FileAccel *)eval.irtree.user_data; E_TypeExpandInfo info = {accel, accel->fields.count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(file) { E_FileAccel *accel = (E_FileAccel *)user_data; U64 out_idx = 0; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { E_Expr *expr = &e_expr_nil; String8 string = {0}; if(0 <= idx && idx < accel->fields.count) { String8 name = accel->fields.v[idx]; evals_out[out_idx] = e_eval_wrapf(eval, "$.%S", name); } } } ================================================ FILE: src/eval/eval_types.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_TYPES_H #define EVAL_TYPES_H //////////////////////////////// //~ rjf: Type Unwrapping typedef U32 E_TypeUnwrapFlags; enum { E_TypeUnwrapFlag_Modifiers = (1<<0), E_TypeUnwrapFlag_Pointers = (1<<1), E_TypeUnwrapFlag_Lenses = (1<<2), E_TypeUnwrapFlag_Meta = (1<<3), E_TypeUnwrapFlag_Enums = (1<<4), E_TypeUnwrapFlag_Aliases = (1<<5), E_TypeUnwrapFlag_Bitfields = (1<<6), E_TypeUnwrapFlag_All = 0xffffffff, E_TypeUnwrapFlag_AllDecorative = (E_TypeUnwrapFlag_All & ~(E_TypeUnwrapFlag_Pointers|E_TypeUnwrapFlag_Bitfields)) }; //////////////////////////////// //~ rjf: Globals global read_only E_Member e_member_nil = {E_MemberKind_Null}; global read_only E_Type e_type_nil = {E_TypeKind_Null}; E_TYPE_EXPAND_INFO_FUNCTION_DEF(default); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity); global read_only E_TypeExpandRule e_type_expand_rule__default = { E_TYPE_EXPAND_INFO_FUNCTION_NAME(default), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(default), E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity), }; //////////////////////////////// //~ rjf: Type Kind Enum Functions internal E_TypeKind e_type_kind_from_base(TypeKind kind); internal E_TypeKind e_type_kind_from_rdi(RDI_TypeKind kind); internal E_MemberKind e_member_kind_from_rdi(RDI_MemberKind kind); internal RDI_EvalTypeGroup e_type_group_from_kind(E_TypeKind kind); internal B32 e_type_kind_is_integer(E_TypeKind kind); internal B32 e_type_kind_is_signed(E_TypeKind kind); internal B32 e_type_kind_is_basic_or_enum(E_TypeKind kind); internal B32 e_type_kind_is_pointer_or_ref(E_TypeKind kind); //////////////////////////////// //~ rjf: Member Functions internal void e_member_list_push(Arena *arena, E_MemberList *list, E_Member *member); #define e_member_list_push_new(arena, list, ...) e_member_list_push((arena), (list), &(E_Member){.kind = E_MemberKind_DataField, __VA_ARGS__}) internal E_MemberArray e_member_array_from_list(Arena *arena, E_MemberList *list); //////////////////////////////// //~ rjf: Enum Value Functions internal void e_enum_val_list_push(Arena *arena, E_EnumValList *list, E_EnumVal *enum_val); #define e_enum_val_list_push_new(arena, list, ...) e_enum_val_list_push((arena), (list), &(E_EnumVal){.val = 0, __VA_ARGS__}) internal E_EnumValArray e_enum_val_array_from_list(Arena *arena, E_EnumValList *list); //////////////////////////////// //~ rjf: Type Operation Functions //- rjf: basic key constructors internal E_TypeKey e_type_key_zero(void); internal E_TypeKey e_type_key_basic(E_TypeKind kind); internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num); internal E_TypeKey e_type_key_reg(Arch arch, REGS_RegCode code); internal E_TypeKey e_type_key_reg_alias(Arch arch, REGS_AliasCode code); //- rjf: constructed type construction internal U64 e_hash_from_cons_type_params(E_ConsTypeParams *params); internal B32 e_cons_type_params_match(E_ConsTypeParams *l, E_ConsTypeParams *r); internal E_TypeKey e_type_key_cons_(E_ConsTypeParams *params); #define e_type_key_cons(...) e_type_key_cons_(&(E_ConsTypeParams){.kind = E_TypeKind_Null, __VA_ARGS__}) //- rjf: constructed type construction helpers internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count, E_TypeFlags flags); internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags); internal E_TypeKey e_type_key_cons_meta_expr(E_TypeKey type_key, String8 expr); internal E_TypeKey e_type_key_cons_meta_display_name(E_TypeKey type_key, String8 name); internal E_TypeKey e_type_key_cons_meta_description(E_TypeKey type_key, String8 desc); internal E_TypeKey e_type_key_cons_base(Type *type); internal E_TypeKey e_type_key_file(void); internal E_TypeKey e_type_key_folder(void); //- rjf: basic type key functions internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r); //- rjf: type key -> info extraction internal U64 e_hash_from_type(E_Type *type); internal E_TypeKind e_type_kind_from_key(E_TypeKey key); internal U64 e_type_byte_size_from_key(E_TypeKey key); internal E_Type *e_push_type_from_key(Arena *arena, E_TypeKey key); internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b); internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key); internal E_TypeExpandRule *e_expand_rule_from_type_key(E_TypeKey key); //- rjf: type key traversal internal E_TypeKey e_type_key_direct(E_TypeKey key); internal E_TypeKey e_type_key_owner(E_TypeKey key); internal E_TypeKey e_type_key_promote(E_TypeKey key); internal E_TypeKey e_type_key_unwrap(E_TypeKey key, E_TypeUnwrapFlags flags); //- rjf: type comparisons internal B32 e_type_match(E_TypeKey l, E_TypeKey r); //- rjf: type key -> string internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return); internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec); internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key); internal E_TypeKey e_default_expansion_type_from_key(E_TypeKey key); //////////////////////////////// //~ rjf: Cache Lookups internal E_Type *e_type_from_key(E_TypeKey key); //- rjf: member lookups internal E_MemberCacheNode *e_member_cache_node_from_type_key(E_TypeKey key); internal E_MemberArray e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter); internal E_MemberArray e_type_data_members_from_key__cached(E_TypeKey key); internal E_Member e_type_member_from_key_name__cached(E_TypeKey key, String8 name); //- rjf: enum val lookups internal E_EnumValCacheNode *e_enum_val_cache_node_from_type_key(E_TypeKey key); internal E_EnumValArray e_type_enum_vals_from_key_filter__cached(E_TypeKey key, String8 filter); internal E_EnumValArray e_type_enum_vals_from_key__cached(E_TypeKey key); internal E_EnumVal e_type_enum_val_from_key_name__cached(E_TypeKey key, String8 name); //////////////////////////////// //~ rjf: (Built-In Type Hooks) Default Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(default); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `rows` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(rows); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(rows); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `sequence` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(sequence); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(sequence); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `array` lens E_TYPE_EXPAND_INFO_FUNCTION_DEF(array); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `slice` lens E_TYPE_IREXT_FUNCTION_DEF(slice); E_TYPE_ACCESS_FUNCTION_DEF(slice); E_TYPE_EXPAND_INFO_FUNCTION_DEF(slice); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(slice); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `only`, `omit` lenses E_TYPE_EXPAND_INFO_FUNCTION_DEF(only_and_omit); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(only_and_omit); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `folder` type E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(folder); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(folder); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(folder); //////////////////////////////// //~ rjf: (Built-In Type Hooks) `file` type E_TYPE_IREXT_FUNCTION_DEF(file); E_TYPE_ACCESS_FUNCTION_DEF(file); E_TYPE_EXPAND_INFO_FUNCTION_DEF(file); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(file); #endif // EVAL_TYPES_H ================================================ FILE: src/eval/generated/eval.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 e_token_kind_strings[6] = { str8_lit_comp("Null"), str8_lit_comp("Identifier"), str8_lit_comp("Numeric"), str8_lit_comp("StringLiteral"), str8_lit_comp("CharLiteral"), str8_lit_comp("Symbol"), }; String8 e_type_kind_basic_string_table[61] = { str8_lit_comp(""), str8_lit_comp("void"), str8_lit_comp("HANDLE"), str8_lit_comp("HRESULT"), str8_lit_comp("char8"), str8_lit_comp("char16"), str8_lit_comp("char32"), str8_lit_comp("uchar8"), str8_lit_comp("uchar16"), str8_lit_comp("uchar32"), str8_lit_comp("uint8"), str8_lit_comp("uint16"), str8_lit_comp("uint32"), str8_lit_comp("uint64"), str8_lit_comp("uint128"), str8_lit_comp("uint256"), str8_lit_comp("uint512"), str8_lit_comp("int8"), str8_lit_comp("int16"), str8_lit_comp("int32"), str8_lit_comp("int64"), str8_lit_comp("int128"), str8_lit_comp("int256"), str8_lit_comp("int512"), str8_lit_comp("bool"), str8_lit_comp("float16"), str8_lit_comp("float32"), str8_lit_comp("float32PP"), str8_lit_comp("float48"), str8_lit_comp("float64"), str8_lit_comp("float80"), str8_lit_comp("float128"), str8_lit_comp("complex_float32"), str8_lit_comp("complex_float64"), str8_lit_comp("complex_float80"), str8_lit_comp("complex_float128"), str8_lit_comp("modifier"), str8_lit_comp("ptr"), str8_lit_comp("lref"), str8_lit_comp("rref"), str8_lit_comp("array"), str8_lit_comp("function"), str8_lit_comp("method"), str8_lit_comp("member_ptr"), str8_lit_comp("struct"), str8_lit_comp("class"), str8_lit_comp("union"), str8_lit_comp("enum"), str8_lit_comp("typedef"), str8_lit_comp("struct"), str8_lit_comp("union"), str8_lit_comp("class"), str8_lit_comp("enum"), str8_lit_comp("bitfield"), str8_lit_comp("variadic"), str8_lit_comp("set"), str8_lit_comp("lens"), str8_lit_comp("lens_spec"), str8_lit_comp("meta_expr"), str8_lit_comp("meta_display_name"), str8_lit_comp("meta_description"), }; U8 e_type_kind_basic_byte_size_table[61] = { 0, 0, 0xFF, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 8, 16, 32, 64, 1, 2, 4, 8, 16, 32, 64, 1, 2, 4, 4, 6, 8, 10, 16, 8, 16, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; String8 e_expr_kind_strings[50] = { str8_lit_comp("Nil"), str8_lit_comp("Ref"), str8_lit_comp("ArrayIndex"), str8_lit_comp("MemberAccess"), str8_lit_comp("Deref"), str8_lit_comp("Address"), str8_lit_comp("Cast"), str8_lit_comp("Sizeof"), str8_lit_comp("Typeof"), str8_lit_comp("Symbolof"), str8_lit_comp("ByteSwap"), str8_lit_comp("Pos"), str8_lit_comp("Neg"), str8_lit_comp("LogNot"), str8_lit_comp("BitNot"), str8_lit_comp("Mul"), str8_lit_comp("Div"), str8_lit_comp("Mod"), str8_lit_comp("Add"), str8_lit_comp("Sub"), str8_lit_comp("LShift"), str8_lit_comp("RShift"), str8_lit_comp("Less"), str8_lit_comp("LsEq"), str8_lit_comp("Grtr"), str8_lit_comp("GrEq"), str8_lit_comp("EqEq"), str8_lit_comp("NtEq"), str8_lit_comp("BitAnd"), str8_lit_comp("BitXor"), str8_lit_comp("BitOr"), str8_lit_comp("LogAnd"), str8_lit_comp("LogOr"), str8_lit_comp("Ternary"), str8_lit_comp("Call"), str8_lit_comp("LeafBytecode"), str8_lit_comp("LeafStringLiteral"), str8_lit_comp("LeafU64"), str8_lit_comp("LeafF64"), str8_lit_comp("LeafF32"), str8_lit_comp("LeafIdentifier"), str8_lit_comp("LeafOffset"), str8_lit_comp("LeafValue"), str8_lit_comp("LeafFilePath"), str8_lit_comp("TypeIdent"), str8_lit_comp("Ptr"), str8_lit_comp("Array"), str8_lit_comp("Func"), str8_lit_comp("Unsigned"), str8_lit_comp("Define"), }; E_OpInfo e_expr_kind_op_info_table[50] = { { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("&"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 1, str8_lit_comp("cast("), str8_lit_comp(")"), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 1, str8_lit_comp("sizeof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 1, str8_lit_comp("typeof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 1, str8_lit_comp("symbolof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 1, str8_lit_comp("bswap "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("+"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("-"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("!"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_UnaryPrefix, 2, str8_lit_comp("~"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" * "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" / "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" % "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp(" + "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp(" - "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(" << "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(" >> "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" < "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" <= "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" > "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" >= "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp(" == "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp(" != "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 8, str8_lit_comp(""), str8_lit_comp(" & "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 9, str8_lit_comp(""), str8_lit_comp(" ^ "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 10, str8_lit_comp(""), str8_lit_comp(" | "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp(" && "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp(" || "), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(" ? "), str8_lit_comp(""), str8_lit_comp(" : ") }, { E_OpKind_Null, 15, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(", ") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Null, 0, str8_lit_comp("unsigned "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") }, { E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp(" = "), str8_lit_comp(""), str8_lit_comp("") }, }; String8 e_interpretation_code_display_strings[11] = { str8_lit_comp(""), str8_lit_comp("Cannot divide by zero."), str8_lit_comp("Invalid operation."), str8_lit_comp("Invalid operation types."), str8_lit_comp("Failed memory read."), str8_lit_comp("Failed register read."), str8_lit_comp("Invalid frame base address."), str8_lit_comp("Invalid module base address."), str8_lit_comp("Invalid thread-local storage base address."), str8_lit_comp("Insufficient evaluation machine stack space."), str8_lit_comp("Malformed bytecode."), }; C_LINKAGE_END ================================================ FILE: src/eval/generated/eval.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef EVAL_META_H #define EVAL_META_H typedef enum E_TokenKind { E_TokenKind_Null, E_TokenKind_Identifier, E_TokenKind_Numeric, E_TokenKind_StringLiteral, E_TokenKind_CharLiteral, E_TokenKind_Symbol, E_TokenKind_COUNT, } E_TokenKind; typedef enum E_TypeKind { E_TypeKind_Null, E_TypeKind_Void, E_TypeKind_Handle, E_TypeKind_HResult, E_TypeKind_Char8, E_TypeKind_Char16, E_TypeKind_Char32, E_TypeKind_UChar8, E_TypeKind_UChar16, E_TypeKind_UChar32, E_TypeKind_U8, E_TypeKind_U16, E_TypeKind_U32, E_TypeKind_U64, E_TypeKind_U128, E_TypeKind_U256, E_TypeKind_U512, E_TypeKind_S8, E_TypeKind_S16, E_TypeKind_S32, E_TypeKind_S64, E_TypeKind_S128, E_TypeKind_S256, E_TypeKind_S512, E_TypeKind_Bool, E_TypeKind_F16, E_TypeKind_F32, E_TypeKind_F32PP, E_TypeKind_F48, E_TypeKind_F64, E_TypeKind_F80, E_TypeKind_F128, E_TypeKind_ComplexF32, E_TypeKind_ComplexF64, E_TypeKind_ComplexF80, E_TypeKind_ComplexF128, E_TypeKind_Modifier, E_TypeKind_Ptr, E_TypeKind_LRef, E_TypeKind_RRef, E_TypeKind_Array, E_TypeKind_Function, E_TypeKind_Method, E_TypeKind_MemberPtr, E_TypeKind_Struct, E_TypeKind_Class, E_TypeKind_Union, E_TypeKind_Enum, E_TypeKind_Alias, E_TypeKind_IncompleteStruct, E_TypeKind_IncompleteUnion, E_TypeKind_IncompleteClass, E_TypeKind_IncompleteEnum, E_TypeKind_Bitfield, E_TypeKind_Variadic, E_TypeKind_Set, E_TypeKind_Lens, E_TypeKind_LensSpec, E_TypeKind_MetaExpr, E_TypeKind_MetaDisplayName, E_TypeKind_MetaDescription, E_TypeKind_COUNT, E_TypeKind_FirstBasic = E_TypeKind_Void, E_TypeKind_LastBasic = E_TypeKind_ComplexF128, E_TypeKind_FirstInteger = E_TypeKind_Char8, E_TypeKind_LastInteger = E_TypeKind_S512, E_TypeKind_FirstSigned1 = E_TypeKind_Char8, E_TypeKind_LastSigned1 = E_TypeKind_Char32, E_TypeKind_FirstSigned2 = E_TypeKind_S8, E_TypeKind_LastSigned2 = E_TypeKind_S512, E_TypeKind_FirstIncomplete = E_TypeKind_IncompleteStruct, E_TypeKind_LastIncomplete = E_TypeKind_IncompleteEnum, E_TypeKind_FirstMeta = E_TypeKind_MetaExpr, E_TypeKind_LastMeta = E_TypeKind_MetaDescription, } E_TypeKind; typedef U32 E_ExprKind; typedef enum E_ExprKindEnum { E_ExprKind_Nil, E_ExprKind_Ref, E_ExprKind_ArrayIndex, E_ExprKind_MemberAccess, E_ExprKind_Deref, E_ExprKind_Address, E_ExprKind_Cast, E_ExprKind_Sizeof, E_ExprKind_Typeof, E_ExprKind_Symbolof, E_ExprKind_ByteSwap, E_ExprKind_Pos, E_ExprKind_Neg, E_ExprKind_LogNot, E_ExprKind_BitNot, E_ExprKind_Mul, E_ExprKind_Div, E_ExprKind_Mod, E_ExprKind_Add, E_ExprKind_Sub, E_ExprKind_LShift, E_ExprKind_RShift, E_ExprKind_Less, E_ExprKind_LsEq, E_ExprKind_Grtr, E_ExprKind_GrEq, E_ExprKind_EqEq, E_ExprKind_NtEq, E_ExprKind_BitAnd, E_ExprKind_BitXor, E_ExprKind_BitOr, E_ExprKind_LogAnd, E_ExprKind_LogOr, E_ExprKind_Ternary, E_ExprKind_Call, E_ExprKind_LeafBytecode, E_ExprKind_LeafStringLiteral, E_ExprKind_LeafU64, E_ExprKind_LeafF64, E_ExprKind_LeafF32, E_ExprKind_LeafIdentifier, E_ExprKind_LeafOffset, E_ExprKind_LeafValue, E_ExprKind_LeafFilePath, E_ExprKind_TypeIdent, E_ExprKind_Ptr, E_ExprKind_Array, E_ExprKind_Func, E_ExprKind_Unsigned, E_ExprKind_Define, E_ExprKind_COUNT, } E_ExprKindEnum; typedef enum E_InterpretationCode { E_InterpretationCode_Good, E_InterpretationCode_DivideByZero, E_InterpretationCode_BadOp, E_InterpretationCode_BadOpTypes, E_InterpretationCode_BadMemRead, E_InterpretationCode_BadRegRead, E_InterpretationCode_BadFrameBase, E_InterpretationCode_BadModuleBase, E_InterpretationCode_BadTLSBase, E_InterpretationCode_InsufficientStackSpace, E_InterpretationCode_MalformedBytecode, E_InterpretationCode_COUNT, } E_InterpretationCode; C_LINKAGE_BEGIN extern String8 e_token_kind_strings[6]; extern String8 e_type_kind_basic_string_table[61]; extern U8 e_type_kind_basic_byte_size_table[61]; extern String8 e_expr_kind_strings[50]; extern E_OpInfo e_expr_kind_op_info_table[50]; extern String8 e_interpretation_code_display_strings[11]; C_LINKAGE_END #endif // EVAL_META_H ================================================ FILE: src/eval_visualization/eval_visualization_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Nil/Identity View Rule Hooks EV_EXPAND_RULE_INFO_FUNCTION_DEF(nil) { EV_ExpandInfo info = {0}; return info; } //////////////////////////////// //~ rjf: Key Functions #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal EV_Key ev_key_make(U64 parent_hash, U64 child_id) { EV_Key key; { key.parent_hash = parent_hash; key.child_id = child_id; } return key; } internal EV_Key ev_key_zero(void) { EV_Key key = {0}; return key; } internal EV_Key ev_key_root(void) { EV_Key key = ev_key_make(5381, 1); return key; } internal B32 ev_key_match(EV_Key a, EV_Key b) { B32 result = MemoryMatchStruct(&a, &b); return result; } internal U64 ev_hash_from_seed_string(U64 seed, String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); return result; } internal U64 ev_hash_from_key(EV_Key key) { U64 data[] = { key.child_id, }; U64 hash = ev_hash_from_seed_string(key.parent_hash, str8((U8 *)data, sizeof(data))); return hash; } //////////////////////////////// //~ rjf: Type Info Helpers //- rjf: type info -> expandability/editablity internal E_TypeKey ev_expansion_type_from_key(E_TypeKey type_key) { E_TypeKey result = zero_struct; for(E_TypeKey key = type_key; !e_type_key_match(key, e_type_key_zero()); key = e_type_key_direct(key)) { B32 done = 1; E_TypeKind kind = e_type_kind_from_key(key); //- rjf: lenses -> try to see if this lens has special expansion rules. if // so, choose the current eval if(kind == E_TypeKind_Lens) { E_Type *type = e_type_from_key(key); if(type->expand.info != 0 || ev_expand_rule_from_string(type->name) != &ev_nil_expand_rule) { done = 1; result = key; } else { done = 0; } } //- rjf: if we have meta-expression tags in the type chain, defer // to the next type in the chain. else if(E_TypeKind_FirstMeta <= kind && kind <= E_TypeKind_LastMeta) { done = 0; } //- rjf: break if done if(done) { break; } } return result; } internal B32 ev_type_key_and_mode_is_expandable(E_TypeKey type_key, E_Mode mode) { B32 result = 0; E_TypeKey ev_expansion_type_key = ev_expansion_type_from_key(type_key); if(!e_type_key_match(ev_expansion_type_key, e_type_key_zero())) { result = 1; } else { E_TypeKey default_expansion_type_key = e_default_expansion_type_from_key(type_key); E_TypeKind kind = e_type_kind_from_key(default_expansion_type_key); if(kind == E_TypeKind_Enum) { result = (mode == E_Mode_Null); } else if(kind != E_TypeKind_Null) { result = 1; } } return result; } internal B32 ev_type_key_is_editable(E_TypeKey type_key) { B32 result = 0; B32 done = 0; for(E_TypeKey t = type_key; !result && !done; t = e_type_key_direct(t)) { E_Type *type = e_type_from_key(t); E_TypeKind kind = type->kind; if(type->flags & E_TypeFlag_IsNotEditable) { result = 0; done = 1; } else switch(kind) { case E_TypeKind_Null: case E_TypeKind_Function: { result = 0; done = 1; }break; default: if((E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) || e_type_kind_is_pointer_or_ref(kind)) { result = 1; done = 1; }break; case E_TypeKind_Array: { if(type->flags & E_TypeFlag_IsNotText) { result = 0; done = 1; } else { E_TypeKind element_kind = e_type_kind_from_key(e_type_key_unwrap(t, E_TypeUnwrapFlag_All)); result = (element_kind == E_TypeKind_U8 || element_kind == E_TypeKind_U16 || element_kind == E_TypeKind_U32 || element_kind == E_TypeKind_S8 || element_kind == E_TypeKind_S16 || element_kind == E_TypeKind_S32 || element_kind == E_TypeKind_UChar8 || element_kind == E_TypeKind_UChar16 || element_kind == E_TypeKind_UChar32 || element_kind == E_TypeKind_Char8 || element_kind == E_TypeKind_Char16 || element_kind == E_TypeKind_Char32); done = 1; } }break; } } return result; } //////////////////////////////// //~ rjf: View Functions //- rjf: creation / deletion internal EV_View * ev_view_alloc(void) { Arena *arena = arena_alloc(); EV_View *view = push_array(arena, EV_View, 1); view->arena = arena; view->expand_slots_count = 256; view->expand_slots = push_array(arena, EV_ExpandSlot, view->expand_slots_count); view->key_view_rule_slots_count = 256; view->key_view_rule_slots = push_array(arena, EV_KeyViewRuleSlot, view->key_view_rule_slots_count); return view; } internal void ev_view_release(EV_View *view) { arena_release(view->arena); } //- rjf: lookups / mutations internal EV_ExpandNode * ev_expand_node_from_key(EV_View *view, EV_Key key) { U64 hash = ev_hash_from_key(key); U64 slot_idx = hash%view->expand_slots_count; EV_ExpandSlot *slot = &view->expand_slots[slot_idx]; EV_ExpandNode *node = 0; for(EV_ExpandNode *n = slot->first; n != 0; n = n->hash_next) { if(ev_key_match(n->key, key)) { node = n; break; } } return node; } internal B32 ev_expansion_from_key(EV_View *view, EV_Key key) { EV_ExpandNode *node = ev_expand_node_from_key(view, key); return (node != 0 && node->expanded); } internal String8 ev_view_rule_from_key(EV_View *view, EV_Key key) { String8 result = {0}; //- rjf: key -> hash * slot idx * slot U64 hash = ev_hash_from_key(key); U64 slot_idx = hash%view->key_view_rule_slots_count; EV_KeyViewRuleSlot *slot = &view->key_view_rule_slots[slot_idx]; //- rjf: slot -> existing node EV_KeyViewRuleNode *existing_node = 0; for(EV_KeyViewRuleNode *n = slot->first; n != 0; n = n->hash_next) { if(ev_key_match(n->key, key)) { existing_node = n; break; } } //- rjf: node -> result if(existing_node != 0) { result = str8(existing_node->buffer, existing_node->buffer_string_size); } return result; } internal void ev_key_set_expansion(EV_View *view, EV_Key parent_key, EV_Key key, B32 expanded) { // rjf: map keys => nodes EV_ExpandNode *parent_node = ev_expand_node_from_key(view, parent_key); EV_ExpandNode *node = ev_expand_node_from_key(view, key); // rjf: make node if we don't have one, and we need one if(node == 0 && expanded) { node = view->free_expand_node; if(node != 0) { SLLStackPop(view->free_expand_node); MemoryZeroStruct(node); } else { node = push_array(view->arena, EV_ExpandNode, 1); } // rjf: link into table U64 hash = ev_hash_from_key(key); U64 slot = hash % view->expand_slots_count; DLLPushBack_NP(view->expand_slots[slot].first, view->expand_slots[slot].last, node, hash_next, hash_prev); // rjf: link into parent if(parent_node != 0) { EV_ExpandNode *prev = 0; for(EV_ExpandNode *n = parent_node->first; n != 0; n = n->next) { if(n->key.child_id < key.child_id) { prev = n; } else { break; } } DLLInsert_NP(parent_node->first, parent_node->last, prev, node, next, prev); node->parent = parent_node; } } // rjf: fill if(node != 0) { node->key = key; node->expanded = expanded; } // rjf: unlink node & free if we don't need it anymore if(expanded == 0 && node != 0 && node->first == 0) { // rjf: unlink from table U64 hash = ev_hash_from_key(key); U64 slot = hash % view->expand_slots_count; DLLRemove_NP(view->expand_slots[slot].first, view->expand_slots[slot].last, node, hash_next, hash_prev); // rjf: unlink from tree if(parent_node != 0) { DLLRemove_NP(parent_node->first, parent_node->last, node, next, prev); } // rjf: free SLLStackPush(view->free_expand_node, node); } } internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_string) { //- rjf: key -> hash * slot idx * slot U64 hash = ev_hash_from_key(key); U64 slot_idx = hash%view->key_view_rule_slots_count; EV_KeyViewRuleSlot *slot = &view->key_view_rule_slots[slot_idx]; //- rjf: slot -> existing node EV_KeyViewRuleNode *existing_node = 0; for(EV_KeyViewRuleNode *n = slot->first; n != 0; n = n->hash_next) { if(ev_key_match(n->key, key)) { existing_node = n; break; } } //- rjf: existing node * new node -> node EV_KeyViewRuleNode *node = existing_node; if(node == 0) { node = push_array(view->arena, EV_KeyViewRuleNode, 1); DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev); node->key = key; node->buffer_cap = 512; node->buffer = push_array(view->arena, U8, node->buffer_cap); } //- rjf: mutate node if(node != 0) { node->buffer_string_size = ClampTop(view_rule_string.size, node->buffer_cap); MemoryCopy(node->buffer, view_rule_string.str, node->buffer_string_size); } } //////////////////////////////// //~ rjf: View Rule Info Table Building / Selection / Lookups internal void ev_expand_rule_table_push(Arena *arena, EV_ExpandRuleTable *table, EV_ExpandRule *info) { if(table->slots_count == 0) { table->slots_count = 512; table->slots = push_array(arena, EV_ExpandRuleSlot, table->slots_count); } U64 hash = ev_hash_from_seed_string(5381, info->string); U64 slot_idx = hash%table->slots_count; EV_ExpandRuleSlot *slot = &table->slots[slot_idx]; EV_ExpandRuleNode *n = push_array(arena, EV_ExpandRuleNode, 1); SLLQueuePush(slot->first, slot->last, n); MemoryCopyStruct(&n->v, info); n->v.string = push_str8_copy(arena, n->v.string); } internal void ev_select_expand_rule_table(EV_ExpandRuleTable *table) { ev_view_rule_info_table = table; } internal EV_ExpandRule * ev_expand_rule_from_string(String8 string) { EV_ExpandRule *info = &ev_nil_expand_rule; if(ev_view_rule_info_table != 0 && ev_view_rule_info_table->slots_count != 0) { U64 hash = ev_hash_from_seed_string(5381, string); U64 slot_idx = hash%ev_view_rule_info_table->slots_count; EV_ExpandRuleSlot *slot = &ev_view_rule_info_table->slots[slot_idx]; EV_ExpandRuleNode *node = 0; for(EV_ExpandRuleNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->v.string, string, 0)) { node = n; break; } } if(node != 0) { info = &node->v; } } return info; } internal EV_ExpandRule * ev_expand_rule_from_type_key(E_TypeKey type_key) { EV_ExpandRule *rule = &ev_nil_expand_rule; { E_TypeKey k = e_type_key_unwrap(type_key, E_TypeUnwrapFlag_Meta); E_TypeKind kind = e_type_kind_from_key(k); for(;kind == E_TypeKind_Lens; k = e_type_key_direct(e_type_key_unwrap(k, E_TypeUnwrapFlag_Meta)), kind = e_type_kind_from_key(k)) { E_Type *type = e_type_from_key(k); EV_ExpandRule *candidate = ev_expand_rule_from_string(type->name); if(candidate != &ev_nil_expand_rule) { rule = candidate; break; } } } return rule; } //////////////////////////////// //~ rjf: Block Building internal EV_BlockTree ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval root_eval) { ProfBeginFunction(); EV_BlockTree tree = {&ev_nil_block}; { Temp scratch = scratch_begin(&arena, 1); //- rjf: generate root expression EV_Key root_key = ev_key_root(); EV_Key root_row_key = ev_key_make(ev_hash_from_key(root_key), 1); //- rjf: generate root block tree.root = push_array(arena, EV_Block, 1); MemoryCopyStruct(tree.root, &ev_nil_block); tree.root->key = root_key; tree.root->string = str8_zero(); tree.root->eval = root_eval; tree.root->type_expand_rule = &e_type_expand_rule__default; tree.root->viz_expand_rule = &ev_nil_expand_rule; tree.root->row_count = 1; tree.total_row_count += 1; tree.total_item_count += 1; //- rjf: generate initial task, for root's evaluation typedef struct BlockTreeBuildTask BlockTreeBuildTask; struct BlockTreeBuildTask { BlockTreeBuildTask *next; EV_Block *parent_block; E_Eval eval; E_Expr *next_expr; U64 child_id; U64 split_relative_idx; B32 default_expanded; B32 force_expanded; S32 depth; }; BlockTreeBuildTask start_task = {0, tree.root, tree.root->eval, tree.root->eval.expr->next, 1, 0}; BlockTreeBuildTask *first_task = &start_task; BlockTreeBuildTask *last_task = first_task; //- rjf: iterate all expansions & generate blocks for each for(BlockTreeBuildTask *t = first_task; t != 0; t = t->next) { // rjf: get task key EV_Key key = ev_key_make(ev_hash_from_key(t->parent_block->key), t->child_id); // rjf: obtain expansion node & expansion state EV_ExpandNode *expand_node = ev_expand_node_from_key(view, key); B32 is_expanded = (expand_node != 0 && expand_node->expanded); if(t->default_expanded || t->force_expanded) { is_expanded ^= 1; } // rjf: skip if not expanded if(!is_expanded) { continue; } // rjf: unpack eval E_Mode mode = t->eval.irtree.mode; E_Eval eval = t->eval; // rjf: pointers/reference evaluations -> dereference for expansion { E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_Modifiers|E_TypeUnwrapFlag_Meta); E_TypeKind type_kind = e_type_kind_from_key(type_key); if(e_type_kind_is_pointer_or_ref(type_kind)) { eval = e_eval_wrapf(eval, "*($)"); } } // rjf: unpack type key we'll use for expanding this eval E_TypeKey expansion_type_key = ev_expansion_type_from_key(eval.irtree.type_key); if(!e_type_key_match(expansion_type_key, e_type_key_zero())) { eval.irtree.type_key = expansion_type_key; } // rjf: get expansion rules from type E_TypeExpandRule *type_expand_rule = e_expand_rule_from_type_key(eval.irtree.type_key); EV_ExpandRule *viz_expand_rule = ev_expand_rule_from_type_key(eval.irtree.type_key); // rjf: skip if no expansion rule, & type info disallows expansion if(viz_expand_rule == &ev_nil_expand_rule && !ev_type_key_and_mode_is_expandable(eval.irtree.type_key, mode)) { continue; } // rjf: get filter for this task String8 task_filter = t->depth == 0 ? filter : str8_zero(); // rjf: get top-level lookup/expansion info E_TypeExpandInfo type_expand_info = type_expand_rule->info(arena, eval, task_filter); EV_ExpandInfo viz_expand_info = viz_expand_rule->info(arena, view, task_filter, eval.expr); // rjf: determine expansion info U64 expansion_row_count = type_expand_info.expr_count; if(viz_expand_rule != &ev_nil_expand_rule) { expansion_row_count = viz_expand_info.row_count; } expansion_row_count = Min(0x0fffffffffffffffull, expansion_row_count); // rjf: determine if this expansion supports child expansions B32 allow_child_expansions = 1; if(viz_expand_info.single_item) { // NOTE(rjf): for now, just plugging in the heuristic of "is this a single row (a.k.a. visualizer)?" allow_child_expansions = 0; } // rjf: generate block for expansion EV_Block *expansion_block = &ev_nil_block; if(expansion_row_count != 0) { expansion_block = push_array(arena, EV_Block, 1); MemoryCopyStruct(expansion_block, &ev_nil_block); DLLPushBack_NPZ(&ev_nil_block, t->parent_block->first, t->parent_block->last, expansion_block, next, prev); expansion_block->parent = t->parent_block; expansion_block->key = key; expansion_block->split_relative_idx = t->split_relative_idx; expansion_block->eval = eval; expansion_block->filter = task_filter; expansion_block->type_expand_info = type_expand_info; expansion_block->type_expand_rule = type_expand_rule; expansion_block->viz_expand_info = viz_expand_info; expansion_block->viz_expand_rule = viz_expand_rule; expansion_block->row_count = expansion_row_count; tree.total_row_count += expansion_row_count; tree.total_item_count += viz_expand_info.single_item ? 1 : expansion_row_count; } // rjf: gather children expansions from expansion state U64 child_count = 0; EV_Key *child_keys = 0; U64 *child_nums = 0; if(allow_child_expansions && !child_count && !viz_expand_info.rows_default_expanded && expand_node != 0 && expansion_row_count != 0) { // rjf: count children for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next, child_count += 1){} // rjf: gather children keys & numbers B32 needs_sort = 0; child_keys = push_array(scratch.arena, EV_Key, child_count); child_nums = push_array(scratch.arena, U64, child_count); { U64 idx = 0; for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next, idx += 1) { child_keys[idx] = child->key; child_nums[idx] = type_expand_rule->num_from_id(type_expand_info.user_data, child->key.child_id); if(child_nums[idx] != child_keys[idx].child_id) { needs_sort = 1; } } } // rjf: sort children by number, if needed if(needs_sort) { for(U64 idx1 = 0; idx1 < child_count; idx1 += 1) { U64 min_idx2 = 0; U64 min_num = child_nums[idx1]; for(U64 idx2 = idx1+1; idx2 < child_count; idx2 += 1) { if(child_nums[idx2] < min_num) { min_idx2 = idx2; min_num = child_nums[idx2]; } } if(min_idx2 != 0) { Swap(EV_Key, child_keys[idx1], child_keys[min_idx2]); Swap(U64, child_nums[idx1], child_nums[min_idx2]); } } } } // rjf: gather children expansions from inverse of expansion state if(allow_child_expansions && !child_count && (viz_expand_info.rows_default_expanded || (expand_node == 0 && !viz_expand_info.rows_default_expanded))) { child_count = viz_expand_info.row_count; child_keys = push_array(scratch.arena, EV_Key, child_count); child_nums = push_array(scratch.arena, U64, child_count); for(U64 idx = 0; idx < child_count; idx += 1) { U64 child_id = type_expand_rule->id_from_num(type_expand_info.user_data, idx+1); child_keys[idx] = ev_key_make(ev_hash_from_key(key), child_id); child_nums[idx] = idx+1; } } // rjf: iterate children expansions & generate recursion tasks for(U64 idx = 0; idx < child_count; idx += 1) { U64 split_num = child_nums[idx]; U64 split_relative_idx = split_num - 1; if(split_relative_idx >= expansion_row_count) { continue; } if(viz_expand_info.rows_default_expanded || ev_expansion_from_key(view, child_keys[idx])) { Rng1U64 child_range = r1u64(split_relative_idx, split_relative_idx+1); E_Eval child_eval = {0}; type_expand_rule->range(arena, type_expand_info.user_data, eval, task_filter, r1u64(split_relative_idx, split_relative_idx+1), &child_eval); EV_Key child_key = child_keys[idx]; BlockTreeBuildTask *task = push_array(scratch.arena, BlockTreeBuildTask, 1); SLLQueuePush(first_task, last_task, task); task->parent_block = expansion_block; task->eval = child_eval; task->next_expr = &e_expr_nil; task->child_id = child_key.child_id; task->split_relative_idx = split_relative_idx; task->default_expanded = viz_expand_info.rows_default_expanded; task->depth = t->depth+1; } } // rjf: if this expr has a sibling, push another task to continue the chain if(t->next_expr != &e_expr_nil) { BlockTreeBuildTask *task = push_array(scratch.arena, BlockTreeBuildTask, 1); task->next = t->next; t->next = task; task->parent_block = t->parent_block; task->eval = e_eval_from_expr(t->next_expr); task->next_expr = t->next_expr->next; task->child_id = t->child_id + 1; task->split_relative_idx = 0; task->default_expanded = t->default_expanded; task->force_expanded = 1; task->depth = t->depth; } } scratch_end(scratch); } ProfEnd(); return tree; } internal U64 ev_depth_from_block(EV_Block *block) { U64 depth = 0; for(EV_Block *b = block->parent; b != &ev_nil_block; b = b->parent) { depth += 1; } return depth; } //////////////////////////////// //~ rjf: Block Coordinate Spaces internal U64 ev_block_id_from_num(EV_Block *block, U64 num) { U64 result = block->type_expand_rule->id_from_num(block->type_expand_info.user_data, num); return result; } internal U64 ev_block_num_from_id(EV_Block *block, U64 id) { U64 result = block->type_expand_rule->num_from_id(block->type_expand_info.user_data, id); return result; } internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockTree *block_tree) { EV_BlockRangeList list = {0}; { Temp scratch = scratch_begin(&arena, 1); typedef struct BlockTask BlockTask; struct BlockTask { BlockTask *next; EV_Block *block; EV_Block *next_child; Rng1U64 block_relative_range; }; BlockTask start_task = {0, block_tree->root, block_tree->root->first, r1u64(0, block_tree->root->row_count)}; for(BlockTask *t = &start_task; t != 0; t = t->next) { // rjf: get block-relative range, truncated by split position of next child Rng1U64 block_relative_range = t->block_relative_range; if(t->next_child != &ev_nil_block) { block_relative_range.max = t->next_child->split_relative_idx+1; } U64 block_num_visual_rows = dim_1u64(block_relative_range); // rjf: generate range node if(block_num_visual_rows != 0) { EV_BlockRangeNode *n = push_array(arena, EV_BlockRangeNode, 1); n->v.block = t->block; n->v.range = block_relative_range; SLLQueuePush(list.first, list.last, n); list.count += 1; } // rjf: generate task for child, + for post-child parts of this block if(t->next_child != &ev_nil_block) { // rjf: generate task for child - do *before* remainder (descend block tree depth first) BlockTask *child_task = push_array(scratch.arena, BlockTask, 1); child_task->next = t->next; t->next = child_task; child_task->block = t->next_child; child_task->next_child = t->next_child->first; child_task->block_relative_range = r1u64(0, t->next_child->row_count); // rjf: generate task for post-child rows, if any, after children Rng1U64 remainder_range = r1u64(t->next_child->split_relative_idx+1, t->block_relative_range.max); if(remainder_range.max >= remainder_range.min) { BlockTask *remainder_task = push_array(scratch.arena, BlockTask, 1); remainder_task->next = child_task->next; child_task->next = remainder_task; remainder_task->block = t->block; remainder_task->next_child = t->next_child->next; remainder_task->block_relative_range = remainder_range; } } } scratch_end(scratch); } return list; } internal EV_BlockRange ev_block_range_from_num(EV_BlockRangeList *block_ranges, U64 num) { EV_BlockRange result = {&ev_nil_block}; U64 base_num = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { U64 range_size = n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range); Rng1U64 global_range = r1u64(base_num, base_num + range_size); if(contains_1u64(global_range, num)) { result = n->v; break; } base_num += range_size; } return result; } internal EV_Key ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num) { EV_Key key = {0}; if(block_ranges->first) { key = ev_key_make(ev_hash_from_key(ev_key_root()), 1); } U64 base_num = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { U64 range_size = n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range); Rng1U64 global_range = r1u64(base_num, base_num + range_size); if(contains_1u64(global_range, num)) { U64 relative_num = (num - base_num) + n->v.range.min + 1; U64 child_id = ev_block_id_from_num(n->v.block, relative_num); EV_Key block_key = n->v.block->key; key = ev_key_make(ev_hash_from_key(block_key), child_id); break; } base_num += range_size; } return key; } internal U64 ev_num_from_key(EV_BlockRangeList *block_ranges, EV_Key key) { U64 result = 0; U64 base_num = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { U64 hash = ev_hash_from_key(n->v.block->key); if(hash == key.parent_hash) { U64 relative_num = ev_block_num_from_id(n->v.block, key.child_id); Rng1U64 num_range = r1u64(n->v.range.min, n->v.block->viz_expand_info.single_item ? (n->v.range.min+1) : n->v.range.max); if(contains_1u64(num_range, relative_num-1)) { result = base_num + (relative_num - 1 - n->v.range.min); break; } } base_num += n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range); } return result; } internal U64 ev_vnum_from_num(EV_BlockRangeList *block_ranges, U64 num) { U64 vnum = 0; { U64 base_vnum = 1; U64 base_num = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { U64 next_base_num = base_num + (n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range)); if(base_num <= num && num < next_base_num) { U64 relative_vnum = (n->v.block->viz_expand_info.single_item ? 0 : (num - base_num)); vnum = base_vnum + relative_vnum; break; } base_num = next_base_num; base_vnum += dim_1u64(n->v.range); } if(vnum == 0) { vnum = base_vnum; } } return vnum; } internal U64 ev_num_from_vnum(EV_BlockRangeList *block_ranges, U64 vnum) { U64 num = 0; { U64 base_vnum = 1; U64 base_num = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { U64 next_base_vnum = base_vnum + dim_1u64(n->v.range); if(base_vnum <= vnum && vnum < next_base_vnum) { U64 relative_num = (n->v.block->viz_expand_info.single_item ? 0 : (vnum - base_vnum)); num = base_num + relative_num; break; } base_vnum = next_base_vnum; base_num += (n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range)); } } return num; } //////////////////////////////// //~ rjf: Row Building internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 vnum_range) { EV_WindowedRowList rows = {0}; { U64 base_vnum = 1; for(EV_BlockRangeNode *n = block_ranges->first; n != 0; n = n->next) { // rjf: unpack this block/range pair Rng1U64 block_relative_range = n->v.range; U64 block_num_visual_rows = dim_1u64(block_relative_range); Rng1U64 block_global_range = r1u64(base_vnum, base_vnum + block_num_visual_rows); String8 block_filter = n->v.block->filter; // rjf: get skip/chop of global range U64 num_skipped = 0; U64 num_chopped = 0; { if(vnum_range.min > block_global_range.min) { num_skipped = (vnum_range.min - block_global_range.min); num_skipped = Min(num_skipped, block_num_visual_rows); } if(vnum_range.max < block_global_range.max) { num_chopped = (block_global_range.max - vnum_range.max); num_chopped = Min(num_chopped, block_num_visual_rows); } } // rjf: get block-relative *windowed* range Rng1U64 block_relative_range__windowed = r1u64(block_relative_range.min + num_skipped, block_relative_range.max - num_chopped); // rjf: sum & advance base_vnum += block_num_visual_rows; rows.count_before_visual += num_skipped; if(block_num_visual_rows != 0 && num_skipped != 0) { if(n->v.block->viz_expand_info.single_item) { if(num_skipped >= block_num_visual_rows) { rows.count_before_semantic += 1; } } else { rows.count_before_semantic += num_skipped; } } // rjf: generate rows before next splitting child if(block_relative_range__windowed.max > block_relative_range__windowed.min) { // rjf: get info about expansion range B32 is_standalone_row = 0; U64 range_exprs_count = dim_1u64(block_relative_range__windowed); E_Eval *range_evals = push_array(arena, E_Eval, range_exprs_count); for EachIndex(idx, range_exprs_count) { range_evals[idx] = e_eval_nil; } if(n->v.block->viz_expand_info.single_item || n->v.block->parent == &ev_nil_block) { is_standalone_row = 1; } else { n->v.block->type_expand_rule->range(arena, n->v.block->type_expand_info.user_data, n->v.block->eval, block_filter, block_relative_range__windowed, range_evals); } // rjf: no expansion operator applied -> push row for block expression; pass through block info if(is_standalone_row) { EV_WindowedRowNode *row_node = push_array(arena, EV_WindowedRowNode, 1); SLLQueuePush(rows.first, rows.last, row_node); rows.count += 1; row_node->visual_size_skipped = num_skipped; row_node->visual_size_chopped = num_chopped; EV_Row *row = &row_node->row; row->block = n->v.block; row->key = ev_key_make(ev_hash_from_key(row->block->key), 1); row->visual_size = n->v.block->viz_expand_info.single_item ? (n->v.block->row_count - (num_skipped + num_chopped)) : 1; row->edit_string = n->v.block->string; row->eval = n->v.block->eval; } // rjf: expansion operator applied -> call, and add rows for all expressions in the viewable range else for EachIndex(idx, range_exprs_count) { U64 child_num = block_relative_range.min + num_skipped + idx + 1; U64 child_id = ev_block_id_from_num(n->v.block, child_num); EV_Key row_key = ev_key_make(ev_hash_from_key(n->v.block->key), child_id); E_Eval row_eval = range_evals[idx]; EV_WindowedRowNode *row_node = push_array(arena, EV_WindowedRowNode, 1); SLLQueuePush(rows.first, rows.last, row_node); rows.count += 1; EV_Row *row = &row_node->row; row->block = n->v.block; row->key = row_key; row->visual_size = 1; row->edit_string = row_eval.string; row->eval = row_eval; } } } } return rows; } internal EV_Row * ev_row_from_num(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, U64 num) { U64 vidx = ev_vnum_from_num(block_ranges, num); EV_WindowedRowList rows = ev_windowed_row_list_from_block_range_list(arena, view, block_ranges, r1u64(vidx, vidx+1)); EV_Row *result = 0; if(rows.first != 0) { result = &rows.first->row; } else { result = push_array(arena, EV_Row, 1); result->block = &ev_nil_block; result->eval = e_eval_nil; } return result; } internal EV_WindowedRowList ev_rows_from_num_range(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 num_range) { Rng1U64 vnum_range = r1u64(ev_vnum_from_num(block_ranges, num_range.min), ev_vnum_from_num(block_ranges, num_range.max)+1); EV_WindowedRowList rows = ev_windowed_row_list_from_block_range_list(arena, view, block_ranges, vnum_range); return rows; } internal B32 ev_eval_is_expandable(E_Eval eval) { B32 result = 0; E_IRTreeAndType irtree = eval.irtree; // rjf: determine if lenses force expandability if(!result) { EV_ExpandRule *expand_rule = ev_expand_rule_from_type_key(irtree.type_key); if(expand_rule != &ev_nil_expand_rule) { result = 1; } } // rjf: determine if type info force expandability if(!result) { result = ev_type_key_and_mode_is_expandable(irtree.type_key, irtree.mode); } return result; } internal B32 ev_row_is_expandable(EV_Row *row) { B32 result = 0; if(!ev_key_match(ev_key_root(), row->block->key)) { result = ev_eval_is_expandable(row->eval); } return result; } internal B32 ev_row_is_editable(EV_Row *row) { B32 result = 0; E_IRTreeAndType irtree = row->eval.irtree; result = ev_type_key_is_editable(irtree.type_key); return result; } //////////////////////////////// //~ rjf: Stringification //- rjf: leaf stringification internal String8 ev_string_from_ascii_value(Arena *arena, U8 val) { String8 result = {0}; switch(val) { case 0x00:{result = str8_lit("\\0");}break; case 0x07:{result = str8_lit("\\a");}break; case 0x08:{result = str8_lit("\\b");}break; case 0x0c:{result = str8_lit("\\f");}break; case 0x0a:{result = str8_lit("\\n");}break; case 0x0d:{result = str8_lit("\\r");}break; case 0x09:{result = str8_lit("\\t");}break; case 0x0b:{result = str8_lit("\\v");}break; case 0x3f:{result = str8_lit("\\?");}break; case '"': {result = str8_lit("\\\"");}break; case '\'':{result = str8_lit("\\'");}break; case '\\':{result = str8_lit("\\\\");}break; default: if(32 <= val && val < 255) { result = push_str8f(arena, "%c", val); }break; } return result; } internal String8 ev_string_from_hresult_facility_code(U32 code) { String8 result = {0}; switch(code) { default:{}break; case 0x1:{result = str8_lit("RPC");}break; case 0x2:{result = str8_lit("DISPATCH");}break; case 0x3:{result = str8_lit("STORAGE");}break; case 0x4:{result = str8_lit("ITF");}break; case 0x7:{result = str8_lit("WIN32");}break; case 0x8:{result = str8_lit("WINDOWS");}break; case 0x9:{result = str8_lit("SECURITY|SSPI");}break; case 0xA:{result = str8_lit("CONTROL");}break; case 0xB:{result = str8_lit("CERT");}break; case 0xC:{result = str8_lit("INTERNET");}break; case 0xD:{result = str8_lit("MEDIASERVER");}break; case 0xE:{result = str8_lit("MSMQ");}break; case 0xF:{result = str8_lit("SETUPAPI");}break; case 0x10:{result = str8_lit("SCARD");}break; case 0x11:{result = str8_lit("COMPLUS");}break; case 0x12:{result = str8_lit("AAF");}break; case 0x13:{result = str8_lit("URT");}break; case 0x14:{result = str8_lit("ACS");}break; case 0x15:{result = str8_lit("DPLAY");}break; case 0x16:{result = str8_lit("UMI");}break; case 0x17:{result = str8_lit("SXS");}break; case 0x18:{result = str8_lit("WINDOWS_CE");}break; case 0x19:{result = str8_lit("HTTP");}break; case 0x1A:{result = str8_lit("USERMODE_COMMONLOG");}break; case 0x1B:{result = str8_lit("WER");}break; case 0x1F:{result = str8_lit("USERMODE_FILTER_MANAGER");}break; case 0x20:{result = str8_lit("BACKGROUNDCOPY");}break; case 0x21:{result = str8_lit("CONFIGURATION|WIA");}break; case 0x22:{result = str8_lit("STATE_MANAGEMENT");}break; case 0x23:{result = str8_lit("METADIRECTORY");}break; case 0x24:{result = str8_lit("WINDOWSUPDATE");}break; case 0x25:{result = str8_lit("DIRECTORYSERVICE");}break; case 0x26:{result = str8_lit("GRAPHICS");}break; case 0x27:{result = str8_lit("SHELL|NAP");}break; case 0x28:{result = str8_lit("TPM_SERVICES");}break; case 0x29:{result = str8_lit("TPM_SOFTWARE");}break; case 0x2A:{result = str8_lit("UI");}break; case 0x2B:{result = str8_lit("XAML");}break; case 0x2C:{result = str8_lit("ACTION_QUEUE");}break; case 0x30:{result = str8_lit("WINDOWS_SETUP|PLA");}break; case 0x31:{result = str8_lit("FVE");}break; case 0x32:{result = str8_lit("FWP");}break; case 0x33:{result = str8_lit("WINRM");}break; case 0x34:{result = str8_lit("NDIS");}break; case 0x35:{result = str8_lit("USERMODE_HYPERVISOR");}break; case 0x36:{result = str8_lit("CMI");}break; case 0x37:{result = str8_lit("USERMODE_VIRTUALIZATION");}break; case 0x38:{result = str8_lit("USERMODE_VOLMGR");}break; case 0x39:{result = str8_lit("BCD");}break; case 0x3A:{result = str8_lit("USERMODE_VHD");}break; case 0x3C:{result = str8_lit("SDIAG");}break; case 0x3D:{result = str8_lit("WINPE|WEBSERVICES");}break; case 0x3E:{result = str8_lit("WPN");}break; case 0x3F:{result = str8_lit("WINDOWS_STORE");}break; case 0x40:{result = str8_lit("INPUT");}break; case 0x42:{result = str8_lit("EAP");}break; case 0x50:{result = str8_lit("WINDOWS_DEFENDER");}break; case 0x51:{result = str8_lit("OPC");}break; case 0x52:{result = str8_lit("XPS");}break; case 0x53:{result = str8_lit("RAS");}break; case 0x54:{result = str8_lit("POWERSHELL|MBN");}break; case 0x55:{result = str8_lit("EAS");}break; case 0x62:{result = str8_lit("P2P_INT");}break; case 0x63:{result = str8_lit("P2P");}break; case 0x64:{result = str8_lit("DAF");}break; case 0x65:{result = str8_lit("BLUETOOTH_ATT");}break; case 0x66:{result = str8_lit("AUDIO");}break; case 0x6D:{result = str8_lit("VISUALCPP");}break; case 0x70:{result = str8_lit("SCRIPT");}break; case 0x71:{result = str8_lit("PARSE");}break; case 0x78:{result = str8_lit("BLB");}break; case 0x79:{result = str8_lit("BLB_CLI");}break; case 0x7A:{result = str8_lit("WSBAPP");}break; case 0x80:{result = str8_lit("BLBUI");}break; case 0x81:{result = str8_lit("USN");}break; case 0x82:{result = str8_lit("USERMODE_VOLSNAP");}break; case 0x83:{result = str8_lit("TIERING");}break; case 0x85:{result = str8_lit("WSB_ONLINE");}break; case 0x86:{result = str8_lit("ONLINE_ID");}break; case 0x99:{result = str8_lit("DLS");}break; case 0xA0:{result = str8_lit("SOS");}break; case 0xB0:{result = str8_lit("DEBUGGERS");}break; case 0xE7:{result = str8_lit("USERMODE_SPACES");}break; case 0x100:{result = str8_lit("DMSERVER|RESTORE|SPP");}break; case 0x101:{result = str8_lit("DEPLOYMENT_SERVICES_SERVER");}break; case 0x102:{result = str8_lit("DEPLOYMENT_SERVICES_IMAGING");}break; case 0x103:{result = str8_lit("DEPLOYMENT_SERVICES_MANAGEMENT");}break; case 0x104:{result = str8_lit("DEPLOYMENT_SERVICES_UTIL");}break; case 0x105:{result = str8_lit("DEPLOYMENT_SERVICES_BINLSVC");}break; case 0x107:{result = str8_lit("DEPLOYMENT_SERVICES_PXE");}break; case 0x108:{result = str8_lit("DEPLOYMENT_SERVICES_TFTP");}break; case 0x110:{result = str8_lit("DEPLOYMENT_SERVICES_TRANSPORT_MANAGEMENT");}break; case 0x116:{result = str8_lit("DEPLOYMENT_SERVICES_DRIVER_PROVISIONING");}break; case 0x121:{result = str8_lit("DEPLOYMENT_SERVICES_MULTICAST_SERVER");}break; case 0x122:{result = str8_lit("DEPLOYMENT_SERVICES_MULTICAST_CLIENT");}break; case 0x125:{result = str8_lit("DEPLOYMENT_SERVICES_CONTENT_PROVIDER");}break; case 0x131:{result = str8_lit("LINGUISTIC_SERVICES");}break; case 0x375:{result = str8_lit("WEB");}break; case 0x376:{result = str8_lit("WEB_SOCKET");}break; case 0x446:{result = str8_lit("AUDIOSTREAMING");}break; case 0x600:{result = str8_lit("ACCELERATOR");}break; case 0x701:{result = str8_lit("MOBILE");}break; case 0x7CC:{result = str8_lit("WMAAECMA");}break; case 0x801:{result = str8_lit("WEP");}break; case 0x802:{result = str8_lit("SYNCENGINE");}break; case 0x878:{result = str8_lit("DIRECTMUSIC");}break; case 0x879:{result = str8_lit("DIRECT3D10");}break; case 0x87A:{result = str8_lit("DXGI");}break; case 0x87B:{result = str8_lit("DXGI_DDI");}break; case 0x87C:{result = str8_lit("DIRECT3D11");}break; case 0x888:{result = str8_lit("LEAP");}break; case 0x889:{result = str8_lit("AUDCLNT");}break; case 0x898:{result = str8_lit("WINCODEC_DWRITE_DWM");}break; case 0x899:{result = str8_lit("DIRECT2D");}break; case 0x900:{result = str8_lit("DEFRAG");}break; case 0x901:{result = str8_lit("USERMODE_SDBUS");}break; case 0x902:{result = str8_lit("JSCRIPT");}break; case 0xA01:{result = str8_lit("PIDGENX");}break; } return result; } internal String8 ev_string_from_hresult_code(U32 code) { String8 result = {0}; switch(code) { default:{}break; case 0x00000000: {result = str8_lit("S_OK: Operation successful");}break; case 0x00000001: {result = str8_lit("S_FALSE: Operation successful but returned no results");}break; case 0x80004004: {result = str8_lit("E_ABORT: Operation aborted");}break; case 0x80004005: {result = str8_lit("E_FAIL: Unspecified failure");}break; case 0x80004002: {result = str8_lit("E_NOINTERFACE: No such interface supported");}break; case 0x80004001: {result = str8_lit("E_NOTIMPL: Not implemented");}break; case 0x80004003: {result = str8_lit("E_POINTER: Pointer that is not valid");}break; case 0x8000FFFF: {result = str8_lit("E_UNEXPECTED: Unexpected failure");}break; case 0x80070005: {result = str8_lit("E_ACCESSDENIED: General access denied error");}break; case 0x80070006: {result = str8_lit("E_HANDLE: Handle that is not valid");}break; case 0x80070057: {result = str8_lit("E_INVALIDARG: One or more arguments are not valid");}break; case 0x8007000E: {result = str8_lit("E_OUTOFMEMORY: Failed to allocate necessary memory");}break; } return result; } internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringParams *params, E_Eval eval) { String8 result = {0}; E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums); E_TypeKind type_kind = e_type_kind_from_key(type_key); U64 type_byte_size = e_type_byte_size_from_key(type_key); U8 digit_group_separator = 0; if(!(params->flags & EV_StringFlag_ReadOnlyDisplayRules)) { digit_group_separator = 0; } S64 s64 = 0; U64 u64 = 0; F64 f64 = 0; switch(type_kind) { default:{}break; case E_TypeKind_Handle: { result = str8_from_s64(arena, eval.value.s64, params->radix, params->min_digits, digit_group_separator); }break; case E_TypeKind_HResult: { if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { Temp scratch = scratch_begin(&arena, 1); U32 hresult_value = (U32)eval.value.u64; U32 is_error = !!(hresult_value & (1ull<<31)); U32 error_code = (hresult_value); U32 facility = (hresult_value & 0x7ff0000) >> 16; String8 value_string = str8_from_s64(scratch.arena, eval.value.u64, params->radix, params->min_digits, digit_group_separator); String8 facility_string = ev_string_from_hresult_facility_code(facility); String8 error_string = ev_string_from_hresult_code(error_code); result = push_str8f(arena, "%S%s%s%S%s%s%S%s", error_string, error_string.size != 0 ? " " : "", facility_string.size != 0 ? "[" : "", facility_string, facility_string.size != 0 ? "] ": "", error_string.size != 0 ? "(" : "", value_string, error_string.size != 0 ? ")" : ""); scratch_end(scratch); } else { result = str8_from_s64(arena, eval.value.u64, params->radix, params->min_digits, digit_group_separator); } }break; case E_TypeKind_Char8: case E_TypeKind_Char16: case E_TypeKind_Char32: case E_TypeKind_UChar8: case E_TypeKind_UChar16: case E_TypeKind_UChar32: { B32 type_is_unsigned = (E_TypeKind_UChar8 <= type_kind && type_kind <= E_TypeKind_UChar32); String8 char_str = {0}; if(!(params->flags & EV_StringFlag_DisableChars)) { char_str = ev_string_from_ascii_value(arena, eval.value.s64); } if(char_str.size != 0) { if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { String8 imm_string = (type_is_unsigned ? str8_from_u64(arena, eval.value.u64, params->radix, params->min_digits, digit_group_separator) : str8_from_s64(arena, eval.value.s64, params->radix, params->min_digits, digit_group_separator)); result = push_str8f(arena, "'%S' (%S)", char_str, imm_string); } else { result = push_str8f(arena, "'%S'", char_str); } } else { result = (type_is_unsigned ? str8_from_u64(arena, eval.value.u64, params->radix, params->min_digits, digit_group_separator) : str8_from_s64(arena, eval.value.s64, params->radix, params->min_digits, digit_group_separator)); } }break; case E_TypeKind_S8: s64 = (S64)eval.value.s8; goto sint_path; case E_TypeKind_S16: s64 = (S64)eval.value.s16; goto sint_path; case E_TypeKind_S32: s64 = (S64)eval.value.s32; goto sint_path; case E_TypeKind_S64: s64 = (S64)eval.value.s64; goto sint_path; sint_path:; { result = str8_from_s64(arena, s64, params->radix, params->min_digits, digit_group_separator); }break; case E_TypeKind_U8: u64 = (U64)eval.value.u8; goto uint_path; case E_TypeKind_U16: u64 = (U64)eval.value.u16; goto uint_path; case E_TypeKind_U32: u64 = (U64)eval.value.u32; goto uint_path; case E_TypeKind_U64: u64 = (U64)eval.value.u64; goto uint_path; uint_path:; { result = str8_from_u64(arena, u64, params->radix, params->min_digits, digit_group_separator); }break; case E_TypeKind_U128: { Temp scratch = scratch_begin(&arena, 1); String8 upper64 = str8_from_u64(scratch.arena, eval.value.u128.u64[0], params->radix, params->min_digits, digit_group_separator); String8 lower64 = str8_from_u64(scratch.arena, eval.value.u128.u64[1], params->radix, params->min_digits, digit_group_separator); result = push_str8f(arena, "%S:%S", upper64, lower64); scratch_end(scratch); }break; case E_TypeKind_F32:{f64 = (F64)eval.value.f32;}goto f64_path; case E_TypeKind_F64:{f64 = eval.value.f64;}goto f64_path; f64_path:; { result = push_str8f(arena, "%.*f", params->min_digits ? params->min_digits : 16, f64); U64 num_to_chop = 0; for(U64 num_trimmed = 0; num_trimmed < result.size; num_trimmed += 1) { if(result.str[result.size - 1 - num_trimmed] != '0') { if(result.str[result.size - 1 - num_trimmed] == '.' && num_to_chop > 0) { num_to_chop -= 1; } break; } num_to_chop += 1; } result = str8_chop(result, num_to_chop); }break; case E_TypeKind_Bool:{result = push_str8f(arena, "%s", eval.value.u64 ? "true" : "false");}break; case E_TypeKind_Ptr: {result = push_str8f(arena, "0x%I64x", eval.value.u64);}break; case E_TypeKind_LRef:{result = push_str8f(arena, "0x%I64x", eval.value.u64);}break; case E_TypeKind_RRef:{result = push_str8f(arena, "0x%I64x", eval.value.u64);}break; case E_TypeKind_Function:{result = push_str8f(arena, "0x%I64x", eval.value.u64);}break; } return result; } internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw) { Temp scratch = scratch_begin(&arena, 1); String8List parts = {0}; U64 start_split_idx = 0; for(U64 idx = 0; idx <= raw.size; idx += 1) { U8 byte = (idx < raw.size) ? raw.str[idx] : 0; B32 split = 1; String8 separator_replace = {0}; switch(byte) { default:{split = 0;}break; case 0: {}break; case '\a': {separator_replace = str8_lit("\\a");}break; case '\b': {separator_replace = str8_lit("\\b");}break; case '\f': {separator_replace = str8_lit("\\f");}break; case '\n': {separator_replace = str8_lit("\\n");}break; case '\r': {separator_replace = str8_lit("\\r");}break; case '\t': {separator_replace = str8_lit("\\t");}break; case '\v': {separator_replace = str8_lit("\\v");}break; case '\\': {separator_replace = str8_lit("\\\\");}break; case '"': {separator_replace = str8_lit("\\\"");}break; } if(split) { String8 substr = str8_substr(raw, r1u64(start_split_idx, idx)); start_split_idx = idx+1; str8_list_push(scratch.arena, &parts, substr); if(separator_replace.size != 0) { str8_list_push(scratch.arena, &parts, separator_replace); } } } StringJoin join = {0}; String8 result = str8_list_join(arena, &parts, &join); scratch_end(scratch); return result; } //- rjf: tree stringification iterator internal EV_StringIter * ev_string_iter_begin(Arena *arena, E_Eval eval, EV_StringParams *params) { EV_StringIter *it = push_array(arena, EV_StringIter, 1); it->top_task = push_array(arena, EV_StringIterTask, 1); it->top_task->eval = eval; MemoryCopyStruct(&it->top_task->params, params); return it; } internal B32 ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) { B32 result = 0; //- rjf: make progress on top task MemoryZeroStruct(out_string); B32 need_pop = 1; B32 need_new_task = 0; EV_StringIterTask new_task = {0}; S32 top_task_depth = 0; if(it->top_task != 0) { result = 1; //- rjf: unpack task U64 task_idx = it->top_task->idx; S32 depth = top_task_depth = it->top_task->depth; EV_StringParams *params = &it->top_task->params; E_Eval eval = it->top_task->eval; E_TypeKey type_key = eval.irtree.type_key; E_TypeKind type_kind = e_type_kind_from_key(type_key); String8 expansion_opener_symbol = str8_lit("{"); String8 expansion_closer_symbol = str8_lit("}"); //- rjf: type evaluations -> display type string if(eval.irtree.mode == E_Mode_Null && !e_type_key_match(e_type_key_zero(), eval.irtree.type_key)) { *out_string = e_type_string_from_key(arena, type_key); } //- rjf: non-type evaluations else switch(type_kind) { ////////////////////////// //- rjf: default - leaf cases // default: { E_Eval value_eval = e_value_eval_from_eval(eval); *out_string = ev_string_from_simple_typed_eval(arena, params, value_eval); }break; ////////////////////////// //- rjf: enums // case E_TypeKind_Enum: { switch(task_idx) { default:{}break; case 0: { E_Type *type = e_type_from_key(type_key); E_Eval value_eval = e_value_eval_from_eval(eval); String8 constant_name = {0}; for(U64 val_idx = 0; val_idx < type->count; val_idx += 1) { if(value_eval.value.u64 == type->enum_vals[val_idx].val) { constant_name = type->enum_vals[val_idx].name; break; } } String8 sufficient_suffix = constant_name; if(str8_match(sufficient_suffix, type->name, StringMatchFlag_RightSideSloppy)) { sufficient_suffix = str8_skip(sufficient_suffix, type->name.size); if(str8_match(sufficient_suffix, str8_lit("_"), StringMatchFlag_RightSideSloppy)) { sufficient_suffix = str8_skip(sufficient_suffix, 1); } } if(sufficient_suffix.size != 0) { *out_string = push_str8f(arena, "%S.%S", type->name, sufficient_suffix); if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { need_pop = 0; } } else { need_pop = 1; need_new_task = 1; new_task.params = *params; new_task.eval = e_value_eval_from_eval(eval); new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); } }break; case 1: { *out_string = str8_lit(" ("); need_pop = 0; need_new_task = 1; new_task.params = *params; new_task.eval = e_value_eval_from_eval(eval); new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); }break; case 2: { *out_string = str8_lit(")"); }break; } }break; ////////////////////////// //- rjf: lenses // case E_TypeKind_Lens: { if(it->top_task->redirect_to_sets_and_structs) { E_Type *type = e_type_from_key(type_key); if(type->flags & E_TypeFlag_ArrayLikeExpansion) { expansion_opener_symbol = str8_lit("["); expansion_closer_symbol = str8_lit("]"); } goto arrays_and_sets_and_structs; } E_Type *type = e_type_from_key(type_key); E_TypeKind element_type_kind = e_type_kind_from_key(e_type_key_unwrap(type->direct_type_key, E_TypeUnwrapFlag_All)); B32 lens_applied = 1; EV_StringParams lens_params = *params; if(0){} else if(str8_match(type->name, str8_lit("bin"), 0)) { lens_params.radix = 2; } else if(str8_match(type->name, str8_lit("oct"), 0)) { lens_params.radix = 8; } else if(str8_match(type->name, str8_lit("dec"), 0)) { lens_params.radix = 10; } else if(str8_match(type->name, str8_lit("hex"), 0)) { lens_params.radix = 16; } else if(str8_match(type->name, str8_lit("digits"), 0) && type->count >= 1) { E_ParentKey(eval.key) { E_Value value = e_value_from_expr(type->args[0]); lens_params.min_digits = value.u64; } } else if(str8_match(type->name, str8_lit("no_string"), 0)) { lens_params.flags |= EV_StringFlag_DisableStrings; } else if(str8_match(type->name, str8_lit("no_char"), 0)) { lens_params.flags |= EV_StringFlag_DisableChars; } else if(str8_match(type->name, str8_lit("no_addr"), 0)) { lens_params.flags |= EV_StringFlag_DisableAddresses; } else if(str8_match(type->name, str8_lit("array"), 0) && type->count >= 1 && (((E_TypeKind_Char8 <= element_type_kind && element_type_kind <= E_TypeKind_UChar32) || element_type_kind == E_TypeKind_S8 || element_type_kind == E_TypeKind_U8))) { E_ParentKey(eval.key) { lens_params.limit_strings = 1; lens_params.limit_strings_size = e_value_from_expr(type->args[0]).u64; } } else { lens_applied = 0; } if(lens_applied) { need_new_task = 1; need_pop = 1; new_task.params = lens_params; new_task.eval = eval; new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); } else if(type->kind != E_TypeKind_Lens || type->expand.info != 0) { need_new_task = 1; need_pop = 1; new_task.params = *params; new_task.eval = eval; new_task.redirect_to_sets_and_structs = 1; } else { need_new_task = 1; need_pop = 1; new_task.params = lens_params; new_task.eval = eval; new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); #if 0 // NOTE(rjf): will explicitly visualize lenses in value strings. does not seem useful for now? switch(task_idx) { default:{}break; // rjf: step 0 -> generate lens description, then descend to same evaluation w/ direct type case 0: { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; { str8_list_pushf(scratch.arena, &strings, "%S(", type->name); for EachIndex(idx, type->count) { String8 string = e_string_from_expr(scratch.arena, type->args[idx]); str8_list_push(scratch.arena, &strings, string); if(idx+1 < type->count) { str8_list_pushf(scratch.arena, &strings, ", "); } } str8_list_pushf(scratch.arena, &strings, ") <- ("); } *out_string = str8_list_join(arena, &strings, 0); need_new_task = 1; need_pop = 0; new_task.params = *params; new_task.eval = eval; new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); scratch_end(scratch); }break; // rjf: step 1 -> close case 1: { *out_string = str8_lit(")"); }break; } #endif } }break; ////////////////////////// //- rjf: meta-expression tags // case E_TypeKind_MetaExpr: { if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { switch(task_idx) { default:{}break; case 0: { E_Type *type = e_type_from_key(type_key); *out_string = push_str8f(arena, "%S (", type->name); need_pop = 0; need_new_task = 1; new_task.params = *params; new_task.eval = eval; new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); }break; case 1: { *out_string = str8_lit(")"); }break; } } else { E_Type *type = e_type_from_key(type_key); *out_string = type->name; } }break; ////////////////////////// //- rjf: modifiers / no-ops // case E_TypeKind_Alias: case E_TypeKind_Modifier: case E_TypeKind_MetaDescription: case E_TypeKind_MetaDisplayName: { need_pop = 1; need_new_task = 1; new_task.params = *params; new_task.eval = eval; new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); }break; ////////////////////////// //- rjf: bitfields // case E_TypeKind_Bitfield: { need_pop = 1; need_new_task = 1; new_task.params = *params; new_task.eval = e_value_eval_from_eval(eval); new_task.eval.irtree.type_key = e_type_key_direct(eval.irtree.type_key); }break; ////////////////////////// //- rjf: pointers // case E_TypeKind_Function: case E_TypeKind_Ptr: case E_TypeKind_LRef: case E_TypeKind_RRef: case E_TypeKind_Array: { if(type_kind == E_TypeKind_Array && it->top_task->redirect_to_sets_and_structs) { expansion_opener_symbol = str8_lit("["); expansion_closer_symbol = str8_lit("]"); goto arrays_and_sets_and_structs; } typedef struct EV_StringPtrData EV_StringPtrData; struct EV_StringPtrData { E_Eval value_eval; E_Type *type; E_Type *direct_type; B32 ptee_has_content; B32 ptee_has_string; B32 did_prefix_content; B32 did_prefix_string; B32 did_redirect; }; EV_StringPtrData *ptr_data = it->top_task->user_data; if(ptr_data == 0) { ptr_data = it->top_task->user_data = push_array(arena, EV_StringPtrData, 1); ptr_data->value_eval = e_value_eval_from_eval(eval); ptr_data->type = e_type_from_key(type_key); ptr_data->direct_type = e_type_from_key(e_type_key_unwrap(type_key, E_TypeUnwrapFlag_All)); ptr_data->ptee_has_content = (ptr_data->value_eval.value.u64 != 0 && ptr_data->direct_type->kind != E_TypeKind_Null && ptr_data->direct_type->kind != E_TypeKind_Void); ptr_data->ptee_has_string = ((E_TypeKind_Char8 <= ptr_data->direct_type->kind && ptr_data->direct_type->kind <= E_TypeKind_UChar32) || ptr_data->direct_type->kind == E_TypeKind_S8 || ptr_data->direct_type->kind == E_TypeKind_U8); } if(ptr_data->did_redirect) { need_pop = 1; } else switch(task_idx) { default:{}break; //- rjf: step 0 -> try "prefix content", which we want to print before the pointer value, // like strings or symbol names case 0: { // rjf: try strings if(!(ptr_data->type->flags & E_TypeFlag_IsNotText) && !ptr_data->did_prefix_content && ptr_data->ptee_has_string && !(params->flags & EV_StringFlag_DisableStrings) && (type_kind == E_TypeKind_Array || params->flags & EV_StringFlag_ReadOnlyDisplayRules)) { Temp scratch = scratch_begin(&arena, 1); // rjf: read string data #define EV_STRING_ITER_STRING_BUFFER_CAPACITY 4096 U64 string_buffer_size = EV_STRING_ITER_STRING_BUFFER_CAPACITY; U8 *string_buffer = push_array(scratch.arena, U8, string_buffer_size); if(type_kind == E_TypeKind_Array && eval.irtree.mode == E_Mode_Value) { StaticAssert(sizeof(eval.value.u512.u8) <= EV_STRING_ITER_STRING_BUFFER_CAPACITY, ev_string_iter_value_string_buffer_size_check); MemoryCopy(string_buffer, eval.value.u512.u8, sizeof(eval.value.u512.u8)); } else { U64 string_memory_addr = ptr_data->value_eval.value.u64; for(U64 try_size = string_buffer_size; try_size >= 16; try_size /= 2) { B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+try_size)); if(read_good) { break; } } string_buffer[string_buffer_size-1] = 0; } // rjf: check element size - if non-U8, assume UTF-16 or UTF-32 based on type, and convert U64 element_size = ptr_data->direct_type->byte_size; String8 string = {0}; switch(element_size) { default:{string = str8_cstring((char *)string_buffer);}break; case 2: {string = str8_from_16(scratch.arena, str16_cstring((U16 *)string_buffer));}break; case 4: {string = str8_from_32(scratch.arena, str32_cstring((U32 *)string_buffer));}break; } // rjf: apply string size limitation if(params->limit_strings) { string = str8_prefix(string, params->limit_strings_size); } else if(type_kind == E_TypeKind_Array && ptr_data->type->count != 0) { string = str8_prefix(string, ptr_data->type->count); } // rjf: escape and quote B32 string__is_escaped_and_quoted = (!(params->flags & EV_StringFlag_DisableStringQuotes) || depth > 0); String8 string__escaped_and_quoted = string; if(string__is_escaped_and_quoted) { String8 string_escaped = ev_escaped_from_raw_string(scratch.arena, string); string__escaped_and_quoted = push_str8f(scratch.arena, "\"%S\"", string_escaped); } // rjf: report *out_string = push_str8_copy(arena, string__escaped_and_quoted); ptr_data->did_prefix_content = 1; ptr_data->did_prefix_string = 1; scratch_end(scratch); } // rjf: try symbols if(!ptr_data->did_prefix_content) { U64 vaddr = ptr_data->value_eval.value.u64; E_Module *module = &e_module_nil; for EachIndex(idx, e_base_ctx->modules_count) { if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vaddr)) { module = &e_base_ctx->modules[idx]; break; } } E_DbgInfo *dbg_info = e_dbg_info_from_module(module); if(dbg_info == &e_dbg_info_nil) { dbg_info = e_dbg_info_from_type_key(type_key); } U32 dbg_info_num = 0; if(dbg_info != &e_dbg_info_nil) { dbg_info_num = (U32)(dbg_info - e_base_ctx->dbg_infos) + 1; } RDI_Parsed *rdi = dbg_info->rdi; U64 voff = vaddr - module->vaddr_range.min; B32 good_symbol_match = 0; // NOTE(rjf): read-only -> generate non-parseable things, like type-info / inlines if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { // rjf: voff -> scope U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); // rjf: scope -> # of max possible inline depth U64 inline_site_count = 0; for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next) { RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx); s_idx_next = s->parent_scope_idx; if(s->inline_site_idx != 0) { inline_site_count += 1; } else { break; } } // rjf: depth in [1, max]? -> form name from inline site if(0 < ptr_data->type->depth && ptr_data->type->depth <= inline_site_count) { RDI_InlineSite *inline_site = 0; U64 s_inline_depth = inline_site_count; for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next) { RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx); s_idx_next = s->parent_scope_idx; if(s_inline_depth == ptr_data->type->depth) { inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); break; } s_inline_depth -= 1; if(s_inline_depth == 0) { break; } } if(inline_site != 0) { RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, inline_site->type_idx); E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, dbg_info_num); String8 name = {0}; name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); if(inline_site->type_idx != 0) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; str8_list_pushf(scratch.arena, &list, "[inlined] "); e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0); str8_list_push(scratch.arena, &list, name); e_type_rhs_string_from_key(scratch.arena, type, &list, 0); *out_string = str8_list_join(arena, &list, 0); scratch_end(scratch); } else { *out_string = push_str8_copy(arena, name); } good_symbol_match = (name.size != 0); } } // rjf: depth == 0 or depth >= max? -> form name from scope procedure else { Temp scratch = scratch_begin(&arena, 1); RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, dbg_info_num); String8 name = {0}; name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); if(procedure->type_idx != 0) { String8List list = {0}; e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0); str8_list_push(scratch.arena, &list, name); e_type_rhs_string_from_key(scratch.arena, type, &list, 0); *out_string = str8_list_join(arena, &list, 0); } else { *out_string = push_str8_copy(arena, name); } good_symbol_match = (out_string->size != 0); scratch_end(scratch); } // rjf: if we have a function type, but we did not generate any name, then just put a ??? if(out_string->size == 0 && e_type_kind_from_key(ptr_data->type->direct_type_key) == E_TypeKind_Function) { *out_string = str8_lit("???"); good_symbol_match = 1; } } // NOTE(rjf): non-read-only -> only generate thing which can be parsed, so just procedure name else { // rjf: voff -> scope U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); // rjf: scope -> procedure / string RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); String8 procedure_name = {0}; procedure_name.str = rdi_name_from_procedure(rdi, procedure, &procedure_name.size); *out_string = procedure_name; good_symbol_match = (procedure_name.size != 0); } ptr_data->did_prefix_content = good_symbol_match; } // rjf: if this is an array, and we do not have a prefix, then we need to // generate a new task which redirects array types -> sets and structs. if(type_kind == E_TypeKind_Array && !ptr_data->did_prefix_content) { need_new_task = 1; need_pop = 0; new_task.params = *params; new_task.eval = eval; new_task.redirect_to_sets_and_structs = 1; ptr_data->did_redirect = 1; } // rjf: if this is an array, and we *did* prefix content, then we are // just done. else if(type_kind == E_TypeKind_Array && ptr_data->did_prefix_content) { // NOTE(rjf): no-op, task is done. } // rjf: otherwise, keep going on this task else { need_pop = 0; } }break; //- rjf: step 1 -> do pointer value + descend if needed case 1: { Temp scratch = scratch_begin(&arena, 1); String8 ptr_value_string = str8_from_u64(scratch.arena, ptr_data->value_eval.value.u64, 16, 0, 0); // // NOTE(rjf): currently, we are not using the string-generation radix parameter when // generating a pointer value - it is weird to want to change pointer value visualization // to anything other than hex, so it is just not supported right now... // // rjf: [read only] if we did prefix content, do a parenthesized pointer value if(!(params->flags & EV_StringFlag_DisableAddresses) && params->flags & EV_StringFlag_ReadOnlyDisplayRules && ptr_data->did_prefix_content) { *out_string = push_str8f(arena, " (%S)", ptr_value_string); } // rjf: [read only] if we did *not* do any prefix content, but we have content, // do " -> " then descend else if(params->flags & EV_StringFlag_ReadOnlyDisplayRules && !ptr_data->did_prefix_content && ptr_data->ptee_has_content) { if(!(params->flags & EV_StringFlag_DisableAddresses)) { *out_string = push_str8f(arena, "%S -> ", ptr_value_string); } // rjf: single-length pointers -> just gen new task for deref'd expr if(ptr_data->type->count == 1) { E_Eval deref_eval = e_eval_wrapf(eval, "*$"); need_new_task = 1; need_pop = 0; new_task.params = *params; new_task.eval = deref_eval; } // rjf: multi-length pointers -> expand like an array (try to dedup with array case) else { // TODO(rjf) } } // rjf: [writeable, catchall] if we did *not* do any prefix content, do "" else if(!ptr_data->did_prefix_content) { *out_string = push_str8_copy(arena, ptr_value_string); } scratch_end(scratch); }break; } }break; ////////////////////////// //- rjf: non-string-arrays/structs, sets // case E_TypeKind_Struct: case E_TypeKind_Union: case E_TypeKind_Class: case E_TypeKind_IncompleteStruct: case E_TypeKind_IncompleteUnion: case E_TypeKind_IncompleteClass: case E_TypeKind_Set: arrays_and_sets_and_structs: { typedef struct EV_ExpandedTypeData EV_ExpandedTypeData; struct EV_ExpandedTypeData { E_Type *type; E_TypeExpandRule *expand_rule; E_TypeExpandInfo expand_info; }; EV_ExpandedTypeData *expand_data = (EV_ExpandedTypeData *)it->top_task->user_data; if(expand_data == 0) { expand_data = it->top_task->user_data = push_array(arena, EV_ExpandedTypeData, 1); expand_data->type = e_type_from_key(type_key); } switch(task_idx) { //- rjf: step 0 -> generate opener symbol case 0: { if(expand_data->type->flags & E_TypeFlag_StubSingleLineExpansion) { *out_string = push_str8f(arena, "%S...%S", expansion_opener_symbol, expansion_closer_symbol); } else { need_pop = 0; expand_data->expand_rule = e_expand_rule_from_type_key(type_key); expand_data->expand_info = expand_data->expand_rule->info(arena, eval, params->filter); *out_string = expansion_opener_symbol; } }break; default: //- rjf: last step -> generate closer symbol if(task_idx == expand_data->expand_info.expr_count+1) { *out_string = expansion_closer_symbol; } //- rjf: middle step -> generate new task for next thing in expansion else { E_Eval next_eval = e_eval_nil; expand_data->expand_rule->range(arena, expand_data->expand_info.user_data, eval, params->filter, r1u64(task_idx-1, task_idx), &next_eval); if(next_eval.expr != &e_expr_nil) { need_new_task = 1; need_pop = 0; new_task.params = *params; new_task.eval = next_eval; if(task_idx > 1) { *out_string = str8_lit(", "); } } else { need_pop = 0; } }break; } }break; } } //- rjf: bump task counter if(it->top_task != 0) { it->top_task->idx += 1; } //- rjf: if result is good, and we want to pop? -> pop if(result && need_pop) { EV_StringIterTask *task = it->top_task; SLLStackPop(it->top_task); SLLStackPush(it->free_task, task); } //- rjf: if result is good, and we have a new task? -> push if(result && need_new_task) { EV_StringIterTask *new_t = it->free_task; if(new_t != 0) { SLLStackPop(it->free_task); } else { new_t = push_array(arena, EV_StringIterTask, 1); } MemoryCopyStruct(new_t, &new_task); new_t->depth = top_task_depth + 1*(!need_pop); SLLStackPush(it->top_task, new_t); new_t->idx = 0; } return result; } ================================================ FILE: src/eval_visualization/eval_visualization_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_VISUALIZATION_CORE_H #define EVAL_VISUALIZATION_CORE_H //////////////////////////////// //~ rjf: Key Type (Uniquely Refers To One Tree Node) typedef struct EV_Key EV_Key; struct EV_Key { U64 parent_hash; U64 child_id; }; //////////////////////////////// //~ rjf: Visualization State Type //- rjf: expand hash table & tree typedef struct EV_ExpandNode EV_ExpandNode; struct EV_ExpandNode { EV_ExpandNode *hash_next; EV_ExpandNode *hash_prev; EV_ExpandNode *first; EV_ExpandNode *last; EV_ExpandNode *next; EV_ExpandNode *prev; EV_ExpandNode *parent; EV_Key key; B32 expanded; }; typedef struct EV_ExpandSlot EV_ExpandSlot; struct EV_ExpandSlot { EV_ExpandNode *first; EV_ExpandNode *last; }; //- rjf: hash table for view rules typedef struct EV_KeyViewRuleNode EV_KeyViewRuleNode; struct EV_KeyViewRuleNode { EV_KeyViewRuleNode *hash_next; EV_KeyViewRuleNode *hash_prev; EV_Key key; U8 *buffer; U64 buffer_cap; U64 buffer_string_size; }; typedef struct EV_KeyViewRuleSlot EV_KeyViewRuleSlot; struct EV_KeyViewRuleSlot { EV_KeyViewRuleNode *first; EV_KeyViewRuleNode *last; }; //- rjf: view state bundle typedef struct EV_View EV_View; struct EV_View { Arena *arena; EV_ExpandSlot *expand_slots; U64 expand_slots_count; EV_ExpandNode *free_expand_node; EV_KeyViewRuleSlot *key_view_rule_slots; U64 key_view_rule_slots_count; EV_KeyViewRuleNode *free_key_view_rule_node; }; //////////////////////////////// //~ rjf: Expansion Rule Types typedef struct EV_ExpandInfo EV_ExpandInfo; struct EV_ExpandInfo { void *user_data; U64 row_count; B32 single_item; // all rows form a single "item" - a singular, but large, row B32 add_new_row; // also supports an 'add new row', as the final row, within `row_count` B32 rows_default_expanded; }; #define EV_EXPAND_RULE_INFO_FUNCTION_SIG(name) EV_ExpandInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr) #define EV_EXPAND_RULE_INFO_FUNCTION_NAME(name) ev_expand_rule_info__##name #define EV_EXPAND_RULE_INFO_FUNCTION_DEF(name) internal EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_EXPAND_RULE_INFO_FUNCTION_NAME(name)) typedef EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_ExpandRuleInfoHookFunctionType); typedef struct EV_ExpandRule EV_ExpandRule; struct EV_ExpandRule { String8 string; EV_ExpandRuleInfoHookFunctionType *info; }; typedef struct EV_ExpandRuleNode EV_ExpandRuleNode; struct EV_ExpandRuleNode { EV_ExpandRuleNode *next; EV_ExpandRule v; }; typedef struct EV_ExpandRuleSlot EV_ExpandRuleSlot; struct EV_ExpandRuleSlot { EV_ExpandRuleNode *first; EV_ExpandRuleNode *last; }; typedef struct EV_ExpandRuleTable EV_ExpandRuleTable; struct EV_ExpandRuleTable { EV_ExpandRuleSlot *slots; U64 slots_count; }; typedef struct EV_ExpandRuleTagPair EV_ExpandRuleTagPair; struct EV_ExpandRuleTagPair { EV_ExpandRule *rule; E_Expr *tag; }; //////////////////////////////// //~ rjf: Blocks typedef struct EV_Block EV_Block; struct EV_Block { // rjf: links EV_Block *first; EV_Block *last; EV_Block *next; EV_Block *prev; EV_Block *parent; // rjf: key EV_Key key; // rjf: split index, relative to parent's space U64 split_relative_idx; // rjf: evaluation info String8 string; E_Eval eval; String8 filter; E_TypeExpandInfo type_expand_info; E_TypeExpandRule *type_expand_rule; EV_ExpandInfo viz_expand_info; EV_ExpandRule *viz_expand_rule; // rjf: expansion info U64 row_count; }; typedef struct EV_BlockTree EV_BlockTree; struct EV_BlockTree { EV_Block *root; U64 total_row_count; U64 total_item_count; }; typedef struct EV_BlockRange EV_BlockRange; struct EV_BlockRange { EV_Block *block; Rng1U64 range; }; typedef struct EV_BlockRangeNode EV_BlockRangeNode; struct EV_BlockRangeNode { EV_BlockRangeNode *next; EV_BlockRange v; }; typedef struct EV_BlockRangeList EV_BlockRangeList; struct EV_BlockRangeList { EV_BlockRangeNode *first; EV_BlockRangeNode *last; U64 count; }; //////////////////////////////// //~ rjf: Rows typedef struct EV_Row EV_Row; struct EV_Row { EV_Block *block; EV_Key key; U64 visual_size; String8 edit_string; E_Eval eval; }; typedef struct EV_WindowedRowNode EV_WindowedRowNode; struct EV_WindowedRowNode { EV_WindowedRowNode *next; U64 visual_size_skipped; U64 visual_size_chopped; EV_Row row; }; typedef struct EV_WindowedRowList EV_WindowedRowList; struct EV_WindowedRowList { EV_WindowedRowNode *first; EV_WindowedRowNode *last; U64 count; U64 count_before_visual; U64 count_before_semantic; }; //////////////////////////////// //~ rjf: String Generation Types typedef U32 EV_StringFlags; enum { EV_StringFlag_ReadOnlyDisplayRules = (1<<0), EV_StringFlag_PrettyNames = (1<<1), EV_StringFlag_DisableAddresses = (1<<2), EV_StringFlag_DisableStrings = (1<<3), EV_StringFlag_DisableChars = (1<<4), EV_StringFlag_DisableStringQuotes = (1<<5), }; typedef struct EV_StringParams EV_StringParams; struct EV_StringParams { EV_StringFlags flags; U32 radix; U32 min_digits; U8 digit_group_separator; String8 filter; B32 limit_strings; U64 limit_strings_size; }; typedef struct EV_StringIterTask EV_StringIterTask; struct EV_StringIterTask { EV_StringIterTask *next; EV_StringParams params; E_Eval eval; U64 idx; S32 depth; B32 redirect_to_sets_and_structs; void *user_data; }; typedef struct EV_StringIter EV_StringIter; struct EV_StringIter { EV_StringIterTask *top_task; EV_StringIterTask *free_task; }; //////////////////////////////// //~ rjf: Nil/Identity View Rule Hooks EV_EXPAND_RULE_INFO_FUNCTION_DEF(nil); //////////////////////////////// //~ rjf: Globals global read_only EV_ExpandRule ev_nil_expand_rule = { {0}, EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), }; thread_static EV_ExpandRuleTable *ev_view_rule_info_table = 0; global read_only EV_Block ev_nil_block = { &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, {{0}, {0}, {0}, &e_expr_nil, &e_irnode_nil}, {0}, {0}, &e_type_expand_rule__default, {0}, &ev_nil_expand_rule, }; //////////////////////////////// //~ rjf: Key Functions internal EV_Key ev_key_make(U64 parent_hash, U64 child_id); internal EV_Key ev_key_zero(void); internal EV_Key ev_key_root(void); internal B32 ev_key_match(EV_Key a, EV_Key b); internal U64 ev_hash_from_seed_string(U64 seed, String8 string); internal U64 ev_hash_from_key(EV_Key key); //////////////////////////////// //~ rjf: Type Info Helpers //- rjf: type info -> expandability/editablity internal E_TypeKey ev_expansion_type_from_key(E_TypeKey type_key); internal B32 ev_type_key_and_mode_is_expandable(E_TypeKey type_key, E_Mode mode); internal B32 ev_type_key_is_editable(E_TypeKey type_key); //////////////////////////////// //~ rjf: View Functions //- rjf: creation / deletion internal EV_View *ev_view_alloc(void); internal void ev_view_release(EV_View *view); //- rjf: lookups / mutations internal EV_ExpandNode *ev_expand_node_from_key(EV_View *view, EV_Key key); internal B32 ev_expansion_from_key(EV_View *view, EV_Key key); internal String8 ev_view_rule_from_key(EV_View *view, EV_Key key); internal void ev_key_set_expansion(EV_View *view, EV_Key parent_key, EV_Key key, B32 expanded); internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_string); //////////////////////////////// //~ rjf: View Rule Info Table Building / Selection / Lookups internal void ev_expand_rule_table_push(Arena *arena, EV_ExpandRuleTable *table, EV_ExpandRule *info); #define ev_expand_rule_table_push_new(arena, table, ...) ev_expand_rule_table_push((arena), (table), &(EV_ExpandRule){__VA_ARGS__}) internal void ev_select_expand_rule_table(EV_ExpandRuleTable *table); internal EV_ExpandRule *ev_expand_rule_from_string(String8 string); internal EV_ExpandRule *ev_expand_rule_from_type_key(E_TypeKey type_key); //////////////////////////////// //~ rjf: Block Building internal EV_BlockTree ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval root_eval); internal U64 ev_depth_from_block(EV_Block *block); //////////////////////////////// //~ rjf: Block Coordinate Spaces internal U64 ev_block_id_from_num(EV_Block *block, U64 num); internal U64 ev_block_num_from_id(EV_Block *block, U64 id); internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockTree *block_tree); internal EV_BlockRange ev_block_range_from_num(EV_BlockRangeList *block_ranges, U64 num); internal EV_Key ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num); internal U64 ev_num_from_key(EV_BlockRangeList *block_ranges, EV_Key key); internal U64 ev_vnum_from_num(EV_BlockRangeList *block_ranges, U64 num); internal U64 ev_num_from_vnum(EV_BlockRangeList *block_ranges, U64 vidx); //////////////////////////////// //~ rjf: Row Building internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 vnum_range); internal EV_Row *ev_row_from_num(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, U64 num); internal EV_WindowedRowList ev_rows_from_num_range(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 num_range); internal B32 ev_eval_is_expandable(E_Eval eval); internal B32 ev_row_is_expandable(EV_Row *row); internal B32 ev_row_is_editable(EV_Row *row); //////////////////////////////// //~ rjf: Stringification //- rjf: leaf stringification internal String8 ev_string_from_ascii_value(Arena *arena, U8 val); internal String8 ev_string_from_hresult_facility_code(U32 code); internal String8 ev_string_from_hresult_code(U32 code); internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringParams *params, E_Eval eval); internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw); //- rjf: tree stringification iterator internal EV_StringIter *ev_string_iter_begin(Arena *arena, E_Eval eval, EV_StringParams *params); internal B32 ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string); #endif // EVAL_VISUALIZATION_CORE_H ================================================ FILE: src/eval_visualization/eval_visualization_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "eval_visualization_core.c" ================================================ FILE: src/eval_visualization/eval_visualization_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_VISUALIZATION_INC_H #define EVAL_VISUALIZATION_INC_H #include "eval_visualization_core.h" #endif // EVAL_VISUALIZATION_INC_H ================================================ FILE: src/file_stream/file_stream.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xfffa00ff //////////////////////////////// //~ rjf: Top-Level API internal void fs_init(void) { Arena *arena = arena_alloc(); fs_shared = push_array(arena, FS_Shared, 1); fs_shared->arena = arena; fs_shared->change_gen = 1; fs_shared->slots_count = 1024; fs_shared->slots = push_array(arena, FS_Slot, fs_shared->slots_count); fs_shared->stripes = stripe_array_alloc(arena); } //////////////////////////////// //~ rjf: Change Generation internal U64 fs_change_gen(void) { return ins_atomic_u64_eval(&fs_shared->change_gen); } //////////////////////////////// //~ rjf: Cache Interaction internal AC_Artifact fs_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); //- rjf: unpack key String8 path = {0}; Rng1U64 range = {0}; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &path.size); path.str = push_array(scratch.arena, U8, path.size); key_read_off += str8_deserial_read(key, key_read_off, path.str, path.size, 1); key_read_off += str8_deserial_read_struct(key, key_read_off, &range); } //- rjf: measure file properties *before* read B32 file_is_good = 0; FileProperties pre_props = {0}; if(lane_idx() == 0) { pre_props = os_properties_from_file_path(path); file_is_good = (pre_props.modified != 0); } lane_sync_u64(&file_is_good, 0); //- rjf: setup output data Arena *data_arena = 0; U64 data_buffer_size = 0; U8 *data_buffer = 0; if(file_is_good) { if(lane_idx() == 0) { U64 range_size = dim_1u64(range); U64 read_size = Min(pre_props.size - range.min, range_size); U64 data_arena_size = read_size+ARENA_HEADER_SIZE; data_arena_size += KB(4)-1; data_arena_size -= data_arena_size%KB(4); data_arena = arena_alloc(.reserve_size = data_arena_size, .commit_size = data_arena_size); data_buffer_size = read_size; data_buffer = push_array_no_zero(data_arena, U8, data_buffer_size); } lane_sync_u64(&data_buffer, 0); lane_sync_u64(&data_buffer_size, 0); } //- rjf: open file OS_Handle file = {0}; if(file_is_good) { if(lane_idx() == 0) { file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite, path); } lane_sync_u64(&file, 0); } B32 file_handle_is_valid = !os_handle_match(os_handle_zero(), file); //- rjf: do read U64 total_bytes_read = 0; if(file_handle_is_valid) { U64 *total_bytes_read_ptr = 0; if(lane_idx() == 0) { total_bytes_read_ptr = &total_bytes_read; } lane_sync_u64(&total_bytes_read_ptr, 0); ProfScope("read \"%.*s\" [0x%I64x, 0x%I64x)", str8_varg(path), range.min, range.max) { Rng1U64 lane_read_range = lane_range(data_buffer_size); U64 bytes_read = os_file_read(file, shift_1u64(lane_read_range, range.min), data_buffer + lane_read_range.min); ins_atomic_u64_add_eval(total_bytes_read_ptr, bytes_read); } lane_sync(); lane_sync_u64(&total_bytes_read, 0); } //- rjf: close file if(file_handle_is_valid) { if(lane_idx() == 0) { os_file_close(file); } } //- rjf: measure file properties *after* read FileProperties post_props = {0}; if(lane_idx() == 0) { post_props = os_properties_from_file_path(path); } //- rjf: form content key C_Key content_key = {0}; { content_key.id.u128[0] = u128_hash_from_str8(key); } //- rjf: abort if modification timestamps or sizes differ - we did not successfully read the file; // otherwise submit data B32 read_good = 0; if(file_is_good) { if(lane_idx() == 0) { read_good = (pre_props.modified == post_props.modified && pre_props.size == post_props.size && data_buffer_size == total_bytes_read && (file_handle_is_valid || pre_props.flags & FilePropertyFlag_IsFolder)); if(!read_good) { retry_out[0] = 1; ProfScope("abort") { arena_release(data_arena); MemoryZeroStruct(&content_key); } } else { ProfScope("submit") { c_submit_data(content_key, &data_arena, str8(data_buffer, data_buffer_size)); } } } lane_sync(); } //- rjf: if the read was good, record this path's timestamp in this layer's path info cache U64 path_hash = u64_hash_from_str8(path); if(lane_idx() == 0 && read_good) { U64 slot_idx = path_hash%fs_shared->slots_count; FS_Slot *slot = &fs_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&fs_shared->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 1) { FS_Node *node = 0; for(FS_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->path, path, 0)) { node = n; break; } } if(node == 0) { node = stripe->free; if(node) { stripe->free = node->next; } else { node = push_array_no_zero(stripe->arena, FS_Node, 1); } MemoryZeroStruct(node); node->path = str8_copy(stripe->arena, path); SLLQueuePush(slot->first, slot->last, node); } node->last_modified_timestamp = pre_props.modified; node->size = pre_props.size; } } lane_sync(); //- rjf: bundle content key as artifact AC_Artifact artifact = {0}; StaticAssert(sizeof(content_key) == sizeof(artifact), artifact_key_size_check); MemoryCopyStruct(&artifact, &content_key); scratch_end(scratch); ProfEnd(); return artifact; } internal void fs_artifact_destroy(AC_Artifact artifact) { C_Key key = {0}; MemoryCopyStruct(&key, &artifact); c_close_key(key); } internal C_Key fs_key_from_path_range(String8 path, Rng1U64 range, U64 endt_us) { C_Key result = {0}; Temp scratch = scratch_begin(0, 0); Access *access = access_open(); { String8List key_parts = {0}; str8_list_push(scratch.arena, &key_parts, str8_struct(&path.size)); str8_list_push(scratch.arena, &key_parts, path); str8_list_push(scratch.arena, &key_parts, str8_struct(&range)); String8 key = str8_list_join(scratch.arena, &key_parts, 0); //- rjf: find generation number for this key U64 gen = 0; { U64 hash = u64_hash_from_str8(path); U64 slot_idx = hash%fs_shared->slots_count; FS_Slot *slot = &fs_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&fs_shared->stripes, slot_idx); RWMutexScope(stripe->rw_mutex, 0) { for(FS_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(path, n->path, 0)) { gen = n->gen; break; } } } } //- rjf: map to artifact AC_Artifact artifact = ac_artifact_from_key(access, key, fs_artifact_create, fs_artifact_destroy, endt_us, .gen = gen, .flags = AC_Flag_Wide); MemoryCopyStruct(&result, &artifact); } access_close(access); scratch_end(scratch); return result; } internal U128 fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us) { U128 hash = {0}; { C_Key key = fs_key_from_path_range(path, range, endt_us); for EachIndex(rewind_idx, C_KEY_HASH_HISTORY_COUNT) { hash = c_hash_from_key(key, rewind_idx); if(!u128_match(hash, u128_zero())) { break; } } } return hash; } //////////////////////////////// //~ rjf: Asynchronous Tick internal void fs_async_tick(void) { ProfBeginFunction(); //- rjf: detect changed timestamps for active paths { Rng1U64 range = lane_range(fs_shared->slots_count); for EachInRange(slot_idx, range) { FS_Slot *slot = &fs_shared->slots[slot_idx]; Stripe *stripe = stripe_from_slot_idx(&fs_shared->stripes, slot_idx); for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { B32 found_work = 0; RWMutexScope(stripe->rw_mutex, write_mode) { for(FS_Node *n = slot->first; n != 0; n = n->next) { FileProperties props = os_properties_from_file_path(n->path); if(props.modified != n->last_modified_timestamp) { found_work = 1; if(write_mode) { n->gen += 1; ins_atomic_u64_inc_eval(&fs_shared->change_gen); } } } } if(!found_work) { break; } } } } ProfEnd(); } ================================================ FILE: src/file_stream/file_stream.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FILE_STREAM_H #define FILE_STREAM_H //////////////////////////////// //~ rjf: Path Cache typedef struct FS_Node FS_Node; struct FS_Node { FS_Node *next; String8 path; U64 gen; U64 last_modified_timestamp; U64 size; }; typedef struct FS_Slot FS_Slot; struct FS_Slot { FS_Node *first; FS_Node *last; }; //////////////////////////////// //~ rjf: Shared State Bundle typedef struct FS_Shared FS_Shared; struct FS_Shared { Arena *arena; U64 change_gen; U64 slots_count; FS_Slot *slots; StripeArray stripes; }; //////////////////////////////// //~ rjf: Globals global FS_Shared *fs_shared = 0; //////////////////////////////// //~ rjf: Top-Level API internal void fs_init(void); //////////////////////////////// //~ rjf: Change Generation internal U64 fs_change_gen(void); //////////////////////////////// //~ rjf: Artifact Cache Hooks / Accessing API internal AC_Artifact fs_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void fs_artifact_destroy(AC_Artifact artifact); internal C_Key fs_key_from_path_range(String8 path, Rng1U64 range, U64 endt_us); internal U128 fs_hash_from_path_range(String8 path, Rng1U64 range, U64 endt_us); #define fs_key_from_path(path, endt_us) fs_key_from_path_range((path), r1u64(0, max_U64), (endt_us)) #define fs_hash_from_path(path, endt_us) fs_hash_from_path_range((path), r1u64(0, max_U64), (endt_us)) //////////////////////////////// //~ rjf: Asynchronous Tick internal void fs_async_tick(void); #endif // FILE_STREAM_H ================================================ FILE: src/font_cache/font_cache.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Basic Functions #if !defined(XXH_IMPLEMENTATION) # define XXH_IMPLEMENTATION # define XXH_STATIC_LINKING_ONLY # include "third_party/xxHash/xxhash.h" #endif internal U128 fnt_hash_from_string(String8 string) { union { XXH128_hash_t xxhash; U128 u128; } hash; hash.xxhash = XXH3_128bits(string.str, string.size); return hash.u128; } internal U64 fnt_little_hash_from_string(U64 seed, String8 string) { U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); return result; } internal Vec2S32 fnt_vertex_from_corner(Corner corner) { Vec2S32 result = {0}; switch(corner) { default: break; case Corner_00:{result = v2s32(0, 0);}break; case Corner_01:{result = v2s32(0, 1);}break; case Corner_10:{result = v2s32(1, 0);}break; case Corner_11:{result = v2s32(1, 1);}break; } return result; } //////////////////////////////// //~ rjf: Font Tags internal FNT_Tag fnt_tag_zero(void) { FNT_Tag result = {0}; return result; } internal B32 fnt_tag_match(FNT_Tag a, FNT_Tag b) { return a.u64[0] == b.u64[0] && a.u64[1] == b.u64[1]; } internal FP_Handle fnt_handle_from_tag(FNT_Tag tag) { ProfBeginFunction(); U64 slot_idx = tag.u64[1] % fnt_state->font_hash_table_size; FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&tag, &n->tag)) { existing_node = n; break; } } } FP_Handle result = {0}; if(existing_node != 0) { result = existing_node->handle; } ProfEnd(); return result; } internal FP_Metrics fnt_fp_metrics_from_tag(FNT_Tag tag) { ProfBeginFunction(); U64 slot_idx = tag.u64[1] % fnt_state->font_hash_table_size; FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&tag, &n->tag)) { existing_node = n; break; } } } FP_Metrics result = {0}; if(existing_node != 0) { result = existing_node->metrics; } ProfEnd(); return result; } internal FNT_Tag fnt_tag_from_path(String8 path) { ProfBeginFunction(); //- rjf: produce tag from hash of path FNT_Tag result = {0}; { U128 hash = fnt_hash_from_string(path); MemoryCopy(&result, &hash, sizeof(result)); result.u64[1] |= bit64; } //- rjf: tag -> slot index U64 slot_idx = result.u64[1] % fnt_state->font_hash_table_size; //- rjf: slot * tag -> existing node FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&result, &n->tag)) { existing_node = n; break; } } } //- rjf: allocate & push new node if we don't have an existing one if(existing_node == 0) { FP_Handle handle = fp_font_open(path); FNT_FontHashSlot *slot = &fnt_state->font_hash_table[slot_idx]; existing_node = push_array(fnt_state->permanent_arena, FNT_FontHashNode, 1); existing_node->tag = result; existing_node->handle = handle; existing_node->metrics = fp_metrics_from_font(existing_node->handle); existing_node->path = push_str8_copy(fnt_state->permanent_arena, path); SLLQueuePush_N(slot->first, slot->last, existing_node, hash_next); } //- rjf: tag result must be zero if this is not a valid font if(fp_handle_match(existing_node->handle, fp_handle_zero())) { MemoryZeroStruct(&result); } //- rjf: return ProfEnd(); return result; } internal FNT_Tag fnt_tag_from_static_data_string(String8 *data_ptr) { ProfBeginFunction(); //- rjf: produce tag hash of ptr FNT_Tag result = {0}; { U128 hash = fnt_hash_from_string(str8((U8 *)&data_ptr, sizeof(String8 *))); MemoryCopy(&result, &hash, sizeof(result)); result.u64[1] &= ~bit64; } //- rjf: tag -> slot index U64 slot_idx = result.u64[1] % fnt_state->font_hash_table_size; //- rjf: slot * tag -> existing node FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&result, &n->tag)) { existing_node = n; break; } } } //- rjf: allocate & push new node if we don't have an existing one FNT_FontHashNode *new_node = 0; if(existing_node == 0) { FNT_FontHashSlot *slot = &fnt_state->font_hash_table[slot_idx]; new_node = push_array(fnt_state->permanent_arena, FNT_FontHashNode, 1); new_node->tag = result; new_node->handle = fp_font_open_from_static_data_string(data_ptr); new_node->metrics = fp_metrics_from_font(new_node->handle); new_node->path = str8_lit(""); SLLQueuePush_N(slot->first, slot->last, new_node, hash_next); } //- rjf: return ProfEnd(); return result; } internal String8 fnt_path_from_tag(FNT_Tag tag) { //- rjf: tag -> slot index U64 slot_idx = tag.u64[1] % fnt_state->font_hash_table_size; //- rjf: slot * tag -> existing node FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&tag, &n->tag)) { existing_node = n; break; } } } //- rjf: existing node -> path String8 result = {0}; if(existing_node != 0) { result = existing_node->path; } return result; } //////////////////////////////// //~ rjf: Atlas internal Rng2S16 fnt_atlas_region_alloc(Arena *arena, FNT_Atlas *atlas, Vec2S16 needed_size) { //- rjf: find node with best-fit size Vec2S16 region_p0 = {0}; Vec2S16 region_sz = {0}; Corner node_corner = Corner_Invalid; FNT_AtlasRegionNode *node = 0; { Vec2S16 n_supported_size = atlas->root_dim; for(FNT_AtlasRegionNode *n = atlas->root, *next = 0; n != 0; n = next, next = 0) { // rjf: we've traversed to a taken node. if(n->flags & FNT_AtlasRegionNodeFlag_Taken) { break; } // rjf: calculate if this node can be allocated (all children are non-allocated) B32 n_can_be_allocated = (n->num_allocated_descendants == 0); // rjf: fill size if(n_can_be_allocated) { region_sz = n_supported_size; } // rjf: calculate size of this node's children Vec2S16 child_size = v2s16(n_supported_size.x/2, n_supported_size.y/2); // rjf: find best next child FNT_AtlasRegionNode *best_child = 0; if(child_size.x >= needed_size.x && child_size.y >= needed_size.y) { for(Corner corner = (Corner)0; corner < Corner_COUNT; corner = (Corner)(corner+1)) { if(n->children[corner] == 0) { n->children[corner] = push_array(arena, FNT_AtlasRegionNode, 1); n->children[corner]->parent = n; n->children[corner]->max_free_size[Corner_00] = n->children[corner]->max_free_size[Corner_01] = n->children[corner]->max_free_size[Corner_10] = n->children[corner]->max_free_size[Corner_11] = v2s16(child_size.x/2, child_size.y/2); } if(n->max_free_size[corner].x >= needed_size.x && n->max_free_size[corner].y >= needed_size.y) { best_child = n->children[corner]; node_corner = corner; Vec2S32 side_vertex = fnt_vertex_from_corner(corner); region_p0.x += side_vertex.x*child_size.x; region_p0.y += side_vertex.y*child_size.y; break; } } } // rjf: resolve node to this node if it can be allocated and children // don't fit, or keep going to the next best child if(n_can_be_allocated && best_child == 0) { node = n; } else { next = best_child; n_supported_size = child_size; } } } //- rjf: we're taking the subtree rooted by `node`. mark up all parents if(node != 0 && node_corner != Corner_Invalid) { node->flags |= FNT_AtlasRegionNodeFlag_Taken; if(node->parent != 0) { MemoryZeroStruct(&node->parent->max_free_size[node_corner]); } for(FNT_AtlasRegionNode *p = node->parent; p != 0; p = p->parent) { p->num_allocated_descendants += 1; FNT_AtlasRegionNode *parent = p->parent; if(parent != 0) { Corner p_corner = (p == parent->children[Corner_00] ? Corner_00 : p == parent->children[Corner_01] ? Corner_01 : p == parent->children[Corner_10] ? Corner_10 : p == parent->children[Corner_11] ? Corner_11 : Corner_Invalid); if(p_corner == Corner_Invalid) { InvalidPath; } parent->max_free_size[p_corner].x = Max(Max(p->max_free_size[Corner_00].x, p->max_free_size[Corner_01].x), Max(p->max_free_size[Corner_10].x, p->max_free_size[Corner_11].x)); parent->max_free_size[p_corner].y = Max(Max(p->max_free_size[Corner_00].y, p->max_free_size[Corner_01].y), Max(p->max_free_size[Corner_10].y, p->max_free_size[Corner_11].y)); } } } //- rjf: fill rectangular region & return Rng2S16 result = {0}; result.p0 = region_p0; result.p1 = add_2s16(region_p0, region_sz); return result; } internal void fnt_atlas_region_release(FNT_Atlas *atlas, Rng2S16 region) { //- rjf: extract region size Vec2S16 region_size = v2s16(region.x1 - region.x0, region.y1 - region.y0); //- rjf: map region to associated node Vec2S16 calc_region_size = {0}; FNT_AtlasRegionNode *node = 0; Corner node_corner = Corner_Invalid; { Vec2S16 n_p0 = v2s16(0, 0); Vec2S16 n_sz = atlas->root_dim; for(FNT_AtlasRegionNode *n = atlas->root, *next = 0; n != 0; n = next) { // rjf: is the region within this node's boundaries? (either this node, or a descendant) if(n_p0.x <= region.p0.x && region.p0.x < n_p0.x+n_sz.x && n_p0.y <= region.p0.y && region.p0.y < n_p0.y+n_sz.y) { // rjf: check the region against this node if(region.p0.x == n_p0.x && region.p0.y == n_p0.y && region_size.x == n_sz.x && region_size.y == n_sz.y) { node = n; calc_region_size = n_sz; break; } // rjf: check the region against children & iterate else { Vec2S16 r_midpoint = v2s16(region.p0.x + region_size.x/2, region.p0.y + region_size.y/2); Vec2S16 n_midpoint = v2s16(n_p0.x + n_sz.x/2, n_p0.y + n_sz.y/2); Corner next_corner = Corner_Invalid; if(r_midpoint.x <= n_midpoint.x && r_midpoint.y <= n_midpoint.y) { next_corner = Corner_00; } else if(r_midpoint.x <= n_midpoint.x && n_midpoint.y <= r_midpoint.y) { next_corner = Corner_01; } else if(n_midpoint.x <= r_midpoint.x && r_midpoint.y <= n_midpoint.y) { next_corner = Corner_10; } else if(n_midpoint.x <= r_midpoint.x && n_midpoint.y <= r_midpoint.y) { next_corner = Corner_11; } next = n->children[next_corner]; node_corner = next_corner; n_sz.x /= 2; n_sz.y /= 2; Vec2S32 side_vertex = fnt_vertex_from_corner(node_corner); n_p0.x += side_vertex.x*n_sz.x; n_p0.y += side_vertex.y*n_sz.y; } } else { break; } } } //- rjf: free node if(node != 0 && node_corner != Corner_Invalid) { node->flags &= ~FNT_AtlasRegionNodeFlag_Taken; if(node->parent != 0) { node->parent->max_free_size[node_corner] = calc_region_size; } for(FNT_AtlasRegionNode *p = node->parent; p != 0; p = p->parent) { p->num_allocated_descendants -= 1; FNT_AtlasRegionNode *parent = p->parent; if(parent != 0) { Corner p_corner = (p == parent->children[Corner_00] ? Corner_00 : p == parent->children[Corner_01] ? Corner_01 : p == parent->children[Corner_10] ? Corner_10 : p == parent->children[Corner_11] ? Corner_11 : Corner_Invalid); if(p_corner == Corner_Invalid) { InvalidPath; } parent->max_free_size[p_corner].x = Max(Max(p->max_free_size[Corner_00].x, p->max_free_size[Corner_01].x), Max(p->max_free_size[Corner_10].x, p->max_free_size[Corner_11].x)); parent->max_free_size[p_corner].y = Max(Max(p->max_free_size[Corner_00].y, p->max_free_size[Corner_01].y), Max(p->max_free_size[Corner_10].y, p->max_free_size[Corner_11].y)); } } } } //////////////////////////////// //~ rjf: Piece Type Functions internal FNT_Piece * fnt_piece_chunk_list_push_new(Arena *arena, FNT_PieceChunkList *list, U64 cap) { FNT_PieceChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, FNT_PieceChunkNode, 1); node->v = push_array_no_zero(arena, FNT_Piece, cap); node->cap = cap; SLLQueuePush(list->first, list->last, node); list->node_count += 1; } FNT_Piece *result = node->v + node->count; node->count += 1; list->total_piece_count += 1; return result; } internal void fnt_piece_chunk_list_push(Arena *arena, FNT_PieceChunkList *list, U64 cap, FNT_Piece *piece) { FNT_Piece *new_piece = fnt_piece_chunk_list_push_new(arena, list, cap); MemoryCopyStruct(new_piece, piece); } internal FNT_PieceArray fnt_piece_array_from_chunk_list(Arena *arena, FNT_PieceChunkList *list) { FNT_PieceArray array = {0}; array.count = list->total_piece_count; array.v = push_array_no_zero(arena, FNT_Piece, array.count); U64 write_idx = 0; for(FNT_PieceChunkNode *node = list->first; node != 0; node = node->next) { MemoryCopy(array.v + write_idx, node->v, node->count * sizeof(FNT_Piece)); write_idx += node->count; } return array; } internal FNT_PieceArray fnt_piece_array_copy(Arena *arena, FNT_PieceArray *src) { FNT_PieceArray dst = {0}; dst.count = src->count; dst.v = push_array_no_zero(arena, FNT_Piece, dst.count); MemoryCopy(dst.v, src->v, sizeof(FNT_Piece)*dst.count); return dst; } //////////////////////////////// //~ rjf: Cache Usage internal FNT_Hash2StyleRasterCacheNode * fnt_hash2style_from_tag_size_flags(FNT_Tag tag, F32 size, FNT_RasterFlags flags) { //- rjf: tag * size -> style hash U64 style_hash = {0}; { F64 size_f64 = size; U64 buffer[] = { tag.u64[0], tag.u64[1], *(U64 *)(&size_f64), (U64)flags, }; style_hash = fnt_little_hash_from_string(5381, str8((U8 *)buffer, sizeof(buffer))); } //- rjf: style hash -> style node FNT_Hash2StyleRasterCacheNode *hash2style_node = 0; { U64 slot_idx = style_hash%fnt_state->hash2style_slots_count; FNT_Hash2StyleRasterCacheSlot *slot = &fnt_state->hash2style_slots[slot_idx]; for(FNT_Hash2StyleRasterCacheNode *n = slot->first; n != 0; n = n->hash_next) { if(n->style_hash == style_hash) { hash2style_node = n; break; } } if(Unlikely(hash2style_node == 0)) { FNT_Metrics metrics = fnt_metrics_from_tag_size(tag, size); hash2style_node = push_array(fnt_state->raster_arena, FNT_Hash2StyleRasterCacheNode, 1); DLLPushBack_NP(slot->first, slot->last, hash2style_node, hash_next, hash_prev); hash2style_node->style_hash = style_hash; hash2style_node->ascent = metrics.ascent; hash2style_node->descent = metrics.descent; hash2style_node->utf8_class1_direct_map = push_array_no_zero(fnt_state->raster_arena, FNT_RasterCacheInfo, 256); hash2style_node->hash2info_slots_count = 1024; hash2style_node->hash2info_slots = push_array(fnt_state->raster_arena, FNT_Hash2InfoRasterCacheSlot, hash2style_node->hash2info_slots_count); } } return hash2style_node; } internal FNT_Run fnt_run_from_string(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, String8 string) { //- rjf: map tag/size to style node FNT_Hash2StyleRasterCacheNode *hash2style_node = fnt_hash2style_from_tag_size_flags(tag, size, flags); //- rjf: set up this style's run cache if needed if(hash2style_node->run_slots_frame_index != fnt_state->frame_index) { hash2style_node->run_slots_count = 1024; hash2style_node->run_slots = push_array(fnt_state->frame_arena, FNT_RunCacheSlot, hash2style_node->run_slots_count); hash2style_node->run_slots_frame_index = fnt_state->frame_index; } //- rjf: unpack run params U64 run_hash = fnt_little_hash_from_string(5381, string); U64 run_slot_idx = run_hash%hash2style_node->run_slots_count; FNT_RunCacheSlot *run_slot = &hash2style_node->run_slots[run_slot_idx]; //- rjf: find existing run node for this string FNT_RunCacheNode *run_node = 0; { for(FNT_RunCacheNode *n = run_slot->first; n != 0; n = n->next) { if(str8_match(n->string, string, 0)) { run_node = n; break; } } } //- rjf: no run node? -> cache miss - compute & build & fill node if possible B32 run_is_cacheable = 1; FNT_Run run = {0}; if(run_node) { run = run_node->run; } else { //- rjf: decode string & produce run pieces FNT_PieceChunkList piece_chunks = {0}; Vec2F32 dim = {0}; B32 font_handle_mapped_on_miss = 0; FP_Handle font_handle = {0}; U64 piece_substring_start_idx = 0; U64 piece_substring_end_idx = 0; for(U64 idx = 0; idx <= string.size;) { //- rjf: decode next codepoint & get piece substring, or continuation rule U8 byte = (idx < string.size ? string.str[idx] : 0); B32 need_another_codepoint = 0; if(byte == 0) { idx += 1; } else switch(utf8_class[byte>>3]) { case 1: { idx += 1; piece_substring_end_idx += 1; need_another_codepoint = 0; }break; default: { UnicodeDecode decode = utf8_decode(string.str+idx, string.size-idx); idx += decode.inc; piece_substring_end_idx += decode.inc; need_another_codepoint = 0; }break; } //- rjf: need another codepoint, or have no substring? -> continue if(need_another_codepoint || piece_substring_end_idx == piece_substring_start_idx) { continue; } //- rjf: do not need another codepoint? -> grab substring, bump piece start idx String8 piece_substring = str8_substr(string, r1u64(piece_substring_start_idx, piece_substring_end_idx)); piece_substring_start_idx = idx; piece_substring_end_idx = idx; //- rjf: determine if this piece is a tab - if so, use space info to draw B32 is_tab = (piece_substring.size == 1 && piece_substring.str[0] == '\t'); if(is_tab) { run_is_cacheable = 0; piece_substring = str8_lit(" "); } //- rjf: piece substring -> raster cache info FNT_RasterCacheInfo *info = 0; U64 piece_hash = 0; { // rjf: fast path for utf8 class 1 -> direct map if(piece_substring.size == 1 && hash2style_node->utf8_class1_direct_map_mask[piece_substring.str[0]/64] & (1ull<<(piece_substring.str[0]%64))) { info = &hash2style_node->utf8_class1_direct_map[piece_substring.str[0]]; } // rjf: more general, slower path for other glyphs if(piece_substring.size > 1) { piece_hash = fnt_little_hash_from_string(5381, piece_substring); U64 slot_idx = piece_hash%hash2style_node->hash2info_slots_count; FNT_Hash2InfoRasterCacheSlot *slot = &hash2style_node->hash2info_slots[slot_idx]; for(FNT_Hash2InfoRasterCacheNode *node = slot->first; node != 0; node = node->hash_next) { if(node->hash == piece_hash) { info = &node->info; break; } } } } //- rjf: no info found -> miss... fill this hash in the cache if(info == 0) { Temp scratch = scratch_begin(0, 0); // rjf: grab font handle for this tag if we don't have one already if(font_handle_mapped_on_miss == 0) { font_handle_mapped_on_miss = 1; // rjf: tag -> font slot index U64 font_slot_idx = tag.u64[1] % fnt_state->font_hash_table_size; // rjf: tag * slot -> existing node FNT_FontHashNode *existing_node = 0; { for(FNT_FontHashNode *n = fnt_state->font_hash_table[font_slot_idx].first; n != 0 ; n = n->hash_next) { if(MemoryMatchStruct(&n->tag, &tag)) { existing_node = n; break; } } } // rjf: existing node -> font handle if(existing_node != 0) { font_handle = existing_node->handle; } } // rjf: call into font provider to rasterize this substring FP_RasterResult raster = {0}; if(size > 0) { FP_RasterFlags fp_flags = 0; if(flags & FNT_RasterFlag_Smooth) { fp_flags |= FP_RasterFlag_Smooth; } if(flags & FNT_RasterFlag_Hinted) { fp_flags |= FP_RasterFlag_Hinted; } raster = fp_raster(scratch.arena, font_handle, floor_f32(size), flags, piece_substring); } // rjf: allocate portion of an atlas to upload the rasterization S16 chosen_atlas_num = 0; FNT_Atlas *chosen_atlas = 0; Rng2S16 chosen_atlas_region = {0}; if(raster.atlas_dim.x != 0 && raster.atlas_dim.y != 0) { U64 num_atlases = 0; for(FNT_Atlas *atlas = fnt_state->first_atlas;; atlas = atlas->next, num_atlases += 1) { // rjf: create atlas if needed if(atlas == 0 && num_atlases < 64) { atlas = push_array(fnt_state->raster_arena, FNT_Atlas, 1); DLLPushBack(fnt_state->first_atlas, fnt_state->last_atlas, atlas); atlas->root_dim = v2s16(1024, 1024); atlas->root = push_array(fnt_state->raster_arena, FNT_AtlasRegionNode, 1); atlas->root->max_free_size[Corner_00] = atlas->root->max_free_size[Corner_01] = atlas->root->max_free_size[Corner_10] = atlas->root->max_free_size[Corner_11] = v2s16(atlas->root_dim.x/2, atlas->root_dim.y/2); atlas->texture = r_tex2d_alloc(R_ResourceKind_Dynamic, v2s32((S32)atlas->root_dim.x, (S32)atlas->root_dim.y), R_Tex2DFormat_RGBA8, 0); } // rjf: allocate from atlas if(atlas != 0) { Vec2S16 needed_dimensions = v2s16(raster.atlas_dim.x + 2, raster.atlas_dim.y + 2); chosen_atlas_region = fnt_atlas_region_alloc(fnt_state->raster_arena, atlas, needed_dimensions); if(chosen_atlas_region.x1 != chosen_atlas_region.x0) { chosen_atlas = atlas; chosen_atlas_num = (S32)num_atlases; break; } } else { break; } } } // rjf: upload rasterization to allocated region of atlas texture memory if(chosen_atlas != 0) { Rng2S32 subregion = { chosen_atlas_region.x0, chosen_atlas_region.y0, chosen_atlas_region.x0 + raster.atlas_dim.x, chosen_atlas_region.y0 + raster.atlas_dim.y }; r_fill_tex2d_region(chosen_atlas->texture, subregion, raster.atlas); } // rjf: allocate & fill & push node { if(piece_substring.size == 1) { info = &hash2style_node->utf8_class1_direct_map[piece_substring.str[0]]; hash2style_node->utf8_class1_direct_map_mask[piece_substring.str[0]/64] |= (1ull<<(piece_substring.str[0]%64)); } else { U64 slot_idx = piece_hash%hash2style_node->hash2info_slots_count; FNT_Hash2InfoRasterCacheSlot *slot = &hash2style_node->hash2info_slots[slot_idx]; FNT_Hash2InfoRasterCacheNode *node = push_array_no_zero(fnt_state->raster_arena, FNT_Hash2InfoRasterCacheNode, 1); DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev); node->hash = piece_hash; info = &node->info; } if(info != 0) { info->subrect = chosen_atlas_region; info->atlas_num = chosen_atlas_num; info->raster_dim = raster.atlas_dim; info->advance = raster.advance; } } scratch_end(scratch); } //- rjf: push piece for this raster portion if(info != 0) { // rjf: find atlas FNT_Atlas *atlas = 0; { if(info->subrect.x1 != 0 && info->subrect.y1 != 0) { S32 num = 0; for(FNT_Atlas *a = fnt_state->first_atlas; a != 0; a = a->next, num += 1) { if(info->atlas_num == num) { atlas = a; break; } } } } // rjf: on tabs -> expand advance F32 advance = info->advance; if(is_tab) { advance = floor_f32(tab_size_px) - mod_f32(floor_f32(base_align_px), floor_f32(tab_size_px)); } // rjf: push piece { FNT_Piece *piece = fnt_piece_chunk_list_push_new(fnt_state->frame_arena, &piece_chunks, string.size); { piece->texture = atlas ? atlas->texture : r_handle_zero(); piece->subrect = r2s16p(info->subrect.x0, info->subrect.y0, info->subrect.x0 + info->raster_dim.x, info->subrect.y0 + info->raster_dim.y); piece->advance = advance; piece->decode_size = piece_substring.size; piece->offset = v2s16(0, -(hash2style_node->ascent + hash2style_node->descent)); } base_align_px += advance; dim.x += piece->advance; dim.y = Max(dim.y, info->raster_dim.y); } } } //- rjf: tighten & fill { if(piece_chunks.node_count == 1) { run.pieces.v = piece_chunks.first->v; run.pieces.count = piece_chunks.first->count; } else { run.pieces = fnt_piece_array_from_chunk_list(fnt_state->frame_arena, &piece_chunks); } run.dim = dim; run.ascent = hash2style_node->ascent; run.descent = hash2style_node->descent; } } //- rjf: build node for cacheable runs if(run_is_cacheable) { run_node = push_array(fnt_state->frame_arena, FNT_RunCacheNode, 1); SLLQueuePush(run_slot->first, run_slot->last, run_node); run_node->string = push_str8_copy(fnt_state->frame_arena, string); run_node->run = run; } return run; } internal String8List fnt_wrapped_string_lines_from_font_size_string_max(Arena *arena, FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, String8 string, F32 max) { String8List list = {0}; { Temp scratch = scratch_begin(&arena, 1); FNT_Run run = fnt_run_from_string(font, size, base_align_px, tab_size_px, 0, string); F32 off_px = 0; U64 off_bytes = 0; U64 line_start_off_bytes = 0; U64 line_end_off_bytes = 0; B32 seeking_word_end = 0; F32 word_start_off_px = 0; FNT_Piece *last_word_start_piece = 0; U64 last_word_start_off_bytes = 0; FNT_Piece *pieces_first = run.pieces.v; FNT_Piece *pieces_opl = run.pieces.v + run.pieces.count; for(FNT_Piece *piece = pieces_first, *next = 0; piece != 0 && piece <= pieces_opl; piece = next) { if(piece != 0) {next = piece+1;} // rjf: gather info U8 byte = off_bytes < string.size ? string.str[off_bytes] : 0; F32 advance = (piece != 0) ? piece->advance : 0; U64 decode_size = (piece != 0) ? piece->decode_size : 0; // rjf: find start/end of words B32 is_first_byte_of_word = 0; B32 is_first_space_after_word = 0; if(!seeking_word_end && !char_is_space(byte)) { seeking_word_end = 1; is_first_byte_of_word = 1; last_word_start_off_bytes = off_bytes; last_word_start_piece = piece; word_start_off_px = off_px; } else if(seeking_word_end && char_is_space(byte)) { seeking_word_end = 0; is_first_space_after_word = 1; } else if(seeking_word_end && byte == 0) { is_first_space_after_word = 1; } // rjf: determine properties of this advance B32 is_illegal = (off_px >= max); B32 is_next_illegal = (off_px + advance >= max); B32 is_end = (byte == 0); // rjf: legal word end -> extend line if(is_first_space_after_word && !is_illegal) { line_end_off_bytes = off_bytes; } // rjf: illegal mid-word split -> wrap mid-word if(is_next_illegal && word_start_off_px == 0) { String8 line = str8(string.str + line_start_off_bytes, off_bytes - line_start_off_bytes); line = str8_skip_chop_whitespace(line); if(line.size != 0) { str8_list_push(arena, &list, line); } off_px = advance; line_start_off_bytes = off_bytes; line_end_off_bytes = off_bytes; word_start_off_px = 0; last_word_start_piece = piece; last_word_start_off_bytes = off_bytes; off_bytes += decode_size; } // rjf: illegal word end -> wrap line else if(is_first_space_after_word && (is_illegal || is_end)) { String8 line = str8(string.str + line_start_off_bytes, line_end_off_bytes - line_start_off_bytes); line = str8_skip_chop_whitespace(line); if(line.size != 0) { str8_list_push(arena, &list, line); } line_start_off_bytes = line_end_off_bytes; if(is_illegal) { off_px = 0; word_start_off_px = 0; off_bytes = last_word_start_off_bytes; next = last_word_start_piece; } } // rjf: advance offsets otherwise else { off_px += advance; off_bytes += decode_size; } // rjf: 0 piece and 0 next -> done if(piece == 0 && next == 0) { break; } } scratch_end(scratch); } return list; } internal Vec2F32 fnt_dim_from_tag_size_string(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8 string) { Temp scratch = scratch_begin(0, 0); Vec2F32 result = {0}; FNT_Run run = fnt_run_from_string(tag, size, base_align_px, tab_size_px, 0, string); result = run.dim; scratch_end(scratch); return result; } internal Vec2F32 fnt_dim_from_tag_size_string_list(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8List list) { Vec2F32 sum = {0}; for(String8Node *n = list.first; n != 0; n = n->next) { Vec2F32 str_dim = fnt_dim_from_tag_size_string(tag, size, base_align_px, tab_size_px, n->string); sum.x += str_dim.x; sum.y = Max(sum.y, str_dim.y); } return sum; } internal F32 fnt_column_size_from_tag_size(FNT_Tag tag, F32 size) { F32 result = fnt_dim_from_tag_size_string(tag, size, 0, 0, str8_lit("H")).x; return result; } internal U64 fnt_char_pos_from_tag_size_string_p(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8 string, F32 p) { Temp scratch = scratch_begin(0, 0); U64 best_offset_bytes = 0; F32 best_offset_px = inf32(); U64 offset_bytes = 0; F32 offset_px = 0.f; FNT_Run run = fnt_run_from_string(tag, size, base_align_px, tab_size_px, 0, string); for(U64 idx = 0; idx <= run.pieces.count; idx += 1) { F32 this_piece_offset_px = abs_f32(offset_px - p); if(this_piece_offset_px < best_offset_px) { best_offset_bytes = offset_bytes; best_offset_px = this_piece_offset_px; } if(idx < run.pieces.count) { FNT_Piece *piece = &run.pieces.v[idx]; offset_px += piece->advance; offset_bytes += piece->decode_size; } } scratch_end(scratch); return best_offset_bytes; } //////////////////////////////// //~ rjf: Metrics internal FNT_Metrics fnt_metrics_from_tag_size(FNT_Tag tag, F32 size) { FP_Metrics metrics = fnt_fp_metrics_from_tag(tag); FNT_Metrics result = {0}; { result.ascent = floor_f32(size) * metrics.ascent / metrics.design_units_per_em; result.descent = floor_f32(size) * metrics.descent / metrics.design_units_per_em; result.line_gap = floor_f32(size) * metrics.line_gap / metrics.design_units_per_em; result.capital_height = floor_f32(size) * metrics.capital_height / metrics.design_units_per_em; } return result; } internal F32 fnt_line_height_from_metrics(FNT_Metrics *metrics) { return metrics->ascent + metrics->descent + metrics->line_gap; } //////////////////////////////// //~ rjf: Main Calls internal void fnt_init(void) { Arena *arena = arena_alloc(); fnt_state = push_array(arena, FNT_State, 1); fnt_state->permanent_arena = arena; fnt_state->raster_arena = arena_alloc(); fnt_state->frame_arena = arena_alloc(); fnt_state->font_hash_table_size = 64; fnt_state->font_hash_table = push_array(fnt_state->permanent_arena, FNT_FontHashSlot, fnt_state->font_hash_table_size); fnt_reset(); } internal void fnt_reset(void) { for(FNT_Atlas *a = fnt_state->first_atlas; a != 0; a = a->next) { r_tex2d_release(a->texture); } fnt_state->first_atlas = fnt_state->last_atlas = 0; arena_clear(fnt_state->raster_arena); fnt_state->hash2style_slots_count = 1024; fnt_state->hash2style_slots = push_array(fnt_state->raster_arena, FNT_Hash2StyleRasterCacheSlot, fnt_state->hash2style_slots_count); } internal void fnt_frame(void) { fnt_state->frame_index += 1; arena_clear(fnt_state->frame_arena); } ================================================ FILE: src/font_cache/font_cache.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_CACHE_H #define FONT_CACHE_H //////////////////////////////// //~ rjf: Rasterization Flags typedef U32 FNT_RasterFlags; enum { FNT_RasterFlag_Smooth = (1<<0), FNT_RasterFlag_Hinted = (1<<1), }; //////////////////////////////// //~ rjf: Handles & Tags typedef struct FNT_Tag FNT_Tag; struct FNT_Tag { U64 u64[2]; }; //////////////////////////////// //~ rjf: Draw Package Types (For Cache Queries) typedef struct FNT_Piece FNT_Piece; struct FNT_Piece { R_Handle texture; Rng2S16 subrect; Vec2S16 offset; F32 advance; U16 decode_size; }; typedef struct FNT_PieceChunkNode FNT_PieceChunkNode; struct FNT_PieceChunkNode { FNT_PieceChunkNode *next; FNT_Piece *v; U64 count; U64 cap; }; typedef struct FNT_PieceChunkList FNT_PieceChunkList; struct FNT_PieceChunkList { FNT_PieceChunkNode *first; FNT_PieceChunkNode *last; U64 node_count; U64 total_piece_count; }; typedef struct FNT_PieceArray FNT_PieceArray; struct FNT_PieceArray { FNT_Piece *v; U64 count; }; typedef struct FNT_Run FNT_Run; struct FNT_Run { FNT_PieceArray pieces; Vec2F32 dim; F32 ascent; F32 descent; }; //////////////////////////////// //~ rjf: Font Path -> Handle * Metrics * Path Cache Types typedef struct FNT_FontHashNode FNT_FontHashNode; struct FNT_FontHashNode { FNT_FontHashNode *hash_next; FNT_Tag tag; FP_Handle handle; FP_Metrics metrics; String8 path; }; typedef struct FNT_FontHashSlot FNT_FontHashSlot; struct FNT_FontHashSlot { FNT_FontHashNode *first; FNT_FontHashNode *last; }; //////////////////////////////// //~ rjf: Rasterization Cache Types //- rjf: base glyph rasterization / dimensions cache typedef struct FNT_RasterCacheInfo FNT_RasterCacheInfo; struct FNT_RasterCacheInfo { Rng2S16 subrect; Vec2S16 raster_dim; S16 atlas_num; F32 advance; }; typedef struct FNT_Hash2InfoRasterCacheNode FNT_Hash2InfoRasterCacheNode; struct FNT_Hash2InfoRasterCacheNode { FNT_Hash2InfoRasterCacheNode *hash_next; FNT_Hash2InfoRasterCacheNode *hash_prev; U64 hash; FNT_RasterCacheInfo info; }; typedef struct FNT_Hash2InfoRasterCacheSlot FNT_Hash2InfoRasterCacheSlot; struct FNT_Hash2InfoRasterCacheSlot { FNT_Hash2InfoRasterCacheNode *first; FNT_Hash2InfoRasterCacheNode *last; }; //- rjf: run cache (arrangements of many glyphs to represent a full string) typedef struct FNT_RunCacheNode FNT_RunCacheNode; struct FNT_RunCacheNode { FNT_RunCacheNode *next; String8 string; FNT_Run run; }; typedef struct FNT_RunCacheSlot FNT_RunCacheSlot; struct FNT_RunCacheSlot { FNT_RunCacheNode *first; FNT_RunCacheNode *last; }; //- rjf: style hash -> artifacts/metrics cache typedef struct FNT_Hash2StyleRasterCacheNode FNT_Hash2StyleRasterCacheNode; struct FNT_Hash2StyleRasterCacheNode { FNT_Hash2StyleRasterCacheNode *hash_next; FNT_Hash2StyleRasterCacheNode *hash_prev; U64 style_hash; F32 ascent; F32 descent; F32 column_width; FNT_RasterCacheInfo *utf8_class1_direct_map; U64 utf8_class1_direct_map_mask[4]; U64 hash2info_slots_count; FNT_Hash2InfoRasterCacheSlot *hash2info_slots; U64 run_slots_count; FNT_RunCacheSlot *run_slots; U64 run_slots_frame_index; }; typedef struct FNT_Hash2StyleRasterCacheSlot FNT_Hash2StyleRasterCacheSlot; struct FNT_Hash2StyleRasterCacheSlot { FNT_Hash2StyleRasterCacheNode *first; FNT_Hash2StyleRasterCacheNode *last; }; //////////////////////////////// //~ rjf: Atlas Types typedef U32 FNT_AtlasRegionNodeFlags; enum { FNT_AtlasRegionNodeFlag_Taken = (1<<0), }; typedef struct FNT_AtlasRegionNode FNT_AtlasRegionNode; struct FNT_AtlasRegionNode { FNT_AtlasRegionNode *parent; FNT_AtlasRegionNode *children[Corner_COUNT]; Vec2S16 max_free_size[Corner_COUNT]; FNT_AtlasRegionNodeFlags flags; U64 num_allocated_descendants; }; typedef struct FNT_Atlas FNT_Atlas; struct FNT_Atlas { FNT_Atlas *next; FNT_Atlas *prev; R_Handle texture; Vec2S16 root_dim; FNT_AtlasRegionNode *root; }; //////////////////////////////// //~ rjf: Metrics typedef struct FNT_Metrics FNT_Metrics; struct FNT_Metrics { F32 ascent; F32 descent; F32 line_gap; F32 capital_height; }; //////////////////////////////// //~ rjf: Main State Type typedef struct FNT_State FNT_State; struct FNT_State { Arena *permanent_arena; Arena *raster_arena; Arena *frame_arena; U64 frame_index; // rjf: font table U64 font_hash_table_size; FNT_FontHashSlot *font_hash_table; // rjf: hash -> raster cache table U64 hash2style_slots_count; FNT_Hash2StyleRasterCacheSlot *hash2style_slots; // rjf: atlas list FNT_Atlas *first_atlas; FNT_Atlas *last_atlas; }; //////////////////////////////// //~ rjf: Globals global FNT_State *fnt_state = 0; //////////////////////////////// //~ rjf: Basic Functions internal U128 fnt_hash_from_string(String8 string); internal U64 fnt_little_hash_from_string(U64 seed, String8 string); internal Vec2S32 fnt_vertex_from_corner(Corner corner); //////////////////////////////// //~ rjf: Font Tags internal FNT_Tag fnt_tag_zero(void); internal B32 fnt_tag_match(FNT_Tag a, FNT_Tag b); internal FP_Handle fnt_handle_from_tag(FNT_Tag tag); internal FP_Metrics fnt_fp_metrics_from_tag(FNT_Tag tag); internal FNT_Tag fnt_tag_from_path(String8 path); internal FNT_Tag fnt_tag_from_static_data_string(String8 *data_ptr); internal String8 fnt_path_from_tag(FNT_Tag tag); //////////////////////////////// //~ rjf: Atlas internal Rng2S16 fnt_atlas_region_alloc(Arena *arena, FNT_Atlas *atlas, Vec2S16 needed_size); internal void fnt_atlas_region_release(FNT_Atlas *atlas, Rng2S16 region); //////////////////////////////// //~ rjf: Piece Type Functions internal FNT_Piece *fnt_piece_chunk_list_push_new(Arena *arena, FNT_PieceChunkList *list, U64 cap); internal void fnt_piece_chunk_list_push(Arena *arena, FNT_PieceChunkList *list, U64 cap, FNT_Piece *piece); internal FNT_PieceArray fnt_piece_array_from_chunk_list(Arena *arena, FNT_PieceChunkList *list); internal FNT_PieceArray fnt_piece_array_copy(Arena *arena, FNT_PieceArray *src); //////////////////////////////// //~ rjf: Cache Usage //- rjf: base cache lookups internal FNT_Hash2StyleRasterCacheNode *fnt_hash2style_from_tag_size_flags(FNT_Tag tag, F32 size, FNT_RasterFlags flags); internal FNT_Run fnt_run_from_string(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, String8 string); //- rjf: helpers internal String8List fnt_wrapped_string_lines_from_font_size_string_max(Arena *arena, FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, String8 string, F32 max); internal Vec2F32 fnt_dim_from_tag_size_string(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8 string); internal Vec2F32 fnt_dim_from_tag_size_string_list(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8List list); internal F32 fnt_column_size_from_tag_size(FNT_Tag tag, F32 size); internal U64 fnt_char_pos_from_tag_size_string_p(FNT_Tag tag, F32 size, F32 base_align_px, F32 tab_size_px, String8 string, F32 p); //////////////////////////////// //~ rjf: Metrics internal FNT_Metrics fnt_metrics_from_tag_size(FNT_Tag tag, F32 size); internal F32 fnt_line_height_from_metrics(FNT_Metrics *metrics); //////////////////////////////// //~ rjf: Main Calls internal void fnt_init(void); internal void fnt_reset(void); internal void fnt_frame(void); #endif // FONT_CACHE_H ================================================ FILE: src/font_provider/dwrite/font_provider_dwrite.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Globals global FP_DWrite_State *fp_dwrite_state = 0; global FP_DWrite_FontFileLoaderVTable fp_dwrite_static_data_font_file_loader__vtable = { fp_dwrite_iunknown_noop__query_interface, fp_dwrite_iunknown_noop__add_ref, fp_dwrite_iunknown_noop__release, fp_dwrite_static_font_file_loader__stream_from_key, }; global FP_DWrite_FontFileLoader fp_dwrite_static_data_font_file_loader = {&fp_dwrite_static_data_font_file_loader__vtable}; global FP_DWrite_FontFileStreamVTable fp_dwrite_static_data_font_file_stream__vtable = { fp_dwrite_iunknown_noop__query_interface, fp_dwrite_iunknown_noop__add_ref, fp_dwrite_iunknown_noop__release, fp_dwrite_static_font_file_stream__read_file_fragment, fp_dwrite_static_font_file_stream__release_file_fragment, fp_dwrite_static_font_file_stream__get_file_size, fp_dwrite_static_font_file_stream__get_last_write_time, }; //////////////////////////////// //~ rjf: Helpers //- rjf: handle conversion functions internal FP_DWrite_Font fp_dwrite_font_from_handle(FP_Handle handle) { FP_DWrite_Font result = {0}; result.file = (IDWriteFontFile *)handle.u64[0]; result.face = (IDWriteFontFace *)handle.u64[1]; return result; } internal FP_Handle fp_dwrite_handle_from_font(FP_DWrite_Font font) { FP_Handle result = {0}; result.u64[0] = (U64)font.file; result.u64[1] = (U64)font.face; return result; } //- rjf: file stream allocator internal FP_DWrite_FontFileStreamNode * fp_dwrite_font_file_stream_node_alloc(String8 *data_ptr) { FP_DWrite_FontFileStreamNode *node = 0; for(FP_DWrite_FontFileStreamNode *n = fp_dwrite_state->first_stream_node; n != 0; n = n->next) { if(n->stream.data == data_ptr) { node = n; break; } } if(node == 0) { node = fp_dwrite_state->free_stream_node; if(node != 0) { SLLStackPop(fp_dwrite_state->free_stream_node); } else { node = push_array_no_zero(fp_dwrite_state->arena, FP_DWrite_FontFileStreamNode, 1); } MemoryZeroStruct(node); node->stream.lpVtbl = &fp_dwrite_static_data_font_file_stream__vtable; node->stream.data = data_ptr; DLLPushBack(fp_dwrite_state->first_stream_node, fp_dwrite_state->last_stream_node, node); } return node; } internal void fp_dwrite_font_file_stream_node_release(FP_DWrite_FontFileStreamNode *node) { DLLPushBack(fp_dwrite_state->first_stream_node, fp_dwrite_state->last_stream_node, node); SLLStackPush(fp_dwrite_state->free_stream_node, node); } //- rjf: iunknown no-op helpers internal HRESULT fp_dwrite_iunknown_noop__query_interface(void *obj, REFIID riid, void *ptr_to_object) { return E_NOINTERFACE; } internal ULONG fp_dwrite_iunknown_noop__add_ref(void *obj) { ULONG result = 1; return result; } internal ULONG fp_dwrite_iunknown_noop__release(void *obj) { ULONG result = 1; return result; } //- rjf: font file loader interface function implementations internal HRESULT fp_dwrite_static_font_file_loader__stream_from_key(FP_DWrite_FontFileLoader *obj, void const *font_file_ref_key, UINT32 font_file_ref_key_size, IDWriteFontFileStream **stream_out) { HRESULT result = S_OK; String8 *key = *(String8 **)font_file_ref_key; FP_DWrite_FontFileStreamNode *node = fp_dwrite_font_file_stream_node_alloc(key); *stream_out = (IDWriteFontFileStream *)&node->stream; return result; } //- rjf: font file stream interface function implementations internal HRESULT fp_dwrite_static_font_file_stream__read_file_fragment(FP_DWrite_FontFileStream *obj, void const **fragment_start, UINT64 file_offset, UINT64 fragment_size, void **fragment_context) { HRESULT result = S_OK; *fragment_start = obj->data->str + file_offset; *fragment_context = 0; return result; } internal HRESULT fp_dwrite_static_font_file_stream__release_file_fragment(FP_DWrite_FontFileStream *obj, void *fragment_context) { HRESULT result = S_OK; return result; } internal HRESULT fp_dwrite_static_font_file_stream__get_file_size(FP_DWrite_FontFileStream *obj, UINT64 *size_out) { HRESULT result = S_OK; *size_out = obj->data->size; return result; } internal HRESULT fp_dwrite_static_font_file_stream__get_last_write_time(FP_DWrite_FontFileStream *obj, UINT64 *time_out) { HRESULT result = S_OK; *time_out = 0; return result; } //////////////////////////////// //~ rjf: Backend Implementations fp_hook void fp_init(void) { ProfBeginFunction(); HRESULT error = 0; //- rjf: initialize main state { Arena *arena = arena_alloc(); fp_dwrite_state = push_array(arena, FP_DWrite_State, 1); fp_dwrite_state->arena = arena; } //- rjf: make dwrite factory error = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2, (void **)&fp_dwrite_state->factory); if(error == S_OK) { fp_dwrite_state->dwrite2_is_supported = 1; } else { error = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (void **)&fp_dwrite_state->factory); } //- rjf: register static data font "loader" interface error = IDWriteFactory_RegisterFontFileLoader(fp_dwrite_state->factory, (IDWriteFontFileLoader *)&fp_dwrite_static_data_font_file_loader); //- rjf: make base rendering params error = IDWriteFactory_CreateRenderingParams(fp_dwrite_state->factory, &fp_dwrite_state->base_rendering_params); //- rjf: make sharp-hinted rendering params { FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params); gamma = 1.f; FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params); if(fp_dwrite_state->dwrite2_is_supported) { error = IDWriteFactory2_CreateCustomRenderingParams2((IDWriteFactory2 *)fp_dwrite_state->factory, gamma, enhanced_contrast, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, DWRITE_GRID_FIT_MODE_ENABLED, (IDWriteRenderingParams2 **)&fp_dwrite_state->rendering_params_sharp_hinted); } else { error = IDWriteFactory_CreateCustomRenderingParams(fp_dwrite_state->factory, gamma, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, &fp_dwrite_state->rendering_params_sharp_hinted); } } //- rjf: make sharp-unhinted rendering params { FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params); gamma = 1.f; FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params); if(fp_dwrite_state->dwrite2_is_supported) { error = IDWriteFactory2_CreateCustomRenderingParams2((IDWriteFactory2 *)fp_dwrite_state->factory, gamma, enhanced_contrast, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, DWRITE_GRID_FIT_MODE_DISABLED, (IDWriteRenderingParams2 **)&fp_dwrite_state->rendering_params_sharp_unhinted); } else { error = IDWriteFactory_CreateCustomRenderingParams(fp_dwrite_state->factory, gamma, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_GDI_NATURAL, &fp_dwrite_state->rendering_params_sharp_unhinted); } } //- rjf: make smooth-hinted rendering params { FLOAT gamma = IDWriteRenderingParams_GetGamma(fp_dwrite_state->base_rendering_params); gamma = 1.f; FLOAT enhanced_contrast = IDWriteRenderingParams_GetEnhancedContrast(fp_dwrite_state->base_rendering_params); if(fp_dwrite_state->dwrite2_is_supported) { error = IDWriteFactory2_CreateCustomRenderingParams2((IDWriteFactory2 *)fp_dwrite_state->factory, gamma, enhanced_contrast, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, DWRITE_GRID_FIT_MODE_ENABLED, (IDWriteRenderingParams2 **)&fp_dwrite_state->rendering_params_smooth_hinted); } else { error = IDWriteFactory_CreateCustomRenderingParams(fp_dwrite_state->factory, gamma, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, &fp_dwrite_state->rendering_params_smooth_hinted); } } //- rjf: make smooth rendering params { FLOAT gamma = 1.f; FLOAT enhanced_contrast = 0.f; if(fp_dwrite_state->dwrite2_is_supported) { error = IDWriteFactory2_CreateCustomRenderingParams2((IDWriteFactory2 *)fp_dwrite_state->factory, gamma, enhanced_contrast, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, DWRITE_GRID_FIT_MODE_DISABLED, (IDWriteRenderingParams2 **)&fp_dwrite_state->rendering_params_smooth_unhinted); } else { error = IDWriteFactory_CreateCustomRenderingParams(fp_dwrite_state->factory, gamma, enhanced_contrast, 0.f, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, &fp_dwrite_state->rendering_params_smooth_unhinted); } } //- rjf: make dwrite gdi interop error = IDWriteFactory_GetGdiInterop(fp_dwrite_state->factory, &fp_dwrite_state->gdi_interop); //- rjf: build render target for rasterization fp_dwrite_state->bitmap_render_target_dim = v2s32(2048, 256); error = IDWriteGdiInterop_CreateBitmapRenderTarget(fp_dwrite_state->gdi_interop, 0, fp_dwrite_state->bitmap_render_target_dim.x, fp_dwrite_state->bitmap_render_target_dim.y, &fp_dwrite_state->bitmap_render_target); IDWriteBitmapRenderTarget_SetPixelsPerDip(fp_dwrite_state->bitmap_render_target, 1.0); ProfEnd(); } fp_hook FP_Handle fp_font_open(String8 path) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); FP_DWrite_Font font = {0}; HRESULT error = 0; //- rjf: build initial path task typedef struct PathTask PathTask; struct PathTask { PathTask *next; String8 path; }; PathTask start_task = {0, path}; PathTask *first_task = &start_task; PathTask *last_task = first_task; //- rjf: try to open font for(PathTask *t = first_task; t != 0 && font.file == 0; t = t->next) { B32 file_exists = (os_properties_from_file_path(t->path).created != 0); String16 path16 = str16_from_8(scratch.arena, t->path); if(file_exists) { error = IDWriteFactory_CreateFontFileReference(fp_dwrite_state->factory, (WCHAR *)path16.str, 0, &font.file); } if(font.file != 0) { error = IDWriteFactory_CreateFontFace(fp_dwrite_state->factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font.file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font.face); } // rjf: failure trying just the normal path? -> generate new tasks that search in system folders if(t == first_task && font.file == 0 && t->path.size != 0) { // rjf: generate task for user-installed fonts { HKEY reg_key = 0; LSTATUS status = 0; char name[256] = {0}; char data[256] = {0}; DWORD name_size = sizeof(name); DWORD data_size = sizeof(data); DWORD type = 0; status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\Fonts", 0, KEY_QUERY_VALUE, ®_key); status = RegEnumValueA(reg_key, 0, name, &name_size, 0, &type, (unsigned char *)data, &data_size); String8 user_fonts_path = str8_cstring(data); PathTask *task = push_array(scratch.arena, PathTask, 1); task->path = push_str8f(scratch.arena, "%s/%S", user_fonts_path, path); SLLQueuePush(first_task, last_task, task); } // rjf: generate task for windows directory (C:/Windows/Fonts, generally) { char windows_path[256] = {0}; GetWindowsDirectoryA(windows_path, sizeof(windows_path)); PathTask *task = push_array(scratch.arena, PathTask, 1); task->path = push_str8f(scratch.arena, "%s/Fonts/%S", windows_path, path); SLLQueuePush(first_task, last_task, task); } } } //- rjf: handlify & return FP_Handle handle = {0}; if(font.file != 0) { handle = fp_dwrite_handle_from_font(font); } scratch_end(scratch); ProfEnd(); return handle; } fp_hook FP_Handle fp_font_open_from_static_data_string(String8 *data_ptr) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); FP_DWrite_Font font = {0}; HRESULT error = 0; //- rjf: open font file reference error = IDWriteFactory_CreateCustomFontFileReference(fp_dwrite_state->factory, &data_ptr, sizeof(String8 *), (IDWriteFontFileLoader *)&fp_dwrite_static_data_font_file_loader, &font.file); //- rjf: open font face error = IDWriteFactory_CreateFontFace(fp_dwrite_state->factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &font.file, 0, DWRITE_FONT_SIMULATIONS_NONE, &font.face); //- rjf: handlify & return FP_Handle handle = fp_dwrite_handle_from_font(font); scratch_end(scratch); ProfEnd(); return handle; } fp_hook void fp_font_close(FP_Handle handle) { ProfBeginFunction(); FP_DWrite_Font font = fp_dwrite_font_from_handle(handle); if(font.face != 0) { IDWriteFontFace_Release(font.face); } if(font.file != 0) { IDWriteFontFile_Release(font.file); } ProfEnd(); } fp_hook FP_Metrics fp_metrics_from_font(FP_Handle handle) { ProfBeginFunction(); FP_DWrite_Font font = fp_dwrite_font_from_handle(handle); DWRITE_FONT_METRICS metrics = {0}; if(font.face != 0) { IDWriteFontFace_GetMetrics(font.face, &metrics); } FP_Metrics result = {0}; { result.design_units_per_em = (F32)metrics.designUnitsPerEm; result.ascent = (F32)metrics.ascent; result.descent = (F32)metrics.descent; result.line_gap = (F32)metrics.lineGap; result.capital_height = (F32)metrics.capHeight; } ProfEnd(); return result; } fp_hook NO_ASAN FP_RasterResult fp_raster(Arena *arena, FP_Handle font_handle, F32 size, FP_RasterFlags flags, String8 string) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); HRESULT error = 0; String32 string32 = str32_from_8(scratch.arena, string); FP_DWrite_Font font = fp_dwrite_font_from_handle(font_handle); COLORREF bg_color = RGB(0, 0, 0); COLORREF fg_color = RGB(255, 255, 255); //- rjf: get font metrics DWRITE_FONT_METRICS font_metrics = {0}; if(font.face != 0) { IDWriteFontFace_GetMetrics(font.face, &font_metrics); } F32 design_units_per_em = (F32)font_metrics.designUnitsPerEm; //- rjf: get glyph indices U16 *glyph_indices = push_array_no_zero(scratch.arena, U16, string32.size); if(font.face != 0) { error = IDWriteFontFace_GetGlyphIndices(font.face, string32.str, string32.size, glyph_indices); } //- rjf: get metrics info U64 glyphs_count = string32.size; DWRITE_GLYPH_METRICS *glyphs_metrics = push_array_no_zero(scratch.arena, DWRITE_GLYPH_METRICS, glyphs_count); if(font.face != 0) { error = IDWriteFontFace_GetGdiCompatibleGlyphMetrics(font.face, (96.f/72.f)*size, 1.f, 0, 1, glyph_indices, glyphs_count, glyphs_metrics, 0); } //- rjf: derive info from metrics F32 advance = 0; Vec2S16 atlas_dim = {0}; F32 left_side_bearing = 0; F32 right_side_bearing = 0; if(font.face != 0) { atlas_dim.y = (S16)round_f32((96.f/72.f) * size * (font_metrics.ascent + font_metrics.descent + font_metrics.lineGap) / design_units_per_em) + 1; for(U64 idx = 0; idx < glyphs_count; idx += 1) { DWRITE_GLYPH_METRICS *glyph_metrics = glyphs_metrics + idx; F32 glyph_advance_width = (96.f/72.f) * size * glyph_metrics->advanceWidth / design_units_per_em; advance += glyph_advance_width; atlas_dim.x = Max(atlas_dim.x, (S16)(advance+1)); if(idx == 0) { left_side_bearing = (96.f/72.f) * size * glyph_metrics->leftSideBearing / design_units_per_em; } if(idx+1 == glyphs_count) { right_side_bearing = (96.f/72.f) * size * glyph_metrics->rightSideBearing / design_units_per_em; } } atlas_dim.x -= right_side_bearing; atlas_dim.x += 2; atlas_dim.x += 7; atlas_dim.x -= atlas_dim.x%8; } //- rjf: make dwrite bitmap for rendering IDWriteBitmapRenderTarget *render_target = 0; if(font.face != 0) { error = IDWriteGdiInterop_CreateBitmapRenderTarget(fp_dwrite_state->gdi_interop, 0, atlas_dim.x, atlas_dim.y, &render_target); IDWriteBitmapRenderTarget_SetPixelsPerDip(render_target, 1.f); } //- rjf: get bitmap & clear HDC dc = 0; if(font.face != 0) { dc = IDWriteBitmapRenderTarget_GetMemoryDC(render_target); HGDIOBJ original = SelectObject(dc, GetStockObject(DC_PEN)); SetDCPenColor(dc, bg_color); SelectObject(dc, GetStockObject(DC_BRUSH)); SetDCBrushColor(dc, bg_color); Rectangle(dc, 0, 0, atlas_dim.x, atlas_dim.y); SelectObject(dc, original); } //- rjf: draw glyph run Vec2F32 draw_p = {0, (F32)atlas_dim.y}; if(font.face != 0) { F32 descent = round_f32((96.f/72.f)*size * font_metrics.descent / design_units_per_em); F32 line_gap = round_f32((96.f/72.f)*size * font_metrics.lineGap / design_units_per_em); draw_p.y -= descent; draw_p.y -= line_gap; } DWRITE_GLYPH_RUN glyph_run = {0}; if(font.face != 0) { glyph_run.fontFace = font.face; glyph_run.fontEmSize = size * 96.f/72.f; glyph_run.glyphCount = string32.size; glyph_run.glyphIndices = glyph_indices; } RECT bounding_box = {0}; if(font.face != 0) { IDWriteRenderingParams *rendering_params = fp_dwrite_state->rendering_params_sharp_hinted; switch(flags) { default:{}break; case 0:{rendering_params = fp_dwrite_state->rendering_params_sharp_unhinted;}break; case FP_RasterFlag_Hinted:{rendering_params = fp_dwrite_state->rendering_params_sharp_hinted;}break; case FP_RasterFlag_Smooth:{rendering_params = fp_dwrite_state->rendering_params_smooth_unhinted;}break; case FP_RasterFlag_Smooth|FP_RasterFlag_Hinted:{rendering_params = fp_dwrite_state->rendering_params_smooth_hinted;}break; } error = IDWriteBitmapRenderTarget_DrawGlyphRun(render_target, draw_p.x, draw_p.y, DWRITE_MEASURING_MODE_NATURAL, &glyph_run, rendering_params, fg_color, &bounding_box); } //- rjf: get bitmap DIBSECTION dib = {0}; if(font.face != 0) { HBITMAP bitmap = (HBITMAP)GetCurrentObject(dc, OBJ_BITMAP); GetObject(bitmap, sizeof(dib), &dib); } //- rjf: fill & return FP_RasterResult result = {0}; if(font.face != 0) { // rjf: fill basics result.atlas_dim = atlas_dim; result.atlas = push_array_no_zero(arena, U8, atlas_dim.x*atlas_dim.y*4); result.advance = floor_f32(advance); // rjf: fill atlas { U8 *in_data = (U8 *)dib.dsBm.bmBits; U64 in_pitch = (U64)dib.dsBm.bmWidthBytes; U8 *out_data = (U8 *)result.atlas; U64 out_pitch = atlas_dim.x * 4; U64 color_sum = 0; U8 *in_line = (U8 *)in_data; U8 *out_line = out_data; for(U64 y = 0; y < atlas_dim.y; y += 1) { U8 *in_pixel = in_line; U8 *out_pixel = out_line; for(U64 x = 0; x < atlas_dim.x; x += 1) { U8 in_pixel_byte = in_pixel[0]; out_pixel[0] = 255; out_pixel[1] = 255; out_pixel[2] = 255; out_pixel[3] = in_pixel_byte; color_sum += in_pixel_byte; in_pixel += 4; out_pixel += 4; } in_line += in_pitch; out_line += out_pitch; } if(color_sum == 0) { result.atlas_dim = v2s16(0, 0); } } IDWriteBitmapRenderTarget_Release(render_target); } scratch_end(scratch); ProfEnd(); return result; } ================================================ FILE: src/font_provider/dwrite/font_provider_dwrite.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_DWRITE_H #define FONT_PROVIDER_DWRITE_H #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "dwrite.lib") // #include //////////////////////////////// //~ rjf: (C) DirectWrite Definitions // // (courtesy of mmozeiko, Martins Mozeiko, https://github.com/mmozeiko/c_d2d_dwrite) // // This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. // // In jurisdictions that recognize copyright laws, the author or authors // of this software dedicate any and all copyright interest in the // software to the public domain. We make this dedication for the benefit // of the public at large and to the detriment of our heirs and // successors. We intend this dedication to be an overt act of // relinquishment in perpetuity of all present and future rights to this // software under copyright law. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // For more information, please refer to #include #include #include //- rjf: enums typedef enum DWRITE_FACTORY_TYPE { DWRITE_FACTORY_TYPE_SHARED = 0, DWRITE_FACTORY_TYPE_ISOLATED = 1, } DWRITE_FACTORY_TYPE; typedef enum DWRITE_PIXEL_GEOMETRY { DWRITE_PIXEL_GEOMETRY_FLAT = 0, DWRITE_PIXEL_GEOMETRY_RGB = 1, DWRITE_PIXEL_GEOMETRY_BGR = 2, } DWRITE_PIXEL_GEOMETRY; typedef enum DWRITE_RENDERING_MODE { DWRITE_RENDERING_MODE_DEFAULT = 0, DWRITE_RENDERING_MODE_ALIASED = 1, DWRITE_RENDERING_MODE_GDI_CLASSIC = 2, DWRITE_RENDERING_MODE_GDI_NATURAL = 3, DWRITE_RENDERING_MODE_NATURAL = 4, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC = 5, DWRITE_RENDERING_MODE_OUTLINE = 6, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC = 2, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL = 3, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL = 4, DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC = 5, } DWRITE_RENDERING_MODE; typedef enum DWRITE_FONT_SIMULATIONS { DWRITE_FONT_SIMULATIONS_NONE = 0, DWRITE_FONT_SIMULATIONS_BOLD = 1, DWRITE_FONT_SIMULATIONS_OBLIQUE = 2, } DWRITE_FONT_SIMULATIONS; typedef enum DWRITE_FONT_FACE_TYPE { DWRITE_FONT_FACE_TYPE_CFF = 0, DWRITE_FONT_FACE_TYPE_TRUETYPE = 1, DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION = 2, DWRITE_FONT_FACE_TYPE_TYPE1 = 3, DWRITE_FONT_FACE_TYPE_VECTOR = 4, DWRITE_FONT_FACE_TYPE_BITMAP = 5, DWRITE_FONT_FACE_TYPE_UNKNOWN = 6, DWRITE_FONT_FACE_TYPE_RAW_CFF = 7, DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION = 2, } DWRITE_FONT_FACE_TYPE; typedef enum DWRITE_GRID_FIT_MODE { DWRITE_GRID_FIT_MODE_DEFAULT = 0, DWRITE_GRID_FIT_MODE_DISABLED = 1, DWRITE_GRID_FIT_MODE_ENABLED = 2, } DWRITE_GRID_FIT_MODE; //- rjf: interfaces typedef struct IDWriteFactory { struct { void* tbl[]; }* v; } IDWriteFactory; typedef struct IDWriteFactory1 { struct { void* tbl[]; }* v; } IDWriteFactory1; typedef struct IDWriteFactory2 { struct { void* tbl[]; }* v; } IDWriteFactory2; typedef struct IDWriteRenderingParams { struct { void* tbl[]; }* v; } IDWriteRenderingParams; typedef struct IDWriteRenderingParams1 { struct { void* tbl[]; }* v; } IDWriteRenderingParams1; typedef struct IDWriteRenderingParams2 { struct { void* tbl[]; }* v; } IDWriteRenderingParams2; typedef struct IDWriteFontFileLoader { struct { void* tbl[]; }* v; } IDWriteFontFileLoader; typedef struct IDWriteFontFileStream { struct { void* tbl[]; }* v; } IDWriteFontFileStream; typedef struct IDWriteFontFile { struct { void* tbl[]; }* v; } IDWriteFontFile; typedef struct IDWriteFontFace { struct { void* tbl[]; }* v; } IDWriteFontFace; typedef struct IDWriteFontFace1 { struct { void* tbl[]; }* v; } IDWriteFontFace1; typedef struct IDWriteFontFace2 { struct { void* tbl[]; }* v; } IDWriteFontFace2; typedef struct IDWriteGdiInterop { struct { void* tbl[]; }* v; } IDWriteGdiInterop; typedef struct IDWriteBitmapRenderTarget { struct { void* tbl[]; }* v; } IDWriteBitmapRenderTarget; typedef struct IDWriteBitmapRenderTarget1 { struct { void* tbl[]; }* v; } IDWriteBitmapRenderTarget1; //- rjf: structs typedef struct DWRITE_GLYPH_METRICS { INT32 leftSideBearing; UINT32 advanceWidth; INT32 rightSideBearing; INT32 topSideBearing; UINT32 advanceHeight; INT32 bottomSideBearing; INT32 verticalOriginY; } DWRITE_GLYPH_METRICS; typedef struct DWRITE_GLYPH_OFFSET { FLOAT advanceOffset; FLOAT ascenderOffset; } DWRITE_GLYPH_OFFSET; typedef struct DWRITE_GLYPH_RUN { IDWriteFontFace* fontFace; FLOAT fontEmSize; UINT32 glyphCount; UINT16* glyphIndices; FLOAT* glyphAdvances; DWRITE_GLYPH_OFFSET* glyphOffsets; BOOL isSideways; UINT32 bidiLevel; } DWRITE_GLYPH_RUN; typedef struct DWRITE_FONT_METRICS { UINT16 designUnitsPerEm; UINT16 ascent; UINT16 descent; INT16 lineGap; UINT16 capHeight; UINT16 xHeight; INT16 underlinePosition; UINT16 underlineThickness; INT16 strikethroughPosition; UINT16 strikethroughThickness; } DWRITE_FONT_METRICS; typedef struct DWRITE_MATRIX { FLOAT m11; FLOAT m12; FLOAT m21; FLOAT m22; FLOAT dx; FLOAT dy; } DWRITE_MATRIX; //- rjf: GUIDs DEFINE_GUID(IID_IDWriteFactory, 0xb859ee5a, 0xd838, 0x4b5b, 0xa2, 0xe8, 0x1a, 0xdc, 0x7d, 0x93, 0xdb, 0x48); DEFINE_GUID(IID_IDWriteFactory1, 0x30572f99, 0xdac6, 0x41db, 0xa1, 0x6e, 0x04, 0x86, 0x30, 0x7e, 0x60, 0x6a); DEFINE_GUID(IID_IDWriteFactory2, 0x0439fc60, 0xca44, 0x4994, 0x8d, 0xee, 0x3a, 0x9a, 0xf7, 0xb7, 0x32, 0xec); //- rjf: functions EXTERN_C HRESULT DECLSPEC_IMPORT WINAPI DWriteCreateFactory (DWRITE_FACTORY_TYPE factoryType, const GUID* iid, void** factory); //- rjf: methods static inline HRESULT IDWriteFactory_RegisterFontFileLoader (IDWriteFactory* this_, IDWriteFontFileLoader* fontFileLoader) { return ((HRESULT (WINAPI*)(IDWriteFactory*, IDWriteFontFileLoader*))this_->v->tbl[13])(this_, fontFileLoader); } static inline HRESULT IDWriteFactory_CreateRenderingParams (IDWriteFactory* this_, IDWriteRenderingParams** renderingParams) { return ((HRESULT (WINAPI*)(IDWriteFactory*, IDWriteRenderingParams**))this_->v->tbl[10])(this_, renderingParams); } static inline HRESULT IDWriteFactory_CreateCustomRenderingParams (IDWriteFactory* this_, FLOAT gamma, FLOAT enhancedContrast, FLOAT clearTypeLevel, DWRITE_PIXEL_GEOMETRY pixelGeometry, DWRITE_RENDERING_MODE renderingMode, IDWriteRenderingParams** renderingParams) { return ((HRESULT (WINAPI*)(IDWriteFactory*, FLOAT, FLOAT, FLOAT, DWRITE_PIXEL_GEOMETRY, DWRITE_RENDERING_MODE, IDWriteRenderingParams**))this_->v->tbl[12])(this_, gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); } static inline HRESULT IDWriteFactory_GetGdiInterop (IDWriteFactory* this_, IDWriteGdiInterop** gdiInterop) { return ((HRESULT (WINAPI*)(IDWriteFactory*, IDWriteGdiInterop**))this_->v->tbl[17])(this_, gdiInterop); } static inline HRESULT IDWriteFactory_CreateCustomFontFileReference (IDWriteFactory* this_, const void* fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileLoader* fontFileLoader, IDWriteFontFile** fontFile) { return ((HRESULT (WINAPI*)(IDWriteFactory*, const void*, UINT32, IDWriteFontFileLoader*, IDWriteFontFile**))this_->v->tbl[8])(this_, fontFileReferenceKey, fontFileReferenceKeySize, fontFileLoader, fontFile); } static inline HRESULT IDWriteFactory_CreateFontFileReference (IDWriteFactory* this_, const WCHAR* filePath, const FILETIME* lastWriteTime, IDWriteFontFile** fontFile) { return ((HRESULT (WINAPI*)(IDWriteFactory*, const WCHAR*, const FILETIME*, IDWriteFontFile**))this_->v->tbl[7])(this_, filePath, lastWriteTime, fontFile); } static inline HRESULT IDWriteFactory_CreateFontFace (IDWriteFactory* this_, DWRITE_FONT_FACE_TYPE fontFaceType, UINT32 numberOfFiles, IDWriteFontFile** fontFiles, UINT32 faceIndex, DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, IDWriteFontFace** fontFace) { return ((HRESULT (WINAPI*)(IDWriteFactory*, DWRITE_FONT_FACE_TYPE, UINT32, IDWriteFontFile**, UINT32, DWRITE_FONT_SIMULATIONS, IDWriteFontFace**))this_->v->tbl[9])(this_, fontFaceType, numberOfFiles, fontFiles, faceIndex, fontFaceSimulationFlags, fontFace); } static inline HRESULT IDWriteFactory2_CreateCustomRenderingParams2 (IDWriteFactory2* this, FLOAT gamma, FLOAT enhancedContrast, FLOAT grayscaleEnhancedContrast, FLOAT clearTypeLevel, DWRITE_PIXEL_GEOMETRY pixelGeometry, DWRITE_RENDERING_MODE renderingMode, DWRITE_GRID_FIT_MODE gridFitMode, IDWriteRenderingParams2** renderingParams) { return ((HRESULT (WINAPI*)(IDWriteFactory2*, FLOAT, FLOAT, FLOAT, FLOAT, DWRITE_PIXEL_GEOMETRY, DWRITE_RENDERING_MODE, DWRITE_GRID_FIT_MODE, IDWriteRenderingParams2**))this->v->tbl[29])(this, gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); } static inline FLOAT IDWriteRenderingParams_GetEnhancedContrast (IDWriteRenderingParams* this_) { return ((FLOAT (WINAPI*)(IDWriteRenderingParams*))this_->v->tbl[4])(this_); } static inline FLOAT IDWriteRenderingParams_GetGamma (IDWriteRenderingParams* this_) { return ((FLOAT (WINAPI*)(IDWriteRenderingParams*))this_->v->tbl[3])(this_); } static inline HRESULT IDWriteGdiInterop_CreateBitmapRenderTarget (IDWriteGdiInterop* this_, HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget** renderTarget) { return ((HRESULT (WINAPI*)(IDWriteGdiInterop*, HDC, UINT32, UINT32, IDWriteBitmapRenderTarget**))this_->v->tbl[7])(this_, hdc, width, height, renderTarget); } static inline HRESULT IDWriteBitmapRenderTarget_SetPixelsPerDip (IDWriteBitmapRenderTarget* this_, FLOAT pixelsPerDip) { return ((HRESULT (WINAPI*)(IDWriteBitmapRenderTarget*, FLOAT))this_->v->tbl[6])(this_, pixelsPerDip); } static inline HDC IDWriteBitmapRenderTarget_GetMemoryDC (IDWriteBitmapRenderTarget* this_) { return ((HDC (WINAPI*)(IDWriteBitmapRenderTarget*))this_->v->tbl[4])(this_); } static inline HRESULT IDWriteBitmapRenderTarget_DrawGlyphRun (IDWriteBitmapRenderTarget* this_, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, const DWRITE_GLYPH_RUN* glyphRun, IDWriteRenderingParams* renderingParams, COLORREF textColor, RECT* blackBoxRect) { return ((HRESULT (WINAPI*)(IDWriteBitmapRenderTarget*, FLOAT, FLOAT, DWRITE_MEASURING_MODE, const DWRITE_GLYPH_RUN*, IDWriteRenderingParams*, COLORREF, RECT*))this_->v->tbl[3])(this_, baselineOriginX, baselineOriginY, measuringMode, glyphRun, renderingParams, textColor, blackBoxRect); } static inline UINT32 IDWriteFontFace_Release (IDWriteFontFace* this_) { return ((UINT32 (WINAPI*)(IDWriteFontFace*))this_->v->tbl[2])(this_); } static inline void IDWriteFontFace_GetMetrics (IDWriteFontFace* this_, DWRITE_FONT_METRICS* fontFaceMetrics) { ((void (WINAPI*)(IDWriteFontFace*, DWRITE_FONT_METRICS*))this_->v->tbl[8])(this_, fontFaceMetrics); } static inline UINT32 IDWriteFontFile_Release (IDWriteFontFile* this_) { return ((UINT32 (WINAPI*)(IDWriteFontFile*))this_->v->tbl[2])(this_); } static inline HRESULT IDWriteFontFace_GetGlyphIndices (IDWriteFontFace* this_, const UINT32* codePoints, UINT32 codePointCount, UINT16* glyphIndices) { return ((HRESULT (WINAPI*)(IDWriteFontFace*, const UINT32*, UINT32, UINT16*))this_->v->tbl[11])(this_, codePoints, codePointCount, glyphIndices); } static inline HRESULT IDWriteFontFace_GetGdiCompatibleGlyphMetrics (IDWriteFontFace* this_, FLOAT emSize, FLOAT pixelsPerDip, const DWRITE_MATRIX* transform, BOOL useGdiNatural, const UINT16* glyphIndices, UINT32 glyphCount, DWRITE_GLYPH_METRICS* glyphMetrics, BOOL isSideways) { return ((HRESULT (WINAPI*)(IDWriteFontFace*, FLOAT, FLOAT, const DWRITE_MATRIX*, BOOL, const UINT16*, UINT32, DWRITE_GLYPH_METRICS*, BOOL))this_->v->tbl[17])(this_, emSize, pixelsPerDip, transform, useGdiNatural, glyphIndices, glyphCount, glyphMetrics, isSideways); } static inline UINT32 IDWriteBitmapRenderTarget_Release (IDWriteBitmapRenderTarget* this_) { return ((UINT32 (WINAPI*)(IDWriteBitmapRenderTarget*))this_->v->tbl[2])(this_); } //////////////////////////////// //~ rjf: Font Provider Implementation Types //- rjf: font file loader interface types typedef struct FP_DWrite_FontFileLoader FP_DWrite_FontFileLoader; typedef struct FP_DWrite_FontFileLoaderVTable FP_DWrite_FontFileLoaderVTable; struct FP_DWrite_FontFileLoaderVTable { HRESULT (*QueryInterface)(void *obj, REFIID riid, void *ptr_to_object); ULONG (*AddRef)(void *obj); ULONG (*Release)(void *obj); HRESULT (*CreateStreamFromKey)(FP_DWrite_FontFileLoader *loader, void const *font_file_ref_key, UINT32 font_file_ref_key_size, IDWriteFontFileStream **stream_out); }; struct FP_DWrite_FontFileLoader { FP_DWrite_FontFileLoaderVTable *lpVtbl; }; //- rjf: font file stream interface types typedef struct FP_DWrite_FontFileStream FP_DWrite_FontFileStream; typedef struct FP_DWrite_FontFileStreamVTable FP_DWrite_FontFileStreamVTable; typedef struct FP_DWrite_FontFileStreamNode FP_DWrite_FontFileStreamNode; struct FP_DWrite_FontFileStreamVTable { HRESULT (*QueryInterface)(void *obj, REFIID riid, void *ptr_to_object); ULONG (*AddRef)(void *obj); ULONG (*Release)(void *obj); HRESULT (*ReadFileFragment)(FP_DWrite_FontFileStream *obj, void const **fragment_start, UINT64 file_offset, UINT64 fragment_size, void **fragment_context); HRESULT (*ReleaseFileFragment)(FP_DWrite_FontFileStream *obj, void *fragment_context); HRESULT (*GetFileSize)(FP_DWrite_FontFileStream *obj, UINT64 *size_out); HRESULT (*GetLastWriteTime)(FP_DWrite_FontFileStream *obj, UINT64 *time_out); }; struct FP_DWrite_FontFileStream { FP_DWrite_FontFileStreamVTable *lpVtbl; String8 *data; }; struct FP_DWrite_FontFileStreamNode { FP_DWrite_FontFileStreamNode *next; FP_DWrite_FontFileStreamNode *prev; FP_DWrite_FontFileStream stream; }; //- rjf: state & underlying handle types typedef struct FP_DWrite_State FP_DWrite_State; struct FP_DWrite_State { Arena *arena; B32 dwrite2_is_supported; IDWriteFactory *factory; IDWriteRenderingParams *base_rendering_params; IDWriteRenderingParams *rendering_params_sharp_hinted; IDWriteRenderingParams *rendering_params_sharp_unhinted; IDWriteRenderingParams *rendering_params_smooth_hinted; IDWriteRenderingParams *rendering_params_smooth_unhinted; IDWriteGdiInterop *gdi_interop; Vec2S32 bitmap_render_target_dim; IDWriteBitmapRenderTarget *bitmap_render_target; FP_DWrite_FontFileStreamNode *first_stream_node; FP_DWrite_FontFileStreamNode *last_stream_node; FP_DWrite_FontFileStreamNode *free_stream_node; }; typedef struct FP_DWrite_Font FP_DWrite_Font; struct FP_DWrite_Font { IDWriteFontFile *file; IDWriteFontFace *face; }; //////////////////////////////// //~ rjf: Helpers //- rjf: handle conversion functions internal FP_DWrite_Font fp_dwrite_font_from_handle(FP_Handle handle); internal FP_Handle fp_dwrite_handle_from_font(FP_DWrite_Font font); //- rjf: file stream allocator internal FP_DWrite_FontFileStreamNode *fp_dwrite_font_file_stream_node_alloc(String8 *data_ptr); internal void fp_dwrite_font_file_stream_node_release(FP_DWrite_FontFileStreamNode *node); //- rjf: iunknown no-op helpers internal HRESULT fp_dwrite_iunknown_noop__query_interface(void *obj, REFIID riid, void *ptr_to_object); internal ULONG fp_dwrite_iunknown_noop__add_ref(void *obj); internal ULONG fp_dwrite_iunknown_noop__release(void *obj); //- rjf: font file loader interface function implementations internal HRESULT fp_dwrite_static_font_file_loader__stream_from_key(FP_DWrite_FontFileLoader *obj, void const *font_file_ref_key, UINT32 font_file_ref_key_size, IDWriteFontFileStream **stream_out); //- rjf: font file stream interface function implementations internal HRESULT fp_dwrite_static_font_file_stream__read_file_fragment(FP_DWrite_FontFileStream *obj, void const **fragment_start, UINT64 file_offset, UINT64 fragment_size, void **fragment_context); internal HRESULT fp_dwrite_static_font_file_stream__release_file_fragment(FP_DWrite_FontFileStream *obj, void *fragment_context); internal HRESULT fp_dwrite_static_font_file_stream__get_file_size(FP_DWrite_FontFileStream *obj, UINT64 *size_out); internal HRESULT fp_dwrite_static_font_file_stream__get_last_write_time(FP_DWrite_FontFileStream *obj, UINT64 *time_out); #endif // FONT_PROVIDER_DWRITE_H ================================================ FILE: src/font_provider/font_provider.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Basic Type Functions internal FP_Handle fp_handle_zero(void) { FP_Handle result = {0}; return result; } internal B32 fp_handle_match(FP_Handle a, FP_Handle b) { return (a.u64[0] == b.u64[0] && a.u64[1] == b.u64[1]); } ================================================ FILE: src/font_provider/font_provider.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_H #define FONT_PROVIDER_H #define fp_hook C_LINKAGE //////////////////////////////// //~ rjf: Types typedef U32 FP_RasterFlags; enum { FP_RasterFlag_Smooth = (1<<0), FP_RasterFlag_Hinted = (1<<1), }; typedef struct FP_Handle FP_Handle; struct FP_Handle { U64 u64[2]; }; typedef struct FP_Metrics FP_Metrics; struct FP_Metrics { F32 design_units_per_em; F32 ascent; F32 descent; F32 line_gap; F32 capital_height; }; typedef struct FP_RasterResult FP_RasterResult; struct FP_RasterResult { Vec2S16 atlas_dim; void *atlas; F32 advance; }; //////////////////////////////// //~ rjf: Basic Type Functions internal FP_Handle fp_handle_zero(void); internal B32 fp_handle_match(FP_Handle a, FP_Handle b); //////////////////////////////// //~ rjf: Backend Hooks fp_hook void fp_init(void); fp_hook FP_Handle fp_font_open(String8 path); fp_hook FP_Handle fp_font_open_from_static_data_string(String8 *data_ptr); fp_hook void fp_font_close(FP_Handle handle); fp_hook FP_Metrics fp_metrics_from_font(FP_Handle font); fp_hook NO_ASAN FP_RasterResult fp_raster(Arena *arena, FP_Handle font, F32 size, FP_RasterFlags flags, String8 string); #endif // FONT_PROVIDER_H ================================================ FILE: src/font_provider/font_provider_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "font_provider.c" #if FP_BACKEND == FP_BACKEND_DWRITE # include "dwrite/font_provider_dwrite.c" #elif FP_BACKEND == FP_BACKEND_FREETYPE # include "freetype/font_provider_freetype.c" #else # error Font provider backend not specified. #endif ================================================ FILE: src/font_provider/font_provider_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_INC_H #define FONT_PROVIDER_INC_H //////////////////////////////// //~ rjf: Backend Constants #define FP_BACKEND_DWRITE 1 #define FP_BACKEND_FREETYPE 2 //////////////////////////////// //~ rjf: Decide On Backend #if !defined(FP_BACKEND) # if OS_WINDOWS # define FP_BACKEND FP_BACKEND_DWRITE # elif OS_LINUX # define FP_BACKEND FP_BACKEND_FREETYPE # endif #endif //////////////////////////////// //~ rjf: Main Includes #include "font_provider.h" //////////////////////////////// //~ rjf: Backend Includes #if FP_BACKEND == FP_BACKEND_DWRITE # include "dwrite/font_provider_dwrite.h" #elif FP_BACKEND == FP_BACKEND_FREETYPE # include "freetype/font_provider_freetype.h" #else # error Font provider backend not specified. #endif #endif // FONT_PROVIDER_INC_H ================================================ FILE: src/font_provider/freetype/font_provider_freetype.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal FP_FT_Font fp_ft_font_from_handle(FP_Handle handle) { FP_FT_Font result = {(FT_Face)handle.u64[0]}; return result; } internal FP_Handle fp_ft_handle_from_font(FP_FT_Font font) { FP_Handle result = {(U64)font.face}; return result; } //////////////////////////////// //~ rjf: Backend Implementations fp_hook void fp_init(void) { Arena *arena = arena_alloc(); fp_ft_state = push_array(arena, FP_FT_State, 1); fp_ft_state->arena = arena; FT_Init_FreeType(&fp_ft_state->library); } fp_hook FP_Handle fp_font_open(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); FP_FT_Font font = {0}; FT_New_Face(fp_ft_state->library, (char *)path_copy.str, 0, &font.face); FP_Handle handle = fp_ft_handle_from_font(font); scratch_end(scratch); return handle; } fp_hook FP_Handle fp_font_open_from_static_data_string(String8 *data_ptr) { FP_FT_Font font = {0}; FT_New_Memory_Face(fp_ft_state->library, data_ptr->str, (FT_Long)data_ptr->size, 0, &font.face); FP_Handle handle = fp_ft_handle_from_font(font); return handle; } fp_hook void fp_font_close(FP_Handle handle) { FP_FT_Font font = fp_ft_font_from_handle(handle); if(font.face != 0) { FT_Done_Face(font.face); } } fp_hook FP_Metrics fp_metrics_from_font(FP_Handle handle) { FP_FT_Font font = fp_ft_font_from_handle(handle); FP_Metrics result = {0}; if(font.face != 0) { result.design_units_per_em = (F32)(font.face->units_per_EM); result.ascent = (F32)font.face->ascender; result.descent = -(F32)font.face->descender; result.line_gap = (F32)(font.face->height - font.face->ascender + font.face->descender); result.capital_height = (F32)(font.face->ascender); } return result; } fp_hook FP_RasterResult fp_raster(Arena *arena, FP_Handle handle, F32 size, FP_RasterFlags flags, String8 string) { ProfBeginFunction(); FP_FT_Font font = fp_ft_font_from_handle(handle); FP_RasterResult result = {0}; if(font.face != 0) { Temp scratch = scratch_begin(&arena, 1); //- rjf: unpack font FT_Face face = font.face; FT_Set_Pixel_Sizes(face, 0, (FT_UInt)((96.f/72.f) * size)); S64 ascent = face->size->metrics.ascender >> 6; S64 descent = abs_s64(face->size->metrics.descender >> 6); S64 height = face->size->metrics.height >> 6; //- rjf: unpack string String32 string32 = str32_from_8(scratch.arena, string); //- rjf: measure S32 total_width = 0; for EachIndex(idx, string32.size) { FT_Load_Char(face, string32.str[idx], FT_LOAD_RENDER); total_width += (face->glyph->advance.x >> 6); } //- rjf: allocate & fill atlas w/ rasterization Vec2S16 dim = {(S16)total_width+1, height+1}; U64 atlas_size = dim.x * dim.y * 4; U8 *atlas = push_array(arena, U8, atlas_size); S32 baseline = ascent; S32 atlas_write_x = 0; for EachIndex(idx, string32.size) { FT_Load_Char(face, string32.str[idx], FT_LOAD_RENDER); FT_Bitmap *bmp = &face->glyph->bitmap; S32 top = face->glyph->bitmap_top; S32 left = face->glyph->bitmap_left; for(S32 row = 0; row < (S32)bmp->rows; row += 1) { S32 y = baseline - top + row; for(S32 col = 0; col < (S32)bmp->width; col += 1) { S32 x = atlas_write_x + left + col; U64 off = (y*dim.x + x)*4; if(off+4 <= atlas_size) { atlas[off+0] = 255; atlas[off+1] = 255; atlas[off+2] = 255; atlas[off+3] = bmp->buffer[row*bmp->pitch + col]; } } } atlas_write_x += (face->glyph->advance.x >> 6); } //- rjf: fill result result.atlas_dim = dim; result.advance = (F32)total_width; result.atlas = atlas; scratch_end(scratch); } ProfEnd(); return result; } ================================================ FILE: src/font_provider/freetype/font_provider_freetype.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_FREETYPE_H #define FONT_PROVIDER_FREETYPE_H //////////////////////////////// //~ rjf: Freetype Includes #undef internal #include #include FT_FREETYPE_H #include FT_GLYPH_H #define internal static //////////////////////////////// //~ rjf: State Types typedef struct FP_FT_Font FP_FT_Font; struct FP_FT_Font { FT_Face face; }; typedef struct FP_FT_State FP_FT_State; struct FP_FT_State { Arena *arena; FT_Library library; }; //////////////////////////////// //~ rjf: Globals global FP_FT_State *fp_ft_state = 0; //////////////////////////////// //~ rjf: Helpers internal FP_FT_Font fp_ft_font_from_handle(FP_Handle handle); internal FP_Handle fp_ft_handle_from_font(FP_FT_Font font); #endif // FONT_PROVIDER_FREETYPE_H ================================================ FILE: src/gnu/gnu.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal GNU_LinkMap64 gnu_linkmap64_from_linkmap32(GNU_LinkMap32 linkmap32) { GNU_LinkMap64 linkmap64 = {0}; linkmap64.addr_vaddr = linkmap32.addr_vaddr; linkmap64.name_vaddr = linkmap32.name_vaddr; linkmap64.ld_vaddr = linkmap32.ld_vaddr; linkmap64.next_vaddr = linkmap32.next_vaddr; linkmap64.prev_vaddr = linkmap32.prev_vaddr; return linkmap64; } internal U64 gnu_rdebug_info_size_from_arch(Arch arch) { U64 size = 0; switch (byte_size_from_arch(arch)) { case 0: break; case 4: size = sizeof(GNU_RDebugInfo32); break; case 8: size = sizeof(GNU_RDebugInfo64); break; default: InvalidPath; break; } return size; } internal U64 gnu_r_brk_offset_from_arch(Arch arch) { U64 offset = 0; switch (gnu_rdebug_info_size_from_arch(arch)) { case 0: offset = 0; break; case sizeof(GNU_RDebugInfo32): offset = OffsetOf(GNU_RDebugInfo32, r_brk); break; case sizeof(GNU_RDebugInfo64): offset = OffsetOf(GNU_RDebugInfo64, r_brk); break; default: InvalidPath; break; } return offset; } internal GNU_RDebugInfo64 gnu_rdebug_info64_from_rdebug_info32(GNU_RDebugInfo32 rdebug32) { GNU_RDebugInfo64 result = {0}; result.r_version = rdebug32.r_version; result.r_map = rdebug32.r_map; result.r_brk = rdebug32.r_brk; result.r_state = rdebug32.r_state; result.r_ldbase = rdebug32.r_ldbase; return result; } internal String8 gnu_string_from_abi_tag(GNU_AbiTag abi_tag) { switch (abi_tag) { case GNU_AbiTag_Linux: return str8_lit("Linux"); case GNU_AbiTag_Hurd: return str8_lit("Hurd"); case GNU_AbiTag_Solaris: return str8_lit("Solaris"); case GNU_AbiTag_FreeBsd: return str8_lit("FreeBsd"); case GNU_AbiTag_NetBsd: return str8_lit("NetBsd"); case GNU_AbiTag_Syllable: return str8_lit("Syllable"); case GNU_AbiTag_Nacl: return str8_lit("Nacl"); } return str8_zero(); } internal String8 gnu_string_from_note_type(GNU_NoteType note_type) { switch (note_type) { case GNU_NoteType_Abi: return str8_lit("GNU_Abi"); case GNU_NoteType_HwCap: return str8_lit("GNU_HwCap"); case GNU_NoteType_BuildId: return str8_lit("GNU_BuildId"); case GNU_NoteType_GoldVersion: return str8_lit("GNU_GoldVersion"); case GNU_NoteType_PropertyType0: return str8_lit("GNU_PropertyType0"); } return str8_zero(); } internal String8 gnu_string_from_property_x86(GNU_PropertyX86 prop) { switch (prop) { case GNU_PropertyX86_Feature1And: return str8_lit("Feature1And"); case GNU_PropertyX86_Feature2Used: return str8_lit("Feature2Used"); case GNU_PropertyX86_Isa1needed: return str8_lit("Isa1needed"); case GNU_PropertyX86_Isa2Needed: return str8_lit("Isa2Needed"); case GNU_PropertyX86_Isa1Used: return str8_lit("Isa1Used"); case GNU_PropertyX86_Compat_isa_1_used: return str8_lit("Compat_isa_1_used"); case GNU_PropertyX86_Compat_isa_1_needed: return str8_lit("Compat_isa_1_needed"); case GNU_PropertyX86_UInt32AndHi: return str8_lit("UInt32AndHi"); case GNU_PropertyX86_UInt32OrLo: return str8_lit("UInt32OrLo"); case GNU_PropertyX86_UInt32OrHi: return str8_lit("UInt32OrHi"); case GNU_PropertyX86_UInt32OrAndLo: return str8_lit("UInt32OrAndLo"); case GNU_PropertyX86_UInt32OrAndHi: return str8_lit("UInt32OrAndHi"); } return str8_zero(); } internal String8 gnu_string_from_property_flags_x86(Arena *arena, GNU_PropertyX86 prop, U32 flags) { Temp scratch = scratch_begin(&arena, 1); String8List fmt = {0}; if (flags == 0) { str8_list_pushf(scratch.arena, &fmt, "None"); } switch (prop) { case GNU_PropertyX86_Isa1needed: case GNU_PropertyX86_Isa1Used: { if (flags & GNU_PropertyX86Isa1_BaseLine) { str8_list_pushf(scratch.arena, &fmt, "BaseLine"); flags &= ~GNU_PropertyX86Isa1_BaseLine; } if (flags & GNU_PropertyX86Isa1_V2) { str8_list_pushf(scratch.arena, &fmt, "V2"); flags &= ~GNU_PropertyX86Isa1_V2; } if (flags & GNU_PropertyX86Isa1_V3) { str8_list_pushf(scratch.arena, &fmt, "V3"); flags &= ~GNU_PropertyX86Isa1_V3; } if (flags & GNU_PropertyX86Isa1_V4) { str8_list_pushf(scratch.arena, &fmt, "V4"); flags &= ~GNU_PropertyX86Isa1_V4; } } break; case GNU_PropertyX86_Feature1And: { if (flags & GNU_PropertyX86Feature1_Ibt) { str8_list_pushf(scratch.arena, &fmt, "Ibt"); flags &= ~GNU_PropertyX86Feature1_Ibt; } if (flags & GNU_PropertyX86Feature1_Shstk) { str8_list_pushf(scratch.arena, &fmt, "Shstk"); flags &= ~GNU_PropertyX86Feature1_Shstk; } if (flags & GNU_PropertyX86Feature1_LamU48) { str8_list_pushf(scratch.arena, &fmt, "LamU48"); flags &= ~GNU_PropertyX86Feature1_LamU48; } if (flags & GNU_PropertyX86Feature1_LamU57) { str8_list_pushf(scratch.arena, &fmt, "LamU57"); flags &= ~GNU_PropertyX86Feature1_LamU57; } } break; case GNU_PropertyX86_Feature2Used: { if (flags & GNU_PropertyX86Feature2_X86) { str8_list_pushf(scratch.arena, &fmt, "X86"); flags &= ~GNU_PropertyX86Feature2_X86; } if (flags & GNU_PropertyX86Feature2_X87) { str8_list_pushf(scratch.arena, &fmt, "X87"); flags &= ~GNU_PropertyX86Feature2_X87; } if (flags & GNU_PropertyX86Feature2_MMX) { str8_list_pushf(scratch.arena, &fmt, "MMX"); flags &= ~GNU_PropertyX86Feature2_MMX; } if (flags & GNU_PropertyX86Feature2_XMM) { str8_list_pushf(scratch.arena, &fmt, "XMM"); flags &= ~GNU_PropertyX86Feature2_XMM; } if (flags & GNU_PropertyX86Feature2_YMM) { str8_list_pushf(scratch.arena, &fmt, "YMM"); flags &= ~GNU_PropertyX86Feature2_YMM; } if (flags & GNU_PropertyX86Feature2_ZMM) { str8_list_pushf(scratch.arena, &fmt, "ZMM"); flags &= ~GNU_PropertyX86Feature2_ZMM; } if (flags & GNU_PropertyX86Feature2_FXSR) { str8_list_pushf(scratch.arena, &fmt, "FXSR"); flags &= ~GNU_PropertyX86Feature2_FXSR; } if (flags & GNU_PropertyX86Feature2_XSAVE) { str8_list_pushf(scratch.arena, &fmt, "XSAVE"); flags &= ~GNU_PropertyX86Feature2_XSAVE; } if (flags & GNU_PropertyX86Feature2_XSAVEOPT) { str8_list_pushf(scratch.arena, &fmt, "XSAVEOPT"); flags &= ~GNU_PropertyX86Feature2_XSAVEOPT; } if (flags & GNU_PropertyX86Feature2_XSAVEC) { str8_list_pushf(scratch.arena, &fmt, "XSAVEC"); flags &= ~GNU_PropertyX86Feature2_XSAVEC; } if (flags & GNU_PropertyX86Feature2_TMM) { str8_list_pushf(scratch.arena, &fmt, "TMM"); flags &= ~GNU_PropertyX86Feature2_TMM; } if (flags & GNU_PropertyX86Feature2_MASK) { str8_list_pushf(scratch.arena, &fmt, "MASK"); flags &= ~GNU_PropertyX86Feature2_MASK; } } break; case GNU_PropertyX86_Compat_isa_1_used: case GNU_PropertyX86_Compat_isa_1_needed: { if (flags & GNU_PropertyX86Compat1Isa1_486) { str8_list_pushf(scratch.arena, &fmt, "486"); flags &= ~GNU_PropertyX86Compat1Isa1_486; } if (flags & GNU_PropertyX86Compat1Isa1_586) { str8_list_pushf(scratch.arena, &fmt, "586"); flags &= ~GNU_PropertyX86Compat1Isa1_586; } if (flags & GNU_PropertyX86Compat1Isa1_686) { str8_list_pushf(scratch.arena, &fmt, "686"); flags &= ~GNU_PropertyX86Compat1Isa1_686; } if (flags & GNU_PropertyX86Compat1Isa1_SSE) { str8_list_pushf(scratch.arena, &fmt, "SSE"); flags &= ~GNU_PropertyX86Compat1Isa1_SSE; } if (flags & GNU_PropertyX86Compat1Isa1_SSE2) { str8_list_pushf(scratch.arena, &fmt, "SSE2"); flags &= ~GNU_PropertyX86Compat1Isa1_SSE2; } if (flags & GNU_PropertyX86Compat1Isa1_SSE3) { str8_list_pushf(scratch.arena, &fmt, "SSE3"); flags &= ~GNU_PropertyX86Compat1Isa1_SSE3; } if (flags & GNU_PropertyX86Compat1Isa1_SSSE3) { str8_list_pushf(scratch.arena, &fmt, "SSSE3"); flags &= ~GNU_PropertyX86Compat1Isa1_SSSE3; } if (flags & GNU_PropertyX86Compat1Isa1_SSE4_1) { str8_list_pushf(scratch.arena, &fmt, "SSE4_1"); flags &= ~GNU_PropertyX86Compat1Isa1_SSE4_1; } if (flags & GNU_PropertyX86Compat1Isa1_SSE4_2) { str8_list_pushf(scratch.arena, &fmt, "SSE4_2"); flags &= ~GNU_PropertyX86Compat1Isa1_SSE4_2; } if (flags & GNU_PropertyX86Compat1Isa1_AVX) { str8_list_pushf(scratch.arena, &fmt, "AVX"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX; } if (flags & GNU_PropertyX86Compat1Isa1_AVX2) { str8_list_pushf(scratch.arena, &fmt, "AVX2"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX2; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512F) { str8_list_pushf(scratch.arena, &fmt, "AVX512F"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512F; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512ER) { str8_list_pushf(scratch.arena, &fmt, "AVX512ER"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512ER; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512PF) { str8_list_pushf(scratch.arena, &fmt, "AVX512PF"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512PF; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512VL) { str8_list_pushf(scratch.arena, &fmt, "AVX512VL"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512VL; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512DQ) { str8_list_pushf(scratch.arena, &fmt, "AVX512DQ"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512DQ; } if (flags & GNU_PropertyX86Compat1Isa1_AVX512BW) { str8_list_pushf(scratch.arena, &fmt, "AVX512BW"); flags &= ~GNU_PropertyX86Compat1Isa1_AVX512BW; } } break; } if (flags) { str8_list_pushf(scratch.arena, &fmt, "Unknown: 0x%x", flags); } String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); scratch_end(scratch); return result; } ================================================ FILE: src/gnu/gnu.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef GNU_H #define GNU_H typedef ELF_NoteType GNU_NoteType; enum { GNU_NoteType_Abi = 1, GNU_NoteType_HwCap = 2, GNU_NoteType_BuildId = 3, GNU_NoteType_GoldVersion = 4, GNU_NoteType_PropertyType0 = 5, }; typedef U32 GNU_Property; enum { GNU_Property_LoProc = 0xc0000000, // processor-specific range GNU_Property_HiProc = 0xdfffffff, GNU_Property_LoUser = 0xe0000000, // application-specific range GNU_Property_HiUser = 0xffffffff, GNU_Property_StackSize = 1, GNU_Property_NoCopyOnProtected = 2, }; typedef U32 GNU_PropertyX86Isa1; enum { GNU_PropertyX86Isa1_BaseLine = (1 << 0), GNU_PropertyX86Isa1_V2 = (1 << 1), GNU_PropertyX86Isa1_V3 = (1 << 2), GNU_PropertyX86Isa1_V4 = (1 << 3), }; typedef U32 GNU_PropertyX86Compat1Isa1; enum { GNU_PropertyX86Compat1Isa1_486 = (1 << 0), GNU_PropertyX86Compat1Isa1_586 = (1 << 1), GNU_PropertyX86Compat1Isa1_686 = (1 << 2), GNU_PropertyX86Compat1Isa1_SSE = (1 << 3), GNU_PropertyX86Compat1Isa1_SSE2 = (1 << 4), GNU_PropertyX86Compat1Isa1_SSE3 = (1 << 5), GNU_PropertyX86Compat1Isa1_SSSE3 = (1 << 6), GNU_PropertyX86Compat1Isa1_SSE4_1 = (1 << 7), GNU_PropertyX86Compat1Isa1_SSE4_2 = (1 << 8), GNU_PropertyX86Compat1Isa1_AVX = (1 << 9), GNU_PropertyX86Compat1Isa1_AVX2 = (1 << 10), GNU_PropertyX86Compat1Isa1_AVX512F = (1 << 11), GNU_PropertyX86Compat1Isa1_AVX512ER = (1 << 12), GNU_PropertyX86Compat1Isa1_AVX512PF = (1 << 13), GNU_PropertyX86Compat1Isa1_AVX512VL = (1 << 14), GNU_PropertyX86Compat1Isa1_AVX512DQ = (1 << 15), GNU_PropertyX86Compat1Isa1_AVX512BW = (1 << 16), }; typedef U32 GNU_PropertyX86Compat2Isa1; enum { GNU_PropertyX86Compat2Isa1_CMOVE = (1 << 0), GNU_PropertyX86Compat2Isa1_SSE = (1 << 1), GNU_PropertyX86Compat2Isa1_SSE2 = (1 << 2), GNU_PropertyX86Compat2Isa1_SSE3 = (1 << 3), GNU_PropertyX86Compat2Isa1_SSE4_1 = (1 << 4), GNU_PropertyX86Compat2Isa1_SSE4_2 = (1 << 5), GNU_PropertyX86Compat2Isa1_AVX = (1 << 6), GNU_PropertyX86Compat2Isa1_AVX2 = (1 << 7), GNU_PropertyX86Compat2Isa1_FMA = (1 << 8), GNU_PropertyX86Compat2Isa1_AVX512F = (1 << 9), GNU_PropertyX86Compat2Isa1_AVX512CD = (1 << 10), GNU_PropertyX86Compat2Isa1_AVX512ER = (1 << 11), GNU_PropertyX86Compat2Isa1_AVX512PF = (1 << 12), GNU_PropertyX86Compat2Isa1_AVX512VL = (1 << 13), GNU_PropertyX86Compat2Isa1_AVX512DQ = (1 << 14), GNU_PropertyX86Compat2Isa1_AVX512BW = (1 << 15), GNU_PropertyX86Compat2Isa1_AVX512_4FMAPS = (1 << 16), GNU_PropertyX86Compat2Isa1_AVX512_4VNNIW = (1 << 17), GNU_PropertyX86Compat2Isa1_AVX512_BITALG = (1 << 18), GNU_PropertyX86Compat2Isa1_AVX512_IFMA = (1 << 19), GNU_PropertyX86Compat2Isa1_AVX512_VBMI = (1 << 20), GNU_PropertyX86Compat2Isa1_AVX512_VBMI2 = (1 << 21), GNU_PropertyX86Compat2Isa1_AVX512_VNNI = (1 << 22), GNU_PropertyX86Compat2Isa1_AVX512_BF16 = (1 << 23), }; typedef GNU_Property GNU_PropertyX86; enum { GNU_PropertyX86_Feature1And = 0xc0000002, GNU_PropertyX86_Feature2Used = 0xc0010001, GNU_PropertyX86_Isa1needed = 0xc0008002, GNU_PropertyX86_Isa2Needed = 0xc0008001, GNU_PropertyX86_Isa1Used = 0xc0010002, GNU_PropertyX86_Compat_isa_1_used = 0xc0000000, GNU_PropertyX86_Compat_isa_1_needed = 0xc0000001, GNU_PropertyX86_UInt32AndLo = GNU_PropertyX86_Feature1And, GNU_PropertyX86_UInt32AndHi = 0xc0007fff, GNU_PropertyX86_UInt32OrLo = 0xc0008000, GNU_PropertyX86_UInt32OrHi = 0xc000ffff, GNU_PropertyX86_UInt32OrAndLo = 0xc0010000, GNU_PropertyX86_UInt32OrAndHi = 0xc0017fff, }; typedef U32 GNU_PropertyX86Feature1; enum { GNU_PropertyX86Feature1_Ibt = (1 << 0), GNU_PropertyX86Feature1_Shstk = (1 << 1), GNU_PropertyX86Feature1_LamU48 = (1 << 2), GNU_PropertyX86Feature1_LamU57 = (1 << 3), }; typedef U32 GNU_PropertyX86Feature2; enum { GNU_PropertyX86Feature2_X86 = (1 << 0), GNU_PropertyX86Feature2_X87 = (1 << 1), GNU_PropertyX86Feature2_MMX = (1 << 2), GNU_PropertyX86Feature2_XMM = (1 << 3), GNU_PropertyX86Feature2_YMM = (1 << 4), GNU_PropertyX86Feature2_ZMM = (1 << 5), GNU_PropertyX86Feature2_FXSR = (1 << 6), GNU_PropertyX86Feature2_XSAVE = (1 << 7), GNU_PropertyX86Feature2_XSAVEOPT = (1 << 8), GNU_PropertyX86Feature2_XSAVEC = (1 << 9), GNU_PropertyX86Feature2_TMM = (1 << 10), GNU_PropertyX86Feature2_MASK = (1 << 11), }; typedef U32 GNU_AbiTag; enum { GNU_AbiTag_Linux = 0, GNU_AbiTag_Hurd = 1, GNU_AbiTag_Solaris = 2, GNU_AbiTag_FreeBsd = 3, GNU_AbiTag_NetBsd = 4, GNU_AbiTag_Syllable = 5, GNU_AbiTag_Nacl = 6, }; typedef struct GNU_LinkMap64 { U64 addr_vaddr; U64 name_vaddr; U64 ld_vaddr; // address of the dynamic section U64 next_vaddr; U64 prev_vaddr; } GNU_LinkMap64; typedef struct GNU_LinkMap32 { U32 addr_vaddr; U32 name_vaddr; U32 ld_vaddr; U32 next_vaddr; U32 prev_vaddr; } GNU_LinkMap32; typedef U32 GNU_RT; enum { GNU_RT_Consistent = 0, GNU_RT_Add = 1, GNU_RT_Delete = 2, }; // struct reflects r_debug from /usr/include/link.h typedef struct GNU_RDebugInfo64 { S32 r_version; // must be greater than 0 U64 r_map; // address of first loaded object U64 r_brk; // when module is loared/unloaded DL calls this function GNU_RT r_state; U64 r_ldbase; // base addres of dynamic linker } GNU_RDebugInfo64; typedef struct GNU_RDebugInfo32 { S32 r_version; U32 r_map; U32 r_brk; GNU_RT r_state; U32 r_ldbase; } GNU_RDebugInfo32; //////////////////////////////// internal GNU_LinkMap64 elf_linkmap64_from_linkmap32(GNU_LinkMap32 linkmap32); internal U64 gnu_rdebug_info_size_from_arch(Arch arch); internal U64 gnu_r_brk_offset_from_arch(Arch arch); //////////////////////////////// //~ enum internal String8 gnu_string_from_abi_tag(GNU_AbiTag abi_tag); internal String8 gnu_string_from_note_type(GNU_NoteType note_type); internal String8 gnu_string_from_property_x86(GNU_PropertyX86 prop); #endif // GNU_H ================================================ FILE: src/lib_raddbg_markup/raddbg_markup.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_MARKUP_H #define RADDBG_MARKUP_H //////////////////////////////// //~ Implementation Overrides #if !defined(RADDBG_MARKUP_VSNPRINTF) # define RADDBG_MARKUP_DEFAULT_VSNPRINTF 1 # define RADDBG_MARKUP_VSNPRINTF vsnprintf #endif #if !defined(RADDBG_MARKUP_STL_TYPE_VIEWS) # define RADDBG_MARKUP_STL_TYPE_VIEWS 1 #endif //////////////////////////////// //~ Usage Macros #if !defined(RADDBG_MARKUP_STUBS) # define raddbg_is_attached(...) raddbg_is_attached__impl() # define raddbg_thread_id(...) raddbg_thread_id__impl() # define raddbg_thread_name(fmt, ...) raddbg_thread_name__impl(raddbg_thread_id(), (fmt), __VA_ARGS__) # define raddbg_thread_id_name(id, fmt, ...) raddbg_thread_name__impl((id), (fmt), __VA_ARGS__) # define raddbg_thread_color_u32(u32) raddbg_thread_color__impl(raddbg_thread_id(), (u32)) # define raddbg_thread_color_rgba(r, g, b, a) raddbg_thread_color__impl(raddbg_thread_id(), ((unsigned int)((r)*255) << 24) | ((unsigned int)((g)*255) << 16) | ((unsigned int)((b)*255) << 8) | ((unsigned int)(a)*255)) # define raddbg_thread_id_color_u32(id, u32) raddbg_thread_color__impl((id), (u32)) # define raddbg_thread_id_color_rgba(id, r, g, b, a) raddbg_thread_color__impl((id), ((unsigned int)((r)*255) << 24) | ((unsigned int)((g)*255) << 16) | ((unsigned int)((b)*255) << 8) | ((unsigned int)(a)*255)) # define raddbg_break(...) raddbg_break__impl() # define raddbg_break_if(expr, ...) ((expr) ? raddbg_break__impl() : (void)0) # define raddbg_watch(fmt, ...) raddbg_watch__impl((fmt), __VA_ARGS__) # define raddbg_pin(expr, ...) /* NOTE(rjf): inspected by debugger ui - does not change program execution */ # define raddbg_log(fmt, ...) raddbg_log__impl((fmt), __VA_ARGS__) # define raddbg_entry_point(...) raddbg_exe_data char raddbg_gen_data_id()[] = ("entry_point: \"" #__VA_ARGS__ "\"") # define raddbg_type_view(type, ...) raddbg_exe_data char raddbg_gen_data_id()[] = ("type_view: {type: ```" #type "```, expr: ```" #__VA_ARGS__ "```}") # define raddbg_add_breakpoint(ptr, size, r, w, x) raddbg_add_or_remove_breakpoint__impl((ptr), (1), (size), (r), (w), (x)) # define raddbg_remove_breakpoint(ptr, size, r, w, x) raddbg_add_or_remove_breakpoint__impl((ptr), (0), (size), (r), (w), (x)) # define raddbg_annotate_vaddr_range(ptr, size, ...) raddbg_annotate_vaddr_range__impl((ptr), (size), __VA_ARGS__) #else # define raddbg_is_attached(...) (0) # define raddbg_thread_id(...) ((void)0) # define raddbg_thread_name(fmt, ...) ((void)0) # define raddbg_thread_id_name(id, fmt, ...) ((void)0) # define raddbg_thread_color_u32(u32) ((void)0) # define raddbg_thread_color_rgba(r, g, b, a) ((void)0) # define raddbg_thread_id_color_u32(id, u32) ((void)0) # define raddbg_thread_id_color_rgba(id, r, g, b, a) ((void)0) # define raddbg_break(...) ((void)0) # define raddbg_break_if(expr, ...) ((void)expr) # define raddbg_watch(fmt, ...) ((void)0) # define raddbg_pin(expr, ...) # define raddbg_log(fmt, ...) ((void)0) # define raddbg_entry_point(...) struct raddbg_gen_data_id(){int __unused__;} # define raddbg_type_view(type, ...) struct raddbg_gen_data_id(){int __unused__;} # define raddbg_add_breakpoint(ptr, size, r, w, x) ((void)0) # define raddbg_remove_breakpoint(ptr, size, r, w, x) ((void)0) # define raddbg_annotate_vaddr_range(ptr, size, ...) ((void)0) #endif //////////////////////////////// //~ Helpers #define raddbg_glue_(a, b) a##b #define raddbg_glue(a, b) raddbg_glue_(a, b) #define raddbg_gen_data_id() raddbg_glue(raddbg_data__, __COUNTER__) //////////////////////////////// //~ Global Symbols #if !defined(RADDBG_MARKUP_STUBS) extern unsigned char raddbg_is_attached_byte_marker[1]; int raddbg_is_attached__impl(void); int raddbg_thread_id__impl(void); void raddbg_thread_name__impl(int id, char *fmt, ...); void raddbg_thread_color__impl(int id, unsigned int hexcode); void raddbg_watch__impl(char *fmt, ...); void raddbg_log__impl(char *fmt, ...); void raddbg_add_or_remove_breakpoint__impl(void *ptr, int set, int size, int r, int w, int x); void raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, ...); #endif //////////////////////////////// //~ Win32 Implementations #if defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS) //- section allocating #pragma section(".raddbg", read, write) #define raddbg_exe_data __declspec(allocate(".raddbg")) //- one-time implementations #if defined(RADDBG_MARKUP_IMPLEMENTATION) //- default includes #if RADDBG_MARKUP_DEFAULT_VSNPRINTF #include #endif //- special section gets "is attached" byte #pragma section(".rdbgia", read, write) __declspec(allocate(".rdbgia")) unsigned char raddbg_is_attached_byte_marker[1] = {0}; //- types typedef int BOOL; typedef long LONG; typedef unsigned long ULONG; typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; typedef unsigned long DWORD; typedef wchar_t WCHAR; typedef char const *LPCSTR; typedef const WCHAR *LPCWSTR, *PCWSTR; typedef LONG HRESULT; typedef void *HANDLE; struct HINSTANCE__; typedef struct HINSTANCE__ *HMODULE; typedef __int64 INT_PTR; typedef INT_PTR (*FARPROC)(); //- prototypes #include #if defined(__cplusplus) extern "C" { #endif __declspec(dllimport) HMODULE LoadLibraryA(LPCSTR name); __declspec(dllimport) FARPROC GetProcAddress(HMODULE module, LPCSTR name); __declspec(dllimport) BOOL FreeLibrary(HMODULE mod); __declspec(dllimport) HANDLE GetCurrentThread(void); __declspec(dllimport) DWORD GetCurrentThreadId(void); __declspec(dllimport) void RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR *lpArguments); __declspec(dllimport) void OutputDebugStringA(LPCSTR buffer); long long _InterlockedCompareExchange64(long long volatile*, long long, long long); long long _InterlockedExchangeAdd64(long long volatile*, long long); #pragma intrinsic(_InterlockedCompareExchange64) #pragma intrinsic(_InterlockedExchangeAdd64) #if RADDBG_MARKUP_DEFAULT_VSNPRINTF int RADDBG_MARKUP_VSNPRINTF(char * const, unsigned long long const, const char * const, va_list); #endif #if defined(__cplusplus) } #endif //- helpers typedef struct RADDBG_MARKUP_UnicodeDecode RADDBG_MARKUP_UnicodeDecode; struct RADDBG_MARKUP_UnicodeDecode { unsigned __int32 inc; unsigned __int32 codepoint; }; static __int8 raddbg_utf8_class[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5}; static RADDBG_MARKUP_UnicodeDecode raddbg_decode_utf8(char *str, unsigned __int64 max) { RADDBG_MARKUP_UnicodeDecode result = {1, 0xffffffff}; unsigned __int8 byte = str[0]; unsigned __int8 byte_class = raddbg_utf8_class[byte >> 3]; switch(byte_class) { case 1: { result.codepoint = byte; }break; case 2: if(2 < max) { unsigned char cont_byte = str[1]; if(raddbg_utf8_class[cont_byte >> 3] == 0) { result.codepoint = (byte & 0x0000001f) << 6; result.codepoint |= (cont_byte & 0x0000003f); result.inc = 2; } }break; case 3: if(2 < max) { unsigned char cont_byte[2] = {(unsigned char)str[1], (unsigned char)str[2]}; if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && raddbg_utf8_class[cont_byte[1] >> 3] == 0) { result.codepoint = (byte & 0x0000000f) << 12; result.codepoint |= ((cont_byte[0] & 0x0000003f) << 6); result.codepoint |= (cont_byte[1] & 0x0000003f); result.inc = 3; } }break; case 4: if(3 < max) { unsigned char cont_byte[3] = {(unsigned char)str[1], (unsigned char)str[2], (unsigned char)str[3]}; if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && raddbg_utf8_class[cont_byte[1] >> 3] == 0 && raddbg_utf8_class[cont_byte[2] >> 3] == 0) { result.codepoint = (byte & 0x00000007) << 18; result.codepoint |= ((cont_byte[0] & 0x0000003f) << 12); result.codepoint |= ((cont_byte[1] & 0x0000003f) << 6); result.codepoint |= (cont_byte[2] & 0x0000003f); result.inc = 4; } } } return result; } static unsigned __int32 raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint) { unsigned __int32 inc = 1; if(codepoint == 0xffffffff) { str[0] = (wchar_t)'?'; } else if(codepoint < 0x10000) { str[0] = (wchar_t)codepoint; } else { unsigned __int32 v = codepoint - 0x10000; str[0] = (wchar_t)(0xD800 + (v >> 10)); str[1] = (wchar_t)(0xDC00 + (v & 0x000003ff)); inc = 2; } return inc; } //- implementations int raddbg_is_attached__impl(void) { return !!raddbg_is_attached_byte_marker[0]; } int raddbg_thread_id__impl(void) { DWORD result = GetCurrentThreadId(); return result; } void raddbg_thread_name__impl(int id, char *fmt, ...) { // rjf: resolve variadic arguments char buffer[512] = {0}; char *name = buffer; { va_list args; va_start(args, fmt); RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args); va_end(args); } // rjf: get windows 10 style procedure HRESULT (*SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription) = 0; { static HRESULT (*global_SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription); static volatile __int64 global_SetThreadDescription_init_started; static volatile __int64 global_SetThreadDescription_init_done; __int64 do_init = !_InterlockedCompareExchange64(&global_SetThreadDescription_init_started, 1, 0); if(do_init) { HMODULE module = LoadLibraryA("kernel32.dll"); global_SetThreadDescription_function = (HRESULT (*)(HANDLE, PCWSTR))GetProcAddress(module, "SetThreadDescription"); FreeLibrary(module); _InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 1); } for(;_InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 0) == 0;) { // NOTE(rjf): busy-loop, until init is done } SetThreadDescription_function = global_SetThreadDescription_function; } // rjf: set thread name, windows 10 style if(SetThreadDescription_function && id == GetCurrentThreadId()) { WCHAR buffer16[1024] = {0}; int name_length = 0; for(;name[name_length]; name_length += 1); int write_offset = 0; for(int idx = 0; idx < name_length;) { RADDBG_MARKUP_UnicodeDecode decode = raddbg_decode_utf8(name+idx, name_length-idx); write_offset += raddbg_encode_utf16(buffer16 + write_offset, decode.codepoint); idx += decode.inc; } SetThreadDescription_function(GetCurrentThread(), buffer16); } // rjf: set thread name, raise-exception style { #pragma pack(push, 8) typedef struct THREADNAME_INFO THREADNAME_INFO; struct THREADNAME_INFO { DWORD dwType; LPCSTR szName; DWORD dwThreadID; DWORD dwFlags; }; #pragma pack(pop) THREADNAME_INFO info; info.dwType = 0x1000; info.szName = name; info.dwThreadID = id; info.dwFlags = 0; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x406D1388u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except(1) { } #pragma warning(pop) } } void raddbg_thread_color__impl(int id, unsigned int hexcode) { if(raddbg_is_attached()) { #pragma pack(push, 8) typedef struct RADDBG_ThreadColorInfo RADDBG_ThreadColorInfo; struct RADDBG_ThreadColorInfo { DWORD dwThreadID; DWORD _pad_0; DWORD rgba; DWORD _pad_1; }; #pragma pack(pop) RADDBG_ThreadColorInfo info; info.dwThreadID = id; info.rgba = hexcode; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x00524144u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except(1) { } #pragma warning(pop) } } #define raddbg_break__impl() (__debugbreak()) void raddbg_watch__impl(char *fmt, ...) { // TODO(rjf) } void raddbg_log__impl(char *fmt, ...) { // rjf: resolve variadic arguments char buffer[4096]; { va_list args; va_start(args, fmt); RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args); va_end(args); } // rjf: output debug string OutputDebugStringA(buffer); } void raddbg_add_or_remove_breakpoint__impl(void *ptr, int set, int size, int r, int w, int x) { if(raddbg_is_attached()) { #pragma pack(push, 8) typedef struct RADDBG_AddBreakpointInfo RADDBG_AddBreakpointInfo; struct RADDBG_AddBreakpointInfo { unsigned __int64 vaddr; unsigned __int64 size; unsigned __int64 r; unsigned __int64 w; unsigned __int64 x; unsigned __int64 add; }; #pragma pack(pop) RADDBG_AddBreakpointInfo info; info.vaddr = (unsigned __int64)ptr; info.size = size; info.r = r; info.w = w; info.x = x; info.add = set; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x00524145u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except(1) { } #pragma warning(pop) } } void raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, ...) { if(raddbg_is_attached()) { // rjf: resolve variadic arguments char buffer[4096]; int buffer_size = 0; { va_list args; va_start(args, fmt); buffer_size = RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args); buffer_size = ((buffer_size < 0) ? 0 : (buffer_size > sizeof(buffer)) ? sizeof(buffer) : buffer_size); va_end(args); } // rjf: send annotation info via exception #pragma pack(push, 8) typedef struct RADDBG_VaddrRangeAnnotationInfo RADDBG_VaddrRangeAnnotationInfo; struct RADDBG_VaddrRangeAnnotationInfo { unsigned __int64 vaddr; unsigned __int64 size; void *name; unsigned __int64 name_size; }; #pragma pack(pop) RADDBG_VaddrRangeAnnotationInfo info; info.vaddr = (unsigned __int64)ptr; info.size = size; info.name = buffer; info.name_size = buffer_size; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x00524156u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except(1) { } #pragma warning(pop) } } #endif // defined(RADDBG_MARKUP_IMPLEMENTATION) #endif // defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS) //////////////////////////////// //~ Win32 STL Type Views #if defined(_WIN32) && defined(RADDBG_MARKUP_IMPLEMENTATION) && RADDBG_MARKUP_STL_TYPE_VIEWS # if defined(_VECTOR_) raddbg_type_view(std::vector, slice(_Mypair._Myval2)); # endif # if defined(_MEMORY_) raddbg_type_view(std::unique_ptr, _Mypair._Myval2); # endif # if defined(_STRING_) raddbg_type_view(std::basic_string, _Mypair._Myval2._Myres <= 15 ? _Mypair._Myval2._Bx._Buf : array(_Mypair._Myval2._Bx._Ptr, _Mypair._Myval2._Mysize)); # endif # if defined(_STRING_VIEW_) raddbg_type_view(std::basic_string_view, array(_Mydata, _Mysize)); # endif #endif // defined(_WIN32) && defined(RADDBG_MARKUP_IMPLEMENTATION) && RADDBG_MARKUP_STL_TYPE_VIEWS #endif // RADDBG_MARKUP_H ================================================ FILE: src/lib_rdi/rdi.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// //~ (R)AD (D)ebug (I)nfo Format Library // // Defines standard RDI debug information format types and // functions. #ifndef RDI_C #define RDI_C RDI_U16 rdi_section_element_size_table[44] = { sizeof(RDI_U8), sizeof(RDI_TopLevelInfo), sizeof(RDI_U8), sizeof(RDI_U32), sizeof(RDI_U32), sizeof(RDI_BinarySection), sizeof(RDI_FilePathNode), sizeof(RDI_SourceFile), sizeof(RDI_LineTable), sizeof(RDI_U64), sizeof(RDI_Line), sizeof(RDI_Column), sizeof(RDI_SourceLineMap), sizeof(RDI_U32), sizeof(RDI_U32), sizeof(RDI_U64), sizeof(RDI_Unit), sizeof(RDI_VMapEntry), sizeof(RDI_TypeNode), sizeof(RDI_UDT), sizeof(RDI_Member), sizeof(RDI_EnumMember), sizeof(RDI_GlobalVariable), sizeof(RDI_VMapEntry), sizeof(RDI_ThreadVariable), sizeof(RDI_Constant), sizeof(RDI_Procedure), sizeof(RDI_Scope), sizeof(RDI_U64), sizeof(RDI_VMapEntry), sizeof(RDI_InlineSite), sizeof(RDI_Local), sizeof(RDI_LocationBlock), sizeof(RDI_U8), sizeof(RDI_U8), sizeof(RDI_U32), sizeof(RDI_MD5), sizeof(RDI_SHA1), sizeof(RDI_SHA256), sizeof(RDI_U64), sizeof(RDI_NameMap), sizeof(RDI_NameMapBucket), sizeof(RDI_NameMapNode), sizeof(RDI_U8), }; RDI_U16 rdi_eval_op_ctrlbits_table[53] = { RDI_EVAL_CTRLBITS(0, 0, 0), RDI_EVAL_CTRLBITS(0, 0, 0), RDI_EVAL_CTRLBITS(1, 1, 0), RDI_EVAL_CTRLBITS(2, 0, 0), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(0, 1, 1), RDI_EVAL_CTRLBITS(8, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(0, 0, 0), RDI_EVAL_CTRLBITS(0, 0, 0), RDI_EVAL_CTRLBITS(1, 0, 1), RDI_EVAL_CTRLBITS(2, 0, 1), RDI_EVAL_CTRLBITS(4, 0, 1), RDI_EVAL_CTRLBITS(8, 0, 1), RDI_EVAL_CTRLBITS(16, 0, 1), RDI_EVAL_CTRLBITS(1, 0, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(2, 2, 1), RDI_EVAL_CTRLBITS(2, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(2, 1, 1), RDI_EVAL_CTRLBITS(1, 0, 1), RDI_EVAL_CTRLBITS(0, 1, 0), RDI_EVAL_CTRLBITS(1, 0, 0), RDI_EVAL_CTRLBITS(1, 2, 1), RDI_EVAL_CTRLBITS(1, 1, 1), RDI_EVAL_CTRLBITS(4, 0, 0), RDI_EVAL_CTRLBITS(4, 0, 0), RDI_EVAL_CTRLBITS(8, 0, 0), RDI_EVAL_CTRLBITS(0, 2, 2), RDI_EVAL_CTRLBITS(0, 0, 0), }; struct {RDI_EvalConversionKind dst_typegroups[RDI_EvalTypeGroup_COUNT];} rdi_eval_typegroup_conversion_kind_matrix[6] = { {{RDI_EvalConversionKind_OtherToOther, RDI_EvalConversionKind_FromOther, RDI_EvalConversionKind_FromOther, RDI_EvalConversionKind_FromOther, RDI_EvalConversionKind_FromOther}}, {{RDI_EvalConversionKind_ToOther, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Legal}}, {{RDI_EvalConversionKind_ToOther, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Legal}}, {{RDI_EvalConversionKind_ToOther, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Legal}}, {{RDI_EvalConversionKind_ToOther, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Legal, RDI_EvalConversionKind_Noop}}, {{RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop, RDI_EvalConversionKind_Noop}}, }; struct {RDI_U8 *str; RDI_U64 size;} rdi_eval_conversion_kind_message_string_table[6] = { {(RDI_U8 *)"", sizeof("")}, {(RDI_U8 *)"", sizeof("")}, {(RDI_U8 *)"Cannot convert between these types.", sizeof("Cannot convert between these types.")}, {(RDI_U8 *)"Cannot convert to this type.", sizeof("Cannot convert to this type.")}, {(RDI_U8 *)"Cannot convert this type.", sizeof("Cannot convert this type.")}, {(RDI_U8 *)"", sizeof("")}, }; RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size) { RDI_U64 result = 0; if(size != 0) { result = 5381; RDI_U8 *opl = ptr + size; for(;ptr < opl; ptr += 1) { result = ((result << 5) + result) + *ptr; } } return result; } RDI_PROC RDI_U8 * rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out) { RDI_U8 *result = 0; *size_out = 0; switch (kind) { default:{}break; case RDI_TypeKind_NULL: {result = (RDI_U8*)"NULL"; *size_out = sizeof("NULL")-1;}break; case RDI_TypeKind_Void: {result = (RDI_U8*)"Void"; *size_out = sizeof("Void")-1;}break; case RDI_TypeKind_Handle: {result = (RDI_U8*)"Handle"; *size_out = sizeof("Handle")-1;}break; case RDI_TypeKind_HResult: {result = (RDI_U8*)"HResult"; *size_out = sizeof("HResult")-1;}break; case RDI_TypeKind_Char8: {result = (RDI_U8*)"Char8"; *size_out = sizeof("Char8")-1;}break; case RDI_TypeKind_Char16: {result = (RDI_U8*)"Char16"; *size_out = sizeof("Char16")-1;}break; case RDI_TypeKind_Char32: {result = (RDI_U8*)"Char32"; *size_out = sizeof("Char32")-1;}break; case RDI_TypeKind_UChar8: {result = (RDI_U8*)"UChar8"; *size_out = sizeof("UChar8")-1;}break; case RDI_TypeKind_UChar16: {result = (RDI_U8*)"UChar16"; *size_out = sizeof("UChar16")-1;}break; case RDI_TypeKind_UChar32: {result = (RDI_U8*)"UChar32"; *size_out = sizeof("UChar32")-1;}break; case RDI_TypeKind_U8: {result = (RDI_U8*)"U8"; *size_out = sizeof("U8")-1;}break; case RDI_TypeKind_U16: {result = (RDI_U8*)"U16"; *size_out = sizeof("U16")-1;}break; case RDI_TypeKind_U32: {result = (RDI_U8*)"U32"; *size_out = sizeof("U32")-1;}break; case RDI_TypeKind_U64: {result = (RDI_U8*)"U64"; *size_out = sizeof("U64")-1;}break; case RDI_TypeKind_U128: {result = (RDI_U8*)"U128"; *size_out = sizeof("U128")-1;}break; case RDI_TypeKind_U256: {result = (RDI_U8*)"U256"; *size_out = sizeof("U256")-1;}break; case RDI_TypeKind_U512: {result = (RDI_U8*)"U512"; *size_out = sizeof("U512")-1;}break; case RDI_TypeKind_S8: {result = (RDI_U8*)"S8"; *size_out = sizeof("S8")-1;}break; case RDI_TypeKind_S16: {result = (RDI_U8*)"S16"; *size_out = sizeof("S16")-1;}break; case RDI_TypeKind_S32: {result = (RDI_U8*)"S32"; *size_out = sizeof("S32")-1;}break; case RDI_TypeKind_S64: {result = (RDI_U8*)"S64"; *size_out = sizeof("S64")-1;}break; case RDI_TypeKind_S128: {result = (RDI_U8*)"S128"; *size_out = sizeof("S128")-1;}break; case RDI_TypeKind_S256: {result = (RDI_U8*)"S256"; *size_out = sizeof("S256")-1;}break; case RDI_TypeKind_S512: {result = (RDI_U8*)"S512"; *size_out = sizeof("S512")-1;}break; case RDI_TypeKind_Bool: {result = (RDI_U8*)"Bool"; *size_out = sizeof("Bool")-1;}break; case RDI_TypeKind_F16: {result = (RDI_U8*)"F16"; *size_out = sizeof("F16")-1;}break; case RDI_TypeKind_F32: {result = (RDI_U8*)"F32"; *size_out = sizeof("F32")-1;}break; case RDI_TypeKind_F32PP: {result = (RDI_U8*)"F32PP"; *size_out = sizeof("F32PP")-1;}break; case RDI_TypeKind_F48: {result = (RDI_U8*)"F48"; *size_out = sizeof("F48")-1;}break; case RDI_TypeKind_F64: {result = (RDI_U8*)"F64"; *size_out = sizeof("F64")-1;}break; case RDI_TypeKind_F80: {result = (RDI_U8*)"F80"; *size_out = sizeof("F80")-1;}break; case RDI_TypeKind_F128: {result = (RDI_U8*)"F128"; *size_out = sizeof("F128")-1;}break; case RDI_TypeKind_ComplexF32: {result = (RDI_U8*)"ComplexF32"; *size_out = sizeof("ComplexF32")-1;}break; case RDI_TypeKind_ComplexF64: {result = (RDI_U8*)"ComplexF64"; *size_out = sizeof("ComplexF64")-1;}break; case RDI_TypeKind_ComplexF80: {result = (RDI_U8*)"ComplexF80"; *size_out = sizeof("ComplexF80")-1;}break; case RDI_TypeKind_ComplexF128: {result = (RDI_U8*)"ComplexF128"; *size_out = sizeof("ComplexF128")-1;}break; case RDI_TypeKind_Modifier: {result = (RDI_U8*)"Modifier"; *size_out = sizeof("Modifier")-1;}break; case RDI_TypeKind_Ptr: {result = (RDI_U8*)"Ptr"; *size_out = sizeof("Ptr")-1;}break; case RDI_TypeKind_LRef: {result = (RDI_U8*)"LRef"; *size_out = sizeof("LRef")-1;}break; case RDI_TypeKind_RRef: {result = (RDI_U8*)"RRef"; *size_out = sizeof("RRef")-1;}break; case RDI_TypeKind_Array: {result = (RDI_U8*)"Array"; *size_out = sizeof("Array")-1;}break; case RDI_TypeKind_Function: {result = (RDI_U8*)"Function"; *size_out = sizeof("Function")-1;}break; case RDI_TypeKind_Method: {result = (RDI_U8*)"Method"; *size_out = sizeof("Method")-1;}break; case RDI_TypeKind_MemberPtr: {result = (RDI_U8*)"MemberPtr"; *size_out = sizeof("MemberPtr")-1;}break; case RDI_TypeKind_Struct: {result = (RDI_U8*)"Struct"; *size_out = sizeof("Struct")-1;}break; case RDI_TypeKind_Class: {result = (RDI_U8*)"Class"; *size_out = sizeof("Class")-1;}break; case RDI_TypeKind_Union: {result = (RDI_U8*)"Union"; *size_out = sizeof("Union")-1;}break; case RDI_TypeKind_Enum: {result = (RDI_U8*)"Enum"; *size_out = sizeof("Enum")-1;}break; case RDI_TypeKind_Alias: {result = (RDI_U8*)"Alias"; *size_out = sizeof("Alias")-1;}break; case RDI_TypeKind_IncompleteStruct: {result = (RDI_U8*)"IncompleteStruct"; *size_out = sizeof("IncompleteStruct")-1;}break; case RDI_TypeKind_IncompleteUnion: {result = (RDI_U8*)"IncompleteUnion"; *size_out = sizeof("IncompleteUnion")-1;}break; case RDI_TypeKind_IncompleteClass: {result = (RDI_U8*)"IncompleteClass"; *size_out = sizeof("IncompleteClass")-1;}break; case RDI_TypeKind_IncompleteEnum: {result = (RDI_U8*)"IncompleteEnum"; *size_out = sizeof("IncompleteEnum")-1;}break; case RDI_TypeKind_Bitfield: {result = (RDI_U8*)"Bitfield"; *size_out = sizeof("Bitfield")-1;}break; case RDI_TypeKind_Variadic: {result = (RDI_U8*)"Variadic"; *size_out = sizeof("Variadic")-1;}break; case RDI_TypeKind_Count: {result = (RDI_U8*)"Count"; *size_out = sizeof("Count")-1;}break; } return result; } RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind) { RDI_U32 result = 0; switch(kind) { default:{}break; case RDI_TypeKind_Handle:{result = 0xFFFFFFFF;}break; case RDI_TypeKind_HResult:{result = 4;}break; case RDI_TypeKind_Char8:{result = 1;}break; case RDI_TypeKind_Char16:{result = 2;}break; case RDI_TypeKind_Char32:{result = 4;}break; case RDI_TypeKind_UChar8:{result = 1;}break; case RDI_TypeKind_UChar16:{result = 2;}break; case RDI_TypeKind_UChar32:{result = 4;}break; case RDI_TypeKind_U8:{result = 1;}break; case RDI_TypeKind_U16:{result = 2;}break; case RDI_TypeKind_U32:{result = 4;}break; case RDI_TypeKind_U64:{result = 8;}break; case RDI_TypeKind_U128:{result = 16;}break; case RDI_TypeKind_U256:{result = 32;}break; case RDI_TypeKind_U512:{result = 64;}break; case RDI_TypeKind_S8:{result = 1;}break; case RDI_TypeKind_S16:{result = 2;}break; case RDI_TypeKind_S32:{result = 4;}break; case RDI_TypeKind_S64:{result = 8;}break; case RDI_TypeKind_S128:{result = 16;}break; case RDI_TypeKind_S256:{result = 32;}break; case RDI_TypeKind_S512:{result = 64;}break; case RDI_TypeKind_Bool:{result = 1;}break; case RDI_TypeKind_F16:{result = 2;}break; case RDI_TypeKind_F32:{result = 4;}break; case RDI_TypeKind_F32PP:{result = 4;}break; case RDI_TypeKind_F48:{result = 6;}break; case RDI_TypeKind_F64:{result = 8;}break; case RDI_TypeKind_F80:{result = 10;}break; case RDI_TypeKind_F128:{result = 16;}break; case RDI_TypeKind_ComplexF32:{result = 8;}break; case RDI_TypeKind_ComplexF64:{result = 16;}break; case RDI_TypeKind_ComplexF80:{result = 20;}break; case RDI_TypeKind_ComplexF128:{result = 32;}break; } return result; } RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch) { RDI_U32 result = 0; switch(arch) { default:{}break; case RDI_Arch_X86:{result = 4;}break; case RDI_Arch_X64:{result = 8;}break; } return result; } RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out) { RDI_EvalConversionKind k = rdi_eval_typegroup_conversion_kind_matrix[in].dst_typegroups[out]; return k; } RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group) { RDI_S32 result = 0; switch(op) { case RDI_EvalOp_Neg: case RDI_EvalOp_Add: case RDI_EvalOp_Sub: case RDI_EvalOp_Mul: case RDI_EvalOp_Div: case RDI_EvalOp_EqEq:case RDI_EvalOp_NtEq: case RDI_EvalOp_LsEq:case RDI_EvalOp_GrEq: case RDI_EvalOp_Less:case RDI_EvalOp_Grtr: { if(group != RDI_EvalTypeGroup_Other) { result = 1; } }break; case RDI_EvalOp_Mod:case RDI_EvalOp_LShift:case RDI_EvalOp_RShift: case RDI_EvalOp_BitNot:case RDI_EvalOp_BitAnd:case RDI_EvalOp_BitXor: case RDI_EvalOp_BitOr:case RDI_EvalOp_LogNot:case RDI_EvalOp_LogAnd: case RDI_EvalOp_LogOr: { if(group == RDI_EvalTypeGroup_S || group == RDI_EvalTypeGroup_U) { result = 1; } }break; } return result; } RDI_PROC RDI_U8 * rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out) { *size_out = rdi_eval_conversion_kind_message_string_table[kind].size; return rdi_eval_conversion_kind_message_string_table[kind].str; } RDI_PROC RDI_SectionKind rdi_section_kind_from_checksum_kind(RDI_ChecksumKind kind) { RDI_SectionKind result = 0; switch(kind) { default:{}break; case RDI_ChecksumKind_NULL:{result = RDI_SectionKind_NULL;}break; case RDI_ChecksumKind_MD5:{result = RDI_SectionKind_MD5Checksums;}break; case RDI_ChecksumKind_SHA1:{result = RDI_SectionKind_SHA1Checksums;}break; case RDI_ChecksumKind_SHA256:{result = RDI_SectionKind_SHA256Checksums;}break; case RDI_ChecksumKind_Timestamp:{result = RDI_SectionKind_Timestamps;}break; case RDI_ChecksumKind_COUNT:{result = RDI_SectionKind_NULL;}break; } return result; } #endif // RDI_C ================================================ FILE: src/lib_rdi/rdi.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// //~ (R)AD (D)ebug (I)nfo Format Library // // Defines standard RDI debug information format types and // functions. #ifndef RDI_H #define RDI_H //////////////////////////////////////////////////////////////// //~ Overridable Procedure Decoration #if !defined(RDI_PROC) # define RDI_PROC static #endif //////////////////////////////////////////////////////////////// //~ Overridable Basic Integer Types #if !defined(RDI_U8) # define RDI_U8 RDI_U8 # define RDI_U16 RDI_U16 # define RDI_U32 RDI_U32 # define RDI_U64 RDI_U64 # define RDI_S8 RDI_S8 # define RDI_S16 RDI_S16 # define RDI_S32 RDI_S32 # define RDI_S64 RDI_S64 #include typedef uint8_t RDI_U8; typedef uint16_t RDI_U16; typedef uint32_t RDI_U32; typedef uint64_t RDI_U64; typedef int8_t RDI_S8; typedef int16_t RDI_S16; typedef int32_t RDI_S32; typedef int64_t RDI_S64; #endif //////////////////////////////////////////////////////////////// //~ Checksum Types typedef union RDI_MD5 RDI_MD5; union RDI_MD5 {RDI_U8 u8[16]; RDI_U64 u64[2];}; typedef union RDI_SHA1 RDI_SHA1; union RDI_SHA1 {RDI_U8 u8[20];}; typedef union RDI_SHA256 RDI_SHA256; union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];}; typedef union RDI_GUID RDI_GUID; union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];}; //////////////////////////////////////////////////////////////// //~ Overridable Enabling/Disabling Of Table Index Typechecking #if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING) # define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0 #endif //////////////////////////////////////////////////////////////// //~ Format Constants // "raddbg\0\0" #define RDI_MAGIC_CONSTANT 0x0000676264646172 #define RDI_ENCODING_VERSION 17 //////////////////////////////////////////////////////////////// //~ Format Types & Functions typedef RDI_U32 RDI_SectionKind; typedef enum RDI_SectionKindEnum { RDI_SectionKind_NULL = 0x0000, RDI_SectionKind_TopLevelInfo = 0x0001, RDI_SectionKind_StringData = 0x0002, RDI_SectionKind_StringTable = 0x0003, RDI_SectionKind_IndexRuns = 0x0004, RDI_SectionKind_BinarySections = 0x0005, RDI_SectionKind_FilePathNodes = 0x0006, RDI_SectionKind_SourceFiles = 0x0007, RDI_SectionKind_LineTables = 0x0008, RDI_SectionKind_LineInfoVOffs = 0x0009, RDI_SectionKind_LineInfoLines = 0x000A, RDI_SectionKind_LineInfoColumns = 0x000B, RDI_SectionKind_SourceLineMaps = 0x000C, RDI_SectionKind_SourceLineMapNumbers = 0x000D, RDI_SectionKind_SourceLineMapRanges = 0x000E, RDI_SectionKind_SourceLineMapVOffs = 0x000F, RDI_SectionKind_Units = 0x0010, RDI_SectionKind_UnitVMap = 0x0011, RDI_SectionKind_TypeNodes = 0x0012, RDI_SectionKind_UDTs = 0x0013, RDI_SectionKind_Members = 0x0014, RDI_SectionKind_EnumMembers = 0x0015, RDI_SectionKind_GlobalVariables = 0x0016, RDI_SectionKind_GlobalVMap = 0x0017, RDI_SectionKind_ThreadVariables = 0x0018, RDI_SectionKind_Constants = 0x0019, RDI_SectionKind_Procedures = 0x001A, RDI_SectionKind_Scopes = 0x001B, RDI_SectionKind_ScopeVOffData = 0x001C, RDI_SectionKind_ScopeVMap = 0x001D, RDI_SectionKind_InlineSites = 0x001E, RDI_SectionKind_Locals = 0x001F, RDI_SectionKind_LocationBlocks = 0x0020, RDI_SectionKind_LocationData = 0x0021, RDI_SectionKind_ConstantValueData = 0x0022, RDI_SectionKind_ConstantValueTable = 0x0023, RDI_SectionKind_MD5Checksums = 0x0024, RDI_SectionKind_SHA1Checksums = 0x0025, RDI_SectionKind_SHA256Checksums = 0x0026, RDI_SectionKind_Timestamps = 0x0027, RDI_SectionKind_NameMaps = 0x0028, RDI_SectionKind_NameMapBuckets = 0x0029, RDI_SectionKind_NameMapNodes = 0x002A, RDI_SectionKind_COUNT = 0x002B, } RDI_SectionKindEnum; typedef RDI_U32 RDI_SectionEncoding; typedef enum RDI_SectionEncodingEnum { RDI_SectionEncoding_Unpacked = 0, RDI_SectionEncoding_LZB = 1, } RDI_SectionEncodingEnum; typedef RDI_U32 RDI_Arch; typedef enum RDI_ArchEnum { RDI_Arch_NULL = 0, RDI_Arch_X86 = 1, RDI_Arch_X64 = 2, } RDI_ArchEnum; typedef RDI_U8 RDI_RegCode; typedef enum RDI_RegCodeEnum { RDI_RegCode_nil, } RDI_RegCodeEnum; typedef RDI_U8 RDI_RegCodeX86; typedef enum RDI_RegCodeX86Enum { RDI_RegCodeX86_nil = 0, RDI_RegCodeX86_eax = 1, RDI_RegCodeX86_ecx = 2, RDI_RegCodeX86_edx = 3, RDI_RegCodeX86_ebx = 4, RDI_RegCodeX86_esp = 5, RDI_RegCodeX86_ebp = 6, RDI_RegCodeX86_esi = 7, RDI_RegCodeX86_edi = 8, RDI_RegCodeX86_fsbase = 9, RDI_RegCodeX86_gsbase = 10, RDI_RegCodeX86_eflags = 11, RDI_RegCodeX86_eip = 12, RDI_RegCodeX86_dr0 = 13, RDI_RegCodeX86_dr1 = 14, RDI_RegCodeX86_dr2 = 15, RDI_RegCodeX86_dr3 = 16, RDI_RegCodeX86_dr4 = 17, RDI_RegCodeX86_dr5 = 18, RDI_RegCodeX86_dr6 = 19, RDI_RegCodeX86_dr7 = 20, RDI_RegCodeX86_fpr0 = 21, RDI_RegCodeX86_fpr1 = 22, RDI_RegCodeX86_fpr2 = 23, RDI_RegCodeX86_fpr3 = 24, RDI_RegCodeX86_fpr4 = 25, RDI_RegCodeX86_fpr5 = 26, RDI_RegCodeX86_fpr6 = 27, RDI_RegCodeX86_fpr7 = 28, RDI_RegCodeX86_st0 = 29, RDI_RegCodeX86_st1 = 30, RDI_RegCodeX86_st2 = 31, RDI_RegCodeX86_st3 = 32, RDI_RegCodeX86_st4 = 33, RDI_RegCodeX86_st5 = 34, RDI_RegCodeX86_st6 = 35, RDI_RegCodeX86_st7 = 36, RDI_RegCodeX86_fcw = 37, RDI_RegCodeX86_fsw = 38, RDI_RegCodeX86_ftw = 39, RDI_RegCodeX86_fop = 40, RDI_RegCodeX86_fcs = 41, RDI_RegCodeX86_fds = 42, RDI_RegCodeX86_fip = 43, RDI_RegCodeX86_fdp = 44, RDI_RegCodeX86_mxcsr = 45, RDI_RegCodeX86_mxcsr_mask = 46, RDI_RegCodeX86_ss = 47, RDI_RegCodeX86_cs = 48, RDI_RegCodeX86_ds = 49, RDI_RegCodeX86_es = 50, RDI_RegCodeX86_fs = 51, RDI_RegCodeX86_gs = 52, RDI_RegCodeX86_ymm0 = 53, RDI_RegCodeX86_ymm1 = 54, RDI_RegCodeX86_ymm2 = 55, RDI_RegCodeX86_ymm3 = 56, RDI_RegCodeX86_ymm4 = 57, RDI_RegCodeX86_ymm5 = 58, RDI_RegCodeX86_ymm6 = 59, RDI_RegCodeX86_ymm7 = 60, RDI_RegCodeX86_tr = 61, RDI_RegCodeX86_ldtr = 62, } RDI_RegCodeX86Enum; typedef RDI_U8 RDI_RegCodeX64; typedef enum RDI_RegCodeX64Enum { RDI_RegCodeX64_nil = 0, RDI_RegCodeX64_rax = 1, RDI_RegCodeX64_rcx = 2, RDI_RegCodeX64_rdx = 3, RDI_RegCodeX64_rbx = 4, RDI_RegCodeX64_rsp = 5, RDI_RegCodeX64_rbp = 6, RDI_RegCodeX64_rsi = 7, RDI_RegCodeX64_rdi = 8, RDI_RegCodeX64_r8 = 9, RDI_RegCodeX64_r9 = 10, RDI_RegCodeX64_r10 = 11, RDI_RegCodeX64_r11 = 12, RDI_RegCodeX64_r12 = 13, RDI_RegCodeX64_r13 = 14, RDI_RegCodeX64_r14 = 15, RDI_RegCodeX64_r15 = 16, RDI_RegCodeX64_es = 17, RDI_RegCodeX64_cs = 18, RDI_RegCodeX64_ss = 19, RDI_RegCodeX64_ds = 20, RDI_RegCodeX64_fs = 21, RDI_RegCodeX64_gs = 22, RDI_RegCodeX64_rip = 23, RDI_RegCodeX64_rflags = 24, RDI_RegCodeX64_dr0 = 25, RDI_RegCodeX64_dr1 = 26, RDI_RegCodeX64_dr2 = 27, RDI_RegCodeX64_dr3 = 28, RDI_RegCodeX64_dr4 = 29, RDI_RegCodeX64_dr5 = 30, RDI_RegCodeX64_dr6 = 31, RDI_RegCodeX64_dr7 = 32, RDI_RegCodeX64_st0 = 33, RDI_RegCodeX64_st1 = 34, RDI_RegCodeX64_st2 = 35, RDI_RegCodeX64_st3 = 36, RDI_RegCodeX64_st4 = 37, RDI_RegCodeX64_st5 = 38, RDI_RegCodeX64_st6 = 39, RDI_RegCodeX64_st7 = 40, RDI_RegCodeX64_fpr0 = 41, RDI_RegCodeX64_fpr1 = 42, RDI_RegCodeX64_fpr2 = 43, RDI_RegCodeX64_fpr3 = 44, RDI_RegCodeX64_fpr4 = 45, RDI_RegCodeX64_fpr5 = 46, RDI_RegCodeX64_fpr6 = 47, RDI_RegCodeX64_fpr7 = 48, RDI_RegCodeX64_zmm0 = 49, RDI_RegCodeX64_zmm1 = 50, RDI_RegCodeX64_zmm2 = 51, RDI_RegCodeX64_zmm3 = 52, RDI_RegCodeX64_zmm4 = 53, RDI_RegCodeX64_zmm5 = 54, RDI_RegCodeX64_zmm6 = 55, RDI_RegCodeX64_zmm7 = 56, RDI_RegCodeX64_zmm8 = 57, RDI_RegCodeX64_zmm9 = 58, RDI_RegCodeX64_zmm10 = 59, RDI_RegCodeX64_zmm11 = 60, RDI_RegCodeX64_zmm12 = 61, RDI_RegCodeX64_zmm13 = 62, RDI_RegCodeX64_zmm14 = 63, RDI_RegCodeX64_zmm15 = 64, RDI_RegCodeX64_zmm16 = 65, RDI_RegCodeX64_zmm17 = 66, RDI_RegCodeX64_zmm18 = 67, RDI_RegCodeX64_zmm19 = 68, RDI_RegCodeX64_zmm20 = 69, RDI_RegCodeX64_zmm21 = 70, RDI_RegCodeX64_zmm22 = 71, RDI_RegCodeX64_zmm23 = 72, RDI_RegCodeX64_zmm24 = 73, RDI_RegCodeX64_zmm25 = 74, RDI_RegCodeX64_zmm26 = 75, RDI_RegCodeX64_zmm27 = 76, RDI_RegCodeX64_zmm28 = 77, RDI_RegCodeX64_zmm29 = 78, RDI_RegCodeX64_zmm30 = 79, RDI_RegCodeX64_zmm31 = 80, RDI_RegCodeX64_k0 = 81, RDI_RegCodeX64_k1 = 82, RDI_RegCodeX64_k2 = 83, RDI_RegCodeX64_k3 = 84, RDI_RegCodeX64_k4 = 85, RDI_RegCodeX64_k5 = 86, RDI_RegCodeX64_k6 = 87, RDI_RegCodeX64_k7 = 88, RDI_RegCodeX64_mxcsr = 89, RDI_RegCodeX64_fsbase = 90, RDI_RegCodeX64_gsbase = 91, RDI_RegCodeX64_fcw = 92, RDI_RegCodeX64_fsw = 93, RDI_RegCodeX64_ftw = 94, RDI_RegCodeX64_fop = 95, RDI_RegCodeX64_fcs = 96, RDI_RegCodeX64_fds = 97, RDI_RegCodeX64_fip = 98, RDI_RegCodeX64_fdp = 99, RDI_RegCodeX64_mxcsr_mask = 100, RDI_RegCodeX64_cetmsr = 101, RDI_RegCodeX64_cetssp = 102, RDI_RegCodeX64_tr = 103, RDI_RegCodeX64_ldtr = 104, } RDI_RegCodeX64Enum; typedef RDI_U32 RDI_BinarySectionFlags; typedef enum RDI_BinarySectionFlagsEnum { RDI_BinarySectionFlag_Read = 1<<0, RDI_BinarySectionFlag_Write = 1<<1, RDI_BinarySectionFlag_Execute = 1<<2, } RDI_BinarySectionFlagsEnum; typedef RDI_U32 RDI_ChecksumKind; typedef enum RDI_ChecksumKindEnum { RDI_ChecksumKind_NULL = 0, RDI_ChecksumKind_MD5 = 1, RDI_ChecksumKind_SHA1 = 2, RDI_ChecksumKind_SHA256 = 3, RDI_ChecksumKind_Timestamp = 4, RDI_ChecksumKind_COUNT = 5, } RDI_ChecksumKindEnum; typedef RDI_U32 RDI_Language; typedef enum RDI_LanguageEnum { RDI_Language_NULL = 0, RDI_Language_C = 1, RDI_Language_CPlusPlus = 2, RDI_Language_Masm = 3, RDI_Language_COUNT = 4, } RDI_LanguageEnum; typedef RDI_U16 RDI_TypeKind; typedef enum RDI_TypeKindEnum { RDI_TypeKind_NULL = 0x0000, RDI_TypeKind_Void = 0x0001, RDI_TypeKind_Handle = 0x0002, RDI_TypeKind_HResult = 0x0003, RDI_TypeKind_Char8 = 0x0004, RDI_TypeKind_Char16 = 0x0005, RDI_TypeKind_Char32 = 0x0006, RDI_TypeKind_UChar8 = 0x0007, RDI_TypeKind_UChar16 = 0x0008, RDI_TypeKind_UChar32 = 0x0009, RDI_TypeKind_U8 = 0x000A, RDI_TypeKind_U16 = 0x000B, RDI_TypeKind_U32 = 0x000C, RDI_TypeKind_U64 = 0x000D, RDI_TypeKind_U128 = 0x000E, RDI_TypeKind_U256 = 0x000F, RDI_TypeKind_U512 = 0x0010, RDI_TypeKind_S8 = 0x0011, RDI_TypeKind_S16 = 0x0012, RDI_TypeKind_S32 = 0x0013, RDI_TypeKind_S64 = 0x0014, RDI_TypeKind_S128 = 0x0015, RDI_TypeKind_S256 = 0x0016, RDI_TypeKind_S512 = 0x0017, RDI_TypeKind_Bool = 0x0018, RDI_TypeKind_F16 = 0x0019, RDI_TypeKind_F32 = 0x001A, RDI_TypeKind_F32PP = 0x001B, RDI_TypeKind_F48 = 0x001C, RDI_TypeKind_F64 = 0x001D, RDI_TypeKind_F80 = 0x001E, RDI_TypeKind_F128 = 0x001F, RDI_TypeKind_ComplexF32 = 0x0020, RDI_TypeKind_ComplexF64 = 0x0021, RDI_TypeKind_ComplexF80 = 0x0022, RDI_TypeKind_ComplexF128 = 0x0023, RDI_TypeKind_Modifier = 0x1000, RDI_TypeKind_Ptr = 0x1001, RDI_TypeKind_LRef = 0x1002, RDI_TypeKind_RRef = 0x1003, RDI_TypeKind_Array = 0x1004, RDI_TypeKind_Function = 0x1005, RDI_TypeKind_Method = 0x1006, RDI_TypeKind_MemberPtr = 0x1007, RDI_TypeKind_Struct = 0x2000, RDI_TypeKind_Class = 0x2001, RDI_TypeKind_Union = 0x2002, RDI_TypeKind_Enum = 0x2003, RDI_TypeKind_Alias = 0x2004, RDI_TypeKind_IncompleteStruct = 0x2005, RDI_TypeKind_IncompleteUnion = 0x2006, RDI_TypeKind_IncompleteClass = 0x2007, RDI_TypeKind_IncompleteEnum = 0x2008, RDI_TypeKind_Bitfield = 0xF000, RDI_TypeKind_Variadic = 0xF001, RDI_TypeKind_Count = 0xF002, RDI_TypeKind_FirstBuiltIn = RDI_TypeKind_Void, RDI_TypeKind_LastBuiltIn = RDI_TypeKind_ComplexF128, RDI_TypeKind_FirstConstructed = RDI_TypeKind_Modifier, RDI_TypeKind_LastConstructed = RDI_TypeKind_MemberPtr, RDI_TypeKind_FirstUserDefined = RDI_TypeKind_Struct, RDI_TypeKind_LastRecord = RDI_TypeKind_Union, RDI_TypeKind_FirstIncomplete = RDI_TypeKind_IncompleteStruct, RDI_TypeKind_LastIncomplete = RDI_TypeKind_IncompleteEnum, RDI_TypeKind_FirstRecord = RDI_TypeKind_Struct, RDI_TypeKind_LastUserDefined = RDI_TypeKind_IncompleteEnum, } RDI_TypeKindEnum; typedef RDI_U16 RDI_TypeModifierFlags; typedef enum RDI_TypeModifierFlagsEnum { RDI_TypeModifierFlag_Const = 1<<0, RDI_TypeModifierFlag_Volatile = 1<<1, RDI_TypeModifierFlag_Restrict = 1<<2, } RDI_TypeModifierFlagsEnum; typedef RDI_U32 RDI_UDTFlags; typedef enum RDI_UDTFlagsEnum { RDI_UDTFlag_EnumMembers = 1<<0, } RDI_UDTFlagsEnum; typedef RDI_U16 RDI_MemberKind; typedef enum RDI_MemberKindEnum { RDI_MemberKind_NULL = 0x0000, RDI_MemberKind_DataField = 0x0001, RDI_MemberKind_StaticData = 0x0002, RDI_MemberKind_Method = 0x0100, RDI_MemberKind_StaticMethod = 0x0101, RDI_MemberKind_VirtualMethod = 0x0102, RDI_MemberKind_VTablePtr = 0x0200, RDI_MemberKind_Base = 0x0201, RDI_MemberKind_VirtualBase = 0x0202, RDI_MemberKind_NestedType = 0x0300, } RDI_MemberKindEnum; typedef RDI_U32 RDI_LinkFlags; typedef enum RDI_LinkFlagsEnum { RDI_LinkFlag_External = 1<<0, RDI_LinkFlag_TypeScoped = 1<<1, RDI_LinkFlag_ProcScoped = 1<<2, } RDI_LinkFlagsEnum; typedef RDI_U32 RDI_LocalKind; typedef enum RDI_LocalKindEnum { RDI_LocalKind_NULL = 0x0, RDI_LocalKind_Parameter = 0x1, RDI_LocalKind_Variable = 0x2, } RDI_LocalKindEnum; typedef RDI_U8 RDI_LocationKind; typedef enum RDI_LocationKindEnum { RDI_LocationKind_NULL = 0x0, RDI_LocationKind_AddrBytecodeStream = 0x1, RDI_LocationKind_ValBytecodeStream = 0x2, RDI_LocationKind_AddrRegPlusU16 = 0x3, RDI_LocationKind_AddrAddrRegPlusU16 = 0x4, RDI_LocationKind_ValReg = 0x5, } RDI_LocationKindEnum; typedef RDI_U8 RDI_EvalOp; typedef enum RDI_EvalOpEnum { RDI_EvalOp_Stop = 0, RDI_EvalOp_Noop = 1, RDI_EvalOp_Cond = 2, RDI_EvalOp_Skip = 3, RDI_EvalOp_MemRead = 4, RDI_EvalOp_RegRead = 5, RDI_EvalOp_RegReadDyn = 6, RDI_EvalOp_FrameOff = 7, RDI_EvalOp_ModuleOff = 8, RDI_EvalOp_TLSOff = 9, RDI_EvalOp_ObjectOff = 10, RDI_EvalOp_CFA = 11, RDI_EvalOp_ConstU8 = 12, RDI_EvalOp_ConstU16 = 13, RDI_EvalOp_ConstU32 = 14, RDI_EvalOp_ConstU64 = 15, RDI_EvalOp_ConstU128 = 16, RDI_EvalOp_ConstString = 17, RDI_EvalOp_Abs = 18, RDI_EvalOp_Neg = 19, RDI_EvalOp_Add = 20, RDI_EvalOp_Sub = 21, RDI_EvalOp_Mul = 22, RDI_EvalOp_Div = 23, RDI_EvalOp_Mod = 24, RDI_EvalOp_LShift = 25, RDI_EvalOp_RShift = 26, RDI_EvalOp_BitAnd = 27, RDI_EvalOp_BitOr = 28, RDI_EvalOp_BitXor = 29, RDI_EvalOp_BitNot = 30, RDI_EvalOp_LogAnd = 31, RDI_EvalOp_LogOr = 32, RDI_EvalOp_LogNot = 33, RDI_EvalOp_EqEq = 34, RDI_EvalOp_NtEq = 35, RDI_EvalOp_LsEq = 36, RDI_EvalOp_GrEq = 37, RDI_EvalOp_Less = 38, RDI_EvalOp_Grtr = 39, RDI_EvalOp_Trunc = 40, RDI_EvalOp_TruncSigned = 41, RDI_EvalOp_Convert = 42, RDI_EvalOp_Pick = 43, RDI_EvalOp_Pop = 44, RDI_EvalOp_Insert = 45, RDI_EvalOp_ValueRead = 46, RDI_EvalOp_ByteSwap = 47, RDI_EvalOp_CallSiteValue = 48, RDI_EvalOp_PartialValue = 49, RDI_EvalOp_PartialValueBit = 50, RDI_EvalOp_Swap = 51, RDI_EvalOp_COUNT = 52, } RDI_EvalOpEnum; typedef RDI_U8 RDI_EvalTypeGroup; typedef enum RDI_EvalTypeGroupEnum { RDI_EvalTypeGroup_Other = 0, RDI_EvalTypeGroup_U = 1, RDI_EvalTypeGroup_S = 2, RDI_EvalTypeGroup_F32 = 3, RDI_EvalTypeGroup_F64 = 4, RDI_EvalTypeGroup_COUNT = 5, } RDI_EvalTypeGroupEnum; typedef RDI_U8 RDI_EvalConversionKind; typedef enum RDI_EvalConversionKindEnum { RDI_EvalConversionKind_Noop = 0, RDI_EvalConversionKind_Legal = 1, RDI_EvalConversionKind_OtherToOther = 2, RDI_EvalConversionKind_ToOther = 3, RDI_EvalConversionKind_FromOther = 4, RDI_EvalConversionKind_COUNT = 5, } RDI_EvalConversionKindEnum; typedef RDI_U32 RDI_NameMapKind; typedef enum RDI_NameMapKindEnum { RDI_NameMapKind_NULL = 0, RDI_NameMapKind_GlobalVariables = 1, RDI_NameMapKind_ThreadVariables = 2, RDI_NameMapKind_Constants = 3, RDI_NameMapKind_Procedures = 4, RDI_NameMapKind_Types = 5, RDI_NameMapKind_LinkNameProcedures = 6, RDI_NameMapKind_NormalSourcePaths = 7, RDI_NameMapKind_COUNT = 8, } RDI_NameMapKindEnum; #define RDI_Header_XList \ X(RDI_U64, magic)\ X(RDI_U32, encoding_version)\ X(RDI_U32, data_section_off)\ X(RDI_U32, data_section_count)\ #define RDI_SectionKind_XList \ X(NULL, null, RDI_U8)\ X(TopLevelInfo, top_level_info, RDI_TopLevelInfo)\ X(StringData, string_data, RDI_U8)\ X(StringTable, string_table, RDI_U32)\ X(IndexRuns, index_runs, RDI_U32)\ X(BinarySections, binary_sections, RDI_BinarySection)\ X(FilePathNodes, file_path_nodes, RDI_FilePathNode)\ X(SourceFiles, source_files, RDI_SourceFile)\ X(LineTables, line_tables, RDI_LineTable)\ X(LineInfoVOffs, line_info_voffs, RDI_U64)\ X(LineInfoLines, line_info_lines, RDI_Line)\ X(LineInfoColumns, line_info_columns, RDI_Column)\ X(SourceLineMaps, source_line_maps, RDI_SourceLineMap)\ X(SourceLineMapNumbers, source_line_map_numbers, RDI_U32)\ X(SourceLineMapRanges, source_line_map_ranges, RDI_U32)\ X(SourceLineMapVOffs, source_line_map_voffs, RDI_U64)\ X(Units, units, RDI_Unit)\ X(UnitVMap, unit_vmap, RDI_VMapEntry)\ X(TypeNodes, type_nodes, RDI_TypeNode)\ X(UDTs, udts, RDI_UDT)\ X(Members, members, RDI_Member)\ X(EnumMembers, enum_members, RDI_EnumMember)\ X(GlobalVariables, global_variables, RDI_GlobalVariable)\ X(GlobalVMap, global_vmap, RDI_VMapEntry)\ X(ThreadVariables, thread_variables, RDI_ThreadVariable)\ X(Constants, constants, RDI_Constant)\ X(Procedures, procedures, RDI_Procedure)\ X(Scopes, scopes, RDI_Scope)\ X(ScopeVOffData, scope_voff_data, RDI_U64)\ X(ScopeVMap, scope_vmap, RDI_VMapEntry)\ X(InlineSites, inline_sites, RDI_InlineSite)\ X(Locals, locals, RDI_Local)\ X(LocationBlocks, location_blocks, RDI_LocationBlock)\ X(LocationData, location_data, RDI_U8)\ X(ConstantValueData, constant_value_data, RDI_U8)\ X(ConstantValueTable, constant_value_table, RDI_U32)\ X(MD5Checksums, md5_checksums, RDI_MD5)\ X(SHA1Checksums, sha1_checksums, RDI_SHA1)\ X(SHA256Checksums, sha256_checksums, RDI_SHA256)\ X(Timestamps, timestamps, RDI_U64)\ X(NameMaps, name_maps, RDI_NameMap)\ X(NameMapBuckets, name_map_buckets, RDI_NameMapBucket)\ X(NameMapNodes, name_map_nodes, RDI_NameMapNode)\ #define RDI_SectionEncoding_XList \ X(Unpacked)\ X(LZB)\ #define RDI_Section_XList \ X(RDI_SectionEncoding, encoding)\ X(RDI_U32, pad)\ X(RDI_U64, off)\ X(RDI_U64, encoded_size)\ X(RDI_U64, unpacked_size)\ #define RDI_VMapEntry_XList \ X(RDI_U64, voff)\ X(RDI_U64, idx)\ #define RDI_Arch_XList \ X(NULL)\ X(X86)\ X(X64)\ #define RDI_RegCodeX86_XList \ X(nil, 0)\ X(eax, 1)\ X(ecx, 2)\ X(edx, 3)\ X(ebx, 4)\ X(esp, 5)\ X(ebp, 6)\ X(esi, 7)\ X(edi, 8)\ X(fsbase, 9)\ X(gsbase, 10)\ X(eflags, 11)\ X(eip, 12)\ X(dr0, 13)\ X(dr1, 14)\ X(dr2, 15)\ X(dr3, 16)\ X(dr4, 17)\ X(dr5, 18)\ X(dr6, 19)\ X(dr7, 20)\ X(fpr0, 21)\ X(fpr1, 22)\ X(fpr2, 23)\ X(fpr3, 24)\ X(fpr4, 25)\ X(fpr5, 26)\ X(fpr6, 27)\ X(fpr7, 28)\ X(st0, 29)\ X(st1, 30)\ X(st2, 31)\ X(st3, 32)\ X(st4, 33)\ X(st5, 34)\ X(st6, 35)\ X(st7, 36)\ X(fcw, 37)\ X(fsw, 38)\ X(ftw, 39)\ X(fop, 40)\ X(fcs, 41)\ X(fds, 42)\ X(fip, 43)\ X(fdp, 44)\ X(mxcsr, 45)\ X(mxcsr_mask, 46)\ X(ss, 47)\ X(cs, 48)\ X(ds, 49)\ X(es, 50)\ X(fs, 51)\ X(gs, 52)\ X(ymm0, 53)\ X(ymm1, 54)\ X(ymm2, 55)\ X(ymm3, 56)\ X(ymm4, 57)\ X(ymm5, 58)\ X(ymm6, 59)\ X(ymm7, 60)\ X(tr, 61)\ X(ldtr, 62)\ #define RDI_RegCodeX64_XList \ X(nil, 0)\ X(rax, 1)\ X(rcx, 2)\ X(rdx, 3)\ X(rbx, 4)\ X(rsp, 5)\ X(rbp, 6)\ X(rsi, 7)\ X(rdi, 8)\ X(r8, 9)\ X(r9, 10)\ X(r10, 11)\ X(r11, 12)\ X(r12, 13)\ X(r13, 14)\ X(r14, 15)\ X(r15, 16)\ X(es, 17)\ X(cs, 18)\ X(ss, 19)\ X(ds, 20)\ X(fs, 21)\ X(gs, 22)\ X(rip, 23)\ X(rflags, 24)\ X(dr0, 25)\ X(dr1, 26)\ X(dr2, 27)\ X(dr3, 28)\ X(dr4, 29)\ X(dr5, 30)\ X(dr6, 31)\ X(dr7, 32)\ X(st0, 33)\ X(st1, 34)\ X(st2, 35)\ X(st3, 36)\ X(st4, 37)\ X(st5, 38)\ X(st6, 39)\ X(st7, 40)\ X(fpr0, 41)\ X(fpr1, 42)\ X(fpr2, 43)\ X(fpr3, 44)\ X(fpr4, 45)\ X(fpr5, 46)\ X(fpr6, 47)\ X(fpr7, 48)\ X(zmm0, 49)\ X(zmm1, 50)\ X(zmm2, 51)\ X(zmm3, 52)\ X(zmm4, 53)\ X(zmm5, 54)\ X(zmm6, 55)\ X(zmm7, 56)\ X(zmm8, 57)\ X(zmm9, 58)\ X(zmm10, 59)\ X(zmm11, 60)\ X(zmm12, 61)\ X(zmm13, 62)\ X(zmm14, 63)\ X(zmm15, 64)\ X(zmm16, 65)\ X(zmm17, 66)\ X(zmm18, 67)\ X(zmm19, 68)\ X(zmm20, 69)\ X(zmm21, 70)\ X(zmm22, 71)\ X(zmm23, 72)\ X(zmm24, 73)\ X(zmm25, 74)\ X(zmm26, 75)\ X(zmm27, 76)\ X(zmm28, 77)\ X(zmm29, 78)\ X(zmm30, 79)\ X(zmm31, 80)\ X(k0, 81)\ X(k1, 82)\ X(k2, 83)\ X(k3, 84)\ X(k4, 85)\ X(k5, 86)\ X(k6, 87)\ X(k7, 88)\ X(mxcsr, 89)\ X(fsbase, 90)\ X(gsbase, 91)\ X(fcw, 92)\ X(fsw, 93)\ X(ftw, 94)\ X(fop, 95)\ X(fcs, 96)\ X(fds, 97)\ X(fip, 98)\ X(fdp, 99)\ X(mxcsr_mask, 100)\ X(cetmsr, 101)\ X(cetssp, 102)\ X(tr, 103)\ X(ldtr, 104)\ #define RDI_TopLevelInfo_XList \ X(RDI_Arch, arch)\ X(RDI_U32, exe_name_string_idx)\ X(RDI_U64, exe_hash)\ X(RDI_U64, voff_max)\ X(RDI_GUID, guid)\ X(RDI_U32, producer_name_string_idx)\ #define RDI_BinarySectionFlags_XList \ X(Read)\ X(Write)\ X(Execute)\ #define RDI_BinarySection_XList \ X(RDI_U32, name_string_idx)\ X(RDI_BinarySectionFlags, flags)\ X(RDI_U64, voff_first)\ X(RDI_U64, voff_opl)\ X(RDI_U64, foff_first)\ X(RDI_U64, foff_opl)\ #define RDI_ChecksumKind_XList \ X(NULL, NULL)\ X(MD5, MD5Checksums)\ X(SHA1, SHA1Checksums)\ X(SHA256, SHA256Checksums)\ X(Timestamp, Timestamps)\ X(COUNT, NULL)\ #define RDI_FilePathNode_XList \ X(RDI_U32, name_string_idx)\ X(RDI_U32, parent_path_node)\ X(RDI_U32, first_child)\ X(RDI_U32, next_sibling)\ X(RDI_U32, source_file_idx)\ #define RDI_SourceFile_XList \ X(RDI_U32, file_path_node_idx)\ X(RDI_U32, normal_full_path_string_idx)\ X(RDI_U32, source_line_map_idx)\ X(RDI_ChecksumKind, checksum_kind)\ X(RDI_U32, checksum_idx)\ #define RDI_Unit_XList \ X(RDI_U32, unit_name_string_idx)\ X(RDI_U32, compiler_name_string_idx)\ X(RDI_U32, source_file_path_node)\ X(RDI_U32, object_file_path_node)\ X(RDI_U32, archive_file_path_node)\ X(RDI_U32, build_path_node)\ X(RDI_Language, language)\ X(RDI_U32, line_table_idx)\ #define RDI_LineTable_XList \ X(RDI_U32, voffs_base_idx)\ X(RDI_U32, lines_base_idx)\ X(RDI_U32, cols_base_idx)\ X(RDI_U32, lines_count)\ X(RDI_U32, cols_count)\ #define RDI_Line_XList \ X(RDI_U32, file_idx)\ X(RDI_U32, line_num)\ #define RDI_Column_XList \ X(RDI_U16, col_first)\ X(RDI_U16, col_opl)\ #define RDI_SourceLineMapMemberTable \ X(RDI_U32, line_count)\ X(RDI_U32, voff_count)\ X(RDI_U32, line_map_nums_base_idx)\ X(RDI_U32, line_map_range_base_idx)\ X(RDI_U32, line_map_voff_base_idx)\ #define RDI_Language_XList \ X(NULL)\ X(C)\ X(CPlusPlus)\ X(Masm)\ X(COUNT)\ #define RDI_TypeKind_XList \ X(NULL)\ X(Void)\ X(Handle)\ X(HResult)\ X(Char8)\ X(Char16)\ X(Char32)\ X(UChar8)\ X(UChar16)\ X(UChar32)\ X(U8)\ X(U16)\ X(U32)\ X(U64)\ X(U128)\ X(U256)\ X(U512)\ X(S8)\ X(S16)\ X(S32)\ X(S64)\ X(S128)\ X(S256)\ X(S512)\ X(Bool)\ X(F16)\ X(F32)\ X(F32PP)\ X(F48)\ X(F64)\ X(F80)\ X(F128)\ X(ComplexF32)\ X(ComplexF64)\ X(ComplexF80)\ X(ComplexF128)\ X(Modifier)\ X(Ptr)\ X(LRef)\ X(RRef)\ X(Array)\ X(Function)\ X(Method)\ X(MemberPtr)\ X(Struct)\ X(Class)\ X(Union)\ X(Enum)\ X(Alias)\ X(IncompleteStruct)\ X(IncompleteUnion)\ X(IncompleteClass)\ X(IncompleteEnum)\ X(Bitfield)\ X(Variadic)\ X(Count)\ #define RDI_TypeModifierFlags_XList \ X(Const)\ X(Volatile)\ X(Restrict)\ #define RDI_TypeNode_XList \ X(RDI_TypeKind, kind)\ X(RDI_U16, flags)\ X(RDI_U32, byte_size)\ #define RDI_UDTFlags_XList \ X(EnumMembers)\ #define RDI_UDT_XList \ X(RDI_U32, self_type_idx)\ X(RDI_UDTFlags, flags)\ X(RDI_U32, member_first)\ X(RDI_U32, member_count)\ X(RDI_U32, file_idx)\ X(RDI_U32, line)\ X(RDI_U32, col)\ #define RDI_MemberKind_XList \ X(NULL)\ X(DataField)\ X(StaticData)\ X(Method)\ X(StaticMethod)\ X(VirtualMethod)\ X(VTablePtr)\ X(Base)\ X(VirtualBase)\ X(NestedType)\ #define RDI_Member_XList \ X(RDI_MemberKind, kind)\ X(RDI_U16, pad)\ X(RDI_U32, name_string_idx)\ X(RDI_U32, type_idx)\ X(RDI_U32, off)\ #define RDI_EnumMember_XList \ X(RDI_U32, name_string_idx)\ X(RDI_U32, pad)\ X(RDI_U64, val)\ #define RDI_LinkFlags_XList \ X(External)\ X(TypeScoped)\ X(ProcScoped)\ #define RDI_LocalKind_XList \ X(NULL)\ X(Parameter)\ X(Variable)\ #define RDI_LocationKind_XList \ X(NULL)\ X(AddrBytecodeStream)\ X(ValBytecodeStream)\ X(AddrRegPlusU16)\ X(AddrAddrRegPlusU16)\ X(ValReg)\ #define RDI_GlobalVariable_XList \ X(RDI_U32, name_string_idx)\ X(RDI_LinkFlags, link_flags)\ X(RDI_U64, voff)\ X(RDI_U32, type_idx)\ X(RDI_U32, container_idx)\ #define RDI_ThreadVariable_XList \ X(type, name_string_idx)\ X(type, link_flags)\ X(type, tls_off)\ X(type, type_idx)\ X(type, container_idx)\ #define RDI_Procedure_XList \ X(RDI_U32, name_string_idx)\ X(RDI_U32, link_name_string_idx)\ X(RDI_LinkFlags, link_flags)\ X(RDI_U32, type_idx)\ X(RDI_U32, root_scope_idx)\ X(RDI_U32, container_idx)\ X(RDI_U32, frame_base_location_first)\ X(RDI_U32, frame_base_location_opl)\ #define RDI_Scope_XList \ X(RDI_U32, proc_idx)\ X(RDI_U32, parent_scope_idx)\ X(RDI_U32, first_child_scope_idx)\ X(RDI_U32, next_sibling_scope_idx)\ X(RDI_U32, voff_range_first)\ X(RDI_U32, voff_range_opl)\ X(RDI_U32, local_first)\ X(RDI_U32, local_count)\ X(RDI_U32, inline_site_idx)\ #define RDI_InlineSite_XList \ X(RDI_U32, name_string_idx)\ X(RDI_U32, type_idx)\ X(RDI_U32, owner_type_idx)\ X(RDI_U32, line_table_idx)\ #define RDI_Local_XList \ X(RDI_LocalKind, kind)\ X(RDI_U32, name_string_idx)\ X(RDI_U32, type_idx)\ X(RDI_U32, pad)\ X(RDI_U32, location_first)\ X(RDI_U32, location_opl)\ #define RDI_LocationBlock_XList \ X(RDI_U32, scope_off_first)\ X(RDI_U32, scope_off_opl)\ X(RDI_U32, location_data_off)\ #define RDI_LocationBytecodeStream_XList \ X(RDI_LocationKind, kind)\ #define RDI_LocationRegPlusU16_XList \ X(RDI_LocationKind, kind)\ X(RDI_RegCode, reg_code)\ X(RDI_U16, offset)\ #define RDI_LocationReg_XList \ X(RDI_LocationKind, kind)\ X(RDI_RegCode, reg_code)\ #define RDI_EvalOp_XList \ X(Stop)\ X(Noop)\ X(Cond)\ X(Skip)\ X(MemRead)\ X(RegRead)\ X(RegReadDyn)\ X(FrameOff)\ X(ModuleOff)\ X(TLSOff)\ X(ObjectOff)\ X(CFA)\ X(ConstU8)\ X(ConstU16)\ X(ConstU32)\ X(ConstU64)\ X(ConstU128)\ X(ConstString)\ X(Abs)\ X(Neg)\ X(Add)\ X(Sub)\ X(Mul)\ X(Div)\ X(Mod)\ X(LShift)\ X(RShift)\ X(BitAnd)\ X(BitOr)\ X(BitXor)\ X(BitNot)\ X(LogAnd)\ X(LogOr)\ X(LogNot)\ X(EqEq)\ X(NtEq)\ X(LsEq)\ X(GrEq)\ X(Less)\ X(Grtr)\ X(Trunc)\ X(TruncSigned)\ X(Convert)\ X(Pick)\ X(Pop)\ X(Insert)\ X(ValueRead)\ X(ByteSwap)\ X(CallSiteValue)\ X(PartialValue)\ X(PartialValueBit)\ X(Swap)\ #define RDI_EvalTypeGroup_XList \ X(Other)\ X(U)\ X(S)\ X(F32)\ X(F64)\ #define RDI_EvalConversionKind_XList \ X(Noop)\ X(Legal)\ X(OtherToOther)\ X(ToOther)\ X(FromOther)\ #define RDI_NameMapKind_XList \ X(NULL)\ X(GlobalVariables)\ X(ThreadVariables)\ X(Constants)\ X(Procedures)\ X(Types)\ X(LinkNameProcedures)\ X(NormalSourcePaths)\ #define RDI_NameMap_XList \ X(RDI_U32, bucket_base_idx)\ X(RDI_U32, node_base_idx)\ X(RDI_U32, bucket_count)\ X(RDI_U32, node_count)\ #define RDI_NameMapBucket_XList \ X(RDI_U32, first_node)\ X(RDI_U32, node_count)\ #define RDI_NameMapNode_XList \ X(RDI_U32, string_idx)\ X(RDI_U32, match_count)\ X(RDI_U32, match_idx_or_idx_run_first)\ #if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING typedef struct RDI_U32_StringTable { RDI_U32 v; } RDI_U32_StringTable; typedef struct RDI_U32_IndexRuns { RDI_U32 v; } RDI_U32_IndexRuns; typedef struct RDI_U32_BinarySections { RDI_U32 v; } RDI_U32_BinarySections; typedef struct RDI_U32_FilePathNodes { RDI_U32 v; } RDI_U32_FilePathNodes; typedef struct RDI_U32_SourceFiles { RDI_U32 v; } RDI_U32_SourceFiles; typedef struct RDI_U32_LineTables { RDI_U32 v; } RDI_U32_LineTables; typedef struct RDI_U32_LineInfoVOffs { RDI_U32 v; } RDI_U32_LineInfoVOffs; typedef struct RDI_U32_LineInfoLines { RDI_U32 v; } RDI_U32_LineInfoLines; typedef struct RDI_U32_LineInfoColumns { RDI_U32 v; } RDI_U32_LineInfoColumns; typedef struct RDI_U32_SourceLineMaps { RDI_U32 v; } RDI_U32_SourceLineMaps; typedef struct RDI_U32_SourceLineMapNumbers { RDI_U32 v; } RDI_U32_SourceLineMapNumbers; typedef struct RDI_U32_SourceLineMapRanges { RDI_U32 v; } RDI_U32_SourceLineMapRanges; typedef struct RDI_U32_SourceLineMapVOffs { RDI_U32 v; } RDI_U32_SourceLineMapVOffs; typedef struct RDI_U32_Units { RDI_U32 v; } RDI_U32_Units; typedef struct RDI_U32_TypeNodes { RDI_U32 v; } RDI_U32_TypeNodes; typedef struct RDI_U32_UDTs { RDI_U32 v; } RDI_U32_UDTs; typedef struct RDI_U32_Members { RDI_U32 v; } RDI_U32_Members; typedef struct RDI_U32_EnumMembers { RDI_U32 v; } RDI_U32_EnumMembers; typedef struct RDI_U32_GlobalVariables { RDI_U32 v; } RDI_U32_GlobalVariables; typedef struct RDI_U32_ThreadVariables { RDI_U32 v; } RDI_U32_ThreadVariables; typedef struct RDI_U32_Constants { RDI_U32 v; } RDI_U32_Constants; typedef struct RDI_U32_Procedures { RDI_U32 v; } RDI_U32_Procedures; typedef struct RDI_U32_Scopes { RDI_U32 v; } RDI_U32_Scopes; typedef struct RDI_U32_ScopeVOffData { RDI_U32 v; } RDI_U32_ScopeVOffData; typedef struct RDI_U32_InlineSites { RDI_U32 v; } RDI_U32_InlineSites; typedef struct RDI_U32_Locals { RDI_U32 v; } RDI_U32_Locals; typedef struct RDI_U32_LocationBlocks { RDI_U32 v; } RDI_U32_LocationBlocks; typedef struct RDI_U32_LocationData { RDI_U32 v; } RDI_U32_LocationData; typedef struct RDI_U32_ConstantValueData { RDI_U32 v; } RDI_U32_ConstantValueData; typedef struct RDI_U32_ConstantValueTable { RDI_U32 v; } RDI_U32_ConstantValueTable; typedef struct RDI_U32_MD5Checksums { RDI_U32 v; } RDI_U32_MD5Checksums; typedef struct RDI_U32_SHA1Checksums { RDI_U32 v; } RDI_U32_SHA1Checksums; typedef struct RDI_U32_SHA256Checksums { RDI_U32 v; } RDI_U32_SHA256Checksums; typedef struct RDI_U32_Timestamps { RDI_U32 v; } RDI_U32_Timestamps; typedef struct RDI_U32_NameMaps { RDI_U32 v; } RDI_U32_NameMaps; typedef struct RDI_U32_NameMapBuckets { RDI_U32 v; } RDI_U32_NameMapBuckets; typedef struct RDI_U32_NameMapNodes { RDI_U32 v; } RDI_U32_NameMapNodes; #else typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table; typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table; typedef RDI_U32_Table RDI_U32_StringTable; typedef RDI_U32_Table RDI_U32_IndexRuns; typedef RDI_U32_Table RDI_U32_BinarySections; typedef RDI_U32_Table RDI_U32_FilePathNodes; typedef RDI_U32_Table RDI_U32_SourceFiles; typedef RDI_U32_Table RDI_U32_LineTables; typedef RDI_U32_Table RDI_U32_LineInfoVOffs; typedef RDI_U32_Table RDI_U32_LineInfoLines; typedef RDI_U32_Table RDI_U32_LineInfoColumns; typedef RDI_U32_Table RDI_U32_SourceLineMaps; typedef RDI_U32_Table RDI_U32_SourceLineMapNumbers; typedef RDI_U32_Table RDI_U32_SourceLineMapRanges; typedef RDI_U32_Table RDI_U32_SourceLineMapVOffs; typedef RDI_U32_Table RDI_U32_Units; typedef RDI_U32_Table RDI_U32_TypeNodes; typedef RDI_U32_Table RDI_U32_UDTs; typedef RDI_U32_Table RDI_U32_Members; typedef RDI_U32_Table RDI_U32_EnumMembers; typedef RDI_U32_Table RDI_U32_GlobalVariables; typedef RDI_U32_Table RDI_U32_ThreadVariables; typedef RDI_U32_Table RDI_U32_Constants; typedef RDI_U32_Table RDI_U32_Procedures; typedef RDI_U32_Table RDI_U32_Scopes; typedef RDI_U32_Table RDI_U32_ScopeVOffData; typedef RDI_U32_Table RDI_U32_InlineSites; typedef RDI_U32_Table RDI_U32_Locals; typedef RDI_U32_Table RDI_U32_LocationBlocks; typedef RDI_U32_Table RDI_U32_LocationData; typedef RDI_U32_Table RDI_U32_ConstantValueData; typedef RDI_U32_Table RDI_U32_ConstantValueTable; typedef RDI_U32_Table RDI_U32_MD5Checksums; typedef RDI_U32_Table RDI_U32_SHA1Checksums; typedef RDI_U32_Table RDI_U32_SHA256Checksums; typedef RDI_U32_Table RDI_U32_Timestamps; typedef RDI_U32_Table RDI_U32_NameMaps; typedef RDI_U32_Table RDI_U32_NameMapBuckets; typedef RDI_U32_Table RDI_U32_NameMapNodes; #endif #define RDI_EVAL_CTRLBITS(decodeN,popN,pushN) (((decodeN) << 8) | ((popN) << 4) | ((pushN) << 0)) #define RDI_DECODEN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 8) & 0xff) #define RDI_POPN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 4) & 0xf) #define RDI_PUSHN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 0) & 0xf) #define RDI_EncodeRegReadParam(reg,bytesize,bytepos) ((reg)|((bytesize)<<8)|((bytepos)<<16)) typedef struct RDI_Header RDI_Header; struct RDI_Header { RDI_U64 magic; RDI_U32 encoding_version; RDI_U32 data_section_off; RDI_U32 data_section_count; }; typedef struct RDI_Section RDI_Section; struct RDI_Section { RDI_SectionEncoding encoding; RDI_U32 pad; RDI_U64 off; RDI_U64 encoded_size; RDI_U64 unpacked_size; }; typedef struct RDI_VMapEntry RDI_VMapEntry; struct RDI_VMapEntry { RDI_U64 voff; RDI_U64 idx; }; typedef struct RDI_TopLevelInfo RDI_TopLevelInfo; struct RDI_TopLevelInfo { RDI_Arch arch; RDI_U32 exe_name_string_idx; RDI_U64 exe_hash; RDI_U64 voff_max; RDI_GUID guid; RDI_U32 producer_name_string_idx; }; typedef struct RDI_BinarySection RDI_BinarySection; struct RDI_BinarySection { RDI_U32 name_string_idx; RDI_BinarySectionFlags flags; RDI_U64 voff_first; RDI_U64 voff_opl; RDI_U64 foff_first; RDI_U64 foff_opl; }; typedef struct RDI_FilePathNode RDI_FilePathNode; struct RDI_FilePathNode { RDI_U32 name_string_idx; RDI_U32 parent_path_node; RDI_U32 first_child; RDI_U32 next_sibling; RDI_U32 source_file_idx; }; typedef struct RDI_SourceFile RDI_SourceFile; struct RDI_SourceFile { RDI_U32 file_path_node_idx; RDI_U32 normal_full_path_string_idx; RDI_U32 source_line_map_idx; RDI_ChecksumKind checksum_kind; RDI_U32 checksum_idx; }; typedef struct RDI_Unit RDI_Unit; struct RDI_Unit { RDI_U32 unit_name_string_idx; RDI_U32 compiler_name_string_idx; RDI_U32 source_file_path_node; RDI_U32 object_file_path_node; RDI_U32 archive_file_path_node; RDI_U32 build_path_node; RDI_Language language; RDI_U32 line_table_idx; }; typedef struct RDI_LineTable RDI_LineTable; struct RDI_LineTable { RDI_U32 voffs_base_idx; RDI_U32 lines_base_idx; RDI_U32 cols_base_idx; RDI_U32 lines_count; RDI_U32 cols_count; }; typedef struct RDI_Line RDI_Line; struct RDI_Line { RDI_U32 file_idx; RDI_U32 line_num; }; typedef struct RDI_Column RDI_Column; struct RDI_Column { RDI_U16 col_first; RDI_U16 col_opl; }; typedef struct RDI_SourceLineMap RDI_SourceLineMap; struct RDI_SourceLineMap { RDI_U32 line_count; RDI_U32 voff_count; RDI_U32 line_map_nums_base_idx; RDI_U32 line_map_range_base_idx; RDI_U32 line_map_voff_base_idx; }; typedef struct RDI_TypeNode RDI_TypeNode; struct RDI_TypeNode { RDI_TypeKind kind; RDI_U16 flags; RDI_U32 byte_size; union { // kind is 'built-in' struct { RDI_U32 name_string_idx; } built_in; // kind is 'constructed' struct { RDI_U32 direct_type_idx; RDI_U32 count; union { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; } constructed; // kind is 'user defined' struct { RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; } user_defined; // (kind = Bitfield) struct { RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; } bitfield; } ; }; typedef struct RDI_UDT RDI_UDT; struct RDI_UDT { RDI_U32 self_type_idx; RDI_UDTFlags flags; RDI_U32 member_first; RDI_U32 member_count; RDI_U32 file_idx; RDI_U32 line; RDI_U32 col; }; typedef struct RDI_Member RDI_Member; struct RDI_Member { RDI_MemberKind kind; RDI_U16 pad; RDI_U32 name_string_idx; RDI_U32 type_idx; RDI_U32 off; }; typedef struct RDI_EnumMember RDI_EnumMember; struct RDI_EnumMember { RDI_U32 name_string_idx; RDI_U32 pad; RDI_U64 val; }; typedef struct RDI_GlobalVariable RDI_GlobalVariable; struct RDI_GlobalVariable { RDI_U32 name_string_idx; RDI_LinkFlags link_flags; RDI_U64 voff; RDI_U32 type_idx; RDI_U32 container_idx; }; typedef struct RDI_ThreadVariable RDI_ThreadVariable; struct RDI_ThreadVariable { RDI_U32 name_string_idx; RDI_LinkFlags link_flags; RDI_U32 tls_off; RDI_U32 type_idx; RDI_U32 container_idx; }; typedef struct RDI_Constant RDI_Constant; struct RDI_Constant { RDI_U32 name_string_idx; RDI_U32 type_idx; RDI_U32 constant_value_idx; }; typedef struct RDI_Procedure RDI_Procedure; struct RDI_Procedure { RDI_U32 name_string_idx; RDI_U32 link_name_string_idx; RDI_LinkFlags link_flags; RDI_U32 type_idx; RDI_U32 root_scope_idx; RDI_U32 container_idx; RDI_U32 frame_base_location_first; RDI_U32 frame_base_location_opl; }; typedef struct RDI_Scope RDI_Scope; struct RDI_Scope { RDI_U32 proc_idx; RDI_U32 parent_scope_idx; RDI_U32 first_child_scope_idx; RDI_U32 next_sibling_scope_idx; RDI_U32 voff_range_first; RDI_U32 voff_range_opl; RDI_U32 local_first; RDI_U32 local_count; RDI_U32 inline_site_idx; }; typedef struct RDI_InlineSite RDI_InlineSite; struct RDI_InlineSite { RDI_U32 name_string_idx; RDI_U32 type_idx; RDI_U32 owner_type_idx; RDI_U32 line_table_idx; }; typedef struct RDI_Local RDI_Local; struct RDI_Local { RDI_LocalKind kind; RDI_U32 name_string_idx; RDI_U32 type_idx; RDI_U32 pad; RDI_U32 location_first; RDI_U32 location_opl; }; typedef struct RDI_LocationBlock RDI_LocationBlock; struct RDI_LocationBlock { RDI_U32 scope_off_first; RDI_U32 scope_off_opl; RDI_U32 location_data_off; }; typedef struct RDI_LocationBytecodeStream RDI_LocationBytecodeStream; struct RDI_LocationBytecodeStream { RDI_LocationKind kind; }; typedef struct RDI_LocationRegPlusU16 RDI_LocationRegPlusU16; struct RDI_LocationRegPlusU16 { RDI_LocationKind kind; RDI_RegCode reg_code; RDI_U16 offset; }; typedef struct RDI_LocationReg RDI_LocationReg; struct RDI_LocationReg { RDI_LocationKind kind; RDI_RegCode reg_code; }; typedef struct RDI_NameMap RDI_NameMap; struct RDI_NameMap { RDI_U32 bucket_base_idx; RDI_U32 node_base_idx; RDI_U32 bucket_count; RDI_U32 node_count; }; typedef struct RDI_NameMapBucket RDI_NameMapBucket; struct RDI_NameMapBucket { RDI_U32 first_node; RDI_U32 node_count; }; typedef struct RDI_NameMapNode RDI_NameMapNode; struct RDI_NameMapNode { RDI_U32 string_idx; RDI_U32 match_count; RDI_U32 match_idx_or_idx_run_first; }; typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; typedef RDI_U8 RDI_SectionElementType_StringData; typedef RDI_U32 RDI_SectionElementType_StringTable; typedef RDI_U32 RDI_SectionElementType_IndexRuns; typedef RDI_BinarySection RDI_SectionElementType_BinarySections; typedef RDI_FilePathNode RDI_SectionElementType_FilePathNodes; typedef RDI_SourceFile RDI_SectionElementType_SourceFiles; typedef RDI_LineTable RDI_SectionElementType_LineTables; typedef RDI_U64 RDI_SectionElementType_LineInfoVOffs; typedef RDI_Line RDI_SectionElementType_LineInfoLines; typedef RDI_Column RDI_SectionElementType_LineInfoColumns; typedef RDI_SourceLineMap RDI_SectionElementType_SourceLineMaps; typedef RDI_U32 RDI_SectionElementType_SourceLineMapNumbers; typedef RDI_U32 RDI_SectionElementType_SourceLineMapRanges; typedef RDI_U64 RDI_SectionElementType_SourceLineMapVOffs; typedef RDI_Unit RDI_SectionElementType_Units; typedef RDI_VMapEntry RDI_SectionElementType_UnitVMap; typedef RDI_TypeNode RDI_SectionElementType_TypeNodes; typedef RDI_UDT RDI_SectionElementType_UDTs; typedef RDI_Member RDI_SectionElementType_Members; typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; typedef RDI_Constant RDI_SectionElementType_Constants; typedef RDI_Procedure RDI_SectionElementType_Procedures; typedef RDI_Scope RDI_SectionElementType_Scopes; typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; typedef RDI_VMapEntry RDI_SectionElementType_ScopeVMap; typedef RDI_InlineSite RDI_SectionElementType_InlineSites; typedef RDI_Local RDI_SectionElementType_Locals; typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; typedef RDI_U8 RDI_SectionElementType_LocationData; typedef RDI_U8 RDI_SectionElementType_ConstantValueData; typedef RDI_U32 RDI_SectionElementType_ConstantValueTable; typedef RDI_MD5 RDI_SectionElementType_MD5Checksums; typedef RDI_SHA1 RDI_SectionElementType_SHA1Checksums; typedef RDI_SHA256 RDI_SectionElementType_SHA256Checksums; typedef RDI_U64 RDI_SectionElementType_Timestamps; typedef RDI_NameMap RDI_SectionElementType_NameMaps; typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out); RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); extern RDI_U16 rdi_section_element_size_table[44]; extern RDI_U16 rdi_eval_op_ctrlbits_table[53]; #endif // RDI_H ================================================ FILE: src/lib_rdi/rdi_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ Compression/Decompression Forward-Declares #ifndef _RAD_LZB_SIMPLE_H_ #define _RAD_LZB_SIMPLE_H_ /*====================================================== To encode : Set up an rr_lzb_simple_context fill out m_tableSizeBits (14-16 is typical) allocate m_hashTable rr_lzb_simple_context c; c.m_tableSizeBits = 14; c.m_hashTable = OODLE_MALLOC_ARRAY(U16,RR_ONE_SA< typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef S64 SINTa; typedef U64 RAD_U64; typedef S64 RAD_S64; typedef U32 RAD_U32; typedef S32 RAD_S32; #define RADINLINE __inline #if defined(_MSC_VER) # define RADFORCEINLINE __forceinline #elif defined(__clang__) || defined(__GNUC__) # define RADFORCEINLINE __attribute__((always_inline)) #else # error need force inline for this compiler #endif #if _MSC_VER # define RADLZB_TRAP() __debugbreak() #elif __clang__ || __GNUC__ # define RADLZB_TRAP() __builtin_trap() #else # error Unknown trap intrinsic for this compiler. #endif #define RR_STRING_JOIN(arg1, arg2) RR_STRING_JOIN_DELAY(arg1, arg2) #define RR_STRING_JOIN_DELAY(arg1, arg2) RR_STRING_JOIN_IMMEDIATE(arg1, arg2) #define RR_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 #ifdef _MSC_VER #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__COUNTER__) #else #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__LINE__) #endif #define RR_COMPILER_ASSERT(exp) typedef char RR_NUMBERNAME(_dummy_array) [ (exp) ? 1 : -1 ] #if defined(__clang__) # define Expect(expr, val) __builtin_expect((expr), (val)) #else # define Expect(expr, val) (expr) #endif #define RAD_LIKELY(expr) Expect(expr,1) #define RAD_UNLIKELY(expr) Expect(expr,0) #define __RADLITTLEENDIAN__ 1 #define RAD_PTRBYTES 8 #define RR_MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define RR_MAX(a,b) ( (a) > (b) ? (a) : (b) ) #define RR_ASSERT_ALWAYS(c) do{if(!(c)) {RADLZB_TRAP();}}while(0) #define RR_ASSERT(c) RR_ASSERT_ALWAYS(c) #define RR_PUT16_LE(ptr,val) *((U16 *)(ptr)) = (U16)(val) #define RR_GET16_LE_UNALIGNED(ptr) *((const U16 *)(ptr)) static RADINLINE U32 rrCtzBytes32(U32 val) { // Don't get fancy here. Assumes val != 0. if (val & 0x000000ffu) return 0; if (val & 0x0000ff00u) return 1; if (val & 0x00ff0000u) return 2; return 3; } static RADINLINE U32 rrCtzBytes64(U64 val) { U32 lo = (U32) val; return lo ? rrCtzBytes32(lo) : 4 + rrCtzBytes32((U32) (val >> 32)); } //~ //--------------------- typedef struct rr_lzb_simple_context rr_lzb_simple_context; struct rr_lzb_simple_context { U16 * m_hashTable; // must be allocated to sizeof(U16)*(1<magic != RDI_MAGIC_CONSTANT) { hdr = 0; result = RDI_ParseStatus_HeaderDoesNotMatch; } if(hdr != 0 && hdr->encoding_version != RDI_ENCODING_VERSION) { hdr = 0; result = RDI_ParseStatus_UnsupportedVersionNumber; } } ////////////////////////////// //- rjf: extract data sections // RDI_Section *dsecs = 0; RDI_U32 dsec_count = 0; if(result == RDI_ParseStatus_Good) { RDI_U64 opl = (RDI_U64)hdr->data_section_off + (RDI_U64)hdr->data_section_count*sizeof(*dsecs); if(opl <= size) { dsecs = (RDI_Section*)(data + hdr->data_section_off); dsec_count = hdr->data_section_count; } if(dsecs == 0) { result = RDI_ParseStatus_InvalidDataSecionLayout; } } ////////////////////////////// //- rjf: fill result // if(result == RDI_ParseStatus_Good) { out->raw_data = data; out->raw_data_size = size; out->sections = dsecs; out->sections_count = dsec_count; } return result; } //////////////////////////////// //~ Base Parsed Info Extraction Helpers //- section table/element raw data extraction RDI_PROC void * rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out) { void *result = 0; #if !defined(RDI_DISABLE_NILS) result = &rdi_nil_element_union; *size_out = rdi_section_element_size_table[kind]; #endif if(0 <= kind && kind < rdi->sections_count && rdi->sections[kind].off < rdi->raw_data_size) { result = rdi->raw_data+rdi->sections[kind].off; *size_out = rdi->sections[kind].encoded_size; *encoding_out = rdi->sections[kind].encoding; } return result; } RDI_PROC void * rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out) { void *result = 0; RDI_U64 all_elements_size = 0; RDI_SectionEncoding all_elements_encoding = 0; void *all_elements = rdi_section_raw_data_from_kind(rdi, kind, &all_elements_encoding, &all_elements_size); if(all_elements_encoding == RDI_SectionEncoding_Unpacked) { RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; RDI_U64 all_elements_count = all_elements_size/element_size; result = all_elements; *count_out = all_elements_count; } return result; } RDI_PROC void * rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx) { RDI_U64 count = 0; void *table = rdi_section_raw_table_from_kind(rdi, kind, &count); void *result = table; if(idx < count) { RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; result = (RDI_U8 *)table + element_size*idx; } return result; } //- info about whole parse RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi) { RDI_U64 decompressed_size = rdi->raw_data_size; for(RDI_U64 section_idx = 0; section_idx < rdi->sections_count; section_idx += 1) { decompressed_size += (rdi->sections[section_idx].unpacked_size - rdi->sections[section_idx].encoded_size); } return decompressed_size; } //- decompression internal void rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed *og_rdi) { // rjf: copy header RDI_Header *src_header = (RDI_Header *)og_rdi->raw_data; RDI_Header *dst_header = (RDI_Header *)decompressed_data; { MemoryCopy(dst_header, src_header, sizeof(RDI_Header)); } // rjf: copy & adjust sections for decompressed version if(og_rdi->sections_count != 0) { RDI_Section *dsec_base = (RDI_Section *)(decompressed_data + dst_header->data_section_off); MemoryCopy(dsec_base, (U8 *)og_rdi->raw_data + src_header->data_section_off, sizeof(RDI_Section) * og_rdi->sections_count); U64 off = dst_header->data_section_off + sizeof(RDI_Section) * og_rdi->sections_count; off += 7; off -= off%8; for(U64 idx = 0; idx < og_rdi->sections_count; idx += 1) { dsec_base[idx].encoding = RDI_SectionEncoding_Unpacked; dsec_base[idx].off = off; dsec_base[idx].encoded_size = dsec_base[idx].unpacked_size; off += dsec_base[idx].unpacked_size; off += 7; off -= off%8; } } // rjf: decompress sections into new decompressed file buffer if(og_rdi->sections_count != 0) { RDI_Section *src_first = og_rdi->sections; RDI_Section *dst_first = (RDI_Section *)(decompressed_data + dst_header->data_section_off); RDI_Section *src_opl = src_first + og_rdi->sections_count; RDI_Section *dst_opl = dst_first + og_rdi->sections_count; for(RDI_Section *src = src_first, *dst = dst_first; src < src_opl && dst < dst_opl; src += 1, dst += 1) { rr_lzb_simple_decode((U8*)og_rdi->raw_data + src->off, src->encoded_size, decompressed_data + dst->off, dst->unpacked_size); } } } //- strings RDI_PROC RDI_U8 * rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out) { RDI_U8 *result_base = 0; RDI_U64 result_size = 0; { RDI_U64 string_offs_count = 0; RDI_U32 *string_offs = rdi_table_from_name(rdi, StringTable, &string_offs_count); if(idx < string_offs_count) { RDI_U64 string_data_size = 0; RDI_U8 *string_data = rdi_table_from_name(rdi, StringData, &string_data_size); RDI_U32 off_raw = string_offs[idx]; RDI_U32 opl_raw = string_offs[idx + 1]; RDI_U32 opl = rdi_parse__min(opl_raw, string_data_size); RDI_U32 off = rdi_parse__min(off_raw, opl); result_base = string_data + off; result_size = opl - off; } } *len_out = result_size; return result_base; } //- index runs RDI_PROC RDI_U32* rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out) { RDI_U64 idx_run_count = 0; RDI_U32 *idx_run_data = rdi_table_from_name(rdi, IndexRuns, &idx_run_count); RDI_U32 raw_opl = raw_first + raw_count; RDI_U32 opl = rdi_parse__min(raw_opl, idx_run_count); RDI_U32 first = rdi_parse__min(raw_first, opl); RDI_U32 *result = 0; if(first < idx_run_count) { result = idx_run_data + first; } *n_out = opl - first; return result; } //- line info RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out) { //- rjf: extract top-level line info tables RDI_U64 all_voffs_count = 0; RDI_U64 *all_voffs = rdi_table_from_name(rdi, LineInfoVOffs, &all_voffs_count); RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; RDI_U64 all_lines_count = 0; RDI_Line *all_lines = rdi_table_from_name(rdi, LineInfoLines, &all_lines_count); RDI_Line *all_lines_opl = all_lines + all_lines_count; RDI_U64 all_cols_count = 0; RDI_Column *all_cols = rdi_table_from_name(rdi, LineInfoColumns, &all_cols_count); RDI_Column *all_cols_opl = all_cols + all_cols_count; //- rjf: extract ranges of top-level tables belonging to this line table RDI_U64 *lt_voffs = all_voffs + line_table->voffs_base_idx; RDI_Line *lt_lines = all_lines + line_table->lines_base_idx; RDI_Column *lt_cols = all_cols + line_table->cols_base_idx; RDI_U64 lines_count = line_table->lines_count; RDI_U64 cols_count = line_table->cols_count; if(lt_voffs >= all_voffs_opl) {lt_voffs = all_voffs; lines_count = 0;} if(lt_lines >= all_lines_opl) {lt_lines = all_lines; lines_count = 0;} if(lt_cols >= all_cols_opl) {lt_cols = all_cols; cols_count = 0;} //- rjf: fill result out->voffs = lt_voffs; out->lines = lt_lines; out->cols = lt_cols; out->count = lines_count; out->col_count = cols_count; } RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out) { RDI_U64 result = 0; RDI_U64 n = 0; if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]) { //- rjf: find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) // assuming: (i < j) -> (vmap[i].voff < vmap[j].voff) RDI_U32 first = 0; RDI_U32 opl = line_info->count; for(;;) { RDI_U32 mid = (first + opl)/2; if(line_info->voffs[mid] < voff) { first = mid; } else if(line_info->voffs[mid] > voff) { opl = mid; } else { first = mid; break; } if(opl - first <= 1) { break; } } result = (RDI_U64)first; //- rjf: scan leftward, to find shallowest line info matching this voff for(;result != 0;) { if(line_info->voffs[result-1] == voff) { result -= 1; } else { break; } } //- rjf: scan rightward, to count # of line info with this voff for(RDI_U64 idx = result; idx < line_info->count; idx += 1) { if(line_info->voffs[idx] == voff) { n += 1; } else { break; } } } if(n_out) { *n_out = n; } return result; } RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) { RDI_U64 count = 0; RDI_U64 result = rdi_line_info_idx_range_from_voff(line_info, voff, &count); for(RDI_S64 idx = count-1; idx >= 0; idx -= 1) { if(result + idx < line_info->count && line_info->lines[result+idx].file_idx != 0) { result += idx; break; } } return result; } RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out) { //- rjf: extract top-level line info tables RDI_U64 all_nums_count = 0; RDI_U32 *all_nums = rdi_table_from_name(rdi, SourceLineMapNumbers, &all_nums_count); RDI_U32 *all_nums_opl = all_nums + all_nums_count; RDI_U64 all_rngs_count = 0; RDI_U32 *all_rngs = rdi_table_from_name(rdi, SourceLineMapRanges, &all_rngs_count); RDI_U32 *all_rngs_opl = all_rngs + all_rngs_count; RDI_U64 all_voffs_count = 0; RDI_U64 *all_voffs = rdi_table_from_name(rdi, SourceLineMapVOffs, &all_voffs_count); RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; //- rjf: extract ranges of top-level tables belonging to this line map RDI_U32 *map_nums = all_nums + map->line_map_nums_base_idx; RDI_U32 *map_rngs = all_rngs + map->line_map_range_base_idx; RDI_U64 *map_voffs= all_voffs+ map->line_map_voff_base_idx; RDI_U64 lines_count = (RDI_U64)map->line_count; RDI_U64 voffs_count = (RDI_U64)map->voff_count; if(map_nums >= all_nums_opl) {map_nums = all_nums; lines_count = 0;} if(map_rngs >= all_rngs_opl) {map_rngs = all_rngs; lines_count = 0;} if(map_voffs>= all_voffs_opl){map_voffs= all_voffs;voffs_count = 0;} //- rjf: fill result out->nums = map_nums; out->ranges = map_rngs; out->voffs = map_voffs; out->count = lines_count; out->voff_count = voffs_count; } RDI_PROC RDI_U64 * rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) { RDI_U64 *result = 0; *n_out = 0; RDI_U32 closest_i = 0; if(map->count > 0 && map->nums[0] <= linenum) { // assuming: (i < j) -> (nums[i] < nums[j]) // find i such that: (nums[i] <= linenum) && (linenum < nums[i + 1]) RDI_U32 *nums = map->nums; RDI_U32 first = 0; RDI_U32 opl = map->count; for(;;) { RDI_U32 mid = (first + opl)/2; if(nums[mid] < linenum) { first = mid; } else if(nums[mid] > linenum) { opl = mid; } else { first = mid; break; } if(opl - first <= 1) { break; } } closest_i = first; } // round up instead of down if possible if(closest_i + 1 < map->count && map->nums[closest_i] < linenum) { closest_i += 1; } // set result if possible if(closest_i < map->count) { RDI_U32 first = map->ranges[closest_i]; RDI_U32 opl = map->ranges[closest_i + 1]; if(opl <= map->voff_count) { result = map->voffs + first; *n_out = opl - first; } } return result; } //- vmap lookups RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff) { RDI_U64 result = 0; if(vmap_count > 0 && vmap[0].voff <= voff && voff < vmap[vmap_count - 1].voff) { // assuming: (i < j) -> (vmap[i].voff < vmap[j].voff) // find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) RDI_U32 first = 0; RDI_U32 opl = vmap_count; for(;;) { RDI_U32 mid = (first + opl)/2; if(vmap[mid].voff < voff) { first = mid; } else if(vmap[mid].voff > voff) { opl = mid; } else { first = mid; break; } if(opl - first <= 1) { break; } } result = (RDI_U64)vmap[first].idx; } return result; } RDI_PROC RDI_U64 rdi_vmap_idx_from_section_kind_voff(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 voff) { RDI_U64 vmaps_count = 0; RDI_VMapEntry *vmaps = rdi_section_raw_table_from_kind(rdi, kind, &vmaps_count); RDI_U64 result = rdi_vmap_idx_from_voff(vmaps, vmaps_count, voff); return result; } //- name maps RDI_PROC void rdi_parsed_from_name_map(RDI_Parsed *rdi, RDI_NameMap *mapptr, RDI_ParsedNameMap *out) { out->buckets = 0; out->bucket_count = 0; if(mapptr != 0) { RDI_U64 all_buckets_count = 0; RDI_NameMapBucket *all_buckets = rdi_table_from_name(rdi, NameMapBuckets, &all_buckets_count); RDI_U64 all_nodes_count = 0; RDI_NameMapNode *all_nodes = rdi_table_from_name(rdi, NameMapNodes, &all_nodes_count); out->buckets = all_buckets+mapptr->bucket_base_idx; out->nodes = all_nodes+mapptr->node_base_idx; out->bucket_count = mapptr->bucket_count; out->node_count = mapptr->node_count; if(mapptr->bucket_base_idx > all_buckets_count) { out->buckets = 0; out->bucket_count = 0; } if(mapptr->node_base_idx > all_nodes_count) { out->nodes = 0; out->node_count = 0; } } } RDI_PROC RDI_NameMapNode* rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len) { RDI_NameMapNode *result = 0; if(map->bucket_count > 0) { RDI_NameMapBucket *buckets = map->buckets; RDI_U64 bucket_count = map->bucket_count; RDI_U64 hash = rdi_hash(str, len); RDI_U64 bucket_index = hash%bucket_count; RDI_NameMapBucket *bucket = map->buckets + bucket_index; RDI_NameMapNode *node = map->nodes + bucket->first_node; RDI_NameMapNode *node_opl = node + bucket->node_count; for(;node < node_opl; node += 1) { // extract a string from this node RDI_U64 nlen = 0; RDI_U8 *nstr = rdi_string_from_idx(p, node->string_idx, &nlen); // compare this to the needle string RDI_S32 match = 0; if(nlen == len) { RDI_U8 *a = str; RDI_U8 *aopl = str + len; RDI_U8 *b = nstr; for (;a < aopl && *a == *b; a += 1, b += 1); match = (a == aopl); } // stop with a matching node in result if(match) { result = node; break; } } } return result; } RDI_PROC RDI_U32* rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out) { RDI_U32 *result = 0; *n_out = 0; if(node != 0) { if(node->match_count == 1) { result = &node->match_idx_or_idx_run_first; *n_out = 1; } else { result = rdi_idx_run_from_first_count(p, node->match_idx_or_idx_run_first, node->match_count, n_out); } } return result; } //////////////////////////////// //~ High-Level Composite Lookup Functions //- procedures RDI_PROC RDI_Procedure * rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) { RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); RDI_ParsedNameMap map_parsed = {0}; rdi_parsed_from_name_map(rdi, map, &map_parsed); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); RDI_U32 id_count = 0; RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); RDI_U32 procedure_idx = 0; if(id_count > 0) { procedure_idx = ids[0]; } RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); return procedure; } RDI_PROC RDI_Procedure * rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr) { RDI_Procedure *result = rdi_procedure_from_name(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); return result; } RDI_PROC RDI_U8 * rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out) { return rdi_string_from_idx(rdi, procedure->name_string_idx, len_out); } RDI_PROC RDI_Scope * rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); return scope; } RDI_PROC RDI_UDT * rdi_container_udt_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { RDI_U64 idx = 0; if(procedure->link_flags & RDI_LinkFlag_TypeScoped) { idx = procedure->container_idx; } RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, idx); return udt; } RDI_PROC RDI_Procedure * rdi_container_procedure_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { RDI_U64 idx = 0; if(procedure->link_flags & RDI_LinkFlag_ProcScoped) { idx = procedure->container_idx; } RDI_Procedure *container_procedure = rdi_element_from_name_idx(rdi, Procedures, idx); return container_procedure; } RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); RDI_U64 result = rdi_first_voff_from_scope(rdi, scope); return result; } RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); RDI_U64 result = rdi_opl_voff_from_scope(rdi, scope); return result; } RDI_PROC RDI_Procedure * rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); return procedure; } //- scopes RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) { RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); RDI_U64 result = *voffs; return result; } RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) { RDI_U64 result = 0; if(scope->voff_range_opl != 0) { RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_opl-1); result = *voffs; } return result; } RDI_PROC RDI_Scope * rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, idx); return scope; } RDI_PROC RDI_Scope * rdi_parent_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) { RDI_Scope *parent = rdi_element_from_name_idx(rdi, Scopes, scope->parent_scope_idx); return parent; } RDI_PROC RDI_Procedure * rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) { RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); return procedure; } RDI_PROC RDI_InlineSite * rdi_inline_site_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) { RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, scope->inline_site_idx); return inline_site; } //- global variables RDI_PROC RDI_GlobalVariable * rdi_global_variable_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff); RDI_GlobalVariable *gvar = rdi_element_from_name_idx(rdi, GlobalVariables, idx); return gvar; } //- units RDI_PROC RDI_Unit * rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); return unit; } RDI_PROC RDI_LineTable * rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit) { RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); return line_table; } //- line info RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff); return line; } RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff) { RDI_ParsedLineTable parsed = {0}; rdi_parsed_from_line_table(rdi, line_table, &parsed); RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff); RDI_Line result = {0}; if(line_info_idx < parsed.count) { result = parsed.lines[line_info_idx]; } return result; } RDI_PROC RDI_SourceFile * rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line) { RDI_SourceFile *result = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); return result; } //- source files RDI_PROC RDI_SourceFile * rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) { RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); RDI_ParsedNameMap map_parsed = {0}; rdi_parsed_from_name_map(rdi, map, &map_parsed); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); RDI_U32 id_count = 0; RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); RDI_U32 file_idx = 0; if(id_count > 0) { file_idx = ids[0]; } RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, file_idx); return file; } RDI_PROC RDI_SourceFile * rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr) { RDI_SourceFile *result = rdi_source_file_from_normal_path(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); return result; } RDI_PROC RDI_U8 * rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out) { return rdi_string_from_idx(rdi, src_file->normal_full_path_string_idx, len_out); } RDI_PROC RDI_FilePathNode * rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) { RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, src_file->file_path_node_idx); return result; } RDI_PROC RDI_SourceLineMap * rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) { RDI_SourceLineMap *result = rdi_element_from_name_idx(rdi, SourceLineMaps, src_file->source_line_map_idx); return result; } RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num) { RDI_SourceLineMap *source_line_map = rdi_source_line_map_from_source_file(rdi, src_file); RDI_U64 voff = rdi_first_voff_from_source_line_map_num(rdi, source_line_map, line_num); return voff; } //- source line maps RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num) { RDI_ParsedSourceLineMap parsed = {0}; rdi_parsed_from_source_line_map(rdi, map, &parsed); RDI_U32 all_voffs_count = 0; RDI_U64 *all_voffs = rdi_line_voffs_from_num(&parsed, line_num, &all_voffs_count); RDI_U64 voff = 0; if(all_voffs_count != 0) { voff = all_voffs[0]; } return voff; } //- file path nodes RDI_PROC RDI_FilePathNode * rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node) { RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, node->parent_path_node); return result; } RDI_PROC RDI_U8 * rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out) { return rdi_string_from_idx(rdi, node->name_string_idx, len_out); } //////////////////////////////// //~ Parser Helpers RDI_PROC RDI_U64 rdi_cstring_length(char *cstr) { RDI_U64 result = 0; for(;cstr[result] != 0; result += 1){} return result; } RDI_PROC RDI_U64 rdi_size_from_bytecode_stream(RDI_U8 *ptr, RDI_U8 *opl) { RDI_U64 bytecode_size = 0; RDI_U8 *off_first = ptr + sizeof(RDI_LocationKind); for(RDI_U8 *off = off_first, *next_off = opl; off < opl; off = next_off) { RDI_U8 op = *off; if(op == 0) { break; } RDI_U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); bytecode_size += (1 + p_size); next_off = (off + 1 + p_size); } return bytecode_size; } //////////////////////////////// //~ Compression/Decompression Implementation #include //------------------------------------------------- // UINTr = int the size of a register #ifdef __RAD64REGS__ #define RAD_UINTr RAD_U64 #define RAD_SINTr RAD_S64 #define readR read64 #define writeR write64 #define rrClzBytesR rrClzBytes64 #define rrCtzBytesR rrCtzBytes64 #else #define RAD_UINTr RAD_U32 #define RAD_SINTr RAD_S32 #define readR read32 #define writeR write32 #define rrClzBytesR rrClzBytes32 #define rrCtzBytesR rrCtzBytes32 #endif typedef RAD_SINTr SINTr; typedef RAD_UINTr UINTr; #define OOINLINE RADFORCEINLINE #define if_unlikely(exp) if ( RAD_UNLIKELY( exp ) ) #define if_likely( exp) if ( RAD_LIKELY( exp ) ) // Raw byte IO #if defined(__RADARM__) && !defined(__RAD64__) && defined(__GNUC__) // older GCCs don't turn the memcpy variant into loads/stores, but // they do support this: typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unaligned_type; static inline U16 read16(const void *ptr) { return ((const unaligned_type *)ptr)->u16; } static inline void write16(void *ptr, U16 x) { ((unaligned_type *)ptr)->u16 = x; } static inline U32 read32(const void *ptr) { return ((const unaligned_type *)ptr)->u32; } static inline void write32(void *ptr, U32 x) { ((unaligned_type *)ptr)->u32 = x; } static inline U64 read64(const void *ptr) { return ((const unaligned_type *)ptr)->u64; } static inline void write64(void *ptr, U64 x) { ((unaligned_type *)ptr)->u64 = x; } #else // most C compilers we target are smart enough to turn this into single loads/stores static inline U16 read16(const void *ptr) { U16 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write16(void *ptr, U16 x) { memcpy(ptr, &x, sizeof(x)); } static inline U32 read32(const void *ptr) { U32 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write32(void *ptr, U32 x) { memcpy(ptr, &x, sizeof(x)); } static inline U64 read64(const void *ptr) { U64 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write64(void *ptr, U64 x) { memcpy(ptr, &x, sizeof(x)); } #endif #define RR_PUT16_LE_UNALIGNED(ptr,val) RR_PUT16_LE(ptr,val) #define RR_PUT16_LE_UNALIGNED_OFFSET(ptr,val,offset) RR_PUT16_LE_OFFSET(ptr,val,offset) //=========================================================================== static RADINLINE SINTa rrPtrDiffV(void * end, void *start) { return (SINTa)( ((char *)(end)) - ((char *)(start)) ); } // helper function to show I really am intending to put a pointer difference in an int : static RADINLINE SINTa rrPtrDiff(SINTa val) { return val; } static RADINLINE S32 rrPtrDiff32(SINTa val) { S32 ret = (S32) val; RR_ASSERT( (SINTa)ret == val ); return ret; } static RADINLINE SINTr rrPtrDiffR(SINTa val) { SINTr ret = (SINTr) val; RR_ASSERT( (SINTa)ret == val ); return ret; } //================================================================= #define LZB_LRL_BITS 4 #define LZB_LRL_ESCAPE 15 #define LZB_ML_BITS 4 #define LZB_MLCONTROL_ESCAPE 15 #define LZB_SLIDING_WINDOW_POW2 16 #define LZB_SLIDING_WINDOW_SIZE (1<>= 6; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; *cp++ = (U8) val; } } } } \ } while(0) // max bytes consumed: 5 #define LZB_AddExcessBW(cp,val) do { U32 b = *cp++; \ if ( b < 192 ) val += b; \ else { val += 192; val += (b-192); b = *cp++; \ val += (b<<6); if ( b >= 128 ) { b = *cp++; \ val += (b<<13); if ( b >= 128 ) { b = *cp++; \ val += (b<<20); if ( b >= 128 ) { b = *cp++; \ val += (b<<27); } } } } \ } while(0) #define LZB_PutExcessLRL(cp,val) LZB_PutExcessBW(cp,val) #define LZB_PutExcessML(cp,val) LZB_PutExcessBW(cp,val) #define LZB_AddExcessLRL(cp,val) LZB_AddExcessBW(cp,val) #define LZB_AddExcessML(cp,val) LZB_AddExcessBW(cp,val) //============================================================================= // match copies : // used for LRL : static OOINLINE void copy_no_overlap_long(U8 * to, const U8 * from, SINTr length) { for(int i=0;i= LZB_MML && ml < LZB_MATCHLEN_ESCAPE ); // overlap // @@ err not awesome to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to[4] = from[4]; to[5] = from[5]; to[6] = from[6]; to[7] = from[7]; if ( ml > 8 ) { to += 8; from += 8; ml -= 8; // max of 10 more while(ml--) { *to++ = *from++; } } } static OOINLINE void copy_match_memset(U8 * to, int c, SINTr ml) { RR_ASSERT( ml >= 4 ); U32 four = c * 0x01010101; U8 * end = to + ml; write32(to, four); to += 4; while(to>4); // copy 4 literals speculatively : write32( rp , read32(cp) ); //RR_ASSERT( lrl >= 8 || ml_control >= 8 ); if ( lrl > 4 ) { // if lrl was <= 8 we did it, else need this : if_unlikely ( lrl > 8 ) { if_unlikely ( lrl >= LZB_LRL_ESCAPE ) { LZB_AddExcessLRL( cp, lrl ); // hide the EOF check here ? // has to be after the GetExcess if_unlikely ( rp+lrl >= rpEnd ) { RR_ASSERT( rp+lrl == rpEnd ); copy_no_overlap_nooverrun(rp,cp,lrl); rp += lrl; cp += lrl; break; } else { // total undo of the previous copy copy_no_overlap_long(rp,cp,lrl); } } else // > 8 but not 0xF { // hide the EOF check here ? if_unlikely ( rp+lrl >= rpEnd ) { if ( lrl == 9 ) { // may be a false 9 lrl = rrPtrDiff32( rpEnd - rp ); } RR_ASSERT( rp+lrl == rpEnd ); copy_no_overlap_nooverrun(rp,cp,lrl); rp += lrl; cp += lrl; break; } else { write32( rp+4 , read32(cp+4) ); // put 8 more : write64( (rp+8) , read64((cp+8)) ); } } } else { write32( rp+4 , read32(cp+4) ); } } rp += lrl; cp += lrl; RR_ASSERT( rp+LZB_MML <= rpEnd ); UINTr ml = ml_control + LZB_MML; // speculatively grab offset but don't advance cp yet UINTr off = RR_GET16_LE_UNALIGNED(cp); if ( ml_control <= 8 ) { cp += 2; // consume offset const U8 * match = rp - off; RR_ASSERT( ml <= 12 ); write64( rp , read64(match) ); write32( rp+8 , read32(match+8) ); rp += ml; continue; } else { if_likely( ml_control < LZB_MLCONTROL_ESCAPE ) // short match { cp += 2; // consume offset const U8 * match = rp - off; RR_ASSERT( off >= 8 || ml <= off ); write64( rp , read64(match) ); write64( rp+8 , read64(match+8) ); if ( ml > 16 ) { write16( rp+16, read16(match+16) ); } } else { // get 1-byte excess code UINTr excesslow = off&127; cp++; // consume 1 //if ( excess1 >= 128 ) if ( off & 128 ) { ml_control = excesslow >> 3; ml = ml_control + LZB_MML; if ( ml_control == 0xF ) { // get more ml LZB_AddExcessML( cp, ml ); } UINTr myoff = off & 7; // low offset, can't do 8-byte grabs if ( myoff == 1 ) { int c = rp[-1]; copy_match_memset(rp,c,ml); } else { // shit but whatever, very rare for(UINTr i=0;i>13); return h; } #define HashMatchFinder_Hash32 hmf_hash4_32 //================================================================================= #define LZB_Hash4 hmf_hash4_32 static RADINLINE U32 LZB_SecondHash4(U32 be4) { const U32 m = 0x5bd1e995; U32 h = be4 * m; h += (h>>11); return h; } //============================================= static int RADFORCEINLINE GetNumBytesZeroNeverAllR(UINTr x) { RR_ASSERT( x != 0 ); #if defined(__RADBIGENDIAN__) // big endian, so earlier bytes are at the top int nb = (int)rrClzBytesR(x); #elif defined(__RADLITTLEENDIAN__) // little endian, so earlier bytes are at the bottom int nb = (int)rrCtzBytesR(x); #else #error wtf no endian set #endif RR_ASSERT( nb >= 0 && nb < (int)sizeof(UINTr) ); return nb; } //=============================== static RADFORCEINLINE U8 * LZB_Output(U8 * cp, S32 lrl, const U8 * literals, S32 matchlen , S32 mo ) { RR_ASSERT( lrl >= 0 ); RR_ASSERT( matchlen >= LZB_MML ); RR_ASSERT( mo > 0 && mo <= LZB_MAX_OFFSET ); //rrprintf("[%3d][%3d][%7d]\n",lrl,ml,mo); S32 sendml = matchlen - LZB_MML; U32 ml_in_control = RR_MIN(sendml,LZB_MLCONTROL_ESCAPE); if ( mo >= 8 ) // no overlap { if ( lrl < LZB_LRL_ESCAPE ) { U32 control = lrl | (ml_in_control<<4); *cp++ = (U8) control; write64(cp, read64(literals)); if ( lrl > 8 ) { write64(cp+8, read64(literals+8)); } cp += lrl; } else { U32 control = LZB_LRL_ESCAPE | (ml_in_control<<4); *cp++ = (U8) control; U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); // @@ ? is this okay for overrun ? lz_copysteptoend_overrunok(cp,literals,lrl); } if ( ml_in_control < LZB_MLCONTROL_ESCAPE ) { RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; } else { U32 ml_excess = sendml - LZB_MLCONTROL_ESCAPE; // put special first byte, then offset, then remainder if ( ml_excess < 127 ) { *cp++ = (U8)ml_excess; RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; } else { *cp++ = (U8)127; RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; ml_excess -= 127; LZB_PutExcessML(cp,ml_excess); } } } else { U32 lrl_in_control = RR_MIN(lrl,LZB_LRL_ESCAPE); // overlap case U32 control = (lrl_in_control) | (LZB_MLCONTROL_ESCAPE<<4); *cp++ = (U8) control; if ( lrl_in_control == LZB_LRL_ESCAPE ) { U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); } lz_copysteptoend_overrunok(cp,literals,lrl); //cp += lrl; // special excess1 : UINTr excess1 = 128 + (ml_in_control<<3) + mo; RR_ASSERT( excess1 < 256 ); *cp++ = (U8)excess1; if ( ml_in_control == LZB_MLCONTROL_ESCAPE ) { U32 ml_excess = sendml - LZB_MLCONTROL_ESCAPE; LZB_PutExcessML(cp,ml_excess); } } return cp; } #if LZB_FORCELASTLRL9 static RADINLINE U8 * LZB_OutputLast(U8 * cp, S32 lrl, const U8 * literals ) { RR_ASSERT( lrl >= 0 ); //U32 ml = 0; //U32 mo = 0; U32 lrl_in_control = RR_MIN(lrl,LZB_LRL_ESCAPE); #if LZB_END_WITH_LITERALS // lrl_in_control must be at least 9 lrl_in_control = RR_MAX(lrl_in_control,9); #endif U32 control = lrl_in_control; *cp++ = (U8) control; if ( lrl_in_control == LZB_LRL_ESCAPE ) { U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); } memmove(cp,literals,lrl); cp += lrl; return cp; } #else static RADINLINE U8 * LZB_OutputLast(U8 * cp, S32 lrl, const U8 * literals ) { cp = LZB_Output(cp,lrl,literals,LZB_MML,1); // remove the offset we put : cp -= 2; return cp; } #endif //=============================================================== static void rr_lzb_simple_context_init(rr_lzb_simple_context * ctx) //, const void * base) { RR_ASSERT( ctx->m_tableSizeBits >= 12 && ctx->m_tableSizeBits <= 24 ); memset(ctx->m_hashTable,0,sizeof(U16)*((SINTa)1<m_tableSizeBits)); } //=============================================================== /* #define FAST_HASH_DEPTH_SHIFT (1) // more depth = more & more compression, #define DO_FAST_2ND_HASH // rate= 30.69 mb/s , 15451369 <- turning this off is the best way to get more speed and less compression /*/ #define FAST_HASH_DEPTH_SHIFT (0) #define DO_FAST_2ND_HASH /**/ // lzt99, 24700820, 15475520, 16677179 //encode only : 0.880 seconds, 1.62 b/hc, rate= 28.08 mb/s //#define FAST_HASH_DEPTH_SHIFT (1) // more depth = more & more compression, but slower #define DO_FAST_UPDATE_MATCH_HASHES 1 // helps compression a lot , like 0.30 //#define DO_FAST_UPDATE_MATCH_HASHES 2 // helps compression a lot , like 0.30 #define DO_FAST_LAZY_MATCH // also helps a lot , like 0.15 #define DO_FAST_HASH_DWORD 1 #define FAST_MULTISTEP_LITERALS_SHIFT (5) //----------------------- // derived : /* #define FAST_HASH_BITS (FAST_HASH_TOTAL_BITS-FAST_HASH_DEPTH_SHIFT) #define FAST_HASH_SIZE (1< 1 #define FAST_HASH_INDEX(h,d) ( ((h)< 1 int hashCycle = 0; #endif U16 * hashTable16 = fh->m_hashTable; int hashTableSizeBits = fh->m_tableSizeBits; U32 hash_table_mask = (U32)((1UL<<(hashTableSizeBits - FAST_HASH_DEPTH_SHIFT)) - 1); const U8 * zeroPosPtr = (const U8 *)raw; // first byte is always a literal rp++; for(;;) { S32 matchOff; UINTr failedMatches = (1<= 0 ); #ifdef DO_FAST_2ND_HASH hash2 = ( LZB_SecondHash4(rp32) ) & hash_table_mask; #endif #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); hashrp = rp - matchOff; //if ( matchOff <= LZB_MAX_OFFSET ) RR_ASSERT( matchOff <= LZB_MAX_OFFSET ); { const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } } } #ifdef DO_FAST_2ND_HASH #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); hashrp = rp - matchOff; RR_ASSERT( matchOff <= LZB_MAX_OFFSET ); { const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } } } #endif //--------------------------- // update hash : hashTable16[ FAST_HASH_INDEX(hash,hashCycle) ] = (U16) curpos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! //hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; hashTable16[ FAST_HASH_INDEX(hash2,hashCycle) ] = (U16) curpos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif UINTr stepLiterals = (failedMatches>>FAST_MULTISTEP_LITERALS_SHIFT); RR_ASSERT( stepLiterals >= 1 ); ++failedMatches; rp += stepLiterals; if ( rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } //------------------------------- found_match: // found something //------------------------- // update hash now so lazy can see it : #if 1 // pretty important to compression hashTable16[ FAST_HASH_INDEX(hash,hashCycle) ] = (U16) curpos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! //hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; hashTable16[ FAST_HASH_INDEX(hash2,hashCycle) ] = (U16) curpos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif #endif //----------------------------------- const U8 * match_start = rp; rp += 4; while( rp < rpEndSafe ) { UINTr big1 = readR(rp); UINTr big2 = readR(rp-matchOff); if ( big1 == big2 ) { rp += RAD_PTRBYTES; continue; } else { rp += GetNumBytesZeroNeverAllR(big1^big2); break; } } rp = RR_MIN(rp,rpMatchEnd); //------------------------------- // rp is now at the *end* of the match //------------------------------- // check lazy match too #ifdef DO_FAST_LAZY_MATCH if (rp< rpEndSafe) { const U8 * lazyrp = match_start + 1; //SINTa lazypos = rrPtrDiff(lazyrp - zeroPosPtr); SINTa lazypos = curpos + 1; RR_ASSERT( lazypos == rrPtrDiff(lazyrp - zeroPosPtr) ); U32 lazyrp32 = read32(lazyrp); const U8 * lazyhashrp; SINTa lazymatchOff; U32 lazyHash = FAST_HASH_FUNC(lazyrp, lazyrp32 ); #ifdef DO_FAST_2ND_HASH U32 lazyhash2 = LZB_SecondHash4(lazyrp32) & hash_table_mask; #endif #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); RR_ASSERT( lazymatchOff <= LZB_MAX_OFFSET ); { lazyhashrp = lazyrp - lazymatchOff; const U32 hashrp32 = read32(lazyhashrp); if ( lazyrp32 == hashrp32 && lazymatchOff != 0 ) { goto lazy_found_match; } } } #ifdef DO_FAST_2ND_HASH #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); RR_ASSERT( lazymatchOff <= LZB_MAX_OFFSET ); { lazyhashrp = lazyrp - lazymatchOff; const U32 hashrp32 = read32(lazyhashrp); if ( lazyrp32 == hashrp32 && lazymatchOff != 0 ) { goto lazy_found_match; } } } #endif if ( 0 ) { lazy_found_match: lazyrp += 4; while( lazyrp < rpEndSafe ) { UINTr big1 = readR(lazyrp); UINTr big2 = readR(lazyrp-lazymatchOff); if ( big1 == big2 ) { lazyrp += RAD_PTRBYTES; continue; } else { lazyrp += GetNumBytesZeroNeverAllR(big1^big2); break; } } lazyrp = RR_MIN(lazyrp,rpMatchEnd); //S32 lazymatchLen = rrPtrDiff32( lazyrp - (match_start+1) ); //RR_ASSERT( lazymatchLen >= 4 ); if ( lazyrp >= rp+3 ) { // yes take the lazy match // put a literal : match_start++; // I had a bug where lazypos was set wrong for the hash fill // it set it to the *end* of the normal match // and for some reason that helped compression WTF WTF //SINTa lazypos = rrPtrDiff(rp - zeroPosPtr); // 233647528 // with correct lazypos : 233651228 // really this shouldn't be necessary at all // because I do an update of hash at all positions in the match including first! #if 1 // with update disabled - 233690274 hashTable16[ FAST_HASH_INDEX(lazyHash,hashCycle) ] = (U16) lazypos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! hashTable16[ FAST_HASH_INDEX(lazyhash2,hashCycle) ] = (U16) lazypos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif #endif // and then drop out and do the lazy match : //matchLen = lazymatchLen; matchOff = (S32)lazymatchOff; rp = lazyrp; hashrp = lazyhashrp; } } } #endif //--------------------------------------------------- // back up start of match that we missed due to stepLiterals ! // make sure we don't read off the start of the array // this costs a little speed and gains a little compression // 15662162 at 121.58 mb/s // 15776473 at 127.92 mb/s #if 1 /* lzbf : 24,700,820 ->15,963,503 = 5.170 bpb = 1.547 to 1 encode : 0.171 seconds, 83.60 b/kc, rate= 144.54 M/s decode : 0.014 seconds, 1002.64 b/kc, rate= 1733.57 M/s */ { // 144 M/s // back up start of match that we missed // make sure we don't read off the start of the array const U8 * rpm1 = match_start-1; if ( rpm1 >= literals_start && hashrp > zeroPosPtr && rpm1[0] == hashrp[-1] ) { rpm1--; hashrp-= 2; while ( rpm1 >= literals_start && hashrp >= zeroPosPtr && rpm1[0] == *hashrp ) { rpm1--; hashrp--; } match_start = rpm1+1; //rp = RR_MAX(rp,literals_start); RR_ASSERT( match_start >= literals_start ); } } #endif S32 matchLen = rrPtrDiff32( rp - match_start ); RR_ASSERT( matchLen >= 4 ); //=============================================== // chose a match // output LRL (if any) and match S32 cur_lrl = rrPtrDiff32(match_start - literals_start); // catch expansion while writing : if_unlikely ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_Output(cp,cur_lrl,literals_start,matchLen,matchOff); // skip the match : literals_start = rp; if ( rp >= rpEndSafe ) break; // step & update hashes : // (I already did cur pos) #ifdef DO_FAST_UPDATE_MATCH_HASHES // don't bother if it takes us to the end : // (this check is not for speed it's to avoid the access violation) const U8 * ptr = match_start+1; U16 pos16 = (U16) rrPtrDiff( ptr - zeroPosPtr ); for(;ptr 0 ); #endif if ( cur_lrl > 0 ) { // catch expansion while writing : if ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_OutputLast(cp,cur_lrl,literals_start); } SINTa compLen = rrPtrDiff( cp - (U8 *)comp ); return compLen; } SINTa rr_lzb_simple_encode_fast(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { rr_lzb_simple_context_init(fh); //,raw); SINTa comp_len = rr_lzb_simple_encode_fast_sub(fh,raw,rawLen,comp); if ( comp_len >= rawLen ) { memcpy(comp,raw,rawLen); return rawLen; } return comp_len; } #undef FAST_HASH_DEPTH_SHIFT #undef DO_FAST_UPDATE_MATCH_HASHES #undef DO_FAST_LAZY_MATCH #undef DO_FAST_2ND_HASH //===================================================== #define FAST_HASH_DEPTH_SHIFT (0) #undef FAST_MULTISTEP_LITERALS_SHIFT #define FAST_MULTISTEP_LITERALS_SHIFT (4) //----------------------- // derived : RR_COMPILER_ASSERT( FAST_HASH_DEPTH_SHIFT == 0 ); #undef FAST_HASH_FUNC //#define FAST_HASH_FUNC(ptr,dword) ( LZB_Hash4(dword) & hash_table_mask ) #define FAST_HASH_FUNC(ptr,dword) ( (((dword)*2654435761U)>>16) & hash_table_mask ) // @@@@ ???? #define LZBVF_DO_BACKUP 0 //#define LZBVF_DO_BACKUP 1 static SINTa rr_lzb_simple_encode_veryfast_sub(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { //SIMPLEPROFILE_SCOPE_N(lzbfast_sub,rawLen); //THREADPROFILEFUNC(); U8 * cp = (U8 *)comp; U8 * compExpandedPtr = cp + rawLen - 8; const U8 * rp = (const U8 *)raw; const U8 * rpEnd = rp+rawLen; // we can match up to rpEnd // but matches can't start past rpEndSafe const U8 * rpMatchEnd = rpEnd - LZB_END_OF_BLOCK_NO_MATCH_ZONE; const U8 * rpEndSafe = rpMatchEnd - LZB_MML; if ( rpEndSafe <= (U8 *)raw ) { // can't compress return rawLen+1; } const U8 * literals_start = rp; U16 * hashTable16 = fh->m_hashTable; int hashTableSizeBits = fh->m_tableSizeBits; U32 hash_table_mask = (U32)((1UL<<(hashTableSizeBits)) - 1); const U8 * zeroPosPtr = (const U8 *)raw; // first byte is always a literal rp++; for(;;) { U32 rp32 = read32(rp); U32 hash = FAST_HASH_FUNC(rp, rp32 ); const U8 * hashrp; S32 matchOff; UINTr failedMatches; // loop while no match found : // first loop with step = 1 // @@ //int step1count = (1<= 0 ); U16 hashpos16 = hashTable16[hash]; hashTable16[ hash ] = (U16) curpos; matchOff = (U16)(curpos - hashpos16); RR_ASSERT( matchOff >= 0 && matchOff <= LZB_MAX_OFFSET ); hashrp = rp - matchOff; const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } if ( ++rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } // step starts at 2 : failedMatches = (2<= 0 ); U16 hashpos16 = hashTable16[hash]; hashTable16[ hash ] = (U16) curpos; matchOff = (U16)(curpos - hashpos16); RR_ASSERT( matchOff >= 0 && matchOff <= LZB_MAX_OFFSET ); hashrp = rp - matchOff; const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } UINTr stepLiterals = (failedMatches>>FAST_MULTISTEP_LITERALS_SHIFT); RR_ASSERT( stepLiterals >= 1 ); ++failedMatches; rp += stepLiterals; if ( rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } //------------------------------- found_match:; // found something #if LZBVF_DO_BACKUP // alternative backup using counter : S32 cur_lrl = rrPtrDiff32(rp - literals_start); int neg_max_backup = - RR_MIN(cur_lrl , rrPtrDiff32(hashrp - zeroPosPtr) ); int neg_backup = -1; if( neg_backup >= neg_max_backup && rp[neg_backup] == hashrp[neg_backup] ) { neg_backup--; while( neg_backup >= neg_max_backup && rp[neg_backup] == hashrp[neg_backup] ) { neg_backup--; } neg_backup++; rp += neg_backup; cur_lrl += neg_backup; RR_ASSERT( cur_lrl >= 0 ); RR_ASSERT( cur_lrl == rrPtrDiff32(rp - literals_start) ); } #else S32 cur_lrl = rrPtrDiff32(rp - literals_start); #endif // catch expansion while writing : if_unlikely ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } RR_ASSERT( matchOff >= 1 ); //--------------------------------------- // find rest of match len // save pointer to start of match // walk rp ahead to end of match const U8 * match_start = rp; rp += 4; while( rp < rpEndSafe ) { UINTr big1 = readR(rp); UINTr big2 = readR(rp-matchOff); if ( big1 == big2 ) { rp += RAD_PTRBYTES; continue; } else { rp += GetNumBytesZeroNeverAllR(big1^big2); break; } } rp = RR_MIN(rp,rpMatchEnd); S32 matchLen = rrPtrDiff32( rp - match_start ); //=============================================== // chose a match // output LRL (if any) and match cp = LZB_Output(cp,cur_lrl,literals_start,matchLen,matchOff); // skip the match : literals_start = rp; if ( rp >= rpEndSafe ) goto done; } done:; int cur_lrl = rrPtrDiff32(rpEnd - literals_start); #if LZB_END_WITH_LITERALS RR_ASSERT_ALWAYS(cur_lrl > 0 ); #endif if ( cur_lrl > 0 ) { // catch expansion while writing : if ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_OutputLast(cp,cur_lrl,literals_start); } SINTa compLen = rrPtrDiff( cp - (U8 *)comp ); return compLen; } SINTa rr_lzb_simple_encode_veryfast(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { rr_lzb_simple_context_init(fh); //,raw); SINTa comp_len = rr_lzb_simple_encode_veryfast_sub(fh,raw,rawLen,comp); if ( comp_len >= rawLen ) { memcpy(comp,raw,rawLen); return rawLen; } return comp_len; } #undef FAST_HASH_DEPTH_SHIFT #undef DO_FAST_UPDATE_MATCH_HASHES #undef DO_FAST_LAZY_MATCH #undef DO_FAST_2ND_HASH //===================================================== // vim:noet:sw=4:ts=4 ================================================ FILE: src/lib_rdi/rdi_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// //~ (R)AD (D)ebug (I)nfo Format Parsing Library // // Defines helper types and functions for extracting data from // RDI files. //////////////////////////////////////////////////////////////// //~ Usage Samples // #if 0 // Procedure Name -> Line { RDI_Parsed *rdi = ...; char *name = "mule_main"; RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file RDI_U64 file_path_size = 0; // 5. source file -> path RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size); printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num); } // Line -> Procedure Name { RDI_Parsed *rdi = ...; char *path = "c:/devel/raddebugger/src/mule/mule_main.cpp"; RDI_U32 line_num = 2557; RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure RDI_U64 name_size = 0; // 4. procedure -> name RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size); printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name); } #endif #ifndef RDI_PARSE_H #define RDI_PARSE_H //////////////////////////////////////////////////////////////// //~ Parsed Information Types typedef enum RDI_ParseStatus { RDI_ParseStatus_Good = 0, RDI_ParseStatus_HeaderDoesNotMatch = 1, RDI_ParseStatus_UnsupportedVersionNumber = 2, RDI_ParseStatus_InvalidDataSecionLayout = 3, } RDI_ParseStatus; typedef struct RDI_Parsed RDI_Parsed; struct RDI_Parsed { RDI_U8 *raw_data; RDI_U64 raw_data_size; RDI_Section *sections; RDI_U64 sections_count; }; typedef struct RDI_ParsedLineTable RDI_ParsedLineTable; struct RDI_ParsedLineTable { // NOTE: Mapping VOFF -> LINE_INFO // // * [ voff[i], voff[i + 1] ) forms the voff range // * for the line info at lines[i] (and cols[i] if i < col_count) RDI_U64* voffs; // [count + 1] sorted RDI_Line* lines; // [count] RDI_Column* cols; // [col_count] RDI_U64 count; RDI_U64 col_count; }; typedef struct RDI_ParsedSourceLineMap RDI_ParsedSourceLineMap; struct RDI_ParsedSourceLineMap { // NOTE: Mapping LINE_NUMBER -> VOFFs // // * nums[i] gives a line number // * that line number has one or more associated voffs // // * to find all associated voffs for the line number nums[i] : // * let k span over the range [ ranges[i], ranges[i + 1] ) // * voffs[k] gives the associated voffs RDI_U32* nums; // [count] sorted RDI_U32* ranges; // [count + 1] RDI_U64* voffs; // [voff_count] RDI_U64 count; RDI_U64 voff_count; }; typedef struct RDI_ParsedNameMap RDI_ParsedNameMap; struct RDI_ParsedNameMap { RDI_NameMapBucket *buckets; RDI_NameMapNode *nodes; RDI_U64 bucket_count; RDI_U64 node_count; }; //////////////////////////////// //~ Global Nils static union { RDI_TopLevelInfo top_level_info; RDI_BinarySection binary_section; RDI_FilePathNode file_path_node; RDI_SourceFile source_file; RDI_LineTable line_table; RDI_SourceLineMap source_line_map; RDI_Line line; RDI_Column column; RDI_Unit unit; RDI_VMapEntry vmap_entry; RDI_TypeNode type_node; RDI_UDT udt; RDI_Member member; RDI_EnumMember enum_member; RDI_GlobalVariable global_variable; RDI_ThreadVariable thread_variable; RDI_Procedure procedure; RDI_Scope scope; RDI_U64 voff; RDI_LocationBlock location_block; RDI_Local local; } rdi_nil_element_union = {0}; static RDI_Parsed rdi_parsed_nil = {0}; //////////////////////////////// //~ Top-Level Parsing API RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); //////////////////////////////// //~ Base Parsed Info Extraction Helpers //- section table/element raw data extraction RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out); RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out); RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx); #define rdi_table_from_name(rdi, name, count_out) ((RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out))) #define rdi_element_from_name_idx(rdi, name, idx) ((RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx))) //- info about whole parse RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); //- decompression internal void rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed *og_rdi); //- strings RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out); //- index runs RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out); //- line info RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out); RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out); RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); //- vmap lookups RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff); //- name maps RDI_PROC RDI_NameMap *rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind); RDI_PROC void rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out); RDI_PROC RDI_NameMapNode *rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len); RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out); //////////////////////////////// //~ High-Level Composite Lookup Functions //- procedures RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr); RDI_PROC RDI_U8 *rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out); RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_UDT *rdi_container_udt_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_Procedure *rdi_container_procedure_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_Procedure *rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff); //- scopes RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); RDI_PROC RDI_Scope *rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_Scope *rdi_parent_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); RDI_PROC RDI_Procedure *rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); RDI_PROC RDI_InlineSite *rdi_inline_site_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); //- global variables RDI_PROC RDI_GlobalVariable *rdi_global_variable_from_voff(RDI_Parsed *rdi, RDI_U64 voff); //- units RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); //- line tables RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); //- source files RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr); RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out); RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); RDI_PROC RDI_SourceLineMap *rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num); //- source line maps RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num); //- file path nodes RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node); RDI_PROC RDI_U8 *rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out); //////////////////////////////// //~ Parser Helpers #define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) RDI_PROC RDI_U64 rdi_cstring_length(char *cstr); RDI_PROC RDI_U64 rdi_size_from_bytecode_stream(RDI_U8 *ptr, RDI_U8 *opl); #endif // RDI_FORMAT_PARSE_H ================================================ FILE: src/lib_rdi_make/rdi_make.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: API Implementation Helper Macros #define RDIM_IdxedChunkListPush(arena, list, chunk_type, element_type, cap_value, result, ...) \ element_type *result = 0;\ do\ {\ chunk_type *n = list->last;\ if(n == 0 || n->count >= n->cap)\ {\ n = rdim_push_array(arena, chunk_type, 1);\ n->cap = cap_value;\ n->base_idx = list->total_count;\ __VA_ARGS__;\ n->v = rdim_push_array_no_zero(arena, element_type, n->cap);\ RDIM_SLLQueuePush(list->first, list->last, n);\ list->chunk_count += 1;\ }\ result = &n->v[n->count];\ result->chunk = n;\ n->count += 1;\ list->total_count += 1;\ }while(0) #define RDIM_IdxedChunkListElementGetIdx(ptr, result) \ RDI_U64 idx = 0;\ if(ptr != 0 && ptr->chunk != 0)\ {\ idx = ptr->chunk->base_idx + (ptr - ptr->chunk->v) + 1;\ } #define RDIM_IdxedChunkListConcatInPlace(chunk_type, dst, to_push, ...) \ for(chunk_type *n = to_push->first; n != 0; n = n->next)\ {\ n->base_idx += dst->total_count;\ }\ if(dst->last != 0 && to_push->first != 0)\ {\ dst->last->next = to_push->first;\ dst->last = to_push->last;\ dst->chunk_count += to_push->chunk_count;\ dst->total_count += to_push->total_count;\ __VA_ARGS__;\ }\ else if(dst->first == 0)\ {\ rdim_memcpy_struct(dst, to_push);\ }\ rdim_memzero_struct(to_push); //////////////////////////////// //~ rjf: Basic Helpers //- rjf: memory set #if !defined(RDIM_MEMSET_OVERRIDE) RDI_PROC void * rdim_memset_fallback(void *dst, RDI_U8 c, RDI_U64 size) { for(RDI_U64 idx = 0; idx < size; idx += 1) { ((RDI_U8 *)dst)[idx] = c; } return dst; } #endif #if !defined(RDIM_MEMCPY_OVERRIDE) RDI_PROC void * rdim_memcpy_fallback(void *dst, void *src, RDI_U64 size) { for(RDI_U64 idx = 0; idx < size; idx += 1) { ((RDI_U8 *)dst)[idx] = ((RDI_U8 *)src)[idx]; } return dst; } #endif //- rjf: arenas #if !defined (RDIM_ARENA_OVERRIDE) RDI_PROC RDIM_Arena * rdim_arena_alloc_fallback(void) { RDIM_Arena *arena = 0; // TODO(rjf) return arena; } RDI_PROC void rdim_arena_release_fallback(RDIM_Arena *arena) { // TODO(rjf) } RDI_PROC RDI_U64 rdim_arena_pos_fallback(RDIM_Arena *arena) { // TODO(rjf) return 0; } RDI_PROC void * rdim_arena_push_fallback(RDIM_Arena *arena, RDI_U64 size, RDI_U64 align, RDI_U32 zero) { // TODO(rjf) return 0; } RDI_PROC void rdim_arena_pop_to_fallback(RDIM_Arena *arena, RDI_U64 pos) { // TODO(rjf) } #endif //- rjf: thread-local scratch arenas #if !defined (RDIM_SCRATCH_OVERRIDE) static RDIM_THREAD_LOCAL RDIM_Arena *rdim_thread_scratches[2]; RDI_PROC RDIM_Temp rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count) { if(rdim_thread_scratches[0] == 0) { rdim_thread_scratches[0] = rdim_arena_alloc(); rdim_thread_scratches[1] = rdim_arena_alloc(); } RDIM_Arena *arena = 0; for(RDI_U64 scratch_idx = 0; scratch_idx < sizeof(rdim_thread_scratches)/sizeof(rdim_thread_scratches[0]); scratch_idx += 1) { RDI_S32 scratch_conflicts = 0; for(RDI_U64 conflict_idx = 0; conflict_idx < conflicts_count; conflict_idx += 1) { if(conflicts[conflict_idx] == rdim_thread_scratches[scratch_idx]) { scratch_conflicts = 1; break; } } if(!scratch_conflicts) { arena = rdim_thread_scratches[scratch_idx]; } } RDIM_Temp temp; temp.arena = arena; temp.pos = rdim_arena_pos(arena); return temp; } RDI_PROC void rdim_scratch_end_fallback(RDIM_Temp temp) { rdim_arena_pop_to(temp.arena, temp.pos); } #endif //- rjf: strings RDI_PROC RDIM_String8 rdim_str8(RDI_U8 *str, RDI_U64 size) { RDIM_String8 result; result.RDIM_String8_BaseMember = str; result.RDIM_String8_SizeMember = size; return result; } RDI_PROC RDIM_String8 rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src) { RDIM_String8 dst; dst.RDIM_String8_SizeMember = src.RDIM_String8_SizeMember; dst.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, dst.RDIM_String8_SizeMember+1); rdim_memcpy(dst.RDIM_String8_BaseMember, src.RDIM_String8_BaseMember, src.RDIM_String8_SizeMember); dst.RDIM_String8_BaseMember[dst.RDIM_String8_SizeMember] = 0; return dst; } RDI_PROC RDIM_String8 rdim_str8f(RDIM_Arena *arena, char *fmt, ...) { va_list args; va_start(args, fmt); RDIM_String8 result = rdim_str8fv(arena, fmt, args); va_end(args); return(result); } RDI_PROC RDIM_String8 rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args) { va_list args2; va_copy(args2, args); RDI_U32 needed_bytes = rdim_vsnprintf(0, 0, fmt, args) + 1; RDIM_String8 result = {0}; result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, needed_bytes); result.RDIM_String8_SizeMember = rdim_vsnprintf((char*)result.str, needed_bytes, fmt, args2); result.RDIM_String8_BaseMember[result.RDIM_String8_SizeMember] = 0; va_end(args2); return(result); } RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags) { RDI_S32 result = 0; if(a.RDIM_String8_SizeMember == b.RDIM_String8_SizeMember) { RDI_S32 case_insensitive = (flags & RDIM_StringMatchFlag_CaseInsensitive); RDI_U64 size = a.RDIM_String8_SizeMember; result = 1; for(RDI_U64 idx = 0; idx < size; idx += 1) { RDI_U8 at = a.RDIM_String8_BaseMember[idx]; RDI_U8 bt = b.RDIM_String8_BaseMember[idx]; if(case_insensitive) { at = ('a' <= at && at <= 'z') ? at-('a'-'A') : at; bt = ('a' <= bt && bt <= 'z') ? bt-('a'-'A') : bt; } if(at != bt) { result = 0; break; } } } return result; } RDI_PROC RDIM_String8 rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string) { RDIM_String8 result = rdim_str8_copy(arena, string); for(RDI_U64 idx = 0; idx < result.RDIM_String8_SizeMember; idx += 1) { RDI_U8 byte = result.RDIM_String8_BaseMember[idx]; if('A' <= byte && byte <= 'Z') { result.RDIM_String8_BaseMember[idx] += ('a' - 'A'); } } return result; } //- rjf: string lists RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) { RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); n->RDIM_String8Node_StringMember = string; RDIM_SLLQueuePush_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); list->RDIM_String8List_NodeCountMember += 1; list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; } RDI_PROC void rdim_str8_list_push_front(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string) { RDIM_String8Node *n = rdim_push_array(arena, RDIM_String8Node, 1); n->RDIM_String8Node_StringMember = string; RDIM_SLLQueuePushFront_N(list->RDIM_String8List_FirstMember, list->RDIM_String8List_LastMember, n, RDIM_String8Node_NextPtrMember); list->RDIM_String8List_NodeCountMember += 1; list->RDIM_String8List_TotalSizeMember += string.RDIM_String8_SizeMember; } RDI_PROC void rdim_str8_list_push_align(RDIM_Arena *arena, RDIM_String8List *list, RDI_U64 align) { RDI_U64 total_size_pre_align = list->total_size; RDI_U64 total_size_post_align = (total_size_pre_align + (align-1))&(~(align-1)); RDI_U64 needed_size = total_size_post_align - total_size_pre_align; if(needed_size != 0) { RDI_U8 *padding = rdim_push_array(arena, RDI_U8, needed_size); rdim_str8_list_push(arena, list, rdim_str8(padding, needed_size)); } } RDI_PROC RDIM_String8 rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep) { RDIM_String8 result; rdim_memzero_struct(&result); RDI_U64 sep_count = (list->RDIM_String8List_NodeCountMember > 1) ? (list->RDIM_String8List_NodeCountMember-1) : 0; result.RDIM_String8_SizeMember = list->RDIM_String8List_TotalSizeMember+sep_count*sep.RDIM_String8_SizeMember; result.RDIM_String8_BaseMember = rdim_push_array_no_zero(arena, RDI_U8, result.RDIM_String8_SizeMember+1); RDI_U64 off = 0; for(RDIM_String8Node *node = list->RDIM_String8List_FirstMember; node != 0; node = node->RDIM_String8Node_NextPtrMember) { rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, node->RDIM_String8Node_StringMember.RDIM_String8_BaseMember, node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember); off += node->RDIM_String8Node_StringMember.RDIM_String8_SizeMember; if(sep.RDIM_String8_SizeMember != 0 && node->RDIM_String8Node_NextPtrMember != 0) { rdim_memcpy((RDI_U8*)result.RDIM_String8_BaseMember+off, sep.RDIM_String8_BaseMember, sep.RDIM_String8_SizeMember); off += sep.RDIM_String8_SizeMember; } } result.RDIM_String8_BaseMember[off] = 0; return result; } //- rjf: sortable range sorting RDI_PROC RSFORCEINLINE int rdim_sort_key_is_before(void *l, void *r) { return ((RDIM_SortKey *)l)->key < ((RDIM_SortKey *)r)->key; } RDI_PROC RDIM_SortKey * rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) { // This sort is designed to take advantage of lots of pre-existing sorted ranges. // Most line info is already sorted or close to already sorted. // Similarly most vmap data has lots of pre-sorted ranges. etc. etc. // Also - this sort should be a "stable" sort. In the use case of sorting vmap // ranges, we want to be able to rely on order, so it needs to be preserved here. RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); RDIM_SortKey *result = 0; if(count <= 1) { result = keys; } else { RDIM_OrderedRange *ranges_first = 0; RDIM_OrderedRange *ranges_last = 0; RDI_U64 range_count = 0; { RDI_U64 pos = 0; for(;pos < count;) { // identify ordered range RDI_U64 first = pos; RDI_U64 opl = pos + 1; for(; opl < count && keys[opl - 1].key <= keys[opl].key; opl += 1); // generate an ordered range node RDIM_OrderedRange *new_range = rdim_push_array(rdim_temp_arena(scratch), RDIM_OrderedRange, 1); RDIM_SLLQueuePush(ranges_first, ranges_last, new_range); range_count += 1; new_range->first = first; new_range->opl = opl; // update pos pos = opl; } } if(range_count == 1) { result = keys; } else { RDIM_SortKey *keys_swap = rdim_push_array_no_zero(arena, RDIM_SortKey, count); RDIM_SortKey *src = keys; RDIM_SortKey *dst = keys_swap; RDIM_OrderedRange *src_ranges = ranges_first; RDIM_OrderedRange *dst_ranges = 0; RDIM_OrderedRange *dst_ranges_last = 0; for(;;) { // begin a pass for(;;) { // end pass when out of ranges if(src_ranges == 0) { break; } // get first range RDIM_OrderedRange *range1 = src_ranges; RDIM_SLLStackPop(src_ranges); // if this range is the whole array, we are done if(range1->first == 0 && range1->opl == count) { result = src; goto sort_done; } // if there is not a second range, save this range for next time and end this pass if(src_ranges == 0) { RDI_U64 first = range1->first; rdim_memcpy(dst + first, src + first, sizeof(*src)*(range1->opl - first)); RDIM_SLLQueuePush(dst_ranges, dst_ranges_last, range1); break; } // get second range RDIM_OrderedRange *range2 = src_ranges; RDIM_SLLStackPop(src_ranges); #if 0 rdim_assert(range1->opl == range2->first); #endif // merge these ranges RDI_U64 jd = range1->first; RDI_U64 j1 = range1->first; RDI_U64 j1_opl = range1->opl; RDI_U64 j2 = range2->first; RDI_U64 j2_opl = range2->opl; for(;;) { if(src[j1].key <= src[j2].key) { rdim_memcpy(dst + jd, src + j1, sizeof(*src)); j1 += 1; jd += 1; if(j1 >= j1_opl) { break; } } else { rdim_memcpy(dst + jd, src + j2, sizeof(*src)); j2 += 1; jd += 1; if(j2 >= j2_opl) { break; } } } if(j1 < j1_opl) { rdim_memcpy(dst + jd, src + j1, sizeof(*src)*(j1_opl - j1)); } else { rdim_memcpy(dst + jd, src + j2, sizeof(*src)*(j2_opl - j2)); } // save this as one range range1->opl = range2->opl; SLLQueuePush(dst_ranges, dst_ranges_last, range1); } // end pass by swapping buffers and range nodes { RDIM_SortKey *temp = src; src = dst; dst = temp; } src_ranges = dst_ranges; dst_ranges = 0; dst_ranges_last = 0; } } } sort_done:; #if 0 // assert sortedness for(RDI_U64 i = 1; i < count; i += 1) { rdim_assert(result[i - 1].key <= result[i].key); } #endif rdim_scratch_end(scratch); return result; } //- rjf: rng1u64 list RDI_PROC void rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r) { RDIM_Rng1U64Node *n = rdim_push_array(arena, RDIM_Rng1U64Node, 1); n->v = r; RDIM_SLLQueuePush(list->first, list->last, n); list->count += 1; if(list->count == 1 || r.min < list->min) { list->min = r.min; } } RDI_PROC void rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkList *list, RDI_U64 chunk_cap, RDIM_Rng1U64 r) { RDIM_Rng1U64ChunkNode *n = list->last; if(n == 0 || n->count >= n->cap) { n = rdim_push_array(arena, RDIM_Rng1U64ChunkNode, 1); RDIM_SLLQueuePush(list->first, list->last, n); n->cap = chunk_cap; n->v = rdim_push_array_no_zero(arena, RDIM_Rng1U64, n->cap); list->chunk_count += 1; } n->v[n->count] = r; n->count += 1; list->total_count += 1; if(list->total_count == 1 || r.min < list->min) { list->min = r.min; } } //////////////////////////////// //~ rjf: [Building] Data Model RDI_PROC RDI_TypeKind rdim_short_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_S16;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_S16;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_S16;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_S16;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_S64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_unsigned_short_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_U16;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_U16;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_U16;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_U16;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_U64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_int_type_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_S32;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_S32;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_S32;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_S64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_U64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_long_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_S32;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_S32;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_S64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_unsigned_long_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_U64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_long_long_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_S64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_S64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_unsigned_long_long_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_U64;}break; } return result; } RDI_PROC RDI_TypeKind rdim_pointer_size_t_type_kind_from_data_model(RDIM_DataModel data_model) { RDI_TypeKind result = RDI_TypeKind_NULL; switch((RDIM_DataModelEnum)data_model) { case RDIM_DataModel_Null:{}break; case RDIM_DataModel_ILP32 :{result = RDI_TypeKind_U32;}break; case RDIM_DataModel_LLP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_LP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_ILP64 :{result = RDI_TypeKind_U64;}break; case RDIM_DataModel_SILP64:{result = RDI_TypeKind_U64;}break; } return result; } //////////////////////////////// //~ rjf: [Building] Binary Section List Building RDI_PROC RDIM_BinarySection * rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list) { RDIM_BinarySectionNode *n = rdim_push_array(arena, RDIM_BinarySectionNode, 1); RDIM_SLLQueuePush(list->first, list->last, n); list->count += 1; RDIM_BinarySection *result = &n->v; return result; } //////////////////////////////// //~ rjf: [Building] Source File Info Building RDI_PROC RDIM_SrcFile * rdim_src_file_chunk_list_push(RDIM_Arena *arena, RDIM_SrcFileChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_SrcFileChunkNode, RDIM_SrcFile, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_src_file(RDIM_SrcFile *src_file) { RDIM_IdxedChunkListElementGetIdx(src_file, idx); return idx; } RDI_PROC void rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFileChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_SrcFileChunkNode, dst, to_push, dst->source_line_map_count += to_push->source_line_map_count, dst->total_line_count += to_push->total_line_count); } RDI_PROC void rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq) { if(src_file->first_line_map_fragment == 0) { src_files->source_line_map_count += 1; } RDIM_SrcFileLineMapFragment *fragment = rdim_push_array(arena, RDIM_SrcFileLineMapFragment, 1); fragment->seq = seq; RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); src_file->total_line_count += seq->line_count; src_files->total_line_count += seq->line_count; } //////////////////////////////// //~ rjf: [Building] Line Info Building RDI_PROC RDIM_LineTable * rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_LineTableChunkNode, RDIM_LineTable, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_line_table(RDIM_LineTable *line_table) { RDIM_IdxedChunkListElementGetIdx(line_table, idx); return idx; } RDI_PROC void rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_LineTableChunkNode, dst, to_push, dst->total_seq_count += to_push->total_seq_count, dst->total_line_count += to_push->total_line_count, dst->total_col_count += to_push->total_col_count); } RDI_PROC RDIM_LineSequence * rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count) { RDIM_LineSequenceNode *n = push_array(arena, RDIM_LineSequenceNode, 1); n->v.src_file = src_file; n->v.voffs = voffs; n->v.line_nums = line_nums; n->v.col_nums = col_nums; n->v.line_count = line_count; SLLQueuePush(line_table->first_seq, line_table->last_seq, n); line_table->seq_count += 1; line_table->line_count += line_count; line_table->col_count += line_count*2*(col_nums != 0); line_tables->total_seq_count += 1; line_tables->total_line_count += line_count; line_tables->total_col_count += line_count*2*(col_nums != 0); return &n->v; } //////////////////////////////// //~ rjf: [Building] Unit List Building RDI_PROC RDIM_Unit * rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_UnitChunkNode, RDIM_Unit, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_unit(RDIM_Unit *unit) { RDIM_IdxedChunkListElementGetIdx(unit, idx); return idx; } RDI_PROC void rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_UnitChunkNode, dst, to_push); } //////////////////////////////// //~ rjf: [Building] Type Info Building //- rjf: type nodes RDI_PROC RDIM_Type ** rdim_array_from_type_list(RDIM_Arena *arena, RDIM_TypeList list) { RDIM_Type **arr = push_array(arena, RDIM_Type *, list.count); U64 i = 0; for(RDIM_TypeNode *n = list.first; n != 0; n = n->next, ++i) { arr[i] = n->v; } return arr; } RDI_PROC RDIM_TypeNode * rdim_type_list_push(RDIM_Arena *arena, RDIM_TypeList *list, RDIM_Type *v) { RDIM_TypeNode *n = push_array(arena, RDIM_TypeNode, 1); n->v = v; SLLQueuePush(list->first, list->last, n); list->count += 1; return n; } RDI_PROC RDIM_Type * rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_TypeChunkNode, RDIM_Type, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_type(RDIM_Type *type) { RDIM_IdxedChunkListElementGetIdx(type, idx); return idx; } RDI_PROC void rdim_type_chunk_list_concat_in_place(RDIM_TypeChunkList *dst, RDIM_TypeChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_TypeChunkNode, dst, to_push); } //- rjf: UDTs RDI_PROC RDIM_UDT * rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_UDTChunkNode, RDIM_UDT, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_udt(RDIM_UDT *udt) { RDIM_IdxedChunkListElementGetIdx(udt, idx); return idx; } RDI_PROC void rdim_udt_chunk_list_concat_in_place(RDIM_UDTChunkList *dst, RDIM_UDTChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_UDTChunkNode, dst, to_push, dst->total_member_count += to_push->total_member_count, dst->total_enum_val_count += to_push->total_enum_val_count); } RDI_PROC RDIM_UDTMember * rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) { RDIM_UDTMember *mem = rdim_push_array(arena, RDIM_UDTMember, 1); RDIM_SLLQueuePush(udt->first_member, udt->last_member, mem); udt->member_count += 1; list->total_member_count += 1; return mem; } RDI_PROC RDIM_UDTEnumVal * rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt) { RDIM_UDTEnumVal *mem = rdim_push_array(arena, RDIM_UDTEnumVal, 1); RDIM_SLLQueuePush(udt->first_enum_val, udt->last_enum_val, mem); udt->enum_val_count += 1; list->total_enum_val_count += 1; return mem; } //////////////////////////////// //~ rjf: [Building] Symbol Info Building RDI_PROC RDIM_Symbol * rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_SymbolChunkNode, RDIM_Symbol, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_symbol(RDIM_Symbol *symbol) { RDIM_IdxedChunkListElementGetIdx(symbol, idx); return idx; } RDI_PROC void rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_SymbolChunkNode, dst, to_push, dst->total_value_data_size += to_push->total_value_data_size); } internal void rdim_symbol_push_value_data(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDIM_Symbol *symbol, RDIM_String8 data) { symbol->value_data = rdim_str8_copy(arena, data); list->total_value_data_size += data.size; } //////////////////////////////// //~ rjf: [Building] Inline Site Info Building RDI_PROC RDIM_InlineSite * rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_InlineSiteChunkNode, RDIM_InlineSite, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_inline_site(RDIM_InlineSite *inline_site) { RDIM_IdxedChunkListElementGetIdx(inline_site, idx); return idx; } RDI_PROC void rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_InlineSiteChunkNode, dst, to_push); } //////////////////////////////// //~ rjf: [Building] Location Info Building //- rjf: bytecode RDI_PROC RDIM_EvalBytecodeOp * rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) { RDI_U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); RDIM_EvalBytecodeOp *node = rdim_push_array(arena, RDIM_EvalBytecodeOp, 1); node->op = op; node->p_size = p_size; node->p = p; RDIM_SLLQueuePush(bytecode->first_op, bytecode->last_op, node); bytecode->op_count += 1; bytecode->encoded_size += 1 + p_size; return node; } RDI_PROC void rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x) { if(x <= 0xFF) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, x); } else if(x <= 0xFFFF) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, x); } else if(x <= 0xFFFFFFFF) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, x); } else { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, x); } } RDI_PROC void rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x) { if(-0x80 <= x && x <= 0x7F) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)x); rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); } else if(-0x8000 <= x && x <= 0x7FFF) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)x); rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); } else if(-0x80000000ll <= x && x <= 0x7FFFFFFFll) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)x); rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 32); } else { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)x); } } RDI_PROC void rdim_bytecode_push_convert(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalTypeGroup in, RDI_EvalTypeGroup out) { rdim_bytecode_push_op(arena, bytecode, RDI_EvalOp_Convert, (U16)(in) | ((U16)(out) << 8)); } RDI_PROC void rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed) { if(right_destroyed->first_op != 0) { if(left_dst->first_op == 0) { rdim_memcpy_struct(left_dst, right_destroyed); } else { left_dst->last_op->next = right_destroyed->first_op; left_dst->last_op = right_destroyed->last_op; left_dst->op_count += right_destroyed->op_count; left_dst->encoded_size += right_destroyed->encoded_size; } rdim_memzero_struct(right_destroyed); } } RDI_PROC B32 rdim_is_bytecode_tls_dependent(RDIM_EvalBytecode bytecode) { B32 result = 0; for(RDIM_EvalBytecodeOp *n = bytecode.first_op; n != 0; n = n->next) { if(n->op == RDI_EvalOp_TLSOff) { result = 1; break; } } return result; } //- rjf: locations RDI_PROC RDI_U64 rdim_encoded_size_from_location_info(RDIM_LocationInfo *info) { RDI_U64 result = 0; switch((RDI_LocationKindEnum)info->kind) { case RDI_LocationKind_NULL:{}break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { result = sizeof(RDI_LocationBytecodeStream) + info->bytecode.encoded_size + 1; }break; case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { result = sizeof(RDI_LocationRegPlusU16); }break; case RDI_LocationKind_ValReg: { result = sizeof(RDI_LocationReg); }break; } return result; } RDI_PROC RDIM_Location * rdim_location_chunk_list_push_new(RDIM_Arena *arena, RDIM_LocationChunkList *list, RDI_U64 cap, RDIM_LocationInfo *info) { RDIM_IdxedChunkListPush(arena, list, RDIM_LocationChunkNode, RDIM_Location, cap, result, n->base_encoding_off = list->total_encoded_size); { RDI_U64 encoded_size = rdim_encoded_size_from_location_info(info); rdim_memcpy_struct(&result->info, info); result->relative_encoding_off = list->last->encoded_size; list->last->encoded_size += encoded_size; list->total_encoded_size += encoded_size; } return result; } RDI_PROC RDI_U64 rdim_off_from_location(RDIM_Location *location) { RDI_U64 off = 0; if(location != 0 && location->chunk != 0) { off = location->chunk->base_encoding_off + location->relative_encoding_off + 1; } return off; } RDI_PROC void rdim_location_chunk_list_concat_in_place(RDIM_LocationChunkList *dst, RDIM_LocationChunkList *to_push) { for(RDIM_LocationChunkNode *n = to_push->first; n != 0; n = n->next) { n->base_encoding_off += dst->total_encoded_size; } RDIM_IdxedChunkListConcatInPlace(RDIM_LocationChunkNode, dst, to_push, dst->total_encoded_size += to_push->total_encoded_size); } //////////////////////////////// //~ rjf: [Building] Scope Info Building RDI_PROC RDIM_Scope * rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap) { RDIM_IdxedChunkListPush(arena, list, RDIM_ScopeChunkNode, RDIM_Scope, cap, result); return result; } RDI_PROC RDI_U64 rdim_idx_from_scope(RDIM_Scope *scope) { RDIM_IdxedChunkListElementGetIdx(scope, idx); return idx; } RDI_PROC void rdim_scope_chunk_list_concat_in_place(RDIM_ScopeChunkList *dst, RDIM_ScopeChunkList *to_push) { RDIM_IdxedChunkListConcatInPlace(RDIM_ScopeChunkNode, dst, to_push, dst->scope_voff_count += to_push->scope_voff_count, dst->local_count += to_push->local_count, dst->location_case_count += to_push->location_case_count); } RDI_PROC void rdim_scope_push_voff_range(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDIM_Scope *scope, RDIM_Rng1U64 range) { rdim_rng1u64_list_push(arena, &scope->voff_ranges, range); list->scope_voff_count += 2; } RDI_PROC RDIM_Local * rdim_scope_push_local(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *scope) { RDIM_Local *local = rdim_push_array(arena, RDIM_Local, 1); RDIM_SLLQueuePush(scope->first_local, scope->last_local, local); scope->local_count += 1; scopes->local_count += 1; return local; } RDI_PROC RDIM_LocationCase * rdim_push_location_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationCaseList *list, RDIM_Location *location, RDIM_Rng1U64 voff_range) { RDIM_LocationCase *n = rdim_push_array(arena, RDIM_LocationCase, 1); RDIM_SLLQueuePush(list->first, list->last, n); list->count += 1; n->location = location; n->voff_range = voff_range; scopes->location_case_count += 1; return n; } RDI_PROC RDIM_LocationCase * rdim_local_push_location_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Local *local, RDIM_Location *location, RDIM_Rng1U64 voff_range) { return rdim_push_location_case(arena, scopes, &local->location_cases, location, voff_range); } //////////////////////////////// //~ rjf: [Building] Bake Parameter Joining RDI_PROC void rdim_bake_params_concat_in_place(RDIM_BakeParams *dst, RDIM_BakeParams *src) { // rjf: join top-level info (deduplicate - throw away conflicts) { dst->subset_flags |= src->subset_flags; if(dst->top_level_info.arch == RDI_Arch_NULL) { dst->top_level_info.arch = src->top_level_info.arch; } if(dst->top_level_info.exe_name.size == 0) { dst->top_level_info.exe_name = src->top_level_info.exe_name; } if(dst->top_level_info.exe_hash == 0) { dst->top_level_info.exe_hash = src->top_level_info.exe_hash; } if(dst->top_level_info.voff_max == 0) { dst->top_level_info.voff_max = src->top_level_info.voff_max; } if(dst->top_level_info.guid.u64[0] == 0 && dst->top_level_info.guid.u64[1] == 0) { dst->top_level_info.guid = src->top_level_info.guid; } if(dst->top_level_info.producer_name.size == 0) { dst->top_level_info.producer_name = src->top_level_info.producer_name; } } // rjf: join binary sections (deduplicate) { RDIM_Temp scratch = rdim_scratch_begin(0, 0); RDI_U64 slots_count = 256; RDIM_BinarySectionNode **slots = rdim_push_array(scratch.arena, RDIM_BinarySectionNode *, slots_count); for(RDIM_BinarySectionNode *n = dst->binary_sections.first; n != 0; n = n->next) { RDIM_BinarySectionNode *hash_node = rdim_push_array(scratch.arena, RDIM_BinarySectionNode, 1); RDI_U64 hash = rdi_hash(n->v.name.str, n->v.name.size); RDI_U64 slot_idx = hash%slots_count; RDIM_SLLStackPush(slots[slot_idx], hash_node); hash_node->v = n->v; } for(RDIM_BinarySectionNode *n = src->binary_sections.first, *next = 0; n != 0; n = next) { next = n->next; RDI_U64 hash = rdi_hash(n->v.name.str, n->v.name.size); RDI_U64 slot_idx = hash%slots_count; RDI_S32 is_duplicate = 0; for(RDIM_BinarySectionNode *hash_n = slots[slot_idx]; hash_n != 0; hash_n = hash_n->next) { if(rdim_str8_match(hash_n->v.name, n->v.name, 0)) { is_duplicate = 1; break; } } if(!is_duplicate) { RDIM_SLLQueuePush(dst->binary_sections.first, dst->binary_sections.last, n); dst->binary_sections.count += 1; } } rdim_scratch_end(scratch); } // rjf: join non-top-level chunk lists { rdim_unit_chunk_list_concat_in_place(&dst->units, &src->units); rdim_type_chunk_list_concat_in_place(&dst->types, &src->types); rdim_udt_chunk_list_concat_in_place(&dst->udts, &src->udts); rdim_src_file_chunk_list_concat_in_place(&dst->src_files, &src->src_files); rdim_line_table_chunk_list_concat_in_place(&dst->line_tables, &src->line_tables); rdim_location_chunk_list_concat_in_place(&dst->locations, &src->locations); rdim_symbol_chunk_list_concat_in_place(&dst->global_variables, &src->global_variables); rdim_symbol_chunk_list_concat_in_place(&dst->thread_variables, &src->thread_variables); rdim_symbol_chunk_list_concat_in_place(&dst->constants, &src->constants); rdim_symbol_chunk_list_concat_in_place(&dst->procedures, &src->procedures); rdim_scope_chunk_list_concat_in_place(&dst->scopes, &src->scopes); rdim_inline_site_chunk_list_concat_in_place(&dst->inline_sites, &src->inline_sites); } } //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated String Baking Map //- rjf: chunk lists RDI_PROC RDIM_BakeString * rdim_bake_string_chunk_list_push(RDIM_Arena *arena, RDIM_BakeStringChunkList *list, RDI_U64 cap) { RDIM_BakeStringChunkNode *n = list->last; if(n == 0 || n->count >= n->cap) { n = rdim_push_array(arena, RDIM_BakeStringChunkNode, 1); n->cap = cap; n->v = rdim_push_array(arena, RDIM_BakeString, n->cap); RDIM_SLLQueuePush(list->first, list->last, n); list->chunk_count += 1; } RDIM_BakeString *s = &n->v[n->count]; n->count += 1; list->total_count += 1; return s; } RDI_PROC void rdim_bake_string_chunk_list_concat_in_place(RDIM_BakeStringChunkList *dst, RDIM_BakeStringChunkList *to_push) { for(RDIM_BakeStringChunkNode *n = to_push->first; n != 0; n = n->next) { n->base_idx += dst->total_count; } if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; } else if(dst->first == 0) { rdim_memcpy_struct(dst, to_push); } rdim_memzero_struct(to_push); } RDI_PROC RSFORCEINLINE int rdim_bake_string_is_before(void *l, void *r) { return str8_is_before(((RDIM_BakeString *)l)->string, ((RDIM_BakeString *)r)->string); } RDI_PROC RDIM_BakeStringChunkList rdim_bake_string_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeStringChunkList *src) { //- rjf: produce unsorted destination list with single chunk node RDIM_BakeStringChunkList dst = {0}; for(RDIM_BakeStringChunkNode *n = src->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDIM_BakeString *src_str = &n->v[idx]; RDIM_BakeString *dst_str = rdim_bake_string_chunk_list_push(arena, &dst, src->total_count); rdim_memcpy_struct(dst_str, src_str); } } //- rjf: sort chunk node if(dst.first != 0) { radsort(dst.first->v, dst.first->count, rdim_bake_string_is_before); } //- rjf: iterate sorted chunk node, remove duplicates, count # of duplicates RDI_U64 num_duplicates = 0; if(dst.first != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(rdim_str8_match(dst.first->v[last_idx].string, dst.first->v[idx].string, 0)) { rdim_memzero_struct(&dst.first->v[idx]); num_duplicates += 1; } else { last_idx = idx; } } } //- rjf: iterate sorted chunk node, make non-empty elements contiguous if(num_duplicates != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(last_idx == 0 && dst.first->v[idx].string.RDIM_String8_SizeMember == 0 && dst.first->v[idx].hash == 0) { last_idx = idx; } if(last_idx != 0 && dst.first->v[idx].string.RDIM_String8_SizeMember != 0) { rdim_memcpy_struct(&dst.first->v[last_idx], &dst.first->v[idx]); rdim_memzero_struct(&dst.first->v[idx]); last_idx += 1; } } //- rjf: pop extras if(num_duplicates != 0) { RDI_U64 arena_pos_pre_pop = rdim_arena_pos(arena); rdim_arena_pop_to(arena, arena_pos_pre_pop - num_duplicates*sizeof(dst.first->v[0])); dst.first->count -= num_duplicates; dst.first->cap -= num_duplicates; dst.total_count -= num_duplicates; } } return dst; } //- rjf: loose map RDI_PROC RDIM_BakeStringMapLoose * rdim_bake_string_map_loose_make(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top) { RDIM_BakeStringMapLoose *map = rdim_push_array(arena, RDIM_BakeStringMapLoose, 1); map->slots = rdim_push_array(arena, RDIM_BakeStringChunkList *, top->slots_count); return map; } RDI_PROC void rdim_bake_string_map_loose_insert(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map, RDI_U64 chunk_cap, RDIM_String8 string) { if(string.RDIM_String8_SizeMember != 0) { RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); RDI_U64 slot_idx = hash%map_topology->slots_count; RDIM_BakeStringChunkList *slot = map->slots[slot_idx]; if(slot == 0) { slot = map->slots[slot_idx] = rdim_push_array(arena, RDIM_BakeStringChunkList, 1); } RDI_S32 is_duplicate = 0; for(RDIM_BakeStringChunkNode *n = slot->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { if(rdim_str8_match(n->v[idx].string, string, 0)) { is_duplicate = 1; goto break_all; } } } break_all:; if(!is_duplicate) { RDIM_BakeString *bstr = rdim_bake_string_chunk_list_push(arena, slot, chunk_cap); bstr->string = string; bstr->hash = hash; } } } RDI_PROC RDIM_BakeStringMapBaseIndices rdim_bake_string_map_base_indices_from_map_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map) { RDIM_BakeStringMapBaseIndices indices = {0}; indices.slots_base_idxs = rdim_push_array(arena, RDI_U64, map_topology->slots_count+1); RDI_U64 total_count = 0; for(RDI_U64 idx = 0; idx < map_topology->slots_count; idx += 1) { indices.slots_base_idxs[idx] += total_count; if(map->slots[idx] != 0) { total_count += map->slots[idx]->total_count; } } indices.slots_base_idxs[map_topology->slots_count] = total_count; return indices; } //- rjf: finalized / tight map RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) { RDI_U32 idx = 0; if(string.RDIM_String8_SizeMember != 0) { RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); RDI_U64 slot_idx = hash%map->slots_count; for(RDIM_BakeStringChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { if(n->v[chunk_idx].hash == hash && rdim_str8_match(n->v[chunk_idx].string, string, 0)) { idx = map->slots_base_idxs[slot_idx] + n->base_idx + chunk_idx + 1; break; } } } } return idx; } //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Index Run Baking Map //- rjf: bake idx run map reading/writing RDI_PROC RDI_U64 rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count) { RDI_U64 hash = 5381; RDI_U32 *ptr = idx_run; RDI_U32 *opl = idx_run + count; for(;ptr < opl; ptr += 1) { hash = ((hash << 5) + hash) + (*ptr); } return hash; } //- rjf: chunk lists RDI_PROC RDIM_BakeIdxRun * rdim_bake_idx_run_chunk_list_push(RDIM_Arena *arena, RDIM_BakeIdxRunChunkList *list, RDI_U64 cap) { RDIM_BakeIdxRunChunkNode *n = list->last; if(n == 0 || n->count >= n->cap) { n = rdim_push_array(arena, RDIM_BakeIdxRunChunkNode, 1); n->cap = cap; n->v = rdim_push_array(arena, RDIM_BakeIdxRun, n->cap); RDIM_SLLQueuePush(list->first, list->last, n); list->chunk_count += 1; } RDIM_BakeIdxRun *s = &n->v[n->count]; n->count += 1; list->total_count += 1; return s; } RDI_PROC void rdim_bake_idx_run_chunk_list_concat_in_place(RDIM_BakeIdxRunChunkList *dst, RDIM_BakeIdxRunChunkList *to_push) { if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; } else if(dst->first == 0) { rdim_memcpy_struct(dst, to_push); } rdim_memzero_struct(to_push); } RDI_PROC RSFORCEINLINE int rdim_bake_idx_run_is_before(void *l, void *r) { B32 is_less_than = 0; { RDIM_BakeIdxRun *lir = (RDIM_BakeIdxRun *)l; RDIM_BakeIdxRun *rir = (RDIM_BakeIdxRun *)r; U64 common_count = Min(lir->count, rir->count); for(U64 off = 0; off < common_count; off += 1) { if(lir->idxes[off] < rir->idxes[off]) { is_less_than = 1; break; } else if(lir->idxes[off] > rir->idxes[off]) { is_less_than = 0; break; } else if(off+1 == common_count) { is_less_than = (lir->count < rir->count); } } } return is_less_than; } RDI_PROC RDIM_BakeIdxRunChunkList rdim_bake_idx_run_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeIdxRunChunkList *src) { //- rjf: produce unsorted destination list with single chunk node RDIM_BakeIdxRunChunkList dst = {0}; for(RDIM_BakeIdxRunChunkNode *n = src->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDIM_BakeIdxRun *src_str = &n->v[idx]; RDIM_BakeIdxRun *dst_str = rdim_bake_idx_run_chunk_list_push(arena, &dst, src->total_count); rdim_memcpy_struct(dst_str, src_str); } } //- rjf: sort chunk node if(dst.first != 0) { radsort(dst.first->v, dst.first->count, rdim_bake_idx_run_is_before); } //- rjf: iterate sorted chunk node, remove duplicates, count # of duplicates RDI_U64 num_duplicates = 0; if(dst.first != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(dst.first->v[last_idx].count == dst.first->v[idx].count && MemoryMatch(dst.first->v[last_idx].idxes, dst.first->v[idx].idxes, sizeof(dst.first->v[idx].idxes[0]) * dst.first->v[idx].count)) { rdim_memzero_struct(&dst.first->v[idx]); num_duplicates += 1; } else { last_idx = idx; } } } //- rjf: iterate sorted chunk node, make non-empty elements contiguous if(num_duplicates != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(last_idx == 0 && dst.first->v[idx].hash == 0) { last_idx = idx; } if(last_idx != 0 && dst.first->v[idx].hash != 0) { rdim_memcpy_struct(&dst.first->v[last_idx], &dst.first->v[idx]); rdim_memzero_struct(&dst.first->v[idx]); last_idx += 1; } } //- rjf: pop extras if(num_duplicates != 0) { RDI_U64 arena_pos_pre_pop = rdim_arena_pos(arena); rdim_arena_pop_to(arena, arena_pos_pre_pop - num_duplicates*sizeof(dst.first->v[0])); dst.first->count -= num_duplicates; dst.first->cap -= num_duplicates; dst.total_count -= num_duplicates; } } return dst; } //- rjf: loose map RDI_PROC RDIM_BakeIdxRunMapLoose * rdim_bake_idx_run_map_loose_make(RDIM_Arena *arena, RDIM_BakeIdxRunMapTopology *top) { RDIM_BakeIdxRunMapLoose *map = rdim_push_array(arena, RDIM_BakeIdxRunMapLoose, 1); map->slots = rdim_push_array(arena, RDIM_BakeIdxRunChunkList *, top->slots_count); map->slots_idx_counts = rdim_push_array(arena, RDI_U64, top->slots_count); return map; } RDI_PROC void rdim_bake_idx_run_map_loose_insert(RDIM_Arena *arena, RDIM_BakeIdxRunMapTopology *map_topology, RDIM_BakeIdxRunMapLoose *map, RDI_U64 chunk_cap, RDI_U32 *idxes, RDI_U32 count) { if(count != 0) { RDI_U64 hash = rdim_hash_from_idx_run(idxes, count); RDI_U64 slot_idx = hash%map_topology->slots_count; RDIM_BakeIdxRunChunkList *slot = map->slots[slot_idx]; if(slot == 0) { slot = map->slots[slot_idx] = rdim_push_array(arena, RDIM_BakeIdxRunChunkList, 1); } RDI_S32 is_duplicate = 0; for(RDIM_BakeIdxRunChunkNode *n = slot->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { if(n->v[idx].hash == hash && n->v[idx].count == count && MemoryMatch(n->v[idx].idxes, idxes, sizeof(idxes[0])*count)) { is_duplicate = 1; goto break_all; } } } break_all:; if(!is_duplicate) { RDIM_BakeIdxRun *bir = rdim_bake_idx_run_chunk_list_push(arena, slot, chunk_cap); bir->hash = hash; bir->count = count; bir->idxes = idxes; map->slots_idx_counts[slot_idx] += count; } } } //- rjf: finalized / tight map RDI_PROC RDI_U32 rdim_bake_idx_from_idx_run(RDIM_BakeIdxRunMap *map, RDI_U32 *idxes, RDI_U32 count) { RDI_U32 idx = 0; if(count != 0) { RDI_U64 hash = rdim_hash_from_idx_run(idxes, count); RDI_U64 slot_idx = hash%map->slots_count; RDI_U64 off = 0; for(RDIM_BakeIdxRunChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { if(n->v[chunk_idx].hash == hash && n->v[chunk_idx].count == count && MemoryMatch(n->v[chunk_idx].idxes, idxes, sizeof(idxes[0])*count)) { idx = (RDI_U32)(map->slots_base_idxs[slot_idx] + off); // TODO(rjf): @u64_to_u32 goto end_lookup; } off += n->v[chunk_idx].count; } } end_lookup:; } return idx; } //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Name Map Baking Map //- rjf: chunk lists RDI_PROC RDIM_BakeName * rdim_bake_name_chunk_list_push(RDIM_Arena *arena, RDIM_BakeNameChunkList *list, RDI_U64 cap) { RDIM_BakeNameChunkNode *n = list->last; if(n == 0 || n->count >= n->cap) { n = rdim_push_array(arena, RDIM_BakeNameChunkNode, 1); n->cap = cap; n->base_idx = list->total_count; n->v = rdim_push_array(arena, RDIM_BakeName, n->cap); RDIM_SLLQueuePush(list->first, list->last, n); list->chunk_count += 1; } RDIM_BakeName *result = &n->v[n->count]; n->count += 1; list->total_count += 1; return result; } RDI_PROC void rdim_bake_name_chunk_list_concat_in_place(RDIM_BakeNameChunkList *dst, RDIM_BakeNameChunkList *to_push) { for(RDIM_BakeNameChunkNode *n = to_push->first; n != 0; n = n->next) { n->base_idx += dst->total_count; } if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; } else if(dst->first == 0) { rdim_memcpy_struct(dst, to_push); } rdim_memzero_struct(to_push); } RDI_PROC RSFORCEINLINE int rdim_bake_name_is_before(void *l, void *r) { RDIM_BakeName *lhs = (RDIM_BakeName *)l; RDIM_BakeName *rhs = (RDIM_BakeName *)r; B32 lhs_name_lt = str8_is_before(lhs->string, rhs->string); B32 is_before = lhs_name_lt; if(!lhs_name_lt) { B32 rhs_name_lt = str8_is_before(rhs->string, lhs->string); if(!rhs_name_lt) { is_before = (lhs->idx > rhs->idx); } } return is_before; } RDI_PROC RDIM_BakeNameChunkList rdim_bake_name_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeNameChunkList *src) { //- rjf: produce unsorted destination list with single chunk node RDIM_BakeNameChunkList dst = {0}; for(RDIM_BakeNameChunkNode *n = src->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDIM_BakeName *src_str = &n->v[idx]; RDIM_BakeName *dst_str = rdim_bake_name_chunk_list_push(arena, &dst, src->total_count); rdim_memcpy_struct(dst_str, src_str); } } //- rjf: sort chunk node if(dst.first != 0) { radsort(dst.first->v, dst.first->count, rdim_bake_name_is_before); } //- rjf: iterate sorted chunk node, remove duplicates, count # of duplicates RDI_U64 num_duplicates = 0; if(dst.first != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(rdim_str8_match(dst.first->v[last_idx].string, dst.first->v[idx].string, 0) && dst.first->v[last_idx].idx == dst.first->v[idx].idx) { rdim_memzero_struct(&dst.first->v[idx]); num_duplicates += 1; } else { last_idx = idx; } } } //- rjf: iterate sorted chunk node, make non-empty elements contiguous if(num_duplicates != 0) { RDI_U64 last_idx = 0; for(RDI_U64 idx = 1; idx < dst.first->count; idx += 1) { if(last_idx == 0 && dst.first->v[idx].string.RDIM_String8_SizeMember == 0 && dst.first->v[idx].hash == 0) { last_idx = idx; } if(last_idx != 0 && dst.first->v[idx].string.RDIM_String8_SizeMember != 0) { rdim_memcpy_struct(&dst.first->v[last_idx], &dst.first->v[idx]); rdim_memzero_struct(&dst.first->v[idx]); last_idx += 1; } } //- rjf: pop extras if(num_duplicates != 0) { RDI_U64 arena_pos_pre_pop = rdim_arena_pos(arena); rdim_arena_pop_to(arena, arena_pos_pre_pop - num_duplicates*sizeof(dst.first->v[0])); dst.first->count -= num_duplicates; dst.first->cap -= num_duplicates; dst.total_count -= num_duplicates; } } return dst; } //- rjf: bake name chunk list maps RDI_PROC RDIM_BakeNameMap * rdim_bake_name_map_make(RDIM_Arena *arena, RDIM_BakeNameMapTopology *top) { RDIM_BakeNameMap *map = rdim_push_array(arena, RDIM_BakeNameMap, 1); map->slots = rdim_push_array(arena, RDIM_BakeNameChunkList *, top->slots_count); return map; } RDI_PROC void rdim_bake_name_map_insert(RDIM_Arena *arena, RDIM_BakeNameMapTopology *map_topology, RDIM_BakeNameMap *map, RDI_U64 chunk_cap, RDIM_String8 string, RDI_U64 idx) { if(string.RDIM_String8_SizeMember != 0) { RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); RDI_U64 slot_idx = hash%map_topology->slots_count; RDIM_BakeNameChunkList *slot = map->slots[slot_idx]; if(slot == 0) { slot = map->slots[slot_idx] = rdim_push_array(arena, RDIM_BakeNameChunkList, 1); } RDI_S32 is_duplicate = 0; for(RDIM_BakeNameChunkNode *n = slot->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { if(rdim_str8_match(n->v[idx].string, string, 0) && n->v[idx].idx == idx) { is_duplicate = 1; goto break_all; } } } break_all:; if(!is_duplicate) { RDIM_BakeName *bstr = rdim_bake_name_chunk_list_push(arena, slot, chunk_cap); bstr->string = string; bstr->idx = idx; bstr->hash = hash; } } } //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Path Baking Tree RDI_PROC RDIM_BakePathNode * rdim_bake_path_node_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) { RDIM_BakePathNode *node = &tree->root; RDI_U8 *ptr = string.str; RDI_U8 *opl = string.str + string.size; for(;ptr < opl && node != 0;) { // rjf: skip past non-leading slashes RDI_U32 leading_slash = 0; if(ptr > string.str) { for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); } else if(ptr < opl) { leading_slash = (*ptr == '/'); } // rjf: save beginning of non-slash range RDI_U8 *range_first = ptr; // rjf: advance past leading slash if(leading_slash) { ptr += 1; } // rjf: skip past non-slashes for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); // rjf: empty range -> continue if(range_first >= ptr) { continue; } // rjf: range -> sub-directory string RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); // rjf: sub-directory string -> find child of node RDIM_BakePathNode *sub_dir_node = 0; for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) { if(rdim_str8_match(child->name, sub_dir, 0)) { sub_dir_node = child; } } // rjf: .. -> go up if(sub_dir.RDIM_String8_SizeMember == 2 && sub_dir.RDIM_String8_BaseMember[0] == '.' && sub_dir.RDIM_String8_BaseMember[1] == '.') { sub_dir_node = node->parent; if(sub_dir_node == 0) { sub_dir_node = &tree->root; } } // rjf: . -> stay here else if(sub_dir.RDIM_String8_SizeMember == 1 && sub_dir.RDIM_String8_BaseMember[0] == '.') { sub_dir_node = node; } // rjf: descend to child node = sub_dir_node; } return node; } RDI_PROC RDI_U32 rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) { RDIM_BakePathNode *path_node = rdim_bake_path_node_from_string(tree, string); RDI_U32 result = 0; if(path_node != 0) { result = path_node->idx; } return result; } RDI_PROC RDIM_BakePathNode * rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_String8 string) { RDIM_BakePathNode *node = &tree->root; RDI_U8 *ptr = string.str; RDI_U8 *opl = string.str + string.size; for(;ptr < opl;) { // rjf: skip past non-leading slashes RDI_U32 leading_slash = 0; if(ptr > string.str) { for(;ptr < opl && (*ptr == '/' || *ptr == '\\'); ptr += 1); } else if(ptr < opl) { leading_slash = (*ptr == '/'); } // rjf: save beginning of path part RDI_U8 *range_first = ptr; // rjf: advance past leading slash if(leading_slash) { ptr += 1; } // rjf: skip past non-slashes for(;ptr < opl && !(*ptr == '/' || *ptr == '\\'); ptr += 1); // rjf: empty range -> continue if(range_first >= ptr) { continue; } // rjf: range -> sub-directory string RDIM_String8 sub_dir = rdim_str8(range_first, (RDI_U64)(ptr-range_first)); // rjf: sub-directory string -> find child of node RDIM_BakePathNode *sub_dir_node = 0; for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling) { if(rdim_str8_match(child->name, sub_dir, 0)) { sub_dir_node = child; } } // rjf: .. -> go up if(sub_dir.RDIM_String8_SizeMember == 2 && sub_dir.RDIM_String8_BaseMember[0] == '.' && sub_dir.RDIM_String8_BaseMember[1] == '.') { sub_dir_node = node->parent; if(sub_dir_node == 0) { sub_dir_node = &tree->root; } } // rjf: . -> stay here else if(sub_dir.RDIM_String8_SizeMember == 1 && sub_dir.RDIM_String8_BaseMember[0] == '.') { sub_dir_node = node; } // rjf: no child -> make one else if(sub_dir_node == 0) { sub_dir_node = rdim_push_array(arena, RDIM_BakePathNode, 1); RDIM_SLLQueuePush_N(tree->first, tree->last, sub_dir_node, next_order); sub_dir_node->parent = node; RDIM_SLLQueuePush_N(node->first_child, node->last_child, sub_dir_node, next_sibling); sub_dir_node->name = rdim_str8_copy(arena, sub_dir); sub_dir_node->idx = tree->count; tree->count += 1; } // rjf: descend to child node = sub_dir_node; } return node; } //////////////////////////////// //~ rjf: [Baking Helpers] Data Section List Building Helpers RDI_PROC RDIM_BakeSection * rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list) { RDIM_BakeSectionNode *n = rdim_push_array(arena, RDIM_BakeSectionNode, 1); RDIM_SLLQueuePush(list->first, list->last, n); list->count += 1; RDIM_BakeSection *result = &n->v; return result; } RDI_PROC RDIM_BakeSection * rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx) { RDIM_BakeSection *section = rdim_bake_section_list_push(arena, list); section->data = data; section->encoding = RDI_SectionEncoding_Unpacked; section->encoded_size = size; section->unpacked_size = size; section->tag = tag; section->tag_idx = tag_idx; return section; } RDI_PROC void rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push) { if(dst->last != 0 && to_push->first != 0) { dst->last->next = to_push->first; dst->last = to_push->last; dst->count += to_push->count; } else if(to_push->first != 0) { rdim_memcpy_struct(dst, to_push); } rdim_memzero_struct(to_push); } //////////////////////////////// //~ rjf: [Serializing] Bake Results -> String Blobs RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data, RDI_U64 size) { RDIM_SerializedSection s; rdim_memzero_struct(&s); s.data = data; s.encoded_size = s.unpacked_size = size; s.encoding = RDI_SectionEncoding_Unpacked; return s; } RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) { RDIM_SerializedSectionBundle bundle; rdim_memzero_struct(&bundle); bundle.sections[RDI_SectionKind_TopLevelInfo] = rdim_serialized_section_make_unpacked_struct(&results->top_level_info.top_level_info); bundle.sections[RDI_SectionKind_StringData] = rdim_serialized_section_make_unpacked_array(results->strings.string_data, results->strings.string_data_size); bundle.sections[RDI_SectionKind_StringTable] = rdim_serialized_section_make_unpacked_array(results->strings.string_offs, results->strings.string_offs_count); bundle.sections[RDI_SectionKind_IndexRuns] = rdim_serialized_section_make_unpacked_array(results->idx_runs.idx_runs, results->idx_runs.idx_count); bundle.sections[RDI_SectionKind_BinarySections] = rdim_serialized_section_make_unpacked_array(results->binary_sections.binary_sections, results->binary_sections.binary_sections_count); bundle.sections[RDI_SectionKind_FilePathNodes] = rdim_serialized_section_make_unpacked_array(results->file_paths.nodes, results->file_paths.nodes_count); bundle.sections[RDI_SectionKind_SourceFiles] = rdim_serialized_section_make_unpacked_array(results->src_files.source_files, results->src_files.source_files_count); bundle.sections[RDI_SectionKind_LineTables] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_tables, results->line_tables.line_tables_count); bundle.sections[RDI_SectionKind_LineInfoVOffs] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_voffs, results->line_tables.line_table_voffs_count); bundle.sections[RDI_SectionKind_LineInfoLines] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_lines, results->line_tables.line_table_lines_count); bundle.sections[RDI_SectionKind_LineInfoColumns] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_columns, results->line_tables.line_table_columns_count); bundle.sections[RDI_SectionKind_SourceLineMaps] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_maps, results->src_files.source_line_maps_count); bundle.sections[RDI_SectionKind_SourceLineMapNumbers] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_nums, results->src_files.source_line_map_nums_count); bundle.sections[RDI_SectionKind_SourceLineMapRanges] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_rngs, results->src_files.source_line_map_rngs_count); bundle.sections[RDI_SectionKind_SourceLineMapVOffs] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_voffs, results->src_files.source_line_map_voffs_count); bundle.sections[RDI_SectionKind_Units] = rdim_serialized_section_make_unpacked_array(results->units.units, results->units.units_count); bundle.sections[RDI_SectionKind_UnitVMap] = rdim_serialized_section_make_unpacked_array(results->unit_vmap.vmap.vmap, results->unit_vmap.vmap.count); bundle.sections[RDI_SectionKind_TypeNodes] = rdim_serialized_section_make_unpacked_array(results->type_nodes.type_nodes, results->type_nodes.type_nodes_count); bundle.sections[RDI_SectionKind_UDTs] = rdim_serialized_section_make_unpacked_array(results->udts.udts, results->udts.udts_count); bundle.sections[RDI_SectionKind_Members] = rdim_serialized_section_make_unpacked_array(results->udts.members, results->udts.members_count); bundle.sections[RDI_SectionKind_EnumMembers] = rdim_serialized_section_make_unpacked_array(results->udts.enum_members, results->udts.enum_members_count); bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count); bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); bundle.sections[RDI_SectionKind_Constants] = rdim_serialized_section_make_unpacked_array(results->constants.constants, results->constants.constants_count); bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count); bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked_array(results->inline_sites.inline_sites, results->inline_sites.inline_sites_count); bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->location_blocks.location_blocks, results->location_blocks.location_blocks_count); bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->locations.location_data, results->locations.location_data_size); bundle.sections[RDI_SectionKind_ConstantValueData] = rdim_serialized_section_make_unpacked_array(results->constants.constant_value_data, results->constants.constant_value_data_size); bundle.sections[RDI_SectionKind_ConstantValueTable] = rdim_serialized_section_make_unpacked_array(results->constants.constant_values, results->constants.constant_values_count); bundle.sections[RDI_SectionKind_MD5Checksums] = rdim_serialized_section_make_unpacked_array(results->checksums.md5s, results->checksums.md5s_count); bundle.sections[RDI_SectionKind_SHA1Checksums] = rdim_serialized_section_make_unpacked_array(results->checksums.sha1s, results->checksums.sha1s_count); bundle.sections[RDI_SectionKind_SHA256Checksums] = rdim_serialized_section_make_unpacked_array(results->checksums.sha256s, results->checksums.sha256s_count); bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); return bundle; } RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle) { RDIM_String8List strings; rdim_memzero_struct(&strings); { RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); // rjf: push empty header & data section table RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, RDI_SectionKind_COUNT); rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); rdim_str8_list_push_align(arena, &strings, 8); U32 data_section_off = (U32)strings.total_size; rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*RDI_SectionKind_COUNT)); // rjf: fill baked header { rdi_header->magic = RDI_MAGIC_CONSTANT; rdi_header->encoding_version = RDI_ENCODING_VERSION; rdi_header->data_section_off = data_section_off; rdi_header->data_section_count = RDI_SectionKind_COUNT; } // rjf: fill baked data section table for(RDI_SectionKind k = RDI_SectionKind_NULL; k < RDI_SectionKind_COUNT; k += 1) { RDI_Section *dst = rdi_sections+k; U64 data_section_off = 0; if(bundle->sections[k].encoded_size != 0) { rdim_str8_list_push_align(arena, &strings, 8); data_section_off = strings.total_size; rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)bundle->sections[k].data, bundle->sections[k].encoded_size)); } dst->encoding = bundle->sections[k].encoding; dst->off = data_section_off; dst->encoded_size = bundle->sections[k].encoded_size; dst->unpacked_size = bundle->sections[k].unpacked_size; } rdim_scratch_end(scratch); } return strings; } ================================================ FILE: src/lib_rdi_make/rdi_make.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// // RAD Debug Info Make, (R)AD(D)BG(I) (M)ake Library // // Library for building loose data structures which contain // RDI debug information, and baking that down into the // proper flattened RDI format. // // Requires prior inclusion of the RAD Debug Info, (R)AD(D)BG(I) // Format Library, in rdi_format.h. #ifndef RDI_MAKE_H #define RDI_MAKE_H //////////////////////////////// //~ rjf: Overrideable Memory Operations // To override the slow/default memset implementation used by the library, // do the following: // // #define RDIM_MEMSET_OVERRIDE // #define rdim_memset #if !defined(rdim_memset) # define rdim_memset rdim_memset_fallback #endif // To override the slow/default memcpy implementation used by the library, // do the following: // // #define RDIM_MEMCPY_OVERRIDE // #define rdim_memcpy #if !defined(rdim_memset) # define rdim_memset rdim_memset_fallback #endif #if !defined(rdim_memcpy) # define rdim_memcpy rdim_memcpy_fallback #endif //////////////////////////////// //~ rjf: Overrideable sprintf Functions #if !defined(rdim_vsnprintf) # include # define rdim_vsnprintf vsnprintf #endif //////////////////////////////// //~ rjf: Overrideable String View Types // To override the string view type used by the library, do the following: // // #define RDIM_STRING8_OVERRIDE // #define RDIM_String8 // #define RDIM_String8_BaseMember // #define RDIM_String8_SizeMember // To override the string view list type used by the library, do the following: // // #define RDIM_STRING8LIST_OVERRIDE // #define RDIM_String8Node // #define RDIM_String8_NextPtrMember // #define RDIM_String8_StringMember // #define RDIM_String8List // #define RDIM_String8_FirstMember // #define RDIM_String8_LastMember // #define RDIM_String8_NodeCount // #define RDIM_String8_TotalSizeMember #if !defined(RDIM_String8) #define RDIM_String8 RDIM_String8 #define RDIM_String8_BaseMember str #define RDIM_String8_SizeMember size typedef struct RDIM_String8 RDIM_String8; struct RDIM_String8 { RDI_U8 *str; RDI_U64 size; }; #endif #if !defined(RDIM_String8Node) #define RDIM_String8Node RDIM_String8Node #define RDIM_String8Node_NextPtrMember next #define RDIM_String8Node_StringMember string typedef struct RDIM_String8Node RDIM_String8Node; struct RDIM_String8Node { RDIM_String8Node *next; RDIM_String8 string; }; #endif #if !defined(RDIM_String8List) #define RDIM_String8List RDIM_String8List #define RDIM_String8List_FirstMember first #define RDIM_String8List_LastMember last #define RDIM_String8List_NodeCountMember node_count #define RDIM_String8List_TotalSizeMember total_size typedef struct RDIM_String8List RDIM_String8List; struct RDIM_String8List { RDIM_String8Node *first; RDIM_String8Node *last; RDI_U64 node_count; RDI_U64 total_size; }; #endif typedef RDI_U32 RDIM_StringMatchFlags; enum { RDIM_StringMatchFlag_CaseInsensitive = (1<<0), }; //////////////////////////////// //~ rjf: Overrideable Arena Allocator Types // To override the arena allocator type used by the library, do the following: // // #define RDIM_ARENA_OVERRIDE // #define RDIM_Arena // #define rdim_arena_alloc Arena*> // #define rdim_arena_release void> // #define rdim_arena_pos U64> // #define rdim_arena_push void*> // #define rdim_arena_pop_to void> #if !defined(RDIM_Arena) # define RDIM_Arena RDIM_Arena typedef struct RDIM_Arena RDIM_Arena; struct RDIM_Arena { RDIM_Arena *prev; RDIM_Arena *current; RDI_U64 base_pos; RDI_U64 pos; RDI_U64 cmt; RDI_U64 res; RDI_U64 align; RDI_S8 grow; }; #endif #if !defined(rdim_arena_alloc) # define rdim_arena_alloc rdim_arena_alloc_fallback #endif #if !defined(rdim_arena_release) # define rdim_arena_release rdim_arena_release_fallback #endif #if !defined(rdim_arena_pos) # define rdim_arena_pos rdim_arena_pos_fallback #endif #if !defined(rdim_arena_push) # define rdim_arena_push rdim_arena_push_fallback #endif //////////////////////////////// //~ rjf: Overrideable Thread-Local Scratch Arenas // To override the default thread-local scratch arenas used by the library, // do the following: // // #define RDIM_SCRATCH_OVERRIDE // #define RDIM_Temp arena implementation - must be (Temp) -> (Arena*)> // #define rdim_scratch_begin Temp> // #define rdim_scratch_end void #if !defined(RDIM_Temp) # define RDIM_Temp RDIM_Temp typedef struct RDIM_Temp RDIM_Temp; struct RDIM_Temp { RDIM_Arena *arena; RDI_U64 pos; }; #define rdim_temp_arena(t) ((t).arena) #endif #if !defined(rdim_scratch_begin) # define rdim_scratch_begin rdim_scratch_begin_fallback #endif #if !defined(rdim_scratch_end) # define rdim_scratch_end rdim_scratch_end_fallback #endif //////////////////////////////// //~ rjf: Overrideable Profile Markup // To override the default profiling markup, do the following: // // #define RDIM_ProfBegin(...) // #define RDIM_ProfEnd() #if !defined(RDIM_ProfBegin) # define RDIM_ProfBegin(...) ((void)0) #endif #if !defined(RDIM_ProfEnd) # define RDIM_ProfEnd() ((void)0) #endif #define RDIM_ProfScope(...) for(int _i_ = ((RDIM_ProfBegin(__VA_ARGS__)), 0); !_i_; _i_ += 1, (RDIM_ProfEnd())) //////////////////////////////// //~ rjf: Alignment Macros #if _MSC_VER # define RDIM_AlignOf(T) __alignof(T) #elif __clang__ # define RDIM_AlignOf(T) __alignof(T) #elif __GNUC__ # define RDIM_AlignOf(T) __alignof__(T) #else # error [RDIM Build Error] RDIM_AlignOf(T) is not defined for this compiler. #endif //////////////////////////////// //~ rjf: Linked List Helper Macros #define RDIM_CheckNil(nil,p) ((p) == 0 || (p) == nil) #define RDIM_SetNil(nil,p) ((p) = nil) //- rjf: Base Doubly-Linked-List Macros #define RDIM_DLLInsert_NPZ(nil,f,l,p,n,next,prev) (RDIM_CheckNil(nil,f) ? \ ((f) = (l) = (n), RDIM_SetNil(nil,(n)->next), RDIM_SetNil(nil,(n)->prev)) :\ RDIM_CheckNil(nil,p) ? \ ((n)->next = (f), (f)->prev = (n), (f) = (n), RDIM_SetNil(nil,(n)->prev)) :\ ((p)==(l)) ? \ ((l)->next = (n), (n)->prev = (l), (l) = (n), RDIM_SetNil(nil, (n)->next)) :\ (((!RDIM_CheckNil(nil,p) && RDIM_CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p)))) #define RDIM_DLLPushBack_NPZ(nil,f,l,n,next,prev) RDIM_DLLInsert_NPZ(nil,f,l,l,n,next,prev) #define RDIM_DLLPushFront_NPZ(nil,f,l,n,next,prev) RDIM_DLLInsert_NPZ(nil,l,f,f,n,prev,next) #define RDIM_DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\ ((n) == (l) ? (l) = (l)->prev : (0)),\ (RDIM_CheckNil(nil,(n)->prev) ? (0) :\ ((n)->prev->next = (n)->next)),\ (RDIM_CheckNil(nil,(n)->next) ? (0) :\ ((n)->next->prev = (n)->prev))) //- rjf: Base Singly-Linked-List Queue Macros #define RDIM_SLLQueuePush_NZ(nil,f,l,n,next) (RDIM_CheckNil(nil,f)?\ ((f)=(l)=(n),RDIM_SetNil(nil,(n)->next)):\ ((l)->next=(n),(l)=(n),RDIM_SetNil(nil,(n)->next))) #define RDIM_SLLQueuePushFront_NZ(nil,f,l,n,next) (RDIM_CheckNil(nil,f)?\ ((f)=(l)=(n),RDIM_SetNil(nil,(n)->next)):\ ((n)->next=(f),(f)=(n))) #define RDIM_SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ (RDIM_SetNil(nil,f), RDIM_SetNil(nil,l)):\ ((f)=(f)->next)) //- rjf: Base Singly-Linked-List Stack Macros #define RDIM_SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) #define RDIM_SLLStackPop_N(f,next) ((f)=(f)->next) //////////////////////////////// //~ rjf: Convenience Wrappers //- rjf: Doubly-Linked-List Wrappers #define RDIM_DLLInsert_NP(f,l,p,n,next,prev) RDIM_DLLInsert_NPZ(0,f,l,p,n,next,prev) #define RDIM_DLLPushBack_NP(f,l,n,next,prev) RDIM_DLLPushBack_NPZ(0,f,l,n,next,prev) #define RDIM_DLLPushFront_NP(f,l,n,next,prev) RDIM_DLLPushFront_NPZ(0,f,l,n,next,prev) #define RDIM_DLLRemove_NP(f,l,n,next,prev) RDIM_DLLRemove_NPZ(0,f,l,n,next,prev) #define RDIM_DLLInsert(f,l,p,n) RDIM_DLLInsert_NPZ(0,f,l,p,n,next,prev) #define RDIM_DLLPushBack(f,l,n) RDIM_DLLPushBack_NPZ(0,f,l,n,next,prev) #define RDIM_DLLPushFront(f,l,n) RDIM_DLLPushFront_NPZ(0,f,l,n,next,prev) #define RDIM_DLLRemove(f,l,n) RDIM_DLLRemove_NPZ(0,f,l,n,next,prev) //- rjf: Singly-Linked-List Queue Wrappers #define RDIM_SLLQueuePush_N(f,l,n,next) RDIM_SLLQueuePush_NZ(0,f,l,n,next) #define RDIM_SLLQueuePushFront_N(f,l,n,next) RDIM_SLLQueuePushFront_NZ(0,f,l,n,next) #define RDIM_SLLQueuePop_N(f,l,next) RDIM_SLLQueuePop_NZ(0,f,l,next) #define RDIM_SLLQueuePush(f,l,n) RDIM_SLLQueuePush_NZ(0,f,l,n,next) #define RDIM_SLLQueuePushFront(f,l,n) RDIM_SLLQueuePushFront_NZ(0,f,l,n,next) #define RDIM_SLLQueuePop(f,l) RDIM_SLLQueuePop_NZ(0,f,l,next) //- rjf: Singly-Linked-List Stack Wrappers #define RDIM_SLLStackPush(f,n) RDIM_SLLStackPush_N(f,n,next) #define RDIM_SLLStackPop(f) RDIM_SLLStackPop_N(f,next) //////////////////////////////// //~ rjf: Helper Macros #if defined(_MSC_VER) # define RDIM_THREAD_LOCAL __declspec(thread) #elif defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) # define RDIM_THREAD_LOCAL __thread #else # error RDIM_THREAD_LOCAL not defined for this compiler. #endif #if defined(_MSC_VER) # define rdim_trap() __debugbreak() #elif defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) # define rdim_trap() __builtin_trap() #else # error "rdim_trap not defined for this compiler." #endif #define rdim_assert_always(x) do{if(!(x)) {rdim_trap();}}while(0) #if !defined(NDEBUG) # define rdim_assert(x) rdim_assert_always(x) #else # define rdim_assert(x) (void)(x) #endif #define rdim_noop ((void)0) //////////////////////////////// //~ rjf: RDI Subsets #define RDIM_Subset_XList \ X(BinarySections, binary_sections)\ X(Units, units)\ X(Procedures, procedures)\ X(GlobalVariables, global_variables)\ X(ThreadVariables, thread_variables)\ X(Constants, constants)\ X(Scopes, scopes)\ X(Locals, locals)\ X(Types, types)\ X(UDTs, udts)\ X(LineInfo, line_info)\ X(InlineLineInfo, inline_line_info)\ Y(GlobalVariableNameMap, global_variable_name_map)\ Y(ThreadVariableNameMap, thread_variable_name_map)\ Y(ProcedureNameMap, procedure_name_map)\ Y(ConstantNameMap, constant_name_map)\ Y(TypeNameMap, type_name_map)\ Y(LinkNameProcedureNameMap, link_name_procedure_name_map)\ Y(NormalSourcePathNameMap, normal_source_path_name_map)\ typedef enum RDIM_Subset { #define X(name, name_lower) RDIM_Subset_##name, #define Y(name, name_lower) RDIM_Subset_##name, RDIM_Subset_XList #undef X #undef Y } RDIM_Subset; typedef U32 RDIM_SubsetFlags; enum { #define X(name, name_lower) RDIM_SubsetFlag_##name = (1< pointer map typedef struct RDIM_U64ToPtrNode RDIM_U64ToPtrNode; struct RDIM_U64ToPtrNode { RDIM_U64ToPtrNode *next; RDI_U64 _padding_; RDI_U64 key[1]; void *ptr[1]; }; typedef struct RDIM_U64ToPtrMap RDIM_U64ToPtrMap; struct RDIM_U64ToPtrMap { RDIM_U64ToPtrNode **buckets; RDI_U64 buckets_count; RDI_U64 bucket_collision_count; RDI_U64 pair_count; }; typedef struct RDIM_U64ToPtrLookup RDIM_U64ToPtrLookup; struct RDIM_U64ToPtrLookup { void *match; RDIM_U64ToPtrNode *fill_node; RDI_U32 fill_k; }; //- rjf: string8 -> pointer map typedef struct RDIM_Str8ToPtrNode RDIM_Str8ToPtrNode; struct RDIM_Str8ToPtrNode { struct RDIM_Str8ToPtrNode *next; RDIM_String8 key; RDI_U64 hash; void *ptr; }; typedef struct RDIM_Str8ToPtrMap RDIM_Str8ToPtrMap; struct RDIM_Str8ToPtrMap { RDIM_Str8ToPtrNode **buckets; RDI_U64 buckets_count; RDI_U64 bucket_collision_count; RDI_U64 pair_count; }; //- rjf: sortable range data structure typedef struct RDIM_SortKey RDIM_SortKey; struct RDIM_SortKey { RDI_U64 key; void *val; }; typedef struct RDIM_OrderedRange RDIM_OrderedRange; struct RDIM_OrderedRange { RDIM_OrderedRange *next; RDI_U64 first; RDI_U64 opl; }; //////////////////////////////// //~ rjf: Error/Warning/Note Message Types typedef struct RDIM_Msg RDIM_Msg; struct RDIM_Msg { RDIM_Msg *next; RDIM_String8 string; }; typedef struct RDIM_MsgList RDIM_MsgList; struct RDIM_MsgList { RDIM_Msg *first; RDIM_Msg *last; RDI_U64 count; }; //////////////////////////////// //~ rjf: Top-Level Debug Info Types typedef struct RDIM_TopLevelInfo RDIM_TopLevelInfo; struct RDIM_TopLevelInfo { RDI_Arch arch; RDIM_String8 exe_name; RDI_U64 exe_hash; RDI_U64 voff_max; RDI_GUID guid; RDIM_String8 producer_name; }; //////////////////////////////// //~ rjf: Binary Section Types typedef struct RDIM_BinarySection RDIM_BinarySection; struct RDIM_BinarySection { RDIM_String8 name; RDI_BinarySectionFlags flags; RDI_U64 voff_first; RDI_U64 voff_opl; RDI_U64 foff_first; RDI_U64 foff_opl; }; typedef struct RDIM_BinarySectionNode RDIM_BinarySectionNode; struct RDIM_BinarySectionNode { RDIM_BinarySectionNode *next; RDIM_BinarySection v; }; typedef struct RDIM_BinarySectionList RDIM_BinarySectionList; struct RDIM_BinarySectionList { RDIM_BinarySectionNode *first; RDIM_BinarySectionNode *last; RDI_U64 count; }; //////////////////////////////// //~ rjf: Source File Info Types typedef struct RDIM_SrcFileLineMapFragment RDIM_SrcFileLineMapFragment; struct RDIM_SrcFileLineMapFragment { RDIM_SrcFileLineMapFragment *next; struct RDIM_LineSequence *seq; }; typedef struct RDIM_SrcFile RDIM_SrcFile; struct RDIM_SrcFile { struct RDIM_SrcFileChunkNode *chunk; RDIM_String8 path; RDIM_SrcFileLineMapFragment *first_line_map_fragment; RDIM_SrcFileLineMapFragment *last_line_map_fragment; RDI_U64 total_line_count; RDI_ChecksumKind checksum_kind; RDIM_String8 checksum; }; typedef struct RDIM_SrcFileChunkNode RDIM_SrcFileChunkNode; struct RDIM_SrcFileChunkNode { RDIM_SrcFileChunkNode *next; RDIM_SrcFile *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_SrcFileChunkList RDIM_SrcFileChunkList; struct RDIM_SrcFileChunkList { RDIM_SrcFileChunkNode *first; RDIM_SrcFileChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 source_line_map_count; RDI_U64 total_line_count; }; //////////////////////////////// //~ rjf: Line Info Types typedef struct RDIM_LineSequence RDIM_LineSequence; struct RDIM_LineSequence { RDIM_SrcFile *src_file; RDI_U64 *voffs; // [line_count + 1] (sorted) RDI_U32 *line_nums; // [line_count] RDI_U16 *col_nums; // [2*line_count] RDI_U64 line_count; }; typedef struct RDIM_LineSequenceNode RDIM_LineSequenceNode; struct RDIM_LineSequenceNode { RDIM_LineSequenceNode *next; RDIM_LineSequence v; }; typedef struct RDIM_LineTable RDIM_LineTable; struct RDIM_LineTable { struct RDIM_LineTableChunkNode *chunk; RDIM_LineSequenceNode *first_seq; RDIM_LineSequenceNode *last_seq; RDI_U64 seq_count; RDI_U64 line_count; RDI_U64 col_count; }; typedef struct RDIM_LineTableChunkNode RDIM_LineTableChunkNode; struct RDIM_LineTableChunkNode { RDIM_LineTableChunkNode *next; RDIM_LineTable *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_LineTableChunkList RDIM_LineTableChunkList; struct RDIM_LineTableChunkList { RDIM_LineTableChunkNode *first; RDIM_LineTableChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 total_seq_count; RDI_U64 total_line_count; RDI_U64 total_col_count; }; //////////////////////////////// //~ rjf: Per-Compilation-Unit Info Types typedef struct RDIM_Unit RDIM_Unit; struct RDIM_Unit { struct RDIM_UnitChunkNode *chunk; RDIM_String8 unit_name; RDIM_String8 compiler_name; RDIM_String8 source_file; RDIM_String8 object_file; RDIM_String8 archive_file; RDIM_String8 build_path; RDI_Language language; RDIM_LineTable *line_table; RDIM_Rng1U64ChunkList voff_ranges; }; typedef struct RDIM_UnitChunkNode RDIM_UnitChunkNode; struct RDIM_UnitChunkNode { RDIM_UnitChunkNode *next; RDIM_Unit *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_UnitChunkList RDIM_UnitChunkList; struct RDIM_UnitChunkList { RDIM_UnitChunkNode *first; RDIM_UnitChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; //////////////////////////////// //~ rjf: Type System Node Types typedef RDI_U32 RDIM_DataModel; typedef enum RDIM_DataModelEnum { RDIM_DataModel_Null, RDIM_DataModel_ILP32, RDIM_DataModel_LLP64, RDIM_DataModel_LP64, RDIM_DataModel_ILP64, RDIM_DataModel_SILP64 } RDIM_DataModelEnum; typedef struct RDIM_Type RDIM_Type; struct RDIM_Type { struct RDIM_TypeChunkNode *chunk; RDI_TypeKind kind; RDI_U32 byte_size; RDI_U32 flags; RDI_U32 off; RDI_U32 count; RDIM_String8 name; RDIM_String8 link_name; RDIM_Type *direct_type; RDIM_Type **param_types; struct RDIM_UDT *udt; }; typedef struct RDIM_TypeNode RDIM_TypeNode; struct RDIM_TypeNode { struct RDIM_TypeNode *next; RDIM_Type *v; }; typedef struct RDIM_TypeList RDIM_TypeList; struct RDIM_TypeList { U64 count; RDIM_TypeNode *first; RDIM_TypeNode *last; }; typedef struct RDIM_TypeChunkNode RDIM_TypeChunkNode; struct RDIM_TypeChunkNode { RDIM_TypeChunkNode *next; RDIM_Type *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_TypeChunkList RDIM_TypeChunkList; struct RDIM_TypeChunkList { RDIM_TypeChunkNode *first; RDIM_TypeChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; //////////////////////////////// //~ rjf: User-Defined-Type Info Types //- rjf: UDT members typedef struct RDIM_UDTMember RDIM_UDTMember; struct RDIM_UDTMember { RDIM_UDTMember *next; RDI_MemberKind kind; RDIM_String8 name; RDIM_Type *type; RDI_U32 off; }; //- rjf: UDT enum values typedef struct RDIM_UDTEnumVal RDIM_UDTEnumVal; struct RDIM_UDTEnumVal { RDIM_UDTEnumVal *next; RDIM_String8 name; RDI_U64 val; }; //- rjf: UDTs typedef struct RDIM_UDT RDIM_UDT; struct RDIM_UDT { struct RDIM_UDTChunkNode *chunk; RDIM_Type *self_type; RDIM_UDTMember *first_member; RDIM_UDTMember *last_member; RDIM_UDTEnumVal *first_enum_val; RDIM_UDTEnumVal *last_enum_val; RDI_U32 member_count; RDI_U32 enum_val_count; RDIM_SrcFile *src_file; RDI_U32 line; RDI_U32 col; }; typedef struct RDIM_UDTChunkNode RDIM_UDTChunkNode; struct RDIM_UDTChunkNode { RDIM_UDTChunkNode *next; RDIM_UDT *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_UDTChunkList RDIM_UDTChunkList; struct RDIM_UDTChunkList { RDIM_UDTChunkNode *first; RDIM_UDTChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 total_member_count; RDI_U64 total_enum_val_count; }; //////////////////////////////// //~ rjf: Location Info Types //- rjf: bytecode types typedef struct RDIM_EvalBytecodeOp RDIM_EvalBytecodeOp; struct RDIM_EvalBytecodeOp { RDIM_EvalBytecodeOp *next; RDI_EvalOp op; RDI_U32 p_size; RDI_U64 p; }; typedef struct RDIM_EvalBytecode RDIM_EvalBytecode; struct RDIM_EvalBytecode { RDIM_EvalBytecodeOp *first_op; RDIM_EvalBytecodeOp *last_op; RDI_U32 op_count; RDI_U32 encoded_size; }; //- rjf: location types typedef struct RDIM_LocationInfo RDIM_LocationInfo; struct RDIM_LocationInfo { RDI_LocationKind kind; RDI_U8 reg_code; RDI_U16 offset; RDIM_EvalBytecode bytecode; }; typedef struct RDIM_Location RDIM_Location; struct RDIM_Location { struct RDIM_LocationChunkNode *chunk; RDIM_LocationInfo info; RDI_U64 relative_encoding_off; }; typedef struct RDIM_LocationChunkNode RDIM_LocationChunkNode; struct RDIM_LocationChunkNode { RDIM_LocationChunkNode *next; RDIM_Location *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; RDI_U64 base_encoding_off; RDI_U64 encoded_size; }; typedef struct RDIM_LocationChunkList RDIM_LocationChunkList; struct RDIM_LocationChunkList { RDIM_LocationChunkNode *first; RDIM_LocationChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 total_encoded_size; }; //- rjf: location cases typedef struct RDIM_LocationCase RDIM_LocationCase; struct RDIM_LocationCase { RDIM_LocationCase *next; RDIM_Location *location; RDIM_Rng1U64 voff_range; }; typedef struct RDIM_LocationCaseList RDIM_LocationCaseList; struct RDIM_LocationCaseList { RDIM_LocationCase *first; RDIM_LocationCase *last; RDI_U64 count; }; //////////////////////////////// //~ rjf: Symbol Info Types typedef struct RDIM_Symbol RDIM_Symbol; struct RDIM_Symbol { struct RDIM_SymbolChunkNode *chunk; RDI_S32 is_extern; RDIM_String8 name; RDIM_String8 link_name; RDIM_Type *type; RDI_U64 offset; RDIM_Symbol *container_symbol; RDIM_Type *container_type; struct RDIM_Scope *root_scope; RDIM_LocationCaseList location_cases; RDIM_String8 value_data; }; typedef struct RDIM_SymbolChunkNode RDIM_SymbolChunkNode; struct RDIM_SymbolChunkNode { RDIM_SymbolChunkNode *next; RDIM_Symbol *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_SymbolChunkList RDIM_SymbolChunkList; struct RDIM_SymbolChunkList { RDIM_SymbolChunkNode *first; RDIM_SymbolChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 total_value_data_size; }; //////////////////////////////// //~ rjf: Inline Site Info Types typedef struct RDIM_InlineSite RDIM_InlineSite; struct RDIM_InlineSite { struct RDIM_InlineSiteChunkNode *chunk; RDIM_String8 name; RDIM_Type *type; RDIM_Type *owner; RDIM_LineTable *line_table; }; typedef struct RDIM_InlineSiteChunkNode RDIM_InlineSiteChunkNode; struct RDIM_InlineSiteChunkNode { RDIM_InlineSiteChunkNode *next; RDIM_InlineSite *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_InlineSiteChunkList RDIM_InlineSiteChunkList; struct RDIM_InlineSiteChunkList { RDIM_InlineSiteChunkNode *first; RDIM_InlineSiteChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; //////////////////////////////// //~ rjf: Scope Info Types typedef struct RDIM_Local RDIM_Local; struct RDIM_Local { RDIM_Local *next; RDI_LocalKind kind; RDIM_String8 name; RDIM_Type *type; RDIM_LocationCaseList location_cases; }; typedef struct RDIM_Scope RDIM_Scope; struct RDIM_Scope { struct RDIM_ScopeChunkNode *chunk; RDIM_Symbol *symbol; RDIM_Scope *parent_scope; RDIM_Scope *first_child; RDIM_Scope *last_child; RDIM_Scope *next_sibling; RDIM_Rng1U64List voff_ranges; RDIM_Local *first_local; RDIM_Local *last_local; RDI_U32 local_count; RDIM_InlineSite *inline_site; }; typedef struct RDIM_ScopeChunkNode RDIM_ScopeChunkNode; struct RDIM_ScopeChunkNode { RDIM_ScopeChunkNode *next; RDIM_Scope *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_ScopeChunkList RDIM_ScopeChunkList; struct RDIM_ScopeChunkList { RDIM_ScopeChunkNode *first; RDIM_ScopeChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; RDI_U64 scope_voff_count; RDI_U64 local_count; RDI_U64 location_case_count; }; //////////////////////////////// //~ rjf: Baking Types //- rjf: baking parameters typedef struct RDIM_BakeParams RDIM_BakeParams; struct RDIM_BakeParams { RDIM_SubsetFlags subset_flags; RDIM_TopLevelInfo top_level_info; RDIM_BinarySectionList binary_sections; RDIM_UnitChunkList units; RDIM_TypeChunkList types; RDIM_UDTChunkList udts; RDIM_SrcFileChunkList src_files; RDIM_LineTableChunkList line_tables; RDIM_LocationChunkList locations; RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; RDIM_SymbolChunkList constants; RDIM_SymbolChunkList procedures; RDIM_ScopeChunkList scopes; RDIM_InlineSiteChunkList inline_sites; }; //- rjf: data sections typedef struct RDIM_BakeSection RDIM_BakeSection; struct RDIM_BakeSection { void *data; RDI_SectionEncoding encoding; RDI_U64 encoded_size; RDI_U64 unpacked_size; RDI_SectionKind tag; RDI_U64 tag_idx; }; typedef struct RDIM_BakeSectionNode RDIM_BakeSectionNode; struct RDIM_BakeSectionNode { RDIM_BakeSectionNode *next; RDIM_BakeSection v; }; typedef struct RDIM_BakeSectionList RDIM_BakeSectionList; struct RDIM_BakeSectionList { RDIM_BakeSectionNode *first; RDIM_BakeSectionNode *last; RDI_U64 count; }; //- rjf: interned string type typedef struct RDIM_BakeString RDIM_BakeString; struct RDIM_BakeString { RDI_U64 hash; RDIM_String8 string; }; typedef struct RDIM_BakeStringChunkNode RDIM_BakeStringChunkNode; struct RDIM_BakeStringChunkNode { RDIM_BakeStringChunkNode *next; RDIM_BakeString *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_BakeStringChunkList RDIM_BakeStringChunkList; struct RDIM_BakeStringChunkList { RDIM_BakeStringChunkNode *first; RDIM_BakeStringChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; typedef struct RDIM_BakeStringMapTopology RDIM_BakeStringMapTopology; struct RDIM_BakeStringMapTopology { RDI_U64 slots_count; }; typedef struct RDIM_BakeStringMapBaseIndices RDIM_BakeStringMapBaseIndices; struct RDIM_BakeStringMapBaseIndices { RDI_U64 *slots_base_idxs; }; typedef struct RDIM_BakeStringMapLoose RDIM_BakeStringMapLoose; struct RDIM_BakeStringMapLoose { RDIM_BakeStringChunkList **slots; }; typedef struct RDIM_BakeStringMapTight RDIM_BakeStringMapTight; struct RDIM_BakeStringMapTight { RDIM_BakeStringChunkList *slots; RDI_U64 *slots_base_idxs; RDI_U64 slots_count; RDI_U64 total_count; }; //- rjf: index runs typedef struct RDIM_BakeIdxRun RDIM_BakeIdxRun; struct RDIM_BakeIdxRun { RDI_U64 hash; RDI_U64 count; RDI_U32 *idxes; }; typedef struct RDIM_BakeIdxRunChunkNode RDIM_BakeIdxRunChunkNode; struct RDIM_BakeIdxRunChunkNode { RDIM_BakeIdxRunChunkNode *next; RDIM_BakeIdxRun *v; RDI_U64 count; RDI_U64 cap; }; typedef struct RDIM_BakeIdxRunChunkList RDIM_BakeIdxRunChunkList; struct RDIM_BakeIdxRunChunkList { RDIM_BakeIdxRunChunkNode *first; RDIM_BakeIdxRunChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; typedef struct RDIM_BakeIdxRunMapTopology RDIM_BakeIdxRunMapTopology; struct RDIM_BakeIdxRunMapTopology { RDI_U64 slots_count; }; typedef struct RDIM_BakeIdxRunMapLoose RDIM_BakeIdxRunMapLoose; struct RDIM_BakeIdxRunMapLoose { RDIM_BakeIdxRunChunkList **slots; RDI_U64 *slots_idx_counts; }; typedef struct RDIM_BakeIdxRunMap RDIM_BakeIdxRunMap; struct RDIM_BakeIdxRunMap { RDIM_BakeIdxRunChunkList *slots; RDI_U64 *slots_base_idxs; // NOTE(rjf): [slots_count+1], [slots_count] holds total count RDI_U64 slots_count; }; //- rjf: source info & path tree typedef struct RDIM_BakePathNode RDIM_BakePathNode; struct RDIM_BakePathNode { RDIM_BakePathNode *next_order; RDIM_BakePathNode *parent; RDIM_BakePathNode *first_child; RDIM_BakePathNode *last_child; RDIM_BakePathNode *next_sibling; RDIM_String8 name; RDIM_SrcFile *src_file; RDI_U32 idx; }; typedef struct RDIM_BakeLineMapFragment RDIM_BakeLineMapFragment; struct RDIM_BakeLineMapFragment { RDIM_BakeLineMapFragment *next; RDIM_LineSequence *seq; }; typedef struct RDIM_BakePathTree RDIM_BakePathTree; struct RDIM_BakePathTree { RDIM_BakePathNode root; RDIM_BakePathNode *first; RDIM_BakePathNode *last; RDI_U32 count; }; //- rjf: name maps typedef struct RDIM_BakeName RDIM_BakeName; struct RDIM_BakeName { RDIM_String8 string; RDI_U64 hash; RDI_U64 idx; }; typedef struct RDIM_BakeNameChunkNode RDIM_BakeNameChunkNode; struct RDIM_BakeNameChunkNode { RDIM_BakeNameChunkNode *next; RDIM_BakeName *v; RDI_U64 count; RDI_U64 cap; RDI_U64 base_idx; }; typedef struct RDIM_BakeNameChunkList RDIM_BakeNameChunkList; struct RDIM_BakeNameChunkList { RDIM_BakeNameChunkNode *first; RDIM_BakeNameChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; }; typedef struct RDIM_BakeNameMapTopology RDIM_BakeNameMapTopology; struct RDIM_BakeNameMapTopology { RDI_U64 slots_count; }; typedef struct RDIM_BakeNameMap RDIM_BakeNameMap; struct RDIM_BakeNameMap { RDIM_BakeNameChunkList **slots; }; //- rjf: vmaps typedef struct RDIM_BakeVMap RDIM_BakeVMap; struct RDIM_BakeVMap { RDI_VMapEntry *vmap; // [count + 1] RDI_U32 count; }; typedef struct RDIM_VMapMarker RDIM_VMapMarker; struct RDIM_VMapMarker { RDI_U32 idx; RDI_U32 begin_range; }; //- rjf: source line maps typedef struct RDIM_BakeSrcLineMapNode RDIM_BakeSrcLineMapNode; struct RDIM_BakeSrcLineMapNode { RDIM_BakeSrcLineMapNode *next; RDI_U32 line_num; RDIM_Rng1U64List voff_ranges; }; typedef struct RDIM_BakeSrcLineMapSlot RDIM_BakeSrcLineMapSlot; struct RDIM_BakeSrcLineMapSlot { RDIM_BakeSrcLineMapNode *first; RDIM_BakeSrcLineMapNode *last; }; typedef struct RDIM_BakeSrcLineMap RDIM_BakeSrcLineMap; struct RDIM_BakeSrcLineMap { RDIM_BakeSrcLineMapSlot *slots; RDI_U64 slots_count; RDI_U64 line_count; RDI_U64 voff_range_count; }; //- rjf: line table records typedef struct RDIM_LineRec RDIM_LineRec; struct RDIM_LineRec { RDI_U32 file_id; RDI_U32 line_num; RDI_U16 col_first; RDI_U16 col_opl; }; //- rjf: baking results typedef struct RDIM_TopLevelInfoBakeResult RDIM_TopLevelInfoBakeResult; struct RDIM_TopLevelInfoBakeResult { RDI_TopLevelInfo top_level_info; }; typedef struct RDIM_BinarySectionBakeResult RDIM_BinarySectionBakeResult; struct RDIM_BinarySectionBakeResult { RDI_BinarySection *binary_sections; RDI_U64 binary_sections_count; }; typedef struct RDIM_UnitBakeResult RDIM_UnitBakeResult; struct RDIM_UnitBakeResult { RDI_Unit *units; RDI_U64 units_count; }; typedef struct RDIM_UnitVMapBakeResult RDIM_UnitVMapBakeResult; struct RDIM_UnitVMapBakeResult { RDIM_BakeVMap vmap; }; typedef struct RDIM_SrcFileBakeResult RDIM_SrcFileBakeResult; struct RDIM_SrcFileBakeResult { RDI_SourceFile *source_files; RDI_U64 source_files_count; RDI_SourceLineMap *source_line_maps; RDI_U64 source_line_maps_count; RDI_U32 *source_line_map_nums; RDI_U32 *source_line_map_rngs; RDI_U64 *source_line_map_voffs; RDI_U64 source_line_map_nums_count; RDI_U64 source_line_map_rngs_count; RDI_U64 source_line_map_voffs_count; }; typedef struct RDIM_ChecksumBakeResult RDIM_ChecksumBakeResult; struct RDIM_ChecksumBakeResult { RDI_MD5 *md5s; RDI_U64 md5s_count; RDI_SHA1 *sha1s; RDI_U64 sha1s_count; RDI_SHA256 *sha256s; RDI_U64 sha256s_count; RDI_U64 *timestamps; RDI_U64 timestamps_count; }; typedef struct RDIM_LineTableBakeResult RDIM_LineTableBakeResult; struct RDIM_LineTableBakeResult { RDI_LineTable *line_tables; RDI_U64 line_tables_count; RDI_U64 *line_table_voffs; RDI_U64 line_table_voffs_count; RDI_Line *line_table_lines; RDI_U64 line_table_lines_count; RDI_Column *line_table_columns; RDI_U64 line_table_columns_count; }; typedef struct RDIM_TypeNodeBakeResult RDIM_TypeNodeBakeResult; struct RDIM_TypeNodeBakeResult { RDI_TypeNode *type_nodes; RDI_U64 type_nodes_count; }; typedef struct RDIM_UDTBakeResult RDIM_UDTBakeResult; struct RDIM_UDTBakeResult { RDI_UDT *udts; RDI_U64 udts_count; RDI_Member *members; RDI_U64 members_count; RDI_EnumMember *enum_members; RDI_U64 enum_members_count; }; typedef struct RDIM_LocationBakeResult RDIM_LocationBakeResult; struct RDIM_LocationBakeResult { RDI_U8 *location_data; RDI_U64 location_data_size; }; typedef struct RDIM_LocationBlockBakeResult RDIM_LocationBlockBakeResult; struct RDIM_LocationBlockBakeResult { RDI_LocationBlock *location_blocks; RDI_U64 location_blocks_count; }; typedef struct RDIM_GlobalVariableBakeResult RDIM_GlobalVariableBakeResult; struct RDIM_GlobalVariableBakeResult { RDI_GlobalVariable *global_variables; RDI_U64 global_variables_count; }; typedef struct RDIM_GlobalVMapBakeResult RDIM_GlobalVMapBakeResult; struct RDIM_GlobalVMapBakeResult { RDIM_BakeVMap vmap; }; typedef struct RDIM_ThreadVariableBakeResult RDIM_ThreadVariableBakeResult; struct RDIM_ThreadVariableBakeResult { RDI_ThreadVariable *thread_variables; RDI_U64 thread_variables_count; }; typedef struct RDIM_ConstantsBakeResult RDIM_ConstantsBakeResult; struct RDIM_ConstantsBakeResult { RDI_Constant *constants; RDI_U64 constants_count; RDI_U32 *constant_values; RDI_U64 constant_values_count; RDI_U8 *constant_value_data; RDI_U64 constant_value_data_size; }; typedef struct RDIM_ProcedureBakeResult RDIM_ProcedureBakeResult; struct RDIM_ProcedureBakeResult { RDI_Procedure *procedures; RDI_U64 procedures_count; }; typedef struct RDIM_ScopeBakeResult RDIM_ScopeBakeResult; struct RDIM_ScopeBakeResult { RDI_Scope *scopes; RDI_U64 scopes_count; RDI_U64 *scope_voffs; RDI_U64 scope_voffs_count; RDI_Local *locals; RDI_U64 locals_count; }; typedef struct RDIM_ScopeVMapBakeResult RDIM_ScopeVMapBakeResult; struct RDIM_ScopeVMapBakeResult { RDIM_BakeVMap vmap; }; typedef struct RDIM_InlineSiteBakeResult RDIM_InlineSiteBakeResult; struct RDIM_InlineSiteBakeResult { RDI_InlineSite *inline_sites; RDI_U64 inline_sites_count; }; typedef struct RDIM_TopLevelNameMapBakeResult RDIM_TopLevelNameMapBakeResult; struct RDIM_TopLevelNameMapBakeResult { RDI_NameMap *name_maps; RDI_U64 name_maps_count; }; typedef struct RDIM_NameMapBakeResult RDIM_NameMapBakeResult; struct RDIM_NameMapBakeResult { RDI_NameMapBucket *buckets; RDI_U64 buckets_count; RDI_NameMapNode *nodes; RDI_U64 nodes_count; }; typedef struct RDIM_FilePathBakeResult RDIM_FilePathBakeResult; struct RDIM_FilePathBakeResult { RDI_FilePathNode *nodes; RDI_U64 nodes_count; }; typedef struct RDIM_StringBakeResult RDIM_StringBakeResult; struct RDIM_StringBakeResult { RDI_U32 *string_offs; RDI_U64 string_offs_count; RDI_U8 *string_data; RDI_U64 string_data_size; }; typedef struct RDIM_IndexRunBakeResult RDIM_IndexRunBakeResult; struct RDIM_IndexRunBakeResult { RDI_U32 *idx_runs; RDI_U64 idx_count; }; typedef struct RDIM_BakeResults RDIM_BakeResults; struct RDIM_BakeResults { RDIM_TopLevelInfoBakeResult top_level_info; RDIM_BinarySectionBakeResult binary_sections; RDIM_UnitBakeResult units; RDIM_UnitVMapBakeResult unit_vmap; RDIM_SrcFileBakeResult src_files; RDIM_ChecksumBakeResult checksums; RDIM_LineTableBakeResult line_tables; RDIM_TypeNodeBakeResult type_nodes; RDIM_UDTBakeResult udts; RDIM_GlobalVariableBakeResult global_variables; RDIM_GlobalVMapBakeResult global_vmap; RDIM_ThreadVariableBakeResult thread_variables; RDIM_ConstantsBakeResult constants; RDIM_ProcedureBakeResult procedures; RDIM_ScopeBakeResult scopes; RDIM_InlineSiteBakeResult inline_sites; RDIM_ScopeVMapBakeResult scope_vmap; RDIM_TopLevelNameMapBakeResult top_level_name_maps; RDIM_NameMapBakeResult name_maps; RDIM_FilePathBakeResult file_paths; RDIM_StringBakeResult strings; RDIM_IndexRunBakeResult idx_runs; RDIM_LocationBakeResult locations; RDIM_LocationBlockBakeResult location_blocks; }; //////////////////////////////// //~ rjf: Serialization Types typedef struct RDIM_SerializedSection RDIM_SerializedSection; struct RDIM_SerializedSection { void *data; RDI_U64 encoded_size; RDI_U64 unpacked_size; RDI_SectionEncoding encoding; }; typedef struct RDIM_SerializedSectionBundle RDIM_SerializedSectionBundle; struct RDIM_SerializedSectionBundle { RDIM_SerializedSection sections[RDI_SectionKind_COUNT]; }; //////////////////////////////// //~ rjf: Basic Helpers //- rjf: memory operations #if !defined(RDIM_MEMSET_OVERRIDE) RDI_PROC void *rdim_memset_fallback(void *dst, RDI_U8 c, RDI_U64 size); #endif #if !defined(RDIM_MEMCPY_OVERRIDE) RDI_PROC void *rdim_memcpy_fallback(void *dst, void *src, RDI_U64 size); #endif #define rdim_memzero(ptr, size) rdim_memset((ptr), 0, (size)) #define rdim_memzero_struct(ptr) rdim_memset((ptr), 0, sizeof(*(ptr))) #define rdim_memcpy_struct(dst, src) rdim_memcpy((dst), (src), sizeof(*(dst))) //- rjf: arenas #if !defined(RDIM_ARENA_OVERRIDE) RDI_PROC RDIM_Arena *rdim_arena_alloc_fallback(void); RDI_PROC void rdim_arena_release_fallback(RDIM_Arena *arena); RDI_PROC RDI_U64 rdim_arena_pos_fallback(RDIM_Arena *arena); RDI_PROC void *rdim_arena_push_fallback(RDIM_Arena *arena, RDI_U64 align, RDI_U64 size); RDI_PROC void rdim_arena_pop_to_fallback(RDIM_Arena *arena, RDI_U64 pos); #endif #define rdim_push_array_no_zero(a,T,c) (T*)rdim_arena_push((a), sizeof(T)*(c), RDIM_AlignOf(T), (0)) #define rdim_push_array(a,T,c) (T*)rdim_arena_push((a), sizeof(T)*(c), RDIM_AlignOf(T), (1)) //- rjf: thread-local scratch arenas #if !defined (RDIM_SCRATCH_OVERRIDE) RDI_PROC RDIM_Temp rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count); RDI_PROC void rdim_scratch_end_fallback(RDIM_Temp temp); #endif //- rjf: strings RDI_PROC RDIM_String8 rdim_str8(RDI_U8 *str, RDI_U64 size); RDI_PROC RDIM_String8 rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src); RDI_PROC RDIM_String8 rdim_str8f(RDIM_Arena *arena, char *fmt, ...); RDI_PROC RDIM_String8 rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args); RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags); #define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1) #define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) #define rdim_str8_struct_array(S, C) rdim_str8((RDI_U8*)(S), sizeof(*(S)) * (C)) RDI_PROC RDIM_String8 rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string); //- rjf: string lists RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); RDI_PROC void rdim_str8_list_push_front(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); RDI_PROC void rdim_str8_list_push_align(RDIM_Arena *arena, RDIM_String8List *list, RDI_U64 align); RDI_PROC RDIM_String8 rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 sep); //- rjf: sortable range sorting RDI_PROC RDIM_SortKey *rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count); //- rjf: rng1u64 lists RDI_PROC void rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r); RDI_PROC void rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkList *list, RDI_U64 chunk_cap, RDIM_Rng1U64 r); //////////////////////////////// //~ rjf: [Building] Data Model RDI_PROC RDI_TypeKind rdim_short_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_unsigned_short_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_int_type_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_long_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_unsigned_long_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_long_long_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_unsigned_long_long_type_kind_from_data_model(RDIM_DataModel data_model); RDI_PROC RDI_TypeKind rdim_pointer_size_t_type_kind_from_data_model(RDIM_DataModel data_model); //////////////////////////////// //~ rjf: [Building] Binary Section Info Building RDI_PROC RDIM_BinarySection *rdim_binary_section_list_push(RDIM_Arena *arena, RDIM_BinarySectionList *list); //////////////////////////////// //~ rjf: [Building] Source File Info Building RDI_PROC RDIM_SrcFile *rdim_src_file_chunk_list_push(RDIM_Arena *arena, RDIM_SrcFileChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_src_file(RDIM_SrcFile *src_file); RDI_PROC void rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFileChunkList *to_push); RDI_PROC void rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq); //////////////////////////////// //~ rjf: [Building] Line Info Building RDI_PROC RDIM_LineTable *rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_line_table(RDIM_LineTable *line_table); RDI_PROC void rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push); RDI_PROC RDIM_LineSequence *rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count); //////////////////////////////// //~ rjf: [Building] Unit Info Building RDI_PROC RDIM_Unit *rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_unit(RDIM_Unit *unit); RDI_PROC void rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList *to_push); //////////////////////////////// //~ rjf: [Building] Type Info & UDT Building //- rjf: type nodes RDI_PROC RDIM_Type *rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_type(RDIM_Type *type); RDI_PROC void rdim_type_chunk_list_concat_in_place(RDIM_TypeChunkList *dst, RDIM_TypeChunkList *to_push); //- rjf: UDTs RDI_PROC RDIM_UDT *rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_udt(RDIM_UDT *udt); RDI_PROC void rdim_udt_chunk_list_concat_in_place(RDIM_UDTChunkList *dst, RDIM_UDTChunkList *to_push); RDI_PROC RDIM_UDTMember *rdim_udt_push_member(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt); RDI_PROC RDIM_UDTEnumVal *rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDIM_UDT *udt); //////////////////////////////// //~ rjf: [Building] Symbol Info Building RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_symbol(RDIM_Symbol *symbol); RDI_PROC void rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push); internal void rdim_symbol_push_value_data(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDIM_Symbol *symbol, RDIM_String8 data); //////////////////////////////// //~ rjf: [Building] Inline Site Info Building RDI_PROC RDIM_InlineSite *rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_inline_site(RDIM_InlineSite *inline_site); RDI_PROC void rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push); //////////////////////////////// //~ rjf: [Building] Location Info Building //- rjf: bytecode RDI_PROC RDIM_EvalBytecodeOp * rdim_bytecode_push_op(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p); RDI_PROC void rdim_bytecode_push_uconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_U64 x); RDI_PROC void rdim_bytecode_push_sconst(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_S64 x); RDI_PROC void rdim_bytecode_push_convert(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode, RDI_EvalTypeGroup in, RDI_EvalTypeGroup out); RDI_PROC void rdim_bytecode_concat_in_place(RDIM_EvalBytecode *left_dst, RDIM_EvalBytecode *right_destroyed); RDI_PROC B32 rdim_is_bytecode_tls_dependent(RDIM_EvalBytecode bytecode); //- rjf: locations RDI_PROC RDI_U64 rdim_encoded_size_from_location_info(RDIM_LocationInfo *info); RDI_PROC RDIM_Location *rdim_location_chunk_list_push_new(RDIM_Arena *arena, RDIM_LocationChunkList *list, RDI_U64 cap, RDIM_LocationInfo *info); RDI_PROC RDI_U64 rdim_off_from_location(RDIM_Location *location); RDI_PROC void rdim_location_chunk_list_concat_in_place(RDIM_LocationChunkList *dst, RDIM_LocationChunkList *to_push); //////////////////////////////// //~ rjf: [Building] Scope Info Building RDI_PROC RDIM_Scope *rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_scope(RDIM_Scope *scope); RDI_PROC void rdim_scope_chunk_list_concat_in_place(RDIM_ScopeChunkList *dst, RDIM_ScopeChunkList *to_push); RDI_PROC void rdim_scope_push_voff_range(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDIM_Scope *scope, RDIM_Rng1U64 range); RDI_PROC RDIM_Local *rdim_scope_push_local(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *scope); RDI_PROC RDIM_LocationCase *rdim_local_push_location_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Local *local, RDIM_Location *location, RDIM_Rng1U64 voff_range); //////////////////////////////// //~ rjf: [Building] Bake Parameter Joining RDI_PROC void rdim_bake_params_concat_in_place(RDIM_BakeParams *dst, RDIM_BakeParams *src); //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated String Baking Map //- rjf: chunk lists RDI_PROC RDIM_BakeString *rdim_bake_string_chunk_list_push(RDIM_Arena *arena, RDIM_BakeStringChunkList *list, RDI_U64 cap); RDI_PROC void rdim_bake_string_chunk_list_concat_in_place(RDIM_BakeStringChunkList *dst, RDIM_BakeStringChunkList *to_push); RDI_PROC RDIM_BakeStringChunkList rdim_bake_string_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeStringChunkList *src); //- rjf: loose map RDI_PROC RDIM_BakeStringMapLoose *rdim_bake_string_map_loose_make(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top); RDI_PROC void rdim_bake_string_map_loose_insert(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map, RDI_U64 chunk_cap, RDIM_String8 string); RDI_PROC RDIM_BakeStringMapBaseIndices rdim_bake_string_map_base_indices_from_map_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapLoose *map); //- rjf: finalized / tight map RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string); //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Index Run Baking Map //- rjf: bake idx run map reading/writing RDI_PROC RDI_U64 rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count); //- rjf: chunk lists RDI_PROC RDIM_BakeIdxRun *rdim_bake_idx_run_chunk_list_push(RDIM_Arena *arena, RDIM_BakeIdxRunChunkList *list, RDI_U64 cap); RDI_PROC void rdim_bake_idx_run_chunk_list_concat_in_place(RDIM_BakeIdxRunChunkList *dst, RDIM_BakeIdxRunChunkList *to_push); RDI_PROC RDIM_BakeIdxRunChunkList rdim_bake_idx_run_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeIdxRunChunkList *src); //- rjf: loose map RDI_PROC RDIM_BakeIdxRunMapLoose *rdim_bake_idx_run_map_loose_make(RDIM_Arena *arena, RDIM_BakeIdxRunMapTopology *top); RDI_PROC void rdim_bake_idx_run_map_loose_insert(RDIM_Arena *arena, RDIM_BakeIdxRunMapTopology *map_topology, RDIM_BakeIdxRunMapLoose *map, RDI_U64 chunk_cap, RDI_U32 *idxes, RDI_U32 count); //- rjf: finalized / tight map RDI_PROC RDI_U32 rdim_bake_idx_from_idx_run(RDIM_BakeIdxRunMap *map, RDI_U32 *idxes, RDI_U32 count); //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Name Map Baking Map //- rjf: chunk lists RDI_PROC RDIM_BakeName *rdim_bake_name_chunk_list_push(RDIM_Arena *arena, RDIM_BakeNameChunkList *list, RDI_U64 cap); RDI_PROC void rdim_bake_name_chunk_list_concat_in_place(RDIM_BakeNameChunkList *dst, RDIM_BakeNameChunkList *to_push); RDI_PROC RDIM_BakeNameChunkList rdim_bake_name_chunk_list_sorted_from_unsorted(RDIM_Arena *arena, RDIM_BakeNameChunkList *src); //- rjf: bake name chunk list maps RDI_PROC RDIM_BakeNameMap *rdim_bake_name_map_make(RDIM_Arena *arena, RDIM_BakeNameMapTopology *top); RDI_PROC void rdim_bake_name_map_insert(RDIM_Arena *arena, RDIM_BakeNameMapTopology *map_topology, RDIM_BakeNameMap *map, RDI_U64 chunk_cap, RDIM_String8 string, RDI_U64 idx); //////////////////////////////// //~ rjf: [Baking Helpers] Deduplicated Path Baking Tree RDI_PROC RDIM_BakePathNode *rdim_bake_path_node_from_string(RDIM_BakePathTree *tree, RDIM_String8 string); RDI_PROC RDI_U32 rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string); RDI_PROC RDIM_BakePathNode *rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_String8 string); //////////////////////////////// //~ rjf: [Baking Helpers] Data Section List Building Helpers RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list); RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx); RDI_PROC void rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push); //////////////////////////////// //~ rjf: [Serializing] Bake Results -> String Blobs RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data, RDI_U64 size); #define rdim_serialized_section_make_unpacked_struct(ptr) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))) #define rdim_serialized_section_make_unpacked_array(ptr, count) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))*(count)) RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results); RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle); #endif // RDI_MAKE_H ================================================ FILE: src/linker/base_ext/base_arena.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 * push_u64(Arena *arena, U64 value) { U64 *result = push_array_no_zero(arena, U64, 1); *result = value; return result; } internal U32 * push_array_copy_u32(Arena *arena, U32 *v, U64 count) { U32 *result = push_array_no_zero(arena, U32, count); MemoryCopyTyped(result, v, count); return result; } internal U64 * push_array_copy_u64(Arena *arena, U64 *v, U64 count) { U64 *result = push_array_no_zero(arena, U64, count); MemoryCopyTyped(result, v, count); return result; } internal U64 ** push_matrix_u64(Arena *arena, U64 rows, U64 columns) { U64 **result = push_array_no_zero(arena, U64 *, rows); for (U64 row_idx = 0; row_idx < rows; row_idx += 1) { result[row_idx] = push_array(arena, U64, columns); } return result; } internal Arena ** alloc_fixed_size_arena_array(Arena *arena, U64 count, U64 res, U64 cmt) { U64 data_size = sizeof(count) + sizeof(Arena *) * count; U8 *data = push_array_no_zero(arena, U8, data_size); U64 *count_ptr = (U64 *)data; Arena **arr = (Arena **)(count_ptr + 1); *count_ptr = count; ArenaParams params = {0}; params.reserve_size = res; params.commit_size = cmt; for (U64 i = 0; i < count; i += 1) { Arena *fixed_arena = arena_alloc_(¶ms); arr[i] = fixed_arena; } return arr; } internal void release_arena_array(Arena **arr) { U64 *count_ptr = (U64 *)arr - 1; U64 count = *count_ptr; for (U64 i = 0; i < count; i += 1) { arena_release(arr[i]); arr[i] = 0; } } ================================================ FILE: src/linker/base_ext/base_arena.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal U64 * push_u64 (Arena *arena, U64 value); internal U32 * push_array_copy_u32(Arena *arena, U32 *v, U64 count); internal U64 * push_array_copy_u64(Arena *arena, U64 *v, U64 count); internal U64 ** push_matrix_u64 (Arena *arena, U64 rows, U64 columns); internal Arena ** alloc_fixed_size_arena_array(Arena *arena, U64 count, U64 res, U64 cmt); internal void release_arena_array(Arena **arr); ================================================ FILE: src/linker/base_ext/base_arrays.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 void_list_count_nodes(VoidNode *head) { U64 node_count = 0; for (VoidNode *curr = head; curr != 0; curr = curr->next) { ++node_count; } return node_count; } internal void void_node_concat(VoidNode **head, VoidNode *node) { Assert(*head != node); node->next = *head; *head = node; } internal void void_node_concat_atomic(VoidNode **head, VoidNode *node) { Assert(*head != node); node->next = ins_atomic_ptr_eval_assign(head, node); } internal U64Node * u64_list_push(Arena *arena, U64List *list, U64 data) { U64Node *n = push_array(arena, U64Node, 1); n->next = 0; n->data = data; SLLQueuePush(list->first, list->last, n); ++list->count; return n; } internal void u64_list_concat_in_place(U64List *list, U64List *to_concat) { SLLConcatInPlace(list, to_concat); } internal U64Array u64_array_from_list(Arena *arena, U64List *list) { U64Array result; result.count = 0; result.v = push_array(arena, U64, list->count); for (U64Node *n = list->first; n != NULL; n = n->next) { result.v[result.count++] = n->data; } return result; } internal void u32_array_sort(U64 count, U32 *v) { radsort(v, count, u32_is_before); } internal void u64_array_sort(U64 count, U64 *v) { radsort(v, count, u64_is_before); } internal void u32_pair_radix_sort(U64 count, PairU32 *arr) { Temp scratch = scratch_begin(0,0); PairU32 *temp = push_array(scratch.arena, PairU32, count); const U64 bit_count0 = 11; const U64 bit_count1 = 11; const U64 bit_count2 = 10; U32 *count0 = push_array(scratch.arena, U32, (1 << bit_count0)); U32 *count1 = push_array(scratch.arena, U32, (1 << bit_count1)); U32 *count2 = push_array(scratch.arena, U32, (1 << bit_count2)); for (U64 i = 0; i < count; ++i) { U32 digit0 = (arr[i].v0 >> 0 ) % (1 << bit_count0); U32 digit1 = (arr[i].v0 >> bit_count0) % (1 << bit_count1); U32 digit2 = (arr[i].v0 >> bit_count1) % (1 << bit_count2); ++count0[digit0]; ++count1[digit1]; ++count2[digit2]; } counts_to_offsets_array_u32((1 << bit_count0), count0); counts_to_offsets_array_u32((1 << bit_count1), count1); counts_to_offsets_array_u32((1 << bit_count2), count2); for (U64 i = 0; i < count; ++i) { U32 digit0 = (arr[i].v0 >> 0) % (1 << bit_count0); temp[count0[digit0]++] = arr[i]; } for (U64 i = 0; i < count; ++i) { U32 digit1 = (temp[i].v0 >> bit_count0) % (1 << bit_count1); arr[count1[digit1]++] = temp[i]; } for (U64 i = 0; i < count; ++i) { U32 digit2 = (arr[i].v0 >> bit_count1) % (1 << bit_count2); temp[count2[digit2]++] = arr[i]; } MemoryCopyTyped(arr, temp, count); scratch_end(scratch); } internal B32 u32_array_compare(U32Array a, U32Array b) { B32 are_equal = 0; if (a.count == b.count) { int cmp = MemoryCompare(a.v, b.v, sizeof(a.v[0]) * a.count); are_equal = (cmp == 0); } return are_equal; } internal U64Array u64_array_remove_duplicates(Arena *arena, U64Array in) { U64Array result; result.count = 0; result.v = push_array(arena, U64, in.count); for (U64 i = 1; i < in.count; ++i) { B32 is_unique = in.v[i - 1] != in.v[i]; if (is_unique) { result.v[result.count++] = in.v[i - 1]; } } if (in.count > 0 && result.count > 0) { B32 is_unique = result.v[result.count - 1] != in.v[in.count - 1]; if (is_unique) { result.v[result.count++] = in.v[in.count - 1]; } } U64 slack_size = (in.count - result.count) * sizeof(result.v[0]); arena_pop(arena, slack_size); return result; } internal U64 sum_array_u64(U64 count, U64 *v) { U64 result = 0; for (U64 i = 0; i < count; i += 1) { result += v[i]; } return result; } internal U64 sum_matrix_u64(U64 rows, U64 cols, U64 **v) { U64 result = 0; for (U64 i = 0; i < rows; ++i) { result += sum_array_u64(cols, v[i]); } return result; } internal U64 max_array_u64(U64 count, U64 *v) { U64 result = 0; for (U64 i = 0; i < count; i += 1) { result = Max(v[i], result); } return result; } internal U64 min_array_u64(U64 count, U64 *v) { U64 result = max_U64; for (U64 i = 0; i < count; i += 1) { result = Min(v[i], result); } return result; } internal void counts_to_offsets_array_u32(U64 count, U32 *arr) { U32 next_offset = 0; for (U64 i = 0; i < count; i += 1) { U32 current_offset = next_offset; next_offset += arr[i]; arr[i] = current_offset; } } internal void counts_to_offsets_array_u64(U64 count, U64 *arr) { U64 next_offset = 0; for (U64 i = 0; i < count; i += 1) { U64 current_offset = next_offset; next_offset += arr[i]; arr[i] = current_offset; } } internal U32 * offsets_from_counts_array_u32(Arena *arena, U32 *v, U64 count) { U32 *result = push_array_copy_u32(arena, v, count); counts_to_offsets_array_u32(count, result); return result; } internal U64 * offsets_from_counts_array_u64(Arena *arena, U64 *v, U64 count) { U64 *result = push_array_copy_u64(arena, v, count); counts_to_offsets_array_u64(count, result); return result; } ================================================ FILE: src/linker/base_ext/base_arrays.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef struct U32Node { struct U32Node *next; U32 data; } U32Node; typedef struct U64Node { struct U64Node *next; U64 data; } U64Node; typedef struct U64List { U64 count; U64Node *first; U64Node *last; } U64List; typedef struct VoidNode { struct VoidNode *next; void *v; } VoidNode; //////////////////////////////// internal U64Node * u64_list_push(Arena *arena, U64List *list, U64 data); internal void u64_list_concat_in_place(U64List *list, U64List *to_concat); internal U64Array u64_array_from_list(Arena *arena, U64List *list); internal U64Array u64_array_remove_duplicates(Arena *arena, U64Array in); internal void u32_array_sort(U64 count, U32 *v); internal void u64_array_sort(U64 count, U64 *v); internal B32 u32_array_compare(U32Array a, U32Array b); internal U64 sum_array_u64(U64 count, U64 *v); internal U64 max_array_u64(U64 count, U64 *v); internal U64 min_array_u64(U64 count, U64 *v); internal void counts_to_offsets_array_u32(U64 count, U32 *arr); internal void counts_to_offsets_array_u64(U64 count, U64 *arr); internal U32 * offsets_from_counts_array_u32(Arena *arena, U32 *v, U64 count); internal U64 * offsets_from_counts_array_u64(Arena *arena, U64 *v, U64 count); ================================================ FILE: src/linker/base_ext/base_bit_array.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U32Array bit_array_init32(Arena *arena, U64 word_count) { U32Array result; result.count = CeilIntegerDiv(word_count, 32); result.v = push_array(arena, U32, word_count); return result; } internal U64 bit_array_scan_left_to_right32(U32Array bit_array, U64 lo, U64 hi, B32 state) { Assert(lo < bit_array.count*32); Assert(hi <= bit_array.count*32); Assert(lo <= hi); Assert(state == 0 || state == 1); U64 word_lo = lo / 32; U64 word_hi = CeilIntegerDiv(hi, 32) - 1; U64 word_idx = word_lo; U64 bit_idx = 0; U64 scan_count = hi - lo; if (scan_count < 32) { U64 bit_lo = lo % 32; U64 bit_hi = hi % 32; U64 word = bit_array.v[word_idx]; word ^= state - 1; word &= (1U << bit_hi) - (1U << bit_lo); if (word) { bit_idx = ctz32(word); goto exit; } } else { U32 first_word = bit_array.v[word_idx]; first_word ^= state - 1; first_word &= ~0u << (lo % 32); if (first_word) { bit_idx = ctz32(first_word); goto exit; } for (word_idx += 1; word_idx < word_hi; word_idx += 1) { U32 word = bit_array.v[word_idx]; word ^= state - 1; if (word != 0) { bit_idx = ctz32(word); goto exit; } } U64 bit_hi = hi - (word_idx * 32); U32 last_word = bit_array.v[word_idx]; last_word ^= state - 1; last_word &= (1 << bit_hi) - 1; if (last_word) { bit_idx = ctz32(last_word); goto exit; } } word_idx = 0; bit_idx = max_U32; exit:; U64 result = word_idx * 32 + bit_idx; return result; } internal U64 bit_array_scan_right_to_left32(U32Array bit_array, U64 lo, U64 hi, B32 state) { Assert(lo <= hi); Assert(state == 0 || state == 1); S64 word_lo = lo / 32; S64 word_hi = CeilIntegerDiv(hi, 32) - 1; S64 word_idx = word_hi; S64 bit_idx = -1; U64 scan_count = hi - lo; if (scan_count < 32) { S64 bit_lo = lo % 32; S64 bit_hi = bit_lo + scan_count; U32 word = bit_array.v[word_idx]; for (bit_idx = bit_hi; bit_idx >= bit_lo; bit_idx -= 1) { U32 bit = ExtractBit(word, bit_idx); if (bit == state) { goto exit; } } } else { U32 last_word = bit_array.v[word_idx]; S64 bit_hi = hi % 32; for (bit_idx = bit_hi; bit_idx >= 0; bit_idx -= 1) { U32 bit = ExtractBit(last_word, bit_idx); if (bit == state) { goto exit; } } for (word_idx -= 1; word_idx > word_lo; word_idx -= 1) { U32 word = bit_array.v[word_idx]; for (bit_idx = 32 - 1; bit_idx >= 0; bit_idx -= 1) { U32 bit = ExtractBit(word, bit_idx); if (bit == state) { goto exit; } } } U32 first_word = bit_array.v[word_idx]; S64 bit_lo = lo % 32; for (bit_idx = 32 - 1; bit_idx >= bit_lo; bit_idx -= 1) { U32 bit = ExtractBit(first_word, bit_idx); if (bit == state) { goto exit; } } } word_idx = 0; bit_idx = max_U32; exit:; S64 result_s64 = word_idx * 32 + bit_idx; U64 result_u64 = (U64)result_s64; return result_u64; } internal Rng1U64 bit_array_scan_left_to_right32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count) { Rng1U64 result = rng_1u64(max_U64, max_U64); U64 curr_count = 0, rover = lo; while (curr_count < in_row_count) { rover = bit_array_scan_left_to_right32(bit_array, rover, hi, state); // no more bits in range if (rover >= hi) { break; } // set first match if (result.v[0] == max_U64) { result = rng_1u64(rover, rover); continue; } // reset on non-contiguous range B32 is_bit_index_not_adjoined = (result.v[0] + 1 < rover); if (is_bit_index_not_adjoined) { curr_count = 0; result = rng_1u64(max_U64, max_U64); continue; } // advance result.v[1] = rover; curr_count -= 1; } // did we allocate enough bits? if (curr_count != in_row_count) { result = rng_1u64(max_U64, max_U64); } return result; } internal Rng1U64 bit_array_scan_right_to_left32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count) { Rng1U64 result = rng_1u64(max_U64, max_U64); U64 curr_count = 0, rover = lo; while (curr_count < in_row_count) { rover = bit_array_scan_right_to_left32(bit_array, lo, rover, state); // no more bits in range if (rover >= hi) { break; } // set first match if (result.v[0] == max_U64) { result = rng_1u64(rover, rover); continue; } // reset on non-contiguous range B32 is_bit_index_not_adjoined = (result.v[0] + 1 < rover); if (is_bit_index_not_adjoined) { curr_count = 0; result = rng_1u64(max_U64, max_U64); continue; } // advance result.v[0] = rover; curr_count -= 1; } // did we allocate enough bits? if (curr_count != in_row_count) { result = rng_1u64(max_U64, max_U64); } return result; } internal U64 bit_array_find_next_unset_bit32(U32Array bit_array) { U64 result = bit_array_scan_left_to_right32(bit_array, 0, bit_array.count*32, 0); return result; } internal U64 bit_array_find_next_set_bit32(U32Array bit_array) { U64 result = bit_array_scan_left_to_right32(bit_array, 0, bit_array.count*32, 1); return result; } internal void bit_array_set_bit32(U32Array bit_array, U64 idx, B32 state) { Assert(idx < bit_array.count*32); U64 word_idx = idx / 32; U64 bit_idx = idx % 32; if (state) { bit_array.v[word_idx] |= (1 << bit_idx); } else { bit_array.v[word_idx] &= ~(1 << bit_idx); } } internal void bit_array_set_bit_range32(U32Array bit_array, Rng1U64 range, B32 state) { for (U64 idx = range.min ; idx < range.max; idx += 1) { bit_array_set_bit32(bit_array, idx, state); } } internal U32 bit_array_get_bit32(U32Array bit_array, U64 idx) { Assert(idx < bit_array.count*32); U64 word_idx = idx / 32; U64 bit_idx = idx % 32; U32 bit = (bit_array.v[word_idx] & (1 << bit_idx)) >> bit_idx; return bit; } internal B32 bit_array_is_bit_set(U32Array bit_arr, U64 bit_pos) { U64 word_idx = bit_pos / 32; Assert(word_idx < bit_arr.count); U32 word = bit_arr.v[word_idx]; U64 bit_idx = bit_pos % 32; B32 is_set = !!(word & (1 << bit_idx)); return is_set; } ================================================ FILE: src/linker/base_ext/base_bit_array.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal U32Array bit_array_init32 (Arena *arena, U64 word_count); internal U64 bit_array_scan_left_to_right32 (U32Array bit_array, U64 lo, U64 hi, B32 state); internal U64 bit_array_scan_right_to_left32 (U32Array bit_array, U64 lo, U64 hi, B32 state); internal Rng1U64 bit_array_scan_left_to_right32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count); internal Rng1U64 bit_array_scan_right_to_left32_contiguous(U32Array bit_array, U64 lo, U64 hi, B32 state, U64 in_row_count); internal B32 byte_scan_right_to_left (U8 *start, U8 *opl, U8 byte, U64 *offset_out); internal U64 bit_array_find_next_unset_bit32 (U32Array bit_array); internal U64 bit_array_find_next_set_bit32 (U32Array bit_array); internal void bit_array_set_bit32 (U32Array bit_array, U64 idx, B32 state); internal void bit_array_set_bit_range32 (U32Array bit_array, Rng1U64 range, B32 state); internal U32 bit_array_get_bit32 (U32Array bit_array, U64 idx); ================================================ FILE: src/linker/base_ext/base_blake3.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmacro-redefined" #pragma clang diagnostic ignored "-Wsign-conversion" #elif defined(_MSC_VER) #pragma warning (push, 0) #endif #include "third_party/blake3/c/blake3_portable.c" #if defined(_M_AMD64) || defined(__x86_64__) #define round_fn sse2_round_fn #define compress_pre sse2_compress_pre #include "third_party/blake3/c/blake3_sse2.c" #define loadu sse41_loadu #define storeu sse41_storeu #define addv sse41_addv #define xorv sse41_xorv #define set1 sse41_set1 #define set4 sse41_set4 #define rot16 sse41_rot16 #define rot12 sse41_rot12 #define rot8 sse41_rot8 #define rot7 sse41_rot7 #define g1 sse41_g1 #define g2 sse41_g2 #define diagonalize sse41_diagonalize #define undiagonalize sse41_undiagonalize #define compress_pre sse41_compress_pre #define round_fn sse41_round_fn #define transpose_vecs sse41_transpose_vecs #define transpose_msg_vecs sse41_transpose_msg_vecs #define load_counters sse41_load_counters #if defined(__clang__) #pragma clang attribute push(__attribute__((target("sse4.1"))), apply_to=function) #endif #include "third_party/blake3/c/blake3_sse41.c" #if defined(__clang__) #pragma clang attribute pop #endif #define loadu avx2_loadu #define storeu avx2_storeu #define addv avx2_addv #define xorv avx2_xorv #define set1 avx2_set1 #define rot7 avx2_rot7 #define rot8 avx2_rot8 #define rot12 avx2_rot12 #define rot16 avx2_rot16 #define round_fn avx2_round_fn #define transpose_vecs avx2_transpose_vecs #define transpose_msg_vecs avx2_transpose_msg_vecs #define load_counters avx2_load_counters #if defined(__clang__) #pragma clang attribute push(__attribute__((target("avx2"))), apply_to=function) #endif #include "third_party/blake3/c/blake3_avx2.c" #if defined(__clang__) #pragma clang attribute pop #endif #define set4 avx512_set4 #define g1 avx512_g1 #define g2 avx512_g2 #define diagonalize avx512_diagonalize #define undiagonalize avx512_undiagonalize #define compress_pre avx512_compress_pre #define transpose_vecs avx512_transpose_vecs #define transpose_msg_vecs avx512_transpose_msg_vecs #define load_counters avx512_load_counters #if defined(__clang__) #pragma clang attribute push(__attribute__((target("avx512f,avx512vl"))), apply_to=function) #endif #include "third_party/blake3/c/blake3_avx512.c" #if defined(__clang__) #pragma clang attribute pop #endif #endif #if defined(__aarch64__) || defined(_M_ARM64) #include "third_party/blake3/c/blake3_neon.c" #endif #include "third_party/blake3/c/blake3_dispatch.c" #include "third_party/blake3/c/blake3.c" #if defined(__clang__) #pragma clang diagnostic pop #elif defined(_MSC_VER) #pragma warning (pop, 0) #endif ================================================ FILE: src/linker/base_ext/base_blake3.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #define BLAKE3_API static #define BLAKE3_PRIVATE static #if defined(__clang__) && defined(__x86_64__) # if defined(__IMMINTRIN_H) # error "include this header before immintrin.h / x86intrin.h / intrin.h" # endif # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wreserved-macro-identifier" # pragma push_macro("__AVX__") # pragma push_macro("__AVX2__") # pragma push_macro("__SSE4_1__") # pragma push_macro("__AVX512F__") # pragma push_macro("__AVX512VL__") # define __AVX__ 1 # define __AVX2__ 1 # define __SSE4_1__ 1 # define __AVX512F__ 1 # define __AVX512VL__ 1 # include # pragma pop_macro("__AVX512VL__") # pragma pop_macro("__AVX512F__") # pragma pop_macro("__SSE4_1__") # pragma pop_macro("__AVX2__") # pragma pop_macro("__AVX__") # pragma clang diagnostic pop #endif #include "third_party/blake3/c/blake3.h" static void blake3(void* out, size_t outlen, void* in, size_t inlen) { blake3_hasher hasher; blake3_hasher_init(&hasher); blake3_hasher_update(&hasher, in, inlen); blake3_hasher_finalize(&hasher, (uint8_t*)out, outlen); } ================================================ FILE: src/linker/base_ext/base_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U16 safe_cast_u16x(U64 x) { AssertAlways(x <= max_U16); return (U16)x; } internal U64 u128_mod64(U128 a, U64 b) { return a.u64[1] % b; } internal Version make_version(U64 major, U64 minor) { Version version; version.major = major; version.minor = minor; return version; } internal int version_compar(Version a, Version b) { int cmp = 0; if (a.major < b.major) { cmp = -1; } else if (a.major > b.major) { cmp = +1; } else if (a.major == b.major) { if (a.minor < b.minor) { cmp = -1; } else if (a.minor > b.minor) { cmp = +1; } } return cmp; } internal ISectOff isect_off(U32 isect, U32 off) { ISectOff result = { isect, off }; return result; } internal int u16_compar(const void *raw_a, const void *raw_b) { U16 a = *(U16*)raw_a; U16 b = *(U16*)raw_b; int result = a < b ? -1 : a > b ? +1 : 0; return result; } internal int u32_compar(const void *raw_a, const void *raw_b) { U32 a = *(U32*)raw_a; U32 b = *(U32*)raw_b; int result = a < b ? -1 : a > b ? +1 : 0; return result; } internal int u64_compar(const void *raw_a, const void *raw_b) { U64 a = *(const U64*)raw_a; U64 b = *(const U64*)raw_b; int result = a < b ? -1 : a > b ? +1 : 0; return result; } internal int u64_compar_inv(const void *raw_a, const void *raw_b) { U64 a = *(const U64*)raw_a; U64 b = *(const U64*)raw_b; int result = a < b ? +1 : a > b ? -1 : 0; return result; } internal int u16_compar_is_before(void *raw_a, void *raw_b) { U16 *a = (U16 *)raw_a; U16 *b = (U16 *)raw_b; int is_before = *a < *b; return is_before; } internal int u32_compar_is_before(void *raw_a, void *raw_b) { U32 *a = (U32 *)raw_a; U32 *b = (U32 *)raw_b; int is_before = *a < *b; return is_before; } internal int u64_compar_is_before(void *raw_a, void *raw_b) { U64 *a = (U64 *)raw_a; U64 *b = (U64 *)raw_b; int is_before = *a < *b; return is_before; } internal int u8_is_before(void *raw_a, void *raw_b) { U8 *a = (U8 *) raw_a; U8 *b = (U8 *) raw_b; return *a < *b; } internal int u16_is_before(void *raw_a, void *raw_b) { U16 *a = (U16 *) raw_a; U16 *b = (U16 *) raw_b; return *a < *b; } internal int u32_is_before(void *raw_a, void *raw_b) { U32 *a = (U32 *) raw_a; U32 *b = (U32 *) raw_b; return *a < *b; } internal int u64_is_before(void *raw_a, void *raw_b) { U64 *a = (U64 *) raw_a; U64 *b = (U64 *) raw_b; return *a < *b; } internal int pair_u32_is_before_v0(void *raw_a, void *raw_b) { PairU32 *a = raw_a; PairU32 *b = raw_b; return a->v0 < b->v0; } internal int pair_u32_is_before(void *raw_a, void *raw_b) { PairU32 *a = raw_a; PairU32 *b = raw_b; return a->v1 < b->v1; } internal int pair_u64_is_before_v0(void *raw_a, void *raw_b) { PairU64 *a = raw_a; PairU64 *b = raw_b; return a->v0 < b->v0; } internal int pair_u64_is_before_v1(void *raw_a, void *raw_b) { PairU64 *a = raw_a; PairU64 *b = raw_b; return a->v1 < b->v1; } internal int pair_u32_compar_v0(const void *raw_a, const void *raw_b) { const PairU32 *a = raw_a; const PairU32 *b = raw_b; return u32_compar(&a->v0, &b->v0); } internal int pair_u64_compar_v0(const void *raw_a, const void *raw_b) { const PairU64 *a = raw_a; const PairU64 *b = raw_b; return u64_compar(&a->v0, &b->v0); } internal int pair_u64_compar_v1(const void *raw_a, const void *raw_b) { const PairU64 *a = raw_a; const PairU64 *b = raw_b; return u64_compar(&a->v1, &b->v1); } internal U64 pair_u64_nearest_v0(PairU64 *arr, U64 count, U64 v) { U64 result = max_U64; if (count > 1 && arr[0].v0 <= v && v < arr[count-1].v0) { U64 l = 0; U64 r = count - 1; for (; l <= r; ) { U64 m = l + (r - l) / 2; if (arr[m].v0 == v) { return m; } else if (arr[m].v0 < v) { l = m + 1; } else { r = m - 1; } } result = l; } else if (count == 1 && arr[0].v0 == v) { result = 0; } else if (count > 0 && v >= arr[count-1].v0) { result = count-1; } return result; } internal void str8_list_concat_in_place_array(String8List *list, String8List *arr, U64 count) { for (U64 i = 0; i < count; ++i) { str8_list_concat_in_place(list, &arr[i]); } } ================================================ FILE: src/linker/base_ext/base_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #if COMPILER_MSVC # define COMPILER_STRING "MSVC" #elif COMPILER_CLANG # define COMPILER_STRING "Clang" #elif COMPILER_GCC # define COMPILER_STRING "GCC" #else # error "undefined compiler string" #endif #if BUILD_DEBUG # define BUILD_MODE_STRING "Debug" #else # define BUILD_MODE_STRING "Release" #endif //////////////////////////////// #define BitExtract(x, count, shift) (((x) >> (shift)) & ((1 << (count)) - 1)) //////////////////////////////// // Linked List Helpers #define DLLConcatInPlace(list, to_concat) do { \ if ((to_concat)->count) { \ if ((list)->count) { \ (list)->last->next = (to_concat)->first; \ (to_concat)->first->prev = (list)->last; \ (list)->last = (to_concat)->last; \ } else { \ (list)->first = (to_concat)->first; \ (list)->last = (to_concat)->last; \ } \ (list)->count += (to_concat)->count; \ MemoryZeroStruct(to_concat); \ } \ } while (0) #define DLLConcatInPlaceArray(list, to_concat_arr, count) for (U64 i = 0; i < (count); i += 1) { DLLConcatInPlace(list, &(to_concat_arr)[i]); } #define SLLQueuePushCount(list, node) do { \ SLLQueuePush((list)->first, (list)->last, node); \ ++(list)->count; \ } while (0) #define SLLConcatInPlaceNoCount(list, to_concat) do { \ if ((to_concat)->first) { \ if ((list)->first) { \ (list)->last->next = (to_concat)->first; \ (list)->last = (to_concat)->last; \ } else { \ (list)->first = (to_concat)->first; \ (list)->last = (to_concat)->last; \ } \ MemoryZeroStruct(to_concat); \ } \ } while (0) #define SLLConcatInPlace(list, to_concat) do { \ if ((to_concat)->count) { \ if ((list)->count) { \ (list)->last->next = (to_concat)->first; \ (list)->last = (to_concat)->last; \ } else { \ (list)->first = (to_concat)->first; \ (list)->last = (to_concat)->last; \ } \ (list)->count += (to_concat)->count; \ MemoryZeroStruct(to_concat); \ } \ } while (0) #define SLLConcatInPlaceArray(list, to_concat_arr, count) for (U64 i = 0; i < (count); ++i) { SLLConcatInPlace(list, &(to_concat_arr)[i]); } #define SLLConcatInPlaceChunkList(list, to_concat, chunk_type) do { \ if ((list)->last != 0) { \ U64 base_cursor = (list)->last->base + (list)->last->count; \ for (chunk_type *c = (to_concat)->first; c != 0; c = c->next) { \ c->base = base_cursor; \ base_cursor += c->count; \ } \ } \ SLLConcatInPlace(list, to_concat); \ } while (0) #define SLLConcatInPlaceChunkListArray(list, to_concat_arr, type, count) for (U64 i = 0; i < (count); ++i) { SLLConcatInPlaceChunkList(list, &(to_concat_arr)[i], type); } #define SLLChunkListPush(_arena, _list, _cap, _value_type) do { \ if ((_list)->last == 0 || (_list)->last->count >= (_list)->last->cap) { \ _value_type##Chunk *new_chunk = push_array(_arena, _value_type##Chunk, 1); \ new_chunk->v = push_array(_arena, _value_type, _cap); \ new_chunk->cap = _cap; \ new_chunk->base = (_list)->last ? (_list)->last->base + (_list)->last->cap : 0; \ SLLQueuePushCount(_list, new_chunk); \ } \ _value_type *v = &(_list)->last->v[(_list)->last->count++]; \ v->chunk = (_list)->last; \ } while (0) #define SLLChunkListPushZero(_arena, _list, _cap, _value_type) do { \ SLLChunkListPush(_arena, _list, _cap, _value_type); \ MemoryZeroStruct(SLLChunkListLastItem(_list)); \ SLLChunkListLastItem(_list)->chunk = (_list)->last; \ } while(0) #define SLLChunkListLastItem(_list) (&(_list)->last->v[(_list)->last->count - 1]) //////////////////////////////// typedef struct { U64 major; U64 minor; } Version; //////////////////////////////// typedef struct ISectOff { U32 isect; U32 off; } ISectOff; //////////////////////////////// typedef struct PairU32 { U32 v0; U32 v1; } PairU32; typedef struct PairU64 { U64 v0; U64 v1; } PairU64; //////////////////////////////// internal U16 safe_cast_u16x(U64 x); //////////////////////////////// internal U64 u128_mod64(U128 a, U64 b); //////////////////////////////// internal Version make_version(U64 major, U64 minor); internal int version_compar(Version a, Version b); //////////////////////////////// internal ISectOff isect_off(U32 isect, U32 off); //////////////////////////////// internal int u16_compar(const void *raw_a, const void *raw_b); internal int u32_compar(const void *raw_a, const void *raw_b); internal int u64_compar(const void *raw_a, const void *raw_b); internal int u8_is_before(void *raw_a, void *raw_b); internal int u16_is_before(void *raw_a, void *raw_b); internal int u32_is_before(void *raw_a, void *raw_b); internal int u64_is_before(void *raw_a, void *raw_b); internal int pair_u32_is_before_v0(void *raw_a, void *raw_b); internal int pair_u32_is_before_v1(void *raw_a, void *raw_b); internal int pair_u64_is_before_v0(void *raw_a, void *raw_b); internal int pair_u64_is_before_v1(void *raw_a, void *raw_b); //////////////////////////////// internal void str8_list_concat_in_place_array(String8List *list, String8List *arr, U64 count); ================================================ FILE: src/linker/base_ext/base_crc32.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U32 update_crc32(U32 crc, U8 *ptr, U64 size) { // CRC-32 algo borrowed from stb.h local_persist U32 crc_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #if 0 for (U32 i = 0; i < 256; ++i) { U32 s = i; for (U32 j = 0; j < 8; ++j) { s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0); } crc_table[i] = s; } #endif crc = ~crc; for (U32 i = 0; i < size; ++i) { crc = (crc >> 8) ^ crc_table[(ptr[i] ^ crc) & 0xff]; } return ~crc; } internal U32 crc32_from_string(String8 string) { return update_crc32(0, string.str, string.size); } ================================================ FILE: src/linker/base_ext/base_crc32.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal U32 update_crc32(U32 crc, U8 *ptr, U64 size); internal U32 crc32_from_string(String8 string); ================================================ FILE: src/linker/base_ext/base_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "base_core.c" #include "base_strings.c" #include "base_arena.c" #include "base_arrays.c" #include "base_bit_array.c" #include "base_crc32.c" ================================================ FILE: src/linker/base_ext/base_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #include "base_core.h" #include "base_strings.h" #include "base_arena.h" #include "base_arrays.h" #include "base_blake3.h" #include "base_bit_array.h" #include "base_crc32.h" ================================================ FILE: src/linker/base_ext/base_strings.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 str8_starts_with(String8 string, String8 expected_prefix) { return str8_match(str8_prefix(string, expected_prefix.size), expected_prefix, 0); } internal String8Node * str8_list_pop_front(String8List *list) { String8Node *node = 0; if (list->node_count) { node = list->first; Assert(list->total_size >= list->first->string.size); list->node_count -= 1; list->total_size -= list->first->string.size; SLLQueuePop(list->first, list->last); } return node; } internal U64 str8_array_bsearch(String8Array arr, String8 value) { if (arr.count > 1) { int lo_compar = str8_compar_case_sensitive(&value, &arr.v[0]); if (lo_compar == 0) { return 0; } int hi_compar = str8_compar_case_sensitive(&value, &arr.v[arr.count-1]); if (hi_compar == 0){ return arr.count-1; } if (lo_compar > 0 && hi_compar < 0) { for (U64 l = 0, r = arr.count -1; l <= r; ) { U64 m = l + (r- l) / 2; int cmp = str8_compar_case_sensitive(&arr.v[m], &value); if (cmp == 0) { return m; } else if (cmp < 0) { l = m + 1; } else { r = m - 1; } } } } else if (arr.count == 1 && str8_match(arr.v[0], value, 0)) { return 0; } return max_U64; } ================================================ FILE: src/linker/base_ext/base_strings.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once // TODO: remove internal String8Node * str8_list_pop_front(String8List *list); internal B32 str8_starts_with(String8 string, String8 expected_prefix); internal U64 str8_array_bsearch(String8Array arr, String8 value); ================================================ FILE: src/linker/codeview_ext/codeview.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// internal U64 hash_from_cv_symbol(CV_Symbol *symbol) { XXH3_state_t hasher; XXH3_64bits_reset(&hasher); XXH3_64bits_update(&hasher, &symbol->kind, sizeof(symbol->kind)); XXH3_64bits_update(&hasher, &symbol->data.size, sizeof(symbol->data.size)); XXH3_64bits_update(&hasher, symbol->data.str, symbol->data.size); XXH64_hash_t hash = XXH3_64bits_digest(&hasher); return hash; } //////////////////////////////// internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol) { CV_ObjInfo result; MemoryZeroStruct(&result); switch (symbol.kind) { case CV_SymKind_OBJNAME: { CV_SymObjName *obj_name = (CV_SymObjName *) symbol.data.str; result.sig = obj_name->sig; str8_deserial_read_cstr(symbol.data, sizeof(CV_SymObjName), &result.name); } break; case CV_SymKind_OBJNAME_ST: { NotImplemented; } break; default: { InvalidPath; } break; } return result; } internal CV_TypeServerInfo cv_type_server_info_from_leaf(CV_Leaf leaf) { CV_TypeServerInfo result = {0}; switch (leaf.kind) { case CV_LeafKind_TYPESERVER: { CV_LeafTypeServer *ts = (CV_LeafTypeServer *) leaf.data.str; result.name = str8_cstring_capped_reverse(ts + 1, leaf.data.str + leaf.data.size); result.sig.data1 = ts->sig; result.age = ts->age; } break; case CV_LeafKind_TYPESERVER2: { CV_LeafTypeServer2 *ts = (CV_LeafTypeServer2 *) leaf.data.str; Assert(sizeof(result.sig) == sizeof(ts->sig70)); MemoryCopy(&result.sig, &ts->sig70, sizeof(ts->sig70)); result.name = str8_cstring_capped_reverse(ts + 1, leaf.data.str + leaf.data.size); result.age = ts->age; } break; case CV_LeafKind_TYPESERVER_ST: { Assert("TODO: LF_TYPESERVER_ST"); } break; default: InvalidPath; } return result; } internal CV_PrecompInfo cv_precomp_info_from_leaf(CV_Leaf leaf) { CV_PrecompInfo result = {0}; switch (leaf.kind) { case CV_LeafKind_PRECOMP: { CV_LeafPreComp *precomp = (CV_LeafPreComp*)leaf.data.str; result.start_index = precomp->start_index; result.sig = precomp->sig; result.leaf_count = precomp->count; str8_deserial_read_cstr(leaf.data, sizeof(CV_LeafPreComp), &result.obj_name); } break; case CV_LeafKind_PRECOMP_16t: { NotImplemented; } break; case CV_LeafKind_PRECOMP_ST: { NotImplemented; } break; default: { InvalidPath; } break; } return result; } //////////////////////////////// //~ Leaf Helpers internal U64 cv_compute_leaf_record_size(String8 data, U64 align) { U64 size = 0; size += sizeof(CV_LeafSize); size += sizeof(CV_LeafKind); size += data.size; size = AlignPow2(size, align); return size; } internal U64 cv_serialize_leaf_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_LeafKind kind, String8 data, U64 align) { U64 buffer_cursor_start = buffer_cursor; // compute record size U64 record_size = sizeof(kind) + data.size; Assert(record_size <= CV_LeafSize_Max); CV_LeafSize record_size16 = (CV_LeafSize)record_size; // compute pad static U8 LEAF_PAD_ARR[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; U64 pad_size = AlignPadPow2(data.size, align); Assert(pad_size <= ArrayCount(LEAF_PAD_ARR)); // write header CV_LeafHeader *header_ptr = (CV_LeafHeader *)(buffer + buffer_cursor); header_ptr->size = record_size16; header_ptr->kind = kind; buffer_cursor += sizeof(*header_ptr); // write body U8 *leaf_data_ptr = buffer + buffer_cursor; MemoryCopy(leaf_data_ptr, data.str, data.size); buffer_cursor += data.size; // write pad U8 *pad_data_ptr = buffer + buffer_cursor; MemoryCopy(pad_data_ptr, &LEAF_PAD_ARR[0], pad_size); buffer_cursor += pad_size; U64 write_size = buffer_cursor - buffer_cursor_start; return write_size; } internal String8 cv_serialize_raw_leaf(Arena *arena, CV_LeafKind kind, String8 data, U64 align) { U64 buffer_size = cv_compute_leaf_record_size(data, align); U8 *buffer = push_array_no_zero(arena, U8, buffer_size); U64 size = cv_serialize_leaf_to_buffer(buffer, 0, buffer_size, kind, data, align); String8 raw_leaf = str8(buffer, size); return raw_leaf; } internal String8 cv_serialize_leaf(Arena *arena, CV_Leaf *leaf, U64 align) { return cv_serialize_raw_leaf(arena, leaf->kind, leaf->data, align); } internal CV_Leaf cv_make_leaf(Arena *arena, CV_LeafKind kind, String8 data) { CV_Leaf result = {0}; String8 raw_leaf = cv_serialize_raw_leaf(arena, kind, data, 1); cv_deserial_leaf(raw_leaf, 0, 1, &result); return result; } internal U64 cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out) { // do we have enough bytes to read header? Assert(raw_data.size >= sizeof(CV_LeafHeader)); CV_LeafHeader *header = (CV_LeafHeader*)(raw_data.str + off); // leaf size must have enough bytes for the kind enum Assert(header->size >= sizeof(CV_LeafKind)); // do we have enough bytes to read leaf data? Assert(sizeof(CV_LeafSize) + header->size <= raw_data.size); // fill out leaf leaf_out->kind = header->kind; leaf_out->data = str8(raw_data.str + sizeof(CV_LeafHeader), header->size - sizeof(CV_LeafKind)); U64 leaf_size = AlignPow2(sizeof(CV_LeafHeader) + leaf_out->data.size, align); Assert(leaf_size <= raw_data.size); return leaf_size; } internal CV_Leaf cv_leaf_from_string(String8 raw_data) { CV_Leaf result; cv_deserial_leaf(raw_data, 0, 1, &result); return result; } //////////////////////////////// //~ Symbol Helpers internal U64 cv_compute_symbol_record_size(CV_Symbol *symbol, U64 align) { U64 size = 0; size += sizeof(CV_SymSize); size += sizeof(CV_SymKind); size += AlignPow2(symbol->data.size, align); return size; } internal U64 cv_serialize_symbol_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_Symbol *symbol, U64 align) { U64 write_size = cv_compute_symbol_record_size(symbol, align); Assert(buffer_cursor + write_size <= buffer_size); U64 record_size = 0; record_size += sizeof(symbol->kind); record_size += AlignPow2(symbol->data.size, align); Assert(record_size <= CV_SymSize_Max); CV_SymSize record_size16 = (CV_SymSize)record_size; // init header CV_SymbolHeader *header = (CV_SymbolHeader *)(buffer + buffer_cursor); header->size = record_size16; header->kind = symbol->kind; // copy symbol data U8 *data_dst = (U8 *)(header + 1); MemoryCopy(data_dst, symbol->data.str, symbol->data.size); // set pad bytes U64 pad_size = AlignPadPow2(symbol->data.size, align); U8 *pad_dst = data_dst + symbol->data.size; MemorySet(&pad_dst[0], 0, pad_size); return write_size; } internal String8 cv_serialize_symbol(Arena *arena, CV_Symbol *symbol, U64 align) { U64 buffer_size = cv_compute_symbol_record_size(symbol, align); U8 *buffer = push_array(arena, U8, buffer_size); cv_serialize_symbol_to_buffer(buffer, 0, buffer_size, symbol, align); String8 result = str8(buffer, buffer_size); return result; } internal String8 cv_make_symbol(Arena *arena, CV_SymKind kind, String8 data) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); AssertAlways((data.size + sizeof(kind)) <= CV_SymSize_Max); CV_SymSize symbol_size = (CV_SymSize)data.size + sizeof(kind); String8List srl = {0}; str8_serial_begin(scratch.arena, &srl); str8_serial_push_struct(scratch.arena, &srl, &symbol_size); str8_serial_push_struct(scratch.arena, &srl, &kind); str8_serial_push_string(scratch.arena, &srl, data); String8 symbol = str8_serial_end(arena, &srl); scratch_end(scratch); ProfEnd(); return symbol; } internal String8 cv_make_obj_name(Arena *arena, String8 obj_path, U32 sig) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); CV_SymObjName obj = {0}; obj.sig = sig; String8List serial = {0}; str8_serial_begin(scratch.arena, &serial); str8_serial_push_struct(scratch.arena, &serial, &obj); str8_serial_push_cstr(scratch.arena, &serial, obj_path); String8 result = str8_serial_end(arena, &serial); scratch_end(scratch); ProfEnd(); return result; } internal String8 cv_make_comp3(Arena *arena, CV_Compile3Flags flags, CV_Language lang, CV_Arch arch, U16 ver_fe_major, U16 ver_fe_minor, U16 ver_fe_build, U16 ver_feqfe, U16 ver_major, U16 ver_minor, U16 ver_build, U16 ver_qfe, String8 version_string) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); CV_SymCompile3 comp = {0}; comp.flags = flags | lang; comp.machine = arch; comp.ver_fe_major = ver_fe_major; comp.ver_fe_minor = ver_fe_minor; comp.ver_fe_build = ver_fe_build; comp.ver_feqfe = ver_feqfe; comp.ver_major = ver_major; comp.ver_minor = ver_minor; comp.ver_build = ver_build; comp.ver_qfe = ver_qfe; String8List serial = {0}; str8_serial_begin(scratch.arena, &serial); str8_serial_push_struct(scratch.arena, &serial, &comp); str8_serial_push_cstr(scratch.arena, &serial, version_string); String8 result = str8_serial_end(arena, &serial); scratch_end(scratch); ProfEnd(); return result; } internal String8 cv_make_envblock(Arena *arena, String8List string_list) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); String8List serial = {0}; str8_serial_begin(scratch.arena, &serial); CV_SymEnvBlock envblock = {0}; str8_serial_push_struct(scratch.arena, &serial, &envblock); for (String8Node *n = string_list.first; n != NULL; n = n->next) { str8_serial_push_cstr(scratch.arena, &serial, n->string); } String8 result = str8_serial_end(arena, &serial); scratch_end(scratch); ProfEnd(); return result; } internal CV_Symbol cv_make_proc_ref(Arena *arena, CV_ModIndex imod, U32 stream_offset, String8 name, B32 is_local) { U64 buffer_size = sizeof(CV_SymRef2) + name.size + 1; U8 *buffer = push_array_no_zero(arena, U8, buffer_size); CV_SymRef2 *ref = (CV_SymRef2*)buffer; ref->suc_name = 0; ref->sym_off = stream_offset; ref->imod = imod + 1; // MSVC adds one U8 *name_ptr = (U8*)(ref + 1); MemoryCopy(name_ptr, name.str, name.size); name_ptr[name.size] = '\0'; CV_Symbol symbol; symbol.kind = is_local ? CV_SymKind_LPROCREF : CV_SymKind_PROCREF; symbol.data = str8(buffer, buffer_size); symbol.offset = max_U64; return symbol; } internal CV_Symbol cv_make_pub32(Arena *arena, CV_Pub32Flags flags, U32 off, U16 isect, String8 name) { U64 buffer_size = sizeof(CV_SymPub32) + name.size + 1; U8 *buffer = push_array_no_zero(arena, U8, buffer_size); CV_SymPub32 *pub = (CV_SymPub32 *)buffer; pub->flags = flags; pub->off = off; pub->sec = isect; U8 *name_ptr = (U8*)(pub + 1); MemoryCopy(name_ptr, name.str, name.size); name_ptr[name.size] = '\0'; CV_Symbol symbol; symbol.kind = CV_SymKind_PUB32; symbol.data = str8(buffer, buffer_size); return symbol; } internal CV_SymbolList cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_SymbolList symbol_list) { CV_SymbolList proc_ref_list = {0}; for (CV_SymbolNode *symbol_node = symbol_list.first; symbol_node != 0; symbol_node = symbol_node->next) { CV_Symbol *symbol = &symbol_node->data; if (symbol->kind == CV_SymKind_GPROC32) { String8 name = cv_name_from_symbol(symbol->kind, symbol->data); CV_Symbol ref = cv_make_proc_ref(arena, imod, safe_cast_u32(symbol->offset), name, /* is_local: */ 0); CV_SymbolNode *proc_ref_node = cv_symbol_list_push(arena, &proc_ref_list); proc_ref_node->data = ref; } else if (symbol->kind == CV_SymKind_LPROC32) { String8 name = cv_name_from_symbol(symbol->kind, symbol->data); CV_Symbol ref = cv_make_proc_ref(arena, imod, safe_cast_u32(symbol->offset), name, /* is_local */ 1); CV_SymbolNode *proc_ref_node = cv_symbol_list_push(arena, &proc_ref_list); proc_ref_node->data = ref; } } return proc_ref_list; } //////////////////////////////// //~ .debug$S helpers internal void cv_parse_debug_s_c13_(Arena *arena, CV_DebugS *debug_s, String8 raw_debug_s) { for (U64 cursor = 0; cursor + sizeof(CV_C13SubSectionHeader) <= raw_debug_s.size; ) { // read header CV_C13SubSectionHeader header = {0}; cursor += str8_deserial_read_struct(raw_debug_s, cursor, &header); if (~header.kind & CV_C13SubSectionKind_IgnoreFlag) { // pick sub-section list U64 sub_sect_idx = cv_c13_sub_section_idx_from_kind(header.kind); String8List *sub_sect_list = debug_s->data_list + sub_sect_idx; // push data to sub-section Rng1U64 sub_sect_range = r1u64(cursor, cursor + header.size); String8 sub_sect_data = str8_substr(raw_debug_s, sub_sect_range); str8_list_push(arena, sub_sect_list, sub_sect_data); } // advance cursor += header.size; cursor = AlignPow2(cursor, CV_C13SubSectionAlign); } } internal CV_DebugS cv_parse_debug_s_c13(Arena *arena, String8 raw_debug_s) { CV_DebugS debug_s = {0}; cv_parse_debug_s_c13_(arena, &debug_s, raw_debug_s); return debug_s; } internal CV_DebugS cv_parse_debug_s_c13_list(Arena *arena, String8List raw_debug_s) { CV_DebugS debug_s = {0}; for (String8Node *node = raw_debug_s.first; node != 0; node = node->next) { cv_parse_debug_s_c13_(arena, &debug_s, node->string); } return debug_s; } internal CV_DebugS cv_parse_debug_s(Arena *arena, String8 raw_debug_s) { CV_DebugS result; MemoryZeroStruct(&result); if (raw_debug_s.size >= sizeof(CV_Signature)) { CV_Signature sig = *(CV_Signature *)raw_debug_s.str; switch (sig) { case CV_Signature_C13: { String8 raw_debug_s_past_sig = str8_substr(raw_debug_s, r1u64(sizeof(sig), raw_debug_s.size)); result = cv_parse_debug_s_c13(arena, raw_debug_s_past_sig); } break; case CV_Signature_C6: { Assert(!"TODO: handle C6"); } break; case CV_Signature_C7: { Assert(!"TODO: handle C7"); } break; case CV_Signature_C11: { Assert(!"TODO: handle C11"); } break; default: Assert(!"invalid signature"); break; } } return result; } internal void cv_debug_s_concat_in_place(CV_DebugS *dst, CV_DebugS *src) { for (U64 sub_sect_idx = 0; sub_sect_idx < ArrayCount(dst->data_list); sub_sect_idx += 1) { str8_list_concat_in_place(&dst->data_list[sub_sect_idx], &src->data_list[sub_sect_idx]); } } internal String8List cv_data_c13_from_debug_s(Arena *arena, CV_DebugS *debug_s, B32 write_sig) { String8List srl = {0}; str8_serial_begin(arena, &srl); if (write_sig) { CV_Signature sig = CV_Signature_C13; str8_serial_push_struct(arena, &srl, &sig); } static CV_C13SubSectionKind layout_arr[] = { CV_C13SubSectionKind_Symbols, //CV_C13SubSectionKind_Lines, CV_C13SubSectionKind_FileChksms, CV_C13SubSectionKind_FrameData, CV_C13SubSectionKind_InlineeLines, CV_C13SubSectionKind_IlLines, CV_C13SubSectionKind_CrossScopeImports, CV_C13SubSectionKind_CrossScopeExports, CV_C13SubSectionKind_FuncMDTokenMap, CV_C13SubSectionKind_TypeMDTokenMap, CV_C13SubSectionKind_MergedAssemblyInput, CV_C13SubSectionKind_CoffSymbolRVA, CV_C13SubSectionKind_XfgHashType, CV_C13SubSectionKind_XfgHashVirtual, }; for (U64 layout_idx = 0; layout_idx < ArrayCount(layout_arr); layout_idx += 1) { CV_C13SubSectionKind kind = layout_arr[layout_idx]; String8List *data = cv_sub_section_ptr_from_debug_s(debug_s, kind); if (data->total_size > 0) { U32 size32 = safe_cast_u32(data->total_size); str8_serial_push_u32(arena, &srl, kind); str8_serial_push_u32(arena, &srl, size32); str8_serial_push_data_list(arena, &srl, data->first); str8_serial_push_align(arena, &srl, 4); } } String8List *line_data = cv_sub_section_ptr_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); for (String8Node *line_node = line_data->first; line_node != 0; line_node = line_node->next) { str8_serial_push_u32(arena, &srl, CV_C13SubSectionKind_Lines); str8_serial_push_u32(arena, &srl, safe_cast_u32(line_node->string.size)); str8_serial_push_string(arena, &srl, line_node->string); str8_serial_push_align(arena, &srl, 4); } return srl; } internal CV_C13SubSectionIdxKind cv_c13_sub_section_idx_from_kind(CV_C13SubSectionKind kind) { switch (kind) { #define X(n,c) case CV_C13SubSectionKind_##n: return CV_C13SubSectionIdxKind_##n; CV_C13SubSectionKindXList(X) #undef X } return CV_C13SubSectionIdxKind_NULL; } internal String8List * cv_sub_section_ptr_from_debug_s(CV_DebugS *debug_s, CV_C13SubSectionKind kind) { CV_C13SubSectionIdxKind idx = cv_c13_sub_section_idx_from_kind(kind); return &debug_s->data_list[idx]; } internal String8List cv_sub_section_from_debug_s(CV_DebugS debug_s, CV_C13SubSectionKind kind) { String8List *list_ptr = cv_sub_section_ptr_from_debug_s(&debug_s, kind); return *list_ptr; } internal String8 cv_string_table_from_debug_s(CV_DebugS debug_s) { String8List data_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_StringTable); String8 string_data = str8_zero(); if (data_list.node_count > 0) { string_data = data_list.first->string; } return string_data; } internal String8 cv_file_chksms_from_debug_s(CV_DebugS debug_s) { String8List data_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); String8 file_chksms = str8_zero(); if (data_list.node_count > 0) { file_chksms = data_list.first->string; } return file_chksms; } //////////////////////////////// //~ String Table Deduper internal U64 cv_string_hash_table_hash(String8 string) { return u64_hash_from_str8(string); } internal int cv_string_bucket_is_before(void *raw_a, void *raw_b) { CV_StringBucket **a = raw_a; CV_StringBucket **b = raw_b; int is_before; if ((*a)->u.idx0 == (*b)->u.idx0) { is_before = (*a)->u.idx1 < (*b)->u.idx1; } else { is_before = (*a)->u.idx0 < (*b)->u.idx0; } return is_before; } internal CV_StringBucket * cv_string_hash_table_insert_or_update(CV_StringBucket **buckets, U64 cap, U64 hash, CV_StringBucket *new_bucket) { CV_StringBucket *result = 0; B32 was_bucket_inserted_or_updated = 0; U64 best_idx = hash % cap; U64 idx = best_idx; do { retry:; CV_StringBucket *curr_bucket = buckets[idx]; if (curr_bucket == 0) { CV_StringBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted was_bucket_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if (str8_match(curr_bucket->string, new_bucket->string, 0)) { if (cv_string_bucket_is_before(&curr_bucket, &new_bucket)) { // recycle bucket result = new_bucket; // don't need to update, more recent leaf is in the bucket was_bucket_inserted_or_updated = 1; break; } CV_StringBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // recycle bucket result = compare_bucket; // new bucket is in the hash table, exit was_bucket_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1) % cap; } while (idx != best_idx); // are there enough free buckets? Assert(was_bucket_inserted_or_updated); return result; } internal THREAD_POOL_TASK_FUNC(cv_count_strings_in_debug_s_arr_task) { ProfBeginFunction(); CV_DedupStringTablesTask *task = raw_task; CV_StringTableRange *range_list = task->range_lists[task_id]; for (CV_StringTableRange *range_n = range_list; range_n != 0; range_n = range_n->next) { CV_DebugS debug_s = task->arr[range_n->debug_s_idx]; String8 string_buffer = cv_string_table_from_debug_s(debug_s); Assert(range_n->range.min <= range_n->range.max); Assert(range_n->range.min <= string_buffer.size); Assert(range_n->range.max <= string_buffer.size); U64 count = 0; for (U64 i = range_n->range.min; i < range_n->range.max; ++i) { U8 b = string_buffer.str[i]; if (b == '\0') { count += 1; } } ins_atomic_u64_add_eval(&task->string_counts[range_n->debug_s_idx], count); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(cv_dedup_strings_in_debug_s_arr_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 debug_s_idx = task_id; CV_DedupStringTablesTask *task = raw_task; CV_DebugS debug_s = task->arr[debug_s_idx]; String8 string_table = cv_string_table_from_debug_s(debug_s); String8List strings_list = str8_split_by_string_chars(scratch.arena, string_table, str8_lit("\0"), 0); CV_StringBucket *bucket = 0; U64 total_string_size = 0; U64 total_insert_count = 0; U64 string_idx = 0; for (String8Node *string_n = strings_list.first; string_n != 0; string_n = string_n->next, ++string_idx) { if (bucket == 0) { bucket = push_array_no_zero(arena, CV_StringBucket, 1); } bucket->u.idx0 = debug_s_idx; bucket->u.idx1 = string_idx; bucket->string = string_n->string; U64 hash = cv_string_hash_table_hash(string_n->string); CV_StringBucket *insert_or_update = cv_string_hash_table_insert_or_update(task->buckets, task->bucket_cap, hash, bucket); if (insert_or_update == 0) { total_string_size += string_n->string.size; total_insert_count += 1; } if (insert_or_update != bucket) { bucket = 0; } } ins_atomic_u64_add_eval(&task->total_string_size, total_string_size); ins_atomic_u64_add_eval(&task->total_insert_count, total_insert_count); scratch_end(scratch); ProfEnd(); } internal CV_StringHashTable cv_dedup_string_tables(TP_Arena *arena, TP_Context *tp, U64 count, CV_DebugS *arr) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Compute Total Weight"); U64 total_weight = 0; for (U64 i = 0; i < count; ++i) { String8 string_table = cv_string_table_from_debug_s(arr[i]); total_weight += string_table.size; } ProfEnd(); U64 per_task_weight = CeilIntegerDiv(total_weight, tp->worker_count); U64 task_weight = 0; U64 task_id = 0; CV_StringTableRange **range_lists = push_array(scratch.arena, CV_StringTableRange *, tp->worker_count); ProfBegin("Divide Work"); for (U64 debug_s_idx = 0; debug_s_idx < count; ++debug_s_idx) { String8 string_table = cv_string_table_from_debug_s(arr[debug_s_idx]); for (U64 cursor = 0; cursor < string_table.size; cursor += per_task_weight) { if (task_weight >= per_task_weight) { task_id = (task_id + 1) % tp->worker_count; task_weight = 0; } U64 max_range_weight = Min(per_task_weight, string_table.size - cursor); CV_StringTableRange *node = push_array(scratch.arena, CV_StringTableRange, 1); node->range = rng_1u64(cursor, cursor + max_range_weight); node->debug_s_idx = debug_s_idx; SLLStackPush(range_lists[task_id], node); task_weight += max_range_weight; } } ProfEnd(); ProfBegin("Count"); CV_DedupStringTablesTask task = {0}; task.arr = arr; task.range_lists = range_lists; task.string_counts = push_array(scratch.arena, U64, count); tp_for_parallel(tp, 0, tp->worker_count, cv_count_strings_in_debug_s_arr_task, &task); ProfEnd(); ProfBegin("Dedup"); U64 total_string_count = sum_array_u64(count, task.string_counts); task.bucket_cap = (U64)((F64)total_string_count * 1.3); task.buckets = push_array(arena->v[0], CV_StringBucket *, task.bucket_cap); tp_for_parallel(tp, arena, count, cv_dedup_strings_in_debug_s_arr_task, &task); ProfEnd(); CV_StringHashTable string_ht = {0}; string_ht.total_string_size = task.total_string_size; string_ht.total_insert_count = task.total_insert_count; string_ht.bucket_cap = task.bucket_cap; string_ht.buckets = task.buckets; scratch_end(scratch); ProfEnd(); return string_ht; } internal void cv_string_hash_table_assign_buffer_offsets(TP_Context *tp, CV_StringHashTable string_ht) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); ProfBegin("Count Strings"); U64 string_count = 0; for (U64 i = 0; i < string_ht.bucket_cap; ++i) { if (string_ht.buckets[i] != 0) { string_count += 1; } } ProfEnd(); ProfBegin("Push"); CV_StringBucket **strings = push_array_no_zero(scratch.arena, CV_StringBucket *, string_count); ProfEnd(); ProfBegin("Copy Present Buckets"); for (U64 i = 0, string_idx = 0; i < string_ht.bucket_cap; ++i) { if (string_ht.buckets[i] != 0) { strings[string_idx++] = string_ht.buckets[i]; } } ProfEnd(); ProfBegin("Sort"); radsort(strings, string_count, cv_string_bucket_is_before); ProfEnd(); ProfBegin("Assign Offsets"); for (U64 i = 0, offset_cursor = 0; i < string_count; ++i) { CV_StringBucket *s = strings[i]; s->u.offset = offset_cursor; offset_cursor += s->string.size + 1; } ProfEnd(); scratch_end(scratch); ProfEnd(); } internal CV_StringBucket * cv_string_hash_table_lookup(CV_StringHashTable ht, String8 string) { U64 hash = cv_string_hash_table_hash(string); U64 best_idx = hash % ht.bucket_cap; U64 idx = best_idx; do { if (ht.buckets[idx] == 0) { break; } if (str8_match(ht.buckets[idx]->string, string, 0)) { return ht.buckets[idx]; } idx = (idx + 1) % ht.bucket_cap; } while (idx != best_idx); return 0; } internal THREAD_POOL_TASK_FUNC(cv_pack_string_hash_table_task) { ProfBeginFunction(); CV_PackStringHashTableTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) { CV_StringBucket *bucket = task->buckets[bucket_idx]; if (bucket) { MemoryCopy(task->buffer + bucket->u.offset, bucket->string.str, bucket->string.size); task->buffer[bucket->u.offset + bucket->string.size] = '\0'; } } ProfEnd(); } internal String8 cv_pack_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable string_ht) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 buffer_size = string_ht.total_string_size + /* nulls: */ string_ht.total_insert_count; U8 *buffer = push_array_no_zero(arena, U8, buffer_size); CV_PackStringHashTableTask task = {0}; task.buckets = string_ht.buckets; task.buffer = buffer; task.ranges = tp_divide_work(scratch.arena, string_ht.bucket_cap, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, cv_pack_string_hash_table_task, &task); String8 result = str8(buffer, buffer_size); scratch_end(scratch); ProfEnd(); return result; } //////////////////////////////// //~ Symbol Deduper internal int cv_symbol_deduper_is_before(void *raw_a, void *raw_b) { return raw_a < raw_b; } internal CV_SymbolNode ** cv_symbol_deduper_insert_or_update(CV_SymbolNode ***buckets, U64 cap, U64 hash, CV_SymbolNode **new_bucket) { CV_SymbolNode **result = 0; B32 is_inserted_or_updated = 0; U64 best_idx = hash % cap; U64 idx = best_idx; do { retry:; CV_SymbolNode **curr_bucket = buckets[idx]; Assert(curr_bucket != new_bucket); if (curr_bucket == 0) { CV_SymbolNode **compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted is_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if ((*curr_bucket)->data.kind == (*new_bucket)->data.kind && (*curr_bucket)->data.data.size == (*new_bucket)->data.data.size && MemoryMatch((*curr_bucket)->data.data.str, (*new_bucket)->data.data.str, (*new_bucket)->data.data.size)) { if (cv_symbol_deduper_is_before(curr_bucket, new_bucket)) { result = new_bucket; is_inserted_or_updated = 1; // don't need to update, more recent leaf is in the bucket break; } CV_SymbolNode **compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { result = compare_bucket; is_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1) % cap; } while (idx != best_idx); Assert(is_inserted_or_updated); return result; } internal THREAD_POOL_TASK_FUNC(cv_symbol_deduper_insert_task) { ProfBeginFunction(); CV_SymbolDeduperTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) { CV_SymbolNode **symbol_node = &task->symbols[symbol_idx]; U64 hash = hash_from_cv_symbol(&(*symbol_node)->data); cv_symbol_deduper_insert_or_update(task->u.buckets, task->cap, hash, symbol_node); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(cv_symbol_deduper_deref_buckets_task) { ProfBeginFunction(); CV_SymbolDeduperTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) { CV_SymbolNode **bucket = task->u.buckets[bucket_idx]; if (bucket) { task->u.deref_buckets[bucket_idx] = *bucket; } } ProfEnd(); } internal void cv_dedup_symbol_ptr_array(TP_Context *tp, CV_SymbolPtrArray *symbols) { ProfBeginDynamic("Dedup Symbols [Count %llu]", symbols->count); Temp scratch = scratch_begin(0, 0); ProfBegin("Setup Task"); CV_SymbolDeduperTask task = {0}; task.symbols = symbols->v; task.cap = (U64)((F64)symbols->count * 1.3); task.u.buckets = push_array(scratch.arena, CV_SymbolNode **, task.cap); ProfEnd(); ProfBegin("Dedup"); task.ranges = tp_divide_work(scratch.arena, symbols->count, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, cv_symbol_deduper_insert_task, &task); ProfEnd(); ProfBegin("Deref Buckets"); task.ranges = tp_divide_work(scratch.arena, task.cap, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, cv_symbol_deduper_deref_buckets_task, &task); ProfEnd(); ProfBegin("Copy Extant Buckets"); U64 unique_symbol_count = 0; for (U64 bucket_idx = 0; bucket_idx < task.cap; ++bucket_idx) { CV_SymbolNode *bucket = task.u.deref_buckets[bucket_idx]; if (bucket) { symbols->v[unique_symbol_count++] = bucket; } } ProfEnd(); Assert(unique_symbol_count <= symbols->count); symbols->count = unique_symbol_count; ProfBeginDynamic("Sort [Count %llu]", symbols->count); radsort(symbols->v, symbols->count, cv_symbol_deduper_is_before); ProfEnd(); scratch_end(scratch); ProfEnd(); } //////////////////////////////// //~ .debug$T helpers internal CV_DebugT cv_debug_t_from_data_arr(Arena *arena, String8Array data_arr, U64 align) { ProfBegin("Upfront parse"); U64 max_leaf_count = 0; for (U64 data_idx = 0; data_idx < data_arr.count; data_idx += 1) { String8 data = data_arr.v[data_idx]; for (U64 cursor = 0; cursor < data.size; ) { CV_Leaf leaf; cursor += cv_deserial_leaf(data, cursor, align, &leaf); max_leaf_count += 1; } } ProfEnd(); U8 **leaf_arr = push_array_no_zero(arena, U8 *, max_leaf_count); U64 leaf_count = 0; for (U64 data_idx = 0; data_idx < data_arr.count; data_idx += 1) { String8 data = data_arr.v[data_idx]; U64 cursor = 0; while (cursor < data.size) { CV_Leaf leaf; U64 read_size = cv_deserial_leaf(data, cursor, align, &leaf); Assert(leaf_count < max_leaf_count); leaf_arr[leaf_count] = str8_deserial_get_raw_ptr(data, cursor, read_size); leaf_count += 1; // advance cursor cursor += read_size; } } CV_DebugT debug_t = {0}; debug_t.count = leaf_count; debug_t.v = leaf_arr; return debug_t; } internal CV_DebugT cv_debug_t_from_data(Arena *arena, String8 data, U64 align) { String8Array arr = {0}; arr.count = 1; arr.v = &data; return cv_debug_t_from_data_arr(arena, arr, align); } internal CV_Leaf cv_debug_t_get_leaf(CV_DebugT debug_t, U64 leaf_idx) { Assert(leaf_idx < debug_t.count); U8 *ptr = debug_t.v[leaf_idx]; String8 data = str8(ptr, max_U64); CV_Leaf leaf; cv_deserial_leaf(data, 0, 1, &leaf); U64 size = cv_header_struct_size_from_leaf_kind(leaf.kind); Assert(size <= leaf.data.size); return leaf; } internal String8 cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx) { Assert(leaf_idx < debug_t.count); U8 *leaf_ptr = debug_t.v[leaf_idx]; CV_LeafSize *size_ptr = (CV_LeafSize *)leaf_ptr; CV_LeafSize total_size = sizeof(*size_ptr) + *size_ptr; String8 raw_leaf = str8(leaf_ptr, total_size); return raw_leaf; } internal CV_LeafHeader * cv_debug_t_get_leaf_header(CV_DebugT debug_t, U64 leaf_idx) { Assert(leaf_idx < debug_t.count); CV_LeafHeader *leaf_header = (CV_LeafHeader *) debug_t.v[leaf_idx]; return leaf_header; } internal B32 cv_debug_t_is_pch(CV_DebugT debug_t) { if (debug_t.count > 0) { CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, 0); return cv_is_leaf_pch(leaf.kind); } return 0; } internal B32 cv_debug_t_is_type_server(CV_DebugT debug_t) { if (debug_t.count > 0) { CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, 0); return cv_is_leaf_type_server(leaf.kind); } return 0; } internal U64 cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr) { U64 total_leaf_count = 0; for (U64 i = 0; i < count; i += 1) { total_leaf_count += arr[i].count; } return total_leaf_count; } internal THREAD_POOL_TASK_FUNC(cv_str8_list_from_debug_t_task) { CV_Str8ListFromDebugT *task = raw_task; for (U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) { String8Node *node = &task->nodes[leaf_idx]; node->string = cv_debug_t_get_raw_leaf(task->debug_t, leaf_idx); str8_list_push_node(&task->lists[task_id], node); } } internal String8List cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT debug_t) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // build lists in parallel CV_Str8ListFromDebugT task = {0}; task.debug_t = debug_t; task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count); task.lists = push_array(scratch.arena, String8List, tp->worker_count); task.nodes = push_array_no_zero(arena, String8Node, debug_t.count); tp_for_parallel(tp, 0, tp->worker_count, cv_str8_list_from_debug_t_task, &task); // concat output lists String8List list = {0}; for (U64 task_id = 0; task_id < tp->worker_count; ++task_id) { str8_list_concat_in_place(&list, &task.lists[task_id]); } scratch_end(scratch); ProfEnd(); return list; } // $$Symbols internal void cv_parse_symbol_sub_section_capped(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align, U64 cap) { U64 count = 0; for (U64 cursor = 0, opl = data.size; cursor < opl && count < cap; count += 1) { // read symbol header CV_SymbolHeader header; cursor += str8_deserial_read_struct(data, cursor, &header); // size from header has to be larger than 2 bytes if (header.size < sizeof(header.kind)) { Assert(!"TODO: error handle invalid symbol data"); break; } // is there enough bytes in the range? U64 symbol_opl = cursor + (header.size - sizeof(header.kind)); if (symbol_opl > opl) { Assert(!"TODO: error handle corrupted symbol data"); break; } // get symbol data Rng1U64 symbol_data_range = r1u64(cursor, symbol_opl); String8 symbol_data = str8_substr(data, symbol_data_range); // init symbol CV_SymbolNode *node = cv_symbol_list_push(arena, list); node->data.offset = offset_base + cursor; node->data.kind = header.kind; node->data.data = symbol_data; // advance cursor cursor = symbol_opl; cursor = AlignPow2(cursor, align); } } internal void cv_parse_symbol_sub_section(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align) { cv_parse_symbol_sub_section_capped(arena, list, offset_base, data, align, max_U64); } internal CV_SymbolList cv_symbol_list_from_data_list(Arena *arena, String8List data_list, U64 align) { CV_SymbolList symbol_list = {0}; U64 cursor = 0; for (String8Node *sect = data_list.first; sect != 0; cursor += sect->string.size, sect = sect->next) { cv_parse_symbol_sub_section(arena, &symbol_list, cursor, sect->string, align); } return symbol_list; } internal void cv_symbol_list_push_node(CV_SymbolList *list, CV_SymbolNode *node) { node->prev = 0; node->next = 0; DLLPushBack(list->first, list->last, node); list->count += 1; } internal CV_SymbolNode * cv_symbol_list_push(Arena *arena, CV_SymbolList *list) { CV_SymbolNode *node = push_array(arena, CV_SymbolNode, 1); cv_symbol_list_push_node(list, node); return node; } internal CV_SymbolNode * cv_symbol_list_push_data(Arena *arena, CV_SymbolList *list, CV_SymKind kind, String8 data) { CV_SymbolNode *node = cv_symbol_list_push(arena, list); node->data.kind = kind; node->data.data = data; return node; } internal CV_SymbolNode * cv_symbol_list_push_many(Arena *arena, CV_SymbolList *list, U64 count) { CV_SymbolNode *node_arr = push_array_no_zero(arena, CV_SymbolNode, 1); for (U64 node_idx = 0; node_idx < count; node_idx += 1) { cv_symbol_list_push_node(list, &node_arr[node_idx]); } return node_arr; } internal void cv_symbol_list_remove_node(CV_SymbolList *list, CV_SymbolNode *node) { Assert(list->count > 0); list->count -= 1; DLLRemove(list->first, list->last, node); } internal void cv_symbol_list_concat_in_place(CV_SymbolList *list, CV_SymbolList *to_concat) { SLLConcatInPlace(list, to_concat); } internal void cv_symbol_list_concat_in_place_arr(CV_SymbolList *list, U64 count, CV_SymbolList *to_concat) { SLLConcatInPlaceArray(list, to_concat, count); } internal U64 cv_symbol_list_arr_get_count(U64 count, CV_SymbolList *list_arr) { U64 result = 0; for (U64 idx = 0; idx < count; idx += 1) { result += list_arr[idx].count; } return result; } internal String8List cv_data_from_symbol_list(Arena *arena, CV_SymbolList symbol_list, U64 align) { String8List data_list = {0}; for (CV_SymbolNode *node = symbol_list.first; node != 0; node = node->next) { String8 data = cv_serialize_symbol(arena, &node->data, align); str8_list_push(arena, &data_list, data); } return data_list; } internal THREAD_POOL_TASK_FUNC(cv_symbol_list_syncer) { ProfBeginFunction(); CV_SymbolListSyncer *task = raw_task; // context shortcuts Rng1U64 list_range = task->list_range_arr[task_id]; U64 symbol_base = task->symbol_base_arr[task_id]; for (U64 list_idx = list_range.min, symbol_idx = symbol_base; list_idx < list_range.max; list_idx += 1) { // pick up assigned list CV_SymbolList list = task->list_arr[list_idx]; // fill out assigned range in the symbol array for (CV_SymbolNode *node = list.first; node != 0; node = node->next, symbol_idx += 1) { task->symbol_arr[symbol_idx] = node; } } ProfEnd(); } internal CV_SymbolPtrArray cv_symbol_ptr_array_from_list(Arena *arena, TP_Context *tp, U64 count, CV_SymbolList *list_arr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 total_count = cv_symbol_list_arr_get_count(count, list_arr); CV_SymbolListSyncer task = {0}; task.list_arr = list_arr; task.symbol_arr = push_array_no_zero(arena, CV_SymbolNode *, total_count); task.symbol_base_arr = push_array_no_zero(scratch.arena, U64, tp->worker_count); task.list_range_arr = tp_divide_work(scratch.arena, count, tp->worker_count); for (U64 thread_idx = 0, symbol_base = 0; thread_idx < tp->worker_count; thread_idx += 1) { task.symbol_base_arr[thread_idx] = symbol_base; Rng1U64 range = task.list_range_arr[thread_idx]; for (U64 list_idx = range.min; list_idx < range.max; list_idx += 1) { symbol_base += list_arr[list_idx].count; } } tp_for_parallel(tp, 0, tp->worker_count, cv_symbol_list_syncer, &task); CV_SymbolPtrArray result = {0}; result.count = total_count; result.v = task.symbol_arr; scratch_end(scratch); ProfEnd(); return result; } internal CV_Scope * cv_scope_list_push(Arena *arena, CV_ScopeList *list) { CV_Scope *node = push_array(arena, CV_Scope, 1); SLLQueuePush(list->first, list->last, node); return node; } internal CV_SymbolList cv_global_scope_symbols_from_list(Arena *arena, CV_SymbolList list) { CV_SymbolList gsym_list = {0}; S64 scope_depth = 0; for (CV_SymbolNode *symbol_n = list.first; symbol_n != 0; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; if (cv_is_global_symbol(symbol.kind) && scope_depth == 0) { cv_symbol_list_push_data(arena, &gsym_list, symbol.kind, symbol.data); } else if (cv_is_scope_symbol(symbol.kind)) { scope_depth += 1; } else if (cv_is_end_symbol(symbol.kind)) { scope_depth -= 1; if (scope_depth < 0) { break; } } } return gsym_list; } internal CV_ScopeList cv_symbol_tree_from_symbol_list(Arena *arena, CV_SymbolList list) { Temp scratch = scratch_begin(&arena, 1); CV_ScopeList root = {0}; // setup root frame CV_ScopeFrame *stack = push_array(scratch.arena, CV_ScopeFrame, 1); stack->list = &root; for (CV_SymbolNode *symbol_node = list.first; symbol_node != 0; symbol_node = symbol_node->next) { // store symbol in current scope CV_Scope *scope = cv_scope_list_push(arena, stack->list); scope->symbol = symbol_node->data; // does this symbol define a new scope? if (cv_is_scope_symbol(symbol_node->data.kind)) { CV_ScopeFrame *frame = push_array(scratch.arena, CV_ScopeFrame, 1); frame->list = push_array(arena, CV_ScopeList, 1); SLLStackPush(stack, frame); } // does this symbol end current scope? else if (cv_is_end_symbol(symbol_node->data.kind)) { CV_ScopeFrame *prev_stack_frame = stack->next; if (prev_stack_frame) { // set children in parent scope CV_Scope *parent_scope = prev_stack_frame->list->last; parent_scope->children = stack->list; } // pop frame SLLStackPop(stack); } } scratch_end(scratch); return root; } internal U64 cv_patch_symbol_tree_offsets(CV_SymbolList list, U64 base_offset, U64 align) { Temp scratch = scratch_begin(0, 0); struct Stack { struct Stack *next; CV_Symbol *symbol; U64 offset; }; struct Stack *stack = 0; struct Stack *free_list = 0; U64 cursor = base_offset; for (CV_SymbolNode *symbol_n = list.first; symbol_n != 0; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; if (cv_is_scope_symbol(symbol.kind)) { // NOTE: We don't patch 'next' offset in PROC symbols because // it's not used by visual studio and MSVC leaves the offsets // zeroed. LLD is on the same page. Assert(symbol.data.size >= sizeof(U32)*2); // patch symbol parent if (stack) { U32 *parent_off_ptr = (U32 *)symbol.data.str; *parent_off_ptr = stack->offset; } // reuse/alloc frame struct Stack *frame; if (free_list) { frame = free_list; SLLStackPop(free_list); } else { frame = push_array_no_zero(scratch.arena, struct Stack, 1); } // push frame to the stack frame->symbol = &symbol_n->data; frame->offset = cursor; SLLStackPush(stack, frame); } else if (cv_is_end_symbol(symbol.kind)) { // patch symbol end U32 *end_off_ptr = (U32 *)stack->symbol->data.str + /* skip parent off */ 1; *end_off_ptr = cursor; // recycle frame struct Stack *free_frame = stack; SLLStackPop(stack); SLLStackPush(free_list, free_frame); } // advance cursor cursor += cv_compute_symbol_record_size(&symbol, align); } scratch_end(scratch); U64 serial_size = cursor - base_offset; return serial_size; } // $$FileChksms internal void cv_parse_checksum_data(Arena *arena, CV_ChecksumList *list, String8 checksum_data) { for (U64 cursor = 0, cursor_opl = checksum_data.size; cursor < cursor_opl; ) { U64 expected_cursor_after_checksum = cursor + sizeof(CV_C13Checksum); if (expected_cursor_after_checksum > cursor_opl) { break; } CV_C13Checksum *header = (CV_C13Checksum *)str8_deserial_get_raw_ptr(checksum_data, cursor, sizeof(CV_C13Checksum)); cursor += sizeof(CV_C13Checksum); U64 expected_cursor_after_value = cursor + header->len; if (expected_cursor_after_value > cursor_opl) { break; } String8 value = str8(0,0); cursor += str8_deserial_read_block(checksum_data, cursor, header->len, &value); cursor = AlignPow2(cursor, 4); CV_ChecksumNode *node = push_array(arena, CV_ChecksumNode, 1); node->next = 0; CV_Checksum *data = &node->data; data->header = header; data->value = value; SLLQueuePush(list->first, list->last, node); list->count += 1; } } internal CV_ChecksumList cv_c13_parse_checksum_data_list(Arena *arena, String8List checksum_data_list) { CV_ChecksumList result = {0}; for (String8Node *node = checksum_data_list.first; node != 0; node = node->next) { cv_parse_checksum_data(arena, &result, node->string); } return result; } internal void cv_c13_patch_string_offsets_in_checksum_list(CV_ChecksumList checksum_list, String8 string_data, U64 string_data_base_offset, CV_StringHashTable string_ht) { for (CV_ChecksumNode *node = checksum_list.first; node != 0; node = node->next) { CV_Checksum *checksum = &node->data; CV_C13Checksum *header = checksum->header; String8 name = str8_cstring_capped(string_data.str + header->name_off, string_data.str + string_data.size); CV_StringBucket *bucket = cv_string_hash_table_lookup(string_ht, name); U64 name_off64 = string_data_base_offset + bucket->u.offset; header->name_off = safe_cast_u32(name_off64); } } internal String8List cv_c13_collect_source_file_names(Arena *arena, CV_ChecksumList checksum_list, String8 string_data) { String8List source_file_name_list = {0}; for (CV_ChecksumNode *node = checksum_list.first; node != 0; node = node->next) { CV_Checksum *checksum = &node->data; CV_C13Checksum *header = checksum->header; Assert(header->name_off < string_data.size); String8 name = str8_cstring_capped(string_data.str + header->name_off, string_data.str + string_data.size); str8_list_push(arena, &source_file_name_list, name); } return source_file_name_list; } // $$Lines internal void cv_c13_lines_header_list_concat_in_place(CV_C13LinesHeaderList *list, CV_C13LinesHeaderList *to_concat) { SLLConcatInPlace(list, to_concat); } internal CV_C13LinesHeaderList cv_c13_lines_from_sub_sections(Arena *arena, String8 c13_data, Rng1U64 ss_range) { ProfBeginFunction(); CV_C13LinesHeaderList parsed_line_list = {0}; String8 sub_sect_data = str8_substr(c13_data, ss_range); for (U64 cursor = 0; cursor + sizeof(CV_C13SubSecLinesHeader) <= sub_sect_data.size; ) { CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader *)(sub_sect_data.str + cursor); cursor += sizeof(*hdr); // read files for (; cursor + sizeof(CV_C13File) <= sub_sect_data.size; ) { // grab next file header CV_C13File *file = (CV_C13File *)(sub_sect_data.str + cursor); cursor += sizeof(CV_C13File); // parse lines and columns // // TODO: export columns U64 max_line_count = (sub_sect_data.size - cursor) / sizeof(CV_C13Line); U32 line_count = Min(file->num_lines, max_line_count); // TODO(allen): check order correctness here U64 line_array_off = cursor; //U64 col_array_off = line_array_off + line_count * sizeof(CV_C13Line); // compute line entry size U64 line_entry_size = sizeof(CV_C13Line); if (hdr->flags & CV_C13SubSecLinesFlag_HasColumns) { line_entry_size += sizeof(CV_C13Column); } // advance past line and column entries cursor += line_count * line_entry_size; // emit parsed lines CV_C13LinesHeaderNode *lines_parsed_node = push_array_no_zero(arena, CV_C13LinesHeaderNode, 1); lines_parsed_node->next = 0; CV_C13LinesHeader *lines_parsed = &lines_parsed_node->v; lines_parsed->sec_idx = hdr->sec; lines_parsed->sec_off_lo = hdr->sec_off; lines_parsed->sec_off_hi = hdr->sec_off + hdr->len; lines_parsed->file_off = file->file_off; lines_parsed->line_count = line_count; lines_parsed->col_count = 0; // TODO: columns lines_parsed->line_array_off = ss_range.min + line_array_off; lines_parsed->col_array_off = 0; // TODO: columns SLLQueuePush(parsed_line_list.first, parsed_line_list.last, lines_parsed_node); parsed_line_list.count += 1; } } ProfEnd(); return parsed_line_list; } internal CV_LineArray cv_c13_line_array_from_data(Arena *arena, String8 c13_data, U64 sec_base, CV_C13LinesHeader parsed_lines) { CV_LineArray result; result.file_off = parsed_lines.file_off; result.line_count = parsed_lines.line_count; result.col_count = parsed_lines.col_count; result.voffs = push_array_no_zero(arena, U64, parsed_lines.line_count + 1); result.line_nums = push_array_no_zero(arena, U32, parsed_lines.line_count); result.col_nums = 0; CV_C13Line *raw_lines = (CV_C13Line *)str8_deserial_get_raw_ptr(c13_data, parsed_lines.line_array_off, parsed_lines.line_count * sizeof(raw_lines[0])); for(U64 line_idx = 0; line_idx < parsed_lines.line_count; line_idx += 1) { CV_C13Line line = raw_lines[line_idx]; result.voffs[line_idx] = sec_base + parsed_lines.sec_off_lo + line.off; result.line_nums[line_idx] = CV_C13LineFlags_Extract_LineNumber(line.flags); } // emit voff ender result.voffs[result.line_count] = sec_base + parsed_lines.sec_off_hi; return result; } internal void cv_c13_patch_checksum_offsets_in_line_data_list(String8List line_data, U64 checksum_rebase) { for(String8Node *node = line_data.first; node != 0; node = node->next) { String8 raw_data = node->string; if(raw_data.size < sizeof(CV_C13SubSecLinesHeader)) { Assert(!"unable to patch checksum in line sub seciton header"); continue; } CV_C13File *file_header = (CV_C13File *)(raw_data.str + sizeof(CV_C13SubSecLinesHeader)); U64 rebased_file_off = file_header->file_off + checksum_rebase; file_header->file_off = safe_cast_u32(rebased_file_off); } } // $$InlineeLines internal CV_C13InlineeLinesParsedList cv_c13_inlinee_lines_from_sub_sections(Arena *arena, String8List raw_inlinee_lines) { ProfBeginFunction(); CV_C13InlineeLinesParsedList inlinee_lines_list = {0}; for (String8Node *raw_data_node = raw_inlinee_lines.first; raw_data_node != 0; raw_data_node = raw_data_node->next) { U64 cursor = 0; CV_C13InlineeLinesSig sig = 0; cursor += str8_deserial_read_struct(raw_data_node->string, cursor, &sig); for (; cursor + sizeof(CV_C13InlineeSourceLineHeader) <= raw_data_node->string.size; ) { CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(raw_data_node->string.str + cursor); cursor += sizeof(*hdr); CV_C13InlineeLinesParsedNode *inlinee_parsed_node = push_array_no_zero(arena, CV_C13InlineeLinesParsedNode, 1); inlinee_parsed_node->next = 0; SLLQueuePush(inlinee_lines_list.first, inlinee_lines_list.last, inlinee_parsed_node); inlinee_lines_list.count += 1; CV_C13InlineeLinesParsed *inlinee_parsed = &inlinee_parsed_node->v; inlinee_parsed->inlinee = hdr->inlinee; inlinee_parsed->file_off = hdr->file_off; inlinee_parsed->first_source_ln = hdr->first_source_ln; inlinee_parsed->extra_file_count = 0; inlinee_parsed->extra_files = 0; if (sig == CV_C13InlineeLinesSig_EXTRA_FILES) { if (cursor + sizeof(U32) <= raw_data_node->string.size) { U32 *extra_file_count_ptr = (U32 *)(raw_data_node->string.str + cursor); cursor += sizeof(*extra_file_count_ptr); U32 max_extra_file_count = (raw_data_node->string.size - cursor) / sizeof(U32); U32 extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count); U32 *extra_files = (U32 *)(raw_data_node->string.str + cursor); cursor += sizeof(*extra_files) * extra_file_count; inlinee_parsed->extra_file_count = extra_file_count; inlinee_parsed->extra_files = extra_files; } } } } ProfEnd(); return inlinee_lines_list; } // $$FrameData internal void cv_c13_patch_checksum_offsets_in_frame_data_list(String8List frame_data, U32 checksum_rebase) { for(String8Node *node = frame_data.first; node != 0; node = node->next) { String8 raw_data = node->string; U64 count = raw_data.size / sizeof(CV_C13FrameData); CV_C13FrameData *arr = (CV_C13FrameData *)raw_data.str; CV_C13FrameData *ptr = arr; CV_C13FrameData *opl = arr + count; for(; ptr < opl; ptr += 1) { U64 rebased_frame_func = ptr->frame_func + checksum_rebase; ptr->frame_func = safe_cast_u32(rebased_frame_func); } } } //////////////////////////////// // $$Lines Accel internal int cv_c13_voff_map_compar(const void *raw_a, const void *raw_b) { CV_Line *a = (CV_Line*)raw_a; CV_Line *b = (CV_Line*)raw_b; int cmp = a->voff < b->voff ? -1 : a->voff > b->voff ? +1 : 0; return cmp; } internal CV_LinesAccel * cv_c13_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines) { ProfBeginFunction(); U64 total_voff_count = 0; for(U64 arr_idx = 0; arr_idx < lines_count; arr_idx += 1) { total_voff_count += lines[arr_idx].line_count + 1; } CV_Line *map = push_array_no_zero(arena, CV_Line, total_voff_count); U64 map_idx = 0; for(U64 line_idx = 0; line_idx < lines_count; line_idx += 1) { CV_LineArray *l = lines + line_idx; if (l->line_count > 0) { for(U64 voff_idx = 0; voff_idx < l->line_count; voff_idx += 1) { map[map_idx].voff = l->voffs[voff_idx]; map[map_idx].file_off = l->file_off; map[map_idx].line_num = l->line_nums[voff_idx]; map[map_idx].col_num = 0; // TODO: columns map_idx += 1; } map[map_idx].voff = l->voffs[l->line_count]; map[map_idx].file_off = l->file_off; map[map_idx].line_num = 0; map[map_idx].col_num = 0; map_idx += 1; } } Assert(map_idx == total_voff_count); qsort(map, total_voff_count, sizeof(map[0]), cv_c13_voff_map_compar); CV_LinesAccel *accel = push_array(arena, CV_LinesAccel, 1); accel->map_count = total_voff_count; accel->map = map; ProfEnd(); return accel; } internal CV_LinesAccel * cv_lines_accel_from_debug_s(Arena *arena, CV_DebugS debug_s) { // parse $$LINES U64 c13_lines_count = 0; CV_LineArray *c13_lines = 0; { String8List raw_lines_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { Temp temp = temp_begin(arena); CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(temp.arena, raw_lines_node->string, rng_1u64(0, raw_lines_node->string.size)); c13_lines_count += parsed_list.count; temp_end(temp); } c13_lines = push_array_no_zero(arena, CV_LineArray, c13_lines_count); U64 c13_lines_idx = 0; for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { String8 raw_lines = raw_lines_node->string; CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(arena, raw_lines, rng_1u64(0, raw_lines.size)); for(CV_C13LinesHeaderNode *header_node = parsed_list.first; header_node != 0; header_node = header_node->next) { c13_lines[c13_lines_idx++] = cv_c13_line_array_from_data(arena, raw_lines, 0, header_node->v); } } } return cv_c13_make_lines_accel(arena, c13_lines_count, c13_lines); } internal U64 cv_nearest_line(CV_Line *arr, U64 count, U64 value) { if(count > 1 && arr[0].voff <= value && value < arr[count-1].voff) { U64 l = 0; U64 r = count - 1; for (; l <= r; ) { U64 m = l + (r - l) / 2; if (arr[m].voff == value) { return m; } else if (arr[m].voff < value) { l = m + 1; } else { r = m - 1; } } return l; } else if (count == 1 && arr[0].voff == value) { return 0; } return max_U64; } internal CV_Line * cv_line_from_voff(CV_LinesAccel *accel, U64 voff, U64 *out_line_count) { ProfBeginFunction(); U64 voff_line_count = 0; CV_Line *lines = 0; U64 map_idx = cv_nearest_line(accel->map, accel->map_count, voff); if(map_idx < accel->map_count) { U64 near_voff = accel->map[map_idx].voff; for (; map_idx > 0; map_idx -= 1) { if(accel->map[map_idx - 1].voff != near_voff) { break; } } lines = accel->map + map_idx; for(; map_idx < (accel->map_count-1); map_idx += 1) { if(accel->map[map_idx].voff != near_voff) { break; } voff_line_count += 1; } } *out_line_count = voff_line_count; ProfEnd(); return lines; } //////////////////////////////// // $$InlineeLines Accel internal U64 cv_c13_inlinee_lines_accel_hash(void *buffer, U64 size) { XXH64_hash_t hash64 = XXH3_64bits(buffer, size); return hash64; } internal B32 cv_c13_inlinee_lines_accel_push(CV_InlineeLinesAccel *accel, CV_C13InlineeLinesParsed *parsed) { U64 load_factor = accel->bucket_max * 2/3 + 1; if(accel->bucket_count > load_factor) { Assert("TODO: increase max count and rehash buckets"); } B32 is_pushed = 0; U64 hash = cv_c13_inlinee_lines_accel_hash(&parsed->inlinee, sizeof(parsed->inlinee)); U64 best_idx = hash % accel->bucket_max; U64 idx = best_idx; do { if(accel->buckets[idx] == 0) { accel->buckets[idx] = parsed; accel->bucket_count += 1; is_pushed = 1; break; } idx = (idx + 1) % accel->bucket_max; } while(idx != best_idx); return is_pushed; } internal CV_C13InlineeLinesParsed * cv_c13_inlinee_lines_accel_find(CV_InlineeLinesAccel *accel, CV_ItemId inlinee) { CV_C13InlineeLinesParsed *match = 0; U64 hash = cv_c13_inlinee_lines_accel_hash(&inlinee, sizeof(inlinee)); U64 best_idx = hash % accel->bucket_max; U64 idx = best_idx; do { if(accel->buckets[idx] != 0) { if(accel->buckets[idx]->inlinee == inlinee) { match = accel->buckets[idx]; break; } } idx = (idx + 1) % accel->bucket_max; } while(idx != best_idx); return match; } internal CV_InlineeLinesAccel * cv_c13_make_inlinee_lines_accel(Arena *arena, CV_C13InlineeLinesParsedList inlinee_lines) { ProfBeginFunction(); // alloc hash table CV_InlineeLinesAccel *accel = push_array(arena, CV_InlineeLinesAccel, 1); accel->bucket_count = 0; accel->bucket_max = (U64)((F64)inlinee_lines.count * 2.5); accel->buckets = push_array(arena, CV_C13InlineeLinesParsed *, accel->bucket_max); // push parsed inlinees for(CV_C13InlineeLinesParsedNode *inlinee = inlinee_lines.first; inlinee != 0; inlinee = inlinee->next) { cv_c13_inlinee_lines_accel_push(accel, &inlinee->v); } ProfEnd(); return accel; } //////////////////////////////// internal CV_InlineBinaryAnnotsParsed cv_c13_parse_inline_binary_annots(Arena *arena, U64 parent_voff, CV_C13InlineeLinesParsed *inlinee_parsed, String8 binary_annots) { Temp scratch = scratch_begin(&arena, 1); struct CodeRange { struct CodeRange *next; Rng1U64 range; }; struct SourceLine { struct SourceLine *next; U64 voff; U64 length; U64 ln; U64 cn; CV_InlineRangeKind kind; }; struct SourceFile { struct SourceFile *next; struct SourceLine *line_first; struct SourceLine *line_last; U64 line_count; U64 checksum_off; Rng1U64 last_code_range; }; Rng1U64List code_ranges = {0}; struct SourceFile *file_first = 0; struct SourceFile *file_last = 0; U64 file_count = 0; CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_parsed->file_off, inlinee_parsed->first_source_ln, parent_voff); for (;;) { CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); if (step.flags == 0) { break; } if (step.flags & CV_C13InlineSiteDecoderStepFlag_EmitRange) { rng1u64_list_push(arena, &code_ranges, step.range); } if (step.flags & CV_C13InlineSiteDecoderStepFlag_ExtendLastRange) { if (code_ranges.last) { code_ranges.last->v = step.range; } } if (step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) { struct SourceFile *file = push_array(scratch.arena, struct SourceFile, 1); file->checksum_off = step.file_off; SLLQueuePush(file_first, file_last, file); ++file_count; } if (step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) { struct SourceLine *line = push_array(scratch.arena, struct SourceLine, 1); line->voff = step.line_voff; line->ln = step.ln; line->cn = step.cn; SLLQueuePush(file_last->line_first, file_last->line_last, line); ++file_last->line_count; } } CV_LineArray *lines = push_array(arena, CV_LineArray, file_count); { U64 lines_idx = 0; for (struct SourceFile *file = file_first; file != 0; file = file->next, lines_idx += 1) { CV_LineArray *l = lines + lines_idx; l->file_off = file->checksum_off; l->line_count = file->line_count; l->col_count = 0; if (file->line_count > 0) { l->voffs = push_array_no_zero(arena, U64, file->line_count + 1); l->line_nums = push_array_no_zero(arena, U32, file->line_count); l->col_nums = 0; // TODO: column info U64 line_idx = 0; for (struct SourceLine *line = file->line_first; line != NULL; line = line->next, ++line_idx) { // emit line voff and line number l->voffs[line_idx] = line->voff; l->line_nums[line_idx] = (U32)line->ln; } Assert(line_idx == file->line_count); l->voffs[line_idx] = file->last_code_range.max; } } } // fill out result CV_InlineBinaryAnnotsParsed result = {0}; result.lines_count = file_count; result.lines = lines; result.code_ranges = code_ranges; scratch_end(scratch); return result; } //////////////////////////////// internal Rng1U64List cv_make_defined_range_list_from_gaps(Arena *arena, Rng1U64 defrange, CV_LvarAddrGap *gaps, U64 gap_count) { Rng1U64List result = {0}; if (gap_count == 0) { // no gaps, push whole range rng1u64_list_push(arena, &result, defrange); } else { U64 cursor = defrange.min; for (U64 gap_idx = 0; gap_idx < gap_count; ++gap_idx) { // make range Rng1U64 range = rng_1u64(cursor, cursor + gaps[gap_idx].off); rng1u64_list_push(arena, &result, range); // advance cursor = defrange.min + gaps[gap_idx].off + gaps[gap_idx].len; } // emit range past last gap if (gap_count > 0) { CV_LvarAddrGap last_gap = gaps[gap_count - 1]; U64 last_range_byte_size = dim_1u64(defrange) - (last_gap.off + last_gap.len); if (last_range_byte_size) { Rng1U64 last_range = rng_1u64(defrange.min + last_gap.off + last_gap.len, defrange.max); rng1u64_list_push(arena, &result, last_range); } } } return result; } ================================================ FILE: src/linker/codeview_ext/codeview.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once //- Symbol and Leaf Headers typedef struct CV_LeafHeader { CV_LeafSize size; CV_LeafKind kind; } CV_LeafHeader; typedef struct CV_SymbolHeader { CV_SymSize size; CV_SymKind kind; } CV_SymbolHeader; //////////////////////////////// // Type Index Helpers //- $$Symbols typedef struct CV_Symbol { CV_SymKind kind; U64 offset; String8 data; } CV_Symbol; typedef struct CV_SymbolNode { struct CV_SymbolNode *next; struct CV_SymbolNode *prev; CV_Symbol data; } CV_SymbolNode; typedef struct CV_SymbolPtrNode { struct CV_SymbolPtrNode *next; CV_Symbol *data; } CV_SymbolPtrNode; typedef struct CV_SymbolList { U64 count; CV_Signature signature; CV_SymbolNode *first; CV_SymbolNode *last; } CV_SymbolList; typedef struct CV_SymbolListArray { U64 count; CV_SymbolList *v; } CV_SymbolListArray; typedef struct CV_SymbolPtrArray { U64 count; CV_SymbolNode **v; } CV_SymbolPtrArray; typedef struct CV_Scope { struct CV_ScopeList *children; struct CV_Scope *next; struct CV_Scope *prev; CV_Symbol symbol; } CV_Scope; typedef struct CV_ScopeList { CV_Scope *first; CV_Scope *last; } CV_ScopeList; typedef struct CV_ScopeFrame { struct CV_ScopeFrame *next; CV_ScopeList *list; CV_Scope *curr; U64 symbol_off; U32 *parent_off_ptr; U32 *end_off_ptr; } CV_ScopeFrame; //- $$FileChksms typedef struct CV_Checksum { CV_C13Checksum *header; String8 value; } CV_Checksum; typedef struct CV_ChecksumNode { struct CV_ChecksumNode *next; CV_Checksum data; } CV_ChecksumNode; typedef struct CV_ChecksumList { U64 count; CV_ChecksumNode *first; CV_ChecksumNode *last; } CV_ChecksumList; //- $$Lines typedef struct CV_LineArray { U32 file_off; U64 line_count; U64 col_count; U64 *voffs; // [line_count + 1] U32 *line_nums; // [line_count] U16 *col_nums; // [line_count * 2] } CV_LineArray; typedef struct CV_File { U32 file_off; CV_LineArray lines; } CV_File; typedef struct CV_C13LinesHeader { U64 sec_idx; U64 sec_off_lo; U64 sec_off_hi; U64 file_off; U64 line_count; U64 col_count; U64 line_array_off; U64 col_array_off; } CV_C13LinesHeader; typedef struct CV_C13LinesHeaderNode { struct CV_C13LinesHeaderNode *next; CV_C13LinesHeader v; } CV_C13LinesHeaderNode; typedef struct CV_C13LinesHeaderList { CV_C13LinesHeaderNode *first; CV_C13LinesHeaderNode *last; U64 count; } CV_C13LinesHeaderList; //////////////////////////////// typedef struct CV_TypeServerInfo { String8 name; Guid sig; U32 age; } CV_TypeServerInfo; typedef struct CV_TypeServerInfoNode { struct CV_TypeServerInfoNode *next; CV_TypeServerInfo data; } CV_TypeServerInfoNode; typedef struct CV_TypeServerInfoList { CV_TypeServerInfoNode *first; CV_TypeServerInfoNode *last; U64 count; } CV_TypeServerInfoList; typedef struct CV_PrecompInfo { CV_TypeIndex start_index; U32 sig; U32 leaf_count; String8 obj_name; } CV_PrecompInfo; typedef struct CV_ObjInfo { U32 sig; String8 name; } CV_ObjInfo; //////////////////////////////// // Accels typedef struct CV_Line { U64 voff; U32 file_off; U32 line_num; U16 col_num; } CV_Line; typedef struct CV_LinesAccel { U64 map_count; CV_Line *map; } CV_LinesAccel; typedef struct CV_InlineeLinesAccel { U64 bucket_count; U64 bucket_max; CV_C13InlineeLinesParsed **buckets; } CV_InlineeLinesAccel; typedef struct CV_InlineBinaryAnnotsParsed { U64 lines_count; CV_LineArray *lines; Rng1U64List code_ranges; } CV_InlineBinaryAnnotsParsed; typedef struct CV_C13InlineeLinesParsedList { CV_C13InlineeLinesParsedNode *first; CV_C13InlineeLinesParsedNode *last; U64 count; } CV_C13InlineeLinesParsedList; //////////////////////////////// typedef U32 CV_C13SubSectionIdxKind; enum { CV_C13SubSectionIdxKind_NULL, #define X(N,c) CV_C13SubSectionIdxKind_##N, CV_C13SubSectionKindXList(X) #undef X CV_C13SubSectionIdxKind_COUNT }; typedef struct CV_C13SubSectionList { CV_C13SubSectionNode *first; CV_C13SubSectionNode *last; U64 count; } CV_C13SubSectionList; //////////////////////////////// typedef struct CV_DebugS { String8List data_list[CV_C13SubSectionIdxKind_COUNT]; } CV_DebugS; typedef struct CV_DebugT { U64 size; U64 count; U8 **v; } CV_DebugT; //////////////////////////////// //~ Leaf Helpers typedef struct CV_Leaf { CV_LeafKind kind; String8 data; } CV_Leaf; typedef struct CV_LeafNode { struct CV_LeafNode *next; CV_Leaf data; } CV_LeafNode; typedef struct CV_LeafList { U64 count; CV_LeafNode *first; CV_LeafNode *last; } CV_LeafList; //////////////////////////////// //~ String Hash Table typedef struct CV_StringTableRange { struct CV_StringTableRange *next; Rng1U64 range; U64 debug_s_idx; } CV_StringTableRange; typedef struct CV_StringBucket { String8 string; union { struct { U32 idx0; U32 idx1; }; U64 offset; } u; } CV_StringBucket; typedef struct CV_StringHashTable { U64 total_string_size; U64 total_insert_count; U64 bucket_cap; CV_StringBucket **buckets; } CV_StringHashTable; typedef struct CV_StringHashTableResult { U64 string_count; CV_StringBucket **buckets; } CV_StringHashTableResult; //////////////////////////////// //~ Task Contexts typedef struct { U64 cap; union { CV_SymbolNode ***buckets; CV_SymbolNode **deref_buckets; } u; Rng1U64 *ranges; CV_SymbolNode **symbols; } CV_SymbolDeduperTask; typedef struct { CV_SymbolList *list_arr; Rng1U64 *list_range_arr; U64 *symbol_base_arr; CV_SymbolNode **symbol_arr; } CV_SymbolListSyncer; typedef struct { CV_DebugS *arr; CV_StringTableRange **range_lists; U64 *string_counts; U64 bucket_cap; CV_StringBucket **buckets; U64 total_string_size; U64 total_insert_count; } CV_DedupStringTablesTask; typedef struct { U8 *buffer; Rng1U64 *ranges; CV_StringBucket **buckets; } CV_PackStringHashTableTask; typedef struct { CV_DebugT debug_t; Rng1U64 *ranges; String8List *lists; String8Node *nodes; } CV_Str8ListFromDebugT; //////////////////////////////// internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol); internal CV_TypeServerInfo cv_type_server_info_from_leaf(CV_Leaf leaf); internal CV_PrecompInfo cv_precomp_info_from_leaf(CV_Leaf leaf); //////////////////////////////// //~ Leaf Helpers internal U64 cv_compute_leaf_record_size(String8 data, U64 align); internal U64 cv_serialize_leaf_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_LeafKind kind, String8 data, U64 align); internal String8 cv_serialize_raw_leaf(Arena *arena, CV_LeafKind kind, String8 data, U64 align); internal String8 cv_serialize_leaf(Arena *arena, CV_Leaf *leaf, U64 align); internal CV_Leaf cv_make_leaf(Arena *arena, CV_LeafKind kind, String8 data); internal U64 cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out); internal CV_Leaf cv_leaf_from_string(String8 raw_data); //////////////////////////////// //~ Symbol Helpers internal U64 cv_compute_symbol_record_size(CV_Symbol *symbol, U64 align); internal U64 cv_serialize_symbol_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_Symbol *symbol, U64 align); internal String8 cv_serialize_symbol(Arena *arena, CV_Symbol *symbol, U64 align); internal String8 cv_make_symbol(Arena *arena, CV_SymKind kind, String8 data); internal String8 cv_make_obj_name(Arena *arena, String8 obj_path, U32 sig); internal String8 cv_make_comp3(Arena *arena, CV_Compile3Flags flags, CV_Language lang, CV_Arch arch, U16 ver_fe_major, U16 ver_fe_minor, U16 ver_fe_build, U16 ver_feqfe, U16 ver_major, U16 ver_minor, U16 ver_build, U16 ver_qfe, String8 version_string); internal String8 cv_make_envblock(Arena *arena, String8List string_list); internal CV_Symbol cv_make_proc_ref(Arena *arena, CV_ModIndex imod, U32 stream_offset, String8 name, B32 is_local); internal CV_Symbol cv_make_pub32(Arena *arena, CV_Pub32Flags flags, U32 off, U16 isect, String8 name); internal CV_SymbolList cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_SymbolList symbol_list); //////////////////////////////// // .debug$S Helpers internal CV_DebugS cv_parse_debug_s_c13(Arena *arena, String8 raw_debug_s); internal CV_DebugS cv_parse_debug_s_c13_list(Arena *arena, String8List raw_debug_s); internal CV_DebugS cv_parse_debug_s(Arena *arena, String8 raw_debug_s); internal void cv_debug_s_concat_in_place(CV_DebugS *dst, CV_DebugS *src); internal String8List cv_data_c13_from_debug_s(Arena *arena, CV_DebugS *debug_s, B32 write_sig); internal CV_C13SubSectionIdxKind cv_c13_sub_section_idx_from_kind(CV_C13SubSectionKind kind); internal String8List * cv_sub_section_ptr_from_debug_s(CV_DebugS *debug_s, CV_C13SubSectionKind kind); internal String8List cv_sub_section_from_debug_s(CV_DebugS debug_s, CV_C13SubSectionKind kind); internal String8 cv_string_table_from_debug_s(CV_DebugS debug_s); internal String8 cv_file_chksms_from_debug_s(CV_DebugS debug_s); //////////////////////////////// //~ .debug$T helpers internal CV_DebugT cv_debug_t_from_data_arr(Arena *arena, String8Array data_arr, U64 align); internal CV_DebugT cv_debug_t_from_data(Arena *arena, String8 data, U64 align); internal CV_Leaf cv_debug_t_get_leaf(CV_DebugT debug_t, U64 leaf_idx); internal String8 cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx); internal CV_LeafHeader * cv_debug_t_get_leaf_header(CV_DebugT debug_t, U64 leaf_idx); internal B32 cv_debug_t_is_pch(CV_DebugT debug_t); internal B32 cv_debug_t_is_type_server(CV_DebugT debug_t); internal U64 cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr); internal String8List cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT types); //////////////////////////////// //~ Sub Section helpers // $$Symbols internal void cv_parse_symbol_sub_section_capped(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align, U64 cap); internal void cv_parse_symbol_sub_section(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align); internal void cv_symbol_list_push_node(CV_SymbolList *list, CV_SymbolNode *node); internal CV_SymbolNode * cv_symbol_list_push(Arena *arena, CV_SymbolList *list); internal CV_SymbolNode * cv_symbol_list_push_data(Arena *arena, CV_SymbolList *list, CV_SymKind kind, String8 data); internal CV_SymbolNode * cv_symbol_list_push_many(Arena *arena, CV_SymbolList *list, U64 count); internal void cv_symbol_list_remove_node(CV_SymbolList *list, CV_SymbolNode *node); internal void cv_symbol_list_concat_in_place(CV_SymbolList *list, CV_SymbolList *to_concat); internal void cv_symbol_list_concat_in_place_arr(CV_SymbolList *list, U64 count, CV_SymbolList *to_concat); internal U64 cv_symbol_list_arr_get_count(U64 count, CV_SymbolList *list_arr); internal String8List cv_data_from_symbol_list(Arena *arena, CV_SymbolList symbol_list, U64 align); internal CV_SymbolList cv_global_scope_symbols_from_list(Arena *arena, CV_SymbolList list); internal CV_SymbolPtrArray cv_symbol_ptr_array_from_list(Arena *arena, TP_Context *tp, U64 count, CV_SymbolList *symbol_list_arr); // $$FileChksms #define CV_MAP_STRING_TO_OFFSET_FUNC(name) U64 name(void *ud, String8 string) typedef CV_MAP_STRING_TO_OFFSET_FUNC(CV_MapStringToOffsetFunc); internal void cv_c13_patch_string_offsets_in_checksum_list(CV_ChecksumList checksum_list, String8 string_data, U64 string_data_base_offset, CV_StringHashTable string_ht); internal String8List cv_c13_collect_source_file_names(Arena *arena, CV_ChecksumList checksum_list, String8 string_data); // $$Lines internal CV_C13LinesHeaderList cv_c13_lines_from_sub_sections(Arena *arena, String8 c13_data, Rng1U64 ss_range); internal CV_LineArray cv_c13_line_array_from_data(Arena *arena, String8 c13_data, U64 sec_base, CV_C13LinesHeader parsed_lines); // $$InlineeLines internal CV_C13InlineeLinesParsedList cv_c13_inlinee_lines_from_sub_sections(Arena *arena, String8List raw_inlinee_lines); internal CV_InlineBinaryAnnotsParsed cv_c13_parse_inline_binary_annots(Arena *arena, U64 parent_voff, CV_C13InlineeLinesParsed *inlinee_parsed, String8 binary_annots); // $$FrameData internal void cv_c13_patch_checksum_offsets_in_frame_data_list(String8List frame_data, U32 checksum_rebase); //////////////////////////////// // $$Lines Accel internal void cv_make_c13_files(Arena *arena, String8 c13_data, CV_C13SubSectionList lines, U64 *file_count_out, CV_C13File **files_out); internal CV_LinesAccel * cv_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines); internal CV_Line * cv_line_from_voff(CV_LinesAccel *accel, U64 voff, U64 *out_line_count); //////////////////////////////// // $$InlineeLines Accel internal U64 cv_c13_inlinee_lines_accel_hash(void *buffer, U64 size); internal B32 cv_c13_inlinee_lines_accel_push(CV_InlineeLinesAccel *accel, CV_C13InlineeLinesParsed *parsed); internal CV_C13InlineeLinesParsed * cv_c13_inlinee_lines_accel_find(CV_InlineeLinesAccel *accel, CV_ItemId inlinee); internal CV_InlineeLinesAccel * cv_c13_make_inlinee_lines_accel(Arena *arena, CV_C13InlineeLinesParsedList sub_sects); //////////////////////////////// // String Hash Table internal U64 cv_string_hash_table_hash(String8 string); internal CV_StringHashTable cv_dedup_string_tables(TP_Arena *arena, TP_Context *tp, U64 count, CV_DebugS *arr); internal CV_StringHashTableResult cv_serialize_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable string_ht); internal String8 cv_pack_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable string_ht); //////////////////////////////// internal Rng1U64List cv_make_defined_range_list_from_gaps(Arena *arena, Rng1U64 defrange, CV_LvarAddrGap *gaps, U64 gap_count); ================================================ FILE: src/linker/hash_table.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void bucket_list_concat_in_place(BucketList *list, BucketList *to_concat) { if (to_concat->first) { if (list->first) { list->last->next = to_concat->first; list->last = to_concat->last; } else { list->first = to_concat->first; list->last = to_concat->last; } MemoryZeroStruct(to_concat); } } internal BucketNode * bucket_list_pop(BucketList *list) { BucketNode *result = list->first; SLLQueuePop(list->first, list->last); return result; } internal U64 hash_table_hasher(String8 string) { return u64_hash_from_str8(string); } internal HashTable * hash_table_init(Arena *arena, U64 cap) { HashTable *ht = push_array(arena, HashTable, 1); ht->cap = cap; ht->buckets = push_array(arena, BucketList, cap); return ht; } internal void hash_table_purge(HashTable *ht) { // reset key count ht->count = 0; // concat buckets for (U64 ibucket = 0; ibucket < ht->cap; ++ibucket) { bucket_list_concat_in_place(&ht->free_buckets, &ht->buckets[ibucket]); } } internal BucketNode * hash_table_push(Arena *arena, HashTable *ht, U64 hash, KeyValuePair v) { BucketNode *node; if (ht->free_buckets.first != 0) { node = bucket_list_pop(&ht->free_buckets); } else { node = push_array(arena, BucketNode, 1); } node->next = 0; node->v = v; U64 ibucket = hash % ht->cap; DLLPushBack(ht->buckets[ibucket].first, ht->buckets[ibucket].last, node); ht->count += 1; return node; } internal BucketNode * hash_table_push_string_string(Arena *arena, HashTable *ht, String8 key, String8 value) { U64 hash = hash_table_hasher(key); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_string = key, .value_string = value }); } internal BucketNode * hash_table_push_string_raw(Arena *arena, HashTable *ht, String8 key, void *value) { U64 hash = hash_table_hasher(key); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_string = key, .value_raw = value }); } internal BucketNode * hash_table_push_string_u64(Arena *arena, HashTable *ht, String8 key, U64 value) { U64 hash = hash_table_hasher(key); return hash_table_push(arena, ht, hash, (KeyValuePair){.key_string = key, .value_u64 = value }); } internal BucketNode * hash_table_push_u32_raw(Arena *arena, HashTable *ht, U32 key, void *value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u32 = key, .value_raw = value }); } internal BucketNode * hash_table_push_u32_string(Arena *arena, HashTable *ht, U32 key, String8 value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u32 = key, .value_string = value }); } internal BucketNode * hash_table_push_u64_raw(Arena *arena, HashTable *ht, U64 key, void *value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u64 = key, .value_raw = value }); } internal BucketNode * hash_table_push_u64_string(Arena *arena, HashTable *ht, U64 key, String8 value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u64 = key, .value_string = value }); } internal BucketNode * hash_table_push_u64_u64(Arena *arena, HashTable *ht, U64 key, U64 value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u64 = key, .value_u64 = value }); } internal String8 hash_table_normalize_path_string(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); String8 result; result = lower_from_str8(scratch.arena, path); result = path_convert_slashes(arena, result, PathStyle_UnixAbsolute); scratch_end(scratch); return result; } internal BucketNode * hash_table_push_path_string(Arena *arena, HashTable *ht, String8 path, String8 value) { String8 path_canon = hash_table_normalize_path_string(arena, path); return hash_table_push_string_string(arena, ht, path_canon, value); } internal BucketNode * hash_table_push_path_u64(Arena *arena, HashTable *ht, String8 path, U64 value) { String8 path_canon = hash_table_normalize_path_string(arena, path); U64 hash = hash_table_hasher(path_canon); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_string = path_canon, .value_u64 = value }); } internal BucketNode * hash_table_push_path_raw(Arena *arena, HashTable *ht, String8 path, void *value) { String8 path_canon = hash_table_normalize_path_string(arena, path); U64 hash = hash_table_hasher(path_canon); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_string = path_canon, .value_raw = value }); } //////////////////////////////// internal BucketNode * hash_table_search_string(HashTable *ht, String8 key_string) { U64 hash = hash_table_hasher(key_string); U64 ibucket = hash % ht->cap; BucketList *bucket = ht->buckets + ibucket; for (BucketNode *n = bucket->first; n != 0; n = n->next) { if (str8_match(n->v.key_string, key_string, 0)) { return n; } } return 0; } internal BucketNode * hash_table_search_u32(HashTable *ht, U32 key_u32) { U64 hash = hash_table_hasher(str8_struct(&key_u32)); U64 ibucket = hash % ht->cap; BucketList *bucket = ht->buckets + ibucket; for (BucketNode *n = bucket->first; n != 0; n = n->next) { if (n->v.key_u32 == key_u32) { return n; } } return 0; } internal BucketNode * hash_table_search_u64(HashTable *ht, U64 key_u64) { U64 hash = hash_table_hasher(str8_struct(&key_u64)); U64 ibucket = hash % ht->cap; BucketList *bucket = ht->buckets + ibucket; for (BucketNode *n = bucket->first; n != 0; n = n->next) { if (n->v.key_u64 == key_u64) { return n; } } return 0; } internal BucketNode * hash_table_search_path(HashTable *ht, String8 path) { Temp scratch = scratch_begin(0,0); String8 path_canon = path; path_canon = lower_from_str8(scratch.arena, path_canon); path_canon = path_convert_slashes(scratch.arena, path_canon, PathStyle_UnixAbsolute); BucketNode *result = hash_table_search_string(ht, path_canon); scratch_end(scratch); return result; } internal BucketNode * hash_table_search_raw(HashTable *ht, void *key) { U64 hash = hash_table_hasher(str8_struct(&key)); U64 ibucket = hash % ht->cap; BucketList *bucket = ht->buckets + ibucket; for (BucketNode *n = bucket->first; n != 0; n = n->next) { if (n->v.key_raw == key) { return n; } } return 0; } internal B32 hash_table_search_path_u64(HashTable *ht, String8 key, U64 *value_out) { BucketNode *result = hash_table_search_path(ht, key); if (result != 0) { if (value_out != 0) { *value_out = result->v.value_u64; } return 1; } return 0; } internal BucketNode * hash_table_push_u32_u32(Arena *arena, HashTable *ht, U32 key, U32 value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_u32 = key, .value_u32 = value }); } internal BucketNode * hash_table_push_raw_raw(Arena *arena, HashTable *ht, void *key, void *value) { U64 hash = hash_table_hasher(str8_struct(&key)); return hash_table_push(arena, ht, hash, (KeyValuePair){ .key_raw = key, .value_raw = value }); } internal B32 hash_table_search_string_u64(HashTable *ht, String8 key, U64 *value_out) { BucketNode *result = hash_table_search_string(ht, key); if (result != 0) { if (value_out != 0) { *value_out = result->v.value_u64; } return 1; } return 0; } internal B32 hash_table_search_string_string(HashTable *ht, String8 key, String8 *value_out) { BucketNode *result = hash_table_search_string(ht, key); if (result) { if (value_out) { *value_out = result->v.value_string; } return 1; } return 0; } internal B32 hash_table_search_u32_u32(HashTable *ht, U32 key, U32 *value_out) { BucketNode *result = hash_table_search_u32(ht, key); if (result) { if (value_out) { *value_out = result->v.value_u32; } return 1; } return 0; } internal void * hash_table_search_string_raw(HashTable *ht, String8 key) { BucketNode *result = hash_table_search_string(ht, key); if (result) { return result->v.value_raw; } return 0; } internal void * hash_table_search_u64_raw(HashTable *ht, U64 key_u64) { BucketNode *n = hash_table_search_u64(ht, key_u64); return n ? n->v.value_raw : 0; } internal void * hash_table_search_path_raw(HashTable *ht, String8 path) { BucketNode *n = hash_table_search_path(ht, path); return n ? n->v.value_raw : 0; } internal void * hash_table_search_raw_raw(HashTable *ht, void *key) { BucketNode *n = hash_table_search_raw(ht, key); return n ? n->v.value_raw : 0; } internal void hash_table_purge_item(HashTable *ht, U64 hash, BucketNode *node) { U64 bucket_idx = hash % ht->cap; DLLRemove(ht->buckets[bucket_idx].first, ht->buckets[bucket_idx].last, node); ht->count -= 1; } internal B32 hash_table_purge_u64(HashTable *ht, U64 key) { U64 hash = hash_table_hasher(str8_struct(&key)); BucketNode *n = hash_table_search_u64(ht, key); if (n) { hash_table_purge_item(ht, hash, n); return 1; } return 0; } internal B32 hash_table_purge_string(HashTable *ht, String8 key) { U64 hash = hash_table_hasher(key); BucketNode *n = hash_table_search_string(ht, key); if (n) { hash_table_purge_item(ht, hash, n); return 1; } return 0; } internal int key_value_pair_is_before_u32(void *a, void *b) { return ((KeyValuePair *)a)->key_u32 < ((KeyValuePair *)b)->key_u32; } internal int key_value_pair_is_before_u64(void *a, void *b) { return ((KeyValuePair *)a)->key_u64 < ((KeyValuePair *)b)->key_u64; } internal int key_value_pair_is_before_string_sensitive(void *a, void *b) { return str8_compar_case_sensitive(&((KeyValuePair*)a)->key_string, &((KeyValuePair*)b)->key_string) < 0; } internal U32 * keys_from_hash_table_u32(Arena *arena, HashTable *ht) { U32 *result = push_array_no_zero(arena, U32, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); result[cursor++] = n->v.key_u32; } } return result; } internal U64 * keys_from_hash_table_u64(Arena *arena, HashTable *ht) { U64 *result = push_array_no_zero(arena, U64, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); result[cursor++] = n->v.key_u64; } } return result; } internal String8 * keys_from_hash_table_string(Arena *arena, HashTable *ht) { String8 *result = push_array_no_zero(arena, String8, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); result[cursor++] = n->v.key_string; } } return result; } internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht) { KeyValuePair *pairs = push_array_no_zero(arena, KeyValuePair, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); pairs[cursor++] = n->v; } } return pairs; } internal void * keys_from_hash_table_raw(Arena *arena, HashTable *ht) { void **result = push_array(arena, void *, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); result[cursor++] = n->v.key_raw; } } return result; } internal void * values_from_hash_table_raw(Arena *arena, HashTable *ht) { void **result = push_array(arena, void *, ht->count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < ht->cap; ++bucket_idx) { for (BucketNode *n = ht->buckets[bucket_idx].first; n != 0; n = n->next) { Assert(cursor < ht->count); result[cursor++] = n->v.value_raw; } } return result; } #include "third_party/radsort/radsort.h" internal void sort_key_value_pairs_as_u32(KeyValuePair *pairs, U64 count) { radsort(pairs, count, key_value_pair_is_before_u32); } internal void sort_key_value_pairs_as_u64(KeyValuePair *pairs, U64 count) { radsort(pairs, count, key_value_pair_is_before_u64); } internal void sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count) { radsort(pairs, count, key_value_pair_is_before_string_sensitive); } internal U64Array remove_duplicates_u64_array(Arena *arena, U64Array arr) { Temp scratch = scratch_begin(&arena, 1); HashTable *ht = hash_table_init(scratch.arena, ((U64)(F64)arr.count * 0.5)); for (U64 i = 0; i < arr.count; ++i) { BucketNode *is_present = hash_table_search_u64(ht, arr.v[i]); if (!is_present) { hash_table_push_u64_raw(scratch.arena, ht, arr.v[i], 0); } } U64Array result = {0}; result.count = ht->count; result.v = keys_from_hash_table_u64(arena, ht); scratch_end(scratch); return result; } internal String8List remove_duplicates_str8_list(Arena *arena, String8List list) { Temp scratch = scratch_begin(&arena, 1); String8List result = {0}; HashTable *ht = hash_table_init(scratch.arena, list.node_count); for (String8Node *node = list.first; node != 0; node = node->next) { BucketNode *is_present = hash_table_search_string(ht, node->string); if (!is_present) { hash_table_push_string_raw(scratch.arena, ht, node->string, 0); str8_list_push(arena, &result, node->string); } } scratch_end(scratch); return result; } ================================================ FILE: src/linker/hash_table.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef struct KeyValuePair { union { String8 key_string; void *key_raw; U32 key_u32; U64 key_u64; }; union { String8 value_string; void *value_raw; U32 value_u32; U64 value_u64; }; } KeyValuePair; typedef struct BucketNode { KeyValuePair v; struct BucketNode *next; struct BucketNode *prev; } BucketNode; typedef struct BucketList { BucketNode *first; BucketNode *last; } BucketList; typedef struct HashTable { U64 count; U64 cap; BucketList *buckets; BucketList free_buckets; } HashTable; // --- Bucket List ------------------------------------------------------------- internal void bucket_list_concat_in_place(BucketList *list, BucketList *to_concat); internal BucketNode * bucket_list_pop (BucketList *list); // --- Hash Table -------------------------------------------------------------- internal U64 hash_table_hasher(String8 string); internal HashTable * hash_table_init (Arena *arena, U64 cap); internal void hash_table_purge(HashTable *ht); internal BucketNode * hash_table_push(Arena *arena, HashTable *ht, U64 hash, KeyValuePair kv); internal BucketNode * hash_table_push_u32_string (Arena *arena, HashTable *ht, U32 key, String8 value); internal BucketNode * hash_table_push_u64_string (Arena *arena, HashTable *ht, U64 key, String8 value); internal BucketNode * hash_table_push_string_string(Arena *arena, HashTable *ht, String8 key, String8 value); internal BucketNode * hash_table_push_path_string (Arena *arena, HashTable *ht, String8 key, String8 value); internal BucketNode * hash_table_push_u32_raw (Arena *arena, HashTable *ht, U32 key, void *value); internal BucketNode * hash_table_push_u64_raw (Arena *arena, HashTable *ht, U64 key, void *value); internal BucketNode * hash_table_push_path_raw (Arena *arena, HashTable *ht, String8 path, void *value); internal BucketNode * hash_table_push_path_u64 (Arena *arena, HashTable *ht, String8 path, U64 value); internal BucketNode * hash_table_push_u64_u64 (Arena *arena, HashTable *ht, U64 key, U64 value); internal BucketNode * hash_table_push_u32_u32 (Arena *arena, HashTable *ht, U32 key, U32 value); internal BucketNode * hash_table_search_string (HashTable *ht, String8 key); internal BucketNode * hash_table_search_u32 (HashTable *ht, U32 key); internal BucketNode * hash_table_search_u64 (HashTable *ht, U64 key); internal BucketNode * hash_table_search_path (HashTable *ht, String8 key); internal BucketNode * hash_table_search_raw (HashTable *ht, void *key); internal B32 hash_table_search_path_u64 (HashTable *ht, String8 key, U64 *value_out); internal B32 hash_table_search_string_u64 (HashTable *ht, String8 key, U64 *value_out); internal B32 hash_table_search_string_string(HashTable *ht, String8 key, String8 *value_out); internal B32 hash_table_search_u32_u32 (HashTable *ht, U32 key, U32 *value_out); internal void * hash_table_search_string_raw(HashTable *ht, String8 key); internal void * hash_table_search_u64_raw (HashTable *ht, U64 key); internal void * hash_table_search_path_raw (HashTable *ht, String8 key); internal void * hash_table_search_raw_raw (HashTable *ht, void *key); internal void hash_table_purge_item (HashTable *ht, U64 hash, BucketNode *node); internal B32 hash_table_purge_u64 (HashTable *ht, U64 key); internal B32 hash_table_purge_string(HashTable *ht, String8 key); // --- Key Value Helpers ------------------------------------------------------- internal U32 * keys_from_hash_table_u32 (Arena *arena, HashTable *ht); internal U64 * keys_from_hash_table_u64 (Arena *arena, HashTable *ht); internal String8 keys_from_hash_table_str8 (Arena *arena, HashTable *ht); internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht); internal void * keys_from_hash_table_raw (Arena *arena, HashTable *ht); internal void * values_from_hash_table_raw(Arena *arena, HashTable *ht); internal void sort_key_value_pairs_as_u32 (KeyValuePair *pairs, U64 count); internal void sort_key_value_pairs_as_u64 (KeyValuePair *pairs, U64 count); internal void sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count); // --- Misc -------------------------------------------------------------------- internal U64Array remove_duplicates_u64_array(Arena *arena, U64Array arr); internal String8List remove_duplicates_str8_list(Arena *arena, String8List list); ================================================ FILE: src/linker/linker.natvis ================================================ {{ name={name} flags={flags} id={id} sort_index={sort_index} }} lib->was_member_linked[member_idx] lib member_idx count count v {{count={count} first={first} last={last} }} count first next this {{count={count} first={first} }} count first next data count v chunk_count first next this {{count={count} first={first} last={last} }} count first next v {{count={count} first={first} last={last} }} count count first next_line_table this count idx = 0 node->v[idx] idx += 1 node = node->next {count,cap,v} count cap count v count idx = 0 node->v[idx] idx += 1 node = node->next {count,cap,v} base count cap count v empty first next v cap count free_buckets node = buckets[bucket_idx].first node node = node->next bucket_idx += 1 ================================================ FILE: src/linker/lnk.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // --- Build Options ----------------------------------------------------------- #define BUILD_CONSOLE_INTERFACE 1 #define BUILD_TITLE "Epic Games Tools (R) RAD PE/COFF Linker" // --- Arena ------------------------------------------------------------------- #define ARENA_FREE_LIST 1 // --- Third Party ------------------------------------------------------------- #include "base_ext/base_blake3.h" #include "base_ext/base_blake3.c" #define XXH_INLINE_ALL #define XXH_IMPLEMENTATION #define XXH_STATIC_LINKING_ONLY #include "third_party/xxHash/xxhash.c" #include "third_party/xxHash/xxhash.h" #include "third_party/radsort/radsort.h" // --- Code Base --------------------------------------------------------------- #include "base/base_inc.h" #include "os/os_inc.h" #include "hash_table.h" #include "coff/coff.h" #include "coff/coff_parse.h" #include "coff/coff_obj_writer.h" #include "coff/coff_lib_writer.h" #include "pe/pe.h" #include "pe/pe_section_flags.h" #include "pe/pe_make_import_table.h" #include "pe/pe_make_export_table.h" #include "pe/pe_make_debug_dir.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" #include "msf/msf_parse.h" #include "pdb/pdb.h" #include "msvc_crt/msvc_crt.h" #include "base/base_inc.c" #include "os/os_inc.c" #include "hash_table.c" #include "coff/coff.c" #include "coff/coff_parse.c" #include "coff/coff_obj_writer.c" #include "coff/coff_lib_writer.c" #include "pe/pe.c" #include "pe/pe_make_import_table.c" #include "pe/pe_make_export_table.c" #include "pe/pe_make_debug_dir.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c" #include "msf/msf_parse.c" #include "pdb/pdb.c" #include "msvc_crt/msvc_crt.c" // --- RDI --------------------------------------------------------------------- #include "rdi/rdi_local.h" #include "rdi/rdi_local.c" // --- Code Base Extensions ---------------------------------------------------- #include "base_ext/base_inc.h" #include "thread_pool/thread_pool.h" #include "codeview_ext/codeview.h" #include "pdb_ext/msf_builder.h" #include "pdb_ext/pdb.h" #include "pdb_ext/pdb_helpers.h" #include "pdb_ext/pdb_builder.h" #include "base_ext/base_inc.c" #include "thread_pool/thread_pool.c" #include "codeview_ext/codeview.c" #include "pdb_ext/msf_builder.c" #include "pdb_ext/pdb.c" #include "pdb_ext/pdb_helpers.c" #include "pdb_ext/pdb_builder.c" // --- RDI Builder ------------------------------------------------------------- #include "rdi/rdi_builder.h" #include "rdi/rdi_coff.h" #include "rdi/rdi_cv.h" #include "rdi/rdi_builder.c" #include "rdi/rdi_coff.c" #include "rdi/rdi_cv.c" // --- Linker ------------------------------------------------------------------ #include "lnk_error.h" #include "lnk_log.h" #include "lnk_timer.h" #include "lnk_io.h" #include "lnk_cmd_line.h" #include "lnk_config.h" #include "lnk_symbol_table.h" #include "lnk_section_table.h" #include "lnk_debug_helper.h" #include "lnk_obj.h" #include "lnk_lib.h" #include "lnk_debug_info.h" #include "lnk.h" #include "lnk_error.c" #include "lnk_log.c" #include "lnk_timer.c" #include "lnk_io.c" #include "lnk_cmd_line.c" #include "lnk_config.c" #include "lnk_symbol_table.c" #include "lnk_section_table.c" #include "lnk_obj.c" #include "lnk_debug_helper.c" #include "lnk_lib.c" #include "lnk_debug_info.c" // ----------------------------------------------------------------------------- internal LNK_Config * lnk_config_from_argcv(Arena *arena, int argc, char **argv) { Temp scratch = scratch_begin(&arena, 1); String8List raw_cmd_line = {0}; for EachIndex(i, argc) { str8_list_push(arena, &raw_cmd_line, str8_cstring(argv[i])); } // remove exe name first argument str8_list_pop_front(&raw_cmd_line); // parse command line String8List unwrapped_cmd_line = lnk_unwrap_rsp(scratch.arena, raw_cmd_line); LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, unwrapped_cmd_line); // setup default flags lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Align, "%u", KB(4)); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Debug, "none"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_FileAlign, "%u", 512); if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Dll)) { lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_SubSystem, "%S", pe_string_from_subsystem(PE_WindowsSubsystem_WINDOWS_GUI)); } lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_HighEntropyVa, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_ManifestUac, "\"level='asInvoker' uiAccess='false'\""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_NxCompat, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_LargeAddressAware, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_PdbAltPath, "%%_RAD_PDB_PATH%%"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_PdbPageSize, "%u", KB(4)); if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Brepro)) { lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_TimeStamp, "%u", os_get_process_start_time_unix()); } lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Age, "%u", 1); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_DoMerge, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_EnvLib, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Exe, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Guid, "imageblake3"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_LargePages, "no"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_LinkVer, "14.0"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_OsVer, "6.0"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_PageSize, "%u", KB(4)); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_PathStyle, "system"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Workers, "%u", os_get_system_info()->logical_processor_count); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_TargetOs, "windows"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_DebugAltPath, "%%_RAD_RDI_PATH%%"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_MemoryMapFiles, ""); #if BUILD_DEBUG lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "debug"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_Log, "io_write"); #else lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SuppressError, "%u", LNK_Error_InvalidTypeIndex); #endif // default section merges lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".xdata=.rdata"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".00cfg=.rdata"); // TODO: .tls must be always first contribution in .data section because compiler generates TLS relative movs //lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".tls=.data"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".idata=.data"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".didat=.data"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".edata=.rdata"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".RAD_LINK_PE_DEBUG_DIR=.rdata"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Merge, ".RAD_LINK_PE_DEBUG_DATA=.rdata"); // sections to remove from the image lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_RemoveSection, ".debug"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_RemoveSection, ".gehcont"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_RemoveSection, ".gfids"); lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_RemoveSection, ".gxfg"); // set limits on unresolved symbol errors lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_MapLinesForUnresolvedSymbols, ""); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_UnresolvedSymbolLimit, "1000"); lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit, "10"); // set default max worker count if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Rad_SharedThreadPool)) { lnk_cmd_line_push_optionf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, ""); } if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Rad_MtPath)) { lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_MtPath, "%s", LNK_MANIFEST_MERGE_TOOL_NAME); } // when /FORCE is specified on the command line, do not stop on these errors if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Force)) { g_error_mode_arr[LNK_Error_UnresolvedSymbol] = LNK_ErrorMode_Continue; } // init config LNK_Config *config = lnk_config_from_cmd_line(raw_cmd_line, cmd_line); #if PROFILE_TELEMETRY { String8 cmdl = str8_list_join(scratch.arena, &config->raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") }); tmMessage(0, TMMF_ICON_NOTE, "Command Line: %.*s", str8_varg(cmdl)); } #endif if (lnk_get_log_status(LNK_Log_Debug)) { String8 full_cmd_line = str8_list_join(scratch.arena, &raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") }); fprintf(stderr, "--------------------------------------------------------------------------------\n"); fprintf(stderr, "Command Line: %.*s\n", str8_varg(full_cmd_line)); fprintf(stderr, "Work Dir : %.*s\n", str8_varg(config->work_dir)); fprintf(stderr, "--------------------------------------------------------------------------------\n"); } scratch_end(scratch); return config; } internal String8 lnk_make_full_path(Arena *arena, PathStyle system_path_style, String8 work_dir, String8 path) { ProfBeginFunction(); String8 result = str8(0,0); PathStyle path_style = path_style_from_str8(path); if (path_style == PathStyle_Relative) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; str8_list_push(scratch.arena, &list, work_dir); str8_list_push(scratch.arena, &list, path); result = str8_path_list_join_by_style(arena, &list, system_path_style); scratch_end(scratch); } else { result = push_str8_copy(arena, path); } ProfEnd(); return result; } internal THREAD_POOL_TASK_FUNC(lnk_blake3_hasher_task) { ProfBeginFunction(); LNK_Blake3Hasher *task = raw_task; Rng1U64 range = task->ranges[task_id]; String8 sub_data = str8_substr(task->data, range); blake3_hasher hasher; blake3_hasher_init(&hasher); blake3_hasher_update(&hasher, sub_data.str, sub_data.size); blake3_hasher_finalize(&hasher, (U8 *)task->hashes[task_id].u64, sizeof(task->hashes[task_id].u64)); ProfEnd(); } internal U128 lnk_blake3_hash_parallel(TP_Context *tp, U64 chunk_count, String8 data) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); ProfBegin("Hash Chunks"); LNK_Blake3Hasher task = {0}; task.data = data; task.ranges = tp_divide_work(scratch.arena, data.size, chunk_count); task.hashes = push_array(scratch.arena, U128, chunk_count); tp_for_parallel(tp, 0, chunk_count, lnk_blake3_hasher_task, &task); ProfEnd(); ProfBegin("Combine Hashes"); blake3_hasher hasher; blake3_hasher_init(&hasher); for (U64 i = 0; i < chunk_count; ++i) { blake3_hasher_update(&hasher, (U8 *)task.hashes[i].u64, sizeof(task.hashes[i].u64)); } U128 result; blake3_hasher_finalize(&hasher, (U8 *)result.u64, sizeof(result.u64)); ProfEnd(); scratch_end(scratch); ProfEnd(); return result; } internal String8 lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list) { // TODO: we write a temp file with manifest attributes collected from obj directives and command line switches // so we can pass file to mt.exe or llvm-mt.exe, when we have our own tool for merging manifest we can switch // to writing manifest file in memory to skip roun-trip to disk Temp scratch = scratch_begin(&arena, 1); String8List srl = {0}; str8_serial_begin(scratch.arena, &srl); str8_serial_push_string(scratch.arena, &srl, str8_lit( "\n" "\n")); if (manifest_uac) { #if 1 String8 uac = push_str8f(scratch.arena, " \n" " \n" " \n" " \n" " \n" " \n" " \n", manifest_level, manifest_ui_access); #else String8 uac = push_str8f(scratch.arena, "\n" "" "" "" "" "" "" "", manifest_level, manifest_ui_access); #endif str8_serial_push_string(scratch.arena, &srl, uac); } for (String8Node *node = manifest_dependency_list.first; node != 0; node = node->next) { String8 dep = push_str8f(scratch.arena, " \n" " \n" " \n" " \n" " \n", node->string); str8_serial_push_string(scratch.arena, &srl, dep); } str8_serial_push_string(scratch.arena, &srl, str8_lit("\n")); String8 result = str8_list_join(arena, &srl, 0); scratch_end(scratch); return result; } internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); String8List cmd_line = {0}; str8_list_push(scratch.arena, &cmd_line, mt_path); str8_list_pushf(scratch.arena, &cmd_line, "-out:%S", out_name); str8_list_pushf(scratch.arena, &cmd_line, "-nologo"); // register input manifest files on command line String8 work_dir = os_get_current_path(scratch.arena); for (String8Node *man_node = manifest_path_list.first; man_node != 0; man_node = man_node->next) { // resolve relative inputs String8 full_path = path_absolute_dst_from_relative_dst_src(scratch.arena, man_node->string, work_dir); // normalize slashes full_path = path_convert_slashes(scratch.arena, full_path, PathStyle_UnixAbsolute); // push input to command line str8_list_pushf(scratch.arena, &cmd_line, "-manifest"); str8_list_push(scratch.arena, &cmd_line, full_path); } // launch mt.exe with our command line OS_ProcessLaunchParams launch_opts = {0}; launch_opts.cmd_line = cmd_line; launch_opts.inherit_env = 1; launch_opts.consoleless = 0; OS_Handle mt_handle = os_process_launch(&launch_opts); if (os_handle_match(mt_handle, os_handle_zero())) { lnk_error(LNK_Error_Mt, "unable to start process: %S", mt_path); } else { os_process_join(mt_handle, max_U64, 0); os_process_detach(mt_handle); } scratch_end(scratch); ProfEnd(); } internal String8 lnk_manifest_from_inputs(Arena *arena, LNK_IO_Flags io_flags, String8 mt_path, String8 manifest_name, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List input_manifest_path_list, String8List deps_list) { Temp scratch = scratch_begin(&arena, 1); String8List unique_deps = remove_duplicates_str8_list(scratch.arena, deps_list); String8 manifest_data; if (input_manifest_path_list.node_count > 0) { ProfBegin("Merge Manifests"); String8 linker_manifest = lnk_make_linker_manifest(scratch.arena, manifest_uac, manifest_level, manifest_ui_access, unique_deps); // write linker manifest to temp file String8 linker_manifest_path = push_str8f(scratch.arena, "%S.manifest.temp", manifest_name); lnk_write_data_to_file_path(linker_manifest_path, str8_zero(), linker_manifest); String8List unique_input_manifest_paths = remove_duplicates_str8_list(scratch.arena, input_manifest_path_list); // push linker manifest str8_list_push(scratch.arena, &unique_input_manifest_paths, linker_manifest_path); // launch mt.exe to merge input manifests String8 merged_manifest_path = push_str8f(scratch.arena, "%S.manifest.merged", manifest_name); lnk_merge_manifest_files(mt_path, merged_manifest_path, unique_input_manifest_paths); // read mt.exe output from disk manifest_data = lnk_read_data_from_file_path(arena, io_flags, merged_manifest_path); if (manifest_data.size == 0) { lnk_error(LNK_Error_Mt, "unable to find mt.exe output manifest on disk, expected path \"%S\"", merged_manifest_path); } // cleanup disk os_delete_file_at_path(linker_manifest_path); os_delete_file_at_path(merged_manifest_path); ProfEnd(); } else { manifest_data = lnk_make_linker_manifest(arena, manifest_uac, manifest_level, manifest_ui_access, unique_deps); } scratch_end(scratch); return manifest_data; } internal String8 lnk_make_null_obj(Arena *arena) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_Unknown); // push null symbol COFF_ObjSymbol *null_abs = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(LNK_NULL_SYMBOL), 0, COFF_SymStorageClass_External); // push import stub coff_obj_writer_push_symbol_weak(obj_writer, str8_lit(LNK_IMPORT_STUB), COFF_WeakExt_Null, null_abs); // push .debug$T sections with null leaf String8 null_debug_data; { String8 raw_null_leaf = cv_serialize_raw_leaf(obj_writer->arena, CV_LeafKind_NOTYPE, str8(0,0), 1); String8List srl = {0}; str8_serial_begin(obj_writer->arena, &srl); str8_serial_push_u32(obj_writer->arena, &srl, CV_Signature_C13); str8_serial_push_string(obj_writer->arena, &srl, raw_null_leaf); null_debug_data = str8_serial_end(obj_writer->arena, &srl); } coff_obj_writer_push_section(obj_writer, str8_lit(".debug$T"), PE_DEBUG_SECTION_FLAGS, null_debug_data); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); return obj; } internal int lnk_res_string_id_is_before(void *raw_a, void *raw_b) { PE_Resource *a = raw_a; PE_Resource *b = raw_b; Assert(a->id.type == COFF_ResourceIDType_String); Assert(b->id.type == COFF_ResourceIDType_String); int is_before = str8_is_before_case_sensitive(&a->id.u.string, &b->id.u.string); return is_before; } internal int lnk_res_number_id_is_before(void *raw_a, void *raw_b) { PE_Resource *a = raw_a; PE_Resource *b = raw_b; Assert(a->id.type == COFF_ResourceIDType_Number); Assert(b->id.type == COFF_ResourceIDType_Number); int is_before = u16_is_before(&a->id.u.number, &b->id.u.number); return is_before; } internal void lnk_serialize_pe_resource_tree(COFF_ObjWriter *obj_writer, PE_ResourceDir *root_dir) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); struct Stack { struct Stack *next; U64 arr_idx; U64 res_idx[2]; PE_ResourceArray res_arr[2]; COFF_ResourceDirEntry *coff_entry_arr[2]; }; struct Stack *stack = push_array(scratch.arena, struct Stack, 1); // init stack { PE_Resource *root_wrapper = push_array(scratch.arena, PE_Resource, 1); root_wrapper->id.type = COFF_ResourceIDType_Number; root_wrapper->id.u.number = 0; root_wrapper->kind = PE_ResDataKind_DIR; root_wrapper->u.dir = root_dir; COFF_ResourceDirEntry *root_dir = push_array(scratch.arena, COFF_ResourceDirEntry, 1); stack->res_arr[0].count = 1; stack->res_arr[0].v = root_wrapper; stack->coff_entry_arr[0] = root_dir; stack->coff_entry_arr[1] = 0; } COFF_ObjSection *rsrc1 = coff_obj_writer_push_section(obj_writer, str8_lit(".rsrc$01"), PE_RSRC1_SECTION_FLAGS, str8_zero()); COFF_ObjSection *rsrc2 = coff_obj_writer_push_section(obj_writer, str8_lit(".rsrc$02"), PE_RSRC2_SECTION_FLAGS, str8_zero()); for (; stack; ) { for (; stack->arr_idx < ArrayCount(stack->res_arr); stack->arr_idx += 1) { for (; stack->res_idx[stack->arr_idx] < stack->res_arr[stack->arr_idx].count; ) { U64 res_idx = stack->res_idx[stack->arr_idx]++; PE_Resource *res = &stack->res_arr[stack->arr_idx].v[res_idx]; { COFF_ResourceDirEntry *coff_entry = &stack->coff_entry_arr[stack->arr_idx][res_idx]; // assign entry data offset coff_entry->id.data_entry_offset = safe_cast_u32(rsrc1->data.total_size); // set directory flag if (res->kind == PE_ResDataKind_DIR) { coff_entry->id.data_entry_offset |= COFF_Resource_SubDirFlag; } } switch (res->kind) { case PE_ResDataKind_DIR: { // fill out directory header COFF_ResourceDirTable *dir_header = push_array(obj_writer->arena, COFF_ResourceDirTable, 1); dir_header->characteristics = res->u.dir->characteristics; dir_header->time_stamp = res->u.dir->time_stamp; dir_header->major_version = res->u.dir->major_version; dir_header->minor_version = res->u.dir->minor_version; dir_header->name_entry_count = res->u.dir->named_list.count; dir_header->id_entry_count = res->u.dir->id_list.count; // sort input resources PE_ResourceArray named_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->named_list); PE_ResourceArray id_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->id_list); radsort(named_array.v, named_array.count, lnk_res_string_id_is_before); radsort(id_array.v, id_array.count, lnk_res_number_id_is_before); // allocate COFF entries COFF_ResourceDirEntry *named_entries = push_array(obj_writer->arena, COFF_ResourceDirEntry, named_array.count); COFF_ResourceDirEntry *id_entries = push_array(obj_writer->arena, COFF_ResourceDirEntry, id_array.count); // push header and entries str8_list_push(obj_writer->arena, &rsrc1->data, str8_struct(dir_header)); str8_list_push(obj_writer->arena, &rsrc1->data, str8_array(named_entries, named_array.count)); str8_list_push(obj_writer->arena, &rsrc1->data, str8_array(id_entries, id_array.count)); // fill out named ids for (U64 i = 0; i < named_array.count; i += 1) { PE_Resource src = named_array.v[i]; COFF_ResourceDirEntry *dst = &named_entries[i]; // append resource name U32 res_name_off = safe_cast_u32(rsrc1->data.total_size); String8 res_name = coff_resource_string_from_str8(obj_writer->arena, res->id.u.string); str8_list_push(obj_writer->arena, &rsrc1->data, res_name); // not sure why high bit has to be turned on here since number id and string id entries are // in separate arrays but windows doesn't treat name offset like string without this bit. dst->name.offset = (1 << 31) | res_name_off; } // fill out number ids for (U64 i = 0; i < id_array.count; i += 1) { PE_Resource src = id_array.v[i]; COFF_ResourceDirEntry *dst = &id_entries[i]; dst->name.id = src.id.u.number; } // fill out sub directory stack frame struct Stack *frame = push_array(scratch.arena, struct Stack, 1); frame->res_arr[0] = named_array; frame->res_arr[1] = id_array; frame->coff_entry_arr[0] = named_entries; frame->coff_entry_arr[1] = id_entries; SLLStackPush(stack, frame); } goto yield; // recurse to sub directory case PE_ResDataKind_COFF_RESOURCE: { // fill out resource header COFF_ResourceDataEntry *coff_res = push_array(obj_writer->arena, COFF_ResourceDataEntry, 1); coff_res->data_size = res->u.coff_res.data.size; coff_res->data_voff = 0; // relocated coff_res->code_page = 0; // TODO: whats this for? (lld-link writes zero) // emit symbol for resource data U32 resdat_off = safe_cast_u32(rsrc2->data.total_size); COFF_ObjSymbol *resdat = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("resdat"), resdat_off, rsrc2); // emit reloc for 'data_voff' U64 apply_off = rsrc1->data.total_size + OffsetOf(COFF_ResourceDataEntry, data_voff); U32 apply_off32 = safe_cast_u32(apply_off); coff_obj_writer_section_push_reloc(obj_writer, rsrc1, apply_off32, resdat, COFF_Reloc_X64_Addr32Nb); // push resource entry & data str8_list_push(obj_writer->arena, &rsrc1->data, str8_struct(coff_res)); str8_list_push(obj_writer->arena, &rsrc2->data, res->u.coff_res.data); } break; case PE_ResDataKind_NULL: break; // we must not have this resource node here, it is used to represent on-disk version of entry case PE_ResDataKind_COFF_LEAF: InvalidPath; } } } SLLStackPop(stack); yield:; } scratch_end(scratch); ProfEnd(); } internal void lnk_add_resource_debug_s(COFF_ObjWriter *obj_writer, String8 obj_path, String8 cwd_path, String8 exe_path, CV_Arch arch, String8List res_file_list, MD5 *res_hash_array) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); // init serial for tables String8List string_srl = {0}; String8List file_srl = {0}; str8_serial_begin(scratch.arena, &string_srl); str8_serial_begin(scratch.arena, &file_srl); // reserve first byte for null str8_serial_push_u8(scratch.arena, &string_srl, 0); // build file and string table U64 node_idx = 0; for (String8Node *n = res_file_list.first; n != NULL; n = n->next, ++node_idx) { CV_C13Checksum checksum = {0}; checksum.name_off = string_srl.total_size; checksum.len = sizeof(MD5); checksum.kind = CV_C13ChecksumKind_MD5; str8_serial_push_struct(scratch.arena, &file_srl, &checksum); str8_serial_push_struct(scratch.arena, &file_srl, &res_hash_array[node_idx]); str8_serial_push_align(scratch.arena, &file_srl, CV_FileCheckSumsAlign); str8_serial_push_cstr(scratch.arena, &string_srl, n->string); } // build symbols String8 obj_data = cv_make_obj_name(scratch.arena, obj_path, 0); String8 exe_name_with_ext = str8_skip_last_slash(exe_path); String8 exe_name_ext = str8_skip_last_dot(exe_name_with_ext); String8 exe_name = str8_chop(exe_name_with_ext, exe_name_ext.size); if (exe_name_ext.size > 0) { exe_name = str8_chop(exe_name, 1); } String8 version_string = push_str8f(scratch.arena, BUILD_TITLE_STRING_LITERAL); String8 comp_data = cv_make_comp3(scratch.arena, CV_Compile3Flag_EC, CV_Language_CVTRES, arch, 0, 0, 0, 0, 1, 0, 1, 0, version_string); String8List env_list = {0}; str8_list_push(scratch.arena, &env_list, str8_lit("cwd")); str8_list_push(scratch.arena, &env_list, cwd_path); str8_list_push(scratch.arena, &env_list, str8_lit("exe")); str8_list_push(scratch.arena, &env_list, exe_path); str8_list_push(scratch.arena, &env_list, str8_lit("")); str8_list_push(scratch.arena, &env_list, str8_lit("")); String8 envblock_data = cv_make_envblock(scratch.arena, env_list); String8 obj_symbol = cv_make_symbol(scratch.arena, CV_SymKind_OBJNAME, obj_data); String8 comp_symbol = cv_make_symbol(scratch.arena, CV_SymKind_COMPILE3, comp_data); String8 envblock_symbol = cv_make_symbol(scratch.arena, CV_SymKind_ENVBLOCK, envblock_data); String8List symbol_srl = {0}; str8_serial_begin(scratch.arena, &symbol_srl); str8_serial_push_string(scratch.arena, &symbol_srl, obj_symbol); str8_serial_push_string(scratch.arena, &symbol_srl, comp_symbol); str8_serial_push_string(scratch.arena, &symbol_srl, envblock_symbol); // build code view sub-sections String8List sub_sect_srl = {0}; str8_serial_begin(scratch.arena, &sub_sect_srl); CV_Signature sig = CV_Signature_C13; str8_serial_push_struct(scratch.arena, &sub_sect_srl, &sig); CV_C13SubSectionHeader string_header; string_header.kind = CV_C13SubSectionKind_StringTable; string_header.size = string_srl.total_size; str8_serial_push_struct(scratch.arena, &sub_sect_srl, &string_header); str8_serial_push_data_list(scratch.arena, &sub_sect_srl, string_srl.first); str8_serial_push_align(scratch.arena, &sub_sect_srl, CV_C13SubSectionAlign); CV_C13SubSectionHeader file_header; file_header.kind = CV_C13SubSectionKind_FileChksms; file_header.size = file_srl.total_size; str8_serial_push_struct(scratch.arena, &sub_sect_srl, &file_header); str8_serial_push_data_list(scratch.arena, &sub_sect_srl, file_srl.first); str8_serial_push_align(scratch.arena, &sub_sect_srl, CV_C13SubSectionAlign); CV_C13SubSectionHeader symbol_header; symbol_header.kind = CV_C13SubSectionKind_Symbols; symbol_header.size = symbol_srl.total_size; str8_serial_push_struct(scratch.arena, &sub_sect_srl, &symbol_header); str8_serial_push_data_list(scratch.arena, &sub_sect_srl, symbol_srl.first); str8_serial_push_align(scratch.arena, &sub_sect_srl, CV_C13SubSectionAlign); String8 sub_sect_data = str8_serial_end(obj_writer->arena, &sub_sect_srl); coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS, sub_sect_data); scratch_end(scratch); ProfEnd(); } internal String8 lnk_make_res_obj(Arena *arena, String8List res_data_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena,1); Assert(res_data_list.node_count == res_path_list.node_count); // load res files PE_ResourceDir *root_dir = push_array(scratch.arena, PE_ResourceDir, 1); MD5 *res_hash_array = push_array(scratch.arena, MD5, res_data_list.node_count); U64 node_idx = 0; for (String8Node *node = res_data_list.first; node != 0; node = node->next, node_idx += 1) { res_hash_array[node_idx] = md5_from_data(node->string); pe_resource_dir_push_res_file(scratch.arena, root_dir, node->string); } // convert res paths to stable paths String8List stable_res_file_list = {0}; for (String8Node *node = res_path_list.first; node != 0; node = node->next) { String8 stable_res_path = lnk_make_full_path(scratch.arena, system_path_style, work_dir, node->string); str8_list_push(scratch.arena, &stable_res_file_list, stable_res_path); } // convert res to obj OS_ProcessInfo *process_info = os_get_process_info(); String8List exe_path_strs = {0}; str8_list_push(scratch.arena, &exe_path_strs, process_info->binary_path); String8 exe_path = str8_list_first(&exe_path_strs); String8 res_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); // obj features coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@feat.00"), COFF_SymStorageClass_Static, MSCRT_FeatFlag_HAS_SAFE_SEH|MSCRT_FeatFlag_UNKNOWN_4); // serialize resource tree lnk_serialize_pe_resource_tree(obj_writer, root_dir); // push resource debug info lnk_add_resource_debug_s(obj_writer, obj_name, work_dir, exe_path, cv_arch_from_coff_machine(machine), stable_res_file_list, res_hash_array); // finalize obj res_obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); } scratch_end(scratch); ProfEnd(); return res_obj; } internal String8 lnk_make_linker_coff_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 cwd_path, String8 exe_path, String8 pdb_path, String8 cmd_line, String8 obj_name) { Temp scratch = scratch_begin(&arena, 1); String8 debug_symbols = {0}; { CV_SymbolList symbol_list = { .signature = CV_Signature_C13 }; // S_OBJ String8 obj_data = cv_make_obj_name(scratch.arena, obj_name, 0); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data); // S_COMPILE3 String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data); // S_ENVBLOCK String8List env_list = {0}; str8_list_push(scratch.arena, &env_list, str8_lit("cwd")); str8_list_push(scratch.arena, &env_list, cwd_path); str8_list_push(scratch.arena, &env_list, str8_lit("exe")); str8_list_push(scratch.arena, &env_list, exe_path); str8_list_push(scratch.arena, &env_list, str8_lit("pdb")); str8_list_push(scratch.arena, &env_list, pdb_path); str8_list_push(scratch.arena, &env_list, str8_lit("cmd")); str8_list_push(scratch.arena, &env_list, cmd_line); str8_list_push(scratch.arena, &env_list, str8_lit("")); str8_list_push(scratch.arena, &env_list, str8_lit("")); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_ENVBLOCK, cv_make_envblock(scratch.arena, env_list)); // TODO: emit S_SECTION and S_COFFGROUP // TODO: emit S_TRAMPOLINE debug_symbols = lnk_make_debug_s(scratch.arena, symbol_list); } String8 obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); } scratch_end(scratch); return obj; } internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, config->machine); // Emit __ImageBase symbol. // // This symbol is used with REL32 to compute delta from current IP // to the image base. CRT uses this trick to get to HINSTANCE * without // passing it around as a function argument. // // 100h: lea rax, [rip + ffffff00h] ; -100h coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("__ImageBase"), 0, COFF_SymStorageClass_External); { // load config symbols if (config->machine == COFF_MachineType_X86) { coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME), 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME), 0, COFF_SymStorageClass_External); } // TODO: investigate IMAGE_ENCLAVE_CONFIG 32/64 coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_ENCLAVE_CONFIG_SYMBOL_NAME), 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_FLAGS_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_FIDS_TABLE_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_FIDS_COUNT_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_IAT_TABLE_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_IAT_COUNT_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_LONGJMP_TABLE_SYMBOL_NAME), 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_LONGJMP_COUNT_SYMBOL_NAME), 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_EHCONT_TABLE_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit(MSCRT_GUARD_EHCONT_COUNT_SYMBOL_NAME) , 0, COFF_SymStorageClass_External); } String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 lnk_make_obj_with_undefined_symbols(Arena *arena, String8List symbol_names) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown); for (String8Node *name_n = symbol_names.first; name_n != 0; name_n = name_n->next) { coff_obj_writer_push_symbol_undef(obj_writer, name_n->string); } String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); return obj; } internal void lnk_input_list_push_node(LNK_InputList *list, LNK_Input *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal void lnk_input_list_concat_in_place(LNK_InputList *list, LNK_InputList *to_concat) { SLLConcatInPlace(list, to_concat); } internal LNK_InputPtrArray lnk_array_from_input_list(Arena *arena, LNK_InputList list) { LNK_InputPtrArray result = {0}; result.v = push_array(arena, LNK_Input *, list.count); for (LNK_Input *node = list.first; node != 0; node = node->next, result.count += 1) { result.v[result.count] = node; } return result; } internal LNK_Inputer * lnk_inputer_init(void) { Arena *arena = arena_alloc(); LNK_Inputer *inputer = push_array(arena, LNK_Inputer, 1); inputer->arena = arena; inputer->objs_ht = hash_table_init(arena, 0x20000); inputer->libs_ht = hash_table_init(arena, 0x1000); inputer->missing_lib_ht = hash_table_init(arena, 0x100); return inputer; } internal LNK_Input * lnk_input_push(Arena *arena, LNK_InputList *list, String8 path, String8 data) { LNK_Input *node = push_array(arena, LNK_Input, 1); node->path = path; node->data = data; lnk_input_list_push_node(list, node); return node; } internal LNK_Input * lnk_inputer_push_linkgen(Arena *arena, LNK_InputList *list, String8 data, String8 path) { LNK_Input *input = lnk_input_push(arena, list, data, path); input->exclude_from_debug_info = 1; return input; } internal LNK_Input * lnk_inputer_push_thin(Arena *arena, LNK_InputList *list, HashTable *ht, String8 full_path) { Temp scratch = scratch_begin(&arena, 1); LNK_Input *input = hash_table_search_path_raw(ht, full_path); if (input == 0) { input = lnk_input_push(arena, list, full_path, str8_zero()); input->path = push_str8_copy(arena, full_path); input->is_thin = 1; hash_table_push_path_raw(arena, ht, full_path, input); } scratch_end(scratch); return input; } internal LNK_Input * lnk_inputer_push_obj(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path, String8 data) { lnk_log(LNK_Log_InputObj, "Input Obj: %S", path); LNK_Input *input = lnk_input_push(inputer->arena, &inputer->new_objs, path, data); input->link_member = link_member; return input; } internal LNK_Input * lnk_inputer_push_obj_linkgen(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path, String8 data) { lnk_log(LNK_Log_InputObj, "Input Obj: %S", path); LNK_Input *input = lnk_inputer_push_linkgen(inputer->arena, &inputer->new_objs, path, data); input->link_member = link_member; return input; } internal LNK_Input * lnk_inputer_push_obj_thin(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path) { lnk_log(LNK_Log_InputObj, "Input Obj: %S", path); Temp scratch = scratch_begin(0,0); String8 full_path = os_full_path_from_path(scratch.arena, path); LNK_Input *input = lnk_inputer_push_thin(inputer->arena, &inputer->new_objs, inputer->objs_ht, full_path); input->link_member = link_member; scratch_end(scratch); return input; } internal LNK_Input * lnk_inputer_push_lib(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data) { lnk_log(LNK_Log_InputLib, "Input Lib: %S", path); return lnk_input_push(inputer->arena, &inputer->new_libs[input_source], path, data); } internal LNK_Input * lnk_inputer_push_lib_linkgen(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data) { lnk_log(LNK_Log_InputLib, "Input Lib: %S", path); return lnk_input_push(inputer->arena, &inputer->new_libs[input_source], path, data); } internal LNK_Input * lnk_input_from_path(HashTable *load_ht, String8 path) { LNK_Input *input = hash_table_search_path_raw(load_ht, path); if (input == 0) { Temp scratch = scratch_begin(0, 0); String8 full_path = os_full_path_from_path(scratch.arena, path); input = hash_table_search_path_raw(load_ht, full_path); scratch_end(scratch); } return input; } internal LNK_Input * lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSourceType input_source, String8 path) { Temp scratch = scratch_begin(0,0); LNK_Input *input = 0; // default libraries may omit extension if (input_source == LNK_InputSource_Default || input_source == LNK_InputSource_Obj) { if (!str8_ends_with(path, str8_lit(".lib"), StringMatchFlag_CaseInsensitive)) { path = push_str8f(scratch.arena, "%S.lib", path); } if (lnk_is_lib_disallowed(config, path)) { goto exit; } } // was library already loaded? input = hash_table_search_path_raw(inputer->libs_ht, path); if (input) { goto exit; } // search disk for library String8 first_match = lnk_find_first_file(scratch.arena, config->lib_dir_list, path); // warn about missing library if (first_match.size == 0) { BucketNode *was_reported = hash_table_search_path(inputer->missing_lib_ht, path); if (was_reported == 0) { hash_table_push_path_u64(inputer->arena, inputer->missing_lib_ht, path, 0); lnk_error(LNK_Warning_FileNotFound, "unable to find library `%S`", path); } goto exit; } // was input with full path already loaded? input = hash_table_search_path_raw(inputer->libs_ht, first_match); if (input) { goto exit; } lnk_log(LNK_Log_InputLib, "Input Lib: %S", first_match); input = lnk_inputer_push_thin(inputer->arena, &inputer->new_libs[input_source], inputer->libs_ht, first_match); // store input path to early-out of file searches for default libs if (!str8_match(first_match, path, StringMatchFlag_CaseInsensitive)) { hash_table_push_path_raw(inputer->arena, inputer->libs_ht, path, input); } exit:; scratch_end(scratch); return input; } internal B32 lnk_inputer_has_items(LNK_Inputer *inputer) { if (inputer->new_objs.count > 0) { return 1; } for EachIndex(i, ArrayCount(inputer->new_libs)) { if (inputer->new_libs[i].count > 0) { return 1; } } return 0; } internal LNK_InputPtrArray lnk_inputer_flush(Arena *arena, TP_Context *tp, LNK_Inputer *inputer, LNK_IO_Flags io_flags, LNK_InputList *all_inputs, LNK_InputList *new_inputs) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); ProfBegin("Gather Thin Inputs"); U64 thin_inputs_count = 0; for (LNK_Input *node = new_inputs->first; node != 0; node = node->next) { if (node->is_thin) { thin_inputs_count += 1; } } LNK_Input **thin_inputs = push_array(scratch.arena, LNK_Input *, thin_inputs_count); U64 thin_idx = 0; for (LNK_Input *node = new_inputs->first; node != 0; node = node->next) { if (node->is_thin) { thin_inputs[thin_idx++] = node; } } String8Array thin_input_paths = {0}; thin_input_paths.count = thin_inputs_count; thin_input_paths.v = push_array(scratch.arena, String8, thin_inputs_count); for EachIndex(i, thin_inputs_count) { thin_input_paths.v[i] = thin_inputs[i]->path; } ProfEnd(); ProfBegin("Load Inputs From Disk"); String8Array thin_input_datas = lnk_read_data_from_file_path_parallel(tp, inputer->arena, io_flags, thin_input_paths); for EachIndex(thin_input_idx, thin_inputs_count) { thin_inputs[thin_input_idx]->has_disk_read_failed = thin_input_datas.v[thin_input_idx].size == 0; thin_inputs[thin_input_idx]->data = thin_input_datas.v[thin_input_idx]; } ProfEnd(); ProfBegin("Disk Read Check"); for EachIndex(i, thin_inputs_count) { if (thin_inputs[i]->has_disk_read_failed) { lnk_error(LNK_Error_InvalidPath, "unable to find file \"%S\"", thin_inputs[i]->path); } } ProfEnd(); LNK_InputPtrArray result = lnk_array_from_input_list(arena, *new_inputs); lnk_input_list_concat_in_place(all_inputs, new_inputs); scratch_end(scratch); ProfEnd(); return result; } internal void lnk_lib_member_ref_list_push_node(LNK_LibMemberRefList *list, LNK_LibMemberRef *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal void lnk_lib_member_ref_list_concat_in_place_array(LNK_LibMemberRefList *list, LNK_LibMemberRefList *to_concat_arr, U64 count) { SLLConcatInPlaceArray(list, to_concat_arr, count); } internal int lnk_lib_member_ref_is_before(void *raw_a, void *raw_b) { LNK_LibMemberRef **a = raw_a, **b = raw_b; LNK_Symbol *a_pull_in_ref = (*a)->lib->member_links[(*a)->member_idx]; LNK_Symbol *b_pull_in_ref = (*b)->lib->member_links[(*b)->member_idx]; return lnk_symbol_is_before(a_pull_in_ref, b_pull_in_ref); } internal LNK_LibMemberRef ** lnk_array_from_lib_member_list(Arena *arena, LNK_LibMemberRefList list) { LNK_LibMemberRef **result = push_array(arena, LNK_LibMemberRef *, list.count); U64 idx = 0; for (LNK_LibMemberRef *node = list.first; node != 0; node = node->next, idx += 1) { result[idx] = node; } return result; } internal LNK_ObjNode * lnk_load_objs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link, U64 *objs_count_out) { ProfBeginV("Load Objs [Count %llu]", inputer->new_objs.count); Temp scratch = scratch_begin(arena->v, arena->count); // load obj inputer from disk LNK_InputPtrArray new_input_objs = lnk_inputer_flush(arena->v[0], tp, inputer, config->io_flags, &inputer->objs, &inputer->new_objs); if (lnk_get_log_status(LNK_Log_InputObj) && new_input_objs.count) { U64 input_size = 0; for EachIndex(i, new_input_objs.count) { input_size += new_input_objs.v[i]->data.size; } lnk_log(LNK_Log_InputObj, "[ Obj Input Size %M ]", input_size); } LNK_ObjNode *new_objs = lnk_obj_from_input_many(tp, arena, config->machine, new_input_objs.count, new_input_objs.v); // if machine type was unspecified on the command line, derive it from obj file if (config->machine == COFF_MachineType_Unknown) { for EachIndex(obj_idx, new_input_objs.count) { if (new_objs[obj_idx].data.header.machine != COFF_MachineType_Unknown) { config->machine = new_objs[obj_idx].data.header.machine; break; } } } ProfBegin("Apply Directives"); for EachIndex(obj_idx, new_input_objs.count) { LNK_Obj *obj = &new_objs[obj_idx].data; String8List raw_directives = lnk_raw_directives_from_obj(scratch.arena, obj); LNK_DirectiveInfo directive_info = lnk_directive_info_from_raw_directives(scratch.arena, obj, raw_directives); for EachIndex(i, ArrayCount(directive_info.v)) { for (LNK_Directive *dir = directive_info.v[i].first; dir != 0; dir = dir->next) { lnk_apply_cmd_option_to_config(config, dir->id, dir->value_list, obj); } } } ProfEnd(); if (objs_count_out) { *objs_count_out = new_input_objs.count; } scratch_end(scratch); ProfEnd(); return new_objs; } internal void lnk_load_libs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_Link *link) { for EachIndex(input_source, LNK_InputSource_Count) { ProfBegin("Input Libs [Count %llu]", inputer->new_libs[input_source].count); LNK_InputPtrArray new_input_libs = lnk_inputer_flush(arena->v[0], tp, inputer, config->io_flags, &inputer->libs, &inputer->new_libs[input_source]); if (lnk_get_log_status(LNK_Log_InputLib) && new_input_libs.count) { U64 input_size = 0; for EachIndex(i, new_input_libs.count) { input_size += new_input_libs.v[i]->data.size; } lnk_log(LNK_Log_InputObj, "[ Lib Input Size %M ]", input_size); } lnk_lib_list_push_parallel(tp, arena, &link->libs, new_input_libs.count, new_input_libs.v); ProfEnd(); } } internal void lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); U64 obj_id_base = link->objs.count; U64 objs_count = 0; LNK_ObjNode *objs = lnk_load_objs(tp, arena, config, inputer, symtab, link, &objs_count); lnk_obj_list_push_node_many(&link->objs, objs_count, objs); // if delay load DLLs are present, include delay load helper symbol if (config->machine != COFF_MachineType_Unknown && config->delay_load_helper_name.size == 0 && config->delay_load_dll_list.node_count) { config->delay_load_helper_name = mscrt_delay_load_helper_name_from_machine(config->machine); if (config->delay_load_helper_name.size) { lnk_include_symbol(config, config->delay_load_helper_name, 0); } } { ProfBegin("Process /INCLUDE"); // group include symbols by obj HashTable *ht = hash_table_init(scratch.arena, 64); for (; *link->last_include; link->last_include = &(*link->last_include)->next) { LNK_IncludeSymbol *include_symbol = &(*link->last_include)->v; // skip, include symbol is already in the global symbol table if (lnk_symbol_table_search(symtab, include_symbol->name)) { continue; } // was obj already seen? String8List *include_name_list = hash_table_search_raw_raw(ht, include_symbol->obj); if (include_name_list == 0) { // push entry for new obj include_name_list = push_array(scratch.arena, String8List, 1); hash_table_push_raw_raw(scratch.arena, ht, include_symbol->obj, include_name_list); } // append include symbol to obj's name list str8_list_push(scratch.arena, include_name_list, include_symbol->name); } LNK_Obj **objs_with_includes = keys_from_hash_table_raw(scratch.arena, ht); String8List **include_names = values_from_hash_table_raw(scratch.arena, ht); for EachIndex(i, ht->count) { LNK_Obj *obj_with_includes = objs_with_includes[i]; String8 include_obj_path = obj_with_includes ? obj_with_includes->path : str8_lit("RADLINK"); String8 include_obj_data = lnk_make_obj_with_undefined_symbols(arena->v[0], *include_names[i]); lnk_inputer_push_obj_linkgen(inputer, obj_with_includes ? obj_with_includes->link_member : 0, include_obj_path, include_obj_data); U64 include_obj_count = 0; LNK_ObjNode *include_obj = lnk_load_objs(tp, arena, config, inputer, symtab, link, &include_obj_count); AssertAlways(include_obj_count == 1); if (obj_with_includes) { DLLInsert(link->objs.first, link->objs.last, obj_with_includes->node, include_obj); link->objs.count += 1; } else { lnk_obj_list_push_node(&link->objs, include_obj); } } ProfEnd(); } // finalize input indices on new objs and push external symbols to the symbol table { U64 node_idx = 0; for (LNK_ObjNode **n = link->last_symbol_input; *n; n = &(*n)->next, node_idx += 1) { (*n)->data.input_idx = obj_id_base + node_idx; } U64 new_objs_count = node_idx; LNK_Obj **new_objs = push_array(scratch.arena, LNK_Obj *, node_idx); node_idx = 0; for (; *link->last_symbol_input; link->last_symbol_input = &(*link->last_symbol_input)->next, node_idx += 1) { new_objs[node_idx] = &(*link->last_symbol_input)->data; } lnk_push_obj_symbols(tp, arena, symtab, new_objs_count, new_objs); } // input default libraries for (; *link->last_default_lib; link->last_default_lib = &(*link->last_default_lib)->next) { lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Default, (*link->last_default_lib)->string); } // input libraries referenced in objs for (; *link->last_obj_lib; link->last_obj_lib = &(*link->last_obj_lib)->next) { lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, (*link->last_obj_lib)->string); } // load new libs lnk_load_libs(tp, arena, config, inputer, link); // resolve entry point if (link->try_to_resolve_entry_point) { B32 is_entry_point_name_inferred = config->entry_point_name.size == 0; // loop over all possible subsystems and entry point names and pick // subsystem that has a defined entry point symbol if (config->entry_point_name.size == 0) { PE_WindowsSubsystem subsys_first = config->subsystem; PE_WindowsSubsystem subsys_last = config->subsystem == PE_WindowsSubsystem_UNKNOWN ? PE_WindowsSubsystem_COUNT : config->subsystem+1; LNK_Symbol *entry_point_symbol = 0; for (U64 subsys_idx = subsys_first; subsys_idx < subsys_last; subsys_idx += 1) { String8Array entry_points = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics); for EachIndex(i, entry_points.count) { LNK_Symbol *symbol = lnk_symbol_table_search(symtab, entry_points.v[i]); if (symbol) { config->subsystem = subsys_idx; config->entry_point_name = entry_points.v[i]; goto found_entry_and_subsystem; } } } found_entry_and_subsystem:; } // search for entry point in libs if (config->entry_point_name.size == 0 && config->subsystem != PE_WindowsSubsystem_UNKNOWN) { String8Array entry_points = pe_get_entry_point_names(config->machine, config->subsystem, config->file_characteristics); for EachIndex(entry_idx, entry_points.count) { for (LNK_LibNode *lib_n = link->libs.first; lib_n != 0; lib_n = lib_n->next) { if (lnk_search_lib(&lib_n->data, entry_points.v[entry_idx], 0)) { config->entry_point_name = entry_points.v[entry_idx]; goto found_entry_in_libs; } } } found_entry_in_libs:; } // infer subsystem from entry point name if (config->entry_point_name.size != 0 && config->subsystem == PE_WindowsSubsystem_UNKNOWN) { for EachIndex(subsys_idx, PE_WindowsSubsystem_COUNT) { String8Array entry_points = pe_get_entry_point_names(config->machine, subsys_idx, config->file_characteristics); for EachIndex(i, entry_points.count) { if (str8_match(entry_points.v[i], config->entry_point_name, 0)) { config->subsystem = subsys_idx; goto subsystem_inferred_from_entry; } } } subsystem_inferred_from_entry:; } // do we have an entry point name? if (config->entry_point_name.size) { if (is_entry_point_name_inferred) { // redirect user entry to appropriate CRT entry String8 crt_entry_point_name = msvcrt_ctr_entry_from_user_entry(config->entry_point_name); config->entry_point_name = crt_entry_point_name.size ? crt_entry_point_name : config->entry_point_name; } // generate undefined symbol for entry point lnk_include_symbol(config, config->entry_point_name, 0); // do we have a subsystem? if (config->subsystem != PE_WindowsSubsystem_UNKNOWN) { // if subsystem version not specified set default values if (config->subsystem_ver.major == 0 && config->subsystem_ver.minor == 0) { config->subsystem_ver = lnk_get_default_subsystem_version(config->subsystem, config->machine); } // check subsystem version against allowed min version Version min_subsystem_ver = lnk_get_min_subsystem_version(config->subsystem, config->machine); if (version_compar(config->subsystem_ver, min_subsystem_ver) < 0) { lnk_error(LNK_Error_Cmdl, "subsystem version %I64u.%I64u can't be lower than %I64u.%I64u", config->subsystem_ver.major, config->subsystem_ver.minor, min_subsystem_ver.major, min_subsystem_ver.minor); } // by default terminal server is enabled for windows and console applications if (~config->flags & LNK_ConfigFlag_NoTsAware && ~config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { if (config->subsystem == PE_WindowsSubsystem_WINDOWS_GUI || config->subsystem == PE_WindowsSubsystem_WINDOWS_CUI) { config->dll_characteristics |= PE_DllCharacteristic_TERMINAL_SERVER_AWARE; } } // entry point found! link->try_to_resolve_entry_point = 0; } else { lnk_error(LNK_Error_NoSubsystem, "unknown subsystem, please use /SUBSYSTEM to set subsytem type you need"); } } } scratch_end(scratch); ProfEnd(); } internal void lnk_queue_lib_member(Arena *arena, LNK_LibMemberRefList *queued_members, LNK_Symbol *link_symbol, LNK_Lib *lib, U32 member_idx) { B32 was_linked = lnk_lib_set_link_symbol(lib, member_idx, link_symbol); if (was_linked) { LNK_LibMemberRef *member_ref = push_array(arena, LNK_LibMemberRef, 1); member_ref->lib = lib; member_ref->member_idx = member_idx; lnk_lib_member_ref_list_push_node(queued_members, member_ref); } } internal THREAD_POOL_TASK_FUNC(lnk_search_lib_task) { LNK_SearchLibTask *task = raw_task; LNK_Lib *lib = task->lib; LNK_SymbolTable *symtab = task->symtab; B32 search_anti_deps = task->search_anti_deps; LNK_LibMemberRefList *member_ref_list = &task->member_ref_lists[task_id]; for EachNode(c, LNK_SymbolHashTrieChunk, symtab->search_chunks[task_id].first) { for EachIndex(i, c->count) { LNK_Symbol *symbol = c->v[i].symbol; LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); if (symbol_interp == COFF_SymbolValueInterp_Undefined) { U32 member_idx; if (lnk_search_lib(lib, symbol->name, &member_idx)) { lnk_queue_lib_member(arena, member_ref_list, symbol, lib, member_idx); } } else if (symbol_interp == COFF_SymbolValueInterp_Weak) { COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol_ref.obj->header.is_big_obj); if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) { U32 member_idx; if (lnk_search_lib(lib, symbol->name, &member_idx)) { lnk_queue_lib_member(arena, member_ref_list, symbol, lib, member_idx); } } else if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) { if (search_anti_deps) { LNK_ObjSymbolRef dep_symbol = {0}; if (lnk_resolve_weak_symbol(symtab, symbol_ref, &dep_symbol)) { COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dep_symbol.obj, dep_symbol.symbol_idx); COFF_SymbolValueInterpType dep_interp = coff_interp_from_parsed_symbol(dep_parsed); if (dep_interp == COFF_SymbolValueInterp_Weak) { U32 member_idx; if (lnk_search_lib(lib, symbol_parsed.name, &member_idx)) { lnk_queue_lib_member(arena, member_ref_list, symbol, lib, member_idx); } } } } } } } } } internal void lnk_link_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); LNK_LibMemberRefList *member_ref_lists = push_array(scratch.arena, LNK_LibMemberRefList, tp->worker_count); B32 search_anti_deps = 0; for (U64 resolved_members_count = 0; ; resolved_members_count = 0) { lnk_load_inputs(tp, arena, config, inputer, symtab, link); for EachNode(lib_n, LNK_LibNode, link->libs.first) { LNK_Lib *lib = &lib_n->data; ProfBeginV("Search %S", str8_skip_last_slash(lib->path)); do { lnk_load_inputs(tp, arena, config, inputer, symtab, link); // search symbols in lib MemoryZeroTyped(member_ref_lists, tp->worker_count); tp_for_parallel(tp, arena, tp->worker_count, lnk_search_lib_task, &(LNK_SearchLibTask){ .search_anti_deps = search_anti_deps, .lib = lib, .symtab = symtab, .member_ref_lists = member_ref_lists }); LNK_LibMemberRefList queued_members = {0}; lnk_lib_member_ref_list_concat_in_place_array(&queued_members, member_ref_lists, tp->worker_count); // sort library member refs to match the order of their appearance in obj symbol tables LNK_LibMemberRef **member_refs = lnk_array_from_lib_member_list(scratch.arena, queued_members); //qsort(member_refs, queued_members.count, sizeof(member_refs[0]), lnk_lib_member_ref_compar); radsort(member_refs, queued_members.count, lnk_lib_member_ref_is_before); if (queued_members.count) { lnk_log(LNK_Log_Links, "Searching %S:", lib_n->data.path); for EachIndex(i, queued_members.count) { Temp temp = temp_begin(scratch.arena); LNK_LibMemberRef *member_ref = member_refs[i]; LNK_Lib *lib = member_ref->lib; LNK_Symbol *link_symbol = lib->member_links[member_ref->member_idx]; COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_ref->member_idx]); COFF_DataType member_type = coff_data_type_from_data(member_info.data); String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name); U64 refs_count = 0; LNK_ObjSymbolRef **refs = lnk_ref_from_symbol_many(temp.arena, link_symbol, &refs_count); lnk_log(LNK_Log_Links, "\tFound %S in %S", link_symbol->name, str8_skip_last_slash(member_name)); for EachIndex(i, refs_count) { lnk_log(LNK_Log_Links, "\t\tReferenced in %S", lnk_loc_from_obj(temp.arena, refs[i]->obj)); } temp_end(temp); } } // push inputs for lib member refs for EachIndex(i, queued_members.count) { LNK_LibMemberRef *member_ref = member_refs[i]; U64 member_idx = member_ref->member_idx; // parse member info COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_idx]); COFF_DataType member_type = coff_data_type_from_data(member_info.data); String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name); switch (member_type) { case COFF_DataType_Import: { LNK_Symbol *link_symbol = lib->member_links[member_idx]; LNK_Symbol *import_symbols[2] = {0}; if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) { import_symbols[0] = link_symbol; import_symbols[1] = lnk_symbol_table_search(symtab, str8_skip(link_symbol->name, str8_lit("__imp_").size)); } else { Temp temp = temp_begin(scratch.arena); String8 imp_name = push_str8f(temp.arena, "__imp_%S", link_symbol->name); import_symbols[0] = lnk_symbol_table_search(symtab, imp_name); import_symbols[1] = link_symbol; temp_end(temp); } for EachIndex(i, ArrayCount(import_symbols)) { LNK_Symbol *import_symbol = import_symbols[i]; if (import_symbol == 0) { continue; } LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, str8_lit(LNK_IMPORT_STUB)); // same import symbol must never be queued more than once, if it is, there is a bug in the link set logic AssertAlways(import_symbol->refs != import_stub->refs); // replace the import symbol with a stub, which is later replaced with the real import symbol once import obj is ready import_symbol->refs = import_stub->refs; } // push import member for import obj generation lnk_lib_member_ref_list_push_node(&link->imports, member_ref); } break; case COFF_DataType_BigObj: case COFF_DataType_Obj: { if (lib->type == COFF_Archive_Thin) { // obj path in thin archive is relative to the directory with lib String8List obj_path_list = {0}; str8_list_push(scratch.arena, &obj_path_list, str8_chop_last_slash(lib->path)); str8_list_push(scratch.arena, &obj_path_list, member_name); String8 obj_path = str8_path_list_join_by_style(inputer->arena, &obj_path_list, config->path_style); lnk_inputer_push_obj_thin(inputer, member_ref, obj_path); } else { lnk_inputer_push_obj(inputer, member_ref, member_name, member_info.data); } } break; case COFF_DataType_Null: break; default: { InvalidPath; } break; } } resolved_members_count += queued_members.count; } while (lnk_inputer_has_items(inputer)); ProfEnd(); } if (resolved_members_count == 0) { search_anti_deps = 0; // replace undefined symbols that have an alternate name with a weak symbol for (LNK_AltNameNode *alt_name_n = config->alt_name_list.first; alt_name_n != 0; alt_name_n = alt_name_n->next) { LNK_SymbolHashTrie *symbol_ht = lnk_symbol_table_search_(symtab, alt_name_n->v.from); if (symbol_ht) { COFF_SymbolValueInterpType interp = lnk_interp_from_symbol(symbol_ht->symbol); if (interp == COFF_SymbolValueInterp_Undefined) { // clear out slot so weak symbol can replace undefined symbol (general rule is // weak symbol is not allowed to replace undefined) LNK_Symbol *undef_symbol = symbol_ht->symbol; symbol_ht->symbol = 0; // make obj with alternamte name symbol String8 alt_name_obj_data; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown); COFF_ObjSymbol *from_symbol = coff_obj_writer_push_symbol_weak(obj_writer, alt_name_n->v.from, COFF_WeakExt_SearchLibrary, 0); COFF_ObjSymbol *to_symbol = coff_obj_writer_push_symbol_weak(obj_writer, alt_name_n->v.to, COFF_WeakExt_AntiDependency, from_symbol); coff_obj_writer_set_default_symbol(from_symbol, to_symbol); alt_name_obj_data = coff_obj_writer_serialize(arena->v[0], obj_writer); coff_obj_writer_release(&obj_writer); } LNK_Obj *obj_with_alt_name = alt_name_n->v.obj; String8 obj_with_alt_name_path = obj_with_alt_name ? obj_with_alt_name->path : str8_lit("RADLINK"); lnk_inputer_push_obj_linkgen(inputer, obj_with_alt_name ? obj_with_alt_name->link_member : 0, obj_with_alt_name_path, alt_name_obj_data); search_anti_deps = 1; } } } resolved_members_count = lnk_inputer_has_items(inputer); } if (resolved_members_count == 0) { break; } } scratch_end(scratch); ProfEnd(); } internal LNK_Link * lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); // // init link context // LNK_Link *link = push_array(arena->v[0], LNK_Link, 1); link->last_symbol_input = &link->objs.first; link->last_include = &config->include_symbol_list.first; link->last_default_lib = &config->input_default_lib_list.first; link->last_obj_lib = &config->input_obj_lib_list.first; link->last_cmd_lib = &config->input_list[LNK_Input_Lib].first; link->try_to_resolve_entry_point = 1; // input :null_obj String8 null_obj = lnk_make_null_obj(inputer->arena); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Null *"), null_obj); // input objs on command line for (String8Node *obj_path = config->input_list[LNK_Input_Obj].first; obj_path != 0; obj_path = obj_path->next) { lnk_inputer_push_obj_thin(inputer, 0, obj_path->string); } // input libs from command line for (; *link->last_cmd_lib; link->last_cmd_lib = &(*link->last_cmd_lib)->next) { lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_CmdLine, (*link->last_cmd_lib)->string); } // link inputer lnk_link_inputs(tp, arena, config, inputer, symtab, link); // TODO: need to figure out under what condition to include load config //lnk_include_symbol(config, str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME), 0); { ProfBegin("Push Linker Symbols"); String8 linker_symbols_obj = lnk_make_linker_obj(arena->v[0], config); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Linker Symbols *"), linker_symbols_obj); ProfEnd(); } // // make imports // { HashTable *static_imports_ht = hash_table_init(scratch.arena, 0x1000); HashTable *delayed_imports_ht = hash_table_init(scratch.arena, 0x1000); String8List delayed_dll_names = {0}; String8List static_dll_names = {0}; for EachNode(member_ref, LNK_LibMemberRef, link->imports.first) { LNK_Lib *lib = member_ref->lib; U64 member_idx = member_ref->member_idx; LNK_Symbol *link_symbol = lib->member_links[member_idx]; COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_idx]); COFF_DataType member_type = coff_data_type_from_data(member_info.data); String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name); COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(member_info.data); // import machine compat check if (import_header.machine != config->machine) { LNK_ObjSymbolRef ref = lnk_ref_from_symbol(link_symbol); lnk_error_obj(LNK_Error_IncompatibleMachine, ref.obj, "symbol %S pulls-in import from %S with an incompatible machine %S (expected machine %S)", link_symbol->name, str8_chop_last_slash(lib->path), coff_string_from_machine_type(import_header.machine), coff_string_from_machine_type(config->machine)); break; } // find DLL with import symbols B32 is_delay_load = lnk_is_dll_delay_load(config, import_header.dll_name); String8List *dll_names = is_delay_load ? &delayed_dll_names : &static_dll_names; HashTable *imports_ht = is_delay_load ? delayed_imports_ht : static_imports_ht; PE_MakeImportList *import_symbols = hash_table_search_path_raw(imports_ht, import_header.dll_name); // create record for a first time-DLL if (import_symbols == 0) { import_symbols = push_array(scratch.arena, PE_MakeImportList, 1); str8_list_push(scratch.arena, dll_names, import_header.dll_name); hash_table_push_path_raw(scratch.arena, imports_ht, import_header.dll_name, import_symbols); } B32 make_jump_thunk = 1; if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) { LNK_Symbol *thunk_symbol = lnk_symbol_table_search(symtab, str8_skip(link_symbol->name, str8_lit("__imp_").size)); make_jump_thunk = thunk_symbol != 0; } // push make import info pe_make_import_header_list_push(scratch.arena, import_symbols, (PE_MakeImport){ .header = member_info.data, .make_jump_thunk = make_jump_thunk }); } AssertAlways(delayed_dll_names.node_count == delayed_imports_ht->count); AssertAlways(static_dll_names.node_count == static_imports_ht->count); // make and input delayed imports if (delayed_imports_ht->count) { ProfBegin("Build Delay Import Table"); COFF_TimeStamp time_stamp = COFF_TimeStamp_Max; B32 emit_biat = config->import_table_emit_biat == LNK_SwitchState_Yes; B32 emit_uiat = config->import_table_emit_uiat == LNK_SwitchState_Yes; for (String8Node *dll_name_n = delayed_dll_names.first; dll_name_n != 0; dll_name_n = dll_name_n->next) { PE_MakeImportList *imports = hash_table_search_path_raw(delayed_imports_ht, dll_name_n->string); String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_name_n->string); String8 import_obj = pe_make_import_dll_obj_delayed(arena->v[0], time_stamp, config->machine, dll_name_n->string, config->delay_load_helper_name, import_debug_symbols, *imports, emit_biat, emit_uiat); lnk_inputer_push_obj(inputer, 0, dll_name_n->string, import_obj); } String8 linker_debug_symbols = lnk_make_linker_debug_symbols(arena->v[0], config->machine); String8 null_desc_obj = pe_make_null_import_descriptor_delayed(arena->v[0], time_stamp, config->machine, linker_debug_symbols); String8 null_thunk_obj = pe_make_null_thunk_data_obj_delayed(arena->v[0], lnk_get_image_name(config), time_stamp, config->machine, linker_debug_symbols); lnk_inputer_push_obj(inputer, 0, str8_lit("* Delayed Null Import Descriptor *"), null_desc_obj); lnk_inputer_push_obj(inputer, 0, str8_lit("* Delayed Null Thunk Data *"), null_thunk_obj); ProfEnd(); } // make and input static imports if (static_imports_ht->count) { ProfBegin("Build Static Import Table"); COFF_TimeStamp time_stamp = COFF_TimeStamp_Max; for (String8Node *dll_name_n = static_dll_names.first; dll_name_n != 0; dll_name_n = dll_name_n->next) { PE_MakeImportList *imports = hash_table_search_path_raw(static_imports_ht, dll_name_n->string); String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_name_n->string); String8 import_obj = pe_make_import_dll_obj_static(arena->v[0], time_stamp, config->machine, dll_name_n->string, import_debug_symbols, *imports); lnk_inputer_push_obj(inputer, 0, dll_name_n->string, import_obj); } String8 linker_debug_symbols = lnk_make_linker_debug_symbols(scratch.arena, config->machine); String8 null_desc_obj = pe_make_null_import_descriptor_obj(arena->v[0], time_stamp, config->machine, linker_debug_symbols); String8 null_thunk_obj = pe_make_null_thunk_data_obj(arena->v[0], lnk_get_image_name(config), time_stamp, config->machine, linker_debug_symbols); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Null Import Descriptor *"), null_desc_obj); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Null Thunk Data *"), null_thunk_obj); ProfEnd(); } // warn about unused delayloads if (config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll) { for (String8Node *dll_name_n = config->delay_load_dll_list.first; dll_name_n != 0; dll_name_n = dll_name_n->next) { if (!hash_table_search_path_raw(delayed_imports_ht, dll_name_n->string)) { lnk_error(LNK_Warning_UnusedDelayLoadDll, "/DELAYLOAD: %S found no imports", dll_name_n->string); } } } } if (config->export_symbol_list.count) { ProfBegin("Build Export Table"); PE_ExportParseList resolved_exports = {0}; for (PE_ExportParseNode *exp_n = config->export_symbol_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) { exp_n_next = exp_n->next; PE_ExportParse *exp = &exp_n->data; if (str8_match(exp->name, config->entry_point_name, 0)) { lnk_error_with_loc(LNK_Warning_TryingToExportEntryPoint, exp->obj_path, exp->lib_path, "exported entry point \"%S\"", exp->name); } if (str8_match(exp->alias, config->entry_point_name, 0)) { lnk_error_with_loc(LNK_Warning_TryingToExportEntryPoint, exp->obj_path, exp->lib_path, "alias exports entry point \"%S=%S\"", exp->name, exp->alias); continue; } if (!exp->is_forwarder) { // filter out unresolved exports LNK_Symbol *symbol = lnk_symbol_table_search(symtab, exp_n->data.name); if (symbol == 0) { lnk_error_with_loc(LNK_Warning_IllExport, exp->obj_path, exp->lib_path, "unresolved export symbol %S\n", exp->name); continue; } } // push resolved export pe_export_parse_list_push_node(&resolved_exports, exp_n); } PE_FinalizedExports finalized_exports = pe_finalize_export_list(scratch.arena, resolved_exports); String8 edata_obj = pe_make_edata_obj(arena->v[0], str8_skip_last_slash(config->image_name), COFF_TimeStamp_Max, config->machine, finalized_exports); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Exports *"), edata_obj); ProfEnd(); } { String8List res_data_list = {0}; String8List res_path_list = {0}; // do we have manifest deps passed through pragma alone? LNK_ManifestOpt manifest_opt = config->manifest_opt; if (config->manifest_dependency_list.node_count > 0 && manifest_opt == LNK_ManifestOpt_Null) { manifest_opt = LNK_ManifestOpt_Embed; } switch (manifest_opt) { case LNK_ManifestOpt_Embed: { ProfBegin("Embed Manifest"); // TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest // resource to the tree directly String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, config->input_list[LNK_Input_Manifest], config->manifest_dependency_list); String8 manifest_res = pe_make_manifest_resource(scratch.arena, *config->manifest_resource_id, manifest_data); str8_list_push(scratch.arena, &res_data_list, manifest_res); str8_list_push(scratch.arena, &res_path_list, str8_lit("* Manifest *")); ProfEnd(); } break; case LNK_ManifestOpt_WriteToFile: { ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name)); Temp temp = temp_begin(scratch.arena); String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, config->input_list[LNK_Input_Manifest], config->manifest_dependency_list); lnk_write_data_to_file_path(config->manifest_name, str8_zero(), manifest_data); temp_end(temp); ProfEnd(); } break; case LNK_ManifestOpt_Null: { Assert(config->input_list[LNK_Input_Manifest].node_count == 0); Assert(config->manifest_dependency_list.node_count == 0); } break; case LNK_ManifestOpt_No: { // omit manifest generation } break; } ProfBegin("Load .res files from disk"); for (String8Node *node = config->input_list[LNK_Input_Res].first; node != 0; node = node->next) { String8 res_data = lnk_read_data_from_file_path(scratch.arena, config->io_flags, node->string); if (res_data.size > 0) { if (pe_is_res(res_data)) { str8_list_push(scratch.arena, &res_data_list, res_data); String8 stable_res_path = lnk_make_full_path(scratch.arena, config->path_style, config->work_dir, node->string); str8_list_push(scratch.arena, &res_path_list, stable_res_path); } else { lnk_error(LNK_Error_LoadRes, "file is not of RES format: %S", node->string); } } else { lnk_error(LNK_Error_LoadRes, "unable to open res file: %S", node->string); } } ProfEnd(); if (res_data_list.node_count > 0) { ProfBegin("Build * Resources *"); String8 obj_name = str8_lit("* Resources *"); String8 obj_data = lnk_make_res_obj(arena->v[0], res_data_list, res_path_list, config->machine, config->time_stamp, config->work_dir, config->path_style, obj_name); lnk_inputer_push_obj_linkgen(inputer, 0, obj_name, obj_data); ProfEnd(); } } if (lnk_do_debug_info(config)) { { ProfBegin("Build * Linker * Obj"); String8 obj_name = str8_lit("* Linker *"); String8 raw_cmd_line = str8_list_join(scratch.arena, &config->raw_cmd_line, &(StringJoin){ str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }); String8 obj_data = lnk_make_linker_coff_obj(arena->v[0], config->time_stamp, config->machine, config->work_dir, config->image_name, config->pdb_name, raw_cmd_line, obj_name); lnk_inputer_push_obj_linkgen(inputer, 0, obj_name, obj_data); ProfEnd(); } ProfBegin("Build * Debug Directories *"); if (config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null) { String8 pdb_dir_obj = pe_make_debug_directory_pdb_obj(arena->v[0], config->machine, config->guid, config->age, config->time_stamp, config->pdb_alt_path); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Debug Directory PDB *"), pdb_dir_obj); } if (config->rad_debug == LNK_SwitchState_Yes) { String8 rdi_dir_obj = pe_make_debug_directory_rdi_obj(arena->v[0], config->machine, config->guid, config->age, config->time_stamp, config->rad_debug_alt_path); lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Debug Directory RDI *"), rdi_dir_obj); } ProfEnd(); } // // link linker made objs // lnk_link_inputs(tp, arena, config, inputer, symtab, link); // // finalize symbol table // lnk_replace_weak_with_default_symbols(tp, symtab); // // was entry point resolved? // if (config->entry_point_name.size == 0 || link->try_to_resolve_entry_point) { lnk_error(LNK_Error_EntryPoint, "unable to find entry point symbol"); } // // report unresolved symbols // { ProfBegin("Report Unresolved Symbols"); U64 unresolved_symbols_count = 0; LNK_Symbol **unresolved_symbols = 0; { U64 chunks_count = 0; LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunks, symtab->arena->count, &chunks_count); for EachIndex(chunk_idx, chunks_count) { LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; for EachIndex(i, chunk->count) { LNK_Symbol *symbol = chunk->v[i].symbol; COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); if (symbol_interp == COFF_SymbolValueInterp_Undefined) { unresolved_symbols_count += 1; } } } unresolved_symbols = push_array(scratch.arena, LNK_Symbol *, unresolved_symbols_count); if (unresolved_symbols_count) { U64 cursor = 0; for EachIndex(chunk_idx, chunks_count) { LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; for EachIndex(i, chunk->count) { LNK_Symbol *symbol = chunk->v[i].symbol; if (lnk_interp_from_symbol(symbol) == COFF_SymbolValueInterp_Undefined) { unresolved_symbols[cursor++] = chunk->v[i].symbol; } } } } radsort(unresolved_symbols, unresolved_symbols_count, lnk_symbol_ptr_is_before); } for EachIndex(i, unresolved_symbols_count) { LNK_Symbol *symbol = unresolved_symbols[i]; if (i > config->unresolved_symbol_limit) { lnk_error(LNK_Error_UnresolvedSymbol, "too many unresolved symbol errors, stopping now"); break; } String8List supp_info = {0}; { U64 refs_count = 0; LNK_ObjSymbolRef **refs = lnk_ref_from_symbol_many(scratch.arena, symbol, &refs_count); for EachIndex(ref_idx, refs_count) { LNK_ObjSymbolRef *ref = refs[ref_idx]; LNK_Obj *obj = ref->obj; COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); String8 string_table = lnk_coff_string_table_from_obj(obj); CV_DebugS debug_s = {0}; CV_LinesAccel *debug_lines = 0; String8 debug_checksums = {0}; String8 debug_strings = {0}; for EachIndex(sect_idx, obj->header.section_count_no_null) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; if (section_header->flags & LNK_SECTION_FLAG_DEBUG) { continue; } String8 section_name = coff_name_from_section_header(string_table, section_header); U64 section_number = sect_idx+1; COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section_header); for EachIndex(reloc_idx, relocs.count) { if (supp_info.node_count > config->unresolved_symbol_ref_limit) { str8_list_pushf(scratch.arena, &supp_info, "too many unresolved symbol references reported, stopping now"); goto next_undefined_symbol; } COFF_Reloc *reloc = &relocs.v[reloc_idx]; if (reloc->isymbol == ref->symbol_idx) { U64 line_matches_count = 0; CV_Line *line_matches = 0; if (config->map_lines_for_unresolved_symbols == LNK_SwitchState_Yes) { if (debug_lines == 0) { debug_s = lnk_debug_s_from_obj(scratch.arena, obj); String8List raw_checksums = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); String8List raw_strings = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_StringTable); debug_lines = cv_lines_accel_from_debug_s(scratch.arena, debug_s); debug_checksums = str8_list_first(&raw_checksums); debug_strings = str8_list_first(&raw_strings); } line_matches_count = 0; line_matches = cv_line_from_voff(debug_lines, reloc->apply_off, &line_matches_count); } if (line_matches) { for EachIndex(i, line_matches_count) { CV_Line line = line_matches[i]; CV_C13Checksum checksum = {0}; String8 file_name = {0}; str8_deserial_read_struct(debug_checksums, line.file_off, &checksum); str8_deserial_read_cstr(debug_strings, checksum.name_off, &file_name); str8_list_pushf(scratch.arena, &supp_info, "%S: %S:%u", lnk_loc_from_obj(scratch.arena, obj), file_name, line.line_num); } } else { str8_list_pushf(scratch.arena, &supp_info, "%S: %S(%llx)+%x", lnk_loc_from_obj(scratch.arena, obj), section_name, section_number, reloc->apply_off); } } } } } next_undefined_symbol:; } lnk_error(LNK_Error_UnresolvedSymbol, "unresolved symbol %S", symbol->name); lnk_supplement_error_list(supp_info); } // TODO: /FORCE if (unresolved_symbols_count) { lnk_exit(LNK_Error_UnresolvedSymbol); } ProfEnd(); } // // discard COMDAT sections that are not referenced // if (config->opt_ref == LNK_SwitchState_Yes) { lnk_opt_ref(tp, symtab, config, link->objs); } // // infer minimal padding size for functions from the target machine // if (config->machine != COFF_MachineType_Unknown && config->infer_function_pad_min) { config->function_pad_min = lnk_get_default_function_pad_min(config->machine); config->infer_function_pad_min = 0; } // // log // if (lnk_get_log_status(LNK_Log_InputObj)) { U64 total_input_size = 0; for (LNK_ObjNode *obj_n = link->objs.first; obj_n != 0; obj_n = obj_n->next) { total_input_size += obj_n->data.data.size; } lnk_log(LNK_Log_InputObj, "[Total Obj Input Size %M]", total_input_size); } if (lnk_get_log_status(LNK_Log_InputLib)) { U64 total_input_size = 0; for (LNK_LibNode *lib_n = link->libs.first; lib_n != 0; lib_n = lib_n->next) { total_input_size += lib_n->data.data.size; } lnk_log(LNK_Log_InputLib, "[Total Lib Input Size %M]", total_input_size); } scratch_end(scratch); ProfEnd(); return link; } internal void lnk_reloc_refs_list_push_node(LNK_RelocRefsList *list, LNK_RelocRefsNode *node) { LNK_RelocRefsPointer old_head = list->head; node->next = old_head.node; list->head = (LNK_RelocRefsPointer){ .node = node, .tag = old_head.tag + 1 }; } internal LNK_RelocRefsNode * lnk_reloc_refs_list_pop_node(LNK_RelocRefsList *list) { LNK_RelocRefsPointer old_head = list->head; if (old_head.node) { list->head = (LNK_RelocRefsPointer){ .node = old_head.node->next, .tag = old_head.tag + 1}; } return old_head.node; } internal LNK_RelocRefsNode * lnk_reloc_refs_list_push(Arena *arena, LNK_RelocRefsList *list, LNK_RelocRefs *v) { LNK_RelocRefsNode *node = push_array(arena, LNK_RelocRefsNode, 1); node->v = v; lnk_reloc_refs_list_push_node(list, node); return node; } internal LNK_RelocRefsNode * lnk_reloc_refs_list_pop_node_atomic(LNK_RelocRefsList *list) { LNK_RelocRefsPointer old_head = { .node = ins_atomic_ptr_eval(&list->head.node), .tag = ins_atomic_u64_eval(&list->head.tag) }; for (;;) { if (old_head.node == 0) { break; } LNK_RelocRefsPointer new_head = { .node = old_head.node->next, .tag = old_head.tag + 1 }; if (ins_atomic_u128_eval_cond_assign(&list->head, &new_head, &old_head)) { break; } } return old_head.node; } internal void lnk_reloc_refs_list_push_node_atomic(LNK_RelocRefsList *list, LNK_RelocRefsNode *node) { LNK_RelocRefsPointer old_head = { .node = ins_atomic_ptr_eval(&list->head.node), .tag = ins_atomic_u64_eval(&list->head.tag) }; for (;;) { node->next = old_head.node; LNK_RelocRefsPointer new_head = { .node = node, .tag = old_head.tag + 1 }; if (ins_atomic_u128_eval_cond_assign(&list->head, &new_head, &old_head)) { break; } } } internal void lnk_reloc_refs_list_concat_in_place(LNK_RelocRefsList *list, LNK_RelocRefsNode *first, LNK_RelocRefsNode *last) { LNK_RelocRefsPointer old_head = { .node = ins_atomic_ptr_eval(&list->head.node), .tag = ins_atomic_u64_eval(&list->head.tag) }; for (;;) { last->next = old_head.node; LNK_RelocRefsPointer new_head = { .node = first, .tag = old_head.tag + 1 }; if (ins_atomic_u128_eval_cond_assign(&list->head, &new_head, &old_head)) { break; } } } internal THREAD_POOL_TASK_FUNC(lnk_walk_relocs_and_mark_ref_sections_task) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); LNK_OptRefTask *task = raw_task; LNK_SymbolTable *symtab = task->symtab; LNK_RelocRefsList free_list = {0}; for (;;) { // update active thread count ins_atomic_u32_inc_eval(&task->active_thread_count); for (;;) { // pop head node LNK_RelocRefsNode *node = lnk_reloc_refs_list_pop_node_atomic(task->reloc_refs); if (!node) { break; } LNK_RelocRefs *reloc_refs = node->v; LNK_RelocRefsNode *first_node = 0, *last_node = 0; for EachIndex(reloc_idx, reloc_refs->relocs.count) { COFF_Reloc *reloc = &reloc_refs->relocs.v[reloc_idx]; LNK_ObjSymbolRef reloc_defn = (LNK_ObjSymbolRef){ .obj = reloc_refs->obj, .symbol_idx = reloc->isymbol }; COFF_ParsedSymbol reloc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(reloc_defn.obj, reloc_defn.symbol_idx); COFF_SymbolValueInterpType reloc_interp = coff_interp_from_parsed_symbol(reloc_parsed); LNK_ObjSymbolRef ref_symbol = reloc_defn; for (;;) { COFF_ParsedSymbol ref_parsed = lnk_parsed_symbol_from_coff_symbol_idx(ref_symbol.obj, ref_symbol.symbol_idx); COFF_SymbolValueInterpType ref_interp = coff_interp_from_parsed_symbol(ref_parsed); LNK_ObjSymbolRef next_ref = {0}; if (ref_interp == COFF_SymbolValueInterp_Regular) { LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(ref_symbol.obj, ref_parsed.section_number); if (symlink) { ref_symbol = lnk_ref_from_symbol(symlink); } break; } else if (ref_interp == COFF_SymbolValueInterp_Undefined) { if (reloc_parsed.storage_class == COFF_SymStorageClass_External) { LNK_Symbol *defn = lnk_symbol_table_search(symtab, ref_parsed.name); next_ref = lnk_ref_from_symbol(defn); } else { MemoryZeroStruct(&ref_symbol); break; } } else if (ref_interp == COFF_SymbolValueInterp_Weak) { LNK_Symbol *defn = lnk_symbol_table_search(symtab, ref_parsed.name); next_ref = lnk_ref_from_symbol(defn); } else { break; } if (MemoryMatchStruct(&next_ref, &ref_symbol)) { MemoryZeroStruct(&ref_symbol); break; } ref_symbol = next_ref; } // skip unresolved symbol if (ref_symbol.obj == 0) { continue; } COFF_ParsedSymbol ref_parsed = lnk_parsed_symbol_from_coff_symbol_idx(ref_symbol.obj, ref_symbol.symbol_idx); COFF_SymbolValueInterpType ref_interp = coff_interp_from_parsed_symbol(ref_parsed); LNK_Obj *ref_obj = ref_symbol.obj; if (ref_interp == COFF_SymbolValueInterp_Regular) { // make section number list (reloc section + associates) U32Node *section_number_list = push_array(scratch.arena, U32Node, 1); section_number_list->data = ref_parsed.section_number; section_number_list->next = ref_obj->associated_sections[ref_parsed.section_number]; // push section headers relocations to the task stack for EachNode(section_number_n, U32Node, section_number_list) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(ref_obj, section_number_n->data); // is section eligible for walking? if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_header->flags & COFF_SectionFlag_LnkInfo) { continue; } if (section_header->flags & LNK_SECTION_FLAG_DEBUG) { continue; } if (section_header->flags & LNK_SECTION_FLAG_LIVE) { continue; } // mark section live section_header->flags |= LNK_SECTION_FLAG_LIVE; LNK_RelocRefsNode *node; if (free_list.head.node) { node = lnk_reloc_refs_list_pop_node(&free_list); } else { node = push_array(scratch.arena, LNK_RelocRefsNode, 1); node->v = push_array(scratch.arena, LNK_RelocRefs, 1); } node->v->obj = ref_obj; node->v->relocs = lnk_coff_reloc_info_from_section_number(ref_obj, section_number_n->data); if (first_node == 0) { first_node = node; last_node = node; } else { node->next = first_node; first_node = node; } } } } lnk_reloc_refs_list_push_node(&free_list, node); if (first_node && last_node) { lnk_reloc_refs_list_concat_in_place(task->reloc_refs, first_node, last_node); } } // are all threads done walking? U32 active_thread_count = ins_atomic_u32_dec_eval(&task->active_thread_count); if (active_thread_count == 0 && ins_atomic_ptr_eval(&task->reloc_refs->head.node) == 0) { break; } // comprehensive solution to the waiting problem for (; ins_atomic_ptr_eval(&task->reloc_refs->head.node) == 0; ) { // was signaled to exit? if (ins_atomic_u64_eval(&task->active_thread_count) == 0) { goto exit; } } } exit:; scratch_end(scratch); ProfEnd(); } internal void lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_ObjList objs) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); LNK_RelocRefsList reloc_refs = {0}; // // reset live flag on sections // for EachNode(obj_n, LNK_ObjNode, objs.first) { for EachIndex(sect_idx, obj_n->data.header.section_count_no_null) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(&obj_n->data, sect_idx+1); section_header->flags &= ~LNK_SECTION_FLAG_LIVE; } } // // define roots // { // tls LNK_Symbol *tls_symbol = lnk_symbol_table_searchf(symtab, MSCRT_TLS_SYMBOL_NAME); if (tls_symbol) { lnk_include_symbol(config, str8_lit(MSCRT_TLS_SYMBOL_NAME), 0); } // push tasks for each root symbol for EachNode(root_n, LNK_IncludeSymbolNode, config->include_symbol_list.first) { LNK_Symbol *root = lnk_symbol_table_search(symtab, root_n->v.name); LNK_ObjSymbolRef root_ref = lnk_ref_from_symbol(root); LNK_RelocRefs *r = push_array(scratch.arena, LNK_RelocRefs, 1); r->obj = root_ref.obj; r->relocs.count = 1; r->relocs.v = push_array(scratch.arena, COFF_Reloc, 1); r->relocs.v[0].isymbol = root_ref.symbol_idx; lnk_reloc_refs_list_push(scratch.arena, &reloc_refs, r); } // push task for every non-COMDAT section for EachNode(obj_n, LNK_ObjNode, objs.first) { LNK_Obj *obj = &obj_n->data; for EachIndex(sect_idx, obj->header.section_count_no_null) { U32 section_number = sect_idx+1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); // is section eligible for walking? if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_header->flags & COFF_SectionFlag_LnkCOMDAT) { continue; } if (section_header->flags & COFF_SectionFlag_LnkInfo) { continue; } if (section_header->flags & LNK_SECTION_FLAG_DEBUG) { continue; } // divide relocs and push task for each reloc block COFF_RelocArray relocs = lnk_coff_reloc_info_from_section_number(obj, section_number); U64 new_task_count = CeilIntegerDiv(relocs.count, LNK_RELOCS_PER_TASK); LNK_RelocRefs *new_tasks = push_array(scratch.arena, LNK_RelocRefs, new_task_count); for EachIndex(new_task_idx, new_task_count) { LNK_RelocRefs *r = new_tasks + new_task_idx; r->obj = obj; r->relocs.count = Min(LNK_RELOCS_PER_TASK, relocs.count - (new_task_idx * LNK_RELOCS_PER_TASK)); r->relocs.v = relocs.v + (new_task_idx * LNK_RELOCS_PER_TASK); lnk_reloc_refs_list_push(scratch.arena, &reloc_refs, r); } } } } // // walk relocations and mark referenced sections with live flag // LNK_OptRefTask task = {0}; task.symtab = symtab; task.reloc_refs = &reloc_refs; tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_walk_relocs_and_mark_ref_sections_task, &task, "Mark Live Sections"); ProfBegin("Remove Unreachable Sections"); for EachNode(obj_n, LNK_ObjNode, objs.first) { LNK_Obj *obj = &obj_n->data; for EachIndex(sect_idx, obj->header.section_count_no_null) { U32 section_number = sect_idx+1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); if (section_header->flags & LNK_SECTION_FLAG_DEBUG) { continue; } // remove unreferenced sections if (~section_header->flags & LNK_SECTION_FLAG_LIVE && section_header->flags & COFF_SectionFlag_LnkCOMDAT) { section_header->flags |= COFF_SectionFlag_LnkRemove; } // remove associated sections if (section_header->flags & COFF_SectionFlag_LnkRemove) { for EachNode(section_number_n, U32Node, obj->associated_sections[section_number]) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number_n->data); section_header->flags |= COFF_SectionFlag_LnkRemove; } } // TODO: Reset reserved flag so it does not get propagated to the image sections. // We need to mask out reserved flags when gathering section definitions to actually // prevent propagation. section_header->flags &= ~LNK_SECTION_FLAG_LIVE; } } ProfEnd(); scratch_end(scratch); ProfEnd(); } internal B32 lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_ObjSymbolRef *symbol_out) { B32 is_resolved = 1; COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx(symbol.obj, symbol.symbol_idx); COFF_SymbolValueInterpType symbol_interp = coff_interp_symbol(symbol_parsed.section_number, symbol_parsed.value, symbol_parsed.storage_class); switch (symbol_interp) { case COFF_SymbolValueInterp_Regular: { LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(symbol.obj, symbol_parsed.section_number); *symbol_out = symlink ? lnk_ref_from_symbol(symlink) : symbol; } break; case COFF_SymbolValueInterp_Weak: { LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name); COFF_ParsedSymbol defn_parsed = lnk_parsed_from_symbol(defn); COFF_SymbolValueInterpType defn_interp = lnk_interp_from_symbol(defn); if (defn_interp != COFF_SymbolValueInterp_Undefined) { *symbol_out = lnk_ref_from_symbol(defn); } else { is_resolved = 0; } } break; case COFF_SymbolValueInterp_Undefined: { LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name); if (defn) { *symbol_out = lnk_ref_from_symbol(defn); } else { is_resolved = 0; } } break; case COFF_SymbolValueInterp_Common: { LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name); *symbol_out = lnk_ref_from_symbol(defn); } break; case COFF_SymbolValueInterp_Abs: { if (symbol_parsed.storage_class == COFF_SymStorageClass_External) { LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name); *symbol_out = lnk_ref_from_symbol(defn); } else { *symbol_out = symbol; } } break; case COFF_SymbolValueInterp_Debug: { *symbol_out = symbol; } break; } return is_resolved; } internal THREAD_POOL_TASK_FUNC(lnk_gather_section_definitions_task) { Temp scratch = scratch_begin(&arena, 1); LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; HashTable *sect_defn_ht = task->u.gather_sects.defns[worker_id]; LNK_Obj *obj = task->objs[obj_idx]; COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; String8 string_table = str8_substr(obj->data, obj->header.string_table_range); for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (~sect_header->flags & COFF_SectionFlag_LnkRemove && ~sect_header->flags & COFF_SectionFlag_LnkInfo && sect_header->fsize > 0) { Temp temp = temp_begin(scratch.arena); // was section defined? String8 sect_name = coff_name_from_section_header(string_table, sect_header); String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, sect_header->flags & ~COFF_SectionFlags_LnkFlags); LNK_SectionDefinition *sect_defn = hash_table_search_string_raw(sect_defn_ht, sect_name_with_flags); // push new section definition if (sect_defn == 0) { sect_defn = push_array(arena, LNK_SectionDefinition, 1); sect_defn->name = sect_name; sect_defn->obj = obj; sect_defn->obj_sect_idx = sect_idx; sect_defn->flags = sect_header->flags & ~COFF_SectionFlags_LnkFlags; sect_name_with_flags = push_str8_copy(arena, sect_name_with_flags); hash_table_push_string_raw(arena, sect_defn_ht, sect_name_with_flags, sect_defn); } // acc contrib count sect_defn->contribs_count += 1; temp_end(temp); } } scratch_end(scratch); } internal THREAD_POOL_TASK_FUNC(lnk_gather_section_contribs_task) { Temp scratch = scratch_begin(&arena, 1); LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; String8 string_table = str8_substr(obj->data, obj->header.string_table_range); ProfBeginV("Gather Section Contribs [%S]", obj->path); for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { LNK_SectionContrib *sc = task->null_sc; COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (~sect_header->flags & COFF_SectionFlag_LnkRemove && ~sect_header->flags & COFF_SectionFlag_LnkInfo && sect_header->fsize > 0) { LNK_SectionContribChunk *sc_chunk = 0; { Temp temp = temp_begin(scratch.arena); String8 sect_name = coff_name_from_section_header(string_table, sect_header); String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, sect_header->flags & ~COFF_SectionFlags_LnkFlags); sc_chunk = hash_table_search_string_raw(task->contribs_ht, sect_name_with_flags); temp_end(temp); } if (sc_chunk) { String8 data; if (sect_header->flags & COFF_SectionFlag_CntUninitializedData) { data = str8(0, sect_header->fsize); } else { data = str8_substr(obj->data, rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize)); } U16 sc_align = coff_align_size_from_section_flags(sect_header->flags); sc = lnk_section_contrib_chunk_push_atomic(sc_chunk, 1); sc->first_data_node.next = 0; sc->first_data_node.string = data; sc->last_data_node = &sc->first_data_node; sc->align = sc_align == 0 ? task->default_align : sc_align; sc->u.obj_idx = obj_idx; sc->u.obj_sect_idx = sect_idx; } } task->sect_map[obj_idx][sect_idx] = sc; } ProfEnd(); scratch_end(scratch); } internal THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Set COMDAT Section Contribs [%S]", obj->path); for EachIndex(sect_idx, obj->header.section_count_no_null) { U64 section_number = sect_idx+1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); if (~section_header->flags & COFF_SectionFlag_LnkCOMDAT) { continue; } LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(obj, section_number); if (symlink == 0) { continue; } COFF_ParsedSymbol symlink_parsed = lnk_parsed_from_symbol(symlink); LNK_ObjSymbolRef symlink_ref = lnk_ref_from_symbol(symlink); task->sect_map[obj_idx][sect_idx] = task->sect_map[symlink_ref.obj->input_idx][symlink_parsed.section_number - 1]; } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_flag_debug_symbols_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number); if (section_header->flags & LNK_SECTION_FLAG_DEBUG) { task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1; } } } } internal THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task) { Temp scratch = scratch_begin(&arena, 1); LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("%S", obj->path); ProfBegin("Patch COMDAT Offsets"); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(obj, symbol.section_number); if (symlink) { LNK_ObjSymbolRef symlink_ref = lnk_ref_from_symbol(symlink); if (symlink_ref.obj != obj) { U32 section_number; U32 value; if (symbol.storage_class == COFF_SymStorageClass_External) { // COMDAT leader may be at a different offset, so update this symbol with leader's offset COFF_ParsedSymbol parsed_symlink = lnk_parsed_from_symbol(symlink); section_number = symbol.section_number; value = parsed_symlink.value; } else { // COMDAT section may have static symbols which are now invalid to relocate against section_number = lnk_obj_get_removed_section_number(obj); value = max_U32; task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1; } if (obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = symbol.raw_symbol; symbol32->section_number = section_number; symbol32->value = value; } else { COFF_Symbol16 *symbol16 = symbol.raw_symbol; symbol16->section_number = (U16)section_number; symbol16->value = value; } } } } } ProfEnd(); ProfEnd(); scratch_end(scratch); } internal int lnk_section_contrib_ptr_is_before(void *raw_a, void *raw_b) { LNK_SectionContrib **a = raw_a, **b = raw_b; U64 input_idx_a = Compose64Bit((*a)->u.obj_idx, (*a)->u.obj_sect_idx); U64 input_idx_b = Compose64Bit((*b)->u.obj_idx, (*b)->u.obj_sect_idx); return u64_compar_is_before(&input_idx_a, &input_idx_b); } internal THREAD_POOL_TASK_FUNC(lnk_sort_contribs_task) { LNK_BuildImageTask *task = raw_task; LNK_SectionContribChunk *chunk = task->u.sort_contribs.chunks[task_id]; ProfBeginV("[%llu]", chunk->count); radsort(chunk->v, chunk->count, lnk_section_contrib_ptr_is_before); ProfEnd(); } internal int lnk_common_block_contrib_is_before(void *raw_a, void *raw_b) { LNK_CommonBlockContrib *a = raw_a; LNK_CommonBlockContrib *b = raw_b; int is_before; if (a->u.size == b->u.size) { LNK_Symbol *a_symbol = a->symbol; LNK_Symbol *b_symbol = b->symbol; is_before = lnk_symbol_is_before(a_symbol, b_symbol); } else { is_before = a->u.size > b->u.size; } return is_before; } internal THREAD_POOL_TASK_FUNC(lnk_patch_common_block_leaders_task) { ProfBeginFunction(); LNK_BuildImageTask *task = raw_task; Rng1U64 contrib_range = task->u.patch_symtabs.common_block_ranges[task_id]; for (U64 contrib_idx = contrib_range.min; contrib_idx < contrib_range.max; contrib_idx += 1) { LNK_CommonBlockContrib *contrib = &task->u.patch_symtabs.common_block_contribs[contrib_idx]; LNK_Symbol *symbol = contrib->symbol; LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); COFF_ParsedSymbol parsed_symbol = lnk_parsed_from_symbol(symbol); U64 section_number = task->u.patch_symtabs.common_block_sect->sect_idx + 1; if (symbol_ref.obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = parsed_symbol.raw_symbol; symbol32->value = contrib->u.offset; symbol32->section_number = safe_cast_u32(section_number); } else { COFF_Symbol16 *symbol16 = parsed_symbol.raw_symbol; symbol16->value = contrib->u.offset; symbol16->section_number = safe_cast_u16(section_number); } task->u.patch_symtabs.was_symbol_patched[symbol_ref.obj->input_idx][symbol_ref.symbol_idx] = 1; } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_common_block_symbols_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Patch Common Block Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Common) { LNK_Symbol *defn = lnk_symbol_table_search(task->symtab, symbol.name); COFF_ParsedSymbol defn_parsed = lnk_parsed_from_symbol(defn); Assert(lnk_interp_from_symbol(defn) == COFF_SymbolValueInterp_Regular); if (defn) { if (obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = symbol.raw_symbol; symbol32->section_number = defn_parsed.section_number; symbol32->value = safe_cast_u32(defn_parsed.value); symbol32->storage_class = COFF_SymStorageClass_Static; } else { COFF_Symbol16 *symbol16 = symbol.raw_symbol; symbol16->section_number = safe_cast_u16(defn_parsed.section_number); symbol16->value = safe_cast_u32(defn_parsed.value); symbol16->storage_class = COFF_SymStorageClass_Static; } } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Patch Regular Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); if (task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx]) { continue; } COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number); LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1]; U32 section_number; U32 value; if (sc == task->null_sc) { section_number = lnk_obj_get_removed_section_number(obj); value = max_U32; } else { section_number = safe_cast_u32(sc->u.sect_idx + 1); value = sc->u.off + symbol.value; } if (obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = symbol.raw_symbol; symbol32->section_number = section_number; symbol32->value = value; } else { COFF_Symbol16 *symbol16 = symbol.raw_symbol; symbol16->section_number = safe_cast_u16(section_number); symbol16->value = value; } } } ProfEnd(); } internal void lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Obj *obj, B8 *was_symbol_patched, COFF_SymbolValueInterpType fixup_type) { ProfBeginV("%S\n", obj->path); COFF_ParsedSymbol fixup_dst; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + fixup_dst.aux_symbol_count)) { fixup_dst = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); if (was_symbol_patched[symbol_idx]) { continue; } COFF_SymbolValueInterpType fixup_dst_type = coff_interp_symbol(fixup_dst.section_number, fixup_dst.value, fixup_dst.storage_class); if (fixup_type != fixup_dst_type) { continue; } LNK_ObjSymbolRef symbol_to_resolve = { .obj = obj, .symbol_idx = symbol_idx }; LNK_ObjSymbolRef fixup_symbol = {0}; B32 is_resolved = lnk_resolve_symbol(symtab, symbol_to_resolve, &fixup_symbol); if (is_resolved) { COFF_ParsedSymbol fixup_src = lnk_parsed_symbol_from_coff_symbol_idx(fixup_symbol.obj, fixup_symbol.symbol_idx); COFF_SymbolValueInterpType fixup_type = coff_interp_symbol(fixup_src.section_number, fixup_src.value, fixup_src.storage_class); B32 was_fixup_removed = fixup_src.section_number == lnk_obj_get_removed_section_number(fixup_symbol.obj); U32 section_number; U32 value; if (was_fixup_removed || fixup_type == COFF_SymbolValueInterp_Undefined || fixup_type == COFF_SymbolValueInterp_Weak) { section_number = lnk_obj_get_removed_section_number(obj); value = 0; } else { section_number = fixup_src.section_number; value = fixup_src.value; } if (obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = fixup_dst.raw_symbol; symbol32->section_number = section_number; symbol32->value = value; symbol32->storage_class = COFF_SymStorageClass_Static; } else { COFF_Symbol16 *symbol16 = fixup_dst.raw_symbol; symbol16->section_number = (U16)section_number; symbol16->value = value; symbol16->storage_class = COFF_SymStorageClass_Static; } was_symbol_patched[symbol_idx] = 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_common_symbols_task) { LNK_BuildImageTask *task = raw_task; lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Common); } internal THREAD_POOL_TASK_FUNC(lnk_patch_abs_symbols_task) { LNK_BuildImageTask *task = raw_task; lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Abs); } internal THREAD_POOL_TASK_FUNC(lnk_patch_undefined_symbols_task) { LNK_BuildImageTask *task = raw_task; lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Undefined); } internal THREAD_POOL_TASK_FUNC(lnk_patch_weak_symbols_task) { LNK_BuildImageTask *task = raw_task; lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Weak); } internal THREAD_POOL_TASK_FUNC(lnk_image_fill_task) { ProfBeginFunction(); LNK_BuildImageTask *task = raw_task; String8 image_data = task->u.image_fill.image_data; for EachNode(n, LNK_ImageFillNode, task->u.image_fill.fill_nodes[task_id]) { for EachIndex(i, n->sc_count) { LNK_SectionContrib *sc = n->sc[i]; U64 cursor = 0; for EachNode(data_n, String8Node, &sc->first_data_node) { U64 image_off = sc->u.off + n->base_foff + cursor; Assert(image_off + data_n->string.size <= image_data.size); MemoryCopyStr8(image_data.str + image_off, data_n->string); cursor += data_n->string.size; } } } ProfEnd(); } internal U64 lnk_compute_win32_image_header_size(LNK_Config *config, U64 sect_count) { U64 image_header_size = 0; image_header_size += sizeof(PE_DosHeader) + pe_dos_program.size; image_header_size += sizeof(U32); // PE_MAGIC image_header_size += sizeof(COFF_FileHeader); image_header_size += pe_has_plus_header(config->machine) ? sizeof(PE_OptionalHeader32Plus) : sizeof(PE_OptionalHeader32); image_header_size += sizeof(PE_DataDirectory) * config->data_dir_count; image_header_size += sizeof(COFF_SectionHeader) * sect_count; return image_header_size; } internal THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher) { ProfBeginFunction(); LNK_ObjRelocPatcher *task = raw_task; LNK_Obj *obj = task->objs[task_id]; COFF_FileHeaderInfo obj_header = obj->header; COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); String8 symbol_table = lnk_coff_symbol_table_from_obj(obj); String8 string_table = lnk_coff_string_table_from_obj(obj); U32 closest_sect = 0; U32 closest_reloc = 0; U32 closest_foff = max_U32; for EachIndex(sect_idx, obj_header.section_count_no_null) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; if (section_header->flags & COFF_SectionFlag_LnkInfo) { continue; } if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_header->flags & COFF_SectionFlag_CntUninitializedData) { continue; } // get section bytes (special case debug info because it is not copied to the image) String8 data = section_header->flags & LNK_SECTION_FLAG_DEBUG ? obj->data : task->image_data; Rng1U64 section_frange = rng_1u64(section_header->foff, section_header->foff + section_header->fsize); String8 section_data = str8_substr(data, section_frange); // apply relocs COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section_header); for EachIndex(reloc_idx, relocs.count) { COFF_Reloc *reloc = &relocs.v[reloc_idx]; // error check relocation if (obj->header.machine == COFF_MachineType_X64) { if (reloc->type > COFF_Reloc_X64_Last) { lnk_error_obj(LNK_Error_IllegalRelocation, obj, "unknown relocation type 0x%x", reloc->type); } } else if (obj->header.machine != COFF_MachineType_Unknown) { lnk_not_implemented("relocation patching is not implemented for %S", coff_string_from_machine_type(obj->header.machine)); continue; } // compute virtual offsets U64 reloc_voff = section_header->voff + reloc->apply_off; // compute symbol location values U32 symbol_secnum = 0; U32 symbol_secoff = 0; S64 symbol_voff = 0; { COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, reloc->isymbol); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); if (interp == COFF_SymbolValueInterp_Regular) { if (symbol.section_number == lnk_obj_get_removed_section_number(obj)) { if (~section_header->flags & LNK_SECTION_FLAG_DEBUG) { String8 sect_name = coff_name_from_section_header(string_table, §ion_table[sect_idx]); lnk_error_obj(LNK_Error_RelocationAgainstRemovedSection, obj, "relocating against symbol that is in a removed section (symbol: %S, reloc-section: %S 0x%llx, reloc-index: 0x%llx)", symbol.name, sect_name, sect_idx+1, reloc_idx); } continue; } symbol_secnum = symbol.section_number; symbol_secoff = symbol.value; symbol_voff = safe_cast_u32((U64)task->image_section_table[symbol.section_number]->voff + (U64)symbol_secoff); } else if (interp == COFF_SymbolValueInterp_Abs) { // There aren't enough bits in COFF symbol to store full image base address, // so we special case __ImageBase. A better solution would be to add // a 64-bit symbol format to COFF. if (str8_match(symbol.name, str8_lit("__ImageBase"), 0)) { symbol.value = task->image_base; } symbol_secnum = 0; symbol_secoff = 0; symbol_voff = (S64)symbol.value - (S64)task->image_base; } else if (interp == COFF_SymbolValueInterp_Weak) { // unresolved weak } else if (interp == COFF_SymbolValueInterp_Undefined) { // unresolved undefined } else { InvalidPath; } } // pick reloc value COFF_RelocValue reloc_value = {0}; switch (obj_header.machine) { case COFF_MachineType_Unknown: {} break; case COFF_MachineType_X64: { reloc_value = coff_pick_reloc_value_x64(reloc->type, task->image_base, reloc_voff, symbol_secnum, symbol_secoff, symbol_voff); } break; default: { NotImplemented; } break; } // read addend Assert(reloc_value.size <= section_data.size); U64 raw_addend = 0; str8_deserial_read(section_data, reloc->apply_off, &raw_addend, reloc_value.size, 1); // compute new reloc value S64 addend = extend_sign64(raw_addend, reloc_value.size); U64 reloc_result = reloc_value.value + addend; // commit new reloc value MemoryCopy(section_data.str + reloc->apply_off, &reloc_result, reloc_value.size); } } ProfEnd(); } internal int lnk_section_definition_is_before(void *raw_a, void *raw_b) { LNK_SectionDefinition **a = raw_a, **b = raw_b; U64 input_idx_a = Compose64Bit((*a)->obj->input_idx, (*a)->obj_sect_idx); U64 input_idx_b = Compose64Bit((*b)->obj->input_idx, (*b)->obj_sect_idx); return u64_compar_is_before(&input_idx_a, &input_idx_b); } internal THREAD_POOL_TASK_FUNC(lnk_count_common_block_contribs_task) { LNK_BuildImageTask *task = raw_task; LNK_SymbolTable *symtab = task->symtab; for (LNK_SymbolHashTrieChunk *chunk = symtab->chunks[task_id].first; chunk != 0; chunk = chunk->next) { for EachIndex(i, chunk->count) { LNK_Symbol *symbol = chunk->v[i].symbol; COFF_ParsedSymbol parsed_symbol = lnk_parsed_from_symbol(symbol); COFF_SymbolValueInterpType parsed_interp = coff_interp_symbol(parsed_symbol.section_number, parsed_symbol.value, parsed_symbol.storage_class); if (parsed_interp == COFF_SymbolValueInterp_Common) { task->u.common_block.counts[task_id] += 1; } } } } internal THREAD_POOL_TASK_FUNC(lnk_fill_out_common_block_contribs_task) { LNK_BuildImageTask *task = raw_task; LNK_SymbolTable *symtab = task->symtab; U64 cursor = task->u.common_block.offsets[task_id]; for (LNK_SymbolHashTrieChunk *chunk = symtab->chunks[task_id].first; chunk != 0; chunk = chunk->next) { for EachIndex(i, chunk->count) { LNK_Symbol *symbol = chunk->v[i].symbol; COFF_ParsedSymbol parsed_symbol = lnk_parsed_from_symbol(symbol); COFF_SymbolValueInterpType parsed_interp = coff_interp_symbol(parsed_symbol.section_number, parsed_symbol.value, parsed_symbol.storage_class); if (parsed_interp == COFF_SymbolValueInterp_Common) { LNK_CommonBlockContrib *contrib = &task->u.common_block.contribs[cursor++]; contrib->symbol = chunk->v[i].symbol; contrib->u.size = parsed_symbol.value; } } } } internal THREAD_POOL_TASK_FUNC(lnk_flag_hotpatch_contribs_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; if (obj->hotpatch) { COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number); LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1]; if (sc != task->null_sc) { sc->hotpatch = !!(section_header->flags & COFF_SectionFlag_CntCode); } } } } } internal void lnk_push_coff_symbols_from_data(Arena *arena, LNK_SymbolList *symbol_list, String8 data, LNK_SymbolArray obj_symbols) { if (data.size % sizeof(U32)) { // TODO: report invalid data size } U64 count = data.size / sizeof(U32); for (U32 *ptr = (U32*)data.str, *opl = ptr + count; ptr < opl; ++ptr) { U32 coff_symbol_idx = *ptr; if (coff_symbol_idx >= obj_symbols.count) { // TODO: report invalid symbol index continue; } Assert(coff_symbol_idx < obj_symbols.count); LNK_Symbol *symbol = obj_symbols.v + coff_symbol_idx; lnk_symbol_list_push(arena, symbol_list, symbol); } } internal String8 lnk_build_guard_data(Arena *arena, U64Array voff_arr, U64 stride) { Assert(stride >= sizeof(U32)); // check for duplicates #if DEBUG for (U64 i = 1; i < voff_arr.count; ++i) { Assert(voff_arr.[i-1] != voff_ptr[i]); } #endif U64 buffer_size = stride * voff_arr.count; U8 *buffer = push_array(arena, U8, buffer_size); for (U64 i = 0; i < voff_arr.count; ++i) { U32 *voff_ptr = (U32*)(buffer + i * stride); *voff_ptr = voff_arr.v[i]; } String8 guard_data = str8(buffer, buffer_size); return guard_data; } internal String8List lnk_build_guard_tables(TP_Context *tp, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs, COFF_MachineType machine, String8 entry_point_name, LNK_GuardFlags guard_flags, B32 emit_suppress_flag) { NotImplemented; String8List result = {0}; return result; #if 0 ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); LNK_Section **sect_id_map = lnk_sect_id_map_from_section_table(scratch.arena, sectab); enum { GUARD_FIDS, GUARD_IATS, GUARD_LJMP, GUARD_EHCONT, GUARD_COUNT }; LNK_SymbolList guard_symbol_list_table[GUARD_COUNT]; MemoryZeroStruct(&guard_symbol_list_table[0]); // collect symbols from objs for (LNK_ObjNode *obj_node = obj_list.first; obj_node != NULL; obj_node = obj_node->next) { LNK_Obj *obj = &obj_node->data; MSCRT_FeatFlags feat_flags = lnk_obj_get_features(obj); B32 has_guard_flags = (feat_flags & MSCRT_FeatFlag_GUARD_CF) || (feat_flags & MSCRT_FeatFlag_GUARD_EH_CONT); if (has_guard_flags) { LNK_SymbolArray symbol_arr = lnk_symbol_array_from_list(scratch.arena, obj->symbol_list); if (guard_flags & LNK_Guard_Cf) { String8List gfids_list = lnk_collect_obj_chunks(scratch.arena, obj, str8_lit(".gfids"), str8_zero(), 1); for (String8Node *node = gfids_list.first; node != 0; node = node->next) { lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], node->string, symbol_arr); } String8List giats_list = lnk_collect_obj_chunks(scratch.arena, obj, str8_lit(".giats"), str8_zero(), 1); for (String8Node *node = giats_list.first; node != 0; node = node->next) { lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_IATS], node->string, symbol_arr); } } if (guard_flags & LNK_Guard_LongJmp) { String8List gljmp_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gljmp"), str8_zero(), 1); for (String8Node *node = gljmp_list.first; node != 0; node = node->next) { lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_LJMP], node->string, symbol_arr); } } if (guard_flags & LNK_Guard_EhCont) { String8List gehcont_list = lnk_obj_search_chunks(scratch.arena, obj, str8_lit(".gehcont"), str8_zero(), 1); for (String8Node *node = gehcont_list.first; node != 0; node = node->next) { lnk_push_coff_symbols_from_data(scratch.arena, &guard_symbol_list_table[GUARD_EHCONT], node->string, symbol_arr); } } } else { // TODO: loop over COFF relocs NotImplemented; #if 0 // use relocation data in code sections to get function symbols for (U64 isect = 0; isect < obj->sect_count; ++isect) { LNK_Chunk *chunk = obj->chunk_arr[isect]; if (!chunk) { continue; } if (lnk_chunk_is_discarded(chunk)) { continue; } if (~chunk->flags & COFF_SectionFlag_CntCode) { continue; } Assert(chunk->type == LNK_Chunk_Leaf); for (LNK_Reloc *reloc = obj->sect_reloc_list_arr[isect].first; reloc != 0; reloc = reloc->next) { LNK_Symbol *symbol = lnk_resolve_symbol(symtab, reloc->symbol); if (!LNK_Symbol_IsDefined(symbol->type)) { continue; } LNK_DefinedSymbol *defined_symbol = &symbol->u.defined; if (~defined_symbol->flags & LNK_DefinedSymbolFlag_IsFunc) { continue; } LNK_Chunk *symbol_chunk = defined_symbol->u.chunk; if (!symbol_chunk) { continue; } if (symbol_chunk->type != LNK_Chunk_Leaf) { continue; } if (~symbol_chunk->flags & COFF_SectionFlag_CntCode) { continue; } lnk_symbol_list_push(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], symbol); } } #endif } } // entry point LNK_Symbol *entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, entry_point_name); lnk_symbol_list_push(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], entry_point_symbol); // push exports { Temp temp = temp_begin(scratch.arena); KeyValuePair *raw_exports = key_value_pairs_from_hash_table(temp.arena, exptab->name_export_ht); for (U64 i = 0; i < exptab->name_export_ht->count; ++i) { LNK_Export *exp = raw_exports[i].value_raw; lnk_symbol_list_push(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], exp->symbol); } scratch_end(temp); } // TODO: push noname exports NotImplemented; #if 0 // push thunks LNK_SymbolScope scope_array[] = { LNK_SymbolScope_Defined, LNK_SymbolScope_Internal }; for (U64 iscope = 0; iscope < ArrayCount(scope_array); ++iscope) { LNK_SymbolScope scope = scope_array[iscope]; for (U64 ibucket = 0; ibucket < symtab->bucket_count[scope]; ++ibucket) { for (LNK_SymbolNode *symbol_node = symtab->buckets[scope][ibucket].first; symbol_node != NULL; symbol_node = symbol_node->next) { LNK_Symbol *symbol = symbol_node->data; if (!LNK_Symbol_IsDefined(symbol->type)) continue; LNK_DefinedSymbol *defined_symbol = &symbol->u.defined; if (~defined_symbol->flags & LNK_DefinedSymbolFlag_IsThunk) continue; lnk_symbol_list_push(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], symbol); } } } #endif // build section data lnk_section_table_build_data(tp, sectab, machine); lnk_section_table_assign_virtual_offsets(sectab); // compute symbols virtual offsets U64Array guard_voff_arr_table[GUARD_COUNT]; for (U64 i = 0; i < ArrayCount(guard_symbol_list_table); ++i) { U64List voff_list; MemoryZeroStruct(&voff_list); LNK_SymbolList symbol_list = guard_symbol_list_table[i]; for (LNK_SymbolNode *symbol_node = symbol_list.first; symbol_node != NULL; symbol_node = symbol_node->next) { LNK_Symbol *symbol = lnk_resolve_symbol(symtab, symbol_node->data); if (!LNK_Symbol_IsDefined(symbol->type)) { continue; } LNK_DefinedSymbol *defined_symbol = &symbol->u.defined; LNK_Chunk *chunk = defined_symbol->u.chunk; if (!chunk) { continue; } if (lnk_chunk_is_discarded(chunk)) { continue; } U64 chunk_voff = lnk_virt_off_from_chunk_ref(sect_id_map, chunk->ref); U64 symbol_voff = chunk_voff + defined_symbol->u.chunk_offset; Assert(symbol_voff != 0); u64_list_push(scratch.arena, &voff_list, symbol_voff); } U64Array voff_arr = u64_array_from_list(scratch.arena, &voff_list); radsort(voff_arr.v, voff_arr.count, u64_compar_is_before); guard_voff_arr_table[i] = u64_array_remove_duplicates(scratch.arena, voff_arr); } // push guard sections static struct { char *name; char *symbol; int flags; } sect_layout[] = { { ".gfids", LNK_GFIDS_SYMBOL_NAME, LNK_GFIDS_SECTION_FLAGS }, { ".giats", LNK_GIATS_SYMBOL_NAME, LNK_GIATS_SECTION_FLAGS }, { ".gljmp", LNK_GLJMP_SYMBOL_NAME, LNK_GLJMP_SECTION_FLAGS }, { ".gehcont", LNK_GEHCONT_SYMBOL_NAME, LNK_GEHCONT_SECTION_FLAGS }, }; for (U64 i = 0; i < ArrayCount(sect_layout); ++i) { LNK_Section *sect = lnk_section_table_push(sectab, str8_cstring(sect_layout[i].name), sect_layout[i].flags); } // TODO: emit table for SEH on X86 if (machine == COFF_MachineType_X86) { lnk_not_implemented("__safe_se_handler_table"); lnk_not_implemented("__safe_se_handler_count"); } LNK_Symbol *gfids_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Internal, str8_lit(LNK_GFIDS_SYMBOL_NAME)); LNK_Symbol *giats_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Internal, str8_lit(LNK_GIATS_SYMBOL_NAME)); LNK_Symbol *gljmp_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Internal, str8_lit(LNK_GLJMP_SYMBOL_NAME)); LNK_Symbol *gehcont_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Internal, str8_lit(LNK_GEHCONT_SYMBOL_NAME)); LNK_Section *gfids_sect = lnk_section_table_search_id(sectab, gfids_symbol->u.defined.u.chunk->ref.sect_id); LNK_Section *giats_sect = lnk_section_table_search_id(sectab, giats_symbol->u.defined.u.chunk->ref.sect_id); LNK_Section *gljmp_sect = lnk_section_table_search_id(sectab, gljmp_symbol->u.defined.u.chunk->ref.sect_id); LNK_Section *gehcont_sect = lnk_section_table_search_id(sectab, gehcont_symbol->u.defined.u.chunk->ref.sect_id); LNK_Chunk *gfids_array_chunk = gfids_sect->root; LNK_Chunk *giats_array_chunk = giats_sect->root; LNK_Chunk *gljmp_array_chunk = gljmp_sect->root; LNK_Chunk *gehcont_array_chunk = gehcont_sect->root; // first 4 bytes are call's destination virtual offset U64 entry_stride = sizeof(U32); if (emit_suppress_flag) { // 4th byte tells kernel what to do when destination VA is not in the bitmap. // If byte is 1 exception is suppressed and program keeps running. // If zero then exception is raised with nt!_KiRaiseSecurityCheckFailure(FAST_FAIL_GUARD_ICALL_CHECK_FAILURE) and exception code 0xA. entry_stride = 5; } // make guard data from virtual offsets String8 gfids_data = lnk_build_guard_data(gfids_sect->arena, guard_voff_arr_table[GUARD_FIDS], entry_stride); String8 giats_data = lnk_build_guard_data(giats_sect->arena, guard_voff_arr_table[GUARD_IATS], entry_stride); String8 gljmp_data = lnk_build_guard_data(gljmp_sect->arena, guard_voff_arr_table[GUARD_LJMP], entry_stride); String8 gehcont_data = lnk_build_guard_data(gehcont_sect->arena, guard_voff_arr_table[GUARD_EHCONT], entry_stride); // push guard data lnk_section_push_chunk_data(gfids_sect, gfids_array_chunk, gfids_data, str8_zero()); lnk_section_push_chunk_data(giats_sect, giats_array_chunk, giats_data, str8_zero()); lnk_section_push_chunk_data(gljmp_sect, gljmp_array_chunk, gljmp_data, str8_zero()); lnk_section_push_chunk_data(gehcont_sect, gehcont_array_chunk, gehcont_data, str8_zero()); LNK_Symbol *gflags_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_FLAGS_SYMBOL_NAME)); LNK_Symbol *gfids_table_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_FIDS_TABLE_SYMBOL_NAME)); LNK_Symbol *gfids_count_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_FIDS_COUNT_SYMBOL_NAME)); LNK_Symbol *giats_table_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_IAT_TABLE_SYMBOL_NAME)); LNK_Symbol *giats_count_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_IAT_COUNT_SYMBOL_NAME)); LNK_Symbol *gljmp_table_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_LONGJMP_TABLE_SYMBOL_NAME)); LNK_Symbol *gljmp_count_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_LONGJMP_COUNT_SYMBOL_NAME)); LNK_Symbol *gehcont_table_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_EHCONT_TABLE_SYMBOL_NAME)); LNK_Symbol *gehcont_count_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Main, str8_lit(MSCRT_GUARD_EHCONT_COUNT_SYMBOL_NAME)); LNK_DefinedSymbol *gflags_def = &gflags_symbol->u.defined; LNK_DefinedSymbol *gfids_table_def = &gfids_table_symbol->u.defined; LNK_DefinedSymbol *gfids_count_def = &gfids_count_symbol->u.defined; LNK_DefinedSymbol *giats_table_def = &giats_table_symbol->u.defined; LNK_DefinedSymbol *giats_count_def = &giats_count_symbol->u.defined; LNK_DefinedSymbol *gljmp_table_def = &gljmp_table_symbol->u.defined; LNK_DefinedSymbol *gljmp_count_def = &gljmp_count_symbol->u.defined; LNK_DefinedSymbol *gehcont_table_def = &gehcont_table_symbol->u.defined; LNK_DefinedSymbol *gehcont_count_def = &gehcont_count_symbol->u.defined; // guard flags gflags_def->value_type = LNK_DefinedSymbolValue_VA; gflags_def->u.va = PE_LoadConfigGuardFlags_CF_INSTRUMENTED; if ((guard_flags & LNK_Guard_Cf)) { gflags_def->u.va |= PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_PRESENT; } if ((guard_flags & LNK_Guard_LongJmp) && guard_voff_arr_table[GUARD_LJMP].count) { gflags_def->u.va |= PE_LoadConfigGuardFlags_CF_LONGJUMP_TABLE_PRESENT; } if ((guard_flags & LNK_Guard_EhCont) && guard_voff_arr_table[GUARD_EHCONT].count) { gflags_def->u.va |= PE_LoadConfigGuardFlags_EH_CONTINUATION_TABLE_PRESENT; } { LNK_Section *didat_sect = lnk_section_table_search(sectab, str8_lit(".didat")); if (didat_sect) { gflags_def->u.va |= PE_LoadConfigGuardFlags_DELAYLOAD_IAT_IN_ITS_OWN_SECTION; } } if (entry_stride > sizeof(U32)) { U64 size_bit = (entry_stride - 5); if (emit_suppress_flag) { gflags_def->u.va |= PE_LoadConfigGuardFlags_CF_EXPORT_SUPPRESSION_INFO_PRESENT; } gflags_def->u.va |= (1 << size_bit) << PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_SHIFT; } // gfids if (guard_voff_arr_table[GUARD_FIDS].count) { gfids_table_def->value_type = LNK_DefinedSymbolValue_Chunk; gfids_table_def->u.chunk = gfids_array_chunk; } gfids_count_def->value_type = LNK_DefinedSymbolValue_VA; gfids_count_def->u.va = guard_voff_arr_table[GUARD_FIDS].count; // giats if (guard_voff_arr_table[GUARD_IATS].count) { giats_table_def->value_type = LNK_DefinedSymbolValue_Chunk; giats_table_def->u.chunk = giats_array_chunk; } giats_count_def->value_type = LNK_DefinedSymbolValue_VA; giats_count_def->u.va = guard_voff_arr_table[GUARD_IATS].count; // gljmp if (guard_voff_arr_table[GUARD_LJMP].count) { gljmp_table_def->value_type = LNK_DefinedSymbolValue_Chunk; gljmp_table_def->u.chunk = gljmp_array_chunk; } gljmp_count_def->value_type = LNK_DefinedSymbolValue_VA; gljmp_count_def->u.va = guard_voff_arr_table[GUARD_LJMP].count; // gehcont if (guard_voff_arr_table[GUARD_EHCONT].count) { gehcont_table_def->value_type = LNK_DefinedSymbolValue_Chunk; gehcont_table_def->u.chunk = gehcont_array_chunk; } gehcont_count_def->value_type = LNK_DefinedSymbolValue_VA; gehcont_count_def->u.va = guard_voff_arr_table[GUARD_EHCONT].count; scratch_end(scratch); ProfEnd(); #endif } internal THREAD_POOL_TASK_FUNC(lnk_patch_virtual_offsets_and_sizes_in_obj_section_headers_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Patch Virtual Offset And Size In Section Headers [%S]", obj->path); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (~sect_header->flags & COFF_SectionFlag_LnkRemove) { LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx]; LNK_Section *sect = task->image_sects.v[sc->u.sect_idx]; sect_header->vsize = lnk_size_from_section_contrib(sc); sect_header->voff = sect->voff + sc->u.off; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_file_offsets_and_sizes_in_obj_section_headers_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Patch File Offsets And Sizes In Obj Section Headers [%S]", obj->path); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; B32 patch_section_header = (~sect_header->flags & COFF_SectionFlag_LnkRemove) && (~sect_header->flags & LNK_SECTION_FLAG_DEBUG); if (patch_section_header) { LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx]; LNK_Section *sect = task->image_sects.v[sc->u.sect_idx]; if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { sect_header->fsize = lnk_size_from_section_contrib(sc); sect_header->foff = sect->foff + sc->u.off; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_section_symbols_task) { LNK_BuildImageTask *task = raw_task; U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; ProfBegin("Patch Section Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Undefined) { if (symbol.storage_class == COFF_SymStorageClass_Section) { LNK_Section *sect = lnk_section_table_search(task->sectab, symbol.name, symbol.value); if (sect) { if (~sect->flags & COFF_SectionFlag_MemDiscardable) { LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); if (obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = symbol.raw_symbol; symbol32->section_number = safe_cast_u32(first_sc->u.sect_idx + 1); symbol32->value = first_sc->u.off; symbol32->storage_class = COFF_SymStorageClass_Static; } else { COFF_Symbol16 *symbol16 = symbol.raw_symbol; symbol16->section_number = safe_cast_u16(first_sc->u.sect_idx + 1); symbol16->value = first_sc->u.off; symbol16->storage_class = COFF_SymStorageClass_Static; } } else { lnk_error_obj(LNK_Error_SectRefsDiscardedMemory, obj, "symbol %S (No. 0x%llx) references section with discard flag", symbol.name, symbol_idx); } } else { lnk_error_obj(LNK_Error_UnresolvedSymbol, obj, "undefined section symbol %S (No 0x%llx) refers to an image section that doesn't exist", symbol.name, symbol_idx); } } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_gather_base_reloc_pages_task) { LNK_BaseRelocsTask *task = raw_task; HashTable *page_ht = task->gather.page_ht[worker_id]; LNK_BaseRelocPageList *pages = &task->gather.pages[worker_id]; LNK_Obj *obj = task->gather.objs[task_id]; COFF_SectionHeader *sect_table = lnk_coff_section_table_from_obj(obj); ProfBeginV("%S", obj->path); for EachIndex(sect_idx, obj->header.section_count_no_null) { COFF_SectionHeader *sect_header = §_table[sect_idx]; if (sect_header->flags & COFF_SectionFlag_LnkRemove) { continue; } COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, sect_header); for EachIndex(reloc_idx, relocs.count) { COFF_Reloc *r = &relocs.v[reloc_idx]; COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, r->isymbol); COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol); if (symbol_interp == COFF_SymbolValueInterp_Abs) { continue; } U64 is_addr = coff_is_addr_reloc(obj->header.machine, r->type); if (is_addr == 0) { continue; } U64 reloc_voff = sect_header->voff + r->apply_off; U64 page_voff = AlignDownPow2(reloc_voff, task->page_size); LNK_BaseRelocPageNode *page = hash_table_search_u64_raw(page_ht, page_voff); if (page == 0) { // fill out page page = push_array(arena, LNK_BaseRelocPageNode, 1); page->v.voff = page_voff; page->v.entries_addr32 = push_array(arena, U64List, 1); page->v.entries_addr64 = push_array(arena, U64List, 1); // push page SLLQueuePush(pages->first, pages->last, page); pages->count += 1; // register page voff hash_table_push_u64_raw(arena, page_ht, page_voff, page); } switch (is_addr) { case 4: { if (task->is_large_addr_aware) { lnk_error_obj(LNK_Error_LargeAddrAwareRequired, obj, "found out of range ADDR32 relocation for '%S', link with /LARGEADDRESSAWARE:NO", symbol.name); } else { u64_list_push(arena, page->v.entries_addr32, reloc_voff); } } break; case 8: { u64_list_push(arena, page->v.entries_addr64, reloc_voff); } break; default: { InvalidPath; } break; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_serialize_base_reloc_pages_task) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); LNK_BaseRelocsTask *task = raw_task; HashTable *voff_ht = hash_table_init(scratch.arena, task->page_size); U64 voffs_max = task->page_size; U32 *voffs32 = push_array(scratch.arena, U32, voffs_max); U64 *voffs64 = push_array(scratch.arena, U64, voffs_max); for EachInRange(page_idx, task->serialize.ranges[task_id]) { LNK_BaseRelocPage *page = &task->serialize.pages.v[page_idx]; // filter out duplicate 32-bit virtual offsets U64 voff_count32 = 0; for EachNode(voff_n, U64Node, page->entries_addr32->first) { if (hash_table_search_u64(voff_ht, voff_n->data)) { continue; } hash_table_push_u64_u64(scratch.arena, voff_ht, voff_n->data, 0); voffs32[voff_count32] = voff_n->data; voff_count32 += 1; } // filter out duplicate 64-bit virtual offsets U64 voff_count64 = 0; for EachNode(voff_n, U64Node, page->entries_addr64->first) { if (hash_table_search_u64(voff_ht, voff_n->data)) { continue; } hash_table_push_u64_u64(scratch.arena, voff_ht, voff_n->data, 0); voffs64[voff_count64] = voff_n->data; voff_count64 += 1; } // gather step is not deterministic radsort(voffs32, voff_count32, u32_is_before); radsort(voffs64, voff_count64, u64_is_before); // find block bytes in the buffer void *block = task->serialize.buffer + page->buffer_offset; // setup pointers into the block U32 *page_voff_ptr = block; U32 *block_size_ptr = page_voff_ptr + 1; U16 *reloc_arr_base = (U16 *)(block_size_ptr + 1); U16 *reloc_arr_ptr = reloc_arr_base; // write 32-bit relocation entries for EachIndex(i, voff_count32) { U64 rel_off = voffs32[i] - page->voff; *reloc_arr_ptr = PE_BaseRelocMake(PE_BaseRelocKind_HIGHLOW, rel_off); reloc_arr_ptr += 1; } // write 64-bit relocation entries for EachIndex(i, voff_count64) { U64 rel_off = voffs64[i] - page->voff; *reloc_arr_ptr = PE_BaseRelocMake(PE_BaseRelocKind_DIR64, rel_off); reloc_arr_ptr += 1; } // compute block size U64 reloc_arr_size = IntFromPtr(reloc_arr_ptr - reloc_arr_base) * sizeof(reloc_arr_ptr[0]); U64 block_size = sizeof(*page_voff_ptr) + sizeof(*block_size_ptr) + reloc_arr_size; U64 block_size_aligned = AlignPow2(block_size, sizeof(U32)); // zero-out alignment U64 align_size = block_size_aligned - block_size; MemoryZero(reloc_arr_ptr, align_size); // write page header *page_voff_ptr = safe_cast_u32(page->voff); *block_size_ptr = safe_cast_u32(block_size_aligned); // purge hash table for the next run hash_table_purge(voff_ht); } scratch_end(scratch); ProfEnd(); } internal int lnk_base_reloc_page_is_before(void *raw_a, void *raw_b) { return ((LNK_BaseRelocPage *)raw_a)->voff < ((LNK_BaseRelocPage *)raw_b)->voff; } internal String8 lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, U64 objs_count, LNK_Obj **objs) { ProfBeginFunction(); Arena *arena = tp_arena->v[0]; Temp scratch = scratch_begin(tp_arena->v, tp_arena->count); tp_arena->v[0] = scratch.arena; TP_Temp tp_temp = tp_temp_begin(tp_arena); LNK_BaseRelocsTask task = {0}; task.page_size = config->machine_page_size; task.is_large_addr_aware = !!(config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE); LNK_BaseRelocPageArray pages = {0}; { LNK_BaseRelocPageList *page_lists = push_array(scratch.arena, LNK_BaseRelocPageList, tp->worker_count); HashTable **page_ht = push_array(scratch.arena, HashTable *, tp->worker_count); for EachIndex(i, tp->worker_count) { page_ht[i] = hash_table_init(scratch.arena, task.page_size/2); } task.gather.objs = objs; task.gather.pages = page_lists; task.gather.page_ht = page_ht; tp_for_parallel_prof(tp, tp_arena, objs_count, lnk_gather_base_reloc_pages_task, &task, "Gather"); ProfBegin("Merge Page Lists"); LNK_BaseRelocPageList *main_page_list = &page_lists[0]; HashTable *main_ht = page_ht[0]; for (U64 list_idx = 1; list_idx < tp->worker_count; list_idx += 1) { for (LNK_BaseRelocPageNode *src_page = page_lists[list_idx].first, *src_next; src_page != 0; src_page = src_next) { src_next = src_page->next; LNK_BaseRelocPageNode *page = hash_table_search_u64_raw(main_ht, src_page->v.voff); if (page) { // page exists, concat voffs Assert(page != src_page); u64_list_concat_in_place(page->v.entries_addr32, src_page->v.entries_addr32); u64_list_concat_in_place(page->v.entries_addr64, src_page->v.entries_addr64); } else { // push page to the main list SLLQueuePush(main_page_list->first, main_page_list->last, src_page); main_page_list->count += 1; // store lookup voff hash_table_push_u64_raw(scratch.arena, main_ht, src_page->v.voff, src_page); } } } ProfEnd(); ProfBegin("Page List -> Array"); pages.v = push_array_no_zero(scratch.arena, LNK_BaseRelocPage, main_page_list->count); for EachNode(n, LNK_BaseRelocPageNode, main_page_list->first) { pages.v[pages.count++] = n->v; } ProfEnd(); } ProfBeginV("Sort Pages [Count %llu]", pages.count); radsort(pages.v, pages.count, lnk_base_reloc_page_is_before); ProfEnd(); String8 base_relocs = {0}; { ProfBegin("Compute Buffer Size"); U64 buffer_size = 0; for EachIndex(page_idx, pages.count) { LNK_BaseRelocPage *page = &pages.v[page_idx]; page->buffer_offset = buffer_size; buffer_size += /* page base voff */ sizeof(U32) + /* size of block */ sizeof(U32); // header buffer_size += sizeof(U16)*page->entries_addr32->count; // 32-bit voff entries buffer_size += sizeof(U16)*page->entries_addr64->count; // 64-bit voff entries buffer_size = AlignPow2(buffer_size, sizeof(U32)); } ProfEnd(); ProfBeginV("Alloc Buffer [%M]", buffer_size); U8 *buffer = push_array_no_zero(arena, U8, buffer_size); ProfEnd(); task.serialize.buffer_size = buffer_size; task.serialize.buffer = buffer; task.serialize.pages = pages; task.serialize.ranges = tp_divide_work(scratch.arena, pages.count, tp->worker_count); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_serialize_base_reloc_pages_task, &task, "Serialize"); base_relocs = str8(task.serialize.buffer, task.serialize.buffer_size); } tp_temp_end(tp_temp); // scratch is cleared here tp_arena->v[0] = arena; ProfEnd(); return base_relocs; } internal String8List lnk_build_win32_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sects, U64 expected_image_header_size) { ProfBeginFunction(); String8List result = {0}; // // DOS header // U32 dos_stub_size = sizeof(PE_DosHeader) + pe_dos_program.size; { PE_DosHeader *dos_header = push_array(arena, PE_DosHeader, 1); dos_header->magic = PE_DOS_MAGIC; dos_header->last_page_size = dos_stub_size % 512; dos_header->page_count = CeilIntegerDiv(dos_stub_size, 512); dos_header->paragraph_header_size = sizeof(PE_DosHeader) / 16; dos_header->min_paragraph = 0; dos_header->max_paragraph = 0; dos_header->init_ss = 0; dos_header->init_sp = 0; dos_header->checksum = 0; dos_header->init_ip = 0xFFFF; dos_header->init_cs = 0; dos_header->reloc_table_file_off = sizeof(PE_DosHeader); dos_header->overlay_number = 0; MemoryZeroStruct(dos_header->reserved); dos_header->oem_id = 0; dos_header->oem_info = 0; MemoryZeroArray(dos_header->reserved2); dos_header->coff_file_offset = dos_stub_size; str8_list_push(arena, &result, str8_struct(dos_header)); str8_list_push(arena, &result, pe_dos_program); } // // PE magic // U32 *pe_magic = push_array(arena, U32, 1); *pe_magic = PE_MAGIC; str8_list_push(arena, &result, str8_struct(pe_magic)); // // determine PE optional header type // B32 has_pe_plus_header = pe_has_plus_header(config->machine); // // COFF file header // { COFF_FileHeader *file_header = push_array_no_zero(arena, COFF_FileHeader, 1); file_header->machine = config->machine; file_header->time_stamp = config->time_stamp; file_header->symbol_table_foff = 0; file_header->symbol_count = 0; file_header->section_count = sects.count; file_header->optional_header_size = (has_pe_plus_header ? sizeof(PE_OptionalHeader32Plus) : sizeof(PE_OptionalHeader32)) + (sizeof(PE_DataDirectory) * config->data_dir_count); file_header->flags = config->file_characteristics; str8_list_push(arena, &result, str8_struct(file_header)); } // // compute code/inited/uninited sizes // U64 code_base = 0; U64 sizeof_code = 0; U64 sizeof_inited_data = 0; U64 sizeof_uninited_data = 0; U64 sizeof_image = 0; for (U64 sect_idx = 0; sect_idx < sects.count; sect_idx += 1) { LNK_Section *sect = sects.v[sect_idx]; if (code_base == 0 && sect->flags & COFF_SectionFlag_CntCode) { code_base = sect->voff; } if (sect->flags & COFF_SectionFlag_CntUninitializedData) { sizeof_uninited_data += sect->vsize; } if ((sect->flags & COFF_SectionFlag_CntInitializedData) || (sect->flags & COFF_SectionFlag_CntCode)) { sizeof_inited_data += sect->fsize; } if (sect->flags & COFF_SectionFlag_CntCode) { sizeof_code += sect->fsize; } sizeof_image = Max(sizeof_image, sects.v[sect_idx]->voff + sects.v[sect_idx]->vsize); } sizeof_code = AlignPow2(sizeof_code, config->file_align); sizeof_inited_data = AlignPow2(sizeof_inited_data, config->file_align); sizeof_uninited_data = AlignPow2(sizeof_uninited_data, config->file_align); sizeof_image = AlignPow2(sizeof_image, 4096); // // compute image headers size // U64 sizeof_image_headers = 0; sizeof_image_headers += dos_stub_size; sizeof_image_headers += sizeof(COFF_FileHeader); sizeof_image_headers += has_pe_plus_header ? sizeof(PE_OptionalHeader32Plus) : sizeof(PE_OptionalHeader32); sizeof_image_headers += sizeof(PE_DataDirectory) * config->data_dir_count; sizeof_image_headers += sizeof(COFF_SectionHeader) * sects.count; sizeof_image_headers = AlignPow2(sizeof_image_headers, config->file_align); // // fill out PE optional header // U32 *entry_point_va; U32 *check_sum; if (has_pe_plus_header) { PE_OptionalHeader32Plus *opt_header = push_array_no_zero(arena, PE_OptionalHeader32Plus, 1); opt_header->magic = PE_PE32PLUS_MAGIC; opt_header->major_linker_version = config->link_ver.major; opt_header->minor_linker_version = config->link_ver.minor; opt_header->sizeof_code = safe_cast_u32(sizeof_code); opt_header->sizeof_inited_data = safe_cast_u32(sizeof_inited_data); opt_header->sizeof_uninited_data = safe_cast_u32(sizeof_uninited_data); opt_header->entry_point_va = 0; opt_header->code_base = code_base; opt_header->image_base = lnk_get_base_addr(config); opt_header->section_alignment = config->sect_align; opt_header->file_alignment = config->file_align; opt_header->major_os_ver = config->os_ver.major; opt_header->minor_os_ver = config->os_ver.minor; opt_header->major_img_ver = config->image_ver.major; opt_header->minor_img_ver = config->image_ver.minor; opt_header->major_subsystem_ver = config->subsystem_ver.major; opt_header->minor_subsystem_ver = config->subsystem_ver.minor; opt_header->win32_version_value = 0; // MSVC writes zero opt_header->sizeof_image = sizeof_image; opt_header->sizeof_headers = safe_cast_u32(sizeof_image_headers); opt_header->check_sum = 0; // :check_sum opt_header->subsystem = config->subsystem; opt_header->dll_characteristics = config->dll_characteristics; opt_header->sizeof_stack_reserve = config->stack_reserve; opt_header->sizeof_stack_commit = config->stack_commit; opt_header->sizeof_heap_reserve = config->heap_reserve; opt_header->sizeof_heap_commit = config->heap_commit; opt_header->loader_flags = 0; // for dynamic linker, always zero opt_header->data_dir_count = safe_cast_u32(config->data_dir_count); entry_point_va = &opt_header->entry_point_va; check_sum = &opt_header->check_sum; str8_list_push(arena, &result, str8_struct(opt_header)); } else { NotImplemented; } // // PE directories // PE_DataDirectory *directory_array; { directory_array = push_array(arena, PE_DataDirectory, config->data_dir_count); str8_list_push(arena, &result, str8_array(directory_array, config->data_dir_count)); } // // COFF section table // COFF_SectionHeader *coff_section_table = push_array(arena, COFF_SectionHeader, sects.count); U64 coff_section_table_count = 0; { for (U64 sect_idx = 0; sect_idx < sects.count; sect_idx += 1) { LNK_Section *sect = sects.v[sect_idx]; COFF_SectionHeader *coff_section = &coff_section_table[sect_idx]; if (coff_section->flags & COFF_SectionFlag_LnkRemove) { continue; } // TODO: for objs we can store long name in string table and write here /offset if (sect->name.size > sizeof(coff_section->name)) { lnk_error(LNK_Warning_LongSectionName, "not enough space in COFF section header to store entire name \"%S\"", sect->name); } MemorySet(&coff_section->name[0], 0, sizeof(coff_section->name)); MemoryCopy(&coff_section->name[0], sect->name.str, Min(sect->name.size, sizeof(coff_section->name))); coff_section->vsize = sect->vsize; coff_section->voff = sect->voff; coff_section->fsize = sect->fsize; coff_section->foff = sect->foff; coff_section->relocs_foff = 0; // not present in image coff_section->lines_foff = 0; // obsolete coff_section->reloc_count = 0; // not present in image coff_section->line_count = 0; // obsolete coff_section->flags = sect->flags; coff_section_table_count += 1; } str8_list_push(arena, &result, str8_array(coff_section_table, coff_section_table_count)); } // align image headers { U64 image_headers_align_size = AlignPadPow2(result.total_size, config->file_align); U8 *image_headers_align = push_array(arena, U8, image_headers_align_size); str8_list_push(arena, &result, str8(image_headers_align, image_headers_align_size)); } // // entry point // { Temp scratch = scratch_begin(&arena, 1); COFF_SectionHeader **section_table = push_array(arena, COFF_SectionHeader *, coff_section_table_count + 1); for (U64 i = 1; i <= coff_section_table_count; i += 1) { section_table[i] = &coff_section_table[i-1]; } LNK_Symbol *entry_symbol = lnk_symbol_table_search(symtab, config->entry_point_name); if (entry_symbol) { *entry_point_va = safe_cast_u32(lnk_voff_from_symbol(section_table, entry_symbol)); } scratch_end(scratch); } Assert(result.total_size == expected_image_header_size); ProfEnd(); return result; } internal LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs) { ProfBegin("Image"); lnk_timer_begin(LNK_Timer_Image); Temp scratch = scratch_begin(arena->v, arena->count); // // init section table // LNK_SectionTable *sectab = lnk_section_table_alloc(); lnk_section_table_push(sectab, str8_lit(".text" ), PE_TEXT_SECTION_FLAGS ); lnk_section_table_push(sectab, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS); lnk_section_table_push(sectab, str8_lit(".data" ), PE_DATA_SECTION_FLAGS ); lnk_section_table_push(sectab, str8_lit(".bss" ), PE_BSS_SECTION_FLAGS ); lnk_section_table_push(sectab, str8_lit(".pdata"), PE_PDATA_SECTION_FLAGS); LNK_Section *common_block_sect = lnk_section_table_search(sectab, str8_lit(".bss"), PE_BSS_SECTION_FLAGS); LNK_BuildImageTask task = { .symtab = symtab, .sectab = sectab, .objs_count = objs_count, .objs = objs, .function_pad_min = config->function_pad_min, .default_align = coff_default_align_from_machine(config->machine), .null_sc = push_array(arena->v[0], LNK_SectionContrib, 1), }; { ProfBegin("Define And Count Sections"); TP_Temp temp = tp_temp_begin(arena); ProfBegin("Init Hash Tables For Gathering Section Definitions"); task.u.gather_sects.defns = push_array(arena->v[0], HashTable *, tp->worker_count); for EachIndex(worker_id, tp->worker_count) { task.u.gather_sects.defns[worker_id] = hash_table_init(arena->v[0], 128); } ProfEnd(); tp_for_parallel_prof(tp, arena, objs_count, lnk_gather_section_definitions_task, &task, "Gather Section Definitions"); ProfBegin("Merge Section Definitions Hash Tables"); for (U64 worker_idx = 1; worker_idx < tp->worker_count; worker_idx += 1) { U64 sect_defns_count = task.u.gather_sects.defns[worker_idx]->count; LNK_SectionDefinition **sect_defns = values_from_hash_table_raw(arena->v[0], task.u.gather_sects.defns[worker_idx]); radsort(sect_defns, sect_defns_count, lnk_section_definition_is_before); for EachIndex(defn_idx, sect_defns_count) { LNK_SectionDefinition *defn = sect_defns[defn_idx]; String8 name_with_flags = lnk_make_name_with_flags(arena->v[0], defn->name, defn->flags); LNK_SectionDefinition *main_defn = hash_table_search_string_raw(task.u.gather_sects.defns[0], name_with_flags); if (main_defn == 0) { main_defn = sect_defns[defn_idx]; hash_table_push_string_raw(arena->v[0], task.u.gather_sects.defns[0], name_with_flags, main_defn); } else { if (lnk_section_definition_is_before(§_defns[defn_idx], &main_defn)) { main_defn->obj = sect_defns[defn_idx]->obj; main_defn->obj_sect_idx = sect_defns[defn_idx]->obj_sect_idx; } main_defn->contribs_count += sect_defns[defn_idx]->contribs_count; } } } U64 sect_defns_count = task.u.gather_sects.defns[0]->count; LNK_SectionDefinition **sect_defns = values_from_hash_table_raw(arena->v[0], task.u.gather_sects.defns[0]); ProfEnd(); ProfBegin("Sort Sections Definitions"); radsort(sect_defns, sect_defns_count, lnk_section_definition_is_before); ProfEnd(); ProfBegin("Push Sections And Reserve Section Contrib Memory"); task.contribs_ht = hash_table_init(sectab->arena, sect_defns_count); for EachIndex(defn_idx, sect_defns_count) { LNK_SectionDefinition *sect_defn = sect_defns[defn_idx]; // parse section name String8 sect_name, sort_idx; coff_parse_section_name(sect_defn->name, §_name, &sort_idx); // do not create definitions for sections that are removed from the image if (lnk_is_section_removed(config, sect_name)) { continue; } // warn about conflicting section flags for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { if (str8_match(sect_n->data.name, sect_name, 0) && sect_n->data.flags != sect_defn->flags) { LNK_Obj *obj = sect_defn->obj; U32 sect_number = sect_defn->obj_sect_idx + 1; COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, sect_number); String8 sect_name = coff_name_from_section_header(str8_substr(obj->data, obj->header.string_table_range), sect_header); String8 expected_flags_str = coff_string_from_section_flags(arena->v[0], sect_n->data.flags); String8 current_flags_str = coff_string_from_section_flags(arena->v[0], sect_defn->flags); lnk_error_obj(LNK_Warning_SectionFlagsConflict, sect_defn->obj, "detected section flags conflict in %S(No. %X); expected {%S} but got {%S}", sect_name, sect_number, expected_flags_str, current_flags_str); } } { ProfBeginV("Reserve Section Contrib Chunks [%S]", sect_defn->name); LNK_Section *sect = lnk_section_table_search(sectab, sect_name, sect_defn->flags); if (!sect) { sect = lnk_section_table_push(sectab, sect_name, sect_defn->flags); } String8 defn_name_with_flags = lnk_make_name_with_flags(sectab->arena, sect_defn->name, sect_defn->flags); LNK_SectionContribChunk *contrib_chunk = hash_table_search_string_raw(task.contribs_ht, defn_name_with_flags); if (!contrib_chunk) { contrib_chunk = lnk_section_contrib_chunk_list_push_chunk(arena->v[0], §->contribs, sect_defn->contribs_count, sort_idx); hash_table_push_string_raw(sectab->arena, task.contribs_ht, defn_name_with_flags, contrib_chunk); } ProfEnd(); } } ProfEnd(); tp_temp_end(temp); ProfEnd(); } U64 expected_image_header_size; { ProfBegin("Alloc Section Map"); task.sect_map = push_array(scratch.arena, LNK_SectionContrib **, objs_count); for EachIndex(obj_idx, objs_count) { task.sect_map[obj_idx] = push_array(scratch.arena, LNK_SectionContrib *, objs[obj_idx]->header.section_count_no_null); } ProfEnd(); tp_for_parallel_prof(tp, 0, objs_count, lnk_gather_section_contribs_task, &task, "Gather Section Contribs"); // ensure determinism by sorting section contribs in chunks by input index { ProfBegin("Sort Section Contribs"); U64 total_chunk_count = 0; { for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { total_chunk_count += sect_n->data.contribs.chunk_count; } } { U64 cursor = 0; task.u.sort_contribs.chunks = push_array(scratch.arena, LNK_SectionContribChunk *, total_chunk_count); for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { for (LNK_SectionContribChunk *chunk_n = sect_n->data.contribs.first; chunk_n != 0; chunk_n = chunk_n->next) { task.u.sort_contribs.chunks[cursor++] = chunk_n; } } Assert(cursor == total_chunk_count); } tp_for_parallel(tp, 0, total_chunk_count, lnk_sort_contribs_task, &task); ProfEnd(); } tp_for_parallel_prof(tp, 0, objs_count, lnk_set_comdat_leaders_contribs_task, &task, "Update Section Map With COMDAT Leader Contribs"); // build common block // // TODO: build common block in .bss and merge with .data U64 common_block_contribs_count; LNK_CommonBlockContrib *common_block_contribs; { ProfBegin("Build Common Block"); task.u.common_block.counts = push_array(scratch.arena, U64, tp->worker_count); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_count_common_block_contribs_task, &task, "Count Contribs"); ProfBegin("Push Contribs"); common_block_contribs_count = sum_array_u64(tp->worker_count, task.u.common_block.counts); common_block_contribs = push_array(scratch.arena, LNK_CommonBlockContrib, common_block_contribs_count); ProfEnd(); ProfBegin("Fill Out Contribs [%Iu64]", common_block_contribs_count); task.u.common_block.offsets = offsets_from_counts_array_u64(scratch.arena, task.u.common_block.counts, tp->worker_count); task.u.common_block.contribs = common_block_contribs; tp_for_parallel(tp, 0, tp->worker_count, lnk_fill_out_common_block_contribs_task, &task); ProfEnd(); if (common_block_contribs_count) { ProfBeginV("Make Common Block [count %llu]", common_block_contribs_count); // sort common blocks from for tighter packing radsort(common_block_contribs, common_block_contribs_count, lnk_common_block_contrib_is_before); // compute .bss virtual size - this marks start of the common block lnk_finalize_section_layout(common_block_sect, config->file_align, config->function_pad_min); U64 common_block_cursor = common_block_sect->vsize; // compute and assign offsets into the common block for EachIndex(contrib_idx, common_block_contribs_count) { LNK_CommonBlockContrib *contrib = &common_block_contribs[contrib_idx]; U32 size = contrib->u.size; U32 align = Min(32, u64_up_to_pow2(size)); // link.exe caps align at 32 bytes common_block_cursor = AlignPow2(common_block_cursor, align); contrib->u.offset = common_block_cursor; common_block_cursor += size; } // append common block's contribution LNK_SectionContribChunk *common_block_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &common_block_sect->contribs, 1, str8(0,0)); LNK_SectionContrib *common_block_sc = lnk_section_contrib_chunk_push(common_block_chunk, 1); common_block_sc->u.obj_idx = max_U32; common_block_sc->u.obj_sect_idx = max_U32; common_block_sc->align = 1; common_block_sc->first_data_node.next = 0; common_block_sc->first_data_node.string = str8(0, common_block_cursor - common_block_sect->vsize); common_block_sc->last_data_node = &common_block_sc->first_data_node; ProfEnd(); } ProfEnd(); } { ProfBegin("Finalize Sections Layout"); // Grouped Sections (PE Format) // "All contributions with the same object-section name are allocated contiguously in the image, // and the blocks of contributions are sorted in lexical order by object-section name." ProfBegin("Sort Sections"); for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { lnk_sort_section_contribs(§_n->data); } ProfEnd(); // merge sections if (config->flags & LNK_ConfigFlag_Merge) { lnk_section_table_merge(sectab, config->merge_list); } if (config->do_function_pad_min == LNK_SwitchState_Yes) { tp_for_parallel_prof(tp, arena, objs_count, lnk_flag_hotpatch_contribs_task, &task, "Flag Hotpatch Section Contribs"); } // assign contribs offsets, sizes, and section indices for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { lnk_finalize_section_layout(§_n->data, config->file_align, config->function_pad_min); } // remove empty sections { String8List empty_sect_list = {0}; for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { if (sect_n->data.vsize == 0) { str8_list_push(scratch.arena, &empty_sect_list, sect_n->data.name); } } for (String8Node *name_n = empty_sect_list.first; name_n != 0; name_n = name_n->next) { lnk_section_table_purge(sectab, name_n->string); } } // assign section indices to sections for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { lnk_assign_section_index(§_n->data, sectab->next_sect_idx++); } // assing layout offsets and sizes to merged sections for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) { LNK_Section *sect = §_n->data; LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); U64 last_sc_size = lnk_size_from_section_contrib(last_sc); sect->voff = sect->merge_dst->voff + first_sc->u.off; sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size; sect->foff = sect->merge_dst->foff + first_sc->u.off; sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc_size; lnk_assign_section_index(sect, sect->merge_dst->sect_idx); } ProfEnd(); } { ProfBegin("Patch Symbol Tables"); Temp temp = temp_begin(scratch.arena); // set up context for patch tasks task.u.patch_symtabs.common_block_sect = common_block_sect; task.u.patch_symtabs.common_block_ranges = tp_divide_work(temp.arena, common_block_contribs_count, tp->worker_count); task.u.patch_symtabs.common_block_contribs = common_block_contribs; task.u.patch_symtabs.was_symbol_patched = push_array(temp.arena, B8 *, objs_count); for EachIndex(obj_idx, objs_count) { task.u.patch_symtabs.was_symbol_patched[obj_idx] = push_array(temp.arena, B8, objs[obj_idx]->header.symbol_count); } // flag debug symbols to prevent them from being patched in subsequent passes tp_for_parallel_prof(tp, 0, objs_count, lnk_flag_debug_symbols_task, &task, "Flag Debug Symbols"); // patch symbols tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_comdat_leaders_task, &task, "COMDAT Leaders" ); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_patch_common_block_leaders_task, &task, "Common Block Leaders"); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_regular_symbols_task, &task, "Regular Symbols" ); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_common_symbols_task, &task, "Common Symbols" ); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_abs_symbols_task, &task, "Absolute Symbols" ); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_undefined_symbols_task, &task, "Undefined Symbols" ); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_weak_symbols_task, &task, "Weak Symbols" ); tp_for_parallel_prof(tp, 0, objs_count, lnk_patch_undefined_symbols_task, &task, "Undefined Symbols" ); temp_end(temp); ProfEnd(); } // section list -> array task.image_sects = lnk_section_array_from_list(scratch.arena, sectab->list); // assign virtual offsets to sections expected_image_header_size = lnk_compute_win32_image_header_size(config, task.image_sects.count); U64 voff_cursor = AlignPow2(expected_image_header_size + sizeof(COFF_SectionHeader), config->sect_align); for EachIndex(sect_idx, task.image_sects.count) { lnk_assign_section_virtual_space(task.image_sects.v[sect_idx], config->sect_align, &voff_cursor); } tp_for_parallel_prof(tp, 0, task.objs_count, lnk_patch_virtual_offsets_and_sizes_in_obj_section_headers_task, &task, "Patch Virtual Offsets and Sizes in Obj Section Headers"); // build base relocs if (~config->flags & LNK_ConfigFlag_Fixed) { String8 base_relocs_data = lnk_build_base_relocs(tp, arena, config, objs_count, objs); if (base_relocs_data.size) { LNK_Section *reloc = lnk_section_table_push(sectab, str8_lit(".reloc"), PE_RELOC_SECTION_FLAGS); LNK_SectionContribChunk *first_sc_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &reloc->contribs, 1, str8_zero()); LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(first_sc_chunk, 1); sc->first_data_node.string = base_relocs_data; sc->last_data_node = &sc->first_data_node; sc->align = 1; sc->u.obj_idx = max_U32; lnk_finalize_section_layout(reloc, config->file_align, config->function_pad_min); lnk_assign_section_virtual_space(reloc, config->sect_align, &voff_cursor); lnk_assign_section_index(reloc, sectab->next_sect_idx++); task.image_sects = lnk_section_array_from_list(scratch.arena, sectab->list); expected_image_header_size = lnk_compute_win32_image_header_size(config, task.image_sects.count); } } // assign file offsets to sections U64 foff_cursor = AlignPow2(expected_image_header_size, config->file_align); for EachIndex(sect_idx, task.image_sects.count) { lnk_assign_section_file_space(task.image_sects.v[sect_idx], &foff_cursor); } tp_for_parallel_prof(tp, 0, task.objs_count, lnk_patch_file_offsets_and_sizes_in_obj_section_headers_task, &task, "Patch File Offsets And Sizes In Section Headers"); } // build win32 image header { String8List image_header_data = lnk_build_win32_header(sectab->arena, symtab, config, task.image_sects, AlignPow2(expected_image_header_size, config->file_align)); LNK_Section *image_header_sect = lnk_section_table_push(sectab, str8_lit(".rad_linker_image_header_section"), 0); LNK_SectionContribChunk *image_header_sc_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &image_header_sect->contribs, 1, str8_zero()); LNK_SectionContrib *image_header_sc = lnk_section_contrib_chunk_push(image_header_sc_chunk, 1); image_header_sc->align = config->file_align; image_header_sc->first_data_node = *image_header_data.first; image_header_sc->last_data_node = image_header_data.last; lnk_finalize_section_layout(image_header_sect, config->file_align, config->function_pad_min); } tp_for_parallel_prof(tp, 0, task.objs_count, lnk_patch_section_symbols_task, &task, "Patch Section Symbols"); String8 image_data = {0}; { ProfBegin("Image Fill"); ProfBeginV("Alloc Image Buffer [%M]", lnk_section_table_total_fsize(sectab)); image_data.size = lnk_section_table_total_fsize(sectab); image_data.str = push_array_no_zero(arena->v[0], U8, image_data.size); ProfEnd(); ProfBegin("Fill Align Bytes"); for EachNode(sect_n, LNK_SectionNode, sectab->list.first) { LNK_Section *sect = §_n->data; ProfBeginV("Section: %S Size: %M", sect->name, sect->fsize); U8 fill_byte = sect->flags & COFF_SectionFlag_CntCode ? coff_code_align_byte_from_machine(config->machine) : 0; MemorySet(image_data.str + sect->foff, fill_byte, sect->fsize); ProfEnd(); } ProfEnd(); Temp temp = temp_begin(scratch.arena); ProfBegin("Prepare Worker Nodes"); LNK_ImageFillNode **fill_nodes = push_array(scratch.arena, LNK_ImageFillNode *, tp->worker_count); U64 worker_cap = 4096, worker_load = 0, worker_idx = 0; for EachNode(sect_n, LNK_SectionNode, sectab->list.first) { LNK_Section *sect = §_n->data; // skip bss sections if (sect->flags & COFF_SectionFlag_CntUninitializedData) { continue; } for EachNode(sc_chunk, LNK_SectionContribChunk, sect->contribs.first) { for (U64 sc_left = sc_chunk->count; sc_left > 0; ) { U64 count = Min(worker_cap - worker_load, sc_left); U64 sc_pos = sc_chunk->count - sc_left; sc_left -= count; LNK_ImageFillNode *n = push_array(scratch.arena, LNK_ImageFillNode, 1); n->base_foff = sect->foff; n->sc_count = count; n->sc = sc_chunk->v + sc_pos; SLLStackPush(fill_nodes[worker_idx], n); worker_load += count; if (worker_load >= worker_cap) { worker_load = 0; worker_idx = (worker_idx + 1) % tp->worker_count; } } } } ProfEnd(); task.u.image_fill.image_data = image_data; task.u.image_fill.fill_nodes = fill_nodes; tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_image_fill_task, &task, "Fill"); temp_end(temp); ProfEnd(); } { ProfBegin("Image Patch"); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); COFF_SectionHeader **image_section_table = coff_section_table_from_data(scratch.arena, image_data, pe.section_table_range); // patch relocs { LNK_ObjRelocPatcher task = { .image_data = image_data, .objs = objs, .image_base = pe.image_base, .image_section_table = image_section_table }; tp_for_parallel_prof(tp, 0, objs_count, lnk_obj_reloc_patcher, &task, "Patch Relocs"); } // patch load config { LNK_Symbol *load_config_symbol = lnk_symbol_table_search(symtab, str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME)); if (load_config_symbol) { U64 load_config_foff = lnk_foff_from_symbol(image_section_table, load_config_symbol); String8 load_config_data = str8_skip(image_data, load_config_foff); U32 load_config_size = 0; if (sizeof(load_config_size) <= load_config_data.size) { PE_DataDirectory *load_config_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_LOAD_CONFIG); load_config_dir->virt_off = lnk_voff_from_symbol(image_section_table, load_config_symbol); load_config_dir->virt_size = load_config_size; } else { // TODO: report corrupted load config } } } // patch exceptions { LNK_Section *pdata_sect = lnk_section_table_search(sectab, str8_lit(".pdata"), PE_PDATA_SECTION_FLAGS); if (pdata_sect) { String8 raw_pdata = str8_substr(image_data, rng_1u64(pdata_sect->foff, pdata_sect->foff + pdata_sect->vsize)); pe_pdata_sort(config->machine, raw_pdata); PE_DataDirectory *pdata_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_EXCEPTIONS); pdata_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, pdata_sect); pdata_dir->virt_size = lnk_get_section_contrib_size(pdata_sect); } } // patch export { LNK_Section *edata_sect = lnk_section_table_search(sectab, str8_lit(".edata"), PE_EDATA_SECTION_FLAGS); if (edata_sect) { PE_DataDirectory *export_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_EXPORT); LNK_SectionContrib *edata_first_contrib = lnk_get_first_section_contrib(edata_sect); LNK_SectionContrib *edata_last_contrib = lnk_get_last_section_contrib(edata_sect); export_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, edata_sect); export_dir->virt_size = lnk_get_section_contrib_size(edata_sect); } } // patch base relocs { LNK_Section *reloc_sect = lnk_section_table_search(sectab, str8_lit(".reloc"), PE_RELOC_SECTION_FLAGS); if (reloc_sect) { PE_DataDirectory *reloc_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_BASE_RELOC); reloc_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, reloc_sect); reloc_dir->virt_size = lnk_get_section_contrib_size(reloc_sect); } } // patch import and import addr { LNK_Section *idata_sect = lnk_section_table_search(sectab, str8_lit(".idata"), PE_IDATA_SECTION_FLAGS); LNK_Symbol *null_import_desc = lnk_symbol_table_searchf(symtab, "__NULL_IMPORT_DESCRIPTOR"); LNK_Symbol *null_thunk_data = lnk_symbol_table_searchf(symtab, "\x7f%S_NULL_THUNK_DATA", lnk_get_image_name(config)); if (idata_sect && null_import_desc && null_thunk_data) { COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_from_symbol(null_import_desc); LNK_SectionContrib *idata_first_contrib = lnk_get_first_section_contrib(idata_sect); PE_DataDirectory *import_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_IMPORT); import_dir->virt_off = image_section_table[idata_first_contrib->u.sect_idx + 1]->voff + idata_first_contrib->u.off; import_dir->virt_size = null_import_desc_parsed.value - idata_first_contrib->u.off; COFF_ParsedSymbol null_thunk_data_parsed = lnk_parsed_from_symbol(null_thunk_data); U64 null_thunk_data_voff = image_section_table[null_thunk_data_parsed.section_number]->voff + null_thunk_data_parsed.value; U64 first_import_foff = image_section_table[idata_first_contrib->u.sect_idx+1]->foff + idata_first_contrib->u.off; PE_ImportEntry *first_import = str8_deserial_get_raw_ptr(image_data, first_import_foff, sizeof(*first_import)); PE_DataDirectory *import_addr_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_IMPORT_ADDR); import_addr_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, idata_sect); import_addr_dir->virt_size = null_thunk_data_voff - first_import->import_addr_table_voff /* null */ + coff_word_size_from_machine(config->machine); } } // patch delay imports { LNK_Section *didat_sect = lnk_section_table_search(sectab, str8_lit(".didat"), PE_IDATA_SECTION_FLAGS); LNK_Symbol *null_import_desc = lnk_symbol_table_search(symtab, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR")); LNK_Symbol *last_null_thunk = lnk_symbol_table_searchf(symtab,"\x7f%S_NULL_THUNK_DATA_DLA", lnk_get_image_name(config)); if (didat_sect && null_import_desc && last_null_thunk) { COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_from_symbol(null_import_desc); LNK_SectionContrib *didat_first_contrib = lnk_get_first_section_contrib(didat_sect); PE_DataDirectory *import_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_DELAY_IMPORT); import_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, didat_sect); import_dir->virt_size = lnk_get_section_contrib_size(didat_sect); } } // patch TLS { LNK_Symbol *tls_used_symbol = lnk_symbol_table_searchf(symtab, MSCRT_TLS_SYMBOL_NAME); if (tls_used_symbol) { ProfBegin("Patch TLS"); // find max align in .tls U64 tls_align = 0; LNK_Section *tls_sect = lnk_section_table_search(sectab, str8_lit(".tls"), PE_TLS_SECTION_FLAGS); for (LNK_SectionContribChunk *sc_chunk = tls_sect->contribs.first; sc_chunk != 0; sc_chunk = sc_chunk->next) { for EachIndex (sc_idx, sc_chunk->count) { Assert(IsPow2(sc_chunk->v[sc_idx]->align)); tls_align = Max(tls_align, sc_chunk->v[sc_idx]->align); } } // patch-in align U64 tls_header_foff = lnk_foff_from_symbol(image_section_table, tls_used_symbol); B32 is_tls_header64 = coff_word_size_from_machine(config->machine) == 8; if (is_tls_header64) { PE_TLSHeader64 *tls_header = str8_deserial_get_raw_ptr(image_data, tls_header_foff, sizeof(*tls_header)); tls_header->characteristics |= coff_section_flag_from_align_size(tls_align); } else { PE_TLSHeader32 *tls_header = str8_deserial_get_raw_ptr(image_data, tls_header_foff, sizeof(*tls_header)); tls_header->characteristics |= coff_section_flag_from_align_size(tls_align); } // patch directory PE_DataDirectory *tls_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_TLS); tls_dir->virt_off = lnk_voff_from_symbol(image_section_table, tls_used_symbol); tls_dir->virt_size = is_tls_header64 ? sizeof(PE_TLSHeader64) : sizeof(PE_TLSHeader32); ProfEnd(); } } // patch debug { LNK_Section *debug_dir_sect = lnk_section_table_search(sectab, str8_lit(".RAD_LINK_PE_DEBUG_DIR"), PE_RDATA_SECTION_FLAGS); if (debug_dir_sect) { // patch directory PE_DataDirectory *debug_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_DEBUG); debug_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, debug_dir_sect); debug_dir->virt_size = lnk_get_section_contrib_size(debug_dir_sect); // find debug directory begin and end pair LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(debug_dir_sect); LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(debug_dir_sect); U64 debug_begin_foff = lnk_foff_from_section_contrib(image_section_table, first_sc); U64 debug_end_fopl = lnk_fopl_from_section_contrib(image_section_table, last_sc); // patch file offsets to the debug directories for (U64 cursor = debug_begin_foff; cursor + sizeof(PE_DebugDirectory) <= debug_end_fopl; cursor += sizeof(PE_DebugDirectory)) { PE_DebugDirectory *dir = str8_deserial_get_raw_ptr(image_data, cursor, sizeof(PE_DebugDirectory)); for (U64 section_number = 1; section_number < pe.section_count+1; section_number += 1) { if (image_section_table[section_number]->voff <= dir->voff && dir->voff < image_section_table[section_number]->voff + image_section_table[section_number]->vsize) { dir->foff = image_section_table[section_number]->foff + (dir->voff - image_section_table[section_number]->voff); } } } } } // patch resources { LNK_Section *rsrc_sect = lnk_section_table_search(sectab, str8_lit(".rsrc"), PE_RSRC_SECTION_FLAGS); if (rsrc_sect) { PE_DataDirectory *rsrc_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_RESOURCES); rsrc_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, rsrc_sect); rsrc_dir->virt_size = lnk_get_section_contrib_size(rsrc_sect); } } // image checksum if (config->flags & LNK_ConfigFlag_WriteImageChecksum) { ProfBegin("Image Checksum"); *pe.check_sum = pe_compute_checksum(image_data.str, image_data.size); ProfEnd(); } // compute image guid, and patch PDB and RDI guids { LNK_Symbol *guid_pdb_symbol = lnk_symbol_table_search(symtab, str8_lit("RAD_LINK_PE_DEBUG_GUID_PDB")); LNK_Symbol *guid_rdi_symbol = lnk_symbol_table_search(symtab, str8_lit("RAD_LINK_PE_DEBUG_GUID_RDI")); if (guid_pdb_symbol || guid_rdi_symbol) { switch (config->guid_type) { case LNK_DebugInfoGuid_Null: break; case Lnk_DebugInfoGuid_ImageBlake3: { ProfBegin("Hash Image With Blake3"); U128 hash = lnk_blake3_hash_parallel(tp, 128, image_data); MemoryCopy(&config->guid, hash.u8, sizeof(hash.u8)); ProfEnd(); } break; } } if (guid_pdb_symbol) { U64 cv_guid_foff = lnk_foff_from_symbol(image_section_table, guid_pdb_symbol); Guid *cv_guid = str8_deserial_get_raw_ptr(image_data, cv_guid_foff, sizeof(*cv_guid)); *cv_guid = config->guid; } if (guid_rdi_symbol) { U64 cv_guid_foff = lnk_foff_from_symbol(image_section_table, guid_rdi_symbol); Guid *cv_guid = str8_deserial_get_raw_ptr(image_data, cv_guid_foff, sizeof(*cv_guid)); *cv_guid = config->guid; } } ProfEnd(); } LNK_ImageContext image_ctx = {0}; image_ctx.image_data = image_data; image_ctx.sectab = sectab; lnk_timer_end(LNK_Timer_Image); ProfEnd(); // :EndImage scratch_end(scratch); return image_ctx; } internal PairU32 * lnk_obj_sect_idx_from_section(Arena *arena, U64 objs_count, LNK_Obj **objs, LNK_Section *sect, LNK_Config *config, U64 *obj_sect_idxs_count_out) { U64 max_contribs = 0; for (LNK_SectionContribChunk *chunk = sect->contribs.first; chunk != 0; chunk = chunk->next) { max_contribs += chunk->count; } U64 obj_sect_idxs_count = 0; PairU32 *obj_sect_idxs = push_array(arena, PairU32, max_contribs); for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) { LNK_Obj *obj = objs[obj_idx]; COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); String8 string_table = str8_substr(obj->data, obj->header.string_table_range); for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 full_section_name = coff_name_from_section_header(string_table, section_header); String8 section_name, section_postfix; coff_parse_section_name(full_section_name, §ion_name, §ion_postfix); if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_header->fsize == 0) { continue; } if (lnk_is_section_removed(config, section_name)) { continue; } if (sect->voff <= section_header->voff && section_header->voff < sect->voff + sect->vsize) { Assert(obj_sect_idxs_count < max_contribs); obj_sect_idxs[obj_sect_idxs_count].v0 = obj_idx; obj_sect_idxs[obj_sect_idxs_count].v1 = sect_idx; obj_sect_idxs_count += 1; } } } U64 pop_size = (max_contribs - obj_sect_idxs_count) * sizeof(obj_sect_idxs[0]); arena_pop(arena, pop_size); *obj_sect_idxs_count_out = obj_sect_idxs_count; return obj_sect_idxs; } internal COFF_SectionHeader * lnk_coff_section_header_from_obj_sect_idx_pair(LNK_Obj **objs, PairU32 p) { LNK_Obj *obj = objs[p.v0]; COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); return §ion_table[p.v1]; } global LNK_Obj **g_rad_map_objs; internal int lnk_obj_sect_idx_is_before(void *raw_a, void *raw_b) { PairU32 *a = raw_a, *b = raw_b; COFF_SectionHeader *section_header_a = lnk_coff_section_header_from_obj_sect_idx_pair(g_rad_map_objs, *a); COFF_SectionHeader *section_header_b = lnk_coff_section_header_from_obj_sect_idx_pair(g_rad_map_objs, *b); return section_header_a->voff < section_header_b->voff; } internal U64 lnk_pair_u32_nearest_section(PairU32 *arr, U64 count, LNK_Obj **objs, U32 voff) { U64 result = max_U64; if (count > 0) { COFF_SectionHeader *first = lnk_coff_section_header_from_obj_sect_idx_pair(objs, arr[0]); if (first->voff == voff) { return 0; } COFF_SectionHeader *last = lnk_coff_section_header_from_obj_sect_idx_pair(objs, arr[count-1]); if (last->voff <= voff) { return count - 1; } if (first->voff <= voff && voff < last->voff + last->vsize) { U64 l = 0; U64 r = count - 1; for (; l <= r; ) { U64 m = l + (r - l) / 2; COFF_SectionHeader *s = lnk_coff_section_header_from_obj_sect_idx_pair(objs, arr[m]); if (s->voff == voff) { return m; } else if (s->voff < voff) { l = m + 1; } else { r = m - 1; } } result = l; } } return result; } internal String8List lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs_count, LNK_Obj **objs, U64 libs_count, LNK_Lib **libs, LNK_SectionTable *sectab) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); COFF_SectionHeader **image_section_table = coff_section_table_from_data(scratch.arena, image_data, pe.section_table_range); String8List map = {0}; ProfBegin("SECTIONS"); str8_list_pushf(arena, &map, "# SECTIONS\n"); for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { LNK_Section *sect = §_n->data; str8_list_pushf(arena, &map, "%S\n", sect->name); str8_list_pushf(arena, &map, "%-4s %-8s %-8s %-8s %-8s %-16s %-4s %s\n", "No.", "VirtOff", "VirtSize", "FileOff", "FileSize", "Blake3", "Algn", "SC"); U64 obj_sect_idxs_count = 0; PairU32 *obj_sect_idxs = lnk_obj_sect_idx_from_section(scratch.arena, objs_count, objs, sect, config, &obj_sect_idxs_count); g_rad_map_objs = objs; radsort(obj_sect_idxs, obj_sect_idxs_count, lnk_obj_sect_idx_is_before); U64 global_sc_idx = 0; for (LNK_SectionContribChunk *sc_chunk = sect->contribs.first; sc_chunk != 0; sc_chunk = sc_chunk->next) { for (U64 sc_idx = 0; sc_idx < sc_chunk->count; sc_idx += 1, global_sc_idx += 1) { Temp temp = temp_begin(scratch.arena); LNK_SectionContrib *sc = sc_chunk->v[sc_idx]; U64 file_off = image_section_table[sc->u.sect_idx+1]->foff + sc->u.off; U64 virt_off = image_section_table[sc->u.sect_idx+1]->voff + sc->u.off; U64 virt_size = lnk_size_from_section_contrib(sc); U64 file_size = lnk_size_from_section_contrib(sc); String8 sc_data = str8_substr(image_data, rng_1u64(file_off, file_off + virt_size)); LNK_Obj *obj = 0; U32 sect_idx = 0; U64 obj_sect_idx_idx = lnk_pair_u32_nearest_section(obj_sect_idxs, obj_sect_idxs_count, objs, virt_off); if (obj_sect_idx_idx < obj_sect_idxs_count) { obj = objs[obj_sect_idxs[obj_sect_idx_idx].v0]; sect_idx = obj_sect_idxs[obj_sect_idx_idx].v1; } U128 sc_hash = {0}; if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { blake3_hasher hasher; blake3_hasher_init(&hasher); blake3_hasher_update(&hasher, sc_data.str, sc_data.size); blake3_hasher_finalize(&hasher, (U8 *)&sc_hash, sizeof(sc_hash)); } String8 sc_idx_str = push_str8f(temp.arena, "%4llx", global_sc_idx); String8 virt_size_str = push_str8f(temp.arena, "%08x", virt_size); String8 sc_hash_str = (~sect->flags & COFF_SectionFlag_CntUninitializedData) ? push_str8f(temp.arena, "%08x%08x", sc_hash.u64[0], sc_hash.u64[1]) : str8_lit("--------"); String8 file_off_str = (~sect->flags & COFF_SectionFlag_CntUninitializedData) ? push_str8f(temp.arena, "%08x", file_off) : str8_lit("--------"); String8 file_size_str = (~sect->flags & COFF_SectionFlag_CntUninitializedData) ? push_str8f(temp.arena, "%08x", file_size) : str8_lit("--------"); String8 virt_off_str = push_str8f(temp.arena, "%08x", virt_off); String8 align_str = push_str8f(temp.arena, "%4x", sc->align); String8 contrib_str; { String8List source_list = {0}; if (obj) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1); String8 string_table = str8_substr(obj->data, obj->header.string_table_range); String8 section_name = coff_name_from_section_header(string_table, section_header); LNK_Lib *lib = lnk_obj_get_lib(obj); if (lib) { String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(lib->path)); String8 obj_name = str8_skip_last_slash(obj->path); str8_list_pushf(temp.arena, &source_list, "%S(%S) SECT%X (%S)", lib_name, obj_name, sect_idx+1, section_name); } else { str8_list_pushf(temp.arena, &source_list, "%S SECT%X (%S)", obj->path, sect_idx+1, section_name); } } else { str8_list_pushf(temp.arena, &source_list, ""); } contrib_str = str8_list_join(temp.arena, &source_list, &(StringJoin){.sep=str8_lit(" ")}); } str8_list_pushf(arena, &map, "%S %S %S %S %S %S %S %S\n", sc_idx_str, virt_off_str, virt_size_str, file_off_str, file_size_str, sc_hash_str, align_str, contrib_str); temp_end(temp); } } str8_list_pushf(arena, &map, "\n"); } ProfEnd(); str8_list_pushf(arena, &map, "# DEBUG\n"); for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) { LNK_Obj *obj = objs[obj_idx]; COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; if (~section_header->flags & COFF_SectionFlag_LnkRemove && section_header->flags & LNK_SECTION_FLAG_DEBUG) { LNK_Lib *lib = lnk_obj_get_lib(obj); if (lib) { String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(lib->path)); String8 obj_name = str8_skip_last_slash(obj->path); str8_list_pushf(arena, &map, "%S(%S) SECT%X\n", lib_name, obj_name, sect_idx+1); } else { str8_list_pushf(arena, &map, "%S SECT%X\n", obj->path, sect_idx+1); } } } } str8_list_pushf(arena, &map, "\n"); ProfBegin("LIBS"); if (libs_count) { str8_list_pushf(arena, &map, "# LIBS\n"); for EachIndex(i, libs_count) { str8_list_pushf(arena, &map, "%S\n", libs[i]->path); } } ProfEnd(); scratch_end(scratch); ProfEnd(); return map; } internal void lnk_write_thread(void *raw_ctx) { ProfBeginFunction(); LNK_WriteThreadContext *ctx = raw_ctx; lnk_write_data_to_file_path(ctx->path, ctx->temp_path, ctx->data); ProfEnd(); } internal void lnk_log_timers(void) { Temp scratch = scratch_begin(0, 0); U64 total_build_time_micro = 0; for (U64 i = 0; i < LNK_Timer_Count; ++i) { total_build_time_micro += g_timers[i].end - g_timers[i].begin; } String8List output_list = {0}; str8_list_pushf(scratch.arena, &output_list, "------ Link Times --------------------------------------------------------------"); for (U64 i = 0; i < LNK_Timer_Count; ++i) { U64 build_time_micro = g_timers[i].end - g_timers[i].begin; if (build_time_micro != 0) { String8 timer_name = lnk_string_from_timer_type(i); DateTime time = date_time_from_micro_seconds(build_time_micro); String8 time_str = string_from_elapsed_time(scratch.arena, time); str8_list_pushf(scratch.arena, &output_list, " %-5S Time: %S", timer_name, time_str); } } DateTime total_time = date_time_from_micro_seconds(total_build_time_micro); String8 total_time_str = string_from_elapsed_time(scratch.arena, total_time); str8_list_pushf(scratch.arena, &output_list, " Total Time: %S", total_time_str); StringJoin new_line_join = { str8_lit_comp(""), str8_lit_comp("\n"), str8_lit_comp("") }; String8 output = str8_list_join(scratch.arena, &output_list, &new_line_join); lnk_log(LNK_Log_Timers, "%S\n", output); scratch_end(scratch); } internal void lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); // // Input Context // LNK_Inputer *inputer = lnk_inputer_init(); // // Symbol Table // LNK_SymbolTable *symtab = lnk_symbol_table_init(arena); // // Link Image // LNK_Link *link = lnk_link_image(tp, arena, config, inputer, symtab); U64 objs_count = link->objs.count; U64 libs_count = link->libs.count; LNK_Obj **objs = lnk_array_from_obj_list(scratch.arena, link->objs); LNK_Lib **libs = lnk_array_from_lib_list(scratch.arena, link->libs); // // Layout Image // LNK_ImageContext image_ctx = lnk_build_image(arena, tp, config, symtab, objs_count, objs); // Write image in the background LNK_WriteThreadContext *image_write_ctx = push_array(scratch.arena, LNK_WriteThreadContext, 1); image_write_ctx->path = config->image_name; image_write_ctx->temp_path = config->temp_image_name; image_write_ctx->data = image_ctx.image_data; Thread image_write_thread = thread_launch(lnk_write_thread, image_write_ctx); // // RAD Map // if (config->rad_chunk_map == LNK_SwitchState_Yes) { String8List rad_map = lnk_build_rad_map(scratch.arena, image_ctx.image_data, config, objs_count, objs, libs_count, libs, image_ctx.sectab); lnk_write_data_list_to_file_path(config->rad_chunk_map_name, config->temp_rad_chunk_map_name, rad_map); } // // Import Library // if (config->build_imp_lib && (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL)) { ProfBegin("Build Import Library"); lnk_timer_begin(LNK_Timer_Lib); String8 linker_debug_symbols = lnk_make_linker_debug_symbols(scratch.arena, config->machine); String8 lib = pe_make_import_lib(arena->v[0], config->machine, config->time_stamp, str8_skip_last_slash(config->image_name), linker_debug_symbols, config->export_symbol_list); lnk_write_data_to_file_path(config->imp_lib_name, str8_zero(), lib); lnk_timer_end(LNK_Timer_Lib); ProfEnd(); } // // Debug Info // if (lnk_do_debug_info(config)) { ProfBegin("Debug Info"); lnk_timer_begin(LNK_Timer_Debug); U64 debug_info_objs_count = 0; LNK_Obj **debug_info_objs = push_array(scratch.arena, LNK_Obj *, objs_count); for EachIndex(obj_idx, objs_count) { LNK_Obj *obj = objs[obj_idx]; if (obj->exclude_from_debug_info) { continue; } debug_info_objs[debug_info_objs_count++] = obj; } // // CodeView // LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs); CV_DebugT *types = lnk_import_types(tp, arena, &input); // // RDI // if (config->rad_debug == LNK_SwitchState_Yes) { lnk_timer_begin(LNK_Timer_Rdi); String8List rdi_data = lnk_build_rad_debug_info(tp, arena, config->target_os, rdi_arch_from_coff_machine(config->machine), config->image_name, image_ctx.image_data, input.count, input.obj_arr, input.debug_s_arr, input.total_symbol_input_count, input.symbol_inputs, input.parsed_symbols, types); lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_data); lnk_timer_end(LNK_Timer_Rdi); } // // PDB // // TODO: Parallel debug info builds are currently blocked by the patch // strings in $$FILE_CHECKSUM step in `lnk_process_c13_data_task`. if (config->debug_mode == LNK_DebugMode_Full) { lnk_timer_begin(LNK_Timer_Pdb); if (config->pdb_hash_type_names != LNK_TypeNameHashMode_Null && config->pdb_hash_type_names != LNK_TypeNameHashMode_None) { lnk_replace_type_names_with_hashes(tp, arena, types[CV_TypeIndexSource_TPI], config->pdb_hash_type_names, config->pdb_hash_type_name_length, config->pdb_hash_type_name_map); } String8List pdb_data = lnk_build_pdb(tp, arena, image_ctx.image_data, config, symtab, input.count, input.obj_arr, input.debug_s_arr, input.total_symbol_input_count, input.symbol_inputs, input.parsed_symbols, types); lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data); lnk_timer_end(LNK_Timer_Pdb); } lnk_timer_end(LNK_Timer_Debug); ProfEnd(); } // wait for the thread to finish writing image to disk thread_join(image_write_thread, -1); // // Timers // if (lnk_get_log_status(LNK_Log_Timers)) { lnk_log_timers(); } scratch_end(scratch); ProfEnd(); } internal void entry_point(CmdLine *cmdline) { Temp scratch = scratch_begin(0,0); lnk_init_error_handler(); LNK_Config *config = lnk_config_from_argcv(scratch.arena, cmdline->argc, cmdline->argv); TP_Context *tp = tp_alloc(scratch.arena, config->worker_count, config->max_worker_count, config->shared_thread_pool_name); TP_Arena *tp_arena = tp_arena_alloc(tp); lnk_run(tp, tp_arena, config); scratch_end(scratch); } ================================================ FILE: src/linker/lnk.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once // --- Input ------------------------------------------------------------------- typedef struct LNK_LibMemberRef { LNK_Lib *lib; U32 member_idx; struct LNK_LibMemberRef *next; } LNK_LibMemberRef; typedef struct LNK_LibMemberRefList { U64 count; LNK_LibMemberRef *first; LNK_LibMemberRef *last; } LNK_LibMemberRefList; typedef enum { LNK_InputSource_CmdLine, // specified on command line LNK_InputSource_Default, // specified through defaultlib switch LNK_InputSource_Obj, // refrenced from objects LNK_InputSource_Count } LNK_InputSourceType; typedef struct LNK_Input { String8 path; String8 data; B32 disallow; B32 is_thin; B32 has_disk_read_failed; B32 exclude_from_debug_info; LNK_LibMemberRef *link_member; void *loaded_input; struct LNK_Input *next; } LNK_Input; typedef struct LNK_InputList { U64 count; LNK_Input *first; LNK_Input *last; } LNK_InputList; typedef struct LNK_InputPtrArray { U64 count; LNK_Input **v; } LNK_InputPtrArray; typedef struct LNK_Inputer { Arena *arena; LNK_InputList objs; HashTable *objs_ht; LNK_InputList new_objs; HashTable *libs_ht; HashTable *missing_lib_ht; LNK_InputList libs; LNK_InputList new_libs[LNK_InputSource_Count]; } LNK_Inputer; // --- Image Link ------------------------------------------------------------- #define LNK_IMPORT_STUB "*** RAD_IMPORT_STUB ***" #define LNK_NULL_SYMBOL "*** RAD_NULL_SYMBOL ***" #define LNK_SECTION_FLAG_LIVE (1 << 0) #define LNK_SECTION_FLAG_DEBUG (1 << 1) typedef struct LNK_Link { LNK_ObjList objs; LNK_LibList libs; LNK_ObjNode **last_symbol_input; LNK_IncludeSymbolNode **last_include; String8Node **last_cmd_lib; String8Node **last_default_lib; String8Node **last_obj_lib; LNK_LibMemberRefList imports; B32 try_to_resolve_entry_point; } LNK_Link; // -- Image Layout ------------------------------------------------------------ #define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3 #define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3 typedef struct LNK_ImageContext { String8 image_data; LNK_SectionTable *sectab; } LNK_ImageContext; typedef struct LNK_SectionDefinition { String8 name; COFF_SectionFlags flags; U64 contribs_count; struct LNK_Obj *obj; U64 obj_sect_idx; } LNK_SectionDefinition; typedef struct LNK_CommonBlockContrib { struct LNK_Symbol *symbol; union { U32 size; U32 offset; } u; } LNK_CommonBlockContrib; // --- Ref --------------------------------------------------------------------- #define LNK_RELOCS_PER_TASK 0x1000 typedef struct LNK_RelocRefs { LNK_Obj *obj; COFF_RelocArray relocs; } LNK_RelocRefs; typedef struct LNK_RelocRefsNode { LNK_RelocRefs *v; struct LNK_RelocRefsNode *next; } LNK_RelocRefsNode; typedef union LNK_RelocRefsPointer { struct { LNK_RelocRefsNode *node; U64 tag; }; U64 v[2]; } LNK_RelocRefsPointer; typedef struct AlignType(16) LNK_RelocRefsList { LNK_RelocRefsPointer head; } LNK_RelocRefsList; // --- Base Reloc -------------------------------------------------------------- typedef struct LNK_BaseRelocPage { U32 buffer_offset; U32 voff; U64List *entries_addr32; U64List *entries_addr64; } LNK_BaseRelocPage; typedef struct LNK_BaseRelocPageNode { struct LNK_BaseRelocPageNode *next; LNK_BaseRelocPage v; } LNK_BaseRelocPageNode; typedef struct LNK_BaseRelocPageList { U64 count; LNK_BaseRelocPageNode *first; LNK_BaseRelocPageNode *last; } LNK_BaseRelocPageList; typedef struct LNK_BaseRelocPageArray { U64 count; LNK_BaseRelocPage *v; } LNK_BaseRelocPageArray; // --- Workers Contexts -------------------------------------------------------- typedef struct { B32 search_anti_deps; LNK_SymbolTable *symtab; LNK_Lib *lib; LNK_LibMemberRefList *member_ref_lists; } LNK_SearchLibTask; typedef struct { LNK_SymbolTable *symtab; U32 active_thread_count; LNK_RelocRefsList *reloc_refs; } LNK_OptRefTask; typedef struct { String8 image_data; LNK_Obj **objs; U64 image_base; COFF_SectionHeader **image_section_table; } LNK_ObjRelocPatcher; typedef struct { U64 page_size; B32 is_large_addr_aware; union { struct { LNK_Obj **objs; LNK_BaseRelocPageList *pages; HashTable **page_ht; } gather; struct { U64 buffer_size; U8 *buffer; LNK_BaseRelocPageArray pages; Rng1U64 *ranges; } serialize; }; } LNK_BaseRelocsTask; typedef struct LNK_ImageFillNode { U64 base_foff; U64 sc_count; LNK_SectionContrib **sc; struct LNK_ImageFillNode *next; } LNK_ImageFillNode; typedef struct { LNK_SymbolTable *symtab; LNK_SectionTable *sectab; U64 objs_count; LNK_Obj **objs; U64 function_pad_min; U64 default_align; LNK_SectionContrib *null_sc; LNK_SectionContrib ***sect_map; HashTable *contribs_ht; LNK_SectionArray image_sects; union { struct { HashTable **defns; } gather_sects; struct { U64 *counts; U64 *offsets; LNK_CommonBlockContrib *contribs; } common_block; struct { LNK_SectionContribChunk **chunks; } sort_contribs; struct { B8 **was_symbol_patched; LNK_Section *common_block_sect; Rng1U64 *common_block_ranges; LNK_CommonBlockContrib *common_block_contribs; COFF_SymbolValueInterpType fixup_type; } patch_symtabs; struct { String8 image_data; LNK_ImageFillNode **fill_nodes; } image_fill; } u; } LNK_BuildImageTask; typedef struct { String8 path; String8 temp_path; String8 data; } LNK_WriteThreadContext; typedef struct { String8 data; Rng1U64 *ranges; U128 *hashes; } LNK_Blake3Hasher; // --- Config ----------------------------------------------------------------- internal LNK_Config * lnk_config_from_argcv(Arena *arena, int argc, char **argv); // --- Entry Point ------------------------------------------------------------- internal void lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config); // --- Path -------------------------------------------------------------------- internal String8 lnk_make_full_path(Arena *arena, PathStyle system_path_style, String8 work_dir, String8 path); // --- Hasher ------------------------------------------------------------------ internal U128 lnk_blake3_hash_parallel(TP_Context *tp, U64 chunk_count, String8 data); // --- Manifest ---------------------------------------------------------------- internal String8 lnk_make_linker_manifest(Arena *arena, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List manifest_dependency_list); internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, String8List manifest_path_list); internal String8 lnk_manifest_from_inputs(Arena *arena, LNK_IO_Flags io_flags, String8 mt_path, String8 manifest_name, B32 manifest_uac, String8 manifest_level, String8 manifest_ui_access, String8List input_manifest_path_list, String8List deps_list); // --- Internal Objs ----------------------------------------------------------- internal String8 lnk_make_null_obj(Arena *arena); internal String8 lnk_make_res_obj(Arena *arena, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name); internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config); // --- Inputer ----------------------------------------------------------------- internal void lnk_input_list_push_node(LNK_InputList *list, LNK_Input *node); internal void lnk_input_list_concat_in_place(LNK_InputList *list, LNK_InputList *to_concat); internal LNK_InputPtrArray lnk_array_from_input_list(Arena *arena, LNK_InputList list); internal LNK_Inputer * lnk_inputer_init(void); internal LNK_Input * lnk_input_push(Arena *arena, LNK_InputList *list, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_linkgen(Arena *arena, LNK_InputList *list, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_thin(Arena *arena, LNK_InputList *list, HashTable *ht, String8 full_path); internal LNK_Input * lnk_inputer_push_obj(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_obj_linkgen(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_obj_thin(LNK_Inputer *inputer, LNK_LibMemberRef *link_member, String8 path); internal LNK_Input * lnk_inputer_push_lib(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_lib_linkgen(LNK_Inputer *inputer, LNK_InputSourceType input_source, String8 path, String8 data); internal LNK_Input * lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSourceType input_source, String8 lib_path); internal B32 lnk_inputer_has_items(LNK_Inputer *inputer); internal LNK_InputPtrArray lnk_inputer_flush(Arena *arena, TP_Context *tp, LNK_Inputer *inputer, LNK_IO_Flags io_flags, LNK_InputList *all_inputs, LNK_InputList *new_inputs); // --- Link Context ------------------------------------------------------------ internal void lnk_lib_member_ref_list_push_node(LNK_LibMemberRefList *list, LNK_LibMemberRef *node); internal void lnk_lib_member_ref_list_concat_in_place_array(LNK_LibMemberRefList *list, LNK_LibMemberRefList *to_concat_arr, U64 count); internal int lnk_lib_member_ref_is_before(void *raw_a, void *raw_b); internal LNK_LibMemberRef ** lnk_array_from_lib_member_list(Arena *arena, LNK_LibMemberRefList list); internal LNK_ObjNode * lnk_load_objs (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link, U64 *objs_count_out); internal void lnk_load_libs (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_Link *link); internal void lnk_link_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab, LNK_Link *link); internal LNK_Link * lnk_link_image (TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab); // --- Optimizations ----------------------------------------------------------- internal void lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_ObjList objs); // --- Win32 Image ------------------------------------------------------------- internal String8List lnk_build_guard_tables(TP_Context *tp, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs, COFF_MachineType machine, String8 entry_point_name, LNK_GuardFlags guard_flags, B32 emit_suppress_flag); internal String8 lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_temp, LNK_Config *config, U64 objs_count, LNK_Obj **objs); internal String8List lnk_build_win32_image_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sect_arr, U64 expected_image_header_size); internal LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, U64 obj_count, LNK_Obj **objs); // --- Logger ------------------------------------------------------------------ internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab); internal void lnk_log_timers(void); ================================================ FILE: src/linker/lnk_cmd_line.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8List lnk_arg_list_parse_windows_rules(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; U8 *ptr = string.str; U8 *opl = string.str + string.size; while (ptr < opl) { // skip white space and new lines for (;;) { U64 size = (U64)(opl - ptr); UnicodeDecode uni = utf8_decode(ptr, size); if (uni.codepoint != ' ' && uni.codepoint != '\n' && uni.codepoint != '\r') { break; } ptr += uni.inc; } if (*ptr == '\0') { break; } String8List token_builder = {0}; U8 *anchor = ptr; while (ptr < opl) { UnicodeDecode uni; uni = utf8_decode(ptr, (U64)(opl-ptr)); if (uni.codepoint == '\0' || uni.codepoint == '\n' || uni.codepoint == '\r' || uni.codepoint == ' ') { break; } // handle string and strip quotes if (uni.codepoint == '"') { String8 text_before_quote = str8(anchor, (U64)(ptr - anchor)); str8_list_push(scratch.arena, &token_builder, text_before_quote); // advance past starting quote ptr += uni.inc; anchor = ptr; U8 *quote_end = ptr; while (ptr < opl) { uni = utf8_decode(ptr, (U64)(opl - ptr)); ptr += uni.inc; // skip escape char if (uni.codepoint == '\\') { uni = utf8_decode(ptr, (U64)(opl - ptr)); ptr += uni.inc; } else if (uni.codepoint == '"' || uni.codepoint == '\0') { break; // found matching quote char } quote_end = ptr; } String8 text_inside_quotes = str8(anchor, (U64)(quote_end - anchor)); str8_list_push(scratch.arena, &token_builder, text_inside_quotes); anchor = ptr; } else { ptr += uni.inc; } } // push remaining text String8 text = str8(anchor, (U64)(ptr - anchor)); str8_list_push(scratch.arena, &token_builder, text); // push token String8 token = str8_list_join(arena, &token_builder, NULL); if (token.size) { str8_list_push(arena, &list, token); } } scratch_end(scratch); return list; } internal void lnk_cmd_line_push_option_node(LNK_CmdLine *cmd_line, LNK_CmdOption *opt) { SLLQueuePush(cmd_line->first_option, cmd_line->last_option, opt); cmd_line->option_count += 1; } internal LNK_CmdOption * lnk_cmd_line_push_option_list(Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8List value_strings) { // fill out node LNK_CmdOption *opt = push_array_no_zero(arena, LNK_CmdOption, 1); opt->next = 0; opt->string = string; opt->value_strings = value_strings; // push node lnk_cmd_line_push_option_node(cmd_line, opt); return opt; } internal LNK_CmdOption * lnk_cmd_line_push_option_string(Arena *arena, LNK_CmdLine *cmd_line, String8 string, String8 value) { String8List value_list = str8_split_by_string_chars(arena, value, str8_lit(","), StringSplitFlag_KeepEmpties); LNK_CmdOption *opt = lnk_cmd_line_push_option_list(arena, cmd_line, string, value_list); return opt; } internal LNK_CmdOption * lnk_cmd_line_push_option(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value) { return lnk_cmd_line_push_option_string(arena, cmd_line, str8_cstring(string), str8_cstring(value)); } internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_present(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value) { if (!lnk_cmd_line_has_option(*cmd_line, string)) { return lnk_cmd_line_push_option(arena, cmd_line, string, value); } return 0; } internal LNK_CmdLine lnk_cmd_line_parse_windows_rules(Arena *arena, String8List arg_list) { LNK_CmdLine cmd_line = {0}; cmd_line.raw_cmd_line = str8_list_copy(arena, &arg_list); for (String8Node *arg_node = arg_list.first; arg_node != 0; arg_node = arg_node->next) { String8 arg = arg_node->string; B32 is_option = str8_match_lit("/", arg, StringMatchFlag_RightSideSloppy) || str8_match_lit("-", arg, StringMatchFlag_RightSideSloppy); if (is_option) { U64 param_start_pos = str8_find_needle(arg, 0, str8_lit(":"), 0); String8 option_name = str8_chop(arg, arg.size - param_start_pos); // remove '/' or '-' from option name option_name = str8_skip(option_name, 1); // skip ':' String8 value_string = str8_skip(arg, param_start_pos + 1); // make value list String8List value_list = str8_split_by_string_chars(arena, value_string, str8_lit(","), 0); // push command lnk_cmd_line_push_option_list(arena, &cmd_line, option_name, value_list); } else { str8_list_push(arena, &cmd_line.input_list, arg); } } return cmd_line; } internal LNK_CmdOption * lnk_cmd_line_option_from_string(LNK_CmdLine cmd_line, String8 string) { LNK_CmdOption *opt; for (opt = cmd_line.first_option; opt != NULL; opt = opt->next) { if (str8_match(string, opt->string, StringMatchFlag_CaseInsensitive)) { break; } } return opt; } internal B32 lnk_cmd_line_has_option_string(LNK_CmdLine cmd_line, String8 string) { LNK_CmdOption *opt = lnk_cmd_line_option_from_string(cmd_line, string); B32 has_option = (opt != 0); return has_option; } internal B32 lnk_cmd_line_has_option(LNK_CmdLine cmd_line, char *string) { return lnk_cmd_line_has_option_string(cmd_line, str8_cstring(string)); } internal String8List lnk_data_from_cmd_line(Arena *arena, LNK_CmdLine cmd_line) { String8List result = {0}; for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) { // separate directives if (opt != cmd_line.first_option) { str8_list_pushf(arena, &result, " "); } // push new directive str8_list_pushf(arena, &result, "/%.*s", str8_varg(opt->string)); // do we have arguments? if (opt->value_strings.node_count > 0) { str8_list_pushf(arena, &result, ":"); for (String8Node *value_node = opt->value_strings.first; value_node != 0; value_node = value_node->next) { // separate arguments if (value_node != opt->value_strings.first) { str8_list_pushf(arena, &result, ","); } // push argument B32 has_spaces = str8_find_needle(value_node->string, 0, str8_lit(" "), StringMatchFlag_CaseInsensitive) < value_node->string.size; if (has_spaces) { str8_list_pushf(arena, &result, "\"%.*s\"", str8_varg(value_node->string)); } else { str8_list_pushf(arena, &result, "%.*s", str8_varg(value_node->string)); } } } } // append inputs for (String8Node *input_node = cmd_line.input_list.first; input_node != 0; input_node = input_node->next) { if (input_node != cmd_line.input_list.first) { str8_list_pushf(arena, &result, " "); } str8_list_pushf(arena, &result, "\"%.*s\"", str8_varg(input_node->string)); } return result; } ================================================ FILE: src/linker/lnk_cmd_line.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef struct LNK_CmdOption { struct LNK_CmdOption *next; String8 string; String8List value_strings; } LNK_CmdOption; typedef struct LNK_CmdLine { U64 option_count; LNK_CmdOption *first_option; LNK_CmdOption *last_option; String8List input_list; String8List raw_cmd_line; } LNK_CmdLine; internal String8List lnk_arg_list_parse_windows_rules(Arena *arena, String8 string); internal LNK_CmdLine lnk_cmd_line_parse_windows_rules(Arena *arena, String8List arg_list); internal LNK_CmdOption * lnk_cmd_line_option_from_string(LNK_CmdLine cmd_line, String8 string); internal B32 lnk_cmd_line_has_option_string(LNK_CmdLine cmd_line, String8 string); internal B32 lnk_cmd_line_has_option(LNK_CmdLine cmd_line, char *string); internal LNK_CmdOption * lnk_cmd_line_push_option(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value); internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_present(Arena *arena, LNK_CmdLine *cmd_line, char *string, char *value); internal String8List lnk_data_from_cmd_line(Arena *arena, LNK_CmdLine cmd_line); ================================================ FILE: src/linker/lnk_config.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) global read_only LNK_CmdSwitch g_cmd_switch_map[] = { { LNK_CmdSwitch_Null, 0, "", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "NOT_IMPLEMENTED", "", "" }, { LNK_CmdSwitch_Align, 0, "ALIGN", ":#", "" }, { LNK_CmdSwitch_AllowBind, 0, "ALLOWBIND", "[:NO]", "" }, { LNK_CmdSwitch_AllowIsolation, 0, "ALLOWISOLATION", "[:NO]", "" }, { LNK_CmdSwitch_AlternateName, 1, "ALTERNATENAME", "Creates an a symbol alias \"FROM=TO\"." }, { LNK_CmdSwitch_AppContainer, 0, "APPCONTAINER", "[:NO]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYDEBUG", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYLINKRESOURCE", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYMODULE", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYRESOURCE", "", "" }, // .NET { LNK_CmdSwitch_Base, 0, "BASE", "{ADDRESS[,SIZE]|@FILENAME,KEY}", "" }, { LNK_CmdSwitch_Brepro, 0, "BREPRO", "", "Not supported" }, { LNK_CmdSwitch_NotImplemented, 0, "CLRIMAGETYPE", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "CLRLOADEROPTIMIZATION","", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "CLRSUPPORTLASTERROR", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "CLRTHREADATTRIBUTE", "", "" }, // .NET { LNK_CmdSwitch_NotImplemented, 0, "CLRUNMANAGEDCODECHECK","", "" }, // .NET { LNK_CmdSwitch_Debug, 0, "DEBUG", "[:{FULL|NONE}]", "" }, { LNK_CmdSwitch_Dump, 0, "DUMP", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "DEF", ":FILENAME", "" }, { LNK_CmdSwitch_DefaultLib, 1, "DEFAULTLIB", ":LIBNAME", "" }, { LNK_CmdSwitch_Delay, 0, "DELAY", ":{NOBIND|UNLOAD}", "" }, { LNK_CmdSwitch_DelayLoad, 0, "DELAYLOAD", ":DLL", "" }, { LNK_CmdSwitch_NotImplemented, 0, "DELAYSIGN", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "DEPENDENTLOADFLAG", "", "" }, { LNK_CmdSwitch_Dll, 0, "DLL", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "DRIVER", "", "" }, { LNK_CmdSwitch_DisallowLib, 1, "DISALLOWLIB", ":LIBRARY", "", }, { LNK_CmdSwitch_D2, 0, "D2", "" }, { LNK_CmdSwitch_EditAndContinue, 1, "EDITANDCONTINUE", "[:NO]", "" }, { LNK_CmdSwitch_DynamicBase, 0, "DYNAMICBASE", "[:NO]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "EMITVOLATILEMETADATA", "", "" }, { LNK_CmdSwitch_Entry, 1, "ENTRY", ":FUNCTION", "" }, { LNK_CmdSwitch_ErrorReport, 0, "ERRORREPORT", "", "Deprecated starting Windows Vista." }, { LNK_CmdSwitch_Export, 1, "EXPORT", ":SYMBOL", "" }, { LNK_CmdSwitch_NotImplemented, 0, "EXPORTADMIN", "", "" }, { LNK_CmdSwitch_FastFail, 0, "FASTFAIL", "", "Not used." }, { LNK_CmdSwitch_NotImplemented, 0, "FASTGENPROFILE", "", "" }, { LNK_CmdSwitch_FailIfMismatch, 1, "FAILIFMISMATCH", "", "" }, { LNK_CmdSwitch_FileAlign, 0, "FILEALIGN", ":#", "" }, { LNK_CmdSwitch_Fixed, 0, "FIXED", "[:NO]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "FORCE", "", "" }, { LNK_CmdSwitch_FunctionPadMin, 0, "FUNCTIONPADMIN", ":#", "Not Implemented" }, { LNK_CmdSwitch_NotImplemented, 0, "GUARD", "", "" }, { LNK_CmdSwitch_GuardSym, 1, "GUARDSYM", "", "", }, { LNK_CmdSwitch_NotImplemented, 0, "GENPROFILE", "", "" }, { LNK_CmdSwitch_Heap, 0, "HEAP", "RESERVE[,COMMIT]", "" }, { LNK_CmdSwitch_HighEntropyVa, 0, "HIGHENTROPYVA", "[:NO]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "IDLOUT", "", "" }, { LNK_CmdSwitch_Ignore, 0, "IGNORE", ":#", "" }, { LNK_CmdSwitch_NotImplemented, 0, "IGNOREIDL", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "ILK", "", "" }, { LNK_CmdSwitch_ImpLib, 0, "IMPLIB", ":FILENAME", "" }, { LNK_CmdSwitch_Include, 1, "INCLUDE", "", "" }, { LNK_CmdSwitch_Incremental, 0, "INCREMENTAL", "[:NO]", "Incremental linking is not supported." }, { LNK_CmdSwitch_NotImplemented, 0, "INTEGRITYCHECK", "", "" }, { LNK_CmdSwitch_InferAsanLibs, 1, "INFERASANLIBS", "[:NO]", "" }, { LNK_CmdSwitch_InferAsanLibsNo, 1, "INFERASANLIBSNO", "", "", }, { LNK_CmdSwitch_NotImplemented, 0, "KERNEL", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "KEYCONTAINER", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "KEYFILE", "", "" }, { LNK_CmdSwitch_LargeAddressAware, 0, "LARGEADDRESSAWARE", "[:NO]", "" }, { LNK_CmdSwitch_Lib, 0, "LIB", "" }, { LNK_CmdSwitch_LibPath, 0, "LIBPATH", ":DIR", "" }, { LNK_CmdSwitch_NotImplemented, 0, "LINKERREPO", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "LINKERREPOTARGET", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "LTCG", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "LTCGOUT", "", "" }, { LNK_CmdSwitch_Machine, 0, "MACHINE", ":{X64|X86}", "" }, { LNK_CmdSwitch_Manifest, 0, "MANIFEST", "[:{EMBED[,ID=#]|NO]", "" }, { LNK_CmdSwitch_ManifestDependency, 1, "MANIFESTDEPENDENCY", ":\"manifest dependency XML string\"", "" }, { LNK_CmdSwitch_ManifestFile, 0, "MANIFESTFILE", ":FILENAME", "" }, { LNK_CmdSwitch_ManifestInput, 0, "MANIFESTINPUT", ":FILENAME", "" }, { LNK_CmdSwitch_ManifestUac, 0, "MANIFESTUAC", ":{NO|{'level'={'asInvoker'|'highestAvailable'|'requireAdministrator'} ['uiAccess'={'true'|'false'}]}}", "" }, { LNK_CmdSwitch_NotImplemented, 0, "MAP", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "MAPINFO", "", "" }, { LNK_CmdSwitch_Merge, 1, "MERGE", ":from=to", "" }, { LNK_CmdSwitch_NotImplemented, 0, "MIDL", "", "" }, { LNK_CmdSwitch_Natvis, 0, "NATVIS", ":FILENAME", "" }, { LNK_CmdSwitch_NotImplemented, 0, "NOASSEMBLY", "", "" }, { LNK_CmdSwitch_NoDefaultLib, 1, "NODEFAULTLIB", ":LIBNAME", "" }, { LNK_CmdSwitch_NoDefaultLib, 0, "NOD", ":LIBNAME", "" }, { LNK_CmdSwitch_NotImplemented, 0, "NOENTRY", "", "" }, { LNK_CmdSwitch_NoExp, 0, "NOEXP", "", ".exp is not supported." }, { LNK_CmdSwitch_NoImpLib, 0, "NOIMPLIB", "", "" }, { LNK_CmdSwitch_NoLogo, 0, "NOLOGO", "", "" }, { LNK_CmdSwitch_NxCompat, 0, "NXCOMPAT", "[:NO]", "" }, { LNK_CmdSwitch_Opt, 0, "OPT", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "ORDER", "", "" }, { LNK_CmdSwitch_Out, 0, "OUT", ":FILENAME", "" }, { LNK_CmdSwitch_Pdb, 0, "PDB", ":FILENAME", "" }, { LNK_CmdSwitch_PdbAltPath, 0, "PDBALTPATH", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "PDBSTRIPPED", "", "" }, { LNK_CmdSwitch_PdbPageSize, 0, "PDBPAGESIZE", ":#", "Page size must be power of two" }, { LNK_CmdSwitch_NotImplemented, 0, "PROFILE", "", "" }, { LNK_CmdSwitch_Release, 1, "RELEASE", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "SAFESEH", "", "" }, { LNK_CmdSwitch_Section, 1, "SECTION", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "SOURCELINK", "", "" }, { LNK_CmdSwitch_Stack, 1, "STACK", ":RESERVE[,COMMIT]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "STUB", "", "" }, { LNK_CmdSwitch_SubSystem, 1, "SUBSYSTEM", ":{CONSOLE|NATIVE|WINDOWS}[,#[.##]]", "" }, { LNK_CmdSwitch_NotImplemented, 0, "SWAPRUN", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "TLBID", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "TLBOUT", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "TIME", "", "" }, { LNK_CmdSwitch_TsAware, 0, "TSAWARE", "[:NO]", "" }, { LNK_CmdSwitch_ThrowingNew, 1, "THROWINGNEW", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "USERPROFILE", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "VERBOSE", "", "" }, { LNK_CmdSwitch_Version, 0, "VERSION", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WINMD", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WINMDDELAYSIGN", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WINMDKEYCONTAINER", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WINMDKEYFILE", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WHOLEARCHIVE", "", "" }, { LNK_CmdSwitch_NotImplemented, 0, "WX", "", "" }, //- internal switches { LNK_CmdSwitch_Rad_Age, 0, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." }, { LNK_CmdSwitch_Rad_AltPchDir, 0, "RAD_ALT_PCH_DIR", ":PATH", "Alternative directory to search for PCH object files." }, { LNK_CmdSwitch_Rad_BuildInfo, 0, "RAD_BUILD_INFO", "", "Print build info and exit." }, { LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, 0, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" }, { LNK_CmdSwitch_Rad_Map, 0, "RAD_MAP", ":FILENAME", "Emit file with the output image's layout description." }, { LNK_CmdSwitch_Rad_MapLinesForUnresolvedSymbols, 0, "RAD_MAP_LINES_FOR_UNRESOLVED_SYMBOLS", "[:NO]", "Use debug info to print source file location for unresolved symbol" }, { LNK_CmdSwitch_Rad_MemoryMapFiles, 0, "RAD_MEMORY_MAP_FILES", "[:NO]", "When enabled, files are memory-mapped instead of being read entirely on request." }, { LNK_CmdSwitch_Rad_Debug, 0, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." }, { LNK_CmdSwitch_Rad_DebugAltPath, 0, "RAD_DEBUGALTPATH", "", "" }, { LNK_CmdSwitch_Rad_DebugName, 0, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." }, { LNK_CmdSwitch_Rad_DelayBind, 0, "RAD_DELAY_BIND", "[:NO]", "" }, { LNK_CmdSwitch_Rad_DoMerge, 0, "RAD_DO_MERGE", "[:NO]", "" }, { LNK_CmdSwitch_Rad_EnvLib, 0, "RAD_ENV_LIB", "[:NO]", "" }, { LNK_CmdSwitch_Rad_Exe, 0, "RAD_EXE", "[:NO]", "" }, { LNK_CmdSwitch_Rad_Guid, 0, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" }, { LNK_CmdSwitch_Rad_LargePages, 0, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." }, { LNK_CmdSwitch_Rad_LinkVer, 0, "RAD_LINK_VER", ":##,##", "" }, { LNK_CmdSwitch_Rad_Log, 0, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" }, { LNK_CmdSwitch_Rad_MtPath, 0, "RAD_MT_PATH", ":EXEPATH", "Exe path to manifest tool, default: " LNK_MANIFEST_MERGE_TOOL_NAME }, { LNK_CmdSwitch_Rad_OsVer, 0, "RAD_OS_VER", ":##,##", "" }, { LNK_CmdSwitch_Rad_PageSize, 0, "RAD_PAGE_SIZE", ":#", "Must be power of two." }, { LNK_CmdSwitch_Rad_PathStyle, 0, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" }, { LNK_CmdSwitch_Rad_PdbHashTypeNameLength, 0, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." }, { LNK_CmdSwitch_Rad_PdbHashTypeNameMap, 0, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." }, { LNK_CmdSwitch_Rad_PdbHashTypeNames, 0, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." }, { LNK_CmdSwitch_Rad_RemoveSection, 0, "RAD_REMOVE_SECTION", ":NAME", "Removes a section from output image." }, { LNK_CmdSwitch_Rad_SharedThreadPool, 0, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" }, { LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, 0, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." }, { LNK_CmdSwitch_Rad_SuppressError, 0, "RAD_SUPPRESS_ERROR", ":#", "" }, { LNK_CmdSwitch_Rad_TargetOs, 0, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" }, { LNK_CmdSwitch_Rad_WriteTempFiles, 0, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." }, { LNK_CmdSwitch_Rad_TimeStamp, 0, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." }, { LNK_CmdSwitch_Rad_UnresolvedSymbolLimit, 0, "RAD_UNRESOLVED_SYMBOL_LIMIT", ":#", "Limits number of unresolved symbol errors linker reports." }, { LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit, 0, "RAD_UNRESOLVED_SYMBOL_REF_LIMIT", ":#", "Limit number of unresolved symbol references linker reports." }, { LNK_CmdSwitch_Rad_Version, 0, "RAD_VERSION", "", "Print version and exit." }, { LNK_CmdSwitch_Rad_Workers, 0, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." }, { LNK_CmdSwitch_Help, 0, "HELP", "", "" }, { LNK_CmdSwitch_Help, 0, "?", "", "" }, }; global read_only struct { char *name; LNK_InputType type; } g_input_type_map[] = { { "o", LNK_Input_Obj }, { "obj", LNK_Input_Obj }, { "lib", LNK_Input_Lib }, { "rlib", LNK_Input_Lib }, // rust libs { "res", LNK_Input_Res }, }; global read_only struct { char *name; LNK_DebugMode mode; } g_debug_mode_map[] = { { "null", LNK_DebugMode_Null }, { "none", LNK_DebugMode_None }, { "fastlink", LNK_DebugMode_FastLink }, { "ghash", LNK_DebugMode_GHash }, { "full", LNK_DebugMode_Full }, }; global read_only struct { char *name; LNK_TypeNameHashMode mode; } g_type_name_hash_mode_map[] = { { "none", LNK_TypeNameHashMode_None }, { "lenient", LNK_TypeNameHashMode_Lenient }, { "full", LNK_TypeNameHashMode_Full } }; internal LNK_CmdSwitchType lnk_cmd_switch_type_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_cmd_switch_map); i += 1) { if (str8_match_cstr(g_cmd_switch_map[i].name, name, StringMatchFlag_CaseInsensitive)) { return g_cmd_switch_map[i].type; } } return LNK_CmdSwitch_Null; } internal LNK_CmdSwitch * lnk_cmd_switch_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_cmd_switch_map); i += 1) { if (str8_match_cstr(g_cmd_switch_map[i].name, name, StringMatchFlag_CaseInsensitive)) { return &g_cmd_switch_map[i]; } } return 0; } internal LNK_CmdSwitch * lnk_cmd_switch_from_type(LNK_CmdSwitchType type) { for (U64 cmd_idx = 0; cmd_idx < ArrayCount(g_cmd_switch_map); cmd_idx += 1) { if (g_cmd_switch_map[cmd_idx].type == type) { return &g_cmd_switch_map[cmd_idx]; } } return 0; } internal String8 lnk_string_from_cmd_switch_type(LNK_CmdSwitchType type) { LNK_CmdSwitch *cmd_switch = lnk_cmd_switch_from_type(type); return cmd_switch ? str8_cstring(cmd_switch->name) : str8_zero(); } internal LNK_InputType lnk_input_type_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_input_type_map); i += 1) { if (str8_match_cstr(g_input_type_map[i].name, name, StringMatchFlag_CaseInsensitive)) { return g_input_type_map[i].type; } } return LNK_Input_Null; } internal LNK_DebugMode lnk_debug_mode_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_debug_mode_map); i += 1) { if (str8_match_cstr(g_debug_mode_map[i].name, name, StringMatchFlag_CaseInsensitive)) { return g_debug_mode_map[i].mode; } } return LNK_DebugMode_Null; } internal LNK_TypeNameHashMode lnk_type_name_hash_mode_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_type_name_hash_mode_map); i += 1) { if (str8_match_cstr(g_type_name_hash_mode_map[i].name, name, StringMatchFlag_CaseInsensitive)) { return g_type_name_hash_mode_map[i].mode; } } return LNK_TypeNameHashMode_Null; } internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_presentf(Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...) { LNK_CmdOption *opt = 0; String8 cmd_switch_name = lnk_string_from_cmd_switch_type(cmd_switch_type); if (!lnk_cmd_line_has_option_string(*cmd_line, cmd_switch_name)) { va_list param_args; va_start(param_args, param_fmt); String8 param_str = push_str8fv(arena, param_fmt, param_args); va_end(param_args); opt = lnk_cmd_line_push_option_string(arena, cmd_line, cmd_switch_name, param_str); } return opt; } internal LNK_CmdOption * lnk_cmd_line_push_optionf(Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch, char *param_fmt, ...) { va_list param_args; va_start(param_args, param_fmt); String8 param_str = push_str8fv(arena, param_fmt, param_args); va_end(param_args); String8 cmd_switch_name = lnk_string_from_cmd_switch_type(cmd_switch); LNK_CmdOption *opt = lnk_cmd_line_push_option_string(arena, cmd_line, cmd_switch_name, param_str); return opt; } internal B32 lnk_cmd_line_has_switch(LNK_CmdLine cmd_line, LNK_CmdSwitchType cmd_switch) { String8 cmd_switch_name = lnk_string_from_cmd_switch_type(cmd_switch); return lnk_cmd_line_has_option_string(cmd_line, cmd_switch_name); } internal void lnk_error_cmd_switch(LNK_ErrorCode code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, char *fmt, ...) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 switch_name = lnk_string_from_cmd_switch_type(cmd_switch); String8 message = push_str8fv(scratch.arena, fmt, args); String8 output = push_str8f(scratch.arena, "/%S: %S", switch_name, message); lnk_error_obj(code, obj, "%S", output); va_end(args); scratch_end(scratch); } internal void lnk_error_cmd_switch_invalid_param_count(LNK_ErrorCode code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch) { lnk_error_cmd_switch(code, obj, cmd_switch, "invalid number of parameters"); } internal void lnk_error_cmd_switch_invalid_param(LNK_ErrorCode code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8 param) { lnk_error_cmd_switch(code, obj, cmd_switch, "invalid parameter \"%S\"", param); } internal String8 lnk_error_check_and_strip_quotes(LNK_ErrorCode error_code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8 string) { String8 result = string; B32 starts_with_quote = str8_match(str8_substr(string, rng_1u64(0,1)), str8_lit("\""), 0); B32 ends_with_quote = 0; if (string.size > 2) { ends_with_quote = str8_match(str8_substr(string, rng_1u64(string.size-1,string.size)), str8_lit("\""), 0); } if (starts_with_quote && ends_with_quote) { result = str8_skip(result, 1); result = str8_chop(result, 1); } else if (starts_with_quote && !ends_with_quote) { lnk_error_cmd_switch(error_code, obj, cmd_switch, "detected unmatched \" in \"%S\"", string); } return result; } internal void lnk_error_invalid_uac_level_param(LNK_ErrorCode error_code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8 input) { lnk_error_cmd_switch(error_code, obj, cmd_switch, "invalid param format, expected \"level={'asInvoker'|'highestAvailable'|'requireAdministrator'}\" but got \"%S\"", input); } internal void lnk_error_invalid_uac_ui_access_param(LNK_ErrorCode error_code, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8 input) { lnk_error_cmd_switch(error_code, obj, cmd_switch, "invalid param format, expected \"uiAccess={'true'|'false'}\" but got \"%S\"", input); } internal B32 lnk_cmd_switch_parse_version(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, Version *ver_out) { Temp scratch = scratch_begin(0,0); B32 is_parsed = 0; if (value_strings.node_count == 1) { String8List split_list = str8_split_by_string_chars(scratch.arena, value_strings.first->string, str8_lit("."), StringSplitFlag_KeepEmpties); String8 maj_str = str8_lit("0"); String8 min_str = str8_lit("0"); if (split_list.node_count == 1) { maj_str = split_list.first->string; } else if (split_list.node_count == 2) { maj_str = split_list.first->string; min_str = split_list.last->string; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid version format, too many dots, expected format: {N[.N]}"); goto exit; } U64 maj, min; if (try_u64_from_str8_c_rules(maj_str, &maj)) { if (try_u64_from_str8_c_rules(min_str, &min)) { *ver_out = make_version(maj, min); is_parsed = 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse minor version"); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse major version"); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } exit:; scratch_end(scratch); return is_parsed; } internal B32 lnk_cmd_switch_parse_tuple(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, Rng1U64 *tuple_out) { if (value_strings.node_count == 1) { U64 value; if (try_u64_from_str8_c_rules(value_strings.first->string, &value)) { tuple_out->v[0] = value; return 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse the parameter \"%S\"", value_strings.first->string); } } else if (value_strings.node_count == 2) { U64 a,b; if (try_u64_from_str8_c_rules(value_strings.first->string, &a)) { if (try_u64_from_str8_c_rules(value_strings.last->string, &b)) { tuple_out->v[0] = a; tuple_out->v[1] = b; return 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable ot parse second parameter \"%S\"", value_strings.last->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse first parameter \"%S\"", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } return 0; } internal B32 lnk_try_parse_u64(String8 string, LNK_ParseU64Flags flags, U64 *value_out) { if (try_u64_from_str8_c_rules(string, value_out)) { if (flags & LNK_ParseU64Flag_CheckUnder32bit) { if (*value_out > max_U32) { return 0; } } if (flags & LNK_ParseU64Flag_CheckPow2) { if (!IsPow2(*value_out)) { return 0; } } } return 1; } internal B32 lnk_cmd_switch_parse_u64(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *value_out, LNK_ParseU64Flags flags) { if (value_strings.node_count != 1) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters, exepcted integer number as input"); return 0; } if (!lnk_try_parse_u64(value_strings.first->string, flags, value_out)) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse string \"%S\"", value_strings.first->string); return 0; } return 1; } internal B32 lnk_cmd_switch_parse_u32(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U32 *value_out, LNK_ParseU64Flags flags) { U64 value; if (lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &value, flags | LNK_ParseU64Flag_CheckUnder32bit)) { *value_out = (U32)value; return 1; } return 0; } internal B32 lnk_cmd_switch_parse_u64_list(Arena *arena, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64List *list_out, LNK_ParseU64Flags flags) { for (String8Node *string_n = value_strings.first; string_n != 0; string_n = string_n->next) { U64 value; if (!lnk_try_parse_u64(string_n->string, flags, &value)) { return 0; } u64_list_push(arena, list_out, value); } return 1; } internal B32 lnk_cmd_switch_parse_flag(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, LNK_SwitchState *value_out) { B32 is_parsed = 0; if (value_strings.node_count > 1) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "too many parameters"); } else if (value_strings.node_count == 1) { if (str8_match_lit("no", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { *value_out = LNK_SwitchState_No; is_parsed = 1; } else if (str8_match_lit("yes", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { *value_out = LNK_SwitchState_Yes; is_parsed = 1; } else if (value_strings.first->string.size == 0) { *value_out = 1; is_parsed = 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid parameter \"%S\"", value_strings.first->string); } } else { *value_out = LNK_SwitchState_Yes; is_parsed = 1; } return is_parsed; } internal void lnk_cmd_switch_set_flag_inv_16(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U16 *flags, U16 bits) { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { switch (state) { case LNK_SwitchState_Null: break; case LNK_SwitchState_Yes : *flags |= bits; break; case LNK_SwitchState_No : *flags &= ~bits; break; } } } internal void lnk_cmd_switch_set_flag_inv_64(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *flags, U64 bits) { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { switch (state) { case LNK_SwitchState_Null: break; case LNK_SwitchState_Yes : *flags |= bits; break; case LNK_SwitchState_No : *flags &= ~bits; break; } } } internal void lnk_cmd_switch_set_flag_16(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U16 *flags, U16 bits) { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { switch (state) { case LNK_SwitchState_Null: break; case LNK_SwitchState_Yes : *flags |= bits; break; case LNK_SwitchState_No : *flags &= ~bits; break; } } } internal void lnk_cmd_switch_set_flag_32(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U32 *flags, U32 bits) { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { switch (state) { case LNK_SwitchState_Null: break; case LNK_SwitchState_Yes : *flags |= bits; break; case LNK_SwitchState_No : *flags &= ~bits; break; } } } internal void lnk_cmd_switch_set_flag_64(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *flags, U64 bits) { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { switch (state) { case LNK_SwitchState_Null: break; case LNK_SwitchState_Yes : *flags |= bits; break; case LNK_SwitchState_No : *flags &= ~bits; break; } } } internal B32 lnk_cmd_switch_parse_string(LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out) { if (value_strings.node_count == 1) { if (value_strings.first->string.size > 0) { *string_out = value_strings.first->string; return 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "empty string is not permitted"); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } return 0; } internal void lnk_cmd_switch_parse_string_copy(Arena *arena, LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out) { if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, string_out)) { *string_out = push_str8_copy(arena, *string_out); } } internal B32 lnk_parse_alt_name_directive(String8 string, LNK_Obj *obj, LNK_AltName *alt_out) { Temp scratch = scratch_begin(0,0); B32 is_parse_ok = 0; String8List pair = str8_split_by_string_chars(scratch.arena, string, str8_lit("="), 0); if (pair.node_count == 2) { alt_out->from = pair.first->string; alt_out->to = pair.last->string; alt_out->obj = obj; is_parse_ok = 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, LNK_CmdSwitch_AlternateName, "syntax error in \"%S\", expected format \"FROM=TO\"", string); } scratch_end(scratch); return is_parse_ok; } internal B32 lnk_parse_export_directive_ex(Arena *arena, String8List directive, LNK_Obj *obj, PE_ExportParse *export_out) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); B32 is_parsed = 0; // parse "alias=name" String8 name = {0}; String8 alias = {0}; String8List flags = {0}; { String8List alias_name_split = str8_split_by_string_chars(scratch.arena, directive.first->string, str8_lit("="), 0); if (alias_name_split.node_count == 2) { alias = alias_name_split.first->string; name = alias_name_split.last->string; } else if (alias_name_split.node_count == 1) { name = alias_name_split.first->string; } else { String8 d = str8_list_join(scratch.arena, &directive, &(StringJoin){.sep=str8_lit(",")}); lnk_error_obj(LNK_Error_IllExport, obj, "invalid export directive \"/EXPORT:%S\"", d); goto exit; } flags = directive; str8_list_pop_front(&flags); } // discard alias to itself if (str8_match(name, alias, 0)) { alias = str8_zero(); } // does directive have ordinal? COFF_ImportByType import_by = COFF_ImportBy_Name; U16 ordinal16 = 0; String8 ordinal = {0}; String8 noname_flag = {0}; if (str8_match(str8_prefix(str8_list_first(&flags), 1), str8_lit("@"), 0)) { // parse ordinal ordinal = str8_skip(str8_list_pop_front(&flags)->string, 1); if (str8_is_integer(ordinal, 10)) { U64 ordinal64 = u64_from_str8(ordinal, 10); if (ordinal64 <= max_U16) { ordinal16 = (U16)ordinal64; import_by = COFF_ImportBy_Ordinal; } else { String8 d = str8_list_join(scratch.arena, &directive, &(StringJoin){.sep=str8_lit(",")}); lnk_error_obj(LNK_Error_IllExport, obj, "ordinal value must fit into 16-bit integer, \"/EXPORT:%S\"", d); goto exit; } } else { String8 d = str8_list_join(scratch.arena, &directive, &(StringJoin){.sep=str8_lit(",")}); lnk_error_obj(LNK_Error_IllExport, obj, "invalid export directive \"/EXPORT:%S\"", d); goto exit; } // detect NONAME flag if (str8_match(str8_list_first(&flags), str8_lit("NONAME"), StringMatchFlag_CaseInsensitive)) { noname_flag = str8_list_pop_front(&flags)->string; } } // detect PRIVATE flag String8 private_flag = {0}; if (str8_match(str8_list_first(&flags), str8_lit("PRIVATE"), StringMatchFlag_CaseInsensitive)) { private_flag = str8_list_pop_front(&flags)->string; } // parse export type COFF_ImportType type = COFF_ImportHeader_Code; if (flags.node_count) { type = coff_import_header_type_from_string(str8_list_pop_front(&flags)->string); if (type == COFF_ImportType_Invalid) { String8 d = str8_list_join(scratch.arena, &directive, &(StringJoin){.sep=str8_lit(",")}); lnk_error_obj(LNK_Error_IllExport, obj, "invalid export directive \"/EXPORT:%S\"", d); goto exit; } } // are there leftover nodes? if (flags.node_count != 0) { String8 d = str8_list_join(scratch.arena, &directive, &(StringJoin){.sep=str8_lit(",")}); lnk_error_obj(LNK_Error_IllExport, obj, "invalid export directive \"/EXPORT:%S\"", d); goto exit; } // fill out export export_out->obj_path = obj ? obj->path : str8_zero(); export_out->lib_path = lnk_obj_get_lib_path(obj); export_out->name = push_str8_copy(arena, name); export_out->alias = push_str8_copy(arena, alias); export_out->type = type; export_out->import_by = import_by; export_out->ordinal = ordinal16; export_out->is_ordinal_assigned = ordinal.size > 0; export_out->is_noname_present = noname_flag.size > 0; export_out->is_private = private_flag.size > 0; export_out->is_forwarder = str8_find_needle(name, 0, str8_lit("."), 0) < name.size; is_parsed = 1; exit:; scratch_end(scratch); ProfEnd(); return is_parsed; } internal B32 lnk_parse_export_directive(Arena *arena, String8 directive, LNK_Obj *obj, PE_ExportParse *export_out) { Temp scratch = scratch_begin(&arena, 1); String8List split_directive = str8_split_by_string_chars(scratch.arena, directive, str8_lit(","), 0); B32 is_parsed = lnk_parse_export_directive_ex(arena, split_directive, obj, export_out); scratch_end(scratch); return is_parsed; } internal B32 lnk_parse_merge_directive(String8 string, LNK_Obj *obj, LNK_MergeDirective *out) { Temp scratch = scratch_begin(0, 0); B32 is_parse_ok = 0; String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("="), 0); if (list.node_count == 2) { out->src = list.first->string; out->dst = list.last->string; is_parse_ok = 1; } else { lnk_error_cmd_switch(LNK_Warning_InvalidMergeDirectiveFormat, obj, LNK_CmdSwitch_Merge, "unable to parse merge directive, expected format \"/MERGE:FROM=TO\" but got \"%S\"", string); } scratch_end(scratch); return is_parse_ok; } internal LNK_AltNameNode * lnk_alt_name_list_push(Arena *arena, LNK_AltNameList *list, LNK_AltName v) { LNK_AltNameNode *node = push_array(arena, LNK_AltNameNode, 1); node->v = v; SLLQueuePush(list->first, list->last, node); list->count += 1; return node; } internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective v) { LNK_MergeDirectiveNode *node = push_array_no_zero(arena, LNK_MergeDirectiveNode, 1); node->v = v; SLLQueuePush(list->first, list->last, node); list->count += 1; return node; } internal String8 lnk_get_image_name(LNK_Config *config) { String8 image_name = config->image_name; image_name = str8_skip_last_slash(image_name); image_name = str8_chop_last_dot(image_name); return image_name; } internal U64 lnk_get_default_function_pad_min(COFF_MachineType machine) { U64 function_pad_min = 0; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: { function_pad_min = 5; } break; case COFF_MachineType_X64: { function_pad_min = 6; } break; default: { lnk_error_cmd_switch(LNK_Error_Cmdl, 0, LNK_CmdSwitch_FunctionPadMin, "default paramter is not defined for: %S", coff_string_from_machine_type(machine)); } break; } return function_pad_min; } internal U64 lnk_get_base_addr(LNK_Config *config) { U64 base_addr = config->user_base_addr; if (base_addr == 0) { if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { base_addr = coff_default_dll_base_from_machine(config->machine); } else if (config->file_characteristics & PE_ImageFileCharacteristic_EXE) { if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && config->machine == COFF_MachineType_X64) { base_addr = coff_default_exe_base_from_machine(COFF_MachineType_X86); } else { base_addr = coff_default_exe_base_from_machine(config->machine); } } else { lnk_error(LNK_Error_Cmdl, "image type is not specified."); } } return base_addr; } internal Version lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine) { Version ver = make_version(0,0); switch (subsystem) { case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break; case PE_WindowsSubsystem_WINDOWS_CUI: { switch (machine) { case COFF_MachineType_X64: case COFF_MachineType_X86: ver = make_version(6,0); break; case COFF_MachineType_ArmNt: case COFF_MachineType_Arm64: case COFF_MachineType_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } } break; case PE_WindowsSubsystem_WINDOWS_GUI: { switch (machine) { case COFF_MachineType_X64: case COFF_MachineType_X86: ver = make_version(6,0); break; case COFF_MachineType_ArmNt: case COFF_MachineType_Arm64: case COFF_MachineType_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } } break; case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(19,90); break; case PE_WindowsSubsystem_EFI_APPLICATION: case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: case PE_WindowsSubsystem_EFI_ROM: case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break; case PE_WindowsSubsystem_NATIVE_WINDOWS: case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break; default: lnk_not_implemented("unknown subsystem kind %u", subsystem); break; } return ver; } internal Version lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine) { Version ver = make_version(0,0); switch (subsystem) { case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: ver = make_version(1,0); break; case PE_WindowsSubsystem_WINDOWS_CUI: { switch (machine) { case COFF_MachineType_X86: ver = make_version(5,1); break; case COFF_MachineType_X64: ver = make_version(5,2); break; case COFF_MachineType_ArmNt: case COFF_MachineType_Arm64: case COFF_MachineType_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } } break; case PE_WindowsSubsystem_WINDOWS_GUI: { switch (machine) { case COFF_MachineType_X86: ver = make_version(5,1); break; case COFF_MachineType_X64: ver = make_version(5,2); break; case COFF_MachineType_ArmNt: case COFF_MachineType_Arm64: case COFF_MachineType_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } } break; case PE_WindowsSubsystem_POSIX_CUI: ver = make_version(1,0); break; case PE_WindowsSubsystem_EFI_APPLICATION: case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: case PE_WindowsSubsystem_EFI_ROM: case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: ver = make_version(1,0); break; case PE_WindowsSubsystem_NATIVE_WINDOWS: case PE_WindowsSubsystem_NATIVE: lnk_not_implemented("detect -drive=WDM switch"); break; default: lnk_not_implemented("unknown subsystem kind %u", subsystem); } return ver; } internal B32 lnk_do_debug_info(LNK_Config *config) { B32 do_debug_info = config->rad_debug == LNK_SwitchState_Yes || (config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null); return do_debug_info; } internal B32 lnk_is_thread_pool_shared(LNK_Config *config) { return config->shared_thread_pool_name.size > 0; } internal B32 lnk_is_section_removed(LNK_Config *config, String8 section_name) { B32 is_removed = 0; for (String8Node *name_n = config->remove_sections.first; name_n != 0 && !is_removed; name_n = name_n->next) { is_removed = str8_match(section_name, name_n->string, 0); } return is_removed; } internal B32 lnk_is_dll_delay_load(LNK_Config *config, String8 dll_name) { return hash_table_search_path_u64(config->delay_load_ht, dll_name, 0); } internal String8 lnk_get_lib_name(String8 path) { static String8 LIB_EXT = str8_lit_comp(".LIB"); // strip path String8 name = str8_skip_last_slash(path); // strip extension String8 name_ext = str8_postfix(name, LIB_EXT.size); if (str8_match(name_ext, LIB_EXT, StringMatchFlag_CaseInsensitive)) { name = str8_chop(name, LIB_EXT.size); } return name; } internal void lnk_push_disallow_lib(LNK_Config *config, String8 path) { String8 lib_name = lnk_get_lib_name(path); hash_table_push_path_u64(config->arena, config->disallow_lib_ht, lib_name, 0); } internal B32 lnk_is_lib_disallowed(LNK_Config *config, String8 path) { String8 lib_name = lnk_get_lib_name(path); return hash_table_search_path(config->disallow_lib_ht, lib_name) != 0; } internal void lnk_include_symbol(LNK_Config *config, String8 name, LNK_Obj *obj) { // is this a duplicate symbol? if (hash_table_search_string_raw(config->include_symbol_ht, name)) { return; } name = push_str8_copy(config->arena, name); LNK_IncludeSymbolNode *node = push_array(config->arena, LNK_IncludeSymbolNode, 1); node->v.name = name; node->v.obj = obj; SLLQueuePush(config->include_symbol_list.first, config->include_symbol_list.last, node); config->include_symbol_list.count += 1; hash_table_push_string_raw(config->arena, config->include_symbol_ht, name, node); } internal void lnk_print_build_info() { fprintf(stdout, " Compiler: %s\n", COMPILER_STRING); fprintf(stdout, " Mode : %s\n", BUILD_MODE_STRING); fprintf(stdout, " Date : %s %s\n", __TIME__, __DATE__); fprintf(stdout, " Version : %s\n", BUILD_VERSION_STRING_LITERAL); } internal void lnk_print_help(void) { Temp scratch = scratch_begin(0,0); fprintf(stdout, "--- Help -------------------------------------------------------\n"); fprintf(stdout, " %s\n", BUILD_TITLE_STRING_LITERAL); fprintf(stdout, "\n"); fprintf(stdout, " Usage: radlink.exe [Options] [Files] [@rsp]\n"); fprintf(stdout, "\n"); fprintf(stdout, " Options:\n"); for (U64 i = 0; i < ArrayCount(g_cmd_switch_map); ++i) { Temp temp = temp_begin(scratch.arena); char *name = g_cmd_switch_map[i].name; char *args = g_cmd_switch_map[i].args; char *desc = g_cmd_switch_map[i].desc; LNK_CmdSwitchType type = g_cmd_switch_map[i].type; if (strcmp(name, "") == 0 || strcmp(name, "NOT_IMPLEMENTED") == 0 || type == LNK_CmdSwitch_Help) { continue; } String8 name_args = push_str8f(temp.arena, "%s%s", name, args); fprintf(stdout, " /%-32.*s %s%s\n", str8_varg(name_args), desc, type == LNK_CmdSwitch_NotImplemented ? "Not Implemented" : ""); temp_end(temp); } fprintf(stdout, "\n"); scratch_end(scratch); } internal String8 lnk_expand_env_vars_windows(Arena *arena, HashTable *env_vars, String8 string) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for (U64 i = 0; i < string.size; ) { U64 open = str8_find_needle(string, i, str8_lit("%"), 0); U64 close = str8_find_needle(string, open+1, str8_lit("%"), 0); String8 text = str8_substr(string, rng_1u64(i, open)); str8_list_push(scratch.arena, &list, text); i += text.size; if (open < close) { String8 env_var_name = str8_substr(string, rng_1u64(open+1, close)); BucketNode *match = hash_table_search_path(env_vars, env_var_name); if (match) { str8_list_push(scratch.arena, &list, match->v.value_string); i = close+1; } else { str8_list_pushf(scratch.arena, &list, "%%%S", env_var_name); i = close; } } } String8 result = str8_list_join(arena, &list, 0); scratch_end(scratch); return result; } internal String8List lnk_unwrap_rsp(Arena *arena, String8List arg_list) { Temp scratch = scratch_begin(&arena, 1); String8List result = {0}; for (String8Node *curr = arg_list.first; curr != 0; curr = curr->next) { B32 is_rsp = str8_match_lit("@", curr->string, StringMatchFlag_RightSideSloppy); if (is_rsp) { // remove "@" String8 name = str8_skip(curr->string, 1); if (os_file_path_exists(name)) { // read rsp from disk String8 file = lnk_read_data_from_file_path(scratch.arena, 0, name); // parse rsp String8List rsp_args = lnk_arg_list_parse_windows_rules(scratch.arena, file); // handle case where rsp references another rsp String8List list = lnk_unwrap_rsp(arena, rsp_args); // push arguments from rsp list = str8_list_copy(arena, &list); str8_list_concat_in_place(&result, &list); } else { lnk_error(LNK_Error_Cmdl, "unable to find rsp: %S", name); } } else { // push regular argument String8 str = push_str8_copy(arena, curr->string); str8_list_push(arena, &result, str); } } scratch_end(scratch); return result; } internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List value_strings, LNK_Obj *obj) { Temp scratch = scratch_begin(&config->arena, 1); LNK_CmdSwitchType cmd_switch = lnk_cmd_switch_type_from_string(cmd_name); switch (cmd_switch) { case LNK_CmdSwitch_Null: { String8 value = str8_list_join(scratch.arena, &value_strings, &(StringJoin){.sep=str8_lit_comp(",")}); lnk_error_obj(LNK_Warning_UnknownSwitch, obj, "unknown switch: \"/%S%s%S\"", cmd_name, value.size ? ":" : "", value); } break; default: break; case LNK_CmdSwitch_NotImplemented: { String8 value = str8_list_join(scratch.arena, &value_strings, &(StringJoin){.sep=str8_lit_comp(",")}); lnk_not_implemented("switch \"%S\" is not implemented \"%S\"", cmd_name, value); } break; case LNK_CmdSwitch_Align: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->sect_align, LNK_ParseU64Flag_CheckPow2); } break; case LNK_CmdSwitch_AllowBind: { lnk_cmd_switch_set_flag_inv_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_NO_BIND); } break; case LNK_CmdSwitch_AllowIsolation: { lnk_cmd_switch_set_flag_inv_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_NO_ISOLATION); } break; case LNK_CmdSwitch_AlternateName: { if (value_strings.node_count == 1) { LNK_AltName alt_name; if (lnk_parse_alt_name_directive(value_strings.first->string, obj, &alt_name)) { String8 to_extant = {0}; if (hash_table_search_string_string(config->alt_name_ht, alt_name.from, &to_extant)) { if (str8_match(to_extant, alt_name.to, 0)) { // ignore, duplicate } else { lnk_error_obj(LNK_Error_AlternateNameConflict, obj, "conflicting alternative name: existing '%S=%S' vs. new '%S=%S'", alt_name.from, to_extant, alt_name.from, alt_name.to); } } else { alt_name.from = push_str8_copy(config->arena, alt_name.from); alt_name.to = push_str8_copy(config->arena, alt_name.to); lnk_alt_name_list_push(config->arena, &config->alt_name_list, alt_name); hash_table_push_string_string(config->arena, config->alt_name_ht, alt_name.from, alt_name.to); } } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_AppContainer: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_APPCONTAINER); } break; case LNK_CmdSwitch_Base: { if (value_strings.node_count == 2) { String8Node *first_node = value_strings.first; //String8Node *second_node = first_node->next; B32 is_response_file = str8_match_lit("@", first_node->string, StringMatchFlag_RightSideSloppy); if (is_response_file) { //String8 file_path = first_node->string; //String8 tag = second_node->string; lnk_not_implemented("Response files are not implemented for /BASE"); } else { Rng1U64 addr_size = {0}; if (lnk_cmd_switch_parse_tuple(obj, cmd_switch, value_strings, &addr_size)) { config->user_base_addr = addr_size.v[0]; config->max_image_size = addr_size.v[1]; } } } else if (value_strings.node_count == 1) { U64 addr; if (lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &addr, 0)) { config->user_base_addr = addr; } } else if (value_strings.node_count == 0) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "expected at least 1 parameter"); } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "too many parameters"); } } break; case LNK_CmdSwitch_Brepro: { // not supported -- ignore } break; case LNK_CmdSwitch_Debug: { if (value_strings.node_count == 0) { config->debug_mode = LNK_DebugMode_Full; } else if (value_strings.node_count == 1) { LNK_DebugMode debug_mode = lnk_debug_mode_from_string(value_strings.first->string); if (debug_mode == LNK_DebugMode_GHash) { config->debug_mode = LNK_DebugMode_Full; lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "GHASH is not supported, switching to FULL"); } else if (debug_mode == LNK_DebugMode_FastLink) { config->debug_mode = LNK_DebugMode_Full; lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "FASTLINK is not supported, switching to FULL"); } else if (debug_mode != LNK_DebugMode_Null) { config->debug_mode = debug_mode; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid parameter \"%S\"", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_DefaultLib: { String8List default_lib_list = str8_list_copy(config->arena, &value_strings); if (obj) { str8_list_concat_in_place(&config->input_obj_lib_list, &default_lib_list); } else { str8_list_concat_in_place(&config->input_default_lib_list, &default_lib_list); } } break; case LNK_CmdSwitch_Delay: { if (value_strings.node_count == 0 || value_strings.node_count > 1) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } else { String8 value = value_strings.first->string; if (str8_match_lit("unload", value, StringMatchFlag_CaseInsensitive)) { config->import_table_emit_uiat = 1; } else if (str8_match_lit("nobind", value, StringMatchFlag_CaseInsensitive)) { config->import_table_emit_biat = 0; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown parameter \"%S\"", value); } } } break; case LNK_CmdSwitch_DelayLoad: { for (String8Node *name_n = value_strings.first; name_n != 0; name_n = name_n->next) { if (hash_table_search_path_u64(config->delay_load_ht, name_n->string, 0)) { continue; } String8 name = push_str8_copy(config->arena, name_n->string); hash_table_push_path_u64(config->arena, config->delay_load_ht, name, 0); str8_list_push(config->arena, &config->delay_load_dll_list, name); } } break; case LNK_CmdSwitch_Dll: { config->file_characteristics |= PE_ImageFileCharacteristic_FILE_DLL; } break; case LNK_CmdSwitch_DynamicBase: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_DYNAMIC_BASE); } break; case LNK_CmdSwitch_Dump: { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unsupported switch; binary dump is done by passing /DUMP to link.exe"); } break; case LNK_CmdSwitch_D2: { // not supported -- ignore } break; case LNK_CmdSwitch_Entry: { String8 new_entry_point_name = {0}; lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &new_entry_point_name); if (config->entry_point_name.size) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "unable to redefine entry point \"%S\" to \"%S\"", config->entry_point_name, new_entry_point_name); break; } config->entry_point_name = new_entry_point_name; } break; case LNK_CmdSwitch_ErrorReport: { // not supported -- ignore } break; case LNK_CmdSwitch_Export: { PE_ExportParse export_parse = {0}; if (lnk_parse_export_directive_ex(config->arena, value_strings, obj, &export_parse)) { String8 export_name = pe_name_from_export_parse(&export_parse); PE_ExportParseNode *exp_n = hash_table_search_string_raw(config->export_ht, export_name); if (exp_n == 0) { // make sure export is defined if (!export_parse.is_forwarder) { lnk_include_symbol(config, export_parse.name, 0); } // push new export exp_n = pe_export_parse_list_push(config->arena, &config->export_symbol_list, export_parse); hash_table_push_string_raw(config->arena, config->export_ht, export_name, exp_n); } else { B32 is_ambiguous = 1; PE_ExportParse *extant_export = &exp_n->data; if (extant_export->alias.size && export_parse.alias.size && !str8_match(extant_export->alias, export_parse.alias, 0)) { goto report; } if (extant_export->ordinal != export_parse.ordinal) { goto report; } is_ambiguous = 0; if (extant_export->alias.size == 0 && export_parse.alias.size != 0) { extant_export->alias = export_parse.alias; } report:; if (is_ambiguous) { lnk_error_obj(LNK_Error_IllExport, obj, "ambiguous symbol export %S", export_parse.name); } } } } break; case LNK_CmdSwitch_FastFail: { // do nothing } break; case LNK_CmdSwitch_FileAlign: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->file_align, LNK_ParseU64Flag_CheckPow2); } break; case LNK_CmdSwitch_Fixed: { lnk_cmd_switch_set_flag_64(obj, cmd_switch, value_strings, &config->flags, LNK_ConfigFlag_Fixed); } break; case LNK_CmdSwitch_FunctionPadMin: { if (value_strings.node_count == 0) { config->function_pad_min = 0; config->infer_function_pad_min = 1; } else { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->function_pad_min, LNK_ParseU64Flag_CheckUnder32bit); } config->do_function_pad_min = LNK_SwitchState_Yes; } break; case LNK_CmdSwitch_Heap: { Rng1U64 reserve_commit; reserve_commit.v[0] = config->heap_reserve; reserve_commit.v[1] = config->heap_commit; if (lnk_cmd_switch_parse_tuple(obj, cmd_switch, value_strings, &reserve_commit)) { if (reserve_commit.v[0] >= reserve_commit.v[1]) { U64 reserve_aligned = AlignPow2(reserve_commit.v[0], 4); U64 commit_aligned = AlignPow2(reserve_commit.v[1], 4); #if 0 if (reserve_aligned != reserve_commit.v[0]) { lnk_error_cmd_switch(LNK_WARNING_CMDL, obj, cmd_switch, "reserve is not power of two, aligned to %u bytes", reserve_aligned); } if (commit_aligned != reserve_commit.v[1]) { lnk_error_cmd_switch(LNK_WARNING_CMDL, obj, cmd_switch, "commit is not power of two, aligned to %u bytes", commit_aligned); } #endif config->heap_reserve = reserve_aligned; config->heap_commit = commit_aligned; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "commit(%llu) is greater than reserve(%llu)", reserve_commit.v[1], reserve_commit.v[0]); } } } break; case LNK_CmdSwitch_HighEntropyVa: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_HIGH_ENTROPY_VA); } break; case LNK_CmdSwitch_Ignore: { U64 error_code; if (lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &error_code, 0)) { switch (error_code) { case LNK_MsWarningCode_UnsuedDelayLoadDll: { lnk_suppress_error(LNK_Warning_UnusedDelayLoadDll); } break; case LNK_MsWarningCode_MissingExternalTypeServer: { lnk_suppress_error(LNK_Warning_MissingExternalTypeServer); } break; case LNK_MsWarningCode_SectionFlagsConflict: { lnk_suppress_error(LNK_Warning_SectionFlagsConflict); } break; default: { lnk_not_implemented("TODO: /IGNORE:%llu", error_code); } break; } } } break; case LNK_CmdSwitch_ImpLib: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->imp_lib_name); } break; case LNK_CmdSwitch_Include: { for (String8Node *value_n = value_strings.first; value_n != 0; value_n = value_n->next) { lnk_include_symbol(config, value_n->string, obj); } } break; case LNK_CmdSwitch_Incremental: { LNK_SwitchState state; if (lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &state)) { if (state == LNK_SwitchState_Yes) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "incremental linkage is not supported"); } } } break; case LNK_CmdSwitch_LargeAddressAware: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE); } break; case LNK_CmdSwitch_Lib: { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unsupported switch; static library is created by passing /LIB to link.exe"); } break; case LNK_CmdSwitch_LibPath: { String8List lib_dir_list = str8_list_copy(config->arena, &value_strings); for (String8Node *dir_n = lib_dir_list.first; dir_n != 0; dir_n = dir_n->next) { if (!os_folder_path_exists(dir_n->string)) { String8 full_path = os_full_path_from_path(scratch.arena, dir_n->string); lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "path doesn't exist %S", full_path); } } str8_list_concat_in_place(&config->lib_dir_list, &lib_dir_list); } break; case LNK_CmdSwitch_Machine: { if (value_strings.node_count == 1) { COFF_MachineType machine = coff_machine_from_string(value_strings.first->string); if (machine != COFF_MachineType_Unknown) { config->machine = machine; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown parameter \"%S\"", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_Manifest: { if (value_strings.node_count == 1) { String8List param_list = str8_split_by_string_chars(scratch.arena, value_strings.first->string, str8_lit(","), 0); String8Array param_arr = str8_array_from_list(scratch.arena, ¶m_list); if (param_arr.count > 0) { if (str8_match_lit("embed", param_arr.v[0], StringMatchFlag_CaseInsensitive)) { config->manifest_opt = LNK_ManifestOpt_Embed; if (param_arr.count == 1) { config->manifest_resource_id = 0; } else if (param_arr.count > 1) { // parse resource id if (str8_match_lit("id=", param_arr.v[1], StringMatchFlag_RightSideSloppy|StringMatchFlag_CaseInsensitive)) { String8List res_id_list = str8_split_by_string_chars(scratch.arena, param_arr.v[1], str8_lit("="), 0); String8Array res_id_arr = str8_array_from_list(scratch.arena, &res_id_list); if (res_id_arr.count == 2) { U64 resource_id; if (try_u64_from_str8_c_rules(res_id_arr.v[1], &resource_id)) { config->manifest_resource_id = push_u64(config->arena, resource_id); } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse resource_id \"%S\"", res_id_arr.v[1]); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid syntax expected form ID=# but got \"%S\"", param_arr.v[1]); } } else { lnk_error_cmd_switch_invalid_param(LNK_Error_Cmdl, obj, cmd_switch, param_arr.v[0]); } } else { lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch); } } else if (str8_match_lit("no", param_arr.v[0], StringMatchFlag_CaseInsensitive)) { config->manifest_opt = LNK_ManifestOpt_No; } else { lnk_error_cmd_switch_invalid_param(LNK_Error_Cmdl, obj, cmd_switch, param_arr.v[0]); } } else { lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch); } } else if (value_strings.node_count == 0) { config->manifest_opt = LNK_ManifestOpt_WriteToFile; } else { lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch); } } break; case LNK_CmdSwitch_ManifestDependency: { String8List manifest_dependency_list = str8_list_copy(config->arena, &value_strings); str8_list_concat_in_place(&config->manifest_dependency_list, &manifest_dependency_list); if (config->manifest_opt == LNK_ManifestOpt_Null) { config->manifest_opt = LNK_ManifestOpt_WriteToFile; } } break; case LNK_CmdSwitch_ManifestFile: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->manifest_name); } break; case LNK_CmdSwitch_ManifestInput: { // see :manifest_input } break; case LNK_CmdSwitch_ManifestUac: { if (value_strings.node_count == 1) { String8 uac = lnk_error_check_and_strip_quotes(LNK_Error_Cmdl, obj, cmd_switch, value_strings.first->string); String8List param_list = str8_split_by_string_chars(scratch.arena, uac, str8_lit(" "), 0); String8Array param_arr = str8_array_from_list(scratch.arena, ¶m_list); if (param_arr.count > 0) { if (str8_match_lit("level=", param_arr.v[0], StringMatchFlag_RightSideSloppy|StringMatchFlag_CaseInsensitive)) { String8 level_param = param_arr.v[0]; String8List level_list = str8_split_by_string_chars(scratch.arena, level_param, str8_lit("="), 0); if (level_list.node_count == 2) { if (str8_match_lit("level", level_list.first->string, StringMatchFlag_CaseInsensitive)) { String8 level = level_list.last->string; if (str8_match_lit("'asInvoker'", level, 0) || str8_match_lit("'highestAvailable'", level, 0) || str8_match_lit("'requireAdministrator'", level, 0)) { // manifest level was parsed! config->manifest_uac = 1; config->manifest_level = push_str8_copy(config->arena, level); if (param_arr.count > 1) { String8 ui_access_param = param_arr.v[1]; String8List ui_access_list = str8_split_by_string_chars(scratch.arena, ui_access_param, str8_lit("="), 0); if (ui_access_list.node_count == 2) { String8 ui_access = ui_access_list.last->string; if (str8_match_lit("'true'", ui_access, 0) || str8_match_lit("'false'", ui_access, 0)) { // ui access was parsed! config->manifest_ui_access = push_str8_copy(config->arena, ui_access); } else { lnk_error_invalid_uac_ui_access_param(LNK_Error_Cmdl, obj, cmd_switch, ui_access_param); } } else { lnk_error_invalid_uac_ui_access_param(LNK_Error_Cmdl, obj, cmd_switch, ui_access_param); } } } else { lnk_error_invalid_uac_level_param(LNK_Error_Cmdl, obj, cmd_switch, level_param); } } else { lnk_error_invalid_uac_level_param(LNK_Error_Cmdl, obj, cmd_switch, level_param); } } else { lnk_error_invalid_uac_level_param(LNK_Error_Cmdl, obj, cmd_switch, level_param); } } else if (str8_match_lit("no", param_arr.v[0], StringMatchFlag_CaseInsensitive)) { config->manifest_uac = 0; } else { lnk_error_cmd_switch_invalid_param(LNK_Error_Cmdl, obj, cmd_switch, param_arr.v[0]); } } else { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "empty param string"); } } else { lnk_error_cmd_switch_invalid_param_count(LNK_Error_Cmdl, obj, cmd_switch); } } break; case LNK_CmdSwitch_Merge: { if (value_strings.node_count == 1) { LNK_MergeDirective merge = {0}; if (lnk_parse_merge_directive(value_strings.first->string, obj, &merge)) { merge.src = push_str8_copy(config->arena, merge.src); merge.dst = push_str8_copy(config->arena, merge.dst); lnk_merge_directive_list_push(config->arena, &config->merge_list, merge); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters %d", value_strings.node_count); } } break; case LNK_CmdSwitch_Natvis: { // warn about invalid natvis extension for (String8Node *node = value_strings.first; node != 0; node = node->next) { String8 ext = str8_skip_last_dot(node->string); if (!str8_match_lit("natvis", ext, StringMatchFlag_CaseInsensitive)) { lnk_error_cmd_switch(LNK_Warning_InvalidNatvisFileExt, obj, cmd_switch, "Visual Studio expects .natvis extension: \"%S\"", node->string); } } String8List natvis_list = str8_list_copy(config->arena, &value_strings); str8_list_concat_in_place(&config->natvis_list, &natvis_list); } break; case LNK_CmdSwitch_DisallowLib: case LNK_CmdSwitch_NoDefaultLib: { if (value_strings.node_count == 0) { config->no_default_libs = 1; } else { for (String8Node *lib_n = value_strings.first; lib_n != 0; lib_n = lib_n->next) { String8 lib_name = lnk_get_lib_name(lib_n->string); if (hash_table_search_path_raw(config->disallow_lib_ht, lib_name)) { continue; } hash_table_push_path_raw(config->arena, config->disallow_lib_ht, lib_name, 0); } } } break; case LNK_CmdSwitch_NoExp: { config->build_exp = 0; } break; case LNK_CmdSwitch_NoImpLib: { config->build_imp_lib = 0; } break; case LNK_CmdSwitch_NoLogo: { // we don't print logo } break; case LNK_CmdSwitch_NxCompat: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_NX_COMPAT); } break; case LNK_CmdSwitch_Opt: { for (String8Node *n = value_strings.first; n != 0; n = n->next) { String8 param = n->string; if (str8_match_lit("ref", param, StringMatchFlag_CaseInsensitive)) { config->opt_ref = LNK_SwitchState_Yes; } else if (str8_match_lit("noref", param, StringMatchFlag_CaseInsensitive)) { config->opt_ref = LNK_SwitchState_No; } else if (str8_match_lit("icf", param, StringMatchFlag_CaseInsensitive) || str8_match_lit("icf=", param, StringMatchFlag_CaseInsensitive | StringMatchFlag_RightSideSloppy)) { String8List vals = str8_split_by_string_chars(scratch.arena, param, str8_lit("="), 0); if (vals.node_count > 2) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "too many parameters for iteration"); continue; } if (vals.node_count == 2) { B32 is_parsed = try_u64_from_str8_c_rules(vals.last->string, &config->opt_iter_count); if (!is_parsed) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse iterations \"%S\"", vals.last->string); continue; } } config->opt_icf = LNK_SwitchState_Yes; } else if (str8_match_lit("noicf", param, StringMatchFlag_CaseInsensitive)) { config->opt_icf = LNK_SwitchState_No; } else if (str8_match_lit("lbr", param, StringMatchFlag_CaseInsensitive)) { config->opt_lbr = LNK_SwitchState_Yes; } else if (str8_match_lit("nolibr", param, StringMatchFlag_CaseInsensitive)) { config->opt_lbr = LNK_SwitchState_No; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown option \"%S\"", param); } } } break; case LNK_CmdSwitch_Out: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->image_name); } break; case LNK_CmdSwitch_Pdb: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_name); } break; case LNK_CmdSwitch_PdbAltPath: { // see :PdbAltPath lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_alt_path); } break; case LNK_CmdSwitch_PdbPageSize: { U64 page_size; if (lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &page_size, LNK_ParseU64Flag_CheckPow2)) { if (page_size >= MSF_MIN_PAGE_SIZE) { if (page_size < MSF_MAX_PAGE_SIZE) { config->pdb_page_size = page_size; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "page size must be <= %u bytes", MSF_MAX_PAGE_SIZE); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "page size must be >= %u bytes", MSF_MIN_PAGE_SIZE); } } } break; case LNK_CmdSwitch_Release: { if (value_strings.node_count == 0) { config->flags |= LNK_ConfigFlag_WriteImageChecksum; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_Stack: { Rng1U64 reserve_commit; reserve_commit.v[0] = config->stack_reserve; reserve_commit.v[1] = config->stack_commit; if (lnk_cmd_switch_parse_tuple(obj, cmd_switch, value_strings, &reserve_commit)) { if (reserve_commit.v[0] >= reserve_commit.v[1]) { U64 reserve_aligned = AlignPow2(reserve_commit.v[0], 4); U64 commit_aligned = AlignPow2(reserve_commit.v[1], 4); #if 0 if (reserve_aligned != reserve_commit.v[0]) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "reserve is not power of two, aligned to %u", reserve_aligned); } if (commit_aligned != reserve_commit.v[1]) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "commit is not power of two, aligned to %u", commit_aligned); } #endif config->stack_reserve = reserve_aligned; config->stack_commit = commit_aligned; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "commit(%llu) is greater than reserve(%llu)", reserve_commit.v[1], reserve_commit.v[0]); } } } break; case LNK_CmdSwitch_SubSystem: { if (value_strings.node_count <= 2 && value_strings.node_count > 0) { // set subsystem type PE_WindowsSubsystem subsystem = pe_subsystem_from_string(value_strings.first->string); if (subsystem != PE_WindowsSubsystem_UNKNOWN) { if (config->subsystem != PE_WindowsSubsystem_UNKNOWN) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "overriding subystem \"%S\" with \"%S\"", pe_string_from_subsystem(config->subsystem), pe_string_from_subsystem(subsystem)); } config->subsystem = subsystem; // parse version (optional) if (value_strings.node_count == 2) { str8_list_pop_front(&value_strings); // pop subsystem parameter lnk_cmd_switch_parse_version(obj, cmd_switch, value_strings, &config->subsystem_ver); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid subsystem \"%S\"", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_Time: { } break; case LNK_CmdSwitch_TsAware: { lnk_cmd_switch_set_flag_inv_64(obj, cmd_switch, value_strings, &config->flags, LNK_ConfigFlag_NoTsAware); } break; case LNK_CmdSwitch_Version: { lnk_cmd_switch_parse_version(obj, cmd_switch, value_strings, &config->image_ver); } break; case LNK_CmdSwitch_Rad_Age: { lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->age, 0); } break; case LNK_CmdSwitch_Rad_AltPchDir: { if (value_strings.node_count == 0) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "missing parameters"); break; } String8List dirs = str8_list_copy(config->arena, &value_strings); str8_list_concat_in_place(&config->alt_pch_dirs, &dirs); } break; case LNK_CmdSwitch_Rad_BuildInfo: { lnk_print_build_info(); os_abort(0); } break; case LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll: { lnk_cmd_switch_set_flag_64(obj, cmd_switch, value_strings, &config->flags, LNK_ConfigFlag_CheckUnusedDelayLoadDll); } break; case LNK_CmdSwitch_Rad_Map: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_chunk_map_name); config->rad_chunk_map = LNK_SwitchState_Yes; } break; case LNK_CmdSwitch_Rad_MapLinesForUnresolvedSymbols: { lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &config->map_lines_for_unresolved_symbols); } break; case LNK_CmdSwitch_Rad_MemoryMapFiles: { lnk_cmd_switch_set_flag_32(obj, cmd_switch, value_strings, &config->io_flags, LNK_IO_Flags_MemoryMapFiles); } break; case LNK_CmdSwitch_Rad_Debug: { lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &config->rad_debug); } break; case LNK_CmdSwitch_Rad_DebugName: { // :Rad_DebugAltPath lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_debug_name); } break; case LNK_CmdSwitch_Rad_DebugAltPath: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->rad_debug_alt_path); } break; case LNK_CmdSwitch_Rad_DelayBind: { lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &config->import_table_emit_biat); } break; case LNK_CmdSwitch_Rad_DoMerge: { lnk_cmd_switch_set_flag_64(obj, cmd_switch, value_strings, &config->flags, LNK_ConfigFlag_Merge); } break; case LNK_CmdSwitch_Rad_EnvLib: { lnk_cmd_switch_set_flag_64(obj, cmd_switch, value_strings, &config->flags, LNK_ConfigFlag_EnvLib); } break; case LNK_CmdSwitch_Rad_Exe: { lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_EXE); } break; case LNK_CmdSwitch_Rad_Guid: { if (value_strings.node_count == 1) { if (str8_match_lit("imageblake3", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { config->guid_type = Lnk_DebugInfoGuid_ImageBlake3; } else if (str8_match_lit("random", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { config->guid = os_make_guid(); } else { Guid guid; if (try_guid_from_string(value_strings.first->string, &guid)) { config->guid = guid; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse \"%S\"", value_strings.first->string); } } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters, expected GUID formatted as following: \"0000000-0000-0000-0000-000000000000\""); } } break; case LNK_CmdSwitch_Rad_LargePages: { if (value_strings.node_count == 0) { OS_ProcessInfo *process_info = os_get_process_info(); if (process_info->large_pages_allowed) { arena_default_flags |= ArenaFlag_LargePages; } else { lnk_error_cmd_switch(LNK_Warning_LargePages, obj, cmd_switch, "Large pages aren't enabled on this system."); #if OS_WINDOWS lnk_supplement_error("To enable large pages:"); lnk_supplement_error("\t- Press Win+R and open \"gpedit.msc\""); lnk_supplement_error("\t- Navigate to Local Computer Policy > Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights And Assignments"); lnk_supplement_error("\t- Double-click on \"Lock pages in memory\""); lnk_supplement_error("\t- Click \"Add User or Group...\""); lnk_supplement_error("\t- Type in your user name"); lnk_supplement_error("\t- Click Oks and reboot the machine"); #endif } } else if (value_strings.node_count == 1) { if (str8_match_lit("quiet", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { OS_ProcessInfo *process_info = os_get_process_info(); if (process_info->large_pages_allowed) { arena_default_flags |= ArenaFlag_LargePages; } } else if (str8_match_lit("no", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { arena_default_flags &= ~ArenaFlag_LargePages; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid parameter: \"%S\", expected NO or QUIET", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_Rad_LinkVer: { lnk_cmd_switch_parse_version(obj, cmd_switch, value_strings, &config->link_ver); } break; case LNK_CmdSwitch_Rad_Log: { if (value_strings.node_count == 1) { if (str8_match_lit("all", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { for (U64 ilog = 0; ilog < LNK_Log_Count; ilog += 1) { lnk_set_log_status((LNK_LogType)ilog, 1); } } else if (str8_match_lit("io", value_strings.first->string, StringMatchFlag_CaseInsensitive)) { lnk_set_log_status(LNK_Log_IO_Read, 1); lnk_set_log_status(LNK_Log_IO_Write, 1); } else { LNK_LogType log_type = lnk_log_type_from_string(value_strings.first->string); if (log_type == LNK_Log_Null) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown parameter \"%S\"", value_strings.first->string); } else { lnk_set_log_status(log_type, 1); } } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters, expected 1"); } } break; case LNK_CmdSwitch_Rad_MtPath: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->mt_path); } break; case LNK_CmdSwitch_Rad_OsVer: { lnk_cmd_switch_parse_version(obj, cmd_switch, value_strings, &config->os_ver); } break; case LNK_CmdSwitch_Rad_PageSize: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->machine_page_size, 0); } break; case LNK_CmdSwitch_Rad_PathStyle: { if (value_strings.node_count == 1) { PathStyle path_style = path_style_from_string(str8_list_first(&value_strings)); if (path_style != PathStyle_Null) { config->path_style = path_style; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unable to parse parameter \"%S\"", value_strings.first->string); } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters"); } } break; case LNK_CmdSwitch_Rad_PdbHashTypeNames: { String8 mode_string = str8_list_first(&value_strings); LNK_TypeNameHashMode mode; if (mode_string.size == 0) { config->pdb_hash_type_names = LNK_TypeNameHashMode_Lenient; } else { mode = lnk_type_name_hash_mode_from_string(mode_string); if (mode == LNK_TypeNameHashMode_Null) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown parameter: \"%S\"", mode_string); } else { config->pdb_hash_type_names = mode; } } } break; case LNK_CmdSwitch_Rad_PdbHashTypeNameMap: { lnk_cmd_switch_parse_string_copy(config->arena, obj, cmd_switch, value_strings, &config->pdb_hash_type_name_map); } break; case LNK_CmdSwitch_Rad_PdbHashTypeNameLength: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->pdb_hash_type_name_length, 0); } break; case LNK_CmdSwitch_Rad_RemoveSection: { String8 sect_name = {0}; if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, §_name)) { sect_name = push_str8_copy(config->arena, sect_name); str8_list_push(config->arena, &config->remove_sections, sect_name); } } break; case LNK_CmdSwitch_Rad_SharedThreadPool: { if (value_strings.node_count == 0) { config->shared_thread_pool_name = str8_lit(LNK_DEFAULT_THREAD_POOL_NAME); } else { lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &config->shared_thread_pool_name); if (config->shared_thread_pool_name.size == 0) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid empty string for thread pool name"); } } } break; case LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers: { OS_SystemInfo *sysinfo = os_get_system_info(); if (value_strings.node_count == 0) { config->max_worker_count = sysinfo->logical_processor_count; } else { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->max_worker_count, 0); if (config->max_worker_count == 0) { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "number of workers must be greater than zero"); } else if (config->max_worker_count > sysinfo->logical_processor_count) { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "number of workers %llu exceeds processor count %llu", config->max_worker_count, sysinfo->logical_processor_count); config->max_worker_count = sysinfo->logical_processor_count; } } } break; case LNK_CmdSwitch_Rad_SuppressError: { U64List error_code_list = {0}; if (lnk_cmd_switch_parse_u64_list(scratch.arena, obj, cmd_switch, value_strings, &error_code_list, 0)) { for (U64Node *error_code_n = error_code_list.first; error_code_n != 0; error_code_n = error_code_n->next) { if (error_code_n->data < LNK_Error_Count) { lnk_suppress_error(error_code_n->data); } else { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "unknown error code %llu", error_code_n->data); } } } } break; case LNK_CmdSwitch_Rad_TargetOs: { if (value_strings.node_count == 1) { String8 os_string = str8_list_first(&value_strings); OperatingSystem target_os = operating_system_from_string(os_string); if (target_os != OperatingSystem_Null) { config->target_os = target_os; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown operating system type %S", os_string); } } else { lnk_error_cmd_switch(LNK_Warning_Cmdl, obj, cmd_switch, "expected 1 parameter"); } } break; case LNK_CmdSwitch_Rad_WriteTempFiles: { lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &config->write_temp_files); } break; case LNK_CmdSwitch_Rad_TimeStamp: { lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->time_stamp, 0); } break; case LNK_CmdSwitch_Rad_UnresolvedSymbolLimit: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->unresolved_symbol_limit, 0); } break; case LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit: { lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &config->unresolved_symbol_ref_limit, 0); } break; case LNK_CmdSwitch_Rad_Version: { fprintf(stdout, "%s\n", BUILD_TITLE_STRING_LITERAL); os_abort(0); } break; case LNK_CmdSwitch_Rad_Workers: { U64 worker_count; if (lnk_cmd_switch_parse_u64(obj, cmd_switch, value_strings, &worker_count, 0)) { config->worker_count = worker_count; } } break; case LNK_CmdSwitch_Help: { lnk_print_help(); os_abort(0); } break; } scratch_end(scratch); } internal LNK_Config * lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); Arena *arena = arena_alloc(); LNK_Config *config = push_array(arena, LNK_Config, 1); config->arena = arena; config->raw_cmd_line = str8_list_copy(arena, &raw_cmd_line); config->work_dir = os_get_current_path(arena); config->build_imp_lib = 1; config->build_exp = 1; config->heap_reserve = MB(1); config->heap_commit = KB(1); config->stack_reserve = MB(1); config->stack_commit = KB(1); config->pdb_hash_type_names = LNK_TypeNameHashMode_None; config->pdb_hash_type_name_length = 8; config->data_dir_count = PE_DataDirectoryIndex_COUNT; config->export_ht = hash_table_init(arena, max_U16/2); config->alt_name_ht = hash_table_init(arena, 0x100); config->include_symbol_ht = hash_table_init(arena, 0x100); config->delay_load_ht = hash_table_init(arena, 0x100); config->disallow_lib_ht = hash_table_init(arena, 0x100); // process command line switches for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) { lnk_apply_cmd_option_to_config(config, cmd->string, cmd->value_strings, 0); } // :manifest_input if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_ManifestInput)) { if (config->manifest_opt == LNK_ManifestOpt_Embed) { for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) { LNK_CmdSwitchType cmd_switch = lnk_cmd_switch_type_from_string(cmd->string); if (cmd_switch == LNK_CmdSwitch_ManifestInput) { String8List manifest_list = str8_list_copy(arena, &cmd->value_strings); str8_list_concat_in_place(&config->input_list[LNK_Input_Manifest], &manifest_list); } } } else { lnk_error_cmd_switch(LNK_Error_Cmdl, 0, LNK_CmdSwitch_ManifestInput, "missing /MANIFEST:EMBED"); } } // set default manifest resource id if (config->manifest_resource_id == 0) { if (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { config->manifest_resource_id = push_u64(arena, 2); } else { config->manifest_resource_id = push_u64(arena, 1); } } // input files for (String8Node *input_node = cmd_line.input_list.first; input_node != 0; input_node = input_node->next) { String8 path = push_str8_copy(arena, input_node->string); String8 ext = str8_skip_last_dot(path); // map file extension to input type LNK_InputType input_type = lnk_input_type_from_string(ext); // do we support this file format? if (input_type == LNK_Input_Null) { lnk_error(LNK_Error_Cmdl, "unknown file format \"%S\"", path); continue; } // psuh file path str8_list_push(arena, &config->input_list[input_type], path); } // os version and subsystem are always same? if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Rad_OsVer)) { config->os_ver = config->subsystem_ver; } // don't emit bind table with /ALLOWBIND:NO if (config->dll_characteristics & PE_DllCharacteristic_NO_BIND) { config->import_table_emit_biat = LNK_SwitchState_No; } // set flags for /OPT { // these flags remove and merge inline functions and methods defined in class, // and makes stepping tougher, in debug mode we don't link with these optimizations // unless user specifically orverrides. if (config->debug_mode != LNK_DebugMode_None) { if (config->opt_ref == LNK_SwitchState_Null) { config->opt_ref = LNK_SwitchState_No; } if (config->opt_icf == LNK_SwitchState_Null) { config->opt_icf = LNK_SwitchState_No; } } // by default enable all optimizations if (config->opt_ref == LNK_SwitchState_Null) { config->opt_ref = LNK_SwitchState_Yes; } if (config->opt_icf == LNK_SwitchState_Null) { config->opt_icf = LNK_SwitchState_Yes; } if (config->opt_lbr == LNK_SwitchState_Null) { config->opt_lbr = LNK_SwitchState_Yes; } } // warn about unused large address aware flag if ((~config->file_characteristics & PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE) && (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL)) { lnk_error(LNK_Warning_NoLargeAddressAwarenessForDll, "/LARGEADDRESSAWARE:NO has no effect when specified together with /DLL"); } // error check base address flags if (config->flags & LNK_ConfigFlag_Fixed) { if (lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_DynamicBase)) { B32 is_dynamic_base_set = !!(config->dll_characteristics & PE_DllCharacteristic_DYNAMIC_BASE); if (is_dynamic_base_set) { lnk_error(LNK_Error_IncomatibleCmdOptions, "unable to link with /FIXED and /DYNAMICBASE at the same time"); } } } if (lnk_is_thread_pool_shared(config)) { if (config->worker_count > config->max_worker_count) { config->worker_count = config->max_worker_count; lnk_error_cmd_switch(LNK_Warning_Cmdl, 0, LNK_CmdSwitch_Rad_Workers, "worker count %llu exceeds thread pool max worker count %llu; claping count to max", config->worker_count, config->max_worker_count); } } // set flags for /FIXED if (config->flags & LNK_ConfigFlag_Fixed) { config->file_characteristics |= PE_ImageFileCharacteristic_STRIPPED; config->dll_characteristics &= ~PE_DllCharacteristic_DYNAMIC_BASE; } // if we don't have a fixed image and dynamic base switch // was omitted we make image with dynamic base else if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_DynamicBase)) { config->dll_characteristics |= PE_DllCharacteristic_DYNAMIC_BASE; } // set flag for /guard if (config->guard_flags != LNK_Guard_None) { config->dll_characteristics |= PE_DllCharacteristic_GUARD_CF; } // handle empty /OUT if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Out)) { String8 name = str8_list_first(&config->input_list[LNK_Input_Obj]); String8 ext = (config->file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) ? str8_lit("dll") : str8_lit("exe"); config->image_name = path_replace_file_extension(scratch.arena, name, ext); } // handle empty /PDB if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Pdb)) { config->pdb_name = path_replace_file_extension(scratch.arena, config->image_name, str8_lit("pdb")); } // handle empty /RAD_DEBUG_NAME if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_Rad_DebugName)) { config->rad_debug_name = path_replace_file_extension(scratch.arena, config->image_name, str8_lit("rdi")); } // handle empty /IMPLIB if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_ImpLib)) { config->imp_lib_name = path_replace_file_extension(scratch.arena, config->image_name, str8_lit("lib")); } // handle empty /MANIFESTFILE if (!lnk_cmd_line_has_switch(cmd_line, LNK_CmdSwitch_ManifestFile)) { config->manifest_name = push_str8f(scratch.arena, "%S.manifest", config->image_name); } // convert to full paths config->image_name = os_full_path_from_path(arena, config->image_name); config->pdb_name = os_full_path_from_path(arena, config->pdb_name); config->rad_debug_name = os_full_path_from_path(arena, config->rad_debug_name); config->imp_lib_name = os_full_path_from_path(arena, config->imp_lib_name); config->manifest_name = os_full_path_from_path(arena, config->manifest_name); // collect env vars HashTable *env_vars = hash_table_init(scratch.arena, 512); { #if OS_WINDOWS OS_ProcessInfo *process_info = os_get_process_info(); for (String8Node *node = process_info->environment.first; node != 0; node = node->next) { String8List list = str8_split_by_string_chars(scratch.arena, node->string, str8_lit("="), 0); String8 key = list.first->string; String8 val = str8_zero(); if (list.node_count == 2) { val = list.last->string; } else if (list.node_count > 2) { U64 sep_idx = str8_find_needle(node->string, node->string.size, str8_lit("="), 0); val = str8_skip(node->string, sep_idx+1); } hash_table_push_path_string(scratch.arena, env_vars, key, val); } #endif } // define linker env vars hash_table_push_path_string(scratch.arena, env_vars, str8_lit("_pdb"), str8_skip_last_slash(config->pdb_name)); hash_table_push_path_string(scratch.arena, env_vars, str8_lit("_ext"), str8_skip_last_dot(config->image_name)); hash_table_push_path_string(scratch.arena, env_vars, str8_lit("_rad_pdb_path"), config->pdb_name); hash_table_push_path_string(scratch.arena, env_vars, str8_lit("_rad_rdi"), str8_skip_last_slash(config->rad_debug_name)); hash_table_push_path_string(scratch.arena, env_vars, str8_lit("_rad_rdi_path"), config->rad_debug_name); // collect LIB and LIBPATH if (config->flags & LNK_ConfigFlag_EnvLib) { BucketNode *lib = hash_table_search_path(env_vars, str8_lit("lib")); if (lib) { String8List val_list = str8_split_by_string_chars(scratch.arena, lib->v.value_string, str8_lit(";"), 0); String8List val_list_copy = str8_list_copy(arena, &val_list); str8_list_concat_in_place(&config->lib_dir_list, &val_list_copy); } BucketNode *lib_path = hash_table_search_path(env_vars, str8_lit("libpath")); if (lib_path) { String8List val_list = str8_split_by_string_chars(scratch.arena, lib->v.value_string, str8_lit(";"), 0); String8List val_list_copy = str8_list_copy(arena, &val_list); str8_list_concat_in_place(&config->lib_dir_list, &val_list_copy); } } // :PdbAltPath config->pdb_alt_path = lnk_expand_env_vars_windows(arena, env_vars, config->pdb_alt_path); // :Rad_DebugAltPath config->rad_debug_alt_path = lnk_expand_env_vars_windows(arena, env_vars, config->rad_debug_alt_path); // create temporary files names if (config->write_temp_files == LNK_SwitchState_Yes) { config->temp_rad_chunk_map_name = push_str8f(arena, "%S.tmp%x", config->rad_chunk_map_name, config->time_stamp); config->temp_image_name = push_str8f(arena, "%S.tmp%x", config->image_name, config->time_stamp); config->temp_pdb_name = push_str8f(arena, "%S.tmp%x", config->pdb_name, config->time_stamp); config->temp_rad_debug_name = push_str8f(arena, "%S.tmp%x", config->rad_debug_name, config->time_stamp); } scratch_end(scratch); ProfEnd(); return config; } ================================================ FILE: src/linker/lnk_config.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #if OS_WINDOWS # define LNK_MANIFEST_MERGE_TOOL_NAME "mt.exe" #elif OS_LINUX || OS_MAC # define LNK_MANIFEST_MERGE_TOOL_NAME "llvm-mt" #else # error #endif #define LNK_DEFAULT_THREAD_POOL_NAME "RADLINK_THREAD_POOL" typedef enum { LNK_ParseU64Flag_CheckUnder32bit = (1 << 0), LNK_ParseU64Flag_CheckPow2 = (1 << 1), } LNK_ParseU64Flags; typedef enum { LNK_SwitchState_Null, LNK_SwitchState_No, LNK_SwitchState_Yes } LNK_SwitchState; typedef enum { LNK_CmdSwitch_Null, LNK_CmdSwitch_NotImplemented, LNK_CmdSwitch_Align, LNK_CmdSwitch_AllowBind, LNK_CmdSwitch_AllowIsolation, LNK_CmdSwitch_AlternateName, LNK_CmdSwitch_AppContainer, LNK_CmdSwitch_Base, LNK_CmdSwitch_Brepro, LNK_CmdSwitch_Debug, LNK_CmdSwitch_DefaultLib, LNK_CmdSwitch_Delay, LNK_CmdSwitch_DelayLoad, LNK_CmdSwitch_Dll, LNK_CmdSwitch_DynamicBase, LNK_CmdSwitch_Dump, LNK_CmdSwitch_D2, LNK_CmdSwitch_Entry, LNK_CmdSwitch_ErrorReport, LNK_CmdSwitch_Export, LNK_CmdSwitch_FastFail, LNK_CmdSwitch_FileAlign, LNK_CmdSwitch_Fixed, LNK_CmdSwitch_FunctionPadMin, LNK_CmdSwitch_Heap, LNK_CmdSwitch_HighEntropyVa, LNK_CmdSwitch_Ignore, LNK_CmdSwitch_ImpLib, LNK_CmdSwitch_Include, LNK_CmdSwitch_Incremental, LNK_CmdSwitch_LargeAddressAware, LNK_CmdSwitch_Lib, LNK_CmdSwitch_LibPath, LNK_CmdSwitch_Machine, LNK_CmdSwitch_Manifest, LNK_CmdSwitch_ManifestDependency, LNK_CmdSwitch_ManifestFile, LNK_CmdSwitch_ManifestInput, LNK_CmdSwitch_ManifestUac, LNK_CmdSwitch_Merge, LNK_CmdSwitch_Natvis, LNK_CmdSwitch_NoDefaultLib, LNK_CmdSwitch_NoExp, LNK_CmdSwitch_NoImpLib, LNK_CmdSwitch_NoLogo, LNK_CmdSwitch_NxCompat, LNK_CmdSwitch_Opt, LNK_CmdSwitch_Out, LNK_CmdSwitch_Pdb, LNK_CmdSwitch_PdbAltPath, LNK_CmdSwitch_PdbPageSize, LNK_CmdSwitch_Stack, LNK_CmdSwitch_SubSystem, LNK_CmdSwitch_Time, LNK_CmdSwitch_TsAware, // -- NOT Implemented: LNK_CmdSwitch_AssemblyDebug, LNK_CmdSwitch_AssemblyLinkResource, LNK_CmdSwitch_AssemblyModule, LNK_CmdSwitch_AssemblyResource, LNK_CmdSwitch_ClrImageType, LNK_CmdSwitch_ClrLoaderOptimization, LNK_CmdSwitch_ClrSupportLastError, LNK_CmdSwitch_ClrThreadAttribute, LNK_CmdSwitch_ClrRunManagedCodeCheck, LNK_CmdSwitch_ClrUnmanagedCheck, LNK_CmdSwitch_Def, LNK_CmdSwitch_DelaySign, LNK_CmdSwitch_DependentLoadFlag, LNK_CmdSwitch_Driver, LNK_CmdSwitch_DisallowLib, LNK_CmdSwitch_EditAndContinue, LNK_CmdSwitch_EmitVolatileMetadata, LNK_CmdSwitch_ExportAdmin, LNK_CmdSwitch_FastGenProfile, LNK_CmdSwitch_FailIfMismatch, LNK_CmdSwitch_Force, LNK_CmdSwitch_Guard, LNK_CmdSwitch_GuardSym, LNK_CmdSwitch_GenProfile, LNK_CmdSwitch_IdlOut, LNK_CmdSwitch_IgnoreIdl, LNK_CmdSwitch_Ilk, LNK_CmdSwitch_IntegrityCheck, LNK_CmdSwitch_InferAsanLibs, LNK_CmdSwitch_InferAsanLibsNo, LNK_CmdSwitch_Kernel, LNK_CmdSwitch_KeyContainer, LNK_CmdSwitch_KeyFile, LNK_CmdSwitch_LinkerRepro, LNK_CmdSwitch_LinkerReproTarget, LNK_CmdSwitch_Ltcg, LNK_CmdSwitch_LtcgOut, LNK_CmdSwitch_Map, LNK_CmdSwitch_MapInfo, LNK_CmdSwitch_Midl, LNK_CmdSwitch_NoAssembly, LNK_CmdSwitch_NoEntry, LNK_CmdSwitch_Order, LNK_CmdSwitch_PdbStripped, LNK_CmdSwitch_Profile, LNK_CmdSwitch_Release, LNK_CmdSwitch_SafeSeh, LNK_CmdSwitch_Section, LNK_CmdSwitch_SourceLink, LNK_CmdSwitch_Stub, LNK_CmdSwitch_SwapRun, LNK_CmdSwitch_TlbId, LNK_CmdSwitch_ThrowingNew, LNK_CmdSwitch_UserProfile, LNK_CmdSwitch_Verbose, LNK_CmdSwitch_Version, LNK_CmdSwitch_Winmd, LNK_CmdSwitch_WinmdDelaySign, LNK_CmdSwitch_WinmdKeyContainer, LNK_CmdSwitch_WinmdKeyFile, LNK_CmdSwitch_WholeArchive, LNK_CmdSwitch_Wx, LNK_CmdSwitch_Rad_Age, LNK_CmdSwitch_Rad_AltPchDir, LNK_CmdSwitch_Rad_BuildInfo, LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, LNK_CmdSwitch_Rad_Debug, LNK_CmdSwitch_Rad_DebugAltPath, LNK_CmdSwitch_Rad_DebugName, LNK_CmdSwitch_Rad_DelayBind, LNK_CmdSwitch_Rad_DoMerge, LNK_CmdSwitch_Rad_EnvLib, LNK_CmdSwitch_Rad_Exe, LNK_CmdSwitch_Rad_Guid, LNK_CmdSwitch_Rad_LargePages, LNK_CmdSwitch_Rad_LinkVer, LNK_CmdSwitch_Rad_Log, LNK_CmdSwitch_Rad_Logo, LNK_CmdSwitch_Rad_Map, LNK_CmdSwitch_Rad_MapLinesForUnresolvedSymbols, LNK_CmdSwitch_Rad_MemoryMapFiles, LNK_CmdSwitch_Rad_MtPath, LNK_CmdSwitch_Rad_OsVer, LNK_CmdSwitch_Rad_PageSize, LNK_CmdSwitch_Rad_PathStyle, LNK_CmdSwitch_Rad_PdbHashTypeNameLength, LNK_CmdSwitch_Rad_PdbHashTypeNameMap, LNK_CmdSwitch_Rad_PdbHashTypeNames, LNK_CmdSwitch_Rad_RemoveSection, LNK_CmdSwitch_Rad_SharedThreadPool, LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, LNK_CmdSwitch_Rad_SuppressError, LNK_CmdSwitch_Rad_TargetOs, LNK_CmdSwitch_Rad_TimeStamp, LNK_CmdSwitch_Rad_UnresolvedSymbolLimit, LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit, LNK_CmdSwitch_Rad_Version, LNK_CmdSwitch_Rad_Workers, LNK_CmdSwitch_Rad_WriteTempFiles, LNK_CmdSwitch_Help, LNK_CmdSwitch_Count } LNK_CmdSwitchType; typedef struct LNK_CmdSwitch { LNK_CmdSwitchType type; B32 is_legal_directive; char *name; char *args; char *desc; } LNK_CmdSwitch; typedef enum { LNK_Input_Null, LNK_Input_Obj, LNK_Input_Lib, LNK_Input_Res, LNK_Input_Manifest, LNK_Input_Count } LNK_InputType; enum { LNK_ConfigFlag_Fixed = (1 << 0), LNK_ConfigFlag_Merge = (1 << 1), LNK_ConfigFlag_EnvLib = (1 << 2), LNK_ConfigFlag_CheckUnusedDelayLoadDll = (1 << 5), LNK_ConfigFlag_NoTsAware = (1 << 6), LNK_ConfigFlag_WriteImageChecksum = (1 << 8), LNK_ConfigFlag_ManifestEmbed = (1 << 9), }; typedef U64 LNK_ConfigFlags; typedef enum { LNK_DebugMode_Null, LNK_DebugMode_None, LNK_DebugMode_FastLink, LNK_DebugMode_GHash, LNK_DebugMode_Full, } LNK_DebugMode; enum { LNK_Guard_None = 0, LNK_Guard_Cf = (1 << 0), LNK_Guard_LongJmp = (1 << 1), LNK_Guard_EhCont = (1 << 2), LNK_Guard_All = LNK_Guard_Cf | LNK_Guard_LongJmp | LNK_Guard_EhCont }; typedef U32 LNK_GuardFlags; typedef enum { LNK_ManifestOpt_Null, LNK_ManifestOpt_WriteToFile, LNK_ManifestOpt_Embed, LNK_ManifestOpt_No, } LNK_ManifestOpt; typedef struct LNK_IncludeSymbol { String8 name; struct LNK_Obj *obj; } LNK_IncludeSymbol; typedef struct LNK_IncludeSymbolNode { struct LNK_IncludeSymbolNode *next; LNK_IncludeSymbol v; } LNK_IncludeSymbolNode; typedef struct LNK_IncludeSymbolList { U64 count; LNK_IncludeSymbolNode *first; LNK_IncludeSymbolNode *last; } LNK_IncludeSymbolList; typedef struct LNK_AltName { String8 from; String8 to; struct LNK_Obj *obj; } LNK_AltName; typedef struct LNK_AltNameNode { struct LNK_AltNameNode *next; LNK_AltName v; } LNK_AltNameNode; typedef struct LNK_AltNameList { U64 count; LNK_AltNameNode *first; LNK_AltNameNode *last; } LNK_AltNameList; typedef struct LNK_MergeDirective { String8 src; String8 dst; } LNK_MergeDirective; typedef struct LNK_MergeDirectiveNode { struct LNK_MergeDirectiveNode *next; LNK_MergeDirective v; } LNK_MergeDirectiveNode; typedef struct LNK_MergeDirectiveList { U64 count; LNK_MergeDirectiveNode *first; LNK_MergeDirectiveNode *last; } LNK_MergeDirectiveList; typedef enum { LNK_DebugInfoGuid_Null, Lnk_DebugInfoGuid_ImageBlake3, } LNK_DebugInfoGuidType; typedef enum { LNK_TypeNameHashMode_Null, LNK_TypeNameHashMode_None, LNK_TypeNameHashMode_Lenient, LNK_TypeNameHashMode_Full, } LNK_TypeNameHashMode; typedef struct LNK_Config { Arena *arena; LNK_ConfigFlags flags; LNK_DebugMode debug_mode; LNK_SwitchState opt_ref; LNK_SwitchState opt_icf; LNK_SwitchState opt_lbr; U64 opt_iter_count; LNK_SwitchState import_table_emit_biat; LNK_SwitchState import_table_emit_uiat; LNK_GuardFlags guard_flags; LNK_DebugInfoGuidType guid_type; Guid guid; COFF_TimeStamp time_stamp; U32 age; U64 file_align; U64 sect_align; U64 stack_reserve; U64 stack_commit; U64 heap_reserve; U64 heap_commit; U64 user_base_addr; U64 max_image_size; U64 machine_page_size; U64 pdb_page_size; U64 worker_count; U64 max_worker_count; String8 shared_thread_pool_name; LNK_SwitchState do_function_pad_min; B32 infer_function_pad_min; U64 function_pad_min; U64 *manifest_resource_id; B32 no_default_libs; Version link_ver; Version os_ver; Version image_ver; OperatingSystem target_os; COFF_MachineType machine; PE_WindowsSubsystem subsystem; Version subsystem_ver; PE_ImageFileCharacteristics file_characteristics; PE_DllCharacteristics dll_characteristics; String8 entry_point_name; String8List lib_dir_list; PathStyle path_style; LNK_ManifestOpt manifest_opt; String8 work_dir; String8 image_name; String8 imp_lib_name; String8List raw_cmd_line; String8 pdb_name; String8 pdb_alt_path; String8 mt_path; LNK_TypeNameHashMode pdb_hash_type_names; String8 pdb_hash_type_name_map; U64 pdb_hash_type_name_length; PE_ExportParseList export_symbol_list; String8List input_list[LNK_Input_Count]; String8List input_obj_lib_list; String8List input_default_lib_list; String8List delay_load_dll_list; String8List natvis_list; String8 manifest_name; B32 manifest_uac; String8 manifest_level; String8 manifest_ui_access; String8List manifest_dependency_list; LNK_SwitchState rad_debug; LNK_SwitchState rad_chunk_map; String8 rad_chunk_map_name; String8 rad_debug_name; String8 rad_debug_alt_path; LNK_IncludeSymbolList include_symbol_list; LNK_AltNameList alt_name_list; LNK_MergeDirectiveList merge_list; U64 data_dir_count; B32 build_imp_lib; B32 build_exp; LNK_SwitchState write_temp_files; String8 temp_image_name; String8 temp_pdb_name; String8 temp_rad_debug_name; String8 temp_rad_chunk_map_name; String8 delay_load_helper_name; String8List remove_sections; LNK_IO_Flags io_flags; HashTable *export_ht; HashTable *alt_name_ht; HashTable *include_symbol_ht; HashTable *delay_load_ht; HashTable *disallow_lib_ht; U64 unresolved_symbol_limit; U64 unresolved_symbol_ref_limit; LNK_SwitchState map_lines_for_unresolved_symbols; String8List alt_pch_dirs; } LNK_Config; // --- MSVC Error Codes -------------------------------------------------------- typedef enum { LNK_MsErrorCode_Lnk1000 = 1000, LNK_MsErrorCode_Lnk1103 = 1103, LNK_MsErrorCode_Lnk1104 = 1104, LNK_MsErrorCode_Lnk1106 = 1106, LNK_MsErrorCode_Lnk1107 = 1107, LNK_MsErrorCode_Lnk1112 = 1112, LNK_MsErrorCode_Lnk1113 = 1113, LNK_MsErrorCode_Lnk1120 = 1120, LNK_MsErrorCode_Lnk1123 = 1123, LNK_MsErrorCode_Lnk1127 = 1127, LNK_MsErrorCode_Lnk1136 = 1136, LNK_MsErrorCode_Lnk1140 = 1140, LNK_MsErrorCode_Lnk1141 = 1141, LNK_MsErrorCode_Lnk1143 = 1143, LNK_MsErrorCode_Lnk1152 = 1152, LNK_MsErrorCode_Lnk1158 = 1158, LNK_MsErrorCode_Lnk1164 = 1164, LNK_MsErrorCode_Lnk1166 = 1166, LNK_MsErrorCode_Lnk1168 = 1168, LNK_MsErrorCode_Lnk1169 = 1169, LNK_MsErrorCode_Lnk1170 = 1170, LNK_MsErrorCode_Lnk1179 = 1179, LNK_MsErrorCode_Lnk1181 = 1181, LNK_MsErrorCode_Lnk1189 = 1189, LNK_MsErrorCode_Lnk1196 = 1196, LNK_MsErrorCode_Lnk1200 = 1200, LNK_MsErrorCode_Lnk1201 = 1201, LNK_MsErrorCode_Lnk1211 = 1211, LNK_MsErrorCode_Lnk1215 = 1215, LNK_MsErrorCode_Lnk1218 = 1218, LNK_MsErrorCode_Lnk1221 = 1221, LNK_MsErrorCode_Lnk1223 = 1223, LNK_MsErrorCode_Lnk1224 = 1224, LNK_MsErrorCode_Lnk1237 = 1237, LNK_MsErrorCode_Lnk1240 = 1240, LNK_MsErrorCode_Lnk1241 = 1241, LNK_MsErrorCode_Lnk1245 = 1245, LNK_MsErrorCode_Lnk1248 = 1248, LNK_MsErrorCode_Lnk1256 = 1256, LNK_MsErrorCode_Lnk1264 = 1264, LNK_MsErrorCode_Lnk1277 = 1277, LNK_MsErrorCode_Lnk1282 = 1282, LNK_MsErrorCode_Lnk1287 = 1287, LNK_MsErrorCode_Lnk1296 = 1296, LNK_MsErrorCode_Lnk1301 = 1301, LNK_MsErrorCode_Lnk1302 = 1302, LNK_MsErrorCode_Lnk1306 = 1306, LNK_MsErrorCode_Lnk1309 = 1309, LNK_MsErrorCode_Lnk1312 = 1312, LNK_MsErrorCode_Lnk1313 = 1313, LNK_MsErrorCode_Lnk1314 = 1314, LNK_MsErrorCode_Lnk1318 = 1318, LNK_MsErrorCode_Lnk1332 = 1332, LNK_MsErrorCode_Lnk1352 = 1352, LNK_MsErrorCode_Lnk1561 = 1561, LNK_MsErrorCode_Lnk2001 = 2001, LNK_MsErrorCode_Lnk2004 = 2004, LNK_MsErrorCode_Lnk2005 = 2005, LNK_MsErrorCode_Lnk2008 = 2008, LNK_MsErrorCode_Lnk2011 = 2011, LNK_MsErrorCode_Lnk2013 = 2013, LNK_MsErrorCode_Lnk2017 = 2017, LNK_MsErrorCode_Lnk2019 = 2019, LNK_MsErrorCode_Lnk2020 = 2020, LNK_MsErrorCode_Lnk2022 = 2022, LNK_MsErrorCode_Lnk2023 = 2023, LNK_MsErrorCode_Lnk2026 = 2026, LNK_MsErrorCode_Lnk2027 = 2027, LNK_MsErrorCode_Lnk2031 = 2031, LNK_MsErrorCode_Lnk2033 = 2033, LNK_MsErrorCode_Lnk2038 = 2038, LNK_MsErrorCode_Lnk2039 = 2039, LNK_MsWarningCode_Lnk4001 = 4001, LNK_MsWarningCode_Lnk4002 = 4002, LNK_MsWarningCode_Lnk4006 = 4006, LNK_MsWarningCode_Lnk4010 = 4010, LNK_MsWarningCode_Lnk4014 = 4014, LNK_MsWarningCode_Lnk4020 = 4020, LNK_MsWarningCode_Lnk4022 = 4022, LNK_MsWarningCode_Lnk4039 = 4039, LNK_MsWarningCode_Lnk4044 = 4044, LNK_MsWarningCode_Lnk4049 = 4049, LNK_MsWarningCode_Lnk4065 = 4065, LNK_MsWarningCode_Lnk4070 = 4070, LNK_MsWarningCode_Lnk4071 = 4071, LNK_MsWarningCode_Lnk4073 = 4073, LNK_MsWarningCode_Lnk4075 = 4075, LNK_MsWarningCode_Lnk4076 = 4076, LNK_MsWarningCode_SectionFlagsConflict = 4078, LNK_MsWarningCode_Lnk4086 = 4086, LNK_MsWarningCode_Lnk4092 = 4092, LNK_MsWarningCode_Lnk4096 = 4096, LNK_MsWarningCode_Lnk4098 = 4098, LNK_MsWarningCode_MissingExternalTypeServer = 4099, LNK_MsWarningCode_Lnk4102 = 4102, LNK_MsWarningCode_Lnk4104 = 4104, LNK_MsWarningCode_Lnk4105 = 4105, LNK_MsWarningCode_Lnk4194 = 4194, LNK_MsWarningCode_Lnk4197 = 4197, LNK_MsWarningCode_UnsuedDelayLoadDll = 4199, LNK_MsWarningCode_Lnk4200 = 4200, LNK_MsWarningCode_Lnk4204 = 4204, LNK_MsWarningCode_Lnk4205 = 4205, LNK_MsWarningCode_Lnk4206 = 4206, LNK_MsWarningCode_Lnk4210 = 4210, LNK_MsWarningCode_Lnk4216 = 4216, LNK_MsWarningCode_Lnk4217 = 4217, LNK_MsWarningCode_Lnk4219 = 4219, LNK_MsWarningCode_Lnk4220 = 4220, LNK_MsWarningCode_Lnk4221 = 4221, LNK_MsWarningCode_Lnk4222 = 4222, LNK_MsWarningCode_Lnk4224 = 4224, LNK_MsWarningCode_Lnk4227 = 4227, LNK_MsWarningCode_Lnk4229 = 4229, LNK_MsWarningCode_Lnk4237 = 4237, LNK_MsWarningCode_Lnk4247 = 4247, LNK_MsWarningCode_Lnk4248 = 4248, LNK_MsWarningCode_Lnk4253 = 4253, LNK_MsWarningCode_Lnk4254 = 4254, LNK_MsWarningCode_Lnk4286 = 4286, } LNK_MsErrorCode; // --- Enum <-> String --------------------------------------------------------- internal String8 lnk_string_cmd_switch_type(LNK_CmdSwitchType type); internal LNK_CmdSwitchType lnk_cmd_switch_type_from_string(String8 string); internal LNK_CmdSwitch * lnk_cmd_switch_from_string(String8 string); internal LNK_InputType lnk_input_type_from_string(String8 string); internal LNK_DebugMode lnk_debug_mode_from_string(String8 string); internal LNK_TypeNameHashMode lnk_type_name_hash_mode_from_string(String8 string); // --- Command Line Helpers ---------------------------------------------------- internal LNK_CmdOption * lnk_cmd_line_push_option_if_not_presentf(Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...); internal LNK_CmdOption * lnk_cmd_line_push_optionf (Arena *arena, LNK_CmdLine *cmd_line, LNK_CmdSwitchType cmd_switch_type, char *param_fmt, ...); internal B32 lnk_cmd_line_has_switch(LNK_CmdLine cmd_line, LNK_CmdSwitchType cmd_switch_type); // --- Errors ------------------------------------------------------------------ internal void lnk_error_cmd_switch (LNK_ErrorCode code, struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, char *fmt, ...); internal void lnk_error_cmd_switch_invalid_param_count(LNK_ErrorCode code, struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch); internal void lnk_error_cmd_switch_invalid_param (LNK_ErrorCode code, struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8 param); // --- Specialized Parsers ------------------------------------------------------ internal B32 lnk_cmd_switch_parse_version (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, Version *ver_out); internal B32 lnk_cmd_switch_parse_tuple (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, Rng1U64 *tuple_out); internal B32 lnk_cmd_switch_parse_u64 (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *value_out, LNK_ParseU64Flags flags); internal B32 lnk_cmd_switch_parse_u32 (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U32 *value_out, LNK_ParseU64Flags flags); internal B32 lnk_cmd_switch_parse_flag (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, LNK_SwitchState *value_out); internal void lnk_cmd_switch_set_flag_inv_16(struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U16 *flags, U16 bits); internal void lnk_cmd_switch_set_flag_inv_64(struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *flags, U64 bits); internal void lnk_cmd_switch_set_flag_16 (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U16 *flags, U16 bits); internal void lnk_cmd_switch_set_flag_32 (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U32 *flags, U32 bits); internal void lnk_cmd_switch_set_flag_64 (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, U64 *flags, U64 bits); internal B32 lnk_cmd_switch_parse_string (struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out); internal void lnk_cmd_switch_parse_string_copy(Arena *arena, struct LNK_Obj *obj, LNK_CmdSwitchType cmd_switch, String8List value_strings, String8 *string_out); internal B32 lnk_parse_alt_name_directive (String8 string, struct LNK_Obj *obj, LNK_AltName *alt_out); internal B32 lnk_parse_merge_directive (String8 string, struct LNK_Obj *obj, LNK_MergeDirective *parse_out); internal B32 lnk_parse_export_directive (Arena *arena, String8 directive, struct LNK_Obj *obj, PE_ExportParse *export_out); internal B32 lnk_parse_export_directive_ex(Arena *arena, String8List directive, struct LNK_Obj *obj, PE_ExportParse *export_out); internal LNK_AltNameNode * lnk_alt_name_list_push(Arena *arena, LNK_AltNameList *list, LNK_AltName v); internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective v); // --- Getters ----------------------------------------------------------------- internal String8 lnk_get_image_name (LNK_Config *config); internal U64 lnk_get_default_function_pad_min (COFF_MachineType machine); internal U64 lnk_get_base_addr (LNK_Config *config); internal Version lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType machine); internal Version lnk_get_min_subsystem_version (PE_WindowsSubsystem subsystem, COFF_MachineType machine); internal B32 lnk_do_debug_info (LNK_Config *config); internal B32 lnk_is_thread_pool_shared(LNK_Config *config); internal B32 lnk_is_section_removed (LNK_Config *config, String8 section_name); internal B32 lnk_is_dll_delay_load (LNK_Config *config, String8 dll_name); internal String8 lnk_get_lib_name (String8 path); internal void lnk_push_disallow_lib(LNK_Config *config, String8 path); internal B32 lnk_is_lib_disallowed(LNK_Config *config, String8 path); internal void lnk_include_symbol(LNK_Config *config, String8 name, struct LNK_Obj *obj); // --- Config ------------------------------------------------------------------ internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 name, String8List value_list, struct LNK_Obj *obj); internal LNK_Config * lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line); ================================================ FILE: src/linker/lnk_debug_helper.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 lnk_make_linker_compile3(Arena *arena, COFF_MachineType machine) { String8 comp3_data = cv_make_comp3(arena, 0, CV_Language_LINK, cv_arch_from_coff_machine(machine), /* ver_fe_major */ 0, /* ver_fe_minor */ 0, /* ver_fe_build */ 0, /* ver_feqfe */ 0, /* ver_major */ 14, /* ver_minor */ 36, /* ver_build */ 32537, /* ver_qfe */ 0, str8_lit(BUILD_TITLE)); return comp3_data; } internal String8 lnk_make_debug_s(Arena *arena, CV_SymbolList symbol_list) { Temp scratch = scratch_begin(&arena, 1); CV_DebugS debug_s = {0}; String8List *symbol_list_ptr = cv_sub_section_ptr_from_debug_s(&debug_s, CV_C13SubSectionKind_Symbols); *symbol_list_ptr = cv_data_from_symbol_list(scratch.arena, symbol_list, CV_SymbolAlign); String8List debug_s_data_list = cv_data_c13_from_debug_s(scratch.arena, &debug_s, 1); String8 debug_s_data = str8_list_join(arena, &debug_s_data_list, 0); scratch_end(scratch); return debug_s_data; } internal String8 lnk_make_linker_debug_symbols(Arena *arena, COFF_MachineType machine) { Temp scratch = scratch_begin(&arena, 1); CV_SymbolList symbol_list = { .signature = CV_Signature_C13 }; String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data); String8 debug_symbols = lnk_make_debug_s(arena, symbol_list); scratch_end(scratch); return debug_symbols; } internal String8 lnk_make_dll_import_debug_symbols(Arena *arena, COFF_MachineType machine, String8 dll_name) { Temp scratch = scratch_begin(&arena,1); CV_SymbolList symbol_list = { .signature = CV_Signature_C13 }; // S_OBJ String8 obj_data = cv_make_obj_name(scratch.arena, dll_name, 0); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data); // S_COMPILE3 String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data); // TODO: add thunks // serialize symbols String8 debug_symbols = lnk_make_debug_s(arena, symbol_list); scratch_end(scratch); return debug_symbols; } ================================================ FILE: src/linker/lnk_debug_helper.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal String8 lnk_make_linker_compile3(Arena *arena, COFF_MachineType machine); internal String8 lnk_make_debug_s(Arena *arena, CV_SymbolList symbol_list); ================================================ FILE: src/linker/lnk_debug_info.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal THREAD_POOL_TASK_FUNC(lnk_parse_debug_s_task) { U64 obj_idx = task_id; LNK_ParseDebugSTaskData *task = raw_task; LNK_Obj *obj = task->obj_arr[obj_idx]; String8List sect_list = task->sect_list_arr[obj_idx]; CV_DebugS *debug_s = &task->debug_s_arr[obj_idx]; for (String8Node *node = sect_list.first; node != 0; node = node->next) { // parse & merge sub sections CV_DebugS ds = cv_parse_debug_s(arena, node->string); cv_debug_s_concat_in_place(debug_s, &ds); // make sure there is one string table String8List string_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_StringTable); if (string_data_list.node_count > 1) { // TODO: print section index lnk_error_obj(LNK_Warning_IllData, obj, ".debug$S has %u string table sub-sections defined, picking first sub-section", string_data_list.node_count); } // make sure there is one file checksum table String8List checksum_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_FileChksms); if (checksum_data_list.node_count > 1) { // TODO: print section index lnk_error_obj(LNK_Warning_IllData, obj, ".debug$S has %u file checksum sub-sections defined, picking first sub-section", checksum_data_list.node_count); } } } internal CV_DebugS * lnk_parse_debug_s_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *sect_list_arr) { ProfBeginFunction(); LNK_ParseDebugSTaskData task_data = {0}; task_data.obj_arr = obj_arr; task_data.sect_list_arr = sect_list_arr; task_data.debug_s_arr = push_array(arena->v[0], CV_DebugS, obj_count); tp_for_parallel(tp, arena, obj_count, lnk_parse_debug_s_task, &task_data); ProfEnd(); return task_data.debug_s_arr; } internal THREAD_POOL_TASK_FUNC(lnk_check_debug_t_sig_and_get_data_task) { U64 obj_idx = task_id; LNK_CheckDebugTSigTaskData *task = raw_task; String8Array data_arr = task->data_arr_arr[obj_idx]; LNK_Obj *obj = task->obj_arr[obj_idx]; for (String8 *data_ptr = &data_arr.v[0], *data_opl = data_arr.v + data_arr.count; data_ptr < data_opl; ++data_ptr) { if (data_ptr->size == 0) { continue; } if (data_ptr->size < sizeof(CV_Signature)) { // TODO: print section index lnk_error_obj(LNK_Error_IllData, obj, ".debug$T must have at least 4 bytes for CodeView signature"); } CV_Signature *sig_ptr = (CV_Signature *)data_ptr->str; switch (*sig_ptr) { default: { lnk_error_obj(LNK_Warning_IllData, obj, "unknown CodeView type signature in section (TODO: print section index)"); *data_ptr = str8(0,0); } break; case CV_Signature_C6: { lnk_not_implemented("TODO: C6 types"); *data_ptr = str8(0,0); } break; case CV_Signature_C7: { lnk_not_implemented("TODO: C7 types"); *data_ptr = str8(0,0); } break; case CV_Signature_C11: { lnk_not_implemented("TODO: C11 types"); *data_ptr = str8(0,0); } break; case CV_Signature_C13: { data_ptr->str += sizeof(CV_Signature); data_ptr->size -= sizeof(CV_Signature); } break; } } } internal THREAD_POOL_TASK_FUNC(lnk_parse_debug_t_task) { ProfBeginFunction(); U64 obj_idx = task_id; LNK_ParseDebugTTaskData *task = raw_task; String8Array data_arr = task->data_arr_arr[obj_idx]; CV_DebugT *debug_t = &task->debug_t_arr[obj_idx]; *debug_t = cv_debug_t_from_data_arr(arena, data_arr, CV_LeafAlign); ProfEnd(); } internal CV_DebugT * lnk_parse_debug_t_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *debug_t_list_arr) { ProfBeginFunction(); // list -> array String8Array *data_arr_arr = str8_array_from_list_arr(arena->v[0], debug_t_list_arr, obj_count); // validate signatures LNK_CheckDebugTSigTaskData check_sig; check_sig.obj_arr = obj_arr; check_sig.data_arr_arr = data_arr_arr; tp_for_parallel(tp, 0, obj_count, lnk_check_debug_t_sig_and_get_data_task, &check_sig); // parse debug types LNK_ParseDebugTTaskData parse; parse.data_arr_arr = data_arr_arr; parse.debug_t_arr = push_array_no_zero(arena->v[0], CV_DebugT, obj_count); tp_for_parallel(tp, arena, obj_count, lnk_parse_debug_t_task, &parse); ProfEnd(); return parse.debug_t_arr; } internal THREAD_POOL_TASK_FUNC(lnk_parse_cv_symbols_task) { LNK_ParseCVSymbolsTaskData *task = raw_task; LNK_CodeViewSymbolsInput *input = &task->inputs[task_id]; cv_parse_symbol_sub_section(arena, input->symbol_list, 0, input->raw_symbols, CV_SymbolAlign); } internal LNK_PchInfo * lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols, String8List alt_pch_dirs) { Temp scratch = scratch_begin(&arena, 1); String8 work_dir = os_get_current_path(scratch.arena); HashTable *debug_p_ht = hash_table_init(scratch.arena, obj_count); CV_LeafHeader **endprecomp_arr = push_array(scratch.arena, CV_LeafHeader *, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { CV_DebugT *debug_p = &debug_p_arr[obj_idx]; CV_DebugT *debug_t = &debug_t_arr[obj_idx]; if (debug_t->count && debug_p->count) { lnk_error_obj(LNK_Warning_MultipleDebugTAndDebugP, obj_arr[obj_idx], "multiple sections with debug types detected, obj must have either .debug$T or .debug$P (using .debug$T for type server)"); continue; } if (debug_p->count) { String8 obj_path = obj_arr[obj_idx]->path; obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, obj_path, work_dir); if (hash_table_search_path(debug_p_ht, obj_path)) { lnk_error_obj(LNK_Warning_DuplicateObjPath, obj_arr[obj_idx], "duplicate obj path %S", obj_path); } else { hash_table_push_path_u64(scratch.arena, debug_p_ht, obj_path, obj_idx); } } } LNK_PchInfo* pch_arr = push_array_no_zero(arena, LNK_PchInfo, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { CV_DebugT debug_t = debug_t_arr[obj_idx]; if (cv_debug_t_is_pch(debug_t)) { CV_Leaf precomp_leaf = cv_debug_t_get_leaf(debug_t, 0); CV_PrecompInfo precomp = cv_precomp_info_from_leaf(precomp_leaf); String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, precomp.obj_name, work_dir); // map obj name in LF_PRECOMP to obj index U64 debug_p_obj_idx = max_U64; if (!hash_table_search_path_u64(debug_p_ht, obj_path, &debug_p_obj_idx)) { String8 obj_name = str8_skip_last_slash(obj_path); for EachNode(alt_dir_n, String8Node, alt_pch_dirs.first) { String8 alt_obj_path = str8f(scratch.arena, "%S/%S", alt_dir_n->string, obj_name); if (hash_table_search_path_u64(debug_p_ht, alt_obj_path, &debug_p_obj_idx)) { break; } } } if (debug_p_obj_idx == max_U64) { lnk_error_obj(LNK_Error_PrecompObjNotFound, obj_arr[obj_idx], "LF_PRECOMP references non-existent obj %S", obj_path); lnk_exit(LNK_Error_PrecompObjNotFound); } // get LF_PRECOMP CV_DebugT debug_p = debug_p_arr[debug_p_obj_idx]; CV_Leaf endprecomp_leaf = cv_debug_t_get_leaf(debug_p, precomp.leaf_count); CV_LeafEndPreComp *endprecomp = (CV_LeafEndPreComp*) endprecomp_leaf.data.str; // error check LF_PRECOMP if (precomp.start_index > CV_MinComplexTypeIndex) { lnk_error_obj(LNK_Warning_AtypicalStartIndex, obj_arr[obj_idx], "atypical start index 0x%X in LF_PRECOMP", precomp.start_index); } if (precomp.start_index < CV_MinComplexTypeIndex) { lnk_error_obj(LNK_Error_InvalidStartIndex, obj_arr[obj_idx], "invalid start index 0x%X in LF_PRECOMP; must be >= 0x%X", precomp.start_index, CV_MinComplexTypeIndex); } if (precomp.leaf_count > debug_p.count) { lnk_error_obj(LNK_Error_InvalidPrecompLeafCount, obj_arr[obj_idx], "leaf count %u LF_PRECOMP exceeds leaf count %u in .debug$P in %S", precomp.leaf_count, debug_p.count, obj_arr[debug_p_obj_idx]->path); } // error check LF_ENDPRECOMP if (endprecomp_leaf.kind != CV_LeafKind_ENDPRECOMP) { lnk_error_obj(LNK_Error_EndprecompNotFound, obj_arr[obj_idx], "unable to find LF_ENDPRECOMP @ 0x%X in %S", precomp.leaf_count, obj_arr[debug_p_obj_idx]->path); } if (endprecomp_leaf.data.size != sizeof(CV_LeafEndPreComp)) { lnk_error_obj(LNK_Error_IllData, obj_arr[obj_idx], "invalid size 0x%X for LF_ENDPRECOMP", endprecomp_leaf.data.size); } if (endprecomp->sig != precomp.sig) { lnk_error_obj(LNK_Error_PrecompSigMismatch, obj_arr[obj_idx], "signature mismatch between LF_PRECOMP(0x%X) and LF_ENDPRECOMP(0x%X); precomp obj %S", precomp.sig, endprecomp->sig, obj_arr[debug_p_obj_idx]->path); } { // check against S_OBJNAME sig in precompiled obj $$SYMBOLS CV_SymbolList symbol_list = parsed_symbols[debug_p_obj_idx].v[0]; if (symbol_list.count) { CV_ObjInfo obj_info = cv_obj_info_from_symbol(symbol_list.first->data); if (obj_info.sig != 0 && obj_info.sig != precomp.sig) { lnk_error_obj(LNK_Error_PrecompSigMismatch, obj_arr[obj_idx], "signature mismatch between LF_PRECOMP(0x%X) and S_OBJNAME(0x%X) in %S", precomp.sig, obj_info.sig, obj_arr[debug_p_obj_idx]->path); } } else { lnk_error_obj(LNK_Warning_PrecompObjSymbolsNotFound, obj_arr[obj_idx], "symbols not found, unable to chceck LF_PRECOMP signature against S_OBJ"); } } // see :pch_check LNK_PchInfo *pch = &pch_arr[obj_idx]; pch->ti_lo = precomp.start_index; pch->ti_hi = precomp.start_index + precomp.leaf_count; pch->debug_p_obj_idx = debug_p_obj_idx; // [start_index, start_index+type_index_count) debug_t_arr[obj_idx].count -= 1; debug_t_arr[obj_idx].v += 1; endprecomp_arr[debug_p_obj_idx] = cv_debug_t_get_leaf_header(debug_p, precomp.leaf_count); } else { LNK_PchInfo *pch = &pch_arr[obj_idx]; pch->ti_lo = CV_MinComplexTypeIndex; pch->ti_hi = CV_MinComplexTypeIndex; pch->debug_p_obj_idx = 0; // :null_obj } } // remove LF_ENDPRECOMP for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { if (endprecomp_arr[obj_idx]) { endprecomp_arr[obj_idx]->kind = CV_LeafKind_NOTYPE; endprecomp_arr[obj_idx]->size = sizeof(CV_LeafKind); } } scratch_end(scratch); return pch_arr; } internal void lnk_do_debug_info_discard(CV_DebugS *debug_s_arr, CV_SymbolListArray *parsed_symbols, U64 obj_idx) { // remove symbols for (U64 i = 0; i < parsed_symbols[obj_idx].count; ++i) { MemoryZeroStruct(&parsed_symbols[obj_idx].v[i]); } // remove inline sites String8List *inlineelines_ptr = cv_sub_section_ptr_from_debug_s(&debug_s_arr[obj_idx], CV_C13SubSectionKind_InlineeLines); MemoryZeroStruct(inlineelines_ptr); } internal THREAD_POOL_TASK_FUNC(lnk_msf_parsed_from_data_task) { ProfBeginFunction(); LNK_MsfParsedFromDataTask *task = raw_task; // TODO: pick Info, TPI and IPI to flattten to make sure we don't waste compute on throw-away streams task->msf_parse_arr[task_id] = msf_parsed_from_data(arena, task->data_arr.v[task_id]); ProfEnd(); } internal MSF_Parsed ** lnk_msf_parsed_from_data_parallel(TP_Arena *arena, TP_Context *tp, String8Array data_arr) { ProfBeginFunction(); LNK_MsfParsedFromDataTask task = {0}; task.data_arr = data_arr; task.msf_parse_arr = push_array_no_zero(arena->v[0], MSF_Parsed *, data_arr.count); tp_for_parallel(tp, arena, data_arr.count, lnk_msf_parsed_from_data_task, &task); ProfEnd(); return task.msf_parse_arr; } internal THREAD_POOL_TASK_FUNC(lnk_get_external_leaves_task) { ProfBeginFunction(); U64 ts_idx = task_id; LNK_GetExternalLeavesTask *task = raw_task; MSF_Parsed *msf_parse = task->msf_parse_arr[ts_idx]; task->external_ti_ranges[ts_idx] = push_array(arena, Rng1U64, CV_TypeIndexSource_COUNT); task->external_leaves[ts_idx] = push_array(arena, CV_DebugT, CV_TypeIndexSource_COUNT); task->is_corrupted[ts_idx] = 1; if (msf_parse) { PDB_OpenTypeServerError tpi_error = PDB_OpenTypeServerError_UNKNOWN; PDB_OpenTypeServerError ipi_error = PDB_OpenTypeServerError_UNKNOWN; PDB_TypeServerParse tpi_parse, ipi_parse; if (PDB_FixedStream_Tpi < msf_parse->stream_count && PDB_FixedStream_Ipi < msf_parse->stream_count) { tpi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Tpi], &tpi_parse); ipi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Ipi], &ipi_parse); } if (tpi_error == PDB_OpenTypeServerError_OK && ipi_error == PDB_OpenTypeServerError_OK) { task->is_corrupted[ts_idx] = 0; task->external_ti_ranges[ts_idx][CV_TypeIndexSource_NULL] = rng_1u64(0,0); task->external_ti_ranges[ts_idx][CV_TypeIndexSource_TPI ] = tpi_parse.ti_range; task->external_ti_ranges[ts_idx][CV_TypeIndexSource_IPI ] = ipi_parse.ti_range; MemoryZeroStruct(&task->external_leaves[ts_idx][CV_TypeIndexSource_NULL]); task->external_leaves[ts_idx][CV_TypeIndexSource_TPI] = cv_debug_t_from_data(arena, tpi_parse.leaf_data, PDB_LEAF_ALIGN); task->external_leaves[ts_idx][CV_TypeIndexSource_IPI] = cv_debug_t_from_data(arena, ipi_parse.leaf_data, PDB_LEAF_ALIGN); } else { if (tpi_error != PDB_OpenTypeServerError_OK) { lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open TPI in %S, reson %S", task->ts_info_arr[ts_idx].name, pdb_string_from_open_type_server_error(tpi_error)); } if (ipi_error != PDB_OpenTypeServerError_OK) { lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open IPI in %S, reason %S", task->ts_info_arr[ts_idx].name, pdb_string_from_open_type_server_error(ipi_error)); } } } ProfEnd(); } internal CV_DebugT * lnk_merge_debug_t_and_debug_p(Arena *arena, U64 obj_count, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr) { CV_DebugT *result = push_array_no_zero(arena, CV_DebugT, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { CV_DebugT *debug_p = &debug_p_arr[obj_idx]; CV_DebugT *debug_t = &debug_t_arr[obj_idx]; if (debug_p->count) { Assert(!debug_t->count); result[obj_idx] = *debug_p; } else if (debug_t->count) { Assert(!debug_p->count); result[obj_idx] = *debug_t; } else { MemoryZeroStruct(&result[obj_idx]); } } return result; } internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, String8List alt_pch_dirs, U64 obj_count, LNK_Obj **obj_arr) { ProfBegin("Extract CodeView"); Temp scratch = scratch_begin(0,0); // gather debug info sections from objs ProfBegin("Collect CodeView"); // TODO: fix memory leak, we need a Temp wrapper for pool arena B32 collect_discarded_flag = 0; String8List *debug_s_list_arr = lnk_collect_obj_sections(tp, tp_arena, obj_count, obj_arr, str8_lit(".debug$S"), collect_discarded_flag); String8List *debug_p_list_arr = lnk_collect_obj_sections(tp, tp_arena, obj_count, obj_arr, str8_lit(".debug$P"), collect_discarded_flag); String8List *debug_t_list_arr = lnk_collect_obj_sections(tp, tp_arena, obj_count, obj_arr, str8_lit(".debug$T"), collect_discarded_flag); ProfEnd(); if (lnk_get_log_status(LNK_Log_Debug) || PROFILE_TELEMETRY) { U64 total_debug_s_size = 0, total_debug_t_size = 0, total_debug_p_size = 0; for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { for (String8Node *chunk = debug_s_list_arr[obj_idx].first; chunk != 0; chunk = chunk->next) { total_debug_s_size += chunk->string.size; } for (String8Node *chunk = debug_t_list_arr[obj_idx].first; chunk != 0; chunk = chunk->next) { total_debug_t_size += chunk->string.size; } for (String8Node *chunk = debug_p_list_arr[obj_idx].first; chunk != 0; chunk = chunk->next) { total_debug_p_size += chunk->string.size; } } ProfNoteV("Total .debug$S Input Size: %M", total_debug_s_size); ProfNoteV("Total .debug$T Input Size: %M", total_debug_t_size); ProfNoteV("Total .debug$P Input Size: %M", total_debug_p_size); if (lnk_get_log_status(LNK_Log_Debug)) { lnk_log(LNK_Log_Debug, "[Total .debug$S Input Size %M]", total_debug_s_size); lnk_log(LNK_Log_Debug, "[Total .debug$T Input Size %M]", total_debug_t_size); lnk_log(LNK_Log_Debug, "[Total .debug$P Input Size %M]", total_debug_p_size); } } ProfBegin("Parse CodeView"); CV_DebugS *debug_s_arr = lnk_parse_debug_s_sections(tp, tp_arena, obj_count, obj_arr, debug_s_list_arr); CV_DebugT *debug_p_arr = lnk_parse_debug_t_sections(tp, tp_arena, obj_count, obj_arr, debug_p_list_arr); CV_DebugT *debug_t_arr = lnk_parse_debug_t_sections(tp, tp_arena, obj_count, obj_arr, debug_t_list_arr); ProfEnd(); ProfBegin("Sort Type Servers"); U64 external_count = 0, internal_count = 0; LNK_Obj **sorted_obj_arr = push_array_no_zero(tp_arena->v[0], LNK_Obj *, obj_count); CV_DebugS *sorted_debug_s_arr = push_array_no_zero(tp_arena->v[0], CV_DebugS, obj_count); CV_DebugT *sorted_debug_t_arr = push_array_no_zero(tp_arena->v[0], CV_DebugT, obj_count); CV_DebugT *sorted_debug_p_arr = push_array_no_zero(tp_arena->v[0], CV_DebugT, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { B32 is_type_server = cv_debug_t_is_type_server(debug_t_arr[obj_idx]); if (is_type_server) { Assert(internal_count + external_count < obj_count); U64 slot_idx = (obj_count - external_count - 1); ++external_count; // TODO: report error: somehow obj was compiled with /Zi and /Yc Assert(debug_p_arr[obj_idx].count == 0); sorted_obj_arr[slot_idx] = obj_arr[obj_idx]; sorted_debug_s_arr[slot_idx] = debug_s_arr[obj_idx]; sorted_debug_t_arr[slot_idx] = debug_t_arr[obj_idx]; MemoryZeroStruct(&sorted_debug_p_arr[slot_idx]); } else { Assert(internal_count + external_count < obj_count); U64 slot_idx = internal_count; ++internal_count; sorted_obj_arr[slot_idx] = obj_arr[obj_idx]; sorted_debug_s_arr[slot_idx] = debug_s_arr[obj_idx]; sorted_debug_t_arr[slot_idx] = debug_t_arr[obj_idx]; sorted_debug_p_arr[slot_idx] = debug_p_arr[obj_idx]; } } ProfEnd(); // setup pointers to arrays LNK_Obj **internal_obj_arr = sorted_obj_arr; LNK_Obj **external_obj_arr = sorted_obj_arr + internal_count; CV_DebugS *internal_debug_s_arr = sorted_debug_s_arr; CV_DebugS *external_debug_s_arr = sorted_debug_s_arr + internal_count; CV_DebugT *internal_debug_t_arr = sorted_debug_t_arr; CV_DebugT *external_debug_t_arr = sorted_debug_t_arr + internal_count; CV_DebugT *internal_debug_p_arr = sorted_debug_p_arr; CV_DebugT *external_debug_p_arr = sorted_debug_p_arr + internal_count; ProfBegin("Parse Symbols"); ProfBegin("Count Symbol Inputs"); U64 internal_total_symbol_input_count = 0; U64 external_total_symbol_input_count = 0; for (U64 obj_idx = 0; obj_idx < internal_count; ++obj_idx) { String8List raw_symbols = cv_sub_section_from_debug_s(internal_debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols); internal_total_symbol_input_count += raw_symbols.node_count; } for (U64 obj_idx = 0; obj_idx < external_count; ++obj_idx) { String8List raw_symbols = cv_sub_section_from_debug_s(external_debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols); external_total_symbol_input_count += raw_symbols.node_count; } ProfEnd(); ProfBegin("Prepare Symbol Inputs"); U64 total_symbol_input_count = internal_total_symbol_input_count + external_total_symbol_input_count; LNK_CodeViewSymbolsInput *symbol_inputs = push_array_no_zero(tp_arena->v[0], LNK_CodeViewSymbolsInput, total_symbol_input_count); CV_SymbolListArray *parsed_symbols = push_array_no_zero(tp_arena->v[0], CV_SymbolListArray, obj_count); { CV_SymbolList *reserved_lists = push_array(tp_arena->v[0], CV_SymbolList, total_symbol_input_count); for (U64 obj_idx = 0, input_idx = 0; obj_idx < obj_count; ++obj_idx) { String8List raw_symbols = cv_sub_section_from_debug_s(sorted_debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols); // init parse output if (raw_symbols.node_count > 0) { parsed_symbols[obj_idx].count = raw_symbols.node_count; parsed_symbols[obj_idx].v = reserved_lists + input_idx; } else { parsed_symbols[obj_idx].count = 0; parsed_symbols[obj_idx].v = 0; } // init worker input for (String8Node *data_n = raw_symbols.first; data_n != 0; data_n = data_n->next, ++input_idx) { Assert(input_idx < total_symbol_input_count); LNK_CodeViewSymbolsInput *in = &symbol_inputs[input_idx]; in->obj_idx = obj_idx; in->symbol_list = &reserved_lists[input_idx]; in->raw_symbols = data_n->string; } } } ProfEnd(); ProfBegin("Symbol Parse"); LNK_ParseCVSymbolsTaskData task = {0}; task.inputs = symbol_inputs; tp_for_parallel(tp, tp_arena, total_symbol_input_count, lnk_parse_cv_symbols_task, &task); ProfEnd(); // TODO: do we rely on this behaviour? // // :zero_out_symbol_sub_section ProfBegin("Zero-out Symbols Sub-sections"); for (U64 i = 0; i < obj_count; ++i) { CV_DebugS *debug_s = &sorted_debug_s_arr[i]; String8List *symbols_ptr = cv_sub_section_ptr_from_debug_s(debug_s, CV_C13SubSectionKind_Symbols); MemoryZeroStruct(symbols_ptr); } ProfEnd(); ProfEnd(); CV_SymbolListArray *internal_parsed_symbols = parsed_symbols; CV_SymbolListArray *external_parsed_symbols = parsed_symbols + internal_count; LNK_CodeViewSymbolsInput *internal_symbol_inputs = symbol_inputs; LNK_CodeViewSymbolsInput *external_symbol_inputs = symbol_inputs + internal_count; LNK_PchInfo *pch_arr = lnk_setup_pch(tp_arena->v[0], internal_count, internal_obj_arr, internal_debug_t_arr, internal_debug_p_arr, internal_parsed_symbols, alt_pch_dirs); CV_DebugT *merged_debug_t_p_arr = lnk_merge_debug_t_and_debug_p(tp_arena->v[0], internal_count, internal_debug_t_arr, internal_debug_p_arr); ProfBegin("Analyze & Read External Type Server Files"); String8Array ts_path_arr; Rng1U64 **external_ti_ranges; CV_DebugT **external_leaves; U64 *obj_to_ts_idx_arr = push_array_no_zero(tp_arena->v[0], U64, external_count + 1); U64List *ts_to_obj_arr = push_array(tp_arena->v[0], U64List, external_count + 1); { HashTable *type_server_path_ht = hash_table_init(scratch.arena, 256); HashTable *ignored_path_ht = hash_table_init(scratch.arena, 256); CV_TypeServerInfoList ts_info_list = {0}; // push null CV_TypeServerInfoNode *null_ts_info = push_array(scratch.arena, CV_TypeServerInfoNode, 1); null_ts_info->data.name = str8_lit("\0"); SLLQueuePush(ts_info_list.first, ts_info_list.last, null_ts_info); ++ts_info_list.count; for (U64 obj_idx = 0; obj_idx < external_count; ++obj_idx) { // first leaf always type server CV_DebugT debug_t = external_debug_t_arr[obj_idx]; CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, 0); CV_TypeServerInfo ts = cv_type_server_info_from_leaf(leaf); // search disk for type server String8 type_server_path = lnk_find_first_file(scratch.arena, lib_dir_list, ts.name); // report no match B32 do_debug_info_discard = 0; if (type_server_path.size == 0) { if (!hash_table_search_path(ignored_path_ht, ts.name)) { hash_table_push_string_u64(scratch.arena, ignored_path_ht, ts.name, 0); lnk_error_obj(LNK_Warning_MissingExternalTypeServer, obj_arr[obj_idx], "unable to open external type server %S", ts.name); } do_debug_info_discard = 1; } // external type server is missing, discard parts of debug info that need types if (do_debug_info_discard) { lnk_do_debug_info_discard(external_debug_s_arr, external_parsed_symbols, obj_idx); continue; } { struct HT_Value { CV_TypeServerInfo ts; LNK_Obj *obj; U64 ts_idx; }; // was this type server queued? BucketNode *is_path_queued = hash_table_search_path(type_server_path_ht, type_server_path); if (is_path_queued) { struct HT_Value *present = is_path_queued->v.value_raw; // make sure type servers sigs match if (MemoryMatchStruct(&ts.sig, &present->ts.sig)) { // wire obj to type server data obj_to_ts_idx_arr[obj_idx] = present->ts_idx; // wire type server to obj u64_list_push(tp_arena->v[0], &ts_to_obj_arr[present->ts_idx], obj_idx); } else { lnk_error_obj(LNK_Error_ExternalTypeServerConflict, obj_arr[obj_idx], "external type server signature conflicts with type server loaded from '%S'", present->obj->path); } } else { U64 ts_idx = ts_info_list.count; // when we search matches on disk we store path on scratch, // make path copy in case we need it for error reporting type_server_path = push_str8_copy(tp_arena->v[0], type_server_path); // fill out type server info we read from obj CV_TypeServerInfoNode *ts_info_node = push_array(scratch.arena, CV_TypeServerInfoNode, 1); ts_info_node->data = ts; ts_info_node->data.name = type_server_path; // push to type server info list SLLQueuePush(ts_info_list.first, ts_info_list.last, ts_info_node); ts_info_list.count += 1; // wire obj to type server obj_to_ts_idx_arr[obj_idx] = ts_idx; // wire type server to obj u64_list_push(tp_arena->v[0], &ts_to_obj_arr[ts_idx], obj_idx); // fill out value struct HT_Value *value = push_array(scratch.arena, struct HT_Value, 1); value->ts = ts; value->obj = obj_arr[obj_idx]; value->ts_idx = ts_idx; // update hash table hash_table_push_path_raw(scratch.arena, type_server_path_ht, type_server_path, value); } } } // type server info list -> array ts_path_arr.count = ts_info_list.count; ts_path_arr.v = push_array(tp_arena->v[0], String8, ts_info_list.count); CV_TypeServerInfo *ts_info_arr = push_array(scratch.arena, CV_TypeServerInfo, ts_info_list.count); { U64 idx = 0; for (CV_TypeServerInfoNode *n = ts_info_list.first; n != 0; n = n->next, ++idx) { ts_path_arr.v[idx] = n->data.name; ts_info_arr[idx] = n->data; } } // read type servers from disk in parallel { ProfBegin("Read External Type Servers"); String8Array msf_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, 0, ts_path_arr); ProfEnd(); MSF_Parsed **msf_parse_arr = lnk_msf_parsed_from_data_parallel(tp_arena, tp, msf_data_arr); ProfBegin("Error check type servers"); for (U64 ts_idx = 0; ts_idx < msf_data_arr.count; ++ts_idx) { MSF_Parsed *msf_parse = msf_parse_arr[ts_idx]; B32 do_debug_info_discard = 0; if (!msf_parse) { do_debug_info_discard = 1; } else { PDB_InfoParse info_parse = {0}; pdb_info_parse_from_data(msf_parse->streams[PDB_FixedStream_Info], &info_parse); if (!MemoryMatchStruct(&info_parse.guid, &ts_info_arr[ts_idx].sig)) { Temp scratch = scratch_begin(0,0); String8 expected_sig_str = string_from_guid(scratch.arena, ts_info_arr[ts_idx].sig); String8 on_disk_sig_str = string_from_guid(scratch.arena, info_parse.guid); lnk_error(LNK_Warning_MismatchedTypeServerSignature, "%S: signature mismatch in type server read from disk, expected %S, got %S", ts_info_arr[ts_idx].name, expected_sig_str, on_disk_sig_str); scratch_end(scratch); do_debug_info_discard = 1; } } if (do_debug_info_discard) { U64List obj_idx_list = ts_to_obj_arr[ts_idx]; for (U64Node *obj_idx_n = obj_idx_list.first; obj_idx_n != 0; obj_idx_n = obj_idx_n->next) { lnk_do_debug_info_discard(external_debug_s_arr, external_parsed_symbols, obj_idx_n->data); } } } ProfEnd(); ProfBeginDynamic("Open External Type Servers [Count %llu]", ts_path_arr.count); LNK_GetExternalLeavesTask task = {0}; task.ts_info_arr = ts_info_arr; task.msf_parse_arr = msf_parse_arr; task.external_ti_ranges = push_array_no_zero(tp_arena->v[0], Rng1U64 *, msf_data_arr.count); task.external_leaves = push_array_no_zero(tp_arena->v[0], CV_DebugT *, msf_data_arr.count); task.is_corrupted = push_array_no_zero(scratch.arena, B8, msf_data_arr.count); tp_for_parallel(tp, tp_arena, msf_data_arr.count, lnk_get_external_leaves_task, &task); ProfEnd(); String8List unopen_type_server_list = {0}; // discard debug info that depends on the missing type server for (U64 ts_idx = 1; ts_idx < msf_data_arr.count; ++ts_idx) { if (task.is_corrupted[ts_idx]) { U64List obj_idx_list = ts_to_obj_arr[ts_idx]; for (U64Node *node = obj_idx_list.first; node != 0; node = node->next) { lnk_do_debug_info_discard(external_debug_s_arr, external_parsed_symbols, node->data); } } } // format error for (U64 ts_idx = 1; ts_idx < msf_data_arr.count; ++ts_idx) { if (task.is_corrupted[ts_idx]) { U64List obj_idx_list = ts_to_obj_arr[ts_idx]; str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t%S\n", ts_path_arr.v[ts_idx]); str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t\tDependent obj(s):\n"); for (U64Node *obj_idx_node = obj_idx_list.first; obj_idx_node != 0; obj_idx_node = obj_idx_node->next) { String8 obj_path = external_obj_arr[obj_idx_node->data]->path; str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t\t\t%S\n", obj_path); } } } if (unopen_type_server_list.node_count) { String8List error_msg_list = { 0 }; str8_list_pushf(scratch.arena, &error_msg_list, "unable to open external type server(s):\n"); str8_list_concat_in_place(&error_msg_list, &unopen_type_server_list); String8 error_msg = str8_list_join(scratch.arena, &error_msg_list, 0); lnk_error(LNK_Error_UnableToOpenTypeServer, "%S", error_msg); } // output external_ti_ranges = task.external_ti_ranges; external_leaves = task.external_leaves; } } ProfEnd(); // fill out result LNK_CodeViewInput cv = {0}; cv.count = obj_count; cv.internal_count = internal_count; cv.external_count = external_count; cv.type_server_count = ts_path_arr.count; cv.type_server_path_arr = ts_path_arr.v; cv.ts_to_obj_arr = ts_to_obj_arr; cv.obj_arr = sorted_obj_arr; cv.pch_arr = pch_arr; cv.debug_s_arr = sorted_debug_s_arr; cv.debug_p_arr = sorted_debug_p_arr; cv.debug_t_arr = sorted_debug_t_arr; cv.merged_debug_t_p_arr = merged_debug_t_p_arr; cv.total_symbol_input_count = total_symbol_input_count; cv.symbol_inputs = symbol_inputs; cv.parsed_symbols = parsed_symbols; cv.internal_obj_arr = internal_obj_arr; cv.external_obj_arr = external_obj_arr; cv.internal_debug_s_arr = internal_debug_s_arr; cv.external_debug_s_arr = external_debug_s_arr; cv.internal_debug_t_arr = internal_debug_t_arr; cv.external_debug_t_arr = external_debug_t_arr; cv.internal_debug_p_arr = internal_debug_p_arr; cv.external_debug_p_arr = external_debug_p_arr; cv.internal_total_symbol_input_count = internal_total_symbol_input_count; cv.internal_symbol_inputs = internal_symbol_inputs; cv.internal_parsed_symbols = internal_parsed_symbols; cv.external_total_symbol_input_count = external_total_symbol_input_count; cv.external_symbol_inputs = external_symbol_inputs; cv.external_parsed_symbols = external_parsed_symbols; cv.external_ti_ranges = external_ti_ranges; cv.external_leaves = external_leaves; cv.external_obj_to_ts_idx_arr = obj_to_ts_idx_arr; cv.external_obj_range = rng_1u64(internal_count, internal_count + external_count); scratch_end(scratch); ProfEnd(); return cv; } internal LNK_LeafRef lnk_leaf_ref(U32 enc_loc_idx, U32 enc_leaf_idx) { LNK_LeafRef ref; ref.enc_loc_idx = enc_loc_idx; ref.enc_leaf_idx = enc_leaf_idx; return ref; } internal LNK_LeafRef lnk_obj_leaf_ref(U32 obj_idx, U32 leaf_idx) { return lnk_leaf_ref(obj_idx, leaf_idx); } internal LNK_LeafRef lnk_ts_leaf_ref(CV_TypeIndexSource ti_source, U32 ts_idx, U32 leaf_idx) { ts_idx |= LNK_LeafRefFlag_LocIdxExternal; if (ti_source == CV_TypeIndexSource_IPI) { leaf_idx |= LNK_LeafRefFlag_LeafIdxIPI; } return lnk_leaf_ref(ts_idx, leaf_idx); } internal int lnk_leaf_ref_compare(LNK_LeafRef a, LNK_LeafRef b) { int cmp = 0; if (a.enc_loc_idx < b.enc_loc_idx) { cmp = -1; } else if (a.enc_loc_idx > b.enc_loc_idx) { cmp = +1; } else { if (a.enc_leaf_idx < b.enc_leaf_idx) { cmp = -1; } else if (a.enc_leaf_idx > b.enc_leaf_idx) { cmp = +1; } } return cmp; } internal int lnk_leaf_ref_is_before(void *raw_a, void *raw_b) { LNK_LeafRef **a = raw_a; LNK_LeafRef **b = raw_b; int is_before; if ((*a)->enc_loc_idx == (*b)->enc_loc_idx) { is_before = (*a)->enc_leaf_idx < (*b)->enc_leaf_idx; } else { is_before = (*a)->enc_loc_idx < (*b)->enc_loc_idx; } return is_before; } internal LNK_LeafLocType lnk_loc_type_from_leaf_ref(LNK_LeafRef leaf_ref) { if (leaf_ref.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal) { return LNK_LeafLocType_External; } return LNK_LeafLocType_Internal; } internal LNK_LeafLocType lnk_loc_type_from_obj_idx(LNK_CodeViewInput *input, U64 obj_idx) { if (input->external_obj_range.min <= obj_idx && obj_idx < input->external_obj_range.max) { return LNK_LeafLocType_External; } return LNK_LeafLocType_Internal; } internal U64 lnk_loc_idx_from_obj_idx(LNK_CodeViewInput *input, U64 obj_idx) { if (input->external_obj_range.min <= obj_idx && obj_idx < input->external_obj_range.max) { return input->external_obj_to_ts_idx_arr[obj_idx - input->external_obj_range.min]; } return obj_idx; } internal CV_TypeIndex lnk_ti_lo_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref) { CV_TypeIndex ti_lo; LNK_LeafLocType loc_type = lnk_loc_type_from_leaf_ref(leaf_ref); switch (loc_type) { case LNK_LeafLocType_Internal: { ti_lo = CV_MinComplexTypeIndex; } break; case LNK_LeafLocType_External: { U64 ts_idx = leaf_ref.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; CV_TypeIndexSource ti_source = (leaf_ref.enc_loc_idx & LNK_LeafRefFlag_LeafIdxIPI) ? CV_TypeIndexSource_IPI : CV_TypeIndexSource_TPI; ti_lo = input->external_ti_ranges[ts_idx][ti_source].min; } break; default: ti_lo = 0; break; } return ti_lo; } internal CV_TypeIndex lnk_ti_lo_from_loc(LNK_CodeViewInput *input, LNK_LeafLocType loc_type, U64 loc_idx, CV_TypeIndexSource ti_source) { CV_TypeIndex ti_lo = 0; if (loc_type == LNK_LeafLocType_Internal) { ti_lo = CV_MinComplexTypeIndex; } else if (loc_type == LNK_LeafLocType_External) { ti_lo = input->external_ti_ranges[loc_idx][ti_source].min; } return ti_lo; } internal String8 lnk_data_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref) { String8 data; LNK_LeafLocType loc_type = lnk_loc_type_from_leaf_ref(leaf_ref); switch (loc_type) { case LNK_LeafLocType_Internal: { U32 obj_idx = leaf_ref.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; U32 leaf_idx = leaf_ref.enc_leaf_idx; CV_DebugT debug_t = input->merged_debug_t_p_arr[obj_idx]; data = cv_debug_t_get_raw_leaf(debug_t, leaf_idx); } break; case LNK_LeafLocType_External: { U64 ts_idx = leaf_ref.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; U64 leaf_idx = leaf_ref.enc_leaf_idx & ~LNK_LeafRefFlag_LeafIdxIPI; CV_TypeIndexSource ti_source = leaf_ref.enc_leaf_idx & LNK_LeafRefFlag_LeafIdxIPI ? CV_TypeIndexSource_IPI : CV_TypeIndexSource_TPI; CV_DebugT debug_t = input->external_leaves[ts_idx][ti_source]; data = cv_debug_t_get_raw_leaf(debug_t, leaf_idx); } break; default: data = str8(0,0); break; } return data; } internal CV_TypeIndex lnk_type_index_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref) { CV_TypeIndex type_index = 0; LNK_LeafLocType loc_type = lnk_loc_type_from_leaf_ref(leaf_ref); switch (loc_type) { case LNK_LeafLocType_Internal: { LNK_PchInfo pch_info = input->pch_arr[leaf_ref.enc_loc_idx]; type_index = pch_info.ti_hi + leaf_ref.enc_leaf_idx; } break; case LNK_LeafLocType_External: { CV_TypeIndex lo = lnk_ti_lo_from_leaf_ref(input, leaf_ref); type_index = lo + leaf_ref.enc_leaf_idx & ~LNK_LeafRefFlag_LeafIdxIPI; } break; default: InvalidPath; } return type_index; } internal CV_Leaf lnk_cv_leaf_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref) { String8 raw_leaf = lnk_data_from_leaf_ref(input, leaf_ref); CV_Leaf leaf; cv_deserial_leaf(raw_leaf, 0, 1, &leaf); return leaf; } internal U128 lnk_hash_from_leaf_ref(LNK_LeafHashes *hashes, LNK_LeafRef leaf_ref) { LNK_LeafLocType loc_type; CV_TypeIndexSource ti_source; if (leaf_ref.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal) { loc_type = LNK_LeafLocType_External; ti_source = (leaf_ref.enc_leaf_idx & LNK_LeafRefFlag_LeafIdxIPI) ? CV_TypeIndexSource_IPI : CV_TypeIndexSource_TPI; } else { loc_type = LNK_LeafLocType_Internal; ti_source = CV_TypeIndexSource_TPI; } U32 loc_idx = leaf_ref.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; U32 leaf_idx = leaf_ref.enc_leaf_idx & ~LNK_LeafRefFlag_LeafIdxIPI; U128 hash = hashes->v[loc_type][loc_idx][ti_source].v[leaf_idx]; return hash; } internal LNK_LeafRef lnk_leaf_ref_from_loc_idx_and_ti(LNK_CodeViewInput *input, LNK_LeafLocType loc_type, CV_TypeIndexSource ti_source, U64 loc_idx, CV_TypeIndex obj_ti) { LNK_LeafRef leaf_ref; switch (loc_type) { case LNK_LeafLocType_External: { U64 ts_idx = loc_idx; CV_TypeIndex ti_lo = input->external_ti_ranges[ts_idx][ti_source].min; Assert(obj_ti >= ti_lo); // encode leaf index for type server leaf_ref = lnk_ts_leaf_ref(ti_source, ts_idx, obj_ti - ti_lo); } break; case LNK_LeafLocType_Internal: { U64 obj_idx = loc_idx; LNK_PchInfo pch = input->pch_arr[obj_idx]; if (obj_ti < pch.ti_lo) { CV_TypeIndex ti_lo = CV_MinComplexTypeIndex; Assert(obj_ti >= ti_lo); leaf_ref = lnk_obj_leaf_ref(obj_idx, obj_ti - ti_lo); } // PCH indirection else if (obj_ti < pch.ti_hi) { // we don't support nested precompiled types Assert(input->pch_arr[pch.debug_p_obj_idx].debug_p_obj_idx == /* null_obj: */ 0); Assert(input->pch_arr[pch.debug_p_obj_idx].ti_lo == input->pch_arr[pch.debug_p_obj_idx].ti_hi); leaf_ref = lnk_obj_leaf_ref(pch.debug_p_obj_idx, obj_ti - pch.ti_lo); } else { leaf_ref = lnk_obj_leaf_ref(obj_idx, pch.ti_lo + (obj_ti - pch.ti_hi) - CV_MinComplexTypeIndex); } } break; default: leaf_ref = lnk_leaf_ref(0, 0); break; } return leaf_ref; } internal B32 lnk_match_leaf_ref(LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef a, LNK_LeafRef b) { B32 are_same = 0; U128 a_hash = lnk_hash_from_leaf_ref(hashes, a); U128 b_hash = lnk_hash_from_leaf_ref(hashes, b); if (u128_match(a_hash, b_hash)) { CV_Leaf a_leaf = lnk_cv_leaf_from_leaf_ref(input, a); CV_Leaf b_leaf = lnk_cv_leaf_from_leaf_ref(input, b); Assert(a_leaf.kind == b_leaf.kind); #if 0 { Temp scratch = scratch_begin(0,0); CV_TypeIndexInfoList ti_info_list = cv_get_leaf_type_index_offsets(scratch.arena, a_leaf.kind, a_leaf.data); String8Array a_raw_data_arr = cv_get_data_around_type_indices(scratch.arena, ti_info_list, a_leaf.data); String8Array b_raw_data_arr = cv_get_data_around_type_indices(scratch.arena, ti_info_list, b_leaf.data); for (U64 i = 0; i < a_raw_data_arr.count; ++i) { String8 a_chunk = a_raw_data_arr.v[i]; String8 b_chunk = b_raw_data_arr.v[i]; Assert(str8_match(a_chunk, b_chunk, 0)); } scratch_end(scratch); } #endif are_same = 1; } return are_same; } internal B32 lnk_match_leaf_ref_deep(Arena *arena, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef a, LNK_LeafRef b) { B32 are_equal = 0; U128 a_hash = lnk_hash_from_leaf_ref(hashes, a); U128 b_hash = lnk_hash_from_leaf_ref(hashes, b); if (u128_match(a_hash, b_hash)) { String8 a_raw_leaf = lnk_data_from_leaf_ref(input, a); String8 b_raw_leaf = lnk_data_from_leaf_ref(input, b); CV_LeafHeader *a_header = (CV_LeafHeader *) a_raw_leaf.str; CV_LeafHeader *b_header = (CV_LeafHeader *) b_raw_leaf.str; if (a_header->kind == b_header->kind && a_header->size == b_header->size) { CV_Leaf a_leaf = cv_leaf_from_string(a_raw_leaf); CV_Leaf b_leaf = cv_leaf_from_string(b_raw_leaf); Temp temp = temp_begin(arena); CV_TypeIndexInfoList ti_info_list = cv_get_leaf_type_index_offsets(temp.arena, a_leaf.kind, a_leaf.data); String8Array a_raw_data_arr = cv_get_data_around_type_indices(temp.arena, ti_info_list, a_leaf.data); String8Array b_raw_data_arr = cv_get_data_around_type_indices(temp.arena, ti_info_list, b_leaf.data); are_equal = 1; for (U64 i = 0; i < a_raw_data_arr.count; ++i) { String8 a_chunk = a_raw_data_arr.v[i]; String8 b_chunk = b_raw_data_arr.v[i]; Assert(a_chunk.size == b_chunk.size); are_equal = str8_match(a_chunk, b_chunk, 0); if (!are_equal) { goto skip_type_index_compare; } } CV_TypeIndex a_ti_lo = lnk_ti_lo_from_leaf_ref(input, a); CV_TypeIndex b_ti_lo = lnk_ti_lo_from_leaf_ref(input, b); AssertAlways(a_ti_lo == b_ti_lo); for (CV_TypeIndexInfo *ti_info = ti_info_list.first; ti_info != 0; ti_info = ti_info->next) { CV_TypeIndex *a_ti_ptr = (CV_TypeIndex *) (a_leaf.data.str + ti_info->offset); CV_TypeIndex *b_ti_ptr = (CV_TypeIndex *)(b_leaf.data.str + ti_info->offset); if (*a_ti_ptr >= a_ti_lo && *b_ti_ptr >= b_ti_lo) { LNK_LeafLocType a_loc_type = (a.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal) >> 31; LNK_LeafLocType b_loc_type = (b.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal) >> 31; U64 a_loc_idx = a.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; U64 b_loc_idx = b.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; LNK_LeafRef a_sub_leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(input, a_loc_type, ti_info->source, a_loc_idx, *a_ti_ptr); LNK_LeafRef b_sub_leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(input, b_loc_type, ti_info->source, b_loc_idx, *b_ti_ptr); are_equal = lnk_match_leaf_ref_deep(arena, input, hashes, a_sub_leaf_ref, b_sub_leaf_ref); if (!are_equal) { break; } } // compare simple leaves else { are_equal = *a_ti_ptr == *b_ti_ptr; if (!are_equal) { break; } } } skip_type_index_compare:; temp_end(temp); } } return are_equal; } internal U128 lnk_hash_cv_leaf(Arena *arena, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafLocType loc_type, U32 loc_idx, Rng1U64 *ti_ranges, CV_TypeIndex curr_ti, CV_Leaf leaf, CV_TypeIndexInfoList ti_info_list) { // init hasher blake3_hasher hasher; blake3_hasher_init(&hasher); // hash leaf size blake3_hasher_update(&hasher, &leaf.data.size, sizeof leaf.data.size); // hash leaf kind blake3_hasher_update(&hasher, &leaf.kind, sizeof leaf.kind); // hash bytes around indices { Temp temp = temp_begin(arena); String8Array raw_data_arr = cv_get_data_around_type_indices(temp.arena, ti_info_list, leaf.data); for (U64 i = 0; i < raw_data_arr.count; ++i) { blake3_hasher_update(&hasher, raw_data_arr.v[i].str, raw_data_arr.v[i].size); } temp_end(temp); } // mix-in sub leaf hashes for (CV_TypeIndexInfo *ti_n = ti_info_list.first; ti_n != 0; ti_n = ti_n->next) { CV_TypeIndex sub_ti = *(CV_TypeIndex *) (leaf.data.str + ti_n->offset); // is type index complex? if (sub_ti >= ti_ranges[ti_n->source].min) { // Mostly leaves are laid out as DAG and we can get to sub leaf hash through index lookup, // however MASM doesn't follow DAG rule, for example: // // Engine\Source\Developer\Windows\LiveCoding\Private\External\LC_JumpToSelf.asm // .debug$T (No. 4): // LF_PROCEDURE (0x1000) [0008-0014] // Return type: 3 // Call Convention: Near C // Function Attribs: NULL // Argumnet Count: 0 // Argument List Type: 1001 // LF_ARGLIST (0x1001) [0018-001C] // Types 0 // LF_LABEL (0x1002) [0020-0024] // $UNDEFINED: E // // Note: LF_ARGLIST(0x1001) > LF_PROCEDURE(0x1000) // // Luckily we don't have many leaves that break DAG rule and we can skip without // much memory and perf penalty (In Ancient Game we skip 7 leaves) if (sub_ti < curr_ti) { LNK_LeafRef sub_leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(input, loc_type, ti_n->source, loc_idx, sub_ti); // query sub hash U128 sub_hash = lnk_hash_from_leaf_ref(hashes, sub_leaf_ref); // make sure sub hash was computed (:zero_hash_array) Assert(!u128_match(sub_hash, u128_zero())); // mix-in sub hash blake3_hasher_update(&hasher, &sub_hash, sizeof sub_hash); } else { Temp scratch = scratch_begin(0,0); String8 leaf_kind_str = cv_string_from_leaf_kind(leaf.kind); String8 leaf_info = push_str8f(scratch.arena, "LF_%S(type_index: 0x%x) forward refs member type index 0x%x (leaf struct offset: 0x%llx)", leaf_kind_str, curr_ti, sub_ti, ti_n->offset); if (loc_type == LNK_LeafLocType_Internal) { lnk_error_obj(LNK_Error_InvalidTypeIndex, input->internal_obj_arr[loc_idx], "%S", leaf_info); } else if (loc_type == LNK_LeafLocType_External) { lnk_error(LNK_Error_InvalidTypeIndex, "%S: %S", input->type_server_path_arr[loc_idx], leaf_info); } else { InvalidPath; } scratch_end(scratch); } } // simple indices are stable across compile units else { blake3_hasher_update(&hasher, &sub_ti, sizeof sub_ti); } } U128 hash; blake3_hasher_finalize(&hasher, (U8 *) &hash, sizeof hash); return hash; } internal void lnk_hash_cv_leaf_deep(Arena *arena, LNK_CodeViewInput *input, Rng1U64 *ti_ranges, CV_DebugT *leaves, LNK_LeafHashes *hashes, LNK_LeafLocType loc_type, U32 loc_idx, CV_TypeIndexInfoList ti_info_list, String8 data) { Temp temp = temp_begin(arena); struct stack_s { struct stack_s *next; CV_TypeIndexInfoList ti_info_list; CV_TypeIndexInfo *ti_info; CV_Leaf leaf; String8 data; CV_TypeIndex ti; CV_TypeIndexSource ti_source; }; // set up root frame struct stack_s *root_frame = push_array_no_zero(temp.arena, struct stack_s, 1); root_frame->next = 0; root_frame->ti_info_list = ti_info_list; root_frame->ti_info = ti_info_list.first; root_frame->data = data; root_frame->ti = 0; root_frame->ti_source = CV_TypeIndexSource_NULL; MemoryZeroStruct(&root_frame->leaf); U128Array *curr_hashes = hashes->v[loc_type][loc_idx]; struct stack_s *stack = root_frame; while (stack) { while (stack->ti_info) { CV_TypeIndexInfo *curr_ti_info = stack->ti_info; // advance iterator stack->ti_info = stack->ti_info->next; // get type index info CV_TypeIndex *ti_ptr = (CV_TypeIndex *) (stack->data.str + curr_ti_info->offset); // is index complex? if (*ti_ptr >= ti_ranges[curr_ti_info->source].min) { // TODO: handle malformed index AssertAlways(*ti_ptr < ti_ranges[curr_ti_info->source].max); U64 ti_idx = (*ti_ptr - ti_ranges[curr_ti_info->source].min); // was leaf hashed? if (MemoryIsZeroStruct(&curr_hashes[curr_ti_info->source].v[ti_idx])) { // :zero_hash_array CV_Leaf leaf = cv_debug_t_get_leaf(leaves[curr_ti_info->source], ti_idx); // find index offsets CV_TypeIndexInfoList sub_ti_info_list = cv_get_leaf_type_index_offsets(temp.arena, leaf.kind, leaf.data); // do we have sub leaves? if (sub_ti_info_list.count) { // fill out new frame struct stack_s *frame = push_array_no_zero(temp.arena, struct stack_s, 1); frame->next = 0; frame->ti_info_list = sub_ti_info_list; frame->ti_info = sub_ti_info_list.first; frame->leaf = leaf; frame->data = leaf.data; frame->ti = *ti_ptr; frame->ti_source = curr_ti_info->source; // recurse to sub leaf SLLStackPush(stack, frame); break; } else { curr_hashes[curr_ti_info->source].v[ti_idx] = lnk_hash_cv_leaf(temp.arena, input, hashes, loc_type, loc_idx, ti_ranges, CV_TypeIndex_Max, leaf, sub_ti_info_list); } } } } // no more type indices, pop frame if (!stack->ti_info) { if (stack != root_frame) { // sub leaves are hashed we can now hash parent leaf Temp temp2 = temp_begin(temp.arena); U64 leaf_idx = stack->ti - ti_ranges[stack->ti_source].min; curr_hashes[stack->ti_source].v[leaf_idx] = lnk_hash_cv_leaf(temp2.arena, input, hashes, loc_type, loc_idx, ti_ranges, CV_TypeIndex_Max, stack->leaf, stack->ti_info_list); temp_end(temp2); } SLLStackPop(stack); } } temp_end(temp); } internal LNK_LeafBucket * lnk_leaf_hash_table_insert_or_update(LNK_LeafHashTable *leaf_ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, U128 new_hash, LNK_LeafBucket *new_bucket) { LNK_LeafBucket *result = 0; B32 is_inserted_or_updated = 0; U64 best_idx = u128_mod64(new_hash, leaf_ht->cap); U64 idx = best_idx; do { retry:; LNK_LeafBucket *curr_bucket = leaf_ht->bucket_arr[idx]; if (curr_bucket == 0) { LNK_LeafBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&leaf_ht->bucket_arr[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted is_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if (lnk_match_leaf_ref(input, hashes, curr_bucket->leaf_ref, new_bucket->leaf_ref)) { int leaf_cmp = lnk_leaf_ref_compare(curr_bucket->leaf_ref, new_bucket->leaf_ref); if (leaf_cmp <= 0) { // are we inserting bucket that was already inserterd? Assert(leaf_cmp < 0); result = new_bucket; is_inserted_or_updated = 1; // don't need to update, more recent leaf is in the bucket break; } LNK_LeafBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&leaf_ht->bucket_arr[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { result = compare_bucket; is_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1) % leaf_ht->cap; } while (idx != best_idx); Assert(is_inserted_or_updated); return result; } internal LNK_LeafBucket * lnk_leaf_hash_table_search(LNK_LeafHashTable *ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef leaf_ref) { LNK_LeafBucket *match = 0; U128 hash = lnk_hash_from_leaf_ref(hashes, leaf_ref); U64 best_bucket_idx = u128_mod64(hash, ht->cap); U64 bucket_idx = best_bucket_idx; do { LNK_LeafBucket *bucket = ht->bucket_arr[bucket_idx]; if (bucket == 0) { break; } if (lnk_match_leaf_ref(input, hashes, bucket->leaf_ref, leaf_ref)) { match = bucket; break; } bucket_idx = (bucket_idx + 1) % ht->cap; } while (bucket_idx != best_bucket_idx); return match; } internal THREAD_POOL_TASK_FUNC(lnk_count_per_source_leaf_task) { ProfBeginFunction(); LNK_CountPerSourceLeafTask *task = raw_task; LNK_LeafRangeList leaf_range_list = task->leaf_ranges_per_task[task_id]; for (LNK_LeafRange *leaf_range = leaf_range_list.first; leaf_range != 0; leaf_range = leaf_range->next) { CV_DebugT debug_t = *leaf_range->debug_t; for (U64 leaf_idx = leaf_range->range.min; leaf_idx < leaf_range->range.max; ++leaf_idx) { CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_idx); CV_TypeIndexSource leaf_source = cv_type_index_source_from_leaf_kind(leaf_header->kind); task->count_arr_arr[leaf_source][task_id] += 1; } } ProfEnd(); } internal void lnk_cv_debug_t_count_leaves_per_source(TP_Context *tp, U64 count, CV_DebugT *debug_t_arr, U64 per_source_count_arr[CV_TypeIndexSource_COUNT]) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); ProfBegin("Compute Per Task Ranges"); U64 per_task_leaf_count = 10000; LNK_LeafRangeList *leaf_ranges_per_task = push_array(scratch.arena, LNK_LeafRangeList, tp->worker_count); for (U64 i = 0, task_weight = 0, task_id = 0; i < count; ++i) { CV_DebugT *debug_t = &debug_t_arr[i]; for (U64 k = 0; k < debug_t->count; k += per_task_leaf_count) { U64 cap = per_task_leaf_count - task_weight; LNK_LeafRange *leaf_range = push_array(scratch.arena, LNK_LeafRange, 1); leaf_range->range = rng_1u64(k, Min(k + cap, debug_t->count)); leaf_range->debug_t = debug_t; LNK_LeafRangeList *list = &leaf_ranges_per_task[task_id]; SLLQueuePush(list->first, list->last, leaf_range); ++list->count; task_weight += dim_1u64(leaf_range->range); if (task_weight >= per_task_leaf_count) { task_id = (task_id + 1) % tp->worker_count; task_weight = 0; } } } ProfEnd(); LNK_CountPerSourceLeafTask task; task.leaf_ranges_per_task = leaf_ranges_per_task; task.count_arr_arr = push_matrix_u64(scratch.arena, CV_TypeIndexSource_COUNT, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, lnk_count_per_source_leaf_task, &task); for (U64 i = 0; i < CV_TypeIndexSource_COUNT; ++i) { per_source_count_arr[i] += sum_array_u64(tp->worker_count, task.count_arr_arr[i]); } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_hash_debug_t_task) { ProfBeginFunction(); U64 obj_idx = task_id; LNK_LeafHasherTask *task = raw_task; Arena *fixed_arena = task->fixed_arenas[worker_id]; CV_DebugT debug_t = task->debug_t_arr[obj_idx]; U128Array out_hashes = task->hashes->v[LNK_LeafLocType_Internal][obj_idx][CV_TypeIndexSource_TPI]; Rng1U64 ti_ranges[CV_TypeIndexSource_COUNT]; for (U64 ti_source = 0; ti_source < ArrayCount(ti_ranges); ++ti_source) { ti_ranges[ti_source] = rng_1u64(task->input->pch_arr[obj_idx].ti_lo, task->input->pch_arr[obj_idx].ti_hi + debug_t.count); } for (U64 leaf_idx = 0; leaf_idx < debug_t.count; ++leaf_idx) { Temp temp = temp_begin(fixed_arena); // :debug_zero_hash_assert make sure we don't write same hash more than once //Assert(MemoryIsZeroStruct(&out_hash_arr.v[leaf_idx])); CV_TypeIndex curr_ti = lnk_type_index_from_leaf_ref(task->input, lnk_leaf_ref(obj_idx, leaf_idx)); CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx); CV_TypeIndexInfoList ti_info_list = cv_get_leaf_type_index_offsets(temp.arena, leaf.kind, leaf.data); out_hashes.v[leaf_idx] = lnk_hash_cv_leaf(temp.arena, task->input, task->hashes, LNK_LeafLocType_Internal, obj_idx, ti_ranges, curr_ti, leaf, ti_info_list); temp_end(temp); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_hash_type_server_leaves_task) { ProfBeginFunction(); LNK_LeafHasherTask *task = raw_task; U64 obj_idx = task_id; LNK_CodeViewInput *input = task->input; LNK_LeafHashes *hashes = task->hashes; CV_SymbolListArray parsed_symbols = input->external_parsed_symbols[obj_idx]; CV_DebugS debug_s = input->external_debug_s_arr[obj_idx]; U64 ts_idx = input->external_obj_to_ts_idx_arr[obj_idx]; CV_DebugT *leaves = input->external_leaves[ts_idx]; Rng1U64 *ti_ranges = input->external_ti_ranges[ts_idx]; // hash leaves referenced in symbols for (U64 i = 0; i < parsed_symbols.count; ++i) { CV_SymbolList symbol_list = parsed_symbols.v[i]; for (CV_SymbolNode *symnode = symbol_list.first; symnode != 0; symnode = symnode->next) { Temp temp = temp_begin(task->fixed_arenas[worker_id]); CV_TypeIndexInfoList ti_info_list = cv_get_symbol_type_index_offsets(temp.arena, symnode->data.kind, symnode->data.data); lnk_hash_cv_leaf_deep(temp.arena, task->input, ti_ranges, leaves, hashes, LNK_LeafLocType_External, ts_idx, ti_info_list, symnode->data.data); temp_end(temp); } } // hash leaves referenced in inlinees String8List inline_data_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_InlineeLines); for (String8Node *inline_data_node = inline_data_list.first; inline_data_node != 0; inline_data_node = inline_data_node->next) { Temp temp = temp_begin(task->fixed_arenas[worker_id]); CV_TypeIndexInfoList ti_info_list = cv_get_inlinee_type_index_offsets(temp.arena, inline_data_node->string); lnk_hash_cv_leaf_deep(temp.arena, task->input, ti_ranges, leaves, hashes, LNK_LeafLocType_External, ts_idx, ti_info_list, inline_data_node->string); temp_end(temp); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_leaf_dedup_internal_task) { LNK_LeafDedupInternal *task = raw_task; U64 obj_idx = task_id; CV_DebugT debug_t = task->debug_t_arr[obj_idx]; ProfBeginDynamic("Leaf Dedup Task 0x%X [Leaf Count %u]", obj_idx, task->debug_t_arr[obj_idx].count); LNK_LeafBucket *bucket = 0; for (U64 leaf_idx = 0; leaf_idx < debug_t.count; ++leaf_idx) { CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_idx); CV_TypeIndexSource ti_source = cv_type_index_source_from_leaf_kind(leaf_header->kind); LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_source]; LNK_LeafRef leaf_ref = lnk_obj_leaf_ref(obj_idx, leaf_idx); U128 leaf_hash = lnk_hash_from_leaf_ref(task->hashes, leaf_ref); if (bucket == 0) { bucket = push_array_no_zero(arena, LNK_LeafBucket, 1); } bucket->leaf_ref = leaf_ref; LNK_LeafBucket *inserted_or_updated = lnk_leaf_hash_table_insert_or_update(leaf_ht, task->input, task->hashes, leaf_hash, bucket); if (inserted_or_updated != bucket) { bucket = 0; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_leaf_dedup_external_task) { ProfBeginFunction(); LNK_LeafDedupExternal *task = raw_task; U64 ts_idx = task_id; LNK_CodeViewInput *input = task->input; LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[task->dedup_ti_source]; U128Array hashes = task->hashes->external_hashes[ts_idx][task->dedup_ti_source]; U64 leaf_count = dim_1u64(input->external_ti_ranges[ts_idx][task->dedup_ti_source]); LNK_LeafBucket *bucket = 0; for (U64 leaf_idx = 0; leaf_idx < leaf_count; ++leaf_idx) { if (!MemoryIsZeroStruct(&hashes.v[leaf_idx])) { // :zero_hash_check LNK_LeafRef leaf_ref = lnk_ts_leaf_ref(task->dedup_ti_source, ts_idx, leaf_idx); U128 leaf_hash = lnk_hash_from_leaf_ref(task->hashes, leaf_ref); if (bucket == 0) { bucket = push_array_no_zero(arena, LNK_LeafBucket, 1); } bucket->leaf_ref = leaf_ref; LNK_LeafBucket *inserted_or_updated = lnk_leaf_hash_table_insert_or_update(leaf_ht, task->input, task->hashes, leaf_hash, bucket); if (inserted_or_updated != bucket) { bucket = 0; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_count_present_buckets_task) { ProfBeginFunction(); LNK_GetPresentBucketsTask *task = raw_task; for (U64 bucket_idx = task->range_arr[task_id].min; bucket_idx < task->range_arr[task_id].max; ++bucket_idx) { if (task->ht->bucket_arr[bucket_idx] != 0) { task->count_arr[task_id] += 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_get_present_buckets_task) { ProfBeginFunction(); LNK_GetPresentBucketsTask *task = raw_task; Rng1U64 range = task->range_arr[task_id]; U64 cursor = task->offset_arr[task_id]; LNK_LeafHashTable *ht = task->ht; for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) { if (ht->bucket_arr[bucket_idx]) { task->result.v[cursor++] = ht->bucket_arr[bucket_idx]; } } ProfEnd(); } internal LNK_LeafBucketArray lnk_present_bucket_array_from_leaf_hash_table(TP_Context *tp, Arena *arena, LNK_LeafHashTable *ht) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); LNK_GetPresentBucketsTask task = {0}; task.ht = ht; task.count_arr = push_array(scratch.arena, U64, tp->worker_count); task.range_arr = tp_divide_work(scratch.arena, ht->cap, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, lnk_count_present_buckets_task, &task); LNK_LeafBucketArray result; result.count = sum_array_u64(tp->worker_count, task.count_arr); result.v = push_array_no_zero(arena, LNK_LeafBucket *, result.count); task.result = result; task.offset_arr = offsets_from_counts_array_u64(scratch.arena, task.count_arr, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, lnk_get_present_buckets_task, &task); scratch_end(scratch); ProfEnd(); return result; } internal THREAD_POOL_TASK_FUNC(lnk_leaf_ref_histo_task) { ProfBeginFunction(); LNK_LeafRadixSortTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; U32 *counts_ptr = task->counts_arr[task_id]; U32 loc_idx_bit_count_0 = task->loc_idx_bit_count_0; U32 loc_idx_bit_count_1 = task->loc_idx_bit_count_1; U32 loc_idx_bit_count_2 = task->loc_idx_bit_count_2; MemoryZeroTyped(task->counts_arr[task_id], task->counts_max); switch (task->pass_idx) { case 0: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit0 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 10, 0); ++counts_ptr[leaf_digit0]; } } break; case 1: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit1 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 11, 10); ++counts_ptr[leaf_digit1]; } } break; case 2: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit2 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 11, 21 - 1); // don't take into account IPI flag ++counts_ptr[leaf_digit2]; } } break; case 3: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit0 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_0, 0); ++counts_ptr[digit0]; } } break; case 4: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit1 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_1, loc_idx_bit_count_0); ++counts_ptr[digit1]; } } break; case 5: { for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit2 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_2, loc_idx_bit_count_0 + loc_idx_bit_count_1); U64 loc_bit = !!(bucket->leaf_ref.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal); digit2 |= loc_bit << loc_idx_bit_count_2; ++counts_ptr[digit2]; } } break; default: InvalidPath; } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_loc_idx_radix_sort_task) { ProfBeginFunction(); LNK_LeafRadixSortTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; U32 *counts_ptr = task->counts_arr[task_id]; U32 loc_idx_bit_count_0 = task->loc_idx_bit_count_0; U32 loc_idx_bit_count_1 = task->loc_idx_bit_count_1; U32 loc_idx_bit_count_2 = task->loc_idx_bit_count_2; switch (task->pass_idx) { // // Sort items on leaf index // case 0: { ProfBegin("Leaf Sort Low"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit0 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 10, 0); task->dst[counts_ptr[leaf_digit0]++] = bucket; } ProfEnd(); } break; case 1: { ProfBegin("Leaf Sort Mid"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit1 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 11, 10); task->dst[counts_ptr[leaf_digit1]++] = bucket; } ProfEnd(); } break; case 2: { ProfBegin("Leaf Sort High"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 leaf_digit2 = BitExtract(bucket->leaf_ref.enc_leaf_idx, 11, 21 - 1); // don't take into account IPI flag task->dst[counts_ptr[leaf_digit2]++] = bucket; } ProfEnd(); } break; // // Sort items on obj and type server index // case 3: { ProfBegin("Loc Sort Low"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit0 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_0, 0); task->dst[counts_ptr[digit0]++] = bucket; } ProfEnd(); } break; case 4: { ProfBegin("Loc Sort Mid"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit1 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_1, loc_idx_bit_count_0); task->dst[counts_ptr[digit1]++] = bucket; } ProfEnd(); } break; case 5: { ProfBegin("Loc Sort High"); for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->src[i]; U64 digit2 = BitExtract(bucket->leaf_ref.enc_loc_idx, loc_idx_bit_count_2, loc_idx_bit_count_0 + loc_idx_bit_count_1); U64 loc_bit = !!(bucket->leaf_ref.enc_loc_idx & LNK_LeafRefFlag_LocIdxExternal); digit2 |= loc_bit << loc_idx_bit_count_2; Assert(counts_ptr[digit2] != max_U32); task->dst[counts_ptr[digit2]++] = bucket; } ProfEnd(); } break; default: InvalidPath; } ProfEnd(); } internal void lnk_leaf_bucket_array_sort(TP_Context *tp, LNK_LeafBucketArray arr, U64 obj_count, U64 type_server_count) { Temp scratch = scratch_begin(0,0); #if PROFILE_TELEMETRY String8 leaf_count_string = str8_from_count(scratch.arena, arr.count); String8 obj_count_string = str8_from_count(scratch.arena, obj_count); String8 type_server_count_string = str8_from_count(scratch.arena, type_server_count); ProfBeginDynamic("Leaf Sort [Leaf Count: %.*s, Obj Count: %.*s, Type Server Count: %.*s]", str8_varg(leaf_count_string), str8_varg(obj_count_string), str8_varg(type_server_count_string)); #endif if (arr.count > 140000) { ProfBegin("Radix"); U32 loc_idx_max_bits = 32 - clz32(Max(obj_count, type_server_count)); LNK_LeafRadixSortTask task = {0}; task.loc_idx_bit_count_0 = Clamp(0, (S32)loc_idx_max_bits - 21, 11); task.loc_idx_bit_count_1 = Clamp(0, (S32)loc_idx_max_bits - 10, 11); task.loc_idx_bit_count_2 = Clamp(0, (S32)loc_idx_max_bits, 10); task.counts_max = (1 << 11); task.loc_idx_max = arr.count; task.ranges = tp_divide_work(scratch.arena, arr.count, tp->worker_count); task.dst = push_array_no_zero(scratch.arena, LNK_LeafBucket *, arr.count); task.src = arr.v; ProfBegin("Push Counts"); task.counts_arr = push_array_no_zero(scratch.arena, U32 *, tp->worker_count); for (U64 i = 0; i < tp->worker_count; ++i) { // zero-out happens in histogram step task.counts_arr[i] = push_array_no_zero(scratch.arena, U32, task.counts_max); } ProfEnd(); for (task.pass_idx = 0; task.pass_idx < 6; ++task.pass_idx) { ProfBeginDynamic("Pass: %u", task.pass_idx); ProfBegin("Histo"); tp_for_parallel(tp, 0, tp->worker_count, lnk_leaf_ref_histo_task, &task); ProfEnd(); B32 is_range_not_empty = 0; for (U64 task_id = 0; task_id < tp->worker_count; ++task_id) { is_range_not_empty = task.counts_arr[task_id][0] != dim_1u64(task.ranges[task_id]); if (is_range_not_empty) { break; } } ProfBegin("Counts -> Offsets"); { U64 digit_cursor = 0; for (U64 digit_idx = 0; digit_idx < task.counts_max; ++digit_idx) { for (U64 task_id = 0; task_id < tp->worker_count; ++task_id) { U64 count = task.counts_arr[task_id][digit_idx]; task.counts_arr[task_id][digit_idx] = digit_cursor; digit_cursor += count; } } Assert(digit_cursor == arr.count); } ProfEnd(); ProfBegin("Sort"); tp_for_parallel(tp, 0, tp->worker_count, lnk_loc_idx_radix_sort_task, &task); Swap(LNK_LeafBucket **, task.src, task.dst); ProfEnd(); ProfEnd(); } if (task.src != arr.v) { MemoryCopyTyped(arr.v, task.dst, arr.count); } #if 0 for (U64 i = 1; i < arr.count; ++i) { AssertAlways(arr.v[i-1]->leaf_ref.enc_loc_idx <= arr.v[i]->leaf_ref.enc_loc_idx); if (arr.v[i-1]->leaf_ref.enc_loc_idx == arr.v[i]->leaf_ref.enc_loc_idx) { AssertAlways(arr.v[i-1]->leaf_ref.enc_leaf_idx <= arr.v[i]->leaf_ref.enc_leaf_idx); } } #endif ProfEnd(); } else { ProfBegin("Radsort"); radsort(arr.v, arr.count, lnk_leaf_ref_is_before); ProfEnd(); } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_assign_type_indices_task) { LNK_AssignTypeIndicesTask *task = raw_task; Rng1U64 range = task->range_arr[task_id]; for (U64 i = range.min; i < range.max; ++i) { LNK_LeafBucket *bucket = task->bucket_arr.v[i]; bucket->type_index = task->min_type_index + i; } } internal void lnk_assign_type_indices(TP_Context *tp, LNK_LeafBucketArray bucket_arr, CV_TypeIndex min_type_index) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); LNK_AssignTypeIndicesTask task; task.range_arr = tp_divide_work(scratch.arena, bucket_arr.count, tp->worker_count); task.bucket_arr = bucket_arr; task.min_type_index = min_type_index; tp_for_parallel(tp, 0, tp->worker_count, lnk_assign_type_indices_task, &task); ProfEnd(); scratch_end(scratch); } internal THREAD_POOL_TASK_FUNC(lnk_patch_symbols_task) { ProfBeginFunction(); LNK_PatchSymbolTypesTask *task = raw_task; Arena *fixed_arena = task->arena_arr[task_id]; for EachInRange(symbol_input_idx, task->ranges[task_id]) { LNK_CodeViewSymbolsInput symbol_input = task->input->symbol_inputs[symbol_input_idx]; LNK_LeafLocType loc_type = lnk_loc_type_from_obj_idx(task->input, symbol_input.obj_idx); U64 loc_idx = lnk_loc_idx_from_obj_idx(task->input, symbol_input.obj_idx); CV_TypeIndex ti_lo_arr[CV_TypeIndexSource_COUNT]; ti_lo_arr[CV_TypeIndexSource_NULL] = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, CV_TypeIndexSource_NULL); ti_lo_arr[CV_TypeIndexSource_TPI ] = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, CV_TypeIndexSource_TPI); ti_lo_arr[CV_TypeIndexSource_IPI ] = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, CV_TypeIndexSource_IPI); for (CV_SymbolNode *symnode = symbol_input.symbol_list->first; symnode != 0; symnode = symnode->next) { Temp temp = temp_begin(fixed_arena); // find type index offsets in symbol CV_TypeIndexInfoList ti_list = cv_get_symbol_type_index_offsets(temp.arena, symnode->data.kind, symnode->data.data); // overwrite type indices in symbol for (CV_TypeIndexInfo *ti_info = ti_list.first; ti_info != 0; ti_info = ti_info->next) { CV_TypeIndex *ti_ptr = (CV_TypeIndex *) (symnode->data.data.str + ti_info->offset); if (*ti_ptr >= ti_lo_arr[ti_info->source]) { LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_info->source]; LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr); LNK_LeafBucket *leaf_bucket = lnk_leaf_hash_table_search(leaf_ht, task->input, task->hashes, leaf_ref); // we overwrite section memory directly *ti_ptr = leaf_bucket->type_index; } } temp_end(temp); } } ProfEnd(); } internal void lnk_patch_symbols(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); U64 max_ti_list_size = sizeof(CV_TypeIndexInfo) * (max_U16 / sizeof(CV_TypeIndex)); LNK_PatchSymbolTypesTask task = {0}; task.ranges = tp_divide_work(scratch.arena, input->total_symbol_input_count, tp->worker_count); task.input = input; task.hashes = hashes; task.leaf_ht_arr = leaf_ht_arr; task.arena_arr = alloc_fixed_size_arena_array(scratch.arena, tp->worker_count, max_ti_list_size, max_ti_list_size); tp_for_parallel(tp, 0, tp->worker_count, lnk_patch_symbols_task, &task); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_inlines_task) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); LNK_PatchInlinesTask *task = raw_task; U64 loc_idx = lnk_loc_idx_from_obj_idx(task->input, task_id); LNK_LeafLocType loc_type = lnk_loc_type_from_obj_idx(task->input, task_id); String8List inline_data_list = cv_sub_section_from_debug_s(task->debug_s_arr[task_id], CV_C13SubSectionKind_InlineeLines); for (String8Node *inline_data_node = inline_data_list.first; inline_data_node != 0; inline_data_node = inline_data_node->next) { Temp temp = temp_begin(scratch.arena); // get indices offsets CV_TypeIndexInfoList ti_info_list = cv_get_inlinee_type_index_offsets(temp.arena, inline_data_node->string); for (CV_TypeIndexInfo *ti_info = ti_info_list.first; ti_info != 0; ti_info = ti_info->next) { CV_TypeIndex *ti_ptr = (CV_TypeIndex *) (inline_data_node->string.str + ti_info->offset); CV_TypeIndex ti_lo = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, ti_info->source); if (*ti_ptr >= ti_lo) { LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr); LNK_LeafBucket *leaf_bucket = lnk_leaf_hash_table_search(&task->leaf_ht_arr[ti_info->source], task->input, task->hashes, leaf_ref); // patch index *ti_ptr = leaf_bucket->type_index; } } temp_end(temp); } scratch_end(scratch); ProfEnd(); } internal void lnk_patch_inlines(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr, U64 obj_count, CV_DebugS *debug_s_arr) { ProfBeginFunction(); LNK_PatchInlinesTask task = {0}; task.input = input; task.hashes = hashes; task.leaf_ht_arr = leaf_ht_arr; task.debug_s_arr = debug_s_arr; tp_for_parallel(tp, 0, obj_count, lnk_patch_inlines_task, &task); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_patch_leaves_task) { ProfBeginFunction(); LNK_PatchLeavesTask *task = raw_task; Rng1U64 range = task->range_arr[task_id]; for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) { Temp temp = temp_begin(task->fixed_arena_arr[task_id]); LNK_LeafBucket *bucket = task->bucket_arr[bucket_idx]; U64 loc_idx = bucket->leaf_ref.enc_loc_idx & ~LNK_LeafRefFlag_LocIdxExternal; LNK_LeafLocType loc_type = lnk_loc_type_from_leaf_ref(bucket->leaf_ref); CV_TypeIndex ti_lo = lnk_ti_lo_from_leaf_ref(task->input, bucket->leaf_ref); String8 raw_leaf = lnk_data_from_leaf_ref(task->input, bucket->leaf_ref); CV_Leaf leaf = cv_leaf_from_string(raw_leaf); // get type indices offsets CV_TypeIndexInfoList ti_info_list = cv_get_leaf_type_index_offsets(temp.arena, leaf.kind, leaf.data); for (CV_TypeIndexInfo *ti_info = ti_info_list.first; ti_info != 0; ti_info = ti_info->next) { CV_TypeIndex *ti_ptr = (CV_TypeIndex *) (leaf.data.str + ti_info->offset); if (*ti_ptr >= ti_lo) { LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_info->source]; LNK_LeafRef sub_leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr); LNK_LeafBucket *sub_leaf_bucket = lnk_leaf_hash_table_search(leaf_ht, task->input, task->hashes, sub_leaf_ref); // patch index *ti_ptr = sub_leaf_bucket->type_index; } } temp_end(temp); } ProfEnd(); } internal void lnk_patch_leaves(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr, LNK_LeafBucketArray bucket_arr) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); LNK_PatchLeavesTask task; task.input = input; task.hashes = hashes; task.leaf_ht_arr = leaf_ht_arr; task.bucket_arr = bucket_arr.v; task.range_arr = tp_divide_work(scratch.arena, bucket_arr.count, tp->worker_count); task.fixed_arena_arr = alloc_fixed_size_arena_array(scratch.arena, tp->worker_count, MB(1), MB(1)); tp_for_parallel(tp, 0, tp->worker_count, lnk_patch_leaves_task, &task); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_unbucket_raw_leaves_task) { LNK_UnbucketRawLeavesTask *task = raw_task; Rng1U64 range = task->range_arr[task_id]; for (U64 i = range.min; i < range.max; ++i) { String8 raw_leaf = lnk_data_from_leaf_ref(task->input, task->bucket_arr[i]->leaf_ref); task->raw_leaf_arr[i] = raw_leaf.str; } } internal CV_DebugT lnk_unbucket_leaf_array(TP_Context *tp, Arena *arena, LNK_CodeViewInput *input, LNK_LeafBucketArray bucket_arr) { ProfBeginDynamic("Unbucket Leaves [Count %llu]", bucket_arr.count); Temp scratch = scratch_begin(&arena, 1); LNK_UnbucketRawLeavesTask task = {0}; task.input = input; task.bucket_arr = bucket_arr.v; task.raw_leaf_arr = push_array_no_zero(arena, U8 *, bucket_arr.count); task.range_arr = tp_divide_work(scratch.arena, bucket_arr.count, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, lnk_unbucket_raw_leaves_task, &task); CV_DebugT debug_t = {0}; debug_t.count = bucket_arr.count; debug_t.v = task.raw_leaf_arr; scratch_end(scratch); ProfEnd(); return debug_t; } internal THREAD_POOL_TASK_FUNC(lnk_post_process_cv_symbols_task) { LNK_PostProcessCvSymbolsTask *task = raw_task; LNK_CodeViewSymbolsInput symbol_input = task->symbol_inputs[task_id]; for (CV_SymbolNode *symnode = symbol_input.symbol_list->first; symnode != 0; symnode = symnode->next) { CV_Symbol *symbol = &symnode->data; if (symbol->kind == CV_SymKind_LPROC32_ID || symbol->kind == CV_SymKind_GPROC32_ID || symbol->kind == CV_SymKind_LPROC32_DPC) { CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol->data.str; if (proc32->itype >= task->ipi_min_type_index) { if ((proc32->itype - task->ipi_min_type_index) < task->ipi_types.count) { U64 leaf_idx = proc32->itype - task->ipi_min_type_index; CV_Leaf leaf = cv_debug_t_get_leaf(task->ipi_types, leaf_idx); if (leaf.kind == CV_LeafKind_FUNC_ID) { if (leaf.data.size >= sizeof(CV_LeafFuncId)) { proc32->itype = ((CV_LeafFuncId *) leaf.data.str)->itype; } else { Assert(!"TODO: error handle corrupt leaf"); } } else if (leaf.kind == CV_LeafKind_MFUNC_ID) { if (leaf.data.size >= sizeof(CV_LeafMFuncId)) { proc32->itype = ((CV_LeafMFuncId *) leaf.data.str)->itype; } else { Assert(!"TODO: error handle corrupt leaf"); } } else { Assert(!"TODO: erorr handle unexpected leaf type"); } } else { Assert("TODO: error handle corrupted type index"); } } else { // TODO: in some cases destructors don't have a type, need a repro } } // convert symbol to final type switch (symbol->kind) { case CV_SymKind_LPROC32_ID: symbol->kind = CV_SymKind_LPROC32; break; case CV_SymKind_GPROC32_ID: symbol->kind = CV_SymKind_GPROC32; break; case CV_SymKind_LPROC32_DPC_ID: symbol->kind = CV_SymKind_LPROC32_DPC; break; case CV_SymKind_LPROCMIPS_ID: symbol->kind = CV_SymKind_LPROCMIPS; break; case CV_SymKind_GPROCMIPS_ID: symbol->kind = CV_SymKind_GPROCMIPS; break; case CV_SymKind_LPROCIA64_ID: symbol->kind = CV_SymKind_LPROCIA64; break; case CV_SymKind_GPROCIA64_ID: symbol->kind = CV_SymKind_GPROCIA64; break; case CV_SymKind_PROC_ID_END: symbol->kind = CV_SymKind_END; break; } } } internal CV_DebugT * lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input) { ProfBegin("Import Types"); ProfBegin("Hash Leaves"); LNK_LeafHashes *hashes = push_array(tp_temp->v[0], LNK_LeafHashes, 1); { Temp scratch = scratch_begin(tp_temp->v, tp_temp->count); // push internal hash arrays // // TPI and IPI leaves in .debug$T are stored in one array (we don't move them // to respective arrays before this point to save on memory move) ProfBegin("Push Internal Hash Arrays"); hashes->internal_hashes = push_array_no_zero(tp_temp->v[0], U128Array *, input->internal_count); for (U64 obj_idx = 0; obj_idx < input->internal_count; ++obj_idx) { CV_DebugT debug_t = input->merged_debug_t_p_arr[obj_idx]; U128Array arr = {0}; arr.count = debug_t.count; arr.v = push_array_no_zero(tp_temp->v[0], U128, debug_t.count); // :debug_zero_hash_assert #if BUILD_DEBUG MemoryZeroTyped(arr.v, arr.count); #endif hashes->internal_hashes[obj_idx] = push_array(tp_temp->v[0], U128Array, CV_TypeIndexSource_COUNT); for (U64 ti_source = 0; ti_source < CV_TypeIndexSource_COUNT; ++ti_source) { hashes->internal_hashes[obj_idx][ti_source] = arr; } } ProfEnd(); // push external hash arrays ProfBegin("Push External Hash Arrays"); hashes->external_hashes = push_array_no_zero(tp_temp->v[0], U128Array *, input->type_server_count); for (U64 ts_idx = 0; ts_idx < input->type_server_count; ++ts_idx) { hashes->external_hashes[ts_idx] = push_array_no_zero(tp_temp->v[0], U128Array, CV_TypeIndexSource_COUNT); for (U64 ti_source = 0; ti_source < CV_TypeIndexSource_COUNT; ++ti_source) { U64 leaf_count = dim_1u64(input->external_ti_ranges[ts_idx][ti_source]); hashes->external_hashes[ts_idx][ti_source].count = leaf_count; hashes->external_hashes[ts_idx][ti_source].v = push_array(tp_temp->v[0], U128, leaf_count); // :zero_hash_check } } ProfEnd(); LNK_LeafHasherTask task = {0}; task.input = input; task.hashes = hashes; task.fixed_arenas = alloc_fixed_size_arena_array(scratch.arena, tp->worker_count, MB(1), MB(1)); // hash .debug$P first so we can mix in hashes for precompiled sub leaves when hashing leaves in .debug$T ProfBeginDynamic("Hash .debug$P [Count: %llu]", input->internal_count); task.debug_t_arr = input->internal_debug_p_arr; tp_for_parallel(tp, 0, input->internal_count, lnk_hash_debug_t_task, &task); ProfEnd(); #if PROFILE_TELEMETRY String8 count_string = str8_from_count(scratch.arena, input->internal_count); ProfBegin("Hash .debug$T [Count: %.*s]", str8_varg(count_string)); #endif task.debug_t_arr = input->internal_debug_t_arr; tp_for_parallel(tp, 0, input->internal_count, lnk_hash_debug_t_task, &task); ProfEnd(); ProfBegin("Hash Type Server Leaves [Count: %.*s]", str8_varg(count_string)); tp_for_parallel(tp, 0, input->external_count, lnk_hash_type_server_leaves_task, &task); ProfEnd(); scratch_end(scratch); } ProfEnd(); ProfBegin("Leaf Hash Table Init"); LNK_LeafHashTable leaf_ht_arr[CV_TypeIndexSource_COUNT] = { 0 }; U64 internal_per_source_count[CV_TypeIndexSource_COUNT] = { 0 }; U64 external_per_source_count[CV_TypeIndexSource_COUNT] = { 0 }; { // count internal leaves lnk_cv_debug_t_count_leaves_per_source(tp, input->internal_count, input->internal_debug_p_arr, internal_per_source_count); lnk_cv_debug_t_count_leaves_per_source(tp, input->internal_count, input->internal_debug_t_arr, internal_per_source_count); // count external leaves for (U64 ts_idx = 0; ts_idx < input->type_server_count; ++ts_idx) { for (U64 ti_source = 0; ti_source < CV_TypeIndexSource_COUNT; ++ti_source) { external_per_source_count[ti_source] += dim_1u64(input->external_ti_ranges[ts_idx][ti_source]); } } // push buckets per source for (U64 ti_source = 0; ti_source < CV_TypeIndexSource_COUNT; ++ti_source) { U64 bucket_cap = 0; bucket_cap += internal_per_source_count[ti_source]; bucket_cap += external_per_source_count[ti_source]; bucket_cap = (U64) ((F64) bucket_cap * 1.3); #if PROFILE_TELEMETRY tmMessage(0, TMMF_ICON_NOTE, "%.*s Bucket Count: %llu", str8_varg(cv_string_from_type_index_source(ti_source)), bucket_cap); #endif leaf_ht_arr[ti_source].cap = bucket_cap; leaf_ht_arr[ti_source].bucket_arr = push_array(tp_temp->v[0], LNK_LeafBucket *, bucket_cap); } } ProfEnd(); #if PROFILE_TELEMETRY String8 obj_count_string = str8_from_count(tp_temp->v[0], input->internal_count); String8 tpi_count_string = str8_from_count(tp_temp->v[0], internal_per_source_count[CV_TypeIndexSource_TPI]); String8 ipi_count_string = str8_from_count(tp_temp->v[0], internal_per_source_count[CV_TypeIndexSource_IPI]); ProfBeginDynamic("Internal Leaf Dedup [Obj Count: %.*s, TPI: %.*s, IPI: %.*s]", str8_varg(obj_count_string), str8_varg(tpi_count_string), str8_varg(ipi_count_string)); #endif { LNK_LeafDedupInternal task; task.input = input; task.hashes = hashes; task.leaf_ht_arr = leaf_ht_arr; ProfBegin("Dedup .debug$P"); task.debug_t_arr = input->internal_debug_p_arr; tp_for_parallel(tp, tp_temp, input->internal_count, lnk_leaf_dedup_internal_task, &task); ProfEnd(); ProfBegin("Dedup .debug$T"); task.debug_t_arr = input->internal_debug_t_arr; tp_for_parallel(tp, tp_temp, input->internal_count, lnk_leaf_dedup_internal_task, &task); ProfEnd(); } ProfEnd(); ProfBeginDynamic("External Leaf Import [Type Server Count: %llu, Dependent Obj Count: %llu]", input->type_server_count, input->external_count); { LNK_LeafDedupExternal task = {0}; task.input = input; task.hashes = hashes; task.leaf_ht_arr = leaf_ht_arr; ProfBeginDynamic("Dedup TPI [Leaf Count %llu]", external_per_source_count[CV_TypeIndexSource_TPI]); task.dedup_ti_source = CV_TypeIndexSource_TPI; tp_for_parallel(tp, tp_temp, input->type_server_count, lnk_leaf_dedup_external_task, &task); ProfEnd(); ProfBeginDynamic("Dedup IPI [Leaf Count %llu]", external_per_source_count[CV_TypeIndexSource_IPI]); task.dedup_ti_source = CV_TypeIndexSource_IPI; tp_for_parallel(tp, tp_temp, input->type_server_count, lnk_leaf_dedup_external_task, &task); ProfEnd(); } ProfEnd(); // extract present buckets from the hash tables LNK_LeafBucketArray tpi_arr = lnk_present_bucket_array_from_leaf_hash_table(tp, tp_temp->v[0], &leaf_ht_arr[CV_TypeIndexSource_TPI]); LNK_LeafBucketArray ipi_arr = lnk_present_bucket_array_from_leaf_hash_table(tp, tp_temp->v[0], &leaf_ht_arr[CV_TypeIndexSource_IPI]); // sort output leaves based on { location index, leaf index } to guarantee determinism lnk_leaf_bucket_array_sort(tp, ipi_arr, input->internal_count, input->type_server_count); lnk_leaf_bucket_array_sort(tp, tpi_arr, input->internal_count, input->type_server_count); // assign type indices to each bucket lnk_assign_type_indices(tp, tpi_arr, CV_MinComplexTypeIndex); lnk_assign_type_indices(tp, ipi_arr, CV_MinComplexTypeIndex); // patch indices in symbols, inline sites, and leaves lnk_patch_symbols(tp, input, hashes, leaf_ht_arr); lnk_patch_inlines(tp, input, hashes, leaf_ht_arr, input->count, input->debug_s_arr); lnk_patch_leaves(tp, input, hashes, leaf_ht_arr, tpi_arr); lnk_patch_leaves(tp, input, hashes, leaf_ht_arr, ipi_arr); CV_DebugT tpi_types = lnk_unbucket_leaf_array(tp, tp_temp->v[0], input, tpi_arr); CV_DebugT ipi_types = lnk_unbucket_leaf_array(tp, tp_temp->v[0], input, ipi_arr); ProfBegin("Post Process CV Symbols"); { LNK_PostProcessCvSymbolsTask task = {0}; task.ipi_min_type_index = CV_MinComplexTypeIndex; task.ipi_types = ipi_types; task.symbol_inputs = input->symbol_inputs; task.parsed_symbols = input->parsed_symbols; tp_for_parallel(tp, 0, input->total_symbol_input_count, lnk_post_process_cv_symbols_task, &task); } ProfEnd(); CV_DebugT *types = push_array(tp_temp->v[0], CV_DebugT, CV_TypeIndexSource_COUNT); types[CV_TypeIndexSource_TPI] = tpi_types; types[CV_TypeIndexSource_IPI] = ipi_types; ProfEnd(); return types; } internal U64 lnk_format_u128(U8 *buf, U64 buf_max, U64 length, U128 v) { U64 size = 0; if (length > 0 && buf_max > 0) { if (length <= 8) { U64 mask = length == 8 ? max_U64 : (1ull << (length*8)) - 1; size = raddbg_snprintf((char*)buf, buf_max - 1, "%llX", (long long)(v.u64[0] & mask)); } else { U64 mask1 = length == 16 ? max_U64 : (1ull << ((length-8)*8)) - 1; size = raddbg_snprintf((char*)buf, buf_max, "%llX%llX", (long long)(v.u64[1] & mask1), (long long)v.u64[0]); } } return size; } internal THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_lenient_task) { ProfBeginFunction(); LNK_TypeNameReplacer *task = raw_task; Rng1U64 range = task->ranges[task_id]; CV_DebugT debug_t = task->debug_t; U64 hash_length = task->hash_length; B32 make_map = task->make_map; Arena *map_arena = 0; String8List *map = 0; if (make_map) { map_arena = task->map_arena->v[task_id]; map = &task->maps[task_id]; } U64 hash_max_chars = hash_length*2; U8 temp[128]; for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) { CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx); if (leaf.kind == CV_LeafKind_STRUCTURE || leaf.kind == CV_LeafKind_CLASS) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if ((udt_info.props & CV_TypeProp_HasUniqueName) && udt_info.unique_name.size > hash_max_chars && udt_info.name.size > hash_max_chars) { // hash unique name U128 name_hash; blake3_hasher hasher; blake3_hasher_init(&hasher); blake3_hasher_update(&hasher, udt_info.unique_name.str, udt_info.unique_name.size); blake3_hasher_finalize(&hasher, (U8*)&name_hash, sizeof(name_hash)); // emit hash -> unique name map if (make_map) { lnk_format_u128(temp, sizeof(temp), hash_length, name_hash); str8_list_pushf(map_arena, map, "%s %S\n", temp, str8_varg(udt_info.unique_name)); } // parse leaf size CV_NumericParsed dummy; U64 numeric_size = cv_read_numeric(leaf.data, sizeof(CV_LeafStruct), &dummy); String8 lambda_prefix = str8_lit("size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1 + udt_info.unique_name.size + 1; } else { // replace uniuqe type name with hash udt_info.unique_name.str = udt_info.name.str + udt_info.name.size + 1; udt_info.unique_name.size = lnk_format_u128(udt_info.unique_name.str, udt_info.unique_name.size, hash_length, name_hash); // update leaf header CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx); header->size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1 + udt_info.unique_name.size + 1; } } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task) { ProfBeginFunction(); LNK_TypeNameReplacer *task = raw_task; Rng1U64 range = task->ranges[task_id]; CV_DebugT debug_t = task->debug_t; U64 hash_length = task->hash_length; B32 make_map = task->make_map; Arena *map_arena = 0; String8List *map = 0; if (make_map) { map_arena = task->map_arena->v[task_id]; map = &task->maps[task_id]; } U64 hash_max_chars = hash_length*2; U8 temp[128]; for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) { CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx); if (leaf.kind == CV_LeafKind_STRUCTURE || leaf.kind == CV_LeafKind_CLASS) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if (udt_info.name.size > hash_max_chars) { // pick name to hash String8 name; if (udt_info.props & CV_TypeProp_HasUniqueName) { name = udt_info.unique_name; } else { name = udt_info.name; } // hash name U128 name_hash; blake3_hasher hasher; blake3_hasher_init(&hasher); blake3_hasher_update(&hasher, udt_info.name.str, udt_info.name.size); blake3_hasher_finalize(&hasher, (U8*)&name_hash, sizeof(name_hash)); // emit hash -> name map if (make_map) { lnk_format_u128(temp, sizeof(temp), hash_length, name_hash); str8_list_pushf(map_arena, map, "%s %.*s\n", temp, str8_varg(name)); } // replace name with hash udt_info.name.size = lnk_format_u128(udt_info.name.str, udt_info.name.size, hash_length, name_hash); // parse struct size CV_NumericParsed dummy; U64 numeric_size = cv_read_numeric(leaf.data, sizeof(CV_LeafStruct), &dummy); // update header CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx); header->size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1; // discard unique name CV_LeafStruct *lf = (CV_LeafStruct *)(header + 1); lf->props &= ~CV_TypeProp_HasUniqueName; } } } ProfEnd(); } internal void lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); // init task context LNK_TypeNameReplacer task = {0}; task.debug_t = debug_t; task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count); task.hash_length = Clamp(1, hash_length, 16); if (map_name.size > 0) { task.make_map = 1; task.map_arena = tp_arena_alloc(tp); task.maps = push_array(scratch.arena, String8List, tp->worker_count); } // pick task function TP_TaskFunc *func = 0; switch (mode) { case LNK_TypeNameHashMode_Null: case LNK_TypeNameHashMode_None: break; case LNK_TypeNameHashMode_Lenient: func = lnk_replace_type_names_with_hashes_lenient_task; break; case LNK_TypeNameHashMode_Full: func = lnk_replace_type_names_with_hashes_full_task; break; } // run task tp_for_parallel(tp, arena, tp->worker_count, func, &task); // optionally write out map file if (task.make_map) { String8List map = {0}; str8_list_concat_in_place_array(&map, task.maps, tp->worker_count); lnk_write_data_list_to_file_path(map_name, str8_zero(), map); tp_arena_release(&task.map_arena); } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_filter_out_gsi_symbols_task) { U64 obj_idx = task_id; LNK_ProcessSymDataTaskData *task = raw_task; CV_SymbolList *gsi_list = &task->gsi_list_arr[obj_idx]; CV_SymbolListArray parsed_symbols = task->parsed_symbols[obj_idx]; CV_SymbolList global_list = {0}; CV_SymbolList typedef_list = {0}; for (U64 i = 0; i < parsed_symbols.count; ++i) { CV_SymbolList *list = &parsed_symbols.v[i]; U64 depth = 0; for (CV_SymbolNode *curr = list->first, *next; curr != 0; curr = next) { next = curr->next; if (cv_is_global_symbol(curr->data.kind)) { cv_symbol_list_remove_node(list, curr); cv_symbol_list_push_node(&global_list, curr); } else if (cv_is_typedef(curr->data.kind)) { if (depth == 0) { cv_symbol_list_remove_node(list, curr); cv_symbol_list_push_node(&typedef_list, curr); } } // Undocumented symbol that appears only in objs. // MSVC removes these symbols from output. // // LLD-link replaces symbol with S_SKIP: // https://github.com/llvm/llvm-project/blob/main/lld/COFF/PDB.cpp#L575 else if (curr->data.kind == 0x1176) { cv_symbol_list_remove_node(list, curr); } if (cv_is_scope_symbol(curr->data.kind)) { ++depth; } else if (cv_is_end_symbol(curr->data.kind)) { Assert(depth > 0); --depth; } } } // collect GSI symbols Assert(gsi_list->count == 0); cv_symbol_list_concat_in_place(gsi_list, &global_list); cv_symbol_list_concat_in_place(gsi_list, &typedef_list); } internal THREAD_POOL_TASK_FUNC(lnk_make_proc_refs_task) { ProfBeginFunction(); U64 obj_idx = task_id; LNK_ProcessSymDataTaskData *task = raw_task; PDB_DbiModule *mod = task->mod_arr[obj_idx]; CV_SymbolList *gsi_list = &task->gsi_list_arr[obj_idx]; CV_SymbolListArray parsed_symbols = task->parsed_symbols[obj_idx]; for (U64 i = 0; i < parsed_symbols.count; ++i) { CV_SymbolList list = parsed_symbols.v[i]; CV_SymbolList proc_refs = cv_make_proc_refs(arena, mod->imod, list); cv_symbol_list_concat_in_place(gsi_list, &proc_refs); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_process_sym_data_task) { ProfBeginFunction(); U64 obj_idx = task_id; LNK_ProcessSymDataTaskData *task = raw_task; CV_SymbolListArray parsed_symbols = task->parsed_symbols[obj_idx]; static CV_Signature MODULE_SYMBOL_SIGNATURE = CV_Signature_C13; ProfBegin("Compute Buffer Size"); U64 buffer_size = sizeof(MODULE_SYMBOL_SIGNATURE); for (U64 i = 0; i < parsed_symbols.count; ++i) { CV_SymbolList list = parsed_symbols.v[i]; U64 data_size = cv_patch_symbol_tree_offsets(list, buffer_size, PDB_SYMBOL_ALIGN); buffer_size += data_size; } ProfEnd(); // alloc buffer U8 *buffer = push_array_no_zero(arena, U8, buffer_size); U64 buffer_cursor = 0; // MS Symbol and Type Information p.4: // "The first four bytes of the $$SYMBOLS segment is used as a signature to specify the version of // the Symbol and Type OMF contained in the $$SYMBOLS segment." CV_Signature *sig_ptr = (CV_Signature *) (buffer + buffer_cursor); *sig_ptr = MODULE_SYMBOL_SIGNATURE; buffer_cursor += sizeof(*sig_ptr); ProfBegin("Serialize Symbols"); for (U64 i = 0; i < parsed_symbols.count; ++i) { CV_SymbolList list = parsed_symbols.v[i]; for (CV_SymbolNode *symbol_n = list.first; symbol_n != 0; symbol_n = symbol_n->next) { symbol_n->data.offset = buffer_cursor; buffer_cursor += cv_serialize_symbol_to_buffer(buffer, buffer_cursor, buffer_size, &symbol_n->data, PDB_SYMBOL_ALIGN); } } ProfEnd(); // output Assert(task->symbol_data_arr[obj_idx].total_size == 0); str8_list_push(arena, &task->symbol_data_arr[obj_idx], str8(buffer, buffer_size)); ProfEnd(); } internal LNK_ProcessedCodeViewC11Data lnk_process_c11_data(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr, U64 string_data_base_offset, CV_StringHashTable string_ht, MSF_Context *msf, PDB_DbiModule **mod_arr) { // TODO: handle c11 data String8List *data_list_arr = push_array(arena->v[0], String8List, obj_count); LNK_ProcessedCodeViewC11Data result; result.data_list_arr = data_list_arr; return result; } internal THREAD_POOL_TASK_FUNC(lnk_process_c13_data_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena,1); U64 obj_idx = task_id; LNK_ProcessC13DataTask *task = raw_task; CV_DebugS debug_s = task->debug_s_arr[obj_idx]; // parse checksum data String8List checksum_data = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); CV_ChecksumList checksum_list = cv_c13_parse_checksum_data_list(scratch.arena, checksum_data); // get strings sub-section String8 string_data = cv_string_table_from_debug_s(debug_s); // collect source file names from checksum headers String8List source_file_names_list = cv_c13_collect_source_file_names(arena, checksum_list, string_data); // relocate checksum data cv_c13_patch_string_offsets_in_checksum_list(checksum_list, string_data, task->string_data_base_offset, task->string_ht); // get module sub-sections PDB_DbiModule *mod = task->dbi_mod_arr[obj_idx]; String8 mod_c13_data = dbi_module_read_c13_data(scratch.arena, task->msf, mod); CV_DebugS mod_debug_s = cv_parse_debug_s_c13(scratch.arena, mod_c13_data); // relocate line and frame data String8List *mod_checksum_data = cv_sub_section_ptr_from_debug_s(&mod_debug_s, CV_C13SubSectionKind_FileChksms); U64 checksum_base = mod_checksum_data->total_size; B32 is_checksum_patch_needed = checksum_base > 0; if (is_checksum_patch_needed) { String8List line_data = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); String8List frame_data = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FrameData); cv_c13_patch_checksum_offsets_in_line_data_list(line_data, checksum_base); cv_c13_patch_checksum_offsets_in_frame_data_list(frame_data, checksum_base); } // push obj c13 data to module cv_debug_s_concat_in_place(&mod_debug_s, &debug_s); // serialize c13 data B32 include_sig = 0; String8List c13_data = cv_data_c13_from_debug_s(arena, &mod_debug_s, include_sig); // store for later pass task->c13_data_arr[obj_idx] = c13_data; task->source_file_names_list_arr[obj_idx] = source_file_names_list; scratch_end(scratch); ProfEnd(); } internal LNK_ProcessedCodeViewC13Data lnk_process_c13_data(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr, U64 string_data_base_offset, CV_StringHashTable string_ht, MSF_Context *msf, PDB_DbiModule **mod_arr) { ProfBeginFunction(); LNK_ProcessC13DataTask task = {0}; task.debug_s_arr = debug_s_arr; task.msf = msf; task.dbi_mod_arr = mod_arr; task.c13_data_arr = push_array_no_zero(arena->v[0], String8List, obj_count); task.source_file_names_list_arr = push_array_no_zero(arena->v[0], String8List, obj_count); task.string_data_base_offset = string_data_base_offset; task.string_ht = string_ht; tp_for_parallel(tp, arena, obj_count, lnk_process_c13_data_task, &task); // fill out result LNK_ProcessedCodeViewC13Data result = {0}; result.data_list_arr = task.c13_data_arr; result.source_file_names_list_arr = task.source_file_names_list_arr; ProfEnd(); return result; } internal THREAD_POOL_TASK_FUNC(lnk_write_module_data_task) { U64 obj_idx = task_id; LNK_WriteModuleDataTask *task = raw_task; PDB_DbiModule *mod = task->mod_arr[obj_idx]; String8List sym_data = task->symbol_data_arr[obj_idx]; String8List c11_data = task->c11_data_list_arr[obj_idx]; String8List c13_data = task->c13_data_list_arr[obj_idx]; String8List globrefs = task->globrefs_arr[obj_idx]; U32 sym_data_size32 = safe_cast_u32(sym_data.total_size); U32 c11_data_size32 = safe_cast_u32(c11_data.total_size); U32 c13_data_size32 = safe_cast_u32(c13_data.total_size); U32 globrefs_size32 = safe_cast_u32(globrefs.total_size); // layout module data String8List module_data = {0}; str8_list_concat_in_place(&module_data, &sym_data); str8_list_concat_in_place(&module_data, &c11_data); str8_list_concat_in_place(&module_data, &c13_data); str8_list_concat_in_place(&module_data, &globrefs); // make stream has enough memory so it doens't trigger memory allocations in MSF // during multi-thread write MSF_UInt stream_pos = msf_stream_get_pos(task->msf, mod->sn); if (stream_pos != 0) { Assert(!"stream must be at start position"); } MSF_UInt stream_cap = msf_stream_get_cap(task->msf, mod->sn); if (stream_cap < module_data.total_size) { Assert(!"not enough bytes in destination stream to copy module data"); } // write data B32 is_write_ok = msf_stream_write_list(task->msf, mod->sn, module_data); // update module data sizes if (is_write_ok) { mod->sym_data_size = sym_data_size32; mod->c11_data_size = c11_data_size32; mod->c13_data_size = c13_data_size32; mod->globrefs_size = globrefs_size32; } else { // TODO: error handle } } internal THREAD_POOL_TASK_FUNC(lnk_cv_symbol_ptr_array_hasher) { LNK_CvSymbolPtrArrayHasher *task = raw_task; Rng1U64 range = task->range_arr[task_id]; for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) { task->hash_arr[symbol_idx] = XXH3_64bits(task->arr[symbol_idx]->data.data.str, task->arr[symbol_idx]->data.data.size); } } internal U64 * lnk_hash_cv_symbol_ptr_arr(TP_Context *tp, Arena *arena, CV_SymbolPtrArray arr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); LNK_CvSymbolPtrArrayHasher task = {0}; task.hash_arr = push_array_no_zero(arena, U64, arr.count); task.arr = arr.v; task.range_arr = tp_divide_work(scratch.arena, arr.count, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, lnk_cv_symbol_ptr_array_hasher, &task); scratch_end(scratch); ProfEnd(); return task.hash_arr; } internal THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task) { // TODO: use chunked lists for SC // TODO: put back unused sc nodes // TODO: compute CRC for relocations U64 obj_idx = task_id; LNK_PushDbiSecContribTaskData *task = raw_task; PDB_DbiModule *mod = task->mod_arr[obj_idx]; LNK_Obj *obj = task->obj_arr[obj_idx]; COFF_SectionHeader *obj_section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; PDB_DbiSectionContribNode *sc_arr = push_array_no_zero(arena, PDB_DbiSectionContribNode, obj->header.section_count_no_null); U64 sc_count = 0; for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *obj_sect_header = &obj_section_table[sect_idx]; if (obj_sect_header->flags & COFF_SectionFlag_LnkInfo) { continue; } if (obj_sect_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (obj_sect_header->flags & LNK_SECTION_FLAG_DEBUG) { continue; } U64 sect_number; String8 sect_data; U32 sect_off; U32 data_crc; if (obj_sect_header->flags & COFF_SectionFlag_CntUninitializedData) { if (obj_sect_header->vsize == 0) { continue; } sect_number = rng_1u64_array_bsearch(task->image_section_virt_ranges, obj_sect_header->voff); Assert(sect_number < task->image_section_virt_ranges.count); sect_data = str8_zero(); sect_off = obj_sect_header->voff - task->image_section_virt_ranges.v[sect_number].min; data_crc = 0; } else { if (obj_sect_header->fsize == 0) { continue; } sect_number = rng_1u64_array_bsearch(task->image_section_file_ranges, obj_sect_header->foff); Assert(sect_number < task->image_section_file_ranges.count); sect_data = str8_substr(task->image_data, rng_1u64(obj_sect_header->foff, obj_sect_header->foff + obj_sect_header->fsize)); sect_off = obj_sect_header->foff - task->image_section_file_ranges.v[sect_number].min; data_crc = update_crc32(0, sect_data.str, sect_data.size); } // fill out SC PDB_DbiSectionContribNode *sc = sc_arr + sc_count++; sc->data.base.sec = (U16)sect_number; sc->data.base.pad0 = 0; sc->data.base.sec_off = sect_off; sc->data.base.size = obj_sect_header->vsize; sc->data.base.flags = obj_sect_header->flags; sc->data.base.mod = mod->imod; sc->data.base.pad1 = 0; sc->data.data_crc = 0; sc->data.reloc_crc = 0; dbi_sec_contrib_list_push_node(&task->sc_list[obj_idx], sc); } // Mod1::fUpdateSecContrib if (sc_count > 0) { for (U64 sc_idx = 0; sc_idx < sc_count; ++sc_idx) { if (sc_arr[sc_idx].data.base.flags & COFF_SectionFlag_CntCode) { mod->first_sc = sc_arr[sc_idx].data; break; } } } } internal THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_defined_task) { ProfBeginFunction(); LNK_BuildPublicSymbolsTask *task = raw_task; for (LNK_SymbolHashTrieChunk *chunk = task->chunk_lists[task_id].first; chunk != 0; chunk = chunk->next) { CV_SymbolNode *nodes = push_array_no_zero(arena, CV_SymbolNode, chunk->count); U64 node_idx = 0; for EachIndex(i, chunk->count) { LNK_Symbol *symbol = chunk->v[i].symbol; LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol_ref.obj)) { continue; } COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; } CV_Pub32Flags flags = 0; if (COFF_SymbolType_IsFunc(symbol_parsed.type)) { flags |= CV_Pub32Flag_Function; } ISectOff sc = lnk_sc_from_symbol(symbol); U16 symbol_isect16 = safe_cast_u16(sc.isect); U32 symbol_off32 = safe_cast_u32(sc.off); nodes[node_idx].data = cv_make_pub32(arena, flags, symbol_off32, symbol_isect16, symbol->name); cv_symbol_list_push_node(&task->pub_list_arr[task_id], &nodes[node_idx]); node_idx += 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_gsi_hash_cv_list_task) { ProfBeginFunction(); LNK_BuildPublicSymbolsTask *task = raw_task; Rng1U64 range = task->symbol_ranges[task_id]; for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) { CV_Symbol *symbol = &task->symbols.v[symbol_idx]->data; String8 name = cv_name_from_symbol(symbol->kind, symbol->data); task->hashes[symbol_idx] = gsi_hash(task->gsi, name); } ProfEnd(); } internal void lnk_build_pdb_public_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, PDB_PsiContext *psi) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Defined"); LNK_BuildPublicSymbolsTask task = {0}; task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, tp->worker_count); task.chunk_lists = symtab->chunks; tp_for_parallel(tp, arena, tp->worker_count, lnk_build_pdb_public_symbols_defined_task, &task); ProfEnd(); CV_SymbolPtrArray symbols = cv_symbol_ptr_array_from_list(scratch.arena, tp, tp->worker_count, task.pub_list_arr); ProfBegin("GSI Push"); gsi_push_many_arr(tp, psi->gsi, symbols.count, symbols.v); ProfEnd(); scratch_end(scratch); ProfEnd(); } internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, U64 obj_count, LNK_Obj **obj_arr, CV_DebugS *debug_s_arr, U64 total_symbol_input_count, LNK_CodeViewSymbolsInput *symbol_inputs, CV_SymbolListArray *parsed_symbols, CV_DebugT types[CV_TypeIndexSource_COUNT]) { ProfBegin("PDB"); Temp scratch = scratch_begin(tp_arena->v, tp_arena->count); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); COFF_SectionHeader **image_section_table = coff_section_table_from_data(scratch.arena, image_data, pe.section_table_range); U64 image_section_table_count = pe.section_count+1; ProfBegin("Setup PDB Context"); PDB_Context *pdb = pdb_alloc(config->pdb_page_size, config->machine, config->time_stamp, config->age, config->guid); ProfEnd(); // move patched type data // // leaf data is stored in g_file_arena which has linker's life-time // and this way we skip redundant leaf copy to the type server to make things faster pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_IPI], types[CV_TypeIndexSource_IPI]); pdb_type_server_push_parallel(tp, pdb->type_servers[CV_TypeIndexSource_TPI], types[CV_TypeIndexSource_TPI]); ProfBegin("Collect Symbols for GSI"); CV_SymbolList *gsi_list_arr = push_array(scratch.arena, CV_SymbolList, obj_count); { LNK_ProcessSymDataTaskData task = {0}; task.gsi_list_arr = gsi_list_arr; task.parsed_symbols = parsed_symbols; tp_for_parallel(tp, 0, obj_count, lnk_filter_out_gsi_symbols_task, &task); } ProfEnd(); ProfBegin("Reserve DBI Modules"); PDB_DbiModule **mod_arr = push_array(tp_arena->v[0], PDB_DbiModule *, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { LNK_Obj *obj = obj_arr[obj_idx]; mod_arr[obj_idx] = dbi_push_module(pdb->dbi, obj->path, lnk_obj_get_lib_path(obj)); // we don't support symbol append Assert(mod_arr[obj_idx]->sn == MSF_INVALID_STREAM_NUMBER); } ProfEnd(); ProfBegin("Build String Table"); CV_StringHashTable string_ht = cv_dedup_string_tables(tp_arena, tp, obj_count, debug_s_arr); cv_string_hash_table_assign_buffer_offsets(tp, string_ht); U64 string_data_base_offset = pdb->info->strtab.size; pdb_strtab_add_cv_string_hash_table(&pdb->info->strtab, string_ht); ProfEnd(); ProfBegin("Build DBI Modules"); { TP_Temp temp = tp_temp_begin(tp_arena); { ProfBegin("Reloc Module Data"); ProfBegin("Serialize Symbols"); String8List *serialized_symbol_data = push_array(scratch.arena, String8List, obj_count); { LNK_ProcessSymDataTaskData task = {0}; task.symbol_inputs = symbol_inputs; task.parsed_symbols = parsed_symbols; task.mod_arr = mod_arr; task.symbol_data_arr = serialized_symbol_data; tp_for_parallel(tp, tp_arena, obj_count, lnk_process_sym_data_task, &task); } ProfEnd(); LNK_ProcessedCodeViewC11Data processed_c11 = lnk_process_c11_data(tp, tp_arena, obj_count, debug_s_arr, string_data_base_offset, string_ht, pdb->msf, mod_arr); LNK_ProcessedCodeViewC13Data processed_c13 = lnk_process_c13_data(tp, tp_arena, obj_count, debug_s_arr, string_data_base_offset, string_ht, pdb->msf, mod_arr); ProfEnd(); // TODO: actually collect offsets and pass them here ProfBegin("Build Empty Global Reference Array"); String8List *globrefs_arr = push_array(tp_arena->v[0], String8List, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { String8List *globrefs = &globrefs_arr[obj_idx]; str8_serial_begin(tp_arena->v[0], globrefs); Assert(globrefs->total_size == 0); str8_serial_push_u32(tp_arena->v[0], globrefs, globrefs->total_size); } ProfEnd(); // reserve memory for module streams ProfBegin("Reserve Modules Memory"); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { // compute number of bytes needed for module data U64 mod_size = 0; mod_size += serialized_symbol_data[obj_idx].total_size; mod_size += processed_c11.data_list_arr[obj_idx].total_size; mod_size += processed_c13.data_list_arr[obj_idx].total_size; mod_size += globrefs_arr[obj_idx].total_size; U32 mod_size32 = safe_cast_u32(mod_size); // allocate stream for module PDB_DbiModule *mod = mod_arr[obj_idx]; mod->sn = msf_stream_alloc_ex(pdb->msf, mod_size32); } ProfEnd(); // copy data to module streams ProfBegin("Write Modules Data"); LNK_WriteModuleDataTask write_module_data_task_data; write_module_data_task_data.msf = pdb->msf; write_module_data_task_data.mod_arr = mod_arr; write_module_data_task_data.symbol_data_arr = serialized_symbol_data; write_module_data_task_data.c11_data_list_arr = processed_c11.data_list_arr; write_module_data_task_data.c13_data_list_arr = processed_c13.data_list_arr; write_module_data_task_data.globrefs_arr = globrefs_arr; tp_for_parallel(tp, 0, obj_count, lnk_write_module_data_task, &write_module_data_task_data); ProfEnd(); // push source files per module info ProfBegin("Build Source Files List"); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { PDB_DbiModule *mod = mod_arr[obj_idx]; String8List source_file_list_scratch = processed_c13.source_file_names_list_arr[obj_idx]; String8List source_file_list = str8_list_copy(pdb->dbi->arena, &source_file_list_scratch); str8_list_concat_in_place(&mod->source_file_list, &source_file_list); } ProfEnd(); } tp_temp_end(temp); } ProfEnd(); ProfBegin("Make Proc Refs"); { LNK_ProcessSymDataTaskData task = {0}; task.mod_arr = mod_arr; task.gsi_list_arr = gsi_list_arr; task.parsed_symbols = parsed_symbols; tp_for_parallel(tp, tp_arena, obj_count, lnk_make_proc_refs_task, &task); } ProfEnd(); ProfBegin("Push Global Symbols"); { CV_SymbolPtrArray global_symbols = cv_symbol_ptr_array_from_list(scratch.arena, tp, obj_count, gsi_list_arr); cv_dedup_symbol_ptr_array(tp, &global_symbols); gsi_push_many_arr(tp, pdb->gsi, global_symbols.count, global_symbols.v); } ProfEnd(); ProfBegin("Build DBI Section Headers"); { for (U64 sect_idx = 1; sect_idx < image_section_table_count; sect_idx += 1) { dbi_push_section(pdb->dbi, image_section_table[sect_idx]); } } ProfEnd(); ProfBegin("Build Section Contrib Map"); { Rng1U64Array image_section_file_ranges = {0}; image_section_file_ranges.count = 0; image_section_file_ranges.v = push_array(scratch.arena, Rng1U64, image_section_table_count); Rng1U64Array image_section_virt_ranges = {0}; image_section_virt_ranges.count = image_section_table_count; image_section_virt_ranges.v = push_array(scratch.arena, Rng1U64, image_section_table_count); for (U64 i = 0; i < image_section_table_count; i += 1) { COFF_SectionHeader *sect_header = image_section_table[i]; if (~sect_header->flags & COFF_SectionFlag_CntUninitializedData) { image_section_file_ranges.v[image_section_file_ranges.count++] = rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize); } image_section_virt_ranges.v[i] = rng_1u64(sect_header->voff, sect_header->voff + sect_header->vsize); } LNK_PushDbiSecContribTaskData task = {0}; task.obj_arr = obj_arr; task.mod_arr = mod_arr; task.sc_list = push_array(scratch.arena, PDB_DbiSectionContribList, obj_count); task.image_data = image_data; task.image_section_file_ranges = image_section_file_ranges; task.image_section_virt_ranges = image_section_virt_ranges; tp_for_parallel(tp, tp_arena, obj_count, lnk_push_dbi_sec_contrib_task, &task); dbi_sec_list_concat_arr(&pdb->dbi->sec_contrib_list, obj_count, task.sc_list); } ProfEnd(); ProfBegin("Build NatVis"); { String8Array natvis_file_path_arr = str8_array_from_list(scratch.arena, &config->natvis_list); String8Array natvis_file_data_arr = lnk_read_data_from_file_path_parallel(tp, scratch.arena, config->io_flags, natvis_file_path_arr); for (U64 i = 0; i < natvis_file_data_arr.count; ++i) { String8 natvis_file_path = natvis_file_path_arr.v[i]; String8 natvis_file_data = natvis_file_data_arr.v[i]; // did we read the file? if (natvis_file_data.size == 0) { lnk_error(LNK_Warning_FileNotFound, "unable to open natvis file \"%S\"", natvis_file_path); continue; } // sanity check file extension or VS wont load NatVis String8 ext = str8_skip_last_dot(natvis_file_path); if (!str8_match(ext, str8_lit("natvis"), StringMatchFlag_CaseInsensitive)) { lnk_error(LNK_Warning_Natvis, "Visual Studio expects .natvis extension: \"%S\"", natvis_file_path); } // add natvis to PDB PDB_SrcError error = pdb_add_src(pdb->info, pdb->msf, natvis_file_path, natvis_file_data, PDB_SrcComp_NULL); if (error != PDB_SrcError_OK) { lnk_error(LNK_Error_Natvis, "%S", pdb_string_from_src_error(error)); } } } ProfEnd(); lnk_build_pdb_public_symbols(tp, tp_arena, symtab, pdb->psi); pdb_build(tp, tp_arena, pdb, string_ht); MSF_Error msf_err = msf_build(pdb->msf); if (msf_err != MSF_Error_OK) { lnk_error(LNK_Error_UnableToSerializeMsf, "unable to serialize MSF: %s", msf_error_to_string(msf_err)); } ProfBegin("Get Page Nodes"); String8List page_data_list = msf_get_page_data_nodes(tp_arena->v[0], pdb->msf); ProfEnd(); // NOTE: linker is about to exit so we can skip memory release // and let windows free memory since it does this faster #if 0 ProfBegin("Context Release"); pdb_release(&pdb); ProfEnd(); #endif scratch_end(scratch); ProfEnd(); return page_data_list; } internal U64 lnk_udt_name_hash_table_hash(String8 string) { return XXH3_64bits(string.str, string.size); } internal THREAD_POOL_TASK_FUNC(lnk_build_udt_name_hash_table_task) { LNK_BuildUDTNameHashTableTask *task = raw_task; LNK_UDTNameBucket *new_bucket = 0; for (U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) { CV_Leaf leaf = cv_debug_t_get_leaf(task->debug_t, leaf_idx); if (cv_is_udt(leaf.kind)) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if (~udt_info.props & CV_TypeProp_FwdRef) { if (!cv_is_udt_name_anon(udt_info.name)) { String8 name = cv_name_from_udt_info(udt_info); U64 hash = lnk_udt_name_hash_table_hash(name); U64 best_idx = hash % task->buckets_cap; U64 bucket_idx = best_idx; if (new_bucket == 0) { new_bucket = push_array(arena, LNK_UDTNameBucket, 1); } new_bucket->name = name; new_bucket->leaf_idx = leaf_idx; B32 is_inserted_or_updated = 0; do { retry:; LNK_UDTNameBucket *curr_bucket = task->buckets[bucket_idx]; if (curr_bucket == 0) { LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted is_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if (str8_match(curr_bucket->name, name, 0)) { // there is more than one UDT with identical name, pick most recent and ignore others if (leaf_idx < curr_bucket->leaf_idx) { LNK_UDTNameBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&task->buckets[bucket_idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { is_inserted_or_updated = 1; break; } } else { // don't need to update, more recent leaf is in the bucket break; } // another thread took the bucket... goto retry; } // advance bucket_idx = (bucket_idx + 1) % task->buckets_cap; } while (bucket_idx != best_idx); if (is_inserted_or_updated) { new_bucket = 0; } } } } } } internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_debug_t(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 *buckets_cap_out) { Temp scratch = scratch_begin(&arena->v[0], 1); LNK_BuildUDTNameHashTableTask task = {0}; task.debug_t = debug_t; task.buckets_cap = (U64)((F64)debug_t.count * 1.3); task.buckets = push_array(arena->v[0], LNK_UDTNameBucket *, task.buckets_cap); task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count); tp_for_parallel(tp, arena, tp->worker_count, lnk_build_udt_name_hash_table_task, &task); *buckets_cap_out = task.buckets_cap; scratch_end(scratch); return task.buckets; } internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup(LNK_UDTNameBucket **buckets, U64 cap, String8 name) { U64 hash = lnk_udt_name_hash_table_hash(name); U64 best_idx = hash % cap; U64 bucket_idx = best_idx; do { if (buckets[bucket_idx] == 0) { break; } if (str8_match(buckets[bucket_idx]->name, name, 0)) { return buckets[bucket_idx]; } bucket_idx = (bucket_idx + 1) % cap; } while (bucket_idx != best_idx); return 0; } internal CV_TypeIndex lnk_udt_name_hash_table_lookup_itype(LNK_UDTNameBucket **buckets, U64 cap, String8 name) { LNK_UDTNameBucket *bucket = lnk_udt_name_hash_table_lookup(buckets, cap, name); if (bucket != 0) { return CV_MinComplexTypeIndex + bucket->leaf_idx; } return 0; } internal RDIB_Type * lnk_push_converted_codeview_type(Arena *arena, RDIB_TypeChunkList *list, RDIB_Type **itype_map, CV_TypeIndex itype) { RDIB_Type *type = rdib_type_chunk_list_push(arena, list, 8196); type->final_idx = 0; type->itype = itype; Assert(itype_map[itype] == 0); itype_map[itype] = type; return type; } internal void lnk_push_basic_itypes(Arena *arena, RDIB_DataModel data_model, RDIB_Type **itype_map, RDIB_TypeChunkList *rdib_types_list) { RDI_TypeKind short_type = rdib_short_type_from_data_model(data_model); RDI_TypeKind ushort_type = rdib_unsigned_short_type_from_data_model(data_model); RDI_TypeKind int_type = rdib_int_type_from_data_model(data_model); RDI_TypeKind uint_type = rdib_unsigned_int_type_from_data_model(data_model); RDI_TypeKind long_type = rdib_long_type_from_data_model(data_model); RDI_TypeKind ulong_type = rdib_unsigned_long_type_from_data_model(data_model); RDI_TypeKind long_long_type = rdib_long_long_type_from_data_model(data_model); RDI_TypeKind ulong_long_type = rdib_unsigned_long_long_type_from_data_model(data_model); RDI_TypeKind ptr_type = rdib_pointer_size_t_type_from_data_model(data_model); struct { char * name; RDI_TypeKind kind_rdi; CV_LeafKind kind_cv; B32 make_pointer_near; B32 make_pointer_32; B32 make_pointer_64; } table[] = { { "void" , RDI_TypeKind_Void , CV_BasicType_VOID , 1, 1, 1 }, { "HRESULT" , RDI_TypeKind_Handle , CV_BasicType_HRESULT , 0, 1, 1 }, { "signed char" , RDI_TypeKind_Char8 , CV_BasicType_CHAR , 1, 1, 1 }, // TODO: we need Signed Char8 in RDI { "short" , short_type , CV_BasicType_SHORT , 1, 1, 1 }, { "long" , long_type , CV_BasicType_LONG , 1, 1, 1 }, { "long long" , long_long_type , CV_BasicType_QUAD , 1, 1, 1 }, { "__int128" , RDI_TypeKind_S128 , CV_BasicType_OCT , 1, 1, 1 }, // GCC/Clang type { "unsigned char" , RDI_TypeKind_UChar8 , CV_BasicType_UCHAR , 1, 1, 1 }, { "unsigned short" , ushort_type , CV_BasicType_USHORT , 1, 1, 1 }, { "unsigned long" , ulong_type , CV_BasicType_ULONG , 1, 1, 1 }, { "unsigned long long" , ulong_long_type , CV_BasicType_UQUAD , 1, 1, 1 }, { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UOCT , 1, 1, 1 }, // GCC/Clang type { "bool" , RDI_TypeKind_S8 , CV_BasicType_BOOL8 , 1, 1, 1 }, // TODO: we need a actual boolean type in RDI so we can format value as true/false. { "__bool16" , RDI_TypeKind_S16 , CV_BasicType_BOOL16 , 1, 1, 1 }, // not real C type { "__bool32" , RDI_TypeKind_S32 , CV_BasicType_BOOL32 , 1, 1, 1 }, // not real C type { "float" , RDI_TypeKind_F32 , CV_BasicType_FLOAT32 , 1, 1, 1 }, { "double" , RDI_TypeKind_F64 , CV_BasicType_FLOAT64 , 1, 1, 1 }, { "long double" , RDI_TypeKind_F80 , CV_BasicType_FLOAT80 , 1, 1, 1 }, { "__float128" , RDI_TypeKind_F128 , CV_BasicType_FLOAT128 , 1, 1, 1 }, // GCC/Clang type { "__float48" , RDI_TypeKind_F48 , CV_BasicType_FLOAT48 , 1, 1, 1 }, // not real C type { "__float32pp" , RDI_TypeKind_F32PP , CV_BasicType_FLOAT32PP , 1, 1, 1 }, // not real C type { "_Complex float" , RDI_TypeKind_ComplexF32 , CV_BasicType_COMPLEX32 , 0, 0, 0 }, { "_Complex double" , RDI_TypeKind_ComplexF64 , CV_BasicType_COMPLEX64 , 0, 0, 0 }, { "_Complex long double" , RDI_TypeKind_ComplexF80 , CV_BasicType_COMPLEX80 , 0, 0, 0 }, { "_Complex __float128" , RDI_TypeKind_ComplexF128, CV_BasicType_COMPLEX128 , 0, 0, 0 }, { "__int8" , RDI_TypeKind_S8 , CV_BasicType_INT8 , 1, 1, 1 }, { "__uint8" , RDI_TypeKind_U8 , CV_BasicType_UINT8 , 1, 1, 1 }, { "__int16" , RDI_TypeKind_S16 , CV_BasicType_INT16 , 1, 1, 1 }, { "__uint16" , RDI_TypeKind_U16 , CV_BasicType_UINT16 , 1, 1, 1 }, { "int" , int_type , CV_BasicType_INT32 , 1, 1, 1 }, { "unsigned int" , uint_type , CV_BasicType_UINT32 , 1, 1, 1 }, { "__int64" , RDI_TypeKind_S64 , CV_BasicType_INT64 , 1, 1, 1 }, { "__uint64" , RDI_TypeKind_U64 , CV_BasicType_UINT64 , 1, 1, 1 }, { "__int128" , RDI_TypeKind_S128 , CV_BasicType_INT128 , 1, 1, 1 }, { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UINT128 , 1, 1, 1 }, { "char" , RDI_TypeKind_Char8 , CV_BasicType_RCHAR , 1, 1, 1 }, // always ASCII { "wchar_t" , RDI_TypeKind_UChar16 , CV_BasicType_WCHAR , 1, 1, 1 }, // on windows always UTF-16 { "char8_t" , RDI_TypeKind_Char8 , CV_BasicType_CHAR8 , 1, 1, 1 }, // always UTF-8 { "char16_t" , RDI_TypeKind_Char16 , CV_BasicType_CHAR16 , 1, 1, 1 }, // always UTF-16 { "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 , 1, 1, 1 }, // always UTF-32 { "__pointer" , ptr_type , CV_BasicType_PTR , 0, 0, 0 } }; for (U64 i = 0; i < ArrayCount(table); ++i) { U64 builtin_size; if (table[i].kind_rdi == RDI_TypeKind_Void || table[i].kind_rdi == RDI_TypeKind_Handle) { builtin_size = rdi_size_from_basic_type_kind(ptr_type); } else { builtin_size = rdi_size_from_basic_type_kind(table[i].kind_rdi); } RDIB_Type *builtin = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv); builtin->kind = table[i].kind_rdi; builtin->builtin.name = str8_cstring(table[i].name); builtin->builtin.size = builtin_size; RDIB_Type **wrapper = push_array(arena, RDIB_Type *, 1); *wrapper = builtin; if (table[i].make_pointer_near) { RDIB_Type *ptr_near = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x100); ptr_near->kind = RDI_TypeKind_Ptr; ptr_near->ptr.size = rdi_size_from_basic_type_kind(ptr_type); ptr_near->ptr.type_ref = wrapper; } if (table[i].make_pointer_32) { RDIB_Type *ptr_32 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x400); ptr_32->kind = RDI_TypeKind_Ptr; ptr_32->ptr.size = 4; ptr_32->ptr.type_ref = wrapper; } if (table[i].make_pointer_64) { RDIB_Type *ptr_64 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x600); ptr_64->kind = RDI_TypeKind_Ptr; ptr_64->ptr.size = 8; ptr_64->ptr.type_ref = wrapper; } #if 0 RDIB_Type *ptr_far = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x200); RDIB_Type *ptr_huge = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x300); RDIB_Type *ptr_16_32 = lnk_push_converted_codeview_type(arena, rdib_types_list, itype_map, table[i].kind_cv | 0x500); ptr_far->kind = RDI_TypeKind_Ptr; ptr_far->ptr.size = rdi_size_from_basic_type_kind(ptr_type); ptr_far->ptr.type_ref = wrapper; ptr_huge->kind = RDI_TypeKind_Ptr; ptr_huge->ptr.size = 4; ptr_huge->ptr.type_ref = wrapper; ptr_16_32->kind = RDI_TypeKind_Ptr; ptr_16_32->ptr.size = 6; ptr_16_32->ptr.type_ref = wrapper; #endif } } internal RDIB_TypeRef lnk_rdib_type_from_itype(LNK_ConvertTypesToRDI *task, CV_TypeIndex itype) { RDIB_TypeRef result = &task->tpi_itype_map[0]; Rng1U64 tpi_range = task->itype_ranges[CV_TypeIndexSource_TPI]; if (itype < tpi_range.min) { // check for supported CodeView pointer formats: AssertAlways(BitExtract(itype, 8, 8) == /* near */ 0x1 || BitExtract(itype, 8, 8) == /* 32 bit */ 0x4 || BitExtract(itype, 8, 8) == /* 64 bit */ 0x6 || BitExtract(itype, 8, 8) == /* regular */ 0x0); } if (itype < tpi_range.max) { CV_TypeIndex final_itype = itype; // try to resovle forward reference (defn might be missing) if (itype >= tpi_range.min) { U64 leaf_idx = itype - tpi_range.min; CV_Leaf leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], leaf_idx); if (cv_is_udt(leaf.kind)) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if (udt_info.props & CV_TypeProp_FwdRef) { String8 name = cv_name_from_udt_info(udt_info); CV_TypeIndex resolved_itype = lnk_udt_name_hash_table_lookup_itype(task->udt_name_buckets, task->udt_name_bucket_cap, name); if (resolved_itype != 0) { final_itype = resolved_itype; } } } } result = &task->tpi_itype_map[final_itype]; } return result; } internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop(CV_MethodProp prop) { switch (prop) { case CV_MethodProp_Vanilla: return RDI_MemberKind_Method; case CV_MethodProp_Virtual: return RDI_MemberKind_VirtualMethod; case CV_MethodProp_Static: return RDI_MemberKind_StaticMethod; case CV_MethodProp_Friend: NotImplemented; case CV_MethodProp_Intro: return RDI_MemberKind_VirtualMethod; case CV_MethodProp_PureVirtual: return RDI_MemberKind_VirtualMethod; case CV_MethodProp_PureIntro: return RDI_MemberKind_VirtualMethod; } return RDI_MemberKind_NULL; } internal THREAD_POOL_TASK_FUNC(lnk_convert_types_to_rdi_task) { ProfBeginFunction(); LNK_ConvertTypesToRDI *task = raw_task; // upfront push output type array U64 leaf_count = dim_1u64(task->ranges[task_id]); rdib_type_chunk_list_reserve(arena, &task->rdib_types_lists[task_id], leaf_count); for(U64 leaf_idx = task->ranges[task_id].min; leaf_idx < task->ranges[task_id].max; ++leaf_idx) { U64 itype = task->itype_ranges[CV_TypeIndexSource_TPI].min + leaf_idx; CV_Leaf src = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], leaf_idx); switch (src.kind) { case CV_LeafKind_MODIFIER: { CV_LeafModifier *modifier = (CV_LeafModifier *) src.data.str; RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKind_Modifier; dst->modifier.flags = rdi_type_modifier_flags_from_cv_modifier_flags(modifier->flags); dst->modifier.type_ref = lnk_rdib_type_from_itype(task, modifier->itype); } break; case CV_LeafKind_POINTER: { CV_LeafPointer *ptr = (CV_LeafPointer *) src.data.str; CV_PointerKind ptr_kind = CV_PointerAttribs_Extract_Kind(ptr->attribs); CV_PointerMode ptr_mode = CV_PointerAttribs_Extract_Mode(ptr->attribs); U32 ptr_size = CV_PointerAttribs_Extract_Size(ptr->attribs); (void)ptr_kind; // parse ahead type chain and squash modifiers RDI_TypeModifierFlags modifier_flags = rdi_type_modifier_flags_from_cv_pointer_attribs(ptr->attribs); CV_TypeIndex next_itype; for (next_itype = ptr->itype; task->itype_ranges[CV_TypeIndexSource_TPI].min <= next_itype && next_itype < task->itype_ranges[CV_TypeIndexSource_TPI].max;) { U64 next_leaf_idx = next_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min; CV_Leaf next_leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], next_leaf_idx); if (next_leaf.kind != CV_LeafKind_MODIFIER) { break; } // parse LF_MODIFIER CV_LeafModifier *sym_modifier = (CV_LeafModifier *) next_leaf.data.str; RDI_TypeModifierFlags flags = rdi_type_modifier_flags_from_cv_modifier_flags(sym_modifier->flags); // accumulate modifier flags modifier_flags |= flags; // advance next_itype = sym_modifier->itype; } if (modifier_flags == 0) { // No modifer just generate pointer type. RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = rdi_type_kind_from_pointer(ptr->attribs, ptr_mode); dst->ptr.size = ptr_size; dst->ptr.type_ref = lnk_rdib_type_from_itype(task, ptr->itype); } else { // CodeView embeds modifier in pointer struct, we don't have an equivalent // so generate a modifier type in pointer slot and link with pointer type. RDIB_Type *ptr_type = rdib_type_chunk_list_push(arena, &task->rdib_types_lists[task_id], task->type_cap); ptr_type->kind = rdi_type_kind_from_pointer(ptr->attribs, ptr_mode); ptr_type->ptr.type_ref = lnk_rdib_type_from_itype(task, next_itype); RDIB_Type **indirect_ptr_type = push_array(arena, RDIB_Type *, 1); *indirect_ptr_type = ptr_type; RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKind_Modifier; dst->modifier.flags = modifier_flags; dst->modifier.type_ref = indirect_ptr_type; } } break; case CV_LeafKind_PROCEDURE: { CV_LeafProcedure *proc = (CV_LeafProcedure *) src.data.str; RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKind_Function; dst->func.return_type = lnk_rdib_type_from_itype(task, proc->ret_itype); dst->func.params_type = lnk_rdib_type_from_itype(task, proc->arg_itype); } break; case CV_LeafKind_MFUNCTION: { CV_LeafMFunction *mfunc = (CV_LeafMFunction *) src.data.str; B32 is_static_method = mfunc->this_itype == 0; RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); if (is_static_method) { dst->kind = RDI_TypeKindExt_StaticMethod; dst->static_method.class_type = lnk_rdib_type_from_itype(task, mfunc->class_itype); dst->static_method.return_type = lnk_rdib_type_from_itype(task, mfunc->ret_itype); dst->static_method.params_type = lnk_rdib_type_from_itype(task, mfunc->arg_itype); } else { dst->kind = RDI_TypeKind_Method; dst->method.class_type = lnk_rdib_type_from_itype(task, mfunc->class_itype); dst->method.this_type = lnk_rdib_type_from_itype(task, mfunc->this_itype); dst->method.return_type = lnk_rdib_type_from_itype(task, mfunc->ret_itype); dst->method.params_type = lnk_rdib_type_from_itype(task, mfunc->arg_itype); } } break; case CV_LeafKind_BITFIELD: { CV_LeafBitField *bitfield = (CV_LeafBitField *) src.data.str; RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKind_Bitfield; dst->bitfield.off = bitfield->pos; dst->bitfield.count = bitfield->len; dst->bitfield.value_type = lnk_rdib_type_from_itype(task, bitfield->itype); } break; case CV_LeafKind_ARRAY: { CV_LeafArray *array = (CV_LeafArray *) src.data.str; CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafArray), src.data.str + src.data.size); RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKind_Array; dst->array.entry_type = lnk_rdib_type_from_itype(task, array->entry_itype); dst->array.size = cv_u64_from_numeric(&size); } break; case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { CV_LeafStruct *udt = (CV_LeafStruct *) src.data.str; CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafStruct), src.data.str + src.data.size); String8 name; String8 link_name; if (udt->props & CV_TypeProp_HasUniqueName) { name = str8_cstring_capped(src.data.str + sizeof(CV_LeafStruct) + size.encoded_size, src.data.str + src.data.size); link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); } else { name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafStruct) + size.encoded_size, src.data.str + src.data.size); link_name = name; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_struct_lists[task_id], task->tpi_itype_map, itype); dst->udt.name = name; dst->udt.link_name = link_name; dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); dst->udt.struct_type.size = cv_u64_from_numeric(&size); dst->udt.struct_type.derived = lnk_rdib_type_from_itype(task, udt->derived_itype); dst->udt.struct_type.vtshape = lnk_rdib_type_from_itype(task, udt->vshape_itype); if (udt->props & CV_TypeProp_FwdRef) { dst->kind = src.kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct; } else { dst->kind = src.kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct; } } break; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { CV_LeafStruct2 *udt = (CV_LeafStruct2 *) src.data.str; CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafStruct2), src.data.str + src.data.size); String8 name; String8 link_name; if (udt->props & CV_TypeProp_HasUniqueName) { name = str8_cstring_capped(src.data.str + sizeof(CV_LeafStruct2) + size.encoded_size, src.data.str + src.data.size); link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); } else { name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafStruct2) + size.encoded_size, src.data.str + src.data.size); link_name = name; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_struct_lists[task_id], task->tpi_itype_map, itype); dst->udt.name = name; dst->udt.link_name = link_name; dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); dst->udt.struct_type.size = cv_u64_from_numeric(&size); dst->udt.struct_type.derived = lnk_rdib_type_from_itype(task, udt->derived_itype); dst->udt.struct_type.vtshape = lnk_rdib_type_from_itype(task, udt->vshape_itype); if (udt->props & CV_TypeProp_FwdRef) { dst->kind = src.kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct; } else { dst->kind = src.kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_Class : RDI_TypeKind_Struct; } } break; case CV_LeafKind_UNION: { CV_LeafUnion *udt = (CV_LeafUnion *) src.data.str; CV_NumericParsed size = cv_numeric_from_data_range(src.data.str + sizeof(CV_LeafUnion), src.data.str + src.data.size); String8 name; String8 link_name; if (udt->props & CV_TypeProp_HasUniqueName) { name = str8_cstring_capped(src.data.str + sizeof(CV_LeafUnion) + size.encoded_size, src.data.str + src.data.size); link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); } else { name = str8_cstring_capped_reverse(src.data.str + sizeof(CV_LeafUnion) + size.encoded_size, src.data.str + src.data.size); link_name = name; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_union_lists[task_id], task->tpi_itype_map, itype); dst->udt.name = name; dst->udt.link_name = link_name; dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); dst->udt.union_type.size = cv_u64_from_numeric(&size); if (udt->props & CV_TypeProp_FwdRef) { dst->kind = RDI_TypeKind_IncompleteUnion; } else { dst->kind = RDI_TypeKind_Union; } } break; case CV_LeafKind_ENUM: { CV_LeafEnum *udt = (CV_LeafEnum *) src.data.str; String8 name; String8 link_name; if (udt->props & CV_TypeProp_HasUniqueName) { name = str8_cstring_capped(src.data.str + sizeof(*udt), src.data.str + src.data.size); link_name = str8_cstring_capped_reverse(name.str + name.size + 1, src.data.str + src.data.size); } else { name = str8_cstring_capped_reverse(src.data.str + sizeof(*udt), src.data.str + src.data.size); link_name = name; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_enum_lists[task_id], task->tpi_itype_map, itype); dst->kind = (RDI_TypeKindExt)RDI_TypeKind_Enum; dst->udt.name = name; dst->udt.link_name = link_name; dst->udt.members = lnk_rdib_type_from_itype(task, udt->field_itype); dst->udt.enum_type.base_type = lnk_rdib_type_from_itype(task, udt->base_itype); if (udt->props & CV_TypeProp_FwdRef) { dst->kind = RDI_TypeKind_IncompleteEnum; } else { dst->kind = (RDI_TypeKindExt)RDI_TypeKind_Enum; } } break; case CV_LeafKind_ARGLIST: { CV_LeafArgList *arglist = (CV_LeafArgList *) src.data.str; CV_TypeIndex *itypes = (CV_TypeIndex *) (arglist + 1); if (arglist->count * sizeof(CV_TypeIndex) + sizeof(CV_LeafArgList) > src.data.size) { AssertAlways("error: ill-formed LF_ARGLIST"); break; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_params_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKindExt_Params; // there is no Params kind in RDI dst->params.count = arglist->count; dst->params.types = push_array(arena, RDIB_TypeRef, arglist->count); for (U64 param_idx = 0; param_idx < arglist->count; ++param_idx) { // strange way to encode variadic params, when outside LF_ARGLIST LF_NOTYPE actually means null... if (itypes[param_idx] == CV_LeafKind_NOTYPE) { dst->params.types[param_idx] = task->variadic_type_ref; } else { dst->params.types[param_idx] = lnk_rdib_type_from_itype(task, itypes[param_idx]); } } } break; case CV_LeafKind_FIELDLIST: { RDIB_UDTMemberChunkList *rdib_member_list; RDIB_TypeChunkList *rdib_member_types; B32 is_enum = sizeof(CV_LeafKind) <= src.data.size && (*(CV_LeafKind *)src.data.str == CV_LeafKind_ENUMERATE); if (is_enum) { rdib_member_list = &task->rdib_enum_members_lists[worker_id]; rdib_member_types = &task->rdib_types_enum_members_lists[worker_id]; } else { rdib_member_list = &task->rdib_udt_members_lists[worker_id]; rdib_member_types = &task->rdib_types_udt_members_lists[worker_id]; } RDIB_Type *dst = lnk_push_converted_codeview_type(arena, rdib_member_types, task->tpi_itype_map, itype); dst->kind = RDI_TypeKindExt_Members; for (U64 cursor = 0; cursor + sizeof(CV_LeafKind) <= src.data.size; ) { CV_LeafKind field_kind = *(CV_LeafKind *) (src.data.str + cursor); cursor += sizeof(field_kind); // do we have bytes to read? U64 header_size = cv_header_struct_size_from_leaf_kind(field_kind); if (cursor + header_size > src.data.size) { break; } switch (field_kind) { case CV_LeafKind_INDEX: { CV_LeafIndex *index = (CV_LeafIndex *) (src.data.str + cursor); cursor += sizeof(*index); // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB member list pointer member->kind = RDI_MemberKindExt_MemberListPointer; member->member_list_pointer = lnk_rdib_type_from_itype(task, index->itype); } break; case CV_LeafKind_MEMBER: { // prase CodeView struct/class/union data member CV_LeafMember *leaf_member = (CV_LeafMember *) (src.data.str + cursor); CV_NumericParsed offset = cv_numeric_from_data_range((U8 *)(leaf_member + 1), src.data.str + src.data.size); String8 name = str8_cstring_capped(src.data.str + cursor + sizeof(CV_LeafMember) + offset.encoded_size, src.data.str + src.data.size); cursor += sizeof(CV_LeafMember); cursor += offset.encoded_size; cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB data member member->kind = RDI_MemberKind_DataField; member->data_field.name = name; member->data_field.type_ref = lnk_rdib_type_from_itype(task, leaf_member->itype); member->data_field.offset = cv_u64_from_numeric(&offset); } break; case CV_LeafKind_STMEMBER: { // parse CodeView static member CV_LeafStMember *st_member = (CV_LeafStMember *) (src.data.str + cursor); String8 name = str8_cstring_capped(st_member + 1, src.data.str + src.data.size); cursor += sizeof(CV_LeafStMember); cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB static member member->kind = RDI_MemberKind_StaticData; member->static_data.name = name; member->static_data.type_ref = lnk_rdib_type_from_itype(task, st_member->itype); } break; case CV_LeafKind_METHOD: { // parse CodeView over-loaded method CV_LeafMethod *method = (CV_LeafMethod *) (src.data.str + cursor); String8 name = str8_cstring_capped(method + 1, src.data.str + src.data.size); cursor += sizeof(CV_LeafMethod); cursor += name.size + 1; if (contains_1u64(task->itype_ranges[CV_TypeIndexSource_TPI], method->list_itype)) { U64 method_list_leaf_idx = method->list_itype - task->itype_ranges[CV_TypeIndexSource_TPI].min; CV_Leaf method_list_leaf = cv_debug_t_get_leaf(task->types[CV_TypeIndexSource_TPI], method_list_leaf_idx); if (method_list_leaf.kind == CV_LeafKind_METHODLIST) { for (U64 cursor = 0; cursor + sizeof(CV_LeafMethodListMember) <= method_list_leaf.data.size; ) { // parse CodeView method overload info CV_LeafMethodListMember *list_member = (CV_LeafMethodListMember *) (method_list_leaf.data.str + cursor); CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(list_member->attribs); cursor += sizeof(CV_LeafMethodListMember); U32 vftable_offset = 0; if (prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { str8_deserial_read_struct(src.data, cursor, &vftable_offset); cursor += sizeof(vftable_offset); } // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB method member->kind = RDI_MemberKind_Method; member->method.kind = lnk_rdib_method_kind_from_cv_prop(prop); member->method.name = name; member->method.type_ref = lnk_rdib_type_from_itype(task, list_member->itype); member->method.vftable_offset = vftable_offset; } } else { Assert(!"error: expected LF_METHODLIST"); } } } break; case CV_LeafKind_ONEMETHOD: { // parse CodeView method CV_LeafOneMethod *one_method = (CV_LeafOneMethod *) (src.data.str + cursor); CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(one_method->attribs); cursor += sizeof(CV_LeafOneMethod); U32 vftable_offset = 0; if (prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { str8_deserial_read_struct(src.data, cursor, &vftable_offset); cursor += sizeof(vftable_offset); } String8 name = str8_cstring_capped(src.data.str + cursor, src.data.str + src.data.size); cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB member member->kind = RDI_MemberKind_Method; member->method.kind = lnk_rdib_method_kind_from_cv_prop(prop); member->method.name = name; member->method.type_ref = lnk_rdib_type_from_itype(task, one_method->itype); member->method.vftable_offset = vftable_offset; } break; case CV_LeafKind_NESTTYPE: { // parse CodeView nested type CV_LeafNestType *nest_type = (CV_LeafNestType *) (src.data.str + cursor); String8 name = str8_cstring_capped(nest_type + 1, src.data.str + src.data.size); cursor += sizeof(CV_LeafNestType); cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB nested type member member->kind = RDI_MemberKind_NestedType; member->nested_type.name = name; member->nested_type.type_ref = lnk_rdib_type_from_itype(task, nest_type->itype); } break; case CV_LeafKind_NESTTYPEEX: { // parse CodeView nested type extended CV_LeafNestTypeEx *nest_type_ex = (CV_LeafNestTypeEx *) (src.data.str + cursor); String8 name = str8_cstring_capped(nest_type_ex + 1, src.data.str + src.data.size); cursor += sizeof(CV_LeafNestTypeEx); cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB nested type member member->kind = RDI_MemberKind_NestedType; member->nested_type.name = name; member->nested_type.type_ref = lnk_rdib_type_from_itype(task, nest_type_ex->itype); } break; case CV_LeafKind_BCLASS: { // parse CodeView base class member CV_LeafBClass *bclass = (CV_LeafBClass *) (src.data.str + cursor); CV_NumericParsed offset = cv_numeric_from_data_range((U8 *)(bclass + 1), src.data.str + src.data.size); cursor += sizeof(CV_LeafBClass); cursor += offset.encoded_size; U64 offset64 = cv_u64_from_numeric(&offset); // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB base class member member->kind = RDI_MemberKind_Base; member->base_class.type_ref = lnk_rdib_type_from_itype(task, bclass->itype); member->base_class.offset = offset64; } break; case CV_LeafKind_VBCLASS: case CV_LeafKind_IVBCLASS: { // parse CodeView virtual base class CV_LeafVBClass *vbclass = (CV_LeafVBClass *) (src.data.str + cursor); CV_NumericParsed vbptr_off = cv_numeric_from_data_range(src.data.str + cursor + sizeof(*vbclass), src.data.str + src.data.size); CV_NumericParsed vtable_off = cv_numeric_from_data_range(src.data.str + cursor + sizeof(*vbclass) + vbptr_off.encoded_size, src.data.str + src.data.size); cursor += sizeof(CV_LeafVBClass); cursor += vbptr_off.encoded_size; cursor += vtable_off.encoded_size; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB virtual base class member member->kind = RDI_MemberKind_VirtualBase; member->virtual_base_class.type_ref = lnk_rdib_type_from_itype(task, vbclass->itype); member->virtual_base_class.vbptr_off = cv_u64_from_numeric(&vbptr_off); member->virtual_base_class.vtable_off = cv_u64_from_numeric(&vtable_off); } break; case CV_LeafKind_VFUNCTAB: { // parse CodeView virtual function table CV_LeafVFuncTab *vfunc_tab = (CV_LeafVFuncTab *) (src.data.str + cursor); cursor += sizeof(*vfunc_tab); // TODO: we don't have an equivalent in RDI } break; case CV_LeafKind_ENUMERATE: { // parse CodeView enum member CV_LeafEnumerate *enumerate = (CV_LeafEnumerate *) (src.data.str + cursor); CV_NumericParsed value = cv_numeric_from_data_range((U8 *) (enumerate + 1), src.data.str + src.data.size); String8 name = str8_cstring_capped(src.data.str + cursor + sizeof(CV_LeafEnumerate) + value.encoded_size, src.data.str + src.data.size); cursor += sizeof(CV_LeafEnumerate); cursor += value.encoded_size; cursor += name.size + 1; // push new node RDIB_UDTMember *member = rdib_udt_member_chunk_list_push(arena, rdib_member_list, task->udt_cap); rdib_udt_member_list_push_node(&dst->members.list, member); // fill out RDIB enum member member->kind = RDI_MemberKind_NULL; member->enumerate.name = name; member->enumerate.value = cv_u64_from_numeric(&value); } break; default: InvalidPath; } cursor = AlignPow2(cursor, 4); } } break; case CV_LeafKind_METHODLIST: { // see CV_LeafKind_METHOD } break; case CV_LeafKind_LABEL: { // ??? } break; case CV_LeafKind_VTSHAPE: { RDIB_Type *dst = lnk_push_converted_codeview_type(arena, &task->rdib_types_lists[task_id], task->tpi_itype_map, itype); dst->kind = RDI_TypeKindExt_VirtualTable; // ??? } break; case CV_LeafKind_VFTABLE: { // ??? } break; default: InvalidPath; break; } #undef push_converted_type } ProfEnd(); } internal U64 lnk_src_file_hash_cv(String8 normal_full_path, CV_C13ChecksumKind checksum_kind, String8 checksum) { XXH3_state_t state; XXH3_INITSTATE(&state); XXH3_64bits_reset(&state); XXH3_64bits_update(&state, normal_full_path.str, normal_full_path.size); XXH3_64bits_update(&state, &checksum_kind, sizeof(checksum_kind)); XXH3_64bits_update(&state, checksum.str, checksum.size); XXH64_hash_t result = XXH3_64bits_digest(&state); return result; } internal String8 lnk_normalize_src_file_path(Arena *arena, String8 file_path) { Temp scratch = scratch_begin(&arena, 1); String8 result = file_path; result = lower_from_str8(scratch.arena, result); result = path_convert_slashes(scratch.arena, result, PathStyle_UnixAbsolute); result = push_str8_copy(arena, result); scratch_end(scratch); return result; } internal LNK_SourceFileBucket * lnk_src_file_hash_table_lookup_slot(LNK_SourceFileBucket **buckets, U64 cap, U64 hash, String8 normal_path, CV_C13ChecksumKind checksum_kind, String8 checksum) { U64 best_idx = hash % cap; U64 bucket_idx = best_idx; RDIB_SourceFile temp = {0}; temp.normal_full_path = normal_path; temp.checksum_kind = checksum_kind; temp.checksum = checksum; do { if (buckets[bucket_idx] == 0) { break; } if (rdib_source_file_match(buckets[bucket_idx]->src_file, &temp, OperatingSystem_CURRENT)) { return buckets[bucket_idx]; } bucket_idx = (bucket_idx + 1) % cap; } while (bucket_idx != best_idx); return 0; } internal LNK_SourceFileBucket * lnk_src_file_insert_or_update(LNK_SourceFileBucket **buckets, U64 cap, U64 hash, LNK_SourceFileBucket *new_bucket) { LNK_SourceFileBucket *result = 0; U64 best_idx = hash % cap; U64 idx = best_idx; do { retry:; LNK_SourceFileBucket *curr_bucket = buckets[idx]; if (curr_bucket == 0) { LNK_SourceFileBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted result = curr_bucket; break; } // another thread took the bucket... goto retry; } else if (rdib_source_file_match(curr_bucket->src_file, new_bucket->src_file, OperatingSystem_CURRENT)) { // do we need to update value in the bucket? int cmp = u64_compar(&curr_bucket->obj_idx, &new_bucket->obj_idx); if (cmp <= 0) { // are we inserting bucket that was already inserterd? Assert(cmp < 0); // don't need to update, more recent value is in the bucket break; } LNK_SourceFileBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted result = compare_bucket; break; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1); idx = idx == cap ? 0 : idx; } while (idx != best_idx); return result; } internal THREAD_POOL_TASK_FUNC(lnk_count_source_files_task) { U64 unit_idx = task_id; LNK_ConvertSourceFilesToRDITask *task = raw_task; CV_DebugS debug_s = task->debug_s_arr[unit_idx]; String8List raw_chksms_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); U64 count = 0; for (String8Node *raw_chksms_n = raw_chksms_list.first; raw_chksms_n != 0; raw_chksms_n = raw_chksms_n->next) { for(U64 cursor = 0; cursor + sizeof(CV_C13Checksum) <= raw_chksms_n->string.size; ) { // parse header CV_C13Checksum *header = (CV_C13Checksum *) (raw_chksms_n->string.str + cursor); // update count ++count; // advance cursor cursor += sizeof(*header); cursor += header->len; cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); } } // update total count ins_atomic_u64_add_eval(&task->total_src_file_count, count); } internal THREAD_POOL_TASK_FUNC(lnk_insert_src_files_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 obj_idx = task_id; LNK_ConvertSourceFilesToRDITask *task = raw_task; CV_DebugS debug_s = task->debug_s_arr[obj_idx]; String8List raw_chksms_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); String8List raw_strtab_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_StringTable); if (raw_strtab_list.node_count > 1) { lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Multiple string table sub-sections, picking first one."); } if (raw_chksms_list.node_count > 1) { lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Multiple file checksum sub-sections, picking first one."); } String8 string_table = cv_string_table_from_debug_s(debug_s); LNK_SourceFileBucket *curr_bucket = 0; for (String8Node *raw_chksms_n = raw_chksms_list.first; raw_chksms_n != 0; raw_chksms_n = raw_chksms_n->next) { for (U64 cursor = 0; cursor + sizeof(CV_C13Checksum) <= raw_chksms_n->string.size; ) { // parse header CV_C13Checksum *header = (CV_C13Checksum *) (raw_chksms_n->string.str + cursor); // grab checksum String8 checksum = str8_substr(raw_chksms_n->string, rng_1u64(cursor + sizeof(CV_C13Checksum), cursor + sizeof(CV_C13Checksum) + header->len)); // grab file path Assert(header->name_off < string_table.size); String8 file_path = str8_cstring_capped(string_table.str + header->name_off, string_table.str + string_table.size); // normalize file path String8 normal_path = lnk_normalize_src_file_path(arena, file_path); // push new bucket if (curr_bucket == 0) { curr_bucket = push_array(arena, LNK_SourceFileBucket, 1); curr_bucket->src_file = push_array(arena, RDIB_SourceFile, 1); } // fill out obj idx so we can decide which source file to keep in the hash table curr_bucket->obj_idx = obj_idx; // fill out part with source file info curr_bucket->src_file->file_path = file_path; curr_bucket->src_file->normal_full_path = normal_path; curr_bucket->src_file->checksum_kind = rdi_checksum_from_cv_c13(header->kind); curr_bucket->src_file->checksum = checksum; curr_bucket->src_file->line_table_frags = 0; // insert bucket U64 normal_path_hash = lnk_src_file_hash_cv(normal_path, header->kind, checksum); LNK_SourceFileBucket *insert_result = lnk_src_file_insert_or_update(task->src_file_buckets, task->src_file_buckets_cap, normal_path_hash, curr_bucket); if (curr_bucket == insert_result) { // bucket was inserted into empty slot, reset current bucket curr_bucket = 0; } else if (curr_bucket != insert_result) { // reuse evicted bucket curr_bucket = insert_result; } // advance cursor cursor += sizeof(*header); cursor += header->len; cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); } } scratch_end(scratch); ProfEnd(); } internal RDIB_Type * lnk_find_container_type(String8 name, Rng1U64 tpi_itype_range, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap, RDIB_Type **tpi_itype_map) { CV_TypeIndex container_itype = 0; String8 delim = str8_lit("::"); U64 delim_pos = str8_find_needle_reverse(name, 0, delim, 0); if (delim_pos > 0) { U64 container_name_size = delim_pos - delim.size; String8 container_name = str8_prefix(name, container_name_size); container_itype = lnk_udt_name_hash_table_lookup_itype(udt_name_buckets, udt_name_buckets_cap, container_name); } RDIB_Type *container = 0; if (container_itype > 0) { Assert(container_itype < tpi_itype_range.max); container = tpi_itype_map[container_itype]; } return container; } internal RDIB_Type * lnk_type_from_itype(CV_TypeIndex itype, Rng1U64 tpi_itype_range, RDIB_Type **tpi_itype_map, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) { RDIB_Type *type = 0; if (itype < tpi_itype_range.max) { type = tpi_itype_map[itype]; } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds type index 0x%x in S_%S @ 0x%llx.", itype, cv_string_from_sym_kind(symbol_kind), symbol_offset); } return type; } internal U64 lnk_voff_from_sect_off(U64 sect_idx, U64 sect_off, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) { U64 voff = 0; if (sect_idx < image_sects.count) { voff = image_sects.v[sect_idx].voff + sect_off; } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", sect_idx, cv_string_from_sym_kind(symbol_kind), symbol_offset); } return voff; } internal Rng1U64 lnk_virt_range_from_sect_off_size(U64 sect_idx, U64 sect_off, U64 size, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) { Rng1U64 virt_range = {0}; if (sect_idx < image_sects.count) { U64 voff = image_sects.v[sect_idx].voff + sect_off; virt_range = rng_1u64(voff, voff + size); } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", sect_idx, cv_string_from_sym_kind(symbol_kind), symbol_offset); } return virt_range; } internal void lnk_error_on_invalid_defrange_symbol(LNK_Obj *obj, CV_Symbol symbol) { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Unable to parse symbol stream, unexpected S_%S without preceding S_LOCAL @ 0x%llx.", cv_string_from_sym_kind(symbol.kind), symbol.offset); } internal void lnk_error_on_missing_cv_frameproc(LNK_Obj *obj, CV_Symbol symbol) { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Missing S_FRAMEPROC, unable to parse S_%S @ 0x%llx.", cv_string_from_sym_kind(symbol.kind), symbol.offset); } internal THREAD_POOL_TASK_FUNC(lnk_find_obj_compiler_info_task) { ProfBeginFunction(); LNK_ConvertUnitToRDITask *task = raw_task; CV_SymbolListArray parsed_symbols = task->parsed_symbols[task_id]; LNK_CodeViewCompilerInfo *comp_info = &task->comp_info_arr[task_id]; comp_info->arch = (CV_Arch)~0u; comp_info->language = (CV_Language)~0u; comp_info->compiler_name = str8_zero(); // infer unit compiler data from S_COMPILE* which always follows S_OBJ for (U64 symbol_list_idx = 0; symbol_list_idx < parsed_symbols.count; ++symbol_list_idx) { CV_SymbolList symbol_list = parsed_symbols.v[symbol_list_idx]; for (CV_SymbolNode *symbol_n = symbol_list.first; symbol_n != 0; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; if (symbol.kind == CV_SymKind_COMPILE) { AssertAlways(sizeof(CV_SymCompile) <= symbol.data.size); CV_SymCompile *compile = (CV_SymCompile *)symbol.data.str; comp_info->arch = compile->machine; comp_info->language = CV_CompileFlags_Extract_Language(compile->flags); comp_info->compiler_name = str8_cstring_capped(compile + 1, symbol.data.str + symbol.data.size); goto exit; } else if (symbol.kind == CV_SymKind_COMPILE2) { AssertAlways(sizeof(CV_SymCompile2) <= symbol.data.size); CV_SymCompile2 *compile2 = (CV_SymCompile2 *)symbol.data.str; comp_info->arch = compile2->machine; comp_info->language = CV_Compile2Flags_Extract_Language(compile2->flags); comp_info->compiler_name = str8_cstring_capped(compile2 + 1, symbol.data.str + symbol.data.size); goto exit; } else if (symbol.kind == CV_SymKind_COMPILE3) { AssertAlways(sizeof(CV_SymCompile3) <= symbol.data.size); CV_SymCompile3 *compile3 = (CV_SymCompile3 *)symbol.data.str; comp_info->arch = compile3->machine; comp_info->language = CV_Compile3Flags_Extract_Language(compile3->flags); comp_info->compiler_name = str8_cstring_capped(compile3 + 1, symbol.data.str + symbol.data.size); goto exit; } } } exit:; LNK_Obj *obj = task->obj_arr[task_id]; // fill out unit info U64 unit_chunk_idx = task_id / task->unit_chunk_cap; U64 local_unit_idx = task_id - unit_chunk_idx * task->unit_chunk_cap; RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; dst->arch = rdi_arch_from_cv_arch(comp_info->arch); dst->unit_name = str8_skip_last_slash(obj->path); dst->compiler_name = comp_info->compiler_name; dst->source_file = str8_zero(); dst->object_file = push_str8_copy(arena, obj->path); dst->archive_file = lnk_obj_get_lib_path(obj); dst->build_path = str8_zero(); dst->language = rdi_language_from_cv_language(comp_info->language); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_convert_line_tables_to_rdi_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 unit_idx = task_id; LNK_ConvertUnitToRDITask *task = raw_task; LNK_Obj *obj = task->obj_arr[unit_idx]; CV_DebugS debug_s = task->debug_s_arr[unit_idx]; U64 unit_chunk_idx = unit_idx / task->unit_chunk_cap; U64 local_unit_idx = unit_idx - unit_chunk_idx * task->unit_chunk_cap; RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; // find sub sections String8 raw_string_table = cv_string_table_from_debug_s(debug_s); String8 raw_file_chksms = cv_file_chksms_from_debug_s(debug_s); String8List raw_lines_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); // emit line table fragments for each source file from C13 line info dst->line_table = rdib_line_table_chunk_list_push(arena, &task->line_tables[worker_id], task->line_table_cap); for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { String8 raw_lines = raw_lines_node->string; CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(scratch.arena, raw_lines, rng_1u64(0, raw_lines.size)); for (CV_C13LinesHeaderNode *lines_node = parsed_list.first; lines_node != 0; lines_node = lines_node->next) { CV_C13LinesHeader parsed_lines = lines_node->v; // parse checksum header if (parsed_lines.file_off + sizeof(CV_C13Checksum) > raw_file_chksms.size) { lnk_error_obj(LNK_Warning_IllData, obj, "Out of bounds $$FILE_CHECKSUM offset (0x%llx) in line table header.", parsed_lines.file_off); continue; } CV_C13Checksum *checksum_header = (CV_C13Checksum *) (raw_file_chksms.str + parsed_lines.file_off); if (parsed_lines.file_off + sizeof(CV_C13Checksum) + checksum_header->len > raw_file_chksms.size) { lnk_error_obj(LNK_Warning_IllData, obj, "Not enough bytes to read file checksum @ 0x%llx.", parsed_lines.file_off); continue; } String8 file_path = str8_cstring_capped(raw_string_table.str + checksum_header->name_off, raw_string_table.str + raw_string_table.size); String8 checksum_bytes = str8((U8 *) (checksum_header + 1), checksum_header->len); // read out lines if (0 == parsed_lines.sec_idx || parsed_lines.sec_idx > task->image_sects.count) { lnk_error_obj(LNK_Warning_IllData, obj, "Out of bounds section index (%u) in $$LINES; skip line info for \"%S\".", parsed_lines.sec_idx, file_path); continue; } COFF_SectionHeader *sect = &task->image_sects.v[parsed_lines.sec_idx]; CV_LineArray lines = cv_c13_line_array_from_data(arena, raw_lines, sect->voff, parsed_lines); // find source file for this line table String8 normal_path = lnk_normalize_src_file_path(scratch.arena, file_path); U64 src_file_hash = lnk_src_file_hash_cv(normal_path, checksum_header->kind, checksum_bytes); LNK_SourceFileBucket *src_file_bucket = lnk_src_file_hash_table_lookup_slot(task->src_file_buckets, task->src_file_buckets_cap, src_file_hash, normal_path, checksum_header->kind, checksum_bytes); if (src_file_bucket == 0) { lnk_error_obj(LNK_Error_UnexpectedCodePath, obj, "Unable to find source file in the hash table: \"%S\".", file_path); continue; } RDIB_SourceFile *src_file = src_file_bucket->src_file; // fill out line table fragment and atomically insert RDIB_LineTableFragment *frag = rdib_line_table_push(arena, dst->line_table); frag->src_file = src_file; frag->voffs = lines.voffs; frag->line_nums = lines.line_nums; frag->col_nums = lines.col_nums; frag->line_count = lines.line_count; frag->col_count = lines.col_count; // build list of line table fragments per file frag->next_src_file = ins_atomic_ptr_eval_assign(&src_file->line_table_frags, frag); } } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_build_inlinee_lines_accels_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); LNK_ConvertUnitToRDITask *task = raw_task; CV_DebugS debug_s = task->debug_s_arr[task_id]; String8List raw_inlinee_lines = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_InlineeLines); CV_C13InlineeLinesParsedList inlinee_lines = cv_c13_inlinee_lines_from_sub_sections(arena, raw_inlinee_lines); CV_InlineeLinesAccel *inlinee_lines_accel = cv_c13_make_inlinee_lines_accel(arena, inlinee_lines); task->inlinee_lines_accel_arr[task_id] = inlinee_lines_accel; scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_convert_symbols_to_rdi_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); LNK_ConvertUnitToRDITask *task = raw_task; LNK_CodeViewSymbolsInput symbols_input = task->symbol_inputs[task_id]; LNK_Obj *obj = task->obj_arr[symbols_input.obj_idx]; LNK_CodeViewCompilerInfo comp_info = task->comp_info_arr[symbols_input.obj_idx]; CV_InlineeLinesAccel *inlinee_lines_accel = task->inlinee_lines_accel_arr[symbols_input.obj_idx]; RDI_Arch arch_rdi = rdi_arch_from_cv_arch(comp_info.arch); struct ScopeFrame { struct ScopeFrame *prev; RDIB_Scope *scope; RDIB_Procedure *proc; CV_ProcFlags proc_flags; CV_SymFrameproc *frameproc; U64 param_count; U64 regrel32_idx; RDIB_Variable *defrange_target; }; #define push_scope_frame() do { \ struct ScopeFrame *frame; \ if (free_scope_stack != 0) { \ frame = free_scope_stack; \ SLLStackPop_N(free_scope_stack, prev); \ } else { \ frame = push_array(scratch.arena, struct ScopeFrame, 1); \ } \ SLLStackPush_N(scope_stack, frame, prev); \ } while (0) struct ScopeFrame *scope_stack = 0; struct ScopeFrame *free_scope_stack = 0; // root frame push_scope_frame(); for (CV_SymbolNode *symbol_n = symbols_input.symbol_list->first; symbol_n != 0; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; switch (symbol.kind) { case CV_SymKind_COMPILE: case CV_SymKind_COMPILE2: case CV_SymKind_COMPILE3: { // handled above } break; case CV_SymKind_INLINESITE_END: case CV_SymKind_END: { if (scope_stack != 0) { // move top frame to free stack struct ScopeFrame *free_frame = scope_stack; SLLStackPop_N(scope_stack, prev); SLLStackPush_N(free_scope_stack, free_frame, prev); } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Encountered unbalanced blocks. Unable to finish symbol parse."); goto exit; } } break; case CV_SymKind_BLOCK32: { CV_SymBlock32 *block32 = (CV_SymBlock32 *) symbol.data.str; Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(block32->sec, block32->off, block32->len, task->image_sects, obj, symbol.kind, symbol.offset); // push new scope node RDIB_Scope *scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); // fill out scope scope->container_proc = scope_stack->proc; scope->parent = scope_stack->scope; SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, scope, next_sibling); rng1u64_list_push(arena, &scope->ranges, virt_range); #if 0 if (scope->parent) { Assert(virt_range.min >= scope->parent->ranges.first->v.min); Assert(virt_range.max <= scope->parent->ranges.first->v.max); } #endif // push new scope stack frame push_scope_frame(); scope_stack->scope = scope; scope_stack->proc = scope->container_proc; scope_stack->proc_flags = scope_stack->proc_flags; scope_stack->frameproc = scope_stack->prev->frameproc; } break; case CV_SymKind_GDATA32: case CV_SymKind_LDATA32: { CV_SymData32 *data32 = (CV_SymData32 *) symbol.data.str; String8 name = str8_cstring_capped(data32 + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(data32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); RDIB_Type *container_type = lnk_find_container_type(name, task->tpi_itype_range, task->udt_name_buckets, task->udt_name_buckets_cap, task->tpi_itype_map); U64 data_voff = lnk_voff_from_sect_off(data32->sec, data32->off, task->image_sects, obj, symbol.kind, symbol.offset); B32 is_comp_gen = symbol.kind == CV_SymKind_LDATA32 && name.size == 0 && type == 0; if (!is_comp_gen) { // get link name through virtual offset look up String8 link_name = {0}; if (symbol.kind == CV_SymKind_GDATA32) { BucketNode *pair = hash_table_search_u64(task->extern_symbol_voff_ht, data_voff); if (pair != 0) { LNK_Symbol *link_symbol = pair->v.value_raw; link_name = link_symbol->name; } } // make module relative location RDIB_LocationList locations = {0}; { RDIB_EvalBytecode bytecode = {0}; rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_ModuleOff, data_voff); U64 data_size = rdib_size_from_type(type); if (data_size == 0) { data_size = max_U64; } Rng1U64List ranges = {0}; rng1u64_list_push(arena, &ranges, rng_1u64(data_voff, data_voff + data_size)); RDIB_Location location = rdib_make_location_addr_byte_stream(ranges, bytecode); rdib_location_list_push(arena, &locations, location); } RDIB_VariableChunkList *var_chunk_list = symbol.kind == CV_SymKind_GDATA32 ? &task->extern_gvars[worker_id] : &task->static_gvars[worker_id]; // push new node RDIB_Variable *gvar = rdib_variable_chunk_list_push(arena, var_chunk_list, task->symbol_chunk_cap); gvar->link_flags = symbol.kind == CV_SymKind_GDATA32 ? RDI_LinkFlag_External : 0; gvar->name = name; gvar->link_name = link_name; gvar->type = type; gvar->container_type = container_type; gvar->container_proc = scope_stack->proc; gvar->locations = locations; } } break; case CV_SymKind_LTHREAD32: case CV_SymKind_GTHREAD32: { CV_SymThread32 *thread32 = (CV_SymThread32 *) symbol.data.str; String8 name = str8_cstring_capped(thread32 + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(thread32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); RDIB_Type *container_type = lnk_find_container_type(name, task->tpi_itype_range, task->udt_name_buckets, task->udt_name_buckets_cap, task->tpi_itype_map); // make TLS offset location RDIB_LocationList locations = {0}; { RDIB_EvalBytecode bytecode = {0}; rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_TLSOff, thread32->tls_off); Rng1U64List ranges = {0}; rng1u64_list_push(arena, &ranges, rng_1u64(0, max_U64)); RDIB_Location location = rdib_make_location_addr_byte_stream(ranges, bytecode); rdib_location_list_push(arena, &locations, location); } // push new node RDIB_VariableChunkList *tvar_list = symbol.kind == CV_SymKind_GTHREAD32 ? &task->extern_tvars[worker_id] : &task->static_tvars[worker_id]; RDIB_Variable *tvar = rdib_variable_chunk_list_push(arena, tvar_list, task->symbol_chunk_cap); // fill out thread variable tvar->link_flags = symbol.kind == CV_SymKind_GTHREAD32 ? RDI_LinkFlag_External : 0; tvar->name = name; tvar->link_name = str8(0,0); tvar->type = type; tvar->container_type = container_type; tvar->container_proc = scope_stack->proc; tvar->locations = locations; } break; case CV_SymKind_LPROC32_ID: case CV_SymKind_GPROC32_ID: { AssertAlways(!"linker converts *_ID symbols in post-process step, if we ever get to this case then we have a bug in post-process step"); } break; case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol.data.str; String8 name = str8_cstring_capped(proc32 + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(proc32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(proc32->sec, proc32->off, proc32->len, task->image_sects, obj, symbol.kind, symbol.offset); // infer container type for method RDIB_Type *container_type = 0; if (type != 0) { if (type->kind == RDI_TypeKind_Method) { container_type = (RDIB_Type *) type->method.class_type; } else if (type->kind == RDI_TypeKindExt_StaticMethod) { container_type = (RDIB_Type *) type->static_method.class_type; } } // get link name through virtual offset look up String8 link_name = str8(0,0); if (symbol.kind == CV_SymKind_GPROC32) { LNK_Symbol *link_symbol = hash_table_search_u64_raw(task->extern_symbol_voff_ht, virt_range.min); if (link_symbol) { link_name = link_symbol->name; } } // scan ahead for context S_FRAMEPROC (must be defined in scope of PROC symbol) CV_SymFrameproc *frameproc = 0; { U64 depth = 1; for (CV_SymbolNode *lookahead = symbol_n->next; lookahead != 0; lookahead = lookahead->next) { if (lookahead->data.kind == CV_SymKind_FRAMEPROC) { frameproc = (CV_SymFrameproc *) lookahead->data.data.str; break; } if (cv_is_scope_symbol(lookahead->data.kind)) { ++depth; } else if (cv_is_end_symbol(lookahead->data.kind)) { --depth; if (depth == 0) { break; } } } } // push new procedure node RDIB_ProcedureChunkList *proc_list = symbol.kind == CV_SymKind_GPROC32 ? &task->extern_procs[worker_id] : &task->static_procs[worker_id]; RDIB_Procedure *proc = rdib_procedure_chunk_list_push(arena, proc_list, task->symbol_chunk_cap); // push new scope node RDIB_Scope *root_scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); root_scope->container_proc = proc; root_scope->parent = scope_stack->scope; if (scope_stack->scope != 0) { SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, root_scope, next_sibling); } rng1u64_list_push(arena, &root_scope->ranges, virt_range); // fill out procedure proc->link_flags = symbol.kind == CV_SymKind_GPROC32 ? RDI_LinkFlag_External : 0; proc->name = name; proc->link_name = link_name; proc->type = type; proc->container_type = container_type; proc->container_proc = scope_stack->proc; proc->scope = root_scope; // push scope frame push_scope_frame(); scope_stack->scope = root_scope; scope_stack->proc = proc; scope_stack->proc_flags = proc32->flags; scope_stack->frameproc = frameproc; // set number of params for procedure on scope so we can figure out which S_REGREL32 is param { B32 is_proc_scope = (scope_stack->proc->scope == scope_stack->scope); if (is_proc_scope) { RDIB_Type *params = 0; if (scope_stack->proc != 0) { RDIB_Type *proc_type = scope_stack->proc->type; if (proc_type != 0) { if (proc_type->kind == RDI_TypeKind_NULL) { // compiler generates procedures with no type for __try/__except, lambdas, and etc. } else if (proc_type->kind == RDI_TypeKind_Function) { params = (RDIB_Type *)proc_type->func.params_type; } else if (proc_type->kind == RDI_TypeKind_Method) { params = (RDIB_Type *)proc_type->method.params_type; } else if (proc_type->kind == RDI_TypeKindExt_StaticMethod) { params = (RDIB_Type *)proc_type->static_method.params_type; } else { InvalidPath; } } } if (params != 0) { AssertAlways(params->kind == RDI_TypeKindExt_Params); scope_stack->param_count = params->params.count; scope_stack->regrel32_idx = 0; } } } } break; case CV_SymKind_THUNK32: { CV_SymThunk32 *thunk32 = (CV_SymThunk32 *) symbol.data.str; String8 name = str8_cstring_capped(thunk32 + 1, symbol.data.str + symbol.data.size); Rng1U64 virt_range = lnk_virt_range_from_sect_off_size(thunk32->sec, thunk32->off, thunk32->len, task->image_sects, obj, symbol.kind, symbol.offset); // scan ahead for context S_FRAMEPROC (must be defined in scope of PROC symbol) CV_SymFrameproc *frameproc = 0; { U64 depth = 1; for (CV_SymbolNode *lookahead = symbol_n->next; lookahead != 0; lookahead = lookahead->next) { if (lookahead->data.kind == CV_SymKind_FRAMEPROC) { frameproc = (CV_SymFrameproc *) lookahead->data.data.str; break; } if (cv_is_scope_symbol(lookahead->data.kind)) { ++depth; } else if (cv_is_end_symbol(lookahead->data.kind)) { --depth; if (depth == 0) { break; } } } } // push new procedure node RDIB_ProcedureChunkList *proc_list = &task->static_procs[worker_id]; RDIB_Procedure *thunk = rdib_procedure_chunk_list_push(arena, proc_list, task->symbol_chunk_cap); // push new scope node RDIB_Scope *root_scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); root_scope->container_proc = thunk; root_scope->parent = scope_stack->scope; if (scope_stack->scope != 0) { SLLQueuePush_N(scope_stack->scope->first_child, scope_stack->scope->last_child, root_scope, next_sibling); } rng1u64_list_push(arena, &root_scope->ranges, virt_range); // fill out procedure thunk->name = name; thunk->type = 0; thunk->scope = root_scope; // push scope frame push_scope_frame(); scope_stack->scope = root_scope; scope_stack->proc = thunk; scope_stack->proc_flags = 0; scope_stack->frameproc = frameproc; } break; case CV_SymKind_REGREL32: { if (~scope_stack->proc_flags & CV_ProcFlag_OptDbgInfo) { CV_SymRegrel32 *regrel32 = (CV_SymRegrel32 *) symbol.data.str; String8 name = str8_cstring_capped(regrel32 + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(regrel32->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); RDI_LocalKind local_kind = RDI_LocalKind_Variable; B32 is_ref = 0; if (scope_stack->regrel32_idx < scope_stack->param_count) { local_kind = RDI_LocalKind_Parameter; if (type != 0) { U64 byte_size = rdib_size_from_type(type); switch (comp_info.arch) { case CV_Arch_8086: is_ref = byte_size > 4 || !IsPow2OrZero(byte_size); break; case CV_Arch_X64: is_ref = byte_size > 8 || !IsPow2OrZero(byte_size); break; default: NotImplemented; } } } // push node RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); ++scope_stack->scope->local_count; // fill out local local->link_flags = 0; local->name = name; local->kind = local_kind; local->type = type; // encode location RDI_RegCode reg_code = rdi_reg_code_from_cv(comp_info.arch, regrel32->reg); U32 value_size = 8; U32 value_pos = 0; rdib_push_location_addr_reg_off(arena, &local->locations, arch_rdi, reg_code, value_size, value_pos, (S64)regrel32->reg_off, is_ref, scope_stack->scope->ranges); // advance reg rel index ++scope_stack->regrel32_idx; } } break; case CV_SymKind_LOCAL: { CV_SymLocal *sym_local = (CV_SymLocal *) symbol.data.str; String8 name = str8_cstring_capped(sym_local + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(sym_local->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); // reset defrange target scope_stack->defrange_target = 0; if (sym_local->flags & CV_LocalFlag_Global) { // TODO: apply global modifications } else if (sym_local->flags & CV_LocalFlag_Static) { // TODO: apply local modifications } // push New node RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); ++scope_stack->scope->local_count; // fill out local local->link_flags = 0; local->kind = sym_local->flags & CV_LocalFlag_Param ? RDI_LocalKind_Parameter : RDI_LocalKind_Variable; local->name = name; local->type = type; scope_stack->defrange_target = local; } break; case CV_SymKind_FILESTATIC: { CV_SymFileStatic *file_static = (CV_SymFileStatic *) symbol.data.str; String8 name = str8_cstring_capped(file_static + 1, symbol.data.str + symbol.data.size); RDIB_Type *type = lnk_type_from_itype(file_static->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); // push New node RDIB_Variable *local = rdib_variable_chunk_list_push(arena, &task->locals[worker_id], task->symbol_chunk_cap); SLLQueuePush(scope_stack->scope->local_first, scope_stack->scope->local_last, local); ++scope_stack->scope->local_count; // fill out local local->link_flags = 0; local->kind = RDI_LocalKind_Variable; local->name = name; local->type = type; // set target for following defrange modifications scope_stack->defrange_target = local; } break; case CV_SymKind_DEFRANGE_REGISTER: { if (scope_stack->defrange_target == 0) { lnk_error_on_invalid_defrange_symbol(obj, symbol); break; } CV_SymDefrangeRegister *defrange_reg = (CV_SymDefrangeRegister *) symbol.data.str; RDI_RegCode reg_code = rdi_reg_code_from_cv(comp_info.arch, defrange_reg->reg); CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_reg + 1); U64 gap_count = (symbol.data.size - sizeof(*defrange_reg)) / sizeof(*gaps); Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_reg->range.sec, defrange_reg->range.off, defrange_reg->range.len, task->image_sects, obj, symbol.kind, symbol.offset); Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); RDIB_Location location = rdib_make_location_val_reg(ranges, reg_code); rdib_location_list_push(arena, &scope_stack->defrange_target->locations, location); } break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: { if (scope_stack->defrange_target == 0) { lnk_error_on_invalid_defrange_symbol(obj, symbol); break; } if (scope_stack->frameproc == 0) { lnk_error_on_missing_cv_frameproc(obj, symbol); break; } CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel *)symbol.data.str; CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_fprel + 1); U64 gap_count = (symbol.data.size - sizeof(*defrange_fprel)) / sizeof(gaps[0]); B32 is_local_param = scope_stack->defrange_target->kind == RDI_LocalKind_Parameter; CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(scope_stack->frameproc, is_local_param); CV_Reg fp_reg = cv_decode_fp_reg(comp_info.arch, encoded_fp_reg); RDI_RegCode fp_reg_rdi = rdi_reg_code_from_cv(comp_info.arch, fp_reg); Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_fprel->range.sec, defrange_fprel->range.off, defrange_fprel->range.len, task->image_sects, obj, symbol.kind, symbol.offset); Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); U32 value_pos = 0; U32 value_size = rdi_addr_size_from_arch(arch_rdi); rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, fp_reg_rdi, value_size, value_pos, (S64)defrange_fprel->off, 0, ranges); } break; case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: { if (scope_stack->defrange_target == 0) { lnk_error_on_invalid_defrange_symbol(obj, symbol); break; } CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister *) symbol.data.str; CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_subfield_register + 1); U64 gap_count = (symbol.data.size - sizeof(*defrange_subfield_register)) / sizeof(gaps[0]); RDI_RegCode reg_rdi = rdi_reg_code_from_cv(comp_info.arch, defrange_subfield_register->reg); U32 value_pos = CV_DefrangeSubfieldRegister_Extract_ParentOffset(defrange_subfield_register->field_offset); U32 value_size = cv_size_from_reg(comp_info.arch, defrange_subfield_register->reg) - value_pos; Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_subfield_register->range.sec, defrange_subfield_register->range.off, defrange_subfield_register->range.len, task->image_sects, obj, symbol.kind, symbol.offset); Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, reg_rdi, value_size, value_pos, 0, 0, ranges); } break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { if (scope_stack->defrange_target == 0) { lnk_error_on_invalid_defrange_symbol(obj, symbol); break; } if (scope_stack->frameproc == 0) { lnk_error_on_missing_cv_frameproc(obj, symbol); break; } CV_SymDefrangeFramepointerRelFullScope *defrange_fprelfs = (CV_SymDefrangeFramepointerRelFullScope *) symbol.data.str; B32 is_local_param = scope_stack->defrange_target->kind == RDI_LocalKind_Parameter; CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(scope_stack->frameproc, is_local_param); CV_Reg fp_reg = cv_decode_fp_reg(comp_info.arch, encoded_fp_reg); RDI_RegCode fp_reg_rdi = rdi_reg_code_from_cv(comp_info.arch, fp_reg); U32 value_size = cv_size_from_reg(comp_info.arch, fp_reg); U32 value_pos = 0; Rng1U64List ranges = scope_stack->scope->ranges; // variable is available everywhere in the scope rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, fp_reg_rdi, value_size, value_pos, (S64)defrange_fprelfs->off, 0, ranges); } break; case CV_SymKind_DEFRANGE_REGISTER_REL: { if (scope_stack->defrange_target == 0) { lnk_error_on_invalid_defrange_symbol(obj, symbol); break; } CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel *) symbol.data.str; CV_LvarAddrGap *gaps = (CV_LvarAddrGap *) (defrange_register_rel + 1); U64 gap_count = (symbol.data.size - sizeof(*defrange_register_rel)) / sizeof(gaps[0]); RDI_RegCode reg_rdi = rdi_reg_code_from_cv(comp_info.arch, defrange_register_rel->reg); U64 value_size = cv_size_from_reg(comp_info.arch, defrange_register_rel->reg); U64 value_pos = 0; Rng1U64 defrange = lnk_virt_range_from_sect_off_size(defrange_register_rel->range.sec, defrange_register_rel->range.off, defrange_register_rel->range.len, task->image_sects, obj, symbol.kind, symbol.offset); Rng1U64List ranges = cv_make_defined_range_list_from_gaps(arena, defrange, gaps, gap_count); rdib_push_location_addr_reg_off(arena, &scope_stack->defrange_target->locations, arch_rdi, reg_rdi, value_size, value_pos, (S64)defrange_register_rel->reg_off, 0, ranges); } break; case CV_SymKind_INLINESITE: { CV_SymInlineSite *sym_inline_site = (CV_SymInlineSite *) symbol.data.str; String8 binary_annots = str8_skip(symbol.data, sizeof(*sym_inline_site)); U64 parent_voff = 0; if (scope_stack != 0) { RDIB_Scope *proc_scope = scope_stack->proc->scope; Assert(proc_scope->ranges.count == 1); Rng1U64 scope_vrange = proc_scope->ranges.first->v; parent_voff = scope_vrange.min; } else { Assert(!"S_INLINESITE doesn't have a parent procedure symbol"); } // parse binary annots CV_C13InlineeLinesParsed *inlinee_parsed = cv_c13_inlinee_lines_accel_find(inlinee_lines_accel, sym_inline_site->inlinee); CV_InlineBinaryAnnotsParsed binary_annots_parsed = cv_c13_parse_inline_binary_annots(arena, parent_voff, inlinee_parsed, binary_annots); String8 name = str8_zero(); RDIB_Type *type = 0; RDIB_Type *owner = 0; if (task->ipi_itype_range.min <= sym_inline_site->inlinee && sym_inline_site->inlinee < task->ipi_itype_range.max) { U64 leaf_idx = sym_inline_site->inlinee - task->tpi_itype_range.min; CV_Leaf leaf = cv_debug_t_get_leaf(task->ipi, leaf_idx); if (leaf.kind == CV_LeafKind_MFUNC_ID) { if (sizeof(CV_LeafMFuncId) <= leaf.data.size) { CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId *) leaf.data.str; name = str8_cstring_capped_reverse(mfunc_id + 1, leaf.data.str + leaf.data.size); type = lnk_type_from_itype(mfunc_id->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); owner = lnk_type_from_itype(mfunc_id->owner_itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); } else { Assert(!"invalid leaf size"); } } else if (leaf.kind == CV_LeafKind_FUNC_ID) { if (sizeof(CV_LeafFuncId) <= leaf.data.size) { CV_LeafFuncId *func_id = (CV_LeafFuncId *) leaf.data.str; name = str8_cstring_capped_reverse(func_id + 1, leaf.data.str + leaf.data.size); type = lnk_type_from_itype(func_id->itype, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); owner = lnk_type_from_itype(func_id->scope_string_id, task->tpi_itype_range, task->tpi_itype_map, obj, symbol.kind, symbol.offset); } else { Assert(!"invalid leaf size"); } } else { Assert(!"inlinee must pointer to LF_FUNC_ID or LF_MFUNC_ID"); } } else { Assert(!"out of bounds inlinee"); } // fill out inline site RDIB_InlineSite *inline_site = rdib_inline_site_chunk_list_push(arena, &task->inline_sites[worker_id], task->inline_site_cap); inline_site->name = name; inline_site->type = type; inline_site->owner = owner; inline_site->convert_ref.ud0 = binary_annots_parsed.lines; inline_site->convert_ref.ud1 = binary_annots_parsed.lines_count; inline_site->convert_ref.ud2 = symbols_input.obj_idx; // fill out scope RDIB_Scope *scope = rdib_scope_chunk_list_push(arena, &task->scopes[worker_id], task->symbol_chunk_cap); scope->container_proc = scope_stack->proc; scope->parent = scope_stack->scope; scope->inline_site = inline_site; scope->ranges = binary_annots_parsed.code_ranges; // push new scope stack frame push_scope_frame(); scope_stack->scope = scope; scope_stack->proc = scope->container_proc; scope_stack->proc_flags = scope_stack->proc_flags; scope_stack->frameproc = scope_stack->prev->frameproc; } break; default: break; } } exit:; #undef push_scope_frame scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_convert_inline_site_line_tables_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); LNK_ConvertUnitToRDITask *task = raw_task; RDIB_InlineSiteChunk *chunk = task->inline_site_chunks[task_id]; RDIB_LineTableFragmentChunkList frag_chunk_list = {0}; for (U64 i = 0; i < chunk->count; ++i) { RDIB_InlineSite *inline_site = &chunk->v[i]; CV_LineArray *lines_arr = inline_site->convert_ref.ud0; U64 lines_count = inline_site->convert_ref.ud1; U64 obj_idx = inline_site->convert_ref.ud2; CV_DebugS debug_s = task->debug_s_arr[obj_idx]; String8 raw_string_table = cv_string_table_from_debug_s(debug_s); String8 raw_file_chksms = cv_file_chksms_from_debug_s(debug_s); if (lines_count > 0) { inline_site->line_table = rdib_line_table_chunk_list_push(arena, &task->line_tables[worker_id], task->line_table_cap); } else { inline_site->line_table = task->null_line_table; } // emit line tables for each file (yes, it is possbile to split inline site among two or more files via #include) for (U64 file_idx = 0; file_idx < lines_count; ++file_idx) { CV_LineArray lines = lines_arr[file_idx]; // prase checksum header CV_C13Checksum *checksum_header = (CV_C13Checksum *) (raw_file_chksms.str + lines.file_off); if (lines.file_off + sizeof(CV_C13Checksum) + checksum_header->len > raw_file_chksms.size) { lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], "Not enough bytes to read file checksum @ 0x%llx.", lines.file_off); continue; } String8 file_path = str8_cstring_capped(raw_string_table.str + checksum_header->name_off, raw_string_table.str + raw_string_table.size); String8 checksum_bytes = str8((U8 *) (checksum_header + 1), checksum_header->len); // find source file for this line table String8 normal_path = lnk_normalize_src_file_path(scratch.arena, file_path); U64 src_file_hash = lnk_src_file_hash_cv(normal_path, checksum_header->kind, checksum_bytes); LNK_SourceFileBucket *src_file_bucket = lnk_src_file_hash_table_lookup_slot(task->src_file_buckets, task->src_file_buckets_cap, src_file_hash, normal_path, checksum_header->kind, checksum_bytes); if (src_file_bucket == 0) { lnk_error_obj(LNK_Error_UnexpectedCodePath, task->obj_arr[obj_idx], "Unable to find source file in the hash table: \"%S\".", file_path); continue; } RDIB_SourceFile *src_file = src_file_bucket->src_file; // fill out line table fragment RDIB_LineTableFragment *frag = rdib_line_table_fragment_chunk_list_push(arena, &frag_chunk_list, chunk->count); frag->src_file = src_file; frag->voffs = lines.voffs; frag->line_nums = lines.line_nums; frag->col_nums = lines.col_nums; frag->line_count = lines.line_count; frag->col_count = lines.col_count; // build list of fragments per line table rdib_line_table_push_fragment_node(inline_site->line_table, frag); // build list of line table fragments per file frag->next_src_file = ins_atomic_ptr_eval_assign(&src_file->line_table_frags, frag); } } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(lnk_collect_obj_virtual_ranges_task) { ProfBeginFunction(); LNK_ConvertUnitToRDITask *task = raw_task; U64 unit_idx = task_id; LNK_Obj *obj = task->obj_arr[unit_idx]; U64 unit_chunk_idx = unit_idx / task->unit_chunk_cap; U64 local_unit_idx = unit_idx - unit_chunk_idx * task->unit_chunk_cap; RDIB_Unit *dst = &task->units[unit_chunk_idx].v[local_unit_idx]; dst->virt_range_count = 0; dst->virt_ranges = push_array_no_zero(arena, Rng1U64, obj->header.section_count_no_null); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (sect_header->flags & COFF_SectionFlag_LnkRemove) { continue; } if (sect_header->vsize == 0) { continue; } dst->virt_ranges[dst->virt_range_count] = rng_1u64(sect_header->voff, sect_header->voff + sect_header->vsize); ++dst->virt_range_count; } // free unused memory arena_pop(arena, sizeof(dst->virt_ranges[0]) * (obj->header.section_count_no_null - dst->virt_range_count)); ProfEnd(); } internal String8List lnk_build_rad_debug_info(TP_Context *tp, TP_Arena *tp_arena, OperatingSystem os, RDI_Arch arch, String8 image_name, String8 image_data, U64 obj_count, LNK_Obj **obj_arr, CV_DebugS *debug_s_arr, U64 total_symbol_input_count, LNK_CodeViewSymbolsInput *symbol_inputs, CV_SymbolListArray *parsed_symbols, CV_DebugT types[CV_TypeIndexSource_COUNT]) { ProfBegin("RDI"); Temp scratch = scratch_begin(tp_arena->v,tp_arena->count); RDIB_Input input = rdib_init_input(scratch.arena); COFF_SectionHeaderArray image_sects; String8 image_strtab; { PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); image_sects.count = pe.section_count; image_sects.v = (COFF_SectionHeader *)str8_substr(image_data, pe.section_table_range).str; image_strtab = str8_substr(image_data, pe.string_table_range); } ProfBegin("Top Level Info"); { U64 image_vsize = 0; for (U64 sect_idx = 0; sect_idx < image_sects.count; sect_idx++) { COFF_SectionHeader *sect = &image_sects.v[sect_idx]; image_vsize = Max(image_vsize, sect->voff + sect->vsize); } input.top_level_info.arch = arch; input.top_level_info.exe_name = image_name; input.top_level_info.exe_hash = rdi_hash(image_data.str, image_data.size); input.top_level_info.voff_max = image_vsize; input.top_level_info.producer_string = push_str8f(scratch.arena, "%s [Debug Info: CodeView]", BUILD_VERSION_STRING_LITERAL); } ProfEnd(); ProfBegin("Sections"); { input.sect_count = image_sects.count; input.sections = push_array(scratch.arena, RDIB_BinarySection, image_sects.count); for (U64 sect_idx = 0; sect_idx < image_sects.count; ++sect_idx) { COFF_SectionHeader *src = &image_sects.v[sect_idx]; RDIB_BinarySection *dst = &input.sections[sect_idx]; String8 sect_name = coff_name_from_section_header(image_strtab, src); dst->name = push_str8_copy(scratch.arena, sect_name); dst->flags = rdi_binary_section_flags_from_coff_section_flags(src->flags); dst->voff_first = src->voff; dst->voff_opl = src->voff + src->vsize; dst->foff_first = src->foff; dst->foff_opl = src->foff + src->fsize; } } ProfEnd(); // assing low and high type indices per source Rng1U64 itype_ranges[CV_TypeIndexSource_COUNT]; for (U64 i = 0; i < ArrayCount(itype_ranges); ++i) { itype_ranges[i] = rng_1u64(CV_MinComplexTypeIndex, CV_MinComplexTypeIndex + types[i].count); } ProfBegin("Convert Types"); U64 udt_name_buckets_cap; LNK_UDTNameBucket **udt_name_buckets; RDIB_Type **tpi_itype_map; { ProfBegin("Push TPI itype -> RDIB Type map"); tpi_itype_map = push_array(scratch.arena, RDIB_Type *, itype_ranges[CV_TypeIndexSource_TPI].max); ProfEnd(); ProfBegin("Push Built-in Types"); RDIB_DataModel data_model = rdib_infer_data_model(os, arch); lnk_push_basic_itypes(scratch.arena, data_model, tpi_itype_map, &input.types); ProfEnd(); Assert(tpi_itype_map[0] == 0); tpi_itype_map[0] = input.null_type; ProfBegin("Build UDT Name Hash Table"); // TODO: fix memory life-time udt_name_buckets_cap = 0; udt_name_buckets = lnk_udt_name_hash_table_from_debug_t(tp, tp_arena, types[CV_TypeIndexSource_TPI], &udt_name_buckets_cap); ProfEnd(); ProfBegin("Convert CodeView types to RDIB Types"); LNK_ConvertTypesToRDI task = {0}; task.types = types; task.type_cap = input.type_cap; task.udt_cap = input.udt_cap; task.variadic_type_ref = rdib_make_type_ref(scratch.arena, input.variadic_type); task.itype_ranges = itype_ranges; task.tpi_itype_map = tpi_itype_map; task.udt_name_bucket_cap = udt_name_buckets_cap; task.udt_name_buckets = udt_name_buckets; task.rdib_types_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_struct_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_union_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_enum_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_udt_members_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_enum_members_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_types_params_lists = push_array(scratch.arena, RDIB_TypeChunkList, tp->worker_count); task.rdib_udt_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count); task.rdib_enum_members_lists = push_array(scratch.arena, RDIB_UDTMemberChunkList, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, types[CV_TypeIndexSource_TPI].count, tp->worker_count); tp_for_parallel(tp, tp_arena, tp->worker_count, lnk_convert_types_to_rdi_task, &task); ProfEnd(); ProfBegin("Concat converted types"); rdib_type_chunk_list_concat_in_place_many (&input.types, task.rdib_types_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.struct_list, task.rdib_types_struct_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.union_list, task.rdib_types_union_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.enum_list, task.rdib_types_enum_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.param_types, task.rdib_types_params_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.member_types, task.rdib_types_udt_members_lists, tp->worker_count); rdib_type_chunk_list_concat_in_place_many (&input.enum_types, task.rdib_types_enum_members_lists, tp->worker_count); rdib_udt_member_chunk_list_concat_in_place_many(&input.udt_members, task.rdib_udt_members_lists, tp->worker_count); rdib_udt_member_chunk_list_concat_in_place_many(&input.enum_members, task.rdib_enum_members_lists, tp->worker_count); ProfEnd(); // types are converted and we can remove indirection and release 'itype_map' ProfBegin("Deref Type Refs"); rdib_deref_type_refs(tp, &input.types); rdib_deref_type_refs(tp, &input.struct_list); rdib_deref_type_refs(tp, &input.union_list); rdib_deref_type_refs(tp, &input.enum_list); rdib_deref_type_refs(tp, &input.param_types); rdib_deref_type_refs(tp, &input.member_types); rdib_deref_type_refs(tp, &input.enum_types); ProfEnd(); } ProfEnd(); // Loop over source files in objs and build a hash table // for path -> source file maps. During symbol conversion // we use the hash table to lookup source files and append // inline site line tables. U64 src_file_buckets_cap; LNK_SourceFileBucket **src_file_buckets; { ProfBegin("Build Source File Hash Table"); LNK_ConvertSourceFilesToRDITask task = {0}; task.obj_arr = obj_arr; task.debug_s_arr = debug_s_arr; ProfBegin("Count Source Files"); tp_for_parallel(tp, 0, obj_count, lnk_count_source_files_task, &task); ProfEnd(); ProfBeginDynamic("Insert Source Files [Count %llu]", task.total_src_file_count); task.src_file_buckets_cap = (U64)(task.total_src_file_count * 1.3); task.src_file_buckets = push_array(tp_arena->v[0], LNK_SourceFileBucket*, task.src_file_buckets_cap); tp_for_parallel(tp, tp_arena, obj_count, lnk_insert_src_files_task, &task); ProfEnd(); src_file_buckets_cap = task.src_file_buckets_cap; src_file_buckets = task.src_file_buckets; ProfEnd(); } // Copy source files to a contiguous array and update source file pointers // in buckets so we can do lookup and compute source file index in output array // with a pointer subtraction. ProfBegin("Source Files"); for (U64 bucket_idx = 0; bucket_idx < src_file_buckets_cap; ++bucket_idx) { LNK_SourceFileBucket *bucket = src_file_buckets[bucket_idx]; if (bucket != 0) { RDIB_SourceFile *new_src_file = rdib_source_file_chunk_list_push(scratch.arena, &input.src_files, input.src_file_chunk_cap); // restore chunk pointer after copy RDIB_SourceFileChunk *new_src_file_chunk = new_src_file->chunk; *new_src_file = *bucket->src_file; new_src_file->chunk = new_src_file_chunk; bucket->src_file = new_src_file; } } ProfEnd(); ProfBegin("Units"); { LNK_ConvertUnitToRDITask task = {0}; task.image_sects = image_sects; task.obj_arr = obj_arr; task.debug_s_arr = debug_s_arr; task.ipi = types[CV_TypeIndexSource_IPI]; task.symbol_inputs = symbol_inputs; task.parsed_symbols = parsed_symbols; task.ipi_itype_range = itype_ranges[CV_TypeIndexSource_IPI]; task.tpi_itype_range = itype_ranges[CV_TypeIndexSource_TPI]; task.tpi_itype_map = tpi_itype_map; task.src_file_buckets_cap = src_file_buckets_cap; task.src_file_buckets = src_file_buckets; task.udt_name_buckets = udt_name_buckets; task.udt_name_buckets_cap = udt_name_buckets_cap; task.src_file_chunk_cap = input.src_file_chunk_cap; task.line_table_cap = input.line_table_cap; task.symbol_chunk_cap = input.symbol_chunk_cap; task.unit_chunk_cap = input.unit_chunk_cap; task.inline_site_cap = input.inline_site_cap; task.null_line_table = input.null_line_table; task.extern_symbol_voff_ht = hash_table_init(scratch.arena, 256); task.units = rdib_unit_chunk_list_reserve_ex(scratch.arena, &input.units, input.unit_chunk_cap, obj_count); task.scopes = push_array(scratch.arena, RDIB_ScopeChunkList, tp->worker_count); task.locals = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); task.extern_gvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); task.static_gvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); task.extern_tvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); task.static_tvars = push_array(scratch.arena, RDIB_VariableChunkList, tp->worker_count); task.extern_procs = push_array(scratch.arena, RDIB_ProcedureChunkList, tp->worker_count); task.static_procs = push_array(scratch.arena, RDIB_ProcedureChunkList, tp->worker_count); task.inline_sites = push_array(scratch.arena, RDIB_InlineSiteChunkList, tp->worker_count); task.line_tables = push_array(scratch.arena, RDIB_LineTableChunkList, tp->worker_count); ProfBegin("Gather Compiler Info"); task.comp_info_arr = push_array(scratch.arena, LNK_CodeViewCompilerInfo, obj_count); tp_for_parallel(tp, tp_arena, obj_count, lnk_find_obj_compiler_info_task, &task); ProfEnd(); ProfBegin("Convert Line Tables"); tp_for_parallel(tp, tp_arena, obj_count, lnk_convert_line_tables_to_rdi_task, &task); ProfEnd(); ProfBegin("Build Inlinee Lines Accels"); task.inlinee_lines_accel_arr = push_array(scratch.arena, CV_InlineeLinesAccel *, obj_count); tp_for_parallel(tp, tp_arena, obj_count, lnk_build_inlinee_lines_accels_task, &task); ProfEnd(); ProfBegin("Convert Symbols"); tp_for_parallel(tp, tp_arena, total_symbol_input_count, lnk_convert_symbols_to_rdi_task, &task); ProfEnd(); ProfBegin("Convert Inline Sites Line Tables"); rdib_inline_site_chunk_list_concat_in_place_many(&input.inline_sites, task.inline_sites, tp->worker_count); task.inline_site_chunks = rdib_array_from_inline_site_chunk_list(scratch.arena, input.inline_sites); tp_for_parallel(tp, tp_arena, input.inline_sites.count, lnk_convert_inline_site_line_tables_task, &task); ProfEnd(); ProfBegin("Collect Units Virtual Ranges"); tp_for_parallel(tp, tp_arena, obj_count, lnk_collect_obj_virtual_ranges_task, &task); ProfEnd(); rdib_line_table_chunk_list_concat_in_place_many(&input.line_tables, task.line_tables, tp->worker_count); rdib_scope_chunk_list_concat_in_place_many(&input.scopes, task.scopes, tp->worker_count); rdib_variable_chunk_list_concat_in_place_many(&input.locals, task.locals, tp->worker_count); rdib_variable_chunk_list_concat_in_place_many(&input.extern_gvars, task.extern_gvars, tp->worker_count); rdib_variable_chunk_list_concat_in_place_many(&input.static_gvars, task.static_gvars, tp->worker_count); rdib_variable_chunk_list_concat_in_place_many(&input.extern_tvars, task.extern_tvars, tp->worker_count); rdib_variable_chunk_list_concat_in_place_many(&input.static_tvars, task.static_tvars, tp->worker_count); rdib_procedure_chunk_list_concat_in_place_many(&input.extern_procs, task.extern_procs, tp->worker_count); rdib_procedure_chunk_list_concat_in_place_many(&input.static_procs, task.static_procs, tp->worker_count); } ProfEnd(); String8List rdi_data = rdib_finish(tp, tp_arena, &input); scratch_end(scratch); ProfEnd(); return rdi_data; } ================================================ FILE: src/linker/lnk_debug_info.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once // --- Code View Input --------------------------------------------------------- typedef struct LNK_PchInfo { CV_TypeIndex ti_lo; CV_TypeIndex ti_hi; U64 debug_p_obj_idx; } LNK_PchInfo; typedef struct LNK_CodeViewSymbolsInput { U64 obj_idx; CV_SymbolList *symbol_list; String8 raw_symbols; } LNK_CodeViewSymbolsInput; typedef struct LNK_CodeViewInput { U64 count; U64 internal_count; U64 external_count; U64 type_server_count; String8 *type_server_path_arr; // [type_server_count] String8 *type_server_data_arr; // [type_server_count] U64List *ts_to_obj_arr; // [type_server_count] LNK_Obj **obj_arr; // [count] LNK_PchInfo *pch_arr; // [count] CV_DebugS *debug_s_arr; // [count] CV_DebugT *debug_p_arr; // [count] CV_DebugT *debug_t_arr; // [count] CV_DebugT *merged_debug_t_p_arr; // [count] U64 total_symbol_input_count; LNK_CodeViewSymbolsInput *symbol_inputs; // [total_symbol_input_count] CV_SymbolListArray *parsed_symbols; // [count] LNK_Obj **internal_obj_arr; // [internal_count] CV_DebugS *internal_debug_s_arr; // [internal_count] CV_DebugT *internal_debug_t_arr; // [internal_count] CV_DebugT *internal_debug_p_arr; // [internal_count] U64 internal_total_symbol_input_count; LNK_CodeViewSymbolsInput *internal_symbol_inputs; // [internal_total_symbol_input_count] CV_SymbolListArray *internal_parsed_symbols; // [internal_count] LNK_Obj **external_obj_arr; // [external_count] CV_DebugS *external_debug_s_arr; // [external_count] CV_DebugT *external_debug_t_arr; // [external_count] CV_DebugT *external_debug_p_arr; // [external_count] U64 external_total_symbol_input_count; LNK_CodeViewSymbolsInput *external_symbol_inputs; // [exteranl_total_symbol_input_count] CV_SymbolListArray *external_parsed_symbols; // [external_count] Rng1U64 **external_ti_ranges; // [type_server_count] CV_DebugT **external_leaves; // [type_server_count] U64 *external_obj_to_ts_idx_arr; // [external_count] Rng1U64 external_obj_range; } LNK_CodeViewInput; // --- Leaf Ref ---------------------------------------------------------------- typedef enum { LNK_LeafLocType_Internal, LNK_LeafLocType_External, LNK_LeafLocType_Count } LNK_LeafLocType; #define LNK_LeafRefFlag_LocIdxExternal (1 << 31) #define LNK_LeafRefFlag_LeafIdxIPI (1 << 31) typedef struct { U32 enc_loc_idx; U32 enc_leaf_idx; } LNK_LeafRef; typedef struct LNK_LeafRange { struct LNK_LeafRange *next; Rng1U64 range; CV_DebugT *debug_t; } LNK_LeafRange; typedef struct LNK_LeafRangeList { U64 count; LNK_LeafRange *first; LNK_LeafRange *last; } LNK_LeafRangeList; typedef struct { LNK_LeafRef leaf_ref; CV_TypeIndex type_index; } LNK_LeafBucket; typedef struct { U64 count; LNK_LeafBucket **v; } LNK_LeafBucketArray; typedef struct { U64 cap; LNK_LeafBucket **bucket_arr; } LNK_LeafHashTable; typedef union { struct { U128Array **internal_hashes; U128Array **external_hashes; }; U128Array **v[CV_TypeIndexSource_COUNT]; } LNK_LeafHashes; // --- Symbol Parsing Tasks ---------------------------------------------------- typedef struct { LNK_Obj **obj_arr; String8List *sect_list_arr; CV_DebugS *debug_s_arr; } LNK_ParseDebugSTaskData; typedef struct { LNK_Obj **obj_arr; String8Array *data_arr_arr; } LNK_CheckDebugTSigTaskData; typedef struct { LNK_Obj **obj_arr; String8Array *data_arr_arr; CV_DebugT *debug_t_arr; } LNK_ParseDebugTTaskData; typedef struct { String8Array data_arr; MSF_Parsed **msf_parse_arr; } LNK_MsfParsedFromDataTask; typedef struct { CV_TypeServerInfo *ts_info_arr; MSF_Parsed **msf_parse_arr; Rng1U64 **external_ti_ranges; CV_DebugT **external_leaves; B8 *is_corrupted; } LNK_GetExternalLeavesTask; // --- Leaf Deduping Tasks ----------------------------------------------------- typedef struct { LNK_LeafRangeList *leaf_ranges_per_task; U64 **count_arr_arr; } LNK_CountPerSourceLeafTask; typedef struct { LNK_CodeViewInput *input; LNK_LeafHashes *hashes; Arena **fixed_arenas; CV_DebugT *debug_t_arr; } LNK_LeafHasherTask; typedef struct { LNK_CodeViewInput *input; LNK_LeafHashes *hashes; LNK_LeafHashTable *leaf_ht_arr; CV_DebugT *debug_t_arr; } LNK_LeafDedupInternal; typedef struct { LNK_CodeViewInput *input; LNK_LeafHashes *hashes; LNK_LeafHashTable *leaf_ht_arr; CV_TypeIndexSource dedup_ti_source; } LNK_LeafDedupExternal; typedef struct { LNK_LeafHashTable *ht; U64 *count_arr; Rng1U64 *range_arr; U64 *offset_arr; LNK_LeafBucketArray result; } LNK_GetPresentBucketsTask; typedef struct { U64 loc_idx_bit_count_0; U64 loc_idx_bit_count_1; U64 loc_idx_bit_count_2; U64 counts_max; U32 **counts_arr; Rng1U64 *ranges; LNK_LeafBucket **dst; LNK_LeafBucket **src; U64 loc_idx_max; U64 pass_idx; } LNK_LeafRadixSortTask; typedef struct { U32 *counts; U32 *offsets; LNK_LeafBucket **dst; LNK_LeafBucket **src; Rng1U64 *ranges; } LNK_LeafLocRadixSortTask; typedef struct { Rng1U64 *range_arr; CV_TypeIndex min_type_index; LNK_LeafBucketArray bucket_arr; } LNK_AssignTypeIndicesTask; typedef struct { LNK_CodeViewInput *input; LNK_LeafBucket **bucket_arr; U8 **raw_leaf_arr; Rng1U64 *range_arr; } LNK_UnbucketRawLeavesTask; typedef struct { Rng1U64 *ranges; LNK_CodeViewInput *input; LNK_LeafHashes *hashes; LNK_LeafHashTable *leaf_ht_arr; CV_SymbolList *symbol_list_arr; Arena **arena_arr; } LNK_PatchSymbolTypesTask; typedef struct { LNK_CodeViewInput *input; LNK_LeafHashes *hashes; LNK_LeafHashTable *leaf_ht_arr; CV_DebugS *debug_s_arr; } LNK_PatchInlinesTask; typedef struct { LNK_CodeViewInput *input; LNK_LeafHashes *hashes; LNK_LeafHashTable *leaf_ht_arr; LNK_LeafBucket **bucket_arr; Rng1U64 *range_arr; Arena **fixed_arena_arr; } LNK_PatchLeavesTask; // --- Code View Processing Trasks --------------------------------------------- typedef struct { String8List *data_list_arr; } LNK_ProcessedCodeViewC11Data; typedef struct { String8List *data_list_arr; String8List *source_file_names_list_arr; } LNK_ProcessedCodeViewC13Data; typedef struct { LNK_CodeViewSymbolsInput *inputs; } LNK_ParseCVSymbolsTaskData; typedef struct { U64 total_symbol_input_count; LNK_CodeViewSymbolsInput *symbol_inputs; CV_SymbolListArray *parsed_symbols; PDB_DbiModule **mod_arr; String8List *symbol_data_arr; CV_SymbolList *gsi_list_arr; } LNK_ProcessSymDataTaskData; typedef struct { CV_DebugS *debug_s_arr; MSF_Context *msf; PDB_DbiModule **dbi_mod_arr; String8List *c13_data_arr; String8List *source_file_names_list_arr; U64 string_data_base_offset; CV_StringHashTable string_ht; } LNK_ProcessC13DataTask; typedef struct { MSF_Context *msf; PDB_DbiModule **mod_arr; String8List *symbol_data_arr; String8List *c11_data_list_arr; String8List *c13_data_list_arr; String8List *globrefs_arr; } LNK_WriteModuleDataTask; typedef struct { LNK_Obj **obj_arr; PDB_DbiModule **mod_arr; PDB_DbiSectionContribList *sc_list; String8 image_data; Rng1U64Array image_section_file_ranges; Rng1U64Array image_section_virt_ranges; } LNK_PushDbiSecContribTaskData; typedef struct { U32Array *hash_arr_arr; CV_SymbolList *list_arr; } LNK_HashCVSymbolListTask; typedef struct { U64 *hash_arr; CV_SymbolNode **arr; Rng1U64 *range_arr; } LNK_CvSymbolPtrArrayHasher; typedef struct { LNK_SymbolHashTrieChunkList *chunk_lists; CV_SymbolList *pub_list_arr; Rng1U64 *symbol_ranges; PDB_GsiContext *gsi; CV_SymbolPtrArray symbols; U32 *hashes; } LNK_BuildPublicSymbolsTask; typedef struct { CV_TypeIndex ipi_min_type_index; CV_DebugT ipi_types; LNK_CodeViewSymbolsInput *symbol_inputs; CV_SymbolListArray *parsed_symbols; } LNK_PostProcessCvSymbolsTask; typedef struct { Rng1U64 *range_arr; CV_SymbolPtrNode **bucket_arr; CV_SymbolPtrNode **out_arr; U64 *out_count_arr; } LNK_GsiDeduper; typedef struct { Rng1U64 *range_arr; CV_SymbolPtrNode **bucket_arr; U64 *symbol_base_arr; CV_SymbolNode **symbol_arr; } LNK_GsiUnbucket; typedef struct { CV_DebugT debug_t; Rng1U64 *ranges; U64 hash_length; B32 make_map; TP_Arena *map_arena; String8List *maps; } LNK_TypeNameReplacer; // --- RAD Debug Info ---------------------------------------------------------- typedef struct { String8 name; U64 leaf_idx; } LNK_UDTNameBucket; typedef struct { CV_DebugT debug_t; Rng1U64 *ranges; U64 buckets_cap; LNK_UDTNameBucket **buckets; } LNK_BuildUDTNameHashTableTask; typedef struct { CV_DebugT debug_t; CV_TypeIndex ti_lo; Rng1U64 *ranges; U64 udt_name_buckets_cap; LNK_UDTNameBucket **udt_name_buckets; CV_TypeIndex *fwdmap; } LNK_BuildUDTFwdMapTask; // --- RDI Conversion Tasks ---------------------------------------------------- typedef struct { CV_DebugT *types; U64 type_cap; U64 udt_cap; RDIB_TypeRef variadic_type_ref; Rng1U64 *itype_ranges; U64 udt_name_bucket_cap; LNK_UDTNameBucket **udt_name_buckets; RDIB_Type **tpi_itype_map; RDIB_TypeChunkList *rdib_types_lists; RDIB_TypeChunkList *rdib_types_struct_lists; RDIB_TypeChunkList *rdib_types_union_lists; RDIB_TypeChunkList *rdib_types_enum_lists; RDIB_TypeChunkList *rdib_types_params_lists; RDIB_TypeChunkList *rdib_types_udt_members_lists; RDIB_TypeChunkList *rdib_types_enum_members_lists; RDIB_UDTMemberChunkList *rdib_udt_members_lists; RDIB_UDTMemberChunkList *rdib_enum_members_lists; Rng1U64 *ranges; } LNK_ConvertTypesToRDI; typedef struct { U64 obj_idx; RDIB_SourceFile *src_file; } LNK_SourceFileBucket; typedef struct { LNK_Obj **obj_arr; CV_DebugS *debug_s_arr; U64 total_src_file_count; LNK_SourceFileBucket **src_file_buckets; U64 src_file_buckets_cap; } LNK_ConvertSourceFilesToRDITask; typedef struct { CV_Arch arch; CV_Language language; String8 compiler_name; } LNK_CodeViewCompilerInfo; typedef struct { COFF_SectionHeaderArray image_sects; LNK_Obj **obj_arr; CV_DebugS *debug_s_arr; CV_DebugT ipi; LNK_CodeViewSymbolsInput *symbol_inputs; CV_SymbolListArray *parsed_symbols; Rng1U64 ipi_itype_range; Rng1U64 tpi_itype_range; RDIB_Type **tpi_itype_map; U64 src_file_buckets_cap; LNK_SourceFileBucket **src_file_buckets; LNK_UDTNameBucket **udt_name_buckets; U64 line_table_cap; U64 udt_name_buckets_cap; U64 src_file_chunk_cap; U64 symbol_chunk_cap; U64 unit_chunk_cap; U64 inline_site_cap; RDIB_LineTable *null_line_table; HashTable *extern_symbol_voff_ht; LNK_CodeViewCompilerInfo *comp_info_arr; CV_InlineeLinesAccel **inlinee_lines_accel_arr; RDIB_InlineSiteChunk **inline_site_chunks; // output RDIB_UnitChunk *units; RDIB_VariableChunkList *locals; RDIB_ScopeChunkList *scopes; RDIB_VariableChunkList *extern_gvars; RDIB_VariableChunkList *static_gvars; RDIB_VariableChunkList *extern_tvars; RDIB_VariableChunkList *static_tvars; RDIB_ProcedureChunkList *extern_procs; RDIB_ProcedureChunkList *static_procs; RDIB_InlineSiteChunkList *inline_sites; RDIB_LineTableChunkList *line_tables; } LNK_ConvertUnitToRDITask; // --- CodeView ---------------------------------------------------------------- internal CV_DebugS * lnk_parse_debug_s_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *sect_list_arr); internal CV_DebugT * lnk_parse_debug_t_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *debug_t_list_arr); internal CV_SymbolList * lnk_cv_symbol_list_arr_from_debug_s_arr(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr); internal LNK_PchInfo * lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols, String8List alt_pch_dirs); internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, String8List alt_pch_dirs, U64 objs_count, LNK_Obj **objs); internal LNK_LeafRef lnk_leaf_ref(U32 idx, U32 leaf_idx); internal LNK_LeafRef lnk_obj_leaf_ref(U32 obj_idx, U32 leaf_idx); internal LNK_LeafRef lnk_ts_leaf_ref(CV_TypeIndexSource ti_source, U32 ts_idx, U32 leaf_idx); internal int lnk_leaf_ref_compare(LNK_LeafRef a, LNK_LeafRef b); internal LNK_LeafLocType lnk_loc_type_from_leaf_ref(LNK_LeafRef leaf_ref); internal LNK_LeafLocType lnk_loc_type_from_obj_idx(LNK_CodeViewInput *input, U64 obj_idx); internal U64 lnk_loc_idx_from_obj_idx(LNK_CodeViewInput *input, U64 obj_idx); internal CV_TypeIndex lnk_ti_lo_from_loc(LNK_CodeViewInput *input, LNK_LeafLocType loc_type, U64 loc_idx, CV_TypeIndexSource ti_source); internal CV_TypeIndex lnk_ti_lo_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref); internal String8 lnk_data_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref); internal CV_Leaf lnk_cv_leaf_from_leaf_ref(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref); internal U128 lnk_hash_from_leaf_ref(LNK_LeafHashes *hashes, LNK_LeafRef leaf_ref); internal LNK_LeafRef lnk_leaf_ref_from_loc_idx_and_ti(LNK_CodeViewInput *input, LNK_LeafLocType loc_type, CV_TypeIndexSource ti_source, U64 loc_idx, CV_TypeIndex obj_ti); internal B32 lnk_match_leaf_ref(LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef a, LNK_LeafRef b); internal B32 lnk_match_leaf_ref_deep(Arena *arena, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef a, LNK_LeafRef b); internal U128 lnk_hash_cv_leaf(Arena *arena, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafLocType loc_type, U32 loc_idx, Rng1U64 *ti_ranges, CV_TypeIndex curr_ti, CV_Leaf leaf, CV_TypeIndexInfoList ti_info_list); internal void lnk_hash_cv_leaf_deep(Arena *arena, LNK_CodeViewInput *input, Rng1U64 *ti_ranges, CV_DebugT *leaves, LNK_LeafHashes *hashes, LNK_LeafLocType loc_type, U32 loc_idx, CV_TypeIndexInfoList ti_info_list, String8 data); internal LNK_LeafBucket * lnk_leaf_hash_table_insert_or_update(LNK_LeafHashTable *leaf_ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, U128 hash, LNK_LeafBucket *new_bucket); internal LNK_LeafBucket * lnk_leaf_hash_table_search(LNK_LeafHashTable *ht, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafRef leaf_ref); internal void lnk_cv_debug_t_count_leaves_per_source(TP_Context *tp, U64 count, CV_DebugT *debug_t_arr, U64 *per_source_count_arr); internal void lnk_hash_debug_t_arr(TP_Context *tp, Arena *arena, U64 obj_count, CV_DebugT *debug_t_arr, U128Array *hash_arr_arr); internal LNK_LeafBucketArray lnk_present_bucket_array_from_leaf_hash_table(TP_Context *tp, Arena *arena, LNK_LeafHashTable *ht); internal void lnk_leaf_bucket_array_sort_radix_subset_parallel(TP_Context *tp, U64 bucket_count, U64 loc_idx_max, LNK_LeafBucket **dst, LNK_LeafBucket **src); internal void lnk_leaf_bucket_array_sort_radix_parallel(TP_Context *tp, LNK_LeafBucketArray arr, U64 obj_count, U64 type_server_count); internal void lnk_assign_type_indices(TP_Context *tp, LNK_LeafBucketArray bucket_arr, CV_TypeIndex min_type_index); internal void lnk_patch_symbols(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr); internal void lnk_patch_inlines(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr, U64 obj_count, CV_DebugS *debug_s_arr); internal void lnk_patch_leaves(TP_Context *tp, LNK_CodeViewInput *input, LNK_LeafHashes *hashes, LNK_LeafHashTable *leaf_ht_arr, LNK_LeafBucketArray bucket_arr); internal String8Node * lnk_copy_raw_leaf_arr_to_type_server(TP_Context *tp, CV_DebugT types, PDB_TypeServer *type_server); internal CV_DebugT * lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input); internal void lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name); // --- RAD Debug info ---------------------------------------------------------- internal U64 lnk_udt_name_hash_table_hash(String8 string); internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_debug_t(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 *buckets_cap_out); internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup(LNK_UDTNameBucket **buckets, U64 cap, String8 name); internal CV_TypeIndex * lnk_build_udt_fwdmap(TP_Context *tp, Arena *arena, CV_DebugT debug_t, CV_TypeIndex ti_lo, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap); internal RDIB_TypeRef lnk_rdib_type_from_itype(LNK_ConvertTypesToRDI *task, CV_TypeIndex itype); internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop(CV_MethodProp prop); internal LNK_SourceFileBucket * lnk_src_file_hash_table_hash(String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes); internal LNK_SourceFileBucket * lnk_src_file_hash_table_lookup_slot(LNK_SourceFileBucket **src_file_buckets, U64 src_file_buckets_cap, U64 hash, String8 file_path, CV_C13ChecksumKind checksum_kind, String8 checksum_bytes); internal String8List lnk_build_rad_debug_info(TP_Context *tp, TP_Arena *tp_arena, OperatingSystem os, RDI_Arch arch, String8 image_name, String8 image_data, U64 obj_count, LNK_Obj **obj_arr, CV_DebugS *debug_s_arr, U64 total_symbol_input_count, LNK_CodeViewSymbolsInput *symbol_inputs, CV_SymbolListArray *parsed_symbols, CV_DebugT types[CV_TypeIndexSource_COUNT]); // --- PDB --------------------------------------------------------------------- internal LNK_ProcessedCodeViewC11Data lnk_process_c11_data(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr, U64 string_data_base_offset, CV_StringHashTable string_ht, MSF_Context *msf, PDB_DbiModule **mod_arr); internal LNK_ProcessedCodeViewC13Data lnk_process_c13_data(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr, U64 string_data_base_offset, CV_StringHashTable string_ht, MSF_Context *msf, PDB_DbiModule **mod_arr); internal U64 * lnk_hash_cv_symbol_ptr_arr(TP_Context *tp, Arena *arena, CV_SymbolPtrArray arr); internal CV_SymbolPtrArray lnk_dedup_gsi_symbols(TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 obj_count, CV_SymbolList *symbol_list_arr); internal void lnk_build_pdb_public_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, PDB_PsiContext *psi); internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, U64 obj_count, LNK_Obj **obj_arr, CV_DebugS *debug_s_arr, U64 total_symbol_input_count, LNK_CodeViewSymbolsInput *symbol_inputs, CV_SymbolListArray *parsed_symbols, CV_DebugT types[CV_TypeIndexSource_COUNT]); // --- RAD Debug Info ---------------------------------------------------------- internal U64 lnk_udt_name_hash_table_hash(String8 string); internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_debug_t(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 *buckets_cap_out); internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup(LNK_UDTNameBucket **buckets, U64 cap, String8 name); internal CV_TypeIndex * lnk_build_udt_fwdmap(TP_Context *tp, Arena *arena, CV_DebugT debug_t, CV_TypeIndex ti_lo, LNK_UDTNameBucket **udt_name_buckets, U64 udt_name_buckets_cap); internal void lnk_init_rdib_itype_map(Arena *arena, RDI_Arch arch, RDIB_Type **itype_map, RDIB_TypeChunkList *rdib_types_list); internal RDIB_TypeRef lnk_rdib_type_from_itype(LNK_ConvertTypesToRDI *task, CV_TypeIndex itype); internal RDI_MemberKind lnk_rdib_method_kind_from_cv_prop(CV_MethodProp prop); ================================================ FILE: src/linker/lnk_error.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) static LNK_ErrorMode g_error_mode_arr[LNK_Error_Count]; static LNK_ErrorCodeStatus g_error_code_status_arr[LNK_Error_Count]; static B32 g_log_status[LNK_Log_Count]; internal void lnk_exit(int code) { exit(code); } internal void lnk_init_error_handler(void) { for (int i = LNK_Error_StopFirst; i < LNK_Error_StopLast; ++i) { g_error_mode_arr[i] = LNK_ErrorMode_Stop; } for (int i = LNK_Error_First; i < LNK_Error_Last; ++i) { g_error_mode_arr[i] = LNK_ErrorMode_Continue; } for (int i = LNK_Warning_First; i < LNK_Warning_Last; ++i) { g_error_mode_arr[i] = LNK_ErrorMode_Warn; } } internal String8 lnk_string_from_error_mode(LNK_ErrorMode mode) { switch (mode) { case LNK_ErrorMode_Ignore: return str8_lit("Ignore"); case LNK_ErrorMode_Continue: return str8_lit("Error"); case LNK_ErrorMode_Stop: return str8_lit("Error"); case LNK_ErrorMode_Warn: return str8_lit("Warning"); } return str8_zero(); } internal void lnk_errorfv(LNK_ErrorCode code, char *fmt, va_list args) { if (g_error_mode_arr[code] == LNK_ErrorMode_Ignore) { return; } if (lnk_is_error_code_ignored(code)) { return; } Temp scratch = scratch_begin(0,0); String8 message = push_str8fv(scratch.arena, fmt, args); String8 string = push_str8f(scratch.arena, "%S(%03d): %S\n", lnk_string_from_error_mode(g_error_mode_arr[code]), code, message); fprintf(stderr, "%.*s", str8_varg(string)); scratch_end(scratch); if (g_error_mode_arr[code] == LNK_ErrorMode_Stop) { lnk_exit(code); } } internal void lnk_error(LNK_ErrorCode code, char *fmt, ...) { va_list args; va_start(args, fmt); lnk_errorfv(code, fmt, args); va_end(args); } internal void lnk_error_with_loc_fv(LNK_ErrorCode code, String8 obj_path, String8 lib_path, char *fmt, va_list args) { Temp scratch = scratch_begin(0, 0); String8 text = push_str8fv(scratch.arena, fmt, args); if (obj_path.size) { if (lib_path.size) { lnk_error(code, "%S(%S): %S", lib_path, str8_skip_last_slash(obj_path), text); } else { lnk_error(code, "%S: %S", obj_path, text); } } else { lnk_error(code, "RADLINK: %S", text); } scratch_end(scratch); } internal void lnk_error_with_loc(LNK_ErrorCode code, String8 obj_path, String8 lib_path, char *fmt, ...) { va_list args; va_start(args, fmt); lnk_error_with_loc_fv(code, obj_path, lib_path, fmt, args); va_end(args); } internal void lnk_supplement_error(char *fmt, ...) { va_list args; va_start(args, fmt); Temp scratch = scratch_begin(0,0); String8 string = push_str8fv(scratch.arena, fmt, args); fprintf(stderr, "\t"); fprintf(stderr, "%.*s", str8_varg(string)); fprintf(stderr, "\n"); va_end(args); scratch_end(scratch); } internal void lnk_supplement_error_list(String8List list) { for (String8Node *node = list.first; node != 0; node = node->next) { lnk_supplement_error("%.*s", str8_varg(node->string)); } } internal void lnk_suppress_error(LNK_ErrorCode code) { g_error_code_status_arr[code] = LNK_ErrorCodeStatus_Ignore; } internal LNK_ErrorCodeStatus lnk_get_error_code_status(LNK_ErrorCode code) { return g_error_code_status_arr[code]; } internal void lnk_internal_error(LNK_InternalError code, char *file, int line, char *fmt, ...) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 issue = push_str8fv(scratch.arena, fmt, args); fprintf(stderr, "internal error #%03d in %s:%u\n", code, file, line); fprintf(stderr, "\t%.*s\n", str8_varg(issue)); va_end(args); scratch_end(scratch); } ================================================ FILE: src/linker/lnk_error.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef enum { LNK_Error_Null, LNK_Error_StopFirst, LNK_Error_Cmdl, LNK_Error_EndprecompNotFound, LNK_Error_EntryPoint, LNK_Error_ExternalTypeServerConflict, LNK_Error_FileNotFound, LNK_Error_IllData, LNK_Error_IllExport, LNK_Error_IncomatibleCmdOptions, LNK_Error_IncompatibleMachine, LNK_Error_InvalidPrecompLeafCount, LNK_Error_InvalidStartIndex, LNK_Error_NoAccess, LNK_Error_NoSubsystem, LNK_Error_OutOfExportOrdinals, LNK_Error_PrecompObjNotFound, LNK_Error_PrecompSigMismatch, LNK_Error_Telemetry, LNK_Error_UnsupportedMachine, LNK_Error_Mt, LNK_Error_UnableToSerializeMsf, LNK_Error_LoadRes, LNK_Error_IO, LNK_Error_LargeAddrAwareRequired, LNK_Error_InvalidPath, LNK_Error_MultiplyDefinedSymbol, LNK_Error_SectRefsDiscardedMemory, LNK_Error_IllegalSectionMerge, LNK_Error_IllegalRelocation, LNK_Error_CircularMerge, LNK_Error_AssociativeLoop, LNK_Error_AlternateNameConflict, LNK_Error_RelocationAgainstRemovedSection, LNK_Error_StopLast, LNK_Error_First, LNK_Error_AlreadyDefinedSymbol, LNK_Error_CvPrecomp, LNK_Error_Natvis, LNK_Error_TooManyFiles, LNK_Error_UnableToOpenTypeServer, LNK_Error_UnexpectedCodePath, LNK_Error_CvIllSymbolData, LNK_Error_InvalidTypeIndex, LNK_Error_UndefinedIsWeak, LNK_Error_WeakCycle, LNK_Error_InvalidLib, LNK_Error_UnresolvedSymbol, LNK_Error_Last, LNK_Warning_First, LNK_Warning_InvalidMergeDirectiveFormat, LNK_Warning_AmbiguousMerge, LNK_Warning_AtypicalStartIndex, LNK_Warning_Cmdl, LNK_Warning_Directive, LNK_Warning_DuplicateObjPath, LNK_Warning_ExternalTypeServerAgeMismatch, LNK_Warning_FileNotFound, LNK_Warning_IllData, LNK_Warning_IllExport, LNK_Warning_InvalidNatvisFileExt, LNK_Warning_LargePages, LNK_Warning_LargePagesNotEnabled, LNK_Warning_MismatchedTypeServerSignature, LNK_Warning_MissingExternalTypeServer, LNK_Warning_MultipleDebugTAndDebugP, LNK_Warning_MultipleExternalTypeServers, LNK_Warning_MultipleLibMatch, LNK_Warning_MultiplyDefinedImport, LNK_Warning_Natvis, LNK_Warning_PrecompObjSymbolsNotFound, LNK_Warning_SectionFlagsConflict, LNK_Warning_Subsystem, LNK_Warning_UnknownDirective, LNK_Warning_IllegalDirective, LNK_Warning_UnresolvedComdat, LNK_Warning_UnusedDelayLoadDll, LNK_Warning_LongSectionName, LNK_Warning_UnknownSwitch, LNK_Warning_TLSAlign, LNK_Warning_DirectiveSectionWithRelocs, LNK_Warning_NoLargeAddressAwarenessForDll, LNK_Warning_TryingToExportEntryPoint, LNK_Warning_Last, LNK_Error_Count } LNK_ErrorCode; typedef enum { LNK_ErrorMode_Ignore, LNK_ErrorMode_Stop, LNK_ErrorMode_Continue, LNK_ErrorMode_Warn, } LNK_ErrorMode; typedef enum { LNK_InternalError_Null, LNK_InternalError_NotImplemented, LNK_InternalError_InvalidPath, LNK_InternalError_IncompleteSwitch, LNK_InternalError_OutOfMemory } LNK_InternalError; typedef enum { LNK_ErrorCodeStatus_Active, LNK_ErrorCodeStatus_Ignore, } LNK_ErrorCodeStatus; internal void lnk_init_error_handler(void); internal void lnk_errorfv(LNK_ErrorCode code, char *fmt, va_list args); internal void lnk_error(LNK_ErrorCode code, char *fmt, ...); internal void lnk_error_with_loc(LNK_ErrorCode code, String8 obj_path, String8 lib_path, char *fmt, ...); internal void lnk_supplement_error(char *fmt, ...); internal void lnk_supplement_error_list(String8List list); internal void lnk_suppress_error(LNK_ErrorCode code); #define lnk_is_error_code_active(code) (lnk_get_error_code_status(code) == LNK_ErrorCodeStatus_Active) #define lnk_is_error_code_ignored(code) (lnk_get_error_code_status(code) == LNK_ErrorCodeStatus_Ignore) internal LNK_ErrorCodeStatus lnk_get_error_code_status(LNK_ErrorCode code); internal void lnk_internal_error(LNK_InternalError code, char *file, int line, char *fmt, ...); #define lnk_invalid_path(...) lnk_internal_error(LNK_InternalError_InvalidPath, __FILE__, __LINE__, __VA_ARGS__) #define lnk_not_implemented(...) lnk_internal_error(LNK_InternalError_NotImplemented, __FILE__, __LINE__, __VA_ARGS__) #define lnk_incomplete_switch(...) lnk_internal_error(LNK_InternalError_IncompleteSwitch, __FILE__, __LINE__, __VA_ARGS__) ================================================ FILE: src/linker/lnk_io.c ================================================ shared_function int lnk_open_file_read(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max) { OS_Handle handle = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, str8((U8*)path, path_size)); Assert(sizeof(handle) <= handle_buffer_max); MemoryCopy(handle_buffer, &handle, sizeof(handle)); return !os_handle_match(handle, os_handle_zero()); } shared_function int lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max) { OS_Handle handle = os_file_open(OS_AccessFlag_Write, str8((U8*)path, path_size)); Assert(sizeof(handle) <= handle_buffer_max); MemoryCopy(handle_buffer, &handle, sizeof(handle)); return !os_handle_match(handle, os_handle_zero()); } shared_function void lnk_close_file(void *raw_handle) { OS_Handle handle = *(OS_Handle *)raw_handle; os_file_close(handle); } shared_function uint64_t lnk_size_from_file(void *raw_handle) { OS_Handle handle = *(OS_Handle *)raw_handle; FileProperties props = os_properties_from_file(handle); return props.size; } shared_function uint64_t lnk_read_file(void *raw_handle, void *buffer, uint64_t buffer_max) { OS_Handle handle = *(OS_Handle *)raw_handle; U64 read_size = os_file_read(handle, rng_1u64(0, buffer_max), buffer); Assert(read_size == buffer_max); return read_size; } shared_function uint64_t lnk_write_file(void *raw_handle, uint64_t offset, void *buffer, uint64_t buffer_size) { OS_Handle handle = *(OS_Handle*)raw_handle; U64 write_size = os_file_write(handle, r1u64(offset, offset + buffer_size), buffer); return write_size; } internal String8 lnk_find_first_file(Arena *arena, String8List dir_list, String8 path) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); String8 result = {0}; if (os_file_path_exists(path)) { PathStyle path_style = path_style_from_str8(path); if (path_style == PathStyle_Relative) { String8 current_path = os_get_current_path(scratch.arena); String8List l = {0}; str8_list_push(scratch.arena, &l, current_path); str8_list_push(scratch.arena, &l, path); result = str8_path_list_join_by_style(arena, &l, PathStyle_SystemAbsolute); } else { result = path; } } else { String8 file_name = str8_skip_last_slash(path); for EachNode(n, String8Node, dir_list.first) { String8 full_path = push_str8f(scratch.arena, "%S/%S", n->string, file_name); if (os_file_path_exists(full_path)) { result = push_str8_copy(arena, full_path); break; } } } scratch_end(scratch); ProfEnd(); return result; } internal OS_Handle lnk_file_open_with_rename_permissions(String8 path) { OS_Handle file_handle = os_handle_zero(); #if OS_WINDOWS Temp scratch = scratch_begin(0,0); // open file with permissions to rename String16 path16 = str16_from_8(scratch.arena, path); SECURITY_ATTRIBUTES security_attributes = { sizeof(security_attributes) }; HANDLE native_handle = CreateFileW((WCHAR*)path16.str, GENERIC_WRITE|DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, &security_attributes, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (native_handle != INVALID_HANDLE_VALUE) { file_handle.u64[0] = (U64)native_handle; } scratch_end(scratch); #else # error "TODO: file rename" #endif return file_handle; } internal B32 lnk_file_set_delete_on_close(OS_Handle handle, B32 delete_file) { #if OS_WINDOWS FILE_DISPOSITION_INFO file_disposition = {0}; file_disposition.DeleteFile = (BOOL)delete_file; B32 is_set = SetFileInformationByHandle((HANDLE)handle.u64[0], FileDispositionInfo, &file_disposition, sizeof(file_disposition)); #else # error "TODO: file rename" #endif return is_set; } internal B32 lnk_file_rename(OS_Handle handle, String8 new_name) { Temp scratch = scratch_begin(0,0); #if OS_WINDOWS String16 new_name16 = str16_from_8(scratch.arena, new_name); U64 file_rename_info_size = sizeof(FILE_RENAME_INFO); U64 buffer_size = file_rename_info_size + sizeof(new_name16.str)*new_name16.size; U8 *buffer = push_array(scratch.arena, U8, buffer_size); FILE_RENAME_INFO *rename_info = (FILE_RENAME_INFO *)buffer; rename_info->ReplaceIfExists = 1; rename_info->FileNameLength = new_name16.size * sizeof(new_name16.str[0]); MemoryCopy(rename_info->FileName, new_name16.str, new_name16.size * sizeof(new_name16.str[0])); B32 is_renamed = SetFileInformationByHandle((HANDLE)handle.u64[0], FileRenameInfo, buffer, buffer_size); #else #error "TODO: file rename" #endif scratch_end(scratch); return is_renamed; } internal void lnk_log_read(String8 path, U64 size) { lnk_log(LNK_Log_IO_Read, "Read from \"%S\" %M", path, size); } internal String8 lnk_read_data_from_file_path(Arena *arena, LNK_IO_Flags io_flags, String8 path) { Temp scratch = scratch_begin(&arena, 1); TP_Context *single_thread_ctx = tp_alloc(scratch.arena, 1, 1, str8_zero()); String8Array data_arr = lnk_read_data_from_file_path_parallel(single_thread_ctx, arena, io_flags, (String8Array){ .count = 1, .v = &path }); scratch_end(scratch); return data_arr.v[0]; } internal THREAD_POOL_TASK_FUNC(lnk_data_size_from_file_path_task) { LNK_DiskReader *task = raw_task; String8 path = task->path_arr.v[task_id]; OS_Handle handle = {0}; U64 size = 0; int is_open = lnk_open_file_read((char*)path.str, path.size, &handle, sizeof(handle)); if (is_open) { size = lnk_size_from_file(&handle); } task->handle_arr[task_id] = handle; task->size_arr[task_id] = size; } internal THREAD_POOL_TASK_FUNC(lnk_data_from_file_path_task) { LNK_DiskReader *task = raw_task; OS_Handle handle = task->handle_arr[task_id]; U64 buffer_size = task->size_arr[task_id]; U8 *buffer = task->buffer + task->off_arr[task_id]; U64 read_size = lnk_read_file(&handle, buffer, buffer_size); Assert(read_size == buffer_size); task->data_arr.v[task_id] = str8(buffer, read_size); } internal THREAD_POOL_TASK_FUNC(lnk_memory_map_file_task) { LNK_DiskReader *task = raw_task; #if OS_WINDOWS Temp scratch = scratch_begin(&arena, 1); String16 path16 = str16_from_8(scratch.arena, task->path_arr.v[task_id]); HANDLE file_handle = CreateFileW(path16.str, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (file_handle != INVALID_HANDLE_VALUE) { HANDLE mapping_handle = CreateFileMappingA(file_handle, 0, PAGE_WRITECOPY, 0, 0, 0); if (mapping_handle != INVALID_HANDLE_VALUE) { LARGE_INTEGER file_size = {0}; GetFileSizeEx(file_handle, &file_size); void *file_data = MapViewOfFile(mapping_handle, FILE_MAP_COPY, 0, 0, file_size.QuadPart); if (file_data) { // asan crashes for an unknown reason on memory-mapped files, even though the allocation is perfectly fine AsanUnpoisonMemoryRegion(file_data, file_size.QuadPart); task->data_arr.v[task_id] = str8(file_data, file_size.QuadPart); } CloseHandle(mapping_handle); } CloseHandle(file_handle); } scratch_end(scratch); #else # error "memory mapping files is not supported on this platform" #endif } internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, LNK_IO_Flags io_flags, String8Array path_arr) { LNK_DiskReader reader = {0}; if (io_flags & LNK_IO_Flags_MemoryMapFiles) { reader.io_flags = io_flags; reader.path_arr = path_arr; reader.data_arr.count = path_arr.count; reader.data_arr.v = push_array(arena, String8, path_arr.count); tp_for_parallel(tp, 0, path_arr.count, lnk_memory_map_file_task, &reader); } else { Temp scratch = scratch_begin(&arena,1); reader.path_arr = path_arr; reader.handle_arr = push_array_no_zero(scratch.arena, OS_Handle, path_arr.count); reader.size_arr = push_array_no_zero(scratch.arena, U64, path_arr.count); // open handles and get sizes tp_for_parallel(tp, 0, path_arr.count, lnk_data_size_from_file_path_task, &reader); // compute file buffer size U64 total_data_size = sum_array_u64(path_arr.count, reader.size_arr); // assign offsets into file buffer U64 *off_arr = push_array_no_zero(scratch.arena, U64, path_arr.count); MemoryCopyTyped(off_arr, reader.size_arr, path_arr.count); counts_to_offsets_array_u64(path_arr.count, off_arr); reader.io_flags = io_flags; reader.data_arr = str8_array_reserve(arena, path_arr.count); reader.off_arr = off_arr; reader.buffer = push_array_no_zero(arena, U8, total_data_size); // read files and close handles tp_for_parallel(tp, 0, path_arr.count, lnk_data_from_file_path_task, &reader); scratch_end(scratch); } String8Array result = {0}; result.count = path_arr.count; result.v = reader.data_arr.v; if (lnk_get_log_status(LNK_Log_IO_Read)) { for (U64 i = 0; i < result.count; ++i) { lnk_log_read(path_arr.v[i], result.v[i].size); } } return result; } internal void lnk_write_data_list_to_file_path(String8 path, String8 temp_path, String8List data) { ProfBeginV("Write %M to %S", data.total_size, path); B32 open_with_rename = (temp_path.size > 0); OS_Handle file_handle = {0}; String8 open_file_path = {0}; if (open_with_rename) { file_handle = lnk_file_open_with_rename_permissions(temp_path); open_file_path = temp_path; // mark file to be deleted on exit, so we don't leave corrupted files on disk if (!lnk_file_set_delete_on_close(file_handle, 1)) { lnk_error(LNK_Error_IO, "failed to update file disposition on %S", open_file_path); } } else { lnk_open_file_write((char*)path.str, path.size, &file_handle, sizeof(file_handle)); open_file_path = path; } if (!os_handle_match(file_handle, os_handle_zero())) { // try to reserve up front file size if (!os_file_reserve_size(file_handle, data.total_size)) { lnk_log(LNK_Log_IO_Write, "Failed to pre-allocate file %S with size %M", open_file_path, data.total_size); } // write data nodes U64 bytes_written = 0; for (String8Node *data_n = data.first; data_n != 0; data_n = data_n->next) { U64 write_size = lnk_write_file(&file_handle, bytes_written, data_n->string.str, data_n->string.size); if (write_size != data_n->string.size) { break; } bytes_written += data_n->string.size; } B32 is_write_complete = (bytes_written == data.total_size); if (is_write_complete) { // rename temp file if (open_with_rename) { // all writes succeeded, remove delete on exit flag if (!lnk_file_set_delete_on_close(file_handle, 0)) { lnk_error(LNK_Error_IO, "failed to update file disposition on %S", open_file_path); } if (lnk_file_rename(file_handle, path)) { lnk_log(LNK_Log_IO_Write, "Renamed %S -> %S", temp_path, path); } else { lnk_error(LNK_Error_IO, "failed to rename %S -> %S", temp_path, path); } } } // clean up file handle lnk_close_file(&file_handle); // log write if (is_write_complete) { if (lnk_get_log_status(LNK_Log_IO_Write)) { lnk_log(LNK_Log_IO_Write, "File \"%S\" %M written", path, data.total_size); } } else { lnk_error(LNK_Error_IO, "incomplete write, %M written, expected %M, file %S", bytes_written, data.total_size, path); } } else { lnk_error(LNK_Error_NoAccess, "don't have access to write to %S", path); } ProfEnd(); } internal void lnk_write_data_to_file_path(String8 path, String8 temp_path, String8 data) { Temp scratch = scratch_begin(0,0); String8List data_list = {0}; str8_list_push(scratch.arena, &data_list, data); lnk_write_data_list_to_file_path(path, temp_path, data_list); scratch_end(scratch); } ================================================ FILE: src/linker/lnk_io.h ================================================ #pragma once typedef U32 LNK_IO_Flags; enum { LNK_IO_Flags_MemoryMapFiles = (1 << 0), }; typedef struct { LNK_IO_Flags io_flags; String8Array path_arr; String8Array data_arr; OS_Handle *handle_arr; U64 *size_arr; U64 *off_arr; U8 *buffer; } LNK_DiskReader; // --- Shared File API --------------------------------------------------------- shared_function int lnk_open_file_read(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max); shared_function int lnk_open_file_write(char *path, uint64_t path_size, void *handle_buffer, uint64_t handle_buffer_max); shared_function void lnk_close_file(void *raw_handle); shared_function uint64_t lnk_size_from_file(void *raw_handle); shared_function uint64_t lnk_read_file(void *raw_handle, void *buffer, uint64_t buffer_max); shared_function uint64_t lnk_write_file(void *raw_handle, uint64_t offset, void *buffer, uint64_t buffer_size); // --- IO Functions ------------------------------------------------------------ internal OS_Handle lnk_file_open_with_rename_permissions(String8 path); internal B32 lnk_file_set_delete_on_close(OS_Handle handle, B32 delete_file); internal B32 lnk_file_rename(OS_Handle handle, String8 new_name); internal String8 lnk_read_data_from_file_path(Arena *arena, LNK_IO_Flags io_flags, String8 path); internal String8Array lnk_read_data_from_file_path_parallel(TP_Context *tp, Arena *arena, LNK_IO_Flags io_flags, String8Array path_arr); internal void lnk_write_data_list_to_file_path(String8 path, String8 temp_path, String8List list); internal void lnk_write_data_to_file_path(String8 path, String8 temp_path, String8 data); ================================================ FILE: src/linker/lnk_lib.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal int lnk_lib_node_is_before(void *a, void *b) { return ((LNK_LibNode*)a)->data.input_idx < ((LNK_LibNode*)b)->data.input_idx; } internal int lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b) { return lnk_lib_node_is_before(*(LNK_Lib **)raw_a, *(LNK_Lib **)raw_b); } internal B32 lnk_first_member_sort_key_is_before(void *raw_a, void *raw_b) { LNK_FirstMemberSortKey *a = raw_a, *b = raw_b; return str8_is_before_case_sensitive(&a->symbol_name, &b->symbol_name); } internal B32 lnk_lib_from_data(Arena *arena, String8 data, String8 path, U64 input_idx, LNK_Lib *lib_out) { // is data archive? COFF_ArchiveType type = coff_archive_type_from_data(data); if (type == COFF_Archive_Null) { return 0; } // TODO: report parse errors COFF_ArchiveParse parse = coff_archive_parse_from_data(data); if (parse.error.size) { return 0; } U32 member_count = 0; U64 symbol_count = 0; String8Array symbol_names = {0}; U16 *symbol_indices = 0; U32 *member_offsets = 0; // try to init library from optional second member if (parse.second_member.member_count) { COFF_ArchiveSecondMember second_member = parse.second_member; Assert(second_member.symbol_count == second_member.symbol_index_count); Assert(second_member.member_count == second_member.member_offset_count); member_count = second_member.member_count; symbol_count = second_member.symbol_count; member_offsets = second_member.member_offsets; symbol_indices = second_member.symbol_indices; // parse symbol names { Temp scratch = scratch_begin(&arena, 1); String8List symbol_name_list = str8_split_by_string_chars(scratch.arena, second_member.string_table, str8_lit("\0"), 0); Assert(symbol_name_list.node_count >= symbol_count); symbol_names = str8_array_from_list(arena, &symbol_name_list); scratch_end(scratch); } } // first member is deprecated however tools emit it for compatibility reasons // and lld-link with /DLL emits only first member else if (parse.first_member.symbol_count) { Temp scratch = scratch_begin(&arena, 1); COFF_ArchiveFirstMember first_member = parse.first_member; Assert(first_member.symbol_count == first_member.member_offset_count); symbol_count = first_member.symbol_count; // convert big endian offsets for (U32 offset_idx = 0; offset_idx < symbol_count; offset_idx += 1) { first_member.member_offsets[offset_idx] = from_be_u32(first_member.member_offsets[offset_idx]); } // compress member offsets to match those from the second header { HashTable *member_off_ht = hash_table_init(scratch.arena, (U64)((F64)first_member.symbol_count * 1.3)); for EachIndex(symbol_idx, symbol_count) { if (!hash_table_search_u32_u32(member_off_ht, first_member.member_offsets[symbol_idx], 0)) { hash_table_push_u32_u32(scratch.arena, member_off_ht, first_member.member_offsets[symbol_idx], member_off_ht->count); } } symbol_indices = push_array(arena, U16, first_member.symbol_count); for EachIndex(symbol_idx, first_member.symbol_count) { U32 member_off = first_member.member_offsets[symbol_idx]; U32 member_off_idx = 0; if (!hash_table_search_u32_u32(member_off_ht, member_off, &member_off_idx)) { InvalidPath; } symbol_indices[symbol_idx] = member_off_idx+1; } member_count = member_off_ht->count; member_offsets = push_array_no_zero(arena, U32, member_count); for EachIndex(bucket_idx, member_off_ht->cap) { BucketList *bucket = &member_off_ht->buckets[bucket_idx]; for (BucketNode *n = bucket->first; n != 0; n = n->next) { U32 member_off = n->v.key_u32; U32 member_off_idx = n->v.value_u32; member_offsets[member_off_idx] = member_off; } } // parse symbol names { Temp scratch = scratch_begin(&arena, 1); String8List symbol_name_list = str8_split_by_string_chars(scratch.arena, first_member.string_table, str8_lit("\0"), 0); Assert(symbol_name_list.node_count >= first_member.symbol_count); symbol_names = str8_array_from_list(arena, &symbol_name_list); scratch_end(scratch); } // sort lexically symbol names LNK_FirstMemberSortKey *sort_keys = push_array_no_zero(scratch.arena, LNK_FirstMemberSortKey, first_member.symbol_count); for EachIndex(symbol_idx, first_member.symbol_count) { sort_keys[symbol_idx].symbol_name = symbol_names.v[symbol_idx]; sort_keys[symbol_idx].member_off_idx = symbol_indices[symbol_idx]; } radsort(sort_keys, first_member.symbol_count, lnk_first_member_sort_key_is_before); for EachIndex(symbol_idx, first_member.symbol_count) { symbol_names.v[symbol_idx] = sort_keys[symbol_idx].symbol_name; symbol_indices[symbol_idx] = sort_keys[symbol_idx].member_off_idx; } } scratch_end(scratch); } // init lib lib_out->path = push_str8_copy(arena, path); lib_out->data = data; lib_out->type = type; lib_out->member_count = member_count; lib_out->symbol_count = Min(symbol_count, symbol_names.count); // TODO: warn about mismatched number of symbol names and symbol count in the header lib_out->member_offsets = member_offsets; lib_out->symbol_indices = symbol_indices; lib_out->member_links = push_array(arena, LNK_Symbol *, member_count); lib_out->symbol_names = symbol_names; lib_out->long_names = parse.long_names; lib_out->input_idx = input_idx; return 1; } internal THREAD_POOL_TASK_FUNC(lnk_lib_initer) { LNK_LibIniter *task = raw_task; LNK_Input *input = task->inputs[task_id]; U64 lib_node_idx = ins_atomic_u64_inc_eval(&task->next_free_lib_idx)-1; LNK_LibNode *lib_node = &task->free_libs[lib_node_idx]; B32 is_valid_lib = lnk_lib_from_data(arena, input->data, input->path, task->lib_id_base + task_id, &lib_node->data); if (is_valid_lib) { U64 valid_lib_idx = ins_atomic_u64_inc_eval(&task->valid_libs_count)-1; task->valid_libs[valid_lib_idx] = lib_node; } else { U64 invalid_lib_idx = ins_atomic_u64_inc_eval(&task->invalid_libs_count); task->invalid_libs[invalid_lib_idx] = lib_node; } } internal LNK_Lib ** lnk_array_from_lib_list(Arena *arena, LNK_LibList list) { LNK_Lib **arr = push_array_no_zero(arena, LNK_Lib *, list.count); U64 idx = 0; for (LNK_LibNode *node = list.first; node != 0; node = node->next, ++idx) { arr[idx] = &node->data; } return arr; } internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U64 inputs_count, LNK_Input **inputs) { Temp scratch = scratch_begin(arena->v, arena->count); U64 lib_id_base = list->count; // parse libs in parallel LNK_LibIniter task = {0}; task.lib_id_base = list->count; task.free_libs = push_array(arena->v[0], LNK_LibNode, inputs_count); task.valid_libs = push_array(scratch.arena, LNK_LibNode *, inputs_count); task.invalid_libs = push_array(scratch.arena, LNK_LibNode *, inputs_count); task.inputs = inputs; tp_for_parallel(tp, arena, inputs_count, lnk_lib_initer, &task); // report invalid libs radsort(task.invalid_libs, task.invalid_libs_count, lnk_lib_node_ptr_is_before); for EachIndex(i, task.invalid_libs_count) { U64 input_idx = task.invalid_libs[i]->data.input_idx; lnk_error(LNK_Error_InvalidLib, "%S: failed to parse library", inputs[input_idx]->path); } // push parsed libs radsort(task.valid_libs, task.valid_libs_count, lnk_lib_node_ptr_is_before); for EachIndex(i, task.valid_libs_count) { lnk_lib_list_push_node(list, task.valid_libs[i]); } LNK_LibNodeArray result = { .count = task.valid_libs_count, task.valid_libs }; scratch_end(scratch); return result; } internal B32 lnk_lib_set_link_symbol(LNK_Lib *lib, U32 member_idx, LNK_Symbol *link_symbol) { local_persist LNK_Symbol null_symbol; LNK_Symbol *slot = ins_atomic_ptr_eval_assign(&lib->member_links[member_idx], &null_symbol); B32 was_linked = (slot == 0); for (LNK_Symbol *leader = link_symbol;;) { // update slot symbol if it is empty or link symbol comes before symbol in the slot if (slot && slot != &null_symbol) { if (lnk_symbol_is_before(slot, leader)) { leader = slot; } } else { leader = link_symbol; } // try to insert back updated slot symbol LNK_Symbol *swap = ins_atomic_ptr_eval_cond_assign(&lib->member_links[member_idx], leader, &null_symbol); // exit if slot symbol was null if (swap == &null_symbol) { break; } // reload slot symbol slot = ins_atomic_ptr_eval_assign(&lib->member_links[member_idx], &null_symbol); } return was_linked; } internal force_inline B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out) { U64 symbol_idx = str8_array_bsearch(lib->symbol_names, symbol_name); if (symbol_idx < lib->symbol_count) { if (member_idx_out) { *member_idx_out = lib->symbol_indices[symbol_idx]-1; } return 1; } return 0; } ================================================ FILE: src/linker/lnk_lib.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef struct LNK_Lib { String8 path; String8 data; COFF_ArchiveType type; U32 member_count; U32 symbol_count; U32 *member_offsets; U16 *symbol_indices; LNK_Symbol **member_links; String8Array symbol_names; String8 long_names; U64 input_idx; } LNK_Lib; typedef struct LNK_LibNode { LNK_Lib data; struct LNK_LibNode *next; } LNK_LibNode; typedef struct LNK_LibNodeArray { U64 count; LNK_LibNode **v; } LNK_LibNodeArray; typedef struct LNK_LibList { U64 count; LNK_LibNode *first; LNK_LibNode *last; } LNK_LibList; typedef struct LNK_FirstMemberSortKey { String8 symbol_name; U16 member_off_idx; } LNK_FirstMemberSortKey; // --- Workers Contexts -------------------------------------------------------- typedef struct { struct LNK_Input **inputs; U64 lib_id_base; U64 next_free_lib_idx; U64 valid_libs_count; U64 invalid_libs_count; LNK_LibNode *free_libs; LNK_LibNode **valid_libs; LNK_LibNode **invalid_libs; } LNK_LibIniter; // ----------------------------------------------------------------------------- internal int lnk_lib_node_is_before(void *a, void *b); internal int lnk_lib_node_ptr_is_before(void *raw_a, void *raw_b); internal B32 lnk_lib_from_data(Arena *arena, String8 data, String8 path, U64 input_idx, LNK_Lib *lib_out); internal LNK_Lib ** lnk_array_from_lib_list(Arena *arena, LNK_LibList list); internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node); internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U64 inputs_count, struct LNK_Input **inputs); internal B32 lnk_lib_set_link_symbol(LNK_Lib *lib, U32 member_idx, LNK_Symbol *link_symbol); internal B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out); ================================================ FILE: src/linker/lnk_log.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void lnk_set_log_status(LNK_LogType type, B32 is_enabled) { g_log_status[type] = is_enabled; } internal B32 lnk_get_log_status(LNK_LogType type) { B32 status = g_log_status[type]; return status; } internal void lnk_log(LNK_LogType type, char *fmt, ...) { B32 is_log_enabled = g_log_status[type]; if (is_log_enabled) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); fprintf(stdout, "%.*s\n", str8_varg(string)); va_end(args); scratch_end(scratch); } } internal LNK_LogType lnk_log_type_from_string(String8 string) { static struct { char *name; LNK_LogType type; } map[] = { "Null", LNK_Log_Null, "Debug", LNK_Log_Debug, "InputObj", LNK_Log_InputObj, "InputLib", LNK_Log_InputLib, "IO_Read", LNK_Log_IO_Read, "IO_Write", LNK_Log_IO_Write, "SizeBreakdown", LNK_Log_SizeBreakdown, "LinkStats", LNK_Log_LinkStats, "Timers", LNK_Log_Timers, "Links", LNK_Log_Links, }; Assert(ArrayCount(map) == LNK_Log_Count); for (U64 i = 0; i < ArrayCount(map); ++i) { if (str8_match(str8_cstring(map[i].name), string, StringMatchFlag_CaseInsensitive)) { return map[i].type; } } return LNK_Log_Null; } ================================================ FILE: src/linker/lnk_log.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef enum { LNK_Log_Null, LNK_Log_Debug, LNK_Log_InputObj, LNK_Log_InputLib, LNK_Log_IO_Read, LNK_Log_IO_Write, LNK_Log_SizeBreakdown, LNK_Log_LinkStats, LNK_Log_Timers, LNK_Log_Links, LNK_Log_Count } LNK_LogType; internal void set_log_level(LNK_LogType type, B32 is_enabled); internal B32 lnk_get_log_status(LNK_LogType type); internal void lnk_log(LNK_LogType type, char *fmt, ...); internal LNK_LogType lnk_log_type_from_string(String8 string); ================================================ FILE: src/linker/lnk_obj.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 lnk_loc_from_obj(Arena *arena, LNK_Obj *obj) { String8 obj_path = str8_skip_last_slash(obj ? obj->path : str8_lit("RADLINK")); String8 lib_path = str8_skip_last_slash(lnk_obj_get_lib_path(obj)); String8 result; if (lib_path.size) { result = push_str8f(arena, "%S(%S)", lib_path, obj_path); } else { result = push_str8_copy(arena, obj_path); } return result; } internal void lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...) { va_list args; va_start(args, fmt); String8 obj_path = obj ? obj->path : str8_zero(); String8 lib_path = lnk_obj_get_lib_path(obj); lnk_error_with_loc_fv(code, obj_path, lib_path, fmt, args); va_end(args); } internal void lnk_error_input_obj(LNK_ErrorCode code, LNK_Input *input, char *fmt, ...) { va_list args; va_start(args, fmt); LNK_LibMemberRef *link_member = input->link_member; LNK_Lib *link_lib = link_member ? link_member->lib : 0; lnk_error_with_loc_fv(code, input->path, link_lib ? link_lib->path : str8_zero(), fmt, args); va_end(args); } internal LNK_Obj ** lnk_array_from_obj_list(Arena *arena, LNK_ObjList list) { LNK_Obj **arr = push_array_no_zero(arena, LNK_Obj *, list.count); U64 idx = 0; for (LNK_ObjNode *node = list.first; node != 0; node = node->next, ++idx) { arr[idx] = &node->data; } return arr; } internal THREAD_POOL_TASK_FUNC(lnk_obj_initer) { LNK_ObjIniter *task = raw_task; LNK_Input *input = task->inputs[task_id]; LNK_Obj *obj = &task->objs[task_id].data; //ProfBeginV("Init Obj [%S%s%S]", input->lib_path, (input->lib_path.size ? ": " : 0), input->path); // // parse obj header // COFF_FileHeaderInfo header = coff_file_header_info_from_data(input->data); // // set & check machine compatibility // if (header.machine != COFF_MachineType_Unknown) { COFF_MachineType current_machine = ins_atomic_u32_eval_cond_assign(&task->machine, header.machine, COFF_MachineType_Unknown); if (current_machine != COFF_MachineType_Unknown && current_machine != header.machine) { lnk_error_input_obj(LNK_Error_IncompatibleMachine, input, "conflicting machine types expected %S but got %S", coff_string_from_machine_type(current_machine), coff_string_from_machine_type(header.machine)); } } // // extract COFF info // String8 raw_coff_section_table = str8_substr(input->data, header.section_table_range); String8 raw_coff_symbol_table = str8_substr(input->data, header.symbol_table_range); String8 raw_coff_string_table = str8_substr(input->data, header.string_table_range); // // error check section table / symbol table / string table // if (raw_coff_section_table.size != dim_1u64(header.section_table_range)) { lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read section header table"); } if (raw_coff_symbol_table.size != dim_1u64(header.symbol_table_range)) { lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read symbol table"); } if (raw_coff_string_table.size != dim_1u64(header.string_table_range)) { lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read string table"); } // // error check section headers // COFF_SectionHeader *coff_section_table = (COFF_SectionHeader *)raw_coff_section_table.str; for (U64 sect_idx = 0; sect_idx < header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *coff_sect_header = &coff_section_table[sect_idx]; String8 sect_name = coff_name_from_section_header(raw_coff_string_table, coff_sect_header); if (~coff_sect_header->flags & COFF_SectionFlag_CntUninitializedData) { if (coff_sect_header->fsize > 0) { Rng1U64 sect_range = rng_1u64(coff_sect_header->foff, coff_sect_header->foff + coff_sect_header->fsize); if (contains_1u64(header.header_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.header_range, sect_range.max-1))) { lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into file header)", sect_name, sect_idx+1); } if (contains_1u64(header.section_table_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.section_table_range, sect_range.max-1))) { lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into section header table)", sect_name, sect_idx+1); } if (contains_1u64(header.symbol_table_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.symbol_table_range, sect_range.max-1))) { lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into symbol table)", sect_name, sect_idx+1); } if (dim_1u64(sect_range) != coff_sect_header->fsize) { lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data", sect_name, sect_idx+1); } } } } // // error check symbol table // { COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(input->data, header.section_table_range).str; COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { if (symbol.section_number == 0 || symbol.section_number > header.section_count_no_null) { lnk_error_input_obj(LNK_Error_IllData, input, "symbol %S (No. 0x%x) points to an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); } if (symbol.storage_class == COFF_SymStorageClass_Static && symbol.aux_symbol_count > 0) { COFF_ComdatSelectType select; U32 section_number = 0; coff_parse_secdef(symbol, header.is_big_obj, &select, §ion_number, 0, 0); if (select == COFF_ComdatSelect_Associative) { if (section_number == 0 || section_number > header.section_count_no_null) { lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbol %S (No. 0x%x) associates with an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); } } } } } } // // create symbol links to COMDAT sections // U32 *comdats; { comdats = push_array_no_zero(arena, U32, header.section_count_no_null); MemorySet(comdats, 0xff, header.section_count_no_null * sizeof(comdats[0])); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { if (symbol.storage_class == COFF_SymStorageClass_Static) { if (symbol.section_number > 0 && symbol.section_number <= header.section_count_no_null) { COFF_SectionHeader *sect_header = &coff_section_table[symbol.section_number-1]; if (sect_header->flags & COFF_SectionFlag_LnkCOMDAT) { if (symbol.aux_symbol_count) { U32 section_length = 0; coff_parse_secdef(symbol, header.is_big_obj, 0, 0, §ion_length, 0); if (sect_header->fsize == section_length) { if (comdats[symbol.section_number-1] == ~0) { comdats[symbol.section_number-1] = symbol_idx; } else { lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbo (No. 0x%llx) tries to ovewrite comdat", symbol_idx); } } else { lnk_error_input_obj(LNK_Error_IllData, input, "section size specified by section definition symbol (No 0x%llx) doesn't match size in section header (No. 0x%x); expected 0x%x got 0x%x", symbol_idx, symbol.section_number, section_length, sect_header->fsize); } } } } else { lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbol (No. 0x%llx) has out of bounds section number 0x%x", symbol_idx, symbol.section_number); } } } } } // // COMDAT loop checker // { Temp scratch = scratch_begin(&arena, 1); HashTable *visited_sections = hash_table_init(scratch.arena, 32); for (U64 sect_idx = 0; sect_idx < header.section_count_no_null; sect_idx += 1) { for (U32 curr_section = sect_idx;;) { U32 symbol_idx = comdats[curr_section]; // is section COMDAT? if (symbol_idx == max_U32) { break; } // extract COMDAT info for current section COFF_ParsedSymbol symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx); COFF_ComdatSelectType select = COFF_ComdatSelect_Null; U32 section_number = 0; coff_parse_secdef(symbol, header.is_big_obj, &select, §ion_number, 0, 0); if (select != COFF_ComdatSelect_Associative) { // section terminates at non-associative COMDAT -- no loop break; } // was section visited? -- loop found if (hash_table_search_u64(visited_sections, curr_section)) { COFF_ParsedSymbol symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, comdats[sect_idx]); lnk_error_input_obj(LNK_Error_AssociativeLoop, input, "section symbol %S (No. 0x%x) does not terminate on a non-associate COMDAT symbol", symbol.name, comdats[sect_idx]); break; } // track visited sections hash_table_push_u64_u64(scratch.arena, visited_sections, curr_section, 0); // follow association Assert(section_number > 0); curr_section = section_number-1; } // purge hash table for next run hash_table_purge(visited_sections); } scratch_end(scratch); } // // collect sections associations // U32Node **associated_sections = push_array(arena, U32Node *, header.section_count_no_null + 1); { COFF_ParsedSymbol symbol; for (U32 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); if (interp == COFF_SymbolValueInterp_Regular && symbol.storage_class == COFF_SymStorageClass_Static && symbol.aux_symbol_count > 0) { COFF_ComdatSelectType selection = COFF_ComdatSelect_Null; U32 section_number = 0; coff_parse_secdef(symbol, header.is_big_obj, &selection, §ion_number, 0, 0); if (selection != COFF_ComdatSelect_Associative) { continue; } U32Node *associated_node = push_array(arena, U32Node, 1); associated_node->data = symbol.section_number; SLLStackPush(associated_sections[section_number], associated_node); } } } // // mark sections // { for EachIndex(sect_idx, header.section_count_no_null) { COFF_SectionHeader *sect_header = &coff_section_table[sect_idx]; String8 sect_name = coff_name_from_section_header(raw_coff_string_table, sect_header); // debug info if (str8_starts_with(sect_name, str8_lit(".debug$"))) { sect_header->flags |= LNK_SECTION_FLAG_DEBUG; } // function overrides if (str8_ends_with(sect_name, str8_lit("$fo$"), 0) || str8_ends_with(sect_name, str8_lit("$fo_rvas$"), 0) || str8_ends_with(sect_name, str8_lit("$fo_bdd$"), 0)) { sect_header->flags |= COFF_SectionFlag_LnkInfo; } } } B8 hotpatch = 0; if (header.machine == COFF_MachineType_X64) { hotpatch = 1; } // // extract obj features from compile symbol in .debug$S // else { Temp scratch = scratch_begin(&arena, 1); CV_Symbol comp_symbol = {0}; for EachIndex(sect_idx, header.section_count_no_null) { COFF_SectionHeader *sect_header = &coff_section_table[sect_idx]; if (sect_header->flags & LNK_SECTION_FLAG_DEBUG) { String8 name = str8_cstring_capped(sect_header->name, sect_header->name+sizeof(sect_header->name)); if (str8_match(name, str8_lit(".debug$S"), 0)) { Temp temp = temp_begin(scratch.arena); String8 debug_s_data = str8_substr(input->data, rng_1u64(sect_header->foff, sect_header->foff+sect_header->fsize)); CV_DebugS debug_s = cv_parse_debug_s(temp.arena, debug_s_data); for EachNode(symbols_n, String8Node, debug_s.data_list[CV_C13SubSectionIdxKind_Symbols].first) { CV_SymbolList symbol_list = {0}; cv_parse_symbol_sub_section_capped(scratch.arena, &symbol_list, 0, symbols_n->string, CV_SymbolAlign, 2); if (symbol_list.first->data.kind == CV_SymKind_COMPILE3) { comp_symbol = symbol_list.first->data; goto found_comp_symbol; } else if (symbol_list.last->data.kind == CV_SymKind_COMPILE3) { comp_symbol = symbol_list.last->data; goto found_comp_symbol; } } temp_end(temp); } } } found_comp_symbol:; if (comp_symbol.kind == CV_SymKind_COMPILE3 && comp_symbol.data.size >= sizeof(CV_SymCompile3)) { CV_SymCompile3 *comp = (CV_SymCompile3 *)comp_symbol.data.str; hotpatch = !!(comp->flags & CV_Compile3Flag_HotPatch); } scratch_end(scratch); } // fill out obj obj->data = input->data; obj->path = push_str8_copy(arena, input->path); obj->header = header; obj->comdats = comdats; obj->exclude_from_debug_info = input->exclude_from_debug_info; obj->hotpatch = hotpatch; obj->associated_sections = associated_sections; obj->node = &task->objs[task_id]; obj->link_member = input->link_member; } internal LNK_ObjNode * lnk_obj_from_input_many(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, U64 inputs_count, LNK_Input **inputs) { LNK_ObjNode *objs = 0; if (inputs_count) { objs = push_array(arena->v[0], LNK_ObjNode, inputs_count); tp_for_parallel(tp, arena, inputs_count, lnk_obj_initer, &(LNK_ObjIniter){ .inputs = inputs, .objs = objs, .machine = machine }); } return objs; } internal LNK_ObjNode * lnk_obj_from_input(Arena *arena, COFF_MachineType machine, LNK_Input *input) { Temp scratch = scratch_begin(&arena, 1); TP_Context *tp = tp_alloc(scratch.arena, 1, 1, str8_zero()); TP_Arena tp_arena = { .count = 1, .v = &arena }; LNK_ObjNode *result = lnk_obj_from_input_many(tp, &tp_arena, machine, 1, &input); scratch_end(scratch); return result; } internal void lnk_obj_list_push_node_many(LNK_ObjList *list, U64 count, LNK_ObjNode *nodes) { for EachIndex(i, count) { DLLPushBack(list->first, list->last, &nodes[i]); } list->count += count; } internal void lnk_obj_list_push_node(LNK_ObjList *list, LNK_ObjNode *node) { lnk_obj_list_push_node_many(list, 1, node); } internal THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table) { LNK_InputCoffSymbolTable *task = raw_task; LNK_Obj *obj = task->objs[task_id]; COFF_ParsedSymbol symbol = {0}; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); switch (interp) { case COFF_SymbolValueInterp_Regular: { if (symbol.storage_class == COFF_SymStorageClass_External) { COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number); if (sect_header->flags & COFF_SectionFlag_LnkRemove) { break; } LNK_Symbol *defn = lnk_make_symbol(arena, symbol.name, obj, symbol_idx); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); } } break; case COFF_SymbolValueInterp_Weak: { LNK_Symbol *defn = lnk_make_symbol(arena, symbol.name, obj, symbol_idx); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); } break; case COFF_SymbolValueInterp_Undefined: { if (symbol.storage_class == COFF_SymStorageClass_External) { LNK_Symbol *defn = lnk_make_symbol(arena, symbol.name, obj, symbol_idx); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); } } break; case COFF_SymbolValueInterp_Common: { LNK_Symbol *defn = lnk_make_symbol(arena, symbol.name, obj, symbol_idx); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); } break; case COFF_SymbolValueInterp_Abs: { if (symbol.storage_class == COFF_SymStorageClass_External) { LNK_Symbol *defn = lnk_make_symbol(arena, symbol.name, obj, symbol_idx); lnk_symbol_table_push_(task->symtab, arena, worker_id, defn); } } break; case COFF_SymbolValueInterp_Debug: { // not used } break; default: { InvalidPath; } break; } } } internal LNK_SymbolHashTrie ** lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj) { LNK_SymbolHashTrie **symlinks = push_array(arena, LNK_SymbolHashTrie *, obj->header.section_count_no_null+1); COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular && symbol.aux_symbol_count == 0 && symbol.storage_class == COFF_SymStorageClass_External) { COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number); if (sect_header->flags & COFF_SectionFlag_LnkCOMDAT) { if (symlinks[symbol.section_number] == 0 || symbol.value == 0) { symlinks[symbol.section_number] = lnk_symbol_table_search_(symtab, symbol.name); } } } } return symlinks; } internal THREAD_POOL_TASK_FUNC(lnk_assign_comdat_symlinks_task) { LNK_InputCoffSymbolTable *task = raw_task; LNK_Obj *obj = task->objs[task_id]; obj->symlinks = lnk_symlinks_from_obj(arena, task->symtab, obj); } internal void lnk_push_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs) { ProfBeginFunction(); LNK_InputCoffSymbolTable task = { .symtab = symtab, .objs = objs }; tp_for_parallel(tp, arena, objs_count, lnk_input_coff_symbol_table, &task); tp_for_parallel(tp, arena, objs_count, lnk_assign_comdat_symlinks_task, &task); ProfEnd(); } internal COFF_ParsedSymbol lnk_obj_match_symbol(LNK_Obj *obj, String8 match_name) { COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); if (str8_match(symbol.name, match_name, 0)) { return symbol; } } return (COFF_ParsedSymbol){0}; } internal MSCRT_FeatFlags lnk_obj_get_features(LNK_Obj *obj) { return lnk_obj_match_symbol(obj, str8_lit("@feat.00")).value; } internal U32 lnk_obj_get_comp_id(LNK_Obj *obj) { return lnk_obj_match_symbol(obj, str8_lit("@comp.id")).value; } internal U32 lnk_obj_get_vol_md(LNK_Obj *obj) { return lnk_obj_match_symbol(obj, str8_lit("@vol.md")).value; } internal LNK_Lib * lnk_obj_get_lib(LNK_Obj *obj) { return obj->link_member ? obj->link_member->lib : 0; } internal String8 lnk_obj_get_lib_path(LNK_Obj *obj) { String8 lib_path = {0}; if (obj) { LNK_Lib *lib = lnk_obj_get_lib(obj); lib_path = lib ? lib->path : str8_zero(); } return lib_path; } internal U32 lnk_obj_get_removed_section_number(LNK_Obj *obj) { return obj->header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16; } internal LNK_Symbol * lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number) { LNK_SymbolHashTrie *symlink = obj->symlinks[section_number]; return symlink ? symlink->symbol : 0; } internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number) { COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; COFF_SectionHeader *section_header = §ion_table[section_number-1]; return section_header; } internal COFF_RelocArray lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_header) { COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section_header); COFF_Reloc *relocs = (COFF_Reloc *)(obj->data.str + reloc_info.array_off); COFF_RelocArray result = { .count = reloc_info.count, .v = relocs }; return result; } internal COFF_SectionHeader * lnk_coff_section_table_from_obj(LNK_Obj *obj) { return (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; } internal String8 lnk_coff_string_table_from_obj(LNK_Obj *obj) { return str8_substr(obj->data, obj->header.string_table_range); } internal String8 lnk_coff_symbol_table_from_obj(LNK_Obj *obj) { return str8_substr(obj->data, obj->header.symbol_table_range); } internal COFF_RelocArray lnk_coff_reloc_info_from_section_number(LNK_Obj *obj, U64 section_number) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section_header); COFF_Reloc *relocs = str8_deserial_get_raw_ptr(obj->data, reloc_info.array_off, sizeof(*relocs)*reloc_info.count); COFF_RelocArray result = { .count = reloc_info.count, .v = relocs }; return result; } internal B32 lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out) { Assert(section_number > 0); U32 symbol_idx = obj->comdats[section_number-1]; if (symbol_idx != max_U32) { COFF_ParsedSymbol secdef = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); coff_parse_secdef(secdef, obj->header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out); return 1; } return 0; } internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx) { String8 string_table = str8_substr(obj->data, obj->header.string_table_range); String8 symbol_table = str8_substr(obj->data, obj->header.symbol_table_range); COFF_ParsedSymbol result = {0}; if (obj->header.is_big_obj) { result = coff_parse_symbol32(string_table, (COFF_Symbol32 *)symbol_table.str + symbol_idx); } else { result = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx); } return result; } internal THREAD_POOL_TASK_FUNC(lnk_collect_obj_chunks_task) { LNK_SectionCollector *task = raw_task; LNK_Obj *obj = task->objs[task_id]; COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; String8 string_table = str8_substr(obj->data, obj->header.string_table_range); for (U32 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; if (section_header->flags & COFF_SectionFlag_LnkRemove) { if (!task->collect_discarded) { continue; } } String8 section_name = coff_name_from_section_header(string_table, section_header); if (str8_match(section_name, task->name, 0)) { String8 section_data = str8_substr(obj->data, rng_1u64(section_header->foff, section_header->foff + section_header->fsize)); str8_list_push(arena, &task->out_lists[task_id], section_data); } } } internal String8List * lnk_collect_obj_sections(TP_Context *tp, TP_Arena *arena, U64 objs_count, LNK_Obj **objs, String8 name, B32 collect_discarded) { LNK_SectionCollector task = {0}; task.objs = objs; task.name = name; task.collect_discarded = collect_discarded; task.out_lists = push_array(arena->v[0], String8List, objs_count); tp_for_parallel(tp, arena, objs_count, lnk_collect_obj_chunks_task, &task); return task.out_lists; } internal B32 lnk_obj_is_before(void *raw_a, void *raw_b) { LNK_Obj *a = raw_a, *b = raw_b; return a->input_idx < b->input_idx; } internal void lnk_parse_msvc_linker_directive(Arena *arena, LNK_Obj *obj, LNK_DirectiveInfo *directive_info, String8 buffer) { Temp scratch = scratch_begin(&arena, 1); String8 to_parse; { local_persist const U8 bom_sig[] = { 0xEF, 0xBB, 0xBF }; local_persist const U8 ascii_sig[] = { 0x20, 0x20, 0x20 }; if (MemoryMatch(buffer.str, &bom_sig[0], sizeof(bom_sig))) { to_parse = str8_zero(); lnk_error_obj(LNK_Error_IllData, obj, "TODO: support for BOM encoding"); } else if (MemoryMatch(buffer.str, &ascii_sig[0], sizeof(ascii_sig))) { to_parse = str8_skip(buffer, sizeof(ascii_sig)); } else { to_parse = buffer; } } String8List arg_list = lnk_arg_list_parse_windows_rules(scratch.arena, to_parse); LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, arg_list); for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) { LNK_CmdSwitch *cmd_switch = lnk_cmd_switch_from_string(opt->string); if (cmd_switch == 0) { lnk_error_obj(LNK_Warning_UnknownDirective, obj, "unknown directive \"%S\"", opt->string); continue; } if (!cmd_switch->is_legal_directive) { lnk_error_obj(LNK_Warning_IllegalDirective, obj, "illegal directive \"%S\"", opt->string); continue; } LNK_Directive *directive = push_array_no_zero(arena, LNK_Directive, 1); directive->next = 0; directive->id = str8_cstring(cmd_switch->name); directive->value_list = str8_list_copy(arena, &opt->value_strings); LNK_DirectiveList *directive_list = &directive_info->v[cmd_switch->type]; SLLQueuePush(directive_list->first, directive_list->last, directive); ++directive_list->count; } scratch_end(scratch); } internal String8List lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj) { COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); String8List drectve_data = {0}; for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (sect_header->flags & COFF_SectionFlag_LnkInfo) { String8 sect_name = str8_cstring_capped(sect_header->name, sect_header->name + sizeof(sect_header->name)); if (str8_match(sect_name, str8_lit(".drectve"), 0)) { if (sect_header->flags & COFF_SectionFlag_CntUninitializedData) { lnk_error_obj(LNK_Error_IllData, obj, ".drectve section header has flag COFF_SectionFlag_CntUninitializedData"); break; } if (sect_header->fsize < 3) { lnk_error_obj(LNK_Error_IllData, obj, "not enough bytes to parse .drectve"); break; } if (sect_header->reloc_count > 0) { lnk_error_obj(LNK_Error_IllData, obj, ".drectve must not have relocations"); break; } Rng1U64 sect_range = rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize); str8_list_push(arena, &drectve_data, str8_substr(obj->data, sect_range)); } } } return drectve_data; } internal LNK_DirectiveInfo lnk_directive_info_from_raw_directives(Arena *arena, LNK_Obj *obj, String8List raw_directives) { LNK_DirectiveInfo directive_info = {0}; for (String8Node *drectve_n = raw_directives.first; drectve_n != 0; drectve_n = drectve_n->next) { lnk_parse_msvc_linker_directive(arena, obj, &directive_info, drectve_n->string); } return directive_info; } internal CV_DebugS lnk_debug_s_from_obj(Arena *arena, LNK_Obj *obj) { Temp scratch = scratch_begin(&arena, 1); String8List raw_debug_s = {0}; { COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); String8 string_table = lnk_coff_string_table_from_obj(obj); for EachIndex(sect_idx, obj->header.section_count_no_null) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 section_name = coff_name_from_section_header(string_table, section_header); if (str8_match(section_name, str8_lit(".debug$S"), 0)) { String8 debug_s = str8_substr(obj->data, rng_1u64(section_header->foff, section_header->foff + section_header->fsize)); str8_list_push(scratch.arena, &raw_debug_s, debug_s); } } } CV_DebugS debug_s = {0}; { for (String8Node *node = raw_debug_s.first; node != 0; node = node->next) { // parse & merge sub sections CV_DebugS ds = cv_parse_debug_s(scratch.arena, node->string); cv_debug_s_concat_in_place(&debug_s, &ds); // make sure there is one string table String8List string_data_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_StringTable); if (string_data_list.node_count > 1) { break; } // make sure there is one file checksum table String8List checksum_data_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_FileChksms); if (checksum_data_list.node_count > 1) { continue; } } } scratch_end(scratch); return debug_s; } ================================================ FILE: src/linker/lnk_obj.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once // --- Input ------------------------------------------------------------------- typedef struct LNK_Obj { String8 path; String8 data; U32 input_idx; COFF_FileHeaderInfo header; U32 *comdats; B8 hotpatch; B8 exclude_from_debug_info; U32Node **associated_sections; LNK_SymbolHashTrie **symlinks; struct LNK_LibMemberRef *link_member; struct LNK_ObjNode *node; } LNK_Obj; typedef struct LNK_ObjNode { struct LNK_ObjNode *next; struct LNK_ObjNode *prev; LNK_Obj data; } LNK_ObjNode; typedef struct LNK_ObjList { U64 count; LNK_ObjNode *first; LNK_ObjNode *last; } LNK_ObjList; typedef struct LNK_ObjNodeArray { U64 count; LNK_ObjNode *v; } LNK_ObjNodeArray; // --- Directive Parser -------------------------------------------------------- typedef struct LNK_Directive { struct LNK_Directive *next; String8 id; String8List value_list; } LNK_Directive; typedef struct LNK_DirectiveList { U64 count; LNK_Directive *first; LNK_Directive *last; } LNK_DirectiveList; typedef struct LNK_DirectiveInfo { LNK_DirectiveList v[LNK_CmdSwitch_Count]; } LNK_DirectiveInfo; // --- Workers Contexts -------------------------------------------------------- typedef struct { struct LNK_Input **inputs; LNK_ObjNode *objs; U64 obj_id_base; U32 machine; } LNK_ObjIniter; typedef struct { LNK_SymbolTable *symtab; LNK_Obj **objs; } LNK_InputCoffSymbolTable; typedef struct { LNK_Obj **objs; String8 name; B32 collect_discarded; String8List *out_lists; } LNK_SectionCollector; // --- Error ------------------------------------------------------------------- internal String8 lnk_loc_from_obj(Arena *arena, LNK_Obj *obj); internal void lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...); internal void lnk_error_input_obj(LNK_ErrorCode code, struct LNK_Input *input, char *fmt, ...); // --- Input ------------------------------------------------------------------- internal LNK_Obj ** lnk_array_from_obj_list(Arena *arena, LNK_ObjList list); internal void lnk_obj_list_push_node_many(LNK_ObjList *list, U64 count, LNK_ObjNode *nodes); internal void lnk_obj_list_push_node(LNK_ObjList *list, LNK_ObjNode *node); internal void lnk_inputer_push_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, U64 objs_count, LNK_ObjNode *objs); // --- Metadata ---------------------------------------------------------------- internal U32 lnk_obj_get_features(LNK_Obj *obj); internal U32 lnk_obj_get_comp_id(LNK_Obj *obj); internal U32 lnk_obj_get_vol_md(LNK_Obj *obj); internal struct LNK_Lib * lnk_obj_get_lib(LNK_Obj *obj); internal String8 lnk_obj_get_lib_path(LNK_Obj *obj); internal U32 lnk_obj_get_removed_section_number(LNK_Obj *obj); internal LNK_Symbol * lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number); // --- Symbol & Section Helpers ------------------------------------------------ internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff(LNK_Obj *obj, void *coff_symbol); internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx); internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number); internal COFF_RelocArray lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_header); internal COFF_SectionHeader * lnk_coff_section_table_from_obj(LNK_Obj *obj); internal String8 lnk_coff_string_table_from_obj(LNK_Obj *obj); internal String8 lnk_coff_symbol_table_from_obj(LNK_Obj *obj); internal B32 lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out); // --- Helpers ----------------------------------------------------------------- internal String8List * lnk_collect_obj_sections(TP_Context *tp, TP_Arena *arena, U64 objs_count, LNK_Obj **objs, String8 name, B32 collect_discarded); internal B32 lnk_obj_is_before(void *raw_a, void *raw_b); // --- Directive Parser -------------------------------------------------------- internal void lnk_parse_msvc_linker_directive(Arena *arena, LNK_Obj *obj, LNK_DirectiveInfo *directive_info, String8 buffer); internal String8List lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj); internal LNK_DirectiveInfo lnk_directive_info_from_raw_directives(Arena *arena, LNK_Obj *obj, String8List raw_directives); // --- Debug Info -------------------------------------------------------------- internal CV_DebugS lnk_debug_s_from_obj(Arena *arena, LNK_Obj *obj); ================================================ FILE: src/linker/lnk_section_table.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal LNK_SectionContrib * lnk_section_contrib_chunk_push(LNK_SectionContribChunk *chunk, U64 count) { Assert(chunk->count + count <= chunk->cap); LNK_SectionContrib *result = chunk->v[chunk->count]; chunk->count += count; return result; } internal LNK_SectionContrib * lnk_section_contrib_chunk_push_atomic(LNK_SectionContribChunk *chunk, U64 count) { U64 pos = ins_atomic_u64_add_eval(&chunk->count, count) - count; Assert(pos + count <= chunk->cap); LNK_SectionContrib *result = chunk->v[pos]; return result; } internal LNK_SectionContribChunk * lnk_section_contrib_chunk_list_push_chunk(Arena *arena, LNK_SectionContribChunkList *list, U64 cap, String8 sort_idx) { LNK_SectionContribChunk *chunk = push_array(arena, LNK_SectionContribChunk, 1); chunk->count = 0; chunk->cap = cap; chunk->v = push_array(arena, LNK_SectionContrib *, cap); chunk->v2 = push_array(arena, LNK_SectionContrib, cap); chunk->sort_idx = sort_idx; for (U64 i = 0; i < cap; i += 1) { chunk->v[i] = &chunk->v2[i]; } SLLQueuePush(list->first, list->last, chunk); list->chunk_count += 1; return chunk; } internal void lnk_section_contrib_chunk_list_concat_in_place(LNK_SectionContribChunkList *list, LNK_SectionContribChunkList *to_concat) { if (list->chunk_count == 0) { *list = *to_concat; } else { list->last->next = to_concat->first; list->last = to_concat->last; list->chunk_count += to_concat->chunk_count; } } internal LNK_SectionContribChunk ** lnk_array_from_section_contrib_chunk_list(Arena *arena, LNK_SectionContribChunkList list) { LNK_SectionContribChunk **result = push_array(arena, LNK_SectionContribChunk *, list.chunk_count); U64 i = 0; for (LNK_SectionContribChunk *chunk = list.first; chunk != 0; chunk = chunk->next, i += 1) { result[i] = chunk; } return result; } internal void lnk_section_list_push_node(LNK_SectionList *list, LNK_SectionNode *node) { DLLPushBack(list->first, list->last, node); list->count += 1; } internal void lnk_section_list_remove_node(LNK_SectionList *list, LNK_SectionNode *node) { DLLRemove(list->first, list->last, node); list->count -= 1; } internal LNK_SectionArray lnk_section_array_from_list(Arena *arena, LNK_SectionList list) { LNK_SectionArray result; result.count = 0; result.v = push_array_no_zero(arena, LNK_Section *, list.count); for (LNK_SectionNode *node = list.first; node != 0; node = node->next) { result.v[result.count] = &node->data; result.count += 1; } return result; } internal String8 lnk_make_name_with_flags(Arena *arena, String8 name, COFF_SectionFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List l = {0}; str8_list_push(scratch.arena, &l, name); str8_list_push(scratch.arena, &l, str8_struct(&flags)); String8 name_with_flags = str8_list_join(arena, &l, 0); scratch_end(scratch); return name_with_flags; } internal LNK_SectionTable * lnk_section_table_alloc(void) { ProfBeginFunction(); Arena *arena = arena_alloc(); LNK_SectionTable *sectab = push_array(arena, LNK_SectionTable, 1); sectab->arena = arena; sectab->sect_ht = hash_table_init(arena, 256); ProfEnd(); return sectab; } internal void lnk_section_table_release(LNK_SectionTable **sectab_ptr) { ProfBeginFunction(); LNK_SectionTable *sectab = *sectab_ptr; arena_release(sectab->arena); *sectab_ptr = 0; ProfEnd(); } internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags) { ProfBeginFunction(); LNK_SectionNode *sect_node = push_array(sectab->arena, LNK_SectionNode, 1); LNK_Section *sect = §_node->data; sect->name = push_str8_copy(sectab->arena, name); sect->flags = flags; LNK_SectionList *sect_list = §ab->list; DLLPushBack(sect_list->first, sect_list->last, sect_node); sect_list->count += 1; String8 name_with_flags = lnk_make_name_with_flags(sectab->arena, name, flags); hash_table_push_string_raw(sectab->arena, sectab->sect_ht, name_with_flags, sect); ProfEnd(); return sect; } internal LNK_SectionNode * lnk_section_table_remove(LNK_SectionTable *sectab, String8 name) { ProfBeginFunction(); LNK_SectionNode *node; for (node = sectab->list.first; node != 0; node = node->next) { if (str8_match(node->data.name, name, 0)) { lnk_section_list_remove_node(§ab->list, node); break; } } ProfEnd(); return node; } internal void lnk_section_table_purge(LNK_SectionTable *sectab, String8 name) { Temp scratch = scratch_begin(0,0); LNK_SectionNode *node = lnk_section_table_remove(sectab, name); String8 name_with_flags = lnk_make_name_with_flags(scratch.arena, name, node->data.flags); hash_table_purge_string(sectab->sect_ht, name_with_flags); scratch_end(scratch); } internal LNK_Section * lnk_section_table_search(LNK_SectionTable *sectab, String8 full_or_partial_name, COFF_SectionFlags flags) { Temp scratch = scratch_begin(0,0); String8 name = {0}; String8 postfix = {0}; coff_parse_section_name(full_or_partial_name, &name, &postfix); String8 name_with_flags = lnk_make_name_with_flags(scratch.arena, name, flags); LNK_Section *section = hash_table_search_string_raw(sectab->sect_ht, name_with_flags); scratch_end(scratch); return section; } internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name) { String8 name = {0}; String8 postfix = {0}; coff_parse_section_name(full_or_partial_name, &name, &postfix); U64 match_count = 0; for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { if (str8_match(sect_n->data.name, name, 0)) { match_count += 1; } } LNK_SectionArray result = {0}; if (match_count > 0) { result.count = 0; result.v = push_array(arena, LNK_Section *, match_count); for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { if (str8_match(sect_n->data.name, name, 0)) { result.v[result.count++] = §_n->data; } } } return result; } internal void lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_list) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); for (LNK_MergeDirectiveNode *merge_node = merge_list.first; merge_node != 0; merge_node = merge_node->next) { LNK_MergeDirective *merge = &merge_node->v; // guard against illegal merges { local_persist String8 illegal_merge_sections[] = { str8_lit_comp(".rsrc"), str8_lit_comp(".reloc"), }; for EachIndex(i, ArrayCount(illegal_merge_sections)) { if (str8_match(merge->src, illegal_merge_sections[i], 0)) { lnk_error(LNK_Error_IllegalSectionMerge, "illegal to merge %S with %S", illegal_merge_sections[i], merge->dst); } if (str8_match(merge->dst, illegal_merge_sections[i], 0)) { lnk_error(LNK_Error_IllegalSectionMerge, "illegal to merge %S with %S", merge->src, illegal_merge_sections[i]); } } } // guard against circular merges { if (str8_match(merge_node->v.dst, merge_node->v.src, 0)) { lnk_error(LNK_Error_CircularMerge, "detected circular /MERGE:%S=%S", merge_node->v.src, merge_node->v.dst); } for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) { if (str8_match(sect_n->data.name, merge_node->v.dst, 0)) { lnk_error(LNK_Error_CircularMerge, "detected circular /MERGE:%S=%S", merge_node->v.src, merge_node->v.dst); } } } // are we trying to merge section that was already merged? LNK_Section *merge_sect = hash_table_search_string_raw(sectab->sect_ht, merge->src); if (merge_sect && merge_sect->merge_dst) { LNK_Section *dst = merge_sect->merge_dst; B32 is_ambiguous_merge = !str8_match(dst->name, merge->dst, 0); if (is_ambiguous_merge) { lnk_error(LNK_Warning_AmbiguousMerge, "Detected ambiguous section merge:"); lnk_supplement_error("%S => %S (Merged)", merge_sect->name, dst->name); lnk_supplement_error("%S => %S", merge_sect->name, merge->dst); } continue; } // find source seciton LNK_SectionArray src_matches = lnk_section_table_search_many(scratch.arena, sectab, merge->src); if (src_matches.count == 0) { continue; } LNK_Section *dst; { LNK_SectionArray dst_matches = lnk_section_table_search_many(scratch.arena, sectab, merge->dst); if (dst_matches.count > 1) { lnk_error(LNK_Warning_AmbiguousMerge, "unable to merge %S=%S, too many dest sections (%llu)", merge->src, merge->dst, dst_matches.count); continue; } // push a new section if the destination section does not exist if (dst_matches.count == 0) { dst = lnk_section_table_push(sectab, merge->dst, src_matches.v[0]->flags); } else { dst = dst_matches.v[0]; } } for EachIndex(src_idx, src_matches.count) { LNK_Section *src = src_matches.v[src_idx]; if (src->flags != dst->flags) { lnk_error(LNK_Warning_AmbiguousMerge, "unable to merge %S=%S because of conflicting section flags", merge->src, merge->dst); continue; } // merge section with destination lnk_section_contrib_chunk_list_concat_in_place(&dst->contribs, &src->contribs); src->merge_dst = dst; // remove node from output section list LNK_SectionNode *merge_node = lnk_section_table_remove(sectab, src->name); // move node to the merge list lnk_section_list_push_node(§ab->merge_list, merge_node); } } scratch_end(scratch); ProfEnd(); } internal U64 lnk_section_table_total_fsize(LNK_SectionTable *sectab) { U64 total_fsize = 0; for EachNode(n, LNK_SectionNode, sectab->list.first) { total_fsize += n->data.fsize; } return total_fsize; } internal U64 lnk_section_table_total_vsize(LNK_SectionTable *sectab) { U64 total_vsize = 0; for EachNode(n, LNK_SectionNode, sectab->list.first) { total_vsize += n->data.vsize; } return total_vsize; } internal int lnk_section_contrib_chunk_is_before(void *raw_a, void *raw_b) { LNK_SectionContribChunk **a = raw_a, **b = raw_b; return str8_is_before_case_sensitive(&(*a)->sort_idx, &(*b)->sort_idx); } internal void lnk_sort_section_contribs(LNK_Section *sect) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); LNK_SectionContribChunk **chunks = lnk_array_from_section_contrib_chunk_list(scratch.arena, sect->contribs); radsort(chunks, sect->contribs.chunk_count, lnk_section_contrib_chunk_is_before); // repopulate chunk list in sorted order sect->contribs.first = 0; sect->contribs.last = 0; for (U64 chunk_idx = 0; chunk_idx < sect->contribs.chunk_count; chunk_idx += 1) { SLLQueuePush(sect->contribs.first, sect->contribs.last, chunks[chunk_idx]); } scratch_end(scratch); ProfEnd(); } internal void lnk_finalize_section_layout(LNK_Section *sect, U64 file_align, U64 pad_size) { ProfBegin("Layout Contribs"); U64 cursor = 0; for (LNK_SectionContribChunk *sc_chunk = sect->contribs.first; sc_chunk != 0; sc_chunk = sc_chunk->next) { for (U64 sc_idx = 0; sc_idx < sc_chunk->count; sc_idx += 1) { LNK_SectionContrib *sc = sc_chunk->v[sc_idx]; // add section pad bytes if (sc->hotpatch) { cursor += pad_size; } // assign offset cursor = AlignPow2(cursor, sc->align); sc->u.off = cursor; // advance cursor U64 sc_size = lnk_size_from_section_contrib(sc); cursor += sc_size; } } ProfEnd(); if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { sect->fsize = AlignPow2(cursor, file_align); } sect->vsize = cursor; } internal void lnk_assign_section_index(LNK_Section *sect, U64 sect_idx) { sect->sect_idx = sect_idx; // assign section indices to contribs for (LNK_SectionContribChunk *sc_chunk = sect->contribs.first; sc_chunk != 0; sc_chunk = sc_chunk->next) { for (U64 sc_idx = 0; sc_idx < sc_chunk->count; sc_idx += 1) { sc_chunk->v[sc_idx]->u.sect_idx = sect_idx; } } } internal void lnk_assign_section_virtual_space(LNK_Section *sect, U64 sect_align, U64 *voff_cursor) { sect->voff = *voff_cursor; *voff_cursor += sect->vsize; *voff_cursor = AlignPow2(*voff_cursor, sect_align); } internal void lnk_assign_section_file_space(LNK_Section *sect, U64 *foff_cursor) { if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { sect->foff = *foff_cursor; *foff_cursor += sect->fsize; } } internal U64 lnk_size_from_section_contrib(LNK_SectionContrib *sc) { U64 size = 0; for (String8Node *n = &sc->first_data_node; n != 0; n = n->next) { size += n->string.size; } return size; } internal U64 lnk_voff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) { COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; U64 voff = sect_header->voff + sc->u.off; return voff; } internal U64 lnk_foff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) { COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; U64 foff = sect_header->foff + sc->u.off; return foff; } internal U64 lnk_fopl_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) { U64 foff = lnk_foff_from_section_contrib(image_section_table, sc); return foff + lnk_size_from_section_contrib(sc); } internal LNK_SectionContrib * lnk_get_first_section_contrib(LNK_Section *sect) { if (sect->contribs.chunk_count > 0) { if (sect->contribs.first->count > 0) { return sect->contribs.first->v[0]; } } return 0; } internal LNK_SectionContrib * lnk_get_last_section_contrib(LNK_Section *sect) { if (sect->contribs.chunk_count > 0) { if (sect->contribs.last->count > 0) { return sect->contribs.last->v[sect->contribs.last->count-1]; } } return 0; } internal U64 lnk_get_section_contrib_size(LNK_Section *sect) { LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); U64 size = (last_sc->u.off - first_sc->u.off) + lnk_size_from_section_contrib(last_sc); return size; } internal U64 lnk_get_first_section_contrib_voff(COFF_SectionHeader **image_section_table, LNK_Section *sect) { LNK_SectionContrib *sc = lnk_get_first_section_contrib(sect); return lnk_voff_from_section_contrib(image_section_table, sc); } ================================================ FILE: src/linker/lnk_section_table.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef struct LNK_SectionContrib { String8Node first_data_node; // most contributions require at least one data node, so preallocate it here String8Node *last_data_node; // list of data nodes that contribute to final section union { // used to sort sections to get deterministic output struct { U32 obj_idx; // index of the input obj that contributes to the image section U32 obj_sect_idx; // index into contributing obj's section table }; // used after section layout is finalized struct { U32 off; // contribution offset within the image section U16 sect_idx; // section index in the image U8 unused[2]; }; } u; U16 align; // contribution alignment in the image B8 hotpatch; } LNK_SectionContrib; typedef struct LNK_SectionContribChunk { struct LNK_SectionContribChunk *next; U64 count; U64 cap; String8 sort_idx; LNK_SectionContrib **v; LNK_SectionContrib *v2; } LNK_SectionContribChunk; typedef struct LNK_SectionContribChunkList { U64 chunk_count; LNK_SectionContribChunk *first; LNK_SectionContribChunk *last; } LNK_SectionContribChunkList; typedef struct LNK_Section { String8 name; COFF_SectionFlags flags; LNK_SectionContribChunkList contribs; struct LNK_Section *merge_dst; U64 voff; U64 vsize; U64 fsize; U64 foff; U64 sect_idx; } LNK_Section; typedef struct LNK_SectionNode { struct LNK_SectionNode *next; struct LNK_SectionNode *prev; LNK_Section data; } LNK_SectionNode; typedef struct LNK_SectionList { U64 count; LNK_SectionNode *first; LNK_SectionNode *last; } LNK_SectionList; typedef struct LNK_SectionArray { U64 count; LNK_Section **v; } LNK_SectionArray; typedef struct LNK_SectionTable { Arena *arena; LNK_SectionList list; LNK_SectionList merge_list; HashTable *sect_ht; // (name * COFF_SectionFlags) -> LNK_Section * U64 next_sect_idx; } LNK_SectionTable; // --- Section Contrib Chunk List ---------------------------------------------- internal LNK_SectionContrib * lnk_section_contrib_chunk_push(LNK_SectionContribChunk *chunk, U64 count); internal LNK_SectionContrib * lnk_section_contrib_chunk_push_atomic(LNK_SectionContribChunk *chunk, U64 count); internal LNK_SectionContribChunk * lnk_section_contrib_chunk_list_push_chunk(Arena *arena, LNK_SectionContribChunkList *list, U64 cap, String8 sort_idx); internal void lnk_section_contrib_chunk_list_concat_in_place(LNK_SectionContribChunkList *list, LNK_SectionContribChunkList *to_concat); internal LNK_SectionContribChunk ** lnk_array_from_section_contrib_chunk_list(Arena *arena, LNK_SectionContribChunkList list); // --- Section List ------------------------------------------------------------ internal LNK_SectionArray lnk_section_array_from_list(Arena *arena, LNK_SectionList list); // --- Section Table ----------------------------------------------------------- internal String8 lnk_make_name_with_flags(Arena *arena, String8 name, COFF_SectionFlags flags); internal LNK_SectionTable * lnk_section_table_alloc(void); internal void lnk_section_table_release(LNK_SectionTable **sectab_ptr); internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); internal LNK_SectionNode * lnk_section_table_remove(LNK_SectionTable *sectab, String8 name); internal void lnk_section_table_purge(LNK_SectionTable *sectab, String8 name); internal LNK_Section * lnk_section_table_search(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name); internal void lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_list); internal U64 lnk_section_table_total_fsize(LNK_SectionTable *sectab); internal U64 lnk_section_table_total_vsize(LNK_SectionTable *sectab); // --- Section Finalization ---------------------------------------------------- internal void lnk_finalize_section_layout (LNK_Section *sect, U64 file_align, U64 pad_size); internal void lnk_assign_section_index (LNK_Section *sect, U64 sect_idx); internal void lnk_assign_section_virtual_space(LNK_Section *sect, U64 sect_align, U64 *voff_cursor); internal void lnk_assign_section_file_space (LNK_Section *sect, U64 *foff_cursor); // --- Section Contribution ---------------------------------------------------- internal U64 lnk_size_from_section_contrib(LNK_SectionContrib *sc); internal U64 lnk_voff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc); internal U64 lnk_foff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc); internal U64 lnk_fopl_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc); internal LNK_SectionContrib * lnk_get_first_section_contrib(LNK_Section *sect); internal LNK_SectionContrib * lnk_get_last_section_contrib(LNK_Section *sect); internal U64 lnk_get_section_contrib_size(LNK_Section *sect); internal U64 lnk_get_first_section_contrib_voff(COFF_SectionHeader **image_section_table, LNK_Section *sect); ================================================ FILE: src/linker/lnk_symbol_table.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal LNK_Symbol * lnk_make_symbol(Arena *arena, String8 name, LNK_Obj *obj, U32 symbol_idx) { LNK_ObjSymbolRefNode *ref = push_array(arena, LNK_ObjSymbolRefNode, 1); ref->v.obj = obj; ref->v.symbol_idx = symbol_idx; LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1); symbol->name = name; symbol->refs = ref; return symbol; } internal int lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b) { LNK_ObjSymbolRef *a_ref = raw_a; LNK_ObjSymbolRef *b_ref = raw_b; LNK_Lib *a_lib = lnk_obj_get_lib(a_ref->obj); LNK_Lib *b_lib = lnk_obj_get_lib(b_ref->obj); U32 a_lib_input_idx = a_lib ? a_lib->input_idx : 0; U32 b_lib_input_idx = b_lib ? b_lib->input_idx : 0; if (a_lib_input_idx == b_lib_input_idx) { if (a_ref->obj->input_idx == b_ref->obj->input_idx) { return a_ref->symbol_idx < b_ref->symbol_idx; } return a_ref->obj->input_idx < b_ref->obj->input_idx; } return a_lib_input_idx < b_lib_input_idx; } internal int lnk_obj_symbol_ref_ptr_is_before(void *raw_a, void *raw_b) { LNK_ObjSymbolRef **a = raw_a, **b = raw_b; return lnk_obj_symbol_ref_is_before(*a, *b); } internal int lnk_symbol_is_before(void *raw_a, void *raw_b) { LNK_Symbol *a = raw_a, *b = raw_b; LNK_ObjSymbolRef a_ref = lnk_ref_from_symbol(a); LNK_ObjSymbolRef b_ref = lnk_ref_from_symbol(b); return lnk_obj_symbol_ref_is_before(&a_ref, &b_ref); } internal int lnk_symbol_ptr_is_before(void *raw_a, void *raw_b) { return lnk_symbol_is_before(*(LNK_Symbol **)raw_a, *(LNK_Symbol **)raw_b); } internal void lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal LNK_SymbolNode * lnk_symbol_list_push(Arena *arena, LNK_SymbolList *list, LNK_Symbol *symbol) { LNK_SymbolNode *node = push_array(arena, LNK_SymbolNode, 1); node->data = symbol; lnk_symbol_list_push_node(list, node); return node; } internal LNK_SymbolHashTrie * lnk_symbol_hash_trie_chunk_list_push(Arena *arena, LNK_SymbolHashTrieChunkList *list, U64 cap) { if (list->last == 0 || list->last->count >= list->last->cap) { LNK_SymbolHashTrieChunk *chunk = push_array(arena, LNK_SymbolHashTrieChunk, 1); chunk->cap = cap; chunk->v = push_array_no_zero(arena, LNK_SymbolHashTrie, cap); SLLQueuePush(list->first, list->last, chunk); ++list->count; } LNK_SymbolHashTrie *result = &list->last->v[list->last->count++]; return result; } internal void lnk_symbol_hash_trie_chunk_list_concat_in_place(LNK_SymbolHashTrieChunkList *list, LNK_SymbolHashTrieChunkList *to_concat) { SLLConcatInPlace(list, to_concat); } internal void lnk_error_multiply_defined_symbol(LNK_Symbol *dst, LNK_Symbol *src) { LNK_ObjSymbolRef dst_ref = lnk_ref_from_symbol(dst); LNK_ObjSymbolRef src_ref = lnk_ref_from_symbol(src); lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, dst_ref.obj, "symbol \"%S\" (No. %#x) is multiply defined in %S (No. %#x)", dst->name, dst_ref.symbol_idx, src_ref.obj->path, src_ref.symbol_idx); } internal B32 lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src) { B32 can_replace = 0; COFF_ParsedSymbol dst_parsed = lnk_parsed_from_symbol(dst); COFF_ParsedSymbol src_parsed = lnk_parsed_from_symbol(src); COFF_SymbolValueInterpType dst_interp = lnk_interp_from_symbol(dst); COFF_SymbolValueInterpType src_interp = lnk_interp_from_symbol(src); LNK_ObjSymbolRef dst_ref = lnk_ref_from_symbol(dst); LNK_ObjSymbolRef src_ref = lnk_ref_from_symbol(src); LNK_Obj *dst_obj = dst_ref.obj; LNK_Obj *src_obj = src_ref.obj; // undefined vs regular if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Regular) { can_replace = 1; } // (weak vs undefined) or (undefined vs weak) else if ((dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Undefined) || (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Weak)) { LNK_Symbol *weak, *undef; COFF_ParsedSymbol weak_parsed; if (dst_interp == COFF_SymbolValueInterp_Weak) { weak = dst, undef = src; weak_parsed = dst_parsed; } else { weak = src, undef = dst; weak_parsed = src_parsed; } LNK_ObjSymbolRef weak_symbol_ref = lnk_ref_from_symbol(weak); COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak_symbol_ref.obj->header.is_big_obj); if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) { // NOTE: MSVC does not let a weak symbol to replace an undefined one, // but LLD links without errors or warnings, meaning undefined symbols // are resolved to the weak, which can potentially change behaviour of // the linked image can_replace = dst_interp == COFF_SymbolValueInterp_Weak; } else if (weak_ext->characteristics == COFF_WeakExt_NoLibrary) { can_replace = dst_interp == COFF_SymbolValueInterp_Weak; } else if (weak_ext->characteristics == COFF_WeakExt_SearchAlias) { can_replace = dst_interp == COFF_SymbolValueInterp_Undefined; } else { can_replace = lnk_symbol_is_before(src, dst); } } // undefined vs undefined else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) { can_replace = lnk_symbol_is_before(src, dst); } // undefined vs common else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Common) { can_replace = 1; } // undefined vs abs else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Abs) { can_replace = 1; } // undefined vs debug else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Debug) { can_replace = 1; } // regular/common/abs/debug vs undefined else if (dst_interp != COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) { can_replace = 0; } // regular vs abs else if (dst_interp == COFF_SymbolValueInterp_Regular && src_interp == COFF_SymbolValueInterp_Abs) { lnk_error_multiply_defined_symbol(dst, src); } // abs vs regular else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Regular) { lnk_error_multiply_defined_symbol(dst, src); } // abs vs common else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Common) { if (lnk_symbol_is_before(dst, src)) { can_replace = 1; } else { lnk_error_multiply_defined_symbol(dst, src); } } // common vs abs else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Abs) { if (lnk_symbol_is_before(dst, src)) { lnk_error_multiply_defined_symbol(dst, src); } } // abs vs abs else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Abs) { lnk_error_multiply_defined_symbol(dst, src); } // weak vs weak else if (dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Weak) { COFF_SymbolWeakExt *dst_ext = coff_parse_weak_tag(dst_parsed, dst_ref.obj->header.is_big_obj); COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src_ref.obj->header.is_big_obj); if ((dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias)) { if (lnk_symbol_is_before(dst, src) || src_ext->characteristics == COFF_WeakExt_AntiDependency) { can_replace = 0; } else { lnk_error_multiply_defined_symbol(dst, src); } } else if (dst_ext->characteristics != COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) { if (lnk_symbol_is_before(src, dst) || dst_ext->characteristics == COFF_WeakExt_AntiDependency) { can_replace = 1; } else { lnk_error_multiply_defined_symbol(dst, src); } } else if (dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) { lnk_error_multiply_defined_symbol(dst, src); } else { can_replace = lnk_symbol_is_before(src, dst); } } // weak vs regular/abs/common else if (dst_interp == COFF_SymbolValueInterp_Weak && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Abs || src_interp == COFF_SymbolValueInterp_Common)) { can_replace = 1; } // regular/abs/common vs weak else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Abs || dst_interp == COFF_SymbolValueInterp_Common) && src_interp == COFF_SymbolValueInterp_Weak) { can_replace = 0; } // regular/common vs regular/common else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Common) && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common)) { // parse dst symbol properties B32 dst_is_comdat = 0; COFF_ComdatSelectType dst_select; U32 dst_section_length; U32 dst_check_sum; if (dst_interp == COFF_SymbolValueInterp_Regular) { dst_is_comdat = lnk_try_comdat_props_from_section_number(dst_ref.obj, dst_parsed.section_number, &dst_select, 0, &dst_section_length, &dst_check_sum); } else if (dst_interp == COFF_SymbolValueInterp_Common) { dst_select = COFF_ComdatSelect_Largest; dst_section_length = dst_parsed.value; dst_check_sum = 0; dst_is_comdat = 1; } // parse src symbol properties B32 src_is_comdat = 0; COFF_ComdatSelectType src_select; U32 src_section_length, src_checks; U32 src_check_sum; if (src_interp == COFF_SymbolValueInterp_Regular) { src_is_comdat = lnk_try_comdat_props_from_section_number(src_ref.obj, src_parsed.section_number, &src_select, 0, &src_section_length, &src_check_sum); } else if (src_interp == COFF_SymbolValueInterp_Common) { src_select = COFF_ComdatSelect_Largest; src_section_length = src_parsed.value; src_check_sum = 0; src_is_comdat = 1; } // regular non-comdat vs communal if (dst_interp == COFF_SymbolValueInterp_Regular && !dst_is_comdat && src_interp == COFF_SymbolValueInterp_Common) { can_replace = 0; } // communal vs regular non-comdat else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Regular && !src_is_comdat) { can_replace = 1; } // handle COMDATs else if (dst_is_comdat && src_is_comdat) { if ((src_select == COFF_ComdatSelect_Any && dst_select == COFF_ComdatSelect_Largest)) { src_select = COFF_ComdatSelect_Largest; } if (src_select == COFF_ComdatSelect_Largest && dst_select == COFF_ComdatSelect_Any) { dst_select = COFF_ComdatSelect_Largest; } if (src_select == dst_select) { switch (src_select) { case COFF_ComdatSelect_Null: case COFF_ComdatSelect_Any: { can_replace = lnk_obj_is_before(src_obj, dst_obj); } break; case COFF_ComdatSelect_NoDuplicates: { lnk_error_multiply_defined_symbol(dst, src); } break; case COFF_ComdatSelect_SameSize: { if (dst_section_length == src_section_length) { can_replace = lnk_obj_is_before(src_obj, dst_obj); } else { lnk_error_multiply_defined_symbol(dst, src); } } break; case COFF_ComdatSelect_ExactMatch: { COFF_SectionHeader *dst_sect_header = lnk_coff_section_header_from_section_number(dst_obj, dst_parsed.section_number); COFF_SectionHeader *src_sect_header = lnk_coff_section_header_from_section_number(src_obj, src_parsed.section_number); String8 dst_data = str8_substr(dst_obj->data, rng_1u64(dst_sect_header->foff, dst_sect_header->foff + dst_sect_header->fsize)); String8 src_data = str8_substr(src_obj->data, rng_1u64(src_sect_header->foff, src_sect_header->foff + src_sect_header->fsize)); B32 is_exact_match = 0; if (dst_check_sum != 0 && src_check_sum != 0) { is_exact_match = dst_check_sum == src_check_sum && str8_match(dst_data, src_data, 0); } else { is_exact_match = str8_match(dst_data, src_data, 0); } if (is_exact_match) { can_replace = lnk_obj_is_before(src_obj, dst_obj); } else { lnk_error_multiply_defined_symbol(dst, src); } } break; case COFF_ComdatSelect_Largest: { if (dst_section_length == src_section_length) { can_replace = lnk_obj_is_before(src_obj, dst_obj); } else { can_replace = dst_section_length < src_section_length; } } break; case COFF_ComdatSelect_Associative: { /* ignore */ } break; default: { InvalidPath; } break; } } else { lnk_error_obj(LNK_Warning_UnresolvedComdat, src_obj, "%S: COMDAT selection conflict detected, current selection %S, leader selection %S from %S", src->name, coff_string_from_comdat_select_type(src_select), coff_string_from_comdat_select_type(dst_select), dst_obj); } } else { lnk_error_multiply_defined_symbol(dst, src); } } else { lnk_error(LNK_Error_InvalidPath, "unable to find a suitable replacement logic for symbol combination"); } return can_replace; } internal void lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src) { COFF_ParsedSymbol dst_parsed = lnk_parsed_from_symbol(dst); COFF_SymbolValueInterpType dst_interp = lnk_interp_from_symbol(dst); LNK_ObjSymbolRef dst_ref = lnk_ref_from_symbol(dst); if (dst_interp == COFF_SymbolValueInterp_Regular) { // remove replaced section from the output COFF_SectionHeader *dst_sect = lnk_coff_section_header_from_section_number(dst_ref.obj, dst_parsed.section_number); dst_sect->flags |= COFF_SectionFlag_LnkRemove; // remove associated sections from the output for (U32Node *associated_section = dst_ref.obj->associated_sections[dst_parsed.section_number]; associated_section != 0; associated_section = associated_section->next) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(dst_ref.obj, associated_section->data); section_header->flags |= COFF_SectionFlag_LnkRemove; } } // merge symbol refs LNK_ObjSymbolRefNode *src_last_ref; for (src_last_ref = src->refs; src_last_ref->next != 0; src_last_ref = src_last_ref->next); src_last_ref->next = dst->refs; // assert leader section is live #if BUILD_DEBUG { COFF_ParsedSymbol src_parsed = lnk_parsed_from_symbol(src); COFF_SymbolValueInterpType src_interp = lnk_interp_from_symbol(src); LNK_ObjSymbolRef src_ref = lnk_ref_from_symbol(src); if (src_interp == COFF_SymbolValueInterp_Regular) { COFF_SectionHeader *src_sect = lnk_coff_section_header_from_section_number(src_ref.obj, src_parsed.section_number); AssertAlways(~src_sect->flags & COFF_SectionFlag_LnkRemove); } } #endif } internal void lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunks, LNK_SymbolHashTrie **trie, U64 hash, LNK_Symbol *symbol) { LNK_SymbolHashTrie **curr_trie_ptr = trie; for (U64 h = hash; ; h <<= 2) { // load current pointer LNK_SymbolHashTrie *curr_trie = ins_atomic_ptr_eval(curr_trie_ptr); if (curr_trie == 0) { // init node LNK_SymbolHashTrie *new_trie = lnk_symbol_hash_trie_chunk_list_push(arena, chunks, 0x1000); new_trie->name = &symbol->name; new_trie->symbol = symbol; MemoryZeroArray(new_trie->child); // try to insert new node LNK_SymbolHashTrie *cmp = ins_atomic_ptr_eval_cond_assign(curr_trie_ptr, new_trie, curr_trie); // was symbol inserted? if (cmp == curr_trie) { break; } // rollback chunk list push --chunks->last->count; // retry insert with trie node from another thread curr_trie = cmp; } // load current symbol String8 *curr_name = ins_atomic_ptr_eval(&curr_trie->name); if (curr_name && str8_match(*curr_name, symbol->name, 0)) { for (LNK_Symbol *src = symbol;;) { // try replacing current symbol with zero, otherwise loop back and retry LNK_Symbol *leader = ins_atomic_ptr_eval_assign(&curr_trie->symbol, 0); // apply replacement if (leader) { if (lnk_can_replace_symbol(leader, src)) { // discard leader lnk_on_symbol_replace(leader, src); leader = src; } else { // discard source lnk_on_symbol_replace(src, leader); src = leader; } } else { leader = src; } // try replacing symbol, if another thread has already taken the slot, rerun replacement loop again LNK_Symbol *was_replaced = ins_atomic_ptr_eval_cond_assign(&curr_trie->symbol, leader, 0); // symbol replaced, exit if (was_replaced == 0) { goto exit; } } } // pick child and descend curr_trie_ptr = curr_trie->child + (h >> 62); } exit:; } internal LNK_SymbolHashTrie * lnk_symbol_hash_trie_search(LNK_SymbolHashTrie *trie, U64 hash, String8 name) { LNK_SymbolHashTrie *result = 0; LNK_SymbolHashTrie **curr_ptr = ≜ for (U64 h = hash; ; h <<= 2) { LNK_SymbolHashTrie *curr = ins_atomic_ptr_eval(curr_ptr); if (curr == 0) { break; } if (curr->name && str8_match(*curr->name, name, 0)) { result = curr; break; } curr_ptr = curr->child + (h >> 62); } return result; } internal void lnk_symbol_hash_trie_remove(LNK_SymbolHashTrie *trie) { ins_atomic_ptr_eval_assign(&trie->name, 0); ins_atomic_ptr_eval_assign(&trie->symbol, 0); } internal LNK_SymbolHashTrieChunk ** lnk_array_from_symbol_hash_trie_chunk_list(Arena *arena, LNK_SymbolHashTrieChunkList *lists, U64 lists_count, U64 *count_out) { U64 chunks_count = 0; for EachIndex(i, lists_count) { chunks_count += lists[i].count; } LNK_SymbolHashTrieChunk **chunks = push_array(arena, LNK_SymbolHashTrieChunk *, chunks_count); U64 chunks_cursor = 0; for EachIndex(i, lists_count) { for (LNK_SymbolHashTrieChunk *chunk = lists[i].first; chunk != 0; chunk = chunk->next) { chunks[chunks_cursor++] = chunk; } } if (count_out) { *count_out = chunks_count; } return chunks; } internal LNK_ObjSymbolRef lnk_ref_from_symbol(LNK_Symbol *symbol) { return symbol->refs->v; } internal U64 lnk_ref_count_from_symbol(LNK_Symbol *symbol) { U64 count = 0; for (LNK_ObjSymbolRefNode *node = symbol->refs; node != 0; node = node->next, count += 1); return count; } internal LNK_ObjSymbolRef ** lnk_ref_from_symbol_many(Arena *arena, LNK_Symbol *symbol, U64 *count_out) { // TODO: would be simpler if we sorted refs on insert/update U64 refs_count = lnk_ref_count_from_symbol(symbol); LNK_ObjSymbolRef **refs = push_array(arena, LNK_ObjSymbolRef *, refs_count); U64 i = 0; for (LNK_ObjSymbolRefNode *node = symbol->refs; node != 0; node = node->next, i += 1) { refs[i] = &node->v; } radsort(refs, refs_count, lnk_obj_symbol_ref_ptr_is_before); if (count_out) { *count_out = refs_count; } return refs; } internal COFF_ParsedSymbol lnk_parsed_from_symbol(LNK_Symbol *symbol) { LNK_ObjSymbolRef ref = lnk_ref_from_symbol(symbol); return lnk_parsed_symbol_from_coff_symbol_idx(ref.obj, ref.symbol_idx); } internal COFF_SymbolValueInterpType lnk_interp_from_symbol(LNK_Symbol *symbol) { COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); return coff_interp_from_parsed_symbol(symbol_parsed); } internal U64 lnk_symbol_table_hasher(String8 string) { return u64_hash_from_str8(string); } internal LNK_SymbolTable * lnk_symbol_table_init(TP_Arena *arena) { LNK_SymbolTable *symtab = push_array(arena->v[0], LNK_SymbolTable, 1); symtab->arena = arena; symtab->chunks = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count); symtab->search_chunks = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count); return symtab; } internal void lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_Symbol *symbol) { U64 hash = lnk_symbol_table_hasher(symbol->name); COFF_SymbolValueInterpType interp = lnk_interp_from_symbol(symbol); LNK_SymbolHashTrieChunkList *chunks; if (interp == COFF_SymbolValueInterp_Weak || interp == COFF_SymbolValueInterp_Undefined) { chunks = &symtab->search_chunks[worker_id]; } else { chunks = &symtab->chunks[worker_id]; } lnk_symbol_hash_trie_insert_or_replace(arena, chunks, &symtab->root, hash, symbol); } internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol) { lnk_symbol_table_push_(symtab, symtab->arena->v[0], 0, symbol); } internal LNK_SymbolHashTrie * lnk_symbol_table_search_(LNK_SymbolTable *symtab, String8 name) { U64 hash = lnk_symbol_table_hasher(name); return lnk_symbol_hash_trie_search(symtab->root, hash, name); } internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, String8 name) { LNK_SymbolHashTrie *trie = lnk_symbol_table_search_(symtab, name); return trie ? trie->symbol : 0; } internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 name = push_str8fv(scratch.arena, fmt, args); va_end(args); LNK_Symbol *symbol = lnk_symbol_table_search(symtab, name); scratch_end(scratch); return symbol; } internal ISectOff lnk_sc_from_symbol(LNK_Symbol *symbol) { COFF_ParsedSymbol parsed_symbol = lnk_parsed_from_symbol(symbol); ISectOff sc = { .isect = parsed_symbol.section_number, .off = parsed_symbol.value }; return sc; } internal U64 lnk_voff_from_symbol(COFF_SectionHeader **image_section_table, LNK_Symbol *symbol) { ISectOff sc = lnk_sc_from_symbol(symbol); U64 voff = image_section_table[sc.isect]->voff + sc.off; return voff; } internal U64 lnk_foff_from_symbol(COFF_SectionHeader **image_section_table, LNK_Symbol *symbol) { ISectOff sc = lnk_sc_from_symbol(symbol); U64 foff = image_section_table[sc.isect]->foff + sc.off; return foff; } internal B32 lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_ObjSymbolRef *resolved_symbol_out) { Temp scratch = scratch_begin(0,0); B32 is_resolved = 0; struct S { struct S *next; LNK_ObjSymbolRef symbol; B32 is_anti_dep; }; struct S *sf = 0, *sl = 0; LNK_ObjSymbolRef current_symbol = symbol; for (;;) { // guard against self-referencing weak symbols struct S *was_visited = 0; for (struct S *s = sf; s != 0; s = s->next) { if (MemoryCompare(&s->symbol, ¤t_symbol, sizeof(LNK_ObjSymbolRef)) == 0) { was_visited = s; break; } } if (was_visited) { String8List chain = {0}; for (struct S *s = sf; s != 0; s = s->next) { COFF_ParsedSymbol s_parsed = lnk_parsed_symbol_from_coff_symbol_idx(s->symbol.obj, s->symbol.symbol_idx); str8_list_pushf(scratch.arena, &chain, "\t%S Symbol %S (No. %#x) =>", s->symbol.obj->path, s_parsed.name, s->symbol.symbol_idx); } COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx(symbol.obj, symbol.symbol_idx); str8_list_pushf(scratch.arena, &chain, "\t%S Symbol %S (No. %#x)", sf->symbol.obj->path, symbol_parsed.name, sf->symbol.symbol_idx); String8 chain_string = str8_list_join(scratch.arena, &chain, &(StringJoin){ .sep = str8_lit("\n") }); lnk_error_obj(LNK_Error_WeakCycle, symbol.obj, "unable to resolve cyclic symbol %S; ref chain:\n%S", symbol_parsed.name, chain_string); goto exit; } COFF_ParsedSymbol current_parsed = lnk_parsed_symbol_from_coff_symbol_idx(current_symbol.obj, current_symbol.symbol_idx); COFF_SymbolValueInterpType current_interp = coff_interp_symbol(current_parsed.section_number, current_parsed.value, current_parsed.storage_class); if (current_interp == COFF_SymbolValueInterp_Weak) { // record visited symbol struct S *s = push_array(scratch.arena, struct S, 1); s->symbol = current_symbol; SLLQueuePush(sf, sl, s); // does weak symbol have a definition? LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, current_parsed.name); COFF_ParsedSymbol defn_parsed = lnk_parsed_from_symbol(defn_symbol); COFF_SymbolValueInterpType defn_interp = coff_interp_symbol(defn_parsed.section_number, defn_parsed.value, defn_parsed.storage_class); if (defn_interp != COFF_SymbolValueInterp_Weak) { current_symbol = lnk_ref_from_symbol(defn_symbol); break; } COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->header.is_big_obj); // no definition -- fallback to default symbol COFF_ParsedSymbol tag_parsed = lnk_parsed_symbol_from_coff_symbol_idx(current_symbol.obj, weak_ext->tag_index); COFF_SymbolValueInterpType tag_interp = coff_interp_symbol(tag_parsed.section_number, tag_parsed.value, tag_parsed.storage_class); current_symbol = (LNK_ObjSymbolRef){ .obj = current_symbol.obj, .symbol_idx = weak_ext->tag_index }; if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) { if (tag_interp == COFF_SymbolValueInterp_Undefined || tag_interp == COFF_SymbolValueInterp_Weak) { LNK_Symbol *dep_symbol = lnk_symbol_table_search(symtab, tag_parsed.name); tag_interp = lnk_interp_from_symbol(dep_symbol); } if (tag_interp == COFF_SymbolValueInterp_Weak) { break; } } } else if (current_interp == COFF_SymbolValueInterp_Undefined) { LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, current_parsed.name); COFF_SymbolValueInterpType defn_interp = lnk_interp_from_symbol(defn_symbol); // unresolved undefined symbol if (defn_interp == COFF_SymbolValueInterp_Undefined) { break; } // follow symbol definition current_symbol = lnk_ref_from_symbol(defn_symbol); } else { break; } } if (resolved_symbol_out) { *resolved_symbol_out = current_symbol; } is_resolved = 1; exit:; scratch_end(scratch); return is_resolved; } internal THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task) { LNK_SymbolTable *symtab = raw_task; for EachNode(c, LNK_SymbolHashTrieChunk, symtab->search_chunks[task_id].first) { for EachIndex(i, c->count) { LNK_Symbol *symbol = c->v[i].symbol; LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); if (symbol_interp == COFF_SymbolValueInterp_Weak) { LNK_ObjSymbolRef resolve = {0}; if (lnk_resolve_weak_symbol(symtab, symbol_ref, &resolve)) { COFF_ParsedSymbol resolve_parsed = lnk_parsed_symbol_from_coff_symbol_idx(resolve.obj, resolve.symbol_idx); COFF_SymbolValueInterpType resolve_interp = coff_interp_from_parsed_symbol(resolve_parsed); if (resolve_interp == COFF_SymbolValueInterp_Weak) { COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(resolve_parsed, symbol_ref.obj->header.is_big_obj); if (symbol_ref.obj->header.is_big_obj) { COFF_Symbol32 *symbol32 = symbol_parsed.raw_symbol; symbol32->section_number = COFF_Symbol_UndefinedSection; symbol32->value = 0; symbol32->storage_class = COFF_SymStorageClass_External; } else { COFF_Symbol16 *symbol16 = symbol_parsed.raw_symbol; symbol16->section_number = COFF_Symbol_UndefinedSection; symbol16->value = 0; symbol16->storage_class = COFF_SymStorageClass_External; } } else { symbol->refs->v = resolve; } } } } } } internal void lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab) { ProfBeginFunction(); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_replace_weak_with_default_symbol_task, symtab, "Replace Weak With Default Symbols"); for EachIndex(i, tp->worker_count) { lnk_symbol_hash_trie_chunk_list_concat_in_place(&symtab->chunks[i], &symtab->search_chunks[i]); } ProfEnd(); } ================================================ FILE: src/linker/lnk_symbol_table.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once // --- Symbol ------------------------------------------------------------------ typedef struct LNK_ObjSymbolRef { struct LNK_Obj *obj; U32 symbol_idx; } LNK_ObjSymbolRef; typedef struct LNK_ObjSymbolRefNode { struct LNK_ObjSymbolRefNode *next; LNK_ObjSymbolRef v; } LNK_ObjSymbolRefNode; typedef struct LNK_Symbol { String8 name; LNK_ObjSymbolRefNode *refs; } LNK_Symbol; // --- Symbol Containers ------------------------------------------------------- typedef struct LNK_SymbolNode { struct LNK_SymbolNode *next; LNK_Symbol *data; } LNK_SymbolNode; typedef struct LNK_SymbolList { U64 count; LNK_SymbolNode *first; LNK_SymbolNode *last; } LNK_SymbolList; typedef struct LNK_SymbolArray { U64 count; LNK_Symbol *v; } LNK_SymbolArray; // --- Symbol Hash Trie -------------------------------------------------------- typedef struct LNK_SymbolHashTrie { String8 *name; LNK_Symbol *symbol; struct LNK_SymbolHashTrie *child[4]; } LNK_SymbolHashTrie; typedef struct LNK_SymbolHashTrieChunk { struct LNK_SymbolHashTrieChunk *next; U64 count; U64 cap; LNK_SymbolHashTrie *v; } LNK_SymbolHashTrieChunk; typedef struct LNK_SymbolHashTrieChunkList { U64 count; LNK_SymbolHashTrieChunk *first; LNK_SymbolHashTrieChunk *last; } LNK_SymbolHashTrieChunkList; // --- Symbol Table ------------------------------------------------------------ typedef struct LNK_SymbolTable { TP_Arena *arena; LNK_SymbolHashTrie *root; LNK_SymbolHashTrieChunkList *chunks; LNK_SymbolHashTrieChunkList *search_chunks; } LNK_SymbolTable; // --- Workers Contexts -------------------------------------------------------- typedef struct { LNK_SymbolTable *symtab; LNK_SymbolHashTrieChunk **chunks; } LNK_ReplaceWeakSymbolsWithDefaultSymbolTask; // --- Symbol ----------------------------------------------------------------- internal LNK_Symbol * lnk_make_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 symbol_idx); internal int lnk_obj_symbol_ref_is_before(void *raw_a, void *raw_b); internal int lnk_obj_symbol_ref_ptr_is_before(void *raw_a, void *raw_b); internal int lnk_symbol_is_before(void *raw_a, void *raw_b); internal int lnk_symbol_ptr_is_before(void *raw_a, void *raw_b); // --- Symbol Containers ------------------------------------------------------ internal void lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node); internal LNK_SymbolNode * lnk_symbol_list_push(Arena *arena, LNK_SymbolList *list, LNK_Symbol *symbol); // --- Symbol Hash Trie -------------------------------------------------------- internal LNK_SymbolHashTrie * lnk_symbol_hash_tire_chunk_list_push(Arena *arena, LNK_SymbolHashTrieChunkList *list, U64 cap); internal void lnk_symbol_hash_trie_chunk_list_concat_in_place(LNK_SymbolHashTrieChunkList *list, LNK_SymbolHashTrieChunkList *to_concat); internal void lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunks, LNK_SymbolHashTrie **trie, U64 hash, LNK_Symbol *symbol); internal LNK_SymbolHashTrie * lnk_symbol_hash_trie_search(LNK_SymbolHashTrie *trie, U64 hash, String8 name); internal void lnk_symbol_hash_trie_remove(LNK_SymbolHashTrie *trie); internal LNK_SymbolHashTrieChunk ** lnk_array_from_symbol_hash_trie_chunk_list(Arena *arena, LNK_SymbolHashTrieChunkList *lists, U64 lists_count, U64 *count_out); // --- Symbol Helpers ---------------------------------------------------------- internal LNK_ObjSymbolRef lnk_ref_from_symbol(LNK_Symbol *symbol); internal U64 lnk_ref_count_from_symbol(LNK_Symbol *symbol); internal COFF_ParsedSymbol lnk_parsed_from_symbol(LNK_Symbol *symbol); internal COFF_SymbolValueInterpType lnk_interp_from_symbol(LNK_Symbol *symbol); // --- Symbol Table ------------------------------------------------------------ internal U64 lnk_symbol_table_hasher(String8 string); internal LNK_SymbolTable * lnk_symbol_table_init(TP_Arena *arena); internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol); internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, String8 name); internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, char *fmt, ...); // --- Symbol Contrib Helpers -------------------------------------------------- internal ISectOff lnk_sc_from_symbol(LNK_Symbol *symbol); internal U64 lnk_voff_from_symbol(COFF_SectionHeader **image_section_table, LNK_Symbol *symbol); internal U64 lnk_foff_from_symbol(COFF_SectionHeader **image_section_table, LNK_Symbol *symbol); // --- Weak Symbol ------------------------------------------------------------- internal B32 lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_ObjSymbolRef *resolved_symbol_out); internal void lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab); ================================================ FILE: src/linker/lnk_timer.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) global LNK_Timer g_timers[LNK_Timer_Count]; internal void lnk_timer_begin(LNK_TimerType timer) { g_timers[timer].begin = os_now_microseconds(); } internal void lnk_timer_end(LNK_TimerType timer) { g_timers[timer].end = os_now_microseconds(); } internal String8 lnk_string_from_timer_type(LNK_TimerType type) { switch (type) { case LNK_Timer_Image: return str8_lit("Image"); case LNK_Timer_Pdb: return str8_lit("PDB"); case LNK_Timer_Rdi: return str8_lit("RDI"); case LNK_Timer_Lib: return str8_lit("Lib"); case LNK_Timer_Debug: return str8_lit("Debug"); default: InvalidPath; } return str8_zero(); } ================================================ FILE: src/linker/lnk_timer.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once typedef enum LNK_TimerType { LNK_Timer_Image, LNK_Timer_Pdb, LNK_Timer_Rdi, LNK_Timer_Lib, LNK_Timer_Debug, LNK_Timer_Count } LNK_TimerType; typedef struct LNK_Timer { U64 begin; U64 end; } LNK_Timer; internal void lnk_timer_begin(LNK_TimerType timer); internal void lnk_timer_end(LNK_TimerType timer); ================================================ FILE: src/linker/pdb_ext/msf_builder.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 msf_get_data_node_size(MSF_UInt page_size) { U64 interval = msf_get_fpm_interval_correct(page_size); U64 bytes_per_interval = interval * (U64)page_size; return bytes_per_interval; } internal void msf_page_data_list_push(Arena *arena, MSF_PageDataList *list, MSF_UInt page_size, MSF_UInt count) { U64 data_size = msf_get_data_node_size(page_size); for (MSF_UInt i = 0; i < count; i += 1) { // TODO: clearing memory to zero here is expensive, // with 4KiB pages we have to zero-out 128 MiB // memory block // // we can make API for stream allocation to let user // choose between zeroed and dirty allocations // U8 *data = push_array_aligned(arena, U8, data_size, page_size); // init node MSF_PageDataNode *node = push_array_no_zero(arena, MSF_PageDataNode, 1); node->prev = 0; node->next = 0; node->data = data; // push node to list DLLPushBack(list->first, list->last, node); list->count += 1; } } internal MSF_PageDataList msf_page_data_list_pop(MSF_PageDataList *list, MSF_UInt count) { MSF_PageDataList result = {0}; MSF_UInt to_remove = Min(count, list->count); for (MSF_UInt i = 0; i < to_remove; i += 1) { MSF_PageDataNode *node = list->last; DLLRemove(list->first, list->last, node); node->prev = 0; node->next = 0; DLLPushBack(result.first, result.last, node); result.count += 1; } list->count -= to_remove; return result; } internal void msf_page_data_list_concat_in_place(MSF_PageDataList *list, MSF_PageDataList *to_concat) { DLLConcatInPlace(list, to_concat); } internal void msf_set_page_data_list(Arena *arena, MSF_PageDataList *list, MSF_UInt page_size, String8 data) { ProfBeginFunction(); U64 node_size = msf_get_data_node_size(page_size); U64 node_count = CeilIntegerDiv(data.size, node_size); U64 node_idx; for (node_idx = 0; node_idx < node_count - 1; node_idx += 1) { MSF_PageDataNode *node = push_array(arena, MSF_PageDataNode, 1); node->data = data.str + node_idx * node_size; SLLQueuePush(list->first, list->last, node); list->count += 1; } ProfBegin("Last Page Handle"); B32 is_last_node_size_aligned = (data.size & (node_size - 1)) == 0; U8 *last_node_data = 0; if (is_last_node_size_aligned) { last_node_data = data.str + node_idx * node_size; } else { U64 last_node_size = data.size % node_size; last_node_data = push_array_no_zero(arena, U8, node_size); MemoryCopy(last_node_data, data.str + node_idx * node_size, last_node_size); } ProfEnd(); MSF_PageDataNode *last_node = push_array(arena, MSF_PageDataNode, 1); last_node->data = last_node_data; SLLQueuePush(list->first, list->last, last_node); list->count += 1; ProfEnd(); } internal String8 msf_data_from_pn(MSF_PageDataList list, MSF_UInt page_size, MSF_PageNumber pn) { U64 node_size = msf_get_data_node_size(page_size); U64 page_offset = (U64)pn * (U64)page_size; U64 data_node_idx = page_offset / node_size; MSF_PageDataNode *node = list.first; for (U64 i = 0; i < data_node_idx; i += 1) { node = node->next; } U64 node_offset = page_offset % node_size; U8 *ptr = node->data + node_offset; String8 data = str8(ptr, page_size); return data; } //////////////////////////////// internal MSF_StreamNode * msf_stream_list_push(Arena *arena, MSF_StreamList *list) { MSF_StreamNode *n = push_array(arena, MSF_StreamNode, 1); DLLPushBack(list->first, list->last, n); list->count += 1; return n; } internal void msf_stream_list_remove(MSF_StreamList *list, MSF_StreamNode *node) { Assert(list->count > 0); DLLRemove(list->first, list->last, node); list->count -= 1; } //////////////////////////////// internal void msf_page_list_push_node(MSF_PageList *list, MSF_PageNode *node) { DLLPushBack(list->first, list->last, node); list->count += 1; } internal MSF_PageNode * msf_page_list_push(Arena *arena, MSF_PageList *list) { MSF_PageNode *node = push_array(arena, MSF_PageNode, 1); msf_page_list_push_node(list, node); return node; } internal MSF_PageNode * msf_page_list_pop_last(MSF_PageList *list) { MSF_PageNode *node = NULL; if (list->count) { node = list->last; DLLRemove(list->first, list->last, node); list->count -= 1; } return node; } internal void msf_page_list_concat_in_place(MSF_PageList *list, MSF_PageList *to_concat) { DLLConcatInPlace(list, to_concat); } internal MSF_PageNumber * msf_page_list_to_arr(Arena *arena, MSF_PageList list) { MSF_PageNumber *arr = push_array(arena, MSF_PageNumber, list.count); MSF_UInt i = 0; for (MSF_PageNode *node = list.first; node != 0; node = node->next, i += 1) { arr[i] = node->pn; } return arr; } internal MSF_PageNode * msf_page_from_index(MSF_PageList page_list, MSF_UInt index) { MSF_PageNode *page; B32 scan_from_last_node = index > page_list.count/2; if (scan_from_last_node) { page = page_list.last; if (page_list.count > 0) { for (MSF_UInt i = page_list.count - 1; i > index; i -= 1) { page = page->prev; if (!page) { return 0; } } } } else { page = page_list.first; for (MSF_UInt i = 0; i < index; i += 1) { page = page->next; if (!page) { return 0; } } } return page; } internal void msf_page_list_push_extant_page_arr(Arena *arena, MSF_PageList *list, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber *pn_arr, MSF_UInt pn_count) { U64 node_size = msf_get_data_node_size(page_size); U64 data_max = page_data_list.count * node_size; for (MSF_PageNumber *pn_ptr = pn_arr, *pn_opl = pn_ptr + pn_count; pn_ptr < pn_opl; pn_ptr += 1) { // is page number valid? Assert(*pn_ptr * page_size + page_size <= data_max); // init page node MSF_PageNode *page_node = msf_page_list_push(arena, list); page_node->pn = *pn_ptr; } } internal void msf_page_list_push_extant_page(Arena *arena, MSF_PageList *list, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber pn) { msf_page_list_push_extant_page_arr(arena, list, page_data_list, page_size, &pn, 1); } #if LNK_PARANOID internal void msf_check_fpm_bits_for_page_list(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageList page_list, MSF_UInt test_state) { for (MSF_PageNode *page_node = page_list.first; page_node != 0; page_node = page_node->next) { MSF_UInt state = msf_get_fpm_page_bit_state(page_data_list, page_size, active_fpm, page_node->pn); if (state != test_state) { //Assert(!"state bit doesn't match"); } } } #endif //////////////////////////////// internal MSF_UInt msf_count_pages(MSF_UInt page_size, U64 data_size) { MSF_UInt page_count = CeilIntegerDiv(data_size, page_size); return page_count; } internal MSF_PageNumber msf_get_page_count_cap(MSF_PageDataList page_data_list, MSF_UInt page_size) { U64 node_size = msf_get_data_node_size(page_size); U64 file_size = page_data_list.count * node_size; U64 count = CeilIntegerDiv(file_size, (U64)page_size); return safe_cast_u32(count); } //////////////////////////////// internal U32Array msf_fpm_data_from_pn(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber fpm_pn) { String8 raw_fpm = msf_data_from_pn(page_data_list, page_size, fpm_pn); U32Array fpm_data; fpm_data.count = raw_fpm.size / sizeof(fpm_data.v[0]); fpm_data.v = (U32*)raw_fpm.str; return fpm_data; } internal MSF_UInt msf_get_fpm_interval_correct(MSF_UInt page_size) { return page_size * MSF_BITS_PER_CHAR; } internal MSF_UInt msf_get_fpm_interval_wrong(MSF_UInt page_size) { return page_size; } internal MSF_UInt msf_get_fpm_idx_from_pn(MSF_UInt page_size, MSF_PageNumber pn) { MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt fpm_idx = pn / fpm_interval_correct; return fpm_idx; } internal MSF_UInt msf_get_fpm_page_count(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_UInt fpm_interval) { U64 node_size = msf_get_data_node_size(page_size); U64 file_size = (U64)page_data_list.count * node_size; U64 file_page_count = CeilIntegerDiv(file_size, page_size); U64 fpm_page_count = CeilIntegerDiv(file_page_count, (U64)fpm_interval); return safe_cast_u32(fpm_page_count); } internal MSF_PageNumberArray msf_get_fpm_page_arr(Arena *arena, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_UInt active_fpm) { Assert(active_fpm == MSF_FPM0 || active_fpm == MSF_FPM1); MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(page_size); MSF_UInt page_count = msf_get_page_count_cap(page_data_list, page_size); MSF_PageNumberArray arr; arr.count = CeilIntegerDiv(page_count, fpm_interval_correct); arr.v = push_array(arena, MSF_PageNumber, arr.count); for (MSF_UInt interval_idx = 0; interval_idx < arr.count; interval_idx += 1) { arr.v[interval_idx] = active_fpm + interval_idx * fpm_interval_wrong; } return arr; } internal MSF_PageNumber msf_get_fpm_from_page_number(MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn) { Assert(active_fpm == 1 || active_fpm == 2); MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(page_size); MSF_PageNumber fpm_pn = active_fpm; fpm_pn += (pn / fpm_interval_correct) * fpm_interval_wrong; return fpm_pn; } internal MSF_UInt msf_get_fpm_page_bit_state(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn) { // fetch FPM MSF_PageNumber fpm_pn = msf_get_fpm_from_page_number(page_size, active_fpm, pn); U32Array fpm_data = msf_fpm_data_from_pn(page_data_list, page_size, fpm_pn); // get page bit MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt page_bit_idx = pn % fpm_interval_correct; MSF_UInt state = bit_array_get_bit32(fpm_data, page_bit_idx); return state; } internal void msf_set_fpm_bit_(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn, B32 state) { // fetch FPM MSF_PageNumber fpm_pn = msf_get_fpm_from_page_number(page_size, active_fpm, pn); U32Array fpm_data = msf_fpm_data_from_pn(page_data_list, page_size, fpm_pn); // set page bit MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt page_bit_idx = pn % fpm_interval_correct; bit_array_set_bit32(fpm_data, page_bit_idx, state); } internal void msf_set_fpm_bit(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn, B32 state) { msf_set_fpm_bit_(page_data_list, page_size, active_fpm, pn, state); } internal B32 msf_grow(MSF_Context *msf, MSF_PageNumber new_page_count) { MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(msf->page_size); MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(msf->page_size); // check alloc limit U64 new_page_count64 = AlignPow2((U64)new_page_count, (U64)fpm_interval_correct); B32 is_overflowed = new_page_count64 > MSF_PN_MAX; if (is_overflowed) { return 0; } // check can only grow MSF here new_page_count = safe_cast_u32(new_page_count64); if (new_page_count < msf->page_count) { return 0; } // compute number of FPM pages to allocate // // we allocate 8 times more FPMs because in MS impl they use wrong interval: // https://github.com/microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L509 // MSF_PageNumber prev_fpm_page_cap_wrong = msf_get_fpm_page_count(msf->page_data_list, msf->page_size, fpm_interval_wrong); MSF_PageNumber curr_fpm_page_cap_wrong = CeilIntegerDiv(new_page_count, fpm_interval_wrong); MSF_PageNumber alloc_count_wrong = curr_fpm_page_cap_wrong - prev_fpm_page_cap_wrong; MSF_PageNumber next_pn_wrong = prev_fpm_page_cap_wrong * fpm_interval_wrong; MSF_PageNumber end_pn_wrong = next_pn_wrong + alloc_count_wrong * fpm_interval_wrong; // compute correct number of FPM pages to grow MSF_PageNumber prev_fpm_page_cap_correct = msf_get_fpm_page_count(msf->page_data_list, msf->page_size, fpm_interval_correct); MSF_PageNumber curr_fpm_page_cap_correct = CeilIntegerDiv(new_page_count, fpm_interval_correct); MSF_PageNumber alloc_count_correct = curr_fpm_page_cap_correct - prev_fpm_page_cap_correct; MSF_PageNumber next_pn_correct = prev_fpm_page_cap_correct * fpm_interval_correct; MSF_PageNumber end_pn_correct = next_pn_correct + alloc_count_correct * fpm_interval_correct; MSF_PageNumber to_alloc = alloc_count_correct; // are there unused data nodes? if (msf->page_data_pool.count) { MSF_PageNumber pool_alloc_count = Min(msf->page_data_pool.count, alloc_count_correct); MSF_PageDataList page_data_list = msf_page_data_list_pop(&msf->page_data_pool, pool_alloc_count); msf_page_data_list_concat_in_place(&msf->page_data_list, &page_data_list); to_alloc -= pool_alloc_count; } // push enough data nodes to encompass allocated FPMs msf_page_data_list_push(msf->arena, &msf->page_data_list, msf->page_size, to_alloc); // set FPM bits to free for (MSF_PageNumber pn = next_pn_wrong; pn < end_pn_wrong; pn += fpm_interval_wrong) { MSF_PageNumber fpm0_pn = pn + MSF_FPM0; MSF_PageNumber fpm1_pn = pn + MSF_FPM1; String8 fpm0_data = msf_data_from_pn(msf->page_data_list, msf->page_size, fpm0_pn); String8 fpm1_data = msf_data_from_pn(msf->page_data_list, msf->page_size, fpm1_pn); MemorySet(fpm0_data.str, 0xFF, msf->page_size); MemorySet(fpm1_data.str, 0xFF, msf->page_size); } // set correct FPM bits for (MSF_PageNumber pn = next_pn_correct; pn < end_pn_correct; pn += fpm_interval_correct) { MSF_PageNumber fpm0_pn = pn + MSF_FPM0; MSF_PageNumber fpm1_pn = pn + MSF_FPM1; msf_set_fpm_bit(msf->page_data_list, msf->page_size, MSF_FPM0, fpm0_pn, MSF_PAGE_STATE_ALLOC); msf_set_fpm_bit(msf->page_data_list, msf->page_size, MSF_FPM0, fpm1_pn, MSF_PAGE_STATE_ALLOC); msf_set_fpm_bit(msf->page_data_list, msf->page_size, MSF_FPM1, fpm0_pn, MSF_PAGE_STATE_ALLOC); msf_set_fpm_bit(msf->page_data_list, msf->page_size, MSF_FPM1, fpm1_pn, MSF_PAGE_STATE_ALLOC); } // update context msf->page_count += alloc_count_wrong * 2; return 1; } #if 0 internal B32 msf_shrink(MSF_Context *msf, MSF_PageNumber new_page_count) { MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(msf->page_size); MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(msf->page_size); U64 new_page_count64 = AlignPow2((U64)new_page_count, (U64)fpm_interval_correct); new_page_count = safe_cast_u32(new_page_count64); Assert(new_page_count < msf->page_count); // compute number of FPM pages to deallocate MSF_PageNumber prev_fpm_page_count_wrong = msf_get_fpm_page_count(msf->page_data_list, msf->page_size, fpm_interval_wrong); MSF_PageNumber curr_fpm_page_count_wrong = CeilIntegerDiv(new_page_count, fpm_interval_wrong); MSF_PageNumber dealloc_count_wrong = prev_fpm_page_count_wrong - curr_fpm_page_count_wrong; // compute next FPM page number MSF_PageNumber next_pn = prev_fpm_page_count_wrong * fpm_interval_wrong; MSF_PageNumber end_pn = next_pn - dealloc_count_wrong * fpm_interval_wrong; // pop data nodes MSF_PageNumber prev_fpm_page_count_correct = msf_get_fpm_page_count(msf->page_data_list, msf->page_size, fpm_interval_correct); MSF_PageNumber curr_fpm_page_count_correct = CeilIntegerDiv(new_page_count, fpm_interval_correct); MSF_PageNumber dealloc_count_correct = prev_fpm_page_count_correct - curr_fpm_page_count_correct; MSF_PageDataList free_page_data_list = msf_page_data_list_pop(&msf->page_data_list, dealloc_count_correct); msf_page_data_list_concat_in_place(&msf->page_data_pool, &free_page_data_list); for (MSF_PageNumber pn = next_pn; pn > end_pn; pn -= fpm_interval_wrong) { MSF_PageNumber fpm0_pn = pn + MSF_FPM0; MSF_PageNumber fpm1_pn = pn + MSF_FPM1; // free FPM pages msf_set_fpm_bit(msf->page_data_list, msf->page_size, 1, fpm0_pn, MSF_PAGE_STATE_FREE); msf_set_fpm_bit(msf->page_data_list, msf->page_size, 1, fpm1_pn, MSF_PAGE_STATE_FREE); msf_set_fpm_bit(msf->page_data_list, msf->page_size, 2, fpm0_pn, MSF_PAGE_STATE_FREE); msf_set_fpm_bit(msf->page_data_list, msf->page_size, 2, fpm1_pn, MSF_PAGE_STATE_FREE); } // update context msf->page_count -= dealloc_count_wrong * 2; return true; } #endif internal MSF_PageNumber * msf_alloc_pn_arr(Arena *arena, MSF_Context *msf, MSF_UInt alloc_count) { // make sure FPM has enough space for new page numbers // // we grow FPM at correct intervals here because we pre-alloc unused FPM pages ahead of time MSF_UInt curr_page_cap = msf_get_page_count_cap(msf->page_data_list, msf->page_size); MSF_UInt new_page_count = msf->page_count + alloc_count; if (new_page_count > curr_page_cap) { B32 is_fpm_alloced = msf_grow(msf, new_page_count); if (!is_fpm_alloced) { return 0; } } Temp scratch = scratch_begin(&arena, 1); // reserve memory for page numbers MSF_PageNumber *pn_arr = push_array(arena, MSF_PageNumber, alloc_count); MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(msf->page_size); MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(msf->page_size); // get first FPM page MSF_PageNumberArray fpm_pn_arr = msf_get_fpm_page_arr(scratch.arena, msf->page_data_list, msf->page_size, msf->active_fpm); for (MSF_UInt alloc_idx = 0; alloc_idx < alloc_count; ) { // get FPM bits MSF_UInt fpm_idx = msf->fpm_rover / fpm_interval_correct; Assert(fpm_idx < fpm_pn_arr.count); MSF_PageNumber fpm_pn = fpm_pn_arr.v[fpm_idx]; U32Array fpm_data = msf_fpm_data_from_pn(msf->page_data_list, msf->page_size, fpm_pn); // scan FPM for free bit MSF_UInt fpm_rover_page_relative = msf->fpm_rover % fpm_interval_correct; U32 bit_idx = bit_array_scan_left_to_right32(fpm_data, fpm_rover_page_relative, fpm_interval_correct, MSF_PAGE_STATE_FREE); B32 is_full = (bit_idx >= fpm_interval_correct); if (is_full) { msf->fpm_rover = (fpm_idx + 1) * fpm_interval_correct; continue; } // compute page number MSF_PageNumber pn = bit_idx + (fpm_idx * fpm_interval_correct); // make sure unused FPMs aren't allocated for regular streams, // we used to mark with free bits unused FPMs but in VS2022 // update they started to check for these bits and VS began // to error out with "PDB format is not supported" message B32 is_pn_valid = (pn % fpm_interval_wrong) != MSF_FPM0 && (pn % fpm_interval_wrong) != MSF_FPM1; if (is_pn_valid) { // update FPM bit_array_set_bit32(fpm_data, bit_idx, MSF_PAGE_STATE_ALLOC); // store page number pn_arr[alloc_idx++] = pn; } // advance FPM rover msf->fpm_rover = pn + 1; } // update context msf->page_count += alloc_count; scratch_end(scratch); return pn_arr; } internal void msf_free_pn_arr(MSF_Context *msf, MSF_PageNumber *pn_arr, MSF_UInt pn_count) { // set FPM bits for (MSF_UInt i = 0; i < pn_count; i += 1) { MSF_PageNumber pn = pn_arr[i]; msf_set_fpm_bit(msf->page_data_list, msf->page_size, msf->active_fpm, pn, MSF_PAGE_STATE_FREE); // update FPM cursor msf->fpm_rover = Min(msf->fpm_rover, pn); } // update context Assert(msf->page_count >= pn_count); msf->page_count -= pn_count; } internal MSF_PageList msf_alloc_pages(MSF_Context *msf, MSF_UInt alloc_count) { Temp scratch = scratch_begin(0, 0); MSF_PageList alloc_list = {0}; MSF_PageNumber *pn_arr = msf_alloc_pn_arr(scratch.arena, msf, alloc_count); if (pn_arr) { for (MSF_UInt page_idx = 0; page_idx < alloc_count; page_idx += 1) { // get page node MSF_PageNode *page_node = 0; if (msf->page_pool.count) { page_node = msf_page_list_pop_last(&msf->page_pool); msf_page_list_push_node(&alloc_list, page_node); } else { page_node = msf_page_list_push(msf->arena, &alloc_list); } // copy page number page_node->pn = pn_arr[page_idx]; } } scratch_end(scratch); return alloc_list; } internal void msf_free_pages(MSF_Context *msf, MSF_PageList *page_list) { Temp scratch = scratch_begin(0, 0); // free page numbers MSF_PageNumber *pn_arr = msf_page_list_to_arr(scratch.arena, *page_list); msf_free_pn_arr(msf, pn_arr, page_list->count); // push free nodes msf_page_list_concat_in_place(&msf->page_pool, page_list); scratch_end(scratch); } internal MSF_PageNumber msf_find_max_pn_(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumberArray fpm_pn_arr) { MSF_PageNumber max_pn = 0; MSF_UInt fpm_interval_correct = msf_get_fpm_interval_correct(page_size); MSF_UInt fpm_interval_wrong = msf_get_fpm_interval_wrong(page_size); MSF_UInt fpm_page_count = fpm_interval_correct / fpm_interval_wrong; for (MSF_Int fpm_pn_idx = (MSF_Int)fpm_pn_arr.count - 1; fpm_pn_idx >= 0; fpm_pn_idx -= 1) { MSF_PageNumber fpm_pn = fpm_pn_arr.v[fpm_pn_idx]; U32Array fpm_data = msf_fpm_data_from_pn(page_data_list, page_size, fpm_pn); // we have to work around the fact that FPM bits are always alloced // and also there is a trail of unused FPM groups too U32 bit_idx = max_U32; for (MSF_Int i = fpm_page_count - 1; i >= 0; i -= 1) { U32 fpm_lo = i * fpm_interval_wrong + 3; // skip first page bit and FPM group bits U32 fpm_hi = i * fpm_interval_wrong + fpm_interval_wrong; bit_idx = bit_array_scan_right_to_left32(fpm_data, fpm_lo, fpm_hi, MSF_PAGE_STATE_ALLOC); if (bit_idx <= fpm_interval_correct) { break; } } // check first page bit if (bit_idx >= fpm_interval_correct) { bit_idx = bit_array_scan_left_to_right32(fpm_data, 0, 1, MSF_PAGE_STATE_ALLOC); if (bit_idx >= fpm_interval_correct) { continue; } } // compute max page number MSF_PageNumber pn = bit_idx + (MSF_UInt)fpm_pn_idx * fpm_interval_correct; max_pn = Max(max_pn, pn); break; } return max_pn; } internal MSF_PageNumber msf_find_max_pn(MSF_PageDataList page_data_list, MSF_UInt page_size) { Temp scratch = scratch_begin(0, 0); MSF_PageNumberArray fpm0_pn_arr = msf_get_fpm_page_arr(scratch.arena, page_data_list, page_size, MSF_FPM0); MSF_PageNumberArray fpm1_pn_arr = msf_get_fpm_page_arr(scratch.arena, page_data_list, page_size, MSF_FPM1); MSF_PageNumber fpm0_max = msf_find_max_pn_(page_data_list, page_size, fpm0_pn_arr); MSF_PageNumber fpm1_max = msf_find_max_pn_(page_data_list, page_size, fpm1_pn_arr); MSF_PageNumber max_pn = Max(fpm0_max, fpm1_max); scratch_end(scratch); return max_pn; } //////////////////////////////// internal B32 msf_write__(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNode **page_ptr, MSF_UInt *pos_ptr, void *buffer, MSF_UInt buffer_size) { MSF_PageNode *start_page = *page_ptr; MSF_UInt start_pos = *pos_ptr; MSF_UInt buffer_pos = 0; while (*page_ptr) { MSF_UInt page_offset = *pos_ptr % page_size; // compute copy size MSF_UInt buffer_bytes_left = buffer_size - buffer_pos; MSF_UInt page_bytes_left = page_size - page_offset; MSF_UInt copy_size = Min(buffer_bytes_left, page_bytes_left); // fetch page bytes MSF_PageNumber page_number = (*page_ptr)->pn; String8 page_bytes = msf_data_from_pn(page_data_list, page_size, page_number); // copy bytes to buffer U8 *buffer_copy_ptr = (U8*)buffer + buffer_pos; U8 *page_bytes_ptr = page_bytes.str + page_offset; MemoryCopy(page_bytes_ptr, buffer_copy_ptr, copy_size); // advance buffer_pos += copy_size; *pos_ptr += copy_size; // have we used all bytes in this page? if (page_bytes_left <= copy_size) { *page_ptr = (*page_ptr)->next; } // have we copied all bytes? if (buffer_bytes_left <= copy_size) { break; } } B32 is_write_ok = (buffer_pos == buffer_size); // not enough bytes to perform write - restore positions if (!is_write_ok) { *page_ptr = start_page; *pos_ptr = start_pos; } return is_write_ok; } internal MSF_UInt msf_read__(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNode **page_ptr, MSF_UInt *pos_ptr, void *buffer, MSF_UInt buffer_size) { MSF_UInt buffer_pos = 0; while (*page_ptr) { MSF_UInt page_offset = *pos_ptr % page_size; // compute copy size MSF_UInt buffer_bytes_left = buffer_size - buffer_pos; MSF_UInt page_bytes_left = page_size - page_offset; MSF_UInt copy_size = Min(buffer_bytes_left, page_bytes_left); // fetch page bytes MSF_PageNumber page_number = (*page_ptr)->pn; String8 page_bytes = msf_data_from_pn(page_data_list, page_size, page_number); // copy bytes to buffer U8 *buffer_ptr = (U8*)buffer + buffer_pos; U8 *page_bytes_ptr = page_bytes.str + page_offset; MemoryCopy(buffer_ptr, page_bytes_ptr, copy_size); // advance buffer_pos += copy_size; *pos_ptr += copy_size; // no more bytes left in this page if (page_bytes_left <= copy_size) { *page_ptr = (*page_ptr)->next; } // have we copied all bytes? if (buffer_bytes_left <= copy_size) { break; } } MSF_UInt bytes_read = buffer_pos; //Assert(bytes_read == buffer_size); return bytes_read; } internal B32 msf_write(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList page_list, MSF_UInt offset, void *buffer, MSF_UInt buffer_size) { MSF_UInt page_idx = offset / page_size; MSF_PageNode *page = msf_page_from_index(page_list, page_idx); B32 is_write_ok = msf_write__(page_data_list, page_size, &page, &offset, buffer, buffer_size); return is_write_ok; } internal MSF_UInt msf_read(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList page_list, MSF_UInt offset, void *buffer, MSF_UInt buffer_size) { MSF_UInt page_idx = offset / page_size; MSF_PageNode *page = msf_page_from_index(page_list, page_idx); MSF_UInt bytes_read = msf_read__(page_data_list, page_size, &page, &offset, buffer, buffer_size); return bytes_read; } //////////////////////////////// internal MSF_StreamNode * msf_stream_alloc_(Arena *arena, MSF_StreamList *list) { Assert(list->count < MSF_STREAM_NUMBER_MAX); MSF_UInt sn = list->count; MSF_StreamNode *stream_node = msf_stream_list_push(arena, list); MSF_Stream *stream = &stream_node->data; stream->sn = safe_cast_u16(sn); return stream_node; } internal MSF_StreamNumber msf_stream_alloc_ex(MSF_Context *msf, MSF_UInt size) { MSF_StreamNode *node = msf_stream_alloc_(msf->arena, &msf->sectab); MSF_Stream *stream = &node->data; msf_stream_resize_ex(msf, stream, size); return stream->sn; } internal MSF_StreamNumber msf_stream_alloc(MSF_Context *msf) { return msf_stream_alloc_ex(msf, 0); } internal B32 msf_stream_resize_ex(MSF_Context *msf, MSF_Stream *stream, MSF_UInt size) { MSF_UInt new_page_count = msf_count_pages(msf->page_size, size); MSF_UInt cur_page_count = stream->page_list.count; if (new_page_count > cur_page_count) { MSF_UInt alloc_count = new_page_count - cur_page_count; MSF_PageList page_list = msf_alloc_pages(msf, alloc_count); msf_page_list_concat_in_place(&stream->page_list, &page_list); } else { MSF_PageList free_page_list = {0}; for (MSF_UInt i = cur_page_count; i > new_page_count; i -= 1) { MSF_PageNode *page_node = msf_page_list_pop_last(&stream->page_list); msf_page_list_push_node(&free_page_list, page_node); } msf_free_pages(msf, &free_page_list); } // update stream stream->size = Min(stream->size, stream->page_list.count * msf->page_size); stream->pos = Min(stream->pos, stream->size); stream->pos_page = 0; return 1; } internal B32 msf_stream_resize(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt new_size) { MSF_Stream *stream = msf_find_stream(msf, sn); B32 is_resized = 0; if (stream) { is_resized = msf_stream_resize_ex(msf, stream, new_size); } return is_resized; } internal B32 msf_stream_free(MSF_Context *msf, MSF_StreamNumber sn) { B32 is_free_ok = 0; MSF_StreamNode *stream_node = msf_find_stream_node(msf, sn); if (stream_node) { msf_stream_list_remove(&msf->sectab, stream_node); msf_stream_resize_ex(msf, &stream_node->data, 0); stream_node->data.size = MSF_DELETED_STREAM_STAMP; is_free_ok = 1; } return is_free_ok; } internal void msf_stream_set_size(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt size) { MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { stream->size = Min(size, stream->page_list.count * msf->page_size); } else { Assert(!"invalid stream number"); } } internal MSF_UInt msf_stream_get_size(MSF_Context *msf, MSF_StreamNumber sn) { MSF_UInt size = MSF_UINT_MAX; MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { size = stream->size; } return size; } internal MSF_UInt msf_stream_get_cap__(MSF_Context *msf, MSF_Stream *stream) { return stream->page_list.count * msf->page_size; } internal MSF_UInt msf_stream_get_cap(MSF_Context *msf, MSF_StreamNumber sn) { MSF_Stream *stream = msf_find_stream(msf, sn); MSF_UInt cap = 0; if (stream) { cap = msf_stream_get_cap__(msf, stream); } return cap; } internal MSF_UInt msf_stream_get_pos__(MSF_Context *msf, MSF_Stream *stream) { return stream->pos; } internal MSF_UInt msf_stream_get_pos(MSF_Context *msf, MSF_StreamNumber sn) { MSF_Stream *stream = msf_find_stream(msf, sn); MSF_UInt pos = MSF_UINT_MAX; if (stream) { pos = msf_stream_get_pos__(msf, stream); } return pos; } internal B32 msf_stream_seek__(MSF_Context *msf, MSF_Stream *stream, MSF_UInt new_pos) { (void)msf; stream->pos = Min(new_pos, stream->size); stream->pos_page = 0; return 1; } internal B32 msf_stream_seek(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt new_pos) { B32 is_seek_ok = 0; MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { is_seek_ok = msf_stream_seek__(msf, stream, new_pos); } else { Assert(!"failed to stream seek"); } return is_seek_ok; } internal B32 msf_stream_seek_start(MSF_Context *msf, MSF_StreamNumber sn) { return msf_stream_seek(msf, sn, 0); } internal B32 msf_stream_seek_end(MSF_Context *msf, MSF_StreamNumber sn) { MSF_UInt end = msf_stream_get_size(msf, sn); return msf_stream_seek(msf, sn, end); } internal B32 msf_stream_write__(MSF_Context *msf, MSF_Stream *stream, void *buffer, MSF_UInt buffer_size) { B32 is_write_ok = 0; // are we writing over limit? Assert((U64)stream->pos + (U64)buffer_size <= (U64)MSF_UINT_MAX); // make sure we have enough space to write buffer MSF_UInt stream_cap = msf_stream_get_cap__(msf, stream); MSF_UInt stream_pos_opl = stream->pos + buffer_size; B32 grow_stream = stream_pos_opl > stream_cap; if (grow_stream) { B32 is_resize_ok = msf_stream_resize_ex(msf, stream, stream_pos_opl); if (!is_resize_ok) { goto exit; } } if (buffer) { // lookup page for current stream position if (!stream->pos_page) { MSF_UInt page_idx = stream->pos / msf->page_size; stream->pos_page = msf_page_from_index(stream->page_list, page_idx); } // make write is_write_ok = msf_write__(msf->page_data_list, msf->page_size, &stream->pos_page, &stream->pos, buffer, buffer_size); } else { stream->pos += buffer_size; stream->pos_page = 0; is_write_ok = 1; } // update stream size stream->size = Max(stream->size, stream->pos); exit:; Assert(is_write_ok); return is_write_ok; } internal MSF_UInt msf_stream_reserve__(MSF_Context *msf, MSF_Stream *stream, MSF_UInt res) { ProfBeginV("MSF Reserve %m", res); B32 is_ok = 1; MSF_UInt cap = msf_stream_get_cap__(msf, stream); MSF_UInt pos = msf_stream_get_pos__(msf, stream); MSF_UInt cur = cap - pos; if (cur < res) { is_ok = msf_stream_write__(msf, stream, 0, res); AssertAlways(is_ok); is_ok = msf_stream_seek__(msf, stream, pos); AssertAlways(is_ok); } ProfEnd(); return is_ok; } internal B32 msf_stream_reserve(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt res) { MSF_Stream *stream = msf_find_stream(msf, sn); B32 is_res_ok = 0; if (stream) { is_res_ok = msf_stream_reserve__(msf, stream, res); } return is_res_ok; } internal B32 msf_stream_write(MSF_Context *msf, MSF_StreamNumber sn, void *buffer, MSF_UInt buffer_size) { B32 is_write_ok = 0; MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { is_write_ok = msf_stream_write__(msf, stream, buffer, buffer_size); } return is_write_ok; } internal B32 msf_stream_write_string(MSF_Context *msf, MSF_StreamNumber sn, String8 string) { return msf_stream_write(msf, sn, string.str, string.size); } internal B32 msf_stream_write_list(MSF_Context *msf, MSF_StreamNumber sn, String8List list) { B32 is_write_ok = 0; MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { for (String8Node *node = list.first; node != 0; node = node->next) { is_write_ok = msf_stream_write__(msf, stream, node->string.str, node->string.size); if (!is_write_ok) { break; } } } return is_write_ok; } internal B32 msf_stream_write_uint(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt value) { return msf_stream_write_struct(msf, sn, &value); } internal B32 msf_stream_write_cstr(MSF_Context *msf, MSF_StreamNumber sn, String8 string) { B32 is_string_written = msf_stream_write_string(msf, sn, string); B32 is_null_written = msf_stream_write(msf, sn, 0, 1); return is_string_written && is_null_written; } internal B32 msf_stream_write_u8(MSF_Context *msf, MSF_StreamNumber sn, U8 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_u16(MSF_Context *msf, MSF_StreamNumber sn, U16 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_u32(MSF_Context *msf, MSF_StreamNumber sn, U32 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_u64(MSF_Context *msf, MSF_StreamNumber sn, U64 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_s8(MSF_Context *msf, MSF_StreamNumber sn, S8 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_s16(MSF_Context *msf, MSF_StreamNumber sn, S16 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_s32(MSF_Context *msf, MSF_StreamNumber sn, S32 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal B32 msf_stream_write_s64(MSF_Context *msf, MSF_StreamNumber sn, S64 value) { return msf_stream_write(msf, sn, &value, sizeof(value)); } internal THREAD_POOL_TASK_FUNC(msf_write_task) { ProfBeginFunction(); MSF_WriteTask *task = raw_task; Rng1U64 range = task->range_arr[task_id]; String8 data = str8_substr(task->data, range); MSF_UInt data_pos = range.min + task->stream_pos; MSF_UInt page_idx = data_pos / task->page_size; MSF_PageNode *page = msf_page_from_index(task->page_list, page_idx); if (!msf_write__(task->page_data_list, task->page_size, &page, &data_pos, data.str, data.size)) { InvalidPath; } ProfEnd(); } internal B32 msf_stream_write_parallel(TP_Context *tp, MSF_Context *msf, MSF_StreamNumber sn, void *buffer, MSF_UInt buffer_size) { ProfBeginV("MSF Write Parallel %m", buffer_size); MSF_Stream *stream = msf_find_stream(msf, sn); B32 is_write_ok = msf_stream_reserve__(msf, stream, buffer_size); if (is_write_ok) { U64 expected_pos = stream->pos + buffer_size; U64 pre_size = Min(AlignPadPow2(stream->pos, msf->page_size), buffer_size); U64 mid_size = AlignDownPow2(buffer_size - pre_size, msf->page_size); U64 end_size = buffer_size - (pre_size + mid_size); U8 *pre_ptr = (U8*)buffer; U8 *mid_ptr = (U8*)buffer + pre_size; U8 *end_ptr = (U8*)buffer + pre_size + mid_size; ProfBeginV("Write Buffer Pre %M", pre_size); B32 is_pre_written = msf_stream_write__(msf, stream, pre_ptr, pre_size); AssertAlways(is_pre_written); ProfEnd(); // write buffer mid if (mid_size > 0) { Temp scratch = scratch_begin(0,0); Assert(stream->pos % msf->page_size == 0); Assert(mid_size % msf->page_size == 0); MSF_WriteTask task; task.page_size = msf->page_size; task.page_data_list = msf->page_data_list; task.page_list = stream->page_list; task.stream_pos = stream->pos; task.data = str8(mid_ptr, mid_size); task.range_arr = tp_divide_work(scratch.arena, mid_size, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, msf_write_task, &task); // we rely on low-level msf_write__ to copy bytes which doesn't advance stream pos U64 after_mid = stream->pos + mid_size; B32 is_seek_ok = msf_stream_seek__(msf, stream, after_mid); AssertAlways(is_seek_ok); scratch_end(scratch); } ProfBeginV("Write Buffer End %M", end_size); B32 is_end_ok = msf_stream_write__(msf, stream, end_ptr, end_size); AssertAlways(is_end_ok); ProfEnd(); // did we write bytes correctly? AssertAlways(stream->pos == expected_pos); } ProfEnd(); return is_write_ok; } internal B32 msf_stream_write_string_parallel(TP_Context *tp, MSF_Context *msf, MSF_StreamNumber sn, String8 string) { return msf_stream_write_parallel(tp, msf, sn, string.str, string.size); } //////////////////////////////// internal MSF_UInt msf_stream_read__(MSF_Context *msf, MSF_Stream *stream, void *buffer, MSF_UInt buffer_size) { // are we reading over limit? Assert((U64)stream->pos + (U64)buffer_size <= (U64)MSF_UINT_MAX); // lookup page for current stream position if (!stream->pos_page) { MSF_UInt pos_page_idx = stream->pos / msf->page_size; stream->pos_page = msf_page_from_index(stream->page_list, pos_page_idx); } MSF_UInt bytes_read = msf_read__(msf->page_data_list, msf->page_size, &stream->pos_page, &stream->pos, buffer, buffer_size); return bytes_read; } internal MSF_UInt msf_stream_read(MSF_Context *msf, MSF_StreamNumber sn, void *buffer, MSF_UInt buffer_size) { MSF_Stream *stream = msf_find_stream(msf, sn); if (stream) { return msf_stream_read__(msf, stream, buffer, buffer_size); } return 0; } internal S8 msf_stream_read_s8(MSF_Context *msf, MSF_StreamNumber sn) { S8 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal S16 msf_stream_read_s16(MSF_Context *msf, MSF_StreamNumber sn) { S16 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal S32 msf_stream_read_s32(MSF_Context *msf, MSF_StreamNumber sn) { S32 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal S64 msf_stream_read_s64(MSF_Context *msf, MSF_StreamNumber sn) { S64 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal U8 msf_stream_read_u8(MSF_Context *msf, MSF_StreamNumber sn) { U8 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal U16 msf_stream_read_u16(MSF_Context *msf, MSF_StreamNumber sn) { U16 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal U32 msf_stream_read_u32(MSF_Context *msf, MSF_StreamNumber sn) { U32 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal U64 msf_stream_read_u64(MSF_Context *msf, MSF_StreamNumber sn) { U64 result = 0; msf_stream_read_struct(msf, sn, &result); return result; } internal String8 msf_stream_read_block(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, U64 block_size) { U8 *block_buffer = push_array(arena, U8, block_size); MSF_UInt block_read = msf_stream_read(msf, sn, block_buffer, block_size); Assert((U64)block_read == block_size); String8 block = str8(block_buffer, block_size); return block; } internal String8 msf_stream_read_string(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn) { MSF_UInt start_pos = msf_stream_get_pos(msf, sn); U64 size = 0; for (;; size += 1) { U8 cp = msf_stream_read_u8(msf, sn); if (cp == 0) { break; } } msf_stream_seek(msf, sn, start_pos); String8 string = msf_stream_read_block(arena, msf, sn, size); msf_stream_seek(msf, sn, start_pos + size + 1); // skip null return string; } internal void msf_stream_align(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt align) { MSF_UInt pos = msf_stream_get_pos(msf, sn); MSF_UInt pos_aligned = AlignPow2(pos, align); msf_stream_seek(msf, sn, pos_aligned); } //////////////////////////////// internal MSF_Context * msf_alloc__(MSF_UInt page_size, MSF_PageNumber active_fpm) { ProfBeginFunction(); Assert(active_fpm == MSF_FPM0 || active_fpm == MSF_FPM1); Assert(IsPow2(page_size)); Arena *arena = arena_alloc(); MSF_Context *msf = push_array(arena, MSF_Context, 1); msf->arena = arena; msf->page_size = page_size; msf->active_fpm = active_fpm; ProfEnd(); return msf; } internal MSF_Context * msf_alloc(MSF_UInt page_size, MSF_UInt active_fpm) { MSF_Context *msf = msf_alloc__(page_size, active_fpm); // reserve first page for header msf->header_page_list = msf_alloc_pages(msf, 1); Assert(msf->header_page_list.count > 0); Assert(msf->header_page_list.first->pn == 0); // reserve root page close to start of the file so we don't have to seek too far (not required) msf->root_page_list = msf_alloc_pages(msf, 1); Assert(msf->root_page_list.count == 1); Assert(msf->root_page_list.first->pn == 3); return msf; } internal MSF_StreamNode * msf_find_stream_node(MSF_Context *msf, MSF_StreamNumber sn) { MSF_StreamNode *node; for (node = msf->sectab.first; node != 0; node = node->next) { if (node->data.sn == sn) { break; } } return node; } internal MSF_Stream * msf_find_stream(MSF_Context *msf, MSF_StreamNumber sn) { MSF_StreamNode *node = msf_find_stream_node(msf, sn); MSF_Stream *data = 0; if (node) { data = &node->data; } return data; } internal MSF_Error msf_open_header(Arena *arena, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList *page_list) { ProfBeginFunction(); msf_page_list_push_extant_page(arena, page_list, page_data_list, page_size, 0); ProfEnd(); return MSF_Error_OK; } internal MSF_Error msf_open_root(Arena *arena, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber root_pn, MSF_UInt stream_table_size, MSF_PageList *page_list) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); MSF_PageNumber st_page_count = msf_count_pages(page_size, stream_table_size); MSF_UInt st_pn_size = sizeof(MSF_PageNumber) * st_page_count; MSF_PageNumber root_pn_count = msf_count_pages(page_size, st_pn_size); MSF_PageNumber *root_pn_arr = push_array(scratch.arena, MSF_PageNumber, root_pn_count); for (MSF_UInt i = 0; i < root_pn_count; i += 1) { root_pn_arr[i] = root_pn + i; } msf_page_list_push_extant_page_arr(arena, page_list, page_data_list, page_size, root_pn_arr, root_pn_count); scratch_end(scratch); ProfEnd(); return MSF_Error_OK; } internal MSF_Error msf_open_stream_table_page_list(Arena *arena, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList root_page_list, MSF_UInt stream_table_size, MSF_PageList *page_list) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); MSF_Error error = MSF_Error_OK; MSF_UInt st_pn_count = msf_count_pages(page_size, stream_table_size); MSF_UInt st_pn_size = st_pn_count * sizeof(MSF_PageNumber); MSF_PageNumber *st_pn_arr = push_array(scratch.arena, MSF_PageNumber, st_pn_count); MSF_UInt st_pn_read_size = msf_read(page_data_list, page_size, root_page_list, 0, st_pn_arr, st_pn_size); if (st_pn_read_size == st_pn_size) { msf_page_list_push_extant_page_arr(arena, page_list, page_data_list, page_size, st_pn_arr, st_pn_count); } else { error = MSF_OpenError_UNABLE_TO_READ_STREAM_TABLE_PAGE_NUMBERS; } scratch_end(scratch); ProfEnd(); return error; } internal MSF_Error msf_open_stream_table(Arena *arena, MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList st_page_list, MSF_UInt stream_table_size, MSF_StreamList *stream_list) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); MSF_Error error = MSF_Error_OK; // read out entire stream table U8 *st_buffer = push_array(scratch.arena, U8, stream_table_size); MSF_UInt st_read_size = msf_read(page_data_list, page_size, st_page_list, 0, st_buffer, stream_table_size); if (st_read_size != stream_table_size) { error = MSF_OpenError_INVALID_STREAM_TABLE; goto exit; } // setup buffer reader String8 st_data = str8(st_buffer, st_read_size); U64 st_cursor = 0; MSF_UInt stream_count = 0; st_cursor += str8_deserial_read_struct(st_data, st_cursor, &stream_count); // stream count is a 32-bit but stream number is 16-bit?! if (stream_count > MSF_STREAM_NUMBER_MAX) { error = MSF_OpenError_STREAM_COUNT_OVERFLOW; goto exit; } // is there enoguh bytes to read streams sizes? U64 size_arr_end = st_cursor + (U64)stream_count * sizeof(MSF_UInt); if (size_arr_end > st_data.size) { error = MSF_OpenError_UNABLE_TO_READ_STREAM_SIZES; goto exit; } // make pointer to stream sizes array MSF_UInt *stream_size_arr = (MSF_UInt*)(st_buffer + st_cursor); st_cursor += sizeof(stream_size_arr[0]) * stream_count; U64 arena_pos_before_stream_allocations = arena_pos(arena); // open streams for (MSF_UInt stream_idx = 0; stream_idx < stream_count; stream_idx += 1) { MSF_UInt stream_size = stream_size_arr[stream_idx]; B32 is_present = stream_size != MSF_DELETED_STREAM_STAMP; if (is_present) { MSF_PageNumber pn_count = msf_count_pages(page_size, stream_size); // is there enough bytes in buffer to build stream page list? MSF_UInt st_pn_end = st_cursor + pn_count * sizeof(MSF_PageNumber); if (st_pn_end > stream_table_size) { break; } // setup page number array MSF_PageNumber *pn_arr = (MSF_PageNumber*)(st_buffer + st_cursor); st_cursor += sizeof(pn_arr[0]) * pn_count; // build stream page list MSF_PageList page_list = {0}; msf_page_list_push_extant_page_arr(arena, &page_list, page_data_list, page_size, pn_arr, pn_count); // alloc stream with opened pages MSF_StreamNode *stream_node = msf_stream_alloc_(arena, stream_list); stream_node->data.size = stream_size; stream_node->data.page_list = page_list; } // stream was deleted but slot was kept to be reused in subsequent allocations else { MSF_StreamNode *stream_node = msf_stream_alloc_(arena, stream_list); stream_node->data.size = stream_size; } } if (stream_list->count != stream_count) { arena_pop_to(arena, arena_pos_before_stream_allocations); error = MSF_OpenError_INVALID_STREAM_TABLE; goto exit; } exit:; scratch_end(scratch); ProfEnd(); return error; } internal MSF_Error msf_open(String8 data, MSF_Context **msf_out) { ProfBeginFunction(); MSF_Error error = MSF_Error_OK; MSF_Context *msf = 0; MSF_PageDataList page_data_list = {0}; // are there enough bytes for header? if (sizeof(MSF_Header70) > data.size) { error = MSF_OpenError_NOT_ENOUGH_BYTES_TO_READ_HEADER; goto exit; } // is this MSF 7.0? MSF_Header70 *header = (MSF_Header70*)data.str; if (MemoryCompare(header->magic, msf_msf70_magic, sizeof(msf_msf70_magic)) != 0) { error = MSF_OpenError_INVALID_MAGIC; goto exit; } // validate page size if (!IsPow2(header->page_size)) { error = MSF_OpenError_PAGE_SIZE_IS_NOT_POW2; goto exit; } // validate page count MSF_UInt file_page_count = msf_count_pages(header->page_size, data.size); if (file_page_count != header->page_count) { error = MSF_OpenError_PAGE_COUNT_DOESNT_MATCH_DATA_SIZE; goto exit; } // validate FPM if (header->page_size < MSF_MIN_PAGE_SIZE) { error = MSF_OpenError_INVALID_PAGE_SIZE; goto exit; } if (header->page_size > MSF_MAX_PAGE_SIZE) { error = MSF_OpenError_INVALID_PAGE_SIZE; goto exit; } // is there enough bytes to initialize PDB? MSF_UInt check_size = header->page_size*3 + header->stream_table_size; if (check_size > data.size) { error = MSF_OpenError_NOT_ENOUGH_PAGES_TO_INIT; goto exit; } // validate FPM if (header->active_fpm != MSF_FPM0 && header->active_fpm != MSF_FPM1) { error = MSF_OpenError_INVALID_ACTIVE_FPM; goto exit; } // is there enough bytes to initialize root stream? MSF_UInt root_pn_offset = OffsetOf(MSF_Header70, root_pn); if (root_pn_offset + header->stream_table_size > data.size) { error = MSF_OpenError_INVALID_ROOT_STREAM_PAGE_NUMBER; goto exit; } // validate root directory MSF_UInt root_directory_page_count = msf_count_pages(header->page_size, header->stream_table_size); MSF_UInt root_directory_max_page_count = header->page_size / sizeof(MSF_UInt); if (root_directory_page_count > root_directory_max_page_count) { error = MSF_Error_STREAM_TABLE_HAS_TOO_MANY_PAGES; goto exit; } // allocate MSF context and don't reserve special pages msf = msf_alloc__(header->page_size, header->active_fpm); // divide data into fixed size nodes (with 4KB page each node is 128MB) msf_set_page_data_list(msf->arena, &page_data_list, header->page_size, data); do { MSF_PageList header_page_list = {0}; error = msf_open_header(msf->arena, page_data_list, header->page_size, &header_page_list); if (error != MSF_Error_OK) { break; } MSF_PageList root_page_list = {0}; error = msf_open_root(msf->arena, page_data_list, header->page_size, header->root_pn, header->stream_table_size, &root_page_list); if (error != MSF_Error_OK) { break; } MSF_PageList st_page_list = {0}; error = msf_open_stream_table_page_list(msf->arena, page_data_list, header->page_size, root_page_list, header->stream_table_size, &st_page_list); if (error != MSF_Error_OK) { break; } MSF_StreamList stream_list = {0}; error = msf_open_stream_table(msf->arena, page_data_list, header->page_size, st_page_list, header->stream_table_size, &stream_list); if (error != MSF_Error_OK) { break; } Assert(msf->page_size == header->page_size); Assert(msf->active_fpm == header->active_fpm); msf->page_count = header->page_count; msf->page_data_list = page_data_list; msf->header_page_list = header_page_list; msf->root_page_list = root_page_list; msf->st_page_list = st_page_list; msf->sectab = stream_list; *msf_out = msf; #if LNK_PARANOID msf_check_fpm_bits_for_page_list(page_data_list, msf->page_size, msf->active_fpm, header_page_list, MSF_PAGE_STATE_ALLOC); msf_check_fpm_bits_for_page_list(page_data_list, msf->page_size, msf->active_fpm, root_page_list, MSF_PAGE_STATE_ALLOC); msf_check_fpm_bits_for_page_list(page_data_list, msf->page_size, msf->active_fpm, st_page_list, MSF_PAGE_STATE_ALLOC); for (MSF_StreamNode *stream_node = stream_list.first; stream_node != 0; stream_node = stream_node->next) { msf_check_fpm_bits_for_page_list(page_data_list, msf->page_size, msf->active_fpm, stream_node->data.page_list, MSF_PAGE_STATE_ALLOC); } #endif } while(0); exit:; if (error != MSF_Error_OK) { if (msf) { msf_release(&msf); } } ProfEnd(); return error; } internal void msf_release(MSF_Context **msf_ptr) { arena_release((*msf_ptr)->arena); *msf_ptr = 0; } internal String8List msf_build_stream_table_data(Arena *arena, MSF_StreamList *sectab, MSF_UInt page_size, MSF_UInt page_count) { ProfBeginFunction(); MSF_UInt *stream_count_ptr = push_array(arena, MSF_UInt, 1); *stream_count_ptr = sectab->count; MSF_UInt *stream_size_arr = push_array(arena, MSF_UInt, sectab->count); MSF_UInt stream_page_count = 0; MSF_PageNumber *stream_pages_arr = push_array(arena, MSF_PageNumber, page_count); for (MSF_StreamNode *stream_node = sectab->first; stream_node != 0; stream_node = stream_node->next) { MSF_Stream *stream = &stream_node->data; // is page list correct? MSF_UInt expected_stream_page_count = msf_count_pages(page_size, stream->size); if (expected_stream_page_count > stream->page_list.count) { Assert(!"invalid page list "); } // store stream sizes stream_size_arr[stream->sn] = stream->size; // store stream pages for (MSF_PageNode *page_node = stream->page_list.first; page_node != 0; page_node = page_node->next) { // first three pages are reserved for header, FPM0, and FPM1 Assert(page_node->pn > 2); // it's not necessarily a bug to use interval FPM pages, // but for sake of correctness make sure there is no stream // aside from FPM that uses these pages // // also, actual FPM pages should be asserted on: pn % (msf->page_size * MSF_BITS_PER_CHAR) Assert((page_node->pn % page_size) != 1); Assert((page_node->pn % page_size) != 2); // is there a stream with too many page nodes? Assert(stream_page_count < page_count); // is this page number allocated? //Assert(msf_get_fpm_page_bit_state(msf, page_node->pn) == MSF_PAGE_STATE_ALLOC); stream_pages_arr[stream_page_count] = page_node->pn; stream_page_count += 1; } } // on disk stream table: // MSF_UInt stream_count; // MSF_UInt stream_size[stream_count]; // MSF_PageNumber pages[stream_count][*]; String8List st_data_list = {0}; str8_list_push(arena, &st_data_list, str8((U8*)stream_count_ptr, sizeof(*stream_count_ptr))); str8_list_push(arena, &st_data_list, str8((U8*)stream_size_arr, sizeof(*stream_size_arr) * (*stream_count_ptr))); str8_list_push(arena, &st_data_list, str8((U8*)stream_pages_arr, sizeof(*stream_pages_arr) * stream_page_count)); ProfEnd(); return st_data_list; } internal MSF_Error msf_build_stream_table(MSF_Context *msf, MSF_UInt *stream_table_size_out) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); MSF_Error error = MSF_Error_OK; String8List st_data_list = msf_build_stream_table_data(scratch.arena, &msf->sectab, msf->page_size, msf->page_count); MSF_UInt st_page_count = msf_count_pages(msf->page_size, st_data_list.total_size); msf_free_pages(msf, &msf->st_page_list); // TODO: page reuse msf->st_page_list = msf_alloc_pages(msf, st_page_count); MSF_UInt cursor = 0; for (String8Node *node = st_data_list.first; node != 0; node = node->next) { B32 is_data_written = msf_write(msf->page_data_list, msf->page_size, msf->st_page_list, cursor, node->string.str, node->string.size); if (!is_data_written) { error = MSF_BuildError_UNABLE_TO_WRITE_STREAM_TABLE; goto exit; } cursor += node->string.size; } *stream_table_size_out = st_data_list.total_size; exit:; scratch_end(scratch); ProfEnd(); return error; } internal MSF_Error msf_build_root_directory(MSF_Context *msf) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); MSF_Error error = MSF_Error_OK; // MS impl doesn't handle root directory with page count above 1. MSF_UInt max_page_count_in_root_directory = msf->page_size / sizeof(MSF_PageNumber); if (msf->st_page_list.count > max_page_count_in_root_directory) { error = MSF_Error_STREAM_TABLE_HAS_TOO_MANY_PAGES; goto exit; } // collect stream table page numbers MSF_PageNumber *pn_arr = push_array(scratch.arena, MSF_PageNumber, msf->st_page_list.count); MSF_UInt pn_count = 0; for (MSF_PageNode *page = msf->st_page_list.first; page != 0; page = page->next) { pn_arr[pn_count++] = page->pn; } MSF_UInt root_page_count = msf_count_pages(msf->page_size, pn_count * sizeof(pn_arr[0])); Assert(root_page_count == 1); msf_free_pages(msf, &msf->root_page_list); // TODO: page reuse msf->root_page_list = msf_alloc_pages(msf, root_page_count); B32 is_root_written = msf_write(msf->page_data_list, msf->page_size, msf->root_page_list, 0, pn_arr, sizeof(pn_arr[0]) * pn_count); if (!is_root_written) { error = MSF_BuildError_UNABLE_TO_WRITE_ROOT_DIRECTORY; goto exit; } exit:; scratch_end(scratch); ProfEnd(); return error; } internal MSF_Error msf_build_header(MSF_Context *msf, MSF_UInt stream_table_size) { ProfBeginFunction(); MSF_Error error = MSF_Error_OK; MSF_Header70 header; MemoryCopy(&header.magic[0], &msf_msf70_magic[0], sizeof(msf_msf70_magic)); header.page_size = msf->page_size; header.active_fpm = msf->active_fpm; header.page_count = msf->page_count; header.stream_table_size = stream_table_size; header.unknown = 0; header.root_pn = msf->root_page_list.first->pn; B32 is_header_written = msf_write(msf->page_data_list, msf->page_size, msf->header_page_list, 0, &header, sizeof(header)); if (!is_header_written) { error = MSF_BuildError_UNABLE_TO_WRITE_HEADER; goto exit; } exit:; ProfEnd(); return error; } internal MSF_Error msf_build(MSF_Context *msf) { ProfBeginFunction(); MSF_Error err; do { MSF_UInt stream_table_size; err = msf_build_stream_table(msf, &stream_table_size); if (err != MSF_Error_OK) { break; } err = msf_build_root_directory(msf); if (err != MSF_Error_OK) { break; } err = msf_build_header(msf, stream_table_size); if (err != MSF_Error_OK) { break; } } while (0); ProfEnd(); return err; } internal String8List msf_get_page_data_nodes(Arena *arena, MSF_Context *msf) { String8List list; MemoryZeroStruct(&list); U64 total_size = msf_get_save_size(msf); U64 bytes_left = total_size; U64 node_size = msf_get_data_node_size(msf->page_size); for (MSF_PageDataNode *data_node = msf->page_data_list.first; data_node != 0; data_node = data_node->next) { // compute byte count for the node U64 to_copy = Min(bytes_left, node_size); bytes_left -= to_copy; String8 data = str8(data_node->data, to_copy); str8_list_push(arena, &list, data); } return list; } internal U64 msf_get_save_size(MSF_Context *msf) { #if 0 MSF_PageNumber max_pn = msf_find_max_pn(msf->page_data_list, msf->page_size); U64 size = ((U64)max_pn + 1) * (U64)msf->page_size; Assert(msf_count_pages(size, msf->page_size) == msf->page_count); #else U64 size = (U64)msf->page_count * msf->page_size; #endif return size; } internal B32 msf_save(MSF_Context *msf, void *buffer, U64 buffer_size) { ProfBeginFunction(); U64 node_size = msf_get_data_node_size(msf->page_size); U64 cursor = 0; for (MSF_PageDataNode *node = msf->page_data_list.first; node != 0; node = node->next) { // compute byte count for the copy U64 bytes_in_buffer = buffer_size - cursor; U64 to_copy = Min(bytes_in_buffer, node_size); // copy MSF bytes to output buffer U8 *dst = (U8 *)buffer + cursor; U8 *src = node->data; MemoryCopy(dst, src, to_copy); // advance cursor cursor += to_copy; // is output buffer full? if (to_copy == 0) { break; } } B32 is_save_ok = (cursor == buffer_size); Assert(is_save_ok); ProfEnd(); return is_save_ok; } internal MSF_Error msf_save_arena(Arena *arena, MSF_Context *msf, String8 *data_out) { ProfBeginFunction(); MSF_Error err = msf_build(msf); if (err == MSF_Error_OK) { U64 buffer_size = msf_get_save_size(msf); U8 *buffer = push_array(arena, U8, buffer_size); B32 is_saved = msf_save(msf, buffer, buffer_size); if (is_saved) { *data_out = str8(buffer, buffer_size); } else { arena_pop(arena, buffer_size); } } ProfEnd(); return err; } internal char * msf_error_to_string(MSF_Error code) { char *str = ""; switch (code) { case MSF_Error_OK: break; case MSF_Error_STREAM_TABLE_HAS_TOO_MANY_PAGES: str = "stream table exceeds page limit"; break; case MSF_OpenError_NOT_ENOUGH_BYTES_TO_READ_HEADER: str = "input does not have enough bytes to read header"; break; case MSF_OpenError_INVALID_MAGIC: str = "magic value does not match"; break; case MSF_OpenError_PAGE_SIZE_IS_NOT_POW2: str = "page size is not power of two"; break; case MSF_OpenError_INVALID_PAGE_SIZE: str = "invalid page size"; break; case MSF_OpenError_NOT_ENOUGH_PAGES_TO_INIT: str = "not enough pages to initialize MSF"; break; case MSF_OpenError_INVALID_ROOT_STREAM_PAGE_NUMBER: str = "invalid root stream page number"; break; case MSF_OpenError_UNABLE_TO_READ_STREAM_TABLE_PAGE_NUMBERS: str = "unable to read stream table's page numbers"; break; case MSF_OpenError_STREAM_COUNT_OVERFLOW: str = "stream count is overflown"; break; case MSF_OpenError_UNABLE_TO_READ_STREAM_SIZES: str = "unable to read streams sizes"; break; case MSF_OpenError_INVALID_STREAM_TABLE: str = "invalid stream table"; break; case MSF_OpenError_INVALID_ACTIVE_FPM: str = "invalid active FPM"; break; case MSF_OpenError_PAGE_COUNT_DOESNT_MATCH_DATA_SIZE: str = "page count from MSF header does not match data page count"; break; case MSF_BuildError_UNABLE_TO_WRITE_STREAM_TABLE: str = "unable to write stream table"; break; case MSF_BuildError_UNABLE_TO_WRITE_STREAM_TABLE_PAGE_NUMBER_DIRECTORY: str = "unable to write stream table page number directory"; break; case MSF_BuildError_UNABLE_TO_WRITE_ROOT_DIRECTORY: str = "unable to write root directory"; break; case MSF_BuildError_UNABLE_TO_WRITE_HEADER: str = "unable to write header"; break; } return str; } //////////////////////////////// /* Multi-Stream-Format is a database type of format for storing debug info but in principle can store anything you want. MSF divides file into fixed-sized pages (default page size is 4KiB) and puts them together into streams. A stream is made up from a non-contigous number of pages and supports following operations: alloc, free, open, write, read. Current MSF 7.0 allows creating up to 64K of streams, where each stream can potentially contain 2GiB of data (assuming default page size). Free Page Map assigns a bit to each page to indicate page alloc state. 0 = allocated and 1 = free. FPM is alloced at fixed intervals of 'page_size * MSF_BITS_PER_CHAR'. At the begining of interval two pages are reserved for status bits. The 'active_fpm' field in the MSF header tells which FPM page is in use. On commit time MSF alternates between two pages, this way they support atomic read and write. FPM Bug: Let's say you have a MSF file with page size 0x1000 bytes, you can represent 0x1000 * 8 = 0x8000 pages or 0x8000 * 0x1000 = 128MiB. And when file exceeds this size a new FPM group should be allocated at page numbers 0x8001 and 0x8002. However, in MS impl there is a bug where they don't multiply interval by 8 and each FPM group is allocated at intervals of page size or 0x1000, so each FPM group is placed at page numbers 0x1001, 0x1002, 0x2001, 0x2002, and so on. This way MSF files end up allocating 8 times more pages. Also, MS impl marks unused pages as allocated thus leaving them empty but LLVM repurposes them for regular allocations and things work out fine because of the fact that MS computes correct number of FPM pages when they save and load and the trailing pages aren't being touched: https://github.com/microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L2512 Root directory is a single paged stored as a page number in 'MSF_Header70.root_pn'. The directory contains an array of page numbers needed to read the stream table. This is a late addition introduced in version 7.0 that lets us have bigger stream tables. However, there is a limit if stream table exceeds root directory, MSF becomes invalid. MS impl isn't clear what should happen in this case, so we tried to contiguously allocate root pages but VS and LLVM error out. In practice you can double page size to work around the limit. TODO: explain stream table */ #if 0 internal void msf_bytedump_stream(char *file_name, MSF_Context *msf, MSF_StreamNumber sn, U64 start, U64 byte_count) { Temp scratch = scratch_begin(0, 0); U64 pos = msf_stream_get_pos(msf, sn); msf_stream_seek(msf, sn, start); U64 buffer_size = byte_count; U8 *buffer = push_array(scratch.arena, U8, buffer_size); MSF_UInt read_size = msf_stream_read(msf, sn, buffer, buffer_size); os_write_file(str8_cstring(file_name), str8(buffer, read_size)); msf_stream_seek(msf, sn, pos); scratch_end(scratch); } internal void msf_hexdump_stream(FILE *file, MSF_Context *msf, MSF_StreamNumber sn, U64 start, U64 byte_count, U64 stride) { Temp scratch = scratch_begin(0, 0); U8 *row_buffer = push_array(scratch.arena, U8, stride); U64 stream_size = msf_stream_get_size(msf, sn); U64 cursor = start; U64 end = Min(start + byte_count, stream_size); while (cursor < stream_size) { MSF_UInt read_size = msf_stream_read(msf, sn, row_buffer, stride); // print offset fprintf(file, "%04llX", cursor); // print bytes fprintf(file, " "); for (U64 i = 0; i < read_size; i += 1) { if (i > 0) { fprintf(file, " "); } fprintf(file, "%02X", row_buffer[i]); } // print ascii fprintf(file, " "); for (U64 i = 0; i < read_size; i += 1) { U8 print_char = row_buffer[i]; if (0x20 > print_char || print_char > 0x7E) { print_char = '.'; } fprintf(file, "%c", print_char); } // row is done fprintf(file, "\n"); cursor += stride; } scratch_end(scratch); } internal void msf_hexdump_stream_to_file(char *name, MSF_Context *msf, MSF_StreamNumber sn, U64 start, U64 byte_count, U64 stride) { FILE *f = fopen(name, "w"); msf_hexdump_stream(f, msf, sn, start, byte_count, stride); fclose(f); } #endif #if 0 internal void test_msf_open_save(void) { Temp scratch = scratch_begin(0, 0); U32 item0 = 123; U32 item1 = 321; MSF_StreamNumber stream; String8 data; { MSF_Context *msf = msf_alloc(MSF_DEFAULT_PAGE_SIZE, MSF_DEFAULT_FPM); stream = msf_stream_alloc(msf); msf_stream_write_u32(msf, stream, item0); msf_stream_write_u32(msf, stream, item1); data = msf_save_arena(scratch.arena, msf); msf_release(&msf); } String8 data1; { MSF_Context *msf = 0; MSF_Error err = msf_open(data, &msf); Assert(err == MSF_Error_OK); U32 read0 = msf_stream_read_u32(msf, stream); Assert(read0 == item0); U32 read1 = msf_stream_read_u32(msf, stream); Assert(read1 == item1); data1 = msf_save_arena(scratch.arena, msf); msf_release(&msf); } { MSF_Context *msf = 0; MSF_Error err = msf_open(data, &msf); Assert(err == MSF_Error_OK); U32 read0 = msf_stream_read_u32(msf, stream); Assert(read0 == item0); U32 read1 = msf_stream_read_u32(msf, stream); Assert(read1 == item1); msf_release(&msf); } scratch_end(scratch); } internal void test_size_limit(void) { Temp scratch = scratch_begin(0, 0); MSF_Context *msf = msf_alloc(8192, MSF_DEFAULT_FPM); Assert(msf); U64 c = (1 * 1024 * 1024 * 1024) / msf->page_size; U64 stream_count = 8; U64 data_size = msf->page_size; U8 *data = push_array(scratch.arena, U8, data_size); for (U64 stream_idx = 0; stream_idx < stream_count; stream_idx += 1) { MSF_StreamNumber stream = msf_stream_alloc(msf); Assert(stream != MSF_INVALID_STREAM_NUMBER); MemorySet(&data[0], 1 + stream_idx, data_size); msf_stream_resize(msf, stream, c * msf->page_size); for (U64 i = 0; i < c; i += 1) { B32 is_written = msf_stream_write(msf, stream, data, data_size); Assert(is_written); } } //msf_grow(msf, MSF_PN_MAX); msf_stream_free(msf, 7); msf_stream_free(msf, 6); msf_stream_free(msf, 5); stream_count -= 3; String8 msf_data = msf_save_arena(scratch.arena, msf); Assert(msf_data.size > 0); msf_release(&msf); //os_write_file(str8_lit("test.msf"), msf_data); MSF_Error err = msf_open(msf_data, &msf); Assert(err == MSF_Error_OK); #if 1 U8 *buffer = push_array(scratch.arena, U8, data_size); for (U64 stream_idx = 0; stream_idx < stream_count; stream_idx += 1) { MSF_StreamNumber sn = (MSF_StreamNumber)stream_idx; MemorySet(&data[0], 1 + stream_idx, data_size); for (U64 i = 0; i < c; i += 1) { MSF_UInt read_size = msf_stream_read(msf, sn, buffer, data_size); Assert(read_size == data_size); int cmp = MemoryCompare(buffer, data, data_size); Assert(cmp == 0); } } #endif msf_release(&msf); scratch_end(scratch); } internal void test_msf(void) { test_size_limit(); test_msf_open_save(); } #endif ================================================ FILE: src/linker/pdb_ext/msf_builder.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #define MSF_PAGE_STATE_FREE 1 #define MSF_PAGE_STATE_ALLOC 0 #define MSF_FPM0 1 #define MSF_FPM1 2 #define MSF_DEFAULT_PAGE_SIZE 4096 #define MSF_DEFAULT_FPM MSF_FPM0 typedef struct MSF_PageNumberArray { U64 count; MSF_PageNumber *v; } MSF_PageNumberArray; typedef struct MSF_PageNode { struct MSF_PageNode *next; struct MSF_PageNode *prev; MSF_PageNumber pn; } MSF_PageNode; typedef struct MSF_PageList { MSF_PageNode *first; MSF_PageNode *last; MSF_UInt count; } MSF_PageList; typedef struct MSF_Stream { MSF_StreamNumber sn; MSF_UInt size; MSF_UInt pos; MSF_PageNode *pos_page; MSF_PageList page_list; } MSF_Stream; typedef struct MSF_StreamNode { struct MSF_StreamNode *next; struct MSF_StreamNode *prev; MSF_Stream data; } MSF_StreamNode; typedef struct MSF_StreamList { MSF_UInt count; MSF_StreamNode *first; MSF_StreamNode *last; } MSF_StreamList; typedef struct MSF_PageDataNode { struct MSF_PageDataNode *next; struct MSF_PageDataNode *prev; U8 *data; } MSF_PageDataNode; typedef struct MSF_PageDataList { MSF_PageDataNode *first; MSF_PageDataNode *last; MSF_UInt count; } MSF_PageDataList; typedef struct MSF_Context { Arena *arena; MSF_UInt page_size; MSF_UInt active_fpm; MSF_UInt fpm_rover; MSF_PageNumber page_count; MSF_PageDataList page_data_list; MSF_PageDataList page_data_pool; MSF_PageList header_page_list; MSF_PageList root_page_list; MSF_PageList st_page_list; MSF_PageList page_pool; MSF_StreamList sectab; } MSF_Context; typedef enum MSF_Error { MSF_Error_OK, // if you get this error this means stream table was divided into too many // pages, and to fix this you need to bump up the page size MSF_Error_STREAM_TABLE_HAS_TOO_MANY_PAGES, MSF_OpenError_NOT_ENOUGH_BYTES_TO_READ_HEADER, MSF_OpenError_INVALID_MAGIC, MSF_OpenError_PAGE_SIZE_IS_NOT_POW2, MSF_OpenError_INVALID_PAGE_SIZE, MSF_OpenError_NOT_ENOUGH_PAGES_TO_INIT, MSF_OpenError_INVALID_ROOT_STREAM_PAGE_NUMBER, MSF_OpenError_UNABLE_TO_READ_STREAM_TABLE_PAGE_NUMBERS, MSF_OpenError_STREAM_COUNT_OVERFLOW, MSF_OpenError_UNABLE_TO_READ_STREAM_SIZES, MSF_OpenError_INVALID_STREAM_TABLE, MSF_OpenError_INVALID_ACTIVE_FPM, MSF_OpenError_PAGE_COUNT_DOESNT_MATCH_DATA_SIZE, MSF_BuildError_UNABLE_TO_WRITE_STREAM_TABLE, MSF_BuildError_UNABLE_TO_WRITE_STREAM_TABLE_PAGE_NUMBER_DIRECTORY, MSF_BuildError_UNABLE_TO_WRITE_ROOT_DIRECTORY, MSF_BuildError_UNABLE_TO_WRITE_HEADER, } MSF_Error; //////////////////////////////// typedef struct { MSF_UInt page_size; MSF_PageDataList page_data_list; MSF_PageList page_list; MSF_UInt stream_pos; String8 data; Rng1U64 *range_arr; } MSF_WriteTask; //////////////////////////////// internal MSF_Context * msf_alloc(MSF_UInt page_size, MSF_UInt active_fpm); internal MSF_Error msf_open(String8 data, MSF_Context **msf_out); internal void msf_release(MSF_Context **msf_ptr); internal MSF_Error msf_build(MSF_Context *msf); internal U64 msf_get_save_size(MSF_Context *msf); internal String8List msf_get_page_data_nodes(Arena *arena, MSF_Context *msf); internal B32 msf_save(MSF_Context *msf, void *buffer, U64 buffer_size); internal MSF_Error msf_save_arena(Arena *arena, MSF_Context *msf, String8 *data_out); internal MSF_StreamNode * msf_find_stream_node(MSF_Context *msf, MSF_StreamNumber sn); internal MSF_Stream * msf_find_stream(MSF_Context *msf, MSF_StreamNumber sn); internal B32 msf_grow(MSF_Context *msf, MSF_PageNumber page_count); internal MSF_PageNumber * msf_alloc_pn_arr(Arena *arena, MSF_Context *msf, MSF_UInt alloc_count); internal void msf_free_pn_arr(MSF_Context *msf, MSF_PageNumber *pn_arr, MSF_UInt pn_count); internal MSF_PageList msf_alloc_pages(MSF_Context *msf, MSF_UInt alloc_count); internal void msf_free_pages(MSF_Context *msf, MSF_PageList *page_list); internal MSF_StreamNumber msf_stream_alloc_ex(MSF_Context *msf, MSF_UInt size); internal MSF_StreamNumber msf_stream_alloc(MSF_Context *msf); internal B32 msf_stream_free(MSF_Context *msf, MSF_StreamNumber sn); internal B32 msf_stream_resize(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt new_size); internal B32 msf_stream_resize_ex(MSF_Context *msf, MSF_Stream *stream, MSF_UInt size); internal void msf_stream_set_size(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt size); internal MSF_UInt msf_stream_get_size(MSF_Context *msf, MSF_StreamNumber sn); internal MSF_UInt msf_stream_get_cap(MSF_Context *msf, MSF_StreamNumber); internal MSF_UInt msf_stream_get_pos(MSF_Context *msf, MSF_StreamNumber sn); internal void msf_stream_align(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt align); internal B32 msf_stream_reserve(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt size); internal B32 msf_stream_seek(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt new_pos); internal B32 msf_stream_seek_start(MSF_Context *msf, MSF_StreamNumber sn); internal B32 msf_stream_seek_end(MSF_Context *msf, MSF_StreamNumber sn); internal MSF_UInt msf_stream_read(MSF_Context *msf, MSF_StreamNumber sn, void *dst, MSF_UInt dst_len); internal String8 msf_stream_read_block(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, U64 block_size); internal String8 msf_stream_read_string(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn); internal S8 msf_stream_read_s8(MSF_Context *msf, MSF_StreamNumber sn); internal S16 msf_stream_read_s16(MSF_Context *msf, MSF_StreamNumber sn); internal S32 msf_stream_read_s32(MSF_Context *msf, MSF_StreamNumber sn); internal S64 msf_stream_read_s64(MSF_Context *msf, MSF_StreamNumber sn); internal U8 msf_stream_read_u8(MSF_Context *msf, MSF_StreamNumber sn); internal U16 msf_stream_read_u16(MSF_Context *msf, MSF_StreamNumber sn); internal U32 msf_stream_read_u32(MSF_Context *msf, MSF_StreamNumber sn); internal U64 msf_stream_read_u64(MSF_Context *msf, MSF_StreamNumber sn); #define msf_stream_read_array(msf, sn, ptr, count) msf_stream_read(msf, sn, ptr, sizeof(*ptr) * (count)) #define msf_stream_read_struct(msf, sn, ptr) msf_stream_read_array(msf, sn, ptr, 1) internal B32 msf_stream_write(MSF_Context *msf, MSF_StreamNumber sn, void *buffer, MSF_UInt buffer_size); internal B32 msf_stream_write_string(MSF_Context *msf, MSF_StreamNumber sn, String8 string); internal B32 msf_stream_write_list(MSF_Context *msf, MSF_StreamNumber sn, String8List list); internal B32 msf_stream_write_uint(MSF_Context *msf, MSF_StreamNumber sn, MSF_UInt value); internal B32 msf_stream_write_cstr(MSF_Context *msf, MSF_StreamNumber sn, String8 string); internal B32 msf_stream_write_u8(MSF_Context *msf, MSF_StreamNumber sn, U8 value); internal B32 msf_stream_write_u16(MSF_Context *msf, MSF_StreamNumber sn, U16 value); internal B32 msf_stream_write_u32(MSF_Context *msf, MSF_StreamNumber sn, U32 value); internal B32 msf_stream_write_u64(MSF_Context *msf, MSF_StreamNumber sn, U64 value); internal B32 msf_stream_write_s8(MSF_Context *msf, MSF_StreamNumber sn, S8 value); internal B32 msf_stream_write_s16(MSF_Context *msf, MSF_StreamNumber sn, S16 value); internal B32 msf_stream_write_s32(MSF_Context *msf, MSF_StreamNumber sn, S32 value); internal B32 msf_stream_write_s64(MSF_Context *msf, MSF_StreamNumber sn, S64 value); internal B32 msf_stream_write_parallel(TP_Context *tp, MSF_Context *msf, MSF_StreamNumber sn, void *buffer, MSF_UInt buffer_size); #define msf_stream_write_array(m, s, v, c) msf_stream_write(m, s, (void*)(v), sizeof(*(v)) * (c)) #define msf_stream_write_struct(m, s, v ) msf_stream_write_array(m, s, v, 1) internal MSF_UInt msf_count_pages(MSF_UInt page_size, U64 data_size); internal MSF_PageNumber msf_get_page_count_cap(MSF_PageDataList page_data_list, MSF_UInt page_size); internal MSF_UInt msf_get_fpm_interval_correct(MSF_UInt page_size); internal MSF_UInt msf_get_fpm_interval_wrong(MSF_UInt page_size); internal MSF_UInt msf_get_fpm_idx_from_pn(MSF_UInt page_size, MSF_PageNumber pn); internal MSF_UInt msf_get_fpm_page_bit_state(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn); internal void msf_set_fpm_bit(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageNumber active_fpm, MSF_PageNumber pn, B32 state); internal B32 msf_write(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList page_list, MSF_UInt offset, void *buffer, MSF_UInt buffer_size); internal MSF_UInt msf_read(MSF_PageDataList page_data_list, MSF_UInt page_size, MSF_PageList page_list, MSF_UInt offset, void *buffer, MSF_UInt buffer_size); internal char * msf_error_to_string(MSF_Error code); ================================================ FILE: src/linker/pdb_ext/pdb.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U32 pdb_hash_udt(CV_UDTInfo udt_info, String8 data) { B32 is_fwdref = !!(udt_info.props & CV_TypeProp_FwdRef); B32 is_scoped = !!(udt_info.props & CV_TypeProp_Scoped); B32 has_unique_name = !!(udt_info.props & CV_TypeProp_HasUniqueName); B32 is_anon = has_unique_name && cv_is_udt_name_anon(udt_info.name); U32 hash = 0; // dbi/tpi.cpp:1918 if (!is_fwdref && !is_scoped && !is_anon) { hash = pdb_hash_v1(udt_info.name); } // dbi/tpi.cpp:1937 else if (!is_fwdref && has_unique_name && is_scoped && !is_anon) { hash = pdb_hash_v1(udt_info.unique_name); } // dbi/tpi.cpp 1338 else { hash = pdb_hash_v1(data); } return hash; } internal U32 pdb_crc32_from_string(String8 string) { return ~update_crc32(~0, string.str, string.size); } ================================================ FILE: src/linker/pdb_ext/pdb.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal U32 pdb_hash_udt(CV_UDTInfo udt_info, String8 data); internal U32 pdb_crc32_from_string(String8 string); ================================================ FILE: src/linker/pdb_ext/pdb_builder.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// internal U64 pdb_hash_table_compute_load_factor(U64 count) { // PDB/include/map.h:cdrLoadMax() U64 load_factor = count * 2/3 + 1; return load_factor; } internal void pdb_hash_table_alloc(PDB_HashTable *ht, U32 max) { ProfBeginFunction(); ht->arena = arena_alloc(); ht->bucket_arr = push_array(ht->arena, PDB_HashTableBucket, max); ht->present_bits = bit_array_init32(ht->arena, max); ht->deleted_bits = bit_array_init32(ht->arena, max); ht->max = max; ht->count = 0; bit_array_set_bit_range32(ht->deleted_bits, rng_1u64(0, max), 1); ProfEnd(); } internal void pdb_hash_table_release(PDB_HashTable *ht) { ProfBeginFunction(); arena_release(ht->arena); MemoryZeroStruct(ht); ProfEnd(); } internal PDB_HashTableParseError pdb_hash_table_from_data(PDB_HashTable *ht, String8 data, B32 has_local_data, PDB_HashTableUnpackFunc *unpack_func, void *unpack_ud, U64 *read_bytes_out) { ProfBeginFunction(); PDB_HashTableParseError error = PDB_HashTableParseError_OK; U64 cursor = 0; U32 local_data_size = 0; String8 local_data = str8(0,0); U32 count = 0; U32 max = 0; U32Array present_bits = {0}; U32Array deleted_bits = {0}; do { error = PDB_HashTableParseError_OUT_OF_BYTES; if (has_local_data) { if (cursor + sizeof(local_data_size) > data.size) { break; } cursor += str8_deserial_read_struct(data, cursor, &local_data_size); if (cursor + local_data_size > data.size) { break; } cursor += str8_deserial_read_block(data, cursor, local_data_size, &local_data); } if (cursor + sizeof(count) > data.size) { break; } cursor += str8_deserial_read_struct(data, cursor, &count); if (cursor + sizeof(max) > data.size) { break; } cursor += str8_deserial_read_struct(data, cursor, &max); cursor += pdb_read_bit_vector_string(data, cursor, &present_bits); cursor += pdb_read_bit_vector_string(data, cursor, &deleted_bits); error = PDB_HashTableParseError_OK; } while(0); if (error == PDB_HashTableParseError_OK) { U64 load_factor = pdb_hash_table_compute_load_factor(max); B32 is_count_ok = count < max; B32 is_load_factor_ok = count < load_factor; B32 is_present_bits_ok = present_bits.count <= AlignPow2(max, 32); B32 is_deleted_bits_ok = deleted_bits.count <= AlignPow2(max, 32); if (is_count_ok && is_load_factor_ok && is_present_bits_ok && is_deleted_bits_ok) { Arena *arena = arena_alloc(); PDB_HashTableBucket *bucket_arr = push_array_no_zero(arena, PDB_HashTableBucket, max); U32Array present_bits_new = bit_array_init32(arena, max); U32Array deleted_bits_new = bit_array_init32(arena, max); MemoryCopyTyped(&present_bits_new.v[0], &present_bits.v[0], present_bits.count); MemoryCopyTyped(&deleted_bits_new.v[0], &deleted_bits.v[0], deleted_bits.count); // unpack buckets U64 read_count = 0; for (U64 bucket_idx = 0; bucket_idx < max; bucket_idx += 1) { if (bit_array_is_bit_set(present_bits_new, bucket_idx)) { if (bit_array_is_bit_set(deleted_bits_new, bucket_idx)) { error = PDB_HashTableParseError_CORRUPTED; break; } if (read_count >= count) { error = PDB_HashTableParseError_CORRUPTED; break; } String8 key; String8 value; B32 has_unpack_failed = unpack_func(unpack_ud, local_data, data, &cursor, &key, &value); if (has_unpack_failed) { error = PDB_HashTableParseError_CORRUPTED; break; } bucket_arr[bucket_idx].key = key; bucket_arr[bucket_idx].value = value; read_count += 1; } } if (error == PDB_HashTableParseError_OK) { ht->arena = arena; ht->bucket_arr = bucket_arr; ht->present_bits = present_bits_new; ht->deleted_bits = deleted_bits_new; ht->count = count; ht->max = max; if (read_bytes_out) { // TBH data format should tell parser upfront size of the hash table *read_bytes_out = cursor; } } else { arena_release(arena); } } else { error = PDB_HashTableParseError_CORRUPTED; } } ProfEnd(); return error; } internal String8 pdb_data_from_hash_table(Arena *arena, PDB_HashTable *ht, B32 has_local_data, PDB_HashTablePackFunc *pack_func, void *pack_ud) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); String8Array key_arr = {0}; String8Array value_arr = {0}; pdb_hash_table_get_present_keys_and_values(scratch.arena, ht, &key_arr, &value_arr); String8List local_data_srl = {0}; String8List key_value_srl = {0}; str8_serial_begin(scratch.arena, &local_data_srl); str8_serial_begin(scratch.arena, &key_value_srl); for (U64 i = 0; i < ht->count; i += 1) { String8 key = key_arr.v[i]; String8 value = value_arr.v[i]; pack_func(scratch.arena, &local_data_srl, &key_value_srl, key, value, pack_ud); } // serialize hash table String8List srl = {0}; str8_serial_begin(scratch.arena, &srl); if (has_local_data) { U32 local_data_size32 = safe_cast_u32(local_data_srl.total_size); str8_serial_push_u32(scratch.arena, &srl, local_data_size32); str8_list_concat_in_place(&srl, &local_data_srl); } str8_serial_push_u32(scratch.arena, &srl, ht->count); str8_serial_push_u32(scratch.arena, &srl, ht->max); str8_serial_push_u32(scratch.arena, &srl, ht->present_bits.count); str8_serial_push_array(scratch.arena, &srl, &ht->present_bits.v[0], ht->present_bits.count); str8_serial_push_u32(scratch.arena, &srl, ht->deleted_bits.count); str8_serial_push_array(scratch.arena, &srl, &ht->deleted_bits.v[0], ht->deleted_bits.count); str8_list_concat_in_place(&srl, &key_value_srl); String8 data = str8_serial_end(arena, &srl); scratch_end(scratch); ProfEnd(); return data; } internal void pdb_hash_table_grow(PDB_HashTable *ht, U64 new_capacity) { ProfBeginFunction(); PDB_HashTable new_ht; pdb_hash_table_alloc(&new_ht, new_capacity); for (U32 i = 0; i < ht->max; ++i) { if (bit_array_is_bit_set(ht->present_bits, i)) { PDB_HashTableBucket *bucket = &ht->bucket_arr[i]; B32 is_set = pdb_hash_table_try_set(&new_ht, bucket->key, bucket->value); Assert(is_set); } } pdb_hash_table_release(ht); *ht = new_ht; ProfEnd(); } internal U32 pdb_hash_table_hash(String8 key) { return (U16)pdb_hash_v1(key); } internal B32 pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value) { ProfBeginFunction(); B32 is_set = 0; U32 best_ibucket = pdb_hash_table_hash(key) % ht->max; U32 ibucket = best_ibucket; do { B32 is_present = pdb_hash_table_is_present(ht, ibucket); if ( ! is_present) { PDB_HashTableBucket *bucket = &ht->bucket_arr[ibucket]; bucket->key = push_str8_copy(ht->arena, key); bucket->value = push_str8_copy(ht->arena, value); bit_array_set_bit32(ht->present_bits, ibucket, 1); bit_array_set_bit32(ht->deleted_bits, ibucket, 0); ht->count += 1; is_set = 1; break; } ibucket = (ibucket + 1) % ht->max; } while (ibucket != best_ibucket); ProfEnd(); return is_set; } internal void pdb_hash_table_set(PDB_HashTable *ht, String8 key, String8 value) { ProfBeginFunction(); // should resize? U64 load_factor = pdb_hash_table_compute_load_factor(ht->max); if (ht->count + 1 >= load_factor) { pdb_hash_table_grow(ht, ht->max * 2); } // set new item B32 is_set = pdb_hash_table_try_set(ht, key, value); AssertAlways(is_set); ProfEnd(); } internal B32 pdb_hash_table_get(PDB_HashTable *ht, String8 key, String8 *value_out) { ProfBeginFunction(); B32 is_get_ok = 0; U32 best_ibucket = pdb_hash_table_hash(key) % ht->max; U32 ibucket = best_ibucket; do { B32 is_present = pdb_hash_table_is_present(ht, ibucket); if (is_present) { PDB_HashTableBucket *bucket = &ht->bucket_arr[ibucket]; B32 is_match = str8_match(bucket->key, key, 0); if (is_match) { *value_out = bucket->value; is_get_ok = 1; break; } } else { break; } ibucket = (ibucket + 1) % ht->max; } while (ibucket != best_ibucket); ProfEnd(); return is_get_ok; } internal void pdb_hash_table_delete(PDB_HashTable *ht, String8 key) { ProfBeginFunction(); U32 best_ibucket = pdb_hash_table_hash(key) % ht->max; U32 ibucket = best_ibucket; do { B32 is_present = pdb_hash_table_is_present(ht, ibucket); if (!is_present) { break; } PDB_HashTableBucket *bucket = &ht->bucket_arr[ibucket]; int cmp = MemoryCompare(key.str, bucket->key.str, key.size); if (cmp == 0) { bit_array_set_bit32(ht->present_bits, ibucket, 0); bit_array_set_bit32(ht->deleted_bits, ibucket, 1); ht->count -= 1; break; } ibucket = (ibucket + 1) % ht->max; } while (ibucket != best_ibucket); ProfEnd(); } internal B32 pdb_hash_table_is_present(PDB_HashTable *ht, U32 k) { Assert(k < ht->max); return bit_array_is_bit_set(ht->present_bits, k); } internal B32 pdb_hash_table_is_deleted(PDB_HashTable *ht, U32 k) { Assert(k < ht->max); return bit_array_is_bit_set(ht->deleted_bits, k); } internal void pdb_hash_table_get_present_keys_and_values(Arena *arena, PDB_HashTable *ht, String8Array *keys_out, String8Array *values_out) { *keys_out = str8_array_reserve(arena, ht->count); *values_out = str8_array_reserve(arena, ht->count); for (U64 bucket_idx = 0; bucket_idx < ht->max; bucket_idx += 1) { if (bit_array_is_bit_set(ht->present_bits, bucket_idx)) { PDB_HashTableBucket *bucket = &ht->bucket_arr[bucket_idx]; Assert(keys_out->count < ht->count); keys_out->v[keys_out->count++] = bucket->key; values_out->v[values_out->count++] = bucket->value; } } } //////////////////////////////// internal PDB_HASH_TABLE_UNPACK_FUNC(pdb_named_stream_ht_unpack) { Assert(!ud); U32 key_data_offset = max_U32; *key_value_cursor += str8_deserial_read_struct(key_value_data, *key_value_cursor, &key_data_offset); U8 *cstr_ptr = local_data.str + key_data_offset; U8 *cstr_opl = local_data.str + local_data.size; String8 stream_name = str8_cstring_capped(cstr_ptr, cstr_opl); // NOTE: stream number is U16 but in the reference they cast to U32 String8 stream_number = {0}; *key_value_cursor += str8_deserial_read_block(key_value_data, *key_value_cursor, sizeof(U32), &stream_number); *key_out = stream_name; *value_out = stream_number; return 0; } internal PDB_HASH_TABLE_UNPACK_FUNC(pdb_hash_adj_ht_unpack) { Assert(local_data.size == 0); if (*key_value_cursor + sizeof(PDB_StringOffset) > key_value_data.size){ return 1; } PDB_StringOffset string_offset = 0; *key_value_cursor += str8_deserial_read_struct(key_value_data, *key_value_cursor, &string_offset); if (*key_value_cursor + sizeof(CV_TypeIndex) > key_value_data.size) { return 1; } String8 type_index = {0}; *key_value_cursor += str8_deserial_read_block(key_value_data, *key_value_cursor, sizeof(CV_TypeIndex), &type_index); PDB_StringTable *strtab = (PDB_StringTable*)ud; String8 type_name = pdb_strtab_string_from_offset(strtab, string_offset); *key_out = type_name; *value_out = type_index; return 0; } internal PDB_HASH_TABLE_UNPACK_FUNC(pdb_src_header_block_ht_unpack) { if (*key_value_cursor + sizeof(PDB_StringOffset) > key_value_data.size) { return 1; } PDB_StringOffset path_offset = 0; *key_value_cursor += str8_deserial_read_struct(key_value_data, *key_value_cursor, &path_offset); if (path_offset + sizeof(PDB_SrcHeaderBlockEntry) > key_value_data.size) { return 1; } String8 src_header_block_entry = {0}; *key_value_cursor += str8_deserial_read_block(key_value_data, *key_value_cursor, sizeof(PDB_SrcHeaderBlockEntry), &src_header_block_entry); PDB_StringTable *strtab = (PDB_StringTable*)ud; String8 path = pdb_strtab_string_from_offset(strtab, path_offset); *key_out = path; *value_out = src_header_block_entry; return 0; } internal PDB_HASH_TABLE_PACK_FUNC(pdb_named_stream_ht_pack) { Assert(!ud); Assert(value.size == sizeof(U32)); U64 key_data_offset = local_data_srl->total_size; str8_serial_push_cstr(arena, local_data_srl, key); U32 key_data_offset32 = safe_cast_u32(key_data_offset); str8_serial_push_u32(arena, key_value_srl, key_data_offset32); str8_serial_push_string(arena, key_value_srl, value); } internal PDB_HASH_TABLE_PACK_FUNC(pdb_hash_adj_ht_pack) { Assert(value.size == sizeof(CV_TypeIndex)); PDB_StringTable *strtab = (PDB_StringTable*)ud; PDB_StringIndex string_idx = PDB_INVALID_STRING_INDEX; B32 is_found = pdb_strtab_search(strtab, key, &string_idx); Assert(is_found); PDB_StringOffset type_name_offset = pdb_strtab_string_to_offset(strtab, string_idx); str8_serial_push_struct(arena, key_value_srl, &type_name_offset); str8_serial_push_string(arena, key_value_srl, value); } internal PDB_HASH_TABLE_PACK_FUNC(pdb_src_header_block_ht_pack) { Assert(value.size == sizeof(PDB_SrcHeaderBlockEntry)); PDB_StringTable *strtab = (PDB_StringTable*)ud; PDB_StringIndex path_idx = 0; B32 is_found = pdb_strtab_search(strtab, key, &path_idx); Assert(is_found); PDB_StringOffset path_offset = pdb_strtab_string_to_offset(strtab, path_idx); str8_serial_push_struct(arena, key_value_srl, &path_offset); str8_serial_push_string(arena, key_value_srl, value); } //////////////////////////////// internal PDB_HashTableParseError pdb_hash_adj_hash_table_from_data(PDB_HashTable *ht, String8 data, PDB_StringTable *strtab, U64 *read_bytes_out) { return pdb_hash_table_from_data(ht, data, 0, pdb_hash_adj_ht_unpack, strtab, read_bytes_out); } internal PDB_HashTableParseError pdb_src_header_block_ht_from_data(PDB_HashTable *ht, String8 data, PDB_StringTable *strtab, U64 *read_bytes_out) { return pdb_hash_table_from_data(ht, data, 0, pdb_src_header_block_ht_unpack, strtab, read_bytes_out); } internal PDB_HashTableParseError pdb_named_stream_ht_from_data(PDB_HashTable *ht, String8 data, U64 *read_bytes_out) { return pdb_hash_table_from_data(ht, data, 1, pdb_named_stream_ht_unpack, 0, read_bytes_out); } internal String8 pdb_data_from_hash_adj_hash_table(Arena *arena, PDB_HashTable *ht, PDB_StringTable *strtab) { String8 data = pdb_data_from_hash_table(arena, ht, 0, pdb_hash_adj_ht_pack, strtab); return data; } internal String8 pdb_data_from_src_header_block_ht(Arena *arena, PDB_HashTable *ht, PDB_StringTable *strtab) { String8 data = pdb_data_from_hash_table(arena, ht, 0, pdb_src_header_block_ht_pack, strtab); return data; } internal String8 pdb_data_from_named_stream_ht(Arena *arena, PDB_HashTable *ht) { String8 data = pdb_data_from_hash_table(arena, ht, 1, pdb_named_stream_ht_pack, 0); return data; } //////////////////////////////// internal void pdb_strtab_alloc(PDB_StringTable *strtab, U32 max) { ProfBeginFunction(); U64 bucket_max = (U64)((F64)max * 1.3); bucket_max += 1; // reserve space for null string strtab->arena = arena_alloc(); strtab->version = 1; strtab->size = 0; strtab->bucket_count = 0; strtab->bucket_max = bucket_max; strtab->ibucket_array = push_array(strtab->arena, U32, strtab->bucket_max); MemorySet(strtab->ibucket_array, 0xff, sizeof(strtab->ibucket_array[0]) * strtab->bucket_max); strtab->bucket_array = push_array(strtab->arena, PDB_StringTableBucket *, strtab->bucket_max); // string table always has a null for first entry pdb_strtab_add(strtab, str8_lit("")); ProfEnd(); } internal PDB_StringTableOpenError pdb_strtab_open(PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); PDB_StringTableOpenError err = PDB_StringTableOpenError_OK; Arena *arena = 0; String8 string_buffer; U32 bucket_max; U32 bucket_count; U32 *ibucket_array; PDB_StringTableBucket **bucket_array; PDB_StringTableHeader header = {0}; msf_stream_read_struct(msf, sn, &header); if (header.magic == PDB_StringTableHeader_MAGIC) { if (header.version == PDB_StringTableHeader_CurrentVersion) { Temp scratch = scratch_begin(0,0); arena = arena_alloc(); U32 string_size; String8 offset_buffer; // read table data string_size = msf_stream_read_u32(msf, sn); string_buffer = msf_stream_read_block(arena, msf, sn, string_size); bucket_max = msf_stream_read_u32(msf, sn); offset_buffer = msf_stream_read_block(scratch.arena, msf, sn, bucket_max * sizeof(U32)); bucket_count = msf_stream_read_u32(msf, sn); U64 expected_size = sizeof(PDB_StringTableHeader) + string_buffer.size + sizeof(bucket_max) + offset_buffer.size + sizeof(bucket_count); U64 actual_size = msf_stream_get_size(msf, sn); if (expected_size <= actual_size && string_buffer.size == string_size && offset_buffer.size == sizeof(U32)*bucket_max && bucket_count <= bucket_max) { // init string table ibucket_array = push_array_no_zero(arena, U32, bucket_max); bucket_array = push_array_no_zero(arena, PDB_StringTableBucket *, bucket_max); // open buckets PDB_StringTableBucket *node_arr = push_array_no_zero(arena, PDB_StringTableBucket, bucket_count); U8 *string_buffer_ptr = string_buffer.str; U8 *string_buffer_opl = string_buffer.str + string_buffer.size; U32 *offset_array = (U32*)offset_buffer.str; U32 bucket_read_idx = 0; for (U32 bucket_idx = 0; bucket_idx < bucket_max; bucket_idx += 1) { U32 string_offset = offset_array[bucket_idx]; // sanity check offset if (string_offset >= string_buffer.size) { err = PDB_StringTableOpenError_STRING_OFFSET_OUT_OF_BOUNDS; break; } // empty bucket else if (string_offset == 0) { ibucket_array[bucket_idx] = 0; bucket_array[bucket_idx] = 0; } // bucket with string else { if (bucket_read_idx >= bucket_count) { err = PDB_StringTableOpenError_OFFSETS_EXCEED_BUCKET_COUNT; break; } // get bucket PDB_StringTableBucket *bucket = &node_arr[bucket_read_idx]; // init bucket bucket->data = str8_cstring_capped(string_buffer_ptr + string_offset, string_buffer_opl); bucket->offset = string_offset; bucket->istr = bucket_read_idx; // assign bucket bucket_array[bucket_idx] = bucket; ibucket_array[bucket_idx] = bucket_read_idx; // advance bucket_read_idx += 1; } } } else { err = PDB_StringTableOpenError_CORRUPTED; } scratch_end(scratch); } else { err = PDB_StringTableOpenError_UNKNOWN_VERSION; } } else { err = PDB_StringTableOpenError_BAD_MAGIC; } if (err == PDB_StringTableOpenError_OK) { strtab->arena = arena; strtab->version = header.version; strtab->size = string_buffer.size; strtab->bucket_count = bucket_count; strtab->bucket_max = bucket_max; strtab->ibucket_array = ibucket_array; strtab->bucket_array = bucket_array; } else { if (arena) { arena_release(arena); } } ProfEnd(); return err; } internal void pdb_strtab_build(PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); // serialize bucket data U8 *string_buffer = push_array_no_zero(scratch.arena, U8, strtab->size); U32 *bucket_offset_arr = push_array(scratch.arena, U32, strtab->bucket_max); for (U32 bucket_idx = 0; bucket_idx < strtab->bucket_max; bucket_idx += 1) { PDB_StringTableBucket *bucket = strtab->bucket_array[bucket_idx]; if (bucket) { // store string offset Assert(bucket->offset + bucket->data.size <= strtab->size); bucket_offset_arr[bucket_idx] = bucket->offset; // write c string at bucket offset U8 *str_ptr = string_buffer + bucket->offset; MemoryCopy(str_ptr, bucket->data.str, bucket->data.size); str_ptr[bucket->data.size] = '\0'; } } // fill out header PDB_StringTableHeader header; header.magic = PDB_StringTableHeader_MAGIC; header.version = strtab->version; // reserve memory for entire string table MSF_UInt reserve_size = sizeof(header) + sizeof(strtab->size) + strtab->size + sizeof(bucket_offset_arr[0]) * strtab->bucket_max + sizeof(strtab->bucket_count); msf_stream_reserve(msf, sn, reserve_size); // write out string table msf_stream_write_struct(msf, sn, &header); msf_stream_write_struct(msf, sn, &strtab->size); msf_stream_write_array (msf, sn, string_buffer, strtab->size); msf_stream_write_struct(msf, sn, &strtab->bucket_max); msf_stream_write_array (msf, sn, bucket_offset_arr, strtab->bucket_max); msf_stream_write_u32(msf, sn, strtab->bucket_count - 1); // 1 for null scratch_end(scratch); ProfEnd(); } internal void pdb_strtab_release(PDB_StringTable *strtab) { ProfBeginFunction(); arena_release(strtab->arena); MemoryZeroStruct(strtab); ProfEnd(); } internal U32 pdb_strtab_get_serialized_size(PDB_StringTable *strtab) { U32 result = 0; result += sizeof(PDB_StringTableHeader); result += sizeof(U32); // strtab size result += strtab->size; result += sizeof(U32); // bucket count result += sizeof(U32) * strtab->bucket_max; result += sizeof(U32); // string count return result; } internal U32 pdb_strtab_hash(PDB_StringTable *strtab, String8 string) { U32 hash = 0; switch (strtab->version) { case 1: hash = pdb_hash_v1(string); break; default: NotImplemented; break; } U32 ibucket = hash % strtab->bucket_max; return ibucket; } internal B32 pdb_strtab_add_(PDB_StringTable *strtab, U64 hash, PDB_StringTableBucket *bucket) { U64 best_bucket_idx = hash; U64 bucket_idx = best_bucket_idx; do { if (strtab->bucket_array[bucket_idx] == 0) { strtab->ibucket_array[bucket->istr] = bucket_idx; strtab->bucket_array[bucket_idx] = bucket; strtab->size += bucket->data.size + /* null: */ 1; return 1; } bucket_idx = (bucket_idx + 1) % strtab->bucket_max; } while (best_bucket_idx != bucket_idx); return 0; } internal void pdb_strtab_add_cv_string_hash_table(PDB_StringTable *strtab, CV_StringHashTable string_ht) { ProfBeginFunction(); // reserve enough slots for new strings pdb_strtab_grow(strtab, string_ht.total_insert_count); // upfront push buckets PDB_StringTableBucket *buckets = push_array_no_zero(strtab->arena, PDB_StringTableBucket, string_ht.total_insert_count); U64 base_offset = strtab->size; // proceed to fill out buckets & add them to the string table for (U64 bucket_idx = 0, string_idx = 0; bucket_idx < string_ht.bucket_cap; ++bucket_idx) { if (string_ht.buckets[bucket_idx] != 0) { PDB_StringTableBucket *dst = &buckets[string_idx++]; dst->data = string_ht.buckets[bucket_idx]->string; dst->offset = base_offset + string_ht.buckets[bucket_idx]->u.offset; dst->istr = strtab->bucket_count++; // TODO: precompute hashes in parallel U64 hash = pdb_strtab_hash(strtab, dst->data); B32 was_added = pdb_strtab_add_(strtab, hash, dst); Assert(was_added); } } ProfEnd(); } internal B32 pdb_strtab_try_add(PDB_StringTable *strtab, String8 string, PDB_StringIndex *index_out) { PDB_StringTableBucket *bucket = push_array(strtab->arena, PDB_StringTableBucket, 1); bucket->data = push_str8_copy(strtab->arena, string); bucket->offset = strtab->size; bucket->istr = (PDB_StringIndex)strtab->bucket_count++; U32 hash = pdb_strtab_hash(strtab, string); B32 was_added = pdb_strtab_add_(strtab, hash, bucket); *index_out = bucket->istr; return was_added; } internal void pdb_strtab_grow(PDB_StringTable *strtab, U64 new_max) { ProfBeginFunction(); PDB_StringTable new_strtab; pdb_strtab_alloc(&new_strtab, new_max); // start with 1 because null bucket is already added during string table alloc for (PDB_StringIndex istr = 1; istr < strtab->bucket_max; ++istr) { U32 ibucket = strtab->ibucket_array[istr]; B32 is_bucket_null = ibucket >= strtab->bucket_max; if (is_bucket_null) { continue; } PDB_StringTableBucket *bucket = strtab->bucket_array[ibucket]; PDB_StringIndex new_istr; B32 is_bucket_pushed = pdb_strtab_try_add(&new_strtab, bucket->data, &new_istr); Assert(is_bucket_pushed); Assert(new_istr == istr); U32 new_ibucket = new_strtab.ibucket_array[new_istr]; PDB_StringTableBucket *new_bucket = new_strtab.bucket_array[new_ibucket]; Assert(new_bucket->offset == bucket->offset); } *strtab = new_strtab; ProfEnd(); } internal PDB_StringIndex pdb_strtab_add(PDB_StringTable *strtab, String8 string) { PDB_StringIndex index = 0; B32 is_pushed = pdb_strtab_try_add(strtab, string, &index); if (!is_pushed) { // increase number of slots in the hash table pdb_strtab_grow(strtab, strtab->bucket_max * 2); // now we have enough slots for the new string is_pushed = pdb_strtab_try_add(strtab, string, &index); AssertAlways(is_pushed); } return index; } internal B32 pdb_strtab_search(PDB_StringTable *strtab, String8 string, PDB_StringIndex *index_out) { B32 is_found = 0; U32 best_ibucket = pdb_strtab_hash(strtab, string); U32 ibucket = best_ibucket; do { PDB_StringTableBucket *bucket = strtab->bucket_array[ibucket]; if (bucket == NULL) { break; } if (str8_match(bucket->data, string, 0)) { *index_out = bucket->istr; is_found = 1; break; } ibucket = (ibucket + 1) % strtab->bucket_max; } while (ibucket != best_ibucket); return is_found; } internal String8 pdb_strtab_string_from_offset(PDB_StringTable *strtab, PDB_StringOffset offset) { String8 string = str8(0,0); for (U32 ibucket = 0; ibucket < strtab->bucket_max; ++ibucket) { PDB_StringTableBucket *bucket = strtab->bucket_array[ibucket]; if (bucket) { if (bucket->offset == offset) { string = bucket->data; break; } } } return string; } internal PDB_StringOffset pdb_strtab_string_to_offset(PDB_StringTable *strtab, PDB_StringIndex stridx) { Assert(stridx < strtab->bucket_max); U32 ibucket = strtab->ibucket_array[stridx]; PDB_StringOffset offset = strtab->bucket_array[ibucket]->offset; return offset; } internal String8 pdb_string_from_string_table_open_error(PDB_StringTableOpenError err) { String8 result = str8(0,0); switch (err) { case PDB_StringTableOpenError_OK: break; case PDB_StringTableOpenError_BAD_MAGIC: result = str8_lit("BAD_MAGIC"); break; case PDB_StringTableOpenError_UNKNOWN_VERSION: result = str8_lit("UNKNOWN_VERSION"); break; case PDB_StringTableOpenError_CORRUPTED: result = str8_lit("CORRUPTED"); break; case PDB_StringTableOpenError_OFFSETS_EXCEED_BUCKET_COUNT: result = str8_lit("OFFSETS_EXCEED_BUCKET_COUNT"); break; case PDB_StringTableOpenError_STRING_OFFSET_OUT_OF_BOUNDS: result = str8_lit("STRING_OFFSET_OUT_OF_BOUNDS"); break; } return result; } //////////////////////////////// internal PDB_OpenTypeServerError pdb_type_server_parse_from_data_v80(String8 data, PDB_TypeServerParse *parse) { ProfBeginFunction(); PDB_OpenTypeServerError error = PDB_OpenTypeServerError_UNKNOWN; PDB_TpiHeader header; MemoryZeroStruct(&header); str8_deserial_read_struct(data, 0, &header); Assert(header.version == PDB_TpiVersion_IMPV80); if (header.ti_lo >= CV_MinComplexTypeIndex && header.ti_lo <= header.ti_hi) { if (header.hash_bucket_count > 0 && header.hash_bucket_count <= PDB_TYPE_SERVER_HASH_BUCKET_COUNT_MAX) { parse->ti_range = rng_1u64(header.ti_lo, header.ti_hi); parse->leaf_data = str8_substr(data, rng_1u64(sizeof(PDB_TpiHeader), sizeof(PDB_TpiHeader) + header.leaf_data_size )); error = PDB_OpenTypeServerError_OK; } else { error = PDB_OpenTypeServerError_INVALID_BUCKET_COUNT; } } else { error = PDB_OpenTypeServerError_INVALID_TI_RANGE; } ProfEnd(); return error; } internal PDB_OpenTypeServerError pdb_type_server_parse_from_data(String8 data, PDB_TypeServerParse *parse_out) { PDB_OpenTypeServerError error = PDB_OpenTypeServerError_UNKNOWN; PDB_TpiVersion version = 0; str8_deserial_read_struct(data, 0, &version); switch (version) { case PDB_TpiVersion_IMPV80: error = pdb_type_server_parse_from_data_v80(data, parse_out); break; case PDB_TpiVersion_INTV_VC2: case PDB_TpiVersion_IMPV40: case PDB_TpiVersion_IMPV50_INTERIM: case PDB_TpiVersion_IMPV70: error = PDB_OpenTypeServerError_UNSUPPORTED_VERSION; break; default: Assert(!"unknown TPI version"); break; } return error; } internal PDB_TypeServer * pdb_type_server_alloc(U64 bucket_cap) { ProfBeginFunction(); AssertAlways(0x1000 <= bucket_cap && bucket_cap <= 0x40000); Arena *arena = arena_alloc(); PDB_TypeServer *ts = push_array(arena, PDB_TypeServer, 1); ts->arena = arena; ts->hash_sn = MSF_INVALID_STREAM_NUMBER; ts->ti_lo = CV_MinComplexTypeIndex; ts->bucket_cap = bucket_cap; ts->buckets = push_array(arena, PDB_TypeBucket *, ts->bucket_cap); pdb_hash_table_alloc(&ts->hash_adj, 32); ProfEnd(); return ts; } internal PDB_TypeServer * pdb_type_server_open_v80(MSF_Context *msf, MSF_StreamNumber sn, PDB_StringTable *strtab) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); PDB_TypeServer *ts = NULL; PDB_TpiHeader header = {0}; msf_stream_seek(msf, sn, 0); MSF_UInt read_header_size = msf_stream_read_struct(msf, sn, &header); // have we read enough bytes? if (read_header_size != sizeof(PDB_TpiHeader)) { goto exit; } // is lowest non-simple type index valid? if (header.ti_lo < CV_MinComplexTypeIndex) { goto exit; } // is high non-simple type index valid? if (header.ti_lo > header.ti_hi) { goto exit; } // validate hash bucket count if (header.hash_bucket_count == 0) { goto exit; } if (header.hash_bucket_count > PDB_TYPE_SERVER_HASH_BUCKET_COUNT_MAX) { goto exit; } // are there enough bytes in the stream to read hash values? U64 hash_stream_size = msf_stream_get_size(msf, header.hash_sn); if (header.hash_vals.off + header.hash_vals.size > hash_stream_size) { goto exit; } ts = pdb_type_server_alloc(header.hash_bucket_count); // read & parse code view types String8 types_data = msf_stream_read_block(ts->arena, msf, sn, header.leaf_data_size); CV_DebugT debug_t = cv_debug_t_from_data(scratch.arena, types_data, PDB_LEAF_ALIGN); // read hash data U8 *hash_buffer = push_array(scratch.arena, U8, header.hash_vals.size); msf_stream_seek(msf, header.hash_sn, header.hash_vals.off); MSF_UInt hash_buffer_size = msf_stream_read(msf, header.hash_sn, hash_buffer, header.hash_vals.size); Assert(hash_buffer_size == header.hash_vals.size); // rebuild type buckets for (U64 cursor = 0, leaf_idx = 0; cursor + header.hash_key_size <= hash_buffer_size; cursor += header.hash_key_size, leaf_idx += 1) { String8 raw_leaf = cv_debug_t_get_raw_leaf(debug_t, leaf_idx); str8_list_push(ts->arena, &ts->leaf_list, raw_leaf); // read out bucket hash U64 hash = 0; MemoryCopy(&hash, hash_buffer + cursor, header.hash_key_size); // push bucket PDB_TypeBucket *bucket = push_array(ts->arena, PDB_TypeBucket, 1); bucket->raw_leaf = raw_leaf; bucket->type_index = header.ti_lo + leaf_idx; SLLStackPush(ts->buckets[hash], bucket); } // adjust type buckets msf_stream_seek(msf, header.hash_sn, header.hash_adj.off); String8 adjust_data = msf_stream_read_block(scratch.arena, msf, header.hash_sn, header.hash_adj.size); // open adjust hash table PDB_HashTableParseError hash_adj_parse_error = pdb_hash_adj_hash_table_from_data(&ts->hash_adj, adjust_data, strtab, 0); if (hash_adj_parse_error == PDB_HashTableParseError_OUT_OF_BYTES) { pdb_hash_table_alloc(&ts->hash_adj, 16); } else { Assert(hash_adj_parse_error == PDB_HashTableParseError_OK); } // grab keys and values String8Array key_arr = {0}; String8Array value_arr = {0}; pdb_hash_table_get_present_keys_and_values(scratch.arena, &ts->hash_adj, &key_arr, &value_arr); // adjust type buckets for (U64 i = 0; i < ts->hash_adj.count; i += 1) { String8 type_name = key_arr.v[i]; CV_TypeIndex type_index = *(CV_TypeIndex*)value_arr.v[i].str; // name -> hash U64 hash = pdb_hash_v1(type_name); hash %= ts->bucket_cap; // search for type bucket PDB_TypeBucket *curr, *prev; for (curr = ts->buckets[hash], prev = 0; curr != 0; prev = curr, curr = curr->next) { if (curr->type_index == type_index) { break; } } // move type to the head if (prev && curr) { prev->next = curr->next; curr->next = ts->buckets[hash]; ts->buckets[hash] = curr; } Assert(curr); } exit:; scratch_end(scratch); ProfEnd(); return ts; } internal PDB_TypeServer * pdb_type_server_open(MSF_Context *msf, MSF_StreamNumber sn, PDB_StringTable *strtab) { ProfBeginFunction(); PDB_TypeServer *ts = NULL; PDB_TpiVersion version = 0; msf_stream_seek(msf, sn, 0); msf_stream_read_struct(msf, sn, &version); switch (version) { case PDB_TpiVersion_IMPV80: { ts = pdb_type_server_open_v80(msf, sn, strtab); } break; case PDB_TpiVersion_INTV_VC2: case PDB_TpiVersion_IMPV40: case PDB_TpiVersion_IMPV50_INTERIM: case PDB_TpiVersion_IMPV70: { NotImplemented; } break; default: Assert(!"unknown TPI version"); break; } ProfEnd(); return ts; } internal THREAD_POOL_TASK_FUNC(pdb_write_type_to_bucket_map_32_task) { PDB_WriteTypeToBucketMap *task = raw_task; U64 bucket_idx = task_id; U32 bucket_idx32 = safe_cast_u32(bucket_idx); PDB_TypeServer *ts = task->ts; PDB_TypeBucket *head = ts->buckets[bucket_idx]; for (PDB_TypeBucket *bucket = head; bucket != 0; bucket = bucket->next) { Assert(bucket->type_index >= ts->ti_lo); Assert(bucket->type_index - ts->ti_lo < ts->leaf_list.node_count); CV_TypeIndex type_idx = bucket->type_index - ts->ti_lo; Assert(task->map[type_idx] == 0); task->map[type_idx] = bucket_idx32; } } internal PDB_TypeHashStreamInfo pdb_type_hash_stream_build(TP_Context *tp, PDB_TypeServer *ts, PDB_StringTable *strtab, MSF_Context *msf, PDB_TpiOffHint *hint_arr, U64 hint_count) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); // write (type index -> bucket index) map // // zero-out entire map so non-UDTs type indices, that are NOT in the hash table, // map to zero offset U32 *type_to_bucket_map = push_array(scratch.arena, U32, ts->leaf_list.node_count); { ProfBegin("Bucket Map"); PDB_WriteTypeToBucketMap type_to_bucket_task; type_to_bucket_task.ts = ts; type_to_bucket_task.map = type_to_bucket_map; tp_for_parallel(tp, 0, ts->bucket_cap, pdb_write_type_to_bucket_map_32_task, &type_to_bucket_task); ProfEnd(); } // write bucket adjust info String8 hash_adj_data = pdb_data_from_hash_adj_hash_table(scratch.arena, &ts->hash_adj, strtab); ProfBegin("MSF Write"); // write data to stream if (ts->hash_sn == MSF_INVALID_STREAM_NUMBER) { ts->hash_sn = msf_stream_alloc(msf); } msf_stream_seek_start(msf, ts->hash_sn); PDB_OffsetSize hash_vals; hash_vals.off = msf_stream_get_pos(msf, ts->hash_sn); hash_vals.size = sizeof(type_to_bucket_map[0]) * ts->leaf_list.node_count; msf_stream_write(msf, ts->hash_sn, &type_to_bucket_map[0], hash_vals.size); PDB_OffsetSize hint_offs; hint_offs.off = msf_stream_get_pos(msf, ts->hash_sn); hint_offs.size = sizeof(hint_arr[0]) * hint_count; msf_stream_write(msf, ts->hash_sn, &hint_arr[0], hint_offs.size); PDB_OffsetSize hash_adj; hash_adj.off = msf_stream_get_pos(msf, ts->hash_sn); hash_adj.size = hash_adj_data.size; msf_stream_write_string(msf, ts->hash_sn, hash_adj_data); ProfEnd(); // fill out result PDB_TypeHashStreamInfo result; result.hash_vals = hash_vals; result.ti_offs = hint_offs; result.hash_adj = hash_adj; scratch_end(scratch); ProfEnd(); return result; } internal THREAD_POOL_TASK_FUNC(pdb_write_types_task) { ProfBeginFunction(); PDB_WriteTypesTask *task = raw_task; String8Node *node = task->lf_arr[task_id]; Rng1U64 range = task->lf_range_arr[task_id]; U64 cursor = task->lf_cursor_arr[task_id]; for (U64 lf_idx = range.min; lf_idx < range.max; node = node->next, lf_idx += 1) { if (lf_idx % PDB_TYPE_HINT_STEP == 0) { U64 off_idx = lf_idx / PDB_TYPE_HINT_STEP; Assert(off_idx < task->hint_count); Assert(cursor < PDB_TYPE_OFFSET_MAX); task->hint_arr[off_idx].itype = task->ti_lo + lf_idx; task->hint_arr[off_idx].off = (PDB_TypeOffset)cursor; } // copy leaf data MemoryCopy(task->lf_buf + cursor, node->string.str, node->string.size); cursor += node->string.size; } ProfEnd(); } internal void pdb_type_server_build(TP_Context *tp, PDB_TypeServer *ts, PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); ProfBeginDynamic("Prepare Buffers [Leaf Count: %llu]", ts->leaf_list.node_count); U64 hint_count = CeilIntegerDiv(ts->leaf_list.node_count, PDB_TYPE_HINT_STEP); PDB_TpiOffHint *hint_arr = push_array_no_zero(scratch.arena, PDB_TpiOffHint, hint_count); String8Node **lf_arr = push_array_no_zero(scratch.arena, String8Node *, tp->worker_count); U64 *lf_cursor_arr = push_array_no_zero(scratch.arena, U64, tp->worker_count); Rng1U64 *lf_range_arr = tp_divide_work(scratch.arena, ts->leaf_list.node_count, tp->worker_count); U64 lf_buf_size = 0; U64 lf_node_idx = 0; U64 lf_arr_idx = 0; for (String8Node *lf = ts->leaf_list.first; lf != 0; lf = lf->next) { if (lf_node_idx == lf_range_arr[lf_arr_idx].min) { // :thread_pool_dummy_range lf_cursor_arr[lf_arr_idx] = lf_buf_size; lf_arr[lf_arr_idx] = lf; lf_arr_idx += 1; } lf_buf_size += lf->string.size; lf_node_idx += 1; } ProfEnd(); ProfBegin("Write Type Data & Hints"); PDB_WriteTypesTask write_types_task; write_types_task.ti_lo = ts->ti_lo; write_types_task.ti_hi = ts->ti_lo + ts->leaf_list.node_count; write_types_task.hint_count = hint_count; write_types_task.hint_arr = hint_arr; write_types_task.lf_arr = lf_arr; write_types_task.lf_range_arr = lf_range_arr; write_types_task.lf_cursor_arr = lf_cursor_arr; write_types_task.lf_buf = push_array_no_zero(scratch.arena, U8, lf_buf_size); write_types_task.lf_buf_size = lf_buf_size; tp_for_parallel(tp, 0, tp->worker_count, pdb_write_types_task, &write_types_task); ProfEnd(); // build type lookup accelerator PDB_TypeHashStreamInfo hash_stream_info = pdb_type_hash_stream_build(tp, ts, strtab, msf, hint_arr, hint_count); // fill out header PDB_TpiHeader header; header.version = PDB_TpiVersion_IMPV80; header.header_size = sizeof(header); header.ti_lo = ts->ti_lo; header.ti_hi = ts->ti_lo + ts->leaf_list.node_count; header.leaf_data_size = safe_cast_u32(lf_buf_size); header.hash_sn = ts->hash_sn; header.hash_sn_aux = MSF_INVALID_STREAM_NUMBER; header.hash_key_size = sizeof(U32); header.hash_bucket_count = ts->bucket_cap; header.hash_vals = hash_stream_info.hash_vals; header.itype_offs = hash_stream_info.ti_offs; header.hash_adj = hash_stream_info.hash_adj; // write type server to stream ProfBegin("MSF Commit"); msf_stream_seek_start(msf, sn); msf_stream_write_struct(msf, sn, &header); msf_stream_write_parallel(tp, msf, sn, write_types_task.lf_buf, lf_buf_size); ProfEnd(); scratch_end(scratch); ProfEnd(); } internal void pdb_type_server_release(PDB_TypeServer **ts_ptr) { ProfBeginFunction(); arena_release((*ts_ptr)->arena); *ts_ptr = 0; ProfEnd(); } internal String8Node * pdb_type_server_make_leaf(PDB_TypeServer *ts, CV_LeafKind kind, String8 data) { ProfBeginFunction(); String8 leaf = cv_serialize_raw_leaf(ts->arena, kind, data, PDB_LEAF_ALIGN); String8Node *node = str8_list_push(ts->arena, &ts->leaf_list, leaf); ProfEnd(); return node; } internal U32 pdb_type_server_hash(String8 data) { U32 hash = pdb_hash_v1(data); return hash; } internal PDB_TypeBucket * pdb_type_server_push_udt_arr(PDB_TypeServer *ts, U64 count, U32 *hash_arr, String8 *raw_leaf_arr) { // check if type server already contains this leaf and if so move // it to the head of bucket list. #if 0 B32 is_udt = pdb_is_udt(kind); if (is_udt) { PDB_UDTInfo udt_info = pdb_get_udt_info(kind, data); U32 udt_hash = pdb_hash_udt(udt_info, data) % ts->bucket_count; U64 match_count = 0; for (PDB_TypeBucket *curr = ts->bucket_table[udt_hash], *prev = NULL; curr != NULL; prev = curr, curr = curr->next) { if (curr->leaf->kind == kind) { PDB_UDTInfo this_udt_info = pdb_get_udt_info(curr->leaf->kind, curr->leaf->data); if (str8_match(udt_info.name, this_udt_info.name)) { B32 is_data_match = curr->leaf->data.size == data.size && MemoryCompare(curr->leaf->data.str, data.str, data.size) == 0; if (is_data_match) { B32 is_not_head = (match_count > 0); if (is_not_head) { // move bucket to head prev->next = curr->next; curr->next = ts->bucket_table[udt_hash]; ts->bucket_table[udt_hash] = curr; // update hash adjust pdb_hash_table_delete(&ts->hash_adj, udt_info.name); pdb_hash_table_set(&ts->hash_adj, udt_info.name, str8((U8*)&curr->leaf->type_index, sizeof(curr->leaf->type_index))); } return curr->leaf; } match_count += 1; } } } } #endif PDB_TypeBucket *bucket_arr = push_array_no_zero(ts->arena, PDB_TypeBucket, count); for (U64 leaf_idx = 0; leaf_idx < count; leaf_idx += 1) { U32 hash = hash_arr[leaf_idx]; String8 raw_leaf = raw_leaf_arr[leaf_idx]; CV_Leaf leaf = cv_leaf_from_string(raw_leaf); // make sure we push a complete UDT Assert(cv_is_udt(leaf.kind)); Assert(!(cv_get_udt_info(leaf.kind, leaf.data).props & CV_TypeProp_FwdRef)); PDB_TypeBucket *bucket = &bucket_arr[leaf_idx]; bucket->next = 0; bucket->raw_leaf = raw_leaf; bucket->type_index = ts->ti_lo + ts->leaf_list.node_count + leaf_idx; U32 bucket_idx = hash % ts->bucket_cap; SLLStackPush(ts->buckets[bucket_idx], bucket); } return bucket_arr; } internal PDB_TypeBucket * pdb_type_server_push_udt(PDB_TypeServer *ts, U32 hash, String8 raw_leaf) { return pdb_type_server_push_udt_arr(ts, 1, &hash, &raw_leaf); } internal void pdb_type_server_push(PDB_TypeServer *ts, String8 raw_leaf) { ProfBeginFunction(); CV_Leaf leaf; cv_deserial_leaf(raw_leaf, 0, 1, &leaf); if (cv_is_udt(leaf.kind)) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); B32 is_complete = !(udt_info.props & CV_TypeProp_FwdRef); if (is_complete) { U32 hash = pdb_hash_udt(udt_info, leaf.data); pdb_type_server_push_udt(ts, hash, raw_leaf); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(pdb_count_udt_task) { PDB_PushLeafTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) { CV_Leaf leaf = cv_debug_t_get_leaf(task->debug_t, leaf_idx); if (cv_is_udt(leaf.kind)) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if (~udt_info.props & CV_TypeProp_FwdRef) { ++task->udt_counts[task_id]; } } } } internal THREAD_POOL_TASK_FUNC(pdb_push_udt_leaf_task) { PDB_PushLeafTask *task = raw_task; PDB_TypeServer *type_server = task->type_server; Rng1U64 range = task->ranges[task_id]; U64 bucket_cursor = task->udt_offsets[task_id]; CV_DebugT debug_t = task->debug_t; PDB_TypeBucket *new_buckets = task->udt_buckets; U64 type_ht_cap = type_server->bucket_cap; PDB_TypeBucket **type_ht_buckets = type_server->buckets; U64 base_type_index = type_server->ti_lo + type_server->leaf_list.node_count; for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) { CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx); if (cv_is_udt(leaf.kind)) { CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data); if (~udt_info.props & CV_TypeProp_FwdRef) { // hash udt and compute bucket index U32 hash = pdb_hash_udt(udt_info, leaf.data); U32 bucket_idx = hash % type_ht_cap; // fill out & insert bucket PDB_TypeBucket *bucket = &new_buckets[bucket_cursor++]; bucket->raw_leaf = cv_debug_t_get_raw_leaf(debug_t, leaf_idx); bucket->type_index = base_type_index + leaf_idx; bucket->next = ins_atomic_ptr_eval_assign(&type_ht_buckets[bucket_idx], bucket); } } } } internal void pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *type_server, CV_DebugT debug_t) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); PDB_PushLeafTask task = {0}; task.debug_t = debug_t; task.type_server = type_server; task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count); ProfBegin("Count UDT"); task.udt_counts = push_array(scratch.arena, U64, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, pdb_count_udt_task, &task); ProfEnd(); ProfBegin("Push UDT Leaves"); U64 total_udt_count = sum_array_u64(tp->worker_count, task.udt_counts); task.udt_offsets = offsets_from_counts_array_u64(scratch.arena, task.udt_counts, tp->worker_count); task.udt_buckets = push_array_no_zero(type_server->arena, PDB_TypeBucket, total_udt_count); tp_for_parallel(tp, 0, tp->worker_count, pdb_push_udt_leaf_task, &task); ProfEnd(); ProfBegin("Append New Leaves"); String8List new_leaves = cv_str8_list_from_debug_t_parallel(tp, type_server->arena, debug_t); str8_list_concat_in_place(&type_server->leaf_list, &new_leaves); ProfEnd(); scratch_end(scratch); ProfEnd(); } #if 0 internal CV_LeafNode * pdb_type_server_leaf_from_string(PDB_TypeServer *ts, String8 string) { ProfBeginFunction(); U32 hash = pdb_hash_v1(string); U32 bucket_idx = hash % ts->bucket_count; PDB_TypeBucket *head_bucket = ts->bucket_table[bucket_idx]; CV_LeafNode *result = 0; for (PDB_TypeBucket *i = head_bucket; i != 0; i = i->next) { CV_LeafNode *leaf = i->leaf_node; String8 leaf_name = cv_get_leaf_name(leaf->data.kind, leaf->data.data); if (str8_match(leaf_name, string, 0)) { result = leaf; break; } } ProfEnd(); return result; } #endif //////////////////////////////// #if 0 internal PDB_TypeIndexMap * pdb_load_types_from_leaf_list(PDB_TypeServer **type_server_arr, CV_LeafList leaf_list) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); // 1. redistribute leaves in parallel CV_LeafList leaf_list_arr[CV_TypeIndexSource_COUNT] = {0}; for (CV_LeafNode *curr = leaf_list.first, *next = 0; curr != 0; curr = next) { next = curr->next; curr->next = 0; CV_TypeIndexSource ti_source = cv_type_index_source_from_leaf_kind(curr->data.kind); CV_LeafList *list = &leaf_list_arr[ti_source]; SLLQueuePush(list->first, list->last, curr); list->count += 1; } // 2. reserve type leafs on main thread PDB_TypeLeaf *leaf_arr_arr[CV_TypeIndexSource_COUNT]; for (U64 source_idx = 0; source_idx < ArrayCount(leaf_list_arr); source_idx += 1) { PDB_TypeServer *type_server = type_server_arr[source_idx]; CV_LeafList input_leaf_list = leaf_list_arr[source_idx]; PDB_TypeLeaf *leaf_arr = pdb_type_server_reserve(type_server, input_leaf_list.count); leaf_arr_arr[source_idx] = leaf_arr; } // 3. populate type index map in parallel PDB_TypeIndexMap *ti_map = pdb_type_index_map_alloc(); for (U64 source_idx = 0; source_idx < ArrayCount(leaf_list_arr); source_idx += 1) { CV_LeafList input_leaf_list = leaf_list_arr[source_idx]; PDB_TypeLeaf *leaf_arr = leaf_arr_arr[source_idx]; for (U64 leaf_idx = 0; leaf_idx < input_leaf_list.count; leaf_idx += 1) { CV_TypeIndex external_ti = ti_map->min_itype[source_idx] + leaf_idx; CV_TypeIndex internal_ti = leaf_arr[leaf_idx].type_index; pdb_type_index_map_add(ti_map, (CV_TypeIndexSource)source_idx, external_ti, internal_ti); } } // 4. patch type indices in parallel for (U64 source_idx = 0; source_idx < ArrayCount(leaf_list_arr); source_idx += 1) { CV_LeafList list = leaf_list_arr[source_idx]; for (CV_LeafNode *node = list.first; node != 0; node = node->next) { Temp temp = temp_begin(scratch.arena); // get offsets for type indices in data blob CV_Leaf *leaf = &node->data; CV_TypeIndexInfoList ti_info_list = cv_get_leaf_type_index_offsets(temp.arena, leaf->kind, leaf->data); for (CV_TypeIndexInfo *ti_info = ti_info_list.first; ti_info != 0; ti_info = ti_info->next) { Assert(ti_info->offset + sizeof(CV_TypeIndex) <= leaf->data.size); CV_TypeIndex *ti_ptr = (CV_TypeIndex *)(leaf->data.str + ti_info->offset); CV_TypeIndex external_ti = *ti_ptr; B32 is_complex_type = external_ti >= ti_map->min_itype[ti_info->source]; if (is_complex_type) { // search external type index CV_TypeIndex internal_tpi_idx = pdb_type_index_map_search(ti_map, CV_TypeIndexSource_TPI, external_ti); CV_TypeIndex internal_ipi_idx = pdb_type_index_map_search(ti_map, CV_TypeIndexSource_IPI, external_ti); // error checks if (internal_tpi_idx == 0 && internal_ipi_idx == 0) { lnk_invalid_path("unable to find match for external type index 0x%X", external_ti); continue; } if (internal_tpi_idx != 0 && internal_ipi_idx != 0) { lnk_invalid_path("both TPI and IPI matched for external type index 0x%X", external_ti); continue; } // rewrite index CV_TypeIndex internal_ti = internal_tpi_idx ? internal_tpi_idx : internal_ipi_idx; *ti_ptr = internal_ti; } } temp_end(temp); } } // 5. push types to hash table on main thread for (U64 source_idx = 0; source_idx < ArrayCount(leaf_list_arr); source_idx += 1) { PDB_TypeServer *type_server = type_server_arr[source_idx]; CV_LeafList list = leaf_list_arr[source_idx]; PDB_TypeLeaf *leaf_arr = leaf_arr_arr[source_idx]; U64 leaf_idx = 0; for (CV_LeafNode *node = list.first; node != 0; node = node->next, leaf_idx += 1) { CV_Leaf *external_leaf = &node->data; // move patched type data PDB_TypeLeaf *internal_leaf = leaf_arr + leaf_idx; internal_leaf->kind = external_leaf->kind; internal_leaf->data = push_str8_copy(type_server->arena, external_leaf->data); // push leaf to type server pdb_type_server_push_(type_server, internal_leaf); } } scratch_end(scratch); ProfEnd(); return ti_map; } #endif //////////////////////////////// internal PDB_InfoContext * pdb_info_alloc(U32 age, COFF_TimeStamp time_stamp, Guid guid) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_InfoContext *info = push_array(arena, PDB_InfoContext, 1); info->arena = arena; info->flags = PDB_FeatureFlag_HAS_ID_STREAM; info->time_stamp = time_stamp; info->age = age; info->guid = guid; pdb_strtab_alloc(&info->strtab, 0x3fff); pdb_hash_table_alloc(&info->named_stream_ht, 4); pdb_hash_table_alloc(&info->src_header_block_ht, 8); ProfEnd(); return info; } internal void pdb_info_parse_from_data(String8 data, PDB_InfoParse *parse_out) { PDB_InfoVersion version = 0; str8_deserial_read_struct(data, 0, &version); switch (version) { case PDB_InfoVersion_VC70: { U64 cursor = 0; // read header PDB_InfoHeaderV70 header; cursor += str8_deserial_read_struct(data, cursor, &header); parse_out->version = version; parse_out->time_stamp = header.time_stamp; parse_out->age = header.age; parse_out->guid = header.guid; parse_out->extra_info = str8_skip(data, cursor); } break; case PDB_InfoVersion_VC2: case PDB_InfoVersion_VC4: case PDB_InfoVersion_VC41: case PDB_InfoVersion_VC50: case PDB_InfoVersion_VC98: case PDB_InfoVersion_VC70_DEP: case PDB_InfoVersion_VC80: case PDB_InfoVersion_VC110: case PDB_InfoVersion_VC140: { NotImplemented; } break; default: Assert(!"invalid info stream version"); break; } } internal PDB_InfoContext * pdb_info_open(MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); U64 info_size = msf_stream_get_size(msf, sn); String8 info_data = msf_stream_read_block(scratch.arena, msf, sn, info_size); PDB_InfoParse parse = {0}; pdb_info_parse_from_data(info_data, &parse); PDB_FeatureFlags flags = 0; PDB_HashTable named_stream_ht = {0}; if (parse.version == PDB_InfoVersion_VC70) { // open named stream hash table U64 cursor = 0; U64 named_stream_ht_size = 0; PDB_HashTableParseError named_stream_ht_error = pdb_named_stream_ht_from_data(&named_stream_ht, parse.extra_info, &named_stream_ht_size); if (named_stream_ht_error == PDB_HashTableParseError_OK) { cursor += named_stream_ht_size; // read PDB features while (cursor < info_data.size) { PDB_FeatureSig sig = 0; cursor += str8_deserial_read_struct(parse.extra_info, cursor, &sig); switch (sig) { case PDB_FeatureSig_NULL: break; case PDB_FeatureSig_VC140: { flags |= PDB_FeatureFlag_HAS_ID_STREAM; } break; case PDB_FeatureSig_NO_TYPE_MERGE: { flags |= PDB_FeatureFlag_NO_TYPE_MERGE; } break; case PDB_FeatureSig_MINIMAL_DEBUG_INFO: { flags |= PDB_FeatureFlag_MINIMAL_DBG_INFO; } break; default: Assert(!"unknown feature sig"); break; } } } else { Assert(!"unable to open named stream hash table"); } } // open string table PDB_StringTable strtab = {0}; MSF_StreamNumber strtab_sn = pdb_find_named_stream(&named_stream_ht, PDB_NAMES_STREAM_NAME); if (strtab_sn != MSF_INVALID_STREAM_NUMBER) { PDB_StringTableOpenError err = pdb_strtab_open(&strtab, msf, strtab_sn); Assert(err == PDB_StringTableOpenError_OK); } // open injected source files PDB_HashTable src_header_block_ht = {0}; MSF_StreamNumber src_header_block_sn = pdb_find_named_stream(&named_stream_ht, PDB_SRC_HEADER_BLOCK_STREAM_NAME); if (src_header_block_sn != MSF_INVALID_STREAM_NUMBER) { U64 src_header_block_stream_size = msf_stream_get_size(msf, src_header_block_sn); String8 src_header_block_data = msf_stream_read_block(scratch.arena, msf, src_header_block_sn, src_header_block_stream_size); PDB_HashTableParseError err = pdb_src_header_block_ht_from_data(&src_header_block_ht, src_header_block_data, &strtab, 0); Assert(err == PDB_HashTableParseError_OK); } // fill out info Arena *arena = arena_alloc(); PDB_InfoContext *info = push_array_no_zero(arena, PDB_InfoContext, 1); info->arena = arena; info->time_stamp = parse.time_stamp; info->age = parse.age; info->guid = parse.guid; info->flags = flags; info->named_stream_ht = named_stream_ht; info->src_header_block_ht = src_header_block_ht; info->strtab = strtab; scratch_end(scratch); ProfEnd(); return info; } internal void pdb_info_build_src_header_block(PDB_InfoContext *info, MSF_Context *msf) { Temp scratch = scratch_begin(0,0); // was stream allocated? MSF_StreamNumber src_header_block_sn = pdb_find_named_stream(&info->named_stream_ht, PDB_SRC_HEADER_BLOCK_STREAM_NAME); if (src_header_block_sn == MSF_INVALID_STREAM_NUMBER) { src_header_block_sn = pdb_push_named_stream(&info->named_stream_ht, msf, PDB_SRC_HEADER_BLOCK_STREAM_NAME); } // build the hash table String8 hash_table_data = pdb_data_from_src_header_block_ht(scratch.arena, &info->src_header_block_ht, &info->strtab); AssertAlways(hash_table_data.size); // compute stream size U64 src_header_stream_size = 0; src_header_stream_size += sizeof(PDB_SrcHeaderBlockHeader); src_header_stream_size += hash_table_data.size; // fill out header PDB_SrcHeaderBlockHeader src_header; src_header.version = PDB_SRC_HEADER_BLOCK_MAGIC_V1; src_header.stream_size = src_header_stream_size; src_header.file_time = 0; src_header.age = 0; MemoryZeroStruct(&src_header.pad); // write to stream B32 is_header_written = msf_stream_write_struct(msf, src_header_block_sn, &src_header); B32 is_hash_table_written = msf_stream_write_string(msf, src_header_block_sn, hash_table_data); AssertAlways(is_header_written); AssertAlways(is_hash_table_written); AssertAlways(msf_stream_get_size(msf, src_header_block_sn) == src_header.stream_size); scratch_end(scratch); } internal void pdb_info_build_link_info(PDB_InfoContext *info, MSF_Context *msf) { MSF_StreamNumber linkinfo_sn = pdb_find_named_stream(&info->named_stream_ht, PDB_LINK_INFO_STREAM_NAME); if (linkinfo_sn == MSF_INVALID_STREAM_NUMBER) { linkinfo_sn = pdb_push_named_stream(&info->named_stream_ht, msf, PDB_LINK_INFO_STREAM_NAME); } // TODO: populate LINKINFO } internal void pdb_info_build_names(PDB_InfoContext *info, MSF_Context *msf) { MSF_StreamNumber strtab_sn = pdb_find_named_stream(&info->named_stream_ht, PDB_NAMES_STREAM_NAME); if (strtab_sn == MSF_INVALID_STREAM_NUMBER) { strtab_sn = pdb_push_named_stream(&info->named_stream_ht, msf, PDB_NAMES_STREAM_NAME); } pdb_strtab_build(&info->strtab, msf, strtab_sn); } internal void pdb_info_build(PDB_InfoContext *info, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); // finalize named streams pdb_info_build_src_header_block(info, msf); pdb_info_build_link_info(info, msf); pdb_info_build_names(info, msf); // serialize named streams hash table String8 named_stream_ht_data = pdb_data_from_named_stream_ht(scratch.arena, &info->named_stream_ht); // fill out header PDB_InfoHeaderV70 header; header.version = PDB_InfoVersion_VC70; header.time_stamp = info->time_stamp; header.age = info->age; header.guid = info->guid; // layout info stream String8List info_srl = {0}; str8_serial_begin(scratch.arena, &info_srl); str8_serial_push_struct(scratch.arena, &info_srl, &header); str8_serial_push_string(scratch.arena, &info_srl, named_stream_ht_data); if (info->flags & PDB_FeatureFlag_HAS_ID_STREAM) { str8_serial_push_u32(scratch.arena, &info_srl, PDB_FeatureSig_VC140); } if (info->flags & PDB_FeatureFlag_NO_TYPE_MERGE) { str8_serial_push_u32(scratch.arena, &info_srl, PDB_FeatureSig_NO_TYPE_MERGE); } if (info->flags & PDB_FeatureFlag_MINIMAL_DBG_INFO) { str8_serial_push_u32(scratch.arena, &info_srl, PDB_FeatureSig_MINIMAL_DEBUG_INFO); } // write info to MSF msf_stream_seek_start(msf, sn); msf_stream_resize(msf, sn, info_srl.total_size); msf_stream_write_list(msf, sn, info_srl); scratch_end(scratch); ProfEnd(); } internal void pdb_info_release(PDB_InfoContext **info_ptr) { ProfBeginFunction(); arena_release((*info_ptr)->arena); *info_ptr = NULL; ProfEnd(); } internal MSF_StreamNumber pdb_push_named_stream(PDB_HashTable *named_stream_ht, MSF_Context *msf, String8 name) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); MSF_StreamNumber sn = msf_stream_alloc(msf); String8 name_cstr = push_cstr(scratch.arena, name); U32 sn32 = (U32)sn; pdb_hash_table_set(named_stream_ht, name_cstr, str8_struct(&sn32)); scratch_end(scratch); ProfEnd(); return sn; } internal MSF_StreamNumber pdb_find_named_stream(PDB_HashTable *named_stream_ht, String8 name) { ProfBeginFunction(); MSF_StreamNumber result = MSF_INVALID_STREAM_NUMBER; String8 value; if (pdb_hash_table_get(named_stream_ht, name, &value)) { Assert(value.size == sizeof(U32)); result = *(MSF_StreamNumber*)value.str; } ProfEnd(); return result; } internal PDB_SrcError pdb_add_src(PDB_InfoContext *info, MSF_Context *msf, String8 file_path, String8 file_data, PDB_SrcCompType comp) { Temp scratch = scratch_begin(0,0); PDB_SrcError error_status = PDB_SrcError_UNKNOWN; if (comp == PDB_SrcComp_NULL) { // process path so it passes VS validity checks String8 virt_path = file_path; String8 work_dir = os_get_current_path(scratch.arena); virt_path = path_absolute_dst_from_relative_dst_src(scratch.arena, virt_path, work_dir); virt_path = lower_from_str8(scratch.arena, virt_path); virt_path = path_convert_slashes(scratch.arena, virt_path, PathStyle_UnixAbsolute); String8 dummy_value; B32 is_virt_path_present = pdb_hash_table_get(&info->src_header_block_ht, virt_path, &dummy_value); if (!is_virt_path_present) { String8 stream_name = push_str8f(scratch.arena, "/src/files/%S", virt_path); MSF_StreamNumber sn = pdb_find_named_stream(&info->named_stream_ht, stream_name); B32 is_name_free = (sn == MSF_INVALID_STREAM_NUMBER); if (is_name_free) { sn = pdb_push_named_stream(&info->named_stream_ht, msf, stream_name); B32 is_file_data_written = msf_stream_write_string(msf, sn, file_data); if (is_file_data_written) { // add command line path PDB_StringIndex file_path_stridx; if (!pdb_strtab_search(&info->strtab, file_path, &file_path_stridx)) { file_path_stridx = pdb_strtab_add(&info->strtab, file_path); } // add virtual path PDB_StringIndex virt_path_stridx; if (!pdb_strtab_search(&info->strtab, virt_path, &virt_path_stridx)) { virt_path_stridx = pdb_strtab_add(&info->strtab, virt_path); } // string indices -> offsets PDB_StringOffset file_path_stroff = pdb_strtab_string_to_offset(&info->strtab, file_path_stridx); PDB_StringOffset virt_path_stroff = pdb_strtab_string_to_offset(&info->strtab, virt_path_stridx); // fill out entry PDB_SrcHeaderBlockEntry entry; entry.size = sizeof(entry); entry.version = PDB_SRC_HEADER_BLOCK_MAGIC_V1; entry.file_crc = pdb_crc32_from_string(file_data); entry.file_size = file_data.size; entry.file_path = file_path_stroff; entry.obj = 0; // null string offset entry.virt_path = virt_path_stroff; entry.comp = comp; entry.flags = 0; MemorySet(&entry.pad[0], 0, sizeof(entry.pad)); MemorySet(&entry.reserved[0], 0, sizeof(entry.reserved)); // add to hash table { path, entry } String8 key = virt_path; String8 val = str8_struct(&entry); pdb_hash_table_set(&info->src_header_block_ht, key, val); error_status = PDB_SrcError_OK; } else { error_status = PDB_SrcError_UNABLE_TO_WRITE_DATA; } } else { error_status = PDB_SrcError_DUPLICATE_NAME_STREAM; } } else { error_status = PDB_SrcError_DUPLICATE_ENTRY; } } else { error_status = PDB_SrcError_UNSUPPORTED_COMPRESSION; } scratch_end(scratch); return error_status; } //////////////////////////////// internal PDB_GsiContext * gsi_alloc(void) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_GsiContext *gsi = push_array(arena, PDB_GsiContext, 1); gsi->arena = arena; gsi->word_size = PDB_GSI_V70_WORD_SIZE; gsi->symbol_align = PDB_GSI_V70_SYMBOL_ALIGN; gsi->bucket_count = PDB_GSI_V70_BUCKET_COUNT; gsi->bucket_arr = push_array(arena, CV_SymbolList, gsi->bucket_count); ProfEnd(); return gsi; } internal PDB_GsiContext * gsi_open(MSF_Context *msf, MSF_StreamNumber sn, String8 symbol_data) { ProfBeginFunction(); PDB_GsiHeader header = {0}; msf_stream_read_struct(msf, sn, &header); Arena *arena = arena_alloc(); PDB_GsiContext *gsi = push_array(arena, PDB_GsiContext, 1); gsi->arena = arena; gsi->word_size = PDB_GSI_V70_WORD_SIZE; gsi->symbol_align = PDB_GSI_V70_SYMBOL_ALIGN; gsi->bucket_count = PDB_GSI_V70_BUCKET_COUNT; gsi->bucket_arr = push_array(gsi->arena, CV_SymbolList, gsi->bucket_count); if (header.signature == PDB_GsiSignature_Basic) { if (header.version == PDB_GsiVersion_V70) { Temp scratch = scratch_begin(0, 0); Assert(header.bucket_data_size >= PDB_GSI_V70_BITMAP_SIZE); // TODO: error handle U64 hash_record_count = header.hash_record_arr_size / sizeof(PDB_GsiHashRecord); PDB_GsiHashRecord *hash_record_array = push_array(scratch.arena, PDB_GsiHashRecord, hash_record_count); msf_stream_read_array(msf, sn, &hash_record_array[0], hash_record_count); U32 *bitmap = push_array(scratch.arena, U32, PDB_GSI_V70_BITMAP_COUNT); msf_stream_read_array(msf, sn, &bitmap[0], PDB_GSI_V70_BITMAP_COUNT); U32 compressed_offset_count = (header.bucket_data_size - PDB_GSI_V70_BITMAP_SIZE) / sizeof(U32); U32 *compressed_offset_array = push_array(scratch.arena, U32, compressed_offset_count); msf_stream_read_array(msf, sn, &compressed_offset_array[0], compressed_offset_count); U32 *compressed_offset_ptr = &compressed_offset_array[0]; U32 *compressed_offset_opl = &compressed_offset_array[0] + compressed_offset_count; U32 compressed_offset_max = (header.bucket_data_size / sizeof(PDB_GsiHashRecord)) * sizeof(PDB_GsiHashRecordOffsetCalc); for (U32 imask = 0; imask < PDB_GSI_V70_BITMAP_COUNT; imask += 1) { for (U32 ibit = 0; ibit < PDB_GSI_V70_WORD_SIZE; ibit += 1) { B32 is_bucket_compressed = !!(bitmap[imask] & (1 << ibit)); if (is_bucket_compressed) { Assert(compressed_offset_ptr < compressed_offset_opl); U32 next_compressed_offset = compressed_offset_max; if (compressed_offset_ptr + 1 < compressed_offset_opl) { next_compressed_offset = compressed_offset_ptr[1]; } U32 compressed_count = (next_compressed_offset - *compressed_offset_ptr) / sizeof(PDB_GsiHashRecordOffsetCalc); U64 hash_record_index = *compressed_offset_ptr / sizeof(PDB_GsiHashRecordOffsetCalc); Assert(hash_record_index < hash_record_count); for (PDB_GsiHashRecord *hash_record_ptr = &hash_record_array[hash_record_index], *hash_record_opl = hash_record_ptr + compressed_count; hash_record_ptr < hash_record_opl; hash_record_ptr += 1) { Assert(hash_record_ptr->symbol_off > 0); Assert(hash_record_ptr->cref > 0); U32 symbol_off = hash_record_ptr->symbol_off -1; U8 *symbol_ptr = symbol_data.str + symbol_off; U16 *size_ptr = (U16*)symbol_ptr; CV_SymKind *kind_ptr = (CV_SymKind*)(size_ptr + 1); U8 *data_ptr = (U8*)(kind_ptr + 1); if (*size_ptr >= sizeof(*kind_ptr)) { CV_Symbol symbol; symbol.kind = *kind_ptr; symbol.data = str8(data_ptr, *size_ptr - sizeof(*kind_ptr)); gsi_push(gsi, &symbol); } else { Assert(!"invalid global codeview symbol"); } } compressed_offset_ptr += 1; } } } scratch_end(scratch); } else { Assert(!"unknown GSI version"); } } // check if buckets are sorted #if 0 { for (U64 i = 0; i < gsi->bucket_count; ++i) { CV_SymbolList *bucket = &gsi->bucket_arr[i]; for (CV_SymbolNode *prev = bucket->first, *curr = bucket->first ? bucket->first->next : NULL; curr != NULL; prev = curr, curr = curr->next) { String8 a = pdb_get_symbol_name(prev->symbol.kind, prev->symbol.data); String8 b = pdb_get_symbol_name(curr->symbol.kind, curr->symbol.data); int compar = string_compar(a, b, false); Assert(compar >= 0); } } } #endif ProfEnd(); return gsi; } internal void gsi_release(PDB_GsiContext **gsi_ptr) { ProfBeginFunction(); arena_release((*gsi_ptr)->arena); *gsi_ptr = NULL; ProfEnd(); } internal void gsi_write_build_result(TP_Context *tp, PDB_GsiBuildResult build, MSF_Context *msf, MSF_StreamNumber gsi_sn, MSF_StreamNumber symbols_sn) { ProfBeginFunction(); U64 hash_record_arr_size = sizeof(build.hash_record_arr[0]) * build.hash_record_count; U64 bitmap_size = sizeof(build.bitmap[0]) * build.bitmap_count; U64 compressed_bucket_arr_size = sizeof(build.compressed_bucket_arr[0]) * build.compressed_bucket_count; U64 gsi_size = sizeof(build.header) + hash_record_arr_size + bitmap_size + compressed_bucket_arr_size; ProfBeginV("Reserve %M for GSI hash table", gsi_size); msf_stream_reserve(msf, gsi_sn, gsi_size); ProfEnd(); ProfBeginV("Reserve %M for symbols", build.symbol_data.size); msf_stream_reserve(msf, symbols_sn, build.symbol_data.size); ProfEnd(); ProfBegin("Write GSI header"); msf_stream_write_struct(msf, gsi_sn, &build.header); ProfEnd(); ProfBegin("Write hash records [%M]", hash_record_arr_size); msf_stream_write_parallel(tp, msf, gsi_sn, &build.hash_record_arr[0], hash_record_arr_size); ProfEnd(); ProfBeginV("Write bucket bitmap [%M]", bitmap_size); msf_stream_write(msf, gsi_sn, &build.bitmap[0], bitmap_size); ProfEnd(); ProfBegin("Write buckets [%M]", compressed_bucket_arr_size); msf_stream_write(msf, gsi_sn, &build.compressed_bucket_arr[0], compressed_bucket_arr_size); ProfEnd(); ProfBegin("Write symbols [%M]", build.symbol_data.size); msf_stream_write_string_parallel(tp, msf, symbols_sn, build.symbol_data); ProfEnd(); ProfEnd(); } internal int gsi_hash_record_compar_is_before(void *raw_a, void *raw_b) { PDB_GsiSortRecord *a = raw_a; PDB_GsiSortRecord *b = raw_b; int is_before; if (a->name.size != b->name.size) { is_before = a->name.size < b->name.size; } else { int cmp = str8_compar_ignore_case(&a->name, &b->name); if (cmp == 0) { cmp = u64_compar(&a->offset, &b->offset); } is_before = cmp < 0; } return is_before; } internal int psi_addr_map_compar_is_before(void *raw_a, void *raw_b) { PDB_GsiSortRecord *a = raw_a; PDB_GsiSortRecord *b = raw_b; int is_before; if (a->isect_off.isect != b->isect_off.isect) { is_before = a->isect_off.isect < b->isect_off.isect; } else if (a->isect_off.off != b->isect_off.off) { is_before = a->isect_off.off < b->isect_off.off; } else { is_before = str8_compar_case_sensitive(&a->name, &b->name); } return is_before; } internal void gsi_record_sort_by_name(PDB_GsiSortRecord *arr, U64 count) { ProfBeginFunction(); radsort(arr, count, gsi_hash_record_compar_is_before); ProfEnd(); } internal void gsi_record_sort_by_sc(PDB_GsiSortRecord *arr, U64 count) { ProfBeginFunction(); radsort(arr, count, psi_addr_map_compar_is_before); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(gsi_size_buckets_task) { U64 bucket_idx = task_id; PDB_GsiSerializeSymbolsTask *task = raw_task; CV_SymbolList *bucket_list = &task->bucket_arr[bucket_idx]; for (CV_SymbolNode *node = bucket_list->first; node != 0; node = node->next) { task->bucket_size_arr[bucket_idx] += cv_compute_symbol_record_size(&node->data, task->symbol_align); } } internal THREAD_POOL_TASK_FUNC(gsi_serialize_pub32) { U64 bucket_idx = task_id; PDB_GsiSerializeSymbolsTask *task = raw_task; CV_SymbolList bucket_list = task->bucket_arr[bucket_idx]; PDB_GsiSortRecord *sort_record_arr = task->sort_record_arr_arr[bucket_idx]; U64 buffer_size = task->bucket_size_arr[bucket_idx]; U64 buffer_base = task->bucket_off_arr[bucket_idx]; U8 *buffer = task->buffer + buffer_base; U64 sort_idx = 0; U64 buffer_cursor = 0; for (CV_SymbolNode *node = bucket_list.first; node != 0; node = node->next) { CV_Symbol *symbol = &node->data; Assert(symbol->kind == CV_SymKind_PUB32); CV_SymPub32 *pub32 = (CV_SymPub32 *)symbol->data.str; U8 *str_ptr = (U8 *)(pub32 + 1); U64 str_size = symbol->data.size - sizeof(*pub32); String8 name = str8(str_ptr, str_size); // init sort record PDB_GsiSortRecord *sr = &sort_record_arr[sort_idx]; sr->isect_off = isect_off(pub32->sec, pub32->off); sr->name = name; sr->offset = buffer_cursor; // serialize symbol U64 serial_size = cv_serialize_symbol_to_buffer(buffer, buffer_cursor, buffer_size, symbol, task->symbol_align); // advance sort_idx += 1; buffer_cursor += serial_size; } Assert(sort_idx == bucket_list.count); Assert(buffer_cursor == buffer_size); // sort symbols by name within bucket gsi_record_sort_by_name(sort_record_arr, bucket_list.count); } internal THREAD_POOL_TASK_FUNC(gsi_serialize_symbols_task) { U64 bucket_idx = task_id; PDB_GsiSerializeSymbolsTask *task = raw_task; CV_SymbolList bucket_list = task->bucket_arr[bucket_idx]; PDB_GsiSortRecord *sort_record_arr = task->sort_record_arr_arr[bucket_idx]; U64 buffer_size = task->bucket_size_arr[bucket_idx]; U64 buffer_base = task->bucket_off_arr[bucket_idx]; U8 *buffer = task->buffer + buffer_base; U64 sort_idx = 0; U64 buffer_cursor = 0; for (CV_SymbolNode *node = bucket_list.first; node != 0; node = node->next) { CV_Symbol *symbol = &node->data; // init sort record PDB_GsiSortRecord *sr = &sort_record_arr[sort_idx]; //sr->isect_off = isect_off(0,0); sr->name = cv_name_from_symbol(symbol->kind, symbol->data); sr->offset = buffer_cursor; // serialize symbol U64 serial_size = cv_serialize_symbol_to_buffer(buffer, buffer_cursor, buffer_size, symbol, task->symbol_align); // advance sort_idx += 1; buffer_cursor += serial_size; } Assert(sort_idx == bucket_list.count); Assert(buffer_cursor == buffer_size); // sort symbols by name within bucket gsi_record_sort_by_name(sort_record_arr, bucket_list.count); } internal PDB_GsiBuildResult gsi_build_ex(TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 symbol_data_base, B32 is_pub32, U64 msf_page_size) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena,1); ProfBegin("Serialize & Sort Symbols"); PDB_GsiSerializeSymbolsTask serial_task; serial_task.symbol_align = gsi->symbol_align; serial_task.bucket_arr = gsi->bucket_arr; serial_task.bucket_size_arr = push_array(scratch.arena, U64, gsi->bucket_count); // estimate each bucket size tp_for_parallel(tp, 0, gsi->bucket_count, gsi_size_buckets_task, &serial_task); // prepare serial buffer U64 buffer_size = sum_array_u64(gsi->bucket_count, serial_task.bucket_size_arr); serial_task.buffer = push_array_no_zero(arena, U8, buffer_size); serial_task.bucket_off_arr = push_array_copy_u64(scratch.arena, serial_task.bucket_size_arr, gsi->bucket_count); counts_to_offsets_array_u64(gsi->bucket_count, serial_task.bucket_off_arr); // prepare GSI records serial_task.sort_record_arr_arr = push_array_no_zero(scratch.arena, PDB_GsiSortRecord *, gsi->bucket_count); serial_task.sort_record_arr = push_array_no_zero(arena, PDB_GsiSortRecord, gsi->symbol_count); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < gsi->bucket_count; bucket_idx += 1) { serial_task.sort_record_arr_arr[bucket_idx] = serial_task.sort_record_arr + cursor; cursor += gsi->bucket_arr[bucket_idx].count; } // fill out sort records & serialize symbols TP_TaskFunc *serial_func = is_pub32 ? gsi_serialize_pub32 : gsi_serialize_symbols_task; tp_for_parallel(tp, 0, gsi->bucket_count, serial_func, &serial_task); ProfEnd(); U64 bitmap_count = (gsi->bucket_count / gsi->word_size) + 1; // ms-pdb allocates extra bucket and funnels free buckets there U64 compressed_offset_count = 0; U64 hash_record_count = gsi->symbol_count; U32 *bitmap = push_array(arena, U32, bitmap_count); U32 *compressed_offset_arr = push_array_no_zero(arena, U32, gsi->bucket_count); PDB_GsiHashRecord *hash_record_arr = push_array_no_zero(arena, PDB_GsiHashRecord, hash_record_count); // offsets for symbol stream are shifted by one to tell apart from null and zero (see GSI1::fixSymRecs) U64 offset_cursor = (1 + symbol_data_base); U64 hash_idx = 0; ProfBegin("Write Bitmap & Record Offsets"); for (U64 bucket_idx = 0; bucket_idx < gsi->bucket_count; bucket_idx += 1) { // set bit for each occupied bucket CV_SymbolList bucket_list = gsi->bucket_arr[bucket_idx]; if (bucket_list.count) { U64 word_idx = bucket_idx / gsi->word_size; Assert(word_idx < bitmap_count); bitmap[word_idx] |= 1 << (bucket_idx % gsi->word_size); compressed_offset_arr[compressed_offset_count] = hash_idx * sizeof(PDB_GsiHashRecordOffsetCalc); // store in-memory offset for first bucket compressed_offset_count += 1; } // write out sorted hash records PDB_GsiSortRecord *sort_record_arr = serial_task.sort_record_arr_arr[bucket_idx]; for (U64 sr_idx = 0; sr_idx < gsi->bucket_arr[bucket_idx].count; sr_idx += 1, hash_idx += 1) { PDB_GsiHashRecord *hr = &hash_record_arr[hash_idx]; hr->symbol_off = offset_cursor + sort_record_arr[sr_idx].offset; hr->cref = 1; } // advance offset cursor offset_cursor += serial_task.bucket_size_arr[bucket_idx]; } ProfEnd(); // fill out header PDB_GsiHeader header; header.signature = PDB_GsiSignature_Basic; header.version = PDB_GsiVersion_V70; header.hash_record_arr_size = sizeof(hash_record_arr[0]) * hash_record_count; header.bucket_data_size = sizeof(bitmap[0]) * bitmap_count + sizeof(compressed_offset_arr[0]) * compressed_offset_count; // fill out result PDB_GsiBuildResult result; result.header = header; result.hash_record_count = hash_record_count; result.hash_record_arr = hash_record_arr; result.sort_record_arr = serial_task.sort_record_arr; result.bitmap_count = bitmap_count; result.bitmap = bitmap; result.compressed_bucket_count = compressed_offset_count; result.compressed_bucket_arr = compressed_offset_arr; result.total_hash_size = sizeof(header) + header.hash_record_arr_size + header.bucket_data_size; result.symbol_data = str8(serial_task.buffer, buffer_size); scratch_end(scratch); ProfEnd(); return result; } internal void gsi_build(TP_Context *tp, PDB_GsiContext *gsi, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); U64 symbol_data_base = msf_stream_get_pos(msf, symbols_sn); PDB_GsiBuildResult build = gsi_build_ex(tp, scratch.arena, gsi, symbol_data_base, /* is_pub32: */ 0, msf->page_size); gsi_write_build_result(tp, build, msf, sn, symbols_sn); scratch_end(scratch); ProfEnd(); } internal U32 gsi_hash(PDB_GsiContext *gsi, String8 input) { (void)gsi; U32 hash = pdb_hash_v1(input); return hash; } internal void gsi_push_(PDB_GsiContext *gsi, U32 hash, CV_SymbolNode *node) { U64 bucket_idx = hash % gsi->bucket_count; CV_SymbolList *list = &gsi->bucket_arr[bucket_idx]; cv_symbol_list_push_node(list, node); gsi->symbol_count += 1; } internal CV_SymbolNode * gsi_push(PDB_GsiContext *gsi, CV_Symbol *symbol) { String8 name = cv_name_from_symbol(symbol->kind, symbol->data); U32 hash = gsi_hash(gsi, name); CV_SymbolNode *node = push_array_no_zero(gsi->arena, CV_SymbolNode, 1); node->next = 0; node->prev = 0; node->data = *symbol; gsi_push_(gsi, hash, node); return node; } internal THREAD_POOL_TASK_FUNC(gsi_symbol_hasher_task) { ProfBeginFunction(); GSI_SymbolHasherTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) { CV_SymbolNode *symbol = task->symbols[symbol_idx]; String8 name = cv_name_from_symbol(symbol->data.kind, symbol->data.data); task->hashes[symbol_idx] = gsi_hash(task->gsi, name); } ProfEnd(); } internal void gsi_push_many_arr(TP_Context *tp, PDB_GsiContext *gsi, U64 count, CV_SymbolNode **symbols) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); ProfBegin("Hash UDT Names"); GSI_SymbolHasherTask task = {0}; task.gsi = gsi; task.ranges = tp_divide_work(scratch.arena, count, tp->worker_count); task.symbols = symbols; task.hashes = push_array_no_zero(scratch.arena, U32, count); tp_for_parallel(tp, 0, tp->worker_count, gsi_symbol_hasher_task, &task); ProfEnd(); for (U64 i = 0; i < count; ++i) { gsi_push_(gsi, task.hashes[i], symbols[i]); } scratch_end(scratch); ProfEnd(); } internal void gsi_push_many_list(PDB_GsiContext *gsi, U64 count, U32 *hash_arr, CV_SymbolList *list) { Assert(count == list->count); U64 hash_idx = 0; for (CV_SymbolNode *curr = list->first, *next = 0; curr != 0; curr = next, ++hash_idx) { next = curr->next; curr->prev = 0; curr->next = 0; gsi_push_(gsi, hash_arr[hash_idx], curr); } MemoryZeroStruct(list); } internal CV_SymbolNode * gsi_search(PDB_GsiContext *gsi, CV_Symbol *symbol) { String8 name = cv_name_from_symbol(symbol->kind, symbol->data); U32 hash = gsi_hash(gsi, name); U64 ibucket = hash % gsi->bucket_count; CV_SymbolList bucket_list = gsi->bucket_arr[ibucket]; for (CV_SymbolNode *node = bucket_list.first; node != 0; node = node->next) { String8 that_name = cv_name_from_symbol(node->data.kind, node->data.data); if (str8_match(name, that_name, 0)) { return node; } } return NULL; } //////////////////////////////// internal PDB_PsiContext * psi_alloc(void) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_PsiContext *psi = push_array(arena, PDB_PsiContext, 1); psi->arena = arena; psi->gsi = gsi_alloc(); ProfEnd(); return psi; } internal PDB_PsiContext * psi_open(MSF_Context *msf, MSF_StreamNumber sn, String8 symbol_data) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_PsiContext *psi = push_array(arena, PDB_PsiContext, 1); psi->arena = arena; // TODO: read out address table PDB_PsiHeader header = {0}; msf_stream_read_struct(msf, sn, &header); psi->gsi = gsi_open(msf, sn, symbol_data); ProfEnd(); return psi; } internal void psi_build(TP_Context *tp, PDB_PsiContext *psi, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); U64 symbol_data_base = msf_stream_get_pos(msf, symbols_sn); PDB_GsiBuildResult gsi_build = gsi_build_ex(tp, scratch.arena, psi->gsi, symbol_data_base, /* is_pub32: */ 1, msf->page_size); ProfBegin("Address Map"); ProfBegin("Sort"); gsi_record_sort_by_sc(gsi_build.sort_record_arr, gsi_build.hash_record_count); ProfEnd(); ProfBegin("Offset Fill"); U64 addr_map_count = gsi_build.hash_record_count; U64 addr_map_size = addr_map_count * sizeof(U32); U32 *addr_map = push_array_no_zero(scratch.arena, U32, addr_map_count); for (U64 i = 0; i < addr_map_count; i += 1) { addr_map[i] = gsi_build.sort_record_arr[i].offset; } ProfEnd(); ProfEnd(); PDB_PsiHeader header; header.sym_hash_size = gsi_build.total_hash_size; header.addr_map_size = addr_map_size; header.thunk_count = 0; header.thunk_size = 0; header.isec_thunk_table = 0; header.padding = 0; header.sec_thunk_table_off = 0; header.sec_count = 0; ProfBegin("MSF Write"); msf_stream_write_struct(msf, sn, &header); gsi_write_build_result(tp, gsi_build, msf, sn, symbols_sn); msf_stream_write_array(msf, sn, &addr_map[0], addr_map_count); ProfEnd(); scratch_end(scratch); ProfEnd(); } internal void psi_release(PDB_PsiContext **psi_ptr) { ProfBeginFunction(); gsi_release(&(*psi_ptr)->gsi); arena_release((*psi_ptr)->arena); *psi_ptr = NULL; ProfEnd(); } internal CV_SymbolNode * psi_push(PDB_PsiContext *psi, CV_Pub32Flags flags, U32 offset, U16 isect, String8 name) { CV_Symbol pub = cv_make_pub32(psi->arena, flags, offset, isect, name); CV_SymbolNode *node = gsi_push(psi->gsi, &pub); return node; } //////////////////////////////// internal void dbi_sec_contrib_list_push_node(PDB_DbiSectionContribList *list, PDB_DbiSectionContribNode *node) { node->next = 0; SLLQueuePush(list->first, list->last, node); list->count += 1; } internal PDB_DbiSectionContribNode * dbi_sec_contrib_list_push(Arena *arena, PDB_DbiSectionContribList *list) { PDB_DbiSectionContribNode *node = push_array_no_zero(arena, PDB_DbiSectionContribNode, 1); node->next = 0; dbi_sec_contrib_list_push_node(list, node); return node; } internal void dbi_sec_list_concat_arr(PDB_DbiSectionContribList *list, U64 count, PDB_DbiSectionContribList *to_concat) { SLLConcatInPlaceArray(list, to_concat, count); } internal PDB_DbiContext * dbi_alloc(COFF_MachineType machine, U32 age) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_DbiContext *dbi = push_array(arena, PDB_DbiContext, 1); dbi->arena = arena; dbi->age = age; dbi->machine = machine; dbi->globals_sn = MSF_INVALID_STREAM_NUMBER; dbi->publics_sn = MSF_INVALID_STREAM_NUMBER; dbi->symbols_sn = MSF_INVALID_STREAM_NUMBER; pdb_strtab_alloc(&dbi->ec_names, 8); for (U64 istream = 0; istream < ArrayCount(dbi->dbg_streams); istream += 1) { dbi->dbg_streams[istream] = MSF_INVALID_STREAM_NUMBER; } ProfEnd(); return dbi; } internal String8List * dbi_open_file_info(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); MSF_UInt file_info_pos = sizeof(PDB_DbiHeader) + dbi_header->module_info_size + dbi_header->sec_con_size + dbi_header->sec_map_size; msf_stream_seek(msf, sn, file_info_pos); U16 mod_count = msf_stream_read_u16(msf, sn); U16 total_file_count16 = msf_stream_read_u16(msf, sn); CV_ModIndex *imod_array = push_array(scratch.arena, CV_ModIndex, mod_count); msf_stream_read_array(msf, sn, &imod_array[0], mod_count); U16 *mod_file_count = push_array(scratch.arena, U16, mod_count); msf_stream_read_array(msf, sn, &mod_file_count[0], mod_count); U64 total_file_count = 0; for (U16 imod = 0; imod < mod_count; imod += 1) { total_file_count += mod_file_count[imod]; } U32 *file_name_offset_array = push_array(scratch.arena, U32, total_file_count); msf_stream_read_array(msf, sn, &file_name_offset_array[0], total_file_count); U64 file_name_buffer_offset = sizeof(mod_count) + sizeof(total_file_count16) + sizeof(imod_array[0]) * mod_count + sizeof(mod_file_count[0]) * mod_count + sizeof(file_name_offset_array[0]) * total_file_count; Assert(dbi_header->file_info_size >= file_name_buffer_offset); U64 file_name_buffer_size = dbi_header->file_info_size - file_name_buffer_offset; char *file_name_buffer = push_array(arena, char, file_name_buffer_size + 1); msf_stream_read_array(msf, sn, &file_name_buffer[0], file_name_buffer_size); String8List *file_info = push_array(arena, String8List, mod_count + 1); U32 *file_name_offset_ptr = &file_name_offset_array[0]; for (U64 mod_idx = 0; mod_idx < mod_count; ++mod_idx) { String8List *file_list = &file_info[mod_idx]; U16 file_count = mod_file_count[mod_idx]; for (U16 ifile = 0; ifile < file_count; ifile += 1, file_name_offset_ptr += 1) { Assert(*file_name_offset_ptr <= file_name_buffer_size); String8 file_path = str8_cstring(file_name_buffer + *file_name_offset_ptr); str8_list_push(arena, file_list, file_path); } } scratch_end(scratch); ProfEnd(); return file_info; } internal PDB_DbiModuleList dbi_open_module_info(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header, String8List *file_info) { ProfBeginFunction(); PDB_DbiModuleList list = {0}; MSF_UInt module_info_pos = sizeof(PDB_DbiHeader); msf_stream_seek(msf, sn, module_info_pos); MSF_UInt module_info_opl = module_info_pos + dbi_header->module_info_size; while (msf_stream_get_pos(msf, sn) < module_info_opl) { PDB_DbiCompUnitHeader header = {0}; msf_stream_read_struct(msf, sn, &header); String8 obj_path = msf_stream_read_string(arena, msf, sn); String8 lib_path = msf_stream_read_string(arena, msf, sn); msf_stream_align(msf, sn, PDB_MODULE_ALIGN); String8List source_file_list = {0}; if (header.contribution.base.mod != CV_ModIndex_Invalid) { source_file_list = file_info[header.contribution.base.mod]; } PDB_DbiModule *mod = push_array(arena, PDB_DbiModule, 1); mod->next = 0; mod->sn = header.sn; mod->imod = header.contribution.base.mod; mod->sym_data_size = header.symbols_size; mod->c11_data_size = header.c11_lines_size; mod->c13_data_size = header.c13_lines_size; mod->source_file_list = source_file_list; mod->obj_path = obj_path; mod->lib_path = lib_path; mod->first_sc = header.contribution; SLLQueuePush(list.first, list.last, mod); list.count += 1; } ProfEnd(); return list; } internal PDB_DbiSectionContribList dbi_open_sec_contrib(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header) { ProfBeginFunction(); PDB_DbiSectionContribList sec_contrib = {0}; if (dbi_header->sec_con_size > sizeof(PDB_DbiSectionContrib)) { Temp scratch = scratch_begin(&arena, 1); // seek to start of section contrib info MSF_UInt sec_con_pos = sizeof(PDB_DbiHeader) + dbi_header->module_info_size; msf_stream_seek(msf, sn, sec_con_pos); // read header PDB_DbiSectionContribVersion version = 0; msf_stream_read_struct(msf, sn, &version); // parse contrib items switch (version) { case PDB_DbiSectionContribVersion_1: { U64 contrib_count = dbi_header->sec_con_size / sizeof(PDB_DbiSectionContrib); PDB_DbiSectionContrib *src_contrib_array = push_array(scratch.arena, PDB_DbiSectionContrib, contrib_count); MSF_UInt sec_con_read = msf_stream_read_array(msf, sn, &src_contrib_array[0], contrib_count); Assert(sec_con_read == sizeof(src_contrib_array[0]) * contrib_count); PDB_DbiSectionContribNode *dst_contrib_array = push_array_no_zero(arena, PDB_DbiSectionContribNode, contrib_count); for (U64 icontrib = 0; icontrib < contrib_count; icontrib += 1) { dst_contrib_array[icontrib].next = 0; dst_contrib_array[icontrib].data = src_contrib_array[icontrib]; dbi_sec_contrib_list_push_node(&sec_contrib, &dst_contrib_array[icontrib]); } } break; case PDB_DbiSectionContribVersion_2: { NotImplemented; } break; default: Assert(!"unknown section contrib version"); break; } // have we exhausted sec-con bytes? Assert(sec_con_pos + dbi_header->sec_con_size == msf_stream_get_pos(msf, sn)); scratch_end(scratch); } ProfEnd(); return sec_contrib; } internal PDB_StringTable dbi_open_ec_names(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header) { ProfBeginFunction(); PDB_StringTable ec_names = {0}; if (dbi_header->ec_info_size >= sizeof(PDB_StringTableHeader)) { MSF_UInt ec_names_pos = sizeof(PDB_DbiHeader) + dbi_header->module_info_size + dbi_header->sec_con_size + dbi_header->sec_map_size + dbi_header->file_info_size + dbi_header->tsm_size; msf_stream_seek(msf, sn, ec_names_pos); pdb_strtab_open(&ec_names, msf, sn); } ProfEnd(); return ec_names; } internal void dbi_open_dbg_streams(MSF_StreamNumber *dbg_streams, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header) { ProfBeginFunction(); Assert(dbi_header->dbg_header_size % sizeof(dbg_streams[0]) == 0); // TODO: error handle MSF_UInt dbg_stream_pos = sizeof(PDB_DbiHeader) + dbi_header->module_info_size + dbi_header->sec_con_size + dbi_header->sec_map_size + dbi_header->file_info_size + dbi_header->tsm_size + dbi_header->ec_info_size; msf_stream_seek(msf, sn, dbg_stream_pos); msf_stream_read(msf, sn, &dbg_streams[0], dbi_header->dbg_header_size); ProfEnd(); } internal PDB_DbiSectionList dbi_open_section_headers(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); PDB_DbiSectionList sec_list = {0}; U64 sec_count = msf_stream_get_size(msf, sn) / sizeof(PDB_DbiSectionNode); PDB_DbiSectionNode *sec_nodes = push_array(arena, PDB_DbiSectionNode, sec_count); for (U64 isec = 0; isec < sec_count; isec += 1) { PDB_DbiSectionNode *sec = &sec_nodes[isec]; msf_stream_read_struct(msf, sn, &sec->data); SLLQueuePush(sec_list.first, sec_list.last, sec); sec_list.count += 1; } ProfEnd(); return sec_list; } internal PDB_DbiContext * dbi_open(MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); PDB_DbiHeader header = {0}; msf_stream_read_struct(msf, sn, &header); Arena *arena = arena_alloc(); PDB_DbiContext *dbi = push_array(arena, PDB_DbiContext, 1); dbi->arena = arena; dbi->age = header.age; dbi->machine = header.machine; dbi->globals_sn = header.gsi_sn; dbi->publics_sn = header.psi_sn; dbi->symbols_sn = header.sym_sn; if (header.sig == PDB_DbiHeaderSignature_V1) { switch (header.version) { case PDB_DbiVersion_41: case PDB_DbiVersion_50: case PDB_DbiVersion_60: case PDB_DbiVersion_110: { Assert(!"TODO: support for older DBI versions"); } break; case PDB_DbiVersion_70: { String8List *file_info = dbi_open_file_info(dbi->arena, msf, sn, &header); dbi->module_list = dbi_open_module_info(dbi->arena, msf, sn, &header, file_info); dbi->sec_contrib_list = dbi_open_sec_contrib(dbi->arena, msf, sn, &header); // TODO: section map //dbi->sec_map = dbi_open_sec_map(dbi->arena, msf, sn, &header); dbi->ec_names = dbi_open_ec_names(dbi->arena, msf, sn, &header); dbi_open_dbg_streams(&dbi->dbg_streams[0], msf, sn, &header); dbi->section_list = dbi_open_section_headers(dbi->arena, msf, dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER]); } break; } } ProfEnd(); return dbi; } internal void dbi_build_section_header_stream(PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumber sn) { ProfBeginFunction(); U64 header_arr_size = sizeof(dbi->section_list.first->data) * dbi->section_list.count; msf_stream_resize(msf, sn, header_arr_size); msf_stream_seek(msf, sn, 0); for (PDB_DbiSectionNode *i = dbi->section_list.first; i; i = i->next) { msf_stream_write_struct(msf, sn, &i->data); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(dbi_build_file_info_assign_file_offsets_task) { ProfBeginFunction(); PDB_DbiBuildFileInfoTask *task = raw_task; PDB_DbiModule *mod = task->mod_arr[task_id]; task->imod_arr[mod->imod] = mod->imod; if (mod->imod != CV_ModIndex_Invalid) { // assign source file count task->source_file_name_count_arr[mod->imod] = safe_cast_u16x(mod->source_file_list.node_count); // assign source file offsets U64 source_file_idx = 0; for (String8Node *string_n = mod->source_file_list.first; string_n != 0; string_n = string_n->next, ++source_file_idx) { CV_StringBucket *string_bucket = cv_string_hash_table_lookup(task->string_ht, string_n->string); task->source_file_name_offset_arr[mod->imod][source_file_idx] = safe_cast_u32(string_bucket->u.offset); } } else { // module was deleted don't create source file info task->source_file_name_count_arr[mod->imod] = 0; } ProfEnd(); } internal String8List dbi_build_file_info(Arena *arena, TP_Context *tp, PDB_DbiModuleList mod_list, CV_StringHashTable string_ht) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 total_source_file_count = 0; U64 mod_arr_count = 0; PDB_DbiModule **mod_arr = push_array_no_zero(scratch.arena, PDB_DbiModule *, mod_list.count); for (PDB_DbiModule *mod = mod_list.first; mod != 0; mod = mod->next) { mod_arr[mod_arr_count++] = mod; if (mod->imod != CV_ModIndex_Invalid) { total_source_file_count += mod->source_file_list.node_count; } } U32 **source_file_name_offsets_arr = push_array_no_zero(scratch.arena, U32 *, mod_list.count); U32 *source_file_name_offsets = push_array_no_zero(arena, U32, total_source_file_count); for (U64 mod_idx = 0, cursor = 0; mod_idx < mod_list.count; ++mod_idx) { if (mod_arr[mod_idx]->imod != CV_ModIndex_Invalid) { source_file_name_offsets_arr[mod_idx] = source_file_name_offsets + cursor; cursor += mod_arr[mod_idx]->source_file_list.node_count; } else { source_file_name_offsets_arr[mod_idx] = 0; } } U16 total_source_file_count16 = Min(max_U16, total_source_file_count); U16 mod_count16 = Min(max_U16, mod_list.count); PDB_DbiBuildFileInfoTask task = {0}; task.string_ht = string_ht; task.mod_arr = mod_arr; task.imod_arr = push_array_no_zero(arena, U16, mod_count16); task.source_file_name_count_arr = push_array_no_zero(arena, U16, mod_list.count); task.source_file_name_offset_arr = source_file_name_offsets_arr; tp_for_parallel(tp, 0, mod_arr_count, dbi_build_file_info_assign_file_offsets_task, &task); // pack strings String8 string_buffer = cv_pack_string_hash_table(arena, tp, string_ht); // layout file info sections String8List file_info_srl = {0}; str8_serial_begin(arena, &file_info_srl); str8_serial_push_u16(arena, &file_info_srl, mod_count16); str8_serial_push_u16(arena, &file_info_srl, total_source_file_count16); str8_list_push(arena, &file_info_srl, str8_array(task.imod_arr, mod_count16)); str8_list_push(arena, &file_info_srl, str8_array(task.source_file_name_count_arr, mod_list.count)); str8_list_push(arena, &file_info_srl, str8_array(source_file_name_offsets, total_source_file_count)); str8_list_push(arena, &file_info_srl, string_buffer); str8_serial_push_align(arena, &file_info_srl, sizeof(U32)); scratch_end(scratch); ProfEnd(); return file_info_srl; } internal String8List dbi_build_module_info(Arena *arena, PDB_DbiContext *dbi, MSF_Context *msf) { ProfBeginFunction(); String8List module_info_list = {0}; str8_serial_begin(arena, &module_info_list); for (PDB_DbiModule *mod = dbi->module_list.first; mod != 0; mod = mod->next) { // fill out header PDB_DbiCompUnitHeader *header = push_array(arena, PDB_DbiCompUnitHeader, 1); header->contribution = mod->first_sc; // we don't use these flags right now // U16 is_written : 1 // U16 unused : 7 // U16 tsm_index : 8 ; index into type server map header->flags = 0; header->sn = mod->sn; header->symbols_size = mod->sym_data_size; header->c11_lines_size = mod->c11_data_size; header->c13_lines_size = mod->c13_data_size; header->num_contrib_files = Min(max_U16, mod->source_file_list.node_count); header->file_names_offset = 0; // TODO: fill out the offset // TODO: generate EC info header->src_file = 0; header->pdb_file = 0; Assert(header->sn != MSF_INVALID_STREAM_NUMBER); // push module info str8_serial_push_struct(arena, &module_info_list, header); str8_serial_push_cstr(arena, &module_info_list, mod->obj_path); str8_serial_push_cstr(arena, &module_info_list, mod->lib_path); str8_serial_push_align(arena, &module_info_list, PDB_MODULE_ALIGN); } ProfEnd(); return module_info_list; } #if 0 int dbi_sc_compar(const PDB_DbiSectionContrib *a, const PDB_DbiSectionContrib *b) { #if 0 int cmp = 0; if (a->base.sec == b->base.sec) { if (a->base.sec_off < b->base.sec_off) { cmp = -1; } else if (a->base.sec_off > b->base.sec_off) { cmp = +1; } } else if (a->base.sec < b->base.sec) { cmp = -1; } else { cmp = +1; } #else #define MAKE_SORTER(x) (((U64)(x)->base.sec << 32) | (U64)(x)->base.sec_off) U64 l = MAKE_SORTER(a); U64 r = MAKE_SORTER(b); int cmp = l < r ? -1 : l > r ? + 1 : 0; #undef MAKE_SORTER #endif return cmp; } #endif internal void lnk_radix_sort_dbi_sc_array(PDB_DbiSectionContrib *arr, U64 sc_count, U64 sect_count) { ProfBeginFunction(); #if 1 // faster but uses more memory # define RADIX_BIT_COUNT 16 # define RADIX_MAX 2 #else // slower but uses less memory # define RADIX_BIT_COUNT 8 # define RADIX_MAX 4 #endif Temp scratch = scratch_begin(0,0); PDB_DbiSectionContrib *temp_arr = push_array_no_zero(scratch.arena, PDB_DbiSectionContrib, sc_count); PDB_DbiSectionContrib *src_arr = arr; PDB_DbiSectionContrib *dst_arr = temp_arr; ProfBegin("Count Memzero"); U32 count_8lo[256]; MemoryZeroArray(count_8lo); U32 count_8hi[256]; MemoryZeroArray(count_8hi); U32 count_16[1 << 16]; MemoryZeroArray(count_16); U32 *count_arr = push_array(scratch.arena, U32, sect_count + 1); ProfEnd(); ProfBegin("Histogram"); for (U64 i = 0; i < sc_count; i += 1) { PDB_DbiSectionContrib *sc = src_arr + i; count_arr[sc->base.sec] += 1; U64 digit_8lo = (sc->base.sec_off >> 0) % ArrayCount(count_8lo); U64 digit_8hi = (sc->base.sec_off >> 8) % ArrayCount(count_8hi); U64 digit_16 = (sc->base.sec_off >> 16) % ArrayCount(count_16); count_8lo[digit_8lo] += 1; count_8hi[digit_8hi] += 1; count_16[digit_16] += 1; } ProfEnd(); // // sort on section offset // ProfBegin("Offsets"); U32 offset_8lo = 0; U32 offset_8hi = 0; for (U64 i = 1; i <= ArrayCount(count_8lo); i += 1) { U32 current_8lo = count_8lo[i - 1]; U32 current_8hi = count_8hi[i - 1]; count_8lo[i - 1] = offset_8lo; count_8hi[i - 1] = offset_8hi; offset_8lo += current_8lo; offset_8hi += current_8hi; } U32 offset_16 = 0; for (U64 i = 1; i <= ArrayCount(count_16); i += 1) { U32 current_16 = count_16[i - 1]; count_16[i - 1] = offset_16; offset_16 += current_16; } ProfEnd(); count_8lo[0] = 0; count_8hi[0] = 0; count_16[0] = 0; ProfBegin("Order 8 Lo"); for (U64 i = 0; i < sc_count; i += 1) { PDB_DbiSectionContrib *sc = &src_arr[i]; U64 digit = (sc->base.sec_off >> 0) % ArrayCount(count_8lo); dst_arr[count_8lo[digit]++] = *sc; } ProfEnd(); ProfBegin("Order 8 Hi"); for (U64 i = 0; i < sc_count; i += 1) { PDB_DbiSectionContrib *sc = &dst_arr[i]; U64 digit = (sc->base.sec_off >> 8) % ArrayCount(count_8hi); src_arr[count_8hi[digit]++] = *sc; } ProfEnd(); ProfBegin("Order 16"); for (U64 i = 0; i < sc_count; i += 1) { PDB_DbiSectionContrib *sc = &src_arr[i]; U64 digit = (sc->base.sec_off >> 16) % ArrayCount(count_16); dst_arr[count_16[digit]++] = *sc; } ProfEnd(); // // sort on section index // ProfBegin("Section Indices"); U32 offset = 0; for (U64 i = 1; i <= sect_count; i += 1) { U32 current = count_arr[i - 1]; count_arr[i - 1] = offset; offset += current; } count_arr[0] = 0; for (U64 i = 0; i < sc_count; i += 1) { PDB_DbiSectionContrib *sc = dst_arr + i; src_arr[count_arr[sc->base.sec]++] = *sc; } ProfEnd(); #if 0 for (U64 i = 1; i < sc_count; i += 1) { U64 a = ((U64)arr[i - 1].base.sec << 32) | arr[i - 1].base.sec_off; U64 b = ((U64)arr[i ].base.sec << 32) | arr[i ].base.sec_off; Assert(a <= b); } #endif scratch_end(scratch); #undef RADIX_BIT_COUNT #undef RADIX_MAX ProfEnd(); } internal String8List dbi_build_sec_con(Arena *arena, PDB_DbiContext *dbi) { ProfBeginFunction(); PDB_DbiSectionContribVersion *version = push_array(arena, PDB_DbiSectionContribVersion, 1); *version = PDB_DbiSectionContribVersion_1; // push section contribs V1 ProfBegin("Push sect contribs [Count %llu]", dbi->sec_contrib_list.count); PDB_DbiSectionContrib *sc_array = push_array_no_zero(arena, PDB_DbiSectionContrib, dbi->sec_contrib_list.count); PDB_DbiSectionContrib *dst = &sc_array[0]; for (PDB_DbiSectionContribNode *src = dbi->sec_contrib_list.first; src != 0; src = src->next, dst += 1) { *dst = src->data; } ProfEnd(); // sort section contribs so they are binary searchable lnk_radix_sort_dbi_sc_array(sc_array, dbi->sec_contrib_list.count, dbi->section_list.count + 1); // push section contrib info ProfBegin("List Push"); String8List sec_con_list = {0}; str8_list_push(arena, &sec_con_list, str8((U8*)version, sizeof(*version))); str8_list_push(arena, &sec_con_list, str8((U8*)sc_array, sizeof(sc_array[0])*dbi->sec_contrib_list.count)); ProfEnd(); ProfEnd(); return sec_con_list; } internal String8List dbi_build_sec_map(Arena *arena, PDB_DbiContext *dbi) { ProfBeginFunction(); U64 entry_count = dbi->section_list.count + 1; PDB_DbiSecMapEntry *entry_array = push_array(arena, PDB_DbiSecMapEntry, entry_count); U64 isect = 0; for (PDB_DbiSectionNode *sect = dbi->section_list.first; sect; sect = sect->next, ++isect) { PDB_DbiSecMapEntry *s = &entry_array[isect]; COFF_SectionHeader *section_header = §->data; if (section_header->flags & COFF_SectionFlag_MemRead) { s->flags |= PDB_DbiOMF_READ; } if (section_header->flags & COFF_SectionFlag_MemWrite) { s->flags |= PDB_DbiOMF_WRITE; } if (section_header->flags & COFF_SectionFlag_MemExecute) { s->flags |= PDB_DbiOMF_EXEC; } if (~section_header->flags & COFF_SectionFlag_Mem16Bit) { s->flags |= PDB_DbiOMF_IS_32BIT_ADDR; } s->flags |= PDB_DbiOMF_IS_SELECTOR; // always set s->sec_size = section_header->vsize; s->frame = isect + 1; s->sec_name = max_U16; s->class_name = max_U16; } // init last entry { PDB_DbiSecMapEntry *s = &entry_array[entry_count - 1]; s->flags = PDB_DbiOMF_IS_32BIT_ADDR | PDB_DbiOMF_IS_ABS_ADDR; s->sec_size = max_U32; s->frame = isect + 1; s->sec_name = max_U16; s->class_name = max_U16; } // init header PDB_DbiSecMapHeader *header = push_array(arena, PDB_DbiSecMapHeader, 1); header->section_count = entry_count; header->segment_count = entry_count; // push section map info String8List sec_map_list = {0}; str8_list_push(arena, &sec_map_list, str8((U8*)header, sizeof(*header))); str8_list_push(arena, &sec_map_list, str8((U8*)entry_array, sizeof(entry_array[0])*entry_count)); ProfEnd(); return sec_map_list; } internal String8List dbi_build_dbg_header(Arena *arena, PDB_DbiContext *dbi, MSF_Context *msf) { ProfBeginFunction(); if (dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER] == MSF_INVALID_STREAM_NUMBER) { dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER] = msf_stream_alloc(msf); } dbi_build_section_header_stream(dbi, msf, dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER]); String8List dbg_header_srl = {0}; str8_serial_begin(arena, &dbg_header_srl); str8_serial_push_array(arena, &dbg_header_srl, dbi->dbg_streams, ArrayCount(dbi->dbg_streams)); ProfEnd(); return dbg_header_srl; } internal void dbi_build(TP_Context *tp, PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumber dbi_sn, CV_StringHashTable string_ht) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); ProfBegin("Build"); String8List module_info_list = dbi_build_module_info(scratch.arena, dbi, msf); String8List sec_con_list = dbi_build_sec_con(scratch.arena, dbi); String8List sec_map_list = dbi_build_sec_map(scratch.arena, dbi); String8List file_info_list = dbi_build_file_info(scratch.arena, tp, dbi->module_list, string_ht); String8List dbg_header_list = dbi_build_dbg_header(scratch.arena, dbi, msf); String8List tsm_list = {0}; // TODO: TSM ProfEnd(); PDB_DbiHeader header = {0}; header.sig = PDB_DbiHeaderSignature_V1; header.version = PDB_DbiVersion_70; header.age = dbi->age; header.gsi_sn = dbi->globals_sn; header.build_number = PDB_DbiMakeBuildNumber(14, 11); header.psi_sn = dbi->publics_sn; header.pdb_version = 0; header.sym_sn = dbi->symbols_sn; header.pdb_version2 = 0; header.module_info_size = module_info_list.total_size; header.sec_con_size = sec_con_list.total_size; header.sec_map_size = sec_map_list.total_size; header.file_info_size = file_info_list.total_size; header.tsm_size = tsm_list.total_size; header.mfc_index = 0; header.dbg_header_size = dbg_header_list.total_size; header.ec_info_size = pdb_strtab_get_serialized_size(&dbi->ec_names); header.flags = 0; header.machine = dbi->machine; header.reserved = 0; ProfBegin("MSF Write"); U64 dbi_stream_size = sizeof(header) + module_info_list.total_size + sec_con_list.total_size + sec_map_list.total_size + file_info_list.total_size + tsm_list.total_size + dbg_header_list.total_size; msf_stream_resize(msf, dbi_sn, dbi_stream_size); msf_stream_seek_start(msf, dbi_sn); msf_stream_write(msf, dbi_sn, &header, sizeof(header)); msf_stream_write_list(msf, dbi_sn, module_info_list); msf_stream_write_list(msf, dbi_sn, sec_con_list); msf_stream_write_list(msf, dbi_sn, sec_map_list); msf_stream_write_list(msf, dbi_sn, file_info_list); msf_stream_write_list(msf, dbi_sn, tsm_list); pdb_strtab_build(&dbi->ec_names, msf, dbi_sn); msf_stream_write_list(msf, dbi_sn, dbg_header_list); ProfEnd(); ProfEnd(); scratch_end(scratch); } internal void dbi_release(PDB_DbiContext **dbi_ptr) { ProfBeginFunction(); arena_release((*dbi_ptr)->arena); *dbi_ptr = 0; ProfEnd(); } internal PDB_DbiModule * dbi_push_module(PDB_DbiContext *dbi, String8 obj_path, String8 lib_path) { // init module PDB_DbiModule *mod = push_array(dbi->arena, PDB_DbiModule, 1); mod->imod = safe_cast_u32(dbi->module_list.count); mod->sn = MSF_INVALID_STREAM_NUMBER; mod->obj_path = push_str8_copy(dbi->arena, obj_path); mod->lib_path = push_str8_copy(dbi->arena, lib_path.size > 0 ? lib_path : obj_path); // push to list SLLQueuePush(dbi->module_list.first, dbi->module_list.last, mod); dbi->module_list.count += 1; return mod; } internal void dbi_module_push_section_contrib(PDB_DbiContext *dbi, PDB_DbiModule *mod, ISectOff isect_off, U32 size, U32 data_crc, U32 reloc_crc, COFF_SectionFlags flags) { ProfBeginFunction(); PDB_DbiSectionContrib sc; sc.base.sec = safe_cast_u16(isect_off.isect); sc.base.sec_off = isect_off.off; sc.base.size = size; sc.base.flags = flags; sc.base.mod = mod->imod; sc.data_crc = data_crc; sc.reloc_crc = reloc_crc; PDB_DbiSectionContribNode *node = push_array_no_zero(dbi->arena, PDB_DbiSectionContribNode, 1); node->data = sc; dbi_sec_contrib_list_push_node(&dbi->sec_contrib_list, node); // Mod1::fUpdateSecContrib if (mod->first_sc.base.mod == 0) { if (flags & COFF_SectionFlag_CntCode) { mod->first_sc = sc; } } ProfEnd(); } internal String8 dbi_module_read_symbol_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod) { String8 symbol_data = str8(0,0); if (mod->sn != MSF_INVALID_STREAM_NUMBER) { B32 is_seek_ok = msf_stream_seek(msf, mod->sn, 0); if (is_seek_ok) { symbol_data = msf_stream_read_block(arena, msf, mod->sn, mod->sym_data_size); } } return symbol_data; } internal String8 dbi_module_read_c11_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod) { String8 c11_data = str8(0,0); if (mod->sn != MSF_INVALID_STREAM_NUMBER) { MSF_UInt c11_data_pos = mod->sym_data_size; B32 is_seek_ok = msf_stream_seek(msf, mod->sn, c11_data_pos); if (is_seek_ok) { c11_data = msf_stream_read_block(arena, msf, mod->sn, mod->c13_data_size); } } return c11_data; } internal String8 dbi_module_read_c13_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod) { String8 c13_data = str8(0,0); if (mod->sn != MSF_INVALID_STREAM_NUMBER) { MSF_UInt c13_data_pos = mod->sym_data_size + mod->c11_data_size; B32 is_seek_ok = msf_stream_seek(msf, mod->sn, c13_data_pos); if (is_seek_ok) { c13_data = msf_stream_read_block(arena, msf, mod->sn, mod->c13_data_size); } } return c13_data; } internal void dbi_push_section(PDB_DbiContext *dbi, COFF_SectionHeader *hdr) { ProfBeginFunction(); PDB_DbiSectionNode *n = push_array(dbi->arena, PDB_DbiSectionNode, 1); n->data = *hdr; n->next = 0; SLLQueuePush(dbi->section_list.first, dbi->section_list.last, n); dbi->section_list.count += 1; ProfEnd(); } //////////////////////////////// internal MSF_Context * pdb_alloc_msf(U64 page_size) { ProfBeginFunction(); MSF_Context *msf = msf_alloc(page_size, MSF_DEFAULT_FPM); MSF_StreamNumber null_sn = msf_stream_alloc(msf); MSF_StreamNumber info_sn = msf_stream_alloc(msf); MSF_StreamNumber tpi_sn = msf_stream_alloc(msf); MSF_StreamNumber dbi_sn = msf_stream_alloc(msf); MSF_StreamNumber ipi_sn = msf_stream_alloc(msf); Assert(null_sn == 0); Assert(info_sn == PDB_FixedStream_Info); Assert(dbi_sn == PDB_FixedStream_Dbi); Assert(tpi_sn == PDB_FixedStream_Tpi); Assert(ipi_sn == PDB_FixedStream_Ipi); ProfEnd(); return msf; } internal PDB_Context * pdb_alloc(U64 page_size, COFF_MachineType machine, COFF_TimeStamp time_stamp, U32 age, Guid guid) { ProfBeginFunction(); Arena *arena = arena_alloc(); PDB_Context *pdb = push_array(arena, PDB_Context, 1); pdb->arena = arena; pdb->msf = pdb_alloc_msf(page_size); pdb->info = pdb_info_alloc(age, time_stamp, guid); pdb->dbi = dbi_alloc(machine, age); pdb->gsi = gsi_alloc(); pdb->psi = psi_alloc(); pdb->type_servers[CV_TypeIndexSource_NULL] = push_array(arena, PDB_TypeServer, 1); for (U64 i = CV_TypeIndexSource_NULL + 1; i < ArrayCount(pdb->type_servers); ++i) { pdb->type_servers[i] = pdb_type_server_alloc(PDB_TYPE_SERVER_HASH_BUCKET_COUNT_CURRENT); } ProfEnd(); return pdb; } internal PDB_Context * pdb_open(String8 data) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); PDB_Context *pdb = 0; MSF_Context *msf = 0; MSF_Error msf_err = msf_open(data, &msf); if (msf_err == MSF_Error_OK) { Arena *arena = arena_alloc(); pdb = push_array(arena, PDB_Context, 1); pdb->arena = arena; pdb->msf = msf; pdb->info = pdb_info_open(pdb->msf, PDB_FixedStream_Info); pdb->dbi = dbi_open(pdb->msf, PDB_FixedStream_Dbi); if (pdb->dbi) { MSF_UInt sym_data_size = msf_stream_get_size(pdb->msf, pdb->dbi->symbols_sn); String8 symbol_data = msf_stream_read_block(scratch.arena, pdb->msf, pdb->dbi->symbols_sn, sym_data_size); pdb->gsi = gsi_open(pdb->msf, pdb->dbi->globals_sn, symbol_data); pdb->psi = psi_open(pdb->msf, pdb->dbi->publics_sn, symbol_data); } PDB_StringTable *strtab = &pdb->info->strtab; pdb->type_servers[CV_TypeIndexSource_NULL] = push_array(pdb->arena, PDB_TypeServer, 1); pdb->type_servers[CV_TypeIndexSource_TPI] = pdb_type_server_open(pdb->msf, PDB_FixedStream_Tpi, strtab); if (pdb->info->flags & PDB_FeatureFlag_HAS_ID_STREAM) { pdb->type_servers[CV_TypeIndexSource_IPI] = pdb_type_server_open(pdb->msf, PDB_FixedStream_Ipi, strtab); } } scratch_end(scratch); ProfEnd(); return pdb; } internal void pdb_release(PDB_Context **pdb_ptr) { ProfBeginFunction(); PDB_Context *pdb = *pdb_ptr; msf_release(&pdb->msf); dbi_release(&pdb->dbi); gsi_release(&pdb->gsi); for (U64 i = 1; i < ArrayCount(pdb->type_servers); ++i) { pdb_type_server_release(&pdb->type_servers[i]); } arena_release(pdb->arena); *pdb_ptr = 0; ProfEnd(); } internal void pdb_set_machine(PDB_Context *pdb, COFF_MachineType machine) { pdb->dbi->machine = machine; } internal void pdb_set_guid(PDB_Context *pdb, Guid guid) { pdb->info->guid = guid; } internal void pdb_set_time_stamp(PDB_Context *pdb, COFF_TimeStamp time_stamp) { pdb->info->time_stamp = time_stamp; } internal void pdb_set_age(PDB_Context *pdb, U32 age) { pdb->dbi->age = age; pdb->info->age = age; } internal COFF_MachineType pdb_get_machine(PDB_Context *pdb) { return pdb->dbi->machine; } internal COFF_TimeStamp pdb_get_time_stamp(PDB_Context *pdb) { return pdb->info->time_stamp; } internal U32 pdb_get_age(PDB_Context *pdb) { return pdb->info->age; } internal Guid pdb_get_guid(PDB_Context *pdb) { return pdb->info->guid; } internal void pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht) { ProfBeginFunction(); PDB_InfoContext *info = pdb->info; PDB_StringTable *strtab = &info->strtab; PDB_DbiContext *dbi = pdb->dbi; PDB_TypeServer *tpi = pdb->type_servers[CV_TypeIndexSource_TPI]; PDB_TypeServer *ipi = pdb->type_servers[CV_TypeIndexSource_IPI]; if (dbi->globals_sn == MSF_INVALID_STREAM_NUMBER) { dbi->globals_sn = msf_stream_alloc(pdb->msf); } if (dbi->publics_sn == MSF_INVALID_STREAM_NUMBER) { dbi->publics_sn = msf_stream_alloc(pdb->msf); } if (dbi->symbols_sn == MSF_INVALID_STREAM_NUMBER) { dbi->symbols_sn = msf_stream_alloc(pdb->msf); } pdb_type_server_build(tp, tpi, strtab, pdb->msf, PDB_FixedStream_Tpi); if (info->flags & PDB_FeatureFlag_HAS_ID_STREAM) { pdb_type_server_build(tp, ipi, strtab, pdb->msf, PDB_FixedStream_Ipi); } psi_build(tp, pdb->psi, pdb->msf, dbi->publics_sn, dbi->symbols_sn); gsi_build(tp, pdb->gsi, pdb->msf, dbi->globals_sn, dbi->symbols_sn); dbi_build(tp, pdb->dbi, pdb->msf, PDB_FixedStream_Dbi, string_ht); pdb_info_build(pdb->info, pdb->msf, PDB_FixedStream_Info); ProfEnd(); } //////////////////////////////// internal String8 pdb_string_from_src_error(PDB_SrcError error) { switch (error) { case PDB_SrcError_OK: return str8_lit("OK"); case PDB_SrcError_DUPLICATE_NAME_STREAM: return str8_lit("DUPLICATE_NAME_STREAM"); case PDB_SrcError_DUPLICATE_ENTRY: return str8_lit("DUPLICATE_ENTRY"); case PDB_SrcError_UNABLE_TO_WRITE_DATA: return str8_lit("UNABLE_TO_WRITE_DATA"); case PDB_SrcError_UNSUPPORTED_COMPRESSION: return str8_lit("UNSUPPORTED_COMPRESSION"); case PDB_SrcError_UNKNOWN: return str8_lit("UNKNOWN"); } return str8(0,0); } internal String8 pdb_string_from_open_type_server_error(PDB_OpenTypeServerError error) { switch (error) { case PDB_OpenTypeServerError_OK: return str8_lit("OK"); case PDB_OpenTypeServerError_UNKNOWN: return str8_lit("UNKNOWN"); case PDB_OpenTypeServerError_INVALID_BUCKET_COUNT: return str8_lit("INVALID_BUCKET_COUNT"); case PDB_OpenTypeServerError_INVALID_TI_RANGE: return str8_lit("INVALID_TI_RANGE"); case PDB_OpenTypeServerError_UNSUPPORTED_VERSION: return str8_lit("UNSUPPORTED_VERSION"); } return str8(0,0); } ================================================ FILE: src/linker/pdb_ext/pdb_builder.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once //////////////////////////////// #define PDB_NATURAL_ALIGN 4 #define PDB_SYMBOL_ALIGN PDB_NATURAL_ALIGN //////////////////////////////// // Hash table #define PDB_HASH_TABLE_PACK_FUNC(name) void name(Arena *arena, String8List *local_data_srl, String8List *key_value_srl, String8 key, String8 value, void *ud) typedef PDB_HASH_TABLE_PACK_FUNC(PDB_HashTablePackFunc); #define PDB_HASH_TABLE_UNPACK_FUNC(name) B32 name(void *ud, String8 local_data, String8 key_value_data, U64 *key_value_cursor, String8 *key_out, String8 *value_out) typedef PDB_HASH_TABLE_UNPACK_FUNC(PDB_HashTableUnpackFunc); typedef struct PDB_HashTableBucket { String8 key; String8 value; } PDB_HashTableBucket; typedef struct PDB_HashTable { Arena *arena; PDB_HashTableBucket *bucket_arr; U32Array present_bits; U32Array deleted_bits; U32 max; U32 count; } PDB_HashTable; typedef enum { PDB_HashTableParseError_OK, PDB_HashTableParseError_OUT_OF_BYTES, PDB_HashTableParseError_CORRUPTED } PDB_HashTableParseError; //////////////////////////////// // String Table typedef struct PDB_StringTableBucket { String8 data; PDB_StringOffset offset; PDB_StringIndex istr; } PDB_StringTableBucket; typedef struct PDB_StringTable { Arena *arena; U32 version; U32 size; U32 bucket_count; U32 bucket_max; U32 *ibucket_array; PDB_StringTableBucket **bucket_array; } PDB_StringTable; typedef enum { PDB_StringTableOpenError_OK, PDB_StringTableOpenError_BAD_MAGIC, PDB_StringTableOpenError_UNKNOWN_VERSION, PDB_StringTableOpenError_CORRUPTED, PDB_StringTableOpenError_STRING_OFFSET_OUT_OF_BOUNDS, PDB_StringTableOpenError_OFFSETS_EXCEED_BUCKET_COUNT } PDB_StringTableOpenError; //////////////////////////////// // Type Server #define PDB_TYPE_HINT_STEP 128 #define PDB_LEAF_ALIGN PDB_NATURAL_ALIGN typedef enum { PDB_OpenTypeServerError_OK, PDB_OpenTypeServerError_UNKNOWN, PDB_OpenTypeServerError_INVALID_BUCKET_COUNT, PDB_OpenTypeServerError_INVALID_TI_RANGE, PDB_OpenTypeServerError_UNSUPPORTED_VERSION, } PDB_OpenTypeServerError; typedef struct PDB_TypeBucket { struct PDB_TypeBucket *next; String8 raw_leaf; CV_TypeIndex type_index; } PDB_TypeBucket; typedef struct PDB_TypeServer { Arena *arena; CV_TypeIndex ti_lo; String8List leaf_list; U64 bucket_cap; PDB_TypeBucket **buckets; MSF_StreamNumber hash_sn; PDB_HashTable hash_adj; } PDB_TypeServer; typedef struct PDB_TypeHashStreamInfo { PDB_OffsetSize hash_vals; PDB_OffsetSize ti_offs; PDB_OffsetSize hash_adj; } PDB_TypeHashStreamInfo; typedef struct PDB_TypeServerParse { Rng1U64 ti_range; String8 leaf_data; } PDB_TypeServerParse; typedef struct { CV_DebugT debug_t; U64 *udt_counts; U64 *udt_offsets; Rng1U64 *ranges; PDB_TypeServer *type_server; PDB_TypeBucket *udt_buckets; } PDB_PushLeafTask; typedef struct { PDB_TypeServer *ts; U32 *map; } PDB_WriteTypeToBucketMap; typedef struct { CV_TypeIndex ti_lo; CV_TypeIndex ti_hi; U64 hint_count; PDB_TpiOffHint *hint_arr; String8Node **lf_arr; Rng1U64 *lf_range_arr; U64 *lf_cursor_arr; U8 *lf_buf; U64 lf_buf_size; } PDB_WriteTypesTask; //////////////////////////////// // Info typedef struct PDB_InfoParse { PDB_TpiVersion version; COFF_TimeStamp time_stamp; U32 age; Guid guid; String8 extra_info; } PDB_InfoParse; typedef struct PDB_InfoContext { Arena *arena; COFF_TimeStamp time_stamp; U32 age; Guid guid; PDB_FeatureFlags flags; PDB_HashTable named_stream_ht; PDB_HashTable src_header_block_ht; PDB_StringTable strtab; } PDB_InfoContext; //////////////////////////////// // SRC Header Block typedef enum { PDB_SrcError_OK, PDB_SrcError_DUPLICATE_NAME_STREAM, PDB_SrcError_DUPLICATE_ENTRY, PDB_SrcError_UNABLE_TO_WRITE_DATA, PDB_SrcError_UNSUPPORTED_COMPRESSION, PDB_SrcError_UNKNOWN } PDB_SrcError; //////////////////////////////// // GSI #define PDB_GSI_V70_SYMBOL_ALIGN 4 #define PDB_GSI_V70_WORD_SIZE 32 #define PDB_GSI_V70_BUCKET_COUNT 4096 #define PDB_GSI_V70_BITMAP_COUNT ((PDB_GSI_V70_BUCKET_COUNT / PDB_GSI_V70_WORD_SIZE) + 1) #define PDB_GSI_V70_BITMAP_SIZE (PDB_GSI_V70_BITMAP_COUNT * sizeof(U32)) typedef struct PDB_GsiContext { Arena *arena; U64 word_size; U64 symbol_align; U64 bucket_count; U64 symbol_count; CV_SymbolList *bucket_arr; } PDB_GsiContext; typedef struct PDB_GsiSortRecord { ISectOff isect_off; String8 name; U64 offset; } PDB_GsiSortRecord; typedef struct PDB_GsiBuildResult { PDB_GsiHeader header; U64 hash_record_count; PDB_GsiHashRecord *hash_record_arr; PDB_GsiSortRecord *sort_record_arr; U64 bitmap_count; U32 *bitmap; U64 compressed_bucket_count; U32 *compressed_bucket_arr; U64 total_hash_size; String8 symbol_data; } PDB_GsiBuildResult; typedef struct PDB_GsiSerializeSymbolsTask { U64 symbol_align; CV_SymbolList *bucket_arr; U64 *bucket_size_arr; U64 *bucket_off_arr; U8 *buffer; PDB_GsiSortRecord **sort_record_arr_arr; PDB_GsiSortRecord *sort_record_arr; } PDB_GsiSerializeSymbolsTask; //////////////////////////////// // PSI typedef struct PDB_PsiContext { Arena *arena; PDB_GsiContext *gsi; } PDB_PsiContext; //////////////////////////////// // DBI #define PDB_MODULE_ALIGN PDB_NATURAL_ALIGN typedef struct PDB_DbiModule { struct PDB_DbiModule *next; MSF_StreamNumber sn; CV_ModIndex imod; PDB_DbiSectionContrib first_sc; U64 sym_data_size; U64 c11_data_size; U64 c13_data_size; U64 globrefs_size; // TODO: what is this for? String8 obj_path; String8 lib_path; String8List source_file_list; } PDB_DbiModule; typedef struct PDB_DbiModuleList { PDB_DbiModule *first; PDB_DbiModule *last; U64 count; } PDB_DbiModuleList; typedef struct PDB_DbiSectionContribNode { struct PDB_DbiSectionContribNode *next; PDB_DbiSectionContrib data; } PDB_DbiSectionContribNode; typedef struct PDB_DbiSectionContribList { PDB_DbiSectionContribNode *first; PDB_DbiSectionContribNode *last; U64 count; } PDB_DbiSectionContribList; typedef struct PDB_DbiSectionNode { struct PDB_DbiSectionNode *next; COFF_SectionHeader data; } PDB_DbiSectionNode; typedef struct PDB_DbiSectionList { U64 count; PDB_DbiSectionNode *first; PDB_DbiSectionNode *last; } PDB_DbiSectionList; typedef struct PDB_DbiContext { Arena *arena; U32 age; COFF_MachineType machine; MSF_StreamNumber globals_sn; MSF_StreamNumber publics_sn; MSF_StreamNumber symbols_sn; PDB_DbiModuleList module_list; PDB_DbiSectionContribList sec_contrib_list; PDB_DbiSectionList section_list; PDB_StringTable ec_names; MSF_StreamNumber dbg_streams[PDB_DbiStream_COUNT]; } PDB_DbiContext; //////////////////////////////// // PDB typedef struct PDB_Context { Arena *arena; MSF_Context *msf; PDB_InfoContext *info; PDB_DbiContext *dbi; PDB_GsiContext *gsi; PDB_PsiContext *psi; PDB_TypeServer *type_servers[CV_TypeIndexSource_COUNT]; } PDB_Context; //////////////////////////////// typedef struct { PDB_GsiContext *gsi; Rng1U64 *ranges; CV_SymbolNode **symbols; U32 *hashes; } GSI_SymbolHasherTask; typedef struct { CV_StringHashTable string_ht; PDB_DbiModule **mod_arr; U16 *imod_arr; U16 *source_file_name_count_arr; U32 **source_file_name_offset_arr; } PDB_DbiBuildFileInfoTask; //////////////////////////////// // PDB internal PDB_Context * pdb_alloc(U64 page_size, COFF_MachineType machine, COFF_TimeStamp time_stamp, U32 age, Guid guid); internal PDB_Context * pdb_open(String8 data); internal void pdb_release(PDB_Context **pdb_ptr); internal void pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht); internal void pdb_set_machine(PDB_Context *pdb, COFF_MachineType machine); internal void pdb_set_guid(PDB_Context *pdb, Guid guid); internal void pdb_set_time_stamp(PDB_Context *pdb, COFF_TimeStamp time_stamp); internal void pdb_set_age(PDB_Context *pdb, U32 age); internal COFF_MachineType pdb_get_machine(PDB_Context *pdb); internal COFF_TimeStamp pdb_get_time_stamp(PDB_Context *pdb); internal U32 pdb_get_age(PDB_Context *pdb); internal Guid pdb_get_guid(PDB_Context *pdb); //////////////////////////////// // Info internal PDB_InfoContext * pdb_info_alloc(U32 age, COFF_TimeStamp time_stamp, Guid guid); internal void pdb_info_parse_from_data(String8 data, PDB_InfoParse *parse_out); internal PDB_InfoContext * pdb_info_open(MSF_Context *msf, MSF_StreamNumber sn); internal void pdb_info_build(PDB_InfoContext *info, MSF_Context *msf, MSF_StreamNumber sn); internal void pdb_info_release(PDB_InfoContext **info_ptr); internal MSF_StreamNumber pdb_push_named_stream(PDB_HashTable *named_stream_ht, MSF_Context *msf, String8 name); internal MSF_StreamNumber pdb_find_named_stream(PDB_HashTable *named_stream_ht, String8 name); internal PDB_SrcError pdb_add_src(PDB_InfoContext *info, MSF_Context *msf, String8 file_path, String8 file_data, PDB_SrcCompType comp); //////////////////////////////// // GSI internal PDB_GsiContext * gsi_alloc(void); internal PDB_GsiContext * gsi_open(MSF_Context *msf, MSF_StreamNumber sn, String8 symbol_data); internal void gsi_build(TP_Context *tp, PDB_GsiContext *gsi, MSF_Context *msf, MSF_StreamNumber gsi_sn, MSF_StreamNumber symbols_sn); internal void gsi_release(PDB_GsiContext **gsi_ptr); internal void gsi_write_build_result(TP_Context *tp, PDB_GsiBuildResult build, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn); internal PDB_GsiBuildResult gsi_build_ex(TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 symbol_data_base, B32 export_symbol_ptr_arr, U64 msf_page_size); internal U32 gsi_hash(PDB_GsiContext *gsi, String8 input); internal CV_SymbolNode * gsi_push(PDB_GsiContext *gsi, CV_Symbol *symbol); internal void gsi_push_many_arr(TP_Context *tp, PDB_GsiContext *gsi, U64 count, CV_SymbolNode **symbol_arr); internal void gsi_push_many_list(PDB_GsiContext *gsi, U64 count, U32 *hash_arr, CV_SymbolList *list); internal CV_SymbolNode * gsi_search(PDB_GsiContext *gsi, CV_Symbol *symbol); //////////////////////////////// // PSI internal PDB_PsiContext * psi_alloc(void); internal PDB_PsiContext * psi_open(MSF_Context *msf, MSF_StreamNumber sn, String8 symbol_data); internal void psi_build(TP_Context *tp, PDB_PsiContext *psi, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn); internal void psi_release(PDB_PsiContext **psi_ptr); internal CV_SymbolNode * psi_push(PDB_PsiContext *psi, CV_Pub32Flags flags, U32 offset, U16 isect, String8 name); // TODO: //internal CV_Symbol psi_neareset_symbol(PDB_PsiContext *psi, U16 isect, U32 off); //internal void psi_push_thunk_map(PDB_PsiContext *psi, U32 *thunk_map, U32 thunk_count, U32 thunk_size, PDB_SO *sect_map, U32 sect_count, ISectOff thunk_table); //////////////////////////////// // DBI internal PDB_DbiContext * dbi_alloc(COFF_MachineType machine, U32 age); internal PDB_DbiContext * dbi_open(MSF_Context *msf, MSF_StreamNumber sn); internal void dbi_build(TP_Context *tp, PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumber dbi_sn, CV_StringHashTable string_ht); internal void dbi_release(PDB_DbiContext **dbi_ptr); internal PDB_DbiModule * dbi_push_module(PDB_DbiContext *dbi, String8 obj_path, String8 lib_path); internal String8 dbi_module_read_symbol_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod); internal String8 dbi_module_read_c11_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod); internal String8 dbi_module_read_c13_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod); internal void dbi_module_push_section_contrib(PDB_DbiContext *dbi, PDB_DbiModule *mod, ISectOff isect_off, U32 size, U32 data_crc, U32 reloc_crc, COFF_SectionFlags flags); internal String8List * dbi_open_file_info(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header); internal PDB_DbiModuleList dbi_open_module_info(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header, String8List *file_info); internal PDB_DbiSectionContribList dbi_open_sec_contrib(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header); internal PDB_StringTable dbi_open_ec_names(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header); internal void dbi_open_dbg_streams(MSF_StreamNumber *dbg_streams, MSF_Context *msf, MSF_StreamNumber sn, PDB_DbiHeader *dbi_header); internal PDB_DbiSectionList dbi_open_section_headers(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn); internal void dbi_build_section_header_stream(PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumber sn); //////////////////////////////// // Hash Table internal void pdb_hash_table_alloc(PDB_HashTable *ht, U32 max); internal void pdb_hash_table_release(PDB_HashTable *ht); internal PDB_HashTableParseError pdb_hash_table_from_data(PDB_HashTable *ht, String8 data, B32 has_local_data, PDB_HashTableUnpackFunc *unpack_func, void *unpack_ud, U64 *read_bytes_out); internal String8 pdb_data_from_hash_table(Arena *arena, PDB_HashTable *ht, B32 has_local_data, PDB_HashTablePackFunc *pack_func, void *pack_ud); internal void pdb_hash_table_set(PDB_HashTable *ht, String8 key, String8 value); internal B32 pdb_hash_table_get(PDB_HashTable *ht, String8 key, String8 *value_out); internal void pdb_hash_table_delete(PDB_HashTable *ht, String8 key); internal B32 pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value); internal B32 pdb_hash_table_is_present(PDB_HashTable *ht, U32 k); internal B32 pdb_hash_table_is_deleted(PDB_HashTable *ht, U32 k); internal U32 pdb_hash_table_hash(String8 key); internal void pdb_hash_table_grow(PDB_HashTable *ht, U64 new_capacity); internal void pdb_hash_table_get_present_keys_and_values(Arena *arena, PDB_HashTable *ht, String8Array *keys_out, String8Array *values_out); //////////////////////////////// internal PDB_HashTableParseError pdb_hash_adj_hash_table_from_data(PDB_HashTable *ht, String8 data, PDB_StringTable *strtab, U64 *read_bytes_out); internal PDB_HashTableParseError pdb_src_header_block_ht_from_data(PDB_HashTable *ht, String8 data, PDB_StringTable *strtab, U64 *read_bytes_out); internal PDB_HashTableParseError pdb_named_stream_ht_from_data(PDB_HashTable *ht, String8 data, U64 *read_bytes_out); internal String8 pdb_data_from_hash_adj_hash_table(Arena *arena, PDB_HashTable *ht, PDB_StringTable *strtab); internal String8 pdb_data_from_src_header_block_ht(Arena *arena, PDB_HashTable *ht, PDB_StringTable *strtab); internal String8 pdb_data_from_named_stream_ht(Arena *arena, PDB_HashTable *ht); //////////////////////////////// // String Table internal void pdb_strtab_alloc(PDB_StringTable *strtab, U32 max); internal PDB_StringTableOpenError pdb_strtab_open(PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn); internal void pdb_strtab_build(PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn); internal void pdb_strtab_release(PDB_StringTable *strtab); internal PDB_StringIndex pdb_strtab_add(PDB_StringTable *strtab, String8 string); internal B32 pdb_strtab_search(PDB_StringTable *strtab, String8 string, PDB_StringIndex *index_out); internal String8 pdb_strtab_string_from_offset(PDB_StringTable *strtab, PDB_StringOffset offset); internal PDB_StringOffset pdb_strtab_string_to_offset(PDB_StringTable *strtab, PDB_StringIndex stridx); internal U32 pdb_strtab_get_serialized_size(PDB_StringTable *strtab); internal B32 pdb_strtab_try_add(PDB_StringTable *strtab, String8 string, PDB_StringIndex *index_out); internal void pdb_strtab_grow(PDB_StringTable *strtab, U64 new_max); internal U32 pdb_strtab_hash(PDB_StringTable *strtab, String8 string); //////////////////////////////// // Type Server internal PDB_OpenTypeServerError pdb_type_server_parse_from_data_v80(String8 data, PDB_TypeServerParse *parse_out); internal PDB_OpenTypeServerError pdb_type_server_parse_from_data(String8 data, PDB_TypeServerParse *parse_out); internal PDB_TypeServer * pdb_type_server_alloc(U64 bucket_count); internal PDB_TypeServer * pdb_type_server_open_v80(MSF_Context *msf, MSF_StreamNumber sn, PDB_StringTable *strtab); internal PDB_TypeServer * pdb_type_server_open(MSF_Context *msf, MSF_StreamNumber sn, PDB_StringTable *strtab); internal void pdb_type_server_build(TP_Context *tp, PDB_TypeServer *ts, PDB_StringTable *strtab, MSF_Context *msf, MSF_StreamNumber sn); internal void pdb_type_server_release(PDB_TypeServer **serv_ptr); internal void pdb_type_server_push(PDB_TypeServer *ts, String8 raw_leaf); internal void pdb_type_server_push_parallel(TP_Context *tp, PDB_TypeServer *ts, CV_DebugT types); //internal CV_LeafNode * pdb_type_server_leaf_from_string(PDB_TypeServer *ts, String8 string); internal String8Node * pdb_type_server_reserve(PDB_TypeServer *ts, U64 count); internal String8Node * pdb_type_server_make_leaf(PDB_TypeServer *ts, CV_LeafKind kind, String8 data); internal void pdb_type_server_push_bucket(PDB_TypeServer *ts, CV_Leaf *leaf); internal PDB_TypeHashStreamInfo pdb_type_hash_stream_build(TP_Context *tp, PDB_TypeServer *ts, PDB_StringTable *strtab, MSF_Context *msf, PDB_TpiOffHint *hint_arr, U64 hint_count); //////////////////////////////// // Enum -> String internal String8 pdb_string_from_src_error(PDB_SrcError error); internal String8 pdb_string_from_open_type_server_error(PDB_OpenTypeServerError error); ================================================ FILE: src/linker/pdb_ext/pdb_helpers.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 pdb_read_bit_vector_string(String8 data, U64 offset, U32Array *bits_out) { U64 cursor = offset; U32 word_count = 0; cursor += str8_deserial_read_struct(data, cursor, &word_count); U64 word_data_read_size = word_count * sizeof(U32); String8 word_data = str8(0,0); cursor += str8_deserial_read_block(data, cursor, word_data_read_size, &word_data); if (word_data.size == word_data_read_size) { bits_out->count = word_count; bits_out->v = (U32*)word_data.str; } else { bits_out->count = 0; bits_out->v = 0; } U64 read_size = cursor - offset; return read_size; } internal U64 pdb_read_bit_vector_msf(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, U32Array *bits_out) { // peek word count MSF_UInt pos = msf_stream_get_pos(msf, sn); U32 word_count = msf_stream_read_u32(msf, sn); msf_stream_seek(msf, sn, pos); // read out header + packed words U64 buffer_size = sizeof(word_count) + word_count * sizeof(U32); U8 *buffer = push_array(arena, U8, buffer_size); MSF_UInt read_size = msf_stream_read(msf, sn, buffer, buffer_size); Assert(read_size == buffer_size); // parse words U64 parse_size = pdb_read_bit_vector_string(str8(buffer, buffer_size), 0, bits_out); return parse_size; } internal B32 pdb_write_bit_vector(MSF_Context *msf, MSF_StreamNumber sn, B32 *flag_array, U64 flag_count) { B32 is_write_ok = 0; U32 word_size = sizeof(U32); U32 bits_per_word = MSF_BITS_PER_CHAR * word_size; U32 word_count = (flag_count + MSF_BITS_PER_CHAR) / MSF_BITS_PER_CHAR; is_write_ok = msf_stream_write_struct(msf, sn, &word_count); if (is_write_ok) { for (U64 iword = 0, iflag = 0; iword < word_count; ++iword) { U32 word = 0; for (U64 iflag_opl = Min(flag_count, iflag + MSF_BITS_PER_CHAR); iflag < iflag_opl; ++iflag) { if (flag_array[iflag]) { word |= 1 << (iflag % bits_per_word); } } is_write_ok = msf_stream_write_struct(msf, sn, &word); if (!is_write_ok) { break; } } } return is_write_ok; } internal U64 pdb_get_bit_vector_size(U32 bucket_count) { U32 word_size = sizeof(U32); U32 word_count = (bucket_count + MSF_BITS_PER_CHAR) / MSF_BITS_PER_CHAR; U64 result = 0; result += sizeof(word_count); result += word_size * word_count; return result; } ================================================ FILE: src/linker/pdb_ext/pdb_helpers.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal U32 pdb_hash_v1(String8 data); internal U32 pdb_hash_udt(CV_UDTInfo udt_info, String8 data); internal U64 pdb_read_bit_vector_string(String8 data, U64 offset, U32Array *bits_out); internal U64 pdb_read_bit_vector_msf(Arena *arena, MSF_Context *msf, MSF_StreamNumber sn, U32Array *bits_out); internal B32 pdb_write_bit_vector(MSF_Context *msf, MSF_StreamNumber sn, B32 *flag_array, U64 flag_count); internal U64 pdb_get_bit_vector_size(U32 bucket_count); ================================================ FILE: src/linker/rdi/rdi_builder.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDIB_DataModel rdib_infer_data_model(OperatingSystem os, RDI_Arch arch) { RDIB_DataModel data_model = RDIB_DataModel_Null; switch (os) { case OperatingSystem_Null: break; case OperatingSystem_Windows: { switch (arch) { case RDI_Arch_X86: case RDI_Arch_X64: data_model = RDIB_DataModel_LLP64; break; default: NotImplemented; } } break; case OperatingSystem_Linux: { switch (arch) { case RDI_Arch_X86: data_model = RDIB_DataModel_ILP32; break; case RDI_Arch_X64: data_model = RDIB_DataModel_LLP64; break; default: NotImplemented; } } break; case OperatingSystem_Mac: { switch (arch) { case RDI_Arch_X86: NotImplemented; break; case RDI_Arch_X64: data_model = RDIB_DataModel_LP64; break; } } break; default: InvalidPath; } return data_model; } internal RDI_TypeKind rdib_short_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_S16; case RDIB_DataModel_LLP64 : return RDI_TypeKind_S16; case RDIB_DataModel_LP64 : return RDI_TypeKind_S16; case RDIB_DataModel_ILP64 : return RDI_TypeKind_S16; case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_unsigned_short_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_U16; case RDIB_DataModel_LLP64 : return RDI_TypeKind_U16; case RDIB_DataModel_LP64 : return RDI_TypeKind_U16; case RDIB_DataModel_ILP64 : return RDI_TypeKind_U16; case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_int_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_S32; case RDIB_DataModel_LLP64 : return RDI_TypeKind_S32; case RDIB_DataModel_LP64 : return RDI_TypeKind_S32; case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_unsigned_int_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; case RDIB_DataModel_LLP64 : return RDI_TypeKind_U32; case RDIB_DataModel_LP64 : return RDI_TypeKind_U32; case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_long_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_S32; case RDIB_DataModel_LLP64 : return RDI_TypeKind_S32; case RDIB_DataModel_LP64 : return RDI_TypeKind_S64; case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_unsigned_long_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; case RDIB_DataModel_LLP64 : return RDI_TypeKind_U32; case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_long_long_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_S64; case RDIB_DataModel_LLP64 : return RDI_TypeKind_S64; case RDIB_DataModel_LP64 : return RDI_TypeKind_S64; case RDIB_DataModel_ILP64 : return RDI_TypeKind_S64; case RDIB_DataModel_SILP64: return RDI_TypeKind_S64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_unsigned_long_long_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_U64; case RDIB_DataModel_LLP64 : return RDI_TypeKind_U64; case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; default: InvalidPath; } return RDI_TypeKind_NULL; } internal RDI_TypeKind rdib_pointer_size_t_type_from_data_model(RDIB_DataModel data_model) { switch (data_model) { case RDIB_DataModel_Null : break; case RDIB_DataModel_ILP32 : return RDI_TypeKind_U32; case RDIB_DataModel_LLP64 : return RDI_TypeKind_U64; case RDIB_DataModel_LP64 : return RDI_TypeKind_U64; case RDIB_DataModel_ILP64 : return RDI_TypeKind_U64; case RDIB_DataModel_SILP64: return RDI_TypeKind_U64; default: InvalidPath; } return RDI_TypeKind_NULL; } //////////////////////////////// internal void rdib_udt_member_list_push_node(RDIB_UDTMemberList *list, RDIB_UDTMember *node) { SLLQueuePushCount(list, node); } internal void rdib_udt_member_list_concat_in_place(RDIB_UDTMemberList *list, RDIB_UDTMemberList *to_concat) { SLLConcatInPlace(list, to_concat); } internal void rdib_line_table_push_fragment_node(RDIB_LineTable *list, RDIB_LineTableFragment *n) { SLLQueuePush_N(list->first, list->last, n, next_line_table); ++list->count; } internal RDIB_LineTableFragment * rdib_line_table_push(Arena *arena, RDIB_LineTable *list) { RDIB_LineTableFragment *n = push_array(arena, RDIB_LineTableFragment, 1); rdib_line_table_push_fragment_node(list, n); return n; } //////////////////////////////// internal RDIB_LineTableFragment * rdib_line_table_fragment_chunk_list_push(Arena *arena, RDIB_LineTableFragmentChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_LineTableFragment); return SLLChunkListLastItem(list); } internal RDIB_Unit * rdib_unit_chunk_list_push(Arena *arena, RDIB_UnitChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_Unit); return SLLChunkListLastItem(list); } internal RDIB_Scope * rdib_scope_chunk_list_push(Arena *arena, RDIB_ScopeChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_Scope); return SLLChunkListLastItem(list); } internal RDIB_Procedure * rdib_procedure_chunk_list_push(Arena *arena, RDIB_ProcedureChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_Procedure); return SLLChunkListLastItem(list); } internal RDIB_Variable * rdib_variable_chunk_list_push(Arena *arena, RDIB_VariableChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_Variable); return SLLChunkListLastItem(list); } internal RDIB_LineTable * rdib_line_table_chunk_list_push(Arena *arena, RDIB_LineTableChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_LineTable); return SLLChunkListLastItem(list); } internal RDIB_Type * rdib_type_chunk_list_push(Arena *arena, RDIB_TypeChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_Type); RDIB_Type *type = SLLChunkListLastItem(list); type->final_idx = 0; return type; } internal RDIB_UDTMember * rdib_udt_member_chunk_list_push(Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_UDTMember); return SLLChunkListLastItem(list); } internal RDIB_SourceFile * rdib_source_file_chunk_list_push(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_SourceFile); return SLLChunkListLastItem(list); } internal RDIB_InlineSite * rdib_inline_site_chunk_list_push(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap) { SLLChunkListPush(arena, list, cap, RDIB_InlineSite); return SLLChunkListLastItem(list); } internal RDIB_Unit * rdib_unit_chunk_list_push_zero(Arena *arena, RDIB_UnitChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_Unit); return SLLChunkListLastItem(list); } internal RDIB_Scope * rdib_scope_chunk_list_push_zero(Arena *arena, RDIB_ScopeChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_Scope); return SLLChunkListLastItem(list); } internal RDIB_Procedure * rdib_procedure_chunk_list_push_zero(Arena *arena, RDIB_ProcedureChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_Procedure); return SLLChunkListLastItem(list); } internal RDIB_Variable * rdib_variable_chunk_list_push_zero(Arena *arena, RDIB_VariableChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_Variable); return SLLChunkListLastItem(list); } internal RDIB_LineTable * rdib_line_table_chunk_list_push_zero(Arena *arena, RDIB_LineTableChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_LineTable); return SLLChunkListLastItem(list); } internal RDIB_Type * rdib_type_chunk_list_push_zero(Arena *arena, RDIB_TypeChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_Type); return SLLChunkListLastItem(list); } internal RDIB_UDTMember * rdib_udt_member_chunk_list_push_zero(Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_UDTMember); return SLLChunkListLastItem(list); } internal RDIB_SourceFile * rdib_source_file_chunk_list_push_zero(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_SourceFile); return SLLChunkListLastItem(list); } internal RDIB_InlineSite * rdib_inline_site_chunk_list_push_zero(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap) { SLLChunkListPushZero(arena, list, cap, RDIB_InlineSite); return SLLChunkListLastItem(list); } internal RDIB_UnitChunk * rdib_unit_chunk_list_reserve_ex(Arena *arena, RDIB_UnitChunkList *list, U64 count_per_chunk, U64 item_count) { U64 chunk_count = CeilIntegerDiv(item_count, count_per_chunk); RDIB_UnitChunk *chunks = push_array(arena, RDIB_UnitChunk, chunk_count); U64 base = list->last ? list->last->base : 0; for (U64 i = 0; i+1 < chunk_count; i += 1, item_count -= count_per_chunk, base += count_per_chunk) { chunks[i].base = base; chunks[i].count = count_per_chunk; chunks[i].cap = count_per_chunk; chunks[i].v = push_array(arena, RDIB_Unit, count_per_chunk); SLLQueuePush(list->first, list->last, &chunks[i]); for (U64 k = 0; k < count_per_chunk; ++k) { chunks[i].v[k].chunk = &chunks[i]; } } chunks[chunk_count-1].base = base; chunks[chunk_count-1].count = item_count; chunks[chunk_count-1].cap = item_count; chunks[chunk_count-1].v = push_array(arena, RDIB_Unit, item_count); for (U64 k = 0; k < item_count; ++k) { chunks[chunk_count-1].v[k].chunk = &chunks[chunk_count-1]; } SLLQueuePush(list->first, list->last, &chunks[chunk_count-1]); list->count += chunk_count; return chunks; } internal void rdib_unit_chunk_list_reserve(Arena *arena, RDIB_UnitChunkList *list, U64 cap) { // fill out node RDIB_UnitChunk *chunk = push_array(arena, RDIB_UnitChunk, 1); chunk->cap = cap; chunk->v = push_array(arena, RDIB_Unit, cap); // push node to list SLLQueuePush(list->first, list->last, chunk); list->count += 1; } internal void rdib_type_chunk_list_reserve(Arena *arena, RDIB_TypeChunkList *list, U64 cap) { // fill out node RDIB_TypeChunk *chunk = push_array(arena, RDIB_TypeChunk, 1); chunk->cap = cap; chunk->v = push_array(arena, RDIB_Type, cap); // push node to list SLLQueuePush(list->first, list->last, chunk); list->count += 1; } internal void rdib_source_file_list_reserve(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap) { // fill out node RDIB_SourceFileChunk *chunk = push_array(arena, RDIB_SourceFileChunk, 1); chunk->cap = cap; chunk->v = push_array(arena, RDIB_SourceFile, cap); // push node to list SLLQueuePush(list->first, list->last, chunk); list->count += 1; } internal void rdib_unit_chunk_list_concat_in_place(RDIB_UnitChunkList *list, RDIB_UnitChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_UnitChunk); } internal void rdib_scope_chunk_list_concat_in_place(RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_ScopeChunk); } internal void rdib_udt_member_chunk_list_concat_in_place(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_UDTMemberChunk); } internal void rdib_procedure_chunk_list_concat_in_place(RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_ProcedureChunk); } internal void rdib_variable_chunk_list_concat_in_place(RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_VariableChunk); } internal void rdib_line_table_chunk_list_concat_in_place(RDIB_LineTableChunkList *list, RDIB_LineTableChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_LineTableChunk); } internal void rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_InlineSiteChunk); } internal void rdib_type_chunk_list_concat_in_place(RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_TypeChunk); } internal void rdib_source_file_chunk_list_concat_in_place(RDIB_SourceFileChunkList *list, RDIB_SourceFileChunkList *to_concat) { SLLConcatInPlaceChunkList(list, to_concat, RDIB_SourceFileChunk); } internal void rdib_line_table_chunk_list_concat_in_place_many(RDIB_LineTableChunkList *list, RDIB_LineTableChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_LineTableChunk, count); } internal void rdib_scope_chunk_list_concat_in_place_many(RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_ScopeChunk, count); } internal void rdib_variable_chunk_list_concat_in_place_many(RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_VariableChunk, count); } internal void rdib_procedure_chunk_list_concat_in_place_many(RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_ProcedureChunk, count); } internal void rdib_inline_site_chunk_list_concat_in_place_many(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_InlineSiteChunk, count); } internal void rdib_type_chunk_list_concat_in_place_many(RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_TypeChunk, count); } internal void rdib_udt_member_chunk_list_concat_in_place_many(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat, U64 count) { SLLConcatInPlaceChunkListArray(list, to_concat, RDIB_UDTMemberChunk, count); } internal RDIB_UnitChunk ** rdib_array_from_unit_chunk_list(Arena *arena, RDIB_UnitChunkList list) { ProfBeginFunction(); RDIB_UnitChunk **result = push_array_no_zero(arena, RDIB_UnitChunk *, list.count); U64 chunk_idx = 0; for (RDIB_UnitChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_ScopeChunk ** rdib_array_from_scope_chunk_list(Arena *arena, RDIB_ScopeChunkList list) { ProfBeginFunction(); RDIB_ScopeChunk **result = push_array_no_zero(arena, RDIB_ScopeChunk *, list.count); U64 chunk_idx = 0; for (RDIB_ScopeChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_VariableChunk ** rdib_array_from_variable_chunk_list(Arena *arena, RDIB_VariableChunkList list) { ProfBeginFunction(); RDIB_VariableChunk **result = push_array_no_zero(arena, RDIB_VariableChunk *, list.count); U64 chunk_idx = 0; for (RDIB_VariableChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_LineTableChunk ** rdib_array_from_line_table_chunk_list(Arena *arena, RDIB_LineTableChunkList list) { ProfBeginFunction(); RDIB_LineTableChunk **result = push_array_no_zero(arena, RDIB_LineTableChunk *, list.count); U64 chunk_idx = 0; for (RDIB_LineTableChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_ProcedureChunk ** rdib_array_from_procedure_chunk_list(Arena *arena, RDIB_ProcedureChunkList list) { ProfBeginFunction(); RDIB_ProcedureChunk **result = push_array_no_zero(arena, RDIB_ProcedureChunk *, list.count); U64 chunk_idx = 0; for (RDIB_ProcedureChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_InlineSiteChunk ** rdib_array_from_inline_site_chunk_list(Arena *arena, RDIB_InlineSiteChunkList list) { ProfBeginFunction(); RDIB_InlineSiteChunk **result = push_array_no_zero(arena, RDIB_InlineSiteChunk *, list.count); U64 chunk_idx = 0; for (RDIB_InlineSiteChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_UDTMemberChunk ** rdib_array_from_udt_member_chunk_list(Arena *arena, RDIB_UDTMemberChunkList list) { ProfBeginFunction(); RDIB_UDTMemberChunk **result = push_array_no_zero(arena, RDIB_UDTMemberChunk *, list.count); U64 chunk_idx = 0; for (RDIB_UDTMemberChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_TypeChunk ** rdib_array_from_type_chunk_list(Arena *arena, RDIB_TypeChunkList list) { ProfBeginFunction(); RDIB_TypeChunk **result = push_array_no_zero(arena, RDIB_TypeChunk *, list.count); U64 chunk_idx = 0; for (RDIB_TypeChunk *chunk = list.first; chunk != 0; chunk = chunk->next, ++chunk_idx) { result[chunk_idx] = chunk; } ProfEnd(); return result; } internal RDIB_SourceFileChunk ** rdib_array_from_source_file_chunk_list(Arena *arena, RDIB_SourceFileChunkList list) { ProfBeginFunction(); RDIB_SourceFileChunk **result = push_array_no_zero(arena, RDIB_SourceFileChunk *, list.count); U64 chunk_idx = 0; for (RDIB_SourceFileChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { result[chunk_idx++] = chunk; } ProfEnd(); return result; } internal U64 rdib_unit_chunk_list_total_count(RDIB_UnitChunkList list) { U64 total_count = 0; for (RDIB_UnitChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_scope_chunk_list_total_count(RDIB_ScopeChunkList list) { U64 total_count = 0; for (RDIB_ScopeChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_variable_chunk_list_total_count(RDIB_VariableChunkList list) { U64 total_count = 0; for (RDIB_VariableChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_line_table_chunk_list_total_count(RDIB_LineTableChunkList list) { U64 total_count = 0; for (RDIB_LineTableChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_procedure_chunk_list_total_count(RDIB_ProcedureChunkList list) { U64 total_count = 0; for (RDIB_ProcedureChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_inline_site_chunk_list_total_count(RDIB_InlineSiteChunkList list) { U64 total_count = 0; for (RDIB_InlineSiteChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_udt_member_chunk_list_total_count(RDIB_UDTMemberChunkList list) { U64 total_count = 0; for (RDIB_UDTMemberChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_type_chunk_list_total_count(RDIB_TypeChunkList list) { U64 total_count = 0; for (RDIB_TypeChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U64 rdib_source_file_chunk_list_total_count(RDIB_SourceFileChunkList list) { U64 total_count = 0; for (RDIB_SourceFileChunk *chunk = list.first; chunk != 0; chunk = chunk->next) { total_count += chunk->count; } return total_count; } internal U32 rdib_idx_from_unit(RDIB_Unit *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_scope(RDIB_Scope *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_inline_site(RDIB_InlineSite *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_variable(RDIB_Variable *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_procedure(RDIB_Procedure *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_source_file(RDIB_SourceFile *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_line_table(RDIB_LineTable *n) { U32 idx = 0; if (n) { Assert(n->chunk->v <= n && n < (n->chunk->v + n->chunk->count)); idx = safe_cast_u32(n->chunk->base + (n - n->chunk->v)); Assert(idx - n->chunk->base < n->chunk->count); } return idx; } internal U32 rdib_idx_from_type(RDIB_Type *n) { U32 idx = 0; if (n) { idx = safe_cast_u32(n->final_idx); } return idx; } internal U32 rdib_idx_from_udt_type(RDIB_Type *n) { U32 idx = 0; if (n && RDI_IsUserDefinedType(n->kind)) { idx = safe_cast_u32(n->udt.udt_idx); } return idx; } //////////////////////////////// // Source File internal B32 rdib_source_file_match(RDIB_SourceFile *a, RDIB_SourceFile *b, OperatingSystem os) { StringMatchFlags match_flags = path_match_flags_from_os(os); if (str8_match(a->normal_full_path, b->normal_full_path, match_flags)) { if (a->checksum_kind == b->checksum_kind) { if (str8_match(a->checksum, b->checksum, 0)) { return 1; } } } return 0; } //////////////////////////////// // Eval Ops internal RDIB_EvalBytecodeOp * rdib_bytecode_push_op(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p) { RDIB_EvalBytecodeOp *node = push_array(arena, RDIB_EvalBytecodeOp, 1); node->op = op; node->p_size = RDI_DECODEN_FROM_CTRLBITS(rdi_eval_op_ctrlbits_table[op]); node->p = p; SLLQueuePush(bytecode->first, bytecode->last, node); bytecode->count += 1; bytecode->size += 1 + node->p_size; return node; } internal void rdib_bytecode_push_ucsont(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_U64 uconst) { if (uconst <= max_U8) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, uconst); } else if (uconst <= max_U16) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, uconst); } else if (uconst <= max_U32) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, uconst); } else { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, uconst); } } internal void rdib_bytecode_push_sconst(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_S64 sconst) { if (min_S8 <= sconst && sconst <= max_S8) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU8, (RDI_U64)sconst); rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 8); } else if (min_S16 <= sconst && sconst <= max_S16) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU16, (RDI_U64)sconst); rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_TruncSigned, 16); } else if (min_S32 <= sconst && sconst <= max_S32) { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU32, (RDI_U64)sconst); } else { rdib_bytecode_push_op(arena, bytecode, RDI_EvalOp_ConstU64, (RDI_U64)sconst); } } //////////////////////////////// // Location internal RDIB_Location rdib_make_location_addr_byte_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) { RDIB_Location loc = {0}; loc.ranges = ranges; loc.kind = RDI_LocationKind_AddrBytecodeStream; loc.bytecode = bytecode; return loc; } internal RDIB_Location rdib_make_location_addr_bytecode_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) { RDIB_Location loc = {0}; loc.ranges = ranges; loc.kind = RDI_LocationKind_AddrBytecodeStream; loc.bytecode = bytecode; return loc; } internal RDIB_Location rdib_make_location_val_bytecode_stream(Rng1U64List ranges, RDIB_EvalBytecode bytecode) { RDIB_Location loc = {0}; loc.ranges = ranges; loc.kind = RDI_LocationKind_ValBytecodeStream; loc.bytecode = bytecode; return loc; } internal RDIB_Location rdib_make_location_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset) { RDIB_Location loc = {0}; loc.ranges = ranges; loc.kind = RDI_LocationKind_AddrRegPlusU16; loc.reg_code = reg_code; loc.offset = offset; return loc; } internal RDIB_Location rdib_make_location_addr_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset) { RDIB_Location loc = {0}; loc.kind = RDI_LocationKind_AddrAddrRegPlusU16; loc.ranges = ranges; loc.reg_code = reg_code; loc.offset = offset; return loc; } internal RDIB_Location rdib_make_location_val_reg(Rng1U64List ranges, RDI_RegCode reg_code) { RDIB_Location loc = {0}; loc.kind = RDI_LocationKind_ValReg; loc.ranges = ranges; loc.reg_code = reg_code; return loc; } internal RDIB_LocationNode * rdib_location_list_push(Arena *arena, RDIB_LocationList *list, RDIB_Location v) { RDIB_LocationNode *node = push_array(arena, RDIB_LocationNode, 1); node->v = v; SLLQueuePush(list->first, list->last, node); ++list->count; return node; } internal RDIB_LocationNode * rdib_push_location_addr_reg_off(Arena *arena, RDIB_LocationList *list, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 is_reference, Rng1U64List ranges) { RDIB_Location loc; if (0 <= offset && offset <= (S64)max_U16) { if (is_reference) { loc = rdib_make_location_addr_addr_reg_plus_u16(ranges, reg_code, (U16)offset); } else { loc = rdib_make_location_addr_reg_plus_u16(ranges, reg_code, (U16)offset); } } // long offset, emit byte code else { RDIB_EvalBytecode bytecode = {0}; U32 reg_read_param = RDI_EncodeRegReadParam(reg_code, reg_byte_size, reg_byte_pos); rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_RegRead, reg_read_param); rdib_bytecode_push_sconst(arena, &bytecode, offset); rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_Add, 0); if (is_reference) { U64 addr_size = rdi_addr_size_from_arch(arch); rdib_bytecode_push_op(arena, &bytecode, RDI_EvalOp_MemRead, addr_size); } loc = rdib_make_location_addr_bytecode_stream(ranges, bytecode); } RDIB_LocationNode *node = rdib_location_list_push(arena, list, loc); return node; } internal void rdib_variable_list_push_node(RDIB_VariableList *list, RDIB_VariableNode *node) { SLLQueuePush(list->first, list->last, node); ++list->count; } internal RDIB_VariableNode * rdib_variable_list_push(Arena *arena, RDIB_VariableList *list) { RDIB_VariableNode *node = push_array(arena, RDIB_VariableNode, 1); rdib_variable_list_push_node(list, node); return node; } //////////////////////////////// // Types internal U64 rdib_size_from_type(RDIB_Type *type) { if (type) { switch (type->kind) { case RDI_TypeKind_Void: case RDI_TypeKind_Char8: case RDI_TypeKind_Char16: case RDI_TypeKind_Char32: case RDI_TypeKind_UChar8: case RDI_TypeKind_UChar16: case RDI_TypeKind_UChar32: case RDI_TypeKind_U8: case RDI_TypeKind_U16: case RDI_TypeKind_U32: case RDI_TypeKind_U64: case RDI_TypeKind_U128: case RDI_TypeKind_U256: case RDI_TypeKind_U512: case RDI_TypeKind_S8: case RDI_TypeKind_S16: case RDI_TypeKind_S32: case RDI_TypeKind_S64: case RDI_TypeKind_S128: case RDI_TypeKind_S256: case RDI_TypeKind_S512: case RDI_TypeKind_Bool: case RDI_TypeKind_F16: case RDI_TypeKind_F32: case RDI_TypeKind_F32PP: case RDI_TypeKind_F48: case RDI_TypeKind_F64: case RDI_TypeKind_F80: case RDI_TypeKind_F128: case RDI_TypeKind_ComplexF32: case RDI_TypeKind_ComplexF64: case RDI_TypeKind_ComplexF80: case RDI_TypeKind_ComplexF128: case RDI_TypeKind_Handle: return type->builtin.size; case RDI_TypeKind_Modifier: return rdib_size_from_type((RDIB_Type *)type->modifier.type_ref); case RDI_TypeKind_Ptr: case RDI_TypeKind_LRef: case RDI_TypeKind_RRef: return type->ptr.size; case RDI_TypeKind_Array: return type->array.size; case RDI_TypeKind_Function: case RDI_TypeKind_Method: case RDI_TypeKindExt_StaticMethod: { Assert(!"check"); return 0; } case RDI_TypeKind_Struct: case RDI_TypeKind_Class: case RDI_TypeKind_IncompleteStruct: case RDI_TypeKind_IncompleteClass: return type->udt.struct_type.size; case RDI_TypeKind_Union: case RDI_TypeKind_IncompleteUnion: return type->udt.union_type.size; case RDI_TypeKind_Alias: Assert(!"check"); case RDI_TypeKind_Enum: case RDI_TypeKind_IncompleteEnum: return rdib_size_from_type(type->udt.enum_type.base_type); case RDI_TypeKind_MemberPtr: case RDI_TypeKind_Bitfield: case RDI_TypeKind_Variadic: case RDI_TypeKindExt_Members: case RDI_TypeKindExt_Params: InvalidPath; // no size } } return 0; } internal RDIB_TypeRef rdib_make_type_ref(Arena *arena, RDIB_Type *type) { RDIB_Type **ref = push_array(arena, RDIB_Type *, 1); ref[0] = type; return ref; } internal void rdib_deref_type_refs(TP_Context *tp, RDIB_TypeChunkList *list) { for (RDIB_TypeChunk *chunk = list->first; chunk != 0; chunk = chunk->next) { for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; if (type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Class || type->kind == RDI_TypeKind_IncompleteStruct || type->kind == RDI_TypeKind_IncompleteClass) { type->udt.members = *(RDIB_Type **)type->udt.members; type->udt.struct_type.derived = *(RDIB_Type **)type->udt.struct_type.derived; type->udt.struct_type.vtshape = *(RDIB_Type **)type->udt.struct_type.vtshape; } else if (type->kind == RDI_TypeKind_Enum || type->kind == RDI_TypeKind_IncompleteEnum) { type->udt.members = *(RDIB_Type **)type->udt.members; type->udt.enum_type.base_type = *(RDIB_Type **)type->udt.enum_type.base_type; } else if (type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_IncompleteUnion) { type->udt.members = *(RDIB_Type **)type->udt.members; } else if (type->kind == RDI_TypeKind_Array) { type->array.entry_type = *(RDIB_Type **)type->array.entry_type; } else if (type->kind == RDI_TypeKind_Function) { type->func.return_type = *(RDIB_Type **)type->func.return_type; type->func.params_type = *(RDIB_Type **)type->func.params_type; } else if (type->kind == RDI_TypeKind_Method) { type->method.class_type = *(RDIB_Type **)type->method.class_type; type->method.this_type = *(RDIB_Type **)type->method.this_type; type->method.return_type = *(RDIB_Type **)type->method.return_type; type->method.params_type = *(RDIB_Type **)type->method.params_type; } else if (type->kind == RDI_TypeKindExt_StaticMethod) { type->static_method.class_type = *(RDIB_Type **)type->static_method.class_type; type->static_method.return_type = *(RDIB_Type **)type->static_method.return_type; type->static_method.params_type = *(RDIB_Type **)type->static_method.params_type; } else if (type->kind == RDI_TypeKind_Ptr || type->kind == RDI_TypeKind_LRef || type->kind == RDI_TypeKind_RRef) { type->ptr.type_ref = *(RDIB_Type **)type->ptr.type_ref; } else if (type->kind == RDI_TypeKind_Modifier) { type->modifier.type_ref = *(RDIB_Type **)type->modifier.type_ref; } else if (type->kind == RDI_TypeKind_Bitfield) { type->bitfield.value_type = *(RDIB_Type **)type->bitfield.value_type; } else if (type->kind == RDI_TypeKindExt_Params) { for (U64 i = 0; i < type->params.count; ++i) { type->params.types[i] = *(RDIB_Type **)type->params.types[i]; } } else if (type->kind == RDI_TypeKindExt_Members) { for (RDIB_UDTMember *member = type->members.list.first; member != 0; member = member->next) { switch (member->kind) { case RDI_MemberKind_NULL: break; case RDI_MemberKind_DataField: { member->data_field.type_ref = *(RDIB_Type **)member->data_field.type_ref; } break; case RDI_MemberKind_StaticData: { member->static_data.type_ref = *(RDIB_Type **)member->static_data.type_ref; } break; case RDI_MemberKind_Method: { member->method.type_ref = *(RDIB_Type **)member->method.type_ref; } break; case RDI_MemberKind_NestedType: { member->nested_type.type_ref = *(RDIB_Type **)member->nested_type.type_ref; } break; case RDI_MemberKind_Base: { member->base_class.type_ref = *(RDIB_Type **)member->base_class.type_ref; } break; case RDI_MemberKind_VirtualBase: { member->virtual_base_class.type_ref = *(RDIB_Type **)member->virtual_base_class.type_ref; } break; case RDI_MemberKindExt_MemberListPointer: { member->member_list_pointer = *(RDIB_Type **)member->member_list_pointer; } break; #if 0 case RDI_MemberKind_Enumerate: { // no types } break; #endif default: InvalidPath; } } } } } } internal U64 rdib_sizeof_type(RDIB_Type *type) { U64 size = 0; if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind < RDI_TypeKind_LastBuiltIn) { size = type->builtin.size; } else if (type->kind == RDI_TypeKind_Modifier) { size = rdib_sizeof_type(type->modifier.type_ref); } else if (type->kind == RDI_TypeKind_Ptr || type->kind == RDI_TypeKind_LRef || type->kind == RDI_TypeKind_RRef) { size = type->ptr.size; } else if (type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Class || type->kind == RDI_TypeKind_IncompleteStruct || type->kind == RDI_TypeKind_IncompleteClass) { size = type->udt.struct_type.size; } else if (type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_IncompleteUnion) { size = type->udt.union_type.size; } else if (type->kind == RDI_TypeKind_Enum || type->kind == RDI_TypeKind_IncompleteEnum) { size = rdib_sizeof_type(type->udt.enum_type.base_type); } else if (type->kind == RDI_TypeKind_Bitfield) { size = rdib_sizeof_type(type->bitfield.value_type); } else if (type->kind == RDI_TypeKind_Array) { size = type->array.size; } else { Assert(!"error: type doens't have a size"); } return size; } internal U64 rdib_count_members_deep(RDIB_Type *type) { U64 member_count = 0; for (RDIB_UDTMember *member = type->members.list.first; member != 0; member = member->next) { if (member->kind == RDI_MemberKindExt_MemberListPointer) { member_count += rdib_count_members_deep(member->member_list_pointer); } else { member_count += 1; } } return member_count; } internal THREAD_POOL_TASK_FUNC(rdib_type_stats_task) { ProfBeginFunction(); RDIB_TypeStatsTask *task = raw_task; RDIB_TypeChunk *chunk = task->chunks[task_id]; for (U64 itype = 0; itype < chunk->count; ++itype) { RDIB_Type *type = chunk->v + itype; if (type->kind == RDI_TypeKind_Class || type->kind == RDI_TypeKind_Struct || type->kind == RDI_TypeKind_Union || type->kind == RDI_TypeKind_Enum) { task->type_stats->udt_counts[task_id] += 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_concat_members_task) { ProfBeginFunction(); RDIB_MembersTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; RDIB_UDTMemberList acc = {0}; for (RDIB_Type *curr = type; ;) { // concat members rdib_udt_member_list_concat_in_place(&acc, &curr->members.list); // does this type continue member list? if (acc.count == 0 || acc.last->kind != RDI_MemberKindExt_MemberListPointer) { break; } // remove member list pointer RDIB_UDTMember *continuation = acc.last; SLLQueuePop(acc.first, acc.last); --acc.count; // advance to next type curr = continuation->member_list_pointer; // other types should not reference any part of member list except for head type. Assert(curr->kind == RDI_TypeKindExt_Members); curr->kind = RDI_TypeKind_NULL; } // update member list type->members.list = acc; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_count_head_members_task) { ProfBeginFunction(); RDIB_MembersTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; if (type->kind == RDI_TypeKindExt_Members) { task->counts[task_id] += type->members.list.count; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_assign_head_member_indices_task) { ProfBeginFunction(); RDIB_MembersTask *task = raw_task; U64 cursor = task->offsets[task_id]; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_TypeChunk *chunk = task->type_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; if (type->kind == RDI_TypeKindExt_Members) { type->members.first_member_idx = cursor; cursor += type->members.list.count; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_udt_members_task) { ProfBeginFunction(); RDIB_MembersTask *task = raw_task; RDIB_TypeChunk *chunk = task->type_chunks[task_id]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = chunk->v + i; Assert(type->kind == RDI_TypeKindExt_Members); U64 member_idx = 0; for (RDIB_UDTMember *src = type->members.list.first; src != 0; src = src->next, ++member_idx) { U64 idx = type->members.first_member_idx + member_idx; RDI_Member *dst = &task->udt_members_rdi[idx]; switch (src->kind) { case RDI_MemberKind_NULL: { MemoryZeroStruct(dst); } break; case RDI_MemberKind_DataField: { dst->kind = RDI_MemberKind_DataField; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->data_field.name); dst->type_idx = rdib_idx_from_type(src->data_field.type_ref); dst->off = src->data_field.offset; } break; case RDI_MemberKind_StaticData: { dst->kind = RDI_MemberKind_StaticData; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->static_data.name); dst->type_idx = rdib_idx_from_type(src->static_data.type_ref); } break; case RDI_MemberKind_Method: case RDI_MemberKind_StaticMethod: case RDI_MemberKind_VirtualMethod: { dst->kind = src->kind; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->method.name); dst->type_idx = rdib_idx_from_type(src->method.type_ref); dst->off = src->method.vftable_offset; } break; case RDI_MemberKind_Base: { dst->kind = RDI_MemberKind_Base; dst->name_string_idx = 0; dst->type_idx = rdib_idx_from_type(src->base_class.type_ref); dst->off = src->base_class.offset; } break; case RDI_MemberKind_VirtualBase: { dst->kind = RDI_MemberKind_VirtualBase; dst->name_string_idx = 0; dst->type_idx = rdib_idx_from_type(src->virtual_base_class.type_ref); dst->off = 0; // TODO: ??? } break; case RDI_MemberKind_NestedType: { dst->kind = RDI_MemberKind_NestedType; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->nested_type.name); dst->type_idx = rdib_idx_from_type(src->nested_type.type_ref); dst->off = 0; } break; case RDI_MemberKindExt_MemberListPointer: { InvalidPath; } break; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_enum_members_task) { ProfBeginFunction(); RDIB_MembersTask *task = raw_task; RDIB_TypeChunk *chunk = task->type_chunks[task_id]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = chunk->v + i; if (type->kind != RDI_TypeKindExt_Members) continue; U64 member_idx = 0; for (RDIB_UDTMember *src = type->members.list.first; src != 0; src = src->next, ++member_idx) { U64 idx = type->members.first_member_idx + member_idx; RDI_EnumMember *dst = &task->enum_members_rdi[idx]; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->enumerate.name); dst->val = src->enumerate.value; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_udts_task) { ProfBeginFunction(); RDIB_UserDefinesTask *task = raw_task; U64 ichunk = task_id; RDIB_TypeChunk *chunk = task->type_chunks[ichunk]; U64 udt_cursor = task->udt_base_idx[ichunk]; U64 udt_cap = task->type_stats.udt_counts[ichunk]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; if (RDI_IsCompleteUserDefinedTypeKind(type->kind)) { RDIB_Type *members_type = type->udt.members; // assign UDT idx type->udt.udt_idx = udt_cursor; // fill out struct/class UDT Assert(udt_cursor < task->udt_base_idx[ichunk] + udt_cap); RDI_UDT *udt = &task->udts[udt_cursor++]; udt->self_type_idx = rdib_idx_from_type(type); udt->flags = type->kind == RDI_TypeKind_Enum ? RDI_UDTFlag_EnumMembers : 0; if (members_type->members.list.count > 0) { udt->member_first = members_type->members.first_member_idx; udt->member_count = members_type->members.list.count; } else { udt->member_first = 0; udt->member_count = 0; } udt->file_idx = 0; udt->line = 0; udt->col = 0; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_type_nodes_task) { Temp scratch = scratch_begin(0, 0); U64 ichunk = task_id; RDIB_TypeNodesTask *task = raw_task; RDIB_TypeChunk *chunk = task->type_chunks[ichunk]; for (U64 itype = 0; itype < chunk->count; ++itype) { RDIB_Type *src = &chunk->v[itype]; U64 dst_idx = rdib_idx_from_type(src); RDI_TypeNode *dst = &task->type_nodes[dst_idx]; if (src->kind == RDI_TypeKind_NULL) { MemoryZeroStruct(dst); dst->kind = RDI_TypeKind_NULL; } else if (RDI_TypeKind_FirstBuiltIn <= src->kind && src->kind <= RDI_TypeKind_LastBuiltIn) { dst->kind = src->kind; dst->flags = 0; dst->byte_size = src->builtin.size; dst->built_in.name_string_idx = rdib_idx_from_string_map(task->string_map, src->builtin.name); } else if (src->kind == RDI_TypeKind_Modifier) { dst->kind = RDI_TypeKind_Modifier; dst->byte_size = rdib_sizeof_type(src->modifier.type_ref); dst->flags = src->modifier.flags; dst->constructed.direct_type_idx = rdib_idx_from_type(src->modifier.type_ref); } else if (src->kind == RDI_TypeKind_Ptr || src->kind == RDI_TypeKind_LRef || src->kind == RDI_TypeKind_RRef) { dst->kind = src->kind; dst->byte_size = src->ptr.size; dst->flags = 0; dst->constructed.direct_type_idx = rdib_idx_from_type(src->ptr.type_ref); } else if (src->kind == RDI_TypeKind_Method) { RDIB_Type *params_type = src->method.params_type; Assert(params_type->kind == RDI_TypeKindExt_Params); RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->method.param_idx_run_bucket_idx]; dst->kind = RDI_TypeKind_Method; dst->flags = 0; dst->byte_size = 0; dst->constructed.direct_type_idx = rdib_idx_from_type(src->method.return_type); dst->constructed.count = param_idx_run->indices.count; dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; } else if (src->kind == RDI_TypeKindExt_StaticMethod) { RDIB_Type *params_type = src->static_method.params_type; Assert(params_type->kind == RDI_TypeKindExt_Params); RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->static_method.param_idx_run_bucket_idx]; dst->kind = RDI_TypeKind_Method; dst->flags = 0; dst->byte_size = 0; dst->constructed.direct_type_idx = rdib_idx_from_type(src->static_method.return_type); dst->constructed.count = param_idx_run->indices.count; dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; } else if (src->kind == RDI_TypeKind_Function) { RDIB_Type *params_type = src->func.params_type; Assert(params_type->kind == RDI_TypeKindExt_Params); RDIB_IndexRunBucket *param_idx_run = task->idx_run_map->buckets[src->func.param_idx_run_bucket_idx]; dst->kind = RDI_TypeKind_Function; dst->flags = 0; dst->byte_size = 0; dst->constructed.direct_type_idx = rdib_idx_from_type(src->func.return_type); dst->constructed.count = param_idx_run->indices.count; dst->constructed.param_idx_run_first = param_idx_run->index_in_output_array; } else if (src->kind == RDI_TypeKind_Array) { U64 entry_size = rdib_size_from_type(src->array.entry_type); U64 array_size = src->array.size; U64 array_count = entry_size > 0 ? array_size / entry_size : 0; dst->kind = src->kind; dst->flags = 0; dst->byte_size = array_size; dst->constructed.direct_type_idx = rdib_idx_from_type(src->array.entry_type); dst->constructed.count = array_count; } else if (src->kind == RDI_TypeKind_Bitfield) { dst->kind = RDI_TypeKind_Bitfield; dst->flags = 0; dst->byte_size = rdib_sizeof_type(src->bitfield.value_type); dst->bitfield.direct_type_idx = rdib_idx_from_type(src->bitfield.value_type); dst->bitfield.off = src->bitfield.off; dst->bitfield.size = src->bitfield.count; } else if (src->kind == RDI_TypeKind_Struct || src->kind == RDI_TypeKind_Class || src->kind == RDI_TypeKind_IncompleteStruct || src->kind == RDI_TypeKind_IncompleteClass) { dst->kind = src->kind; dst->flags = 0; dst->byte_size = src->udt.struct_type.size; dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); dst->user_defined.udt_idx = src->udt.udt_idx; dst->user_defined.direct_type_idx = 0; } else if (src->kind == RDI_TypeKind_Union || src->kind == RDI_TypeKind_IncompleteUnion) { dst->kind = src->kind; dst->flags = 0; dst->byte_size = src->udt.union_type.size; dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); dst->user_defined.udt_idx = src->udt.udt_idx; dst->user_defined.direct_type_idx = 0; } else if (src->kind == RDI_TypeKind_Enum || src->kind == RDI_TypeKind_IncompleteEnum) { dst->kind = RDI_TypeKind_Enum; dst->flags = 0; dst->byte_size = rdib_size_from_type(src->udt.enum_type.base_type); dst->user_defined.name_string_idx = rdib_idx_from_string_map(task->string_map, src->udt.name); dst->user_defined.udt_idx = src->udt.udt_idx; dst->user_defined.direct_type_idx = rdib_idx_from_type(src->udt.enum_type.base_type); } else if (src->kind == RDI_TypeKind_Alias) { // TODO NotImplemented; } else if (src->kind == RDI_TypeKind_MemberPtr) { // TODO NotImplemented; } else if (src->kind == RDI_TypeKind_Variadic) { MemoryZeroStruct(dst); dst->kind = RDI_TypeKind_Variadic; } else if (src->kind == RDI_TypeKindExt_VirtualTable) { // TODO MemoryZeroStruct(dst); dst->kind = RDI_TypeKind_NULL; } else { InvalidPath; } } scratch_end(scratch); } internal void rdib_data_sections_from_types(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDI_Arch arch, RDIB_StringMap *string_map, RDIB_IndexRunMap *idx_run_map, U64 udt_member_chunk_count, RDIB_TypeChunk **udt_member_type_chunks, U64 enum_member_chunk_count, RDIB_TypeChunk **enum_member_type_chunks, U64 total_type_node_count, U64 type_chunk_count, RDIB_TypeChunk **type_chunks, RDIB_TypeStats type_stats) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); ProfBegin("UDT Members"); U64 udt_member_count_rdi; RDI_Member *udt_members_rdi; { RDIB_MembersTask task = {0}; ProfBegin("Concat"); task.ranges = tp_divide_work(scratch.arena, udt_member_chunk_count, tp->worker_count); task.type_chunks = udt_member_type_chunks; tp_for_parallel(tp, 0, tp->worker_count, rdib_concat_members_task, &task); ProfEnd(); ProfBegin("Count"); task.counts = push_array(scratch.arena, U64, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_count_head_members_task, &task); ProfEnd(); ProfBegin("Assign Indices"); task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_assign_head_member_indices_task, &task); ProfEnd(); udt_member_count_rdi = sum_array_u64(tp->worker_count, task.counts); udt_members_rdi = push_array_no_zero(arena, RDI_Member, udt_member_count_rdi); ProfBegin("Fill"); task.string_map = string_map; task.udt_members_rdi = udt_members_rdi; tp_for_parallel(tp, 0, udt_member_chunk_count, rdib_fill_udt_members_task, &task); ProfEnd(); } ProfEnd(); ProfBegin("Enum Members"); U64 enum_member_count_rdi; RDI_EnumMember *enum_members_rdi; { RDIB_MembersTask task = {0}; ProfBegin("Concat"); task.ranges = tp_divide_work(scratch.arena, enum_member_chunk_count, tp->worker_count); task.type_chunks = enum_member_type_chunks; tp_for_parallel(tp, 0, tp->worker_count, rdib_concat_members_task, &task); ProfEnd(); ProfBegin("Count"); task.counts = push_array(scratch.arena, U64, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_count_head_members_task, &task); ProfEnd(); ProfBegin("Assign Indices"); task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_assign_head_member_indices_task, &task); ProfEnd(); enum_member_count_rdi = sum_array_u64(tp->worker_count, task.counts); enum_members_rdi = push_array_no_zero(arena, RDI_EnumMember, enum_member_count_rdi); ProfBegin("Fill"); task.string_map = string_map; task.enum_members_rdi = enum_members_rdi; tp_for_parallel(tp, 0, enum_member_chunk_count, rdib_fill_enum_members_task, &task); ProfEnd(); } ProfEnd(); ProfBegin("Sum type stats"); U64 total_udt_count = sum_array_u64(type_chunk_count, type_stats.udt_counts); ProfEnd(); ProfBegin("Up front pushes"); RDI_UDT *udts = push_array_no_zero(arena, RDI_UDT, total_udt_count ); RDI_TypeNode *type_nodes = push_array_no_zero(arena, RDI_TypeNode, total_type_node_count); ProfEnd(); ProfBegin("Fill out UDTs"); RDIB_UserDefinesTask udts_task = {0}; udts_task.type_chunks = type_chunks; udts_task.type_stats = type_stats; udts_task.udt_base_idx = offsets_from_counts_array_u64(scratch.arena, type_stats.udt_counts, type_chunk_count); udts_task.udts = udts; tp_for_parallel(tp, 0, type_chunk_count, rdib_fill_udts_task, &udts_task); ProfEnd(); ProfBegin("Fill out type nodes"); RDIB_TypeNodesTask type_nodes_task = {0}; type_nodes_task.addr_size = rdi_addr_size_from_arch(arch); type_nodes_task.string_map = string_map; type_nodes_task.idx_run_map = idx_run_map; type_nodes_task.type_chunks = type_chunks; type_nodes_task.type_stats = type_stats; type_nodes_task.type_nodes = type_nodes; tp_for_parallel(tp, 0, type_chunk_count, rdib_type_nodes_task, &type_nodes_task); ProfEnd(); RDIB_DataSection udt_member_sect = { .tag = RDI_SectionKind_Members }; RDIB_DataSection enum_member_sect = { .tag = RDI_SectionKind_EnumMembers }; RDIB_DataSection udt_sect = { .tag = RDI_SectionKind_UDTs }; RDIB_DataSection type_nodes_sect = { .tag = RDI_SectionKind_TypeNodes }; str8_list_push(arena, &udt_member_sect.data, str8_array(udt_members_rdi, udt_member_count_rdi )); str8_list_push(arena, &enum_member_sect.data, str8_array(enum_members_rdi, enum_member_count_rdi)); str8_list_push(arena, &udt_sect.data, str8_array(udts, total_udt_count )); str8_list_push(arena, &type_nodes_sect.data, str8_array(type_nodes, total_type_node_count)); rdib_data_section_list_push(arena, sect_list, enum_member_sect); rdib_data_section_list_push(arena, sect_list, udt_member_sect ); rdib_data_section_list_push(arena, sect_list, udt_sect ); rdib_data_section_list_push(arena, sect_list, type_nodes_sect ); scratch_end(scratch); ProfEnd(); } //////////////////////////////// internal RDIB_PathTree * rdib_path_tree_init(Arena *arena, U64 list_count) { RDIB_PathTree *tree = push_array(arena, RDIB_PathTree, 1); tree->root = push_array(arena, RDIB_PathTreeNode, 1); tree->list_count = list_count; tree->node_lists = push_array(arena, RDIB_PathTreeNodeList, list_count); return tree; } internal void rdib_path_tree_insert(Arena *arena, RDIB_PathTree *tree, String8 path, RDIB_SourceFile *src_file) { Temp scratch = scratch_begin(&arena, 1); RDIB_PathTreeNode *curr_sub_path = tree->root; String8List sub_paths = str8_split_path(scratch.arena, path); str8_path_list_resolve_dots_in_place(&sub_paths, path_style_from_str8(path)); for (String8Node *n = sub_paths.first; n != 0; n = n->next) { RDIB_PathTreeNode *sub_child; // is there directory or file defined on this level? for (sub_child = curr_sub_path->first_child; sub_child != 0; sub_child = sub_child->next_sibling) { if (str8_match(sub_child->sub_path, n->string, 0)) { break; } } // new directory/file if (sub_child == 0) { sub_child = push_array(arena, RDIB_PathTreeNode, 1); sub_child->node_idx = tree->node_count; sub_child->parent = curr_sub_path; sub_child->sub_path = n->string; sub_child->src_file = 0; SLLQueuePush_N(curr_sub_path->first_child, curr_sub_path->last_child, sub_child, next_sibling); ++tree->node_count; // last node, insert file if (n->next == 0) { sub_child->src_file = src_file; } // HACK: setup node list per thread for serialization step U64 list_idx = tree->next_list_idx % tree->list_count; SLLQueuePush_N(tree->node_lists[list_idx].first, tree->node_lists[list_idx].last, sub_child, next_order); ++tree->next_list_idx; } // descend to sub node curr_sub_path = sub_child; } scratch_end(scratch); } internal U32 rdib_idx_from_path_tree(RDIB_PathTree *tree, String8 path) { Temp scratch = scratch_begin(0,0); // redirect to special nil string if (path.size == 0) { path = RDIB_PATH_TREE_NIL_STRING; } // begin traverse from tree root RDIB_PathTreeNode *curr_sub_path = tree->root; // split path & resolve dots String8List sub_paths = str8_split_path(scratch.arena, path); str8_path_list_resolve_dots_in_place(&sub_paths, path_style_from_str8(path)); for (String8Node *n = sub_paths.first; n != 0; n = n->next) { // scan children sub-path match RDIB_PathTreeNode *sub_child; for (sub_child = curr_sub_path->first_child; sub_child != 0; sub_child = sub_child->next_sibling) { if (str8_match(sub_child->sub_path, n->string, 0)) { break; } } // found match? if (sub_child == 0) { break; } // descend to sub directory curr_sub_path = sub_child; } // did we find source file? U64 idx = 0; if (curr_sub_path != 0 && curr_sub_path->src_file != 0) { idx = curr_sub_path->node_idx; } else { Assert(!"unable to find source file path"); } scratch_end(scratch); return safe_cast_u32(idx); } //////////////////////////////// internal U64 rdib_string_map_hash(String8 string) { XXH64_hash_t hash64 = XXH3_64bits(string.str, string.size); return hash64; } internal RDIB_StringMap * rdib_init_string_map(Arena *arena, U64 cap) { RDIB_StringMap *string_map = push_array(arena, RDIB_StringMap, 1); string_map->cap = (U64)((F64)cap * 1.3); string_map->buckets = push_array(arena, RDIB_StringMapBucket *, string_map->cap); return string_map; } internal U32 rdib_idx_from_string_map(RDIB_StringMap *string_map, String8 string) { U64 hash = rdib_string_map_hash(string); U64 best_idx = hash % string_map->cap; U64 idx = best_idx; do { RDIB_StringMapBucket *bucket = string_map->buckets[idx]; if (bucket == 0) { break; } if (str8_match(bucket->string, string, 0)) { return safe_cast_u32(bucket->idx); } idx = (idx + 1) % string_map->cap; } while (idx != best_idx); Assert(!"incomplete string map"); return max_U32; } internal RDIB_StringMapBucket * rdib_string_map_insert_or_update(RDIB_StringMapBucket **buckets, U64 cap, U64 hash, RDIB_StringMapBucket *new_bucket, RDIB_StringMapUpdateFunc *update_func) { RDIB_StringMapBucket *result = 0; B32 was_bucket_inserted_or_updated = 0; U64 best_idx = hash % cap; U64 idx = best_idx; do { retry:; RDIB_StringMapBucket *curr_bucket = buckets[idx]; if (curr_bucket == 0) { RDIB_StringMapBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted was_bucket_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if (str8_match(curr_bucket->string, new_bucket->string, 0)) { if (curr_bucket->sorter.v <= new_bucket->sorter.v) { if (new_bucket->raw_values != 0) { void_node_concat_atomic(&curr_bucket->raw_values, new_bucket->raw_values); new_bucket->raw_values = 0; } // recycle bucket result = new_bucket; // don't need to update, more recent leaf is in the bucket was_bucket_inserted_or_updated = 1; break; } if (new_bucket->raw_values) { new_bucket->raw_values->next = buckets[idx]->raw_values; } RDIB_StringMapBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // recycle bucket result = compare_bucket; // new bucket is in the hash table, exit was_bucket_inserted_or_updated = 1; break; } if (new_bucket->raw_values) { new_bucket->raw_values->next = 0; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1) % cap; } while (idx != best_idx); // are there enough free buckets? Assert(was_bucket_inserted_or_updated); return result; } internal void rdib_string_map_insert_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, void *value) { // do we have a free bucket? RDIB_StringMapBucket **bucket = &task->free_buckets[task_id]; if (*bucket == 0) { *bucket = push_array(arena, RDIB_StringMapBucket, 1); } // fill out bucket (*bucket)->string = string; (*bucket)->raw_values = value; (*bucket)->sorter.hi = safe_cast_u32(task_id); (*bucket)->sorter.lo = safe_cast_u32(task->element_indices[task_id]); // insert bucket into string map U64 hash = rdib_string_map_hash(string); RDIB_StringMapBucket *insert_or_update = rdib_string_map_insert_or_update(task->string_map->buckets, task->string_map->cap, hash, *bucket, task->string_map_update_func); // advance element index if (insert_or_update != *bucket) { ++task->element_indices[task_id]; } // recycle bucket *bucket = insert_or_update; } internal THREAD_POOL_TASK_FUNC(rdib_count_extant_buckets_string_map_task) { ProfBeginFunction(); RDIB_GetExtantBucketsStringMapTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { if (task->string_map->buckets[bucket_idx] != 0) { task->counts[task_id] += 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_get_extant_buckets_string_map_task) { ProfBeginFunction(); RDIB_GetExtantBucketsStringMapTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min, cursor = task->offsets[task_id]; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_StringMapBucket *bucket = task->string_map->buckets[bucket_idx]; if (bucket != 0) { task->result[cursor] = bucket; ++cursor; } } ProfEnd(); } internal RDIB_StringMapBucket ** rdib_extant_buckets_from_string_map(TP_Context *tp, Arena *arena, RDIB_StringMap *string_map, U64 *bucket_count_out) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); RDIB_GetExtantBucketsStringMapTask task = {0}; task.string_map = string_map; ProfBegin("Count Extant Buckets"); task.counts = push_array(scratch.arena, U64, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, string_map->cap, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_count_extant_buckets_string_map_task, &task); ProfEnd(); *bucket_count_out = sum_array_u64(tp->worker_count, task.counts); ProfBegin("Copy Extant Buckets"); task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); task.result = push_array(arena, RDIB_StringMapBucket *, *bucket_count_out); tp_for_parallel(tp, 0, tp->worker_count, rdib_get_extant_buckets_string_map_task, &task); ProfEnd(); scratch_end(scratch); ProfEnd(); return task.result; } internal THREAD_POOL_TASK_FUNC(rdib_string_map_bucket_chunk_idx_histo_task) { ProfBeginFunction(); RDIB_StringMapRadixSort *task = raw_task; Temp scratch = scratch_begin(0,0); U32 *range_histo = push_array(scratch.arena, U32, task->chunk_idx_opl); // count items per sorter for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_StringMapBucket *bucket = task->src[bucket_idx]; U64 chunk_idx = bucket->sorter.hi; Assert(chunk_idx < task->chunk_idx_opl); ++range_histo[chunk_idx]; } // add in per thread sorter counts for (U64 i = 0; i < task->chunk_idx_opl; ++i) { ins_atomic_u32_add_eval(&task->chunk_histo[i], range_histo[i]); } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_string_map_radix_sort_chunk_idx_task) { ProfBeginFunction(); RDIB_StringMapRadixSort *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_StringMapBucket *bucket = task->src[bucket_idx]; U32 chunk_idx = bucket->sorter.hi; U32 dst_idx = ins_atomic_u32_inc_eval(&task->chunk_offsets[chunk_idx]) - 1; task->dst[dst_idx] = bucket; } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_string_map_radix_sort_element_idx_task) { ProfBeginFunction(); RDIB_StringMapRadixSort *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { U64 range_lo = task->chunk_offsets[chunk_idx]; U64 range_hi = task->chunk_offsets[chunk_idx] + task->chunk_histo[chunk_idx]; ProfBegin("Zero out Histogram"); U32 histo_bot[1 << 10]; MemoryZeroArray(histo_bot); U32 histo_mid[1 << 11]; MemoryZeroArray(histo_mid); U32 histo_top[1 << 11]; MemoryZeroArray(histo_top); ProfEnd(); ProfBegin("Element Histogram"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_StringMapBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit_bot = (elem_idx >> 0) % ArrayCount(histo_bot); U32 digit_mid = (elem_idx >> 10) % ArrayCount(histo_mid); U32 digit_top = (elem_idx >> 21) % ArrayCount(histo_top); histo_bot[digit_bot] += 1; histo_mid[digit_mid] += 1; histo_top[digit_top] += 1; } ProfEnd(); ProfBegin("Histogram Counts -> Offsets"); counts_to_offsets_array_u32(ArrayCount(histo_bot), &histo_bot[0]); counts_to_offsets_array_u32(ArrayCount(histo_mid), &histo_mid[0]); counts_to_offsets_array_u32(ArrayCount(histo_top), &histo_top[0]); ProfEnd(); ProfBegin("Sort Bot"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_StringMapBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 0) % ArrayCount(histo_bot); U32 src_idx = range_lo + histo_bot[digit]++; task->src[src_idx] = elem; } ProfEnd(); ProfBegin("Sort Mid"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_StringMapBucket *elem = task->src[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 10) % ArrayCount(histo_mid); U32 dst_idx = range_lo + histo_mid[digit]++; task->dst[dst_idx] = elem; } ProfEnd(); ProfBegin("Sort Top"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_StringMapBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 21) % ArrayCount(histo_top); U32 src_idx = range_lo + histo_top[digit]++; task->src[src_idx] = elem; } ProfEnd(); } ProfEnd(); } internal void rdib_string_map_sort_buckets(TP_Context *tp, RDIB_StringMapBucket **buckets, U64 bucket_count, U64 chunk_idx_opl) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); RDIB_StringMapRadixSort task = {0}; task.chunk_idx_opl = chunk_idx_opl; task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); task.src = buckets; task.dst = push_array_no_zero(scratch.arena, RDIB_StringMapBucket *, bucket_count); ProfBegin("Chunk Index Histogram"); task.chunk_histo = push_array(scratch.arena, U32, chunk_idx_opl); tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_bucket_chunk_idx_histo_task, &task); ProfEnd(); // sort correctness check on chunk index #if 0 for (U64 i = 1; i < bucket_count; ++i) { RDIB_StringMapBucket *prev = buckets[i - 1]; RDIB_StringMapBucket *curr = buckets[i + 0]; U32 prev_chunk_idx = prev->sorter.hi; U32 curr_chunk_idx = curr->sorter.hi; AssertAlways(prev_chunk_idx <= curr_chunk_idx); } #endif ProfBegin("Chunk Histo -> Offsets"); task.chunk_offsets = offsets_from_counts_array_u32(scratch.arena, task.chunk_histo, chunk_idx_opl); ProfEnd(); ProfBegin("Sort on chunk index"); tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_radix_sort_chunk_idx_task, &task); ProfEnd(); ProfBegin("Sort on element index"); task.chunk_offsets = offsets_from_counts_array_u32(scratch.arena, task.chunk_histo, chunk_idx_opl); task.ranges = tp_divide_work(scratch.arena, chunk_idx_opl, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_string_map_radix_sort_element_idx_task, &task); ProfEnd(); // sort correctness check on element index #if 0 { for (U64 i = 1; i < bucket_count; ++i) { RDIB_StringMapBucket *prev = buckets[i - 1]; RDIB_StringMapBucket *curr = buckets[i + 0]; U32 prev_chunk_idx = prev->sorter.hi; U32 curr_chunk_idx = curr->sorter.hi; if (prev_chunk_idx == curr_chunk_idx) { U32 prev_elem_idx = prev->sorter.lo; U32 curr_elem_idx = curr->sorter.lo; AssertAlways(prev_elem_idx < curr_elem_idx); } } } #endif scratch_end(scratch); ProfEnd(); } internal void rdib_string_map_assign_indices(RDIB_StringMapBucket **buckets, U64 bucket_count) { ProfBeginFunction(); for (U64 idx = 0; idx < bucket_count; ++idx) { buckets[idx]->idx = idx; } ProfEnd(); } // Specialized Inserts internal void rdib_string_map_insert_string_table_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string) { rdib_string_map_insert_item(arena, task, task_id, string, 0); } internal void rdib_string_map_insert_name_map_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, VoidNode *node) { rdib_string_map_insert_item(arena, task, task_id, string, node); } internal RDIB_STRING_MAP_UPDATE_FUNC(rdib_string_map_update_null) { // null update } internal RDIB_STRING_MAP_UPDATE_FUNC(rdib_string_map_update_concat_void_list_atomic) { node->next = ins_atomic_ptr_eval_assign(head, node); } //////////////////////////////// // String Table Tasks internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_sects_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 sect_idx = task->ranges[task_id].min; sect_idx < task->ranges[task_id].max; ++sect_idx) { RDIB_BinarySection *sect = &task->sects[sect_idx]; rdib_string_map_insert_string_table_item(arena, task, task_id, sect->name); } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_units_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_UnitChunk *chunk = task->units[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Unit *unit = &chunk->v[i]; rdib_string_map_insert_string_table_item(arena, task, task_id, unit->unit_name); rdib_string_map_insert_string_table_item(arena, task, task_id, unit->compiler_name); rdib_string_map_insert_string_table_item(arena, task, task_id, unit->source_file); rdib_string_map_insert_string_table_item(arena, task, task_id, unit->object_file); rdib_string_map_insert_string_table_item(arena, task, task_id, unit->archive_file); rdib_string_map_insert_string_table_item(arena, task, task_id, unit->build_path); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_source_files_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_SourceFile *src_file = chunk->v + i; rdib_string_map_insert_string_table_item(arena, task, task_id, src_file->normal_full_path); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_vars_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->vars[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Variable *var = &chunk->v[i]; rdib_string_map_insert_string_table_item(arena, task, task_id, var->name); rdib_string_map_insert_string_table_item(arena, task, task_id, var->link_name); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_procs_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Procedure *proc = &chunk->v[i]; rdib_string_map_insert_string_table_item(arena, task, task_id, proc->name); rdib_string_map_insert_string_table_item(arena, task, task_id, proc->link_name); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_inline_sites_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_InlineSiteChunk *chunk = task->inline_sites[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_InlineSite *inline_site = &chunk->v[i]; rdib_string_map_insert_string_table_item(arena, task, task_id, inline_site->name); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_udt_members_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_UDTMemberChunk *chunk = task->udt_members[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_UDTMember *udt_member = &chunk->v[i]; switch (udt_member->kind) { case RDI_MemberKind_NULL : break; case RDI_MemberKind_DataField : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->data_field.name ); break; case RDI_MemberKind_StaticData : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->static_data.name); break; case RDI_MemberKind_Method : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->method.name ); break; case RDI_MemberKind_NestedType : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->nested_type.name); break; case RDI_MemberKind_Base : break; case RDI_MemberKind_VirtualBase : break; //case RDI_MemberKind_Enumerate : rdib_string_map_insert_string_table_item(arena, task, task_id, udt_member->enumerate.name); break; case RDI_MemberKindExt_MemberListPointer: break; default: InvalidPath; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_enum_members_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_UDTMemberChunk *chunk = task->enum_members[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { rdib_string_map_insert_string_table_item(arena, task, task_id, chunk->v[i].enumerate.name); } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_types_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_TypeChunk *chunk = task->types[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Type *type = &chunk->v[i]; if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) { rdib_string_map_insert_string_table_item(arena, task, task_id, type->builtin.name); } else if (RDI_IsUserDefinedType(type->kind)) { rdib_string_map_insert_string_table_item(arena, task, task_id, type->udt.name); } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_collect_strings_path_nodes_task) { ProfBeginFunction(); RDIB_CollectStringsTask *task = raw_task; for (RDIB_PathTreeNode *n = task->path_node_lists[task_id].first; n != 0; n = n->next_order) { rdib_string_map_insert_string_table_item(arena, task, task_id, n->sub_path); } ProfEnd(); } //////////////////////////////// // Name Map Tasks internal THREAD_POOL_TASK_FUNC(rdib_name_map_var_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->vars[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { RDIB_Variable *n = &chunk->v[var_idx]; nodes[var_idx].v = n; rdib_string_map_insert_name_map_item(arena, task, task_id, n->name, &nodes[var_idx]); } } } internal THREAD_POOL_TASK_FUNC(rdib_name_map_var_link_name_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->vars[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { RDIB_Variable *n = &chunk->v[var_idx]; nodes[var_idx].v = n; rdib_string_map_insert_name_map_item(arena, task, task_id, n->link_name, &nodes[var_idx]); } } } internal THREAD_POOL_TASK_FUNC(rdib_name_map_procedure_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); for (U64 proc_idx = 0; proc_idx < chunk->count; ++proc_idx) { RDIB_Procedure *n = &chunk->v[proc_idx]; nodes[proc_idx].v = n; rdib_string_map_insert_name_map_item(arena, task, task_id, n->name, &nodes[proc_idx]); } } } internal THREAD_POOL_TASK_FUNC(rdib_name_map_procedures_link_name_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ProcedureChunk *chunk = task->procs[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); for (U64 proc_idx = 0; proc_idx < chunk->count; ++proc_idx) { RDIB_Procedure *n = &chunk->v[proc_idx]; nodes[proc_idx].v = n; rdib_string_map_insert_name_map_item(arena, task, task_id, n->link_name, &nodes[proc_idx]); } } } internal THREAD_POOL_TASK_FUNC(rdib_name_map_types_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_TypeChunk *chunk = task->types[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); VoidNode *node_cursor = nodes; for (U64 type_idx = 0; type_idx < chunk->count; ++type_idx) { RDIB_Type *type = &chunk->v[type_idx]; node_cursor->v = type; if (RDI_IsUserDefinedType(type->kind)) { rdib_string_map_insert_name_map_item(arena, task, task_id, type->udt.name, node_cursor); ++node_cursor; } } } } internal THREAD_POOL_TASK_FUNC(rdib_name_map_normal_paths_task) { RDIB_CollectStringsTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; VoidNode *nodes = push_array(arena, VoidNode, chunk->count); VoidNode *node_cursor = nodes; for (U64 i = 0; i < chunk->count; ++i, ++node_cursor) { node_cursor->v = &chunk->v[i]; rdib_string_map_insert_name_map_item(arena, task, task_id, chunk->v[i].normal_full_path, node_cursor); } } } //////////////////////////////// // Index Run Map internal U64 rdib_index_run_hash(U32 count, U32 *idxs) { XXH64_hash_t hash64 = XXH3_64bits(idxs, count * sizeof(idxs[0])); return hash64; } internal RDIB_IndexRunMap * rdib_init_index_run_map(Arena *arena, U64 cap) { ProfBeginFunction(); RDIB_IndexRunMap *map = push_array(arena, RDIB_IndexRunMap, 1); map->cap = cap; map->buckets = push_array(arena, RDIB_IndexRunBucket *, cap); ProfEnd(); return map; } internal RDIB_IndexRunBucket * rdib_index_run_map_insert_or_update(Arena *arena, RDIB_IndexRunBucket **buckets, U64 cap, U64 hash, RDIB_IndexRunBucket *new_bucket, U64 *bucket_idx_out) { B32 was_bucket_inserted_or_updated = 0; RDIB_IndexRunBucket *result = 0; U64 best_idx = hash % cap; U64 idx = best_idx; do { retry:; RDIB_IndexRunBucket *curr_bucket = buckets[idx]; if (curr_bucket == 0) { RDIB_IndexRunBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // success, bucket was inserted was_bucket_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } else if (u32_array_compare(curr_bucket->indices, new_bucket->indices)) { if (curr_bucket->sorter.v <= new_bucket->sorter.v) { // recycle bucket result = new_bucket; // don't need to update, more recent leaf is in the bucket was_bucket_inserted_or_updated = 1; break; } RDIB_IndexRunBucket *compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket); if (compare_bucket == curr_bucket) { // recycle bucket result = compare_bucket; // new bucket is in the hash table, exit was_bucket_inserted_or_updated = 1; break; } // another thread took the bucket... goto retry; } // advance idx = (idx + 1) % cap; } while (idx != best_idx); // are there enough free buckets? Assert(was_bucket_inserted_or_updated); // output bucket index *bucket_idx_out = idx; return result; } internal U32 rdib_idx_run_from_bucket_idx(RDIB_IndexRunMap *map, U64 bucket_idx) { RDIB_IndexRunBucket *bucket = map->buckets[bucket_idx]; U32 idx_run32 = safe_cast_u32(bucket->index_in_output_array); return idx_run32; } internal THREAD_POOL_TASK_FUNC(rdib_count_extant_buckets_index_run_map_task) { ProfBeginFunction(); RDIB_GetExtantBucketsIndexRunMapTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { if (task->idx_run_map->buckets[bucket_idx] != 0) { task->counts[task_id] += 1; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_get_extant_buckets_index_run_map_task) { ProfBeginFunction(); RDIB_GetExtantBucketsIndexRunMapTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min, cursor = task->offsets[task_id]; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_IndexRunBucket *bucket = task->idx_run_map->buckets[bucket_idx]; if (bucket != 0) { task->result[cursor] = bucket; ++cursor; } } ProfEnd(); } internal RDIB_IndexRunBucket ** rdib_extant_buckets_from_index_run_map(TP_Context *tp, Arena *arena, RDIB_IndexRunMap *idx_run_map, U64 *bucket_count_out) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); RDIB_GetExtantBucketsIndexRunMapTask task = {0}; task.idx_run_map = idx_run_map; ProfBegin("Count Extant Buckets"); task.counts = push_array(scratch.arena, U64, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, idx_run_map->cap, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_count_extant_buckets_index_run_map_task, &task); ProfEnd(); *bucket_count_out = sum_array_u64(tp->worker_count, task.counts); ProfBegin("Copy Extant Buckets"); task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); task.result = push_array(arena, RDIB_IndexRunBucket *, *bucket_count_out); tp_for_parallel(tp, 0, tp->worker_count, rdib_get_extant_buckets_index_run_map_task, &task); ProfEnd(); scratch_end(scratch); ProfEnd(); return task.result; } internal THREAD_POOL_TASK_FUNC(rdib_index_run_map_bucket_chunk_idx_histo_task) { ProfBeginFunction(); RDIB_IndexRunMapRadixSort *task = raw_task; Temp scratch = scratch_begin(0,0); U32 *range_histo = push_array(scratch.arena, U32, task->chunk_idx_opl); // count items per sorter for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_IndexRunBucket *bucket = task->src[bucket_idx]; U32 chunk_idx = bucket->sorter.hi; Assert(chunk_idx < task->chunk_idx_opl); ++range_histo[chunk_idx]; } // add in per thread sorter counts for (U64 i = 0; i < task->chunk_idx_opl; ++i) { ins_atomic_u32_add_eval(&task->chunk_histo[i], range_histo[i]); } scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_index_run_map_radix_sort_chunk_idx_task) { ProfBeginFunction(); RDIB_IndexRunMapRadixSort *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_IndexRunBucket *bucket = task->src[bucket_idx]; U32 chunk_idx = bucket->sorter.hi; U32 dst_idx = ins_atomic_u32_inc_eval(&task->chunk_offsets[chunk_idx]) - 1; task->dst[dst_idx] = bucket; } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_index_run_map_radix_sort_element_idx_task) { ProfBeginFunction(); RDIB_IndexRunMapRadixSort *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { U64 range_lo = task->chunk_offsets[chunk_idx]; U64 range_hi = task->chunk_offsets[chunk_idx] + task->chunk_histo[chunk_idx]; ProfBegin("Zero out Histogram"); U32 histo_bot[1 << 10]; MemoryZeroArray(histo_bot); U32 histo_mid[1 << 11]; MemoryZeroArray(histo_mid); U32 histo_top[1 << 11]; MemoryZeroArray(histo_top); ProfEnd(); ProfBegin("Element Histogram"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_IndexRunBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit_bot = (elem_idx >> 0) % ArrayCount(histo_bot); U32 digit_mid = (elem_idx >> 10) % ArrayCount(histo_mid); U32 digit_top = (elem_idx >> 21) % ArrayCount(histo_top); histo_bot[digit_bot] += 1; histo_mid[digit_mid] += 1; histo_top[digit_top] += 1; } ProfEnd(); ProfBegin("Histogram Counts -> Offsets"); counts_to_offsets_array_u32(ArrayCount(histo_bot), &histo_bot[0]); counts_to_offsets_array_u32(ArrayCount(histo_mid), &histo_mid[0]); counts_to_offsets_array_u32(ArrayCount(histo_top), &histo_top[0]); ProfEnd(); ProfBegin("Sort Bot"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_IndexRunBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 0) % ArrayCount(histo_bot); U32 src_idx = range_lo + histo_bot[digit]++; task->src[src_idx] = elem; } ProfEnd(); ProfBegin("Sort Mid"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_IndexRunBucket *elem = task->src[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 10) % ArrayCount(histo_mid); U32 dst_idx = range_lo + histo_mid[digit]++; task->dst[dst_idx] = elem; } ProfEnd(); ProfBegin("Sort Top"); for (U64 i = range_lo; i < range_hi; ++i) { RDIB_IndexRunBucket *elem = task->dst[i]; U32 elem_idx = elem->sorter.lo; U32 digit = (elem_idx >> 21) % ArrayCount(histo_top); U32 src_idx = range_lo + histo_top[digit]++; task->src[src_idx] = elem; } ProfEnd(); } ProfEnd(); } internal void rdib_index_run_map_sort_buckets(TP_Context *tp, RDIB_IndexRunBucket **buckets, U64 bucket_count, U64 chunk_idx_opl) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); RDIB_IndexRunMapRadixSort task = {0}; task.chunk_idx_opl = chunk_idx_opl; task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); task.src = buckets; task.dst = push_array_no_zero(scratch.arena, RDIB_IndexRunBucket *, bucket_count); ProfBegin("Chunk Index Histogram"); task.chunk_histo = push_array(scratch.arena, U32, chunk_idx_opl); tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_bucket_chunk_idx_histo_task, &task); ProfEnd(); // sort correctness check on chunk index #if 0 for (U64 i = 1; i < bucket_count; ++i) { RDIB_StringMapBucket *prev = buckets[i - 1]; RDIB_StringMapBucket *curr = buckets[i + 0]; U32 prev_chunk_idx = RDIB_StringMap_ChunkIdx32FromSorter(prev->sorter); U32 curr_chunk_idx = RDIB_StringMap_ChunkIdx32FromSorter(curr->sorter); AssertAlways(prev_chunk_idx <= curr_chunk_idx); } #endif ProfBegin("Chunk Histo -> Offsets"); task.chunk_offsets = offsets_from_counts_array_u32(scratch.arena, task.chunk_histo, chunk_idx_opl); ProfEnd(); ProfBegin("Sort on chunk index"); tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_radix_sort_chunk_idx_task, &task); ProfEnd(); ProfBegin("Sort on element index"); task.chunk_offsets = offsets_from_counts_array_u32(scratch.arena, task.chunk_histo, chunk_idx_opl); task.ranges = tp_divide_work(scratch.arena, chunk_idx_opl, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_index_run_map_radix_sort_element_idx_task, &task); ProfEnd(); // sort correctness check on element index #if 0 { for (U64 i = 1; i < bucket_count; ++i) { RDIB_IndexRunBucket *prev = buckets[i - 1]; RDIB_IndexRunBucket *curr = buckets[i + 0]; U32 prev_chunk_idx = prev->sorter.hi; U32 curr_chunk_idx = curr->sorter.hi; if (prev_chunk_idx == curr_chunk_idx) { U32 prev_elem_idx = prev->sorter.lo; U32 curr_elem_idx = curr->sorter.lo; AssertAlways(prev_elem_idx < curr_elem_idx); } } } #endif scratch_end(scratch); ProfEnd(); } internal void rdib_index_run_map_assign_indices(RDIB_IndexRunBucket **buckets, U64 bucket_count) { ProfBeginFunction(); for (U64 bucket_idx = 0, cursor = 0; bucket_idx < bucket_count; ++bucket_idx) { buckets[bucket_idx]->index_in_output_array = cursor; cursor += buckets[bucket_idx]->indices.count; } ProfEnd(); } // index run map specialization internal U64 rdib_index_run_map_insert_item(Arena *arena, RDIB_BuildIndexRunsTask *task, U64 worker_id, U64 item_idx, U64 count, U32 *idxs) { Assert(item_idx < max_U32); // do we have a free bucket? RDIB_IndexRunBucket *bucket = task->free_buckets[worker_id]; if (bucket == 0) { bucket = push_array(arena, RDIB_IndexRunBucket, 1); } // fill out bucket bucket->indices.count = count; bucket->indices.v = idxs; bucket->sorter.v = task->sorter_idx << 32 | (U32)item_idx; // insert bucket U64 hash = rdib_index_run_hash(count, idxs); U64 bucket_idx = max_U64; RDIB_IndexRunBucket *free_bucket = rdib_index_run_map_insert_or_update(arena, task->idx_run_map->buckets, task->idx_run_map->cap, hash, bucket, &bucket_idx); Assert(bucket_idx != max_U64); // recycle bucket task->free_buckets[worker_id] = free_bucket; return bucket_idx; } internal THREAD_POOL_TASK_FUNC(rdib_build_idx_runs_params_task) { ProfBeginFunction(); RDIB_BuildIndexRunsTask *task = raw_task; RDIB_TypeChunk *chunk = task->type_chunks[task_id]; for (RDIB_Type *type = &chunk->v[0], *opl = chunk->v + chunk->count; type < opl; ++type) { if (type->kind == RDI_TypeKind_Function) { RDIB_Type *params = type->func.params_type; // pack params U64 type_index_count = params->params.count; U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { type_indices[param_idx] = rdib_idx_from_type(params->params.types[param_idx]); } // insert type indices U32 func_type_idx = rdib_idx_from_type(type); type->func.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, func_type_idx, type_index_count, type_indices); } else if (type->kind == RDI_TypeKind_Method) { RDIB_Type *params = type->method.params_type; U64 type_index_count = params->params.count + 1; U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); U64 type_idx_cursor = 0; // pack 'this' type type_indices[type_idx_cursor++] = rdib_idx_from_type(type->method.this_type); // pack params for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { type_indices[type_idx_cursor++] = rdib_idx_from_type(params->params.types[param_idx]); } // insert type indices U32 method_type_idx = rdib_idx_from_type(type); type->method.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, method_type_idx, type_index_count, type_indices); } else if (type->kind == RDI_TypeKindExt_StaticMethod) { RDIB_Type *params = type->static_method.params_type; U64 type_index_count = params->params.count + 1; U32 *type_indices = push_array_no_zero(arena, U32, type_index_count); U64 type_idx_cursor = 0; // static methods don't have 'this' type_indices[type_idx_cursor++] = 0; // pack params for (U64 param_idx = 0; param_idx < params->params.count; ++param_idx) { type_indices[type_idx_cursor++] = rdib_idx_from_type(params->params.types[param_idx]); } // insert type indices U32 static_method_type_idx = rdib_idx_from_type(type); type->static_method.param_idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, static_method_type_idx, type_index_count, type_indices); } } ProfEnd(); } internal U32 rdib_idx_from_name_map_void_node(RDIB_BuildIndexRunsTask *task, VoidNode *node) { U64 idx = 0; switch (task->name_map_kind) { case RDI_NameMapKind_NULL : break; case RDI_NameMapKind_GlobalVariables : idx = rdib_idx_from_variable ((RDIB_Variable* ) node); break; case RDI_NameMapKind_ThreadVariables : idx = rdib_idx_from_variable ((RDIB_Variable * ) node); break; case RDI_NameMapKind_Procedures : idx = rdib_idx_from_procedure ((RDIB_Procedure * ) node); break; case RDI_NameMapKind_Types : idx = rdib_idx_from_type ((RDIB_Type * ) node); break; case RDI_NameMapKind_LinkNameProcedures: idx = rdib_idx_from_procedure ((RDIB_Procedure * ) node); break; case RDI_NameMapKind_NormalSourcePaths : idx = rdib_idx_from_source_file((RDIB_SourceFile *) node); break; default: InvalidPath; } U32 idx32 = safe_cast_u32(idx); return idx32; } internal THREAD_POOL_TASK_FUNC(rdib_build_idx_runs_name_map_buckets_task) { ProfBeginFunction(); RDIB_BuildIndexRunsTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_StringMapBucket *bucket = task->name_map_buckets[bucket_idx]; U64 count = void_list_count_nodes(bucket->raw_values); if (count > 1) { // build array of indices that point to name map respective arrays U32 *idxs = push_array_no_zero(arena, U32, count); { U64 curr_idx = 0; for (VoidNode *curr = bucket->raw_values; curr != 0; curr = curr->next, ++curr_idx) { idxs[curr_idx] = rdib_idx_from_name_map_void_node(task, curr->v); } } // make index array deterministic u32_array_sort(count, idxs); // TODO: we don't need to sort with one worker thread // :string_map_bucket_sorter_copy U64 idx_run_bucket_idx = rdib_index_run_map_insert_item(arena, task, worker_id, bucket_idx, count, idxs); // TODO: fix `idx` leak when we insert same runs // fill out bucket bucket->count = count; bucket->idx_run_bucket_idx = idx_run_bucket_idx; } if (count == 1) { U32 match_idx = rdib_idx_from_name_map_void_node(task, bucket->raw_values->v); // fill out bucket bucket->count = 1; bucket->match_idx = match_idx; } } ProfEnd(); } //////////////////////////////// #if 0 internal U32 rdib_idx_from_params(RDIB_IndexRunMap *map, RDIB_Type *params) { Assert(params->kind == RDI_TypeKindExt_Params); U32 idx = params->params.idx_run_bucket->index_in_output_array; return idx; } #endif //////////////////////////////// // Data Sections internal void rdib_data_section_list_push_node(RDIB_DataSectionList *list, RDIB_DataSectionNode *node) { SLLQueuePushCount(list, node); } internal RDIB_DataSectionNode * rdib_data_section_list_push(Arena *arena, RDIB_DataSectionList *list, RDIB_DataSection v) { RDIB_DataSectionNode *node = push_array(arena, RDIB_DataSectionNode, 1); node->v = v; rdib_data_section_list_push_node(list, node); return node; } internal void rdib_data_section_list_concat_in_place(RDIB_DataSectionList *list, RDIB_DataSectionList *to_concat) { SLLConcatInPlace(list, to_concat); } internal void rdib_data_sections_from_top_level_info(Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_TopLevelInfo *src) { ProfBeginFunction(); RDI_TopLevelInfo *dst = push_array(arena, RDI_TopLevelInfo, 1); dst->arch = src->arch; dst->exe_name_string_idx = rdib_idx_from_string_map(string_map, src->exe_name); dst->exe_hash = src->exe_hash; dst->voff_max = src->voff_max; dst->producer_name_string_idx = rdib_idx_from_string_map(string_map, src->producer_string); RDIB_DataSection sect = { .tag = RDI_SectionKind_TopLevelInfo }; str8_list_push(arena, §.data, str8_struct(dst)); rdib_data_section_list_push(arena, sect_list, sect); ProfEnd(); } internal void rdib_data_sections_from_binary_sections(Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_BinarySection *binary_sects, U64 binary_sects_count) { ProfBeginFunction(); RDI_BinarySection *dst_arr = push_array(arena, RDI_BinarySection, binary_sects_count); for (U64 sect_idx = 0; sect_idx < binary_sects_count; ++sect_idx) { RDIB_BinarySection *src = &binary_sects[sect_idx]; RDI_BinarySection *dst = &dst_arr[sect_idx]; dst->name_string_idx = rdib_idx_from_string_map(string_map, src->name); dst->flags = src->flags; dst->voff_first = src->voff_first; dst->voff_opl = src->voff_opl; dst->foff_first = src->foff_first; dst->foff_opl = src->foff_opl; } RDIB_DataSection sect = { .tag = RDI_SectionKind_BinarySections }; str8_list_push(arena, §.data, str8_array(dst_arr, binary_sects_count)); rdib_data_section_list_push(arena, sect_list, sect); ProfEnd(); } internal void rdib_data_sections_from_units(Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_unit_count, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks) { ProfBeginFunction(); RDI_Unit *dst_arr = push_array(arena, RDI_Unit, total_unit_count); for (U64 chunk_idx = 0; chunk_idx < unit_chunk_count; chunk_idx += 1) { RDIB_UnitChunk *chunk = unit_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; i += 1) { RDIB_Unit *src = &chunk->v[i]; U64 unit_idx = rdib_idx_from_unit(src); RDI_Unit *dst = &dst_arr[unit_idx]; dst->unit_name_string_idx = rdib_idx_from_string_map(string_map, src->unit_name); dst->compiler_name_string_idx = rdib_idx_from_string_map(string_map, src->compiler_name); dst->source_file_path_node = rdib_idx_from_path_tree(path_tree, src->source_file); dst->object_file_path_node = rdib_idx_from_path_tree(path_tree, src->object_file); dst->archive_file_path_node = rdib_idx_from_path_tree(path_tree, src->archive_file); dst->build_path_node = rdib_idx_from_path_tree(path_tree, src->build_path); dst->language = src->language; dst->line_table_idx = src->line_table->output_array_idx; } } RDIB_DataSection sect = { .tag = RDI_SectionKind_Units }; str8_list_push(arena, §.data, str8_array(dst_arr, total_unit_count)); rdib_data_section_list_push(arena, sect_list, sect); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_unit_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_UnitChunk *chunk = task->unit_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Unit *unit = &chunk->v[i]; task->counts[task_id] += unit->virt_range_count; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_gvar_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->gvar_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Variable *var = &chunk->v[i]; for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { task->counts[task_id] += loc_n->v.ranges.count; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_vmap_count_ranges_scope_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ScopeChunk *chunk = task->scope_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { task->counts[task_id] += chunk->v[i].ranges.count; } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_unit_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; U64 range_cursor = task->offsets[task_id]; U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_UnitChunk *chunk = task->unit_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_Unit *unit = &chunk->v[i]; for (Rng1U64 *range_ptr = unit->virt_ranges, *range_opl = unit->virt_ranges + unit->virt_range_count; range_ptr < range_opl; ++range_ptr) { Assert(range_cursor < range_cursor_opl); Assert(range_ptr->min <= range_ptr->max); RDIB_VMapRange *vmap_range = task->vmap + range_cursor; vmap_range->voff = range_ptr->min; vmap_range->size = range_ptr->max - range_ptr->min; vmap_range->idx = rdib_idx_from_unit(unit); range_cursor += 1; } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_gvar_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; U64 range_cursor = task->offsets[task_id]; U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->gvar_chunks[chunk_idx]; for (U64 var_idx = 0; var_idx < chunk->count; ++var_idx) { RDIB_Variable *var = &chunk->v[var_idx]; for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { for (Rng1U64Node *range_n = loc_n->v.ranges.first; range_n != 0; range_n = range_n->next) { Assert(range_cursor < range_cursor_opl); Assert(range_n->v.min <= range_n->v.max); U64 size = range_n->v.max - range_n->v.min; RDIB_VMapRange *vmap_range = task->vmap + range_cursor; vmap_range->voff = range_n->v.min; vmap_range->size = size; vmap_range->idx = rdib_idx_from_variable(var); range_cursor += 1; } } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_vmap_entries_scope_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; U64 range_cursor = task->offsets[task_id]; U64 range_cursor_opl = task->offsets[task_id] + task->counts[task_id]; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ScopeChunk *chunk = task->scope_chunks[chunk_idx]; for (U64 scope_idx = 0; scope_idx < chunk->count; ++scope_idx) { RDIB_Scope *scope = &chunk->v[scope_idx]; for (Rng1U64Node *range_n = scope->ranges.first; range_n != 0; range_n = range_n->next) { Assert(range_cursor < range_cursor_opl); Assert(range_n->v.min <= range_n->v.max); RDIB_VMapRange *vmap_range = task->vmap + range_cursor; vmap_range->voff = range_n->v.min; vmap_range->size = range_n->v.max - range_n->v.min; vmap_range->idx = rdib_idx_from_scope(scope); range_cursor += 1; } } } ProfEnd(); } internal void rdib_sort_procs_radix_32(RDIB_Procedure **v, U64 count) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); RDIB_Procedure **temp = push_array_no_zero(scratch.arena, RDIB_Procedure *, count); RDIB_Procedure **src = v; RDIB_Procedure **dst = temp; ProfBegin("Count Memzero"); U32 count_8lo[256]; MemoryZeroArray(count_8lo); U32 count_8hi[256]; MemoryZeroArray(count_8hi); U32 count_16[1 << 16]; MemoryZeroArray(count_16); ProfEnd(); ProfBegin("Histogram"); for (U64 i = 0; i < count; i += 1) { RDIB_Procedure *p = src[i]; U64 digit_8lo = (p->scope->ranges.first->v.min >> 0) % ArrayCount(count_8lo); U64 digit_8hi = (p->scope->ranges.first->v.min >> 8) % ArrayCount(count_8hi); U64 digit_16 = (p->scope->ranges.first->v.min >> 16) % ArrayCount(count_16); count_8lo[digit_8lo] += 1; count_8hi[digit_8hi] += 1; count_16[digit_16] += 1; } ProfEnd(); ProfBegin("Counts -> Offsets"); counts_to_offsets_array_u32(ArrayCount(count_8lo), count_8lo); counts_to_offsets_array_u32(ArrayCount(count_8hi), count_8hi); counts_to_offsets_array_u32(ArrayCount(count_16), count_16 ); ProfEnd(); ProfBegin("Order 8 Lo"); for (U64 i = 0; i < count; i += 1) { RDIB_Procedure *p = src[i]; U64 digit = (p->scope->ranges.first->v.min >> 0) % ArrayCount(count_8lo); dst[count_8lo[digit]++] = p; } ProfEnd(); ProfBegin("Order 8 Hi"); for (U64 i = 0; i < count; i += 1) { RDIB_Procedure *p = dst[i]; U64 digit = (p->scope->ranges.first->v.min >> 8) % ArrayCount(count_8hi); src[count_8hi[digit]++] = p; } ProfEnd(); ProfBegin("Order 16"); for (U64 i = 0; i < count; i += 1) { RDIB_Procedure *p = src[i]; U64 digit = (p->scope->ranges.first->v.min >> 16) % ArrayCount(count_16); dst[count_16[digit]++] = p; } ProfEnd(); MemoryCopyTyped(src, dst, count); scratch_end(scratch); ProfEnd(); } internal String8List rdib_data_from_vmap(Arena *arena, U64 range_count, RDIB_VMapRange *ranges) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); const U64 size_bit_count0 = 8; const U64 size_bit_count1 = 8; const U64 size_bit_count2 = 16; const U64 voff_bit_count0 = 11; const U64 voff_bit_count1 = 11; const U64 voff_bit_count2 = 10; ProfBegin("Push shared buffer"); U64 radix_memory_size = sizeof(RDIB_VMapRange) * range_count + sizeof(U32) * ((1 << size_bit_count0) + (1 << size_bit_count1) + (1 << size_bit_count2)) + sizeof(U32) * ((1 << voff_bit_count0) + (1 << voff_bit_count1) + (1 << voff_bit_count2)); U8 *radix_memory = push_array_no_zero(arena, U8, radix_memory_size); ProfEnd(); // TODO: windows caps images at 4GiB so we use 32-bit radix sort, but on linux // images can have > 4GiB and we need to detect when vmap uses upper 32bits // in voffs do a 64-bit radix sort. ProfBegin("Sort"); { RDIB_VMapRange *src = ranges; RDIB_VMapRange *dst = (RDIB_VMapRange *)radix_memory; U32 *size_count0 = (U32 *)(dst + range_count); U32 *size_count1 = size_count0 + (1 << size_bit_count0); U32 *size_count2 = size_count1 + (1 << size_bit_count1); U32 *voff_count0 = size_count2 + (1 << size_bit_count2); U32 *voff_count1 = voff_count0 + (1 << voff_bit_count0); U32 *voff_count2 = voff_count1 + (1 << voff_bit_count1); // // Build histogram // MemoryZeroTyped(size_count0, 1 << size_bit_count0); MemoryZeroTyped(size_count1, 1 << size_bit_count1); MemoryZeroTyped(size_count2, 1 << size_bit_count2); MemoryZeroTyped(voff_count0, 1 << voff_bit_count0); MemoryZeroTyped(voff_count1, 1 << voff_bit_count1); MemoryZeroTyped(voff_count2, 1 << voff_bit_count2); for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange *r = src+i; U32 size_digit0 = (-r->size >> 0) % (1 << size_bit_count0); U32 size_digit1 = (-r->size >> size_bit_count0) % (1 << size_bit_count1); U32 size_digit2 = (-r->size >> (size_bit_count0 + size_bit_count1)) % (1 << size_bit_count2); U64 voff_digit0 = (r->voff >> 0) % (1 << voff_bit_count0); U64 voff_digit1 = (r->voff >> voff_bit_count0) % (1 << voff_bit_count1); U64 voff_digit2 = (r->voff >> (voff_bit_count0 + voff_bit_count1)) % (1 << voff_bit_count2); ++size_count0[size_digit0]; ++size_count1[size_digit1]; ++size_count2[size_digit2]; ++voff_count0[voff_digit0]; ++voff_count1[voff_digit1]; ++voff_count2[voff_digit2]; } counts_to_offsets_array_u32((1 << size_bit_count0), size_count0); counts_to_offsets_array_u32((1 << size_bit_count1), size_count1); counts_to_offsets_array_u32((1 << size_bit_count2), size_count2); counts_to_offsets_array_u32((1 << voff_bit_count0), voff_count0); counts_to_offsets_array_u32((1 << voff_bit_count1), voff_count1); counts_to_offsets_array_u32((1 << voff_bit_count2), voff_count2); // // Sort on range size (high to low) // for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = src[i]; U32 digit = (-r.size >> 0) % (1 << size_bit_count0); dst[size_count0[digit]++] = r; } for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = dst[i]; U32 digit = (-r.size >> size_bit_count0) % (1 << size_bit_count1); src[size_count1[digit]++] = r; } for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = src[i]; U32 digit = (-r.size >> (size_bit_count0 + size_bit_count1)) % (1 << size_bit_count2); dst[size_count2[digit]++] = r; } // // Sort on range voff (low to high) // for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = dst[i]; U32 digit = (r.voff >> 0) % (1 << voff_bit_count0); src[voff_count0[digit]++] = r; } for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = src[i]; U32 digit = (r.voff >> voff_bit_count0) % (1 << voff_bit_count1); dst[voff_count1[digit]++] = r; } for (U64 i = 0; i < range_count; ++i) { RDIB_VMapRange r = dst[i]; U32 digit = (r.voff >> (voff_bit_count0 + voff_bit_count1)) % (1 << voff_bit_count2); src[voff_count2[digit]++] = r; } } ProfEnd(); ProfBegin("Layout virtual map"); String8List raw_vmap = {0}; { U64 default_vme_cap = 4096; U64 vme_block_cap = radix_memory_size / sizeof(RDI_VMapEntry); U64 vme_block_size = 0; RDI_VMapEntry *vme_block = (RDI_VMapEntry *)radix_memory; // Recycle radix sort memory str8_list_push(arena, &raw_vmap, str8_array(vme_block, vme_block_cap)); #define push_vme() (vme_block_size < raw_vmap.last->string.size/sizeof(vme_block[0])) ? &vme_block[vme_block_size++] : \ (vme_block = push_array(arena, RDI_VMapEntry, vme_block_cap), \ vme_block_cap = default_vme_cap, \ vme_block_size = 0, \ str8_list_push(arena, &raw_vmap, str8_array(vme_block, vme_block_cap)), \ &vme_block[vme_block_size++]) struct Stack { RDIB_VMapRange *range; struct Stack *next; }; struct Stack *stack = 0; struct Stack *free_stack = 0; stack = push_array(scratch.arena, struct Stack, 1); stack->range = &ranges[0]; for (U64 range_idx = 1; range_idx < range_count; ++range_idx) { RDIB_VMapRange *r = ranges+range_idx; RDIB_VMapRange *last_bot_range = stack->range; RDIB_VMapRange *last_pop_range = 0; while (stack->range->idx != 0) { if (r->voff < stack->range->voff + stack->range->size) { // Current range is a subset, keep building stack break; } struct Stack *frame = stack; SLLStackPop(stack); // Did we reach bottom most range? if (last_pop_range == 0) { // Don't push VME for index with adjacent ranges if (vme_block_size > 0 && vme_block[vme_block_size-1].idx != frame->range->idx) { RDI_VMapEntry *vme = push_vme(); vme->voff = frame->range->voff; vme->idx = frame->range->idx; } } // Reopen parent range // // Does parent range extend past child range? if (stack->range->voff + stack->range->size != frame->range->voff + frame->range->size && // Does next range open on where stack range ends? r->voff != frame->range->voff + frame->range->size) { RDI_VMapEntry *vme = push_vme(); vme->idx = stack->range->idx; vme->voff = frame->range->voff + frame->range->size; } last_pop_range = stack->range; // Recycle stack frame SLLStackPush(free_stack, frame); } // Prefix if (last_pop_range == 0 && last_bot_range->voff != r->voff) { RDI_VMapEntry* vme = push_vme(); vme->voff = last_bot_range->voff; vme->idx = last_bot_range->idx; } struct Stack *frame; if (free_stack == 0) { frame = push_array(scratch.arena, struct Stack, 1); } else { frame = free_stack; SLLStackPop(free_stack); } frame->range = r; SLLStackPush(stack, frame); } // Empty stack { RDIB_VMapRange *last_pop_range = 0; while (stack->range->idx != 0) { struct Stack *frame = stack; SLLStackPop(stack); if (last_pop_range == 0) { if (vme_block_size > 0 && vme_block[vme_block_size-1].idx != frame->range->idx) { RDI_VMapEntry *vme = push_vme(); vme->voff = frame->range->voff; vme->idx = frame->range->idx; } } if (stack->range->voff + stack->range->size != frame->range->voff + frame->range->size) { RDI_VMapEntry *vme = push_vme(); vme->voff = frame->range->voff + frame->range->size; vme->idx = stack->range->idx; } last_pop_range = stack->range; } } // Subtract unsued vmap entries U64 last_vme_unused = raw_vmap.last->string.size - sizeof(vme_block[0]) * vme_block_size; raw_vmap.last->string.size -= last_vme_unused; raw_vmap.total_size -= last_vme_unused; #undef push_vme } ProfEnd(); // duplicate voff check #if 0 U64 prev = max_U64; for (String8Node *node = raw_vmap.first; node != 0; node = node->next) { RDI_VMapEntry *e = (RDI_VMapEntry*)node->string.str; for (U64 i = 0, c = node->string.size / sizeof(RDI_VMapEntry); i < c; ++i) { Assert(e[i].voff != prev); prev = e[i].voff; } } #endif scratch_end(scratch); ProfEnd(); return raw_vmap; } internal THREAD_POOL_TASK_FUNC(rdib_fill_scope_vmaps_task) { ProfBeginFunction(); RDIB_VMapBuilderTask *task = raw_task; task->raw_vmaps[task_id] = rdib_data_from_vmap(arena, task->vmap_counts[task_id], task->vmaps[task_id]); ProfEnd(); } internal void rdib_data_sections_from_unit_gvar_scope_vmaps(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks, U64 gvar_chunk_count, RDIB_VariableChunk **gvar_chunks, U64 scope_chunk_count, RDIB_ScopeChunk **scope_chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); RDIB_VMapBuilderTask task = {0}; task.counts = push_array(scratch.arena, U64, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, unit_chunk_count, tp->worker_count); ProfBegin("Unit VMap"); U64 unit_vmap_count; RDIB_VMapRange *unit_vmaps; { ProfBegin("Count Ranges"); MemoryZeroTyped(task.counts, tp->worker_count); task.unit_chunks = unit_chunks; task.ranges = tp_divide_work(scratch.arena, unit_chunk_count, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_unit_task, &task); ProfEnd(); ProfBegin("Push"); unit_vmap_count = sum_array_u64(tp->worker_count, task.counts); unit_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, unit_vmap_count); ProfEnd(); ProfBegin("Fill"); task.vmap = unit_vmaps; task.unit_chunks = unit_chunks; task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_unit_task, &task); ProfEnd(); } ProfEnd(); ProfBegin("Global Variables"); U64 gvar_vmap_count; RDIB_VMapRange *gvar_vmaps; { ProfBegin("Count"); MemoryZeroTyped(task.counts, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, gvar_chunk_count, tp->worker_count); task.gvar_chunks = gvar_chunks; tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_gvar_task, &task); ProfEnd(); ProfBegin("Push"); gvar_vmap_count = sum_array_u64(tp->worker_count, task.counts); gvar_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, gvar_vmap_count); ProfEnd(); ProfBegin("Fill"); task.vmap = gvar_vmaps; task.gvar_chunks = gvar_chunks; task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_gvar_task, &task); ProfEnd(); } ProfEnd(); ProfBegin("Scopes"); U64 scope_vmap_count; RDIB_VMapRange *scope_vmaps; { ProfBegin("Count"); MemoryZeroTyped(task.counts, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, scope_chunk_count, tp->worker_count); task.scope_chunks = scope_chunks; tp_for_parallel(tp, 0, tp->worker_count, rdib_vmap_count_ranges_scope_task, &task); ProfEnd(); ProfBegin("Push"); scope_vmap_count = sum_array_u64(tp->worker_count, task.counts); scope_vmaps = push_array_no_zero(scratch.arena, RDIB_VMapRange, scope_vmap_count); ProfEnd(); ProfBegin("Fill"); task.vmap = scope_vmaps; task.scope_chunks = scope_chunks; task.offsets = offsets_from_counts_array_u64(scratch.arena, task.counts, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_vmap_entries_scope_task, &task); ProfEnd(); } ProfEnd(); task.vmap_counts[0] = unit_vmap_count; task.vmap_counts[1] = gvar_vmap_count; task.vmap_counts[2] = scope_vmap_count; task.vmaps[0] = unit_vmaps; task.vmaps[1] = gvar_vmaps; task.vmaps[2] = scope_vmaps; ProfBegin("Fill RDI VMaps"); MemoryZeroArray(task.raw_vmaps); tp_for_parallel(tp, arena, 3, rdib_fill_scope_vmaps_task, &task); ProfEnd(); RDIB_DataSection unit_vmap_sect = { .tag = RDI_SectionKind_UnitVMap, .data = task.raw_vmaps[0] }; RDIB_DataSection gvar_vmap_sect = { .tag = RDI_SectionKind_GlobalVMap, .data = task.raw_vmaps[1] }; RDIB_DataSection scope_vmap_sect = { .tag = RDI_SectionKind_ScopeVMap, .data = task.raw_vmaps[2] }; rdib_data_section_list_push(arena->v[0], sect_list, unit_vmap_sect ); rdib_data_section_list_push(arena->v[0], sect_list, gvar_vmap_sect ); rdib_data_section_list_push(arena->v[0], sect_list, scope_vmap_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_copy_string_data_task) { RDIB_CopyStringDataTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_StringMapBucket *bucket = task->buckets[bucket_idx]; U64 string_table_offset = task->string_table[bucket_idx]; Assert(string_table_offset + bucket->string.size <= task->string_data_size); MemoryCopy(task->string_data + string_table_offset, bucket->string.str, bucket->string.size); } } internal void rdib_data_sections_from_string_map(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // assign string table offset for each bucket U64 cursor = 0; U32 *string_table = push_array_no_zero(arena, U32, bucket_count); for (U64 bucket_idx = 0; bucket_idx < bucket_count; ++bucket_idx) { string_table[bucket_idx] = cursor; cursor += buckets[bucket_idx]->string.size; } // populate string data buffer with bucket strings RDIB_CopyStringDataTask task = {0}; task.string_table = string_table; task.string_data_size = cursor; task.string_data = push_array_no_zero(arena, U8, task.string_data_size); task.buckets = buckets; task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_copy_string_data_task, &task); // fill out string table section RDIB_DataSection string_table_sect = {0}; string_table_sect.tag = RDI_SectionKind_StringTable; str8_list_push(arena, &string_table_sect.data, str8((U8 *)task.string_table, sizeof(task.string_table[0]) * bucket_count)); // fill out string data section RDIB_DataSection string_data_sect = { .tag = RDI_SectionKind_StringData }; str8_list_push(arena, &string_data_sect.data, str8(task.string_data, task.string_data_size)); // push sections to list rdib_data_section_list_push(arena, sect_list, string_table_sect); rdib_data_section_list_push(arena, sect_list, string_data_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_idx_run_copy_task) { RDIB_IdxRunCopyTask *task = raw_task; for (U64 bucket_idx = task->ranges[task_id].min; bucket_idx < task->ranges[task_id].max; ++bucket_idx) { RDIB_IndexRunBucket *bucket = task->buckets[bucket_idx]; MemoryCopyTyped(&task->output_array[bucket->index_in_output_array], bucket->indices.v, bucket->indices.count); } } internal void rdib_data_sections_from_index_runs(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_IndexRunBucket **buckets, U64 bucket_count) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); ProfBegin("Count Indices"); U64 total_index_count = 0; for (U64 bucket_idx = 0; bucket_idx < bucket_count; ++bucket_idx) { total_index_count += buckets[bucket_idx]->indices.count; } ProfEnd(); U32 *output_array = push_array_no_zero(arena, U32, total_index_count); RDIB_IdxRunCopyTask task = {0}; task.buckets = buckets; task.ranges = tp_divide_work(scratch.arena, bucket_count, tp->worker_count); task.output_array = output_array; tp_for_parallel(tp, 0, tp->worker_count, rdib_idx_run_copy_task, &task); RDIB_DataSection data_sect = { .tag = RDI_SectionKind_IndexRuns }; str8_list_push(arena, &data_sect.data, str8_array(output_array, total_index_count)); rdib_data_section_list_push(arena, sect_list, data_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_file_path_nodes_task) { ProfBeginFunction(); RDIB_BuildFilePathNodesTask *task = raw_task; RDIB_StringMap *string_map = task->string_map; RDIB_PathTree *path_tree = task->path_tree; for (RDIB_PathTreeNode *n = path_tree->node_lists[task_id].first; n != 0; n = n->next_order) { RDI_FilePathNode *dst = task->nodes_dst + n->node_idx; dst->name_string_idx = rdib_idx_from_string_map(string_map, n->sub_path); B32 is_source_file_node = (n->first_child == 0); if (is_source_file_node) { dst->source_file_idx = rdib_idx_from_source_file(n->src_file); } else { // directories don't have a source file Assert(n->src_file == 0); dst->source_file_idx = 0; } if(n->parent) { dst->parent_path_node = n->parent->node_idx; } if (n->first_child) { dst->first_child = n->first_child->node_idx; } if (n->next_sibling) { dst->next_sibling = n->next_sibling->node_idx; } } ProfEnd(); } internal void rdib_data_sections_from_path_tree(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree) { ProfBeginFunction(); RDI_FilePathNode *nodes_dst = push_array_no_zero(arena, RDI_FilePathNode, path_tree->node_count); RDIB_BuildFilePathNodesTask task = {0}; task.path_tree = path_tree; task.string_map = string_map; task.nodes_dst = nodes_dst; tp_for_parallel(tp, 0, path_tree->list_count, rdib_build_file_path_nodes_task, &task); RDIB_DataSection data_sect = { .tag = RDI_SectionKind_FilePathNodes }; str8_list_push(arena, &data_sect.data, str8_array(nodes_dst, path_tree->node_count)); rdib_data_section_list_push(arena, sect_list, data_sect); ProfEnd(); } internal RDIB_PathTree * rdib_build_path_tree(Arena *arena, U64 worker_count, RDIB_SourceFile *null_src_file, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_file_chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); RDIB_PathTree *tree = rdib_path_tree_init(arena, worker_count); rdib_path_tree_insert(arena, tree, RDIB_PATH_TREE_NIL_STRING, null_src_file); ProfBegin("Units"); for (U64 ichunk = 0; ichunk < unit_chunk_count; ++ichunk) { RDIB_UnitChunk *chunk = unit_chunks[ichunk]; for (U64 iunit = 0; iunit < chunk->count; ++iunit) { RDIB_Unit *unit = &chunk->v[iunit]; rdib_path_tree_insert(arena, tree, unit->source_file, null_src_file); rdib_path_tree_insert(arena, tree, unit->object_file, null_src_file); rdib_path_tree_insert(arena, tree, unit->archive_file, null_src_file); rdib_path_tree_insert(arena, tree, unit->build_path, null_src_file); } } ProfEnd(); ProfBegin("Source Files"); for (U64 chunk_idx = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_SourceFile *src_file = chunk->v + i; rdib_path_tree_insert(arena, tree, src_file->file_path, src_file); } } ProfEnd(); scratch_end(scratch); ProfEnd(); return tree; } internal THREAD_POOL_TASK_FUNC(rdib_build_var_section_task) { ProfBeginDynamic("Global Variables Task %llu", task_id); RDIB_BuildSymbolSectionTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->gvars_rdib[chunk_idx]; RDI_GlobalVariable *vars = push_array_no_zero(arena, RDI_GlobalVariable, chunk->count); for (U64 i = 0; i < chunk->count; ++i) { RDIB_Variable *src = &chunk->v[i]; RDI_GlobalVariable *dst = &vars[i]; // TODO: temporary hack while we don't have bytecode eval in RDI_GlobalVariable U64 voff = 0; if (src->locations.first != 0) { if (src->locations.first->v.kind == RDI_LocationKind_AddrBytecodeStream && src->locations.first->v.bytecode.first->op == RDI_EvalOp_ModuleOff) { voff = src->locations.first->v.bytecode.first->p; } } dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); dst->voff = voff; dst->type_idx = rdib_idx_from_type(src->type); dst->link_flags = src->link_flags; if (src->container_type != 0) { Assert(!src->container_proc); dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = rdib_idx_from_udt_type(src->container_type); } if (src->container_proc != 0) { Assert(!src->container_type); dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = rdib_idx_from_procedure(src->container_proc); } } str8_list_push(arena, &task->gvars_out[task_id], str8_array(vars, chunk->count)); } ProfEnd(); } internal void rdib_data_sections_from_global_variables(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Build"); RDIB_BuildSymbolSectionTask task = {0}; task.string_map = string_map; task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); task.gvars_rdib = chunks; task.gvars_out = push_array(scratch.arena, String8List, tp->worker_count); tp_for_parallel(tp, arena, tp->worker_count, rdib_build_var_section_task, &task); ProfEnd(); RDIB_DataSection gvars_sect = { .tag = RDI_SectionKind_GlobalVariables }; str8_list_concat_in_place_array(&gvars_sect.data, task.gvars_out, tp->worker_count); rdib_data_section_list_push(arena->v[0], sect_list, gvars_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_tvar_section_task) { RDIB_BuildSymbolSectionTask *task = raw_task; ProfBeginDynamic("Thread Variables Task [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_VariableChunk *chunk = task->tvars_rdib[chunk_idx]; RDI_ThreadVariable *vars = push_array_no_zero(arena, RDI_ThreadVariable, chunk->count); for (U64 i = 0; i < chunk->count; ++i) { RDIB_Variable *src = &chunk->v[i]; RDI_ThreadVariable *dst = &vars[i]; U32 tls_off = 0; if (src->locations.first != 0) { if (src->locations.first->v.kind == RDI_LocationKind_AddrBytecodeStream && src->locations.first->v.bytecode.first->op == RDI_EvalOp_TLSOff) { tls_off = src->locations.first->v.bytecode.first->p; } } dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); dst->tls_off = tls_off; dst->type_idx = rdib_idx_from_type(src->type); if (src->container_type != 0) { Assert(!src->container_proc); dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = rdib_idx_from_udt_type(src->container_type); } if (src->container_proc != 0) { Assert(!src->container_type); dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = rdib_idx_from_procedure(src->container_proc); } } str8_list_push(arena, &task->tvars_out[task_id], str8_array(vars, chunk->count)); } ProfEnd(); } internal void rdib_data_sections_from_thread_variables(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks) { ProfBeginDynamic("Thread Variables [Chunk Count: %llu, Total Count %llu]", total_count, chunk_count); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Build"); RDIB_BuildSymbolSectionTask task = {0}; task.string_map = string_map; task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); task.tvars_rdib = chunks; task.tvars_out = push_array(scratch.arena, String8List, tp->worker_count); tp_for_parallel(tp, arena, tp->worker_count, rdib_build_tvar_section_task, &task); ProfEnd(); RDIB_DataSection tvars_sect = { .tag = RDI_SectionKind_ThreadVariables }; str8_list_concat_in_place_array(&tvars_sect.data, task.tvars_out, tp->worker_count); rdib_data_section_list_push(arena->v[0], sect_list, tvars_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_procs_section_task) { RDIB_BuildSymbolSectionTask *task = raw_task; ProfBeginDynamic("Procedures Task [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ProcedureChunk *chunk = task->procs_rdib[chunk_idx]; RDI_Procedure *procs = push_array_no_zero(arena, RDI_Procedure, chunk->count); for (U64 i = 0; i < chunk->count; ++i) { RDIB_Procedure *src = &chunk->v[i]; RDI_Procedure *dst = &procs[i]; dst->name_string_idx = rdib_idx_from_string_map(task->string_map, src->name); dst->link_name_string_idx = rdib_idx_from_string_map(task->string_map, src->link_name); dst->link_flags = src->link_flags; dst->type_idx = rdib_idx_from_type(src->type); dst->root_scope_idx = rdib_idx_from_scope(src->scope); if (src->container_type != 0) { AssertAlways(!src->container_proc); dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = rdib_idx_from_udt_type(src->container_type); } if (src->container_proc != 0) { AssertAlways(!src->container_type); dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = rdib_idx_from_procedure(0); Assert(!"TODO"); // src->container_proc } } str8_list_push(arena, &task->procs_out[task_id], str8_array(procs, chunk->count)); } ProfEnd(); } internal void rdib_data_sections_from_procedures(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_ProcedureChunk **chunks) { ProfBeginDynamic("Procedures [Total Count: %llu, Chunk Count: %llu]", total_count, chunk_count); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Build"); RDIB_BuildSymbolSectionTask task = {0}; task.string_map = string_map; task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); task.procs_rdib = chunks; task.procs_out = push_array(scratch.arena, String8List, tp->worker_count); tp_for_parallel(tp, arena, tp->worker_count, rdib_build_procs_section_task, &task); ProfEnd(); RDIB_DataSection procs_sect = { .tag = RDI_SectionKind_Procedures }; str8_list_concat_in_place_array(&procs_sect.data, task.procs_out, tp->worker_count); rdib_data_section_list_push(arena->v[0], sect_list, procs_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_count_scopes_task) { ProfBeginFunction(); RDIB_BuildSymbolSectionTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_ScopeChunk *chunk = task->scopes_rdib[chunk_idx]; for (U64 scope_i = 0; scope_i < chunk->count; ++scope_i) { RDIB_Scope *scope = &chunk->v[scope_i]; task->scope_voff_counts[task_id] += scope->ranges.count * 2; task->local_counts[task_id] += scope->local_count; for (RDIB_Variable *var = scope->local_first; var != 0; var = var->next) { for (RDIB_LocationNode *loc_n = var->locations.first; loc_n != 0; loc_n = loc_n->next) { switch (loc_n->v.kind) { case RDI_LocationKind_NULL: break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { task->loc_data_sizes[task_id] += loc_n->v.bytecode.size + /* stream ender: */ 1; } break; case RDI_LocationKind_ValReg: { task->loc_data_sizes[task_id] += sizeof(RDI_LocationReg); } break; case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { task->loc_data_sizes[task_id] += sizeof(RDI_LocationRegPlusU16); } break; default: InvalidPath; } task->loc_block_counts[task_id] += loc_n->v.ranges.count; task->loc_data_sizes[task_id] += AlignPadPow2(task->loc_data_sizes[task_id], 8); } } } } ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_scopes_task) { RDIB_BuildSymbolSectionTask *task = raw_task; ProfBeginDynamic("Scopes [Chunk Count: %llu]", task->ranges[task_id].max - task->ranges[task_id].min); // scope voff fill info U64 scope_voff_cursor = task->scope_voff_offsets[task_id]; U64 scope_voff_max = task->scope_voff_offsets[task_id] + task->scope_voff_counts[task_id]; U64 *scope_voff_ptr = task->scope_voffs_rdi; // local fill info U64 local_cursor = task->local_offsets[task_id]; U64 local_max = task->local_offsets[task_id] + task->local_counts[task_id]; RDI_Local *locals = task->locals_rdi; // location data fill info U64 loc_data_max = task->loc_data_offsets[task_id] + task->loc_data_sizes[task_id]; U64 loc_data_cursor = task->loc_data_offsets[task_id]; U8 *loc_data = task->loc_data_rdi; // location block fill info U64 loc_block_cursor = task->loc_block_offsets[task_id]; U64 loc_block_max = task->loc_block_offsets[task_id] + task->loc_block_counts[task_id]; RDI_LocationBlock *loc_blocks = task->loc_blocks_rdi; for (U64 ichunk = task->ranges[task_id].min; ichunk < task->ranges[task_id].max; ++ichunk) { RDIB_ScopeChunk *chunk = task->scopes_rdib[ichunk]; for (U64 iscope = 0; iscope < chunk->count; ++iscope) { RDIB_Scope *scope_src = &chunk->v[iscope]; U64 scope_idx = rdib_idx_from_scope(scope_src); RDI_Scope *scope_dst = &task->scopes_rdi[scope_idx]; scope_dst->proc_idx = rdib_idx_from_procedure(scope_src->container_proc); scope_dst->parent_scope_idx = rdib_idx_from_scope(scope_src->parent); scope_dst->first_child_scope_idx = rdib_idx_from_scope(scope_src->first_child); scope_dst->next_sibling_scope_idx = rdib_idx_from_scope(scope_src->next_sibling); scope_dst->voff_range_first = scope_voff_cursor; scope_dst->voff_range_opl = scope_voff_cursor + scope_src->ranges.count * 2; scope_dst->local_count = scope_src->local_count; if (scope_src->local_count > 0) { scope_dst->local_first = local_cursor; } else { scope_dst->local_first = 0; } // TODO: static locals can be exported as local variables //scope_dst->static_local_idx_run_first = ???; //scope_dst->static_local_count = ???; scope_dst->inline_site_idx = rdib_idx_from_inline_site(scope_src->inline_site); // fill out scope voffs for (Rng1U64Node *range_n = scope_src->ranges.first; range_n != 0; range_n = range_n->next) { Assert(scope_voff_cursor + 2 <= scope_voff_max); scope_voff_ptr[scope_voff_cursor + 0] = range_n->v.min; scope_voff_ptr[scope_voff_cursor + 1] = range_n->v.max; scope_voff_cursor += 2; } // fill out locals & locations for (RDIB_Variable *local_src = scope_src->local_first; local_src != 0; local_src = local_src->next, ++local_cursor) { U64 loc_block_first = loc_block_cursor; for (RDIB_LocationNode *loc_n = local_src->locations.first; loc_n != 0; loc_n = loc_n->next) { RDIB_Location *loc = &loc_n->v; // fill out location data U64 location_data_off = loc_data_cursor; switch (loc->kind) { case RDI_LocationKind_NULL: break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { // write opcodes & operands for (RDIB_EvalBytecodeOp *op_node = loc->bytecode.first; op_node != 0; op_node = op_node->next) { // opcode Assert(loc_data_cursor + sizeof(op_node->op) <= loc_data_max); MemoryCopy(loc_data + loc_data_cursor, &op_node->op, sizeof(op_node->op)); loc_data_cursor += sizeof(op_node->op); // operand Assert(loc_data_cursor + op_node->p_size <= loc_data_max); MemoryCopy(loc_data + loc_data_cursor, &op_node->p, op_node->p_size); loc_data_cursor += op_node->p_size; } // stream ender Assert(loc_data_cursor + 1 <= loc_data_max); loc_data[loc_data_cursor] = 0; loc_data_cursor += 1; } break; case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { Assert(loc_data_cursor + sizeof(RDI_LocationRegPlusU16) <= loc_data_max); RDI_LocationRegPlusU16 *dst = (RDI_LocationRegPlusU16 *) (loc_data + loc_data_cursor); dst->kind = loc->kind; dst->reg_code = loc->reg_code; dst->offset = loc->offset; loc_data_cursor += sizeof(*dst); } break; case RDI_LocationKind_ValReg: { Assert(loc_data_cursor + sizeof(RDI_LocationReg) <= loc_data_max); RDI_LocationReg *dst = (RDI_LocationReg *) (loc_data + loc_data_cursor); dst->kind = loc->kind; dst->reg_code = loc->reg_code; loc_data_cursor += sizeof(*dst); } break; default: InvalidPath; } // zero out align bytes U64 align_size = AlignPadPow2(loc_data_cursor, 8); Assert(loc_data_cursor + align_size <= loc_data_max); MemorySet(loc_data + loc_data_cursor, 0, align_size); loc_data_cursor += align_size; // fill out location block for (Rng1U64Node *range_n = loc->ranges.first; range_n != 0; range_n = range_n->next, ++loc_block_cursor) { Assert(loc_block_cursor < loc_block_max); RDI_LocationBlock *loc_block_dst = &loc_blocks[loc_block_cursor]; loc_block_dst->scope_off_first = range_n->v.min; loc_block_dst->scope_off_opl = range_n->v.max; loc_block_dst->location_data_off = location_data_off; } } Assert(local_cursor <= local_max); RDI_Local *local_dst = &locals[local_cursor]; local_dst->kind = local_src->kind; local_dst->name_string_idx = rdib_idx_from_string_map(task->string_map, local_src->name); local_dst->type_idx = rdib_idx_from_type(local_src->type); if (local_src->locations.count > 0) { local_dst->location_first = loc_block_first; local_dst->location_opl = loc_block_cursor; } else { local_dst->location_first = 0; local_dst->location_opl = 0; } } } } Assert(scope_voff_cursor == scope_voff_max); Assert(local_cursor == local_max); Assert(loc_data_cursor == loc_data_max); ProfEnd(); } internal void rdib_data_sections_from_scopes(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_scope_count, U64 chunk_count, RDIB_ScopeChunk **scopes) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); RDIB_BuildSymbolSectionTask task = {0}; task.string_map = string_map; task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); task.scopes_rdib = scopes; ProfBegin("Count Locals & Locations"); task.scope_voff_counts = push_array(scratch.arena, U64, tp->worker_count); task.local_counts = push_array(scratch.arena, U64, tp->worker_count); task.loc_block_counts = push_array(scratch.arena, U64, tp->worker_count); task.loc_data_sizes = push_array(scratch.arena, U64, tp->worker_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_count_scopes_task, &task); ProfEnd(); U64 total_scope_voff_count = sum_array_u64(tp->worker_count, task.scope_voff_counts); U64 total_local_count = sum_array_u64(tp->worker_count, task.local_counts ); U64 total_loc_block_count = sum_array_u64(tp->worker_count, task.loc_block_counts ); U64 total_loc_data_size = sum_array_u64(tp->worker_count, task.loc_data_sizes ); ProfBegin("Fill out scopes, locals, location blocks, and location data"); task.scope_voff_offsets = offsets_from_counts_array_u64(scratch.arena, task.scope_voff_counts, tp->worker_count); task.local_offsets = offsets_from_counts_array_u64(scratch.arena, task.local_counts, tp->worker_count); task.loc_block_offsets = offsets_from_counts_array_u64(scratch.arena, task.loc_block_counts, tp->worker_count); task.loc_data_offsets = offsets_from_counts_array_u64(scratch.arena, task.loc_data_sizes, tp->worker_count); ProfBegin("Push"); task.scope_voffs_rdi = push_array_no_zero(arena->v[0], U64, total_scope_voff_count); task.scopes_rdi = push_array_no_zero(arena->v[0], RDI_Scope, total_scope_count ); task.locals_rdi = push_array_no_zero(arena->v[0], RDI_Local, total_local_count ); task.loc_blocks_rdi = push_array_no_zero(arena->v[0], RDI_LocationBlock, total_loc_block_count ); task.loc_data_rdi = push_array_no_zero(arena->v[0], U8, total_loc_data_size ); ProfEnd(); tp_for_parallel(tp, 0, tp->worker_count, rdib_build_scopes_task, &task); ProfEnd(); RDIB_DataSection scopes_sect = { .tag = RDI_SectionKind_Scopes }; RDIB_DataSection scope_voffs_sect = { .tag = RDI_SectionKind_ScopeVOffData }; RDIB_DataSection locals_sect = { .tag = RDI_SectionKind_Locals }; RDIB_DataSection loc_blocks_sect = { .tag = RDI_SectionKind_LocationBlocks }; RDIB_DataSection loc_data_sect = { .tag = RDI_SectionKind_LocationData }; str8_list_push(arena->v[0], &scopes_sect.data, str8_array(task.scopes_rdi, total_scope_count )); str8_list_push(arena->v[0], &scope_voffs_sect.data, str8_array(task.scope_voffs_rdi, total_scope_voff_count)); str8_list_push(arena->v[0], &locals_sect.data, str8_array(task.locals_rdi, total_local_count )); str8_list_push(arena->v[0], &loc_blocks_sect.data, str8_array(task.loc_blocks_rdi, total_loc_block_count )); str8_list_push(arena->v[0], &loc_data_sect.data, str8_array(task.loc_data_rdi, total_loc_data_size )); rdib_data_section_list_push(arena->v[0], sect_list, scopes_sect ); rdib_data_section_list_push(arena->v[0], sect_list, scope_voffs_sect); rdib_data_section_list_push(arena->v[0], sect_list, locals_sect ); rdib_data_section_list_push(arena->v[0], sect_list, loc_blocks_sect ); rdib_data_section_list_push(arena->v[0], sect_list, loc_data_sect ); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_name_map_task) { ProfBeginFunction("Build Name Map"); Temp scratch = scratch_begin(&arena, 1); RDIB_NameMapBuilderTask *task = raw_task; RDI_NameMapKind name_map_idx = (RDI_NameMapKind)task_id; U64 out_node_count = task->in_bucket_counts[name_map_idx]; U64 load_factor = 4; U64 out_bucket_count = CeilIntegerDiv(out_node_count, load_factor); ProfBegin("Build temp hash map"); struct Node { struct Node *next; RDIB_StringMapBucket *name; }; struct NodeList { struct Node *first; struct Node *last; U64 node_count; }; struct NodeList *temp_map = push_array(scratch.arena, struct NodeList, out_bucket_count); struct Node *temp_nodes = push_array_no_zero(scratch.arena, struct Node, out_node_count); for (U64 i = 0; i < task->in_bucket_counts[name_map_idx]; ++i) { RDIB_StringMapBucket *src_bucket = task->in_buckets[name_map_idx][i]; U64 hash = rdi_hash(src_bucket->string.str, src_bucket->string.size); U64 bucket_idx = hash % out_bucket_count; struct Node *node = temp_nodes + i; node->next = 0; node->name = src_bucket; SLLQueuePush(temp_map[bucket_idx].first, temp_map[bucket_idx].last, node); ++temp_map[bucket_idx].node_count; } ProfEnd(); ProfBegin("Push buckets and nodes"); RDI_NameMapBucket *out_buckets = push_array_no_zero(arena, RDI_NameMapBucket, out_bucket_count); RDI_NameMapNode *out_nodes = push_array_no_zero(arena, RDI_NameMapNode, out_node_count); ProfEnd(); ProfBegin("Fill out buckets"); for (U64 bucket_idx = 0, node_cursor = 0; bucket_idx < out_bucket_count; ++bucket_idx) { struct NodeList *src_bucket = &temp_map[bucket_idx]; RDI_NameMapBucket *dst_bucket = &out_buckets[bucket_idx]; if (src_bucket->node_count == 0) { dst_bucket->first_node = 0; dst_bucket->node_count = 0; continue; } dst_bucket->first_node = safe_cast_u32(node_cursor); dst_bucket->node_count = src_bucket->node_count; for (struct Node *n = src_bucket->first; n != 0; n = n->next, ++node_cursor) { RDIB_StringMapBucket *src_name = n->name; RDI_NameMapNode *dst_node = &out_nodes[node_cursor]; dst_node->string_idx = rdib_idx_from_string_map(task->string_map, src_name->string); dst_node->match_count = src_name->count; if (src_name->count > 1) { dst_node->match_idx_or_idx_run_first = task->idx_run_map->buckets[src_name->idx_run_bucket_idx]->index_in_output_array; } else { dst_node->match_idx_or_idx_run_first = src_name->match_idx; } } } ProfEnd(); // fill out output task->out_buckets[name_map_idx] = out_buckets; task->out_nodes[name_map_idx] = out_nodes; task->out_bucket_counts[name_map_idx] = out_bucket_count; task->out_node_counts[name_map_idx] = out_node_count; scratch_end(scratch); ProfEnd(); } internal void rdib_data_sections_from_name_maps(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_IndexRunMap *idx_run_map, RDIB_StringMapBucket **src_name_maps[RDI_NameMapKind_COUNT], U64 src_name_map_counts[RDI_NameMapKind_COUNT]) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Build Name Maps"); RDIB_NameMapBuilderTask task = {0}; task.string_map = string_map; task.idx_run_map = idx_run_map; task.in_bucket_counts = src_name_map_counts; task.in_buckets = src_name_maps; task.out_buckets = push_array(scratch.arena, RDI_NameMapBucket *, RDI_NameMapKind_COUNT); task.out_nodes = push_array(scratch.arena, RDI_NameMapNode *, RDI_NameMapKind_COUNT); task.out_bucket_counts = push_array(scratch.arena, U64, RDI_NameMapKind_COUNT); task.out_node_counts = push_array(scratch.arena, U64, RDI_NameMapKind_COUNT); tp_for_parallel(tp, arena, RDI_NameMapKind_COUNT, rdib_build_name_map_task, &task); ProfEnd(); U64 *bucket_offsets = offsets_from_counts_array_u64(scratch.arena, task.out_bucket_counts, RDI_NameMapKind_COUNT); U64 *node_offsets = offsets_from_counts_array_u64(scratch.arena, task.out_node_counts, RDI_NameMapKind_COUNT); String8List raw_name_maps = {0}, raw_name_map_buckets = {0}, raw_name_map_nodes = {0}; for (U64 i = 0; i < RDI_NameMapKind_COUNT; ++i) { RDI_NameMap *dst_name_map = push_array(arena->v[0], RDI_NameMap, 1); dst_name_map->bucket_base_idx = bucket_offsets[i]; dst_name_map->node_base_idx = node_offsets[i]; dst_name_map->bucket_count = task.out_bucket_counts[i]; dst_name_map->node_count = task.out_node_counts[i]; str8_list_push(arena->v[0], &raw_name_maps, str8_struct(dst_name_map)); str8_list_push(arena->v[0], &raw_name_map_buckets, str8_array(task.out_buckets[i], task.out_bucket_counts[i])); str8_list_push(arena->v[0], &raw_name_map_nodes, str8_array(task.out_nodes[i], task.out_node_counts[i])); } RDIB_DataSection name_maps_sect = { .tag = RDI_SectionKind_NameMaps, .data = raw_name_maps }; RDIB_DataSection name_map_buckets_sect = { .tag = RDI_SectionKind_NameMapBuckets, .data = raw_name_map_buckets }; RDIB_DataSection name_map_nodes_sect = { .tag = RDI_SectionKind_NameMapNodes, .data = raw_name_map_nodes }; rdib_data_section_list_push(arena->v[0], sect_list, name_maps_sect); rdib_data_section_list_push(arena->v[0], sect_list, name_map_buckets_sect); rdib_data_section_list_push(arena->v[0], sect_list, name_map_nodes_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_src_line_map_task) { // Line tables are ordered to perform 'virtual offset -> line number' maps, // and thus we potentially can have multiple virtual offsets map to same line number. // (e.g. in C/C++ if for-loop declaration site is on one line, intial-statment-condition // and expression parts map to same line number). And so to make things easy on debugger // we remove duplicates from source line map and reorient mapping to 'line number -> virtual offset' // this way debugger can quickly compute virtual offsets when placing a breakpoint on a source line. Temp scratch = scratch_begin(&arena, 1); RDIB_SrcLineMapsTask *task = raw_task; RDIB_SourceFile *src_file = task->src_file_arr[task_id]; U64 src_file_idx = rdib_idx_from_source_file(src_file); //ProfBeginDynamic("Build Source Line Map [%.*s]", str8_varg(src_file->file_path)); ProfBegin("Build Source Line Map"); ProfBegin("Count lines/virt offsets"); U64 ln_voff_count = 0; for (RDIB_LineTableFragment *frag = src_file->line_table_frags; frag != 0; frag = frag->next_src_file) { ln_voff_count += frag->line_count; } ProfEnd(); ProfBegin("Push ln_voff_arr"); PairU32 *ln_voff_arr = push_array_no_zero(scratch.arena, PairU32, ln_voff_count); ProfEnd(); ProfBegin("Fill out ln_voff_arr"); { U64 cursor = 0; for (RDIB_LineTableFragment *frag = src_file->line_table_frags; frag != 0; frag = frag->next_src_file) { for (U64 line_idx = 0; line_idx < frag->line_count; ++line_idx) { ln_voff_arr[cursor].v0 = frag->line_nums[line_idx]; ln_voff_arr[cursor].v1 = frag->voffs[line_idx]; ++cursor; } } } ProfEnd(); // sort on line number ProfBegin("Sort"); if (ln_voff_count < 512) { // TODO: Radsort is buggy and inifte loops if we sort pair of u64. // Check-in with Jeff on Monday about bugfix. For now workaround // the bug wiht pair of u32s. There is no virtual offset larger // than 4GiB in line table anyway. radsort(ln_voff_arr, ln_voff_count, pair_u32_is_before_v0); } else { u32_pair_radix_sort(ln_voff_count, ln_voff_arr); } ProfEnd(); // TODO: leak, precompute unique line number count and push exact array lengths U32 *line_nums = push_array_no_zero(arena, U32, ln_voff_count); U32 *line_ranges = push_array_no_zero(arena, U32, ln_voff_count + 1); U64 *voffs = push_array_no_zero(arena, U64, ln_voff_count); U64 voff_cursor = 0; U64 line_num_cursor = 0; if (ln_voff_count > 0) { line_nums[line_num_cursor] = ln_voff_arr[0].v0; voffs[voff_cursor] = ln_voff_arr[0].v1; line_ranges[line_num_cursor] = voff_cursor; ++voff_cursor; ++line_num_cursor; ProfBegin("Fill out output array"); for (U64 i = 1; i < ln_voff_count; ++i) { // does this voff belong to next line number? if (ln_voff_arr[i].v0 != line_nums[line_num_cursor-1]) { line_nums[line_num_cursor] = ln_voff_arr[i].v0; line_ranges[line_num_cursor] = (U32)voff_cursor; ++line_num_cursor; } voffs[voff_cursor++] = ln_voff_arr[i].v1; } ProfEnd(); // did we fill out voff array correctly? Assert(voff_cursor == ln_voff_count); // close last line range line_ranges[line_num_cursor] = voff_cursor; } // fill out result task->out_line_counts[src_file_idx] = line_num_cursor; task->out_voff_counts[src_file_idx] = safe_cast_u32(voff_cursor); task->out_line_nums[src_file_idx] = line_nums; task->out_line_ranges[src_file_idx] = line_ranges; task->out_voffs[src_file_idx] = voffs; scratch_end(scratch); ProfEnd(); } internal void rdib_data_sections_from_source_line_maps(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_file_chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); ProfBegin("Prepare Source File Array"); RDIB_SourceFile **src_file_arr = push_array_no_zero(scratch.arena, RDIB_SourceFile *, total_src_file_count); for (U64 chunk_idx = 0, cursor = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { src_file_arr[cursor++] = &chunk->v[i]; } } ProfEnd(); ProfBegin("Init Task Context"); RDIB_SrcLineMapsTask task = {0}; task.src_file_arr = src_file_arr; task.out_line_counts = push_array_no_zero(scratch.arena, U32, total_src_file_count); task.out_voff_counts = push_array_no_zero(scratch.arena, U32, total_src_file_count); task.out_line_nums = push_array_no_zero(scratch.arena, U32 *, total_src_file_count); task.out_line_ranges = push_array_no_zero(scratch.arena, U32 *, total_src_file_count); task.out_voffs = push_array_no_zero(scratch.arena, U64 *, total_src_file_count); ProfEnd(); ProfBegin("Build Source Line Maps"); tp_for_parallel(tp, arena, total_src_file_count, rdib_build_src_line_map_task, &task); ProfEnd(); ProfBegin("Fill out Source Line Maps"); RDIB_DataSection src_line_maps_sect = { .tag = RDI_SectionKind_SourceLineMaps }; RDIB_DataSection src_line_nums_sect = { .tag = RDI_SectionKind_SourceLineMapNumbers }; RDIB_DataSection src_line_ranges_sect = { .tag = RDI_SectionKind_SourceLineMapRanges }; RDIB_DataSection src_line_voffs_sect = { .tag = RDI_SectionKind_SourceLineMapVOffs }; ProfBegin("Push"); RDI_SourceLineMap *src_line_maps = push_array_no_zero(arena->v[0], RDI_SourceLineMap, total_src_file_count + 1); ProfEnd(); U64 src_line_map_cursor = 0; U64 line_num_cursor = 0; U64 line_range_cursor = 0; U64 voff_cursor = 0; // zero-out null source line map MemoryZeroStruct(&src_line_maps[src_line_map_cursor]); ++src_line_map_cursor; for (U64 chunk_idx = 0; chunk_idx < src_file_chunk_count; ++chunk_idx) { RDIB_SourceFileChunk *chunk = src_file_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_SourceFile *src_file = chunk->v + i; U64 src_file_idx = rdib_idx_from_source_file(src_file); if (task.out_line_counts[src_file_idx] > 0) { src_file->src_line_map_idx = src_line_map_cursor; RDI_SourceLineMap *sm = src_line_maps + src_line_map_cursor++; sm->line_count = task.out_line_counts[src_file_idx]; sm->voff_count = task.out_voff_counts[src_file_idx]; sm->line_map_nums_base_idx = line_num_cursor; sm->line_map_range_base_idx = line_range_cursor; sm->line_map_voff_base_idx = voff_cursor; str8_list_push(arena->v[0], &src_line_nums_sect.data, str8_array(task.out_line_nums[src_file_idx], task.out_line_counts[src_file_idx])); str8_list_push(arena->v[0], &src_line_ranges_sect.data, str8_array(task.out_line_ranges[src_file_idx], task.out_line_counts[src_file_idx] + 1)); str8_list_push(arena->v[0], &src_line_voffs_sect.data, str8_array(task.out_voffs[src_file_idx], task.out_voff_counts[src_file_idx])); line_num_cursor += task.out_line_counts[src_file_idx]; line_range_cursor += task.out_line_counts[src_file_idx] + 1; voff_cursor += task.out_voff_counts[src_file_idx]; } else { src_file->src_line_map_idx = 0; } } } ProfEnd(); str8_list_push(arena->v[0], &src_line_maps_sect.data, str8_array(src_line_maps, src_line_map_cursor)); rdib_data_section_list_push(arena->v[0], sect_list, src_line_maps_sect); rdib_data_section_list_push(arena->v[0], sect_list, src_line_nums_sect); rdib_data_section_list_push(arena->v[0], sect_list, src_line_ranges_sect); rdib_data_section_list_push(arena->v[0], sect_list, src_line_voffs_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_build_line_tables_task) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); RDIB_BuildLineTablesTask *task = raw_task; Rng1U64 range = task->ranges[task_id]; for (U64 chunk_idx = range.min; chunk_idx < range.max; ++chunk_idx) { RDIB_LineTableChunk *chunk = task->chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_LineTable *line_table = &chunk->v[i]; U64 line_table_idx = chunk->base + i; U64 total_line_count = 0; for (RDIB_LineTableFragment *frag = line_table->first; frag != 0; frag = frag->next_line_table) { total_line_count += frag->line_count + /* range terminator */ 1; } if (total_line_count > 0) { struct Value { U32 src_file_idx; U32 line_num; U16 col_first; U16 col_opl; }; KeyValuePair *pairs = push_array_no_zero(scratch.arena, KeyValuePair, total_line_count); struct Value *values = push_array_no_zero(scratch.arena, struct Value, total_line_count); U64 pair_cursor = 0; for (RDIB_LineTableFragment *frag = line_table->first; frag != 0; frag = frag->next_line_table) { for (U64 line_idx = 0; line_idx < frag->line_count; ++line_idx, ++pair_cursor) { struct Value *value = &values[pair_cursor]; KeyValuePair *pair = &pairs[pair_cursor]; value->src_file_idx = rdib_idx_from_source_file(frag->src_file); value->line_num = frag->line_nums[line_idx]; if (frag->col_count > 0) { value->col_first = frag->col_nums[line_idx*2]; value->col_opl = frag->col_nums[line_idx*2 + 1]; } else { value->col_first = 0; value->col_opl = 0; } pair->key_u64 = frag->voffs[line_idx]; pair->value_raw = value; } // emit terminator { KeyValuePair *pair = &pairs[pair_cursor]; struct Value *value = &values[pair_cursor]; pair_cursor += 1; value->src_file_idx = 0; value->line_num = 0; value->col_first = 0; value->col_opl = 0; pair->key_u64 = frag->voffs[frag->line_count]; pair->value_raw = value; } } // sort on virtual offset sort_key_value_pairs_as_u64(pairs, pair_cursor); // fill out RDI_Line output U64 line_count = pair_cursor + 1; U64 *voffs = push_array_no_zero(arena, U64, line_count); RDI_Line *lines = push_array_no_zero(arena, RDI_Line, line_count); U64 line_cursor = 0; for (U64 line_idx = 0; line_idx < pair_cursor; ++line_idx) { // remove terminator if there is a real line number if (line_idx + 1 < pair_cursor && pairs[line_idx].key_u64 == pairs[line_idx+1].key_u64) { continue; } struct Value *value = pairs[line_idx].value_raw; voffs[line_cursor] = pairs[line_idx].key_u64; lines[line_cursor].file_idx = value->src_file_idx; lines[line_cursor].line_num = value->line_num; line_cursor += 1; } // fill out terminators voffs[line_cursor] = ~0llu; MemoryZeroStruct(&lines[line_cursor]); line_cursor += 1; // fill out line table output task->out_line_table_counts[line_table_idx] = line_cursor; task->out_line_table_voffs[line_table_idx] = voffs; task->out_line_table_lines[line_table_idx] = lines; } else { task->out_line_table_counts[line_table_idx] = 0; task->out_line_table_voffs[line_table_idx] = 0; task->out_line_table_lines[line_table_idx] = 0; } } } scratch_end(scratch); ProfEnd(); } internal void rdib_data_sections_from_line_tables(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 total_line_table_count, U64 chunk_count, RDIB_LineTableChunk **chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); ProfBegin("Build Line Tables"); RDIB_BuildLineTablesTask task = {0}; task.chunks = chunks; task.ranges = tp_divide_work(scratch.arena, chunk_count, tp->worker_count); task.out_line_table_counts = push_array_no_zero(scratch.arena, U64, total_line_table_count); task.out_line_table_voffs = push_array_no_zero(scratch.arena, U64 *, total_line_table_count); task.out_line_table_lines = push_array_no_zero(scratch.arena, RDI_Line *, total_line_table_count); tp_for_parallel(tp, arena, tp->worker_count, rdib_build_line_tables_task, &task); ProfEnd(); RDIB_DataSection line_tables_sect = { .tag = RDI_SectionKind_LineTables }; RDIB_DataSection line_table_voffs_sect = { .tag = RDI_SectionKind_LineInfoVOffs }; RDIB_DataSection line_table_lines_sect = { .tag = RDI_SectionKind_LineInfoLines }; RDIB_DataSection line_table_cols_sect = { .tag = RDI_SectionKind_LineInfoColumns }; ProfBegin("Fill out Line Tables"); ProfBegin("Push"); RDI_LineTable *line_tables_rdi = push_array_no_zero(arena->v[0], RDI_LineTable, total_line_table_count); ProfEnd(); U64 line_table_cursor = 0; U64 line_table_voff_cursor = 0; U64 line_table_line_cursor = 0; for (U64 chunk_idx = 0; chunk_idx < chunk_count; ++chunk_idx) { RDIB_LineTableChunk *chunk = chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_LineTable *src = &chunk->v[i]; U64 src_idx = rdib_idx_from_line_table(src); if (task.out_line_table_counts[src_idx] > 0) { RDI_LineTable *dst = &line_tables_rdi[line_table_cursor]; src->output_array_idx = line_table_cursor; dst->voffs_base_idx = line_table_voff_cursor; dst->lines_base_idx = line_table_line_cursor; dst->cols_base_idx = 0; dst->lines_count = task.out_line_table_counts[src_idx] - 1; dst->cols_count = 0; str8_list_push(arena->v[0], &line_table_voffs_sect.data, str8_array(task.out_line_table_voffs[src_idx], task.out_line_table_counts[src_idx])); str8_list_push(arena->v[0], &line_table_lines_sect.data, str8_array(task.out_line_table_lines[src_idx], task.out_line_table_counts[src_idx])); line_table_voff_cursor += task.out_line_table_counts[src_idx]; line_table_line_cursor += task.out_line_table_counts[src_idx]; line_table_cursor += 1; } else { src->output_array_idx = 0; } } } str8_list_push(arena->v[0], &line_tables_sect.data, str8_array(line_tables_rdi, line_table_cursor)); ProfEnd(); rdib_data_section_list_push(arena->v[0], sect_list, line_tables_sect); rdib_data_section_list_push(arena->v[0], sect_list, line_table_voffs_sect); rdib_data_section_list_push(arena->v[0], sect_list, line_table_lines_sect); rdib_data_section_list_push(arena->v[0], sect_list, line_table_cols_sect); scratch_end(scratch); ProfEnd(); } internal THREAD_POOL_TASK_FUNC(rdib_fill_src_files_task) { RDIB_FillSourceFilesTask *task = raw_task; for (U64 chunk_idx = task->ranges[task_id].min; chunk_idx < task->ranges[task_id].max; ++chunk_idx) { RDIB_SourceFileChunk *chunk = task->src_file_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_SourceFile *src = chunk->v + i; U32 src_file_idx = rdib_idx_from_source_file(src); RDI_SourceFile *dst = task->src_files_dst + src_file_idx; dst->file_path_node_idx = rdib_idx_from_path_tree(task->path_tree, src->file_path); dst->normal_full_path_string_idx = rdib_idx_from_string_map(task->string_map, src->normal_full_path); dst->source_line_map_idx = src->src_line_map_idx; } } } internal void rdib_data_sections_from_source_files(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_file_chunks) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); RDIB_FillSourceFilesTask task = {0}; task.ranges = tp_divide_work(scratch.arena, src_file_chunk_count, tp->worker_count); task.string_map = string_map; task.path_tree = path_tree; task.src_file_chunks = src_file_chunks; task.src_files_dst = push_array_no_zero(arena->v[0], RDI_SourceFile, total_src_file_count); tp_for_parallel(tp, 0, tp->worker_count, rdib_fill_src_files_task, &task); RDIB_DataSection src_files_sect = { .tag = RDI_SectionKind_SourceFiles }; str8_list_push(arena->v[0], &src_files_sect.data, str8_array(task.src_files_dst, total_src_file_count)); rdib_data_section_list_push(arena->v[0], sect_list, src_files_sect); scratch_end(scratch); ProfEnd(); } internal void rdib_data_sections_from_inline_sites(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_inline_site_count, U64 inline_site_chunk_count, RDIB_InlineSiteChunk **inline_site_chunks) { ProfBeginFunction(); RDI_InlineSite *dst_arr = push_array(arena, RDI_InlineSite, total_inline_site_count); for (U64 chunk_idx = 0; chunk_idx < inline_site_chunk_count; ++chunk_idx) { RDIB_InlineSiteChunk *chunk = inline_site_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { RDIB_InlineSite *src = &chunk->v[i]; U64 idx = rdib_idx_from_inline_site(src); RDI_InlineSite *dst = &dst_arr[idx]; dst->name_string_idx = rdib_idx_from_string_map(string_map, src->name); dst->type_idx = rdib_idx_from_type(src->type); dst->owner_type_idx = rdib_idx_from_type(src->owner); dst->line_table_idx = src->line_table->output_array_idx; } } RDIB_DataSection inline_site_sect = { .tag = RDI_SectionKind_InlineSites }; str8_list_push(arena, &inline_site_sect.data, str8_array(dst_arr, total_inline_site_count)); rdib_data_section_list_push(arena, sect_list, inline_site_sect); ProfEnd(); } internal void rdib_data_sections_from_checksums(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list) { NotImplemented; } //////////////////////////////// internal RDIB_Input rdib_init_input(Arena *arena) { ProfBeginFunction(); RDIB_Input input = {0}; input.unit_chunk_cap = 128; input.src_file_chunk_cap = 4096; input.symbol_chunk_cap = 4096; input.line_table_cap = 4096; input.inline_site_cap = 4096; input.type_cap = 1024; input.udt_cap = 4096; RDIB_SourceFile *null_src_file = rdib_source_file_chunk_list_push_zero(arena, &input.src_files, 1); RDIB_LineTable *null_line_table = rdib_line_table_chunk_list_push_zero (arena, &input.line_tables, 1); RDIB_LineTableFragment *null_frag = rdib_line_table_push (arena, null_line_table); RDIB_Type *null_type = rdib_type_chunk_list_push_zero (arena, &input.types, 1); RDIB_Scope *null_scope = rdib_scope_chunk_list_push_zero (arena, &input.scopes, 1); RDIB_Unit *null_unit = rdib_unit_chunk_list_push_zero (arena, &input.units, 1); RDIB_Procedure *null_proc = rdib_procedure_chunk_list_push_zero (arena, &input.procs, 1); RDIB_Variable *null_local = rdib_variable_chunk_list_push_zero (arena, &input.locals, 1); RDIB_Variable *null_gvar = rdib_variable_chunk_list_push_zero (arena, &input.gvars, 1); RDIB_Variable *null_tvar = rdib_variable_chunk_list_push_zero (arena, &input.tvars, 1); RDIB_UDTMember *null_udt_member = rdib_udt_member_chunk_list_push_zero (arena, &input.udt_members, 1); RDIB_UDTMember *null_enum_member = rdib_udt_member_chunk_list_push_zero (arena, &input.enum_members, 1); RDIB_InlineSite *null_inline_site = rdib_inline_site_chunk_list_push_zero(arena, &input.inline_sites, 1); { // Line Table Fragment null_frag->src_file = null_src_file; null_frag->voffs = push_array(arena, U64, 1); // Source File null_src_file->line_table_frags = null_frag; // Unit null_unit->arch = RDI_Arch_NULL; null_unit->unit_name = str8_zero(); null_unit->compiler_name = str8_zero(); null_unit->source_file = str8_zero(); null_unit->object_file = str8_zero(); null_unit->archive_file = str8_zero(); null_unit->build_path = str8_zero(); null_unit->virt_range_count = 1; null_unit->virt_ranges = push_array(arena, Rng1U64, 1); null_unit->virt_ranges[0] = rng_1u64(0,0); null_unit->line_table = null_line_table; // Scope rng1u64_list_push(arena, &null_scope->ranges, rng_1u64(0,max_U32)); // Location RDIB_Location null_loc = {0}; rng1u64_list_push(arena, &null_loc.ranges, rng_1u64(0,0)); RDIB_LocationList null_loc_list = {0}; rdib_location_list_push(arena, &null_loc_list, null_loc); // Proc null_proc->type = null_type; null_proc->scope = null_scope; // Global Var null_gvar->link_flags = RDI_LinkFlag_External; null_gvar->type = null_type; null_gvar->locations = null_loc_list; // Thread Var null_tvar->link_flags = RDI_LinkFlag_External; null_tvar->type = null_type; null_tvar->locations = null_loc_list; // Local Var null_local->type = null_type; null_local->locations = null_loc_list; // Inline Site null_inline_site->type = null_type; null_inline_site->owner = 0; null_inline_site->line_table = null_line_table; } input.null_src_file = null_src_file; input.null_line_table = null_line_table; input.null_frag = null_frag; input.null_type = null_type; input.null_scope = null_scope; input.null_unit = null_unit; input.null_proc = null_proc; input.null_local = null_local; input.null_gvar = null_gvar; input.null_tvar = null_tvar; input.null_udt_member = null_udt_member; input.null_enum_member = null_enum_member; input.null_inline_site = null_inline_site; input.variadic_type = rdib_type_chunk_list_push(arena, &input.types, 1); input.variadic_type->kind = RDI_TypeKind_Variadic; ProfEnd(); return input; } internal String8List rdib_finish(TP_Context *tp, TP_Arena *arena, RDIB_Input *input) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); RDIB_UnitChunkList all_units = {0}; RDIB_SourceFileChunkList all_src_files = {0}; RDIB_LineTableChunkList all_line_tables = {0}; RDIB_VariableChunkList all_locals = {0}; RDIB_VariableChunkList all_tvars = {0}; RDIB_VariableChunkList all_gvars = {0}; RDIB_ProcedureChunkList all_procs = {0}; RDIB_ScopeChunkList all_scopes = {0}; RDIB_InlineSiteChunkList all_inline_sites = {0}; RDIB_TypeChunkList all_types = {0}; RDIB_TypeChunkList all_param_types = {0}; RDIB_TypeChunkList all_udt_member_types = {0}; RDIB_TypeChunkList all_enum_member_types = {0}; RDIB_UDTMemberChunkList all_udt_members = {0}; RDIB_UDTMemberChunkList all_enum_members = {0}; //U64 type_chunk_count = types.count; //U64 struct_chunk_count = struct_list.count; //U64 union_chunk_count = union_list.count; //U64 enum_chunk_count = enum_list.count; //U64 total_struct_count = rdib_type_chunk_list_total_count(struct_list); //U64 total_union_count = rdib_type_chunk_list_total_count(union_list); //U64 total_enum_count = rdib_type_chunk_list_total_count(enum_list); //U64 extern_gvar_chunk_count = extern_gvars.count; //U64 extern_tvar_chunk_count = extern_tvars.count; //U64 extern_proc_chunk_count = extern_procs.count; //U64 static_gvar_chunk_count = static_gvars.count; //U64 static_tvar_chunk_count = static_tvars.count; //U64 static_proc_chunk_count = static_procs.count; //U64 total_extern_gvar_count = rdib_variable_chunk_list_total_count (extern_gvars); //U64 total_extern_tvar_count = rdib_variable_chunk_list_total_count (extern_tvars); //U64 total_extern_proc_count = rdib_procedure_chunk_list_total_count(extern_procs); ProfBegin("Concat Chunk Lists"); rdib_unit_chunk_list_concat_in_place (&all_units, &input->units ); rdib_source_file_chunk_list_concat_in_place(&all_src_files, &input->src_files ); rdib_line_table_chunk_list_concat_in_place (&all_line_tables, &input->line_tables ); rdib_scope_chunk_list_concat_in_place (&all_scopes, &input->scopes ); rdib_variable_chunk_list_concat_in_place (&all_locals, &input->locals ); rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->tvars ); rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->extern_tvars ); rdib_variable_chunk_list_concat_in_place (&all_tvars, &input->static_tvars ); rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->gvars ); rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->extern_gvars ); rdib_variable_chunk_list_concat_in_place (&all_gvars, &input->static_gvars ); rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->procs ); rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->extern_procs ); rdib_procedure_chunk_list_concat_in_place (&all_procs, &input->static_procs ); rdib_inline_site_chunk_list_concat_in_place(&all_inline_sites, &input->inline_sites ); rdib_type_chunk_list_concat_in_place (&all_types, &input->types ); rdib_type_chunk_list_concat_in_place (&all_types, &input->struct_list ); rdib_type_chunk_list_concat_in_place (&all_types, &input->union_list ); rdib_type_chunk_list_concat_in_place (&all_types, &input->enum_list ); rdib_type_chunk_list_concat_in_place (&all_param_types, &input->param_types ); rdib_type_chunk_list_concat_in_place (&all_udt_member_types, &input->member_types ); rdib_type_chunk_list_concat_in_place (&all_enum_member_types, &input->enum_types ); rdib_udt_member_chunk_list_concat_in_place (&all_udt_members, &input->udt_members ); rdib_udt_member_chunk_list_concat_in_place (&all_enum_members, &input->enum_members ); ProfEnd(); ProfBegin("Chunk Lists -> Chunk Arrays"); RDIB_UnitChunk **all_unit_chunks = rdib_array_from_unit_chunk_list (scratch.arena, all_units ); RDIB_SourceFileChunk **all_src_file_chunks = rdib_array_from_source_file_chunk_list(scratch.arena, all_src_files ); RDIB_LineTableChunk **all_line_table_chunks = rdib_array_from_line_table_chunk_list (scratch.arena, all_line_tables ); RDIB_ScopeChunk **all_scope_chunks = rdib_array_from_scope_chunk_list (scratch.arena, all_scopes ); RDIB_VariableChunk **all_local_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_locals ); RDIB_VariableChunk **all_gvar_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_gvars ); RDIB_VariableChunk **all_tvar_chunks = rdib_array_from_variable_chunk_list (scratch.arena, all_tvars ); RDIB_ProcedureChunk **all_proc_chunks = rdib_array_from_procedure_chunk_list (scratch.arena, all_procs ); RDIB_InlineSiteChunk **all_inline_site_chunks = rdib_array_from_inline_site_chunk_list(scratch.arena, all_inline_sites ); RDIB_TypeChunk **all_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_types ); //RDIB_TypeChunk **all_param_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_param_types ); RDIB_TypeChunk **all_udt_member_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_udt_member_types ); RDIB_TypeChunk **all_enum_member_type_chunks = rdib_array_from_type_chunk_list (scratch.arena, all_enum_member_types); RDIB_UDTMemberChunk **all_udt_member_chunks = rdib_array_from_udt_member_chunk_list (scratch.arena, all_udt_members ); RDIB_UDTMemberChunk **all_enum_member_chunks = rdib_array_from_udt_member_chunk_list (scratch.arena, all_enum_members ); ProfEnd(); ProfBegin("Count Symbols, Types, and etc."); U64 total_unit_count = rdib_unit_chunk_list_total_count (all_units ); U64 total_src_file_count = rdib_source_file_chunk_list_total_count(all_src_files ); U64 total_line_table_count = rdib_line_table_chunk_list_total_count (all_line_tables ); U64 total_scope_count = rdib_scope_chunk_list_total_count (all_scopes ); U64 total_local_count = rdib_variable_chunk_list_total_count (all_locals ); U64 total_inline_site_count = rdib_inline_site_chunk_list_total_count(all_inline_sites ); U64 total_udt_member_count = rdib_udt_member_chunk_list_total_count (all_udt_members ); U64 total_enum_member_count = rdib_udt_member_chunk_list_total_count (all_enum_members ); U64 total_type_count = rdib_type_chunk_list_total_count (all_types ); U64 total_param_type_count = rdib_type_chunk_list_total_count (all_param_types ); //U64 total_udt_member_type_count = rdib_type_chunk_list_total_count (all_udt_member_types ); //U64 total_enum_member_type_count = rdib_type_chunk_list_total_count (all_enum_member_types); U64 total_tvar_count = rdib_variable_chunk_list_total_count (all_tvars ); U64 total_gvar_count = rdib_variable_chunk_list_total_count (all_gvars ); U64 total_proc_count = rdib_procedure_chunk_list_total_count (all_procs ); ProfEnd(); // +1 to skip nulls //RDIB_VariableChunk **extern_gvar_chunks = all_gvar_chunks + 1; //RDIB_VariableChunk **extern_tvar_chunks = all_tvar_chunks + 1; //RDIB_ProcedureChunk **extern_proc_chunks = all_proc_chunks + 1; //RDIB_VariableChunk **static_gvar_chunks = extern_gvar_chunks + extern_gvar_chunk_count; //RDIB_VariableChunk **static_tvar_chunks = extern_tvar_chunks + extern_tvar_chunk_count; //RDIB_ProcedureChunk **static_proc_chunks = extern_proc_chunks + extern_proc_chunk_count; //RDIB_TypeChunk **type_chunks = all_type_chunks + 1; //RDIB_TypeChunk **struct_chunks = type_chunks + type_chunk_count; //RDIB_TypeChunk **union_chunks = struct_chunks + struct_chunk_count; //RDIB_TypeChunk **enum_chunks = union_chunks + union_chunk_count; //RDIB_TypeChunk **udt_chunks = struct_chunks; //U64 udt_chunk_count = struct_chunk_count + union_chunk_count + enum_chunk_count; ProfBegin("Assign Type Indices"); U64 total_type_node_count = 1; { struct TypeNode { struct TypeNode *next; RDIB_Type *type; }; struct TypeNode *stack = 0; struct TypeNode *free_nodes = 0; #define push_node(t) do { \ if (((RDIB_Type*)(t))->kind == RDI_TypeKindExt_VirtualTable) break; \ struct TypeNode *n; \ if (free_nodes == 0) { \ n = push_array(scratch.arena, struct TypeNode, 1); \ } else { \ n = free_nodes; \ SLLStackPop(free_nodes); \ } \ Assert(t); \ n->type = t; \ SLLStackPush(stack, n); \ } while (0) for (U64 chunk_idx = 0; chunk_idx < all_types.count; ++chunk_idx) { RDIB_TypeChunk *chunk = all_type_chunks[chunk_idx]; for (U64 i = 0; i < chunk->count; ++i) { push_node(&chunk->v[i]); for (struct TypeNode *cursor = stack; cursor != 0; cursor = cursor->next) { if (cursor->type->kind == RDI_TypeKind_NULL){ // no type refs } else if (cursor->type->kind == RDI_TypeKind_Variadic) { // no type refs } else if (cursor->type->kind == RDI_TypeKind_Union) { // no type refs } else if (RDI_IsBuiltinType(cursor->type->kind)) { // no type refs } else if (cursor->type->kind == RDI_TypeKind_IncompleteStruct) { // no type refs } else if (cursor->type->kind == RDI_TypeKind_IncompleteUnion) { // no type refs } else if (cursor->type->kind == RDI_TypeKind_IncompleteClass) { // no type refs } else if (cursor->type->kind == RDI_TypeKind_IncompleteEnum) { push_node(cursor->type->udt.enum_type.base_type); } else if (cursor->type->kind == RDI_TypeKind_Modifier) { push_node(cursor->type->modifier.type_ref); } else if (RDI_IsPtrType(cursor->type->kind)) { push_node(cursor->type->ptr.type_ref); } else if (cursor->type->kind == RDI_TypeKind_Function) { push_node(cursor->type->func.return_type); push_node(cursor->type->func.params_type); RDIB_Type *params = cursor->type->func.params_type; for (U64 i = 0; i < params->params.count; ++i) { push_node(params->params.types[i]); } } else if (cursor->type->kind == RDI_TypeKind_Method) { push_node(cursor->type->method.class_type); push_node(cursor->type->method.this_type); push_node(cursor->type->method.return_type); RDIB_Type *params = cursor->type->method.params_type; for (U64 i = 0; i < params->params.count; ++i) { push_node(params->params.types[i]); } } else if (cursor->type->kind == RDI_TypeKindExt_StaticMethod) { push_node(cursor->type->static_method.class_type); push_node(cursor->type->static_method.return_type); RDIB_Type *params = cursor->type->static_method.params_type; for (U64 i = 0; i < params->params.count; ++i) { push_node(params->params.types[i]); } } else if (cursor->type->kind == RDI_TypeKind_Bitfield) { push_node(cursor->type->bitfield.value_type); } else if (cursor->type->kind == RDI_TypeKind_Array) { push_node(cursor->type->array.entry_type); } else if (cursor->type->kind == RDI_TypeKind_Struct || cursor->type->kind == RDI_TypeKind_Class) { if (cursor->type->udt.struct_type.derived != 0) { push_node(cursor->type->udt.struct_type.derived); } //push_node(cursor->type->udt.struct_type.vtshape); } else if (cursor->type->kind == RDI_TypeKind_Enum) { push_node(cursor->type->udt.enum_type.base_type); } else if (cursor->type->kind > RDI_TypeKindExt_Lo) { InvalidPath; } else { InvalidPath; } } for (struct TypeNode *cursor = stack; cursor != 0; cursor = cursor->next) { // was this type visisted? if (cursor->type != input->null_type && cursor->type->final_idx == 0) { cursor->type->final_idx = total_type_node_count; ++total_type_node_count; } } free_nodes = stack; stack = 0; } } #undef push_node } ProfEnd(); ProfBegin("Type Stats"); RDIB_TypeStats type_stats = {0}; { type_stats.udt_counts = push_array(scratch.arena, U64, all_types.count); RDIB_TypeStatsTask task = { .chunks = all_type_chunks, .type_stats = &type_stats }; tp_for_parallel(tp, 0, all_types.count, rdib_type_stats_task, &task); } ProfEnd(); RDIB_PathTree *path_tree = rdib_build_path_tree(arena->v[0], tp->worker_count, input->null_src_file, all_units.count, all_unit_chunks, all_src_files.count, all_src_file_chunks); // loop over structs and build a map with every possible string ProfBegin("String Map"); RDIB_StringMap *string_map; { U64 top_level_string_count = 2; U64 sect_string_count = 1; U64 src_file_string_count = 1; U64 unit_string_count = 6; U64 variable_string_count = 2; U64 procedure_string_count = 2; U64 scope_string_count = 0; U64 inline_site_string_count = 0; U64 member_string_count = 2; U64 type_string_count = 3; U64 path_tree_node_count = 1; U64 total_string_count = 1 /* :string_map_null */ + 1 * top_level_string_count + input->sect_count * sect_string_count + total_src_file_count * src_file_string_count + total_unit_count * unit_string_count + total_local_count * variable_string_count + total_gvar_count * variable_string_count + total_tvar_count * variable_string_count + total_proc_count * procedure_string_count + total_inline_site_count * inline_site_string_count + total_udt_member_count * member_string_count + total_enum_member_count * member_string_count + total_type_count * type_string_count + path_tree->node_count * path_tree_node_count + total_scope_count * scope_string_count; string_map = rdib_init_string_map(arena->v[0], total_string_count); RDIB_CollectStringsTask task = {0}; task.string_map = string_map; task.string_map_update_func = rdib_string_map_update_null; task.free_buckets = push_array(scratch.arena, RDIB_StringMapBucket *, tp->worker_count); task.element_indices = push_array(scratch.arena, U64, tp->worker_count); // :string_map_null rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, str8_lit("")); // top level info rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, input->top_level_info.exe_name); rdib_string_map_insert_string_table_item(arena->v[0], &task, 0, input->top_level_info.producer_string); ProfBegin("Sections"); task.ranges = tp_divide_work(scratch.arena, input->sect_count, tp->worker_count); task.sects = input->sections; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_sects_task, &task); ProfEnd(); ProfBegin("Units"); task.ranges = tp_divide_work(scratch.arena, all_units.count, tp->worker_count); task.units = all_unit_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_units_task, &task); ProfEnd(); ProfBegin("Source Files"); task.ranges = tp_divide_work(scratch.arena, all_src_files.count, tp->worker_count); task.src_file_chunks = all_src_file_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_source_files_task, &task); ProfEnd(); ProfBegin("Locals"); task.ranges = tp_divide_work(scratch.arena, all_locals.count, tp->worker_count); task.vars = all_local_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); ProfEnd(); ProfBegin("Global Variables"); task.ranges = tp_divide_work(scratch.arena, all_gvars.count, tp->worker_count); task.vars = all_gvar_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); ProfEnd(); ProfBegin("Thread Variables"); task.ranges = tp_divide_work(scratch.arena, all_tvars.count, tp->worker_count); task.vars = all_tvar_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_vars_task, &task); ProfEnd(); ProfBegin("Procedures"); task.ranges = tp_divide_work(scratch.arena, all_procs.count, tp->worker_count); task.procs = all_proc_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_procs_task, &task); ProfEnd(); ProfBegin("Inline Sites"); task.ranges = tp_divide_work(scratch.arena, all_inline_sites.count, tp->worker_count); task.inline_sites = all_inline_site_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_inline_sites_task, &task); ProfEnd(); ProfBegin("UDT Members"); task.ranges = tp_divide_work(scratch.arena, all_udt_members.count, tp->worker_count); task.udt_members = all_udt_member_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_udt_members_task, &task); ProfEnd(); ProfBegin("Enum Members"); task.ranges = tp_divide_work(scratch.arena, all_enum_members.count, tp->worker_count); task.udt_members = all_enum_member_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_enum_members_task, &task); ProfEnd(); ProfBegin("Types"); task.ranges = tp_divide_work(scratch.arena, all_types.count, tp->worker_count); task.types = all_type_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_types_task, &task); ProfEnd(); ProfBegin("Path Tree"); task.ranges = tp_divide_work(scratch.arena, path_tree->list_count, tp->worker_count); task.path_node_lists = path_tree->node_lists; tp_for_parallel(tp, arena, tp->worker_count, rdib_collect_strings_path_nodes_task, &task); ProfEnd(); } ProfEnd(); ProfBegin("Name Maps"); RDIB_StringMap *name_maps[RDI_NameMapKind_COUNT] = {0}; { name_maps[RDI_NameMapKind_NULL ] = rdib_init_string_map(scratch.arena, 1 ); name_maps[RDI_NameMapKind_GlobalVariables ] = rdib_init_string_map(scratch.arena, total_gvar_count ); name_maps[RDI_NameMapKind_ThreadVariables ] = rdib_init_string_map(scratch.arena, total_tvar_count ); name_maps[RDI_NameMapKind_Procedures ] = rdib_init_string_map(scratch.arena, total_proc_count ); name_maps[RDI_NameMapKind_Types ] = rdib_init_string_map(scratch.arena, total_type_count ); name_maps[RDI_NameMapKind_LinkNameProcedures] = rdib_init_string_map(scratch.arena, total_proc_count ); name_maps[RDI_NameMapKind_NormalSourcePaths ] = rdib_init_string_map(scratch.arena, total_src_file_count); RDIB_CollectStringsTask task = {0}; task.string_map = 0; task.string_map_update_func = rdib_string_map_update_concat_void_list_atomic; task.free_buckets = push_array(scratch.arena, RDIB_StringMapBucket *, tp->worker_count); task.element_indices = push_array(scratch.arena, U64, tp->worker_count); ProfBegin("Global Variables"); task.string_map = name_maps[RDI_NameMapKind_GlobalVariables]; task.ranges = tp_divide_work(scratch.arena, all_gvars.count, tp->worker_count); task.vars = all_gvar_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_var_task, &task); ProfEnd(); ProfBegin("Thread Variables"); task.string_map = name_maps[RDI_NameMapKind_ThreadVariables]; task.ranges = tp_divide_work(scratch.arena, all_tvars.count, tp->worker_count); task.vars = all_tvar_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_var_task, &task); ProfEnd(); ProfBegin("Procedure Names"); task.string_map = name_maps[RDI_NameMapKind_Procedures]; task.ranges = tp_divide_work(scratch.arena, all_procs.count, tp->worker_count); task.procs = all_proc_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_procedure_task, &task); ProfEnd(); ProfBegin("Types"); task.string_map = name_maps[RDI_NameMapKind_Types]; task.ranges = tp_divide_work(scratch.arena, all_types.count, tp->worker_count); task.types = all_type_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_types_task, &task); ProfEnd(); ProfBegin("Normal Source Paths"); task.string_map = name_maps[RDI_NameMapKind_NormalSourcePaths]; task.ranges = tp_divide_work(scratch.arena, all_src_files.count, tp->worker_count); task.src_file_chunks = all_src_file_chunks; tp_for_parallel(tp, arena, tp->worker_count, rdib_name_map_normal_paths_task, &task); ProfEnd(); } ProfEnd(); ProfBeginDynamic("Extract String Table Buckets [Cap: %llu]", string_map->cap); U64 string_map_bucket_count; RDIB_StringMapBucket **string_map_buckets = rdib_extant_buckets_from_string_map(tp, scratch.arena, string_map, &string_map_bucket_count); rdib_string_map_sort_buckets(tp, string_map_buckets, string_map_bucket_count, tp->worker_count); rdib_string_map_assign_indices(string_map_buckets, string_map_bucket_count); ProfEnd(); ProfBegin("Extract Name Maps Buckets"); RDIB_StringMapBucket **name_map_buckets[RDI_NameMapKind_COUNT]; U64 name_map_bucket_counts[RDI_NameMapKind_COUNT]; for (U64 i = 0; i < ArrayCount(name_map_buckets); ++i) { ProfBeginDynamic("Name Map: %.*s", str8_varg(rdi_string_from_name_map_kind(i))); name_map_buckets[i] = rdib_extant_buckets_from_string_map(tp, scratch.arena, name_maps[i], &name_map_bucket_counts[i]); rdib_string_map_sort_buckets(tp, name_map_buckets[i], name_map_bucket_counts[i], tp->worker_count); rdib_string_map_assign_indices(name_map_buckets[i], name_map_bucket_counts[i]); ProfEnd(); } ProfEnd(); ProfBegin("Index Run Map"); RDIB_IndexRunMap *idx_run_map; RDIB_IndexRunBucket **idx_run_buckets; U64 idx_run_bucket_count; { // TODO: we over-allocate for name map index runs since not every bucket has > 1 value U64 total_name_map_value_count = 0; for (U64 i = 0; i < ArrayCount(name_map_bucket_counts); ++i) { total_name_map_value_count += name_map_bucket_counts[i]; } // rough bucket estimate U64 idx_run_cap = (total_param_type_count + total_name_map_value_count) * 2; idx_run_map = rdib_init_index_run_map(arena->v[0], idx_run_cap); // setup task context RDIB_BuildIndexRunsTask task = {0}; task.idx_run_map = idx_run_map; task.free_buckets = push_array(scratch.arena, RDIB_IndexRunBucket *, tp->worker_count); ProfBegin("Type Params Pass"); task.type_chunks = all_type_chunks; tp_for_parallel(tp, arena, all_types.count, rdib_build_idx_runs_params_task, &task); task.sorter_idx += 1; ProfEnd(); ProfBegin("Name Maps Pass - Build Index Runs"); for (U64 name_map_kind = 0; name_map_kind < ArrayCount(name_maps); ++name_map_kind) { ProfBeginDynamic("Name Map: %.*s", str8_varg(rdi_string_from_name_map_kind(name_map_kind))); task.name_map_kind = name_map_kind; task.ranges = tp_divide_work(scratch.arena, name_map_bucket_counts[name_map_kind], tp->worker_count); task.name_map_buckets = name_map_buckets[name_map_kind]; tp_for_parallel(tp, arena, tp->worker_count, rdib_build_idx_runs_name_map_buckets_task, &task); task.sorter_idx += 1; ProfEnd(); } ProfEnd(); idx_run_buckets = rdib_extant_buckets_from_index_run_map(tp, arena->v[0], idx_run_map, &idx_run_bucket_count); rdib_index_run_map_sort_buckets(tp, idx_run_buckets, idx_run_bucket_count, task.sorter_idx); rdib_index_run_map_assign_indices(idx_run_buckets, idx_run_bucket_count); } ProfEnd(); ProfBegin("Serialize Data Sections"); RDIB_DataSectionList sections = {0}; rdib_data_sections_from_top_level_info(arena->v[0], §ions, string_map, &input->top_level_info); rdib_data_sections_from_binary_sections(arena->v[0], §ions, string_map, input->sections, input->sect_count); rdib_data_sections_from_path_tree(tp, arena->v[0], §ions, string_map, path_tree); rdib_data_sections_from_string_map(tp, arena->v[0], §ions, string_map_buckets, string_map_bucket_count); rdib_data_sections_from_index_runs(tp, arena->v[0], §ions, idx_run_buckets, idx_run_bucket_count); rdib_data_sections_from_name_maps(tp, arena, §ions, string_map, idx_run_map, name_map_buckets, name_map_bucket_counts); rdib_data_sections_from_types(tp, arena->v[0], §ions, input->top_level_info.arch, string_map, idx_run_map, all_udt_member_types.count, all_udt_member_type_chunks, all_enum_member_types.count, all_enum_member_type_chunks, total_type_node_count, all_types.count, all_type_chunks, type_stats); rdib_data_sections_from_line_tables(tp, arena, §ions, total_line_table_count, all_line_tables.count, all_line_table_chunks); rdib_data_sections_from_source_line_maps(tp, arena, §ions, total_src_file_count, all_src_files.count, all_src_file_chunks); rdib_data_sections_from_source_files(tp, arena, §ions, string_map, path_tree, total_src_file_count, all_src_files.count, all_src_file_chunks); rdib_data_sections_from_units(arena->v[0], §ions, string_map, path_tree, total_unit_count, all_units.count, all_unit_chunks); rdib_data_sections_from_global_variables(tp, arena, §ions, string_map, total_gvar_count, all_gvars.count, all_gvar_chunks); rdib_data_sections_from_thread_variables(tp, arena, §ions, string_map, total_tvar_count, all_tvars.count, all_tvar_chunks); rdib_data_sections_from_procedures(tp, arena, §ions, string_map, total_proc_count, all_procs.count, all_proc_chunks); rdib_data_sections_from_scopes(tp, arena, §ions, string_map, total_scope_count, all_scopes.count, all_scope_chunks); rdib_data_sections_from_unit_gvar_scope_vmaps(tp, arena, §ions, all_units.count, all_unit_chunks, all_gvars.count, all_gvar_chunks, all_scopes.count, all_scope_chunks); rdib_data_sections_from_inline_sites(tp, arena->v[0], §ions, string_map, total_inline_site_count, all_inline_sites.count, all_inline_site_chunks); //rdib_data_sections_from_checksums(tp, arena->v[0], §ions); ProfEnd(); ProfBegin("Make RDI header and sections"); String8List rdi_data = {0}; { // concat section datas String8List raw_section_datas[RDI_SectionKind_COUNT] = {0}; for (RDIB_DataSectionNode *n = sections.first; n != 0; n = n->next) { str8_list_concat_in_place(&raw_section_datas[n->v.tag], &n->v.data); } RDI_Header *rdi_header = push_array(arena->v[0], RDI_Header, 1); RDI_Section *rdi_sections = push_array(arena->v[0], RDI_Section, RDI_SectionKind_COUNT); rdi_header->magic = RDI_MAGIC_CONSTANT; rdi_header->encoding_version = RDI_ENCODING_VERSION; rdi_header->data_section_off = sizeof(*rdi_header); rdi_header->data_section_count = RDI_SectionKind_COUNT; str8_list_push(arena->v[0], &rdi_data, str8_struct(rdi_header)); str8_list_push(arena->v[0], &rdi_data, str8_array(rdi_sections, RDI_SectionKind_COUNT)); for (U64 sect_idx = 0; sect_idx < RDI_SectionKind_COUNT; ++sect_idx) { RDI_Section *dst = &rdi_sections[sect_idx]; dst->encoding = RDI_SectionEncoding_Unpacked; dst->pad = 0; dst->off = 0; dst->encoded_size = 0; dst->unpacked_size = 0; if (raw_section_datas[sect_idx].total_size > 0) { str8_list_push_aligner(arena->v[0], &rdi_data, 0, 8); dst->off = rdi_data.total_size; dst->encoded_size = raw_section_datas[sect_idx].total_size; dst->unpacked_size = raw_section_datas[sect_idx].total_size; str8_list_concat_in_place(&rdi_data, &raw_section_datas[sect_idx]); #if BUILD_DEBUG { U64 expected_total_size = 0; for (String8Node *n = rdi_data.first; n != 0; n = n->next) { expected_total_size += n->string.size; } Assert(expected_total_size == rdi_data.total_size); } #endif } } } ProfEnd(); scratch_end(scratch); ProfEnd(); return rdi_data; } ================================================ FILE: src/linker/rdi/rdi_builder.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once StaticAssert(sizeof(RDI_Header) == AlignPow2(sizeof(RDI_Header), 8), g_rdi_header_align_check); //////////////////////////////// // TODO: move to rdi_format.h #define RDI_IsCompleteUserDefinedTypeKind(x) ((x) == RDI_TypeKind_Class || (x) == RDI_TypeKind_Struct || (x) == RDI_TypeKind_Union || (x) == RDI_TypeKind_Enum) #define RDI_IsIncompleteUsedDefinedTypeKind(x) (RDI_TypeKind_FirstIncomplete <= (x) && (x) <= RDI_TypeKind_LastIncomplete) #define RDI_IsUserDefinedType(x) (RDI_IsCompleteUserDefinedTypeKind(x) || RDI_IsIncompleteUsedDefinedTypeKind(x)) #define RDI_IsBuiltinType(x) (RDI_TypeKind_FirstBuiltIn <= (x) && (x) <= RDI_TypeKind_LastBuiltIn) #define RDI_IsPtrType(x) ((x) == RDI_TypeKind_Ptr || (x) == RDI_TypeKind_LRef || (x) == RDI_TypeKind_RRef) //////////////////////////////// typedef enum { RDIB_DataModel_Null, RDIB_DataModel_ILP32, RDIB_DataModel_LLP64, RDIB_DataModel_LP64, RDIB_DataModel_ILP64, RDIB_DataModel_SILP64 } RDIB_DataModel; //////////////////////////////// typedef void * RDIB_TypeRef; typedef struct RDIB_EvalBytecodeOp { struct RDIB_EvalBytecodeOp *next; RDI_EvalOp op; U64 p_size; U64 p; } RDIB_EvalBytecodeOp; typedef struct RDIB_EvalBytecode { U64 count; U64 size; RDIB_EvalBytecodeOp *first; RDIB_EvalBytecodeOp *last; } RDIB_EvalBytecode; typedef struct RDIB_Location { RDI_LocationKind kind; Rng1U64List ranges; union { struct { RDI_RegCode reg_code; U64 offset; }; RDIB_EvalBytecode bytecode; }; // used by RDI builder U64 data_offset; } RDIB_Location; typedef struct RDIB_LocationNode { struct RDIB_LocationNode *next; RDIB_Location v; } RDIB_LocationNode; typedef struct RDIB_LocationList { U64 count; RDIB_LocationNode *first; RDIB_LocationNode *last; } RDIB_LocationList; typedef struct RDIB_Variable { RDI_LinkFlags link_flags; String8 name; String8 link_name; RDI_LocalKind kind; struct RDIB_Type *type; struct RDIB_Type *container_type; struct RDIB_Procedure *container_proc; RDIB_LocationList locations; struct RDIB_VariableChunk *chunk; struct RDIB_Variable *next; } RDIB_Variable; typedef struct RDIB_VariableNode { struct RDIB_VariableNode *next; RDIB_Variable v; } RDIB_VariableNode; typedef struct RDIB_VariableList { U64 count; RDIB_VariableNode *first; RDIB_VariableNode *last; } RDIB_VariableList; //////////////////////////////// typedef struct { RDI_Arch arch; U64 exe_hash; U64 voff_max; String8 exe_name; String8 producer_string; } RDIB_TopLevelInfo; typedef struct { String8 name; RDI_BinarySectionFlags flags; U64 voff_first; U64 voff_opl; U64 foff_first; U64 foff_opl; } RDIB_BinarySection; typedef struct RDIB_LineTableFragment { struct RDIB_SourceFile *src_file; PairU32 ln_voff; U64 *voffs; U32 *line_nums; U16 *col_nums; U64 line_count; U64 col_count; struct RDIB_LineTableFragment *next_src_file; struct RDIB_LineTableFragment *next_line_table; struct RDIB_LineTableFragmentChunk *chunk; } RDIB_LineTableFragment; typedef struct RDIB_LineTableFragmentChunk { struct RDIB_LineTableFragmentChunk *next; U64 base; U64 count; U64 cap; RDIB_LineTableFragment *v; } RDIB_LineTableFragmentChunk; typedef struct RDIB_LineTableFragmentChunkList { U64 count; RDIB_LineTableFragmentChunk *first; RDIB_LineTableFragmentChunk *last; } RDIB_LineTableFragmentChunkList; typedef struct RDIB_LineTable { struct RDIB_LineTableChunk *chunk; U64 count; RDIB_LineTableFragment *first; RDIB_LineTableFragment *last; U32 output_array_idx; } RDIB_LineTable; typedef struct RDIB_LineTableChunk { struct RDIB_LineTableChunk *next; U64 base; U64 count; U64 cap; RDIB_LineTable *v; } RDIB_LineTableChunk; typedef struct RDIB_LineTableChunkList { U64 count; RDIB_LineTableChunk *first; RDIB_LineTableChunk *last; } RDIB_LineTableChunkList; typedef struct RDIB_SourceFile { String8 file_path; String8 normal_full_path; RDI_ChecksumKind checksum_kind; String8 checksum; RDIB_LineTableFragment *line_table_frags; U64 src_line_map_idx; U64 line_table_idx; struct RDIB_SourceFileChunk *chunk; } RDIB_SourceFile; typedef struct RDIB_SourceFileChunk { struct RDIB_SourceFileChunk *next; U64 base; U64 count; U64 cap; RDIB_SourceFile *v; } RDIB_SourceFileChunk; typedef struct RDIB_SourceFileChunkList { U64 count; RDIB_SourceFileChunk *first; RDIB_SourceFileChunk *last; } RDIB_SourceFileChunkList; typedef struct RDIB_Procedure { RDI_LinkFlags link_flags; String8 name; String8 link_name; struct RDIB_Type *type; struct RDIB_Type *container_type; struct RDIB_Procedure *container_proc; struct RDIB_Scope *scope; struct RDIB_ScopeNode *scope_first; struct RDIB_ScopeNode *scope_last; U64 scope_count; struct RDIB_ProcedureChunk *chunk; } RDIB_Procedure; typedef struct RDIB_Scope { struct RDIB_Scope *parent; struct RDIB_Scope *first_child; struct RDIB_Scope *last_child; struct RDIB_Scope *next_sibling; struct RDIB_Procedure *container_proc; Rng1U64List ranges; RDIB_Variable *local_first; RDIB_Variable *local_last; U64 local_count; struct RDIB_InlineSite *inline_site; // used by RDI builder U64 local_first_idx; struct RDIB_ScopeChunk *chunk; } RDIB_Scope; typedef struct RDIB_InlineSite { String8 name; struct RDIB_Type *type; struct RDIB_Type *owner; struct RDIB_InlineSiteChunk *chunk; union { struct RDIB_LineTable *line_table; struct { void *ud0; U64 ud1; U64 ud2; } convert_ref; }; } RDIB_InlineSite; typedef RDI_MemberKind RDI_MemberKindExt; enum { RDI_MemberKind_COUNT = RDI_MemberKind_NestedType, RDI_MemberKindExt_MemberListPointer // NOTE: must always be last in the list! }; typedef struct RDIB_UDTMember { RDI_MemberKindExt kind; union { struct { String8 name; U64 offset; RDIB_TypeRef type_ref; } data_field; struct { String8 name; RDIB_TypeRef type_ref; } static_data; RDIB_TypeRef member_list_pointer; struct { RDI_MemberKind kind; String8 name; RDIB_TypeRef type_ref; U64 vftable_offset; } method; struct { String8 name; RDIB_TypeRef type_ref; } nested_type; struct { RDIB_TypeRef type_ref; U64 offset; } base_class; struct { RDIB_TypeRef type_ref; U64 vbptr_off; U64 vtable_off; } virtual_base_class; struct { String8 name; U64 value; } enumerate; }; struct RDIB_UDTMember *next; struct RDIB_UDTMemberChunk *chunk; } RDIB_UDTMember; typedef struct RDIB_UDTMemberList { U64 count; RDIB_UDTMember *first; RDIB_UDTMember *last; } RDIB_UDTMemberList; typedef struct RDIB_UDT { struct RDIB_Type *self_type; struct RDIB_Type *members; RDIB_SourceFile *decl_src_file; U32 decl_line_num; U32 decl_col_num; } RDIB_UDT; enum { RDI_TypeKindExt_Lo = RDI_TypeKind_Count, RDI_TypeKindExt_VirtualTable, RDI_TypeKindExt_StaticMethod, RDI_TypeKindExt_Members, RDI_TypeKindExt_Params, RDI_TypeKindExt_Count, }; typedef RDI_TypeKind RDI_TypeKindExt; typedef struct RDIB_Type { RDI_TypeKindExt kind; U64 final_idx; U64 itype; union { struct { String8 name; U64 size; } builtin; struct { RDI_TypeModifierFlags flags; RDIB_TypeRef type_ref; } modifier; struct { RDIB_TypeRef type_ref; U64 size; } ptr; struct { RDIB_TypeRef return_type; RDIB_TypeRef params_type; U64 param_idx_run_bucket_idx; } func; struct { RDIB_TypeRef class_type; RDIB_TypeRef this_type; RDIB_TypeRef return_type; RDIB_TypeRef params_type; U64 param_idx_run_bucket_idx; } method; struct { RDIB_TypeRef class_type; RDIB_TypeRef return_type; RDIB_TypeRef params_type; U64 param_idx_run_bucket_idx; } static_method; struct { U64 off; U64 count; RDIB_TypeRef value_type; } bitfield; struct { RDIB_TypeRef entry_type; U64 size; } array; struct { String8 name; String8 link_name; RDIB_TypeRef members; // assigned in UDT build step U64 udt_idx; union { struct { U64 size; RDIB_TypeRef derived; RDIB_TypeRef vtshape; } struct_type; struct { U64 size; } union_type; struct { String8 name; RDIB_TypeRef base_type; } enum_type; }; } udt; struct { U64 count; RDIB_TypeRef *types; } params; struct { RDIB_UDTMemberList list; // assigned in member build step B32 is_head; U64 first_member_idx; } members, enum_members; }; struct RDIB_TypeChunk *chunk; } RDIB_Type; typedef struct RDIB_Unit { RDI_Arch arch; String8 unit_name; String8 compiler_name; String8 source_file; String8 object_file; String8 archive_file; String8 build_path; RDI_Language language; RDIB_LineTable *line_table; U64 virt_range_count; Rng1U64 *virt_ranges; struct RDIB_UnitChunk *chunk; } RDIB_Unit; typedef struct RDIB_DataSection { RDI_SectionKind tag; String8List data; } RDIB_DataSection; typedef struct RDIB_DataSectionNode { struct RDIB_DataSectionNode *next; RDIB_DataSection v; } RDIB_DataSectionNode; typedef struct RDIB_DataSectionList { U64 count; RDIB_DataSectionNode *first; RDIB_DataSectionNode *last; } RDIB_DataSectionList; typedef struct RDIB_UnitChunk { U64 base; U64 count; U64 cap; RDIB_Unit *v; struct RDIB_UnitChunk *next; } RDIB_UnitChunk; typedef struct RDIB_UnitChunkList { U64 count; RDIB_UnitChunk *first; RDIB_UnitChunk *last; } RDIB_UnitChunkList; typedef struct RDIB_VariableChunk { struct RDIB_VariableChunk *next; U64 base; U64 count; U64 cap; RDIB_Variable *v; } RDIB_VariableChunk; typedef struct RDIB_VariableChunkList { U64 count; RDIB_VariableChunk *first; RDIB_VariableChunk *last; } RDIB_VariableChunkList; typedef struct RDIB_ProcedureChunk { struct RDIB_ProcedureChunk *next; U64 base; U64 count; U64 cap; RDIB_Procedure *v; } RDIB_ProcedureChunk; typedef struct RDIB_ProcedureChunkList { U64 count; RDIB_ProcedureChunk *first; RDIB_ProcedureChunk *last; } RDIB_ProcedureChunkList; typedef struct RDIB_ScopeChunk { struct RDIB_ScopeChunk *next; U64 base; U64 count; U64 cap; RDIB_Scope *v; } RDIB_ScopeChunk; typedef struct RDIB_ScopeChunkList { U64 count; RDIB_ScopeChunk *first; RDIB_ScopeChunk *last; } RDIB_ScopeChunkList; typedef struct RDIB_ScopeNode { struct RDIB_ScopeNode *next; RDIB_Scope *v; } RDIB_ScopeNode; typedef struct RDIB_ScopeList { U64 count; RDIB_Scope *first; RDIB_Scope *last; } RDIB_ScopeList; typedef struct RDIB_InlineSiteChunk { struct RDIB_InlineSiteChunk *next; U64 base; U64 count; U64 cap; RDIB_InlineSite *v; } RDIB_InlineSiteChunk; typedef struct RDIB_InlineSiteChunkList { U64 count; RDIB_InlineSiteChunk *first; RDIB_InlineSiteChunk *last; } RDIB_InlineSiteChunkList; typedef struct RDIB_TypeChunk { struct RDIB_TypeChunk *next; U64 base; U64 count; U64 cap; RDIB_Type *v; } RDIB_TypeChunk; typedef struct { U64 count; RDIB_TypeChunk *first; RDIB_TypeChunk *last; } RDIB_TypeChunkList; typedef struct RDIB_UDTMemberChunk { struct RDIB_UDTMemberChunk *next; U64 base; U64 count; U64 cap; RDIB_UDTMember *v; } RDIB_UDTMemberChunk; typedef struct RDIB_UDTMemberChunkList { U64 count; RDIB_UDTMemberChunk *first; RDIB_UDTMemberChunk *last; } RDIB_UDTMemberChunkList; //////////////////////////////// // UDT Forward Ref Map typedef struct { struct RDIB_Type *type; U64 idx; } RDIB_UDTFwdrefBucket; //////////////////////////////// // String Map typedef struct RDIB_StringMapBucket { String8 string; union { // to get deterministic output we assign each bucket a unique index union { struct { U32 lo; U32 hi; }; U64 v; } sorter; // after buckets are sorted we replace 'sorter' with indices into output array U64 idx; }; union { // depending on the usage context sotres: pointers to variables, procedures, and etc. VoidNode *raw_values; // during index-run-map build step 'raw_values' are replaced with index-run bucket index struct { U32 count; // if we have single index - store it in the bucket union { U64 idx_run_bucket_idx; U32 match_idx; }; }; }; } RDIB_StringMapBucket; typedef struct RDIB_StringMap { U64 cap; RDIB_StringMapBucket **buckets; } RDIB_StringMap; #define RDIB_STRING_MAP_UPDATE_FUNC(name) void name(VoidNode **head, VoidNode *node) typedef RDIB_STRING_MAP_UPDATE_FUNC(RDIB_StringMapUpdateFunc); typedef struct { RDIB_StringMap *string_map; Rng1U64 *ranges; U64 *counts; U64 *offsets; RDIB_StringMapBucket **result; } RDIB_GetExtantBucketsStringMapTask; typedef struct { U32 *string_table; U64 string_data_size; U8 *string_data; RDIB_StringMapBucket **buckets; Rng1U64 *ranges; } RDIB_CopyStringDataTask; typedef struct { U64 chunk_idx_opl; Rng1U64 *ranges; RDIB_StringMapBucket **src; RDIB_StringMapBucket **dst; U32 *chunk_histo; U32 *chunk_offsets; } RDIB_StringMapRadixSort; //////////////////////////////// // Index Run Map typedef struct RDIB_IndexRunBucket { union { struct { U32 lo; U32 hi; }; U64 v; } sorter; U32Array indices; U64 index_in_output_array; } RDIB_IndexRunBucket; typedef struct RDIB_IndexRunMap { U64 cap; RDIB_IndexRunBucket **buckets; } RDIB_IndexRunMap; //////////////////////////////// typedef struct { U64 voff; U32 size; U32 idx; } RDIB_VMapRange; //////////////////////////////// #define RDIB_PATH_TREE_NIL_STRING str8_lit("") typedef struct RDIB_PathTreeNode { struct RDIB_PathTreeNode *parent; struct RDIB_PathTreeNode *next_order; struct RDIB_PathTreeNode *next_sibling; struct RDIB_PathTreeNode *first_child; struct RDIB_PathTreeNode *last_child; U64 node_idx; String8 sub_path; RDIB_SourceFile *src_file; } RDIB_PathTreeNode; typedef struct RDIB_PathTreeNodeList { U64 count; RDIB_PathTreeNode *first; RDIB_PathTreeNode *last; } RDIB_PathTreeNodeList; typedef struct RDIB_PathTree { RDIB_PathTreeNode *root; U64 node_count; U64 next_list_idx; U64 list_count; RDIB_PathTreeNodeList *node_lists; } RDIB_PathTree; //////////////////////////////// typedef struct RDIB_Input { U64 unit_chunk_cap; U64 src_file_chunk_cap; U64 symbol_chunk_cap; U64 line_table_cap; U64 inline_site_cap; U64 type_cap; U64 udt_cap; RDIB_TopLevelInfo top_level_info; U64 sect_count; RDIB_BinarySection *sections; RDIB_UnitChunkList units; RDIB_SourceFileChunkList src_files; RDIB_LineTableChunkList line_tables; RDIB_ScopeChunkList scopes; RDIB_VariableChunkList locals; RDIB_VariableChunkList gvars; RDIB_VariableChunkList extern_gvars; RDIB_VariableChunkList static_gvars; RDIB_VariableChunkList tvars; RDIB_VariableChunkList extern_tvars; RDIB_VariableChunkList static_tvars; RDIB_ProcedureChunkList procs; RDIB_ProcedureChunkList extern_procs; RDIB_ProcedureChunkList static_procs; RDIB_InlineSiteChunkList inline_sites; RDIB_TypeChunkList types; RDIB_TypeChunkList struct_list; RDIB_TypeChunkList union_list; RDIB_TypeChunkList enum_list; RDIB_TypeChunkList param_types; RDIB_TypeChunkList member_types; RDIB_TypeChunkList enum_types; RDIB_UDTMemberChunkList udt_members; RDIB_UDTMemberChunkList enum_members; RDIB_SourceFile *null_src_file; RDIB_LineTable *null_line_table; RDIB_LineTableFragment *null_frag; RDIB_Type *null_type; RDIB_Scope *null_scope; RDIB_Unit *null_unit; RDIB_Procedure *null_proc; RDIB_Variable *null_local; RDIB_Variable *null_gvar; RDIB_Variable *null_tvar; RDIB_UDTMember *null_udt_member; RDIB_UDTMember *null_enum_member; RDIB_InlineSite *null_inline_site; RDIB_Type *variadic_type; //RDIB_TypeChunkList struct_list; //RDIB_TypeChunkList union_list; //RDIB_TypeChunkList enum_list; //RDIB_TypeChunkList param_types; } RDIB_Input; //////////////////////////////// // Parallel For Tasks typedef struct { U64 *udt_counts; } RDIB_TypeStats; typedef struct { RDIB_TypeChunk **chunks; RDIB_TypeStats *type_stats; } RDIB_TypeStatsTask; typedef struct { Rng1U64 *ranges; U64 *counts; U64 *offsets; RDIB_TypeChunk **type_chunks; RDIB_StringMap *string_map; union { RDI_Member *udt_members_rdi; RDI_EnumMember *enum_members_rdi; }; } RDIB_MembersTask; typedef struct { RDIB_TypeChunk **type_chunks; RDIB_TypeStats type_stats; U64 *udt_base_idx; RDI_UDT *udts; } RDIB_UserDefinesTask; typedef struct { U64 addr_size; RDIB_StringMap *string_map; RDIB_IndexRunMap *idx_run_map; RDIB_TypeChunk **type_chunks; RDIB_TypeStats type_stats; RDI_TypeNode *type_nodes; } RDIB_TypeNodesTask; typedef struct { RDIB_StringMap *string_map; Rng1U64 *ranges; RDIB_StringMapUpdateFunc *string_map_update_func; RDIB_StringMapBucket **free_buckets; U64 *insert_counts; U64 *element_indices; union { RDIB_UnitChunk **units; RDIB_BinarySection *sects; RDIB_SourceFileChunk **src_file_chunks; RDIB_VariableChunk **vars; RDIB_ProcedureChunk **procs; RDIB_InlineSiteChunk **inline_sites; RDIB_UDTMemberChunk **udt_members; RDIB_UDTMemberChunk **enum_members; RDIB_TypeChunk **types; RDIB_PathTreeNodeList *path_node_lists; }; } RDIB_CollectStringsTask; typedef struct { RDIB_StringMap *string_map; Rng1U64 *ranges; RDIB_TypeChunk **chunks; String8List *data_lists; } RDIB_BuildTypeDataTask; typedef struct { RDIB_StringMap *string_map; Rng1U64 *ranges; union { struct { RDIB_VariableChunk **gvars_rdib; String8List *gvars_out; }; struct { RDIB_VariableChunk **tvars_rdib; String8List *tvars_out; }; struct { RDIB_ProcedureChunk **procs_rdib; String8List *procs_out; }; struct { RDIB_ScopeChunk **scopes_rdib; U64 *scope_voff_counts; U64 *loc_data_sizes; U64 *local_counts; U64 *loc_block_counts; U64 *scope_voff_offsets; U64 *local_offsets; U64 *loc_block_offsets; U64 *loc_data_offsets; U64 *scope_voffs_rdi; RDI_Scope *scopes_rdi; RDI_Local *locals_rdi; RDI_LocationBlock *loc_blocks_rdi; U8 *loc_data_rdi; }; }; } RDIB_BuildSymbolSectionTask; typedef union { struct { U64 *counts; U64 *offsets; Rng1U64 *ranges; RDIB_VMapRange *vmap; union { RDIB_UnitChunk **unit_chunks; RDIB_VariableChunk **gvar_chunks; RDIB_ScopeChunk **scope_chunks; }; }; struct { U64 vmap_counts[3]; RDIB_VMapRange *vmaps[3]; String8List raw_vmaps[3]; }; } RDIB_VMapBuilderTask; typedef struct { U64 sorter_idx; RDI_NameMapKind name_map_kind; RDIB_IndexRunMap *idx_run_map; RDIB_IndexRunBucket **free_buckets; Rng1U64 *ranges; union { RDIB_TypeChunk **type_chunks; RDIB_StringMapBucket **name_map_buckets; }; } RDIB_BuildIndexRunsTask; typedef struct { RDIB_IndexRunBucket **buckets; Rng1U64 *ranges; U32 *output_array; } RDIB_IdxRunCopyTask; typedef struct { RDIB_IndexRunMap *idx_run_map; Rng1U64 *ranges; U64 *counts; U64 *offsets; RDIB_IndexRunBucket **result; } RDIB_GetExtantBucketsIndexRunMapTask; typedef struct { U64 chunk_idx_opl; Rng1U64 *ranges; RDIB_IndexRunBucket **src; RDIB_IndexRunBucket **dst; U32 *chunk_histo; U32 *chunk_offsets; } RDIB_IndexRunMapRadixSort; typedef struct { RDIB_StringMap *string_map; RDIB_IndexRunMap *idx_run_map; U64 *in_bucket_counts; RDIB_StringMapBucket ***in_buckets; RDI_NameMapBucket **out_buckets; RDI_NameMapNode **out_nodes; U64 *out_bucket_counts; U64 *out_node_counts; } RDIB_NameMapBuilderTask; typedef struct { RDIB_PathTree *path_tree; RDIB_StringMap *string_map; RDI_FilePathNode *nodes_dst; } RDIB_BuildFilePathNodesTask; typedef struct { RDIB_SourceFile **src_file_arr; U32 *out_line_counts; U32 *out_voff_counts; U32 **out_line_nums; U32 **out_line_ranges; U64 **out_voffs; } RDIB_SrcLineMapsTask; typedef struct { RDIB_LineTableChunk **chunks; Rng1U64 *ranges; U64 *out_line_table_counts; U64 **out_line_table_voffs; RDI_Line **out_line_table_lines; } RDIB_BuildLineTablesTask; typedef struct { Rng1U64 *ranges; RDIB_StringMap *string_map; RDIB_PathTree *path_tree; RDIB_SourceFileChunk **src_file_chunks; RDI_SourceFile *src_files_dst; } RDIB_FillSourceFilesTask; //////////////////////////////// // Data Model Helpers internal RDIB_DataModel rdib_infer_data_model(OperatingSystem os, RDI_Arch arch); internal RDI_TypeKind rdib_short_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_unsigned_short_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_int_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_unsigned_int_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_long_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_unsigned_long_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_long_long_type_from_data_model (RDIB_DataModel data_model); internal RDI_TypeKind rdib_unsigned_long_long_type_from_data_model(RDIB_DataModel data_model); internal RDI_TypeKind rdib_pointer_size_t_type_from_data_model (RDIB_DataModel data_model); //////////////////////////////// internal void rdib_udt_member_list_push_node (RDIB_UDTMemberList *list, RDIB_UDTMember *node); internal void rdib_udt_member_list_concat_in_place(RDIB_UDTMemberList *list, RDIB_UDTMemberList *to_concat); internal RDIB_LineTableFragment * rdib_line_table_push(Arena *arena, RDIB_LineTable *list); //////////////////////////////// // Chunk Lists // push internal RDIB_Unit * rdib_unit_chunk_list_push (Arena *arena, RDIB_UnitChunkList *list, U64 cap); internal RDIB_Scope * rdib_scope_chunk_list_push (Arena *arena, RDIB_ScopeChunkList *list, U64 cap); internal RDIB_Procedure * rdib_procedure_chunk_list_push (Arena *arena, RDIB_ProcedureChunkList *list, U64 cap); internal RDIB_Variable * rdib_variable_chunk_list_push (Arena *arena, RDIB_VariableChunkList *list, U64 cap); internal RDIB_LineTable * rdib_line_table_chunk_list_push (Arena *arena, RDIB_LineTableChunkList *list, U64 cap); internal RDIB_Type * rdib_type_chunk_list_push (Arena *arena, RDIB_TypeChunkList *list, U64 cap); internal RDIB_UDTMember * rdib_udt_member_chunk_list_push (Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap); internal RDIB_SourceFile * rdib_source_file_chunk_list_push(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); internal RDIB_InlineSite * rdib_inline_site_chunk_list_push(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap); internal RDIB_Scope * rdib_scope_chunk_list_push_zero (Arena *arena, RDIB_ScopeChunkList *list, U64 cap); internal RDIB_Procedure * rdib_procedure_chunk_list_push_zero (Arena *arena, RDIB_ProcedureChunkList *list, U64 cap); internal RDIB_Variable * rdib_variable_chunk_list_push_zero (Arena *arena, RDIB_VariableChunkList *list, U64 cap); internal RDIB_LineTable * rdib_line_table_chunk_list_push_zero (Arena *arena, RDIB_LineTableChunkList *list, U64 cap); internal RDIB_Type * rdib_type_chunk_list_push_zero (Arena *arena, RDIB_TypeChunkList *list, U64 cap); internal RDIB_UDTMember * rdib_udt_member_chunk_list_push_zero (Arena *arena, RDIB_UDTMemberChunkList *list, U64 cap); internal RDIB_SourceFile * rdib_source_file_chunk_list_push_zero(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); internal RDIB_InlineSite * rdib_inline_site_chunk_list_push_zero(Arena *arena, RDIB_InlineSiteChunkList *list, U64 cap); // push many internal RDIB_UnitChunk * rdib_unit_chunk_list_reserve_ex(Arena *arena, RDIB_UnitChunkList *list, U64 chunk_count, U64 item_count); internal void rdib_unit_chunk_list_reserve (Arena *arena, RDIB_UnitChunkList *list, U64 cap); internal void rdib_type_chunk_list_reserve (Arena *arena, RDIB_TypeChunkList *list, U64 cap); internal void rdib_source_file_chunk_list_reserve(Arena *arena, RDIB_SourceFileChunkList *list, U64 cap); // concat in place internal void rdib_scope_chunk_list_concat_in_place (RDIB_ScopeChunkList *list, RDIB_ScopeChunkList *to_concat); internal void rdib_udt_member_chunk_list_concat_in_place (RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat); internal void rdib_procedure_chunk_list_concat_in_place (RDIB_ProcedureChunkList *list, RDIB_ProcedureChunkList *to_concat); internal void rdib_variable_chunk_list_concat_in_place (RDIB_VariableChunkList *list, RDIB_VariableChunkList *to_concat); internal void rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat); internal void rdib_inline_site_chunk_list_concat_in_place(RDIB_InlineSiteChunkList *list, RDIB_InlineSiteChunkList *to_concat); internal void rdib_type_chunk_list_concat_in_place (RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat); internal void rdib_source_file_chunk_list_concat_in_place(RDIB_SourceFileChunkList *list, RDIB_SourceFileChunkList *to_concat); // concat in place many internal void rdib_type_chunk_list_concat_in_place_many (RDIB_TypeChunkList *list, RDIB_TypeChunkList *to_concat, U64 count); internal void rdib_udt_member_chunk_list_concat_in_place_many(RDIB_UDTMemberChunkList *list, RDIB_UDTMemberChunkList *to_concat, U64 count); // array from chunk list internal RDIB_UnitChunk ** rdib_array_from_unit_chunk_list (Arena *arena, RDIB_UnitChunkList list); internal RDIB_ScopeChunk ** rdib_array_from_scope_chunk_list (Arena *arena, RDIB_ScopeChunkList list); internal RDIB_ProcedureChunk ** rdib_array_from_procedure_chunk_list (Arena *arena, RDIB_ProcedureChunkList list); internal RDIB_VariableChunk ** rdib_array_from_variable_chunk_list (Arena *arena, RDIB_VariableChunkList list); internal RDIB_LineTableChunk ** rdib_array_from_line_table_chunk_list (Arena *arena, RDIB_LineTableChunkList list); internal RDIB_InlineSiteChunk ** rdib_array_from_inline_site_chunk_list(Arena *arena, RDIB_InlineSiteChunkList list); internal RDIB_UDTMemberChunk ** rdib_array_from_udt_member_chunk_list (Arena *arena, RDIB_UDTMemberChunkList list); internal RDIB_TypeChunk ** rdib_array_from_type_chunk_list (Arena *arena, RDIB_TypeChunkList list); internal RDIB_SourceFileChunk ** rdib_array_from_source_file_chunk_list(Arena *arena, RDIB_SourceFileChunkList list); // total count from chunk list internal U64 rdib_unit_chunk_list_total_count (RDIB_UnitChunkList list); internal U64 rdib_scope_chunk_list_total_count (RDIB_ScopeChunkList list); internal U64 rdib_variable_chunk_list_total_count (RDIB_VariableChunkList list); internal U64 rdib_line_table_chunk_list_total_count (RDIB_LineTableChunkList list); internal U64 rdib_procedure_chunk_list_total_count (RDIB_ProcedureChunkList list); internal U64 rdib_inline_site_chunk_list_total_count(RDIB_InlineSiteChunkList list); internal U64 rdib_udt_member_chunk_list_total_count (RDIB_UDTMemberChunkList list); internal U64 rdib_type_chunk_list_total_count (RDIB_TypeChunkList list); internal U64 rdib_source_file_chunk_list_total_count(RDIB_SourceFileChunkList list); // pointer -> array index internal U32 rdib_idx_from_unit (RDIB_Unit *n); internal U32 rdib_idx_from_scope (RDIB_Scope *n); internal U32 rdib_idx_from_variable (RDIB_Variable *n); internal U32 rdib_idx_from_procedure (RDIB_Procedure *n); internal U32 rdib_idx_from_source_file(RDIB_SourceFile *n); internal U32 rdib_idx_from_line_table (RDIB_LineTable *n); internal U32 rdib_idx_from_type (RDIB_Type *n); internal U32 rdib_idx_from_udt_type (RDIB_Type *n); internal U32 rdib_idx_from_inline_site(RDIB_InlineSite *n); //////////////////////////////// //- Source File internal B32 rdib_source_file_match(RDIB_SourceFile *a, RDIB_SourceFile *b, OperatingSystem os); //- Eval Ops internal RDIB_EvalBytecodeOp * rdib_bytecode_push_op (Arena *arena, RDIB_EvalBytecode *bytecode, RDI_EvalOp op, RDI_U64 p); internal void rdib_bytecode_push_ucsont(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_U64 uconst); internal void rdib_bytecode_push_sconst(Arena *arena, RDIB_EvalBytecode *bytecode, RDI_S64 sconst); //- Location internal RDIB_Location rdib_make_location_addr_byte_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); internal RDIB_Location rdib_make_location_addr_bytecode_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); internal RDIB_Location rdib_make_location_val_bytecode_stream (Rng1U64List ranges, RDIB_EvalBytecode bytecode); internal RDIB_Location rdib_make_location_addr_reg_plus_u16 (Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); internal RDIB_Location rdib_make_location_addr_addr_reg_plus_u16(Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); internal RDIB_Location rdib_make_location_addr_reg_plus_u16 (Rng1U64List ranges, RDI_RegCode reg_code, RDI_U16 offset); internal RDIB_Location rdib_make_location_val_reg (Rng1U64List ranges, RDI_RegCode reg_code); internal RDIB_LocationNode * rdib_push_location_addr_reg_off(Arena *arena, RDIB_LocationList *list, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 is_reference, Rng1U64List ranges); //- UDT Fwdrefs internal U64 rdib_udt_fwdref_map_hash(String8 string); internal RDIB_UDTFwdrefBucket * rdib_udt_fwdref_map_insert_or_update(RDIB_UDTFwdrefBucket **buckets, U64 cap, U64 hash, RDIB_UDTFwdrefBucket *new_bucket); internal RDIB_UDTFwdrefBucket * rdib_udt_fwdrefmap_map_lookup(RDIB_UDTFwdrefBucket **buckets, U64 cap, U64 hash, String8 name); //- Types internal RDIB_TypeRef rdib_make_type_ref(Arena *arena, RDIB_Type *type); internal void rdib_deref_type_refs(TP_Context *tp, RDIB_TypeChunkList *list); internal RDIB_TypeStats rdib_sum_type_stats (RDIB_TypeStats *stats, U64 count); internal U64 rdib_udt_count_from_type_stats (RDIB_TypeStats *stats); internal U64 rdib_type_node_count_from_type_stats(RDIB_TypeStats *stats); internal U64 rdib_size_from_type (RDIB_Type *type); internal U64 rdib_count_members_deep(RDIB_Type *type); //- Path Tree internal RDIB_PathTree * rdib_path_tree_init (Arena *arena, U64 list_count); internal void rdib_path_tree_insert (Arena *arena, RDIB_PathTree *tree, String8 path, RDIB_SourceFile *src_file); internal U32 rdib_idx_from_path_tree(RDIB_PathTree *tree, String8 path); //- String Map internal U64 rdib_string_map_hash (String8 string); internal RDIB_StringMap * rdib_init_string_map (Arena *arena, U64 cap); internal U32 rdib_idx_from_string_map (RDIB_StringMap *string_map, String8 string); internal RDIB_StringMapBucket * rdib_string_map_insert_or_update (RDIB_StringMapBucket **buckets, U64 cap, U64 hash, RDIB_StringMapBucket *new_bucket, RDIB_StringMapUpdateFunc *update_func); internal void rdib_string_map_assign_indices (RDIB_StringMapBucket **buckets, U64 bucket_count); internal RDIB_StringMapBucket ** rdib_extant_buckets_from_string_map(TP_Context *tp, Arena *arena, RDIB_StringMap *string_map, U64 *bucket_count_out); internal void rdib_string_map_sort_buckets (TP_Context *tp, RDIB_StringMapBucket **buckets, U64 bucket_count, U64 max_sorter); //- String Map Specialized Inserters internal void rdib_string_map_insert_item (Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, void *value); internal void rdib_string_map_insert_string_table_item(Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string); internal void rdib_string_map_insert_name_map_item (Arena *arena, RDIB_CollectStringsTask *task, U64 task_id, String8 string, VoidNode *node); //- Index Run Map internal U64 rdib_index_run_hash (U32 count, U32 *idxs); internal RDIB_IndexRunMap * rdib_init_index_run_map (Arena *arena, U64 cap); internal RDIB_IndexRunBucket * rdib_index_run_map_insert_or_update (Arena *arena, RDIB_IndexRunBucket **buckets, U64 cap, U64 hash, RDIB_IndexRunBucket *new_bucket, U64 *bucket_idx_out); internal U32 rdib_idx_run_from_bucket_idx (RDIB_IndexRunMap *map, U64 bucket_idx); internal void rdib_index_run_map_assign_indices (RDIB_IndexRunBucket **buckets, U64 bucket_count); internal RDIB_IndexRunBucket ** rdib_extant_buckets_from_index_run_map(TP_Context *tp, Arena *arena, RDIB_IndexRunMap *idx_run_map, U64 *bucket_count_out); internal void rdib_index_run_map_sort_buckets (TP_Context *tp, RDIB_IndexRunBucket **buckets, U64 bucket_count, U64 chunk_idx_opl); //- Index Map Spesialized Query internal U32 rdib_idx_from_params(RDIB_IndexRunMap *map, RDIB_Type *params); //- Data Sections internal void rdib_data_section_list_push_node (RDIB_DataSectionList *list, RDIB_DataSectionNode *node); internal RDIB_DataSectionNode * rdib_data_section_list_push (Arena *arena, RDIB_DataSectionList *list, RDIB_DataSection v); internal void rdib_data_section_list_concat_in_place(RDIB_DataSectionList *list, RDIB_DataSectionList *to_concat); internal void rdib_data_sections_from_top_level_info (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_TopLevelInfo *src); internal void rdib_data_sections_from_binary_sections (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_BinarySection *binary_sects, U64 binary_sects_count); internal void rdib_data_sections_from_string_map (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count); internal void rdib_data_sections_from_index_runs (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_IndexRunBucket **buckets, U64 bucket_count); internal void rdib_data_sections_from_file_path_nodes (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_PathTree *tree); internal void rdib_data_sections_from_source_files (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_file_chunks); internal void rdib_data_sections_from_units (Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_PathTree *path_tree, U64 total_unit_count, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks); internal void rdib_data_sections_from_string_map (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMapBucket **buckets, U64 bucket_count); internal void rdib_data_sections_from_types(TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDI_Arch arch, RDIB_StringMap *string_map, RDIB_IndexRunMap *idx_run_map, U64 udt_member_chunk_count, RDIB_TypeChunk **udt_member_type_chunks, U64 enum_member_chunk_count, RDIB_TypeChunk **enum_member_type_chunks, U64 total_type_node_count, U64 type_chunk_count, RDIB_TypeChunk **type_chunks, RDIB_TypeStats type_stats); internal void rdib_data_sections_from_global_variables (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks); internal void rdib_data_sections_from_thread_variables (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_VariableChunk **chunks); internal void rdib_data_sections_from_procedures (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_ProcedureChunk **chunks); internal void rdib_data_sections_from_scopes (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_count, U64 chunk_count, RDIB_ScopeChunk **chunks); internal void rdib_data_sections_from_name_maps (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, RDIB_IndexRunMap *idx_run_map, RDIB_StringMapBucket **src_name_maps[RDI_NameMapKind_COUNT], U64 src_name_map_counts[RDI_NameMapKind_COUNT]); internal void rdib_data_sections_from_source_line_maps (TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 total_src_file_count, U64 src_file_chunk_count, RDIB_SourceFileChunk **src_fille_chunks); internal void rdib_data_sections_from_unit_gvar_scope_vmaps(TP_Context *tp, TP_Arena *arena, RDIB_DataSectionList *sect_list, U64 unit_chunk_count, RDIB_UnitChunk **unit_chunks, U64 gvar_chunk_count, RDIB_VariableChunk **gvar_chunks, U64 scope_chunk_count, RDIB_ScopeChunk **scope_chunks); internal void rdib_data_sections_from_inline_sites (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list, RDIB_StringMap *string_map, U64 total_inline_site_count, U64 inline_site_chunk_count, RDIB_InlineSiteChunk **inline_site_chunks); internal void rdib_data_sections_from_checksums (TP_Context *tp, Arena *arena, RDIB_DataSectionList *sect_list); internal RDIB_Input rdib_init_input(Arena *arena); internal String8List rdib_finish(TP_Context *tp, TP_Arena *arena, RDIB_Input *input); ================================================ FILE: src/linker/rdi/rdi_coff.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDI_Arch rdi_arch_from_coff_machine(COFF_MachineType machine) { switch (machine) { case COFF_MachineType_X86: return RDI_Arch_X86; case COFF_MachineType_X64: return RDI_Arch_X64; case COFF_MachineType_Unknown: case COFF_MachineType_Am33: case COFF_MachineType_Arm: case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: case COFF_MachineType_Ebc: case COFF_MachineType_Ia64: case COFF_MachineType_M32R: case COFF_MachineType_Mips16: case COFF_MachineType_MipsFpu: case COFF_MachineType_MipsFpu16: case COFF_MachineType_PowerPc: case COFF_MachineType_PowerPcFp: case COFF_MachineType_R4000: case COFF_MachineType_RiscV32: case COFF_MachineType_RiscV64: case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp: case COFF_MachineType_Sh4: case COFF_MachineType_Sh5: case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2: NotImplemented; default: return RDI_Arch_NULL; } } internal RDI_BinarySectionFlags rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) { RDI_BinarySectionFlags result = 0; if (flags & COFF_SectionFlag_MemRead) { result |= RDI_BinarySectionFlag_Read; } if (flags & COFF_SectionFlag_MemWrite) { result |= RDI_BinarySectionFlag_Write; } if (flags & COFF_SectionFlag_MemExecute) { result |= RDI_BinarySectionFlag_Execute; } return result; } ================================================ FILE: src/linker/rdi/rdi_coff.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal RDI_Arch rdi_arch_from_coff_machine(COFF_MachineType machine); ================================================ FILE: src/linker/rdi/rdi_cv.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDI_Arch rdi_arch_from_cv_arch(CV_Arch arch) { switch (arch) { case CV_Arch_8086: return RDI_Arch_X86; case CV_Arch_X64: return RDI_Arch_X64; case CV_Arch_8080: case CV_Arch_80286: case CV_Arch_80386: case CV_Arch_80486: case CV_Arch_PENTIUM: case CV_Arch_PENTIUMII: case CV_Arch_PENTIUMIII: case CV_Arch_MIPS: case CV_Arch_MIPS16: case CV_Arch_MIPS32: case CV_Arch_MIPS64: case CV_Arch_MIPSI: case CV_Arch_MIPSII: case CV_Arch_MIPSIII: case CV_Arch_MIPSIV: case CV_Arch_MIPSV: case CV_Arch_M68000: case CV_Arch_M68010: case CV_Arch_M68020: case CV_Arch_M68030: case CV_Arch_M68040: case CV_Arch_ALPHA: case CV_Arch_ALPHA_21164: case CV_Arch_ALPHA_21164A: case CV_Arch_ALPHA_21264: case CV_Arch_ALPHA_21364: case CV_Arch_PPC601: case CV_Arch_PPC603: case CV_Arch_PPC604: case CV_Arch_PPC620: case CV_Arch_PPCFP: case CV_Arch_PPCBE: case CV_Arch_SH3: case CV_Arch_SH3E: case CV_Arch_SH3DSP: case CV_Arch_SH4: case CV_Arch_SHMEDIA: case CV_Arch_ARM3: case CV_Arch_ARM4: case CV_Arch_ARM4T: case CV_Arch_ARM5: case CV_Arch_ARM5T: case CV_Arch_ARM6: case CV_Arch_ARM_XMAC: case CV_Arch_ARM_WMMX: case CV_Arch_ARM7: case CV_Arch_OMNI: case CV_Arch_IA64_1: case CV_Arch_IA64_2: case CV_Arch_CEE: case CV_Arch_AM33: case CV_Arch_M32R: case CV_Arch_TRICORE: case CV_Arch_EBC: case CV_Arch_THUMB: case CV_Arch_ARMNT: case CV_Arch_ARM64: case CV_Arch_D3D11_SHADER: NotImplemented; default: return RDI_Arch_NULL; } } internal RDI_Language rdi_language_from_cv_language(CV_Language language) { switch (language) { case CV_Language_C: return RDI_Language_C; case CV_Language_CXX: return RDI_Language_CPlusPlus; case CV_Language_MASM: return RDI_Language_Masm; case CV_Language_LINK: return RDI_Language_NULL; case CV_Language_CVTRES: return RDI_Language_NULL; case CV_Language_FORTRAN: case CV_Language_PASCAL: case CV_Language_BASIC: case CV_Language_COBOL: case CV_Language_CVTPGD: case CV_Language_CSHARP: case CV_Language_VB: case CV_Language_ILASM: case CV_Language_JAVA: case CV_Language_JSCRIPT: case CV_Language_MSIL: case CV_Language_HLSL: NotImplemented; default: return RDI_Language_NULL; } } internal RDI_TypeModifierFlags rdi_type_modifier_flags_from_cv_modifier_flags(CV_ModifierFlags flags) { RDI_TypeModifierFlags result = 0; if (flags & CV_ModifierFlag_Const) { result |= RDI_TypeModifierFlag_Const; } if (flags & CV_ModifierFlag_Volatile) { result |= RDI_TypeModifierFlag_Volatile; } return result; } internal RDI_TypeModifierFlags rdi_type_modifier_flags_from_cv_pointer_attribs(CV_PointerAttribs attribs) { RDI_TypeModifierFlags result = 0; if (attribs & CV_PointerAttrib_Const) { result |= RDI_TypeModifierFlag_Const; } if (attribs & CV_PointerAttrib_Volatile) { result |= RDI_TypeModifierFlag_Volatile; } return result; } internal RDI_TypeKind rdi_type_kind_from_pointer(CV_PointerAttribs attribs, CV_PointerMode mode) { RDI_TypeKind result = RDI_TypeKind_Ptr; if (attribs & CV_PointerAttrib_LRef) { result = RDI_TypeKind_LRef; } else if (attribs & CV_PointerAttrib_RRef) { result = RDI_TypeKind_RRef; } if (mode == CV_PointerMode_LRef) { result = RDI_TypeKind_LRef; } else if (mode == CV_PointerMode_RRef) { result = RDI_TypeKind_RRef; } return result; } internal RDI_TypeKind rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type) { switch (basic_type) { case CV_BasicType_NOTYPE : return RDI_TypeKind_NULL; case CV_BasicType_ABS : return RDI_TypeKind_NULL; case CV_BasicType_SEGMENT : return RDI_TypeKind_NULL; case CV_BasicType_VOID : return RDI_TypeKind_Void; case CV_BasicType_CURRENCY : return RDI_TypeKind_NULL; case CV_BasicType_NBASICSTR : return RDI_TypeKind_NULL; case CV_BasicType_FBASICSTR : return RDI_TypeKind_NULL; case CV_BasicType_HRESULT : return RDI_TypeKind_Handle; case CV_BasicType_CHAR : return RDI_TypeKind_Char8; case CV_BasicType_SHORT : return RDI_TypeKind_S16; case CV_BasicType_LONG : return RDI_TypeKind_S32; case CV_BasicType_QUAD : return RDI_TypeKind_S64; case CV_BasicType_OCT : return RDI_TypeKind_S128; case CV_BasicType_UCHAR : return RDI_TypeKind_UChar8; case CV_BasicType_USHORT : return RDI_TypeKind_U16; case CV_BasicType_ULONG : return RDI_TypeKind_U32; case CV_BasicType_UQUAD : return RDI_TypeKind_U64; case CV_BasicType_UOCT : return RDI_TypeKind_U128; case CV_BasicType_BOOL8 : return RDI_TypeKind_S8; case CV_BasicType_BOOL16 : return RDI_TypeKind_S16; case CV_BasicType_BOOL32 : return RDI_TypeKind_S32; case CV_BasicType_BOOL64 : return RDI_TypeKind_S64; case CV_BasicType_FLOAT32 : return RDI_TypeKind_F32; case CV_BasicType_FLOAT64 : return RDI_TypeKind_F64; case CV_BasicType_FLOAT80 : return RDI_TypeKind_F80; case CV_BasicType_FLOAT128 : return RDI_TypeKind_F128; case CV_BasicType_FLOAT48 : return RDI_TypeKind_F48; case CV_BasicType_FLOAT32PP : return RDI_TypeKind_F32PP; case CV_BasicType_FLOAT16 : return RDI_TypeKind_F16; case CV_BasicType_COMPLEX32 : return RDI_TypeKind_ComplexF32; case CV_BasicType_COMPLEX64 : return RDI_TypeKind_ComplexF64; case CV_BasicType_COMPLEX80 : return RDI_TypeKind_ComplexF80; case CV_BasicType_COMPLEX128: return RDI_TypeKind_ComplexF128; case CV_BasicType_BIT : return RDI_TypeKind_NULL; case CV_BasicType_PASCHAR : return RDI_TypeKind_NULL; case CV_BasicType_BOOL32FF : return RDI_TypeKind_NULL; case CV_BasicType_INT8 : return RDI_TypeKind_S8; case CV_BasicType_UINT8 : return RDI_TypeKind_U8; case CV_BasicType_RCHAR : return RDI_TypeKind_Char8; case CV_BasicType_WCHAR : return RDI_TypeKind_UChar16; case CV_BasicType_CHAR16 : return RDI_TypeKind_Char16; case CV_BasicType_CHAR32 : return RDI_TypeKind_Char32; case CV_BasicType_INT16 : return RDI_TypeKind_S16; case CV_BasicType_UINT16 : return RDI_TypeKind_U16; case CV_BasicType_INT32 : return RDI_TypeKind_S32; case CV_BasicType_UINT32 : return RDI_TypeKind_U32; case CV_BasicType_INT64 : return RDI_TypeKind_S64; case CV_BasicType_UINT64 : return RDI_TypeKind_U64; case CV_BasicType_INT128 : return RDI_TypeKind_S128; case CV_BasicType_UINT128 : return RDI_TypeKind_U128; case CV_BasicType_CHAR8 : return RDI_TypeKind_Char8; case CV_BasicType_PTR : return RDI_TypeKind_Ptr; } return RDI_TypeKind_NULL; } internal RDI_RegCode rdi_reg_code_from_cv(CV_Arch arch, CV_Reg reg) { RDI_RegCode result = 0; switch (arch) { case CV_Arch_8086: { switch (reg) { #define X(CVN,C,RDN,BP,BZ) case C: result = RDI_RegCodeX86_##RDN; break; CV_Reg_X86_XList(X) #undef X } } break; case CV_Arch_X64: { switch (reg) { #define X(CVN,C,RDN,BP,BZ) case C: result = RDI_RegCodeX64_##RDN; break; CV_Reg_X64_XList(X) #undef X } } break; default: NotImplemented; } return result; } internal RDI_ChecksumKind rdi_checksum_from_cv_c13(CV_C13ChecksumKind kind) { switch (kind) { case CV_C13ChecksumKind_Null: return RDI_ChecksumKind_NULL; case CV_C13ChecksumKind_MD5: return RDI_ChecksumKind_MD5; case CV_C13ChecksumKind_SHA1: return RDI_ChecksumKind_SHA1; case CV_C13ChecksumKind_SHA256: return RDI_ChecksumKind_SHA256; } return RDI_ChecksumKind_NULL; } ================================================ FILE: src/linker/rdi/rdi_cv.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once internal RDI_Arch rdi_arch_from_cv_arch(CV_Arch arch); internal RDI_Language rdi_language_from_cv_language(CV_Language language); internal RDI_TypeModifierFlags rdi_type_modifier_flags_from_cv_pointer_attribs(CV_PointerAttribs attribs); internal RDI_TypeKind rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type); internal RDI_RegCode rdi_reg_code_from_cv(CV_Arch arch, CV_Reg reg); internal RDI_ChecksumKind rdi_checksum_from_cv_c13(CV_C13ChecksumKind kind); ================================================ FILE: src/linker/rdi/rdi_overrides.h ================================================ #pragma once typedef U8 RDI_U8; typedef U16 RDI_U16; typedef U32 RDI_U32; typedef U64 RDI_U64; typedef S8 RDI_S8; typedef S16 RDI_S16; typedef S32 RDI_S32; typedef S64 RDI_S64; #define RDI_PROC internal #define RDIM_MEMSET_OVERRIDE #define rdim_memset MemorySet #define RDIM_MEMCPY_OVERRIDE #define rdim_memcpy MemoryCopy #define rdim_vsnprintf raddbg_vsnprintf ================================================ FILE: src/linker/scripts/obj_paths_from_pdb.py ================================================ import subprocess import sys import os def get_sorted_objs(pdb_path): result = subprocess.run(["llvm-pdbutil", "dump", "--modules", pdb_path], stdout=subprocess.PIPE, text=True) lines = result.stdout.strip().split('\n') filtered_lines = [line for line in lines if line.lstrip().startswith("Mod ")] # sort by the obj_path portion (line format: "Mod ") def extract_path(line): return line.split(maxsplit=2)[2].lower() #sorted_lines = sorted(filtered_lines, key=extract_path) return filtered_lines if __name__ == "__main__": sorted_objs = get_sorted_objs(sys.argv[1]) for l in sorted_objs: print(l.lstrip()) ================================================ FILE: src/linker/thread_pool/thread_pool.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void tp_run_tasks(TP_Context *pool, TP_Worker *worker) { for (;;) { S64 task_left = ins_atomic_u64_dec_eval(&pool->task_left); // are there any tasks left to run? if (task_left < 0) { break; } // run task Arena *arena = pool->task_arena ? pool->task_arena->v[worker->id] : 0; U64 task_id = pool->task_count - (task_left+1); pool->task_func(arena, worker->id, task_id, pool->task_data); // cache task count so we dont touch pool memory after atomic inc U64 task_count = pool->task_count; // on last task ping main thread U64 task_done = ins_atomic_u64_inc_eval(&pool->task_done); if (task_done == task_count) { os_semaphore_drop(pool->main_semaphore); } } } internal void tp_worker_main(void *raw_worker) { TP_Worker *worker = raw_worker; TP_Context *pool = worker->pool; for (; pool->is_live; ) { if (os_semaphore_take(pool->task_semaphore, max_U64)) { tp_run_tasks(pool, worker); } } } internal void tp_worker_main_shared(void *raw_worker) { TP_Worker *worker = raw_worker; TP_Context *pool = worker->pool; for (; pool->is_live; ) { if (os_semaphore_take(pool->exec_semaphore, max_U64)) { if (os_semaphore_take(pool->task_semaphore, max_U64)) { tp_run_tasks(pool, worker); } } } } internal TP_Context * tp_alloc(Arena *arena, U32 worker_count, U32 max_worker_count, String8 name) { ProfBeginDynamic("Alloc Thread Pool [Worker Count: %u]", worker_count); AssertAlways(worker_count > 0); B32 is_shared = (name.size > 0); // alloc semaphores Semaphore main_semaphore = {0}; Semaphore task_semaphore = {0}; Semaphore exec_semaphore = {0}; if (worker_count > 1) { main_semaphore = os_semaphore_alloc(0, 1, str8_zero()); if (is_shared) { AssertAlways(worker_count <= max_worker_count); task_semaphore = os_semaphore_alloc(0, max_worker_count, name); exec_semaphore = os_semaphore_alloc(0, worker_count, str8_zero()); } else { task_semaphore = os_semaphore_alloc(0, worker_count, str8_zero()); } } // pick entry point for the workers void *worker_entry = is_shared ? tp_worker_main_shared : tp_worker_main; // init pool TP_Context *pool = push_array(arena, TP_Context, 1); pool->exec_semaphore = exec_semaphore; pool->task_semaphore = task_semaphore; pool->main_semaphore = main_semaphore; pool->is_live = 1; pool->worker_count = worker_count; pool->worker_arr = push_array(arena, TP_Worker, worker_count); // init worker data for (U64 i = 0; i < worker_count; i += 1) { TP_Worker *worker = &pool->worker_arr[i]; worker->id = i; worker->pool = pool; } // launch worker threads for (U64 i = 1; i < worker_count; i += 1) { TP_Worker *worker = &pool->worker_arr[i]; worker->handle = thread_launch(worker_entry, worker); } ProfEnd(); return pool; } internal void tp_release(TP_Context *pool) { pool->is_live = 0; B32 is_shared = pool->exec_semaphore.u64[0] != 0; if (is_shared) { for (U64 i = 0; i < pool->worker_count; ++i) { semaphore_drop(pool->exec_semaphore); } } for (U64 i = 0; i < pool->worker_count; ++i) { semaphore_drop(pool->task_semaphore); } for (U64 i = 1; i < pool->worker_count; i += 1) { thread_detach(pool->worker_arr[i].handle); } if (is_shared) { semaphore_release(pool->exec_semaphore); } semaphore_release(pool->task_semaphore); semaphore_release(pool->main_semaphore); MemoryZeroStruct(pool); } internal TP_Arena * tp_arena_alloc(TP_Context *pool) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); Arena **arr = push_array(scratch.arena, Arena *, pool->worker_count); for (U64 i = 0; i < pool->worker_count; ++i) { arr[i] = arena_alloc(); } Arena **dst = push_array(arr[0], Arena *, pool->worker_count); MemoryCopy(dst, arr, sizeof(Arena*) * pool->worker_count); TP_Arena *worker_arena_arr = push_array(arr[0], TP_Arena, 1); worker_arena_arr->count = pool->worker_count; worker_arena_arr->v = dst; scratch_end(scratch); ProfEnd(); return worker_arena_arr; } internal void tp_arena_release(TP_Arena **arena_ptr) { ProfBeginFunction(); for (U64 i = 1; i < (*arena_ptr)->count; ++i) { arena_release((*arena_ptr)->v[i]); } arena_release((*arena_ptr)->v[0]); *arena_ptr = NULL; ProfEnd(); } internal TP_Temp tp_temp_begin(TP_Arena *arena) { ProfBeginFunction(); Temp first_temp = temp_begin(arena->v[0]); TP_Temp temp; temp.count = arena->count; temp.v = push_array_no_zero(first_temp.arena, Temp, arena->count); temp.v[0] = first_temp; for (U64 arena_idx = 1; arena_idx < arena->count; arena_idx += 1) { temp.v[arena_idx] = temp_begin(arena->v[arena_idx]); } ProfEnd(); return temp; } internal void tp_temp_end(TP_Temp temp) { ProfBeginFunction(); for (U64 temp_idx = temp.count - 1; temp_idx > 0; temp_idx -= 1) { temp_end(temp.v[temp_idx]); } ProfEnd(); } internal void tp_for_parallel(TP_Context *pool, TP_Arena *task_arena, U64 task_count, TP_TaskFunc *task_func, void *task_data) { if (task_count > 0) { // init run pool->task_arena = task_arena; pool->task_func = task_func; pool->task_data = task_data; pool->task_count = task_count; pool->task_done = 0; ins_atomic_u64_eval_assign(&pool->task_left, task_count); U64 drop_count = Min(task_count, pool->worker_count); // if we are in shared mode ping local semaphore if (pool->exec_semaphore.u64[0] != 0) { for (U64 worker_idx = 0; worker_idx < drop_count; worker_idx +=1) { os_semaphore_drop(pool->exec_semaphore); } } // ping shared semaphore for (U64 worker_idx = 0; worker_idx < drop_count; worker_idx += 1) { os_semaphore_drop(pool->task_semaphore); } // run tasks on main worker tp_run_tasks(pool, &pool->worker_arr[0]); // wait for workers to finish tasks os_semaphore_take(pool->main_semaphore, max_U64); } } internal Rng1U64 * tp_divide_work(Arena *arena, U64 item_count, U32 worker_count) { U64 per_count = CeilIntegerDiv(item_count, worker_count); Rng1U64 *range_arr = push_array_no_zero(arena, Rng1U64, worker_count + 1); for (U64 i = 0; i < worker_count; i += 1) { range_arr[i] = rng_1u64(Min(item_count, i * per_count), Min(item_count, i * per_count + per_count)); } // thread_pool_dummy_range: range_arr[worker_count] = rng_1u64(item_count, item_count); return range_arr; } ================================================ FILE: src/linker/thread_pool/thread_pool.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #define THREAD_POOL_TASK_FUNC(name) void name(Arena *arena, U64 worker_id, U64 task_id, void *raw_task) typedef THREAD_POOL_TASK_FUNC(TP_TaskFunc); typedef struct TP_Arena { U64 count; Arena **v; } TP_Arena; typedef struct TP_Temp { U64 count; Temp *v; } TP_Temp; typedef struct TP_Worker { U64 id; struct TP_Context *pool; Thread handle; } TP_Worker; typedef struct TP_Context { B32 is_live; Semaphore exec_semaphore; Semaphore task_semaphore; Semaphore main_semaphore; U32 worker_count; TP_Worker *worker_arr; TP_Arena *task_arena; TP_TaskFunc *task_func; void *task_data; U64 task_count; U64 task_done; S64 task_left; } TP_Context; internal TP_Context * tp_alloc(Arena *arena, U32 worker_count, U32 max_worker_count, String8 name); internal void tp_release(TP_Context *pool); internal TP_Arena * tp_arena_alloc(TP_Context *pool); internal void tp_arena_release(TP_Arena **arena_ptr); internal TP_Temp tp_temp_begin(TP_Arena *arena); internal void tp_temp_end(TP_Temp temp); #define tp_for_parallel_prof(pool, arena, task_count, task_func, task_data, zone_name) ProfBegin(zone_name); tp_for_parallel(pool, arena, task_count, task_func, task_data); ProfEnd(); internal void tp_for_parallel(TP_Context *pool, TP_Arena *arena, U64 task_count, TP_TaskFunc *task_func, void *task_data); internal Rng1U64 * tp_divide_work(Arena *arena, U64 item_count, U32 worker_count); ================================================ FILE: src/mdesk/mdesk.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Message Type Functions internal void md_msg_list_push(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, String8 string) { MD_Msg *msg = push_array(arena, MD_Msg, 1); msg->node = node; msg->kind = kind; msg->string = string; SLLQueuePush(msgs->first, msgs->last, msg); msgs->count += 1; msgs->worst_message_kind = Max(kind, msgs->worst_message_kind); } internal void md_msg_list_pushf(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, char *fmt, ...) { va_list args; va_start(args, fmt); String8 string = push_str8fv(arena, fmt, args); md_msg_list_push(arena, msgs, node, kind, string); va_end(args); } internal void md_msg_list_concat_in_place(MD_MsgList *dst, MD_MsgList *to_push) { if(to_push->first != 0) { if(dst->last) { dst->last->next = to_push->first; dst->last = to_push->last; dst->count += to_push->count; dst->worst_message_kind = Max(dst->worst_message_kind, to_push->worst_message_kind); } else { MemoryCopyStruct(dst, to_push); } } MemoryZeroStruct(to_push); } //////////////////////////////// //~ rjf: Token Type Functions internal MD_Token md_token_make(Rng1U64 range, MD_TokenFlags flags) { MD_Token token = {range, flags}; return token; } internal B32 md_token_match(MD_Token a, MD_Token b) { return (a.range.min == b.range.min && a.range.max == b.range.max && a.flags == b.flags); } internal String8List md_string_list_from_token_flags(Arena *arena, MD_TokenFlags flags) { String8List strs = {0}; if(flags & MD_TokenFlag_Identifier ){str8_list_push(arena, &strs, str8_lit("Identifier"));} if(flags & MD_TokenFlag_Numeric ){str8_list_push(arena, &strs, str8_lit("Numeric"));} if(flags & MD_TokenFlag_StringLiteral ){str8_list_push(arena, &strs, str8_lit("StringLiteral"));} if(flags & MD_TokenFlag_Symbol ){str8_list_push(arena, &strs, str8_lit("Symbol"));} if(flags & MD_TokenFlag_Reserved ){str8_list_push(arena, &strs, str8_lit("Reserved"));} if(flags & MD_TokenFlag_Comment ){str8_list_push(arena, &strs, str8_lit("Comment"));} if(flags & MD_TokenFlag_Whitespace ){str8_list_push(arena, &strs, str8_lit("Whitespace"));} if(flags & MD_TokenFlag_Newline ){str8_list_push(arena, &strs, str8_lit("Newline"));} if(flags & MD_TokenFlag_BrokenComment ){str8_list_push(arena, &strs, str8_lit("BrokenComment"));} if(flags & MD_TokenFlag_BrokenStringLiteral ){str8_list_push(arena, &strs, str8_lit("BrokenStringLiteral"));} if(flags & MD_TokenFlag_BadCharacter ){str8_list_push(arena, &strs, str8_lit("BadCharacter"));} return strs; } internal void md_token_chunk_list_push(Arena *arena, MD_TokenChunkList *list, U64 cap, MD_Token token) { MD_TokenChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, MD_TokenChunkNode, 1); node->cap = cap; node->v = push_array_no_zero(arena, MD_Token, cap); SLLQueuePush(list->first, list->last, node); list->chunk_count += 1; } MemoryCopyStruct(&node->v[node->count], &token); node->count += 1; list->total_token_count += 1; } internal MD_TokenArray md_token_array_from_chunk_list(Arena *arena, MD_TokenChunkList *chunks) { MD_TokenArray result = {0}; result.count = chunks->total_token_count; result.v = push_array_no_zero(arena, MD_Token, result.count); U64 write_idx = 0; for(MD_TokenChunkNode *n = chunks->first; n != 0; n = n->next) { MemoryCopy(result.v+write_idx, n->v, sizeof(MD_Token)*n->count); write_idx += n->count; } return result; } internal String8 md_content_string_from_token_flags_str8(MD_TokenFlags flags, String8 string) { U64 num_chop = 0; U64 num_skip = 0; { num_skip += 3*!!(flags & MD_TokenFlag_StringTriplet); num_chop += 3*!!(flags & MD_TokenFlag_StringTriplet); num_skip += 1*(!(flags & MD_TokenFlag_StringTriplet) && flags & MD_TokenFlag_StringLiteral); num_chop += 1*(!(flags & MD_TokenFlag_StringTriplet) && flags & MD_TokenFlag_StringLiteral); } String8 result = string; result = str8_chop(result, num_chop); result = str8_skip(result, num_skip); return result; } //////////////////////////////// //~ rjf: Node Type Functions //- rjf: flag conversions internal MD_NodeFlags md_node_flags_from_token_flags(MD_TokenFlags flags) { MD_NodeFlags result = 0; result |= MD_NodeFlag_Identifier*!!(flags&MD_TokenFlag_Identifier); result |= MD_NodeFlag_Numeric*!!(flags&MD_TokenFlag_Numeric); result |= MD_NodeFlag_StringLiteral*!!(flags&MD_TokenFlag_StringLiteral); result |= MD_NodeFlag_Symbol*!!(flags&MD_TokenFlag_Symbol); result |= MD_NodeFlag_StringSingleQuote *!!(flags&MD_TokenFlag_StringSingleQuote); result |= MD_NodeFlag_StringDoubleQuote *!!(flags&MD_TokenFlag_StringDoubleQuote); result |= MD_NodeFlag_StringTick*!!(flags&MD_TokenFlag_StringTick); result |= MD_NodeFlag_StringTriplet*!!(flags&MD_TokenFlag_StringTriplet); return result; } //- rjf: nil internal B32 md_node_is_nil(MD_Node *node) { return (node == 0 || node == &md_nil_node || node->kind == MD_NodeKind_Nil); } //- rjf: iteration internal MD_NodeRec md_node_rec_depth_first(MD_Node *node, MD_Node *subtree_root, U64 child_off, U64 sib_off) { MD_NodeRec rec = {0}; rec.next = &md_nil_node; if(!md_node_is_nil(*MemberFromOffset(MD_Node **, node, child_off))) { rec.next = *MemberFromOffset(MD_Node **, node, child_off); rec.push_count = 1; } else for(MD_Node *p = node; !md_node_is_nil(p) && p != subtree_root; p = p->parent, rec.pop_count += 1) { if(!md_node_is_nil(*MemberFromOffset(MD_Node **, p, sib_off))) { rec.next = *MemberFromOffset(MD_Node **, p, sib_off); break; } } return rec; } //- rjf: tree building internal MD_Node * md_push_node(Arena *arena, MD_NodeKind kind, MD_NodeFlags flags, String8 string, String8 raw_string, U64 src_offset) { MD_Node *node = push_array(arena, MD_Node, 1); node->first = node->last = node->parent = node->next = node->prev = node->first_tag = node->last_tag = &md_nil_node; node->kind = kind; node->flags = flags; node->string = string; node->raw_string = raw_string; node->src_offset = src_offset; return node; } internal void md_node_insert_child(MD_Node *parent, MD_Node *prev_child, MD_Node *node) { node->parent = parent; DLLInsert_NPZ(&md_nil_node, parent->first, parent->last, prev_child, node, next, prev); } internal void md_node_insert_tag(MD_Node *parent, MD_Node *prev_child, MD_Node *node) { node->kind = MD_NodeKind_Tag; node->parent = parent; DLLInsert_NPZ(&md_nil_node, parent->first_tag, parent->last_tag, prev_child, node, next, prev); } internal void md_node_push_child(MD_Node *parent, MD_Node *node) { node->parent = parent; DLLPushBack_NPZ(&md_nil_node, parent->first, parent->last, node, next, prev); } internal void md_node_push_tag(MD_Node *parent, MD_Node *node) { node->kind = MD_NodeKind_Tag; node->parent = parent; DLLPushBack_NPZ(&md_nil_node, parent->first_tag, parent->last_tag, node, next, prev); } internal void md_unhook(MD_Node *node) { MD_Node *parent = node->parent; if(!md_node_is_nil(parent)) { if(node->kind == MD_NodeKind_Tag) { DLLRemove_NPZ(&md_nil_node, parent->first_tag, parent->last_tag, node, next, prev); } else { DLLRemove_NPZ(&md_nil_node, parent->first, parent->last, node, next, prev); } node->parent = &md_nil_node; } } //- rjf: tree introspection internal MD_Node * md_node_from_chain_string(MD_Node *first, MD_Node *opl, String8 string, StringMatchFlags flags) { MD_Node *result = &md_nil_node; for(MD_Node *n = first; !md_node_is_nil(n) && n != opl; n = n->next) { if(str8_match(n->string, string, flags)) { result = n; break; } } return result; } internal MD_Node * md_node_from_chain_index(MD_Node *first, MD_Node *opl, U64 index) { MD_Node *result = &md_nil_node; S64 idx = 0; for(MD_Node *n = first; !md_node_is_nil(n) && n != opl; n = n->next, idx += 1) { if(index == idx) { result = n; break; } } return result; } internal MD_Node * md_node_from_chain_flags(MD_Node *first, MD_Node *opl, MD_NodeFlags flags) { MD_Node *result = &md_nil_node; for(MD_Node *n = first; !md_node_is_nil(n) && n != opl; n = n->next) { if(n->flags & flags) { result = n; break; } } return result; } internal U64 md_index_from_node(MD_Node *node) { U64 index = 0; for(MD_Node *n = node->prev; !md_node_is_nil(n); n = n->prev) { index += 1; } return index; } internal MD_Node * md_root_from_node(MD_Node *node) { MD_Node *result = node; for(MD_Node *p = node->parent; (p->kind == MD_NodeKind_Main || p->kind == MD_NodeKind_Tag) && !md_node_is_nil(p); p = p->parent) { result = p; } return result; } internal MD_Node * md_child_from_string(MD_Node *node, String8 child_string, StringMatchFlags flags) { return md_node_from_chain_string(node->first, &md_nil_node, child_string, flags); } internal MD_Node * md_tag_from_string(MD_Node *node, String8 tag_string, StringMatchFlags flags) { return md_node_from_chain_string(node->first_tag, &md_nil_node, tag_string, flags); } internal MD_Node * md_child_from_index(MD_Node *node, U64 index) { return md_node_from_chain_index(node->first, &md_nil_node, index); } internal MD_Node * md_tag_from_index(MD_Node *node, U64 index) { return md_node_from_chain_index(node->first_tag, &md_nil_node, index); } internal MD_Node * md_tag_arg_from_index(MD_Node *node, String8 tag_string, StringMatchFlags flags, U64 index) { MD_Node *tag = md_tag_from_string(node, tag_string, flags); return md_child_from_index(tag, index); } internal MD_Node * md_tag_arg_from_string(MD_Node *node, String8 tag_string, StringMatchFlags tag_str_flags, String8 arg_string, StringMatchFlags arg_str_flags) { MD_Node *tag = md_tag_from_string(node, tag_string, tag_str_flags); MD_Node *arg = md_child_from_string(tag, arg_string, arg_str_flags); return arg; } internal B32 md_node_has_child(MD_Node *node, String8 string, StringMatchFlags flags) { return !md_node_is_nil(md_child_from_string(node, string, flags)); } internal B32 md_node_has_tag(MD_Node *node, String8 string, StringMatchFlags flags) { return !md_node_is_nil(md_tag_from_string(node, string, flags)); } internal U64 md_child_count_from_node(MD_Node *node) { U64 result = 0; for(MD_Node *child = node->first; !md_node_is_nil(child); child = child->next) { result += 1; } return result; } internal U64 md_tag_count_from_node(MD_Node *node) { U64 result = 0; for(MD_Node *child = node->first_tag; !md_node_is_nil(child); child = child->next) { result += 1; } return result; } internal String8 md_string_from_children(Arena *arena, MD_Node *root) { Temp scratch = scratch_begin(&arena, 1); String8List strs = {0}; for MD_EachNode(child, root->first) { if(child->flags == child->prev->flags) { str8_list_push(scratch.arena, &strs, str8_lit(" ")); } str8_list_push(scratch.arena, &strs, child->string); } String8 result = str8_list_join(arena, &strs, 0); scratch_end(scratch); return result; } //- rjf: tree comparison internal B32 md_node_match(MD_Node *a, MD_Node *b, StringMatchFlags flags) { B32 result = 0; if(a->kind == b->kind && str8_match(a->string, b->string, flags)) { result = 1; if(result) { result = result && a->flags == b->flags; } if(result && a->kind != MD_NodeKind_Tag) { for(MD_Node *a_tag = a->first_tag, *b_tag = b->first_tag; !md_node_is_nil(a_tag) || !md_node_is_nil(b_tag); a_tag = a_tag->next, b_tag = b_tag->next) { if(md_node_match(a_tag, b_tag, flags)) { for(MD_Node *a_tag_arg = a_tag->first, *b_tag_arg = b_tag->first; !md_node_is_nil(a_tag_arg) || !md_node_is_nil(b_tag_arg); a_tag_arg = a_tag_arg->next, b_tag_arg = b_tag_arg->next) { if(!md_tree_match(a_tag_arg, b_tag_arg, flags)) { result = 0; goto end; } } } else { result = 0; goto end; } } } } end:; return result; } internal B32 md_tree_match(MD_Node *a, MD_Node *b, StringMatchFlags flags) { B32 result = md_node_match(a, b, flags); if(result) { for(MD_Node *a_child = a->first, *b_child = b->first; !md_node_is_nil(a_child) || !md_node_is_nil(b_child); a_child = a_child->next, b_child = b_child->next) { if(!md_tree_match(a_child, b_child, flags)) { result = 0; goto end; } } } end:; return result; } //- rjf: tree duplication internal MD_Node * md_tree_copy(Arena *arena, MD_Node *src_root) { MD_Node *dst_root = &md_nil_node; MD_Node *dst_parent = dst_root; { MD_NodeRec rec = {0}; for(MD_Node *src = src_root; !md_node_is_nil(src); src = rec.next) { MD_Node *dst = push_array(arena, MD_Node, 1); dst->first = dst->last = dst->parent = dst->next = dst->prev = &md_nil_node; dst->first_tag = dst->last_tag = &md_nil_node; dst->kind = src->kind; dst->flags = src->flags; dst->string = push_str8_copy(arena, src->string); dst->raw_string = push_str8_copy(arena, src->raw_string); dst->src_offset = src->src_offset; dst->parent = dst_parent; if(dst_parent != &md_nil_node) { DLLPushBack_NPZ(&md_nil_node, dst_parent->first, dst_parent->last, dst, next, prev); } else { dst_root = dst_parent = dst; } rec = md_node_rec_depth_first_pre(src, src_root); if(rec.push_count != 0) { dst_parent = dst; } else for(U64 idx = 0; idx < rec.pop_count; idx += 1) { dst_parent = dst_parent->parent; } } } return dst_root; } //////////////////////////////// //~ rjf: Text -> Tokens Functions internal MD_TokenizeResult md_tokenize_from_text(Arena *arena, String8 text) { Temp scratch = scratch_begin(&arena, 1); MD_TokenChunkList tokens = {0}; MD_MsgList msgs = {0}; U8 *byte_first = text.str; U8 *byte_opl = byte_first + text.size; U8 *byte = byte_first; //- rjf: scan string & produce tokens for(;byte < byte_opl;) { MD_TokenFlags token_flags = 0; U8 *token_start = 0; U8 *token_opl = 0; //- rjf: whitespace if(token_flags == 0 && (*byte == ' ' || *byte == '\t' || *byte == '\v' || *byte == '\r')) { token_flags = MD_TokenFlag_Whitespace; token_start = byte; token_opl = byte; byte += 1; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl || (*byte != ' ' && *byte != '\t' && *byte != '\v' && *byte != '\r')) { break; } } } //- rjf: newlines if(token_flags == 0 && *byte == '\n') { token_flags = MD_TokenFlag_Newline; token_start = byte; token_opl = byte+1; byte += 1; } //- rjf: single-line comments if(token_flags == 0 && (byte+1 < byte_opl && *byte == '/' && byte[1] == '/')) { token_flags = MD_TokenFlag_Comment; token_start = byte; token_opl = byte+2; byte += 2; B32 escaped = 0; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl) { break; } if(escaped) { escaped = 0; } else { if(*byte == '\n') { break; } else if(*byte == '\\') { escaped = 1; } } } } //- rjf: multi-line comments if(token_flags == 0 && (byte+1 < byte_opl && *byte == '/' && byte[1] == '*')) { token_flags = MD_TokenFlag_Comment; token_start = byte; token_opl = byte+2; byte += 2; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl) { token_flags |= MD_TokenFlag_BrokenComment; break; } if(byte+1 < byte_opl && byte[0] == '*' && byte[1] == '/') { token_opl += 2; break; } } } //- rjf: identifiers if(token_flags == 0 && (('A' <= *byte && *byte <= 'Z') || ('a' <= *byte && *byte <= 'z') || *byte == '_' || utf8_class[*byte>>3] >= 2 )) { token_flags = MD_TokenFlag_Identifier; token_start = byte; token_opl = byte; byte += 1; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl || (!('A' <= *byte && *byte <= 'Z') && !('a' <= *byte && *byte <= 'z') && !('0' <= *byte && *byte <= '9') && *byte != '_' && utf8_class[*byte>>3] < 2)) { break; } } } //- rjf: numerics if(token_flags == 0 && (('0' <= *byte && *byte <= '9') || (*byte == '.' && byte+1 < byte_opl && '0' <= byte[1] && byte[1] <= '9') || (*byte == '-' && byte+1 < byte_opl && '0' <= byte[1] && byte[1] <= '9') || *byte == '_')) { token_flags = MD_TokenFlag_Numeric; token_start = byte; token_opl = byte; byte += 1; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl || (!('A' <= *byte && *byte <= 'Z') && !('a' <= *byte && *byte <= 'z') && !('0' <= *byte && *byte <= '9') && *byte != '_' && *byte != '.')) { break; } } } //- rjf: triplet string literals if(token_flags == 0 && byte+2 < byte_opl && ((byte[0] == '"' && byte[1] == '"' && byte[2] == '"') || (byte[0] == '\''&& byte[1] == '\''&& byte[2] == '\'') || (byte[0] == '`' && byte[1] == '`' && byte[2] == '`'))) { U8 literal_style = byte[0]; token_flags = MD_TokenFlag_StringLiteral|MD_TokenFlag_StringTriplet; token_flags |= (literal_style == '\'')*MD_TokenFlag_StringSingleQuote; token_flags |= (literal_style == '"')*MD_TokenFlag_StringDoubleQuote; token_flags |= (literal_style == '`')*MD_TokenFlag_StringTick; token_start = byte; token_opl = byte+3; byte += 3; for(;byte <= byte_opl; byte += 1) { if(byte == byte_opl) { token_flags |= MD_TokenFlag_BrokenStringLiteral; token_opl = byte; break; } if(byte+2 < byte_opl && (byte[0] == literal_style && byte[1] == literal_style && byte[2] == literal_style)) { byte += 3; token_opl = byte; break; } } } //- rjf: singlet string literals if(token_flags == 0 && (byte[0] == '"' || byte[0] == '\'' || byte[0] == '`')) { U8 literal_style = byte[0]; token_flags = MD_TokenFlag_StringLiteral; token_flags |= (literal_style == '\'')*MD_TokenFlag_StringSingleQuote; token_flags |= (literal_style == '"')*MD_TokenFlag_StringDoubleQuote; token_flags |= (literal_style == '`')*MD_TokenFlag_StringTick; token_start = byte; token_opl = byte+1; byte += 1; B32 escaped = 0; for(;byte <= byte_opl; byte += 1) { if(byte == byte_opl || *byte == '\n') { token_opl = byte; token_flags |= MD_TokenFlag_BrokenStringLiteral; break; } if(!escaped && byte[0] == '\\') { escaped = 1; } else if(!escaped && byte[0] == literal_style) { token_opl = byte+1; byte += 1; break; } else if(escaped) { escaped = 0; } } } //- rjf: non-reserved symbols if(token_flags == 0 && (*byte == '~' || *byte == '!' || *byte == '$' || *byte == '%' || *byte == '^' || *byte == '&' || *byte == '*' || *byte == '-' || *byte == '=' || *byte == '+' || *byte == '<' || *byte == '.' || *byte == '>' || *byte == '/' || *byte == '?' || *byte == '|')) { token_flags = MD_TokenFlag_Symbol; token_start = byte; token_opl = byte; byte += 1; for(;byte <= byte_opl; byte += 1) { token_opl += 1; if(byte == byte_opl || (*byte != '~' && *byte != '!' && *byte != '$' && *byte != '%' && *byte != '^' && *byte != '&' && *byte != '*' && *byte != '-' && *byte != '=' && *byte != '+' && *byte != '<' && *byte != '.' && *byte != '>' && *byte != '/' && *byte != '?' && *byte != '|')) { break; } } } //- rjf: reserved symbols if(token_flags == 0 && (*byte == '{' || *byte == '}' || *byte == '(' || *byte == ')' || *byte == '[' || *byte == ']' || *byte == '#' || *byte == ',' || *byte == '\\'|| *byte == ':' || *byte == ';' || *byte == '@')) { token_flags = MD_TokenFlag_Reserved; token_start = byte; token_opl = byte+1; byte += 1; } //- rjf: bad characters in all other cases if(token_flags == 0) { token_flags = MD_TokenFlag_BadCharacter; token_start = byte; token_opl = byte+1; byte += 1; } //- rjf; push token if formed if(token_flags != 0 && token_start != 0 && token_opl > token_start) { MD_Token token = {{(U64)(token_start - byte_first), (U64)(token_opl - byte_first)}, token_flags}; md_token_chunk_list_push(scratch.arena, &tokens, 4096, token); } //- rjf: push errors on unterminated comments if(token_flags & MD_TokenFlag_BrokenComment) { MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, str8_lit(""), str8_lit(""), token_start - byte_first); String8 error_string = str8_lit("Unterminated comment."); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Error, error_string); } //- rjf: push errors on unterminated strings if(token_flags & MD_TokenFlag_BrokenStringLiteral) { MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, str8_lit(""), str8_lit(""), token_start - byte_first); String8 error_string = str8_lit("Unterminated string literal."); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Error, error_string); } } //- rjf: bake, fill & return MD_TokenizeResult result = {0}; { result.tokens = md_token_array_from_chunk_list(arena, &tokens); result.msgs = msgs; } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Tokens -> Tree Functions internal MD_ParseResult md_parse_from_text_tokens(Arena *arena, String8 filename, String8 text, MD_TokenArray tokens) { Temp scratch = scratch_begin(&arena, 1); //- rjf: set up outputs MD_MsgList msgs = {0}; MD_Node *root = md_push_node(arena, MD_NodeKind_File, 0, filename, text, 0); //- rjf: set up parse rule stack typedef enum MD_ParseWorkKind { MD_ParseWorkKind_Main, MD_ParseWorkKind_MainImplicit, MD_ParseWorkKind_NodeOptionalFollowUp, MD_ParseWorkKind_NodeChildrenStyleScan, } MD_ParseWorkKind; typedef struct MD_ParseWorkNode MD_ParseWorkNode; struct MD_ParseWorkNode { MD_ParseWorkNode *next; MD_ParseWorkKind kind; MD_Node *parent; MD_Node *first_gathered_tag; MD_Node *last_gathered_tag; MD_NodeFlags gathered_node_flags; S32 counted_newlines; }; MD_ParseWorkNode first_work = { 0, MD_ParseWorkKind_Main, root, }; MD_ParseWorkNode broken_work = { 0, MD_ParseWorkKind_Main, root,}; MD_ParseWorkNode *work_top = &first_work; MD_ParseWorkNode *work_free = 0; #define MD_ParseWorkPush(work_kind, work_parent) do\ {\ MD_ParseWorkNode *work_node = work_free;\ if(work_node == 0) {work_node = push_array(scratch.arena, MD_ParseWorkNode, 1);}\ else { SLLStackPop(work_free); }\ work_node->kind = (work_kind);\ work_node->parent = (work_parent);\ SLLStackPush(work_top, work_node);\ }while(0) #define MD_ParseWorkPop() do\ {\ SLLStackPop(work_top);\ if(work_top == 0) {work_top = &broken_work;}\ }while(0) //- rjf: parse MD_Token *tokens_first = tokens.v; MD_Token *tokens_opl = tokens_first + tokens.count; MD_Token *token = tokens_first; for(;token < tokens_opl;) { //- rjf: unpack token String8 token_string = str8_substr(text, token[0].range); //- rjf: whitespace -> always no-op & inc if(token->flags & MD_TokenFlag_Whitespace) { token += 1; goto end_consume; } //- rjf: comments -> always no-op & inc if(token->flags & MD_TokenGroup_Comment) { token += 1; goto end_consume; } //- rjf: [node follow up] : following label -> work top parent has children. we need // to scan for explicit delimiters, else parse an implicitly delimited set of children if(work_top->kind == MD_ParseWorkKind_NodeOptionalFollowUp && str8_match(token_string, str8_lit(":"), 0)) { MD_Node *parent = work_top->parent; MD_ParseWorkPop(); MD_ParseWorkPush(MD_ParseWorkKind_NodeChildrenStyleScan, parent); token += 1; goto end_consume; } //- rjf: [node follow up] anything but : following label -> node has no children. just // pop & move on if(work_top->kind == MD_ParseWorkKind_NodeOptionalFollowUp) { MD_ParseWorkPop(); goto end_consume; } //- rjf: [main] separators -> mark & inc if(work_top->kind == MD_ParseWorkKind_Main && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit(","), 0) || str8_match(token_string, str8_lit(";"), 0))) { MD_Node *parent = work_top->parent; if(!md_node_is_nil(parent->last)) { parent->last->flags |= MD_NodeFlag_IsBeforeComma*!!str8_match(token_string, str8_lit(","), 0); parent->last->flags |= MD_NodeFlag_IsBeforeSemicolon*!!str8_match(token_string, str8_lit(";"), 0); work_top->gathered_node_flags |= MD_NodeFlag_IsAfterComma*!!str8_match(token_string, str8_lit(","), 0); work_top->gathered_node_flags |= MD_NodeFlag_IsAfterSemicolon*!!str8_match(token_string, str8_lit(";"), 0); } token += 1; goto end_consume; } //- rjf: [main_implicit] separators -> pop if(work_top->kind == MD_ParseWorkKind_MainImplicit && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit(","), 0) || str8_match(token_string, str8_lit(";"), 0))) { MD_ParseWorkPop(); goto end_consume; } //- rjf: [main, main_implicit] unexpected reserved tokens if((work_top->kind == MD_ParseWorkKind_Main || work_top->kind == MD_ParseWorkKind_MainImplicit) && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit("#"), 0) || str8_match(token_string, str8_lit("\\"), 0) || str8_match(token_string, str8_lit(":"), 0))) { MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, token_string, token_string, token->range.min); String8 error_string = push_str8f(arena, "Unexpected reserved symbol \"%S\".", token_string); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Error, error_string); token += 1; goto end_consume; } //- rjf: [main, main_implicit] tag signifier -> create new tag if((work_top->kind == MD_ParseWorkKind_Main || work_top->kind == MD_ParseWorkKind_MainImplicit) && token[0].flags & MD_TokenFlag_Reserved && str8_match(token_string, str8_lit("@"), 0)) { if(token+1 >= tokens_opl || !(token[1].flags & MD_TokenGroup_Label)) { MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, token_string, token_string, token->range.min); String8 error_string = str8_lit("Tag label expected after @ symbol."); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Error, error_string); token += 1; goto end_consume; } else { String8 tag_name_raw = str8_substr(text, token[1].range); String8 tag_name = md_content_string_from_token_flags_str8(token[1].flags, tag_name_raw); MD_Node *node = md_push_node(arena, MD_NodeKind_Tag, md_node_flags_from_token_flags(token[1].flags), tag_name, tag_name_raw, token[0].range.min); DLLPushBack_NPZ(&md_nil_node, work_top->first_gathered_tag, work_top->last_gathered_tag, node, next, prev); if(token+2 < tokens_opl && token[2].flags & MD_TokenFlag_Reserved && (str8_match(str8_substr(text, token[2].range), str8_lit("("), 0) || str8_match(str8_substr(text, token[2].range), str8_lit("["), 0) || str8_match(str8_substr(text, token[2].range), str8_lit("{"), 0))) { token += 3; MD_ParseWorkPush(MD_ParseWorkKind_Main, node); } else { token += 2; } goto end_consume; } } //- rjf: [main, main_implicit] label -> create new main if((work_top->kind == MD_ParseWorkKind_Main || work_top->kind == MD_ParseWorkKind_MainImplicit) && token->flags & MD_TokenGroup_Label) { String8 node_string_raw = token_string; String8 node_string = md_content_string_from_token_flags_str8(token->flags, node_string_raw); MD_NodeFlags flags = md_node_flags_from_token_flags(token->flags)|work_top->gathered_node_flags; work_top->gathered_node_flags = 0; MD_Node *node = md_push_node(arena, MD_NodeKind_Main, flags, node_string, node_string_raw, token[0].range.min); node->first_tag = work_top->first_gathered_tag; node->last_tag = work_top->last_gathered_tag; for(MD_Node *tag = work_top->first_gathered_tag; !md_node_is_nil(tag); tag = tag->next) { tag->parent = node; } work_top->first_gathered_tag = work_top->last_gathered_tag = &md_nil_node; md_node_push_child(work_top->parent, node); MD_ParseWorkPush(MD_ParseWorkKind_NodeOptionalFollowUp, node); token += 1; goto end_consume; } //- rjf: [main] {s, [s, and (s -> create new main if(work_top->kind == MD_ParseWorkKind_Main && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit("{"), 0) || str8_match(token_string, str8_lit("["), 0) || str8_match(token_string, str8_lit("("), 0))) { MD_NodeFlags flags = md_node_flags_from_token_flags(token->flags)|work_top->gathered_node_flags; flags |= MD_NodeFlag_HasBraceLeft*!!str8_match(token_string, str8_lit("{"), 0); flags |= MD_NodeFlag_HasBracketLeft*!!str8_match(token_string, str8_lit("["), 0); flags |= MD_NodeFlag_HasParenLeft*!!str8_match(token_string, str8_lit("("), 0); work_top->gathered_node_flags = 0; MD_Node *node = md_push_node(arena, MD_NodeKind_Main, flags, str8_lit(""), str8_lit(""), token[0].range.min); node->first_tag = work_top->first_gathered_tag; node->last_tag = work_top->last_gathered_tag; for(MD_Node *tag = work_top->first_gathered_tag; !md_node_is_nil(tag); tag = tag->next) { tag->parent = node; } work_top->first_gathered_tag = work_top->last_gathered_tag = &md_nil_node; md_node_push_child(work_top->parent, node); MD_ParseWorkPush(MD_ParseWorkKind_Main, node); token += 1; goto end_consume; } //- rjf: [node children style scan] {s, [s, and (s -> explicitly delimited children if(work_top->kind == MD_ParseWorkKind_NodeChildrenStyleScan && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit("{"), 0) || str8_match(token_string, str8_lit("["), 0) || str8_match(token_string, str8_lit("("), 0))) { MD_Node *parent = work_top->parent; parent->flags |= MD_NodeFlag_HasBraceLeft*!!str8_match(token_string, str8_lit("{"), 0); parent->flags |= MD_NodeFlag_HasBracketLeft*!!str8_match(token_string, str8_lit("["), 0); parent->flags |= MD_NodeFlag_HasParenLeft*!!str8_match(token_string, str8_lit("("), 0); MD_ParseWorkPop(); MD_ParseWorkPush(MD_ParseWorkKind_Main, parent); token += 1; goto end_consume; } //- rjf: [node children style scan] count newlines if(work_top->kind == MD_ParseWorkKind_NodeChildrenStyleScan && token->flags & MD_TokenFlag_Newline) { work_top->counted_newlines += 1; token += 1; goto end_consume; } //- rjf: [main_implicit] newline -> pop *all* current implicit work tasks if(work_top->kind == MD_ParseWorkKind_MainImplicit && token->flags & MD_TokenFlag_Newline) { for(;work_top->kind == MD_ParseWorkKind_MainImplicit;) { MD_ParseWorkPop(); } token += 1; goto end_consume; } //- rjf: [all but main_implicit] newline -> no-op & inc if(work_top->kind != MD_ParseWorkKind_MainImplicit && token->flags & MD_TokenFlag_Newline) { token += 1; goto end_consume; } //- rjf: [node children style scan] anything causing implicit set -> <2 newlines, all good, // >=2 newlines, houston we have a problem if(work_top->kind == MD_ParseWorkKind_NodeChildrenStyleScan) { if(work_top->counted_newlines >= 2) { MD_Node *node = work_top->parent; MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, token_string, token_string, token->range.min); String8 error_string = push_str8f(arena, "More than two newlines following \"%S\", which has implicitly-delimited children, resulting in an empty list of children.", node->string); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Warning, error_string); MD_ParseWorkPop(); } else { MD_Node *parent = work_top->parent; MD_ParseWorkPop(); MD_ParseWorkPush(MD_ParseWorkKind_MainImplicit, parent); } goto end_consume; } //- rjf: [main] }s, ]s, and )s -> pop if(work_top->kind == MD_ParseWorkKind_Main && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit("}"), 0) || str8_match(token_string, str8_lit("]"), 0) || str8_match(token_string, str8_lit(")"), 0))) { MD_Node *parent = work_top->parent; parent->flags |= MD_NodeFlag_HasBraceRight*!!str8_match(token_string, str8_lit("}"), 0); parent->flags |= MD_NodeFlag_HasBracketRight*!!str8_match(token_string, str8_lit("]"), 0); parent->flags |= MD_NodeFlag_HasParenRight*!!str8_match(token_string, str8_lit(")"), 0); MD_ParseWorkPop(); token += 1; goto end_consume; } //- rjf: [main implicit] }s, ]s, and )s -> pop without advancing if(work_top->kind == MD_ParseWorkKind_MainImplicit && token->flags & MD_TokenFlag_Reserved && (str8_match(token_string, str8_lit("}"), 0) || str8_match(token_string, str8_lit("]"), 0) || str8_match(token_string, str8_lit(")"), 0))) { MD_ParseWorkPop(); goto end_consume; } //- rjf: no consumption -> unexpected token! we don't know what to do with this. { MD_Node *error = md_push_node(arena, MD_NodeKind_ErrorMarker, 0, token_string, token_string, token->range.min); String8 error_string = push_str8f(arena, "Unexpected \"%S\" token.", token_string); md_msg_list_push(arena, &msgs, error, MD_MsgKind_Error, error_string); token += 1; } end_consume:; } //- rjf: fill & return MD_ParseResult result = {0}; result.root = root; result.msgs = msgs; scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Bundled Text -> Tree Functions internal MD_ParseResult md_parse_from_text(Arena *arena, String8 filename, String8 text) { Temp scratch = scratch_begin(&arena, 1); MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, text); MD_ParseResult parse = md_parse_from_text_tokens(arena, filename, text, tokenize.tokens); scratch_end(scratch); return parse; } //////////////////////////////// //~ rjf: Tree -> Text Functions internal String8List md_debug_string_list_from_tree(Arena *arena, MD_Node *root) { String8List strings = {0}; { char *indentation = " "; S32 depth = 0; for(MD_Node *node = root, *next = &md_nil_node; !md_node_is_nil(node); node = next) { // rjf: get next recursion MD_NodeRec rec = md_node_rec_depth_first_pre(node, root); next = rec.next; // rjf: extract node info String8 kind_string = str8_lit("Unknown"); switch(node->kind) { default:{}break; case MD_NodeKind_File: {kind_string = str8_lit("File"); }break; case MD_NodeKind_ErrorMarker:{kind_string = str8_lit("ErrorMarker");}break; case MD_NodeKind_Main: {kind_string = str8_lit("Main"); }break; case MD_NodeKind_Tag: {kind_string = str8_lit("Tag"); }break; case MD_NodeKind_List: {kind_string = str8_lit("List"); }break; case MD_NodeKind_Reference: {kind_string = str8_lit("Reference"); }break; } // rjf: push node line str8_list_pushf(arena, &strings, "%.*s\"%S\" : %S", depth, indentation, node->string, kind_string); // rjf: children -> open brace if(rec.push_count != 0) { str8_list_pushf(arena, &strings, "%.*s{", depth, indentation); } // rjf: descend depth += rec.push_count; // rjf: popping -> close braces for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1) { str8_list_pushf(arena, &strings, "%.*s}", depth-1-pop_idx, indentation); } // rjf: ascend depth -= rec.pop_count; } } return strings; } //////////////////////////////// //~ rjf: Node Pointer List Functions internal void md_node_ptr_list_push(Arena *arena, MD_NodePtrList *list, MD_Node *node) { MD_NodePtrNode *n = push_array(arena, MD_NodePtrNode, 1); n->v = node; SLLQueuePush(list->first, list->last, n); list->count += 1; } internal void md_node_ptr_list_push_front(Arena *arena, MD_NodePtrList *list, MD_Node *node) { MD_NodePtrNode *n = push_array(arena, MD_NodePtrNode, 1); n->v = node; SLLQueuePushFront(list->first, list->last, n); list->count += 1; } ================================================ FILE: src/mdesk/mdesk.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MDESK_H #define MDESK_H //////////////////////////////// //~ rjf: Messages typedef enum MD_MsgKind { MD_MsgKind_Null, MD_MsgKind_Note, MD_MsgKind_Warning, MD_MsgKind_Error, MD_MsgKind_FatalError, } MD_MsgKind; typedef struct MD_Msg MD_Msg; struct MD_Msg { MD_Msg *next; struct MD_Node *node; MD_MsgKind kind; String8 string; }; typedef struct MD_MsgList MD_MsgList; struct MD_MsgList { MD_Msg *first; MD_Msg *last; U64 count; MD_MsgKind worst_message_kind; }; //////////////////////////////// //~ rjf: Token Types typedef U32 MD_TokenFlags; enum { // rjf: base kind info MD_TokenFlag_Identifier = (1<<0), MD_TokenFlag_Numeric = (1<<1), MD_TokenFlag_StringLiteral = (1<<2), MD_TokenFlag_Symbol = (1<<3), MD_TokenFlag_Reserved = (1<<4), MD_TokenFlag_Comment = (1<<5), MD_TokenFlag_Whitespace = (1<<6), MD_TokenFlag_Newline = (1<<7), // rjf: decoration info MD_TokenFlag_StringSingleQuote = (1<<8), MD_TokenFlag_StringDoubleQuote = (1<<9), MD_TokenFlag_StringTick = (1<<10), MD_TokenFlag_StringTriplet = (1<<11), // rjf: error info MD_TokenFlag_BrokenComment = (1<<12), MD_TokenFlag_BrokenStringLiteral = (1<<13), MD_TokenFlag_BadCharacter = (1<<14), }; typedef U32 MD_TokenGroups; enum { MD_TokenGroup_Comment = MD_TokenFlag_Comment, MD_TokenGroup_Whitespace = (MD_TokenFlag_Whitespace| MD_TokenFlag_Newline), MD_TokenGroup_Irregular = (MD_TokenGroup_Comment| MD_TokenGroup_Whitespace), MD_TokenGroup_Regular = ~MD_TokenGroup_Irregular, MD_TokenGroup_Label = (MD_TokenFlag_Identifier| MD_TokenFlag_Numeric| MD_TokenFlag_StringLiteral| MD_TokenFlag_Symbol), MD_TokenGroup_Error = (MD_TokenFlag_BrokenComment| MD_TokenFlag_BrokenStringLiteral| MD_TokenFlag_BadCharacter), }; typedef struct MD_Token MD_Token; struct MD_Token { Rng1U64 range; MD_TokenFlags flags; }; typedef struct MD_TokenChunkNode MD_TokenChunkNode; struct MD_TokenChunkNode { MD_TokenChunkNode *next; MD_Token *v; U64 count; U64 cap; }; typedef struct MD_TokenChunkList MD_TokenChunkList; struct MD_TokenChunkList { MD_TokenChunkNode *first; MD_TokenChunkNode *last; U64 chunk_count; U64 total_token_count; }; typedef struct MD_TokenArray MD_TokenArray; struct MD_TokenArray { MD_Token *v; U64 count; }; //////////////////////////////// //~ rjf: Node Types typedef enum MD_NodeKind { MD_NodeKind_Nil, MD_NodeKind_File, MD_NodeKind_ErrorMarker, MD_NodeKind_Main, MD_NodeKind_Tag, MD_NodeKind_List, MD_NodeKind_Reference, MD_NodeKind_COUNT } MD_NodeKind; typedef U32 MD_NodeFlags; enum { MD_NodeFlag_MaskSetDelimiters = (0x3F<<0), MD_NodeFlag_HasParenLeft = (1<<0), MD_NodeFlag_HasParenRight = (1<<1), MD_NodeFlag_HasBracketLeft = (1<<2), MD_NodeFlag_HasBracketRight = (1<<3), MD_NodeFlag_HasBraceLeft = (1<<4), MD_NodeFlag_HasBraceRight = (1<<5), MD_NodeFlag_MaskSeparators = (0xF<<6), MD_NodeFlag_IsBeforeSemicolon = (1<<6), MD_NodeFlag_IsAfterSemicolon = (1<<7), MD_NodeFlag_IsBeforeComma = (1<<8), MD_NodeFlag_IsAfterComma = (1<<9), MD_NodeFlag_MaskStringDelimiters = (0xF<<10), MD_NodeFlag_StringSingleQuote = (1<<10), MD_NodeFlag_StringDoubleQuote = (1<<11), MD_NodeFlag_StringTick = (1<<12), MD_NodeFlag_StringTriplet = (1<<13), MD_NodeFlag_MaskLabelKind = (0xF<<14), MD_NodeFlag_Numeric = (1<<14), MD_NodeFlag_Identifier = (1<<15), MD_NodeFlag_StringLiteral = (1<<16), MD_NodeFlag_Symbol = (1<<17), }; #define MD_NodeFlag_AfterFromBefore(f) ((f) << 1) typedef struct MD_Node MD_Node; struct MD_Node { // rjf: tree links MD_Node *next; MD_Node *prev; MD_Node *parent; MD_Node *first; MD_Node *last; // rjf: tag links MD_Node *first_tag; MD_Node *last_tag; // rjf: node info MD_NodeKind kind; MD_NodeFlags flags; String8 string; String8 raw_string; // rjf: source code info U64 src_offset; // rjf: user-controlled generation number // // (unused by mdesk layer, but can be used by usage code to use MD_Node trees // in a "retained mode" way, where stable generational handles can be formed // to nodes) U64 user_gen; // rjf: extra padding to 128 bytes U64 _unused_[2]; }; typedef struct MD_NodeRec MD_NodeRec; struct MD_NodeRec { MD_Node *next; S32 push_count; S32 pop_count; }; typedef struct MD_NodePtrNode MD_NodePtrNode; struct MD_NodePtrNode { MD_NodePtrNode *next; MD_Node *v; }; typedef struct MD_NodePtrList MD_NodePtrList; struct MD_NodePtrList { MD_NodePtrNode *first; MD_NodePtrNode *last; U64 count; }; //////////////////////////////// //~ rjf: Text -> Tokens Types typedef struct MD_TokenizeResult MD_TokenizeResult; struct MD_TokenizeResult { MD_TokenArray tokens; MD_MsgList msgs; }; //////////////////////////////// //~ rjf: Tokens -> Tree Types typedef struct MD_ParseResult MD_ParseResult; struct MD_ParseResult { MD_Node *root; MD_MsgList msgs; }; //////////////////////////////// //~ rjf: Globals global read_only MD_Node md_nil_node = { &md_nil_node, &md_nil_node, &md_nil_node, &md_nil_node, &md_nil_node, &md_nil_node, &md_nil_node, }; //////////////////////////////// //~ rjf: Message Type Functions internal void md_msg_list_push(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, String8 string); internal void md_msg_list_pushf(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, char *fmt, ...); internal void md_msg_list_concat_in_place(MD_MsgList *dst, MD_MsgList *to_push); //////////////////////////////// //~ rjf: Token Type Functions internal MD_Token md_token_make(Rng1U64 range, MD_TokenFlags flags); internal B32 md_token_match(MD_Token a, MD_Token b); internal String8List md_string_list_from_token_flags(Arena *arena, MD_TokenFlags flags); internal void md_token_chunk_list_push(Arena *arena, MD_TokenChunkList *list, U64 cap, MD_Token token); internal MD_TokenArray md_token_array_from_chunk_list(Arena *arena, MD_TokenChunkList *chunks); internal String8 md_content_string_from_token_flags_str8(MD_TokenFlags flags, String8 string); //////////////////////////////// //~ rjf: Node Type Functions //- rjf: flag conversions internal MD_NodeFlags md_node_flags_from_token_flags(MD_TokenFlags flags); //- rjf: nil internal B32 md_node_is_nil(MD_Node *node); //- rjf: iteration #define MD_EachNode(it, first) (MD_Node *it = first; !md_node_is_nil(it); it = it->next) internal MD_NodeRec md_node_rec_depth_first(MD_Node *node, MD_Node *subtree_root, U64 child_off, U64 sib_off); #define md_node_rec_depth_first_pre(node, subtree_root) md_node_rec_depth_first((node), (subtree_root), OffsetOf(MD_Node, first), OffsetOf(MD_Node, next)) #define md_node_rec_depth_first_pre_rev(node, subtree_root) md_node_rec_depth_first((node), (subtree_root), OffsetOf(MD_Node, last), OffsetOf(MD_Node, prev)) //- rjf: tree building internal MD_Node *md_push_node(Arena *arena, MD_NodeKind kind, MD_NodeFlags flags, String8 string, String8 raw_string, U64 src_offset); internal void md_node_insert_child(MD_Node *parent, MD_Node *prev_child, MD_Node *node); internal void md_node_insert_tag(MD_Node *parent, MD_Node *prev_child, MD_Node *node); internal void md_node_push_child(MD_Node *parent, MD_Node *node); internal void md_node_push_tag(MD_Node *parent, MD_Node *node); internal void md_unhook(MD_Node *node); //- rjf: tree introspection internal MD_Node * md_node_from_chain_string(MD_Node *first, MD_Node *opl, String8 string, StringMatchFlags flags); internal MD_Node * md_node_from_chain_index(MD_Node *first, MD_Node *opl, U64 index); internal MD_Node * md_node_from_chain_flags(MD_Node *first, MD_Node *opl, MD_NodeFlags flags); internal U64 md_index_from_node(MD_Node *node); internal MD_Node * md_root_from_node(MD_Node *node); internal MD_Node * md_child_from_string(MD_Node *node, String8 child_string, StringMatchFlags flags); internal MD_Node * md_tag_from_string(MD_Node *node, String8 tag_string, StringMatchFlags flags); internal MD_Node * md_child_from_index(MD_Node *node, U64 index); internal MD_Node * md_tag_from_index(MD_Node *node, U64 index); internal MD_Node * md_tag_arg_from_index(MD_Node *node, String8 tag_string, StringMatchFlags flags, U64 index); internal MD_Node * md_tag_arg_from_string(MD_Node *node, String8 tag_string, StringMatchFlags tag_str_flags, String8 arg_string, StringMatchFlags arg_str_flags); internal B32 md_node_has_child(MD_Node *node, String8 string, StringMatchFlags flags); internal B32 md_node_has_tag(MD_Node *node, String8 string, StringMatchFlags flags); internal U64 md_child_count_from_node(MD_Node *node); internal U64 md_tag_count_from_node(MD_Node *node); internal String8 md_string_from_children(Arena *arena, MD_Node *root); //- rjf: tree comparison internal B32 md_tree_match(MD_Node *a, MD_Node *b, StringMatchFlags flags); internal B32 md_node_match(MD_Node *a, MD_Node *b, StringMatchFlags flags); //- rjf: tree duplication internal MD_Node *md_tree_copy(Arena *arena, MD_Node *src_root); //////////////////////////////// //~ rjf: Text -> Tokens Functions internal MD_TokenizeResult md_tokenize_from_text(Arena *arena, String8 text); //////////////////////////////// //~ rjf: Tokens -> Tree Functions internal MD_ParseResult md_parse_from_text_tokens(Arena *arena, String8 filename, String8 text, MD_TokenArray tokens); //////////////////////////////// //~ rjf: Bundled Text -> Tree Functions internal MD_ParseResult md_parse_from_text(Arena *arena, String8 filename, String8 text); #define md_tree_from_string(arena, string) (md_parse_from_text((arena), str8_zero(), (string)).root) //////////////////////////////// //~ rjf: Tree -> Text Functions internal String8List md_debug_string_list_from_tree(Arena *arena, MD_Node *root); //////////////////////////////// //~ rjf: Node Pointer List Functions internal void md_node_ptr_list_push(Arena *arena, MD_NodePtrList *list, MD_Node *node); internal void md_node_ptr_list_push_front(Arena *arena, MD_NodePtrList *list, MD_Node *node); #endif // MDESK_H ================================================ FILE: src/metagen/metagen.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: String Expression Operator Tables read_only global String8 mg_str_expr_op_symbol_string_table[MG_StrExprOp_COUNT] = { str8_lit_comp(""), str8_lit_comp("."), // MG_StrExprOp_Dot str8_lit_comp("->"), // MG_StrExprOp_ExpandIfTrue str8_lit_comp(".."), // MG_StrExprOp_Concat str8_lit_comp("=>"), // MG_StrExprOp_BumpToColumn str8_lit_comp("+"), // MG_StrExprOp_Add str8_lit_comp("-"), // MG_StrExprOp_Subtract str8_lit_comp("*"), // MG_StrExprOp_Multiply str8_lit_comp("/"), // MG_StrExprOp_Divide str8_lit_comp("%"), // MG_StrExprOp_Modulo str8_lit_comp("<<"), // MG_StrExprOp_LeftShift str8_lit_comp(">>"), // MG_StrExprOp_RightShift str8_lit_comp("&"), // MG_StrExprOp_BitwiseAnd str8_lit_comp("|"), // MG_StrExprOp_BitwiseOr str8_lit_comp("^"), // MG_StrExprOp_BitwiseXor str8_lit_comp("~"), // MG_StrExprOp_BitwiseNegate str8_lit_comp("&&"), // MG_StrExprOp_BooleanAnd str8_lit_comp("||"), // MG_StrExprOp_BooleanOr str8_lit_comp("!"), // MG_StrExprOp_BooleanNot str8_lit_comp("=="), // MG_StrExprOp_Equals str8_lit_comp("!="), // MG_StrExprOp_DoesNotEqual }; read_only global S8 mg_str_expr_op_precedence_table[MG_StrExprOp_COUNT] = { 0, 20, // MG_StrExprOp_Dot 1, // MG_StrExprOp_ExpandIfTrue 2, // MG_StrExprOp_Concat 12, // MG_StrExprOp_BumpToColumn 5, // MG_StrExprOp_Add 5, // MG_StrExprOp_Subtract 6, // MG_StrExprOp_Multiply 6, // MG_StrExprOp_Divide 6, // MG_StrExprOp_Modulo 7, // MG_StrExprOp_LeftShift 7, // MG_StrExprOp_RightShift 8, // MG_StrExprOp_BitwiseAnd 10, // MG_StrExprOp_BitwiseOr 9, // MG_StrExprOp_BitwiseXor 11, // MG_StrExprOp_BitwiseNegate 3, // MG_StrExprOp_BooleanAnd 3, // MG_StrExprOp_BooleanOr 11, // MG_StrExprOp_BooleanNot 4, // MG_StrExprOp_Equals 4, // MG_StrExprOp_DoesNotEqual }; read_only global MG_StrExprOpKind mg_str_expr_op_kind_table[MG_StrExprOp_COUNT] = { MG_StrExprOpKind_Null, MG_StrExprOpKind_Binary, // MG_StrExprOp_Dot MG_StrExprOpKind_Binary, // MG_StrExprOp_ExpandIfTrue MG_StrExprOpKind_Binary, // MG_StrExprOp_Concat MG_StrExprOpKind_Prefix, // MG_StrExprOp_BumpToColumn MG_StrExprOpKind_Binary, // MG_StrExprOp_Add MG_StrExprOpKind_Binary, // MG_StrExprOp_Subtract MG_StrExprOpKind_Binary, // MG_StrExprOp_Multiply MG_StrExprOpKind_Binary, // MG_StrExprOp_Divide MG_StrExprOpKind_Binary, // MG_StrExprOp_Modulo MG_StrExprOpKind_Binary, // MG_StrExprOp_LeftShift MG_StrExprOpKind_Binary, // MG_StrExprOp_RightShift MG_StrExprOpKind_Binary, // MG_StrExprOp_BitwiseAnd MG_StrExprOpKind_Binary, // MG_StrExprOp_BitwiseOr MG_StrExprOpKind_Binary, // MG_StrExprOp_BitwiseXor MG_StrExprOpKind_Prefix, // MG_StrExprOp_BitwiseNegate MG_StrExprOpKind_Binary, // MG_StrExprOp_BooleanAnd MG_StrExprOpKind_Binary, // MG_StrExprOp_BooleanOr MG_StrExprOpKind_Prefix, // MG_StrExprOp_BooleanNot MG_StrExprOpKind_Binary, // MG_StrExprOp_Equals MG_StrExprOpKind_Binary, // MG_StrExprOp_DoesNotEqual }; //////////////////////////////// //~ rjf: Basic Helpers internal U64 mg_hash_from_string(String8 string) { U64 result = 5381; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + string.str[i]; } return result; } internal TxtPt mg_txt_pt_from_string_off(String8 string, U64 off) { TxtPt pt = txt_pt(1, 1); for(U64 idx = 0; idx < string.size && idx < off; idx += 1) { if(string.str[idx] == '\n') { pt.line += 1; pt.column = 1; } else { pt.column += 1; } } return pt; } //////////////////////////////// //~ rjf: Message Lists internal void mg_msg_list_push(Arena *arena, MG_MsgList *msgs, MG_Msg *msg) { MG_MsgNode *n = push_array(arena, MG_MsgNode, 1); MemoryCopyStruct(&n->v, msg); SLLQueuePush(msgs->first, msgs->last, n); msgs->count += 1; } //////////////////////////////// //~ rjf: String Escaping internal String8 mg_escaped_from_str8(Arena *arena, String8 string) { // NOTE(rjf): This doesn't handle hex/octal/unicode escape sequences right // now, just the simple stuff. Temp scratch = scratch_begin(&arena, 1); String8List strs = {0}; U64 start = 0; for(U64 idx = 0; idx <= string.size; idx += 1) { if(idx == string.size || string.str[idx] == '\\' || string.str[idx] == '\r') { String8 str = str8_substr(string, r1u64(start, idx)); if(str.size != 0) { str8_list_push(scratch.arena, &strs, str); } start = idx+1; } if(idx < string.size && string.str[idx] == '\\') { U8 next_char = string.str[idx+1]; U8 replace_byte = 0; switch(next_char) { default:{}break; case 'a': replace_byte = 0x07; break; case 'b': replace_byte = 0x08; break; case 'e': replace_byte = 0x1b; break; case 'f': replace_byte = 0x0c; break; case 'n': replace_byte = 0x0a; break; case 'r': replace_byte = 0x0d; break; case 't': replace_byte = 0x09; break; case 'v': replace_byte = 0x0b; break; case '\\':replace_byte = '\\'; break; case '\'':replace_byte = '\''; break; case '"': replace_byte = '"'; break; case '?': replace_byte = '?'; break; } String8 replace_string = push_str8_copy(scratch.arena, str8(&replace_byte, 1)); str8_list_push(scratch.arena, &strs, replace_string); if(replace_byte == '\\' || replace_byte == '"' || replace_byte == '\'') { idx += 1; start += 1; } } } String8 result = str8_list_join(arena, &strs, 0); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: String Wrapping internal String8List mg_wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent) { String8List list = {0}; Rng1U64 line_range = r1u64(0, 0); U64 wrapped_indent_level = 0; static char *spaces = " "; for (U64 idx = 0; idx <= string.size; idx += 1){ U8 chr = idx < string.size ? string.str[idx] : 0; if (chr == '\n'){ Rng1U64 candidate_line_range = line_range; candidate_line_range.max = idx; // NOTE(nick): when wrapping is interrupted with \n we emit a string without including \n // because later tool_fprint_list inserts separator after each node // except for last node, so don't strip last \n. if (idx + 1 == string.size){ candidate_line_range.max += 1; } String8 substr = str8_substr(string, candidate_line_range); str8_list_push(arena, &list, substr); line_range = r1u64(idx+1,idx+1); } else if (char_is_space(chr) || chr == 0){ Rng1U64 candidate_line_range = line_range; candidate_line_range.max = idx; String8 substr = str8_substr(string, candidate_line_range); U64 width_this_line = max_width-wrapped_indent_level; if (list.node_count == 0){ width_this_line = first_line_max_width; } if (substr.size > width_this_line){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); line_range = r1u64(line_range.max+1, candidate_line_range.max); wrapped_indent_level = ClampTop(64, wrap_indent); } else{ line_range = candidate_line_range; } } } if (line_range.min < string.size && line_range.max > line_range.min){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); } return list; } //////////////////////////////// //~ rjf: C-String-Izing internal String8 mg_c_string_literal_from_multiline_string(String8 string) { String8List strings = {0}; { str8_list_push(mg_arena, &strings, str8_lit("\"\"\n")); U64 active_line_start_off = 0; for(U64 off = 0; off <= string.size; off += 1) { B32 is_newline = (off < string.size && (string.str[off] == '\n' || string.str[off] == '\r')); B32 is_ender = (off >= string.size || is_newline); if(is_ender) { String8 line = str8_substr(string, r1u64(active_line_start_off, off)); str8_list_push(mg_arena, &strings, str8_lit("\"")); str8_list_push(mg_arena, &strings, line); if(is_newline) { str8_list_push(mg_arena, &strings, str8_lit("\\n\"\n")); } else { str8_list_push(mg_arena, &strings, str8_lit("\"\n")); } active_line_start_off = off+1; } if(is_newline && string.str[off] == '\r') { active_line_start_off += 1; off += 1; } } } String8 result = str8_list_join(mg_arena, &strings, 0); return result; } internal String8 mg_c_array_literal_contents_from_data(String8 data) { Temp scratch = scratch_begin(0, 0); String8List strings = {0}; { for(U64 off = 0; off < data.size;) { U64 chunk_size = Min(data.size-off, 64); U8 *chunk_bytes = data.str+off; String8 chunk_text_string = {0}; chunk_text_string.size = chunk_size*5; chunk_text_string.str = push_array(mg_arena, U8, chunk_text_string.size); for(U64 byte_idx = 0; byte_idx < chunk_size; byte_idx += 1) { String8 byte_str = push_str8f(scratch.arena, "0x%02x,", chunk_bytes[byte_idx]); MemoryCopy(chunk_text_string.str+byte_idx*5, byte_str.str, byte_str.size); } off += chunk_size; str8_list_push(mg_arena, &strings, chunk_text_string); str8_list_push(mg_arena, &strings, str8_lit("\n")); } } String8 result = str8_list_join(mg_arena, &strings, 0); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Map Functions internal MG_Map mg_push_map(Arena *arena, U64 slot_count) { MG_Map map = {0}; map.slots_count = slot_count; map.slots = push_array(arena, MG_MapSlot, map.slots_count); return map; } internal void * mg_map_ptr_from_string(MG_Map *map, String8 string) { void *result = 0; { U64 hash = mg_hash_from_string(string); U64 slot_idx = hash%map->slots_count; MG_MapSlot *slot = &map->slots[slot_idx]; for(MG_MapNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, string, 0)) { result = n->val; break; } } } return result; } internal void mg_map_insert_ptr(Arena *arena, MG_Map *map, String8 string, void *val) { U64 hash = mg_hash_from_string(string); U64 slot_idx = hash%map->slots_count; MG_MapSlot *slot = &map->slots[slot_idx]; MG_MapNode *n = push_array(arena, MG_MapNode, 1); n->key = push_str8_copy(arena, string); n->val = val; SLLQueuePush(slot->first, slot->last, n); } //////////////////////////////// //~ rjf: String Expression Parsing internal MG_StrExpr * mg_push_str_expr(Arena *arena, MG_StrExprOp op, MD_Node *node) { MG_StrExpr *expr = push_array(arena, MG_StrExpr, 1); MemoryCopyStruct(expr, &mg_str_expr_nil); expr->op = op; expr->node = node; return expr; } internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node *opl, S8 min_prec) { MG_StrExprParseResult parse = {&mg_str_expr_nil}; { MD_Node *it = first; //- rjf: consume prefix operators MG_StrExpr *leafmost_op = &mg_str_expr_nil; for(;it != opl && !md_node_is_nil(it);) { MG_StrExprOp found_op = MG_StrExprOp_Null; for(MG_StrExprOp op = (MG_StrExprOp)(MG_StrExprOp_Null+1); op < MG_StrExprOp_COUNT; op = (MG_StrExprOp)(op+1)) { if(mg_str_expr_op_kind_table[op] == MG_StrExprOpKind_Prefix && str8_match(it->string, mg_str_expr_op_symbol_string_table[op], 0) && mg_str_expr_op_precedence_table[op] >= min_prec) { found_op = op; break; } } if(found_op != MG_StrExprOp_Null) { MG_StrExpr *op_expr = mg_push_str_expr(arena, found_op, it); if(leafmost_op == &mg_str_expr_nil) { leafmost_op = op_expr; } op_expr->left = parse.root; parse.root = op_expr; it = it->next; } else { break; } } //- rjf: parse atom { MG_StrExpr *atom = &mg_str_expr_nil; if(it->flags & (MD_NodeFlag_Identifier|MD_NodeFlag_Numeric|MD_NodeFlag_StringLiteral) && md_node_is_nil(it->first)) { atom = mg_push_str_expr(arena, MG_StrExprOp_Null, it); it = it->next; } else if(!md_node_is_nil(it->first)) { MG_StrExprParseResult subparse = mg_str_expr_parse_from_first_opl__min_prec(arena, it->first, &md_nil_node, 0); atom = subparse.root; md_msg_list_concat_in_place(&parse.msgs, &subparse.msgs); it = it->next; } if(leafmost_op != &mg_str_expr_nil) { leafmost_op->left = atom; } else { parse.root = atom; } } //- rjf: parse binary operator extensions at this precedence level for(;it != opl && !md_node_is_nil(it);) { // rjf: find binary op kind of `it` MG_StrExprOp found_op = MG_StrExprOp_Null; for(MG_StrExprOp op = (MG_StrExprOp)(MG_StrExprOp_Null+1); op < MG_StrExprOp_COUNT; op = (MG_StrExprOp)(op+1)) { if(mg_str_expr_op_kind_table[op] == MG_StrExprOpKind_Binary && str8_match(it->string, mg_str_expr_op_symbol_string_table[op], 0) && mg_str_expr_op_precedence_table[op] >= min_prec) { found_op = op; break; } } // rjf: good found_op -> build binary expr if(found_op != MG_StrExprOp_Null) { MG_StrExpr *op_expr = mg_push_str_expr(arena, found_op, it); if(leafmost_op == &mg_str_expr_nil) { leafmost_op = op_expr; } op_expr->left = parse.root; parse.root = op_expr; it = it->next; } else { break; } // rjf: parse right hand side of binary operator MG_StrExprParseResult subparse = mg_str_expr_parse_from_first_opl__min_prec(arena, it, opl, mg_str_expr_op_precedence_table[found_op]+1); parse.root->right = subparse.root; md_msg_list_concat_in_place(&parse.msgs, &subparse.msgs); if(subparse.root == &mg_str_expr_nil) { md_msg_list_pushf(arena, &parse.msgs, it, MD_MsgKind_Error, "Missing right-hand-side of '%S'.", mg_str_expr_op_symbol_string_table[found_op]); } it = subparse.next_node; } // rjf: store next node for more caller-side parsing parse.next_node = it; } return parse; } internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl(Arena *arena, MD_Node *first, MD_Node *opl) { MG_StrExprParseResult parse = mg_str_expr_parse_from_first_opl__min_prec(arena, first, opl, 0); return parse; } internal MG_StrExprParseResult mg_str_expr_parse_from_root(Arena *arena, MD_Node *root) { MG_StrExprParseResult parse = mg_str_expr_parse_from_first_opl__min_prec(arena, root->first, &md_nil_node, 0); return parse; } //////////////////////////////// //~ rjf: Table Generation Functions internal MG_NodeArray mg_node_array_make(Arena *arena, U64 count) { MG_NodeArray result = {0}; result.count = count; result.v = push_array(arena, MD_Node *, result.count); for(U64 idx = 0; idx < result.count; idx += 1) { result.v[idx] = &md_nil_node; } return result; } internal MG_NodeArray mg_child_array_from_node(Arena *arena, MD_Node *node) { MG_NodeArray children = mg_node_array_make(arena, md_child_count_from_node(node)); U64 idx = 0; for MD_EachNode(child, node->first) { children.v[idx] = child; idx += 1; } return children; } internal MG_NodeGrid mg_node_grid_make_from_node(Arena *arena, MD_Node *root) { MG_NodeGrid grid = {0}; // rjf: determine dimensions U64 row_count = md_child_count_from_node(root); U64 column_count = 0; for MD_EachNode(row, root->first) { U64 cell_count_this_row = md_child_count_from_node(row); column_count = Max(column_count, cell_count_this_row); } // rjf: fill grid grid.x_stride = 1; grid.y_stride = column_count; grid.cells = mg_node_array_make(arena, row_count*column_count); grid.row_parents = mg_node_array_make(arena, row_count); // rjf: fill nodes { U64 y = 0; for MD_EachNode(row, root->first) { U64 x = 0; grid.row_parents.v[y] = row; for MD_EachNode(cell, row->first) { grid.cells.v[x*grid.x_stride + y*grid.y_stride] = cell; x += 1; } y += 1; } } return grid; } internal MG_NodeArray mg_row_from_index(MG_NodeGrid grid, U64 index) { MG_NodeArray result = {0}; if(0 <= index && index < grid.cells.count / grid.x_stride) { result.count = grid.y_stride; result.v = &grid.cells.v[index*grid.y_stride]; } return result; } internal MG_NodeArray mg_column_from_index(Arena *arena, MG_NodeGrid grid, U64 index) { MG_NodeArray result = {0}; if(0 <= index && index < grid.y_stride) { U64 row_count = grid.cells.count / grid.y_stride; result = mg_node_array_make(arena, row_count); U64 idx = 0; for(U64 row_idx = 0; row_idx < row_count; row_idx += 1, idx += 1) { result.v[idx] = grid.cells.v[index*grid.x_stride + row_idx*grid.y_stride]; } } return result; } internal MD_Node * mg_node_from_grid_xy(MG_NodeGrid grid, U64 x, U64 y) { MD_Node *result = &md_nil_node; U64 idx = x*grid.x_stride + y*grid.y_stride; if(0 <= idx && idx < grid.cells.count) { result = grid.cells.v[idx]; } return result; } internal MG_ColumnDescArray mg_column_desc_array_make(Arena *arena, U64 count, MG_ColumnDesc *descs) { MG_ColumnDescArray result = {0}; result.count = count; result.v = push_array(arena, MG_ColumnDesc, result.count); MemoryCopy(result.v, descs, sizeof(*result.v)*result.count); return result; } internal MG_ColumnDescArray mg_column_desc_array_from_tag(Arena *arena, MD_Node *tag) { MG_ColumnDescArray result = {0}; result.count = md_child_count_from_node(tag); result.v = push_array(arena, MG_ColumnDesc, result.count); U64 idx = 0; for MD_EachNode(hdr, tag->first) { result.v[idx].name = push_str8_copy(arena, hdr->string); result.v[idx].kind = MG_ColumnKind_DirectCell; if(md_node_has_tag(hdr, str8_lit("tag_check"), 0)) { result.v[idx].kind = MG_ColumnKind_CheckForTag; } if(md_node_has_tag(hdr, str8_lit("tag_child"), 0)) { String8 tag_name = md_tag_from_string(hdr, str8_lit("tag_child"), 0)->first->string; result.v[idx].kind = MG_ColumnKind_TagChild; result.v[idx].tag_name = tag_name; } idx += 1; } return result; } internal U64 mg_column_index_from_name(MG_ColumnDescArray descs, String8 name) { U64 result = 0; for(U64 idx = 0; idx < descs.count; idx += 1) { if(str8_match(descs.v[idx].name, name, 0)) { result = idx; break; } } return result; } internal String8 mg_string_from_row_desc_idx(MD_Node *row_parent, MG_ColumnDescArray descs, U64 idx) { String8 result = {0}; // rjf: grab relevant column description MG_ColumnDesc *desc = 0; if(0 <= idx && idx < descs.count) { desc = descs.v + idx; } // rjf: grab node if(desc != 0) { switch(desc->kind) { default: break; case MG_ColumnKind_DirectCell: { // rjf: determine grid idx (shifted by synthetic columns) U64 cell_idx = idx; for(U64 col_idx = 0; col_idx < descs.count && col_idx < idx; col_idx += 1) { if(descs.v[col_idx].kind != MG_ColumnKind_DirectCell) { cell_idx -= 1; } } MD_Node *node = md_child_from_index(row_parent, cell_idx); result = node->string; }break; case MG_ColumnKind_CheckForTag: { String8 tag_name = desc->name; MD_Node *tag = md_tag_from_string(row_parent, tag_name, 0); result = md_node_is_nil(tag) ? str8_lit("0") : str8_lit("1"); }break; case MG_ColumnKind_TagChild: { String8 tag_name = desc->tag_name; MD_Node *tag = md_tag_from_string(row_parent, tag_name, 0); result = tag->first->string; }break; } } return result; } internal S64 mg_eval_table_expand_expr__numeric(MG_StrExpr *expr, MG_TableExpandInfo *info) { S64 result = 0; MG_StrExprOp op = expr->op; switch(op) { default: { if(MG_StrExprOp_FirstString <= op && op <= MG_StrExprOp_LastString) { Temp scratch = scratch_begin(0, 0); String8List result_strs = {0}; mg_eval_table_expand_expr__string(scratch.arena, expr, info, &result_strs); String8 result_str = str8_list_join(scratch.arena, &result_strs, 0); try_s64_from_str8_c_rules(result_str, &result); scratch_end(scratch); } }break; case MG_StrExprOp_Null: { try_s64_from_str8_c_rules(expr->node->string, &result); }break; //- rjf: numeric arithmetic binary ops case MG_StrExprOp_Add: case MG_StrExprOp_Subtract: case MG_StrExprOp_Multiply: case MG_StrExprOp_Divide: case MG_StrExprOp_Modulo: case MG_StrExprOp_LeftShift: case MG_StrExprOp_RightShift: case MG_StrExprOp_BitwiseAnd: case MG_StrExprOp_BitwiseOr: case MG_StrExprOp_BitwiseXor: case MG_StrExprOp_BooleanAnd: case MG_StrExprOp_BooleanOr: { S64 left_val = mg_eval_table_expand_expr__numeric(expr->left, info); S64 right_val = mg_eval_table_expand_expr__numeric(expr->right, info); switch(op) { default:break; case MG_StrExprOp_Add: result = left_val+right_val; break; case MG_StrExprOp_Subtract: result = left_val-right_val; break; case MG_StrExprOp_Multiply: result = left_val*right_val; break; case MG_StrExprOp_Divide: result = left_val/right_val; break; case MG_StrExprOp_Modulo: result = left_val%right_val; break; case MG_StrExprOp_LeftShift: result = left_val<>right_val; break; case MG_StrExprOp_BitwiseAnd: result = left_val&right_val; break; case MG_StrExprOp_BitwiseOr: result = left_val|right_val; break; case MG_StrExprOp_BitwiseXor: result = left_val^right_val; break; case MG_StrExprOp_BooleanAnd: result = left_val&&right_val; break; case MG_StrExprOp_BooleanOr: result = left_val||right_val; break; } }break; //- rjf: prefix unary ops case MG_StrExprOp_BitwiseNegate: case MG_StrExprOp_BooleanNot: { S64 right_val = mg_eval_table_expand_expr__numeric(expr->left, info); switch(op) { default:break; case MG_StrExprOp_BitwiseNegate: result = (S64)(~((U64)right_val)); break; case MG_StrExprOp_BooleanNot: result = !right_val; } }break; //- rjf: comparisons case MG_StrExprOp_Equals: case MG_StrExprOp_DoesNotEqual: { Temp scratch = scratch_begin(0, 0); String8List left_strs = {0}; String8List right_strs = {0}; mg_eval_table_expand_expr__string(scratch.arena, expr->left, info, &left_strs); mg_eval_table_expand_expr__string(scratch.arena, expr->right, info, &right_strs); String8 left_str = str8_list_join(scratch.arena, &left_strs, 0); String8 right_str = str8_list_join(scratch.arena, &right_strs, 0); B32 match = str8_match(left_str, right_str, 0); result = (op == MG_StrExprOp_Equals ? match : !match); scratch_end(scratch); }break; } return result; } internal void mg_eval_table_expand_expr__string(Arena *arena, MG_StrExpr *expr, MG_TableExpandInfo *info, String8List *out) { MG_StrExprOp op = expr->op; switch(op) { default: { if(MG_StrExprOp_FirstNumeric <= op && op <= MG_StrExprOp_LastNumeric) { S64 numeric_eval = mg_eval_table_expand_expr__numeric(expr, info); String8 numeric_eval_stringized = {0}; if(md_node_has_tag(md_root_from_node(expr->node), str8_lit("hex"), 0)) { numeric_eval_stringized = push_str8f(arena, "0x%I64x", numeric_eval); } else { numeric_eval_stringized = push_str8f(arena, "%I64d", numeric_eval); } str8_list_push(arena, out, numeric_eval_stringized); } }break; case MG_StrExprOp_Null: { str8_list_push(arena, out, expr->node->string); }break; case MG_StrExprOp_Dot: { // rjf: grab left/right MG_StrExpr *left_expr = expr->left; MD_Node *left_node = left_expr->node; MG_StrExpr *right_expr = expr->right; MD_Node *right_node = right_expr->node; // rjf: grab table name (LHS of .) and column lookup string (RHS of .) String8 expand_label = left_node->string; String8 column_lookup = right_node->string; // rjf: find which task corresponds to this table U64 row_idx = 0; MG_NodeGrid *grid = 0; MG_ColumnDescArray column_descs = {0}; { for(MG_TableExpandTask *task = info->first_expand_task; task != 0; task = task->next) { if(str8_match(expand_label, task->expansion_label, 0)) { row_idx = task->idx; grid = task->grid; column_descs = task->column_descs; break; } } } // rjf: grab row parent MD_Node *row_parent = &md_nil_node; if(grid && (0 <= row_idx && row_idx < grid->row_parents.count)) { row_parent = grid->row_parents.v[row_idx]; } // rjf: get string for this table lookup String8 lookup_string = {0}; { U64 column_idx = 0; if(str8_match(column_lookup, str8_lit("_it"), 0)) { lookup_string = push_str8f(arena, "%I64u", row_idx); } else { // NOTE(rjf): numeric column lookup (column index) if(right_node->flags & MD_NodeFlag_Numeric) { try_u64_from_str8_c_rules(column_lookup, &column_idx); } // NOTE(rjf): string column lookup (column name) if(right_node->flags & (MD_NodeFlag_Identifier|MD_NodeFlag_StringLiteral)) { column_idx = mg_column_index_from_name(column_descs, column_lookup); } lookup_string = mg_string_from_row_desc_idx(row_parent, column_descs, column_idx); if(str8_match(lookup_string, str8_lit("--"), 0)) { lookup_string = info->missing_value_fallback; } } } // rjf: push lookup string { B32 is_multiline = (str8_find_needle(lookup_string, 0, str8_lit("\n"), 0) < lookup_string.size); if(is_multiline) { lookup_string = indented_from_string(mg_arena, lookup_string); lookup_string = escaped_from_raw_str8(mg_arena, lookup_string); lookup_string = escaped_from_raw_str8(mg_arena, lookup_string); } str8_list_push(arena, out, lookup_string); } }break; case MG_StrExprOp_ExpandIfTrue: { S64 bool_value = mg_eval_table_expand_expr__numeric(expr->left, info); if(bool_value) { mg_eval_table_expand_expr__string(arena, expr->right, info, out); } }break; case MG_StrExprOp_Concat: { mg_eval_table_expand_expr__string(arena, expr->left, info, out); mg_eval_table_expand_expr__string(arena, expr->right, info, out); }break; case MG_StrExprOp_BumpToColumn: { S64 column = mg_eval_table_expand_expr__numeric(expr->left, info); S64 current_column = out->total_size; S64 spaces_to_push = column - current_column; if(spaces_to_push > 0) { String8 str = {0}; str.size = spaces_to_push; str.str = push_array(arena, U8, spaces_to_push); for(S64 idx = 0; idx < spaces_to_push; idx += 1) { str.str[idx] = ' '; } str8_list_push(arena, out, str); } }break; } } internal void mg_loop_table_column_expansion(Arena *arena, String8 strexpr, MG_TableExpandInfo *info, MG_TableExpandTask *task, String8List *out) { Temp scratch = scratch_begin(&arena, 1); for(U64 it_idx = 0; it_idx < task->count; it_idx += 1) { task->idx = it_idx; //- rjf: iterate all further dimensions, if there's left in the chain if(task->next) { mg_loop_table_column_expansion(arena, strexpr, info, task->next, out); } //- rjf: if this is the last task in the chain, perform expansion else { String8List expansion_strs = {0}; U64 start = 0; for(U64 char_idx = 0; char_idx <= strexpr.size;) { // rjf: push plain text parts of strexpr if(char_idx == strexpr.size || strexpr.str[char_idx] == '$') { String8 plain_text_substr = str8_substr(strexpr, r1u64(start, char_idx)); start = char_idx; if(plain_text_substr.size != 0) { str8_list_push(arena, &expansion_strs, plain_text_substr); } } // rjf: handle expansion expression if(strexpr.str[char_idx] == '$') { String8 string = str8_skip(strexpr, char_idx+1); Rng1U64 expr_range = {0}; S64 paren_nest = 0; for(U64 idx = 0; idx < string.size; idx += 1) { if(string.str[idx] == '(') { paren_nest += 1; if(paren_nest == 1) { expr_range.min = idx; } } if(string.str[idx] == ')') { paren_nest -= 1; if(paren_nest == 0) { expr_range.max = idx+1; break; } } } String8 expr_string = str8_substr(string, expr_range); MD_TokenizeResult expr_tokenize = md_tokenize_from_text(scratch.arena, expr_string); MD_ParseResult expr_base_parse = md_parse_from_text_tokens(scratch.arena, str8_lit(""), expr_string, expr_tokenize.tokens); MG_StrExprParseResult expr_parse = mg_str_expr_parse_from_root(scratch.arena, expr_base_parse.root->first); mg_eval_table_expand_expr__string(arena, expr_parse.root, info, &expansion_strs); char_idx = start = char_idx + 1 + expr_range.max; } else { char_idx += 1; } } String8 expansion_str = str8_list_join(arena, &expansion_strs, 0); if(expansion_str.size != 0) { expansion_str = raw_from_escaped_str8(mg_arena, expansion_str); str8_list_push(arena, out, expansion_str); } } } scratch_end(scratch); } internal String8List mg_string_list_from_table_gen(Arena *arena, MG_Map grid_name_map, MG_Map grid_column_desc_map, String8 fallback, MD_Node *gen) { String8List result = {0}; Temp scratch = scratch_begin(&arena, 1); if(md_node_is_nil(gen->first) && gen->string.size != 0) { str8_list_push(arena, &result, raw_from_escaped_str8(arena, gen->string)); str8_list_push(arena, &result, str8_lit("\n")); } else for MD_EachNode(strexpr_node, gen->first) { // rjf: build task list MG_TableExpandTask *first_task = 0; MG_TableExpandTask *last_task = 0; for MD_EachNode(tag, strexpr_node->first_tag) { if(str8_match(tag->string, str8_lit("expand"), 0)) { // rjf: grab args for this expansion MD_Node *table_name_node = md_child_from_index(tag, 0); MD_Node *expand_label_node = md_child_from_index(tag, 1); String8 table_name = table_name_node->string; String8 expand_label = expand_label_node->string; // rjf: lookup table / column descriptions MG_NodeGrid *grid = mg_map_ptr_from_string(&grid_name_map, table_name); MG_ColumnDescArray *column_descs = mg_map_ptr_from_string(&grid_column_desc_map, table_name); // rjf: figure out row count U64 grid_row_count = 0; if(grid != 0) { grid_row_count = grid->cells.count / grid->y_stride; } // rjf: push task for this expansion if(grid != 0) { MG_TableExpandTask *task = push_array(scratch.arena, MG_TableExpandTask, 1); task->expansion_label = expand_label; task->grid = grid; task->column_descs = *column_descs; task->count = grid_row_count; task->idx = 0; SLLQueuePush(first_task, last_task, task); } } } // rjf: do expansion generation, OR just push this string if we have no expansions { MG_TableExpandInfo info = {first_task, fallback}; if(first_task != 0) { mg_loop_table_column_expansion(arena, strexpr_node->string, &info, first_task, &result); } else { str8_list_push(arena, &result, raw_from_escaped_str8(arena, strexpr_node->string)); } } } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Layer Lookup Functions internal String8 mg_layer_key_from_path(String8 path) { Temp scratch = scratch_begin(0, 0); U64 src_folder_pos = 0; for(U64 next_src_folder_pos = 0; next_src_folder_pos < path.size; next_src_folder_pos = str8_find_needle(path, next_src_folder_pos+1, str8_lit("src"), 0)) { src_folder_pos = next_src_folder_pos; } String8List path_parts = str8_split_path(scratch.arena, str8_chop_last_slash(str8_skip(path, src_folder_pos+4))); StringJoin join = {0}; join.sep = str8_lit("/"); String8 key = str8_list_join(mg_arena, &path_parts, &join); scratch_end(scratch); return key; } internal MG_Layer * mg_layer_from_key(String8 key) { U64 hash = mg_hash_from_string(key); U64 slot_idx = hash%mg_state->slots_count; MG_LayerSlot *slot = &mg_state->slots[slot_idx]; MG_Layer *layer = 0; for(MG_LayerNode *n = slot->first; n != 0; n = n->next) { if(str8_match(n->v.key, key, 0)) { layer = &n->v; break; } } if(layer == 0) { MG_LayerNode *n = push_array(mg_arena, MG_LayerNode, 1); SLLQueuePush(slot->first, slot->last, n); n->v.key = push_str8_copy(mg_arena, key); layer = &n->v; } return layer; } ================================================ FILE: src/metagen/metagen.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef METAGEN_H #define METAGEN_H //////////////////////////////// //~ rjf: Message Type typedef struct MG_Msg MG_Msg; struct MG_Msg { String8 location; String8 kind; String8 msg; }; typedef struct MG_MsgNode MG_MsgNode; struct MG_MsgNode { MG_MsgNode *next; MG_Msg v; }; typedef struct MG_MsgList MG_MsgList; struct MG_MsgList { MG_MsgNode *first; MG_MsgNode *last; U64 count; }; //////////////////////////////// //~ rjf: Parse Artifact Types typedef struct MG_FileParse MG_FileParse; struct MG_FileParse { MD_Node *root; }; typedef struct MG_FileParseNode MG_FileParseNode; struct MG_FileParseNode { MG_FileParseNode *next; MG_FileParse v; }; typedef struct MG_FileParseList MG_FileParseList; struct MG_FileParseList { MG_FileParseNode *first; MG_FileParseNode *last; U64 count; }; //////////////////////////////// //~ rjf: Map Type typedef struct MG_MapNode MG_MapNode; struct MG_MapNode { MG_MapNode *next; String8 key; void *val; }; typedef struct MG_MapSlot MG_MapSlot; struct MG_MapSlot { MG_MapNode *first; MG_MapNode *last; }; typedef struct MG_Map MG_Map; struct MG_Map { MG_MapSlot *slots; U64 slots_count; }; //////////////////////////////// //~ rjf: String Expression Types typedef enum MG_StrExprOpKind { MG_StrExprOpKind_Null, MG_StrExprOpKind_Prefix, MG_StrExprOpKind_Postfix, MG_StrExprOpKind_Binary, MG_StrExprOpKind_COUNT } MG_StrExprOpKind; typedef enum MG_StrExprOp { MG_StrExprOp_Null, #define MG_StrExprOp_FirstString MG_StrExprOp_Dot MG_StrExprOp_Dot, MG_StrExprOp_ExpandIfTrue, MG_StrExprOp_Concat, MG_StrExprOp_BumpToColumn, #define MG_StrExprOp_LastString MG_StrExprOp_BumpToColumn #define MG_StrExprOp_FirstNumeric MG_StrExprOp_Add MG_StrExprOp_Add, MG_StrExprOp_Subtract, MG_StrExprOp_Multiply, MG_StrExprOp_Divide, MG_StrExprOp_Modulo, MG_StrExprOp_LeftShift, MG_StrExprOp_RightShift, MG_StrExprOp_BitwiseAnd, MG_StrExprOp_BitwiseOr, MG_StrExprOp_BitwiseXor, MG_StrExprOp_BitwiseNegate, MG_StrExprOp_BooleanAnd, MG_StrExprOp_BooleanOr, MG_StrExprOp_BooleanNot, MG_StrExprOp_Equals, MG_StrExprOp_DoesNotEqual, #define MG_StrExprOp_LastNumeric MG_StrExprOp_DoesNotEqual MG_StrExprOp_COUNT, } MG_StrExprOp; typedef struct MG_StrExpr MG_StrExpr; struct MG_StrExpr { MG_StrExpr *parent; MG_StrExpr *left; MG_StrExpr *right; MG_StrExprOp op; MD_Node *node; }; typedef struct MG_StrExprParseResult MG_StrExprParseResult; struct MG_StrExprParseResult { MG_StrExpr *root; MD_MsgList msgs; MD_Node *next_node; }; //////////////////////////////// //~ rjf: Table Generation Types typedef struct MG_NodeArray MG_NodeArray; struct MG_NodeArray { MD_Node **v; U64 count; }; typedef struct MG_NodeGrid MG_NodeGrid; struct MG_NodeGrid { U64 x_stride; U64 y_stride; MG_NodeArray cells; MG_NodeArray row_parents; }; typedef enum MG_ColumnKind { MG_ColumnKind_DirectCell, MG_ColumnKind_CheckForTag, MG_ColumnKind_TagChild, MG_ColumnKind_COUNT } MG_ColumnKind; typedef struct MG_ColumnDesc MG_ColumnDesc; struct MG_ColumnDesc { String8 name; MG_ColumnKind kind; String8 tag_name; }; typedef struct MG_ColumnDescArray MG_ColumnDescArray; struct MG_ColumnDescArray { U64 count; MG_ColumnDesc *v; }; typedef struct MG_TableExpandTask MG_TableExpandTask; struct MG_TableExpandTask { MG_TableExpandTask *next; String8 expansion_label; MG_NodeGrid *grid; MG_ColumnDescArray column_descs; U64 count; U64 idx; }; typedef struct MG_TableExpandInfo MG_TableExpandInfo; struct MG_TableExpandInfo { MG_TableExpandTask *first_expand_task; String8 missing_value_fallback; }; //////////////////////////////// //~ rjf: Main Output Path Types typedef struct MG_Layer MG_Layer; struct MG_Layer { String8 key; B32 is_library; String8 gen_folder_name; String8 h_name_override; String8 c_name_override; String8List enums; String8List structs; String8List h_functions; String8List h_tables; String8List h_catchall; String8List h_header; String8List h_footer; String8List c_functions; String8List c_tables; String8List c_catchall; String8List c_header; String8List c_footer; }; typedef struct MG_LayerNode MG_LayerNode; struct MG_LayerNode { MG_LayerNode *next; MG_Layer v; }; typedef struct MG_LayerSlot MG_LayerSlot; struct MG_LayerSlot { MG_LayerNode *first; MG_LayerNode *last; }; typedef struct MG_State MG_State; struct MG_State { U64 slots_count; MG_LayerSlot *slots; }; //////////////////////////////// //~ rjf: Globals global Arena *mg_arena = 0; global MG_State *mg_state = 0; read_only global MG_StrExpr mg_str_expr_nil = {&mg_str_expr_nil, &mg_str_expr_nil, &mg_str_expr_nil}; //////////////////////////////// //~ rjf: Basic Helpers internal U64 mg_hash_from_string(String8 string); internal TxtPt mg_txt_pt_from_string_off(String8 string, U64 off); //////////////////////////////// //~ rjf: Message Lists internal void mg_msg_list_push(Arena *arena, MG_MsgList *msgs, MG_Msg *msg); //////////////////////////////// //~ rjf: String Escaping internal String8 mg_escaped_from_str8(Arena *arena, String8 string); //////////////////////////////// //~ rjf: String Wrapping internal String8List mg_wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); //////////////////////////////// //~ rjf: C-String-Izing internal String8 mg_c_string_literal_from_multiline_string(String8 string); internal String8 mg_c_array_literal_contents_from_data(String8 data); //////////////////////////////// //~ rjf: Map Functions internal MG_Map mg_push_map(Arena *arena, U64 slot_count); internal void *mg_map_ptr_from_string(MG_Map *map, String8 string); internal void mg_map_insert_ptr(Arena *arena, MG_Map *map, String8 string, void *val); //////////////////////////////// //~ rjf: String Expression Parsing internal MG_StrExpr *mg_push_str_expr(Arena *arena, MG_StrExprOp op, MD_Node *node); internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node *opl, S8 min_prec); internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl(Arena *arena, MD_Node *first, MD_Node *opl); internal MG_StrExprParseResult mg_str_expr_parse_from_root(Arena *arena, MD_Node *root); //////////////////////////////// //~ rjf: Table Generation Functions internal MG_NodeArray mg_node_array_make(Arena *arena, U64 count); internal MG_NodeArray mg_child_array_from_node(Arena *arena, MD_Node *node); internal MG_NodeGrid mg_node_grid_make_from_node(Arena *arena, MD_Node *root); internal MG_NodeArray mg_row_from_index(MG_NodeGrid grid, U64 index); internal MG_NodeArray mg_column_from_index(Arena *arena, MG_NodeGrid grid, U64 index); internal MD_Node *mg_node_from_grid_xy(MG_NodeGrid grid, U64 x, U64 y); internal MG_ColumnDescArray mg_column_desc_array_make(Arena *arena, U64 count, MG_ColumnDesc *descs); internal MG_ColumnDescArray mg_column_desc_array_from_tag(Arena *arena, MD_Node *tag); internal U64 mg_column_index_from_name(MG_ColumnDescArray descs, String8 name); internal String8 mg_string_from_row_desc_idx(MD_Node *row_parent, MG_ColumnDescArray descs, U64 idx); internal S64 mg_eval_table_expand_expr__numeric(MG_StrExpr *expr, MG_TableExpandInfo *info); internal void mg_eval_table_expand_expr__string(Arena *arena, MG_StrExpr *expr, MG_TableExpandInfo *info, String8List *out); internal void mg_loop_table_column_expansion(Arena *arena, String8 strexpr, MG_TableExpandInfo *info, MG_TableExpandTask *task, String8List *out); internal String8List mg_string_list_from_table_gen(Arena *arena, MG_Map grid_name_map, MG_Map grid_column_desc_map, String8 fallback, MD_Node *gen); //////////////////////////////// //~ rjf: Layer Lookup Functions internal String8 mg_layer_key_from_path(String8 path); internal MG_Layer *mg_layer_from_key(String8 key); #endif //METAGEN_H ================================================ FILE: src/metagen/metagen_base/metagen_base_arena.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Arena Functions //- rjf: arena creation/destruction internal Arena * arena_alloc_(ArenaParams *params) { // rjf: round up reserve/commit sizes U64 reserve_size = params->reserve_size; U64 commit_size = params->commit_size; if(params->flags & ArenaFlag_LargePages) { reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size); } else { reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size); commit_size = AlignPow2(commit_size, os_get_system_info()->page_size); } // rjf: reserve/commit initial block void *base = params->optional_backing_buffer; if(base == 0) { if(params->flags & ArenaFlag_LargePages) { base = os_reserve_large(reserve_size); os_commit_large(base, commit_size); } else { base = os_reserve(reserve_size); os_commit(base, commit_size); } } // rjf: panic on arena creation failure #if OS_FEATURE_GRAPHICAL if(Unlikely(base == 0)) { os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_abort(1); } #endif // rjf: extract arena header & fill Arena *arena = (Arena *)base; arena->current = arena; arena->flags = params->flags; arena->cmt_size = params->commit_size; arena->res_size = params->reserve_size; arena->base_pos = 0; arena->pos = ARENA_HEADER_SIZE; arena->cmt = commit_size; arena->res = reserve_size; #if ARENA_FREE_LIST arena->free_size = 0; arena->free_last = 0; #endif AsanPoisonMemoryRegion(base, commit_size); AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE); return arena; } internal void arena_release(Arena *arena) { for(Arena *n = arena->current, *prev = 0; n != 0; n = prev) { prev = n->prev; os_release(n, n->res); } } //- rjf: arena push/pop core functions internal void * arena_push(Arena *arena, U64 size, U64 align) { Arena *current = arena->current; U64 pos_pre = AlignPow2(current->pos, align); U64 pos_pst = pos_pre + size; // rjf: chain, if needed if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain)) { Arena *new_block = 0; #if ARENA_FREE_LIST Arena *prev_block; for(new_block = arena->free_last, prev_block = 0; new_block != 0; prev_block = new_block, new_block = new_block->prev) { if(new_block->res >= AlignPow2(size, align)) { if(prev_block) { prev_block->prev = new_block->prev; } else { arena->free_last = new_block->prev; } arena->free_size -= new_block->res_size; AsanUnpoisonMemoryRegion((U8*)new_block + ARENA_HEADER_SIZE, new_block->res_size - ARENA_HEADER_SIZE); break; } } #endif if(new_block == 0) { U64 res_size = current->res_size; U64 cmt_size = current->cmt_size; if(size + ARENA_HEADER_SIZE > res_size) { res_size = AlignPow2(size + ARENA_HEADER_SIZE, align); cmt_size = AlignPow2(size + ARENA_HEADER_SIZE, align); } new_block = arena_alloc(.reserve_size = res_size, .commit_size = cmt_size, .flags = current->flags); } new_block->base_pos = current->base_pos + current->res; SLLStackPush_N(arena->current, new_block, prev); current = new_block; pos_pre = AlignPow2(current->pos, align); pos_pst = pos_pre + size; } // rjf: commit new pages, if needed if(current->cmt < pos_pst) { U64 cmt_pst_aligned = pos_pst + current->cmt_size-1; cmt_pst_aligned -= cmt_pst_aligned%current->cmt_size; U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res); U64 cmt_size = cmt_pst_clamped - current->cmt; U8 *cmt_ptr = (U8 *)current + current->cmt; if(current->flags & ArenaFlag_LargePages) { os_commit_large(cmt_ptr, cmt_size); } else { os_commit(cmt_ptr, cmt_size); } current->cmt = cmt_pst_clamped; } // rjf: push onto current block void *result = 0; if(current->cmt >= pos_pst) { result = (U8 *)current+pos_pre; current->pos = pos_pst; AsanUnpoisonMemoryRegion(result, size); } // rjf: panic on failure #if OS_FEATURE_GRAPHICAL if(Unlikely(result == 0)) { os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_abort(1); } #endif return result; } internal U64 arena_pos(Arena *arena) { Arena *current = arena->current; U64 pos = current->base_pos + current->pos; return pos; } internal void arena_pop_to(Arena *arena, U64 pos) { U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos); Arena *current = arena->current; #if ARENA_FREE_LIST for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; current->pos = ARENA_HEADER_SIZE; arena->free_size += current->res_size; SLLStackPush_N(arena->free_last, current, prev); AsanPoisonMemoryRegion((U8*)current + ARENA_HEADER_SIZE, current->res_size - ARENA_HEADER_SIZE); } #else for(Arena *prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; os_release(current, current->res); } #endif arena->current = current; U64 new_pos = big_pos - current->base_pos; AssertAlways(new_pos <= current->pos); AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos)); current->pos = new_pos; } //- rjf: arena push/pop helpers internal void arena_clear(Arena *arena) { arena_pop_to(arena, 0); } internal void arena_pop(Arena *arena, U64 amt) { U64 pos_old = arena_pos(arena); U64 pos_new = pos_old; if(amt < pos_old) { pos_new = pos_old - amt; } arena_pop_to(arena, pos_new); } //- rjf: temporary arena scopes internal Temp temp_begin(Arena *arena) { U64 pos = arena_pos(arena); Temp temp = {arena, pos}; return temp; } internal void temp_end(Temp temp) { arena_pop_to(temp.arena, temp.pos); } ================================================ FILE: src/metagen/metagen_base/metagen_base_arena.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ARENA_H #define BASE_ARENA_H //////////////////////////////// //~ rjf: Constants #define ARENA_HEADER_SIZE 128 //////////////////////////////// //~ rjf: Types typedef U64 ArenaFlags; enum { ArenaFlag_NoChain = (1<<0), ArenaFlag_LargePages = (1<<1), }; typedef struct ArenaParams ArenaParams; struct ArenaParams { ArenaFlags flags; U64 reserve_size; U64 commit_size; void *optional_backing_buffer; }; typedef struct Arena Arena; struct Arena { Arena *prev; // previous arena in chain Arena *current; // current arena in chain ArenaFlags flags; U64 cmt_size; U64 res_size; U64 base_pos; U64 pos; U64 cmt; U64 res; #if ARENA_FREE_LIST U64 free_size; Arena *free_last; #endif }; StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check); typedef struct Temp Temp; struct Temp { Arena *arena; U64 pos; }; //////////////////////////////// //~ rjf: Global Defaults global U64 arena_default_reserve_size = MB(64); global U64 arena_default_commit_size = KB(64); global ArenaFlags arena_default_flags = 0; //////////////////////////////// //~ rjf: Arena Functions //- rjf: arena creation/destruction internal Arena *arena_alloc_(ArenaParams *params); #define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, __VA_ARGS__}) internal void arena_release(Arena *arena); //- rjf: arena push/pop/pos core functions internal void *arena_push(Arena *arena, U64 size, U64 align); internal U64 arena_pos(Arena *arena); internal void arena_pop_to(Arena *arena, U64 pos); //- rjf: arena push/pop helpers internal void arena_clear(Arena *arena); internal void arena_pop(Arena *arena, U64 amt); //- rjf: temporary arena scopes internal Temp temp_begin(Arena *arena); internal void temp_end(Temp temp); //- rjf: push helper macros #define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align)) #define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c)) #define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T))) #define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T))) #endif // BASE_ARENA_H ================================================ FILE: src/metagen/metagen_base/metagen_base_command_line.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ NOTE(rjf): Command Line Option Parsing internal U64 cmd_line_hash_from_string(String8 string) { U64 result = 5381; for(U64 i = 0; i < string.size; i += 1) { result = ((result << 5) + result) + string.str[i]; } return result; } internal CmdLineOpt ** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string) { CmdLineOpt **slot = 0; if(cmd_line->option_table_size != 0) { U64 hash = cmd_line_hash_from_string(string); U64 bucket = hash % cmd_line->option_table_size; slot = &cmd_line->option_table[bucket]; } return slot; } internal CmdLineOpt * cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string) { CmdLineOpt *result = 0; for(CmdLineOpt *var = *slot; var; var = var->hash_next) { if(str8_match(string, var->string, 0)) { result = var; break; } } return result; } internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var) { SLLQueuePush(list->first, list->last, var); list->count += 1; } internal CmdLineOpt * cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values) { CmdLineOpt *var = 0; CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string); CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string); if(existing_var != 0) { var = existing_var; } else { var = push_array(arena, CmdLineOpt, 1); var->hash_next = *slot; var->hash = cmd_line_hash_from_string(string); var->string = push_str8_copy(arena, string); var->value_strings = values; StringJoin join = {0}; join.pre = str8_lit(""); join.sep = str8_lit(","); join.post = str8_lit(""); var->value_string = str8_list_join(arena, &var->value_strings, &join); *slot = var; cmd_line_push_opt(&cmd_line->options, var); } return var; } internal CmdLine cmd_line_from_string_list(Arena *arena, String8List command_line) { CmdLine parsed = {0}; parsed.exe_name = command_line.first->string; // NOTE(rjf): Set up config option table. { parsed.option_table_size = 4096; parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size); } // NOTE(rjf): Parse command line. B32 after_passthrough_option = 0; B32 first_passthrough = 1; for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next) { next = node->next; String8 option_name = node->string; // NOTE(rjf): Look at --, -, or / (only on Windows) at the start of an // argument to determine if it's a flag option. All arguments after a // single "--" (with no trailing string on the command line will be // considered as input files. B32 is_option = 1; if(after_passthrough_option == 0) { if(str8_match(node->string, str8_lit("--"), 0)) { after_passthrough_option = 1; is_option = 0; } else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0)) { option_name = str8_skip(option_name, 2); } else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0)) { option_name = str8_skip(option_name, 1); } else if(operating_system_from_context() == OperatingSystem_Windows && str8_match(str8_prefix(node->string, 1), str8_lit("/"), 0)) { option_name = str8_skip(option_name, 1); } else { is_option = 0; } } else { is_option = 0; } // NOTE(rjf): This string is an option. if(is_option) { B32 has_arguments = 0; U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0); U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0); U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2); String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1); if(arg_signifier_position < option_name.size) { has_arguments = 1; } option_name = str8_prefix(option_name, arg_signifier_position); String8List arguments = {0}; // NOTE(rjf): Parse arguments. if(has_arguments) { for(String8Node *n = node; n; n = n->next) { next = n->next; String8 string = n->string; if(n == node) { string = arg_portion_this_string; } U8 splits[] = { ',' }; String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0); for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next) { str8_list_push(arena, &arguments, sub_arg->string); } if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) && (n != node || arg_portion_this_string.size != 0)) { break; } } } // NOTE(rjf): Register config variable. cmd_line_insert_opt(arena, &parsed, option_name, arguments); } // NOTE(rjf): Default path, treat as a passthrough config option to be // handled by tool-specific code. else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough) { str8_list_push(arena, &parsed.inputs, node->string); after_passthrough_option = 1; first_passthrough = 0; } } // rjf: fill argc/argv parsed.argc = command_line.node_count; parsed.argv = push_array(arena, char *, parsed.argc); { U64 idx = 0; for(String8Node *n = command_line.first; n != 0; n = n->next) { parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str; idx += 1; } } return parsed; } internal CmdLineOpt * cmd_line_opt_from_string(CmdLine *cmd_line, String8 name) { return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name); } internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name) { String8List result = {0}; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); if(var != 0) { result = var->value_strings; } return result; } internal String8 cmd_line_string(CmdLine *cmd_line, String8 name) { String8 result = {0}; CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); if(var != 0) { result = var->value_string; } return result; } internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); return(var != 0); } internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); return(var != 0 && var->value_strings.node_count > 0); } ================================================ FILE: src/metagen/metagen_base/metagen_base_command_line.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_COMMAND_LINE_H #define BASE_COMMAND_LINE_H //////////////////////////////// //~ rjf: Parsed Command Line Types typedef struct CmdLineOpt CmdLineOpt; struct CmdLineOpt { CmdLineOpt *next; CmdLineOpt *hash_next; U64 hash; String8 string; String8List value_strings; String8 value_string; }; typedef struct CmdLineOptList CmdLineOptList; struct CmdLineOptList { U64 count; CmdLineOpt *first; CmdLineOpt *last; }; typedef struct CmdLine CmdLine; struct CmdLine { String8 exe_name; CmdLineOptList options; String8List inputs; U64 option_table_size; CmdLineOpt **option_table; U64 argc; char **argv; }; //////////////////////////////// //~ NOTE(rjf): Command Line Option Parsing internal U64 cmd_line_hash_from_string(String8 string); internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string); internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string); internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var); internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values); internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments); internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name); internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name); internal String8 cmd_line_string(CmdLine *cmd_line, String8 name); internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name); internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name); #endif // BASE_COMMAND_LINE_H ================================================ FILE: src/metagen/metagen_base/metagen_base_context_cracking.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CONTEXT_CRACKING_H #define BASE_CONTEXT_CRACKING_H //////////////////////////////// //~ rjf: Clang OS/Arch Cracking #if defined(__clang__) # define COMPILER_CLANG 1 # if defined(_WIN32) # define OS_WINDOWS 1 # elif defined(__gnu_linux__) || defined(__linux__) # define OS_LINUX 1 # elif defined(__APPLE__) && defined(__MACH__) # define OS_MAC 1 # else # error This compiler/OS combo is not supported. # endif # if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # define ARCH_X64 1 # elif defined(i386) || defined(__i386) || defined(__i386__) # define ARCH_X86 1 # elif defined(__aarch64__) # define ARCH_ARM64 1 # elif defined(__arm__) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif //////////////////////////////// //~ rjf: MSVC OS/Arch Cracking #elif defined(_MSC_VER) # define COMPILER_MSVC 1 # if _MSC_VER >= 1920 # define COMPILER_MSVC_YEAR 2019 # elif _MSC_VER >= 1910 # define COMPILER_MSVC_YEAR 2017 # elif _MSC_VER >= 1900 # define COMPILER_MSVC_YEAR 2015 # elif _MSC_VER >= 1800 # define COMPILER_MSVC_YEAR 2013 # elif _MSC_VER >= 1700 # define COMPILER_MSVC_YEAR 2012 # elif _MSC_VER >= 1600 # define COMPILER_MSVC_YEAR 2010 # elif _MSC_VER >= 1500 # define COMPILER_MSVC_YEAR 2008 # elif _MSC_VER >= 1400 # define COMPILER_MSVC_YEAR 2005 # else # define COMPILER_MSVC_YEAR 0 # endif # if defined(_WIN32) # define OS_WINDOWS 1 # else # error This compiler/OS combo is not supported. # endif # if defined(_M_AMD64) # define ARCH_X64 1 # elif defined(_M_IX86) # define ARCH_X86 1 # elif defined(_M_ARM64) # define ARCH_ARM64 1 # elif defined(_M_ARM) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif //////////////////////////////// //~ rjf: GCC OS/Arch Cracking #elif defined(__GNUC__) || defined(__GNUG__) # define COMPILER_GCC 1 # if defined(__gnu_linux__) || defined(__linux__) # define OS_LINUX 1 # else # error This compiler/OS combo is not supported. # endif # if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) # define ARCH_X64 1 # elif defined(i386) || defined(__i386) || defined(__i386__) # define ARCH_X86 1 # elif defined(__aarch64__) # define ARCH_ARM64 1 # elif defined(__arm__) # define ARCH_ARM32 1 # else # error Architecture not supported. # endif #else # error Compiler not supported. #endif //////////////////////////////// //~ rjf: Arch Cracking #if defined(ARCH_X64) # define ARCH_64BIT 1 #elif defined(ARCH_X86) # define ARCH_32BIT 1 #endif #if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86 # define ARCH_LITTLE_ENDIAN 1 #else # error Endianness of this architecture not understood by context cracker. #endif //////////////////////////////// //~ rjf: Language Cracking #if defined(__cplusplus) # define LANG_CPP 1 #else # define LANG_C 1 #endif //////////////////////////////// //~ rjf: Build Option Cracking #if !defined(BUILD_DEBUG) # define BUILD_DEBUG 1 #endif #if !defined(BUILD_SUPPLEMENTARY_UNIT) # define BUILD_SUPPLEMENTARY_UNIT 0 #endif #if !defined(BUILD_ENTRY_DEFINING_UNIT) # define BUILD_ENTRY_DEFINING_UNIT 1 #endif #if !defined(BUILD_CONSOLE_INTERFACE) # define BUILD_CONSOLE_INTERFACE 0 #endif #if !defined(BUILD_VERSION_MAJOR) # define BUILD_VERSION_MAJOR 0 #endif #if !defined(BUILD_VERSION_MINOR) # define BUILD_VERSION_MINOR 9 #endif #if !defined(BUILD_VERSION_PATCH) # define BUILD_VERSION_PATCH 14 #endif #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) #if BUILD_DEBUG # define BUILD_MODE_STRING_LITERAL_APPEND " [Debug]" #else # define BUILD_MODE_STRING_LITERAL_APPEND "" #endif #if defined(BUILD_GIT_HASH) # define BUILD_GIT_HASH_STRING_LITERAL_APPEND " [" BUILD_GIT_HASH "]" #else # define BUILD_GIT_HASH_STRING_LITERAL_APPEND "" #endif #if !defined(BUILD_TITLE) # define BUILD_TITLE "Untitled" #endif #if !defined(BUILD_RELEASE_PHASE_STRING_LITERAL) # define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" #endif #if !defined(BUILD_ISSUES_LINK_STRING_LITERAL) # define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGamesExt/raddebugger/issues" #endif #define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND //////////////////////////////// //~ rjf: Zero All Undefined Options #if !defined(ARCH_32BIT) # define ARCH_32BIT 0 #endif #if !defined(ARCH_64BIT) # define ARCH_64BIT 0 #endif #if !defined(ARCH_X64) # define ARCH_X64 0 #endif #if !defined(ARCH_X86) # define ARCH_X86 0 #endif #if !defined(ARCH_ARM64) # define ARCH_ARM64 0 #endif #if !defined(ARCH_ARM32) # define ARCH_ARM32 0 #endif #if !defined(COMPILER_MSVC) # define COMPILER_MSVC 0 #endif #if !defined(COMPILER_GCC) # define COMPILER_GCC 0 #endif #if !defined(COMPILER_CLANG) # define COMPILER_CLANG 0 #endif #if !defined(OS_WINDOWS) # define OS_WINDOWS 0 #endif #if !defined(OS_LINUX) # define OS_LINUX 0 #endif #if !defined(OS_MAC) # define OS_MAC 0 #endif #if !defined(LANG_CPP) # define LANG_CPP 0 #endif #if !defined(LANG_C) # define LANG_C 0 #endif //////////////////////////////// //~ rjf: Unsupported Errors #if ARCH_X86 # error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported. #endif #if !ARCH_X64 # error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported. #endif #endif // BASE_CONTEXT_CRACKING_H ================================================ FILE: src/metagen/metagen_base/metagen_base_core.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Safe Casts internal U16 safe_cast_u16(U32 x) { AssertAlways(x <= max_U16); U16 result = (U16)x; return result; } internal U32 safe_cast_u32(U64 x) { AssertAlways(x <= max_U32); U32 result = (U32)x; return result; } internal S32 safe_cast_s32(S64 x) { AssertAlways(x <= max_S32); S32 result = (S32)x; return result; } //////////////////////////////// //~ rjf: Large Base Type Functions internal U128 u128_zero(void) { U128 v = {0}; return v; } internal U128 u128_make(U64 v0, U64 v1) { U128 v = {v0, v1}; return v; } internal B32 u128_match(U128 a, U128 b) { return MemoryMatchStruct(&a, &b); } //////////////////////////////// //~ rjf: Bit Patterns internal U32 u32_from_u64_saturate(U64 x){ U32 x32 = (x > max_U32)?max_U32:(U32)x; return(x32); } internal U64 u64_up_to_pow2(U64 x){ if (x == 0){ x = 1; } else{ x -= 1; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x |= (x >> 32); x += 1; } return(x); } internal S32 extend_sign32(U32 x, U32 size){ U32 high_bit = size * 8; U32 shift = 32 - high_bit; S32 result = ((S32)x << shift) >> shift; return result; } internal S64 extend_sign64(U64 x, U64 size){ U64 high_bit = size * 8; U64 shift = 64 - high_bit; S64 result = ((S64)x << shift) >> shift; return result; } internal F32 inf32(void){ union { U32 u; F32 f; } x; x.u = exponent32; return(x.f); } internal F32 neg_inf32(void){ union { U32 u; F32 f; } x; x.u = sign32 | exponent32; return(x.f); } internal U16 bswap_u16(U16 x) { U16 result = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)); return result; } internal U32 bswap_u32(U32 x) { U32 result = (((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24)); return result; } internal U64 bswap_u64(U64 x) { // TODO(nick): naive bswap, replace with something that is faster like an intrinsic U64 result = (((x & 0xFF00000000000000ULL) >> 56) | ((x & 0x00FF000000000000ULL) >> 40) | ((x & 0x0000FF0000000000ULL) >> 24) | ((x & 0x000000FF00000000ULL) >> 8) | ((x & 0x00000000FF000000ULL) << 8) | ((x & 0x0000000000FF0000ULL) << 24) | ((x & 0x000000000000FF00ULL) << 40) | ((x & 0x00000000000000FFULL) << 56)); return result; } #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) internal U64 count_bits_set32(U32 val) { return __popcnt(val); } internal U64 count_bits_set64(U64 val) { return __popcnt64(val); } internal U64 ctz32(U32 mask) { unsigned long idx; _BitScanForward(&idx, mask); return idx; } internal U64 ctz64(U64 mask) { unsigned long idx; _BitScanForward64(&idx, mask); return idx; } internal U64 clz32(U32 mask) { unsigned long idx; _BitScanReverse(&idx, mask); return 31 - idx; } internal U64 clz64(U64 mask) { unsigned long idx; _BitScanReverse64(&idx, mask); return 63 - idx; } #elif COMPILER_CLANG || COMPILER_GCC internal U64 count_bits_set32(U32 val) { return __builtin_popcount(val); } internal U64 count_bits_set64(U64 val) { return __builtin_popcountll(val); } internal U64 ctz32(U32 val) { return __builtin_ctz(val); } internal U64 clz32(U32 val) { return __builtin_clz(val); } internal U64 ctz64(U64 val) { return __builtin_ctzll(val); } internal U64 clz64(U64 val) { return __builtin_clzll(val); } #else # error "Bit intrinsic functions not defined for this compiler." #endif //////////////////////////////// //~ rjf: Enum -> Sign internal S32 sign_from_side_S32(Side side){ return((side == Side_Min)?-1:1); } internal F32 sign_from_side_F32(Side side){ return((side == Side_Min)?-1.f:1.f); } //////////////////////////////// //~ rjf: Memory Functions internal B32 memory_is_zero(void *ptr, U64 size){ B32 result = 1; // break down size U64 extra = (size&0x7); U64 count8 = (size >> 3); // check with 8-byte stride U64 *p64 = (U64*)ptr; if(result) { for (U64 i = 0; i < count8; i += 1, p64 += 1){ if (*p64 != 0){ result = 0; goto done; } } } // check extra if(result) { U8 *p8 = (U8*)p64; for (U64 i = 0; i < extra; i += 1, p8 += 1){ if (*p8 != 0){ result = 0; goto done; } } } done:; return(result); } //////////////////////////////// //~ rjf: Text 2D Coordinate/Range Functions internal TxtPt txt_pt(S64 line, S64 column) { TxtPt p = {0}; p.line = line; p.column = column; return p; } internal B32 txt_pt_match(TxtPt a, TxtPt b) { return a.line == b.line && a.column == b.column; } internal B32 txt_pt_less_than(TxtPt a, TxtPt b) { B32 result = 0; if(a.line < b.line) { result = 1; } else if(a.line == b.line) { result = a.column < b.column; } return result; } internal TxtPt txt_pt_min(TxtPt a, TxtPt b) { TxtPt result = b; if(txt_pt_less_than(a, b)) { result = a; } return result; } internal TxtPt txt_pt_max(TxtPt a, TxtPt b) { TxtPt result = a; if(txt_pt_less_than(a, b)) { result = b; } return result; } internal TxtRng txt_rng(TxtPt min, TxtPt max) { TxtRng range = {0}; if(txt_pt_less_than(min, max)) { range.min = min; range.max = max; } else { range.min = max; range.max = min; } return range; } internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b) { TxtRng result = {0}; result.min = txt_pt_max(a.min, b.min); result.max = txt_pt_min(a.max, b.max); if(txt_pt_less_than(result.max, result.min)) { MemoryZeroStruct(&result); } return result; } internal TxtRng txt_rng_union(TxtRng a, TxtRng b) { TxtRng result = {0}; result.min = txt_pt_min(a.min, b.min); result.max = txt_pt_max(a.max, b.max); return result; } internal B32 txt_rng_contains(TxtRng r, TxtPt pt) { B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) && txt_pt_less_than(pt, r.max)); return result; } //////////////////////////////// //~ rjf: Toolchain/Environment Enum Functions internal U64 bit_size_from_arch(Arch arch) { // TODO(rjf): metacode U64 arch_bitsize = 0; switch(arch) { case Arch_x64: arch_bitsize = 64; break; case Arch_x86: arch_bitsize = 32; break; case Arch_arm64: arch_bitsize = 64; break; case Arch_arm32: arch_bitsize = 32; break; default: break; } return arch_bitsize; } internal U64 max_instruction_size_from_arch(Arch arch) { // TODO(rjf): make this real return 64; } internal OperatingSystem operating_system_from_context(void){ OperatingSystem os = OperatingSystem_Null; #if OS_WINDOWS os = OperatingSystem_Windows; #elif OS_LINUX os = OperatingSystem_Linux; #elif OS_MAC os = OperatingSystem_Mac; #endif return os; } internal Arch arch_from_context(void){ Arch arch = Arch_Null; #if ARCH_X64 arch = Arch_x64; #elif ARCH_X86 arch = Arch_x86; #elif ARCH_ARM64 arch = Arch_arm64; #elif ARCH_ARM32 arch = Arch_arm32; #endif return arch; } internal Compiler compiler_from_context(void){ Compiler compiler = Compiler_Null; #if COMPILER_MSVC compiler = Compiler_msvc; #elif COMPILER_GCC compiler = Compiler_gcc; #elif COMPILER_CLANG compiler = Compiler_clang; #endif return compiler; } //////////////////////////////// //~ rjf: Time Functions internal DenseTime dense_time_from_date_time(DateTime date_time){ DenseTime result = 0; result += date_time.year; result *= 12; result += date_time.mon; result *= 31; result += date_time.day; result *= 24; result += date_time.hour; result *= 60; result += date_time.min; result *= 61; result += date_time.sec; result *= 1000; result += date_time.msec; return(result); } internal DateTime date_time_from_dense_time(DenseTime time){ DateTime result = {0}; result.msec = time%1000; time /= 1000; result.sec = time%61; time /= 61; result.min = time%60; time /= 60; result.hour = time%24; time /= 24; result.day = time%31; time /= 31; result.mon = time%12; time /= 12; Assert(time <= max_U32); result.year = (U32)time; return(result); } internal DateTime date_time_from_micro_seconds(U64 time){ DateTime result = {0}; result.micro_sec = time%1000; time /= 1000; result.msec = time%1000; time /= 1000; result.sec = time%60; time /= 60; result.min = time%60; time /= 60; result.hour = time%24; time /= 24; result.day = time%31; time /= 31; result.mon = time%12; time /= 12; Assert(time <= max_U32); result.year = (U32)time; return(result); } internal DateTime date_time_from_unix_time(U64 unix_time) { DateTime date = {0}; date.year = 1970; date.day = 1 + (unix_time / 86400); date.sec = (U32)unix_time % 60; date.min = (U32)(unix_time / 60) % 60; date.hour = (U32)(unix_time / 3600) % 24; for(;;) { for(date.month = 0; date.month < 12; ++date.month) { U64 c = 0; switch(date.month) { case Month_Jan: c = 31; break; case Month_Feb: { if((date.year % 4 == 0) && ((date.year % 100) != 0 || (date.year % 400) == 0)) { c = 29; } else { c = 28; } } break; case Month_Mar: c = 31; break; case Month_Apr: c = 30; break; case Month_May: c = 31; break; case Month_Jun: c = 30; break; case Month_Jul: c = 31; break; case Month_Aug: c = 31; break; case Month_Sep: c = 30; break; case Month_Oct: c = 31; break; case Month_Nov: c = 30; break; case Month_Dec: c = 31; break; default: InvalidPath; } if(date.day <= c) { goto exit; } date.day -= c; } ++date.year; } exit:; return date; } //////////////////////////////// //~ rjf: Non-Fancy Ring Buffer Reads/Writes internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size) { Assert(src_data_size <= ring_size); { U64 ring_off = ring_pos%ring_size; U64 bytes_before_split = ring_size-ring_off; U64 pre_split_bytes = Min(bytes_before_split, src_data_size); U64 pst_split_bytes = src_data_size-pre_split_bytes; void *pre_split_data = src_data; void *pst_split_data = ((U8 *)src_data + pre_split_bytes); MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes); MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes); } return src_data_size; } internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size) { Assert(read_size <= ring_size); { U64 ring_off = ring_pos%ring_size; U64 bytes_before_split = ring_size-ring_off; U64 pre_split_bytes = Min(bytes_before_split, read_size); U64 pst_split_bytes = read_size-pre_split_bytes; MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes); MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes); } return read_size; } ================================================ FILE: src/metagen/metagen_base/metagen_base_core.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CORE_H #define BASE_CORE_H //////////////////////////////// //~ rjf: Foreign Includes #include #include #include #include #include //////////////////////////////// //~ rjf: Codebase Keywords #define internal static #define global static #define local_persist static #if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS) # pragma section(".rdata$", read) # define read_only __declspec(allocate(".rdata$")) #elif (COMPILER_CLANG && OS_LINUX) # define read_only __attribute__((section(".rodata"))) #else // NOTE(rjf): I don't know of a useful way to do this in GCC land. // __attribute__((section(".rodata"))) looked promising, but it introduces a // strange warning about malformed section attributes, and it doesn't look // like writing to that section reliably produces access violations, strangely // enough. (It does on Clang) # define read_only #endif #if COMPILER_MSVC # define thread_static __declspec(thread) #elif COMPILER_CLANG || COMPILER_GCC # define thread_static __thread #endif #if COMPILER_MSVC # define force_inline __forceinline #elif COMPILER_CLANG || COMPILER_GCC # define force_inline __attribute__((always_inline)) #endif //////////////////////////////// //~ rjf: Linkage Keyword Macros #if OS_WINDOWS # define shared_function C_LINKAGE __declspec(dllexport) #else # define shared_function C_LINKAGE #endif #if LANG_CPP # define C_LINKAGE_BEGIN extern "C"{ # define C_LINKAGE_END } # define C_LINKAGE extern "C" #else # define C_LINKAGE_BEGIN # define C_LINKAGE_END # define C_LINKAGE #endif //////////////////////////////// //~ rjf: Units #define KB(n) (((U64)(n)) << 10) #define MB(n) (((U64)(n)) << 20) #define GB(n) (((U64)(n)) << 30) #define TB(n) (((U64)(n)) << 40) #define Thousand(n) ((n)*1000) #define Million(n) ((n)*1000000) #define Billion(n) ((n)*1000000000) //////////////////////////////// //~ rjf: Branch Predictor Hints #if defined(__clang__) # define Expect(expr, val) __builtin_expect((expr), (val)) #else # define Expect(expr, val) (expr) #endif #define Likely(expr) Expect(expr,1) #define Unlikely(expr) Expect(expr,0) //////////////////////////////// //~ rjf: Clamps, Mins, Maxes #define Min(A,B) (((A)<(B))?(A):(B)) #define Max(A,B) (((A)>(B))?(A):(B)) #define ClampTop(A,X) Min(A,X) #define ClampBot(X,B) Max(X,B) #define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X)) //////////////////////////////// //~ rjf: Type -> Alignment #if COMPILER_MSVC # define AlignOf(T) __alignof(T) #elif COMPILER_CLANG # define AlignOf(T) __alignof(T) #elif COMPILER_GCC # define AlignOf(T) __alignof__(T) #else # error AlignOf not defined for this compiler. #endif //////////////////////////////// //~ rjf: Member Offsets #define Member(T,m) (((T*)0)->m) #define OffsetOf(T,m) IntFromPtr(&Member(T,m)) #define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off))) #define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m)) //////////////////////////////// //~ rjf: For-Loop Construct Macros #define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) #define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end)) #define EachIndex(it, count) (U64 it = 0; it < (count); it += 1) #define EachElement(it, array) (U64 it = 0; it < ArrayCount(array); it += 1) #define EachEnumVal(type, it) (type it = (type)0; it < type##_COUNT; it = (type)(it+1)) #define EachNonZeroEnumVal(type, it) (type it = (type)1; it < type##_COUNT; it = (type)(it+1)) //////////////////////////////// //~ rjf: Memory Operation Macros #define MemoryCopy(dst, src, size) memmove((dst), (src), (size)) #define MemorySet(dst, byte, size) memset((dst), (byte), (size)) #define MemoryCompare(a, b, size) memcmp((a), (b), (size)) #define MemoryStrlen(ptr) strlen(ptr) #define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d))) #define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d)) #define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c)) #define MemoryZero(s,z) memset((s),0,(z)) #define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s))) #define MemoryZeroArray(a) MemoryZero((a),sizeof(a)) #define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c)) #define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0) #define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a))) #define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a)) #define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) ) #define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) ) //////////////////////////////// //~ rjf: Asserts #if COMPILER_MSVC # define Trap() __debugbreak() #elif COMPILER_CLANG || COMPILER_GCC # define Trap() __builtin_trap() #else # error Unknown trap intrinsic for this compiler. #endif #define AssertAlways(x) do{if(!(x)) {Trap();}}while(0) #if BUILD_DEBUG # define Assert(x) AssertAlways(x) #else # define Assert(x) (void)(x) #endif #define InvalidPath Assert(!"Invalid Path!") #define NotImplemented Assert(!"Not Implemented!") #define NoOp ((void)0) #define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1] //////////////////////////////// //~ rjf: Atomic Operations #if COMPILER_MSVC # include # if ARCH_X64 # define ins_atomic_u64_eval(x) *((volatile U64 *)(x)) # define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x)) # define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x)) # define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c)) # define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c) # define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c)) # define ins_atomic_u32_eval(x) *((volatile U32 *)(x)) # define ins_atomic_u32_inc_eval(x) InterlockedIncrement((volatile LONG *)x) # define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c)) # define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c)) # define ins_atomic_u32_add_eval(x,c) InterlockedAdd((volatile LONG *)(x), c) # else # error Atomic intrinsics not defined for this compiler / architecture combination. # endif #elif COMPILER_CLANG || COMPILER_GCC # define ins_atomic_u64_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) # define ins_atomic_u64_inc_eval(x) (__atomic_fetch_add((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) + 1) # define ins_atomic_u64_dec_eval(x) (__atomic_fetch_sub((volatile U64 *)(x), 1, __ATOMIC_SEQ_CST) - 1) # define ins_atomic_u64_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST) # define ins_atomic_u64_add_eval(x,c) (__atomic_fetch_add((volatile U64 *)(x), c, __ATOMIC_SEQ_CST) + (c)) # define ins_atomic_u64_eval_cond_assign(x,k,c) ({ U64 _new = (c); __atomic_compare_exchange_n((volatile U64 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) # define ins_atomic_u32_eval(x) __atomic_load_n(x, __ATOMIC_SEQ_CST) # define ins_atomic_u32_inc_eval(x) (__atomic_fetch_add((volatile U32 *)(x), 1, __ATOMIC_SEQ_CST) + 1) # define ins_atomic_u32_add_eval(x,c) (__atomic_fetch_add((volatile U32 *)(x), c, __ATOMIC_SEQ_CST) + (c)) # define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n(x, c, __ATOMIC_SEQ_CST) # define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((volatile U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; }) #else # error Atomic intrinsics not defined for this compiler / architecture. #endif #if ARCH_64BIT # define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u64_eval_cond_assign((volatile U64 *)(x), (U64)(k), (U64)(c)) # define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile U64 *)(x), (U64)(c)) # define ins_atomic_ptr_eval(x) (void*)ins_atomic_u64_eval((volatile U64 *)x) #elif ARCH_32BIT # define ins_atomic_ptr_eval_cond_assign(x,k,c) (void*)ins_atomic_u32_eval_cond_assign((volatile U32 *)(x), (U32)(k), (U32)(c)) # define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u32_eval_assign((volatile U32 *)(x), (U32)(c)) # define ins_atomic_ptr_eval(x) (void*)ins_atomic_u32_eval((volatile U32 *)x) #else # error Atomic intrinsics for pointers not defined for this architecture. #endif //////////////////////////////// //~ rjf: Linked List Building Macros //- rjf: linked list macro helpers #define CheckNil(nil,p) ((p) == 0 || (p) == nil) #define SetNil(nil,p) ((p) = nil) //- rjf: doubly-linked-lists #define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \ ((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\ CheckNil(nil,p) ? \ ((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\ ((p)==(l)) ? \ ((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\ (((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p)))) #define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev) #define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next) #define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\ ((n) == (l) ? (l) = (l)->prev : (0)),\ (CheckNil(nil,(n)->prev) ? (0) :\ ((n)->prev->next = (n)->next)),\ (CheckNil(nil,(n)->next) ? (0) :\ ((n)->next->prev = (n)->prev))) //- rjf: singly-linked, doubly-headed lists (queues) #define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ ((f)=(l)=(n),SetNil(nil,(n)->next)):\ ((l)->next=(n),(l)=(n),SetNil(nil,(n)->next))) #define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ ((f)=(l)=(n),SetNil(nil,(n)->next)):\ ((n)->next=(f),(f)=(n))) #define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ (SetNil(nil,f),SetNil(nil,l)):\ ((f)=(f)->next)) //- rjf: singly-linked, singly-headed lists (stacks) #define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n)) #define SLLStackPop_N(f,next) ((f)=(f)->next) //- rjf: doubly-linked-list helpers #define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev) #define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev) #define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev) #define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev) #define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev) #define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev) #define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev) #define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev) //- rjf: singly-linked, doubly-headed list helpers #define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next) #define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next) #define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next) #define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next) //- rjf: singly-linked, singly-headed list helpers #define SLLStackPush(f,n) SLLStackPush_N(f,n,next) #define SLLStackPop(f) SLLStackPop_N(f,next) //////////////////////////////// //~ rjf: Address Sanitizer Markup #if COMPILER_MSVC # if defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # define NO_ASAN __declspec(no_sanitize_address) # else # define NO_ASAN # endif #elif COMPILER_CLANG # if defined(__has_feature) # if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # endif # endif # define NO_ASAN __attribute__((no_sanitize("address"))) #else # define NO_ASAN #endif #if ASAN_ENABLED #pragma comment(lib, "clang_rt.asan-x86_64.lib") C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size); C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size); # define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size)) # define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size)) #else # define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) # define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) #endif //////////////////////////////// //~ rjf: Misc. Helper Macros #define Stringify_(S) #S #define Stringify(S) Stringify_(S) #define Glue_(A,B) A##B #define Glue(A,B) Glue_(A,B) #define ArrayCount(a) (sizeof(a) / sizeof((a)[0])) #define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b)) #define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0) #if ARCH_64BIT # define IntFromPtr(ptr) ((U64)(ptr)) #elif ARCH_32BIT # define IntFromPtr(ptr) ((U32)(ptr)) #else # error Missing pointer-to-integer cast for this architecture. #endif #define PtrFromInt(i) (void*)((U8*)0 + (i)) #define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)); #define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) #define AlignDownPow2(x,b) ((x)&(~((b) - 1))) #define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1)) #define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0) #define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0) #define ExtractBit(word, idx) (((word) >> (idx)) & 1) #if LANG_CPP # define zero_struct {} #else # define zero_struct {0} #endif #if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015 # define this_function_name "unknown" #else # define this_function_name __func__ #endif //////////////////////////////// //~ rjf: Base Types typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; typedef float F32; typedef double F64; typedef void VoidProc(void); typedef struct U128 U128; struct U128 { U64 u64[2]; }; //////////////////////////////// //~ rjf: Basic Types & Spaces typedef enum Dimension { Dimension_X, Dimension_Y, Dimension_Z, Dimension_W, } Dimension; typedef enum Side { Side_Invalid = -1, Side_Min, Side_Max, Side_COUNT, } Side; #define side_flip(s) ((Side)(!(s))) typedef enum Axis2 { Axis2_Invalid = -1, Axis2_X, Axis2_Y, Axis2_COUNT, } Axis2; #define axis2_flip(a) ((Axis2)(!(a))) typedef enum Corner { Corner_Invalid = -1, Corner_00, Corner_01, Corner_10, Corner_11, Corner_COUNT } Corner; typedef enum Dir2 { Dir2_Invalid = -1, Dir2_Left, Dir2_Up, Dir2_Right, Dir2_Down, Dir2_COUNT } Dir2; #define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X) #define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) //////////////////////////////// //~ rjf: Toolchain/Environment Enums typedef enum OperatingSystem { OperatingSystem_Null, OperatingSystem_Windows, OperatingSystem_Linux, OperatingSystem_Mac, OperatingSystem_COUNT, } OperatingSystem; typedef enum ImageType { Image_Null, Image_CoffPe, Image_Elf32, Image_Elf64, Image_Macho } ImageType; typedef enum Arch { Arch_Null, Arch_x64, Arch_x86, Arch_arm64, Arch_arm32, Arch_COUNT, } Arch; typedef enum Compiler { Compiler_Null, Compiler_msvc, Compiler_gcc, Compiler_clang, Compiler_COUNT, } Compiler; //////////////////////////////// //~ rjf: Text 2D Coordinates & Ranges typedef struct TxtPt TxtPt; struct TxtPt { S64 line; S64 column; }; typedef struct TxtRng TxtRng; struct TxtRng { TxtPt min; TxtPt max; }; //////////////////////////////// //~ Globally Unique Ids typedef union Guid Guid; union Guid { struct { U32 data1; U16 data2; U16 data3; U8 data4[8]; }; U8 v[16]; }; StaticAssert(sizeof(Guid) == 16, g_guid_size_check); //////////////////////////////// //~ Arrays typedef struct U16Array U16Array; struct U16Array { U64 count; U16 *v; }; typedef struct U32Array U32Array; struct U32Array { U64 count; U32 *v; }; typedef struct U64Array U64Array; struct U64Array { U64 count; U64 *v; }; typedef struct U128Array U128Array; struct U128Array { U64 count; U128 *v; }; //////////////////////////////// //~ NOTE(allen): Constants global U32 sign32 = 0x80000000; global U32 exponent32 = 0x7F800000; global U32 mantissa32 = 0x007FFFFF; global F32 big_golden32 = 1.61803398875f; global F32 small_golden32 = 0.61803398875f; global F32 pi32 = 3.1415926535897f; global F64 machine_epsilon64 = 4.94065645841247e-324; global U64 max_U64 = 0xffffffffffffffffull; global U32 max_U32 = 0xffffffff; global U16 max_U16 = 0xffff; global U8 max_U8 = 0xff; global S64 max_S64 = (S64)0x7fffffffffffffffull; global S32 max_S32 = (S32)0x7fffffff; global S16 max_S16 = (S16)0x7fff; global S8 max_S8 = (S8)0x7f; global S64 min_S64 = (S64)0xffffffffffffffffull; global S32 min_S32 = (S32)0xffffffff; global S16 min_S16 = (S16)0xffff; global S8 min_S8 = (S8)0xff; global const U32 bitmask1 = 0x00000001; global const U32 bitmask2 = 0x00000003; global const U32 bitmask3 = 0x00000007; global const U32 bitmask4 = 0x0000000f; global const U32 bitmask5 = 0x0000001f; global const U32 bitmask6 = 0x0000003f; global const U32 bitmask7 = 0x0000007f; global const U32 bitmask8 = 0x000000ff; global const U32 bitmask9 = 0x000001ff; global const U32 bitmask10 = 0x000003ff; global const U32 bitmask11 = 0x000007ff; global const U32 bitmask12 = 0x00000fff; global const U32 bitmask13 = 0x00001fff; global const U32 bitmask14 = 0x00003fff; global const U32 bitmask15 = 0x00007fff; global const U32 bitmask16 = 0x0000ffff; global const U32 bitmask17 = 0x0001ffff; global const U32 bitmask18 = 0x0003ffff; global const U32 bitmask19 = 0x0007ffff; global const U32 bitmask20 = 0x000fffff; global const U32 bitmask21 = 0x001fffff; global const U32 bitmask22 = 0x003fffff; global const U32 bitmask23 = 0x007fffff; global const U32 bitmask24 = 0x00ffffff; global const U32 bitmask25 = 0x01ffffff; global const U32 bitmask26 = 0x03ffffff; global const U32 bitmask27 = 0x07ffffff; global const U32 bitmask28 = 0x0fffffff; global const U32 bitmask29 = 0x1fffffff; global const U32 bitmask30 = 0x3fffffff; global const U32 bitmask31 = 0x7fffffff; global const U32 bitmask32 = 0xffffffff; global const U64 bitmask33 = 0x00000001ffffffffull; global const U64 bitmask34 = 0x00000003ffffffffull; global const U64 bitmask35 = 0x00000007ffffffffull; global const U64 bitmask36 = 0x0000000fffffffffull; global const U64 bitmask37 = 0x0000001fffffffffull; global const U64 bitmask38 = 0x0000003fffffffffull; global const U64 bitmask39 = 0x0000007fffffffffull; global const U64 bitmask40 = 0x000000ffffffffffull; global const U64 bitmask41 = 0x000001ffffffffffull; global const U64 bitmask42 = 0x000003ffffffffffull; global const U64 bitmask43 = 0x000007ffffffffffull; global const U64 bitmask44 = 0x00000fffffffffffull; global const U64 bitmask45 = 0x00001fffffffffffull; global const U64 bitmask46 = 0x00003fffffffffffull; global const U64 bitmask47 = 0x00007fffffffffffull; global const U64 bitmask48 = 0x0000ffffffffffffull; global const U64 bitmask49 = 0x0001ffffffffffffull; global const U64 bitmask50 = 0x0003ffffffffffffull; global const U64 bitmask51 = 0x0007ffffffffffffull; global const U64 bitmask52 = 0x000fffffffffffffull; global const U64 bitmask53 = 0x001fffffffffffffull; global const U64 bitmask54 = 0x003fffffffffffffull; global const U64 bitmask55 = 0x007fffffffffffffull; global const U64 bitmask56 = 0x00ffffffffffffffull; global const U64 bitmask57 = 0x01ffffffffffffffull; global const U64 bitmask58 = 0x03ffffffffffffffull; global const U64 bitmask59 = 0x07ffffffffffffffull; global const U64 bitmask60 = 0x0fffffffffffffffull; global const U64 bitmask61 = 0x1fffffffffffffffull; global const U64 bitmask62 = 0x3fffffffffffffffull; global const U64 bitmask63 = 0x7fffffffffffffffull; global const U64 bitmask64 = 0xffffffffffffffffull; global const U32 bit1 = (1<<0); global const U32 bit2 = (1<<1); global const U32 bit3 = (1<<2); global const U32 bit4 = (1<<3); global const U32 bit5 = (1<<4); global const U32 bit6 = (1<<5); global const U32 bit7 = (1<<6); global const U32 bit8 = (1<<7); global const U32 bit9 = (1<<8); global const U32 bit10 = (1<<9); global const U32 bit11 = (1<<10); global const U32 bit12 = (1<<11); global const U32 bit13 = (1<<12); global const U32 bit14 = (1<<13); global const U32 bit15 = (1<<14); global const U32 bit16 = (1<<15); global const U32 bit17 = (1<<16); global const U32 bit18 = (1<<17); global const U32 bit19 = (1<<18); global const U32 bit20 = (1<<19); global const U32 bit21 = (1<<20); global const U32 bit22 = (1<<21); global const U32 bit23 = (1<<22); global const U32 bit24 = (1<<23); global const U32 bit25 = (1<<24); global const U32 bit26 = (1<<25); global const U32 bit27 = (1<<26); global const U32 bit28 = (1<<27); global const U32 bit29 = (1<<28); global const U32 bit30 = (1<<29); global const U32 bit31 = (1<<30); global const U32 bit32 = (1<<31); global const U64 bit33 = (1ull<<32); global const U64 bit34 = (1ull<<33); global const U64 bit35 = (1ull<<34); global const U64 bit36 = (1ull<<35); global const U64 bit37 = (1ull<<36); global const U64 bit38 = (1ull<<37); global const U64 bit39 = (1ull<<38); global const U64 bit40 = (1ull<<39); global const U64 bit41 = (1ull<<40); global const U64 bit42 = (1ull<<41); global const U64 bit43 = (1ull<<42); global const U64 bit44 = (1ull<<43); global const U64 bit45 = (1ull<<44); global const U64 bit46 = (1ull<<45); global const U64 bit47 = (1ull<<46); global const U64 bit48 = (1ull<<47); global const U64 bit49 = (1ull<<48); global const U64 bit50 = (1ull<<49); global const U64 bit51 = (1ull<<50); global const U64 bit52 = (1ull<<51); global const U64 bit53 = (1ull<<52); global const U64 bit54 = (1ull<<53); global const U64 bit55 = (1ull<<54); global const U64 bit56 = (1ull<<55); global const U64 bit57 = (1ull<<56); global const U64 bit58 = (1ull<<57); global const U64 bit59 = (1ull<<58); global const U64 bit60 = (1ull<<59); global const U64 bit61 = (1ull<<60); global const U64 bit62 = (1ull<<61); global const U64 bit63 = (1ull<<62); global const U64 bit64 = (1ull<<63); //////////////////////////////// //~ allen: Time typedef enum WeekDay { WeekDay_Sun, WeekDay_Mon, WeekDay_Tue, WeekDay_Wed, WeekDay_Thu, WeekDay_Fri, WeekDay_Sat, WeekDay_COUNT, } WeekDay; typedef enum Month { Month_Jan, Month_Feb, Month_Mar, Month_Apr, Month_May, Month_Jun, Month_Jul, Month_Aug, Month_Sep, Month_Oct, Month_Nov, Month_Dec, Month_COUNT, } Month; typedef struct DateTime DateTime; struct DateTime { U16 micro_sec; // [0,999] U16 msec; // [0,999] U16 sec; // [0,60] U16 min; // [0,59] U16 hour; // [0,24] U16 day; // [0,30] union { WeekDay week_day; U32 wday; }; union { Month month; U32 mon; }; U32 year; // 1 = 1 CE, 0 = 1 BC }; typedef U64 DenseTime; //////////////////////////////// //~ allen: Files typedef U32 FilePropertyFlags; enum { FilePropertyFlag_IsFolder = (1 << 0), }; typedef struct FileProperties FileProperties; struct FileProperties { U64 size; DenseTime modified; DenseTime created; FilePropertyFlags flags; }; //////////////////////////////// //~ rjf: Safe Casts internal U16 safe_cast_u16(U32 x); internal U32 safe_cast_u32(U64 x); internal S32 safe_cast_s32(S64 x); //////////////////////////////// //~ rjf: Large Base Type Functions internal U128 u128_zero(void); internal U128 u128_make(U64 v0, U64 v1); internal B32 u128_match(U128 a, U128 b); //////////////////////////////// //~ rjf: Bit Patterns internal U32 u32_from_u64_saturate(U64 x); internal U64 u64_up_to_pow2(U64 x); internal S32 extend_sign32(U32 x, U32 size); internal S64 extend_sign64(U64 x, U64 size); internal F32 inf32(void); internal F32 neg_inf32(void); internal U16 bswap_u16(U16 x); internal U32 bswap_u32(U32 x); internal U64 bswap_u64(U64 x); #if ARCH_LITTLE_ENDIAN # define from_be_u16(x) bswap_u16(x) # define from_be_u32(x) bswap_u32(x) # define from_be_u64(x) bswap_u64(x) #else # define from_be_u16(x) (x) # define from_be_u32(x) (x) # define from_be_u64(x) (x) #endif internal U64 count_bits_set32(U32 val); internal U64 count_bits_set64(U64 val); internal U64 ctz32(U32 val); internal U64 ctz64(U64 val); internal U64 clz32(U32 val); internal U64 clz64(U64 val); //////////////////////////////// //~ rjf: Enum -> Sign internal S32 sign_from_side_S32(Side side); internal F32 sign_from_side_F32(Side side); //////////////////////////////// //~ rjf: Memory Functions internal B32 memory_is_zero(void *ptr, U64 size); //////////////////////////////// //~ rjf: Text 2D Coordinate/Range Functions internal TxtPt txt_pt(S64 line, S64 column); internal B32 txt_pt_match(TxtPt a, TxtPt b); internal B32 txt_pt_less_than(TxtPt a, TxtPt b); internal TxtPt txt_pt_min(TxtPt a, TxtPt b); internal TxtPt txt_pt_max(TxtPt a, TxtPt b); internal TxtRng txt_rng(TxtPt min, TxtPt max); internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b); internal TxtRng txt_rng_union(TxtRng a, TxtRng b); internal B32 txt_rng_contains(TxtRng r, TxtPt pt); //////////////////////////////// //~ rjf: Toolchain/Environment Enum Functions internal U64 bit_size_from_arch(Arch arch); internal U64 max_instruction_size_from_arch(Arch arch); internal OperatingSystem operating_system_from_context(void); internal Arch arch_from_context(void); internal Compiler compiler_from_context(void); //////////////////////////////// //~ rjf: Time Functions internal DenseTime dense_time_from_date_time(DateTime date_time); internal DateTime date_time_from_dense_time(DenseTime time); internal DateTime date_time_from_micro_seconds(U64 time); internal DateTime date_time_from_unix_time(U64 unix_time); //////////////////////////////// //~ rjf: Non-Fancy Ring Buffer Reads/Writes internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size); internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size); #define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) #define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr))) //////////////////////////////// //~ rjf: Sorts #define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function)) #endif // BASE_CORE_H ================================================ FILE: src/metagen/metagen_base/metagen_base_entry_point.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) global U64 global_update_tick_idx = 0; internal void main_thread_base_entry_point(int arguments_count, char **arguments) { Temp scratch = scratch_begin(0, 0); ThreadNameF("[main thread]"); //- rjf: set up telemetry #if PROFILE_TELEMETRY local_persist char tm_data[MB(64)]; tmLoadLibrary(TM_RELEASE); tmSetMaxThreadCount(256); tmInitialize(sizeof(tm_data), tm_data); #endif //- rjf: parse command line String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments); CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); //- rjf: begin captures B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture")); if(capture) { ProfBeginCapture(arguments[0]); } #if PROFILE_TELEMETRY tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE); #endif //- rjf: initialize all included layers #if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL) async_init(&cmdline); #endif #if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL) p2r_init(); #endif #if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL) hs_init(); #endif #if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL) fs_init(); #endif #if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL) txt_init(); #endif #if defined(MUTABLE_TEXT_H) && !defined(MTX_INIT_MANUAL) mtx_init(); #endif #if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL) dasm_init(); #endif #if defined(DBGI_H) && !defined(DI_INIT_MANUAL) di_init(); #endif #if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL) dmn_init(); #endif #if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL) ctrl_init(); #endif #if defined(OS_GFX_H) && !defined(OS_GFX_INIT_MANUAL) os_gfx_init(); #endif #if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL) fp_init(); #endif #if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL) r_init(&cmdline); #endif #if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL) tex_init(); #endif #if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL) geo_init(); #endif #if defined(FONT_CACHE_H) && !defined(FNT_INIT_MANUAL) fnt_init(); #endif #if defined(DBG_ENGINE_CORE_H) && !defined(D_INIT_MANUAL) d_init(); #endif #if defined(RADDBG_CORE_H) && !defined(RD_INIT_MANUAL) rd_init(&cmdline); #endif //- rjf: call into entry point entry_point(&cmdline); //- rjf: end captures if(capture) { ProfEndCapture(); } scratch_end(scratch); } internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params) { TCTX tctx; tctx_init_and_equip(&tctx); entry_point(params); tctx_release(); } internal U64 update_tick_idx(void) { U64 result = ins_atomic_u64_eval(&global_update_tick_idx); return result; } internal B32 update(void) { ProfTick(0); ins_atomic_u64_inc_eval(&global_update_tick_idx); #if OS_FEATURE_GRAPHICAL B32 result = frame(); #else B32 result = 0; #endif return result; } ================================================ FILE: src/metagen/metagen_base/metagen_base_entry_point.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ENTRY_POINT_H #define BASE_ENTRY_POINT_H internal void main_thread_base_entry_point(int argc, char **argv); internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params); internal U64 update_tick_idx(void); internal B32 update(void); #endif // BASE_ENTRY_POINT_H ================================================ FILE: src/metagen/metagen_base/metagen_base_inc.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Base Includes #undef MARKUP_LAYER_COLOR #define MARKUP_LAYER_COLOR 0.20f, 0.60f, 0.80f #include "metagen_base_core.c" #include "metagen_base_profile.c" #include "metagen_base_arena.c" #include "metagen_base_math.c" #include "metagen_base_strings.c" #include "metagen_base_thread_context.c" #include "metagen_base_command_line.c" #include "metagen_base_markup.c" #include "metagen_base_meta.c" #include "metagen_base_log.c" #include "metagen_base_entry_point.c" ================================================ FILE: src/metagen/metagen_base/metagen_base_inc.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_INC_H #define BASE_INC_H //////////////////////////////// //~ rjf: Base Includes #include "metagen_base_context_cracking.h" #include "metagen_base_core.h" #include "metagen_base_profile.h" #include "metagen_base_arena.h" #include "metagen_base_math.h" #include "metagen_base_strings.h" #include "metagen_base_thread_context.h" #include "metagen_base_command_line.h" #include "metagen_base_markup.h" #include "metagen_base_meta.h" #include "metagen_base_log.h" #include "metagen_base_entry_point.h" #endif // BASE_INC_H ================================================ FILE: src/metagen/metagen_base/metagen_base_log.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Globals/Thread-Locals C_LINKAGE thread_static Log *log_active; #if !BUILD_SUPPLEMENTARY_UNIT C_LINKAGE thread_static Log *log_active = 0; #endif //////////////////////////////// //~ rjf: Log Creation/Selection internal Log * log_alloc(void) { Arena *arena = arena_alloc(); Log *log = push_array(arena, Log, 1); log->arena = arena; return log; } internal void log_release(Log *log) { arena_release(log->arena); } internal void log_select(Log *log) { log_active = log; } //////////////////////////////// //~ rjf: Log Building/Clearing internal void log_msg(LogMsgKind kind, String8 string) { if(log_active != 0 && log_active->top_scope != 0) { String8 string_copy = push_str8_copy(log_active->arena, string); str8_list_push(log_active->arena, &log_active->top_scope->strings[kind], string_copy); } } internal void log_msgf(LogMsgKind kind, char *fmt, ...) { if(log_active != 0) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); log_msg(kind, string); va_end(args); scratch_end(scratch); } } //////////////////////////////// //~ rjf: Log Scopes internal void log_scope_begin(void) { if(log_active != 0) { U64 pos = arena_pos(log_active->arena); LogScope *scope = push_array(log_active->arena, LogScope, 1); scope->pos = pos; SLLStackPush(log_active->top_scope, scope); } } internal LogScopeResult log_scope_end(Arena *arena) { LogScopeResult result = {0}; if(log_active != 0) { LogScope *scope = log_active->top_scope; if(scope != 0) { SLLStackPop(log_active->top_scope); if(arena != 0) { for EachEnumVal(LogMsgKind, kind) { Temp scratch = scratch_begin(&arena, 1); String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0); result.strings[kind] = indented_from_string(arena, result_unindented); scratch_end(scratch); } } arena_pop_to(log_active->arena, scope->pos); } } return result; } ================================================ FILE: src/metagen/metagen_base/metagen_base_log.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_LOG_H #define BASE_LOG_H //////////////////////////////// //~ rjf: Log Types typedef enum LogMsgKind { LogMsgKind_Info, LogMsgKind_UserError, LogMsgKind_COUNT } LogMsgKind; typedef struct LogScope LogScope; struct LogScope { LogScope *next; U64 pos; String8List strings[LogMsgKind_COUNT]; }; typedef struct LogScopeResult LogScopeResult; struct LogScopeResult { String8 strings[LogMsgKind_COUNT]; }; typedef struct Log Log; struct Log { Arena *arena; LogScope *top_scope; }; //////////////////////////////// //~ rjf: Log Creation/Selection internal Log *log_alloc(void); internal void log_release(Log *log); internal void log_select(Log *log); //////////////////////////////// //~ rjf: Log Building internal void log_msg(LogMsgKind kind, String8 string); internal void log_msgf(LogMsgKind kind, char *fmt, ...); #define log_info(s) log_msg(LogMsgKind_Info, (s)) #define log_infof(fmt, ...) log_msgf(LogMsgKind_Info, (fmt), __VA_ARGS__) #define log_user_error(s) log_msg(LogMsgKind_UserError, (s)) #define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__) #define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n")) #define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n")) //////////////////////////////// //~ rjf: Log Scopes internal void log_scope_begin(void); internal LogScopeResult log_scope_end(Arena *arena); #endif // BASE_LOG_H ================================================ FILE: src/metagen/metagen_base/metagen_base_markup.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void set_thread_name(String8 string) { ProfThreadName("%.*s", str8_varg(string)); os_set_thread_name(string); } internal void set_thread_namef(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); set_thread_name(string); va_end(args); scratch_end(scratch); } ================================================ FILE: src/metagen/metagen_base/metagen_base_markup.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MARKUP_H #define BASE_MARKUP_H internal void set_thread_name(String8 string); internal void set_thread_namef(char *fmt, ...); #define ThreadNameF(...) (set_thread_namef(__VA_ARGS__)) #define ThreadName(str) (set_thread_name(str)) #endif // BASE_MARKUP_H ================================================ FILE: src/metagen/metagen_base/metagen_base_math.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Scalar Ops internal F32 mix_1f32(F32 a, F32 b, F32 t) { F32 c = (a + (b-a) * Clamp(0.f, t, 1.f)); return c; } internal F64 mix_1f64(F64 a, F64 b, F64 t) { F64 c = (a + (b-a) * Clamp(0.0, t, 1.0)); return c; } //////////////////////////////// //~ rjf: Vector Ops internal Vec2F32 vec_2f32(F32 x, F32 y) {Vec2F32 v = {x, y}; return v;} internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2F32 scale_2f32(Vec2F32 v, F32 s) {Vec2F32 c = {v.x*s, v.y*s}; return c;} internal F32 dot_2f32(Vec2F32 a, Vec2F32 b) {F32 c = a.x*b.x + a.y*b.y; return c;} internal F32 length_squared_2f32(Vec2F32 v) {F32 c = v.x*v.x + v.y*v.y; return c;} internal F32 length_2f32(Vec2F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y); return c;} internal Vec2F32 normalize_2f32(Vec2F32 v) {v = scale_2f32(v, 1.f/length_2f32(v)); return v;} internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t) {Vec2F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t)}; return c;} internal Vec2S64 vec_2s64(S64 x, S64 y) {Vec2S64 v = {x, y}; return v;} internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2S64 scale_2s64(Vec2S64 v, S64 s) {Vec2S64 c = {v.x*s, v.y*s}; return c;} internal S64 dot_2s64(Vec2S64 a, Vec2S64 b) {S64 c = a.x*b.x + a.y*b.y; return c;} internal S64 length_squared_2s64(Vec2S64 v) {S64 c = v.x*v.x + v.y*v.y; return c;} internal S64 length_2s64(Vec2S64 v) {S64 c = (S64)sqrt_f64((F64)(v.x*v.x + v.y*v.y)); return c;} internal Vec2S64 normalize_2s64(Vec2S64 v) {v = scale_2s64(v, (S64)(1.f/length_2s64(v))); return v;} internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t) {Vec2S64 c = {(S64)mix_1f32((F32)a.x, (F32)b.x, t), (S64)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec2S32 vec_2s32(S32 x, S32 y) {Vec2S32 v = {x, y}; return v;} internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x+b.x, a.y+b.y}; return c;} internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x-b.x, a.y-b.y}; return c;} internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x*b.x, a.y*b.y}; return c;} internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x/b.x, a.y/b.y}; return c;} internal Vec2S32 scale_2s32(Vec2S32 v, S32 s) {Vec2S32 c = {v.x*s, v.y*s}; return c;} internal S32 dot_2s32(Vec2S32 a, Vec2S32 b) {S32 c = a.x*b.x + a.y*b.y; return c;} internal S32 length_squared_2s32(Vec2S32 v) {S32 c = v.x*v.x + v.y*v.y; return c;} internal S32 length_2s32(Vec2S32 v) {S32 c = (S32)sqrt_f32((F32)v.x*(F32)v.x + (F32)v.y*(F32)v.y); return c;} internal Vec2S32 normalize_2s32(Vec2S32 v) {v = scale_2s32(v, (S32)(1.f/length_2s32(v))); return v;} internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t) {Vec2S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec2S16 vec_2s16(S16 x, S16 y) {Vec2S16 v = {x, y}; return v;} internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x+b.x), (S16)(a.y+b.y)}; return c;} internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x-b.x), (S16)(a.y-b.y)}; return c;} internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x*b.x), (S16)(a.y*b.y)}; return c;} internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x/b.x), (S16)(a.y/b.y)}; return c;} internal Vec2S16 scale_2s16(Vec2S16 v, S16 s) {Vec2S16 c = {(S16)(v.x*s), (S16)(v.y*s)}; return c;} internal S16 dot_2s16(Vec2S16 a, Vec2S16 b) {S16 c = a.x*b.x + a.y*b.y; return c;} internal S16 length_squared_2s16(Vec2S16 v) {S16 c = v.x*v.x + v.y*v.y; return c;} internal S16 length_2s16(Vec2S16 v) {S16 c = (S16)sqrt_f32((F32)(v.x*v.x + v.y*v.y)); return c;} internal Vec2S16 normalize_2s16(Vec2S16 v) {v = scale_2s16(v, (S16)(1.f/length_2s16(v))); return v;} internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t) {Vec2S16 c = {(S16)mix_1f32((F32)a.x, (F32)b.x, t), (S16)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;} internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z) {Vec3F32 v = {x, y, z}; return v;} internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} internal Vec3F32 scale_3f32(Vec3F32 v, F32 s) {Vec3F32 c = {v.x*s, v.y*s, v.z*s}; return c;} internal F32 dot_3f32(Vec3F32 a, Vec3F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} internal F32 length_squared_3f32(Vec3F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z); return c;} internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;} internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;} internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;} internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;} internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;} internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;} internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;} internal Vec3S32 scale_3s32(Vec3S32 v, S32 s) {Vec3S32 c = {v.x*s, v.y*s, v.z*s}; return c;} internal S32 dot_3s32(Vec3S32 a, Vec3S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;} internal S32 length_squared_3s32(Vec3S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;} internal S32 length_3s32(Vec3S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z)); return c;} internal Vec3S32 normalize_3s32(Vec3S32 v) {v = scale_3s32(v, (S32)(1.f/length_3s32(v))); return v;} internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t) {Vec3S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t)}; return c;} internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;} internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w) {Vec4F32 v = {x, y, z, w}; return v;} internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} internal Vec4F32 scale_4f32(Vec4F32 v, F32 s) {Vec4F32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} internal F32 dot_4f32(Vec4F32 a, Vec4F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} internal F32 length_squared_4f32(Vec4F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} internal F32 length_4f32(Vec4F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); return c;} internal Vec4F32 normalize_4f32(Vec4F32 v) {v = scale_4f32(v, 1.f/length_4f32(v)); return v;} internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t) {Vec4F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t), mix_1f32(a.w, b.w, t)}; return c;} internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w) {Vec4S32 v = {x, y, z, w}; return v;} internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;} internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;} internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;} internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;} internal Vec4S32 scale_4s32(Vec4S32 v, S32 s) {Vec4S32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;} internal S32 dot_4s32(Vec4S32 a, Vec4S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;} internal S32 length_squared_4s32(Vec4S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;} internal S32 length_4s32(Vec4S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)); return c;} internal Vec4S32 normalize_4s32(Vec4S32 v) {v = scale_4s32(v, (S32)(1.f/length_4s32(v))); return v;} internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t) {Vec4S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t), (S32)mix_1f32((F32)a.w, (F32)b.w, t)}; return c;} //////////////////////////////// //~ rjf: Matrix Ops internal Mat3x3F32 mat_3x3f32(F32 diagonal) { Mat3x3F32 result = {0}; result.v[0][0] = diagonal; result.v[1][1] = diagonal; result.v[2][2] = diagonal; return result; } internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta) { Mat3x3F32 mat = mat_3x3f32(1.f); mat.v[2][0] = delta.x; mat.v[2][1] = delta.y; return mat; } internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale) { Mat3x3F32 mat = mat_3x3f32(1.f); mat.v[0][0] = scale.x; mat.v[1][1] = scale.y; return mat; } internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b) { Mat3x3F32 c = {0}; for(int j = 0; j < 3; j += 1) { for(int i = 0; i < 3; i += 1) { c.v[i][j] = (a.v[0][j]*b.v[i][0] + a.v[1][j]*b.v[i][1] + a.v[2][j]*b.v[i][2]); } } return c; } internal Mat4x4F32 mat_4x4f32(F32 diagonal) { Mat4x4F32 result = {0}; result.v[0][0] = diagonal; result.v[1][1] = diagonal; result.v[2][2] = diagonal; result.v[3][3] = diagonal; return result; } internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[3][0] = delta.x; result.v[3][1] = delta.y; result.v[3][2] = delta.z; return result; } internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[0][0] = scale.x; result.v[1][1] = scale.y; result.v[2][2] = scale.z; return result; } internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z) { Mat4x4F32 result = mat_4x4f32(1.f); F32 tan_theta_over_2 = tan_f32(fov / 2); result.v[0][0] = 1.f / tan_theta_over_2; result.v[1][1] = aspect_ratio / tan_theta_over_2; result.v[2][3] = 1.f; result.v[2][2] = -(near_z + far_z) / (near_z - far_z); result.v[3][2] = (2.f * near_z * far_z) / (near_z - far_z); result.v[3][3] = 0.f; return result; } internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z) { Mat4x4F32 result = mat_4x4f32(1.f); result.v[0][0] = 2.f / (right - left); result.v[1][1] = 2.f / (top - bottom); result.v[2][2] = 2.f / (far_z - near_z); result.v[3][3] = 1.f; result.v[3][0] = (left + right) / (left - right); result.v[3][1] = (bottom + top) / (bottom - top); result.v[3][2] = (near_z + far_z) / (near_z - far_z); return result; } internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up) { Mat4x4F32 result; Vec3F32 f = normalize_3f32(sub_3f32(eye, center)); Vec3F32 s = normalize_3f32(cross_3f32(f, up)); Vec3F32 u = cross_3f32(s, f); result.v[0][0] = s.x; result.v[0][1] = u.x; result.v[0][2] = -f.x; result.v[0][3] = 0.0f; result.v[1][0] = s.y; result.v[1][1] = u.y; result.v[1][2] = -f.y; result.v[1][3] = 0.0f; result.v[2][0] = s.z; result.v[2][1] = u.z; result.v[2][2] = -f.z; result.v[2][3] = 0.0f; result.v[3][0] = -dot_3f32(s, eye); result.v[3][1] = -dot_3f32(u, eye); result.v[3][2] = dot_3f32(f, eye); result.v[3][3] = 1.0f; return result; } internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns) { Mat4x4F32 result = mat_4x4f32(1.f); axis = normalize_3f32(axis); F32 sin_theta = sin_f32(turns); F32 cos_theta = cos_f32(turns); F32 cos_value = 1.f - cos_theta; result.v[0][0] = (axis.x * axis.x * cos_value) + cos_theta; result.v[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta); result.v[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta); result.v[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta); result.v[1][1] = (axis.y * axis.y * cos_value) + cos_theta; result.v[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta); result.v[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta); result.v[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta); result.v[2][2] = (axis.z * axis.z * cos_value) + cos_theta; return result; } internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b) { Mat4x4F32 c = {0}; for(int j = 0; j < 4; j += 1) { for(int i = 0; i < 4; i += 1) { c.v[i][j] = (a.v[0][j]*b.v[i][0] + a.v[1][j]*b.v[i][1] + a.v[2][j]*b.v[i][2] + a.v[3][j]*b.v[i][3]); } } return c; } internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale) { for(int j = 0; j < 4; j += 1) { for(int i = 0; i < 4; i += 1) { m.v[i][j] *= scale; } } return m; } internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m) { F32 coef00 = m.v[2][2] * m.v[3][3] - m.v[3][2] * m.v[2][3]; F32 coef02 = m.v[1][2] * m.v[3][3] - m.v[3][2] * m.v[1][3]; F32 coef03 = m.v[1][2] * m.v[2][3] - m.v[2][2] * m.v[1][3]; F32 coef04 = m.v[2][1] * m.v[3][3] - m.v[3][1] * m.v[2][3]; F32 coef06 = m.v[1][1] * m.v[3][3] - m.v[3][1] * m.v[1][3]; F32 coef07 = m.v[1][1] * m.v[2][3] - m.v[2][1] * m.v[1][3]; F32 coef08 = m.v[2][1] * m.v[3][2] - m.v[3][1] * m.v[2][2]; F32 coef10 = m.v[1][1] * m.v[3][2] - m.v[3][1] * m.v[1][2]; F32 coef11 = m.v[1][1] * m.v[2][2] - m.v[2][1] * m.v[1][2]; F32 coef12 = m.v[2][0] * m.v[3][3] - m.v[3][0] * m.v[2][3]; F32 coef14 = m.v[1][0] * m.v[3][3] - m.v[3][0] * m.v[1][3]; F32 coef15 = m.v[1][0] * m.v[2][3] - m.v[2][0] * m.v[1][3]; F32 coef16 = m.v[2][0] * m.v[3][2] - m.v[3][0] * m.v[2][2]; F32 coef18 = m.v[1][0] * m.v[3][2] - m.v[3][0] * m.v[1][2]; F32 coef19 = m.v[1][0] * m.v[2][2] - m.v[2][0] * m.v[1][2]; F32 coef20 = m.v[2][0] * m.v[3][1] - m.v[3][0] * m.v[2][1]; F32 coef22 = m.v[1][0] * m.v[3][1] - m.v[3][0] * m.v[1][1]; F32 coef23 = m.v[1][0] * m.v[2][1] - m.v[2][0] * m.v[1][1]; Vec4F32 fac0 = { coef00, coef00, coef02, coef03 }; Vec4F32 fac1 = { coef04, coef04, coef06, coef07 }; Vec4F32 fac2 = { coef08, coef08, coef10, coef11 }; Vec4F32 fac3 = { coef12, coef12, coef14, coef15 }; Vec4F32 fac4 = { coef16, coef16, coef18, coef19 }; Vec4F32 fac5 = { coef20, coef20, coef22, coef23 }; Vec4F32 vec0 = { m.v[1][0], m.v[0][0], m.v[0][0], m.v[0][0] }; Vec4F32 vec1 = { m.v[1][1], m.v[0][1], m.v[0][1], m.v[0][1] }; Vec4F32 vec2 = { m.v[1][2], m.v[0][2], m.v[0][2], m.v[0][2] }; Vec4F32 vec3 = { m.v[1][3], m.v[0][3], m.v[0][3], m.v[0][3] }; Vec4F32 inv0 = add_4f32(sub_4f32(mul_4f32(vec1, fac0), mul_4f32(vec2, fac1)), mul_4f32(vec3, fac2)); Vec4F32 inv1 = add_4f32(sub_4f32(mul_4f32(vec0, fac0), mul_4f32(vec2, fac3)), mul_4f32(vec3, fac4)); Vec4F32 inv2 = add_4f32(sub_4f32(mul_4f32(vec0, fac1), mul_4f32(vec1, fac3)), mul_4f32(vec3, fac5)); Vec4F32 inv3 = add_4f32(sub_4f32(mul_4f32(vec0, fac2), mul_4f32(vec1, fac4)), mul_4f32(vec2, fac5)); Vec4F32 sign_a = { +1, -1, +1, -1 }; Vec4F32 sign_b = { -1, +1, -1, +1 }; Mat4x4F32 inverse; for(U32 i = 0; i < 4; i += 1) { inverse.v[0][i] = inv0.v[i] * sign_a.v[i]; inverse.v[1][i] = inv1.v[i] * sign_b.v[i]; inverse.v[2][i] = inv2.v[i] * sign_a.v[i]; inverse.v[3][i] = inv3.v[i] * sign_b.v[i]; } Vec4F32 row0 = { inverse.v[0][0], inverse.v[1][0], inverse.v[2][0], inverse.v[3][0] }; Vec4F32 m0 = { m.v[0][0], m.v[0][1], m.v[0][2], m.v[0][3] }; Vec4F32 dot0 = mul_4f32(m0, row0); F32 dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w); F32 one_over_det = 1 / dot1; return scale_4x4f32(inverse, one_over_det); } internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat) { Vec3F32 scale = { length_3f32(v3f32(mat.v[0][0], mat.v[0][1], mat.v[0][2])), length_3f32(v3f32(mat.v[1][0], mat.v[1][1], mat.v[1][2])), length_3f32(v3f32(mat.v[2][0], mat.v[2][1], mat.v[2][2])), }; mat.v[0][0] = scale.x; mat.v[1][0] = 0.f; mat.v[2][0] = 0.f; mat.v[0][1] = 0.f; mat.v[1][1] = scale.y; mat.v[2][1] = 0.f; mat.v[0][2] = 0.f; mat.v[1][2] = 0.f; mat.v[2][2] = scale.z; return mat; } //////////////////////////////// //~ rjf: Range Ops internal Rng1U32 rng_1u32(U32 min, U32 max) {Rng1U32 r = {min, max}; if(r.min > r.max) { Swap(U32, r.min, r.max); } return r;} internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.max += x; return r;} internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;} internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;} internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal U32 dim_1u32(Rng1U32 r) {U32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1S32 rng_1s32(S32 min, S32 max) {Rng1S32 r = {min, max}; if(r.min > r.max) { Swap(S32, r.min, r.max); } return r;} internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.max += x; return r;} internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;} internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;} internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal S32 dim_1s32(Rng1S32 r) {S32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1U64 rng_1u64(U64 min, U64 max) {Rng1U64 r = {min, max}; if(r.min > r.max) { Swap(U64, r.min, r.max); } return r;} internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.max += x; return r;} internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;} internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;} internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;} internal U64 dim_1u64(Rng1U64 r) {U64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1S64 rng_1s64(S64 min, S64 max) {Rng1S64 r = {min, max}; if(r.min > r.max) { Swap(S64, r.min, r.max); } return r;} internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.max += x; return r;} internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;} internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;} internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;} internal S64 dim_1s64(Rng1S64 r) {S64 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng1F32 rng_1f32(F32 min, F32 max) {Rng1F32 r = {min, max}; if(r.min > r.max) { Swap(F32, r.min, r.max); } return r;} internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.max += x; return r;} internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;} internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;} internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;} internal F32 dim_1f32(Rng1F32 r) {F32 c = ((r.max > r.min) ? (r.max - r.min) : 0); return c;} internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;} internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;} internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;} internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max) {Rng2S16 r = {min, max}; return r;} internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s16(r.min, x); r.max = add_2s16(r.max, x); return r;} internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;} internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;} internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0)), (S16)(((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0))}; return dim;} internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max) {Rng2S32 r = {min, max}; return r;} internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s32(r.min, x); r.max = add_2s32(r.max, x); return r;} internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;} internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max) {Rng2S64 r = {min, max}; return r;} internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s64(r.min, x); r.max = add_2s64(r.max, x); return r;} internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;} internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max) {Rng2F32 r = {min, max}; return r;} internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f32(r.min, x); r.max = add_2f32(r.max, x); return r;} internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;} internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;} internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;} internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {((r.max.x > r.min.x) ? (r.max.x - r.min.x) : 0), ((r.max.y > r.min.y) ? (r.max.y - r.min.y) : 0)}; return dim;} internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;} internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;} internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;} //////////////////////////////// //~ rjf: Miscellaneous Ops internal Vec3F32 hsv_from_rgb(Vec3F32 rgb) { F32 c_max = Max(rgb.x, Max(rgb.y, rgb.z)); F32 c_min = Min(rgb.x, Min(rgb.y, rgb.z)); F32 delta = c_max - c_min; F32 h = ((delta == 0.f) ? 0.f : (c_max == rgb.x) ? mod_f32((rgb.y - rgb.z)/delta + 6.f, 6.f) : (c_max == rgb.y) ? (rgb.z - rgb.x)/delta + 2.f : (c_max == rgb.z) ? (rgb.x - rgb.y)/delta + 4.f : 0.f); F32 s = (c_max == 0.f) ? 0.f : (delta/c_max); F32 v = c_max; Vec3F32 hsv = {h/6.f, s, v}; return hsv; } internal Vec3F32 rgb_from_hsv(Vec3F32 hsv) { F32 h = mod_f32(hsv.x * 360.f, 360.f); F32 s = hsv.y; F32 v = hsv.z; F32 c = v*s; F32 x = c*(1.f - abs_f32(mod_f32(h/60.f, 2.f) - 1.f)); F32 m = v - c; F32 r = 0; F32 g = 0; F32 b = 0; if ((h >= 0.f && h < 60.f) || (h >= 360.f && h < 420.f)){ r = c; g = x; b = 0; } else if (h >= 60.f && h < 120.f){ r = x; g = c; b = 0; } else if (h >= 120.f && h < 180.f){ r = 0; g = c; b = x; } else if (h >= 180.f && h < 240.f){ r = 0; g = x; b = c; } else if (h >= 240.f && h < 300.f){ r = x; g = 0; b = c; } else if ((h >= 300.f && h <= 360.f) || (h >= -60.f && h <= 0.f)){ r = c; g = 0; b = x; } Vec3F32 rgb = {r + m, g + m, b + m}; return(rgb); } internal Vec4F32 hsva_from_rgba(Vec4F32 rgba) { Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z); Vec3F32 hsv = hsv_from_rgb(rgb); Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w); return hsva; } internal Vec4F32 rgba_from_hsva(Vec4F32 hsva) { Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); Vec3F32 rgb = rgb_from_hsv(hsv); Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w); return rgba; } internal Vec4F32 rgba_from_u32(U32 hex) { Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f, ((hex&0x00ff0000)>>16)/255.f, ((hex&0x0000ff00)>> 8)/255.f, ((hex&0x000000ff)>> 0)/255.f); return result; } internal U32 u32_from_rgba(Vec4F32 rgba) { U32 result = 0; result |= ((U32)((U8)(rgba.x*255.f))) << 24; result |= ((U32)((U8)(rgba.y*255.f))) << 16; result |= ((U32)((U8)(rgba.z*255.f))) << 8; result |= ((U32)((U8)(rgba.w*255.f))) << 0; return result; } //////////////////////////////// //~ rjf: List Type Functions internal void rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng) { Rng1U64Node *n = push_array(arena, Rng1U64Node, 1); MemoryCopyStruct(&n->v, &rng); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat) { if(to_concat->first) { if(list->first) { list->last->next = to_concat->first; list->last = to_concat->last; } else { list->first = to_concat->first; list->last = to_concat->last; } MemoryZeroStruct(to_concat); } } internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list) { Rng1U64Array arr = {0}; arr.count = list->count; arr.v = push_array_no_zero(arena, Rng1U64, arr.count); U64 idx = 0; for(Rng1U64Node *n = list->first; n != 0; n = n->next) { arr.v[idx] = n->v; idx += 1; } return arr; } internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng) { Rng1S64Node *n = push_array(arena, Rng1S64Node, 1); MemoryCopyStruct(&n->v, &rng); SLLQueuePush(list->first, list->last, n); list->count += 1; } internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list) { Rng1S64Array arr = {0}; arr.count = list->count; arr.v = push_array_no_zero(arena, Rng1S64, arr.count); U64 idx = 0; for(Rng1S64Node *n = list->first; n != 0; n = n->next) { arr.v[idx] = n->v; idx += 1; } return arr; } ================================================ FILE: src/metagen/metagen_base/metagen_base_math.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MATH_H #define BASE_MATH_H //////////////////////////////// //~ rjf: Vector Types //- rjf: 2-vectors typedef union Vec2F32 Vec2F32; union Vec2F32 { struct { F32 x; F32 y; }; F32 v[2]; }; typedef union Vec2S64 Vec2S64; union Vec2S64 { struct { S64 x; S64 y; }; S64 v[2]; }; typedef union Vec2S32 Vec2S32; union Vec2S32 { struct { S32 x; S32 y; }; S32 v[2]; }; typedef union Vec2S16 Vec2S16; union Vec2S16 { struct { S16 x; S16 y; }; S16 v[2]; }; //- rjf: 3-vectors typedef union Vec3F32 Vec3F32; union Vec3F32 { struct { F32 x; F32 y; F32 z; }; struct { Vec2F32 xy; F32 _z0; }; struct { F32 _x0; Vec2F32 yz; }; F32 v[3]; }; typedef union Vec3S32 Vec3S32; union Vec3S32 { struct { S32 x; S32 y; S32 z; }; struct { Vec2S32 xy; S32 _z0; }; struct { S32 _x0; Vec2S32 yz; }; S32 v[3]; }; //- rjf: 4-vectors typedef union Vec4F32 Vec4F32; union Vec4F32 { struct { F32 x; F32 y; F32 z; F32 w; }; struct { Vec2F32 xy; Vec2F32 zw; }; struct { Vec3F32 xyz; F32 _z0; }; struct { F32 _x0; Vec3F32 yzw; }; F32 v[4]; }; typedef union Vec4S32 Vec4S32; union Vec4S32 { struct { S32 x; S32 y; S32 z; S32 w; }; struct { Vec2S32 xy; Vec2S32 zw; }; struct { Vec3S32 xyz; S32 _z0; }; struct { S32 _x0; Vec3S32 yzw; }; S32 v[4]; }; //////////////////////////////// //~ rjf: Matrix Types typedef struct Mat3x3F32 Mat3x3F32; struct Mat3x3F32 { F32 v[3][3]; }; typedef struct Mat4x4F32 Mat4x4F32; struct Mat4x4F32 { F32 v[4][4]; }; //////////////////////////////// //~ rjf: Range Types //- rjf: 1-range typedef union Rng1U32 Rng1U32; union Rng1U32 { struct { U32 min; U32 max; }; U32 v[2]; }; typedef union Rng1S32 Rng1S32; union Rng1S32 { struct { S32 min; S32 max; }; S32 v[2]; }; typedef union Rng1U64 Rng1U64; union Rng1U64 { struct { U64 min; U64 max; }; U64 v[2]; }; typedef union Rng1S64 Rng1S64; union Rng1S64 { struct { S64 min; S64 max; }; S64 v[2]; }; typedef union Rng1F32 Rng1F32; union Rng1F32 { struct { F32 min; F32 max; }; F32 v[2]; }; //- rjf: 2-range (rectangles) typedef union Rng2S16 Rng2S16; union Rng2S16 { struct { Vec2S16 min; Vec2S16 max; }; struct { Vec2S16 p0; Vec2S16 p1; }; struct { S16 x0; S16 y0; S16 x1; S16 y1; }; Vec2S16 v[2]; }; typedef union Rng2S32 Rng2S32; union Rng2S32 { struct { Vec2S32 min; Vec2S32 max; }; struct { Vec2S32 p0; Vec2S32 p1; }; struct { S32 x0; S32 y0; S32 x1; S32 y1; }; Vec2S32 v[2]; }; typedef union Rng2F32 Rng2F32; union Rng2F32 { struct { Vec2F32 min; Vec2F32 max; }; struct { Vec2F32 p0; Vec2F32 p1; }; struct { F32 x0; F32 y0; F32 x1; F32 y1; }; Vec2F32 v[2]; }; typedef union Rng2S64 Rng2S64; union Rng2S64 { struct { Vec2S64 min; Vec2S64 max; }; struct { Vec2S64 p0; Vec2S64 p1; }; struct { S64 x0; S64 y0; S64 x1; S64 y1; }; Vec2S64 v[2]; }; //////////////////////////////// //~ rjf: List Types typedef struct Rng1U64Node Rng1U64Node; struct Rng1U64Node { Rng1U64Node *next; Rng1U64 v; }; typedef struct Rng1U64List Rng1U64List; struct Rng1U64List { U64 count; Rng1U64Node *first; Rng1U64Node *last; }; typedef struct Rng1U64Array Rng1U64Array; struct Rng1U64Array { Rng1U64 *v; U64 count; }; typedef struct Rng1S64Node Rng1S64Node; struct Rng1S64Node { Rng1S64Node *next; Rng1S64 v; }; typedef struct Rng1S64List Rng1S64List; struct Rng1S64List { Rng1S64Node *first; Rng1S64Node *last; U64 count; }; typedef struct Rng1S64Array Rng1S64Array; struct Rng1S64Array { Rng1S64 *v; U64 count; }; //////////////////////////////// //~ rjf: Scalar Ops #define abs_s64(v) (S64)llabs(v) #define sqrt_f32(v) sqrtf(v) #define mod_f32(a, b) fmodf((a), (b)) #define pow_f32(b, e) powf((b), (e)) #define ceil_f32(v) ceilf(v) #define floor_f32(v) floorf(v) #define round_f32(v) roundf(v) #define abs_f32(v) fabsf(v) #define radians_from_turns_f32(v) ((v)*2*3.1415926535897f) #define turns_from_radians_f32(v) ((v)/2*3.1415926535897f) #define degrees_from_turns_f32(v) ((v)*360.f) #define turns_from_degrees_f32(v) ((v)/360.f) #define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v))) #define radians_from_degrees_f32(v) (radians_from_turns_f32(turns_from_degrees_f32(v))) #define sin_f32(v) sinf(radians_from_turns_f32(v)) #define cos_f32(v) cosf(radians_from_turns_f32(v)) #define tan_f32(v) tanf(radians_from_turns_f32(v)) #define sqrt_f64(v) sqrt(v) #define mod_f64(a, b) fmod((a), (b)) #define pow_f64(b, e) pow((b), (e)) #define ceil_f64(v) ceil(v) #define floor_f64(v) floor(v) #define round_f64(v) round(v) #define abs_f64(v) fabs(v) #define radians_from_turns_f64(v) ((v)*2*3.1415926535897) #define turns_from_radians_f64(v) ((v)/2*3.1415926535897) #define degrees_from_turns_f64(v) ((v)*360.0) #define turns_from_degrees_f64(v) ((v)/360.0) #define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v))) #define radians_from_degrees_f64(v) (radians_from_turns_f64(turns_from_degrees_f64(v))) #define sin_f64(v) sin(radians_from_turns_f64(v)) #define cos_f64(v) cos(radians_from_turns_f64(v)) #define tan_f64(v) tan(radians_from_turns_f64(v)) internal F32 mix_1f32(F32 a, F32 b, F32 t); internal F64 mix_1f64(F64 a, F64 b, F64 t); //////////////////////////////// //~ rjf: Vector Ops #define v2f32(x, y) vec_2f32((x), (y)) internal Vec2F32 vec_2f32(F32 x, F32 y); internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b); internal Vec2F32 scale_2f32(Vec2F32 v, F32 s); internal F32 dot_2f32(Vec2F32 a, Vec2F32 b); internal F32 length_squared_2f32(Vec2F32 v); internal F32 length_2f32(Vec2F32 v); internal Vec2F32 normalize_2f32(Vec2F32 v); internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t); #define v2s64(x, y) vec_2s64((x), (y)) internal Vec2S64 vec_2s64(S64 x, S64 y); internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b); internal Vec2S64 scale_2s64(Vec2S64 v, S64 s); internal S64 dot_2s64(Vec2S64 a, Vec2S64 b); internal S64 length_squared_2s64(Vec2S64 v); internal S64 length_2s64(Vec2S64 v); internal Vec2S64 normalize_2s64(Vec2S64 v); internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t); #define v2s32(x, y) vec_2s32((x), (y)) internal Vec2S32 vec_2s32(S32 x, S32 y); internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b); internal Vec2S32 scale_2s32(Vec2S32 v, S32 s); internal S32 dot_2s32(Vec2S32 a, Vec2S32 b); internal S32 length_squared_2s32(Vec2S32 v); internal S32 length_2s32(Vec2S32 v); internal Vec2S32 normalize_2s32(Vec2S32 v); internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t); #define v2s16(x, y) vec_2s16((x), (y)) internal Vec2S16 vec_2s16(S16 x, S16 y); internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b); internal Vec2S16 scale_2s16(Vec2S16 v, S16 s); internal S16 dot_2s16(Vec2S16 a, Vec2S16 b); internal S16 length_squared_2s16(Vec2S16 v); internal S16 length_2s16(Vec2S16 v); internal Vec2S16 normalize_2s16(Vec2S16 v); internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t); #define v3f32(x, y, z) vec_3f32((x), (y), (z)) internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z); internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b); internal Vec3F32 scale_3f32(Vec3F32 v, F32 s); internal F32 dot_3f32(Vec3F32 a, Vec3F32 b); internal F32 length_squared_3f32(Vec3F32 v); internal F32 length_3f32(Vec3F32 v); internal Vec3F32 normalize_3f32(Vec3F32 v); internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t); internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b); #define v3s32(x, y, z) vec_3s32((x), (y), (z)) internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z); internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b); internal Vec3S32 scale_3s32(Vec3S32 v, S32 s); internal S32 dot_3s32(Vec3S32 a, Vec3S32 b); internal S32 length_squared_3s32(Vec3S32 v); internal S32 length_3s32(Vec3S32 v); internal Vec3S32 normalize_3s32(Vec3S32 v); internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t); internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b); #define v4f32(x, y, z, w) vec_4f32((x), (y), (z), (w)) internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w); internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b); internal Vec4F32 scale_4f32(Vec4F32 v, F32 s); internal F32 dot_4f32(Vec4F32 a, Vec4F32 b); internal F32 length_squared_4f32(Vec4F32 v); internal F32 length_4f32(Vec4F32 v); internal Vec4F32 normalize_4f32(Vec4F32 v); internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t); #define v4s32(x, y, z, w) vec_4s32((x), (y), (z), (w)) internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w); internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b); internal Vec4S32 scale_4s32(Vec4S32 v, S32 s); internal S32 dot_4s32(Vec4S32 a, Vec4S32 b); internal S32 length_squared_4s32(Vec4S32 v); internal S32 length_4s32(Vec4S32 v); internal Vec4S32 normalize_4s32(Vec4S32 v); internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t); //////////////////////////////// //~ rjf: Matrix Ops internal Mat3x3F32 mat_3x3f32(F32 diagonal); internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta); internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale); internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b); internal Mat4x4F32 mat_4x4f32(F32 diagonal); internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta); internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale); internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z); internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z); internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up); internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns); internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b); internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale); internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m); internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat); //////////////////////////////// //~ rjf: Range Ops #define r1u32(min, max) rng_1u32((min), (max)) internal Rng1U32 rng_1u32(U32 min, U32 max); internal Rng1U32 shift_1u32(Rng1U32 r, U32 x); internal Rng1U32 pad_1u32(Rng1U32 r, U32 x); internal U32 center_1u32(Rng1U32 r); internal B32 contains_1u32(Rng1U32 r, U32 x); internal U32 dim_1u32(Rng1U32 r); internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b); internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b); internal U32 clamp_1u32(Rng1U32 r, U32 v); #define r1s32(min, max) rng_1s32((min), (max)) internal Rng1S32 rng_1s32(S32 min, S32 max); internal Rng1S32 shift_1s32(Rng1S32 r, S32 x); internal Rng1S32 pad_1s32(Rng1S32 r, S32 x); internal S32 center_1s32(Rng1S32 r); internal B32 contains_1s32(Rng1S32 r, S32 x); internal S32 dim_1s32(Rng1S32 r); internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b); internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b); internal S32 clamp_1s32(Rng1S32 r, S32 v); #define r1u64(min, max) rng_1u64((min), (max)) internal Rng1U64 rng_1u64(U64 min, U64 max); internal Rng1U64 shift_1u64(Rng1U64 r, U64 x); internal Rng1U64 pad_1u64(Rng1U64 r, U64 x); internal U64 center_1u64(Rng1U64 r); internal B32 contains_1u64(Rng1U64 r, U64 x); internal U64 dim_1u64(Rng1U64 r); internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b); internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b); internal U64 clamp_1u64(Rng1U64 r, U64 v); #define r1s64(min, max) rng_1s64((min), (max)) internal Rng1S64 rng_1s64(S64 min, S64 max); internal Rng1S64 shift_1s64(Rng1S64 r, S64 x); internal Rng1S64 pad_1s64(Rng1S64 r, S64 x); internal S64 center_1s64(Rng1S64 r); internal B32 contains_1s64(Rng1S64 r, S64 x); internal S64 dim_1s64(Rng1S64 r); internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b); internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b); internal S64 clamp_1s64(Rng1S64 r, S64 v); #define r1f32(min, max) rng_1f32((min), (max)) internal Rng1F32 rng_1f32(F32 min, F32 max); internal Rng1F32 shift_1f32(Rng1F32 r, F32 x); internal Rng1F32 pad_1f32(Rng1F32 r, F32 x); internal F32 center_1f32(Rng1F32 r); internal B32 contains_1f32(Rng1F32 r, F32 x); internal F32 dim_1f32(Rng1F32 r); internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b); internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b); internal F32 clamp_1f32(Rng1F32 r, F32 v); #define r2s16(min, max) rng_2s16((min), (max)) #define r2s16p(x, y, z, w) r2s16(v2s16((x), (y)), v2s16((z), (w))) internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max); internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x); internal Rng2S16 pad_2s16(Rng2S16 r, S16 x); internal Vec2S16 center_2s16(Rng2S16 r); internal B32 contains_2s16(Rng2S16 r, Vec2S16 x); internal Vec2S16 dim_2s16(Rng2S16 r); internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b); internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b); internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v); #define r2s32(min, max) rng_2s32((min), (max)) #define r2s32p(x, y, z, w) r2s32(v2s32((x), (y)), v2s32((z), (w))) internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max); internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x); internal Rng2S32 pad_2s32(Rng2S32 r, S32 x); internal Vec2S32 center_2s32(Rng2S32 r); internal B32 contains_2s32(Rng2S32 r, Vec2S32 x); internal Vec2S32 dim_2s32(Rng2S32 r); internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b); internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b); internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v); #define r2s64(min, max) rng_2s64((min), (max)) #define r2s64p(x, y, z, w) r2s64(v2s64((x), (y)), v2s64((z), (w))) internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max); internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x); internal Rng2S64 pad_2s64(Rng2S64 r, S64 x); internal Vec2S64 center_2s64(Rng2S64 r); internal B32 contains_2s64(Rng2S64 r, Vec2S64 x); internal Vec2S64 dim_2s64(Rng2S64 r); internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b); internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b); internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v); #define r2f32(min, max) rng_2f32((min), (max)) #define r2f32p(x, y, z, w) r2f32(v2f32((x), (y)), v2f32((z), (w))) internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max); internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x); internal Rng2F32 pad_2f32(Rng2F32 r, F32 x); internal Vec2F32 center_2f32(Rng2F32 r); internal B32 contains_2f32(Rng2F32 r, Vec2F32 x); internal Vec2F32 dim_2f32(Rng2F32 r); internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b); internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b); internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v); //////////////////////////////// //~ rjf: Miscellaneous Ops internal Vec3F32 hsv_from_rgb(Vec3F32 rgb); internal Vec3F32 rgb_from_hsv(Vec3F32 hsv); internal Vec4F32 hsva_from_rgba(Vec4F32 rgba); internal Vec4F32 rgba_from_hsva(Vec4F32 hsva); internal Vec4F32 rgba_from_u32(U32 hex); internal U32 u32_from_rgba(Vec4F32 rgba); #define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f } //////////////////////////////// //~ rjf: List Type Functions internal void rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng); internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat); internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list); internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng); internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list); #endif // BASE_MATH_H ================================================ FILE: src/metagen/metagen_base/metagen_base_meta.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Type Info Lookups internal Member * member_from_name(Type *type, String8 name) { Member *member = &member_nil; if(type->members != 0 && name.size != 0) { for(U64 idx = 0; idx < type->count; idx += 1) { if(str8_match(type->members[idx].name, name, 0)) { member = &type->members[idx]; break; } } } return member; } //////////////////////////////// //~ rjf: Type Info * Instance Operations internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr) { Temp scratch = scratch_begin(0, 0); typedef struct RebaseTypeTask RebaseTypeTask; struct RebaseTypeTask { RebaseTypeTask *next; Type *type; U8 *ptr; }; RebaseTypeTask start_task = {0, type, data.str}; RebaseTypeTask *first_task = &start_task; RebaseTypeTask *last_task = first_task; for(RebaseTypeTask *t = first_task; t != 0; t = t->next) { switch(t->type->kind) { default:{}break; case TypeKind_Ptr: if(!(t->type->flags & TypeFlag_IsExternal)) { *(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr)); }break; case TypeKind_Array: { for(U64 idx = 0; idx < t->type->count; idx += 1) { RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); task->type = t->type->direct; task->ptr = t->ptr + t->type->direct->size * idx; SLLQueuePush(first_task, last_task, task); } }break; case TypeKind_Struct: { for(U64 idx = 0; idx < t->type->count; idx += 1) { Member *member = &t->type->members[idx]; RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1); task->type = member->type; task->ptr = t->ptr + member->value; SLLQueuePush(first_task, last_task, task); } }break; } } scratch_end(scratch); } internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; str8_serial_begin(scratch.arena, &strings); { typedef struct SerializeTypeTask SerializeTypeTask; struct SerializeTypeTask { SerializeTypeTask *next; Type *type; U64 count; U8 *src; Type *containing_type; U8 *containing_ptr; B32 is_post_header; }; SerializeTypeTask start_task = {0, type, 1, data.str}; SerializeTypeTask *first_task = &start_task; SerializeTypeTask *last_task = first_task; for(SerializeTypeTask *t = first_task; t != 0; t = t->next) { switch(t->type->kind) { //- rjf: leaf -> just copy the data directly default: if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) { str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); }break; //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise just write as plain data case TypeKind_Ptr: { // rjf: unpack info about this pointer TypeSerializePtrRefInfo *ptr_ref_info = 0; for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) { if(params->ptr_ref_infos[idx].type == t->type->direct) { ptr_ref_info = ¶ms->ptr_ref_infos[idx]; break; } } // rjf: indexification -> subtract base, divide direct size, write index if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size); str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } // rjf: offsetification -> subtract base, write offsets else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base); str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } // rjf: size-by-member (pre-header): still potentially dependent on other members which // delimit our size, so push a new post-header task for pointer. else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type; task->count = t->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; task->is_post_header = 1; SLLQueuePush(first_task, last_task, task); } // rjf: size-by-member (post-header): all flat parts of containing struct have been // iterated, so now we can read the size, & descend to new task to read pointer // destination contents else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) { // rjf: determine count of this pointer U64 count = 0; { Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); } // rjf: push task SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = count; task->src = *(void **)t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); } // rjf: catch-all: write pointer value else { str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); } }break; //- rjf: arrays -> descend to underlying type, + count case TypeKind_Array: { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = t->type->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; //- rjf: struct -> descend to members case TypeKind_Struct: { U64 off = 0; for(U64 idx = 0; idx < t->count; idx += 1) { for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) { if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) { continue; } SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->members[member_idx].type; task->count = 1; task->src = t->src + idx*t->type->size + t->type->members[member_idx].value; task->containing_type = t->type; task->containing_ptr = t->src; SLLQueuePush(first_task, last_task, task); } } }break; //- rjf: enum -> descend to basic type interpretation case TypeKind_Enum: { SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1); task->type = t->type->direct; task->count = t->count; task->src = t->src; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; } } } String8 result = str8_serial_end(arena, &strings); scratch_end(scratch); return result; } internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { String8 result = {0}; result.size = type->size; result.str = push_array(arena, U8, result.size); { Temp scratch = scratch_begin(&arena, 1); typedef struct DeserializeTypeTask DeserializeTypeTask; struct DeserializeTypeTask { DeserializeTypeTask *next; Type *type; U64 count; U8 *dst; Type *containing_type; U8 *containing_ptr; B32 is_post_header; }; U64 read_off = 0; DeserializeTypeTask start_task = {0, type, 1, result.str}; DeserializeTypeTask *first_task = &start_task; DeserializeTypeTask *last_task = first_task; for(DeserializeTypeTask *t = first_task; t != 0; t = t->next) { U8 *t_src = data.str + read_off; switch(t->type->kind) { //- rjf: leaf -> copy the data directly default: if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) { MemoryCopy(t->dst, t_src, t->type->size*t->count); read_off += t->type->size*t->count; }break; //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip case TypeKind_Ptr: { // rjf: unpack info about this pointer TypeSerializePtrRefInfo *ptr_ref_info = 0; for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) { if(params->ptr_ref_infos[idx].type == t->type->direct) { ptr_ref_info = ¶ms->ptr_ref_infos[idx]; break; } } // rjf: indexification -> add base, multiply direct size if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size; MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); read_off += sizeof(ptr_value); } // rjf: offsetification -> subtract base, write offsets else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) { U64 ptr_value = 0; MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base; MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); read_off += sizeof(ptr_value); } // rjf: size-by-member (pre-header): still potentially dependent on other members which // delimit our size, so push a new post-header task for pointer. else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type; task->count = t->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; task->is_post_header = 1; SLLQueuePush(first_task, last_task, task); } // rjf: size-by-member (post-header): all flat parts of containing struct have been // iterated, so now we can read the size, & descend to new task to read pointer // destination contents else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) { // rjf: determine count of this pointer U64 count = 0; { Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); } // rjf: allocate buffer for pointer destination; write address into pointer value slot U64 ptr_dest_buffer_size = (count+1)*t->type->direct->size; U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size); MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer)); // rjf: push task DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = count; task->dst = ptr_dest_buffer; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); } // rjf: catch-all: read pointer value else { MemoryCopy(t->dst, t_src, t->type->size*t->count); read_off += t->type->size*t->count; } }break; //- rjf: arrays -> descend to underlying type, + count case TypeKind_Array: { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = t->type->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; //- rjf: struct -> descend to members case TypeKind_Struct: { for(U64 idx = 0; idx < t->count; idx += 1) { for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) { if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) { continue; } DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->members[member_idx].type; task->count = 1; task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value; task->containing_type = t->type; task->containing_ptr = t->dst; SLLQueuePush(first_task, last_task, task); } } }break; //- rjf: enum -> descend to basic type interpretation case TypeKind_Enum: { DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1); task->type = t->type->direct; task->count = t->count; task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; } } if(params->advance_out != 0) { params->advance_out[0] = read_off; } scratch_end(scratch); } return result; } internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { Temp scratch = scratch_begin(&arena, 1); String8 data_srlz = serialized_from_typed_data(scratch.arena, type, data, params); String8 data_copy = deserialized_from_typed_data(arena, type, data_srlz, params); scratch_end(scratch); return data_copy; } ================================================ FILE: src/metagen/metagen_base/metagen_base_meta.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_META_H #define BASE_META_H //////////////////////////////// //~ rjf: Meta Markup Features #define EmbedFile(name, path) #define TweakB32(name, default) (TWEAK_##name) #define TweakF32(name, default, min, max) (TWEAK_##name) //////////////////////////////// //~ rjf: Tweak Info Tables typedef struct TweakB32Info TweakB32Info; struct TweakB32Info { String8 name; B32 default_value; B32 *value_ptr; }; typedef struct TweakF32Info TweakF32Info; struct TweakF32Info { String8 name; F32 default_value; Rng1F32 value_range; F32 *value_ptr; }; typedef struct TweakB32InfoTable TweakB32InfoTable; struct TweakB32InfoTable { TweakB32Info *v; U64 count; }; typedef struct TweakF32InfoTable TweakF32InfoTable; struct TweakF32InfoTable { TweakF32Info *v; U64 count; }; typedef struct EmbedInfo EmbedInfo; struct EmbedInfo { String8 name; String8 *data; U128 *hash; }; typedef struct EmbedInfoTable EmbedInfoTable; struct EmbedInfoTable { EmbedInfo *v; U64 count; }; //////////////////////////////// //~ rjf: Type Info Types typedef enum TypeKind { TypeKind_Null, // rjf: leaves TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void, TypeKind_U8, TypeKind_U16, TypeKind_U32, TypeKind_U64, TypeKind_S8, TypeKind_S16, TypeKind_S32, TypeKind_S64, TypeKind_B8, TypeKind_B16, TypeKind_B32, TypeKind_B64, TypeKind_F32, TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64, // rjf: operators TypeKind_Ptr, TypeKind_Array, // rjf: user-defined-types TypeKind_Struct, TypeKind_Union, TypeKind_Enum, TypeKind_COUNT } TypeKind; typedef U32 TypeFlags; enum { TypeFlag_IsExternal = (1<<0), TypeFlag_IsPlainText = (1<<1), TypeFlag_IsCodeText = (1<<2), TypeFlag_IsPathText = (1<<3), }; typedef U32 MemberFlags; enum { MemberFlag_DoNotSerialize = (1<<0), }; typedef struct Type Type; typedef struct Member Member; struct Member { String8 name; String8 pretty_name; Type *type; U64 value; MemberFlags flags; }; typedef struct Type Type; struct Type { TypeKind kind; TypeFlags flags; U64 size; Type *direct; String8 name; String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N] U64 count; Member *members; }; //////////////////////////////// //~ rjf: Type Serialization Parameters typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo; struct TypeSerializePtrRefInfo { Type *type; // pointers to this void *indexify_base; // can be indexified using this void *offsetify_base; // can be offsetified using this void *nil_ptr; // is terminal if matching 0 or this }; typedef struct TypeSerializeParams TypeSerializeParams; struct TypeSerializeParams { U64 *advance_out; TypeSerializePtrRefInfo *ptr_ref_infos; U64 ptr_ref_infos_count; }; //////////////////////////////// //~ rjf: Type Name -> Type Info #define type(T) (&T##__type) //////////////////////////////// //~ rjf: Type Info Table Initializer Helpers #define member_lit_comp(S, ti, m, ...) {str8_lit_comp(#m), {0}, (ti), OffsetOf(S, m), __VA_ARGS__} #define struct_members(S) read_only global Member S##__members[] = #define struct_type(S, ...) read_only global Type S##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#S), {0}, ArrayCount(S##__members), S##__members, __VA_ARGS__} #define named_struct_type(name, S, ...) read_only global Type name##__type = {TypeKind_Struct, 0, sizeof(S), &type_nil, str8_lit_comp(#name), {0}, ArrayCount(name##__members), name##__members, __VA_ARGS__} #define ptr_type(name, ti, ...) read_only global Type name = {TypeKind_Ptr, 0, sizeof(void *), (ti), __VA_ARGS__} //////////////////////////////// //~ rjf: Globals read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil}; read_only global Member member_nil = {{0}, {0}, &type_nil}; //////////////////////////////// //~ rjf: Built-In Types //- rjf: leaves read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")}; read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")}; read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")}; read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")}; read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")}; read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")}; read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")}; read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")}; read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")}; read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")}; read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")}; read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")}; read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")}; read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")}; read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")}; read_only global Type *type_kind_type_table[] = { &type_nil, type(void), type(U8), type(U16), type(U32), type(U64), type(S8), type(S16), type(S32), type(S64), type(B8), type(B16), type(B32), type(B64), type(F32), type(F64), &type_nil, &type_nil, &type_nil, &type_nil, &type_nil, }; //- rjf: Rng1U64 struct_members(Rng1U64) { member_lit_comp(Rng1U64, type(U64), min), member_lit_comp(Rng1U64, type(U64), max), }; struct_type(Rng1U64); //- rjf: String8 ptr_type(String8__str_ptr_type, type(U8), str8_lit_comp("size")); struct_members(String8) { member_lit_comp(String8, &String8__str_ptr_type, str), member_lit_comp(String8, type(U64), size), }; struct_type(String8); //- rjf: String8Node extern Type String8Node__type; Type String8Node__ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &String8Node__type}; Member String8Node__members[] = { {str8_lit_comp("next"), {0}, &String8Node__ptr_type, OffsetOf(String8Node, next)}, {str8_lit_comp("string"), {0}, type(String8), OffsetOf(String8Node, string)}, }; Type String8Node__type = { TypeKind_Struct, 0, sizeof(String8Node), &type_nil, str8_lit_comp("String8Node"), {0}, ArrayCount(String8Node__members), String8Node__members, }; //- rjf: String8List Member String8List__members[] = { {str8_lit_comp("first"), {0}, &String8Node__ptr_type, OffsetOf(String8List, first)}, {str8_lit_comp("last"), {0}, &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize}, {str8_lit_comp("node_count"), {0}, type(U64), OffsetOf(String8List, node_count)}, {str8_lit_comp("total_size"), {0}, type(U64), OffsetOf(String8List, total_size)}, }; Type String8List__type = { TypeKind_Struct, 0, sizeof(String8List), &type_nil, str8_lit_comp("String8List"), {0}, ArrayCount(String8List__members), String8List__members, }; //////////////////////////////// //~ rjf: Type Info Lookups internal Member *member_from_name(Type *type, String8 name); #define EachMember(T, it) (Member *it = (type(T))->members; it != 0 && it < (type(T))->members + (type(T))->count; it += 1) //////////////////////////////// //~ rjf: Type Info * Instance Operations internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr); internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); #define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base)) #define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) #define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str #define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str #endif // BASE_META_H ================================================ FILE: src/metagen/metagen_base/metagen_base_profile.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) ================================================ FILE: src/metagen/metagen_base/metagen_base_profile.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_PROFILE_H #define BASE_PROFILE_H //////////////////////////////// //~ rjf: Zero Settings #if !defined(PROFILE_TELEMETRY) # define PROFILE_TELEMETRY 0 #endif #if !defined(MARKUP_LAYER_COLOR) # define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f #endif //////////////////////////////// //~ rjf: Third Party Includes #if PROFILE_TELEMETRY # include "rad_tm.h" # if OS_WINDOWS # pragma comment(lib, "ws2_32.lib") # pragma comment(lib, "rad_tm_win64.lib") # endif #endif //////////////////////////////// //~ rjf: Telemetry Profile Defines #if PROFILE_TELEMETRY # define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__) # define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0) # define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0) # define ProfTick(...) tmTick(0) # define ProfIsCapturing(...) tmRunning() # define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100) # define ProfEndCapture(...) tmClose(0) # define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0) # define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0) # define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__) # define ProfEndLockWait(...) tmEndWaitForLock(0) # define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__) # define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__) # define ProfColor(color) tmZoneColorSticky(color) # define ProfBeginV(...) \ if (TM_API_PTR) { \ static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ Temp scratch = scratch_begin(0,0); \ String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \ scratch_end(scratch); \ } # define ProfNoteV(...) \ if (TM_API_PTR) { \ static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \ Temp scratch = scratch_begin(0,0); \ String8 string = push_str8f(scratch.arena, __VA_ARGS__); \ tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \ hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \ TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \ scratch_end(scratch); \ } #endif //////////////////////////////// //~ rjf: Zeroify Undefined Defines #if !defined(ProfBegin) # define ProfBegin(...) (0) # define ProfBeginDynamic(...) (0) # define ProfEnd(...) (0) # define ProfTick(...) (0) # define ProfIsCapturing(...) (0) # define ProfBeginCapture(...) (0) # define ProfEndCapture(...) (0) # define ProfThreadName(...) (0) # define ProfMsg(...) (0) # define ProfBeginLockWait(...) (0) # define ProfEndLockWait(...) (0) # define ProfLockTake(...) (0) # define ProfLockDrop(...) (0) # define ProfColor(...) (0) # define ProfBeginV(...) (0) # define ProfNoteV(...) (0) #endif //////////////////////////////// //~ rjf: Helper Wrappers #define ProfBeginFunction(...) ProfBegin(this_function_name) #define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd()) #endif // BASE_PROFILE_H ================================================ FILE: src/metagen/metagen_base/metagen_base_strings.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Third Party Includes #if !BUILD_SUPPLEMENTARY_UNIT # define STB_SPRINTF_IMPLEMENTATION # define STB_SPRINTF_STATIC # include "third_party/stb/stb_sprintf.h" #endif //////////////////////////////// //~ NOTE(allen): String <-> Integer Tables read_only global U8 integer_symbols[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', }; // NOTE(allen): Includes reverses for uppercase and lowercase hex. read_only global U8 integer_symbol_reverse[128] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; read_only global U8 base64[64] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '$', }; read_only global U8 base64_reverse[128] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0x00, 0xFF,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32, 0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0xFF,0x3E, 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0xFF,0xFF,0xFF,0xFF,0xFF, }; //////////////////////////////// //~ rjf: Character Classification & Conversion Functions internal B32 char_is_space(U8 c){ return(c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v'); } internal B32 char_is_upper(U8 c){ return('A' <= c && c <= 'Z'); } internal B32 char_is_lower(U8 c){ return('a' <= c && c <= 'z'); } internal B32 char_is_alpha(U8 c){ return(char_is_upper(c) || char_is_lower(c)); } internal B32 char_is_slash(U8 c){ return(c == '/' || c == '\\'); } internal B32 char_is_digit(U8 c, U32 base){ B32 result = 0; if (0 < base && base <= 16){ U8 val = integer_symbol_reverse[c]; if (val < base){ result = 1; } } return(result); } internal U8 char_to_lower(U8 c){ if (char_is_upper(c)){ c += ('a' - 'A'); } return(c); } internal U8 char_to_upper(U8 c){ if (char_is_lower(c)){ c += ('A' - 'a'); } return(c); } internal U8 char_to_correct_slash(U8 c){ if(char_is_slash(c)){ c = '/'; } return(c); } //////////////////////////////// //~ rjf: C-String Measurement internal U64 cstring8_length(U8 *c){ U8 *p = c; for (;*p != 0; p += 1); return(p - c); } internal U64 cstring16_length(U16 *c){ U16 *p = c; for (;*p != 0; p += 1); return(p - c); } internal U64 cstring32_length(U32 *c){ U32 *p = c; for (;*p != 0; p += 1); return(p - c); } //////////////////////////////// //~ rjf: String Constructors internal String8 str8(U8 *str, U64 size){ String8 result = {str, size}; return(result); } internal String8 str8_range(U8 *first, U8 *one_past_last){ String8 result = {first, (U64)(one_past_last - first)}; return(result); } internal String8 str8_zero(void){ String8 result = {0}; return(result); } internal String16 str16(U16 *str, U64 size){ String16 result = {str, size}; return(result); } internal String16 str16_range(U16 *first, U16 *one_past_last){ String16 result = {first, (U64)(one_past_last - first)}; return(result); } internal String16 str16_zero(void){ String16 result = {0}; return(result); } internal String32 str32(U32 *str, U64 size){ String32 result = {str, size}; return(result); } internal String32 str32_range(U32 *first, U32 *one_past_last){ String32 result = {first, (U64)(one_past_last - first)}; return(result); } internal String32 str32_zero(void){ String32 result = {0}; return(result); } internal String8 str8_cstring(char *c){ String8 result = {(U8*)c, cstring8_length((U8*)c)}; return(result); } internal String16 str16_cstring(U16 *c){ String16 result = {(U16*)c, cstring16_length((U16*)c)}; return(result); } internal String32 str32_cstring(U32 *c){ String32 result = {(U32*)c, cstring32_length((U32*)c)}; return(result); } internal String8 str8_cstring_capped(void *cstr, void *cap) { char *ptr = (char *)cstr; char *opl = (char *)cap; for (;ptr < opl && *ptr != 0; ptr += 1); U64 size = (U64)(ptr - (char *)cstr); String8 result = str8((U8*)cstr, size); return result; } internal String16 str16_cstring_capped(void *cstr, void *cap) { U16 *ptr = (U16 *)cstr; U16 *opl = (U16 *)cap; for (;ptr < opl && *ptr != 0; ptr += 1); U64 size = (U64)(ptr - (U16 *)cstr); String16 result = str16(cstr, size); return result; } internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap) { U8 *start = raw_start; U8 *ptr = raw_cap; for(; ptr > start; ) { ptr -= 1; if (*ptr == '\0') { break; } } U64 size = (U64)(ptr - start); String8 result = str8(start, size); return result; } //////////////////////////////// //~ rjf: String Stylization internal String8 upper_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = char_to_upper(string.str[idx]); } return string; } internal String8 lower_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = char_to_lower(string.str[idx]); } return string; } internal String8 backslashed_from_str8(Arena *arena, String8 string) { string = push_str8_copy(arena, string); for(U64 idx = 0; idx < string.size; idx += 1) { string.str[idx] = char_is_slash(string.str[idx]) ? '\\' : string.str[idx]; } return string; } //////////////////////////////// //~ rjf: String Matching internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags) { B32 result = 0; if(a.size == b.size && flags == 0) { result = MemoryMatch(a.str, b.str, b.size); } else if(a.size == b.size || (flags & StringMatchFlag_RightSideSloppy)) { B32 case_insensitive = (flags & StringMatchFlag_CaseInsensitive); B32 slash_insensitive = (flags & StringMatchFlag_SlashInsensitive); U64 size = Min(a.size, b.size); result = 1; for(U64 i = 0; i < size; i += 1) { U8 at = a.str[i]; U8 bt = b.str[i]; if(case_insensitive) { at = char_to_upper(at); bt = char_to_upper(bt); } if(slash_insensitive) { at = char_to_correct_slash(at); bt = char_to_correct_slash(bt); } if(at != bt) { result = 0; break; } } } return result; } internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags){ U8 *p = string.str + start_pos; U64 stop_offset = Max(string.size + 1, needle.size) - needle.size; U8 *stop_p = string.str + stop_offset; if (needle.size > 0){ U8 *string_opl = string.str + string.size; String8 needle_tail = str8_skip(needle, 1); StringMatchFlags adjusted_flags = flags | StringMatchFlag_RightSideSloppy; U8 needle_first_char_adjusted = needle.str[0]; if(adjusted_flags & StringMatchFlag_CaseInsensitive){ needle_first_char_adjusted = char_to_upper(needle_first_char_adjusted); } for (;p < stop_p; p += 1){ U8 haystack_char_adjusted = *p; if(adjusted_flags & StringMatchFlag_CaseInsensitive){ haystack_char_adjusted = char_to_upper(haystack_char_adjusted); } if (haystack_char_adjusted == needle_first_char_adjusted){ if (str8_match(str8_range(p + 1, string_opl), needle_tail, adjusted_flags)){ break; } } } } U64 result = string.size; if (p < stop_p){ result = (U64)(p - string.str); } return(result); } internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags) { U64 result = 0; for(S64 i = string.size - start_pos - needle.size; i >= 0; --i) { String8 haystack = str8_substr(string, rng_1u64(i, i + needle.size)); if(str8_match(haystack, needle, flags)) { result = (U64)i + needle.size; break; } } return result; } internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags){ String8 postfix = str8_postfix(string, end.size); B32 is_match = str8_match(end, postfix, flags); return is_match; } //////////////////////////////// //~ rjf: String Slicing internal String8 str8_substr(String8 str, Rng1U64 range){ range.min = ClampTop(range.min, str.size); range.max = ClampTop(range.max, str.size); str.str += range.min; str.size = dim_1u64(range); return(str); } internal String8 str8_prefix(String8 str, U64 size){ str.size = ClampTop(size, str.size); return(str); } internal String8 str8_skip(String8 str, U64 amt){ amt = ClampTop(amt, str.size); str.str += amt; str.size -= amt; return(str); } internal String8 str8_postfix(String8 str, U64 size){ size = ClampTop(size, str.size); str.str = (str.str + str.size) - size; str.size = size; return(str); } internal String8 str8_chop(String8 str, U64 amt){ amt = ClampTop(amt, str.size); str.size -= amt; return(str); } internal String8 str8_skip_chop_whitespace(String8 string){ U8 *first = string.str; U8 *opl = first + string.size; for (;first < opl; first += 1){ if (!char_is_space(*first)){ break; } } for (;opl > first;){ opl -= 1; if (!char_is_space(*opl)){ opl += 1; break; } } String8 result = str8_range(first, opl); return(result); } //////////////////////////////// //~ rjf: String Formatting & Copying internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2){ String8 str; str.size = s1.size + s2.size; str.str = push_array_no_zero(arena, U8, str.size + 1); MemoryCopy(str.str, s1.str, s1.size); MemoryCopy(str.str + s1.size, s2.str, s2.size); str.str[str.size] = 0; return(str); } internal String8 push_str8_copy(Arena *arena, String8 s){ String8 str; str.size = s.size; str.str = push_array_no_zero(arena, U8, str.size + 1); MemoryCopy(str.str, s.str, s.size); str.str[str.size] = 0; return(str); } internal String8 push_str8fv(Arena *arena, char *fmt, va_list args){ va_list args2; va_copy(args2, args); U32 needed_bytes = raddbg_vsnprintf(0, 0, fmt, args) + 1; String8 result = {0}; result.str = push_array_no_zero(arena, U8, needed_bytes); result.size = raddbg_vsnprintf((char*)result.str, needed_bytes, fmt, args2); result.str[result.size] = 0; va_end(args2); return(result); } internal String8 push_str8f(Arena *arena, char *fmt, ...){ va_list args; va_start(args, fmt); String8 result = push_str8fv(arena, fmt, args); va_end(args); return(result); } //////////////////////////////// //~ rjf: String <=> Integer Conversions //- rjf: string -> integer internal S64 sign_from_str8(String8 string, String8 *string_tail){ // count negative signs U64 neg_count = 0; U64 i = 0; for (; i < string.size; i += 1){ if (string.str[i] == '-'){ neg_count += 1; } else if (string.str[i] != '+'){ break; } } // output part of string after signs *string_tail = str8_skip(string, i); // output integer sign S64 sign = (neg_count & 1)?-1:+1; return(sign); } internal B32 str8_is_integer(String8 string, U32 radix){ B32 result = 0; if (string.size > 0){ if (1 < radix && radix <= 16){ result = 1; for (U64 i = 0; i < string.size; i += 1){ U8 c = string.str[i]; if (!(c < 0x80) || integer_symbol_reverse[c] >= radix){ result = 0; break; } } } } return(result); } internal U64 u64_from_str8(String8 string, U32 radix){ U64 x = 0; if (1 < radix && radix <= 16){ for (U64 i = 0; i < string.size; i += 1){ x *= radix; x += integer_symbol_reverse[string.str[i]&0x7F]; } } return(x); } internal S64 s64_from_str8(String8 string, U32 radix){ S64 sign = sign_from_str8(string, &string); S64 x = (S64)u64_from_str8(string, radix) * sign; return(x); } internal U32 u32_from_str8(String8 string, U32 radix) { U64 x64 = u64_from_str8(string, radix); U32 x32 = safe_cast_u32(x64); return x32; } internal S32 s32_from_str8(String8 string, U32 radix) { S64 x64 = s64_from_str8(string, radix); S32 x32 = safe_cast_s32(x64); return x32; } internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x){ B32 is_integer = 0; if (str8_is_integer(string, 10)){ is_integer = 1; *x = u64_from_str8(string, 10); } else{ String8 hex_string = str8_skip(string, 2); if (str8_match(str8_prefix(string, 2), str8_lit("0x"), 0) && str8_is_integer(hex_string, 0x10)){ is_integer = 1; *x = u64_from_str8(hex_string, 0x10); } else if (str8_match(str8_prefix(string, 2), str8_lit("0b"), 0) && str8_is_integer(hex_string, 2)){ is_integer = 1; *x = u64_from_str8(hex_string, 2); } else{ String8 oct_string = str8_skip(string, 1); if (str8_match(str8_prefix(string, 1), str8_lit("0"), 0) && str8_is_integer(hex_string, 010)){ is_integer = 1; *x = u64_from_str8(oct_string, 010); } } } return(is_integer); } internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x){ String8 string_tail = {0}; S64 sign = sign_from_str8(string, &string_tail); U64 x_u64 = 0; B32 is_integer = try_u64_from_str8_c_rules(string_tail, &x_u64); *x = x_u64*sign; return(is_integer); } //- rjf: integer -> string internal String8 str8_from_memory_size(Arena *arena, U64 size) { String8 result; if(size < KB(1)) { result = push_str8f(arena, "%llu Bytes", size); } else if(size < MB(1)) { result = push_str8f(arena, "%llu.%02llu KiB", size / KB(1), ((size * 100) / KB(1)) % 100); } else if(size < GB(1)) { result = push_str8f(arena, "%llu.%02llu MiB", size / MB(1), ((size * 100) / MB(1)) % 100); } else if(size < TB(1)) { result = push_str8f(arena, "%llu.%02llu GiB", size / GB(1), ((size * 100) / GB(1)) % 100); } else { result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100); } return result; } internal String8 str8_from_count(Arena *arena, U64 count) { String8 result; if(count < 1 * 1000) { result = push_str8f(arena, "%llu", count); } else if(count < 1000000) { U64 frac = ((count * 100) / 1000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluK", count / 1000, frac); } else { result = push_str8f(arena, "%lluK", count / 1000); } } else if(count < 1000000000) { U64 frac = ((count * 100) / 1000000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluM", count / 1000000, frac); } else { result = push_str8f(arena, "%lluM", count / 1000000); } } else { U64 frac = ((count * 100) * 1000000000) % 100; if(frac > 0) { result = push_str8f(arena, "%llu.%02lluB", count / 1000000000, frac); } else { result = push_str8f(arena, "%lluB", count / 1000000000, frac); } } return result; } internal String8 str8_from_bits_u32(Arena *arena, U32 x) { U8 c0 = 'a' + ((x >> 28) & 0xf); U8 c1 = 'a' + ((x >> 24) & 0xf); U8 c2 = 'a' + ((x >> 20) & 0xf); U8 c3 = 'a' + ((x >> 16) & 0xf); U8 c4 = 'a' + ((x >> 12) & 0xf); U8 c5 = 'a' + ((x >> 8) & 0xf); U8 c6 = 'a' + ((x >> 4) & 0xf); U8 c7 = 'a' + ((x >> 0) & 0xf); String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7); return result; } internal String8 str8_from_bits_u64(Arena *arena, U64 x) { U8 c0 = 'a' + ((x >> 60) & 0xf); U8 c1 = 'a' + ((x >> 56) & 0xf); U8 c2 = 'a' + ((x >> 52) & 0xf); U8 c3 = 'a' + ((x >> 48) & 0xf); U8 c4 = 'a' + ((x >> 44) & 0xf); U8 c5 = 'a' + ((x >> 40) & 0xf); U8 c6 = 'a' + ((x >> 36) & 0xf); U8 c7 = 'a' + ((x >> 32) & 0xf); U8 c8 = 'a' + ((x >> 28) & 0xf); U8 c9 = 'a' + ((x >> 24) & 0xf); U8 ca = 'a' + ((x >> 20) & 0xf); U8 cb = 'a' + ((x >> 16) & 0xf); U8 cc = 'a' + ((x >> 12) & 0xf); U8 cd = 'a' + ((x >> 8) & 0xf); U8 ce = 'a' + ((x >> 4) & 0xf); U8 cf = 'a' + ((x >> 0) & 0xf); String8 result = push_str8f(arena, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf); return result; } internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator) { String8 result = {0}; { // rjf: prefix String8 prefix = {0}; switch(radix) { case 16:{prefix = str8_lit("0x");}break; case 8: {prefix = str8_lit("0o");}break; case 2: {prefix = str8_lit("0b");}break; } // rjf: determine # of chars between separators U8 digit_group_size = 3; switch(radix) { default:break; case 2: case 8: case 16: {digit_group_size = 4;}break; } // rjf: prep U64 needed_leading_0s = 0; { U64 needed_digits = 1; { U64 u64_reduce = u64; for(;;) { u64_reduce /= radix; if(u64_reduce == 0) { break; } needed_digits += 1; } } needed_leading_0s = (min_digits > needed_digits) ? min_digits - needed_digits : 0; U64 needed_separators = 0; if(digit_group_separator != 0) { needed_separators = (needed_digits+needed_leading_0s)/digit_group_size; if(needed_separators > 0 && (needed_digits+needed_leading_0s)%digit_group_size == 0) { needed_separators -= 1; } } result.size = prefix.size + needed_leading_0s + needed_separators + needed_digits; result.str = push_array_no_zero(arena, U8, result.size + 1); result.str[result.size] = 0; } // rjf: fill contents { U64 u64_reduce = u64; U64 digits_until_separator = digit_group_size; for(U64 idx = 0; idx < result.size; idx += 1) { if(digits_until_separator == 0 && digit_group_separator != 0) { result.str[result.size - idx - 1] = digit_group_separator; digits_until_separator = digit_group_size+1; } else { result.str[result.size - idx - 1] = char_to_lower(integer_symbols[u64_reduce%radix]); u64_reduce /= radix; } digits_until_separator -= 1; if(u64_reduce == 0) { break; } } for(U64 leading_0_idx = 0; leading_0_idx < needed_leading_0s; leading_0_idx += 1) { result.str[prefix.size + leading_0_idx] = '0'; } } // rjf: fill prefix if(prefix.size != 0) { MemoryCopy(result.str, prefix.str, prefix.size); } } return result; } internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator) { String8 result = {0}; // TODO(rjf): preeeeetty sloppy... if(s64 < 0) { Temp scratch = scratch_begin(&arena, 1); String8 numeric_part = str8_from_u64(scratch.arena, (U64)(-s64), radix, min_digits, digit_group_separator); result = push_str8f(arena, "-%S", numeric_part); scratch_end(scratch); } else { result = str8_from_u64(arena, (U64)s64, radix, min_digits, digit_group_separator); } return result; } //////////////////////////////// //~ rjf: String <=> Float Conversions internal F64 f64_from_str8(String8 string) { // TODO(rjf): crappy implementation for now that just uses atof. F64 result = 0; if(string.size > 0) { // rjf: find starting pos of numeric string, as well as sign F64 sign = +1.0; if(string.str[0] == '-') { sign = -1.0; } else if(string.str[0] == '+') { sign = 1.0; } // rjf: gather numerics U64 num_valid_chars = 0; char buffer[64]; B32 exp = 0; for(U64 idx = 0; idx < string.size && num_valid_chars < sizeof(buffer)-1; idx += 1) { if(char_is_digit(string.str[idx], 10) || string.str[idx] == '.' || string.str[idx] == 'e' || (exp && (string.str[idx] == '+' || string.str[idx] == '-'))) { buffer[num_valid_chars] = string.str[idx]; num_valid_chars += 1; exp = 0; exp = (string.str[idx] == 'e'); } } // rjf: null-terminate (the reason for all of this!!!!!!) buffer[num_valid_chars] = 0; // rjf: do final conversion result = sign * atof(buffer); } return result; } //////////////////////////////// //~ rjf: String List Construction Functions internal String8Node* str8_list_push_node(String8List *list, String8Node *node){ SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size += node->string.size; return(node); } internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string){ SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size += string.size; node->string = string; return(node); } internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node){ SLLQueuePushFront(list->first, list->last, node); list->node_count += 1; list->total_size += node->string.size; return(node); } internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string){ SLLQueuePushFront(list->first, list->last, node); list->node_count += 1; list->total_size += string.size; node->string = string; return(node); } internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string){ String8Node *node = push_array_no_zero(arena, String8Node, 1); str8_list_push_node_set_string(list, node, string); return(node); } internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string){ String8Node *node = push_array_no_zero(arena, String8Node, 1); str8_list_push_node_front_set_string(list, node, string); return(node); } internal void str8_list_concat_in_place(String8List *list, String8List *to_push){ if(to_push->node_count != 0){ if (list->last){ list->node_count += to_push->node_count; list->total_size += to_push->total_size; list->last->next = to_push->first; list->last = to_push->last; } else{ *list = *to_push; } MemoryZeroStruct(to_push); } } internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align){ String8Node *node = push_array_no_zero(arena, String8Node, 1); U64 new_size = list->total_size + min; U64 increase_size = 0; if (align > 1){ // NOTE(allen): assert is power of 2 Assert(((align - 1) & align) == 0); U64 mask = align - 1; new_size += mask; new_size &= (~mask); increase_size = new_size - list->total_size; } local_persist const U8 zeroes_buffer[64] = {0}; Assert(increase_size <= ArrayCount(zeroes_buffer)); SLLQueuePush(list->first, list->last, node); list->node_count += 1; list->total_size = new_size; node->string.str = (U8*)zeroes_buffer; node->string.size = increase_size; return(node); } internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...){ va_list args; va_start(args, fmt); String8 string = push_str8fv(arena, fmt, args); String8Node *result = str8_list_push(arena, list, string); va_end(args); return(result); } internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...){ va_list args; va_start(args, fmt); String8 string = push_str8fv(arena, fmt, args); String8Node *result = str8_list_push_front(arena, list, string); va_end(args); return(result); } internal String8List str8_list_copy(Arena *arena, String8List *list){ String8List result = {0}; for (String8Node *node = list->first; node != 0; node = node->next){ String8Node *new_node = push_array_no_zero(arena, String8Node, 1); String8 new_string = push_str8_copy(arena, node->string); str8_list_push_node_set_string(&result, new_node, new_string); } return(result); } internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags){ String8List list = {0}; B32 keep_empties = (flags & StringSplitFlag_KeepEmpties); U8 *ptr = string.str; U8 *opl = string.str + string.size; for (;ptr < opl;){ U8 *first = ptr; for (;ptr < opl; ptr += 1){ U8 c = *ptr; B32 is_split = 0; for (U64 i = 0; i < split_char_count; i += 1){ if (split_chars[i] == c){ is_split = 1; break; } } if (is_split){ break; } } String8 string = str8_range(first, ptr); if (keep_empties || string.size > 0){ str8_list_push(arena, &list, string); } ptr += 1; } return(list); } internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags){ String8List list = str8_split(arena, string, split_chars.str, split_chars.size, flags); return list; } internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags){ String8List result = {0}; for (String8Node *node = list.first; node != 0; node = node->next){ String8List split = str8_split_by_string_chars(arena, node->string, split_chars, flags); str8_list_concat_in_place(&result, &split); } return result; } internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params){ StringJoin join = {0}; if (optional_params != 0){ MemoryCopyStruct(&join, optional_params); } U64 sep_count = 0; if (list->node_count > 0){ sep_count = list->node_count - 1; } String8 result; result.size = join.pre.size + join.post.size + sep_count*join.sep.size + list->total_size; U8 *ptr = result.str = push_array_no_zero(arena, U8, result.size + 1); MemoryCopy(ptr, join.pre.str, join.pre.size); ptr += join.pre.size; for (String8Node *node = list->first; node != 0; node = node->next){ MemoryCopy(ptr, node->string.str, node->string.size); ptr += node->string.size; if (node->next != 0){ MemoryCopy(ptr, join.sep.str, join.sep.size); ptr += join.sep.size; } } MemoryCopy(ptr, join.post.str, join.post.size); ptr += join.post.size; *ptr = 0; return(result); } internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count){ for (U32 i = 0; i < flag_string_count; i += 1){ U32 flag = (1 << i); if (flags & flag){ str8_list_push(arena, list, flag_string_table[i]); } } } //////////////////////////////// //~ rjf; String Arrays internal String8Array str8_array_from_list(Arena *arena, String8List *list) { String8Array array; array.count = list->node_count; array.v = push_array_no_zero(arena, String8, array.count); U64 idx = 0; for(String8Node *n = list->first; n != 0; n = n->next, idx += 1) { array.v[idx] = n->string; } return array; } internal String8Array str8_array_reserve(Arena *arena, U64 count) { String8Array arr; arr.count = 0; arr.v = push_array(arena, String8, count); return arr; } //////////////////////////////// //~ rjf: String Path Helpers internal String8 str8_chop_last_slash(String8 string){ if (string.size > 0){ U8 *ptr = string.str + string.size - 1; for (;ptr >= string.str; ptr -= 1){ if (*ptr == '/' || *ptr == '\\'){ break; } } if (ptr >= string.str){ string.size = (U64)(ptr - string.str); } else{ string.size = 0; } } return(string); } internal String8 str8_skip_last_slash(String8 string){ if (string.size > 0){ U8 *ptr = string.str + string.size - 1; for (;ptr >= string.str; ptr -= 1){ if (*ptr == '/' || *ptr == '\\'){ break; } } if (ptr >= string.str){ ptr += 1; string.size = (U64)(string.str + string.size - ptr); string.str = ptr; } } return(string); } internal String8 str8_chop_last_dot(String8 string) { String8 result = string; U64 p = string.size; for (;p > 0;){ p -= 1; if (string.str[p] == '.'){ result = str8_prefix(string, p); break; } } return(result); } internal String8 str8_skip_last_dot(String8 string){ String8 result = string; U64 p = string.size; for (;p > 0;){ p -= 1; if (string.str[p] == '.'){ result = str8_skip(string, p + 1); break; } } return(result); } internal PathStyle path_style_from_str8(String8 string){ PathStyle result = PathStyle_Relative; if (string.size >= 1 && string.str[0] == '/'){ result = PathStyle_UnixAbsolute; } else if (string.size >= 2 && char_is_alpha(string.str[0]) && string.str[1] == ':'){ if (string.size == 2 || char_is_slash(string.str[2])){ result = PathStyle_WindowsAbsolute; } } return(result); } internal String8List str8_split_path(Arena *arena, String8 string){ String8List result = str8_split(arena, string, (U8*)"/\\", 2, 0); return(result); } internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){ Temp scratch = scratch_begin(0, 0); String8MetaNode *stack = 0; String8MetaNode *free_meta_node = 0; String8Node *first = path->first; MemoryZeroStruct(path); for (String8Node *node = first, *next = 0; node != 0; node = next){ // save next now next = node->next; // cases: if (node == first && style == PathStyle_WindowsAbsolute){ goto save_without_stack; } if (node->string.size == 1 && node->string.str[0] == '.'){ goto do_nothing; } if (node->string.size == 2 && node->string.str[0] == '.' && node->string.str[1] == '.'){ if (stack != 0){ goto eliminate_stack_top; } else{ goto save_without_stack; } } goto save_with_stack; // handlers: save_with_stack: { str8_list_push_node(path, node); String8MetaNode *stack_node = free_meta_node; if (stack_node != 0){ SLLStackPop(free_meta_node); } else{ stack_node = push_array_no_zero(scratch.arena, String8MetaNode, 1); } SLLStackPush(stack, stack_node); stack_node->node = node; continue; } save_without_stack: { str8_list_push_node(path, node); continue; } eliminate_stack_top: { path->node_count -= 1; path->total_size -= stack->node->string.size; SLLStackPop(stack); if (stack == 0){ path->last = path->first; } else{ path->last = stack->node; } continue; } do_nothing: continue; } scratch_end(scratch); } internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){ StringJoin params = {0}; switch(style) { case PathStyle_Null:{}break; case PathStyle_Relative: case PathStyle_WindowsAbsolute: { params.sep = str8_lit("/"); }break; case PathStyle_UnixAbsolute: { params.pre = str8_lit("/"); params.sep = str8_lit("/"); }break; } String8 result = str8_list_join(arena, path, ¶ms); return result; } internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string) { String8TxtPtPair pair = {0}; { String8 file_part = {0}; String8 line_part = {0}; String8 col_part = {0}; // rjf: grab file part for(U64 idx = 0; idx <= string.size; idx += 1) { U8 byte = (idx < string.size) ? (string.str[idx]) : 0; U8 next_byte = ((idx+1 < string.size) ? (string.str[idx+1]) : 0); if(byte == ':' && next_byte != '/' && next_byte != '\\') { file_part = str8_prefix(string, idx); line_part = str8_skip(string, idx+1); break; } else if(byte == 0) { file_part = string; break; } } // rjf: grab line/column { U64 colon_pos = str8_find_needle(line_part, 0, str8_lit(":"), 0); if(colon_pos < line_part.size) { col_part = str8_skip(line_part, colon_pos+1); line_part = str8_prefix(line_part, colon_pos); } } // rjf: convert line/column strings to numerics U64 line = 0; U64 column = 0; try_u64_from_str8_c_rules(line_part, &line); try_u64_from_str8_c_rules(col_part, &column); // rjf: fill pair.string = file_part; pair.pt = txt_pt((S64)line, (S64)column); if(pair.pt.line == 0) { pair.pt.line = 1; } if(pair.pt.column == 0) { pair.pt.column = 1; } } return pair; } //////////////////////////////// //~ rjf: UTF-8 & UTF-16 Decoding/Encoding read_only global U8 utf8_class[32] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5, }; internal UnicodeDecode utf8_decode(U8 *str, U64 max){ UnicodeDecode result = {1, max_U32}; U8 byte = str[0]; U8 byte_class = utf8_class[byte >> 3]; switch (byte_class) { case 1: { result.codepoint = byte; }break; case 2: { if (2 < max) { U8 cont_byte = str[1]; if (utf8_class[cont_byte >> 3] == 0) { result.codepoint = (byte & bitmask5) << 6; result.codepoint |= (cont_byte & bitmask6); result.inc = 2; } } }break; case 3: { if (2 < max) { U8 cont_byte[2] = {str[1], str[2]}; if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0) { result.codepoint = (byte & bitmask4) << 12; result.codepoint |= ((cont_byte[0] & bitmask6) << 6); result.codepoint |= (cont_byte[1] & bitmask6); result.inc = 3; } } }break; case 4: { if (3 < max) { U8 cont_byte[3] = {str[1], str[2], str[3]}; if (utf8_class[cont_byte[0] >> 3] == 0 && utf8_class[cont_byte[1] >> 3] == 0 && utf8_class[cont_byte[2] >> 3] == 0) { result.codepoint = (byte & bitmask3) << 18; result.codepoint |= ((cont_byte[0] & bitmask6) << 12); result.codepoint |= ((cont_byte[1] & bitmask6) << 6); result.codepoint |= (cont_byte[2] & bitmask6); result.inc = 4; } } } } return(result); } internal UnicodeDecode utf16_decode(U16 *str, U64 max){ UnicodeDecode result = {1, max_U32}; result.codepoint = str[0]; result.inc = 1; if (max > 1 && 0xD800 <= str[0] && str[0] < 0xDC00 && 0xDC00 <= str[1] && str[1] < 0xE000){ result.codepoint = ((str[0] - 0xD800) << 10) | ((str[1] - 0xDC00) + 0x10000); result.inc = 2; } return(result); } internal U32 utf8_encode(U8 *str, U32 codepoint){ U32 inc = 0; if (codepoint <= 0x7F){ str[0] = (U8)codepoint; inc = 1; } else if (codepoint <= 0x7FF){ str[0] = (bitmask2 << 6) | ((codepoint >> 6) & bitmask5); str[1] = bit8 | (codepoint & bitmask6); inc = 2; } else if (codepoint <= 0xFFFF){ str[0] = (bitmask3 << 5) | ((codepoint >> 12) & bitmask4); str[1] = bit8 | ((codepoint >> 6) & bitmask6); str[2] = bit8 | ( codepoint & bitmask6); inc = 3; } else if (codepoint <= 0x10FFFF){ str[0] = (bitmask4 << 4) | ((codepoint >> 18) & bitmask3); str[1] = bit8 | ((codepoint >> 12) & bitmask6); str[2] = bit8 | ((codepoint >> 6) & bitmask6); str[3] = bit8 | ( codepoint & bitmask6); inc = 4; } else{ str[0] = '?'; inc = 1; } return(inc); } internal U32 utf16_encode(U16 *str, U32 codepoint){ U32 inc = 1; if (codepoint == max_U32){ str[0] = (U16)'?'; } else if (codepoint < 0x10000){ str[0] = (U16)codepoint; } else{ U32 v = codepoint - 0x10000; str[0] = safe_cast_u16(0xD800 + (v >> 10)); str[1] = safe_cast_u16(0xDC00 + (v & bitmask10)); inc = 2; } return(inc); } internal U32 utf8_from_utf32_single(U8 *buffer, U32 character){ return(utf8_encode(buffer, character)); } //////////////////////////////// //~ rjf: Unicode String Conversions internal String8 str8_from_16(Arena *arena, String16 in) { String8 result = str8_zero(); if(in.size) { U64 cap = in.size*3; U8 *str = push_array_no_zero(arena, U8, cap + 1); U16 *ptr = in.str; U16 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf16_decode(ptr, opl - ptr); size += utf8_encode(str + size, consume.codepoint); } str[size] = 0; arena_pop(arena, (cap - size)); result = str8(str, size); } return result; } internal String16 str16_from_8(Arena *arena, String8 in) { String16 result = str16_zero(); if(in.size) { U64 cap = in.size*2; U16 *str = push_array_no_zero(arena, U16, cap + 1); U8 *ptr = in.str; U8 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf8_decode(ptr, opl - ptr); size += utf16_encode(str + size, consume.codepoint); } str[size] = 0; arena_pop(arena, (cap - size)*2); result = str16(str, size); } return result; } internal String8 str8_from_32(Arena *arena, String32 in) { String8 result = str8_zero(); if(in.size) { U64 cap = in.size*4; U8 *str = push_array_no_zero(arena, U8, cap + 1); U32 *ptr = in.str; U32 *opl = ptr + in.size; U64 size = 0; for(;ptr < opl; ptr += 1) { size += utf8_encode(str + size, *ptr); } str[size] = 0; arena_pop(arena, (cap - size)); result = str8(str, size); } return result; } internal String32 str32_from_8(Arena *arena, String8 in) { String32 result = str32_zero(); if(in.size) { U64 cap = in.size; U32 *str = push_array_no_zero(arena, U32, cap + 1); U8 *ptr = in.str; U8 *opl = ptr + in.size; U64 size = 0; UnicodeDecode consume; for(;ptr < opl; ptr += consume.inc) { consume = utf8_decode(ptr, opl - ptr); str[size] = consume.codepoint; size += 1; } str[size] = 0; arena_pop(arena, (cap - size)*4); result = str32(str, size); } return result; } //////////////////////////////// //~ String -> Enum Conversions read_only global struct { String8 string; OperatingSystem os; } g_os_enum_map[] = { { str8_lit_comp(""), OperatingSystem_Null }, { str8_lit_comp("Windows"), OperatingSystem_Windows, }, { str8_lit_comp("Linux"), OperatingSystem_Linux, }, { str8_lit_comp("Mac"), OperatingSystem_Mac, }, }; StaticAssert(ArrayCount(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check); internal OperatingSystem operating_system_from_string(String8 string) { for(U64 i = 0; i < ArrayCount(g_os_enum_map); ++i) { if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive)) { return g_os_enum_map[i].os; } } return OperatingSystem_Null; } //////////////////////////////// //~ rjf: Basic Types & Space Enum -> String Conversions internal String8 string_from_dimension(Dimension dimension){ local_persist String8 strings[] = { str8_lit_comp("X"), str8_lit_comp("Y"), str8_lit_comp("Z"), str8_lit_comp("W"), }; String8 result = str8_lit("error"); if ((U32)dimension < 4){ result = strings[dimension]; } return(result); } internal String8 string_from_side(Side side){ local_persist String8 strings[] = { str8_lit_comp("Min"), str8_lit_comp("Max"), }; String8 result = str8_lit("error"); if ((U32)side < 2){ result = strings[side]; } return(result); } internal String8 string_from_operating_system(OperatingSystem os) { String8 result = g_os_enum_map[OperatingSystem_Null].string; if(os < ArrayCount(g_os_enum_map)) { result = g_os_enum_map[os].string; } return result; } internal String8 string_from_arch(Arch arch){ local_persist String8 strings[] = { str8_lit_comp("Null"), str8_lit_comp("x64"), str8_lit_comp("x86"), str8_lit_comp("arm64"), str8_lit_comp("arm32"), }; String8 result = str8_lit("error"); if (arch < Arch_COUNT){ result = strings[arch]; } return(result); } //////////////////////////////// //~ rjf: Time Types -> String internal String8 string_from_week_day(WeekDay week_day){ local_persist String8 strings[] = { str8_lit_comp("Sun"), str8_lit_comp("Mon"), str8_lit_comp("Tue"), str8_lit_comp("Wed"), str8_lit_comp("Thu"), str8_lit_comp("Fri"), str8_lit_comp("Sat"), }; String8 result = str8_lit("Err"); if ((U32)week_day < WeekDay_COUNT){ result = strings[week_day]; } return(result); } internal String8 string_from_month(Month month){ local_persist String8 strings[] = { str8_lit_comp("Jan"), str8_lit_comp("Feb"), str8_lit_comp("Mar"), str8_lit_comp("Apr"), str8_lit_comp("May"), str8_lit_comp("Jun"), str8_lit_comp("Jul"), str8_lit_comp("Aug"), str8_lit_comp("Sep"), str8_lit_comp("Oct"), str8_lit_comp("Nov"), str8_lit_comp("Dec"), }; String8 result = str8_lit("Err"); if ((U32)month < Month_COUNT){ result = strings[month]; } return(result); } internal String8 push_date_time_string(Arena *arena, DateTime *date_time){ char *mon_str = (char*)string_from_month(date_time->month).str; U32 adjusted_hour = date_time->hour%12; if (adjusted_hour == 0){ adjusted_hour = 12; } char *ampm = "am"; if (date_time->hour >= 12){ ampm = "pm"; } String8 result = push_str8f(arena, "%d %s %d, %02d:%02d:%02d %s", date_time->day, mon_str, date_time->year, adjusted_hour, date_time->min, date_time->sec, ampm); return(result); } internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time){ char *mon_str = (char*)string_from_month(date_time->month).str; String8 result = push_str8f(arena, "%d-%s-%0d--%02d-%02d-%02d", date_time->year, mon_str, date_time->day, date_time->hour, date_time->min, date_time->sec); return(result); } internal String8 string_from_elapsed_time(Arena *arena, DateTime dt){ Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; if (dt.year){ str8_list_pushf(scratch.arena, &list, "%dy", dt.year); str8_list_pushf(scratch.arena, &list, "%um", dt.mon); str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } else if (dt.mon){ str8_list_pushf(scratch.arena, &list, "%um", dt.mon); str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } else if (dt.day){ str8_list_pushf(scratch.arena, &list, "%ud", dt.day); } str8_list_pushf(scratch.arena, &list, "%u:%u:%u:%u ms", dt.hour, dt.min, dt.sec, dt.msec); StringJoin join = { str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }; String8 result = str8_list_join(arena, &list, &join); scratch_end(scratch); return(result); } //////////////////////////////// //~ Globally UNique Ids internal String8 string_from_guid(Arena *arena, Guid guid) { String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7]); return result; } internal B32 try_guid_from_string(String8 string, Guid *guid_out) { Temp scratch = scratch_begin(0,0); B32 is_parsed = 0; String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties); if(list.node_count == 5) { String8 data1_str = list.first->string; String8 data2_str = list.first->next->string; String8 data3_str = list.first->next->next->string; String8 data4_hi_str = list.first->next->next->next->string; String8 data4_lo_str = list.first->next->next->next->next->string; if(str8_is_integer(data1_str, 16) && str8_is_integer(data2_str, 16) && str8_is_integer(data3_str, 16) && str8_is_integer(data4_hi_str, 16) && str8_is_integer(data4_lo_str, 16)) { U64 data1 = u64_from_str8(data1_str, 16); U64 data2 = u64_from_str8(data2_str, 16); U64 data3 = u64_from_str8(data3_str, 16); U64 data4_hi = u64_from_str8(data4_hi_str, 16); U64 data4_lo = u64_from_str8(data4_lo_str, 16); if(data1 <= max_U32 && data2 <= max_U16 && data3 <= max_U16 && data4_hi <= max_U16 && data4_lo <= 0xffffffffffff) { guid_out->data1 = (U32)data1; guid_out->data2 = (U16)data2; guid_out->data3 = (U16)data3; U64 data4 = (data4_hi << 48) | data4_lo; MemoryCopy(&guid_out->data4[0], &data4, sizeof(data4)); is_parsed = 1; } } } scratch_end(scratch); return is_parsed; } internal Guid guid_from_string(String8 string) { Guid guid = {0}; try_guid_from_string(string, &guid); return guid; } //////////////////////////////// //~ rjf: Basic Text Indentation internal String8 indented_from_string(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); read_only local_persist U8 indentation_bytes[] = " "; String8List indented_strings = {0}; S64 depth = 0; S64 next_depth = 0; U64 line_begin_off = 0; for(U64 off = 0; off <= string.size; off += 1) { U8 byte = off width_this_line){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); line_range = r1u64(line_range.max+1, candidate_line_range.max); wrapped_indent_level = ClampTop(64, wrap_indent); } else{ line_range = candidate_line_range; } } } if (line_range.min < string.size && line_range.max > line_range.min){ String8 line = str8_substr(string, line_range); if (wrapped_indent_level > 0){ line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); } str8_list_push(arena, &list, line); } return list; } //////////////////////////////// //~ rjf: String <-> Color internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba) { String8 hex_string = push_str8f(arena, "%02x%02x%02x%02x", (U8)(rgba.x*255.f), (U8)(rgba.y*255.f), (U8)(rgba.z*255.f), (U8)(rgba.w*255.f)); return hex_string; } internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string) { U8 byte_text[8] = {0}; U64 byte_text_idx = 0; for(U64 idx = 0; idx < hex_string.size && byte_text_idx < ArrayCount(byte_text); idx += 1) { if(char_is_digit(hex_string.str[idx], 16)) { byte_text[byte_text_idx] = char_to_lower(hex_string.str[idx]); byte_text_idx += 1; } } U8 byte_vals[4] = {0}; for(U64 idx = 0; idx < 4; idx += 1) { byte_vals[idx] = (U8)u64_from_str8(str8(&byte_text[idx*2], 2), 16); } Vec4F32 rgba = v4f32(byte_vals[0]/255.f, byte_vals[1]/255.f, byte_vals[2]/255.f, byte_vals[3]/255.f); return rgba; } //////////////////////////////// //~ rjf: String Fuzzy Matching internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack) { FuzzyMatchRangeList result = {0}; Temp scratch = scratch_begin(&arena, 1); String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0); result.needle_part_count = needles.node_count; for(String8Node *needle_n = needles.first; needle_n != 0; needle_n = needle_n->next) { U64 find_pos = 0; for(;find_pos < haystack.size;) { find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive); B32 is_in_gathered_ranges = 0; for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next) { if(n->range.min <= find_pos && find_pos < n->range.max) { is_in_gathered_ranges = 1; find_pos = n->range.max; break; } } if(!is_in_gathered_ranges) { break; } } if(find_pos < haystack.size) { Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size); FuzzyMatchRangeNode *n = push_array(arena, FuzzyMatchRangeNode, 1); n->range = range; SLLQueuePush(result.first, result.last, n); result.count += 1; result.total_dim += dim_1u64(range); } } scratch_end(scratch); return result; } internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src) { FuzzyMatchRangeList dst = {0}; for(FuzzyMatchRangeNode *src_n = src->first; src_n != 0; src_n = src_n->next) { FuzzyMatchRangeNode *dst_n = push_array(arena, FuzzyMatchRangeNode, 1); SLLQueuePush(dst.first, dst.last, dst_n); dst_n->range = src_n->range; } dst.count = src->count; dst.needle_part_count = src->needle_part_count; dst.total_dim = src->total_dim; return dst; } //////////////////////////////// //~ NOTE(allen): Serialization Helpers internal void str8_serial_begin(Arena *arena, String8List *srl){ String8Node *node = push_array(arena, String8Node, 1); node->string.str = push_array_no_zero(arena, U8, 0); srl->first = srl->last = node; srl->node_count = 1; srl->total_size = 0; } internal String8 str8_serial_end(Arena *arena, String8List *srl){ U64 size = srl->total_size; U8 *out = push_array_no_zero(arena, U8, size); str8_serial_write_to_dst(srl, out); String8 result = str8(out, size); return result; } internal void str8_serial_write_to_dst(String8List *srl, void *out){ U8 *ptr = (U8*)out; for (String8Node *node = srl->first; node != 0; node = node->next){ U64 size = node->string.size; MemoryCopy(ptr, node->string.str, size); ptr += size; } } internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align){ Assert(IsPow2(align)); U64 pos = srl->total_size; U64 new_pos = AlignPow2(pos, align); U64 size = (new_pos - pos); if(size != 0) { U8 *buf = push_array(arena, U8, size); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += size; srl->total_size += size; } else{ str8_list_push(arena, srl, str8(buf, size)); } } return size; } internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size) { void *result = 0; if(size != 0) { U8 *buf = push_array_no_zero(arena, U8, size); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += size; srl->total_size += size; } else{ str8_list_push(arena, srl, str8(buf, size)); } result = buf; } return result; } internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size){ void *result = str8_serial_push_size(arena, srl, size); if(result != 0) { MemoryCopy(result, data, size); } return result; } internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first){ for (String8Node *node = first; node != 0; node = node->next){ str8_serial_push_data(arena, srl, node->string.str, node->string.size); } } internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x){ U8 *buf = push_array_no_zero(arena, U8, 8); MemoryCopy(buf, &x, 8); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += 8; srl->total_size += 8; } else{ str8_list_push(arena, srl, str8(buf, 8)); } } internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x){ U8 *buf = push_array_no_zero(arena, U8, 4); MemoryCopy(buf, &x, 4); String8 *str = &srl->last->string; if (str->str + str->size == buf){ srl->last->string.size += 4; srl->total_size += 4; } else{ str8_list_push(arena, srl, str8(buf, 4)); } } internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x){ str8_serial_push_data(arena, srl, &x, sizeof(x)); } internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x){ str8_serial_push_data(arena, srl, &x, sizeof(x)); } internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str){ str8_serial_push_data(arena, srl, str.str, str.size); str8_serial_push_u8(arena, srl, 0); } internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str){ str8_serial_push_data(arena, srl, str.str, str.size); } //////////////////////////////// //~ rjf: Deserialization Helpers internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity) { U64 bytes_left = string.size-Min(off, string.size); U64 actually_readable_size = Min(bytes_left, read_size); U64 legally_readable_size = actually_readable_size - actually_readable_size%granularity; if(legally_readable_size > 0) { MemoryCopy(read_dst, string.str+off, legally_readable_size); } return legally_readable_size; } internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val) { U64 cursor = off; for (;;) { U16 val = 0; str8_deserial_read_struct(string, cursor, &val); if (val == scan_val) { break; } cursor += sizeof(val); } return cursor; } internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size) { void *raw_ptr = 0; if (off + size <= string.size) { raw_ptr = string.str + off; } return raw_ptr; } internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out) { U64 cstr_size = 0; if (off < string.size) { U8 *ptr = string.str + off; U8 *cap = string.str + string.size; *cstr_out = str8_cstring_capped(ptr, cap); cstr_size = (cstr_out->size + 1); } return cstr_size; } internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out) { U64 null_off = str8_deserial_find_first_match(string, off, 0); U64 size = null_off - off; U16 *str = (U16 *)str8_deserial_get_raw_ptr(string, off, size); U64 count = size / sizeof(*str); *str_out = str16(str, count); U64 read_size_with_null = size + sizeof(*str); return read_size_with_null; } internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out) { Rng1U64 range = rng_1u64(off, off + size); *block_out = str8_substr(string, range); return block_out->size; } internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out) { U64 value = 0; U64 shift = 0; U64 cursor = off; for(;;) { U8 byte = 0; U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); if(bytes_read != sizeof(byte)) { break; } U8 val = byte & 0x7fu; value |= ((U64)val) << shift; cursor += bytes_read; shift += 7u; if((byte & 0x80u) == 0) { break; } } if(value_out != 0) { *value_out = value; } U64 bytes_read = cursor - off; return bytes_read; } internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out) { U64 value = 0; U64 shift = 0; U64 cursor = off; for(;;) { U8 byte; U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); if(bytes_read != sizeof(byte)) { break; } U8 val = byte & 0x7fu; value |= ((U64)val) << shift; cursor += bytes_read; shift += 7u; if((byte & 0x80u) == 0) { if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0) { value |= -(S64)(1ull << shift); } break; } } if(value_out != 0) { *value_out = value; } U64 bytes_read = cursor - off; return bytes_read; } ================================================ FILE: src/metagen/metagen_base/metagen_base_strings.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_STRINGS_H #define BASE_STRINGS_H //////////////////////////////// //~ rjf: Third Party Includes #define STB_SPRINTF_DECORATE(name) raddbg_##name #include "third_party/stb/stb_sprintf.h" //////////////////////////////// //~ rjf: String Types typedef struct String8 String8; struct String8 { U8 *str; U64 size; }; typedef struct String16 String16; struct String16 { U16 *str; U64 size; }; typedef struct String32 String32; struct String32 { U32 *str; U64 size; }; //////////////////////////////// //~ rjf: String List & Array Types typedef struct String8Node String8Node; struct String8Node { String8Node *next; String8 string; }; typedef struct String8MetaNode String8MetaNode; struct String8MetaNode { String8MetaNode *next; String8Node *node; }; typedef struct String8List String8List; struct String8List { String8Node *first; String8Node *last; U64 node_count; U64 total_size; }; typedef struct String8Array String8Array; struct String8Array { String8 *v; U64 count; }; //////////////////////////////// //~ rjf: String Matching, Splitting, & Joining Types typedef U32 StringMatchFlags; enum { StringMatchFlag_CaseInsensitive = (1 << 0), StringMatchFlag_RightSideSloppy = (1 << 1), StringMatchFlag_SlashInsensitive = (1 << 2), }; typedef U32 StringSplitFlags; enum { StringSplitFlag_KeepEmpties = (1 << 0), }; typedef enum PathStyle { PathStyle_Null, PathStyle_Relative, PathStyle_WindowsAbsolute, PathStyle_UnixAbsolute, #if OS_WINDOWS PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute #elif OS_LINUX PathStyle_SystemAbsolute = PathStyle_UnixAbsolute #else # error "absolute path style is undefined for this OS" #endif } PathStyle; typedef struct StringJoin StringJoin; struct StringJoin { String8 pre; String8 sep; String8 post; }; //////////////////////////////// //~ rjf: String Pair Types typedef struct String8TxtPtPair String8TxtPtPair; struct String8TxtPtPair { String8 string; TxtPt pt; }; //////////////////////////////// //~ rjf: UTF Decoding Types typedef struct UnicodeDecode UnicodeDecode; struct UnicodeDecode { U32 inc; U32 codepoint; }; //////////////////////////////// //~ rjf: String Fuzzy Matching Types typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode; struct FuzzyMatchRangeNode { FuzzyMatchRangeNode *next; Rng1U64 range; }; typedef struct FuzzyMatchRangeList FuzzyMatchRangeList; struct FuzzyMatchRangeList { FuzzyMatchRangeNode *first; FuzzyMatchRangeNode *last; U64 count; U64 needle_part_count; U64 total_dim; }; //////////////////////////////// //~ rjf: Character Classification & Conversion Functions internal B32 char_is_space(U8 c); internal B32 char_is_upper(U8 c); internal B32 char_is_lower(U8 c); internal B32 char_is_alpha(U8 c); internal B32 char_is_slash(U8 c); internal B32 char_is_digit(U8 c, U32 base); internal U8 char_to_lower(U8 c); internal U8 char_to_upper(U8 c); internal U8 char_to_correct_slash(U8 c); //////////////////////////////// //~ rjf: C-String Measurement internal U64 cstring8_length(U8 *c); internal U64 cstring16_length(U16 *c); internal U64 cstring32_length(U32 *c); //////////////////////////////// //~ rjf: String Constructors #define str8_lit(S) str8((U8*)(S), sizeof(S) - 1) #define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,} #define str8_varg(S) (int)((S).size), ((S).str) #define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C)) #define str8_array_fixed(S) str8((U8*)(S), sizeof(S)) #define str8_struct(S) str8((U8*)(S), sizeof(*(S))) internal String8 str8(U8 *str, U64 size); internal String8 str8_range(U8 *first, U8 *one_past_last); internal String8 str8_zero(void); internal String16 str16(U16 *str, U64 size); internal String16 str16_range(U16 *first, U16 *one_past_last); internal String16 str16_zero(void); internal String32 str32(U32 *str, U64 size); internal String32 str32_range(U32 *first, U32 *one_past_last); internal String32 str32_zero(void); internal String8 str8_cstring(char *c); internal String16 str16_cstring(U16 *c); internal String32 str32_cstring(U32 *c); internal String8 str8_cstring_capped(void *cstr, void *cap); internal String16 str16_cstring_capped(void *cstr, void *cap); internal String8 str8_cstring_capped_reverse(void *raw_start, void *raw_cap); //////////////////////////////// //~ rjf: String Stylization internal String8 upper_from_str8(Arena *arena, String8 string); internal String8 lower_from_str8(Arena *arena, String8 string); internal String8 backslashed_from_str8(Arena *arena, String8 string); //////////////////////////////// //~ rjf: String Matching internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags); internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal U64 str8_find_needle_reverse(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags); internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags); //////////////////////////////// //~ rjf: String Slicing internal String8 str8_substr(String8 str, Rng1U64 range); internal String8 str8_prefix(String8 str, U64 size); internal String8 str8_skip(String8 str, U64 amt); internal String8 str8_postfix(String8 str, U64 size); internal String8 str8_chop(String8 str, U64 amt); internal String8 str8_skip_chop_whitespace(String8 string); //////////////////////////////// //~ rjf: String Formatting & Copying internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2); internal String8 push_str8_copy(Arena *arena, String8 s); internal String8 push_str8fv(Arena *arena, char *fmt, va_list args); internal String8 push_str8f(Arena *arena, char *fmt, ...); //////////////////////////////// //~ rjf: String <=> Integer Conversions //- rjf: string -> integer internal S64 sign_from_str8(String8 string, String8 *string_tail); internal B32 str8_is_integer(String8 string, U32 radix); internal U64 u64_from_str8(String8 string, U32 radix); internal S64 s64_from_str8(String8 string, U32 radix); internal U32 u32_from_str8(String8 string, U32 radix); internal S32 s32_from_str8(String8 string, U32 radix); internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x); internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x); //- rjf: integer -> string internal String8 str8_from_memory_size(Arena *arena, U64 size); internal String8 str8_from_count(Arena *arena, U64 count); internal String8 str8_from_bits_u32(Arena *arena, U32 x); internal String8 str8_from_bits_u64(Arena *arena, U64 x); internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator); internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator); //////////////////////////////// //~ rjf: String <=> Float Conversions internal F64 f64_from_str8(String8 string); //////////////////////////////// //~ rjf: String List Construction Functions internal String8Node* str8_list_push_node(String8List *list, String8Node *node); internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string); internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node); internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string); internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string); internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string); internal void str8_list_concat_in_place(String8List *list, String8List *to_push); internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align); internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...); internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...); internal String8List str8_list_copy(Arena *arena, String8List *list); #define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero()) //////////////////////////////// //~ rjf: String Splitting & Joining internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags); internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags); internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags); internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params); internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count); //////////////////////////////// //~ rjf; String Arrays internal String8Array str8_array_from_list(Arena *arena, String8List *list); internal String8Array str8_array_reserve(Arena *arena, U64 count); //////////////////////////////// //~ rjf: String Path Helpers internal String8 str8_chop_last_slash(String8 string); internal String8 str8_skip_last_slash(String8 string); internal String8 str8_chop_last_dot(String8 string); internal String8 str8_skip_last_dot(String8 string); internal PathStyle path_style_from_str8(String8 string); internal String8List str8_split_path(Arena *arena, String8 string); internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style); internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style); internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string); //////////////////////////////// //~ rjf: UTF-8 & UTF-16 Decoding/Encoding internal UnicodeDecode utf8_decode(U8 *str, U64 max); internal UnicodeDecode utf16_decode(U16 *str, U64 max); internal U32 utf8_encode(U8 *str, U32 codepoint); internal U32 utf16_encode(U16 *str, U32 codepoint); internal U32 utf8_from_utf32_single(U8 *buffer, U32 character); //////////////////////////////// //~ rjf: Unicode String Conversions internal String8 str8_from_16(Arena *arena, String16 in); internal String16 str16_from_8(Arena *arena, String8 in); internal String8 str8_from_32(Arena *arena, String32 in); internal String32 str32_from_8(Arena *arena, String8 in); //////////////////////////////// //~ String -> Enum Conversions internal OperatingSystem operating_system_from_string(String8 string); //////////////////////////////// //~ rjf: Basic Types & Space Enum -> String Conversions internal String8 string_from_dimension(Dimension dimension); internal String8 string_from_side(Side side); internal String8 string_from_operating_system(OperatingSystem os); internal String8 string_from_arch(Arch arch); //////////////////////////////// //~ rjf: Time Types -> String internal String8 string_from_week_day(WeekDay week_day); internal String8 string_from_month(Month month); internal String8 push_date_time_string(Arena *arena, DateTime *date_time); internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time); internal String8 string_from_elapsed_time(Arena *arena, DateTime dt); //////////////////////////////// //~ Globally Unique Ids internal String8 string_from_guid(Arena *arena, Guid guid); internal B32 try_guid_from_string(String8 string, Guid *guid_out); internal Guid guid_from_string(String8 string); //////////////////////////////// //~ rjf: Basic Text Indentation internal String8 indented_from_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Text Escaping internal String8 escaped_from_raw_str8(Arena *arena, String8 string); internal String8 raw_from_escaped_str8(Arena *arena, String8 string); //////////////////////////////// //~ rjf: Text Wrapping internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); //////////////////////////////// //~ rjf: String <-> Color internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba); internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string); //////////////////////////////// //~ rjf: String Fuzzy Matching internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack); internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src); //////////////////////////////// //~ NOTE(allen): Serialization Helpers internal void str8_serial_begin(Arena *arena, String8List *srl); internal String8 str8_serial_end(Arena *arena, String8List *srl); internal void str8_serial_write_to_dst(String8List *srl, void *out); internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align); internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size); internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size); internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first); internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x); internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x); internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x); internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x); internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str); internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str); #define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count)) #define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1) //////////////////////////////// //~ rjf: Deserialization Helpers internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity); internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val); internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size); internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out); internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out); internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out); internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out); internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out); #define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr))) #define str8_deserial_read_struct(string, off, ptr) str8_deserial_read_array(string, off, ptr, 1) #endif // BASE_STRINGS_H ================================================ FILE: src/metagen/metagen_base/metagen_base_thread_context.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// // NOTE(allen): Thread Context Functions C_LINKAGE thread_static TCTX* tctx_thread_local; #if !BUILD_SUPPLEMENTARY_UNIT C_LINKAGE thread_static TCTX* tctx_thread_local = 0; #endif internal void tctx_init_and_equip(TCTX *tctx){ MemoryZeroStruct(tctx); Arena **arena_ptr = tctx->arenas; for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ *arena_ptr = arena_alloc(); } tctx_thread_local = tctx; } internal void tctx_release(void) { for(U64 i = 0; i < ArrayCount(tctx_thread_local->arenas); i += 1) { arena_release(tctx_thread_local->arenas[i]); } } internal TCTX* tctx_get_equipped(void){ return(tctx_thread_local); } internal Arena* tctx_get_scratch(Arena **conflicts, U64 count){ TCTX *tctx = tctx_get_equipped(); Arena *result = 0; Arena **arena_ptr = tctx->arenas; for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ Arena **conflict_ptr = conflicts; B32 has_conflict = 0; for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){ if (*arena_ptr == *conflict_ptr){ has_conflict = 1; break; } } if (!has_conflict){ result = *arena_ptr; break; } } return(result); } internal void tctx_set_thread_name(String8 string){ TCTX *tctx = tctx_get_equipped(); U64 size = ClampTop(string.size, sizeof(tctx->thread_name)); MemoryCopy(tctx->thread_name, string.str, size); tctx->thread_name_size = size; } internal String8 tctx_get_thread_name(void){ TCTX *tctx = tctx_get_equipped(); String8 result = str8(tctx->thread_name, tctx->thread_name_size); return(result); } internal void tctx_write_srcloc(char *file_name, U64 line_number){ TCTX *tctx = tctx_get_equipped(); tctx->file_name = file_name; tctx->line_number = line_number; } internal void tctx_read_srcloc(char **file_name, U64 *line_number){ TCTX *tctx = tctx_get_equipped(); *file_name = tctx->file_name; *line_number = tctx->line_number; } ================================================ FILE: src/metagen/metagen_base/metagen_base_thread_context.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_THREAD_CONTEXT_H #define BASE_THREAD_CONTEXT_H //////////////////////////////// // NOTE(allen): Thread Context typedef struct TCTX TCTX; struct TCTX { Arena *arenas[2]; U8 thread_name[32]; U64 thread_name_size; char *file_name; U64 line_number; }; //////////////////////////////// // NOTE(allen): Thread Context Functions internal void tctx_init_and_equip(TCTX *tctx); internal void tctx_release(void); internal TCTX* tctx_get_equipped(void); internal Arena* tctx_get_scratch(Arena **conflicts, U64 countt); internal void tctx_set_thread_name(String8 name); internal String8 tctx_get_thread_name(void); internal void tctx_write_srcloc(char *file_name, U64 line_number); internal void tctx_read_srcloc(char **file_name, U64 *line_number); #define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__) #define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count))) #define scratch_end(scratch) temp_end(scratch) #endif // BASE_THREAD_CONTEXT_H ================================================ FILE: src/metagen/metagen_main.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Build Options #define BUILD_CONSOLE_INTERFACE 1 //////////////////////////////// //~ rjf: Includes //- rjf: headers #include "metagen/metagen_base/metagen_base_inc.h" #include "metagen/metagen_os/metagen_os_inc.h" #include "mdesk/mdesk.h" #include "metagen.h" //- rjf: impls #include "metagen/metagen_base/metagen_base_inc.c" #include "metagen/metagen_os/metagen_os_inc.c" #include "mdesk/mdesk.c" #include "metagen.c" //////////////////////////////// //~ rjf: Entry Point internal void entry_point(CmdLine *cmdline) { ////////////////////////////// //- rjf: set up state // MG_MsgList msgs = {0}; mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64)); mg_state = push_array(mg_arena, MG_State, 1); mg_state->slots_count = 256; mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count); ////////////////////////////// //- rjf: extract paths // String8 build_dir_path = os_get_process_info()->binary_path; String8 project_dir_path = str8_chop_last_slash(build_dir_path); String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path); ////////////////////////////// //- rjf: search code directories for all files to consider // String8List file_paths = {0}; DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count)) { typedef struct Task Task; struct Task { Task *next; String8 path; }; Task start_task = {0, code_dir_path}; Task *first_task = &start_task; Task *last_task = &start_task; for(Task *task = first_task; task != 0; task = task->next) { OS_FileIter *it = os_file_iter_begin(mg_arena, task->path, 0); for(OS_FileInfo info = {0}; os_file_iter_next(mg_arena, it, &info);) { String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name); if(info.props.flags & FilePropertyFlag_IsFolder) { Task *next_task = push_array(mg_arena, Task, 1); SLLQueuePush(first_task, last_task, next_task); next_task->path = file_path; } else { str8_list_push(mg_arena, &file_paths, file_path); } } os_file_iter_end(it); } } ////////////////////////////// //- rjf: parse all metadesk files // MG_FileParseList parses = {0}; DeferLoop(printf("parsing metadesk..."), printf(" %i metadesk files parsed\n", (int)parses.count)) { for(String8Node *n = file_paths.first; n != 0; n = n->next) { String8 file_path = n->string; String8 file_ext = str8_skip_last_dot(file_path); if(str8_match(file_ext, str8_lit("mdesk"), 0)) { String8 data = os_data_from_file_path(mg_arena, file_path); MD_TokenizeResult tokenize = md_tokenize_from_text(mg_arena, data); MD_ParseResult parse = md_parse_from_text_tokens(mg_arena, file_path, data, tokenize.tokens); for(MD_Msg *m = parse.msgs.first; m != 0; m = m->next) { TxtPt pt = mg_txt_pt_from_string_off(data, m->node->src_offset); String8 msg_kind_string = {0}; switch(m->kind) { default:{}break; case MD_MsgKind_Note: {msg_kind_string = str8_lit("note");}break; case MD_MsgKind_Warning: {msg_kind_string = str8_lit("warning");}break; case MD_MsgKind_Error: {msg_kind_string = str8_lit("error");}break; case MD_MsgKind_FatalError: {msg_kind_string = str8_lit("fatal error");}break; } String8 location = push_str8f(mg_arena, "%S:%I64d:%I64d", file_path, pt.line, pt.column); MG_Msg dst_m = {location, msg_kind_string, m->string}; mg_msg_list_push(mg_arena, &msgs, &dst_m); } MG_FileParseNode *parse_n = push_array(mg_arena, MG_FileParseNode, 1); SLLQueuePush(parses.first, parses.last, parse_n); parse_n->v.root = parse.root; parses.count += 1; } } } ////////////////////////////// //- rjf: gather tables // MG_Map table_grid_map = mg_push_map(mg_arena, 1024); MG_Map table_col_map = mg_push_map(mg_arena, 1024); U64 table_count = 0; DeferLoop(printf("gathering tables..."), printf(" %i tables found\n", (int)table_count)) { for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *table_tag = md_tag_from_string(node, str8_lit("table"), 0); if(!md_node_is_nil(table_tag)) { MG_NodeGrid *table = push_array(mg_arena, MG_NodeGrid, 1); MG_ColumnDescArray *col_descs = push_array(mg_arena, MG_ColumnDescArray, 1); *table = mg_node_grid_make_from_node(mg_arena, node); *col_descs = mg_column_desc_array_from_tag(mg_arena, table_tag); mg_map_insert_ptr(mg_arena, &table_grid_map, node->string, table); mg_map_insert_ptr(mg_arena, &table_col_map, node->string, col_descs); table_count += 1; } } } } ////////////////////////////// //- rjf: gather layer options // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); for MD_EachNode(node, file->first) { if(md_node_has_tag(node, str8_lit("option"), 0)) { if(str8_match(node->string, str8_lit("library"), 0)) { layer->is_library = 1; } } if(md_node_has_tag(node, str8_lit("gen_folder"), 0)) { layer->gen_folder_name = node->string; } if(md_node_has_tag(node, str8_lit("h_name"), 0)) { layer->h_name_override = node->string; } if(md_node_has_tag(node, str8_lit("c_name"), 0)) { layer->c_name_override = node->string; } if(md_node_has_tag(node, str8_lit("h_header"), 0)) { String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_push(mg_arena, &layer->h_header, n->string); str8_list_push(mg_arena, &layer->h_header, str8_lit("\n")); } } if(md_node_has_tag(node, str8_lit("h_footer"), 0)) { String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_push(mg_arena, &layer->h_footer, n->string); str8_list_push(mg_arena, &layer->h_footer, str8_lit("\n")); } } if(md_node_has_tag(node, str8_lit("c_header"), 0)) { String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_push(mg_arena, &layer->c_header, n->string); str8_list_push(mg_arena, &layer->c_header, str8_lit("\n")); } } if(md_node_has_tag(node, str8_lit("c_footer"), 0)) { String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_push(mg_arena, &layer->c_footer, n->string); str8_list_push(mg_arena, &layer->c_footer, str8_lit("\n")); } } } } ////////////////////////////// //- rjf: generate enums // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *tag = md_tag_from_string(node, str8_lit("enum"), 0); if(!md_node_is_nil(tag)) { String8 enum_name = node->string; String8 enum_member_prefix = enum_name; if(str8_match(str8_postfix(enum_name, 5), str8_lit("Flags"), 0)) { enum_member_prefix = str8_chop(enum_name, 1); } String8 enum_base_type_name = tag->first->string; String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); if(enum_base_type_name.size == 0) { str8_list_pushf(mg_arena, &layer->enums, "typedef enum %S\n{\n", enum_name); } else { str8_list_pushf(mg_arena, &layer->enums, "typedef %S %S;\n", enum_base_type_name, enum_name); str8_list_pushf(mg_arena, &layer->enums, "typedef enum %SEnum\n{\n", enum_name); } for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &layer->enums, "%S_%S,\n", enum_member_prefix, n->string); } if(enum_base_type_name.size == 0) { str8_list_pushf(mg_arena, &layer->enums, "} %S;\n\n", enum_name); } else { str8_list_pushf(mg_arena, &layer->enums, "} %SEnum;\n\n", enum_name); } } } } ////////////////////////////// //- rjf: generate xlists // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *tag = md_tag_from_string(node, str8_lit("xlist"), 0); if(!md_node_is_nil(tag)) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); str8_list_pushf(mg_arena, &layer->enums, "#define %S \\\n", node->string); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &layer->enums, "X(%S)\\\n", n->string); } str8_list_push(mg_arena, &layer->enums, str8_lit("\n")); } } } ////////////////////////////// //- rjf: generate structs // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { if(md_node_has_tag(node, str8_lit("struct"), 0)) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); str8_list_pushf(mg_arena, &layer->structs, "typedef struct %S %S;\n", node->string, node->string); str8_list_pushf(mg_arena, &layer->structs, "struct %S\n{\n", node->string); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &layer->structs, "%S;\n", n->string); } str8_list_pushf(mg_arena, &layer->structs, "};\n\n"); } } } ////////////////////////////// //- rjf: generate data tables // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *tag = md_tag_from_string(node, str8_lit("data"), 0); if(!md_node_is_nil(tag)) { String8 element_type = tag->first->string; String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); if(!md_node_has_tag(node, str8_lit("c_file"), 0)) { str8_list_pushf(mg_arena, &layer->h_tables, "extern %S %S[%I64u];\n", element_type, node->string, gen_strings.node_count); } str8_list_pushf(mg_arena, &layer->c_tables, "%S %S[%I64u] =\n{\n", element_type, node->string, gen_strings.node_count); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &layer->c_tables, "%S,\n", n->string); } str8_list_push(mg_arena, &layer->c_tables, str8_lit("};\n\n")); } } } ////////////////////////////// //- rjf: generate enum -> string mapping functions // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *tag = md_tag_from_string(node, str8_lit("enum2string_switch"), 0); if(!md_node_is_nil(tag)) { String8 enum_type = tag->first->string; String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); str8_list_pushf(mg_arena, &layer->h_functions, "internal String8 %S(%S v);\n", node->string, enum_type); str8_list_pushf(mg_arena, &layer->c_functions, "internal String8\n%S(%S v)\n{\n", node->string, enum_type); str8_list_pushf(mg_arena, &layer->c_functions, "String8 result = str8_lit(\"\");\n", enum_type); str8_list_pushf(mg_arena, &layer->c_functions, "switch(v)\n"); str8_list_pushf(mg_arena, &layer->c_functions, "{\n"); str8_list_pushf(mg_arena, &layer->c_functions, "default:{}break;\n"); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &layer->c_functions, "%S;\n", n->string); } str8_list_pushf(mg_arena, &layer->c_functions, "}\n"); str8_list_pushf(mg_arena, &layer->c_functions, "return result;\n"); str8_list_pushf(mg_arena, &layer->c_functions, "}\n\n"); } } } ////////////////////////////// //- rjf: generate catch-all generations // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { MD_Node *tag = md_tag_from_string(node, str8_lit("gen"), 0); if(!md_node_is_nil(tag)) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); B32 prefer_c_file = md_node_has_tag(node, str8_lit("c_file"), 0); String8List *out = prefer_c_file ? &layer->c_catchall : &layer->h_catchall; if(tag->first->string.size == 0){} else if(str8_match(tag->first->string, str8_lit("enums"), 0)) { out = &layer->enums; } else if(str8_match(tag->first->string, str8_lit("structs"), 0)) { out = &layer->structs; } else if(str8_match(tag->first->string, str8_lit("functions"), 0)) { out = prefer_c_file ? &layer->c_functions : &layer->h_functions; } else if(str8_match(tag->first->string, str8_lit("tables"), 0)) { out = prefer_c_file ? &layer->c_tables : &layer->h_tables; } String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { String8 trimmed = str8_skip_chop_whitespace(n->string); str8_list_push(mg_arena, out, trimmed); str8_list_push(mg_arena, out, str8_lit("\n")); } } } } ////////////////////////////// //- rjf: gather & generate all embeds // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { if(md_node_has_tag(node, str8_lit("embed_string"), 0)) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8 embed_string = mg_c_string_literal_from_multiline_string(node->first->string); str8_list_pushf(mg_arena, &layer->h_tables, "read_only global String8 %S =\nstr8_lit_comp(\n", node->string); str8_list_push (mg_arena, &layer->h_tables, embed_string); str8_list_pushf(mg_arena, &layer->h_tables, ");\n\n"); } if(md_node_has_tag(node, str8_lit("embed_file"), 0)) { String8 layer_key = mg_layer_key_from_path(file->string); MG_Layer *layer = mg_layer_from_key(layer_key); String8 data = os_data_from_file_path(mg_arena, node->first->string); String8 embed_string = mg_c_array_literal_contents_from_data(data); str8_list_pushf(mg_arena, &layer->h_tables, "read_only global U8 %S__data[] =\n{\n", node->string); str8_list_push (mg_arena, &layer->h_tables, embed_string); str8_list_pushf(mg_arena, &layer->h_tables, "};\n\n"); str8_list_pushf(mg_arena, &layer->h_tables, "read_only global String8 %S = {%S__data, sizeof(%S__data)};\n", node->string, node->string, node->string); } } } ////////////////////////////// //- rjf: generate all markdown in build folder // for(MG_FileParseNode *n = parses.first; n != 0; n = n->next) { MD_Node *file = n->v.root; for MD_EachNode(node, file->first) { //- rjf: generate markdown page if(md_node_has_tag(node, str8_lit("markdown"), 0)) { String8List md_strs = {0}; for(MD_Node *piece = node->first; !md_node_is_nil(piece); piece = piece->next) { if(md_node_has_tag(piece, str8_lit("title"), 0)) { str8_list_pushf(mg_arena, &md_strs, "# %S\n\n", piece->string); } if(md_node_has_tag(piece, str8_lit("subtitle"), 0)) { str8_list_pushf(mg_arena, &md_strs, "## %S\n\n", piece->string); } if(md_node_has_tag(piece, str8_lit("p"), 0)) { String8 paragraph_text = piece->string; String8List paragraph_lines = mg_wrapped_lines_from_string(mg_arena, paragraph_text, 80, 80, 0); for(String8Node *n = paragraph_lines.first; n != 0; n = n->next) { str8_list_push(mg_arena, &md_strs, n->string); str8_list_push(mg_arena, &md_strs, str8_lit("\n")); } str8_list_push(mg_arena, &md_strs, str8_lit("\n")); } if(md_node_has_tag(piece, str8_lit("unordered_list"), 0)) { String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), piece); for(String8Node *n = gen_strings.first; n != 0; n = n->next) { str8_list_pushf(mg_arena, &md_strs, " - "); String8 item_text = n->string; String8List item_lines = mg_wrapped_lines_from_string(mg_arena, item_text, 80-3, 80, 3); for(String8Node *line_n = item_lines.first; line_n != 0; line_n = line_n->next) { str8_list_push(mg_arena, &md_strs, line_n->string); str8_list_pushf(mg_arena, &md_strs, "\n"); } } str8_list_pushf(mg_arena, &md_strs, "\n"); } } String8 output_path = push_str8f(mg_arena, "%S/%S.md", build_dir_path, node->string); FILE *file = fopen((char *)output_path.str, "w"); for(String8Node *n = md_strs.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, file); } fclose(file); } } } ////////////////////////////// //- rjf: write all layer output files // DeferLoop(printf("generating layer code..."), printf("\n")) { for(U64 slot_idx = 0; slot_idx < mg_state->slots_count; slot_idx += 1) { MG_LayerSlot *slot = &mg_state->slots[slot_idx]; for(MG_LayerNode *n = slot->first; n != 0; n = n->next) { MG_Layer *layer = &n->v; String8 layer_generated_folder = {0}; if(layer->gen_folder_name.size != 0) { String8 gen_folder = layer->gen_folder_name; layer_generated_folder = push_str8f(mg_arena, "%S/%S", code_dir_path, gen_folder); } else { String8 gen_folder = str8_lit("generated"); layer_generated_folder = push_str8f(mg_arena, "%S/%S/%S", code_dir_path, layer->key, gen_folder); } if(os_make_directory(layer_generated_folder)) { String8List layer_key_parts = str8_split_path(mg_arena, layer->key); StringJoin join = {0}; join.sep = str8_lit("_"); String8 layer_key_filename = str8_list_join(mg_arena, &layer_key_parts, &join); String8 layer_key_filename_upper = upper_from_str8(mg_arena, layer_key_filename); String8 h_path = push_str8f(mg_arena, "%S/%S.meta.h", layer_generated_folder, layer_key_filename); String8 c_path = push_str8f(mg_arena, "%S/%S.meta.c", layer_generated_folder, layer_key_filename); if(layer->h_name_override.size != 0) { h_path = push_str8f(mg_arena, "%S/%S", layer_generated_folder, str8_skip_last_slash(layer->h_name_override)); } if(layer->c_name_override.size != 0) { c_path = push_str8f(mg_arena, "%S/%S", layer_generated_folder, str8_skip_last_slash(layer->c_name_override)); } { FILE *h = fopen((char *)h_path.str, "w"); fprintf(h, "// Copyright (c) Epic Games Tools\n"); fprintf(h, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n"); if(layer->h_header.first == 0) { fprintf(h, "//- GENERATED CODE\n\n"); fprintf(h, "#ifndef %.*s_META_H\n", str8_varg(layer_key_filename_upper)); fprintf(h, "#define %.*s_META_H\n\n", str8_varg(layer_key_filename_upper)); } else for(String8Node *n = layer->h_header.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } for(String8Node *n = layer->enums.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } for(String8Node *n = layer->structs.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } for(String8Node *n = layer->h_catchall.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } for(String8Node *n = layer->h_functions.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } if(layer->h_tables.first != 0) { if(!layer->is_library) { fprintf(h, "C_LINKAGE_BEGIN\n"); } for(String8Node *n = layer->h_tables.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } fprintf(h, "\n"); if(!layer->is_library) { fprintf(h, "C_LINKAGE_END\n\n"); } } if(layer->h_footer.first == 0) { fprintf(h, "#endif // %.*s_META_H\n", str8_varg(layer_key_filename_upper)); } else for(String8Node *n = layer->h_footer.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, h); } fclose(h); } { FILE *c = fopen((char *)c_path.str, "w"); fprintf(c, "// Copyright (c) Epic Games Tools\n"); fprintf(c, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n"); if(layer->c_header.first == 0) { fprintf(c, "//- GENERATED CODE\n\n"); } else for(String8Node *n = layer->c_header.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, c); } for(String8Node *n = layer->c_catchall.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, c); } if(layer->c_tables.first != 0) { if(!layer->is_library) { fprintf(c, "C_LINKAGE_BEGIN\n"); } for(String8Node *n = layer->c_tables.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, c); } if(!layer->is_library) { fprintf(c, "C_LINKAGE_END\n\n"); } } for(String8Node *n = layer->c_functions.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, c); } if(layer->c_footer.first != 0) { for(String8Node *n = layer->c_footer.first; n != 0; n = n->next) { fwrite(n->string.str, n->string.size, 1, c); } } fclose(c); } } } } } ////////////////////////////// //- rjf: write out all messages to stderr // for(MG_MsgNode *n = msgs.first; n != 0; n = n->next) { MG_Msg *msg = &n->v; fprintf(stderr, "%.*s: %.*s: %.*s\n", str8_varg(msg->location), str8_varg(msg->kind), str8_varg(msg->msg)); } } ================================================ FILE: src/metagen/metagen_os/core/linux/metagen_os_core_linux.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec) { DateTime dt = {0}; dt.sec = in.tm_sec; dt.min = in.tm_min; dt.hour = in.tm_hour; dt.day = in.tm_mday-1; dt.mon = in.tm_mon; dt.year = in.tm_year+1900; dt.msec = msec; return dt; } internal tm os_lnx_tm_from_date_time(DateTime dt) { tm result = {0}; result.tm_sec = dt.sec; result.tm_min = dt.min; result.tm_hour= dt.hour; result.tm_mday= dt.day+1; result.tm_mon = dt.mon; result.tm_year= dt.year-1900; return result; } internal timespec os_lnx_timespec_from_date_time(DateTime dt) { tm tm_val = os_lnx_tm_from_date_time(dt); time_t seconds = timegm(&tm_val); timespec result = {0}; result.tv_sec = seconds; return result; } internal DenseTime os_lnx_dense_time_from_timespec(timespec in) { DenseTime result = 0; { struct tm tm_time = {0}; gmtime_r(&in.tv_sec, &tm_time); DateTime date_time = os_lnx_date_time_from_tm(tm_time, in.tv_nsec/Million(1)); result = dense_time_from_date_time(date_time); } return result; } internal FileProperties os_lnx_file_properties_from_stat(struct stat *s) { FileProperties props = {0}; props.size = s->st_size; props.created = os_lnx_dense_time_from_timespec(s->st_ctim); props.modified = os_lnx_dense_time_from_timespec(s->st_mtim); if(s->st_mode & S_IFDIR) { props.flags |= FilePropertyFlag_IsFolder; } return props; } internal void os_lnx_safe_call_sig_handler(int x) { OS_LNX_SafeCallChain *chain = os_lnx_safe_call_chain; if(chain != 0 && chain->fail_handler != 0) { chain->fail_handler(chain->ptr); } abort(); } //////////////////////////////// //~ rjf: Entities internal OS_LNX_Entity * os_lnx_entity_alloc(OS_LNX_EntityKind kind) { OS_LNX_Entity *entity = 0; DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), pthread_mutex_unlock(&os_lnx_state.entity_mutex)) { entity = os_lnx_state.entity_free; if(entity) { SLLStackPop(os_lnx_state.entity_free); } else { entity = push_array_no_zero(os_lnx_state.entity_arena, OS_LNX_Entity, 1); } } MemoryZeroStruct(entity); entity->kind = kind; return entity; } internal void os_lnx_entity_release(OS_LNX_Entity *entity) { DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), pthread_mutex_unlock(&os_lnx_state.entity_mutex)) { SLLStackPush(os_lnx_state.entity_free, entity); } } //////////////////////////////// //~ rjf: Thread Entry Point internal void * os_lnx_thread_entry_point(void *ptr) { OS_LNX_Entity *entity = (OS_LNX_Entity *)ptr; OS_ThreadFunctionType *func = entity->thread.func; void *thread_ptr = entity->thread.ptr; TCTX tctx_; tctx_init_and_equip(&tctx_); func(thread_ptr); tctx_release(); return 0; } //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo * os_get_system_info(void) { return &os_lnx_state.system_info; } internal OS_ProcessInfo * os_get_process_info(void) { return &os_lnx_state.process_info; } internal String8 os_get_current_path(Arena *arena) { char *cwdir = getcwd(0, 0); String8 string = push_str8_copy(arena, str8_cstring(cwdir)); free(cwdir); return string; } internal U32 os_get_process_start_time_unix(void) { Temp scratch = scratch_begin(0,0); U64 start_time = 0; pid_t pid = getpid(); String8 path = push_str8f(scratch.arena, "/proc/%u", pid); struct stat st; int err = stat((char*)path.str, &st); if(err == 0) { start_time = st.st_mtime; } scratch_end(scratch); return (U32)start_time; } //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void * os_reserve(U64 size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if(result == MAP_FAILED) { result = 0; } return result; } internal B32 os_commit(void *ptr, U64 size) { mprotect(ptr, size, PROT_READ|PROT_WRITE); return 1; } internal void os_decommit(void *ptr, U64 size) { madvise(ptr, size, MADV_DONTNEED); mprotect(ptr, size, PROT_NONE); } internal void os_release(void *ptr, U64 size) { munmap(ptr, size); } //- rjf: large pages internal void * os_reserve_large(U64 size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); if(result == MAP_FAILED) { result = 0; } return result; } internal B32 os_commit_large(void *ptr, U64 size) { mprotect(ptr, size, PROT_READ|PROT_WRITE); return 1; } //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void) { U32 result = gettid(); return result; } internal void os_set_thread_name(String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); pthread_t current_thread = pthread_self(); pthread_setname_np(current_thread, (char *)name_copy.str); scratch_end(scratch); } //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code) { exit(exit_code); } //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); int lnx_flags = 0; if(flags & OS_AccessFlag_Read && flags & OS_AccessFlag_Write) { lnx_flags = O_RDWR; } else if(flags & OS_AccessFlag_Write) { lnx_flags = O_WRONLY; } else if(flags & OS_AccessFlag_Read) { lnx_flags = O_RDONLY; } if(flags & OS_AccessFlag_Append) { lnx_flags |= O_APPEND; } if(flags & (OS_AccessFlag_Write|OS_AccessFlag_Append)) { lnx_flags |= O_CREAT; } int fd = open((char *)path_copy.str, lnx_flags, 0755); OS_Handle handle = {0}; if(fd != -1) { handle.u64[0] = fd; } scratch_end(scratch); return handle; } internal void os_file_close(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return; } int fd = (int)file.u64[0]; close(fd); } internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; U64 total_num_bytes_to_read = dim_1u64(rng); U64 total_num_bytes_read = 0; U64 total_num_bytes_left_to_read = total_num_bytes_to_read; for(;total_num_bytes_left_to_read > 0;) { int read_result = pread(fd, (U8 *)out_data + total_num_bytes_read, total_num_bytes_left_to_read, rng.min + total_num_bytes_read); if(read_result >= 0) { total_num_bytes_read += read_result; total_num_bytes_left_to_read -= read_result; } else if(errno != EINTR) { break; } } return total_num_bytes_read; } internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; U64 total_num_bytes_to_write = dim_1u64(rng); U64 total_num_bytes_written = 0; U64 total_num_bytes_left_to_write = total_num_bytes_to_write; for(;total_num_bytes_left_to_write > 0;) { int write_result = pwrite(fd, (U8 *)data + total_num_bytes_written, total_num_bytes_left_to_write, rng.min + total_num_bytes_written); if(write_result >= 0) { total_num_bytes_written += write_result; total_num_bytes_left_to_write -= write_result; } else if(errno != EINTR) { break; } } return total_num_bytes_written; } internal B32 os_file_set_times(OS_Handle file, DateTime date_time) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; timespec time = os_lnx_timespec_from_date_time(date_time); timespec times[2] = {time, time}; int futimens_result = futimens(fd, times); B32 good = (futimens_result != -1); return good; } internal FileProperties os_properties_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return (FileProperties){0}; } int fd = (int)file.u64[0]; struct stat fd_stat = {0}; int fstat_result = fstat(fd, &fd_stat); FileProperties props = {0}; if(fstat_result != -1) { props = os_lnx_file_properties_from_stat(&fd_stat); } return props; } internal OS_FileID os_id_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return (OS_FileID){0}; } int fd = (int)file.u64[0]; struct stat fd_stat = {0}; int fstat_result = fstat(fd, &fd_stat); OS_FileID id = {0}; if(fstat_result != -1) { id.v[0] = fd_stat.st_dev; id.v[1] = fd_stat.st_ino; } return id; } internal B32 os_delete_file_at_path(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); if(remove((char*)path_copy.str) != -1) { result = 1; } scratch_end(scratch); return result; } internal B32 os_copy_file_path(String8 dst, String8 src) { B32 result = 0; OS_Handle src_h = os_file_open(OS_AccessFlag_Read, src); OS_Handle dst_h = os_file_open(OS_AccessFlag_Write, dst); if(!os_handle_match(src_h, os_handle_zero()) && !os_handle_match(dst_h, os_handle_zero())) { int src_fd = (int)src_h.u64[0]; int dst_fd = (int)dst_h.u64[0]; FileProperties src_props = os_properties_from_file(src_h); U64 size = src_props.size; U64 total_bytes_copied = 0; U64 bytes_left_to_copy = size; for(;bytes_left_to_copy > 0;) { off_t sendfile_off = total_bytes_copied; int send_result = sendfile(dst_fd, src_fd, &sendfile_off, bytes_left_to_copy); if(send_result <= 0) { break; } U64 bytes_copied = (U64)send_result; bytes_left_to_copy -= bytes_copied; total_bytes_copied += bytes_copied; } } os_file_close(src_h); os_file_close(dst_h); return result; } internal B32 os_move_file_path(String8 dst, String8 src) { // TODO(rjf) return 0; } internal String8 os_full_path_from_path(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); String8 path_copy = push_str8_copy(scratch.arena, path); char buffer[PATH_MAX] = {0}; realpath((char *)path_copy.str, buffer); String8 result = push_str8_copy(arena, str8_cstring(buffer)); scratch_end(scratch); return result; } internal B32 os_file_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); int access_result = access((char *)path_copy.str, F_OK); B32 result = 0; if(access_result == 0) { result = 1; } scratch_end(scratch); return result; } internal B32 os_folder_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); B32 exists = 0; String8 path_copy = push_str8_copy(scratch.arena, path); DIR *handle = opendir((char*)path_copy.str); if(handle) { closedir(handle); exists = 1; } scratch_end(scratch); return exists; } internal FileProperties os_properties_from_file_path(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); struct stat f_stat = {0}; int stat_result = stat((char *)path_copy.str, &f_stat); FileProperties props = {0}; if(stat_result != -1) { props = os_lnx_file_properties_from_stat(&f_stat); } scratch_end(scratch); return props; } //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file) { OS_Handle map = file; return map; } internal void os_file_map_close(OS_Handle map) { // NOTE(rjf): nothing to do; `map` handles are the same as `file` handles in // the linux implementation (on Windows they require separate handles) } internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) { if(os_handle_match(map, os_handle_zero())) { return 0; } int fd = (int)map.u64[0]; int prot_flags = 0; if(flags & OS_AccessFlag_Write) { prot_flags |= PROT_WRITE; } if(flags & OS_AccessFlag_Read) { prot_flags |= PROT_READ; } int map_flags = MAP_PRIVATE; void *base = mmap(0, dim_1u64(range), prot_flags, map_flags, fd, range.min); if(base == MAP_FAILED) { base = 0; } return base; } internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) { munmap(ptr, dim_1u64(range)); } //- rjf: directory iteration internal OS_FileIter * os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) { OS_FileIter *base_iter = push_array(arena, OS_FileIter, 1); base_iter->flags = flags; OS_LNX_FileIter *iter = (OS_LNX_FileIter *)base_iter->memory; { String8 path_copy = push_str8_copy(arena, path); iter->dir = opendir((char *)path_copy.str); iter->path = path_copy; } return base_iter; } internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { B32 good = 0; OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; for(;;) { // rjf: get next entry lnx_iter->dp = readdir(lnx_iter->dir); good = (lnx_iter->dp != 0); // rjf: unpack entry info struct stat st = {0}; int stat_result = 0; if(good) { Temp scratch = scratch_begin(&arena, 1); String8 full_path = push_str8f(scratch.arena, "%S/%s", lnx_iter->path, lnx_iter->dp->d_name); stat_result = stat((char *)full_path.str, &st); scratch_end(scratch); } // rjf: determine if filtered B32 filtered = 0; if(good) { filtered = ((st.st_mode == S_IFDIR && iter->flags & OS_FileIterFlag_SkipFolders) || (st.st_mode == S_IFREG && iter->flags & OS_FileIterFlag_SkipFiles) || (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == 0) || (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == '.' && lnx_iter->dp->d_name[2] == 0)); } // rjf: output & exit, if good & unfiltered if(good && !filtered) { info_out->name = push_str8_copy(arena, str8_cstring(lnx_iter->dp->d_name)); if(stat_result != -1) { info_out->props = os_lnx_file_properties_from_stat(&st); } break; } // rjf: exit if not good if(!good) { break; } } return good; } internal void os_file_iter_end(OS_FileIter *iter) { OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; closedir(lnx_iter->dir); } //- rjf: directory creation internal B32 os_make_directory(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); if(mkdir((char*)path_copy.str, 0755) != -1) { result = 1; } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); int id = shm_open((char *)name_copy.str, O_RDWR, 0); ftruncate(id, size); OS_Handle result = {(U64)id}; scratch_end(scratch); return result; } internal OS_Handle os_shared_memory_open(String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); int id = shm_open((char *)name_copy.str, O_RDWR, 0); OS_Handle result = {(U64)id}; scratch_end(scratch); return result; } internal void os_shared_memory_close(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())){return;} int id = (int)handle.u64[0]; close(id); } internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) { if(os_handle_match(handle, os_handle_zero())){return 0;} int id = (int)handle.u64[0]; void *base = mmap(0, dim_1u64(range), PROT_READ|PROT_WRITE, MAP_SHARED, id, range.min); if(base == MAP_FAILED) { base = 0; } return base; } internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) { if(os_handle_match(handle, os_handle_zero())){return;} munmap(ptr, dim_1u64(range)); } //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); U64 result = t.tv_sec*Million(1) + (t.tv_nsec/Thousand(1)); return result; } internal U32 os_now_unix(void) { time_t t = time(0); return (U32)t; } internal DateTime os_now_universal_time(void) { time_t t = 0; time(&t); struct tm universal_tm = {0}; gmtime_r(&t, &universal_tm); DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); return result; } internal DateTime os_universal_time_from_local(DateTime *date_time) { // rjf: local DateTime -> universal time_t tm local_tm = os_lnx_tm_from_date_time(*date_time); local_tm.tm_isdst = -1; time_t universal_t = mktime(&local_tm); // rjf: universal time_t -> DateTime tm universal_tm = {0}; gmtime_r(&universal_t, &universal_tm); DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); return result; } internal DateTime os_local_time_from_universal(DateTime *date_time) { // rjf: universal DateTime -> local time_t tm universal_tm = os_lnx_tm_from_date_time(*date_time); universal_tm.tm_isdst = -1; time_t universal_t = timegm(&universal_tm); tm local_tm = {0}; localtime_r(&universal_t, &local_tm); // rjf: local tm -> DateTime DateTime result = os_lnx_date_time_from_tm(local_tm, 0); return result; } internal void os_sleep_milliseconds(U32 msec) { usleep(msec*Thousand(1)); } //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params) { NotImplemented; } internal B32 os_process_join(OS_Handle handle, U64 endt_us) { NotImplemented; } internal void os_process_detach(OS_Handle handle) { NotImplemented; } //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Thread); entity->thread.func = func; entity->thread.ptr = ptr; { int pthread_result = pthread_create(&entity->thread.handle, 0, os_lnx_thread_entry_point, entity); if(pthread_result == -1) { os_lnx_entity_release(entity); entity = 0; } } OS_Handle handle = {(U64)entity}; return handle; } internal B32 os_thread_join(OS_Handle handle, U64 endt_us) { if(os_handle_match(handle, os_handle_zero())) { return 0; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; int join_result = pthread_join(entity->thread.handle, 0); B32 result = (join_result == 0); os_lnx_entity_release(entity); return result; } internal void os_thread_detach(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; os_lnx_entity_release(entity); } //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: mutexes internal OS_Handle os_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Mutex); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); int init_result = pthread_mutex_init(&entity->mutex_handle, &attr); pthread_mutexattr_destroy(&attr); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } OS_Handle handle = {(U64)entity}; return handle; } internal void os_mutex_release(OS_Handle mutex) { if(os_handle_match(mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_destroy(&entity->mutex_handle); os_lnx_entity_release(entity); } internal void os_mutex_take(OS_Handle mutex) { if(os_handle_match(mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_lock(&entity->mutex_handle); } internal void os_mutex_drop(OS_Handle mutex) { if(os_handle_match(mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_unlock(&entity->mutex_handle); } //- rjf: reader/writer mutexes internal OS_Handle os_rw_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_RWMutex); int init_result = pthread_rwlock_init(&entity->rwmutex_handle, 0); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } OS_Handle handle = {(U64)entity}; return handle; } internal void os_rw_mutex_release(OS_Handle rw_mutex) { if(os_handle_match(rw_mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_destroy(&entity->rwmutex_handle); os_lnx_entity_release(entity); } internal void os_rw_mutex_take_r(OS_Handle rw_mutex) { if(os_handle_match(rw_mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_rdlock(&entity->rwmutex_handle); } internal void os_rw_mutex_drop_r(OS_Handle rw_mutex) { if(os_handle_match(rw_mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_unlock(&entity->rwmutex_handle); } internal void os_rw_mutex_take_w(OS_Handle rw_mutex) { if(os_handle_match(rw_mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_wrlock(&entity->rwmutex_handle); } internal void os_rw_mutex_drop_w(OS_Handle rw_mutex) { if(os_handle_match(rw_mutex, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_unlock(&entity->rwmutex_handle); } //- rjf: condition variables internal OS_Handle os_condition_variable_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_ConditionVariable); int init_result = pthread_cond_init(&entity->cv.cond_handle, 0); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } int init2_result = 0; if(entity) { init2_result = pthread_mutex_init(&entity->cv.rwlock_mutex_handle, 0); } if(init2_result == -1) { pthread_cond_destroy(&entity->cv.cond_handle); os_lnx_entity_release(entity); entity = 0; } OS_Handle handle = {(U64)entity}; return handle; } internal void os_condition_variable_release(OS_Handle cv) { if(os_handle_match(cv, os_handle_zero())) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_destroy(&entity->cv.cond_handle); pthread_mutex_destroy(&entity->cv.rwlock_mutex_handle); os_lnx_entity_release(entity); } internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) { if(os_handle_match(cv, os_handle_zero())) { return 0; } if(os_handle_match(mutex, os_handle_zero())) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *mutex_entity = (OS_LNX_Entity *)mutex.u64[0]; struct timespec endt_timespec; endt_timespec.tv_sec = endt_us/Million(1); endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &mutex_entity->mutex_handle, &endt_timespec); B32 result = (wait_result != ETIMEDOUT); return result; } internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack // this together, but this would probably just be a lot better if we just // implemented the primitives ourselves with e.g. futexes // if(os_handle_match(cv, os_handle_zero())) { return 0; } if(os_handle_match(mutex_rw, os_handle_zero())) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; struct timespec endt_timespec; endt_timespec.tv_sec = endt_us/Million(1); endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); B32 result = 0; for(;;) { pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle); int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec); if(wait_result != ETIMEDOUT) { pthread_rwlock_rdlock(&rw_mutex_entity->rwmutex_handle); pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); result = 1; break; } pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); if(wait_result == ETIMEDOUT) { break; } } return result; } internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack // this together, but this would probably just be a lot better if we just // implemented the primitives ourselves with e.g. futexes // if(os_handle_match(cv, os_handle_zero())) { return 0; } if(os_handle_match(mutex_rw, os_handle_zero())) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; struct timespec endt_timespec; endt_timespec.tv_sec = endt_us/Million(1); endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); B32 result = 0; for(;;) { pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle); int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec); if(wait_result != ETIMEDOUT) { pthread_rwlock_wrlock(&rw_mutex_entity->rwmutex_handle); pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); result = 1; break; } pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); if(wait_result == ETIMEDOUT) { break; } } return result; } internal void os_condition_variable_signal(OS_Handle cv) { if(os_handle_match(cv, os_handle_zero())) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_signal(&cv_entity->cv.cond_handle); } internal void os_condition_variable_broadcast(OS_Handle cv) { if(os_handle_match(cv, os_handle_zero())) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_broadcast(&cv_entity->cv.cond_handle); } //- rjf: cross-process semaphores internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { OS_Handle result = {0}; if (name.size > 0) { // TODO: we need to allocate shared memory to store sem_t NotImplemented; } else { sem_t *s = mmap(0, sizeof(*s), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); AssertAlways(s != MAP_FAILED); int err = sem_init(s, 0, initial_count); if (err == 0) { result.u64[0] = (U64)s; } } return result; } internal void os_semaphore_release(OS_Handle semaphore) { int err = munmap((void*)semaphore.u64[0], sizeof(sem_t)); AssertAlways(err == 0); } internal OS_Handle os_semaphore_open(String8 name) { NotImplemented; } internal void os_semaphore_close(OS_Handle semaphore) { NotImplemented; } internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us) { AssertAlways(endt_us == max_U64); for (;;) { int err = sem_wait((sem_t*)semaphore.u64[0]); if (err == 0) { break; } else { if (errno == EAGAIN) { continue; } } InvalidPath; break; } return 1; } internal void os_semaphore_drop(OS_Handle semaphore) { for (;;) { int err = sem_post((sem_t*)semaphore.u64[0]); if (err == 0) { break; } else { if (errno == EAGAIN) { continue; } } InvalidPath; break; } } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); char *path_cstr = (char *)push_str8_copy(scratch.arena, path).str; void *so = dlopen(path_cstr, RTLD_LAZY|RTLD_LOCAL); OS_Handle lib = { (U64)so }; scratch_end(scratch); return lib; } internal VoidProc* os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); void *so = (void *)lib.u64; char *name_cstr = (char *)push_str8_copy(scratch.arena, name).str; VoidProc *proc = (VoidProc *)dlsym(so, name_cstr); scratch_end(scratch); return proc; } internal void os_library_close(OS_Handle lib) { void *so = (void *)lib.u64; dlclose(so); } //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr) { // rjf: push handler to chain OS_LNX_SafeCallChain chain = {0}; SLLStackPush(os_lnx_safe_call_chain, &chain); chain.fail_handler = fail_handler; chain.ptr = ptr; // rjf: set up sig handler info struct sigaction new_act = {0}; new_act.sa_handler = os_lnx_safe_call_sig_handler; int signals_to_handle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, }; struct sigaction og_act[ArrayCount(signals_to_handle)] = {0}; // rjf: attach handler info for all signals for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) { sigaction(signals_to_handle[i], &new_act, &og_act[i]); } // rjf: call function func(ptr); // rjf: reset handler info for all signals for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) { sigaction(signals_to_handle[i], &og_act[i], 0); } } //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void) { Guid guid = {0}; getrandom(guid.v, sizeof(guid.v), 0); guid.data3 &= 0x0fff; guid.data3 |= (4 << 12); guid.data4[0] &= 0x3f; guid.data4[0] |= 0x80; return guid; } //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) int main(int argc, char **argv) { //- rjf: set up OS layer { //- rjf: get statically-allocated system/process info { OS_SystemInfo *info = &os_lnx_state.system_info; info->logical_processor_count = (U32)get_nprocs(); info->page_size = (U64)getpagesize(); info->large_page_size = MB(2); info->allocation_granularity = info->page_size; } { OS_ProcessInfo *info = &os_lnx_state.process_info; info->pid = (U32)getpid(); } //- rjf: set up thread context local_persist TCTX tctx; tctx_init_and_equip(&tctx); //- rjf: set up dynamically allocated state os_lnx_state.arena = arena_alloc(); os_lnx_state.entity_arena = arena_alloc(); pthread_mutex_init(&os_lnx_state.entity_mutex, 0); //- rjf: grab dynamically allocated system info { Temp scratch = scratch_begin(0, 0); OS_SystemInfo *info = &os_lnx_state.system_info; // rjf: get machine name B32 got_final_result = 0; U8 *buffer = 0; int size = 0; for(S64 cap = 4096, r = 0; r < 4; cap *= 2, r += 1) { scratch_end(scratch); buffer = push_array_no_zero(scratch.arena, U8, cap); size = gethostname((char*)buffer, cap); if(size < cap) { got_final_result = 1; break; } } // rjf: save name to info if(got_final_result && size > 0) { info->machine_name.size = size; info->machine_name.str = push_array_no_zero(os_lnx_state.arena, U8, info->machine_name.size + 1); MemoryCopy(info->machine_name.str, buffer, info->machine_name.size); info->machine_name.str[info->machine_name.size] = 0; } scratch_end(scratch); } //- rjf: grab dynamically allocated process info { Temp scratch = scratch_begin(0, 0); OS_ProcessInfo *info = &os_lnx_state.process_info; // rjf: grab binary path { // rjf: get self string B32 got_final_result = 0; U8 *buffer = 0; int size = 0; for(S64 cap = PATH_MAX, r = 0; r < 4; cap *= 2, r += 1) { scratch_end(scratch); buffer = push_array_no_zero(scratch.arena, U8, cap); size = readlink("/proc/self/exe", (char*)buffer, cap); if(size < cap) { got_final_result = 1; break; } } // rjf: save if(got_final_result && size > 0) { String8 full_name = str8(buffer, size); String8 name_chopped = str8_chop_last_slash(full_name); info->binary_path = push_str8_copy(os_lnx_state.arena, name_chopped); } } // rjf: grab initial directory { info->initial_path = os_get_current_path(os_lnx_state.arena); } // rjf: grab home directory { char *home = getenv("HOME"); info->user_program_data_path = str8_cstring(home); } scratch_end(scratch); } } //- rjf: call into "real" entry point main_thread_base_entry_point(argc, argv); } ================================================ FILE: src/metagen/metagen_os/core/linux/metagen_os_core_linux.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_LINUX_H #define OS_CORE_LINUX_H //////////////////////////////// //~ rjf: Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t gettid(void); int pthread_setname_np(pthread_t thread, const char *name); int pthread_getname_np(pthread_t thread, char *name, size_t size); typedef struct tm tm; typedef struct timespec timespec; //////////////////////////////// //~ rjf: File Iterator typedef struct OS_LNX_FileIter OS_LNX_FileIter; struct OS_LNX_FileIter { DIR *dir; struct dirent *dp; String8 path; }; StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check); //////////////////////////////// //~ rjf: Safe Call Handler Chain typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain; struct OS_LNX_SafeCallChain { OS_LNX_SafeCallChain *next; OS_ThreadFunctionType *fail_handler; void *ptr; }; //////////////////////////////// //~ rjf: Entities typedef enum OS_LNX_EntityKind { OS_LNX_EntityKind_Thread, OS_LNX_EntityKind_Mutex, OS_LNX_EntityKind_RWMutex, OS_LNX_EntityKind_ConditionVariable, } OS_LNX_EntityKind; typedef struct OS_LNX_Entity OS_LNX_Entity; struct OS_LNX_Entity { OS_LNX_Entity *next; OS_LNX_EntityKind kind; union { struct { pthread_t handle; OS_ThreadFunctionType *func; void *ptr; } thread; pthread_mutex_t mutex_handle; pthread_rwlock_t rwmutex_handle; struct { pthread_cond_t cond_handle; pthread_mutex_t rwlock_mutex_handle; } cv; }; }; //////////////////////////////// //~ rjf: State typedef struct OS_LNX_State OS_LNX_State; struct OS_LNX_State { Arena *arena; OS_SystemInfo system_info; OS_ProcessInfo process_info; pthread_mutex_t entity_mutex; Arena *entity_arena; OS_LNX_Entity *entity_free; }; //////////////////////////////// //~ rjf: Globals global OS_LNX_State os_lnx_state = {0}; thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0; //////////////////////////////// //~ rjf: Helpers internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec); internal tm os_lnx_tm_from_date_time(DateTime dt); internal timespec os_lnx_timespec_from_date_time(DateTime dt); internal DenseTime os_lnx_dense_time_from_timespec(timespec in); internal FileProperties os_lnx_file_properties_from_stat(struct stat *s); internal void os_lnx_safe_call_sig_handler(int x); //////////////////////////////// //~ rjf: Entities internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind); internal void os_lnx_entity_release(OS_LNX_Entity *entity); //////////////////////////////// //~ rjf: Thread Entry Point internal void *os_lnx_thread_entry_point(void *ptr); #endif // OS_CORE_LINUX_H ================================================ FILE: src/metagen/metagen_os/core/metagen_os_core.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Handle Type Functions (Helpers, Implemented Once) internal OS_Handle os_handle_zero(void) { OS_Handle handle = {0}; return handle; } internal B32 os_handle_match(OS_Handle a, OS_Handle b) { return a.u64[0] == b.u64[0]; } internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle) { OS_HandleNode *n = push_array(arena, OS_HandleNode, 1); n->v = handle; SLLQueuePush(handles->first, handles->last, n); handles->count += 1; } internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list) { OS_HandleArray result = {0}; result.count = list->count; result.v = push_array_no_zero(arena, OS_Handle, result.count); U64 idx = 0; for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1) { result.v[idx] = n->v; } return result; } //////////////////////////////// //~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once) internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv) { String8List result = {0}; for(int i = 0; i < argc; i += 1) { String8 str = str8_cstring(argv[i]); str8_list_push(arena, &result, str); } return result; } //////////////////////////////// //~ rjf: Filesystem Helpers (Helpers, Implemented Once) internal String8 os_data_from_file_path(Arena *arena, String8 path) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); FileProperties props = os_properties_from_file(file); String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size)); os_file_close(file); return data; } internal B32 os_write_data_to_file_path(String8 path, String8 data) { B32 good = 0; OS_Handle file = os_file_open(OS_AccessFlag_Write, path); if(!os_handle_match(file, os_handle_zero())) { good = 1; os_file_write(file, r1u64(0, data.size), data.str); os_file_close(file); } return good; } internal B32 os_write_data_list_to_file_path(String8 path, String8List list) { B32 good = 0; OS_Handle file = os_file_open(OS_AccessFlag_Write, path); if(!os_handle_match(file, os_handle_zero())) { good = 1; U64 off = 0; for(String8Node *n = list.first; n != 0; n = n->next) { os_file_write(file, r1u64(off, off+n->string.size), n->string.str); off += n->string.size; } os_file_close(file); } return good; } internal B32 os_append_data_to_file_path(String8 path, String8 data) { B32 good = 0; if(data.size != 0) { OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path); if(!os_handle_match(file, os_handle_zero())) { good = 1; U64 pos = os_properties_from_file(file).size; os_file_write(file, r1u64(pos, pos+data.size), data.str); os_file_close(file); } } return good; } internal OS_FileID os_id_from_file_path(String8 path) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); OS_FileID id = os_id_from_file(file); os_file_close(file); return id; } internal S64 os_file_id_compare(OS_FileID a, OS_FileID b) { S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v)); return cmp; } internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range) { U64 pre_pos = arena_pos(arena); String8 result; result.size = dim_1u64(range); result.str = push_array_no_zero(arena, U8, result.size); U64 actual_read_size = os_file_read(file, range, result.str); if(actual_read_size < result.size) { arena_pop_to(arena, pre_pos + actual_read_size); result.size = actual_read_size; } return result; } //////////////////////////////// //~ rjf: Process Launcher Helpers internal OS_Handle os_cmd_line_launch(String8 string) { Temp scratch = scratch_begin(0, 0); U8 split_chars[] = {' '}; String8List parts = str8_split(scratch.arena, string, split_chars, ArrayCount(split_chars), 0); OS_Handle handle = {0}; if(parts.node_count != 0) { // rjf: unpack exe part String8 exe = parts.first->string; String8 exe_folder = str8_chop_last_slash(exe); if(exe_folder.size == 0) { exe_folder = os_get_current_path(scratch.arena); } // rjf: find stdout delimiter String8Node *stdout_delimiter_n = 0; for(String8Node *n = parts.first; n != 0; n = n->next) { if(str8_match(n->string, str8_lit(">"), 0)) { stdout_delimiter_n = n; break; } } // rjf: read stdout path String8 stdout_path = {0}; if(stdout_delimiter_n && stdout_delimiter_n->next) { stdout_path = stdout_delimiter_n->next->string; } // rjf: open stdout handle OS_Handle stdout_handle = {0}; if(stdout_path.size != 0) { OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path); os_file_close(file); stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path); } // rjf: form command line String8List cmdline = {0}; for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next) { str8_list_push(scratch.arena, &cmdline, n->string); } // rjf: launch OS_ProcessLaunchParams params = {0}; params.cmd_line = cmdline; params.path = exe_folder; params.inherit_env = 1; params.stdout_file = stdout_handle; handle = os_process_launch(¶ms); // rjf: close stdout handle { if(stdout_path.size != 0) { os_file_close(stdout_handle); } } } scratch_end(scratch); return handle; } internal OS_Handle os_cmd_line_launchf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); OS_Handle result = os_cmd_line_launch(string); va_end(args); scratch_end(scratch); return result; } ================================================ FILE: src/metagen/metagen_os/core/metagen_os_core.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_H #define OS_CORE_H //////////////////////////////// //~ rjf: System Info typedef struct OS_SystemInfo OS_SystemInfo; struct OS_SystemInfo { U32 logical_processor_count; U64 page_size; U64 large_page_size; U64 allocation_granularity; String8 machine_name; }; //////////////////////////////// //~ rjf: Process Info typedef struct OS_ProcessInfo OS_ProcessInfo; struct OS_ProcessInfo { U32 pid; B32 large_pages_allowed; String8 binary_path; String8 initial_path; String8 user_program_data_path; String8List module_load_paths; String8List environment; }; //////////////////////////////// //~ rjf: Access Flags typedef U32 OS_AccessFlags; enum { OS_AccessFlag_Read = (1<<0), OS_AccessFlag_Write = (1<<1), OS_AccessFlag_Execute = (1<<2), OS_AccessFlag_Append = (1<<3), OS_AccessFlag_ShareRead = (1<<4), OS_AccessFlag_ShareWrite = (1<<5), OS_AccessFlag_Inherited = (1<<6), }; //////////////////////////////// //~ rjf: Files typedef U32 OS_FileIterFlags; enum { OS_FileIterFlag_SkipFolders = (1 << 0), OS_FileIterFlag_SkipFiles = (1 << 1), OS_FileIterFlag_SkipHiddenFiles = (1 << 2), OS_FileIterFlag_Done = (1 << 31), }; typedef struct OS_FileIter OS_FileIter; struct OS_FileIter { OS_FileIterFlags flags; U8 memory[800]; }; typedef struct OS_FileInfo OS_FileInfo; struct OS_FileInfo { String8 name; FileProperties props; }; // nick: on-disk file identifier typedef struct OS_FileID OS_FileID; struct OS_FileID { U64 v[3]; }; //////////////////////////////// //~ rjf: Handle Type typedef struct OS_Handle OS_Handle; struct OS_Handle { U64 u64[1]; }; typedef struct OS_HandleNode OS_HandleNode; struct OS_HandleNode { OS_HandleNode *next; OS_Handle v; }; typedef struct OS_HandleList OS_HandleList; struct OS_HandleList { OS_HandleNode *first; OS_HandleNode *last; U64 count; }; typedef struct OS_HandleArray OS_HandleArray; struct OS_HandleArray { OS_Handle *v; U64 count; }; //////////////////////////////// //~ rjf: Process Launch Parameters typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams; struct OS_ProcessLaunchParams { String8List cmd_line; String8 path; String8List env; B32 inherit_env; B32 debug_subprocesses; B32 consoleless; OS_Handle stdout_file; OS_Handle stderr_file; OS_Handle stdin_file; }; //////////////////////////////// //~ rjf: Thread Types typedef void OS_ThreadFunctionType(void *ptr); //////////////////////////////// //~ rjf: Handle Type Functions (Helpers, Implemented Once) internal OS_Handle os_handle_zero(void); internal B32 os_handle_match(OS_Handle a, OS_Handle b); internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle); internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list); //////////////////////////////// //~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once) internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv); //////////////////////////////// //~ rjf: Filesystem Helpers (Helpers, Implemented Once) internal String8 os_data_from_file_path(Arena *arena, String8 path); internal B32 os_write_data_to_file_path(String8 path, String8 data); internal B32 os_write_data_list_to_file_path(String8 path, String8List list); internal B32 os_append_data_to_file_path(String8 path, String8 data); internal OS_FileID os_id_from_file_path(String8 path); internal S64 os_file_id_compare(OS_FileID a, OS_FileID b); internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range); //////////////////////////////// //~ rjf: Process Launcher Helpers internal OS_Handle os_cmd_line_launch(String8 string); internal OS_Handle os_cmd_line_launchf(char *fmt, ...); //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo *os_get_system_info(void); internal OS_ProcessInfo *os_get_process_info(void); internal String8 os_get_current_path(Arena *arena); internal U32 os_get_process_start_time_unix(void); //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void *os_reserve(U64 size); internal B32 os_commit(void *ptr, U64 size); internal void os_decommit(void *ptr, U64 size); internal void os_release(void *ptr, U64 size); //- rjf: large pages internal void *os_reserve_large(U64 size); internal B32 os_commit_large(void *ptr, U64 size); //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void); internal void os_set_thread_name(String8 string); //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code); //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path); internal void os_file_close(OS_Handle file); internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data); #define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr)) internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data); internal B32 os_file_set_times(OS_Handle file, DateTime time); internal FileProperties os_properties_from_file(OS_Handle file); internal OS_FileID os_id_from_file(OS_Handle file); internal B32 os_file_reserve_size(OS_Handle file, U64 size); internal B32 os_delete_file_at_path(String8 path); internal B32 os_copy_file_path(String8 dst, String8 src); internal B32 os_move_file_path(String8 dst, String8 src); internal String8 os_full_path_from_path(Arena *arena, String8 path); internal B32 os_file_path_exists(String8 path); internal B32 os_folder_path_exists(String8 path); internal FileProperties os_properties_from_file_path(String8 path); //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file); internal void os_file_map_close(OS_Handle map); internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range); internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range); //- rjf: directory iteration internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags); internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out); internal void os_file_iter_end(OS_FileIter *iter); //- rjf: directory creation internal B32 os_make_directory(String8 path); //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name); internal OS_Handle os_shared_memory_open(String8 name); internal void os_shared_memory_close(OS_Handle handle); internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range); internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range); //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void); internal U32 os_now_unix(void); internal DateTime os_now_universal_time(void); internal DateTime os_universal_time_from_local(DateTime *local_time); internal DateTime os_local_time_from_universal(DateTime *universal_time); internal void os_sleep_milliseconds(U32 msec); //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params); internal B32 os_process_join(OS_Handle handle, U64 endt_us); internal void os_process_detach(OS_Handle handle); //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params); internal B32 os_thread_join(OS_Handle handle, U64 endt_us); internal void os_thread_detach(OS_Handle handle); //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: recursive mutexes internal OS_Handle os_mutex_alloc(void); internal void os_mutex_release(OS_Handle mutex); internal void os_mutex_take(OS_Handle mutex); internal void os_mutex_drop(OS_Handle mutex); //- rjf: reader/writer mutexes internal OS_Handle os_rw_mutex_alloc(void); internal void os_rw_mutex_release(OS_Handle rw_mutex); internal void os_rw_mutex_take_r(OS_Handle mutex); internal void os_rw_mutex_drop_r(OS_Handle mutex); internal void os_rw_mutex_take_w(OS_Handle mutex); internal void os_rw_mutex_drop_w(OS_Handle mutex); //- rjf: condition variables internal OS_Handle os_condition_variable_alloc(void); internal void os_condition_variable_release(OS_Handle cv); // returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us); internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us); internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us); internal void os_condition_variable_signal(OS_Handle cv); internal void os_condition_variable_broadcast(OS_Handle cv); //- rjf: cross-process semaphores internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name); internal void os_semaphore_release(OS_Handle semaphore); internal OS_Handle os_semaphore_open(String8 name); internal void os_semaphore_close(OS_Handle semaphore); internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us); internal void os_semaphore_drop(OS_Handle semaphore); //- rjf: scope macros #define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex)) #define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex)) #define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex)) #define OS_MutexScopeRWPromote(mutex) DeferLoop((os_rw_mutex_drop_r(mutex), os_rw_mutex_take_w(mutex)), (os_rw_mutex_drop_w(mutex), os_rw_mutex_take_r(mutex))) //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path); internal void os_library_close(OS_Handle lib); internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name); //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr); //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void); //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) // NOTE(rjf): The implementation of `os_core` will define low-level entry // points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call // into the standard codebase program entry points, named "entry_point". #if BUILD_ENTRY_DEFINING_UNIT internal void entry_point(CmdLine *cmdline); #endif #endif // OS_CORE_H ================================================ FILE: src/metagen/metagen_os/core/win32/metagen_os_core_win32.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Modern Windows SDK Functions // // (We must dynamically link to them, since they can be missing in older SDKs) typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); global W32_SetThreadDescription_Type *w32_SetThreadDescription_func = 0; //////////////////////////////// //~ rjf: File Info Conversion Helpers internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes) { FilePropertyFlags flags = 0; if(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { flags |= FilePropertyFlag_IsFolder; } return flags; } internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes) { properties->size = Compose64Bit(attributes->nFileSizeHigh, attributes->nFileSizeLow); os_w32_dense_time_from_file_time(&properties->created, &attributes->ftCreationTime); os_w32_dense_time_from_file_time(&properties->modified, &attributes->ftLastWriteTime); properties->flags = os_w32_file_property_flags_from_dwFileAttributes(attributes->dwFileAttributes); } //////////////////////////////// //~ rjf: Time Conversion Helpers internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in) { out->year = in->wYear; out->mon = in->wMonth - 1; out->wday = in->wDayOfWeek; out->day = in->wDay; out->hour = in->wHour; out->min = in->wMinute; out->sec = in->wSecond; out->msec = in->wMilliseconds; } internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in) { out->wYear = (WORD)(in->year); out->wMonth = in->mon + 1; out->wDay = in->day; out->wHour = in->hour; out->wMinute = in->min; out->wSecond = in->sec; out->wMilliseconds = in->msec; } internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in) { SYSTEMTIME systime = {0}; FileTimeToSystemTime(in, &systime); DateTime date_time = {0}; os_w32_date_time_from_system_time(&date_time, &systime); *out = dense_time_from_date_time(date_time); } internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us) { U32 sleep_ms = 0; if(endt_us == max_U64) { sleep_ms = INFINITE; } else { U64 begint = os_now_microseconds(); if(begint < endt_us) { U64 sleep_us = endt_us - begint; sleep_ms = (U32)((sleep_us + 999)/1000); } } return sleep_ms; } internal U32 os_w32_unix_time_from_file_time(FILETIME file_time) { U64 win32_time = ((U64)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime; U64 unix_time64 = ((win32_time - 0x19DB1DED53E8000ULL) / 10000000); Assert(unix_time64 <= max_U32); U32 unix_time32 = (U32)unix_time64; return unix_time32; } //////////////////////////////// //~ rjf: Entity Functions internal OS_W32_Entity * os_w32_entity_alloc(OS_W32_EntityKind kind) { OS_W32_Entity *result = 0; EnterCriticalSection(&os_w32_state.entity_mutex); { result = os_w32_state.entity_free; if(result) { SLLStackPop(os_w32_state.entity_free); } else { result = push_array_no_zero(os_w32_state.entity_arena, OS_W32_Entity, 1); } MemoryZeroStruct(result); } LeaveCriticalSection(&os_w32_state.entity_mutex); result->kind = kind; return result; } internal void os_w32_entity_release(OS_W32_Entity *entity) { entity->kind = OS_W32_EntityKind_Null; EnterCriticalSection(&os_w32_state.entity_mutex); SLLStackPush(os_w32_state.entity_free, entity); LeaveCriticalSection(&os_w32_state.entity_mutex); } //////////////////////////////// //~ rjf: Thread Entry Point internal DWORD os_w32_thread_entry_point(void *ptr) { OS_W32_Entity *entity = (OS_W32_Entity *)ptr; OS_ThreadFunctionType *func = entity->thread.func; void *thread_ptr = entity->thread.ptr; TCTX tctx_; tctx_init_and_equip(&tctx_); func(thread_ptr); tctx_release(); return 0; } //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo * os_get_system_info(void) { return &os_w32_state.system_info; } internal OS_ProcessInfo * os_get_process_info(void) { return &os_w32_state.process_info; } internal String8 os_get_current_path(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); DWORD length = GetCurrentDirectoryW(0, 0); U16 *memory = push_array_no_zero(scratch.arena, U16, length + 1); length = GetCurrentDirectoryW(length + 1, (WCHAR*)memory); String8 name = str8_from_16(arena, str16(memory, length)); scratch_end(scratch); return name; } internal U32 os_get_process_start_time_unix(void) { HANDLE handle = GetCurrentProcess(); FILETIME start_time = {0}; FILETIME exit_time; FILETIME kernel_time; FILETIME user_time; if(GetProcessTimes(handle, &start_time, &exit_time, &kernel_time, &user_time)) { return os_w32_unix_time_from_file_time(start_time); } return 0; } //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void * os_reserve(U64 size) { void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); return result; } internal B32 os_commit(void *ptr, U64 size) { B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); return result; } internal void os_decommit(void *ptr, U64 size) { VirtualFree(ptr, size, MEM_DECOMMIT); } internal void os_release(void *ptr, U64 size) { // NOTE(rjf): size not used - not necessary on Windows, but necessary for other OSes. VirtualFree(ptr, 0, MEM_RELEASE); } //- rjf: large pages internal void * os_reserve_large(U64 size) { // we commit on reserve because windows void *result = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE); return result; } internal B32 os_commit_large(void *ptr, U64 size) { return 1; } //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void) { DWORD id = GetCurrentThreadId(); return (U32)id; } internal void os_set_thread_name(String8 name) { Temp scratch = scratch_begin(0, 0); // rjf: windows 10 style if(w32_SetThreadDescription_func) { String16 name16 = str16_from_8(scratch.arena, name); HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str); } // rjf: raise-exception style { String8 name_copy = push_str8_copy(scratch.arena, name); #pragma pack(push,8) typedef struct THREADNAME_INFO THREADNAME_INFO; struct THREADNAME_INFO { U32 dwType; // Must be 0x1000. char *szName; // Pointer to name (in user addr space). U32 dwThreadID; // Thread ID (-1=caller thread). U32 dwFlags; // Reserved for future use, must be zero. }; #pragma pack(pop) THREADNAME_INFO info; info.dwType = 0x1000; info.szName = (char *)name_copy.str; info.dwThreadID = os_tid(); info.dwFlags = 0; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except (EXCEPTION_EXECUTE_HANDLER) { } #pragma warning(pop) } scratch_end(scratch); } //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code) { ExitProcess(exit_code); } //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { OS_Handle result = {0}; Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); DWORD access_flags = 0; DWORD share_mode = 0; DWORD creation_disposition = OPEN_EXISTING; SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0}; if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;} if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;} if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;} if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;} if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;} if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;} if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; } if(flags & OS_AccessFlag_Inherited) { security_attributes.bInheritHandle = 1; } HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, &security_attributes, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0); if(file != INVALID_HANDLE_VALUE) { result.u64[0] = (U64)file; } scratch_end(scratch); return result; } internal void os_file_close(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return; } HANDLE handle = (HANDLE)file.u64[0]; BOOL result = CloseHandle(handle); (void)result; } internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) { if(os_handle_match(file, os_handle_zero())) { return 0; } HANDLE handle = (HANDLE)file.u64[0]; // rjf: clamp range by file size U64 size = 0; GetFileSizeEx(handle, (LARGE_INTEGER *)&size); Rng1U64 rng_clamped = r1u64(ClampTop(rng.min, size), ClampTop(rng.max, size)); U64 total_read_size = 0; // rjf: read loop { U64 to_read = dim_1u64(rng_clamped); for(U64 off = rng.min; total_read_size < to_read;) { U64 amt64 = to_read - total_read_size; U32 amt32 = u32_from_u64_saturate(amt64); DWORD read_size = 0; OVERLAPPED overlapped = {0}; overlapped.Offset = (off&0x00000000ffffffffull); overlapped.OffsetHigh = (off&0xffffffff00000000ull) >> 32; ReadFile(handle, (U8 *)out_data + total_read_size, amt32, &read_size, &overlapped); off += read_size; total_read_size += read_size; if(read_size != amt32) { break; } } } return total_read_size; } internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data) { if(os_handle_match(file, os_handle_zero())) { return 0; } HANDLE win_handle = (HANDLE)file.u64[0]; U64 src_off = 0; U64 dst_off = rng.min; U64 total_write_size = dim_1u64(rng); for(;;) { void *bytes_src = (U8 *)data + src_off; U64 bytes_left = total_write_size - src_off; DWORD write_size = Min(MB(1), bytes_left); DWORD bytes_written = 0; OVERLAPPED overlapped = {0}; overlapped.Offset = (dst_off&0x00000000ffffffffull); overlapped.OffsetHigh = (dst_off&0xffffffff00000000ull) >> 32; BOOL success = WriteFile(win_handle, bytes_src, write_size, &bytes_written, &overlapped); if(success == 0) { break; } src_off += bytes_written; dst_off += bytes_written; if(bytes_left == 0) { break; } } return src_off; } internal B32 os_file_set_time(OS_Handle file, DateTime time) { if(os_handle_match(file, os_handle_zero())) { return 0; } B32 result = 0; HANDLE handle = (HANDLE)file.u64[0]; SYSTEMTIME system_time = {0}; os_w32_system_time_from_date_time(&system_time, &time); FILETIME file_time = {0}; result = (SystemTimeToFileTime(&system_time, &file_time) && SetFileTime(handle, &file_time, &file_time, &file_time)); return result; } internal FileProperties os_properties_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { FileProperties r = {0}; return r; } FileProperties props = {0}; HANDLE handle = (HANDLE)file.u64[0]; BY_HANDLE_FILE_INFORMATION info; BOOL info_good = GetFileInformationByHandle(handle, &info); if(info_good) { U32 size_lo = info.nFileSizeLow; U32 size_hi = info.nFileSizeHigh; props.size = (U64)size_lo | (((U64)size_hi)<<32); os_w32_dense_time_from_file_time(&props.modified, &info.ftLastWriteTime); os_w32_dense_time_from_file_time(&props.created, &info.ftCreationTime); props.flags = os_w32_file_property_flags_from_dwFileAttributes(info.dwFileAttributes); } return props; } internal OS_FileID os_id_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { OS_FileID r = {0}; return r; } OS_FileID result = {0}; HANDLE handle = (HANDLE)file.u64[0]; BY_HANDLE_FILE_INFORMATION info; BOOL is_ok = GetFileInformationByHandle(handle, &info); if(is_ok) { result.v[0] = info.dwVolumeSerialNumber; result.v[1] = info.nFileIndexLow; result.v[2] = info.nFileIndexHigh; } return result; } internal B32 os_file_reserve_size(OS_Handle file, U64 size) { HANDLE handle = (HANDLE)file.u64[0]; FILE_ALLOCATION_INFO alloc_info = {0}; alloc_info.AllocationSize.LowPart = size & max_U32; alloc_info.AllocationSize.HighPart = (size >> 32) & max_U32; BOOL is_reserved = SetFileInformationByHandle(handle, FileAllocationInfo, &alloc_info, sizeof(alloc_info)); return is_reserved; } internal B32 os_delete_file_at_path(String8 path) { Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); B32 result = DeleteFileW((WCHAR*)path16.str); scratch_end(scratch); return result; } internal B32 os_copy_file_path(String8 dst, String8 src) { Temp scratch = scratch_begin(0, 0); String16 dst16 = str16_from_8(scratch.arena, dst); String16 src16 = str16_from_8(scratch.arena, src); B32 result = CopyFileW((WCHAR*)src16.str, (WCHAR*)dst16.str, 0); scratch_end(scratch); return result; } internal B32 os_move_file_path(String8 dst, String8 src) { Temp scratch = scratch_begin(0, 0); String16 dst16 = str16_from_8(scratch.arena, dst); String16 src16 = str16_from_8(scratch.arena, src); B32 result = MoveFileW((WCHAR*)src16.str, (WCHAR*)dst16.str); scratch_end(scratch); return result; } internal String8 os_full_path_from_path(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); DWORD buffer_size = Max(MAX_PATH, path.size * 2) + 1; String16 path16 = str16_from_8(scratch.arena, path); WCHAR *buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); DWORD path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); if(path16_size > buffer_size) { arena_pop(scratch.arena, buffer_size); buffer_size = path16_size + 1; buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); } String8 full_path = str8_from_16(arena, str16((U16*)buffer, path16_size)); scratch_end(scratch); return full_path; } internal B32 os_file_path_exists(String8 path) { Temp scratch = scratch_begin(0,0); String16 path16 = str16_from_8(scratch.arena, path); DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && !!(~attributes & FILE_ATTRIBUTE_DIRECTORY); scratch_end(scratch); return exists; } internal B32 os_folder_path_exists(String8 path) { Temp scratch = scratch_begin(0,0); String16 path16 = str16_from_8(scratch.arena, path); DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY); scratch_end(scratch); return exists; } internal FileProperties os_properties_from_file_path(String8 path) { WIN32_FIND_DATAW find_data = {0}; Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); HANDLE handle = FindFirstFileW((WCHAR *)path16.str, &find_data); FileProperties props = {0}; if(handle != INVALID_HANDLE_VALUE) { props.size = Compose64Bit(find_data.nFileSizeHigh, find_data.nFileSizeLow); os_w32_dense_time_from_file_time(&props.created, &find_data.ftCreationTime); os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime); props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes); } else { Temp scratch = scratch_begin(0, 0); WCHAR buffer[512] = {0}; DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); U64 last_slash_pos = 0; for(;last_slash_pos < path.size; last_slash_pos = str8_find_needle(path, last_slash_pos+1, str8_lit("/"), StringMatchFlag_SlashInsensitive)); String8 path_trimmed = str8_prefix(path, last_slash_pos); for(U64 off = 0; off < (U64)length;) { String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); off += next_drive_string_16.size+1; String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16); next_drive_string = str8_chop_last_slash(next_drive_string); if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive)) { props.flags |= FilePropertyFlag_IsFolder; break; } } scratch_end(scratch); } FindClose(handle); scratch_end(scratch); return props; } //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file) { OS_Handle map = {0}; { HANDLE file_handle = (HANDLE)file.u64[0]; DWORD protect_flags = 0; { switch(flags) { default:{}break; case OS_AccessFlag_Read: {protect_flags = PAGE_READONLY;}break; case OS_AccessFlag_Write: case OS_AccessFlag_Read|OS_AccessFlag_Write: {protect_flags = PAGE_READWRITE;}break; case OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Execute: {protect_flags = PAGE_EXECUTE_READ;}break; case OS_AccessFlag_Execute|OS_AccessFlag_Write|OS_AccessFlag_Read: case OS_AccessFlag_Execute|OS_AccessFlag_Write: {protect_flags = PAGE_EXECUTE_READWRITE;}break; } } HANDLE map_handle = CreateFileMappingA(file_handle, 0, protect_flags, 0, 0, 0); map.u64[0] = (U64)map_handle; } return map; } internal void os_file_map_close(OS_Handle map) { HANDLE handle = (HANDLE)map.u64[0]; BOOL result = CloseHandle(handle); (void)result; } internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) { HANDLE handle = (HANDLE)map.u64[0]; U32 off_lo = (U32)((range.min&0x00000000ffffffffull)>>0); U32 off_hi = (U32)((range.min&0xffffffff00000000ull)>>32); U64 size = dim_1u64(range); DWORD access_flags = 0; { switch(flags) { default:{}break; case OS_AccessFlag_Read: { access_flags = FILE_MAP_READ; }break; case OS_AccessFlag_Write: { access_flags = FILE_MAP_WRITE; }break; case OS_AccessFlag_Read|OS_AccessFlag_Write: { access_flags = FILE_MAP_ALL_ACCESS; }break; case OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Execute: case OS_AccessFlag_Write|OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Write|OS_AccessFlag_Execute: { access_flags = FILE_MAP_ALL_ACCESS|FILE_MAP_EXECUTE; }break; } } void *result = MapViewOfFile(handle, access_flags, off_hi, off_lo, size); return result; } internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) { BOOL result = UnmapViewOfFile(ptr); (void)result; } //- rjf: directory iteration internal OS_FileIter * os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8 path_with_wildcard = push_str8_cat(scratch.arena, path, str8_lit("\\*")); String16 path16 = str16_from_8(scratch.arena, path_with_wildcard); OS_FileIter *iter = push_array(arena, OS_FileIter, 1); iter->flags = flags; OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; if(path.size == 0) { w32_iter->is_volume_iter = 1; WCHAR buffer[512] = {0}; DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); String8List drive_strings = {0}; for(U64 off = 0; off < (U64)length;) { String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); off += next_drive_string_16.size+1; String8 next_drive_string = str8_from_16(arena, next_drive_string_16); next_drive_string = str8_chop_last_slash(next_drive_string); str8_list_push(scratch.arena, &drive_strings, next_drive_string); } w32_iter->drive_strings = str8_array_from_list(arena, &drive_strings); w32_iter->drive_strings_iter_idx = 0; } else { w32_iter->handle = FindFirstFileW((WCHAR*)path16.str, &w32_iter->find_data); } scratch_end(scratch); return iter; } internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { B32 result = 0; OS_FileIterFlags flags = iter->flags; OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; switch(w32_iter->is_volume_iter) { //- rjf: file iteration default: case 0: { if (!(flags & OS_FileIterFlag_Done) && w32_iter->handle != INVALID_HANDLE_VALUE) { do { // check is usable B32 usable_file = 1; WCHAR *file_name = w32_iter->find_data.cFileName; DWORD attributes = w32_iter->find_data.dwFileAttributes; if (file_name[0] == '.'){ if (flags & OS_FileIterFlag_SkipHiddenFiles){ usable_file = 0; } else if (file_name[1] == 0){ usable_file = 0; } else if (file_name[1] == '.' && file_name[2] == 0){ usable_file = 0; } } if (attributes & FILE_ATTRIBUTE_DIRECTORY){ if (flags & OS_FileIterFlag_SkipFolders){ usable_file = 0; } } else{ if (flags & OS_FileIterFlag_SkipFiles){ usable_file = 0; } } // emit if usable if (usable_file){ info_out->name = str8_from_16(arena, str16_cstring((U16*)file_name)); info_out->props.size = (U64)w32_iter->find_data.nFileSizeLow | (((U64)w32_iter->find_data.nFileSizeHigh)<<32); os_w32_dense_time_from_file_time(&info_out->props.created, &w32_iter->find_data.ftCreationTime); os_w32_dense_time_from_file_time(&info_out->props.modified, &w32_iter->find_data.ftLastWriteTime); info_out->props.flags = os_w32_file_property_flags_from_dwFileAttributes(attributes); result = 1; if (!FindNextFileW(w32_iter->handle, &w32_iter->find_data)){ iter->flags |= OS_FileIterFlag_Done; } break; } }while(FindNextFileW(w32_iter->handle, &w32_iter->find_data)); } }break; //- rjf: volume iteration case 1: { result = w32_iter->drive_strings_iter_idx < w32_iter->drive_strings.count; if(result != 0) { MemoryZeroStruct(info_out); info_out->name = w32_iter->drive_strings.v[w32_iter->drive_strings_iter_idx]; info_out->props.flags |= FilePropertyFlag_IsFolder; w32_iter->drive_strings_iter_idx += 1; } }break; } if(!result) { iter->flags |= OS_FileIterFlag_Done; } return result; } internal void os_file_iter_end(OS_FileIter *iter) { OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; HANDLE zero_handle; MemoryZeroStruct(&zero_handle); if(!MemoryMatchStruct(&zero_handle, &w32_iter->handle)) { FindClose(w32_iter->handle); } } //- rjf: directory creation internal B32 os_make_directory(String8 path) { B32 result = 0; Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, path); WIN32_FILE_ATTRIBUTE_DATA attributes = {0}; GetFileAttributesExW((WCHAR*)name16.str, GetFileExInfoStandard, &attributes); if(attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { result = 1; } else if(CreateDirectoryW((WCHAR*)name16.str, 0)) { result = 1; } scratch_end(scratch); return(result); } //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE file = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, (U32)((size & 0xffffffff00000000) >> 32), (U32)((size & 0x00000000ffffffff)), (WCHAR *)name16.str); OS_Handle result = {(U64)file}; scratch_end(scratch); return result; } internal OS_Handle os_shared_memory_open(String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE file = OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, (WCHAR *)name16.str); OS_Handle result = {(U64)file}; scratch_end(scratch); return result; } internal void os_shared_memory_close(OS_Handle handle) { HANDLE file = (HANDLE)(handle.u64[0]); CloseHandle(file); } internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) { HANDLE file = (HANDLE)(handle.u64[0]); U64 offset = range.min; U64 size = range.max-range.min; void *ptr = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, (U32)((offset & 0xffffffff00000000) >> 32), (U32)((offset & 0x00000000ffffffff)), size); return ptr; } internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) { UnmapViewOfFile(ptr); } //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void) { U64 result = 0; LARGE_INTEGER large_int_counter; if(QueryPerformanceCounter(&large_int_counter)) { result = (large_int_counter.QuadPart*Million(1))/os_w32_state.microsecond_resolution; } return result; } internal U32 os_now_unix(void) { FILETIME file_time; GetSystemTimeAsFileTime(&file_time); U32 unix_time = os_w32_unix_time_from_file_time(file_time); return unix_time; } internal DateTime os_now_universal_time(void) { SYSTEMTIME systime = {0}; GetSystemTime(&systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal DateTime os_universal_time_from_local(DateTime *date_time) { SYSTEMTIME systime = {0}; os_w32_system_time_from_date_time(&systime, date_time); FILETIME ftime = {0}; SystemTimeToFileTime(&systime, &ftime); FILETIME ftime_local = {0}; LocalFileTimeToFileTime(&ftime, &ftime_local); FileTimeToSystemTime(&ftime_local, &systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal DateTime os_local_time_from_universal(DateTime *date_time) { SYSTEMTIME systime = {0}; os_w32_system_time_from_date_time(&systime, date_time); FILETIME ftime = {0}; SystemTimeToFileTime(&systime, &ftime); FILETIME ftime_local = {0}; FileTimeToLocalFileTime(&ftime, &ftime_local); FileTimeToSystemTime(&ftime_local, &systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal void os_sleep_milliseconds(U32 msec) { Sleep(msec); } //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params) { OS_Handle result = {0}; Temp scratch = scratch_begin(0, 0); //- rjf: form full command string String8 cmd = {0}; { StringJoin join_params = {0}; join_params.pre = str8_lit("\""); join_params.sep = str8_lit("\" \""); join_params.post = str8_lit("\""); cmd = str8_list_join(scratch.arena, ¶ms->cmd_line, &join_params); } //- rjf: form environment B32 use_null_env_arg = 0; String8 env = {0}; { StringJoin join_params2 = {0}; join_params2.sep = str8_lit("\0"); join_params2.post = str8_lit("\0"); String8List all_opts = params->env; if(params->inherit_env != 0) { if(all_opts.node_count != 0) { MemoryZeroStruct(&all_opts); for(String8Node *n = params->env.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } for(String8Node *n = os_w32_state.process_info.environment.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } } else { use_null_env_arg = 1; } } if(use_null_env_arg == 0) { env = str8_list_join(scratch.arena, &all_opts, &join_params2); } } //- rjf: utf-8 -> utf-16 String16 cmd16 = str16_from_8(scratch.arena, cmd); String16 dir16 = str16_from_8(scratch.arena, params->path); String16 env16 = {0}; if(use_null_env_arg == 0) { env16 = str16_from_8(scratch.arena, env); } //- rjf: determine creation flags DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT; if(params->consoleless) { creation_flags |= CREATE_NO_WINDOW; } //- rjf: launch BOOL inherit_handles = 0; STARTUPINFOW startup_info = {sizeof(startup_info)}; if(!os_handle_match(params->stdout_file, os_handle_zero())) { HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0]; startup_info.hStdOutput = stdout_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stderr_file, os_handle_zero())) { HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0]; startup_info.hStdError = stderr_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stdin_file, os_handle_zero())) { HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0]; startup_info.hStdInput = stdin_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } PROCESS_INFORMATION process_info = {0}; if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, inherit_handles, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info)) { result.u64[0] = (U64)process_info.hProcess; CloseHandle(process_info.hThread); } scratch_end(scratch); return result; } internal B32 os_process_join(OS_Handle handle, U64 endt_us) { HANDLE process = (HANDLE)(handle.u64[0]); DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); DWORD result = WaitForSingleObject(process, sleep_ms); return (result == WAIT_OBJECT_0); } internal void os_process_detach(OS_Handle handle) { HANDLE process = (HANDLE)(handle.u64[0]); CloseHandle(process); } //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Thread); entity->thread.func = func; entity->thread.ptr = ptr; entity->thread.handle = CreateThread(0, 0, os_w32_thread_entry_point, entity, 0, &entity->thread.tid); OS_Handle result = {IntFromPtr(entity)}; return result; } internal B32 os_thread_join(OS_Handle handle, U64 endt_us) { DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); OS_W32_Entity *entity = (OS_W32_Entity *)PtrFromInt(handle.u64[0]); DWORD wait_result = WAIT_OBJECT_0; if(entity != 0) { wait_result = WaitForSingleObject(entity->thread.handle, sleep_ms); CloseHandle(entity->thread.handle); os_w32_entity_release(entity); } return (wait_result == WAIT_OBJECT_0); } internal void os_thread_detach(OS_Handle thread) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(thread.u64[0]); if(entity != 0) { CloseHandle(entity->thread.handle); os_w32_entity_release(entity); } } //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: mutexes internal OS_Handle os_mutex_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Mutex); InitializeCriticalSection(&entity->mutex); OS_Handle result = {IntFromPtr(entity)}; return result; } internal void os_mutex_release(OS_Handle mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); os_w32_entity_release(entity); } internal void os_mutex_take(OS_Handle mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); EnterCriticalSection(&entity->mutex); } internal void os_mutex_drop(OS_Handle mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); LeaveCriticalSection(&entity->mutex); } //- rjf: reader/writer mutexes internal OS_Handle os_rw_mutex_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_RWMutex); InitializeSRWLock(&entity->rw_mutex); OS_Handle result = {IntFromPtr(entity)}; return result; } internal void os_rw_mutex_release(OS_Handle rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); os_w32_entity_release(entity); } internal void os_rw_mutex_take_r(OS_Handle rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); AcquireSRWLockShared(&entity->rw_mutex); } internal void os_rw_mutex_drop_r(OS_Handle rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); ReleaseSRWLockShared(&entity->rw_mutex); } internal void os_rw_mutex_take_w(OS_Handle rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); AcquireSRWLockExclusive(&entity->rw_mutex); } internal void os_rw_mutex_drop_w(OS_Handle rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); ReleaseSRWLockExclusive(&entity->rw_mutex); } //- rjf: condition variables internal OS_Handle os_condition_variable_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_ConditionVariable); InitializeConditionVariable(&entity->cv); OS_Handle result = {IntFromPtr(entity)}; return result; } internal void os_condition_variable_release(OS_Handle cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); os_w32_entity_release(entity); } internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if(sleep_ms > 0) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); result = SleepConditionVariableCS(&entity->cv, &mutex_entity->mutex, sleep_ms); } return result; } internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if(sleep_ms > 0) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, CONDITION_VARIABLE_LOCKMODE_SHARED); } return result; } internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if(sleep_ms > 0) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, 0); } return result; } internal void os_condition_variable_signal(OS_Handle cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); WakeConditionVariable(&entity->cv); } internal void os_condition_variable_broadcast(OS_Handle cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); WakeAllConditionVariable(&entity->cv); } //- rjf: cross-process semaphores internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE handle = CreateSemaphoreW(0, initial_count, max_count, (WCHAR *)name16.str); OS_Handle result = {(U64)handle}; scratch_end(scratch); return result; } internal void os_semaphore_release(OS_Handle semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; CloseHandle(handle); } internal OS_Handle os_semaphore_open(String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS , 0, (WCHAR *)name16.str); OS_Handle result = {(U64)handle}; scratch_end(scratch); return result; } internal void os_semaphore_close(OS_Handle semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; CloseHandle(handle); } internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); HANDLE handle = (HANDLE)semaphore.u64[0]; DWORD wait_result = WaitForSingleObject(handle, sleep_ms); B32 result = (wait_result == WAIT_OBJECT_0); return result; } internal void os_semaphore_drop(OS_Handle semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; ReleaseSemaphore(handle, 1, 0); } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); HMODULE mod = LoadLibraryW((LPCWSTR)path16.str); OS_Handle result = { (U64)mod }; scratch_end(scratch); return result; } internal VoidProc* os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); HMODULE mod = (HMODULE)lib.u64[0]; name = push_str8_copy(scratch.arena, name); VoidProc *result = (VoidProc*)GetProcAddress(mod, (LPCSTR)name.str); scratch_end(scratch); return result; } internal void os_library_close(OS_Handle lib) { HMODULE mod = (HMODULE)lib.u64[0]; FreeLibrary(mod); } //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr) { __try { func(ptr); } __except (EXCEPTION_EXECUTE_HANDLER) { if(fail_handler != 0) { fail_handler(ptr); } ExitProcess(1); } } //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void) { Guid result; MemoryZeroStruct(&result); UUID uuid; RPC_STATUS rpc_status = UuidCreate(&uuid); if(rpc_status == RPC_S_OK) { result.data1 = uuid.Data1; result.data2 = uuid.Data2; result.data3 = uuid.Data3; MemoryCopyArray(result.data4, uuid.Data4); } return result; } //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) #include #undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside #include internal B32 win32_g_is_quiet = 0; internal HRESULT WINAPI win32_dialog_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LONG_PTR data) { if(msg == TDN_HYPERLINK_CLICKED) { ShellExecuteW(NULL, L"open", (LPWSTR)lparam, NULL, NULL, SW_SHOWNORMAL); } return S_OK; } internal LONG WINAPI win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs) { if(win32_g_is_quiet) { ExitProcess(1); } static volatile LONG first = 0; if(InterlockedCompareExchange(&first, 1, 0) != 0) { // prevent failures in other threads to popup same message box // this handler just shows first thread that crashes // we are terminating afterwards anyway for (;;) Sleep(1000); } WCHAR buffer[4096] = {0}; int buflen = 0; DWORD exception_code = exception_ptrs->ExceptionRecord->ExceptionCode; buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"A fatal exception (code 0x%x) occurred. The process is terminating.\n", exception_code); // load dbghelp dynamically just in case if it is missing HMODULE dbghelp = LoadLibraryA("dbghelp.dll"); if(dbghelp) { DWORD (WINAPI *dbg_SymSetOptions)(DWORD SymOptions); BOOL (WINAPI *dbg_SymInitializeW)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess); BOOL (WINAPI *dbg_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); PVOID (WINAPI *dbg_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase); DWORD64 (WINAPI *dbg_SymGetModuleBase64)(HANDLE hProcess, DWORD64 qwAddr); BOOL (WINAPI *dbg_SymFromAddrW)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFOW Symbol); BOOL (WINAPI *dbg_SymGetLineFromAddrW64)(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line); BOOL (WINAPI *dbg_SymGetModuleInfoW64)(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULEW64 ModuleInfo); *(FARPROC*)&dbg_SymSetOptions = GetProcAddress(dbghelp, "SymSetOptions"); *(FARPROC*)&dbg_SymInitializeW = GetProcAddress(dbghelp, "SymInitializeW"); *(FARPROC*)&dbg_StackWalk64 = GetProcAddress(dbghelp, "StackWalk64"); *(FARPROC*)&dbg_SymFunctionTableAccess64 = GetProcAddress(dbghelp, "SymFunctionTableAccess64"); *(FARPROC*)&dbg_SymGetModuleBase64 = GetProcAddress(dbghelp, "SymGetModuleBase64"); *(FARPROC*)&dbg_SymFromAddrW = GetProcAddress(dbghelp, "SymFromAddrW"); *(FARPROC*)&dbg_SymGetLineFromAddrW64 = GetProcAddress(dbghelp, "SymGetLineFromAddrW64"); *(FARPROC*)&dbg_SymGetModuleInfoW64 = GetProcAddress(dbghelp, "SymGetModuleInfoW64"); if(dbg_SymSetOptions && dbg_SymInitializeW && dbg_StackWalk64 && dbg_SymFunctionTableAccess64 && dbg_SymGetModuleBase64 && dbg_SymFromAddrW && dbg_SymGetLineFromAddrW64 && dbg_SymGetModuleInfoW64) { HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); CONTEXT* context = exception_ptrs->ContextRecord; WCHAR module_path[MAX_PATH]; GetModuleFileNameW(NULL, module_path, ArrayCount(module_path)); PathRemoveFileSpecW(module_path); dbg_SymSetOptions(SYMOPT_EXACT_SYMBOLS | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); if(dbg_SymInitializeW(process, module_path, TRUE)) { // check that raddbg.pdb file is good B32 raddbg_pdb_valid = 0; { IMAGEHLP_MODULEW64 module = {0}; module.SizeOfStruct = sizeof(module); if(dbg_SymGetModuleInfoW64(process, (DWORD64)&win32_exception_filter, &module)) { raddbg_pdb_valid = (module.SymType == SymPdb); } } if(!raddbg_pdb_valid) { buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"\nThe PDB debug information file for this executable is not valid or was not found. Please rebuild binary to get the call stack.\n"); } else { STACKFRAME64 frame = {0}; DWORD image_type; #if defined(_M_AMD64) image_type = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Offset = context->Rip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Rbp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Rsp; frame.AddrStack.Mode = AddrModeFlat; #elif defined(_M_ARM64) image_type = IMAGE_FILE_MACHINE_ARM64; frame.AddrPC.Offset = context->Pc; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Fp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Sp; frame.AddrStack.Mode = AddrModeFlat; #else # error Arch not supported! #endif for(U32 idx=0; ;idx++) { const U32 max_frames = 32; if(idx == max_frames) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"..."); break; } if(!dbg_StackWalk64(image_type, process, thread, &frame, context, 0, dbg_SymFunctionTableAccess64, dbg_SymGetModuleBase64, 0)) { break; } U64 address = frame.AddrPC.Offset; if(address == 0) { break; } if(idx==0) { #if BUILD_CONSOLE_INTERFACE buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nCreate a new issue with this report at %S.\n\n", BUILD_ISSUES_LINK_STRING_LITERAL); #else buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nPress Ctrl+C to copy this text to clipboard, then create a new issue at\n" L"%S\n\n", BUILD_ISSUES_LINK_STRING_LITERAL, BUILD_ISSUES_LINK_STRING_LITERAL); #endif buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"Call stack:\n"); } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"%u. [0x%I64x]", idx + 1, address); struct { SYMBOL_INFOW info; WCHAR name[MAX_SYM_NAME]; } symbol = {0}; symbol.info.SizeOfStruct = sizeof(symbol.info); symbol.info.MaxNameLen = MAX_SYM_NAME; DWORD64 displacement = 0; if(dbg_SymFromAddrW(process, address, &displacement, &symbol.info)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s +%u", symbol.info.Name, (DWORD)displacement); IMAGEHLP_LINEW64 line = {0}; line.SizeOfStruct = sizeof(line); DWORD line_displacement = 0; if(dbg_SymGetLineFromAddrW64(process, address, &line_displacement, &line)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L", %s line %u", PathFindFileNameW(line.FileName), line.LineNumber); } } else { IMAGEHLP_MODULEW64 module = {0}; module.SizeOfStruct = sizeof(module); if(dbg_SymGetModuleInfoW64(process, address, &module)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s", module.ModuleName); } } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\n"); } } } } } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nVersion: %S%S", BUILD_VERSION_STRING_LITERAL, BUILD_GIT_HASH_STRING_LITERAL_APPEND); #if BUILD_CONSOLE_INTERFACE fwprintf(stderr, L"\n--- Fatal Exception ---\n"); fwprintf(stderr, L"%s\n\n", buffer); #else TASKDIALOGCONFIG dialog = {0}; dialog.cbSize = sizeof(dialog); dialog.dwFlags = TDF_SIZE_TO_CONTENT | TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION; dialog.pszMainIcon = TD_ERROR_ICON; dialog.dwCommonButtons = TDCBF_CLOSE_BUTTON; dialog.pszWindowTitle = L"Fatal Exception"; dialog.pszContent = buffer; dialog.pfCallback = &win32_dialog_callback; TaskDialogIndirect(&dialog, 0, 0, 0); #endif ExitProcess(1); } #undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside #define OS_WINDOWS 1 internal void w32_entry_point_caller(int argc, WCHAR **wargv) { SetUnhandledExceptionFilter(&win32_exception_filter); //- rjf: dynamically load windows functions which are not guaranteed // in all SDKs { HMODULE module = LoadLibraryA("kernel32.dll"); w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription"); FreeLibrary(module); } //- rjf: try to allow large pages if we can B32 large_pages_allowed = 0; { HANDLE token; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { LUID luid; if(LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) { TOKEN_PRIVILEGES priv; priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; large_pages_allowed = !!AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0); } CloseHandle(token); } } //- rjf: get system info SYSTEM_INFO sysinfo = {0}; GetSystemInfo(&sysinfo); //- rjf: set up non-dynamically-alloc'd state // // (we need to set up some basics before this layer can supply // memory allocation primitives) { os_w32_state.microsecond_resolution = 1; LARGE_INTEGER large_int_resolution; if(QueryPerformanceFrequency(&large_int_resolution)) { os_w32_state.microsecond_resolution = large_int_resolution.QuadPart; } } { OS_SystemInfo *info = &os_w32_state.system_info; info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors; info->page_size = sysinfo.dwPageSize; info->large_page_size = GetLargePageMinimum(); info->allocation_granularity = sysinfo.dwAllocationGranularity; } { OS_ProcessInfo *info = &os_w32_state.process_info; info->large_pages_allowed = large_pages_allowed; info->pid = GetCurrentProcessId(); } //- rjf: extract arguments Arena *args_arena = arena_alloc(.reserve_size = MB(1), .commit_size = KB(32)); char **argv = push_array(args_arena, char *, argc); for(int i = 0; i < argc; i += 1) { String16 arg16 = str16_cstring((U16 *)wargv[i]); String8 arg8 = str8_from_16(args_arena, arg16); if(str8_match(arg8, str8_lit("--quiet"), StringMatchFlag_CaseInsensitive) || str8_match(arg8, str8_lit("-quiet"), StringMatchFlag_CaseInsensitive)) { win32_g_is_quiet = 1; } if(str8_match(arg8, str8_lit("--large_pages"), StringMatchFlag_CaseInsensitive) || str8_match(arg8, str8_lit("-large_pages"), StringMatchFlag_CaseInsensitive)) { arena_default_flags = ArenaFlag_LargePages; arena_default_reserve_size = Max(MB(64), os_w32_state.system_info.large_page_size); arena_default_commit_size = arena_default_reserve_size; } argv[i] = (char *)arg8.str; } //- rjf: set up thread context local_persist TCTX tctx; tctx_init_and_equip(&tctx); //- rjf: set up dynamically-alloc'd state Arena *arena = arena_alloc(); { os_w32_state.arena = arena; { OS_SystemInfo *info = &os_w32_state.system_info; U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0}; DWORD size = MAX_COMPUTERNAME_LENGTH + 1; if(GetComputerNameA((char*)buffer, &size)) { info->machine_name = push_str8_copy(arena, str8(buffer, size)); } } } { OS_ProcessInfo *info = &os_w32_state.process_info; { Temp scratch = scratch_begin(0, 0); DWORD size = KB(32); U16 *buffer = push_array_no_zero(scratch.arena, U16, size); DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size); String8 name8 = str8_from_16(scratch.arena, str16(buffer, length)); String8 name_chopped = str8_chop_last_slash(name8); info->binary_path = push_str8_copy(arena, name_chopped); scratch_end(scratch); } info->initial_path = os_get_current_path(arena); { Temp scratch = scratch_begin(0, 0); U64 size = KB(32); U16 *buffer = push_array_no_zero(scratch.arena, U16, size); if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer))) { info->user_program_data_path = str8_from_16(arena, str16_cstring(buffer)); } scratch_end(scratch); } { WCHAR *this_proc_env = GetEnvironmentStringsW(); U64 start_idx = 0; for(U64 idx = 0;; idx += 1) { if(this_proc_env[idx] == 0) { if(start_idx == idx) { break; } else { String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx); String8 string = str8_from_16(arena, string16); str8_list_push(arena, &info->environment, string); start_idx = idx+1; } } } } } //- rjf: set up entity storage InitializeCriticalSection(&os_w32_state.entity_mutex); os_w32_state.entity_arena = arena_alloc(); //- rjf: call into "real" entry point main_thread_base_entry_point(argc, argv); } #if BUILD_CONSOLE_INTERFACE int wmain(int argc, WCHAR **argv) { w32_entry_point_caller(argc, argv); return 0; } #else int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { w32_entry_point_caller(__argc, __wargv); return 0; } #endif ================================================ FILE: src/metagen/metagen_os/core/win32/metagen_os_core_win32.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_WIN32_H #define OS_CORE_WIN32_H //////////////////////////////// //~ rjf: Includes / Libraries #include #include #include #include #include #include #pragma comment(lib, "user32") #pragma comment(lib, "winmm") #pragma comment(lib, "shell32") #pragma comment(lib, "advapi32") #pragma comment(lib, "rpcrt4") #pragma comment(lib, "shlwapi") #pragma comment(lib, "comctl32") #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file //////////////////////////////// //~ rjf: File Iterator Types typedef struct OS_W32_FileIter OS_W32_FileIter; struct OS_W32_FileIter { HANDLE handle; WIN32_FIND_DATAW find_data; B32 is_volume_iter; String8Array drive_strings; U64 drive_strings_iter_idx; }; StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size); //////////////////////////////// //~ rjf: Entity Types typedef enum OS_W32_EntityKind { OS_W32_EntityKind_Null, OS_W32_EntityKind_Thread, OS_W32_EntityKind_Mutex, OS_W32_EntityKind_RWMutex, OS_W32_EntityKind_ConditionVariable, } OS_W32_EntityKind; typedef struct OS_W32_Entity OS_W32_Entity; struct OS_W32_Entity { OS_W32_Entity *next; OS_W32_EntityKind kind; union { struct { OS_ThreadFunctionType *func; void *ptr; HANDLE handle; DWORD tid; } thread; CRITICAL_SECTION mutex; SRWLOCK rw_mutex; CONDITION_VARIABLE cv; }; }; //////////////////////////////// //~ rjf: State typedef struct OS_W32_State OS_W32_State; struct OS_W32_State { Arena *arena; // rjf: info OS_SystemInfo system_info; OS_ProcessInfo process_info; U64 microsecond_resolution; // rjf: entity storage CRITICAL_SECTION entity_mutex; Arena *entity_arena; OS_W32_Entity *entity_free; }; //////////////////////////////// //~ rjf: Globals global OS_W32_State os_w32_state = {0}; //////////////////////////////// //~ rjf: File Info Conversion Helpers internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes); internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes); //////////////////////////////// //~ rjf: Time Conversion Helpers internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in); internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in); internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in); internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us); //////////////////////////////// //~ rjf: Entity Functions internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind); internal void os_w32_entity_release(OS_W32_Entity *entity); //////////////////////////////// //~ rjf: Thread Entry Point internal DWORD os_w32_thread_entry_point(void *ptr); #endif // OS_CORE_WIN32_H ================================================ FILE: src/metagen/metagen_os/metagen_os_inc.c ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "metagen/metagen_os/core/metagen_os_core.c" #if OS_WINDOWS # include "metagen/metagen_os/core/win32/metagen_os_core_win32.c" #elif OS_LINUX # include "metagen/metagen_os/core/linux/metagen_os_core_linux.c" #else # error OS core layer not implemented for this operating system. #endif ================================================ FILE: src/metagen/metagen_os/metagen_os_inc.h ================================================ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_INC_H #define OS_INC_H #if !defined(OS_FEATURE_GRAPHICAL) # define OS_FEATURE_GRAPHICAL 0 #endif #include "metagen/metagen_os/core/metagen_os_core.h" #if OS_WINDOWS # include "metagen/metagen_os/core/win32/metagen_os_core_win32.h" #elif OS_LINUX # include "metagen/metagen_os/core/linux/metagen_os_core_linux.h" #else # error OS core layer not implemented for this operating system. #endif #endif // OS_INC_H ================================================ FILE: src/msf/msf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 msf_check_magic_20(String8 data) { B32 is_msf = data.size >= sizeof(msf_msf20_magic) && str8_match(data, str8_lit(msf_msf20_magic), StringMatchFlag_RightSideSloppy); return is_msf; } internal B32 msf_check_magic_70(String8 data) { B32 is_msf = data.size >= sizeof(msf_msf70_magic) && str8_match(data, str8_lit(msf_msf70_magic), StringMatchFlag_RightSideSloppy); return is_msf; } ================================================ FILE: src/msf/msf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSF_H #define MSF_H //////////////////////////////// //~ rjf: MSF Format Types #define MSF_UINT_MAX max_U32 typedef U32 MSF_UInt; typedef S32 MSF_Int; #define MSF_BITS_PER_CHAR 8 #define MSF_BITS_PER_WORD (sizeof(MSF_UInt) * MSF_BITS_PER_CHAR) #define MSF_PN_MAX MSF_UINT_MAX typedef MSF_UInt MSF_PageNumber; #define MSF_MIN_PAGE_SIZE 512 #define MSF_MAX_PAGE_SIZE 32768 #define MSF_MAX_STREAM_SIZE MSF_INT_MAX #define MSF_DELETED_STREAM_STAMP MSF_UINT_MAX #define MSF_STREAM_NUMBER_MAX max_U16 #define MSF_INVALID_STREAM_NUMBER MSF_STREAM_NUMBER_MAX typedef U16 MSF_StreamNumber; static char msf_msf20_magic[] = "Microsoft C/C++ program database 2.00\r\n\x1aJG\0\0"; static char msf_msf70_magic[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"; typedef struct MSF_Header20 MSF_Header20; struct MSF_Header20 { U8 magic[sizeof(msf_msf20_magic)]; U32 page_size; U16 active_fpm; U16 page_count; U32 stream_table_size; U32 unknown; U16 root_pn; }; typedef struct MSF_Header70 MSF_Header70; struct MSF_Header70 { U8 magic[sizeof(msf_msf70_magic)]; MSF_UInt page_size; MSF_PageNumber active_fpm; MSF_PageNumber page_count; MSF_UInt stream_table_size; MSF_UInt unknown; // always set to zero (used to be stream table page number, see SI_PERSIST in msf.cpp) MSF_PageNumber root_pn; }; //////////////////////////////// internal B32 msf_check_magic_20(String8 data); internal B32 msf_check_magic_70(String8 data); #endif // MSF_H ================================================ FILE: src/msf/msf_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: MSF Parser Functions internal MSF_RawStreamTable * msf_raw_stream_table_from_data(Arena *arena, String8 msf_data) { Temp scratch = scratch_begin(&arena, 1); MSF_RawStreamTable *result = 0; //- determine msf type U32 index_size = 0; if (msf_check_magic_20(msf_data)) { index_size = 2; } else if (msf_check_magic_70(msf_data)) { index_size = 4; } if (index_size == 2 || index_size == 4) { //- extract info from header U32 page_size_raw = 0; U32 whole_file_page_count_raw = 0; U32 directory_size_raw = 0; U32 directory_super_map_raw = 0; if (index_size == 2) { MSF_Header20 *header = (MSF_Header20 *) msf_data.str; page_size_raw = header->page_size; whole_file_page_count_raw = header->page_count; directory_size_raw = header->stream_table_size; } else if (index_size == 4) { MSF_Header70 *header = (MSF_Header70 *) msf_data.str; page_size_raw = header->page_size; whole_file_page_count_raw = header->page_count; directory_size_raw = header->stream_table_size; directory_super_map_raw = header->root_pn; } //- setup important sizes & counts // (pages) U32 page_size = ClampTop(page_size_raw, msf_data.size); // (whole file page count) U32 whole_file_page_count_max = CeilIntegerDiv(msf_data.size, page_size); U32 whole_file_page_count = ClampTop(whole_file_page_count_raw, whole_file_page_count_max); // (directory) U32 directory_size = ClampTop(directory_size_raw, msf_data.size); U32 page_count_in_directory = CeilIntegerDiv(directory_size, page_size); // (map) U32 directory_map_size = page_count_in_directory * index_size; U32 page_count_in_directory_map = CeilIntegerDiv(directory_map_size, page_size); // Layout of the "directory": // // super map: [s1, s2, s3, ...] // map: s1 -> [i1, i2, i3, ...]; s2 -> [...]; s3 -> [...]; ... // directory: i1 -> [data]; i2 -> [data]; i3 -> [data]; ... i1 -> [data]; ... // // The "data" in the directory describes streams: // PDB20: // struct Pdb20StreamSize { // U32 size; // U32 unknown; // looks like kind codes or revision counters or something // } // struct { // U32 stream_count; // Pdb20StreamSize stream_sizes[stream_count]; // U16 stream_indices[stream_count][...]; // } // // PDB70: // struct { // U32 stream_count; // U32 stream_sizes[stream_count]; // U32 stream_indices[stream_count][...]; // } //- parse stream directory U8 *directory_buf = push_array_no_zero(arena, U8, directory_size); B32 got_directory = 1; { U32 directory_super_map_dummy = 0; U32 *directory_super_map = 0; U32 directory_map_page_skip_size = 0; if (index_size == 2) { directory_super_map = &directory_super_map_dummy; directory_map_page_skip_size = OffsetOf(MSF_Header20, stream_table_size); } else { U64 super_map_off = OffsetOf(MSF_Header70, root_pn); directory_super_map = (U32 *) (msf_data.str + super_map_off); } U32 max_index_count_in_map_page = (page_size - directory_map_page_skip_size) / index_size; // for each index in super map ... U8 *out_ptr = directory_buf; U32 *super_map_ptr = directory_super_map; for (U32 i = 0; i < page_count_in_directory_map; ++i, ++super_map_ptr) { U32 directory_map_page_index = *super_map_ptr; if (directory_map_page_index >= whole_file_page_count) { got_directory = 0; goto parse_directory_done; } U64 directory_map_page_off = ((U64) directory_map_page_index) * page_size; U8 *directory_map_page_base = msf_data.str + directory_map_page_off; // clamp index count by end of directory U32 index_count; { U32 directory_pos = (U32)(out_ptr - directory_buf); U32 remaining_size = directory_size - directory_pos; U32 remaining_map_page_count = CeilIntegerDiv(remaining_size, page_size); index_count = ClampTop(max_index_count_in_map_page, remaining_map_page_count); } // for each index in map ... U8 *map_ptr = directory_map_page_base + directory_map_page_skip_size; for (U32 j = 0; j < index_count; ++j, map_ptr += index_size) { // read index U32 directory_page_index = 0; if (index_size == 4) { directory_page_index = *(U32 *) map_ptr; } else { directory_page_index = *(U16 *) map_ptr; } if (directory_page_index >= whole_file_page_count) { got_directory = 0; goto parse_directory_done; } U64 directory_page_off = ((U64) directory_page_index) * page_size; U8 *directory_page_base = msf_data.str + directory_page_off; // clamp copy size by end of directory U32 copy_size; { U32 directory_pos = (U32) (out_ptr - directory_buf); U32 remaining_size = directory_size - directory_pos; copy_size = ClampTop(page_size, remaining_size); } // copy page data MemoryCopy(out_ptr, directory_page_base, copy_size); out_ptr += copy_size; } } parse_directory_done:; } //- parse streams from directory U32 stream_count = 0; B32 got_streams = 0; MSF_RawStream *streams = 0; if (got_directory) { got_streams = 1; // read stream count U32 stream_count_raw = *(U32 *) directory_buf; // setup counts, sizes, and offsets U32 size_of_stream_entry = index_size == 2 ? 8 : 4; U32 stream_count_max = (directory_size - 4) / size_of_stream_entry; U32 stream_count__inner = ClampTop(stream_count_raw, stream_count_max); U32 all_stream_entries_off = 4; U32 all_indices_off = all_stream_entries_off + (stream_count__inner * size_of_stream_entry); // set output buffer and count stream_count = stream_count__inner; streams = push_array_no_zero(arena, MSF_RawStream, stream_count); // iterate sizes and indices in lock step U32 entry_cursor = all_stream_entries_off; U32 index_cursor = all_indices_off; MSF_RawStream *stream_ptr = streams; for (U32 i = 0; i < stream_count; ++i) { // read stream size U32 stream_size_raw = *(U32 *) (directory_buf + entry_cursor); if (stream_size_raw == MSF_DELETED_STREAM_STAMP) { stream_size_raw = 0; } // compute page count U32 stream_page_count_raw = CeilIntegerDiv(stream_size_raw, page_size); U32 stream_page_count_max = (directory_size - index_cursor) / index_size; U32 stream_page_count = ClampTop(stream_page_count_raw, stream_page_count_max); U32 stream_size = ClampTop(stream_size_raw, stream_page_count*page_size); // copy stream data stream_ptr->size = stream_size; stream_ptr->page_count = stream_page_count; if (index_size == 4) { stream_ptr->u.page_indices_u32 = (U32 *)(directory_buf + index_cursor); } else { stream_ptr->u.page_indices_u16 = (U16 *)(directory_buf + index_cursor); } // advance cursors entry_cursor += size_of_stream_entry; index_cursor += stream_page_count * index_size; stream_ptr += 1; } } if (got_streams) { result = push_array(arena, MSF_RawStreamTable, 1); result->total_page_count = whole_file_page_count; result->index_size = index_size; result->page_size = page_size; result->stream_count = stream_count; result->streams = streams; } } scratch_end(scratch); return result; } internal String8 msf_data_from_stream_number(Arena *arena, String8 msf_data, MSF_RawStreamTable *st, MSF_StreamNumber sn) { ProfBeginFunction(); String8 result = {0}; if(sn < st->stream_count) { MSF_RawStream stream = st->streams[sn]; U8 *stream_buf = push_array_no_zero(arena, U8, stream.size); U8 *stream_out_ptr = stream_buf; for (U32 i = 0; i < stream.page_count; ++i) { U64 page_idx; if (st->index_size == 4) { page_idx = stream.u.page_indices_u32[i]; } else { page_idx = stream.u.page_indices_u16[i]; } U64 stream_page_off = (U64)page_idx * st->page_size; if (stream_page_off + st->page_size > msf_data.size) { break; } U8 *stream_page_base = msf_data.str + stream_page_off; // clamp copy size by end of stream U32 stream_pos = (U32) (stream_out_ptr - stream_buf); U32 remaining_size = stream.size - stream_pos; U32 copy_size = ClampTop(st->page_size, remaining_size); // copy page data MemoryCopy(stream_out_ptr, stream_page_base, copy_size); stream_out_ptr += copy_size; } U64 copy_size = (U64)(stream_out_ptr - stream_buf); U64 unused_buf_size = stream.size - copy_size; arena_pop(arena, unused_buf_size); result = str8(stream_buf, copy_size); } ProfEnd(); return result; } internal MSF_Parsed * msf_parsed_from_data(Arena *arena, String8 msf_data) { Temp scratch = scratch_begin(&arena, 1); MSF_Parsed *result = 0; MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data); if (st) { String8 *streams = push_array_no_zero(arena, String8, st->stream_count); for (MSF_StreamNumber sn = 0; sn < st->stream_count; ++sn) { streams[sn] = msf_data_from_stream_number(arena, msf_data, st, sn); } result = push_array_no_zero(arena, MSF_Parsed, 1); result->streams = streams; result->stream_count = st->stream_count; result->page_size = st->page_size; result->page_count = st->total_page_count; } scratch_end(scratch); return result; } internal String8 msf_data_from_stream(MSF_Parsed *msf, MSF_StreamNumber sn) { String8 result = {0}; if(sn < msf->stream_count) { result = msf->streams[sn]; } return(result); } ================================================ FILE: src/msf/msf_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSF_PARSE_H #define MSF_PARSE_H //////////////////////////////// //~ rjf: MSF Parser Helper Types typedef struct MSF_RawStream MSF_RawStream; struct MSF_RawStream { U64 size; U64 page_count; union { U32 *page_indices_u32; U16 *page_indices_u16; } u; }; typedef struct MSF_RawStreamTable MSF_RawStreamTable; struct MSF_RawStreamTable { U64 total_page_count; U64 index_size; U64 page_size; U64 stream_count; MSF_RawStream *streams; }; typedef struct MSF_Parsed MSF_Parsed; struct MSF_Parsed { String8 *streams; U64 stream_count; U64 page_size; U64 page_count; }; //////////////////////////////// //~ rjf: MSF Parser Functions internal MSF_RawStreamTable* msf_raw_stream_table_from_data(Arena *arena, String8 msf_data); internal String8 msf_data_from_stream_number(Arena *arena, String8 msf_data, MSF_RawStreamTable *st, MSF_StreamNumber sn); internal MSF_Parsed* msf_parsed_from_data(Arena *arena, String8 msf_data); internal String8 msf_data_from_stream(MSF_Parsed *msf, MSF_StreamNumber sn); #endif // MSF_PARSE_H ================================================ FILE: src/msvc_crt/msvc_crt.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 msvcrt_ctr_entry_from_user_entry(String8 user_entry) { String8 crt_entry = {0}; if (str8_match_lit("wmain", user_entry, 0)) { crt_entry = str8_lit("wmainCRTStartup"); } else if (str8_match_lit("main", user_entry, 0)) { crt_entry = str8_lit("mainCRTStartup"); } else if (str8_match_lit("WinMain", user_entry, 0)) { crt_entry = str8_lit("WinMainCRTStartup"); } else if (str8_match_lit("wWinMain", user_entry, 0)) { crt_entry = str8_lit("wWinMainCRTStartup"); } return crt_entry; } internal String8 mscrt_delay_load_helper_name_from_machine(COFF_MachineType machine) { String8 delay_load_helper_name = str8_zero(); switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: delay_load_helper_name = str8_cstring(MSCRT_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME); break; case COFF_MachineType_X64: delay_load_helper_name = str8_cstring(MSCRT_DELAY_LOAD_HELPER2_SYMBOL_NAME); break; default: { NotImplemented; } break; } return delay_load_helper_name; } internal U64 mscrt_parse_func_info(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, MSCRT_FuncInfo *func_info) { U64 cursor = off; U32 handler_data_voff = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &handler_data_voff); // TODO: what is this? padding? U32 unknown = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &unknown); // read function info U64 handler_data_foff = coff_foff_from_voff(sections, section_count, handler_data_voff); MSCRT_FuncInfo32 func_info32 = {0}; str8_deserial_read_struct(raw_data, handler_data_foff, &func_info32); // unwind map MSCRT_UnwindMap32 *unwind_map = push_array(arena, MSCRT_UnwindMap32, func_info32.max_state); U64 unwind_map_foff = coff_foff_from_voff(sections, section_count, func_info32.unwind_map_voff); cursor += str8_deserial_read_array(raw_data, unwind_map_foff, &unwind_map[0], func_info32.max_state); // read ip states MSCRT_IPState32 *ip_map = push_array(arena, MSCRT_IPState32, func_info32.ip_map_count); U64 ip_map_foff = coff_foff_from_voff(sections, section_count, func_info32.ip_map_voff); str8_deserial_read_array(raw_data, ip_map_foff, &ip_map[0], func_info32.ip_map_count); // read try map MSCRT_TryMapBlock *try_block_map = push_array(arena, MSCRT_TryMapBlock, func_info32.try_block_map_count); U64 try_map_foff = coff_foff_from_voff(sections, section_count, func_info32.try_block_map_voff); for (U32 imap = 0; imap < func_info32.try_block_map_count; ++imap) { MSCRT_TryMapBlock32 map32 = {0}; str8_deserial_read_struct(raw_data, try_map_foff + imap*sizeof(map32), &map32); // convert try map to in-memory version MSCRT_TryMapBlock *map = &try_block_map[imap]; map->try_low = map32.try_low; map->try_high = map32.try_high; map->catch_high = map32.catch_high; map->catch_handlers_count = map32.catch_handlers_count; map->catch_handlers = push_array(arena, MSCRT_EhHandlerType32, map32.catch_handlers_count); // read handlers U64 catch_handlers_foff = coff_foff_from_voff(sections, section_count, map32.catch_handlers_voff); str8_deserial_read_array(raw_data, catch_handlers_foff, &map->catch_handlers[0], map->catch_handlers_count); } // read exception spec list MSCRT_ExceptionSpecTypeList es_type_list = {0}; if (func_info32.es_type_list_voff) { MSCRT_ExceptionSpecTypeList32 es_list32 = {0}; U64 es_list_foff = coff_foff_from_voff(sections, section_count, func_info32.es_type_list_voff); str8_deserial_read_struct(raw_data, es_list_foff, &es_list32); es_type_list.count = es_list32.count; es_type_list.handlers = push_array(arena, MSCRT_EhHandlerType32, es_list32.count); U64 handlers_foff = coff_foff_from_voff(sections, section_count, es_list32.handlers_voff); str8_deserial_read_array(raw_data, handlers_foff, &es_type_list.handlers[0], es_type_list.count); } // pack result func_info->magic = func_info32.magic; func_info->max_state = func_info32.max_state; func_info->unwind_map = unwind_map; func_info->try_block_map_count = func_info32.try_block_map_count; func_info->try_block_map = try_block_map; func_info->ip_map_count = func_info32.ip_map_count; func_info->ip_map = ip_map; func_info->frame_offset_unwind_helper = func_info32.frame_offset_unwind_helper; func_info->es_type_list = es_type_list; func_info->eh_flags = func_info32.eh_flags; U64 parse_size = (cursor - off); return parse_size; } //////////////////////////////// internal U64 mscrt_v4_parse_u32(String8 raw_data, U64 offset, U32 *uint_out) { U64 cursor = offset; U8 one = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &one); if ((one & 0xF) == 15) { U8 two = 0, three = 0, four = 0, five = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &two); cursor += str8_deserial_read_struct(raw_data, cursor, &three); cursor += str8_deserial_read_struct(raw_data, cursor, &four); cursor += str8_deserial_read_struct(raw_data, cursor, &five); *uint_out = (U32)two | ((U32)three << 8) | ((U32)four << 16) | ((U32)five << 24); } else if ((one & 0xF) == 7) { U8 two = 0, three = 0, four = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &two); cursor += str8_deserial_read_struct(raw_data, cursor, &three); cursor += str8_deserial_read_struct(raw_data, cursor, &four); *uint_out = ((U32)one >> 4) | ((U32)two << 4) | ((U32)three << 12) | ((U32)four << 20); } else if ((one & 0x7) == 3) { U8 two = 0, three = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &two); cursor += str8_deserial_read_struct(raw_data, cursor, &three); *uint_out = ((U32)one >> 3) | ((U32)two << 5) | ((U32)three << 13); } else if ((one & 0x3) == 1) { U8 two = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &two); *uint_out = ((U32)one >> 2) | ((U32)two << 6); } else { *uint_out = one >> 1; } U64 read_size = cursor - offset; return read_size; } internal U64 mscrt_v4_parse_s32(String8 raw_data, U64 offset, S32 *int_out) { return str8_deserial_read_struct(raw_data, offset, int_out); } internal U64 mscrt_parse_handler_type_v4(String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4 *handler) { U64 cursor = offset; cursor += str8_deserial_read_struct(raw_data, cursor, &handler->flags); if (handler->flags & MSCRT_EhHandlerV4Flag_Adjectives) { cursor += mscrt_v4_parse_u32(raw_data, cursor, &handler->adjectives); } if (handler->flags & MSCRT_EhHandlerV4Flag_DispType) { cursor += mscrt_v4_parse_s32(raw_data, cursor, &handler->type_voff); } if (handler->flags & MSCRT_EhHandlerV4Flag_DispCatchObj) { cursor += mscrt_v4_parse_u32(raw_data, cursor, &handler->catch_obj_voff); } cursor += mscrt_v4_parse_s32(raw_data, cursor, &handler->catch_code_voff); U32 cont_type = (handler->flags & MSCRT_EhHandlerV4Flag_ContVOffMask) >> MSCRT_EhHandlerV4Flag_ContVOffShift; if (handler->flags & MSCRT_EhHandlerV4Flag_ContIsVOff) { switch (cont_type) { case MSCRT_ContV4Type_NoMetadata: break; case MSCRT_ContV4Type_OneFuncRelAddr: { S32 v = 0; cursor += mscrt_v4_parse_s32(raw_data, cursor, &v); handler->catch_funclet_cont_addr[0] = (U64)v; handler->catch_funclet_cont_addr_count = 1; } break; case MSCRT_ContV4Type_TwoFuncRelAddr: { S32 v1 = 0, v2 = 0; cursor += mscrt_v4_parse_s32(raw_data, cursor, &v1); cursor += mscrt_v4_parse_s32(raw_data, cursor, &v2); handler->catch_funclet_cont_addr[0] = (U64)v1; handler->catch_funclet_cont_addr[1] = (U64)v2; handler->catch_funclet_cont_addr_count = 2; } break; } } else { switch (cont_type) { case MSCRT_ContV4Type_NoMetadata: { } break; case MSCRT_ContV4Type_OneFuncRelAddr: { U32 v = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &v); handler->catch_funclet_cont_addr[0] = func_voff + (U64)v; handler->catch_funclet_cont_addr_count = 1; } break; case MSCRT_ContV4Type_TwoFuncRelAddr: { U32 v1 = 0, v2 = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &v1); cursor += mscrt_v4_parse_u32(raw_data, cursor, &v2); handler->catch_funclet_cont_addr[0] = func_voff + (U64)v1; handler->catch_funclet_cont_addr[1] = func_voff + (U64)v2; handler->catch_funclet_cont_addr_count = 2; } break; } } U64 read_size = cursor - offset; return read_size; } internal U64 mscrt_parse_handler_type_v4_array(Arena *arena, String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4Array *array_out) { U64 cursor = offset; U32 count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &count); MSCRT_EhHandlerTypeV4 *handlers = 0; if (count) { handlers = push_array(arena, MSCRT_EhHandlerTypeV4, count); for (U32 i = 0; i < count; ++i) { cursor += mscrt_parse_handler_type_v4(raw_data, cursor, func_voff, &handlers[i]); } } array_out->count = count; array_out->v = handlers; U64 read_size = cursor - offset; return read_size; } internal U64 mscrt_parse_unwind_v4_entry(String8 raw_data, U64 offset, MSCRT_UnwindEntryV4 *entry_out) { U64 cursor = offset; U32 type_and_next_off = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &type_and_next_off); entry_out->type = type_and_next_off & 0x3; entry_out->next_off = type_and_next_off >> 2; switch (entry_out->type) { case MSCRT_UnwindMapV4Type_DtorWithObj: case MSCRT_UnwindMapV4Type_DtorWithPtrToObj: { cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); cursor += mscrt_v4_parse_u32(raw_data, cursor, &entry_out->object); } break; case MSCRT_UnwindMapV4Type_VOFF: { cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); } break; case MSCRT_UnwindMapV4Type_NoUW: { // no action and/or object is associated with this type } break; default: { Assert(!"unknown unwind entry type"); } break; } U64 read_size = cursor - offset; return read_size; } internal U64 mscrt_parse_unwind_map_v4(Arena *arena, String8 raw_data, U64 off, MSCRT_UnwindMapV4 *map_out) { U64 cursor = off; cursor += mscrt_v4_parse_u32(raw_data, cursor, &map_out->count); map_out->v = push_array(arena, MSCRT_UnwindEntryV4, map_out->count); for (U32 i = 0; i < map_out->count; ++i) { cursor += mscrt_parse_unwind_v4_entry(raw_data, cursor, &map_out->v[i]); } U64 read_size = cursor - off; return read_size; } internal U64 mscrt_parse_try_block_map_array_v4(Arena *arena, String8 raw_data, U64 off, U64 section_count, COFF_SectionHeader *sections, U64 func_voff, MSCRT_TryBlockMapV4Array *map_out) { U64 cursor = off; U32 try_block_map_count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block_map_count); MSCRT_TryBlockMapV4 *try_block_map = push_array(arena, MSCRT_TryBlockMapV4, try_block_map_count); for (U32 itry = 0; itry < try_block_map_count; ++itry) { MSCRT_TryBlockMapV4 *try_block = &try_block_map[itry]; cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->try_low); cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->try_high); cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->catch_high); S32 handler_array_voff = 0; cursor += mscrt_v4_parse_s32(raw_data, cursor, &handler_array_voff); U64 handler_array_foff = coff_foff_from_voff(sections, section_count, (U32)handler_array_voff); mscrt_parse_handler_type_v4_array(arena, raw_data, handler_array_foff, func_voff, &try_block->handlers); } map_out->count = try_block_map_count; map_out->v = try_block_map; U64 read_size = cursor - off; return read_size; } internal U64 mscrt_parse_ip2state_map_v4(Arena *arena, String8 raw_data, U64 off, U64 func_voff, MSCRT_IP2State32V4 *ip2state_map_out) { U64 cursor = off; U32 count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &count); U32 *voffs = push_array(arena, U32, count); S32 *states = push_array(arena, S32, count); U32 prev_voff = func_voff; for (U32 i = 0; i < count; ++i) { // virtual offsets are encoded as deltas cursor += mscrt_v4_parse_u32(raw_data, cursor, &voffs[i]); voffs[i] += prev_voff; prev_voff = voffs[i]; // states are encoded with +1 to avoid encoding negative integers U32 encoded_state = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &encoded_state); states[i] = (S32)encoded_state - 1; } ip2state_map_out->count = count; ip2state_map_out->voffs = voffs; ip2state_map_out->states = states; U64 read_size = cursor - off; return read_size; } internal U64 mscrt_parse_func_info_v4(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, U64 func_voff, MSCRT_ParsedFuncInfoV4 *func_info_out) { U64 cursor = off; MSCRT_FuncInfo32V4 func_info = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &func_info.header); if (func_info.header & MSCRT_FuncInfoV4Flag_IsBBT) { cursor += mscrt_v4_parse_u32(raw_data, cursor, &func_info.bbt_flags); } if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { cursor += mscrt_v4_parse_s32(raw_data, cursor, &func_info.unwind_map_voff); } if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { cursor += mscrt_v4_parse_s32(raw_data, cursor, &func_info.try_block_map_voff); } if (func_info.header & MSCRT_FuncInfoV4Flag_IsSeparated) { // TODO: separted IP state map NotImplemented; } else { cursor += mscrt_v4_parse_s32(raw_data, cursor, &func_info.ip_to_state_map_voff); } if (func_info.header & MSCRT_FuncInfoV4Flag_IsCatch) { cursor += mscrt_v4_parse_s32(raw_data, cursor, &func_info.wrt_frame_establisher_voff); } MSCRT_UnwindMapV4 unwind_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { U64 unwind_map_foff = coff_foff_from_voff(sections, section_count, func_info.unwind_map_voff); mscrt_parse_unwind_map_v4(arena, raw_data, unwind_map_foff, &unwind_map); } MSCRT_TryBlockMapV4Array try_block_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { U64 try_block_map_foff = coff_foff_from_voff(sections, section_count, func_info.try_block_map_voff); mscrt_parse_try_block_map_array_v4(arena, raw_data, try_block_map_foff, section_count, sections, func_voff, &try_block_map); } MSCRT_IP2State32V4 ip2state_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_IsSeparated) { Assert(!"TODO: separated ip2state map"); } else { U64 ip_to_state_map_foff = coff_foff_from_voff(sections, section_count, func_info.ip_to_state_map_voff); mscrt_parse_ip2state_map_v4(arena, raw_data, ip_to_state_map_foff, func_voff, &ip2state_map); } func_info_out->header = func_info.header; func_info_out->bbt_flags = func_info.bbt_flags; func_info_out->try_block_map = try_block_map; func_info_out->unwind_map = unwind_map; func_info_out->ip2state_map = ip2state_map; U64 read_size = cursor - off; return read_size; } //////////////////////////////// internal Rng1U64List mscrt_catch_blocks_from_data_x8664(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, Rng1U64 except_frange) { Temp scratch = scratch_begin(&arena, 1); Rng1U64List result = {0}; String8 raw_pdata = str8_substr(raw_data, except_frange); U64 pdata_count = raw_pdata.size / sizeof(PE_IntelPdata); PE_IntelPdata *src_pdata = (PE_IntelPdata *)raw_pdata.str; PE_IntelPdata *opl_pdata = src_pdata + pdata_count; for (PE_IntelPdata *pdata = src_pdata; pdata < opl_pdata; ++pdata) { U64 uwinfo_foff = coff_foff_from_voff(sections, section_count, pdata->voff_unwind_info); PE_UnwindInfo *uwinfo = str8_deserial_get_raw_ptr(raw_data, uwinfo_foff, sizeof(*uwinfo)); U8 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(uwinfo->header); B32 is_chained = !!(flags & PE_UnwindInfoFlag_CHAINED); B32 has_handler_data = !is_chained && ((flags & (PE_UnwindInfoFlag_EHANDLER | PE_UnwindInfoFlag_UHANDLER)) != 0); if (has_handler_data) { Temp temp = temp_begin(scratch.arena); U32 actual_code_count = PE_UNWIND_INFO_GET_CODE_COUNT(uwinfo->codes_num); U64 handler_data_foff = uwinfo_foff + sizeof(PE_UnwindInfo) + actual_code_count * sizeof(PE_UnwindCode); U32 handler_voff = *(U32 *)str8_deserial_get_raw_ptr(raw_data, handler_data_foff, sizeof(handler_voff)); String8 handler_name = str8_zero(); /* TODO: { UnitID uid = syms_group_uid_from_voff__accelerated(group, handler_voff); UnitAccel *unit = syms_group_unit_from_uid(group, uid); SYMS_SymbolID sid = syms_group_proc_sid_from_uid_voff__accelerated(group, uid, handler_voff); handler_name = syms_group_symbol_name_from_sid(temp.arena, group, unit, sid); } */ B32 is_handler_v3_or_below = str8_match_lit("__CxxFrameHandler3", handler_name, 0) || str8_match_lit("__GSHandlerCheck_EH", handler_name, 0); if (is_handler_v3_or_below) { U64 func_info_foff = handler_data_foff + sizeof(handler_voff); MSCRT_FuncInfo func_info = {0}; mscrt_parse_func_info(temp.arena, raw_data, section_count, sections, func_info_foff, &func_info); for (U32 itry = 0; itry < func_info.try_block_map_count; ++itry) { MSCRT_TryMapBlock *try_block = &func_info.try_block_map[itry]; for (U32 icatch = 0; icatch < try_block->catch_handlers_count; ++icatch) { MSCRT_EhHandlerType32 *catch_block = &try_block->catch_handlers[icatch]; U64 catch_pdata_off = pe_pdata_off_from_voff__binary_search_x8664(raw_pdata, catch_block->catch_handler_voff); PE_IntelPdata *catch_pdata = str8_deserial_get_raw_ptr(raw_pdata, catch_pdata_off, sizeof(*catch_pdata)); rng1u64_list_push(arena, &result, rng_1u64(catch_pdata->voff_first, catch_pdata->voff_one_past_last)); } } goto next; } B32 is_handler_v4 = str8_match_lit("__CxxFrameHandler4", handler_name, 0) || str8_match_lit("__GSHandlerCheck_EH4", handler_name, 0); if (is_handler_v4) { U32 func_info_voff = *(U32 *)str8_deserial_get_raw_ptr(raw_data, handler_data_foff + sizeof(handler_voff), sizeof(func_info_voff)); U64 func_info_foff = coff_foff_from_voff(sections, section_count, func_info_voff); MSCRT_ParsedFuncInfoV4 func_info = {0}; mscrt_parse_func_info_v4(temp.arena, raw_data, section_count, sections, func_info_foff, pdata->voff_first, &func_info); for (U32 itry = 0; itry < func_info.try_block_map.count; ++itry) { MSCRT_TryBlockMapV4 *try_block = &func_info.try_block_map.v[itry]; for (U32 icatch = 0; icatch < try_block->handlers.count; ++icatch) { MSCRT_EhHandlerTypeV4 *catch_block = &try_block->handlers.v[icatch]; U64 catch_pdata_off = pe_pdata_off_from_voff__binary_search_x8664(raw_pdata, catch_block->catch_code_voff); PE_IntelPdata *catch_pdata = str8_deserial_get_raw_ptr(raw_pdata, catch_pdata_off, sizeof(*catch_pdata)); rng1u64_list_push(arena, &result, rng_1u64(catch_pdata->voff_first, catch_pdata->voff_one_past_last)); } } goto next; } next:; temp_end(temp); } } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Enum -> String internal String8 mscrt_string_from_eh_adjectives(Arena *arena, MSCRT_EhHandlerTypeFlags adjectives) { Temp scratch = scratch_begin(&arena, 1); String8List adj_list = {0}; if (adjectives & MSCRT_EhHandlerTypeFlag_IsConst) { str8_list_pushf(scratch.arena, &adj_list, "Const"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsVolatile) { str8_list_pushf(scratch.arena, &adj_list, "Volatile"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsUnaligned) { str8_list_pushf(scratch.arena, &adj_list, "Unaligned"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsReference) { str8_list_pushf(scratch.arena, &adj_list, "Reference"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsResumable) { str8_list_pushf(scratch.arena, &adj_list, "Resumable"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsStdDotDot) { str8_list_pushf(scratch.arena, &adj_list, "StdDotDot"); } if (adjectives & MSCRT_EhHandlerTypeFlag_IsComplusEH) { str8_list_pushf(scratch.arena, &adj_list, "ComplusEH"); } String8 result = str8_list_join(arena, &adj_list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } ================================================ FILE: src/msvc_crt/msvc_crt.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSVC_CRT #define MSVC_CRT //////////////////////////////// // CRT Symbols // _load_config_used points to PE_LoadConfig32/PE_LoadConfig64 // and symbols below are used to patch patricual fields of the struct. #define MSCRT_LOAD_CONFIG_SYMBOL_NAME "_load_config_used" #define MSCRT_ENCLAVE_CONFIG_SYMBOL_NAME "__enclave_config" #define MSCRT_GUARD_FLAGS_SYMBOL_NAME "__guard_flags" #define MSCRT_GUARD_FIDS_TABLE_SYMBOL_NAME "__guard_fids_table" #define MSCRT_GUARD_FIDS_COUNT_SYMBOL_NAME "__guard_fids_count" #define MSCRT_GUARD_IAT_TABLE_SYMBOL_NAME "__guard_iat_table" #define MSCRT_GUARD_IAT_COUNT_SYMBOL_NAME "__guard_iat_count" #define MSCRT_GUARD_LONGJMP_TABLE_SYMBOL_NAME "__guard_longjmp_table" #define MSCRT_GUARD_LONGJMP_COUNT_SYMBOL_NAME "__guard_longjmp_count" #define MSCRT_GUARD_EHCONT_TABLE_SYMBOL_NAME "__guard_eh_cont_table" #define MSCRT_GUARD_EHCONT_COUNT_SYMBOL_NAME "__guard_eh_cont_count" // x86 load config fields #define MSCRT_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME "__safe_se_handler_table" #define MSCRT_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME "__safe_se_handler_count" // load symbols from delayimp.lib #define MSCRT_DELAY_LOAD_HELPER2_SYMBOL_NAME "__delayLoadHelper2" #define MSCRT_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME "___delayLoadHelper2@8" // _tls_used is a special section in CRT which has format of // PE_TLSHeader32 or PE_TLSHeader64, according to machine type. #define MSCRT_TLS_SYMBOL_NAME "_tls_used" //////////////////////////////// // feature flags in absolute symbol @feat.00 enum { MSCRT_FeatFlag_HAS_SAFE_SEH = (1 << 0), // /safeseh MSCRT_FeatFlag_UNKNOWN_4 = (1 << 4), MSCRT_FeatFlag_GUARD_STACK = (1 << 8), // /GS MSCRT_FeatFlag_SDL = (1 << 9), // /sdl MSCRT_FeatFlag_GUARD_CF = (1 << 11), // /guard:cf MSCRT_FeatFlag_GUARD_EH_CONT = (1 << 14), // /guard:ehcont MSCRT_FeatFlag_NO_RTTI = (1 << 17), // /GR- MSCRT_FeatFlag_KERNEL = (1 << 30), // /kernel }; typedef U32 MSCRT_FeatFlags; typedef struct MSCRT_VCFeatures { U32 pre_vcpp; U32 c_cpp; U32 gs; U32 sdl; U32 guard_n; } MSCRT_VCFeatures; //////////////////////////////// // GS Handler #define MSCRT_GSHandler_GetFlags(x) (((x) & 0x00000007) >> 0) #define MSCRT_GSHandler_GetCookieOffset(x) (((x) & 0xFFFFFFF8) >> 3) typedef U8 MSCRT_GSHandlerFlags; enum { MSCRT_GSHandlerFlag_EHandler = (1 << 0), MSCRT_GSHandlerFlag_UHandler = (1 << 1), MSCRT_GSHandlerFlag_HasAlignment = (1 << 2) }; //////////////////////////////// // Exceptions < v4 #define MSCRT_MAGIC_GET_CHECK(x) ((x) & 0x1FFFFFFF) #define MSCRT_MAGIC_GET_FLAGS(x) (((x) & 0xE0000000) >> 29) // Magic numbers are incremented by one everytime there is a new version. // Top 3 bits are reserved for flags. enum { MSCRT_Magic1 = 0x19930520, MSCRT_Magic2 = 0x19930521, MSCRT_Magic3 = 0x19930522, // pure magic indicates that exception cannot be caught in native or managed code. MSCRT_PureMagic1 = 0x1994000, }; enum { MSCRT_MagicFlag_EHS = (1 << 0), MSCRT_MagicFlag_DYNSTALKING = (1 << 1), MSCRT_MagicFlag_EHNOEXCEPT = (1 << 2) }; typedef U32 MSCRT_Flags; enum { MSCRT_Flag_SynchronousExceptionOnly = (1 << 0), MSCRT_Flag_UNKNOWN = (1 << 1), MSCRT_Flag_StopUnwind = (1 << 2), // When set unwinding can't continue. }; enum { MSCRT_CatchableType_IsSimpleType = (1 << 0), MSCRT_CatchableType_ByRefOnly = (1 << 1), MSCRT_CatchableType_HasVirtualBase = (1 << 2), // type is a class with virtual base MSCRT_CatchableType_IsWinRTHandle = (1 << 3), // type is a WinRT handle MSCRT_CatchableType_IsStdBadAlloc = (1 << 4) // type is a std::bad_alloc }; enum { MSCRT_ThrowInfo_IsConst = (1 << 0), MSCRT_ThrowInfo_IsVolatile = (1 << 1), MSCRT_ThrowInfo_IsUnaligned = (1 << 2), MSCRT_ThrowInfo_IsPure = (1 << 3), // thrown object is from pure module MSCRT_ThrowInfo_IsWinRT = (1 << 4) // thrown object is a WinRT exception }; typedef U32 MSCRT_EhHandlerTypeFlags; enum { MSCRT_EhHandlerTypeFlag_IsConst = (1 << 0), // referenced type is 'const' MSCRT_EhHandlerTypeFlag_IsVolatile = (1 << 1), // referenced type is 'volatile' MSCRT_EhHandlerTypeFlag_IsUnaligned = (1 << 2), // referenced type is 'unaligned' MSCRT_EhHandlerTypeFlag_IsReference = (1 << 3), // catch type is by reference MSCRT_EhHandlerTypeFlag_IsResumable = (1 << 4), // catch may choose to resume MSCRT_EhHandlerTypeFlag_IsStdDotDot = (1 << 6), // catch(...) MSCRT_EhHandlerTypeFlag_IsComplusEH = (1 << 31) // is handling EH in complus }; typedef struct MSCRT_FuncInfo32 { U32 magic; U32 max_state; U32 unwind_map_voff; U32 try_block_map_count; U32 try_block_map_voff; U32 ip_map_count; U32 ip_map_voff; U32 frame_offset_unwind_helper; U32 es_type_list_voff; // llvm emits zero, not sure what this supposed to be MSCRT_Flags eh_flags; } MSCRT_FuncInfo32; typedef struct MSCRT_IPState32 { U32 ip; S32 state; } MSCRT_IPState32; typedef struct MSCRT_UnwindMap32 { S32 next_state; U32 action_virt_off; } MSCRT_UnwindMap32; typedef struct MSCRT_EhHandlerType32 { MSCRT_EhHandlerTypeFlags adjectives; U32 descriptor_voff; U32 catch_obj_frame_offset; U32 catch_handler_voff; U32 fp_distance; } MSCRT_EhHandlerType32; typedef struct MSCRT_TryMapBlock32 { S32 try_low; S32 try_high; S32 catch_high; S32 catch_handlers_count; U32 catch_handlers_voff; } MSCRT_TryMapBlock32; typedef struct MSCRT_ExceptionSpecTypeList32 { S32 count; U32 handlers_voff; } MSCRT_ExceptionSpecTypeList32; typedef struct MSCRT_TryMapBlock { S32 try_low; S32 try_high; S32 catch_high; S32 catch_handlers_count; MSCRT_EhHandlerType32 *catch_handlers; } MSCRT_TryMapBlock; typedef struct MSCRT_ExceptionSpecTypeList { S32 count; MSCRT_EhHandlerType32 *handlers; } MSCRT_ExceptionSpecTypeList; typedef struct MSCRT_FuncInfo { U32 magic; U32 max_state; MSCRT_UnwindMap32 *unwind_map; U32 try_block_map_count; MSCRT_TryMapBlock *try_block_map; U32 ip_map_count; MSCRT_IPState32 *ip_map; U32 frame_offset_unwind_helper; MSCRT_ExceptionSpecTypeList es_type_list; MSCRT_Flags eh_flags; } MSCRT_FuncInfo; //////////////////////////////// // C++ Exceptions V4 typedef U8 MSCRT_FuncInfoV4Flags; enum { MSCRT_FuncInfoV4Flag_IsCatch = (1 << 0), // catch funclet MSCRT_FuncInfoV4Flag_IsSeparated = (1 << 1), // func has separate code segment MSCRT_FuncInfoV4Flag_IsBBT = (1 << 2), // flags set by basic block trasformations MSCRT_FuncInfoV4Flag_UnwindMap = (1 << 3), // unwind map is present MSCRT_FuncInfoV4Flag_TryBlockMap = (1 << 4), // try block map is present MSCRT_FuncInfoV4Flag_EHs = (1 << 5), MSCRT_FuncInfoV4Flag_NoExcept = (1 << 6), MSCRT_FuncInfoV4Flag_Reserved = (1 << 7) }; typedef U32 MSCRT_UnwindMapV4Type; enum { MSCRT_UnwindMapV4Type_NoUW = 0, // no unwind action associated with this state MSCRT_UnwindMapV4Type_DtorWithObj = 1, // dtor with an object offset MSCRT_UnwindMapV4Type_DtorWithPtrToObj = 2, // dtor with an offset that contains a pointer to the object to be destroyed MSCRT_UnwindMapV4Type_VOFF = 3, // dtor that has a direct function that is called that knows where the object is and can perform more exotic destruction }; enum { MSCRT_ContV4Type_NoMetadata = 1, // no metadata use whatever funclet returns MSCRT_ContV4Type_OneFuncRelAddr = 2, MSCRT_ContV4Type_TwoFuncRelAddr = 3 }; #define MSCRT__EH_HANDLER_V4_FLAGS_EXTRACT_CONT_TYPE(x) (((x) & MSCRT_EhHandlerV4Flag_ContVOffMask) >> MSVC_CRTHandlerV4Flag_ContVOffShift) typedef U8 MSCRT_EhHandlerV4Flags; enum { MSCRT_EhHandlerV4Flag_Adjectives = (1 << 0), // set if adjectives are present MSCRT_EhHandlerV4Flag_DispType = (1 << 1), // set if type descriptors are present MSCRT_EhHandlerV4Flag_DispCatchObj = (1 << 2), // set if catch object object is present MSCRT_EhHandlerV4Flag_ContIsVOff = (1 << 3), // continuantion addresses are VOFF rather than function relative MSCRT_EhHandlerV4Flag_ContVOffMask = 0x30, MSCRT_EhHandlerV4Flag_ContVOffShift = 4, }; typedef struct MSCRT_EhHandlerTypeV4 { MSCRT_EhHandlerV4Flags flags; MSCRT_EhHandlerTypeFlags adjectives; S32 type_voff; U32 catch_obj_voff; S32 catch_code_voff; U64 catch_funclet_cont_addr[2]; U32 catch_funclet_cont_addr_count; } MSCRT_EhHandlerTypeV4; typedef struct MSCRT_EhHandlerTypeV4Array { U64 count; MSCRT_EhHandlerTypeV4 *v; } MSCRT_EhHandlerTypeV4Array; typedef struct MSCRT_TryBlockMap32V4 { U32 try_low; U32 try_high; U32 catch_high; S32 handler_array_voff; } MSCRT_TryBlockMap32V4; typedef struct MSCRT_IP2State32V4 { U32 count; U32 *voffs; S32 *states; } MSCRT_IP2State32V4; typedef struct MSCRT_SepIPState32V4 { S32 func_start_voff; S32 ip_map_voff; } MSCRT_SepIPState32V4; typedef struct MSCRT_FuncInfo32V4 { MSCRT_FuncInfoV4Flags header; U32 bbt_flags; S32 unwind_map_voff; S32 try_block_map_voff; S32 ip_to_state_map_voff; S32 wrt_frame_establisher_voff; // used only in catch funclets } MSCRT_FuncInfo32V4; typedef struct MSCRT_UnwindEntryV4 { MSCRT_UnwindMapV4Type type; S32 action; U32 object; U32 next_off; } MSCRT_UnwindEntryV4; typedef struct MSCRT_UnwindMapV4 { U32 count; MSCRT_UnwindEntryV4 *v; } MSCRT_UnwindMapV4; typedef struct MSCRT_TryBlockMapV4 { U32 try_low; U32 try_high; U32 catch_high; MSCRT_EhHandlerTypeV4Array handlers; } MSCRT_TryBlockMapV4; typedef struct MSCRT_TryBlockMapV4Array { U64 count; MSCRT_TryBlockMapV4 *v; } MSCRT_TryBlockMapV4Array; typedef struct MSCRT_ParsedFuncInfoV4 { MSCRT_FuncInfoV4Flags header; U32 bbt_flags; MSCRT_UnwindMapV4 unwind_map; MSCRT_TryBlockMapV4Array try_block_map; MSCRT_IP2State32V4 ip2state_map; } MSCRT_ParsedFuncInfoV4; //- Entry Point internal String8 msvcrt_ctr_entry_from_user_entry(String8 user_entry_point); //- Delay Load Helper internal String8 mscrt_delay_load_helper_name_from_machine(COFF_MachineType machine); //- Exception info < v4 internal U64 mscrt_parse_func_info(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, MSCRT_FuncInfo *func_info); //- Exception info v4 internal U64 mscrt_parse_handler_type_v4 (String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4 *handler); internal U64 mscrt_parse_unwind_v4_entry (String8 raw_data, U64 offset, MSCRT_UnwindEntryV4 *entry_out); internal U64 mscrt_parse_handler_type_v4_array (Arena *arena, String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4Array *array_out); internal U64 mscrt_parse_unwind_map_v4 (Arena *arena, String8 raw_data, U64 off, MSCRT_UnwindMapV4 *map_out); internal U64 mscrt_parse_try_block_map_array_v4(Arena *arena, String8 raw_data, U64 off, U64 section_count, COFF_SectionHeader *sections, U64 func_voff, MSCRT_TryBlockMapV4Array *map_out); internal U64 mscrt_parse_ip2state_map_v4 (Arena *arena, String8 raw_data, U64 off, U64 func_voff, MSCRT_IP2State32V4 *ip2state_map_out); internal U64 mscrt_parse_func_info_v4 (Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, U64 func_voff, MSCRT_ParsedFuncInfoV4 *func_info_out); internal Rng1U64List mscrt_catch_blocks_from_data_x8664(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, Rng1U64 except_frange); //////////////////////////////// //~ rjf: Enum -> String internal String8 mscrt_string_from_eh_adjectives(Arena *arena, MSCRT_EhHandlerTypeFlags adjectives); #endif // MSVC_CRT ================================================ FILE: src/mule/inline_body.cpp ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) bias = (bias^x)&7; x -= bias; x *= 2; x *= x; x += bias; ================================================ FILE: src/mule/mule_c.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* * Program to run in debugger organized to provide tests for * single threaded stepping, breakpoints, evaluation. */ //////////////////////////////// // NOTE(allen): Complex Types #include void c_type_coverage_eval_tests(void){ #if _WIN32 _Fcomplex x = _FCbuild(0.f, 1.f); _Dcomplex y = _Cbuild(0.f, -1.f); #else float complex x = 0.f + 1.f*I; double complex y = 0.0 - 1.0*I; #endif } //////////////////////////////// // NOTE(allen): Reuse Type Names From Another Module #include typedef struct Basics{ double a; float b; unsigned long long c; long long d; unsigned int e; int f; unsigned short g; short h; unsigned char i; char j; int z; } Basics; typedef struct Basics_Stdint{ double x1; float x2; uint64_t x3; int64_t x4; uint32_t x5; int32_t x6; uint16_t x7; int16_t x8; uint8_t x9; int8_t x0; } Basics_Stdint; typedef struct Pair{ int i; float f; } Pair; void c_versions_of_same_types(void){ Basics basics = { 1.5f, 1.50000000000001, -1, 1, -2, 2, -4, 4, -8, 8, }; Basics_Stdint basics_stdint = { 1.5f, 1.50000000000001, -1, 1, -2, 2, -4, 4, -8, 8, }; Pair memory_[] = { {100, 1.f}, {101, 2.f}, {102, 4.f}, {103, 8.f}, {104, 16.f}, {105, 32.f}, }; int x = memory_[3].i + basics.f; } //////////////////////////////// //~ NOTE(rjf): Bitfields typedef struct TypeWithBitfield TypeWithBitfield; struct TypeWithBitfield { int v : 14; int w : 4; int x : 32; int y : 4; int z : 10; }; typedef struct BitfieldType64 BitfieldType64; struct BitfieldType64 { uint64_t size : 63; uint64_t is_free : 1; }; void c_type_with_bitfield_usage(void) { TypeWithBitfield b = {0}; b.v = 100; b.w = 6; b.x = 434512; b.y = 7; b.z = 12; int x = (b.v + b.x); int y = (b.y - b.z); int z = (b.w) + 5; BitfieldType64 b64 = {0}; b64.size = 524288; b64.is_free = 1; int abc = 0; } ================================================ FILE: src/mule/mule_c.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* * Program to run in debugger organized to provide tests for * single threaded stepping, breakpoints, evaluation. */ void c_type_coverage_eval_tests(void); void c_type_with_bitfield_usage(void); ================================================ FILE: src/mule/mule_hotload_main.c ================================================ #include #include int main(int argc, char **argv) { int lib_loaded = 0; HANDLE lib = {0}; FILETIME lib_last_filetime = {0}; int (*get_number)(void) = 0; for(;;) { //- rjf: hot-load dll { HANDLE file = CreateFileA("mule_hotload_module.dll", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); FILETIME modified = {0}; if(GetFileTime(file, 0, 0, &modified) && CompareFileTime(&lib_last_filetime, &modified) == -1) { for(int reloaded = 0; !reloaded;) { if(lib_loaded) { FreeLibrary(lib); lib_loaded = 0; } BOOL copy_worked = CopyFile("mule_hotload_module.dll", "mule_hotload_module_temp.dll", 0); lib = LoadLibraryA("mule_hotload_module_temp.dll"); if(lib != INVALID_HANDLE_VALUE) { reloaded = 1; lib_last_filetime = modified; get_number = (int(*)(void))GetProcAddress(lib, "get_number"); lib_loaded = 1; } } } CloseHandle(file); } int number = get_number(); printf("got a number: %i\n", number); if(number == 0) { break; } Sleep(1000); } return 0; } ================================================ FILE: src/mule/mule_hotload_module_main.c ================================================ __declspec(dllexport) int get_number(void) { int sum = 0; for(int i = 0; i < 100; i += 1) { sum += i; sum += i; sum += 1; } sum = 1000; return sum; } ================================================ FILE: src/mule/mule_inline.cpp ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* ** Make sure we have an inlined function */ #if defined(_MSC_VER) # define FORCE_INLINE __forceinline #elif defined(__clang__) || defined(__GNUC__) # define FORCE_INLINE __attribute__((always_inline)) #else # error need force inline for this compiler #endif //////////////////////////////// // NOTE(allen): Inline Stepping unsigned int fixed_frac_bits = 5; static unsigned int bias = 7; static FORCE_INLINE unsigned int fixed_mul(unsigned int a, unsigned int b){ unsigned int c = (((a - bias)*(b - bias)) >> fixed_frac_bits) + bias; return(c); } static FORCE_INLINE unsigned int multi_file_inlinesite(unsigned int x){ // force compiler to generate annotations for code that's inside another file #include "inline_body.cpp" return x >> fixed_frac_bits; } static unsigned int test_value = 0; unsigned int inline_stepping_tests(void){ bias = 15; // NOTE(nick): Interesting that CL does not generate inline site symbols in order of apperance here unlike clang. // CL: // BinaryAnnotations: CodeLengthAndCodeOffset d 0 // BinaryAnnotation Length: 4 bytes (1 bytes padding) // // Clang: // BinaryAnnotations: LineOffset 1 CodeLength d // BinaryAnnotation Length: 4 bytes (0 bytes padding) unsigned int x = fixed_mul(5001, 7121); // CL: // BinaryAnnotations: CodeOffsetAndLineOffset d File 0 CodeOffsetAndLineOffset 22 LineOffset 1e // CodeLengthAndCodeOffset 2 3 // BinaryAnnotation Length: 12 bytes (1 bytes padding) // // Clang: // BinaryAnnotations: File 18 LineOffset ffffffe6 CodeOffset d CodeOffsetAndLineOffset 22 // File 0 LineOffset 1e CodeOffset 3 CodeLength 2 // BinaryAnnotation Length: 16 bytes (0 bytes padding) unsigned int z = multi_file_inlinesite(x); return(z); } ================================================ FILE: src/mule/mule_main.cpp ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* ** Program to run in debugger organized to provide tests for ** stepping, breakpoints, evaluation, cross-module calls. */ #include #include #include #include #if !_WIN32 # define RADDBG_MARKUP_STUBS #endif #define RADDBG_MARKUP_IMPLEMENTATION #include "lib_raddbg_markup/raddbg_markup.h" //////////////////////////////// // NOTE(allen): System For DLL Testing typedef void TestFunction(void); static void mule_init(void); static TestFunction* mule_get_module_function(char *name); #if _WIN32 #include HMODULE mule_dll = 0; static void mule_init(void){ mule_dll = LoadLibraryA("mule_module.dll"); } static TestFunction* mule_get_module_function(char *name){ TestFunction *result = (TestFunction*)GetProcAddress(mule_dll, name); return(result); } #else static void mule_init(void){ // TODO(allen): implement } static TestFunction* mule_get_module_function(char *name){ // TODO(allen): implement return(0); } #endif //////////////////////////////// // NOTE(nick): Entry Point int mule_main(int argc, char **argv); #if _WIN32 #include #include int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){ int argc = __argc; char **argv = __argv; int result = mule_main(argc, argv); return(result); } #else int main(int argc, char **argv){ return(mule_main(argc, argv)); } #endif //////////////////////////////// // NOTE(nick): BSS section test #if defined(__clang__) # pragma clang section bss="muleBSS" #elif defined(_MSC_VER) // NOTE(nick): clang-cl is borken it allocates memory and sets Initialized Flag on the seciton. // This is was reported by Jeff => https://bugs.llvm.org/show_bug.cgi?id=47939 // // This is still unresolved, last checked Sep 11, 2023. # pragma bss_seg("muleBSS") #else # error "bss not defined" #endif char global_variable_in_bss[4096*10000]; //////////////////////////////// // NOTE(allen): Inline Stepping (Built In Separate Unit) extern unsigned int fixed_frac_bits; unsigned int inline_stepping_tests(void); //////////////////////////////// // NOTE(rjf): -O2 Optimized Code (Built In Separate Unit) void optimized_build_eval_tests(void); void optimized_struct_parameters_eval_tests(void); //////////////////////////////// // NOTE(allen): Type Coverage Eval #include struct Basics { char a; unsigned char b; short c; unsigned short d; int e; unsigned int f; long long g; unsigned long long h; float i; double j; int z; }; struct Basics_Stdint { int8_t a; uint8_t b; int16_t c; uint16_t d; int32_t e; uint32_t f; int64_t g; uint64_t h; float i; double j; }; struct Pair { int x; float y; }; struct Fixed_Array { Pair pairs[10]; int count; }; struct Dynamic_Array { Pair *pairs; int count; }; raddbg_type_view(Dynamic_Array, slice($)); template struct TemplatedDynamicArray { T *v; int count; }; raddbg_type_view(TemplatedDynamicArray, rows($, count, array(v, count))); template struct OpaqueTemplatedDynamicArray { void *v; int count; }; raddbg_type_view(OpaqueTemplatedDynamicArray, array(cast(type *)v, count)); struct Struct_With_Embedded_Arrays { int x; float y; Pair pairs[10]; char z; }; typedef unsigned int Custom_Index_Type; typedef void Function_No_Params_Type(void); typedef void Function_Few_Params_Type(Pair *pairs, int count, Function_No_Params_Type *no_params_type); static Function_No_Params_Type *ty_no_params = 0; static Function_Few_Params_Type *ty_few_params = 0; struct Callback{ Function_Few_Params_Type *few_params; Function_No_Params_Type *no_params; Pair pair; }; union Vector_R2 { struct { float x; float y; }; float v[2]; }; raddbg_type_view(Vector_R2, rows($, x, y)); typedef union Matrix4x4F32 Matrix4x4F32; union Matrix4x4F32 { float elements[4][4]; }; raddbg_type_view(Matrix4x4F32, columns($.elements, $[0], $[1], $[2], $[3])); union PackedF16 { uint16_t v; struct { uint16_t mantissa : 10; uint16_t exponent : 5; uint16_t sign : 1; }; }; raddbg_type_view(PackedF16, exponent == 0 ? (0.00006103515625f*mantissa/1024.f) : (exponent == 31 && mantissa == 0 && sign == 1) ? "-infinity" : (exponent == 31 && mantissa == 0 && sign == 1) ? "+infinity" : (exponent == 31) ? "NaN" : (exponent < 15) ? (1.f/(1<<(15 - exponent)) * (sign * -2 + 1.f) * (1.f + mantissa/1024.f)) : (exponent > 15) ? ((1<<(exponent-15)) * (sign * -2 + 1.f) * (1.f + mantissa/1024.f)) : ((sign * -2 + 1) * 1.f + mantissa/1024.f)); enum Kind { Kind_Negative = -1, Kind_None, Kind_First, Kind_Second, Kind_Third, Kind_Fourth, Kind_COUNT, }; enum Flag { Flag_None = 0, Flag_First = 1, Flag_Second = 2, Flag_Third = 4, Flag_Fourth = 8, Flag_AllMoreNarrow = 0xFF, Flag_AllNarrow = 0xFFFF, Flag_All = 0xFFFFFFFF, }; struct Has_Enums { Kind kind; Flag flags; }; struct Discriminated_Union { Kind kind; union { struct { int x; int y; Vector_R2 vector; } first; Pair second; struct { Function_Few_Params_Type *few_params; Pair pairs[4]; } third; struct { Kind sub_kind; Flag flags; } fourth; }; }; raddbg_type_view(Discriminated_Union, kind == Kind.First ? first : kind == Kind.Second ? second : kind == Kind.Third ? third : kind == Kind.Fourth ? fourth : $); struct Crazy_Union { Kind kind; union { struct { int first_and_third__x; int first_and_third__y; int first_and_third__z; } first_and_third; struct { char *second__name; Pair second__pairs[16]; } second; }; union { struct { char *first__name; int first__x; } first; struct { char *third__name; Function_Few_Params_Type *third__few_params; } third; }; }; raddbg_type_view(Crazy_Union, kind == Kind.First ? rows($, first_and_third, first) : kind == Kind.Second ? rows($, second) : kind == Kind.Third ? rows($, first_and_third, third) : kind == Kind.Fourth ? kind : $); struct Linked_List{ Linked_List *next; Linked_List *prev; int x; }; enum{ Anonymous_A, Anonymous_B, Anonymous_C, Anonymous_D, }; typedef uint32_t SizedKind; enum SizedKindEnum { SizedKind_A, SizedKind_B, SizedKind_C, SizedKind_D, }; typedef Kind Alias1; typedef Flag Alias2; typedef Has_Enums Alias3; typedef Discriminated_Union Alias4; struct Has_A_Pre_Forward_Reference{ struct Gets_Referenced_Forwardly *pointer; }; struct Gets_Referenced_Forwardly{ int x; int y; }; struct Has_A_Post_Forward_Reference{ struct Gets_Referenced_Forwardly value; }; struct TypeWithMemberFunction { int x; int y; int z; char *name; __declspec(noinline) void SetInfo(int _x, int _y, char *_name) { x = _x; y = _y; z = 0; name = _name; OutputDebugStringA("setting info\n"); } }; static void no_params1(void){ } static void few_params1(Pair *pairs, int count, Function_No_Params_Type *no_params_type){ } static void type_coverage_eval_tests(void) { Basics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; Basics_Stdint basics_stdint = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; uint32_t a = (1<<31); int32_t b = (1<<31); char string[] = "Hello World!"; char longer_text[] = "Suppose there was some text\n" "With multiple lines in it\r\n" "\t> What ways might it be rendered?\n" "\t> How would it deal with line endings?\r\n"; wchar_t a_wide_string[] = L"This is a string, but instead of being encoded in a stream of bytes,\n" L"it is encoded in a stream of 2-byte packages!\n"; char some_data_with_a_string[] = { 'H', 'e', 'l', 'l', 'o', 27, 27, 2, 27, 125, }; struct SomeDataStructured { char data[4]; }; SomeDataStructured *some_data = (SomeDataStructured *)&some_data_with_a_string[0]; const char *const_string = "Hello, World!"; const char const_string_array[] = "Hello, World!"; const char *const const_ptr_const_string = "Hello, World!"; void *pointer = &basics; Basics *pointer_to_basics = &basics; Basics **pointer_to_pointer_to_basics = &pointer_to_basics; Fixed_Array fixed = { { { 3, 4.f}, { 5, 6.f}, { 7, 8.f}, { 9, 10.f}, {11, 12.f}, {13, 14.f}, {15, 16.f}, {17, 18.f}, {19, 20.f}, }, 9 }; Pair memory_[] = { {100, 1.f}, {101, 2.f}, {102, 4.f}, {103, 8.f}, {104, 16.f}, {105, 32.f}, }; Dynamic_Array dynamic = { memory_, 6 }; TemplatedDynamicArray templated_dynamic = {dynamic.pairs, dynamic.count}; TemplatedDynamicArray templated_dynamics[] = { {dynamic.pairs, dynamic.count}, {dynamic.pairs, dynamic.count}, {dynamic.pairs, dynamic.count}, {dynamic.pairs, dynamic.count}, {dynamic.pairs, dynamic.count}, }; OpaqueTemplatedDynamicArray otd = {dynamic.pairs, dynamic.count}; raddbg_pin(columns(sequence(6), fixed.pairs[$], memory_[$])); raddbg_pin(basics); raddbg_pin(fixed); raddbg_pin(pointer); raddbg_pin(dynamic); Struct_With_Embedded_Arrays swea = {0}; { swea.x = 4; swea.y = 23.5f; swea.pairs[0].x = 100; swea.pairs[0].y = 123.f; swea.pairs[2].x = 300; swea.pairs[2].y = 323.f; swea.pairs[5].x = 600; swea.pairs[5].y = 623.f; swea.z = 'z'; } Struct_With_Embedded_Arrays *swea_ptr = &swea; int access_via_ptr_member = swea_ptr->x; Custom_Index_Type custom_index = 42; Custom_Index_Type more_custom_indices[] = { 04,13,22,31,40 }; Function_No_Params_Type *ptr_no_params = no_params1; Function_No_Params_Type **ptr_ptr_no_params = &ptr_no_params; Function_Few_Params_Type *ptr_few_params = few_params1; Function_Few_Params_Type **ptr_ptr_few_params = &ptr_few_params; Callback callback = {few_params1, no_params1, {1, 2.f}}; Matrix4x4F32 matrix = { { {1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}, } }; Vector_R2 vector = {1.f, 2.f}; Has_Enums has_enums = {(Kind)4, (Flag)7}; struct EnumBitfields { Kind k1 : 4; Kind k2 : 3; Kind k3 : 1; Kind k4 : 16; }; EnumBitfields enum_bitfields = {}; enum_bitfields.k1 = Kind_First; enum_bitfields.k2 = Kind_Second; enum_bitfields.k3 = Kind_None; enum_bitfields.k4 = Kind_Fourth; Crazy_Union crazy_union = {}; crazy_union.kind = Kind_First; crazy_union.kind = Kind_Second; crazy_union.kind = Kind_Third; crazy_union.kind = Kind_Fourth; Discriminated_Union discriminated_union = {}; discriminated_union.kind = Kind_First; discriminated_union.first.x = 16; discriminated_union.first.y = 8; discriminated_union.first.vector.x = 4.f; discriminated_union.first.vector.y = 2.f; discriminated_union.kind = Kind_Second; discriminated_union.second.x = 123; discriminated_union.second.y = 3.14f; discriminated_union.kind = Kind_Third; discriminated_union.third.few_params = few_params1; discriminated_union.third.pairs[0] = memory_[0]; discriminated_union.third.pairs[1] = memory_[1]; discriminated_union.third.pairs[2] = memory_[2]; discriminated_union.third.pairs[3] = memory_[3]; discriminated_union.kind = Kind_Fourth; discriminated_union.fourth.sub_kind = Kind_First; discriminated_union.fourth.flags = (Flag)7; Linked_List list = {&list, &list, 0}; struct SLLNode { SLLNode *next; SLLNode *the_real_next_ptr; int x; }; SLLNode node6 = {0, 0, 6}; SLLNode node5 = {0, &node6, 5}; SLLNode node4 = {0, &node5, 4}; SLLNode node3 = {0, &node4, 3}; SLLNode node2 = {0, &node3, 2}; SLLNode node1 = {0, &node2, 1}; raddbg_pin(list(node1, the_real_next_ptr)); node6.next = &node1; Alias1 a1 = has_enums.kind; Alias2 a2 = has_enums.flags; Alias3 a3 = has_enums; Alias4 a4 = discriminated_union; Has_A_Pre_Forward_Reference r1 = {0}; Has_A_Post_Forward_Reference r2 = {0}; Basics &basics_ref = basics; const Basics *basics_const_ptr = &basics; const Basics &basics_const_ref = basics; union { int x; char y[4]; } integer_slicing = {123456789}; typedef struct stks { void *left; size_t len; } stks; stks stks_test[256] = {0}; stks *stks_first = &stks_test[0]; stks *stks_ptr = stks_first + 8; TypeWithMemberFunction twmf = {0}; twmf.SetInfo(123, 456, "foobar"); TestFunction *function = mule_get_module_function("dll_type_eval_tests"); function(); int abc = 0; for(int i = 0; i < 1000; i += 1) { if(i == 500) { abc+= 1; } int a = i + abc; int b = a*5; } char *names[] = { "samwise gamgee", "mithrandir", "grima wormtongue", "theodred", "theoden", "eomer", "eowyn", "arwen", "sauron", "baggins", "proudfoot", "hardbottle", "bag end", "hobbiton", "bree", "imladris", "isengard", "moria", "mount doom", "helm's deep", "bracegirdle", "buckleberry ferry", "amun sul", "frodo", "bilbo", "buckland", "fangorn", "elrond", "numenor", "treebeard", "shadowfax", "brego", "erod", "azufel", "dunedain", "saruman", "aragorn", "gandalf", "meriadoc brandybuck", "peregrine took", "faramir", "boromir", "ecthelion", "denethor", "mithrandil", "isildur", "haldir", "elessar", "elendil", "dead marsh", "rohan", "gondor", "anarion", "earendil", "cirith ungol", "minas morghul", "minas tirith", "barad-dur", "rivendell", "pellenor", "ithilien", "anduril", "narsil", "edoras", "mordor", "osgiliath", }; for(int i = 0; i < sizeof(names)/sizeof(names[0]); i += 1) { OutputDebugStringA(names[i]); OutputDebugStringA("\n"); } const int32_t x1 = 3; const int32_t y1 = -10; const int32_t z1 = x1 + y1; std::string small_cplusplus_string = "smallstr"; std::string cplusplus_string = "This is a C++ string!"; std::vector int_vector; int_vector.push_back(1); int_vector.push_back(2); int_vector.push_back(3); int_vector.push_back(4); int_vector.push_back(5); int_vector.push_back(6); int_vector.push_back(7); std::unordered_map people = { {"Peter", 1}, {"Oliver", 2}, {"Jack", 3}, }; std::vector *pint_vector = &int_vector; std::vector &rint_vector = int_vector; std::vector dynamic_array_vector; dynamic_array_vector.push_back(dynamic); dynamic_array_vector.push_back(dynamic); dynamic_array_vector.push_back(dynamic); dynamic_array_vector.push_back(dynamic); SizedKind sized_kind = SizedKind_C; int x = (int)(Anonymous_D); } //////////////////////////////// // NOTE(allen): Mutating Variables Eval static const int con_some_constant = 4; static const float con_some_constant_f = 0.04f; static int mut_x = 0; static int mut_y; static int mut_xarray[4] = {0, 1, 2, 3}; static int *mut_xptr; static float mut_f = 0; static float mut_g; static float mut_farray[4] = {0.5f, 1.5f, 2.5f, 3.5f}; static float *mut_fptr; static float mut_arrayarray[3][3]; static Linked_List mut_link; static void mutate_in_function(int *array, int count){ for (int i = 0; i < count; i += 1){ array[i] += 1; } for (int i = 0; i < 4; i += 1){ mut_farray[i] += 1.f; } } static void mutating_variables_eval_tests(void){ //////////////////////////////// // NOTE(allen): Basics int array_literal[10] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, }; Basics struct_literal = { -1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001, }; array_literal[0] = struct_literal.e = 9; int x = mut_x; int y = x + 10 + con_some_constant; mut_y = y; mut_xarray[0] += 0; mut_xarray[1] += x; mut_xarray[2] += y; mut_xarray[3] += x + y; mut_xptr = &mut_xarray[2]; *mut_xptr -= (y - x)/2; *(mut_xptr - 1) += 11; float f = mut_f + .333f + con_some_constant_f; float g = f + 10.1f; mut_g = g; mut_farray[0] += 0.000001f; mut_farray[1] += f; mut_farray[2] += g; mut_farray[3] += f + g; mut_fptr = &mut_farray[3]; *mut_fptr -= (g - f)*0.5f; *(mut_fptr - 1) += 1.f; float a = 0.777f; for (int i = 0; i < 3; i += 1){ float b = a*a - 1.f; for (int j = 0; j < 3; j += 1){ mut_arrayarray[i][j] = b; b += 0.111f; } a += 0.333f; } //////////////////////////////// // NOTE(allen): Changes in functions mutate_in_function(array_literal, 10); mutate_in_function(array_literal, 10); //////////////////////////////// // NOTE(allen): Changes through pointers Basics basic = struct_literal; Basics advanced = struct_literal; Basics *struct_pointer = &basic; basic.a += 1; advanced.a += 1; struct_pointer->a += 1; struct_pointer = &advanced; basic.b += 1; advanced.b += 1; struct_pointer->b += 1; Linked_List links[5]; for (int i = 0; i < 5; i += 1){ links[i].next = &links[i + 1]; links[i].prev = &links[i - 1]; links[i].x = i; } links[0].prev = 0; links[4].next = &mut_link; mut_link.prev = &links[4]; mut_link.next = 0; mut_link.x = 1000; Linked_List *link_ptr = links; link_ptr = link_ptr->next; link_ptr = &links[4]; link_ptr = &mut_link; Linked_List sentinel = {0}; sentinel.x = -1; sentinel.next = &links[0]; links[0].prev = &sentinel; sentinel.prev = &mut_link; mut_link.next = &sentinel; link_ptr = &sentinel; } //////////////////////////////// // NOTE(allen): Global Eval struct NestedNodeInner{ unsigned int small0; unsigned int small1; unsigned int big0; unsigned int big1; }; struct NestedNodeOuter{ NestedNodeOuter *next; NestedNodeInner *inner_nodes; unsigned int inner_node_count; }; static void nested_types_eval_tests(void){ // doing some setup NestedNodeOuter *outer1 = (NestedNodeOuter*)malloc(sizeof(NestedNodeOuter)); NestedNodeOuter *outer2 = (NestedNodeOuter*)malloc(sizeof(NestedNodeOuter)); NestedNodeOuter *outer3 = (NestedNodeOuter*)malloc(sizeof(NestedNodeOuter)); outer1->next = outer2; outer2->next = outer3; outer3->next = 0; outer1->inner_nodes = (NestedNodeInner*)malloc(sizeof(NestedNodeInner)*10); outer1->inner_node_count = 10; outer2->inner_nodes = (NestedNodeInner*)malloc(sizeof(NestedNodeInner)*10); outer2->inner_node_count = 10; outer3->inner_nodes = (NestedNodeInner*)malloc(sizeof(NestedNodeInner)*10); outer3->inner_node_count = 10; for (unsigned int i = 0; i < 10; i += 1){ outer1->inner_nodes[i].small0 = i; outer1->inner_nodes[i].small1 = 2*i; outer1->inner_nodes[i].big0 = 0xFFFFFF + 0xF*i; outer1->inner_nodes[i].big1 = 0xFFFFFF + 0xFF*i; outer2->inner_nodes[i].small0 = 1 + i; outer2->inner_nodes[i].small1 = 3*i; outer2->inner_nodes[i].big0 = 0x1000000 + 0x10*i; outer2->inner_nodes[i].big1 = 0x1000000 + 0x101*i; outer3->inner_nodes[i].small0 = 2 + i; outer3->inner_nodes[i].small1 = 4*i; outer3->inner_nodes[i].big0 = 0x8000000 + 0xF0*i; outer3->inner_nodes[i].big1 = 0x8000000 + 0xF0F*i; } // okay eval it here int x = 0; } //////////////////////////////// // NOTE(rjf): Struct Parameters Eval static void struct_parameter_helper(Basics basics) { basics.a += 1; basics.a += 1; basics.a += 1; } static void struct_parameters_eval_tests(void) { Basics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; struct_parameter_helper(basics); } //////////////////////////////// // NOTE(allen): Global Eval static int g_abc = 100; static float g_xyz = 21.f; static Alias1 g_kind = Kind_First; // TODO(allen): more global test types static void complicated_global_mutation(int *x){ *x = (int)g_xyz; } static void cross_unit_global_mutation(void){ fixed_frac_bits = 10; } static void global_eval_tests(void){ g_abc = 11*11; g_xyz = (float)g_abc - 21.f; int z = g_abc; complicated_global_mutation(&z); complicated_global_mutation(&g_abc); if (g_kind == Kind_First){ g_abc -= 1; g_kind = Kind_None; } cross_unit_global_mutation(); static int l_abc = 200; static float l_xyz = 42.f; static Alias1 l_kind = Kind_Second; l_abc = g_abc*2; l_xyz = g_xyz*2; l_kind = (Alias1)(g_kind + 1); } //////////////////////////////// // NOTE(allen): Return Eval static int complicated_return_expression(void){ int x = 171717; return((x % 13) <= 5?(x % 19)*11:(x - 500)%200); } static void return_eval_tests(void){ complicated_return_expression(); } //////////////////////////////// // NOTE(allen): TLS Eval #if _WIN32 # define thread_var __declspec(thread) #else # define thread_var __thread #endif thread_var int tls_a = 100; thread_var int tls_b = 999; static void tls_eval_tests(void){ tls_a = (tls_a + tls_b)/2; tls_b = tls_b - tls_a; TestFunction *dll_tls_eval_test = mule_get_module_function("dll_tls_eval_test"); if (dll_tls_eval_test != 0){ dll_tls_eval_test(); } } //////////////////////////////// // NOTE(allen): Complicated Type Coverage Eval struct Complicated_Type_Members{ int x600[2][2][2][2]; int *x601[2][2][2][2]; int (*x602)[2][2][2][2]; int (*x603[2])[2][2][2]; int (*(*x604[2])[2])[2][2]; int (*(*(*x605[2])[2])[2])[2]; int (*x33[2])(void); int (*x34[3])(void); int (*x35[2][2])(void); int (*(*z33)(void))[2]; int (*(*z34)(void))[3]; int (*(*z35)(void))[2][2]; int (*(*f2)(void))(void); int (*(*(*f3)(void))(void))(void); int (*(*f4)(int))(void); int (*(*f5)(void))(int); int (*(*f6)(int))(int); int (*(*(*f7_growing)(char))(short))(int); int (*(*(*f7_shrinking)(int))(short))(char); }; static void complicated_type_coverage_tests(void){ Complicated_Type_Members m = {0}; int x1 = {0}; int *x2 = {0}; int **x3 = {0}; int x4a[2] = {0}; int *x4[2] = {0}; int x5a[3] = {0}; int *x5[3] = {0}; int *x6[2][2] = {0}; int (*x7)[2] = {0}; int (*x8)[3] = {0}; int (*x9)[2][2] = {0}; int x600[2][2][2][2] = {0}; int *x601[2][2][2][2] = {0}; int (*x602)[2][2][2][2] = {0}; int (*x603[2])[2][2][2] = {0}; int (*(*x604[2])[2])[2][2] = {0}; int (*(*(*x605[2])[2])[2])[2] = {0}; int x606_growing [2][3][4][5] = {0}; int x606_shrinking[5][4][3][2] = {0}; int (*(*(*x607_growing [2])[3])[4])[5] = {0}; int (*(*(*x607_shrinking[5])[4])[3])[2] = {0}; int **x10[2] = {0}; int **x11[3] = {0}; int **x12[2][2] = {0}; int *(*x13)[2] = {0}; int *(*x14)[3] = {0}; int *(*x15)[2][2] = {0}; int **x16[2] = {0}; int **x17[3] = {0}; int **x18[2][2] = {0}; int (*y1[2])[2] = {0}; int (*y2[3])[2] = {0}; int (*y3[2][2])[2] = {0}; int (*y4[2])[3] = {0}; int (*y5[3])[3] = {0}; int (*y6[2][2])[3] = {0}; int (*y7[2])[2][2] = {0}; int (*y8[3])[2][2] = {0}; int (*y9[2][2])[2][2] = {0}; int (*x19)(void) = {0}; int (*x20)(int) = {0}; int (*x21)(int, int) = {0}; int (*x22)(int*, int) = {0}; int (*x23)(int**, int) = {0}; int (*x24)(int**, int*) = {0}; int (*x25)(int**, int**) = {0}; int *(*x26)(void) = {0}; int *(*x27)(int) = {0}; int *(*x28)(int, int) = {0}; int *(*x29)(int*, int) = {0}; int *(*x30)(int**, int) = {0}; int *(*x31)(int**, int*) = {0}; int *(*x32)(int**, int**) = {0}; int (*x33[2])(void) = {0}; int (*x34[3])(void) = {0}; int (*x35[2][2])(void) = {0}; int (*x36[2])(int) = {0}; int (*x37[3])(int) = {0}; int (*x38[2][2])(int) = {0}; int (*x39[2])(int, int) = {0}; int (*x40[3])(int, int) = {0}; int (*x41[2][2])(int, int) = {0}; int (*x42[2])(int*, int) = {0}; int (*x43[3])(int*, int) = {0}; int (*x44[2][2])(int*, int) = {0}; int (*x45[2])(int**, int) = {0}; int (*x46[3])(int**, int) = {0}; int (*x47[2][2])(int**, int) = {0}; int (*x48[2])(int**, int*) = {0}; int (*x49[3])(int**, int*) = {0}; int (*x50[2][2])(int**, int*) = {0}; int (*x51[2])(int**, int**) = {0}; int (*x52[3])(int**, int**) = {0}; int (*x53[2][2])(int**, int**) = {0}; int (*(*z33)(void))[2] = {0}; int (*(*z34)(void))[3] = {0}; int (*(*z35)(void))[2][2] = {0}; int (*(*z36)(int))[2] = {0}; int (*(*z37)(int))[3] = {0}; int (*(*z38)(int))[2][2] = {0}; int (*(*z39)(int, int))[2] = {0}; int (*(*z40)(int, int))[3] = {0}; int (*(*z41)(int, int))[2][2] = {0}; int (*(*z42)(int*, int))[2] = {0}; int (*(*z43)(int*, int))[3] = {0}; int (*(*z44)(int*, int))[2][2] = {0}; int (*(*z45)(int**, int))[2] = {0}; int (*(*z46)(int**, int))[3] = {0}; int (*(*z47)(int**, int))[2][2] = {0}; int (*(*z48)(int**, int*))[2] = {0}; int (*(*z49)(int**, int*))[3] = {0}; int (*(*z50)(int**, int*))[2][2] = {0}; int (*(*z51)(int**, int**))[2] = {0}; int (*(*z52)(int**, int**))[3] = {0}; int (*(*z53)(int**, int**))[2][2] = {0}; int (*(*z303[2])(void)) = {0}; int (*(*z304[3])(void)) = {0}; int (*(*z305[2][2])(void)) = {0}; int (*(*z306[2])(int)) = {0}; int (*(*z307[3])(int)) = {0}; int (*(*z308[2][2])(int)) = {0}; int (*(*z309[2])(int, int)) = {0}; int (*(*z400[3])(int, int)) = {0}; int (*(*z401[2][2])(int, int)) = {0}; int (*(*z402[2])(int*, int)) = {0}; int (*(*z403[3])(int*, int)) = {0}; int (*(*z404[2][2])(int*, int)) = {0}; int (*(*z405[2])(int**, int)) = {0}; int (*(*z406[3])(int**, int)) = {0}; int (*(*z407[2][2])(int**, int)) = {0}; int (*(*z408[2])(int**, int*)) = {0}; int (*(*z409[3])(int**, int*)) = {0}; int (*(*z500[2][2])(int**, int*)) = {0}; int (*(*z501[2])(int**, int**)) = {0}; int (*(*z502[3])(int**, int**)) = {0}; int (*(*z503[2][2])(int**, int**)) = {0}; int (*(*f2)(void))(void) = {0}; int (*(*(*f3)(void))(void))(void) = {0}; int (*(*f4)(int))(void) = {0}; int (*(*f5)(void))(int) = {0}; int (*(*f6)(int))(int) = {0}; int (*(*(*f7_growing)(char))(short))(int) = {0}; int (*(*(*f7_shrinking)(int))(short))(char) = {0}; int (*f8)(int (*)(void)) = {0}; int (*f9)(void (*)(int)) = {0}; void (*f10)(int (*)(int)) = {0}; int (*f11)(int, int (*)(void)) = {0}; int (*f12)(int (*)(void), int) = {0}; int (*f13)(int (*)(void), int (*)(void)) = {0}; int (*f14)(int (*)(void)) = {0}; int (*f15)(int (*)(int (*)(void))) = {0}; int (*f16)(int (*)(int (*)(int (*)(void)))) = {0}; int (*f17)(int (*)(int (*)(int (*)(int (*)(void))))) = {0}; int (*f18)(int (*)(void)) = {0}; int (*f19)(int (*(*)(void))(void)) = {0}; int (*f20)(int (*(*(*)(void))(void))(void)) = {0}; int (*f21)(int (*(*(*(*)(void))(void))(void))(void)) = {0}; int (*(*(*(*f22)(void))(void))(void))(void) = {0}; int (*(*(*(*f23)(int [2]))(void))(void))(void) = {0}; int (*(*(*(*f24)(int *[2]))(int [3]))(void))(void) = {0}; int (*(*(*(*f25)(int (*)[2]))(int *[3]))(int [4]))(void) = {0}; int (*(*(*(*f26)(int **(**)[2]))(int (*)[3]))(int *[4]))(int [5]) = {0}; int x = 0; } //////////////////////////////// // NOTE(allen): Extended Type Coverage Eval template struct Template_Example{ X x; int y; }; template struct Template_Example2{ X x; Y y; }; template struct Template_Example3{ X x; Y y; Template_Example3(X x, Y y) { this->x = x; this->y = y; } ~Template_Example3() { int x = 2; int y = 5; int z = x + y; } }; struct SingleInheritanceBase { int x; int y; }; struct SingleInheritanceDerived : SingleInheritanceBase { int z; int w; }; struct Has_Members{ int a; int b; uint64_t c; uint64_t d; Basics bas; int w(void){ return a; } int x(void){ return b; } uint64_t y(void){ return c; } uint64_t z(void){ return d; } Basics bas_f(void){ return bas; } }; struct Has_Static_Members{ int a; int b; static uint64_t c; static uint64_t d; int w(void){ return a; } int x(void){ return b; } static uint64_t y(void){ return c; } static uint64_t z(void){ return d; } }; uint64_t Has_Static_Members::c = 0; uint64_t Has_Static_Members::d = 0; struct Pointer_To_Member{ int Has_Members::*member_ptr_int; uint64_t Has_Members::*member_ptr_u64; Basics Has_Members::*member_ptr_bas; int (Has_Members::*method_ptr_int)(void); uint64_t (Has_Members::*method_ptr_u64)(void); Basics (Has_Members::*method_ptr_bas)(void); }; struct Has_Sub_Types{ struct Sub_Type1{ int x; int y; }; struct Sub_Type2{ float x; float y; }; Sub_Type1 a; Sub_Type2 b; }; struct Conflicting_Type_Names{ struct Sub_Type1{ uint64_t z; }; struct Sub_Type2{ int64_t z; }; Sub_Type1 a; Sub_Type2 b; }; struct Has_Private_Sub_Types{ Has_Private_Sub_Types(char x1, char y1, float x2, int y2, int x3, float y3){ this->a.x = x1; this->a.y = y1; this->b.x = x2; this->b.y = y2; this->c.x = x3; this->c.y = y3; } struct Public_Sub_Type{ char x; char y; }; Public_Sub_Type a; protected: struct Protected_Sub_Type{ float x; int y; }; Protected_Sub_Type b; private: struct Private_Sub_Type{ int x; float y; }; Private_Sub_Type c; }; struct Vtable_Parent{ virtual void a_virtual_function(void) = 0; virtual void b_virtual_function(void) = 0; virtual void c_virtual_function(void) = 0; void a_virtual_function(int r){ for (int i = 0; i < r; i += 1){ a_virtual_function(); } } }; struct Vtable_Child : Vtable_Parent{ int x; int y; Vtable_Child(int a, int b){ x = a; y = b; } virtual void a_virtual_function(void){ x = 0; }; virtual void b_virtual_function(void){ y = 0; }; virtual void c_virtual_function(void){ x = y; }; }; struct Vinheritance_Base{ int x; int y; virtual void a_virtual_function(void){ x = 0; }; virtual void b_virtual_function(void){ y = 0; }; virtual void x_virtual_function(void){ y = x; }; }; struct Vinheritance_MidLeft : virtual Vinheritance_Base{ float left; virtual void c1_virtual_function(void){ left = 0; }; virtual void c2_virtual_function(void){ left = 0; }; }; struct Vinheritance_MidRight : virtual Vinheritance_Base{ float right; virtual void d_virtual_function(void){ right = 0; }; }; struct Vinheritance_Child : Vinheritance_MidLeft, Vinheritance_MidRight{ char *name; virtual void a_virtual_function(void){ x = 1; }; virtual void c1_virtual_function(void){ left = 1; }; }; struct Minheritance_Base{ int x; int y; }; struct Minheritance_MidLeft : Minheritance_Base{ float left; }; struct Minheritance_MidRight : Minheritance_Base{ float right; }; struct Minheritance_Child : Minheritance_MidLeft, Minheritance_MidRight{ char *name; }; struct Pure { virtual ~Pure() = default; virtual void Foo() = 0; }; struct PureChild : Pure { virtual ~PureChild() = default; virtual void Foo() {a += 1;} double a = 0; }; struct Base { int x; int y; int z; Base(){x = 1; y = 2; z = 3;} virtual ~Base() = default; virtual void Foo() = 0; }; struct Derived : Base { int r; int g; int b; int a; virtual ~Derived() = default; virtual void Foo() { x += 1; y += 1; y += 1; z += 1; z += 1; z += 1; a += 1; a += 1; a += 1; a += 1; } }; struct DerivedA : Base { float a; float b; DerivedA() {a = 123.f; b = 123.f;} virtual void Foo() {a += 1;} virtual ~DerivedA() = default; }; struct DerivedB : Base { double c; double d; DerivedB() {c = 123.0; d = 123.0;} virtual void Foo() {c += 1;} virtual ~DerivedB() = default; }; struct NonVirtualBase { int x; int y; int z; }; struct NonVirtualDerived : NonVirtualBase { int r; int g; int b; int a; }; struct OverloadedMethods{ int x; int cool_method(void){ return(x); } int cool_method(int z){ int r = x; x = z; return(r); } void cool_method(int y, int z){ if (x < z){ x = y; } else{ x = z; } } }; struct HasStaticConstMembers { int a; int b; static int c; static int d; static const int e = 789; static const int f = 101112; }; int HasStaticConstMembers::c = 123; int HasStaticConstMembers::d = 456; struct Has_A_Constructor{ int n; int d; Has_A_Constructor(int a, int b){ int gcd = 1; { int x = a; int y = b; if (x < y){ y = a; x = b; } for (;y > 0;){ int z = x%y; x = y; y = z; } gcd = x; } n = a/gcd; d = b/gcd; } static int N; static int D; ~Has_A_Constructor(){ int m = N*d + n*D; int e = d*D; N = m; D = d; } }; int Has_A_Constructor::N = 0; int Has_A_Constructor::D = 1; struct Constructor_Gotcha_Test{ int x; int y; void Constructor_Gotcha(void){ x = y = 0; } }; struct Has_A_Friend{ friend struct Modifies_Other; int get_x(void){ return x; } int get_y(void){ return y; } private: int x; int y; }; struct Modifies_Other{ int x; int y; void talk_to_friend(Has_A_Friend *other){ other->x = y; other->y = x; } }; namespace UserNamespace{ namespace SubA{ struct Foo{ int x; int y; }; }; namespace SubB{ struct Foo{ float u; float v; }; }; SubA::Foo foo_a = {10, 20}; SubB::Foo foo_b = {0.1f, 0.05f}; static void namespaced_function(void){ foo_a.x = (int)(foo_a.y*foo_b.u); foo_b.v = (float)(foo_a.x*foo_b.v); } }; static void call_with_pass_by_reference(int &x){ x += 1; } static void call_with_pass_by_const_reference(const int &x){ int y = x; } static void extended_type_coverage_eval_tests(void){ //////////////////////////////// // NOTE(allen): Extensions to base type system. { int x = 0; const int *x_ptr = &x; int *const x_cptr = &x; call_with_pass_by_reference(x); call_with_pass_by_const_reference(x); } //////////////////////////////// // NOTE(allen): Extensions to user defined types { Template_Example temp_f = {1.f, 2}; Template_Example temp_v = {(void*)&temp_f, 2}; Template_Example > temp_tf = {temp_f, 2}; Template_Example2 temp_if = {2, 1.f}; Template_Example3 temp3_if(2, 1.f); Template_Example3 temp3_vi((void *)&temp3_if, 1.f); Template_Example3> temp3_itif(123, temp_if); SingleInheritanceDerived sid; sid.x = 123; sid.y = 456; sid.z = 789; sid.w = 999; Pointer_To_Member pointer_to_member = { &Has_Members::a, &Has_Members::c, &Has_Members::bas, &Has_Members::x, &Has_Members::z, &Has_Members::bas_f, }; Has_Static_Members has_static_members = { 10, 20 }; Has_Static_Members::c = 100; Has_Static_Members::d = 110; has_static_members.x(); has_static_members.y(); has_static_members.z(); has_static_members.w(); Has_Sub_Types has_sub_types = { {100, 200}, {.1f, .2f}, }; Conflicting_Type_Names conflicting_type_names = { {10}, {-20}, }; Has_Private_Sub_Types has_private_sub_types(1, 2, 4, 8, 16, 32); Vtable_Child vtable_child(1, 2); vtable_child.a_virtual_function(); Vinheritance_Child vinheritance_child; vinheritance_child.name = "foobar"; vinheritance_child.left = 10.5f; vinheritance_child.right = 13.0f; vinheritance_child.x = -1; vinheritance_child.y = -1; Minheritance_Child minheritance_child; minheritance_child.name = "foobar"; minheritance_child.left = 10.5f; minheritance_child.right = 13.0f; minheritance_child.Minheritance_MidLeft::x = -1; minheritance_child.Minheritance_MidLeft::y = -1; minheritance_child.Minheritance_MidRight::x = +1; minheritance_child.Minheritance_MidRight::y = +1; Pure *child = new PureChild(); child->Foo(); child->Foo(); child->Foo(); delete child; Base *derived = new Derived(); derived->Foo(); derived->Foo(); derived->Foo(); delete derived; NonVirtualBase *non_virtual_derived = new NonVirtualDerived(); non_virtual_derived->x += 1; non_virtual_derived->x += 1; non_virtual_derived->x += 1; std::unique_ptr ridiculous_cplusplus_base_class = std::make_unique(); std::vector> ridiculous_cplusplus_array; for(int i = 0; i < 1024; i += 1) { if((i & 1) == 1) { ridiculous_cplusplus_array.push_back(std::make_unique()); } else { ridiculous_cplusplus_array.push_back(std::make_unique()); } } Base *base_array[1024] = {0}; for(int i = 0; i < sizeof(base_array)/sizeof(base_array[0]); i += 1) { if((i & 1) == 1) { base_array[i] = new DerivedA(); } else { base_array[i] = new DerivedB(); } } OverloadedMethods overloaded_methods; { overloaded_methods.x = 0; int a = overloaded_methods.cool_method(); overloaded_methods.cool_method(-10, 100); int b = overloaded_methods.cool_method(100); overloaded_methods.cool_method(b*2, a*2); int c = overloaded_methods.cool_method(a + b); int z = c; } Has_A_Constructor construct_me(360, 25); Has_A_Friend has_a_friend; Modifies_Other modifies_other; modifies_other.x = 57; modifies_other.y = 66; modifies_other.talk_to_friend(&has_a_friend); int x = has_a_friend.get_x(); int y = has_a_friend.get_y(); int z = x; HasStaticConstMembers static_const_members = {0}; static_const_members.a = 123 + HasStaticConstMembers::c * HasStaticConstMembers::e; static_const_members.b = 456 + HasStaticConstMembers::d * HasStaticConstMembers::f; } //////////////////////////////// // NOTE(allen): Namespaces { UserNamespace::namespaced_function(); } } //////////////////////////////// //~ rjf: Templated Function Eval Tests typedef struct TemplateArg TemplateArg; struct TemplateArg { int x; int y; int z; float a; float b; float c; char *name; }; template static T templated_factorial(T t) { T result = t; if(t > 1) { result *= templated_factorial(t-1); } return result; } template static T compute_template_arg_info(T t) { int sum = t.x + t.y + t.z; int size = sizeof(t); float sum_f = t.a + t.b + t.c; OutputDebugStringA(t.name); return t; } static void templated_function_eval_tests(void) { int int_factorial = templated_factorial(10); float float_factorial = templated_factorial(10); TemplateArg arg = {1, 2, 3, 4.f, 5.f, 6.f, "my template arg"}; compute_template_arg_info(arg); int x = 0; } //////////////////////////////// //~ NOTE(allen): C Type Coverage extern "C"{ #include "mule_c.h" } //////////////////////////////// //~ rjf: Basic Inline Line Info Tests #if defined(_MSC_VER) # define FORCE_INLINE __forceinline #elif defined(__clang__) # define FORCE_INLINE __attribute__((always_inline)) #else # error need force inline for this compiler #endif static FORCE_INLINE void basic_inlinee(int inlinee_param_x, int inlinee_param_y, int inlinee_param_z) { OutputDebugStringA("A\n"); OutputDebugStringA("B\n"); OutputDebugStringA("C\n"); OutputDebugStringA("D\n"); } static void basic_inline_tests(void) { OutputDebugStringA("{\n"); basic_inlinee(12, 34, 56); OutputDebugStringA("}\n"); } //////////////////////////////// //~ rjf: Fancy Visualization Eval Tests struct PackedBits { unsigned char b1 : 1; unsigned char b2 : 1; unsigned char b3 : 1; unsigned char b4 : 1; unsigned char b5 : 1; unsigned char b6 : 1; }; raddbg_type_view(unsigned char : 1, bool($)); struct Bitmap { unsigned char *base; int width; int height; }; raddbg_type_view(Bitmap, bitmap(base, width, height)); static unsigned int mule_bswap_u32(unsigned int x) { unsigned int result = (((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24)); return result; } static void fancy_viz_eval_tests(void) { //- rjf: windows -> GetLastError #if _WIN32 DWORD error_code = 0; SetLastError(1234); error_code = GetLastError(); SetLastError(4567); error_code = GetLastError(); (void)error_code; #endif //- rjf: booleans (checkboxes) bool bool1 = 0; raddbg_pin(bool1); bool bool2 = 1; raddbg_pin(bool2); bool bool3 = 0; raddbg_pin(bool3); PackedBits packed_bits = {}; packed_bits.b1 = 1; packed_bits.b3 = 1; packed_bits.b5 = 1; //- rjf: sliders float slide1 = 500.f; raddbg_pin(range1(slide1, 0, 1000)); double slide2 = 0.75; raddbg_pin(range1(slide2, 0, 1.0)); int slide3 = 25; raddbg_pin(range1(slide3, 0, 100)); //- rjf: colors float example_color_4f32[4] = {1.00f, 0.85f, 0.25f, 1.00f}; unsigned int example_color_u32 = 0xff6f30ff; struct {float r, g, b, a;} example_color_struct = {0.50f, 0.95f, 0.75f, 1.00f}; int x0 = 0; raddbg_pin(color(example_color_4f32)); raddbg_pin(color(example_color_u32)); raddbg_pin(color(example_color_struct)); //- rjf: multiline text char *long_string = ("This is an example of some very long text with line breaks\n" "in it. This is a very common kind of data which is inspected\n" "in the debugger while programming, and it is often a pain\n" "when it is poorly supported.\n"); char *code_string = ("#include \n" "\n" "int main(int argc, char**argv)\n" "{\n" " printf(\"Hello, World!\\n\");\n" " return 0;\n" "}\n\n"); int x1 = 0; raddbg_pin(text(long_string)); raddbg_pin(text(code_string, lang=c)); raddbg_pin(disasm(fancy_viz_eval_tests)); //- rjf: programmatic memory annotations void *some_block_of_memory = malloc(256); memset(some_block_of_memory, 0x27, 256); raddbg_annotate_vaddr_range(some_block_of_memory, 256, "test memory annotation"); //- rjf: half-floats PackedF16 f16s[] = { {0x0001}, // ~0.000000059604645 {0x03ff}, // ~0.000060975552 {0x0400}, // ~0.00006103515625 {0x3555}, // ~0.33325195 {0x3bff}, // ~0.99951172 {0x3c00}, // 1 {0x3c01}, // 1.00097656 {0x7bff}, // 65504, {0x7c00}, // +inf {0xfc00}, // -inf }; //- rjf: table index lookups struct { char *name; int x; int y; int z; } nodes[] = { {"---", 1, 7, 3}, {"---", 5, 4, 2}, {"second", 12, 41, 22}, {"---", 8, 9, 1}, {"---", 1, 1, 1}, {"first", 50, 50, 50}, {"fourth", 7, 7, 7}, {"---", 7, 12, 1}, {"third", 27, 43, 41}, {"---", 2, 17, 50}, }; int node_indices[] = { 5, 2, 8, 6 }; raddbg_pin(columns(node_indices, nodes[$])); //- rjf: bitmaps unsigned int background_color = 0x00000000; unsigned int main_color = 0xff2424ff; unsigned int shine_color = 0xff5693ff; unsigned int shadow_color = 0xff238faf; unsigned int bg = mule_bswap_u32(background_color); unsigned int cl = mule_bswap_u32(main_color); unsigned int sn = mule_bswap_u32(shine_color); unsigned int sh = mule_bswap_u32(shadow_color); unsigned int pixels[] = { bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, cl, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, cl, cl, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, cl, cl, bg, cl, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, bg, bg, cl, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, cl, cl, bg, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, cl, sn, sn, cl, cl, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, sh, sn, cl, cl, cl, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, sh, cl, cl, cl, sh, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, sh, sh, sh, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, bg, }; raddbg_pin(bitmap(pixels, 18, 18)); for(int i = 0; i < sizeof(pixels)/sizeof(pixels[0]); i += 1) { unsigned int r = pixels[i]&0x000000ff; unsigned int a = pixels[i]&0xff000000; pixels[i] = pixels[i]>>8; pixels[i] &= ~0xffff0000; pixels[i] |= (r<<16); pixels[i] |= (a); } for(int i = 0; i < sizeof(pixels)/sizeof(pixels[0]); i += 1) { unsigned int r = pixels[i]&0x000000ff; unsigned int a = pixels[i]&0xff000000; pixels[i] = pixels[i]>>8; pixels[i] &= ~0xffff0000; pixels[i] |= (r<<16); pixels[i] |= (a); } for(int i = 0; i < sizeof(pixels)/sizeof(pixels[0]); i += 1) { unsigned int r = pixels[i]&0x000000ff; unsigned int a = pixels[i]&0xff000000; pixels[i] = pixels[i]>>8; pixels[i] &= ~0xffff0000; pixels[i] |= (r<<16); pixels[i] |= (a); } int x2 = 0; //- rjf: type-viewed bitmaps Bitmap foo = {(unsigned char *)&pixels[0], 18, 18}; raddbg_pin(foo); //- rjf: name collisions with debugger rules Function_Few_Params_Type *raw = 0; char *text = "some_important_text_here\n"; Bitmap bitmap = foo; int x3 = 0; //- rjf: 3D geometry float vertex_data[] = // pos.x, pos.y, pos.z, nor.x, nor.y, nor.z, tex.u, tex.v, col.r, col.g, col.b, ... { -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 2.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 8.0f, 0.0f, 0.973f, 0.480f, 0.002f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 10.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, 0.6f, -1.0f, 0.0f, 0.0f, -1.0f, 2.0f, 2.0f, 0.973f, 0.480f, 0.002f, 0.6f, 0.6f, -1.0f, 0.0f, 0.0f, -1.0f, 8.0f, 2.0f, 0.973f, 0.480f, 0.002f, -0.6f, -0.6f, -1.0f, 0.0f, 0.0f, -1.0f, 2.0f, 8.0f, 0.973f, 0.480f, 0.002f, 0.6f, -0.6f, -1.0f, 0.0f, 0.0f, -1.0f, 8.0f, 8.0f, 0.973f, 0.480f, 0.002f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 10.0f, 0.973f, 0.480f, 0.002f, -0.6f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 2.0f, 10.0f, 0.973f, 0.480f, 0.002f, 0.6f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 8.0f, 10.0f, 0.973f, 0.480f, 0.002f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 10.0f, 10.0f, 0.973f, 0.480f, 0.002f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 1.0f, -0.6f, 1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 8.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 10.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.897f, 0.163f, 0.011f, 1.0f, 0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 8.0f, 2.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 2.0f, 8.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 8.0f, 8.0f, 0.897f, 0.163f, 0.011f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 10.0f, 0.897f, 0.163f, 0.011f, 1.0f, -1.0f, -0.6f, 1.0f, 0.0f, 0.0f, 2.0f, 10.0f, 0.897f, 0.163f, 0.011f, 1.0f, -1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 8.0f, 10.0f, 0.897f, 0.163f, 0.011f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 10.0f, 10.0f, 0.897f, 0.163f, 0.011f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 8.0f, 0.0f, 0.612f, 0.000f, 0.069f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 2.0f, 0.612f, 0.000f, 0.069f, -0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 1.0f, 8.0f, 2.0f, 0.612f, 0.000f, 0.069f, 0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 8.0f, 0.612f, 0.000f, 0.069f, -0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 1.0f, 8.0f, 8.0f, 0.612f, 0.000f, 0.069f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 10.0f, 0.612f, 0.000f, 0.069f, 0.6f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 10.0f, 0.612f, 0.000f, 0.069f, -0.6f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 8.0f, 10.0f, 0.612f, 0.000f, 0.069f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 10.0f, 10.0f, 0.612f, 0.000f, 0.069f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 1.0f, 0.6f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 1.0f, -0.6f, -1.0f, 0.0f, 0.0f, 8.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 10.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 2.0f, 2.0f, 0.127f, 0.116f, 0.408f, -1.0f, 0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 8.0f, 2.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 2.0f, 8.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 8.0f, 8.0f, 0.127f, 0.116f, 0.408f, -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 10.0f, 0.127f, 0.116f, 0.408f, -1.0f, -1.0f, 0.6f, -1.0f, 0.0f, 0.0f, 2.0f, 10.0f, 0.127f, 0.116f, 0.408f, -1.0f, -1.0f, -0.6f, -1.0f, 0.0f, 0.0f, 8.0f, 10.0f, 0.127f, 0.116f, 0.408f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 10.0f, 10.0f, 0.127f, 0.116f, 0.408f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 8.0f, 0.0f, 0.000f, 0.254f, 0.637f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 10.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, 0.6f, 0.0f, 1.0f, 0.0f, 2.0f, 2.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, 0.6f, 0.0f, 1.0f, 0.0f, 8.0f, 2.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, -0.6f, 0.0f, 1.0f, 0.0f, 2.0f, 8.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, -0.6f, 0.0f, 1.0f, 0.0f, 8.0f, 8.0f, 0.000f, 0.254f, 0.637f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 10.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 2.0f, 10.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 8.0f, 10.0f, 0.000f, 0.254f, 0.637f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 10.0f, 10.0f, 0.000f, 0.254f, 0.637f, -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 2.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 8.0f, 0.0f, 0.001f, 0.447f, 0.067f, 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 10.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, -0.6f, 0.0f, -1.0f, 0.0f, 2.0f, 2.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, -0.6f, 0.0f, -1.0f, 0.0f, 8.0f, 2.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, 0.6f, 0.0f, -1.0f, 0.0f, 2.0f, 8.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, 0.6f, 0.0f, -1.0f, 0.0f, 8.0f, 8.0f, 0.001f, 0.447f, 0.067f, -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 10.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 2.0f, 10.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 8.0f, 10.0f, 0.001f, 0.447f, 0.067f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 10.0f, 10.0f, 0.001f, 0.447f, 0.067f, -0.6f, 0.6f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, 0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, -0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, -0.6f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, 0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, 0.6f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, -0.6f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, -0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, -0.6f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, -0.6f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, -0.6f, 0.6f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, 0.6f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 0.6f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.973f, 0.480f, 0.002f, 1.0f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 1.0f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.897f, 0.163f, 0.011f, 0.6f, 0.6f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, 0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, -0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, -0.6f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, 0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, 0.6f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, -0.6f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, -0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, -0.6f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, -0.6f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, 0.6f, 0.6f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, 0.6f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -0.6f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.612f, 0.000f, 0.069f, -1.0f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, -0.6f, 0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, -0.6f, -0.6f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 0.6f, 0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -1.0f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, 0.6f, -0.6f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.127f, 0.116f, 0.408f, -0.6f, 1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, 1.0f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 1.0f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, 0.6f, 0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.000f, 0.254f, 0.637f, -0.6f, -0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -0.6f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -0.6f, 0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -0.6f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, -0.6f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -0.6f, -0.6f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -1.0f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, -0.6f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -0.6f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, 0.6f, -1.0f, 0.6f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.001f, 0.447f, 0.067f, }; unsigned int index_data[] = { 0, 1, 9, 9, 8, 0, 1, 2, 5, 5, 4, 1, 6, 7, 10, 10, 9, 6, 2, 3, 11, 11, 10, 2, 12, 13, 21, 21, 20, 12, 13, 14, 17, 17, 16, 13, 18, 19, 22, 22, 21, 18, 14, 15, 23, 23, 22, 14, 24, 25, 33, 33, 32, 24, 25, 26, 29, 29, 28, 25, 30, 31, 34, 34, 33, 30, 26, 27, 35, 35, 34, 26, 36, 37, 45, 45, 44, 36, 37, 38, 41, 41, 40, 37, 42, 43, 46, 46, 45, 42, 38, 39, 47, 47, 46, 38, 48, 49, 57, 57, 56, 48, 49, 50, 53, 53, 52, 49, 54, 55, 58, 58, 57, 54, 50, 51, 59, 59, 58, 50, 60, 61, 69, 69, 68, 60, 61, 62, 65, 65, 64, 61, 66, 67, 70, 70, 69, 66, 62, 63, 71, 71, 70, 62, 72, 73, 74, 74, 75, 72, 76, 77, 78, 78, 79, 76, 80, 81, 82, 82, 83, 80, 84, 85, 86, 86, 87, 84, 88, 89, 90, 90, 91, 88, 92, 93, 94, 94, 95, 92, 96, 97, 98, 98, 99, 96, 100, 101, 102, 102, 103, 100, 104, 105, 106, 106, 107, 104, 108, 109, 110, 110, 111, 108, 112, 113, 114, 114, 115, 112, 116, 117, 118, 118, 119, 116, 120, 121, 122, 122, 123, 120, 124, 125, 126, 126, 127, 124, 128, 129, 130, 130, 131, 128, 132, 133, 134, 134, 135, 132, 136, 137, 138, 138, 139, 136, 140, 141, 142, 142, 143, 140, 144, 145, 146, 146, 147, 144, 148, 149, 150, 150, 151, 148, 152, 153, 154, 154, 155, 152, 156, 157, 158, 158, 159, 156, 160, 161, 162, 162, 163, 160, 164, 165, 166, 166, 167, 164, }; int count = (sizeof index_data/4); float *vtx = vertex_data; int vtx_size = sizeof vertex_data; raddbg_pin(geo3d(index_data, count = count, vtx = vtx, vtx_size = vtx_size)); int x4 = 0; } //////////////////////////////// //~ rjf: Markup Tests static void markup_tests(void) { int x = 0; raddbg_add_breakpoint(&x, sizeof(x), 0, 1, 0); for(int i = 0; i < 10000; i += 1) { if(i == 5000) { x += 1; } } raddbg_remove_breakpoint(&x, sizeof(x), 0, 1, 0); } //////////////////////////////// //~ NOTE(allen): Function Overload Resolution static int overloaded_function(float y){ int r = (int)(y + 0.5f); return(r); } static int overloaded_function(float y, int x){ int r = overloaded_function(y) + x; return(r); } static int overloaded_function(int x){ float y = (float)x; int r = overloaded_function(y, 1); return(r); } //////////////////////////////// // NOTE(allen): Control Flow Stepping static void control_flow_stepping_tests(void){ { int a = 1; if (a < 1){ a += 1; } if (a < 2){ a += 2; } } { int a = 1; if (a < 1) { a += 1; } if (a < 2) { a += 2; } } { int a = 1; if (a < 1) a += 1; if (a < 2) a += 2; } { int a = 1; int b = 2; if (a <= b){ if (a == b){ b += 1; } else{ a += 1; } } else{ if (a%2){ a = b; } else{ a = b - 1; } } } { int a = 1; int b = 2; if (a <= b) { if (a == b) { b += 1; } else { a += 1; } } else { if (a%2) { a = b; } else { a = b - 1; } } } { int a = 1; int b = 2; if (a <= b) if (a == b) b += 1; else a += 1; else if (a%2) a = b; else a = b - 1; } { int x = 0; for (int i = 0; i < 10; i += 1){ x += i; } } { int x = 0; for (int i = 0; i < 10; i += 1) { x += i; } } { int x = 0; for (int i = 0; i < 10; i += 1) x += i; } { int x = 0; for (int i = 0; i < 10; i += 1) x += i; } { int a = 1; for (;a < 10;){ switch (a){ case 0: case 1: case 2: { a += 2; }break; default: case 4: case 5: { a += 1; }break; case 6: a += 1; break; case 7: a += 1; case 8: case 9: a += 1; } } } { int i = 0; while (i < 5){ i += 1; } while (i < 10) { i += 1; } while (i < 15) i += 1; while (i < 20) i += 1; } { int i = 0; do { i += 1; } while (i < 10); } { int i = 17; check_again: if (i <= 1) goto done; if ((i&1) == 0) goto even_case; // odd_case: i = 3*i + 1; even_case: i /= 2; goto check_again; done:; } { int x = 15; label_same_line:; x -= 1; if(x > 0) { goto label_same_line; } else { goto end_label_same_line; } } end_label_same_line:; } //////////////////////////////// // NOTE(allen): Indirect Call/Jump Stepping Tests typedef int FunctionType(int); static int function_foo(int a){ if (a < 1){ a += 1; } if (a < 2){ a += 2; } return(a); } static int function_bar(int x){ for (int i = 0; i < 10; i += 1){ x += i; } return(x); } static void indirect_call_jump_stepping_tests(void){ int z = 1; FunctionType *ptr = function_foo; z = ptr(z); if ((z & 1) == 0){ ptr = function_bar; } z = ptr(z); switch (z&7){ case 0: { z += 2; ptr = function_bar; }break; case 1: { z += 1; ptr = function_bar; }break; case 2: { z *= 2; ptr = function_bar; }break; case 3: { z -= 10; ptr = function_foo; }break; case 4: { z -= 5; ptr = function_foo; }break; case 5: { z = z ^ 0x10; ptr = function_foo; }break; case 6: { z = z & ~0x10; ptr = function_foo; }break; case 7: { z = z | 0x10; ptr = function_foo; }break; } z = ptr(z); } //////////////////////////////// // NOTE(rjf): alloca (Variable-Width Stack Changes) Stepping Tests static void alloca_stepping_tests(void) { int x = 1; int y = 3; int z = 5; #if _WIN32 int *mem = (int *)_alloca((x+y+z)*sizeof(int)); mem[0] = x; mem[1] = y; mem[2] = z; #else int *mem = (int *)__builtin_alloca((x+y+z)*sizeof(int)); mem[0] = x; mem[1] = y; mem[2] = z; #endif } //////////////////////////////// // NOTE(allen): Overloaded Line Stepping static int function_get_integer(void){ return(1); } static void function_with_multiple_parameters(int x, int y){ x += y; } static int recursive_single_line(int x){ return(x <= 1?0:x + recursive_single_line(x/2)); } static int shared_1(int x) { return(x); } static int shared_2(int x) { return(1 + shared_1(x)); } static void overloaded_line_stepping_tests(void){ function_with_multiple_parameters(function_get_integer(), function_get_integer()); function_with_multiple_parameters(function_get_integer(), function_get_integer()); function_with_multiple_parameters(function_get_integer(), function_get_integer()); recursive_single_line(50); recursive_single_line(50); recursive_single_line(50); shared_2(5); shared_2(5); shared_2(5); function_get_integer(); shared_1(1); shared_1(2); if ((shared_2(10) && shared_2(-1)) || shared_2(function_get_integer())){ int x = 0; } else{ int y = 0; } } //////////////////////////////// // NOTE(allen): Long Jump Stepping #include static jmp_buf global_jump_buffer; static int global_jump_x; static void long_jump_from_function(void){ int spin = 0; for (; spin < 5; spin += 1); longjmp(global_jump_buffer, 2); global_jump_x = spin; } static void long_jump_wrapped_in_function(void){ global_jump_x = 0; int val = setjmp(global_jump_buffer); if (val == 0){ global_jump_x = 1; longjmp(global_jump_buffer, 1); } else if (val == 1){ if (global_jump_x == 1){ global_jump_x = 2; long_jump_from_function(); } } else if (val == 2){ global_jump_x = 3; } } static void long_jump_stepping_tests(void){ long_jump_wrapped_in_function(); long_jump_wrapped_in_function(); long_jump_wrapped_in_function(); } //////////////////////////////// // NOTE(allen): Recursion Stepping static int recursive_call(int x){ if (x <= 1){ return(x); } int r1 = recursive_call(x - 1); int r2 = recursive_call(x - 2); return(r1 + r2); } static int tail_recursive_call(int x, int m){ if (x <= 1){ return(m); } return(tail_recursive_call(x - 1, x*m)); } static void recursion_stepping_tests(void){ recursive_call(4); recursive_call(4); tail_recursive_call(5, 1); tail_recursive_call(5, 1); } //////////////////////////////// // NOTE(rjf): Thread Stepping #if _WIN32 DWORD thread_step_thread(void *p) { int x = 0; for(int i = 0; i < 100000; i += 1) { x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; x += 1; } return 0; } #endif void thread_stepping_tests(void) { #if _WIN32 HANDLE h[8] = {0}; for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) { DWORD id = 0; h[i] = CreateThread(0, 0, thread_step_thread, 0, CREATE_SUSPENDED, &id); raddbg_thread_id_name(id, "thread_step_thread_%i", i); raddbg_thread_id_color_u32(id, 0xff9f23ff); } for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) { ResumeThread(h[i]); } for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) { WaitForSingleObject(h[i], INFINITE); } #endif } //////////////////////////////// // NOTE(rjf): Debug Strings static void debug_string_tests(void) { for(int i = 0; i < 100; i += 1) { printf("here is a number: %i\n", i); fflush(stdout); } #if _WIN32 for(int i = 0; i < 100; i += 1) { OutputDebugStringA("Hello, World!\n"); } char message[65409+1]; memset(&message[0], '=', sizeof(message)); for(int i = 1; i < sizeof(message); i += 128) { message[i] = '\n'; } message[sizeof(message) - 1] = 0; OutputDebugStringA(message); #endif } //////////////////////////////// //~ rjf: Thread Name Test #if _WIN32 DWORD dummy_thread(void *p) { Sleep(10); return 0; } #endif static void thread_name_tests(void) { #if _WIN32 DWORD id = 0; HANDLE h = CreateThread(0, 0, dummy_thread, 0, CREATE_SUSPENDED, &id); raddbg_thread_id_name(id, "dummy_thread"); raddbg_thread_id_color_u32(id, 0xff1f23ff); ResumeThread(h); WaitForSingleObject(h, INFINITE); #endif } //////////////////////////////// //~ rjf: Interrupt Stepping Tests #include static void interrupt_stepping_tests(void) { __debugbreak(); __debugbreak(); __debugbreak(); __debugbreak(); for(int i = 0; i < 1000; i += 1) { if(i == 999) { __debugbreak(); } } for(int i = 0; i < 1000; i += 1) { if(i == 999) { assert(0); } } int x = 0; } //////////////////////////////// //~ rjf: JIT Stepping Tests static void jit_stepping_tests(void) { OutputDebugString("A\n"); VOID *code = VirtualAlloc(0, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); *((uint32_t*)code) = 0xC39090CC; ((void (__fastcall *)()) code)(); OutputDebugString("B\n"); } //////////////////////////////// // NOTE(allen): Exception Stepping static void exception_filter_test(void) { __try { RaiseException(0xc0000095, 0, 0, 0); } __except (EXCEPTION_EXECUTE_HANDLER) { OutputDebugStringA("did an exception\n"); } } int *global_null_read_pointer = 0; static void trip(void){ *global_null_read_pointer = 0; } static void cpp_exception_in_function(void){ int v = 0; try{ throw 1; } catch (...){ v = 1; } } static void cpp_throw_in_function(void){ throw 1; } static void win32_exception_in_function(void){ #if _WIN32 int v = 0; __try{ trip(); v = 1; } __except (EXCEPTION_EXECUTE_HANDLER){ v = 2; } v = 3; __try{ trip(); v = 4; } __except (EXCEPTION_EXECUTE_HANDLER){ v = 5; } #endif } static void cpp_recursive_exception(int x){ try{ if (x > 1){ throw 1; } } catch (...){ x -= 1; cpp_recursive_exception(x); x += 1; } } static void win32_recursive_exception(int x){ #if _WIN32 __try{ if (x > 1){ throw 1; } } __except (EXCEPTION_EXECUTE_HANDLER){ x -= 1; win32_recursive_exception(x); x += 1; } #endif } static void exception_stepping_tests(void){ { int v = 0; try{ throw 1; } catch (...){ v = 1; } } { int v = 0; try{ cpp_throw_in_function(); } catch (...){ v = 1; } } cpp_exception_in_function(); cpp_exception_in_function(); #if _WIN32 win32_exception_in_function(); win32_exception_in_function(); #endif // NOTE(allen): Exception in catch tests { int v = 0; try{ v = 1; throw 1; } catch (...){ try{ v = 2; throw 2; } catch (...){ v = 3; } } } { int v = 0; try{ v = 1; throw 1; } catch (...){ cpp_exception_in_function(); } } #if _WIN32 { int v = 0; try{ v = 1; throw 1; } catch (...){ win32_exception_in_function(); } } #endif cpp_recursive_exception(4); cpp_recursive_exception(4); cpp_recursive_exception(4); #if _WIN32 win32_recursive_exception(4); win32_recursive_exception(4); win32_recursive_exception(4); #endif // NOTE(allen): Try in try tests { int v = 0; try{ try{ v = 1; throw 1; } catch (...){ v = 2; } throw 2; } catch (...){ v = 3; } } { int v = 0; try{ try{ v = 1; cpp_throw_in_function(); } catch (...){ v = 2; } throw 2; } catch (...){ v = 3; } } { int v = 0; try{ cpp_exception_in_function(); throw 2; } catch (...){ v = 3; } } #if _WIN32 { int v = 0; try{ win32_exception_in_function(); throw 2; } catch (...){ v = 3; } } #endif } typedef void (*callback_t)(int a); static void dynamic_step_test(void){ #if _WIN32 #if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( _M_AMD64 ) void *page = VirtualAlloc(0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); char *ptr = (char*)page; *ptr++ = 0x51; // push rcx *ptr++ = 0x59; // pop rcx *ptr++ = 0xC3; // ret callback_t cb = (callback_t)page; cb(1); #endif #endif } //////////////////////////////// raddbg_entry_point(mule_main); int mule_main(int argc, char** argv) { raddbg_thread_name("mule_main_thread"); raddbg_thread_color_rgba(0.4f, 0.9f, 0.2f, 1); if(raddbg_is_attached()) { raddbg_log("raddbg is attached!\n"); } mule_init(); // NOTE(allen): Eval Tests type_coverage_eval_tests(); mutating_variables_eval_tests(); nested_types_eval_tests(); struct_parameters_eval_tests(); global_eval_tests(); return_eval_tests(); tls_eval_tests(); complicated_type_coverage_tests(); extended_type_coverage_eval_tests(); templated_function_eval_tests(); c_type_coverage_eval_tests(); c_type_with_bitfield_usage(); optimized_build_eval_tests(); optimized_struct_parameters_eval_tests(); fancy_viz_eval_tests(); exception_filter_test(); markup_tests(); // NOTE(allen): Stepping Tests control_flow_stepping_tests(); indirect_call_jump_stepping_tests(); alloca_stepping_tests(); basic_inline_tests(); inline_stepping_tests(); overloaded_line_stepping_tests(); overloaded_function(100); dynamic_step_test(); long_jump_stepping_tests(); recursion_stepping_tests(); thread_stepping_tests(); debug_string_tests(); thread_name_tests(); jit_stepping_tests(); interrupt_stepping_tests(); exception_stepping_tests(); return(0); } ================================================ FILE: src/mule/mule_module.cpp ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #if _WIN32 #define export_function extern "C" __declspec(dllexport) #else #define export_function extern "C" #endif #if _WIN32 # define thread_var __declspec(thread) #else # define thread_var __thread #endif typedef struct OnlyInModule OnlyInModule; struct OnlyInModule { int x; int y; int z; char *name; }; typedef struct Basics Basics; struct Basics { int a; int b; int c; int d; }; static OnlyInModule only_in_module_global = { 1, 2, 3, "foobar", }; thread_var float tls_a = 1.015625f; thread_var int tls_b = -100; export_function void dll_tls_eval_test(void) { tls_a *= 1.5f; tls_b *= -2; only_in_module_global.x += 1; only_in_module_global.y += 2; only_in_module_global.z += 3; } export_function void dll_type_eval_tests(void) { Basics basics1 = {1, 2, 3, 4}; Basics basics2 = {4, 5, 6, 7}; OnlyInModule only_in_module = {123, 456, 789, "this type is only in the module!"}; int x = 0; (void)x; } ================================================ FILE: src/mule/mule_o2.cpp ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) static int important_s32 = 0; static float important_f32 = 0; #if _WIN32 #include #endif static void do_something_with_intermediate_values(void) { static int another_important_s32 = 0; static float another_important_f32 = 0; another_important_s32 = (int)important_f32; another_important_f32 = (float)important_s32; #if _WIN32 char buffer[256] = "Hello, World!\n"; buffer[0] += important_s32 + another_important_s32; buffer[1] += (int)another_important_f32 * important_f32; OutputDebugStringA(buffer); #endif } static void store_important_s32(int *ptr) { important_s32 = *ptr; } static void store_important_f32(float *ptr) { important_f32 = *ptr; } void optimized_build_eval_tests(void) { int simple_sum = 0; for(int i = 0; i < 10000; i += 1) { simple_sum += i; } store_important_s32(&simple_sum); do_something_with_intermediate_values(); static struct {float x, y;} vec2s[] = { { 10.f, 76.f }, { 40.f, 50.f }, { -230.f, 20.f }, { 27.f, 27.f }, { 57.f, -57.f }, { -37.f, 97.f }, { 99.f, 67.f }, { 99.f, 37.f }, { 99.f, 57.f }, }; { struct{float x, y;}sum = {0}; int count = sizeof(vec2s)/sizeof(vec2s[0]); for(int i = 0; i < count; i += 1) { sum.x += vec2s[i].x; sum.y += vec2s[i].y; } struct{float x, y;}avg = {sum.x/count, sum.y/count}; float f32 = avg.x * avg.y; store_important_f32(&f32); } do_something_with_intermediate_values(); int factorial = 1; for(int i = 10; i > 0; i -= 1) { factorial *= i; } store_important_s32(&factorial); do_something_with_intermediate_values(); } //////////////////////////////// // NOTE(allen): Struct Parameters Eval struct OptimizedBasics{ char a; unsigned char b; short c; unsigned short d; int e; unsigned int f; long long g; unsigned long long h; float i; double j; }; static void optimized_struct_parameter_helper(int *ptr, OptimizedBasics basics) { basics.a += *ptr; basics.a += 1; basics.a += 1; } void optimized_struct_parameters_eval_tests(void) { int x = 10; OptimizedBasics basics = {-1, 1, -2, 2, -4, 4, -8, 8, 1.5f, 1.50000000000001}; optimized_struct_parameter_helper(&x, basics); } ================================================ FILE: src/mule/mule_peb_trample.c ================================================ #include #include #include "mule_peb_trample_reload.c" static void HideModuleFromWindowsReload(HMODULE ModuleToFlush) { /* NOTE(casey): Normally you cannot "reload" an executable module with the same name, because Windows checks a linked list of loaded modules and assumes that if it's already loaded, it doesn't need to reload it, even though it may have to because it has changed on disk. This solution to that problem comes from some excellent spelunking by Martins Mozeiko, who figured out that you could overwrite the filenames Windows stores in your process's loaded module table, thus thwarting the Windows filename check against loaded modules, allowing you to reload an existing module that has changed without requiring it to have a different filename! */ PEB *Peb = (PEB *)__readgsqword(offsetof(TEB, ProcessEnvironmentBlock)); LIST_ENTRY *Head = &Peb->Ldr->InMemoryOrderModuleList; for(LIST_ENTRY *Entry = Head->Flink; Entry != Head; Entry = Entry->Flink) { LDR_DATA_TABLE_ENTRY *Mod = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if(Mod->DllBase == ModuleToFlush) { ZeroMemory(Mod->FullDllName.Buffer, Mod->FullDllName.Length); Mod->DllBase = 0; break; } } } int main(int argument_count, char **arguments) { char *exe_name = arguments[0]; HANDLE last_module = GetModuleHandle(0); int (*loop_iteration_function)(int it) = (int (*)(int))GetProcAddress(last_module, "loop_iteration"); FILETIME last_filetime = {0}; int should_exit = 0; for(int it = 0; !should_exit; it += 1) { int result = loop_iteration_function(it); printf("%i\n", result); Sleep(50); FILETIME current_filetime = {0}; HANDLE current_exe_file = CreateFile(exe_name, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); GetFileTime(current_exe_file, 0, 0, ¤t_filetime); CloseHandle(current_exe_file); if(it != 0 && CompareFileTime(&last_filetime, ¤t_filetime) < 0) { HideModuleFromWindowsReload(last_module); last_module = LoadLibrary(arguments[0]); loop_iteration_function = (int (*)(int))GetProcAddress(last_module, "loop_iteration"); } last_filetime = current_filetime; } return 0; } ================================================ FILE: src/mule/mule_peb_trample_reload.c ================================================ __declspec(dllexport) int loop_iteration(int it) { //return 111; #if 1 int sum = 0; for(int i = 0; i < 1000; i += 1) { sum += it*i; } return sum; #endif } ================================================ FILE: src/mutable_text/mutable_text.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xb8a06bff //////////////////////////////// //~ rjf: Main Layer Initialization internal void mtx_init(void) { Arena *arena = arena_alloc(); mtx_shared = push_array(arena, MTX_Shared, 1); mtx_shared->arena = arena; mtx_shared->slots_count = 256; mtx_shared->stripes_count = Min(mtx_shared->slots_count, os_get_system_info()->logical_processor_count); mtx_shared->slots = push_array(arena, MTX_Slot, mtx_shared->slots_count); mtx_shared->stripes = push_array(arena, MTX_Stripe, mtx_shared->stripes_count); for(U64 idx = 0; idx < mtx_shared->stripes_count; idx += 1) { mtx_shared->stripes[idx].arena = arena_alloc(); mtx_shared->stripes[idx].rw_mutex = rw_mutex_alloc(); } mtx_shared->mut_threads_count = Min(os_get_system_info()->logical_processor_count, 4); mtx_shared->mut_threads = push_array(arena, MTX_MutThread, mtx_shared->mut_threads_count); for(U64 idx = 0; idx < mtx_shared->mut_threads_count; idx += 1) { mtx_shared->mut_threads[idx].ring_size = KB(64); mtx_shared->mut_threads[idx].ring_base = push_array_no_zero(arena, U8, mtx_shared->mut_threads[idx].ring_size); mtx_shared->mut_threads[idx].cv = cond_var_alloc(); mtx_shared->mut_threads[idx].mutex = mutex_alloc(); mtx_shared->mut_threads[idx].thread = thread_launch(mtx_mut_thread__entry_point, &mtx_shared->mut_threads[idx]); } } //////////////////////////////// //~ rjf: Buffer Operations internal void mtx_push_op(C_Key buffer_key, MTX_Op op) { U64 hash = u64_hash_from_str8(str8_struct(&buffer_key)); MTX_MutThread *thread = &mtx_shared->mut_threads[hash%mtx_shared->mut_threads_count]; mtx_enqueue_op(thread, buffer_key, op); } //////////////////////////////// //~ rjf: Mutation Threads internal void mtx_enqueue_op(MTX_MutThread *thread, C_Key buffer_key, MTX_Op op) { // TODO(rjf): if op.replace is too big, need to split into multiple edits MutexScope(thread->mutex) for(;;) { U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos; U64 available_size = thread->ring_size - unconsumed_size; U64 needed_size = sizeof(buffer_key) + sizeof(op.range) + sizeof(op.replace.size) + op.replace.size; if(available_size >= needed_size) { thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &buffer_key); thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.range); thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.replace.size); thread->ring_write_pos += ring_write(thread->ring_base, thread->ring_size, thread->ring_write_pos, op.replace.str, op.replace.size); break; } cond_var_wait(thread->cv, thread->mutex, max_U64); } cond_var_broadcast(thread->cv); } internal void mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, C_Key *buffer_key_out, MTX_Op *op_out) { MutexScope(thread->mutex) for(;;) { U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos; if(unconsumed_size >= sizeof(*buffer_key_out) + sizeof(op_out->range) + sizeof(op_out->replace.size)) { thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, buffer_key_out); thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->range); thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->replace.size); op_out->replace.str = push_array_no_zero(arena, U8, op_out->replace.size); thread->ring_read_pos += ring_read(thread->ring_base, thread->ring_size, thread->ring_read_pos, op_out->replace.str, op_out->replace.size); break; } cond_var_wait(thread->cv, thread->mutex, max_U64); } cond_var_broadcast(thread->cv); } internal void mtx_mut_thread__entry_point(void *p) { MTX_MutThread *mut_thread = (MTX_MutThread *)p; ThreadNameF("mtx_mut_thread_%I64u", (U64)(mut_thread - mtx_shared->mut_threads)); for(;;) { Temp scratch = scratch_begin(0, 0); Access *access = access_open(); //- rjf: get next op C_Key buffer_key = {0}; MTX_Op op = {0}; mtx_dequeue_op(scratch.arena, mut_thread, &buffer_key, &op); //- rjf: get buffer's current data U128 hash = c_hash_from_key(buffer_key, 0); String8 data = c_data_from_hash(access, hash); //- rjf: clamp op by data op.range.min = Min(op.range.min, data.size); op.range.max = Min(op.range.max, data.size); //- rjf: construct new buffer if(op.range.max != op.range.min || op.replace.size != 0) { U64 new_data_size = data.size + op.replace.size - dim_1u64(op.range); Arena *arena = arena_alloc(.commit_size = new_data_size + ARENA_HEADER_SIZE, .reserve_size = new_data_size + ARENA_HEADER_SIZE); U8 *new_data_base = push_array_no_zero(arena, U8, new_data_size); String8 pre_replace_data = str8_substr(data, r1u64(0, op.range.min)); String8 post_replace_data = str8_substr(data, r1u64(op.range.max, data.size)); if(pre_replace_data.size != 0) { MemoryCopy(new_data_base+0, pre_replace_data.str, pre_replace_data.size); } if(op.replace.size != 0) { MemoryCopy(new_data_base+pre_replace_data.size, op.replace.str, op.replace.size); } if(post_replace_data.size != 0) { MemoryCopy(new_data_base+pre_replace_data.size+op.replace.size, post_replace_data.str, post_replace_data.size); } String8 new_data = str8(new_data_base, new_data_size); c_submit_data(buffer_key, &arena, new_data); } access_close(access); scratch_end(scratch); } } ================================================ FILE: src/mutable_text/mutable_text.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MUTABLE_TEXT_H #define MUTABLE_TEXT_H //////////////////////////////// //~ rjf: Cache Types typedef struct MTX_Node MTX_Node; struct MTX_Node { MTX_Node *next; MTX_Node *prev; U128 key; }; typedef struct MTX_Slot MTX_Slot; struct MTX_Slot { MTX_Node *first; MTX_Node *last; }; typedef struct MTX_Stripe MTX_Stripe; struct MTX_Stripe { Arena *arena; MTX_Node *free_node; RWMutex rw_mutex; }; //////////////////////////////// //~ rjf: Mutation Thread Types typedef struct MTX_Op MTX_Op; struct MTX_Op { Rng1U64 range; String8 replace; }; typedef struct MTX_MutThread MTX_MutThread; struct MTX_MutThread { U64 ring_size; U8 *ring_base; U64 ring_read_pos; U64 ring_write_pos; CondVar cv; Mutex mutex; Thread thread; }; //////////////////////////////// //~ rjf: Shared State typedef struct MTX_Shared MTX_Shared; struct MTX_Shared { Arena *arena; // rjf: buffer cache U64 slots_count; U64 stripes_count; MTX_Slot *slots; MTX_Stripe *stripes; // rjf: mut threads U64 mut_threads_count; MTX_MutThread *mut_threads; }; //////////////////////////////// //~ rjf: Globals global MTX_Shared *mtx_shared = 0; //////////////////////////////// //~ rjf: Main Layer Initialization internal void mtx_init(void); //////////////////////////////// //~ rjf: Buffer Operations internal void mtx_push_op(C_Key buffer_key, MTX_Op op); //////////////////////////////// //~ rjf: Mutation Threads internal void mtx_enqueue_op(MTX_MutThread *thread, C_Key buffer_key, MTX_Op op); internal void mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, C_Key *buffer_key_out, MTX_Op *op_out); internal void mtx_mut_thread__entry_point(void *p); #endif // MUTABLE_TEXT_H ================================================ FILE: src/natvis/base.natvis ================================================ {size,str} size,str {{ string={string.size,string.str} next={next} }} empty {{node count={node_count} total size={total_size} first={first->string} last={last->string} }} node_count total_size node_count first next string {{ count={count} pointer={strings} }} count count strings x y x*x + y*y x y x*x + y*y x y x*x + y*y x y z x*x + y*y + z*z x y z x*x + y*y + z*z x y z w x*x + y*y + z*z + w*w x y z w x*x + y*y + z*z + w*w {{ min={min} max={max} [dim]={max - min} }} min max max - min {{ min={min} max={max} [dim]={max - min} }} min max max - min {{ min={min} max={max} [dim]={max - min} }} min max max - min {{ min={min} max={max} [dim]={max - min} }} min max max - min {{ min={min} max={max} [dim]={max - min} }} min max max - min {{ name={string} hash={hash} value_string={value_string} value_stirngs={value_strings} }} {{ count={count} first={first} }} count count first next this chunk_count idx = 0 node->v[idx] idx += 1 node = node->next ================================================ FILE: src/os/core/linux/os_core_linux.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec) { DateTime dt = {0}; dt.sec = in.tm_sec; dt.min = in.tm_min; dt.hour = in.tm_hour; dt.day = in.tm_mday-1; dt.mon = in.tm_mon; dt.year = in.tm_year+1900; dt.msec = msec; return dt; } internal tm os_lnx_tm_from_date_time(DateTime dt) { tm result = {0}; result.tm_sec = dt.sec; result.tm_min = dt.min; result.tm_hour= dt.hour; result.tm_mday= dt.day+1; result.tm_mon = dt.mon; result.tm_year= dt.year-1900; return result; } internal timespec os_lnx_timespec_from_date_time(DateTime dt) { tm tm_val = os_lnx_tm_from_date_time(dt); time_t seconds = timegm(&tm_val); timespec result = {0}; result.tv_sec = seconds; return result; } internal DenseTime os_lnx_dense_time_from_timespec(timespec in) { DenseTime result = 0; { struct tm tm_time = {0}; gmtime_r(&in.tv_sec, &tm_time); DateTime date_time = os_lnx_date_time_from_tm(tm_time, in.tv_nsec/Million(1)); result = dense_time_from_date_time(date_time); } return result; } internal FileProperties os_lnx_file_properties_from_stat(struct stat *s) { FileProperties props = {0}; props.size = s->st_size; props.created = os_lnx_dense_time_from_timespec(s->st_ctim); props.modified = os_lnx_dense_time_from_timespec(s->st_mtim); if(s->st_mode & S_IFDIR) { props.flags |= FilePropertyFlag_IsFolder; } return props; } internal void os_lnx_safe_call_sig_handler(int x) { OS_LNX_SafeCallChain *chain = os_lnx_safe_call_chain; if(chain != 0 && chain->fail_handler != 0) { chain->fail_handler(chain->ptr); } abort(); } //////////////////////////////// //~ rjf: Entities internal OS_LNX_Entity * os_lnx_entity_alloc(OS_LNX_EntityKind kind) { OS_LNX_Entity *entity = 0; DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), pthread_mutex_unlock(&os_lnx_state.entity_mutex)) { entity = os_lnx_state.entity_free; if(entity) { SLLStackPop(os_lnx_state.entity_free); } else { entity = push_array_no_zero(os_lnx_state.entity_arena, OS_LNX_Entity, 1); } } MemoryZeroStruct(entity); entity->kind = kind; return entity; } internal void os_lnx_entity_release(OS_LNX_Entity *entity) { DeferLoop(pthread_mutex_lock(&os_lnx_state.entity_mutex), pthread_mutex_unlock(&os_lnx_state.entity_mutex)) { SLLStackPush(os_lnx_state.entity_free, entity); } } //////////////////////////////// //~ rjf: Thread Entry Point internal void * os_lnx_thread_entry_point(void *ptr) { OS_LNX_Entity *entity = (OS_LNX_Entity *)ptr; ThreadEntryPointFunctionType *func = entity->thread.func; void *thread_ptr = entity->thread.ptr; supplement_thread_base_entry_point(func, thread_ptr); return 0; } //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo * os_get_system_info(void) { return &os_lnx_state.system_info; } internal OS_ProcessInfo * os_get_process_info(void) { return &os_lnx_state.process_info; } internal String8 os_get_current_path(Arena *arena) { char *cwdir = getcwd(0, 0); String8 string = push_str8_copy(arena, str8_cstring(cwdir)); free(cwdir); return string; } internal U32 os_get_process_start_time_unix(void) { Temp scratch = scratch_begin(0,0); U64 start_time = 0; pid_t pid = getpid(); String8 path = push_str8f(scratch.arena, "/proc/%u", pid); struct stat st; int err = stat((char*)path.str, &st); if(err == 0) { start_time = st.st_mtime; } scratch_end(scratch); return (U32)start_time; } //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void * os_reserve(U64 size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if(result == MAP_FAILED) { result = 0; } return result; } internal B32 os_commit(void *ptr, U64 size) { mprotect(ptr, size, PROT_READ|PROT_WRITE); return 1; } internal void os_decommit(void *ptr, U64 size) { madvise(ptr, size, MADV_DONTNEED); mprotect(ptr, size, PROT_NONE); } internal void os_release(void *ptr, U64 size) { munmap(ptr, size); } //- rjf: large pages internal void * os_reserve_large(U64 size) { void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0); if(result == MAP_FAILED) { result = 0; } return result; } internal B32 os_commit_large(void *ptr, U64 size) { mprotect(ptr, size, PROT_READ|PROT_WRITE); return 1; } //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void) { U32 result = gettid(); return result; } internal void os_set_thread_name(String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); pthread_t current_thread = pthread_self(); pthread_setname_np(current_thread, (char *)name_copy.str); scratch_end(scratch); } //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code) { exit(exit_code); } //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); int lnx_flags = 0; if(flags & OS_AccessFlag_Read && flags & OS_AccessFlag_Write) { lnx_flags = O_RDWR; } else if(flags & OS_AccessFlag_Write) { lnx_flags = O_WRONLY; } else if(flags & OS_AccessFlag_Read) { lnx_flags = O_RDONLY; } if(flags & OS_AccessFlag_Append) { lnx_flags |= O_APPEND; } if(flags & (OS_AccessFlag_Write|OS_AccessFlag_Append)) { lnx_flags |= O_CREAT; } lnx_flags |= O_CLOEXEC; int fd = open((char *)path_copy.str, lnx_flags, 0755); OS_Handle handle = {0}; if(fd != -1) { handle.u64[0] = fd; } scratch_end(scratch); return handle; } internal void os_file_close(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return; } int fd = (int)file.u64[0]; close(fd); } internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; U64 total_num_bytes_to_read = dim_1u64(rng); U64 total_num_bytes_read = 0; U64 total_num_bytes_left_to_read = total_num_bytes_to_read; for(;total_num_bytes_left_to_read > 0;) { int read_result = pread(fd, (U8 *)out_data + total_num_bytes_read, total_num_bytes_left_to_read, rng.min + total_num_bytes_read); if(read_result >= 0) { total_num_bytes_read += read_result; total_num_bytes_left_to_read -= read_result; } else if(errno != EINTR) { break; } } return total_num_bytes_read; } internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; U64 total_num_bytes_to_write = dim_1u64(rng); U64 total_num_bytes_written = 0; U64 total_num_bytes_left_to_write = total_num_bytes_to_write; for(;total_num_bytes_left_to_write > 0;) { int write_result = pwrite(fd, (U8 *)data + total_num_bytes_written, total_num_bytes_left_to_write, rng.min + total_num_bytes_written); if(write_result >= 0) { total_num_bytes_written += write_result; total_num_bytes_left_to_write -= write_result; } else if(errno != EINTR) { break; } } return total_num_bytes_written; } internal B32 os_file_set_times(OS_Handle file, DateTime date_time) { if(os_handle_match(file, os_handle_zero())) { return 0; } int fd = (int)file.u64[0]; timespec time = os_lnx_timespec_from_date_time(date_time); timespec times[2] = {time, time}; int futimens_result = futimens(fd, times); B32 good = (futimens_result != -1); return good; } internal FileProperties os_properties_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return (FileProperties){0}; } int fd = (int)file.u64[0]; struct stat fd_stat = {0}; int fstat_result = fstat(fd, &fd_stat); FileProperties props = {0}; if(fstat_result != -1) { props = os_lnx_file_properties_from_stat(&fd_stat); } return props; } internal OS_FileID os_id_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return (OS_FileID){0}; } int fd = (int)file.u64[0]; struct stat fd_stat = {0}; int fstat_result = fstat(fd, &fd_stat); OS_FileID id = {0}; if(fstat_result != -1) { id.v[0] = fd_stat.st_dev; id.v[1] = fd_stat.st_ino; } return id; } internal B32 os_delete_file_at_path(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); if(remove((char*)path_copy.str) != -1) { result = 1; } scratch_end(scratch); return result; } internal B32 os_copy_file_path(String8 dst, String8 src) { B32 result = 0; OS_Handle src_h = os_file_open(OS_AccessFlag_Read, src); OS_Handle dst_h = os_file_open(OS_AccessFlag_Write, dst); if(!os_handle_match(src_h, os_handle_zero()) && !os_handle_match(dst_h, os_handle_zero())) { int src_fd = (int)src_h.u64[0]; int dst_fd = (int)dst_h.u64[0]; FileProperties src_props = os_properties_from_file(src_h); U64 size = src_props.size; U64 total_bytes_copied = 0; U64 bytes_left_to_copy = size; for(;bytes_left_to_copy > 0;) { off_t sendfile_off = total_bytes_copied; int send_result = sendfile(dst_fd, src_fd, &sendfile_off, bytes_left_to_copy); if(send_result <= 0) { break; } U64 bytes_copied = (U64)send_result; bytes_left_to_copy -= bytes_copied; total_bytes_copied += bytes_copied; } } os_file_close(src_h); os_file_close(dst_h); return result; } internal B32 os_move_file_path(String8 dst, String8 src) { B32 good = 0; Temp scratch = scratch_begin(0, 0); { char *src_cstr = (char *)push_str8_copy(scratch.arena, src).str; char *dst_cstr = (char *)push_str8_copy(scratch.arena, dst).str; int rename_result = rename(src_cstr, dst_cstr); good = (rename_result != -1); } scratch_end(scratch); return good; } internal String8 os_full_path_from_path(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); String8 path_copy = push_str8_copy(scratch.arena, path); char buffer[PATH_MAX] = {0}; realpath((char *)path_copy.str, buffer); String8 result = push_str8_copy(arena, str8_cstring(buffer)); scratch_end(scratch); return result; } internal B32 os_file_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); int access_result = access((char *)path_copy.str, F_OK); B32 result = 0; if(access_result == 0) { result = 1; } scratch_end(scratch); return result; } internal B32 os_folder_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); B32 exists = 0; String8 path_copy = push_str8_copy(scratch.arena, path); DIR *handle = opendir((char*)path_copy.str); if(handle) { closedir(handle); exists = 1; } scratch_end(scratch); return exists; } internal FileProperties os_properties_from_file_path(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); struct stat f_stat = {0}; int stat_result = stat((char *)path_copy.str, &f_stat); FileProperties props = {0}; if(stat_result != -1) { props = os_lnx_file_properties_from_stat(&f_stat); } scratch_end(scratch); return props; } //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file) { OS_Handle map = file; return map; } internal void os_file_map_close(OS_Handle map) { // NOTE(rjf): nothing to do; `map` handles are the same as `file` handles in // the linux implementation (on Windows they require separate handles) } internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) { if(os_handle_match(map, os_handle_zero())) { return 0; } int fd = (int)map.u64[0]; int prot_flags = 0; if(flags & OS_AccessFlag_Write) { prot_flags |= PROT_WRITE; } if(flags & OS_AccessFlag_Read) { prot_flags |= PROT_READ; } int map_flags = MAP_PRIVATE; void *base = mmap(0, dim_1u64(range), prot_flags, map_flags, fd, range.min); if(base == MAP_FAILED) { base = 0; } return base; } internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) { munmap(ptr, dim_1u64(range)); } //- rjf: directory iteration internal OS_FileIter * os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) { OS_FileIter *base_iter = push_array(arena, OS_FileIter, 1); base_iter->flags = flags; OS_LNX_FileIter *iter = (OS_LNX_FileIter *)base_iter->memory; { String8 path_copy = push_str8_copy(arena, path); iter->dir = opendir((char *)path_copy.str); iter->path = path_copy; } return base_iter; } internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { B32 good = 0; OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; for(;lnx_iter->dir != 0;) { // rjf: get next entry lnx_iter->dp = readdir(lnx_iter->dir); good = (lnx_iter->dp != 0); // rjf: unpack entry info struct stat st = {0}; int stat_result = 0; if(good) { Temp scratch = scratch_begin(&arena, 1); String8 full_path = push_str8f(scratch.arena, "%S/%s", lnx_iter->path, lnx_iter->dp->d_name); stat_result = stat((char *)full_path.str, &st); scratch_end(scratch); } // rjf: determine if filtered B32 filtered = 0; if(good) { filtered = ((st.st_mode == S_IFDIR && iter->flags & OS_FileIterFlag_SkipFolders) || (st.st_mode == S_IFREG && iter->flags & OS_FileIterFlag_SkipFiles) || (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == 0) || (lnx_iter->dp->d_name[0] == '.' && lnx_iter->dp->d_name[1] == '.' && lnx_iter->dp->d_name[2] == 0)); } // rjf: output & exit, if good & unfiltered if(good && !filtered) { info_out->name = push_str8_copy(arena, str8_cstring(lnx_iter->dp->d_name)); if(stat_result != -1) { info_out->props = os_lnx_file_properties_from_stat(&st); } break; } // rjf: exit if not good if(!good) { break; } } return good; } internal void os_file_iter_end(OS_FileIter *iter) { OS_LNX_FileIter *lnx_iter = (OS_LNX_FileIter *)iter->memory; closedir(lnx_iter->dir); } //- rjf: directory creation internal B32 os_make_directory(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); if(mkdir((char*)path_copy.str, 0755) != -1) { result = 1; } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); int id = shm_open((char *)name_copy.str, O_RDWR|O_CREAT, 0666); ftruncate(id, size); OS_Handle result = {(U64)id}; scratch_end(scratch); return result; } internal OS_Handle os_shared_memory_open(String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); int id = shm_open((char *)name_copy.str, O_RDWR, 0); OS_Handle result = {(U64)id}; scratch_end(scratch); return result; } internal void os_shared_memory_close(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())){return;} int id = (int)handle.u64[0]; close(id); } internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) { if(os_handle_match(handle, os_handle_zero())){return 0;} int id = (int)handle.u64[0]; void *base = mmap(0, dim_1u64(range), PROT_READ|PROT_WRITE, MAP_SHARED, id, range.min); if(base == MAP_FAILED) { base = 0; } return base; } internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) { if(os_handle_match(handle, os_handle_zero())){return;} munmap(ptr, dim_1u64(range)); } //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void) { struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); U64 result = t.tv_sec*Million(1) + (t.tv_nsec/Thousand(1)); return result; } internal U32 os_now_unix(void) { time_t t = time(0); return (U32)t; } internal DateTime os_now_universal_time(void) { time_t t = 0; time(&t); struct tm universal_tm = {0}; gmtime_r(&t, &universal_tm); DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); return result; } internal DateTime os_universal_time_from_local(DateTime *date_time) { // rjf: local DateTime -> universal time_t tm local_tm = os_lnx_tm_from_date_time(*date_time); local_tm.tm_isdst = -1; time_t universal_t = mktime(&local_tm); // rjf: universal time_t -> DateTime tm universal_tm = {0}; gmtime_r(&universal_t, &universal_tm); DateTime result = os_lnx_date_time_from_tm(universal_tm, 0); return result; } internal DateTime os_local_time_from_universal(DateTime *date_time) { // rjf: universal DateTime -> local time_t tm universal_tm = os_lnx_tm_from_date_time(*date_time); universal_tm.tm_isdst = -1; time_t universal_t = timegm(&universal_tm); tm local_tm = {0}; localtime_r(&universal_t, &local_tm); // rjf: local tm -> DateTime DateTime result = os_lnx_date_time_from_tm(local_tm, 0); return result; } internal void os_sleep_milliseconds(U32 msec) { usleep(msec*Thousand(1)); } //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params) { OS_Handle handle = {0}; posix_spawn_file_actions_t file_actions = {0}; int file_actions_init_code = posix_spawn_file_actions_init(&file_actions); if(file_actions_init_code == 0) { // redirect STDOUT int stdout_code = posix_spawn_file_actions_adddup2(&file_actions, (int)params->stdout_file.u64[0], STDOUT_FILENO); Assert(stdout_code == 0); // redirect STDERR int stderr_code = posix_spawn_file_actions_adddup2(&file_actions, (int)params->stderr_file.u64[0], STDERR_FILENO); Assert(stderr_code == 0); // redirect STDIN int stdin_code = posix_spawn_file_actions_adddup2(&file_actions, (int)params->stdin_file.u64[0], STDIN_FILENO); Assert(stdin_code == 0); posix_spawnattr_t attr = {0}; int attr_init_code = posix_spawnattr_init(&attr); if(attr_init_code == 0) { Temp scratch = scratch_begin(0, 0); // package argv char **argv = push_array(scratch.arena, char *, params->cmd_line.node_count + 1); { String8List l = str8_split_path(scratch.arena, params->path); str8_list_push(scratch.arena, &l, params->cmd_line.first->string); String8 path_to_exe = str8_path_list_join_by_style(scratch.arena, &l, PathStyle_SystemAbsolute); argv[0] = (char *)path_to_exe.str; U64 arg_idx = 1; for EachNode(n, String8Node, params->cmd_line.first->next) { argv[arg_idx++] = (char *)n->string.str; } } // package envp char **envp = 0; if(params->inherit_env) { envp = __environ; } else { envp = push_array(scratch.arena, char *, params->env.node_count + 2); U64 env_idx = 0; for EachNode(n, String8Node, params->cmd_line.first) { envp[env_idx] = (char *)n->string.str; } } if(params->debug_subprocesses) { // not suported InvalidPath; } if(!params->consoleless) { NotImplemented; } // spawn process pid_t pid = 0; int spawn_code = posix_spawn(&pid, argv[0], &file_actions, &attr, argv, envp); if(spawn_code == 0) { handle.u64[0] = (U64)pid; } // clean up attributes int attr_destroy_code = posix_spawnattr_destroy(&attr); Assert(attr_destroy_code == 0); scratch_end(scratch); } // clean up file actions int file_actions_destroy_code = posix_spawn_file_actions_destroy(&file_actions); Assert(file_actions_destroy_code == 0); } return handle; } internal B32 os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out) { pid_t pid = (pid_t)handle.u64[0]; B32 result = 0; if(endt_us == 0) { if(kill(pid, 0) >= 0) { result = (errno == ENOENT); if(result) { int status; waitpid(pid, &status, 0); } } else { Assert(0 && "failed to get status from pid"); } } else if(endt_us == max_U64) { for(;;) { int status = 0; int w = waitpid(pid, &status, 0); if(w == -1) { break; } if(WIFEXITED(status) || WIFSTOPPED(status) || WIFSIGNALED(status)) { result = 1; break; } } } else { NotImplemented; } return result; } internal void os_process_detach(OS_Handle handle) { // no need to close pid } internal B32 os_process_kill(OS_Handle handle) { int error_code = kill((pid_t)handle.u64[0], SIGKILL); B32 is_killed = error_code == 0; return is_killed; } //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal Thread os_thread_launch(ThreadEntryPointFunctionType *func, void *ptr) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Thread); entity->thread.func = func; entity->thread.ptr = ptr; { int pthread_result = pthread_create(&entity->thread.handle, 0, os_lnx_thread_entry_point, entity); if(pthread_result == -1) { os_lnx_entity_release(entity); entity = 0; } } Thread handle = {(U64)entity}; return handle; } internal B32 os_thread_join(Thread handle, U64 endt_us) { if(MemoryIsZeroStruct(&handle)) { return 0; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; int join_result = pthread_join(entity->thread.handle, 0); B32 result = (join_result == 0); os_lnx_entity_release(entity); return result; } internal void os_thread_detach(Thread handle) { if(MemoryIsZeroStruct(&handle)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)handle.u64[0]; os_lnx_entity_release(entity); } //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: mutexes internal Mutex os_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Mutex); int init_result = pthread_mutex_init(&entity->mutex_handle, 0); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } Mutex handle = {(U64)entity}; return handle; } internal void os_mutex_release(Mutex mutex) { if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_destroy(&entity->mutex_handle); os_lnx_entity_release(entity); } internal void os_mutex_take(Mutex mutex) { if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_lock(&entity->mutex_handle); } internal void os_mutex_drop(Mutex mutex) { if(MemoryIsZeroStruct(&mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)mutex.u64[0]; pthread_mutex_unlock(&entity->mutex_handle); } //- rjf: reader/writer mutexes internal RWMutex os_rw_mutex_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_RWMutex); int init_result = pthread_rwlock_init(&entity->rwmutex_handle, 0); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } RWMutex handle = {(U64)entity}; return handle; } internal void os_rw_mutex_release(RWMutex rw_mutex) { if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_destroy(&entity->rwmutex_handle); os_lnx_entity_release(entity); } internal void os_rw_mutex_take(RWMutex rw_mutex, B32 write_mode) { if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; if(write_mode) { pthread_rwlock_wrlock(&entity->rwmutex_handle); } else { pthread_rwlock_rdlock(&entity->rwmutex_handle); } } internal void os_rw_mutex_drop(RWMutex rw_mutex, B32 write_mode) { if(MemoryIsZeroStruct(&rw_mutex)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)rw_mutex.u64[0]; pthread_rwlock_unlock(&entity->rwmutex_handle); } //- rjf: condition variables internal CondVar os_cond_var_alloc(void) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_ConditionVariable); int init_result = pthread_cond_init(&entity->cv.cond_handle, 0); if(init_result == -1) { os_lnx_entity_release(entity); entity = 0; } int init2_result = 0; if(entity) { init2_result = pthread_mutex_init(&entity->cv.rwlock_mutex_handle, 0); } if(init2_result == -1) { pthread_cond_destroy(&entity->cv.cond_handle); os_lnx_entity_release(entity); entity = 0; } CondVar handle = {(U64)entity}; return handle; } internal void os_cond_var_release(CondVar cv) { if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_destroy(&entity->cv.cond_handle); pthread_mutex_destroy(&entity->cv.rwlock_mutex_handle); os_lnx_entity_release(entity); } internal B32 os_cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) { if(MemoryIsZeroStruct(&cv)) { return 0; } if(MemoryIsZeroStruct(&mutex)) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *mutex_entity = (OS_LNX_Entity *)mutex.u64[0]; struct timespec endt_timespec; endt_timespec.tv_sec = endt_us/Million(1); endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &mutex_entity->mutex_handle, &endt_timespec); B32 result = (wait_result != ETIMEDOUT); return result; } internal B32 os_cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us) { // TODO(rjf): because pthread does not supply cv/rw natively, I had to hack // this together, but this would probably just be a lot better if we just // implemented the primitives ourselves with e.g. futexes // if(MemoryIsZeroStruct(&cv)) { return 0; } if(MemoryIsZeroStruct(&mutex_rw)) { return 0; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; OS_LNX_Entity *rw_mutex_entity = (OS_LNX_Entity *)mutex_rw.u64[0]; struct timespec endt_timespec; endt_timespec.tv_sec = endt_us/Million(1); endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1)); B32 result = 0; pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle); pthread_rwlock_unlock(&rw_mutex_entity->rwmutex_handle); for(;;) { int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec); if(wait_result != ETIMEDOUT) { if(write_mode) { pthread_rwlock_wrlock(&rw_mutex_entity->rwmutex_handle); } else { pthread_rwlock_rdlock(&rw_mutex_entity->rwmutex_handle); } result = 1; break; } if(wait_result == ETIMEDOUT) { if(write_mode) { pthread_rwlock_wrlock(&rw_mutex_entity->rwmutex_handle); } else { pthread_rwlock_rdlock(&rw_mutex_entity->rwmutex_handle); } break; } } pthread_mutex_unlock(&cv_entity->cv.rwlock_mutex_handle); return result; } internal void os_cond_var_signal(CondVar cv) { if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_signal(&cv_entity->cv.cond_handle); } internal void os_cond_var_broadcast(CondVar cv) { if(MemoryIsZeroStruct(&cv)) { return; } OS_LNX_Entity *cv_entity = (OS_LNX_Entity *)cv.u64[0]; pthread_cond_broadcast(&cv_entity->cv.cond_handle); } //- rjf: cross-process semaphores internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { Semaphore result = {0}; if (name.size > 0) { for EachIndex(attempt_idx, 64) { sem_t *s = sem_open((char *)name.str, O_CREAT | O_EXCL, 0666, initial_count); if(s == SEM_FAILED) { s = sem_open((char *)name.str, 0); } if(s != SEM_FAILED) { result.u64[0] = (U64)s; break; } } } else { sem_t *s = mmap(0, sizeof(*s), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); AssertAlways(s != MAP_FAILED); int err = sem_init(s, 0, initial_count); if(err == 0) { result.u64[0] = (U64)s; } } return result; } internal void os_semaphore_release(Semaphore semaphore) { int err = munmap((void*)semaphore.u64[0], sizeof(sem_t)); AssertAlways(err == 0); } internal Semaphore os_semaphore_open(String8 name) { Semaphore result = {0}; sem_t *s = sem_open((char *)name.str, 0); if(s != SEM_FAILED) { result.u64[0] = (U64)s; } return result; } internal void os_semaphore_close(Semaphore semaphore) { sem_t *s = (sem_t *)semaphore.u64[0]; sem_close(s); } internal B32 os_semaphore_take(Semaphore semaphore, U64 endt_us) { // TODO(rjf): we need to use `sem_timedwait` here. AssertAlways(endt_us == max_U64); for(;;) { int err = sem_wait((sem_t*)semaphore.u64[0]); if(err == 0) { break; } else if(errno == EAGAIN) { continue; } break; } return 1; } internal void os_semaphore_drop(Semaphore semaphore) { for(;;) { int err = sem_post((sem_t*)semaphore.u64[0]); if(err == 0) { break; } else { if(errno == EAGAIN) { continue; } } break; } } //- rjf: barriers internal Barrier os_barrier_alloc(U64 count) { OS_LNX_Entity *entity = os_lnx_entity_alloc(OS_LNX_EntityKind_Barrier); if(entity != 0) { pthread_barrier_init(&entity->barrier, 0, count); } Barrier result = {IntFromPtr(entity)}; return result; } internal void os_barrier_release(Barrier barrier) { OS_LNX_Entity *entity = (OS_LNX_Entity*)PtrFromInt(barrier.u64[0]); if(entity != 0) { pthread_barrier_destroy(&entity->barrier); os_lnx_entity_release(entity); } } internal void os_barrier_wait(Barrier barrier) { OS_LNX_Entity *entity = (OS_LNX_Entity*)PtrFromInt(barrier.u64[0]); if(entity != 0) { pthread_barrier_wait(&entity->barrier); } } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); char *path_cstr = (char *)push_str8_copy(scratch.arena, path).str; void *so = dlopen(path_cstr, RTLD_LAZY|RTLD_LOCAL); OS_Handle lib = { (U64)so }; scratch_end(scratch); return lib; } internal VoidProc* os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); void *so = (void *)lib.u64; char *name_cstr = (char *)push_str8_copy(scratch.arena, name).str; VoidProc *proc = (VoidProc *)dlsym(so, name_cstr); scratch_end(scratch); return proc; } internal void os_library_close(OS_Handle lib) { void *so = (void *)lib.u64; dlclose(so); } //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(ThreadEntryPointFunctionType *func, ThreadEntryPointFunctionType *fail_handler, void *ptr) { // rjf: push handler to chain OS_LNX_SafeCallChain chain = {0}; SLLStackPush(os_lnx_safe_call_chain, &chain); chain.fail_handler = fail_handler; chain.ptr = ptr; // rjf: set up sig handler info struct sigaction new_act = {0}; new_act.sa_handler = os_lnx_safe_call_sig_handler; int signals_to_handle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, }; struct sigaction og_act[ArrayCount(signals_to_handle)] = {0}; // rjf: attach handler info for all signals for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) { sigaction(signals_to_handle[i], &new_act, &og_act[i]); } // rjf: call function func(ptr); // rjf: reset handler info for all signals for(U32 i = 0; i < ArrayCount(signals_to_handle); i += 1) { sigaction(signals_to_handle[i], &og_act[i], 0); } } //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void) { Guid guid = {0}; getrandom(guid.v, sizeof(guid.v), 0); guid.data3 &= 0x0fff; guid.data3 |= (4 << 12); guid.data4[0] &= 0x3f; guid.data4[0] |= 0x80; return guid; } //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) internal void lnx_signal_handler(int sig, siginfo_t *info, void *arg) { local_persist volatile U32 first = 0; if (ins_atomic_u32_eval_cond_assign(&first, 1, 0) != 0) { for(;;) { sleep(UINT32_MAX); } } local_persist void *ips[4096]; int ips_count = backtrace(ips, ArrayCount(ips)); fprintf(stderr, "A fatal signal was received: %s (%d). The process is terminating.\n", strsignal(sig), sig); fprintf(stderr, "Create a new issue with this report at %s.\n\n", BUILD_ISSUES_LINK_STRING_LITERAL); fprintf(stderr, "Callstack:\n"); for EachIndex(i, ips_count) { Dl_info info = {0}; dladdr(ips[i], &info); char cmd[2048]; snprintf(cmd, sizeof(cmd), "llvm-symbolizer --relative-address -f -e %s %lu", info.dli_fname, (unsigned long)ips[i] - (unsigned long)info.dli_fbase); FILE *f = popen(cmd, "r"); if(f) { char func_name[256], file_name[256]; if(fgets(func_name, sizeof(func_name), f) && fgets(file_name, sizeof(file_name), f)) { String8 func = str8_cstring(func_name); if(func.size > 0) func.size -= 1; String8 module = str8_skip_last_slash(str8_cstring(info.dli_fname)); String8 file = str8_skip_last_slash(str8_cstring_capped(file_name, file_name + sizeof(file_name))); if(file.size > 0) file.size -= 1; B32 no_func = str8_match(func, str8_lit("??"), StringMatchFlag_RightSideSloppy); B32 no_file = str8_match(file, str8_lit("??"), StringMatchFlag_RightSideSloppy); if(no_func) { func = str8_zero(); } if(no_file) { file = str8_zero(); } fprintf(stderr, "%ld. [0x%016lx] %.*s%s%.*s %.*s\n", i+1, (unsigned long)ips[i], (int)module.size, module.str, (!no_func || !no_file) ? ", " : "", (int)func.size, func.str, (int)file.size, file.str); } pclose(f); } else { fprintf(stderr, "%ld. [0x%016lx] %s\n", i+1, (unsigned long)ips[i], info.dli_fname); } } fprintf(stderr, "\nVersion: %s%s\n\n", BUILD_VERSION_STRING_LITERAL, BUILD_GIT_HASH_STRING_LITERAL_APPEND); _exit(0); } int main(int argc, char **argv) { // install signal handler for the crash call stacks { struct sigaction handler = { .sa_sigaction = lnx_signal_handler, .sa_flags = SA_SIGINFO, }; sigfillset(&handler.sa_mask); sigaction(SIGILL, &handler, NULL); sigaction(SIGTRAP, &handler, NULL); sigaction(SIGABRT, &handler, NULL); sigaction(SIGFPE, &handler, NULL); sigaction(SIGBUS, &handler, NULL); sigaction(SIGSEGV, &handler, NULL); sigaction(SIGQUIT, &handler, NULL); } //- rjf: set up OS layer { //- rjf: get statically-allocated system/process info { OS_SystemInfo *info = &os_lnx_state.system_info; info->logical_processor_count = (U32)get_nprocs(); info->page_size = (U64)getpagesize(); info->large_page_size = MB(2); info->allocation_granularity = info->page_size; } { OS_ProcessInfo *info = &os_lnx_state.process_info; info->pid = (U32)getpid(); } //- rjf: set up thread context TCTX *tctx = tctx_alloc(); tctx_select(tctx); //- rjf: set up dynamically allocated state os_lnx_state.arena = arena_alloc(); os_lnx_state.entity_arena = arena_alloc(); pthread_mutex_init(&os_lnx_state.entity_mutex, 0); //- rjf: grab dynamically allocated system info { Temp scratch = scratch_begin(0, 0); OS_SystemInfo *info = &os_lnx_state.system_info; // rjf: get machine name B32 got_final_result = 0; U8 *buffer = 0; int size = 0; for(S64 cap = 4096, r = 0; r < 4; cap *= 2, r += 1) { scratch_end(scratch); buffer = push_array(scratch.arena, U8, cap); int gethostname_result = gethostname((char*)buffer, cap); size = cstring8_length(buffer); if(gethostname_result == 0 && size < cap) { got_final_result = 1; break; } } // rjf: save name to info if(got_final_result && size > 0) { info->machine_name.size = size; info->machine_name.str = push_array_no_zero(os_lnx_state.arena, U8, info->machine_name.size + 1); MemoryCopy(info->machine_name.str, buffer, info->machine_name.size); info->machine_name.str[info->machine_name.size] = 0; } scratch_end(scratch); } //- rjf: grab dynamically allocated process info { Temp scratch = scratch_begin(0, 0); OS_ProcessInfo *info = &os_lnx_state.process_info; // rjf: grab binary path { // rjf: get self string B32 got_final_result = 0; U8 *buffer = 0; int size = 0; for(S64 cap = PATH_MAX, r = 0; r < 4; cap *= 2, r += 1) { scratch_end(scratch); buffer = push_array_no_zero(scratch.arena, U8, cap); size = readlink("/proc/self/exe", (char*)buffer, cap); if(size < cap) { got_final_result = 1; break; } } // rjf: save if(got_final_result && size > 0) { String8 full_name = str8(buffer, size); String8 name_chopped = str8_chop_last_slash(full_name); info->binary_path = push_str8_copy(os_lnx_state.arena, name_chopped); } } // rjf: grab initial directory { info->initial_path = os_get_current_path(os_lnx_state.arena); } // rjf: grab home directory { char *home = getenv("HOME"); info->user_program_data_path = str8_cstring(home); } scratch_end(scratch); } } //- rjf: call into "real" entry point main_thread_base_entry_point(argc, argv); } ================================================ FILE: src/os/core/linux/os_core_linux.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_LINUX_H #define OS_CORE_LINUX_H //////////////////////////////// //~ rjf: Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include pid_t gettid(void); int pthread_setname_np(pthread_t thread, const char *name); int pthread_getname_np(pthread_t thread, char *name, size_t size); typedef struct tm tm; typedef struct timespec timespec; //////////////////////////////// //~ rjf: File Iterator typedef struct OS_LNX_FileIter OS_LNX_FileIter; struct OS_LNX_FileIter { DIR *dir; struct dirent *dp; String8 path; }; StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check); //////////////////////////////// //~ rjf: Safe Call Handler Chain typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain; struct OS_LNX_SafeCallChain { OS_LNX_SafeCallChain *next; ThreadEntryPointFunctionType *fail_handler; void *ptr; }; //////////////////////////////// //~ rjf: Entities typedef enum OS_LNX_EntityKind { OS_LNX_EntityKind_Thread, OS_LNX_EntityKind_Mutex, OS_LNX_EntityKind_RWMutex, OS_LNX_EntityKind_ConditionVariable, OS_LNX_EntityKind_Barrier, } OS_LNX_EntityKind; typedef struct OS_LNX_Entity OS_LNX_Entity; struct OS_LNX_Entity { OS_LNX_Entity *next; OS_LNX_EntityKind kind; union { struct { pthread_t handle; ThreadEntryPointFunctionType *func; void *ptr; } thread; pthread_mutex_t mutex_handle; pthread_rwlock_t rwmutex_handle; struct { pthread_cond_t cond_handle; pthread_mutex_t rwlock_mutex_handle; } cv; pthread_barrier_t barrier; }; }; //////////////////////////////// //~ rjf: State typedef struct OS_LNX_State OS_LNX_State; struct OS_LNX_State { Arena *arena; OS_SystemInfo system_info; OS_ProcessInfo process_info; pthread_mutex_t entity_mutex; Arena *entity_arena; OS_LNX_Entity *entity_free; }; //////////////////////////////// //~ rjf: Globals global OS_LNX_State os_lnx_state = {0}; thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0; //////////////////////////////// //~ rjf: Helpers internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec); internal tm os_lnx_tm_from_date_time(DateTime dt); internal timespec os_lnx_timespec_from_date_time(DateTime dt); internal DenseTime os_lnx_dense_time_from_timespec(timespec in); internal FileProperties os_lnx_file_properties_from_stat(struct stat *s); internal void os_lnx_safe_call_sig_handler(int x); //////////////////////////////// //~ rjf: Entities internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind); internal void os_lnx_entity_release(OS_LNX_Entity *entity); //////////////////////////////// //~ rjf: Thread Entry Point internal void *os_lnx_thread_entry_point(void *ptr); #endif // OS_CORE_LINUX_H ================================================ FILE: src/os/core/linux/os_core_linux_old.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include //////////////////////////////// //~ rjf: Globals global pthread_mutex_t lnx_mutex = {0}; global Arena *lnx_perm_arena = 0; global String8List lnx_cmd_line_args = {0}; global LNX_Entity lnx_entity_buffer[1024]; global LNX_Entity *lnx_entity_free = 0; global String8 lnx_initial_path = {0}; thread_static LNX_SafeCallChain *lnx_safe_call_chain = 0; //////////////////////////////// //~ rjf: Helpers internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list){ B32 success = true; String8Node *node = list.first; if (node != 0){ U8 *ptr = node->string.str;; U8 *opl = ptr + node->string.size; U64 p = 0; for (;p < list.total_size;){ U64 amt64 = (U64)(opl - ptr); U32 amt = u32_from_u64_saturate(amt64); S64 written_amt = write(fd, ptr, amt); if (written_amt < 0){ break; } p += written_amt; ptr += written_amt; Assert(ptr <= opl); if (ptr == opl){ node = node->next; if (node == 0){ if (p < list.total_size){ success = false; } break; } ptr = node->string.str; opl = ptr + node->string.size; } } } return(success); } internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec){ out->msec = msec; out->sec = in->tm_sec; out->min = in->tm_min; out->hour = in->tm_hour; out->day = in->tm_mday - 1; out->wday = in->tm_wday; out->mon = in->tm_mon; out->year = in->tm_year + 1900; } internal void lnx_tm_from_date_time(struct tm *out, DateTime *in){ out->tm_sec = in->sec; out->tm_min = in->min; out->tm_hour = in->hour; out->tm_mday = in->day + 1; out->tm_mon = in->mon; out->tm_year = in->year - 1900; } internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in){ struct tm tm_time = {0}; gmtime_r(&in->tv_sec, &tm_time); DateTime date_time = {0}; lnx_date_time_from_tm(&date_time, &tm_time, in->tv_nsec/Million(1)); *out = dense_time_from_date_time(date_time); } internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in){ MemoryZeroStruct(out); out->size = in->st_size; lnx_dense_time_from_timespec(&out->created, &in->st_ctim); lnx_dense_time_from_timespec(&out->modified, &in->st_mtim); if ((in->st_mode & S_IFDIR) != 0){ out->flags |= FilePropertyFlag_IsFolder; } } internal String8 lnx_string_from_signal(int signum){ String8 result = str8_lit(""); switch (signum){ case SIGABRT: { result = str8_lit("SIGABRT"); }break; case SIGALRM: { result = str8_lit("SIGALRM"); }break; case SIGBUS: { result = str8_lit("SIGBUS"); }break; case SIGCHLD: { result = str8_lit("SIGCHLD"); }break; case SIGCONT: { result = str8_lit("SIGCONT"); }break; case SIGFPE: { result = str8_lit("SIGFPE"); }break; case SIGHUP: { result = str8_lit("SIGHUP"); }break; case SIGILL: { result = str8_lit("SIGILL"); }break; case SIGINT: { result = str8_lit("SIGINT"); }break; case SIGIO: { result = str8_lit("SIGIO"); } case SIGKILL: { result = str8_lit("SIGKILL"); }break; case SIGPIPE: { result = str8_lit("SIGPIPE"); }break; case SIGPROF: { result = str8_lit("SIGPROF"); }break; case SIGPWR: { result = str8_lit("SIGPWR"); }break; case SIGQUIT: { result = str8_lit("SIGQUIT"); }break; case SIGSEGV: { result = str8_lit("SIGSEGV"); }break; case SIGSTKFLT: { result = str8_lit("SIGSTKFLT"); }break; case SIGSTOP: { result = str8_lit("SIGSTOP"); }break; case SIGTSTP: { result = str8_lit("SIGTSTP"); }break; case SIGSYS: { result = str8_lit("SIGSYS"); }break; case SIGTERM: { result = str8_lit("SIGTERM"); }break; case SIGTRAP: { result = str8_lit("SIGTRAP"); }break; case SIGTTIN: { result = str8_lit("SIGTTIN"); }break; case SIGTTOU: { result = str8_lit("SIGTTOU"); }break; case SIGURG: { result = str8_lit("SIGURG"); }break; case SIGUSR1: { result = str8_lit("SIGUSR1"); }break; case SIGUSR2: { result = str8_lit("SIGUSR2"); }break; case SIGVTALRM: { result = str8_lit("SIGVTALRM"); }break; case SIGXCPU: { result = str8_lit("SIGXCPU"); }break; case SIGXFSZ: { result = str8_lit("SIGXFSZ"); }break; case SIGWINCH: { result = str8_lit("SIGWINCH"); }break; } return(result); } internal String8 lnx_string_from_errno(int error_number){ String8 result = str8_lit(""); switch (error_number){ case EPERM: { result = str8_lit("EPERM"); }break; case ENOENT: { result = str8_lit("ENOENT"); }break; case ESRCH: { result = str8_lit("ESRCH"); }break; case EINTR: { result = str8_lit("EINTR"); }break; case EIO: { result = str8_lit("EIO"); }break; case ENXIO: { result = str8_lit("ENXIO"); }break; case E2BIG: { result = str8_lit("E2BIG"); }break; case ENOEXEC: { result = str8_lit("ENOEXEC"); }break; case EBADF: { result = str8_lit("EBADF"); }break; case ECHILD: { result = str8_lit("ECHILD"); }break; case EAGAIN: { result = str8_lit("EAGAIN"); }break; case ENOMEM: { result = str8_lit("ENOMEM"); }break; case EACCES: { result = str8_lit("EACCES"); }break; case EFAULT: { result = str8_lit("EFAULT"); }break; case ENOTBLK: { result = str8_lit("ENOTBLK"); }break; case EBUSY: { result = str8_lit("EBUSY"); }break; case EEXIST: { result = str8_lit("EEXIST"); }break; case EXDEV: { result = str8_lit("EXDEV"); }break; case ENODEV: { result = str8_lit("ENODEV"); }break; case ENOTDIR: { result = str8_lit("ENOTDIR"); }break; case EISDIR: { result = str8_lit("EISDIR"); }break; case EINVAL: { result = str8_lit("EINVAL"); }break; case ENFILE: { result = str8_lit("ENFILE"); }break; case EMFILE: { result = str8_lit("EMFILE"); }break; case ENOTTY: { result = str8_lit("ENOTTY"); }break; case ETXTBSY: { result = str8_lit("ETXTBSY"); }break; case EFBIG: { result = str8_lit("EFBIG"); }break; case ENOSPC: { result = str8_lit("ENOSPC"); }break; case ESPIPE: { result = str8_lit("ESPIPE"); }break; case EROFS: { result = str8_lit("EROFS"); }break; case EMLINK: { result = str8_lit("EMLINK"); }break; case EPIPE: { result = str8_lit("EPIPE"); }break; case EDOM: { result = str8_lit("EDOM"); }break; case ERANGE: { result = str8_lit("ERANGE"); }break; case EDEADLK: { result = str8_lit("EDEADLK"); }break; case ENAMETOOLONG: { result = str8_lit("ENAMETOOLONG"); }break; case ENOLCK: { result = str8_lit("ENOLCK"); }break; case ENOSYS: { result = str8_lit("ENOSYS"); }break; case ENOTEMPTY: { result = str8_lit("ENOTEMPTY"); }break; case ELOOP: { result = str8_lit("ELOOP"); }break; case ENOMSG: { result = str8_lit("ENOMSG"); }break; case EIDRM: { result = str8_lit("EIDRM"); }break; case ECHRNG: { result = str8_lit("ECHRNG"); }break; case EL2NSYNC: { result = str8_lit("EL2NSYNC"); }break; case EL3HLT: { result = str8_lit("EL3HLT"); }break; case EL3RST: { result = str8_lit("EL3RST"); }break; case ELNRNG: { result = str8_lit("ELNRNG"); }break; case EUNATCH: { result = str8_lit("EUNATCH"); }break; case ENOCSI: { result = str8_lit("ENOCSI"); }break; case EL2HLT: { result = str8_lit("EL2HLT"); }break; case EBADE: { result = str8_lit("EBADE"); }break; case EBADR: { result = str8_lit("EBADR"); }break; case EXFULL: { result = str8_lit("EXFULL"); }break; case ENOANO: { result = str8_lit("ENOANO"); }break; case EBADRQC: { result = str8_lit("EBADRQC"); }break; case EBADSLT: { result = str8_lit("EBADSLT"); }break; case EBFONT: { result = str8_lit("EBFONT"); }break; case ENOSTR: { result = str8_lit("ENOSTR"); }break; case ENODATA: { result = str8_lit("ENODATA"); }break; case ETIME: { result = str8_lit("ETIME"); }break; case ENOSR: { result = str8_lit("ENOSR"); }break; case ENONET: { result = str8_lit("ENONET"); }break; case ENOPKG: { result = str8_lit("ENOPKG"); }break; case EREMOTE: { result = str8_lit("EREMOTE"); }break; case ENOLINK: { result = str8_lit("ENOLINK"); }break; case EADV: { result = str8_lit("EADV"); }break; case ESRMNT: { result = str8_lit("ESRMNT"); }break; case ECOMM: { result = str8_lit("ECOMM"); }break; case EPROTO: { result = str8_lit("EPROTO"); }break; case EMULTIHOP: { result = str8_lit("EMULTIHOP"); }break; case EDOTDOT: { result = str8_lit("EDOTDOT"); }break; case EBADMSG: { result = str8_lit("EBADMSG"); }break; case EOVERFLOW: { result = str8_lit("EOVERFLOW"); }break; case ENOTUNIQ: { result = str8_lit("ENOTUNIQ"); }break; case EBADFD: { result = str8_lit("EBADFD"); }break; case EREMCHG: { result = str8_lit("EREMCHG"); }break; case ELIBACC: { result = str8_lit("ELIBACC"); }break; case ELIBBAD: { result = str8_lit("ELIBBAD"); }break; case ELIBSCN: { result = str8_lit("ELIBSCN"); }break; case ELIBMAX: { result = str8_lit("ELIBMAX"); }break; case ELIBEXEC: { result = str8_lit("ELIBEXEC"); }break; case EILSEQ: { result = str8_lit("EILSEQ"); }break; case ERESTART: { result = str8_lit("ERESTART"); }break; case ESTRPIPE: { result = str8_lit("ESTRPIPE"); }break; case EUSERS: { result = str8_lit("EUSERS"); }break; case ENOTSOCK: { result = str8_lit("ENOTSOCK"); }break; case EDESTADDRREQ: { result = str8_lit("EDESTADDRREQ"); }break; case EMSGSIZE: { result = str8_lit("EMSGSIZE"); }break; case EPROTOTYPE: { result = str8_lit("EPROTOTYPE"); }break; case ENOPROTOOPT: { result = str8_lit("ENOPROTOOPT"); }break; case EPROTONOSUPPORT: { result = str8_lit("EPROTONOSUPPORT"); }break; case ESOCKTNOSUPPORT: { result = str8_lit("ESOCKTNOSUPPORT"); }break; case EOPNOTSUPP: { result = str8_lit("EOPNOTSUPP"); }break; case EPFNOSUPPORT: { result = str8_lit("EPFNOSUPPORT"); }break; case EAFNOSUPPORT: { result = str8_lit("EAFNOSUPPORT"); }break; case EADDRINUSE: { result = str8_lit("EADDRINUSE"); }break; case EADDRNOTAVAIL: { result = str8_lit("EADDRNOTAVAIL"); }break; case ENETDOWN: { result = str8_lit("ENETDOWN"); }break; case ENETUNREACH: { result = str8_lit("ENETUNREACH"); }break; case ENETRESET: { result = str8_lit("ENETRESET"); }break; case ECONNABORTED: { result = str8_lit("ECONNABORTED"); }break; case ECONNRESET: { result = str8_lit("ECONNRESET"); }break; case ENOBUFS: { result = str8_lit("ENOBUFS"); }break; case EISCONN: { result = str8_lit("EISCONN"); }break; case ENOTCONN: { result = str8_lit("ENOTCONN"); }break; case ESHUTDOWN: { result = str8_lit("ESHUTDOWN"); }break; case ETOOMANYREFS: { result = str8_lit("ETOOMANYREFS"); }break; case ETIMEDOUT: { result = str8_lit("ETIMEDOUT"); }break; case ECONNREFUSED: { result = str8_lit("ECONNREFUSED"); }break; case EHOSTDOWN: { result = str8_lit("EHOSTDOWN"); }break; case EHOSTUNREACH: { result = str8_lit("EHOSTUNREACH"); }break; case EALREADY: { result = str8_lit("EALREADY"); }break; case EINPROGRESS: { result = str8_lit("EINPROGRESS"); }break; case ESTALE: { result = str8_lit("ESTALE"); }break; case EUCLEAN: { result = str8_lit("EUCLEAN"); }break; case ENOTNAM: { result = str8_lit("ENOTNAM"); }break; case ENAVAIL: { result = str8_lit("ENAVAIL"); }break; case EISNAM: { result = str8_lit("EISNAM"); }break; case EREMOTEIO: { result = str8_lit("EREMOTEIO"); }break; case EDQUOT: { result = str8_lit("EDQUOT"); }break; case ENOMEDIUM: { result = str8_lit("ENOMEDIUM"); }break; case EMEDIUMTYPE: { result = str8_lit("EMEDIUMTYPE"); }break; case ECANCELED: { result = str8_lit("ECANCELED"); }break; case ENOKEY: { result = str8_lit("ENOKEY"); }break; case EKEYEXPIRED: { result = str8_lit("EKEYEXPIRED"); }break; case EKEYREVOKED: { result = str8_lit("EKEYREVOKED"); }break; case EKEYREJECTED: { result = str8_lit("EKEYREJECTED"); }break; case EOWNERDEAD: { result = str8_lit("EOWNERDEAD"); }break; case ENOTRECOVERABLE: { result = str8_lit("ENOTRECOVERABLE"); }break; case ERFKILL: { result = str8_lit("ERFKILL"); }break; case EHWPOISON: { result = str8_lit("EHWPOISON"); }break; } return(result); } internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind){ pthread_mutex_lock(&lnx_mutex); LNX_Entity *result = lnx_entity_free; Assert(result != 0); SLLStackPop(lnx_entity_free); pthread_mutex_unlock(&lnx_mutex); result->kind = kind; return(result); } internal void lnx_free_entity(LNX_Entity *entity){ entity->kind = LNX_EntityKind_Null; pthread_mutex_lock(&lnx_mutex); SLLStackPush(lnx_entity_free, entity); pthread_mutex_unlock(&lnx_mutex); } internal void* lnx_thread_base(void *ptr){ LNX_Entity *entity = (LNX_Entity*)ptr; ThreadEntryPointFunctionType *func = entity->thread.func; void *thread_ptr = entity->thread.ptr; TCTX tctx_; tctx_init_and_equip(&tctx_); func(thread_ptr); tctx_release(); // remove my bit U32 result = __sync_fetch_and_and(&entity->reference_mask, ~0x2); // if the other bit is also gone, free entity if ((result & 0x1) == 0){ lnx_free_entity(entity); } return(0); } internal void lnx_safe_call_sig_handler(int){ LNX_SafeCallChain *chain = lnx_safe_call_chain; if (chain != 0 && chain->fail_handler != 0){ chain->fail_handler(chain->ptr); } abort(); } //////////////////////////////// //~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) internal void os_init(void) { // NOTE(allen): Initialize linux layer mutex { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); int pthread_result = pthread_mutex_init(&lnx_mutex, &attr); pthread_mutexattr_destroy(&attr); if (pthread_result == -1){ abort(); } } MemoryZeroArray(lnx_entity_buffer); { LNX_Entity *ptr = lnx_entity_free = lnx_entity_buffer; for (U64 i = 1; i < ArrayCount(lnx_entity_buffer); i += 1, ptr += 1){ ptr->next = ptr + 1; } ptr->next = 0; } // NOTE(allen): Permanent memory allocator for this layer Arena *perm_arena = arena_alloc(); lnx_perm_arena = perm_arena; // NOTE(allen): Initialize Paths lnx_initial_path = os_get_path(lnx_perm_arena, OS_SystemPath_Current); // NOTE(rjf): Setup command line args lnx_cmd_line_args = os_string_list_from_argcv(lnx_perm_arena, argc, argv); } //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) internal void* os_reserve(U64 size){ void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); return(result); } internal B32 os_commit(void *ptr, U64 size){ mprotect(ptr, size, PROT_READ|PROT_WRITE); // TODO(allen): can we test this? return(true); } internal void* os_reserve_large(U64 size){ NotImplemented; return 0; } internal B32 os_commit_large(void *ptr, U64 size){ NotImplemented; return 0; } internal void os_decommit(void *ptr, U64 size){ madvise(ptr, size, MADV_DONTNEED); mprotect(ptr, size, PROT_NONE); } internal void os_release(void *ptr, U64 size){ munmap(ptr, size); } internal void os_set_large_pages_enabled(B32 flag) { NotImplemented; } internal B32 os_large_pages_enabled(void) { NotImplemented; return 0; } internal U64 os_large_page_size(void) { NotImplemented; return 0; } //////////////////////////////// //~ rjf: @os_hooks System Info (Implemented Per-OS) internal String8 os_machine_name(void){ local_persist B32 first = true; local_persist String8 name = {0}; // TODO(allen): let's just pre-compute this at init and skip the complexity pthread_mutex_lock(&lnx_mutex); if (first){ Temp scratch = scratch_begin(0, 0); first = false; // get name B32 got_final_result = false; U8 *buffer = 0; int size = 0; for (S64 cap = 4096, r = 0; r < 4; cap *= 2, r += 1){ scratch.restore(); buffer = push_array_no_zero(scratch.arena, U8, cap); size = gethostname((char*)buffer, cap); if (size < cap){ got_final_result = true; break; } } // save string if (got_final_result && size > 0){ name.size = size; name.str = push_array_no_zero(lnx_perm_arena, U8, name.size + 1); MemoryCopy(name.str, buffer, name.size); name.str[name.size] = 0; } scratch_end(scratch); } pthread_mutex_unlock(&lnx_mutex); return(name); } internal U64 os_page_size(void){ int size = getpagesize(); return((U64)size); } internal U64 os_allocation_granularity(void) { // On linux there is no equivalent of "dwAllocationGranularity" os_page_size(); } internal U64 os_logical_core_count(void) { // TODO(rjf): check this return get_nprocs(); } //////////////////////////////// //~ rjf: @os_hooks Process & Thread Info (Implemented Per-OS) internal String8List os_get_command_line_arguments(void) { return lnx_cmd_line_args; } internal S32 os_pid(void){ S32 result = getpid(); return(result); } internal S32 os_tid(void){ S32 result = 0; #ifdef SYS_gettid result = syscall(SYS_gettid); #else result = gettid(); #endif return(result); } internal String8List os_environment(void) { NotImplemented; String8List result = {0}; return result; } internal U64 os_string_list_from_system_path(Arena *arena, OS_SystemPath path, String8List *out){ U64 result = 0; switch (path){ case OS_SystemPath_Binary: { local_persist B32 first = true; local_persist String8 name = {0}; // TODO(allen): let's just pre-compute this at init and skip the complexity pthread_mutex_lock(&lnx_mutex); if (first){ Temp scratch = scratch_begin(&arena, 1); first = false; // get self string B32 got_final_result = false; U8 *buffer = 0; int size = 0; for (S64 cap = PATH_MAX, r = 0; r < 4; cap *= 2, r += 1){ scratch.restore(); buffer = push_array_no_zero(scratch.arena, U8, cap); size = readlink("/proc/self/exe", (char*)buffer, cap); if (size < cap){ got_final_result = true; break; } } // save string if (got_final_result && size > 0){ String8 full_name = str8(buffer, size); String8 name_chopped = string_path_chop_last_slash(full_name); name = push_str8_copy(lnx_perm_arena, name_chopped); } scratch_end(scratch); } pthread_mutex_unlock(&lnx_mutex); result = 1; str8_list_push(arena, out, name); }break; case OS_SystemPath_Initial: { Assert(lnx_initial_path.str != 0); result = 1; str8_list_push(arena, out, lnx_initial_path); }break; case OS_SystemPath_Current: { char *cwdir = getcwd(0, 0); String8 string = push_str8_copy(arena, str8_cstring(cwdir)); free(cwdir); result = 1; str8_list_push(arena, out, string); }break; case OS_SystemPath_UserProgramData: { char *home = getenv("HOME"); String8 string = str8_cstring(home); result = 1; str8_list_push(arena, out, string); }break; case OS_SystemPath_ModuleLoad: { // TODO(allen): this one is big and complicated and only needed for making // a debugger, skipping for now. NotImplemented; }break; } return(result); } //////////////////////////////// //~ rjf: @os_hooks Process Control (Implemented Per-OS) internal void os_abort(S32 exit_code){ exit(exit_code); } //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { OS_Handle file = {0}; NotImplemented; return file; } internal void os_file_close(OS_Handle file) { NotImplemented; } internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) { NotImplemented; return 0; } internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data) { NotImplemented; } internal B32 os_file_set_times(OS_Handle file, DateTime time) { NotImplemented; } internal FileProperties os_properties_from_file(OS_Handle file) { FileProperties props = {0}; NotImplemented; return props; } internal OS_FileID os_id_from_file(OS_Handle file) { // TODO(nick): querry struct stat with fstat(2) and use st_dev and st_ino as ids OS_FileID id = {0}; NotImplemented; return id; } internal B32 os_delete_file_at_path(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = false; String8 name_copy = push_str8_copy(scratch.arena, name); if (remove((char*)name_copy.str) != -1){ result = true; } scratch_end(scratch); return(result); } internal B32 os_copy_file_path(String8 dst, String8 src) { NotImplemented; return 0; } internal String8 os_full_path_from_path(Arena *arena, String8 path) { // TODO: realpath can be used to resolve full path String8 result = {0}; NotImplemented; return result; } internal B32 os_file_path_exists(String8 path) { NotImplemented; return 0; } internal FileProperties os_properties_from_file_path(String8 path) { FileProperties props = {0}; NotImplemented; return props; } //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file) { NotImplemented; OS_Handle handle = {0}; return handle; } internal void os_file_map_close(OS_Handle map) { NotImplemented; } internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) { NotImplemented; return 0; } internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) { NotImplemented; } //- rjf: directory iteration internal OS_FileIter * os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) { NotImplemented; return 0; } internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { NotImplemented; return 0; } internal void os_file_iter_end(OS_FileIter *iter) { NotImplemented; } //- rjf: directory creation internal B32 os_make_directory(String8 path) { Temp scratch = scratch_begin(0, 0); B32 result = false; String8 name_copy = push_str8_copy(scratch.arena, name); if (mkdir((char*)name_copy.str, 0777) != -1){ result = true; } scratch_end(scratch); return(result); } //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name) { OS_Handle result = {0}; NotImplemented; return result; } internal OS_Handle os_shared_memory_open(String8 name) { OS_Handle result = {0}; NotImplemented; return result; } internal void os_shared_memory_close(OS_Handle handle) { NotImplemented; } internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) { NotImplemented; return 0; } internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) { NotImplemented; } //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U32 os_now_unix(void) { time_t t = time(0); return (U32)t; } internal DateTime os_now_universal_time(void){ time_t t = 0; time(&t); struct tm universal_tm = {0}; gmtime_r(&t, &universal_tm); DateTime result = {0}; lnx_date_time_from_tm(&result, &universal_tm, 0); return(result); } internal DateTime os_universal_time_from_local(DateTime *local_time){ // local time -> universal time (using whatever types it takes) struct tm local_tm = {0}; lnx_tm_from_date_time(&local_tm, local_time); local_tm.tm_isdst = -1; time_t universal_t = mktime(&local_tm); // whatever type we ended up with -> DateTime (don't alter the space along the way) struct tm universal_tm = {0}; gmtime_r(&universal_t, &universal_tm); DateTime result = {0}; lnx_date_time_from_tm(&result, &universal_tm, 0); return(result); } internal DateTime os_local_time_from_universal(DateTime *universal_time){ // universal time -> local time (using whatever types it takes) struct tm universal_tm = {0}; lnx_tm_from_date_time(&universal_tm, universal_time); universal_tm.tm_isdst = -1; time_t universal_t = timegm(&universal_tm); struct tm local_tm = {0}; localtime_r(&universal_t, &local_tm); // whatever type we ended up with -> DateTime (don't alter the space along the way) DateTime result = {0}; lnx_date_time_from_tm(&result, &local_tm, 0); return(result); } internal U64 os_now_microseconds(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); U64 result = t.tv_sec*Million(1) + (t.tv_nsec/Thousand(1)); return(result); } internal void os_sleep_milliseconds(U32 msec){ usleep(msec*Thousand(1)); } //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal B32 os_launch_process(OS_LaunchOptions *options){ // TODO(allen): I want to redo this API before I bother implementing it here NotImplemented; return(false); } //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal OS_Handle os_thread_launch(ThreadEntryPointFunctionType *func, void *ptr, void *params){ // entity LNX_Entity *entity = lnx_alloc_entity(LNX_EntityKind_Thread); entity->reference_mask = 0x3; entity->thread.func = func; entity->thread.ptr = ptr; // pthread pthread_attr_t attr; pthread_attr_init(&attr); int pthread_result = pthread_create(&entity->thread.handle, &attr, lnx_thread_base, entity); pthread_attr_destroy(&attr); if (pthread_result == -1){ lnx_free_entity(entity); entity = 0; } // cast to opaque handle OS_Handle result = {IntFromPtr(entity)}; return(result); } internal void os_release_thread_handle(OS_Handle thread){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(thread.id); // remove my bit U32 result = __sync_fetch_and_and(&entity->reference_mask, ~0x1); // if the other bit is also gone, free entity if ((result & 0x2) == 0){ lnx_free_entity(entity); } } //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) // NOTE(allen): Mutexes are recursive - support counted acquire/release nesting // on a single thread //- rjf: recursive mutexes internal OS_Handle os_mutex_alloc(void){ // entity LNX_Entity *entity = lnx_alloc_entity(LNX_EntityKind_Mutex); // pthread pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); int pthread_result = pthread_mutex_init(&entity->mutex, &attr); pthread_mutexattr_destroy(&attr); if (pthread_result == -1){ lnx_free_entity(entity); entity = 0; } // cast to opaque handle OS_Handle result = {IntFromPtr(entity)}; return(result); } internal void os_mutex_release(OS_Handle mutex){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(mutex.id); pthread_mutex_destroy(&entity->mutex); lnx_free_entity(entity); } internal void os_mutex_take_(OS_Handle mutex){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(mutex.id); pthread_mutex_lock(&entity->mutex); } internal void os_mutex_drop_(OS_Handle mutex){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(mutex.id); pthread_mutex_unlock(&entity->mutex); } //- rjf: reader/writer mutexes internal OS_Handle os_rw_mutex_alloc(void) { OS_Handle result = {0}; NotImplemented; return result; } internal void os_rw_mutex_release(OS_Handle rw_mutex) { NotImplemented; } internal void os_rw_mutex_take_r_(OS_Handle mutex) { NotImplemented; } internal void os_rw_mutex_drop_r_(OS_Handle mutex) { NotImplemented; } internal void os_rw_mutex_take_w_(OS_Handle mutex) { NotImplemented; } internal void os_rw_mutex_drop_w_(OS_Handle mutex) { NotImplemented; } //- rjf: condition variables internal OS_Handle os_cond_var_alloc(void){ // entity LNX_Entity *entity = lnx_alloc_entity(LNX_EntityKind_ConditionVariable); // pthread pthread_condattr_t attr; pthread_condattr_init(&attr); int pthread_result = pthread_cond_init(&entity->cond, &attr); pthread_condattr_destroy(&attr); if (pthread_result == -1){ lnx_free_entity(entity); entity = 0; } // cast to opaque handle OS_Handle result = {IntFromPtr(entity)}; return(result); } internal void os_cond_var_release(OS_Handle cv){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(cv.id); pthread_cond_destroy(&entity->cond); lnx_free_entity(entity); } internal B32 os_condition_variable_wait_(OS_Handle cv, OS_Handle mutex, U64 endt_us){ B32 result = false; LNX_Entity *entity_cond = (LNX_Entity*)PtrFromInt(cv.id); LNX_Entity *entity_mutex = (LNX_Entity*)PtrFromInt(mutex.id); // TODO(allen): implement the time control pthread_cond_timedwait(&entity_cond->cond, &entity_mutex->mutex); return(result); } internal B32 os_condition_variable_wait_rw_r_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { NotImplemented; return 0; } internal B32 os_condition_variable_wait_rw_w_(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { NotImplemented; return 0; } internal void os_condition_variable_signal_(OS_Handle cv){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(cv.id); pthread_cond_signal(&entity->cond); } internal void os_condition_variable_broadcast_(OS_Handle cv){ LNX_Entity *entity = (LNX_Entity*)PtrFromInt(cv.id); DontCompile; } //- rjf: cross-process semaphores internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { OS_Handle result = {0}; NotImplemented; return result; } internal void os_semaphore_release(OS_Handle semaphore) { NotImplemented; } internal OS_Handle os_semaphore_open(String8 name) { OS_Handle result = {0}; NotImplemented; return result; } internal void os_semaphore_close(OS_Handle semaphore) { NotImplemented; } internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us) { NotImplemented; return 0; } internal void os_semaphore_drop(OS_Handle semaphore) { NotImplemented; } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); char *path_cstr = (char *)push_str8_copy(scratch.arena, path).str; void *so = dlopen(path_cstr, RTLD_LAZY); OS_Handle lib = { (U64)so }; scratch_end(scratch); return lib; } internal VoidProc * os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); void *so = (void *)lib.id; char *name_cstr = (char *)push_str8_copy(scratch.arena, name).str; VoidProc *proc = (VoidProc *)dlsym(so, name_cstr); scratch_end(scratch); return proc; } internal void os_library_close(OS_Handle lib) { void *so = (void *)lib.id; dlclose(so); } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal void os_safe_call(ThreadEntryPointFunctionType *func, ThreadEntryPointFunctionType *fail_handler, void *ptr){ LNX_SafeCallChain chain = {0}; SLLStackPush(lnx_safe_call_chain, &chain); chain.fail_handler = fail_handler; chain.ptr = ptr; struct sigaction new_act = {0}; new_act.sa_handler = lnx_safe_call_sig_handler; int signals_to_handle[] = { SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, }; struct sigaction og_act[ArrayCount(signals_to_handle)] = {0}; for (U32 i = 0; i < ArrayCount(signals_to_handle); i += 1){ sigaction(signals_to_handle[i], &new_act, &og_act[i]); } func(ptr); for (U32 i = 0; i < ArrayCount(signals_to_handle); i += 1){ sigaction(signals_to_handle[i], &og_act[i], 0); } } //////////////////////////////// internal OS_Guid os_make_guid(void) { NotImplemented; } ================================================ FILE: src/os/core/linux/os_core_linux_old.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef LINUX_H #define LINUX_H //////////////////////////////// //~ NOTE(allen): Get all these linux includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////// //~ NOTE(allen): File Iterator struct LNX_FileIter{ int fd; DIR *dir; }; StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(LNX_FileIter), file_iter_memory_size); //////////////////////////////// //~ NOTE(allen): Threading Entities enum LNX_EntityKind{ LNX_EntityKind_Null, LNX_EntityKind_Thread, LNX_EntityKind_Mutex, LNX_EntityKind_ConditionVariable, }; struct LNX_Entity{ LNX_Entity *next; LNX_EntityKind kind; volatile U32 reference_mask; union{ struct{ ThreadEntryPointFunctionType *func; void *ptr; pthread_t handle; } thread; pthread_mutex_t mutex; pthread_cond_t cond; }; }; //////////////////////////////// //~ NOTE(allen): Safe Call Chain struct LNX_SafeCallChain{ LNX_SafeCallChain *next; ThreadEntryPointFunctionType *fail_handler; void *ptr; }; //////////////////////////////// //~ NOTE(allen): Helpers internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list); internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec); internal void lnx_tm_from_date_time(struct tm *out, DateTime *in); internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in); internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in); internal String8 lnx_string_from_signal(int signum); internal String8 lnx_string_from_errno(int error_number); internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind); internal void lnx_free_entity(LNX_Entity *entity); internal void* lnx_thread_base(void *ptr); internal void lnx_safe_call_sig_handler(int); #endif //LINUX_H ================================================ FILE: src/os/core/os_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Handle Type Functions (Helpers, Implemented Once) internal OS_Handle os_handle_zero(void) { OS_Handle handle = {0}; return handle; } internal B32 os_handle_match(OS_Handle a, OS_Handle b) { return a.u64[0] == b.u64[0]; } internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle) { OS_HandleNode *n = push_array(arena, OS_HandleNode, 1); n->v = handle; SLLQueuePush(handles->first, handles->last, n); handles->count += 1; } internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list) { OS_HandleArray result = {0}; result.count = list->count; result.v = push_array_no_zero(arena, OS_Handle, result.count); U64 idx = 0; for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1) { result.v[idx] = n->v; } return result; } //////////////////////////////// //~ rjf: Filesystem Helpers (Helpers, Implemented Once) internal String8 os_data_from_file_path(Arena *arena, String8 path) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); FileProperties props = os_properties_from_file(file); String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size)); os_file_close(file); return data; } internal B32 os_write_data_to_file_path(String8 path, String8 data) { B32 good = 0; OS_Handle file = os_file_open(OS_AccessFlag_Write, path); if(!os_handle_match(file, os_handle_zero())) { U64 bytes_written = os_file_write(file, r1u64(0, data.size), data.str); good = (bytes_written == data.size); os_file_close(file); } return good; } internal B32 os_write_data_list_to_file_path(String8 path, String8List list) { B32 good = 0; OS_Handle file = os_file_open(OS_AccessFlag_Write, path); if(!os_handle_match(file, os_handle_zero())) { Temp scratch = scratch_begin(0, 0); U64 write_buffer_size = KB(64); U8 *write_buffer = push_array_no_zero(scratch.arena, U8, write_buffer_size); U64 write_buffer_write_pos = 0; U64 write_buffer_read_pos = 0; U64 file_off = 0; { for(String8Node *n = list.first; n != 0; n = n->next) { for(U64 n_off = 0; n_off < n->string.size;) { U64 write_buffer_unconsumed_size = (write_buffer_write_pos - write_buffer_read_pos); U64 write_buffer_available_size = (write_buffer_size - write_buffer_unconsumed_size); if(write_buffer_available_size == 0) { U64 file_write_size = os_file_write(file, r1u64(file_off, file_off+write_buffer_size), write_buffer); if(file_write_size != write_buffer_size) { goto dbl_break; } file_off += write_buffer_size; write_buffer_read_pos += write_buffer_size; } else { U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off); write_buffer_write_pos += ring_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy); n_off += bytes_to_copy; } } } if(write_buffer_write_pos > write_buffer_read_pos) { U64 file_write_size = os_file_write(file, r1u64(file_off, file_off + (write_buffer_write_pos-write_buffer_read_pos)), write_buffer); file_off += file_write_size; } } dbl_break:; good = (file_off == list.total_size); os_file_close(file); scratch_end(scratch); } return good; } internal B32 os_append_data_to_file_path(String8 path, String8 data) { B32 good = 0; if(data.size != 0) { OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path); if(!os_handle_match(file, os_handle_zero())) { U64 pos = os_properties_from_file(file).size; U64 bytes_written = os_file_write(file, r1u64(pos, pos+data.size), data.str); good = (bytes_written == data.size); os_file_close(file); } } return good; } internal OS_FileID os_id_from_file_path(String8 path) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); OS_FileID id = os_id_from_file(file); os_file_close(file); return id; } internal S64 os_file_id_compare(OS_FileID a, OS_FileID b) { S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v)); return cmp; } internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range) { U64 pre_pos = arena_pos(arena); String8 result; result.size = dim_1u64(range); result.str = push_array_no_zero(arena, U8, result.size); U64 actual_read_size = os_file_read(file, range, result.str); if(actual_read_size < result.size) { arena_pop_to(arena, pre_pos + actual_read_size); result.size = actual_read_size; } return result; } internal String8 os_file_read_cstring(Arena *arena, OS_Handle file, U64 off) { Temp scratch = scratch_begin(&arena, 1); String8List block_list = {0}; for(U64 cursor = off, stride = 256;; cursor += stride) { U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride); U64 read_size = os_file_read(file, r1u64(cursor, cursor + stride), raw_block); String8 block = str8_cstring_capped(raw_block, raw_block+read_size); str8_list_push(scratch.arena, &block_list, block); if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0)) { break; } } String8 result = str8_list_join(arena, &block_list, 0); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Process Launcher Helpers internal OS_Handle os_cmd_line_launch(String8 string) { Temp scratch = scratch_begin(0, 0); U8 split_chars[] = {' '}; String8List parts = str8_split(scratch.arena, string, split_chars, ArrayCount(split_chars), 0); OS_Handle handle = {0}; if(parts.node_count != 0) { // rjf: unpack exe part String8 exe = parts.first->string; String8 exe_folder = str8_chop_last_slash(exe); if(exe_folder.size == 0) { exe_folder = os_get_current_path(scratch.arena); } // rjf: find stdout delimiter String8Node *stdout_delimiter_n = 0; for(String8Node *n = parts.first; n != 0; n = n->next) { if(str8_match(n->string, str8_lit(">"), 0)) { stdout_delimiter_n = n; break; } } // rjf: read stdout path String8 stdout_path = {0}; if(stdout_delimiter_n && stdout_delimiter_n->next) { stdout_path = stdout_delimiter_n->next->string; } // rjf: open stdout handle OS_Handle stdout_handle = {0}; if(stdout_path.size != 0) { OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path); os_file_close(file); stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path); } // rjf: form command line String8List cmdline = {0}; for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next) { str8_list_push(scratch.arena, &cmdline, n->string); } // rjf: launch OS_ProcessLaunchParams params = {0}; params.cmd_line = cmdline; params.path = exe_folder; params.inherit_env = 1; params.stdout_file = stdout_handle; handle = os_process_launch(¶ms); // rjf: close stdout handle { if(stdout_path.size != 0) { os_file_close(stdout_handle); } } } scratch_end(scratch); return handle; } internal OS_Handle os_cmd_line_launchf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); OS_Handle result = os_cmd_line_launch(string); va_end(args); scratch_end(scratch); return result; } ================================================ FILE: src/os/core/os_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_H #define OS_CORE_H //////////////////////////////// //~ rjf: System Info typedef struct OS_SystemInfo OS_SystemInfo; struct OS_SystemInfo { U32 logical_processor_count; U64 page_size; U64 large_page_size; U64 allocation_granularity; String8 machine_name; }; //////////////////////////////// //~ rjf: Process Info typedef struct OS_ProcessInfo OS_ProcessInfo; struct OS_ProcessInfo { U32 pid; B32 large_pages_allowed; String8 binary_path; String8 initial_path; String8 user_program_data_path; String8List module_load_paths; String8List environment; }; //////////////////////////////// //~ rjf: Access Flags typedef U32 OS_AccessFlags; enum { OS_AccessFlag_Read = (1<<0), OS_AccessFlag_Write = (1<<1), OS_AccessFlag_Execute = (1<<2), OS_AccessFlag_Append = (1<<3), OS_AccessFlag_ShareRead = (1<<4), OS_AccessFlag_ShareWrite = (1<<5), OS_AccessFlag_Inherited = (1<<6), }; //////////////////////////////// //~ rjf: Files typedef U32 OS_FileIterFlags; enum { OS_FileIterFlag_SkipFolders = (1 << 0), OS_FileIterFlag_SkipFiles = (1 << 1), OS_FileIterFlag_SkipHiddenFiles = (1 << 2), OS_FileIterFlag_Done = (1 << 31), }; typedef struct OS_FileIter OS_FileIter; struct OS_FileIter { OS_FileIterFlags flags; U8 memory[800]; }; typedef struct OS_FileInfo OS_FileInfo; struct OS_FileInfo { String8 name; FileProperties props; }; // nick: on-disk file identifier typedef struct OS_FileID OS_FileID; struct OS_FileID { U64 v[3]; }; //////////////////////////////// //~ rjf: Handle Type typedef struct OS_Handle OS_Handle; struct OS_Handle { U64 u64[1]; }; typedef struct OS_HandleNode OS_HandleNode; struct OS_HandleNode { OS_HandleNode *next; OS_Handle v; }; typedef struct OS_HandleList OS_HandleList; struct OS_HandleList { OS_HandleNode *first; OS_HandleNode *last; U64 count; }; typedef struct OS_HandleArray OS_HandleArray; struct OS_HandleArray { OS_Handle *v; U64 count; }; //////////////////////////////// //~ rjf: Process Launch Parameters typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams; struct OS_ProcessLaunchParams { String8List cmd_line; String8 path; String8List env; B32 inherit_env; B32 debug_subprocesses; B32 consoleless; OS_Handle stdout_file; OS_Handle stderr_file; OS_Handle stdin_file; }; //////////////////////////////// //~ rjf: Handle Type Functions (Helpers, Implemented Once) internal OS_Handle os_handle_zero(void); internal B32 os_handle_match(OS_Handle a, OS_Handle b); internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle); internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list); //////////////////////////////// //~ rjf: Filesystem Helpers (Helpers, Implemented Once) internal String8 os_data_from_file_path(Arena *arena, String8 path); internal B32 os_write_data_to_file_path(String8 path, String8 data); internal B32 os_write_data_list_to_file_path(String8 path, String8List list); internal B32 os_append_data_to_file_path(String8 path, String8 data); internal OS_FileID os_id_from_file_path(String8 path); internal S64 os_file_id_compare(OS_FileID a, OS_FileID b); internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range); internal String8 os_file_read_cstring(Arena *arena, OS_Handle file, U64 off); //////////////////////////////// //~ rjf: Process Launcher Helpers internal OS_Handle os_cmd_line_launch(String8 string); internal OS_Handle os_cmd_line_launchf(char *fmt, ...); //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo *os_get_system_info(void); internal OS_ProcessInfo *os_get_process_info(void); internal String8 os_get_current_path(Arena *arena); internal U32 os_get_process_start_time_unix(void); //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void *os_reserve(U64 size); internal B32 os_commit(void *ptr, U64 size); internal void os_decommit(void *ptr, U64 size); internal void os_release(void *ptr, U64 size); //- rjf: large pages internal void *os_reserve_large(U64 size); internal B32 os_commit_large(void *ptr, U64 size); //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void); internal void os_set_thread_name(String8 string); //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code); //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path); internal void os_file_close(OS_Handle file); internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data); #define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr)) internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data); internal B32 os_file_set_times(OS_Handle file, DateTime time); internal FileProperties os_properties_from_file(OS_Handle file); internal OS_FileID os_id_from_file(OS_Handle file); internal B32 os_file_reserve_size(OS_Handle file, U64 size); internal B32 os_delete_file_at_path(String8 path); internal B32 os_copy_file_path(String8 dst, String8 src); internal B32 os_move_file_path(String8 dst, String8 src); internal String8 os_full_path_from_path(Arena *arena, String8 path); internal B32 os_file_path_exists(String8 path); internal B32 os_folder_path_exists(String8 path); internal FileProperties os_properties_from_file_path(String8 path); //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file); internal void os_file_map_close(OS_Handle map); internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range); internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range); //- rjf: directory iteration internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags); internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out); internal void os_file_iter_end(OS_FileIter *iter); //- rjf: directory creation internal B32 os_make_directory(String8 path); //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name); internal OS_Handle os_shared_memory_open(String8 name); internal void os_shared_memory_close(OS_Handle handle); internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range); internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range); //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void); internal U32 os_now_unix(void); internal DateTime os_now_universal_time(void); internal DateTime os_universal_time_from_local(DateTime *local_time); internal DateTime os_local_time_from_universal(DateTime *universal_time); internal void os_sleep_milliseconds(U32 msec); //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params); internal B32 os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out); internal void os_process_detach(OS_Handle handle); internal B32 os_process_kill(OS_Handle handle); //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal Thread os_thread_launch(ThreadEntryPointFunctionType *f, void *p); internal B32 os_thread_join(Thread handle, U64 endt_us); internal void os_thread_detach(Thread handle); //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: recursive mutexes internal Mutex os_mutex_alloc(void); internal void os_mutex_release(Mutex mutex); internal void os_mutex_take(Mutex mutex); internal void os_mutex_drop(Mutex mutex); //- rjf: reader/writer mutexes internal RWMutex os_rw_mutex_alloc(void); internal void os_rw_mutex_release(RWMutex mutex); internal void os_rw_mutex_take(RWMutex mutex, B32 write_mode); internal void os_rw_mutex_drop(RWMutex mutex, B32 write_mode); //- rjf: condition variables internal CondVar os_cond_var_alloc(void); internal void os_cond_var_release(CondVar cv); // returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout internal B32 os_cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us); internal B32 os_cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us); internal void os_cond_var_signal(CondVar cv); internal void os_cond_var_broadcast(CondVar cv); //- rjf: cross-process semaphores internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name); internal void os_semaphore_release(Semaphore semaphore); internal Semaphore os_semaphore_open(String8 name); internal void os_semaphore_close(Semaphore semaphore); internal B32 os_semaphore_take(Semaphore semaphore, U64 endt_us); internal void os_semaphore_drop(Semaphore semaphore); //- rjf: barriers internal Barrier os_barrier_alloc(U64 count); internal void os_barrier_release(Barrier barrier); internal void os_barrier_wait(Barrier barrier); //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path); internal void os_library_close(OS_Handle lib); internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name); //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(ThreadEntryPointFunctionType *func, ThreadEntryPointFunctionType *fail_handler, void *ptr); //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void); //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) // NOTE(rjf): The implementation of `os_core` will define low-level entry // points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call // into the standard codebase program entry points, named "entry_point". #if BUILD_ENTRY_DEFINING_UNIT raddbg_entry_point(entry_point); internal no_inline void entry_point(CmdLine *cmdline); #endif #endif // OS_CORE_H ================================================ FILE: src/os/core/win32/os_core_win32.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Modern Windows SDK Functions // // (We must dynamically link to them, since they can be missing in older SDKs) typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); global W32_SetThreadDescription_Type *w32_SetThreadDescription_func = 0; global RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {0}; //////////////////////////////// //~ rjf: File Info Conversion Helpers internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes) { FilePropertyFlags flags = 0; if(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { flags |= FilePropertyFlag_IsFolder; } return flags; } internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes) { properties->size = Compose64Bit(attributes->nFileSizeHigh, attributes->nFileSizeLow); os_w32_dense_time_from_file_time(&properties->created, &attributes->ftCreationTime); os_w32_dense_time_from_file_time(&properties->modified, &attributes->ftLastWriteTime); properties->flags = os_w32_file_property_flags_from_dwFileAttributes(attributes->dwFileAttributes); } //////////////////////////////// //~ rjf: Time Conversion Helpers internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in) { out->year = in->wYear; out->mon = in->wMonth - 1; out->wday = in->wDayOfWeek; out->day = in->wDay; out->hour = in->wHour; out->min = in->wMinute; out->sec = in->wSecond; out->msec = in->wMilliseconds; } internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in) { out->wYear = (WORD)(in->year); out->wMonth = in->mon + 1; out->wDay = in->day; out->wHour = in->hour; out->wMinute = in->min; out->wSecond = in->sec; out->wMilliseconds = in->msec; } internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in) { SYSTEMTIME systime = {0}; FileTimeToSystemTime(in, &systime); DateTime date_time = {0}; os_w32_date_time_from_system_time(&date_time, &systime); *out = dense_time_from_date_time(date_time); } internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us) { U32 sleep_ms = 0; if(endt_us == max_U64) { sleep_ms = INFINITE; } else { U64 begint = os_now_microseconds(); if(begint < endt_us) { U64 sleep_us = endt_us - begint; sleep_ms = (U32)((sleep_us + 999)/1000); } } return sleep_ms; } internal U32 os_w32_unix_time_from_file_time(FILETIME file_time) { U64 win32_time = ((U64)file_time.dwHighDateTime << 32) | file_time.dwLowDateTime; U64 unix_time64 = ((win32_time - 0x19DB1DED53E8000ULL) / 10000000); Assert(unix_time64 <= max_U32); U32 unix_time32 = (U32)unix_time64; return unix_time32; } //////////////////////////////// //~ rjf: Entity Functions internal OS_W32_Entity * os_w32_entity_alloc(OS_W32_EntityKind kind) { OS_W32_Entity *result = 0; EnterCriticalSection(&os_w32_state.entity_mutex); { result = os_w32_state.entity_free; if(result) { SLLStackPop(os_w32_state.entity_free); } else { result = push_array_no_zero(os_w32_state.entity_arena, OS_W32_Entity, 1); } MemoryZeroStruct(result); } LeaveCriticalSection(&os_w32_state.entity_mutex); result->kind = kind; return result; } internal void os_w32_entity_release(OS_W32_Entity *entity) { entity->kind = OS_W32_EntityKind_Null; EnterCriticalSection(&os_w32_state.entity_mutex); SLLStackPush(os_w32_state.entity_free, entity); LeaveCriticalSection(&os_w32_state.entity_mutex); } //////////////////////////////// //~ rjf: Thread Entry Point internal DWORD os_w32_thread_entry_point(void *ptr) { OS_W32_Entity *entity = (OS_W32_Entity *)ptr; ThreadEntryPointFunctionType *func = entity->thread.func; void *thread_ptr = entity->thread.ptr; supplement_thread_base_entry_point(func, thread_ptr); return 0; } //////////////////////////////// //~ rjf: @os_hooks System/Process Info (Implemented Per-OS) internal OS_SystemInfo * os_get_system_info(void) { return &os_w32_state.system_info; } internal OS_ProcessInfo * os_get_process_info(void) { return &os_w32_state.process_info; } internal String8 os_get_current_path(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); DWORD length = GetCurrentDirectoryW(0, 0); U16 *memory = push_array_no_zero(scratch.arena, U16, length + 1); length = GetCurrentDirectoryW(length + 1, (WCHAR*)memory); String8 name = str8_from_16(arena, str16(memory, length)); scratch_end(scratch); return name; } internal U32 os_get_process_start_time_unix(void) { HANDLE handle = GetCurrentProcess(); FILETIME start_time = {0}; FILETIME exit_time; FILETIME kernel_time; FILETIME user_time; if(GetProcessTimes(handle, &start_time, &exit_time, &kernel_time, &user_time)) { return os_w32_unix_time_from_file_time(start_time); } return 0; } //////////////////////////////// //~ rjf: @os_hooks Memory Allocation (Implemented Per-OS) //- rjf: basic internal void * os_reserve(U64 size) { void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); return result; } internal B32 os_commit(void *ptr, U64 size) { B32 result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); w32_rio_functions.RIODeregisterBuffer(w32_rio_functions.RIORegisterBuffer(ptr, size)); return result; } internal void os_decommit(void *ptr, U64 size) { VirtualFree(ptr, size, MEM_DECOMMIT); } internal void os_release(void *ptr, U64 size) { // NOTE(rjf): size not used - not necessary on Windows, but necessary for other OSes. VirtualFree(ptr, 0, MEM_RELEASE); } //- rjf: large pages internal void * os_reserve_large(U64 size) { // we commit on reserve because windows void *result = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_LARGE_PAGES, PAGE_READWRITE); return result; } internal B32 os_commit_large(void *ptr, U64 size) { return 1; } //////////////////////////////// //~ rjf: @os_hooks Thread Info (Implemented Per-OS) internal U32 os_tid(void) { DWORD id = GetCurrentThreadId(); return (U32)id; } internal void os_set_thread_name(String8 name) { Temp scratch = scratch_begin(0, 0); // rjf: windows 10 style if(w32_SetThreadDescription_func) { String16 name16 = str16_from_8(scratch.arena, name); HRESULT hr = w32_SetThreadDescription_func(GetCurrentThread(), (WCHAR*)name16.str); } // rjf: raise-exception style { String8 name_copy = push_str8_copy(scratch.arena, name); #pragma pack(push,8) typedef struct THREADNAME_INFO THREADNAME_INFO; struct THREADNAME_INFO { U32 dwType; // Must be 0x1000. char *szName; // Pointer to name (in user addr space). U32 dwThreadID; // Thread ID (-1=caller thread). U32 dwFlags; // Reserved for future use, must be zero. }; #pragma pack(pop) THREADNAME_INFO info; info.dwType = 0x1000; info.szName = (char *)name_copy.str; info.dwThreadID = os_tid(); info.dwFlags = 0; #pragma warning(push) #pragma warning(disable: 6320 6322) __try { RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); } __except (EXCEPTION_EXECUTE_HANDLER) { } #pragma warning(pop) } scratch_end(scratch); } //////////////////////////////// //~ rjf: @os_hooks Aborting (Implemented Per-OS) internal void os_abort(S32 exit_code) { ExitProcess(exit_code); } //////////////////////////////// //~ rjf: @os_hooks File System (Implemented Per-OS) //- rjf: files internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { OS_Handle result = {0}; Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); DWORD access_flags = 0; DWORD share_mode = 0; DWORD creation_disposition = OPEN_EXISTING; SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0}; if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;} if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;} if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;} if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;} if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;} if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;} if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; } if(flags & OS_AccessFlag_Inherited) { security_attributes.bInheritHandle = 1; } HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, &security_attributes, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0); if(file != INVALID_HANDLE_VALUE) { result.u64[0] = (U64)file; } else { DWORD err = GetLastError(); (void)err; } scratch_end(scratch); return result; } internal void os_file_close(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { return; } HANDLE handle = (HANDLE)file.u64[0]; BOOL result = CloseHandle(handle); (void)result; } internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data) { if(os_handle_match(file, os_handle_zero())) { return 0; } HANDLE handle = (HANDLE)file.u64[0]; // rjf: clamp range by file size U64 size = 0; GetFileSizeEx(handle, (LARGE_INTEGER *)&size); Rng1U64 rng_clamped = r1u64(ClampTop(rng.min, size), ClampTop(rng.max, size)); U64 total_read_size = 0; // rjf: read loop { U64 to_read = dim_1u64(rng_clamped); for(U64 off = rng.min; total_read_size < to_read;) { U64 amt64 = to_read - total_read_size; U32 amt32 = u32_from_u64_saturate(amt64); DWORD read_size = 0; OVERLAPPED overlapped = {0}; overlapped.Offset = (off&0x00000000ffffffffull); overlapped.OffsetHigh = (off&0xffffffff00000000ull) >> 32; ReadFile(handle, (U8 *)out_data + total_read_size, amt32, &read_size, &overlapped); off += read_size; total_read_size += read_size; if(read_size != amt32) { break; } } } return total_read_size; } internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data) { if(os_handle_match(file, os_handle_zero())) { return 0; } HANDLE win_handle = (HANDLE)file.u64[0]; U64 src_off = 0; U64 dst_off = rng.min; U64 total_write_size = dim_1u64(rng); for(;;) { void *bytes_src = (U8 *)data + src_off; U64 bytes_left = total_write_size - src_off; DWORD write_size = Min(MB(1), bytes_left); DWORD bytes_written = 0; OVERLAPPED overlapped = {0}; overlapped.Offset = (dst_off&0x00000000ffffffffull); overlapped.OffsetHigh = (dst_off&0xffffffff00000000ull) >> 32; BOOL success = WriteFile(win_handle, bytes_src, write_size, &bytes_written, &overlapped); if(success == 0) { break; } src_off += bytes_written; dst_off += bytes_written; if(bytes_left == 0) { break; } } return src_off; } internal B32 os_file_set_time(OS_Handle file, DateTime time) { if(os_handle_match(file, os_handle_zero())) { return 0; } B32 result = 0; HANDLE handle = (HANDLE)file.u64[0]; SYSTEMTIME system_time = {0}; os_w32_system_time_from_date_time(&system_time, &time); FILETIME file_time = {0}; result = (SystemTimeToFileTime(&system_time, &file_time) && SetFileTime(handle, &file_time, &file_time, &file_time)); return result; } internal FileProperties os_properties_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { FileProperties r = {0}; return r; } FileProperties props = {0}; HANDLE handle = (HANDLE)file.u64[0]; BY_HANDLE_FILE_INFORMATION info; BOOL info_good = GetFileInformationByHandle(handle, &info); if(info_good) { U32 size_lo = info.nFileSizeLow; U32 size_hi = info.nFileSizeHigh; props.size = (U64)size_lo | (((U64)size_hi)<<32); os_w32_dense_time_from_file_time(&props.modified, &info.ftLastWriteTime); os_w32_dense_time_from_file_time(&props.created, &info.ftCreationTime); props.flags = os_w32_file_property_flags_from_dwFileAttributes(info.dwFileAttributes); } return props; } internal OS_FileID os_id_from_file(OS_Handle file) { if(os_handle_match(file, os_handle_zero())) { OS_FileID r = {0}; return r; } OS_FileID result = {0}; HANDLE handle = (HANDLE)file.u64[0]; BY_HANDLE_FILE_INFORMATION info; BOOL is_ok = GetFileInformationByHandle(handle, &info); if(is_ok) { result.v[0] = info.dwVolumeSerialNumber; result.v[1] = info.nFileIndexLow; result.v[2] = info.nFileIndexHigh; } return result; } internal B32 os_file_reserve_size(OS_Handle file, U64 size) { HANDLE handle = (HANDLE)file.u64[0]; FILE_ALLOCATION_INFO alloc_info = {0}; alloc_info.AllocationSize.LowPart = size & max_U32; alloc_info.AllocationSize.HighPart = (size >> 32) & max_U32; BOOL is_reserved = SetFileInformationByHandle(handle, FileAllocationInfo, &alloc_info, sizeof(alloc_info)); return is_reserved; } internal B32 os_delete_file_at_path(String8 path) { Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); B32 result = DeleteFileW((WCHAR*)path16.str); scratch_end(scratch); return result; } internal B32 os_copy_file_path(String8 dst, String8 src) { Temp scratch = scratch_begin(0, 0); String16 dst16 = str16_from_8(scratch.arena, dst); String16 src16 = str16_from_8(scratch.arena, src); B32 result = CopyFileW((WCHAR*)src16.str, (WCHAR*)dst16.str, 0); scratch_end(scratch); return result; } internal B32 os_move_file_path(String8 dst, String8 src) { Temp scratch = scratch_begin(0, 0); String16 dst16 = str16_from_8(scratch.arena, dst); String16 src16 = str16_from_8(scratch.arena, src); B32 result = MoveFileW((WCHAR*)src16.str, (WCHAR*)dst16.str); scratch_end(scratch); return result; } internal String8 os_full_path_from_path(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); DWORD buffer_size = Max(MAX_PATH, path.size * 2) + 1; String16 path16 = str16_from_8(scratch.arena, path); WCHAR *buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); DWORD path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); if(path16_size > buffer_size) { arena_pop(scratch.arena, buffer_size); buffer_size = path16_size + 1; buffer = push_array_no_zero(scratch.arena, WCHAR, buffer_size); path16_size = GetFullPathNameW((WCHAR*)path16.str, buffer_size, buffer, NULL); } String8 full_path = str8_from_16(arena, str16((U16*)buffer, path16_size)); scratch_end(scratch); return full_path; } internal B32 os_file_path_exists(String8 path) { Temp scratch = scratch_begin(0,0); String16 path16 = str16_from_8(scratch.arena, path); DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && !!(~attributes & FILE_ATTRIBUTE_DIRECTORY); scratch_end(scratch); return exists; } internal B32 os_folder_path_exists(String8 path) { Temp scratch = scratch_begin(0,0); String16 path16 = str16_from_8(scratch.arena, path); DWORD attributes = GetFileAttributesW((WCHAR *)path16.str); B32 exists = (attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY); scratch_end(scratch); return exists; } internal FileProperties os_properties_from_file_path(String8 path) { WIN32_FIND_DATAW find_data = {0}; Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); HANDLE handle = FindFirstFileW((WCHAR *)path16.str, &find_data); FileProperties props = {0}; if(handle != INVALID_HANDLE_VALUE) { props.size = Compose64Bit(find_data.nFileSizeHigh, find_data.nFileSizeLow); os_w32_dense_time_from_file_time(&props.created, &find_data.ftCreationTime); os_w32_dense_time_from_file_time(&props.modified, &find_data.ftLastWriteTime); props.flags = os_w32_file_property_flags_from_dwFileAttributes(find_data.dwFileAttributes); } else { Temp scratch = scratch_begin(0, 0); WCHAR buffer[512] = {0}; DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); U64 last_slash_pos = 0; for(;last_slash_pos < path.size; last_slash_pos = str8_find_needle(path, last_slash_pos+1, str8_lit("/"), StringMatchFlag_SlashInsensitive)); String8 path_trimmed = str8_prefix(path, last_slash_pos); for(U64 off = 0; off < (U64)length;) { String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); off += next_drive_string_16.size+1; String8 next_drive_string = str8_from_16(scratch.arena, next_drive_string_16); next_drive_string = str8_chop_last_slash(next_drive_string); if(str8_match(path_trimmed, next_drive_string, StringMatchFlag_CaseInsensitive)) { props.flags |= FilePropertyFlag_IsFolder; break; } } scratch_end(scratch); } FindClose(handle); scratch_end(scratch); return props; } //- rjf: file maps internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file) { OS_Handle map = {0}; { HANDLE file_handle = (HANDLE)file.u64[0]; DWORD protect_flags = 0; { switch(flags) { default:{}break; case OS_AccessFlag_Read: {protect_flags = PAGE_READONLY;}break; case OS_AccessFlag_Write: case OS_AccessFlag_Read|OS_AccessFlag_Write: {protect_flags = PAGE_READWRITE;}break; case OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Execute: {protect_flags = PAGE_EXECUTE_READ;}break; case OS_AccessFlag_Execute|OS_AccessFlag_Write|OS_AccessFlag_Read: case OS_AccessFlag_Execute|OS_AccessFlag_Write: {protect_flags = PAGE_EXECUTE_READWRITE;}break; } } HANDLE map_handle = CreateFileMappingA(file_handle, 0, protect_flags, 0, 0, 0); map.u64[0] = (U64)map_handle; } return map; } internal void os_file_map_close(OS_Handle map) { HANDLE handle = (HANDLE)map.u64[0]; BOOL result = CloseHandle(handle); (void)result; } internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range) { HANDLE handle = (HANDLE)map.u64[0]; U32 off_lo = (U32)((range.min&0x00000000ffffffffull)>>0); U32 off_hi = (U32)((range.min&0xffffffff00000000ull)>>32); U64 size = dim_1u64(range); DWORD access_flags = 0; { switch(flags) { default:{}break; case OS_AccessFlag_Read: { access_flags = FILE_MAP_READ; }break; case OS_AccessFlag_Write: { access_flags = FILE_MAP_WRITE; }break; case OS_AccessFlag_Read|OS_AccessFlag_Write: { access_flags = FILE_MAP_ALL_ACCESS; }break; case OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Execute: case OS_AccessFlag_Write|OS_AccessFlag_Execute: case OS_AccessFlag_Read|OS_AccessFlag_Write|OS_AccessFlag_Execute: { access_flags = FILE_MAP_ALL_ACCESS|FILE_MAP_EXECUTE; }break; } } void *result = MapViewOfFile(handle, access_flags, off_hi, off_lo, size); return result; } internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range) { BOOL result = UnmapViewOfFile(ptr); (void)result; } //- rjf: directory iteration internal OS_FileIter * os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8 path_with_wildcard = push_str8_cat(scratch.arena, path, str8_lit("\\*")); String16 path16 = str16_from_8(scratch.arena, path_with_wildcard); OS_FileIter *iter = push_array(arena, OS_FileIter, 1); iter->flags = flags; OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; if(path.size == 0) { w32_iter->is_volume_iter = 1; WCHAR buffer[512] = {0}; DWORD length = GetLogicalDriveStringsW(sizeof(buffer), buffer); String8List drive_strings = {0}; for(U64 off = 0; off < (U64)length;) { String16 next_drive_string_16 = str16_cstring((U16 *)buffer+off); off += next_drive_string_16.size+1; String8 next_drive_string = str8_from_16(arena, next_drive_string_16); next_drive_string = str8_chop_last_slash(next_drive_string); str8_list_push(scratch.arena, &drive_strings, next_drive_string); } w32_iter->drive_strings = str8_array_from_list(arena, &drive_strings); w32_iter->drive_strings_iter_idx = 0; } else { w32_iter->handle = FindFirstFileExW((WCHAR*)path16.str, FindExInfoBasic, &w32_iter->find_data, FindExSearchNameMatch, 0, FIND_FIRST_EX_LARGE_FETCH); } scratch_end(scratch); return iter; } internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { B32 result = 0; OS_FileIterFlags flags = iter->flags; OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; switch(w32_iter->is_volume_iter) { //- rjf: file iteration default: case 0: { if (!(flags & OS_FileIterFlag_Done) && w32_iter->handle != INVALID_HANDLE_VALUE) { do { // check is usable B32 usable_file = 1; WCHAR *file_name = w32_iter->find_data.cFileName; DWORD attributes = w32_iter->find_data.dwFileAttributes; if (file_name[0] == '.'){ if (flags & OS_FileIterFlag_SkipHiddenFiles){ usable_file = 0; } else if (file_name[1] == 0){ usable_file = 0; } else if (file_name[1] == '.' && file_name[2] == 0){ usable_file = 0; } } if (attributes & FILE_ATTRIBUTE_DIRECTORY){ if (flags & OS_FileIterFlag_SkipFolders){ usable_file = 0; } } else{ if (flags & OS_FileIterFlag_SkipFiles){ usable_file = 0; } } // emit if usable if (usable_file){ info_out->name = str8_from_16(arena, str16_cstring((U16*)file_name)); info_out->props.size = (U64)w32_iter->find_data.nFileSizeLow | (((U64)w32_iter->find_data.nFileSizeHigh)<<32); os_w32_dense_time_from_file_time(&info_out->props.created, &w32_iter->find_data.ftCreationTime); os_w32_dense_time_from_file_time(&info_out->props.modified, &w32_iter->find_data.ftLastWriteTime); info_out->props.flags = os_w32_file_property_flags_from_dwFileAttributes(attributes); result = 1; if (!FindNextFileW(w32_iter->handle, &w32_iter->find_data)){ iter->flags |= OS_FileIterFlag_Done; } break; } }while(FindNextFileW(w32_iter->handle, &w32_iter->find_data)); } }break; //- rjf: volume iteration case 1: { result = w32_iter->drive_strings_iter_idx < w32_iter->drive_strings.count; if(result != 0) { MemoryZeroStruct(info_out); info_out->name = w32_iter->drive_strings.v[w32_iter->drive_strings_iter_idx]; info_out->props.flags |= FilePropertyFlag_IsFolder; w32_iter->drive_strings_iter_idx += 1; } }break; } if(!result) { iter->flags |= OS_FileIterFlag_Done; } return result; } internal void os_file_iter_end(OS_FileIter *iter) { OS_W32_FileIter *w32_iter = (OS_W32_FileIter*)iter->memory; HANDLE zero_handle; MemoryZeroStruct(&zero_handle); if(!MemoryMatchStruct(&zero_handle, &w32_iter->handle)) { FindClose(w32_iter->handle); } } //- rjf: directory creation internal B32 os_make_directory(String8 path) { B32 result = 0; Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, path); WIN32_FILE_ATTRIBUTE_DATA attributes = {0}; GetFileAttributesExW((WCHAR*)name16.str, GetFileExInfoStandard, &attributes); if(attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { result = 1; } else if(CreateDirectoryW((WCHAR*)name16.str, 0)) { result = 1; } scratch_end(scratch); return(result); } //////////////////////////////// //~ rjf: @os_hooks Shared Memory (Implemented Per-OS) internal OS_Handle os_shared_memory_alloc(U64 size, String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE file = CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, (U32)((size & 0xffffffff00000000) >> 32), (U32)((size & 0x00000000ffffffff)), (WCHAR *)name16.str); OS_Handle result = {(U64)file}; scratch_end(scratch); return result; } internal OS_Handle os_shared_memory_open(String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE file = OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, (WCHAR *)name16.str); OS_Handle result = {(U64)file}; scratch_end(scratch); return result; } internal void os_shared_memory_close(OS_Handle handle) { HANDLE file = (HANDLE)(handle.u64[0]); CloseHandle(file); } internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range) { HANDLE file = (HANDLE)(handle.u64[0]); U64 offset = range.min; U64 size = range.max-range.min; void *ptr = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, (U32)((offset & 0xffffffff00000000) >> 32), (U32)((offset & 0x00000000ffffffff)), size); return ptr; } internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range) { UnmapViewOfFile(ptr); } //////////////////////////////// //~ rjf: @os_hooks Time (Implemented Per-OS) internal U64 os_now_microseconds(void) { U64 result = 0; LARGE_INTEGER large_int_counter; if(QueryPerformanceCounter(&large_int_counter)) { result = (large_int_counter.QuadPart*Million(1))/os_w32_state.microsecond_resolution; } return result; } internal U32 os_now_unix(void) { FILETIME file_time; GetSystemTimeAsFileTime(&file_time); U32 unix_time = os_w32_unix_time_from_file_time(file_time); return unix_time; } internal DateTime os_now_universal_time(void) { SYSTEMTIME systime = {0}; GetSystemTime(&systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal DateTime os_universal_time_from_local(DateTime *date_time) { SYSTEMTIME systime = {0}; os_w32_system_time_from_date_time(&systime, date_time); FILETIME ftime = {0}; SystemTimeToFileTime(&systime, &ftime); FILETIME ftime_local = {0}; LocalFileTimeToFileTime(&ftime, &ftime_local); FileTimeToSystemTime(&ftime_local, &systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal DateTime os_local_time_from_universal(DateTime *date_time) { SYSTEMTIME systime = {0}; os_w32_system_time_from_date_time(&systime, date_time); FILETIME ftime = {0}; SystemTimeToFileTime(&systime, &ftime); FILETIME ftime_local = {0}; FileTimeToLocalFileTime(&ftime, &ftime_local); FileTimeToSystemTime(&ftime_local, &systime); DateTime result = {0}; os_w32_date_time_from_system_time(&result, &systime); return result; } internal void os_sleep_milliseconds(U32 msec) { Sleep(msec); } //////////////////////////////// //~ rjf: @os_hooks Child Processes (Implemented Per-OS) internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params) { OS_Handle result = {0}; Temp scratch = scratch_begin(0, 0); //- rjf: form full command string String8 cmd = {0}; { StringJoin join_params = {0}; join_params.pre = str8_lit("\""); join_params.sep = str8_lit("\" \""); join_params.post = str8_lit("\""); cmd = str8_list_join(scratch.arena, ¶ms->cmd_line, &join_params); } //- rjf: form environment B32 use_null_env_arg = 0; String8 env = {0}; { StringJoin join_params2 = {0}; join_params2.sep = str8_lit("\0"); join_params2.post = str8_lit("\0"); String8List all_opts = params->env; if(params->inherit_env != 0) { if(all_opts.node_count != 0) { MemoryZeroStruct(&all_opts); for(String8Node *n = params->env.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } for(String8Node *n = os_w32_state.process_info.environment.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &all_opts, n->string); } } else { use_null_env_arg = 1; } } if(use_null_env_arg == 0) { env = str8_list_join(scratch.arena, &all_opts, &join_params2); } } //- rjf: utf-8 -> utf-16 String16 cmd16 = str16_from_8(scratch.arena, cmd); String16 dir16 = str16_from_8(scratch.arena, params->path); String16 env16 = {0}; if(use_null_env_arg == 0) { env16 = str16_from_8(scratch.arena, env); } //- rjf: determine creation flags DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT; if(params->consoleless) { creation_flags |= CREATE_NO_WINDOW; } //- rjf: launch BOOL inherit_handles = 0; STARTUPINFOW startup_info = {sizeof(startup_info)}; if(!os_handle_match(params->stdout_file, os_handle_zero())) { HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0]; startup_info.hStdOutput = stdout_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stderr_file, os_handle_zero())) { HANDLE stderr_handle = (HANDLE)params->stderr_file.u64[0]; startup_info.hStdError = stderr_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } if(!os_handle_match(params->stdin_file, os_handle_zero())) { HANDLE stdin_handle = (HANDLE)params->stdin_file.u64[0]; startup_info.hStdInput = stdin_handle; startup_info.dwFlags |= STARTF_USESTDHANDLES; inherit_handles = 1; } PROCESS_INFORMATION process_info = {0}; if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, inherit_handles, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info)) { result.u64[0] = (U64)process_info.hProcess; CloseHandle(process_info.hThread); } scratch_end(scratch); return result; } internal B32 os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out) { HANDLE process = (HANDLE)(handle.u64[0]); DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); DWORD result = WaitForSingleObject(process, sleep_ms); B32 process_joined = (result == WAIT_OBJECT_0); if(process_joined && exit_code_out) { DWORD exit_code = 0; if(GetExitCodeProcess(process, &exit_code)) { *exit_code_out = exit_code; } } return process_joined; } internal B32 os_process_kill(OS_Handle handle) { HANDLE process = (HANDLE)handle.u64[0]; BOOL was_terminated = TerminateProcess(process, 999); return was_terminated; } internal void os_process_detach(OS_Handle handle) { HANDLE process = (HANDLE)(handle.u64[0]); CloseHandle(process); } //////////////////////////////// //~ rjf: @os_hooks Threads (Implemented Per-OS) internal Thread os_thread_launch(ThreadEntryPointFunctionType *f, void *p) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Thread); entity->thread.func = f; entity->thread.ptr = p; entity->thread.handle = CreateThread(0, 0, os_w32_thread_entry_point, entity, 0, &entity->thread.tid); Thread result = {IntFromPtr(entity)}; return result; } internal B32 os_thread_join(Thread handle, U64 endt_us) { DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); OS_W32_Entity *entity = (OS_W32_Entity *)PtrFromInt(handle.u64[0]); DWORD wait_result = WAIT_OBJECT_0; if(entity != 0) { wait_result = WaitForSingleObject(entity->thread.handle, sleep_ms); CloseHandle(entity->thread.handle); os_w32_entity_release(entity); } return (wait_result == WAIT_OBJECT_0); } internal void os_thread_detach(Thread thread) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(thread.u64[0]); if(entity != 0) { CloseHandle(entity->thread.handle); os_w32_entity_release(entity); } } //////////////////////////////// //~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS) //- rjf: mutexes internal Mutex os_mutex_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Mutex); InitializeCriticalSection(&entity->mutex); Mutex result = {IntFromPtr(entity)}; return result; } internal void os_mutex_release(Mutex mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); DeleteCriticalSection(&entity->mutex); os_w32_entity_release(entity); } internal void os_mutex_take(Mutex mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); EnterCriticalSection(&entity->mutex); } internal void os_mutex_drop(Mutex mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); LeaveCriticalSection(&entity->mutex); } //- rjf: reader/writer mutexes internal RWMutex os_rw_mutex_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_RWMutex); InitializeSRWLock(&entity->rw_mutex); RWMutex result = {IntFromPtr(entity)}; return result; } internal void os_rw_mutex_release(RWMutex rw_mutex) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); os_w32_entity_release(entity); } internal void os_rw_mutex_take(RWMutex rw_mutex, B32 write_mode) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); if(write_mode) { AcquireSRWLockExclusive(&entity->rw_mutex); } else { AcquireSRWLockShared(&entity->rw_mutex); } } internal void os_rw_mutex_drop(RWMutex rw_mutex, B32 write_mode) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); if(write_mode) { ReleaseSRWLockExclusive(&entity->rw_mutex); } else { ReleaseSRWLockShared(&entity->rw_mutex); } } //- rjf: condition variables internal CondVar os_cond_var_alloc(void) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_ConditionVariable); InitializeConditionVariable(&entity->cv); CondVar result = {IntFromPtr(entity)}; return result; } internal void os_cond_var_release(CondVar cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); os_w32_entity_release(entity); } internal B32 os_cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if(sleep_ms > 0) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); result = SleepConditionVariableCS(&entity->cv, &mutex_entity->mutex, sleep_ms); } return result; } internal B32 os_cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if(sleep_ms > 0) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); OS_W32_Entity *mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, write_mode ? 0 : CONDITION_VARIABLE_LOCKMODE_SHARED); } return result; } internal void os_cond_var_signal(CondVar cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); WakeConditionVariable(&entity->cv); } internal void os_cond_var_broadcast(CondVar cv) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); WakeAllConditionVariable(&entity->cv); } //- rjf: cross-process semaphores internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE handle = CreateSemaphoreW(0, initial_count, max_count, (WCHAR *)name16.str); Semaphore result = {(U64)handle}; scratch_end(scratch); return result; } internal void os_semaphore_release(Semaphore semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; CloseHandle(handle); } internal Semaphore os_semaphore_open(String8 name) { Temp scratch = scratch_begin(0, 0); String16 name16 = str16_from_8(scratch.arena, name); HANDLE handle = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, 0, (WCHAR *)name16.str); Semaphore result = {(U64)handle}; scratch_end(scratch); return result; } internal void os_semaphore_close(Semaphore semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; CloseHandle(handle); } internal B32 os_semaphore_take(Semaphore semaphore, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); HANDLE handle = (HANDLE)semaphore.u64[0]; DWORD wait_result = WaitForSingleObject(handle, sleep_ms); B32 result = (wait_result == WAIT_OBJECT_0); return result; } internal void os_semaphore_drop(Semaphore semaphore) { HANDLE handle = (HANDLE)semaphore.u64[0]; ReleaseSemaphore(handle, 1, 0); } //- rjf: barriers internal Barrier os_barrier_alloc(U64 count) { OS_W32_Entity *entity = os_w32_entity_alloc(OS_W32_EntityKind_Barrier); if(entity != 0) { BOOL init_good = InitializeSynchronizationBarrier(&entity->sb, count, -1); (void)init_good; } Barrier result = {IntFromPtr(entity)}; return result; } internal void os_barrier_release(Barrier barrier) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(barrier.u64[0]); if(entity != 0) { DeleteSynchronizationBarrier(&entity->sb); os_w32_entity_release(entity); } } internal void os_barrier_wait(Barrier barrier) { OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(barrier.u64[0]); if(entity != 0) { EnterSynchronizationBarrier(&entity->sb, 0); } } //////////////////////////////// //~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS) internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); String16 path16 = str16_from_8(scratch.arena, path); HMODULE mod = LoadLibraryW((LPCWSTR)path16.str); OS_Handle result = { (U64)mod }; scratch_end(scratch); return result; } internal VoidProc* os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); HMODULE mod = (HMODULE)lib.u64[0]; name = push_str8_copy(scratch.arena, name); VoidProc *result = (VoidProc*)GetProcAddress(mod, (LPCSTR)name.str); scratch_end(scratch); return result; } internal void os_library_close(OS_Handle lib) { HMODULE mod = (HMODULE)lib.u64[0]; FreeLibrary(mod); } //////////////////////////////// //~ rjf: @os_hooks Safe Calls (Implemented Per-OS) internal void os_safe_call(ThreadEntryPointFunctionType *func, ThreadEntryPointFunctionType *fail_handler, void *ptr) { __try { func(ptr); } __except (EXCEPTION_EXECUTE_HANDLER) { if(fail_handler != 0) { fail_handler(ptr); } ExitProcess(1); } } //////////////////////////////// //~ rjf: @os_hooks GUIDs (Implemented Per-OS) internal Guid os_make_guid(void) { Guid result; MemoryZeroStruct(&result); UUID uuid; RPC_STATUS rpc_status = UuidCreate(&uuid); if(rpc_status == RPC_S_OK) { result.data1 = uuid.Data1; result.data2 = uuid.Data2; result.data3 = uuid.Data3; MemoryCopyArray(result.data4, uuid.Data4); } return result; } //////////////////////////////// //~ rjf: @os_hooks Entry Points (Implemented Per-OS) #include #undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside #include internal B32 win32_g_is_quiet = 0; internal B32 win32_g_gen_dump = 0; internal HRESULT WINAPI win32_dialog_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LONG_PTR data) { if(msg == TDN_HYPERLINK_CLICKED) { ShellExecuteW(NULL, L"open", (LPWSTR)lparam, NULL, NULL, SW_SHOWNORMAL); } return S_OK; } internal LONG WINAPI win32_exception_filter(EXCEPTION_POINTERS* exception_ptrs) { if(win32_g_is_quiet) { ExitProcess(1); } static volatile LONG first = 0; if(InterlockedCompareExchange(&first, 1, 0) != 0) { // prevent failures in other threads to popup same message box // this handler just shows first thread that crashes // we are terminating afterwards anyway for (;;) Sleep(1000); } WCHAR buffer[4096] = {0}; int buflen = 0; DWORD exception_code = exception_ptrs->ExceptionRecord->ExceptionCode; buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"A fatal exception (code 0x%x) occurred. The process is terminating.\n", exception_code); // load dbghelp dynamically just in case if it is missing BOOL (WINAPI *dbg_MiniDumpWriteDump)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam) = 0; HMODULE dbghelp = LoadLibraryA("dbghelp.dll"); if(dbghelp) { DWORD (WINAPI *dbg_SymSetOptions)(DWORD SymOptions); BOOL (WINAPI *dbg_SymInitializeW)(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess); BOOL (WINAPI *dbg_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); PVOID (WINAPI *dbg_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase); DWORD64 (WINAPI *dbg_SymGetModuleBase64)(HANDLE hProcess, DWORD64 qwAddr); BOOL (WINAPI *dbg_SymFromAddrW)(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFOW Symbol); BOOL (WINAPI *dbg_SymGetLineFromAddrW64)(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line); BOOL (WINAPI *dbg_SymGetModuleInfoW64)(HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULEW64 ModuleInfo); *(FARPROC*)&dbg_SymSetOptions = GetProcAddress(dbghelp, "SymSetOptions"); *(FARPROC*)&dbg_SymInitializeW = GetProcAddress(dbghelp, "SymInitializeW"); *(FARPROC*)&dbg_StackWalk64 = GetProcAddress(dbghelp, "StackWalk64"); *(FARPROC*)&dbg_SymFunctionTableAccess64 = GetProcAddress(dbghelp, "SymFunctionTableAccess64"); *(FARPROC*)&dbg_SymGetModuleBase64 = GetProcAddress(dbghelp, "SymGetModuleBase64"); *(FARPROC*)&dbg_SymFromAddrW = GetProcAddress(dbghelp, "SymFromAddrW"); *(FARPROC*)&dbg_SymGetLineFromAddrW64 = GetProcAddress(dbghelp, "SymGetLineFromAddrW64"); *(FARPROC*)&dbg_SymGetModuleInfoW64 = GetProcAddress(dbghelp, "SymGetModuleInfoW64"); *(FARPROC*)&dbg_MiniDumpWriteDump = GetProcAddress(dbghelp, "MiniDumpWriteDump"); if(dbg_SymSetOptions && dbg_SymInitializeW && dbg_StackWalk64 && dbg_SymFunctionTableAccess64 && dbg_SymGetModuleBase64 && dbg_SymFromAddrW && dbg_SymGetLineFromAddrW64 && dbg_SymGetModuleInfoW64) { HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); CONTEXT* context = exception_ptrs->ContextRecord; WCHAR module_path[MAX_PATH]; GetModuleFileNameW(NULL, module_path, ArrayCount(module_path)); PathRemoveFileSpecW(module_path); dbg_SymSetOptions(SYMOPT_EXACT_SYMBOLS | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); if(dbg_SymInitializeW(process, module_path, TRUE)) { // check that raddbg.pdb file is good B32 raddbg_pdb_valid = 0; { IMAGEHLP_MODULEW64 module = {0}; module.SizeOfStruct = sizeof(module); if(dbg_SymGetModuleInfoW64(process, (DWORD64)&win32_exception_filter, &module)) { raddbg_pdb_valid = (module.SymType == SymPdb); } } if(!raddbg_pdb_valid) { buflen += wnsprintfW(buffer + buflen, sizeof(buffer) - buflen, L"\nThe PDB debug information file for this executable is not valid or was not found. Please rebuild binary to get the call stack.\n"); } else { STACKFRAME64 frame = {0}; DWORD image_type; #if defined(_M_AMD64) image_type = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Offset = context->Rip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Rbp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Rsp; frame.AddrStack.Mode = AddrModeFlat; #elif defined(_M_ARM64) image_type = IMAGE_FILE_MACHINE_ARM64; frame.AddrPC.Offset = context->Pc; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Fp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Sp; frame.AddrStack.Mode = AddrModeFlat; #else # error Arch not supported! #endif for(U32 idx=0; ;idx++) { const U32 max_frames = 32; if(idx == max_frames) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"..."); break; } if(!dbg_StackWalk64(image_type, process, thread, &frame, context, 0, dbg_SymFunctionTableAccess64, dbg_SymGetModuleBase64, 0)) { break; } U64 address = frame.AddrPC.Offset; if(address == 0) { break; } if(idx==0) { #if BUILD_CONSOLE_INTERFACE buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nCreate a new issue with this report at %S.\n\n", BUILD_ISSUES_LINK_STRING_LITERAL); #else buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nPress Ctrl+C to copy this text to clipboard, then create a new issue at\n" L"%S\n\n", BUILD_ISSUES_LINK_STRING_LITERAL, BUILD_ISSUES_LINK_STRING_LITERAL); #endif buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"Call stack:\n"); } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"%u. [0x%I64x]", idx + 1, address); struct { SYMBOL_INFOW info; WCHAR name[MAX_SYM_NAME]; } symbol = {0}; symbol.info.SizeOfStruct = sizeof(symbol.info); symbol.info.MaxNameLen = MAX_SYM_NAME; DWORD64 displacement = 0; if(dbg_SymFromAddrW(process, address, &displacement, &symbol.info)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s +%u", symbol.info.Name, (DWORD)displacement); IMAGEHLP_LINEW64 line = {0}; line.SizeOfStruct = sizeof(line); DWORD line_displacement = 0; if(dbg_SymGetLineFromAddrW64(process, address, &line_displacement, &line)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L", %s line %u", PathFindFileNameW(line.FileName), line.LineNumber); } } else { IMAGEHLP_MODULEW64 module = {0}; module.SizeOfStruct = sizeof(module); if(dbg_SymGetModuleInfoW64(process, address, &module)) { buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L" %s", module.ModuleName); } } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\n"); } } } } } buflen += wnsprintfW(buffer + buflen, ArrayCount(buffer) - buflen, L"\nVersion: %S%S", BUILD_VERSION_STRING_LITERAL, BUILD_GIT_HASH_STRING_LITERAL_APPEND); B32 generate_crash_dump = win32_g_gen_dump; #if BUILD_CONSOLE_INTERFACE fwprintf(stderr, L"\n--- Fatal Exception ---\n"); fwprintf(stderr, L"%s\n\n", buffer); #else int selected_button = 0; TASKDIALOG_BUTTON generate_dump = {1, L"Generate Crash Dump File"}; TASKDIALOGCONFIG dialog = {0}; dialog.cbSize = sizeof(dialog); dialog.dwFlags = TDF_SIZE_TO_CONTENT | TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION; dialog.pszMainIcon = TD_ERROR_ICON; dialog.dwCommonButtons = TDCBF_CLOSE_BUTTON; dialog.pszWindowTitle = L"Fatal Exception"; dialog.pszContent = buffer; dialog.pfCallback = &win32_dialog_callback; dialog.cButtons = 1; dialog.pButtons = &generate_dump; TaskDialogIndirect(&dialog, &selected_button, 0, 0); generate_crash_dump = (selected_button == generate_dump.nButtonID); #endif if(dbg_MiniDumpWriteDump && generate_crash_dump) { WCHAR desktop_path[512] = {0}; SHGetFolderPathW(0, CSIDL_DESKTOP, 0, 0, desktop_path); WCHAR dump_file_path[512] = {0}; wnsprintfW(dump_file_path, ArrayCount(dump_file_path), L"%s\\raddbg_crash_dump.dmp", desktop_path); SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0}; HANDLE file = CreateFileW(dump_file_path, GENERIC_WRITE, 0, &security_attributes, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); BOOL dump_successful = dbg_MiniDumpWriteDump(GetCurrentProcess(), os_get_process_info()->pid, file, MiniDumpNormal, 0, 0, 0); CloseHandle(file); (void)dump_successful; } ExitProcess(1); } #undef OS_WINDOWS // shlwapi uses its own OS_WINDOWS include inside #define OS_WINDOWS 1 internal void w32_entry_point_caller(int argc, WCHAR **wargv) { SetUnhandledExceptionFilter(&win32_exception_filter); //- rjf: dynamically load windows functions which are not guaranteed // in all SDKs { HMODULE module = LoadLibraryA("kernel32.dll"); w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription"); FreeLibrary(module); } //- rjf: try to allow large pages if we can B32 large_pages_allowed = 0; { HANDLE token; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { LUID luid; if(LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) { TOKEN_PRIVILEGES priv; priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; large_pages_allowed = !!AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0); } CloseHandle(token); } } //- rjf: get RIO extension function table { // NOTE(mmozeiko): need to get function pointers to RIO functions, and that requires dummy socket WSADATA WinSockData; WSAStartup(MAKEWORD(2, 2), &WinSockData); GUID guid = WSAID_MULTIPLE_RIO; DWORD rio_byte = 0; SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), (void**)&w32_rio_functions, sizeof(w32_rio_functions), &rio_byte, 0, 0); closesocket(Sock); } //- rjf: get system info SYSTEM_INFO sysinfo = {0}; GetSystemInfo(&sysinfo); //- rjf: set up non-dynamically-alloc'd state // // (we need to set up some basics before this layer can supply // memory allocation primitives) { os_w32_state.microsecond_resolution = 1; LARGE_INTEGER large_int_resolution; if(QueryPerformanceFrequency(&large_int_resolution)) { os_w32_state.microsecond_resolution = large_int_resolution.QuadPart; } } { OS_SystemInfo *info = &os_w32_state.system_info; info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors; info->page_size = sysinfo.dwPageSize; info->large_page_size = GetLargePageMinimum(); info->allocation_granularity = sysinfo.dwAllocationGranularity; } { OS_ProcessInfo *info = &os_w32_state.process_info; info->large_pages_allowed = large_pages_allowed; info->pid = GetCurrentProcessId(); } //- rjf: extract arguments Arena *args_arena = arena_alloc(.reserve_size = MB(1), .commit_size = KB(32)); char **argv = push_array(args_arena, char *, argc); for(int i = 0; i < argc; i += 1) { String16 arg16 = str16_cstring((U16 *)wargv[i]); String8 arg8 = str8_from_16(args_arena, arg16); if(str8_match(arg8, str8_lit("--quiet"), StringMatchFlag_CaseInsensitive) || str8_match(arg8, str8_lit("-quiet"), StringMatchFlag_CaseInsensitive)) { win32_g_is_quiet = 1; } if(str8_match(arg8, str8_lit("--large_pages"), StringMatchFlag_CaseInsensitive) || str8_match(arg8, str8_lit("-large_pages"), StringMatchFlag_CaseInsensitive)) { arena_default_flags = ArenaFlag_LargePages; arena_default_reserve_size = Max(MB(64), os_w32_state.system_info.large_page_size); arena_default_commit_size = arena_default_reserve_size; } if(str8_match(arg8, str8_lit("--gen_crash_dump"), StringMatchFlag_CaseInsensitive) || str8_match(arg8, str8_lit("-gen_crash_dump"), StringMatchFlag_CaseInsensitive)) { win32_g_gen_dump = 1; } argv[i] = (char *)arg8.str; } //- rjf: set up thread context TCTX *tctx = tctx_alloc(); tctx_select(tctx); //- rjf: set up dynamically-alloc'd state Arena *arena = arena_alloc(); { os_w32_state.arena = arena; { OS_SystemInfo *info = &os_w32_state.system_info; U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0}; DWORD size = MAX_COMPUTERNAME_LENGTH + 1; if(GetComputerNameA((char*)buffer, &size)) { info->machine_name = push_str8_copy(arena, str8(buffer, size)); } } } { OS_ProcessInfo *info = &os_w32_state.process_info; { Temp scratch = scratch_begin(0, 0); DWORD size = KB(32); U16 *buffer = push_array_no_zero(scratch.arena, U16, size); DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size); String8 name8 = str8_from_16(scratch.arena, str16(buffer, length)); String8 name_chopped = str8_chop_last_slash(name8); info->binary_path = push_str8_copy(arena, name_chopped); scratch_end(scratch); } info->initial_path = os_get_current_path(arena); { Temp scratch = scratch_begin(0, 0); U64 size = KB(32); U16 *buffer = push_array_no_zero(scratch.arena, U16, size); if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer))) { info->user_program_data_path = str8_from_16(arena, str16_cstring(buffer)); } scratch_end(scratch); } { WCHAR *this_proc_env = GetEnvironmentStringsW(); U64 start_idx = 0; for(U64 idx = 0;; idx += 1) { if(this_proc_env[idx] == 0) { if(start_idx == idx) { break; } else { String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx); String8 string = str8_from_16(arena, string16); str8_list_push(arena, &info->environment, string); start_idx = idx+1; } } } } } //- rjf: set up entity storage InitializeCriticalSection(&os_w32_state.entity_mutex); os_w32_state.entity_arena = arena_alloc(); //- rjf: call into "real" entry point main_thread_base_entry_point(argc, argv); } #if BUILD_CONSOLE_INTERFACE int wmain(int argc, WCHAR **argv) { w32_entry_point_caller(argc, argv); return 0; } #else int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { w32_entry_point_caller(__argc, __wargv); return 0; } #endif ================================================ FILE: src/os/core/win32/os_core_win32.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_WIN32_H #define OS_CORE_WIN32_H //////////////////////////////// //~ rjf: Includes / Libraries #include #include #include #include #include #include #include #include #pragma comment(lib, "user32") #pragma comment(lib, "winmm") #pragma comment(lib, "shell32") #pragma comment(lib, "advapi32") #pragma comment(lib, "rpcrt4") #pragma comment(lib, "shlwapi") #pragma comment(lib, "comctl32") #pragma comment(lib, "ws2_32") #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file //////////////////////////////// //~ rjf: File Iterator Types typedef struct OS_W32_FileIter OS_W32_FileIter; struct OS_W32_FileIter { HANDLE handle; WIN32_FIND_DATAW find_data; B32 is_volume_iter; String8Array drive_strings; U64 drive_strings_iter_idx; }; StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size); //////////////////////////////// //~ rjf: Entity Types typedef enum OS_W32_EntityKind { OS_W32_EntityKind_Null, OS_W32_EntityKind_Thread, OS_W32_EntityKind_Mutex, OS_W32_EntityKind_RWMutex, OS_W32_EntityKind_ConditionVariable, OS_W32_EntityKind_Barrier, } OS_W32_EntityKind; typedef struct OS_W32_Entity OS_W32_Entity; struct OS_W32_Entity { OS_W32_Entity *next; OS_W32_EntityKind kind; union { struct { ThreadEntryPointFunctionType *func; void *ptr; HANDLE handle; DWORD tid; } thread; CRITICAL_SECTION mutex; SRWLOCK rw_mutex; CONDITION_VARIABLE cv; SYNCHRONIZATION_BARRIER sb; }; }; //////////////////////////////// //~ rjf: State typedef struct OS_W32_State OS_W32_State; struct OS_W32_State { Arena *arena; // rjf: info OS_SystemInfo system_info; OS_ProcessInfo process_info; U64 microsecond_resolution; // rjf: entity storage CRITICAL_SECTION entity_mutex; Arena *entity_arena; OS_W32_Entity *entity_free; }; //////////////////////////////// //~ rjf: Globals global OS_W32_State os_w32_state = {0}; //////////////////////////////// //~ rjf: File Info Conversion Helpers internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes); internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes); //////////////////////////////// //~ rjf: Time Conversion Helpers internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in); internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in); internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in); internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us); //////////////////////////////// //~ rjf: Entity Functions internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind); internal void os_w32_entity_release(OS_W32_Entity *entity); //////////////////////////////// //~ rjf: Thread Entry Point internal DWORD os_w32_thread_entry_point(void *ptr); #endif // OS_CORE_WIN32_H ================================================ FILE: src/os/gfx/generated/os_gfx.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 os_g_key_display_string_table[143] = { str8_lit_comp("Invalid Key"), str8_lit_comp("Escape"), str8_lit_comp("F1"), str8_lit_comp("F2"), str8_lit_comp("F3"), str8_lit_comp("F4"), str8_lit_comp("F5"), str8_lit_comp("F6"), str8_lit_comp("F7"), str8_lit_comp("F8"), str8_lit_comp("F9"), str8_lit_comp("F10"), str8_lit_comp("F11"), str8_lit_comp("F12"), str8_lit_comp("F13"), str8_lit_comp("F14"), str8_lit_comp("F15"), str8_lit_comp("F16"), str8_lit_comp("F17"), str8_lit_comp("F18"), str8_lit_comp("F19"), str8_lit_comp("F20"), str8_lit_comp("F21"), str8_lit_comp("F22"), str8_lit_comp("F23"), str8_lit_comp("F24"), str8_lit_comp("Tick"), str8_lit_comp("0"), str8_lit_comp("1"), str8_lit_comp("2"), str8_lit_comp("3"), str8_lit_comp("4"), str8_lit_comp("5"), str8_lit_comp("6"), str8_lit_comp("7"), str8_lit_comp("8"), str8_lit_comp("9"), str8_lit_comp("Minus"), str8_lit_comp("Equal"), str8_lit_comp("Backspace"), str8_lit_comp("Tab"), str8_lit_comp("Q"), str8_lit_comp("W"), str8_lit_comp("E"), str8_lit_comp("R"), str8_lit_comp("T"), str8_lit_comp("Y"), str8_lit_comp("U"), str8_lit_comp("I"), str8_lit_comp("O"), str8_lit_comp("P"), str8_lit_comp("Left Bracket"), str8_lit_comp("Right Bracket"), str8_lit_comp("Back Slash"), str8_lit_comp("Caps Lock"), str8_lit_comp("A"), str8_lit_comp("S"), str8_lit_comp("D"), str8_lit_comp("F"), str8_lit_comp("G"), str8_lit_comp("H"), str8_lit_comp("J"), str8_lit_comp("K"), str8_lit_comp("L"), str8_lit_comp("Semicolon"), str8_lit_comp("Quote"), str8_lit_comp("Return"), str8_lit_comp("Shift"), str8_lit_comp("Z"), str8_lit_comp("X"), str8_lit_comp("C"), str8_lit_comp("V"), str8_lit_comp("B"), str8_lit_comp("N"), str8_lit_comp("M"), str8_lit_comp("Comma"), str8_lit_comp("Period"), str8_lit_comp("Slash"), str8_lit_comp("Ctrl"), str8_lit_comp("Alt"), str8_lit_comp("Space"), str8_lit_comp("Menu"), str8_lit_comp("Scroll Lock"), str8_lit_comp("Pause"), str8_lit_comp("Insert"), str8_lit_comp("Home"), str8_lit_comp("Page Up"), str8_lit_comp("Delete"), str8_lit_comp("End"), str8_lit_comp("Page Down"), str8_lit_comp("Up"), str8_lit_comp("Left"), str8_lit_comp("Down"), str8_lit_comp("Right"), str8_lit_comp("Ex0"), str8_lit_comp("Ex1"), str8_lit_comp("Ex2"), str8_lit_comp("Ex3"), str8_lit_comp("Ex4"), str8_lit_comp("Ex5"), str8_lit_comp("Ex6"), str8_lit_comp("Ex7"), str8_lit_comp("Ex8"), str8_lit_comp("Ex9"), str8_lit_comp("Ex10"), str8_lit_comp("Ex11"), str8_lit_comp("Ex12"), str8_lit_comp("Ex13"), str8_lit_comp("Ex14"), str8_lit_comp("Ex15"), str8_lit_comp("Ex16"), str8_lit_comp("Ex17"), str8_lit_comp("Ex18"), str8_lit_comp("Ex19"), str8_lit_comp("Ex20"), str8_lit_comp("Ex21"), str8_lit_comp("Ex22"), str8_lit_comp("Ex23"), str8_lit_comp("Ex24"), str8_lit_comp("Ex25"), str8_lit_comp("Ex26"), str8_lit_comp("Ex27"), str8_lit_comp("Ex28"), str8_lit_comp("Ex29"), str8_lit_comp("Num Lock"), str8_lit_comp("Numpad Slash"), str8_lit_comp("Numpad Star"), str8_lit_comp("Numpad Minus"), str8_lit_comp("Numpad Plus"), str8_lit_comp("Numpad Period"), str8_lit_comp("Numpad 0"), str8_lit_comp("Numpad 1"), str8_lit_comp("Numpad 2"), str8_lit_comp("Numpad 3"), str8_lit_comp("Numpad 4"), str8_lit_comp("Numpad 5"), str8_lit_comp("Numpad 6"), str8_lit_comp("Numpad 7"), str8_lit_comp("Numpad 8"), str8_lit_comp("Numpad 9"), str8_lit_comp("Left Mouse Button"), str8_lit_comp("Middle Mouse Button"), str8_lit_comp("Right Mouse Button"), }; String8 os_g_key_cfg_string_table[143] = { str8_lit_comp("null"), str8_lit_comp("esc"), str8_lit_comp("f1"), str8_lit_comp("f2"), str8_lit_comp("f3"), str8_lit_comp("f4"), str8_lit_comp("f5"), str8_lit_comp("f6"), str8_lit_comp("f7"), str8_lit_comp("f8"), str8_lit_comp("f9"), str8_lit_comp("f10"), str8_lit_comp("f11"), str8_lit_comp("f12"), str8_lit_comp("f13"), str8_lit_comp("f14"), str8_lit_comp("f15"), str8_lit_comp("f16"), str8_lit_comp("f17"), str8_lit_comp("f18"), str8_lit_comp("f19"), str8_lit_comp("f20"), str8_lit_comp("f21"), str8_lit_comp("f22"), str8_lit_comp("f23"), str8_lit_comp("f24"), str8_lit_comp("tick"), str8_lit_comp("0"), str8_lit_comp("1"), str8_lit_comp("2"), str8_lit_comp("3"), str8_lit_comp("4"), str8_lit_comp("5"), str8_lit_comp("6"), str8_lit_comp("7"), str8_lit_comp("8"), str8_lit_comp("9"), str8_lit_comp("minus"), str8_lit_comp("equal"), str8_lit_comp("backspace"), str8_lit_comp("tab"), str8_lit_comp("q"), str8_lit_comp("w"), str8_lit_comp("e"), str8_lit_comp("r"), str8_lit_comp("t"), str8_lit_comp("y"), str8_lit_comp("u"), str8_lit_comp("i"), str8_lit_comp("o"), str8_lit_comp("p"), str8_lit_comp("left_bracket"), str8_lit_comp("right_bracket"), str8_lit_comp("backslash"), str8_lit_comp("caps_lock"), str8_lit_comp("a"), str8_lit_comp("s"), str8_lit_comp("d"), str8_lit_comp("f"), str8_lit_comp("g"), str8_lit_comp("h"), str8_lit_comp("j"), str8_lit_comp("k"), str8_lit_comp("l"), str8_lit_comp("semicolon"), str8_lit_comp("quote"), str8_lit_comp("return"), str8_lit_comp("shift"), str8_lit_comp("z"), str8_lit_comp("x"), str8_lit_comp("c"), str8_lit_comp("v"), str8_lit_comp("b"), str8_lit_comp("n"), str8_lit_comp("m"), str8_lit_comp("comma"), str8_lit_comp("period"), str8_lit_comp("slash"), str8_lit_comp("ctrl"), str8_lit_comp("alt"), str8_lit_comp("space"), str8_lit_comp("menu"), str8_lit_comp("scroll_lock"), str8_lit_comp("pause"), str8_lit_comp("insert"), str8_lit_comp("home"), str8_lit_comp("page_up"), str8_lit_comp("delete"), str8_lit_comp("end"), str8_lit_comp("page_down"), str8_lit_comp("up"), str8_lit_comp("left"), str8_lit_comp("down"), str8_lit_comp("right"), str8_lit_comp("ex0"), str8_lit_comp("ex1"), str8_lit_comp("ex2"), str8_lit_comp("ex3"), str8_lit_comp("ex4"), str8_lit_comp("ex5"), str8_lit_comp("ex6"), str8_lit_comp("ex7"), str8_lit_comp("ex8"), str8_lit_comp("ex9"), str8_lit_comp("ex10"), str8_lit_comp("ex11"), str8_lit_comp("ex12"), str8_lit_comp("ex13"), str8_lit_comp("ex14"), str8_lit_comp("ex15"), str8_lit_comp("ex16"), str8_lit_comp("ex17"), str8_lit_comp("ex18"), str8_lit_comp("ex19"), str8_lit_comp("ex20"), str8_lit_comp("ex21"), str8_lit_comp("ex22"), str8_lit_comp("ex23"), str8_lit_comp("ex24"), str8_lit_comp("ex25"), str8_lit_comp("ex26"), str8_lit_comp("ex27"), str8_lit_comp("ex28"), str8_lit_comp("ex29"), str8_lit_comp("num_lock"), str8_lit_comp("numpad_slash"), str8_lit_comp("numpad_star"), str8_lit_comp("numpad_minus"), str8_lit_comp("numpad_plus"), str8_lit_comp("numpad_period"), str8_lit_comp("numpad_0"), str8_lit_comp("numpad_1"), str8_lit_comp("numpad_2"), str8_lit_comp("numpad_3"), str8_lit_comp("numpad_4"), str8_lit_comp("numpad_5"), str8_lit_comp("numpad_6"), str8_lit_comp("numpad_7"), str8_lit_comp("numpad_8"), str8_lit_comp("numpad_9"), str8_lit_comp("left_mouse"), str8_lit_comp("middle_mouse"), str8_lit_comp("right_mouse"), }; C_LINKAGE_END ================================================ FILE: src/os/gfx/generated/os_gfx.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef OS_GFX_META_H #define OS_GFX_META_H typedef enum OS_Key { OS_Key_Null, OS_Key_Esc, OS_Key_F1, OS_Key_F2, OS_Key_F3, OS_Key_F4, OS_Key_F5, OS_Key_F6, OS_Key_F7, OS_Key_F8, OS_Key_F9, OS_Key_F10, OS_Key_F11, OS_Key_F12, OS_Key_F13, OS_Key_F14, OS_Key_F15, OS_Key_F16, OS_Key_F17, OS_Key_F18, OS_Key_F19, OS_Key_F20, OS_Key_F21, OS_Key_F22, OS_Key_F23, OS_Key_F24, OS_Key_Tick, OS_Key_0, OS_Key_1, OS_Key_2, OS_Key_3, OS_Key_4, OS_Key_5, OS_Key_6, OS_Key_7, OS_Key_8, OS_Key_9, OS_Key_Minus, OS_Key_Equal, OS_Key_Backspace, OS_Key_Tab, OS_Key_Q, OS_Key_W, OS_Key_E, OS_Key_R, OS_Key_T, OS_Key_Y, OS_Key_U, OS_Key_I, OS_Key_O, OS_Key_P, OS_Key_LeftBracket, OS_Key_RightBracket, OS_Key_BackSlash, OS_Key_CapsLock, OS_Key_A, OS_Key_S, OS_Key_D, OS_Key_F, OS_Key_G, OS_Key_H, OS_Key_J, OS_Key_K, OS_Key_L, OS_Key_Semicolon, OS_Key_Quote, OS_Key_Return, OS_Key_Shift, OS_Key_Z, OS_Key_X, OS_Key_C, OS_Key_V, OS_Key_B, OS_Key_N, OS_Key_M, OS_Key_Comma, OS_Key_Period, OS_Key_Slash, OS_Key_Ctrl, OS_Key_Alt, OS_Key_Space, OS_Key_Menu, OS_Key_ScrollLock, OS_Key_Pause, OS_Key_Insert, OS_Key_Home, OS_Key_PageUp, OS_Key_Delete, OS_Key_End, OS_Key_PageDown, OS_Key_Up, OS_Key_Left, OS_Key_Down, OS_Key_Right, OS_Key_Ex0, OS_Key_Ex1, OS_Key_Ex2, OS_Key_Ex3, OS_Key_Ex4, OS_Key_Ex5, OS_Key_Ex6, OS_Key_Ex7, OS_Key_Ex8, OS_Key_Ex9, OS_Key_Ex10, OS_Key_Ex11, OS_Key_Ex12, OS_Key_Ex13, OS_Key_Ex14, OS_Key_Ex15, OS_Key_Ex16, OS_Key_Ex17, OS_Key_Ex18, OS_Key_Ex19, OS_Key_Ex20, OS_Key_Ex21, OS_Key_Ex22, OS_Key_Ex23, OS_Key_Ex24, OS_Key_Ex25, OS_Key_Ex26, OS_Key_Ex27, OS_Key_Ex28, OS_Key_Ex29, OS_Key_NumLock, OS_Key_NumSlash, OS_Key_NumStar, OS_Key_NumMinus, OS_Key_NumPlus, OS_Key_NumPeriod, OS_Key_Num0, OS_Key_Num1, OS_Key_Num2, OS_Key_Num3, OS_Key_Num4, OS_Key_Num5, OS_Key_Num6, OS_Key_Num7, OS_Key_Num8, OS_Key_Num9, OS_Key_LeftMouseButton, OS_Key_MiddleMouseButton, OS_Key_RightMouseButton, OS_Key_COUNT, } OS_Key; C_LINKAGE_BEGIN extern String8 os_g_key_display_string_table[143]; extern String8 os_g_key_cfg_string_table[143]; C_LINKAGE_END #endif // OS_GFX_META_H ================================================ FILE: src/os/gfx/linux/os_gfx_linux.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Helpers internal OS_LNX_Window * os_lnx_window_from_x11window(Window window) { OS_LNX_Window *result = 0; for(OS_LNX_Window *w = os_lnx_gfx_state->first_window; w != 0; w = w->next) { if(w->window == window) { result = w; break; } } return result; } //////////////////////////////// //~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) internal void os_gfx_init(void) { //- rjf: initialize basics Arena *arena = arena_alloc(); os_lnx_gfx_state = push_array(arena, OS_LNX_GfxState, 1); os_lnx_gfx_state->arena = arena; os_lnx_gfx_state->display = XOpenDisplay(0); //- rjf: calculate atoms os_lnx_gfx_state->wm_delete_window_atom = XInternAtom(os_lnx_gfx_state->display, "WM_DELETE_WINDOW", 0); os_lnx_gfx_state->wm_sync_request_atom = XInternAtom(os_lnx_gfx_state->display, "_NET_WM_SYNC_REQUEST", 0); os_lnx_gfx_state->wm_sync_request_counter_atom = XInternAtom(os_lnx_gfx_state->display, "_NET_WM_SYNC_REQUEST_COUNTER", 0); //- rjf: open im os_lnx_gfx_state->xim = XOpenIM(os_lnx_gfx_state->display, 0, 0, 0); //- rjf: fill out gfx info os_lnx_gfx_state->gfx_info.double_click_time = 0.5f; os_lnx_gfx_state->gfx_info.caret_blink_time = 0.5f; os_lnx_gfx_state->gfx_info.default_refresh_rate = 60.f; //- rjf: fill out cursors { struct { OS_Cursor cursor; unsigned int id; } map[] = { {OS_Cursor_Pointer, XC_left_ptr}, {OS_Cursor_IBar, XC_xterm}, {OS_Cursor_LeftRight, XC_sb_h_double_arrow}, {OS_Cursor_UpDown, XC_sb_v_double_arrow}, {OS_Cursor_DownRight, XC_bottom_right_corner}, {OS_Cursor_UpRight, XC_top_right_corner}, {OS_Cursor_UpDownLeftRight, XC_fleur}, {OS_Cursor_HandPoint, XC_hand1}, {OS_Cursor_Disabled, XC_X_cursor}, }; for EachElement(idx, map) { os_lnx_gfx_state->cursors[map[idx].cursor] = XCreateFontCursor(os_lnx_gfx_state->display, map[idx].id); } } } //////////////////////////////// //~ rjf: @os_hooks Graphics System Info (Implemented Per-OS) internal OS_GfxInfo * os_get_gfx_info(void) { return &os_lnx_gfx_state->gfx_info; } //////////////////////////////// //~ rjf: @os_hooks Clipboards (Implemented Per-OS) internal void os_set_clipboard_text(String8 string) { } internal String8 os_get_clipboard_text(Arena *arena) { String8 result = {0}; return result; } //////////////////////////////// //~ rjf: @os_hooks Windows (Implemented Per-OS) internal OS_Handle os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title) { Vec2F32 resolution = dim_2f32(rect); //- rjf: allocate window OS_LNX_Window *w = os_lnx_gfx_state->free_window; if(w) { SLLStackPop(os_lnx_gfx_state->free_window); } else { w = push_array_no_zero(os_lnx_gfx_state->arena, OS_LNX_Window, 1); } MemoryZeroStruct(w); DLLPushBack(os_lnx_gfx_state->first_window, os_lnx_gfx_state->last_window, w); //- rjf: create window & equip with x11 info w->window = XCreateWindow(os_lnx_gfx_state->display, XDefaultRootWindow(os_lnx_gfx_state->display), 0, 0, resolution.x, resolution.y, 0, CopyFromParent, InputOutput, CopyFromParent, 0, 0); XSelectInput(os_lnx_gfx_state->display, w->window, ExposureMask| PointerMotionMask| ButtonPressMask| ButtonReleaseMask| KeyPressMask| KeyReleaseMask| FocusChangeMask); Atom protocols[] = { os_lnx_gfx_state->wm_delete_window_atom, os_lnx_gfx_state->wm_sync_request_atom, }; XSetWMProtocols(os_lnx_gfx_state->display, w->window, protocols, ArrayCount(protocols)); { XSyncValue initial_value; XSyncIntToValue(&initial_value, 0); w->counter_xid = XSyncCreateCounter(os_lnx_gfx_state->display, initial_value); } XChangeProperty(os_lnx_gfx_state->display, w->window, os_lnx_gfx_state->wm_sync_request_counter_atom, XA_CARDINAL, 32, PropModeReplace, (U8 *)&w->counter_xid, 1); //- rjf: create xic w->xic = XCreateIC(os_lnx_gfx_state->xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, w->window, XNFocusWindow, w->window, NULL); //- rjf: attach name Temp scratch = scratch_begin(0, 0); String8 title_copy = push_str8_copy(scratch.arena, title); XStoreName(os_lnx_gfx_state->display, w->window, (char *)title_copy.str); scratch_end(scratch); //- rjf: convert to handle & return OS_Handle handle = {(U64)w}; return handle; } internal void os_window_close(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return;} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; XDestroyWindow(os_lnx_gfx_state->display, w->window); } internal void os_window_set_title(OS_Handle handle, String8 title) { if(os_handle_match(handle, os_handle_zero())) {return;} Temp scratch = scratch_begin(0, 0); OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; String8 title_copy = push_str8_copy(scratch.arena, title); XStoreName(os_lnx_gfx_state->display, w->window, (char *)title_copy.str); scratch_end(scratch); } internal void os_window_first_paint(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return;} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; XMapWindow(os_lnx_gfx_state->display, w->window); } internal void os_window_focus(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return;} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; XSetInputFocus(os_lnx_gfx_state->display, w->window, RevertToNone, CurrentTime); } internal B32 os_window_is_focused(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return 0;} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; Window focused_window = 0; int revert_to = 0; XGetInputFocus(os_lnx_gfx_state->display, &focused_window, &revert_to); B32 result = (w->window == focused_window); return result; } internal B32 os_window_is_fullscreen(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return 0;} // TODO(rjf) return 0; } internal void os_window_set_fullscreen(OS_Handle handle, B32 fullscreen) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal B32 os_window_is_maximized(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return 0;} // TODO(rjf) return 0; } internal void os_window_set_maximized(OS_Handle handle, B32 maximized) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal B32 os_window_is_minimized(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return 0;} // TODO(rjf) return 0; } internal void os_window_set_minimized(OS_Handle handle, B32 minimized) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_bring_to_front(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_set_monitor(OS_Handle handle, OS_Handle monitor) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_clear_custom_border_data(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_push_custom_title_bar(OS_Handle handle, F32 thickness) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_push_custom_edges(OS_Handle handle, F32 thickness) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal void os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect) { if(os_handle_match(handle, os_handle_zero())) {return;} // TODO(rjf) } internal Rng2F32 os_rect_from_window(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return r2f32p(0, 0, 0, 0);} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; XWindowAttributes atts = {0}; Status s = XGetWindowAttributes(os_lnx_gfx_state->display, w->window, &atts); Rng2F32 result = r2f32p((F32)atts.x, (F32)atts.y, (F32)atts.x + (F32)atts.width, (F32)atts.y + (F32)atts.height); return result; } internal Rng2F32 os_client_rect_from_window(OS_Handle handle) { OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; XWindowAttributes atts = {0}; Status s = XGetWindowAttributes(os_lnx_gfx_state->display, w->window, &atts); Rng2F32 result = r2f32p(0, 0, (F32)atts.width, (F32)atts.height); return result; } internal F32 os_dpi_from_window(OS_Handle handle) { // TODO(rjf) return 96.f; } //////////////////////////////// //~ rjf: @os_hooks External Windows (Implemented Per-OS) internal OS_Handle os_focused_external_window(void) { OS_Handle result = {0}; // TODO(rjf) return result; } internal void os_focus_external_window(OS_Handle handle) { // TODO(rjf) } //////////////////////////////// //~ rjf: @os_hooks Monitors (Implemented Per-OS) internal OS_HandleArray os_push_monitors_array(Arena *arena) { OS_HandleArray result = {0}; // TODO(rjf) return result; } internal OS_Handle os_primary_monitor(void) { OS_Handle result = {0}; // TODO(rjf) return result; } internal OS_Handle os_monitor_from_window(OS_Handle window) { OS_Handle result = {0}; // TODO(rjf) return result; } internal String8 os_name_from_monitor(Arena *arena, OS_Handle monitor) { // TODO(rjf) return str8_zero(); } internal Vec2F32 os_dim_from_monitor(OS_Handle monitor) { // TODO(rjf) return v2f32(0, 0); } internal F32 os_dpi_from_monitor(OS_Handle monitor) { // TODO(rjf) return 96.f; } //////////////////////////////// //~ rjf: @os_hooks Events (Implemented Per-OS) internal void os_send_wakeup_event(void) { // TODO(rjf) } internal OS_EventList os_get_events(Arena *arena, B32 wait) { OS_EventList evts = {0}; for(;XPending(os_lnx_gfx_state->display) > 0 || (wait && evts.count == 0);) { XEvent evt = {0}; XNextEvent(os_lnx_gfx_state->display, &evt); B32 set_mouse_cursor = 0; switch(evt.type) { default:{}break; //- rjf: key presses/releases case KeyPress: case KeyRelease: { // rjf: determine flags OS_Modifiers modifiers = 0; if(evt.xkey.state & ShiftMask) { modifiers |= OS_Modifier_Shift; } if(evt.xkey.state & ControlMask) { modifiers |= OS_Modifier_Ctrl; } if(evt.xkey.state & Mod1Mask) { modifiers |= OS_Modifier_Alt; } // rjf: map keycode -> keysym & codepoint OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xkey.window); KeySym keysym = 0; U8 text[256] = {0}; U64 text_size = Xutf8LookupString(window->xic, &evt.xkey, (char *)text, sizeof(text), &keysym, 0); // rjf: map keysym -> OS_Key B32 is_right_sided = 0; OS_Key key = OS_Key_Null; switch(keysym) { default: { if(0){} else if(XK_F1 <= keysym && keysym <= XK_F24) { key = (OS_Key)(OS_Key_F1 + (keysym - XK_F1)); } else if('0' <= keysym && keysym <= '9') { key = OS_Key_0 + (keysym-'0'); } }break; case XK_Escape:{key = OS_Key_Esc;};break; case XK_BackSpace:{key = OS_Key_Backspace;}break; case XK_Delete:{key = OS_Key_Delete;}break; case XK_Return:{key = OS_Key_Return;}break; case XK_Pause:{key = OS_Key_Pause;}break; case XK_Tab:{key = OS_Key_Tab;}break; case XK_Left:{key = OS_Key_Left;}break; case XK_Right:{key = OS_Key_Right;}break; case XK_Up:{key = OS_Key_Up;}break; case XK_Down:{key = OS_Key_Down;}break; case XK_Home:{key = OS_Key_Home;}break; case XK_End:{key = OS_Key_End;}break; case XK_Page_Up:{key = OS_Key_PageUp;}break; case XK_Page_Down:{key = OS_Key_PageDown;}break; case XK_Alt_L:{ key = OS_Key_Alt; }break; case XK_Alt_R:{ key = OS_Key_Alt; is_right_sided = 1;}break; case XK_Shift_L:{ key = OS_Key_Shift; }break; case XK_Shift_R:{ key = OS_Key_Shift; is_right_sided = 1;}break; case XK_Control_L:{ key = OS_Key_Ctrl; }break; case XK_Control_R:{ key = OS_Key_Ctrl; is_right_sided = 1;}break; case '-':{key = OS_Key_Minus;}break; case '=':{key = OS_Key_Equal;}break; case '[':{key = OS_Key_LeftBracket;}break; case ']':{key = OS_Key_RightBracket;}break; case ';':{key = OS_Key_Semicolon;}break; case '\'':{key = OS_Key_Quote;}break; case '.':{key = OS_Key_Period;}break; case ',':{key = OS_Key_Comma;}break; case '/':{key = OS_Key_Slash;}break; case '\\':{key = OS_Key_BackSlash;}break; case '\t':{key = OS_Key_Tab;}break; case 'a':case 'A':{key = OS_Key_A;}break; case 'b':case 'B':{key = OS_Key_B;}break; case 'c':case 'C':{key = OS_Key_C;}break; case 'd':case 'D':{key = OS_Key_D;}break; case 'e':case 'E':{key = OS_Key_E;}break; case 'f':case 'F':{key = OS_Key_F;}break; case 'g':case 'G':{key = OS_Key_G;}break; case 'h':case 'H':{key = OS_Key_H;}break; case 'i':case 'I':{key = OS_Key_I;}break; case 'j':case 'J':{key = OS_Key_J;}break; case 'k':case 'K':{key = OS_Key_K;}break; case 'l':case 'L':{key = OS_Key_L;}break; case 'm':case 'M':{key = OS_Key_M;}break; case 'n':case 'N':{key = OS_Key_N;}break; case 'o':case 'O':{key = OS_Key_O;}break; case 'p':case 'P':{key = OS_Key_P;}break; case 'q':case 'Q':{key = OS_Key_Q;}break; case 'r':case 'R':{key = OS_Key_R;}break; case 's':case 'S':{key = OS_Key_S;}break; case 't':case 'T':{key = OS_Key_T;}break; case 'u':case 'U':{key = OS_Key_U;}break; case 'v':case 'V':{key = OS_Key_V;}break; case 'w':case 'W':{key = OS_Key_W;}break; case 'x':case 'X':{key = OS_Key_X;}break; case 'y':case 'Y':{key = OS_Key_Y;}break; case 'z':case 'Z':{key = OS_Key_Z;}break; case ' ':{key = OS_Key_Space;}break; } // rjf: push text event if(evt.type == KeyPress && text_size != 0) { for(U64 off = 0; off < text_size;) { UnicodeDecode decode = utf8_decode(text+off, text_size-off); if(decode.codepoint != 0 && (decode.codepoint >= 32 || decode.codepoint == '\t')) { OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_Text); e->window.u64[0] = (U64)window; e->character = decode.codepoint; } if(decode.inc == 0) { break; } off += decode.inc; } } // rjf: push key event { OS_Event *e = os_event_list_push_new(arena, &evts, evt.type == KeyPress ? OS_EventKind_Press : OS_EventKind_Release); e->window.u64[0] = (U64)window; e->modifiers = modifiers; e->key = key; e->right_sided = is_right_sided; } }break; //- rjf: mouse button presses/releases case ButtonPress: case ButtonRelease: { // rjf: determine flags OS_Modifiers modifiers = 0; if(evt.xbutton.state & ShiftMask) { modifiers |= OS_Modifier_Shift; } if(evt.xbutton.state & ControlMask) { modifiers |= OS_Modifier_Ctrl; } if(evt.xbutton.state & Mod1Mask) { modifiers |= OS_Modifier_Alt; } // rjf: map button -> OS_Key OS_Key key = OS_Key_Null; switch(evt.xbutton.button) { default:{}break; case Button1:{key = OS_Key_LeftMouseButton;}break; case Button2:{key = OS_Key_MiddleMouseButton;}break; case Button3:{key = OS_Key_RightMouseButton;}break; } // rjf: push event OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xbutton.window); if(key != OS_Key_Null) { OS_Event *e = os_event_list_push_new(arena, &evts, evt.type == ButtonPress ? OS_EventKind_Press : OS_EventKind_Release); e->window.u64[0] = (U64)window; e->modifiers = modifiers; e->key = key; e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y); } else if(evt.xbutton.button == Button4 || evt.xbutton.button == Button5) { OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_Scroll); e->window.u64[0] = (U64)window; e->modifiers = modifiers; e->delta = v2f32(0, evt.xbutton.button == Button4 ? -1.f : +1.f); e->pos = v2f32((F32)evt.xbutton.x, (F32)evt.xbutton.y); } }break; //- rjf: mouse motion case MotionNotify: { OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xclient.window); OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_MouseMove); e->window.u64[0] = (U64)window; e->pos.x = (F32)evt.xmotion.x; e->pos.y = (F32)evt.xmotion.y; set_mouse_cursor = 1; }break; //- rjf: window focus/unfocus case FocusIn: { }break; case FocusOut: { OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xfocus.window); OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_WindowLoseFocus); e->window.u64[0] = (U64)window; }break; //- rjf: client messages case ClientMessage: { if((Atom)evt.xclient.data.l[0] == os_lnx_gfx_state->wm_delete_window_atom) { OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xclient.window); OS_Event *e = os_event_list_push_new(arena, &evts, OS_EventKind_WindowClose); e->window.u64[0] = (U64)window; } else if((Atom)evt.xclient.data.l[0] == os_lnx_gfx_state->wm_sync_request_atom) { OS_LNX_Window *window = os_lnx_window_from_x11window(evt.xclient.window); if(window != 0) { window->counter_value = 0; window->counter_value |= evt.xclient.data.l[2]; window->counter_value |= (evt.xclient.data.l[3] << 32); XSyncValue value; XSyncIntToValue(&value, window->counter_value); XSyncSetCounter(os_lnx_gfx_state->display, window->counter_xid, value); } } }break; } if(set_mouse_cursor) { Window root_window = 0; Window child_window = 0; int root_rel_x = 0; int root_rel_y = 0; int child_rel_x = 0; int child_rel_y = 0; unsigned int mask = 0; if(XQueryPointer(os_lnx_gfx_state->display, XDefaultRootWindow(os_lnx_gfx_state->display), &root_window, &child_window, &root_rel_x, &root_rel_y, &child_rel_x, &child_rel_y, &mask)) { XDefineCursor(os_lnx_gfx_state->display, root_window, os_lnx_gfx_state->cursors[os_lnx_gfx_state->last_set_cursor]); XFlush(os_lnx_gfx_state->display); } } } return evts; } internal OS_Modifiers os_get_modifiers(void) { // TODO(rjf) return 0; } internal B32 os_key_is_down(OS_Key key) { // TODO(rjf) return 0; } internal Vec2F32 os_mouse_from_window(OS_Handle handle) { if(os_handle_match(handle, os_handle_zero())) {return v2f32(0, 0);} OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0]; Vec2F32 result = {0}; { Window root_window = 0; Window child_window = 0; int root_rel_x = 0; int root_rel_y = 0; int child_rel_x = 0; int child_rel_y = 0; unsigned int mask = 0; if(XQueryPointer(os_lnx_gfx_state->display, w->window, &root_window, &child_window, &root_rel_x, &root_rel_y, &child_rel_x, &child_rel_y, &mask)) { result.x = child_rel_x; result.y = child_rel_y; } } return result; } //////////////////////////////// //~ rjf: @os_hooks Cursors (Implemented Per-OS) internal void os_set_cursor(OS_Cursor cursor) { os_lnx_gfx_state->last_set_cursor = cursor; } //////////////////////////////// //~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS) internal void os_graphical_message(B32 error, String8 title, String8 message) { if(error) { fprintf(stderr, "[X] "); } fprintf(stderr, "%.*s\n", str8_varg(title)); fprintf(stderr, "%.*s\n\n", str8_varg(message)); } internal String8 os_graphical_pick_file(Arena *arena, String8 initial_path) { return str8_zero(); } //////////////////////////////// //~ rjf: @os_hooks Shell Operations internal void os_show_in_filesystem_ui(String8 path) { // TODO(rjf) } internal void os_open_in_browser(String8 url) { // TODO(rjf) } ================================================ FILE: src/os/gfx/linux/os_gfx_linux.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_LINUX_H #define OS_GFX_LINUX_H //////////////////////////////// //~ rjf: Includes #include #include #include #include #include #include //////////////////////////////// //~ rjf: Window State typedef struct OS_LNX_Window OS_LNX_Window; struct OS_LNX_Window { OS_LNX_Window *next; OS_LNX_Window *prev; Window window; XIC xic; XID counter_xid; U64 counter_value; }; //////////////////////////////// //~ rjf: State Bundle typedef struct OS_LNX_GfxState OS_LNX_GfxState; struct OS_LNX_GfxState { Arena *arena; Display *display; XIM xim; OS_LNX_Window *first_window; OS_LNX_Window *last_window; OS_LNX_Window *free_window; Atom wm_delete_window_atom; Atom wm_sync_request_atom; Atom wm_sync_request_counter_atom; Cursor cursors[OS_Cursor_COUNT]; OS_Cursor last_set_cursor; OS_GfxInfo gfx_info; }; //////////////////////////////// //~ rjf: Globals global OS_LNX_GfxState *os_lnx_gfx_state = 0; //////////////////////////////// //~ rjf: Helpers internal OS_LNX_Window *os_lnx_window_from_x11window(Window window); #endif // OS_GFX_LINUX_H ================================================ FILE: src/os/gfx/os_gfx.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "generated/os_gfx.meta.c" //////////////////////////////// //~ rjf: Event Functions (Helpers, Implemented Once) internal String8 os_string_from_event_kind(OS_EventKind kind) { String8 result = {0}; switch(kind) { case OS_EventKind_Null: case OS_EventKind_COUNT: {}break; case OS_EventKind_Press: {result = str8_lit("Press");}break; case OS_EventKind_Release: {result = str8_lit("Release");}break; case OS_EventKind_MouseMove: {result = str8_lit("MouseMove");}break; case OS_EventKind_Text: {result = str8_lit("Text");}break; case OS_EventKind_Scroll: {result = str8_lit("Scroll");}break; case OS_EventKind_WindowLoseFocus: {result = str8_lit("WindowLoseFocus");}break; case OS_EventKind_WindowClose: {result = str8_lit("WindowClose");}break; case OS_EventKind_FileDrop: {result = str8_lit("FileDrop");}break; case OS_EventKind_Wakeup: {result = str8_lit("Wakeup");}break; } return result; } internal String8List os_string_list_from_modifiers(Arena *arena, OS_Modifiers modifiers) { String8List result = {0}; if(modifiers & OS_Modifier_Ctrl) { str8_list_push(arena, &result, str8_lit("Ctrl")); } if(modifiers & OS_Modifier_Shift) { str8_list_push(arena, &result, str8_lit("Shift")); } if(modifiers & OS_Modifier_Alt) { str8_list_push(arena, &result, str8_lit("Alt")); } return result; } internal String8 os_string_from_modifiers_key(Arena *arena, OS_Modifiers modifiers, OS_Key key) { String8 result = {0}; if(key != OS_Key_Null) { Temp scratch = scratch_begin(&arena, 1); String8List mods = os_string_list_from_modifiers(scratch.arena, modifiers); String8 key_string = os_g_key_display_string_table[key]; str8_list_push(scratch.arena, &mods, key_string); StringJoin join = {0}; join.sep = str8_lit(" + "); result = str8_list_join(arena, &mods, &join); scratch_end(scratch); } return result; } internal U32 os_codepoint_from_modifiers_and_key(OS_Modifiers modifiers, OS_Key key) { U32 result = 0; // rjf: special-case map local_persist read_only struct {U32 character; OS_Key key; OS_Modifiers modifiers;} map[] = { {'!', OS_Key_1, OS_Modifier_Shift}, {'@', OS_Key_2, OS_Modifier_Shift}, {'#', OS_Key_3, OS_Modifier_Shift}, {'$', OS_Key_4, OS_Modifier_Shift}, {'%', OS_Key_5, OS_Modifier_Shift}, {'^', OS_Key_6, OS_Modifier_Shift}, {'&', OS_Key_7, OS_Modifier_Shift}, {'*', OS_Key_8, OS_Modifier_Shift}, {'(', OS_Key_9, OS_Modifier_Shift}, {')', OS_Key_0, OS_Modifier_Shift}, {'_', OS_Key_Minus, OS_Modifier_Shift}, {'_', OS_Key_Minus, OS_Modifier_Shift}, {'-', OS_Key_Minus, 0}, {'=', OS_Key_Equal, 0}, {'+', OS_Key_Equal, OS_Modifier_Shift}, {'`', OS_Key_Tick, 0}, {'~', OS_Key_Tick, OS_Modifier_Shift}, {'[', OS_Key_LeftBracket, 0}, {']', OS_Key_RightBracket, 0}, {'{', OS_Key_LeftBracket, OS_Modifier_Shift}, {'}', OS_Key_RightBracket, OS_Modifier_Shift}, {'\\', OS_Key_BackSlash, 0}, {'|', OS_Key_BackSlash, OS_Modifier_Shift}, {';', OS_Key_Semicolon, 0}, {':', OS_Key_Semicolon, OS_Modifier_Shift}, {'\'', OS_Key_Quote, 0}, {'"', OS_Key_Quote, OS_Modifier_Shift}, {'.', OS_Key_Period, 0}, {',', OS_Key_Comma, 0}, {'<', OS_Key_Period, OS_Modifier_Shift}, {'>', OS_Key_Comma, OS_Modifier_Shift}, {'/', OS_Key_Slash, 0}, {'?', OS_Key_Slash, OS_Modifier_Shift}, {'a', OS_Key_A, 0}, {'b', OS_Key_B, 0}, {'c', OS_Key_C, 0}, {'d', OS_Key_D, 0}, {'e', OS_Key_E, 0}, {'f', OS_Key_F, 0}, {'g', OS_Key_G, 0}, {'h', OS_Key_H, 0}, {'i', OS_Key_I, 0}, {'j', OS_Key_J, 0}, {'k', OS_Key_K, 0}, {'l', OS_Key_L, 0}, {'m', OS_Key_M, 0}, {'n', OS_Key_N, 0}, {'o', OS_Key_O, 0}, {'p', OS_Key_P, 0}, {'q', OS_Key_Q, 0}, {'r', OS_Key_R, 0}, {'s', OS_Key_S, 0}, {'t', OS_Key_T, 0}, {'u', OS_Key_U, 0}, {'v', OS_Key_V, 0}, {'w', OS_Key_W, 0}, {'x', OS_Key_X, 0}, {'y', OS_Key_Y, 0}, {'z', OS_Key_Z, 0}, {'A', OS_Key_A, OS_Modifier_Shift}, {'B', OS_Key_B, OS_Modifier_Shift}, {'C', OS_Key_C, OS_Modifier_Shift}, {'D', OS_Key_D, OS_Modifier_Shift}, {'E', OS_Key_E, OS_Modifier_Shift}, {'F', OS_Key_F, OS_Modifier_Shift}, {'G', OS_Key_G, OS_Modifier_Shift}, {'H', OS_Key_H, OS_Modifier_Shift}, {'I', OS_Key_I, OS_Modifier_Shift}, {'J', OS_Key_J, OS_Modifier_Shift}, {'K', OS_Key_K, OS_Modifier_Shift}, {'L', OS_Key_L, OS_Modifier_Shift}, {'M', OS_Key_M, OS_Modifier_Shift}, {'N', OS_Key_N, OS_Modifier_Shift}, {'O', OS_Key_O, OS_Modifier_Shift}, {'P', OS_Key_P, OS_Modifier_Shift}, {'Q', OS_Key_Q, OS_Modifier_Shift}, {'R', OS_Key_R, OS_Modifier_Shift}, {'S', OS_Key_S, OS_Modifier_Shift}, {'T', OS_Key_T, OS_Modifier_Shift}, {'U', OS_Key_U, OS_Modifier_Shift}, {'V', OS_Key_V, OS_Modifier_Shift}, {'W', OS_Key_W, OS_Modifier_Shift}, {'X', OS_Key_X, OS_Modifier_Shift}, {'Y', OS_Key_Y, OS_Modifier_Shift}, {'Z', OS_Key_Z, OS_Modifier_Shift}, {' ', OS_Key_Space, 0}, }; // rjf: check numeric if(OS_Key_0 <= key && key <= OS_Key_9) { result = '0' + (key - OS_Key_0); } // rjf: check special-case map for(U64 idx = 0; idx < ArrayCount(map); idx += 1) { if(map[idx].key == key && map[idx].modifiers == modifiers) { result = map[idx].character; break; } } return result; } internal void os_eat_event(OS_EventList *events, OS_Event *event) { DLLRemove(events->first, events->last, event); events->count -= 1; } internal B32 os_key_press(OS_EventList *events, OS_Handle window, OS_Modifiers modifiers, OS_Key key) { B32 result = 0; for(OS_Event *event = events->first; event != 0; event = event->next) { if((os_handle_match(event->window, window) || os_handle_match(window, os_handle_zero())) && event->kind == OS_EventKind_Press && event->key == key && event->modifiers == modifiers) { result = 1; os_eat_event(events, event); break; } } return result; } internal B32 os_key_release(OS_EventList *events, OS_Handle window, OS_Modifiers modifiers, OS_Key key) { B32 result = 0; for(OS_Event *event = events->first; event != 0; event = event->next) { if((os_handle_match(event->window, window) || os_handle_match(window, os_handle_zero())) && event->kind == OS_EventKind_Release && event->key == key && event->modifiers == modifiers) { result = 1; os_eat_event(events, event); break; } } return result; } internal B32 os_text(OS_EventList *events, OS_Handle window, U32 character) { B32 result = 0; for(OS_Event *event = events->first; event != 0; event = event->next) { if((os_handle_match(event->window, window) || os_handle_match(window, os_handle_zero())) && event->kind == OS_EventKind_Text && event->character == character) { result = 1; os_eat_event(events, event); break; } } return result; } internal OS_EventList os_event_list_copy(Arena *arena, OS_EventList *src) { OS_EventList dst = {0}; for(OS_Event *s = src->first; s != 0; s = s->next) { OS_Event *d = push_array(arena, OS_Event, 1); MemoryCopyStruct(d, s); d->strings = str8_list_copy(arena, &s->strings); DLLPushBack(dst.first, dst.last, d); dst.count += 1; } return dst; } internal void os_event_list_concat_in_place(OS_EventList *dst, OS_EventList *to_push) { if(dst->last && to_push->first) { dst->last->next = to_push->first; to_push->first->prev = dst->last; dst->last = to_push->last; dst->count += to_push->count; } else if(!dst->last && to_push->first) { MemoryCopyStruct(dst, to_push); } MemoryZeroStruct(to_push); } internal OS_Event * os_event_list_push_new(Arena *arena, OS_EventList *evts, OS_EventKind kind) { OS_Event *evt = push_array(arena, OS_Event, 1); DLLPushBack(evts->first, evts->last, evt); evts->count += 1; evt->timestamp_us = os_now_microseconds(); evt->kind = kind; return evt; } ================================================ FILE: src/os/gfx/os_gfx.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_H #define OS_GFX_H //////////////////////////////// //~ rjf: Graphics System Info typedef struct OS_GfxInfo OS_GfxInfo; struct OS_GfxInfo { F32 double_click_time; F32 caret_blink_time; F32 default_refresh_rate; }; //////////////////////////////// //~ rjf: Window Types typedef U32 OS_WindowFlags; enum { OS_WindowFlag_CustomBorder = (1<<0), OS_WindowFlag_UseDefaultPosition = (1<<1), }; //////////////////////////////// //~ rjf: Cursor Types typedef enum OS_Cursor { OS_Cursor_Pointer, OS_Cursor_IBar, OS_Cursor_LeftRight, OS_Cursor_UpDown, OS_Cursor_DownRight, OS_Cursor_UpRight, OS_Cursor_UpDownLeftRight, OS_Cursor_HandPoint, OS_Cursor_Disabled, OS_Cursor_COUNT, } OS_Cursor; //////////////////////////////// //~ rjf: Generated Code #include "os/gfx/generated/os_gfx.meta.h" //////////////////////////////// //~ rjf: Event Types typedef enum OS_EventKind { OS_EventKind_Null, OS_EventKind_Press, OS_EventKind_Release, OS_EventKind_MouseMove, OS_EventKind_Text, OS_EventKind_Scroll, OS_EventKind_WindowLoseFocus, OS_EventKind_WindowClose, OS_EventKind_FileDrop, OS_EventKind_Wakeup, OS_EventKind_COUNT } OS_EventKind; typedef U32 OS_Modifiers; enum { OS_Modifier_Ctrl = (1<<0), OS_Modifier_Shift = (1<<1), OS_Modifier_Alt = (1<<2), }; typedef struct OS_Event OS_Event; struct OS_Event { OS_Event *next; OS_Event *prev; U64 timestamp_us; OS_Handle window; OS_EventKind kind; OS_Modifiers modifiers; OS_Key key; B32 is_repeat; B32 right_sided; U32 character; U32 repeat_count; Vec2F32 pos; Vec2F32 delta; String8List strings; }; typedef struct OS_EventList OS_EventList; struct OS_EventList { U64 count; OS_Event *first; OS_Event *last; }; //////////////////////////////// //~ rjf: Application-Defined Frame Hook Forward Declaration internal B32 frame(void); //////////////////////////////// //~ rjf: Event Functions (Helpers, Implemented Once) internal String8 os_string_from_event_kind(OS_EventKind kind); internal String8List os_string_list_from_modifiers(Arena *arena, OS_Modifiers flags); internal String8 os_string_from_modifiers_key(Arena *arena, OS_Modifiers modifiers, OS_Key key); internal U32 os_codepoint_from_modifiers_and_key(OS_Modifiers flags, OS_Key key); internal void os_eat_event(OS_EventList *events, OS_Event *event); internal B32 os_key_press(OS_EventList *events, OS_Handle window, OS_Modifiers modifiers, OS_Key key); internal B32 os_key_release(OS_EventList *events, OS_Handle window, OS_Modifiers modifiers, OS_Key key); internal B32 os_text(OS_EventList *events, OS_Handle window, U32 character); internal OS_EventList os_event_list_copy(Arena *arena, OS_EventList *src); internal void os_event_list_concat_in_place(OS_EventList *dst, OS_EventList *to_push); internal OS_Event *os_event_list_push_new(Arena *arena, OS_EventList *evts, OS_EventKind kind); //////////////////////////////// //~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) internal void os_gfx_init(void); //////////////////////////////// //~ rjf: @os_hooks Graphics System Info (Implemented Per-OS) internal OS_GfxInfo *os_get_gfx_info(void); //////////////////////////////// //~ rjf: @os_hooks Clipboards (Implemented Per-OS) internal void os_set_clipboard_text(String8 string); internal String8 os_get_clipboard_text(Arena *arena); //////////////////////////////// //~ rjf: @os_hooks Windows (Implemented Per-OS) internal OS_Handle os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title); internal void os_window_close(OS_Handle window); internal void os_window_set_title(OS_Handle window, String8 title); internal void os_window_first_paint(OS_Handle window); internal void os_window_focus(OS_Handle window); internal B32 os_window_is_focused(OS_Handle window); internal B32 os_window_is_fullscreen(OS_Handle window); internal void os_window_set_fullscreen(OS_Handle window, B32 fullscreen); internal B32 os_window_is_maximized(OS_Handle window); internal void os_window_set_maximized(OS_Handle window, B32 maximized); internal B32 os_window_is_minimized(OS_Handle window); internal void os_window_set_minimized(OS_Handle window, B32 minimized); internal void os_window_bring_to_front(OS_Handle window); internal void os_window_set_monitor(OS_Handle window, OS_Handle monitor); internal void os_window_clear_custom_border_data(OS_Handle handle); internal void os_window_push_custom_title_bar(OS_Handle handle, F32 thickness); internal void os_window_push_custom_edges(OS_Handle handle, F32 thickness); internal void os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect); internal Rng2F32 os_rect_from_window(OS_Handle window); internal Rng2F32 os_client_rect_from_window(OS_Handle window); internal F32 os_dpi_from_window(OS_Handle window); //////////////////////////////// //~ rjf: @os_hooks External Windows (Implemented Per-OS) internal OS_Handle os_focused_external_window(void); internal void os_focus_external_window(OS_Handle handle); //////////////////////////////// //~ rjf: @os_hooks Monitors (Implemented Per-OS) internal OS_HandleArray os_push_monitors_array(Arena *arena); internal OS_Handle os_primary_monitor(void); internal OS_Handle os_monitor_from_window(OS_Handle window); internal String8 os_name_from_monitor(Arena *arena, OS_Handle monitor); internal Vec2F32 os_dim_from_monitor(OS_Handle monitor); internal F32 os_dpi_from_monitor(OS_Handle monitor); //////////////////////////////// //~ rjf: @os_hooks Events (Implemented Per-OS) internal void os_send_wakeup_event(void); internal OS_EventList os_get_events(Arena *arena, B32 wait); internal OS_Modifiers os_get_modifiers(void); internal B32 os_key_is_down(OS_Key key); internal Vec2F32 os_mouse_from_window(OS_Handle window); //////////////////////////////// //~ rjf: @os_hooks Cursors (Implemented Per-OS) internal void os_set_cursor(OS_Cursor cursor); //////////////////////////////// //~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS) internal void os_graphical_message(B32 error, String8 title, String8 message); internal String8 os_graphical_pick_file(Arena *arena, String8 initial_path); //////////////////////////////// //~ rjf: @os_hooks Shell Operations internal void os_show_in_filesystem_ui(String8 path); internal void os_open_in_browser(String8 url); #endif // OS_GFX_H ================================================ FILE: src/os/gfx/os_gfx.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Tables @table(name, display_string, cfg_string) OS_KeyTable: { {Null "Invalid Key" "null" } {Esc "Escape" "esc" } {F1 "F1" "f1" } {F2 "F2" "f2" } {F3 "F3" "f3" } {F4 "F4" "f4" } {F5 "F5" "f5" } {F6 "F6" "f6" } {F7 "F7" "f7" } {F8 "F8" "f8" } {F9 "F9" "f9" } {F10 "F10" "f10" } {F11 "F11" "f11" } {F12 "F12" "f12" } {F13 "F13" "f13" } {F14 "F14" "f14" } {F15 "F15" "f15" } {F16 "F16" "f16" } {F17 "F17" "f17" } {F18 "F18" "f18" } {F19 "F19" "f19" } {F20 "F20" "f20" } {F21 "F21" "f21" } {F22 "F22" "f22" } {F23 "F23" "f23" } {F24 "F24" "f24" } {Tick "Tick" "tick" } {0 "0" "0" } {1 "1" "1" } {2 "2" "2" } {3 "3" "3" } {4 "4" "4" } {5 "5" "5" } {6 "6" "6" } {7 "7" "7" } {8 "8" "8" } {9 "9" "9" } {Minus "Minus" "minus" } {Equal "Equal" "equal" } {Backspace "Backspace" "backspace" } {Tab "Tab" "tab" } {Q "Q" "q" } {W "W" "w" } {E "E" "e" } {R "R" "r" } {T "T" "t" } {Y "Y" "y" } {U "U" "u" } {I "I" "i" } {O "O" "o" } {P "P" "p" } {LeftBracket "Left Bracket" "left_bracket" } {RightBracket "Right Bracket" "right_bracket" } {BackSlash "Back Slash" "backslash" } {CapsLock "Caps Lock" "caps_lock" } {A "A" "a" } {S "S" "s" } {D "D" "d" } {F "F" "f" } {G "G" "g" } {H "H" "h" } {J "J" "j" } {K "K" "k" } {L "L" "l" } {Semicolon "Semicolon" "semicolon" } {Quote "Quote" "quote" } {Return "Return" "return" } {Shift "Shift" "shift" } {Z "Z" "z" } {X "X" "x" } {C "C" "c" } {V "V" "v" } {B "B" "b" } {N "N" "n" } {M "M" "m" } {Comma "Comma" "comma" } {Period "Period" "period" } {Slash "Slash" "slash" } {Ctrl "Ctrl" "ctrl" } {Alt "Alt" "alt" } {Space "Space" "space" } {Menu "Menu" "menu" } {ScrollLock "Scroll Lock" "scroll_lock" } {Pause "Pause" "pause" } {Insert "Insert" "insert" } {Home "Home" "home" } {PageUp "Page Up" "page_up" } {Delete "Delete" "delete" } {End "End" "end" } {PageDown "Page Down" "page_down" } {Up "Up" "up" } {Left "Left" "left" } {Down "Down" "down" } {Right "Right" "right" } {Ex0 "Ex0" "ex0" } {Ex1 "Ex1" "ex1" } {Ex2 "Ex2" "ex2" } {Ex3 "Ex3" "ex3" } {Ex4 "Ex4" "ex4" } {Ex5 "Ex5" "ex5" } {Ex6 "Ex6" "ex6" } {Ex7 "Ex7" "ex7" } {Ex8 "Ex8" "ex8" } {Ex9 "Ex9" "ex9" } {Ex10 "Ex10" "ex10" } {Ex11 "Ex11" "ex11" } {Ex12 "Ex12" "ex12" } {Ex13 "Ex13" "ex13" } {Ex14 "Ex14" "ex14" } {Ex15 "Ex15" "ex15" } {Ex16 "Ex16" "ex16" } {Ex17 "Ex17" "ex17" } {Ex18 "Ex18" "ex18" } {Ex19 "Ex19" "ex19" } {Ex20 "Ex20" "ex20" } {Ex21 "Ex21" "ex21" } {Ex22 "Ex22" "ex22" } {Ex23 "Ex23" "ex23" } {Ex24 "Ex24" "ex24" } {Ex25 "Ex25" "ex25" } {Ex26 "Ex26" "ex26" } {Ex27 "Ex27" "ex27" } {Ex28 "Ex28" "ex28" } {Ex29 "Ex29" "ex29" } {NumLock "Num Lock" "num_lock" } {NumSlash "Numpad Slash" "numpad_slash" } {NumStar "Numpad Star" "numpad_star" } {NumMinus "Numpad Minus" "numpad_minus" } {NumPlus "Numpad Plus" "numpad_plus" } {NumPeriod "Numpad Period" "numpad_period" } {Num0 "Numpad 0" "numpad_0" } {Num1 "Numpad 1" "numpad_1" } {Num2 "Numpad 2" "numpad_2" } {Num3 "Numpad 3" "numpad_3" } {Num4 "Numpad 4" "numpad_4" } {Num5 "Numpad 5" "numpad_5" } {Num6 "Numpad 6" "numpad_6" } {Num7 "Numpad 7" "numpad_7" } {Num8 "Numpad 8" "numpad_8" } {Num9 "Numpad 9" "numpad_9" } {LeftMouseButton "Left Mouse Button" "left_mouse" } {MiddleMouseButton "Middle Mouse Button" "middle_mouse" } {RightMouseButton "Right Mouse Button" "right_mouse" } } //////////////////////////////// //~ rjf: Generators @enum OS_Key: { @expand(OS_KeyTable a) `$(a.name)`, COUNT, } @data(String8) os_g_key_display_string_table: { @expand(OS_KeyTable a) `str8_lit_comp("$(a.display_string)")`; } @data(String8) os_g_key_cfg_string_table: { @expand(OS_KeyTable a) `str8_lit_comp("$(a.cfg_string)")`; } ================================================ FILE: src/os/gfx/stub/os_gfx_stub.c ================================================ //////////////////////////////// //~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) internal void os_gfx_init(void) { } //////////////////////////////// //~ rjf: @os_hooks Graphics System Info (Implemented Per-OS) internal OS_GfxInfo * os_get_gfx_info(void) { local_persist OS_GfxInfo g = {0}; return &g; } //////////////////////////////// //~ rjf: @os_hooks Clipboards (Implemented Per-OS) internal void os_set_clipboard_text(String8 string) { } internal String8 os_get_clipboard_text(Arena *arena) { return str8_zero(); } //////////////////////////////// //~ rjf: @os_hooks Windows (Implemented Per-OS) internal OS_Handle os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title) { OS_Handle handle = {1}; return handle; } internal void os_window_close(OS_Handle window) { } internal void os_window_set_title(OS_Handle window, String8 title) { } internal void os_window_first_paint(OS_Handle window) { } internal void os_window_focus(OS_Handle window) { } internal B32 os_window_is_focused(OS_Handle window) { return 0; } internal B32 os_window_is_fullscreen(OS_Handle window) { return 0; } internal void os_window_set_fullscreen(OS_Handle window, B32 fullscreen) { } internal B32 os_window_is_maximized(OS_Handle window) { return 0; } internal void os_window_set_maximized(OS_Handle window, B32 maximized) { } internal B32 os_window_is_minimized(OS_Handle window) { return 0; } internal void os_window_set_minimized(OS_Handle window, B32 minimized) { } internal void os_window_bring_to_front(OS_Handle window) { } internal void os_window_set_monitor(OS_Handle window, OS_Handle monitor) { } internal void os_window_clear_custom_border_data(OS_Handle handle) { } internal void os_window_push_custom_title_bar(OS_Handle handle, F32 thickness) { } internal void os_window_push_custom_edges(OS_Handle handle, F32 thickness) { } internal void os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect) { } internal Rng2F32 os_rect_from_window(OS_Handle window) { Rng2F32 rect = r2f32(v2f32(0, 0), v2f32(500, 500)); return rect; } internal Rng2F32 os_client_rect_from_window(OS_Handle window) { Rng2F32 rect = r2f32(v2f32(0, 0), v2f32(500, 500)); return rect; } internal F32 os_dpi_from_window(OS_Handle window) { return 96.f; } //////////////////////////////// //~ rjf: @os_hooks External Windows (Implemented Per-OS) internal OS_Handle os_focused_external_window(void) { OS_Handle result = {0}; // TODO(rjf) return result; } internal void os_focus_external_window(OS_Handle handle) { // TODO(rjf) } //////////////////////////////// //~ rjf: @os_hooks Monitors (Implemented Per-OS) internal OS_HandleArray os_push_monitors_array(Arena *arena) { OS_HandleArray arr = {0}; return arr; } internal OS_Handle os_primary_monitor(void) { OS_Handle handle = {1}; return handle; } internal OS_Handle os_monitor_from_window(OS_Handle window) { OS_Handle handle = {1}; return handle; } internal String8 os_name_from_monitor(Arena *arena, OS_Handle monitor) { return str8_zero(); } internal Vec2F32 os_dim_from_monitor(OS_Handle monitor) { Vec2F32 v = v2f32(1000, 1000); return v; } internal F32 os_dpi_from_monitor(OS_Handle monitor) { return 96.f; } //////////////////////////////// //~ rjf: @os_hooks Events (Implemented Per-OS) internal void os_send_wakeup_event(void) { } internal OS_EventList os_get_events(Arena *arena, B32 wait) { OS_EventList evts = {0}; return evts; } internal OS_Modifiers os_get_modifiers(void) { OS_Modifiers f = 0; return f; } internal B32 os_key_is_down(OS_Key key) { return 0; } internal Vec2F32 os_mouse_from_window(OS_Handle window) { return v2f32(0, 0); } //////////////////////////////// //~ rjf: @os_hooks Cursors (Implemented Per-OS) internal void os_set_cursor(OS_Cursor cursor) { } //////////////////////////////// //~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS) internal void os_graphical_message(B32 error, String8 title, String8 message) { } internal String8 os_graphical_pick_file(Arena *arena, String8 initial_path) { return str8_zero(); } //////////////////////////////// //~ rjf: @os_hooks Shell Operations internal void os_show_in_filesystem_ui(String8 path) { } internal void os_open_in_browser(String8 url) { } ================================================ FILE: src/os/gfx/stub/os_gfx_stub.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_STUB_H #define OS_GFX_STUB_H #endif // OS_GFX_STUB_H ================================================ FILE: src/os/gfx/win32/os_gfx_win32.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Modern Windows SDK Functions // // (We must dynamically link to them, since they can be missing in older SDKs) typedef BOOL w32_SetProcessDpiAwarenessContext_Type(void* value); typedef UINT w32_GetDpiForWindow_Type(HWND hwnd); typedef HRESULT w32_GetDpiForMonitor_Type(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY); typedef int w32_GetSystemMetricsForDpi_Type(int nIndex, UINT dpi); #define w32_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((void*)-4) global w32_GetDpiForWindow_Type *w32_GetDpiForWindow_func = 0; global w32_GetDpiForMonitor_Type *w32_GetDpiForMonitor_func = 0; global w32_GetSystemMetricsForDpi_Type *w32_GetSystemMetricsForDpi_func = 0; //////////////////////////////// //~ rjf: Basic Helpers internal Rng2F32 os_w32_rng2f32_from_rect(RECT rect) { Rng2F32 r = {0}; r.x0 = (F32)rect.left; r.x1 = (F32)rect.right; r.y0 = (F32)rect.top; r.y1 = (F32)rect.bottom; return r; } //////////////////////////////// //~ rjf: Windows internal OS_Handle os_w32_handle_from_window(OS_W32_Window *window) { OS_Handle handle = {(U64)window}; return handle; } internal OS_W32_Window * os_w32_window_from_handle(OS_Handle handle) { OS_W32_Window *window = (OS_W32_Window *)handle.u64[0]; return window; } internal OS_W32_Window * os_w32_window_from_hwnd(HWND hwnd) { OS_W32_Window *result = 0; for(OS_W32_Window *w = os_w32_gfx_state->first_window; w; w = w->next) { if(w->hwnd == hwnd) { result = w; break; } } return result; } internal HWND os_w32_hwnd_from_window(OS_W32_Window *window) { return window->hwnd; } internal OS_W32_Window * os_w32_window_alloc(void) { OS_W32_Window *result = os_w32_gfx_state->free_window; if(result) { SLLStackPop(os_w32_gfx_state->free_window); } else { result = push_array_no_zero(os_w32_gfx_state->arena, OS_W32_Window, 1); } MemoryZeroStruct(result); if(result) { DLLPushBack(os_w32_gfx_state->first_window, os_w32_gfx_state->last_window, result); } result->last_window_placement.length = sizeof(WINDOWPLACEMENT); return result; } internal void os_w32_window_release(OS_W32_Window *window) { if(window->paint_arena != 0) { arena_release(window->paint_arena); } ReleaseDC(window->hwnd, window->hdc); DestroyWindow(window->hwnd); DLLRemove(os_w32_gfx_state->first_window, os_w32_gfx_state->last_window, window); SLLStackPush(os_w32_gfx_state->free_window, window); } internal OS_Event * os_w32_push_event(OS_EventKind kind, OS_W32_Window *window) { OS_Event *result = os_event_list_push_new(os_w32_event_arena, &os_w32_event_list, kind); result->window = os_w32_handle_from_window(window); result->modifiers = os_get_modifiers(); return result; } internal OS_Key os_w32_os_key_from_vkey(WPARAM vkey) { local_persist B32 first = 1; local_persist OS_Key key_table[256]; if (first){ first = 0; MemoryZeroArray(key_table); key_table[(unsigned int)'A'] = OS_Key_A; key_table[(unsigned int)'B'] = OS_Key_B; key_table[(unsigned int)'C'] = OS_Key_C; key_table[(unsigned int)'D'] = OS_Key_D; key_table[(unsigned int)'E'] = OS_Key_E; key_table[(unsigned int)'F'] = OS_Key_F; key_table[(unsigned int)'G'] = OS_Key_G; key_table[(unsigned int)'H'] = OS_Key_H; key_table[(unsigned int)'I'] = OS_Key_I; key_table[(unsigned int)'J'] = OS_Key_J; key_table[(unsigned int)'K'] = OS_Key_K; key_table[(unsigned int)'L'] = OS_Key_L; key_table[(unsigned int)'M'] = OS_Key_M; key_table[(unsigned int)'N'] = OS_Key_N; key_table[(unsigned int)'O'] = OS_Key_O; key_table[(unsigned int)'P'] = OS_Key_P; key_table[(unsigned int)'Q'] = OS_Key_Q; key_table[(unsigned int)'R'] = OS_Key_R; key_table[(unsigned int)'S'] = OS_Key_S; key_table[(unsigned int)'T'] = OS_Key_T; key_table[(unsigned int)'U'] = OS_Key_U; key_table[(unsigned int)'V'] = OS_Key_V; key_table[(unsigned int)'W'] = OS_Key_W; key_table[(unsigned int)'X'] = OS_Key_X; key_table[(unsigned int)'Y'] = OS_Key_Y; key_table[(unsigned int)'Z'] = OS_Key_Z; for (U64 i = '0', j = OS_Key_0; i <= '9'; i += 1, j += 1){ key_table[i] = (OS_Key)j; } for (U64 i = VK_NUMPAD0, j = OS_Key_0; i <= VK_NUMPAD9; i += 1, j += 1){ key_table[i] = (OS_Key)j; } for (U64 i = VK_F1, j = OS_Key_F1; i <= VK_F24; i += 1, j += 1){ key_table[i] = (OS_Key)j; } key_table[VK_SPACE] = OS_Key_Space; key_table[VK_OEM_3] = OS_Key_Tick; key_table[VK_OEM_MINUS] = OS_Key_Minus; key_table[VK_OEM_PLUS] = OS_Key_Equal; key_table[VK_OEM_4] = OS_Key_LeftBracket; key_table[VK_OEM_6] = OS_Key_RightBracket; key_table[VK_OEM_1] = OS_Key_Semicolon; key_table[VK_OEM_7] = OS_Key_Quote; key_table[VK_OEM_COMMA] = OS_Key_Comma; key_table[VK_OEM_PERIOD]= OS_Key_Period; key_table[VK_OEM_2] = OS_Key_Slash; key_table[VK_OEM_5] = OS_Key_BackSlash; key_table[VK_TAB] = OS_Key_Tab; key_table[VK_PAUSE] = OS_Key_Pause; key_table[VK_ESCAPE] = OS_Key_Esc; key_table[VK_UP] = OS_Key_Up; key_table[VK_LEFT] = OS_Key_Left; key_table[VK_DOWN] = OS_Key_Down; key_table[VK_RIGHT] = OS_Key_Right; key_table[VK_BACK] = OS_Key_Backspace; key_table[VK_RETURN] = OS_Key_Return; key_table[VK_DELETE] = OS_Key_Delete; key_table[VK_INSERT] = OS_Key_Insert; key_table[VK_PRIOR] = OS_Key_PageUp; key_table[VK_NEXT] = OS_Key_PageDown; key_table[VK_HOME] = OS_Key_Home; key_table[VK_END] = OS_Key_End; key_table[VK_CAPITAL] = OS_Key_CapsLock; key_table[VK_NUMLOCK] = OS_Key_NumLock; key_table[VK_SCROLL] = OS_Key_ScrollLock; key_table[VK_APPS] = OS_Key_Menu; key_table[VK_CONTROL] = OS_Key_Ctrl; key_table[VK_LCONTROL] = OS_Key_Ctrl; key_table[VK_RCONTROL] = OS_Key_Ctrl; key_table[VK_SHIFT] = OS_Key_Shift; key_table[VK_LSHIFT] = OS_Key_Shift; key_table[VK_RSHIFT] = OS_Key_Shift; key_table[VK_MENU] = OS_Key_Alt; key_table[VK_LMENU] = OS_Key_Alt; key_table[VK_RMENU] = OS_Key_Alt; key_table[VK_DIVIDE] = OS_Key_NumSlash; key_table[VK_MULTIPLY] = OS_Key_NumStar; key_table[VK_SUBTRACT] = OS_Key_NumMinus; key_table[VK_ADD] = OS_Key_NumPlus; key_table[VK_DECIMAL] = OS_Key_NumPeriod; for (U32 i = 0; i < 10; i += 1){ key_table[VK_NUMPAD0 + i] = (OS_Key)((U64)OS_Key_Num0 + i); } for (U64 i = 0xDF, j = 0; i < 0xFF; i += 1, j += 1){ key_table[i] = (OS_Key)((U64)OS_Key_Ex0 + j); } } OS_Key key = key_table[vkey&bitmask8]; return key; } internal WPARAM os_w32_vkey_from_os_key(OS_Key key) { WPARAM result = 0; { local_persist B32 initialized = 0; local_persist WPARAM vkey_table[OS_Key_COUNT] = {0}; if(initialized == 0) { initialized = 1; vkey_table[OS_Key_Esc] = VK_ESCAPE; for(OS_Key key = OS_Key_F1; key <= OS_Key_F24; key = (OS_Key)(key+1)) { vkey_table[key] = VK_F1+(key-OS_Key_F1); } vkey_table[OS_Key_Tick] = VK_OEM_3; for(OS_Key key = OS_Key_0; key <= OS_Key_9; key = (OS_Key)(key+1)) { vkey_table[key] = '0'+(key-OS_Key_0); } vkey_table[OS_Key_Minus] = VK_OEM_MINUS; vkey_table[OS_Key_Equal] = VK_OEM_PLUS; vkey_table[OS_Key_Backspace] = VK_BACK; vkey_table[OS_Key_Tab] = VK_TAB; vkey_table[OS_Key_Q] = 'Q'; vkey_table[OS_Key_W] = 'W'; vkey_table[OS_Key_E] = 'E'; vkey_table[OS_Key_R] = 'R'; vkey_table[OS_Key_T] = 'T'; vkey_table[OS_Key_Y] = 'Y'; vkey_table[OS_Key_U] = 'U'; vkey_table[OS_Key_I] = 'I'; vkey_table[OS_Key_O] = 'O'; vkey_table[OS_Key_P] = 'P'; vkey_table[OS_Key_LeftBracket] = VK_OEM_4; vkey_table[OS_Key_RightBracket] = VK_OEM_6; vkey_table[OS_Key_BackSlash] = VK_OEM_5; vkey_table[OS_Key_CapsLock] = VK_CAPITAL; vkey_table[OS_Key_A] = 'A'; vkey_table[OS_Key_S] = 'S'; vkey_table[OS_Key_D] = 'D'; vkey_table[OS_Key_F] = 'F'; vkey_table[OS_Key_G] = 'G'; vkey_table[OS_Key_H] = 'H'; vkey_table[OS_Key_J] = 'J'; vkey_table[OS_Key_K] = 'K'; vkey_table[OS_Key_L] = 'L'; vkey_table[OS_Key_Semicolon] = VK_OEM_1; vkey_table[OS_Key_Quote] = VK_OEM_7; vkey_table[OS_Key_Return] = VK_RETURN; vkey_table[OS_Key_Shift] = VK_SHIFT; vkey_table[OS_Key_Z] = 'Z'; vkey_table[OS_Key_X] = 'X'; vkey_table[OS_Key_C] = 'C'; vkey_table[OS_Key_V] = 'V'; vkey_table[OS_Key_B] = 'B'; vkey_table[OS_Key_N] = 'N'; vkey_table[OS_Key_M] = 'M'; vkey_table[OS_Key_Comma] = VK_OEM_COMMA; vkey_table[OS_Key_Period] = VK_OEM_PERIOD; vkey_table[OS_Key_Slash] = VK_OEM_2; vkey_table[OS_Key_Ctrl] = VK_CONTROL; vkey_table[OS_Key_Alt] = VK_MENU; vkey_table[OS_Key_Space] = VK_SPACE; vkey_table[OS_Key_Menu] = VK_APPS; vkey_table[OS_Key_ScrollLock] = VK_SCROLL; vkey_table[OS_Key_Pause] = VK_PAUSE; vkey_table[OS_Key_Insert] = VK_INSERT; vkey_table[OS_Key_Home] = VK_HOME; vkey_table[OS_Key_PageUp] = VK_PRIOR; vkey_table[OS_Key_Delete] = VK_DELETE; vkey_table[OS_Key_End] = VK_END; vkey_table[OS_Key_PageDown] = VK_NEXT; vkey_table[OS_Key_Up] = VK_UP; vkey_table[OS_Key_Left] = VK_LEFT; vkey_table[OS_Key_Down] = VK_DOWN; vkey_table[OS_Key_Right] = VK_RIGHT; for(OS_Key key = OS_Key_Ex0; key <= OS_Key_Ex29; key = (OS_Key)(key+1)) { vkey_table[key] = 0xDF + (key-OS_Key_Ex0); } vkey_table[OS_Key_NumLock] = VK_NUMLOCK; vkey_table[OS_Key_NumSlash] = VK_DIVIDE; vkey_table[OS_Key_NumStar] = VK_MULTIPLY; vkey_table[OS_Key_NumMinus] = VK_SUBTRACT; vkey_table[OS_Key_NumPlus] = VK_ADD; vkey_table[OS_Key_NumPeriod] = VK_DECIMAL; vkey_table[OS_Key_Num0] = VK_NUMPAD0; vkey_table[OS_Key_Num1] = VK_NUMPAD1; vkey_table[OS_Key_Num2] = VK_NUMPAD2; vkey_table[OS_Key_Num3] = VK_NUMPAD3; vkey_table[OS_Key_Num4] = VK_NUMPAD4; vkey_table[OS_Key_Num5] = VK_NUMPAD5; vkey_table[OS_Key_Num6] = VK_NUMPAD6; vkey_table[OS_Key_Num7] = VK_NUMPAD7; vkey_table[OS_Key_Num8] = VK_NUMPAD8; vkey_table[OS_Key_Num9] = VK_NUMPAD9; vkey_table[OS_Key_LeftMouseButton] = VK_LBUTTON; vkey_table[OS_Key_MiddleMouseButton] = VK_MBUTTON; vkey_table[OS_Key_RightMouseButton] = VK_RBUTTON; } result = vkey_table[key]; } return result; } internal LRESULT os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ProfBeginFunction(); LRESULT result = 0; B32 good = 1; if(os_w32_event_arena == 0) { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); good = 0; } if(good) { OS_W32_Window *window = os_w32_window_from_hwnd(hwnd); OS_Handle window_handle = os_w32_handle_from_window(window); B32 release = 0; switch(uMsg) { default: { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); }break; case WM_ENTERSIZEMOVE: { os_w32_resizing = 1; }break; case WM_EXITSIZEMOVE: { os_w32_resizing = 0; }break; case WM_SIZE: case WM_PAINT: { PAINTSTRUCT ps = {0}; BeginPaint(hwnd, &ps); update(); EndPaint(hwnd, &ps); DwmFlush(); }break; case WM_CLOSE: { os_w32_push_event(OS_EventKind_WindowClose, window); }break; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: { release = 1; } // fallthrough; case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: { OS_Event *event = os_w32_push_event(release ? OS_EventKind_Release : OS_EventKind_Press, window); switch (uMsg) { case WM_LBUTTONUP: case WM_LBUTTONDOWN: { event->key = OS_Key_LeftMouseButton; }break; case WM_MBUTTONUP: case WM_MBUTTONDOWN: { event->key = OS_Key_MiddleMouseButton; }break; case WM_RBUTTONUP: case WM_RBUTTONDOWN: { event->key = OS_Key_RightMouseButton; }break; } event->pos.x = (F32)(S16)LOWORD(lParam); event->pos.y = (F32)(S16)HIWORD(lParam); if(release) { ReleaseCapture(); } else { SetCapture(hwnd); } }break; case WM_MOUSEMOVE: { OS_Event *event = os_w32_push_event(OS_EventKind_MouseMove, window); event->pos.x = (F32)(S16)LOWORD(lParam); event->pos.y = (F32)(S16)HIWORD(lParam); }break; case WM_MOUSEWHEEL: { S16 wheel_delta = HIWORD(wParam); OS_Event *event = os_w32_push_event(OS_EventKind_Scroll, window); POINT p; p.x = (S32)(S16)LOWORD(lParam); p.y = (S32)(S16)HIWORD(lParam); ScreenToClient(window->hwnd, &p); event->pos.x = (F32)p.x; event->pos.y = (F32)p.y; event->delta = v2f32(0.f, -(F32)wheel_delta); }break; case WM_MOUSEHWHEEL: { S16 wheel_delta = HIWORD(wParam); OS_Event *event = os_w32_push_event(OS_EventKind_Scroll, window); POINT p; p.x = (S32)(S16)LOWORD(lParam); p.y = (S32)(S16)HIWORD(lParam); ScreenToClient(window->hwnd, &p); event->pos.x = (F32)p.x; event->pos.y = (F32)p.y; event->delta = v2f32((F32)wheel_delta, 0.f); }break; case WM_SYSKEYDOWN: case WM_SYSKEYUP: { if(wParam != VK_MENU && (wParam < VK_F1 || VK_F24 < wParam || wParam == VK_F4)) { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } } // fallthrough; case WM_KEYDOWN: case WM_KEYUP: { B32 was_down = (lParam & bit31); B32 is_down = !(lParam & bit32); B32 is_repeat = 0; if(!is_down) { release = 1; } else if(was_down) { is_repeat = 1; } B32 right_sided = 0; if ((lParam & bit25) && (wParam == VK_CONTROL || wParam == VK_RCONTROL || wParam == VK_MENU || wParam == VK_RMENU || wParam == VK_SHIFT || wParam == VK_RSHIFT)) { right_sided = 1; } OS_Event *event = os_w32_push_event(release ? OS_EventKind_Release : OS_EventKind_Press, window); event->key = os_w32_os_key_from_vkey(wParam); event->repeat_count = lParam & bitmask16; event->is_repeat = is_repeat; event->right_sided = right_sided; if(event->key == OS_Key_Alt && event->modifiers & OS_Modifier_Alt) { event->modifiers &= ~OS_Modifier_Alt; } if(event->key == OS_Key_Ctrl && event->modifiers & OS_Modifier_Ctrl) { event->modifiers &= ~OS_Modifier_Ctrl; } if(event->key == OS_Key_Shift && event->modifiers & OS_Modifier_Shift) { event->modifiers &= ~OS_Modifier_Shift; } }break; case WM_SYSCHAR: { WORD vk_code = LOWORD(wParam); if(vk_code == VK_SPACE) { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } else { result = 0; } }break; case WM_CHAR: { U32 character = wParam; if(character >= 32 && character != 127) { OS_Event *event = os_w32_push_event(OS_EventKind_Text, window); if(lParam & bit29) { event->modifiers |= OS_Modifier_Alt; } event->character = character; } }break; case WM_KILLFOCUS: { os_w32_push_event(OS_EventKind_WindowLoseFocus, window); ReleaseCapture(); }break; case WM_SETCURSOR: { Rng2F32 window_rect = os_client_rect_from_window(window_handle); Vec2F32 mouse = os_mouse_from_window(window_handle); B32 on_border = 0; DWORD window_style = window ? GetWindowLong(window->hwnd, GWL_STYLE) : 0; B32 is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW); if(window != 0 && window->custom_border && !is_fullscreen) { B32 on_border_x = (mouse.x <= window->custom_border_edge_thickness || window_rect.x1-window->custom_border_edge_thickness <= mouse.x); B32 on_border_y = (mouse.y <= window->custom_border_edge_thickness || window_rect.y1-window->custom_border_edge_thickness <= mouse.y); on_border = on_border_x || on_border_y; } if(!os_w32_resizing && !on_border && contains_2f32(window_rect, mouse)) { SetCursor(os_w32_gfx_state->hCursor); } else { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } }break; case WM_DPICHANGED: { F32 new_dpi = (F32)(wParam & 0xffff); RECT suggested_new_rect = *(RECT *)lParam; window->dpi = new_dpi; SetWindowPos(window->hwnd, 0, suggested_new_rect.left, suggested_new_rect.top, suggested_new_rect.right - suggested_new_rect.left, suggested_new_rect.bottom - suggested_new_rect.top, 0); }break; //- rjf: [file drop] case WM_DROPFILES: { HDROP drop = (HDROP)wParam; POINT drop_pt = {0}; DragQueryPoint(drop, &drop_pt); U64 num_files_dropped = DragQueryFile(drop, 0xffffffff, 0, 0); OS_Event *event = os_w32_push_event(OS_EventKind_FileDrop, window); event->pos = v2f32((F32)drop_pt.x, (F32)drop_pt.y); for(U64 idx = 0; idx < num_files_dropped; idx += 1) { U64 name_size = DragQueryFile(drop, idx, 0, 0) + 1; U8 *name_ptr = push_array(os_w32_event_arena, U8, name_size); DragQueryFile(drop, idx, (char *)name_ptr, name_size); String8 path_string = str8(name_ptr, name_size - 1); String8 path_string__normalized = path_normalized_from_string(os_w32_event_arena, path_string); str8_list_push(os_w32_event_arena, &event->strings, path_string__normalized); } DragFinish(drop); }break; //- rjf: [custom border] case WM_NCPAINT: { if(os_w32_new_window_custom_border || (window != 0 && window->custom_border && !window->custom_border_composition_enabled)) { result = 0; } else { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } }break; case WM_DWMCOMPOSITIONCHANGED: { if(window != 0 && window->custom_border) { BOOL enabled = 0; DwmIsCompositionEnabled(&enabled); window->custom_border_composition_enabled = enabled; if(enabled) { MARGINS m = { 0, 0, 1, 0 }; DwmExtendFrameIntoClientArea(hwnd, &m); DWORD dwmncrp_enabled = DWMNCRP_ENABLED; DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &enabled, sizeof(dwmncrp_enabled)); } } else { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } }break; case WM_WINDOWPOSCHANGED: { result = 0; }break; case WM_NCUAHDRAWCAPTION: case WM_NCUAHDRAWFRAME: { // NOTE(rjf): undocumented messages for drawing themed window borders. if(os_w32_new_window_custom_border || (window != 0 && window->custom_border)) { result = 0; } else { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } }break; case WM_SETICON: case WM_SETTEXT: { if(os_w32_new_window_custom_border || (window && window->custom_border && !window->custom_border_composition_enabled)) { // NOTE(rjf): // https://blogs.msdn.microsoft.com/wpfsdk/2008/09/08/custom-window-chrome-in-wpf/ LONG_PTR old_style = GetWindowLongPtrW(hwnd, GWL_STYLE); SetWindowLongPtrW(hwnd, GWL_STYLE, old_style & ~WS_VISIBLE); result = DefWindowProcW(hwnd, uMsg, wParam, lParam); SetWindowLongPtrW(hwnd, GWL_STYLE, old_style); } else { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } }break; //- rjf: [custom border] activation - without this `result`, stuff flickers. case WM_NCACTIVATE: { if(!os_w32_new_window_custom_border && (window == 0 || window->custom_border == 0)) { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } else { result = DefWindowProcW(hwnd, uMsg, wParam, -1); } }break; //- rjf: [custom border] client/window size calculation case WM_NCCALCSIZE: { if(os_w32_new_window_custom_border || (window && window->custom_border)) { F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f; S32 frame_x = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXFRAME, dpi) : GetSystemMetrics(SM_CXFRAME); S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME); S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER); DWORD window_style = GetWindowLong(hwnd, GWL_STYLE); B32 is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW); if(!is_fullscreen) { RECT* rect = wParam == 0 ? (RECT*)lParam : ((NCCALCSIZE_PARAMS*)lParam)->rgrc; rect->right -= frame_x + padding; rect->left += frame_x + padding; rect->bottom -= frame_y + padding; if(IsMaximized(hwnd)) { rect->top += frame_y + padding; // If we do not do this hidden taskbar can not be unhidden on mouse hover // Unfortunately it can create an ugly bottom border when maximized... rect->bottom -= 1; } } } else { result = DefWindowProc(hwnd, uMsg, wParam, lParam); } }break; //- rjf: [custom border] client/window hit testing (mapping mouse -> action) case WM_NCHITTEST: { DWORD window_style = window ? GetWindowLong(window->hwnd, GWL_STYLE) : 0; B32 is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW); if(window == 0 || window->custom_border == 0 || is_fullscreen) { result = DefWindowProcW(hwnd, uMsg, wParam, lParam); } else { B32 is_default_handled = 0; // Let the default procedure handle resizing areas result = DefWindowProc(hwnd, uMsg, wParam, lParam); switch (result) { case HTNOWHERE: case HTRIGHT: case HTLEFT: case HTTOPLEFT: case HTTOPRIGHT: case HTBOTTOMRIGHT: case HTBOTTOM: case HTBOTTOMLEFT: { is_default_handled = 1; } break; } if (!is_default_handled) { POINT pos_monitor; pos_monitor.x = GET_X_LPARAM(lParam); pos_monitor.y = GET_Y_LPARAM(lParam); POINT pos_client = pos_monitor; ScreenToClient(hwnd, &pos_client); // Adjustments happening in NCCALCSIZE are messing with the detection // of the top hit area so manually checking that. F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f; S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME); // NOTE(rjf): it seems incorrect to apply this padding here... // S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER); B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y; // + padding; B32 is_over_title_bar = pos_client.y >= 0 && pos_client.y < window->custom_border_title_thickness; //- rjf: check against title bar client areas B32 is_over_title_bar_client_area = 0; for(OS_W32_TitleBarClientArea *area = window->first_title_bar_client_area; area != 0; area = area->next) { Rng2F32 rect = area->rect; if(rect.x0 <= pos_client.x && pos_client.x < rect.x1 && rect.y0 <= pos_client.y && pos_client.y < rect.y1) { is_over_title_bar_client_area = 1; break; } } if (IsMaximized(hwnd)) { if (is_over_title_bar_client_area) { result = HTCLIENT; } else if (is_over_title_bar) { result = HTCAPTION; } else { result = HTCLIENT; } } else { //Swap the first two conditions to choose if hovering the top border //should prioritize resize or title bar buttons. if (is_over_title_bar_client_area) { result = HTCLIENT; } else if (is_over_top_resize) { result = HTTOP; } else if (is_over_title_bar) { result = HTCAPTION; } else { result = HTCLIENT; } } } } }break; } } ProfEnd(); return result; } //////////////////////////////// //~ rjf: Monitors internal BOOL os_w32_monitor_gather_enum_proc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM bundle_ptr) { OS_W32_MonitorGatherBundle *bundle = (OS_W32_MonitorGatherBundle *)bundle_ptr; OS_Handle handle = {(U64)monitor}; os_handle_list_push(bundle->arena, bundle->list, handle); return 1; } //////////////////////////////// //~ rjf: @os_hooks Main Initialization API (Implemented Per-OS) internal void os_gfx_init(void) { //- rjf: set up base shared state Arena *arena = arena_alloc(); os_w32_gfx_state = push_array(arena, OS_W32_GfxState, 1); os_w32_gfx_state->arena = arena; os_w32_gfx_state->gfx_thread_tid = (U32)GetCurrentThreadId(); os_w32_gfx_state->hInstance = GetModuleHandle(0); //- rjf: set dpi awareness w32_SetProcessDpiAwarenessContext_Type *SetProcessDpiAwarenessContext_func = 0; HMODULE module = LoadLibraryA("user32.dll"); if(module != 0) { SetProcessDpiAwarenessContext_func = (w32_SetProcessDpiAwarenessContext_Type*)GetProcAddress(module, "SetProcessDpiAwarenessContext"); w32_GetDpiForWindow_func = (w32_GetDpiForWindow_Type*)GetProcAddress(module, "GetDpiForWindow"); w32_GetDpiForMonitor_func = (w32_GetDpiForMonitor_Type *)GetProcAddress(module, "GetDpiForMonitor"); w32_GetSystemMetricsForDpi_func = (w32_GetSystemMetricsForDpi_Type *)GetProcAddress(module, "GetSystemMetricsForDpi"); FreeLibrary(module); } if(SetProcessDpiAwarenessContext_func != 0) { SetProcessDpiAwarenessContext_func(w32_DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); } else { HMODULE shcore = LoadLibraryA("shcore.dll"); if(shcore) { typedef HRESULT (WINAPI* SetProcessDpiAwareness_t)(int); SetProcessDpiAwareness_t SetProcessDpiAwareness = (void*)GetProcAddress(shcore, "SetProcessDpiAwareness"); if(SetProcessDpiAwareness) { SetProcessDpiAwareness(2); } FreeLibrary(shcore); } SetProcessDPIAware(); } //- rjf: register graphical-window class { WNDCLASSEXW wndclass = {sizeof(wndclass)}; wndclass.lpfnWndProc = os_w32_wnd_proc; wndclass.hInstance = os_w32_gfx_state->hInstance; wndclass.lpszClassName = L"graphical-window"; wndclass.hCursor = LoadCursorA(0, IDC_ARROW); wndclass.hIcon = LoadIcon(os_w32_gfx_state->hInstance, MAKEINTRESOURCE(1)); wndclass.style = CS_VREDRAW|CS_HREDRAW; ATOM wndatom = RegisterClassExW(&wndclass); (void)wndatom; } //- rjf: grab graphics system info { os_w32_gfx_state->gfx_info.double_click_time = GetDoubleClickTime()/1000.f; os_w32_gfx_state->gfx_info.caret_blink_time = GetCaretBlinkTime()/1000.f; DEVMODEW devmodew = {0}; if(EnumDisplaySettingsW(0, ENUM_CURRENT_SETTINGS, &devmodew)) { os_w32_gfx_state->gfx_info.default_refresh_rate = (F32)devmodew.dmDisplayFrequency; } } //- rjf: set initial cursor os_set_cursor(OS_Cursor_Pointer); //- rjf: fill vkey -> OS_Key table { os_w32_gfx_state->key_from_vkey_table[(unsigned int)'A'] = OS_Key_A; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'B'] = OS_Key_B; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'C'] = OS_Key_C; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'D'] = OS_Key_D; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'E'] = OS_Key_E; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'F'] = OS_Key_F; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'G'] = OS_Key_G; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'H'] = OS_Key_H; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'I'] = OS_Key_I; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'J'] = OS_Key_J; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'K'] = OS_Key_K; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'L'] = OS_Key_L; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'M'] = OS_Key_M; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'N'] = OS_Key_N; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'O'] = OS_Key_O; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'P'] = OS_Key_P; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'Q'] = OS_Key_Q; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'R'] = OS_Key_R; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'S'] = OS_Key_S; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'T'] = OS_Key_T; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'U'] = OS_Key_U; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'V'] = OS_Key_V; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'W'] = OS_Key_W; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'X'] = OS_Key_X; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'Y'] = OS_Key_Y; os_w32_gfx_state->key_from_vkey_table[(unsigned int)'Z'] = OS_Key_Z; for(U64 i = '0', j = OS_Key_0; i <= '9'; i += 1, j += 1) { os_w32_gfx_state->key_from_vkey_table[i] = (OS_Key)j; } for(U64 i = VK_NUMPAD0, j = OS_Key_0; i <= VK_NUMPAD9; i += 1, j += 1) { os_w32_gfx_state->key_from_vkey_table[i] = (OS_Key)j; } for(U64 i = VK_F1, j = OS_Key_F1; i <= VK_F24; i += 1, j += 1) { os_w32_gfx_state->key_from_vkey_table[i] = (OS_Key)j; } os_w32_gfx_state->key_from_vkey_table[VK_SPACE] = OS_Key_Space; os_w32_gfx_state->key_from_vkey_table[VK_OEM_3] = OS_Key_Tick; os_w32_gfx_state->key_from_vkey_table[VK_OEM_MINUS] = OS_Key_Minus; os_w32_gfx_state->key_from_vkey_table[VK_OEM_PLUS] = OS_Key_Equal; os_w32_gfx_state->key_from_vkey_table[VK_OEM_4] = OS_Key_LeftBracket; os_w32_gfx_state->key_from_vkey_table[VK_OEM_6] = OS_Key_RightBracket; os_w32_gfx_state->key_from_vkey_table[VK_OEM_1] = OS_Key_Semicolon; os_w32_gfx_state->key_from_vkey_table[VK_OEM_7] = OS_Key_Quote; os_w32_gfx_state->key_from_vkey_table[VK_OEM_COMMA] = OS_Key_Comma; os_w32_gfx_state->key_from_vkey_table[VK_OEM_PERIOD]= OS_Key_Period; os_w32_gfx_state->key_from_vkey_table[VK_OEM_2] = OS_Key_Slash; os_w32_gfx_state->key_from_vkey_table[VK_OEM_5] = OS_Key_BackSlash; os_w32_gfx_state->key_from_vkey_table[VK_TAB] = OS_Key_Tab; os_w32_gfx_state->key_from_vkey_table[VK_PAUSE] = OS_Key_Pause; os_w32_gfx_state->key_from_vkey_table[VK_ESCAPE] = OS_Key_Esc; os_w32_gfx_state->key_from_vkey_table[VK_UP] = OS_Key_Up; os_w32_gfx_state->key_from_vkey_table[VK_LEFT] = OS_Key_Left; os_w32_gfx_state->key_from_vkey_table[VK_DOWN] = OS_Key_Down; os_w32_gfx_state->key_from_vkey_table[VK_RIGHT] = OS_Key_Right; os_w32_gfx_state->key_from_vkey_table[VK_BACK] = OS_Key_Backspace; os_w32_gfx_state->key_from_vkey_table[VK_RETURN] = OS_Key_Return; os_w32_gfx_state->key_from_vkey_table[VK_DELETE] = OS_Key_Delete; os_w32_gfx_state->key_from_vkey_table[VK_INSERT] = OS_Key_Insert; os_w32_gfx_state->key_from_vkey_table[VK_PRIOR] = OS_Key_PageUp; os_w32_gfx_state->key_from_vkey_table[VK_NEXT] = OS_Key_PageDown; os_w32_gfx_state->key_from_vkey_table[VK_HOME] = OS_Key_Home; os_w32_gfx_state->key_from_vkey_table[VK_END] = OS_Key_End; os_w32_gfx_state->key_from_vkey_table[VK_CAPITAL] = OS_Key_CapsLock; os_w32_gfx_state->key_from_vkey_table[VK_NUMLOCK] = OS_Key_NumLock; os_w32_gfx_state->key_from_vkey_table[VK_SCROLL] = OS_Key_ScrollLock; os_w32_gfx_state->key_from_vkey_table[VK_APPS] = OS_Key_Menu; os_w32_gfx_state->key_from_vkey_table[VK_CONTROL] = OS_Key_Ctrl; os_w32_gfx_state->key_from_vkey_table[VK_LCONTROL] = OS_Key_Ctrl; os_w32_gfx_state->key_from_vkey_table[VK_RCONTROL] = OS_Key_Ctrl; os_w32_gfx_state->key_from_vkey_table[VK_SHIFT] = OS_Key_Shift; os_w32_gfx_state->key_from_vkey_table[VK_LSHIFT] = OS_Key_Shift; os_w32_gfx_state->key_from_vkey_table[VK_RSHIFT] = OS_Key_Shift; os_w32_gfx_state->key_from_vkey_table[VK_MENU] = OS_Key_Alt; os_w32_gfx_state->key_from_vkey_table[VK_LMENU] = OS_Key_Alt; os_w32_gfx_state->key_from_vkey_table[VK_RMENU] = OS_Key_Alt; os_w32_gfx_state->key_from_vkey_table[VK_DIVIDE] = OS_Key_NumSlash; os_w32_gfx_state->key_from_vkey_table[VK_MULTIPLY] = OS_Key_NumStar; os_w32_gfx_state->key_from_vkey_table[VK_SUBTRACT] = OS_Key_NumMinus; os_w32_gfx_state->key_from_vkey_table[VK_ADD] = OS_Key_NumPlus; os_w32_gfx_state->key_from_vkey_table[VK_DECIMAL] = OS_Key_NumPeriod; for(U32 i = 0; i < 10; i += 1) { os_w32_gfx_state->key_from_vkey_table[VK_NUMPAD0 + i] = (OS_Key)((U64)OS_Key_Num0 + i); } for(U64 i = 0xDF, j = 0; i < 0xFF; i += 1, j += 1) { os_w32_gfx_state->key_from_vkey_table[i] = (OS_Key)((U64)OS_Key_Ex0 + j); } } } //////////////////////////////// //~ rjf: @os_hooks Graphics System Info (Implemented Per-OS) internal OS_GfxInfo * os_get_gfx_info(void) { return &os_w32_gfx_state->gfx_info; } //////////////////////////////// //~ rjf: @os_hooks Clipboards (Implemented Per-OS) internal void os_set_clipboard_text(String8 string) { Temp scratch = scratch_begin(0, 0); if(OpenClipboard(0)) { EmptyClipboard(); String16 string16 = str16_from_8(scratch.arena, string); HANDLE string16_copy_handle = GlobalAlloc(GMEM_MOVEABLE, (string16.size+1)*sizeof(string16.str[0])); if(string16_copy_handle) { U16 *copy_buffer = (U16 *)GlobalLock(string16_copy_handle); MemoryCopy(copy_buffer, string16.str, string16.size*sizeof(string16.str[0])); copy_buffer[string16.size] = 0; GlobalUnlock(string16_copy_handle); SetClipboardData(CF_UNICODETEXT, string16_copy_handle); } CloseClipboard(); } scratch_end(scratch); } internal String8 os_get_clipboard_text(Arena *arena) { String8 result = {0}; if(IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(0)) { HANDLE data_handle = GetClipboardData(CF_UNICODETEXT); if(data_handle) { U16 *buffer = (U16 *)GlobalLock(data_handle); if(buffer) { U64 size = cstring16_length(buffer); String16 string16 = str16(buffer, size); result = str8_from_16(arena, string16); GlobalUnlock(data_handle); } } CloseClipboard(); } return result; } //////////////////////////////// //~ rjf: @os_hooks Windows (Implemented Per-OS) internal OS_Handle os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title) { B32 custom_border = !!(flags & OS_WindowFlag_CustomBorder); B32 use_default_position = !!(flags & OS_WindowFlag_UseDefaultPosition); Vec2F32 pos = rect.p0; Vec2F32 dim = dim_2f32(rect); //- rjf: make hwnd HWND hwnd = 0; { Temp scratch = scratch_begin(0, 0); String16 title16 = str16_from_8(scratch.arena, title); os_w32_new_window_custom_border = custom_border; DWORD style_flags = WS_EX_APPWINDOW; #if defined(R_BACKEND) && R_BACKEND != R_BACKEND_OPENGL style_flags |= WS_EX_NOREDIRECTIONBITMAP; #endif hwnd = CreateWindowExW(style_flags, L"graphical-window", (WCHAR*)title16.str, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, use_default_position ? CW_USEDEFAULT : (S32)pos.x, use_default_position ? CW_USEDEFAULT : (S32)pos.y, (S32)dim.x, (S32)dim.y, 0, 0, os_w32_gfx_state->hInstance, 0); DragAcceptFiles(hwnd, 1); os_w32_new_window_custom_border = 0; scratch_end(scratch); } //- rjf- make/fill window OS_W32_Window *window = os_w32_window_alloc(); { window->hwnd = hwnd; window->hdc = GetDC(hwnd); if(w32_GetDpiForWindow_func != 0) { window->dpi = (F32)w32_GetDpiForWindow_func(hwnd); } else { window->dpi = 96.f; } } //- rjf: early detection of composition { BOOL enabled = 0; DwmIsCompositionEnabled(&enabled); window->custom_border_composition_enabled = enabled; } //- rjf: custom border if(flags & OS_WindowFlag_CustomBorder) { window->custom_border = 1; window->paint_arena = arena_alloc(); } //- rjf: convert to handle + return OS_Handle result = os_w32_handle_from_window(window); return result; } internal void os_window_close(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); os_w32_window_release(window); } internal void os_window_set_title(OS_Handle handle, String8 title) { Temp scratch = scratch_begin(0, 0); OS_W32_Window *window = os_w32_window_from_handle(handle); String16 title16 = str16_from_8(scratch.arena, title); SetWindowTextW(window->hwnd, (WCHAR *)title16.str); scratch_end(scratch); } internal void os_window_first_paint(OS_Handle window_handle) { OS_W32_Window *window = os_w32_window_from_handle(window_handle); window->first_paint_done = 1; ShowWindow(window->hwnd, SW_SHOW); if(window->maximized) { ShowWindow(window->hwnd, SW_MAXIMIZE); } } internal void os_window_focus(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); SetForegroundWindow(window->hwnd); SetFocus(window->hwnd); } internal B32 os_window_is_focused(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); HWND active_hwnd = GetActiveWindow(); return active_hwnd == window->hwnd; } internal B32 os_window_is_fullscreen(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); DWORD window_style = GetWindowLong(window->hwnd, GWL_STYLE); return !(window_style & WS_OVERLAPPEDWINDOW); } internal void os_window_set_fullscreen(OS_Handle handle, B32 fullscreen) { OS_W32_Window *window = os_w32_window_from_handle(handle); DWORD window_style = GetWindowLong(window->hwnd, GWL_STYLE); B32 is_fullscreen_already = os_window_is_fullscreen(handle); if(fullscreen) { if(!is_fullscreen_already) { GetWindowPlacement(window->hwnd, &window->last_window_placement); } MONITORINFO monitor_info = {sizeof(monitor_info)}; if(GetMonitorInfo(MonitorFromWindow(window->hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info)) { SetWindowLong(window->hwnd, GWL_STYLE, window_style & ~WS_OVERLAPPEDWINDOW); SetWindowPos(window->hwnd, HWND_TOP, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top, monitor_info.rcMonitor.right - monitor_info.rcMonitor.left, monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } } else { SetWindowLong(window->hwnd, GWL_STYLE, window_style | WS_OVERLAPPEDWINDOW); SetWindowPlacement(window->hwnd, &window->last_window_placement); SetWindowPos(window->hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } } internal B32 os_window_is_maximized(OS_Handle handle) { B32 result = 0; OS_W32_Window *window = os_w32_window_from_handle(handle); if(window) { result = !!(IsZoomed(window->hwnd)); } return result; } internal void os_window_set_maximized(OS_Handle handle, B32 maximized) { OS_W32_Window *window = os_w32_window_from_handle(handle); if(window != 0) { if(window->first_paint_done) { switch(maximized) { default: case 0:{ShowWindow(window->hwnd, SW_RESTORE);}break; case 1:{ShowWindow(window->hwnd, SW_MAXIMIZE);}break; } } else { window->maximized = maximized; } } } internal B32 os_window_is_minimized(OS_Handle handle) { B32 result = 0; OS_W32_Window *window = os_w32_window_from_handle(handle); if(window) { result = !!(IsIconic(window->hwnd)); } return result; } internal void os_window_set_minimized(OS_Handle handle, B32 minimized) { OS_W32_Window *window = os_w32_window_from_handle(handle); if(window != 0 && minimized != os_window_is_minimized(handle)) { switch(minimized) { default: case 0:{ShowWindow(window->hwnd, SW_RESTORE);}break; case 1:{ShowWindow(window->hwnd, SW_MINIMIZE);}break; } } } internal void os_window_bring_to_front(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); if(window != 0) { BringWindowToTop(window->hwnd); } } internal void os_window_set_monitor(OS_Handle window_handle, OS_Handle monitor) { OS_W32_Window *window = os_w32_window_from_handle(window_handle); HMONITOR hmonitor = (HMONITOR)monitor.u64[0]; { MONITORINFOEXW info; info.cbSize = sizeof(MONITORINFOEXW); if(GetMonitorInfoW(hmonitor, (MONITORINFO *)&info)) { Rng2F32 existing_rect = os_rect_from_window(window_handle); Vec2F32 window_size = dim_2f32(existing_rect); SetWindowPos(window->hwnd, HWND_TOP, (info.rcWork.left + info.rcWork.right)/2 - window_size.x/2, (info.rcWork.top + info.rcWork.bottom)/2 - window_size.y/2, window_size.x, window_size.y, 0); } } } internal void os_window_clear_custom_border_data(OS_Handle handle) { OS_W32_Window *window = os_w32_window_from_handle(handle); if(window->custom_border) { arena_clear(window->paint_arena); window->first_title_bar_client_area = window->last_title_bar_client_area = 0; window->custom_border_title_thickness = 0; window->custom_border_edge_thickness = 0; } } internal void os_window_push_custom_title_bar(OS_Handle handle, F32 thickness) { OS_W32_Window *window = os_w32_window_from_handle(handle); window->custom_border_title_thickness = thickness; } internal void os_window_push_custom_edges(OS_Handle handle, F32 thickness) { OS_W32_Window *window = os_w32_window_from_handle(handle); window->custom_border_edge_thickness = thickness; } internal void os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect) { OS_W32_Window *window = os_w32_window_from_handle(handle); if(window->custom_border) { OS_W32_TitleBarClientArea *area = push_array(window->paint_arena, OS_W32_TitleBarClientArea, 1); if(area != 0) { area->rect = rect; SLLQueuePush(window->first_title_bar_client_area, window->last_title_bar_client_area, area); } } } internal Rng2F32 os_rect_from_window(OS_Handle handle) { Rng2F32 r = {0}; OS_W32_Window *window = os_w32_window_from_handle(handle); if(window) { RECT rect = {0}; GetWindowRect(os_w32_hwnd_from_window(window), &rect); r = os_w32_rng2f32_from_rect(rect); } return r; } internal Rng2F32 os_client_rect_from_window(OS_Handle handle) { Rng2F32 r = {0}; OS_W32_Window *window = os_w32_window_from_handle(handle); if(window) { RECT rect = {0}; GetClientRect(os_w32_hwnd_from_window(window), &rect); r = os_w32_rng2f32_from_rect(rect); } return r; } internal F32 os_dpi_from_window(OS_Handle handle) { F32 result = 96.f; OS_W32_Window *window = os_w32_window_from_handle(handle); if(window != 0) { result = window->dpi; } return result; } //////////////////////////////// //~ rjf: @os_hooks External Windows (Implemented Per-OS) internal OS_Handle os_focused_external_window(void) { HWND hwnd = GetForegroundWindow(); OS_Handle result = {(U64)hwnd}; return result; } internal void os_focus_external_window(OS_Handle handle) { HWND hwnd = (HWND)handle.u64[0]; if(hwnd != 0) { SetForegroundWindow(hwnd); SetFocus(hwnd); } } //////////////////////////////// //~ rjf: @os_hooks Monitors (Implemented Per-OS) internal OS_HandleArray os_push_monitors_array(Arena *arena) { Temp scratch = scratch_begin(&arena, 1); OS_HandleList list = {0}; { OS_W32_MonitorGatherBundle bundle = {arena, &list}; EnumDisplayMonitors(0, 0, os_w32_monitor_gather_enum_proc, (LPARAM)&bundle); } OS_HandleArray array = os_handle_array_from_list(arena, &list); scratch_end(scratch); return array; } internal OS_Handle os_primary_monitor(void) { POINT zero_pt = {0, 0}; HMONITOR monitor = MonitorFromPoint(zero_pt, MONITOR_DEFAULTTOPRIMARY); OS_Handle result = {(U64)monitor}; return result; } internal OS_Handle os_monitor_from_window(OS_Handle window) { OS_W32_Window *w = os_w32_window_from_handle(window); HMONITOR handle = MonitorFromWindow(w->hwnd, MONITOR_DEFAULTTOPRIMARY); OS_Handle result = {(U64)handle}; return result; } internal String8 os_name_from_monitor(Arena *arena, OS_Handle monitor) { String8 result = {0}; HMONITOR monitor_handle = (HMONITOR)monitor.u64[0]; MONITORINFOEXW info; info.cbSize = sizeof(MONITORINFOEXW); if(GetMonitorInfoW(monitor_handle, (MONITORINFO *)&info)) { String16 result16 = str16_cstring((U16 *)info.szDevice); result = str8_from_16(arena, result16); } return result; } internal Vec2F32 os_dim_from_monitor(OS_Handle monitor) { Vec2F32 result = {0}; HMONITOR monitor_handle = (HMONITOR)monitor.u64[0]; MONITORINFO info = {0}; info.cbSize = sizeof(MONITORINFO); if(GetMonitorInfoW(monitor_handle, &info)) { result.x = info.rcWork.right - info.rcWork.left; result.y = info.rcWork.bottom - info.rcWork.top; } return result; } internal F32 os_dpi_from_monitor(OS_Handle monitor) { F32 result = 96.f; HMONITOR monitor_handle = (HMONITOR)monitor.u64[0]; if(w32_GetDpiForMonitor_func != 0) { UINT dpi_x = 0; UINT dpi_y = 0; HRESULT hr = w32_GetDpiForMonitor_func(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y); result = (F32)dpi_x; } return result; } //////////////////////////////// //~ rjf: @os_hooks Events (Implemented Per-OS) internal void os_send_wakeup_event(void) { PostThreadMessageA(os_w32_gfx_state->gfx_thread_tid, 0x401, 0, 0); } internal OS_EventList os_get_events(Arena *arena, B32 wait) { os_w32_event_arena = arena; MemoryZeroStruct(&os_w32_event_list); MSG msg = {0}; if(!wait || GetMessage(&msg, 0, 0, 0)) { B32 first_wait = wait; for(;first_wait || PeekMessage(&msg, 0, 0, 0, PM_REMOVE); first_wait = 0) { DispatchMessage(&msg); TranslateMessage(&msg); if(msg.message == WM_QUIT) { os_w32_push_event(OS_EventKind_WindowClose, 0); } } } return os_w32_event_list; } internal OS_Modifiers os_get_modifiers(void) { OS_Modifiers modifiers = 0; if(GetKeyState(VK_CONTROL) & 0x8000) { modifiers |= OS_Modifier_Ctrl; } if(GetKeyState(VK_SHIFT) & 0x8000) { modifiers |= OS_Modifier_Shift; } if(GetKeyState(VK_MENU) & 0x8000) { modifiers |= OS_Modifier_Alt; } return modifiers; } internal B32 os_key_is_down(OS_Key key) { B32 down = 0; WPARAM vkey = os_w32_vkey_from_os_key(key); if(GetKeyState(vkey) & 0x8000) { down = 1; } return down; } internal Vec2F32 os_mouse_from_window(OS_Handle handle) { ProfBeginFunction(); Vec2F32 v = {0}; POINT p; if(GetCursorPos(&p)) { OS_W32_Window *window = os_w32_window_from_handle(handle); ScreenToClient(window->hwnd, &p); v.x = (F32)p.x; v.y = (F32)p.y; } ProfEnd(); return v; } //////////////////////////////// //~ rjf: @os_hooks Cursors (Implemented Per-OS) internal void os_set_cursor(OS_Cursor cursor) { B32 valid_cursor = 1; HCURSOR hcursor = 0; switch(cursor) { default: {valid_cursor = 0;}break; #define Win32CursorXList(X) \ X(Pointer, IDC_ARROW) \ X(IBar, IDC_IBEAM) \ X(LeftRight, IDC_SIZEWE) \ X(UpDown, IDC_SIZENS) \ X(DownRight, IDC_SIZENWSE) \ X(UpRight, IDC_SIZENESW) \ X(UpDownLeftRight, IDC_SIZEALL) \ X(HandPoint, IDC_HAND)\ X(Disabled, IDC_NO) #define CursorCase(E,R) case OS_Cursor_##E:{ \ local_persist HCURSOR curs = 0; \ if (curs == 0){ curs = LoadCursor(NULL, R); } \ hcursor = curs; }break; Win32CursorXList(CursorCase) #undef CursorCase #undef Win32CursorXList } if(valid_cursor && !os_w32_resizing) { if(hcursor != os_w32_gfx_state->hCursor) { PostMessage(0, WM_SETCURSOR, 0, 0); POINT p = {0}; GetCursorPos(&p); SetCursorPos(p.x, p.y); } os_w32_gfx_state->hCursor = hcursor; } } //////////////////////////////// //~ rjf: @os_hooks Native User-Facing Graphical Messages (Implemented Per-OS) internal void os_graphical_message(B32 error, String8 title, String8 message) { Temp scratch = scratch_begin(0, 0); String16 title16 = str16_from_8(scratch.arena, title); String16 message16 = str16_from_8(scratch.arena, message); MessageBoxW(0, (WCHAR *)message16.str, (WCHAR *)title16.str, MB_OK|(!!error*MB_ICONERROR)); scratch_end(scratch); } internal String8 os_graphical_pick_file(Arena *arena, String8 initial_path) { String8 result = {0}; { Temp scratch = scratch_begin(&arena, 1); U64 buffer_size = 4096; U16 *buffer = push_array(scratch.arena, U16, buffer_size); OPENFILENAMEW params = {sizeof(params)}; { params.lpstrFile = (WCHAR *)buffer; params.nMaxFile = buffer_size; params.lpstrInitialDir = (WCHAR *)str16_from_8(scratch.arena, initial_path).str; } if(GetOpenFileNameW(¶ms)) { result = str8_from_16(arena, str16_cstring((U16 *)buffer)); } scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: @os_hooks Shell Operations internal void os_show_in_filesystem_ui(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); for(U64 idx = 0; idx < path_copy.size; idx += 1) { if(path_copy.str[idx] == '/') { path_copy.str[idx] = '\\'; } } String16 path16 = str16_from_8(scratch.arena, path_copy); SFGAOF flags = 0; PIDLIST_ABSOLUTE list = 0; if(path16.size != 0 && SUCCEEDED(SHParseDisplayName(path16.str, 0, &list, 0, &flags))) { HRESULT hr = SHOpenFolderAndSelectItems(list, 0, 0, 0); CoTaskMemFree(list); (void)hr; } scratch_end(scratch); } internal void os_open_in_browser(String8 url) { Temp scratch = scratch_begin(0, 0); String16 url16 = str16_from_8(scratch.arena, url); ShellExecuteW(0, L"open", (WCHAR *)url16.str, 0, 0, SW_SHOWNORMAL); scratch_end(scratch); } ================================================ FILE: src/os/gfx/win32/os_gfx_win32.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_WIN32_H #define OS_GFX_WIN32_H //////////////////////////////// //~ rjf: Includes / Libraries #include #include #include #pragma comment(lib, "gdi32") #pragma comment(lib, "dwmapi") #pragma comment(lib, "UxTheme") #pragma comment(lib, "ole32") #pragma comment(lib, "user32") #pragma comment(lib, "comdlg32") #ifndef WM_NCUAHDRAWCAPTION #define WM_NCUAHDRAWCAPTION (0x00AE) #endif #ifndef WM_NCUAHDRAWFRAME #define WM_NCUAHDRAWFRAME (0x00AF) #endif //////////////////////////////// //~ rjf: Windows typedef struct OS_W32_TitleBarClientArea OS_W32_TitleBarClientArea; struct OS_W32_TitleBarClientArea { OS_W32_TitleBarClientArea *next; Rng2F32 rect; }; typedef struct OS_W32_Window OS_W32_Window; struct OS_W32_Window { OS_W32_Window *next; OS_W32_Window *prev; HWND hwnd; HDC hdc; WINDOWPLACEMENT last_window_placement; F32 dpi; B32 first_paint_done; B32 maximized; B32 custom_border; F32 custom_border_title_thickness; F32 custom_border_edge_thickness; B32 custom_border_composition_enabled; Arena *paint_arena; OS_W32_TitleBarClientArea *first_title_bar_client_area; OS_W32_TitleBarClientArea *last_title_bar_client_area; }; //////////////////////////////// //~ rjf: Monitor Gathering Bundle typedef struct OS_W32_MonitorGatherBundle OS_W32_MonitorGatherBundle; struct OS_W32_MonitorGatherBundle { Arena *arena; OS_HandleList *list; }; //////////////////////////////// //~ rjf: Global State typedef struct OS_W32_GfxState OS_W32_GfxState; struct OS_W32_GfxState { Arena *arena; U32 gfx_thread_tid; HINSTANCE hInstance; HCURSOR hCursor; OS_GfxInfo gfx_info; OS_W32_Window *first_window; OS_W32_Window *last_window; OS_W32_Window *free_window; OS_Key key_from_vkey_table[256]; }; //////////////////////////////// //~ rjf: Globals global OS_W32_GfxState *os_w32_gfx_state = 0; global OS_EventList os_w32_event_list = {0}; global Arena *os_w32_event_arena = 0; global B32 os_w32_resizing = 0; global B32 os_w32_new_window_custom_border = 0; //////////////////////////////// //~ rjf: Basic Helpers internal Rng2F32 os_w32_rng2f32_from_rect(RECT rect); //////////////////////////////// //~ rjf: Windows internal OS_Handle os_w32_handle_from_window(OS_W32_Window *window); internal OS_W32_Window * os_w32_window_from_handle(OS_Handle window); internal OS_W32_Window * os_w32_window_from_hwnd(HWND hwnd); internal HWND os_w32_hwnd_from_window(OS_W32_Window *window); internal OS_W32_Window * os_w32_window_alloc(void); internal void os_w32_window_release(OS_W32_Window *window); internal OS_Event * os_w32_push_event(OS_EventKind kind, OS_W32_Window *window); internal OS_Key os_w32_os_key_from_vkey(WPARAM vkey); internal WPARAM os_w32_vkey_from_os_key(OS_Key key); internal LRESULT os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //////////////////////////////// //~ rjf: Monitors internal BOOL os_w32_monitor_gather_enum_proc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM bundle_ptr); #endif // OS_GFX_WIN32_H ================================================ FILE: src/os/os_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "os/core/os_core.c" #if OS_FEATURE_GRAPHICAL # include "os/gfx/os_gfx.c" #endif #if OS_WINDOWS # include "os/core/win32/os_core_win32.c" #elif OS_LINUX # include "os/core/linux/os_core_linux.c" #else # error OS core layer not implemented for this operating system. #endif #if OS_FEATURE_GRAPHICAL # if OS_GFX_STUB # include "os/gfx/stub/os_gfx_stub.c" # elif OS_WINDOWS # include "os/gfx/win32/os_gfx_win32.c" # elif OS_LINUX # include "os/gfx/linux/os_gfx_linux.c" # else # error OS graphical layer not implemented for this operating system. # endif #endif ================================================ FILE: src/os/os_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_INC_H #define OS_INC_H #if !defined(OS_FEATURE_GRAPHICAL) # define OS_FEATURE_GRAPHICAL 0 #endif #if !defined(OS_GFX_STUB) # define OS_GFX_STUB 0 #endif #include "os/core/os_core.h" #if OS_FEATURE_GRAPHICAL # include "os/gfx/os_gfx.h" #endif #if OS_WINDOWS # include "os/core/win32/os_core_win32.h" #elif OS_LINUX # include "os/core/linux/os_core_linux.h" #else # error OS core layer not implemented for this operating system. #endif #if OS_FEATURE_GRAPHICAL # if OS_GFX_STUB # include "os/gfx/stub/os_gfx_stub.h" # elif OS_WINDOWS # include "os/gfx/win32/os_gfx_win32.h" # elif OS_LINUX # include "os/gfx/linux/os_gfx_linux.h" # else # error OS graphical layer not implemented for this operating system. # endif #endif #endif // OS_INC_H ================================================ FILE: src/pdb/pdb.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U32 pdb_hash_v1(String8 string) { U32 result = 0; U8 *ptr = string.str; U8 *opl = ptr + (string.size&(~3)); for(; ptr < opl; ptr += 4) { result ^= *(U32*)ptr; } if((string.size&2) != 0) { result ^= *(U16*)ptr; ptr += 2; } if((string.size&1) != 0) { result ^= *ptr; } result |= 0x20202020; result ^= (result >> 11); result ^= (result >> 16); return result; } ================================================ FILE: src/pdb/pdb.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_H #define PDB_H // https://github.com/microsoft/microsoft-pdb/tree/master/PDB //////////////////////////////// //~ PDB String Table Types #define PDB_INVALID_STRING_INDEX max_U32 typedef U32 PDB_StringIndex; typedef U32 PDB_StringOffset; enum { PDB_StringTableHeader_MAGIC = 0xEFFEEFFE }; enum { PDB_StringTableHeader_Version1 = 1, PDB_StringTableHeader_CurrentVersion = PDB_StringTableHeader_Version1 }; typedef struct PDB_StringTableHeader { U32 magic; U32 version; } PDB_StringTableHeader; //////////////////////////////// typedef enum PDB_FixedStream { PDB_FixedStream_Info = 1, PDB_FixedStream_Tpi = 2, PDB_FixedStream_Dbi = 3, PDB_FixedStream_Ipi = 4 } PDB_FixedStream; //////////////////////////////// //~ PDB Info Types typedef U32 PDB_InfoVersion; enum{ PDB_InfoVersion_VC2 = 19941610, PDB_InfoVersion_VC4 = 19950623, PDB_InfoVersion_VC41 = 19950814, PDB_InfoVersion_VC50 = 19960307, PDB_InfoVersion_VC98 = 19970604, PDB_InfoVersion_VC70_DEP = 19990604, PDB_InfoVersion_VC70 = 20000404, PDB_InfoVersion_VC80 = 20030901, PDB_InfoVersion_VC110 = 20091201, PDB_InfoVersion_VC140 = 20140508 }; // referenced in PDB1::loadPdbStream enum { PDB_FeatureSig_NULL = 0, PDB_FeatureSig_VC110 = PDB_InfoVersion_VC110, PDB_FeatureSig_VC140 = PDB_InfoVersion_VC140, PDB_FeatureSig_NO_TYPE_MERGE = 0x4D544F4E, PDB_FeatureSig_MINIMAL_DEBUG_INFO = 0x494E494D, }; typedef U32 PDB_FeatureSig; enum { PDB_FeatureFlag_HAS_ID_STREAM = (1 << 0), PDB_FeatureFlag_NO_TYPE_MERGE = (1 << 1), PDB_FeatureFlag_MINIMAL_DBG_INFO = (1 << 2), }; typedef U32 PDB_FeatureFlags; #pragma pack(push,1) typedef struct PDB_InfoHeaderV70 { PDB_InfoVersion version; COFF_TimeStamp time_stamp; U32 age; Guid guid; // PDB_HashTable named_stream_hash_table // PDB_FeatureFlag features[*] } PDB_InfoHeaderV70; #pragma pack(pop) StaticAssert(sizeof(PDB_InfoHeaderV70) == 28, pdb_info_header_v70_size_check); #define PDB_SRC_HEADER_BLOCK_STREAM_NAME str8_lit("/src/headerblock") #define PDB_LINK_INFO_STREAM_NAME str8_lit("/LinkInfo") #define PDB_NAMES_STREAM_NAME str8_lit("/names") //////////////////////////////// // SRC Header Block #define PDB_SRC_HEADER_BLOCK_MAGIC_V1 19980827 typedef struct PDB_SrcHeaderBlockHeader { U32 version; U32 stream_size; U64 file_time; U32 age; U8 pad[44]; } PDB_SrcHeaderBlockHeader; enum { PDB_SrcComp_NULL, PDB_SrcComp_RUN_LENGTH_RECORD, PDB_SrcComp_HUFFMAN, PDB_SrcComp_LZ, PDB_SrcComp_DOTNET }; typedef U8 PDB_SrcCompType; enum { PDB_SrcHeaderBlockEntryFlag_IS_VIRTUAL = (1 << 0) }; typedef U8 PDB_SrcHeaderFlags; // (PDB/include/pdb.h: SrcHeaderOut) typedef struct PDB_SrcHeaderBlockEntry { U32 size; U32 version; U32 file_crc; U32 file_size; PDB_StringOffset file_path; PDB_StringOffset obj; PDB_StringOffset virt_path; PDB_SrcCompType comp; PDB_SrcHeaderFlags flags; U8 pad[2]; U8 reserved[8]; } PDB_SrcHeaderBlockEntry; //////////////////////////////// //~ PDB Format DBI Types typedef U32 PDB_DbiStream; enum { PDB_DbiStream_FPO, PDB_DbiStream_EXCEPTION, PDB_DbiStream_FIXUP, PDB_DbiStream_OMAP_TO_SRC, PDB_DbiStream_OMAP_FROM_SRC, PDB_DbiStream_SECTION_HEADER, PDB_DbiStream_TOKEN_RDI_MAP, PDB_DbiStream_XDATA, PDB_DbiStream_PDATA, PDB_DbiStream_NEW_FPO, PDB_DbiStream_SECTION_HEADER_ORIG, PDB_DbiStream_COUNT }; typedef U32 PDB_DbiHeaderSignature; enum { PDB_DbiHeaderSignature_V1 = 0xFFFFFFFF }; typedef U32 PDB_DbiVersion; enum { PDB_DbiVersion_41 = 930803, PDB_DbiVersion_50 = 19960307, PDB_DbiVersion_60 = 19970606, PDB_DbiVersion_70 = 19990903, PDB_DbiVersion_110 = 20091201, }; typedef U16 PDB_DbiBuildNumber; #define PDB_DbiBuildNumberNewFormatFlag 0x8000 #define PDB_DbiBuildNumberMinor(bn) ((bn)&0xFF) #define PDB_DbiBuildNumberMajor(bn) (((bn) >> 8)&0x7F) #define PDB_DbiBuildNumberNewFormat(bn) (!!((bn)&PDB_DbiBuildNumberNewFormatFlag)) #define PDB_DbiMakeBuildNumber(maj, min) (PDB_DbiBuildNumber)(PDB_DbiBuildNumberNewFormatFlag | ((min)&0xFF) | (((maj)&0x7F) << 16)) typedef U16 PDB_DbiHeaderFlags; enum { PDB_DbiHeaderFlag_Incremental = 0x1, PDB_DbiHeaderFlag_Stripped = 0x2, PDB_DbiHeaderFlag_CTypes = 0x4 }; typedef struct PDB_DbiHeader { PDB_DbiHeaderSignature sig; PDB_DbiVersion version; U32 age; MSF_StreamNumber gsi_sn; PDB_DbiBuildNumber build_number; MSF_StreamNumber psi_sn; U16 pdb_version; MSF_StreamNumber sym_sn; U16 pdb_version2; U32 module_info_size; U32 sec_con_size; U32 sec_map_size; U32 file_info_size; U32 tsm_size; U32 mfc_index; U32 dbg_header_size; U32 ec_info_size; PDB_DbiHeaderFlags flags; COFF_MachineType machine; U32 reserved; } PDB_DbiHeader; // "ModuleInfo" DBI range typedef U32 PDB_DbiSectionContribVersion; #define PDB_DbiSectionContribVersion_1 (0xeffe0000u + 19970605u) #define PDB_DbiSectionContribVersion_2 (0xeffe0000u + 20140516u) typedef struct PDB_DbiSectionContrib40 { CV_SectionIndex sec; U16 pad0; U32 sec_off; U32 size; U32 flags; CV_ModIndex mod; U16 pad1; } PDB_DbiSectionContrib40; typedef struct PDB_DbiSectionContrib { PDB_DbiSectionContrib40 base; U32 data_crc; U32 reloc_crc; } PDB_DbiSectionContrib; typedef struct PDB_DbiSectionContrib2 { PDB_DbiSectionContrib40 base; U32 data_crc; U32 reloc_crc; U32 sec_coff; } PDB_DbiSectionContrib2; typedef struct PDB_DbiCompUnitHeader { U32 unused; PDB_DbiSectionContrib contribution; U16 flags; // unknown MSF_StreamNumber sn; U32 symbols_size; U32 c11_lines_size; U32 c13_lines_size; U16 num_contrib_files; U16 unused2; U32 file_names_offset; PDB_StringIndex src_file; PDB_StringIndex pdb_file; // U8[] module_name (null terminated) // U8[] obj_name (null terminated) } PDB_DbiCompUnitHeader; //////////////////////////////// enum { PDB_DbiOMF_NONE = 0, PDB_DbiOMF_READ = (1 << 0), PDB_DbiOMF_WRITE = (1 << 1), PDB_DbiOMF_EXEC = (1 << 2), PDB_DbiOMF_IS_32BIT_ADDR = (1 << 3), // Descritor is 32-bit address PDB_DbiOMF_IS_SELECTOR = (1 << 8), // Frame is a selector PDB_DbiOMF_IS_ABS_ADDR = (1 << 9), // Frame is absolute address PDB_DbiOMF_IS_GROUP = (1 << 10) // Descriptor is a group }; typedef U16 PDB_DbiOMF; typedef struct PDB_DbiSecMapEntry { PDB_DbiOMF flags; U16 ovl; U16 group; U16 frame; U16 sec_name; U16 class_name; U32 offset; U32 sec_size; } PDB_DbiSecMapEntry; typedef struct PDB_DbiSecMapHeader { U16 section_count; U16 segment_count; } PDB_DbiSecMapHeader; //////////////////////////////// //~ PDB Format TPI/IPI Types typedef U32 PDB_TpiVersion; enum { PDB_TpiVersion_INTV_VC2 = 920924, PDB_TpiVersion_IMPV40 = 19950410, PDB_TpiVersion_IMPV41 = 19951122, PDB_TpiVersion_IMPV50_INTERIM = 19960307, PDB_TpiVersion_IMPV50 = 19961031, PDB_TpiVersion_IMPV70 = 19990903, PDB_TpiVersion_IMPV80 = 20040203, }; enum { PDB_TYPE_SERVER_HASH_BUCKET_COUNT_V7 = 0x1000, PDB_TYPE_SERVER_HASH_BUCKET_COUNT_V8 = 0x3FFF, PDB_TYPE_SERVER_HASH_BUCKET_COUNT_INIT = 0x1000, PDB_TYPE_SERVER_HASH_BUCKET_COUNT_MAX = 0x40000, PDB_TYPE_SERVER_HASH_BUCKET_COUNT_CURRENT = PDB_TYPE_SERVER_HASH_BUCKET_COUNT_V8, }; #define PDB_TYPE_OFFSET_MAX max_U32 typedef U32 PDB_TypeOffset; typedef struct PDB_TpiOffHint { CV_TypeId itype; PDB_TypeOffset off; } PDB_TpiOffHint; typedef struct PDB_OffsetSize { U32 off; U32 size; } PDB_OffsetSize; typedef struct PDB_TpiHeader { // (HDR) PDB_TpiVersion version; U32 header_size; U32 ti_lo; U32 ti_hi; U32 leaf_data_size; // (PdbTpiHash) MSF_StreamNumber hash_sn; MSF_StreamNumber hash_sn_aux; U32 hash_key_size; U32 hash_bucket_count; PDB_OffsetSize hash_vals; PDB_OffsetSize itype_offs; PDB_OffsetSize hash_adj; } PDB_TpiHeader; //////////////////////////////// //~ PDB Format GSI Types typedef U32 PDB_GsiSignature; enum { PDB_GsiSignature_Basic = 0xffffffff, }; typedef U32 PDB_GsiVersion; enum { PDB_GsiVersion_V70 = 0xeffe0000 + 19990810, }; typedef struct PDB_GsiHeader { PDB_GsiSignature signature; PDB_GsiVersion version; U32 hash_record_arr_size; U32 bucket_data_size; } PDB_GsiHeader; typedef struct PDB_GsiHashRecord { U32 symbol_off; U32 cref; } PDB_GsiHashRecord; typedef struct PDB_GsiHashRecordOffsetCalc { U32 next; U32 off; U32 cref; } PDB_GsiHashRecordOffsetCalc; typedef struct PDB_PsiHeader { U32 sym_hash_size; U32 addr_map_size; U32 thunk_count; U32 thunk_size; CV_SectionIndex isec_thunk_table; U16 padding; U32 sec_thunk_table_off; U32 sec_count; } PDB_PsiHeader; //////////////////////////////// internal U32 pdb_hash_v1(String8 string); #endif // PDB_H ================================================ FILE: src/pdb/pdb_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ PDB Parser Functions internal PDB_Info* pdb_info_from_data(Arena *arena, String8 data){ ProfBegin("pdb_info_from_data"); // get header PDB_InfoHeader *header = 0; if (data.size >= sizeof(*header)){ header = (PDB_InfoHeader *)data.str; } PDB_Info *result = 0; if (header != 0){ // read guid Guid *auth_guid = 0; U32 after_auth_guid_off = sizeof(*header); switch (header->version){ case PDB_InfoVersion_VC70_DEP: case PDB_InfoVersion_VC70: case PDB_InfoVersion_VC80: case PDB_InfoVersion_VC110: case PDB_InfoVersion_VC140: { auth_guid = (Guid*)(data.str + after_auth_guid_off); after_auth_guid_off = sizeof(*header) + sizeof(*auth_guid); }break; default: {}break; } if (header->version != 0){ // table layout: names U32 names_len_off = after_auth_guid_off; U32 names_len = 0; if (names_len_off + 4 <= data.size){ names_len = *(U32*)(data.str + names_len_off); } U32 names_base_off = names_len_off + 4; U32 names_base_opl = names_base_off + names_len; // table layout: hash table U32 hash_table_count_off = names_base_opl; U32 hash_table_max_off = hash_table_count_off + 4; U32 hash_table_count = 0; U32 hash_table_max = 0; if (hash_table_max_off + 4 <= data.size){ hash_table_count = *(U32*)(data.str + hash_table_count_off); hash_table_max = *(U32*)(data.str + hash_table_max_off); } // table layout: words U32 num_present_words_off = hash_table_max_off + 4; U32 num_present_words = 0; if (hash_table_max_off + 4 <= data.size){ num_present_words = *(U32*)(data.str + num_present_words_off); } U32 present_words_array_off = num_present_words_off + 4; U32 num_deleted_words_off = present_words_array_off + num_present_words*sizeof(U32); U32 num_deleted_words = 0; if (num_deleted_words_off + 4 <= data.size){ num_deleted_words = *(U32*)(data.str + num_deleted_words_off); } U32 deleted_words_array_off = num_deleted_words_off + 4; // table layout: epilogue U32 epilogue_base_off = deleted_words_array_off + num_deleted_words*sizeof(U32); if (epilogue_base_off <= data.size){ U64 record_off = epilogue_base_off; // read table if (hash_table_count > 0) { PDB_InfoNode *first = 0; PDB_InfoNode *last = 0; for (U32 i = 0; i < hash_table_count; i += 1, record_off += 8){ U32 *record = (U32*)(data.str + record_off); U32 relative_name_off = record[0]; MSF_StreamNumber sn = (MSF_StreamNumber)record[1]; U32 name_off = names_base_off + relative_name_off; String8 name = str8_cstring_capped((char*)(data.str + name_off), (char*)(data.str + names_base_opl)); // push info node PDB_InfoNode *node = push_array(arena, PDB_InfoNode, 1); SLLQueuePush(first, last, node); node->string = name; node->sn = sn; } result = push_array(arena, PDB_Info, 1); result->first = first; result->last = last; result->auth_guid = *auth_guid; } // read PDB features PDB_FeatureFlags features = 0; for (; record_off + sizeof(PDB_FeatureSig) <= data.size; ) { PDB_FeatureSig sig = 0; record_off += str8_deserial_read_struct(data, record_off, &sig); switch (sig) { case PDB_FeatureSig_NULL: break; case PDB_FeatureSig_VC140: features |= PDB_FeatureFlag_HAS_ID_STREAM; break; case PDB_FeatureSig_NO_TYPE_MERGE: features |= PDB_FeatureFlag_NO_TYPE_MERGE; break; case PDB_FeatureSig_MINIMAL_DEBUG_INFO: features |= PDB_FeatureFlag_MINIMAL_DBG_INFO; break; } } result->features = features; } } } ProfEnd(); return(result); } internal PDB_NamedStreamTable* pdb_named_stream_table_from_info(Arena *arena, PDB_Info *info){ ProfBegin("pdb_named_stream_table_from_info"); // mapping "NamedStream" indexes to strings struct StreamNameIndexPair{ PDB_NamedStream index; String8 name; }; struct StreamNameIndexPair pairs[] = { {PDB_NamedStream_HeaderBlock, str8_lit("/src/headerblock")}, {PDB_NamedStream_StringTable, str8_lit("/names")}, {PDB_NamedStream_LinkInfo, str8_lit("/LinkInfo")}, }; // build baked table PDB_NamedStreamTable *result = push_array(arena, PDB_NamedStreamTable, 1); struct StreamNameIndexPair *p = pairs; for (U64 i = 0; i < ArrayCount(pairs); i += 1, p += 1){ String8 name = p->name; // get info node with this name PDB_InfoNode *match = 0; for (PDB_InfoNode *node = info->first; node != 0; node = node->next){ if (str8_match(name, node->string, 0)){ match = node; break; } } // if match found save stream number if (match != 0){ result->sn[p->index] = match->sn; } else{ result->sn[p->index] = 0xFFFF; } } ProfEnd(); return(result); } internal PDB_Strtbl* pdb_strtbl_from_data(Arena *arena, String8 data){ ProfBegin("pdb_strtbl_from_data"); // get header PDB_StringTableHeader *header = 0; if (sizeof(*header) <= data.size){ header = (PDB_StringTableHeader *)data.str; } PDB_Strtbl *result = push_array(arena, PDB_Strtbl, 1); if (header != 0 && header->magic == PDB_StringTableHeader_MAGIC && header->version == 1){ U32 strblock_size_off = sizeof(*header); U32 strblock_size = 0; if (strblock_size_off + 4 <= data.size){ strblock_size = *(U32*)(data.str + strblock_size_off); } U32 strblock_off = strblock_size_off + 4; U32 bucket_count_off = strblock_off + strblock_size; U32 bucket_count = 0; if (bucket_count_off + 4 <= data.size){ bucket_count = *(U32*)(data.str + bucket_count_off); } U32 bucket_array_off = bucket_count_off + 4; U32 bucket_array_size = bucket_count*sizeof(PDB_StringIndex); if (bucket_array_off + bucket_array_size <= data.size){ result->data = data; result->bucket_count = bucket_count; result->strblock_min = strblock_off; result->strblock_max = strblock_off + strblock_size; result->buckets_min = bucket_array_off; result->buckets_max = bucket_array_off + bucket_array_size; } } ProfEnd(); return(result); } internal PDB_DbiParsed * pdb_dbi_from_data(Arena *arena, String8 data) { ProfBeginFunction(); PDB_DbiParsed *result = push_array(arena, PDB_DbiParsed, 1);; // rjf: extract header PDB_DbiHeader *header = 0; if(sizeof(*header) <= data.size) { header = (PDB_DbiHeader*)data.str; } // rjf: parse if(header != 0 && header->sig == PDB_DbiHeaderSignature_V1) { // extract range sizes U64 range_size[PDB_DbiRange_COUNT]; range_size[PDB_DbiRange_ModuleInfo] = header->module_info_size; range_size[PDB_DbiRange_SecCon] = header->sec_con_size; range_size[PDB_DbiRange_SecMap] = header->sec_map_size; range_size[PDB_DbiRange_FileInfo] = header->file_info_size; range_size[PDB_DbiRange_TSM] = header->tsm_size; range_size[PDB_DbiRange_EcInfo] = header->ec_info_size; range_size[PDB_DbiRange_DbgHeader] = header->dbg_header_size; // fill result result->data = data; result->machine_type = header->machine; result->gsi_sn = header->gsi_sn; result->psi_sn = header->psi_sn; result->sym_sn = header->sym_sn; // fill result's range offsets { U64 cursor = sizeof(*header); for(U64 i = 0; i < (U64)(PDB_DbiRange_COUNT); i += 1) { result->range_off[i] = cursor; cursor += range_size[i]; cursor = ClampTop(cursor, data.size); } result->range_off[PDB_DbiRange_COUNT] = cursor; } // fill result's debug streams U64 dbg_streams_min = result->range_off[PDB_DbiRange_DbgHeader]; U64 dbg_streams_max = result->range_off[PDB_DbiRange_DbgHeader + 1]; U64 dbg_streams_size_raw = dbg_streams_max - dbg_streams_min; U64 dbg_streams_size = ClampTop(dbg_streams_size_raw, sizeof(result->dbg_streams)); MemoryCopy(result->dbg_streams, data.str + dbg_streams_min, dbg_streams_size); if(dbg_streams_size < sizeof(result->dbg_streams)) { U64 filled_count = dbg_streams_size/sizeof(MSF_StreamNumber); MemorySet(result->dbg_streams + filled_count, 0xff, (ArrayCount(result->dbg_streams) - filled_count)*sizeof(MSF_StreamNumber)); } } ProfEnd(); return result; } internal PDB_TpiParsed * pdb_tpi_from_data(Arena *arena, String8 data) { ProfBeginFunction(); PDB_TpiParsed *result = push_array(arena, PDB_TpiParsed, 1); // rjf: extract header PDB_TpiHeader *header = 0; if (sizeof(*header) <= data.size){ header = (PDB_TpiHeader*)data.str; } // rjf: parse if(header != 0 && header->version == PDB_TpiVersion_IMPV80) { U64 leaf_first_raw = header->header_size; U64 leaf_first = ClampTop(leaf_first_raw, data.size); U64 leaf_opl_raw = leaf_first + header->leaf_data_size; U64 leaf_opl = ClampTop(leaf_opl_raw, data.size); result->data = data; result->leaf_first = leaf_first; result->leaf_opl = leaf_opl; result->itype_first = header->ti_lo; result->itype_opl = header->ti_hi; result->hash_sn = header->hash_sn; result->hash_sn_aux = header->hash_sn_aux; result->hash_key_size = header->hash_key_size; result->hash_bucket_count = header->hash_bucket_count; result->hash_vals_off = header->hash_vals.off; result->hash_vals_size = header->hash_vals.size; result->itype_off = header->itype_offs.off; result->itype_size = header->itype_offs.size; result->hash_adj_off = header->hash_adj.off; result->hash_adj_size = header->hash_adj.size; } ProfEnd(); return result; } internal PDB_TpiHashParsed* pdb_tpi_hash_from_data(Arena *arena, PDB_Strtbl *strtbl, PDB_TpiParsed *tpi, String8 data, String8 aux_data) { ProfBeginFunction(); PDB_TpiHashParsed *result = push_array(arena, PDB_TpiHashParsed, 1); U32 stride = tpi->hash_key_size; U32 bucket_count = tpi->hash_bucket_count; if(1 <= stride && stride <= 8 && bucket_count > 0 && data.str != 0) { // allocate buckets PDB_TpiHashBlock **buckets = push_array(arena, PDB_TpiHashBlock*, bucket_count); // extract "hash" array U8 *hashes = data.str + tpi->hash_vals_off; U8 *hash_opl = hashes + tpi->hash_vals_size; // for each index in the array... CV_TypeId itype = tpi->itype_first; U8 *hash_cursor = hashes; for (;hash_cursor + stride <= hash_opl;){ // read index U64 bucket_idx = 0; MemoryCopy(&bucket_idx, hash_cursor, stride); // save to map if (bucket_idx < bucket_count){ PDB_TpiHashBlock *block = buckets[bucket_idx]; if (block == 0 || block->local_count == ArrayCount(block->itypes)){ block = push_array(arena, PDB_TpiHashBlock, 1); SLLStackPush(buckets[bucket_idx], block); } if(block->local_count != 0) { MemoryCopy(block->itypes+1, block->itypes, sizeof(CV_TypeId)*block->local_count); } block->itypes[0] = itype; block->local_count += 1; } // advance cursor hash_cursor += stride; itype += 1; } //- rjf: compute bucket mask U32 bucket_mask = 0; if(IsPow2OrZero(bucket_count)) { bucket_mask = bucket_count-1; } //- rjf: apply hash adjustments, to pull correct type IDs to the front of // the chains if(tpi->hash_adj_size != 0) { // NOTE(rjf): this table is laid out in the following format: // // pair_count: U32 -> # of name_index/type_index pairs // slot_count: U32 -> # of slots in this hash table // present_bit_array_count: U32 -> count for next array // present_bit_array: U32[present_bit_array_count] -> 1 bit per slot, "is present" // deleted_bit_array_count: U32 -> count for next array // deleted_bit_array: U32[deleted_bit_array_count] -> 1 bit per slot, "is deleted" // (U32, U32)[pair_count] -> array of name_index/type_index pairs // U8 *adjs = data.str + tpi->hash_adj_off; U8 *adjs_opl = adjs + tpi->hash_adj_size; U8 *adjs_cursor = adjs; U32 pair_count = *(U32 *)adjs_cursor; adjs_cursor += sizeof(U32); U32 slot_count = *(U32 *)adjs_cursor; adjs_cursor += sizeof(U32); U32 present_bit_array_count = *(U32 *)adjs_cursor; // skip present_bit_array adjs_cursor += sizeof(U32); adjs_cursor += present_bit_array_count*sizeof(U32); U32 deleted_bit_array_count = *(U32 *)adjs_cursor; // skip deleted_bit_array adjs_cursor += sizeof(U32); adjs_cursor += deleted_bit_array_count*sizeof(U32); U32 adjs_stride = sizeof(U32)*2; U32 pair_idx = 0; for(;adjs_cursor < adjs_opl && pair_idx < pair_count; adjs_cursor += adjs_stride, pair_idx += 1) { U32 name_off = ((U32 *)adjs_cursor)[0]; CV_TypeId type_id = ((CV_TypeId *)adjs_cursor)[1]; String8 string = pdb_strtbl_string_from_off(strtbl, name_off); U32 hash = pdb_hash_v1(string); U32 bucket_idx = ((bucket_mask != 0) ? hash&bucket_mask : hash%bucket_count); PDB_TpiHashBlock *prev_block = 0; for(PDB_TpiHashBlock *block = buckets[bucket_idx]; block != 0; prev_block = block, block = block->next) { for(U32 local_idx = 0; local_idx < block->local_count && local_idx < ArrayCount(block->itypes); local_idx += 1) { if(block->itypes[local_idx] == type_id) { if(prev_block != 0) { prev_block->next = block->next; block->next = buckets[bucket_idx]; buckets[bucket_idx] = block; } if(local_idx != 0) { Swap(CV_TypeId, block->itypes[0], block->itypes[local_idx]); } break; } } } } } // fill result result->data = data; result->aux_data = aux_data; result->buckets = buckets; result->bucket_count = bucket_count; result->bucket_mask = bucket_mask; } ProfEnd(); return result; } internal PDB_GsiParsed * pdb_gsi_from_data(Arena *arena, String8 data) { ProfBeginFunction(); PDB_GsiParsed *result = push_array(arena, PDB_GsiParsed, 1); // rjf: extract header PDB_GsiHeader *header = 0; if(sizeof(*header) <= data.size) { header = (PDB_GsiHeader*)data.str; } // rjf: parse if(header != 0 && header->signature == PDB_GsiSignature_Basic && header->version == PDB_GsiVersion_V70 && header->bucket_data_size != 0) { Temp scratch = scratch_begin(&arena, 1); // hash offset U32 hash_record_array_off = sizeof(*header); // bucket count U32 slot_count = 4097; // array offsets U32 bitmask_u32_count = CeilIntegerDiv(slot_count, 32); U32 bitmask_byte_size = bitmask_u32_count*4; U32 bitmask_off = hash_record_array_off + header->hash_record_arr_size; U32 offsets_off = bitmask_off + bitmask_byte_size; // get bitmask & packed offset arrays U8 *bitmasks = 0; U8 *packed_offsets = 0; if(bitmask_off + bitmask_byte_size <= data.size) { bitmasks = (data.str + bitmask_off); packed_offsets = (data.str + offsets_off); } U32 packed_offset_count = (data.size - offsets_off)/4; // unpack U32 *unpacked_offsets = 0; if(packed_offsets != 0) { unpacked_offsets = push_array(scratch.arena, U32, slot_count); U32 *bitmask_ptr = (U32*)bitmasks; U32 *bitmask_opl = bitmask_ptr + bitmask_u32_count; U32 *src_ptr = (U32*)packed_offsets; U32 *src_opl = src_ptr + packed_offset_count; U32 *dst_ptr = unpacked_offsets; U32 *dst_opl = dst_ptr + slot_count; for(; bitmask_ptr < bitmask_opl && src_ptr < src_opl; bitmask_ptr += 1) { U32 bits = *bitmask_ptr; U32 src_max = (U32)(src_opl - src_ptr); U32 dst_max = (U32)(dst_opl - dst_ptr); U32 k_max0 = ClampTop(32, dst_max); U32 k_max = ClampTop(k_max0, src_max); for(U32 k = 0; k < k_max; k += 1) { if((bits & 1) == 1) { *dst_ptr = *src_ptr; src_ptr += 1; } else { *dst_ptr = 0xFFFFFFFF; } dst_ptr += 1; bits >>= 1; } } for(; dst_ptr < dst_opl; dst_ptr += 1) { *dst_ptr = 0xFFFFFFFF; } } // construct table B32 bad_table = 0; if(unpacked_offsets != 0) { // hash records PDB_GsiHashRecord *hash_records = (PDB_GsiHashRecord*)(data.str + hash_record_array_off); U32 hash_record_count = header->hash_record_arr_size/sizeof(PDB_GsiHashRecord); // * We unpack hash records into the the table by scanning backwards through the // * hash records. Neighboring values in unpacked_offsets *sort of* form counts, but we // * have to skip the max-U32s (sloppy PDB nonsense). // * PDBs put one extra slot at the beginning of the encoded buckets that is mean // * to be padding for modifying the buffer in place. After decoding there are 4096 buckets, // * in the encoded buckets there are 4097. We are meant to drop the first one. // build table PDB_GsiHashRecord *hash_record_ptr = hash_records + hash_record_count - 1; U32 prev_n = hash_record_count; for(U32 i = slot_count; i > 1;) { i -= 1; if(unpacked_offsets[i] != 0xFFFFFFFF) { // determine hash record range to use // * The "12" here is the result of some really sloppy PDB magic. U32 n = unpacked_offsets[i]/12; if(n > prev_n) { bad_table = 1; break; } U32 num_steps = prev_n - n; // fill this bucket U32 *bucket_offs = push_array_aligned(arena, U32, num_steps, 4); for(U32 j = num_steps; j > 0;) { j -= 1; // * The "- 1" is more sloppy PDB magic. bucket_offs[j] = hash_record_ptr->symbol_off - 1; hash_record_ptr -= 1; } PDB_GsiBucket *bucket = &result->buckets[i]; bucket->count = num_steps; bucket->offs = bucket_offs; // update prev_n prev_n = n; } } } scratch_end(scratch); } ProfEnd(); return result; } internal U64 pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 string) { U64 result = max_U64; U32 hash = pdb_hash_v1(string); U32 bucket_idx = hash % ArrayCount(gsi->buckets); PDB_GsiBucket bucket = gsi->buckets[bucket_idx]; for(U64 i = 0; i < bucket.count; ++i) { U32 off = bucket.offs[i]; if(off + sizeof(CV_RecHeader) <= symbol_data.size) { CV_RecHeader *sym_header = (CV_RecHeader *)(symbol_data.str + off); if(sym_header->size >= sizeof(sym_header->kind)) { U64 opl_off = off + sizeof(sym_header->size) + sym_header->size; U8 *sym_opl = (U8*)sym_header; if(opl_off <= symbol_data.size) { sym_opl = symbol_data.str + opl_off; } Rng1U64 raw_symbol_range = rng_1u64(off + sizeof(*sym_header), off + (sym_header->size - sizeof(sym_header->kind))); String8 raw_symbol = str8_substr(symbol_data, raw_symbol_range); String8 sym_name = cv_name_from_symbol(sym_header->kind, raw_symbol); if(str8_match(sym_name, string, 0)) { result = off; goto exit; } } } } exit:; return result; } internal COFF_SectionHeaderArray pdb_coff_section_array_from_data(Arena *arena, String8 data){ COFF_SectionHeaderArray result = {0}; result.count = data.size/sizeof(COFF_SectionHeader); result.v = (COFF_SectionHeader*)data.str; return(result); } internal PDB_CompUnitArray* pdb_comp_unit_array_from_data(Arena *arena, String8 data){ PDB_CompUnitNode *first = 0; PDB_CompUnitNode *last = 0; U64 count = 0; U64 cursor = 0; for (;cursor + sizeof(PDB_DbiCompUnitHeader) <= data.size;){ // get header PDB_DbiCompUnitHeader *header = (PDB_DbiCompUnitHeader*)(data.str + cursor); // get names U64 name_off = cursor + sizeof(*header); String8 name = str8_cstring_capped((char *)(data.str + name_off), (char *)(data.str + data.size)); U64 name2_off = name_off + name.size + 1; String8 name2 = str8_cstring_capped((char *)(data.str + name2_off), (char *)(data.str + data.size)); U64 after_name2_off = name2_off + name2.size + 1; // save mod info PDB_CompUnitNode *node = push_array_no_zero(arena, PDB_CompUnitNode, 1); SLLQueuePush(first, last, node); count += 1; node->unit.sn = header->sn; node->unit.obj_name = name; node->unit.group_name = name2; // fill range offsets U32 *range_buf = node->unit.range_off; { // fill the buffer with size of each range range_buf[PDB_DbiCompUnitRange_Symbols] = header->symbols_size; range_buf[PDB_DbiCompUnitRange_C11] = header->c11_lines_size; range_buf[PDB_DbiCompUnitRange_C13] = header->c13_lines_size; Assert(PDB_DbiCompUnitRange_C13 + 1 == PDB_DbiCompUnitRange_COUNT); // in-place sizes -> offs conversion U64 i = 0; U32 range_cursor = 0; for (; i < (U64)(PDB_DbiCompUnitRange_COUNT); i += 1){ U64 adv = range_buf[i]; range_buf[i] = range_cursor; range_cursor += adv; } range_buf[i] = range_cursor; // skip 4 byte signature in symbols range if (range_buf[1] >= 4){ range_buf[0] += 4; } } // update cursor cursor = AlignPow2(after_name2_off, 4); } // fill result PDB_CompUnit **units = push_array_no_zero(arena, PDB_CompUnit*, count); { U64 idx = 0; for (PDB_CompUnitNode *node = first; node != 0; node = node->next, idx += 1){ units[idx] = &node->unit; } } PDB_CompUnitArray *result = push_array(arena, PDB_CompUnitArray, 1); result->units = units; result->count = count; return(result); } internal PDB_CompUnitContributionArray pdb_comp_unit_contribution_array_from_data(Arena *arena, String8 data, COFF_SectionHeaderArray sections) { PDB_CompUnitContribution *contributions = 0; U64 count = 0; if(data.size >= sizeof(PDB_DbiSectionContribVersion)) { PDB_DbiSectionContribVersion *version = (PDB_DbiSectionContribVersion*)data.str; // determine array layout from version U32 item_size = 0; U32 array_off = 0; switch(*version) { default: { // TODO(allen): do we have a test case for this? item_size = sizeof(PDB_DbiSectionContrib40); }break; case PDB_DbiSectionContribVersion_1: { item_size = sizeof(PDB_DbiSectionContrib); array_off = sizeof(*version); }break; case PDB_DbiSectionContribVersion_2: { item_size = sizeof(PDB_DbiSectionContrib2); array_off = sizeof(*version); }break; } // allocate ranges U64 max_count = (data.size - array_off)/item_size; contributions = push_array_no_zero(arena, PDB_CompUnitContribution, max_count); // binary section info U64 section_count = sections.count; COFF_SectionHeader* section_headers = sections.v; // fill array PDB_CompUnitContribution *contribution_ptr = contributions; U64 cursor = array_off; for(; cursor + item_size <= data.size; cursor += item_size) { PDB_DbiSectionContrib40 *sc = (PDB_DbiSectionContrib40*)(data.str + cursor); if(sc->size > 0 && 1 <= sc->sec && sc->sec <= section_count) { U64 voff = section_headers[sc->sec - 1].voff + sc->sec_off; contribution_ptr->mod = sc->mod; contribution_ptr->voff_first = voff; contribution_ptr->voff_opl = voff + sc->size; contribution_ptr += 1; } } count = (U64)(contribution_ptr - contributions); } // fill result PDB_CompUnitContributionArray result = {0}; result.contributions = contributions; result.count = count; return result; } //////////////////////////////// //~ PDB Dbi Functions internal String8 pdb_data_from_dbi_range(PDB_DbiParsed *dbi, PDB_DbiRange range){ String8 result = {0}; if (range < PDB_DbiRange_COUNT){ U64 first = dbi->range_off[range]; U64 opl = dbi->range_off[range + 1]; result.str = dbi->data.str + first; result.size = opl - first; } return(result); } internal String8 pdb_data_from_unit_range(MSF_Parsed *msf, PDB_CompUnit *unit, PDB_DbiCompUnitRange range){ String8 result = {0}; if (range < PDB_DbiCompUnitRange_COUNT){ String8 full_stream_data = msf_data_from_stream(msf, unit->sn); U64 first_raw = unit->range_off[range]; U64 opl_raw = unit->range_off[range + 1]; U64 opl = ClampTop(opl_raw, full_stream_data.size); U64 first = ClampTop(first_raw, opl); result.str = full_stream_data.str + first; result.size = opl - first; } return(result); } //////////////////////////////// //~ PDB Tpi Functions internal String8 pdb_leaf_data_from_tpi(PDB_TpiParsed *tpi){ String8 data = tpi->data; U8 *first = data.str + tpi->leaf_first; U8 *opl = data.str + tpi->leaf_opl; String8 result = str8_range(first, opl); return(result); } internal CV_TypeIdArray pdb_tpi_itypes_from_name(Arena *arena, PDB_TpiHashParsed *tpi_hash, CV_LeafParsed *leaf, String8 name, B32 compare_unique_name, U32 output_cap) { CV_TypeIdArray result = {0}; if(tpi_hash->bucket_count != 0) { U32 hash = pdb_hash_v1(name); U32 bucket_idx = ((tpi_hash->bucket_mask != 0) ? hash&tpi_hash->bucket_mask : hash%tpi_hash->bucket_count); CV_TypeId itype_first = leaf->itype_first; CV_TypeId itype_opl = leaf->itype_opl; String8 data = leaf->data; Temp scratch = scratch_begin(&arena, 1); struct Chain { struct Chain *next; CV_TypeId itype; }; struct Chain *first = 0; struct Chain *last = 0; U32 count = 0; for (PDB_TpiHashBlock *block = tpi_hash->buckets[bucket_idx]; block != 0; block = block->next){ U32 local_count = block->local_count; CV_TypeId *itype_ptr = block->itypes; for (U32 i = 0; i < local_count; i += 1, itype_ptr += 1){ String8 extracted_name = {0}; CV_TypeId itype = *itype_ptr; if (itype_first <= itype && itype < itype_opl){ CV_RecRange *range = &leaf->leaf_ranges.ranges[itype - leaf->itype_first]; if (range->off + range->hdr.size <= data.size){ U8 *first = data.str + range->off + 2; U64 cap = range->hdr.size - 2; switch (range->hdr.kind){ default:break; case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { if (sizeof(CV_LeafStruct) <= cap){ CV_LeafStruct *lf_struct = (CV_LeafStruct*)first; if (!(lf_struct->props & CV_TypeProp_FwdRef)){ // size U8 *numeric_ptr = (U8*)(lf_struct + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); // name U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped((char*)name_ptr, (char *)(first + cap)); // unique name if (compare_unique_name){ if (lf_struct->props & CV_TypeProp_HasUniqueName) { U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, (char *)(first + cap)); extracted_name = unique_name; } } else{ extracted_name = name; } } } }break; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { if (sizeof(CV_LeafStruct2) <= cap){ CV_LeafStruct2 *lf_struct = (CV_LeafStruct2*)first; if (!(lf_struct->props & CV_TypeProp_FwdRef)){ // size U8 *numeric_ptr = (U8*)(lf_struct + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); // name U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped((char*)name_ptr, (char *)(first + cap)); // unique name if (compare_unique_name){ if (lf_struct->props & CV_TypeProp_HasUniqueName) { U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, (char *)(first + cap)); extracted_name = unique_name; } } else{ extracted_name = name; } } } }break; case CV_LeafKind_UNION: { if (sizeof(CV_LeafUnion) <= cap){ CV_LeafUnion *lf_union = (CV_LeafUnion*)first; if (!(lf_union->props & CV_TypeProp_FwdRef)){ // size U8 *numeric_ptr = (U8*)(lf_union + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, first + cap); // name U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped((char*)name_ptr, (char *)(first + cap)); // unique name if (compare_unique_name){ if (lf_union->props & CV_TypeProp_HasUniqueName) { U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, (char *)(first + cap)); extracted_name = unique_name; } } else{ extracted_name = name; } } } }break; case CV_LeafKind_ENUM: { if (sizeof(CV_LeafEnum) <= cap){ CV_LeafEnum *lf_enum = (CV_LeafEnum*)first; if (!(lf_enum->props & CV_TypeProp_FwdRef)){ // name U8 *name_ptr = (U8*)(lf_enum + 1); String8 name = str8_cstring_capped((char*)name_ptr, (char *)(first + cap)); // unique name if (compare_unique_name){ if (lf_enum->props & CV_TypeProp_HasUniqueName) { U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped((char*)unique_name_ptr, (char *)(first + cap)); extracted_name = unique_name; } } else{ extracted_name = name; } } } }break; } } } if (str8_match(extracted_name, name, 0)){ struct Chain *chain = push_array(scratch.arena, struct Chain, 1); SLLQueuePush(first, last, chain); count += 1; chain->itype = itype; if (count == output_cap){ goto dblbreak; } } } } dblbreak:; // assemble result CV_TypeId *itypes = push_array_aligned(arena, CV_TypeId, count, 8); { CV_TypeId *itype_ptr = itypes; for (struct Chain *node = first; node != 0; node = node->next, itype_ptr += 1){ *itype_ptr = node->itype; } } result.itypes = itypes; result.count = count; scratch_end(scratch); } return result; } internal CV_TypeId pdb_tpi_first_itype_from_name(PDB_TpiHashParsed *tpi_hash, CV_LeafParsed *tpi_leaf, String8 name, B32 compare_unique_name) { Temp scratch = scratch_begin(0, 0); CV_TypeIdArray array = pdb_tpi_itypes_from_name(scratch.arena, tpi_hash, tpi_leaf, name, compare_unique_name, 1); CV_TypeId result = 0; if(array.count > 0) { result = array.itypes[0]; } scratch_end(scratch); return(result); } //////////////////////////////// //~ PDB Strtbl Functions internal String8 pdb_strtbl_string_from_off(PDB_Strtbl *strtbl, U32 off){ U32 strblock_max = strtbl->strblock_max; U32 full_off_raw = strtbl->strblock_min + off; U32 full_off = ClampTop(full_off_raw, strblock_max); String8 result = str8_cstring_capped((char*)(strtbl->data.str + full_off), (char*)(strtbl->data.str + strblock_max)); return(result); } internal String8 pdb_strtbl_string_from_index(PDB_Strtbl *strtbl, PDB_StringIndex idx){ String8 result = {0}; if (idx < strtbl->bucket_count){ U32 off = *(U32*)(strtbl->data.str + strtbl->buckets_min + idx*4); result = pdb_strtbl_string_from_off(strtbl, off); } return(result); } internal U32 pdb_strtbl_off_from_string(PDB_Strtbl *strtbl, String8 string) { U32 result = max_U32; U32 hash = pdb_hash_v1(string); U32 best_bucket_idx = hash % strtbl->bucket_count; U32 bucket_idx = best_bucket_idx; do { String8 test_string = pdb_strtbl_string_from_index(strtbl, bucket_idx); if(test_string.size == 0) { break; } if(str8_match(test_string, string, 0)) { result = bucket_idx; break; } bucket_idx = (bucket_idx+1) % strtbl->buckets_max; } while (bucket_idx != best_bucket_idx); return result; } //////////////////////////////// //~ rjf: Thin Lookup Fast Paths internal B32 pdb_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st) { Temp scratch = scratch_begin(0,0); B32 has_ref = 0; String8 dbi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Dbi); PDB_DbiParsed *dbi = pdb_dbi_from_data(scratch.arena, dbi_data); if(dbi) { String8 gsi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->gsi_sn); PDB_GsiParsed *gsi_parsed = pdb_gsi_from_data(scratch.arena, gsi_data); if(gsi_parsed) { String8 symbol_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->sym_sn); for(String8Node *symbol_n = symbol_list.first; symbol_n != 0; symbol_n = symbol_n->next) { U64 symbol_off = pdb_gsi_symbol_from_string(gsi_parsed, symbol_data, symbol_n->string); if(symbol_off < symbol_data.size) { has_ref = 1; break; } } } } scratch_end(scratch); return has_ref; } internal B32 pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st) { Temp scratch = scratch_begin(0,0); B32 has_ref = 0; String8 info_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Info); PDB_Info *info = pdb_info_from_data(scratch.arena, info_data); if(info) { PDB_NamedStreamTable *named_streams = pdb_named_stream_table_from_info(scratch.arena, info); if(named_streams) { MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable]; String8 strtbl_data = msf_data_from_stream_number(scratch.arena, msf_data, st, strtbl_sn); PDB_Strtbl *strtbl = pdb_strtbl_from_data(scratch.arena, strtbl_data); if(strtbl->bucket_count != 0) { for EachIndex(idx, strtbl->bucket_count) { String8 stored_string = pdb_strtbl_string_from_index(strtbl, idx); for(String8Node *file_n = file_list.first; file_n != 0; file_n = file_n->next) { if(str8_match(file_n->string, stored_string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive)) { has_ref = 1; goto dbl_break; } } } dbl_break:; } } } scratch_end(scratch); return has_ref; } internal B32 pdb_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list) { Temp scratch = scratch_begin(0,0); B32 has_ref = 0; MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data); if(!has_ref && symbol_list.node_count) { has_ref = pdb_has_symbol_ref(msf_data, symbol_list, st); } if(!has_ref && file_list.node_count) { has_ref = pdb_has_file_ref(msf_data, file_list, st); } scratch_end(scratch); return has_ref; } ================================================ FILE: src/pdb/pdb_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_PARSE_H #define PDB_PARSE_H //////////////////////////////// //~ PDB Parser String Table Types typedef struct PDB_Strtbl { String8 data; U32 bucket_count; U32 strblock_min; U32 strblock_max; U32 buckets_min; U32 buckets_max; } PDB_Strtbl; //////////////////////////////// //~ PDB Parser Info Types typedef enum PDB_NamedStream { PDB_NamedStream_HeaderBlock, PDB_NamedStream_StringTable, PDB_NamedStream_LinkInfo, PDB_NamedStream_Count } PDB_NamedStream; typedef struct PDB_NamedStreamTable { MSF_StreamNumber sn[PDB_NamedStream_Count]; } PDB_NamedStreamTable; typedef struct PDB_InfoNode { struct PDB_InfoNode *next; String8 string; MSF_StreamNumber sn; } PDB_InfoNode; typedef struct PDB_Info { PDB_InfoNode *first; PDB_InfoNode *last; Guid auth_guid; PDB_FeatureFlags features; } PDB_Info; typedef struct PDB_InfoHeader { PDB_InfoVersion version; U32 time; U32 age; } PDB_InfoHeader; //////////////////////////////// //~ PDB Parser DBI Types // (this is not "literally" defined by the format - but helpful to have) typedef enum PDB_DbiRange { PDB_DbiRange_ModuleInfo, PDB_DbiRange_SecCon, PDB_DbiRange_SecMap, PDB_DbiRange_FileInfo, PDB_DbiRange_TSM, PDB_DbiRange_EcInfo, PDB_DbiRange_DbgHeader, PDB_DbiRange_COUNT } PDB_DbiRange; // (this is not "literally" defined by the format - but helpful to have) typedef enum { PDB_DbiCompUnitRange_Symbols, PDB_DbiCompUnitRange_C11, PDB_DbiCompUnitRange_C13, PDB_DbiCompUnitRange_COUNT } PDB_DbiCompUnitRange; typedef struct PDB_DbiParsed { String8 data; COFF_MachineType machine_type; MSF_StreamNumber gsi_sn; MSF_StreamNumber psi_sn; MSF_StreamNumber sym_sn; U64 range_off[(U64)(PDB_DbiRange_COUNT) + 1]; MSF_StreamNumber dbg_streams[PDB_DbiStream_COUNT]; } PDB_DbiParsed; typedef struct PDB_CompUnit { MSF_StreamNumber sn; U32 range_off[(U32)(PDB_DbiCompUnitRange_COUNT) + 1]; String8 obj_name; String8 group_name; } PDB_CompUnit; typedef struct PDB_CompUnitNode { struct PDB_CompUnitNode *next; PDB_CompUnit unit; } PDB_CompUnitNode; typedef struct PDB_CompUnitArray { PDB_CompUnit **units; U64 count; } PDB_CompUnitArray; typedef struct PDB_CompUnitContribution { U32 mod; U64 voff_first; U64 voff_opl; } PDB_CompUnitContribution; typedef struct PDB_CompUnitContributionArray { PDB_CompUnitContribution *contributions; U64 count; } PDB_CompUnitContributionArray; //////////////////////////////// //~ PDB Parser TPI/IPI Types typedef struct PDB_TpiParsed { String8 data; // leaf info U64 leaf_first; U64 leaf_opl; U32 itype_first; U32 itype_opl; // hash info MSF_StreamNumber hash_sn; MSF_StreamNumber hash_sn_aux; U32 hash_key_size; U32 hash_bucket_count; U32 hash_vals_off; U32 hash_vals_size; U32 itype_off; U32 itype_size; U32 hash_adj_off; U32 hash_adj_size; } PDB_TpiParsed; typedef struct PDB_TpiHashBlock { struct PDB_TpiHashBlock *next; U32 local_count; CV_TypeId itypes[13]; // 13 = (64 - 12)/4 } PDB_TpiHashBlock; typedef struct PDB_TpiHashParsed { String8 data; String8 aux_data; PDB_TpiHashBlock **buckets; U32 bucket_count; U32 bucket_mask; } PDB_TpiHashParsed; //////////////////////////////// //~ PDB Parser GSI Types typedef struct PDB_GsiBucket { U32 *offs; U64 count; } PDB_GsiBucket; typedef struct PDB_GsiParsed { PDB_GsiBucket buckets[4096]; } PDB_GsiParsed; //////////////////////////////// //~ rjf: Globals read_only global PDB_CompUnit pdb_comp_unit_nil = {0}; //////////////////////////////// //~ PDB Parser Functions internal PDB_Info* pdb_info_from_data(Arena *arena, String8 pdb_info_data); internal PDB_NamedStreamTable*pdb_named_stream_table_from_info(Arena *arena, PDB_Info *info); internal PDB_Strtbl* pdb_strtbl_from_data(Arena *arena, String8 strtbl_data); internal PDB_DbiParsed* pdb_dbi_from_data(Arena *arena, String8 dbi_data); internal PDB_TpiParsed* pdb_tpi_from_data(Arena *arena, String8 tpi_data); internal PDB_TpiHashParsed* pdb_tpi_hash_from_data(Arena *arena, PDB_Strtbl *strtbl, PDB_TpiParsed *tpi, String8 tpi_hash_data, String8 tpi_hash_aux_data); internal PDB_GsiParsed* pdb_gsi_from_data(Arena *arena, String8 gsi_data); internal U64 pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 string); internal COFF_SectionHeaderArray pdb_coff_section_array_from_data(Arena *arena, String8 section_data); internal PDB_CompUnitArray* pdb_comp_unit_array_from_data(Arena *arena, String8 module_info_data); internal PDB_CompUnitContributionArray pdb_comp_unit_contribution_array_from_data(Arena *arena, String8 seccontrib_data, COFF_SectionHeaderArray sections); //////////////////////////////// //~ PDB Dbi Functions internal String8 pdb_data_from_dbi_range(PDB_DbiParsed *dbi, PDB_DbiRange range); internal String8 pdb_data_from_unit_range(MSF_Parsed *msf, PDB_CompUnit *unit, PDB_DbiCompUnitRange range); //////////////////////////////// //~ PDB Tpi Functions internal String8 pdb_leaf_data_from_tpi(PDB_TpiParsed *tpi); internal CV_TypeIdArray pdb_tpi_itypes_from_name(Arena *arena, PDB_TpiHashParsed *tpi_hash, CV_LeafParsed *tpi_leaf, String8 name, B32 compare_unique_name, U32 output_cap); internal CV_TypeId pdb_tpi_first_itype_from_name(PDB_TpiHashParsed *tpi_hash, CV_LeafParsed *tpi_leaf, String8 name, B32 compare_unique_name); //////////////////////////////// //~ PDB Strtbl Functions internal String8 pdb_strtbl_string_from_off(PDB_Strtbl *strtbl, U32 off); internal String8 pdb_strtbl_string_from_index(PDB_Strtbl *strtbl, PDB_StringIndex idx); internal U32 pdb_strtbl_off_from_string(PDB_Strtbl *strtbl, String8 string); //////////////////////////////// //~ rjf: Thin Lookup Fast Paths internal B32 pdb_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st); internal B32 pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st); internal B32 pdb_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list); #endif // PDB_PARSE_H ================================================ FILE: src/pdb/pdb_stringize.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ PDB Stringize Functions internal void pdb_stringize_tpi_hash(Arena *arena, String8List *out, PDB_TpiHashParsed *hash){ U32 bucket_count = hash->bucket_count; str8_list_pushf(arena, out, "bucket_count=%u\n\n", bucket_count); for (U32 i = 0; i < bucket_count; i += 1){ if (hash->buckets[i] != 0){ str8_list_pushf(arena, out, "bucket[%u]:\n", i); for (PDB_TpiHashBlock *block = hash->buckets[i]; block != 0; block = block->next){ U32 local_count = block->local_count; CV_TypeId *itype_ptr = block->itypes; for (U32 j = 0; j < local_count; j += 1, itype_ptr += 1){ str8_list_pushf(arena, out, " %u\n", *itype_ptr); } } str8_list_push(arena, out, str8_lit("\n")); } } } ================================================ FILE: src/pdb/pdb_stringize.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_STRINGIZE_H #define PDB_STRINGIZE_H //////////////////////////////// //~ PDB Stringize Functions internal void pdb_stringize_tpi_hash(Arena *arena, String8List *out, PDB_TpiHashParsed *hash); #endif // PDB_STRINGIZE_H ================================================ FILE: src/pe/dos_program.asm ================================================ ; Copyright (c) Epic Games Tools ; Licensed under the MIT license (https://opensource.org/license/mit/) ; $ c:\devel\projects\bin\win32\nasm src\pe\dos_program.asm -fbin -o dos_program.bin BITS 16 SEGMENT CODE push cs ; copy psp segment address to ds pop ds mov dx, msg ; set print string mov ah, 9h ; print to stdout int 21h mov ax, 0x4c01 ; terminate with return code 1 in al int 0x21 msg: DB "This program cannot be run in DOS mode.$",0 ALIGN 8, DB ================================================ FILE: src/pe/pe.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Basic Enum Functions internal U32 pe_slot_count_from_unwind_op_code(PE_UnwindOpCode opcode) { U32 result = 0; switch(opcode) { case PE_UnwindOpCode_PUSH_NONVOL: result = 1; break; case PE_UnwindOpCode_ALLOC_LARGE: result = 2; break; case PE_UnwindOpCode_ALLOC_SMALL: result = 1; break; case PE_UnwindOpCode_SET_FPREG: result = 1; break; case PE_UnwindOpCode_SAVE_NONVOL: result = 2; break; case PE_UnwindOpCode_SAVE_NONVOL_FAR: result = 3; break; case PE_UnwindOpCode_EPILOG: result = 2; break; case PE_UnwindOpCode_SPARE_CODE: result = 3; break; case PE_UnwindOpCode_SAVE_XMM128: result = 2; break; case PE_UnwindOpCode_SAVE_XMM128_FAR: result = 3; break; case PE_UnwindOpCode_PUSH_MACHFRAME: result = 1; break; } return result; } global read_only struct { String8 string; PE_WindowsSubsystem type; } g_pe_subsystem_map[] = { { str8_lit_comp(""), PE_WindowsSubsystem_UNKNOWN }, { str8_lit_comp("native"), PE_WindowsSubsystem_NATIVE }, { str8_lit_comp("windows"), PE_WindowsSubsystem_WINDOWS_GUI }, { str8_lit_comp("console"), PE_WindowsSubsystem_WINDOWS_CUI }, { str8_lit_comp("os2_cui"), PE_WindowsSubsystem_OS2_CUI }, { str8_lit_comp("posix"), PE_WindowsSubsystem_POSIX_CUI }, { str8_lit_comp("native_windows"), PE_WindowsSubsystem_NATIVE_WINDOWS }, { str8_lit_comp("windows_ce_gui"), PE_WindowsSubsystem_WINDOWS_CE_GUI }, { str8_lit_comp("efi_application"), PE_WindowsSubsystem_EFI_APPLICATION }, { str8_lit_comp("efi_boot_service_driver"), PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER }, { str8_lit_comp("efi_runtime_driver"), PE_WindowsSubsystem_EFI_RUNTIME_DRIVER }, { str8_lit_comp("efi_rom"), PE_WindowsSubsystem_EFI_ROM }, { str8_lit_comp("xbox"), PE_WindowsSubsystem_XBOX }, { str8_lit_comp("windows_boot_application"), PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION }, }; StaticAssert(ArrayCount(g_pe_subsystem_map) == PE_WindowsSubsystem_COUNT, g_pe_subsystem_map_count_check); internal String8 pe_string_from_subsystem(PE_WindowsSubsystem subsystem) { for (U64 i = 0; i < ArrayCount(g_pe_subsystem_map); i += 1) { if (g_pe_subsystem_map[i].type == subsystem) { return g_pe_subsystem_map[i].string; } } return str8(0,0); } internal String8 pe_string_from_unwind_gpr_x64(PE_UnwindGprRegX64 x) { switch (x) { case PE_UnwindGprRegX64_RAX: return str8_lit("RCX"); case PE_UnwindGprRegX64_RCX: return str8_lit("RCX"); case PE_UnwindGprRegX64_RDX: return str8_lit("RDX"); case PE_UnwindGprRegX64_RBX: return str8_lit("RBX"); case PE_UnwindGprRegX64_RSP: return str8_lit("RSP"); case PE_UnwindGprRegX64_RBP: return str8_lit("RBP"); case PE_UnwindGprRegX64_RSI: return str8_lit("RSI"); case PE_UnwindGprRegX64_RDI: return str8_lit("RDI"); case PE_UnwindGprRegX64_R8: return str8_lit("R8"); case PE_UnwindGprRegX64_R9: return str8_lit("R9"); case PE_UnwindGprRegX64_R10: return str8_lit("R10"); case PE_UnwindGprRegX64_R11: return str8_lit("R11"); case PE_UnwindGprRegX64_R12: return str8_lit("R12"); case PE_UnwindGprRegX64_R13: return str8_lit("R13"); case PE_UnwindGprRegX64_R14: return str8_lit("R14"); case PE_UnwindGprRegX64_R15: return str8_lit("R15"); default: InvalidPath; } return str8_zero(); } internal String8 pe_string_from_data_directory_index(PE_DataDirectoryIndex x) { switch (x) { case PE_DataDirectoryIndex_EXPORT: return str8_lit("Export"); case PE_DataDirectoryIndex_IMPORT: return str8_lit("Import"); case PE_DataDirectoryIndex_RESOURCES: return str8_lit("Resources"); case PE_DataDirectoryIndex_EXCEPTIONS: return str8_lit("Exceptions"); case PE_DataDirectoryIndex_CERT: return str8_lit("Cert"); case PE_DataDirectoryIndex_BASE_RELOC: return str8_lit("BaseReloc"); case PE_DataDirectoryIndex_DEBUG: return str8_lit("Debug"); case PE_DataDirectoryIndex_ARCH: return str8_lit("Arch"); case PE_DataDirectoryIndex_GLOBAL_PTR: return str8_lit("GlobalPtr"); case PE_DataDirectoryIndex_TLS: return str8_lit("TLS"); case PE_DataDirectoryIndex_LOAD_CONFIG: return str8_lit("LoadConfig"); case PE_DataDirectoryIndex_BOUND_IMPORT: return str8_lit("BoundImport"); case PE_DataDirectoryIndex_IMPORT_ADDR: return str8_lit("ImportAddr"); case PE_DataDirectoryIndex_DELAY_IMPORT: return str8_lit("DelayImport"); case PE_DataDirectoryIndex_COM_DESCRIPTOR: return str8_lit("COM Descriptor"); case PE_DataDirectoryIndex_RESERVED: return str8_lit("Reserved"); default: InvalidPath; } return str8_zero(); } internal String8 pe_string_from_debug_directory_type(PE_DebugDirectoryType x) { switch (x) { case PE_DebugDirectoryType_UNKNOWN: return str8_lit("UNKNOWN"); case PE_DebugDirectoryType_COFF: return str8_lit("COFF"); case PE_DebugDirectoryType_CODEVIEW: return str8_lit("CODEVIEW"); case PE_DebugDirectoryType_FPO: return str8_lit("FPO"); case PE_DebugDirectoryType_MISC: return str8_lit("MISC"); case PE_DebugDirectoryType_EXCEPTION: return str8_lit("EXCEPTION"); case PE_DebugDirectoryType_FIXUP: return str8_lit("FIXUP"); case PE_DebugDirectoryType_OMAP_TO_SRC: return str8_lit("OMAP_TO_SRC"); case PE_DebugDirectoryType_OMAP_FROM_SRC: return str8_lit("OMAP_FROM_SRC"); case PE_DebugDirectoryType_BORLAND: return str8_lit("BORLAND"); case PE_DebugDirectoryType_RESERVED10: return str8_lit("RESERVED10"); case PE_DebugDirectoryType_CLSID: return str8_lit("CLSID"); case PE_DebugDirectoryType_VC_FEATURE: return str8_lit("VC_FEATURE"); case PE_DebugDirectoryType_COFF_GROUP: return str8_lit("COFF_GROUP"); case PE_DebugDirectoryType_ILTCG: return str8_lit("ILTCG"); case PE_DebugDirectoryType_MPX: return str8_lit("MPX"); case PE_DebugDirectoryType_REPRO: return str8_lit("REPRO"); case PE_DebugDirectoryType_EX_DLLCHARACTERISTICS: return str8_lit("EX_DLLCHARACTERISTICS"); case PE_DebugDirectoryType_COUNT: return str8_lit("COUNT"); } return str8_zero(); } internal String8 pe_string_from_fpo_type(PE_FPOType x) { switch (x) { case PE_FPOType_FPO: return str8_lit("FPO"); case PE_FPOType_TRAP: return str8_lit("TRAP"); case PE_FPOType_TSS: return str8_lit("TSS"); case PE_FPOType_NOFPO: return str8_lit("NOFPO"); } return str8_zero(); } internal String8 pe_string_from_misc_type(PE_DebugMiscType x) { switch (x) { case PE_DebugMiscType_NULL: break; case PE_DebugMiscType_EXE_NAME: return str8_lit("EXE_NAME"); } return str8_zero(); } internal String8 pe_resource_kind_to_string(PE_ResourceKind x) { String8 result = str8_zero(); switch (x) { case PE_ResourceKind_ACCELERATOR: result = str8_lit("Accelerator"); break; case PE_ResourceKind_ANICURSOR: result = str8_lit("Animated Cursor"); break; case PE_ResourceKind_ANIICON: result = str8_lit("Animated Icon"); break; case PE_ResourceKind_BITMAP: result = str8_lit("Bitmap"); break; case PE_ResourceKind_CURSOR: result = str8_lit("Cursor"); break; case PE_ResourceKind_DIALOG: result = str8_lit("Dialog"); break; case PE_ResourceKind_FONT: result = str8_lit("Font"); break; case PE_ResourceKind_FONTDIR: result = str8_lit("Font Directory"); break; case PE_ResourceKind_GROUP_CURSOR: result = str8_lit("Cursor Group"); break; case PE_ResourceKind_GROUP_ICON: result = str8_lit("Icon Group"); break; case PE_ResourceKind_HTML: result = str8_lit("HTML"); break; case PE_ResourceKind_ICON: result = str8_lit("Icon"); break; case PE_ResourceKind_MANIFEST: result = str8_lit("Manifest"); break; case PE_ResourceKind_MENU: result = str8_lit("Menu"); break; case PE_ResourceKind_MESSAGETABLE: result = str8_lit("Message Table"); break; case PE_ResourceKind_PLUGPLAY: result = str8_lit("Plug Play"); break; case PE_ResourceKind_RCDATA: result = str8_lit("RC Data"); break; case PE_ResourceKind_STRING: result = str8_lit("String"); break; case PE_ResourceKind_VERSION: result = str8_lit("Version Info"); break; case PE_ResourceKind_VXD: result = str8_lit("VXD"); break; } return result; } internal String8 pe_string_from_fpo_flags(Arena *arena, PE_FPOFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List l = {0}; if (flags & PE_FPOFlags_HAS_SEH) { str8_list_pushf(scratch.arena, &l, "HAS_SEH"); } if (flags & PE_FPOFlags_USE_BP_REG) { str8_list_pushf(scratch.arena, &l, "USE_BP_REG"); } if (flags & PE_FPOFlags_RESERVED) { str8_list_pushf(scratch.arena, &l, "RESERVED"); } String8 result = str8_list_join(arena, &l, &(StringJoin){.sep=str8_lit(" ")}); scratch_end(scratch); return result; } internal String8 pe_string_from_global_flags(Arena *arena, PE_GlobalFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List l = {0}; if (flags & PE_GlobalFlags_STOP_ON_EXCEPTION) { str8_list_pushf(scratch.arena, &l, "STOP_ON_EXCEPTION"); } if (flags & PE_GlobalFlags_SHOW_LDR_SNAPS) { str8_list_pushf(scratch.arena, &l, "SHOW_LDR_SNAPS"); } if (flags & PE_GlobalFlags_DEBUG_INITIAL_COMMAND) { str8_list_pushf(scratch.arena, &l, "DEBUG_INITIAL_COMMAND"); } if (flags & PE_GlobalFlags_STOP_ON_HUNG_GUI) { str8_list_pushf(scratch.arena, &l, "STOP_ON_HUNG_GUI"); } if (flags & PE_GlobalFlags_HEAP_ENABLE_TAIL_CHECK) { str8_list_pushf(scratch.arena, &l, "HEAP_ENABLE_TAIL_CHECK"); } if (flags & PE_GlobalFlags_HEAP_ENABLE_FREE_CHECK) { str8_list_pushf(scratch.arena, &l, "HEAP_ENABLE_FREE_CHECK"); } if (flags & PE_GlobalFlags_HEAP_VALIDATE_PARAMETERS) { str8_list_pushf(scratch.arena, &l, "HEAP_VALIDATE_PARAMETERS"); } if (flags & PE_GlobalFlags_HEAP_VALIDATE_ALL) { str8_list_pushf(scratch.arena, &l, "HEAP_VALIDATE_ALL"); } if (flags & PE_GlobalFlags_APPLICATION_VERIFIER) { str8_list_pushf(scratch.arena, &l, "APPLICATION_VERIFIER"); } if (flags & PE_GlobalFlags_POOL_ENABLE_TAGGING) { str8_list_pushf(scratch.arena, &l, "POOL_ENABLE_TAGGING"); } if (flags & PE_GlobalFlags_HEAP_ENABLE_TAGGING) { str8_list_pushf(scratch.arena, &l, "HEAP_ENABLE_TAGGING"); } if (flags & PE_GlobalFlags_STACK_TRACE_DB) { str8_list_pushf(scratch.arena, &l, "STACK_TRACE_DB"); } if (flags & PE_GlobalFlags_KERNEL_STACK_TRACE_DB) { str8_list_pushf(scratch.arena, &l, "KERNEL_STACK_TRACE_DB"); } if (flags & PE_GlobalFlags_MAINTAIN_OBJECT_TYPELIST) { str8_list_pushf(scratch.arena, &l, "MAINTAIN_OBJECT_TYPELIST"); } if (flags & PE_GlobalFlags_HEAP_ENABLE_TAG_BY_DLL) { str8_list_pushf(scratch.arena, &l, "HEAP_ENABLE_TAG_BY_DLL"); } if (flags & PE_GlobalFlags_DISABLE_STACK_EXTENSION) { str8_list_pushf(scratch.arena, &l, "DISABLE_STACK_EXTENSION"); } if (flags & PE_GlobalFlags_ENABLE_CSRDEBUG) { str8_list_pushf(scratch.arena, &l, "ENABLE_CSRDEBUG"); } if (flags & PE_GlobalFlags_ENABLE_KDEBUG_SYMBOL_LOAD) { str8_list_pushf(scratch.arena, &l, "ENABLE_KDEBUG_SYMBOL_LOAD"); } if (flags & PE_GlobalFlags_DISABLE_PAGE_KERNEL_STACKS) { str8_list_pushf(scratch.arena, &l, "DISABLE_PAGE_KERNEL_STACKS"); } if (flags & PE_GlobalFlags_ENABLE_SYSTEM_CRIT_BREAKS) { str8_list_pushf(scratch.arena, &l, "ENABLE_SYSTEM_CRIT_BREAKS"); } if (flags & PE_GlobalFlags_HEAP_DISABLE_COALESCING) { str8_list_pushf(scratch.arena, &l, "HEAP_DISABLE_COALESCING"); } if (flags & PE_GlobalFlags_ENABLE_CLOSE_EXCEPTIONS) { str8_list_pushf(scratch.arena, &l, "ENABLE_CLOSE_EXCEPTIONS"); } if (flags & PE_GlobalFlags_ENABLE_EXCEPTION_LOGGING) { str8_list_pushf(scratch.arena, &l, "ENABLE_EXCEPTION_LOGGING"); } if (flags & PE_GlobalFlags_ENABLE_HANDLE_TYPE_TAGGING) { str8_list_pushf(scratch.arena, &l, "ENABLE_HANDLE_TYPE_TAGGING"); } if (flags & PE_GlobalFlags_HEAP_PAGE_ALLOCS) { str8_list_pushf(scratch.arena, &l, "HEAP_PAGE_ALLOCS"); } if (flags & PE_GlobalFlags_DEBUG_INITIAL_COMMAND_EX) { str8_list_pushf(scratch.arena, &l, "DEBUG_INITIAL_COMMAND_EX"); } if (flags & PE_GlobalFlags_DISABLE_DBGPRINT) { str8_list_pushf(scratch.arena, &l, "DISABLE_DBGPRINT"); } if (flags & PE_GlobalFlags_CRITSEC_EVENT_CREATION) { str8_list_pushf(scratch.arena, &l, "CRITSEC_EVENT_CREATION"); } if (flags & PE_GlobalFlags_LDR_TOP_DOWN) { str8_list_pushf(scratch.arena, &l, "LDR_TOP_DOWN"); } if (flags & PE_GlobalFlags_ENABLE_HANDLE_EXCEPTIONS) { str8_list_pushf(scratch.arena, &l, "ENABLE_HANDLE_EXCEPTIONS"); } if (flags & PE_GlobalFlags_DISABLE_PROTDLLS) { str8_list_pushf(scratch.arena, &l, "DISABLE_PROTDLLS"); } String8 result = str8_list_join(arena, &l, &(StringJoin){.sep=str8_lit(" ")}); return result; } internal String8 pe_string_from_load_config_guard_flags(Arena *arena, PE_LoadConfigGuardFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List l = {0}; if (flags & PE_LoadConfigGuardFlags_CF_INSTRUMENTED) { str8_list_pushf(scratch.arena, &l, "CF_INSTRUMENTED"); } if (flags & PE_LoadConfigGuardFlags_CFW_INSTRUMENTED) { str8_list_pushf(scratch.arena, &l, "CFW_INSTRUMENTED"); } if (flags & PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_PRESENT) { str8_list_pushf(scratch.arena, &l, "CF_FUNCTION_TABLE_PRESENT"); } if (flags & PE_LoadConfigGuardFlags_SECURITY_COOKIE_UNUSED) { str8_list_pushf(scratch.arena, &l, "SECURITY_COOKIE_UNUSED"); } if (flags & PE_LoadConfigGuardFlags_PROTECT_DELAYLOAD_IAT) { str8_list_pushf(scratch.arena, &l, "PROTECT_DELAYLOAD_IAT"); } if (flags & PE_LoadConfigGuardFlags_DELAYLOAD_IAT_IN_ITS_OWN_SECTION) { str8_list_pushf(scratch.arena, &l, "DELAYLOAD_IAT_IN_ITS_OWN_SECTION"); } if (flags & PE_LoadConfigGuardFlags_CF_EXPORT_SUPPRESSION_INFO_PRESENT) { str8_list_pushf(scratch.arena, &l, "CF_EXPORT_SUPPRESSION_INFO_PRESENT"); } if (flags & PE_LoadConfigGuardFlags_CF_ENABLE_EXPORT_SUPPRESSION) { str8_list_pushf(scratch.arena, &l, "CF_ENABLE_EXPORT_SUPPRESSION"); } if (flags & PE_LoadConfigGuardFlags_CF_LONGJUMP_TABLE_PRESENT) { str8_list_pushf(scratch.arena, &l, "CF_LONGJUMP_TABLE_PRESENT"); } if (flags & PE_LoadConfigGuardFlags_EH_CONTINUATION_TABLE_PRESENT) { str8_list_pushf(scratch.arena, &l, "EH_CONTINUATION_TABLE_PRESENT"); } String8 result = str8_list_join(arena, &l, &(StringJoin){.sep = str8_lit(" ")}); scratch_end(scratch); return result; } internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacteristics dll_chars) { Temp scratch = scratch_begin(&arena, 1); String8List l = {0}; if (dll_chars & PE_DllCharacteristic_HIGH_ENTROPY_VA) { str8_list_pushf(scratch.arena, &l, "High Entropy Virtual Address"); } if (dll_chars & PE_DllCharacteristic_DYNAMIC_BASE) { str8_list_pushf(scratch.arena, &l, "Dynamic Base"); } if (dll_chars & PE_DllCharacteristic_FORCE_INTEGRITY) { str8_list_pushf(scratch.arena, &l, "Force Integrity"); } if (dll_chars & PE_DllCharacteristic_NX_COMPAT) { str8_list_pushf(scratch.arena, &l, "NX Compatible"); } if (dll_chars & PE_DllCharacteristic_NO_ISOLATION) { str8_list_pushf(scratch.arena, &l, "No Isolation"); } if (dll_chars & PE_DllCharacteristic_NO_SEH) { str8_list_pushf(scratch.arena, &l, "No SEH"); } if (dll_chars & PE_DllCharacteristic_NO_BIND) { str8_list_pushf(scratch.arena, &l, "No Bind"); } if (dll_chars & PE_DllCharacteristic_APPCONTAINER) { str8_list_pushf(scratch.arena, &l, "App Container"); } if (dll_chars & PE_DllCharacteristic_WDM_DRIVER) { str8_list_pushf(scratch.arena, &l, "WDM Driver"); } if (dll_chars & PE_DllCharacteristic_GUARD_CF) { str8_list_pushf(scratch.arena, &l, "GuardCF"); } if (dll_chars & PE_DllCharacteristic_TERMINAL_SERVER_AWARE) { str8_list_pushf(scratch.arena, &l, "Terminal Server Aware"); } String8 result = str8_list_join(arena, &l, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal PE_WindowsSubsystem pe_subsystem_from_string(String8 string) { for (U64 i = 0; i < ArrayCount(g_pe_subsystem_map); i += 1) { if (str8_match(g_pe_subsystem_map[i].string, string, StringMatchFlag_CaseInsensitive)) { return g_pe_subsystem_map[i].type; } } return PE_WindowsSubsystem_UNKNOWN; } //////////////////////////////// //~ rjf: Parser Functions internal B32 pe_check_magic(String8 data) { B32 is_pe = 0; PE_DosHeader dos_header = {0}; str8_deserial_read_struct(data, 0, &dos_header); if (dos_header.magic == PE_DOS_MAGIC) { U32 pe_magic = 0; str8_deserial_read_struct(data, dos_header.coff_file_offset, &pe_magic); is_pe= pe_magic == PE_MAGIC; } return is_pe; } internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data) { PE_BinInfo info = {0}; B32 valid = 1; // rjf: read dos header PE_DosHeader dos_header = {0}; str8_deserial_read_struct(data, 0, &dos_header); // rjf: bad dos magic -> bad if(dos_header.magic != PE_DOS_MAGIC) { valid = 0; } // rjf: read pe magic U32 pe_magic = 0; if(valid) { str8_deserial_read_struct(data, dos_header.coff_file_offset, &pe_magic); } // rjf: bad pe magic -> abort if(pe_magic != PE_MAGIC) { valid = 0; } // rjf: read coff header U32 file_header_off = dos_header.coff_file_offset + sizeof(pe_magic); COFF_FileHeader file_header = {0}; if(valid) { str8_deserial_read_struct(data, file_header_off, &file_header); } // rjf: range of optional extension header ("optional" for short) U32 optional_size = file_header.optional_header_size; U64 after_file_header_off = file_header_off + sizeof(COFF_FileHeader); U64 after_optional_header_off = after_file_header_off + optional_size; Rng1U64 optional_range = {0}; if(valid) { optional_range.min = ClampTop(after_file_header_off, data.size); optional_range.max = ClampTop(after_optional_header_off, data.size); } // rjf: get sections U64 sec_array_off = optional_range.max; U64 sec_array_raw_opl = sec_array_off + file_header.section_count*sizeof(COFF_SectionHeader); U64 sec_array_opl = ClampTop(sec_array_raw_opl, data.size); U64 clamped_sec_count = (sec_array_opl - sec_array_off)/sizeof(COFF_SectionHeader); COFF_SectionHeader *sections = (COFF_SectionHeader*)(data.str + sec_array_off); // rjf: get symbols U64 symbol_array_off = file_header.symbol_table_foff; U64 symbol_count = file_header.symbol_count; // rjf: get string table U64 string_table_off = symbol_array_off + sizeof(COFF_Symbol16) * symbol_count; // rjf: read optional header U16 optional_magic = 0; U64 image_base = 0; U64 entry_point = 0; PE_WindowsSubsystem subsystem = 0; U32 *check_sum = 0; U32 data_dir_count = 0; U64 virt_section_align = 0; U64 file_section_align = 0; Rng1U64 data_dir_range = {0}; Rng1U64 *data_dir_franges = 0; Rng1U64 *data_dir_vranges = 0; if(valid && optional_size > 0) { // rjf: read magic number str8_deserial_read_struct(data, optional_range.min, &optional_magic); // rjf: read info U32 reported_data_dir_offset = 0; U32 reported_data_dir_count = 0; switch(optional_magic) { case PE_PE32_MAGIC: { PE_OptionalHeader32 *pe_optional = str8_deserial_get_raw_ptr(data, optional_range.min, sizeof(*pe_optional)); if(pe_optional) { image_base = pe_optional->image_base; entry_point = pe_optional->entry_point_va; subsystem = pe_optional->subsystem; check_sum = &pe_optional->check_sum; virt_section_align = pe_optional->section_alignment; file_section_align = pe_optional->file_alignment; reported_data_dir_offset = sizeof(*pe_optional); reported_data_dir_count = pe_optional->data_dir_count; } else { Assert(!"unable to read PE Optional Header"); } }break; case PE_PE32PLUS_MAGIC: { PE_OptionalHeader32Plus *pe_optional = str8_deserial_get_raw_ptr(data, optional_range.min, sizeof(*pe_optional)); if(pe_optional) { image_base = pe_optional->image_base; entry_point = pe_optional->entry_point_va; subsystem = pe_optional->subsystem; check_sum = &pe_optional->check_sum; virt_section_align = pe_optional->section_alignment; file_section_align = pe_optional->file_alignment; reported_data_dir_offset = sizeof(*pe_optional); reported_data_dir_count = pe_optional->data_dir_count; } else { Assert(!"unable to read PE Optional Plus Header"); } }break; } // rjf: find file ranges of data directories U32 data_dir_max = (optional_size - reported_data_dir_offset) / sizeof(PE_DataDirectory); data_dir_count = ClampTop(reported_data_dir_count, data_dir_max); // rjf: convert PE directories to ranges data_dir_franges = push_array(arena, Rng1U64, Max(data_dir_count, PE_DataDirectoryIndex_COUNT)); for(U32 dir_idx = 0; dir_idx < data_dir_count; dir_idx += 1) { U64 dir_offset = optional_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*dir_idx; PE_DataDirectory dir = {0}; if(str8_deserial_read_struct(data, dir_offset, &dir) == sizeof(dir)) { U64 file_off = coff_foff_from_voff(sections, clamped_sec_count, dir.virt_off); data_dir_franges[dir_idx] = r1u64(file_off, file_off+dir.virt_size); } else { Assert(!"unable to read data directory"); } } // export virtual directory ranges data_dir_vranges = push_array(arena, Rng1U64, data_dir_count); for(U32 dir_idx = 0; dir_idx < data_dir_count; dir_idx += 1) { U64 dir_offset = optional_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*dir_idx; PE_DataDirectory dir = {0}; if(str8_deserial_read_struct(data, dir_offset, &dir) == sizeof(dir)) { data_dir_vranges[dir_idx] = r1u64(dir.virt_off, dir.virt_off+dir.virt_size); } else { Assert(!"unable to read data directory"); } } // export directory range data_dir_range = rng_1u64(optional_range.min + reported_data_dir_offset, optional_range.min + reported_data_dir_offset + data_dir_count * sizeof(PE_DataDirectory)); } // rjf: extract tls header PE_TLSHeader64 tls_header = {0}; if(valid && PE_DataDirectoryIndex_TLS < data_dir_count) { Rng1U64 tls_header_frng = data_dir_franges[PE_DataDirectoryIndex_TLS]; switch(file_header.machine) { default:{ NotImplemented; }break; case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: { PE_TLSHeader32 tls_header32 = {0}; if(str8_deserial_read_struct(data, tls_header_frng.min, &tls_header32) == sizeof(tls_header32)) { tls_header.raw_data_start = (U64)tls_header32.raw_data_start; tls_header.raw_data_end = (U64)tls_header32.raw_data_end; tls_header.index_address = (U64)tls_header32.index_address; tls_header.callbacks_address = (U64)tls_header32.callbacks_address; tls_header.zero_fill_size = (U64)tls_header32.zero_fill_size; tls_header.characteristics = (U64)tls_header32.characteristics; } else { Assert(!"unable to read TLS Header 32"); } }break; case COFF_MachineType_X64: { if(str8_deserial_read_struct(data, tls_header_frng.min, &tls_header) != sizeof(tls_header)) { MemoryZeroStruct(&tls_header); Assert(!"unable to read TLS Header 64"); } }break; } } // rjf: fill info if(valid) { info.arch = arch_from_coff_machine(file_header.machine); info.image_base = image_base; info.entry_point = entry_point; info.is_pe32 = (optional_magic == PE_PE32_MAGIC); info.subsystem = subsystem; info.check_sum = check_sum; info.virt_section_align = virt_section_align; info.file_section_align = file_section_align; info.section_count = clamped_sec_count; info.symbol_count = symbol_count; info.optional_header_off = optional_range.min; info.section_table_range = rng_1u64(sec_array_off, sec_array_off + sizeof(COFF_SectionHeader) * clamped_sec_count); info.symbol_table_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count); info.string_table_range = rng_1u64(string_table_off, data.size); info.data_dir_range = data_dir_range; info.data_dir_franges = data_dir_franges; info.data_dir_vranges = data_dir_vranges; info.data_dir_count = data_dir_count; info.tls_header = tls_header; } return info; } internal PE_DataDirectory * pe_data_directory_from_idx(String8 file_data, PE_BinInfo pe, PE_DataDirectoryIndex dir_idx) { PE_DataDirectory *result = 0; if (dir_idx < pe.data_dir_count) { result = str8_deserial_get_raw_ptr(file_data, pe.data_dir_range.min + sizeof(*result)*dir_idx, sizeof(*result)); } return result; } internal PE_DebugInfoList pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir) { PE_DebugInfoList result = {0}; PE_DebugDirectory *debug_entry = str8_deserial_get_raw_ptr(raw_debug_dir, 0, sizeof(*debug_entry)); PE_DebugDirectory *debug_entry_opl = debug_entry + raw_debug_dir.size/sizeof(*debug_entry_opl); for(PE_DebugDirectory *entry = debug_entry; entry < debug_entry_opl; entry += 1) { PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); SLLQueuePush(result.first, result.last, n); result.count += 1; n->v.header = *entry; switch(entry->type) { default:{}break; case PE_DebugDirectoryType_CODEVIEW: { str8_deserial_read_struct(raw_image, entry->foff, &n->v.cv_magic); switch(n->v.cv_magic) { case PE_CODEVIEW_PDB20_MAGIC: { PE_CvHeaderPDB20 cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); if(cv_read_size == sizeof(cv)) { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); n->v.cv_pdb20_header = cv; n->v.path = path; } }break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); if(cv_read_size == sizeof(cv)) { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); n->v.cv_pdb70_header = cv; n->v.path = path; } }break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); if(cv_read_size == sizeof(cv)) { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); n->v.cv_rdi_header = cv; n->v.path = path; } }break; default:{}break; } }break; } } return result; } //////////////////////////////// //~ rjf: Helpers internal U64 pe_pdata_off_from_voff__binary_search_x8664(String8 raw_pdata, U64 voff) { U64 result = 0; if(raw_pdata.size >= sizeof(PE_IntelPdata)) { U64 pdata_count = raw_pdata.size/sizeof(PE_IntelPdata); PE_IntelPdata *pdata_array = (PE_IntelPdata*)raw_pdata.str; if(voff >= pdata_array[0].voff_first) { // binary search: // find max index s.t. pdata_array[index].voff_first <= voff // we assume (i < j) -> (pdata_array[i].voff_first < pdata_array[j].voff_first) U64 index = pdata_count; U64 min = 0; U64 opl = pdata_count; for(;;) { U64 mid = (min + opl)/2; PE_IntelPdata *pdata = pdata_array + mid; if(voff < pdata->voff_first) { opl = mid; } else if(pdata->voff_first < voff) { min = mid; } else { index = mid; break; } if(min + 1 >= opl) { index = min; break; } } // if we are in range fill result { PE_IntelPdata *pdata = pdata_array + index; if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last) { result = index*sizeof(PE_IntelPdata); } } } } return result; } internal U64 pe_foff_from_voff(String8 data, PE_BinInfo *bin, U64 voff) { U64 foff = 0; String8 raw_section_table = str8_substr(data, bin->section_table_range); COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; for(U64 sect_idx = 0; sect_idx < bin->section_count; sect_idx += 1) { COFF_SectionHeader *sect = §ion_table[sect_idx]; if(sect->voff <= voff && voff < sect->voff + sect->vsize) { if(!(sect->flags & COFF_SectionFlag_CntUninitializedData)) { foff = sect->foff + (voff - sect->voff); } break; } } return foff; } internal PE_BaseRelocBlockList pe_base_reloc_block_list_from_data(Arena *arena, String8 raw_base_relocs) { PE_BaseRelocBlockList list = {0}; for(U64 off = 0; off < raw_base_relocs.size;) { // rjf: read next entry U32 page_virt_off = 0; U32 block_size = 0; off += str8_deserial_read_struct(raw_base_relocs, off, &page_virt_off); off += str8_deserial_read_struct(raw_base_relocs, off, &block_size); // rjf: break on sentinel if(block_size == 0) { break; } // rjf: add node PE_BaseRelocBlockNode *node = push_array(arena, PE_BaseRelocBlockNode, 1); SLLQueuePush(list.first, list.last, node); list.count += 1; U64 entries_size = block_size - (sizeof(block_size) + sizeof(page_virt_off)); // rjf: fill block PE_BaseRelocBlock *block = &node->v; block->page_virt_off = page_virt_off; block->entry_count = entries_size / sizeof(U16); block->entries = push_array(arena, U16, block->entry_count); U64 entry_read_size = str8_deserial_read_array(raw_base_relocs, off, &block->entries[0], block->entry_count); Assert(entry_read_size == sizeof(block->entries[0]) * block->entry_count); off += entry_read_size; } return list; } internal Rng1U64 pe_tls_rng_from_bin_base_vaddr(String8 data, PE_BinInfo *bin, U64 base_vaddr) { U64 result_addr = (bin->tls_header.index_address - bin->image_base); U64 result_size = sizeof(U32); if(bin->arch != Arch_Null) { U64 addr_size = bit_size_from_arch(bin->arch)/8; Temp scratch = scratch_begin(0, 0); String8 raw_relocs = str8_substr(data, bin->data_dir_franges[PE_DataDirectoryIndex_BASE_RELOC]); PE_BaseRelocBlockList relocs = pe_base_reloc_block_list_from_data(scratch.arena, raw_relocs); for(PE_BaseRelocBlockNode *n = relocs.first; n != 0; n = n->next) { PE_BaseRelocBlock *block = &n->v; for(U64 ientry = 0; ientry < block->entry_count;) { U32 reloc = block->entries[ientry]; U16 kind = PE_BaseRelocKindFromEntry(reloc); U16 offset = PE_BaseRelocOffsetFromEntry(reloc); U64 apply_to_voff = block->page_virt_off + offset; U64 apply_to_foff = pe_foff_from_voff(data, bin, apply_to_voff); U64 apply_to = 0; str8_deserial_read(data, apply_to_foff, &apply_to, addr_size, 1); if(apply_to == bin->tls_header.index_address) { U64 base_diff = base_vaddr-bin->image_base; switch(kind) { default: { // NOTE(rjf): these relocs are arm/mips/riscv specific which aren't supported at the moment }break; case PE_BaseRelocKind_ABSOLUTE:{}break; case PE_BaseRelocKind_HIGH: { // rjf: relocate high 16-bits. U64 high_bits = (apply_to & max_U16) << 16; result_addr = (high_bits + ((base_diff & max_U32) >> 16)) & max_U16; }break; case PE_BaseRelocKind_LOW: { // rjf: relocate low 16-bits. U64 low_bits = apply_to & max_U16; result_addr = (low_bits + (base_diff & max_U32)) & max_U16; }break; case PE_BaseRelocKind_HIGHLOW: { // rjf: relocate 32-bits. result_addr = (apply_to & max_U32) + (base_diff & max_U32); }break; case PE_BaseRelocKind_HIGHADJ: { if(ientry + 1 >= block->entry_count) { // NOTE(rjf): malformed relocation, expected two 16-bit entries break; } // rjf: relocate high bits and adjust sign bit on lower half. U16 adj_offset = PE_BaseRelocOffsetFromEntry(block->entries[ientry + 1]); result_addr = (apply_to & max_U16) << 16; result_addr += adj_offset; result_addr += (base_diff & max_U32); result_addr += 0x8000; result_addr = (result_addr >> 16) & max_U16; }break; case PE_BaseRelocKind_DIR64: { // rjf: image base relocation. result_addr = apply_to + base_diff; }break; } goto dbl_break; } U32 advance = (kind == PE_BaseRelocKind_HIGHADJ) ? 2 : 1; ientry += advance; } } dbl_break:; scratch_end(scratch); } Rng1U64 result = r1u64(result_addr, result_addr+result_size); return result; } internal String8Array pe_get_entry_point_names(COFF_MachineType machine, PE_WindowsSubsystem subsystem, PE_ImageFileCharacteristics file_characteristics) { String8Array entry_point_names = {0}; if (file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { if (machine == COFF_MachineType_X86) { read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("__DllMainCRTStartup@12"), }; entry_point_names.v = &dll_entry_point_arr[0]; entry_point_names.count = ArrayCount(dll_entry_point_arr); } else { read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("_DllMainCRTStartup"), }; entry_point_names.v = &dll_entry_point_arr[0]; entry_point_names.count = ArrayCount(dll_entry_point_arr); } } else { switch (subsystem) { case PE_WindowsSubsystem_UNKNOWN: break; case PE_WindowsSubsystem_WINDOWS_GUI: { read_only static String8 gui_entry_point_arr[] = { str8_lit_comp("WinMain"), str8_lit_comp("wWinMain"), str8_lit_comp("WinMainCRTStartup"), str8_lit_comp("wWinMainCRTStartup"), }; entry_point_names.v = &gui_entry_point_arr[0]; entry_point_names.count = ArrayCount(gui_entry_point_arr); } break; case PE_WindowsSubsystem_WINDOWS_CUI: { read_only static String8 cui_entry_point_arr[] = { str8_lit_comp("main"), str8_lit_comp("wmain"), str8_lit_comp("mainCRTStartup"), str8_lit_comp("wmainCRTStartup"), }; entry_point_names.v = &cui_entry_point_arr[0]; entry_point_names.count = ArrayCount(cui_entry_point_arr); } break; case PE_WindowsSubsystem_NATIVE: case PE_WindowsSubsystem_OS2_CUI: case PE_WindowsSubsystem_POSIX_CUI: case PE_WindowsSubsystem_NATIVE_WINDOWS: case PE_WindowsSubsystem_WINDOWS_CE_GUI: case PE_WindowsSubsystem_EFI_APPLICATION: case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: case PE_WindowsSubsystem_EFI_ROM: case PE_WindowsSubsystem_XBOX: case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: { // TODO } break; } } return entry_point_names; } //////////////////////////////// internal PE_ParsedImport * pe_parsed_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, U64 name_table_voff, U64 *import_count_out) { PE_ParsedImport *imports = 0; U64 import_count = 0; U64 name_table_foff = coff_foff_from_voff(sections, section_count, name_table_voff); String8 entries = str8_substr(raw_data, rng_1u64(name_table_foff, raw_data.size)); if (is_pe32) { import_count = index_of_zero_u32((U32 *)entries.str, entries.size/sizeof(U32)); if (import_count == max_U64) { import_count = 0; } imports = push_array(arena, PE_ParsedImport, import_count); for (U64 imp_idx = 0; imp_idx < import_count; imp_idx += 1) { U32 raw_entry = 0; str8_deserial_read_struct(entries, imp_idx*sizeof(raw_entry), &raw_entry); B32 is_ordinal = ExtractBit(raw_entry, 31); if (is_ordinal) { // fill out ordinal import PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Ordinal; imp->u.ordinal = Extract16(raw_entry, 0); } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); // read hint & name U16 hint = 0; String8 name = str8_zero(); str8_deserial_read_struct(raw_data, off, &hint); str8_deserial_read_cstr(raw_data, off+sizeof(hint), &name); // fill out named import PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; imp->u.name.string = name; } } } else { import_count = index_of_zero_u64((U64 *)entries.str, entries.size/sizeof(U64)); if (import_count == max_U64) { import_count = 0; } imports = push_array(arena, PE_ParsedImport, import_count); for (U64 imp_idx = 0; imp_idx < import_count; imp_idx += 1) { U64 raw_entry = 0; str8_deserial_read_struct(entries, imp_idx*sizeof(raw_entry), &raw_entry); B32 is_ordinal = ExtractBit(raw_entry, 63); if (is_ordinal) { // fill out ordinal import PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Ordinal; imp->u.ordinal = Extract16(raw_entry, 0); } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); // read hint & name U16 hint = 0; String8 name = str8_zero(); str8_deserial_read_struct(raw_data, off, &hint); str8_deserial_read_cstr(raw_data, off + sizeof(hint), &name); // fill out named import PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; imp->u.name.string = name; } } } *import_count_out = import_count; return imports; } internal U64 * pe_array_from_null_term_addr(Arena *arena, B32 is_pe32, String8 raw_data, Rng1U64 range, U64 *count_out) { U64 *result = 0; *count_out = 0; if (is_pe32) { U32 *src = (U32 *)(raw_data.str + range.min); U32 *opl = (U32 *)(raw_data.str + AlignDownPow2(range.max, sizeof(*opl))); // count items U32 *ptr; for (ptr = src; ptr < opl && *ptr != 0; ++ptr); // push output array *count_out = (U64)(ptr - src); result = push_array(arena, U64, *count_out); // convert & copy for (U64 i = 0; i < *count_out; ++i) { result[i] = (U64)src[i]; } } else { U64 *src = (U64 *)(raw_data.str + range.min); U64 *opl = (U64 *)(raw_data.str + AlignDownPow2(range.max, sizeof(*opl))); // count items U64 *ptr; for (ptr = src; ptr < opl && *ptr != 0; ++ptr); // push output array *count_out = (U64)(ptr - src); result = push_array(arena, U64, *count_out); // copy MemoryCopyTyped(result, src, *count_out); } return result; } internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range) { // count imports U64 max_dll_count = dim_1u64(dir_file_range) / sizeof (PE_ImportEntry); U64 dll_count = max_dll_count; for (U64 i = 0; i < max_dll_count; ++i) { PE_ImportEntry *imp = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(i*sizeof(*imp)), sizeof(*imp)); if (memory_is_zero(imp, sizeof(*imp))) { dll_count = i; break; } } PE_ParsedStaticDLLImport *dlls = push_array(arena, PE_ParsedStaticDLLImport, dll_count); for (U64 dll_idx = 0; dll_idx < dll_count; ++dll_idx) { PE_ImportEntry *raw_dll = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(dll_idx*sizeof(*raw_dll)), sizeof(*raw_dll)); // get name U64 name_off = coff_foff_from_voff(sections, section_count, raw_dll->name_voff); String8 name = str8_zero(); str8_deserial_read_cstr(raw_data, name_off, &name); U64 import_count = 0; PE_ParsedImport *imports = pe_parsed_imports_from_data(arena, is_pe32, section_count, sections, raw_data, raw_dll->lookup_table_voff, &import_count); PE_ParsedStaticDLLImport *dll = dlls+dll_idx; dll->name = name; dll->import_address_table_voff = raw_dll->import_addr_table_voff; dll->import_name_table_voff = raw_dll->lookup_table_voff; dll->time_stamp = raw_dll->time_stamp; dll->forwarder_chain = raw_dll->forwarder_chain; dll->import_count = import_count; dll->imports = imports; } PE_ParsedStaticImportTable imptab = {0}; imptab.count = dll_count; imptab.v = dlls; return imptab; } internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range) { // count imports U64 max_dll_count = dim_1u64(dir_file_range) / sizeof(PE_DelayedImportEntry); U64 dll_count = 0; for (; dll_count < max_dll_count; ++dll_count) { PE_DelayedImportEntry *raw_dll = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(dll_count*sizeof(*raw_dll)), sizeof(*raw_dll)); if (memory_is_zero(raw_dll, sizeof(*raw_dll))) { break; } } // parse dll imports PE_ParsedDelayDLLImport *dlls = push_array(arena, PE_ParsedDelayDLLImport, dll_count); for (U64 dll_idx = 0; dll_idx < dll_count; ++dll_idx) { PE_DelayedImportEntry *raw_dll = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(dll_idx*sizeof(*raw_dll)), sizeof(*raw_dll)); U64 name_off = coff_foff_from_voff(sections, section_count, raw_dll->name_voff); String8 name = str8_zero(); str8_deserial_read_cstr(raw_data, name_off, &name); // parse import table U64 import_count = 0; PE_ParsedImport *imports = pe_parsed_imports_from_data(arena, is_pe32, section_count, sections, raw_data, raw_dll->name_table_voff, &import_count); // parse bound table Rng1U64 bound_table_range = {0}; if (raw_dll->bound_table_voff) { U64 bound_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->bound_table_voff); bound_table_range = rng_1u64(bound_table_foff, raw_data.size); } U64 bound_table_count; U64 *bound_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, bound_table_range, &bound_table_count); // parse unload table Rng1U64 unload_table_range = {0}; if (raw_dll->unload_table_voff) { U64 unload_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->unload_table_voff); unload_table_range = rng_1u64(unload_table_foff, raw_data.size); } U64 unload_table_count; U64 *unload_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, unload_table_range, &unload_table_count); // fill out DLL PE_ParsedDelayDLLImport *dll = dlls+dll_idx; dll->attributes = raw_dll->attributes; dll->name = name; dll->module_handle_voff = raw_dll->module_handle_voff; dll->iat_voff = raw_dll->iat_voff; dll->name_table_voff = raw_dll->name_table_voff; dll->bound_table_voff = raw_dll->bound_table_voff; dll->unload_table_voff = raw_dll->unload_table_voff; dll->time_stamp = raw_dll->time_stamp; dll->bound_table_count = bound_table_count; dll->bound_table = bound_table; dll->unload_table_count = unload_table_count; dll->unload_table = unload_table; dll->import_count = import_count; dll->imports = imports; } // fill out result PE_ParsedDelayImportTable imptab = {0}; imptab.count = dll_count; imptab.v = dlls; return imptab; } internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range) { Temp scratch = scratch_begin(&arena, 1); PE_ParsedExportTable exptab = {0}; String8 raw_dir = str8_substr(raw_data, dir_file_range); PE_ExportTableHeader *header = str8_deserial_get_raw_ptr(raw_dir, 0, sizeof(*header)); if (header) { U64 name_table_off = coff_foff_from_voff(sections, section_count, header->name_pointer_table_voff); U64 export_table_off = coff_foff_from_voff(sections, section_count, header->export_address_table_voff); U64 ordinal_table_off = coff_foff_from_voff(sections, section_count, header->ordinal_table_voff); U32 *name_table = str8_deserial_get_raw_ptr(raw_data, name_table_off, sizeof(*name_table )*header->name_pointer_table_count); U32 *export_table = str8_deserial_get_raw_ptr(raw_data, export_table_off, sizeof(*export_table )*header->export_address_table_count); U16 *ordinal_table = str8_deserial_get_raw_ptr(raw_data, ordinal_table_off, sizeof(*ordinal_table)*header->name_pointer_table_count); if (name_table && export_table && ordinal_table) { // Scan export address table to get accruate count of ordinals. // We can't rely on "name_pointer_table_count" becuase it is possible // to define an export without a name through NONAME attribute in DEF file U64 ordinal_count = 0; for (U64 voff_idx = 0; voff_idx < header->export_address_table_count; ++voff_idx) { if (export_table[voff_idx] != 0) { ++ordinal_count; } } U64 ordinal_max = header->export_address_table_count; B32 *is_ordinal_used = push_array(scratch.arena, B32, ordinal_max); PE_ParsedExport *exports = push_array(arena, PE_ParsedExport, ordinal_count); PE_ParsedExport *curr_exp = exports; // parse exports with name for (U64 i = 0; i < header->name_pointer_table_count; ++i) { // get name U32 name_voff = name_table[i]; U64 name_foff = coff_foff_from_voff(sections, section_count, name_voff); String8 name = str8_cstring_capped(raw_data.str+name_foff, raw_data.str+raw_data.size); // get ordinal U16 ordinal_nb = ordinal_table[i]; // mark ordinal Assert(ordinal_nb < ordinal_max); is_ordinal_used[ordinal_nb] = 1; // get voff U32 export_voff = 0; if (ordinal_nb < header->export_address_table_count) { export_voff = export_table[ordinal_nb]; } // make ordinal U16 ordinal = header->ordinal_base + ordinal_nb; String8 forwarder = str8_zero(); { B32 is_forwarder = dir_virt_range.min <= export_voff && export_voff < dir_virt_range.max; if (is_forwarder) { U64 fwd_name_off = coff_foff_from_voff(sections, section_count, export_voff); str8_deserial_read_cstr(raw_data, fwd_name_off, &forwarder); } } curr_exp->forwarder = forwarder; curr_exp->name = name; curr_exp->voff = export_voff; curr_exp->ordinal = ordinal; ++curr_exp; } // parse exports with ordinal for (U64 ordinal_nb = 0; ordinal_nb < header->export_address_table_count; ++ordinal_nb) { U32 voff = export_table[ordinal_nb]; B32 is_voff_taken = (voff != 0); B32 is_ordinal_free = !is_ordinal_used[ordinal_nb]; if (is_voff_taken && is_ordinal_free) { curr_exp->name = str8_zero(); curr_exp->voff = voff; curr_exp->ordinal = header->ordinal_base; ++curr_exp; } } // fill out result exptab.flags = header->flags; exptab.time_stamp = header->time_stamp; exptab.major_ver = header->major_ver; exptab.minor_ver = header->minor_ver; exptab.ordinal_base = header->ordinal_base; exptab.export_count = ordinal_count; exptab.exports = exports; } } scratch_end(scratch); return exptab; } internal PE_ParsedTLS pe_tls_from_data(Arena *arena, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 tls_frange) { String8 raw_tls = str8_substr(raw_data, tls_frange); PE_TLSHeader64 header64 = {0}; U64 callback_count = 0; U64 *callback_addrs = 0; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: { PE_TLSHeader32 header32 = {0}; str8_deserial_read_struct(raw_tls, 0, &header32); header64.raw_data_start = header32.raw_data_start; header64.raw_data_end = header32.raw_data_end; header64.index_address = header32.index_address; header64.callbacks_address = header32.callbacks_address; header64.zero_fill_size = header32.zero_fill_size; header64.characteristics = header32.characteristics; U64 callbacks_voff = header32.callbacks_address - image_base; U64 callbacks_foff = coff_foff_from_voff(sections, section_count, callbacks_voff); U32 *src = (U32 *)(raw_data.str + callbacks_foff); U32 *opl = (U32 *)(raw_data.str + raw_data.size); U32 *ptr = src; for (; ptr < opl && *ptr != 0; ++ptr); callback_count = (U64)(ptr-src); callback_addrs = push_array(arena, U64, callback_count); for (U64 i = 0; i < callback_count; ++i) { callback_addrs[i] = (U64)src[i]; } } break; case COFF_MachineType_X64: { str8_deserial_read_struct(raw_tls, 0, &header64); U64 callbacks_voff = header64.callbacks_address - image_base; U64 callbacks_foff = coff_foff_from_voff(sections, section_count, callbacks_voff); U64 *src = (U64 *)(raw_data.str + callbacks_foff); U64 *opl = (U64 *)(raw_data.str + raw_data.size); U64 *ptr = src; for (; ptr < opl && *ptr != 0; ++ptr); callback_count = (U64)(ptr-src); callback_addrs = push_array(arena, U64, callback_count); MemoryCopyTyped(callback_addrs, src, callback_count); } break; default: NotImplemented; } PE_ParsedTLS result = {0}; result.header = header64; result.callback_count = callback_count; result.callback_addrs = callback_addrs; return result; } //////////////////////////////// internal B32 pe_is_res(String8 data) { U8 magic[sizeof(PE_RES_MAGIC)]; MemoryZeroStruct(&magic); str8_deserial_read_struct(data, 0, &magic); B32 is_res = MemoryCompare(&PE_RES_MAGIC, &magic, sizeof(magic)) == 0; return is_res; } internal PE_ResourceNode * pe_resource_dir_push_dir_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, U32 characteristics, COFF_TimeStamp time_stamp, U16 major_version, U16 minor_version) { PE_ResourceList *list = 0; switch (id.type) { default: case COFF_ResourceIDType_Null: break; case COFF_ResourceIDType_String: list = &dir->named_list; break; case COFF_ResourceIDType_Number: list = &dir->id_list; break; } PE_ResourceNode *res_node = push_array(arena, PE_ResourceNode, 1); SLLQueuePush(list->first, list->last, res_node); list->count += 1; PE_ResourceDir *sub_dir = push_array(arena, PE_ResourceDir, 1); sub_dir->characteristics = characteristics; sub_dir->time_stamp = time_stamp; sub_dir->major_version = major_version; sub_dir->minor_version = minor_version; PE_Resource *res = &res_node->data; res->id = id; res->kind = PE_ResDataKind_DIR; res->u.dir = sub_dir; return res_node; } internal PE_ResourceNode * pe_resource_dir_push_entry_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, COFF_ResourceID type, U32 data_version, U32 version, COFF_ResourceMemoryFlags memory_flags, String8 data) { PE_ResourceList *list = NULL; switch (id.type) { default: case COFF_ResourceIDType_Null: break; case COFF_ResourceIDType_String: list = &dir->named_list; break; case COFF_ResourceIDType_Number: list = &dir->id_list; break; } PE_ResourceNode *res_node = push_array(arena, PE_ResourceNode, 1); SLLQueuePush(list->first, list->last, res_node); list->count += 1; PE_Resource *res = &res_node->data; res->id = id; res->kind = PE_ResDataKind_COFF_RESOURCE; res->u.coff_res.type = type; res->u.coff_res.data_version = data_version; res->u.coff_res.version = version; res->u.coff_res.memory_flags = memory_flags; res->u.coff_res.data = data; return res_node; } internal PE_Resource * pe_resource_dir_push_entry(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, COFF_ResourceID type, U32 data_version, U32 version, COFF_ResourceMemoryFlags memory_flags, String8 data) { PE_ResourceNode *node = pe_resource_dir_push_entry_node(arena, dir, id, type, data_version, version, memory_flags, data); return &node->data; } internal PE_Resource * pe_resource_dir_push_dir(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, U32 characteristics, COFF_TimeStamp time_stamp, U16 major_version, U16 minor_version) { PE_ResourceNode *dir_node = pe_resource_dir_push_dir_node(arena, dir, id, characteristics, time_stamp, major_version, minor_version); return &dir_node->data; } internal PE_ResourceNode * pe_resource_dir_search_node(PE_ResourceDir *dir, COFF_ResourceID id) { for (PE_ResourceNode *i = dir->id_list.first; i != 0; i = i->next) { if (coff_resource_id_compar(&i->data.id, &id) == 0) { return i; } } return NULL; } internal PE_Resource * pe_resource_dir_search(PE_ResourceDir *dir, COFF_ResourceID id) { PE_ResourceNode *node = pe_resource_dir_search_node(dir, id); return node ? &node->data : NULL; } internal PE_ResourceArray pe_resource_list_to_array(Arena *arena, PE_ResourceList *list) { PE_ResourceArray result; result.count = 0; result.v = push_array(arena, PE_Resource, list->count); for (PE_ResourceNode *n = list->first; n != NULL; n = n->next) { result.v[result.count++] = n->data; } return result; } internal void pe_resource_dir_push_res_file(Arena *arena, PE_ResourceDir *root_dir, String8 res_file) { // parse file into resource list String8 res_data = str8_substr(res_file, rng_1u64(sizeof(PE_RES_MAGIC), res_file.size)); COFF_ParsedResourceList list = coff_resource_list_from_data(arena, res_data); // move resources to directories based on type for (COFF_ParsedResourceNode *res_node = list.first; res_node != NULL; res_node = res_node->next) { COFF_ParsedResource *res = &res_node->data; // search existing directories PE_Resource *dir_res = pe_resource_dir_search(root_dir, res->type); // create new directory if (dir_res == NULL) { dir_res = pe_resource_dir_push_dir(arena, root_dir, res->type, 0, 0, 0, 0); } PE_ResourceDir *dir = dir_res->u.dir; // check for name collisions PE_Resource *check_res = pe_resource_dir_search(dir, res->name); if (check_res != NULL) { // TODO: how do we handle name conflicts? Assert(!"name collision"); continue; } // push entry PE_Resource *sub_dir_res = pe_resource_dir_push_dir(arena, dir, res->name, 0, 0, 0, 0); COFF_ResourceID id; id.type = COFF_ResourceIDType_Number; id.u.number = res->language_id; pe_resource_dir_push_entry(arena, sub_dir_res->u.dir, id, res->type, res->data_version, res->version, res->memory_flags, res->data); } } internal PE_ResourceDir * pe_resource_table_from_directory_data(Arena *arena, String8 data) { struct stack_s { struct stack_s *next; U64 table_offset; U64 name_base_offset; U64 id_base_offset; PE_ResourceDir *table; PE_ResourceDir **directory_ptr; U64 name_ientry; U64 id_ientry; U64 name_entry_count; U64 id_entry_count; }; Temp scratch = scratch_begin(&arena,1); struct stack_s *bottom_frame = push_array(scratch.arena, struct stack_s, 1); struct stack_s *stack = bottom_frame; while (stack) { if (stack->table == NULL) { COFF_ResourceDirTable coff_table = {0}; str8_deserial_read_struct(data, stack->table_offset, &coff_table); PE_ResourceDir *table = push_array(arena, PE_ResourceDir, 1); table->characteristics = coff_table.characteristics; table->time_stamp = coff_table.time_stamp; table->major_version = coff_table.major_version; table->minor_version = coff_table.minor_version; stack->table = table; stack->name_base_offset = stack->table_offset + sizeof(COFF_ResourceDirTable); stack->id_base_offset = stack->table_offset + sizeof(COFF_ResourceDirTable) + sizeof(COFF_ResourceDirEntry) * coff_table.name_entry_count; stack->name_entry_count = coff_table.name_entry_count; stack->id_entry_count = coff_table.id_entry_count; if (stack->directory_ptr) { *stack->directory_ptr = table; } } while (stack->name_ientry < stack->name_entry_count) { U64 entry_offset = stack->name_base_offset + stack->name_ientry * sizeof(COFF_ResourceDirEntry); ++stack->name_ientry; PE_ResourceNode *named_node = push_array(arena, PE_ResourceNode, 1); SLLQueuePush(stack->table->named_list.first, stack->table->named_list.last, named_node); ++stack->table->named_list.count; PE_Resource *entry = &named_node->data; COFF_ResourceDirEntry coff_entry = {0}; str8_deserial_read_struct(data, entry_offset, &coff_entry); // NOTE: this is not documented on MSDN but high bit here is set for some reason U32 name_offset = coff_entry.name.offset & ~COFF_Resource_SubDirFlag; U16 name_size = 0; str8_deserial_read_struct(data, name_offset, &name_size); String8 name_block; str8_deserial_read_block(data, name_offset + sizeof(name_size), name_size*sizeof(U16), &name_block); String16 name16 = str16((U16*)name_block.str, name_size); B32 is_dir = !!(coff_entry.id.data_entry_offset & COFF_Resource_SubDirFlag); entry->id.type = COFF_ResourceIDType_String; entry->id.u.string = str8_from_16(arena, name16); entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF; if (is_dir) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_Resource_SubDirFlag; frame->directory_ptr = &entry->u.dir; SLLStackPush(stack, frame); goto yeild; } else { str8_deserial_read_struct(data, coff_entry.id.data_entry_offset, &entry->u.leaf); } } while (stack->id_ientry < stack->id_entry_count) { U64 entry_offset = stack->id_base_offset + stack->id_ientry * sizeof(COFF_ResourceDirEntry); ++stack->id_ientry; PE_ResourceNode *id_node = push_array(arena, PE_ResourceNode, 1); SLLQueuePush(stack->table->id_list.first, stack->table->id_list.last, id_node); ++stack->table->id_list.count; PE_Resource *entry = &id_node->data; COFF_ResourceDirEntry coff_entry = {0}; str8_deserial_read_struct(data, entry_offset, &coff_entry); B32 is_dir = !!(coff_entry.id.sub_dir_offset & COFF_Resource_SubDirFlag); entry->id.type = COFF_ResourceIDType_Number; entry->id.u.number = coff_entry.name.id; entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF; if (is_dir) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_Resource_SubDirFlag; frame->directory_ptr = &entry->u.dir; SLLStackPush(stack, frame); goto yeild; } else { str8_deserial_read_struct(data, coff_entry.id.sub_dir_offset, &entry->u.leaf); } } SLLStackPop(stack); yeild:; } scratch_end(scratch); return bottom_frame->table; } internal String8 pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data) { COFF_ResourceID type = {0}; type.type = COFF_ResourceIDType_Number; type.u.number = PE_ResourceKind_MANIFEST; COFF_ResourceID id = {0}; id.type = COFF_ResourceIDType_Number; id.u.number = resource_id; String8 res = coff_write_resource(arena, type, id, 1, 0, 1033, 0, 0, manifest_data); return res; } //////////////////////////////// //~ Debug Directory internal String8 pe_make_debug_header_pdb70(Arena *arena, Guid guid, U32 age, String8 pdb_path) { Temp scratch = scratch_begin(&arena, 1); PE_CvHeaderPDB70 header = {0}; header.magic = PE_CODEVIEW_PDB70_MAGIC; header.guid = guid; header.age = age; String8List cv_list = {0}; str8_serial_begin(scratch.arena, &cv_list); str8_serial_push_struct(scratch.arena, &cv_list, &header); str8_serial_push_cstr(scratch.arena, &cv_list, pdb_path); String8 cv_data = str8_serial_end(arena, &cv_list); scratch_end(scratch); return cv_data; } internal String8 pe_make_debug_header_rdi(Arena *arena, Guid guid, String8 rdi_path) { Temp scratch = scratch_begin(&arena,1); PE_CvHeaderRDI header = {0}; header.magic = PE_CODEVIEW_RDI_MAGIC; header.guid = guid; String8List list = {0}; str8_serial_begin(scratch.arena, &list); str8_serial_push_struct(scratch.arena, &list, &header); str8_serial_push_cstr(scratch.arena, &list, rdi_path); String8 cv_data = str8_serial_end(arena, &list); scratch_end(scratch); return cv_data; } //////////////////////////////// //~ Image Checksum internal U32 pe_compute_checksum(U8 *buffer, U64 buffer_size) { // https://bytepointer.com/resources/microsoft_pe_checksum_algo_distilled.htm U32 hash = 0; for (U16 *ptr16 = (U16*)buffer, *opl16 = (U16*)(buffer + buffer_size); ptr16 < opl16; ptr16 += 1) { hash += *ptr16; hash = (hash >> 16) + (hash & 0xffff); } hash = (U16)(((hash >> 16) + hash) & 0xffff); hash += buffer_size; return hash; } //////////////////////////////// internal B32 pe_has_plus_header(COFF_MachineType machine) { B32 has_plus_header = 0; switch (machine) { case COFF_MachineType_X86: { has_plus_header = 0; } break; case COFF_MachineType_X64: { has_plus_header = 1; } break; } return has_plus_header; } //////////////////////////////// internal int pe_pdata_is_before_x86_64(void *raw_a, void *raw_b) { PE_IntelPdata *a = raw_a, *b = raw_b; return a->voff_first < b->voff_first; } internal void pe_pdata_sort(COFF_MachineType machine, String8 raw_pdata) { ProfBeginFunction(); switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: case COFF_MachineType_X64: { U64 count = raw_pdata.size / sizeof(PE_IntelPdata); radsort((PE_IntelPdata *)raw_pdata.str, count, pe_pdata_is_before_x86_64); } break; default: { NotImplemented; } break; } ProfEnd(); } ================================================ FILE: src/pe/pe.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_H #define PE_H //////////////////////////////// //~ rjf: PE Format-Defined Types/Constants #pragma pack(push,1) typedef struct PE_DosHeader PE_DosHeader; struct PE_DosHeader { U16 magic; U16 last_page_size; U16 page_count; U16 reloc_count; U16 paragraph_header_size; U16 min_paragraph; U16 max_paragraph; U16 init_ss; U16 init_sp; U16 checksum; U16 init_ip; U16 init_cs; U16 reloc_table_file_off; U16 overlay_number; U16 reserved[4]; U16 oem_id; U16 oem_info; U16 reserved2[10]; U32 coff_file_offset; }; typedef U16 PE_WindowsSubsystem; enum { PE_WindowsSubsystem_UNKNOWN = 0, PE_WindowsSubsystem_NATIVE = 1, PE_WindowsSubsystem_WINDOWS_GUI = 2, PE_WindowsSubsystem_WINDOWS_CUI = 3, PE_WindowsSubsystem_OS2_CUI = 5, PE_WindowsSubsystem_POSIX_CUI = 7, PE_WindowsSubsystem_NATIVE_WINDOWS = 8, PE_WindowsSubsystem_WINDOWS_CE_GUI = 9, PE_WindowsSubsystem_EFI_APPLICATION = 10, PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER = 11, PE_WindowsSubsystem_EFI_RUNTIME_DRIVER = 12, PE_WindowsSubsystem_EFI_ROM = 13, PE_WindowsSubsystem_XBOX = 14, PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION = 16, PE_WindowsSubsystem_COUNT = 14 }; typedef U16 PE_ImageFileCharacteristics; enum { PE_ImageFileCharacteristic_STRIPPED = (1 << 0), PE_ImageFileCharacteristic_EXE = (1 << 1), PE_ImageFileCharacteristic_NUMS_STRIPPED = (1 << 2), PE_ImageFileCharacteristic_PE_STRIPPED = (1 << 3), PE_ImageFileCharacteristic_AGGRESIVE_WS_TRIM = (1 << 4), PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE = (1 << 5), PE_ImageFileCharacteristic_UNUSED1 = (1 << 6), PE_ImageFileCharacteristic_BYTES_RESERVED_LO = (1 << 7), PE_ImageFileCharacteristic_32BIT_MACHINE = (1 << 8), PE_ImageFileCharacteristic_DEBUG_STRIPPED = (1 << 9), PE_ImageFileCharacteristic_FILE_REMOVABLE_RUN_FROM_SWAP = (1 << 10), PE_ImageFileCharacteristic_NET_RUN_FROM_SWAP = (1 << 11), PE_ImageFileCharacteristic_FILE_SYSTEM = (1 << 12), PE_ImageFileCharacteristic_FILE_DLL = (1 << 13), PE_ImageFileCharacteristic_FILE_UP_SYSTEM_ONLY = (1 << 14), PE_ImageFileCharacteristic_BYTES_RESERVED_HI = (1 << 15), }; typedef U16 PE_DllCharacteristics; enum { PE_DllCharacteristic_HIGH_ENTROPY_VA = (1 << 5), PE_DllCharacteristic_DYNAMIC_BASE = (1 << 6), PE_DllCharacteristic_FORCE_INTEGRITY = (1 << 7), PE_DllCharacteristic_NX_COMPAT = (1 << 8), PE_DllCharacteristic_NO_ISOLATION = (1 << 9), PE_DllCharacteristic_NO_SEH = (1 << 10), PE_DllCharacteristic_NO_BIND = (1 << 11), PE_DllCharacteristic_APPCONTAINER = (1 << 12), PE_DllCharacteristic_WDM_DRIVER = (1 << 13), PE_DllCharacteristic_GUARD_CF = (1 << 14), PE_DllCharacteristic_TERMINAL_SERVER_AWARE = (1 << 15), }; typedef struct PE_OptionalHeader32 PE_OptionalHeader32; struct PE_OptionalHeader32 { U16 magic; U8 major_linker_version; U8 minor_linker_version; U32 sizeof_code; U32 sizeof_inited_data; U32 sizeof_uninited_data; U32 entry_point_va; U32 code_base; U32 data_base; U32 image_base; U32 section_alignment; U32 file_alignment; U16 major_os_ver; U16 minor_os_ver; U16 major_img_ver; U16 minor_img_ver; U16 major_subsystem_ver; U16 minor_subsystem_ver; U32 win32_version_value; U32 sizeof_image; U32 sizeof_headers; U32 check_sum; PE_WindowsSubsystem subsystem; PE_DllCharacteristics dll_characteristics; U32 sizeof_stack_reserve; U32 sizeof_stack_commit; U32 sizeof_heap_reserve; U32 sizeof_heap_commit; U32 loader_flags; U32 data_dir_count; }; typedef struct PE_OptionalHeader32Plus PE_OptionalHeader32Plus; struct PE_OptionalHeader32Plus { U16 magic; U8 major_linker_version; U8 minor_linker_version; U32 sizeof_code; U32 sizeof_inited_data; U32 sizeof_uninited_data; U32 entry_point_va; U32 code_base; U64 image_base; U32 section_alignment; U32 file_alignment; U16 major_os_ver; U16 minor_os_ver; U16 major_img_ver; U16 minor_img_ver; U16 major_subsystem_ver; U16 minor_subsystem_ver; U32 win32_version_value; U32 sizeof_image; U32 sizeof_headers; U32 check_sum; PE_WindowsSubsystem subsystem; PE_DllCharacteristics dll_characteristics; U64 sizeof_stack_reserve; U64 sizeof_stack_commit; U64 sizeof_heap_reserve; U64 sizeof_heap_commit; U32 loader_flags; U32 data_dir_count; }; typedef enum PE_DataDirectoryIndex { PE_DataDirectoryIndex_EXPORT, PE_DataDirectoryIndex_IMPORT, PE_DataDirectoryIndex_RESOURCES, PE_DataDirectoryIndex_EXCEPTIONS, PE_DataDirectoryIndex_CERT, PE_DataDirectoryIndex_BASE_RELOC, PE_DataDirectoryIndex_DEBUG, PE_DataDirectoryIndex_ARCH, PE_DataDirectoryIndex_GLOBAL_PTR, PE_DataDirectoryIndex_TLS, PE_DataDirectoryIndex_LOAD_CONFIG, PE_DataDirectoryIndex_BOUND_IMPORT, PE_DataDirectoryIndex_IMPORT_ADDR, PE_DataDirectoryIndex_DELAY_IMPORT, PE_DataDirectoryIndex_COM_DESCRIPTOR, PE_DataDirectoryIndex_RESERVED, PE_DataDirectoryIndex_COUNT = 16 } PE_DataDirectoryIndex; typedef struct PE_DataDirectory PE_DataDirectory; struct PE_DataDirectory { U32 virt_off; U32 virt_size; }; typedef U32 PE_DebugDirectoryType; enum { PE_DebugDirectoryType_UNKNOWN = 0, PE_DebugDirectoryType_COFF = 1, PE_DebugDirectoryType_CODEVIEW = 2, PE_DebugDirectoryType_FPO = 3, PE_DebugDirectoryType_MISC = 4, PE_DebugDirectoryType_EXCEPTION = 5, PE_DebugDirectoryType_FIXUP = 6, PE_DebugDirectoryType_OMAP_TO_SRC = 7, PE_DebugDirectoryType_OMAP_FROM_SRC = 8, PE_DebugDirectoryType_BORLAND = 9, PE_DebugDirectoryType_RESERVED10 = 10, PE_DebugDirectoryType_CLSID = 11, PE_DebugDirectoryType_VC_FEATURE = 12, PE_DebugDirectoryType_COFF_GROUP = 13, PE_DebugDirectoryType_ILTCG = 14, PE_DebugDirectoryType_MPX = 15, PE_DebugDirectoryType_REPRO = 16, PE_DebugDirectoryType_EX_DLLCHARACTERISTICS = 20, PE_DebugDirectoryType_COUNT = 18 }; typedef U8 PE_FPOFlags; enum { PE_FPOFlags_HAS_SEH = 0x800, PE_FPOFlags_USE_BP_REG = 0x1000, PE_FPOFlags_RESERVED = 0x2000, PE_FPOFlags_COUNT = 3 }; typedef U16 PE_FPOEncoded; enum { PE_FPOEncoded_PROLOG_SIZE_SHIFT = 0, PE_FPOEncoded_PROLOG_SIZE_MASK = 0xff, PE_FPOEncoded_SAVED_REGS_SIZE_SHIFT = 8, PE_FPOEncoded_SAVED_REGS_SIZE_MASK = 0x7, PE_FPOEncoded_FLAGS_SHIFT = 11, PE_FPOEncoded_FLAGS_MASK = 0x7, PE_FPOEncoded_FRAME_TYPE_SHIFT = 14, PE_FPOEncoded_FRAME_TYPE_MASK = 0x3, }; #define PE_FPOEncoded_Extract_PROLOG_SIZE(f) (U8)(((f) >> PE_FPOEncoded_PROLOG_SIZE_SHIFT) & PE_FPOEncoded_PROLOG_SIZE_MASK) #define PE_FPOEncoded_Extract_SAVED_REGS_SIZE(f) (U8)(((f) >> PE_FPOEncoded_SAVED_REGS_SIZE_SHIFT) & PE_FPOEncoded_SAVED_REGS_SIZE_MASK) #define PE_FPOEncoded_Extract_FLAGS(f) (U8)(((f) >> PE_FPOEncoded_FLAGS_SHIFT) & PE_FPOEncoded_FLAGS_MASK) #define PE_FPOEncoded_Extract_FRAME_TYPE(f) (U8)(((f) >> PE_FPOEncoded_FRAME_TYPE_SHIFT) & PE_FPOEncoded_FRAME_TYPE_MASK) typedef U8 PE_FPOType; enum { PE_FPOType_FPO = 0, PE_FPOType_TRAP = 1, PE_FPOType_TSS = 2, PE_FPOType_NOFPO = 3, PE_FPOType_COUNT = 4 }; // winnt.h: FPO_DATA typedef struct PE_DebugFPO PE_DebugFPO; struct PE_DebugFPO { U32 func_code_off; U32 func_size; U32 locals_size; U16 params_size; U16 flags; }; typedef U32 PE_DebugMiscType; enum { PE_DebugMiscType_NULL, PE_DebugMiscType_EXE_NAME, PE_DebugMiscType_COUNT = 2 }; // winnt.h: IMAGE_DEBUG_MISC typedef struct PE_DebugMisc PE_DebugMisc; struct PE_DebugMisc { PE_DebugMiscType data_type; U32 size; U8 unicode; U8 pad[3]; //char name[]; }; // winnt.h: IMAGE_COFF_SYMBOLS_HEADER typedef struct PE_DebugCoff PE_DebugCoff; struct PE_DebugCoff { U32 symbol_count; U32 lva_to_first_symbol; U32 line_number_count; U32 lva_to_first_line_number; U32 virt_off_to_first_byte_of_code; U32 virt_off_to_last_byte_of_code; U32 virt_off_to_first_byte_of_data; U32 virt_off_to_last_byte_of_data; }; typedef struct PE_DebugDirectory PE_DebugDirectory; struct PE_DebugDirectory { U32 characteristics; COFF_TimeStamp time_stamp; U16 major_ver; U16 minor_ver; PE_DebugDirectoryType type; U32 size; U32 voff; U32 foff; }; typedef U32 PE_GlobalFlags; enum { PE_GlobalFlags_STOP_ON_EXCEPTION = (1 << 0), PE_GlobalFlags_SHOW_LDR_SNAPS = (1 << 1), PE_GlobalFlags_DEBUG_INITIAL_COMMAND = (1 << 2), PE_GlobalFlags_STOP_ON_HUNG_GUI = (1 << 3), PE_GlobalFlags_HEAP_ENABLE_TAIL_CHECK = (1 << 4), PE_GlobalFlags_HEAP_ENABLE_FREE_CHECK = (1 << 5), PE_GlobalFlags_HEAP_VALIDATE_PARAMETERS = (1 << 6), PE_GlobalFlags_HEAP_VALIDATE_ALL = (1 << 7), PE_GlobalFlags_APPLICATION_VERIFIER = (1 << 8), PE_GlobalFlags_POOL_ENABLE_TAGGING = (1 << 10), PE_GlobalFlags_HEAP_ENABLE_TAGGING = (1 << 11), PE_GlobalFlags_STACK_TRACE_DB = (1 << 12), PE_GlobalFlags_KERNEL_STACK_TRACE_DB = (1 << 13), PE_GlobalFlags_MAINTAIN_OBJECT_TYPELIST = (1 << 14), PE_GlobalFlags_HEAP_ENABLE_TAG_BY_DLL = (1 << 15), PE_GlobalFlags_DISABLE_STACK_EXTENSION = (1 << 16), PE_GlobalFlags_ENABLE_CSRDEBUG = (1 << 17), PE_GlobalFlags_ENABLE_KDEBUG_SYMBOL_LOAD = (1 << 18), PE_GlobalFlags_DISABLE_PAGE_KERNEL_STACKS = (1 << 19), PE_GlobalFlags_ENABLE_SYSTEM_CRIT_BREAKS = (1 << 20), PE_GlobalFlags_HEAP_DISABLE_COALESCING = (1 << 21), PE_GlobalFlags_ENABLE_CLOSE_EXCEPTIONS = (1 << 22), PE_GlobalFlags_ENABLE_EXCEPTION_LOGGING = (1 << 23), PE_GlobalFlags_ENABLE_HANDLE_TYPE_TAGGING = (1 << 24), PE_GlobalFlags_HEAP_PAGE_ALLOCS = (1 << 25), PE_GlobalFlags_DEBUG_INITIAL_COMMAND_EX = (1 << 26), PE_GlobalFlags_DISABLE_DBGPRINT = (1 << 27), PE_GlobalFlags_CRITSEC_EVENT_CREATION = (1 << 28), PE_GlobalFlags_LDR_TOP_DOWN = (1 << 29), PE_GlobalFlags_ENABLE_HANDLE_EXCEPTIONS = (1 << 30), PE_GlobalFlags_DISABLE_PROTDLLS = (1 << 31), }; typedef U32 PE_LoadConfigGuardFlags; enum { PE_LoadConfigGuardFlags_CF_INSTRUMENTED = (1 << 8), PE_LoadConfigGuardFlags_CFW_INSTRUMENTED = (1 << 9), PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_PRESENT = (1 << 10), PE_LoadConfigGuardFlags_SECURITY_COOKIE_UNUSED = (1 << 11), PE_LoadConfigGuardFlags_PROTECT_DELAYLOAD_IAT = (1 << 12), PE_LoadConfigGuardFlags_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = (1 << 13), PE_LoadConfigGuardFlags_CF_EXPORT_SUPPRESSION_INFO_PRESENT = (1 << 14), PE_LoadConfigGuardFlags_CF_ENABLE_EXPORT_SUPPRESSION = (1 << 15), PE_LoadConfigGuardFlags_CF_LONGJUMP_TABLE_PRESENT = (1 << 16), PE_LoadConfigGuardFlags_EH_CONTINUATION_TABLE_PRESENT = (1 << 22), PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_SHIFT = 28, PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_MASK = 0xf, }; #define PE_LoadConfigGuardFlags_Extract_CF_FUNCTION_TABLE_SIZE(f) (U32)(((f) >> PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_SHIFT) & PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_MASK) typedef struct PE_LoadConfigCodeIntegrity PE_LoadConfigCodeIntegrity; struct PE_LoadConfigCodeIntegrity { U16 flags; U16 catalog; U32 catalog_offset; U32 reserved; }; typedef struct PE_LoadConfig32 PE_LoadConfig32; struct PE_LoadConfig32 { U32 size; COFF_TimeStamp time_stamp; U16 major_version; U16 minor_version; U32 global_flag_clear; U32 global_flag_set; U32 critical_section_timeout; U32 decommit_free_block_threshold; U32 decommit_total_free_threshold; U32 lock_prefix_table; U32 maximum_allocation_size; U32 virtual_memory_threshold; U32 process_affinity_mask; U32 process_heap_flags; U16 csd_version; U16 reserved; U32 edit_list; U32 security_cookie; U32 seh_handler_table; U32 seh_handler_count; // msvc 2015 U32 guard_cf_check_func_ptr; U32 guard_cf_dispatch_func_ptr; U32 guard_cf_func_table; U32 guard_cf_func_count; U32 guard_flags; // msvc 2017 PE_LoadConfigCodeIntegrity code_integrity; U32 guard_address_taken_iat_entry_table; U32 guard_address_taken_iat_entry_count; U32 guard_long_jump_target_table; U32 guard_long_jump_target_count; U32 dynamic_value_reloc_table; U32 chpe_metadata_ptr; U32 guard_rf_failure_routine; U32 guard_rf_failure_routine_func_ptr; U32 dynamic_value_reloc_table_offset; U16 dynamic_value_reloc_table_section; U16 reserved2; U32 guard_rf_verify_stack_pointer_func_ptr; U32 hot_patch_table_offset; // msvc 2019 U32 reserved3; U32 enclave_config_ptr; U32 volatile_metadata_ptr; U32 guard_eh_continue_table; U32 guard_eh_continue_count; U32 guard_xfg_check_func_ptr; U32 guard_xfg_dispatch_func_ptr; U32 guard_xfg_table_dispatch_func_ptr; U32 cast_guard_os_determined_failure_mode; }; typedef struct PE_LoadConfig64 PE_LoadConfig64; struct PE_LoadConfig64 { U32 size; COFF_TimeStamp time_stamp; U16 major_version; U16 minor_version; U32 global_flag_clear; U32 global_flag_set; U32 critical_section_timeout; U64 decommit_free_block_threshold; U64 decommit_total_free_threshold; U64 lock_prefix_table; U64 maximum_allocation_size; U64 virtual_memory_threshold; U64 process_affinity_mask; U32 process_heap_flags; U16 csd_version; U16 reserved; U64 edit_list; U64 security_cookie; U64 seh_handler_table; U64 seh_handler_count; // msvc 2015 U64 guard_cf_check_func_ptr; U64 guard_cf_dispatch_func_ptr; U64 guard_cf_func_table; U64 guard_cf_func_count; U32 guard_flags; // msvc 2017 PE_LoadConfigCodeIntegrity code_integrity; U64 guard_address_taken_iat_entry_table; U64 guard_address_taken_iat_entry_count; U64 guard_long_jump_target_table; U64 guard_long_jump_target_count; U64 dynamic_value_reloc_table; U64 chpe_metadata_ptr; U64 guard_rf_failure_routine; U64 guard_rf_failure_routine_func_ptr; U32 dynamic_value_reloc_table_offset; U16 dynamic_value_reloc_table_section; U16 reserved2; U64 guard_rf_verify_stack_pointer_func_ptr; U32 hot_patch_table_offset; // msvc 2019 U32 reserved3; U64 enclave_config_ptr; U64 volatile_metadata_ptr; U64 guard_eh_continue_table; U64 guard_eh_continue_count; U64 guard_xfg_check_func_ptr; U64 guard_xfg_dispatch_func_ptr; U64 guard_xfg_table_dispatch_func_ptr; U64 cast_guard_os_determined_failure_mode; }; // this is the "MZ" as a 16-bit short #define PE_DOS_MAGIC 0x5a4d #define PE_MAGIC 0x00004550u #define PE_PE32_MAGIC 0x010bu #define PE_PE32PLUS_MAGIC 0x020bu typedef U16 PE_DosMagic; typedef struct PE_MipsPdata PE_MipsPdata; struct PE_MipsPdata { U32 voff_first; U32 voff_one_past_last; U32 voff_exception_handler; U32 voff_exception_handler_data; U32 voff_one_past_prolog; }; typedef struct PE_ArmPdata PE_ArmPdata; struct PE_ArmPdata { U32 voff_first; // NOTE(allen): // bits | meaning // [0:7] | prolog length // [8:29] | function length // [30:30] | instructions_are_32bits (otherwise they are 16 bits) // [31:31] | has_exception_handler U32 combined; }; typedef struct PE_IntelPdata PE_IntelPdata; struct PE_IntelPdata { U32 voff_first; U32 voff_one_past_last; U32 voff_unwind_info; }; #define PE_CODEVIEW_PDB20_MAGIC 0x3031424e #define PE_CODEVIEW_PDB70_MAGIC 0x53445352 #define PE_CODEVIEW_RDI_MAGIC '0IDR' typedef struct PE_CvHeaderPDB20 PE_CvHeaderPDB20; struct PE_CvHeaderPDB20 { U32 magic; U32 offset; COFF_TimeStamp time_stamp; U32 age; // file name packed after struct }; typedef struct PE_CvHeaderPDB70 PE_CvHeaderPDB70; struct PE_CvHeaderPDB70 { U32 magic; Guid guid; U32 age; // file name packed after struct }; typedef struct PE_CvHeaderRDI PE_CvHeaderRDI; struct PE_CvHeaderRDI { U32 magic; Guid guid; // file name packed after struct }; typedef struct PE_ImportEntry PE_ImportEntry; struct PE_ImportEntry { U32 lookup_table_voff; COFF_TimeStamp time_stamp; U32 forwarder_chain; U32 name_voff; U32 import_addr_table_voff; }; typedef struct PE_DelayedImportEntry PE_DelayedImportEntry; struct PE_DelayedImportEntry { // According to COFF/PE spec this field is unused and should be set zero, // but when I compile mule with MSVC 2019 this is set to 1. U32 attributes; U32 name_voff; // Name of the DLL U32 module_handle_voff; // Place where module handle from LoadLibrary is stored U32 iat_voff; U32 name_table_voff; // Array of hint/name or oridnals U32 bound_table_voff; // (Optional) Points to an array of PE_ThunkData U32 unload_table_voff; // (Optional) Copy of iat_voff // 0 not bound // -1 if bound and real timestamp located in bounded import directory // Otherwise time when dll was bound COFF_TimeStamp time_stamp; }; typedef struct PE_ExportTableHeader PE_ExportTableHeader; struct PE_ExportTableHeader { U32 flags; // must be zero COFF_TimeStamp time_stamp; // time and date when export table was created U16 major_ver; // table version, user can change major and minor version U16 minor_ver; U32 name_voff; // ASCII name of the dll U32 ordinal_base; // Starting oridnal number U32 export_address_table_count; U32 name_pointer_table_count; U32 export_address_table_voff; U32 name_pointer_table_voff; U32 ordinal_table_voff; }; typedef struct PE_TLSHeader32 PE_TLSHeader32; struct PE_TLSHeader32 { U32 raw_data_start; // Range of initialized data that is copied for each thread from the image. U32 raw_data_end; // (Typically points to .tls section) U32 index_address; // Address where image loader places TLS slot index. U32 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors. U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS. COFF_SectionFlags characteristics; // COFF_SectionFlags but only align flags are used. }; typedef struct PE_TLSHeader64 PE_TLSHeader64; struct PE_TLSHeader64 { U64 raw_data_start; // Range of initialized data that is copied for each thread from the image. U64 raw_data_end; // (Typically points to .tls section) U64 index_address; // Address where image loader places TLS slot index. U64 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors. U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS. COFF_SectionFlags characteristics; // COFF_SectionFlags but only align flags are used. }; global read_only U8 PE_RES_MAGIC[] = { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; typedef U32 PE_ResourceKind; enum { PE_ResourceKind_CURSOR = 0x1, PE_ResourceKind_BITMAP = 0x2, PE_ResourceKind_ICON = 0x3, PE_ResourceKind_MENU = 0x4, PE_ResourceKind_DIALOG = 0x5, PE_ResourceKind_STRING = 0x6, PE_ResourceKind_FONTDIR = 0x7, PE_ResourceKind_FONT = 0x8, PE_ResourceKind_ACCELERATOR = 0x9, PE_ResourceKind_RCDATA = 0xA, PE_ResourceKind_MESSAGETABLE = 0xB, PE_ResourceKind_GROUP_CURSOR = 0xC, PE_ResourceKind_GROUP_ICON = 0xE, PE_ResourceKind_VERSION = 0x10, PE_ResourceKind_DLGINCLUDE = 0x11, PE_ResourceKind_PLUGPLAY = 0x13, PE_ResourceKind_VXD = 0x14, PE_ResourceKind_ANICURSOR = 0x15, PE_ResourceKind_ANIICON = 0x16, PE_ResourceKind_HTML = 0x17, PE_ResourceKind_MANIFEST = 0x18, PE_ResourceKind_BITMAP_NEW = 0x2002, PE_ResourceKind_MENU_NEW = 0x2004, PE_ResourceKind_DIALOG_NEW = 0x2005, }; typedef enum PE_ResDataKind { PE_ResDataKind_NULL, PE_ResDataKind_DIR, PE_ResDataKind_COFF_LEAF, PE_ResDataKind_COFF_RESOURCE, } PE_ResDataKind; typedef struct PE_ResourceHeader PE_ResourceHeader; struct PE_ResourceHeader { COFF_ResourceHeaderPrefix prefix; U16 type; U16 pad0; U16 name; U16 pad1; U32 data_version; COFF_ResourceMemoryFlags memory_flags; U16 language_id; U32 version; U32 characteristics; }; typedef U16 PE_BaseRelocKind; enum { PE_BaseRelocKind_ABSOLUTE = 0, // No reallocation is applied. Can be used as padding. PE_BaseRelocKind_HIGH = 1, PE_BaseRelocKind_LOW = 2, PE_BaseRelocKind_HIGHLOW = 3, PE_BaseRelocKind_HIGHADJ = 4, PE_BaseRelocKind_MIPS_JMPADDR = 5, PE_BaseRelocKind_ARM_MOV32 = 5, PE_BaseRelocKind_RISCV_HIGH20 = 5, // 6 is reserved PE_BaseRelocKind_THUMB_MOV32 = 7, PE_BaseRelocKind_RISCV_LOW12I = 7, PE_BaseRelocKind_RISCV_LOW12S = 8, PE_BaseRelocKind_LOONGARCH32_MARK_LA = 8, PE_BaseRelocKind_LOONGARCH64_MARK_LA = 8, PE_BaseRelocKind_MIPS_JMPADDR16 = 9, PE_BaseRelocKind_DIR64 = 10, }; #define PE_BaseRelocOffsetFromEntry(x) ((x) & 0x1fff) #define PE_BaseRelocKindFromEntry(x) (((x) >> 12) & 0xf) #define PE_BaseRelocMake(k, off) ((((U16)(k) & 0xf) << 12) | (U16)((off) & 0x1fff)) typedef U32 PE_UnwindOpCode; enum { PE_UnwindOpCode_PUSH_NONVOL = 0, PE_UnwindOpCode_ALLOC_LARGE = 1, PE_UnwindOpCode_ALLOC_SMALL = 2, PE_UnwindOpCode_SET_FPREG = 3, PE_UnwindOpCode_SAVE_NONVOL = 4, PE_UnwindOpCode_SAVE_NONVOL_FAR = 5, PE_UnwindOpCode_EPILOG = 6, PE_UnwindOpCode_SPARE_CODE = 7, PE_UnwindOpCode_SAVE_XMM128 = 8, PE_UnwindOpCode_SAVE_XMM128_FAR = 9, PE_UnwindOpCode_PUSH_MACHFRAME = 10, }; typedef U8 PE_UnwindGprRegX64; enum { PE_UnwindGprRegX64_RAX = 0, PE_UnwindGprRegX64_RCX = 1, PE_UnwindGprRegX64_RDX = 2, PE_UnwindGprRegX64_RBX = 3, PE_UnwindGprRegX64_RSP = 4, PE_UnwindGprRegX64_RBP = 5, PE_UnwindGprRegX64_RSI = 6, PE_UnwindGprRegX64_RDI = 7, PE_UnwindGprRegX64_R8 = 8, PE_UnwindGprRegX64_R9 = 9, PE_UnwindGprRegX64_R10 = 10, PE_UnwindGprRegX64_R11 = 11, PE_UnwindGprRegX64_R12 = 12, PE_UnwindGprRegX64_R13 = 13, PE_UnwindGprRegX64_R14 = 14, PE_UnwindGprRegX64_R15 = 15, }; typedef U8 PE_UnwindInfoFlags; enum { PE_UnwindInfoFlag_EHANDLER = (1<<0), PE_UnwindInfoFlag_UHANDLER = (1<<1), PE_UnwindInfoFlag_FHANDLER = 3, PE_UnwindInfoFlag_CHAINED = (1<<2), }; #define PE_UNWIND_OPCODE_FROM_FLAGS(f) ((f)&0xF) #define PE_UNWIND_INFO_FROM_FLAGS(f) (((f) >> 4)&0xF) typedef union PE_UnwindCode PE_UnwindCode; union PE_UnwindCode { struct { U8 off_in_prolog; U8 flags; }; U16 u16; }; #define PE_UNWIND_INFO_VERSION_FROM_HDR(x) ((x)&0x7) #define PE_UNWIND_INFO_FLAGS_FROM_HDR(x) (((x) >> 3)&0x1F) #define PE_UNWIND_INFO_REG_FROM_FRAME(x) ((x)&0xF) #define PE_UNWIND_INFO_OFF_FROM_FRAME(x) (((x) >> 4)&0xF) #define PE_UNWIND_INFO_GET_CODE_COUNT(x) (((x)+1) & ~1) typedef struct PE_UnwindInfo PE_UnwindInfo; struct PE_UnwindInfo { U8 header; U8 prolog_size; U8 codes_num; U8 frame; }; #pragma pack(pop) //////////////////////////////// //~ rjf: DOS Program // generated from pe/dos_program.asm read_only global U8 pe_dos_program_data[] = { 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x24, 0x00, 0x00 }; read_only global String8 pe_dos_program = {pe_dos_program_data, sizeof(pe_dos_program_data)}; //////////////////////////////// //~ rjf: Parsed Info Types //- rjf: relocation blocks typedef struct PE_BaseRelocBlock PE_BaseRelocBlock; struct PE_BaseRelocBlock { U64 page_virt_off; U64 entry_count; U16 *entries; }; typedef struct PE_BaseRelocBlockNode PE_BaseRelocBlockNode; struct PE_BaseRelocBlockNode { PE_BaseRelocBlockNode *next; PE_BaseRelocBlock v; }; typedef struct PE_BaseRelocBlockList PE_BaseRelocBlockList; struct PE_BaseRelocBlockList { PE_BaseRelocBlockNode *first; PE_BaseRelocBlockNode *last; U64 count; }; //- rjf: resources typedef struct PE_Resource PE_Resource; struct PE_Resource { COFF_ResourceID id; PE_ResDataKind kind; union { COFF_ResourceDataEntry leaf; struct PE_ResourceDir *dir; struct { COFF_ResourceID type; U32 data_version; U32 version; COFF_ResourceMemoryFlags memory_flags; String8 data; } coff_res; } u; }; typedef struct PE_ResourceNode PE_ResourceNode; struct PE_ResourceNode { PE_ResourceNode *next; PE_Resource data; }; typedef struct PE_ResourceList PE_ResourceList; struct PE_ResourceList { PE_ResourceNode *first; PE_ResourceNode *last; U64 count; }; typedef struct PE_ResourceArray PE_ResourceArray; struct PE_ResourceArray { PE_Resource *v; U64 count; }; typedef struct PE_ResourceDir PE_ResourceDir; struct PE_ResourceDir { U32 characteristics; COFF_TimeStamp time_stamp; U16 major_version; U16 minor_version; PE_ResourceList named_list; PE_ResourceList id_list; }; //- exports & imports typedef struct PE_ParsedExport PE_ParsedExport; struct PE_ParsedExport { String8 forwarder; String8 name; U64 voff; U64 ordinal; }; typedef struct PE_ParsedExportTable PE_ParsedExportTable; struct PE_ParsedExportTable { U32 flags; COFF_TimeStamp time_stamp; U16 major_ver; U16 minor_ver; U64 ordinal_base; U64 export_count; PE_ParsedExport *exports; }; typedef U32 PE_ParsedImportType; enum PE_ParsedImportTypeEnum { PE_ParsedImport_Null, PE_ParsedImport_Ordinal, PE_ParsedImport_Name, }; typedef struct PE_ParsedImport PE_ParsedImport; struct PE_ParsedImport { PE_ParsedImportType type; union { U16 ordinal; struct { U64 hint; String8 string; } name; } u; }; typedef struct PE_ParsedStaticDLLImport PE_ParsedStaticDLLImport; struct PE_ParsedStaticDLLImport { String8 name; U64 import_address_table_voff; U64 import_name_table_voff; COFF_TimeStamp time_stamp; U64 forwarder_chain; U64 import_count; PE_ParsedImport *imports; }; typedef struct PE_ParsedStaticImportTable PE_ParsedStaticImportTable; struct PE_ParsedStaticImportTable { U64 count; PE_ParsedStaticDLLImport *v; }; typedef struct PE_ParsedDelayDLLImport PE_ParsedDelayDLLImport; struct PE_ParsedDelayDLLImport { U32 attributes; String8 name; U64 module_handle_voff; U64 iat_voff; U64 name_table_voff; U64 bound_table_voff; U64 unload_table_voff; COFF_TimeStamp time_stamp; U64 bound_table_count; U64 *bound_table; U64 unload_table_count; U64 *unload_table; U64 import_count; PE_ParsedImport *imports; }; typedef struct PE_ParsedDelayImportTable PE_ParsedDelayImportTable; struct PE_ParsedDelayImportTable { U64 count; PE_ParsedDelayDLLImport *v; }; typedef struct PE_ParsedTLS PE_ParsedTLS; struct PE_ParsedTLS { PE_TLSHeader64 header; U64 callback_count; U64 *callback_addrs; }; //////////////////////////////// // SEH Scope Table typedef struct PE_HandlerScope PE_HandlerScope; struct PE_HandlerScope { U32 begin; U32 end; U32 handler; U32 target; }; //- rjf: bundle typedef struct PE_BinInfo PE_BinInfo; struct PE_BinInfo { Arch arch; U64 image_base; U64 entry_point; B32 is_pe32; PE_WindowsSubsystem subsystem; U32 *check_sum; U64 virt_section_align; U64 file_section_align; U64 section_count; U64 symbol_count; U64 optional_header_off; Rng1U64 section_table_range; Rng1U64 symbol_table_range; Rng1U64 string_table_range; Rng1U64 data_dir_range; Rng1U64 *data_dir_franges; Rng1U64 *data_dir_vranges; U32 data_dir_count; PE_TLSHeader64 tls_header; }; typedef struct PE_DebugInfo { PE_DebugDirectory header; U32 cv_magic; PE_CvHeaderPDB20 cv_pdb20_header; PE_CvHeaderPDB70 cv_pdb70_header; PE_CvHeaderRDI cv_rdi_header; String8 path; } PE_DebugInfo; typedef struct PE_DebugInfoNode { struct PE_DebugInfoNode *next; PE_DebugInfo v; } PE_DebugInfoNode; typedef struct PE_DebugInfoList { PE_DebugInfoNode *first; PE_DebugInfoNode *last; U64 count; } PE_DebugInfoList; //////////////////////////////// //~ rjf: Basic Enum Functions internal U32 pe_slot_count_from_unwind_op_code(PE_UnwindOpCode opcode); internal PE_WindowsSubsystem pe_subsystem_from_string(String8 string); internal String8 pe_string_from_subsystem(PE_WindowsSubsystem x); internal String8 pe_string_from_unwind_gpr_x64(PE_UnwindGprRegX64 x); internal String8 pe_string_from_data_directory_index(PE_DataDirectoryIndex x); internal String8 pe_string_from_debug_directory_type(PE_DebugDirectoryType x); internal String8 pe_string_from_fpo_type(PE_FPOType x); internal String8 pe_string_from_misc_type(PE_DebugMiscType x); internal String8 pe_resource_kind_to_string(PE_ResourceKind x); internal String8 pe_string_from_fpo_flags(Arena *arena, PE_FPOFlags flags); internal String8 pe_string_from_global_flags(Arena *arena, PE_GlobalFlags flags); internal String8 pe_string_from_load_config_guard_flags(Arena *arena, PE_LoadConfigGuardFlags flags); internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacteristics dll_chars); //////////////////////////////// //~ rjf: Parser Functions internal B32 pe_check_magic(String8 data); internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data); internal PE_DataDirectory * pe_data_directory_from_idx(String8 file_data, PE_BinInfo pe, PE_DataDirectoryIndex dir_idx); internal PE_DebugInfoList pe_parse_debug_directory(Arena *arena, String8 raw_image, String8 raw_debug_dir); internal PE_DebugInfoList pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir); internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range); internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range); internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range); internal PE_ParsedTLS pe_tls_from_data(Arena *arena, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 tls_frange); //////////////////////////////// //~ rjf: Helpers internal U64 pe_pdata_off_from_voff__binary_search_x8664(String8 raw_data, U64 voff); internal U64 pe_foff_from_voff(String8 data, PE_BinInfo *bin, U64 voff); internal PE_BaseRelocBlockList pe_base_reloc_block_list_from_data(Arena *arena, String8 raw_relocs); internal Rng1U64 pe_tls_rng_from_bin_base_vaddr(String8 data, PE_BinInfo *bin, U64 base_vaddr); internal String8Array pe_get_entry_point_names(COFF_MachineType machine, PE_WindowsSubsystem subsystem, PE_ImageFileCharacteristics file_characteristics); //////////////////////////////// //~ Resource Helpers internal B32 pe_is_res(String8 data); internal void pe_resource_dir_push_res_file(Arena *arena, PE_ResourceDir *root_dir, String8 res_file); internal PE_ResourceNode * pe_resource_dir_push_dir_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, U32 characteristics, COFF_TimeStamp time_stamp, U16 major_version, U16 minor_version); internal PE_ResourceNode * pe_resource_dir_push_entry_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, COFF_ResourceID type, U32 data_version, U32 version, COFF_ResourceMemoryFlags memory_flags, String8 data); internal PE_Resource * pe_resource_dir_push_entry(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, COFF_ResourceID type, U32 data_version, U32 version, COFF_ResourceMemoryFlags memory_flags, String8 data); internal PE_Resource * pe_resource_dir_push_dir(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID id, U32 characteristics, COFF_TimeStamp time_stamp, U16 major_version, U16 minor_version); internal PE_ResourceNode * pe_resource_dir_search_node(PE_ResourceDir *dir, COFF_ResourceID id); internal PE_Resource * pe_resource_dir_search(PE_ResourceDir *dir, COFF_ResourceID id); internal PE_ResourceArray pe_resource_list_to_array(Arena *arena, PE_ResourceList *list); internal PE_ResourceDir * pe_resource_table_from_directory_data(Arena *arena, String8 data); internal String8 pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data); //////////////////////////////// //~ Debug Directory internal String8 pe_make_debug_header_pdb70(Arena *arena, Guid guid, U32 age, String8 pdb_path); internal String8 pe_make_debug_header_rdi(Arena *arena, Guid guid, String8 rdi_path); //////////////////////////////// //~ Image Checksum internal U32 pe_compute_checksum(U8 *buffer, U64 buffer_size); //////////////////////////////// internal void pe_pdata_sort(COFF_MachineType machine, String8 raw_pdata); #endif // PE_H ================================================ FILE: src/pe/pe_make_debug_dir.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 pe_make_debug_directory_pdb_obj(Arena *arena, COFF_MachineType machine, Guid guid, U32 age, COFF_TimeStamp time_stamp, String8 path) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine); String8 debug_data = pe_make_debug_header_pdb70(obj_writer->arena, guid, age, path); COFF_ObjSection *debug_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINK_PE_DEBUG_DATA"), PE_DEBUG_DIR_SECTION_FLAGS, debug_data); COFF_ObjSymbol *debug_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("PDB_DEBUG_HEADER_70"), 0, debug_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINK_PE_DEBUG_PDB"), 0, debug_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINK_PE_DEBUG_GUID_PDB"), OffsetOf(PE_CvHeaderPDB70, guid), debug_sect); PE_DebugDirectory *dir = push_array(obj_writer->arena, PE_DebugDirectory, 1); dir->time_stamp = time_stamp; dir->type = PE_DebugDirectoryType_CODEVIEW; dir->size = debug_data.size; COFF_ObjSection *debug_dir_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINK_PE_DEBUG_DIR"), PE_DEBUG_DIR_SECTION_FLAGS, str8_struct(dir)); coff_obj_writer_section_push_reloc_voff(obj_writer, debug_dir_sect, OffsetOf(PE_DebugDirectory, voff), debug_symbol); String8 obj = coff_obj_writer_serialize(arena, obj_writer); return obj; } internal String8 pe_make_debug_directory_rdi_obj(Arena *arena, COFF_MachineType machine, Guid guid, U32 age, COFF_TimeStamp time_stamp, String8 path) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine); String8 debug_data = pe_make_debug_header_rdi(obj_writer->arena, guid, path); COFF_ObjSection *debug_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINK_PE_DEBUG_DATA"), PE_DEBUG_DIR_SECTION_FLAGS, debug_data); COFF_ObjSymbol *debug_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("PDB_DEBUG_HEADER_RDI"), 0, debug_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINK_PE_DEBUG_RDI"), 0, debug_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINK_PE_DEBUG_GUID_RDI"), OffsetOf(PE_CvHeaderRDI, guid), debug_sect); PE_DebugDirectory *dir = push_array(obj_writer->arena, PE_DebugDirectory, 1); dir->time_stamp = time_stamp; dir->type = PE_DebugDirectoryType_CODEVIEW; dir->size = debug_data.size; COFF_ObjSection *dir_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINK_PE_DEBUG_DIR"), PE_DEBUG_DIR_SECTION_FLAGS, str8_struct(dir)); coff_obj_writer_section_push_reloc_voff(obj_writer, dir_sect, OffsetOf(PE_DebugDirectory, voff), debug_symbol); String8 obj = coff_obj_writer_serialize(arena, obj_writer); return obj; } ================================================ FILE: src/pe/pe_make_debug_dir.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_MAKE_DEBUG_DIR_H #define PE_MAKE_DEBUG_DIR_H internal String8 pe_make_debug_directory_pdb_obj(Arena *arena, COFF_MachineType machine, Guid guid, U32 age, COFF_TimeStamp time_stamp, String8 path); internal String8 pe_make_debug_directory_rdi_obj(Arena *arena, COFF_MachineType machine, Guid guid, U32 age, COFF_TimeStamp time_stamp, String8 path); #endif // PE_MAKE_DEBUG_DIR_H ================================================ FILE: src/pe/pe_make_export_table.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 pe_name_from_export_parse(PE_ExportParse *exp) { String8 name; if (exp->is_forwarder) { name = exp->alias; } else if (exp->alias.size) { name = exp->alias; } else { name = exp->name; } return name; } internal U16 pe_hint_or_ordinal_from_export_parse(PE_ExportParse *exp) { U16 hint_or_ordinal = max_U16; if (exp->import_by == COFF_ImportBy_Ordinal) { hint_or_ordinal = exp->ordinal; } else if (exp->import_by == COFF_ImportBy_Name) { hint_or_ordinal = exp->hint; } else { NotImplemented; } return hint_or_ordinal; } internal PE_ExportParsePtrArray pe_array_from_export_list(Arena *arena, PE_ExportParseList list) { PE_ExportParsePtrArray result = {0}; result.v = push_array_no_zero(arena, PE_ExportParse *, list.count); for (PE_ExportParseNode *exp = list.first; exp != 0; exp = exp->next) { result.v[result.count++] = &exp->data; } return result; } internal void pe_export_parse_list_push_node(PE_ExportParseList *list, PE_ExportParseNode *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal PE_ExportParseNode * pe_export_parse_list_push(Arena *arena, PE_ExportParseList *list, PE_ExportParse data) { PE_ExportParseNode *node = push_array(arena, PE_ExportParseNode, 1); node->data = data; pe_export_parse_list_push_node(list, node); return node; } internal void pe_export_parse_list_concat_in_place(PE_ExportParseList *list, PE_ExportParseList *to_concat) { if (to_concat->count) { if (list->count) { list->last->next = to_concat->first; list->last = to_concat->last; } else { list->first = to_concat->first; list->last = to_concat->last; } list->count += to_concat->count; MemoryZeroStruct(to_concat); } } internal int pe_named_export_is_before(void *raw_a, void *raw_b) { PE_ExportParse *a = *(PE_ExportParse **)raw_a; PE_ExportParse *b = *(PE_ExportParse **)raw_b; int cmp = str8_compar_case_sensitive(&a->name, &b->name); return cmp < 0; } internal int pe_ordinal_export_is_before(void *raw_a, void *raw_b) { PE_ExportParse *a = raw_a; PE_ExportParse *b = raw_b; return a->ordinal < b->ordinal; } internal PE_FinalizedExports pe_finalize_export_list(Arena *arena, PE_ExportParseList export_list) { PE_ExportParsePtrArray named_exports = {0}; PE_ExportParsePtrArray ordinal_exports = {0}; PE_ExportParsePtrArray forwarder_exports = {0}; { // group exports based on flags PE_ExportParseList named_exports_list = {0}; PE_ExportParseList ordinal_exports_list = {0}; PE_ExportParseList forwarder_exports_list = {0}; for (PE_ExportParseNode *exp_n = export_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) { exp_n_next = exp_n->next; if (exp_n->data.is_forwarder) { pe_export_parse_list_push_node(&forwarder_exports_list, exp_n); } else if (exp_n->data.is_noname_present) { AssertAlways(exp_n->data.is_ordinal_assigned); pe_export_parse_list_push_node(&ordinal_exports_list, exp_n); } else { pe_export_parse_list_push_node(&named_exports_list, exp_n); } } // list -> array named_exports = pe_array_from_export_list(arena, named_exports_list); forwarder_exports = pe_array_from_export_list(arena, forwarder_exports_list); ordinal_exports = pe_array_from_export_list(arena, ordinal_exports_list); // sort exports radsort(named_exports.v, named_exports.count, pe_named_export_is_before); radsort(ordinal_exports.v, ordinal_exports.count, pe_ordinal_export_is_before); radsort(forwarder_exports.v, forwarder_exports.count, pe_named_export_is_before); MemoryZeroStruct(&export_list); pe_export_parse_list_concat_in_place(&export_list, &named_exports_list); pe_export_parse_list_concat_in_place(&export_list, &forwarder_exports_list); pe_export_parse_list_concat_in_place(&export_list, &ordinal_exports_list); } // compute max ordinal and used ordinal flag array U64 ordinal_low = max_U64; B8 *is_ordinal_used = push_array(arena, B8, max_U16); for (PE_ExportParseNode *exp_n = export_list.first; exp_n != 0; exp_n = exp_n->next) { PE_ExportParse *exp = &exp_n->data; if (exp->is_ordinal_assigned) { ordinal_low = Min(ordinal_low, exp->ordinal); is_ordinal_used[exp->ordinal] = 1; } } if (ordinal_low == max_U64) { ordinal_low = 1; } // assign omitted ordinals { U16 last_ordinal = ordinal_low; for (U64 exp_idx = 0; exp_idx < named_exports.count; exp_idx += 1) { PE_ExportParse *exp = named_exports.v[exp_idx]; if (!exp->is_ordinal_assigned) { for (; last_ordinal < max_U16 && is_ordinal_used[last_ordinal] != 0; last_ordinal += 1); exp->ordinal = last_ordinal; exp->is_ordinal_assigned = 1; is_ordinal_used[last_ordinal] = 1; } } for (U64 exp_idx = 0; exp_idx < forwarder_exports.count; exp_idx += 1) { PE_ExportParse *exp = forwarder_exports.v[exp_idx]; if (!exp->is_ordinal_assigned) { for (; last_ordinal < max_U16 && is_ordinal_used[last_ordinal] != 0; last_ordinal += 1); exp->ordinal = last_ordinal; exp->is_ordinal_assigned = 1; is_ordinal_used[last_ordinal] = 1; } } for (U64 exp_idx = 0; exp_idx < ordinal_exports.count; exp_idx += 1) { PE_ExportParse *exp = ordinal_exports.v[exp_idx]; if (!exp->is_ordinal_assigned) { exp->ordinal = last_ordinal; exp->is_ordinal_assigned = 1; is_ordinal_used[last_ordinal] = 1; } } } // assign hints { U64 hint = 0; for (U64 exp_idx = 0; exp_idx < named_exports.count; exp_idx += 1, hint += 1) { named_exports.v[exp_idx]->hint = hint; } for (U64 exp_idx = 0; exp_idx < forwarder_exports.count; exp_idx += 1, hint += 1) { forwarder_exports.v[exp_idx]->hint = hint; } } PE_FinalizedExports result = {0}; result.ordinal_low = ordinal_low; result.named_exports = named_exports; result.forwarder_exports = forwarder_exports; result.ordinal_exports = ordinal_exports; return result; } internal String8 pe_make_edata_obj(Arena *arena, String8 image_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, PE_FinalizedExports finalized_exports) { Temp scratch = scratch_begin(&arena, 1); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); // push sections COFF_ObjSection *voff_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$2"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_zero()); COFF_ObjSection *name_voff_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$3"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_zero()); COFF_ObjSection *ordinal_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$4"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero()); COFF_ObjSection *string_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$5"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero()); COFF_ObjSection *image_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$6"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, push_cstr(obj_writer->arena, image_name)); ProfBegin("Virtual Offset Table"); { B8 *is_ordinal_bound = push_array(scratch.arena, B8, max_U16); for (U64 arr_idx = 0; arr_idx < ArrayCount(finalized_exports.all); arr_idx += 1) { for (U64 exp_idx = 0; exp_idx < finalized_exports.all[arr_idx].count; exp_idx += 1) { PE_ExportParse *exp = finalized_exports.all[arr_idx].v[exp_idx]; if (is_ordinal_bound[exp->ordinal] == 0) { // alloc only one slot per ordinal, so it's possible to map ordinal to a virtual offset is_ordinal_bound[exp->ordinal] = 1; // create slot for the ordinal virtual offset U64 voff_offset = voff_table_sect->data.total_size; U32 *voff = push_array(obj_writer->arena, U32, 1); str8_list_push(obj_writer->arena, &voff_table_sect->data, str8_struct(voff)); COFF_ObjSymbol *exp_symbol; if (exp->is_forwarder) { U64 forwarder_name_offset = string_table_sect->data.total_size; String8 forwarder_name_cstr = push_cstr(obj_writer->arena, exp->name); str8_list_push(obj_writer->arena, &string_table_sect->data, forwarder_name_cstr); // symbol to the name string exp_symbol = coff_obj_writer_push_symbol_static(obj_writer, exp->name, forwarder_name_offset, string_table_sect); } else { // function or global var symbol exp_symbol = coff_obj_writer_push_symbol_undef(obj_writer, exp->name); } U16 ordinal_nb = exp->ordinal - finalized_exports.ordinal_low; coff_obj_writer_section_push_reloc_voff(obj_writer, voff_table_sect, ordinal_nb*sizeof(U32), exp_symbol); } } } } ProfEnd(); ProfBegin("Named & Forwarder Exports"); { for (U64 arr_idx = 0; arr_idx < ArrayCount(finalized_exports.exports_with_names); arr_idx += 1) { PE_ExportParsePtrArray exports = finalized_exports.exports_with_names[arr_idx]; for (U64 exp_idx = 0; exp_idx < exports.count; exp_idx += 1) { PE_ExportParse *exp = exports.v[exp_idx]; String8 name = pe_name_from_export_parse(exp); // store symbol name string U64 export_name_offset = string_table_sect->data.total_size; String8 export_name_cstr = push_cstr(obj_writer->arena, name); str8_list_push(obj_writer->arena, &string_table_sect->data, export_name_cstr); // create symbol for the name string String8 export_name_symbol_name = push_str8f(obj_writer->arena, "%S", name); COFF_ObjSymbol *export_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, export_name_symbol_name, export_name_offset, string_table_sect); // create slot for export virtual offset U64 export_name_voff_offset = name_voff_table_sect->data.total_size; U8 *export_name_voff = push_array(obj_writer->arena, U8, sizeof(U32)); str8_list_push(obj_writer->arena, &name_voff_table_sect->data, str8_array(export_name_voff, sizeof(U32))); // write string's virtual offset coff_obj_writer_section_push_reloc_voff(obj_writer, name_voff_table_sect, export_name_voff_offset, export_name_symbol); // create and store export's ordinal U16 *ordinal = push_array(obj_writer->arena, U16, 1); *ordinal = exp->ordinal - finalized_exports.ordinal_low; str8_list_push(obj_writer->arena, &ordinal_table_sect->data, str8_struct(ordinal)); } } } ProfEnd(); ProfBegin("Ordinal Exports"); { for (U64 exp_idx = 0; exp_idx < finalized_exports.ordinal_exports.count; exp_idx += 1) { // create and store export's ordinal PE_ExportParse *exp = finalized_exports.ordinal_exports.v[exp_idx]; U16 *ordinal = push_array(obj_writer->arena, U16, 1); *ordinal = exp->ordinal - finalized_exports.ordinal_low; str8_list_push(obj_writer->arena, &ordinal_table_sect->data, str8_struct(ordinal)); } } ProfEnd(); // fill out export table header PE_ExportTableHeader *header = push_array(obj_writer->arena, PE_ExportTableHeader, 1); header->time_stamp = time_stamp; header->ordinal_base = safe_cast_u16(finalized_exports.ordinal_low); header->export_address_table_count = safe_cast_u32(voff_table_sect->data.node_count); header->name_pointer_table_count = safe_cast_u32(name_voff_table_sect->data.node_count); // push header field's symbols COFF_ObjSymbol *image_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_HEADER_NAME_VOFF"), 0, image_name_sect); COFF_ObjSymbol *address_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_HEADER_ADDRESS_TABLE_VOFF"), 0, voff_table_sect); COFF_ObjSymbol *name_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_HEADER_NAME_POINTER_VOFF"), 0, name_voff_table_sect); COFF_ObjSymbol *ordinal_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_HEADER_ORDINAL_TABLE_VOFF"), 0, ordinal_table_sect); // push export table header section COFF_ObjSection *header_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$1"), PE_EDATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_struct(header)); coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_TABLE_HEADER"), 0, header_sect); // patch export table header coff_obj_writer_section_push_reloc_voff(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, name_voff), image_name_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, export_address_table_voff), address_table_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, name_pointer_table_voff), name_table_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, ordinal_table_voff), ordinal_table_symbol); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); scratch_end(scratch); return obj; } internal String8 pe_make_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, String8 debug_symbols, PE_ExportParseList export_list) { ProfBeginFunction(); COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); // These objects appear in first three members of any lib that linker produces with /dll. // Objects are used by MSVC linker to build import table. String8 import_entry_obj = pe_make_import_entry_obj(lib_writer->arena, dll_name, time_stamp, machine, debug_symbols); String8 null_import_descriptor_obj = pe_make_null_import_descriptor_obj(lib_writer->arena, time_stamp, machine, debug_symbols); String8 null_thunk_data_obj = pe_make_null_thunk_data_obj(lib_writer->arena, dll_name, time_stamp, machine, debug_symbols); // push import table nulls coff_lib_writer_push_obj(lib_writer, dll_name, import_entry_obj); coff_lib_writer_push_obj(lib_writer, dll_name, null_import_descriptor_obj); coff_lib_writer_push_obj(lib_writer, dll_name, null_thunk_data_obj); // push exports for (PE_ExportParseNode *exp_n = export_list.first; exp_n != 0; exp_n = exp_n->next) { PE_ExportParse *exp = &exp_n->data; if (exp->is_private) { continue; } String8 name = pe_name_from_export_parse(exp); U16 hint_or_ordinal = pe_hint_or_ordinal_from_export_parse(exp); coff_lib_writer_push_import(lib_writer, machine, time_stamp, dll_name, exp->import_by, name, hint_or_ordinal, exp->type); } // serialize lib String8 lib = coff_lib_writer_serialize(arena, lib_writer, COFF_TimeStamp_Max, 0, /* emit second member: */ 1); coff_lib_writer_release(&lib_writer); ProfEnd(); return lib; } ================================================ FILE: src/pe/pe_make_export_table.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_MAKE_EXPORT_TABLE_H #define PE_MAKE_EXPORT_TABLE_H typedef struct PE_ExportParse { String8 obj_path; String8 lib_path; String8 name; String8 alias; COFF_ImportType type; COFF_ImportByType import_by; U16 hint; U16 ordinal; B32 is_ordinal_assigned; B32 is_noname_present; B32 is_private; B32 is_forwarder; } PE_ExportParse; typedef struct PE_ExportParseNode { PE_ExportParse data; struct PE_ExportParseNode *next; } PE_ExportParseNode; typedef struct PE_ExportParseList { U64 count; PE_ExportParseNode *first; PE_ExportParseNode *last; } PE_ExportParseList; typedef struct PE_ExportParsePtrArray { U64 count; PE_ExportParse **v; } PE_ExportParsePtrArray; typedef struct PE_FinalizedExports { U64 ordinal_low; union { struct { PE_ExportParsePtrArray named_exports; PE_ExportParsePtrArray forwarder_exports; PE_ExportParsePtrArray ordinal_exports; }; PE_ExportParsePtrArray exports_with_names[2]; PE_ExportParsePtrArray all[3]; }; } PE_FinalizedExports; //////////////////////////////// internal PE_ExportParsePtrArray pe_array_from_export_list(Arena *arena, PE_ExportParseList list); internal PE_ExportParseNode * pe_export_parse_list_push(Arena *arena, PE_ExportParseList *list, PE_ExportParse data); internal String8 pe_make_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, String8 debug_symbols, PE_ExportParseList export_list); #endif // COFF_EXPORT_TABLE_H ================================================ FILE: src/pe/pe_make_import_table.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void pe_make_import_header_list_push_node(PE_MakeImportList *list, PE_MakeImportNode *node) { SLLQueuePush(list->first, list->last, node); list->count += 1; } internal PE_MakeImportNode * pe_make_import_header_list_push(Arena *arena, PE_MakeImportList *list, PE_MakeImport v) { PE_MakeImportNode *node = push_array(arena, PE_MakeImportNode, 1); node->v = v; pe_make_import_header_list_push_node(list, node); return node; } internal COFF_ObjSymbol * pe_make_indirect_jump_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *iat_symbol, String8 thunk_name) { ProfBeginFunction(); static U8 thunk[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp [__imp_] // emit chunk String8 jmp_data = push_str8_copy(obj_writer->arena, str8_array_fixed(thunk)); U64 jmp_data_offset = code_sect->data.total_size; str8_list_push(obj_writer->arena, &code_sect->data, jmp_data); // patch thunk with imports address static const U64 JMP_OPERAND_OFFSET = 2; coff_obj_writer_section_push_reloc(obj_writer, code_sect, jmp_data_offset + JMP_OPERAND_OFFSET, iat_symbol, COFF_Reloc_X64_Rel32); COFF_ObjSymbol *jmp_thunk_symbol = coff_obj_writer_push_symbol_extern_func(obj_writer, thunk_name, jmp_data_offset, code_sect); ProfEnd(); return jmp_thunk_symbol; } internal COFF_ObjSymbol * pe_make_load_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *imp_addr_ptr, COFF_ObjSymbol *tail_merge, String8 func_name) { ProfBeginFunction(); static U8 load_thunk[] = { 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00, // lea rax, [__imp_] 0xE9, 0x00, 0x00, 0x00, 0x00 // jmp __tailMerge_ }; // emit load thunk chunk U64 load_thunk_data_offset = code_sect->data.total_size; String8 load_thunk_data = push_str8_copy(obj_writer->arena, str8_array_fixed(load_thunk)); str8_list_push(obj_writer->arena, &code_sect->data, load_thunk_data); // patch lea with IAT entry static const U64 LEA_OPERAND_OFFSET = 3; coff_obj_writer_section_push_reloc(obj_writer, code_sect, load_thunk_data_offset + LEA_OPERAND_OFFSET, imp_addr_ptr, COFF_Reloc_X64_Rel32); // patch jmp __tailMerge_ static const U64 JMP_OPERAND_OFFSET = 8; coff_obj_writer_section_push_reloc(obj_writer, code_sect, load_thunk_data_offset + JMP_OPERAND_OFFSET, tail_merge, COFF_Reloc_X64_Rel32); // emit symbol String8 thunk_name = push_str8f(obj_writer->arena, "__imp_load_%S", func_name); COFF_ObjSymbol *load_thunk_symbol = coff_obj_writer_push_symbol_extern_func(obj_writer, thunk_name, load_thunk_data_offset, code_sect); ProfEnd(); return load_thunk_symbol; } internal COFF_ObjSymbol * pe_make_tail_merge_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, String8 dll_name, String8 delay_load_helper_name, COFF_ObjSymbol *dll_import_descriptor) { ProfBeginFunction(); static U8 tail_merge[] = { 0x48, 0x89, 0x4C, 0x24, 0x08, // mov qword ptr [rsp+8],rcx 0x48, 0x89, 0x54, 0x24, 0x10, // mov qword ptr [rsp+10h],rdx 0x4C, 0x89, 0x44, 0x24, 0x18, // mov qword ptr [rsp+18h],r8 0x4C, 0x89, 0x4C, 0x24, 0x20, // mov qword ptr [rsp+20h],r9 0x48, 0x83, 0xEC, 0x68, // sub rsp,68h 0x66, 0x0F, 0x7F, 0x44, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h],xmm0 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h],xmm1 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x40, // movdqa xmmword ptr [rsp+40h],xmm2 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x50, // movdqa xmmword ptr [rsp+50h],xmm3 0x48, 0x8B, 0xD0, // mov rdx,rax 0x48, 0x8D, 0x0D, 0x00, 0x00, 0x00, 0x00, // lea rcx,[__DELAY_IMPORT_DESCRIPTOR_] 0xE8, 0x00, 0x00, 0x00, 0x00, // call __delayLoadHelper2 0x66, 0x0F, 0x6F, 0x44, 0x24, 0x20, // movdqa xmm0,xmmword ptr [rsp+20h] 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x30, // movdqa xmm1,xmmword ptr [rsp+30h] 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x40, // movdqa xmm2,xmmword ptr [rsp+40h] 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x50, // movdqa xmm3,xmmword ptr [rsp+50h] 0x48, 0x8B, 0x4C, 0x24, 0x70, // mov rcx,qword ptr [rsp+70h] 0x48, 0x8B, 0x54, 0x24, 0x78, // mov rdx,qword ptr [rsp+78h] 0x4C, 0x8B, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00, // mov r8,qword ptr [rsp+80h] 0x4C, 0x8B, 0x8C, 0x24, 0x88, 0x00, 0x00, 0x00, // mov r9,qword ptr [rsp+88h] 0x48, 0x83, 0xC4, 0x68, // add rsp,68h 0xFF, 0xE0, // jmp rax }; // emit tail merge chunk String8 tail_merge_data = push_str8_copy(obj_writer->arena, str8_array_fixed(tail_merge)); U64 tail_merge_off = code_sect->data.total_size; str8_list_push(obj_writer->arena, &code_sect->data, tail_merge_data); // patch lea __DELAY_IMPORT_DESCRIPTOR_ static const U64 LEA_OPERAND_OFFSET = 54; coff_obj_writer_section_push_reloc(obj_writer, code_sect, tail_merge_off + LEA_OPERAND_OFFSET, dll_import_descriptor, COFF_Reloc_X64_Rel32); COFF_ObjSymbol *delay_load_helper = coff_obj_writer_push_symbol_undef(obj_writer, delay_load_helper_name); // patch call __delayLoadHelper2 static const U64 CALL_OPERAND_OFFSET = 59; coff_obj_writer_section_push_reloc(obj_writer, code_sect, tail_merge_off + CALL_OPERAND_OFFSET, delay_load_helper, COFF_Reloc_X64_Rel32); // emit symbol String8 tail_merge_name = push_str8f(obj_writer->arena, "__tailMerge_%S", dll_name); COFF_ObjSymbol *tail_merge_symbol = coff_obj_writer_push_symbol_extern(obj_writer, tail_merge_name, tail_merge_off, code_sect); ProfEnd(); return tail_merge_symbol; } internal String8 pe_make_import_entry_obj_delayed(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); String8 dll_name_cstr = push_cstr(arena, dll_name); PE_DelayedImportEntry *null_import_entry = push_array(obj_writer->arena, PE_DelayedImportEntry, 1); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *didat2 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$2"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(null_import_entry)); COFF_ObjSection *didat6 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$6"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr); coff_obj_writer_push_symbol_extern(obj_writer, push_str8f(obj_writer->arena, "__DELAY_IMPORT_DESCRIPTOR_%S", dll_name), 0, didat2); coff_obj_writer_push_symbol_sect(obj_writer, didat2->name, didat2); coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR")); coff_obj_writer_push_symbol_undef(obj_writer, push_str8f(obj_writer->arena, "\x7f%S_NULL_THUNK_DATA_DLA", dll_name)); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 pe_make_null_import_descriptor_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); PE_DelayedImportEntry *import_desc = push_array(obj_writer->arena, PE_DelayedImportEntry, 1); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *didat3 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$3"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(import_desc)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR"), 0, didat3); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 pe_make_null_thunk_data_obj_delayed(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name); U64 import_size = coff_word_size_from_machine(machine); String8 null_thunk = str8(push_array(obj_writer->arena, U8, import_size), import_size); String8 null_lookup = str8(push_array(obj_writer->arena, U8, import_size), import_size); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *didat4 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$4"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_lookup); COFF_ObjSection *didat5 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$5"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_thunk); COFF_ObjSection *didat8 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$8"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_thunk); COFF_ObjSection *didat9 = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$9"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_thunk); coff_obj_writer_push_symbol_extern(obj_writer, push_str8f(obj_writer->arena, "\x7f%S_NULL_THUNK_DATA_DLA", dll_name), 0, didat5); String8 obj = coff_obj_writer_serialize(arena, obj_writer); ProfEnd(); return obj; } internal String8 pe_make_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name); PE_ImportEntry *null_import_entry = push_array(obj_writer->arena, PE_ImportEntry, 1); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *idata2 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(null_import_entry)); COFF_ObjSection *idata6 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr); coff_obj_writer_push_symbol_extern(obj_writer, push_str8f(obj_writer->arena, "__IMPORT_DESCRIPTOR_%S", dll_name), 0, idata2); coff_obj_writer_push_symbol_sect(obj_writer, idata2->name, idata2); COFF_ObjSymbol *null_desc_undef = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR")); COFF_ObjSymbol *null_thunk_undef = coff_obj_writer_push_symbol_undef(obj_writer, push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name)); COFF_ObjSymbol *idata6_symbol = coff_obj_writer_push_symbol_static(obj_writer, idata6->name, 0, idata6); COFF_ObjSymbol *idata4_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$4"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData); COFF_ObjSymbol *idata5_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$5"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData); coff_obj_writer_section_push_reloc_voff(obj_writer, idata2, OffsetOf(PE_ImportEntry, name_voff), idata6_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, idata2, OffsetOf(PE_ImportEntry, lookup_table_voff), idata4_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, idata2, OffsetOf(PE_ImportEntry, import_addr_table_voff), idata5_symbol); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 pe_make_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); PE_ImportEntry *import_desc = push_array(obj_writer->arena, PE_ImportEntry, 1); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *idata3 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$3"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(import_desc)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR"), 0, idata3); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 pe_make_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols) { ProfBeginFunction(); COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); U64 import_size = coff_word_size_from_machine(machine); String8 null_lookup = str8(push_array(obj_writer->arena, U8, import_size), import_size); String8 null_thunk = str8(push_array(obj_writer->arena, U8, import_size), import_size); COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *idata4 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_lookup); COFF_ObjSection *idata5 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), PE_IDATA_SECTION_FLAGS|coff_section_flag_from_align_size(import_size), null_thunk); coff_obj_writer_push_symbol_extern(obj_writer, push_str8f(obj_writer->arena, "\x7f%S_NULL_THUNK_DATA", dll_name), 0, idata5); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); ProfEnd(); return obj; } internal String8 pe_make_import_dll_obj_static(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 dll_name, String8 debug_symbols, PE_MakeImportList import_headers) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); U64 import_size = coff_word_size_from_machine(machine); COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size); PE_ImportEntry *impdesc = push_array(obj_writer->arena, PE_ImportEntry, 1); String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name); COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc)); COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero()); COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$7"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr); COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$zz"), PE_TEXT_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero()); COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect); COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect); COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect); // patch import DLL header coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, lookup_table_voff), ilt_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, name_voff), dll_name_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, import_addr_table_voff), iat_symbol); for (PE_MakeImportNode *import_header_n = import_headers.first; import_header_n != 0; import_header_n = import_header_n->next) { COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(import_header_n->v.header); COFF_ObjSymbol *iat_symbol = 0; switch (import_header.import_by) { case COFF_ImportBy_Ordinal: { String8 ordinal_data = coff_ordinal_data_from_hint(obj_writer->arena, import_header.machine, import_header.hint_or_ordinal); String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", import_header.func_name); iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_sect->data.total_size, iat_sect); str8_list_push(obj_writer->arena, &ilt_sect->data, ordinal_data); str8_list_push(obj_writer->arena, &iat_sect->data, ordinal_data); } break; case COFF_ImportBy_Name: { // put together name look up entry COFF_ObjSymbol *int_symbol = coff_obj_writer_push_symbol_static(obj_writer, int_sect->name, int_sect->data.total_size, int_sect); String8 int_data = coff_make_import_lookup(obj_writer->arena, import_header.hint_or_ordinal, import_header.func_name); str8_list_push(obj_writer->arena, &int_sect->data, int_data); // in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", import_header.func_name); iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_sect->data.total_size, iat_sect); // patch IAT and ILT coff_obj_writer_section_push_reloc_voff(obj_writer, ilt_sect, ilt_sect->data.total_size, int_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, iat_sect, iat_sect->data.total_size, int_symbol); U64 import_size = coff_word_size_from_machine(import_header.machine); U8 *import_entry = push_array(obj_writer->arena, U8, import_size); str8_list_push(obj_writer->arena, &ilt_sect->data, str8_array(import_entry, import_size)); str8_list_push(obj_writer->arena, &iat_sect->data, str8_array(import_entry, import_size)); } break; case COFF_ImportBy_Undecorate: { NotImplemented; } break; case COFF_ImportBy_NameNoPrefix: { NotImplemented; } break; default: { InvalidPath; } break; } // emit thunks if (import_header_n->v.make_jump_thunk) { if (import_header.type == COFF_ImportHeader_Code) { switch (import_header.machine) { case COFF_MachineType_Unknown: {} break; case COFF_MachineType_X64: { pe_make_indirect_jump_thunk_x64(obj_writer, code_sect, iat_symbol, import_header.func_name); } break; default: { NotImplemented; } break; } } else { Assert(0 && "unable to make a jump thunk for non-code target"); } } } str8_list_push(obj_writer->arena, &ilt_sect->data, str8(0, coff_word_size_from_machine(machine))); str8_list_push(obj_writer->arena, &iat_sect->data, str8(0, coff_word_size_from_machine(machine))); String8 dll_obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); return dll_obj; } internal String8 pe_make_import_dll_obj_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 dll_name, String8 delay_load_helper_name, String8 debug_symbols, PE_MakeImportList import_headers, B32 emit_biat, B32 emit_uiat) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine); // import descriptor PE_DelayedImportEntry *impdesc = push_array(obj_writer->arena, PE_DelayedImportEntry, 1); impdesc->attributes = 1; // DLL name cstring String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name); // DLL handle U64 handle_size = coff_word_size_from_machine(machine); U8 *handle = push_array(obj_writer->arena, U8, handle_size); // import align U64 import_size = coff_word_size_from_machine(machine); COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size); // push sections COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$2"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc)); COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$4"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$5"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$6"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero()); COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$7"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr); COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$"), PE_TEXT_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero()); COFF_ObjSection *handle_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_array(handle, handle_size)); COFF_ObjSection *debug_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); COFF_ObjSection *biat_sect = 0; COFF_ObjSection *uiat_sect = 0; // sections symbols COFF_ObjSymbol *dll_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_sect->name, 0, dll_sect); COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect); COFF_ObjSymbol *handle_symbol = coff_obj_writer_push_symbol_static(obj_writer, handle_sect->name, 0, handle_sect); COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect); COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect); // patch virutal offsets in import header coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_voff), dll_name_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, module_handle_voff), handle_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, iat_voff), iat_symbol); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_table_voff), ilt_symbol); // patch BIAT virtual offset in import header if (emit_biat) { biat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$8"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSymbol *biat_symbol = coff_obj_writer_push_symbol_static(obj_writer, biat_sect->name, 0, biat_sect); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, bound_table_voff), biat_symbol); } // patch UIAT virtual offset in import header if (emit_uiat) { uiat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$9"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSymbol *uiat_symbol = coff_obj_writer_push_symbol_static(obj_writer, uiat_sect->name, 0, uiat_sect); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, unload_table_voff), uiat_symbol); } // emit tail merge COFF_ObjSymbol *tail_merge_symbol = 0; switch (machine) { case COFF_MachineType_Unknown: {} break; case COFF_MachineType_X64: { tail_merge_symbol = pe_make_tail_merge_thunk_x64(obj_writer, code_sect, dll_name, delay_load_helper_name, dll_symbol); } break; default: { NotImplemented; } break; } for (PE_MakeImportNode *import_header_n = import_headers.first; import_header_n != 0; import_header_n = import_header_n->next) { COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(import_header_n->v.header); // emit thunks COFF_ObjSymbol *load_thunk_symbol = 0; if (import_header.type == COFF_ImportHeader_Code) { switch (machine) { case COFF_MachineType_Unknown: {} break; case COFF_MachineType_X64: { String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", import_header.func_name); iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_sect->data.total_size, iat_sect); if (import_header_n->v.make_jump_thunk) { pe_make_indirect_jump_thunk_x64(obj_writer, code_sect, iat_symbol, import_header.func_name); } // emit load thunk load_thunk_symbol = pe_make_load_thunk_x64(obj_writer, code_sect, iat_symbol, tail_merge_symbol, import_header.func_name); } break; default: { NotImplemented; } break; } } switch (import_header.import_by) { case COFF_ImportBy_Ordinal: { String8 ordinal_data = coff_ordinal_data_from_hint(obj_writer->arena, import_header.machine, import_header.hint_or_ordinal); str8_list_push(obj_writer->arena, &ilt_sect->data, ordinal_data); // in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses. U64 iat_offset = iat_sect->data.total_size; str8_list_push(obj_writer->arena, &iat_sect->data, str8(0, import_size)); // patch-in thunk address coff_obj_writer_section_push_reloc_addr(obj_writer, iat_sect, iat_offset, load_thunk_symbol); if (emit_biat) { U64 import_size = coff_word_size_from_machine(machine); U64 biat_offset = biat_sect->data.total_size; str8_list_push(obj_writer->arena, &biat_sect->data, str8(0,import_size)); coff_obj_writer_section_push_reloc_addr(obj_writer, biat_sect, biat_offset, load_thunk_symbol); } if (emit_uiat) { U64 import_size = coff_word_size_from_machine(machine); U64 uiat_offset = uiat_sect->data.total_size; str8_list_push(obj_writer->arena, &biat_sect->data, str8(0,import_size)); coff_obj_writer_section_push_reloc_addr(obj_writer, uiat_sect, uiat_offset, load_thunk_symbol); } } break; case COFF_ImportBy_Name: { // put together name look up entry String8 int_data = coff_make_import_lookup(obj_writer->arena, import_header.hint_or_ordinal, import_header.func_name); U64 int_data_offset = int_sect->data.total_size; str8_list_push(obj_writer->arena, &int_sect->data, int_data); // create symbol for lookup chunk String8 int_symbol_name = push_str8f(obj_writer->arena, "%S.%S.name.delayed", dll_name, import_header.func_name); COFF_ObjSymbol *int_symbol = coff_obj_writer_push_symbol_static(obj_writer, int_symbol_name, int_data_offset, int_sect); U64 import_size = coff_word_size_from_machine(machine); // dynamic linker patches this voff on DLL load event U64 ilt_data_offset = ilt_sect->data.total_size; str8_list_push(obj_writer->arena, &ilt_sect->data, str8(0, import_size)); // patch-in ILT with import voff coff_obj_writer_section_push_reloc_voff(obj_writer, ilt_sect, ilt_data_offset, int_symbol); // in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses. U64 iat_offset = iat_sect->data.total_size; str8_list_push(obj_writer->arena, &iat_sect->data, str8(0, import_size)); // patch-in thunk address coff_obj_writer_section_push_reloc_addr(obj_writer, iat_sect, iat_offset, load_thunk_symbol); if (emit_biat) { U64 biat_data_offset = biat_sect->data.total_size; str8_list_push(obj_writer->arena, &biat_sect->data, str8(0, import_size)); // patch-in thunk address coff_obj_writer_section_push_reloc_addr(obj_writer, biat_sect, biat_data_offset, load_thunk_symbol); } if (emit_uiat) { U64 uiat_data_offset = uiat_sect->data.total_size; str8_list_push(obj_writer->arena, &uiat_sect->data, str8(0, import_size)); // patch-in thunk address coff_obj_writer_section_push_reloc_addr(obj_writer, uiat_sect, uiat_data_offset, load_thunk_symbol); } } break; case COFF_ImportBy_Undecorate: { NotImplemented; } break; case COFF_ImportBy_NameNoPrefix: { NotImplemented; } break; } } str8_list_push(obj_writer->arena, &ilt_sect->data, str8(0, coff_word_size_from_machine(machine))); str8_list_push(obj_writer->arena, &iat_sect->data, str8(0, coff_word_size_from_machine(machine))); if (emit_biat) { str8_list_push(obj_writer->arena, &biat_sect->data, str8(0, coff_word_size_from_machine(machine))); } if (emit_uiat) { str8_list_push(obj_writer->arena, &uiat_sect->data, str8(0, coff_word_size_from_machine(machine))); } String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); return obj; } ================================================ FILE: src/pe/pe_make_import_table.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_MAKE_IMPORT_TABLE_H #define PE_MAKE_IMPORT_TABLE_H typedef struct PE_MakeImport { String8 header; B32 make_jump_thunk; } PE_MakeImport; typedef struct PE_MakeImportNode { PE_MakeImport v; struct PE_MakeImportNode *next; } PE_MakeImportNode; typedef struct PE_MakeImportList { U64 count; PE_MakeImportNode *first; PE_MakeImportNode *last; } PE_MakeImportList; // ----------------------------------------------------------------------------- internal void pe_make_import_header_list_push_node(PE_MakeImportList *list, PE_MakeImportNode *node); internal PE_MakeImportNode * pe_make_import_header_list_push(Arena *arena, PE_MakeImportList *list, PE_MakeImport header); internal COFF_ObjSymbol * pe_make_indirect_jump_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *iat_symbol, String8 thunk_name); internal COFF_ObjSymbol * pe_make_load_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *imp_addr_ptr, COFF_ObjSymbol *tail_merge, String8 func_name); internal COFF_ObjSymbol * pe_make_tail_merge_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, String8 dll_name, String8 delay_load_helper_name, COFF_ObjSymbol *dll_import_descriptor); internal String8 pe_make_import_dll_obj_static(Arena *arena, COFF_TimeStamp time_stmap, COFF_MachineType machine, String8 dll_name, String8 debug_symbols, PE_MakeImportList import_headers); internal String8 pe_make_import_dll_obj_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 dll_name, String8 delay_load_helper_name, String8 debug_symbols, PE_MakeImportList import_headers, B32 emit_biat, B32 emit_uiat); internal String8 pe_make_import_entry_obj_delayed(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); internal String8 pe_make_null_import_descriptor_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); internal String8 pe_make_null_thunk_data_delayed(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); internal String8 pe_make_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); internal String8 pe_make_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); internal String8 pe_make_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 debug_symbols); #endif // PE_MAKE_IMPORT_TABLE_H ================================================ FILE: src/pe/pe_section_flags.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_SECTION_FLAGS_H #define PE_SECTION_FLAGS_H #define PE_TEXT_SECTION_FLAGS (COFF_SectionFlag_CntCode|COFF_SectionFlag_MemExecute|COFF_SectionFlag_MemRead) #define PE_DATA_SECTION_FLAGS (COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite) #define PE_RDATA_SECTION_FLAGS (COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead) #define PE_BSS_SECTION_FLAGS (COFF_SectionFlag_CntUninitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite) #define PE_IDATA_SECTION_FLAGS PE_DATA_SECTION_FLAGS #define PE_DEBUG_DIR_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_RSRC_SECTION_FLAGS PE_DATA_SECTION_FLAGS #define PE_RSRC1_SECTION_FLAGS (PE_DATA_SECTION_FLAGS | COFF_SectionFlag_Align4Bytes) #define PE_RSRC2_SECTION_FLAGS (PE_DATA_SECTION_FLAGS | COFF_SectionFlag_Align4Bytes) #define PE_XDATA_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_PDATA_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_EDATA_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_GFIDS_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_GIATS_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_GLJMP_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_GEHCONT_SECTION_FLAGS PE_RDATA_SECTION_FLAGS #define PE_RELOC_SECTION_FLAGS (PE_RDATA_SECTION_FLAGS | COFF_SectionFlag_MemDiscardable) #define PE_DEBUG_SECTION_FLAGS (PE_RDATA_SECTION_FLAGS | COFF_SectionFlag_MemDiscardable) #define PE_TLS_SECTION_FLAGS PE_DATA_SECTION_FLAGS #endif // PE_SECTION_FLAGS_H ================================================ FILE: src/radbin/generated/radbin.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 rb_file_format_display_name_table[10] = { {0}, str8_lit_comp("PDB"), str8_lit_comp("PE"), str8_lit_comp("COFF (OBJ)"), str8_lit_comp("COFF (Big OBJ)"), str8_lit_comp("COFF (Archive)"), str8_lit_comp("COFF (Thin Archive)"), str8_lit_comp("ELF32"), str8_lit_comp("ELF64"), str8_lit_comp("RDI"), }; C_LINKAGE_END ================================================ FILE: src/radbin/generated/radbin.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef RADBIN_META_H #define RADBIN_META_H typedef enum RB_FileFormat { RB_FileFormat_Null, RB_FileFormat_PDB, RB_FileFormat_PE, RB_FileFormat_COFF_OBJ, RB_FileFormat_COFF_BigOBJ, RB_FileFormat_COFF_Archive, RB_FileFormat_COFF_ThinArchive, RB_FileFormat_ELF32, RB_FileFormat_ELF64, RB_FileFormat_RDI, RB_FileFormat_COUNT, } RB_FileFormat; C_LINKAGE_BEGIN extern String8 rb_file_format_display_name_table[10]; C_LINKAGE_END #endif // RADBIN_META_H ================================================ FILE: src/radbin/radbin.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "radbin/generated/radbin.meta.c" //////////////////////////////// //~ rjf: Top-Level Entry Points internal void rb_entry_point(CmdLine *cmdline) { Temp scratch = scratch_begin(0, 0); U64 threads_count = os_get_system_info()->logical_processor_count; String8 threads_count_from_cmdline_string = cmd_line_string(cmdline, str8_lit("thread_count")); if(threads_count_from_cmdline_string.size != 0) { U64 threads_count_from_cmdline = 0; if(try_u64_from_str8_c_rules(threads_count_from_cmdline_string, &threads_count_from_cmdline)) { threads_count = threads_count_from_cmdline; } } Thread *threads = push_array(scratch.arena, Thread, threads_count); RB_ThreadParams *threads_params = push_array(scratch.arena, RB_ThreadParams, threads_count); Barrier barrier = barrier_alloc(threads_count); U64 broadcast_val = 0; for EachIndex(idx, threads_count) { threads_params[idx].cmdline = cmdline; threads_params[idx].lane_ctx.lane_idx = idx; threads_params[idx].lane_ctx.lane_count = threads_count; threads_params[idx].lane_ctx.barrier = barrier; threads_params[idx].lane_ctx.broadcast_memory = &broadcast_val; threads[idx] = thread_launch(rb_thread_entry_point, &threads_params[idx]); } for EachIndex(idx, threads_count) { thread_join(threads[idx], max_U64); } scratch_end(scratch); } internal void rb_thread_entry_point(void *p) { RB_ThreadParams *params = (RB_ThreadParams *)p; CmdLine *cmdline = params->cmdline; LaneCtx lctx = params->lane_ctx; ThreadNameF("radbin_thread_%I64u", lctx.lane_idx); lane_ctx(lctx); Arena *arena = arena_alloc(); Log *log = log_alloc(); log_select(log); log_scope_begin(); ////////////////////////////// //- rjf: set up shared state // if(lane_idx() == 0) { rb_shared = push_array(arena, RB_Shared, 1); } lane_sync(); ////////////////////////////// //- rjf: analyze & load command line input files // ProfScope("analyze & load command line input files") if(lane_idx() == 0) { String8List input_file_path_tasks = str8_list_copy(arena, &cmdline->inputs); for(String8Node *n = input_file_path_tasks.first; n != 0; n = n->next) { ////////////////////////// //- rjf: do thin analysis of file // RB_FileFormat file_format = RB_FileFormat_Null; RB_FileFormatFlags file_format_flags = 0; ProfScope("do thin analysis of file") { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, n->string); FileProperties props = os_properties_from_file(file); //- rjf: PDB magic -> PDB input if(file_format == RB_FileFormat_Null) { U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe); if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe))) { file_format = RB_FileFormat_PDB; } } if(file_format == RB_FileFormat_Null) { U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0}; os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe); if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe))) { file_format = RB_FileFormat_PDB; } } //- rjf: PE magic -> PE input if(file_format == RB_FileFormat_Null) { PE_DosHeader dos_header_maybe = {0}; os_file_read_struct(file, 0, &dos_header_maybe); if(dos_header_maybe.magic == PE_DOS_MAGIC) { U32 pe_magic_maybe = 0; os_file_read_struct(file, dos_header_maybe.coff_file_offset, &pe_magic_maybe); if(pe_magic_maybe == PE_MAGIC) { file_format = RB_FileFormat_PE; } } } //- rjf: COFF archive magic -> COFF archive input if(file_format == RB_FileFormat_Null) { U8 coff_archive_sig_maybe[sizeof(g_coff_archive_sig)] = {0}; os_file_read(file, r1u64(0, sizeof(coff_archive_sig_maybe)), coff_archive_sig_maybe); if(MemoryMatch(coff_archive_sig_maybe, g_coff_archive_sig, sizeof(g_coff_archive_sig))) { file_format = RB_FileFormat_COFF_Archive; } } if(file_format == RB_FileFormat_Null) { U8 coff_thin_archive_sig_maybe[sizeof(g_coff_thin_archive_sig)] = {0}; os_file_read(file, r1u64(0, sizeof(coff_thin_archive_sig_maybe)), coff_thin_archive_sig_maybe); if(MemoryMatch(coff_thin_archive_sig_maybe, g_coff_thin_archive_sig, sizeof(g_coff_thin_archive_sig))) { file_format = RB_FileFormat_COFF_ThinArchive; } } //- rjf: COFF obj magic -> COFF obj input if(file_format == RB_FileFormat_Null) { COFF_BigObjHeader header_maybe = {0}; os_file_read_struct(file, 0, &header_maybe); if(header_maybe.sig1 == COFF_MachineType_Unknown && header_maybe.sig2 == max_U16 && header_maybe.version >= 2 && MemoryMatch(header_maybe.magic, g_coff_big_header_magic, sizeof(header_maybe.magic))) { file_format = RB_FileFormat_COFF_BigOBJ; } } if(file_format == RB_FileFormat_Null) { Temp scratch = scratch_begin(&arena, 1); COFF_FileHeader header_maybe = {0}; os_file_read_struct(file, 0, &header_maybe); U64 section_count = header_maybe.section_count; U64 section_hdr_opl_off = sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader); // rjf: check if machine type is valid B32 machine_type_is_valid = 0; switch(header_maybe.machine) { case COFF_MachineType_Unknown: case COFF_MachineType_X86: case COFF_MachineType_X64: case COFF_MachineType_Am33: case COFF_MachineType_Arm: case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: case COFF_MachineType_Ebc: case COFF_MachineType_Ia64: case COFF_MachineType_M32R: case COFF_MachineType_Mips16: case COFF_MachineType_MipsFpu:case COFF_MachineType_MipsFpu16: case COFF_MachineType_PowerPc:case COFF_MachineType_PowerPcFp: case COFF_MachineType_R4000: case COFF_MachineType_RiscV32: case COFF_MachineType_RiscV64:case COFF_MachineType_RiscV128: case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp: case COFF_MachineType_Sh4: case COFF_MachineType_Sh5: case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2: { machine_type_is_valid = 1; }break; } // rjf: check if sections are valid B32 sections_are_valid = 0; if(machine_type_is_valid) { if(props.size >= section_hdr_opl_off) { COFF_SectionHeader *section_hdrs = push_array(scratch.arena, COFF_SectionHeader, section_count); os_file_read(file, r1u64(sizeof(header_maybe), sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader)), section_hdrs); B32 section_ranges_valid = 1; for EachIndex(section_hdr_idx, section_count) { COFF_SectionHeader *hdr = §ion_hdrs[section_hdr_idx]; if(!(hdr->flags & COFF_SectionFlag_CntUninitializedData)) { U64 min = hdr->foff; U64 max = min + hdr->fsize; if(hdr->fsize > 0 && !(section_hdr_opl_off <= min && min <= max && max <= props.size)) { section_ranges_valid = 0; break; } } } sections_are_valid = section_ranges_valid; } } // rjf: check if symbol table is valid B32 symbol_table_is_valid = 0; if(sections_are_valid) { U64 symbol_table_off = header_maybe.symbol_table_foff; U64 symbol_table_size = sizeof(COFF_Symbol16)*header_maybe.symbol_count; U64 symbol_table_opl_off = symbol_table_off+symbol_table_size; if(symbol_table_off == 0 && symbol_table_size == 0) { symbol_table_off = section_hdr_opl_off; symbol_table_opl_off = section_hdr_opl_off; } symbol_table_is_valid = (section_hdr_opl_off <= symbol_table_off && symbol_table_off <= symbol_table_opl_off && symbol_table_opl_off <= props.size); } // rjf: symbol table is valid -> is COFF OBJ if(symbol_table_is_valid) { file_format = RB_FileFormat_COFF_OBJ; } scratch_end(scratch); } //- rjf: ELF magic -> ELF input if(file_format == RB_FileFormat_Null) { U8 identifier_maybe[ELF_Identifier_Max] = {0}; os_file_read(file, r1u64(0, sizeof(identifier_maybe)), identifier_maybe); B32 is_elf_magic = (identifier_maybe[ELF_Identifier_Mag0] == 0x7f && identifier_maybe[ELF_Identifier_Mag1] == 'E' && identifier_maybe[ELF_Identifier_Mag2] == 'L' && identifier_maybe[ELF_Identifier_Mag3] == 'F'); if(is_elf_magic) { file_format = ELF_HdrIs64Bit(identifier_maybe) ? RB_FileFormat_ELF64 : RB_FileFormat_ELF32; } } //- rjf: RDI magic -> RDI input if(file_format == RB_FileFormat_Null) { RDI_Header rdi_header_maybe = {0}; os_file_read_struct(file, 0, &rdi_header_maybe); if(rdi_header_maybe.magic == RDI_MAGIC_CONSTANT) { file_format = RB_FileFormat_RDI; } } os_file_close(file); } ////////////////////////// //- rjf: log file recognition // if(file_format != RB_FileFormat_Null) { log_infof("%S recognized as %S\n", n->string, rb_file_format_display_name_table[file_format]); } else { log_infof("%S was not recognized as a supported format.\n", n->string); } ////////////////////////// //- rjf: load recognized files // String8 file_data = {0}; if(file_format != RB_FileFormat_Null) ProfScope("load recognized file") { file_data = os_data_from_file_path(arena, n->string); } ////////////////////////// //- rjf: PE format => generate new implicit path tasks for PDBs // if(file_format == RB_FileFormat_PE) ProfScope("PE file => generate task for PDB") { Temp scratch = scratch_begin(&arena, 1); String8 file_path = n->string; PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data); String8 raw_debug_dir = str8_substr(file_data, pe_bin_info.data_dir_franges[PE_DataDirectoryIndex_DEBUG]); PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, file_data, raw_debug_dir); for(PE_DebugInfoNode *n = debug_dir.first; n != 0; n = n->next) { if(n->v.path.size != 0) { log_infof("Found reference to separate debug info file in %S (%S) at %S\n", file_path, rb_file_format_display_name_table[file_format], n->v.path); str8_list_push(arena, &input_file_path_tasks, n->v.path); } } scratch_end(scratch); } ////////////////////////// //- rjf: ELF format => generate new implicit path tasks for debug files // if(file_format == RB_FileFormat_ELF32 || file_format == RB_FileFormat_ELF64) { Temp scratch = scratch_begin(&arena, 1); ELF_Bin bin = elf_bin_from_data(scratch.arena, file_data); ELF_GnuDebugLink debug_link = elf_gnu_debug_link_from_bin(file_data, &bin); if(debug_link.path.size != 0) { log_infof("Found reference to separate debug info file in %S (%S) at %S\n", n->string, rb_file_format_display_name_table[file_format], debug_link.path); str8_list_push(arena, &input_file_path_tasks, debug_link.path); } scratch_end(scratch); } ////////////////////////// //- rjf: PE => check if contains DWARF // if(file_format == RB_FileFormat_PE) { Temp scratch = scratch_begin(&arena, 1); PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data); String8 raw_section_table = str8_substr(file_data, pe_bin_info.section_table_range); String8 string_table = str8_substr(file_data, pe_bin_info.string_table_range); U64 section_count = raw_section_table.size / sizeof(COFF_SectionHeader); COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; if(dw_is_dwarf_present_coff_section_table(string_table, section_count, section_table)) { log_infof("DWARF data detected in %S (%S)\n", n->string, rb_file_format_display_name_table[file_format]); file_format_flags |= RB_FileFormatFlag_HasDWARF; } scratch_end(scratch); } ////////////////////////// //- rjf: ELF => check if contains DWARF // if(file_format == RB_FileFormat_ELF32 || file_format == RB_FileFormat_ELF64) { Temp scratch = scratch_begin(&arena, 1); ELF_Bin elf_bin = elf_bin_from_data(scratch.arena, file_data); if(dw_is_dwarf_present_from_elf_bin(file_data, &elf_bin)) { log_infof("DWARF data detected in %S (%S)\n", n->string, rb_file_format_display_name_table[file_format]); file_format_flags |= RB_FileFormatFlag_HasDWARF; } scratch_end(scratch); } ////////////////////////// //- rjf: push to list // { RB_File *f = push_array(arena, RB_File, 1); f->format = file_format; f->format_flags = file_format_flags; f->path = n->string; f->data = file_data; RB_FileNode *file_n = push_array(arena, RB_FileNode, 1); file_n->v = f; SLLQueuePush(rb_shared->input_files.first, rb_shared->input_files.last, file_n); rb_shared->input_files.count += 1; } } } lane_sync(); RB_FileList input_files = rb_shared->input_files; ////////////////////////////// //- rjf: bucket input files by format // ProfScope("bucket input files by format") if(lane_idx() == 0) { for(RB_FileNode *n = input_files.first; n != 0; n = n->next) { RB_FileNode *file_n = push_array(arena, RB_FileNode, 1); file_n->v = n->v; SLLQueuePush(rb_shared->input_files_from_format_table[n->v->format].first, rb_shared->input_files_from_format_table[n->v->format].last, file_n); rb_shared->input_files_from_format_table[n->v->format].count += 1; } } lane_sync(); RB_FileList *input_files_from_format_table = rb_shared->input_files_from_format_table; ////////////////////////////// //- rjf: unpack which kind of output we're producing, and to where // typedef enum OutputKind { OutputKind_Null, OutputKind_RDI, OutputKind_Dump, OutputKind_Breakpad, OutputKind_COUNT } OutputKind; struct { String8 arg; String8 title; } output_kind_info[] = { {str8_lit_comp(""), str8_lit_comp("")}, {str8_lit_comp("rdi"), str8_lit_comp("RAD Debug Info (.rdi) Conversion")}, {str8_lit_comp("dump"), str8_lit_comp("Textual Dumping")}, {str8_lit_comp("breakpad"), str8_lit_comp("Breakpad Debug Info Conversion")}, }; OutputKind output_kind = OutputKind_Null; String8 output_path = cmd_line_string(cmdline, str8_lit("out")); { //- rjf: user manually specified output kind if(output_kind == OutputKind_Null) { for EachNonZeroEnumVal(OutputKind, k) { if(cmd_line_has_flag(cmdline, output_kind_info[k].arg)) { log_infof("User specified --%S; performing `%S`\n", output_kind_info[k].arg, output_kind_info[k].title); output_kind = k; break; } } } //- rjf: we can infer from the user-specified output path if(str8_match(str8_skip_last_dot(output_path), str8_lit("rdi"), StringMatchFlag_CaseInsensitive)) { output_kind = OutputKind_RDI; log_infof("Output path has .rdi extension; performing `%S`\n", output_kind_info[output_kind].title); } else if(str8_match(str8_skip_last_dot(output_path), str8_lit("dump"), StringMatchFlag_CaseInsensitive) || str8_match(str8_skip_last_dot(output_path), str8_lit("txt"), StringMatchFlag_CaseInsensitive)) { output_kind = OutputKind_Dump; log_infof("Output path has .dump or .txt extension; performing `%S`\n", output_kind_info[output_kind].title); } else if(str8_match(str8_skip_last_dot(output_path), str8_lit("psym"), StringMatchFlag_CaseInsensitive) || str8_match(str8_skip_last_dot(output_path), str8_lit("psyms"), StringMatchFlag_CaseInsensitive)) { output_kind = OutputKind_Breakpad; log_infof("Output path has .psym or .psyms extension; performing `%S`\n", output_kind_info[output_kind].title); } } ////////////////////////////// //- rjf: print help preamble // if(lane_idx() == 0) { if(output_kind == OutputKind_Null || cmdline->inputs.node_count == 0) { fprintf(stderr, "%s\n", BUILD_TITLE); fprintf(stderr, "%s\n\n", BUILD_VERSION_STRING_LITERAL); if(output_kind != OutputKind_Null) { fprintf(stderr, "%.*s Help\n", str8_varg(output_kind_info[output_kind].title)); fprintf(stderr, "To see top-level options for radbin, run the binary with no arguments.\n\n"); } fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); } } lane_sync(); ////////////////////////////// //- rjf: perform operation based on output kind // String8List output_blobs = {0}; switch(output_kind) { //////////////////////////// //- rjf: no output kind -> nothing to do. output help information to user // default: case OutputKind_Null: if(lane_idx() == 0) { fprintf(stderr, "USAGE EXAMPLES\n\n"); fprintf(stderr, "radbin --rdi program.exe\n"); fprintf(stderr, "Find the debug info for `program.exe`, if any, and converts it to RDI.\n\n"); fprintf(stderr, "radbin program.pdb --out:program.rdi\n"); fprintf(stderr, "Converts `program.pdb` to RDI, and stores it in `program.rdi`.\n\n"); fprintf(stderr, "radbin --dump program.rdi\n"); fprintf(stderr, "Outputs the textual dump of the debug information stored in `program.rdi`.\n\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "DESCRIPTION\n\n"); fprintf(stderr, "This utility provides a number of operations relating to executable image and\n"); fprintf(stderr, "debug information formats. It can convert debug information to the RAD Debug\n"); fprintf(stderr, "Info (.rdi) format. It can also parse and dump textualized contents of several\n"); fprintf(stderr, "formats, including PDB, PE, ELF, and RDI. It also supports converting debug\n"); fprintf(stderr, "information to the textual Breakpad format.\n\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "ARGUMENTS\n\n"); fprintf(stderr, "--rdi Specifies that the utility should convert debug information\n"); fprintf(stderr, " data to the RAD Debug Info (.rdi) format.\n\n"); fprintf(stderr, "--dump Specifies that the utility should dump textualized contents of\n"); fprintf(stderr, " all input files.\n\n"); fprintf(stderr, "--breakpad Specifies that the utility should convert debug information\n"); fprintf(stderr, " data to the textual Breakpad format.\n\n"); fprintf(stderr, "--out: Specifies the path to which output data should be written. If\n"); fprintf(stderr, " not specified, the utility will choose a fallback. If dumping\n"); fprintf(stderr, " textual contents, the utility will write to `stdout`. If\n"); fprintf(stderr, " converting to another format, the utility will form a path by\n"); fprintf(stderr, " changing the extension of input files accordingly.\n\n"); fprintf(stderr, "--deterministic Turns off all sources of non-determinism in generated output,\n"); fprintf(stderr, " like build names, versions, and dates.\n\n"); fprintf(stderr, "--verbose Outputs all log information collected during execution.\n\n"); fprintf(stderr, "There are also operation-specific arguments. To see them, run this binary with\n"); fprintf(stderr, "the operation selected, with no additional inputs (e.g. `radbin --rdi`).\n\n"); }break; //////////////////////////// //- rjf: RDI, Breakpad -> conversion based on inputs // case OutputKind_RDI: case OutputKind_Breakpad: { //- rjf: no inputs => help if(lane_idx() == 0 && cmdline->inputs.node_count == 0) switch(output_kind) { default: case OutputKind_RDI: { fprintf(stderr, "ARGUMENTS\n\n"); fprintf(stderr, "--compress Compresses the RDI file's contents.\n"); fprintf(stderr, "\n"); fprintf(stderr, "--only: Specifies that only the named subsets of debug\n"); fprintf(stderr, " information should be generated. See below for\n"); fprintf(stderr, " a list of valid debug info subset names.\n"); fprintf(stderr, "\n"); fprintf(stderr, "--omit: Specifies that the named subsets of debug\n"); fprintf(stderr, " information should not be generated. See below\n"); fprintf(stderr, " for a list of valid debug info subset names.\n"); fprintf(stderr, "\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "RAD DEBUG INFO SUBSET NAMES\n\n"); #define X(name, name_lower) fprintf(stderr, " - " #name_lower "\n"); #define Y(name, name_lower) X(name, name_lower) RDIM_Subset_XList #undef X #undef Y }break; case OutputKind_Breakpad: { fprintf(stderr, "All input files specified on the command line will be dumped. The following\n"); fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n"); } } //- rjf: unpack subset flags RDIM_SubsetFlags subset_flags = 0xffffffff; switch(output_kind) { default:{}break; case OutputKind_RDI: { String8List only_names = cmd_line_strings(cmdline, str8_lit("only")); if(only_names.node_count != 0) { subset_flags = 0; } for(String8Node *n = only_names.first; n != 0; n = n->next) { if(0){} #define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags |= RDIM_SubsetFlag_##name; } #define Y(name, name_lower) X(name, name_lower) RDIM_Subset_XList #undef X #undef Y } String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit")); for(String8Node *n = omit_names.first; n != 0; n = n->next) { if(0){} #define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags &= ~RDIM_SubsetFlag_##name; } #define Y(name, name_lower) X(name, name_lower) RDIM_Subset_XList #undef X #undef Y } }break; case OutputKind_Breakpad: { subset_flags = (RDIM_SubsetFlag_Units|RDIM_SubsetFlag_Procedures|RDIM_SubsetFlag_Scopes|RDIM_SubsetFlag_LineInfo|RDIM_SubsetFlag_InlineLineInfo); }break; } //- rjf: convert inputs to RDI info B32 convert_done = 0; RDIM_BakeParams pdb_bake_params = {0}; RDIM_BakeParams dwarf_bake_params = {0}; { //- rjf: PE inputs w/ DWARF, or ELF inputs => DWARF -> RDI conversion B32 pe_w_dwarf = (input_files_from_format_table[RB_FileFormat_PE].count != 0 && input_files_from_format_table[RB_FileFormat_PE].first->v->format_flags & RB_FileFormatFlag_HasDWARF); B32 elf_w_dwarf = (input_files_from_format_table[RB_FileFormat_ELF32].count != 0 || input_files_from_format_table[RB_FileFormat_ELF64].count != 0); if(pe_w_dwarf || elf_w_dwarf) { convert_done = 1; if(0){} else if(pe_w_dwarf) { log_infof("PEs w/ DWARF specified; converting DWARF data to RDI\n"); } else if(elf_w_dwarf) { log_infof("ELFs specified; converting DWARF data to RDI\n"); } // rjf: convert D2R_ConvertParams convert_params = {0}; { B32 got_exe = 0; B32 got_dbg = 0; if(!got_exe && !got_dbg) { for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_PE].first; n != 0; n = n->next) { if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) { got_exe = 1; got_dbg = 1; convert_params.dbg_name = n->v->path; convert_params.dbg_data = n->v->data; convert_params.exe_name = n->v->path; convert_params.exe_data = n->v->data; convert_params.exe_kind = ExecutableImageKind_CoffPe; break; } } } if(!got_exe) { for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) { got_exe = 1; convert_params.exe_name = n->v->path; convert_params.exe_data = n->v->data; convert_params.exe_kind = ExecutableImageKind_Elf32; if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) { break; } } } if(!got_exe) { for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) { got_exe = 1; convert_params.exe_name = n->v->path; convert_params.exe_data = n->v->data; convert_params.exe_kind = ExecutableImageKind_Elf64; if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) { break; } } } if(!got_dbg) { for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) { if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) { got_dbg = 1; convert_params.dbg_name = n->v->path; convert_params.dbg_data = n->v->data; break; } } } if(!got_dbg) { for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) { if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) { got_dbg = 1; convert_params.dbg_name = n->v->path; convert_params.dbg_data = n->v->data; break; } } } convert_params.subset_flags = subset_flags; convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); } ProfScope("convert") dwarf_bake_params = d2r_convert(arena, &convert_params); } //- rjf: PDB inputs => PDB -> RDI conversion if(input_files_from_format_table[RB_FileFormat_PDB].count != 0) { convert_done = 1; log_infof("PDBs specified; converting PDB data to RDI\n"); // rjf: get EXE/PDB file data RB_File *exe_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PE]); RB_File *pdb_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PDB]); String8 exe_path = exe_file->path; String8 pdb_path = pdb_file->path; String8 exe_data = exe_file->data; String8 pdb_data = pdb_file->data; // rjf: convert P2R_ConvertParams convert_params = {0}; { convert_params.input_pdb_name = pdb_path; convert_params.input_exe_name = exe_path; convert_params.input_pdb_data = pdb_data; convert_params.input_exe_data = exe_data; convert_params.subset_flags = subset_flags; convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); } ProfScope("convert") pdb_bake_params = p2r_convert(arena, &convert_params); } } lane_sync(); //- rjf: join conversion artifacts RDIM_BakeParams *bake_params = 0; if(lane_idx() == 0) { bake_params = push_array(arena, RDIM_BakeParams, 1); rdim_bake_params_concat_in_place(bake_params, &pdb_bake_params); rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params); } lane_sync_u64(&bake_params, 0); //- rjf: no output path? -> pick one based on input files if(output_path.size == 0) { String8 output_path__noext = {0}; if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PDB])->path); } if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PE])->path); } if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_ELF64])->path); } if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_ELF32])->path); } switch(output_kind) { default:{}break; case OutputKind_RDI: { output_path = push_str8f(arena, "%S.rdi", output_path__noext); }break; case OutputKind_Breakpad: { output_path = push_str8f(arena, "%S.psym", output_path__noext); }break; } } //- rjf: no viable input paths if(!convert_done && cmdline->inputs.node_count != 0) { log_user_errorf("Could not load debug info from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF debug info."); } //- rjf: bake RDIM_BakeResults bake_results = {0}; ProfScope("bake") { bake_results = rdim_bake(arena, bake_params); } //- rjf: convert done => generate output if(convert_done) switch(output_kind) { default:{}break; //- rjf: generate RDI blobs case OutputKind_RDI: { // rjf: serialize RDIM_SerializedSectionBundle *serialized_section_bundle = 0; ProfScope("serialize") if(lane_idx() == 0) { serialized_section_bundle = push_array(arena, RDIM_SerializedSectionBundle, 1); serialized_section_bundle[0] = rdim_serialized_section_bundle_from_bake_results(&bake_results); } lane_sync_u64(&serialized_section_bundle, 0); // rjf: compress RDIM_SerializedSectionBundle serialized_section_bundle__compressed = serialized_section_bundle[0]; if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") { serialized_section_bundle__compressed = rdim_compress(arena, serialized_section_bundle); } // rjf: serialize String8List blobs = rdim_file_blobs_from_section_bundle(arena, &serialized_section_bundle__compressed); str8_list_concat_in_place(&output_blobs, &blobs); }break; //- rjf: generate breakpad text case OutputKind_Breakpad: { //- rjf: set up shared state typedef struct P2B_Shared P2B_Shared; struct P2B_Shared { String8List dump; String8List *lane_chunk_file_dumps; String8List *lane_chunk_func_dumps; }; local_persist P2B_Shared *p2b_shared = 0; if(lane_idx() == 0) { p2b_shared = push_array(arena, P2B_Shared, 1); p2b_shared->lane_chunk_file_dumps = push_array(arena, String8List, lane_count()*bake_params->src_files.chunk_count); p2b_shared->lane_chunk_func_dumps = push_array(arena, String8List, lane_count()*bake_params->procedures.chunk_count); } lane_sync(); //- rjf: dump MODULE record if(lane_idx() == 0) { // rjf: pick name to identify module String8 module_name_string = bake_params->top_level_info.exe_name; if(module_name_string.size == 0 && input_files.first != 0) { module_name_string = input_files.first->v->path; } // rjf: pick string for unique code String8 unique_identifier_string = {0}; if(unique_identifier_string.size == 0 && bake_params->top_level_info.exe_hash != 0) { unique_identifier_string = str8f(arena, "%I64x", bake_params->top_level_info.exe_hash); } if(unique_identifier_string.size == 0) { Temp scratch = scratch_begin(&arena, 1); String8 msf_data = input_files.first->v->data; MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data); String8 info_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Info); PDB_Info *info = pdb_info_from_data(scratch.arena, info_data); if(info != 0 && info_data.size >= sizeof(PDB_InfoHeader)) { PDB_InfoHeader *info_header = (PDB_InfoHeader *)info_data.str; Guid guid = info->auth_guid; unique_identifier_string = str8f(arena, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%u", guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7], info_header->age); } scratch_end(scratch); } // rjf: push record str8_list_pushf(arena, &p2b_shared->dump, "MODULE windows x86_64 %S %S\n", unique_identifier_string, module_name_string); } //- rjf: dump FILE records ProfScope("dump FILE records") { U64 chunk_idx = 0; for EachNode(n, RDIM_SrcFileChunkNode, bake_params->src_files.first) { Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { U64 file_idx = rdim_idx_from_src_file(&n->v[idx]); String8 src_path = n->v[idx].path; str8_list_pushf(arena, &p2b_shared->lane_chunk_file_dumps[lane_idx()*bake_params->src_files.chunk_count + chunk_idx], "FILE %I64u %S\n", file_idx, src_path); } chunk_idx += 1; } } //- rjf: dump FUNC records ProfScope("dump FUNC records") { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, bake_params->procedures.first) { String8List *out = &p2b_shared->lane_chunk_func_dumps[lane_idx()*bake_params->procedures.chunk_count + chunk_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. RDIM_Symbol *proc = &n->v[idx]; RDIM_Scope *root_scope = proc->root_scope; if(root_scope != 0 && root_scope->voff_ranges.first != 0) { // rjf: dump function record RDIM_Rng1U64 voff_range = root_scope->voff_ranges.first->v; str8_list_pushf(arena, out, "FUNC %I64x %I64x %I64x %S\n", voff_range.min, voff_range.max-voff_range.min, 0ull, proc->name); // rjf: dump function lines U64 unit_idx = rdi_vmap_idx_from_voff(bake_results.unit_vmap.vmap.vmap, bake_results.unit_vmap.vmap.count, voff_range.min); if(0 < unit_idx && unit_idx <= bake_results.units.units_count) { U32 line_table_idx = bake_results.units.units[unit_idx].line_table_idx; if(0 < line_table_idx && line_table_idx <= bake_results.line_tables.line_tables_count) { // rjf: unpack unit line info RDI_LineTable *line_table = &bake_results.line_tables.line_tables[line_table_idx]; RDI_ParsedLineTable line_info = { bake_results.line_tables.line_table_voffs + line_table->voffs_base_idx, bake_results.line_tables.line_table_lines + line_table->lines_base_idx, 0, line_table->lines_count, 0 }; for(U64 voff = voff_range.min, last_voff = 0; voff < voff_range.max && voff > last_voff;) { RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); if(line_info_idx < line_info.count) { RDI_Line *line = &line_info.lines[line_info_idx]; U64 line_voff_min = line_info.voffs[line_info_idx]; U64 line_voff_opl = line_info.voffs[line_info_idx+1]; if(line->file_idx != 0) { str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", line_voff_min, line_voff_opl-line_voff_min, (U64)line->line_num, (U64)line->file_idx); } last_voff = voff; voff = line_voff_opl; } else { break; } } } } } } chunk_idx += 1; } } //- rjf: join lane_sync(); if(lane_idx() == 0) { for EachIndex(chunk_idx, bake_params->src_files.chunk_count) { for EachIndex(ln_idx, lane_count()) { str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_chunk_file_dumps[ln_idx*bake_params->src_files.chunk_count + chunk_idx]); } } for EachIndex(chunk_idx, bake_params->procedures.chunk_count) { for EachIndex(ln_idx, lane_count()) { str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_chunk_func_dumps[ln_idx*bake_params->procedures.chunk_count + chunk_idx]); } } } lane_sync(); output_blobs = p2b_shared->dump; }break; } }break; //////////////////////////// //- rjf: dump -> textual dump of inputs // case OutputKind_Dump: { B32 deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); //- rjf: no inputs => help if(lane_idx() == 0 && cmdline->inputs.node_count == 0) { fprintf(stderr, "All input files specified on the command line will be dumped. Currently, only\n"); fprintf(stderr, "RDI files are supported.\n\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "ARGUMENTS\n\n"); fprintf(stderr, "--only: Specifies that only the named subsets should\n"); fprintf(stderr, " be dumped. See below for a list of valid\n"); fprintf(stderr, " subset names.\n"); fprintf(stderr, "\n"); fprintf(stderr, "--omit: Specifies that the named subsets should not\n"); fprintf(stderr, " be dumped. See below for a list of valid\n"); fprintf(stderr, " subset names.\n"); fprintf(stderr, "\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "RAD DEBUG INFO SUBSET NAMES\n\n"); #define X(name, name_lower, title) fprintf(stderr, " - " #name_lower "\n"); RDI_DumpSubset_XList #undef X fprintf(stderr, "\n"); fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); fprintf(stderr, "DWARF INFO SUBSET NAMES\n\n"); #define X(name, name_lower, title) fprintf(stderr, " - " #name_lower "\n"); DW_DumpSubset_XList #undef X fprintf(stderr, "\n"); } //- rjf: unpack dump subset flags RDI_DumpSubsetFlags rdi_dump_subset_flags = RDI_DumpSubsetFlag_All; DW_DumpSubsetFlags dw_dump_subset_flags = DW_DumpSubsetFlag_All; EH_DumpSubsetFlags eh_dump_subset_flags = EH_DumpSubsetFlag_All; ELF_DumpSubsetFlags elf_dump_subset_flags = ELF_DumpSubsetFlag_All; { String8List only_names = cmd_line_strings(cmdline, str8_lit("only")); if(only_names.node_count != 0) { rdi_dump_subset_flags = 0; dw_dump_subset_flags = 0; eh_dump_subset_flags = 0; } for(String8Node *n = only_names.first; n != 0; n = n->next) { if(0){} #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { rdi_dump_subset_flags |= RDI_DumpSubsetFlag_##name; } RDI_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { dw_dump_subset_flags |= DW_DumpSubsetFlag_##name; } DW_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { eh_dump_subset_flags |= EH_DumpSubsetFlag_##name; } EH_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { elf_dump_subset_flags |= ELF_DumpSubsetFlag_##name; } ELF_DumpSubset_XList #undef X } String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit")); for(String8Node *n = omit_names.first; n != 0; n = n->next) { if(0){} #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { rdi_dump_subset_flags &= ~RDI_DumpSubsetFlag_##name; } RDI_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { dw_dump_subset_flags &= ~DW_DumpSubsetFlag_##name; } DW_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { eh_dump_subset_flags &= ~EH_DumpSubsetFlag_##name; } EH_DumpSubset_XList #undef X #define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { elf_dump_subset_flags &= ~ELF_DumpSubsetFlag_##name; } ELF_DumpSubset_XList #undef X } } //- rjf: dump input files in order for(RB_FileNode *n = input_files.first; n != 0; n = n->next) { RB_File *f = n->v; if(lane_idx() == 0) { str8_list_pushf(arena, &output_blobs, "// %S (%S)\n\n", deterministic ? str8_skip_last_slash(f->path) : f->path, f->format ? rb_file_format_display_name_table[f->format] : str8_lit("Unsupported format")); } lane_sync(); //- rjf: unpack file parses Arch arch = Arch_Null; PE_BinInfo pe = {0}; ELF_Bin elf = {0}; DW_Input dw = {0}; U64 eh_frame_hdr_vaddr = 0; U64 eh_frame_vaddr = 0; String8 eh_frame_hdr = {0}; String8 eh_frame = {0}; { if(f->format == RB_FileFormat_PE) { pe = pe_bin_info_from_data(arena, f->data); arch = pe.arch; } if(f->format == RB_FileFormat_ELF32 || f->format == RB_FileFormat_ELF64) { elf = elf_bin_from_data(arena, f->data); arch = arch_from_elf_machine(elf.hdr.e_machine); for EachIndex(sect_idx, elf.hdr.e_shnum) { ELF_Shdr64 *shdr = &elf.shdrs.v[sect_idx]; String8 name = elf_name_from_shdr64(f->data, &elf, shdr); if (str8_match(name, str8_lit(".eh_frame_hdr"), 0)) { eh_frame_hdr = str8_substr(f->data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size)); eh_frame_hdr_vaddr = shdr->sh_addr; } else if(str8_match(name, str8_lit(".eh_frame"), 0)) { eh_frame = str8_substr(f->data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size)); eh_frame_vaddr = shdr->sh_addr; } } } if(f->format_flags & RB_FileFormatFlag_HasDWARF) { if(f->format == RB_FileFormat_PE) { String8 raw_sections = str8_substr(f->data, pe.section_table_range); U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader); COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str; String8 string_table = str8_substr(f->data, pe.string_table_range); dw = dw_input_from_coff_section_table(arena, f->data, string_table, section_count, section_table); } else if(f->format == RB_FileFormat_ELF32 || f->format == RB_FileFormat_ELF64) { dw = dw_input_from_elf_bin(arena, f->data, &elf); } } } //- rjf: dump file info based on format switch(f->format) { default:{}break; //- rjf: PDB case RB_FileFormat_PDB: { // TODO(rjf) }break; //- rjf: PE case RB_FileFormat_PE: { // TODO(rjf) }break; //- rjf: COFF OBJ case RB_FileFormat_COFF_OBJ: { // TODO(rjf) }break; //- rjf: COFF big OBJ case RB_FileFormat_COFF_BigOBJ: { // TODO(rjf) }break; //- rjf: COFF archive case RB_FileFormat_COFF_Archive: case RB_FileFormat_COFF_ThinArchive: { // TODO(rjf) }break; //- rjf: ELF case RB_FileFormat_ELF32: case RB_FileFormat_ELF64: { String8List elf_strings = elf_dump(arena, f->data, elf_dump_subset_flags); str8_list_concat_in_place(&output_blobs, &elf_strings); }break; //- rjf: RDI file case RB_FileFormat_RDI: { RDI_Parsed rdi = {0}; RDI_ParseStatus rdi_status = rdi_parse(f->data.str, f->data.size, &rdi); U64 decompressed_size = rdi_decompressed_size_from_parsed(&rdi); if(decompressed_size > rdi.raw_data_size) { U8 *decompressed_data = push_array_no_zero(arena, U8, decompressed_size); rdi_decompress_parsed(decompressed_data, decompressed_size, &rdi); rdi_status = rdi_parse(decompressed_data, decompressed_size, &rdi); } switch(rdi_status) { default:{}break; case RDI_ParseStatus_HeaderDoesNotMatch: {log_user_errorf("RDI parse failure: header does not match\n");}break; case RDI_ParseStatus_UnsupportedVersionNumber:{log_user_errorf("RDI parse failure: unsupported version\n");}break; case RDI_ParseStatus_InvalidDataSecionLayout: {log_user_errorf("RDI parse failure: invalid data section layout\n");}break; case RDI_ParseStatus_Good: { String8List dump = rdi_dump_list_from_parsed(arena, &rdi, rdi_dump_subset_flags); if(lane_idx() == 0) { str8_list_concat_in_place(&output_blobs, &dump); } }break; } }break; } //- rjf: dump file extension info if(f->format_flags & RB_FileFormatFlag_HasDWARF) { if(lane_idx() == 0) { str8_list_pushf(arena, &output_blobs, "// %S (%S) (DWARF)\n\n", deterministic ? str8_skip_last_slash(f->path) : f->path, f->format ? rb_file_format_display_name_table[f->format] : str8_lit("Unsupported format")); } lane_sync(); { String8List dump = dw_dump_list_from_sections(arena, &dw, arch, dw_dump_subset_flags); if(lane_idx() == 0) { str8_list_concat_in_place(&output_blobs, &dump); } } } if(eh_dump_subset_flags) { if(lane_idx() == 0) { String8List dump = eh_dump_list_from_data(arena, arch, eh_frame_hdr_vaddr, eh_frame_vaddr, eh_frame_hdr, eh_frame, eh_dump_subset_flags); str8_list_concat_in_place(&output_blobs, &dump); } lane_sync(); } } }break; } ////////////////////////////// //- rjf: write outputs // if(lane_idx() == 0) { if(output_path.size != 0) ProfScope("write outputs [file]") { B32 is_written = os_write_data_list_to_file_path(output_path, output_blobs); if(is_written) { log_infof("Results written to %S", output_path); } else { log_user_errorf("ERROR: failed to write file %S\n", output_path); } } else ProfScope("write outputs [stdout]") { for(String8Node *n = output_blobs.first; n != 0; n = n->next) { for(U64 off = 0; off < n->string.size;) { U64 size_to_write = Min(n->string.size - off, GB(2)); fwrite(n->string.str + off, size_to_write, 1, stdout); off += size_to_write; } } log_info(str8_lit("Results written to stdout")); } } lane_sync(); ////////////////////////////// //- rjf: write info & errors // LogScopeResult log_scope = log_scope_end(arena); if(lane_idx() == 0) { if(cmd_line_has_flag(cmdline, str8_lit("verbose")) && log_scope.strings[LogMsgKind_Info].size != 0) { String8List lines = wrapped_lines_from_string(arena, log_scope.strings[LogMsgKind_Info], 80, 80, 0); for(String8Node *n = lines.first; n != 0; n = n->next) { fprintf(stderr, "%.*s\n", str8_varg(n->string)); } } if(log_scope.strings[LogMsgKind_UserError].size != 0) { String8List lines = wrapped_lines_from_string(arena, log_scope.strings[LogMsgKind_UserError], 80, 80, 0); for(String8Node *n = lines.first; n != 0; n = n->next) { fprintf(stderr, "%.*s\n", str8_varg(n->string)); } } } } ================================================ FILE: src/radbin/radbin.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADBIN_H #define RADBIN_H //////////////////////////////// //~ rjf: Generated Code #include "radbin/generated/radbin.meta.h" //////////////////////////////// //~ rjf: Thread Parameters typedef struct RB_ThreadParams RB_ThreadParams; struct RB_ThreadParams { CmdLine *cmdline; LaneCtx lane_ctx; }; //////////////////////////////// //~ rjf: File Types typedef U32 RB_FileFormatFlags; enum { RB_FileFormatFlag_HasDWARF = (1<<0), }; typedef struct RB_File RB_File; struct RB_File { RB_FileFormat format; RB_FileFormatFlags format_flags; String8 path; String8 data; }; typedef struct RB_FileNode RB_FileNode; struct RB_FileNode { RB_FileNode *next; RB_File *v; }; typedef struct RB_FileList RB_FileList; struct RB_FileList { RB_FileNode *first; RB_FileNode *last; U64 count; }; read_only global RB_File rb_file_nil = {0}; #define rb_file_list_first(list) ((list)->first ? (list)->first->v : &rb_file_nil) //////////////////////////////// //~ rjf: Cross-Thread State typedef struct RB_Shared RB_Shared; struct RB_Shared { RB_FileList input_files; RB_FileList input_files_from_format_table[RB_FileFormat_COUNT]; }; //////////////////////////////// //~ rjf: Globals global RB_Shared *rb_shared = 0; //////////////////////////////// //~ rjf: Top-Level Entry Points internal void rb_entry_point(CmdLine *cmdline); internal void rb_thread_entry_point(void *p); #endif //RADBIN_H ================================================ FILE: src/radbin/radbin.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name display_name) RB_FileFormatTable: { { PDB "PDB" } { PE "PE" } { COFF_OBJ "COFF (OBJ)" } { COFF_BigOBJ "COFF (Big OBJ)" } { COFF_Archive "COFF (Archive)" } { COFF_ThinArchive "COFF (Thin Archive)" } { ELF32 "ELF32" } { ELF64 "ELF64" } { RDI "RDI" } } @enum RB_FileFormat: { Null, @expand(RB_FileFormatTable a) `$(a.name)`, COUNT } @data(String8) rb_file_format_display_name_table: { `{0}`, @expand(RB_FileFormatTable a) `str8_lit_comp("$(a.display_name)")`, } ================================================ FILE: src/radbin/radbin_main.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Build Options #define BUILD_TITLE "Epic Games Tools (R) RAD CLI Binary Utility" #define BUILD_CONSOLE_INTERFACE 1 //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "linker/hash_table.h" #include "os/os_inc.h" #include "rdi/rdi_local.h" #include "rdi_make/rdi_make_local.h" #include "coff/coff_inc.h" #include "pe/pe.h" #include "elf/elf.h" #include "gnu/gnu.h" #include "elf/elf_parse.h" #include "elf/elf_dump.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "dwarf/dwarf_inc.h" #include "msf/msf.h" #include "msf/msf_parse.h" #include "pdb/pdb.h" #include "pdb/pdb_parse.h" #include "pdb/pdb_stringize.h" #include "rdi_from_coff/rdi_from_coff.h" #include "rdi_from_elf/rdi_from_elf.h" #include "rdi_from_pdb/rdi_from_pdb.h" #include "rdi_from_dwarf/rdi_from_dwarf.h" #include "radbin/radbin.h" //- rjf: [c] #include "base/base_inc.c" #include "linker/hash_table.c" #include "os/os_inc.c" #include "rdi/rdi_local.c" #include "rdi_make/rdi_make_local.c" #include "coff/coff_inc.c" #include "pe/pe.c" #include "elf/elf.c" #include "gnu/gnu.c" #include "elf/elf_parse.c" #include "elf/elf_dump.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "dwarf/dwarf_inc.c" #include "msf/msf.c" #include "msf/msf_parse.c" #include "pdb/pdb.c" #include "pdb/pdb_parse.c" #include "pdb/pdb_stringize.c" #include "rdi_from_coff/rdi_from_coff.c" #include "rdi_from_elf/rdi_from_elf.c" #include "rdi_from_pdb/rdi_from_pdb.c" #include "rdi_from_dwarf/rdi_from_dwarf.c" #include "radbin/radbin.c" //////////////////////////////// //~ rjf: Entry Point internal void entry_point(CmdLine *cmdline) { rb_entry_point(cmdline); } ================================================ FILE: src/raddbg/generated/raddbg.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 rd_tab_fast_path_view_name_table[25] = { str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("watch"), str8_lit_comp("text"), str8_lit_comp("text"), str8_lit_comp("disasm"), str8_lit_comp("memory"), str8_lit_comp("bitmap"), str8_lit_comp("color"), str8_lit_comp("geo3d"), }; String8 rd_tab_fast_path_query_name_table[25] = { str8_lit_comp(""), str8_lit_comp("query:locals"), str8_lit_comp("query:registers"), str8_lit_comp("query:globals"), str8_lit_comp("query:thread_locals"), str8_lit_comp("query:types"), str8_lit_comp("query:procedures"), str8_lit_comp("query:call_stack"), str8_lit_comp("query:targets"), str8_lit_comp("query:breakpoints"), str8_lit_comp("query:watch_pins"), str8_lit_comp("query:debug_infos"), str8_lit_comp("query:threads"), str8_lit_comp("query:processes"), str8_lit_comp("query:machines"), str8_lit_comp("query:modules"), str8_lit_comp("query:file_path_maps"), str8_lit_comp("query:type_views"), str8_lit_comp("query:output"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), }; RD_VocabInfo rd_vocab_info_table[358] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, {str8_lit_comp("watch_pin"), str8_lit_comp("watch_pins"), str8_lit_comp("Watch Pin"), str8_lit_comp("Watch Pins"), RD_IconKind_Pin}, {str8_lit_comp("debug_info"), str8_lit_comp("debug_infos"), str8_lit_comp("Debug Info"), str8_lit_comp("Debug Info"), RD_IconKind_Module}, {str8_lit_comp("watch"), str8_lit_comp("watches"), str8_lit_comp("Watch"), str8_lit_comp("Watches"), RD_IconKind_Binoculars}, {str8_lit_comp("view"), str8_lit_comp("views"), str8_lit_comp("View"), str8_lit_comp("Views"), RD_IconKind_Binoculars}, {str8_lit_comp("breakpoint"), str8_lit_comp("breakpoints"), str8_lit_comp("Breakpoint"), str8_lit_comp("Breakpoints"), RD_IconKind_CircleFilled}, {str8_lit_comp("condition"), str8_lit_comp("conditions"), str8_lit_comp("Condition"), str8_lit_comp("Conditions"), RD_IconKind_Null}, {str8_lit_comp("location"), str8_lit_comp("locations"), str8_lit_comp("Location"), str8_lit_comp("Locations"), RD_IconKind_Null}, {str8_lit_comp("source_location"), str8_lit_comp("source_locations"), str8_lit_comp("Source Location"), str8_lit_comp("Source Locations"), RD_IconKind_Null}, {str8_lit_comp("address_location"), str8_lit_comp("address_locations"), str8_lit_comp("Address Location"), str8_lit_comp("Address Locations"), RD_IconKind_Null}, {str8_lit_comp("target"), str8_lit_comp("targets"), str8_lit_comp("Target"), str8_lit_comp("Targets"), RD_IconKind_Target}, {str8_lit_comp("color"), str8_lit_comp("colors"), str8_lit_comp("Color"), str8_lit_comp("Colors"), RD_IconKind_Palette}, {str8_lit_comp("theme_color"), str8_lit_comp("theme_colors"), str8_lit_comp("Theme Color"), str8_lit_comp("Theme Colors"), RD_IconKind_Palette}, {str8_lit_comp("executable"), str8_lit_comp("executables"), str8_lit_comp("Executable"), str8_lit_comp("Executables"), RD_IconKind_Module}, {str8_lit_comp("arguments"), str8_lit_comp("arguments"), str8_lit_comp("Arguments"), str8_lit_comp("Arguments"), RD_IconKind_Null}, {str8_lit_comp("exe"), str8_lit_comp("exes"), str8_lit_comp("Executable"), str8_lit_comp("Executables"), RD_IconKind_Module}, {str8_lit_comp("dbg"), str8_lit_comp("dbgs"), str8_lit_comp("Debug Info Path"), str8_lit_comp("Debug Info Paths"), RD_IconKind_Module}, {str8_lit_comp("vaddr_range"), str8_lit_comp("vaddr_ranges"), str8_lit_comp("Virtual Address Range"), str8_lit_comp("Virtual Address Ranges"), RD_IconKind_Null}, {str8_lit_comp("min"), str8_lit_comp("mins"), str8_lit_comp("Minimum"), str8_lit_comp("Minimums"), RD_IconKind_Null}, {str8_lit_comp("max"), str8_lit_comp("maxs"), str8_lit_comp("Maximum"), str8_lit_comp("Maximums"), RD_IconKind_Null}, {str8_lit_comp("working_directory"), str8_lit_comp("working_directories"), str8_lit_comp("Working Directory"), str8_lit_comp("Working Directories"), RD_IconKind_FolderClosedFilled}, {str8_lit_comp("entry_point"), str8_lit_comp("entry_points"), str8_lit_comp("Entry Point"), str8_lit_comp("Entry Points"), RD_IconKind_Null}, {str8_lit_comp("stdout_path"), str8_lit_comp("stdout_paths"), str8_lit_comp("Standard Output Path"), str8_lit_comp("Standard Output Paths"), RD_IconKind_Null}, {str8_lit_comp("stderr_path"), str8_lit_comp("stderr_paths"), str8_lit_comp("Standard Error Path"), str8_lit_comp("Standard Error Paths"), RD_IconKind_Null}, {str8_lit_comp("stdin_path"), str8_lit_comp("stdin_paths"), str8_lit_comp("Standard Input Path"), str8_lit_comp("Standard Input Paths"), RD_IconKind_Null}, {str8_lit_comp("window"), str8_lit_comp("windows"), str8_lit_comp("Window"), str8_lit_comp("Windows"), RD_IconKind_Window}, {str8_lit_comp("panel"), str8_lit_comp("panels"), str8_lit_comp("Panel"), str8_lit_comp("Panels"), RD_IconKind_Null}, {str8_lit_comp("tab"), str8_lit_comp("tabs"), str8_lit_comp("Tab"), str8_lit_comp("Tabs"), RD_IconKind_Null}, {str8_lit_comp("recent_project"), str8_lit_comp("recent_projects"), str8_lit_comp("Recent Project"), str8_lit_comp("Recent Projects"), RD_IconKind_Briefcase}, {str8_lit_comp("recent_file"), str8_lit_comp("recent_files"), str8_lit_comp("Recent File"), str8_lit_comp("Recent Files"), RD_IconKind_FileOutline}, {str8_lit_comp("src"), str8_lit_comp("srcs"), str8_lit_comp("Source"), str8_lit_comp("Sources"), RD_IconKind_Null}, {str8_lit_comp("dst"), str8_lit_comp("dsts"), str8_lit_comp("Destination"), str8_lit_comp("Destinations"), RD_IconKind_Null}, {str8_lit_comp("source"), str8_lit_comp("sources"), str8_lit_comp("Source"), str8_lit_comp("Sources"), RD_IconKind_Null}, {str8_lit_comp("dest"), str8_lit_comp("dests"), str8_lit_comp("Destination"), str8_lit_comp("Destinations"), RD_IconKind_Null}, {str8_lit_comp("conversion_task"), str8_lit_comp("conversion_tasks"), str8_lit_comp("Conversion Task"), str8_lit_comp("Conversion Tasks"), RD_IconKind_Null}, {str8_lit_comp("conversion_fail"), str8_lit_comp("conversion_fails"), str8_lit_comp("Conversion Fail"), str8_lit_comp("Conversion Fails"), RD_IconKind_Null}, {str8_lit_comp("lang"), str8_lit_comp("langs"), str8_lit_comp("Language"), str8_lit_comp("Languages"), RD_IconKind_Null}, {str8_lit_comp("arch"), str8_lit_comp("archs"), str8_lit_comp("Architecture"), str8_lit_comp("Architectures"), RD_IconKind_Null}, {str8_lit_comp("expr"), str8_lit_comp("exprs"), str8_lit_comp("Expression"), str8_lit_comp("Expressions"), RD_IconKind_Null}, {str8_lit_comp("expression"), str8_lit_comp("expressions"), str8_lit_comp("Expression"), str8_lit_comp("Expressions"), RD_IconKind_Null}, {str8_lit_comp("size"), str8_lit_comp("sizes"), str8_lit_comp("Size"), str8_lit_comp("Sizes"), RD_IconKind_Null}, {str8_lit_comp("count"), str8_lit_comp("counts"), str8_lit_comp("Count"), str8_lit_comp("Counts"), RD_IconKind_Null}, {str8_lit_comp("bool"), str8_lit_comp("bools"), str8_lit_comp("Boolean"), str8_lit_comp("Booleans"), RD_IconKind_Null}, {str8_lit_comp("w"), str8_lit_comp("ws"), str8_lit_comp("Width"), str8_lit_comp("Widths"), RD_IconKind_Null}, {str8_lit_comp("h"), str8_lit_comp("hs"), str8_lit_comp("Height"), str8_lit_comp("Heights"), RD_IconKind_Null}, {str8_lit_comp("fmt"), str8_lit_comp("fmts"), str8_lit_comp("Format"), str8_lit_comp("Formats"), RD_IconKind_Null}, {str8_lit_comp("addresses"), str8_lit_comp("addresses"), str8_lit_comp("Addresses"), str8_lit_comp("Addresses"), RD_IconKind_Null}, {str8_lit_comp("code_bytes"), str8_lit_comp("code_bytes"), str8_lit_comp("Code Bytes"), str8_lit_comp("Code Bytes"), RD_IconKind_Null}, {str8_lit_comp("vtx"), str8_lit_comp("vtxs"), str8_lit_comp("Vertex Buffer"), str8_lit_comp("Vertex Buffers"), RD_IconKind_Null}, {str8_lit_comp("vtx_size"), str8_lit_comp("vtx_sizes"), str8_lit_comp("Vertex Buffer Size"), str8_lit_comp("Vertex Buffer Sizes"), RD_IconKind_Null}, {str8_lit_comp("label"), str8_lit_comp("labels"), str8_lit_comp("Label"), str8_lit_comp("Labels"), RD_IconKind_Null}, {str8_lit_comp("thread"), str8_lit_comp("threads"), str8_lit_comp("Thread"), str8_lit_comp("Threads"), RD_IconKind_Thread}, {str8_lit_comp("threads"), str8_lit_comp(""), str8_lit_comp("Threads"), str8_lit_comp(""), RD_IconKind_Threads}, {str8_lit_comp("process"), str8_lit_comp("processes"), str8_lit_comp("Process"), str8_lit_comp("Processes"), RD_IconKind_Scheduler}, {str8_lit_comp("processes"), str8_lit_comp(""), str8_lit_comp("Processes"), str8_lit_comp(""), RD_IconKind_Scheduler}, {str8_lit_comp("machine"), str8_lit_comp("machines"), str8_lit_comp("Machine"), str8_lit_comp("Machines"), RD_IconKind_Machine}, {str8_lit_comp("module"), str8_lit_comp("modules"), str8_lit_comp("Module"), str8_lit_comp("Modules"), RD_IconKind_Module}, {str8_lit_comp("getting_started"), str8_lit_comp(""), str8_lit_comp("Getting Started"), str8_lit_comp(""), RD_IconKind_QuestionMark}, {str8_lit_comp("disasm"), str8_lit_comp(""), str8_lit_comp("Disassembly"), str8_lit_comp(""), RD_IconKind_Glasses}, {str8_lit_comp("text"), str8_lit_comp(""), str8_lit_comp("Text"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("type"), str8_lit_comp("types"), str8_lit_comp("Type"), str8_lit_comp("Types"), RD_IconKind_Null}, {str8_lit_comp("procedure"), str8_lit_comp("procedures"), str8_lit_comp("Procedure"), str8_lit_comp("Procedures"), RD_IconKind_Null}, {str8_lit_comp("global_variable"), str8_lit_comp("global_variables"), str8_lit_comp("Global Variable"), str8_lit_comp("Global Variables"), RD_IconKind_Null}, {str8_lit_comp("global"), str8_lit_comp("globals"), str8_lit_comp("Global"), str8_lit_comp("Globals"), RD_IconKind_Null}, {str8_lit_comp("thread_variable"), str8_lit_comp("thread_variables"), str8_lit_comp("Thread Variable"), str8_lit_comp("Thread Variables"), RD_IconKind_Null}, {str8_lit_comp("thread_local"), str8_lit_comp("thread_locals"), str8_lit_comp("Thread Local"), str8_lit_comp("Thread Locals"), RD_IconKind_Null}, {str8_lit_comp("call_stack"), str8_lit_comp("call_stacks"), str8_lit_comp("Call Stack"), str8_lit_comp("Call Stacks"), RD_IconKind_Thread}, {str8_lit_comp("output"), str8_lit_comp("outputs"), str8_lit_comp("Output"), str8_lit_comp("Outputs"), RD_IconKind_List}, {str8_lit_comp("scheduler"), str8_lit_comp("schedulers"), str8_lit_comp("Scheduler"), str8_lit_comp("Schedulers"), RD_IconKind_Scheduler}, {str8_lit_comp("register"), str8_lit_comp("registers"), str8_lit_comp("Register"), str8_lit_comp("Registers"), RD_IconKind_Null}, {str8_lit_comp("local"), str8_lit_comp("locals"), str8_lit_comp("Local"), str8_lit_comp("Locals"), RD_IconKind_Null}, {str8_lit_comp("memory"), str8_lit_comp("memories"), str8_lit_comp("Memory"), str8_lit_comp("Memories"), RD_IconKind_Grid}, {str8_lit_comp("hit_count"), str8_lit_comp("hit_counts"), str8_lit_comp("Hit Count"), str8_lit_comp("Hit Counts"), RD_IconKind_Null}, {str8_lit_comp("enabled"), str8_lit_comp(""), str8_lit_comp("Enabled"), str8_lit_comp("Enabled"), RD_IconKind_Null}, {str8_lit_comp("disabled"), str8_lit_comp(""), str8_lit_comp("Disabled"), str8_lit_comp("Disabled"), RD_IconKind_Null}, {str8_lit_comp("debug_subprocesses"), str8_lit_comp(""), str8_lit_comp("Debug Subprocesses"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("environment"), str8_lit_comp("environments"), str8_lit_comp("Environment"), str8_lit_comp("Environments"), RD_IconKind_Null}, {str8_lit_comp("frozen"), str8_lit_comp(""), str8_lit_comp("Frozen"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("id"), str8_lit_comp("ids"), str8_lit_comp("ID"), str8_lit_comp("IDs"), RD_IconKind_Null}, {str8_lit_comp("last_modified_time"), str8_lit_comp("last_modified_times"), str8_lit_comp("Last Modified Time"), str8_lit_comp("Last Modified Times"), RD_IconKind_Null}, {str8_lit_comp("creation_time"), str8_lit_comp("creation_times"), str8_lit_comp("Creation Time"), str8_lit_comp("Creation Times"), RD_IconKind_Null}, {str8_lit_comp("data"), str8_lit_comp("datas"), str8_lit_comp("Data"), str8_lit_comp("Datas"), RD_IconKind_Null}, {str8_lit_comp("unattached_processes"), str8_lit_comp(""), str8_lit_comp("Unattached Processes"), str8_lit_comp(""), RD_IconKind_Scheduler}, {str8_lit_comp("user"), str8_lit_comp("users"), str8_lit_comp("User"), str8_lit_comp("Users"), RD_IconKind_Person}, {str8_lit_comp("project"), str8_lit_comp("projects"), str8_lit_comp("Project"), str8_lit_comp("Projects"), RD_IconKind_Briefcase}, {str8_lit_comp("recent_project"), str8_lit_comp("recent_projects"), str8_lit_comp("Recent Project"), str8_lit_comp("Recent Projects"), RD_IconKind_Briefcase}, {str8_lit_comp("recent_file"), str8_lit_comp("recent_files"), str8_lit_comp("Recent File"), str8_lit_comp("Recent Files"), RD_IconKind_FileOutline}, {str8_lit_comp("show_addresses"), str8_lit_comp(""), str8_lit_comp("Show Addresses"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("show_code_bytes"), str8_lit_comp(""), str8_lit_comp("Show Code Bytes"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("show_source_lines"), str8_lit_comp(""), str8_lit_comp("Show Source Lines"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("show_symbol_names"), str8_lit_comp(""), str8_lit_comp("Show Symbol Names"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("show_line_numbers"), str8_lit_comp(""), str8_lit_comp("Show Line Numbers"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("syntax"), str8_lit_comp("syntaxes"), str8_lit_comp("Syntax"), str8_lit_comp("Syntaxes"), RD_IconKind_Null}, {str8_lit_comp("num_columns"), str8_lit_comp(""), str8_lit_comp("Number of Columns"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("bytes_per_cell"), str8_lit_comp(""), str8_lit_comp("Bytes Per Cell"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("bitmap"), str8_lit_comp("bitmaps"), str8_lit_comp("Bitmap"), str8_lit_comp("Bitmaps"), RD_IconKind_Bitmap}, {str8_lit_comp("geo3d"), str8_lit_comp(""), str8_lit_comp("Geometry (3D)"), str8_lit_comp(""), RD_IconKind_Cube}, {str8_lit_comp("address_range_size"), str8_lit_comp("address_range_sizes"), str8_lit_comp("Address Range Size"), str8_lit_comp("Address Range Sizes"), RD_IconKind_Null}, {str8_lit_comp("break_on_read"), str8_lit_comp(""), str8_lit_comp("Break On Read"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("break_on_write"), str8_lit_comp(""), str8_lit_comp("Break On Write"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("break_on_execute"), str8_lit_comp(""), str8_lit_comp("Break On Execution"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("yaw"), str8_lit_comp(""), str8_lit_comp("Yaw"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("pitch"), str8_lit_comp(""), str8_lit_comp("Pitch"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("zoom"), str8_lit_comp(""), str8_lit_comp("Zoom"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("font_size"), str8_lit_comp(""), str8_lit_comp("Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("row_height"), str8_lit_comp(""), str8_lit_comp("Row Height"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("tab_height"), str8_lit_comp(""), str8_lit_comp("Tab Height"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("rgba"), str8_lit_comp(""), str8_lit_comp("RGBA"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("path"), str8_lit_comp(""), str8_lit_comp("Path"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("guid"), str8_lit_comp(""), str8_lit_comp("GUID"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("launch_and_run"), str8_lit_comp(""), str8_lit_comp("Launch and Run"), str8_lit_comp(""), RD_IconKind_Play}, {str8_lit_comp("launch_and_step_into"), str8_lit_comp(""), str8_lit_comp("Launch and Step Into"), str8_lit_comp(""), RD_IconKind_PlayStepForward}, {str8_lit_comp("kill"), str8_lit_comp(""), str8_lit_comp("Kill"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("kill_all"), str8_lit_comp(""), str8_lit_comp("Kill All"), str8_lit_comp(""), RD_IconKind_Stop}, {str8_lit_comp("detach"), str8_lit_comp(""), str8_lit_comp("Detach"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("continue"), str8_lit_comp(""), str8_lit_comp("Continue"), str8_lit_comp(""), RD_IconKind_Play}, {str8_lit_comp("step_into_inst"), str8_lit_comp(""), str8_lit_comp("Step Into (Assembly)"), str8_lit_comp(""), RD_IconKind_StepInto}, {str8_lit_comp("step_over_inst"), str8_lit_comp(""), str8_lit_comp("Step Over (Assembly)"), str8_lit_comp(""), RD_IconKind_StepOver}, {str8_lit_comp("step_into_line"), str8_lit_comp(""), str8_lit_comp("Step Into (Line)"), str8_lit_comp(""), RD_IconKind_StepInto}, {str8_lit_comp("step_over_line"), str8_lit_comp(""), str8_lit_comp("Step Over (Line)"), str8_lit_comp(""), RD_IconKind_StepOver}, {str8_lit_comp("step_out"), str8_lit_comp(""), str8_lit_comp("Step Out"), str8_lit_comp(""), RD_IconKind_StepOut}, {str8_lit_comp("halt"), str8_lit_comp(""), str8_lit_comp("Halt"), str8_lit_comp(""), RD_IconKind_Pause}, {str8_lit_comp("soft_halt_refresh"), str8_lit_comp(""), str8_lit_comp("Soft Halt Refresh"), str8_lit_comp(""), RD_IconKind_Refresh}, {str8_lit_comp("set_thread_ip"), str8_lit_comp(""), str8_lit_comp("Set Thread IP"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("run_to_line"), str8_lit_comp(""), str8_lit_comp("Run To Line"), str8_lit_comp(""), RD_IconKind_Play}, {str8_lit_comp("run"), str8_lit_comp(""), str8_lit_comp("Run"), str8_lit_comp(""), RD_IconKind_Play}, {str8_lit_comp("restart"), str8_lit_comp(""), str8_lit_comp("Restart"), str8_lit_comp(""), RD_IconKind_Redo}, {str8_lit_comp("step_into"), str8_lit_comp(""), str8_lit_comp("Step Into"), str8_lit_comp(""), RD_IconKind_StepInto}, {str8_lit_comp("step_over"), str8_lit_comp(""), str8_lit_comp("Step Over"), str8_lit_comp(""), RD_IconKind_StepOver}, {str8_lit_comp("freeze_thread"), str8_lit_comp(""), str8_lit_comp("Freeze Thread"), str8_lit_comp(""), RD_IconKind_Locked}, {str8_lit_comp("thaw_thread"), str8_lit_comp(""), str8_lit_comp("Thaw Thread"), str8_lit_comp(""), RD_IconKind_Unlocked}, {str8_lit_comp("freeze_process"), str8_lit_comp(""), str8_lit_comp("Freeze Process"), str8_lit_comp(""), RD_IconKind_Locked}, {str8_lit_comp("thaw_process"), str8_lit_comp(""), str8_lit_comp("Thaw Process"), str8_lit_comp(""), RD_IconKind_Unlocked}, {str8_lit_comp("freeze_machine"), str8_lit_comp(""), str8_lit_comp("Freeze Machine"), str8_lit_comp(""), RD_IconKind_Locked}, {str8_lit_comp("thaw_machine"), str8_lit_comp(""), str8_lit_comp("Thaw Machine"), str8_lit_comp(""), RD_IconKind_Unlocked}, {str8_lit_comp("freeze_local_machine"), str8_lit_comp(""), str8_lit_comp("Freeze Local Machine"), str8_lit_comp(""), RD_IconKind_Machine}, {str8_lit_comp("thaw_local_machine"), str8_lit_comp(""), str8_lit_comp("Thaw Local Machine"), str8_lit_comp(""), RD_IconKind_Machine}, {str8_lit_comp("freeze_entity"), str8_lit_comp(""), str8_lit_comp("Freeze Entity"), str8_lit_comp(""), RD_IconKind_Unlocked}, {str8_lit_comp("thaw_entity"), str8_lit_comp(""), str8_lit_comp("Thaw Entity"), str8_lit_comp(""), RD_IconKind_Locked}, {str8_lit_comp("set_entity_color"), str8_lit_comp(""), str8_lit_comp("Set Entity Color"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("set_entity_name"), str8_lit_comp(""), str8_lit_comp("Set Entity Name"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("attach"), str8_lit_comp(""), str8_lit_comp("Attach"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("exit"), str8_lit_comp(""), str8_lit_comp("Exit"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("open_palette"), str8_lit_comp(""), str8_lit_comp("Open Palette"), str8_lit_comp(""), RD_IconKind_List}, {str8_lit_comp("run_command"), str8_lit_comp(""), str8_lit_comp("Run Command"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp("Run External Driver Text Command"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("os_event"), str8_lit_comp(""), str8_lit_comp("OS Event"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("select_thread"), str8_lit_comp(""), str8_lit_comp("Select Thread"), str8_lit_comp(""), RD_IconKind_Thread}, {str8_lit_comp("select_unwind"), str8_lit_comp(""), str8_lit_comp("Select Unwind"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("up_one_frame"), str8_lit_comp(""), str8_lit_comp("Up One Frame"), str8_lit_comp(""), RD_IconKind_UpArrow}, {str8_lit_comp("down_one_frame"), str8_lit_comp(""), str8_lit_comp("Down One Frame"), str8_lit_comp(""), RD_IconKind_DownArrow}, {str8_lit_comp("select_entity"), str8_lit_comp(""), str8_lit_comp("Select"), str8_lit_comp(""), RD_IconKind_RadioHollow}, {str8_lit_comp("deselect_entity"), str8_lit_comp(""), str8_lit_comp("Deselect"), str8_lit_comp(""), RD_IconKind_RadioFilled}, {str8_lit_comp("inc_window_font_size"), str8_lit_comp(""), str8_lit_comp("Increase Window Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("dec_window_font_size"), str8_lit_comp(""), str8_lit_comp("Decrease Window Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("inc_view_font_size"), str8_lit_comp(""), str8_lit_comp("Increase View Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("dec_view_font_size"), str8_lit_comp(""), str8_lit_comp("Decrease View Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("open_window"), str8_lit_comp(""), str8_lit_comp("Open New Window"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("window_settings"), str8_lit_comp(""), str8_lit_comp("Window Settings"), str8_lit_comp(""), RD_IconKind_Gear}, {str8_lit_comp("close_window"), str8_lit_comp(""), str8_lit_comp("Close Window"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("toggle_fullscreen"), str8_lit_comp(""), str8_lit_comp("Toggle Fullscreen"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("bring_to_front"), str8_lit_comp(""), str8_lit_comp("Bring To Front"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("popup_accept"), str8_lit_comp(""), str8_lit_comp("Popup Accept"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("popup_cancel"), str8_lit_comp(""), str8_lit_comp("Popup Cancel"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("reset_to_default_bindings"), str8_lit_comp(""), str8_lit_comp("Reset To Default Bindings"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("reset_to_default_panels"), str8_lit_comp(""), str8_lit_comp("Reset To Default Panel Layout"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("reset_to_compact_panels"), str8_lit_comp(""), str8_lit_comp("Reset To Compact Panel Layout"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("reset_to_simple_panels"), str8_lit_comp(""), str8_lit_comp("Reset To Simple Panel Layout"), str8_lit_comp(""), RD_IconKind_Window}, {str8_lit_comp("new_panel_left"), str8_lit_comp(""), str8_lit_comp("Split Panel Left"), str8_lit_comp(""), RD_IconKind_XSplit}, {str8_lit_comp("new_panel_up"), str8_lit_comp(""), str8_lit_comp("Split Panel Up"), str8_lit_comp(""), RD_IconKind_YSplit}, {str8_lit_comp("new_panel_right"), str8_lit_comp(""), str8_lit_comp("Split Panel Right"), str8_lit_comp(""), RD_IconKind_XSplit}, {str8_lit_comp("new_panel_down"), str8_lit_comp(""), str8_lit_comp("Split Panel Down"), str8_lit_comp(""), RD_IconKind_YSplit}, {str8_lit_comp("split_panel"), str8_lit_comp(""), str8_lit_comp("Split Panel"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("rotate_panel_columns"), str8_lit_comp(""), str8_lit_comp("Rotate Panel Columns"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("next_panel"), str8_lit_comp(""), str8_lit_comp("Focus Next Panel"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("prev_panel"), str8_lit_comp(""), str8_lit_comp("Focus Previous Panel"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("focus_panel"), str8_lit_comp(""), str8_lit_comp("Focus Panel"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("focus_panel_right"), str8_lit_comp(""), str8_lit_comp("Focus Panel Right"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("focus_panel_left"), str8_lit_comp(""), str8_lit_comp("Focus Panel Left"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("focus_panel_up"), str8_lit_comp(""), str8_lit_comp("Focus Panel Up"), str8_lit_comp(""), RD_IconKind_UpArrow}, {str8_lit_comp("focus_panel_down"), str8_lit_comp(""), str8_lit_comp("Focus Panel Down"), str8_lit_comp(""), RD_IconKind_DownArrow}, {str8_lit_comp("undo"), str8_lit_comp(""), str8_lit_comp("Undo"), str8_lit_comp(""), RD_IconKind_Undo}, {str8_lit_comp("redo"), str8_lit_comp(""), str8_lit_comp("Redo"), str8_lit_comp(""), RD_IconKind_Redo}, {str8_lit_comp("go_back"), str8_lit_comp(""), str8_lit_comp("Go Back"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("go_forward"), str8_lit_comp(""), str8_lit_comp("Go Forward"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("close_panel"), str8_lit_comp(""), str8_lit_comp("Close Panel"), str8_lit_comp(""), RD_IconKind_ClosePanel}, {str8_lit_comp("focus_tab"), str8_lit_comp(""), str8_lit_comp("Focus Tab"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("next_tab"), str8_lit_comp(""), str8_lit_comp("Focus Next Tab"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("prev_tab"), str8_lit_comp(""), str8_lit_comp("Focus Previous Tab"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("move_tab_right"), str8_lit_comp(""), str8_lit_comp("Move Tab Right"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("move_tab_left"), str8_lit_comp(""), str8_lit_comp("Move Tab Left"), str8_lit_comp(""), RD_IconKind_LeftArrow}, {str8_lit_comp("open_tab"), str8_lit_comp(""), str8_lit_comp("Open New Tab"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("build_tab"), str8_lit_comp(""), str8_lit_comp("Build Tab"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("duplicate_tab"), str8_lit_comp(""), str8_lit_comp("Duplicate Tab"), str8_lit_comp(""), RD_IconKind_Duplicate}, {str8_lit_comp("copy_tab_full_path"), str8_lit_comp(""), str8_lit_comp("Copy Full Path"), str8_lit_comp(""), RD_IconKind_Clipboard}, {str8_lit_comp("close_tab"), str8_lit_comp(""), str8_lit_comp("Close Tab"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("move_view"), str8_lit_comp(""), str8_lit_comp("Move View"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("tab_bar_top"), str8_lit_comp(""), str8_lit_comp("Anchor Tab Bar To Top"), str8_lit_comp(""), RD_IconKind_UpArrow}, {str8_lit_comp("tab_bar_bottom"), str8_lit_comp(""), str8_lit_comp("Anchor Tab Bar To Bottom"), str8_lit_comp(""), RD_IconKind_DownArrow}, {str8_lit_comp("tab_settings"), str8_lit_comp(""), str8_lit_comp("Tab Settings"), str8_lit_comp(""), RD_IconKind_Gear}, {str8_lit_comp("set_current_path"), str8_lit_comp(""), str8_lit_comp("Set Current Path"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("open"), str8_lit_comp(""), str8_lit_comp("Open"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("switch"), str8_lit_comp(""), str8_lit_comp("Switch"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("switch_to_partner_file"), str8_lit_comp(""), str8_lit_comp("Switch To Partner File"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("record_file_in_project"), str8_lit_comp(""), str8_lit_comp("Record File In Project"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("show_file_in_explorer"), str8_lit_comp(""), str8_lit_comp("Show File In Explorer"), str8_lit_comp(""), RD_IconKind_FolderClosedFilled}, {str8_lit_comp("go_to_disassembly"), str8_lit_comp(""), str8_lit_comp("Go To Disassembly"), str8_lit_comp(""), RD_IconKind_Glasses}, {str8_lit_comp("go_to_source"), str8_lit_comp(""), str8_lit_comp("Go To Source"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("set_file_replacement_path"), str8_lit_comp(""), str8_lit_comp("Set File Replacement Path"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("new_user"), str8_lit_comp(""), str8_lit_comp("New User"), str8_lit_comp(""), RD_IconKind_Add}, {str8_lit_comp("new_project"), str8_lit_comp(""), str8_lit_comp("New Project"), str8_lit_comp(""), RD_IconKind_Add}, {str8_lit_comp("open_user"), str8_lit_comp(""), str8_lit_comp("Open User"), str8_lit_comp(""), RD_IconKind_Person}, {str8_lit_comp("open_project"), str8_lit_comp(""), str8_lit_comp("Open Project"), str8_lit_comp(""), RD_IconKind_Briefcase}, {str8_lit_comp("open_recent_project"), str8_lit_comp(""), str8_lit_comp("Open Recent Project"), str8_lit_comp(""), RD_IconKind_Briefcase}, {str8_lit_comp("save_user"), str8_lit_comp(""), str8_lit_comp("Save User"), str8_lit_comp(""), RD_IconKind_Save}, {str8_lit_comp("save_project"), str8_lit_comp(""), str8_lit_comp("Save Project"), str8_lit_comp(""), RD_IconKind_Save}, {str8_lit_comp("record_user_as_last_opened"), str8_lit_comp(""), str8_lit_comp("Record User As Last Opened"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("record_project_in_user"), str8_lit_comp(""), str8_lit_comp("Records Project In User"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("write_user_data"), str8_lit_comp(""), str8_lit_comp("Write User Data"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("write_project_data"), str8_lit_comp(""), str8_lit_comp("Write Project Data"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("user_settings"), str8_lit_comp(""), str8_lit_comp("User Settings"), str8_lit_comp(""), RD_IconKind_Gear}, {str8_lit_comp("project_settings"), str8_lit_comp(""), str8_lit_comp("Project Settings"), str8_lit_comp(""), RD_IconKind_Gear}, {str8_lit_comp("edit"), str8_lit_comp(""), str8_lit_comp("Edit"), str8_lit_comp(""), RD_IconKind_Pencil}, {str8_lit_comp("accept"), str8_lit_comp(""), str8_lit_comp("Accept"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("cancel"), str8_lit_comp(""), str8_lit_comp("Cancel"), str8_lit_comp(""), RD_IconKind_X}, {str8_lit_comp("move_left"), str8_lit_comp(""), str8_lit_comp("Move Left"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_right"), str8_lit_comp(""), str8_lit_comp("Move Right"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up"), str8_lit_comp(""), str8_lit_comp("Move Up"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down"), str8_lit_comp(""), str8_lit_comp("Move Down"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_left_select"), str8_lit_comp(""), str8_lit_comp("Move Left Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_right_select"), str8_lit_comp(""), str8_lit_comp("Move Right Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_select"), str8_lit_comp(""), str8_lit_comp("Move Up Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_select"), str8_lit_comp(""), str8_lit_comp("Move Down Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_left_chunk"), str8_lit_comp(""), str8_lit_comp("Move Left Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_right_chunk"), str8_lit_comp(""), str8_lit_comp("Move Right Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_chunk"), str8_lit_comp(""), str8_lit_comp("Move Up Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_chunk"), str8_lit_comp(""), str8_lit_comp("Move Down Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_page"), str8_lit_comp(""), str8_lit_comp("Move Up Page"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_page"), str8_lit_comp(""), str8_lit_comp("Move Down Page"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_whole"), str8_lit_comp(""), str8_lit_comp("Move Up Whole"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_whole"), str8_lit_comp(""), str8_lit_comp("Move Down Whole"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_left_chunk_select"), str8_lit_comp(""), str8_lit_comp("Move Left Chunk Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_right_chunk_select"), str8_lit_comp(""), str8_lit_comp("Move Right Chunk Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_chunk_select"), str8_lit_comp(""), str8_lit_comp("Move Up Chunk Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_chunk_select"), str8_lit_comp(""), str8_lit_comp("Move Down Chunk Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_page_select"), str8_lit_comp(""), str8_lit_comp("Move Up Page Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_page_select"), str8_lit_comp(""), str8_lit_comp("Move Down Page Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_whole_select"), str8_lit_comp(""), str8_lit_comp("Move Up Whole Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_whole_select"), str8_lit_comp(""), str8_lit_comp("Move Down Whole Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_up_reorder"), str8_lit_comp(""), str8_lit_comp("Move Up Reorder"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_down_reorder"), str8_lit_comp(""), str8_lit_comp("Move Down Reorder"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_home"), str8_lit_comp(""), str8_lit_comp("Move Home"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_end"), str8_lit_comp(""), str8_lit_comp("Move End"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_home_select"), str8_lit_comp(""), str8_lit_comp("Move Home Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_end_select"), str8_lit_comp(""), str8_lit_comp("Move End Select"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("select_all"), str8_lit_comp(""), str8_lit_comp("Select All"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("delete_single"), str8_lit_comp(""), str8_lit_comp("Delete Single"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("delete_chunk"), str8_lit_comp(""), str8_lit_comp("Delete Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("backspace_single"), str8_lit_comp(""), str8_lit_comp("Backspace Single"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("backspace_chunk"), str8_lit_comp(""), str8_lit_comp("Backspace Chunk"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("copy"), str8_lit_comp(""), str8_lit_comp("Copy"), str8_lit_comp(""), RD_IconKind_Clipboard}, {str8_lit_comp("cut"), str8_lit_comp(""), str8_lit_comp("Cut"), str8_lit_comp(""), RD_IconKind_Clipboard}, {str8_lit_comp("paste"), str8_lit_comp(""), str8_lit_comp("Paste"), str8_lit_comp(""), RD_IconKind_Clipboard}, {str8_lit_comp("insert_text"), str8_lit_comp(""), str8_lit_comp("Insert Text"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_next"), str8_lit_comp(""), str8_lit_comp("Move Next"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("move_prev"), str8_lit_comp(""), str8_lit_comp("Move Previous"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("goto_line"), str8_lit_comp(""), str8_lit_comp("Go To Line"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("goto_address"), str8_lit_comp(""), str8_lit_comp("Go To Address"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("center_cursor"), str8_lit_comp(""), str8_lit_comp("Center Cursor"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("contain_cursor"), str8_lit_comp(""), str8_lit_comp("Contain Cursor"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("find_next"), str8_lit_comp(""), str8_lit_comp("Find Next"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_prev"), str8_lit_comp(""), str8_lit_comp("Find Previous"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_thread"), str8_lit_comp(""), str8_lit_comp("Find Thread"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("find_selected_thread"), str8_lit_comp(""), str8_lit_comp("Find Selected Thread"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("goto_name"), str8_lit_comp(""), str8_lit_comp("Go To Name"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("goto_name_at_cursor"), str8_lit_comp(""), str8_lit_comp("Go To Name At Cursor"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("toggle_watch_expr"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("toggle_watch_expr_at_cursor"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Cursor"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("toggle_watch_expr_at_mouse"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Mouse"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("enable_cfg"), str8_lit_comp(""), str8_lit_comp("Enable"), str8_lit_comp(""), RD_IconKind_CheckHollow}, {str8_lit_comp("disable_cfg"), str8_lit_comp(""), str8_lit_comp("Disable"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("select_cfg"), str8_lit_comp(""), str8_lit_comp("Select"), str8_lit_comp(""), RD_IconKind_RadioHollow}, {str8_lit_comp("deselect_cfg"), str8_lit_comp(""), str8_lit_comp("Deselect"), str8_lit_comp(""), RD_IconKind_RadioFilled}, {str8_lit_comp("remove_cfg"), str8_lit_comp(""), str8_lit_comp("Remove"), str8_lit_comp(""), RD_IconKind_Trash}, {str8_lit_comp("name_cfg"), str8_lit_comp(""), str8_lit_comp("Name"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("condition_cfg"), str8_lit_comp(""), str8_lit_comp("Condition"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("duplicate_cfg"), str8_lit_comp(""), str8_lit_comp("Duplicate"), str8_lit_comp(""), RD_IconKind_Duplicate}, {str8_lit_comp("relocate_cfg"), str8_lit_comp(""), str8_lit_comp("Relocate"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("save_cfg_to_project"), str8_lit_comp(""), str8_lit_comp("Save To Project"), str8_lit_comp(""), RD_IconKind_Briefcase}, {str8_lit_comp("add_breakpoint"), str8_lit_comp(""), str8_lit_comp("Add Line Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("add_address_breakpoint"), str8_lit_comp(""), str8_lit_comp("Add Address Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("add_function_breakpoint"), str8_lit_comp(""), str8_lit_comp("Add Function Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("toggle_breakpoint"), str8_lit_comp(""), str8_lit_comp("Toggle Line Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("remove_breakpoint"), str8_lit_comp(""), str8_lit_comp("Remove Breakpoint"), str8_lit_comp(""), RD_IconKind_Trash}, {str8_lit_comp("enable_breakpoint"), str8_lit_comp(""), str8_lit_comp("Enable Breakpoint"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("disable_breakpoint"), str8_lit_comp(""), str8_lit_comp("Disable Breakpoint"), str8_lit_comp(""), RD_IconKind_CheckHollow}, {str8_lit_comp("clear_breakpoints"), str8_lit_comp(""), str8_lit_comp("Clear Breakpoints"), str8_lit_comp(""), RD_IconKind_Trash}, {str8_lit_comp("list_breakpoints"), str8_lit_comp(""), str8_lit_comp("List Breakpoints"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("clear_output"), str8_lit_comp(""), str8_lit_comp("Clear Output"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("add_watch_pin"), str8_lit_comp(""), str8_lit_comp("Add Watch Pin"), str8_lit_comp(""), RD_IconKind_Pin}, {str8_lit_comp("toggle_watch_pin"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Pin"), str8_lit_comp(""), RD_IconKind_Pin}, {str8_lit_comp("load_debug_info"), str8_lit_comp(""), str8_lit_comp("Load Debug Info"), str8_lit_comp(""), RD_IconKind_Module}, {str8_lit_comp("unload_debug_info"), str8_lit_comp(""), str8_lit_comp("Unload Debug Info"), str8_lit_comp(""), RD_IconKind_Module}, {str8_lit_comp("add_type_view"), str8_lit_comp(""), str8_lit_comp("Add Type View"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("add_file_path_map"), str8_lit_comp(""), str8_lit_comp("Add File Path Map"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("edit_user_theme"), str8_lit_comp(""), str8_lit_comp("Edit User Theme"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("edit_project_theme"), str8_lit_comp(""), str8_lit_comp("Edit Project Theme"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("add_theme_color"), str8_lit_comp(""), str8_lit_comp("Add Theme Color"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("fork_theme"), str8_lit_comp(""), str8_lit_comp("Fork Theme"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("save_theme"), str8_lit_comp(""), str8_lit_comp("Save Theme"), str8_lit_comp(""), RD_IconKind_Save}, {str8_lit_comp("save_and_set_theme"), str8_lit_comp(""), str8_lit_comp("Save And Set Theme"), str8_lit_comp(""), RD_IconKind_Save}, {str8_lit_comp("set_next_statement"), str8_lit_comp(""), str8_lit_comp("Set Next Statement"), str8_lit_comp(""), RD_IconKind_RightArrow}, {str8_lit_comp("add_target"), str8_lit_comp(""), str8_lit_comp("Add Target"), str8_lit_comp(""), RD_IconKind_Target}, {str8_lit_comp("select_target"), str8_lit_comp(""), str8_lit_comp("Select Target"), str8_lit_comp(""), RD_IconKind_Target}, {str8_lit_comp("enable_target"), str8_lit_comp(""), str8_lit_comp("Enable Target"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("disable_target"), str8_lit_comp(""), str8_lit_comp("Disable Target"), str8_lit_comp(""), RD_IconKind_CheckHollow}, {str8_lit_comp("remove_target"), str8_lit_comp(""), str8_lit_comp("Remove Target"), str8_lit_comp(""), RD_IconKind_Trash}, {str8_lit_comp("register_as_jit_debugger"), str8_lit_comp(""), str8_lit_comp("Register As Just-In-Time (JIT) Debugger"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("find_code_location"), str8_lit_comp(""), str8_lit_comp("Find Code Location"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("search"), str8_lit_comp(""), str8_lit_comp("Search"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("search_backwards"), str8_lit_comp(""), str8_lit_comp("Search Backwards"), str8_lit_comp(""), RD_IconKind_Find}, {str8_lit_comp("pick_file"), str8_lit_comp(""), str8_lit_comp("Pick File"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("pick_folder"), str8_lit_comp(""), str8_lit_comp("Pick Folder"), str8_lit_comp(""), RD_IconKind_FolderOpenFilled}, {str8_lit_comp("pick_file_or_folder"), str8_lit_comp(""), str8_lit_comp("Pick File/Folder"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("push_query"), str8_lit_comp(""), str8_lit_comp("Push Query"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("complete_query"), str8_lit_comp(""), str8_lit_comp("Complete Query"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("cancel_query"), str8_lit_comp(""), str8_lit_comp("Cancel Query"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("update_query"), str8_lit_comp(""), str8_lit_comp("Update Query"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("open_event_buffer"), str8_lit_comp(""), str8_lit_comp("Open Event Buffer"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("close_event_buffer"), str8_lit_comp(""), str8_lit_comp("Close Event Buffer"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("toggle_dev_menu"), str8_lit_comp(""), str8_lit_comp("Toggle Developer Menu"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("log_marker"), str8_lit_comp(""), str8_lit_comp("Log Marker"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("watches"), str8_lit_comp(""), str8_lit_comp("Watch"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("locals"), str8_lit_comp(""), str8_lit_comp("Locals"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("registers"), str8_lit_comp(""), str8_lit_comp("Registers"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("globals"), str8_lit_comp(""), str8_lit_comp("Globals"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("thread_locals"), str8_lit_comp(""), str8_lit_comp("Thread Locals"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("types"), str8_lit_comp(""), str8_lit_comp("Types"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("procedures"), str8_lit_comp(""), str8_lit_comp("Procedures"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("call_stack"), str8_lit_comp(""), str8_lit_comp("Call Stack"), str8_lit_comp(""), RD_IconKind_Thread}, {str8_lit_comp("targets"), str8_lit_comp(""), str8_lit_comp("Targets"), str8_lit_comp(""), RD_IconKind_Target}, {str8_lit_comp("breakpoints"), str8_lit_comp(""), str8_lit_comp("Breakpoints"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("watch_pins"), str8_lit_comp(""), str8_lit_comp("Watch Pins"), str8_lit_comp(""), RD_IconKind_Pin}, {str8_lit_comp("debug_infos"), str8_lit_comp(""), str8_lit_comp("Debug Info"), str8_lit_comp(""), RD_IconKind_Module}, {str8_lit_comp("threads"), str8_lit_comp(""), str8_lit_comp("Threads"), str8_lit_comp(""), RD_IconKind_Threads}, {str8_lit_comp("processes"), str8_lit_comp(""), str8_lit_comp("Processes"), str8_lit_comp(""), RD_IconKind_Scheduler}, {str8_lit_comp("machines"), str8_lit_comp(""), str8_lit_comp("Machines"), str8_lit_comp(""), RD_IconKind_Machine}, {str8_lit_comp("modules"), str8_lit_comp(""), str8_lit_comp("Modules"), str8_lit_comp(""), RD_IconKind_Module}, {str8_lit_comp("file_path_maps"), str8_lit_comp(""), str8_lit_comp("File Path Map"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("type_views"), str8_lit_comp(""), str8_lit_comp("Type Views"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("output"), str8_lit_comp(""), str8_lit_comp("Output"), str8_lit_comp(""), RD_IconKind_List}, {str8_lit_comp("text"), str8_lit_comp(""), str8_lit_comp("Text"), str8_lit_comp(""), RD_IconKind_FileOutline}, {str8_lit_comp("disasm"), str8_lit_comp(""), str8_lit_comp("Disassembly"), str8_lit_comp(""), RD_IconKind_Glasses}, {str8_lit_comp("memory"), str8_lit_comp(""), str8_lit_comp("Memory"), str8_lit_comp(""), RD_IconKind_Grid}, {str8_lit_comp("bitmap"), str8_lit_comp(""), str8_lit_comp("Bitmap"), str8_lit_comp(""), RD_IconKind_Bitmap}, {str8_lit_comp("color"), str8_lit_comp(""), str8_lit_comp("Color"), str8_lit_comp(""), RD_IconKind_Palette}, {str8_lit_comp("geo3d"), str8_lit_comp(""), str8_lit_comp("Geometry (3D)"), str8_lit_comp(""), RD_IconKind_Cube}, }; RD_NameSchemaInfo rd_name_schema_info_table[26] = { {str8_lit_comp("user"), str8_lit_comp("@expand_commands(edit_user_theme) x:\n{\n //- rjf: animations\n @display_name('Animations') @description(\"Enables animations.\")\n @default(1) 'animations': bool,\n @display_name('Scrolling Animations') @description(\"Enables scrolling animations.\")\n @expand_if(\"$.animations\") @default(1) 'scrolling_animations': bool,\n @display_name('Tooltip Animations') @description(\"Enables tooltip animations.\")\n @expand_if(\"$.animations\") @default(1) 'tooltip_animations': bool,\n @display_name('Menu Animations') @description(\"Enables menu animations.\")\n @expand_if(\"$.animations\") @default(1) 'menu_animations': bool,\n\n //- rjf: fonts\n @display_name('UI Font') @description(\"The name of, or path to, the font used when displaying non-code UI elements.\")\n @default('') 'main_font': string,\n @display_name('Code Font') @description(\"The name of, or path to, the font used when displaying code.\")\n @default('') 'code_font': string,\n\n //- rjf: theme\n @default(\"Default (Dark)\") @display_name('User Theme')\n @description(\"The user's theme, which describes all colors used throughout the UI.\")\n 'theme': string,\n @no_expand @display_name('User Theme')\n 'theme_colors': query,\n\n //- rjf: autocompletion\n @display_name('Autocompletion Lister') @description(\"Enables the autocompletion lister while typing expressions.\") @default(1)\n 'autocompletion_lister': bool,\n @display_name('View Call Argument Helper') @description(\"Enables the view call argument helper, which shows view arguments and documentation, while typing expressions.\") @default(1)\n 'view_call_argument_helper': bool,\n\n //- rjf: scope decorations\n @default(1) @display_name('Cursor Scope Lines') @description(\"Controls whether or not scopes containing the cursor in text views are drawn.\")\n 'cursor_scope_lines': bool,\n\n //- rjf: cursor decorations\n @default(1) @display_name('Cursor Trail') @description(\"Controls whether or not a movement trail of the cursor is drawn.\")\n 'cursor_trail': bool,\n\n //- rjf: thread & breakpoint decorations\n @default(1) @display_name('Thread Lines') @description(\"Controls whether or not a long horizontal line is drawn before the next line or instruction that the selected thread will execute in source and disassembly views.\")\n 'thread_lines': bool,\n @default(1) @display_name('Thread Glow') @description(\"Controls whether or not a glowing effect is drawn on the selected thread in source and disassembly views.\")\n 'thread_glow': bool,\n @default(1) @display_name('Breakpoint Lines') @description(\"Controls whether or not a long horizontal line is drawn before the line or instruction at which a breakpoint is placed, in source and disassembly views.\")\n 'breakpoint_lines': bool,\n @default(1) @display_name('Breakpoint Glow') @description(\"Controls whether or not a glowing effect is drawn on breakpoints in source and disassembly views.\")\n 'breakpoint_glow': bool,\n\n //- rjf: occluding background settings\n @default(0) @display_name('Opaque Backgrounds') @description(\"Controls whether or not all floating background colors are forced to be fully opaque.\")\n 'opaque_backgrounds': bool,\n @default(1) @display_name('Background Blur') @description(\"Controls whether or not occluded regions behind floating elements are blurred.\")\n 'background_blur': bool,\n\n //- rjf: appearance settings\n @default(1) @display_name('Drop Shadows') @description(\"Controls whether or not drop shadows are drawn.\")\n 'drop_shadows': bool,\n @default(1.f) @display_name('Rounded Corner Amount') @description(\"Controls the degree to which UI corners are rounded.\")\n 'rounded_corner_amount': @range[0, 1] f32,\n\n //- rjf: code formatting settings\n @default(2) @display_name('User Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: windows style menu bar\n @default(1) @display_name('Focus Menu Bar With Alt') @description(\"Mimics standard Windows behavior of focusing the menu bar using the Alt key.\")\n 'focus_menu_bar_with_alt': bool,\n\n //- rjf: native filesystem dialogues\n @default(0) @display_name('Use Native File System Dialog') @description(\"Uses the operating system's file system dialog box, rather than the debugger's built-in UI.\")\n 'use_native_file_system_dialog': bool,\n}\n")}, {str8_lit_comp("project"), str8_lit_comp("@expand_commands(edit_project_theme) x:\n{\n @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: visualizers\n @display_name('Use Default C++ STL Type Visualizers') @description(\"Enables the built-in type views for C++ STL types.\")\n @default(1) use_default_stl_type_views: bool,\n @display_name('Use Default Unreal Engine Type Visualizers') @description(\"Enables the built-in type views for Unreal Engine types.\")\n @default(1) use_default_ue_type_views: bool,\n\n //- rjf: theme\n @default(\"None\") @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme': string,\n @no_expand @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme_colors': query,\n\n //- rjf: exception settings\n @default(1) @display_name(\"Break On Win32 Control-C Exceptions\") @description(\"Code: 0x40010005\")\n win32_ctrl_c: bool;\n @default(1) @display_name(\"Break On Win32 Control-Break Exceptions\") @description(\"Code: 0x40010008\")\n win32_ctrl_break: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Originate Error Exceptions\") @description(\"Code: 0x40080201\")\n win32_win_rt_originate_error: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Transform Error Exceptions\") @description(\"Code: 0x40080202\")\n win32_win_rt_transform_error: bool;\n @default(0) @display_name(\"Break On Win32 RPC Call Cancelled Exceptions\") @description(\"Code: 0x0000071a\")\n win32_rpc_call_cancelled: bool;\n @default(0) @display_name(\"Break On Win32 Data Type Misalignment Exceptions\") @description(\"Code: 0x80000002\")\n win32_datatype_misalignment: bool;\n @default(1) @display_name(\"Break On Win32 Access Violation Exceptions\") @description(\"Code: 0xc0000005\")\n win32_access_violation: bool;\n @default(0) @display_name(\"Break On Win32 In Page Error Exceptions\") @description(\"Code: 0xc0000006\")\n win32_in_page_error: bool;\n @default(1) @display_name(\"Break On Win32 Invalid Handle Specified Exceptions\") @description(\"Code: 0xc0000008\")\n win32_invalid_handle: bool;\n @default(0) @display_name(\"Break On Win32 Not Enough Quota Exceptions\") @description(\"Code: 0xc0000017\")\n win32_not_enough_quota: bool;\n @default(0) @display_name(\"Break On Win32 Illegal Instruction Exceptions\") @description(\"Code: 0xc000001d\")\n win32_illegal_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Cannot Continue From Exception Exceptions\") @description(\"Code: 0xc0000025\")\n win32_cannot_continue_exception: bool;\n @default(0) @display_name(\"Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions\") @description(\"Code: 0xc0000026\")\n win32_invalid_exception_disposition: bool;\n @default(0) @display_name(\"Break On Win32 Array Bounds Exceeded Exceptions\") @description(\"Code: 0xc000008c\")\n win32_array_bounds_exceeded: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Denormal Operand Exceptions\") @description(\"Code: 0xc000008d\")\n win32_floating_point_denormal_operand: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Division By Zero Exceptions\") @description(\"Code: 0xc000008e\")\n win32_floating_point_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Inexact Result Exceptions\") @description(\"Code: 0xc000008f\")\n win32_floating_point_inexact_result: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Invalid Operation Exceptions\") @description(\"Code: 0xc0000090\")\n win32_floating_point_invalid_operation: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Overflow Exceptions\") @description(\"Code: 0xc0000091\")\n win32_floating_point_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Stack Check Exceptions\") @description(\"Code: 0xc0000092\")\n win32_floating_point_stack_check: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Underflow Exceptions\") @description(\"Code: 0xc0000093\")\n win32_floating_point_underflow: bool;\n @default(0) @display_name(\"Break On Win32 Integer Division By Zero Exceptions\") @description(\"Code: 0xc0000094\")\n win32_integer_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Integer Overflow Exceptions\") @description(\"Code: 0xc0000095\")\n win32_integer_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Privileged Instruction Exceptions\") @description(\"Code: 0xc0000096\")\n win32_privileged_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Stack Overflow Exceptions\") @description(\"Code: 0xc00000fd\")\n win32_stack_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Unable To Locate DLL Exceptions\") @description(\"Code: 0xc0000135\")\n win32_unable_to_locate_dll: bool;\n @default(0) @display_name(\"Break On Win32 Ordinal Not Found Exceptions\") @description(\"Code: 0xc0000138\")\n win32_ordinal_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Entry Point Not Found Exceptions\") @description(\"Code: 0xc0000139\")\n win32_entry_point_not_found: bool;\n @default(0) @display_name(\"Break On Win32 DLL Initialization Failed Exceptions\") @description(\"Code: 0xc0000142\")\n win32_dll_initialization_failed: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Faults Exceptions\") @description(\"Code: 0xc00002b4\")\n win32_floating_point_sse_multiple_faults: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Traps Exceptions\") @description(\"Code: 0xc00002b5\")\n win32_floating_point_sse_multiple_traps: bool;\n @default(1) @display_name(\"Break On Win32 Assertion Failed Exceptions\") @description(\"Code: 0xc0000420\")\n win32_assertion_failed: bool;\n @default(0) @display_name(\"Break On Win32 Module Not Found Exceptions\") @description(\"Code: 0xc06d007e\")\n win32_module_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Procedure Not Found Exceptions\") @description(\"Code: 0xc06d007f\")\n win32_procedure_not_found: bool;\n @default(1) @display_name(\"Break On Win32 Sanitizer Error Detected Exceptions\") @description(\"Code: 0xe073616e\")\n win32_sanitizer_error_detected: bool;\n @default(0) @display_name(\"Break On Win32 Sanitizer Raw Access Violation Exceptions\") @description(\"Code: 0xe0736171\")\n win32_sanitizer_raw_access_violation: bool;\n @default(1) @display_name(\"Break On Win32 DirectX Debug Layer Exceptions\") @description(\"Code: 0x0000087a\")\n win32_directx_debug_layer: bool;\n}\n")}, {str8_lit_comp("theme_color"), str8_lit_comp("@collection_commands(add_theme_color, fork_theme, save_theme, save_and_set_theme)\n@row_commands(duplicate_cfg, remove_cfg)\nx:\n{\n @display_name('Tags') tags: string,\n @display_name('Value') value: @color @hex u32,\n}\n")}, {str8_lit_comp("window"), str8_lit_comp("x:\n{\n //- rjf: text rasterization settings\n @default(1) @display_name('Smooth UI Text') @description(\"Controls whether or not UI text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_ui_text': bool,\n @default(1) @display_name('Hint UI Text') @description(\"Controls whether or not UI text is hinted, for better text readability at small sizes.\")\n 'hint_ui_text': bool,\n @default(0) @display_name('Smooth Code Text') @description(\"Controls whether or not code text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_code_text': bool,\n @default(1) @display_name('Hint Code Text') @description(\"Controls whether or not code text is hinted, for better text readability at small sizes.\")\n 'hint_code_text': bool,\n @default(11) @display_name('Window Font Size') @description(\"Controls the window's default font size. Does not apply to tabs with their own font size set.\")\n 'font_size': @range[6, 72] u64,\n\n //- rjf: size settings\n @default(3.f) @display_name('Window Row Height') @description(\"Controls the window's default row height, in multiples of the font size. Does not apply to tabs with their own row height set.\")\n 'row_height': @range[1.75f, 5.f] f32,\n @default(3.f) @description(\"Controls the height of tabs, in multiples of the font size.\")\n 'tab_height': @range[1.75f, 5.f] f32,\n\n //- rjf: theme settings\n @default(1) @display_name('Use Project Theme') @description(\"Prefer using the project theme for this window, if any. If off, only the user's theme settings will be used.\")\n 'use_project_theme': bool,\n}\n")}, {str8_lit_comp("tab"), str8_lit_comp("@row_commands(@file copy_tab_full_path, @file show_file_in_explorer, duplicate_tab, close_tab)\nx:\n{\n @override @display_name('Tab Font Size') @description(\"Controls the tab's font size.\") @no_callee_helper\n 'font_size': @range[6, 72] u64,\n}\n")}, {str8_lit_comp("watch"), str8_lit_comp("@inherit(tab) x:\n{\n @override @display_name('Tab Row Height') @description(\"Controls the tab's row height, in multiples of the font size.\")\n 'row_height': @range[1.75f, 5.f] f32,\n 'label': code_string,\n @description(\"The root expression which is evaluated to produce the watch window.\")\n 'expression': expr_string,\n @no_expand 'watches': query,\n}\n")}, {str8_lit_comp("list"), str8_lit_comp("x:\n{\n @description(\"An expression describing the first node in the list.\")\n 'expression': expr_string,\n @order(0) @description(\"The name of the member which encodes the link to the next node.\")\n 'member_name': code_string,\n}\n")}, {str8_lit_comp("text"), str8_lit_comp("@inherit(tab) @expand_commands(@output clear_output) x:\n{\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': expr_string,\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': code_string,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @no_callee_helper @default(1) @display_name('Line Wrapping') @description(\"Splits textual lines into multiple visual lines, so that all text is within the visible area.\")\n 'line_wrapping': bool,\n @no_callee_helper @default(0) @display_name('Scroll To Bottom On Change') @description(\"Scrolls to the bottom if the text is changed.\")\n 'scroll_to_bottom_on_change': bool,\n @no_callee_helper @no_revert @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n}\n")}, {str8_lit_comp("disasm"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the disassembly.\")\n 'expression': expr_string,\n 'arch': code_string,\n 'syntax': code_string,\n 'size': expr_string,\n @no_callee_helper @default(1) @description(\"Controls whether or not addresses are shown in the disassembly text.\")\n 'show_addresses': bool,\n @no_callee_helper @default(0) @description(\"Controls whether or not code bytes are shown in the disassembly text.\")\n 'show_code_bytes': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.\")\n 'show_source_lines': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not disassembly text is decorated with symbol names.\")\n 'show_symbol_names': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers': bool,\n\n}\n")}, {str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n}\n")}, {str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as a bitmap.\")\n 'expression': expr_string,\n @description(\"An expression describing the width of the bitmap, in pixels.\") @order(0) 'w': u64,\n @description(\"An expression describing the height of the bitmap, in pixels.\") @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': code_string,\n}\n")}, {str8_lit_comp("color"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Value\") @description(\"An expression to describe the value or location of the color.\")\n 'expression': expr_string,\n}\n")}, {str8_lit_comp("geo3d"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Expression\") @description(\"An expression to describe the base address of the index buffer.\")\n 'expression': expr_string,\n 'count': expr_string,\n 'vtx': expr_string,\n 'vtx_size': expr_string,\n 'yaw': @range[0, 1] f32,\n 'pitch': @range[-0.5, 0] f32,\n 'zoom': @range[0, 100] f32,\n}\n")}, {str8_lit_comp("getting_started"), str8_lit_comp("@inherit(tab) x:\n{\n}\n")}, {str8_lit_comp("target"), str8_lit_comp("@row_commands(@cmd_line save_cfg_to_project, enable_cfg, launch_and_run, launch_and_step_into, duplicate_cfg, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': path,\n 'entry_point': expr_string,\n 'stdout_path': @no_relativize path,\n 'stderr_path': @no_relativize path,\n 'stdin_path': @no_relativize path,\n 'environment': query,\n 'debug_subprocesses': bool,\n @no_revert @no_expand @default(0) 'enabled': bool,\n}\n")}, {str8_lit_comp("breakpoint"), str8_lit_comp("@row_commands(enable_cfg, duplicate_cfg, remove_cfg)\n@collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint, add_function_breakpoint, clear_breakpoints)\nx:\n{\n 'label': code_string,\n 'condition': expr_string,\n 'source_location': path_pt,\n 'address_location': expr_string,\n 'hit_count': u64,\n 'address_range_size': @or(0, 1, 2, 4, 8) u64,\n 'break_on_write': bool,\n 'break_on_read': bool,\n 'break_on_execute': bool,\n @no_revert @no_expand @default(1) 'enabled': bool,\n}\n")}, {str8_lit_comp("watch_pin"), str8_lit_comp("@row_commands(duplicate_cfg, remove_cfg)\n@collection_commands(add_watch_pin, toggle_watch_pin)\nx:\n{\n 'expression': expr_string,\n 'source_location': path_pt,\n 'address_location': expr_string,\n}\n")}, {str8_lit_comp("debug_info"), str8_lit_comp("@row_commands(enable_cfg, duplicate_cfg, remove_cfg)\n@collection_commands(load_debug_info)\nx:\n{\n 'path': @no_relativize path,\n @query 'guid': string,\n @no_revert @no_expand @default(1) 'enabled': bool,\n}\n")}, {str8_lit_comp("file_path_map"), str8_lit_comp("@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source': @no_relativize path, 'dest': @no_relativize path}")}, {str8_lit_comp("type_view"), str8_lit_comp("@collection_commands(add_type_view) @row_commands(remove_cfg) x:{'type':expr_string, 'expr':expr_string}")}, {str8_lit_comp("recent_project"), str8_lit_comp("x:{'path':path}")}, {str8_lit_comp("recent_file"), str8_lit_comp("x:{'path':path}")}, {str8_lit_comp("machine"), str8_lit_comp("x:{'label':code_string, @no_expand 'active':bool, 'unattached_processes':query, 'processes':query}")}, {str8_lit_comp("process"), str8_lit_comp("x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'modules':query, 'threads':query}")}, {str8_lit_comp("module"), str8_lit_comp("x:{'exe':path, 'dbg':path, 'vaddr_range':vaddr_range}")}, {str8_lit_comp("thread"), str8_lit_comp("x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'call_stack':query}")}, }; String8 rd_reg_slot_code_name_table[48] = { {0}, str8_lit_comp("machine"), str8_lit_comp("module"), str8_lit_comp("process"), str8_lit_comp("thread"), str8_lit_comp("ctrl_entity"), str8_lit_comp("window"), str8_lit_comp("panel"), str8_lit_comp("tab"), str8_lit_comp("view"), str8_lit_comp("prev_tab"), str8_lit_comp("dst_panel"), str8_lit_comp("cfg"), str8_lit_comp("cfg_list"), str8_lit_comp("eval_space"), str8_lit_comp("unwind_count"), str8_lit_comp("inline_depth"), str8_lit_comp("file_path"), str8_lit_comp("cursor"), str8_lit_comp("mark"), str8_lit_comp("text_key"), str8_lit_comp("lang_kind"), str8_lit_comp("lines"), str8_lit_comp("dbgi_key"), str8_lit_comp("vaddr"), str8_lit_comp("voff"), str8_lit_comp("vaddr_range"), str8_lit_comp("voff_range"), str8_lit_comp("expr"), str8_lit_comp("ui_key"), str8_lit_comp("src_ui_key"), str8_lit_comp("off_px"), str8_lit_comp("reg_slot"), str8_lit_comp("pid"), str8_lit_comp("force_confirm"), str8_lit_comp("force_focus"), str8_lit_comp("prefer_disasm"), str8_lit_comp("no_rich_tooltip"), str8_lit_comp("do_implicit_root"), str8_lit_comp("do_lister"), str8_lit_comp("do_big_rows"), str8_lit_comp("all_windows"), str8_lit_comp("non_graphical"), str8_lit_comp("prefer_new_tab"), str8_lit_comp("dir2"), str8_lit_comp("string"), str8_lit_comp("cmd_name"), str8_lit_comp("os_event"), }; Rng1U64 rd_reg_slot_range_table[48] = { {0}, {OffsetOf(RD_Regs, machine), OffsetOf(RD_Regs, machine) + sizeof(CTRL_Handle)}, {OffsetOf(RD_Regs, module), OffsetOf(RD_Regs, module) + sizeof(CTRL_Handle)}, {OffsetOf(RD_Regs, process), OffsetOf(RD_Regs, process) + sizeof(CTRL_Handle)}, {OffsetOf(RD_Regs, thread), OffsetOf(RD_Regs, thread) + sizeof(CTRL_Handle)}, {OffsetOf(RD_Regs, ctrl_entity), OffsetOf(RD_Regs, ctrl_entity) + sizeof(CTRL_Handle)}, {OffsetOf(RD_Regs, window), OffsetOf(RD_Regs, window) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, panel), OffsetOf(RD_Regs, panel) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, tab), OffsetOf(RD_Regs, tab) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, view), OffsetOf(RD_Regs, view) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, prev_tab), OffsetOf(RD_Regs, prev_tab) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, dst_panel), OffsetOf(RD_Regs, dst_panel) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, cfg), OffsetOf(RD_Regs, cfg) + sizeof(CFG_ID)}, {OffsetOf(RD_Regs, cfg_list), OffsetOf(RD_Regs, cfg_list) + sizeof(CFG_IDList)}, {OffsetOf(RD_Regs, eval_space), OffsetOf(RD_Regs, eval_space) + sizeof(E_Space)}, {OffsetOf(RD_Regs, unwind_count), OffsetOf(RD_Regs, unwind_count) + sizeof(U64)}, {OffsetOf(RD_Regs, inline_depth), OffsetOf(RD_Regs, inline_depth) + sizeof(U64)}, {OffsetOf(RD_Regs, file_path), OffsetOf(RD_Regs, file_path) + sizeof(String8)}, {OffsetOf(RD_Regs, cursor), OffsetOf(RD_Regs, cursor) + sizeof(TxtPt)}, {OffsetOf(RD_Regs, mark), OffsetOf(RD_Regs, mark) + sizeof(TxtPt)}, {OffsetOf(RD_Regs, text_key), OffsetOf(RD_Regs, text_key) + sizeof(C_Key)}, {OffsetOf(RD_Regs, lang_kind), OffsetOf(RD_Regs, lang_kind) + sizeof(TXT_LangKind)}, {OffsetOf(RD_Regs, lines), OffsetOf(RD_Regs, lines) + sizeof(D_LineList)}, {OffsetOf(RD_Regs, dbgi_key), OffsetOf(RD_Regs, dbgi_key) + sizeof(DI_Key)}, {OffsetOf(RD_Regs, vaddr), OffsetOf(RD_Regs, vaddr) + sizeof(U64)}, {OffsetOf(RD_Regs, voff), OffsetOf(RD_Regs, voff) + sizeof(U64)}, {OffsetOf(RD_Regs, vaddr_range), OffsetOf(RD_Regs, vaddr_range) + sizeof(Rng1U64)}, {OffsetOf(RD_Regs, voff_range), OffsetOf(RD_Regs, voff_range) + sizeof(Rng1U64)}, {OffsetOf(RD_Regs, expr), OffsetOf(RD_Regs, expr) + sizeof(String8)}, {OffsetOf(RD_Regs, ui_key), OffsetOf(RD_Regs, ui_key) + sizeof(UI_Key)}, {OffsetOf(RD_Regs, src_ui_key), OffsetOf(RD_Regs, src_ui_key) + sizeof(UI_Key)}, {OffsetOf(RD_Regs, off_px), OffsetOf(RD_Regs, off_px) + sizeof(Vec2F32)}, {OffsetOf(RD_Regs, reg_slot), OffsetOf(RD_Regs, reg_slot) + sizeof(RD_RegSlot)}, {OffsetOf(RD_Regs, pid), OffsetOf(RD_Regs, pid) + sizeof(U32)}, {OffsetOf(RD_Regs, force_confirm), OffsetOf(RD_Regs, force_confirm) + sizeof(B32)}, {OffsetOf(RD_Regs, force_focus), OffsetOf(RD_Regs, force_focus) + sizeof(B32)}, {OffsetOf(RD_Regs, prefer_disasm), OffsetOf(RD_Regs, prefer_disasm) + sizeof(B32)}, {OffsetOf(RD_Regs, no_rich_tooltip), OffsetOf(RD_Regs, no_rich_tooltip) + sizeof(B32)}, {OffsetOf(RD_Regs, do_implicit_root), OffsetOf(RD_Regs, do_implicit_root) + sizeof(B32)}, {OffsetOf(RD_Regs, do_lister), OffsetOf(RD_Regs, do_lister) + sizeof(B32)}, {OffsetOf(RD_Regs, do_big_rows), OffsetOf(RD_Regs, do_big_rows) + sizeof(B32)}, {OffsetOf(RD_Regs, all_windows), OffsetOf(RD_Regs, all_windows) + sizeof(B32)}, {OffsetOf(RD_Regs, non_graphical), OffsetOf(RD_Regs, non_graphical) + sizeof(B32)}, {OffsetOf(RD_Regs, prefer_new_tab), OffsetOf(RD_Regs, prefer_new_tab) + sizeof(B32)}, {OffsetOf(RD_Regs, dir2), OffsetOf(RD_Regs, dir2) + sizeof(Dir2)}, {OffsetOf(RD_Regs, string), OffsetOf(RD_Regs, string) + sizeof(String8)}, {OffsetOf(RD_Regs, cmd_name), OffsetOf(RD_Regs, cmd_name) + sizeof(String8)}, {OffsetOf(RD_Regs, os_event), OffsetOf(RD_Regs, os_event) + sizeof(OS_Event *)}, }; RD_CmdKindInfo rd_cmd_kind_info_table[248] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("launch_and_step_into"), str8_lit_comp("Starts debugging a new instance of a target, then stops at the program's entry point."), str8_lit_comp("launch,start,entry,point"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("kill"), str8_lit_comp("Kills the specified existing attached process(es)."), str8_lit_comp("stop,kill"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Process, str8_lit_comp("query:processes"), str8_lit_comp(""), CTRL_EntityKind_Process}}, { str8_lit_comp("kill_all"), str8_lit_comp("Kills all attached processes."), str8_lit_comp("stop,kill,all"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("detach"), str8_lit_comp("Detaches the specified attached process(es)."), str8_lit_comp("detach"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Process, str8_lit_comp("query:processes"), str8_lit_comp(""), CTRL_EntityKind_Process}}, { str8_lit_comp("continue"), str8_lit_comp("Continues executing all attached processes."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_into_inst"), str8_lit_comp("Performs a step that goes into calls, at the instruction level."), str8_lit_comp("single,step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_over_inst"), str8_lit_comp("Performs a step that skips calls, at the instruction level."), str8_lit_comp("single,step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_into_line"), str8_lit_comp("Performs a step that goes into calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_over_line"), str8_lit_comp("Performs a step that skips calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_out"), str8_lit_comp("Runs to the end of the current function and exits it."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("halt"), str8_lit_comp("Halts all attached processes."), str8_lit_comp("pause"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("soft_halt_refresh"), str8_lit_comp("Interrupts all attached processes to collect data, and then resumes them."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_thread_ip"), str8_lit_comp("Sets the specified thread's instruction pointer at the specified address."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Vaddr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("run_to_line"), str8_lit_comp("Runs until a particular source line is hit."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("run"), str8_lit_comp("Runs all targets after starting them if they have not been started yet."), str8_lit_comp("play"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("restart"), str8_lit_comp("Kills all attached processes, then launches all active targets."), str8_lit_comp("restart,retry"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_into"), str8_lit_comp("Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("step_over"), str8_lit_comp("Steps once, always over function calls, for either source lines or instructions."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("freeze_thread"), str8_lit_comp("Freezes the passed thread."), str8_lit_comp("callstack,unwind"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), CTRL_EntityKind_Thread}}, { str8_lit_comp("thaw_thread"), str8_lit_comp("Thaws the passed thread."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), CTRL_EntityKind_Thread}}, { str8_lit_comp("freeze_process"), str8_lit_comp("Freezes the passed process."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Process, str8_lit_comp("query:processes"), str8_lit_comp(""), CTRL_EntityKind_Process}}, { str8_lit_comp("thaw_process"), str8_lit_comp("Thaws the passed process."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Process, str8_lit_comp("query:processes"), str8_lit_comp(""), CTRL_EntityKind_Process}}, { str8_lit_comp("freeze_machine"), str8_lit_comp("Freezes the passed machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Machine, str8_lit_comp("query:machines"), str8_lit_comp(""), CTRL_EntityKind_Machine}}, { str8_lit_comp("thaw_machine"), str8_lit_comp("Thaws the passed machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Machine, str8_lit_comp("query:machines"), str8_lit_comp(""), CTRL_EntityKind_Machine}}, { str8_lit_comp("freeze_local_machine"), str8_lit_comp("Freezes the local machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("thaw_local_machine"), str8_lit_comp("Thaws the local machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("freeze_entity"), str8_lit_comp("Freezes an entity."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("thaw_entity"), str8_lit_comp("Thaws an entity."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_entity_color"), str8_lit_comp("Sets the passed entity's color."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_entity_name"), str8_lit_comp("Sets the passed entity's name."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("attach"), str8_lit_comp("Attaches to a process that is already running on the local machine."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_PID, str8_lit_comp("query:unattached_processes"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_palette"), str8_lit_comp("Opens the palette."), str8_lit_comp("help,cmd,lister"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:commands"), str8_lit_comp("commands"), CTRL_EntityKind_Null}}, { str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("os_event"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("select_thread"), str8_lit_comp("Selects a thread."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), CTRL_EntityKind_Thread}}, { str8_lit_comp("select_unwind"), str8_lit_comp("Selects an unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("query:call_stack"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("up_one_frame"), str8_lit_comp("Selects the call stack frame above the currently selected."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("down_one_frame"), str8_lit_comp("Selects the call stack frame below the currently selected."), str8_lit_comp("callstack,unwind"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("select_entity"), str8_lit_comp("Selects a control entity."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("deselect_entity"), str8_lit_comp("Deselects a control entity."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("inc_window_font_size"), str8_lit_comp("Increases the window's font size by one point."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("dec_window_font_size"), str8_lit_comp("Decreases the window's font size by one point."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("inc_view_font_size"), str8_lit_comp("Increases the view's font size by one point."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("dec_view_font_size"), str8_lit_comp("Decreases the view's font size by one point."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_window"), str8_lit_comp("Opens a new window."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("window_settings"), str8_lit_comp("Opens settings for a window."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("close_window"), str8_lit_comp("Closes an opened window."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_fullscreen"), str8_lit_comp("Toggles fullscreen view on the active window."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("bring_to_front"), str8_lit_comp("Brings all windows to the front, and focuses the most recently focused window."), str8_lit_comp("top"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("popup_accept"), str8_lit_comp("Accepts the active popup prompt."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("popup_cancel"), str8_lit_comp("Cancels the active popup prompt."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("reset_to_default_bindings"), str8_lit_comp("Resets all keybindings to their defaults."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("reset_to_default_panels"), str8_lit_comp("Resets the window to the default panel layout."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("reset_to_compact_panels"), str8_lit_comp("Resets the window to the compact panel layout."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("reset_to_simple_panels"), str8_lit_comp("Resets the window to the simple panel layout."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_panel_left"), str8_lit_comp("Creates a new panel to the left of the active panel."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_panel_up"), str8_lit_comp("Creates a new panel at the top of the active panel."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_panel_right"), str8_lit_comp("Creates a new panel to the right of the active panel."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_panel_down"), str8_lit_comp("Creates a new panel at the bottom of the active panel."), str8_lit_comp("panel"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("split_panel"), str8_lit_comp("Creates a new panel in a given direction, and moves a tab to it, if specified."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("rotate_panel_columns"), str8_lit_comp("Rotates all panels at the closest column level of the panel hierarchy."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("next_panel"), str8_lit_comp("Cycles the active panel forward."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("prev_panel"), str8_lit_comp("Cycles the active panel backwards."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_panel"), str8_lit_comp("Focuses a new panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_panel_right"), str8_lit_comp("Focuses a panel rightward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_panel_left"), str8_lit_comp("Focuses a panel leftward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_panel_up"), str8_lit_comp("Focuses a panel upward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_panel_down"), str8_lit_comp("Focuses a panel downward of the currently focused panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("undo"), str8_lit_comp("Undoes the previous action."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("redo"), str8_lit_comp("Redoes the first previously undone action."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("go_back"), str8_lit_comp("Returns to the previously selected panel and tab in recorded history."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("go_forward"), str8_lit_comp("Returns to the next selected panel and tab in recorded history."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("close_panel"), str8_lit_comp("Closes the currently active panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("focus_tab"), str8_lit_comp("Focuses the passed tab within its containing panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("next_tab"), str8_lit_comp("Focuses the next tab on the active panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("prev_tab"), str8_lit_comp("Focuses the previous tab on the active panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_tab_right"), str8_lit_comp("Moves the selected tab right one slot."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_tab_left"), str8_lit_comp("Moves the selected tab left one slot."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_tab"), str8_lit_comp("Opens a new tab."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:tab_commands"), str8_lit_comp("commands"), CTRL_EntityKind_Null}}, { str8_lit_comp("build_tab"), str8_lit_comp("Opens a new tab with the parameterized view specification."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("duplicate_tab"), str8_lit_comp("Duplicates a tab."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Tab, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("copy_tab_full_path"), str8_lit_comp("Copies the full path of the file being viewed by this tab."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Tab, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("close_tab"), str8_lit_comp("Closes the currently opened tab."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Tab, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_view"), str8_lit_comp("Moves a view to a new panel."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("tab_bar_top"), str8_lit_comp("Anchors a panel's tab bar to the top of the panel."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("tab_bar_bottom"), str8_lit_comp("Anchors a panel's tab bar to the bottom of the panel."), str8_lit_comp(""), str8_lit_comp("$tab,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("tab_settings"), str8_lit_comp("Opens settings for a tab."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_current_path"), str8_lit_comp("Sets the debugger's current path, which is used as a starting point when browsing for files."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open"), str8_lit_comp("Opens a file."), str8_lit_comp("code,source,file"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("switch"), str8_lit_comp("Switches to a recent file."), str8_lit_comp("code,source,file"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:recent_files, query:source_files"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("switch_to_partner_file"), str8_lit_comp("Switches to the focused file's partner; or from header to implementation or vice versa."), str8_lit_comp("code,source,file"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("record_file_in_project"), str8_lit_comp("Records the passed file path as a recent file in the currently loaded project."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("show_file_in_explorer"), str8_lit_comp("Opens the operating system's file explorer and shows the selected file."), str8_lit_comp(""), str8_lit_comp("$file,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("go_to_disassembly"), str8_lit_comp("Goes to the disassembly, if any, for a given source code line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("go_to_source"), str8_lit_comp("Goes to the source code, if any, for a given disassembly line."), str8_lit_comp("code,source,disassembly,disasm"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_file_replacement_path"), str8_lit_comp("Sets the path which should be used as the replacement for the passed file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_user"), str8_lit_comp("Creates a new user file, and sets the current user path as that file's path."), str8_lit_comp("new,user,project,layout"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("new_project"), str8_lit_comp("Creates a new project file, and sets the current project path as that file's path."), str8_lit_comp("new,user,project,layout"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_user"), str8_lit_comp("Opens a user file path, immediately loading it, and begins autosaving to it."), str8_lit_comp("load,user,project,layout"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_project"), str8_lit_comp("Opens a project file path, immediately loading it, and begins autosaving to it."), str8_lit_comp("project,project,session"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_recent_project"), str8_lit_comp("Opens a recently used project file."), str8_lit_comp("project,project,session"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:recent_projects"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_user"), str8_lit_comp("Saves user data to a file, and sets the current user path as that path."), str8_lit_comp("load,user,project,layout"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_project"), str8_lit_comp("Saves project data to a file, and sets the current project path as that path."), str8_lit_comp("project,project,session"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("record_user_as_last_opened"), str8_lit_comp("Records a file path as the last opened user."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("record_project_in_user"), str8_lit_comp("Records a file path as a recent project in user data."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("write_user_data"), str8_lit_comp("Writes user data to the active user file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("write_project_data"), str8_lit_comp("Writes project data to the active project file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("user_settings"), str8_lit_comp("Opens user settings."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("project_settings"), str8_lit_comp("Opens project settings."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("edit"), str8_lit_comp("Edits the current selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("accept"), str8_lit_comp("Accepts current changes, or answers prompts in the affirmative."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("cancel"), str8_lit_comp("Rejects current changes, exits temporary menus, or answers prompts in the negative."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_left"), str8_lit_comp("Moves the cursor or selection left."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_right"), str8_lit_comp("Moves the cursor or selection right."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up"), str8_lit_comp("Moves the cursor or selection up."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down"), str8_lit_comp("Moves the cursor or selection down."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_left_select"), str8_lit_comp("Moves the cursor or selection left, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_right_select"), str8_lit_comp("Moves the cursor or selection right, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_select"), str8_lit_comp("Moves the cursor or selection up, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_select"), str8_lit_comp("Moves the cursor or selection down, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_left_chunk"), str8_lit_comp("Moves the cursor or selection left one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_right_chunk"), str8_lit_comp("Moves the cursor or selection right one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_chunk"), str8_lit_comp("Moves the cursor or selection up one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_chunk"), str8_lit_comp("Moves the cursor or selection down one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_page"), str8_lit_comp("Moves the cursor or selection up one page."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_page"), str8_lit_comp("Moves the cursor or selection down one page."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_whole"), str8_lit_comp("Moves the cursor or selection to the beginning of the relevant content."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_whole"), str8_lit_comp("Moves the cursor or selection to the end of the relevant content."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_left_chunk_select"), str8_lit_comp("Moves the cursor or selection left one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_right_chunk_select"), str8_lit_comp("Moves the cursor or selection right one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_chunk_select"), str8_lit_comp("Moves the cursor or selection up one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_chunk_select"), str8_lit_comp("Moves the cursor or selection down one chunk."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_page_select"), str8_lit_comp("Moves the cursor or selection up one page, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_page_select"), str8_lit_comp("Moves the cursor or selection down one page, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_whole_select"), str8_lit_comp("Moves the cursor or selection to the beginning of the relevant content, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_whole_select"), str8_lit_comp("Moves the cursor or selection to the end of the relevant content, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_up_reorder"), str8_lit_comp("Moves the cursor or selection up, while swapping the currently selected element with that upward."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_down_reorder"), str8_lit_comp("Moves the cursor or selection down, while swapping the currently selected element with that downward."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_home"), str8_lit_comp("Moves the cursor to the beginning of the line."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_end"), str8_lit_comp("Moves the cursor to the end of the line."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_home_select"), str8_lit_comp("Moves the cursor to the beginning of the line, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_end_select"), str8_lit_comp("Moves the cursor to the end of the line, while selecting."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("select_all"), str8_lit_comp("Selects everything possible."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("delete_single"), str8_lit_comp("Deletes a single element to the right of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("delete_chunk"), str8_lit_comp("Deletes a chunk to the right of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("backspace_single"), str8_lit_comp("Deletes a single element to the left of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("backspace_chunk"), str8_lit_comp("Deletes a chunk to the left of the cursor, or the active selection."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("copy"), str8_lit_comp("Copies the active selection to the clipboard."), str8_lit_comp(""), str8_lit_comp("$text_rng,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("cut"), str8_lit_comp("Copies the active selection to the clipboard, then deletes it."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("paste"), str8_lit_comp("Pastes the current contents of the clipboard."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("insert_text"), str8_lit_comp("Inserts the text that was used to cause this command."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_next"), str8_lit_comp("Moves the cursor or selection to the next element."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("move_prev"), str8_lit_comp("Moves the cursor or selection to the previous element."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("goto_line"), str8_lit_comp("Jumps to a line number in the current code file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_Cursor, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("goto_address"), str8_lit_comp("Jumps to an address in the current memory or disassembly view."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_Vaddr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("center_cursor"), str8_lit_comp("Snaps the current code view to center the cursor."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("contain_cursor"), str8_lit_comp("Snaps the current code view to contain the cursor."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_next"), str8_lit_comp("Searches the current code file forward (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_prev"), str8_lit_comp("Searches the current code file backwards (from the cursor) for the last searched string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_thread"), str8_lit_comp("Jumps to the passed thread in either source code, disassembly, or both if they're already open."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), CTRL_EntityKind_Thread}}, { str8_lit_comp("find_selected_thread"), str8_lit_comp("Jumps to the selected thread in either source code, disassembly, or both if they're already open."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("goto_name"), str8_lit_comp("Searches for the passed string as a file, a symbol in debug info, and more, then jumps to it if possible."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp("query:procedures"), str8_lit_comp("symbol_lister"), CTRL_EntityKind_Null}}, { str8_lit_comp("goto_name_at_cursor"), str8_lit_comp("Searches for the text at the cursor as a file, a symbol in debug info, and more, then jumps to it if possible."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_watch_expr"), str8_lit_comp("Adds or removes an expression to an opened watch view."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_watch_expr_at_cursor"), str8_lit_comp("Adds or removes the expression that the cursor or selection is currently over to an opened watch view."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_watch_expr_at_mouse"), str8_lit_comp("Adds or removes the expression that the mouse is currently over to an opened watch view."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("enable_cfg"), str8_lit_comp("Enables a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("disable_cfg"), str8_lit_comp("Disables a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("select_cfg"), str8_lit_comp("Selects a config tree, disabling all others of the same kind."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("deselect_cfg"), str8_lit_comp("Deselects a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("remove_cfg"), str8_lit_comp("Removes a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("name_cfg"), str8_lit_comp("Equips a config tree with a label."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("condition_cfg"), str8_lit_comp("Equips a config tree with a condition string."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("duplicate_cfg"), str8_lit_comp("Duplicates a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("relocate_cfg"), str8_lit_comp("Relocates a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_cfg_to_project"), str8_lit_comp("Saves the config tree to the project."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_breakpoint"), str8_lit_comp("Places a breakpoint at a given location (file path and line number, address, or symbol name)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_address_breakpoint"), str8_lit_comp("Places a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_function_breakpoint"), str8_lit_comp("Places a breakpoint on the first address of the specified function."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp("query:procedures"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_breakpoint"), str8_lit_comp("Places or removes a breakpoint at a given location (file path and line number, address, or symbol name)."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("remove_breakpoint"), str8_lit_comp("Removes an existing breakpoint."), str8_lit_comp("delete"), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("enable_breakpoint"), str8_lit_comp("Enables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("disable_breakpoint"), str8_lit_comp("Disables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("clear_breakpoints"), str8_lit_comp("Removes all breakpoints."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("list_breakpoints"), str8_lit_comp("Lists all breakpoints."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("clear_output"), str8_lit_comp("Clears all output."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_watch_pin"), str8_lit_comp("Places a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp("$watch_pins,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_watch_pin"), str8_lit_comp("Places or removes a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("load_debug_info"), str8_lit_comp("Loads a debug info file."), str8_lit_comp(""), str8_lit_comp("$debug_infos,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("unload_debug_info"), str8_lit_comp("Unloads a debug info file."), str8_lit_comp(""), str8_lit_comp("$debug_infos,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:debug_infos"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_type_view"), str8_lit_comp("Adds a new type view."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_file_path_map"), str8_lit_comp("Adds a new file path map."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("edit_user_theme"), str8_lit_comp("Edits the current user's theme."), str8_lit_comp("color"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_String, str8_lit_comp("query:themes"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("edit_project_theme"), str8_lit_comp("Edits the current project's theme."), str8_lit_comp("color"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_String, str8_lit_comp("query:themes"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_theme_color"), str8_lit_comp("Adds a new theme color."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("fork_theme"), str8_lit_comp("Imports all colors from the current theme so they can be individually edited."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_theme"), str8_lit_comp("Saves all theme colors to a new theme file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_and_set_theme"), str8_lit_comp("Saves all theme colors to a new theme file, and then sets that theme as the selected theme."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("set_next_statement"), str8_lit_comp("Sets the selected thread's instruction pointer to the cursor's position."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*1)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("add_target"), str8_lit_comp("Adds a new target."), str8_lit_comp("application,executable,debug"), str8_lit_comp("$targets,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("select_target"), str8_lit_comp("Selects a target."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("enable_target"), str8_lit_comp("Enables a target, in addition to all targets currently enabled."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("disable_target"), str8_lit_comp("Disables a target."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("remove_target"), str8_lit_comp("Removes a target."), str8_lit_comp("delete"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("register_as_jit_debugger"), str8_lit_comp("Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("find_code_location"), str8_lit_comp("Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("search"), str8_lit_comp("Begins searching within the active interface."), str8_lit_comp("sort,search,filter,find"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*1)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("search_backwards"), str8_lit_comp("Begins searching backwards within the active interface."), str8_lit_comp("sort,search,filter,find"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*1)|(RD_QueryFlag_SelectOldInput*1)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("pick_file"), str8_lit_comp("Opens the file browser to pick a file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("pick_folder"), str8_lit_comp("Opens the file browser to pick a folder."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*1)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("pick_file_or_folder"), str8_lit_comp("Opens the file browser to pick a file or folder."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*1)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("push_query"), str8_lit_comp("Opens a new temporary query interface."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("complete_query"), str8_lit_comp("Completes and closes a query."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("cancel_query"), str8_lit_comp("Closes a query."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("update_query"), str8_lit_comp("Updates a query input."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("open_event_buffer"), str8_lit_comp("Opens a new event buffer, to which debugger events will be written, for external processing."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("close_event_buffer"), str8_lit_comp("Closes an existing event buffer."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Cfg, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("toggle_dev_menu"), str8_lit_comp("Opens and closes the developer menu."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("log_marker"), str8_lit_comp("Logs a marker in the application log, to denote specific points in time within the log."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("watches"), str8_lit_comp("Opens a Watch tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("locals"), str8_lit_comp("Opens a Locals tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("registers"), str8_lit_comp("Opens a Registers tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("globals"), str8_lit_comp("Opens a Globals tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("thread_locals"), str8_lit_comp("Opens a Thread Locals tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("types"), str8_lit_comp("Opens a Types tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("procedures"), str8_lit_comp("Opens a Procedures tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("call_stack"), str8_lit_comp("Opens a Call Stack tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("targets"), str8_lit_comp("Opens a Targets tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("breakpoints"), str8_lit_comp("Opens a Breakpoints tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("watch_pins"), str8_lit_comp("Opens a Watch Pins tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("debug_infos"), str8_lit_comp("Opens a Debug Info tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("threads"), str8_lit_comp("Opens a Threads tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("processes"), str8_lit_comp("Opens a Processes tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("machines"), str8_lit_comp("Opens a Machines tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("modules"), str8_lit_comp("Opens a Modules tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("file_path_maps"), str8_lit_comp("Opens a File Path Map tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("type_views"), str8_lit_comp("Opens a Type Views tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("output"), str8_lit_comp("Opens a Output tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("text"), str8_lit_comp("Opens a Text tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("disasm"), str8_lit_comp("Opens a Disassembly tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("memory"), str8_lit_comp("Opens a Memory tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("bitmap"), str8_lit_comp("Opens a Bitmap tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("color"), str8_lit_comp("Opens a Color tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, { str8_lit_comp("geo3d"), str8_lit_comp("Opens a Geometry (3D) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}, }; struct {String8 string; CFG_Binding binding;} rd_default_binding_table[116] = { {str8_lit_comp("kill_all"), {OS_Key_F5, 0 |OS_Modifier_Shift }}, {str8_lit_comp("step_into_inst"), {OS_Key_F11, 0 |OS_Modifier_Alt}}, {str8_lit_comp("step_over_inst"), {OS_Key_F10, 0 |OS_Modifier_Alt}}, {str8_lit_comp("step_out"), {OS_Key_F11, 0 |OS_Modifier_Shift }}, {str8_lit_comp("halt"), {OS_Key_X, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("halt"), {OS_Key_Pause, 0 }}, {str8_lit_comp("run"), {OS_Key_F5, 0 }}, {str8_lit_comp("restart"), {OS_Key_F5, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("step_into"), {OS_Key_F11, 0 }}, {str8_lit_comp("step_over"), {OS_Key_F10, 0 }}, {str8_lit_comp("run_to_line"), {OS_Key_F10, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("set_next_statement"), {OS_Key_F10, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("inc_window_font_size"), {OS_Key_Equal, 0 |OS_Modifier_Alt}}, {str8_lit_comp("dec_window_font_size"), {OS_Key_Minus, 0 |OS_Modifier_Alt}}, {str8_lit_comp("window"), {OS_Key_N, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("toggle_fullscreen"), {OS_Key_Return, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("new_panel_right"), {OS_Key_P, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("new_panel_down"), {OS_Key_Minus, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("rotate_panel_columns"), {OS_Key_2, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("next_panel"), {OS_Key_Comma, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("prev_panel"), {OS_Key_Comma, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("focus_panel_right"), {OS_Key_Right, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("focus_panel_left"), {OS_Key_Left, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("focus_panel_up"), {OS_Key_Up, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("focus_panel_down"), {OS_Key_Down, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("undo"), {OS_Key_Z, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("redo"), {OS_Key_Y, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("go_back"), {OS_Key_Left, 0 |OS_Modifier_Alt}}, {str8_lit_comp("go_forward"), {OS_Key_Right, 0 |OS_Modifier_Alt}}, {str8_lit_comp("close_panel"), {OS_Key_P, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("next_tab"), {OS_Key_PageDown, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("prev_tab"), {OS_Key_PageUp, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("next_tab"), {OS_Key_Tab, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("prev_tab"), {OS_Key_Tab, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_tab_right"), {OS_Key_PageDown, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_tab_left"), {OS_Key_PageUp, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("close_tab"), {OS_Key_W, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("tab_bar_top"), {OS_Key_Up, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("tab_bar_bottom"), {OS_Key_Down, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("open_tab"), {OS_Key_T, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("open"), {OS_Key_O, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("switch"), {OS_Key_I, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("switch_to_partner_file"), {OS_Key_O, 0 |OS_Modifier_Alt}}, {str8_lit_comp("open_user"), {OS_Key_N, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("open_project"), {OS_Key_N, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("open_user"), {OS_Key_O, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("open_project"), {OS_Key_O, 0 |OS_Modifier_Ctrl |OS_Modifier_Alt}}, {str8_lit_comp("save_user"), {OS_Key_S, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("save_project"), {OS_Key_S, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("edit"), {OS_Key_F2, 0 }}, {str8_lit_comp("accept"), {OS_Key_Return, 0 }}, {str8_lit_comp("accept"), {OS_Key_Space, 0 }}, {str8_lit_comp("cancel"), {OS_Key_Esc, 0 }}, {str8_lit_comp("move_left"), {OS_Key_Left, 0 }}, {str8_lit_comp("move_right"), {OS_Key_Right, 0 }}, {str8_lit_comp("move_up"), {OS_Key_Up, 0 }}, {str8_lit_comp("move_down"), {OS_Key_Down, 0 }}, {str8_lit_comp("move_left_select"), {OS_Key_Left, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_right_select"), {OS_Key_Right, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_up_select"), {OS_Key_Up, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_down_select"), {OS_Key_Down, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_left_chunk"), {OS_Key_Left, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_right_chunk"), {OS_Key_Right, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_up_chunk"), {OS_Key_Up, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_down_chunk"), {OS_Key_Down, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_up_page"), {OS_Key_PageUp, 0 }}, {str8_lit_comp("move_down_page"), {OS_Key_PageDown, 0 }}, {str8_lit_comp("move_up_whole"), {OS_Key_Home, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_down_whole"), {OS_Key_End, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("move_left_chunk_select"), {OS_Key_Left, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_right_chunk_select"), {OS_Key_Right, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_up_chunk_select"), {OS_Key_Up, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_down_chunk_select"), {OS_Key_Down, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_up_page_select"), {OS_Key_PageUp, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_down_page_select"), {OS_Key_PageDown, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_up_whole_select"), {OS_Key_Home, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_down_whole_select"), {OS_Key_End, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("move_up_reorder"), {OS_Key_Up, 0 |OS_Modifier_Alt}}, {str8_lit_comp("move_down_reorder"), {OS_Key_Down, 0 |OS_Modifier_Alt}}, {str8_lit_comp("move_home"), {OS_Key_Home, 0 }}, {str8_lit_comp("move_end"), {OS_Key_End, 0 }}, {str8_lit_comp("move_home_select"), {OS_Key_Home, 0 |OS_Modifier_Shift }}, {str8_lit_comp("move_end_select"), {OS_Key_End, 0 |OS_Modifier_Shift }}, {str8_lit_comp("select_all"), {OS_Key_A, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("delete_single"), {OS_Key_Delete, 0 }}, {str8_lit_comp("delete_chunk"), {OS_Key_Delete, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("backspace_single"), {OS_Key_Backspace, 0 }}, {str8_lit_comp("backspace_chunk"), {OS_Key_Backspace, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("copy"), {OS_Key_C, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("copy"), {OS_Key_Insert, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("cut"), {OS_Key_X, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("paste"), {OS_Key_V, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("paste"), {OS_Key_Insert, 0 |OS_Modifier_Shift }}, {str8_lit_comp("insert_text"), {OS_Key_Null, 0 }}, {str8_lit_comp("move_next"), {OS_Key_Tab, 0 }}, {str8_lit_comp("move_prev"), {OS_Key_Tab, 0 |OS_Modifier_Shift }}, {str8_lit_comp("goto_line"), {OS_Key_G, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("goto_address"), {OS_Key_G, 0 |OS_Modifier_Alt}}, {str8_lit_comp("search"), {OS_Key_F, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("search_backwards"), {OS_Key_R, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("find_next"), {OS_Key_F3, 0 }}, {str8_lit_comp("find_prev"), {OS_Key_F3, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("find_selected_thread"), {OS_Key_F4, 0 }}, {str8_lit_comp("goto_name"), {OS_Key_J, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("goto_name_at_cursor"), {OS_Key_F12, 0 }}, {str8_lit_comp("toggle_watch_expr_at_cursor"), {OS_Key_W, 0 |OS_Modifier_Alt}}, {str8_lit_comp("toggle_watch_expr_at_mouse"), {OS_Key_D, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("toggle_watch_pin"), {OS_Key_F9, 0 |OS_Modifier_Ctrl }}, {str8_lit_comp("toggle_breakpoint"), {OS_Key_F9, 0 }}, {str8_lit_comp("add_address_breakpoint"), {OS_Key_F9, 0 |OS_Modifier_Shift }}, {str8_lit_comp("add_function_breakpoint"), {OS_Key_F9, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("attach"), {OS_Key_F6, 0 |OS_Modifier_Shift }}, {str8_lit_comp("open_palette"), {OS_Key_F1, 0 }}, {str8_lit_comp("open_palette"), {OS_Key_P, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift }}, {str8_lit_comp("log_marker"), {OS_Key_M, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, {str8_lit_comp("toggle_dev_menu"), {OS_Key_D, 0 |OS_Modifier_Ctrl |OS_Modifier_Shift |OS_Modifier_Alt}}, }; String8 rd_binding_version_remap_old_name_table[8] = { str8_lit_comp("commands"), str8_lit_comp("load_user"), str8_lit_comp("load_profile"), str8_lit_comp("load_project"), str8_lit_comp("open_profile"), str8_lit_comp("address_breakpoint"), str8_lit_comp("function_breakpoint"), str8_lit_comp("toggle_breakpoint_cursor"), }; String8 rd_binding_version_remap_new_name_table[8] = { str8_lit_comp("run_command"), str8_lit_comp("open_user"), str8_lit_comp("open_profile"), str8_lit_comp("open_project"), str8_lit_comp("open_project"), str8_lit_comp("add_address_breakpoint"), str8_lit_comp("add_function_breakpoint"), str8_lit_comp("toggle_breakpoint"), }; String8 rd_icon_kind_text_table[75] = { str8_lit_comp(""), str8_lit_comp("b"), str8_lit_comp("c"), str8_lit_comp("B"), str8_lit_comp("C"), str8_lit_comp("f"), str8_lit_comp("F"), str8_lit_comp("g"), str8_lit_comp("h"), str8_lit_comp("r"), str8_lit_comp("s"), str8_lit_comp("i"), str8_lit_comp("w"), str8_lit_comp("W"), str8_lit_comp("k"), str8_lit_comp("K"), str8_lit_comp("L"), str8_lit_comp("R"), str8_lit_comp("U"), str8_lit_comp("D"), str8_lit_comp("G"), str8_lit_comp("P"), str8_lit_comp("3"), str8_lit_comp("p"), str8_lit_comp("O"), str8_lit_comp("o"), str8_lit_comp("!"), str8_lit_comp("1"), str8_lit_comp("V"), str8_lit_comp("<"), str8_lit_comp(">"), str8_lit_comp("^"), str8_lit_comp("v"), str8_lit_comp("9"), str8_lit_comp("0"), str8_lit_comp("7"), str8_lit_comp("8"), str8_lit_comp("+"), str8_lit_comp("-"), str8_lit_comp("'"), str8_lit_comp("\""), str8_lit_comp("M"), str8_lit_comp("."), str8_lit_comp("x"), str8_lit_comp("q"), str8_lit_comp("j"), str8_lit_comp("u"), str8_lit_comp("m"), str8_lit_comp("n"), str8_lit_comp("l"), str8_lit_comp("a"), str8_lit_comp("z"), str8_lit_comp("y"), str8_lit_comp("X"), str8_lit_comp("Y"), str8_lit_comp("S"), str8_lit_comp("T"), str8_lit_comp("Z"), str8_lit_comp("d"), str8_lit_comp("N"), str8_lit_comp("E"), str8_lit_comp("H"), str8_lit_comp("e"), str8_lit_comp("I"), str8_lit_comp("J"), str8_lit_comp("A"), str8_lit_comp("?"), str8_lit_comp("4"), str8_lit_comp("5"), str8_lit_comp("6"), str8_lit_comp("&"), str8_lit_comp("*"), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp("#"), }; String8 rd_code_color_slot_name_table[14] = { str8_lit_comp("code_default"), str8_lit_comp("code_symbol"), str8_lit_comp("code_type"), str8_lit_comp("code_local"), str8_lit_comp("code_register"), str8_lit_comp("code_keyword"), str8_lit_comp("code_delimiter_or_operator"), str8_lit_comp("code_numeric"), str8_lit_comp("code_numeric_alt_digit_group"), str8_lit_comp("code_string"), str8_lit_comp("code_meta"), str8_lit_comp("code_comment"), str8_lit_comp("code_line_numbers"), str8_lit_comp("code_line_numbers_selected"), }; String8 rd_theme_preset_display_string_table[11] = { str8_lit_comp("Default (Dark)"), str8_lit_comp("Default (Light)"), str8_lit_comp("VS (Dark)"), str8_lit_comp("VS (Light)"), str8_lit_comp("Solarized (Dark)"), str8_lit_comp("Solarized (Light)"), str8_lit_comp("Handmade Hero"), str8_lit_comp("Naysayer"), str8_lit_comp("4coder"), str8_lit_comp("Grove"), str8_lit_comp("Far Manager"), }; String8 rd_theme_preset_code_string_table[11] = { str8_lit_comp("default_dark"), str8_lit_comp("default_light"), str8_lit_comp("vs_dark"), str8_lit_comp("vs_light"), str8_lit_comp("solarized_dark"), str8_lit_comp("solarized_light"), str8_lit_comp("handmade_hero"), str8_lit_comp("naysayer"), str8_lit_comp("four_coder"), str8_lit_comp("grove"), str8_lit_comp("far_manager"), }; String8 rd_theme_preset_cfg_string_table[11] = { str8_lit_comp("theme:\n{\n theme_color: {tags:\"background\", value: 0x1b1b1bff }\n theme_color: {tags:\"alt background\", value: 0x222222ff }\n theme_color: {tags:\"pop background\", value: 0x355b6eff }\n theme_color: {tags:\"fresh background\", value: 0x31393dff }\n theme_color: {tags:\"match background\", value: 0x31393dff }\n theme_color: {tags:\"border\", value: 0x404040ff }\n theme_color: {tags:\"text\", value: 0xe5e5e5ff }\n theme_color: {tags:\"weak text\", value: 0xa4a4a4ff }\n theme_color: {tags:\"good text\", value: 0x32a852ff }\n theme_color: {tags:\"neutral text\", value: 0x3a90bbff }\n theme_color: {tags:\"bad text\", value: 0xcf5242ff }\n theme_color: {tags:\"hover\", value: 0xffffffff }\n theme_color: {tags:\"focus overlay\", value: 0xfda20012 }\n theme_color: {tags:\"focus border\", value: 0xfda200ff }\n theme_color: {tags:\"cursor\", value: 0x8aff00ff }\n theme_color: {tags:\"selection\", value: 0x99ccff0f }\n theme_color: {tags:\"inactive background\", value: 0x0000002f }\n theme_color: {tags:\"drop_shadow\", value: 0x0000007f }\n theme_color: {tags:\"good_pop background\", value: 0x2c5b36ff }\n theme_color: {tags:\"good_pop border\", value: 0x568761ff }\n theme_color: {tags:\"good_pop hover\", value: 0xe3f5d3ff }\n theme_color: {tags:\"good_pop weak text\", value: 0xe3f5d3ff }\n theme_color: {tags:\"bad_pop background\", value: 0x803425ff }\n theme_color: {tags:\"bad_pop hover\", value: 0xff825cff }\n theme_color: {tags:\"code_default\", value: 0xcbcbcbff }\n theme_color: {tags:\"code_symbol\", value: 0x42a2cfff }\n theme_color: {tags:\"code_type\", value: 0xfec746ff }\n theme_color: {tags:\"code_local\", value: 0x98bc80ff }\n theme_color: {tags:\"code_register\", value: 0xb7afd5ff }\n theme_color: {tags:\"code_keyword\", value: 0xb38d4cff }\n theme_color: {tags:\"code_delimiter_or_operator\", value: 0x767676ff }\n theme_color: {tags:\"code_numeric\", value: 0x98abb1ff }\n theme_color: {tags:\"code_numeric_alt_digit_group\", value: 0x738287ff }\n theme_color: {tags:\"code_string\", value: 0x98abb1ff }\n theme_color: {tags:\"code_meta\", value: 0xd96759ff }\n theme_color: {tags:\"code_comment\", value: 0x717171ff }\n theme_color: {tags:\"line_info_0\", value: 0x4f3022ff }\n theme_color: {tags:\"line_info_1\", value: 0x4f3e15ff }\n theme_color: {tags:\"line_info_2\", value: 0x434e2aff }\n theme_color: {tags:\"line_info_3\", value: 0x36241fff }\n theme_color: {tags:\"line_info_4\", value: 0x4f3022ff }\n theme_color: {tags:\"line_info_5\", value: 0x4f3e15ff }\n theme_color: {tags:\"line_info_6\", value: 0x434e2aff }\n theme_color: {tags:\"line_info_7\", value: 0x36241fff }\n theme_color: {tags:\"thread_0\", value: 0xffcb7fff }\n theme_color: {tags:\"thread_1\", value: 0xb2ff65ff }\n theme_color: {tags:\"thread_2\", value: 0xff99e5ff }\n theme_color: {tags:\"thread_3\", value: 0x6598ffff }\n theme_color: {tags:\"thread_4\", value: 0x65ffcbff }\n theme_color: {tags:\"thread_5\", value: 0xff9819ff }\n theme_color: {tags:\"thread_6\", value: 0x9932ffff }\n theme_color: {tags:\"thread_7\", value: 0x65ff4cff }\n theme_color: {tags:\"thread_unwound\", value: 0xb2ccd8ff }\n theme_color: {tags:\"thread_error\", value: 0xb23219ff }\n theme_color: {tags:\"breakpoint\", value: 0xa72911ff }\n theme_color: {tags:\"floating background\", value: 0x1b1b1baf }\n theme_color: {tags:\"floating background alt\", value: 0x0000005f }\n theme_color: {tags:\"floating background fresh\", value: 0x31393d5f }\n theme_color: {tags:\"floating border\", value: 0xbfbfbf1f }\n theme_color: {tags:\"floating scroll_bar background\", value: 0x3b3b3b5f }\n theme_color: {tags:\"floating scroll_bar border\", value: 0x5f5f5f5f }\n theme_color: {tags:\"menu_bar background\", value: 0x2b3740ff }\n theme_color: {tags:\"menu_bar border\", value: 0x3e4c57ff }\n theme_color: {tags:\"scroll_bar background\", value: 0x2b2b2bff }\n theme_color: {tags:\"scroll_bar border\", value: 0x3f3f3fff }\n theme_color: {tags:\"implicit background\", value: 0x00000000 }\n theme_color: {tags:\"implicit border\", value: 0x00000000 }\n theme_color: {tags:\"hollow background\", value: 0x00000000 }\n theme_color: {tags:\"hollow border\", value: 0xffffff1f }\n theme_color: {tags:\"tab background\", value: 0x6f5135ff }\n theme_color: {tags:\"tab border\", value: 0x8a6e54ff }\n theme_color: {tags:\"tab inactive background\", value: 0x2b3740ff }\n theme_color: {tags:\"tab inactive border\", value: 0x3e4c57ff }\n theme_color: {tags:\"tab auto background\", value: 0x693847ff }\n theme_color: {tags:\"tab auto border\", value: 0x9e6274ff }\n theme_color: {tags:\"tab auto inactive background\", value: 0x2f2633ff }\n theme_color: {tags:\"tab auto inactive border\", value: 0x685073ff }\n theme_color: {tags:\"drop_site background\", value: 0xffffff05 }\n theme_color: {tags:\"drop_site border\", value: 0xffffff0f }\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{ tags: background , value: 0xffffffff }\n theme_color:{ tags: \"alt background\" , value: 0xf8f8f8ff }\n theme_color:{ tags: \"pop background\" , value: 0xcbe4f2ff }\n theme_color:{ tags: \"menu_bar pop background\" , value: 0x5aabd9ff }\n theme_color:{ tags: \"fresh background\" , value: 0xeaddceff }\n theme_color:{ tags: \"match background\" , value: 0xc1e9c4ff }\n theme_color:{ tags: border , value: 0xcbcbcbff }\n theme_color:{ tags: text , value: 0xff }\n theme_color:{ tags: \"weak text\" , value: 0x727272ff }\n theme_color:{ tags: \"good text\" , value: 0x217538ff }\n theme_color:{ tags: \"neutral text\" , value: 0x1a5b7cff }\n theme_color:{ tags: \"bad text\" , value: 0x972717ff }\n theme_color:{ tags: hover , value: 0xff }\n theme_color:{ tags: \"focus overlay\" , value: 0x67ff4b }\n theme_color:{ tags: \"focus border\" , value: 0x67ffff }\n theme_color:{ tags: cursor , value: 0xff }\n theme_color:{ tags: selection , value: 0x283d5166 }\n theme_color:{ tags: \"inactive background\" , value: 0x8 }\n theme_color:{ tags: drop_shadow , value: 0xb }\n theme_color:{ tags: \"good_pop background\" , value: 0x90c09aff }\n theme_color:{ tags: \"good_pop border\" , value: 0x1e7231ff }\n theme_color:{ tags: \"good_pop hover\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"good_pop weak text\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"good_pop text\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"bad_pop background\" , value: 0xa93620ff }\n theme_color:{ tags: \"bad_pop text\" , value: 0xffffffff }\n theme_color:{ tags: \"bad_pop text weak\" , value: 0xffffffff }\n theme_color:{ tags: \"menu_bar bad_pop background\" , value: 0xff2a00ff }\n theme_color:{ tags: \"menu_bar bad_pop text\" , value: 0xffffffff }\n theme_color:{ tags: \"bad_pop hover\" , value: 0xff825cff }\n theme_color:{ tags: code_default , value: 0x80808ff }\n theme_color:{ tags: code_symbol , value: 0x4ac3ff }\n theme_color:{ tags: code_type , value: 0xf46200ff }\n theme_color:{ tags: code_local , value: 0x317c00ff }\n theme_color:{ tags: code_register , value: 0x9a00ffff }\n theme_color:{ tags: code_keyword , value: 0xff0600ff }\n theme_color:{ tags: code_delimiter_or_operator , value: 0x8a8a8aff }\n theme_color:{ tags: code_numeric , value: 0x7d49ff }\n theme_color:{ tags: code_numeric_alt_digit_group , value: 0xb56aff }\n theme_color:{ tags: code_string , value: 0x63549fff }\n theme_color:{ tags: code_meta , value: 0xd96759ff }\n theme_color:{ tags: code_comment , value: 0x717171ff }\n theme_color:{ tags: line_info_0 , value: 0xe6d5cdff }\n theme_color:{ tags: line_info_1 , value: 0xdbcfb2ff }\n theme_color:{ tags: line_info_2 , value: 0xddeac1ff }\n theme_color:{ tags: line_info_3 , value: 0xddc4bdff }\n theme_color:{ tags: line_info_4 , value: 0xba917eff }\n theme_color:{ tags: thread_0 , value: 0xffa700ff }\n theme_color:{ tags: thread_1 , value: 0xb41fff }\n theme_color:{ tags: thread_2 , value: 0xff99e5ff }\n theme_color:{ tags: thread_3 , value: 0x6598ffff }\n theme_color:{ tags: thread_4 , value: 0x65ffcbff }\n theme_color:{ tags: thread_5 , value: 0xff9819ff }\n theme_color:{ tags: thread_6 , value: 0x9932ffff }\n theme_color:{ tags: thread_7 , value: 0x65ff4cff }\n theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff }\n theme_color:{ tags: thread_error , value: 0xb23219ff }\n theme_color:{ tags: breakpoint , value: 0xff2800ff }\n theme_color:{ tags: \"floating background\" , value: 0xffffffc7 }\n theme_color:{ tags: \"floating background alt\" , value: 0x23 }\n theme_color:{ tags: \"floating background fresh\" , value: 0xeaddceff }\n theme_color:{ tags: \"floating border\" , value: 0x88888884 }\n theme_color:{ tags: \"scroll_bar background\" , value: 0xe9e9e9ff }\n theme_color:{ tags: \"scroll_bar border\" , value: 0x5f5f5f5f }\n theme_color:{ tags: \"floating scroll_bar background\" , value: 0xe9e9e9ff }\n theme_color:{ tags: \"floating scroll_bar border\" , value: 0x5f5f5f5f }\n theme_color:{ tags: \"menu_bar background\" , value: 0x2b6b9aff }\n theme_color:{ tags: \"menu_bar border\" , value: 0x4d }\n theme_color:{ tags: \"menu_bar text\" , value: 0xffffffff }\n theme_color:{ tags: \"menu_bar text weak\" , value: 0xffffffff }\n theme_color:{ tags: \"good menu_bar text\" , value: 0x70db8dff }\n theme_color:{ tags: \"bad menu_bar text\" , value: 0xffa79bff }\n theme_color:{ tags: \"neutral menu_bar text\" , value: 0xc4dbe7ff }\n theme_color:{ tags: \"implicit background\" , value: 0x00000000 }\n theme_color:{ tags: \"implicit border\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow background\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow border\" , value: 0xffffff1f }\n theme_color:{ tags: \"tab text\" , value: 0xffffffff }\n theme_color:{ tags: \"tab text weak\" , value: 0xffffffff }\n theme_color:{ tags: \"tab background\" , value: 0xb67e48ff }\n theme_color:{ tags: \"tab border\" , value: 0x875b31ff }\n theme_color:{ tags: \"tab inactive background\" , value: 0xcacacaff }\n theme_color:{ tags: \"tab inactive border\" , value: 0xb5b5b5ff }\n theme_color:{ tags: \"tab auto background\" , value: 0xc41c69ff }\n theme_color:{ tags: \"tab auto border\" , value: 0x981039ff }\n theme_color:{ tags: \"tab auto inactive background\" , value: 0x9b88a3ff }\n theme_color:{ tags: \"tab auto inactive border\" , value: 0x373737ff }\n theme_color:{ tags: \"drop_site background\" , value: 0xffffff05 }\n theme_color:{ tags: \"drop_site border\" , value: 0xffffff0f }\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{ tags: background , value: 0x1f1f1fff }\n theme_color:{ tags: \"alt background\" , value: 0x222222ff }\n theme_color:{ tags: \"pop background\" , value: 0x383167ff }\n theme_color:{ tags: \"fresh background\" , value: 0x31393dff }\n theme_color:{ tags: \"match background\" , value: 0x31393dff }\n theme_color:{ tags: border , value: 0x404040ff }\n theme_color:{ tags: text , value: 0xe5e5e5ff }\n theme_color:{ tags: \"weak text\" , value: 0xa4a4a4ff }\n theme_color:{ tags: \"good text\" , value: 0x32a852ff }\n theme_color:{ tags: \"neutral text\" , value: 0x3a90bbff }\n theme_color:{ tags: \"bad text\" , value: 0xcf5242ff }\n theme_color:{ tags: hover , value: 0xffffffff }\n theme_color:{ tags: \"focus overlay\" , value: 0x7160e81e }\n theme_color:{ tags: \"focus border\" , value: 0x7160e8ff }\n theme_color:{ tags: cursor , value: 0x8aff00ff }\n theme_color:{ tags: selection , value: 0x99ccff0f }\n theme_color:{ tags: \"inactive background\" , value: 0x0000002f }\n theme_color:{ tags: drop_shadow , value: 0x0000007f }\n theme_color:{ tags: \"good_pop background\" , value: 0x2c5b36ff }\n theme_color:{ tags: \"good_pop border\" , value: 0x568761ff }\n theme_color:{ tags: \"good_pop hover\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"good_pop weak text\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"bad_pop background\" , value: 0x803425ff }\n theme_color:{ tags: \"bad_pop hover\" , value: 0xff825cff }\n theme_color:{ tags: code_default , value: 0xe0e0e0ff }\n theme_color:{ tags: code_symbol , value: 0xdcdcaaff }\n theme_color:{ tags: code_type , value: 0x4ec9b0ff }\n theme_color:{ tags: code_local , value: 0x9cdcfeff }\n theme_color:{ tags: code_register , value: 0xb7afd5ff }\n theme_color:{ tags: code_keyword , value: 0x569cd6ff }\n theme_color:{ tags: code_delimiter_or_operator , value: 0x767676ff }\n theme_color:{ tags: code_numeric , value: 0xb5cea8ff }\n theme_color:{ tags: code_numeric_alt_digit_group , value: 0x7c986dff }\n theme_color:{ tags: code_string , value: 0xd69d85ff }\n theme_color:{ tags: code_meta , value: 0x9b9b9bff }\n theme_color:{ tags: code_comment , value: 0x51a644ff }\n theme_color:{ tags: line_info_0 , value: 0x4f3022ff }\n theme_color:{ tags: line_info_1 , value: 0x4f3e15ff }\n theme_color:{ tags: line_info_2 , value: 0x434e2aff }\n theme_color:{ tags: line_info_3 , value: 0x36241fff }\n theme_color:{ tags: line_info_4 , value: 0x4f3022ff }\n theme_color:{ tags: line_info_5 , value: 0x4f3e15ff }\n theme_color:{ tags: line_info_6 , value: 0x434e2aff }\n theme_color:{ tags: line_info_7 , value: 0x36241fff }\n theme_color:{ tags: thread_0 , value: 0xffdc48ff }\n theme_color:{ tags: thread_1 , value: 0xb2ff65ff }\n theme_color:{ tags: thread_2 , value: 0xff99e5ff }\n theme_color:{ tags: thread_3 , value: 0x6598ffff }\n theme_color:{ tags: thread_4 , value: 0x65ffcbff }\n theme_color:{ tags: thread_5 , value: 0xff9819ff }\n theme_color:{ tags: thread_6 , value: 0x9932ffff }\n theme_color:{ tags: thread_7 , value: 0x65ff4cff }\n theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff }\n theme_color:{ tags: thread_error , value: 0xb23219ff }\n theme_color:{ tags: breakpoint , value: 0xa72911ff }\n theme_color:{ tags: \"floating background\" , value: 0x1b1b1baf }\n theme_color:{ tags: \"floating background alt\" , value: 0x0000005f }\n theme_color:{ tags: \"floating background fresh\" , value: 0x31393d5f }\n theme_color:{ tags: \"floating border\" , value: 0xbfbfbf1f }\n theme_color:{ tags: \"floating scroll_bar background\" , value: 0x3b3b3b5f }\n theme_color:{ tags: \"floating scroll_bar border\" , value: 0x5f5f5f5f }\n theme_color:{ tags: \"scroll_bar background\" , value: 0x2b2b2bff }\n theme_color:{ tags: \"scroll_bar border\" , value: 0x3f3f3fff }\n theme_color:{ tags: \"implicit background\" , value: 0x00000000 }\n theme_color:{ tags: \"implicit border\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow background\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow border\" , value: 0xffffff1f }\n theme_color:{ tags: \"tab background\" , value: 0x333333ff }\n theme_color:{ tags: \"tab border\" , value: 0x7160e8ff }\n theme_color:{ tags: \"tab inactive background\" , value: 0x171717ff }\n theme_color:{ tags: \"tab inactive border\" , value: 0x3e4c57ff }\n theme_color:{ tags: \"tab auto background\" , value: 0x3f386dff }\n theme_color:{ tags: \"tab auto border\" , value: 0x7160e8ff }\n theme_color:{ tags: \"tab auto inactive background\" , value: 0x2f2633ff }\n theme_color:{ tags: \"tab auto inactive border\" , value: 0x685073ff }\n theme_color:{ tags: \"drop_site background\" , value: 0xffffff05 }\n theme_color:{ tags: \"drop_site border\" , value: 0xffffff0f }\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0xffffffff}\n theme_color:{tags: \"alt background\", value: 0xefefefff}\n theme_color:{tags: \"pop background\", value: 0xe3eaf2ff}\n theme_color:{tags: \"fresh background\", value: 0xeccbbeff}\n theme_color:{tags: \"match background\", value: 0xedcbf9ff}\n theme_color:{tags: border, value: 0xe7e7e7ff}\n theme_color:{tags: text, value: 0xff}\n theme_color:{tags: \"weak text\", value: 0x353535ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: hover, value: 0xa7ffff}\n theme_color:{tags: \"focus overlay\", value: 0x8eff3f}\n theme_color:{tags: \"focus border\", value: 0x8effff}\n theme_color:{tags: cursor, value: 0xff}\n theme_color:{tags: selection, value: 0x56aaff77}\n theme_color:{tags: \"inactive background\", value: 0x17}\n theme_color:{tags: drop_shadow, value: 0xe7b27}\n theme_color:{tags: \"good_pop background\", value: 0x21a43dff}\n theme_color:{tags: \"good_pop border\", value: 0x21a43dff}\n theme_color:{tags: \"good_pop hover\", value: 0xe3f5d3ff}\n theme_color:{tags: \"good_pop weak text\", value: 0xe3f5d3ff}\n theme_color:{tags: \"good_pop text\", value: 0xe3f5d3ff}\n theme_color:{tags: \"bad_pop background\", value: 0xcb3f23ff}\n theme_color:{tags: \"bad_pop text\", value: 0xffcdc4ff}\n theme_color:{tags: \"bad_pop text weak\", value: 0xffcdc4ff}\n theme_color:{tags: \"bad_pop hover\", value: 0xff825cff}\n theme_color:{tags: code_default, value: 0x000000ff}\n theme_color:{tags: code_symbol, value: 0x74531fff}\n theme_color:{tags: code_type, value: 0x2b91afff}\n theme_color:{tags: code_local, value: 0x1f377fff}\n theme_color:{tags: code_register, value: 0x8a1bffff}\n theme_color:{tags: code_keyword, value: 0x0000ffff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x767676ff}\n theme_color:{tags: code_numeric, value: 0xff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x1d1d1dff}\n theme_color:{tags: code_string, value: 0xa61515ff}\n theme_color:{tags: code_meta, value: 0x808080ff}\n theme_color:{tags: code_comment, value: 0x008000ff}\n theme_color:{tags: line_info_0, value: 0xb5d9c8ff}\n theme_color:{tags: line_info_1, value: 0xa9c1d0ff}\n theme_color:{tags: line_info_2, value: 0x99abc5ff}\n theme_color:{tags: line_info_3, value: 0xc6bcd5ff}\n theme_color:{tags: thread_0, value: 0xffb141ff}\n theme_color:{tags: thread_1, value: 0x66c407ff}\n theme_color:{tags: thread_unwound, value: 0x67b3d7ff}\n theme_color:{tags: thread_error, value: 0xff2900ff}\n theme_color:{tags: breakpoint, value: 0xff2800ff}\n theme_color:{tags: \"floating background\", value: 0xffffffff}\n theme_color:{tags: \"floating background alt\", value: 0x11}\n theme_color:{tags: \"floating background fresh\", value: 0xa0c2d318}\n theme_color:{tags: \"floating border\", value: 0x50}\n theme_color:{tags: \"floating scroll_bar background\", value: 0x3b3b3b5f}\n theme_color:{tags: \"floating scroll_bar border\", value: 0x5f5f5f5f}\n theme_color:{tags: \"menu_bar background\", value: 0xccd5f0ff}\n theme_color:{tags: \"menu_bar border\", value: 0xbabdc3ff}\n theme_color:{tags: \"scroll_bar background\", value: 0xe4e4e4ff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0xf5cc84ff}\n theme_color:{tags: \"tab border\", value: 0xae7718ff}\n theme_color:{tags: \"tab inactive background\", value: 0x3b4f81ff}\n theme_color:{tags: \"tab inactive text\", value: 0xffffffff}\n theme_color:{tags: \"tab inactive border\", value: 0x3b4f81ff}\n theme_color:{tags: \"tab auto background\", value: 0xe99595ff}\n theme_color:{tags: \"tab auto border\", value: 0xff6262ff}\n theme_color:{tags: \"tab auto inactive background\", value: 0xac6060ff}\n theme_color:{tags: \"tab auto inactive border\", value: 0xff6262ff}\n theme_color:{tags: \"drop_site background\", value: 0xffffff05}\n theme_color:{tags: \"drop_site border\", value: 0xa7ffff}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0x002a35ff}\n theme_color:{tags: \"alt background\", value: 0x053542ff}\n theme_color:{tags: \"pop background\", value: 0x355b6eff}\n theme_color:{tags: \"fresh background\", value: 0x31393dff}\n theme_color:{tags: \"match background\", value: 0x31393dff}\n theme_color:{tags: border, value: 0x65166ff}\n theme_color:{tags: text, value: 0xeee8d5ff}\n theme_color:{tags: \"weak text\", value: 0x93a1a1ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: hover, value: 0xca4b16ff}\n theme_color:{tags: \"focus overlay\", value: 0xca4b151f}\n theme_color:{tags: \"focus border\", value: 0xca4b16ff}\n theme_color:{tags: cursor, value: 0xca4b16ff}\n theme_color:{tags: selection, value: 0x99ccff0f}\n theme_color:{tags: \"inactive background\", value: 0x0000002f}\n theme_color:{tags: drop_shadow, value: 0x0000007f}\n theme_color:{tags: \"good_pop background\", value: 0x5f8700ff}\n theme_color:{tags: \"good_pop border\", value: 0x5f8700ff}\n theme_color:{tags: \"bad_pop background\", value: 0x810000ff}\n theme_color:{tags: code_default, value: 0x839496ff}\n theme_color:{tags: code_symbol, value: 0xb3880eff}\n theme_color:{tags: code_type, value: 0xb3880eff}\n theme_color:{tags: code_local, value: 0xeee8d5ff}\n theme_color:{tags: code_register, value: 0xeee8d5ff}\n theme_color:{tags: code_keyword, value: 0x849804ff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x839496ff}\n theme_color:{tags: code_numeric, value: 0x2aa198ff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x19766bff}\n theme_color:{tags: code_string, value: 0x2aa198ff}\n theme_color:{tags: code_meta, value: 0xca4b16ff}\n theme_color:{tags: code_comment, value: 0x586e75ff}\n theme_color:{tags: line_info_0, value: 0x4f3022ff}\n theme_color:{tags: line_info_1, value: 0x4f3e15ff}\n theme_color:{tags: line_info_2, value: 0x434e2aff}\n theme_color:{tags: line_info_3, value: 0x36241fff}\n theme_color:{tags: thread_0, value: 0xffcb7fff}\n theme_color:{tags: thread_1, value: 0xb2ff65ff}\n theme_color:{tags: thread_unwound, value: 0xb2ccd8ff}\n theme_color:{tags: thread_error, value: 0xb23219ff}\n theme_color:{tags: breakpoint, value: 0xa72911ff}\n theme_color:{tags: \"floating background\", value: 0x2a3574}\n theme_color:{tags: \"floating background alt\", value: 0x4f}\n theme_color:{tags: \"floating background fresh\", value: 0x31393d5f}\n theme_color:{tags: \"floating scroll_bar background\", value: 0x53542ff}\n theme_color:{tags: \"scroll_bar background\", value: 0x53542ff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0x586e75ff}\n theme_color:{tags: \"tab border\", value: 0x90abb3ff}\n theme_color:{tags: \"tab inactive background\", value: 0x0}\n theme_color:{tags: \"tab inactive border\", value: 0x33494fff}\n theme_color:{tags: \"tab auto background\", value: 0x565ed2ff}\n theme_color:{tags: \"tab auto border\", value: 0xa2a6dfff}\n theme_color:{tags: \"tab auto inactive background\", value: 0}\n theme_color:{tags: \"tab auto inactive border\", value: 0x595fbcff}\n theme_color:{tags: \"drop_site background\", value: 0xffffff05}\n theme_color:{tags: \"drop_site border\", value: 0xffffff0f}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0xfdf6e3ff}\n theme_color:{tags: \"alt background\", value: 0xeee8d5ff}\n theme_color:{tags: \"pop background\", value: 0x29a19890}\n theme_color:{tags: \"fresh background\", value: 0xf7d38dff}\n theme_color:{tags: \"match background\", value: 0xdcddddff}\n theme_color:{tags: border, value: 0xd1ccbdff}\n theme_color:{tags: \"weak text\", value: 0x93a1a1ff}\n theme_color:{tags: text, value: 0x657b83ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: hover, value: 0xca4b16ff}\n theme_color:{tags: \"focus overlay\", value: 0xca4b1454}\n theme_color:{tags: \"focus border\", value: 0xca4b16ff}\n theme_color:{tags: cursor, value: 0xca4b16ff}\n theme_color:{tags: selection, value: 0x8594a264}\n theme_color:{tags: \"inactive background\", value: 0x14}\n theme_color:{tags: drop_shadow, value: 0x3a}\n theme_color:{tags: \"good_pop background\", value: 0xd1e99aff}\n theme_color:{tags: \"good_pop border\", value: 0xd1e99aff}\n theme_color:{tags: \"bad_pop background\", value: 0xd26c6cff}\n theme_color:{tags: \"bad_pop border\", value: 0xd26c6cff}\n theme_color:{tags: \"bad_pop weak text\", value: 0xffffffff}\n theme_color:{tags: \"bad_pop text\", value: 0xffffffff}\n theme_color:{tags: code_default, value: 0x839496ff}\n theme_color:{tags: code_symbol, value: 0xb3880eff}\n theme_color:{tags: code_type, value: 0xb3880eff}\n theme_color:{tags: code_local, value: 0x657b83ff}\n theme_color:{tags: code_register, value: 0x947298ff}\n theme_color:{tags: code_keyword, value: 0x849804ff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x839496ff}\n theme_color:{tags: code_numeric, value: 0x2aa198ff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x19766bff}\n theme_color:{tags: code_string, value: 0x2aa198ff}\n theme_color:{tags: code_meta, value: 0xca4b16ff}\n theme_color:{tags: code_comment, value: 0x586e75ff}\n theme_color:{tags: line_info_0, value: 0xeee1dbff}\n theme_color:{tags: line_info_1, value: 0xe5d5b1ff}\n theme_color:{tags: line_info_2, value: 0xd9e8b6ff}\n theme_color:{tags: line_info_3, value: 0xf5d5ccff}\n theme_color:{tags: thread_0, value: 0xffa100ff}\n theme_color:{tags: thread_1, value: 0x6edd00ff}\n theme_color:{tags: thread_unwound, value: 0x708f9eff}\n theme_color:{tags: thread_error, value: 0xff5231ff}\n theme_color:{tags: breakpoint, value: 0xff411dff}\n theme_color:{tags: \"floating background\", value: 0xfdf6e3b1}\n theme_color:{tags: \"floating background alt\", value: 0x22}\n theme_color:{tags: \"floating background fresh\", value: 0xf7d38dff}\n theme_color:{tags: \"scroll_bar background\", value: 0xeee6d0ff}\n theme_color:{tags: \"scroll_bar floating background\", value: 0xd5ccb5ff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0xfdf6e3ff}\n theme_color:{tags: \"tab inactive background\", value: 0xe0d6bbff}\n theme_color:{tags: \"tab auto background\", value: 0xf5cfe1ff}\n theme_color:{tags: \"tab auto border\", value: 0xa2a6dfff}\n theme_color:{tags: \"tab auto inactive background\", value: 0xc8a5b5ff}\n theme_color:{tags: \"tab auto inactive border\", value: 0x595fbcff}\n theme_color:{tags: \"drop_site background\", value: 0x29a19890}\n theme_color:{tags: \"drop_site border\", value: 0x81ddd690}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0x0c0c0cff}\n theme_color:{tags: \"alt background\", value: 0x161616ff}\n theme_color:{tags: \"pop background\", value: 0x355b6eff}\n theme_color:{tags: \"fresh background\", value: 0x31393dff}\n theme_color:{tags: \"match background\", value: 0x31393dff}\n theme_color:{tags: border, value: 0x404040ff}\n theme_color:{tags: text, value: 0xcac1b6ff}\n theme_color:{tags: \"weak text\", value: 0xa08563ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: hover, value: 0xffffffff}\n theme_color:{tags: \"focus overlay\", value: 0x7485971e}\n theme_color:{tags: \"focus border\", value: 0x5e6b79ff}\n theme_color:{tags: cursor, value: 0x00ee00ff}\n theme_color:{tags: selection, value: 0x99ccff0f}\n theme_color:{tags: \"inactive background\", value: 0x0000002f}\n theme_color:{tags: drop_shadow, value: 0x0000007f}\n theme_color:{tags: \"good_pop background\", value: 0x2c5b36ff}\n theme_color:{tags: \"good_pop border\", value: 0x568761ff}\n theme_color:{tags: \"good_pop hover\", value: 0xe3f5d3ff}\n theme_color:{tags: \"good_pop weak text\", value: 0xe3f5d3ff}\n theme_color:{tags: \"bad_pop background\", value: 0x803425ff}\n theme_color:{tags: \"bad_pop hover\", value: 0xff825cff}\n theme_color:{tags: code_default, value: 0xa08563ff}\n theme_color:{tags: code_symbol, value: 0xcc5735ff}\n theme_color:{tags: code_type, value: 0xd8a51cff}\n theme_color:{tags: code_local, value: 0xd6b995ff}\n theme_color:{tags: code_register, value: 0xc04047ff}\n theme_color:{tags: code_keyword, value: 0xac7b0aff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x907553ff}\n theme_color:{tags: code_numeric, value: 0x6b8e23ff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x4f681cff}\n theme_color:{tags: code_string, value: 0x6b8e23ff}\n theme_color:{tags: code_meta, value: 0xdab98fff}\n theme_color:{tags: code_comment, value: 0x686868ff}\n theme_color:{tags: line_info_0, value: 0x4f3022ff}\n theme_color:{tags: line_info_1, value: 0x4f3e15ff}\n theme_color:{tags: line_info_2, value: 0x434e2aff}\n theme_color:{tags: line_info_3, value: 0x36241fff}\n theme_color:{tags: thread_0, value: 0xffcb7fff}\n theme_color:{tags: thread_1, value: 0xb2ff65ff}\n theme_color:{tags: thread_unwound, value: 0xb2ccd8ff}\n theme_color:{tags: thread_error, value: 0xb23219ff}\n theme_color:{tags: breakpoint, value: 0xa72911ff}\n theme_color:{tags: \"floating background\", value: 0x18181980}\n theme_color:{tags: \"floating background alt\", value: 0x0000005f}\n theme_color:{tags: \"floating background fresh\", value: 0x31393d5f}\n theme_color:{tags: \"floating border\", value: 0xbfbfbf1f}\n theme_color:{tags: \"floating scroll_bar background\", value: 0x3b3b3b5f}\n theme_color:{tags: \"floating scroll_bar border\", value: 0x5f5f5f5f}\n theme_color:{tags: \"menu_bar background\", value: 0x1f1f27ff}\n theme_color:{tags: \"menu_bar border\", value: 0x3d3d47ff}\n theme_color:{tags: \"scroll_bar background\", value: 0x2b2b2bff}\n theme_color:{tags: \"scroll_bar border\", value: 0x3f3f3fff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0x1f1f27ff}\n theme_color:{tags: \"tab border\", value: 0x3d3d47ff}\n theme_color:{tags: \"tab text\", value: 0xca9301ff}\n theme_color:{tags: \"tab text weak\", value: 0x8c690eff}\n theme_color:{tags: \"tab inactive background\", value: 0x171718ff}\n theme_color:{tags: \"tab inactive border\", value: 0x1f1f27ff}\n theme_color:{tags: \"tab auto background\", value: 0x243b38ff}\n theme_color:{tags: \"tab auto border\", value: 0x478980ff}\n theme_color:{tags: \"tab auto inactive background\", value: 0x102623ff}\n theme_color:{tags: \"tab auto inactive border\", value: 0x1e5850ff}\n theme_color:{tags: \"drop_site background\", value: 0xffffff05}\n theme_color:{tags: \"drop_site border\", value: 0xffffff0f}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0x042327ff}\n theme_color:{tags: \"alt background\", value: 0x11b1fff}\n theme_color:{tags: \"pop background\", value: 0x355b6eff}\n theme_color:{tags: \"pop text\", value: 0xbad7e6ff}\n theme_color:{tags: \"fresh background\", value: 0x31393dff}\n theme_color:{tags: \"match background\", value: 0x31393dff}\n theme_color:{tags: border, value: 0x334d50ff}\n theme_color:{tags: text, value: 0xdad3beff}\n theme_color:{tags: \"weak text\", value: 0xb0a688ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: \"menu_bar good text\", value: 0x2a8242ff}\n theme_color:{tags: \"menu_bar neutral text\", value: 0x5681ff}\n theme_color:{tags: \"menu_bar bad text\", value: 0xa21200ff}\n theme_color:{tags: \"menu_bar weak text\", value: 0x313131ff}\n theme_color:{tags: \"menu_bar bad_pop text weak\", value: 0xffffffff}\n theme_color:{tags: hover, value: 0xffffffff}\n theme_color:{tags: \"focus overlay\", value: 0x86e08e20}\n theme_color:{tags: \"focus border\", value: 0x86e08fff}\n theme_color:{tags: cursor, value: 0x86e08fff}\n theme_color:{tags: selection, value: 0x99ccff0f}\n theme_color:{tags: \"inactive background\", value: 0x0000002f}\n theme_color:{tags: drop_shadow, value: 0x0000007f}\n theme_color:{tags: \"good_pop background\", value: 0x2c5b36ff}\n theme_color:{tags: \"good_pop border\", value: 0x568761ff}\n theme_color:{tags: \"good_pop hover\", value: 0xe3f5d3ff}\n theme_color:{tags: \"good_pop weak text\", value: 0xe3f5d3ff}\n theme_color:{tags: \"bad_pop background\", value: 0x803425ff}\n theme_color:{tags: \"bad_pop hover\", value: 0xff825cff}\n theme_color:{tags: code_default, value: 0xbdb395ff}\n theme_color:{tags: code_symbol, value: 0xcbe0f5ff}\n theme_color:{tags: code_type, value: 0xcbe0f5ff}\n theme_color:{tags: code_local, value: 0xd9cfb3ff}\n theme_color:{tags: code_register, value: 0xb7afd5ff}\n theme_color:{tags: code_keyword, value: 0x9de3c0ff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x767676ff}\n theme_color:{tags: code_numeric, value: 0x2ca198ff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x217770ff}\n theme_color:{tags: code_string, value: 0x2ca198ff}\n theme_color:{tags: code_meta, value: 0xB0FFB0ff}\n theme_color:{tags: code_comment, value: 0x31b72cff}\n theme_color:{tags: line_info_0, value: 0x4f3022ff}\n theme_color:{tags: line_info_1, value: 0x4f3e15ff}\n theme_color:{tags: line_info_2, value: 0x434e2aff}\n theme_color:{tags: line_info_3, value: 0x36241fff}\n theme_color:{tags: thread_0, value: 0xffcb7fff}\n theme_color:{tags: thread_1, value: 0xb2ff65ff}\n theme_color:{tags: thread_unwound, value: 0xb2ccd8ff}\n theme_color:{tags: thread_error, value: 0xb23219ff}\n theme_color:{tags: breakpoint, value: 0xa72911ff}\n theme_color:{tags: \"floating background\", value: 0x3232792}\n theme_color:{tags: \"floating background alt\", value: 0x0000005f}\n theme_color:{tags: \"floating background fresh\", value: 0x31393d5f}\n theme_color:{tags: \"floating scroll_bar background\", value: 0xe363bff}\n theme_color:{tags: \"menu_bar background\", value: 0xb59e7aff}\n theme_color:{tags: \"menu_bar text\", value: 0xff}\n theme_color:{tags: \"menu_bar border\", value: 0x947d5aff}\n theme_color:{tags: \"scroll_bar background\", value: 0xe363bff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0x13533aff}\n theme_color:{tags: \"tab border\", value: 0x6c9182ff}\n theme_color:{tags: \"tab inactive background\", value: 0x0}\n theme_color:{tags: \"tab inactive border\", value: 0x947d5a6c}\n theme_color:{tags: \"tab auto background\", value: 0x5b3939ff}\n theme_color:{tags: \"tab auto border\", value: 0x875c5cff}\n theme_color:{tags: \"tab auto inactive background\", value: 0x251b1bff}\n theme_color:{tags: \"tab auto inactive border\", value: 0x563d3dff}\n theme_color:{tags: \"drop_site background\", value: 0xffffff05}\n theme_color:{tags: \"drop_site border\", value: 0xffffff0f}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background,value: 0xc0c0cff}\n theme_color:{tags: \"alt background\", value: 0x131313ff}\n theme_color:{tags: \"pop background\", value: 0x4c00ff}\n theme_color:{tags: \"fresh background\", value: 0x4c00ff}\n theme_color:{tags: \"match background\", value: 0x4c00ff}\n theme_color:{tags: border, value: 0x272727ff}\n theme_color:{tags: text, value: 0x90b080ff}\n theme_color:{tags: \"weak text\", value: 0x6b845fff}\n theme_color:{tags: \"menu_bar background\", value: 0x888888ff}\n theme_color:{tags: \"menu_bar text\", value: 0x20202ff}\n theme_color:{tags: \"menu_bar text weak\", value: 0x525252ff}\n theme_color:{tags: \"good text\", value: 0x32a852ff}\n theme_color:{tags: \"neutral text\", value: 0x3a90bbff}\n theme_color:{tags: \"bad text\", value: 0xcf5242ff}\n theme_color:{tags: hover, value: 0xee00ff}\n theme_color:{tags: \"focus overlay\", value: 0xee0012}\n theme_color:{tags: \"focus border\", value: 0x00ee00ff}\n theme_color:{tags: cursor, value: 0x00ee00ff}\n theme_color:{tags: selection, value: 0x99ccff0f}\n theme_color:{tags: \"inactive background\", value: 0x0000002f}\n theme_color:{tags: drop_shadow, value: 0x0000007f}\n theme_color:{tags: \"good_pop background\", value: 0x4900ff}\n theme_color:{tags: \"good_pop border\", value: 0x4900ff}\n theme_color:{tags: \"bad_pop background\", value: 0x430b00ff}\n theme_color:{tags: code_default, value: 0x90b080ff}\n theme_color:{tags: code_symbol, value: 0xbfd9b2ff}\n theme_color:{tags: code_type, value: 0xbfd9b2ff}\n theme_color:{tags: code_local, value: 0xbfd9b2ff}\n theme_color:{tags: code_register, value: 0xb84cffff}\n theme_color:{tags: code_keyword, value: 0xd08f1fff}\n theme_color:{tags: code_delimiter_or_operator, value: 0x90b080ff}\n theme_color:{tags: code_numeric, value: 0x50ff2fff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0x30af18ff}\n theme_color:{tags: code_string, value: 0x50ff2fff}\n theme_color:{tags: code_meta, value: 0x90b080ff}\n theme_color:{tags: code_comment, value: 0x1f90f0ff}\n theme_color:{tags: line_info_0, value: 0xa253dff}\n theme_color:{tags: line_info_1, value: 0x9103dff}\n theme_color:{tags: line_info_2, value: 0x1e083dff}\n theme_color:{tags: line_info_3, value: 0x1e083dff}\n theme_color:{tags: thread_0, value: 0xd08f1fff}\n theme_color:{tags: thread_1, value: 0x1ea5d0ff}\n theme_color:{tags: thread_unwound, value: 0xb2ccd8ff}\n theme_color:{tags: thread_error, value: 0xb23219ff}\n theme_color:{tags: breakpoint, value: 0xa72911ff}\n theme_color:{tags: \"scroll_bar background\", value: 0x1d1d1dff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0x15490cff}\n theme_color:{tags: \"tab border\", value: 0x15490cff}\n theme_color:{tags: \"tab text\", value: 0x90b080ff}\n theme_color:{tags: \"tab text weak\", value: 0x90b080ff}\n theme_color:{tags: \"tab inactive background\", value: 0x21321eff}\n theme_color:{tags: \"tab inactive border\", value: 0x21321eff}\n theme_color:{tags: \"tab auto background\", value: 0x674f3eff}\n theme_color:{tags: \"tab auto border\", value: 0x674f3eff}\n theme_color:{tags: \"tab auto inactive background\", value: 0x47382eff}\n theme_color:{tags: \"tab auto inactive border\", value: 0x47382eff}\n theme_color:{tags: \"drop_site background\", value: 0xffffff05}\n theme_color:{tags: \"drop_site border\", value: 0xffffff0f}\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{ tags: background , value: 0x1b1f22ff }\n theme_color:{ tags: \"alt background\" , value: 0x232929ff }\n theme_color:{ tags: \"pop background\" , value: 0x2f4838ff }\n theme_color:{ tags: \"fresh background\" , value: 0x31393dff }\n theme_color:{ tags: \"match background\" , value: 0x31393dff }\n theme_color:{ tags: border , value: 0x485347ff }\n theme_color:{ tags: text , value: 0xffffffff }\n theme_color:{ tags: \"weak text\" , value: 0xa2a2a2ff }\n theme_color:{ tags: \"good text\" , value: 0x32a852ff }\n theme_color:{ tags: \"neutral text\" , value: 0x3a90bbff }\n theme_color:{ tags: \"bad text\" , value: 0xcf5242ff }\n theme_color:{ tags: hover , value: 0xffffffff }\n theme_color:{ tags: \"focus overlay\" , value: 0xfda20012 }\n theme_color:{ tags: \"focus border\" , value: 0xfda200ff }\n theme_color:{ tags: cursor , value: 0x8aff00ff }\n theme_color:{ tags: selection , value: 0x99ccff0f }\n theme_color:{ tags: \"inactive background\" , value: 0x0 }\n theme_color:{ tags: drop_shadow , value: 0x0000007f }\n theme_color:{ tags: \"good_pop background\" , value: 0x2c5b36ff }\n theme_color:{ tags: \"good_pop border\" , value: 0x568761ff }\n theme_color:{ tags: \"good_pop hover\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"good_pop weak text\" , value: 0xe3f5d3ff }\n theme_color:{ tags: \"bad_pop background\" , value: 0x803425ff }\n theme_color:{ tags: \"bad_pop hover\" , value: 0xff825cff }\n theme_color:{ tags: code_default , value: 0xad8b69ff }\n theme_color:{ tags: code_symbol , value: 0x87ad6aff }\n theme_color:{ tags: code_type , value: 0xb67474ff }\n theme_color:{ tags: code_local , value: 0xe9bf95ff }\n theme_color:{ tags: code_register , value: 0xa688b2ff }\n theme_color:{ tags: code_keyword , value: 0xe49e17ff }\n theme_color:{ tags: code_delimiter_or_operator , value: 0x795e43ff }\n theme_color:{ tags: code_numeric , value: 0x98b19eff }\n theme_color:{ tags: code_numeric_alt_digit_group , value: 0x688b71ff }\n theme_color:{ tags: code_string , value: 0x98b19eff }\n theme_color:{ tags: code_meta , value: 0xad5979ff }\n theme_color:{ tags: code_comment , value: 0x52675dff }\n theme_color:{ tags: line_info_0 , value: 0x4f3022ff }\n theme_color:{ tags: line_info_1 , value: 0x4f3e15ff }\n theme_color:{ tags: line_info_2 , value: 0x434e2aff }\n theme_color:{ tags: line_info_3 , value: 0x36241fff }\n theme_color:{ tags: line_info_4 , value: 0x4f3022ff }\n theme_color:{ tags: line_info_5 , value: 0x4f3e15ff }\n theme_color:{ tags: line_info_6 , value: 0x434e2aff }\n theme_color:{ tags: line_info_7 , value: 0x36241fff }\n theme_color:{ tags: thread_0 , value: 0xffc258ff }\n theme_color:{ tags: thread_1 , value: 0x82d331ff }\n theme_color:{ tags: thread_2 , value: 0xff99e5ff }\n theme_color:{ tags: thread_3 , value: 0x6598ffff }\n theme_color:{ tags: thread_4 , value: 0x65ffcbff }\n theme_color:{ tags: thread_5 , value: 0xff9819ff }\n theme_color:{ tags: thread_6 , value: 0x9932ffff }\n theme_color:{ tags: thread_7 , value: 0x65ff4cff }\n theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff }\n theme_color:{ tags: thread_error , value: 0xb23219ff }\n theme_color:{ tags: breakpoint , value: 0xa72911ff }\n theme_color:{ tags: \"floating background\" , value: 0x1b1f2276 }\n theme_color:{ tags: \"floating background alt\" , value: 0x0000005f }\n theme_color:{ tags: \"floating background fresh\" , value: 0x31393d5f }\n theme_color:{ tags: \"floating border\" , value: 0xbfbfbf1f }\n theme_color:{ tags: \"floating scroll_bar background\" , value: 0x3b3b3b5f }\n theme_color:{ tags: \"floating scroll_bar border\" , value: 0x5f5f5f5f }\n theme_color:{ tags: \"menu_bar background\" , value: 0x243d32ff }\n theme_color:{ tags: \"menu_bar border\" , value: 0x597b63ff }\n theme_color:{ tags: \"scroll_bar background\" , value: 0x232929ff }\n theme_color:{ tags: \"scroll_bar border\" , value: 0x3c4a3fff }\n theme_color:{ tags: \"implicit background\" , value: 0x00000000 }\n theme_color:{ tags: \"implicit border\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow background\" , value: 0x00000000 }\n theme_color:{ tags: \"hollow border\" , value: 0xffffff1f }\n theme_color:{ tags: \"tab background\" , value: 0x243d32ff }\n theme_color:{ tags: \"tab border\" , value: 0x597b63ff }\n theme_color:{ tags: \"tab inactive background\" , value: 0x30383eff }\n theme_color:{ tags: \"tab inactive border\" , value: 0x6b7680ff }\n theme_color:{ tags: \"tab auto background\" , value: 0x30636dff }\n theme_color:{ tags: \"tab auto border\" , value: 0x768f94ff }\n theme_color:{ tags: \"tab auto inactive background\" , value: 0x2f2633ff }\n theme_color:{ tags: \"tab auto inactive border\" , value: 0x685073ff }\n theme_color:{ tags: \"drop_site background\" , value: 0xffffff05 }\n theme_color:{ tags: \"drop_site border\" , value: 0xffffff0f }\n}\n"), str8_lit_comp("theme:\n{\n theme_color:{tags: background, value: 0x000080ff}\n theme_color:{tags: \"pop background\", value: 0x8080ff}\n theme_color:{tags: \"fresh background\", value: 0x31393dff}\n theme_color:{tags: \"match background\", value: 0x31393dff}\n theme_color:{tags: border, value: 0x8080ff}\n theme_color:{tags: text, value: 0xffffffff}\n theme_color:{tags: \"weak text\", value: 0xffffffff}\n theme_color:{tags: \"good text\", value: 0x00ff00ff}\n theme_color:{tags: \"neutral text\", value: 0x00ffffff}\n theme_color:{tags: \"bad text\", value: 0xff0000ff}\n theme_color:{tags: hover, value: 0xffffffff}\n theme_color:{tags: \"focus overlay\", value: 0xffff0012}\n theme_color:{tags: \"focus border\", value: 0xffff00ff}\n theme_color:{tags: cursor, value: 0xffff00ff}\n theme_color:{tags: selection, value: 0xffff0018}\n theme_color:{tags: \"inactive background\", value: 0x0000002f}\n theme_color:{tags: drop_shadow, value: 0x0000007f}\n theme_color:{tags: \"good_pop background\", value: 0x6c17ff}\n theme_color:{tags: \"good_pop border\", value: 0x6c17ff}\n theme_color:{tags: \"bad_pop background\", value: 0xff0000ff}\n theme_color:{tags: code_default, value: 0xffffffff}\n theme_color:{tags: code_symbol, value: 0xffffff}\n theme_color:{tags: code_type, value: 0x00ff00ff}\n theme_color:{tags: code_local, value: 0x00ffffff}\n theme_color:{tags: code_register, value: 0xff00ffff}\n theme_color:{tags: code_keyword, value: 0xffffffff}\n theme_color:{tags: code_delimiter_or_operator, value: 0xffffffff}\n theme_color:{tags: code_numeric, value: 0xffff00ff}\n theme_color:{tags: code_numeric_alt_digit_group, value: 0xffff00ff}\n theme_color:{tags: code_string, value: 0xffff00ff}\n theme_color:{tags: code_meta, value: 0xff0000ff}\n theme_color:{tags: code_comment, value: 0x008080ff}\n theme_color:{tags: line_info_0, value: 0x8080ff}\n theme_color:{tags: line_info_1, value: 0x800080ff}\n theme_color:{tags: line_info_2, value: 0x800000ff}\n theme_color:{tags: line_info_3, value: 0x08000ff}\n theme_color:{tags: thread_0, value: 0xffff00ff}\n theme_color:{tags: thread_1, value: 0x00ff00ff}\n theme_color:{tags: thread_unwound, value: 0x00ffffff}\n theme_color:{tags: thread_error, value: 0xff0000ff}\n theme_color:{tags: breakpoint, value: 0xff0000ff}\n theme_color:{tags: \"menu_bar background\", value: 0x008080ff}\n theme_color:{tags: \"menu_bar border\", value: 0x8080ff}\n theme_color:{tags: \"scroll_bar background\", value: 0x008080ff}\n theme_color:{tags: \"implicit background\", value: 0x00000000}\n theme_color:{tags: \"implicit border\", value: 0x00000000}\n theme_color:{tags: \"hollow background\", value: 0x00000000}\n theme_color:{tags: \"hollow border\", value: 0xffffff1f}\n theme_color:{tags: \"tab background\", value: 0x8080ff}\n theme_color:{tags: \"tab border\", value: 0x8080ff}\n theme_color:{tags: \"tab inactive background\", value:0}\n theme_color:{tags: \"tab auto background\", value: 0x800000ff}\n theme_color:{tags: \"tab auto border\", value: 0x8080ff}\n theme_color:{tags: \"tab auto inactive background\", value: 0x300000ff}\n theme_color:{tags: \"tab auto inactive border\", value: 0x8080ff}\n theme_color:{tags: \"drop_site background\", value: 0x80ff}\n theme_color:{tags: \"drop_site border\", value: 0xffffff}\n}\n"), }; C_LINKAGE_END ================================================ FILE: src/raddbg/generated/raddbg.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef RADDBG_META_H #define RADDBG_META_H typedef enum RD_RegSlot { RD_RegSlot_Null, RD_RegSlot_Machine, RD_RegSlot_Module, RD_RegSlot_Process, RD_RegSlot_Thread, RD_RegSlot_CtrlEntity, RD_RegSlot_Window, RD_RegSlot_Panel, RD_RegSlot_Tab, RD_RegSlot_View, RD_RegSlot_PrevTab, RD_RegSlot_DstPanel, RD_RegSlot_Cfg, RD_RegSlot_CfgList, RD_RegSlot_EvalSpace, RD_RegSlot_UnwindCount, RD_RegSlot_InlineDepth, RD_RegSlot_FilePath, RD_RegSlot_Cursor, RD_RegSlot_Mark, RD_RegSlot_TextKey, RD_RegSlot_LangKind, RD_RegSlot_Lines, RD_RegSlot_DbgiKey, RD_RegSlot_Vaddr, RD_RegSlot_Voff, RD_RegSlot_VaddrRange, RD_RegSlot_VoffRange, RD_RegSlot_Expr, RD_RegSlot_UIKey, RD_RegSlot_SrcUIKey, RD_RegSlot_OffPx, RD_RegSlot_RegSlot, RD_RegSlot_PID, RD_RegSlot_ForceConfirm, RD_RegSlot_ForceFocus, RD_RegSlot_PreferDisasm, RD_RegSlot_NoRichTooltip, RD_RegSlot_DoImplicitRoot, RD_RegSlot_DoLister, RD_RegSlot_DoBigRows, RD_RegSlot_AllWindows, RD_RegSlot_NonGraphical, RD_RegSlot_PreferNewTab, RD_RegSlot_Dir2, RD_RegSlot_String, RD_RegSlot_CmdName, RD_RegSlot_OSEvent, RD_RegSlot_COUNT, } RD_RegSlot; typedef enum RD_CmdKind { RD_CmdKind_Null, RD_CmdKind_LaunchAndRun, RD_CmdKind_LaunchAndStepInto, RD_CmdKind_Kill, RD_CmdKind_KillAll, RD_CmdKind_Detach, RD_CmdKind_Continue, RD_CmdKind_StepIntoInst, RD_CmdKind_StepOverInst, RD_CmdKind_StepIntoLine, RD_CmdKind_StepOverLine, RD_CmdKind_StepOut, RD_CmdKind_Halt, RD_CmdKind_SoftHaltRefresh, RD_CmdKind_SetThreadIP, RD_CmdKind_RunToLine, RD_CmdKind_Run, RD_CmdKind_Restart, RD_CmdKind_StepInto, RD_CmdKind_StepOver, RD_CmdKind_FreezeThread, RD_CmdKind_ThawThread, RD_CmdKind_FreezeProcess, RD_CmdKind_ThawProcess, RD_CmdKind_FreezeMachine, RD_CmdKind_ThawMachine, RD_CmdKind_FreezeLocalMachine, RD_CmdKind_ThawLocalMachine, RD_CmdKind_FreezeEntity, RD_CmdKind_ThawEntity, RD_CmdKind_SetEntityColor, RD_CmdKind_SetEntityName, RD_CmdKind_Attach, RD_CmdKind_Exit, RD_CmdKind_OpenPalette, RD_CmdKind_RunCommand, RD_CmdKind_RunExternalDriverTextCommand, RD_CmdKind_OSEvent, RD_CmdKind_SelectThread, RD_CmdKind_SelectUnwind, RD_CmdKind_UpOneFrame, RD_CmdKind_DownOneFrame, RD_CmdKind_SelectEntity, RD_CmdKind_DeselectEntity, RD_CmdKind_IncWindowFontSize, RD_CmdKind_DecWindowFontSize, RD_CmdKind_IncViewFontSize, RD_CmdKind_DecViewFontSize, RD_CmdKind_OpenWindow, RD_CmdKind_WindowSettings, RD_CmdKind_CloseWindow, RD_CmdKind_ToggleFullscreen, RD_CmdKind_BringToFront, RD_CmdKind_PopupAccept, RD_CmdKind_PopupCancel, RD_CmdKind_ResetToDefaultBindings, RD_CmdKind_ResetToDefaultPanels, RD_CmdKind_ResetToCompactPanels, RD_CmdKind_ResetToSimplePanels, RD_CmdKind_NewPanelLeft, RD_CmdKind_NewPanelUp, RD_CmdKind_NewPanelRight, RD_CmdKind_NewPanelDown, RD_CmdKind_SplitPanel, RD_CmdKind_RotatePanelColumns, RD_CmdKind_NextPanel, RD_CmdKind_PrevPanel, RD_CmdKind_FocusPanel, RD_CmdKind_FocusPanelRight, RD_CmdKind_FocusPanelLeft, RD_CmdKind_FocusPanelUp, RD_CmdKind_FocusPanelDown, RD_CmdKind_Undo, RD_CmdKind_Redo, RD_CmdKind_GoBack, RD_CmdKind_GoForward, RD_CmdKind_ClosePanel, RD_CmdKind_FocusTab, RD_CmdKind_NextTab, RD_CmdKind_PrevTab, RD_CmdKind_MoveTabRight, RD_CmdKind_MoveTabLeft, RD_CmdKind_OpenTab, RD_CmdKind_BuildTab, RD_CmdKind_DuplicateTab, RD_CmdKind_CopyTabFullPath, RD_CmdKind_CloseTab, RD_CmdKind_MoveView, RD_CmdKind_TabBarTop, RD_CmdKind_TabBarBottom, RD_CmdKind_TabSettings, RD_CmdKind_SetCurrentPath, RD_CmdKind_Open, RD_CmdKind_Switch, RD_CmdKind_SwitchToPartnerFile, RD_CmdKind_RecordFileInProject, RD_CmdKind_ShowFileInExplorer, RD_CmdKind_GoToDisassembly, RD_CmdKind_GoToSource, RD_CmdKind_SetFileReplacementPath, RD_CmdKind_NewUser, RD_CmdKind_NewProject, RD_CmdKind_OpenUser, RD_CmdKind_OpenProject, RD_CmdKind_OpenRecentProject, RD_CmdKind_SaveUser, RD_CmdKind_SaveProject, RD_CmdKind_RecordUserAsLastOpened, RD_CmdKind_RecordProjectInUser, RD_CmdKind_WriteUserData, RD_CmdKind_WriteProjectData, RD_CmdKind_UserSettings, RD_CmdKind_ProjectSettings, RD_CmdKind_Edit, RD_CmdKind_Accept, RD_CmdKind_Cancel, RD_CmdKind_MoveLeft, RD_CmdKind_MoveRight, RD_CmdKind_MoveUp, RD_CmdKind_MoveDown, RD_CmdKind_MoveLeftSelect, RD_CmdKind_MoveRightSelect, RD_CmdKind_MoveUpSelect, RD_CmdKind_MoveDownSelect, RD_CmdKind_MoveLeftChunk, RD_CmdKind_MoveRightChunk, RD_CmdKind_MoveUpChunk, RD_CmdKind_MoveDownChunk, RD_CmdKind_MoveUpPage, RD_CmdKind_MoveDownPage, RD_CmdKind_MoveUpWhole, RD_CmdKind_MoveDownWhole, RD_CmdKind_MoveLeftChunkSelect, RD_CmdKind_MoveRightChunkSelect, RD_CmdKind_MoveUpChunkSelect, RD_CmdKind_MoveDownChunkSelect, RD_CmdKind_MoveUpPageSelect, RD_CmdKind_MoveDownPageSelect, RD_CmdKind_MoveUpWholeSelect, RD_CmdKind_MoveDownWholeSelect, RD_CmdKind_MoveUpReorder, RD_CmdKind_MoveDownReorder, RD_CmdKind_MoveHome, RD_CmdKind_MoveEnd, RD_CmdKind_MoveHomeSelect, RD_CmdKind_MoveEndSelect, RD_CmdKind_SelectAll, RD_CmdKind_DeleteSingle, RD_CmdKind_DeleteChunk, RD_CmdKind_BackspaceSingle, RD_CmdKind_BackspaceChunk, RD_CmdKind_Copy, RD_CmdKind_Cut, RD_CmdKind_Paste, RD_CmdKind_InsertText, RD_CmdKind_MoveNext, RD_CmdKind_MovePrev, RD_CmdKind_GoToLine, RD_CmdKind_GoToAddress, RD_CmdKind_CenterCursor, RD_CmdKind_ContainCursor, RD_CmdKind_FindNext, RD_CmdKind_FindPrev, RD_CmdKind_FindThread, RD_CmdKind_FindSelectedThread, RD_CmdKind_GoToName, RD_CmdKind_GoToNameAtCursor, RD_CmdKind_ToggleWatchExpression, RD_CmdKind_ToggleWatchExpressionAtCursor, RD_CmdKind_ToggleWatchExpressionAtMouse, RD_CmdKind_EnableCfg, RD_CmdKind_DisableCfg, RD_CmdKind_SelectCfg, RD_CmdKind_DeselectCfg, RD_CmdKind_RemoveCfg, RD_CmdKind_NameCfg, RD_CmdKind_ConditionCfg, RD_CmdKind_DuplicateCfg, RD_CmdKind_RelocateCfg, RD_CmdKind_SaveToProject, RD_CmdKind_AddBreakpoint, RD_CmdKind_AddAddressBreakpoint, RD_CmdKind_AddFunctionBreakpoint, RD_CmdKind_ToggleBreakpoint, RD_CmdKind_RemoveBreakpoint, RD_CmdKind_EnableBreakpoint, RD_CmdKind_DisableBreakpoint, RD_CmdKind_ClearBreakpoints, RD_CmdKind_ListBreakpoints, RD_CmdKind_ClearOutput, RD_CmdKind_AddWatchPin, RD_CmdKind_ToggleWatchPin, RD_CmdKind_LoadDebugInfo, RD_CmdKind_UnloadDebugInfo, RD_CmdKind_AddTypeView, RD_CmdKind_AddFilePathMap, RD_CmdKind_EditUserTheme, RD_CmdKind_EditProjectTheme, RD_CmdKind_AddThemeColor, RD_CmdKind_ForkTheme, RD_CmdKind_SaveTheme, RD_CmdKind_SaveAndSetTheme, RD_CmdKind_SetNextStatement, RD_CmdKind_AddTarget, RD_CmdKind_SelectTarget, RD_CmdKind_EnableTarget, RD_CmdKind_DisableTarget, RD_CmdKind_RemoveTarget, RD_CmdKind_RegisterAsJITDebugger, RD_CmdKind_FindCodeLocation, RD_CmdKind_Search, RD_CmdKind_SearchBackwards, RD_CmdKind_PickFile, RD_CmdKind_PickFolder, RD_CmdKind_PickFileOrFolder, RD_CmdKind_PushQuery, RD_CmdKind_CompleteQuery, RD_CmdKind_CancelQuery, RD_CmdKind_UpdateQuery, RD_CmdKind_OpenEventBuffer, RD_CmdKind_CloseEventBuffer, RD_CmdKind_ToggleDevMenu, RD_CmdKind_LogMarker, RD_CmdKind_OpenWatch, RD_CmdKind_OpenLocals, RD_CmdKind_OpenRegisters, RD_CmdKind_OpenGlobals, RD_CmdKind_OpenThreadLocals, RD_CmdKind_OpenTypes, RD_CmdKind_OpenProcedures, RD_CmdKind_OpenCallStack, RD_CmdKind_OpenTargets, RD_CmdKind_OpenBreakpoints, RD_CmdKind_OpenWatchPins, RD_CmdKind_OpenDebugInfos, RD_CmdKind_OpenThreads, RD_CmdKind_OpenProcesses, RD_CmdKind_OpenMachines, RD_CmdKind_OpenModules, RD_CmdKind_OpenFilePathMaps, RD_CmdKind_OpenTypeViews, RD_CmdKind_OpenOutput, RD_CmdKind_OpenText, RD_CmdKind_OpenDisasm, RD_CmdKind_OpenMemory, RD_CmdKind_OpenBitmap, RD_CmdKind_OpenColor, RD_CmdKind_OpenGeo3D, RD_CmdKind_COUNT, RD_CmdKind_FirstTabFastPathCmd = RD_CmdKind_OpenWatch, } RD_CmdKind; typedef enum RD_IconKind { RD_IconKind_Null, RD_IconKind_FolderOpenOutline, RD_IconKind_FolderClosedOutline, RD_IconKind_FolderOpenFilled, RD_IconKind_FolderClosedFilled, RD_IconKind_FileOutline, RD_IconKind_FileFilled, RD_IconKind_Play, RD_IconKind_PlayStepForward, RD_IconKind_Pause, RD_IconKind_Stop, RD_IconKind_Info, RD_IconKind_WarningSmall, RD_IconKind_WarningBig, RD_IconKind_Unlocked, RD_IconKind_Locked, RD_IconKind_LeftArrow, RD_IconKind_RightArrow, RD_IconKind_UpArrow, RD_IconKind_DownArrow, RD_IconKind_Gear, RD_IconKind_Pencil, RD_IconKind_Trash, RD_IconKind_Pin, RD_IconKind_RadioHollow, RD_IconKind_RadioFilled, RD_IconKind_CheckHollow, RD_IconKind_CheckFilled, RD_IconKind_Check, RD_IconKind_LeftCaret, RD_IconKind_RightCaret, RD_IconKind_UpCaret, RD_IconKind_DownCaret, RD_IconKind_UpScroll, RD_IconKind_DownScroll, RD_IconKind_LeftScroll, RD_IconKind_RightScroll, RD_IconKind_Add, RD_IconKind_Minus, RD_IconKind_Thread, RD_IconKind_Threads, RD_IconKind_Machine, RD_IconKind_CircleFilled, RD_IconKind_X, RD_IconKind_Refresh, RD_IconKind_Undo, RD_IconKind_Redo, RD_IconKind_Save, RD_IconKind_Window, RD_IconKind_Target, RD_IconKind_Clipboard, RD_IconKind_Scheduler, RD_IconKind_Module, RD_IconKind_XSplit, RD_IconKind_YSplit, RD_IconKind_ClosePanel, RD_IconKind_StepInto, RD_IconKind_StepOver, RD_IconKind_StepOut, RD_IconKind_Find, RD_IconKind_Palette, RD_IconKind_Thumbnails, RD_IconKind_Glasses, RD_IconKind_Binoculars, RD_IconKind_List, RD_IconKind_Grid, RD_IconKind_QuestionMark, RD_IconKind_Person, RD_IconKind_Briefcase, RD_IconKind_Dot, RD_IconKind_Bitmap, RD_IconKind_Cube, RD_IconKind_WindowRestore, RD_IconKind_WindowMinimize, RD_IconKind_Duplicate, RD_IconKind_COUNT, } RD_IconKind; typedef enum RD_CodeColorSlot { RD_CodeColorSlot_CodeDefault, RD_CodeColorSlot_CodeSymbol, RD_CodeColorSlot_CodeType, RD_CodeColorSlot_CodeLocal, RD_CodeColorSlot_CodeRegister, RD_CodeColorSlot_CodeKeyword, RD_CodeColorSlot_CodeDelimiterOperator, RD_CodeColorSlot_CodeNumeric, RD_CodeColorSlot_CodeNumericAltDigitGroup, RD_CodeColorSlot_CodeString, RD_CodeColorSlot_CodeMeta, RD_CodeColorSlot_CodeComment, RD_CodeColorSlot_CodeLineNumbers, RD_CodeColorSlot_CodeLineNumbersSelected, RD_CodeColorSlot_COUNT, } RD_CodeColorSlot; typedef enum RD_ThemePreset { RD_ThemePreset_DefaultDark, RD_ThemePreset_DefaultLight, RD_ThemePreset_VSDark, RD_ThemePreset_VSLight, RD_ThemePreset_SolarizedDark, RD_ThemePreset_SolarizedLight, RD_ThemePreset_HandmadeHero, RD_ThemePreset_Naysayer, RD_ThemePreset_FourCoder, RD_ThemePreset_Grove, RD_ThemePreset_FarManager, RD_ThemePreset_COUNT, } RD_ThemePreset; typedef struct RD_VocabInfo RD_VocabInfo; struct RD_VocabInfo { String8 code_name; String8 code_name_plural; String8 display_name; String8 display_name_plural; RD_IconKind icon_kind; }; typedef struct RD_NameSchemaInfo RD_NameSchemaInfo; struct RD_NameSchemaInfo { String8 name; String8 schema; }; typedef struct RD_Regs RD_Regs; struct RD_Regs { CTRL_Handle machine; CTRL_Handle module; CTRL_Handle process; CTRL_Handle thread; CTRL_Handle ctrl_entity; CFG_ID window; CFG_ID panel; CFG_ID tab; CFG_ID view; CFG_ID prev_tab; CFG_ID dst_panel; CFG_ID cfg; CFG_IDList cfg_list; E_Space eval_space; U64 unwind_count; U64 inline_depth; String8 file_path; TxtPt cursor; TxtPt mark; C_Key text_key; TXT_LangKind lang_kind; D_LineList lines; DI_Key dbgi_key; U64 vaddr; U64 voff; Rng1U64 vaddr_range; Rng1U64 voff_range; String8 expr; UI_Key ui_key; UI_Key src_ui_key; Vec2F32 off_px; RD_RegSlot reg_slot; U32 pid; B32 force_confirm; B32 force_focus; B32 prefer_disasm; B32 no_rich_tooltip; B32 do_implicit_root; B32 do_lister; B32 do_big_rows; B32 all_windows; B32 non_graphical; B32 prefer_new_tab; Dir2 dir2; String8 string; String8 cmd_name; OS_Event * os_event; }; typedef struct RD_Query RD_Query; struct RD_Query { RD_QueryFlags flags; RD_RegSlot slot; String8 expr; String8 view_name; CTRL_EntityKind ctrl_entity_kind; }; typedef struct RD_CmdKindInfo RD_CmdKindInfo; struct RD_CmdKindInfo { String8 string; String8 description; String8 search_tags; String8 ctx_filter; RD_CmdKindFlags flags; RD_Query query; }; #define RD_FixedTabXList \ Y(watches, watch, "")\ X(locals) \ X(registers) \ X(globals) \ X(thread_locals) \ X(types) \ X(procedures) \ X(call_stack) \ X(targets) \ X(breakpoints) \ X(watch_pins) \ X(debug_infos) \ X(threads) \ X(processes) \ X(machines) \ X(modules) \ X(file_path_maps) \ X(type_views) \ Y(output, text, "query:output")\ Y(text, text, "")\ Y(disasm, disasm, "")\ Y(memory, memory, "")\ Y(bitmap, bitmap, "")\ Y(color, color, "")\ Y(geo3d, geo3d, "")\ Z(getting_started)\ #define rd_regs_lit_init_top \ .machine = rd_regs()->machine,\ .module = rd_regs()->module,\ .process = rd_regs()->process,\ .thread = rd_regs()->thread,\ .ctrl_entity = rd_regs()->ctrl_entity,\ .window = rd_regs()->window,\ .panel = rd_regs()->panel,\ .tab = rd_regs()->tab,\ .view = rd_regs()->view,\ .prev_tab = rd_regs()->prev_tab,\ .dst_panel = rd_regs()->dst_panel,\ .cfg = rd_regs()->cfg,\ .cfg_list = rd_regs()->cfg_list,\ .eval_space = rd_regs()->eval_space,\ .unwind_count = rd_regs()->unwind_count,\ .inline_depth = rd_regs()->inline_depth,\ .file_path = rd_regs()->file_path,\ .cursor = rd_regs()->cursor,\ .mark = rd_regs()->mark,\ .text_key = rd_regs()->text_key,\ .lang_kind = rd_regs()->lang_kind,\ .lines = rd_regs()->lines,\ .dbgi_key = rd_regs()->dbgi_key,\ .vaddr = rd_regs()->vaddr,\ .voff = rd_regs()->voff,\ .vaddr_range = rd_regs()->vaddr_range,\ .voff_range = rd_regs()->voff_range,\ .expr = rd_regs()->expr,\ .ui_key = rd_regs()->ui_key,\ .src_ui_key = rd_regs()->src_ui_key,\ .off_px = rd_regs()->off_px,\ .reg_slot = rd_regs()->reg_slot,\ .pid = rd_regs()->pid,\ .force_confirm = rd_regs()->force_confirm,\ .force_focus = rd_regs()->force_focus,\ .prefer_disasm = rd_regs()->prefer_disasm,\ .no_rich_tooltip = rd_regs()->no_rich_tooltip,\ .do_implicit_root = rd_regs()->do_implicit_root,\ .do_lister = rd_regs()->do_lister,\ .do_big_rows = rd_regs()->do_big_rows,\ .all_windows = rd_regs()->all_windows,\ .non_graphical = rd_regs()->non_graphical,\ .prefer_new_tab = rd_regs()->prefer_new_tab,\ .dir2 = rd_regs()->dir2,\ .string = rd_regs()->string,\ .cmd_name = rd_regs()->cmd_name,\ .os_event = rd_regs()->os_event,\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[25]; extern String8 rd_tab_fast_path_query_name_table[25]; extern RD_VocabInfo rd_vocab_info_table[358]; extern RD_NameSchemaInfo rd_name_schema_info_table[26]; extern String8 rd_reg_slot_code_name_table[48]; extern Rng1U64 rd_reg_slot_range_table[48]; extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_new_name_table[8]; extern String8 rd_icon_kind_text_table[75]; extern String8 rd_code_color_slot_name_table[14]; extern String8 rd_theme_preset_display_string_table[11]; extern String8 rd_theme_preset_code_string_table[11]; extern String8 rd_theme_preset_cfg_string_table[11]; read_only global U8 rd_icon_font_bytes__data[] = { 0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x80,0x00,0x03,0x00,0x70,0x47,0x53,0x55,0x42,0x20,0x8b,0x25,0x7a,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x54,0x4f,0x53,0x2f,0x32,0x56,0x43,0x62,0x25,0x00,0x00,0x01,0x50,0x00,0x00,0x00,0x60,0x63,0x6d,0x61,0x70,0xa3,0x60,0xa4,0x23,0x00,0x00,0x01,0xb0,0x00,0x00,0x06,0x12,0x63,0x76,0x74,0x20, 0x0e,0x1f,0x06,0xf3,0x00,0x00,0x51,0x34,0x00,0x00,0x00,0x38,0x66,0x70,0x67,0x6d,0x62,0x31,0xfb,0x7b,0x00,0x00,0x51,0x6c,0x00,0x00,0x0e,0x0c,0x67,0x61,0x73,0x70,0x00,0x00,0x00,0x10,0x00,0x00,0x51,0x2c,0x00,0x00,0x00,0x08,0x67,0x6c,0x79,0x66,0x71,0xda,0x4c,0xc8,0x00,0x00,0x07,0xc4,0x00,0x00,0x40,0x90,0x68,0x65,0x61,0x64, 0x2b,0xeb,0xd3,0xaf,0x00,0x00,0x48,0x54,0x00,0x00,0x00,0x36,0x68,0x68,0x65,0x61,0x07,0xc2,0x04,0x27,0x00,0x00,0x48,0x8c,0x00,0x00,0x00,0x24,0x68,0x6d,0x74,0x78,0x06,0x4b,0xff,0xca,0x00,0x00,0x48,0xb0,0x00,0x00,0x01,0x44,0x6c,0x6f,0x63,0x61,0x71,0xa6,0x82,0xac,0x00,0x00,0x49,0xf4,0x00,0x00,0x00,0xa4,0x6d,0x61,0x78,0x70, 0x01,0xe8,0x0f,0x19,0x00,0x00,0x4a,0x98,0x00,0x00,0x00,0x20,0x6e,0x61,0x6d,0x65,0xcd,0x9d,0x1c,0x1d,0x00,0x00,0x4a,0xb8,0x00,0x00,0x02,0xcd,0x70,0x6f,0x73,0x74,0x77,0x9e,0x36,0x3b,0x00,0x00,0x4d,0x88,0x00,0x00,0x03,0xa2,0x70,0x72,0x65,0x70,0xeb,0x48,0xca,0x9d,0x00,0x00,0x5f,0x78,0x00,0x00,0x00,0xa7,0x00,0x01,0x00,0x00, 0x00,0x0a,0x00,0x30,0x00,0x3e,0x00,0x02,0x44,0x46,0x4c,0x54,0x00,0x0e,0x6c,0x61,0x74,0x6e,0x00,0x1a,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x6c,0x69,0x67,0x61,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x04, 0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x03,0x3d,0x01,0x90,0x00,0x05,0x00,0x00,0x02,0x7a,0x02,0xbc,0x00,0x00,0x00,0x8c,0x02,0x7a,0x02,0xbc,0x00,0x00,0x01,0xe0,0x00,0x31,0x01,0x02,0x00,0x00,0x02,0x00,0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x66,0x45,0x64,0x00,0xc0,0x00,0x21,0x00,0x7d,0x03,0x52,0xff,0x6a,0x00,0x5a,0x03,0xac,0x00,0x96,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x04, 0x00,0x00,0x02,0x42,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x3c,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x2c,0x00,0x03,0x00,0x0a,0x00,0x00,0x02,0x42,0x00,0x04,0x01,0x10,0x00,0x00,0x00,0x18,0x00,0x10,0x00,0x03,0x00,0x08,0x00,0x23,0x00,0x2b,0x00,0x2e,0x00,0x31,0x00,0x39,0x00,0x3c,0x00,0x5b,0x00,0x5e,0x00,0x73,0x00,0x7b,0x00,0x7d, 0xff,0xff,0x00,0x00,0x00,0x21,0x00,0x26,0x00,0x2d,0x00,0x30,0x00,0x33,0x00,0x3c,0x00,0x3e,0x00,0x5d,0x00,0x61,0x00,0x75,0x00,0x7d,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x1c,0x00,0x26,0x00,0x28,0x00,0x2a,0x00,0x36, 0x00,0x36,0x00,0x70,0x00,0x72,0x00,0x96,0x00,0xa2,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1a, 0x00,0x1b,0x00,0x1c,0x00,0x1d,0x00,0x1e,0x00,0x1f,0x00,0x20,0x00,0x21,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x2b,0x00,0x2c,0x00,0x2d,0x00,0x2e,0x00,0x2f,0x00,0x30,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x39,0x00,0x3a, 0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x40,0x00,0x41,0x00,0x42,0x00,0x43,0x00,0x44,0x00,0x45,0x00,0x46,0x00,0x47,0x00,0x48,0x00,0x49,0x00,0x4a,0x00,0x4b,0x00,0x4c,0x00,0x4d,0x00,0x4e,0x00,0x4f,0x00,0x50,0x00,0x00,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x00,0x00,0x04,0x05,0x06,0x07,0x08,0x09,0x00,0x0a,0x0b,0x00,0x0c,0x0d,0x00,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x00,0x00,0x15,0x00,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25, 0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x00,0x34,0x35,0x00,0x00,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x00,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0xd0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x50,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x05,0x00,0x00, 0x00,0x28,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x2e,0x00,0x00, 0x00,0x2e,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x35,0x00,0x00, 0x00,0x10,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x15,0x00,0x00, 0x00,0x3e,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x43,0x00,0x00, 0x00,0x43,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x48,0x00,0x00, 0x00,0x20,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x25,0x00,0x00, 0x00,0x4e,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x53,0x00,0x00, 0x00,0x53,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x58,0x00,0x00, 0x00,0x30,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x35,0x00,0x00, 0x00,0x61,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x66,0x00,0x00, 0x00,0x66,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x6b,0x00,0x00, 0x00,0x40,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x45,0x00,0x00, 0x00,0x71,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x77,0x00,0x00, 0x00,0x77,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x7d,0x00,0x00,0x00,0x7d,0x00,0x00, 0x00,0x50,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xf9,0x03,0x13,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x25,0x40,0x22,0x00,0x01,0x00,0x02,0x01,0x02,0x63,0x04,0x01,0x00,0x00,0x03,0x5f,0x00,0x03,0x03,0x13,0x00,0x4e,0x02,0x00,0x1e,0x1b,0x16,0x13,0x0a,0x07,0x00,0x0f,0x02,0x0f,0x05,0x07,0x16,0x2b,0x01,0x21,0x22,0x06,0x07,0x11,0x14, 0x16,0x17,0x21,0x32,0x36,0x35,0x11,0x34,0x26,0x17,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x02,0x71,0xfe,0x30,0x25,0x34,0x01,0x36,0x24,0x01,0xd0,0x25,0x34,0x34,0x7c,0x5e,0x43,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42,0x60,0x02,0xc3,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x24,0x01, 0xd0,0x25,0x34,0x59,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42,0x5e,0x01,0x60,0x00,0x06,0x00,0x00,0xff,0xba,0x02,0x80,0x03,0x02,0x00,0x13,0x00,0x1c,0x00,0x25,0x00,0x39,0x00,0x42,0x00,0x4b,0x00,0x54,0x40,0x51,0x39,0x30,0x2f,0x26,0x0d,0x0c,0x03,0x02,0x08,0x02,0x04,0x01,0x4c,0x08,0x0c,0x02,0x04,0x0b,0x01,0x02,0x03,0x04, 0x02,0x69,0x09,0x01,0x05,0x05,0x01,0x61,0x07,0x01,0x01,0x01,0x13,0x4d,0x0d,0x0a,0x02,0x03,0x03,0x00,0x61,0x06,0x01,0x00,0x00,0x11,0x00,0x4e,0x44,0x43,0x1e,0x1d,0x48,0x47,0x43,0x4b,0x44,0x4b,0x41,0x40,0x3d,0x3c,0x35,0x34,0x2b,0x2a,0x22,0x21,0x1d,0x25,0x1e,0x25,0x13,0x14,0x19,0x17,0x0e,0x07,0x1a,0x2b,0x13,0x14,0x07,0x11, 0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34,0x37,0x11,0x26,0x35,0x34,0x36,0x32,0x16,0x03,0x34,0x26,0x22,0x06,0x14,0x16,0x32,0x36,0x03,0x32,0x36,0x34,0x26,0x22,0x06,0x14,0x16,0x01,0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34,0x37,0x11,0x26,0x35,0x34,0x36,0x32,0x16,0x15,0x14,0x07,0x27,0x14,0x16,0x32,0x36,0x34,0x26,0x22,0x06,0x13, 0x32,0x36,0x34,0x26,0x22,0x06,0x14,0x16,0xf0,0x48,0x48,0x46,0x64,0x46,0x48,0x48,0x46,0x64,0x46,0x32,0x2a,0x38,0x28,0x28,0x38,0x2a,0x46,0x1c,0x2a,0x2a,0x38,0x28,0x28,0x01,0xdc,0x48,0x46,0x64,0x46,0x48,0x48,0x46,0x64,0x46,0x48,0x74,0x28,0x38,0x2a,0x2a,0x38,0x28,0x44,0x1c,0x2a,0x2a,0x38,0x28,0x28,0x02,0x8a,0x4c,0x22,0xfe, 0x86,0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0x01,0x7a,0x22,0x4c,0x32,0x46,0x46,0xfd,0x76,0x1e,0x28,0x28,0x3a,0x28,0x28,0x02,0x30,0x28,0x3a,0x28,0x28,0x3a,0x28,0xfe,0x5c,0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0x01,0x7a,0x22,0x4c,0x32,0x46,0x46,0x32,0x4c,0x22,0x6e,0x1c,0x28,0x28,0x3a,0x28,0x28,0xfd,0x46,0x28,0x3a,0x28, 0x28,0x3a,0x28,0x00,0x00,0x05,0x00,0x00,0xff,0x6a,0x03,0xe8,0x03,0x52,0x00,0x1f,0x00,0x22,0x00,0x25,0x00,0x33,0x00,0x3c,0x00,0x70,0x40,0x6d,0x23,0x01,0x00,0x06,0x1d,0x01,0x09,0x00,0x27,0x20,0x02,0x07,0x05,0x03,0x4c,0x00,0x03,0x00,0x06,0x00,0x03,0x06,0x67,0x0c,0x01,0x00,0x00,0x09,0x05,0x00,0x09,0x67,0x00,0x05,0x00,0x07, 0x04,0x05,0x07,0x67,0x00,0x04,0x00,0x0a,0x08,0x04,0x0a,0x67,0x00,0x08,0x00,0x02,0x0b,0x08,0x02,0x67,0x0d,0x01,0x0b,0x01,0x01,0x0b,0x57,0x0d,0x01,0x0b,0x0b,0x01,0x5f,0x00,0x01,0x0b,0x01,0x4f,0x34,0x34,0x01,0x00,0x34,0x3c,0x34,0x3c,0x3b,0x39,0x36,0x35,0x30,0x2f,0x2e,0x2c,0x29,0x28,0x25,0x24,0x22,0x21,0x1a,0x17,0x0e,0x0c, 0x09,0x06,0x00,0x1f,0x01,0x1e,0x0e,0x07,0x16,0x2b,0x01,0x32,0x16,0x17,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x35,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x3f,0x01,0x3e,0x01,0x3b,0x01,0x32,0x16,0x17,0x15,0x36,0x33,0x0f,0x01,0x33,0x01,0x07,0x33,0x17,0x37,0x35,0x23,0x15,0x14,0x06,0x07,0x23,0x11,0x21,0x35,0x34,0x36,0x01,0x11, 0x23,0x15,0x14,0x06,0x27,0x23,0x11,0x03,0xb2,0x17,0x1e,0x01,0x20,0x16,0xfd,0xe9,0x17,0x1e,0x01,0xfe,0xd1,0x17,0x1e,0x01,0x16,0x10,0xe4,0x0f,0x36,0x16,0xe8,0x17,0x1e,0x01,0x26,0x21,0x47,0xa7,0xa7,0xfe,0x9b,0xa7,0xa7,0x6d,0xb0,0xd6,0x1e,0x17,0xe9,0x01,0x1e,0x16,0x02,0x26,0xd7,0x1e,0x17,0xe8,0x02,0x7c,0x20,0x16,0xfd,0x5a, 0x17,0x1e,0x01,0x20,0x16,0xa0,0x20,0x16,0x01,0x77,0x16,0x36,0x0f,0xe4,0x10,0x16,0x20,0x16,0xb7,0x17,0x77,0xa7,0x01,0x7d,0xa7,0xc2,0xb0,0xe9,0xe9,0x16,0x1e,0x01,0xfe,0x9b,0x8f,0x16,0x36,0xfe,0x4e,0x02,0x83,0xe8,0x16,0x20,0x01,0xfe,0x9a,0x00,0x00,0x04,0xff,0xff,0xff,0xb1,0x04,0x2f,0x03,0x0b,0x00,0x08,0x00,0x0f,0x00,0x1f, 0x00,0x2f,0x00,0x52,0x40,0x4f,0x1d,0x14,0x02,0x01,0x03,0x0f,0x01,0x00,0x01,0x0e,0x0d,0x0c,0x09,0x04,0x02,0x00,0x1c,0x15,0x02,0x04,0x02,0x04,0x4c,0x00,0x02,0x00,0x04,0x00,0x02,0x04,0x80,0x00,0x01,0x00,0x00,0x02,0x01,0x00,0x69,0x07,0x01,0x03,0x03,0x06,0x5f,0x00,0x06,0x06,0x13,0x4d,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x05, 0x11,0x05,0x4e,0x11,0x10,0x2e,0x2b,0x26,0x23,0x19,0x17,0x10,0x1f,0x11,0x1f,0x13,0x13,0x12,0x08,0x07,0x19,0x2b,0x01,0x14,0x0e,0x01,0x26,0x34,0x36,0x1e,0x01,0x01,0x15,0x21,0x35,0x37,0x17,0x01,0x25,0x21,0x22,0x06,0x07,0x11,0x14,0x16,0x37,0x21,0x32,0x36,0x27,0x11,0x34,0x26,0x17,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x37,0x11, 0x34,0x36,0x37,0x21,0x32,0x16,0x01,0x65,0x3e,0x5a,0x3e,0x3e,0x5a,0x3e,0x02,0x3c,0xfc,0xee,0xb2,0x5a,0x01,0x1d,0x01,0x1e,0xfc,0x83,0x07,0x0a,0x01,0x0c,0x06,0x03,0x7d,0x07,0x0c,0x01,0x0a,0x51,0x34,0x25,0xfc,0x83,0x24,0x36,0x01,0x34,0x25,0x03,0x7d,0x25,0x34,0x02,0x11,0x2d,0x3e,0x02,0x42,0x56,0x42,0x04,0x3a,0xfe,0xfa,0xfa, 0x6b,0xb3,0x59,0x01,0x1d,0xa1,0x0a,0x08,0xfd,0x5a,0x07,0x0c,0x01,0x0a,0x08,0x02,0xa6,0x08,0x0a,0x12,0xfd,0x5a,0x25,0x34,0x01,0x36,0x24,0x02,0xa6,0x25,0x34,0x01,0x36,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0xba,0x00,0xf0,0x03,0x02,0x00,0x13,0x00,0x1c,0x00,0x25,0x00,0x39,0x40,0x36,0x13,0x0a,0x09,0x00,0x04,0x05,0x02,0x01, 0x4c,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x13,0x4d,0x06,0x01,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x11,0x00,0x4e,0x1e,0x1d,0x22,0x21,0x1d,0x25,0x1e,0x25,0x13,0x17,0x19,0x14,0x07,0x07,0x1a,0x2b,0x37,0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34,0x37,0x11,0x26,0x35,0x34,0x36,0x32,0x16, 0x15,0x14,0x07,0x27,0x14,0x16,0x32,0x36,0x34,0x26,0x22,0x06,0x13,0x32,0x36,0x34,0x26,0x22,0x06,0x14,0x16,0xa8,0x48,0x46,0x64,0x46,0x48,0x48,0x46,0x64,0x46,0x48,0x74,0x28,0x38,0x2a,0x2a,0x38,0x28,0x44,0x1c,0x2a,0x2a,0x38,0x28,0x28,0xa2,0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0x01,0x7a,0x22,0x4c,0x32,0x46,0x46,0x32,0x4c, 0x22,0x6e,0x1c,0x28,0x28,0x3a,0x28,0x28,0xfd,0x46,0x28,0x3a,0x28,0x28,0x3a,0x28,0x00,0x03,0xff,0xff,0xff,0x6a,0x04,0x78,0x03,0x52,0x00,0x03,0x00,0x0c,0x00,0x26,0x00,0x38,0x40,0x35,0x00,0x08,0x00,0x03,0x04,0x08,0x03,0x67,0x07,0x01,0x04,0x00,0x01,0x02,0x04,0x01,0x67,0x00,0x02,0x00,0x05,0x00,0x02,0x05,0x67,0x00,0x00,0x06, 0x06,0x00,0x57,0x00,0x00,0x00,0x06,0x60,0x00,0x06,0x00,0x06,0x50,0x33,0x25,0x33,0x26,0x21,0x11,0x11,0x11,0x10,0x09,0x07,0x1f,0x2b,0x17,0x21,0x11,0x29,0x02,0x11,0x21,0x15,0x33,0x32,0x16,0x15,0x01,0x11,0x14,0x06,0x23,0x21,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x37,0x11,0x34,0x36,0x33,0x21,0x35,0x34,0x36,0x33,0x21,0x32,0x16, 0x8f,0x01,0xac,0xfe,0x54,0x02,0x3b,0x01,0x1e,0xfe,0x53,0x36,0x25,0x34,0x01,0xad,0x34,0x25,0xfe,0xac,0x34,0x25,0xfd,0xe8,0x24,0x36,0x01,0x34,0x25,0x01,0x54,0x34,0x25,0x02,0x18,0x24,0x36,0x07,0x01,0x1e,0x01,0xac,0x8f,0x34,0x25,0x01,0x1e,0xfd,0xe8,0x25,0x34,0xc5,0x25,0x34,0x34,0x25,0x02,0x18,0x25,0x34,0xc5,0x25,0x34,0x34, 0x00,0x01,0xff,0xff,0xff,0xb1,0x03,0xe8,0x00,0xcf,0x00,0x0f,0x00,0x13,0x40,0x10,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x11,0x00,0x4e,0x35,0x33,0x02,0x07,0x18,0x2b,0x25,0x15,0x14,0x06,0x07,0x21,0x22,0x26,0x37,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x03,0xe8,0x34,0x25,0xfc,0xca,0x24,0x36,0x01,0x34,0x25,0x03,0x36,0x25,0x34, 0x76,0x6b,0x25,0x34,0x01,0x36,0x24,0x6b,0x25,0x34,0x34,0x00,0x00,0x03,0x00,0x00,0xff,0x6a,0x03,0xa1,0x03,0x0b,0x00,0x03,0x00,0x07,0x00,0x1f,0x00,0x1f,0x40,0x1c,0x07,0x06,0x05,0x03,0x02,0x01,0x00,0x07,0x00,0x01,0x01,0x4c,0x00,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x13,0x00,0x4e,0x1b,0x1e,0x02,0x07,0x18,0x2b,0x05,0x25,0x11, 0x05,0x27,0x2d,0x01,0x0d,0x01,0x11,0x14,0x06,0x07,0x05,0x06,0x22,0x27,0x25,0x2e,0x01,0x35,0x11,0x34,0x36,0x37,0x25,0x36,0x32,0x17,0x05,0x1e,0x01,0x01,0xf4,0x01,0x65,0xfe,0x9b,0x24,0x01,0x86,0xfe,0x7a,0xfe,0x7b,0x03,0x56,0x14,0x12,0xfe,0x77,0x0f,0x26,0x0f,0xfe,0x77,0x11,0x14,0x1a,0x15,0x01,0x89,0x0c,0x18,0x0d,0x01,0x89, 0x15,0x1a,0x3b,0xc3,0x01,0x63,0x82,0x3f,0x8d,0x8e,0x8e,0x01,0xfe,0x54,0x14,0x22,0x09,0xd6,0x09,0x09,0xd6,0x0a,0x20,0x15,0x01,0xac,0x17,0x24,0x08,0x8f,0x05,0x05,0x8f,0x08,0x24,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x44,0x02,0x80,0x00,0x13,0x00,0x31,0x40,0x2e,0x00,0x05,0x00,0x02,0x05,0x59,0x04,0x06,0x02,0x00,0x03,0x01, 0x01,0x02,0x00,0x01,0x67,0x00,0x05,0x05,0x02,0x61,0x00,0x02,0x05,0x02,0x51,0x01,0x00,0x11,0x10,0x0e,0x0c,0x0b,0x09,0x07,0x06,0x04,0x02,0x00,0x13,0x01,0x13,0x07,0x07,0x16,0x2b,0x01,0x32,0x14,0x2b,0x01,0x15,0x14,0x22,0x3d,0x01,0x23,0x22,0x34,0x3b,0x01,0x35,0x34,0x32,0x1d,0x01,0x02,0x26,0x1e,0x1e,0xd2,0x64,0xd2,0x1e,0x1e, 0xd2,0x64,0x01,0x90,0x64,0xd2,0x1e,0x1e,0xd2,0x64,0xd2,0x1e,0x1e,0xd2,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x44,0x01,0x90,0x00,0x07,0x00,0x20,0x40,0x1d,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x01,0x00,0x05,0x02,0x00,0x07,0x01,0x06,0x03,0x07,0x16,0x2b,0x01,0x32, 0x14,0x23,0x21,0x22,0x34,0x33,0x02,0x26,0x1e,0x1e,0xfd,0xf8,0x1e,0x1e,0x01,0x90,0x64,0x64,0x00,0x00,0x00,0x01,0xff,0xfd,0xff,0xb1,0x03,0x5f,0x03,0x0b,0x00,0x0c,0x00,0x13,0x40,0x10,0x00,0x01,0x01,0x13,0x4d,0x00,0x00,0x00,0x11,0x00,0x4e,0x15,0x13,0x02,0x07,0x18,0x2b,0x01,0x14,0x0e,0x01,0x22,0x2e,0x02,0x3e,0x01,0x32,0x1e, 0x01,0x03,0x59,0x72,0xc6,0xe8,0xc8,0x6e,0x06,0x7a,0xbc,0xf4,0xba,0x7e,0x01,0x5e,0x75,0xc4,0x74,0x74,0xc4,0xea,0xc4,0x74,0x74,0xc4,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x3c,0x01,0xed,0x00,0x0e,0x00,0x1e,0x40,0x1b,0x00,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01, 0x00,0x51,0x35,0x14,0x02,0x07,0x18,0x2b,0x01,0x14,0x0f,0x01,0x06,0x22,0x2f,0x01,0x26,0x34,0x36,0x33,0x21,0x32,0x16,0x02,0x3b,0x0a,0xfa,0x0b,0x1c,0x0b,0xfa,0x0b,0x16,0x0e,0x01,0xf4,0x0e,0x16,0x01,0xc9,0x0e,0x0b,0xfa,0x0b,0x0b,0xfa,0x0b,0x1c,0x16,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xf9,0x03,0xa0,0x03,0x0b,0x00,0x2d, 0x00,0x42,0x00,0x48,0x40,0x45,0x3b,0x01,0x04,0x06,0x25,0x01,0x05,0x04,0x02,0x4c,0x00,0x07,0x01,0x02,0x01,0x07,0x02,0x80,0x00,0x06,0x02,0x04,0x02,0x06,0x04,0x80,0x00,0x04,0x05,0x02,0x04,0x05,0x7e,0x00,0x05,0x03,0x02,0x05,0x03,0x7e,0x00,0x03,0x00,0x00,0x03,0x00,0x64,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x01,0x13,0x02,0x4e, 0x14,0x17,0x15,0x27,0x35,0x39,0x35,0x33,0x08,0x07,0x1e,0x2b,0x01,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x17,0x1e,0x01,0x0f,0x01,0x06,0x23,0x27,0x26,0x23,0x21,0x22,0x06,0x07,0x11,0x14,0x16,0x17,0x21,0x32,0x36,0x3d,0x01,0x34,0x3f,0x01,0x36,0x33,0x32,0x17,0x16,0x13,0x01,0x06,0x22,0x2f,0x01, 0x26,0x34,0x3f,0x01,0x36,0x32,0x1f,0x01,0x01,0x36,0x32,0x1f,0x01,0x16,0x14,0x03,0x12,0x5e,0x43,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x23,0x1e,0x09,0x03,0x07,0x1b,0x06,0x07,0x05,0x0d,0x0c,0xfe,0x30,0x25,0x34,0x01,0x36,0x24,0x01,0xd0,0x25,0x34,0x05,0x24,0x06,0x07,0x03,0x04,0x0b,0x81,0xfe,0x39,0x0d,0x24,0x0e,0xf0,0x0e, 0x0e,0x3d,0x0e,0x24,0x0e,0x93,0x01,0x69,0x0d,0x24,0x0e,0x3e,0x0d,0x01,0x4b,0xb1,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42,0x5e,0x01,0x0e,0x04,0x13,0x06,0x1c,0x05,0x01,0x03,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x24,0x8d,0x08,0x05,0x23,0x06,0x02,0x04,0x01,0x05,0xfe,0x3a,0x0e,0x0e,0xf0,0x0d,0x24,0x0e,0x3e,0x0d,0x0d,0x93,0x01, 0x69,0x0d,0x0d,0x3d,0x0e,0x24,0x00,0x00,0x00,0x06,0x00,0x00,0xff,0xb1,0x03,0x12,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x3b,0x00,0x43,0x00,0x67,0x00,0x5d,0x40,0x5a,0x57,0x45,0x02,0x06,0x08,0x29,0x21,0x19,0x11,0x09,0x01,0x06,0x00,0x01,0x02,0x4c,0x00,0x09,0x0e,0x08,0x0e,0x09,0x08,0x80,0x0f,0x0d,0x02,0x08,0x0c,0x0a, 0x02,0x06,0x01,0x08,0x06,0x68,0x05,0x03,0x02,0x01,0x04,0x02,0x02,0x00,0x07,0x01,0x00,0x69,0x00,0x0e,0x0e,0x13,0x4d,0x00,0x07,0x07,0x0b,0x5f,0x00,0x0b,0x0b,0x11,0x0b,0x4e,0x65,0x64,0x61,0x5e,0x5b,0x59,0x53,0x52,0x4f,0x4c,0x49,0x47,0x41,0x3f,0x14,0x24,0x14,0x26,0x26,0x26,0x26,0x26,0x23,0x10,0x07,0x1f,0x2b,0x01,0x11,0x14, 0x06,0x2b,0x01,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x17,0x11,0x14,0x06,0x2b,0x01,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x17,0x11,0x14,0x06,0x2b,0x01,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x13,0x11,0x21,0x11,0x14,0x1e,0x01,0x33,0x21,0x32,0x3e,0x01,0x01,0x33,0x27,0x26,0x27,0x23,0x06, 0x07,0x05,0x15,0x14,0x06,0x2b,0x01,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x23,0x22,0x26,0x3d,0x01,0x34,0x36,0x3b,0x01,0x37,0x3e,0x01,0x37,0x33,0x32,0x16,0x1f,0x01,0x33,0x32,0x16,0x01,0x1e,0x0a,0x08,0x24,0x08,0x0a,0x0a,0x08,0x24,0x08,0x0a,0x8f,0x0a,0x08,0x24,0x08,0x0a,0x0a,0x08,0x24,0x08,0x0a,0x8e,0x0a,0x07,0x24, 0x08,0x0a,0x0a,0x08,0x24,0x07,0x0a,0x48,0xfe,0x0c,0x08,0x08,0x02,0x01,0xd0,0x02,0x08,0x08,0xfe,0x89,0xfa,0x1b,0x04,0x05,0xb1,0x06,0x04,0x01,0xeb,0x0a,0x08,0x36,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x35,0x08,0x0a,0x0a,0x08,0xac,0x27,0x09,0x2c,0x16,0xb2,0x17,0x2a,0x09,0x27,0xad,0x08,0x0a,0x01,0xb7,0xfe,0xbf,0x08,0x0a,0x0a, 0x08,0x01,0x41,0x08,0x0a,0x0a,0x08,0xfe,0xbf,0x08,0x0a,0x0a,0x08,0x01,0x41,0x08,0x0a,0x0a,0x08,0xfe,0xbf,0x08,0x0a,0x0a,0x08,0x01,0x41,0x08,0x0a,0x0a,0xfe,0x64,0x02,0x11,0xfd,0xef,0x0c,0x14,0x0a,0x0a,0x14,0x02,0x65,0x41,0x05,0x01,0x01,0x05,0x53,0x24,0x08,0x0a,0xfd,0xef,0x2e,0x44,0x42,0x2e,0x02,0x13,0x0a,0x08,0x24,0x08, 0x0a,0x5d,0x15,0x1c,0x01,0x1e,0x14,0x5d,0x0a,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0x9c,0x03,0xac,0x03,0x20,0x00,0x2a,0x00,0x34,0x40,0x09,0x20,0x1e,0x16,0x12,0x04,0x00,0x01,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0b,0x00,0x01,0x01,0x10,0x4d,0x00,0x00,0x00,0x11,0x00,0x4e,0x1b,0x40,0x0b,0x00,0x00,0x00,0x01,0x61,0x00, 0x01,0x01,0x10,0x00,0x4e,0x59,0xb5,0x1b,0x1a,0x13,0x02,0x07,0x17,0x2b,0x25,0x16,0x1d,0x01,0x21,0x35,0x34,0x37,0x3e,0x01,0x35,0x34,0x26,0x27,0x2e,0x03,0x27,0x34,0x36,0x3f,0x01,0x26,0x27,0x26,0x36,0x32,0x16,0x0f,0x01,0x16,0x15,0x0e,0x03,0x07,0x0e,0x01,0x15,0x14,0x16,0x02,0xe0,0xcc,0xfc,0x54,0xcc,0x5e,0x44,0x2c,0x0a,0x02, 0x0e,0x0e,0x0e,0x02,0x0a,0x04,0x04,0x08,0x04,0x04,0x5a,0xe0,0x5c,0x06,0x0c,0x12,0x02,0x0e,0x0e,0x0e,0x02,0x08,0x2e,0x46,0x80,0x48,0x32,0x6a,0x6a,0x32,0x48,0x22,0x46,0x3c,0x16,0x36,0x2e,0x0c,0x0c,0x04,0x1e,0x1c,0x10,0x14,0x02,0x04,0x32,0x26,0x36,0x74,0x74,0x36,0x58,0x08,0x22,0x1c,0x1e,0x04,0x0c,0x0c,0x30,0x34,0x16,0x3c, 0x46,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0xb6,0x03,0xe8,0x03,0x08,0x00,0x18,0x00,0x20,0x00,0x2d,0x00,0x94,0xb5,0x25,0x01,0x09,0x0b,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x30,0x0d,0x01,0x0b,0x08,0x09,0x08,0x0b,0x72,0x0c,0x01,0x05,0x00,0x01,0x05,0x57,0x06,0x03,0x02,0x01,0x04,0x01,0x00,0x08,0x01,0x00,0x67,0x00,0x07, 0x07,0x02,0x5f,0x00,0x02,0x02,0x13,0x4d,0x0a,0x01,0x08,0x08,0x09,0x5f,0x00,0x09,0x09,0x11,0x09,0x4e,0x1b,0x40,0x31,0x0d,0x01,0x0b,0x08,0x09,0x08,0x0b,0x09,0x80,0x0c,0x01,0x05,0x00,0x01,0x05,0x57,0x06,0x03,0x02,0x01,0x04,0x01,0x00,0x08,0x01,0x00,0x67,0x00,0x07,0x07,0x02,0x5f,0x00,0x02,0x02,0x13,0x4d,0x0a,0x01,0x08,0x08, 0x09,0x5f,0x00,0x09,0x09,0x11,0x09,0x4e,0x59,0x40,0x1e,0x21,0x21,0x00,0x00,0x21,0x2d,0x21,0x2d,0x2c,0x2b,0x29,0x26,0x23,0x22,0x20,0x1d,0x1b,0x1a,0x00,0x18,0x00,0x18,0x12,0x24,0x35,0x22,0x11,0x0e,0x07,0x1b,0x2b,0x01,0x15,0x21,0x13,0x36,0x3b,0x01,0x36,0x3f,0x01,0x3e,0x01,0x3b,0x01,0x32,0x16,0x17,0x16,0x17,0x33,0x32,0x17, 0x13,0x21,0x35,0x03,0x07,0x21,0x27,0x26,0x2b,0x01,0x22,0x13,0x35,0x21,0x06,0x07,0x06,0x23,0x21,0x22,0x35,0x27,0x21,0x15,0x01,0xc8,0xfe,0x38,0x0a,0x04,0x60,0xa0,0x10,0x15,0x17,0x0e,0x12,0x1c,0xde,0x1a,0x14,0x0c,0x12,0x2a,0xa0,0x60,0x04,0x0a,0xfe,0x3a,0xa4,0x1c,0x01,0x24,0x1c,0x0e,0x1c,0x98,0x1c,0x96,0x01,0xae,0x06,0x04, 0x06,0x54,0xfd,0x12,0x5a,0x0a,0x01,0xae,0x01,0x46,0x64,0x01,0x24,0x6c,0x1a,0x29,0x2d,0x1a,0x0c,0x0e,0x18,0x20,0x50,0x6c,0xfe,0xdc,0x64,0x01,0x62,0x36,0x36,0x1a,0xfd,0x8a,0x64,0x58,0x4e,0x54,0x54,0xa6,0x64,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0xdc,0x01,0xcc,0x00,0x08,0x00,0x20,0x40,0x1d,0x02,0x01,0x00,0x01, 0x01,0x00,0x59,0x02,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x00,0x01,0x51,0x01,0x00,0x05,0x04,0x00,0x08,0x01,0x08,0x03,0x07,0x16,0x2b,0x13,0x32,0x16,0x14,0x06,0x22,0x26,0x34,0x36,0x6e,0x2e,0x40,0x40,0x5c,0x40,0x40,0x01,0xcc,0x40,0x5a,0x42,0x42,0x5a,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x67,0x02,0x7c,0x00,0x0d, 0x00,0x1e,0x40,0x1b,0x00,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x17,0x13,0x02,0x07,0x18,0x2b,0x01,0x11,0x14,0x06,0x22,0x2f,0x01,0x26,0x34,0x3f,0x01,0x36,0x32,0x16,0x01,0x65,0x14,0x20,0x09,0xfa,0x0a,0x0a,0xfa,0x0b,0x1c,0x18,0x02,0x58,0xfe,0x0c,0x0e,0x16, 0x0b,0xfa,0x0b,0x1c,0x0b,0xfa,0x0b,0x16,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x41,0x02,0x7d,0x00,0x0e,0x00,0x0a,0xb7,0x00,0x00,0x00,0x76,0x14,0x01,0x07,0x17,0x2b,0x01,0x14,0x0f,0x01,0x06,0x22,0x26,0x35,0x11,0x34,0x3e,0x01,0x1f,0x01,0x16,0x01,0x41,0x0a,0xfa,0x0b,0x1c,0x16,0x16,0x1c,0x0b,0xfa,0x0a,0x01,0x5e,0x0e,0x0b,0xfa, 0x0b,0x16,0x0e,0x01,0xf4,0x0f,0x14,0x02,0x0c,0xfa,0x0a,0x00,0x00,0x01,0xff,0xff,0x00,0x00,0x02,0x3b,0x01,0xc9,0x00,0x0e,0x00,0x18,0x40,0x15,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x15,0x32,0x02,0x07,0x18,0x2b,0x25,0x14,0x06,0x27,0x21,0x22,0x2e,0x01,0x3f,0x01,0x36,0x32,0x1f,0x01, 0x16,0x02,0x3b,0x14,0x0f,0xfe,0x0c,0x0f,0x14,0x02,0x0c,0xfa,0x0a,0x1e,0x0a,0xfa,0x0a,0xab,0x0e,0x16,0x01,0x14,0x1e,0x0b,0xfa,0x0a,0x0a,0xfa,0x0b,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x5e,0x02,0x51,0x00,0x15,0x00,0x1e,0x40,0x1b,0x03,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00, 0x61,0x00,0x00,0x01,0x00,0x51,0x17,0x19,0x02,0x07,0x18,0x2b,0x01,0x14,0x0f,0x01,0x17,0x16,0x14,0x0f,0x01,0x06,0x22,0x27,0x01,0x26,0x34,0x37,0x01,0x36,0x32,0x1f,0x01,0x16,0x01,0x5e,0x06,0xdb,0xdb,0x06,0x06,0x1c,0x05,0x0e,0x06,0xfe,0xfc,0x06,0x06,0x01,0x04,0x05,0x10,0x04,0x1c,0x06,0x02,0x22,0x07,0x05,0xdc,0xdb,0x06,0x0e, 0x06,0x1c,0x05,0x05,0x01,0x05,0x05,0x0e,0x06,0x01,0x04,0x06,0x06,0x1c,0x05,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x4c,0x02,0x51,0x00,0x15,0x00,0x1e,0x40,0x1b,0x0b,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x1c,0x14,0x02,0x07,0x18,0x2b,0x01,0x14,0x07,0x01, 0x06,0x22,0x2f,0x01,0x26,0x34,0x3f,0x01,0x27,0x26,0x34,0x3f,0x01,0x36,0x32,0x17,0x01,0x16,0x01,0x4c,0x05,0xfe,0xfb,0x05,0x0e,0x06,0x1c,0x06,0x06,0xdb,0xdb,0x06,0x06,0x1c,0x05,0x10,0x04,0x01,0x05,0x05,0x01,0x3a,0x07,0x05,0xfe,0xfb,0x05,0x05,0x1c,0x06,0x0e,0x06,0xdb,0xdc,0x05,0x0e,0x06,0x1c,0x06,0x06,0xfe,0xfc,0x05,0x00, 0x00,0x03,0xff,0xfc,0xff,0x90,0x03,0x9a,0x03,0x2c,0x00,0x08,0x00,0x16,0x00,0x3f,0x00,0x83,0x40,0x0b,0x38,0x36,0x02,0x03,0x05,0x13,0x01,0x02,0x03,0x02,0x4c,0x4b,0xb0,0x24,0x50,0x58,0x40,0x24,0x00,0x05,0x06,0x03,0x06,0x05,0x03,0x80,0x00,0x06,0x00,0x03,0x02,0x06,0x03,0x69,0x08,0x01,0x02,0x00,0x01,0x02,0x01,0x66,0x00,0x04, 0x04,0x00,0x61,0x07,0x01,0x00,0x00,0x12,0x04,0x4e,0x1b,0x40,0x2b,0x00,0x05,0x06,0x03,0x06,0x05,0x03,0x80,0x07,0x01,0x00,0x00,0x04,0x06,0x00,0x04,0x69,0x00,0x06,0x00,0x03,0x02,0x06,0x03,0x69,0x08,0x01,0x02,0x01,0x01,0x02,0x59,0x08,0x01,0x02,0x02,0x01,0x62,0x00,0x01,0x02,0x01,0x52,0x59,0x40,0x19,0x0a,0x09,0x01,0x00,0x27, 0x26,0x22,0x20,0x1d,0x1b,0x11,0x0e,0x09,0x16,0x0a,0x16,0x05,0x04,0x00,0x08,0x01,0x08,0x09,0x07,0x16,0x2b,0x01,0x36,0x00,0x12,0x00,0x04,0x00,0x02,0x00,0x13,0x32,0x36,0x35,0x36,0x26,0x2b,0x01,0x22,0x06,0x07,0x14,0x16,0x17,0x13,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x07,0x15,0x33,0x35,0x34,0x37,0x36,0x32,0x17,0x16,0x15, 0x14,0x07,0x06,0x0f,0x01,0x06,0x0f,0x01,0x06,0x07,0x06,0x07,0x15,0x33,0x35,0x34,0x37,0x36,0x3f,0x01,0x36,0x01,0xc6,0xbe,0x01,0x10,0x06,0xfe,0xf6,0xfe,0x84,0xfe,0xee,0x06,0x01,0x0c,0xbc,0x1e,0x26,0x02,0x26,0x1e,0x02,0x1c,0x26,0x02,0x26,0x1c,0xa8,0x1a,0x6a,0x52,0x40,0x28,0x44,0x04,0x6e,0x10,0x10,0x4e,0x0c,0x10,0x10,0x08, 0x0c,0x16,0x0a,0x0a,0x15,0x0b,0x06,0x0e,0x04,0x6c,0x04,0x06,0x16,0x1c,0x2e,0x03,0x2a,0x02,0xfe,0xf8,0xfe,0x84,0xfe,0xee,0x06,0x01,0x0a,0x01,0x7c,0x01,0x12,0xfd,0x1e,0x26,0x1c,0x1e,0x26,0x24,0x1c,0x1e,0x26,0x02,0x01,0x48,0x22,0x2c,0x4e,0x4c,0x1a,0x2a,0x68,0x04,0x04,0x1a,0x1c,0x18,0x14,0x14,0x18,0x12,0x16,0x0c,0x08,0x0f, 0x07,0x08,0x11,0x09,0x08,0x14,0x3a,0x08,0x04,0x0c,0x10,0x14,0x10,0x12,0x22,0x00,0x00,0x02,0x00,0x00,0xff,0xbd,0x03,0x4d,0x03,0x0b,0x00,0x08,0x00,0x1d,0x00,0x3a,0xb5,0x00,0x01,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x29,0x50,0x58,0x40,0x10,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x13,0x4d,0x00,0x01,0x01,0x11,0x01,0x4e,0x1b,0x40, 0x10,0x00,0x01,0x00,0x01,0x86,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x13,0x00,0x4e,0x59,0xb5,0x38,0x1a,0x12,0x03,0x07,0x19,0x2b,0x13,0x34,0x26,0x0e,0x01,0x1e,0x02,0x36,0x01,0x14,0x07,0x01,0x06,0x22,0x27,0x01,0x2e,0x01,0x3d,0x01,0x34,0x36,0x37,0x33,0x32,0x16,0x17,0x01,0x16,0xfa,0x2a,0x3a,0x2c,0x02,0x28,0x3e,0x26,0x02, 0x55,0x14,0xfe,0xee,0x16,0x3b,0x14,0xfe,0x71,0x15,0x1e,0x2a,0x1d,0xe9,0x1d,0x48,0x15,0x01,0x8f,0x14,0x02,0x58,0x1e,0x2a,0x02,0x26,0x40,0x24,0x06,0x30,0xfe,0xd9,0x1e,0x15,0xfe,0xee,0x15,0x15,0x01,0x8f,0x15,0x48,0x1d,0xe8,0x1d,0x2a,0x01,0x1e,0x15,0xfe,0x71,0x15,0x00,0x0d,0x00,0x00,0xff,0xea,0x03,0xca,0x02,0xd2,0x00,0x03, 0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x2f,0x00,0x33,0x00,0xa9,0x40,0xa6,0x18,0x12,0x0c,0x03,0x06,0x00,0x07,0x00,0x06,0x07,0x80,0x20,0x19,0x13,0x1d,0x0d,0x05,0x07,0x03,0x00,0x07,0x03,0x7e,0x17,0x11,0x0b,0x03,0x05,0x02,0x04,0x02,0x05,0x04,0x80,0x16,0x10, 0x0a,0x03,0x04,0x01,0x02,0x04,0x01,0x7e,0x00,0x00,0x14,0x1e,0x0f,0x08,0x1b,0x05,0x03,0x02,0x00,0x03,0x67,0x1f,0x15,0x0e,0x1c,0x09,0x05,0x02,0x05,0x01,0x02,0x58,0x1f,0x15,0x0e,0x1c,0x09,0x05,0x02,0x02,0x01,0x5f,0x1a,0x01,0x01,0x02,0x01,0x4f,0x30,0x30,0x28,0x28,0x1c,0x1c,0x18,0x18,0x10,0x10,0x04,0x04,0x00,0x00,0x30,0x33, 0x30,0x33,0x32,0x31,0x2f,0x2e,0x2d,0x2c,0x28,0x2b,0x28,0x2b,0x2a,0x29,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x18,0x1b,0x18,0x1b,0x1a,0x19,0x17,0x16,0x15,0x14,0x10,0x13,0x10,0x13,0x12,0x11,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x21, 0x07,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x15,0x33,0x35,0x03,0x33,0x35,0x23,0x13,0x23,0x15,0x33,0x17,0x35,0x23,0x1d,0x01,0x33,0x35,0x23,0x13,0x35,0x23,0x15,0x05,0x15,0x33,0x35,0x03,0x33,0x35,0x23,0x13,0x23,0x15,0x33,0x17,0x35,0x23,0x1d,0x01,0x33,0x35,0x23,0x13,0x35,0x23,0x15,0x03,0xca,0xfe,0x3d,0x9f,0x9f,0x9f,0x9f,0x9f, 0x9f,0x9f,0xe1,0x9e,0x9e,0x9e,0x9e,0x9e,0xfd,0x5b,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0x9e,0xe1,0x9d,0x9d,0x9d,0x9d,0x9d,0x16,0x02,0xe8,0xfd,0x18,0x01,0xc4,0x9f,0x9f,0xfe,0x80,0x9d,0x01,0xc4,0x9e,0xe2,0x9f,0x9f,0xe1,0x9d,0x01,0x26,0x9e,0x9e,0x43,0x9f,0x9f,0xfe,0x80,0x9d,0x01,0xc4,0x9e,0xe2,0x9f,0x9f,0xe1,0x9d,0x01,0x26,0x9e, 0x9e,0x00,0x00,0x00,0x00,0x02,0xff,0xff,0xff,0xf9,0x04,0x19,0x03,0x0b,0x00,0x12,0x00,0x29,0x00,0x20,0x40,0x1d,0x00,0x04,0x00,0x02,0x01,0x04,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x00,0x63,0x00,0x03,0x03,0x13,0x03,0x4e,0x23,0x3a,0x23,0x36,0x35,0x05,0x07,0x1b,0x2b,0x01,0x14,0x0f,0x01,0x0e,0x01,0x23,0x21,0x22,0x2e,0x01,0x3f, 0x01,0x3e,0x01,0x33,0x21,0x32,0x16,0x27,0x15,0x21,0x22,0x06,0x0f,0x02,0x27,0x26,0x37,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x1d,0x01,0x21,0x32,0x16,0x04,0x19,0x12,0xbb,0x18,0x56,0x26,0xfd,0xa1,0x13,0x1c,0x01,0x11,0xbc,0x18,0x56,0x25,0x02,0x5f,0x13,0x1e,0xc0,0xfe,0x30,0x35,0x72,0x23,0xbc,0x02,0x01,0x01,0x01,0x4a,0x33,0xb3, 0x33,0x4a,0x01,0x2f,0x34,0x48,0x01,0x3f,0x11,0x14,0xdd,0x1c,0x28,0x0e,0x22,0x14,0xdd,0x1c,0x28,0x0e,0xaf,0x5a,0x34,0x29,0xdd,0x03,0x07,0x05,0x02,0x02,0x18,0x33,0x4a,0x4a,0x33,0x12,0x4a,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0xf9,0x03,0xa1,0x03,0x0b,0x00,0x14,0x00,0x16,0x40,0x13,0x00,0x02,0x00,0x00,0x02,0x00,0x64,0x00, 0x01,0x01,0x13,0x01,0x4e,0x23,0x35,0x33,0x03,0x07,0x19,0x2b,0x01,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x1d,0x01,0x21,0x32,0x16,0x03,0xa1,0x4a,0x33,0xfd,0x59,0x33,0x4a,0x4a,0x33,0xb3,0x33,0x4a,0x01,0x77,0x33,0x4a,0x01,0xff,0xfe,0x77,0x33,0x4a,0x4a,0x33,0x02,0x18,0x33,0x4a,0x4a,0x33, 0x12,0x4a,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0xf2,0x02,0xf8,0x02,0xcc,0x00,0x06,0x00,0x1d,0x40,0x1a,0x01,0x01,0x00,0x49,0x00,0x01,0x00,0x01,0x85,0x03,0x02,0x02,0x00,0x00,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x11,0x12,0x04,0x07,0x18,0x2b,0x09,0x02,0x33,0x11,0x21,0x11,0x02,0xf8,0xfe,0x84,0xfe,0x84,0xc0,0x01,0x78,0x01,0x6e, 0xfe,0x84,0x01,0x7c,0x01,0x5e,0xfe,0xa2,0x00,0x02,0xff,0xf7,0xff,0xe2,0x03,0xdb,0x03,0x12,0x00,0x17,0x00,0x20,0x00,0x26,0x40,0x23,0x00,0x02,0x01,0x02,0x85,0x03,0x01,0x01,0x00,0x00,0x01,0x59,0x03,0x01,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x19,0x18,0x1d,0x1c,0x18,0x20,0x19,0x20,0x2f,0x04,0x07,0x17,0x2b,0x01,0x1e, 0x01,0x06,0x07,0x06,0x26,0x06,0x07,0x06,0x1e,0x01,0x07,0x0e,0x02,0x23,0x22,0x26,0x37,0x3e,0x01,0x37,0x24,0x03,0x32,0x36,0x34,0x26,0x22,0x06,0x14,0x16,0x03,0x59,0x48,0x3a,0x12,0x1a,0x10,0x4c,0x54,0x26,0x1e,0x12,0x32,0x02,0x02,0x44,0xb8,0x7c,0xba,0xd2,0x0a,0x08,0xc0,0x78,0x01,0x22,0x48,0x1e,0x2c,0x2c,0x3e,0x2c,0x2c,0x02, 0x6e,0x30,0x7c,0x54,0x06,0x04,0x1c,0x08,0x2a,0x2e,0x3a,0x48,0x0e,0x1a,0x4a,0x4a,0xca,0x90,0x76,0xea,0x22,0x54,0xfd,0x8a,0x2c,0x40,0x2a,0x2a,0x40,0x2c,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0x6a,0x03,0x59,0x03,0x52,0x00,0x06,0x00,0x18,0x00,0x33,0x40,0x30,0x01,0x01,0x00,0x03,0x01,0x4c,0x00,0x03,0x00,0x03,0x85,0x04,0x01,0x00, 0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x60,0x00,0x02,0x01,0x02,0x50,0x00,0x00,0x18,0x16,0x11,0x0e,0x0b,0x09,0x00,0x06,0x00,0x06,0x05,0x07,0x16,0x2b,0x01,0x11,0x16,0x1f,0x01,0x16,0x17,0x05,0x14,0x16,0x17,0x21,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x37,0x21,0x02,0x3b,0x0d,0x08, 0xe3,0x08,0x08,0xfe,0xb1,0x20,0x16,0x01,0x2f,0x1e,0x17,0xfd,0x12,0x17,0x1e,0x01,0x20,0x16,0x01,0xbe,0x02,0x34,0x01,0x08,0x08,0x08,0xe4,0x07,0x0d,0x12,0x16,0x1e,0x01,0xfd,0xb3,0x17,0x1e,0x01,0x20,0x16,0x03,0x7c,0x17,0x1e,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xb1,0x03,0x5a,0x03,0x0b,0x00,0x08,0x00,0x6a,0x00,0x45, 0x40,0x42,0x65,0x59,0x4c,0x41,0x04,0x00,0x04,0x3b,0x0a,0x02,0x01,0x00,0x34,0x28,0x1b,0x10,0x04,0x03,0x01,0x03,0x4c,0x06,0x01,0x04,0x00,0x03,0x02,0x04,0x03,0x69,0x00,0x00,0x00,0x05,0x5f,0x00,0x05,0x05,0x13,0x4d,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x11,0x02,0x4e,0x5c,0x5b,0x53,0x51,0x49,0x48,0x2b,0x2a,0x22,0x20,0x13, 0x12,0x07,0x07,0x18,0x2b,0x01,0x34,0x26,0x22,0x0e,0x01,0x16,0x32,0x36,0x25,0x15,0x14,0x06,0x0f,0x01,0x06,0x07,0x16,0x17,0x16,0x14,0x07,0x0e,0x01,0x27,0x22,0x2f,0x01,0x06,0x07,0x06,0x07,0x06,0x2b,0x01,0x22,0x26,0x35,0x27,0x26,0x27,0x07,0x06,0x22,0x27,0x26,0x27,0x26,0x34,0x37,0x3e,0x01,0x37,0x26,0x2f,0x01,0x2e,0x01,0x27, 0x35,0x34,0x36,0x3f,0x01,0x36,0x37,0x26,0x27,0x26,0x34,0x37,0x3e,0x01,0x33,0x32,0x1f,0x01,0x36,0x37,0x36,0x37,0x36,0x3b,0x01,0x32,0x16,0x1f,0x01,0x16,0x17,0x37,0x36,0x32,0x17,0x16,0x17,0x16,0x14,0x07,0x0e,0x01,0x07,0x16,0x1f,0x01,0x1e,0x01,0x02,0x3b,0x52,0x78,0x52,0x02,0x56,0x74,0x56,0x01,0x1c,0x08,0x07,0x68,0x0a,0x0b, 0x13,0x28,0x06,0x05,0x0f,0x50,0x0d,0x07,0x07,0x4d,0x19,0x1a,0x09,0x07,0x04,0x10,0x7c,0x08,0x0c,0x10,0x1b,0x17,0x4f,0x06,0x10,0x06,0x46,0x16,0x04,0x05,0x08,0x28,0x0a,0x0f,0x08,0x66,0x07,0x08,0x01,0x0a,0x05,0x68,0x08,0x0e,0x17,0x25,0x06,0x05,0x0f,0x50,0x0d,0x07,0x08,0x4d,0x18,0x1a,0x09,0x08,0x03,0x11,0x7c,0x07,0x0c,0x01, 0x0f,0x1c,0x17,0x4f,0x05,0x0f,0x07,0x48,0x14,0x04,0x04,0x09,0x28,0x0a,0x0f,0x08,0x66,0x07,0x0a,0x01,0x5e,0x3b,0x54,0x54,0x76,0x54,0x54,0x78,0x7c,0x07,0x0c,0x01,0x10,0x1e,0x15,0x1b,0x32,0x06,0x0e,0x06,0x15,0x50,0x01,0x05,0x3c,0x0d,0x08,0x4c,0x1c,0x10,0x0a,0x07,0x67,0x09,0x0c,0x3c,0x05,0x06,0x40,0x1e,0x05,0x0e,0x06,0x0c, 0x32,0x0f,0x1c,0x1b,0x0f,0x01,0x0c,0x07,0x7c,0x07,0x0c,0x01,0x10,0x19,0x1a,0x20,0x2d,0x07,0x0c,0x07,0x14,0x50,0x05,0x3c,0x0d,0x08,0x4c,0x1c,0x10,0x0a,0x07,0x67,0x09,0x0b,0x3b,0x05,0x05,0x43,0x1c,0x05,0x0e,0x06,0x0c,0x32,0x0f,0x1c,0x1a,0x10,0x01,0x0c,0x00,0x00,0x00,0x09,0x00,0x00,0xff,0xf9,0x03,0xe8,0x03,0x0b,0x00,0x0f, 0x00,0x1f,0x00,0x2f,0x00,0x3f,0x00,0x4f,0x00,0x5f,0x00,0x6f,0x00,0x7f,0x00,0x8f,0x00,0x47,0x40,0x44,0x0f,0x09,0x02,0x03,0x0e,0x08,0x02,0x02,0x01,0x03,0x02,0x67,0x0b,0x05,0x02,0x01,0x0a,0x04,0x02,0x00,0x01,0x00,0x63,0x10,0x0c,0x02,0x06,0x06,0x07,0x5f,0x11,0x0d,0x02,0x07,0x07,0x13,0x06,0x4e,0x8e,0x8b,0x86,0x83,0x7e,0x7b, 0x76,0x73,0x6e,0x6b,0x66,0x63,0x5e,0x5b,0x56,0x53,0x4e,0x4b,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x35,0x33,0x12,0x07,0x1f,0x2b,0x25,0x15,0x14,0x06,0x07,0x23,0x22,0x26,0x27,0x35,0x34,0x36,0x17,0x33,0x32,0x16,0x13,0x15,0x14,0x06,0x27,0x23,0x22,0x26,0x27,0x35,0x34,0x36,0x37,0x33,0x32,0x16,0x01,0x15,0x14,0x06,0x07,0x23,0x22, 0x26,0x27,0x35,0x34,0x36,0x17,0x33,0x32,0x16,0x01,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x27,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x01,0x15,0x14,0x06,0x27,0x23,0x22,0x26,0x27,0x35,0x34,0x36,0x37,0x33,0x32,0x16,0x01,0x15,0x14,0x06,0x07,0x23,0x22,0x26,0x3d,0x01,0x34,0x36,0x17,0x33,0x32,0x16,0x01,0x15,0x14,0x06,0x2b,0x01,0x22, 0x26,0x27,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x01,0x15,0x14,0x06,0x27,0x23,0x22,0x26,0x3d,0x01,0x34,0x36,0x37,0x33,0x32,0x16,0x13,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x3d,0x01,0x34,0x36,0x3b,0x01,0x32,0x16,0x01,0x1e,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2, 0x17,0x1e,0x01,0x66,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x17,0x1e,0xfe,0x9c,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x17,0x1e,0x01,0x66,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x17,0x1e,0x01,0x66,0x20,0x16,0xb2,0x16,0x20,0x20,0x16,0xb2,0x17,0x1e,0xfe,0x9c,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2, 0x17,0x1e,0x01,0x66,0x20,0x16,0xb2,0x16,0x20,0x20,0x16,0xb2,0x17,0x1e,0x01,0x20,0x16,0xb2,0x16,0x20,0x20,0x16,0xb2,0x17,0x1e,0x9a,0x6c,0x16,0x1e,0x01,0x20,0x15,0x6c,0x16,0x20,0x01,0x1e,0x01,0x06,0x6b,0x16,0x20,0x01,0x1e,0x17,0x6b,0x17,0x1e,0x01,0x20,0xfe,0xcd,0x6c,0x16,0x1e,0x01,0x20,0x15,0x6c,0x16,0x20,0x01,0x1e,0x02, 0x24,0x6b,0x16,0x20,0x20,0x16,0x6b,0x16,0x20,0x20,0xfe,0xcc,0x6b,0x16,0x20,0x01,0x1e,0x17,0x6b,0x17,0x1e,0x01,0x20,0xfe,0xcd,0x6c,0x16,0x1e,0x01,0x20,0x15,0x6c,0x16,0x20,0x01,0x1e,0x02,0x24,0x6b,0x16,0x20,0x20,0x16,0x6b,0x16,0x20,0x20,0xfe,0xcc,0x6b,0x16,0x20,0x01,0x1e,0x17,0x6b,0x17,0x1e,0x01,0x20,0x01,0x08,0x6b,0x16, 0x20,0x20,0x16,0x6b,0x16,0x20,0x20,0x00,0x00,0x05,0x00,0x00,0xff,0x6a,0x03,0xe8,0x03,0x52,0x00,0x10,0x00,0x14,0x00,0x25,0x00,0x2f,0x00,0x39,0x00,0x65,0x40,0x62,0x33,0x29,0x02,0x07,0x08,0x21,0x01,0x05,0x02,0x1d,0x15,0x0d,0x0c,0x04,0x00,0x05,0x03,0x4c,0x04,0x01,0x05,0x01,0x4b,0x0a,0x01,0x08,0x09,0x01,0x07,0x01,0x08,0x07, 0x67,0x00,0x02,0x05,0x01,0x02,0x57,0x06,0x0c,0x03,0x0b,0x04,0x01,0x00,0x05,0x00,0x01,0x05,0x69,0x06,0x0c,0x03,0x0b,0x04,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x11,0x11,0x00,0x00,0x37,0x35,0x32,0x31,0x2d,0x2b,0x28,0x27,0x24,0x22,0x1f,0x1e,0x1b,0x19,0x11,0x14,0x11,0x14,0x13,0x12,0x00,0x10,0x00,0x0f,0x37,0x0d, 0x07,0x17,0x2b,0x01,0x11,0x14,0x06,0x07,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x13,0x36,0x33,0x21,0x11,0x23,0x11,0x01,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x22,0x26,0x27,0x11,0x33,0x32,0x17,0x25,0x15,0x23,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x05,0x15,0x23,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x01,0x89,0x16, 0x0e,0x14,0x10,0xfe,0xe3,0x0f,0x14,0x01,0x8b,0x04,0x0d,0x01,0x9f,0x8e,0x02,0x3b,0x16,0x0e,0xfe,0xe3,0x0f,0x14,0x01,0x0f,0x14,0x01,0xed,0x0d,0x04,0xfe,0x3e,0xc5,0x0a,0x08,0xa1,0x08,0x0a,0x01,0x77,0xc5,0x0a,0x08,0xa1,0x08,0x0a,0x02,0x9f,0xfe,0x54,0x0f,0x14,0x01,0xfe,0xbf,0x0f,0x14,0x01,0x16,0x0e,0x01,0x1d,0x01,0xe8,0x0c, 0xfe,0x78,0x01,0x88,0xfe,0x0c,0xfe,0xe3,0x0f,0x14,0x01,0x16,0x0e,0x01,0x41,0x16,0x0e,0x01,0xac,0x0c,0xad,0x7d,0x7d,0x08,0x0a,0x0a,0x08,0x7d,0x7d,0x08,0x0a,0x0a,0x00,0x08,0xff,0xff,0xff,0xf8,0x03,0xe9,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x3f,0x00,0x4f,0x00,0x5f,0x00,0x6f,0x00,0x7f,0x00,0x6f,0x40,0x6c,0x79,0x78, 0x71,0x49,0x48,0x41,0x06,0x08,0x09,0x69,0x61,0x60,0x29,0x21,0x20,0x06,0x04,0x05,0x59,0x58,0x51,0x50,0x19,0x18,0x11,0x10,0x08,0x02,0x03,0x39,0x38,0x31,0x09,0x08,0x01,0x06,0x00,0x01,0x04,0x4c,0x0d,0x01,0x05,0x0c,0x01,0x04,0x03,0x05,0x04,0x67,0x0b,0x01,0x03,0x0a,0x01,0x02,0x01,0x03,0x02,0x67,0x07,0x01,0x01,0x06,0x01,0x00, 0x01,0x00,0x63,0x0e,0x01,0x08,0x08,0x09,0x5f,0x0f,0x01,0x09,0x09,0x13,0x08,0x4e,0x7d,0x7b,0x75,0x73,0x6d,0x6b,0x65,0x64,0x5d,0x5b,0x55,0x54,0x4d,0x4c,0x26,0x26,0x17,0x26,0x17,0x17,0x17,0x17,0x14,0x10,0x07,0x1f,0x2b,0x37,0x15,0x14,0x06,0x27,0x23,0x22,0x26,0x37,0x35,0x34,0x36,0x37,0x33,0x32,0x16,0x27,0x15,0x14,0x06,0x27, 0x23,0x22,0x26,0x37,0x35,0x34,0x36,0x17,0x33,0x32,0x16,0x27,0x15,0x14,0x06,0x07,0x23,0x22,0x26,0x37,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x01,0x15,0x14,0x06,0x27,0x21,0x22,0x26,0x27,0x35,0x34,0x36,0x37,0x21,0x32,0x16,0x01,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x37,0x35,0x34,0x36,0x37,0x33,0x32,0x16,0x01,0x15,0x14,0x06,0x27, 0x21,0x22,0x26,0x27,0x35,0x34,0x36,0x17,0x21,0x32,0x16,0x27,0x15,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x27,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x35,0x34,0x36,0x37,0x21,0x32,0x16,0x8f,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08, 0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x03,0x58,0x0a,0x08,0xfd,0x12,0x07,0x0a,0x01,0x0c,0x06,0x02,0xee,0x07,0x0c,0xfc,0xa6,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x03,0x58,0x0a,0x08,0xfd,0x12,0x07,0x0a,0x01,0x0c,0x06,0x02,0xee,0x07,0x0c,0x01,0x0a,0x08,0xfd,0x12,0x07, 0x0a,0x01,0x0c,0x06,0x02,0xee,0x07,0x0c,0x01,0x0a,0x08,0xfd,0x12,0x07,0x0a,0x01,0x0c,0x06,0x02,0xee,0x07,0x0c,0x76,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0a,0x01,0x0c,0xd0,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0xce,0x6b,0x07,0x0a,0x01,0x0c,0x06,0x6b,0x08,0x0a,0x0a,0xfe,0x4c,0x6b,0x07,0x0c,0x01,0x0a, 0x08,0x6b,0x07,0x0a,0x01,0x0c,0x02,0x7d,0x6b,0x08,0x0a,0x0a,0x08,0x6b,0x07,0x0a,0x01,0x0c,0xfe,0x4d,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0xce,0x6b,0x07,0x0a,0x01,0x0c,0x06,0x6b,0x08,0x0a,0x0a,0xcf,0x6b,0x08,0x0a,0x0a,0x08,0x6b,0x07,0x0a,0x01,0x0c,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xf9,0x02,0x83, 0x03,0x0b,0x00,0x07,0x00,0x1f,0x00,0x20,0x40,0x1d,0x05,0x03,0x02,0x00,0x00,0x02,0x00,0x02,0x63,0x00,0x01,0x01,0x04,0x61,0x00,0x04,0x04,0x13,0x01,0x4e,0x23,0x13,0x25,0x36,0x13,0x10,0x06,0x07,0x1c,0x2b,0x13,0x21,0x35,0x34,0x26,0x0e,0x01,0x17,0x05,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x17,0x33,0x35,0x34, 0x36,0x32,0x16,0x07,0x15,0x33,0x32,0x16,0xb3,0x01,0x1d,0x54,0x76,0x54,0x01,0x01,0xd0,0x20,0x16,0xfd,0xe9,0x17,0x1e,0x01,0x20,0x16,0x11,0x94,0xcc,0x96,0x02,0x12,0x17,0x1e,0x01,0xa5,0x6c,0x3b,0x54,0x02,0x50,0x3d,0xa1,0xfe,0xbe,0x16,0x1e,0x01,0x20,0x15,0x01,0x42,0x16,0x20,0x01,0x6c,0x66,0x94,0x94,0x66,0x6c,0x1e,0x00,0x00, 0x00,0x01,0x00,0x00,0xff,0xe2,0x02,0xda,0x02,0xda,0x00,0x06,0x00,0x26,0x40,0x23,0x06,0x01,0x01,0x00,0x01,0x4c,0x00,0x01,0x00,0x4a,0x05,0x01,0x01,0x49,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x11,0x11,0x02,0x07,0x18,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x01,0x01,0x7a,0x01,0x60,0xfe, 0xa0,0xfe,0x86,0x02,0xda,0xbe,0xfe,0x86,0xc0,0x01,0x7c,0x00,0x00,0x02,0xff,0xff,0xff,0xb1,0x04,0x2f,0x03,0x52,0x00,0x0f,0x00,0x2f,0x00,0x2e,0x40,0x2b,0x09,0x01,0x02,0x01,0x00,0x20,0x01,0x03,0x02,0x02,0x4c,0x00,0x05,0x00,0x00,0x01,0x05,0x00,0x67,0x00,0x01,0x04,0x01,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x03,0x11,0x03,0x4e, 0x35,0x26,0x36,0x26,0x26,0x14,0x06,0x07,0x1c,0x2b,0x01,0x11,0x34,0x26,0x27,0x21,0x22,0x06,0x07,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x13,0x11,0x14,0x06,0x07,0x21,0x14,0x1e,0x01,0x17,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x34,0x3e,0x01,0x35,0x21,0x22,0x26,0x37,0x11,0x34,0x36,0x33,0x21,0x32,0x16,0x03,0xe8,0x0a,0x08,0xfc,0x83, 0x07,0x0a,0x01,0x0c,0x06,0x03,0x7d,0x07,0x0c,0x46,0x34,0x25,0xfe,0xd1,0x12,0x10,0x01,0x14,0x0f,0xfe,0xe2,0x0f,0x14,0x01,0x12,0x12,0xfe,0xd0,0x24,0x36,0x01,0x34,0x25,0x03,0x7d,0x25,0x34,0x01,0x28,0x01,0xd1,0x07,0x0a,0x01,0x0c,0x06,0xfe,0x2f,0x07,0x0a,0x0a,0x01,0xd8,0xfd,0xa1,0x25,0x34,0x01,0x14,0x2e,0x22,0x07,0x0e,0x16, 0x16,0x0e,0x08,0x22,0x2c,0x15,0x36,0x24,0x02,0x5f,0x25,0x34,0x34,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xe1,0x02,0xf8,0x02,0xdb,0x00,0x21,0x00,0x31,0x00,0x2f,0x40,0x2c,0x11,0x06,0x02,0x00,0x03,0x01,0x4c,0x00,0x01,0x00,0x01,0x86,0x00,0x02,0x00,0x04,0x03,0x02,0x04,0x69,0x00,0x03,0x00,0x00,0x03,0x59,0x00,0x03,0x03,0x00, 0x61,0x00,0x00,0x03,0x00,0x51,0x15,0x2b,0x1d,0x25,0x22,0x05,0x07,0x1b,0x2b,0x01,0x0e,0x01,0x23,0x22,0x26,0x27,0x0f,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x3f,0x02,0x2e,0x01,0x35,0x34,0x37,0x3e,0x01,0x32,0x17,0x16,0x17,0x16,0x15,0x14,0x07,0x06,0x25,0x1e,0x01,0x33,0x32,0x3e,0x01,0x34,0x2e,0x01,0x22,0x0e,0x01,0x15,0x14,0x16, 0x02,0xa8,0x29,0x66,0x36,0x31,0x5d,0x28,0x33,0x82,0x15,0x18,0x1e,0x2d,0x0f,0x81,0x7e,0x20,0x22,0x27,0x25,0x80,0x95,0x40,0x3f,0x26,0x26,0x14,0x14,0xfe,0x99,0x19,0x40,0x21,0x2d,0x4f,0x2e,0x2f,0x4e,0x5b,0x4f,0x2f,0x1a,0x01,0x00,0x29,0x2a,0x22,0x20,0x7d,0x82,0x0f,0x2f,0x1e,0x1a,0x13,0x82,0x33,0x26,0x5e,0x32,0x4b,0x40,0x3f, 0x4b,0x27,0x25,0x3f,0x41,0x4a,0x38,0x32,0x34,0x24,0x18,0x1a,0x2e,0x4f,0x5d,0x4e,0x2e,0x2f,0x4e,0x2d,0x22,0x40,0x00,0x00,0x00,0x02,0xff,0xfd,0xff,0xb1,0x03,0x5f,0x03,0x0b,0x00,0x0c,0x00,0x19,0x00,0x28,0x40,0x25,0x04,0x01,0x00,0x00,0x03,0x61,0x00,0x03,0x03,0x13,0x4d,0x00,0x01,0x01,0x02,0x61,0x00,0x02,0x02,0x11,0x02,0x4e, 0x01,0x00,0x17,0x16,0x11,0x10,0x07,0x06,0x00,0x0c,0x01,0x0c,0x05,0x07,0x16,0x2b,0x01,0x22,0x0e,0x02,0x1e,0x01,0x32,0x3e,0x01,0x2e,0x02,0x01,0x14,0x0e,0x01,0x22,0x2e,0x02,0x3e,0x01,0x32,0x1e,0x01,0x01,0xad,0x53,0x8c,0x50,0x02,0x54,0x88,0xaa,0x86,0x56,0x04,0x4e,0x8e,0x01,0x5b,0x72,0xc6,0xe8,0xc8,0x6e,0x06,0x7a,0xbc,0xf4, 0xba,0x7e,0x02,0x8e,0x52,0x8c,0xa4,0x8c,0x52,0x52,0x8c,0xa4,0x8c,0x52,0xfe,0xd0,0x75,0xc4,0x74,0x74,0xc4,0xea,0xc4,0x74,0x74,0xc4,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0xb1,0x03,0x4d,0x02,0xff,0x00,0x06,0x00,0x14,0x00,0x19,0x00,0x24,0x00,0xe3,0x40,0x17,0x1e,0x01,0x02,0x05,0x1d,0x16,0x0e,0x07,0x04,0x03,0x02,0x19,0x03,0x02, 0x03,0x00,0x03,0x01,0x01,0x01,0x00,0x04,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x26,0x00,0x02,0x05,0x03,0x05,0x02,0x03,0x80,0x00,0x03,0x00,0x00,0x03,0x70,0x06,0x01,0x01,0x00,0x04,0x00,0x01,0x72,0x00,0x05,0x05,0x13,0x4d,0x00,0x00,0x00,0x04,0x60,0x00,0x04,0x04,0x11,0x04,0x4e,0x1b,0x4b,0xb0,0x12,0x50,0x58,0x40,0x27,0x00,0x02, 0x05,0x03,0x05,0x02,0x03,0x80,0x00,0x03,0x00,0x05,0x03,0x00,0x7e,0x06,0x01,0x01,0x00,0x04,0x00,0x01,0x72,0x00,0x05,0x05,0x13,0x4d,0x00,0x00,0x00,0x04,0x60,0x00,0x04,0x04,0x11,0x04,0x4e,0x1b,0x4b,0xb0,0x29,0x50,0x58,0x40,0x28,0x00,0x02,0x05,0x03,0x05,0x02,0x03,0x80,0x00,0x03,0x00,0x05,0x03,0x00,0x7e,0x06,0x01,0x01,0x00, 0x04,0x00,0x01,0x04,0x80,0x00,0x05,0x05,0x13,0x4d,0x00,0x00,0x00,0x04,0x60,0x00,0x04,0x04,0x11,0x04,0x4e,0x1b,0x40,0x23,0x00,0x05,0x02,0x05,0x85,0x00,0x02,0x03,0x02,0x85,0x00,0x03,0x00,0x03,0x85,0x06,0x01,0x01,0x00,0x04,0x00,0x01,0x04,0x80,0x00,0x00,0x00,0x04,0x60,0x00,0x04,0x04,0x11,0x04,0x4e,0x59,0x59,0x59,0x40,0x12, 0x00,0x00,0x21,0x20,0x18,0x17,0x10,0x0f,0x09,0x08,0x00,0x06,0x00,0x06,0x14,0x07,0x07,0x17,0x2b,0x17,0x37,0x27,0x07,0x15,0x33,0x15,0x01,0x34,0x23,0x22,0x07,0x01,0x06,0x15,0x14,0x33,0x32,0x37,0x01,0x36,0x27,0x17,0x01,0x23,0x35,0x01,0x14,0x0f,0x01,0x27,0x37,0x36,0x32,0x1f,0x01,0x16,0xcb,0x32,0x83,0x33,0x48,0x01,0x5f,0x0c, 0x05,0x04,0xfe,0xd1,0x04,0x0d,0x05,0x04,0x01,0x2f,0x03,0x1e,0xe8,0xfe,0x30,0xe8,0x03,0x4d,0x14,0x5d,0xe8,0x5d,0x14,0x3b,0x16,0x83,0x14,0x07,0x33,0x83,0x33,0x3c,0x47,0x02,0x06,0x0c,0x04,0xfe,0xd2,0x04,0x06,0x0c,0x04,0x01,0x2e,0x04,0x71,0xe8,0xfe,0x2f,0xe9,0x01,0x9a,0x1d,0x15,0x5d,0xe9,0x5c,0x15,0x15,0x83,0x16,0x00,0x00, 0x00,0x05,0xff,0xff,0xff,0xf9,0x03,0x59,0x02,0xc4,0x00,0x08,0x00,0x11,0x00,0x21,0x00,0x2b,0x00,0x41,0x00,0x8e,0x40,0x0f,0x13,0x01,0x01,0x04,0x09,0x00,0x02,0x00,0x01,0x1b,0x01,0x05,0x00,0x03,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x30,0x03,0x01,0x01,0x04,0x00,0x04,0x01,0x00,0x80,0x02,0x01,0x00,0x05,0x08,0x00,0x70,0x00,0x09, 0x00,0x07,0x06,0x09,0x07,0x67,0x00,0x06,0x00,0x04,0x01,0x06,0x04,0x67,0x00,0x05,0x08,0x08,0x05,0x58,0x00,0x05,0x05,0x08,0x60,0x00,0x08,0x05,0x08,0x50,0x1b,0x40,0x31,0x03,0x01,0x01,0x04,0x00,0x04,0x01,0x00,0x80,0x02,0x01,0x00,0x05,0x04,0x00,0x05,0x7e,0x00,0x09,0x00,0x07,0x06,0x09,0x07,0x67,0x00,0x06,0x00,0x04,0x01,0x06, 0x04,0x67,0x00,0x05,0x08,0x08,0x05,0x58,0x00,0x05,0x05,0x08,0x60,0x00,0x08,0x05,0x08,0x50,0x59,0x40,0x0e,0x3d,0x3a,0x37,0x23,0x13,0x26,0x25,0x13,0x14,0x13,0x12,0x0a,0x07,0x1f,0x2b,0x25,0x14,0x06,0x22,0x26,0x3e,0x01,0x1e,0x01,0x17,0x14,0x06,0x22,0x26,0x3e,0x01,0x1e,0x01,0x17,0x35,0x34,0x26,0x27,0x21,0x22,0x06,0x07,0x15, 0x14,0x16,0x17,0x21,0x32,0x36,0x01,0x21,0x03,0x2e,0x01,0x23,0x21,0x22,0x06,0x07,0x01,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x37,0x35,0x34,0x37,0x13,0x3e,0x01,0x17,0x21,0x32,0x16,0x17,0x13,0x16,0x02,0x44,0x1a,0x24,0x1c,0x02,0x18,0x28,0x16,0x91,0x1a,0x24,0x1c,0x02,0x18,0x28,0x16,0x41,0x0c,0x06,0xfd,0x59,0x07,0x0a,0x01,0x0c, 0x06,0x02,0xa7,0x07,0x0a,0xfd,0x52,0x02,0x93,0x58,0x02,0x0e,0x07,0xfe,0x4b,0x07,0x0e,0x02,0x02,0x9e,0x34,0x25,0xfd,0x59,0x24,0x36,0x01,0x09,0x6e,0x09,0x34,0x1e,0x01,0xb5,0x1f,0x32,0x0a,0x6e,0x09,0xab,0x12,0x1a,0x1a,0x24,0x1c,0x02,0x18,0x14,0x12,0x1a,0x1a,0x24,0x1c,0x02,0x18,0x6d,0xb3,0x07,0x0a,0x01,0x0c,0x06,0xb3,0x07, 0x0a,0x01,0x0c,0x01,0x12,0x01,0x0d,0x07,0x0a,0x0a,0x07,0xfe,0x9a,0xb3,0x25,0x34,0x34,0x25,0xb3,0x0e,0x1c,0x01,0x52,0x1d,0x26,0x01,0x24,0x1e,0xfe,0xae,0x1c,0x00,0x00,0x01,0x00,0x00,0xff,0xe2,0x02,0xda,0x02,0xda,0x00,0x06,0x00,0x26,0x40,0x23,0x01,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0x4a,0x02,0x01,0x00,0x49,0x00,0x01, 0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x11,0x13,0x02,0x07,0x18,0x2b,0x09,0x02,0x35,0x21,0x11,0x21,0x01,0x5e,0x01,0x7c,0xfe,0x84,0xfe,0xa2,0x01,0x5e,0x02,0xda,0xfe,0x84,0xfe,0x84,0xc0,0x01,0x7a,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0xab,0x03,0x6b,0x03,0x20,0x00,0x0f,0x00,0x13,0x00,0x1f, 0x00,0x38,0x40,0x35,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x0b,0x03,0x02,0x01,0x4c,0x00,0x02,0x02,0x00,0x5f,0x04,0x01,0x00,0x00,0x10,0x4d,0x00,0x03,0x03,0x01,0x5f,0x00,0x01,0x01,0x11,0x01,0x4e,0x01,0x00,0x13,0x12,0x11,0x10,0x09,0x06,0x00,0x0f,0x01,0x0e,0x05,0x07,0x16,0x2b,0x13,0x22,0x06,0x15,0x11,0x14, 0x16,0x33,0x21,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x05,0x21,0x11,0x21,0x01,0x07,0x17,0x07,0x17,0x37,0x17,0x37,0x27,0x37,0x27,0x07,0x87,0x0c,0x11,0x11,0x0c,0x02,0xc6,0x0c,0x11,0x11,0x0c,0xfd,0x58,0x02,0x8b,0xfd,0x75,0x01,0x87,0x2d,0x52,0x52,0x2d,0x53,0x52,0x2e,0x53,0x53,0x2e,0x52,0x03,0x1f,0x12,0x0c,0xfc,0xc8,0x0c,0x11, 0x11,0x0c,0x03,0x38,0x0c,0x12,0x3b,0xfd,0x02,0x02,0xcb,0x2e,0x52,0x53,0x2d,0x52,0x52,0x2d,0x53,0x52,0x2e,0x52,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x84,0x03,0x8f,0x03,0x33,0x00,0x02,0x00,0x10,0x00,0x3c,0x00,0x68,0x01,0x4d,0x40,0x0b,0x01,0x01,0x0a,0x02,0x62,0x36,0x02,0x07,0x06,0x02,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x36, 0x12,0x01,0x01,0x03,0x01,0x85,0x04,0x11,0x02,0x00,0x03,0x02,0x03,0x00,0x72,0x0e,0x05,0x02,0x02,0x0a,0x0a,0x02,0x59,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x69,0x10,0x01,0x09,0x0b,0x01,0x08,0x09,0x08,0x65,0x0f,0x01,0x0a,0x0a,0x03,0x5f,0x00,0x03,0x03,0x13,0x03,0x4e,0x1b,0x4b,0xb0,0x13,0x50,0x58,0x40,0x3c,0x12,0x01, 0x01,0x03,0x01,0x85,0x00,0x04,0x03,0x00,0x03,0x04,0x00,0x80,0x11,0x01,0x00,0x02,0x03,0x00,0x70,0x0e,0x05,0x02,0x02,0x0a,0x0a,0x02,0x59,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x69,0x10,0x01,0x09,0x0b,0x01,0x08,0x09,0x08,0x65,0x0f,0x01,0x0a,0x0a,0x03,0x5f,0x00,0x03,0x03,0x13,0x03,0x4e,0x1b,0x4b,0xb0,0x16,0x50,0x58, 0x40,0x3d,0x12,0x01,0x01,0x03,0x01,0x85,0x00,0x04,0x03,0x00,0x03,0x04,0x00,0x80,0x11,0x01,0x00,0x02,0x03,0x00,0x02,0x7e,0x0e,0x05,0x02,0x02,0x0a,0x0a,0x02,0x59,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x69,0x10,0x01,0x09,0x0b,0x01,0x08,0x09,0x08,0x65,0x0f,0x01,0x0a,0x0a,0x03,0x5f,0x00,0x03,0x03,0x13,0x03,0x4e,0x1b, 0x40,0x44,0x12,0x01,0x01,0x03,0x01,0x85,0x00,0x04,0x03,0x00,0x03,0x04,0x00,0x80,0x11,0x01,0x00,0x02,0x03,0x00,0x02,0x7e,0x00,0x03,0x04,0x0a,0x03,0x57,0x0e,0x05,0x02,0x02,0x0f,0x01,0x0a,0x06,0x02,0x0a,0x69,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x69,0x10,0x01,0x09,0x08,0x08,0x09,0x59,0x10,0x01,0x09,0x09,0x08,0x61, 0x0b,0x01,0x08,0x09,0x08,0x51,0x59,0x59,0x59,0x40,0x2d,0x04,0x03,0x00,0x00,0x68,0x66,0x5e,0x5c,0x5b,0x59,0x4d,0x4b,0x4a,0x48,0x3f,0x3d,0x3c,0x3a,0x32,0x30,0x2f,0x2d,0x21,0x1f,0x1e,0x1c,0x13,0x11,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x03,0x10,0x04,0x0f,0x00,0x02,0x00,0x02,0x13,0x07,0x16,0x2b,0x01,0x07,0x27,0x25,0x22,0x06,0x1d, 0x01,0x33,0x35,0x21,0x15,0x33,0x35,0x34,0x26,0x23,0x13,0x33,0x32,0x16,0x1d,0x01,0x14,0x16,0x17,0x16,0x17,0x16,0x3b,0x01,0x15,0x23,0x22,0x07,0x06,0x07,0x06,0x07,0x06,0x1d,0x01,0x14,0x0e,0x02,0x2b,0x01,0x35,0x33,0x32,0x3d,0x01,0x34,0x37,0x26,0x3d,0x01,0x34,0x2b,0x01,0x03,0x23,0x22,0x26,0x3d,0x01,0x34,0x27,0x26,0x27,0x2e, 0x01,0x2b,0x01,0x35,0x33,0x32,0x36,0x37,0x36,0x37,0x36,0x3d,0x01,0x34,0x37,0x3e,0x02,0x3b,0x01,0x15,0x23,0x22,0x1d,0x01,0x14,0x07,0x16,0x1d,0x01,0x14,0x3b,0x01,0x02,0x90,0x63,0x64,0xfe,0xcd,0x0d,0x13,0x3f,0x01,0x58,0x3f,0x12,0x0d,0x55,0x1b,0x47,0x45,0x07,0x0b,0x09,0x12,0x0e,0x1c,0x0f,0x0f,0x1a,0x12,0x0f,0x0c,0x08,0x05, 0x03,0x0f,0x22,0x34,0x27,0x1b,0x16,0x55,0x4d,0x4e,0x54,0x16,0xa8,0x1b,0x47,0x44,0x04,0x04,0x0b,0x09,0x23,0x18,0x10,0x10,0x1c,0x20,0x0a,0x08,0x05,0x04,0x07,0x07,0x23,0x33,0x27,0x1b,0x15,0x55,0x4e,0x4e,0x55,0x15,0x02,0xb1,0xac,0xac,0x82,0x12,0x0d,0xe7,0xc7,0x2e,0x4e,0x0d,0x12,0xfe,0xfa,0x42,0x44,0x54,0x14,0x1b,0x09,0x0a, 0x05,0x05,0x33,0x05,0x03,0x0a,0x08,0x0f,0x0d,0x14,0x80,0x1d,0x33,0x23,0x13,0x34,0x52,0x7f,0x5a,0x0a,0x09,0x5c,0x54,0x54,0xfd,0x8a,0x43,0x43,0x7e,0x0e,0x12,0x0e,0x0a,0x09,0x0b,0x33,0x08,0x09,0x08,0x0f,0x14,0x0d,0x57,0x21,0x16,0x19,0x24,0x12,0x33,0x53,0x55,0x59,0x0c,0x07,0x5d,0x7d,0x54,0x00,0x00,0x00,0x00,0x01,0x00,0x00, 0xff,0xf2,0x02,0xf8,0x02,0xcc,0x00,0x06,0x00,0x17,0x40,0x14,0x06,0x01,0x00,0x4a,0x02,0x01,0x00,0x01,0x00,0x85,0x00,0x01,0x01,0x76,0x11,0x11,0x10,0x03,0x07,0x19,0x2b,0x01,0x23,0x11,0x21,0x11,0x23,0x01,0x02,0xf8,0xc0,0xfe,0x88,0xc0,0x01,0x7c,0x01,0x50,0xfe,0xa2,0x01,0x5e,0x01,0x7c,0x00,0x01,0x00,0x00,0x00,0x00,0x03,0xa5, 0x02,0x98,0x00,0x15,0x00,0x1d,0x40,0x1a,0x0f,0x01,0x00,0x01,0x01,0x4c,0x00,0x02,0x01,0x02,0x85,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x14,0x17,0x14,0x03,0x07,0x19,0x2b,0x01,0x14,0x07,0x01,0x06,0x22,0x27,0x01,0x26,0x34,0x3f,0x01,0x36,0x32,0x1f,0x01,0x01,0x36,0x32,0x1f,0x01,0x16,0x03,0xa5,0x10,0xfe,0x20,0x10,0x2c, 0x10,0xfe,0xea,0x0f,0x0f,0x4c,0x10,0x2c,0x10,0xa4,0x01,0x6e,0x10,0x2c,0x10,0x4c,0x10,0x02,0x16,0x16,0x10,0xfe,0x20,0x0f,0x0f,0x01,0x16,0x10,0x2c,0x10,0x4c,0x10,0x10,0xa5,0x01,0x6f,0x10,0x10,0x4c,0x0f,0x00,0x03,0xff,0xf5,0xff,0xb1,0x03,0xf3,0x03,0x52,0x00,0x0f,0x00,0x21,0x00,0x33,0x00,0x33,0x40,0x30,0x1b,0x11,0x02,0x03, 0x02,0x09,0x01,0x02,0x01,0x00,0x02,0x4c,0x00,0x05,0x00,0x02,0x03,0x05,0x02,0x67,0x00,0x03,0x00,0x00,0x01,0x03,0x00,0x67,0x00,0x01,0x01,0x04,0x5f,0x00,0x04,0x04,0x11,0x04,0x4e,0x17,0x38,0x27,0x27,0x26,0x23,0x06,0x07,0x1c,0x2b,0x25,0x35,0x34,0x26,0x2b,0x01,0x22,0x06,0x1d,0x01,0x14,0x16,0x17,0x33,0x32,0x36,0x27,0x13,0x34, 0x27,0x26,0x2b,0x01,0x22,0x07,0x06,0x15,0x17,0x14,0x16,0x37,0x33,0x32,0x36,0x03,0x01,0x16,0x07,0x0e,0x01,0x07,0x21,0x22,0x26,0x27,0x26,0x37,0x01,0x3e,0x01,0x32,0x16,0x02,0x3b,0x0a,0x07,0x6c,0x07,0x0a,0x0a,0x07,0x6c,0x07,0x0a,0x01,0x0a,0x05,0x07,0x07,0x7a,0x06,0x08,0x05,0x09,0x0c,0x07,0x67,0x08,0x0c,0x08,0x01,0xac,0x14, 0x15,0x09,0x22,0x12,0xfc,0xa6,0x12,0x22,0x09,0x15,0x14,0x01,0xad,0x09,0x22,0x26,0x22,0x53,0x6a,0x08,0x0a,0x0a,0x08,0x6a,0x08,0x0a,0x01,0x0c,0xd7,0x01,0x01,0x06,0x04,0x06,0x06,0x04,0x08,0xff,0x05,0x08,0x01,0x06,0x02,0x10,0xfc,0xee,0x23,0x23,0x11,0x12,0x01,0x14,0x10,0x23,0x23,0x03,0x12,0x11,0x14,0x14,0x00,0x04,0x00,0x00, 0xff,0x79,0x03,0xd1,0x03,0x3c,0x00,0x0f,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x36,0x40,0x33,0x07,0x01,0x05,0x03,0x01,0x01,0x05,0x01,0x63,0x06,0x01,0x04,0x04,0x00,0x5f,0x09,0x02,0x08,0x03,0x00,0x00,0x12,0x04,0x4e,0x11,0x10,0x01,0x00,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x19,0x16,0x10,0x1f,0x11,0x1e,0x09,0x06,0x00,0x0f, 0x01,0x0e,0x0a,0x07,0x16,0x2b,0x13,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x33,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x05,0x21,0x11,0x21,0x01,0x21,0x11,0x21,0x38,0x0d,0x13,0x13,0x0d,0x01,0x7c,0x0d,0x12,0x12,0x0d,0x80,0x0d,0x12,0x12,0x0d,0x01,0x7d, 0x0d,0x12,0x12,0x0d,0xfc,0xa6,0x01,0x3e,0xfe,0xc2,0x01,0xfc,0x01,0x3e,0xfe,0xc2,0x03,0x3b,0x12,0x0d,0xfc,0x7d,0x0d,0x12,0x12,0x0d,0x03,0x83,0x0d,0x12,0x12,0x0d,0xfc,0x7d,0x0d,0x12,0x12,0x0d,0x03,0x83,0x0d,0x12,0x3e,0xfc,0xbb,0x03,0x45,0xfc,0xbb,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x7e,0x03,0xd6,0x03,0x37,0x00,0x0f, 0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x3d,0x40,0x3a,0x00,0x04,0x00,0x01,0x02,0x04,0x01,0x67,0x00,0x02,0x09,0x01,0x07,0x06,0x02,0x07,0x67,0x00,0x06,0x00,0x03,0x06,0x03,0x63,0x08,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x12,0x05,0x4e,0x24,0x24,0x20,0x20,0x24,0x27,0x24,0x27,0x26,0x25,0x20,0x23,0x20,0x23,0x14,0x35,0x35,0x35, 0x32,0x0a,0x07,0x1b,0x2b,0x01,0x34,0x26,0x23,0x21,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x15,0x34,0x26,0x23,0x21,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x03,0x11,0x21,0x11,0x01,0x11,0x21,0x11,0x03,0xd5,0x12,0x0d,0xfc,0x7d,0x0d,0x13,0x13,0x0d,0x03,0x83,0x0d,0x12,0x12,0x0d,0xfc,0x7d,0x0d, 0x13,0x13,0x0d,0x03,0x83,0x0d,0x12,0x3f,0xfc,0xbc,0x03,0x44,0xfc,0xbc,0x03,0x17,0x0d,0x12,0x12,0x0d,0xfe,0x84,0x0d,0x12,0x12,0x0d,0x80,0x0d,0x12,0x12,0x0d,0xfe,0x83,0x0d,0x12,0x12,0x0d,0x03,0x5a,0xfe,0xc2,0x01,0x3e,0xfe,0x04,0xfe,0xc1,0x01,0x3f,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x89,0x03,0xdc,0x03,0x38,0x00,0x02, 0x00,0x10,0x00,0x39,0x00,0x62,0x01,0x0d,0x40,0x0b,0x01,0x01,0x06,0x0a,0x5c,0x33,0x02,0x07,0x06,0x02,0x4c,0x4b,0xb0,0x1c,0x50,0x58,0x40,0x38,0x12,0x01,0x01,0x03,0x01,0x85,0x04,0x11,0x02,0x00,0x03,0x02,0x03,0x00,0x02,0x80,0x0e,0x05,0x02,0x02,0x0a,0x03,0x02,0x0a,0x7e,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x6a,0x10, 0x01,0x09,0x0b,0x01,0x08,0x09,0x08,0x65,0x0f,0x01,0x0a,0x0a,0x03,0x5f,0x00,0x03,0x03,0x13,0x0a,0x4e,0x1b,0x4b,0xb0,0x21,0x50,0x58,0x40,0x3f,0x12,0x01,0x01,0x03,0x01,0x85,0x04,0x11,0x02,0x00,0x03,0x02,0x03,0x00,0x02,0x80,0x0e,0x05,0x02,0x02,0x0a,0x03,0x02,0x0a,0x7e,0x00,0x03,0x0f,0x01,0x0a,0x06,0x03,0x0a,0x69,0x0d,0x01, 0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x6a,0x10,0x01,0x09,0x08,0x08,0x09,0x59,0x10,0x01,0x09,0x09,0x08,0x61,0x0b,0x01,0x08,0x09,0x08,0x51,0x1b,0x40,0x45,0x12,0x01,0x01,0x03,0x01,0x85,0x00,0x04,0x03,0x00,0x03,0x04,0x00,0x80,0x11,0x01,0x00,0x02,0x03,0x00,0x02,0x7e,0x0e,0x05,0x02,0x02,0x0a,0x03,0x02,0x0a,0x7e,0x00,0x03,0x0f, 0x01,0x0a,0x06,0x03,0x0a,0x69,0x0d,0x01,0x06,0x0c,0x01,0x07,0x09,0x06,0x07,0x6a,0x10,0x01,0x09,0x08,0x08,0x09,0x59,0x10,0x01,0x09,0x09,0x08,0x61,0x0b,0x01,0x08,0x09,0x08,0x51,0x59,0x59,0x40,0x2d,0x04,0x03,0x00,0x00,0x62,0x60,0x58,0x56,0x55,0x53,0x4a,0x48,0x47,0x45,0x3c,0x3a,0x39,0x37,0x2f,0x2d,0x2c,0x2a,0x1f,0x1d,0x1c, 0x1a,0x13,0x11,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x03,0x10,0x04,0x0f,0x00,0x02,0x00,0x02,0x13,0x07,0x16,0x2b,0x01,0x07,0x27,0x25,0x22,0x06,0x1d,0x01,0x33,0x35,0x21,0x15,0x33,0x35,0x34,0x26,0x23,0x01,0x33,0x32,0x16,0x1d,0x01,0x14,0x1e,0x02,0x3b,0x01,0x15,0x23,0x22,0x07,0x0e,0x02,0x1d,0x01,0x14,0x07,0x0e,0x02,0x2b,0x01,0x35, 0x33,0x32,0x3d,0x01,0x34,0x37,0x26,0x3d,0x01,0x34,0x2b,0x01,0x03,0x23,0x22,0x26,0x3d,0x01,0x34,0x27,0x26,0x27,0x2e,0x01,0x2b,0x01,0x35,0x33,0x32,0x3e,0x02,0x3d,0x01,0x34,0x3e,0x02,0x3b,0x01,0x15,0x23,0x22,0x1d,0x01,0x14,0x07,0x16,0x1d,0x01,0x14,0x3b,0x01,0x03,0xdc,0x63,0x64,0xfd,0x31,0x0d,0x13,0x3f,0x02,0xf4,0x3f,0x12, 0x0d,0xfe,0xb9,0x1b,0x47,0x45,0x07,0x16,0x22,0x18,0x10,0x10,0x16,0x16,0x10,0x14,0x07,0x08,0x06,0x21,0x38,0x25,0x1b,0x16,0x55,0x4d,0x4e,0x54,0x16,0xa8,0x1b,0x47,0x44,0x04,0x04,0x0b,0x09,0x23,0x18,0x10,0x10,0x1c,0x1f,0x15,0x07,0x0f,0x21,0x34,0x27,0x1b,0x15,0x55,0x4d,0x4e,0x54,0x15,0x02,0x85,0xad,0xad,0xb3,0x12,0x0d,0xe7, 0xc7,0x6d,0x8d,0x0d,0x12,0xfe,0xfa,0x42,0x44,0x54,0x14,0x1b,0x13,0x0a,0x33,0x04,0x04,0x12,0x1c,0x14,0x80,0x1d,0x1a,0x19,0x23,0x13,0x34,0x52,0x7f,0x5a,0x0a,0x09,0x5c,0x54,0x54,0xfd,0x8a,0x43,0x43,0x7e,0x0e,0x12,0x0e,0x0a,0x09,0x0b,0x33,0x08,0x13,0x1a,0x14,0x57,0x20,0x30,0x23,0x13,0x33,0x53,0x55,0x59,0x0c,0x07,0x5d,0x7d, 0x54,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0xf9,0x03,0x13,0x03,0x0b,0x00,0x23,0x00,0x33,0x00,0x43,0x00,0x44,0x40,0x41,0x18,0x01,0x03,0x04,0x13,0x01,0x02,0x00,0x03,0x06,0x01,0x01,0x00,0x03,0x4c,0x05,0x01,0x03,0x02,0x01,0x00,0x01,0x03,0x00,0x67,0x00,0x04,0x00,0x01,0x07,0x04,0x01,0x69,0x00,0x07,0x00,0x08,0x07,0x08,0x63, 0x00,0x06,0x06,0x09,0x5f,0x00,0x09,0x09,0x13,0x06,0x4e,0x42,0x3f,0x35,0x35,0x36,0x14,0x23,0x26,0x14,0x23,0x23,0x0a,0x07,0x1f,0x2b,0x01,0x15,0x14,0x06,0x2b,0x01,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x3d,0x01,0x23,0x22,0x26,0x3d,0x01,0x34,0x36,0x3b,0x01,0x35,0x34,0x36,0x3b,0x01,0x32,0x16,0x1d,0x01,0x33,0x32,0x16,0x13,0x11, 0x34,0x26,0x23,0x21,0x22,0x06,0x07,0x11,0x14,0x16,0x17,0x21,0x32,0x36,0x13,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x02,0x83,0x0a,0x08,0xc4,0x0a,0x08,0x24,0x08,0x0a,0xc4,0x08,0x0a,0x0a,0x08,0xc4,0x0a,0x08,0x24,0x08,0x0a,0xc4,0x08,0x0a,0x47,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x24, 0x01,0xd0,0x25,0x34,0x48,0x5e,0x43,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42,0x60,0x01,0x94,0x24,0x08,0x0a,0xc4,0x08,0x0a,0x0a,0x08,0xc4,0x0a,0x08,0x24,0x07,0x0a,0xc5,0x08,0x0a,0x0a,0x08,0xc5,0x0a,0xfe,0xff,0x01,0xd0,0x25,0x34,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x01,0xf4,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0, 0x42,0x5e,0x01,0x60,0x00,0x03,0x00,0x00,0xff,0xf9,0x03,0x13,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x2d,0x40,0x2a,0x09,0x01,0x02,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x03,0x00,0x04,0x03,0x04,0x63,0x00,0x02,0x02,0x05,0x5f,0x00,0x05,0x05,0x13,0x02,0x4e,0x35,0x35,0x35,0x36,0x26,0x23,0x06, 0x07,0x1c,0x2b,0x01,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x3d,0x01,0x34,0x36,0x33,0x21,0x32,0x16,0x13,0x11,0x34,0x26,0x23,0x21,0x22,0x06,0x07,0x11,0x14,0x16,0x17,0x21,0x32,0x36,0x13,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x02,0x83,0x0a,0x08,0xfe,0x30,0x08,0x0a,0x0a,0x08,0x01,0xd0,0x08, 0x0a,0x47,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x24,0x01,0xd0,0x25,0x34,0x48,0x5e,0x43,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42,0x60,0x01,0x94,0x24,0x08,0x0a,0x0a,0x08,0x24,0x07,0x0a,0x0a,0xfe,0xff,0x01,0xd0,0x25,0x34,0x34,0x25,0xfe,0x30,0x25,0x34,0x01,0x36,0x01,0xf4,0xfe,0x30,0x43,0x5e,0x5e,0x43,0x01,0xd0,0x42, 0x5e,0x01,0x60,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x01,0xd4,0x00,0x15,0x00,0x21,0xb1,0x06,0x64,0x44,0x40,0x16,0x07,0x01,0x00,0x02,0x01,0x4c,0x00,0x02,0x00,0x02,0x85,0x01,0x01,0x00,0x00,0x76,0x17,0x14,0x14,0x03,0x07,0x19,0x2b,0xb1,0x06,0x00,0x44,0x25,0x14,0x0f,0x01,0x06,0x22,0x2f,0x01,0x07,0x06,0x22,0x2f,0x01, 0x26,0x34,0x37,0x01,0x36,0x32,0x17,0x01,0x16,0x02,0x58,0x06,0x1c,0x05,0x0e,0x06,0xdc,0xdb,0x05,0x10,0x04,0x1c,0x06,0x06,0x01,0x04,0x05,0x0e,0x06,0x01,0x04,0x06,0xbd,0x07,0x05,0x1c,0x06,0x06,0xdb,0xdb,0x06,0x06,0x1c,0x05,0x0e,0x06,0x01,0x04,0x06,0x06,0xfe,0xfc,0x05,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0xff,0x89,0x03,0x42, 0x03,0x33,0x00,0x0f,0x00,0x19,0x00,0x33,0x00,0x3f,0x00,0x4b,0x00,0x57,0x00,0x8c,0x40,0x89,0x56,0x01,0x0c,0x0d,0x44,0x01,0x0a,0x0b,0x3e,0x01,0x08,0x09,0x03,0x4c,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x0d,0x03,0x05,0x0d,0x7e,0x00,0x0b,0x0c,0x0a,0x0c,0x0b,0x0a,0x80,0x00,0x0a,0x09,0x0c,0x0a,0x09,0x7e,0x00,0x09, 0x08,0x0c,0x09,0x08,0x7e,0x10,0x01,0x08,0x07,0x0c,0x08,0x07,0x7e,0x00,0x0d,0x11,0x01,0x0c,0x0b,0x0d,0x0c,0x67,0x00,0x07,0x00,0x01,0x07,0x01,0x64,0x06,0x04,0x0f,0x03,0x03,0x03,0x00,0x5f,0x0e,0x01,0x00,0x00,0x12,0x03,0x4e,0x4e,0x4c,0x36,0x34,0x10,0x10,0x01,0x00,0x54,0x52,0x4c,0x57,0x4e,0x57,0x48,0x45,0x42,0x40,0x3c,0x3a, 0x34,0x3f,0x36,0x3f,0x32,0x2f,0x2a,0x28,0x25,0x22,0x1f,0x1d,0x10,0x19,0x10,0x19,0x16,0x13,0x09,0x06,0x00,0x0f,0x01,0x0e,0x12,0x07,0x16,0x2b,0x01,0x32,0x16,0x17,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x37,0x17,0x15,0x14,0x16,0x3b,0x01,0x32,0x36,0x3d,0x01,0x13,0x11,0x34,0x26,0x07,0x23,0x15,0x14,0x06,0x07, 0x23,0x22,0x26,0x37,0x35,0x23,0x22,0x06,0x17,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x27,0x21,0x22,0x35,0x34,0x36,0x37,0x21,0x32,0x16,0x07,0x14,0x27,0x21,0x22,0x26,0x37,0x34,0x33,0x21,0x32,0x15,0x14,0x06,0x27,0x21,0x22,0x35,0x34,0x36,0x17,0x21,0x32,0x16,0x07,0x14,0x02,0xa6,0x41,0x5a,0x01,0x5c,0x40,0xfd,0xf6,0x41,0x5a,0x01, 0x5c,0x40,0x68,0x20,0x15,0xd0,0x16,0x1e,0x9c,0x1e,0x15,0x35,0x3c,0x2c,0xd0,0x2b,0x3e,0x01,0x35,0x15,0x20,0x01,0x1e,0x16,0x02,0x0a,0x15,0x1e,0x68,0xfe,0x60,0x1a,0x0e,0x0c,0x01,0xa0,0x0b,0x10,0x01,0x1a,0xfe,0x60,0x0b,0x10,0x01,0x1a,0x01,0xa0,0x1a,0x0e,0x0c,0xfe,0x60,0x1a,0x0e,0x0c,0x01,0xa0,0x0b,0x10,0x01,0x03,0x33,0x5c, 0x40,0xfd,0x8f,0x41,0x5c,0x5c,0x41,0x02,0x71,0x41,0x5a,0x01,0x68,0x34,0x15,0x20,0x20,0x15,0x34,0xfd,0x5b,0x02,0x71,0x15,0x20,0x01,0x34,0x2b,0x3c,0x01,0x3e,0x2a,0x34,0x1e,0x16,0xfd,0x8f,0x15,0x20,0x20,0x49,0x19,0x0c,0x0e,0x01,0x10,0x0b,0x19,0x9d,0x0e,0x0c,0x19,0x19,0x0b,0x10,0x9d,0x19,0x0b,0x10,0x01,0x0e,0x0c,0x19,0x00, 0x00,0x03,0x00,0x00,0xff,0xf9,0x04,0x29,0x03,0x0b,0x00,0x11,0x00,0x27,0x00,0x45,0x00,0x4b,0x40,0x48,0x24,0x01,0x01,0x00,0x01,0x4c,0x00,0x07,0x04,0x03,0x04,0x07,0x03,0x80,0x00,0x03,0x02,0x04,0x03,0x02,0x7e,0x08,0x09,0x02,0x02,0x00,0x00,0x01,0x02,0x00,0x68,0x00,0x01,0x00,0x05,0x01,0x05,0x63,0x00,0x04,0x04,0x06,0x5f,0x00, 0x06,0x06,0x13,0x04,0x4e,0x13,0x12,0x42,0x40,0x3d,0x3b,0x38,0x35,0x30,0x2d,0x21,0x1e,0x19,0x16,0x12,0x27,0x13,0x27,0x36,0x31,0x0a,0x07,0x18,0x2b,0x01,0x34,0x23,0x21,0x22,0x06,0x0f,0x01,0x06,0x15,0x14,0x33,0x21,0x32,0x36,0x3f,0x01,0x36,0x25,0x21,0x35,0x34,0x26,0x07,0x21,0x22,0x26,0x27,0x35,0x34,0x26,0x07,0x23,0x22,0x06, 0x15,0x11,0x37,0x3e,0x01,0x05,0x14,0x0f,0x01,0x0e,0x01,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x1d,0x01,0x21,0x32,0x16,0x17,0x15,0x33,0x32,0x16,0x17,0x16,0x03,0xe2,0x1e,0xfd,0xa1,0x16,0x34,0x0d,0xa4,0x0b,0x1e,0x02,0x5f,0x17,0x32,0x0f,0xa4,0x0a,0xfd,0x83,0x01,0xad,0x20,0x16,0xfe,0xbf,0x17,0x1e,0x01, 0x1e,0x17,0xb3,0x16,0x20,0x8f,0x19,0x50,0x02,0xea,0x19,0xa5,0x18,0x52,0x25,0xfd,0xa1,0x33,0x4a,0x4a,0x33,0xb3,0x33,0x4a,0x01,0x2f,0x34,0x48,0x01,0x6b,0x1e,0x34,0x0b,0x08,0x01,0x4b,0x13,0x18,0x11,0xcb,0x0d,0x09,0x14,0x1a,0x10,0xcb,0x0c,0x64,0x5a,0x16,0x20,0x01,0x20,0x16,0x24,0x16,0x20,0x01,0x1e,0x17,0xfe,0x24,0xaf,0x1e, 0x26,0x5a,0x23,0x20,0xcb,0x1e,0x26,0x4a,0x33,0x02,0x18,0x33,0x4a,0x4a,0x33,0x12,0x4a,0x33,0x5a,0x1a,0x1b,0x11,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xf9,0x03,0xa1,0x03,0x0b,0x00,0x17,0x00,0x2c,0x00,0x26,0x40,0x23,0x00,0x05,0x00,0x00,0x02,0x05,0x00,0x67,0x00,0x02,0x00,0x03,0x02,0x03,0x63,0x00,0x01,0x01,0x04,0x5f,0x00,0x04, 0x04,0x13,0x01,0x4e,0x23,0x35,0x35,0x35,0x35,0x33,0x06,0x07,0x1c,0x2b,0x25,0x11,0x34,0x26,0x07,0x21,0x22,0x26,0x27,0x35,0x34,0x26,0x07,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x13,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x1d,0x01,0x21,0x32,0x16,0x03,0x59,0x1e,0x17,0xfe, 0x77,0x17,0x1e,0x01,0x1e,0x17,0xb3,0x16,0x20,0x20,0x16,0x02,0xa7,0x16,0x20,0x47,0x4a,0x33,0xfd,0x59,0x33,0x4a,0x4a,0x33,0xb3,0x33,0x4a,0x01,0x77,0x33,0x4a,0x76,0x01,0x89,0x16,0x20,0x01,0x20,0x16,0x24,0x16,0x20,0x01,0x1e,0x17,0xfd,0xe8,0x16,0x20,0x20,0x01,0x9f,0xfe,0x77,0x33,0x4a,0x4a,0x33,0x02,0x18,0x33,0x4a,0x4a,0x33, 0x12,0x4a,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0xb8,0x03,0x94,0x03,0x1f,0x00,0x02,0x00,0x10,0x00,0x39,0x00,0x66,0x01,0x0d,0x40,0x0b,0x60,0x33,0x02,0x07,0x06,0x01,0x01,0x02,0x07,0x02,0x4c,0x4b,0xb0,0x13,0x50,0x58,0x40,0x38,0x00,0x02,0x07,0x09,0x07,0x02,0x09,0x80,0x00,0x03,0x01,0x03,0x86,0x0d,0x01,0x06,0x0c,0x01,0x07,0x02, 0x06,0x07,0x69,0x0b,0x08,0x12,0x04,0x11,0x05,0x00,0x01,0x09,0x00,0x59,0x10,0x01,0x09,0x00,0x01,0x03,0x09,0x01,0x67,0x0f,0x01,0x0a,0x0a,0x05,0x61,0x0e,0x01,0x05,0x05,0x10,0x0a,0x4e,0x1b,0x4b,0xb0,0x1b,0x50,0x58,0x40,0x3f,0x00,0x02,0x07,0x09,0x07,0x02,0x09,0x80,0x12,0x04,0x11,0x03,0x00,0x08,0x01,0x08,0x00,0x01,0x80,0x00, 0x03,0x01,0x03,0x86,0x0d,0x01,0x06,0x0c,0x01,0x07,0x02,0x06,0x07,0x69,0x0b,0x01,0x08,0x00,0x09,0x08,0x59,0x10,0x01,0x09,0x00,0x01,0x03,0x09,0x01,0x67,0x0f,0x01,0x0a,0x0a,0x05,0x61,0x0e,0x01,0x05,0x05,0x10,0x0a,0x4e,0x1b,0x40,0x45,0x00,0x02,0x07,0x09,0x07,0x02,0x09,0x80,0x11,0x01,0x00,0x08,0x04,0x08,0x00,0x04,0x80,0x12, 0x01,0x04,0x01,0x08,0x04,0x01,0x7e,0x00,0x03,0x01,0x03,0x86,0x0d,0x01,0x06,0x0c,0x01,0x07,0x02,0x06,0x07,0x69,0x0b,0x01,0x08,0x00,0x09,0x08,0x59,0x10,0x01,0x09,0x00,0x01,0x03,0x09,0x01,0x67,0x0f,0x01,0x0a,0x0a,0x05,0x61,0x0e,0x01,0x05,0x05,0x10,0x0a,0x4e,0x59,0x59,0x40,0x2d,0x03,0x03,0x00,0x00,0x66,0x64,0x5c,0x5a,0x59, 0x57,0x4a,0x48,0x47,0x45,0x3c,0x3a,0x39,0x37,0x2f,0x2d,0x2c,0x2a,0x20,0x1e,0x1d,0x1b,0x13,0x11,0x03,0x10,0x03,0x10,0x0d,0x0a,0x07,0x06,0x05,0x04,0x00,0x02,0x00,0x02,0x13,0x07,0x16,0x2b,0x25,0x37,0x17,0x07,0x15,0x21,0x35,0x23,0x15,0x14,0x16,0x33,0x21,0x32,0x36,0x3d,0x01,0x01,0x33,0x32,0x16,0x1d,0x01,0x14,0x17,0x1e,0x02, 0x3b,0x01,0x15,0x23,0x22,0x0e,0x02,0x1d,0x01,0x14,0x07,0x0e,0x02,0x2b,0x01,0x35,0x33,0x32,0x3d,0x01,0x34,0x37,0x26,0x3d,0x01,0x34,0x2b,0x01,0x03,0x23,0x22,0x26,0x3d,0x01,0x34,0x27,0x26,0x27,0x2e,0x01,0x2b,0x01,0x35,0x33,0x32,0x3e,0x01,0x37,0x36,0x3d,0x01,0x34,0x37,0x36,0x37,0x36,0x37,0x36,0x3b,0x01,0x15,0x23,0x22,0x1d, 0x01,0x14,0x07,0x16,0x1d,0x01,0x14,0x3b,0x01,0x02,0xcd,0x64,0x63,0x82,0xfe,0xa7,0x3e,0x12,0x0d,0x01,0x97,0x0d,0x13,0xfe,0xa0,0x1c,0x47,0x44,0x04,0x05,0x11,0x25,0x18,0x10,0x10,0x1c,0x20,0x14,0x07,0x07,0x07,0x22,0x35,0x26,0x1c,0x16,0x55,0x4d,0x4e,0x54,0x16,0xa7,0x1b,0x48,0x44,0x04,0x05,0x09,0x0a,0x23,0x18,0x0f,0x0f,0x1d, 0x20,0x13,0x03,0x04,0x07,0x08,0x10,0x10,0x1b,0x1b,0x27,0x1b,0x16,0x55,0x4d,0x4e,0x54,0x16,0x6a,0xac,0xac,0x09,0x6a,0xb3,0xd3,0x0d,0x12,0x12,0x0d,0x8a,0x02,0xbe,0x42,0x44,0x54,0x14,0x0c,0x10,0x10,0x0c,0x33,0x08,0x14,0x19,0x15,0x80,0x21,0x16,0x19,0x23,0x12,0x33,0x52,0x7f,0x59,0x0b,0x09,0x5c,0x54,0x54,0xfd,0x8b,0x42,0x43, 0x7e,0x14,0x0c,0x10,0x08,0x0b,0x09,0x33,0x09,0x12,0x0e,0x0c,0x15,0x56,0x1a,0x1e,0x18,0x12,0x10,0x0b,0x09,0x33,0x53,0x55,0x59,0x0c,0x07,0x5d,0x7d,0x54,0x00,0x00,0x00,0x03,0xff,0xfe,0x00,0x00,0x03,0xe8,0x02,0x60,0x00,0x20,0x00,0x24,0x00,0x28,0x00,0x36,0x40,0x33,0x00,0x00,0x08,0x06,0x07,0x03,0x04,0x03,0x00,0x04,0x67,0x05, 0x01,0x03,0x01,0x01,0x03,0x57,0x05,0x01,0x03,0x03,0x01,0x5f,0x02,0x01,0x01,0x03,0x01,0x4f,0x25,0x25,0x21,0x21,0x25,0x28,0x25,0x28,0x27,0x26,0x21,0x24,0x21,0x24,0x14,0x27,0x2a,0x18,0x09,0x07,0x1a,0x2b,0x11,0x26,0x37,0x25,0x36,0x17,0x16,0x0f,0x01,0x21,0x27,0x26,0x37,0x36,0x17,0x05,0x16,0x07,0x03,0x06,0x23,0x21,0x26,0x2f, 0x01,0x26,0x0f,0x01,0x06,0x23,0x21,0x26,0x27,0x37,0x17,0x21,0x37,0x33,0x17,0x21,0x37,0x02,0x0a,0x01,0x68,0x1d,0x0c,0x0b,0x19,0xe3,0x02,0x92,0xe4,0x19,0x0b,0x0e,0x1d,0x01,0x6a,0x0b,0x02,0x1b,0x08,0x19,0xfe,0xc7,0x19,0x06,0x31,0x27,0x35,0x32,0x06,0x1a,0xfe,0xc8,0x1b,0x04,0x27,0x13,0x01,0x04,0x2b,0xdd,0x29,0x01,0x03,0x14, 0x01,0x82,0x0d,0x0c,0xba,0x0b,0x1b,0x21,0x0c,0x68,0x68,0x10,0x1d,0x1b,0x0b,0xba,0x0c,0x0d,0xff,0x00,0x1e,0x02,0x18,0xdf,0x19,0x18,0xe0,0x1a,0x02,0x1c,0xe2,0xbd,0xbd,0xbd,0xbd,0x00,0x00,0x03,0x00,0x00,0xff,0x6a,0x03,0x59,0x03,0x52,0x00,0x13,0x00,0x1a,0x00,0x23,0x00,0x39,0x40,0x36,0x14,0x01,0x02,0x04,0x01,0x4c,0x00,0x01, 0x00,0x04,0x02,0x01,0x04,0x67,0x00,0x02,0x00,0x03,0x05,0x02,0x03,0x67,0x06,0x01,0x05,0x00,0x00,0x05,0x57,0x06,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x05,0x00,0x4f,0x1b,0x1b,0x1b,0x23,0x1b,0x23,0x13,0x26,0x14,0x35,0x36,0x07,0x07,0x1b,0x2b,0x01,0x1e,0x01,0x15,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x37,0x21, 0x32,0x16,0x17,0x07,0x15,0x33,0x26,0x2f,0x01,0x26,0x13,0x11,0x23,0x22,0x26,0x27,0x35,0x21,0x11,0x03,0x33,0x10,0x16,0x1e,0x17,0xfd,0x12,0x17,0x1e,0x01,0x20,0x16,0x01,0xf4,0x16,0x36,0x0f,0x4a,0xd2,0x05,0x07,0xaf,0x06,0xc6,0xe8,0x17,0x1e,0x01,0xfe,0x53,0x02,0x7e,0x10,0x34,0x18,0xfd,0x7e,0x17,0x1e,0x01,0x20,0x16,0x03,0x7c, 0x17,0x1e,0x01,0x16,0x10,0x26,0xd2,0x11,0x06,0xaf,0x07,0xfc,0xb0,0x02,0x3c,0x20,0x15,0xe9,0xfc,0xa6,0x00,0x01,0x00,0x00,0xff,0xaa,0x03,0x11,0x03,0x13,0x00,0x0b,0x00,0x06,0xb3,0x07,0x02,0x01,0x32,0x2b,0x09,0x01,0x06,0x26,0x35,0x11,0x34,0x36,0x17,0x01,0x16,0x14,0x03,0x04,0xfd,0x1b,0x0d,0x12,0x12,0x0d,0x02,0xe5,0x0d,0x01, 0x4d,0xfe,0x64,0x07,0x0a,0x0f,0x03,0x36,0x0e,0x0c,0x08,0xfe,0x64,0x07,0x14,0x00,0x00,0x01,0xff,0xff,0xff,0xae,0x02,0x3c,0x03,0x0f,0x00,0x1d,0x00,0x1b,0x40,0x18,0x1b,0x1a,0x12,0x03,0x01,0x00,0x01,0x4c,0x00,0x00,0x00,0x13,0x4d,0x00,0x01,0x01,0x11,0x01,0x4e,0x35,0x3d,0x02,0x07,0x18,0x2b,0x17,0x06,0x26,0x37,0x11,0x34,0x36, 0x17,0x01,0x16,0x17,0x11,0x34,0x36,0x3b,0x01,0x32,0x16,0x07,0x11,0x14,0x06,0x2b,0x01,0x22,0x26,0x37,0x11,0x06,0x07,0x19,0x0a,0x10,0x01,0x0e,0x0b,0x01,0x8c,0x05,0x03,0x14,0x0f,0x48,0x0e,0x16,0x01,0x14,0x0f,0x48,0x0e,0x16,0x01,0x03,0x05,0x47,0x0b,0x06,0x0f,0x03,0x36,0x0e,0x08,0x0c,0xfe,0x74,0x05,0x05,0x01,0x7a,0x0e,0x16, 0x16,0x0e,0xfc,0xee,0x0e,0x16,0x16,0x0e,0x01,0x7b,0x06,0x05,0x00,0x03,0xff,0xfc,0xff,0x90,0x03,0x9a,0x03,0x2c,0x00,0x08,0x00,0x13,0x00,0x29,0x00,0xa7,0x40,0x0d,0x0c,0x01,0x03,0x02,0x23,0x22,0x18,0x17,0x04,0x05,0x07,0x02,0x4c,0x4b,0xb0,0x24,0x50,0x58,0x40,0x32,0x00,0x03,0x02,0x06,0x02,0x03,0x06,0x80,0x00,0x06,0x07,0x02, 0x06,0x07,0x7e,0x00,0x07,0x05,0x02,0x07,0x05,0x7e,0x00,0x05,0x04,0x02,0x05,0x04,0x7e,0x0a,0x01,0x04,0x00,0x01,0x04,0x01,0x66,0x09,0x01,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x12,0x02,0x4e,0x1b,0x40,0x39,0x00,0x03,0x02,0x06,0x02,0x03,0x06,0x80,0x00,0x06,0x07,0x02,0x06,0x07,0x7e,0x00,0x07,0x05,0x02,0x07,0x05,0x7e,0x00, 0x05,0x04,0x02,0x05,0x04,0x7e,0x08,0x01,0x00,0x09,0x01,0x02,0x03,0x00,0x02,0x69,0x0a,0x01,0x04,0x01,0x01,0x04,0x59,0x0a,0x01,0x04,0x04,0x01,0x62,0x00,0x01,0x04,0x01,0x52,0x59,0x40,0x1f,0x15,0x14,0x0a,0x09,0x01,0x00,0x26,0x24,0x20,0x1e,0x1b,0x19,0x14,0x29,0x15,0x29,0x10,0x0e,0x09,0x13,0x0a,0x13,0x05,0x04,0x00,0x08,0x01, 0x08,0x0b,0x07,0x16,0x2b,0x01,0x36,0x00,0x12,0x00,0x04,0x00,0x02,0x00,0x17,0x22,0x06,0x15,0x06,0x16,0x33,0x32,0x36,0x35,0x34,0x03,0x32,0x36,0x37,0x27,0x06,0x23,0x22,0x3f,0x01,0x36,0x23,0x22,0x06,0x07,0x17,0x36,0x33,0x32,0x0f,0x01,0x06,0x01,0xc6,0xbe,0x01,0x10,0x06,0xfe,0xf6,0xfe,0x84,0xfe,0xee,0x06,0x01,0x0c,0xf2,0x2a, 0x2e,0x02,0x22,0x20,0x26,0x2e,0xb4,0x1e,0x6c,0x34,0x12,0x30,0x18,0x0e,0x0a,0x2a,0x1a,0x30,0x1e,0x76,0x38,0x10,0x34,0x16,0x0c,0x0c,0x24,0x1a,0x03,0x2a,0x02,0xfe,0xf8,0xfe,0x84,0xfe,0xee,0x06,0x01,0x0a,0x01,0x7c,0x01,0x12,0x96,0x30,0x1a,0x1c,0x20,0x2c,0x20,0x3a,0xfd,0xae,0x34,0x34,0x18,0x24,0x26,0xa0,0x60,0x3a,0x2e,0x1a, 0x22,0x22,0x98,0x68,0x00,0x01,0x00,0x00,0xff,0xb1,0x03,0x59,0x03,0x0b,0x00,0x31,0x00,0x3b,0x40,0x38,0x2a,0x01,0x03,0x05,0x25,0x1d,0x02,0x04,0x03,0x02,0x4c,0x00,0x04,0x03,0x01,0x03,0x04,0x01,0x80,0x00,0x01,0x02,0x03,0x01,0x02,0x7e,0x00,0x03,0x03,0x05,0x61,0x00,0x05,0x05,0x13,0x4d,0x00,0x02,0x02,0x00,0x61,0x00,0x00,0x00, 0x11,0x00,0x4e,0x29,0x35,0x17,0x23,0x17,0x24,0x06,0x07,0x1c,0x2b,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x26,0x34,0x3f,0x01,0x36,0x16,0x17,0x1e,0x01,0x33,0x32,0x3e,0x03,0x2e,0x02,0x22,0x06,0x07,0x17,0x16,0x06,0x2b,0x01,0x22,0x26,0x27,0x35,0x34,0x36,0x1f,0x01,0x3e,0x01,0x33,0x32,0x1e,0x02,0x03,0x59,0x44,0x72,0xa0,0x56, 0x60,0xae,0x3c,0x04,0x05,0x4c,0x06,0x11,0x04,0x29,0x76,0x43,0x3a,0x68,0x50,0x2a,0x02,0x2e,0x4c,0x6c,0x6f,0x64,0x28,0x4d,0x11,0x13,0x17,0xfa,0x0f,0x14,0x01,0x2c,0x11,0x48,0x3c,0x9a,0x52,0x57,0x9e,0x74,0x42,0x01,0x5e,0x57,0x9e,0x74,0x44,0x52,0x49,0x06,0x0e,0x04,0x4d,0x05,0x01,0x06,0x35,0x3a,0x2e,0x4c,0x6a,0x74,0x6a,0x4c, 0x2e,0x28,0x25,0x4d,0x10,0x2d,0x16,0x0e,0xfa,0x18,0x13,0x12,0x48,0x39,0x3e,0x44,0x74,0x9e,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0xf9,0x02,0x83,0x03,0x53,0x00,0x23,0x00,0x3a,0x40,0x37,0x00,0x04,0x05,0x00,0x05,0x04,0x00,0x80,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x02,0x06,0x02,0x00,0x01,0x01,0x00,0x59,0x02,0x06,0x02,0x00, 0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x01,0x00,0x20,0x1f,0x1b,0x18,0x14,0x13,0x10,0x0e,0x09,0x06,0x00,0x23,0x01,0x23,0x07,0x07,0x16,0x2b,0x01,0x32,0x16,0x17,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x17,0x33,0x35,0x34,0x36,0x1e,0x01,0x07,0x14,0x06,0x2b,0x01,0x22,0x26,0x35,0x34,0x26,0x22,0x06,0x17,0x15, 0x02,0x4d,0x17,0x1e,0x01,0x20,0x16,0xfd,0xe9,0x17,0x1e,0x01,0x20,0x16,0x11,0x94,0xcc,0x96,0x02,0x14,0x0f,0x24,0x0e,0x16,0x54,0x76,0x54,0x01,0x01,0xa5,0x1e,0x17,0xfe,0xbe,0x16,0x1e,0x01,0x20,0x15,0x01,0x42,0x16,0x20,0x01,0xb3,0x67,0x94,0x02,0x90,0x69,0x0e,0x16,0x16,0x0e,0x3b,0x54,0x54,0x3b,0xb3,0x00,0x00,0x08,0x00,0x00, 0xff,0x9f,0x03,0x8f,0x03,0x1d,0x00,0x04,0x00,0x09,0x00,0x0e,0x00,0x13,0x00,0x1b,0x00,0x23,0x00,0x2b,0x00,0x33,0x00,0x41,0x40,0x3e,0x21,0x20,0x15,0x14,0x0e,0x01,0x06,0x00,0x4a,0x31,0x30,0x25,0x24,0x10,0x09,0x06,0x01,0x49,0x05,0x04,0x02,0x08,0x04,0x00,0x01,0x00,0x85,0x07,0x06,0x09,0x03,0x04,0x01,0x01,0x76,0x0f,0x0f,0x00, 0x00,0x2d,0x2c,0x29,0x28,0x1d,0x1c,0x19,0x18,0x0f,0x13,0x0f,0x13,0x0b,0x0a,0x06,0x05,0x00,0x04,0x00,0x04,0x0a,0x07,0x16,0x2b,0x01,0x35,0x1e,0x01,0x17,0x07,0x33,0x0e,0x01,0x07,0x03,0x23,0x3e,0x01,0x37,0x11,0x15,0x2e,0x01,0x27,0x01,0x35,0x1e,0x01,0x17,0x23,0x2e,0x01,0x01,0x23,0x3e,0x01,0x37,0x15,0x0e,0x01,0x01,0x15,0x2e, 0x01,0x27,0x33,0x1e,0x01,0x01,0x33,0x0e,0x01,0x07,0x35,0x3e,0x01,0x02,0x09,0x3c,0x56,0x10,0xa2,0xa2,0x10,0x56,0x3c,0x71,0xa2,0x10,0x56,0x3c,0x3c,0x56,0x10,0x01,0x13,0x98,0xda,0x14,0x71,0x12,0x9a,0xfe,0x11,0x71,0x13,0xda,0x99,0x6a,0x98,0x01,0x02,0x9a,0xd8,0x14,0x71,0x12,0x9a,0x01,0xef,0x71,0x15,0xd8,0x99,0x69,0x9a,0x01, 0x97,0xa2,0x10,0x58,0x3a,0x71,0x3b,0x58,0x0f,0x01,0x13,0x3b,0x56,0x11,0xfe,0xed,0xa2,0x10,0x56,0x3c,0x01,0x86,0x71,0x13,0xda,0x99,0x6b,0x98,0xfe,0xfd,0x98,0xda,0x14,0x71,0x12,0x98,0xfe,0x0f,0x72,0x13,0xdc,0x98,0x6b,0x98,0x01,0x03,0x99,0xda,0x14,0x72,0x12,0x98,0x00,0x04,0x00,0x00,0xff,0xb1,0x03,0x59,0x03,0x0b,0x00,0x03, 0x00,0x21,0x00,0x31,0x00,0x45,0x00,0x53,0x40,0x50,0x2b,0x2a,0x23,0x22,0x04,0x08,0x04,0x01,0x4c,0x0d,0x01,0x04,0x06,0x01,0x08,0x02,0x4b,0x00,0x08,0x04,0x03,0x04,0x08,0x03,0x80,0x00,0x03,0x06,0x04,0x03,0x06,0x7e,0x00,0x06,0x00,0x01,0x00,0x06,0x01,0x68,0x07,0x01,0x04,0x04,0x0a,0x5f,0x00,0x0a,0x0a,0x13,0x4d,0x05,0x02,0x02, 0x00,0x00,0x09,0x5f,0x00,0x09,0x09,0x11,0x09,0x4e,0x40,0x3d,0x38,0x35,0x17,0x26,0x33,0x11,0x13,0x3b,0x11,0x11,0x10,0x0b,0x07,0x1f,0x2b,0x17,0x21,0x35,0x21,0x05,0x33,0x11,0x34,0x26,0x2f,0x01,0x2e,0x01,0x07,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x35,0x23,0x11,0x33,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x07,0x03,0x35,0x34, 0x26,0x2b,0x01,0x22,0x06,0x17,0x15,0x14,0x16,0x37,0x33,0x32,0x36,0x05,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x33,0x21,0x32,0x16,0x1f,0x01,0x1e,0x01,0xd6,0x01,0xad,0xfe,0x53,0x01,0xf4,0x48,0x0c,0x05,0x9d,0x05,0x1c,0x08,0x1e,0x17,0xfe,0xbe,0x16,0x1e,0x01,0x48,0x48,0x20,0x15,0x01,0xd1,0x16,0x20,0x01,0xd6, 0x0a,0x08,0x6b,0x07,0x0c,0x01,0x0a,0x08,0x6b,0x07,0x0c,0x01,0x64,0x1e,0x17,0xfd,0x12,0x17,0x1e,0x01,0x20,0x16,0x02,0x05,0x17,0x36,0x0f,0x9c,0x10,0x16,0x07,0xd6,0xd6,0x01,0xf4,0x08,0x1a,0x07,0x9c,0x06,0x0c,0x01,0xe8,0x16,0x20,0x20,0x16,0xe8,0xfd,0x36,0xe8,0x16,0x20,0x20,0x16,0x01,0x1e,0xb2,0x08,0x0a,0x0a,0x08,0xb2,0x07, 0x0c,0x01,0x0a,0x0a,0xfd,0xfa,0x16,0x20,0x20,0x16,0x02,0xee,0x16,0x20,0x18,0x0e,0x9d,0x0f,0x36,0x00,0x00,0x02,0xff,0xff,0xff,0xb1,0x03,0xe8,0x03,0x0b,0x00,0x03,0x00,0x13,0x00,0x1f,0x40,0x1c,0x00,0x01,0x01,0x03,0x5f,0x00,0x03,0x03,0x13,0x4d,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x11,0x02,0x4e,0x35,0x34,0x11,0x10,0x04, 0x07,0x1a,0x2b,0x37,0x21,0x11,0x21,0x25,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x37,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x8f,0x02,0xca,0xfd,0x36,0x03,0x59,0x34,0x25,0xfc,0xca,0x24,0x36,0x01,0x34,0x25,0x03,0x36,0x25,0x34,0x40,0x01,0xad,0xc4,0xfd,0x5a,0x25,0x34,0x01,0x36,0x24,0x02,0xa6,0x25,0x34,0x01,0x36,0x00,0x03,0xff,0xfd, 0xff,0xb1,0x03,0x5f,0x03,0x0b,0x00,0x08,0x00,0x15,0x00,0x22,0x00,0x32,0x40,0x2f,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x69,0x06,0x01,0x02,0x02,0x05,0x61,0x00,0x05,0x05,0x13,0x4d,0x00,0x03,0x03,0x04,0x61,0x00,0x04,0x04,0x11,0x04,0x4e,0x0a,0x09,0x20,0x1f,0x1a,0x19,0x10,0x0f,0x09,0x15,0x0a,0x15,0x13,0x12,0x07,0x07,0x18,0x2b, 0x01,0x14,0x06,0x22,0x2e,0x01,0x36,0x32,0x16,0x27,0x22,0x0e,0x02,0x1e,0x01,0x32,0x3e,0x01,0x2e,0x02,0x01,0x14,0x0e,0x01,0x22,0x2e,0x02,0x3e,0x01,0x32,0x1e,0x01,0x02,0x3b,0x52,0x78,0x52,0x02,0x56,0x74,0x56,0x90,0x53,0x8c,0x50,0x02,0x54,0x88,0xaa,0x86,0x56,0x04,0x4e,0x8e,0x01,0x5b,0x72,0xc6,0xe8,0xc8,0x6e,0x06,0x7a,0xbc, 0xf4,0xba,0x7e,0x01,0x5e,0x3b,0x54,0x54,0x76,0x54,0x54,0xf5,0x52,0x8c,0xa4,0x8c,0x52,0x52,0x8c,0xa4,0x8c,0x52,0xfe,0xd0,0x75,0xc4,0x74,0x74,0xc4,0xea,0xc4,0x74,0x74,0xc4,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0x6a,0x02,0x83,0x03,0x0b,0x00,0x0b,0x00,0x2e,0x00,0x35,0x40,0x32,0x07,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x03,0x02, 0x03,0x86,0x09,0x05,0x02,0x01,0x04,0x01,0x02,0x03,0x01,0x02,0x67,0x08,0x06,0x02,0x00,0x00,0x07,0x5f,0x00,0x07,0x07,0x13,0x00,0x4e,0x2d,0x2c,0x13,0x33,0x11,0x14,0x22,0x33,0x15,0x15,0x13,0x0a,0x07,0x1f,0x2b,0x01,0x35,0x34,0x26,0x22,0x06,0x1d,0x01,0x14,0x16,0x32,0x36,0x05,0x14,0x06,0x27,0x23,0x03,0x0e,0x01,0x07,0x23,0x22, 0x27,0x03,0x23,0x22,0x26,0x27,0x34,0x36,0x33,0x11,0x22,0x2e,0x01,0x36,0x37,0x21,0x32,0x16,0x14,0x06,0x27,0x11,0x32,0x16,0x01,0x0c,0x0a,0x10,0x0a,0x0a,0x10,0x0a,0x01,0x77,0x16,0x0e,0xef,0x1d,0x01,0x0a,0x06,0x01,0x0f,0x02,0x2b,0xe1,0x0f,0x14,0x01,0x58,0x37,0x1d,0x2a,0x02,0x2e,0x1b,0x01,0x65,0x1d,0x2a,0x2a,0x1d,0x37,0x58, 0x01,0x70,0xfa,0x08,0x0a,0x0a,0x08,0xfa,0x08,0x0a,0x0a,0xbd,0x0e,0x16,0x01,0xfe,0xf2,0x07,0x08,0x01,0x0f,0x01,0x0f,0x14,0x0f,0x45,0x6e,0x01,0x1e,0x2a,0x3a,0x2a,0x01,0x2c,0x38,0x2c,0x01,0xfe,0xe2,0x6e,0x00,0x02,0x00,0x00,0xff,0xb1,0x03,0x5b,0x03,0x0b,0x00,0x24,0x00,0x47,0x00,0x4b,0x40,0x48,0x43,0x25,0x02,0x06,0x09,0x2f, 0x01,0x05,0x06,0x17,0x01,0x03,0x02,0x08,0x01,0x01,0x03,0x04,0x4c,0x00,0x09,0x07,0x01,0x05,0x02,0x09,0x05,0x67,0x04,0x01,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x06,0x06,0x08,0x61,0x00,0x08,0x08,0x13,0x4d,0x00,0x03,0x03,0x00,0x61,0x00,0x00,0x00,0x11,0x00,0x4e,0x46,0x45,0x26,0x25,0x25,0x36,0x25,0x26,0x35,0x14,0x24,0x0a, 0x07,0x1f,0x2b,0x01,0x14,0x15,0x0e,0x01,0x23,0x22,0x26,0x27,0x07,0x06,0x22,0x26,0x3d,0x01,0x34,0x36,0x3b,0x01,0x32,0x16,0x06,0x0f,0x01,0x1e,0x01,0x37,0x32,0x36,0x37,0x36,0x37,0x36,0x3b,0x01,0x32,0x16,0x13,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x36,0x3f,0x01,0x26,0x23,0x22,0x06,0x07,0x06,0x07,0x06,0x2b,0x01,0x22,0x26,0x37, 0x35,0x3e,0x01,0x33,0x32,0x16,0x17,0x37,0x36,0x32,0x16,0x03,0x4b,0x24,0xe4,0x99,0x51,0x98,0x3c,0x48,0x0b,0x1c,0x16,0x16,0x0e,0xfa,0x0e,0x16,0x02,0x09,0x4d,0x28,0x64,0x37,0x4a,0x82,0x27,0x06,0x18,0x04,0x0c,0x6b,0x08,0x0a,0x0e,0x14,0x10,0xfa,0x0e,0x16,0x02,0x09,0x4d,0x52,0x70,0x4b,0x82,0x27,0x06,0x17,0x05,0x0c,0x6f,0x07, 0x0c,0x01,0x24,0xe6,0x99,0x51,0x9a,0x3c,0x48,0x0b,0x1c,0x18,0x01,0x05,0x03,0x01,0x96,0xba,0x3e,0x39,0x48,0x0b,0x16,0x0e,0xfa,0x0e,0x16,0x16,0x1c,0x0b,0x4d,0x24,0x2a,0x01,0x4a,0x3e,0x0a,0x38,0x0d,0x0c,0x01,0xb8,0xfa,0x0e,0x16,0x16,0x1c,0x0b,0x4d,0x4d,0x4a,0x3e,0x0a,0x38,0x0d,0x0c,0x06,0x04,0x96,0xba,0x3e,0x39,0x48,0x0b, 0x16,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0xb1,0x03,0x5a,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x20,0x40,0x1d,0x18,0x10,0x08,0x00,0x04,0x00,0x01,0x01,0x4c,0x03,0x01,0x01,0x01,0x13,0x4d,0x02,0x01,0x00,0x00,0x11,0x00,0x4e,0x35,0x35,0x35,0x33,0x04,0x07,0x1a,0x2b,0x01,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x34,0x36, 0x33,0x21,0x32,0x16,0x05,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x34,0x36,0x33,0x21,0x32,0x16,0x03,0x59,0x14,0x10,0xfe,0xe3,0x0f,0x14,0x01,0x16,0x0e,0x01,0x1d,0x0f,0x16,0xfe,0x0b,0x14,0x10,0xfe,0xe3,0x0f,0x14,0x01,0x16,0x0e,0x01,0x1d,0x0f,0x16,0x02,0xe7,0xfc,0xee,0x0e,0x16,0x16,0x0e,0x03,0x12,0x0e,0x16,0x16,0x0e, 0xfc,0xee,0x0e,0x16,0x16,0x0e,0x03,0x12,0x0e,0x16,0x16,0x00,0x00,0x01,0x00,0x00,0xff,0xb1,0x03,0x5a,0x03,0x0b,0x00,0x0f,0x00,0x1a,0x40,0x17,0x08,0x00,0x02,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0x13,0x4d,0x00,0x00,0x00,0x11,0x00,0x4e,0x35,0x33,0x02,0x07,0x18,0x2b,0x01,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x27,0x11,0x34,0x36, 0x33,0x21,0x32,0x16,0x03,0x59,0x14,0x10,0xfc,0xef,0x0f,0x14,0x01,0x16,0x0e,0x03,0x11,0x0f,0x16,0x02,0xe7,0xfc,0xee,0x0e,0x16,0x16,0x0e,0x03,0x12,0x0e,0x16,0x16,0x00,0x01,0xff,0xfe,0xff,0xb1,0x03,0x59,0x03,0x0b,0x00,0x30,0x00,0x3a,0x40,0x37,0x2d,0x01,0x01,0x05,0x09,0x01,0x00,0x01,0x02,0x4c,0x00,0x00,0x01,0x03,0x01,0x00, 0x03,0x80,0x00,0x03,0x02,0x01,0x03,0x02,0x7e,0x00,0x01,0x01,0x05,0x61,0x00,0x05,0x05,0x13,0x4d,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x11,0x04,0x4e,0x27,0x27,0x13,0x27,0x24,0x33,0x06,0x07,0x1c,0x2b,0x01,0x15,0x14,0x06,0x2b,0x01,0x22,0x26,0x3f,0x01,0x26,0x23,0x22,0x0e,0x02,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x3e,0x01, 0x1f,0x01,0x1e,0x01,0x07,0x0e,0x01,0x07,0x22,0x2e,0x02,0x3e,0x03,0x33,0x32,0x16,0x17,0x37,0x36,0x16,0x03,0x59,0x14,0x10,0xfa,0x17,0x13,0x11,0x4d,0x52,0x70,0x3a,0x6a,0x4c,0x2e,0x2e,0x4c,0x6a,0x3a,0x42,0x76,0x29,0x04,0x11,0x06,0x4c,0x05,0x02,0x06,0x3c,0xae,0x5f,0x57,0xa0,0x70,0x48,0x04,0x40,0x78,0x98,0x5b,0x52,0x98,0x3d, 0x48,0x11,0x2c,0x02,0xc3,0xfa,0x0e,0x16,0x2d,0x10,0x4d,0x4d,0x2e,0x4c,0x6a,0x74,0x6a,0x4c,0x2e,0x3a,0x35,0x06,0x01,0x05,0x4d,0x04,0x0e,0x06,0x4a,0x50,0x01,0x44,0x74,0x9e,0xae,0x9e,0x74,0x44,0x3e,0x39,0x48,0x12,0x13,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x01,0xe6,0x00,0x15,0x00,0x19,0x40,0x16,0x0f,0x01,0x00,0x01, 0x01,0x4c,0x02,0x01,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x14,0x17,0x14,0x03,0x07,0x19,0x2b,0x01,0x14,0x07,0x01,0x06,0x22,0x27,0x01,0x26,0x34,0x3f,0x01,0x36,0x32,0x1f,0x01,0x37,0x36,0x32,0x1f,0x01,0x16,0x02,0x58,0x06,0xfe,0xfc,0x05,0x10,0x04,0xfe,0xfc,0x06,0x06,0x1c,0x05,0x0e,0x06,0xdb,0xdc,0x05,0x10,0x04,0x1c,0x06, 0x01,0xb7,0x07,0x05,0xfe,0xfb,0x05,0x05,0x01,0x05,0x05,0x0e,0x06,0x1c,0x06,0x06,0xdb,0xdb,0x06,0x06,0x1c,0x05,0x00,0x00,0x00,0x03,0xff,0xfd,0xff,0xb1,0x03,0x59,0x03,0x0b,0x00,0x0c,0x00,0x1c,0x00,0x2e,0x00,0x41,0x40,0x3e,0x28,0x1e,0x02,0x05,0x04,0x16,0x15,0x0e,0x03,0x03,0x02,0x02,0x4c,0x00,0x05,0x00,0x02,0x03,0x05,0x02, 0x67,0x00,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x13,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x11,0x01,0x4e,0x01,0x00,0x2c,0x2a,0x23,0x21,0x1a,0x18,0x12,0x10,0x07,0x06,0x00,0x0c,0x01,0x0c,0x07,0x07,0x16,0x2b,0x01,0x32,0x1e,0x01,0x14,0x0e,0x01,0x22,0x2e,0x02,0x3e,0x01,0x13,0x35,0x34,0x26,0x2b,0x01,0x22,0x06,0x07, 0x15,0x14,0x16,0x17,0x33,0x32,0x36,0x27,0x13,0x34,0x27,0x26,0x2b,0x01,0x22,0x07,0x06,0x15,0x13,0x14,0x16,0x3b,0x01,0x32,0x36,0x01,0xad,0x74,0xc6,0x72,0x72,0xc6,0xe8,0xc8,0x6e,0x06,0x7a,0xbc,0xc1,0x0a,0x07,0x6b,0x08,0x0a,0x01,0x0c,0x07,0x6b,0x07,0x0a,0x01,0x0a,0x06,0x05,0x08,0x7b,0x08,0x05,0x06,0x0a,0x0a,0x09,0x67,0x08, 0x0a,0x03,0x0b,0x74,0xc4,0xea,0xc4,0x74,0x74,0xc4,0xea,0xc4,0x74,0xfd,0x48,0x6a,0x08,0x0a,0x0a,0x08,0x6a,0x08,0x0a,0x01,0x0c,0xc7,0x01,0x5a,0x07,0x03,0x05,0x05,0x03,0x07,0xfe,0xa6,0x06,0x08,0x08,0x00,0x00,0x01,0x00,0x00,0xff,0xef,0x02,0xd4,0x02,0x86,0x00,0x24,0x00,0x26,0x40,0x23,0x22,0x19,0x10,0x07,0x04,0x00,0x02,0x01, 0x4c,0x03,0x01,0x02,0x00,0x00,0x02,0x59,0x03,0x01,0x02,0x02,0x00,0x61,0x01,0x01,0x00,0x02,0x00,0x51,0x14,0x1c,0x14,0x14,0x04,0x07,0x1a,0x2b,0x25,0x14,0x0f,0x01,0x06,0x22,0x2f,0x01,0x07,0x06,0x22,0x2f,0x01,0x26,0x34,0x3f,0x01,0x27,0x26,0x34,0x3f,0x01,0x36,0x32,0x1f,0x01,0x37,0x36,0x32,0x1f,0x01,0x16,0x14,0x0f,0x01,0x17, 0x16,0x02,0xd4,0x0f,0x4c,0x10,0x2c,0x10,0xa4,0xa4,0x10,0x2c,0x10,0x4c,0x10,0x10,0xa4,0xa4,0x10,0x10,0x4c,0x10,0x2c,0x10,0xa4,0xa4,0x10,0x2c,0x10,0x4c,0x0f,0x0f,0xa4,0xa4,0x0f,0x70,0x16,0x10,0x4c,0x0f,0x0f,0xa5,0xa5,0x0f,0x0f,0x4c,0x10,0x2c,0x10,0xa4,0xa4,0x10,0x2c,0x10,0x4c,0x10,0x10,0xa4,0xa4,0x10,0x10,0x4c,0x0f,0x2e, 0x0f,0xa4,0xa4,0x0f,0x00,0x03,0x00,0x00,0xff,0xb1,0x03,0xc5,0x03,0x0b,0x00,0x0c,0x00,0x1c,0x00,0x2c,0x00,0x34,0x40,0x31,0x25,0x1d,0x02,0x04,0x05,0x00,0x01,0x01,0x00,0x02,0x4c,0x00,0x03,0x00,0x00,0x01,0x03,0x00,0x67,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x05,0x13,0x4d,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x11,0x02,0x4e, 0x35,0x35,0x35,0x35,0x24,0x32,0x06,0x07,0x1c,0x2b,0x01,0x34,0x26,0x07,0x23,0x22,0x0e,0x01,0x16,0x17,0x33,0x32,0x36,0x25,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x21,0x32,0x16,0x37,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x37,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x02,0x5f,0x14,0x10,0x8e,0x0f,0x14,0x02,0x18, 0x0d,0x8e,0x0f,0x16,0x01,0x41,0x16,0x0e,0xfc,0xee,0x0e,0x16,0x16,0x0e,0x03,0x12,0x0e,0x16,0x23,0x14,0x0f,0xfc,0xa6,0x0e,0x16,0x01,0x14,0x0f,0x03,0x5a,0x0e,0x16,0x01,0x82,0x0e,0x16,0x01,0x14,0x1e,0x14,0x01,0x16,0x79,0xfd,0xe8,0x0e,0x16,0x16,0x0e,0x02,0x18,0x0e,0x16,0x16,0xec,0x8f,0x0e,0x16,0x16,0x0e,0x8f,0x0e,0x16,0x16, 0x00,0x05,0x00,0x00,0xff,0x88,0x03,0xac,0x03,0x34,0x00,0x43,0x00,0x4c,0x00,0x55,0x00,0x5e,0x00,0x67,0x00,0x61,0x40,0x5e,0x3c,0x33,0x02,0x05,0x0a,0x1a,0x0f,0x02,0x01,0x05,0x2b,0x22,0x19,0x10,0x09,0x00,0x06,0x08,0x01,0x03,0x4c,0x07,0x01,0x05,0x03,0x01,0x01,0x08,0x05,0x01,0x67,0x00,0x0a,0x0f,0x0c,0x02,0x08,0x09,0x0a,0x08, 0x69,0x10,0x0e,0x0d,0x03,0x09,0x04,0x02,0x02,0x00,0x09,0x00,0x65,0x00,0x0b,0x0b,0x06,0x61,0x00,0x06,0x06,0x12,0x0b,0x4e,0x60,0x5f,0x64,0x63,0x5f,0x67,0x60,0x67,0x5d,0x5c,0x59,0x58,0x54,0x53,0x50,0x4f,0x4b,0x4a,0x15,0x36,0x16,0x37,0x18,0x36,0x16,0x36,0x14,0x11,0x07,0x1f,0x2b,0x25,0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34, 0x37,0x35,0x34,0x2b,0x01,0x22,0x27,0x15,0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34,0x37,0x35,0x06,0x2b,0x01,0x22,0x0e,0x01,0x1d,0x01,0x16,0x15,0x14,0x06,0x22,0x26,0x35,0x34,0x37,0x35,0x34,0x36,0x3b,0x01,0x32,0x3d,0x01,0x26,0x35,0x34,0x36,0x32,0x16,0x15,0x14,0x07,0x15,0x14,0x3b,0x01,0x32,0x16,0x15,0x05,0x34,0x26,0x22,0x06, 0x14,0x16,0x32,0x36,0x13,0x14,0x16,0x32,0x36,0x34,0x26,0x22,0x06,0x13,0x34,0x26,0x22,0x06,0x14,0x16,0x32,0x36,0x05,0x32,0x36,0x34,0x26,0x22,0x06,0x14,0x16,0x03,0x64,0x48,0x46,0x64,0x46,0x48,0x4c,0x64,0x2c,0x22,0x48,0x46,0x64,0x46,0x48,0x1e,0x2e,0x64,0x22,0x26,0x06,0x48,0x46,0x64,0x46,0x48,0x56,0x58,0x64,0x4c,0x48,0x46, 0x64,0x46,0x48,0x4e,0x64,0x56,0x56,0xfd,0x5a,0x2a,0x38,0x28,0x28,0x38,0x2a,0xd4,0x28,0x38,0x2a,0x2a,0x38,0x28,0x8a,0x2a,0x38,0x28,0x28,0x38,0x2a,0x01,0x18,0x1c,0x2a,0x2a,0x38,0x28,0x28,0x70,0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0x72,0x4e,0x0c,0xcc,0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0xcc,0x0c,0x26,0x1c,0x0c,0x72, 0x22,0x4e,0x32,0x46,0x46,0x32,0x4e,0x22,0x72,0x40,0x6c,0x34,0x8c,0x22,0x4c,0x32,0x46,0x46,0x32,0x4c,0x22,0x8c,0x34,0x6c,0x40,0xe2,0x1e,0x28,0x28,0x3a,0x28,0x28,0x02,0xd8,0x1c,0x28,0x28,0x3a,0x28,0x28,0xfd,0x26,0x1e,0x28,0x28,0x3a,0x28,0x28,0x28,0x28,0x3a,0x28,0x28,0x3a,0x28,0x00,0x00,0x02,0x00,0x00,0xff,0xb1,0x03,0x59, 0x03,0x0b,0x00,0x23,0x00,0x33,0x00,0x3e,0x40,0x3b,0x0d,0x01,0x00,0x01,0x1f,0x01,0x04,0x03,0x02,0x4c,0x02,0x01,0x00,0x01,0x03,0x01,0x00,0x03,0x80,0x05,0x01,0x03,0x04,0x01,0x03,0x04,0x7e,0x00,0x01,0x01,0x07,0x5f,0x00,0x07,0x07,0x13,0x4d,0x00,0x04,0x04,0x06,0x60,0x00,0x06,0x06,0x11,0x06,0x4e,0x35,0x35,0x23,0x33,0x16,0x23, 0x24,0x23,0x08,0x07,0x1e,0x2b,0x01,0x35,0x34,0x26,0x07,0x23,0x35,0x34,0x26,0x27,0x23,0x22,0x06,0x07,0x15,0x23,0x22,0x06,0x07,0x15,0x14,0x16,0x37,0x33,0x15,0x14,0x16,0x3b,0x01,0x32,0x36,0x37,0x35,0x33,0x32,0x36,0x13,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x02,0xca,0x14,0x0f,0xb3,0x16, 0x0e,0x47,0x0f,0x14,0x01,0xb2,0x0f,0x14,0x01,0x16,0x0e,0xb2,0x16,0x0e,0x47,0x0f,0x14,0x01,0xb3,0x0e,0x16,0x8e,0x5e,0x43,0xfd,0xe9,0x43,0x5e,0x5e,0x43,0x02,0x17,0x43,0x5e,0x01,0x3a,0x48,0x0e,0x16,0x01,0xb3,0x0f,0x14,0x01,0x16,0x0e,0xb3,0x14,0x0f,0x48,0x0e,0x16,0x01,0xb3,0x0e,0x16,0x16,0x0e,0xb3,0x14,0x01,0x3f,0xfd,0xe8, 0x42,0x5e,0x01,0x60,0x41,0x02,0x18,0x42,0x5e,0x01,0x60,0x00,0x00,0x02,0x00,0x00,0xff,0xb1,0x03,0x59,0x03,0x0b,0x00,0x0f,0x00,0x1f,0x00,0x1f,0x40,0x1c,0x00,0x00,0x00,0x03,0x5f,0x00,0x03,0x03,0x13,0x4d,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x11,0x02,0x4e,0x35,0x35,0x26,0x33,0x04,0x07,0x1a,0x2b,0x01,0x35,0x34,0x26,0x07, 0x21,0x22,0x06,0x07,0x15,0x14,0x16,0x37,0x21,0x32,0x36,0x13,0x11,0x14,0x06,0x07,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x37,0x21,0x32,0x16,0x02,0xca,0x14,0x0f,0xfe,0x0c,0x0f,0x14,0x01,0x16,0x0e,0x01,0xf4,0x0e,0x16,0x8e,0x5e,0x43,0xfd,0xe9,0x43,0x5e,0x5e,0x43,0x02,0x17,0x43,0x5e,0x01,0x3a,0x48,0x0e,0x16,0x01,0x14,0x0f,0x48, 0x0e,0x16,0x01,0x14,0x01,0x3f,0xfd,0xe8,0x42,0x5e,0x01,0x60,0x41,0x02,0x18,0x42,0x5e,0x01,0x60,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x07,0xb3,0xdb,0xee,0x5f,0x0f,0x3c,0xf5,0x00,0x0f,0x03,0xe8,0x00,0x00,0x00,0x00,0xe4,0x2d,0xc8,0x06,0x00,0x00,0x00,0x00,0xe4,0x2d,0xc8,0x07,0xff,0xf5,0xff,0x6a,0x04,0x78,0x03,0x53, 0x00,0x00,0x00,0x08,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x03,0x52,0xff,0x6a,0x00,0x00,0x04,0x76,0xff,0xf5,0xff,0xf5,0x04,0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x03,0xe8,0x00,0x00,0x03,0x11,0x00,0x00,0x02,0x80,0x00,0x00,0x03,0xe8,0x00,0x00, 0x04,0x2f,0xff,0xff,0x00,0xf0,0x00,0x00,0x04,0x76,0xff,0xff,0x03,0xe8,0xff,0xff,0x03,0xe8,0x00,0x00,0x02,0x44,0x00,0x00,0x02,0x44,0x00,0x00,0x03,0x59,0xff,0xfd,0x02,0x3b,0x00,0x00,0x03,0xa0,0x00,0x00,0x03,0x11,0x00,0x00,0x03,0xac,0x00,0x00,0x03,0xe8,0x00,0x00,0x00,0xdc,0x00,0x00,0x01,0x65,0x00,0x00,0x01,0x65,0x00,0x00, 0x02,0x3b,0xff,0xff,0x01,0x65,0x00,0x00,0x01,0x65,0x00,0x00,0x03,0x98,0xff,0xfc,0x03,0x59,0x00,0x00,0x03,0xca,0x00,0x00,0x04,0x2f,0xff,0xff,0x03,0xa0,0x00,0x00,0x02,0xf8,0x00,0x00,0x03,0xd4,0xff,0xf7,0x03,0x59,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe8,0xff,0xff,0x02,0x82,0x00,0x00, 0x02,0xda,0x00,0x00,0x04,0x2f,0xff,0xff,0x02,0xf8,0x00,0x00,0x03,0x59,0xff,0xfd,0x03,0x59,0x00,0x00,0x03,0x59,0xff,0xff,0x02,0xda,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe8,0x00,0x00,0x02,0xf8,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe8,0xff,0xf5,0x03,0xe8,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0x11,0x00,0x00, 0x03,0x11,0x00,0x00,0x02,0x82,0x00,0x00,0x03,0x42,0x00,0x00,0x04,0x2f,0x00,0x00,0x03,0xa0,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xe7,0xff,0xfe,0x03,0x59,0x00,0x00,0x03,0x11,0x00,0x00,0x02,0x3b,0xff,0xff,0x03,0x98,0xff,0xfc,0x03,0x59,0x00,0x00,0x02,0x82,0x00,0x00,0x03,0xa0,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0xe8,0xff,0xff, 0x03,0x59,0xff,0xfd,0x02,0x82,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0x59,0xff,0xfe,0x02,0x82,0x00,0x00,0x03,0x59,0xff,0xfd,0x03,0x11,0x00,0x00,0x03,0xe8,0x00,0x00,0x03,0xac,0x00,0x00,0x03,0x59,0x00,0x00,0x03,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0xe0,0x01,0x76,0x01,0xf0, 0x02,0x46,0x02,0x9e,0x02,0xc4,0x03,0x10,0x03,0x46,0x03,0x68,0x03,0x8c,0x03,0xb8,0x04,0x42,0x05,0x04,0x05,0x60,0x05,0xf4,0x06,0x18,0x06,0x42,0x06,0x64,0x06,0x8e,0x06,0xc6,0x06,0xfe,0x07,0xa6,0x07,0xf8,0x08,0xa0,0x08,0xf2,0x09,0x20,0x09,0x42,0x09,0x8e,0x09,0xd6,0x0a,0x98,0x0b,0x82,0x0c,0x0e,0x0c,0xfa,0x0d,0x3e,0x0d,0x64, 0x0d,0xc6,0x0e,0x2a,0x0e,0x6c,0x0f,0x1e,0x0f,0xce,0x0f,0xf6,0x10,0x4a,0x11,0x7c,0x11,0x9a,0x11,0xd2,0x12,0x3c,0x12,0x98,0x12,0xf8,0x14,0x00,0x14,0x80,0x14,0xe0,0x15,0x1a,0x15,0xde,0x16,0x6a,0x16,0xc0,0x17,0xce,0x18,0x30,0x18,0x88,0x18,0xa6,0x18,0xe4,0x19,0x80,0x19,0xe8,0x1a,0x3c,0x1a,0xb8,0x1b,0x48,0x1b,0x7c,0x1b,0xd0, 0x1c,0x32,0x1c,0xc0,0x1d,0x04,0x1d,0x2e,0x1d,0x94,0x1d,0xca,0x1e,0x32,0x1e,0x80,0x1e,0xde,0x1f,0x9a,0x20,0x04,0x20,0x48,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x90,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x00,0x7b,0x00,0x8d,0x00,0x00,0x00,0xba,0x0e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xde,0x00,0x01, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x35,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x07,0x00,0x3d,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00,0x44,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x4c,0x00,0x01,0x00,0x00,0x00,0x00, 0x00,0x05,0x00,0x0b,0x00,0x54,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x08,0x00,0x5f,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x2b,0x00,0x67,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x13,0x00,0x92,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x00,0x00,0x6a,0x00,0xa5,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x01,0x00,0x10, 0x01,0x0f,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x02,0x00,0x0e,0x01,0x1f,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x03,0x00,0x10,0x01,0x2d,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x04,0x00,0x10,0x01,0x3d,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x05,0x00,0x16,0x01,0x4d,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x06,0x00,0x10,0x01,0x63,0x00,0x03, 0x00,0x01,0x04,0x09,0x00,0x0a,0x00,0x56,0x01,0x73,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0b,0x00,0x26,0x01,0xc9,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x32,0x35,0x20,0x62,0x79,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x20,0x61,0x75,0x74,0x68,0x6f,0x72,0x73,0x20,0x40,0x20,0x66, 0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x2e,0x63,0x6f,0x6d,0x66,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x52,0x65,0x67,0x75,0x6c,0x61,0x72,0x66,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x66,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2e,0x30,0x66,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x47,0x65,0x6e, 0x65,0x72,0x61,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x73,0x76,0x67,0x32,0x74,0x74,0x66,0x20,0x66,0x72,0x6f,0x6d,0x20,0x46,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x20,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x2e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x66,0x6f,0x6e,0x74,0x65,0x6c,0x6c,0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x43,0x00,0x6f,0x00, 0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0x28,0x00,0x43,0x00,0x29,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x32,0x00,0x35,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x69,0x00,0x6e,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x61,0x00,0x75,0x00,0x74,0x00, 0x68,0x00,0x6f,0x00,0x72,0x00,0x73,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00, 0x61,0x00,0x72,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x31,0x00,0x2e,0x00,0x30,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00, 0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x47,0x00,0x65,0x00,0x6e,0x00,0x65,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x73,0x00,0x76,0x00,0x67,0x00,0x32,0x00,0x74,0x00,0x74,0x00,0x66,0x00,0x20,0x00,0x66,0x00,0x72,0x00,0x6f,0x00,0x6d,0x00,0x20,0x00,0x46,0x00, 0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x6a,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x2e,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x2e,0x00, 0x63,0x00,0x6f,0x00,0x6d,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x01,0x02,0x01,0x03,0x01,0x04,0x01,0x05,0x01,0x06,0x01,0x07,0x01,0x08,0x01,0x09,0x01,0x0a,0x01,0x0b,0x01,0x0c, 0x01,0x0d,0x01,0x0e,0x01,0x0f,0x01,0x10,0x01,0x11,0x01,0x12,0x01,0x13,0x01,0x14,0x01,0x15,0x01,0x16,0x01,0x17,0x01,0x18,0x01,0x19,0x01,0x1a,0x01,0x1b,0x01,0x1c,0x01,0x1d,0x01,0x1e,0x01,0x1f,0x01,0x20,0x01,0x21,0x01,0x22,0x01,0x23,0x01,0x24,0x01,0x25,0x01,0x26,0x01,0x27,0x01,0x28,0x01,0x29,0x01,0x2a,0x01,0x2b,0x01,0x2c, 0x01,0x2d,0x01,0x2e,0x01,0x2f,0x01,0x30,0x01,0x31,0x01,0x32,0x01,0x33,0x01,0x34,0x01,0x35,0x01,0x36,0x01,0x37,0x01,0x38,0x01,0x39,0x01,0x3a,0x01,0x3b,0x01,0x3c,0x01,0x3d,0x01,0x3e,0x01,0x3f,0x01,0x40,0x01,0x41,0x01,0x42,0x01,0x43,0x01,0x44,0x01,0x45,0x01,0x46,0x01,0x47,0x01,0x48,0x01,0x49,0x01,0x4a,0x01,0x4b,0x01,0x4c, 0x01,0x4d,0x01,0x4e,0x01,0x4f,0x01,0x50,0x01,0x51,0x01,0x52,0x00,0x0b,0x63,0x68,0x65,0x63,0x6b,0x2d,0x65,0x6d,0x70,0x74,0x79,0x0d,0x66,0x6c,0x6f,0x77,0x2d,0x70,0x61,0x72,0x61,0x6c,0x6c,0x65,0x6c,0x04,0x64,0x6f,0x63,0x73,0x07,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x09,0x66,0x6c,0x6f,0x77,0x2d,0x6c,0x69,0x6e,0x65,0x0e,0x77, 0x69,0x6e,0x64,0x6f,0x77,0x2d,0x72,0x65,0x73,0x74,0x6f,0x72,0x65,0x0f,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2d,0x6d,0x69,0x6e,0x69,0x6d,0x69,0x7a,0x65,0x04,0x63,0x75,0x62,0x65,0x04,0x70,0x6c,0x75,0x73,0x05,0x6d,0x69,0x6e,0x75,0x73,0x06,0x63,0x69,0x72,0x63,0x6c,0x65,0x08,0x64,0x6f,0x77,0x6e,0x2d,0x64,0x69,0x72,0x05,0x63,0x68, 0x65,0x63,0x6b,0x0b,0x74,0x72,0x61,0x73,0x68,0x2d,0x65,0x6d,0x70,0x74,0x79,0x04,0x75,0x73,0x65,0x72,0x09,0x62,0x72,0x69,0x65,0x66,0x63,0x61,0x73,0x65,0x03,0x64,0x6f,0x74,0x08,0x6c,0x65,0x66,0x74,0x2d,0x64,0x69,0x72,0x09,0x72,0x69,0x67,0x68,0x74,0x2d,0x64,0x69,0x72,0x06,0x75,0x70,0x2d,0x64,0x69,0x72,0x0a,0x61,0x6e,0x67, 0x6c,0x65,0x2d,0x6c,0x65,0x66,0x74,0x0b,0x61,0x6e,0x67,0x6c,0x65,0x2d,0x72,0x69,0x67,0x68,0x74,0x0c,0x68,0x65,0x6c,0x70,0x2d,0x63,0x69,0x72,0x63,0x6c,0x65,0x64,0x03,0x74,0x61,0x67,0x04,0x67,0x72,0x69,0x64,0x0b,0x66,0x6f,0x6c,0x64,0x65,0x72,0x2d,0x6f,0x70,0x65,0x6e,0x06,0x66,0x6f,0x6c,0x64,0x65,0x72,0x09,0x64,0x6f,0x77, 0x6e,0x2d,0x62,0x6f,0x6c,0x64,0x07,0x70,0x61,0x6c,0x65,0x74,0x74,0x65,0x07,0x64,0x6f,0x63,0x2d,0x69,0x6e,0x76,0x03,0x63,0x6f,0x67,0x02,0x74,0x68,0x0a,0x62,0x69,0x6e,0x6f,0x63,0x75,0x6c,0x61,0x72,0x73,0x04,0x6c,0x69,0x73,0x74,0x04,0x6c,0x6f,0x63,0x6b,0x09,0x6c,0x65,0x66,0x74,0x2d,0x62,0x6f,0x6c,0x64,0x07,0x64,0x65,0x73, 0x6b,0x74,0x6f,0x70,0x06,0x73,0x65,0x61,0x72,0x63,0x68,0x0c,0x63,0x69,0x72,0x63,0x6c,0x65,0x2d,0x65,0x6d,0x70,0x74,0x79,0x06,0x70,0x65,0x6e,0x63,0x69,0x6c,0x03,0x68,0x64,0x64,0x0a,0x72,0x69,0x67,0x68,0x74,0x2d,0x62,0x6f,0x6c,0x64,0x0b,0x63,0x6c,0x6f,0x73,0x65,0x5f,0x70,0x61,0x6e,0x65,0x6c,0x08,0x73,0x74,0x65,0x70,0x69, 0x6e,0x74,0x6f,0x07,0x75,0x70,0x2d,0x62,0x6f,0x6c,0x64,0x02,0x6f,0x6b,0x09,0x61,0x74,0x74,0x65,0x6e,0x74,0x69,0x6f,0x6e,0x10,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x5f,0x73,0x70,0x6c,0x69,0x74,0x0e,0x76,0x65,0x72,0x74,0x69,0x63,0x61,0x6c,0x5f,0x73,0x70,0x6c,0x69,0x74,0x08,0x73,0x74,0x65,0x70,0x6f,0x76,0x65, 0x72,0x10,0x70,0x6c,0x75,0x73,0x2d,0x73,0x71,0x75,0x61,0x72,0x65,0x64,0x2d,0x61,0x6c,0x74,0x11,0x6d,0x69,0x6e,0x75,0x73,0x2d,0x73,0x71,0x75,0x61,0x72,0x65,0x64,0x2d,0x61,0x6c,0x74,0x08,0x61,0x6e,0x67,0x6c,0x65,0x2d,0x75,0x70,0x09,0x63,0x6c,0x69,0x70,0x62,0x6f,0x61,0x72,0x64,0x11,0x66,0x6f,0x6c,0x64,0x65,0x72,0x2d,0x6f, 0x70,0x65,0x6e,0x2d,0x65,0x6d,0x70,0x74,0x79,0x0c,0x66,0x6f,0x6c,0x64,0x65,0x72,0x2d,0x65,0x6d,0x70,0x74,0x79,0x07,0x73,0x74,0x65,0x70,0x6f,0x75,0x74,0x07,0x67,0x6c,0x61,0x73,0x73,0x65,0x73,0x03,0x64,0x6f,0x63,0x04,0x70,0x6c,0x61,0x79,0x06,0x74,0x6f,0x2d,0x65,0x6e,0x64,0x0c,0x69,0x6e,0x66,0x6f,0x2d,0x63,0x69,0x72,0x63, 0x6c,0x65,0x64,0x03,0x63,0x63,0x77,0x0d,0x6c,0x6f,0x63,0x6b,0x2d,0x6f,0x70,0x65,0x6e,0x2d,0x61,0x6c,0x74,0x06,0x74,0x61,0x72,0x67,0x65,0x74,0x06,0x66,0x6c,0x6f,0x70,0x70,0x79,0x0f,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2d,0x6d,0x61,0x78,0x69,0x6d,0x69,0x7a,0x65,0x0b,0x64,0x6f,0x74,0x2d,0x63,0x69,0x72,0x63,0x6c,0x65,0x64,0x03, 0x70,0x69,0x6e,0x09,0x61,0x72,0x72,0x6f,0x77,0x73,0x2d,0x63,0x77,0x05,0x70,0x61,0x75,0x73,0x65,0x04,0x73,0x74,0x6f,0x70,0x02,0x63,0x77,0x0a,0x61,0x6e,0x67,0x6c,0x65,0x2d,0x64,0x6f,0x77,0x6e,0x11,0x61,0x74,0x74,0x65,0x6e,0x74,0x69,0x6f,0x6e,0x2d,0x63,0x69,0x72,0x63,0x6c,0x65,0x64,0x06,0x63,0x61,0x6e,0x63,0x65,0x6c,0x03, 0x62,0x6f,0x78,0x09,0x66,0x6c,0x6f,0x77,0x2d,0x74,0x72,0x65,0x65,0x0c,0x70,0x6c,0x75,0x73,0x2d,0x73,0x71,0x75,0x61,0x72,0x65,0x64,0x0d,0x6d,0x69,0x6e,0x75,0x73,0x2d,0x73,0x71,0x75,0x61,0x72,0x65,0x64,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0xff,0xff,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x7e,0x01,0x1e,0x00,0x7d,0x00,0x7d,0x01,0x1e,0x03,0x18,0xff,0xb1,0x03,0x38,0x03,0x0b,0xff,0xb1,0xff,0xb1,0x03,0x18,0xff,0xb1,0x03,0x38,0x03,0x0b,0xff,0xb1,0xff,0xb1,0xb0,0x00,0x2c,0x20,0xb0,0x00,0x55,0x58,0x45,0x59,0x20,0x20,0x4b,0xb8,0x00,0x0e,0x51,0x4b,0xb0,0x06, 0x53,0x5a,0x58,0xb0,0x34,0x1b,0xb0,0x28,0x59,0x60,0x66,0x20,0x8a,0x55,0x58,0xb0,0x02,0x25,0x61,0xb9,0x08,0x00,0x08,0x00,0x63,0x63,0x23,0x62,0x1b,0x21,0x21,0xb0,0x00,0x59,0xb0,0x00,0x43,0x23,0x44,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x01,0x2c,0xb0,0x20,0x60,0x66,0x2d,0xb0,0x02,0x2c,0x23,0x21,0x23,0x21,0x2d,0xb0, 0x03,0x2c,0x20,0x64,0xb3,0x03,0x14,0x15,0x00,0x42,0x43,0xb0,0x13,0x43,0x20,0x60,0x60,0x42,0xb1,0x02,0x14,0x43,0x42,0xb1,0x25,0x03,0x43,0xb0,0x02,0x43,0x54,0x78,0x20,0xb0,0x0c,0x23,0xb0,0x02,0x43,0x43,0x61,0x64,0xb0,0x04,0x50,0x78,0xb2,0x02,0x02,0x02,0x43,0x60,0x42,0xb0,0x21,0x65,0x1c,0x21,0xb0,0x02,0x43,0x43,0xb2,0x0e, 0x15,0x01,0x42,0x1c,0x20,0xb0,0x02,0x43,0x23,0x42,0xb2,0x13,0x01,0x13,0x43,0x60,0x42,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb2,0x16,0x01,0x02,0x43,0x60,0x42,0x2d,0xb0,0x04,0x2c,0xb0,0x03,0x2b,0xb0,0x15,0x43,0x58,0x23,0x21,0x23,0x21,0xb0,0x16,0x43,0x43,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0x1b,0x20,0x64,0x20,0xb0,0xc0,0x50, 0xb0,0x04,0x26,0x5a,0xb2,0x28,0x01,0x0d,0x43,0x45,0x63,0x45,0xb0,0x06,0x45,0x58,0x21,0xb0,0x03,0x25,0x59,0x52,0x5b,0x58,0x21,0x23,0x21,0x1b,0x8a,0x58,0x20,0xb0,0x50,0x50,0x58,0x21,0xb0,0x40,0x59,0x1b,0x20,0xb0,0x38,0x50,0x58,0x21,0xb0,0x38,0x59,0x59,0x20,0xb1,0x01,0x0d,0x43,0x45,0x63,0x45,0x61,0x64,0xb0,0x28,0x50,0x58, 0x21,0xb1,0x01,0x0d,0x43,0x45,0x63,0x45,0x20,0xb0,0x30,0x50,0x58,0x21,0xb0,0x30,0x59,0x1b,0x20,0xb0,0xc0,0x50,0x58,0x20,0x66,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x0a,0x50,0x58,0x60,0x1b,0x20,0xb0,0x20,0x50,0x58,0x21,0xb0,0x0a,0x60,0x1b,0x20,0xb0,0x36,0x50,0x58,0x21,0xb0,0x36,0x60,0x1b,0x60,0x59,0x59,0x59,0x1b,0xb0,0x02,0x25, 0xb0,0x0c,0x43,0x63,0xb0,0x00,0x52,0x58,0xb0,0x00,0x4b,0xb0,0x0a,0x50,0x58,0x21,0xb0,0x0c,0x43,0x1b,0x4b,0xb0,0x1e,0x50,0x58,0x21,0xb0,0x1e,0x4b,0x61,0xb8,0x10,0x00,0x63,0xb0,0x0c,0x43,0x63,0xb8,0x05,0x00,0x62,0x59,0x59,0x64,0x61,0x59,0xb0,0x01,0x2b,0x59,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0x59,0x20,0x64,0xb0,0x16, 0x43,0x23,0x42,0x59,0x2d,0xb0,0x05,0x2c,0x20,0x45,0x20,0xb0,0x04,0x25,0x61,0x64,0x20,0xb0,0x07,0x43,0x50,0x58,0xb0,0x07,0x23,0x42,0xb0,0x08,0x23,0x42,0x1b,0x21,0x21,0x59,0xb0,0x01,0x60,0x2d,0xb0,0x06,0x2c,0x23,0x21,0x23,0x21,0xb0,0x03,0x2b,0x20,0x64,0xb1,0x07,0x62,0x42,0x20,0xb0,0x08,0x23,0x42,0xb0,0x06,0x45,0x58,0x1b, 0xb1,0x01,0x0d,0x43,0x45,0x63,0xb1,0x01,0x0d,0x43,0xb0,0x01,0x60,0x45,0x63,0xb0,0x05,0x2a,0x21,0x20,0xb0,0x08,0x43,0x20,0x8a,0x20,0x8a,0xb0,0x01,0x2b,0xb1,0x30,0x05,0x25,0xb0,0x04,0x26,0x51,0x58,0x60,0x50,0x1b,0x61,0x52,0x59,0x58,0x23,0x59,0x21,0x59,0x20,0xb0,0x40,0x53,0x58,0xb0,0x01,0x2b,0x1b,0x21,0xb0,0x40,0x59,0x23, 0xb0,0x00,0x50,0x58,0x65,0x59,0x2d,0xb0,0x07,0x2c,0xb0,0x09,0x43,0x2b,0xb2,0x00,0x02,0x00,0x43,0x60,0x42,0x2d,0xb0,0x08,0x2c,0xb0,0x09,0x23,0x42,0x23,0x20,0xb0,0x00,0x23,0x42,0x61,0xb0,0x02,0x62,0x66,0xb0,0x01,0x63,0xb0,0x01,0x60,0xb0,0x07,0x2a,0x2d,0xb0,0x09,0x2c,0x20,0x20,0x45,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00, 0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0a,0x2c,0xb2,0x09,0x0e,0x00,0x43,0x45,0x42,0x2a,0x21,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x0b,0x2c,0xb0,0x00,0x43,0x23,0x44,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x0c,0x2c,0x20,0x20,0x45,0x20,0xb0, 0x01,0x2b,0x23,0xb0,0x00,0x43,0xb0,0x04,0x25,0x60,0x20,0x45,0x8a,0x23,0x61,0x20,0x64,0x20,0xb0,0x20,0x50,0x58,0x21,0xb0,0x00,0x1b,0xb0,0x30,0x50,0x58,0xb0,0x20,0x1b,0xb0,0x40,0x59,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb0,0x03,0x25,0x23,0x61,0x44,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0d,0x2c,0x20,0x20,0x45,0x20,0xb0,0x01, 0x2b,0x23,0xb0,0x00,0x43,0xb0,0x04,0x25,0x60,0x20,0x45,0x8a,0x23,0x61,0x20,0x64,0xb0,0x24,0x50,0x58,0xb0,0x00,0x1b,0xb0,0x40,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb0,0x03,0x25,0x23,0x61,0x44,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0e,0x2c,0x20,0xb0,0x00,0x23,0x42,0xb3,0x0d,0x0c,0x00,0x03,0x45,0x50,0x58,0x21,0x1b,0x23,0x21, 0x59,0x2a,0x21,0x2d,0xb0,0x0f,0x2c,0xb1,0x02,0x02,0x45,0xb0,0x64,0x61,0x44,0x2d,0xb0,0x10,0x2c,0xb0,0x01,0x60,0x20,0x20,0xb0,0x0f,0x43,0x4a,0xb0,0x00,0x50,0x58,0x20,0xb0,0x0f,0x23,0x42,0x59,0xb0,0x10,0x43,0x4a,0xb0,0x00,0x52,0x58,0x20,0xb0,0x10,0x23,0x42,0x59,0x2d,0xb0,0x11,0x2c,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63, 0x20,0xb8,0x04,0x00,0x63,0x8a,0x23,0x61,0xb0,0x11,0x43,0x60,0x20,0x8a,0x60,0x20,0xb0,0x11,0x23,0x42,0x23,0x2d,0xb0,0x12,0x2c,0x4b,0x54,0x58,0xb1,0x04,0x64,0x44,0x59,0x24,0xb0,0x0d,0x65,0x23,0x78,0x2d,0xb0,0x13,0x2c,0x4b,0x51,0x58,0x4b,0x53,0x58,0xb1,0x04,0x64,0x44,0x59,0x1b,0x21,0x59,0x24,0xb0,0x13,0x65,0x23,0x78,0x2d, 0xb0,0x14,0x2c,0xb1,0x00,0x12,0x43,0x55,0x58,0xb1,0x12,0x12,0x43,0xb0,0x01,0x61,0x42,0xb0,0x11,0x2b,0x59,0xb0,0x00,0x43,0xb0,0x02,0x25,0x42,0xb1,0x0f,0x02,0x25,0x42,0xb1,0x10,0x02,0x25,0x42,0xb0,0x01,0x16,0x23,0x20,0xb0,0x03,0x25,0x50,0x58,0xb1,0x01,0x00,0x43,0x60,0xb0,0x04,0x25,0x42,0x8a,0x8a,0x20,0x8a,0x23,0x61,0xb0, 0x10,0x2a,0x21,0x23,0xb0,0x01,0x61,0x20,0x8a,0x23,0x61,0xb0,0x10,0x2a,0x21,0x1b,0xb1,0x01,0x00,0x43,0x60,0xb0,0x02,0x25,0x42,0xb0,0x02,0x25,0x61,0xb0,0x10,0x2a,0x21,0x59,0xb0,0x0f,0x43,0x47,0xb0,0x10,0x43,0x47,0x60,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x20,0xb0,0x0e,0x43,0x63, 0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0xb1,0x00,0x00,0x13,0x23,0x44,0xb0,0x01,0x43,0xb0,0x00,0x3e,0xb2,0x01,0x01,0x01,0x43,0x60,0x42,0x2d,0xb0,0x15,0x2c,0x00,0xb1,0x00,0x02,0x45,0x54,0x58,0xb0,0x12,0x23,0x42,0x20,0x45,0xb0,0x0e,0x23,0x42,0xb0,0x0d,0x23,0xb0,0x01,0x60, 0x42,0x20,0x60,0xb7,0x18,0x18,0x01,0x00,0x11,0x00,0x13,0x00,0x42,0x42,0x42,0x8a,0x60,0x20,0xb0,0x14,0x23,0x42,0xb0,0x01,0x61,0xb1,0x14,0x08,0x2b,0xb0,0x8b,0x2b,0x1b,0x22,0x59,0x2d,0xb0,0x16,0x2c,0xb1,0x00,0x15,0x2b,0x2d,0xb0,0x17,0x2c,0xb1,0x01,0x15,0x2b,0x2d,0xb0,0x18,0x2c,0xb1,0x02,0x15,0x2b,0x2d,0xb0,0x19,0x2c,0xb1, 0x03,0x15,0x2b,0x2d,0xb0,0x1a,0x2c,0xb1,0x04,0x15,0x2b,0x2d,0xb0,0x1b,0x2c,0xb1,0x05,0x15,0x2b,0x2d,0xb0,0x1c,0x2c,0xb1,0x06,0x15,0x2b,0x2d,0xb0,0x1d,0x2c,0xb1,0x07,0x15,0x2b,0x2d,0xb0,0x1e,0x2c,0xb1,0x08,0x15,0x2b,0x2d,0xb0,0x1f,0x2c,0xb1,0x09,0x15,0x2b,0x2d,0xb0,0x2b,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63, 0xb0,0x06,0x60,0x4b,0x54,0x58,0x23,0x20,0x2e,0xb0,0x01,0x5d,0x1b,0x21,0x21,0x59,0x2d,0xb0,0x2c,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0xb0,0x16,0x60,0x4b,0x54,0x58,0x23,0x20,0x2e,0xb0,0x01,0x71,0x1b,0x21,0x21,0x59,0x2d,0xb0,0x2d,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0xb0,0x26,0x60,0x4b,0x54,0x58, 0x23,0x20,0x2e,0xb0,0x01,0x72,0x1b,0x21,0x21,0x59,0x2d,0xb0,0x20,0x2c,0x00,0xb0,0x0f,0x2b,0xb1,0x00,0x02,0x45,0x54,0x58,0xb0,0x12,0x23,0x42,0x20,0x45,0xb0,0x0e,0x23,0x42,0xb0,0x0d,0x23,0xb0,0x01,0x60,0x42,0x20,0x60,0xb0,0x01,0x61,0xb5,0x18,0x18,0x01,0x00,0x11,0x00,0x42,0x42,0x8a,0x60,0xb1,0x14,0x08,0x2b,0xb0,0x8b,0x2b, 0x1b,0x22,0x59,0x2d,0xb0,0x21,0x2c,0xb1,0x00,0x20,0x2b,0x2d,0xb0,0x22,0x2c,0xb1,0x01,0x20,0x2b,0x2d,0xb0,0x23,0x2c,0xb1,0x02,0x20,0x2b,0x2d,0xb0,0x24,0x2c,0xb1,0x03,0x20,0x2b,0x2d,0xb0,0x25,0x2c,0xb1,0x04,0x20,0x2b,0x2d,0xb0,0x26,0x2c,0xb1,0x05,0x20,0x2b,0x2d,0xb0,0x27,0x2c,0xb1,0x06,0x20,0x2b,0x2d,0xb0,0x28,0x2c,0xb1, 0x07,0x20,0x2b,0x2d,0xb0,0x29,0x2c,0xb1,0x08,0x20,0x2b,0x2d,0xb0,0x2a,0x2c,0xb1,0x09,0x20,0x2b,0x2d,0xb0,0x2e,0x2c,0x20,0x3c,0xb0,0x01,0x60,0x2d,0xb0,0x2f,0x2c,0x20,0x60,0xb0,0x18,0x60,0x20,0x43,0x23,0xb0,0x01,0x60,0x43,0xb0,0x02,0x25,0x61,0xb0,0x01,0x60,0xb0,0x2e,0x2a,0x21,0x2d,0xb0,0x30,0x2c,0xb0,0x2f,0x2b,0xb0,0x2f, 0x2a,0x2d,0xb0,0x31,0x2c,0x20,0x20,0x47,0x20,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x61,0x38,0x23,0x20,0x8a,0x55,0x58,0x20,0x47,0x20,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01, 0x63,0x60,0x23,0x61,0x38,0x1b,0x21,0x59,0x2d,0xb0,0x32,0x2c,0x00,0xb1,0x00,0x02,0x45,0x54,0x58,0xb1,0x0e,0x07,0x45,0x42,0xb0,0x01,0x16,0xb0,0x31,0x2a,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x1b,0x22,0x59,0x2d,0xb0,0x33,0x2c,0x00,0xb0,0x0f,0x2b,0xb1,0x00,0x02,0x45,0x54,0x58,0xb1,0x0e,0x07,0x45,0x42,0xb0,0x01,0x16,0xb0, 0x31,0x2a,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x1b,0x22,0x59,0x2d,0xb0,0x34,0x2c,0x20,0x35,0xb0,0x01,0x60,0x2d,0xb0,0x35,0x2c,0x00,0xb1,0x0e,0x07,0x45,0x42,0xb0,0x01,0x45,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0xb0,0x01,0x2b,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62, 0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0xb0,0x01,0x2b,0xb0,0x00,0x16,0xb4,0x00,0x00,0x00,0x00,0x00,0x44,0x3e,0x23,0x38,0xb1,0x34,0x01,0x15,0x2a,0x21,0x2d,0xb0,0x36,0x2c,0x20,0x3c,0x20,0x47,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01, 0x63,0x60,0xb0,0x00,0x43,0x61,0x38,0x2d,0xb0,0x37,0x2c,0x2e,0x17,0x3c,0x2d,0xb0,0x38,0x2c,0x20,0x3c,0x20,0x47,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0xb0,0x00,0x43,0x61,0xb0,0x01,0x43,0x63,0x38,0x2d,0xb0,0x39,0x2c,0xb1,0x02,0x00,0x16,0x25,0x20, 0x2e,0x20,0x47,0xb0,0x00,0x23,0x42,0xb0,0x02,0x25,0x49,0x8a,0x8a,0x47,0x23,0x47,0x23,0x61,0x20,0x58,0x62,0x1b,0x21,0x59,0xb0,0x01,0x23,0x42,0xb2,0x38,0x01,0x01,0x15,0x14,0x2a,0x2d,0xb0,0x3a,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x04,0x25,0xb0,0x04,0x25,0x47,0x23,0x47,0x23,0x61,0xb1,0x0c,0x00,0x42,0xb0,0x0b,0x43, 0x2b,0x65,0x8a,0x2e,0x23,0x20,0x20,0x3c,0x8a,0x38,0x2d,0xb0,0x3b,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x04,0x25,0xb0,0x04,0x25,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x06,0x23,0x42,0xb1,0x0c,0x00,0x42,0xb0,0x0b,0x43,0x2b,0x20,0xb0,0x60,0x50,0x58,0x20,0xb0,0x40,0x51,0x58,0xb3,0x04,0x20,0x05,0x20,0x1b,0xb3, 0x04,0x26,0x05,0x1a,0x59,0x42,0x42,0x23,0x20,0xb0,0x0a,0x43,0x20,0x8a,0x23,0x47,0x23,0x47,0x23,0x61,0x23,0x46,0x60,0xb0,0x06,0x43,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x20,0xb0,0x01,0x2b,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x04,0x43,0x60,0x64,0x23,0xb0,0x05,0x43,0x61,0x64,0x50, 0x58,0xb0,0x04,0x43,0x61,0x1b,0xb0,0x05,0x43,0x60,0x59,0xb0,0x03,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x61,0x23,0x20,0x20,0xb0,0x04,0x26,0x23,0x46,0x61,0x38,0x1b,0x23,0xb0,0x0a,0x43,0x46,0xb0,0x02,0x25,0xb0,0x0a,0x43,0x47,0x23,0x47,0x23,0x61,0x60,0x20,0xb0,0x06,0x43,0xb0, 0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x20,0xb0,0x01,0x2b,0x23,0xb0,0x06,0x43,0x60,0xb0,0x01,0x2b,0xb0,0x05,0x25,0x61,0xb0,0x05,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0xb0,0x04,0x26,0x61,0x20,0xb0,0x04,0x25,0x60,0x64,0x23,0xb0, 0x03,0x25,0x60,0x64,0x50,0x58,0x21,0x1b,0x23,0x21,0x59,0x23,0x20,0x20,0xb0,0x04,0x26,0x23,0x46,0x61,0x38,0x59,0x2d,0xb0,0x3c,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0x20,0x20,0xb0,0x05,0x26,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x23,0x3c,0x38,0x2d,0xb0,0x3d,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0xb0,0x0a,0x23, 0x42,0x20,0x20,0x20,0x46,0x23,0x47,0xb0,0x01,0x2b,0x23,0x61,0x38,0x2d,0xb0,0x3e,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x03,0x25,0xb0,0x02,0x25,0x47,0x23,0x47,0x23,0x61,0xb0,0x00,0x54,0x58,0x2e,0x20,0x3c,0x23,0x21,0x1b,0xb0,0x02,0x25,0xb0,0x02,0x25,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x05,0x25,0xb0,0x04,0x25,0x47, 0x23,0x47,0x23,0x61,0xb0,0x06,0x25,0xb0,0x05,0x25,0x49,0xb0,0x02,0x25,0x61,0xb9,0x08,0x00,0x08,0x00,0x63,0x63,0x23,0x20,0x58,0x62,0x1b,0x21,0x59,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x2e,0x23,0x20,0x20,0x3c,0x8a,0x38,0x23,0x21,0x59,0x2d,0xb0,0x3f,0x2c,0xb0, 0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0xb0,0x0a,0x43,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x20,0x60,0xb0,0x20,0x60,0x66,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x23,0x20,0x20,0x3c,0x8a,0x38,0x2d,0xb0,0x40,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52, 0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x41,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x52,0x1b,0x50,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x42,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c, 0x59,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x52,0x1b,0x50,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x43,0x2c,0xb0,0x3a,0x2b,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x44,0x2c, 0xb0,0x3b,0x2b,0x8a,0x20,0x20,0x3c,0xb0,0x06,0x23,0x42,0x8a,0x38,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0xb0,0x06,0x43,0x2e,0xb0,0x30,0x2b,0x2d,0xb0,0x45,0x2c,0xb0,0x00,0x16,0xb0,0x04,0x25,0xb0,0x04,0x26,0x20,0x20,0x20,0x46,0x23, 0x47,0x61,0xb0,0x0c,0x23,0x42,0x2e,0x47,0x23,0x47,0x23,0x61,0xb0,0x0b,0x43,0x2b,0x23,0x20,0x3c,0x20,0x2e,0x23,0x38,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x46,0x2c,0xb1,0x0a,0x04,0x25,0x42,0xb0,0x00,0x16,0xb0,0x04,0x25,0xb0,0x04,0x25,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x06,0x23,0x42,0xb1,0x0c,0x00,0x42,0xb0,0x0b, 0x43,0x2b,0x20,0xb0,0x60,0x50,0x58,0x20,0xb0,0x40,0x51,0x58,0xb3,0x04,0x20,0x05,0x20,0x1b,0xb3,0x04,0x26,0x05,0x1a,0x59,0x42,0x42,0x23,0x20,0x47,0xb0,0x06,0x43,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x20,0xb0,0x01,0x2b,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x04,0x43,0x60,0x64,0x23, 0xb0,0x05,0x43,0x61,0x64,0x50,0x58,0xb0,0x04,0x43,0x61,0x1b,0xb0,0x05,0x43,0x60,0x59,0xb0,0x03,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x61,0xb0,0x02,0x25,0x46,0x61,0x38,0x23,0x20,0x3c,0x23,0x38,0x1b,0x21,0x20,0x20,0x46,0x23,0x47,0xb0,0x01,0x2b,0x23,0x61,0x38,0x21,0x59,0xb1, 0x30,0x01,0x14,0x2b,0x2d,0xb0,0x47,0x2c,0xb1,0x00,0x3a,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x48,0x2c,0xb1,0x00,0x3b,0x2b,0x21,0x23,0x20,0x20,0x3c,0xb0,0x06,0x23,0x42,0x23,0x38,0xb1,0x30,0x01,0x14,0x2b,0xb0,0x06,0x43,0x2e,0xb0,0x30,0x2b,0x2d,0xb0,0x49,0x2c,0xb0,0x00,0x15,0x20,0x47,0xb0,0x00,0x23,0x42,0xb2,0x00, 0x01,0x01,0x15,0x14,0x13,0x2e,0xb0,0x36,0x2a,0x2d,0xb0,0x4a,0x2c,0xb0,0x00,0x15,0x20,0x47,0xb0,0x00,0x23,0x42,0xb2,0x00,0x01,0x01,0x15,0x14,0x13,0x2e,0xb0,0x36,0x2a,0x2d,0xb0,0x4b,0x2c,0xb1,0x00,0x01,0x14,0x13,0xb0,0x37,0x2a,0x2d,0xb0,0x4c,0x2c,0xb0,0x39,0x2a,0x2d,0xb0,0x4d,0x2c,0xb0,0x00,0x16,0x45,0x23,0x20,0x2e,0x20, 0x46,0x8a,0x23,0x61,0x38,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x4e,0x2c,0xb0,0x0a,0x23,0x42,0xb0,0x4d,0x2b,0x2d,0xb0,0x4f,0x2c,0xb2,0x00,0x00,0x46,0x2b,0x2d,0xb0,0x50,0x2c,0xb2,0x00,0x01,0x46,0x2b,0x2d,0xb0,0x51,0x2c,0xb2,0x01,0x00,0x46,0x2b,0x2d,0xb0,0x52,0x2c,0xb2,0x01,0x01,0x46,0x2b,0x2d,0xb0,0x53,0x2c,0xb2,0x00,0x00, 0x47,0x2b,0x2d,0xb0,0x54,0x2c,0xb2,0x00,0x01,0x47,0x2b,0x2d,0xb0,0x55,0x2c,0xb2,0x01,0x00,0x47,0x2b,0x2d,0xb0,0x56,0x2c,0xb2,0x01,0x01,0x47,0x2b,0x2d,0xb0,0x57,0x2c,0xb3,0x00,0x00,0x00,0x43,0x2b,0x2d,0xb0,0x58,0x2c,0xb3,0x00,0x01,0x00,0x43,0x2b,0x2d,0xb0,0x59,0x2c,0xb3,0x01,0x00,0x00,0x43,0x2b,0x2d,0xb0,0x5a,0x2c,0xb3, 0x01,0x01,0x00,0x43,0x2b,0x2d,0xb0,0x5b,0x2c,0xb3,0x00,0x00,0x01,0x43,0x2b,0x2d,0xb0,0x5c,0x2c,0xb3,0x00,0x01,0x01,0x43,0x2b,0x2d,0xb0,0x5d,0x2c,0xb3,0x01,0x00,0x01,0x43,0x2b,0x2d,0xb0,0x5e,0x2c,0xb3,0x01,0x01,0x01,0x43,0x2b,0x2d,0xb0,0x5f,0x2c,0xb2,0x00,0x00,0x45,0x2b,0x2d,0xb0,0x60,0x2c,0xb2,0x00,0x01,0x45,0x2b,0x2d, 0xb0,0x61,0x2c,0xb2,0x01,0x00,0x45,0x2b,0x2d,0xb0,0x62,0x2c,0xb2,0x01,0x01,0x45,0x2b,0x2d,0xb0,0x63,0x2c,0xb2,0x00,0x00,0x48,0x2b,0x2d,0xb0,0x64,0x2c,0xb2,0x00,0x01,0x48,0x2b,0x2d,0xb0,0x65,0x2c,0xb2,0x01,0x00,0x48,0x2b,0x2d,0xb0,0x66,0x2c,0xb2,0x01,0x01,0x48,0x2b,0x2d,0xb0,0x67,0x2c,0xb3,0x00,0x00,0x00,0x44,0x2b,0x2d, 0xb0,0x68,0x2c,0xb3,0x00,0x01,0x00,0x44,0x2b,0x2d,0xb0,0x69,0x2c,0xb3,0x01,0x00,0x00,0x44,0x2b,0x2d,0xb0,0x6a,0x2c,0xb3,0x01,0x01,0x00,0x44,0x2b,0x2d,0xb0,0x6b,0x2c,0xb3,0x00,0x00,0x01,0x44,0x2b,0x2d,0xb0,0x6c,0x2c,0xb3,0x00,0x01,0x01,0x44,0x2b,0x2d,0xb0,0x6d,0x2c,0xb3,0x01,0x00,0x01,0x44,0x2b,0x2d,0xb0,0x6e,0x2c,0xb3, 0x01,0x01,0x01,0x44,0x2b,0x2d,0xb0,0x6f,0x2c,0xb1,0x00,0x3c,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x70,0x2c,0xb1,0x00,0x3c,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x71,0x2c,0xb1,0x00,0x3c,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x72,0x2c,0xb0,0x00,0x16,0xb1,0x00,0x3c,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x73,0x2c,0xb1,0x01,0x3c,0x2b,0xb0, 0x40,0x2b,0x2d,0xb0,0x74,0x2c,0xb1,0x01,0x3c,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x75,0x2c,0xb0,0x00,0x16,0xb1,0x01,0x3c,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x76,0x2c,0xb1,0x00,0x3d,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x77,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x78,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x41,0x2b,0x2d, 0xb0,0x79,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x7a,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x7b,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x7c,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x7d,0x2c,0xb1,0x00,0x3e,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x7e,0x2c,0xb1,0x00,0x3e, 0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x7f,0x2c,0xb1,0x00,0x3e,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x80,0x2c,0xb1,0x00,0x3e,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x81,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x82,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x83,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x84,0x2c,0xb1, 0x00,0x3f,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x85,0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x86,0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x87,0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x88,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x89,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x41,0x2b, 0x2d,0xb0,0x8a,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x8b,0x2c,0xb2,0x0b,0x00,0x03,0x45,0x50,0x58,0xb0,0x06,0x1b,0xb2,0x04,0x02,0x03,0x45,0x58,0x23,0x21,0x1b,0x21,0x59,0x59,0x42,0x2b,0xb0,0x08,0x65,0xb0,0x03,0x24,0x50,0x78,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x2d,0x00,0x4b,0xb8,0x00,0xc8,0x52,0x58,0xb1, 0x01,0x01,0x8e,0x59,0xb0,0x01,0xb9,0x08,0x00,0x08,0x00,0x63,0x70,0xb1,0x00,0x07,0x42,0xb2,0x19,0x01,0x00,0x2a,0xb1,0x00,0x07,0x42,0xb3,0x0d,0x09,0x01,0x0a,0x2a,0xb1,0x00,0x07,0x42,0xb3,0x16,0x06,0x01,0x0a,0x2a,0xb1,0x00,0x08,0x42,0xba,0x03,0x80,0x00,0x01,0x00,0x0b,0x2a,0xb1,0x00,0x09,0x42,0xba,0x00,0x80,0x00,0x01,0x00, 0x0b,0x2a,0xb9,0x00,0x03,0x00,0x00,0x44,0xb1,0x24,0x01,0x88,0x51,0x58,0xb0,0x40,0x88,0x58,0xb9,0x00,0x03,0x00,0x64,0x44,0xb1,0x28,0x01,0x88,0x51,0x58,0xb8,0x08,0x00,0x88,0x58,0xb9,0x00,0x03,0x00,0x00,0x44,0x59,0x1b,0xb1,0x27,0x01,0x88,0x51,0x58,0xba,0x08,0x80,0x00,0x01,0x04,0x40,0x88,0x63,0x54,0x58,0xb9,0x00,0x03,0x00, 0x00,0x44,0x59,0x59,0x59,0x59,0x59,0xb3,0x10,0x06,0x01,0x0e,0x2a,0xb8,0x01,0xff,0x85,0xb0,0x04,0x8d,0xb1,0x02,0x00,0x44,0xb3,0x05,0x64,0x06,0x00,0x44,0x44,0x00, }; read_only global String8 rd_icon_font_bytes = {rd_icon_font_bytes__data, sizeof(rd_icon_font_bytes__data)}; read_only global U8 rd_default_main_font_bytes__data[] = { 0x00,0x01,0x00,0x00,0x00,0x18,0x01,0x00,0x00,0x04,0x00,0x80,0x44,0x53,0x49,0x47,0x63,0xbc,0x04,0x48,0x00,0x0c,0x94,0x20,0x00,0x00,0x23,0xa0,0x47,0x44,0x45,0x46,0xb9,0xab,0xc5,0xc1,0x00,0x0c,0xb7,0xc0,0x00,0x00,0x03,0x58,0x47,0x50,0x4f,0x53,0x5b,0xad,0x7e,0xc2,0x00,0x0c,0xbb,0x18,0x00,0x01,0x4c,0xc8,0x47,0x53,0x55,0x42, 0x62,0x6c,0x1b,0xf3,0x00,0x0e,0x07,0xe0,0x00,0x00,0x8d,0x2e,0x4c,0x54,0x53,0x48,0x69,0x2b,0xe4,0xa7,0x00,0x00,0x55,0xe8,0x00,0x00,0x14,0xe4,0x4d,0x45,0x52,0x47,0x00,0x16,0x00,0x01,0x00,0x0e,0x95,0x10,0x00,0x00,0x00,0x0c,0x4f,0x53,0x2f,0x32,0x5f,0x62,0x3d,0x91,0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x60,0x56,0x44,0x4d,0x58, 0x76,0x58,0x7d,0xd3,0x00,0x00,0x6a,0xcc,0x00,0x00,0x05,0xe0,0x63,0x6d,0x61,0x70,0x33,0x66,0x8a,0xbf,0x00,0x01,0xd3,0xd8,0x00,0x00,0x1c,0xe4,0x63,0x76,0x74,0x20,0x82,0x03,0x5d,0xdb,0x00,0x02,0x03,0x58,0x00,0x00,0x0a,0x22,0x66,0x70,0x67,0x6d,0x49,0x44,0xd8,0x67,0x00,0x01,0xf0,0xbc,0x00,0x00,0x0a,0x5c,0x67,0x61,0x73,0x70, 0x00,0x1b,0x00,0x23,0x00,0x0c,0x94,0x10,0x00,0x00,0x00,0x10,0x67,0x6c,0x79,0x66,0x2b,0xa3,0xa5,0xc9,0x00,0x02,0x61,0x00,0x00,0x09,0x4b,0xfc,0x68,0x64,0x6d,0x78,0xf0,0x92,0x4d,0xb8,0x00,0x00,0x70,0xac,0x00,0x01,0x63,0x2c,0x68,0x65,0x61,0x64,0xf3,0x00,0x6d,0x9b,0x00,0x00,0x01,0x8c,0x00,0x00,0x00,0x36,0x68,0x68,0x65,0x61, 0x14,0x0e,0x1d,0xa4,0x00,0x00,0x01,0xc4,0x00,0x00,0x00,0x24,0x68,0x6d,0x74,0x78,0x5e,0x06,0x4f,0x2c,0x00,0x00,0x02,0x68,0x00,0x00,0x53,0x80,0x6b,0x65,0x72,0x6e,0xcc,0xce,0xe6,0xda,0x00,0x0b,0xac,0xfc,0x00,0x00,0xc2,0x6a,0x6c,0x6f,0x63,0x61,0x5a,0x85,0x46,0xd0,0x00,0x02,0x0d,0x7c,0x00,0x00,0x53,0x84,0x6d,0x61,0x78,0x70, 0x1a,0xb0,0x0d,0xea,0x00,0x00,0x01,0xe8,0x00,0x00,0x00,0x20,0x6d,0x65,0x74,0x61,0x4d,0x44,0xb7,0xb7,0x00,0x0e,0x95,0x1c,0x00,0x00,0x00,0x80,0x6e,0x61,0x6d,0x65,0x4e,0xc3,0x16,0xb3,0x00,0x0c,0x6f,0x68,0x00,0x00,0x24,0x88,0x70,0x6f,0x73,0x74,0xff,0x51,0x00,0x77,0x00,0x0c,0x93,0xf0,0x00,0x00,0x00,0x20,0x70,0x72,0x65,0x70, 0x93,0xee,0x1e,0xb9,0x00,0x01,0xfb,0x18,0x00,0x00,0x08,0x40,0x00,0x01,0x00,0x00,0x00,0x05,0x9e,0xb8,0xa0,0x2c,0x85,0x86,0x5f,0x0f,0x3c,0xf5,0x00,0x1b,0x08,0x00,0x00,0x00,0x00,0x00,0xaf,0xf5,0x3c,0xaf,0x00,0x00,0x00,0x00,0xd8,0x6f,0x46,0x1c,0xfb,0x6b,0xfc,0xb6,0x0f,0xfe,0x0a,0x63,0x00,0x00,0x00,0x09,0x00,0x01,0x00,0x01, 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x08,0xa2,0xfd,0xfe,0x00,0x00,0x0f,0xf4,0xfb,0x6b,0xfa,0xd1,0x0f,0xfe,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x01,0x00,0x00,0x14,0xe0,0x02,0xb9,0x00,0x20,0x00,0xa3,0x00,0x07,0x00,0x02,0x00,0x10,0x00,0x2f,0x00,0x86,0x00,0x00, 0x05,0x0e,0x0a,0x5c,0x00,0x04,0x00,0x01,0x00,0x03,0x04,0x4f,0x01,0x90,0x00,0x05,0x00,0x08,0x05,0x9a,0x05,0x33,0x00,0x00,0x01,0x1b,0x05,0x9a,0x05,0x33,0x00,0x00,0x03,0xd1,0x00,0x66,0x02,0x12,0x08,0x05,0x02,0x0b,0x05,0x02,0x04,0x02,0x04,0x02,0x02,0x03,0xe4,0x00,0x2e,0xff,0xc0,0x00,0xe4,0x7f,0x00,0x00,0x00,0x09,0x00,0x00, 0x00,0x00,0x4d,0x53,0x20,0x20,0x00,0x40,0x00,0x0d,0xff,0xfd,0x05,0xd3,0xfe,0x51,0x01,0x0d,0x08,0xa2,0x02,0x02,0x20,0x00,0x01,0xff,0x00,0x00,0x00,0x00,0x04,0x00,0x05,0x9a,0x00,0x00,0x00,0x20,0x00,0x17,0x05,0x2a,0x00,0xa6,0x00,0x00,0x00,0x00,0x00,0xc7,0x00,0x00,0x02,0x31,0x00,0x00,0x02,0x46,0x00,0xb4,0x03,0x23,0x00,0xa3, 0x04,0xba,0x00,0x21,0x04,0x50,0x00,0xa2,0x06,0x8c,0x00,0x50,0x06,0x67,0x00,0x77,0x01,0xd7,0x00,0xa3,0x02,0x6a,0x00,0x8c,0x02,0x6a,0x00,0x16,0x03,0x56,0x00,0x4c,0x05,0x79,0x00,0xe8,0x01,0xbc,0x00,0x27,0x03,0x33,0x00,0x90,0x01,0xbc,0x00,0x70,0x03,0x1e,0xff,0xe4,0x04,0x50,0x00,0x56,0x04,0x50,0x00,0xe4,0x04,0x50,0x00,0x6d, 0x04,0x50,0x00,0x7b,0x04,0x50,0x00,0x0e,0x04,0x50,0x00,0xa4,0x04,0x50,0x00,0x6f,0x04,0x50,0x00,0x62,0x04,0x50,0x00,0x5a,0x04,0x50,0x00,0x5e,0x01,0xbc,0x00,0x70,0x01,0xbc,0x00,0x27,0x05,0x79,0x01,0x10,0x05,0x79,0x00,0xe8,0x05,0x79,0x01,0x10,0x03,0x96,0x00,0x83,0x07,0xa4,0x00,0xac,0x05,0x29,0x00,0x16,0x04,0x96,0x00,0xbc, 0x04,0xf4,0x00,0x5e,0x05,0x9c,0x00,0xbc,0x04,0x0c,0x00,0xbc,0x03,0xe8,0x00,0xbc,0x05,0x7d,0x00,0x5e,0x05,0xae,0x00,0xbc,0x02,0x21,0x00,0xbc,0x02,0xdb,0x00,0x14,0x04,0xa4,0x00,0xbc,0x03,0xc4,0x00,0xbc,0x07,0x2f,0x00,0xbc,0x05,0xfc,0x00,0xbc,0x06,0x08,0x00,0x5e,0x04,0x7b,0x00,0xbc,0x06,0x08,0x00,0x5e,0x04,0xc9,0x00,0xbc, 0x04,0x40,0x00,0x79,0x04,0x31,0x00,0x29,0x05,0x7f,0x00,0xaa,0x04,0xf8,0x00,0x12,0x07,0x79,0x00,0x1a,0x04,0xb8,0x00,0x1a,0x04,0x6c,0x00,0x12,0x04,0x90,0x00,0x21,0x02,0x6a,0x00,0xc8,0x03,0x08,0xff,0xe6,0x02,0x6a,0x00,0x35,0x05,0x79,0x00,0xe6,0x03,0x52,0x00,0x00,0x02,0x25,0x00,0x52,0x04,0x12,0x00,0x5a,0x04,0xb4,0x00,0xa6, 0x03,0xb2,0x00,0x60,0x04,0xb6,0x00,0x60,0x04,0x2f,0x00,0x60,0x02,0x81,0x00,0x35,0x04,0xb6,0x00,0x60,0x04,0x87,0x00,0xa6,0x01,0xf0,0x00,0x90,0x01,0xf0,0xff,0x3a,0x03,0xfa,0x00,0xa6,0x01,0xf0,0x00,0xa6,0x06,0xe4,0x00,0xa6,0x04,0x87,0x00,0xa6,0x04,0xb0,0x00,0x60,0x04,0xb4,0x00,0xa6,0x04,0xb6,0x00,0x60,0x02,0xc8,0x00,0xa6, 0x03,0x65,0x00,0x68,0x02,0xb6,0x00,0x2b,0x04,0x87,0x00,0x90,0x03,0xd5,0x00,0x0e,0x05,0xc8,0x00,0x18,0x03,0xac,0x00,0x1a,0x03,0xdf,0x00,0x0e,0x03,0x9e,0x00,0x21,0x02,0x6a,0x00,0x5c,0x01,0xea,0x00,0xac,0x02,0x6a,0x00,0x42,0x05,0x79,0x00,0xd1,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x16,0x04,0xf4,0x00,0x5e,0x04,0x0c,0x00,0xbc, 0x05,0xfc,0x00,0xbc,0x06,0x08,0x00,0x5e,0x05,0x7f,0x00,0xaa,0x04,0x12,0x00,0x5a,0x04,0x12,0x00,0x5a,0x04,0x12,0x00,0x5a,0x04,0x12,0x00,0x5a,0x04,0x12,0x00,0x5a,0x04,0x12,0x00,0x5a,0x03,0xb2,0x00,0x60,0x04,0x2f,0x00,0x60,0x04,0x2f,0x00,0x60,0x04,0x2f,0x00,0x60,0x04,0x2f,0x00,0x60,0x01,0xf0,0x00,0x58,0x01,0xf0,0xff,0xec, 0x01,0xf0,0xff,0xd3,0x01,0xf0,0xff,0xc9,0x04,0x87,0x00,0xa6,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0x87,0x00,0x90,0x04,0x87,0x00,0x90,0x04,0x87,0x00,0x90,0x04,0x87,0x00,0x90,0x03,0x00,0x00,0x30,0x03,0x04,0x00,0x6c,0x04,0x50,0x00,0xb8,0x04,0x50,0x00,0x6a, 0x03,0x96,0x00,0x83,0x03,0x40,0x00,0xa4,0x03,0xaa,0x00,0x54,0x04,0x5a,0x00,0xa6,0x03,0x33,0x00,0x90,0x07,0x1f,0x01,0x38,0x07,0x1f,0x00,0xa2,0x06,0x2f,0x00,0x4c,0x02,0x42,0x00,0x87,0x03,0x50,0x00,0x7d,0x05,0x7b,0x00,0xe8,0x06,0xe2,0x00,0x0a,0x06,0x08,0x00,0x5e,0x06,0x89,0x00,0x52,0x05,0x79,0x00,0xe8,0x05,0x7b,0x00,0xe8, 0x05,0x7b,0x00,0xe8,0x04,0x50,0x00,0x44,0x04,0x9e,0x00,0xa6,0x04,0x48,0x00,0x4e,0x04,0xef,0x00,0x33,0x06,0x08,0x00,0xbc,0x04,0x51,0x00,0xbe,0x03,0x23,0x00,0x52,0x03,0x72,0x00,0x4e,0x06,0x0a,0x00,0x64,0x06,0xa8,0x00,0x5a,0x04,0xb0,0x00,0x31,0x03,0x96,0x00,0x8f,0x02,0x31,0x00,0x00,0x02,0x46,0x00,0xb4,0x05,0x79,0x00,0xe8, 0x05,0x33,0x00,0x7b,0x04,0x50,0x00,0x5e,0x05,0x7b,0x00,0xd1,0x05,0x28,0x00,0x33,0x04,0x0c,0x00,0x5c,0x04,0x0c,0x00,0x5a,0x05,0xdd,0x00,0x8c,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x16,0x06,0x08,0x00,0x5e,0x07,0x72,0x00,0x5e,0x07,0x6c,0x00,0x60,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x03,0x04,0x00,0x6a,0x03,0x04,0x00,0x6e, 0x01,0xd5,0x00,0x6a,0x01,0xd5,0x00,0x6e,0x05,0x79,0x00,0xe8,0x04,0xab,0x00,0x6c,0x03,0xdf,0x00,0x0e,0x04,0x6c,0x00,0x12,0x01,0x62,0xfe,0xc8,0x04,0x50,0x00,0x66,0x02,0x87,0x00,0x5c,0x02,0x87,0x00,0x5c,0x04,0x70,0x00,0x35,0x04,0x70,0x00,0x35,0x03,0x00,0x00,0x30,0x01,0xbc,0x00,0x70,0x01,0xd5,0x00,0x58,0x03,0x04,0x00,0x58, 0x09,0xae,0x00,0x50,0x05,0x29,0x00,0x16,0x04,0x0c,0x00,0xbc,0x05,0x29,0x00,0x16,0x04,0x0c,0x00,0xbc,0x04,0x0c,0x00,0xbc,0x02,0x21,0x00,0x78,0x02,0x21,0xff,0xfc,0x02,0x21,0xff,0xf1,0x02,0x21,0x00,0x1b,0x06,0x08,0x00,0x5e,0x06,0x08,0x00,0x5e,0x06,0x08,0x00,0x5e,0x05,0x7f,0x00,0xaa,0x05,0x7f,0x00,0xaa,0x05,0x7f,0x00,0xaa, 0x01,0xf0,0x00,0xa6,0x02,0xf8,0x00,0x5c,0x02,0xb2,0x00,0x23,0x02,0x7b,0x00,0x3e,0x02,0x6e,0x00,0x25,0x01,0x9c,0x00,0x6c,0x02,0x3e,0x00,0x52,0x01,0xa4,0x00,0x33,0x02,0x98,0x00,0x40,0x01,0x7b,0x00,0x3e,0x02,0xf8,0x00,0x66,0x03,0xc4,0x00,0x21,0x02,0x31,0x00,0x16,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x90,0x00,0x21, 0x03,0x9e,0x00,0x21,0x01,0xea,0x00,0xac,0x05,0x9c,0x00,0x1c,0x04,0x79,0x00,0x60,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x7b,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x05,0x79,0x00,0xe8,0x05,0x79,0x01,0x0c,0x02,0xcf,0x00,0x50,0x02,0xee,0x00,0x68,0x02,0xee,0x00,0x81,0x07,0x72,0x00,0x50,0x07,0x40,0x00,0x50,0x07,0x9e,0x00,0x81, 0x03,0xe8,0x00,0x1c,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x02,0x21,0x00,0xad,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0xf4,0x00,0x5e,0x03,0xb2,0x00,0x60,0x04,0xf4,0x00,0x5e,0x03,0xb2,0x00,0x60,0x04,0xb6,0x00,0x60,0x03,0x52,0x00,0x00,0x01,0xbc,0x00,0x70,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16, 0x04,0x12,0x00,0x5a,0x05,0x9c,0x00,0xbc,0x05,0x65,0x00,0x60,0x05,0x9c,0x00,0x1c,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x03,0xc4,0x00,0xbc,0x01,0xf0,0x00,0x8e,0x03,0xc4,0x00,0xbc,0x02,0x75,0x00,0xa6,0x03,0xc4,0x00,0xbc,0x02,0x85,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6, 0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0x97,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x04,0x31,0x00,0x29,0x03,0x85,0x00,0x2b,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90, 0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x03,0xc6,0x00,0xbc,0x06,0x08,0x00,0x5e,0x06,0x08,0x00,0x60,0x04,0xea,0x00,0x5a,0x04,0xac,0x00,0x5c,0x03,0x81,0x00,0x52,0x04,0x99,0x00,0x61,0x03,0xe6,0x00,0x22,0x05,0x98,0x00,0x60,0x03,0x52,0x00,0x00, 0x03,0xd7,0x00,0xb4,0x03,0x23,0x00,0x6e,0x08,0xe2,0x00,0xbc,0x04,0xfc,0x00,0xbc,0x03,0xf6,0x00,0x90,0x04,0xd9,0xff,0xd7,0x01,0xd5,0x00,0x82,0x03,0x04,0x00,0x8d,0x06,0x6e,0x00,0x96,0x02,0x96,0x00,0x0e,0x04,0xd5,0x00,0x92,0x02,0xd5,0x00,0x83,0x02,0xd5,0x00,0x83,0x04,0xd5,0x00,0xb2,0x02,0xd5,0x00,0x70,0x05,0x29,0x00,0x16, 0x04,0x12,0x00,0x5a,0x04,0xf4,0x00,0x5e,0x03,0xb2,0x00,0x60,0x04,0xf4,0x00,0x5e,0x03,0xb2,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x05,0x7d,0x00,0x5e, 0x04,0xb6,0x00,0x60,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xae,0x00,0x1c,0x04,0x87,0x00,0x1e,0x02,0x21,0xff,0xd0,0x01,0xf0,0xff,0xad,0x02,0x21,0x00,0x13,0x01,0xf0,0xff,0xef,0x02,0x21,0xff,0xfe,0x01,0xf0,0xff,0xdb,0x02,0x21,0x00,0x50,0x01,0xf0,0x00,0x37,0x02,0xdb,0x00,0x14,0x01,0xf0,0xff,0x3a,0x04,0xa4,0x00,0xbc, 0x03,0xfa,0x00,0xa6,0x03,0xfa,0x00,0xa6,0x03,0xc4,0x00,0xbc,0x01,0xf0,0x00,0x27,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68, 0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x01,0xee,0x00,0xa6,0x05,0x29,0x00,0x16, 0x04,0x12,0x00,0x5a,0x06,0xe2,0x00,0x0a,0x06,0xa8,0x00,0x5a,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x31,0x01,0xbc,0x00,0x70,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x01,0xd5,0x00,0x6e,0x03,0x52,0x00,0x00, 0x04,0x50,0x00,0x6a,0x04,0xcd,0x00,0x55,0x07,0x60,0x00,0x50,0x07,0x60,0x00,0x81,0x07,0x6e,0x00,0x8c,0x07,0x23,0x00,0xa2,0x03,0x1e,0x00,0xdb,0x03,0x1e,0x00,0xdb,0x01,0xbc,0x00,0x27,0x02,0x2e,0x00,0xce,0x02,0x2e,0xff,0xda,0x05,0x29,0x00,0x16,0x04,0x90,0xff,0xc5,0x06,0x31,0xff,0xc5,0x03,0x07,0xff,0xc6,0x06,0x68,0xff,0xd1, 0x05,0x56,0xff,0xb3,0x06,0x9c,0xff,0xd1,0x02,0x22,0xff,0xb2,0x05,0x29,0x00,0x16,0x04,0x96,0x00,0xbc,0x04,0x0c,0x00,0xbc,0x04,0x90,0x00,0x21,0x05,0xae,0x00,0xbc,0x02,0x21,0x00,0xbc,0x04,0xa4,0x00,0xbc,0x05,0x08,0x00,0x18,0x07,0x2f,0x00,0xbc,0x05,0xfc,0x00,0xbc,0x04,0x14,0x00,0x3a,0x06,0x08,0x00,0x5e,0x05,0xb4,0x00,0xbc, 0x04,0x7b,0x00,0xbc,0x04,0x21,0x00,0x2e,0x04,0x31,0x00,0x29,0x04,0x6c,0x00,0x12,0x04,0xb8,0x00,0x1a,0x06,0x35,0x00,0x88,0x06,0x0a,0x00,0x64,0x02,0x21,0xff,0xf1,0x04,0x6c,0x00,0x12,0x04,0xea,0x00,0x5a,0x03,0x81,0x00,0x52,0x04,0x9a,0x00,0x82,0x02,0x22,0x00,0xa6,0x04,0x6c,0x00,0x14,0x04,0x62,0x00,0xa7,0x04,0x27,0x00,0x05, 0x03,0x89,0x00,0x4c,0x04,0x9a,0x00,0x82,0x04,0xb1,0x00,0x61,0x02,0x22,0x00,0xa6,0x04,0x31,0x00,0xa6,0x03,0xfc,0xff,0xfe,0x04,0x9e,0x00,0xa7,0x04,0x35,0x00,0x0c,0x03,0x8f,0x00,0x4d,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0xa1,0x03,0xaf,0x00,0x57,0x04,0x6c,0x00,0x14,0x04,0x4e,0x00,0x0c,0x06,0x00,0x00,0x98,0x06,0x77,0x00,0x77, 0x02,0x22,0xff,0xed,0x04,0x6c,0x00,0x14,0x04,0xb0,0x00,0x60,0x04,0x6c,0x00,0x14,0x06,0x77,0x00,0x77,0x04,0x0c,0x00,0xbc,0x05,0x9a,0x00,0x29,0x03,0xc6,0x00,0xbc,0x04,0xf0,0x00,0x5e,0x04,0x40,0x00,0x79,0x02,0x21,0xff,0xf1,0x07,0xd9,0x00,0x10,0x07,0xde,0x00,0xbc,0x05,0xc8,0x00,0x29,0x04,0xa4,0x00,0xbc,0x04,0x8a,0x00,0x3c, 0x05,0xab,0x00,0xbc,0x05,0x29,0x00,0x16,0x04,0x93,0x00,0xbc,0x04,0x96,0x00,0xbc,0x03,0xc6,0x00,0xbc,0x05,0x8c,0x00,0x0f,0x04,0x0c,0x00,0xbc,0x06,0xef,0xff,0xea,0x04,0x52,0x00,0x60,0x05,0xfe,0x00,0xbc,0x05,0xfe,0x00,0xbc,0x04,0xa4,0x00,0xbc,0x05,0x62,0x00,0x10,0x07,0x2f,0x00,0xbc,0x05,0xae,0x00,0xbc,0x06,0x08,0x00,0x5e, 0x05,0xb4,0x00,0xbc,0x04,0x7b,0x00,0xbc,0x04,0xf4,0x00,0x5e,0x04,0x31,0x00,0x29,0x04,0x8a,0x00,0x3c,0x05,0xd0,0x00,0x5e,0x04,0xb8,0x00,0x1a,0x05,0xf0,0x00,0xbc,0x05,0x4a,0x00,0xa6,0x07,0x98,0x00,0xbc,0x07,0xd7,0x00,0xbc,0x05,0xa5,0x00,0x29,0x06,0x44,0x00,0xbc,0x04,0x9c,0x00,0xbc,0x04,0xee,0x00,0x68,0x08,0x26,0x00,0xbc, 0x04,0xba,0x00,0x3d,0x04,0x12,0x00,0x5a,0x04,0xa2,0x00,0x77,0x04,0x3d,0x00,0xa6,0x03,0x10,0x00,0xa6,0x04,0x60,0x00,0x12,0x04,0x2f,0x00,0x60,0x05,0xf8,0x00,0x04,0x03,0x91,0x00,0x50,0x04,0xa6,0x00,0xa6,0x04,0xa6,0x00,0xa6,0x03,0xfa,0x00,0xa6,0x04,0x37,0x00,0x10,0x05,0x9e,0x00,0xa6,0x04,0x9e,0x00,0xa6,0x04,0xb0,0x00,0x60, 0x04,0x9e,0x00,0xa6,0x04,0xb4,0x00,0xa6,0x03,0xb2,0x00,0x60,0x03,0x48,0x00,0x1e,0x03,0xdf,0x00,0x0e,0x05,0x7d,0x00,0x60,0x03,0xac,0x00,0x1a,0x04,0xcd,0x00,0xa6,0x04,0x85,0x00,0x98,0x06,0x66,0x00,0xa6,0x06,0x98,0x00,0xa6,0x04,0xba,0x00,0x1e,0x05,0xad,0x00,0xa6,0x04,0x08,0x00,0xa6,0x03,0xb2,0x00,0x5a,0x06,0x81,0x00,0xa6, 0x04,0x06,0x00,0x3e,0x04,0x2f,0x00,0x60,0x04,0x9e,0x00,0x27,0x03,0x10,0x00,0xa6,0x03,0xb2,0x00,0x60,0x03,0x65,0x00,0x68,0x01,0xf0,0xff,0xd3,0x06,0x52,0x00,0x10,0x06,0x74,0x00,0xa6,0x04,0x8a,0x00,0x27,0x03,0xfa,0x00,0xa6,0x03,0xdf,0x00,0x0e,0x04,0x9e,0x00,0xa6,0x03,0xc0,0x00,0xbc,0x03,0x20,0x00,0xa6,0x08,0x00,0x00,0x00, 0x08,0xfa,0x00,0xbc,0x05,0x04,0x00,0x11,0x02,0xcf,0x00,0x2f,0x02,0xee,0x00,0x7b,0x02,0xee,0x00,0x4d,0x02,0xee,0x00,0x41,0x01,0xf0,0x00,0xa6,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x72,0x00,0x64,0x06,0x1a,0x00,0x5e,0x04,0xc7,0x00,0x60,0x05,0xaa,0x00,0xaa,0x04,0xb4,0x00,0x90,0x02,0x6e,0x00,0xab,0x02,0xaa,0x00,0xf2, 0x02,0x25,0x00,0x66,0x02,0x25,0x00,0x64,0x03,0xd3,0x00,0x42,0x03,0xd3,0x00,0x42,0x03,0xd3,0x00,0x6c,0x03,0xd3,0x00,0xa9,0x02,0x6e,0x00,0x25,0x02,0x6e,0x00,0x38,0x02,0x6e,0x00,0x25,0x03,0xd3,0x00,0xa9,0x02,0x6e,0x00,0xab,0x03,0xd3,0x00,0xa9,0x02,0x6e,0x00,0x25,0x02,0x6e,0x00,0x38,0x02,0x6e,0x00,0x25,0x03,0xd3,0x00,0xa9, 0x03,0xd3,0x00,0x6c,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0xff,0xe8,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16, 0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc, 0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0x0e,0x04,0x2f,0x00,0x0c,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x02,0x21,0x00,0x9a,0x01,0xf0,0x00,0x88,0x02,0x21,0x00,0xb2,0x01,0xf0,0x00,0x90,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e, 0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x30,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x1a,0x00,0x5e,0x04,0xc7,0x00,0x60,0x06,0x1a,0x00,0x5e,0x04,0xc7,0x00,0x60,0x06,0x1a,0x00,0x5e, 0x04,0xc7,0x00,0x60,0x06,0x1a,0x00,0x5e,0x04,0xc7,0x00,0x60,0x06,0x1a,0x00,0x5e,0x04,0xc7,0x00,0x60,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0xaa,0x00,0xaa,0x04,0xb4,0x00,0x90,0x05,0xaa,0x00,0xaa,0x04,0xb4,0x00,0x90,0x05,0xaa,0x00,0xaa,0x04,0xb4,0x00,0x90,0x05,0xaa,0x00,0xaa, 0x04,0xb4,0x00,0x90,0x05,0xaa,0x00,0xaa,0x04,0xb4,0x00,0x90,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x05,0xfe,0x00,0xbc,0x04,0xa6,0x00,0xa6,0x02,0x21,0x00,0xbc, 0x02,0xdb,0x00,0x14,0x01,0xf0,0x00,0x90,0x01,0xf0,0xff,0x3a,0x04,0x1e,0x00,0x29,0x03,0x48,0x00,0x1e,0x07,0x48,0xff,0xea,0x06,0x3e,0x00,0x04,0x04,0xe6,0x00,0xbc,0x04,0x3e,0x00,0xa6,0x04,0xa4,0x00,0xbc,0x03,0xf6,0x00,0xa6,0x05,0xf0,0x00,0xbc,0x04,0xcd,0x00,0xa6,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x6c,0x00,0x12, 0x03,0xdf,0x00,0x0e,0x05,0x04,0x00,0x1a,0x03,0xf2,0x00,0x1a,0x05,0x3e,0x00,0xa6,0x04,0x85,0x00,0x98,0x05,0x4a,0x00,0xa6,0x04,0x87,0x00,0xa6,0x05,0xc4,0x00,0x56,0x04,0x2f,0x00,0x52,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x02,0x6e,0x00,0x3e,0x02,0x6e,0x00,0x3e,0x02,0x6e,0x00,0x3e,0x02,0x6e,0x00,0x3e,0x03,0x50,0x00,0x7d, 0x03,0x50,0x00,0x7d,0x03,0xd3,0x00,0xa9,0x03,0xd3,0x00,0xa9,0x03,0xd3,0x00,0xa9,0x03,0xd3,0x00,0xa9,0x02,0x25,0x00,0x14,0x02,0x25,0x00,0x14,0x02,0x6e,0x00,0x1e,0x02,0x6e,0x00,0x1e,0x02,0x6e,0x00,0x14,0x02,0x6e,0x00,0x14,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x04,0x96,0x00,0xbc, 0x04,0xb4,0x00,0xa6,0x04,0x96,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x04,0x96,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x04,0xf4,0x00,0x5e,0x03,0xb2,0x00,0x60,0x05,0x9c,0x00,0xbc,0x04,0xb6,0x00,0x60,0x05,0x9c,0x00,0xbc,0x04,0xb6,0x00,0x60,0x05,0x9c,0x00,0xbc,0x04,0xb6,0x00,0x60,0x05,0x9c,0x00,0xbc,0x04,0xb6,0x00,0x60,0x05,0x9c,0x00,0xbc, 0x04,0xb6,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x03,0xe8,0x00,0xbc,0x02,0x81,0x00,0x35,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x05,0xae,0x00,0xbc, 0x04,0x87,0x00,0xa6,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xae,0x00,0xa0,0x04,0x87,0x00,0x8c,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x02,0x21,0xff,0xcf,0x01,0xf0,0xff,0xb9,0x02,0x21,0xff,0xf2,0x01,0xf0,0xff,0xd4,0x04,0xa4,0x00,0xbc,0x03,0xfa,0x00,0xa6,0x04,0xa4,0x00,0xbc, 0x03,0xfa,0x00,0xa6,0x04,0xa4,0x00,0xbc,0x03,0xfa,0x00,0xa6,0x03,0xc4,0x00,0xbc,0x01,0xf0,0x00,0x95,0x03,0xc4,0x00,0xbc,0x01,0xf0,0xff,0xfa,0x03,0xc4,0x00,0xbc,0x01,0xf0,0xff,0xfc,0x03,0xc4,0x00,0xbc,0x01,0xf0,0xff,0xdf,0x07,0x2f,0x00,0xbc,0x06,0xe4,0x00,0xa6,0x07,0x2f,0x00,0xbc,0x06,0xe4,0x00,0xa6,0x07,0x2f,0x00,0xbc, 0x06,0xe4,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e, 0x04,0xb0,0x00,0x60,0x04,0x7b,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x04,0x7b,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x40,0x00,0x79, 0x03,0x65,0x00,0x68,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x05,0x7f,0x00,0xaa, 0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x04,0xf8,0x00,0x12,0x03,0xd5,0x00,0x0e,0x04,0xf8,0x00,0x12,0x03,0xd5,0x00,0x0e,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x07,0x79,0x00,0x1a, 0x05,0xc8,0x00,0x18,0x04,0xb8,0x00,0x1a,0x03,0xac,0x00,0x1a,0x04,0xb8,0x00,0x1a,0x03,0xac,0x00,0x1a,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x04,0x87,0x00,0xa6,0x02,0xb6,0x00,0x2b,0x05,0xc8,0x00,0x18, 0x03,0xdf,0x00,0x0e,0x04,0x12,0x00,0x5a,0x01,0xee,0x00,0x4e,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x16,0x05,0xee,0xff,0xbc,0x05,0xee,0xff,0xbe,0x05,0xee,0xff,0xbc, 0x05,0xee,0xff,0xbe,0x05,0xee,0xff,0xbc,0x05,0xee,0xff,0xbc,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x04,0x90,0xff,0xbd,0x04,0x90,0xff,0xbe,0x05,0xb2,0xff,0xbc,0x05,0xb2,0xff,0xc0,0x05,0xb2,0xff,0xbd,0x05,0xb2,0xff,0xbf,0x04,0x9a,0x00,0x82, 0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x06,0x30,0xff,0xbd,0x06,0x30,0xff,0xbe,0x07,0x56,0xff,0xbc,0x07,0x56,0xff,0xc0,0x07,0x56,0xff,0xbd,0x07,0x56,0xff,0xbf,0x07,0x56,0xff,0xbc,0x07,0x56,0xff,0xbc,0x02,0x22,0x00,0x94, 0x02,0x22,0x00,0x6e,0x02,0x22,0xff,0xdd,0x02,0x22,0xff,0xb3,0x02,0x22,0x00,0x1b,0x02,0x22,0xff,0xea,0x02,0x22,0xff,0xc0,0x02,0x22,0xff,0xc0,0x03,0x06,0xff,0xbd,0x03,0x06,0xff,0xbe,0x03,0xf8,0xff,0xbd,0x03,0xf8,0xff,0xc0,0x04,0x2a,0xff,0xbc,0x04,0x34,0xff,0xbf,0x04,0x2a,0xff,0xbd,0x04,0x2a,0xff,0xbd,0x04,0xb0,0x00,0x60, 0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x06,0x6e,0xff,0xbd,0x06,0x6e,0xff,0xbe,0x07,0xa0,0xff,0xbc,0x07,0xa0,0xff,0xbe,0x07,0xa0,0xff,0xbc,0x07,0xa0,0xff,0xbe,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14, 0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x05,0x56,0xff,0xbe,0x06,0x8c,0xff,0xc0,0x06,0x8c,0xff,0xbf,0x06,0x8c,0xff,0xbc,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x9c,0xff,0xbd, 0x06,0x9c,0xff,0xbe,0x07,0xa6,0xff,0xbc,0x07,0xa6,0xff,0xc0,0x07,0xa6,0xff,0xbd,0x07,0xa6,0xff,0xbf,0x07,0xa6,0xff,0xbc,0x07,0xa6,0xff,0xbc,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x03,0x81,0x00,0x52,0x03,0x81,0x00,0x52,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x02,0x22,0x00,0x34,0x02,0x22,0x00,0xa6,0x04,0xb0,0x00,0x60, 0x04,0xb0,0x00,0x60,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x16,0x05,0xee,0xff,0xbd, 0x05,0xee,0xff,0xc1,0x05,0xee,0xff,0xbd,0x05,0xee,0xff,0xbf,0x05,0xee,0xff,0xbd,0x05,0xee,0xff,0xbc,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x04,0x9a,0x00,0x82,0x06,0x31,0xff,0xbc,0x06,0x30,0xff,0xbe,0x07,0x56,0xff,0xbc, 0x07,0x56,0xff,0xbe,0x07,0x56,0xff,0xbc,0x07,0x56,0xff,0xbe,0x07,0x56,0xff,0xbc,0x07,0x56,0xff,0xbc,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x9c,0xff,0xbc,0x06,0x9c,0xff,0xbe,0x07,0xa6,0xff,0xbc, 0x07,0xa6,0xff,0xbe,0x07,0xa6,0xff,0xbc,0x07,0xa6,0xff,0xbe,0x07,0xa6,0xff,0xbc,0x07,0xa6,0xff,0xbc,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x16,0x05,0x29,0xff,0xfb,0x05,0x29,0x00,0x16, 0x05,0x29,0x00,0x16,0x04,0xb0,0x01,0xe4,0x04,0xb0,0x01,0xba,0x04,0xb0,0x01,0xe4,0x04,0xb0,0x01,0x40,0x04,0xb0,0x01,0x33,0x04,0x9a,0x00,0x83,0x04,0x9a,0x00,0x83,0x04,0x9a,0x00,0x83,0x04,0x9a,0x00,0x83,0x04,0x9a,0x00,0x83,0x04,0x90,0xff,0xac,0x04,0x90,0xff,0xc4,0x06,0x31,0xff,0xac,0x06,0x31,0xff,0xc4,0x05,0xae,0x00,0xbc, 0x04,0xb0,0x01,0x4a,0x04,0xb0,0x01,0x42,0x04,0xb0,0x01,0x33,0x02,0x22,0xff,0xec,0x02,0x22,0xff,0xfa,0x02,0x22,0xff,0xb2,0x02,0x22,0xff,0xb2,0x02,0x22,0xff,0xdf,0x02,0x22,0xff,0xd5,0x02,0x21,0xff,0xfe,0x02,0x21,0x00,0x12,0x02,0xe8,0xff,0xae,0x03,0x07,0xff,0xc6,0x04,0xb0,0x01,0x44,0x04,0xb0,0x01,0x38,0x04,0xb0,0x01,0x33, 0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0xb0,0x00,0xa1,0x04,0xb0,0x00,0xa1,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x12,0x04,0x6c,0x00,0x12,0x05,0x56,0xff,0x96,0x05,0x56,0xff,0xb2,0x05,0x04,0xff,0xbe,0x04,0xb0,0x01,0x02,0x04,0xb0,0x01,0x02,0x04,0xb0,0x01,0xd1, 0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x77,0x00,0x77,0x06,0x9c,0xff,0xac,0x06,0x9c,0xff,0xd1,0x06,0xb3,0xff,0xac,0x06,0x9c,0xff,0xd1,0x06,0x0a,0x00,0x64,0x04,0xb0,0x01,0xd1,0x04,0xb0,0x01,0xe2,0x00,0x00,0xfe,0xe8,0x00,0x00,0xfe,0xc0,0x00,0x00,0xff,0x02,0x00,0x00,0xfe,0x58, 0x00,0x00,0xfe,0xee,0x00,0x00,0xff,0x9e,0x00,0x00,0xfe,0xdd,0x00,0x00,0xff,0x33,0x00,0x00,0xfe,0xdd,0x00,0x00,0xfe,0xe8,0x00,0x00,0xff,0xcb,0x00,0x00,0xff,0x58,0x00,0x00,0xfe,0xdd,0x00,0x00,0xfe,0xee,0x00,0x00,0xfe,0xee,0x00,0x00,0xff,0x8c,0x00,0x00,0xff,0x8c,0x00,0x00,0xff,0x8c,0x00,0x00,0x00,0x2f,0x00,0x00,0xff,0x3e, 0x00,0x00,0xff,0x3e,0x00,0x00,0xff,0x48,0x00,0x00,0xff,0x48,0x00,0x00,0xff,0x16,0x00,0x00,0xff,0x52,0x00,0x00,0xff,0xa6,0x00,0x00,0xff,0x4c,0x00,0x00,0xff,0x4c,0x00,0x00,0xff,0x4c,0x00,0x00,0xff,0x03,0x00,0x00,0xff,0x1a,0x00,0x00,0xff,0x1a,0x00,0x00,0xfe,0xdd,0x00,0x00,0xff,0x35,0x00,0x00,0xff,0x9c,0x00,0x00,0xff,0x56, 0x00,0x00,0xff,0x5d,0x00,0x00,0xff,0xcb,0x00,0x00,0xfe,0x9c,0x00,0x00,0xfe,0xb1,0x00,0x00,0xfe,0xe8,0x00,0x00,0xfe,0xe8,0x00,0x00,0xfe,0xee,0x00,0x00,0xfe,0xe9,0x00,0x00,0xfe,0xc0,0x00,0x00,0xff,0x05,0x00,0x00,0xfe,0x57,0x00,0x00,0xfe,0x57,0x00,0x00,0xfe,0xc0,0x00,0x00,0xff,0x02,0x00,0x00,0xfe,0x58,0x00,0x00,0xfe,0x66, 0x00,0x00,0xfe,0x70,0x00,0x00,0xff,0xa6,0x00,0x00,0xfe,0x9c,0x00,0x00,0xff,0x44,0x00,0x00,0xfe,0xa5,0x00,0x00,0xff,0x30,0x00,0x00,0xff,0x9e,0x00,0x00,0xfe,0x57,0x00,0x00,0xfe,0x70,0x00,0x00,0x00,0x0a,0x00,0x00,0xfe,0xc0,0x00,0x00,0xff,0x9c,0x00,0x00,0xfe,0xaa,0x00,0x00,0xff,0x64,0x00,0x00,0xfe,0x9c,0x00,0x00,0xfe,0x2a, 0x00,0x00,0xff,0x58,0x00,0x00,0xff,0x4c,0x00,0x00,0xfe,0xc0,0x00,0x00,0xfe,0xc0,0x00,0x00,0xfe,0xc0,0x00,0x00,0xfe,0xa8,0x00,0x00,0xff,0x5c,0x00,0x00,0xfd,0x0e,0x00,0x00,0xfc,0xe6,0x00,0x00,0xfd,0xaf,0x04,0xb4,0x00,0x21,0x04,0xe8,0xff,0xac,0x04,0x93,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x04,0x9e,0x00,0x33,0x04,0xb4,0x00,0x21, 0x04,0xf6,0x00,0x6a,0x04,0xf6,0x00,0x5e,0x03,0xba,0x00,0x60,0x05,0x9c,0x00,0x1c,0x05,0xee,0xff,0xac,0x04,0x94,0x00,0x5c,0x04,0xb4,0x00,0x60,0x04,0xbc,0x00,0x60,0x04,0x0e,0x00,0x5a,0x04,0x54,0x00,0x70,0x03,0xe8,0xff,0x9a,0x05,0x89,0x00,0x5e,0x04,0xf8,0x00,0x12,0x06,0xfe,0x00,0xa6,0x02,0x4e,0x00,0xb8,0x02,0x3a,0x00,0x29, 0x04,0xa4,0x00,0xbc,0x03,0xfc,0x00,0xa6,0x01,0xf0,0x00,0x14,0x03,0xfc,0xff,0xfe,0x07,0x23,0x00,0xb8,0x05,0xfc,0xff,0x9a,0x04,0x9a,0x00,0x83,0x06,0x08,0x00,0x5e,0x07,0xc0,0x00,0x5e,0x06,0x52,0x00,0x60,0x04,0xcf,0xff,0xac,0x04,0xb4,0x00,0xa6,0x04,0x9c,0x00,0xbc,0x04,0x40,0x00,0x62,0x03,0x65,0x00,0x56,0x04,0x21,0x00,0x2d, 0x02,0x5e,0xff,0x83,0x02,0xb8,0x00,0x2b,0x04,0x33,0xff,0xcd,0x02,0xb8,0x00,0x2b,0x04,0x33,0x00,0x27,0x06,0x0a,0x00,0x62,0x05,0xb2,0x00,0xb8,0x04,0x8e,0x00,0x0f,0x04,0x23,0x00,0x0e,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x04,0xe2,0x00,0x0a,0x04,0xe2,0x00,0x5e,0x03,0x89,0x00,0x1e,0x03,0x46,0x00,0x0a,0x04,0x50,0x00,0x60, 0x04,0x50,0x00,0x74,0x03,0x0a,0x00,0x48,0x03,0x27,0x00,0x1e,0x04,0x5e,0x00,0xa6,0x01,0xea,0x00,0xac,0x03,0x10,0x00,0xac,0x03,0xa6,0x00,0x33,0x02,0x46,0x00,0xb4,0x09,0xe8,0x00,0xbc,0x09,0x1c,0x00,0xbc,0x08,0x33,0x00,0x60,0x06,0xd9,0x00,0xbc,0x05,0xc2,0x00,0xbc,0x04,0x01,0x00,0xa6,0x08,0x94,0x00,0xbc,0x07,0xbe,0x00,0xbc, 0x06,0x77,0x00,0xa6,0x05,0x29,0x00,0x16,0x04,0x0a,0x00,0x52,0x02,0x21,0xff,0xf7,0x01,0xf0,0xff,0xdf,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa, 0x04,0x87,0x00,0x90,0x04,0x2f,0x00,0x52,0x05,0x29,0x00,0x16,0x04,0x0a,0x00,0x52,0x05,0x29,0x00,0x16,0x04,0x0a,0x00,0x52,0x06,0xe2,0x00,0x0a,0x06,0xa0,0x00,0x52,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x04,0xa4,0x00,0xbc,0x03,0xfa,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60, 0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0xe2,0x00,0x0a,0x03,0x89,0xff,0xdd,0x01,0xf0,0xff,0x3a,0x09,0xe8,0x00,0xbc,0x09,0x1c,0x00,0xbc,0x08,0x33,0x00,0x60,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x07,0xfe,0x00,0xbc,0x05,0x83,0x00,0xbc,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0x29,0x00,0x16,0x04,0x0a,0x00,0x52, 0x05,0x29,0x00,0x16,0x04,0x0a,0x00,0x52,0x04,0x0c,0x00,0x9e,0x04,0x2f,0x00,0x60,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x02,0x21,0xff,0x86,0x01,0xf0,0xff,0x6e,0x02,0x21,0xff,0xf8,0x01,0xf0,0xff,0xe6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0x9a,0x00,0xa0,0x02,0xc8,0x00,0x04, 0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0x9a,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x05,0x7f,0x00,0xaa,0x04,0x87,0x00,0x90,0x04,0x08,0x00,0x10,0x03,0x70,0x00,0x1e,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xdf,0x00,0xbc,0x04,0xb8,0x00,0x3e,0x04,0x89,0x00,0x48,0x04,0x90,0x00,0x21,0x03,0x9e,0x00,0x21,0x05,0x29,0x00,0x16, 0x04,0x0a,0x00,0x52,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x04,0xb0,0x01,0x33,0x04,0x0a,0x01,0x08,0x04,0x87,0x01,0x1c,0x04,0x87,0x01,0x1c,0x04,0xb0,0x01,0x23, 0x04,0x0a,0x00,0x90,0x04,0xb6,0x00,0x60,0x04,0xb4,0x00,0xa6,0x04,0xb6,0x00,0xa6,0x03,0xba,0x00,0x5a,0x03,0xba,0x00,0x60,0x04,0xb6,0x00,0x60,0x04,0xb6,0x00,0x60,0x04,0x2f,0x00,0x52,0x04,0xe6,0x00,0x50,0x03,0x4e,0x00,0x60,0x03,0x4e,0x00,0x5a,0x04,0x0e,0x00,0x5a,0x04,0x68,0x00,0x60,0x02,0x38,0xff,0x81,0x04,0xb6,0x00,0x60, 0x04,0xb6,0x00,0x60,0x04,0x3c,0x00,0x60,0x03,0xd5,0x00,0x0e,0x03,0xa8,0x00,0x0a,0x04,0x87,0x00,0x90,0x04,0x87,0x00,0xa6,0x04,0x87,0x00,0xa6,0x02,0x18,0x00,0x0a,0x02,0x3a,0x00,0x94,0x02,0x90,0x00,0x4c,0x02,0x3e,0xff,0xec,0x03,0x02,0xff,0xec,0x01,0xee,0x00,0xa6,0x04,0xd3,0x00,0xa6,0x06,0xe4,0x00,0xa6,0x06,0xe4,0x00,0xa6, 0x06,0xe4,0x00,0xa6,0x04,0x72,0xff,0x96,0x04,0x72,0x00,0xa6,0x04,0xb0,0x00,0xa6,0x04,0xb0,0x00,0x60,0x05,0x96,0x00,0x60,0x05,0xc4,0x00,0x60,0x05,0x1a,0x00,0x60,0x02,0xc8,0x00,0x0c,0x02,0xc8,0x00,0x0c,0x02,0xc8,0x00,0x0c,0x02,0xc8,0x00,0xa6,0x02,0xc8,0x00,0xa6,0x02,0xae,0x00,0x90,0x02,0xae,0x00,0x0c,0x03,0xa2,0x00,0xa6, 0x03,0xa2,0x00,0xa6,0x03,0x2f,0x00,0x68,0x01,0xfa,0xff,0x92,0x02,0x10,0xff,0x9e,0x02,0x4e,0xff,0xa6,0x02,0x44,0xff,0x44,0x02,0xb8,0x00,0x38,0x02,0xb8,0x00,0x2b,0x04,0xcb,0x00,0x21,0x04,0xc2,0x00,0x60,0x04,0x77,0x00,0x90,0x03,0xd5,0x00,0x0c,0x05,0xc8,0x00,0x18,0x03,0xdf,0x00,0x0c,0x03,0x56,0x00,0x0a,0x03,0x9e,0x00,0x21, 0x04,0x18,0x00,0x21,0x03,0x89,0xff,0xdd,0x03,0x89,0xff,0xea,0x02,0xec,0x00,0x1c,0x02,0xec,0x00,0x04,0x02,0xec,0x00,0x00,0x03,0xba,0x00,0x60,0x04,0xf2,0x00,0x60,0x03,0xdf,0x00,0xa6,0x04,0x62,0x00,0x5c,0x04,0x3c,0x00,0x60,0x04,0x87,0x00,0xa6,0x01,0xee,0xff,0x18,0x03,0xfc,0x00,0x04,0x03,0x14,0x00,0xa6,0x04,0xb6,0x00,0x60, 0x02,0xec,0x00,0x1c,0x02,0xec,0x00,0x04,0x07,0x54,0x00,0x60,0x07,0x98,0x00,0x60,0x07,0xcf,0x00,0x60,0x04,0xe8,0x00,0x2b,0x03,0xcf,0x00,0x2b,0x05,0xbe,0x00,0x2b,0x06,0x58,0x00,0x35,0x04,0xa4,0x00,0x98,0x04,0x8e,0x00,0xa6,0x03,0xf4,0x00,0x31,0x03,0xf4,0x00,0x74,0x04,0x62,0x00,0xa6,0x04,0xba,0x00,0x14,0x04,0x85,0x00,0x12, 0x05,0x6c,0xff,0xb1,0x04,0x85,0x00,0x12,0x05,0x1a,0x00,0x60,0x06,0x6a,0x00,0x00,0x04,0x90,0x00,0x00,0x05,0x9e,0x00,0x56,0x04,0xb0,0x00,0x60,0x04,0xa8,0x00,0x5e,0x03,0xa4,0x00,0x60,0x03,0xfc,0x00,0xbc,0x03,0x9c,0x00,0x90,0x04,0xc4,0x00,0x48,0x04,0x04,0x00,0x33,0x04,0xe4,0x00,0x00,0x03,0xf2,0xff,0x7b,0x07,0x23,0x00,0xb8, 0x06,0xe4,0x00,0xa6,0x04,0xd5,0x00,0x33,0x04,0x14,0x00,0x33,0x05,0x16,0x00,0x00,0x04,0x44,0xff,0xec,0x04,0xe2,0x00,0x48,0x03,0xae,0x00,0x3e,0x04,0xc4,0x00,0x14,0x03,0xe2,0x00,0x14,0x05,0x4c,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0x85,0x00,0x0a,0x03,0x44,0x00,0x00,0x04,0x90,0x00,0x00,0x04,0xa8,0x00,0xa2,0x03,0xb2,0x00,0x60, 0x01,0xf0,0xff,0x3a,0x06,0x08,0x00,0x5e,0x03,0xbc,0x00,0x60,0x03,0xbc,0x00,0x60,0x06,0xe8,0x00,0x1e,0x05,0x6c,0x00,0x1e,0x05,0x2b,0x00,0x29,0x04,0xa4,0x00,0x29,0x07,0x44,0x00,0xbc,0x05,0xb8,0x00,0xa6,0x05,0x52,0x00,0x16,0x03,0xfe,0x00,0x0c,0x06,0xfc,0x00,0xbc,0x05,0x87,0x00,0xa6,0x05,0xd3,0x00,0x29,0x04,0x85,0x00,0x1e, 0x07,0x70,0x00,0xbc,0x05,0xfe,0x00,0xa6,0x04,0x52,0x00,0x31,0x03,0x99,0x00,0x21,0x06,0x44,0x00,0x66,0x06,0x14,0x00,0x66,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x05,0xc2,0x00,0x12,0x04,0xa0,0x00,0x0e,0x05,0xc2,0x00,0x12,0x04,0xa0,0x00,0x0e,0x0a,0x7f,0x00,0x5e,0x08,0xf2,0x00,0x58,0x06,0x9c,0x00,0x5e,0x05,0x33,0x00,0x60, 0x09,0x08,0x00,0x5e,0x07,0x27,0x00,0x60,0x06,0xe8,0x00,0x1e,0x05,0x6c,0x00,0x1e,0x04,0xb4,0x00,0x5e,0x03,0x81,0x00,0x60,0x04,0x00,0x00,0x2d,0x03,0x27,0x00,0x52,0x03,0x4c,0x00,0x5e,0x00,0x00,0xff,0x90,0x00,0x00,0xff,0x86,0x07,0xe2,0x00,0x21,0x07,0x98,0x00,0x35,0x04,0x9c,0x00,0x29,0x04,0x0c,0x00,0x2d,0x04,0x7c,0x00,0xbc, 0x04,0xb5,0x00,0xa6,0x04,0x8c,0x00,0xbc,0x04,0x04,0x00,0xa6,0x04,0x52,0x00,0x60,0x03,0xa2,0x00,0x58,0x04,0xa4,0x00,0x12,0x03,0xfa,0x00,0x27,0x05,0xae,0x00,0x29,0x04,0xa6,0x00,0x1e,0x06,0xb8,0x00,0xbc,0x05,0x4e,0x00,0xa6,0x08,0x16,0x00,0xbc,0x06,0xb0,0x00,0xa6,0x05,0xc6,0x00,0x5e,0x04,0x74,0x00,0x60,0x04,0xf4,0x00,0x5e, 0x03,0xb2,0x00,0x60,0x04,0x35,0x00,0x29,0x03,0x48,0x00,0x1e,0x06,0xfa,0x00,0x29,0x05,0x79,0x00,0x1e,0x05,0x7f,0x00,0xa6,0x04,0xb4,0x00,0x98,0x06,0xae,0x00,0x29,0x05,0x10,0x00,0x29,0x06,0xae,0x00,0x29,0x05,0x10,0x00,0x29,0x02,0x21,0x00,0xbc,0x06,0xef,0xff,0xea,0x05,0xf8,0x00,0x04,0x04,0xa4,0x00,0xbe,0x04,0x0c,0x00,0xa6, 0x05,0xae,0x00,0xbc,0x04,0x9e,0x00,0xa6,0x05,0x3e,0x00,0xa6,0x04,0x85,0x00,0x98,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x05,0x29,0x00,0x16,0x04,0x12,0x00,0x5a,0x06,0xe2,0x00,0x0a,0x06,0xa8,0x00,0x5a,0x04,0x0c,0x00,0xbc,0x04,0x2f,0x00,0x60,0x05,0xc4,0x00,0x56,0x04,0x2f,0x00,0x52,0x05,0xc4,0x00,0x56,0x04,0x2f,0x00,0x52, 0x06,0xef,0xff,0xea,0x05,0xf8,0x00,0x04,0x04,0x52,0x00,0x60,0x03,0x91,0x00,0x50,0x04,0x2f,0x00,0x52,0x03,0x89,0xff,0xdd,0x05,0xfe,0x00,0xbc,0x04,0xa6,0x00,0xa6,0x05,0xfe,0x00,0xbc,0x04,0xa6,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x04,0xee,0x00,0x68,0x03,0xb2,0x00,0x5a, 0x04,0x8a,0x00,0x3c,0x03,0xdf,0x00,0x0e,0x04,0x8a,0x00,0x3c,0x03,0xdf,0x00,0x0e,0x04,0x8a,0x00,0x3c,0x03,0xdf,0x00,0x0e,0x05,0x4a,0x00,0xa6,0x04,0x85,0x00,0x98,0x06,0x44,0x00,0xbc,0x05,0xad,0x00,0xa6,0x04,0x8e,0x00,0x56,0x04,0xb6,0x00,0x60,0x06,0xd3,0x00,0x64,0x06,0xe2,0x00,0x60,0x06,0x70,0x00,0x29,0x05,0xc6,0x00,0x1e, 0x04,0x77,0x00,0x29,0x03,0xcb,0x00,0x1e,0x07,0x3e,0x00,0x18,0x06,0x5e,0x00,0x14,0x07,0xea,0x00,0xbc,0x06,0xcb,0x00,0xa6,0x05,0xb8,0x00,0x5e,0x04,0x3e,0x00,0x60,0x05,0x66,0x00,0x29,0x04,0xc8,0x00,0x1e,0x04,0xb0,0x01,0x33,0x04,0x87,0x01,0x1c,0x04,0x87,0x01,0x1c,0x04,0x0a,0x01,0x08,0x04,0xb0,0x01,0x23,0x02,0xaa,0xff,0x8c, 0x00,0x00,0xff,0x27,0x00,0x00,0xff,0x21,0x00,0x00,0xff,0xcb,0x00,0x00,0xff,0x04,0x00,0x00,0xff,0x2b,0x00,0x00,0xff,0x2b,0x00,0x00,0xff,0x14,0x00,0x00,0xff,0x2b,0x00,0x00,0xfe,0x96,0x00,0x00,0xff,0x9c,0x00,0x00,0xff,0x6a,0x00,0x00,0xff,0x10,0x00,0x00,0xff,0x23,0x01,0xd5,0x00,0x72,0x01,0xd5,0x00,0x72,0x04,0xb0,0x01,0xba, 0x02,0xb0,0x00,0x66,0x02,0xb0,0x00,0x66,0x01,0x4e,0xff,0xbe,0x01,0xb2,0x00,0x66,0x01,0xb2,0x00,0x0a,0x01,0xb2,0x00,0x0a,0x02,0x3e,0x00,0x66,0x03,0x2d,0x00,0x14,0x02,0x3a,0x00,0x0a,0x01,0xd5,0x00,0x82,0x03,0x04,0x00,0x8d,0x01,0xc7,0x00,0x6a,0x01,0xc7,0x00,0x6e,0x01,0xc7,0x00,0x6e,0x02,0xaa,0x00,0xfb,0x02,0xaa,0x00,0xfb, 0x01,0xba,0x00,0x14,0x01,0xba,0x00,0x0a,0x04,0xac,0x00,0x72,0x04,0xac,0x00,0x70,0x04,0xac,0x00,0x66,0x04,0xac,0x00,0x66,0x02,0xaa,0x01,0x20,0x02,0x42,0x00,0x87,0x02,0x25,0x00,0x52,0x02,0xaa,0x01,0x20,0x02,0x7b,0x00,0x3e,0x02,0x25,0x00,0x52,0x02,0x42,0x00,0x87,0x02,0x39,0x00,0xb6,0x02,0x39,0x00,0xb6,0x02,0xaa,0x00,0xfb, 0x02,0xaa,0x00,0xfb,0x02,0xaa,0x00,0xa0,0x02,0xaa,0x00,0xa0,0x02,0xaa,0x00,0xa0,0x02,0x7b,0x00,0x3e,0x02,0xaa,0x00,0x79,0x02,0xb0,0x00,0x48,0x02,0x56,0x00,0x0a,0x01,0x4c,0x00,0x66,0x01,0xf0,0x00,0x3e,0x02,0x42,0x00,0x14,0x01,0xba,0x00,0x0a,0x03,0x10,0x00,0x96,0x03,0x10,0x00,0x96,0x03,0x10,0x00,0x96,0x03,0x10,0x00,0x96, 0x03,0x10,0x00,0x96,0x02,0xaa,0x00,0x62,0x02,0xaa,0x00,0x62,0x02,0xaa,0x00,0x3c,0x03,0x52,0x00,0x00,0x02,0xaa,0x00,0x6e,0x01,0xf0,0xff,0x3a,0x02,0x18,0x00,0x0a,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x43,0x04,0x57,0x00,0x43,0x04,0x57,0x00,0x43,0x04,0x57,0x00,0x43, 0x04,0x57,0x00,0x43,0x03,0x10,0x00,0x43,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x03,0x10,0x00,0x2f,0x04,0x57,0x00,0x25,0x04,0x57,0x00,0x25,0x04,0x57,0x00,0x25,0x04,0x57,0x00,0x25,0x04,0x57,0x00,0x25,0x03,0x10,0x00,0x2f,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a, 0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x03,0x10,0x00,0x1a,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x03,0x10,0x00,0x42,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42, 0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x03,0x10,0x00,0x42,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x03,0x10,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x03,0x10,0x00,0x2f, 0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x03,0x10,0x00,0x26,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x03,0x10,0x00,0x42,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x42, 0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x03,0x10,0x00,0x42,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x04,0x57,0x00,0x26,0x03,0x10,0x00,0x26,0x04,0x57,0x00,0x23,0x04,0x57,0x00,0x23,0x04,0x57,0x00,0x23,0x04,0x57,0x00,0x23,0x04,0x57,0x00,0x23, 0x03,0x10,0x00,0x23,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x03,0x10,0x00,0x2f,0x04,0x57,0x00,0x4b,0x04,0x57,0x00,0x4b,0x04,0x57,0x00,0x4b,0x04,0x57,0x00,0x4b,0x04,0x57,0x00,0x4b,0x03,0x10,0x00,0x4b,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96, 0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x04,0x57,0x00,0x42,0x03,0x10,0x00,0x42,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x04,0x57,0x00,0x1a,0x03,0x10,0x00,0x1a,0x04,0x57,0x00,0x24,0x04,0x57,0x00,0x24,0x04,0x57,0x00,0x24, 0x04,0x57,0x00,0x24,0x04,0x57,0x00,0x24,0x03,0x10,0x00,0x24,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x04,0x57,0x00,0x2f,0x03,0x10,0x00,0x2f,0x04,0x57,0x00,0x4e,0x04,0x57,0x00,0x4e,0x04,0x57,0x00,0x4e,0x04,0x57,0x00,0x4e,0x04,0x57,0x00,0x4e,0x03,0x10,0x00,0x4e,0x04,0x57,0x00,0x96, 0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x04,0x57,0x00,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x54,0x00,0x00,0xff,0x54,0x00,0x00,0xfd,0xa7,0x00,0x00,0xff,0x68,0x05,0x27,0x00,0x60,0x02,0x60,0x00,0xa6,0x05,0x0e,0x00,0xa6,0x02,0xb6,0x00,0x2b,0x04,0xbc,0xff,0xdb,0x04,0xbc,0xff,0xdb,0x02,0xaa,0x00,0x85,0x02,0xaa,0x00,0x85, 0x02,0xaa,0x00,0xc8,0x02,0xaa,0x00,0xc8,0x02,0xaa,0x00,0x87,0x02,0x25,0x00,0x52,0x02,0x98,0x00,0x28,0x02,0x98,0x00,0x28,0x02,0xb2,0x00,0x23,0x02,0x39,0x00,0xad,0x02,0xaa,0x00,0x98,0x02,0xaa,0x00,0x98,0x02,0xaa,0x00,0x98,0x02,0xaa,0x00,0x98,0x02,0xaa,0xff,0xf0,0x02,0xaa,0xff,0xf2,0x02,0xaa,0x00,0x3a,0x00,0x00,0xff,0x74, 0x00,0x00,0xff,0xa6,0x00,0x00,0xfe,0xee,0x00,0x00,0xff,0x30,0x00,0x00,0xff,0x74,0x00,0x00,0xff,0x74,0x00,0x00,0xfe,0xa1,0x00,0x00,0xff,0xa6,0x00,0x00,0xfc,0xe6,0x00,0x00,0xfc,0xe6,0x00,0x00,0xfc,0xe6,0x04,0x7b,0x00,0xbc,0x04,0xb4,0x00,0xa6,0x03,0xc0,0x00,0x0a,0x05,0x4a,0x00,0x00,0x06,0xa2,0x00,0x52,0x03,0xdf,0x00,0x3e, 0x03,0xb2,0x00,0x60,0x04,0x66,0x00,0xa6,0x04,0x70,0x00,0x3c,0x03,0x56,0x00,0xa6,0x03,0x4c,0x00,0x5a,0x01,0xee,0x00,0x8e,0x02,0x62,0x00,0x14,0x03,0xfa,0x00,0xa6,0x03,0x23,0x00,0x42,0x05,0x9e,0x00,0xa6,0x04,0xa6,0x00,0xa6,0x04,0xb0,0x00,0x60,0x03,0xcd,0x00,0x5a,0x04,0xf2,0x00,0x60,0x04,0xf2,0x00,0x60,0x04,0xf2,0x00,0x4c, 0x07,0x70,0x00,0x52,0x04,0x4a,0x00,0x60,0x04,0xc2,0x00,0x60,0x04,0xc2,0x00,0x60,0x03,0xb2,0x00,0xa6,0x03,0xa2,0x00,0x1e,0x03,0xa2,0x00,0x1e,0x03,0x48,0x00,0x1e,0x04,0x46,0x00,0x90,0x04,0x89,0x00,0x66,0x05,0xbe,0x00,0x3e,0x04,0x89,0x00,0x66,0x03,0xd5,0x00,0x0e,0x05,0xc8,0x00,0x18,0x03,0x9e,0x00,0x21,0x03,0x58,0x00,0x50, 0x03,0x4a,0x00,0x50,0x04,0x3a,0x00,0x14,0x03,0x10,0x00,0xa6,0x03,0xc0,0x00,0x0a,0x04,0x9e,0x00,0xa6,0x03,0xb2,0x00,0xa6,0x04,0xba,0x00,0x60,0x04,0x7d,0x00,0x0a,0x02,0xe2,0x00,0x0a,0x03,0xe6,0xff,0xf6,0x02,0xc6,0x00,0x7b,0x02,0xdb,0x00,0x23,0x03,0x46,0x00,0x7b,0x02,0x72,0x00,0x7b,0x02,0x72,0x00,0x48,0x03,0x46,0x00,0x3e, 0x03,0x64,0x00,0x7b,0x01,0x79,0x00,0x7b,0x01,0xd3,0x00,0x0a,0x02,0xd5,0x00,0x7b,0x02,0x44,0x00,0x7b,0x04,0x31,0x00,0x7b,0x03,0x81,0x00,0x7b,0x03,0x81,0x00,0x7b,0x03,0x68,0x00,0x3e,0x03,0x0c,0x00,0x3e,0x02,0xb6,0x00,0x7b,0x02,0xc2,0x00,0x7b,0x02,0x52,0x00,0x0a,0x03,0x50,0x00,0x74,0x04,0x35,0x00,0x10,0x02,0x85,0x00,0x3e, 0x02,0x85,0x00,0x66,0x02,0xc6,0x00,0x3e,0x03,0xdf,0x00,0x48,0x02,0xc6,0x00,0x66,0x02,0xc6,0x00,0x3e,0x02,0x7d,0x00,0x3e,0x02,0x7d,0x00,0x48,0x02,0x1c,0x00,0x3e,0x02,0x1c,0x00,0x42,0x02,0xc6,0x00,0x3e,0x01,0x4e,0x00,0x58,0x02,0x6a,0x00,0x66,0x03,0xfa,0x00,0x66,0x02,0xb0,0x00,0x66,0x02,0xbc,0x00,0x3e,0x02,0x29,0x00,0x3e, 0x02,0xbc,0x00,0x3e,0x02,0xbc,0x00,0x3e,0x02,0xbe,0x00,0x66,0x01,0x9c,0x00,0x0a,0x02,0xa6,0x00,0x5c,0x02,0x9c,0x00,0x3e,0x03,0xfa,0x00,0x60,0x02,0x40,0x00,0x0a,0x02,0x8e,0x00,0x14,0x02,0xac,0x00,0x60,0x02,0x56,0xff,0xec,0x02,0xbc,0x00,0x3e,0x03,0x44,0x00,0x3e,0x02,0x62,0xff,0xf6,0x01,0x4e,0x00,0x58,0x01,0xb2,0x00,0x66, 0x02,0xa6,0x00,0x5c,0x02,0x40,0x00,0x0a,0x02,0xac,0x00,0x60,0x02,0x56,0xff,0xec,0x02,0xc6,0x00,0x66,0x03,0x44,0x00,0x3e,0x02,0x62,0xff,0xf6,0x04,0xa6,0x00,0xfc,0x01,0x4e,0x00,0x58,0x02,0xc6,0x00,0x66,0x04,0x57,0x00,0x42,0x07,0x04,0x00,0x8f,0x04,0xfe,0x00,0x74,0x04,0x50,0x00,0x76,0x04,0x50,0x00,0x76,0x06,0xe4,0x00,0xa6, 0x05,0x2a,0x00,0x23,0x06,0xda,0x00,0xbc,0x05,0xf4,0x00,0x14,0x04,0x37,0x00,0x64,0x04,0xb6,0x00,0x60,0x04,0x00,0x00,0x2a,0x03,0x96,0x00,0x29,0x09,0x00,0x00,0x2c,0x03,0xa4,0x00,0x30,0x04,0xb5,0x00,0x26,0x07,0x1f,0x00,0xa2,0x07,0x7a,0x00,0x60,0x07,0x7a,0x00,0x60,0x05,0x06,0x00,0x16,0x05,0x29,0x00,0x16,0x04,0xf4,0x00,0x16, 0x03,0xb2,0x00,0x21,0x03,0xc4,0x00,0x12,0x04,0x31,0xff,0xef,0x03,0x65,0x00,0x68,0x03,0x9e,0x00,0x21,0x04,0x16,0x00,0x30,0x01,0x9c,0x00,0x6c,0x00,0x00,0xff,0x2b,0x00,0x00,0xfe,0xbd,0x00,0x00,0xff,0x60,0x00,0x00,0xfc,0xe6,0x04,0xb0,0x00,0x21,0x04,0xf4,0x00,0x68,0x04,0xf4,0x00,0x5e,0x04,0xf4,0x00,0x68,0x03,0xc6,0x00,0xbc, 0x03,0x10,0x00,0xa6,0x04,0xb4,0xff,0xbb,0x04,0xb6,0x00,0x60,0x02,0x81,0xff,0xf8,0x06,0xe4,0xff,0xc0,0x04,0x87,0xff,0xc0,0x04,0xb4,0xff,0xbb,0x02,0xc8,0xff,0xbb,0x02,0xae,0xff,0xa5,0x03,0xb5,0x00,0x27,0x02,0xb6,0xff,0xef,0x03,0x9e,0x00,0x21,0x04,0xb6,0x00,0xa6,0x03,0xb1,0x00,0x7a,0x04,0x9f,0x00,0x60,0x07,0x3d,0x00,0x16, 0x05,0x2e,0x00,0x16,0x02,0x90,0x00,0x4a,0x02,0x22,0xff,0xfb,0x04,0xb4,0x00,0x22,0x04,0x46,0x00,0x22,0x04,0xc2,0x00,0x14,0x04,0xb4,0x00,0xa6,0x04,0xb6,0x00,0x60,0x02,0x81,0x00,0x35,0x04,0xb6,0x00,0x60,0x03,0xfa,0x00,0xa6,0x01,0xf0,0x00,0x5c,0x06,0xe4,0x00,0xa6,0x04,0x87,0x00,0xa6,0x04,0xb4,0x00,0xa6,0x02,0xc8,0x00,0x5c, 0x03,0x65,0x00,0x68,0x03,0x76,0xff,0x92,0x03,0xd5,0x00,0x0e,0x03,0xac,0x00,0x1a,0x03,0x9e,0x00,0x21,0x04,0x12,0x00,0x5a,0x04,0xb6,0x00,0x60,0x04,0xb6,0x00,0x60,0x04,0x2f,0x00,0x60,0x03,0x81,0x00,0x52,0x03,0x91,0x00,0x50,0x05,0xe0,0x00,0x52,0x01,0xf0,0x00,0x90,0x03,0xba,0x00,0x5a,0x01,0xfa,0xff,0x92,0x04,0x87,0x00,0x90, 0x03,0x89,0xff,0xdd,0x02,0xc6,0x00,0x66,0x02,0x22,0x00,0x3e,0x02,0x26,0x00,0x3d,0x02,0xbd,0x00,0x3e,0x02,0x1c,0x00,0x42,0x01,0x77,0x00,0x0a,0x01,0x4e,0xff,0xdd,0x02,0xc6,0x00,0x3e,0x02,0xa6,0x00,0x5c,0x01,0x4e,0x00,0x0f,0x01,0x74,0x00,0x66,0x01,0x62,0x00,0x11,0x01,0x62,0x00,0x11,0x01,0x4e,0xff,0x87,0x01,0x74,0x00,0x66, 0x01,0x4c,0x00,0x31,0x01,0xcb,0x00,0x66,0x03,0xfa,0x00,0x66,0x03,0xfa,0x00,0x60,0x02,0xb0,0xff,0xbc,0x02,0xb0,0x00,0x66,0x02,0xd0,0x00,0x66,0x02,0xb0,0x00,0x3e,0x02,0xef,0x00,0x3e,0x01,0xd8,0x00,0x42,0x01,0x4e,0xff,0xc9,0x01,0x9c,0x00,0x0a,0x02,0xa6,0x00,0x05,0x02,0xbd,0x00,0x3e,0x02,0xa2,0x00,0x5c,0x02,0x93,0x00,0x5c, 0x02,0x40,0x00,0x0b,0x02,0x17,0x00,0x1a,0x02,0x17,0x00,0x1a,0x02,0x5b,0x00,0x1a,0x02,0x12,0xff,0xfb,0x02,0xbd,0x00,0x3e,0x00,0x00,0xff,0x3e,0x00,0x00,0xff,0x3e,0x00,0x00,0xff,0x9c,0x00,0x00,0xfe,0xdd,0x01,0xbc,0x00,0x70,0x02,0x85,0x00,0x3e,0x02,0x7d,0x00,0x3e,0x02,0xbc,0x00,0x3e,0x02,0x23,0x00,0x12,0x02,0x7d,0x00,0x48, 0x04,0x51,0x00,0x54,0x04,0x51,0x00,0x0c,0x04,0x51,0x00,0x69,0x04,0x51,0x00,0x56,0x02,0xaa,0x00,0x42,0x00,0x00,0xff,0x50,0x00,0x00,0xff,0x50,0x00,0x00,0xff,0x50,0x00,0x00,0xff,0x29,0x03,0xb5,0x00,0x27,0x02,0x7b,0x00,0x3e,0x02,0x23,0x00,0x12,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a, 0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x04,0xea,0x00,0x5a,0x02,0x22,0xff,0xf9,0x02,0x22,0x00,0x02,0x02,0x22,0xff,0xfc,0x02,0x22,0xff,0xe5,0x02,0x22,0xff,0xee,0x02,0x22,0xff,0xee,0x02,0x22,0xff,0xee,0x02,0x22,0xff,0xee,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14, 0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x02,0x22,0xff,0xd3,0x02,0x22,0xff,0xd3,0x02,0x22,0xff,0xd3,0x02,0x22,0xff,0xd3,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x04,0x6c,0x00,0x14,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4, 0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x0a,0xa0,0x00,0xb4,0x04,0x51,0x00,0xbc,0x02,0xee,0x00,0x48,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0x6a,0x00,0xcc,0x02,0x6a,0x00,0x64,0x01,0x60,0x00,0x5b, 0x02,0xee,0x00,0x68,0x02,0xee,0x00,0x81,0x02,0xcf,0x00,0x50,0x02,0xee,0x00,0x48,0x02,0xcf,0x00,0x2f,0x02,0xee,0x00,0x7b,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x4d,0x02,0xee,0x00,0x41,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0x6a,0x00,0xcc,0x02,0x6a,0x00,0x64,0x02,0xee,0x00,0x48, 0x02,0xcf,0x00,0x50,0x02,0xee,0x00,0x68,0x02,0xee,0x00,0x81,0x02,0xcf,0x00,0x2f,0x02,0xee,0x00,0x7b,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x4d,0x02,0xee,0x00,0x41,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0xee,0x00,0x5d,0x02,0x6a,0x00,0xcc,0x02,0x6a,0x00,0x64,0x06,0x46,0x00,0xbc,0x05,0x0d,0x00,0xa6, 0x05,0xaa,0x00,0x10,0x04,0x9f,0x00,0x10,0x05,0xf8,0x00,0xbc,0x05,0x06,0x00,0xa6,0x07,0x78,0x00,0xbc,0x06,0x06,0x00,0xa6,0x04,0x50,0x00,0x5a,0x03,0x04,0x00,0x6e,0x04,0x1d,0x00,0x8d,0x05,0x79,0x00,0xe8,0x04,0x47,0x00,0x5e,0x06,0x8e,0x00,0xbc,0x05,0x9e,0x00,0xa6,0x00,0x00,0xff,0xdc,0x00,0x00,0xff,0x25,0x00,0x00,0xff,0xdc, 0x00,0x00,0xfe,0x51,0x02,0x01,0x00,0xab,0x02,0x01,0x00,0x49,0x02,0x01,0xff,0xa2,0x02,0x01,0x00,0x49,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba, 0x08,0x04,0xff,0xba,0x03,0x56,0x00,0xb9,0x02,0x01,0x00,0x2b,0x04,0x02,0x00,0x2b,0x04,0xad,0x00,0x2b,0x03,0x57,0x00,0x62,0x04,0x02,0x00,0x4f,0x04,0x02,0xff,0xef,0x04,0xad,0xff,0xf4,0x04,0xad,0x00,0x49,0x04,0x02,0x00,0x22,0x08,0x04,0xff,0xba,0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x65,0x04,0xae,0xff,0xba, 0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x65,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x05,0x2a,0x00,0xa6,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x02,0xac,0xff,0xba,0x04,0xae,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x53,0x05,0x58,0x00,0x67,0x04,0x02,0x00,0xa1,0x02,0xac,0xff,0xba,0x06,0xae,0x00,0x9a, 0x04,0x02,0x00,0xa1,0x06,0xae,0x00,0x9a,0x02,0x01,0x00,0x6f,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x04,0xad,0x00,0x49,0x04,0xad,0x00,0x49,0x04,0xad,0xff,0xa2,0x06,0xae,0x00,0x82,0x02,0x01,0x00,0x00,0x04,0xad,0xff,0xa2,0x02,0x01,0x00,0x6f, 0x04,0x02,0x00,0xab,0x03,0x57,0x00,0x5a,0x02,0x01,0xff,0xa2,0x02,0x01,0x00,0x49,0x04,0x02,0x00,0x00,0x02,0x01,0x00,0x49,0x06,0x03,0x00,0x82,0x02,0x01,0x00,0xab,0x07,0x59,0x00,0xab,0x04,0x02,0x00,0xab,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0x02,0x00,0x52, 0x04,0x02,0x00,0x52,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x09,0x5a,0x00,0x9b,0x09,0x5a,0x00,0x9b,0x0a,0xb1,0x00,0x9b,0x0a,0xb1,0x00,0x9b,0x06,0xae,0x00,0x19,0x06,0xae,0x00,0x19,0x04,0x02,0x00,0x65,0x04,0x02,0x00,0x65,0x01,0x56,0xff,0xba,0x08,0x04,0x00,0xab,0x06,0x03,0x00,0x9b,0x06,0xae,0x00,0xab,0x05,0x58,0x00,0x9b, 0x04,0xad,0x00,0x39,0x05,0x58,0x00,0x9b,0x04,0x02,0x00,0xab,0x04,0x02,0x00,0x00,0x06,0x03,0x00,0x9a,0x06,0x03,0x00,0x9a,0x00,0x00,0x00,0x05,0x00,0x00,0xff,0x33,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x05,0x00,0x00,0xff,0xbf,0x00,0x00,0x00,0x05,0x00,0x00,0xff,0xd4,0x00,0x00,0x00,0x45,0x04,0xad,0x00,0x52,0x02,0x01,0x00,0x52, 0x05,0x2a,0x00,0xa6,0x00,0x00,0xff,0xa2,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x02,0xac,0xff,0xba,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x03,0x57,0x00,0x00, 0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x04,0x02,0x00,0xa1,0x04,0x02,0x00,0xab,0x03,0x56,0x00,0xb9,0x02,0x01,0x00,0x2b,0x04,0x02,0x00,0x2b,0x04,0xad,0x00,0x2b,0x04,0x02,0x00,0x2b,0x04,0xae,0x00,0x72,0x04,0x02,0x00,0x2f, 0x04,0xad,0xff,0xf4,0x04,0xad,0x00,0x49,0x04,0x02,0x00,0x22,0x05,0x58,0x00,0x9b,0x05,0x2a,0x00,0xa6,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0x02,0x00,0x52,0x03,0x57,0x00,0x00,0x05,0x58,0x00,0x9b,0x04,0x02,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0x02,0xff,0xba,0x04,0x02,0x00,0xab,0x04,0x02,0x00,0xab,0x07,0x59,0x00,0x72, 0x02,0xac,0x00,0x72,0x07,0x59,0x00,0x72,0x02,0xac,0x00,0x72,0x02,0x01,0x00,0x2d,0x04,0xae,0x00,0x7c,0x03,0x1d,0x00,0x42,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x08,0x04,0x00,0xa1,0x04,0x02,0x00,0x57,0x00,0x00,0x00,0xc4,0x00,0x00,0xff,0x17,0x00,0x00,0x00,0x10, 0x05,0x2a,0x00,0xa6,0x00,0x00,0xff,0xc2,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x05,0x2a,0x00,0xa6,0x06,0x03,0x00,0x9b,0x05,0x2a,0x00,0xa6,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x49,0x02,0x01,0xff,0x97,0x02,0x01,0xff,0x97,0x02,0x01,0xff,0xc2,0x02,0x01,0xff,0xc2,0x02,0x01,0xff,0xc2,0x02,0x01,0xff,0xc2, 0x03,0x57,0x00,0xab,0x03,0x57,0x00,0xab,0x04,0x02,0x00,0x00,0x04,0x02,0xff,0xe7,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e, 0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x04,0x02,0x00,0x00, 0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x0a,0xb1,0x00,0x9b,0x08,0x04,0xff,0xba,0x0a,0xb1,0x00,0x9b,0x08,0x04,0xff,0xba,0x06,0xae,0x00,0x19,0x04,0x02,0x00,0x65,0x04,0xad,0x00,0x65, 0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x08,0x04,0x00,0xab,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9b, 0x06,0x03,0x00,0x9b,0x08,0xaf,0x00,0x19,0x08,0x04,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab, 0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b, 0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x04,0x58,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x06,0xae,0x00,0x32, 0x07,0x58,0x00,0x1e,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x04,0x02,0x00,0x00,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x00,0x00,0xff,0xa8,0x00,0x00,0xff,0xb7,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x1d,0x00,0x00,0xff,0x2b,0x08,0xfc,0x00,0x2d,0x08,0xad,0x01,0x46, 0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x16,0x00,0x00,0xff,0x2b,0x00,0x00,0xff,0xc9,0x02,0x01,0x00,0x4d,0x03,0x57,0x00,0x21,0x00,0x00,0xff,0x82,0x00,0x00,0x00,0x32,0x04,0xcd,0x00,0x64,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x16,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba, 0x0a,0xb1,0x00,0x9b,0x08,0x04,0xff,0xba,0x04,0x02,0x00,0x65,0x04,0xad,0x00,0x65,0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x03,0x57,0x00,0x5a,0x04,0xad,0x00,0x39,0x04,0xad,0xff,0xc2,0x04,0xad,0xff,0xc2,0x04,0xad,0x00,0x34,0x04,0xad,0x00,0x34,0x04,0xad,0x00,0x3a,0x04,0xad,0x00,0x3a,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52, 0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x65,0x04,0x02,0x00,0x52,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x02,0xfe,0x00,0x00,0x04,0xad,0xff,0x97,0x04,0xad,0xff,0x97,0x04,0xc1,0x00,0x66,0x09,0xd0,0x00,0x73,0x06,0xa8,0x00,0x73, 0x04,0x40,0x00,0x49,0x0c,0x2d,0x00,0x73,0x08,0xaf,0x00,0x49,0x02,0xac,0x00,0x46,0x04,0xad,0x00,0x32,0x00,0x00,0xff,0xc9,0x00,0x00,0xff,0xe9,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0x88,0x00,0x00,0xff,0xc4,0x00,0x00,0x00,0xc4,0x00,0x00,0xff,0xbf,0x00,0x00,0x00,0x32,0x00,0x00,0xff,0xc6,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52, 0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x06,0x03,0x00,0x53,0x05,0x58,0x00,0x67,0x05,0x58,0xff,0xba,0x04,0x02,0xff,0xba,0x00,0x00,0xfe,0x93,0x00,0x00,0xfe,0xa9,0x00,0x00,0xfe,0x91,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x0a,0x05,0x00,0xa1,0x0c,0x06,0x00,0x9b,0x00,0x00,0xff,0xd4, 0x00,0x00,0xff,0xd4,0x00,0x00,0xff,0xd4,0x00,0x00,0xff,0x6c,0x00,0x00,0xff,0xd4,0x04,0xad,0x00,0x35,0x04,0x02,0x00,0x65,0x00,0x00,0xff,0xe7,0x00,0x00,0xff,0xdf,0x00,0x00,0xff,0xdf,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x05,0x07,0x59,0x00,0xab,0x03,0x56,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba, 0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x03,0x57,0x00,0x00,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x04,0x02,0x00,0x65,0x04,0xad,0x00,0x65,0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x65,0x04,0xad,0x00,0x65,0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x65,0x04,0xad,0x00,0x65,0x04,0xae,0xff,0xba, 0x04,0xad,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba, 0x04,0xad,0x00,0x39,0x04,0xae,0xff,0xba,0x04,0xad,0x00,0x39,0x04,0xae,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00, 0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x05,0x2a,0x00,0xa6,0x04,0xad,0x00,0x52,0x04,0xad,0x00,0x52,0x00,0x00,0xff,0x1a,0x04,0x00,0xff,0x1a,0x04,0x00,0x01,0x9f,0x04,0x00,0x01,0xb3,0x02,0xf4,0x00,0x14,0x04,0x96,0x00,0x1c,0x05,0x7f,0x00,0x1e,0x05,0x07,0x00,0x18,0x04,0x0c,0x00,0x8b,0x04,0x2f,0x00,0x60,0x02,0xdb,0x00,0x14, 0x01,0xf0,0xff,0x3a,0x06,0x01,0x00,0x5e,0x04,0xb6,0x00,0x60,0x04,0xc9,0x00,0x1c,0x02,0xc8,0x00,0x1c,0x04,0x6c,0x00,0x12,0x03,0xdf,0x00,0x0e,0x03,0xcd,0x00,0x5a,0x03,0xb2,0x00,0x60,0x03,0xcd,0x00,0x5a,0x01,0xf0,0x00,0xa6,0x04,0x1e,0x00,0x29,0x03,0x48,0x00,0x1e,0x04,0xf4,0x00,0x1a,0x03,0xe0,0x00,0x1a,0x04,0xb8,0x00,0x1a, 0x03,0xac,0x00,0x1a,0x04,0x54,0x00,0x70,0x03,0x81,0x00,0x52,0x05,0x62,0x00,0x10,0x04,0x37,0x00,0x10,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0xdb,0x05,0xed,0x00,0x35,0x03,0x9c,0x00,0x48, 0x03,0xcd,0x00,0x5a,0x03,0xc4,0x00,0x1c,0x02,0x4a,0x00,0x14,0x04,0x19,0x00,0x27,0x04,0x7b,0x00,0x1c,0x04,0xc9,0x00,0xbc,0x04,0x12,0x00,0x5a,0x02,0xb6,0xff,0xb5,0x05,0xf0,0x00,0xbc,0x04,0xb3,0x00,0xa6,0x05,0x1c,0x00,0xbc,0x04,0x4a,0x00,0xa6,0x04,0xf5,0x00,0x21,0x03,0xfb,0x00,0x21,0x04,0x8d,0x00,0x4b,0x04,0x1f,0x00,0xbc, 0x03,0x2b,0x00,0xa6,0x05,0x98,0x00,0x60,0x02,0xf7,0x00,0xaf,0x03,0x4f,0x00,0xaf,0x03,0x5a,0x00,0xaf,0x03,0xde,0x00,0x75,0x04,0xc9,0x00,0x75,0x04,0xc9,0x00,0x75,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x02,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x55,0x00,0x00,0x04,0x50,0x00,0x00, 0x01,0xbc,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x18,0x00,0x00,0x01,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00, 0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x04,0x02,0x00,0xab,0x04,0x02,0x00,0xa1,0x07,0x6c,0x00,0x79,0x03,0x64,0x00,0x3f,0x06,0x08,0x00,0x5e,0x04,0xb6,0x00,0x60,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x04,0xf5,0x00,0xb0,0x00,0x00,0xfc,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x60,0x00,0x4a,0x07,0x60,0x00,0x8d,0x06,0xe7,0x00,0x96,0x03,0xc7,0x00,0x96,0x06,0xe7,0x00,0xe7,0x03,0xc7,0x00,0x96,0x06,0xe5,0x00,0x96,0x05,0x28,0x00,0x33,0x05,0x78,0x00,0xe6,0x05,0x9d,0x00,0xe6,0x05,0x92,0x00,0xe6,0x06,0x1e,0x00,0xe6, 0x06,0xe4,0x00,0xa5,0x08,0x00,0x00,0xa5,0x06,0xe4,0x00,0x50,0x06,0xe4,0x00,0xa5,0x06,0xe4,0x00,0x50,0x06,0xe4,0x00,0xa5,0x06,0xe4,0x00,0x8c,0x06,0xe4,0x02,0x0d,0x06,0xe4,0x00,0xa5,0x05,0x7a,0x00,0x5e,0x05,0x7a,0x00,0x5e,0x05,0x7a,0x00,0x5e,0x05,0x7a,0x00,0xcd,0x05,0xe8,0x00,0x5e,0x04,0xa0,0x00,0x0e,0x08,0x7e,0x00,0x1a, 0x06,0x9d,0x00,0x18,0x03,0xc7,0x00,0x96,0x03,0xc7,0x00,0x96,0x02,0x46,0x00,0xb4,0x02,0x46,0x00,0xb4,0x02,0x46,0x00,0xb4,0x02,0xf8,0x00,0x63,0x01,0xbc,0x00,0x70,0x04,0x82,0x00,0xe8,0x01,0xd7,0x00,0x94,0x01,0xd7,0x00,0xa3,0x06,0xae,0x03,0x9b,0x05,0x10,0x02,0xd6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xa5,0x00,0x00,0xff,0xcd,0x03,0x33,0x00,0x4b,0x00,0x00,0xfe,0xd2,0x01,0x9d,0x00,0x94,0x00,0x00,0x02,0x00,0x00,0x00,0xfd,0x3c,0x01,0xbc,0x00,0x70, 0x00,0x00,0xff,0x9c,0x00,0x00,0xff,0x9c,0x05,0x18,0x00,0xa5,0x04,0x90,0x00,0x50,0x03,0x82,0x00,0x31,0x03,0xd9,0x00,0x20,0x05,0x6c,0x00,0xb8,0x02,0x25,0x00,0xbe,0x02,0xb2,0x00,0x31,0x05,0x65,0x00,0xbe,0x05,0x72,0x00,0xa0,0x02,0x25,0x00,0xbe,0x04,0x78,0x00,0x2f,0x04,0x5c,0x00,0x4e,0x04,0x68,0x00,0x59,0x05,0x8d,0x00,0xbe, 0x05,0x65,0x00,0xa4,0x02,0x25,0x00,0xbe,0x03,0x32,0x00,0x67,0x05,0x68,0x00,0x96,0x04,0xd6,0x00,0x59,0x04,0xe4,0x00,0x6c,0x05,0x0c,0x00,0x96,0x04,0x85,0x00,0x1e,0x04,0xaf,0x00,0x4b,0x05,0x4f,0x00,0x42,0x04,0x79,0x00,0x2f,0x06,0x47,0x00,0x6e,0x05,0xcf,0x00,0x34,0x04,0x2e,0x00,0xbe,0x04,0x2e,0x00,0xbe,0x04,0x2e,0x00,0xbe, 0x01,0xd5,0x00,0x6e,0x03,0x04,0x00,0x6e,0x04,0x78,0x00,0x2f,0x04,0x78,0x00,0x2f,0x04,0x68,0xff,0x51,0x04,0x68,0xff,0x51,0x04,0x53,0x00,0xbe,0x04,0xd6,0x00,0x59,0x05,0x18,0x00,0xa5,0x03,0xd9,0x00,0x20,0x05,0x6c,0x00,0xb8,0x04,0x5c,0x00,0x4e,0x04,0x68,0x00,0x59,0x05,0x8d,0x00,0xbe,0x04,0x79,0x00,0x2f,0x05,0xcf,0x00,0x34, 0x04,0x6a,0x00,0x5f,0x06,0x47,0x00,0x6e,0x06,0x47,0x00,0x61,0x06,0x47,0x00,0x6e,0x06,0x47,0x00,0x61,0x05,0x18,0x00,0xa5,0x05,0x18,0x00,0xa5,0x05,0x18,0x00,0xa5,0x04,0x90,0x00,0x50,0x03,0x82,0x00,0x31,0x03,0xd9,0x00,0x20,0x05,0x6c,0x00,0xb8,0x02,0x6b,0xff,0xfb,0x02,0xda,0xff,0xfa,0x05,0x72,0x00,0xa0,0x02,0x6b,0xff,0xfb, 0x04,0x78,0x00,0x2f,0x04,0x5c,0x00,0x4e,0x04,0x68,0x00,0x59,0x05,0x65,0x00,0xa4,0x03,0x32,0x00,0x67,0x05,0x68,0x00,0x96,0x04,0xe4,0x00,0x6c,0x05,0x0c,0x00,0x96,0x04,0xaf,0x00,0x4b,0x05,0x4f,0x00,0x42,0x04,0x79,0x00,0x2f,0x06,0x47,0x00,0x6e,0x05,0xcf,0x00,0x34,0x02,0x25,0x00,0xb5,0x04,0x90,0x00,0x50,0x04,0x5c,0x00,0x4e, 0x05,0x0c,0x00,0x96,0x05,0x38,0x00,0x59,0x09,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x18,0x00,0xa5,0x04,0x68,0x00,0x59,0x05,0x38,0x00,0x59,0x05,0x52,0x00,0x59,0x05,0x38,0x00,0x59,0x00,0x00,0xff,0x43,0x00,0x00,0xff,0x15,0x00,0x00,0xff,0x73,0x00,0x00,0xff,0xa1,0x00,0x00,0xff,0x49,0x00,0x00,0xff,0x45,0x00,0x00,0xff,0x61, 0x00,0x00,0xfe,0xab,0x00,0x00,0xfe,0x26,0x00,0x00,0x00,0x64,0x00,0x00,0xff,0x42,0x00,0x00,0xff,0x45,0x00,0x00,0x00,0x64,0x00,0x00,0xfe,0xe1,0x00,0x00,0xfe,0x06,0x00,0x00,0xff,0x17,0x00,0x00,0xff,0x5b,0x00,0x00,0xff,0x43,0x00,0x00,0xff,0x6a,0x00,0x00,0xff,0x4b,0x00,0x00,0xff,0x45,0x00,0x00,0xfe,0xe1,0x00,0x00,0xff,0x68, 0x00,0x00,0xff,0x45,0x00,0x00,0xff,0x17,0x00,0x00,0xff,0x43,0x00,0x00,0xff,0x4b,0x00,0x00,0xff,0x6a,0x00,0x00,0x00,0x64,0x00,0x00,0xfd,0x87,0x00,0x00,0xff,0x29,0x00,0x00,0xff,0xa4,0x03,0x32,0x00,0xab,0x02,0x25,0x00,0xb6,0x00,0x00,0xfe,0xb2,0x06,0x08,0x00,0x5e,0x05,0x22,0x00,0x33,0x05,0x55,0x00,0x64,0x05,0xa6,0x00,0x5a, 0x04,0x68,0x00,0x64,0x05,0x55,0x00,0x64,0x05,0xf6,0x00,0x32,0x06,0x19,0x00,0x5e,0x03,0xc4,0x00,0x20,0x05,0x08,0x00,0x8c,0x05,0xf6,0x00,0x32,0x05,0xe2,0x00,0x5c,0x05,0x4a,0x00,0xc9,0x06,0x08,0x00,0x5e,0x06,0x7f,0x00,0x32,0x06,0x36,0x00,0x32,0x05,0x55,0x00,0x64,0x04,0x68,0x00,0xb0,0x04,0x7b,0x00,0xbc,0x06,0x08,0x00,0x5e, 0x05,0xa6,0x00,0x5a,0x04,0x94,0x00,0x32,0x05,0x7f,0x00,0xaa,0x05,0x6b,0x00,0xa6,0x05,0x4a,0x00,0xa6,0x05,0x6b,0x00,0xc9,0x05,0x7d,0x00,0x5e,0x05,0xe2,0x00,0x5c,0x04,0x9c,0x00,0xbc,0x05,0x19,0x00,0x64,0x05,0x6b,0x00,0xc9,0x05,0x3b,0x00,0x32,0x06,0x31,0x00,0x32,0x05,0x0e,0x00,0xc9,0x04,0xf4,0x00,0x5e,0x05,0x22,0x00,0x33, 0x05,0x5a,0x00,0x96,0x06,0x8c,0x00,0x52,0x03,0xf8,0x00,0x60,0x04,0xb0,0x00,0x60,0x04,0xb0,0x00,0x60,0x07,0x00,0x00,0x60,0x04,0x51,0x00,0x60,0x04,0x51,0x00,0x60,0x06,0x2c,0x00,0x3c,0x07,0x21,0x00,0x60,0x04,0xe1,0x00,0x60,0x04,0x51,0x00,0x60,0x08,0x66,0x00,0x60,0x04,0x88,0x00,0x60,0x04,0x88,0x00,0x60,0x06,0x0e,0x00,0x60, 0x04,0x51,0x00,0x60,0x04,0x51,0x00,0x3f,0x06,0x0e,0x00,0x60,0x04,0x7d,0x00,0x9a,0x06,0x08,0x00,0x5e,0x06,0x82,0x00,0x60,0x06,0xff,0x00,0x40,0x04,0x51,0x00,0x60,0x06,0x2e,0x00,0x60,0x04,0x51,0x00,0x60,0x05,0x3b,0x00,0x32,0x04,0x58,0x00,0xa6,0x04,0xeb,0x00,0x60,0x04,0x88,0x00,0x60,0x05,0x0d,0x00,0x32,0x04,0x50,0x00,0x50, 0x04,0xd6,0x00,0xae,0x06,0x27,0x00,0x21,0x04,0x53,0x00,0x60,0x04,0xf5,0x00,0x60,0x05,0x4f,0x00,0x32,0x04,0x51,0x00,0x5e,0x04,0x51,0x00,0x60,0x04,0xc4,0x00,0x52,0x07,0xa8,0x00,0x60,0x04,0x51,0x00,0x60,0x04,0x51,0x00,0x5f,0x04,0xb0,0x00,0x60,0x04,0xb1,0x00,0x40,0x03,0x64,0x00,0x70,0x02,0xa8,0x00,0x32,0x04,0x75,0x00,0x28, 0x04,0x75,0x00,0x28,0x04,0x75,0x00,0x28,0x04,0x48,0x00,0x30,0x04,0x75,0x00,0x28,0x07,0x10,0x00,0x28,0x04,0x75,0xff,0x3f,0x07,0x13,0x00,0x5b,0x03,0xf4,0x00,0x28,0x04,0x75,0x00,0x59,0x07,0x17,0x00,0x31,0x05,0x51,0x00,0x30,0x04,0x75,0x00,0x31,0x07,0x13,0x00,0x5b,0x05,0xf2,0x00,0x28,0x05,0xf2,0x00,0x28,0x07,0x0c,0x00,0x59, 0x04,0x9c,0x00,0x59,0x04,0x75,0x00,0x42,0x07,0x13,0x00,0x5b,0x07,0x13,0x00,0x5b,0x04,0x72,0x00,0x71,0x04,0x75,0x00,0x28,0x04,0x75,0x00,0x28,0x04,0x75,0x00,0x5b,0x04,0x75,0x00,0x2f,0x04,0x75,0x00,0x42,0x07,0x0c,0x00,0x59,0x07,0x10,0x00,0x3f,0x04,0xb0,0x00,0x21,0x04,0x75,0x00,0x42,0x04,0x89,0xff,0x8a,0x07,0x17,0x00,0x31, 0x04,0xc5,0x00,0x2f,0x04,0x56,0x00,0x35,0x04,0x75,0x00,0x46,0x04,0x75,0x00,0x28,0x07,0x0c,0x00,0x59,0x06,0x3a,0x00,0xaa,0x05,0x7f,0x00,0xaa,0x05,0x86,0x00,0x5e,0x05,0x94,0x00,0x78,0x05,0x7f,0x00,0xaa,0x05,0xa8,0x00,0x64,0x04,0xff,0x00,0xbc,0x05,0x7f,0x00,0xaa,0x06,0x3f,0x00,0xaa,0x05,0x86,0x00,0x5e,0x05,0x33,0x00,0xaa, 0x04,0x58,0x00,0xbc,0x06,0x53,0x00,0xbc,0x05,0x62,0x00,0x5e,0x05,0x7f,0x00,0xaa,0x04,0x90,0x00,0x21,0x05,0x54,0x00,0x5e,0x05,0x94,0x00,0x78,0x05,0xf6,0x00,0x62,0x05,0xc6,0x00,0xaa,0x04,0xab,0x00,0x5e,0x05,0x94,0xff,0xf6,0x05,0x54,0x00,0x5e,0x05,0xcf,0x00,0xaa,0x05,0x54,0x00,0x5e,0x06,0x33,0x00,0x82,0x05,0x9a,0x00,0x64, 0x05,0xc6,0x00,0xaa,0x05,0xcf,0x00,0xaa,0x05,0x7a,0x00,0x5e,0x05,0x19,0x00,0x64,0x05,0x9d,0x00,0xaa,0x05,0x6f,0x00,0x90,0x05,0xc6,0x00,0xaa,0x06,0x56,0x00,0x5e,0x05,0x3f,0x00,0x14,0x06,0x08,0x00,0x5e,0x05,0xcb,0x00,0x86,0x00,0xca,0x00,0x00,0x00,0xe1,0x00,0x00,0x01,0x35,0x00,0x00,0x01,0x92,0x00,0x00,0x01,0x35,0x00,0x00, 0x02,0x29,0x00,0x00,0x02,0xce,0x00,0x00,0x06,0xe4,0x00,0x90,0x04,0x87,0x00,0xa6,0x04,0xf2,0x00,0x60,0x04,0xc3,0x00,0xa6,0x04,0x87,0x00,0xa6,0x04,0xec,0x00,0x60,0x04,0x87,0x00,0xa6,0x04,0x87,0x00,0xa6,0x05,0x2b,0x00,0xa6,0x04,0xca,0x00,0x5e,0x04,0x87,0x00,0xa6,0x02,0x76,0x00,0xa6,0x06,0xb1,0x00,0xa6,0x04,0xb0,0x00,0x60, 0x04,0x87,0x00,0x90,0x04,0x87,0x00,0xa6,0x04,0x57,0x00,0x60,0x04,0xd4,0x00,0xa6,0x04,0x18,0x00,0x60,0x04,0xa5,0x00,0x90,0x02,0x26,0xff,0x70,0x04,0xb0,0xff,0xf6,0x04,0x26,0x00,0x60,0x04,0x87,0x00,0xa6,0x03,0x4c,0x00,0x60,0x06,0xe4,0x00,0x90,0x04,0x64,0x00,0x60,0x04,0x87,0x00,0xa6,0x04,0x87,0x00,0x90,0x04,0xbe,0x00,0x90, 0x06,0xa6,0x00,0x8f,0x04,0x87,0x00,0xa6,0x04,0xb6,0x00,0x60,0x03,0x26,0x00,0xa6,0x06,0xa6,0x00,0x8f,0x04,0xb4,0x00,0x00,0x04,0xb0,0x00,0x60,0x05,0x7f,0x00,0x60,0x05,0x72,0x00,0x90,0x01,0xbc,0x00,0x70,0x02,0x42,0x00,0x2a,0x09,0x0e,0x00,0x90,0x08,0xf8,0x00,0x90,0x08,0xf8,0x00,0x90,0x09,0x0e,0x00,0x90,0x0b,0x67,0x00,0x90, 0x04,0x50,0x00,0x83,0x04,0x50,0x00,0x37,0x01,0xf0,0x00,0x90,0x04,0x50,0x00,0x5c,0x03,0x1e,0x00,0x79,0x04,0x50,0x00,0x99,0x04,0x50,0x00,0x7b,0x04,0x7d,0x00,0x32,0x04,0x50,0x00,0xa4,0x04,0x50,0x00,0x6f,0x04,0x1e,0x00,0x45,0x04,0x50,0x00,0x5a,0x04,0x50,0x00,0x5e,0x04,0x50,0x00,0x5c,0x04,0x50,0x00,0xe8,0x04,0x50,0x00,0x99, 0x04,0x50,0x00,0x7b,0x04,0x50,0x00,0x32,0x04,0x50,0x00,0xa4,0x04,0x50,0x00,0x6f,0x04,0x50,0x00,0x60,0x04,0x50,0x00,0x5a,0x04,0x50,0x00,0x5e,0x04,0x50,0x00,0x56,0x03,0x1e,0x00,0x53,0x04,0x50,0x00,0x6d,0x04,0x50,0x00,0x7b,0x04,0x7d,0x00,0x32,0x04,0x50,0x00,0xa4,0x04,0x50,0x00,0x6f,0x04,0x1e,0x00,0x45,0x04,0x50,0x00,0x5a, 0x04,0x50,0x00,0x5e,0x04,0x50,0x00,0x56,0x04,0x50,0x00,0xa8,0x04,0x50,0x00,0x60,0x04,0x50,0x00,0x83,0x04,0x50,0x00,0x0e,0x04,0x50,0x00,0xa4,0x04,0x50,0x00,0x6e,0x04,0x50,0x00,0x56,0x04,0x50,0x00,0x64,0x04,0x50,0x00,0x5e,0x02,0xee,0x00,0x48,0x02,0xee,0x00,0x50,0x02,0xee,0x00,0x68,0x02,0xee,0x00,0x81,0x02,0xee,0x00,0x2f, 0x02,0xee,0x00,0x7b,0x02,0xee,0x00,0x49,0x02,0xee,0x00,0x4d,0x02,0xee,0x00,0x41,0x02,0xee,0x00,0x49,0x04,0x04,0x00,0x00,0x03,0xec,0x00,0xb0,0x04,0x0f,0x00,0x58,0x04,0xac,0x00,0xb0,0x03,0x70,0x00,0xb0,0x03,0x5b,0x00,0xb0,0x04,0x94,0x00,0x58,0x04,0xe9,0x00,0xb0,0x02,0x04,0x00,0xb0,0x02,0x81,0x00,0x11,0x03,0xec,0x00,0xb0, 0x03,0x4c,0x00,0xb0,0x06,0x12,0x00,0xb0,0x05,0x2a,0x00,0xb0,0x04,0xed,0x00,0x58,0x03,0xe0,0x00,0xb0,0x04,0xed,0x00,0x58,0x03,0xf8,0x00,0xb0,0x03,0x5d,0x00,0x68,0x03,0x85,0x00,0x19,0x04,0xc2,0x00,0x9c,0x04,0x15,0x00,0x00,0x06,0x69,0x00,0x05,0x04,0x02,0x00,0x1e,0x03,0xbb,0x00,0x14,0x03,0xdb,0x00,0x29,0x05,0x9f,0xff,0xf8, 0x06,0x31,0x00,0x58,0x03,0x4c,0x00,0x38,0x05,0x01,0x00,0x41,0x03,0xe0,0x00,0xb0,0x04,0xac,0x00,0x2d,0x04,0x33,0x00,0xa6,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x0f,0x00,0x58,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0, 0x03,0x70,0x00,0xb0,0x02,0x04,0xff,0xfc,0x02,0x04,0x00,0x87,0x02,0x04,0xff,0xe9,0x02,0x04,0xff,0xe0,0x05,0x2a,0x00,0xb0,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x03,0xbb,0x00,0x14, 0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x0f,0x00,0x58,0x04,0x0f,0x00,0x58,0x04,0x94,0x00,0x58,0x04,0xac,0x00,0xb0,0x04,0xac,0x00,0x2d,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0,0x03,0x70,0x00,0xb0,0x04,0x94,0x00,0x58,0x04,0x94,0x00,0x58,0x04,0x0f,0x00,0x58, 0x04,0xe9,0x00,0xb0,0x04,0xe9,0x00,0x2d,0x02,0x04,0xff,0xc3,0x02,0x04,0x00,0x04,0x02,0x04,0xff,0xf1,0x02,0x04,0x00,0x3f,0x02,0x04,0x00,0xa0,0x04,0x85,0x00,0xb0,0x02,0x81,0x00,0x11,0x03,0xec,0x00,0xb0,0x03,0x4c,0x00,0xb0,0x03,0x4c,0x00,0xb0,0x03,0x4c,0x00,0xb0,0x03,0x4c,0x00,0xb0,0x05,0x2a,0x00,0xb0,0x05,0x2a,0x00,0xb0, 0x05,0x2a,0x00,0xb0,0x05,0x38,0x00,0xb0,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x04,0xed,0x00,0x58,0x03,0xf8,0x00,0xb0,0x03,0xf8,0x00,0xb0,0x03,0xf8,0x00,0xb0,0x03,0x5d,0x00,0x68,0x03,0x5d,0x00,0x68,0x03,0x5d,0x00,0x68,0x03,0x5d,0x00,0x68,0x03,0x85,0x00,0x19,0x03,0x85,0x00,0x19,0x03,0x85,0x00,0x19,0x03,0x85,0x00,0x19, 0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x04,0xc2,0x00,0x9c,0x06,0x69,0x00,0x05,0x06,0x69,0x00,0x05,0x06,0x69,0x00,0x05,0x06,0x69,0x00,0x05,0x03,0xbb,0x00,0x14,0x03,0xbb,0x00,0x14,0x03,0xbb,0x00,0x14,0x03,0xdb,0x00,0x29,0x03,0xdb,0x00,0x29,0x03,0xdb,0x00,0x29, 0x04,0x04,0x00,0x00,0x05,0x9f,0xff,0xf8,0x05,0x01,0x00,0x41,0x04,0x04,0x00,0x00,0x03,0xec,0x00,0xb0,0x03,0x22,0x00,0x9c,0x04,0x4a,0x00,0x2a,0x03,0x70,0x00,0xb0,0x03,0xdb,0x00,0x29,0x04,0xe9,0x00,0xb0,0x04,0xed,0x00,0x58,0x02,0x04,0x00,0xb0,0x03,0xec,0x00,0xb0,0x04,0x15,0x00,0x00,0x06,0x12,0x00,0xb0,0x05,0x2a,0x00,0xb0, 0x03,0x95,0x00,0x49,0x04,0xed,0x00,0x58,0x04,0xe7,0x00,0xb0,0x03,0xe0,0x00,0xb0,0x03,0xac,0x00,0x30,0x03,0x85,0x00,0x19,0x03,0xbb,0x00,0x14,0x05,0x02,0x00,0x50,0x04,0x02,0x00,0x1e,0x05,0x40,0x00,0x7d,0x05,0x10,0x00,0x58,0x04,0x04,0x00,0x00,0x03,0x70,0x00,0xb0,0x04,0xe9,0x00,0xb0,0x02,0x04,0x00,0x87,0x04,0xed,0x00,0x58, 0x03,0xbb,0x00,0x14,0x05,0x10,0x00,0x58,0x02,0x04,0xff,0xe0,0x03,0xbb,0x00,0x14,0x03,0x70,0x00,0xb0,0x04,0x8d,0x00,0x22,0x03,0x36,0x00,0xb0,0x04,0x19,0x00,0x58,0x03,0x5d,0x00,0x68,0x02,0x04,0x00,0xb0,0x02,0x04,0xff,0xe0,0x02,0x81,0x00,0x11,0x06,0x80,0x00,0x0d,0x06,0x94,0x00,0xb0,0x04,0xe1,0x00,0x22,0x03,0xec,0x00,0xb0, 0x03,0xf4,0x00,0x36,0x04,0xdf,0x00,0xb0,0x04,0x04,0x00,0x00,0x03,0xe7,0x00,0xb0,0x03,0xec,0x00,0xb0,0x03,0x36,0x00,0xb0,0x04,0xaf,0x00,0x12,0x03,0x70,0x00,0xb0,0x05,0xe7,0x00,0x00,0x03,0x88,0x00,0x50,0x05,0x2a,0x00,0xb0,0x05,0x2a,0x00,0xb0,0x03,0xec,0x00,0xb0,0x04,0x8a,0x00,0x0d,0x06,0x12,0x00,0xb0,0x04,0xe9,0x00,0xb0, 0x04,0xed,0x00,0x58,0x04,0xe7,0x00,0xb0,0x03,0xe0,0x00,0xb0,0x04,0x0f,0x00,0x58,0x03,0x85,0x00,0x19,0x03,0xf4,0x00,0x36,0x05,0x02,0x00,0x50,0x04,0x02,0x00,0x1e,0x05,0x11,0x00,0xb0,0x04,0x60,0x00,0x7d,0x06,0x73,0x00,0xb0,0x06,0xa4,0x00,0xb0,0x04,0x89,0x00,0x22,0x05,0xa1,0x00,0xb0,0x03,0xec,0x00,0xb0,0x04,0x1e,0x00,0x54, 0x06,0xe0,0x00,0xb0,0x03,0xe9,0x00,0x12,0x03,0x31,0x00,0xb0,0x04,0xa5,0x00,0x35,0x04,0xa7,0x00,0x35,0x04,0xfa,0x00,0x35,0x07,0x1e,0x00,0x35,0x07,0x1e,0x00,0x35,0x05,0x45,0x00,0x57,0x04,0x0f,0x00,0x58,0x04,0x94,0x00,0x58,0x03,0x5d,0x00,0x68,0x04,0x96,0x00,0xbc,0x04,0x7b,0x00,0xbc,0x04,0x7b,0x00,0x52,0x05,0x9c,0x00,0xbc, 0x04,0x31,0x00,0x29,0x04,0x31,0x00,0x27,0x05,0x7d,0x00,0x5e,0x04,0xa4,0x00,0xbc,0x04,0xa4,0x00,0x02,0x02,0xdb,0x00,0x14,0x04,0xf4,0x00,0x5e,0x04,0xf4,0x00,0x68,0x04,0x90,0x00,0x21,0x03,0xe8,0x00,0xbc,0x03,0xe8,0x00,0x54,0x07,0x2f,0x00,0xbc,0x05,0xfc,0x00,0xbc,0x03,0xc4,0x00,0xbc,0x04,0x40,0x00,0x79,0x04,0xc9,0x00,0xbc, 0x04,0xc9,0x00,0x09,0x04,0xf8,0x00,0x12,0x04,0xf8,0x00,0x12,0x05,0xae,0x00,0xbc,0x05,0x7d,0x00,0x91,0x02,0xdb,0x00,0xb0,0x07,0x79,0x00,0x1a,0x04,0xb8,0x00,0x1a,0x04,0x6c,0x00,0x12,0x04,0x96,0x00,0x67,0x05,0x29,0x00,0x16,0x05,0x29,0x00,0x17,0x04,0x0c,0x00,0xbc,0x04,0x0c,0x00,0x58,0x02,0x21,0x00,0xbc,0x06,0x08,0x00,0x5e, 0x05,0x7f,0x00,0xaa,0x05,0x7f,0x00,0xaa,0x03,0xc4,0x00,0x20,0x05,0x9c,0x00,0x5e,0x01,0xbc,0x00,0x70,0x01,0xbc,0x00,0x27,0x03,0x78,0x00,0x70,0x03,0x78,0x00,0x70,0x01,0xbc,0x00,0x27,0x01,0xbc,0x00,0x70,0x04,0xef,0x00,0x90,0x03,0x33,0x00,0x90,0x02,0x21,0x00,0x30,0x06,0x08,0x00,0x5e,0x05,0xa6,0x00,0x77,0x02,0x46,0x00,0xb4, 0x01,0xbc,0x00,0x5c,0x01,0xbc,0x00,0x5e,0x03,0x96,0x00,0x83,0x03,0x04,0x00,0x6f,0x03,0x04,0x00,0x68,0x01,0xd5,0x00,0x6f,0x01,0xd5,0x00,0x74,0x01,0xd5,0x00,0x62,0x03,0x04,0x00,0x68,0x05,0x65,0x00,0x60,0x03,0xc4,0x00,0xbc,0x02,0x75,0x00,0xa6,0x04,0xd9,0xff,0xe4,0x05,0x7d,0x00,0x5e,0x04,0xb6,0x00,0x60,0x04,0xa4,0x00,0xbc, 0x03,0xfa,0x00,0xa6,0x05,0xfc,0x00,0xbc,0x04,0x87,0x00,0xa6,0x04,0xc9,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x03,0x85,0x00,0x2b,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x68,0x01,0xbc,0x00,0x5e,0x01,0xd5,0x00,0x74,0x03,0x1f,0x01,0x3d,0x04,0x31,0x00,0x29,0x02,0xb6,0x00,0x2b,0x05,0x58,0xff,0xba,0x05,0x58,0xff,0xba,0x05,0x58,0xff,0xba, 0x07,0x59,0x00,0x1e,0x06,0x03,0x00,0x7c,0x07,0x59,0x00,0x7c,0x02,0x01,0x00,0x76,0x00,0x00,0xff,0xc8,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x37,0x02,0x01,0x00,0x70,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x04,0x02,0x00,0x00,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x0a,0xb0,0x00,0x9b, 0x08,0x04,0xff,0xba,0x0a,0xb0,0x00,0x9b,0x08,0x04,0xff,0xba,0x06,0xae,0x00,0x19,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x06,0xae,0x00,0x19,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba, 0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x08,0x04,0x00,0xab,0x06,0x03,0x00,0x9b,0x06,0xae,0x00,0xab, 0x04,0x02,0xff,0xba,0x04,0xad,0x00,0x39,0x04,0xad,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0xff,0xba,0x06,0x03,0x00,0x53,0x04,0x02,0xff,0xba,0x04,0x02,0x00,0x00,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x00,0x00,0xff,0xd4,0x00,0x00,0xff,0xd8,0x00,0x00,0xff,0xd4,0x00,0x00,0xff,0xd4, 0x00,0x00,0xff,0x6c,0x00,0x00,0x00,0x05,0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x05,0x02,0x01,0x00,0x4f,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x9b,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x02,0x01,0x00,0x49,0x04,0x02,0x00,0x00,0x04,0x02,0xff,0xe7, 0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52, 0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x0a,0xb0,0x00,0x9b,0x08,0x04,0xff,0xba,0x0a,0xb0,0x00,0x9b,0x08,0x04,0xff,0xba,0x06,0xae,0x00,0x19,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x08,0x04,0x00,0xab, 0x08,0x04,0x00,0xab,0x08,0x04,0x00,0xab,0x08,0x04,0x00,0xab,0x08,0x04,0x00,0xab,0x08,0x04,0x00,0xab,0x06,0x03,0x00,0x9b,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9b,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x08,0xaf,0x00,0x19,0x08,0x04,0xff,0xba,0x07,0x59,0x00,0xab, 0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab, 0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b, 0x02,0xac,0xff,0xba,0x05,0x58,0xff,0xba,0x04,0x02,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x57,0x04,0x02,0x00,0x57,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba, 0x04,0x02,0x00,0x00,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x00,0x00,0x00,0x81,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x0a,0xb1,0x00,0x9b,0x08,0x04,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x03,0x57,0x00,0x00,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x08,0x04,0x00,0xab, 0x08,0x04,0x00,0xab,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x04,0xad,0x00,0x39,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x39,0x04,0xad,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba, 0x04,0xae,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xae,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x09,0x5a,0x00,0x9b,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x03,0x57,0x00,0x00,0x03,0x57,0x00,0x00,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e, 0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x02,0xac,0x00,0x17,0x02,0xac,0x00,0x17,0x02,0xac,0x00,0x16,0x02,0xac,0x00,0x16,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0x03,0x00,0x9a,0x06,0xae,0x00,0x9a, 0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x17,0x04,0xad,0x00,0x17,0x04,0xad,0x00,0x16,0x04,0xad,0x00,0x16,0x07,0x59,0x00,0x72,0x02,0xac,0x00,0x72,0x07,0x59,0x00,0x72,0x02,0xac,0x00,0x72,0x04,0xae,0x00,0x7e,0x05,0x58,0x00,0x7e,0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x09,0x5a,0x00,0x9b,0x09,0x5a,0x00,0x9b, 0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x09,0x5a,0x00,0x9b,0x09,0x5a,0x00,0x9b,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x06,0xae,0x00,0xab,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x02,0x01,0x00,0xa4,0x02,0x01,0x00,0x03,0x02,0x01,0x00,0xa4,0x02,0x01,0x00,0x03,0x02,0x01,0x00,0x03,0x02,0x01,0xff,0x62, 0x02,0x01,0x00,0x03,0x02,0x01,0xff,0xc6,0x00,0x00,0xff,0x97,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x89,0x02,0x01,0x00,0x60,0x02,0xac,0x00,0x1e,0x02,0x01,0x00,0x3c,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x30,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xa2,0x02,0xac,0x00,0x49,0x02,0xac,0x00,0x72,0x02,0xac,0x00,0x72, 0x02,0xac,0xff,0x97,0x02,0xac,0xff,0xc2,0x02,0xac,0x00,0x34,0x02,0xac,0x00,0x3a,0x03,0x57,0x00,0x17,0x03,0x57,0x00,0x16,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8, 0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x06,0x03,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8, 0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x07,0x59,0xff,0xc8,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6, 0x02,0x01,0xfd,0xa6,0x02,0x01,0xfd,0xa6,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39,0x03,0x57,0x00,0x39, 0x03,0x57,0x00,0x39,0x05,0x58,0x00,0x82,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x06,0x03,0x00,0x1e,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x04,0xad,0x00,0x72, 0x06,0xae,0x00,0x72,0x04,0xad,0x00,0x72,0x06,0xae,0x00,0x72,0x04,0xad,0x00,0x72,0x06,0xae,0x00,0x72,0x04,0xad,0x00,0x72,0x06,0xae,0x00,0x72,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x05,0x58,0x00,0x9a,0x02,0x01,0xff,0xf1,0x02,0x01,0xff,0xea,0x04,0x02,0x00,0xa1,0x03,0x57,0x00,0x39,0x04,0xa9,0x00,0x64,0x05,0x19,0x00,0x65, 0x04,0x90,0x00,0x21,0x04,0x51,0x00,0x5f,0x04,0x70,0x00,0x0a,0x04,0xb0,0x00,0x60,0x04,0x51,0xff,0xe6,0x04,0x55,0x00,0x2d,0x04,0x50,0x00,0x72,0x04,0x50,0x00,0xa1,0x04,0x50,0x00,0xc2,0x04,0x50,0x01,0x1f,0x04,0x50,0x00,0xf7,0x04,0x50,0x01,0x08,0x04,0x50,0x00,0xe1,0x04,0x50,0x00,0xa1,0x04,0x50,0x00,0xa9,0x04,0x50,0x00,0xbc, 0x04,0x26,0x00,0x76,0x03,0xb0,0x00,0x8a,0x04,0x61,0x00,0x6d,0x04,0x32,0x00,0x76,0x04,0xb4,0x00,0x6c,0x04,0xe2,0x00,0x97,0x04,0xe7,0x00,0x90,0x05,0x40,0x00,0x76,0x04,0xa3,0x00,0x80,0x04,0x87,0x00,0x76,0x05,0x35,0x00,0x96,0x04,0x1e,0x00,0x64,0x05,0x59,0x00,0x78,0x06,0x0d,0x00,0x82,0x05,0x1d,0x00,0x8c,0x05,0xfa,0x00,0x96, 0x06,0xa1,0x00,0x64,0x05,0x18,0x00,0x87,0x06,0x1c,0x00,0x78,0x05,0x81,0x00,0x96,0x04,0x84,0x00,0x98,0x04,0x84,0x01,0x00,0x04,0x84,0x00,0x5d,0x04,0x84,0x00,0x6b,0x04,0x84,0x00,0x94,0x04,0x84,0x00,0x59,0x04,0x84,0x00,0x7d,0x04,0x84,0x00,0xbf,0x04,0x84,0x00,0x2b,0x04,0x84,0x00,0x2b,0x04,0x3e,0x00,0x76,0x03,0xb2,0x00,0x2d, 0x04,0x52,0x00,0x7c,0x04,0xd7,0x00,0x0f,0x04,0xce,0x00,0x0a,0x05,0x44,0x00,0x16,0x04,0x94,0x00,0x41,0x05,0x2c,0x00,0x36,0x04,0x99,0x00,0x80,0x04,0xc2,0x00,0x7d,0x04,0xd1,0x00,0x82,0x04,0x15,0x00,0x82,0x04,0x15,0x00,0x96,0x06,0x00,0x00,0x82,0x05,0x6f,0x00,0x64,0x05,0x87,0x00,0x64,0x05,0x64,0x00,0x64,0x05,0x6f,0x00,0x64, 0x04,0xbe,0x00,0xb4,0x04,0xa6,0x00,0x82,0x04,0xa5,0x00,0x77,0x05,0xe4,0x00,0x50,0x06,0x2c,0x00,0x50,0x06,0x03,0x00,0x8c,0x06,0x1b,0x00,0x50,0x07,0x62,0x00,0x8c,0x07,0x62,0x00,0x50,0x05,0x9b,0x00,0x50,0x07,0x62,0x00,0x32,0x07,0x62,0x00,0x50,0x05,0xde,0x00,0x72,0x06,0xfc,0x00,0x74,0x06,0xc4,0x00,0x60,0x04,0x74,0x00,0x58, 0x06,0x24,0x00,0x73,0x06,0xcc,0x00,0x5d,0x06,0x1a,0x00,0x73,0x04,0xc0,0x00,0x70,0x06,0xce,0x00,0x74,0x05,0xe8,0x00,0x73,0x05,0x87,0x00,0x82,0x05,0x9d,0x00,0x82,0x04,0xd6,0x00,0x64,0x05,0x25,0x00,0x82,0x05,0xf8,0x00,0x6e,0x06,0x5a,0x00,0x82,0x05,0x93,0x00,0x64,0x04,0xee,0x00,0x6e,0x05,0xa7,0x00,0x82,0x04,0xa8,0x00,0x82, 0x04,0x46,0x00,0x5d,0x07,0x60,0x00,0x00,0x07,0x58,0x00,0x64,0x07,0x5d,0x00,0x64,0x06,0x96,0x00,0x61,0x07,0x62,0x00,0x61,0x07,0x62,0x00,0x64,0x05,0x78,0x00,0x46,0x07,0x62,0x00,0x64,0x07,0x62,0x00,0x61,0x05,0xad,0x00,0x82,0x06,0x25,0x00,0x82,0x06,0x44,0x00,0xb4,0x05,0xf5,0x00,0x82,0x05,0xcd,0x00,0x82,0x05,0xcd,0x00,0x82, 0x05,0x29,0x00,0x50,0x07,0x0c,0x00,0x82,0x06,0x1e,0x00,0x82,0x06,0x9d,0x00,0x82,0x05,0xb7,0x00,0x78,0x05,0xb3,0x00,0x78,0x04,0xa2,0x00,0x78,0x05,0xe9,0x00,0x50,0x05,0x89,0x00,0x78,0x05,0x89,0x00,0x78,0x06,0xd0,0x00,0x78,0x06,0x10,0x00,0x64,0x05,0xcb,0x00,0x70,0x07,0x2d,0x00,0x78,0x04,0x56,0x00,0x78,0x04,0x10,0x00,0x64, 0x04,0x78,0x00,0x78,0x04,0x4b,0x00,0x78,0x04,0xe5,0x00,0x78,0x04,0xff,0x00,0x78,0x05,0x94,0x00,0x78,0x05,0xde,0x00,0x64,0x04,0xa0,0x00,0x78,0x04,0x8e,0x00,0x78,0x04,0x84,0x00,0x80,0x04,0x5d,0x00,0x7f,0x04,0x8b,0x00,0x3a,0x04,0x5d,0x00,0x7f,0x04,0x5d,0x00,0x80,0x04,0x8b,0x00,0x80,0x04,0x8b,0x00,0x80,0x04,0x9f,0x00,0x80, 0x04,0x84,0x00,0x80,0x04,0x8b,0x00,0x80,0x04,0x8b,0x00,0x80,0x04,0x11,0x00,0x66,0x04,0x3c,0x00,0x80,0x04,0xb8,0x00,0x66,0x04,0xf5,0x00,0x66,0x04,0xd3,0x00,0x80,0x04,0xd3,0x00,0x80,0x03,0xaa,0x00,0x67,0x04,0x84,0x00,0x80,0x04,0x84,0x00,0x80,0x04,0xb4,0x00,0xa0,0x04,0xd9,0x00,0x8c,0x06,0x1f,0x00,0x64,0x06,0xbe,0x00,0xa0, 0x05,0x3c,0x00,0xa0,0x05,0x3c,0x00,0xa0,0x05,0x01,0x00,0x7b,0x06,0x25,0x00,0xa0,0x05,0x1a,0x00,0xa0,0x05,0x78,0x00,0xe9,0x04,0x1a,0x00,0x84,0x03,0xcc,0x00,0x69,0x04,0xb5,0x00,0x84,0x04,0x80,0x00,0x84,0x03,0xc9,0x00,0x84,0x03,0xf3,0x00,0x84,0x04,0x61,0x00,0x84,0x04,0x6c,0x00,0x84,0x03,0xdb,0x00,0x70,0x03,0xb7,0x00,0x84, 0x05,0x02,0x00,0x60,0x03,0xa4,0x00,0x50,0x04,0x5c,0x00,0x2d,0x03,0xf6,0x00,0x50,0x04,0x62,0x00,0x60,0x06,0x3f,0x00,0x60,0x04,0x81,0x00,0x77,0x06,0x9e,0x00,0x60,0x04,0x4a,0x00,0x0a,0x04,0x85,0x00,0x60,0x04,0x8f,0x00,0x60,0x05,0xf2,0x00,0x82,0x02,0x81,0x00,0xf0,0x06,0x51,0x00,0x64,0x05,0x7c,0x00,0x64,0x05,0xbe,0x00,0xb4, 0x05,0x48,0x00,0xb4,0x04,0x7c,0x00,0x64,0x06,0x01,0x00,0x00,0x04,0xd0,0x00,0x82,0x06,0x41,0x00,0x64,0x04,0xd5,0x00,0x67,0x04,0xd5,0x00,0x84,0x04,0xd5,0x00,0x67,0x04,0xd5,0x00,0x3f,0x04,0xd5,0x00,0x6b,0x04,0xd5,0x00,0x5c,0x04,0x9f,0x00,0xd6,0x04,0xd5,0x00,0x59,0x04,0xd5,0x00,0x7b,0x04,0xd5,0x00,0x8b,0x02,0x21,0x00,0x30, 0x02,0x21,0xff,0xd0,0x02,0x21,0xff,0xf9,0x02,0x21,0xff,0x86,0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x30,0x02,0x21,0xff,0xfd,0x03,0x89,0xff,0xbe,0x03,0x9f,0xff,0xbd,0x03,0x98,0xff,0xc1,0x03,0x9f,0xff,0xbe,0x03,0xb9,0xff,0xc0,0x03,0x9f,0xff,0xbe,0x02,0x79,0xff,0xbf,0x02,0x7b,0xff,0xbe,0x02,0x21,0xff,0xfe,0x02,0x21,0xff,0xf2, 0x02,0x21,0xff,0xf2,0x02,0x21,0xff,0xf2,0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x30,0x04,0xfc,0x00,0x30,0x02,0x21,0xff,0xd1,0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x1c,0x02,0x7b,0xff,0xc7,0x02,0x7b,0xff,0xc7,0x02,0x21,0xff,0xf3,0x02,0x21,0xff,0xf8,0x02,0x21,0x00,0x12,0x02,0x5d,0xff,0xaf, 0x02,0x21,0x00,0x30,0x02,0x21,0x00,0x14,0x02,0x21,0xff,0xff,0x07,0x38,0x00,0xbc,0x07,0x38,0x00,0xbc,0x07,0x38,0x00,0xbc,0x07,0x38,0x00,0xbc,0x03,0xe8,0x00,0x93,0x05,0xee,0x00,0x48,0x05,0xcd,0x00,0x6c,0x03,0xe8,0x00,0x60,0x03,0x40,0x00,0x77,0x03,0xe8,0x00,0x3e,0x04,0x2f,0x00,0x96,0x04,0x78,0x00,0x2e,0x03,0xe8,0x00,0x5c, 0x06,0xbf,0x00,0x73,0x06,0x92,0x00,0x73,0x06,0xe7,0x00,0x75,0x03,0x8a,0x00,0x19,0x08,0x0c,0x00,0xaa,0x03,0xe8,0x00,0x60,0x06,0xaf,0x00,0x73,0x06,0xaf,0x00,0x75,0x06,0xbb,0x00,0x82,0x06,0x77,0x00,0x93,0x04,0x86,0x00,0x69,0x03,0xe8,0x00,0x6b,0x03,0xe8,0x00,0x6b,0x06,0x3e,0x00,0x96,0x04,0xae,0x00,0x20,0x06,0x35,0x00,0xaa, 0x05,0x65,0x00,0x12,0x04,0x45,0x00,0x57,0x03,0xa0,0x00,0x26,0x03,0x40,0x00,0x25,0x08,0x27,0x00,0x28,0x03,0x4c,0x00,0x2b,0x04,0x44,0x00,0x22,0x03,0xe9,0x00,0x4c,0x03,0xe9,0x00,0x0b,0x03,0xe9,0x00,0x5f,0x03,0xe9,0x00,0x4e,0x03,0xe9,0x00,0xaa,0x0a,0xe5,0x00,0x8c,0x06,0xaf,0x00,0x6e,0x06,0xaf,0x00,0x80,0x03,0x6e,0x00,0xb2, 0x02,0x03,0x00,0xb2,0x03,0xa5,0x00,0x53,0x01,0xe5,0x00,0x2b,0x03,0xb3,0x00,0xa6,0x01,0xe5,0x00,0x7a,0x01,0xe5,0x00,0x7a,0x01,0xe5,0x00,0x2b,0x03,0xd7,0x00,0x00,0x04,0xae,0x00,0x6a,0x04,0xae,0x00,0x68,0x04,0x5f,0x00,0x00,0x03,0x04,0x00,0x6f,0x03,0x04,0x00,0x68,0x01,0xd5,0x00,0x6f,0x01,0xd5,0x00,0x74,0x01,0xd5,0x00,0x62, 0x03,0x04,0x00,0x68,0x01,0xd5,0x00,0x74,0x03,0x4c,0x00,0x90,0x06,0xe4,0x00,0x8d,0x01,0xbc,0x00,0x70,0x07,0x38,0x00,0xbc,0x07,0x38,0x00,0xbc,0x07,0x38,0x00,0xbc,0x04,0xad,0x00,0xab,0x04,0xad,0x00,0xab,0x06,0xae,0x00,0xa1,0x06,0xae,0x00,0xa1,0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00, 0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00,0x06,0xae,0x00,0x00,0x09,0x5a,0x00,0x9a,0x09,0x5a,0x00,0x9a,0x05,0x58,0xff,0xba,0x09,0x5a,0x00,0x9a,0x09,0x5a,0x00,0x9a,0x05,0x58,0xff,0xba,0x00,0x00,0xff,0x0e,0x00,0x00,0xff,0x36,0x00,0x00,0xff,0x72,0x00,0x00,0xfe,0xfc,0x00,0x00,0xfe,0x84,0x00,0x00,0xff,0x46, 0x00,0x00,0xff,0x2c,0x00,0x00,0xff,0x20,0x00,0x00,0xfe,0xec,0x00,0x00,0xff,0x2c,0x00,0x00,0xff,0x04,0x00,0x00,0xff,0x2c,0x00,0x00,0xff,0x15,0x00,0x00,0xff,0x40,0x00,0x00,0xff,0x3e,0x00,0x00,0xff,0x23,0x00,0x00,0xff,0x06,0x00,0x00,0xff,0x2f,0x00,0x00,0xfe,0xba,0x00,0x00,0xfe,0x93,0x00,0x00,0xff,0x04,0x00,0x00,0xfe,0x94, 0x00,0x00,0xff,0x36,0x00,0x00,0xff,0x21,0x00,0x00,0xff,0x27,0x00,0x00,0xff,0x18,0x00,0x00,0xfe,0xf7,0x00,0x00,0xfe,0xa2,0x00,0x00,0xfe,0xc2,0x00,0x00,0xff,0x07,0x00,0x00,0xfe,0xee,0x00,0x00,0xfe,0xb2,0x04,0xa9,0x00,0x21,0x03,0xc1,0x00,0x21,0x04,0xa9,0x00,0x21,0x03,0xc1,0x00,0x21,0x04,0x40,0x00,0x77,0x03,0x65,0x00,0x70, 0x02,0xd9,0x00,0xbc,0x02,0xc9,0x00,0xa6,0x05,0x7f,0x00,0xaa,0x04,0x61,0x00,0x7d,0x05,0xbb,0x00,0x48,0x03,0x72,0x00,0x19,0x09,0x08,0x00,0x5e,0x07,0x26,0x00,0x60,0x04,0xbe,0xff,0xf3,0x04,0x6d,0x00,0x32,0x07,0x5f,0x00,0x33,0x06,0x55,0x00,0x1c,0x06,0xc1,0x00,0xbb,0x05,0xfe,0x00,0xa6,0x08,0x26,0x00,0x60,0x06,0x81,0x00,0x63, 0x07,0x67,0x00,0xbc,0x06,0x30,0x00,0xa6,0x05,0x29,0x00,0x16,0x03,0xd1,0x00,0x0a,0x05,0xd3,0x00,0x29,0x04,0xb1,0x00,0x1e,0x07,0x67,0x00,0xbc,0x05,0xda,0x00,0xa6,0x06,0x03,0x00,0x1e,0x04,0xdf,0x00,0x05,0x05,0xf0,0x00,0x3e,0x04,0xcd,0x00,0x3e,0x06,0xe8,0x00,0x0f,0x05,0x51,0x00,0x12,0x07,0x05,0x00,0x10,0x05,0x57,0x00,0x10, 0x08,0xd3,0x00,0xbc,0x06,0xbe,0x00,0xa6,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x09,0xb6,0x00,0x5e,0x07,0x1e,0x00,0x60,0x06,0x55,0x00,0x7e,0x00,0x00,0xfe,0xc2,0x07,0xe2,0x00,0x6f,0x07,0xe2,0x01,0x13,0x07,0xe2,0x00,0x26,0x03,0xd1,0x00,0x7d,0x00,0x00,0xfe,0x9c,0x00,0x00,0xff,0x33, 0x04,0xa6,0x00,0xfc,0x04,0x01,0x01,0x33,0x05,0x98,0x00,0x0f,0x04,0x76,0x00,0x12,0x04,0x40,0x00,0x79,0x03,0x65,0x00,0x67,0x08,0x9c,0x00,0x60,0x07,0x3b,0x00,0x50,0x07,0x8f,0x00,0xa6,0x06,0xe1,0x00,0x98,0x05,0xbe,0x00,0x0f,0x04,0xa4,0x00,0x12,0x05,0x96,0x00,0x29,0x04,0xb0,0x00,0x1e,0x04,0x31,0x00,0x29,0x03,0x48,0x00,0x1e, 0x05,0xeb,0x00,0xae,0x04,0xc7,0x00,0x8f,0x04,0x31,0x00,0x29,0x03,0x48,0x00,0x1e,0x06,0x8e,0x00,0x29,0x05,0x54,0x00,0x1e,0x05,0x4a,0x00,0xa6,0x04,0x87,0x00,0xa6,0x07,0xd1,0x00,0xbc,0x06,0x8f,0x00,0xa6,0x04,0x50,0x00,0x2b,0x04,0x99,0x00,0x32,0x05,0xdc,0x00,0xe7,0x05,0xdc,0x00,0xe7,0x06,0x78,0x00,0x00,0x03,0x96,0x00,0x83, 0x01,0x9a,0x00,0x00,0x03,0xac,0x00,0xac,0x05,0x7a,0x00,0x5e,0x03,0x73,0x00,0x30,0x08,0x00,0x00,0xe6,0x08,0x00,0x00,0xe6,0x01,0xf0,0x00,0x37,0x00,0x00,0xfd,0x33,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00, 0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x07,0xd1,0x00,0x00,0x03,0x33,0x00,0x90,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x08,0xfc,0x00,0x32,0x04,0x50,0x00,0x53,0x04,0xb0,0x00,0xbb,0x04,0xb0,0x01,0x01, 0x04,0xb0,0x00,0xaf,0x04,0xb0,0x00,0xc2,0x04,0xb0,0x00,0x6a,0x04,0xb0,0x00,0x64,0x04,0xb0,0x00,0x39,0x04,0xb0,0x00,0x2e,0x04,0xb0,0x00,0x79,0x04,0xb0,0x00,0x81,0x06,0x04,0x00,0xfd,0x06,0x04,0x01,0x70,0x06,0x04,0x00,0xb9,0x06,0x04,0x00,0x7d,0x06,0x04,0x00,0xff,0x06,0x04,0x00,0x8c,0x06,0x04,0x00,0x1f,0x06,0x04,0x00,0xf5, 0x06,0x04,0x00,0x3a,0x06,0x04,0x00,0xaf,0x04,0xc4,0x00,0xb7,0x04,0xc4,0x01,0x2a,0x04,0xc4,0x00,0x7d,0x04,0xc4,0x00,0x8b,0x04,0xc4,0x00,0xb4,0x04,0xc4,0x00,0x79,0x04,0xc4,0x00,0x9d,0x04,0xc4,0x00,0xdf,0x04,0xc4,0x00,0x4b,0x04,0xc4,0x00,0x4b,0x05,0x14,0x00,0xe1,0x05,0x14,0x00,0xdc,0x05,0x14,0x00,0xa6,0x05,0x14,0x00,0x68, 0x05,0x14,0x00,0x2d,0x05,0x14,0x00,0x0c,0x05,0x14,0x00,0x68,0x05,0x14,0x00,0x4d,0x05,0x14,0x00,0xab,0x05,0x14,0x00,0x7d,0x05,0x28,0x00,0xad,0x05,0x28,0x01,0x15,0x05,0x28,0x01,0x15,0x05,0x28,0x00,0x2f,0x05,0x28,0x00,0x40,0x05,0x28,0x00,0x34,0x05,0x28,0x00,0x55,0x05,0x28,0x00,0x4f,0x05,0x28,0x00,0xc1,0x05,0x28,0x00,0xdc, 0x07,0x44,0x01,0xbd,0x07,0x44,0x01,0x00,0x07,0x44,0x00,0xd2,0x07,0x44,0x00,0xff,0x07,0x44,0x00,0xf8,0x07,0x44,0x00,0x5c,0x07,0x44,0x00,0x27,0x07,0x44,0x01,0x1a,0x07,0x44,0x00,0x48,0x07,0x44,0x00,0x23,0x06,0x68,0x00,0xbf,0x06,0x68,0x00,0x34,0x06,0x68,0x00,0x45,0x06,0x68,0x01,0x78,0x06,0x68,0x00,0x9e,0x06,0x68,0x00,0x36, 0x06,0x68,0x00,0x99,0x06,0x68,0x01,0x4a,0x06,0x68,0x00,0x28,0x06,0x68,0x00,0x99,0x05,0xdc,0x00,0xac,0x05,0xdc,0x00,0xa1,0x05,0xdc,0x00,0xf6,0x05,0xdc,0x00,0xdd,0x05,0xdc,0x00,0x60,0x05,0xdc,0x00,0x43,0x05,0xdc,0x00,0x7e,0x05,0xdc,0x00,0xd6,0x05,0xdc,0x00,0x8d,0x05,0xdc,0x01,0x0d,0x07,0x1c,0x01,0xc8,0x07,0x1c,0x00,0x24, 0x07,0x1c,0x00,0x37,0x07,0x1c,0x00,0x32,0x07,0x1c,0x00,0x7e,0x07,0x1c,0x00,0x37,0x07,0x1c,0x00,0x46,0x07,0x1c,0x01,0x25,0x07,0x1c,0x00,0x4b,0x07,0x1c,0x00,0x3d,0x06,0x68,0x00,0xdf,0x06,0x68,0x00,0xa3,0x06,0x68,0x00,0xc6,0x06,0x68,0x00,0xbb,0x06,0x68,0x00,0xcf,0x06,0x68,0x00,0xcf,0x06,0x68,0x01,0x08,0x06,0x68,0x00,0x35, 0x06,0x68,0x00,0xa7,0x06,0x68,0x00,0x67,0x06,0x68,0x00,0xd0,0x06,0x68,0x00,0xd2,0x06,0x68,0x01,0x47,0x06,0x68,0x00,0xa3,0x06,0x68,0x00,0xdd,0x06,0x68,0x00,0xdd,0x06,0x68,0x00,0x44,0x06,0x68,0x00,0x9a,0x06,0x68,0x00,0xb9,0x06,0x68,0x00,0x15,0x05,0x78,0x01,0x09,0x05,0x78,0x01,0x22,0x05,0x78,0x00,0xf8,0x05,0x78,0x01,0x0e, 0x05,0x78,0x00,0xb7,0x05,0x78,0x00,0x78,0x05,0x78,0x00,0x6c,0x05,0x78,0x00,0x3b,0x05,0x78,0x00,0xcb,0x05,0x78,0x00,0xe3,0x04,0x10,0x00,0x47,0x04,0x10,0x00,0x5a,0x04,0x10,0x00,0x44,0x04,0x10,0x00,0x5a,0x04,0x10,0x00,0x5a,0x04,0x10,0x00,0x44,0x04,0x10,0x00,0x44,0x04,0x10,0x00,0x30,0x04,0x10,0x00,0x47,0x04,0x10,0x00,0x44, 0x04,0x88,0x00,0x80,0x04,0x88,0x00,0xa3,0x04,0x88,0x00,0x9b,0x04,0x88,0x00,0x5d,0x04,0x88,0x00,0x31,0x04,0x88,0x00,0x57,0x04,0x88,0x00,0x57,0x04,0x88,0x00,0xd7,0x04,0x88,0x00,0x83,0x04,0x88,0x00,0x83,0x06,0x04,0x01,0x48,0x06,0x04,0x01,0x21,0x06,0x04,0x00,0x74,0x06,0x04,0x00,0x43,0x06,0x04,0x00,0xf0,0x06,0x04,0x00,0xd6, 0x06,0x04,0x01,0x0f,0x06,0x04,0x00,0x8f,0x06,0x04,0x01,0x0b,0x06,0x04,0x01,0x20,0x04,0x4c,0x00,0x9d,0x04,0x4c,0x00,0xb6,0x04,0x4c,0x00,0x36,0x04,0x4c,0x00,0x5a,0x04,0x4c,0x00,0xc5,0x04,0x4c,0x00,0xab,0x04,0x4c,0x00,0x79,0x04,0x4c,0x00,0x74,0x04,0x4c,0x00,0xa8,0x04,0x4c,0x00,0xce,0x05,0xc8,0x00,0xc3,0x05,0xc8,0x01,0x6a, 0x05,0xc8,0x01,0x08,0x05,0xc8,0x01,0x20,0x05,0xc8,0x01,0x21,0x05,0xc8,0x00,0x3c,0x05,0xc8,0x01,0x05,0x05,0xc8,0x00,0x50,0x05,0xc8,0x00,0xc9,0x05,0xc8,0x01,0x01,0x05,0xc8,0x00,0xd6,0x06,0x04,0x00,0x8b,0x06,0x04,0x02,0xb1,0x06,0x04,0x00,0x1f,0x06,0x04,0x00,0xb7,0x06,0x04,0x00,0xd7,0x06,0x04,0x00,0xf9,0x06,0x04,0x01,0x37, 0x06,0x04,0x00,0x33,0x06,0x04,0x01,0x1c,0x06,0x04,0x00,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x9c,0x00,0x00,0xfe,0xe6,0x00,0x00,0xff,0x9c,0x03,0x82,0x00,0x31,0x03,0xd9,0x00,0x20,0x05,0x6c,0x00,0xb8,0x05,0xcf,0x00,0x34,0x02,0x39,0x00,0x6d,0x01,0xac,0x00,0x5a,0x02,0x39,0x00,0x5b, 0x01,0xac,0x00,0x4e,0x05,0xae,0x00,0xbc,0x04,0x87,0x00,0xa6,0x05,0xf1,0x00,0x29,0x05,0x05,0x00,0x2b,0x04,0x6b,0x00,0x66,0x03,0xc5,0x00,0x26,0x04,0x45,0x00,0x51,0x03,0xda,0x00,0x21,0x04,0xba,0x00,0x51,0x04,0x90,0x00,0x21,0x03,0x5b,0x00,0xb0,0x03,0x5d,0x00,0x68,0x09,0x08,0x00,0x16,0x06,0x8b,0x00,0x5a,0x09,0x39,0x00,0x16, 0x07,0x16,0x00,0x5a,0x07,0xe4,0x00,0x16,0x06,0xc3,0x00,0x5a,0x07,0x36,0x00,0x16,0x05,0x44,0x00,0x5a,0x07,0x36,0x00,0x16,0x05,0x44,0x00,0x5a,0x07,0x36,0x00,0x16,0x05,0x44,0x00,0x5a,0x04,0xf4,0x00,0x68,0x03,0xb2,0x00,0x50,0x04,0xa4,0x00,0x12,0x03,0xfa,0x00,0x27,0x04,0xa4,0x00,0xbc,0x03,0xfa,0x00,0xa6,0x04,0xa4,0x00,0x12, 0x03,0xfa,0x00,0x27,0x04,0x5b,0x00,0xbc,0x02,0x82,0x00,0xa6,0x03,0xc4,0x00,0x12,0x01,0xf0,0x00,0x1e,0x06,0x08,0x00,0x00,0x04,0xb0,0x00,0x00,0x06,0xdf,0x00,0x5e,0x05,0x64,0x00,0x60,0x0a,0xa5,0x00,0x5e,0x07,0xf8,0x00,0x60,0x04,0x7b,0x00,0x19,0x04,0xb4,0x00,0x1e,0x05,0x83,0x00,0x1e,0x05,0xa6,0x00,0x05,0x06,0x79,0x00,0x0a, 0x06,0xe5,0x00,0x05,0x06,0x08,0x00,0x5e,0x04,0xb6,0x00,0x60,0x07,0xd4,0x00,0x5e,0x06,0x42,0x00,0x60,0x04,0x5c,0x00,0x1e,0x03,0x2e,0x00,0x0f,0x04,0x79,0x00,0x3d,0x03,0xee,0x00,0x0f,0x04,0xf8,0x00,0x12,0x03,0xd5,0xff,0xe8,0x07,0x79,0x00,0x1a,0x05,0xc8,0x00,0x18,0x04,0xea,0x00,0x55,0x04,0x2d,0x00,0x3e,0x04,0x7b,0x00,0x12, 0x04,0xb4,0x00,0x27,0x04,0x7b,0x00,0x12,0x04,0xb4,0x00,0x27,0x03,0xd9,0x00,0xbc,0x03,0x32,0x00,0xa6,0x03,0xcd,0x00,0x60,0x03,0x19,0x00,0x1e,0x03,0xc8,0x00,0x14,0x02,0xf2,0xff,0x76,0x04,0x24,0x00,0x38,0x04,0x2a,0x00,0x43,0x02,0x69,0x00,0x28,0x05,0x65,0x00,0x60,0x02,0x9f,0x00,0xa6,0x07,0xa9,0x00,0xa6,0x05,0x4d,0x00,0xa6, 0x02,0xc8,0x00,0xa6,0x04,0xa7,0x00,0xa6,0x04,0xea,0x00,0x2b,0x03,0xb0,0xff,0xec,0x06,0x08,0x00,0x0f,0x04,0x79,0x00,0x60,0x03,0x08,0x00,0xbc,0x02,0xc8,0x00,0xa6,0x04,0xa4,0x00,0x5a,0x04,0xa4,0x00,0x59,0x04,0x9f,0x00,0x60,0x03,0xc4,0x00,0x20,0x01,0xf0,0x00,0xa6,0x06,0x15,0x00,0xbc,0x04,0xc9,0x00,0xa6,0x02,0xf4,0x00,0xbc, 0x02,0xc8,0x00,0xa6,0x04,0xfa,0x00,0x5e,0x03,0xac,0x00,0x60,0x05,0xae,0x00,0xbc,0x03,0x17,0xff,0xe5,0x06,0x3d,0x00,0xbc,0x04,0xcd,0x00,0xa6,0x04,0xf4,0x00,0x00,0x03,0xb2,0x00,0x00,0x05,0x7d,0x00,0x01,0x04,0xb6,0x00,0x00,0x04,0xa4,0x00,0x12,0x03,0xfa,0x00,0x26,0x05,0xfc,0x00,0x12,0x04,0x87,0x00,0x19,0x04,0xc9,0x00,0x12, 0x02,0xc8,0x00,0x23,0x04,0x40,0x00,0x45,0x03,0x65,0x00,0x60,0x06,0x00,0xff,0xac,0x03,0x64,0x00,0x19,0x04,0x3e,0x00,0x3e,0x06,0xe4,0x00,0x90,0x03,0xe8,0x00,0x54,0x04,0x7b,0x00,0x52,0x07,0x2f,0x00,0xbd,0x02,0x21,0x00,0xbc,0x09,0x2b,0x00,0x1a,0x07,0x25,0x00,0x50,0x07,0x31,0x00,0x50,0x09,0x76,0x00,0x4a,0x07,0x11,0x00,0x50, 0x07,0x53,0x00,0x8d,0x07,0x53,0x00,0x81,0x07,0x07,0x00,0x2f,0x07,0x17,0x00,0x50,0x07,0x60,0x00,0x7b,0x04,0x21,0x00,0x50,0x03,0xc4,0x00,0xbc,0x04,0xf4,0x00,0x5e,0x05,0x9c,0x00,0xbc,0x07,0x2f,0x00,0xbc,0x05,0x9c,0x00,0x1a,0x07,0x8c,0x00,0x1a,0x01,0xf0,0x00,0xa6,0x03,0xb2,0x00,0x60,0x04,0xb6,0x00,0x60,0x06,0xe4,0x00,0xa6, 0x08,0x3c,0x00,0x5e,0x05,0x9c,0x00,0xbc,0x08,0x3c,0x00,0x5e,0x04,0xf4,0x00,0x68,0x04,0xf4,0x00,0x5e,0x06,0x5c,0x01,0x05,0x05,0x9c,0x00,0xbc,0x09,0x18,0x00,0x5e,0x07,0x60,0x00,0x48,0x04,0x27,0x00,0x00,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x04,0xad,0x00,0x7e,0x04,0xad,0x00,0x7e, 0x04,0xad,0xff,0xba,0x04,0xad,0xff,0xba,0x06,0xae,0x00,0x19,0x06,0xae,0xff,0xba,0x06,0xae,0xff,0xba,0x06,0xae,0x00,0x19,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x08,0x04,0x00,0xab,0x06,0x03,0x00,0x9b,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9b,0x05,0x58,0x00,0x9b,0x02,0xac,0xff,0xba, 0x02,0xac,0xff,0xba,0x05,0x58,0x00,0x9b,0x04,0xad,0x00,0x39,0x04,0xae,0xff,0xba,0x04,0xad,0xff,0xba,0x04,0xad,0x00,0x39,0x06,0x03,0x00,0x82,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0xae,0x00,0x82,0x06,0x03,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x06,0xae,0x00,0x9a,0x03,0x57,0xff,0xa6,0x03,0x57,0xff,0xa6, 0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x1c,0x00,0x02,0x04,0x1c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00,0x0c,0x66,0x00,0x73, 0x04,0x1f,0x00,0xbc,0x03,0x2b,0x00,0xa6,0x04,0x83,0x00,0x50,0x04,0x38,0x00,0x50,0x05,0xfe,0x00,0xbc,0x04,0xa6,0x00,0xa6,0x04,0xa4,0x00,0xbc,0x07,0x02,0x00,0x10,0x05,0x5a,0x00,0x10,0x05,0xfe,0x00,0xbc,0x06,0x04,0x00,0xa6,0x06,0xa5,0x00,0x3d,0x06,0x8a,0x00,0x3e,0x04,0xa4,0x00,0xbc,0x03,0xfa,0x00,0xa6,0x08,0x09,0x00,0x10, 0x06,0x73,0x00,0x10,0x08,0x57,0x00,0xbc,0x06,0xda,0x00,0xa6,0x05,0x7d,0x00,0xa6,0x04,0xb4,0x00,0x98,0x02,0x81,0x00,0x35,0x02,0x81,0x00,0x35,0x04,0xac,0x00,0x5c,0x05,0x2c,0x00,0xbc,0x03,0x44,0x00,0x1e,0x04,0xcc,0x00,0x81,0x04,0x21,0x00,0x77,0x04,0xa2,0x00,0x06,0x03,0xdf,0xff,0xbd,0x05,0xea,0x00,0xbc,0x06,0x68,0x00,0x60, 0x03,0x34,0x00,0x78,0x04,0xb0,0x00,0x60,0x03,0x70,0x00,0x49,0x01,0xae,0x00,0x06,0x02,0xf7,0x00,0x1c,0x04,0x40,0x00,0x79,0x04,0x68,0x00,0x21,0x01,0xbb,0x00,0x70,0x01,0xbc,0x00,0x70,0x01,0x78,0x00,0x27,0x01,0xbc,0x00,0x6f,0x03,0x00,0x00,0x30,0x03,0x00,0x01,0x2e,0x03,0x00,0x00,0x30,0x03,0x96,0x00,0x83,0x0b,0xe8,0x00,0x00, 0x0f,0xf4,0x00,0x00,0x02,0xb7,0x00,0x25,0x03,0x4c,0x00,0x5b,0x01,0x11,0xff,0xda,0x02,0x21,0xff,0xf7,0x03,0x1b,0x00,0x0c,0x03,0x72,0x00,0x5b,0x02,0x89,0x00,0x5a,0x03,0xf3,0x00,0x1e,0x04,0x38,0x00,0x5c,0x03,0x0f,0x00,0x64,0x03,0x0f,0x00,0x64,0x03,0x0f,0x00,0x64,0x03,0x0f,0x00,0x64,0x03,0x0f,0x00,0x64,0x03,0x0f,0x00,0x96, 0x03,0x0f,0x00,0x96,0x03,0x0f,0x00,0x96,0x03,0x0f,0x00,0x96,0x03,0x0f,0x00,0x96,0x03,0xc3,0x00,0x96,0x03,0xc3,0x00,0x96,0x03,0xc3,0x00,0x96,0x03,0xc3,0x00,0x96,0x03,0xc3,0x00,0x96,0x0a,0xa0,0x00,0xb4,0x04,0x50,0x00,0x40,0x06,0x18,0x00,0x32,0x07,0x57,0x00,0x26,0x07,0x2f,0x00,0xbc,0x05,0x29,0x00,0x16,0x03,0xb2,0x00,0x60, 0x04,0x87,0x00,0xa6,0x05,0xc2,0x00,0x6e,0x05,0xe0,0x00,0x75,0x03,0xe8,0xff,0x9a,0x02,0x81,0x00,0x35,0x05,0x4a,0x00,0x5e,0x04,0x26,0x00,0x60,0x05,0x72,0x00,0x5e,0x04,0x70,0x00,0x60,0x05,0x4a,0x00,0x5e,0x04,0x43,0x00,0x60,0x04,0x52,0x00,0x60,0x05,0xf3,0x00,0x5e,0x04,0xbd,0x00,0x28,0x04,0xa4,0x00,0x02,0x04,0x31,0x00,0x29, 0x05,0xfe,0x00,0x32,0x04,0xea,0xff,0xf9,0x06,0xa8,0x00,0x5a,0x03,0xa4,0x00,0x64,0x04,0x2f,0x00,0x13,0x05,0x10,0x00,0x29,0x02,0x81,0x00,0x35,0x04,0xb6,0x00,0x60,0x02,0xb7,0x00,0x00,0x02,0xc7,0x00,0x23,0x01,0xf0,0xff,0xf6,0x07,0x04,0x00,0xa6,0x04,0xa8,0x00,0xa6,0x04,0x87,0x00,0xa6,0x04,0x2d,0x00,0x64,0x04,0x2d,0x00,0x54, 0x04,0xb0,0x00,0x80,0x07,0x6c,0x00,0x60,0x07,0x6c,0x00,0x60,0x07,0x8d,0x00,0x60,0x07,0xf8,0x00,0x60,0x07,0xf8,0x00,0x60,0x04,0x61,0x00,0x7d,0x03,0xff,0x00,0xb0,0x02,0x42,0x00,0xa6,0x04,0x01,0x00,0xa6,0x03,0xaa,0x00,0x1c,0x04,0xde,0x00,0x1c,0x03,0xa3,0x00,0x3c,0x05,0x57,0x00,0x3c,0x01,0xfa,0xff,0x92,0x04,0x87,0x00,0x90, 0x04,0xcb,0x00,0x21,0x06,0xe4,0x00,0xa6,0x06,0xe4,0x00,0xa6,0x04,0xeb,0x00,0x0e,0x04,0x4e,0x00,0x0c,0x04,0x9c,0x00,0x0c,0x04,0x4e,0x00,0x0c,0x04,0x2c,0x00,0x1a,0x03,0xac,0xff,0x1f,0x04,0x2c,0xff,0x1f,0x03,0xac,0xfe,0xc8,0x03,0xdf,0x00,0x0e,0x02,0x6e,0x00,0x25,0x02,0xb2,0x00,0x64,0x01,0xf4,0x00,0x00,0x01,0xbf,0x00,0x00, 0x02,0xe4,0x00,0x00,0x04,0xa0,0x00,0x60,0x05,0x10,0x00,0x58,0x02,0x58,0x00,0xcf,0x02,0x58,0x00,0xcf,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x67,0x02,0x58,0x00,0xcf,0x02,0x58,0x00,0xcf, 0x02,0x58,0x00,0x8b,0x02,0x8a,0x00,0x0c,0x02,0x8a,0x00,0x0c,0x00,0x00,0xff,0xd4,0x02,0x4e,0xff,0xba,0x02,0x4e,0xff,0xba,0x02,0x4e,0xff,0xba,0x02,0x01,0x00,0x05,0x02,0x01,0x00,0x05,0x0d,0x74,0x00,0x52,0x07,0xf5,0x00,0x32,0x06,0xf9,0x00,0x32,0x08,0x63,0x00,0x32,0x02,0x4e,0x00,0x29,0x02,0x4e,0xff,0xba,0x02,0x9e,0x00,0x05, 0x03,0x2a,0x00,0x9a,0x02,0x0c,0x00,0x05,0x02,0x26,0x00,0x15,0x02,0x4e,0xff,0xba,0x02,0x4e,0x00,0x21,0x02,0x4e,0xff,0xba,0x02,0x4e,0x00,0x29,0x02,0x4e,0xff,0xba,0x02,0x4e,0xff,0xf8,0x02,0x4e,0xff,0xba,0x02,0x4e,0x00,0x69,0x02,0x4e,0xff,0xba,0x02,0x4e,0xff,0xba,0x00,0x00,0xff,0xe7,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba, 0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0x12,0x00,0xc4,0x04,0x02,0x00,0x52,0x04,0x02,0x00,0x52,0x0a,0xb1,0x00,0x9b,0x08,0x04,0xff,0xba,0x08,0x04,0xff,0xba,0x0a,0xb0,0x00,0x9b,0x07,0x59,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x04,0x02,0x00,0xab,0x04,0x02,0x00,0xab,0x03,0x57,0x00,0x00, 0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x8c,0x00,0x00,0xfe,0x45,0x02,0xdb,0x00,0x14,0x05,0xfa,0x00,0xbc,0x04,0xcd,0x00,0xa6,0x05,0xae,0xff,0x98,0x04,0x9e,0xff,0x5c,0x0a,0x08,0x00,0x0f,0x08,0x46,0x00,0x12,0x05,0x8c,0x00,0x0f,0x04,0x60,0x00,0x12,0x05,0x9e,0x00,0x10,0x04,0x65,0x00,0x10,0x0a,0xa5,0x00,0x5e,0x07,0xf8,0x00,0x60, 0x06,0x08,0x00,0x5e,0x04,0xb0,0x00,0x60,0x03,0x1b,0x00,0x0c,0x02,0x89,0x00,0x5a,0x04,0xf2,0x00,0x28,0x00,0x00,0xff,0x38,0x05,0x76,0x00,0x50,0x04,0x50,0x00,0xbc,0x02,0xb0,0x00,0x66,0x02,0x6a,0x00,0x66,0x01,0x4c,0x00,0x66,0x03,0xfa,0x00,0x66,0x02,0xb0,0x00,0x66,0x02,0xbe,0x00,0x66,0x02,0x09,0x00,0x3c,0x01,0x9c,0x00,0x0a, 0x03,0xb1,0x00,0x1e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x02,0xed,0x00,0x6e,0x01,0xbc,0x00,0x70,0x04,0x31,0x00,0x29,0x03,0x68,0x00,0x20,0x04,0xb8,0x00,0x1a,0x04,0x96,0x00,0xbc,0x04,0x62,0x00,0xa7,0x07,0xb2,0x00,0x5a, 0x06,0x77,0x00,0x77,0x06,0x74,0x00,0xa6,0x06,0x50,0x00,0xa6,0x06,0x89,0x00,0x60,0x07,0x8a,0x00,0x90,0x05,0x03,0x00,0x35,0x05,0x7c,0x00,0x68,0x04,0xcf,0x00,0x50,0x03,0x25,0x00,0x50,0x07,0x6e,0x00,0x3c,0x09,0x01,0x00,0x54,0x03,0x85,0x00,0x74,0x09,0x3d,0xff,0xf8,0x04,0x02,0x00,0x65,0x06,0xae,0x00,0xab,0x07,0x59,0x00,0xab, 0x07,0x59,0x00,0xab,0x07,0x59,0x00,0xab,0x03,0x57,0x00,0x00,0x06,0x03,0x00,0x9a,0x08,0x04,0x00,0xab,0x06,0x03,0x00,0x9b,0x05,0x58,0x00,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x32,0x00,0x00,0xfc,0xe6,0x00,0x00,0xfb,0x6b,0x00,0x00,0xfb,0x9b, 0x00,0x00,0xfc,0x00,0x00,0x00,0xfd,0x71,0x00,0x00,0xfd,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xfe,0x04,0x64,0x00,0xdc,0x00,0x00,0xfe,0xd4,0x04,0xad,0x00,0x65,0x04,0xad,0xff,0xba,0x04,0xae,0xff,0xba,0x06,0xae,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba, 0x07,0x59,0x00,0xab,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x07,0x59,0x00,0xab,0x03,0xf1,0xff,0xba,0x03,0xf1,0xff,0xba,0x00,0x00,0xfe,0x84,0x03,0x57,0x00,0x00,0x06,0xae,0x00,0x9a,0x02,0xac,0xff,0xba,0x02,0xac,0xff,0xba,0x08,0x04,0x00,0xab,0x04,0x02,0xff,0xba,0x04,0x02,0xff,0xba,0x06,0x03,0x00,0x9b,0x04,0x02,0xff,0xba, 0x04,0x02,0xff,0xba,0x05,0x58,0x00,0x9b,0x02,0x58,0x00,0xab,0x02,0x58,0x00,0xd4,0x02,0x58,0x00,0x66,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x7f,0x02,0x58,0x00,0x4f,0x02,0x58,0x00,0x35,0x02,0x58,0x00,0x1b,0x02,0x58,0x00,0x1b,0x02,0x58,0x00,0x35,0x02,0x58,0x00,0x53,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x59,0x02,0x58,0x00,0x2b, 0x02,0x58,0x00,0x4d,0x0c,0x05,0x00,0xa1,0x0c,0x05,0x00,0xa1,0x07,0x0a,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0a,0x00,0x73,0x07,0x0a,0x00,0x73,0x03,0x4d,0x00,0xf2,0x03,0x4d,0x01,0x2f,0x03,0x4d,0x00,0x76,0x03,0x4d,0x00,0x25,0x03,0x4d,0x00,0xab,0x03,0x4d,0x00,0x62,0x03,0x4d,0x00,0x42,0x03,0x4d,0x00,0x1c, 0x03,0x4d,0x00,0x1d,0x03,0x4d,0x00,0x3c,0x03,0x4d,0x00,0x69,0x03,0x4d,0x00,0x3c,0x03,0x4d,0x00,0x6f,0x03,0x4d,0x00,0x41,0x03,0x4d,0x00,0x6b,0x03,0x57,0x00,0x39,0x05,0x58,0x00,0x9a,0x04,0xf1,0x00,0x55,0x05,0x26,0x00,0x78,0x05,0x30,0x00,0x78,0x07,0x1a,0x00,0x82,0x05,0x27,0x00,0x64,0x05,0x0b,0x00,0x6e,0x06,0x62,0x00,0x28, 0x07,0xce,0x00,0x82,0x05,0x34,0x00,0x82,0x05,0x0b,0x00,0x6e,0x08,0x8a,0x00,0x82,0x05,0x14,0x00,0x82,0x05,0x14,0x00,0xa0,0x07,0x7a,0x00,0x82,0x05,0x0b,0x00,0x6e,0x05,0x63,0x00,0x64,0x06,0x52,0x00,0x82,0x05,0x1a,0x00,0xa0,0x06,0x28,0x00,0x6e,0x06,0xc3,0x00,0x0a,0x07,0x4d,0x00,0x55,0x05,0x1d,0x00,0x5a,0x06,0x24,0x00,0x82, 0x05,0x31,0x00,0x6e,0x05,0x93,0x00,0x32,0x04,0xf8,0x00,0xa0,0x05,0x95,0x00,0x82,0x05,0x00,0x00,0x6e,0x05,0x45,0x00,0x50,0x05,0x7b,0x00,0x32,0x05,0x00,0x00,0xa0,0x06,0x3a,0x00,0x50,0x04,0xc8,0x00,0x50,0x05,0x4e,0x00,0x82,0x06,0x48,0x00,0x64,0x04,0xf2,0x00,0x64,0x05,0x01,0x00,0x64,0x04,0x8d,0x00,0x6e,0x06,0x47,0x00,0x6e, 0x05,0x23,0x00,0x76,0x05,0x31,0x00,0xa0,0x05,0x30,0x00,0x78,0x05,0x96,0x00,0x82,0x03,0x93,0x00,0x00,0x04,0x39,0x00,0x00,0x05,0x23,0x00,0x62,0x06,0x48,0x00,0x64,0x06,0x36,0x00,0x78,0x04,0x56,0x00,0xbe,0x00,0x00,0x14,0xe0,0x19,0x01,0x25,0x01,0x01,0x01,0x22,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x0c,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x01,0x01,0x0c,0x2c,0x01,0x01,0x24,0x01,0x01,0x01,0x03,0x0c,0x01,0x01,0x01,0x01,0x01,0x09,0x22,0x27,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x2e,0x01,0x0c,0x2e,0x0c,0x01,0x01,0x0c,0x01,0x0d,0x0c,0x0c,0x0c, 0x2e,0x01,0x01,0x01,0x0c,0x19,0x0c,0x01,0x01,0x16,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x01,0x03,0x0c,0x09,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x23,0x01,0x2a,0x2a,0x01,0x01,0x24,0x1c,0x01,0x0c,0x2a, 0x01,0x1c,0x1c,0x01,0x0c,0x0f,0x01,0x01,0x01,0x01,0x01,0x0c,0x04,0x0c,0x01,0x01,0x01,0x01,0x1f,0x01,0x1c,0x27,0x01,0x01,0x0e,0x01,0x01,0x0c,0x01,0x08,0x01,0x01,0x01,0x01,0x19,0x19,0x01,0x01,0x01,0x0c,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x09, 0x09,0x09,0x01,0x01,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x01,0x01,0x01,0x16,0x01,0x01,0x0c,0x0c,0x01,0x01,0x0c,0x01,0x01,0x01,0x10,0x10,0x01,0x01,0x01,0x01,0x2c,0x2e,0x01,0x01,0x01,0x0d,0x01,0x0d,0x01,0x2e,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x03,0x0c,0x03,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x0c,0x09,0x0c,0x01,0x16,0x01,0x16,0x01,0x01,0x0e,0x24,0x0c,0x01,0x15,0x29,0x0d,0x01,0x01,0x01,0x01,0x05,0x0c,0x01,0x19,0x01,0x01,0x12,0x19,0x19,0x19,0x19,0x19,0x01,0x01,0x0d,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2e,0x2c, 0x2e,0x2c,0x2e,0x01,0x0c,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x24,0x01,0x01,0x0c,0x0c,0x01,0x01,0x03,0x0c,0x03,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x27,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x04,0x0c,0x0c,0x0c,0x27,0x0c,0x27,0x0c,0x27,0x0c,0x0c,0x01, 0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x03,0x01,0x0c,0x01,0x01,0x01,0x01,0x0c,0x01,0x0e,0x0c,0x01,0x0c,0x24,0x01,0x0c,0x01,0x0c,0x01,0x1b,0x01,0x0c,0x0c,0x01,0x01,0x04,0x0e,0x01,0x01,0x0c,0x0c,0x27,0x0c,0x01, 0x0e,0x0d,0x01,0x0c,0x0c,0x0c,0x0d,0x01,0x01,0x01,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x0d,0x0d,0x07,0x07,0x01,0x1b,0x01,0x01,0x0c,0x01,0x01,0x0d,0x01,0x01,0x0c,0x01,0x22,0x20,0x0e,0x1a,0x01,0x1f,0x01,0x2c,0x01,0x22,0x01,0x0c,0x01,0x0c,0x0d,0x01,0x0e,0x26,0x26,0x26,0x0c,0x26,0x0d, 0x0e,0x0c,0x0e,0x0c,0x01,0x01,0x01,0x2c,0x01,0x0e,0x0c,0x0e,0x26,0x22,0x01,0x01,0x01,0x01,0x01,0x01,0x0e,0x0c,0x01,0x01,0x01,0x0e,0x2d,0x0c,0x0c,0x01,0x0e,0x01,0x01,0x01,0x2e,0x01,0x01,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x0c,0x25,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x25,0x0c, 0x25,0x0c,0x25,0x0c,0x25,0x0c,0x25,0x09,0x0c,0x09,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x07,0x26,0x01,0x24,0x01,0x01,0x23,0x01,0x28,0x01,0x29,0x22,0x01,0x02,0x22,0x0e,0x0c,0x0e,0x0c,0x0e,0x01,0x02,0x01,0x0c,0x20,0x0c,0x01,0x01,0x01,0x0c,0x01,0x01,0x01, 0x01,0x24,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x0d,0x01,0x01,0x2e,0x01,0x2e,0x01,0x2e,0x01,0x2e,0x01,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x2c,0x2e,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x01,0x01,0x01,0x01, 0x0c,0x01,0x0c,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x01,0x0d,0x01,0x0d,0x03,0x0c,0x03,0x0c,0x03,0x0c,0x03,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x0c,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x22,0x19,0x22,0x19,0x27,0x0c,0x27,0x0c,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x16,0x01,0x16,0x01,0x16,0x0c,0x01,0x0c,0x01,0x01,0x01,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x01,0x01,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x22,0x22,0x22, 0x22,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2a,0x2a,0x02,0x02,0x19,0x01,0x19,0x19,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d, 0x0d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x24,0x24,0x01,0x01,0x0c,0x0c,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0d,0x0d,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x01,0x01,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01, 0x01,0x01,0x0d,0x0d,0x0d,0x0d,0x0d,0x01,0x01,0x29,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x2d,0x01,0x1e,0x01,0x01,0x01,0x01,0x0d,0x01,0x01,0x22,0x05,0x01,0x01,0x01,0x04,0x01,0x04,0x01,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x32,0x1a,0x15,0x1a,0x15,0x01,0x22,0x25,0x01,0x01,0x16,0x0a,0x0a,0x01,0x01,0x01,0x01,0x1a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x13,0x15,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2e,0x2c,0x2e,0x01,0x0c, 0x01,0x01,0x01,0x01,0x0a,0x01,0x01,0x01,0x13,0x15,0x2c,0x2e,0x01,0x01,0x03,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x09,0x0c,0x09,0x0c,0x01,0x01,0x01,0x0c,0x30,0x01,0x01,0x01,0x16,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x2e,0x01,0x2e,0x2d,0x2d,0x2e,0x2e,0x01,0x29,0x01,0x01,0x01,0x01,0x0a,0x2e,0x2e,0x01,0x19,0x01,0x01,0x01,0x01,0x16,0x01,0x28,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x03,0x01,0x01,0x1f,0x1a,0x1a,0x01,0x01,0x01,0x19,0x01,0x01, 0x01,0x16,0x2b,0x01,0x01,0x1b,0x1b,0x1b,0x2d,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x01,0x2e,0x1b,0x1b,0x07,0x0b,0x16,0x17,0x01,0x01,0x01,0x01,0x25,0x02,0x02,0x01,0x22,0x01,0x2e,0x01,0x1e,0x01,0x01,0x01,0x01,0x07,0x01,0x04,0x2a,0x01,0x01,0x01,0x02,0x01,0x01,0x19,0x01,0x01,0x01,0x0a,0x1a,0x01,0x01,0x26,0x01,0x01,0x01,0x01, 0x07,0x01,0x01,0x01,0x01,0x01,0x0c,0x2e,0x01,0x01,0x01,0x01,0x01,0x08,0x05,0x01,0x01,0x01,0x01,0x07,0x01,0x0b,0x1f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x01,0x01,0x1f,0x01,0x01,0x0c,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0b,0x01,0x01,0x22,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x26,0x01,0x01,0x2f,0x01,0x0a, 0x2d,0x01,0x01,0x01,0x01,0x2c,0x01,0x09,0x01,0x01,0x10,0x01,0x10,0x01,0x0d,0x0e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x0e,0x0d,0x26,0x01,0x01,0x07,0x26,0x07,0x26,0x0c,0x0c,0x01,0x0c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x0c,0x1f,0x01,0x25,0x2e,0x01,0x01, 0x01,0x0a,0x01,0x01,0x26,0x01,0x30,0x01,0x01,0x22,0x15,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x23,0x01,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x2d,0x2d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x16,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30, 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x30,0x01,0x30,0x30,0x30,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x01,0x01,0x1f,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x0d,0x26,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x0c,0x16,0x01,0x01,0x01,0x0c,0x01,0x0e,0x01,0x22,0x01,0x2c,0x29,0x01,0x24,0x01,0x01, 0x01,0x01,0x2f,0x14,0x01,0x19,0x1f,0x01,0x01,0x01,0x1c,0x01,0x01,0x01,0x01,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x25,0x25,0x01,0x01,0x01,0x02,0x01,0x14,0x01,0x14,0x14,0x01,0x01,0x01,0x01,0x02,0x01,0x25,0x01,0x01,0x14,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x26,0x01,0x01,0x30,0x01,0x05,0x01, 0x01,0x01,0x19,0x01,0x01,0x26,0x2e,0x01,0x01,0x01,0x01,0x01,0x2a,0x18,0x18,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x16,0x2f,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x0d,0x01,0x01,0x01,0x0c,0x2e,0x0c,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x16,0x2e,0x01,0x01,0x01,0x01,0x28,0x01,0x01,0x01,0x01,0x0c,0x2e,0x0c,0x2e,0x0c,0x01,0x0d,0x0c, 0x0c,0x01,0x01,0x01,0x19,0x01,0x16,0x01,0x2e,0x2e,0x01,0x01,0x26,0x01,0x01,0x2d,0x03,0x0c,0x01,0x01,0x01,0x01,0x01,0x25,0x1f,0x01,0x01,0x01,0x01,0x01,0x1b,0x1b,0x01,0x01,0x01,0x1e,0x02,0x02,0x01,0x01,0x1c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2a,0x01,0x01,0x2d,0x2d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x14, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x0c,0x0c,0x0c,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x01, 0x01,0x01,0x10,0x10,0x01,0x10,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x10,0x01,0x10,0x10,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x25,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x19,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x2c,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x19,0x19,0x19,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x30,0x01,0x01,0x01,0x01,0x01,0x19,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x19,0x19,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x19,0x19,0x19,0x19,0x01,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01, 0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2c,0x05,0x01,0x01,0x01,0x0c,0x04,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x30,0x01,0x01, 0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x2c,0x01,0x01,0x2c,0x01,0x01,0x01,0x30,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x01,0x01,0x01,0x24,0x01,0x01,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x23,0x01,0x01, 0x01,0x01,0x01,0x0d,0x01,0x1b,0x26,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x22,0x29,0x13,0x01,0x01,0x04,0x1e,0x01,0x01,0x06,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x08,0x2f,0x01,0x2e,0x27,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x13,0x01,0x13,0x01,0x27,0x32,0x01,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x1b,0x13,0x13,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x10,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x01,0x2f,0x01,0x01,0x01,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x01,0x01,0x01,0x01,0x08,0x2b,0x17,0x17,0x17,0x19,0x01,0x12,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x01,0x01,0x01, 0x01,0x2b,0x01,0x08,0x08,0x08,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x01,0x08,0x01,0x01,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x2b,0x01,0x01,0x01,0x08,0x2b,0x01,0x01,0x01,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0xfd,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x01,0x20,0x01,0x09,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x01,0x20,0x01,0x2c,0x01,0x01,0x01,0x01,0x28,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x18,0x01,0x01,0x1f,0x10, 0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x01,0x0c,0x01,0x28,0x01,0x01,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x24,0x01,0x01,0x01,0x01,0x2f,0x01,0x24,0x24,0x24,0x0f,0x24,0x30,0x24,0x0e,0x02,0x24,0x17,0x01,0x24,0x0e,0x26,0x26,0x16,0x01,0x24,0x0e,0x0e,0x01,0x24,0x24,0x24,0x24,0x24,0x16,0x30,0x01,0x24, 0x01,0x17,0x01,0x01,0x24,0x24,0x16,0x01,0x09,0x16,0x27,0x09,0x01,0x0d,0x09,0x11,0x16,0x1f,0x01,0x01,0x1b,0x09,0x01,0x01,0x27,0x01,0x0a,0x01,0x27,0x01,0x2b,0x01,0x15,0x01,0x0a,0x2b,0x01,0x01,0x01,0x01,0x0a,0x01,0x11,0x01,0x01,0x06,0x01,0x01,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x16,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x0c,0x30,0x01,0x2b,0x01,0x01,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x0c,0x01,0x04,0x01,0x2e,0x30,0x04,0x01,0x0c,0x09,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x23,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x23,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x02,0x2d,0x01,0x01,0x31,0x01,0x01,0x01,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x15,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x19,0x19,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x2d,0x2d,0x2d,0x2d,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x1d,0x1d,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x01,0x01,0x01,0x01,0x31,0x01,0x19,0x31,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x01,0x01,0x01,0x1e,0x01,0x01,0x2d,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x16,0x01,0x19,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x23,0x01,0x01,0x01,0x01,0x32,0x01,0x01,0x01,0x01,0x01,0x01,0x2d,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x24,0x0d,0x01,0x01,0x0c,0x01,0x01,0x03,0x01, 0x01,0x01,0x01,0x22,0x22,0x01,0x2c,0x24,0x27,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x09,0x09,0x01,0x01,0x0c,0x0c,0x01,0x01,0x0c,0x0c,0x01,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x19,0x19,0x01,0x01,0x01,0x01,0x01,0x2c,0x2e,0x01,0x0c,0x03,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x01, 0x01,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2c,0x01,0x01,0x2c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x30,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x2c,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x01,0x01,0x01,0x01,0x0c,0x01,0x25,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x16,0x01,0x01,0x0a,0x01,0x01,0x01,0x01,0x01,0x23,0x01,0x28,0x01,0x03,0x01,0x01,0x25,0x01,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x01,0x01,0x14,0x01,0x01,0x01,0x01,0x15,0x01,0x01,0x31,0x31,0x01,0x01,0x01,0x18,0x01,0x01,0x26,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x05, 0x01,0x2d,0x1d,0x0b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x03,0x12,0x01,0x2c,0x01,0x07,0x01,0x01,0x01,0x2d,0x01,0x01,0x01,0x32,0x01,0x01,0x01,0x01,0x1f,0x01,0x01,0x01,0x01,0x16,0x01,0x1b,0x01,0x29,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x23,0x01,0x01,0x12,0x01,0x01,0x0d,0x27,0x01,0x01,0x25,0x20,0x01,0x17,0x01,0x01,0x17, 0x17,0x01,0x20,0x17,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x0d,0x20,0x20,0x01,0x01,0x01,0x24,0x01,0x01,0x01,0x01,0x1e,0x32,0x01,0x15,0x01,0x01,0x01,0x02,0x16,0x01,0x1d,0x01,0x01,0x01,0x01,0x02,0x01,0x11,0x01,0x01,0x01,0x01,0x01,0x26,0x01,0x01,0x01,0x01,0x01,0x22,0x01,0x01,0x01,0x19,0x19,0x19,0x19,0x19,0x19,0x01,0x19,0x19, 0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0b,0x01,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x01,0x01,0x01,0x01,0x01,0x12,0x01,0x11,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x2a,0x01,0x01,0x01,0x01,0x01, 0x30,0x01,0x01,0x01,0x01,0x01,0x1b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x01,0x01,0x01,0x01,0x01,0x14,0x29,0x14,0x14,0x14,0x01,0x30,0x30,0x2c,0x01,0x01,0x19,0x19,0x19,0x01,0x19,0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x01,0x07,0x01,0x01,0x01,0x01,0x01,0x09,0x16,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x25,0x01,0x07,0x01,0x01,0x01,0x01,0x01,0x17,0x01,0x01,0x01,0x01,0x01,0x01,0x22,0x01,0x0c,0x01, 0x01,0x01,0x01,0x24,0x01,0x01,0x01,0x01,0x08,0x01,0x25,0x01,0x01,0x01,0x01,0x17,0x01,0x01,0x26,0x01,0x06,0x1b,0x01,0x01,0x01,0x1b,0x01,0x1a,0x01,0x01,0x01,0x01,0x01,0x01,0x1a,0x25,0x01,0x01,0x25,0x01,0x20,0x01,0x17,0x1a,0x01,0x15,0x2c,0x2c,0x23,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x17,0x17,0x17,0x17,0x17, 0x17,0x17,0x17,0x17,0x17,0x01,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27, 0x27,0x27,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x32, 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x14,0x01,0x01,0x01,0x22,0x01,0x01,0x2d,0x01,0x01,0x01,0x01,0x26,0x2b,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x02,0x01,0x02,0x2e,0x01,0x01,0x01,0x01,0x01,0x28,0x18,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x2e,0x01,0x01,0x01,0x01,0x01,0x01,0x22,0x19,0x27,0x01,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1d,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x24,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x31,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x1a,0x01,0x01,0x01,0x2c,0x2e,0x01,0x02,0x03, 0x01,0x01,0x01,0x01,0x01,0x01,0x2f,0x22,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x06,0x01,0x1f,0x07,0x07,0x01,0x17,0x01,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x01,0x2e,0x0d,0x12,0x01,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x1b,0x2c,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x25,0x25,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1f,0x01,0x01,0x01,0x13,0x07,0x26,0x01,0x01,0x01,0x07,0x01,0x01,0x01,0x01, 0x02,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0a,0x01,0x01,0x02,0x13,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x0c,0x01,0x01,0x01,0x01,0x20,0x01,0x01,0x01,0x20,0x01,0x0d,0x01,0x01,0x01,0x01,0x07,0x24,0x04,0x01,0x01,0x10,0x0c,0x2e,0x01,0x25,0x01,0x01,0x07,0x01,0x01,0x01,0x01,0x08,0x08,0x0a,0x01,0x01,0x16,0x10,0x01,0x01,0x0d,0x01,0x01,0x01,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2f, 0x2c,0x11,0x01,0x01,0x10,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x22,0x01,0x01,0x20,0x01,0x01,0x01,0x19,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2c,0x01,0x01,0x2c,0x01, 0x01,0x01,0x01,0x01,0x01,0x24,0x03,0x01,0x01,0x01,0x01,0x01,0x20,0x01,0x01,0x0b,0x01,0x01,0x01,0x01,0x0a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x0c,0x01,0x1c,0x01,0x01,0x01,0x01,0x0d,0x2d,0x01,0x2a,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x2c,0x2c,0x2c,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x30,0x01,0x01,0x01,0x2c,0x01,0x01,0x2c,0x01,0x01,0x2c,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, 0x1e,0x1e,0x1e,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x32,0x01,0x18,0x30,0x01,0x01,0x18,0x26,0x01,0x01,0x18,0x18,0x01,0x01,0x1e,0x01,0x2b,0x01,0x01,0x1d,0x30,0x01,0x22,0x31,0x01,0x01,0x1c,0x01,0x01,0x2f,0x01,0x08,0x01,0x01, 0x1e,0x08,0x08,0x30,0x01,0x01,0x01,0x01,0x08,0x08,0x01,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x0c,0x00,0xf8,0x08,0xff,0x00,0x08,0x00,0x09,0xff,0xfe,0x00,0x09,0x00,0x0a,0xff,0xfe,0x00,0x0a,0x00,0x0a,0xff,0xfe,0x00,0x0b,0x00,0x0b,0xff,0xfe,0x00,0x0c,0x00,0x0c,0xff,0xfd,0x00,0x0d,0x00,0x0e,0xff,0xfd, 0x00,0x0e,0x00,0x0f,0xff,0xfc,0x00,0x0f,0x00,0x10,0xff,0xfc,0x00,0x10,0x00,0x11,0xff,0xfc,0x00,0x11,0x00,0x12,0xff,0xfb,0x00,0x12,0x00,0x14,0xff,0xfb,0x00,0x13,0x00,0x14,0xff,0xfb,0x00,0x14,0x00,0x17,0xff,0xfb,0x00,0x15,0x00,0x18,0xff,0xfa,0x00,0x16,0x00,0x18,0xff,0xfa,0x00,0x17,0x00,0x19,0xff,0xfa,0x00,0x18,0x00,0x1a, 0xff,0xfa,0x00,0x19,0x00,0x1c,0xff,0xf9,0x00,0x1a,0x00,0x1d,0xff,0xf9,0x00,0x1b,0x00,0x1e,0xff,0xf9,0x00,0x1c,0x00,0x1f,0xff,0xf9,0x00,0x1d,0x00,0x20,0xff,0xf8,0x00,0x1e,0x00,0x21,0xff,0xf8,0x00,0x1f,0x00,0x22,0xff,0xf8,0x00,0x20,0x00,0x24,0xff,0xf7,0x00,0x21,0x00,0x24,0xff,0xf7,0x00,0x22,0x00,0x25,0xff,0xf7,0x00,0x23, 0x00,0x26,0xff,0xf7,0x00,0x24,0x00,0x27,0xff,0xf7,0x00,0x25,0x00,0x28,0xff,0xf6,0x00,0x26,0x00,0x29,0xff,0xf6,0x00,0x27,0x00,0x2a,0xff,0xf6,0x00,0x28,0x00,0x2b,0xff,0xf5,0x00,0x29,0x00,0x2c,0xff,0xf5,0x00,0x2a,0x00,0x2e,0xff,0xf5,0x00,0x2b,0x00,0x2f,0xff,0xf4,0x00,0x2c,0x00,0x30,0xff,0xf4,0x00,0x2d,0x00,0x31,0xff,0xf4, 0x00,0x2e,0x00,0x32,0xff,0xf4,0x00,0x2f,0x00,0x32,0xff,0xf4,0x00,0x30,0x00,0x34,0xff,0xf3,0x00,0x31,0x00,0x35,0xff,0xf3,0x00,0x32,0x00,0x36,0xff,0xf3,0x00,0x33,0x00,0x37,0xff,0xf3,0x00,0x34,0x00,0x38,0xff,0xf2,0x00,0x35,0x00,0x39,0xff,0xf2,0x00,0x36,0x00,0x3a,0xff,0xf2,0x00,0x37,0x00,0x3c,0xff,0xf2,0x00,0x38,0x00,0x3c, 0xff,0xf2,0x00,0x39,0x00,0x3d,0xff,0xf1,0x00,0x3a,0x00,0x3e,0xff,0xf1,0x00,0x3b,0x00,0x3f,0xff,0xf1,0x00,0x3c,0x00,0x41,0xff,0xf0,0x00,0x3d,0x00,0x42,0xff,0xf0,0x00,0x3e,0x00,0x44,0xff,0xf0,0x00,0x3f,0x00,0x45,0xff,0xf0,0x00,0x40,0x00,0x45,0xff,0xef,0x00,0x41,0x00,0x46,0xff,0xef,0x00,0x42,0x00,0x47,0xff,0xef,0x00,0x43, 0x00,0x48,0xff,0xef,0x00,0x44,0x00,0x49,0xff,0xee,0x00,0x45,0x00,0x4a,0xff,0xee,0x00,0x46,0x00,0x4b,0xff,0xee,0x00,0x47,0x00,0x4c,0xff,0xee,0x00,0x48,0x00,0x4d,0xff,0xed,0x00,0x49,0x00,0x4f,0xff,0xed,0x00,0x4a,0x00,0x50,0xff,0xed,0x00,0x4b,0x00,0x51,0xff,0xed,0x00,0x4c,0x00,0x51,0xff,0xec,0x00,0x4d,0x00,0x52,0xff,0xec, 0x00,0x4e,0x00,0x54,0xff,0xec,0x00,0x4f,0x00,0x55,0xff,0xec,0x00,0x50,0x00,0x56,0xff,0xec,0x00,0x51,0x00,0x57,0xff,0xeb,0x00,0x52,0x00,0x58,0xff,0xeb,0x00,0x53,0x00,0x59,0xff,0xeb,0x00,0x54,0x00,0x5a,0xff,0xea,0x00,0x55,0x00,0x5b,0xff,0xea,0x00,0x56,0x00,0x5c,0xff,0xea,0x00,0x57,0x00,0x5e,0xff,0xea,0x00,0x58,0x00,0x5e, 0xff,0xea,0x00,0x59,0x00,0x5f,0xff,0xe9,0x00,0x5a,0x00,0x61,0xff,0xe9,0x00,0x5b,0x00,0x61,0xff,0xe9,0x00,0x5c,0x00,0x63,0xff,0xe8,0x00,0x5d,0x00,0x64,0xff,0xe8,0x00,0x5e,0x00,0x65,0xff,0xe8,0x00,0x5f,0x00,0x66,0xff,0xe7,0x00,0x60,0x00,0x67,0xff,0xe7,0x00,0x61,0x00,0x69,0xff,0xe7,0x00,0x62,0x00,0x69,0xff,0xe7,0x00,0x63, 0x00,0x6a,0xff,0xe7,0x00,0x64,0x00,0x6b,0xff,0xe6,0x00,0x65,0x00,0x6d,0xff,0xe6,0x00,0x66,0x00,0x6e,0xff,0xe6,0x00,0x67,0x00,0x6f,0xff,0xe6,0x00,0x68,0x00,0x70,0xff,0xe5,0x00,0x69,0x00,0x71,0xff,0xe5,0x00,0x6a,0x00,0x72,0xff,0xe5,0x00,0x6b,0x00,0x73,0xff,0xe5,0x00,0x6c,0x00,0x75,0xff,0xe4,0x00,0x6d,0x00,0x76,0xff,0xe4, 0x00,0x6e,0x00,0x76,0xff,0xe4,0x00,0x6f,0x00,0x77,0xff,0xe4,0x00,0x70,0x00,0x79,0xff,0xe4,0x00,0x71,0x00,0x79,0xff,0xe3,0x00,0x72,0x00,0x7b,0xff,0xe3,0x00,0x73,0x00,0x7b,0xff,0xe3,0x00,0x74,0x00,0x7c,0xff,0xe3,0x00,0x75,0x00,0x7d,0xff,0xe2,0x00,0x76,0x00,0x7e,0xff,0xe2,0x00,0x77,0x00,0x80,0xff,0xe2,0x00,0x78,0x00,0x80, 0xff,0xe1,0x00,0x79,0x00,0x82,0xff,0xe1,0x00,0x7a,0x00,0x82,0xff,0xe1,0x00,0x7b,0x00,0x84,0xff,0xe1,0x00,0x7c,0x00,0x85,0xff,0xe1,0x00,0x7d,0x00,0x86,0xff,0xe0,0x00,0x7e,0x00,0x87,0xff,0xe0,0x00,0x7f,0x00,0x88,0xff,0xe0,0x00,0x80,0x00,0x89,0xff,0xdf,0x00,0x81,0x00,0x8a,0xff,0xdf,0x00,0x82,0x00,0x8c,0xff,0xdf,0x00,0x83, 0x00,0x8d,0xff,0xdf,0x00,0x84,0x00,0x8e,0xff,0xde,0x00,0x85,0x00,0x8e,0xff,0xdf,0x00,0x86,0x00,0x8f,0xff,0xde,0x00,0x87,0x00,0x90,0xff,0xde,0x00,0x88,0x00,0x92,0xff,0xde,0x00,0x89,0x00,0x93,0xff,0xdd,0x00,0x8a,0x00,0x94,0xff,0xdd,0x00,0x8b,0x00,0x95,0xff,0xdd,0x00,0x8c,0x00,0x96,0xff,0xdc,0x00,0x8d,0x00,0x97,0xff,0xdc, 0x00,0x8e,0x00,0x99,0xff,0xdc,0x00,0x8f,0x00,0x9a,0xff,0xdc,0x00,0x90,0x00,0x9a,0xff,0xdb,0x00,0x91,0x00,0x9b,0xff,0xdb,0x00,0x92,0x00,0x9c,0xff,0xdb,0x00,0x93,0x00,0x9e,0xff,0xdb,0x00,0x94,0x00,0x9f,0xff,0xda,0x00,0x95,0x00,0xa0,0xff,0xda,0x00,0x96,0x00,0xa1,0xff,0xda,0x00,0x97,0x00,0xa2,0xff,0xda,0x00,0x98,0x00,0xa3, 0xff,0xd9,0x00,0x99,0x00,0xa4,0xff,0xd9,0x00,0x9a,0x00,0xa5,0xff,0xd9,0x00,0x9b,0x00,0xa6,0xff,0xd9,0x00,0x9c,0x00,0xa7,0xff,0xd8,0x00,0x9d,0x00,0xa8,0xff,0xd8,0x00,0x9e,0x00,0xa9,0xff,0xd8,0x00,0x9f,0x00,0xab,0xff,0xd8,0x00,0xa0,0x00,0xab,0xff,0xd7,0x00,0xa1,0x00,0xad,0xff,0xd7,0x00,0xa2,0x00,0xae,0xff,0xd7,0x00,0xa3, 0x00,0xaf,0xff,0xd7,0x00,0xa4,0x00,0xb1,0xff,0xd6,0x00,0xa5,0x00,0xb1,0xff,0xd6,0x00,0xa6,0x00,0xb2,0xff,0xd6,0x00,0xa7,0x00,0xb3,0xff,0xd6,0x00,0xa8,0x00,0xb3,0xff,0xd5,0x00,0xa9,0x00,0xb6,0xff,0xd5,0x00,0xaa,0x00,0xb7,0xff,0xd5,0x00,0xab,0x00,0xb8,0xff,0xd5,0x00,0xac,0x00,0xb8,0xff,0xd4,0x00,0xad,0x00,0xb9,0xff,0xd4, 0x00,0xae,0x00,0xba,0xff,0xd4,0x00,0xaf,0x00,0xbb,0xff,0xd3,0x00,0xb0,0x00,0xbe,0xff,0xd3,0x00,0xb1,0x00,0xbe,0xff,0xd3,0x00,0xb2,0x00,0xbf,0xff,0xd3,0x00,0xb3,0x00,0xc0,0xff,0xd3,0x00,0xb4,0x00,0xc1,0xff,0xd2,0x00,0xb5,0x00,0xc2,0xff,0xd2,0x00,0xb6,0x00,0xc3,0xff,0xd2,0x00,0xb7,0x00,0xc5,0xff,0xd2,0x00,0xb8,0x00,0xc5, 0xff,0xd1,0x00,0xb9,0x00,0xc6,0xff,0xd1,0x00,0xba,0x00,0xc8,0xff,0xd1,0x00,0xbb,0x00,0xc9,0xff,0xd1,0x00,0xbc,0x00,0xca,0xff,0xd0,0x00,0xbd,0x00,0xcb,0xff,0xd0,0x00,0xbe,0x00,0xcb,0xff,0xd0,0x00,0xbf,0x00,0xcd,0xff,0xd0,0x00,0xc0,0x00,0xcd,0xff,0xcf,0x00,0xc1,0x00,0xcf,0xff,0xcf,0x00,0xc2,0x00,0xd0,0xff,0xcf,0x00,0xc3, 0x00,0xd0,0xff,0xcf,0x00,0xc4,0x00,0xd1,0xff,0xce,0x00,0xc5,0x00,0xd3,0xff,0xce,0x00,0xc6,0x00,0xd4,0xff,0xce,0x00,0xc7,0x00,0xd5,0xff,0xce,0x00,0xc8,0x00,0xd6,0xff,0xcd,0x00,0xc9,0x00,0xd7,0xff,0xcd,0x00,0xca,0x00,0xd8,0xff,0xcd,0x00,0xcb,0x00,0xd9,0xff,0xcd,0x00,0xcc,0x00,0xda,0xff,0xcc,0x00,0xcd,0x00,0xdc,0xff,0xcc, 0x00,0xce,0x00,0xdc,0xff,0xcc,0x00,0xcf,0x00,0xdd,0xff,0xcc,0x00,0xd0,0x00,0xde,0xff,0xcb,0x00,0xd1,0x00,0xe0,0xff,0xcb,0x00,0xd2,0x00,0xe1,0xff,0xcb,0x00,0xd3,0x00,0xe2,0xff,0xcb,0x00,0xd4,0x00,0xe3,0xff,0xca,0x00,0xd5,0x00,0xe4,0xff,0xca,0x00,0xd6,0x00,0xe5,0xff,0xca,0x00,0xd7,0x00,0xe6,0xff,0xca,0x00,0xd8,0x00,0xe7, 0xff,0xc9,0x00,0xd9,0x00,0xe8,0xff,0xc9,0x00,0xda,0x00,0xea,0xff,0xc9,0x00,0xdb,0x00,0xeb,0xff,0xc9,0x00,0xdc,0x00,0xeb,0xff,0xc8,0x00,0xdd,0x00,0xed,0xff,0xc8,0x00,0xde,0x00,0xee,0xff,0xc8,0x00,0xdf,0x00,0xee,0xff,0xc8,0x00,0xe0,0x00,0xf0,0xff,0xc7,0x00,0xe1,0x00,0xf1,0xff,0xc7,0x00,0xe2,0x00,0xf3,0xff,0xc6,0x00,0xe3, 0x00,0xf3,0xff,0xc6,0x00,0xe4,0x00,0xf4,0xff,0xc6,0x00,0xe5,0x00,0xf5,0xff,0xc6,0x00,0xe6,0x00,0xf6,0xff,0xc6,0x00,0xe7,0x00,0xf8,0xff,0xc6,0x00,0xe8,0x00,0xf8,0xff,0xc5,0x00,0xe9,0x00,0xfa,0xff,0xc5,0x00,0xea,0x00,0xfb,0xff,0xc5,0x00,0xeb,0x00,0xfb,0xff,0xc5,0x00,0xec,0x00,0xfd,0xff,0xc4,0x00,0xed,0x00,0xfd,0xff,0xc4, 0x00,0xee,0x00,0xff,0xff,0xc4,0x00,0xef,0x01,0x01,0xff,0xc4,0x00,0xf0,0x01,0x01,0xff,0xc3,0x00,0xf1,0x01,0x03,0xff,0xc3,0x00,0xf2,0x01,0x03,0xff,0xc3,0x00,0xf3,0x01,0x04,0xff,0xc3,0x00,0xf4,0x01,0x05,0xff,0xc2,0x00,0xf5,0x01,0x07,0xff,0xc2,0x00,0xf6,0x01,0x08,0xff,0xc2,0x00,0xf7,0x01,0x09,0xff,0xc2,0x00,0xf8,0x01,0x0a, 0xff,0xc1,0x00,0xf9,0x01,0x0b,0xff,0xc1,0x00,0xfa,0x01,0x0c,0xff,0xc1,0x00,0xfb,0x01,0x0d,0xff,0xc1,0x00,0xfc,0x01,0x0f,0xff,0xc0,0x00,0xfd,0x01,0x10,0xff,0xc0,0x00,0xfe,0x01,0x10,0xff,0xc0,0x00,0xff,0x01,0x11,0xff,0xc0,0x00,0x00,0x00,0x11,0x00,0x00,0x14,0xe4,0x0b,0x16,0x07,0x00,0x01,0x03,0x03,0x04,0x07,0x06,0x09,0x09, 0x03,0x03,0x03,0x05,0x08,0x03,0x04,0x03,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x08,0x08,0x08,0x05,0x0b,0x07,0x06,0x07,0x08,0x06,0x06,0x08,0x08,0x03,0x04,0x06,0x05,0x0a,0x08,0x09,0x06,0x08,0x07,0x06,0x06,0x08,0x07,0x0b,0x06,0x05,0x06,0x03,0x04,0x03,0x08,0x05,0x03,0x06,0x07,0x05,0x07,0x06,0x04, 0x07,0x07,0x03,0x03,0x06,0x03,0x09,0x07,0x07,0x07,0x07,0x04,0x05,0x04,0x07,0x05,0x09,0x05,0x05,0x05,0x03,0x03,0x03,0x08,0x07,0x07,0x07,0x06,0x08,0x09,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x04,0x04,0x06,0x06,0x05,0x04,0x05,0x06, 0x04,0x0a,0x0a,0x09,0x03,0x05,0x08,0x09,0x09,0x09,0x08,0x08,0x08,0x06,0x07,0x06,0x07,0x08,0x06,0x04,0x05,0x09,0x09,0x07,0x05,0x03,0x03,0x08,0x07,0x06,0x08,0x07,0x06,0x06,0x09,0x07,0x07,0x09,0x0a,0x0a,0x06,0x0b,0x04,0x04,0x03,0x03,0x08,0x06,0x05,0x05,0x02,0x06,0x03,0x03,0x06,0x06,0x04,0x03,0x03,0x04,0x0d,0x07,0x06,0x07, 0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x09,0x09,0x08,0x08,0x08,0x03,0x04,0x04,0x03,0x03,0x02,0x03,0x02,0x04,0x02,0x04,0x05,0x03,0x06,0x05,0x06,0x05,0x03,0x08,0x07,0x05,0x05,0x06,0x07,0x08,0x08,0x04,0x04,0x04,0x0a,0x0a,0x0a,0x05,0x08,0x07,0x03,0x06,0x05,0x07,0x05,0x07,0x05,0x07,0x05,0x03,0x07,0x06,0x07,0x06,0x08,0x07,0x08, 0x06,0x06,0x06,0x06,0x05,0x03,0x05,0x03,0x05,0x03,0x08,0x07,0x08,0x07,0x09,0x07,0x07,0x04,0x07,0x04,0x06,0x05,0x06,0x04,0x06,0x05,0x08,0x07,0x08,0x07,0x06,0x05,0x06,0x05,0x05,0x08,0x07,0x07,0x07,0x05,0x07,0x05,0x09,0x05,0x05,0x04,0x0c,0x07,0x06,0x07,0x03,0x04,0x09,0x04,0x07,0x04,0x04,0x07,0x04,0x07,0x06,0x07,0x05,0x07, 0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x03,0x06,0x06,0x06,0x05,0x03,0x08,0x07,0x08,0x07,0x09,0x07,0x09,0x07,0x07,0x04,0x06,0x05,0x06,0x04,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x0b,0x09,0x05,0x05,0x03,0x07,0x06,0x09,0x09,0x09, 0x07,0x03,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x05,0x05,0x03,0x05,0x06,0x07,0x0a,0x0a,0x0a,0x0a,0x04,0x04,0x03,0x03,0x03,0x07,0x06,0x09,0x04,0x09,0x07,0x09,0x03,0x07,0x06,0x06,0x06,0x08,0x03,0x06,0x07,0x0a,0x08,0x06,0x09,0x08,0x06,0x06,0x06,0x05,0x06,0x09,0x09,0x03,0x05,0x07,0x05,0x07,0x03,0x07,0x06,0x06,0x05,0x07,0x07,0x03, 0x06,0x05,0x07,0x06,0x05,0x07,0x07,0x05,0x07,0x06,0x09,0x09,0x03,0x07,0x07,0x07,0x09,0x06,0x08,0x05,0x07,0x06,0x03,0x0b,0x0b,0x08,0x06,0x06,0x08,0x07,0x06,0x06,0x05,0x08,0x06,0x0b,0x06,0x08,0x08,0x06,0x07,0x0a,0x08,0x09,0x08,0x06,0x07,0x06,0x06,0x07,0x06,0x08,0x07,0x0b,0x0b,0x08,0x09,0x06,0x07,0x0b,0x07,0x06,0x07,0x06, 0x05,0x06,0x06,0x09,0x05,0x07,0x07,0x06,0x06,0x08,0x07,0x07,0x07,0x07,0x05,0x05,0x05,0x09,0x05,0x07,0x07,0x09,0x09,0x07,0x08,0x06,0x05,0x09,0x06,0x06,0x07,0x05,0x05,0x05,0x03,0x09,0x09,0x07,0x06,0x05,0x07,0x05,0x04,0x0b,0x0c,0x07,0x04,0x04,0x04,0x04,0x03,0x06,0x05,0x06,0x09,0x07,0x08,0x07,0x03,0x04,0x03,0x03,0x05,0x05, 0x05,0x05,0x03,0x03,0x03,0x05,0x03,0x05,0x03,0x03,0x03,0x05,0x05,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x07,0x09,0x07,0x09,0x07,0x09, 0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x04,0x06,0x06,0x08,0x07,0x03,0x04,0x03,0x03,0x06,0x05,0x0b,0x09,0x07,0x06,0x06,0x05,0x08,0x07,0x05,0x05,0x05,0x05,0x07,0x05,0x07, 0x07,0x07,0x07,0x08,0x06,0x08,0x07,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x03,0x03,0x06,0x06,0x07,0x06,0x06,0x07,0x06,0x07,0x06,0x07,0x07,0x05,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x08,0x07,0x08,0x07,0x08,0x07,0x08, 0x07,0x08,0x07,0x08,0x07,0x03,0x03,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x03,0x05,0x03,0x05,0x03,0x05,0x03,0x0a,0x09,0x0a,0x09,0x0a,0x09,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x06,0x07,0x06,0x07,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x04,0x06,0x05,0x06,0x05,0x06,0x05,0x06, 0x05,0x06,0x05,0x06,0x04,0x06,0x04,0x06,0x04,0x06,0x04,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x07,0x05,0x07,0x05,0x0b,0x09,0x0b,0x09,0x06,0x05,0x06,0x05,0x05,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x07,0x04,0x09,0x05,0x06,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x05, 0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x05,0x05,0x07,0x07,0x03,0x03,0x07,0x07,0x07,0x07,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x09,0x09,0x08,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x06,0x06,0x06,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x05,0x05,0x07,0x07,0x07,0x06,0x06,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x07,0x06,0x06,0x06,0x06,0x07,0x07,0x05,0x08,0x08,0x06,0x06,0x07,0x06,0x06,0x05,0x08,0x07,0x0a,0x03,0x03,0x06,0x05,0x03,0x05, 0x0a,0x08,0x06,0x08,0x0b,0x09,0x07,0x06,0x06,0x06,0x05,0x06,0x03,0x04,0x06,0x04,0x06,0x08,0x08,0x06,0x06,0x06,0x05,0x07,0x07,0x05,0x05,0x06,0x06,0x04,0x04,0x06,0x03,0x04,0x05,0x03,0x0e,0x0d,0x0b,0x09,0x08,0x06,0x0c,0x0b,0x09,0x07,0x06,0x03,0x03,0x09,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x06,0x07,0x06, 0x07,0x06,0x09,0x09,0x08,0x06,0x08,0x07,0x06,0x06,0x08,0x06,0x08,0x06,0x07,0x05,0x03,0x0e,0x0d,0x0b,0x08,0x07,0x0b,0x08,0x08,0x07,0x07,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x07,0x09,0x07,0x06,0x04,0x07,0x04,0x08,0x07,0x08,0x07,0x06,0x05,0x08,0x07,0x08,0x06,0x06,0x06,0x05,0x07,0x06,0x09,0x07,0x09, 0x07,0x09,0x07,0x09,0x07,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x06,0x06,0x06,0x07,0x05,0x05,0x06,0x06,0x03,0x06,0x07,0x06,0x05,0x05,0x06,0x06,0x06,0x03,0x03,0x04,0x03,0x04,0x03,0x07,0x09,0x09,0x09,0x06,0x06,0x06,0x06,0x08,0x08,0x07,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x04,0x03,0x03, 0x03,0x03,0x04,0x04,0x07,0x07,0x06,0x05,0x08,0x05,0x05,0x05,0x06,0x05,0x05,0x04,0x04,0x04,0x05,0x07,0x05,0x06,0x06,0x06,0x03,0x05,0x04,0x06,0x04,0x04,0x0a,0x0a,0x0b,0x07,0x05,0x08,0x09,0x06,0x06,0x05,0x05,0x06,0x07,0x06,0x07,0x06,0x07,0x09,0x06,0x08,0x06,0x06,0x05,0x05,0x05,0x07,0x06,0x07,0x05,0x0a,0x09,0x07,0x06,0x07, 0x06,0x07,0x05,0x07,0x05,0x07,0x06,0x06,0x04,0x06,0x06,0x05,0x03,0x08,0x05,0x05,0x0a,0x07,0x07,0x06,0x0a,0x08,0x07,0x05,0x0a,0x08,0x08,0x06,0x0a,0x08,0x06,0x05,0x09,0x08,0x08,0x06,0x08,0x06,0x08,0x06,0x0e,0x0c,0x09,0x07,0x0c,0x0a,0x0a,0x07,0x06,0x05,0x06,0x04,0x05,0x00,0x00,0x0b,0x0a,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 0x05,0x06,0x05,0x08,0x06,0x09,0x07,0x0b,0x09,0x08,0x06,0x07,0x05,0x06,0x05,0x0a,0x08,0x08,0x06,0x09,0x07,0x09,0x07,0x03,0x0b,0x09,0x06,0x06,0x08,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x09,0x09,0x06,0x06,0x08,0x06,0x08,0x06,0x0b,0x09,0x06,0x05,0x06,0x05,0x08,0x07,0x08,0x07,0x09,0x07,0x08,0x07,0x07,0x05,0x06,0x05,0x06,0x05, 0x06,0x05,0x07,0x07,0x09,0x08,0x06,0x07,0x09,0x09,0x09,0x08,0x06,0x05,0x0a,0x09,0x0b,0x09,0x08,0x06,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x06,0x04,0x04,0x02,0x02,0x02,0x02,0x03,0x04,0x03,0x03,0x04,0x02,0x02,0x02,0x04,0x04,0x02,0x02,0x06,0x06, 0x06,0x06,0x04,0x03,0x03,0x04,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x03,0x04,0x04,0x03,0x02,0x03,0x03,0x02,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x04,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04, 0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06, 0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x07,0x03,0x07,0x04,0x07,0x07,0x04,0x04,0x04,0x04,0x04,0x03, 0x04,0x04,0x04,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x05,0x07,0x09,0x05,0x05,0x06,0x06,0x05,0x05,0x03,0x03,0x06,0x04,0x08,0x07,0x07,0x05,0x07,0x07,0x07,0x0a,0x06,0x07,0x07,0x05,0x05,0x05,0x05,0x06,0x06,0x08,0x06,0x05,0x09,0x05,0x05,0x05,0x06,0x05,0x05, 0x07,0x05,0x07,0x06,0x04,0x05,0x04,0x04,0x05,0x03,0x03,0x05,0x05,0x02,0x03,0x04,0x03,0x06,0x05,0x05,0x05,0x04,0x04,0x04,0x03,0x05,0x06,0x03,0x03,0x04,0x05,0x04,0x04,0x03,0x03,0x03,0x03,0x04,0x02,0x03,0x05,0x04,0x04,0x03,0x04,0x04,0x04,0x02,0x04,0x04,0x05,0x03,0x04,0x04,0x03,0x04,0x04,0x03,0x02,0x02,0x04,0x03,0x04,0x03, 0x04,0x04,0x03,0x06,0x02,0x04,0x06,0x0a,0x07,0x06,0x06,0x09,0x07,0x09,0x08,0x06,0x06,0x06,0x05,0x0c,0x05,0x06,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x05,0x05,0x06,0x05,0x05,0x06,0x02,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x05,0x04,0x07,0x07,0x04,0x09,0x06,0x07,0x04,0x04,0x05,0x04,0x05,0x06,0x05,0x06,0x0a,0x07,0x04,0x03,0x06, 0x06,0x07,0x07,0x07,0x04,0x07,0x06,0x03,0x09,0x07,0x07,0x04,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x05,0x05,0x08,0x03,0x05,0x03,0x07,0x05,0x04,0x03,0x03,0x04,0x03,0x02,0x02,0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x03,0x02,0x02,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x03, 0x03,0x04,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x04,0x03,0x03,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x05,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x02,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x09,0x07,0x08,0x06,0x08,0x07,0x0a,0x08,0x06,0x04,0x06,0x08,0x06,0x09,0x08,0x00,0x00,0x00,0x00,0x03,0x03,0x03, 0x03,0x04,0x04,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x09,0x0b,0x05,0x03,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x06,0x0b,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x06,0x06,0x06,0x04,0x06,0x04,0x08,0x07,0x06,0x04,0x09,0x06,0x09,0x03,0x04,0x06,0x06,0x07,0x07,0x07,0x06,0x06,0x06,0x09,0x03,0x06,0x03,0x06,0x05,0x03,0x03, 0x06,0x03,0x08,0x03,0x0a,0x06,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x0d,0x0d,0x0f,0x0f,0x09,0x09,0x06,0x06,0x02,0x0b,0x08,0x09,0x07,0x06,0x07,0x06,0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x03,0x07,0x00,0x07,0x07,0x07,0x04,0x06,0x06,0x0a,0x04,0x0a,0x04,0x06,0x07,0x06,0x05,0x0a,0x06,0x0a,0x06, 0x08,0x09,0x04,0x06,0x06,0x05,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x0a,0x04,0x06,0x05,0x07,0x06,0x04,0x06,0x06,0x06,0x0a,0x04,0x0a,0x04,0x03,0x06,0x04,0x0b,0x06,0x06,0x07,0x07,0x0b,0x06,0x00,0x00,0x00,0x07,0x00,0x07,0x07,0x07,0x07,0x08,0x07,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x06,0x06, 0x08,0x09,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x06,0x05,0x05,0x05,0x0d,0x09,0x0d,0x09,0x0d,0x09,0x0f,0x0b,0x0f,0x0b,0x09,0x06,0x06,0x06,0x06,0x0b,0x0b, 0x06,0x06,0x0b,0x06,0x06,0x0b,0x06,0x06,0x0b,0x06,0x06,0x08,0x08,0x0c,0x0b,0x0a,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x07,0x04,0x07,0x04,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x0a,0x08,0x09,0x04, 0x06,0x08,0x09,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x05,0x00,0x00,0x07,0x00,0x00,0x00,0x0d,0x09,0x0f,0x0b,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x04,0x06,0x06,0x07,0x0e,0x09,0x06,0x11,0x0c,0x04, 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x05,0x05,0x08,0x07,0x07,0x06,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x0e,0x11,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x05,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x06,0x06,0x06,0x06,0x07,0x06,0x06,0x06,0x05,0x0d, 0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0b,0x06,0x06,0x0b,0x06,0x06,0x0a,0x06,0x06,0x0a,0x06,0x06,0x0a,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x07,0x04,0x04,0x05,0x05,0x0d,0x09,0x07,0x06,0x06,0x00,0x06,0x06,0x06,0x04,0x06,0x08,0x07,0x06,0x06,0x04,0x03,0x08,0x06,0x07, 0x04,0x06,0x05,0x05,0x05,0x05,0x03,0x06,0x05,0x07,0x05,0x06,0x05,0x06,0x05,0x07,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x05,0x05,0x03,0x06,0x06,0x07,0x06,0x04,0x08,0x06,0x07,0x06,0x07,0x05,0x06,0x06,0x04,0x08,0x04,0x05,0x05,0x05,0x07,0x07,0x06,0x0b,0x06,0x0b,0x04,0x03,0x02,0x06,0x02,0x01,0x00,0x02, 0x02,0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x0a,0x05,0x08,0x07,0x0b,0x09,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05,0x09,0x05,0x09,0x07,0x08,0x08,0x08,0x08,0x09,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x06,0x0c,0x09,0x05,0x05,0x03, 0x03,0x03,0x04,0x03,0x06,0x03,0x03,0x09,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x06,0x05,0x05,0x07,0x03,0x04,0x07,0x07,0x03,0x06,0x06,0x06,0x08,0x07,0x03,0x04,0x07,0x07,0x07,0x07,0x06,0x06,0x07,0x06,0x09,0x08,0x06,0x06,0x06,0x03,0x04,0x06,0x06, 0x06,0x06,0x06,0x07,0x07,0x05,0x07,0x06,0x06,0x08,0x06,0x08,0x06,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x06,0x05,0x05,0x07,0x03,0x04,0x07,0x03,0x06,0x06,0x06,0x07,0x04,0x07,0x07,0x07,0x06,0x07,0x06,0x09,0x08,0x03,0x06,0x06,0x07,0x07,0x0d,0x00,0x07,0x06,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x03,0x00,0x08,0x07,0x07,0x08,0x06,0x07,0x08,0x08,0x05,0x07,0x08,0x08,0x07,0x08,0x09,0x09,0x07,0x06,0x06,0x08,0x08,0x06,0x08,0x07,0x07,0x07,0x08,0x08,0x06,0x07,0x07,0x07,0x09,0x07,0x07,0x07,0x07,0x09,0x05,0x06, 0x06,0x0a,0x06,0x06,0x08,0x0a,0x07,0x06,0x0c,0x06,0x06,0x08,0x06,0x06,0x08,0x06,0x08,0x09,0x0a,0x06,0x09,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x08,0x06,0x07,0x07,0x06,0x06,0x07,0x0b,0x06,0x06,0x06,0x06,0x05,0x04,0x06,0x06,0x06,0x06,0x06,0x0a,0x06,0x0a,0x05,0x06,0x0a,0x07,0x06,0x0a,0x08,0x08,0x0a,0x06,0x06,0x0a,0x0a, 0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x06,0x06,0x06,0x0a,0x07,0x06,0x06,0x06,0x0a,0x09,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x09,0x08,0x07,0x06,0x09,0x07,0x08,0x06,0x07,0x08,0x08,0x08,0x06,0x08,0x07,0x08,0x07,0x09,0x08,0x08,0x08,0x08,0x07,0x08,0x07,0x08,0x09,0x07,0x08,0x08,0x01,0x01,0x02,0x02,0x02,0x03,0x04,0x09,0x06, 0x07,0x07,0x06,0x07,0x06,0x06,0x07,0x07,0x06,0x03,0x09,0x06,0x06,0x07,0x06,0x07,0x06,0x06,0x03,0x06,0x06,0x07,0x05,0x09,0x06,0x06,0x07,0x07,0x09,0x06,0x06,0x04,0x09,0x06,0x07,0x08,0x07,0x03,0x03,0x0c,0x0c,0x0c,0x0c,0x10,0x06,0x06,0x03,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06,0x04,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x05,0x06,0x06,0x05,0x05,0x06,0x07,0x03,0x03,0x05,0x05,0x08,0x07,0x07,0x05,0x07,0x05,0x05,0x05,0x07,0x06,0x09,0x06,0x05,0x05,0x08,0x09,0x05,0x07,0x05, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x06,0x03,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x08,0x07,0x06,0x05,0x04,0x06,0x05,0x05,0x07,0x07,0x03,0x05,0x06,0x08,0x07,0x05,0x07,0x07,0x05,0x05,0x05,0x05,0x07,0x06,0x07,0x07,0x06,0x05,0x07,0x03,0x07,0x05,0x07,0x03,0x05, 0x05,0x06,0x04,0x06,0x05,0x03,0x03,0x03,0x09,0x09,0x07,0x05,0x05,0x07,0x06,0x05,0x05,0x04,0x06,0x05,0x08,0x05,0x07,0x07,0x05,0x06,0x08,0x07,0x07,0x07,0x05,0x06,0x05,0x05,0x07,0x06,0x07,0x06,0x09,0x09,0x06,0x08,0x05,0x06,0x09,0x05,0x04,0x06,0x06,0x07,0x0a,0x0a,0x07,0x06,0x06,0x05,0x06,0x06,0x06,0x08,0x06,0x06,0x08,0x06, 0x06,0x04,0x07,0x07,0x06,0x06,0x05,0x0a,0x08,0x05,0x06,0x07,0x07,0x07,0x07,0x08,0x08,0x04,0x0b,0x06,0x05,0x06,0x07,0x07,0x06,0x06,0x03,0x09,0x08,0x08,0x05,0x08,0x03,0x03,0x05,0x05,0x03,0x03,0x07,0x04,0x03,0x09,0x08,0x03,0x02,0x02,0x05,0x04,0x04,0x03,0x03,0x03,0x04,0x07,0x05,0x03,0x07,0x08,0x07,0x06,0x06,0x08,0x07,0x07, 0x04,0x05,0x06,0x05,0x02,0x03,0x04,0x06,0x04,0x07,0x07,0x07,0x0a,0x08,0x0a,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x08,0x09,0x04,0x04,0x06,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x06,0x06,0x06,0x06,0x06,0x0d,0x09,0x0d,0x09,0x0f,0x0b,0x0f,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x06,0x06,0x0a,0x0a,0x06,0x06,0x08,0x09,0x04, 0x04,0x08,0x09,0x04,0x04,0x08,0x09,0x04,0x04,0x0b,0x08,0x09,0x06,0x06,0x06,0x07,0x04,0x07,0x08,0x06,0x06,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x04,0x08,0x06,0x06,0x03,0x06,0x06,0x06,0x06,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x06,0x06, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0d,0x09,0x0d,0x09,0x0d,0x09,0x0f,0x0b,0x0f,0x0b,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x06,0x06,0x08,0x06,0x06,0x0a,0x06,0x0c,0x0b,0x0a,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x07, 0x07,0x07,0x07,0x07,0x04,0x07,0x07,0x04,0x04,0x07,0x04,0x07,0x04,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x06,0x04,0x04,0x04,0x04,0x00,0x0d,0x09,0x0f,0x0b,0x0a,0x06,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x0a,0x04,0x06,0x06,0x06,0x06,0x05,0x0d,0x09,0x0b,0x0b,0x0a,0x0a,0x0a, 0x06,0x06,0x06,0x06,0x07,0x04,0x07,0x04,0x07,0x04,0x0d,0x09,0x06,0x07,0x06,0x06,0x06,0x07,0x06,0x06,0x0d,0x0d,0x09,0x09,0x05,0x05,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x08,0x09,0x04,0x04,0x08,0x09,0x04,0x04,0x08,0x09,0x04,0x04,0x06,0x06,0x06,0x06,0x0a,0x04,0x0a,0x04,0x06,0x07,0x06,0x06,0x0d,0x0d,0x09,0x09,0x0d,0x0d, 0x09,0x09,0x09,0x09,0x06,0x06,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x03,0x00,0x00,0x00,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x07,0x07,0x07,0x03,0x03,0x06,0x05,0x06,0x07,0x06,0x06,0x06,0x07, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x06,0x06,0x07,0x06,0x07,0x08,0x07,0x08,0x09,0x07,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x07,0x07,0x07,0x06,0x07,0x06,0x07,0x07,0x06,0x06,0x08,0x07,0x08,0x07,0x07,0x07,0x06,0x06,0x08, 0x08,0x08,0x08,0x0a,0x0a,0x08,0x0a,0x0a,0x08,0x0a,0x09,0x06,0x08,0x09,0x08,0x07,0x09,0x08,0x08,0x08,0x07,0x07,0x08,0x09,0x08,0x07,0x08,0x06,0x06,0x0a,0x0a,0x0a,0x09,0x0a,0x0a,0x08,0x0a,0x0a,0x08,0x08,0x09,0x08,0x08,0x08,0x07,0x0a,0x08,0x09,0x08,0x08,0x06,0x08,0x08,0x08,0x09,0x08,0x08,0x0a,0x06,0x06,0x06,0x06,0x07,0x07, 0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x05,0x06,0x06,0x06,0x07,0x08,0x09,0x07,0x07,0x07,0x08,0x07,0x08,0x06,0x05,0x06,0x06,0x05,0x05,0x06,0x06,0x05,0x05,0x07,0x05,0x06,0x05,0x06,0x09,0x06,0x09,0x06,0x06,0x06,0x08,0x03,0x09,0x08,0x08,0x07,0x06,0x08,0x07, 0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x0a,0x0a,0x0a,0x0a,0x05,0x08,0x08,0x05,0x04,0x05,0x06,0x06,0x05,0x09,0x09,0x09,0x05, 0x0b,0x05,0x09,0x09,0x09,0x09,0x06,0x05,0x05,0x09,0x06,0x09,0x07,0x06,0x05,0x04,0x0b,0x05,0x06,0x05,0x05,0x05,0x05,0x05,0x0f,0x09,0x09,0x05,0x03,0x05,0x03,0x05,0x03,0x03,0x03,0x05,0x06,0x06,0x06,0x04,0x04,0x03,0x03,0x03,0x04,0x03,0x05,0x09,0x03,0x0a,0x0a,0x0a,0x06,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x0d,0x0d,0x07,0x0d,0x0d,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x05,0x06,0x05,0x06,0x05,0x04,0x04,0x08,0x06,0x08,0x05,0x0c,0x0a,0x07,0x06,0x0a,0x09,0x09,0x08,0x0b,0x09,0x0a,0x09,0x07,0x05, 0x08,0x06,0x0a,0x08,0x08,0x07,0x08,0x07,0x0a,0x07,0x0a,0x07,0x0c,0x09,0x08,0x06,0x08,0x06,0x0d,0x0a,0x09,0x00,0x0b,0x0b,0x0b,0x05,0x00,0x00,0x06,0x06,0x08,0x06,0x06,0x05,0x0c,0x0a,0x0a,0x09,0x08,0x06,0x08,0x06,0x06,0x05,0x08,0x07,0x06,0x05,0x09,0x07,0x07,0x06,0x0b,0x09,0x06,0x06,0x08,0x08,0x09,0x05,0x02,0x05,0x08,0x05, 0x0b,0x0b,0x03,0x00,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x04,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,0x07,0x08,0x03,0x02,0x03,0x02,0x08,0x06,0x08,0x07,0x06,0x05,0x06,0x05,0x07,0x06,0x05,0x05,0x0c,0x09,0x0d,0x0a,0x0b,0x09,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x07,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x03,0x05, 0x03,0x08,0x06,0x09,0x07,0x0f,0x0b,0x06,0x06,0x08,0x08,0x09,0x09,0x08,0x06,0x0b,0x09,0x06,0x04,0x06,0x05,0x07,0x05,0x0a,0x08,0x07,0x06,0x06,0x06,0x06,0x06,0x05,0x04,0x05,0x04,0x05,0x04,0x06,0x06,0x03,0x07,0x04,0x0b,0x07,0x04,0x06,0x07,0x05,0x08,0x06,0x04,0x04,0x06,0x06,0x06,0x05,0x03,0x08,0x07,0x04,0x04,0x07,0x05,0x08, 0x04,0x09,0x07,0x07,0x05,0x08,0x06,0x06,0x05,0x08,0x06,0x07,0x04,0x06,0x05,0x08,0x05,0x06,0x09,0x05,0x06,0x0a,0x03,0x0d,0x0a,0x0a,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x05,0x07,0x08,0x0a,0x08,0x0a,0x03,0x05,0x07,0x09,0x0b,0x08,0x0b,0x07,0x07,0x09,0x08,0x0d,0x0a,0x06,0x0a,0x04,0x0a,0x04,0x06,0x06,0x06,0x06,0x09,0x09, 0x09,0x09,0x0b,0x06,0x06,0x0b,0x08,0x06,0x06,0x08,0x07,0x04,0x04,0x07,0x06,0x06,0x06,0x06,0x08,0x04,0x04,0x09,0x08,0x04,0x04,0x09,0x05,0x05,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x06,0x04,0x06,0x06, 0x08,0x07,0x06,0x0a,0x07,0x08,0x08,0x09,0x09,0x06,0x05,0x0b,0x09,0x0b,0x09,0x08,0x06,0x03,0x03,0x06,0x07,0x04,0x07,0x06,0x06,0x05,0x08,0x09,0x04,0x06,0x05,0x02,0x04,0x06,0x06,0x02,0x02,0x02,0x02,0x04,0x04,0x04,0x05,0x10,0x16,0x04,0x05,0x01,0x03,0x04,0x05,0x03,0x05,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, 0x05,0x05,0x05,0x05,0x05,0x0f,0x06,0x08,0x0a,0x0a,0x07,0x05,0x07,0x08,0x08,0x05,0x03,0x07,0x06,0x07,0x06,0x07,0x06,0x06,0x08,0x07,0x06,0x06,0x08,0x07,0x09,0x05,0x06,0x07,0x04,0x06,0x04,0x04,0x03,0x0a,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0a,0x0b,0x0b,0x06,0x06,0x03,0x06,0x05,0x07,0x05,0x07,0x03,0x06,0x07,0x09,0x09,0x07, 0x06,0x06,0x06,0x06,0x05,0x06,0x05,0x05,0x03,0x04,0x03,0x02,0x04,0x06,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x03,0x03,0x03,0x03,0x03,0x13,0x0b,0x0a,0x0c,0x03,0x03,0x04,0x04,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x0a,0x04,0x04,0x0a,0x03,0x06, 0x06,0x0f,0x0b,0x0b,0x0f,0x0a,0x06,0x06,0x0a,0x06,0x06,0x05,0x05,0x00,0x00,0x04,0x08,0x07,0x08,0x06,0x0e,0x0b,0x08,0x06,0x08,0x06,0x0f,0x0b,0x08,0x06,0x04,0x03,0x07,0x00,0x08,0x06,0x04,0x03,0x02,0x05,0x04,0x04,0x03,0x02,0x05,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x06,0x05,0x06,0x06,0x06,0x0b,0x09,0x09,0x09,0x09, 0x0a,0x07,0x08,0x07,0x04,0x0a,0x0c,0x05,0x0d,0x06,0x09,0x0a,0x0a,0x0a,0x05,0x08,0x0b,0x08,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x06,0x06,0x09,0x06,0x06,0x0a,0x04,0x04,0x0a,0x04,0x04,0x0a,0x05,0x05,0x00,0x05,0x09,0x04,0x04,0x0b,0x06,0x06,0x08,0x06,0x06,0x07,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x11,0x11,0x0a,0x00,0x00,0x0a,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x0a,0x07,0x07,0x09,0x0b,0x07,0x07,0x0c,0x07,0x07,0x0a,0x07,0x07,0x09,0x07,0x08,0x09,0x0a,0x07,0x08,0x07,0x08,0x07,0x08, 0x07,0x07,0x08,0x07,0x09,0x07,0x07,0x09,0x07,0x07,0x06,0x09,0x07,0x07,0x07,0x08,0x05,0x06,0x07,0x09,0x09,0x06,0x00,0x00,0x0c,0x18,0x08,0x00,0x01,0x03,0x03,0x05,0x07,0x06,0x0a,0x0a,0x03,0x04,0x04,0x05,0x08,0x03,0x05,0x03,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x08,0x08,0x08,0x05,0x0b,0x08,0x07, 0x08,0x08,0x06,0x06,0x08,0x09,0x03,0x04,0x07,0x06,0x0b,0x09,0x09,0x07,0x09,0x07,0x06,0x06,0x08,0x07,0x0b,0x07,0x07,0x07,0x04,0x05,0x04,0x08,0x05,0x03,0x06,0x07,0x06,0x07,0x06,0x04,0x07,0x07,0x03,0x03,0x06,0x03,0x0b,0x07,0x07,0x07,0x07,0x04,0x05,0x04,0x07,0x06,0x09,0x06,0x06,0x05,0x04,0x03,0x04,0x08,0x08,0x08,0x08,0x06, 0x09,0x09,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x05,0x06,0x06,0x05,0x05,0x06,0x07,0x05,0x0b,0x0b,0x09,0x03,0x05,0x08,0x0a,0x09,0x0a,0x08,0x08,0x08,0x06,0x07,0x06,0x07,0x09,0x06,0x05,0x05,0x09,0x0a,0x07,0x05,0x03,0x03,0x08, 0x08,0x06,0x08,0x08,0x06,0x06,0x09,0x08,0x08,0x09,0x0b,0x0b,0x06,0x0c,0x05,0x05,0x03,0x03,0x08,0x07,0x06,0x07,0x02,0x06,0x04,0x04,0x07,0x07,0x05,0x03,0x03,0x05,0x0f,0x08,0x06,0x08,0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x09,0x09,0x08,0x08,0x08,0x03,0x04,0x04,0x04,0x04,0x02,0x03,0x02,0x04,0x02,0x04,0x06,0x03,0x06,0x05,0x07, 0x05,0x03,0x08,0x07,0x07,0x06,0x07,0x07,0x08,0x08,0x04,0x04,0x04,0x0b,0x0b,0x0b,0x06,0x08,0x07,0x03,0x06,0x05,0x08,0x06,0x08,0x06,0x07,0x05,0x03,0x08,0x06,0x08,0x06,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x03,0x06,0x04,0x06,0x04,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x04,0x07,0x04,0x06,0x05,0x06,0x04,0x06,0x05,0x08,0x07, 0x08,0x07,0x07,0x05,0x07,0x05,0x06,0x09,0x09,0x07,0x07,0x05,0x07,0x06,0x09,0x05,0x06,0x05,0x0d,0x07,0x06,0x07,0x03,0x05,0x0a,0x04,0x07,0x04,0x04,0x07,0x04,0x08,0x06,0x08,0x06,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x07,0x08,0x07,0x08,0x07,0x09,0x07,0x09,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x03,0x07, 0x06,0x06,0x06,0x03,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x04,0x06,0x05,0x06,0x04,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x0b,0x09,0x07,0x06,0x03,0x08,0x06,0x0a,0x0a,0x09,0x07,0x03,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x07,0x06,0x03,0x05,0x06,0x07,0x0b,0x0b,0x0b,0x0b,0x05,0x05,0x03,0x03,0x03,0x08,0x07,0x09,0x05,0x0a, 0x08,0x0a,0x03,0x08,0x07,0x06,0x07,0x09,0x03,0x07,0x08,0x0b,0x09,0x06,0x09,0x09,0x07,0x06,0x06,0x07,0x07,0x09,0x09,0x03,0x07,0x07,0x05,0x07,0x03,0x07,0x07,0x06,0x05,0x07,0x07,0x03,0x06,0x06,0x07,0x06,0x05,0x07,0x07,0x06,0x07,0x06,0x09,0x0b,0x03,0x07,0x07,0x07,0x0b,0x06,0x08,0x06,0x07,0x06,0x03,0x0c,0x0c,0x09,0x07,0x07, 0x09,0x08,0x07,0x07,0x06,0x08,0x06,0x0b,0x07,0x09,0x09,0x07,0x08,0x0b,0x09,0x09,0x09,0x07,0x08,0x06,0x07,0x09,0x07,0x09,0x08,0x0b,0x0c,0x08,0x09,0x07,0x07,0x0c,0x07,0x06,0x07,0x06,0x05,0x06,0x06,0x09,0x05,0x07,0x07,0x06,0x07,0x09,0x07,0x07,0x07,0x07,0x06,0x05,0x06,0x09,0x06,0x07,0x07,0x0b,0x0b,0x07,0x09,0x06,0x06,0x0a, 0x06,0x06,0x07,0x05,0x06,0x05,0x03,0x09,0x0a,0x07,0x06,0x06,0x07,0x06,0x05,0x0c,0x0d,0x08,0x04,0x04,0x04,0x04,0x03,0x06,0x05,0x07,0x09,0x07,0x08,0x07,0x04,0x04,0x03,0x03,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x06,0x04,0x06,0x04,0x04,0x04,0x06,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08, 0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08, 0x07,0x08,0x07,0x07,0x06,0x07,0x06,0x07,0x06,0x06,0x04,0x06,0x06,0x09,0x07,0x03,0x04,0x03,0x03,0x06,0x05,0x0c,0x09,0x07,0x06,0x07,0x06,0x09,0x07,0x07,0x06,0x07,0x06,0x08,0x06,0x08,0x07,0x08,0x07,0x09,0x06,0x09,0x07,0x04,0x04,0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x03,0x03,0x04,0x04,0x04,0x04,0x06,0x06,0x08,0x06,0x07, 0x07,0x07,0x07,0x07,0x07,0x08,0x06,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x08,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x03,0x03,0x03,0x03,0x07,0x06,0x07,0x06,0x07,0x06,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x04,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x04,0x06,0x04,0x06,0x04,0x06,0x04,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x07,0x06,0x07,0x06,0x0b,0x09,0x0b, 0x09,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x05,0x07,0x05,0x07,0x05,0x07,0x04,0x09,0x06,0x06,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x05,0x05,0x07,0x07,0x03,0x03,0x07, 0x07,0x07,0x07,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08, 0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x09,0x07,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x08,0x09,0x07,0x07,0x07,0x06,0x07,0x06,0x08,0x07,0x0a,0x03,0x03,0x07,0x06,0x03,0x06,0x0b,0x09,0x07,0x09,0x0c,0x09,0x07,0x07,0x07,0x06,0x05,0x06,0x04,0x04,0x06,0x04,0x06,0x09,0x09,0x07,0x06,0x07,0x05,0x07,0x07,0x05,0x05,0x06, 0x06,0x05,0x05,0x07,0x03,0x05,0x05,0x03,0x0f,0x0e,0x0c,0x0a,0x09,0x06,0x0d,0x0c,0x0a,0x08,0x06,0x03,0x03,0x09,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x06,0x08,0x06,0x08,0x06,0x0a,0x0a,0x08,0x07,0x08,0x07,0x07,0x06,0x09,0x07,0x09,0x07,0x07,0x05,0x03,0x0f,0x0e,0x0c,0x08,0x07,0x0c,0x08,0x09,0x07,0x08,0x06, 0x08,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x09,0x07,0x09,0x07,0x07,0x04,0x07,0x04,0x08,0x07,0x08,0x07,0x06,0x05,0x09,0x07,0x09,0x07,0x07,0x07,0x05,0x08,0x06,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x06,0x07,0x06,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x06,0x06,0x07,0x07,0x06,0x07,0x05,0x05,0x06,0x07,0x03,0x07, 0x07,0x06,0x06,0x05,0x07,0x07,0x07,0x03,0x03,0x04,0x03,0x05,0x03,0x07,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x08,0x09,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x04,0x04,0x07,0x07,0x07,0x06,0x09,0x06,0x05,0x05,0x06,0x05,0x05,0x04,0x04,0x04,0x06,0x07,0x06,0x07,0x06,0x07,0x03,0x06,0x05,0x07, 0x04,0x04,0x0b,0x0b,0x0c,0x07,0x06,0x09,0x0a,0x07,0x07,0x06,0x06,0x07,0x07,0x07,0x08,0x07,0x08,0x0a,0x07,0x08,0x07,0x07,0x05,0x06,0x05,0x07,0x06,0x07,0x06,0x0b,0x0a,0x07,0x06,0x08,0x06,0x07,0x06,0x07,0x06,0x08,0x07,0x07,0x05,0x07,0x07,0x06,0x03,0x09,0x06,0x06,0x0a,0x08,0x08,0x07,0x0b,0x09,0x08,0x06,0x0a,0x08,0x09,0x07, 0x0b,0x09,0x06,0x05,0x09,0x09,0x09,0x07,0x09,0x07,0x09,0x07,0x10,0x0d,0x0a,0x08,0x0e,0x0b,0x0a,0x08,0x07,0x05,0x06,0x05,0x05,0x00,0x00,0x0c,0x0b,0x07,0x06,0x07,0x07,0x07,0x06,0x06,0x05,0x07,0x06,0x09,0x07,0x0a,0x08,0x0c,0x0a,0x09,0x07,0x07,0x06,0x06,0x05,0x0a,0x08,0x08,0x07,0x0a,0x08,0x0a,0x08,0x03,0x0b,0x09,0x07,0x06, 0x09,0x07,0x08,0x07,0x08,0x06,0x08,0x06,0x0a,0x0a,0x06,0x06,0x09,0x06,0x09,0x06,0x0b,0x09,0x07,0x05,0x06,0x05,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x08,0x07,0x09,0x09,0x07,0x07,0x0a,0x0a,0x0a,0x09,0x07,0x06,0x0b,0x0a,0x0c,0x0a,0x09,0x06,0x08,0x07,0x07,0x07,0x07,0x06,0x07,0x04, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x07,0x04,0x04,0x02,0x03,0x03,0x03,0x03,0x05,0x03,0x03,0x05,0x03,0x03,0x03,0x04,0x04,0x03,0x03,0x07,0x07,0x07,0x07,0x04,0x03,0x03,0x04,0x04,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x02,0x03,0x03,0x03,0x05,0x05,0x05,0x05, 0x05,0x04,0x04,0x04,0x05,0x04,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05, 0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07, 0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x08,0x04,0x07,0x07,0x04,0x04,0x04,0x04,0x04,0x03,0x04,0x04,0x04,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x06,0x08,0x0a,0x06, 0x06,0x07,0x07,0x05,0x05,0x03,0x04,0x06,0x05,0x09,0x07,0x07,0x06,0x07,0x07,0x07,0x0b,0x06,0x07,0x07,0x06,0x05,0x05,0x05,0x06,0x07,0x09,0x07,0x06,0x09,0x05,0x05,0x05,0x06,0x05,0x06,0x07,0x06,0x07,0x07,0x04,0x06,0x04,0x04,0x05,0x04,0x04,0x05,0x05,0x02,0x03,0x04,0x03,0x06,0x05,0x05,0x05,0x05,0x04,0x04,0x03,0x05,0x06,0x04, 0x04,0x04,0x06,0x04,0x04,0x04,0x04,0x03,0x03,0x04,0x02,0x04,0x06,0x04,0x04,0x03,0x04,0x04,0x04,0x02,0x04,0x04,0x06,0x03,0x04,0x04,0x04,0x04,0x05,0x04,0x02,0x03,0x04,0x03,0x04,0x04,0x04,0x05,0x04,0x07,0x02,0x04,0x07,0x0b,0x07,0x06,0x06,0x0a,0x08,0x0a,0x09,0x06,0x07,0x06,0x05,0x0e,0x05,0x07,0x0b,0x0b,0x0b,0x08,0x08,0x08, 0x06,0x06,0x06,0x05,0x05,0x06,0x02,0x00,0x00,0x00,0x00,0x07,0x07,0x08,0x07,0x06,0x05,0x07,0x07,0x04,0x0a,0x07,0x07,0x04,0x04,0x06,0x04,0x05,0x07,0x06,0x07,0x0b,0x08,0x04,0x03,0x07,0x06,0x07,0x07,0x07,0x04,0x07,0x06,0x03,0x0b,0x07,0x07,0x04,0x05,0x05,0x06,0x06,0x05,0x06,0x07,0x07,0x06,0x05,0x05,0x09,0x03,0x06,0x03,0x07, 0x05,0x04,0x03,0x03,0x04,0x03,0x02,0x02,0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x06,0x06,0x04,0x04,0x04,0x04,0x04,0x03,0x02,0x02,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x04,0x03,0x04,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x04,0x06,0x06,0x06,0x06,0x04,0x00,0x00,0x00,0x00,0x06,0x04,0x03,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x09,0x08,0x09,0x07,0x09,0x08,0x0b,0x09,0x06,0x05,0x06,0x08,0x06,0x0a,0x08,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0c,0x05,0x03,0x06,0x07,0x05,0x06,0x06,0x07,0x07,0x06,0x0c,0x07,0x07,0x07,0x07, 0x07,0x07,0x06,0x06,0x08,0x06,0x06,0x06,0x04,0x07,0x04,0x09,0x08,0x06,0x04,0x0a,0x06,0x0a,0x03,0x04,0x07,0x07,0x08,0x08,0x08,0x07,0x07,0x07,0x0a,0x03,0x07,0x03,0x06,0x05,0x03,0x03,0x06,0x03,0x09,0x03,0x0b,0x06,0x0b,0x0b,0x07,0x07,0x07,0x06,0x06,0x05,0x05,0x0e,0x0e,0x10,0x10,0x0a,0x0a,0x06,0x06,0x02,0x0c,0x09,0x0a,0x08, 0x07,0x08,0x06,0x06,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x03,0x08,0x00,0x08,0x08,0x08,0x04,0x06,0x06,0x0b,0x04,0x0b,0x04,0x07,0x08,0x07,0x05,0x0b,0x06,0x0b,0x06,0x09,0x0a,0x04,0x06,0x06,0x05,0x03,0x06,0x07,0x06,0x07,0x06,0x07,0x07,0x06,0x08,0x08,0x0b,0x04,0x06,0x05,0x08,0x06,0x04,0x06,0x06,0x06,0x0b, 0x04,0x0b,0x04,0x03,0x07,0x05,0x0c,0x06,0x06,0x08,0x08,0x0c,0x06,0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x09,0x08,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x06,0x06,0x09,0x0a,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x08,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x06,0x05,0x05,0x05,0x0e,0x0a,0x0e,0x0a,0x0e,0x0a,0x10,0x0c,0x10,0x0c,0x0a,0x06,0x07,0x07,0x07,0x0c,0x0c,0x06,0x06,0x0c,0x06,0x06,0x0c,0x06,0x06,0x0c,0x06,0x06,0x09,0x09,0x0d,0x0c,0x0b,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0b,0x06,0x0b,0x06,0x0b, 0x06,0x0b,0x06,0x0b,0x06,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x08,0x04,0x08,0x04,0x07,0x08,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0b,0x09,0x0a,0x04,0x06,0x09,0x0a,0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x0d,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x05,0x00,0x00,0x07,0x00,0x00,0x00,0x0e,0x0a, 0x10,0x0c,0x06,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x0b,0x0b,0x04,0x07,0x07,0x07,0x0f,0x0a,0x06,0x12,0x0d,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x05,0x05,0x09,0x08,0x08,0x06,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x0f,0x12,0x00, 0x00,0x00,0x00,0x00,0x07,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x05,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x07,0x07,0x07,0x07,0x08,0x07,0x06,0x06,0x05,0x0e,0x0a,0x06,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x0c,0x06,0x06,0x0c,0x06,0x06,0x0b,0x06,0x06,0x0b,0x06,0x06,0x0b,0x06,0x06, 0x07,0x07,0x07,0x07,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x08,0x04,0x04,0x05,0x05,0x0e,0x0a,0x08,0x07,0x07,0x00,0x06,0x06,0x06,0x04,0x07,0x08,0x08,0x06,0x06,0x04,0x03,0x09,0x07,0x07,0x04,0x07,0x06,0x06,0x06,0x06,0x03,0x06,0x05,0x07,0x06,0x07,0x06,0x07,0x05,0x08,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x05, 0x06,0x06,0x03,0x06,0x07,0x07,0x06,0x04,0x09,0x07,0x08,0x06,0x07,0x06,0x07,0x06,0x05,0x08,0x04,0x05,0x05,0x06,0x07,0x07,0x06,0x0c,0x06,0x0c,0x04,0x03,0x02,0x06,0x03,0x02,0x00,0x02,0x03,0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x0b,0x05,0x09,0x07,0x0b,0x09,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06,0x0a,0x06,0x0a,0x08,0x08,0x08,0x08,0x09,0x0a,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x08,0x09,0x07,0x0d,0x0a,0x06,0x06,0x03,0x03,0x03,0x04,0x03,0x07,0x03,0x03,0x0a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x02,0x00,0x00,0x03, 0x00,0x00,0x08,0x07,0x05,0x06,0x08,0x03,0x04,0x08,0x08,0x03,0x07,0x07,0x07,0x08,0x08,0x03,0x05,0x08,0x07,0x07,0x08,0x07,0x07,0x08,0x07,0x09,0x09,0x06,0x06,0x06,0x03,0x05,0x07,0x07,0x07,0x07,0x06,0x07,0x08,0x06,0x08,0x07,0x07,0x08,0x07,0x09,0x07,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x07,0x05,0x06,0x08,0x04,0x04,0x08,0x04, 0x07,0x07,0x07,0x08,0x05,0x08,0x07,0x08,0x07,0x08,0x07,0x09,0x09,0x03,0x07,0x07,0x08,0x08,0x0e,0x00,0x08,0x07,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x03,0x00,0x09,0x08,0x08,0x08, 0x07,0x08,0x09,0x09,0x06,0x08,0x09,0x09,0x08,0x09,0x0a,0x09,0x08,0x07,0x07,0x09,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x07,0x08,0x08,0x08,0x09,0x08,0x07,0x08,0x08,0x0a,0x06,0x07,0x07,0x0b,0x06,0x06,0x09,0x0b,0x07,0x06,0x0d,0x07,0x07,0x09,0x06,0x06,0x09,0x07,0x09,0x0a,0x0b,0x06,0x09,0x06,0x08,0x07,0x07,0x07,0x08,0x06, 0x07,0x09,0x06,0x07,0x08,0x06,0x06,0x07,0x0b,0x06,0x06,0x07,0x07,0x05,0x04,0x07,0x07,0x07,0x06,0x07,0x0b,0x07,0x0b,0x06,0x07,0x0b,0x08,0x07,0x0b,0x09,0x09,0x0b,0x07,0x07,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x07,0x07,0x07,0x0b,0x07,0x07,0x07,0x07,0x0b,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x08,0x08, 0x07,0x09,0x08,0x08,0x07,0x08,0x08,0x09,0x09,0x07,0x08,0x08,0x09,0x08,0x09,0x08,0x09,0x09,0x08,0x08,0x08,0x08,0x09,0x0a,0x08,0x09,0x09,0x01,0x01,0x02,0x02,0x02,0x03,0x04,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x07,0x07,0x04,0x0a,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x03,0x07,0x06,0x07,0x05,0x0a,0x07,0x07,0x07,0x07, 0x0a,0x07,0x07,0x05,0x0a,0x07,0x07,0x08,0x08,0x03,0x03,0x0e,0x0d,0x0d,0x0e,0x11,0x06,0x06,0x03,0x06,0x05,0x06,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x06,0x07,0x05,0x05,0x07,0x07,0x03,0x04,0x06,0x05,0x09,0x08,0x07,0x06,0x07,0x06,0x05,0x05,0x07,0x06,0x0a,0x06,0x06,0x06,0x08,0x09,0x05,0x08,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x03,0x03,0x03,0x03,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06, 0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x06,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x07,0x04,0x06,0x05,0x05,0x05,0x05,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x06, 0x06,0x08,0x08,0x06,0x06,0x05,0x06,0x05,0x06,0x07,0x07,0x03,0x06,0x06,0x09,0x08,0x05,0x07,0x07,0x06,0x06,0x05,0x06,0x08,0x06,0x08,0x08,0x06,0x05,0x07,0x03,0x07,0x06,0x08,0x03,0x06,0x05,0x07,0x05,0x06,0x05,0x03,0x03,0x04,0x0a,0x0a,0x07,0x06,0x06,0x07,0x06,0x06,0x06,0x05,0x07,0x05,0x09,0x05,0x08,0x08,0x06,0x07,0x09,0x07, 0x07,0x07,0x06,0x06,0x05,0x06,0x08,0x06,0x08,0x07,0x0a,0x0a,0x07,0x08,0x06,0x06,0x0a,0x06,0x05,0x07,0x07,0x07,0x0b,0x0b,0x08,0x06,0x07,0x05,0x07,0x07,0x07,0x08,0x06,0x06,0x08,0x07,0x07,0x04,0x08,0x07,0x07,0x06,0x06,0x0b,0x09,0x06,0x06,0x07,0x07,0x07,0x07,0x09,0x08,0x04,0x0b,0x07,0x07,0x07,0x08,0x08,0x06,0x06,0x03,0x09, 0x08,0x08,0x06,0x08,0x03,0x03,0x05,0x05,0x03,0x03,0x07,0x05,0x03,0x09,0x08,0x03,0x03,0x03,0x05,0x05,0x05,0x03,0x03,0x03,0x05,0x08,0x06,0x04,0x07,0x08,0x07,0x07,0x06,0x09,0x07,0x07,0x04,0x05,0x06,0x05,0x03,0x03,0x05,0x06,0x04,0x08,0x08,0x08,0x0b,0x09,0x0b,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x09,0x0a,0x04,0x04,0x06,0x04, 0x0b,0x04,0x0b,0x04,0x0b,0x04,0x07,0x07,0x07,0x06,0x06,0x0e,0x0a,0x0e,0x0a,0x10,0x0c,0x10,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x06,0x06,0x0b,0x0b,0x06,0x06,0x09,0x0a,0x04,0x04,0x09,0x0a,0x04,0x04,0x09,0x0a,0x04,0x04,0x0c,0x09,0x0a,0x06,0x07,0x07,0x08,0x04,0x08,0x09,0x06,0x06,0x04,0x04,0x04,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0b,0x04,0x09,0x06,0x06,0x03,0x06,0x06,0x06,0x06,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0e,0x0a,0x0e,0x0a,0x0e,0x0a,0x10,0x0c,0x10,0x0c,0x0a,0x0a,0x0a,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x09,0x06,0x06,0x09,0x06,0x06,0x0b,0x06,0x0d,0x0c,0x0b,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x08,0x08,0x08,0x08,0x08,0x04,0x08,0x08,0x04,0x04,0x08,0x04,0x08,0x04,0x08,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04, 0x06,0x04,0x04,0x04,0x04,0x00,0x0e,0x0a,0x10,0x0c,0x0b,0x06,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x0b,0x04,0x07,0x07,0x06,0x06,0x05,0x0e,0x0a,0x0c,0x0c,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x07,0x08,0x04,0x08,0x04,0x08,0x04,0x0e,0x0a,0x07,0x08,0x07,0x07,0x07,0x08,0x07,0x07,0x0e,0x0e,0x0a,0x0a,0x05,0x05,0x07,0x07, 0x07,0x07,0x04,0x04,0x04,0x04,0x09,0x0a,0x04,0x04,0x09,0x0a,0x04,0x04,0x09,0x0a,0x04,0x04,0x07,0x07,0x07,0x07,0x0b,0x04,0x0b,0x04,0x07,0x08,0x07,0x07,0x0e,0x0e,0x0a,0x0a,0x0e,0x0e,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x03,0x00,0x00,0x00,0x0a,0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, 0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x0a,0x08,0x08,0x08,0x03,0x03,0x06,0x05,0x07,0x08,0x07,0x06,0x07,0x07,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x06,0x07,0x07,0x07,0x08,0x07,0x07,0x08,0x06,0x08,0x09,0x08,0x09, 0x0a,0x08,0x09,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x07,0x07,0x08,0x07,0x08,0x07,0x07,0x07,0x06,0x06,0x09,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x0b,0x0b,0x08,0x0b,0x0b,0x09,0x0a,0x0a,0x07,0x09,0x0a,0x09,0x07,0x0a,0x09,0x08,0x08,0x07,0x08,0x09,0x0a,0x08,0x07,0x08,0x07, 0x06,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x08,0x0b,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x0b,0x09,0x0a,0x09,0x09,0x07,0x09,0x08,0x08,0x0a,0x09,0x09,0x0b,0x07,0x06,0x07,0x06,0x07,0x08,0x08,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x07,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x07,0x09,0x0a, 0x08,0x08,0x08,0x09,0x08,0x08,0x06,0x06,0x07,0x07,0x06,0x06,0x07,0x07,0x06,0x06,0x08,0x05,0x07,0x06,0x07,0x09,0x07,0x0a,0x06,0x07,0x07,0x09,0x04,0x09,0x08,0x09,0x08,0x07,0x09,0x07,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x06,0x05,0x04,0x04,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x07,0x03,0x03,0x03,0x04,0x04,0x03,0x03,0x03,0x04,0x03,0x03,0x03,0x0b,0x0b,0x0b,0x0b,0x06,0x09,0x09,0x06,0x05,0x06,0x06,0x07,0x06,0x0a,0x0a,0x0a,0x05,0x0c,0x06,0x0a,0x0a,0x0a,0x0a,0x07,0x06,0x06,0x09,0x07,0x09,0x08,0x06,0x05,0x05,0x0c,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x10,0x0a,0x0a,0x05, 0x03,0x05,0x03,0x06,0x03,0x03,0x03,0x06,0x07,0x07,0x07,0x05,0x05,0x03,0x03,0x03,0x05,0x03,0x05,0x0a,0x03,0x0b,0x0b,0x0b,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x08,0x0e,0x0e,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x06,0x07,0x06,0x06,0x05,0x04,0x04,0x08,0x07,0x09,0x05,0x0e,0x0b,0x07,0x07,0x0b,0x0a,0x0a,0x09,0x0c,0x0a,0x0b,0x09,0x08,0x06,0x09,0x07,0x0b,0x09,0x09,0x07,0x09,0x07,0x0a,0x08,0x0b,0x08,0x0d,0x0a,0x09,0x07,0x09,0x07,0x0f,0x0b,0x0a,0x00,0x0c,0x0c,0x0c,0x06,0x00,0x00, 0x07,0x06,0x08,0x07,0x06,0x05,0x0d,0x0b,0x0b,0x0a,0x09,0x07,0x08,0x07,0x06,0x05,0x09,0x07,0x06,0x05,0x0a,0x08,0x08,0x07,0x0c,0x0a,0x06,0x07,0x09,0x09,0x0a,0x05,0x02,0x06,0x08,0x05,0x0c,0x0c,0x03,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x05,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x06,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x08,0x09,0x03,0x03,0x03, 0x03,0x09,0x07,0x09,0x08,0x07,0x06,0x06,0x06,0x07,0x07,0x05,0x05,0x0e,0x0a,0x0e,0x0b,0x0c,0x0a,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x04,0x06,0x03,0x09,0x07,0x0a,0x08,0x10,0x0c,0x07,0x07,0x08,0x08,0x0a,0x0a,0x09,0x07,0x0c,0x09,0x07,0x05,0x07,0x06,0x07,0x06,0x0b,0x09,0x07,0x06,0x07, 0x07,0x07,0x07,0x06,0x05,0x06,0x05,0x06,0x04,0x06,0x06,0x04,0x08,0x04,0x0b,0x08,0x04,0x07,0x07,0x06,0x09,0x07,0x05,0x04,0x07,0x07,0x07,0x06,0x03,0x09,0x07,0x04,0x04,0x07,0x06,0x09,0x05,0x09,0x07,0x07,0x06,0x08,0x07,0x07,0x06,0x09,0x07,0x07,0x04,0x06,0x05,0x09,0x05,0x06,0x0a,0x06,0x07,0x0b,0x03,0x0e,0x0b,0x0b,0x0e,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x06,0x06,0x08,0x08,0x0b,0x08,0x0b,0x03,0x06,0x07,0x0b,0x0c,0x08,0x0c,0x07,0x07,0x0a,0x08,0x0e,0x0b,0x06,0x0b,0x04,0x0b,0x04,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0c,0x06,0x06,0x0c,0x09,0x06,0x06,0x09,0x08,0x04,0x04,0x08,0x07,0x07,0x07,0x07,0x09,0x04,0x04,0x0a,0x09,0x04,0x04,0x0a,0x05,0x05, 0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x06,0x05,0x07,0x06,0x09,0x07,0x07,0x0b,0x08,0x09,0x09,0x0a,0x0a,0x07,0x06,0x0c,0x0a,0x0d,0x0a,0x08,0x07,0x04,0x04,0x07,0x08,0x05,0x07,0x06,0x07,0x06,0x09,0x0a, 0x05,0x07,0x05,0x03,0x04,0x06,0x07,0x03,0x03,0x02,0x03,0x05,0x05,0x05,0x05,0x12,0x18,0x04,0x05,0x02,0x03,0x05,0x05,0x04,0x06,0x06,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x10,0x06,0x09,0x0b,0x0b,0x08,0x06,0x07,0x09,0x09,0x06,0x04,0x08,0x06,0x08,0x07,0x08,0x06,0x07,0x09,0x07,0x07,0x06, 0x09,0x07,0x0a,0x05,0x06,0x08,0x04,0x07,0x04,0x04,0x03,0x0b,0x07,0x07,0x06,0x06,0x07,0x0b,0x0b,0x0b,0x0c,0x0c,0x07,0x06,0x03,0x06,0x06,0x07,0x05,0x08,0x03,0x07,0x07,0x0a,0x0a,0x07,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x03,0x03,0x04,0x07,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x00,0x03,0x03,0x03,0x03,0x03,0x14,0x0c,0x0a,0x0d,0x03,0x03,0x04,0x05,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x0b,0x04,0x04,0x0b,0x03,0x06,0x06,0x10,0x0c,0x0c,0x10,0x0b,0x06,0x06,0x0b,0x06,0x06,0x05,0x05,0x00,0x00,0x04,0x09,0x07,0x09,0x07,0x0f,0x0c,0x08,0x07,0x08,0x07,0x10,0x0c, 0x09,0x07,0x05,0x04,0x07,0x00,0x08,0x06,0x04,0x04,0x02,0x06,0x04,0x04,0x03,0x02,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x06,0x05,0x07,0x07,0x07,0x0c,0x0b,0x0a,0x09,0x0a,0x0b,0x08,0x08,0x07,0x05,0x0b,0x0e,0x05,0x0e,0x06,0x0a,0x0b,0x0b,0x0b,0x05,0x09,0x0c,0x09,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x07,0x07,0x0a,0x06,0x06,0x0b,0x04,0x04,0x0b,0x04,0x04,0x0b,0x06,0x06,0x00,0x05,0x0a,0x04,0x04,0x0c,0x06,0x06,0x09,0x06,0x06,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x12,0x12,0x0b,0x00,0x00,0x0b,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x08,0x07,0x08,0x08,0x0b,0x08,0x08,0x0a,0x0c,0x08,0x08,0x0d,0x08,0x08,0x0b,0x08,0x08,0x09,0x08,0x09,0x0a,0x0b,0x08,0x09,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x07,0x08,0x09,0x07,0x08,0x07,0x09,0x08,0x08,0x08,0x08,0x05,0x06,0x08,0x09,0x09,0x07,0x00,0x00,0x0d,0x1a,0x08,0x00, 0x01,0x04,0x04,0x05,0x08,0x07,0x0b,0x0a,0x03,0x04,0x04,0x05,0x09,0x03,0x05,0x03,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x09,0x09,0x09,0x06,0x0c,0x08,0x07,0x08,0x09,0x07,0x06,0x09,0x09,0x03,0x05,0x08,0x06,0x0c,0x0a,0x0a,0x07,0x0a,0x08,0x07,0x07,0x09,0x08,0x0c,0x08,0x07,0x07,0x04,0x05,0x04,0x09, 0x05,0x03,0x07,0x08,0x06,0x08,0x07,0x04,0x08,0x07,0x03,0x03,0x06,0x03,0x0b,0x07,0x08,0x08,0x08,0x05,0x06,0x04,0x07,0x06,0x09,0x06,0x06,0x06,0x04,0x03,0x04,0x09,0x08,0x08,0x08,0x07,0x0a,0x0a,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x07,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07, 0x05,0x05,0x07,0x07,0x06,0x05,0x06,0x07,0x05,0x0c,0x0c,0x0a,0x04,0x05,0x09,0x0b,0x0a,0x0b,0x09,0x09,0x09,0x07,0x08,0x07,0x08,0x0a,0x07,0x05,0x06,0x0a,0x0b,0x08,0x06,0x04,0x04,0x09,0x08,0x07,0x09,0x08,0x07,0x07,0x09,0x08,0x08,0x0a,0x0c,0x0c,0x07,0x0d,0x05,0x05,0x03,0x03,0x09,0x08,0x06,0x07,0x02,0x07,0x04,0x04,0x07,0x07, 0x05,0x03,0x03,0x05,0x10,0x08,0x07,0x08,0x07,0x07,0x03,0x03,0x03,0x03,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x03,0x05,0x04,0x04,0x04,0x03,0x04,0x03,0x04,0x02,0x05,0x06,0x03,0x07,0x06,0x07,0x06,0x03,0x09,0x07,0x07,0x06,0x07,0x08,0x09,0x09,0x05,0x05,0x05,0x0c,0x0c,0x0c,0x06,0x09,0x08,0x03,0x07,0x06,0x08,0x06,0x08,0x06,0x08,0x05, 0x03,0x08,0x07,0x08,0x07,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x06,0x03,0x06,0x04,0x06,0x04,0x0a,0x07,0x0a,0x07,0x0a,0x08,0x08,0x05,0x08,0x05,0x07,0x06,0x07,0x04,0x07,0x06,0x09,0x07,0x09,0x07,0x07,0x06,0x07,0x06,0x06,0x0a,0x09,0x08,0x08,0x06,0x07,0x06,0x09,0x05,0x06,0x05,0x0e,0x08,0x06,0x08,0x03,0x05,0x0a,0x04,0x08,0x05, 0x05,0x08,0x05,0x08,0x07,0x08,0x06,0x08,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x07,0x09,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x03,0x08,0x06,0x06,0x06,0x03,0x0a,0x07,0x0a,0x07,0x0a,0x08,0x0a,0x08,0x08,0x05,0x07,0x06,0x07,0x04,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x0c,0x09, 0x07,0x06,0x03,0x08,0x07,0x0b,0x0b,0x0a,0x08,0x03,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x07,0x06,0x03,0x05,0x07,0x08,0x0c,0x0c,0x0c,0x0c,0x05,0x05,0x03,0x04,0x04,0x08,0x07,0x0a,0x05,0x0a,0x09,0x0b,0x03,0x08,0x07,0x07,0x07,0x09,0x03,0x08,0x08,0x0c,0x0a,0x07,0x0a,0x09,0x07,0x07,0x07,0x07,0x08,0x0b,0x0a,0x03,0x07,0x08,0x06,0x07, 0x03,0x07,0x07,0x07,0x06,0x07,0x08,0x03,0x07,0x06,0x07,0x07,0x06,0x08,0x08,0x06,0x07,0x07,0x09,0x0b,0x03,0x07,0x08,0x07,0x0b,0x07,0x09,0x06,0x08,0x07,0x03,0x0d,0x0d,0x09,0x08,0x07,0x09,0x08,0x07,0x07,0x06,0x09,0x07,0x0b,0x07,0x0a,0x0a,0x08,0x09,0x0c,0x09,0x0a,0x09,0x07,0x08,0x07,0x07,0x09,0x08,0x0a,0x09,0x0d,0x0e,0x09, 0x0a,0x07,0x08,0x0d,0x08,0x07,0x08,0x07,0x05,0x07,0x07,0x09,0x06,0x07,0x07,0x06,0x07,0x09,0x07,0x08,0x07,0x08,0x06,0x05,0x06,0x09,0x06,0x07,0x07,0x0b,0x0b,0x08,0x09,0x07,0x06,0x0b,0x07,0x07,0x07,0x05,0x06,0x06,0x03,0x0b,0x0b,0x07,0x06,0x06,0x07,0x06,0x05,0x0d,0x0f,0x08,0x05,0x05,0x05,0x05,0x03,0x07,0x06,0x07,0x0a,0x08, 0x09,0x08,0x04,0x04,0x03,0x03,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x06,0x04,0x06,0x04,0x04,0x04,0x06,0x06,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03, 0x03,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x09,0x07,0x09,0x07,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x04,0x07,0x07,0x0a,0x07,0x03,0x05,0x03,0x03,0x07,0x05,0x0c,0x0a,0x08,0x07,0x08,0x06,0x0a, 0x07,0x07,0x07,0x07,0x07,0x08,0x06,0x09,0x07,0x09,0x07,0x09,0x07,0x0a,0x08,0x04,0x04,0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x03,0x03,0x04,0x04,0x04,0x04,0x07,0x07,0x08,0x07,0x07,0x08,0x07,0x08,0x07,0x08,0x08,0x06,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06, 0x04,0x09,0x08,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x03,0x03,0x03,0x03,0x08,0x06,0x08,0x06,0x08,0x06,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x0c,0x0b,0x0c,0x0b,0x0c,0x0b,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x0a,0x07,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x07,0x08,0x07,0x08,0x08,0x05,0x08,0x05,0x08,0x05,0x08, 0x05,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x04,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x06,0x08,0x06,0x0c,0x09,0x0c,0x09,0x08,0x06,0x08,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x07,0x04,0x09,0x06,0x07,0x03,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x08,0x08,0x06,0x06,0x07,0x07,0x03,0x03,0x08,0x08,0x07,0x07,0x0b,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x09,0x08,0x08,0x08,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05, 0x05,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x08,0x08,0x07,0x07,0x07,0x07,0x09,0x09,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x06,0x09,0x0a,0x07,0x08,0x08,0x07,0x07,0x06,0x09, 0x08,0x0b,0x04,0x04,0x08,0x06,0x03,0x06,0x0c,0x0a,0x07,0x0a,0x0d,0x0a,0x08,0x08,0x07,0x07,0x06,0x07,0x04,0x04,0x07,0x04,0x07,0x0a,0x09,0x07,0x07,0x07,0x06,0x08,0x08,0x06,0x05,0x07,0x07,0x05,0x05,0x07,0x03,0x05,0x06,0x04,0x10,0x0f,0x0d,0x0b,0x09,0x07,0x0e,0x0d,0x0b,0x08,0x07,0x03,0x03,0x0a,0x08,0x09,0x07,0x09,0x07,0x09, 0x07,0x09,0x07,0x09,0x07,0x07,0x08,0x07,0x08,0x07,0x0b,0x0b,0x09,0x08,0x09,0x08,0x08,0x06,0x0a,0x08,0x0a,0x08,0x08,0x06,0x03,0x10,0x0f,0x0d,0x09,0x08,0x0d,0x09,0x0a,0x07,0x08,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x0a,0x08,0x0a,0x08,0x07,0x05,0x08,0x05,0x09,0x07,0x09,0x07,0x07,0x06,0x09,0x07,0x0a,0x08, 0x07,0x07,0x06,0x08,0x07,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x07,0x06,0x08,0x07,0x07,0x07,0x08,0x07,0x08,0x08,0x08,0x06,0x06,0x08,0x08,0x07,0x08,0x05,0x05,0x07,0x07,0x04,0x08,0x08,0x07,0x06,0x06,0x07,0x07,0x07,0x03,0x04,0x04,0x04,0x05,0x03,0x08,0x0b,0x0b,0x0b,0x07,0x07,0x08,0x08,0x09,0x09,0x08,0x05,0x05,0x05,0x05, 0x05,0x04,0x04,0x06,0x06,0x05,0x03,0x03,0x04,0x04,0x04,0x04,0x08,0x08,0x07,0x06,0x09,0x06,0x05,0x06,0x07,0x06,0x06,0x05,0x05,0x05,0x06,0x08,0x06,0x07,0x07,0x07,0x03,0x06,0x05,0x08,0x05,0x05,0x0c,0x0c,0x0d,0x08,0x06,0x09,0x0a,0x08,0x07,0x06,0x06,0x07,0x08,0x07,0x09,0x07,0x08,0x0a,0x07,0x09,0x08,0x08,0x06,0x06,0x06,0x08, 0x07,0x08,0x06,0x0c,0x0b,0x08,0x07,0x08,0x07,0x08,0x06,0x08,0x06,0x09,0x08,0x07,0x05,0x07,0x08,0x06,0x03,0x0a,0x06,0x06,0x0b,0x09,0x08,0x08,0x0c,0x09,0x09,0x06,0x0b,0x09,0x09,0x07,0x0c,0x0a,0x07,0x06,0x0a,0x0a,0x0a,0x08,0x09,0x08,0x09,0x08,0x11,0x0f,0x0b,0x08,0x0f,0x0c,0x0b,0x09,0x08,0x06,0x07,0x05,0x05,0x00,0x00,0x0d, 0x0c,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x06,0x08,0x06,0x09,0x08,0x0b,0x09,0x0d,0x0b,0x09,0x07,0x08,0x06,0x07,0x05,0x0b,0x09,0x09,0x08,0x0b,0x08,0x0b,0x08,0x03,0x0b,0x09,0x08,0x07,0x09,0x08,0x09,0x07,0x08,0x07,0x08,0x07,0x0b,0x0b,0x07,0x07,0x09,0x07,0x09,0x07,0x0b,0x09,0x07,0x06,0x07,0x06,0x0a,0x07,0x0a,0x07,0x0a,0x08, 0x0a,0x08,0x08,0x06,0x07,0x06,0x07,0x06,0x07,0x06,0x09,0x07,0x0a,0x09,0x07,0x08,0x0b,0x0b,0x0a,0x09,0x07,0x06,0x0c,0x0a,0x0d,0x0b,0x09,0x07,0x09,0x08,0x08,0x07,0x07,0x07,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x08,0x04,0x04,0x02,0x03,0x03,0x03,0x04,0x05,0x04,0x03,0x05,0x03, 0x03,0x03,0x04,0x04,0x03,0x03,0x08,0x08,0x08,0x08,0x04,0x04,0x03,0x04,0x04,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x02,0x03,0x04,0x03,0x05,0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x05,0x04,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07, 0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07, 0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x08,0x04, 0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x06,0x09,0x0b,0x06,0x06,0x07,0x07,0x05,0x05,0x03,0x04,0x06,0x05,0x09,0x07,0x08,0x06,0x08,0x08,0x08,0x0c,0x07,0x08,0x08,0x06,0x06,0x06,0x05,0x07,0x07,0x09,0x07, 0x06,0x09,0x06,0x05,0x05,0x07,0x05,0x06,0x07,0x06,0x08,0x07,0x05,0x06,0x05,0x05,0x05,0x04,0x04,0x05,0x06,0x02,0x03,0x05,0x04,0x07,0x06,0x06,0x06,0x05,0x04,0x04,0x04,0x05,0x07,0x04,0x04,0x05,0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x05,0x02,0x04,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x03,0x04,0x04,0x06,0x04,0x04,0x04,0x04,0x04, 0x05,0x04,0x02,0x03,0x04,0x04,0x04,0x04,0x05,0x05,0x04,0x08,0x02,0x05,0x07,0x0b,0x08,0x07,0x07,0x0b,0x08,0x0b,0x0a,0x07,0x08,0x07,0x06,0x0f,0x06,0x08,0x0c,0x0c,0x0c,0x08,0x08,0x08,0x06,0x06,0x07,0x06,0x06,0x07,0x03,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x06,0x05,0x08,0x08,0x04,0x0b,0x07,0x08,0x05,0x04,0x06,0x04,0x06, 0x08,0x06,0x08,0x0c,0x08,0x04,0x03,0x08,0x07,0x08,0x08,0x08,0x04,0x08,0x06,0x03,0x0b,0x07,0x08,0x05,0x06,0x06,0x06,0x06,0x06,0x07,0x08,0x08,0x07,0x06,0x06,0x0a,0x03,0x06,0x03,0x07,0x06,0x05,0x03,0x03,0x04,0x03,0x02,0x02,0x05,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x06,0x06,0x04,0x04,0x05,0x04,0x05,0x03,0x02,0x03, 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x04,0x03,0x04,0x00,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x04,0x07,0x07,0x07,0x07,0x04,0x00,0x00,0x00,0x00,0x06,0x04,0x03,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x07,0x05,0x05,0x05,0x05,0x05,0x05,0x04,0x04,0x02,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x04,0x04,0x0a,0x08,0x09,0x08,0x0a,0x08,0x0c,0x0a,0x07,0x05,0x07,0x09,0x07,0x0b, 0x09,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0d,0x05,0x03,0x07,0x08,0x05,0x07,0x07,0x08,0x08,0x07,0x0d,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x08,0x07,0x07,0x07,0x04,0x08,0x04,0x0a,0x09,0x07,0x04,0x0b,0x07,0x0b,0x03,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x0b,0x03,0x08,0x03,0x07,0x05,0x03,0x03,0x07,0x03,0x0a,0x03,0x0c,0x07,0x0c,0x0c,0x08,0x08,0x08,0x07,0x07,0x05,0x05,0x0f,0x0f,0x11,0x11,0x0b,0x0b,0x07,0x07,0x02,0x0d,0x0a,0x0b,0x09,0x08,0x09,0x07,0x07,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x03,0x08,0x00,0x08,0x08,0x08,0x04,0x07,0x07,0x0c,0x04,0x0c,0x04, 0x08,0x09,0x08,0x05,0x0c,0x07,0x0c,0x07,0x0a,0x0b,0x04,0x07,0x07,0x05,0x03,0x07,0x08,0x07,0x08,0x07,0x08,0x08,0x07,0x09,0x08,0x0c,0x04,0x07,0x05,0x09,0x07,0x04,0x07,0x07,0x07,0x0c,0x04,0x0c,0x04,0x03,0x08,0x05,0x0d,0x07,0x07,0x08,0x08,0x0d,0x07,0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x0a,0x08,0x00,0x00,0x03,0x03, 0x03,0x03,0x03,0x03,0x05,0x05,0x07,0x07,0x0a,0x0b,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x05,0x05,0x07,0x05,0x05,0x05,0x0f,0x0b,0x0f,0x0b,0x0f,0x0b,0x11,0x0d,0x11, 0x0d,0x0b,0x07,0x08,0x08,0x08,0x0d,0x0d,0x07,0x07,0x0d,0x07,0x07,0x0d,0x07,0x07,0x0d,0x07,0x07,0x0a,0x0a,0x0e,0x0d,0x0c,0x07,0x0b,0x07,0x0b,0x07,0x0b,0x07,0x0c,0x07,0x0c,0x07,0x0c,0x07,0x0c,0x07,0x0c,0x07,0x09,0x04,0x09,0x04,0x09,0x04,0x09,0x04,0x09,0x04,0x09,0x09,0x04,0x09,0x04,0x07,0x09,0x08,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x0b,0x0c,0x0a,0x0b,0x04,0x07,0x0a,0x0b,0x0a,0x0b,0x00,0x00,0x00,0x00,0x00,0x0f,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x05,0x00,0x00,0x08,0x00,0x00,0x00,0x0f,0x0b,0x11,0x0d,0x07,0x08,0x08,0x08,0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x0c,0x0c,0x05,0x08, 0x08,0x08,0x10,0x0b,0x07,0x14,0x0e,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x05,0x05,0x0a,0x09,0x09,0x07,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x10,0x14,0x00,0x00,0x00,0x00,0x00,0x08,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x05,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x08,0x08, 0x08,0x08,0x09,0x08,0x07,0x07,0x05,0x0f,0x0b,0x07,0x08,0x08,0x08,0x07,0x08,0x08,0x08,0x07,0x08,0x08,0x08,0x0d,0x07,0x07,0x0d,0x07,0x07,0x0c,0x07,0x07,0x0c,0x07,0x07,0x0c,0x07,0x07,0x08,0x08,0x08,0x08,0x09,0x04,0x09,0x04,0x09,0x04,0x09,0x09,0x04,0x04,0x05,0x05,0x0f,0x0b,0x08,0x08,0x08,0x00,0x07,0x07,0x07,0x05,0x07,0x09, 0x08,0x07,0x07,0x05,0x03,0x0a,0x08,0x08,0x05,0x07,0x06,0x06,0x06,0x06,0x03,0x07,0x05,0x08,0x06,0x08,0x06,0x07,0x06,0x09,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x06,0x06,0x06,0x04,0x07,0x07,0x08,0x07,0x04,0x0a,0x08,0x08,0x07,0x08,0x06,0x07,0x07,0x05,0x09,0x05,0x05,0x05,0x06,0x08,0x08,0x07,0x0d,0x07,0x0d, 0x04,0x03,0x02,0x07,0x03,0x02,0x00,0x02,0x03,0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x0c,0x06,0x0a,0x08,0x0c,0x09,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0b,0x06,0x0b,0x06,0x0b,0x08,0x09,0x09,0x09,0x0a,0x0b,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09, 0x09,0x0a,0x08,0x0e,0x0b,0x06,0x06,0x04,0x04,0x04,0x05,0x03,0x07,0x03,0x03,0x0b,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x08,0x07,0x06,0x06,0x09,0x03,0x04,0x09,0x09,0x03,0x07,0x07,0x07,0x09,0x09,0x03,0x05,0x09,0x08,0x08,0x08,0x07,0x08,0x09,0x07,0x0a, 0x09,0x07,0x07,0x07,0x03,0x05,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x06,0x09,0x07,0x07,0x09,0x07,0x09,0x07,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x07,0x06,0x06,0x09,0x04,0x05,0x09,0x04,0x07,0x07,0x07,0x09,0x05,0x09,0x08,0x08,0x08,0x09,0x07,0x0a,0x09,0x03,0x07,0x07,0x08,0x08,0x10,0x00,0x08,0x07,0x08,0x08,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x03,0x00,0x0a,0x08,0x09,0x09,0x07,0x09,0x0a,0x0a,0x06,0x08,0x0a,0x0a,0x09,0x0a,0x0b,0x0a,0x09,0x07,0x07,0x0a,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x0a,0x07,0x08,0x09,0x09, 0x0a,0x08,0x08,0x08,0x09,0x0b,0x06,0x08,0x08,0x0b,0x07,0x07,0x0a,0x0c,0x08,0x07,0x0e,0x07,0x07,0x0a,0x07,0x07,0x0a,0x07,0x0a,0x0b,0x0b,0x07,0x0a,0x07,0x09,0x07,0x08,0x07,0x08,0x07,0x08,0x0a,0x07,0x08,0x09,0x07,0x07,0x08,0x0c,0x07,0x07,0x08,0x08,0x06,0x04,0x07,0x07,0x07,0x07,0x07,0x0b,0x07,0x0c,0x06,0x07,0x0c,0x09,0x07, 0x0c,0x0a,0x0a,0x0b,0x07,0x07,0x0c,0x0c,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x08,0x07,0x07,0x0c,0x08,0x07,0x07,0x07,0x0b,0x0a,0x09,0x09,0x09,0x09,0x09,0x08,0x09,0x0a,0x09,0x08,0x07,0x0a,0x09,0x09,0x07,0x09,0x09,0x0a,0x09,0x08,0x09,0x09,0x09,0x09,0x0a,0x09,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x0a,0x09,0x0a,0x09,0x01, 0x01,0x02,0x03,0x02,0x04,0x05,0x0b,0x07,0x08,0x08,0x07,0x08,0x07,0x07,0x08,0x08,0x07,0x04,0x0b,0x08,0x07,0x07,0x07,0x08,0x07,0x08,0x03,0x08,0x07,0x07,0x05,0x0b,0x07,0x07,0x07,0x08,0x0b,0x07,0x08,0x05,0x0b,0x08,0x08,0x09,0x09,0x03,0x04,0x0f,0x0f,0x0f,0x0f,0x13,0x07,0x07,0x03,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x06,0x07,0x08,0x06,0x05,0x07,0x08,0x03,0x04,0x06,0x05,0x0a,0x08,0x08,0x06,0x08,0x06,0x05,0x06,0x08,0x07,0x0a, 0x07,0x06,0x06,0x09,0x0a,0x05,0x08,0x06,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x03,0x03,0x03,0x03,0x03,0x07,0x04,0x06,0x05,0x05, 0x05,0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x09,0x08,0x07,0x06,0x05,0x07,0x06,0x06,0x08,0x08,0x03,0x06,0x07,0x0a,0x08,0x06,0x08,0x08,0x06,0x06,0x06,0x06,0x08,0x07,0x09,0x08,0x07, 0x06,0x08,0x03,0x08,0x06,0x08,0x03,0x06,0x06,0x07,0x05,0x07,0x05,0x03,0x03,0x04,0x0b,0x0b,0x08,0x06,0x06,0x08,0x07,0x06,0x06,0x05,0x08,0x06,0x0a,0x06,0x08,0x08,0x06,0x07,0x0a,0x08,0x08,0x08,0x06,0x07,0x06,0x06,0x08,0x07,0x08,0x07,0x0a,0x0b,0x07,0x09,0x06,0x07,0x0b,0x06,0x05,0x08,0x08,0x08,0x0c,0x0c,0x09,0x07,0x07,0x05, 0x07,0x07,0x07,0x09,0x07,0x07,0x09,0x08,0x08,0x05,0x08,0x08,0x07,0x06,0x06,0x0c,0x0a,0x06,0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x05,0x0c,0x08,0x07,0x07,0x08,0x08,0x07,0x07,0x03,0x0a,0x09,0x09,0x06,0x09,0x03,0x03,0x06,0x06,0x03,0x03,0x08,0x05,0x03,0x0a,0x09,0x04,0x03,0x03,0x06,0x05,0x05,0x03,0x03,0x03,0x05,0x09,0x06,0x04, 0x08,0x09,0x08,0x08,0x06,0x0a,0x07,0x08,0x05,0x06,0x07,0x06,0x03,0x03,0x05,0x07,0x04,0x09,0x09,0x09,0x0c,0x0a,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x0a,0x0b,0x04,0x04,0x07,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x08,0x08,0x08,0x07,0x07,0x0f,0x0b,0x0f,0x0b,0x11,0x0d,0x11,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x07, 0x07,0x0c,0x0c,0x07,0x07,0x0a,0x0b,0x04,0x04,0x0a,0x0b,0x04,0x04,0x0a,0x0b,0x04,0x04,0x0d,0x0a,0x0b,0x07,0x08,0x08,0x09,0x04,0x09,0x0a,0x07,0x07,0x04,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0c,0x04,0x0a,0x07,0x07,0x03,0x07,0x07,0x07,0x07,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04, 0x0c,0x04,0x0c,0x04,0x0c,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0f,0x0b,0x0f,0x0b,0x0f,0x0b,0x11,0x0d,0x11,0x0d,0x0b,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0a,0x07,0x07,0x0a,0x07,0x07,0x0c,0x07,0x0e,0x0d,0x0c,0x07,0x0b,0x07,0x0b,0x07,0x0b,0x07,0x0c,0x07,0x0c,0x07,0x0c, 0x07,0x0c,0x07,0x0c,0x07,0x0c,0x07,0x09,0x09,0x09,0x09,0x09,0x04,0x09,0x09,0x04,0x04,0x09,0x04,0x09,0x04,0x09,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0x00,0x0f,0x0b,0x11,0x0d,0x0c,0x07,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x0c,0x04,0x08,0x08,0x07,0x07, 0x05,0x0f,0x0b,0x0d,0x0d,0x0c,0x0c,0x0c,0x08,0x08,0x08,0x08,0x09,0x04,0x09,0x04,0x09,0x04,0x0f,0x0b,0x08,0x09,0x08,0x08,0x08,0x09,0x08,0x08,0x0f,0x0f,0x0b,0x0b,0x05,0x05,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x0a,0x0b,0x04,0x04,0x0a,0x0b,0x04,0x04,0x0a,0x0b,0x04,0x04,0x08,0x08,0x08,0x08,0x0c,0x04,0x0c,0x04,0x08,0x09, 0x08,0x08,0x0f,0x0f,0x0b,0x0b,0x0f,0x0f,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x03,0x00,0x00,0x00,0x0b,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x09,0x09,0x09,0x03,0x03, 0x07,0x05,0x08,0x08,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x08,0x07,0x08,0x07,0x09,0x0a,0x08,0x0a,0x0b,0x08,0x0a,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x08,0x08,0x09,0x07,0x08,0x07,0x08,0x08,0x07,0x07,0x0a, 0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x09,0x0c,0x0c,0x0a,0x0b,0x0b,0x07,0x0a,0x0b,0x0a,0x08,0x0b,0x0a,0x09,0x09,0x08,0x08,0x0a,0x0a,0x09,0x08,0x09,0x08,0x07,0x0c,0x0c,0x0c,0x0b,0x0c,0x0c,0x09,0x0c,0x0c,0x09,0x0a,0x0a,0x0a,0x09,0x09,0x08,0x0b,0x0a,0x0b,0x09,0x09,0x08,0x0a,0x09,0x09,0x0b,0x0a, 0x09,0x0c,0x07,0x07,0x07,0x07,0x08,0x08,0x09,0x0a,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x06,0x07,0x07,0x08,0x08,0x0a,0x0b,0x09,0x09,0x08,0x0a,0x08,0x09,0x07,0x06,0x08,0x07,0x06,0x06,0x07,0x07,0x06,0x06,0x08,0x06,0x07,0x06,0x07,0x0a,0x07,0x0b,0x07,0x07,0x07,0x0a, 0x04,0x0a,0x09,0x09,0x09,0x07,0x0a,0x08,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x08,0x03,0x03,0x03,0x04,0x04,0x03,0x03,0x03,0x04,0x03,0x03,0x03,0x0c,0x0c,0x0c,0x0c,0x06,0x0a,0x09,0x06,0x05, 0x06,0x07,0x07,0x06,0x0b,0x0b,0x0b,0x06,0x0d,0x06,0x0b,0x0b,0x0b,0x0b,0x07,0x06,0x06,0x0a,0x08,0x0a,0x09,0x07,0x06,0x05,0x0d,0x05,0x07,0x06,0x06,0x06,0x06,0x06,0x12,0x0b,0x0b,0x06,0x03,0x06,0x03,0x06,0x03,0x03,0x03,0x06,0x08,0x08,0x07,0x05,0x05,0x03,0x03,0x03,0x05,0x03,0x05,0x0b,0x03,0x0c,0x0c,0x0c,0x08,0x08,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x09,0x0f,0x0f,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x06,0x08,0x06,0x07,0x06,0x05,0x05,0x09,0x07,0x09,0x06,0x0f,0x0c,0x08,0x07,0x0c,0x0a, 0x0b,0x0a,0x0d,0x0b,0x0c,0x0a,0x08,0x06,0x09,0x08,0x0c,0x0a,0x0a,0x08,0x0a,0x08,0x0b,0x09,0x0b,0x09,0x0e,0x0b,0x0a,0x08,0x0a,0x08,0x10,0x0c,0x0a,0x00,0x0d,0x0d,0x0d,0x06,0x00,0x00,0x08,0x07,0x09,0x07,0x07,0x06,0x0e,0x0c,0x0c,0x0b,0x09,0x08,0x09,0x08,0x07,0x05,0x0a,0x08,0x07,0x05,0x0b,0x09,0x09,0x07,0x0d,0x0b,0x07,0x07, 0x0a,0x0a,0x0b,0x06,0x03,0x06,0x09,0x06,0x0d,0x0d,0x03,0x00,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x05,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x09,0x09,0x04,0x03,0x04,0x03,0x09,0x07,0x0a,0x08,0x07,0x06,0x07,0x06,0x08,0x07,0x05,0x05,0x0f,0x0b,0x0f,0x0c,0x0d,0x0b,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x08,0x06,0x08, 0x06,0x08,0x06,0x08,0x06,0x07,0x04,0x06,0x03,0x0a,0x08,0x0b,0x09,0x11,0x0d,0x07,0x08,0x09,0x09,0x0b,0x0b,0x0a,0x08,0x0d,0x0a,0x07,0x05,0x07,0x06,0x08,0x06,0x0c,0x09,0x08,0x07,0x07,0x08,0x07,0x08,0x06,0x05,0x06,0x05,0x06,0x05,0x07,0x07,0x04,0x09,0x04,0x0c,0x09,0x05,0x08,0x08,0x06,0x0a,0x07,0x05,0x05,0x08,0x08,0x08,0x06, 0x03,0x0a,0x08,0x05,0x05,0x08,0x06,0x09,0x05,0x0a,0x08,0x08,0x06,0x09,0x08,0x08,0x06,0x0a,0x07,0x08,0x05,0x07,0x06,0x0a,0x06,0x07,0x0b,0x06,0x07,0x0c,0x03,0x0f,0x0c,0x0c,0x0f,0x0b,0x0c,0x0c,0x0b,0x0c,0x0c,0x07,0x06,0x08,0x09,0x0c,0x09,0x0c,0x03,0x06,0x08,0x0b,0x0d,0x09,0x0d,0x08,0x08,0x0a,0x09,0x0f,0x0c,0x07,0x0c,0x04, 0x0c,0x04,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x0d,0x07,0x07,0x0d,0x0a,0x07,0x07,0x0a,0x09,0x04,0x04,0x09,0x08,0x08,0x08,0x08,0x0a,0x04,0x04,0x0b,0x0a,0x04,0x04,0x0b,0x05,0x05,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x14,0x07,0x05,0x07,0x07,0x0a,0x07,0x08,0x0b,0x09,0x0a,0x0a,0x0b,0x0b,0x08,0x06,0x0d,0x0a,0x0e,0x0b,0x09,0x08,0x04,0x04,0x08,0x08,0x05,0x08,0x07,0x08,0x06,0x0a,0x0a,0x05,0x08,0x06,0x03,0x05,0x07,0x07,0x03,0x03,0x02,0x03,0x05,0x05,0x05,0x06,0x13,0x1a,0x04,0x05,0x02,0x03,0x05,0x06,0x04,0x06,0x07,0x05,0x05, 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x11,0x07,0x0a,0x0c,0x0c,0x08,0x06,0x07,0x09,0x0a,0x06,0x04,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x0a,0x08,0x08,0x07,0x0a,0x08,0x0b,0x06,0x07,0x08,0x04,0x08,0x04,0x05,0x03,0x0b,0x08,0x07,0x07,0x07,0x08,0x0c,0x0c,0x0c,0x0d,0x0d,0x07,0x07,0x04,0x07,0x06,0x08, 0x06,0x09,0x03,0x07,0x08,0x0b,0x0b,0x08,0x07,0x07,0x07,0x07,0x06,0x07,0x06,0x06,0x04,0x04,0x03,0x03,0x05,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x04,0x04,0x04,0x03,0x03,0x16,0x0d,0x0b,0x0e,0x04,0x04,0x04,0x05,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x00,0x0c,0x04,0x04,0x0c,0x03,0x07,0x07,0x11,0x0d,0x0d,0x11,0x0c,0x07,0x07,0x0c,0x07,0x07,0x05,0x05,0x00,0x00,0x05,0x0a,0x08,0x09,0x08,0x10,0x0d,0x09,0x07,0x09,0x07,0x11,0x0d,0x0a,0x08,0x05,0x04,0x08,0x00,0x09,0x07,0x04,0x04,0x02,0x06,0x04,0x04,0x03,0x03,0x06,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x07,0x06, 0x08,0x07,0x07,0x0d,0x0b,0x0a,0x0a,0x0b,0x0c,0x08,0x09,0x08,0x05,0x0c,0x0f,0x06,0x0f,0x07,0x0b,0x0c,0x0c,0x0c,0x05,0x0a,0x0d,0x0a,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x08,0x08,0x0b,0x07,0x07,0x0c,0x04,0x04,0x0c,0x04,0x04,0x0c,0x06,0x06,0x00,0x05,0x0b,0x04,0x04,0x0d, 0x07,0x07,0x0a,0x07,0x07,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x14,0x14,0x0b,0x00,0x00,0x0b,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x08,0x08,0x08,0x0c,0x08,0x08,0x0a,0x0d,0x08,0x08,0x0e,0x08,0x08,0x0c,0x08,0x09,0x0a,0x08,0x0a, 0x0b,0x0c,0x08,0x0a,0x08,0x09,0x08,0x09,0x08,0x09,0x09,0x08,0x0a,0x08,0x09,0x0a,0x08,0x08,0x07,0x0a,0x08,0x08,0x08,0x09,0x06,0x07,0x08,0x0a,0x0a,0x07,0x00,0x00,0x0f,0x1e,0x0a,0x00,0x01,0x04,0x04,0x06,0x09,0x08,0x0c,0x0c,0x03,0x05,0x05,0x06,0x0a,0x03,0x06,0x03,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x03, 0x03,0x0a,0x0a,0x0a,0x07,0x0e,0x0a,0x09,0x09,0x0b,0x08,0x07,0x0a,0x0b,0x04,0x05,0x09,0x07,0x0d,0x0b,0x0b,0x08,0x0b,0x09,0x08,0x08,0x0a,0x09,0x0e,0x09,0x08,0x09,0x05,0x06,0x05,0x0a,0x06,0x04,0x08,0x09,0x07,0x09,0x08,0x05,0x09,0x08,0x04,0x04,0x07,0x04,0x0d,0x08,0x09,0x09,0x09,0x05,0x06,0x05,0x08,0x07,0x0b,0x07,0x07,0x07, 0x05,0x04,0x05,0x0a,0x0a,0x0a,0x09,0x08,0x0b,0x0b,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x08,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x06,0x06,0x08,0x08,0x07,0x06,0x07,0x08,0x06,0x0d,0x0d,0x0c,0x04,0x06,0x0a,0x0d,0x0b,0x0c,0x0a,0x0a,0x0a,0x08,0x09,0x08,0x09,0x0b,0x08,0x06, 0x06,0x0b,0x0c,0x09,0x07,0x04,0x04,0x0a,0x0a,0x08,0x0a,0x0a,0x08,0x08,0x0b,0x0a,0x0a,0x0b,0x0e,0x0e,0x08,0x0f,0x06,0x06,0x03,0x03,0x0a,0x09,0x07,0x08,0x03,0x08,0x05,0x05,0x08,0x08,0x06,0x03,0x03,0x06,0x12,0x0a,0x08,0x0a,0x08,0x08,0x04,0x04,0x04,0x04,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x04,0x06,0x05,0x05,0x05,0x03,0x04,0x03, 0x05,0x03,0x06,0x07,0x04,0x08,0x06,0x09,0x07,0x04,0x0b,0x08,0x08,0x07,0x08,0x09,0x0a,0x0a,0x05,0x06,0x06,0x0e,0x0e,0x0e,0x07,0x0a,0x09,0x04,0x08,0x06,0x09,0x07,0x09,0x07,0x09,0x06,0x03,0x0a,0x08,0x0a,0x08,0x0b,0x0a,0x0b,0x08,0x08,0x08,0x08,0x07,0x04,0x07,0x05,0x07,0x05,0x0b,0x08,0x0b,0x08,0x0b,0x09,0x09,0x05,0x09,0x05, 0x08,0x06,0x08,0x05,0x08,0x07,0x0a,0x08,0x0a,0x08,0x09,0x07,0x09,0x07,0x07,0x0b,0x0b,0x09,0x09,0x07,0x09,0x07,0x0a,0x06,0x07,0x06,0x11,0x09,0x07,0x09,0x03,0x06,0x0c,0x05,0x09,0x05,0x05,0x09,0x05,0x0a,0x08,0x09,0x07,0x09,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x09,0x0a,0x09,0x0a,0x09,0x0b,0x08,0x0b,0x08,0x04,0x04,0x04, 0x04,0x04,0x04,0x04,0x04,0x05,0x04,0x09,0x07,0x07,0x07,0x04,0x0b,0x08,0x0b,0x08,0x0b,0x09,0x0b,0x09,0x09,0x05,0x08,0x06,0x08,0x05,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0e,0x0b,0x08,0x07,0x04,0x0a,0x08,0x0d,0x0c,0x0b,0x09,0x03,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x08,0x07,0x03,0x06,0x08,0x09,0x0e,0x0e,0x0e,0x0d,0x06,0x06, 0x03,0x04,0x04,0x0a,0x09,0x0c,0x06,0x0c,0x0a,0x0c,0x04,0x0a,0x09,0x08,0x09,0x0b,0x04,0x09,0x09,0x0d,0x0b,0x08,0x0b,0x0b,0x08,0x08,0x08,0x08,0x09,0x0c,0x0b,0x04,0x08,0x09,0x07,0x09,0x04,0x08,0x08,0x08,0x07,0x09,0x09,0x04,0x08,0x07,0x09,0x08,0x07,0x09,0x09,0x07,0x08,0x08,0x0b,0x0c,0x04,0x08,0x09,0x08,0x0c,0x08,0x0b,0x07, 0x09,0x08,0x04,0x0f,0x0f,0x0b,0x09,0x09,0x0b,0x0a,0x09,0x09,0x07,0x0a,0x08,0x0d,0x08,0x0b,0x0b,0x09,0x0a,0x0d,0x0b,0x0b,0x0b,0x08,0x09,0x08,0x09,0x0b,0x09,0x0b,0x0a,0x0e,0x0f,0x0b,0x0c,0x09,0x09,0x0f,0x09,0x08,0x09,0x08,0x06,0x08,0x08,0x0b,0x07,0x09,0x09,0x07,0x08,0x0b,0x09,0x09,0x09,0x09,0x07,0x06,0x07,0x0a,0x07,0x09, 0x08,0x0c,0x0c,0x09,0x0b,0x08,0x07,0x0c,0x08,0x08,0x09,0x06,0x07,0x06,0x04,0x0c,0x0c,0x09,0x07,0x07,0x09,0x07,0x06,0x0f,0x11,0x09,0x05,0x06,0x06,0x06,0x04,0x08,0x06,0x08,0x0b,0x09,0x0b,0x09,0x05,0x05,0x04,0x04,0x07,0x07,0x07,0x07,0x05,0x05,0x05,0x07,0x05,0x07,0x05,0x05,0x05,0x07,0x07,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a, 0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0a,0x08,0x0a, 0x08,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x07,0x08,0x07,0x08,0x07,0x08,0x05,0x08,0x08,0x0b,0x09,0x04,0x05,0x04,0x04,0x08,0x06,0x0e,0x0c,0x09,0x08,0x09,0x07,0x0b,0x09,0x08,0x07,0x08,0x07,0x09,0x07,0x0a,0x08,0x0a,0x08,0x0b,0x08,0x0b,0x09,0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x07,0x04,0x04,0x05, 0x05,0x05,0x05,0x08,0x08,0x0a,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x05,0x0a,0x09,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x04,0x04,0x04,0x04,0x09,0x07,0x09,0x07,0x09,0x07,0x07,0x04,0x07,0x04,0x07, 0x04,0x07,0x04,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x08,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x09,0x08,0x09,0x09,0x05,0x09,0x05,0x09,0x05,0x09,0x05,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x05,0x08,0x05,0x08,0x05,0x08,0x05,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a, 0x08,0x09,0x07,0x09,0x07,0x0e,0x0b,0x0e,0x0b,0x09,0x07,0x09,0x07,0x08,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x05,0x0b,0x07,0x08,0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c, 0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x09, 0x09,0x07,0x07,0x09,0x09,0x04,0x04,0x09,0x09,0x08,0x08,0x0c,0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0b,0x09,0x09,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x06,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x09,0x09,0x08,0x08,0x08,0x08,0x0a,0x0a,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d, 0x0c,0x0b,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x0b,0x0b,0x09,0x09,0x09,0x08,0x08,0x07,0x0a,0x09,0x0d,0x04,0x04,0x09,0x07,0x04,0x07,0x0d,0x0b,0x09,0x0b,0x0f,0x0c,0x09,0x09,0x09,0x08,0x06,0x08,0x04,0x05,0x08,0x05,0x08,0x0b,0x0b,0x09, 0x08,0x09,0x07,0x09,0x09,0x07,0x06,0x08,0x08,0x06,0x06,0x08,0x04,0x06,0x07,0x04,0x13,0x11,0x0f,0x0d,0x0b,0x08,0x10,0x0f,0x0c,0x0a,0x08,0x04,0x04,0x0b,0x09,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x08,0x0a,0x08,0x0a,0x08,0x0d,0x0c,0x0a,0x09,0x0a,0x09,0x09,0x07,0x0b,0x09,0x0b,0x09,0x09,0x07,0x04,0x13,0x11,0x0f, 0x0a,0x09,0x0f,0x0a,0x0b,0x08,0x0a,0x08,0x0a,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x0b,0x09,0x0b,0x09,0x09,0x05,0x09,0x05,0x0a,0x08,0x0a,0x08,0x08,0x06,0x0b,0x08,0x0b,0x09,0x09,0x09,0x07,0x0a,0x08,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x07,0x09,0x08,0x08,0x08,0x09,0x08,0x09,0x09,0x09,0x07,0x07,0x09,0x09, 0x08,0x09,0x06,0x06,0x08,0x08,0x04,0x09,0x09,0x08,0x07,0x07,0x08,0x08,0x08,0x04,0x04,0x05,0x04,0x06,0x04,0x09,0x0d,0x0d,0x0d,0x08,0x08,0x09,0x09,0x0a,0x0b,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x06,0x04,0x04,0x04,0x04,0x05,0x05,0x09,0x09,0x08,0x07,0x0b,0x07,0x06,0x07,0x08,0x07,0x07,0x05,0x05,0x05,0x07,0x09, 0x07,0x08,0x08,0x08,0x04,0x07,0x06,0x09,0x05,0x05,0x0e,0x0e,0x0f,0x09,0x07,0x0b,0x0c,0x09,0x09,0x07,0x07,0x08,0x09,0x08,0x0a,0x08,0x0a,0x0c,0x09,0x0b,0x09,0x09,0x07,0x07,0x07,0x09,0x08,0x09,0x07,0x0d,0x0d,0x09,0x08,0x0a,0x08,0x09,0x07,0x09,0x07,0x0a,0x09,0x08,0x06,0x09,0x09,0x07,0x04,0x0b,0x07,0x07,0x0d,0x0a,0x0a,0x09, 0x0e,0x0b,0x0a,0x07,0x0d,0x0a,0x0b,0x08,0x0e,0x0b,0x08,0x07,0x0c,0x0b,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x14,0x11,0x0c,0x0a,0x11,0x0d,0x0d,0x0a,0x09,0x07,0x08,0x06,0x06,0x00,0x00,0x0f,0x0e,0x09,0x08,0x08,0x09,0x09,0x08,0x08,0x07,0x09,0x07,0x0b,0x09,0x0d,0x0a,0x0f,0x0d,0x0b,0x08,0x09,0x07,0x08,0x06,0x0d,0x0a,0x0a,0x09,0x0d, 0x0a,0x0d,0x0a,0x04,0x0d,0x0b,0x09,0x08,0x0b,0x09,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0d,0x0c,0x08,0x08,0x0b,0x08,0x0b,0x08,0x0d,0x0b,0x08,0x07,0x08,0x07,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x0a,0x08,0x0c,0x0b,0x09,0x09,0x0d,0x0d,0x0c,0x0b,0x08,0x07,0x0e,0x0c,0x0f,0x0d,0x0b,0x08, 0x0a,0x09,0x09,0x08,0x08,0x08,0x09,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x09,0x05,0x05,0x02,0x03,0x03,0x03,0x04,0x06,0x04,0x03,0x06,0x03,0x03,0x03,0x05,0x05,0x03,0x03,0x09,0x09,0x09,0x09,0x05,0x04,0x04,0x05,0x05,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x04, 0x02,0x04,0x04,0x03,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x06,0x05,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08, 0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x08, 0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x0a,0x04,0x09,0x05,0x09,0x09,0x05,0x05,0x05,0x05,0x05,0x04,0x05,0x05,0x05,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x08,0x09,0x07,0x0a,0x0c,0x07,0x07,0x08,0x08,0x06,0x06,0x04,0x04,0x07,0x06,0x0b,0x09,0x09,0x07,0x09,0x09,0x09,0x0e,0x08,0x09,0x09,0x07,0x07,0x07,0x06,0x08,0x09,0x0b,0x09,0x07,0x0b,0x07,0x06,0x06,0x08,0x06,0x07,0x09,0x07,0x09,0x08,0x05,0x07,0x05,0x05,0x06,0x05,0x05,0x06,0x06,0x03,0x03,0x05,0x04,0x08,0x07,0x07, 0x06,0x06,0x05,0x05,0x04,0x06,0x08,0x05,0x05,0x05,0x07,0x05,0x05,0x05,0x05,0x04,0x04,0x05,0x02,0x05,0x07,0x05,0x05,0x04,0x05,0x05,0x05,0x03,0x05,0x05,0x07,0x04,0x05,0x05,0x04,0x05,0x06,0x04,0x02,0x03,0x05,0x04,0x05,0x04,0x05,0x06,0x04,0x09,0x02,0x05,0x08,0x0d,0x09,0x08,0x08,0x0d,0x0a,0x0d,0x0b,0x08,0x09,0x08,0x07,0x11, 0x07,0x09,0x0d,0x0e,0x0e,0x09,0x0a,0x09,0x07,0x07,0x08,0x06,0x07,0x08,0x03,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x07,0x06,0x09,0x09,0x05,0x0d,0x08,0x09,0x05,0x05,0x07,0x05,0x07,0x09,0x07,0x09,0x0e,0x0a,0x05,0x04,0x09,0x08,0x09,0x09,0x09,0x05,0x09,0x07,0x04,0x0d,0x08,0x09,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x09,0x09, 0x08,0x07,0x07,0x0b,0x04,0x07,0x04,0x08,0x07,0x05,0x04,0x04,0x05,0x04,0x03,0x02,0x05,0x05,0x02,0x03,0x03,0x03,0x02,0x03,0x02,0x03,0x07,0x07,0x05,0x05,0x05,0x05,0x06,0x03,0x02,0x03,0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x05,0x00,0x00,0x00,0x00,0x03,0x05,0x05,0x05,0x04,0x05,0x08,0x08,0x08,0x08,0x05,0x00,0x00,0x00, 0x00,0x07,0x05,0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x08,0x08,0x08,0x08,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x03,0x06,0x06,0x05,0x06,0x05,0x06,0x06,0x06, 0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x06,0x05,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x0c,0x09,0x0b,0x09,0x0b,0x09,0x0e,0x0b,0x08,0x06,0x08,0x0a,0x08,0x0c,0x0b,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x0d,0x0d,0x0f,0x06,0x04,0x08,0x09,0x06,0x08,0x08, 0x09,0x09,0x08,0x0f,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x0a,0x08,0x08,0x08,0x05,0x09,0x05,0x0b,0x0a,0x08,0x05,0x0d,0x08,0x0d,0x04,0x05,0x09,0x09,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x0d,0x04,0x09,0x04,0x08,0x06,0x04,0x04,0x08,0x04,0x0b,0x04,0x0e,0x08,0x0e,0x0e,0x09,0x09,0x09,0x08,0x08,0x06,0x06,0x12,0x12,0x14,0x14,0x0d, 0x0d,0x08,0x08,0x03,0x0f,0x0b,0x0d,0x0a,0x09,0x0a,0x08,0x08,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x0a,0x00,0x0a,0x0a,0x0a,0x05,0x08,0x08,0x0e,0x05,0x0e,0x05,0x09,0x0a,0x09,0x06,0x0e,0x08,0x0e,0x08,0x0b,0x0d,0x05,0x08,0x08,0x06,0x04,0x08,0x09,0x08,0x09,0x08,0x09,0x09,0x08,0x0a,0x0a,0x0e,0x05,0x08, 0x06,0x0a,0x08,0x05,0x08,0x08,0x08,0x0e,0x05,0x0e,0x05,0x04,0x09,0x06,0x0f,0x08,0x08,0x0a,0x0a,0x0f,0x08,0x00,0x00,0x00,0x0a,0x00,0x0a,0x0a,0x0a,0x0a,0x0b,0x0a,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x08,0x08,0x0b,0x0d,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x08,0x06,0x06,0x06,0x12,0x0d,0x12,0x0d,0x12,0x0d,0x14,0x0f,0x14,0x0f,0x0d,0x08,0x09,0x09,0x09,0x0f,0x0f,0x08,0x08,0x0f,0x08,0x08,0x0f,0x08,0x08,0x0f,0x08,0x08,0x0b,0x0b,0x10,0x0f,0x0e,0x08,0x0d,0x08,0x0d, 0x08,0x0d,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x0a,0x05,0x0a,0x05,0x08,0x0a,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0e,0x0b,0x0d,0x05,0x08,0x0b,0x0d,0x0b,0x0d,0x00,0x00,0x00,0x00,0x00,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x06, 0x00,0x00,0x09,0x00,0x00,0x00,0x12,0x0d,0x14,0x0f,0x08,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x0e,0x0e,0x06,0x09,0x09,0x09,0x12,0x0c,0x08,0x17,0x10,0x05,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x06,0x06,0x0b,0x0a,0x0a,0x08,0x00,0x00, 0x00,0x05,0x05,0x05,0x05,0x13,0x17,0x00,0x00,0x00,0x00,0x00,0x09,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x06,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x09,0x09,0x09,0x09,0x0a,0x09,0x08,0x08,0x06,0x12,0x0d,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x0f,0x08,0x08,0x0f,0x08,0x08,0x0e, 0x08,0x08,0x0e,0x08,0x08,0x0e,0x08,0x08,0x09,0x09,0x09,0x09,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x0a,0x05,0x05,0x06,0x06,0x12,0x0d,0x0a,0x09,0x09,0x00,0x08,0x08,0x08,0x06,0x09,0x0a,0x09,0x08,0x08,0x05,0x04,0x0b,0x09,0x09,0x05,0x08,0x07,0x07,0x07,0x07,0x04,0x08,0x06,0x09,0x07,0x09,0x07,0x08,0x07,0x0a,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x07,0x07,0x07,0x04,0x08,0x08,0x09,0x08,0x05,0x0b,0x09,0x0a,0x08,0x09,0x07,0x09,0x08,0x06,0x0a,0x06,0x06,0x06,0x07,0x09,0x09,0x08,0x0f,0x08,0x0f,0x05,0x04,0x03,0x08,0x03,0x02,0x00,0x02,0x03,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x0e,0x06,0x0b, 0x09,0x0e,0x0b,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0d,0x07,0x0d,0x07,0x0d,0x0a,0x0a,0x0b,0x0a,0x0b,0x0d,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x0b,0x09,0x10,0x0c,0x07,0x07,0x04,0x04,0x04,0x06,0x03,0x08,0x03,0x03,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x06,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x0a,0x09,0x07,0x07,0x0a,0x04,0x05,0x0a,0x0a,0x04,0x08,0x08,0x08,0x0a,0x0a,0x04,0x06,0x0a,0x09,0x09,0x09,0x08,0x09,0x0a,0x08,0x0c,0x0b,0x08,0x08,0x08,0x03,0x06,0x08,0x08,0x08,0x08,0x08,0x09,0x0a,0x07,0x0a,0x08,0x08,0x0a,0x08,0x0b,0x08,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a, 0x09,0x07,0x07,0x0a,0x05,0x05,0x0a,0x05,0x08,0x08,0x08,0x0a,0x06,0x0a,0x09,0x09,0x09,0x0a,0x08,0x0c,0x0b,0x04,0x09,0x08,0x09,0x0a,0x12,0x00,0x0a,0x08,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x06,0x04,0x00,0x0b,0x0a,0x0a,0x0b,0x08,0x0a,0x0b,0x0b,0x07,0x09,0x0b,0x0b,0x0a,0x0b,0x0c,0x0c,0x0a,0x08,0x08,0x0b,0x0b,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x09,0x0a,0x0a,0x0a,0x0c,0x09,0x09,0x0a,0x0a,0x0c,0x07,0x09,0x09,0x0d,0x08,0x08,0x0c,0x0d,0x09,0x08,0x10,0x09,0x09,0x0b,0x08,0x08,0x0b,0x08,0x0b,0x0c,0x0d,0x08, 0x0c,0x08,0x0a,0x08,0x09,0x09,0x09,0x08,0x09,0x0c,0x08,0x09,0x0a,0x08,0x08,0x09,0x0e,0x08,0x08,0x09,0x09,0x06,0x05,0x08,0x08,0x08,0x08,0x08,0x0d,0x08,0x0d,0x07,0x08,0x0d,0x0a,0x08,0x0d,0x0b,0x0b,0x0d,0x09,0x08,0x0d,0x0d,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0d,0x09,0x08,0x09,0x0d,0x09,0x08,0x08,0x08,0x0d,0x0c,0x0a,0x0a, 0x0a,0x0a,0x0b,0x09,0x0a,0x0c,0x0a,0x0a,0x08,0x0c,0x0a,0x0a,0x09,0x0a,0x0a,0x0b,0x0b,0x09,0x0a,0x0a,0x0b,0x0a,0x0c,0x0b,0x0b,0x0b,0x0a,0x0a,0x0b,0x0a,0x0b,0x0c,0x0a,0x0b,0x0b,0x01,0x02,0x02,0x03,0x02,0x04,0x05,0x0d,0x08,0x09,0x09,0x08,0x09,0x08,0x08,0x0a,0x09,0x08,0x05,0x0d,0x09,0x08,0x08,0x08,0x09,0x08,0x09,0x04,0x09, 0x08,0x08,0x06,0x0d,0x08,0x08,0x08,0x09,0x0c,0x08,0x09,0x06,0x0c,0x09,0x09,0x0a,0x0a,0x03,0x04,0x11,0x11,0x11,0x11,0x15,0x08,0x08,0x04,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x07,0x08,0x09,0x06,0x06,0x09,0x09,0x04,0x05,0x07,0x06,0x0b,0x0a,0x09,0x07,0x09,0x07,0x06,0x07,0x09,0x08,0x0c,0x08,0x07,0x07,0x0b,0x0c,0x06,0x09,0x07,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x0a,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x06,0x06,0x06,0x06,0x06,0x09,0x09,0x08,0x09,0x09,0x04,0x04,0x04,0x04,0x04,0x08,0x05,0x07,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x07,0x07,0x07,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c, 0x0c,0x0c,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x0b,0x09,0x08,0x07,0x06,0x08,0x06,0x07,0x09,0x09,0x04,0x07,0x08,0x0b,0x0a,0x07,0x09,0x09,0x07,0x07,0x07,0x07,0x09,0x08,0x0a,0x0a,0x08,0x06,0x09,0x04,0x09,0x07,0x0a,0x04,0x07,0x06,0x09,0x06,0x08,0x06,0x04,0x04,0x05,0x0c,0x0c,0x09,0x07,0x07,0x09,0x08,0x07,0x07,0x06,0x09,0x06, 0x0b,0x07,0x0a,0x0a,0x07,0x09,0x0b,0x09,0x09,0x09,0x07,0x08,0x07,0x07,0x09,0x08,0x0a,0x08,0x0c,0x0c,0x09,0x0b,0x07,0x08,0x0d,0x07,0x06,0x09,0x09,0x09,0x0d,0x0d,0x0a,0x08,0x09,0x06,0x09,0x08,0x08,0x0b,0x08,0x08,0x0a,0x09,0x09,0x05,0x09,0x09,0x09,0x07,0x07,0x0d,0x0b,0x07,0x08,0x09,0x09,0x09,0x09,0x0b,0x0a,0x05,0x0e,0x09, 0x08,0x09,0x0a,0x0a,0x08,0x08,0x04,0x0b,0x0a,0x0a,0x07,0x0b,0x03,0x03,0x07,0x07,0x03,0x03,0x09,0x06,0x04,0x0b,0x0b,0x04,0x03,0x03,0x07,0x06,0x06,0x03,0x03,0x03,0x06,0x0a,0x07,0x05,0x09,0x0a,0x09,0x09,0x07,0x0b,0x08,0x09,0x05,0x07,0x08,0x06,0x03,0x03,0x06,0x08,0x05,0x0a,0x0a,0x0a,0x0e,0x0b,0x0e,0x04,0x00,0x00,0x00,0x00, 0x00,0x04,0x0b,0x0d,0x05,0x05,0x08,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x09,0x09,0x09,0x08,0x08,0x12,0x0d,0x12,0x0d,0x14,0x0f,0x14,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x08,0x08,0x0e,0x0e,0x08,0x08,0x0b,0x0d,0x05,0x05,0x0b,0x0d,0x05,0x05,0x0b,0x0d,0x05,0x05,0x0f,0x0b,0x0d,0x08,0x09,0x09,0x0a,0x05,0x0a,0x0b,0x08, 0x08,0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0e,0x05,0x0b,0x08,0x08,0x04,0x08,0x08,0x08,0x08,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x12,0x0d,0x12,0x0d,0x12,0x0d, 0x14,0x0f,0x14,0x0f,0x0d,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0b,0x08,0x08,0x0b,0x08,0x08,0x0e,0x08,0x10,0x0f,0x0e,0x08,0x0d,0x08,0x0d,0x08,0x0d,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x05,0x0a,0x0a,0x05,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x08,0x09,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x05,0x05,0x08,0x05,0x05,0x05,0x05,0x00,0x12,0x0d,0x14,0x0f,0x0e,0x08,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x0e,0x05,0x09,0x09,0x08,0x08,0x06,0x12,0x0d,0x0f,0x0f,0x0e,0x0e,0x0e,0x09,0x09,0x09,0x09,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x12,0x0d,0x09,0x0a,0x09,0x09,0x09,0x0a,0x09,0x09, 0x12,0x12,0x0d,0x0d,0x06,0x06,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x0b,0x0d,0x05,0x05,0x0b,0x0d,0x05,0x05,0x0b,0x0d,0x05,0x05,0x09,0x09,0x09,0x09,0x0e,0x05,0x0e,0x05,0x09,0x0a,0x09,0x09,0x12,0x12,0x0d,0x0d,0x12,0x12,0x0d,0x0d,0x0d,0x0d,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x05,0x04, 0x00,0x00,0x00,0x0d,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x0d,0x09,0x0d,0x09,0x0d,0x09,0x0d,0x0a,0x0a,0x0a,0x04,0x04,0x08,0x06,0x09,0x0a,0x09,0x08,0x08,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x08,0x09,0x09,0x09,0x0a, 0x09,0x08,0x0a,0x08,0x0a,0x0b,0x0a,0x0b,0x0c,0x0a,0x0b,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x09,0x09,0x0a,0x09,0x0a,0x09,0x09,0x09,0x08,0x08,0x0b,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x0b,0x0c,0x0b,0x0b,0x0e,0x0e,0x0b,0x0e,0x0e,0x0b,0x0d,0x0d,0x08,0x0c,0x0d,0x0b,0x09,0x0d,0x0b,0x0a,0x0b, 0x09,0x0a,0x0b,0x0c,0x0a,0x09,0x0b,0x09,0x08,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0a,0x0e,0x0e,0x0b,0x0c,0x0c,0x0b,0x0b,0x0b,0x0a,0x0d,0x0b,0x0c,0x0b,0x0b,0x09,0x0b,0x0a,0x0a,0x0d,0x0b,0x0b,0x0d,0x08,0x08,0x08,0x08,0x09,0x09,0x0a,0x0b,0x09,0x09,0x08,0x08,0x09,0x08,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x08,0x08,0x09,0x09,0x09, 0x09,0x07,0x08,0x08,0x09,0x09,0x0b,0x0d,0x0a,0x0a,0x09,0x0c,0x0a,0x0a,0x08,0x07,0x09,0x08,0x07,0x07,0x08,0x08,0x07,0x07,0x09,0x07,0x08,0x07,0x08,0x0c,0x08,0x0c,0x08,0x08,0x09,0x0b,0x05,0x0c,0x0a,0x0b,0x0a,0x08,0x0b,0x09,0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x07, 0x07,0x07,0x07,0x07,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x09,0x04,0x04,0x04,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x0e,0x0e,0x0e,0x0e,0x07,0x0b,0x0b,0x07,0x06,0x07,0x08,0x08,0x07,0x0d,0x0c,0x0d,0x07,0x0f,0x07,0x0d,0x0d,0x0d,0x0c,0x08,0x07,0x07,0x0c,0x09,0x0c,0x0a,0x08,0x07,0x06,0x0f,0x06,0x08,0x07, 0x07,0x07,0x07,0x07,0x14,0x0d,0x0d,0x06,0x04,0x07,0x04,0x07,0x04,0x04,0x04,0x07,0x09,0x09,0x08,0x06,0x06,0x03,0x03,0x03,0x06,0x03,0x06,0x0d,0x03,0x0e,0x0e,0x0e,0x09,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x12,0x12,0x0a,0x12,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x07,0x09,0x07,0x08,0x06,0x05,0x05,0x0a,0x08,0x0b,0x06,0x11,0x0d,0x09,0x08,0x0e,0x0c,0x0d,0x0b,0x0f,0x0c,0x0e,0x0c,0x0a,0x07,0x0b,0x09,0x0e,0x0b,0x0b,0x09,0x0b,0x09,0x0d,0x0a,0x0d,0x0a,0x11,0x0d,0x0b,0x09,0x0b,0x09,0x12,0x0d, 0x0c,0x00,0x0f,0x0f,0x0f,0x07,0x00,0x00,0x09,0x08,0x0a,0x08,0x08,0x06,0x10,0x0e,0x0e,0x0d,0x0b,0x09,0x0a,0x09,0x08,0x06,0x0b,0x09,0x08,0x06,0x0c,0x0a,0x0a,0x08,0x0f,0x0c,0x08,0x09,0x0b,0x0b,0x0c,0x07,0x03,0x07,0x0a,0x06,0x0f,0x0f,0x04,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x06,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00, 0x00,0x07,0x07,0x0a,0x0b,0x04,0x03,0x04,0x03,0x0b,0x08,0x0b,0x09,0x08,0x07,0x08,0x07,0x09,0x09,0x06,0x06,0x11,0x0c,0x11,0x0d,0x0f,0x0d,0x0e,0x0a,0x0e,0x0a,0x0e,0x0a,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x05,0x07,0x04,0x0b,0x09,0x0d,0x0a,0x14,0x0f,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0b,0x09,0x0f,0x0c,0x08,0x06,0x08, 0x07,0x09,0x07,0x0e,0x0b,0x09,0x08,0x08,0x09,0x08,0x09,0x07,0x06,0x07,0x06,0x07,0x06,0x08,0x08,0x05,0x0a,0x05,0x0e,0x0a,0x05,0x09,0x09,0x07,0x0b,0x08,0x06,0x05,0x09,0x09,0x09,0x07,0x04,0x0b,0x09,0x06,0x05,0x09,0x07,0x0b,0x06,0x0c,0x09,0x09,0x07,0x0a,0x09,0x09,0x07,0x0b,0x08,0x09,0x05,0x08,0x06,0x0b,0x06,0x08,0x0d,0x07, 0x08,0x0d,0x04,0x11,0x0d,0x0d,0x12,0x0d,0x0e,0x0e,0x0d,0x0d,0x0e,0x08,0x07,0x09,0x0b,0x0d,0x0b,0x0e,0x04,0x07,0x09,0x0d,0x0f,0x0b,0x0f,0x09,0x09,0x0c,0x0b,0x11,0x0e,0x08,0x0e,0x05,0x0e,0x05,0x09,0x09,0x09,0x09,0x0d,0x0d,0x0d,0x0d,0x0f,0x08,0x08,0x0f,0x0b,0x08,0x08,0x0b,0x0a,0x05,0x05,0x0a,0x09,0x09,0x09,0x09,0x0b,0x05, 0x05,0x0d,0x0b,0x05,0x05,0x0d,0x06,0x06,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x08,0x06,0x08,0x08,0x0b,0x09,0x09,0x0d,0x0a,0x0b,0x0b,0x0c,0x0c,0x09,0x07,0x0f,0x0c,0x10,0x0d,0x0a,0x09,0x05,0x05,0x09, 0x0a,0x06,0x09,0x08,0x09,0x07,0x0b,0x0c,0x06,0x09,0x06,0x03,0x06,0x08,0x08,0x03,0x03,0x03,0x03,0x06,0x06,0x06,0x07,0x16,0x1e,0x05,0x06,0x02,0x04,0x06,0x06,0x05,0x07,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x14,0x08,0x0b,0x0e,0x0d,0x0a,0x07,0x08,0x0b,0x0b,0x07,0x05,0x0a,0x08,0x0a, 0x08,0x0a,0x08,0x08,0x0b,0x09,0x09,0x08,0x0b,0x09,0x0c,0x07,0x08,0x0a,0x05,0x09,0x05,0x05,0x04,0x0d,0x09,0x08,0x08,0x08,0x09,0x0e,0x0e,0x0e,0x0f,0x0f,0x08,0x08,0x04,0x08,0x07,0x09,0x07,0x0a,0x04,0x08,0x09,0x0d,0x0d,0x09,0x08,0x09,0x08,0x08,0x07,0x08,0x07,0x07,0x05,0x05,0x04,0x03,0x05,0x09,0x0a,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x00,0x04,0x04,0x04,0x04,0x04,0x19,0x0f,0x0d,0x10,0x04,0x04,0x05,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x0e,0x05,0x05,0x0e,0x04,0x08,0x08,0x14,0x0f,0x0f,0x14,0x0e,0x08,0x08,0x0e,0x08,0x08,0x06,0x06,0x00,0x00,0x05,0x0b,0x09,0x0b,0x09, 0x13,0x10,0x0a,0x08,0x0b,0x08,0x14,0x0f,0x0b,0x09,0x06,0x05,0x09,0x00,0x0a,0x08,0x05,0x05,0x02,0x07,0x05,0x05,0x04,0x03,0x07,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x08,0x06,0x09,0x09,0x08,0x0e,0x0c,0x0c,0x0c,0x0c,0x0e,0x09,0x0a,0x09,0x06,0x0e,0x11,0x07,0x11,0x08,0x0d,0x0e,0x0e,0x0e,0x06,0x0b,0x0f,0x0b,0x0a,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x09,0x09,0x09,0x0d,0x08,0x08,0x0e,0x05,0x05,0x0e,0x05,0x05,0x0e,0x07,0x07,0x00,0x06,0x0d,0x05,0x05,0x0f,0x08,0x08,0x0b,0x08,0x08,0x0a,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x17,0x17,0x0d,0x00,0x00,0x0d,0x0d, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x09,0x0a,0x0a,0x0d,0x0a,0x09,0x0c,0x0f,0x0a,0x09,0x10,0x0a,0x0a,0x0e,0x09,0x0a,0x0c,0x0a,0x0c,0x0d,0x0e,0x0a,0x0c,0x0a,0x0a,0x09,0x0a,0x09,0x0a,0x0a,0x09,0x0c,0x09,0x0a,0x0c,0x09,0x09,0x09,0x0c,0x0a,0x0a,0x0a,0x0a,0x07,0x08,0x0a,0x0c, 0x0c,0x08,0x00,0x00,0x10,0x20,0x0a,0x00,0x02,0x04,0x05,0x06,0x09,0x09,0x0d,0x0d,0x04,0x05,0x05,0x07,0x0b,0x03,0x06,0x03,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x03,0x03,0x0b,0x0b,0x0b,0x07,0x0f,0x0a,0x09,0x0a,0x0b,0x08,0x08,0x0b,0x0b,0x04,0x06,0x09,0x08,0x0e,0x0c,0x0c,0x09,0x0c,0x0a,0x09,0x08,0x0b,0x0a, 0x0f,0x09,0x09,0x09,0x05,0x06,0x05,0x0b,0x07,0x04,0x08,0x09,0x07,0x09,0x08,0x05,0x09,0x09,0x04,0x04,0x08,0x04,0x0e,0x09,0x09,0x09,0x09,0x06,0x07,0x05,0x09,0x08,0x0c,0x07,0x08,0x07,0x05,0x04,0x05,0x0b,0x0a,0x0a,0x0a,0x08,0x0c,0x0c,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x09,0x09,0x07,0x07,0x07,0x09,0x06,0x0e,0x0e,0x0c,0x05,0x07,0x0b,0x0e,0x0c,0x0d,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x0a,0x0c,0x09,0x06,0x07,0x0c,0x0d,0x09,0x07,0x04,0x05,0x0b,0x0a,0x09,0x0b,0x0a,0x08,0x08,0x0c,0x0a,0x0a,0x0c,0x0f,0x0f,0x08,0x10,0x06,0x06,0x04,0x04,0x0b,0x09, 0x08,0x09,0x03,0x09,0x05,0x05,0x09,0x09,0x06,0x03,0x04,0x06,0x13,0x0a,0x08,0x0a,0x08,0x08,0x04,0x04,0x04,0x04,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x04,0x06,0x05,0x05,0x05,0x03,0x04,0x03,0x05,0x03,0x06,0x08,0x04,0x09,0x07,0x09,0x07,0x04,0x0b,0x09,0x09,0x08,0x09,0x09,0x0b,0x0b,0x06,0x06,0x06,0x0f,0x0f,0x0f,0x08,0x0b,0x09,0x04, 0x09,0x07,0x0a,0x07,0x0a,0x07,0x09,0x07,0x03,0x0a,0x08,0x0a,0x08,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x08,0x08,0x04,0x08,0x05,0x08,0x05,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0a,0x06,0x0a,0x06,0x09,0x07,0x08,0x05,0x08,0x07,0x0b,0x09,0x0b,0x09,0x09,0x07,0x09,0x07,0x08,0x0c,0x0c,0x0a,0x09,0x07,0x09,0x08,0x0b,0x07,0x08,0x06,0x12,0x0a, 0x08,0x0a,0x04,0x06,0x0d,0x05,0x0a,0x06,0x06,0x0a,0x06,0x0a,0x08,0x0a,0x07,0x0a,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x09,0x08,0x08,0x08,0x04,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0a,0x06,0x09,0x07,0x08,0x05,0x0b,0x09, 0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0f,0x0c,0x09,0x08,0x04,0x0a,0x08,0x0e,0x0d,0x0c,0x09,0x03,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x09,0x08,0x04,0x07,0x09,0x0a,0x0f,0x0f,0x0f,0x0e,0x06,0x06,0x03,0x04,0x04,0x0a,0x09,0x0c,0x06,0x0d,0x0b,0x0d,0x04,0x0a,0x09,0x08,0x09,0x0b,0x04,0x09,0x0a,0x0e,0x0c,0x08,0x0c,0x0b,0x09,0x08,0x08,0x09, 0x09,0x0c,0x0c,0x04,0x09,0x0a,0x07,0x09,0x04,0x09,0x09,0x08,0x07,0x09,0x09,0x04,0x08,0x08,0x09,0x08,0x07,0x09,0x09,0x07,0x09,0x09,0x0c,0x0d,0x04,0x09,0x09,0x09,0x0d,0x08,0x0b,0x08,0x0a,0x09,0x04,0x10,0x10,0x0c,0x09,0x09,0x0b,0x0a,0x09,0x09,0x08,0x0b,0x08,0x0e,0x09,0x0c,0x0c,0x09,0x0b,0x0e,0x0b,0x0c,0x0b,0x09,0x0a,0x08, 0x09,0x0c,0x09,0x0c,0x0b,0x0f,0x10,0x0b,0x0d,0x09,0x0a,0x10,0x09,0x08,0x09,0x08,0x06,0x09,0x08,0x0c,0x07,0x09,0x09,0x08,0x08,0x0b,0x09,0x09,0x09,0x09,0x07,0x07,0x08,0x0b,0x07,0x0a,0x09,0x0d,0x0d,0x09,0x0b,0x08,0x07,0x0d,0x08,0x08,0x09,0x06,0x07,0x07,0x04,0x0d,0x0d,0x09,0x08,0x08,0x09,0x08,0x06,0x10,0x12,0x0a,0x06,0x06, 0x06,0x06,0x04,0x09,0x07,0x09,0x0c,0x0a,0x0b,0x09,0x05,0x05,0x04,0x04,0x08,0x08,0x08,0x08,0x05,0x05,0x05,0x08,0x05,0x08,0x05,0x05,0x05,0x08,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x09,0x08,0x09,0x08,0x09,0x08,0x08,0x05,0x08,0x08,0x0c,0x09,0x04,0x06,0x04,0x04,0x08, 0x07,0x0f,0x0c,0x0a,0x08,0x09,0x08,0x0c,0x0a,0x09,0x08,0x09,0x08,0x0a,0x08,0x0a,0x09,0x0b,0x09,0x0c,0x08,0x0c,0x09,0x05,0x05,0x05,0x05,0x07,0x07,0x08,0x08,0x08,0x08,0x04,0x04,0x05,0x05,0x05,0x05,0x08,0x08,0x0a,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x07,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x08,0x08, 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x05,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x04,0x04,0x04,0x04,0x09,0x08,0x09,0x08,0x09,0x08,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x09,0x09,0x09, 0x09,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x08,0x05,0x08,0x05,0x08,0x05,0x08,0x05,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0a,0x08,0x0a,0x08,0x0f,0x0c,0x0f,0x0c,0x09,0x07,0x09,0x07,0x09,0x08,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x05,0x0c,0x08,0x08,0x04,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x09, 0x09,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x07,0x07,0x09,0x09,0x04,0x04,0x09,0x09,0x09,0x09,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0b,0x09,0x09,0x09,0x04, 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0a,0x09,0x09,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x0a,0x09,0x09,0x09,0x09,0x0a,0x0a,0x07,0x0b, 0x0c,0x09,0x09,0x09,0x08,0x09,0x08,0x0b,0x0a,0x0e,0x05,0x04,0x09,0x08,0x04,0x08,0x0e,0x0c,0x09,0x0c,0x10,0x0d,0x0a,0x09,0x09,0x09,0x07,0x08,0x05,0x05,0x08,0x05,0x08,0x0c,0x0b,0x09,0x08,0x09,0x07,0x0a,0x0a,0x07,0x07,0x09,0x09,0x06,0x06,0x09,0x04,0x06,0x07,0x05,0x14,0x12,0x10,0x0e,0x0c,0x08,0x11,0x0f,0x0d,0x0a,0x08,0x04, 0x04,0x0c,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x08,0x0a,0x08,0x0a,0x08,0x0e,0x0d,0x0b,0x09,0x0b,0x09,0x09,0x08,0x0c,0x09,0x0c,0x09,0x0a,0x07,0x04,0x14,0x12,0x10,0x0b,0x09,0x10,0x0b,0x0c,0x09,0x0a,0x08,0x0a,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x04,0x04,0x0c,0x09,0x0c,0x09,0x09,0x06,0x0a,0x06,0x0b,0x09, 0x0b,0x09,0x08,0x07,0x0b,0x09,0x0c,0x09,0x09,0x09,0x07,0x0a,0x08,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x09,0x08,0x09,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x07,0x07,0x09,0x09,0x08,0x0a,0x07,0x07,0x08,0x09,0x04,0x09,0x09,0x08,0x08,0x07,0x09,0x09,0x09,0x04,0x04,0x05,0x04,0x06,0x04,0x0a,0x0e,0x0e,0x0e,0x09,0x09,0x09, 0x09,0x0b,0x0c,0x0a,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x07,0x07,0x06,0x04,0x04,0x05,0x05,0x05,0x05,0x0a,0x0a,0x09,0x08,0x0c,0x08,0x07,0x07,0x08,0x07,0x07,0x06,0x06,0x06,0x07,0x0a,0x08,0x09,0x08,0x09,0x04,0x08,0x06,0x09,0x06,0x06,0x0f,0x0f,0x10,0x0a,0x08,0x0b,0x0d,0x09,0x09,0x08,0x08,0x09,0x09,0x09,0x0b,0x09,0x0a,0x0d, 0x09,0x0b,0x09,0x09,0x07,0x08,0x07,0x0a,0x08,0x0a,0x08,0x0e,0x0e,0x0a,0x08,0x0a,0x09,0x0a,0x07,0x0a,0x08,0x0b,0x09,0x09,0x07,0x09,0x09,0x07,0x04,0x0c,0x07,0x07,0x0e,0x0b,0x0a,0x09,0x0f,0x0b,0x0b,0x08,0x0e,0x0b,0x0c,0x09,0x0f,0x0c,0x09,0x07,0x0d,0x0c,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x15,0x12,0x0d,0x0a,0x12,0x0e,0x0e,0x0b, 0x09,0x07,0x08,0x06,0x07,0x00,0x00,0x10,0x0f,0x09,0x08,0x09,0x09,0x09,0x08,0x09,0x07,0x09,0x08,0x0b,0x09,0x0d,0x0b,0x10,0x0d,0x0c,0x09,0x0a,0x07,0x08,0x07,0x0e,0x0b,0x0b,0x09,0x0d,0x0a,0x0d,0x0a,0x04,0x0e,0x0c,0x09,0x08,0x0b,0x09,0x0a,0x09,0x0a,0x08,0x0a,0x08,0x0e,0x0d,0x08,0x08,0x0c,0x08,0x0c,0x08,0x0e,0x0c,0x09,0x07, 0x08,0x07,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0c,0x09,0x0a,0x07,0x09,0x08,0x09,0x08,0x09,0x08,0x0b,0x09,0x0d,0x0b,0x09,0x09,0x0e,0x0e,0x0d,0x0c,0x09,0x08,0x0e,0x0d,0x10,0x0e,0x0b,0x08,0x0b,0x0a,0x09,0x09,0x09,0x08,0x09,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x09,0x05,0x05,0x03,0x03, 0x03,0x03,0x04,0x06,0x04,0x04,0x06,0x04,0x04,0x04,0x05,0x05,0x03,0x03,0x09,0x09,0x09,0x09,0x05,0x05,0x04,0x05,0x05,0x04,0x05,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x03,0x04,0x05,0x03,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x07,0x05,0x04,0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09, 0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x00, 0x00,0x00,0x00,0x00,0x0a,0x05,0x0a,0x05,0x09,0x09,0x05,0x05,0x05,0x05,0x05,0x04,0x05,0x05,0x05,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x0b,0x0d,0x08,0x07,0x09,0x09,0x07,0x07,0x04,0x05,0x08,0x06,0x0b,0x09,0x09,0x08,0x0a,0x0a,0x0a,0x0f,0x09,0x0a,0x0a, 0x07,0x07,0x07,0x07,0x09,0x09,0x0b,0x09,0x08,0x0c,0x07,0x07,0x07,0x08,0x06,0x08,0x09,0x07,0x09,0x09,0x06,0x08,0x06,0x06,0x07,0x05,0x05,0x07,0x07,0x03,0x04,0x06,0x05,0x08,0x07,0x07,0x07,0x06,0x05,0x06,0x05,0x07,0x08,0x05,0x05,0x06,0x08,0x06,0x06,0x05,0x05,0x04,0x04,0x06,0x03,0x05,0x08,0x05,0x05,0x04,0x05,0x05,0x05,0x03, 0x05,0x05,0x08,0x05,0x05,0x05,0x05,0x05,0x07,0x05,0x03,0x03,0x05,0x05,0x05,0x05,0x06,0x07,0x05,0x09,0x03,0x06,0x09,0x0e,0x0a,0x09,0x09,0x0e,0x0a,0x0e,0x0c,0x08,0x09,0x08,0x07,0x12,0x07,0x09,0x0e,0x0f,0x0f,0x0a,0x0a,0x0a,0x07,0x08,0x08,0x07,0x07,0x08,0x03,0x00,0x00,0x00,0x00,0x09,0x0a,0x0a,0x0a,0x08,0x06,0x09,0x09,0x05, 0x0e,0x09,0x09,0x06,0x05,0x07,0x05,0x07,0x09,0x07,0x09,0x0e,0x0a,0x05,0x04,0x09,0x09,0x0a,0x09,0x09,0x05,0x09,0x08,0x04,0x0e,0x09,0x09,0x06,0x07,0x07,0x08,0x07,0x07,0x08,0x09,0x09,0x08,0x07,0x07,0x0c,0x04,0x07,0x04,0x09,0x07,0x06,0x04,0x04,0x05,0x04,0x03,0x03,0x06,0x05,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x08,0x08, 0x05,0x05,0x06,0x05,0x06,0x04,0x03,0x03,0x05,0x05,0x05,0x05,0x05,0x04,0x04,0x05,0x04,0x05,0x00,0x00,0x00,0x00,0x03,0x05,0x05,0x05,0x04,0x05,0x09,0x09,0x09,0x09,0x05,0x00,0x00,0x00,0x00,0x07,0x05,0x04,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x04,0x04,0x04,0x04,0x09,0x09,0x09,0x09,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x0d,0x0a,0x0b,0x09,0x0c,0x0a, 0x0f,0x0c,0x09,0x06,0x08,0x0b,0x09,0x0d,0x0b,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x0d,0x0d,0x10,0x07,0x04,0x08,0x09,0x07,0x08,0x08,0x09,0x09,0x08,0x10,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x0a,0x08,0x08,0x08,0x05,0x09,0x05,0x0c,0x0b,0x08,0x05,0x0d,0x08,0x0d,0x04,0x05, 0x09,0x09,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x0d,0x04,0x09,0x04,0x08,0x07,0x04,0x04,0x08,0x04,0x0c,0x04,0x0f,0x08,0x0f,0x0f,0x09,0x09,0x09,0x08,0x08,0x07,0x07,0x13,0x13,0x15,0x15,0x0d,0x0d,0x08,0x08,0x03,0x10,0x0c,0x0d,0x0b,0x09,0x0b,0x08,0x08,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x04,0x0a,0x00,0x0a,0x0a, 0x0a,0x05,0x08,0x08,0x0f,0x05,0x0f,0x05,0x09,0x0b,0x09,0x07,0x0f,0x08,0x0f,0x08,0x0c,0x0d,0x05,0x08,0x08,0x07,0x04,0x08,0x09,0x08,0x09,0x08,0x09,0x09,0x08,0x0b,0x0a,0x0f,0x05,0x08,0x07,0x0b,0x08,0x05,0x08,0x08,0x08,0x0f,0x05,0x0f,0x05,0x04,0x09,0x06,0x10,0x08,0x08,0x0a,0x0a,0x10,0x08,0x00,0x00,0x00,0x0a,0x00,0x0a,0x0a, 0x0a,0x0a,0x0c,0x0a,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x07,0x08,0x08,0x0c,0x0d,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x13, 0x0d,0x13,0x0d,0x13,0x0d,0x15,0x10,0x15,0x10,0x0d,0x08,0x09,0x09,0x09,0x10,0x10,0x08,0x08,0x10,0x08,0x08,0x10,0x08,0x08,0x10,0x08,0x08,0x0c,0x0c,0x11,0x10,0x0f,0x08,0x0d,0x08,0x0d,0x08,0x0d,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0b,0x05,0x0b,0x05,0x0b,0x05,0x0b,0x05,0x0b,0x05,0x0b,0x0b,0x05,0x0b,0x05, 0x09,0x0b,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0f,0x0c,0x0d,0x05,0x08,0x0c,0x0d,0x0c,0x0d,0x00,0x00,0x00,0x00,0x00,0x12,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x00,0x00,0x0a,0x00,0x00,0x00,0x13,0x0d,0x15,0x10,0x08,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x08,0x0f,0x0f,0x06,0x09,0x09,0x0a,0x14,0x0d,0x09,0x18,0x11,0x05,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x07,0x07,0x0c,0x0b,0x0b,0x08,0x00,0x00,0x00,0x05,0x05,0x05,0x05,0x14,0x18,0x00,0x00,0x00,0x00,0x00,0x09,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x07,0x0f,0x05,0x0f,0x05,0x0f,0x05, 0x0f,0x05,0x0f,0x05,0x0f,0x05,0x09,0x09,0x09,0x09,0x0b,0x09,0x08,0x08,0x07,0x13,0x0d,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x10,0x08,0x08,0x10,0x08,0x08,0x0f,0x08,0x08,0x0f,0x08,0x08,0x0f,0x08,0x08,0x09,0x09,0x09,0x09,0x0b,0x05,0x0b,0x05,0x0b,0x05,0x0b,0x0b,0x05,0x05,0x07,0x07,0x13,0x0d,0x0a,0x09, 0x09,0x00,0x08,0x08,0x08,0x06,0x09,0x0b,0x0a,0x08,0x08,0x06,0x04,0x0c,0x09,0x0a,0x06,0x09,0x08,0x08,0x07,0x08,0x04,0x08,0x07,0x0a,0x08,0x09,0x07,0x09,0x07,0x0b,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x07,0x08,0x08,0x05,0x08,0x09,0x0a,0x08,0x05,0x0c,0x09,0x0a,0x09,0x0a,0x08,0x09,0x08,0x06,0x0b,0x06,0x07, 0x07,0x08,0x0a,0x0a,0x08,0x10,0x08,0x10,0x05,0x04,0x03,0x09,0x03,0x02,0x00,0x02,0x04,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x0f,0x07,0x0c,0x09,0x0f,0x0c,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0e,0x08,0x0e,0x08,0x0e,0x0a,0x0b,0x0b,0x0b,0x0c,0x0e,0x10,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0b,0x0c,0x09,0x11,0x0d,0x08,0x08,0x05,0x05,0x05,0x06,0x03,0x09,0x04,0x04,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x0a,0x09,0x07,0x08,0x0b,0x04,0x05,0x0b,0x0b,0x04,0x09,0x09,0x09,0x0b,0x0b,0x04,0x06,0x0b, 0x0a,0x0a,0x0a,0x09,0x09,0x0b,0x09,0x0d,0x0c,0x08,0x08,0x08,0x04,0x06,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x08,0x0b,0x09,0x09,0x0b,0x09,0x0c,0x09,0x0d,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x09,0x07,0x08,0x0b,0x05,0x06,0x0b,0x05,0x09,0x09,0x09,0x0b,0x06,0x0b,0x0a,0x0a,0x09,0x0b,0x09,0x0d,0x0c,0x04,0x09,0x09,0x0a,0x0a,0x13,0x00, 0x0a,0x09,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x00,0x0c,0x0a,0x0b,0x0b,0x09,0x0b,0x0c,0x0c,0x08,0x0a,0x0c,0x0c,0x0b,0x0c,0x0d,0x0c,0x0b,0x09,0x09,0x0c,0x0b,0x09,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0c,0x09,0x0a,0x0b,0x0a,0x0c,0x0a,0x0a,0x0a,0x0b,0x0d,0x08,0x09,0x09,0x0e,0x09,0x09,0x0c,0x0e,0x0a,0x09,0x11,0x09,0x09,0x0c,0x09,0x09,0x0c,0x09,0x0c,0x0d,0x0e,0x09,0x0c,0x09,0x0a,0x09,0x0a,0x09,0x0a,0x09,0x0a,0x0c,0x09,0x0a,0x0b,0x09,0x09,0x0a,0x0f,0x09,0x09,0x09,0x09,0x07,0x05,0x09,0x09,0x09,0x09,0x09, 0x0e,0x09,0x0e,0x08,0x09,0x0e,0x0b,0x09,0x0e,0x0c,0x0c,0x0e,0x09,0x09,0x0e,0x0e,0x09,0x09,0x09,0x09,0x09,0x09,0x0e,0x0e,0x09,0x09,0x09,0x0e,0x0a,0x09,0x09,0x09,0x0e,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0b,0x0d,0x0b,0x0a,0x09,0x0d,0x0b,0x0b,0x09,0x0b,0x0b,0x0c,0x0c,0x09,0x0b,0x0b,0x0c,0x0b,0x0c,0x0b,0x0c,0x0c,0x0b,0x0a, 0x0b,0x0b,0x0c,0x0d,0x0b,0x0c,0x0c,0x02,0x02,0x02,0x03,0x02,0x04,0x06,0x0e,0x09,0x0a,0x0a,0x09,0x0a,0x09,0x09,0x0a,0x0a,0x09,0x05,0x0d,0x09,0x09,0x09,0x09,0x0a,0x08,0x09,0x04,0x09,0x08,0x09,0x07,0x0e,0x09,0x09,0x09,0x09,0x0d,0x09,0x09,0x06,0x0d,0x09,0x09,0x0b,0x0b,0x03,0x05,0x12,0x12,0x12,0x12,0x17,0x09,0x09,0x04,0x09, 0x06,0x09,0x09,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x09,0x09,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x09,0x07,0x07,0x09,0x0a,0x04,0x05,0x08,0x07,0x0c,0x0a,0x0a, 0x08,0x0a,0x08,0x07,0x07,0x0a,0x08,0x0d,0x08,0x07,0x08,0x0b,0x0c,0x07,0x0a,0x08,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x04,0x04,0x04,0x04,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x08,0x0a,0x0a,0x04,0x04, 0x04,0x04,0x04,0x09,0x05,0x08,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0d,0x0d,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x0b,0x0a,0x08,0x08,0x06,0x09,0x07,0x08,0x0a,0x0a,0x04,0x08,0x08,0x0c,0x0a,0x07,0x0a,0x0a,0x08, 0x07,0x07,0x07,0x0a,0x08,0x0b,0x0a,0x08,0x07,0x0a,0x04,0x0a,0x07,0x0a,0x04,0x07,0x07,0x09,0x06,0x08,0x07,0x04,0x04,0x05,0x0d,0x0d,0x0a,0x08,0x08,0x0a,0x08,0x08,0x08,0x06,0x09,0x07,0x0c,0x07,0x0a,0x0a,0x08,0x09,0x0c,0x0a,0x0a,0x0a,0x08,0x08,0x07,0x08,0x0a,0x08,0x0a,0x09,0x0d,0x0d,0x09,0x0b,0x08,0x08,0x0e,0x08,0x06,0x09, 0x09,0x0a,0x0e,0x0e,0x0b,0x08,0x09,0x07,0x09,0x09,0x09,0x0b,0x08,0x08,0x0b,0x09,0x09,0x06,0x0a,0x0a,0x09,0x08,0x08,0x0e,0x0c,0x08,0x09,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x06,0x0f,0x09,0x09,0x09,0x0a,0x0a,0x08,0x08,0x04,0x0c,0x0b,0x0b,0x08,0x0b,0x03,0x03,0x07,0x07,0x03,0x03,0x0a,0x06,0x04,0x0c,0x0b,0x05,0x03,0x03,0x07,0x06, 0x06,0x04,0x04,0x04,0x06,0x0b,0x08,0x05,0x0a,0x0b,0x09,0x09,0x08,0x0c,0x09,0x0a,0x06,0x07,0x09,0x07,0x03,0x04,0x06,0x08,0x05,0x0b,0x0b,0x0b,0x0f,0x0c,0x0f,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x0c,0x0d,0x05,0x05,0x08,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x09,0x09,0x09,0x08,0x08,0x13,0x0d,0x13,0x0d,0x15,0x10,0x15,0x10,0x0d, 0x0d,0x0d,0x0d,0x0d,0x0d,0x0f,0x0f,0x08,0x08,0x0f,0x0f,0x08,0x08,0x0c,0x0d,0x05,0x05,0x0c,0x0d,0x05,0x05,0x0c,0x0d,0x05,0x05,0x10,0x0c,0x0d,0x08,0x09,0x09,0x0b,0x05,0x0b,0x0c,0x08,0x08,0x05,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0f,0x05,0x0c,0x08,0x08,0x04,0x08,0x08,0x08,0x08,0x0f,0x05, 0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x13,0x0d,0x13,0x0d,0x13,0x0d,0x15,0x10,0x15,0x10,0x0d,0x0d,0x0d,0x10,0x10,0x10,0x10,0x10,0x10,0x0c,0x08,0x08,0x0c,0x08,0x08,0x0f,0x08,0x11,0x10,0x0f,0x08,0x0d,0x08,0x0d, 0x08,0x0d,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x05,0x0b,0x0b,0x05,0x05,0x0b,0x05,0x0b,0x05,0x0b,0x08,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x05,0x05,0x08,0x05,0x05,0x05,0x05,0x00,0x13,0x0d,0x15,0x10,0x0f,0x08,0x0f,0x05,0x0f,0x05,0x0f,0x05,0x0f,0x05, 0x0f,0x05,0x0f,0x05,0x09,0x09,0x08,0x08,0x07,0x13,0x0d,0x10,0x10,0x0f,0x0f,0x0f,0x09,0x09,0x09,0x09,0x0b,0x05,0x0b,0x05,0x0b,0x05,0x13,0x0d,0x09,0x0b,0x09,0x09,0x09,0x0b,0x09,0x09,0x13,0x13,0x0d,0x0d,0x07,0x07,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x0c,0x0d,0x05,0x05,0x0c,0x0d,0x05,0x05,0x0c,0x0d,0x05,0x05,0x09,0x09, 0x09,0x09,0x0f,0x05,0x0f,0x05,0x09,0x0b,0x09,0x09,0x13,0x13,0x0d,0x0d,0x13,0x13,0x0d,0x0d,0x0d,0x0d,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x05,0x04,0x00,0x00,0x00,0x0d,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x0d,0x09,0x0d,0x09, 0x0d,0x09,0x0d,0x0b,0x0b,0x0b,0x04,0x04,0x08,0x07,0x09,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x07,0x09,0x08,0x09,0x0a,0x0a,0x0b,0x09,0x09,0x0a,0x08,0x0b,0x0c,0x0a,0x0c,0x0d,0x0a,0x0c,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x07,0x09,0x0a,0x0a,0x0b, 0x09,0x0a,0x09,0x0a,0x0a,0x08,0x08,0x0c,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0b,0x0f,0x0f,0x0c,0x0e,0x0e,0x09,0x0c,0x0e,0x0c,0x0a,0x0e,0x0c,0x0b,0x0b,0x0a,0x0a,0x0c,0x0d,0x0b,0x0a,0x0b,0x09,0x09,0x0f,0x0f,0x0f,0x0d,0x0f,0x0f,0x0b,0x0f,0x0f,0x0b,0x0c,0x0d,0x0c,0x0c,0x0c,0x0a,0x0e,0x0c,0x0d, 0x0b,0x0b,0x09,0x0c,0x0b,0x0b,0x0e,0x0c,0x0c,0x0e,0x09,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x09,0x0a,0x0a,0x0a,0x07,0x09,0x09,0x09,0x0a,0x0c,0x0d,0x0a,0x0a,0x0a,0x0c,0x0a,0x0b,0x08,0x08,0x09,0x09,0x08,0x08,0x09,0x09,0x08,0x07,0x0a,0x07,0x09,0x08, 0x09,0x0d,0x09,0x0d,0x09,0x09,0x09,0x0c,0x05,0x0d,0x0b,0x0b,0x0b,0x09,0x0c,0x0a,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x0a,0x0a,0x0a,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x0a,0x04,0x04,0x04,0x05,0x05,0x04,0x04,0x04,0x05,0x04,0x04,0x04,0x0e, 0x0e,0x0e,0x0e,0x08,0x0c,0x0c,0x08,0x07,0x08,0x08,0x09,0x08,0x0e,0x0d,0x0e,0x07,0x10,0x08,0x0d,0x0d,0x0d,0x0d,0x09,0x08,0x08,0x0c,0x09,0x0c,0x0b,0x09,0x07,0x07,0x10,0x07,0x09,0x08,0x08,0x08,0x08,0x08,0x16,0x0d,0x0d,0x07,0x04,0x07,0x04,0x07,0x04,0x04,0x04,0x08,0x09,0x09,0x09,0x06,0x06,0x04,0x04,0x04,0x06,0x04,0x07,0x0e, 0x03,0x0e,0x0e,0x0e,0x09,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x13,0x13,0x0b,0x13,0x13,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x08,0x09,0x08,0x09,0x07,0x06,0x06,0x0b,0x09, 0x0b,0x07,0x12,0x0e,0x09,0x09,0x0f,0x0d,0x0e,0x0c,0x10,0x0d,0x0f,0x0c,0x0a,0x08,0x0c,0x09,0x0f,0x0c,0x0c,0x0a,0x0c,0x0a,0x0e,0x0b,0x0e,0x0b,0x12,0x0d,0x0c,0x09,0x0c,0x09,0x13,0x0e,0x0d,0x00,0x10,0x10,0x10,0x08,0x00,0x00,0x09,0x08,0x0b,0x09,0x09,0x07,0x11,0x0e,0x0f,0x0e,0x0b,0x09,0x0b,0x09,0x08,0x07,0x0c,0x0a,0x08,0x07, 0x0d,0x0b,0x0b,0x09,0x10,0x0d,0x09,0x09,0x0c,0x0c,0x0d,0x07,0x03,0x07,0x0b,0x07,0x10,0x10,0x04,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x06,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x0b,0x0c,0x04,0x03,0x04,0x03,0x0b,0x09,0x0c,0x0a,0x09,0x08,0x09,0x08,0x09,0x09,0x07,0x07,0x12,0x0d,0x12,0x0e,0x10,0x0e,0x0e, 0x0b,0x0e,0x0b,0x0e,0x0b,0x0a,0x07,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x05,0x08,0x04,0x0c,0x09,0x0e,0x0b,0x15,0x10,0x09,0x09,0x0b,0x0b,0x0d,0x0e,0x0c,0x09,0x10,0x0d,0x09,0x06,0x09,0x08,0x0a,0x08,0x0f,0x0c,0x0a,0x08,0x09,0x09,0x09,0x09,0x08,0x06,0x08,0x06,0x08,0x06,0x08,0x08,0x05,0x0b,0x05,0x0f,0x0b,0x06,0x09,0x0a,0x07, 0x0c,0x09,0x06,0x06,0x09,0x09,0x09,0x08,0x04,0x0c,0x0a,0x06,0x06,0x0a,0x07,0x0b,0x06,0x0c,0x0a,0x0a,0x07,0x0b,0x09,0x09,0x08,0x0c,0x09,0x0a,0x06,0x09,0x07,0x0c,0x07,0x08,0x0e,0x08,0x09,0x0e,0x04,0x12,0x0e,0x0e,0x13,0x0e,0x0f,0x0f,0x0e,0x0e,0x0f,0x08,0x08,0x0a,0x0b,0x0e,0x0b,0x0f,0x04,0x07,0x09,0x0e,0x10,0x0b,0x10,0x0a, 0x0a,0x0d,0x0b,0x12,0x0f,0x08,0x0f,0x05,0x0f,0x05,0x09,0x09,0x09,0x09,0x0d,0x0d,0x0d,0x0d,0x10,0x08,0x08,0x10,0x0c,0x08,0x08,0x0c,0x0b,0x05,0x05,0x0b,0x09,0x09,0x09,0x09,0x0c,0x05,0x05,0x0d,0x0c,0x05,0x05,0x0d,0x07,0x07,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x08,0x06,0x09,0x08,0x0c,0x09,0x09,0x0e,0x0b,0x0c,0x0c,0x0d,0x0d,0x09,0x08,0x10,0x0d,0x11,0x0e,0x0b,0x09,0x05,0x05,0x09,0x0a,0x07,0x0a,0x08,0x09,0x08,0x0c,0x0d,0x06,0x09,0x07,0x03,0x06,0x09,0x09,0x03,0x03,0x03,0x03,0x06,0x06,0x06,0x07,0x18,0x20,0x05,0x07,0x02, 0x04,0x06,0x07,0x05,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x08,0x08,0x15,0x09,0x0c,0x0f,0x0e,0x0a,0x07,0x09,0x0c,0x0c,0x08,0x05,0x0b,0x08,0x0b,0x09,0x0b,0x09,0x09,0x0c,0x09,0x09,0x08,0x0c,0x0a,0x0d,0x07,0x08,0x0a,0x05,0x09,0x05,0x06,0x04,0x0e,0x09,0x09,0x08,0x08,0x09,0x0f,0x0f,0x0f, 0x10,0x10,0x09,0x08,0x05,0x08,0x07,0x0a,0x07,0x0b,0x04,0x09,0x0a,0x0e,0x0e,0x0a,0x09,0x09,0x09,0x08,0x07,0x08,0x07,0x08,0x05,0x05,0x04,0x04,0x06,0x09,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x05,0x05,0x05,0x04,0x04,0x1b,0x10,0x0e,0x11,0x05,0x05,0x05,0x06,0x04,0x04,0x05, 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x0f,0x05,0x05,0x0f,0x04,0x08,0x08,0x15,0x10,0x10,0x15,0x0f,0x08,0x08,0x0f,0x08,0x08,0x07,0x07,0x00,0x00,0x06,0x0c,0x0a,0x0b,0x09,0x14,0x11,0x0b,0x09,0x0b,0x09,0x15,0x10,0x0c,0x09,0x06,0x05,0x0a,0x00,0x0b,0x09,0x05,0x05,0x03,0x08,0x05,0x05,0x04,0x03,0x07,0x06,0x06,0x06, 0x06,0x06,0x06,0x06,0x06,0x03,0x08,0x07,0x09,0x09,0x09,0x0f,0x0d,0x0d,0x0d,0x0d,0x0f,0x0a,0x0b,0x0a,0x06,0x0f,0x12,0x07,0x12,0x08,0x0d,0x0f,0x0f,0x0f,0x07,0x0c,0x10,0x0c,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x09,0x09,0x0d,0x08,0x08,0x0f,0x05,0x05,0x0f,0x05,0x05,0x0f, 0x08,0x08,0x00,0x07,0x0d,0x05,0x05,0x10,0x08,0x08,0x0c,0x08,0x08,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x18,0x18,0x0e,0x00,0x00,0x0e,0x0e,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0a,0x0a,0x0a,0x0e,0x0a,0x0a,0x0d,0x10,0x0a,0x0a,0x11, 0x0a,0x0a,0x0f,0x0a,0x0b,0x0d,0x0a,0x0c,0x0e,0x0f,0x0a,0x0c,0x0a,0x0b,0x0a,0x0b,0x0a,0x0b,0x0b,0x0a,0x0c,0x0a,0x0b,0x0d,0x0a,0x0a,0x09,0x0d,0x0a,0x0a,0x0a,0x0b,0x07,0x08,0x0a,0x0d,0x0c,0x09,0x00,0x00,0x11,0x22,0x0b,0x00,0x02,0x05,0x05,0x07,0x0a,0x09,0x0e,0x0e,0x04,0x05,0x05,0x07,0x0c,0x04,0x07,0x04,0x07,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x04,0x04,0x0c,0x0c,0x0c,0x08,0x10,0x0b,0x0a,0x0b,0x0c,0x09,0x08,0x0c,0x0c,0x05,0x06,0x0a,0x08,0x0f,0x0d,0x0d,0x0a,0x0d,0x0a,0x09,0x09,0x0c,0x0b,0x10,0x0a,0x09,0x0a,0x05,0x06,0x05,0x0c,0x07,0x05,0x09,0x0a,0x08,0x0a,0x09,0x05,0x0a,0x0a,0x04,0x04,0x08,0x04,0x0f,0x0a,0x0a,0x0a,0x0a,0x06, 0x07,0x06,0x0a,0x08,0x0c,0x08,0x08,0x08,0x05,0x04,0x05,0x0c,0x0b,0x0b,0x0b,0x09,0x0d,0x0d,0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x09,0x04,0x04,0x04,0x04,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x09,0x09,0x08,0x07,0x08,0x09,0x07,0x0f,0x0f,0x0d,0x05,0x07,0x0c,0x0f,0x0d,0x0e,0x0c,0x0c, 0x0c,0x09,0x0a,0x09,0x0a,0x0d,0x09,0x07,0x07,0x0d,0x0e,0x0a,0x08,0x05,0x05,0x0c,0x0b,0x09,0x0c,0x0b,0x09,0x09,0x0c,0x0b,0x0b,0x0d,0x10,0x10,0x09,0x11,0x06,0x06,0x04,0x04,0x0c,0x0a,0x08,0x09,0x03,0x09,0x05,0x05,0x09,0x09,0x06,0x04,0x04,0x06,0x15,0x0b,0x09,0x0b,0x09,0x09,0x05,0x05,0x05,0x05,0x0d,0x0d,0x0d,0x0c,0x0c,0x0c, 0x04,0x06,0x06,0x05,0x05,0x03,0x05,0x03,0x06,0x03,0x06,0x08,0x05,0x09,0x07,0x0a,0x08,0x04,0x0c,0x0a,0x09,0x08,0x0a,0x0a,0x0c,0x0c,0x06,0x06,0x06,0x10,0x0f,0x10,0x08,0x0c,0x0a,0x05,0x09,0x07,0x0b,0x08,0x0b,0x08,0x0a,0x07,0x04,0x0b,0x09,0x0b,0x09,0x0c,0x0b,0x0c,0x09,0x09,0x09,0x09,0x08,0x04,0x08,0x05,0x08,0x05,0x0d,0x0a, 0x0d,0x0a,0x0d,0x0a,0x0a,0x06,0x0a,0x06,0x09,0x07,0x09,0x06,0x09,0x07,0x0c,0x0a,0x0c,0x0a,0x0a,0x08,0x0a,0x08,0x08,0x0d,0x0d,0x0a,0x0a,0x07,0x0a,0x08,0x0c,0x07,0x08,0x07,0x13,0x0b,0x08,0x0a,0x04,0x06,0x0e,0x06,0x0a,0x06,0x06,0x0a,0x06,0x0b,0x09,0x0b,0x08,0x0b,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0a,0x0c,0x0a,0x0c, 0x0a,0x0c,0x0a,0x0c,0x0a,0x05,0x04,0x05,0x04,0x05,0x04,0x05,0x04,0x06,0x04,0x0a,0x08,0x08,0x08,0x04,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0a,0x06,0x09,0x07,0x09,0x06,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x10,0x0c,0x09,0x08,0x04,0x0b,0x09,0x0f,0x0e,0x0d,0x0a,0x04,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x09,0x08,0x04,0x07, 0x09,0x0a,0x10,0x10,0x10,0x0f,0x07,0x07,0x04,0x05,0x05,0x0b,0x0a,0x0d,0x06,0x0e,0x0b,0x0e,0x05,0x0b,0x0a,0x09,0x0a,0x0c,0x05,0x0a,0x0b,0x0f,0x0d,0x09,0x0d,0x0c,0x0a,0x09,0x09,0x09,0x0a,0x0d,0x0d,0x05,0x09,0x0a,0x07,0x0a,0x05,0x09,0x09,0x09,0x08,0x0a,0x0a,0x05,0x09,0x08,0x0a,0x09,0x08,0x0a,0x0a,0x08,0x09,0x09,0x0d,0x0e, 0x05,0x09,0x0a,0x09,0x0e,0x09,0x0c,0x08,0x0b,0x09,0x05,0x11,0x11,0x0c,0x0a,0x0a,0x0c,0x0b,0x0a,0x0a,0x08,0x0c,0x09,0x0f,0x09,0x0d,0x0d,0x0a,0x0b,0x0f,0x0c,0x0d,0x0c,0x0a,0x0b,0x09,0x0a,0x0c,0x0a,0x0d,0x0b,0x10,0x11,0x0c,0x0d,0x0a,0x0a,0x11,0x0a,0x09,0x0a,0x09,0x07,0x09,0x09,0x0d,0x08,0x0a,0x0a,0x08,0x09,0x0c,0x0a,0x0a, 0x0a,0x0a,0x08,0x07,0x08,0x0c,0x08,0x0a,0x0a,0x0e,0x0e,0x0a,0x0c,0x09,0x08,0x0e,0x09,0x09,0x0a,0x07,0x08,0x07,0x04,0x0d,0x0e,0x0a,0x08,0x08,0x0a,0x08,0x07,0x11,0x13,0x0b,0x06,0x06,0x06,0x06,0x04,0x09,0x07,0x09,0x0d,0x0a,0x0c,0x0a,0x05,0x06,0x05,0x05,0x08,0x08,0x08,0x08,0x05,0x05,0x05,0x08,0x05,0x08,0x05,0x05,0x05,0x08, 0x08,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x05,0x04,0x05,0x04,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d, 0x0a,0x0d,0x0a,0x0d,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x06,0x09,0x09,0x0d,0x0a,0x05,0x06,0x04,0x04,0x09,0x07,0x0f,0x0d,0x0a,0x09,0x0a,0x08,0x0d,0x0a,0x09,0x08,0x09,0x08,0x0b,0x08,0x0b,0x0a,0x0b,0x0a,0x0c,0x09,0x0d,0x0a,0x05,0x05,0x05,0x05,0x07, 0x07,0x08,0x08,0x08,0x08,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x09,0x0b,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x08,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x08,0x05,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x05,0x04,0x05,0x04,0x0a,0x08,0x0a, 0x08,0x0a,0x08,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x07,0x09,0x06,0x09,0x06,0x09,0x06,0x09,0x06,0x0c, 0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0b,0x08,0x0b,0x08,0x10,0x0c,0x10,0x0c,0x0a,0x08,0x0a,0x08,0x09,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x06,0x0c,0x08,0x09,0x04,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x10,0x10,0x10,0x10,0x10,0x10,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x08,0x08,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x10,0x10,0x10,0x10,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x10,0x10,0x10,0x10,0x10,0x10,0x0a,0x0a,0x07,0x07,0x0a,0x0a,0x05,0x05,0x0a,0x0a,0x09,0x09,0x0e,0x0e,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x10, 0x10,0x10,0x10,0x10,0x10,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0c,0x0a,0x0a,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x0a,0x0a,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0d,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x08,0x0c,0x0d,0x0a,0x0a,0x0a,0x09,0x09,0x08,0x0c,0x0b,0x0f,0x05,0x05,0x0a,0x08,0x04,0x08,0x0f,0x0d,0x0a,0x0d,0x10,0x0d,0x0a,0x0a,0x0a,0x09,0x07,0x09, 0x05,0x06,0x09,0x06,0x09,0x0d,0x0c,0x0a,0x09,0x0a,0x08,0x0a,0x0a,0x08,0x07,0x09,0x09,0x06,0x07,0x09,0x04,0x07,0x08,0x05,0x15,0x13,0x11,0x0f,0x0c,0x09,0x12,0x10,0x0e,0x0b,0x09,0x05,0x04,0x0d,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x09,0x0b,0x09,0x0b,0x09,0x0f,0x0e,0x0c,0x0a,0x0c,0x0a,0x0a,0x08,0x0d,0x0a, 0x0d,0x0a,0x0a,0x08,0x04,0x15,0x13,0x11,0x0c,0x0a,0x11,0x0c,0x0d,0x0a,0x0b,0x09,0x0b,0x09,0x09,0x09,0x09,0x09,0x05,0x04,0x05,0x04,0x0d,0x0a,0x0d,0x0a,0x0a,0x06,0x0a,0x06,0x0c,0x0a,0x0c,0x0a,0x09,0x07,0x0c,0x0a,0x0c,0x0a,0x0a,0x0a,0x08,0x0b,0x09,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x09,0x08,0x0a,0x09,0x0a,0x0a,0x0a, 0x09,0x0a,0x0a,0x0a,0x08,0x08,0x0a,0x0a,0x09,0x0a,0x07,0x07,0x09,0x09,0x05,0x0a,0x0a,0x09,0x08,0x08,0x0a,0x0a,0x0a,0x04,0x05,0x05,0x05,0x06,0x04,0x0a,0x0f,0x0f,0x0f,0x09,0x09,0x0a,0x0a,0x0c,0x0c,0x0b,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x07,0x04,0x04,0x05,0x05,0x06,0x06,0x0a,0x0a,0x09,0x08,0x0c,0x08,0x07,0x08, 0x09,0x08,0x08,0x06,0x06,0x06,0x08,0x0b,0x08,0x09,0x09,0x0a,0x04,0x08,0x07,0x0a,0x06,0x06,0x10,0x10,0x11,0x0a,0x08,0x0c,0x0d,0x0a,0x0a,0x08,0x08,0x09,0x0a,0x0a,0x0c,0x0a,0x0b,0x0e,0x0a,0x0c,0x0a,0x0a,0x08,0x08,0x08,0x0a,0x09,0x0a,0x08,0x0f,0x0f,0x0a,0x09,0x0b,0x09,0x0a,0x08,0x0a,0x08,0x0b,0x0a,0x0a,0x07,0x0a,0x0a,0x08, 0x04,0x0d,0x08,0x08,0x0f,0x0c,0x0b,0x0a,0x0f,0x0c,0x0b,0x08,0x0f,0x0c,0x0c,0x0a,0x10,0x0d,0x09,0x08,0x0d,0x0d,0x0d,0x0a,0x0c,0x0a,0x0c,0x0a,0x16,0x13,0x0e,0x0b,0x13,0x0f,0x0f,0x0c,0x0a,0x07,0x09,0x07,0x07,0x00,0x00,0x11,0x10,0x0a,0x09,0x0a,0x0a,0x0a,0x09,0x09,0x08,0x0a,0x08,0x0c,0x0a,0x0e,0x0b,0x11,0x0e,0x0c,0x09,0x0b, 0x08,0x09,0x07,0x0f,0x0c,0x0c,0x0a,0x0e,0x0b,0x0e,0x0b,0x05,0x0f,0x0d,0x0a,0x09,0x0c,0x0a,0x0b,0x0a,0x0b,0x09,0x0b,0x09,0x0f,0x0e,0x09,0x09,0x0c,0x09,0x0c,0x09,0x0f,0x0d,0x09,0x08,0x09,0x08,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0b,0x0a,0x0d,0x0c,0x0a,0x0a,0x0f,0x0f,0x0e,0x0c, 0x09,0x08,0x0f,0x0e,0x11,0x0e,0x0c,0x09,0x0b,0x0a,0x0a,0x0a,0x0a,0x09,0x0a,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x0a,0x06,0x06,0x03,0x04,0x04,0x04,0x05,0x07,0x05,0x04,0x06,0x04,0x04,0x04,0x06,0x06,0x04,0x04,0x0a,0x0a,0x0a,0x0a,0x06,0x05,0x05,0x06,0x05,0x05,0x05,0x05,0x05,0x06, 0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x05,0x03,0x04,0x05,0x04,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x07,0x06,0x04,0x04,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x0b,0x05,0x0b,0x06,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x08,0x0b,0x0e,0x08,0x08,0x09,0x09,0x07,0x07,0x04,0x05,0x08,0x07,0x0c,0x0a,0x0a,0x08,0x0b,0x0b,0x0b,0x10,0x09,0x0a,0x0a,0x08,0x08,0x08,0x07,0x09,0x0a,0x0c,0x0a,0x08,0x0c,0x08,0x07,0x07,0x09,0x07,0x08,0x0a,0x08,0x0a,0x0a,0x06,0x08,0x06,0x06,0x07,0x05,0x05,0x07, 0x07,0x03,0x04,0x06,0x05,0x09,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x07,0x09,0x05,0x05,0x06,0x08,0x06,0x06,0x05,0x05,0x04,0x04,0x06,0x03,0x05,0x08,0x06,0x06,0x05,0x06,0x06,0x06,0x03,0x06,0x06,0x08,0x05,0x05,0x06,0x05,0x06,0x07,0x05,0x03,0x04,0x06,0x05,0x06,0x05,0x06,0x07,0x05,0x0a,0x03,0x06,0x09,0x0f,0x0b,0x09,0x09,0x0f, 0x0b,0x0f,0x0d,0x09,0x0a,0x09,0x08,0x13,0x08,0x0a,0x0f,0x10,0x10,0x0b,0x0b,0x0b,0x08,0x08,0x09,0x07,0x08,0x09,0x03,0x00,0x00,0x00,0x00,0x0a,0x0b,0x0b,0x0b,0x08,0x07,0x0a,0x0a,0x05,0x0f,0x0a,0x0a,0x06,0x06,0x08,0x06,0x08,0x0a,0x08,0x0a,0x0f,0x0b,0x05,0x05,0x0a,0x09,0x0a,0x0a,0x0a,0x05,0x0a,0x08,0x04,0x0f,0x0a,0x0a,0x06, 0x07,0x07,0x08,0x08,0x08,0x09,0x0a,0x0a,0x09,0x07,0x08,0x0c,0x04,0x08,0x04,0x0a,0x08,0x06,0x05,0x05,0x06,0x04,0x03,0x03,0x06,0x06,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x04,0x03,0x03,0x06,0x06,0x06,0x05,0x05,0x04,0x04,0x05,0x04,0x06,0x00,0x00,0x00,0x00,0x04,0x05,0x05,0x06,0x05,0x05, 0x09,0x09,0x09,0x09,0x06,0x00,0x00,0x00,0x00,0x08,0x05,0x05,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x03, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x0d,0x0b,0x0c,0x0a,0x0d,0x0b,0x10,0x0d,0x09,0x06,0x09,0x0c,0x09,0x0e,0x0c,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x06,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e, 0x11,0x07,0x04,0x09,0x0a,0x07,0x09,0x09,0x0a,0x0a,0x09,0x11,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x0b,0x09,0x09,0x09,0x06,0x0a,0x06,0x0d,0x0b,0x09,0x06,0x0e,0x09,0x0e,0x04,0x06,0x0a,0x0a,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0e,0x04,0x0a,0x04,0x09,0x07,0x04,0x04,0x09,0x04,0x0d,0x04,0x10,0x09,0x10,0x10,0x0a,0x0a,0x0a,0x09, 0x09,0x07,0x07,0x14,0x14,0x17,0x17,0x0e,0x0e,0x09,0x09,0x03,0x11,0x0d,0x0e,0x0b,0x0a,0x0b,0x09,0x09,0x0d,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x04,0x0b,0x00,0x0b,0x0b,0x0b,0x06,0x09,0x09,0x10,0x06,0x10,0x06,0x0a,0x0b,0x0a,0x07,0x10,0x09,0x10,0x09,0x0d,0x0e,0x06,0x09,0x09,0x07,0x04,0x09,0x0a,0x09,0x0a,0x09, 0x0a,0x0a,0x09,0x0b,0x0b,0x10,0x06,0x09,0x07,0x0b,0x09,0x06,0x09,0x09,0x09,0x10,0x06,0x10,0x06,0x04,0x0a,0x07,0x11,0x09,0x09,0x0b,0x0b,0x11,0x09,0x00,0x00,0x00,0x0b,0x00,0x0b,0x0b,0x0b,0x0b,0x0d,0x0b,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x07,0x07,0x09,0x09,0x0d,0x0e,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06, 0x10,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x09,0x07,0x07,0x07,0x14,0x0e,0x14,0x0e,0x14,0x0e,0x17,0x11,0x17,0x11,0x0e,0x09,0x0a,0x0a,0x0a,0x11,0x11,0x09,0x09,0x11,0x09,0x09,0x11,0x09,0x09,0x11,0x09,0x09,0x0d, 0x0d,0x12,0x11,0x10,0x09,0x0e,0x09,0x0e,0x09,0x0e,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x0b,0x06,0x0b,0x06,0x09,0x0b,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0e,0x10,0x0d,0x0e,0x06,0x09,0x0d,0x0e,0x0d,0x0e,0x00,0x00,0x00,0x00,0x00,0x13,0x12, 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x07,0x00,0x00,0x0a,0x00,0x00,0x00,0x14,0x0e,0x17,0x11,0x09,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x10,0x10,0x06,0x0a,0x0a,0x0a,0x15,0x0e,0x09,0x1a,0x12,0x06,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09, 0x07,0x07,0x0d,0x0b,0x0b,0x09,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x15,0x1a,0x00,0x00,0x00,0x00,0x00,0x0a,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x0a,0x0a,0x0a,0x0a,0x0b,0x0a,0x09,0x09,0x07,0x14,0x0e,0x09,0x0a,0x0a,0x0a,0x09,0x0a,0x0a,0x0a,0x09,0x0a,0x0a, 0x0a,0x11,0x09,0x09,0x11,0x09,0x09,0x10,0x09,0x09,0x10,0x09,0x09,0x10,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x0b,0x06,0x06,0x07,0x07,0x14,0x0e,0x0b,0x0a,0x0a,0x00,0x09,0x09,0x09,0x06,0x0a,0x0c,0x0b,0x09,0x09,0x06,0x04,0x0d,0x0a,0x0a,0x06,0x09,0x08,0x08,0x08,0x08,0x04,0x09,0x07,0x0b,0x08,0x0a, 0x08,0x09,0x07,0x0b,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x08,0x08,0x08,0x05,0x09,0x0a,0x0a,0x09,0x06,0x0d,0x0a,0x0b,0x09,0x0b,0x08,0x0a,0x09,0x07,0x0c,0x06,0x07,0x07,0x08,0x0a,0x0a,0x09,0x11,0x09,0x11,0x06,0x04,0x03,0x09,0x04,0x02,0x00,0x02,0x04,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x07,0x07,0x07,0x09,0x09,0x10,0x07,0x0d,0x0a,0x10,0x0c,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x0f,0x08,0x0f,0x08,0x0f,0x0b,0x0c,0x0c,0x0c,0x0d,0x0f,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0d,0x0a,0x12,0x0e,0x08,0x08,0x05,0x05,0x05,0x06,0x04,0x0a,0x04,0x04,0x0e,0x0b,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x03,0x00,0x00,0x04,0x00,0x00,0x0b,0x0a,0x07,0x08,0x0c,0x05,0x06,0x0b,0x0c,0x05,0x0a,0x09,0x09,0x0c,0x0b,0x05,0x07,0x0b,0x0a,0x0a,0x0b,0x0a,0x0a,0x0b,0x0a,0x0d,0x0c,0x09,0x09,0x09,0x04,0x06,0x0a,0x0a,0x09,0x09,0x09,0x0a,0x0b,0x08,0x0c,0x09,0x09,0x0c,0x0a,0x0c, 0x09,0x0d,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x0a,0x07,0x08,0x0c,0x05,0x06,0x0c,0x05,0x0a,0x09,0x09,0x0b,0x07,0x0b,0x0a,0x0b,0x0a,0x0b,0x0a,0x0d,0x0c,0x05,0x0a,0x09,0x0b,0x0b,0x14,0x00,0x0b,0x09,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x05,0x00,0x0d,0x0b,0x0b,0x0c,0x09,0x0b,0x0d,0x0d,0x08,0x0b,0x0d,0x0d,0x0b,0x0d,0x0e,0x0d,0x0b,0x09,0x0a,0x0d,0x0c,0x0a,0x0c,0x0c,0x0b,0x0c,0x0c,0x0d,0x0a,0x0b,0x0c,0x0b,0x0d,0x0b,0x0b,0x0b,0x0b,0x0e,0x08,0x0a,0x0a,0x0f,0x09,0x09,0x0d,0x0f,0x0a,0x09,0x12,0x0a,0x0a,0x0d, 0x09,0x09,0x0d,0x0a,0x0d,0x0e,0x0f,0x09,0x0d,0x09,0x0b,0x09,0x0a,0x0a,0x0b,0x09,0x0a,0x0d,0x09,0x0b,0x0b,0x09,0x09,0x0a,0x10,0x09,0x09,0x0a,0x0a,0x07,0x06,0x09,0x09,0x09,0x09,0x09,0x0f,0x09,0x0f,0x08,0x09,0x0f,0x0b,0x09,0x0f,0x0d,0x0d,0x0f,0x0a,0x09,0x0f,0x0f,0x09,0x09,0x09,0x09,0x09,0x09,0x0f,0x0f,0x0a,0x09,0x0a,0x0f, 0x0a,0x09,0x09,0x09,0x0f,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0c,0x0d,0x0c,0x0b,0x09,0x0d,0x0b,0x0c,0x0a,0x0b,0x0c,0x0d,0x0c,0x0a,0x0c,0x0b,0x0c,0x0b,0x0d,0x0c,0x0c,0x0c,0x0c,0x0b,0x0c,0x0c,0x0c,0x0d,0x0b,0x0d,0x0c,0x02,0x02,0x03,0x03,0x03,0x05,0x06,0x0f,0x0a,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0a,0x0a,0x05,0x0e,0x0a, 0x0a,0x0a,0x09,0x0a,0x09,0x0a,0x05,0x0a,0x09,0x0a,0x07,0x0f,0x09,0x0a,0x0a,0x0a,0x0e,0x0a,0x0a,0x07,0x0e,0x0a,0x0a,0x0c,0x0c,0x04,0x05,0x13,0x13,0x13,0x13,0x18,0x09,0x09,0x04,0x09,0x07,0x09,0x09,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x09,0x09,0x0a,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x08,0x09,0x0a,0x07,0x07,0x0a,0x0a,0x04,0x05,0x08,0x07,0x0d,0x0b,0x0a,0x08,0x0a,0x08,0x07,0x07,0x0a,0x09,0x0e,0x09,0x08,0x08,0x0c,0x0d,0x07,0x0b,0x08,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x07, 0x07,0x04,0x04,0x04,0x04,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x09,0x0a,0x0a,0x04,0x04,0x04,0x04,0x04,0x0a,0x05,0x08,0x07,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x0c,0x0b,0x09,0x08,0x07,0x09,0x07,0x08,0x0a,0x0a,0x04,0x08,0x09,0x0d,0x0b,0x08,0x0a,0x0a,0x08,0x08,0x07,0x08,0x0b,0x09,0x0b,0x0b,0x09,0x07,0x0a,0x04,0x0a,0x08,0x0b,0x04,0x08,0x07,0x0a,0x07,0x09,0x07,0x04,0x04,0x05,0x0e,0x0e,0x0a,0x08, 0x08,0x0a,0x09,0x08,0x08,0x07,0x0a,0x07,0x0d,0x08,0x0b,0x0b,0x08,0x0a,0x0d,0x0a,0x0a,0x0a,0x08,0x09,0x07,0x08,0x0b,0x09,0x0b,0x09,0x0e,0x0e,0x0a,0x0c,0x08,0x09,0x0f,0x08,0x07,0x0a,0x0a,0x0b,0x0f,0x0f,0x0b,0x09,0x0a,0x07,0x0a,0x0a,0x0a,0x0c,0x09,0x09,0x0c,0x0a,0x0a,0x06,0x0b,0x0b,0x0a,0x08,0x08,0x0f,0x0d,0x08,0x09,0x0a, 0x0a,0x0b,0x0b,0x0c,0x0c,0x06,0x10,0x0a,0x09,0x0a,0x0b,0x0b,0x09,0x09,0x05,0x0d,0x0c,0x0c,0x08,0x0c,0x04,0x04,0x07,0x07,0x04,0x04,0x0a,0x07,0x05,0x0d,0x0c,0x05,0x04,0x04,0x08,0x06,0x06,0x04,0x04,0x04,0x06,0x0b,0x08,0x05,0x0a,0x0c,0x0a,0x0a,0x08,0x0d,0x0a,0x0a,0x06,0x07,0x09,0x07,0x04,0x04,0x07,0x09,0x06,0x0b,0x0b,0x0b, 0x10,0x0d,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x0d,0x0e,0x06,0x06,0x09,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x0a,0x0a,0x0a,0x09,0x09,0x14,0x0e,0x14,0x0e,0x17,0x11,0x17,0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x10,0x10,0x09,0x09,0x10,0x10,0x09,0x09,0x0d,0x0e,0x06,0x06,0x0d,0x0e,0x06,0x06,0x0d,0x0e,0x06,0x06,0x11,0x0d,0x0e, 0x09,0x0a,0x0a,0x0b,0x06,0x0b,0x0d,0x09,0x09,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x06,0x0d,0x09,0x09,0x04,0x09,0x09,0x09,0x09,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x14,0x0e,0x14,0x0e,0x14,0x0e,0x17,0x11,0x17,0x11,0x0e,0x0e,0x0e,0x11,0x11,0x11,0x11,0x11,0x11,0x0d,0x09,0x09,0x0d,0x09,0x09,0x10,0x09,0x12,0x11,0x10,0x09,0x0e,0x09,0x0e,0x09,0x0e,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x06,0x0b,0x0b,0x06,0x06,0x0b,0x06,0x0b, 0x06,0x0b,0x09,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x09,0x06,0x06,0x06,0x06,0x00,0x14,0x0e,0x17,0x11,0x10,0x09,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0x0a,0x0a,0x09,0x09,0x07,0x14,0x0e,0x11,0x11,0x10,0x10,0x10,0x0a,0x0a,0x0a,0x0a,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x14,0x0e, 0x0a,0x0b,0x0a,0x0a,0x0a,0x0b,0x0a,0x0a,0x14,0x14,0x0e,0x0e,0x07,0x07,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x0d,0x0e,0x06,0x06,0x0d,0x0e,0x06,0x06,0x0d,0x0e,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x10,0x06,0x10,0x06,0x0a,0x0b,0x0a,0x0a,0x14,0x14,0x0e,0x0e,0x14,0x14,0x0e,0x0e,0x0e,0x0e,0x09,0x09,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x00,0x00,0x04,0x04,0x06,0x04,0x00,0x00,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, 0x04,0x04,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0e,0x0a,0x0e,0x0a,0x0e,0x0a,0x0e,0x0b,0x0b,0x0b,0x04,0x04,0x09,0x07,0x0a,0x0b,0x0a,0x09,0x09,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x08,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0a,0x0a,0x0b,0x09,0x0b,0x0d,0x0b,0x0d,0x0e,0x0b,0x0d,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x08,0x09,0x0a,0x0a,0x0b,0x0a,0x0b,0x0a,0x0a,0x0a,0x09,0x09,0x0d,0x0c,0x0c,0x0b,0x0c,0x0a,0x0a,0x0a,0x0d,0x0d,0x0d,0x0d,0x10,0x10,0x0c,0x10,0x10,0x0c,0x0f,0x0e,0x09, 0x0d,0x0e,0x0d,0x0a,0x0e,0x0d,0x0c,0x0c,0x0a,0x0b,0x0d,0x0e,0x0c,0x0a,0x0c,0x0a,0x09,0x10,0x10,0x10,0x0e,0x10,0x10,0x0c,0x10,0x10,0x0c,0x0d,0x0d,0x0d,0x0c,0x0c,0x0b,0x0f,0x0d,0x0e,0x0c,0x0c,0x0a,0x0d,0x0c,0x0c,0x0e,0x0d,0x0c,0x0f,0x09,0x09,0x0a,0x09,0x0a,0x0b,0x0c,0x0c,0x0a,0x0a,0x0a,0x09,0x0a,0x09,0x09,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x09,0x09,0x0a,0x0b,0x0a,0x0a,0x08,0x0a,0x0a,0x0a,0x0a,0x0d,0x0e,0x0b,0x0b,0x0b,0x0d,0x0b,0x0c,0x09,0x08,0x0a,0x0a,0x08,0x08,0x09,0x09,0x08,0x08,0x0b,0x08,0x09,0x08,0x09,0x0d,0x0a,0x0e,0x09,0x0a,0x0a,0x0d,0x05,0x0d,0x0c,0x0c,0x0b,0x0a,0x0d,0x0a,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x05, 0x05,0x05,0x05,0x05,0x05,0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x0f,0x0f,0x0f,0x0f,0x08,0x0d,0x0c,0x08,0x07,0x08,0x09,0x0a,0x08,0x0e,0x0e,0x0f,0x08,0x11,0x08,0x0e,0x0e,0x0e,0x0e,0x0a,0x08,0x08,0x0d,0x0a,0x0d, 0x0b,0x09,0x08,0x07,0x11,0x07,0x09,0x08,0x08,0x08,0x08,0x08,0x17,0x0e,0x0e,0x07,0x04,0x08,0x04,0x08,0x04,0x04,0x04,0x08,0x0a,0x0a,0x09,0x06,0x06,0x04,0x04,0x04,0x06,0x04,0x07,0x0f,0x04,0x0f,0x0f,0x0f,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x14,0x14,0x0b,0x14,0x14,0x0b,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x08,0x0a,0x08,0x09,0x07,0x06,0x06,0x0c,0x09,0x0c,0x07,0x13,0x0f,0x0a,0x09,0x10,0x0d,0x0e,0x0d,0x11,0x0e,0x10,0x0d,0x0b,0x08,0x0c,0x0a,0x10,0x0c,0x0d,0x0a,0x0d,0x0a,0x0f,0x0b,0x0f,0x0b, 0x13,0x0e,0x0d,0x0a,0x0d,0x0a,0x15,0x0f,0x0d,0x00,0x11,0x11,0x11,0x08,0x00,0x00,0x0a,0x09,0x0c,0x09,0x09,0x07,0x12,0x0f,0x10,0x0f,0x0c,0x0a,0x0c,0x0a,0x09,0x07,0x0d,0x0a,0x09,0x07,0x0e,0x0b,0x0b,0x0a,0x11,0x0e,0x09,0x0a,0x0c,0x0c,0x0e,0x08,0x03,0x08,0x0c,0x07,0x11,0x11,0x04,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x07,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x08,0x0c,0x0c,0x05,0x04,0x05,0x04,0x0c,0x0a,0x0d,0x0b,0x09,0x08,0x09,0x08,0x0a,0x0a,0x07,0x07,0x13,0x0e,0x14,0x0f,0x11,0x0e,0x0f,0x0b,0x0f,0x0b,0x0f,0x0b,0x0b,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x09,0x05,0x08,0x04,0x0d,0x0a,0x0f,0x0b,0x17,0x11,0x0a,0x0a,0x0c,0x0c,0x0e, 0x0f,0x0d,0x0a,0x11,0x0d,0x09,0x07,0x0a,0x08,0x0b,0x08,0x10,0x0c,0x0a,0x09,0x0a,0x0a,0x0a,0x0a,0x08,0x07,0x08,0x07,0x08,0x06,0x09,0x09,0x05,0x0b,0x06,0x10,0x0b,0x06,0x0a,0x0a,0x08,0x0d,0x0a,0x06,0x06,0x0a,0x0a,0x0a,0x08,0x04,0x0d,0x0a,0x06,0x06,0x0b,0x08,0x0c,0x07,0x0d,0x0a,0x0b,0x08,0x0c,0x0a,0x0a,0x08,0x0d,0x0a,0x0a, 0x06,0x09,0x07,0x0d,0x07,0x09,0x0f,0x08,0x0a,0x0f,0x05,0x13,0x0f,0x0f,0x14,0x0f,0x10,0x10,0x0f,0x0f,0x10,0x09,0x08,0x0b,0x0c,0x0f,0x0c,0x10,0x04,0x08,0x0a,0x0f,0x12,0x0c,0x12,0x0b,0x0b,0x0e,0x0c,0x13,0x10,0x09,0x10,0x06,0x10,0x06,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x11,0x09,0x09,0x11,0x0d,0x09,0x09,0x0d,0x0b,0x06, 0x06,0x0b,0x0a,0x0a,0x0a,0x0a,0x0d,0x06,0x06,0x0e,0x0d,0x06,0x06,0x0e,0x07,0x07,0x09,0x09,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x09,0x07,0x0a,0x09,0x0d,0x0a,0x0a,0x0f,0x0b,0x0d,0x0d,0x0e,0x0e,0x0a,0x08,0x11, 0x0e,0x12,0x0f,0x0c,0x0a,0x05,0x05,0x0a,0x0b,0x07,0x0a,0x09,0x0a,0x08,0x0d,0x0e,0x07,0x0a,0x07,0x04,0x06,0x09,0x09,0x04,0x04,0x03,0x04,0x06,0x06,0x06,0x08,0x19,0x22,0x06,0x07,0x02,0x05,0x07,0x07,0x05,0x08,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x17,0x09,0x0d,0x10,0x0f,0x0b,0x08, 0x0a,0x0c,0x0c,0x08,0x05,0x0b,0x09,0x0c,0x09,0x0b,0x09,0x09,0x0d,0x0a,0x0a,0x09,0x0d,0x0a,0x0e,0x08,0x09,0x0b,0x05,0x0a,0x06,0x06,0x04,0x0f,0x0a,0x0a,0x09,0x09,0x0a,0x10,0x10,0x10,0x11,0x11,0x09,0x08,0x05,0x09,0x08,0x0a,0x08,0x0b,0x04,0x0a,0x0a,0x0f,0x0f,0x0a,0x09,0x0a,0x09,0x09,0x08,0x09,0x08,0x08,0x05,0x06,0x04,0x04, 0x06,0x0a,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x05,0x05,0x05,0x04,0x04,0x1d,0x11,0x0f,0x12,0x05,0x05,0x06,0x07,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x10,0x06,0x06,0x10,0x04,0x09,0x09,0x17,0x11,0x11,0x17,0x10,0x09,0x09,0x10,0x09,0x09,0x07, 0x07,0x00,0x00,0x06,0x0d,0x0a,0x0c,0x0a,0x15,0x12,0x0c,0x09,0x0c,0x09,0x17,0x11,0x0d,0x0a,0x07,0x05,0x0b,0x00,0x0c,0x09,0x06,0x05,0x03,0x08,0x06,0x06,0x04,0x03,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x09,0x07,0x0a,0x0a,0x09,0x10,0x0e,0x0e,0x0d,0x0e,0x10,0x0b,0x0c,0x0a,0x07,0x10,0x13,0x07,0x14,0x09,0x0e,0x10, 0x10,0x10,0x07,0x0d,0x11,0x0d,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x0a,0x0a,0x0a,0x0e,0x09,0x09,0x10,0x06,0x06,0x10,0x06,0x06,0x10,0x08,0x08,0x00,0x07,0x0e,0x06,0x06,0x11,0x09,0x09,0x0d,0x09,0x09,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, 0x05,0x1a,0x1a,0x0f,0x00,0x00,0x0f,0x0f,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0f,0x0b,0x0b,0x0e,0x11,0x0b,0x0b,0x12,0x0b,0x0b,0x10,0x0b,0x0b,0x0d,0x0b,0x0d,0x0e,0x10,0x0b,0x0d,0x0b,0x0c,0x0b,0x0c,0x0b,0x0b,0x0c,0x0b,0x0d,0x0a,0x0b,0x0d,0x0b,0x0b,0x0a,0x0d, 0x0b,0x0b,0x0b,0x0c,0x08,0x09,0x0b,0x0d,0x0d,0x09,0x00,0x00,0x13,0x26,0x0c,0x00,0x02,0x05,0x05,0x07,0x0b,0x0a,0x10,0x0f,0x04,0x06,0x06,0x08,0x0d,0x04,0x08,0x04,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x04,0x04,0x0d,0x0d,0x0d,0x09,0x12,0x0c,0x0b,0x0c,0x0d,0x0a,0x09,0x0d,0x0d,0x05,0x07,0x0b,0x09,0x11,0x0e, 0x0e,0x0b,0x0e,0x0b,0x0a,0x0a,0x0d,0x0c,0x12,0x0b,0x0b,0x0b,0x06,0x07,0x06,0x0d,0x08,0x05,0x0a,0x0b,0x09,0x0b,0x0a,0x06,0x0b,0x0b,0x05,0x05,0x09,0x05,0x10,0x0b,0x0b,0x0b,0x0b,0x07,0x08,0x06,0x0b,0x09,0x0e,0x09,0x09,0x09,0x06,0x05,0x06,0x0d,0x0c,0x0c,0x0c,0x0a,0x0e,0x0e,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x0a,0x0a, 0x0a,0x0a,0x05,0x05,0x05,0x05,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x0a,0x0a,0x09,0x08,0x09,0x0a,0x08,0x11,0x11,0x0f,0x05,0x08,0x0d,0x10,0x0e,0x10,0x0d,0x0d,0x0d,0x0a,0x0b,0x0a,0x0c,0x0e,0x0a,0x07,0x08,0x0e,0x10,0x0b,0x09,0x05,0x05,0x0d,0x0c,0x0a,0x0d,0x0c,0x0a,0x0a,0x0e,0x0c,0x0c,0x0e,0x12,0x12, 0x0a,0x13,0x07,0x07,0x04,0x04,0x0d,0x0b,0x09,0x0b,0x03,0x0a,0x06,0x06,0x0b,0x0b,0x07,0x04,0x04,0x07,0x17,0x0c,0x0a,0x0c,0x0a,0x0a,0x05,0x05,0x05,0x05,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x05,0x07,0x06,0x06,0x06,0x04,0x05,0x04,0x06,0x04,0x07,0x09,0x05,0x0a,0x08,0x0b,0x09,0x05,0x0d,0x0b,0x0b,0x09,0x0b,0x0b,0x0d,0x0d,0x07,0x07, 0x07,0x12,0x11,0x12,0x09,0x0d,0x0b,0x05,0x0a,0x08,0x0c,0x09,0x0c,0x09,0x0b,0x08,0x04,0x0c,0x0a,0x0c,0x0a,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x09,0x05,0x09,0x06,0x09,0x06,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0b,0x07,0x0b,0x07,0x0a,0x08,0x0a,0x06,0x0a,0x08,0x0d,0x0b,0x0d,0x0b,0x0b,0x09,0x0b,0x09,0x09,0x0e,0x0e,0x0c,0x0b,0x08, 0x0b,0x09,0x0d,0x08,0x09,0x07,0x15,0x0c,0x09,0x0c,0x04,0x07,0x0f,0x06,0x0b,0x07,0x07,0x0b,0x07,0x0c,0x0a,0x0c,0x09,0x0c,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x05,0x0b,0x09,0x09,0x09,0x05,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b, 0x0b,0x07,0x0a,0x08,0x0a,0x06,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x12,0x0e,0x0b,0x09,0x05,0x0c,0x0a,0x10,0x10,0x0e,0x0b,0x04,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0b,0x09,0x04,0x08,0x0a,0x0b,0x12,0x12,0x12,0x11,0x07,0x07,0x04,0x05,0x05,0x0c,0x0b,0x0f,0x07,0x0f,0x0d,0x10,0x05,0x0c,0x0b,0x0a,0x0b,0x0d,0x05,0x0b,0x0c,0x11, 0x0e,0x0a,0x0e,0x0e,0x0b,0x0a,0x0a,0x0b,0x0b,0x0f,0x0e,0x05,0x0b,0x0c,0x08,0x0b,0x05,0x0b,0x0a,0x0a,0x08,0x0b,0x0b,0x05,0x0a,0x09,0x0b,0x0a,0x08,0x0b,0x0b,0x09,0x0b,0x0a,0x0e,0x0f,0x05,0x0b,0x0b,0x0b,0x0f,0x0a,0x0d,0x09,0x0c,0x0a,0x05,0x13,0x13,0x0e,0x0b,0x0b,0x0d,0x0c,0x0b,0x0b,0x09,0x0d,0x0a,0x10,0x0a,0x0e,0x0e,0x0b, 0x0d,0x11,0x0d,0x0e,0x0e,0x0b,0x0c,0x0a,0x0b,0x0e,0x0b,0x0e,0x0d,0x12,0x13,0x0d,0x0f,0x0b,0x0c,0x13,0x0b,0x0a,0x0b,0x0a,0x07,0x0a,0x0a,0x0e,0x08,0x0b,0x0b,0x09,0x0a,0x0d,0x0b,0x0b,0x0b,0x0b,0x09,0x08,0x09,0x0d,0x09,0x0b,0x0b,0x0f,0x10,0x0b,0x0d,0x0a,0x09,0x0f,0x0a,0x0a,0x0b,0x07,0x09,0x08,0x05,0x0f,0x0f,0x0b,0x09,0x09, 0x0b,0x09,0x07,0x13,0x15,0x0c,0x07,0x07,0x07,0x07,0x05,0x0a,0x08,0x0b,0x0e,0x0b,0x0d,0x0b,0x06,0x06,0x05,0x05,0x09,0x09,0x09,0x09,0x06,0x06,0x06,0x09,0x06,0x09,0x06,0x06,0x06,0x09,0x09,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x05,0x05,0x05,0x05,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0a,0x06,0x0a, 0x0a,0x0e,0x0b,0x05,0x07,0x05,0x05,0x0a,0x08,0x11,0x0f,0x0c,0x0a,0x0b,0x09,0x0e,0x0b,0x0b,0x09,0x0b,0x09,0x0c,0x09,0x0c,0x0b,0x0d,0x0b,0x0e,0x0a,0x0e,0x0b,0x06,0x06,0x06,0x06,0x08,0x08,0x09,0x09,0x09,0x09,0x05,0x05,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0c,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x09,0x0d,0x0b,0x0d,0x0b,0x0d, 0x0b,0x0d,0x0b,0x0d,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x06,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x05,0x05,0x05,0x05,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x09,0x05,0x09,0x05,0x09,0x05,0x09,0x05,0x11,0x10,0x11,0x10,0x11,0x10,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e, 0x0b,0x0e,0x0b,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x0b,0x07,0x0b,0x07,0x0b,0x07,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0a,0x06,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0c,0x09,0x0c,0x09,0x12,0x0e,0x12,0x0e,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b, 0x09,0x0b,0x06,0x0e,0x09,0x0a,0x05,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x09,0x09,0x0a, 0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x12,0x12,0x12,0x12,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x10,0x10,0x10,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x12,0x12,0x12,0x12,0x12,0x12,0x0c,0x0c,0x08,0x08,0x0b,0x0b,0x05,0x05,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x12,0x12,0x12,0x12,0x12,0x12,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0f,0x0f,0x0d,0x0b,0x0b,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x0d,0x0c,0x0b,0x0b,0x0b,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x10,0x10,0x0e,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x0c, 0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x09,0x0d,0x0e,0x0b,0x0b,0x0b,0x0a,0x0a,0x09,0x0d,0x0c,0x11,0x05,0x05,0x0b,0x09,0x05,0x09,0x11,0x0e,0x0b,0x0e,0x12,0x0f,0x0b,0x0b,0x0b,0x0a,0x08,0x0a,0x06,0x06,0x0a,0x06,0x0a,0x0e,0x0e,0x0b,0x0a,0x0b,0x09,0x0c,0x0c,0x08,0x08,0x0a,0x0a,0x07,0x07,0x0a,0x05,0x07,0x09,0x05,0x18,0x16,0x13,0x10, 0x0e,0x0a,0x14,0x12,0x0f,0x0c,0x0a,0x05,0x05,0x0e,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0d,0x0b,0x0a,0x0c,0x0a,0x0c,0x0a,0x10,0x10,0x0d,0x0b,0x0d,0x0b,0x0b,0x09,0x0e,0x0b,0x0e,0x0b,0x0c,0x08,0x05,0x18,0x16,0x13,0x0d,0x0b,0x13,0x0d,0x0e,0x0b,0x0c,0x0a,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x05,0x05,0x05,0x05,0x0e,0x0b, 0x0e,0x0b,0x0b,0x07,0x0b,0x07,0x0d,0x0b,0x0d,0x0b,0x0a,0x08,0x0d,0x0b,0x0e,0x0b,0x0b,0x0b,0x09,0x0c,0x0a,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0b,0x09,0x0b,0x0a,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x0b,0x09,0x09,0x0b,0x0b,0x0a,0x0c,0x08,0x08,0x0a,0x0a,0x05,0x0b,0x0b,0x0a,0x09,0x09,0x0b,0x0b,0x0b,0x05,0x05,0x06,0x05,0x07, 0x05,0x0b,0x10,0x10,0x10,0x0b,0x0b,0x0b,0x0b,0x0d,0x0e,0x0c,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x09,0x09,0x08,0x05,0x05,0x05,0x05,0x06,0x06,0x0b,0x0b,0x0b,0x09,0x0e,0x09,0x08,0x09,0x0a,0x08,0x08,0x07,0x07,0x07,0x09,0x0c,0x09,0x0a,0x0a,0x0b,0x05,0x09,0x07,0x0b,0x07,0x07,0x11,0x12,0x13,0x0c,0x09,0x0e,0x0f,0x0b,0x0b,0x09, 0x09,0x0a,0x0b,0x0b,0x0d,0x0b,0x0c,0x0f,0x0b,0x0d,0x0b,0x0b,0x09,0x09,0x09,0x0b,0x0a,0x0c,0x09,0x11,0x10,0x0b,0x0a,0x0c,0x0a,0x0c,0x09,0x0b,0x09,0x0d,0x0b,0x0b,0x08,0x0b,0x0b,0x09,0x05,0x0e,0x09,0x09,0x10,0x0d,0x0c,0x0b,0x11,0x0e,0x0d,0x09,0x11,0x0d,0x0e,0x0b,0x12,0x0e,0x0a,0x09,0x0f,0x0e,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b, 0x19,0x15,0x10,0x0c,0x15,0x11,0x10,0x0d,0x0b,0x08,0x0a,0x07,0x08,0x00,0x00,0x13,0x12,0x0b,0x0a,0x0b,0x0b,0x0b,0x0a,0x0a,0x09,0x0b,0x09,0x0d,0x0b,0x10,0x0d,0x13,0x10,0x0e,0x0b,0x0c,0x09,0x0a,0x08,0x11,0x0d,0x0d,0x0b,0x10,0x0c,0x10,0x0c,0x05,0x10,0x0e,0x0b,0x0a,0x0d,0x0b,0x0c,0x0b,0x0c,0x0a,0x0c,0x0a,0x10,0x10,0x0a,0x0a, 0x0e,0x0a,0x0e,0x0a,0x10,0x0e,0x0a,0x08,0x0a,0x08,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0c,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0d,0x0b,0x0f,0x0d,0x0b,0x0b,0x10,0x10,0x0f,0x0e,0x0b,0x09,0x11,0x0f,0x13,0x10,0x0e,0x0a,0x0d,0x0b,0x0b,0x0b,0x0b,0x0a,0x0b,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x04,0x04,0x0b,0x06,0x06,0x03,0x04,0x04,0x04,0x05,0x08,0x05,0x04,0x07,0x04,0x04,0x04,0x06,0x06,0x04,0x04,0x0b,0x0b,0x0b,0x0b,0x06,0x05,0x05,0x06,0x06,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0x05,0x05,0x04,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,0x08,0x06,0x05,0x05,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x07,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0a, 0x0a,0x0a,0x07,0x0a,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x0c,0x06,0x0c,0x06,0x0b,0x0b,0x06,0x06,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x0b,0x09,0x0d,0x10,0x09,0x09,0x0a,0x0b,0x08,0x08,0x05,0x06,0x09,0x07,0x0d,0x0b,0x0b, 0x09,0x0c,0x0c,0x0c,0x12,0x0a,0x0b,0x0b,0x09,0x09,0x09,0x08,0x0a,0x0b,0x0e,0x0b,0x09,0x0e,0x09,0x08,0x08,0x0a,0x07,0x09,0x0b,0x09,0x0b,0x0b,0x07,0x09,0x07,0x07,0x08,0x06,0x06,0x08,0x08,0x04,0x04,0x07,0x05,0x0a,0x08,0x08,0x08,0x07,0x06,0x07,0x06,0x08,0x0a,0x06,0x06,0x07,0x09,0x07,0x07,0x06,0x06,0x05,0x05,0x07,0x03,0x06, 0x09,0x06,0x07,0x05,0x07,0x07,0x07,0x04,0x06,0x06,0x09,0x05,0x06,0x06,0x06,0x07,0x08,0x06,0x03,0x04,0x06,0x05,0x06,0x06,0x07,0x08,0x06,0x0b,0x03,0x07,0x0a,0x11,0x0c,0x0a,0x0a,0x10,0x0c,0x10,0x0e,0x0a,0x0b,0x0a,0x09,0x15,0x09,0x0b,0x11,0x12,0x12,0x0c,0x0c,0x0c,0x09,0x09,0x0a,0x08,0x09,0x0a,0x04,0x00,0x00,0x00,0x00,0x0b, 0x0c,0x0c,0x0c,0x09,0x07,0x0b,0x0b,0x06,0x10,0x0b,0x0b,0x07,0x06,0x09,0x06,0x09,0x0b,0x09,0x0b,0x11,0x0c,0x06,0x05,0x0b,0x0a,0x0b,0x0b,0x0b,0x06,0x0b,0x09,0x05,0x10,0x0b,0x0b,0x07,0x08,0x08,0x09,0x09,0x09,0x0a,0x0b,0x0b,0x0a,0x08,0x08,0x0e,0x05,0x09,0x05,0x0b,0x08,0x07,0x05,0x05,0x07,0x05,0x03,0x03,0x07,0x06,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x04,0x09,0x09,0x06,0x06,0x07,0x06,0x07,0x04,0x03,0x04,0x06,0x07,0x06,0x06,0x05,0x05,0x05,0x06,0x05,0x07,0x00,0x00,0x00,0x00,0x04,0x06,0x06,0x07,0x05,0x06,0x0a,0x0a,0x0a,0x0a,0x06,0x00,0x00,0x00,0x00,0x09,0x06,0x05,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x05,0x05,0x05,0x05,0x0b,0x0b,0x0b,0x0b,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, 0x06,0x06,0x0f,0x0c,0x0d,0x0b,0x0e,0x0c,0x12,0x0e,0x0a,0x07,0x0a,0x0d,0x0a,0x10,0x0d,0x00,0x00,0x00,0x00,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x10,0x10,0x13,0x08,0x05,0x0a,0x0b,0x08,0x0a,0x0a,0x0b,0x0b,0x0a,0x13,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0c,0x0a,0x0a,0x0a,0x06,0x0b,0x06,0x0e, 0x0d,0x0a,0x06,0x10,0x0a,0x10,0x05,0x06,0x0b,0x0b,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x10,0x05,0x0b,0x05,0x0a,0x08,0x05,0x05,0x0a,0x05,0x0e,0x05,0x11,0x0a,0x11,0x11,0x0b,0x0b,0x0b,0x0a,0x0a,0x08,0x08,0x16,0x16,0x19,0x19,0x10,0x10,0x0a,0x0a,0x03,0x13,0x0e,0x10,0x0d,0x0b,0x0d,0x0a,0x0a,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x0b,0x05,0x0c,0x00,0x0c,0x0c,0x0c,0x06,0x0a,0x0a,0x11,0x06,0x11,0x06,0x0b,0x0d,0x0b,0x08,0x11,0x0a,0x11,0x0a,0x0e,0x10,0x06,0x0a,0x0a,0x08,0x05,0x0a,0x0b,0x0a,0x0b,0x0a,0x0b,0x0b,0x0a,0x0d,0x0c,0x11,0x06,0x0a,0x08,0x0d,0x0a,0x06,0x0a,0x0a,0x0a,0x11,0x06,0x11,0x06,0x05,0x0b,0x07,0x13,0x0a,0x0a,0x0c,0x0c,0x13, 0x0a,0x00,0x00,0x00,0x0c,0x00,0x0c,0x0c,0x0c,0x0c,0x0e,0x0c,0x00,0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x08,0x08,0x0a,0x0a,0x0e,0x10,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x08,0x08,0x08,0x0a,0x08,0x08,0x08,0x16,0x10,0x16,0x10,0x16,0x10,0x19,0x13,0x19,0x13,0x10,0x0a,0x0b,0x0b,0x0b,0x13,0x13,0x0a,0x0a,0x13,0x0a,0x0a,0x13,0x0a,0x0a,0x13,0x0a,0x0a,0x0e,0x0e,0x15,0x13,0x11,0x0a,0x10,0x0a,0x10,0x0a,0x10,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x0d,0x06,0x0d,0x06,0x0d,0x06,0x0d, 0x06,0x0d,0x06,0x0d,0x0d,0x06,0x0d,0x06,0x0a,0x0d,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x10,0x11,0x0e,0x10,0x06,0x0a,0x0e,0x10,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x08,0x00,0x00,0x0b,0x00,0x00,0x00,0x16,0x10,0x19,0x13,0x0a,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x11,0x11,0x07,0x0b,0x0b,0x0b,0x17,0x10,0x0a,0x1d,0x15,0x06,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x08,0x08,0x0e,0x0d,0x0d,0x0a,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x18,0x1d,0x00,0x00,0x00,0x00,0x00,0x0b,0x0a,0x00,0x00,0x00,0x00,0x00,0x00, 0x11,0x08,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0b,0x0b,0x0d,0x0b,0x0a,0x0a,0x08,0x16,0x10,0x0a,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x0b,0x13,0x0a,0x0a,0x13,0x0a,0x0a,0x11,0x0a,0x0a,0x11,0x0a,0x0a,0x11,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0d,0x06,0x0d,0x06,0x0d,0x06,0x0d,0x0d, 0x06,0x06,0x08,0x08,0x16,0x10,0x0c,0x0b,0x0b,0x00,0x0a,0x0a,0x0a,0x07,0x0b,0x0d,0x0c,0x0a,0x0a,0x07,0x05,0x0e,0x0b,0x0b,0x07,0x0b,0x09,0x09,0x09,0x09,0x05,0x0a,0x08,0x0c,0x09,0x0b,0x09,0x0a,0x08,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x09,0x09,0x09,0x05,0x0a,0x0b,0x0b,0x0a,0x06,0x0e,0x0b,0x0c,0x0a, 0x0c,0x09,0x0b,0x0a,0x08,0x0d,0x07,0x08,0x08,0x09,0x0b,0x0b,0x0a,0x13,0x0a,0x13,0x06,0x05,0x03,0x0a,0x04,0x02,0x00,0x03,0x04,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x12,0x08,0x0e,0x0b,0x12,0x0e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x12,0x10,0x09,0x10,0x09,0x10,0x0c, 0x0d,0x0d,0x0d,0x0f,0x10,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0d,0x0d,0x0d,0x0d,0x0e,0x0b,0x14,0x10,0x09,0x09,0x05,0x05,0x05,0x07,0x04,0x0b,0x04,0x04,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x0c,0x0b,0x08,0x09,0x0d,0x05,0x06,0x0d,0x0d,0x05, 0x0b,0x0a,0x0a,0x0d,0x0d,0x05,0x08,0x0d,0x0b,0x0c,0x0c,0x0b,0x0b,0x0d,0x0b,0x0f,0x0e,0x0a,0x0a,0x0a,0x04,0x07,0x0b,0x0b,0x0a,0x0a,0x0a,0x0b,0x0c,0x09,0x0d,0x0a,0x0a,0x0d,0x0b,0x0e,0x0a,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0b,0x08,0x09,0x0d,0x06,0x07,0x0d,0x06,0x0b,0x0a,0x0a,0x0d,0x08,0x0d,0x0c,0x0c,0x0b,0x0d,0x0b,0x0f, 0x0e,0x05,0x0b,0x0a,0x0c,0x0c,0x17,0x00,0x0c,0x0a,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x00,0x0e,0x0c,0x0d,0x0d,0x0a,0x0d,0x0e,0x0e,0x09,0x0c,0x0e,0x0e,0x0d,0x0e,0x0f,0x0f, 0x0d,0x0a,0x0b,0x0e,0x0d,0x0b,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0b,0x0c,0x0d,0x0c,0x0f,0x0c,0x0c,0x0c,0x0d,0x10,0x09,0x0b,0x0b,0x11,0x0a,0x0a,0x0f,0x11,0x0c,0x0a,0x14,0x0b,0x0b,0x0e,0x0a,0x0a,0x0e,0x0b,0x0e,0x0f,0x11,0x0a,0x0f,0x0a,0x0c,0x0a,0x0c,0x0b,0x0c,0x0a,0x0b,0x0f,0x0a,0x0c,0x0d,0x0a,0x0a,0x0b,0x12,0x0a,0x0a,0x0b, 0x0b,0x08,0x06,0x0b,0x0b,0x0b,0x0a,0x0b,0x11,0x0b,0x11,0x09,0x0b,0x11,0x0d,0x0b,0x11,0x0e,0x0e,0x11,0x0b,0x0b,0x11,0x11,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x11,0x11,0x0b,0x0b,0x0b,0x11,0x0b,0x0a,0x0b,0x0b,0x11,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0d,0x0f,0x0d,0x0c,0x0a,0x0f,0x0d,0x0d,0x0b,0x0d,0x0d,0x0e,0x0e,0x0b,0x0d,0x0d, 0x0e,0x0d,0x0f,0x0d,0x0e,0x0e,0x0d,0x0c,0x0d,0x0d,0x0e,0x0f,0x0c,0x0e,0x0e,0x02,0x02,0x03,0x04,0x03,0x05,0x07,0x10,0x0b,0x0c,0x0b,0x0b,0x0c,0x0b,0x0b,0x0c,0x0b,0x0b,0x06,0x10,0x0b,0x0b,0x0b,0x0a,0x0b,0x0a,0x0b,0x05,0x0b,0x0a,0x0b,0x08,0x10,0x0a,0x0b,0x0b,0x0b,0x10,0x0b,0x0b,0x07,0x10,0x0b,0x0b,0x0d,0x0d,0x04,0x05,0x16, 0x15,0x15,0x16,0x1b,0x0a,0x0a,0x05,0x0a,0x07,0x0a,0x0a,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x0a,0x0a,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x09,0x0a,0x0b,0x08,0x08,0x0b, 0x0c,0x05,0x06,0x09,0x08,0x0e,0x0c,0x0c,0x09,0x0c,0x09,0x08,0x08,0x0b,0x0a,0x0f,0x0a,0x09,0x09,0x0d,0x0f,0x08,0x0c,0x09,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08,0x08,0x05,0x05,0x05,0x05,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x08, 0x08,0x0b,0x0b,0x0a,0x0c,0x0c,0x05,0x05,0x05,0x05,0x05,0x0b,0x06,0x09,0x08,0x08,0x08,0x08,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x09,0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x0f,0x0f,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0d,0x0c,0x0a,0x09,0x07,0x0a,0x08,0x09,0x0c,0x0c,0x05, 0x09,0x0a,0x0e,0x0c,0x09,0x0c,0x0c,0x09,0x09,0x08,0x09,0x0c,0x0a,0x0c,0x0c,0x0a,0x08,0x0c,0x05,0x0c,0x09,0x0c,0x05,0x09,0x08,0x0b,0x08,0x0a,0x08,0x05,0x05,0x06,0x0f,0x10,0x0c,0x09,0x09,0x0c,0x0a,0x09,0x09,0x08,0x0b,0x08,0x0e,0x08,0x0c,0x0c,0x09,0x0b,0x0e,0x0c,0x0c,0x0c,0x09,0x0a,0x08,0x09,0x0c,0x0a,0x0c,0x0a,0x0f,0x10, 0x0b,0x0d,0x09,0x0a,0x10,0x09,0x08,0x0b,0x0b,0x0c,0x11,0x11,0x0d,0x0a,0x0b,0x08,0x0b,0x0b,0x0b,0x0d,0x0a,0x0a,0x0d,0x0b,0x0b,0x07,0x0c,0x0c,0x0b,0x09,0x09,0x11,0x0e,0x09,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x07,0x12,0x0b,0x0b,0x0b,0x0c,0x0c,0x0a,0x0a,0x05,0x0e,0x0d,0x0d,0x09,0x0d,0x04,0x04,0x08,0x08,0x04,0x04,0x0c,0x08, 0x05,0x0e,0x0d,0x05,0x04,0x04,0x09,0x07,0x07,0x04,0x04,0x04,0x07,0x0d,0x09,0x06,0x0c,0x0d,0x0b,0x0b,0x09,0x0e,0x0b,0x0b,0x07,0x08,0x0a,0x08,0x04,0x04,0x07,0x0a,0x06,0x0d,0x0d,0x0d,0x11,0x0e,0x11,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x0e,0x10,0x06,0x06,0x0a,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0b,0x0a,0x0a,0x16, 0x10,0x16,0x10,0x19,0x13,0x19,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11,0x0a,0x0a,0x11,0x11,0x0a,0x0a,0x0e,0x10,0x06,0x06,0x0e,0x10,0x06,0x06,0x0e,0x10,0x06,0x06,0x13,0x0e,0x10,0x0a,0x0b,0x0b,0x0d,0x06,0x0d,0x0e,0x0a,0x0a,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x11,0x06,0x0e,0x0a, 0x0a,0x05,0x0a,0x0a,0x0a,0x0a,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x16,0x10,0x16,0x10,0x16,0x10,0x19,0x13,0x19,0x13,0x10,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x0e,0x0a,0x0a,0x0e,0x0a,0x0a,0x11, 0x0a,0x15,0x13,0x11,0x0a,0x10,0x0a,0x10,0x0a,0x10,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x0d,0x0d,0x0d,0x0d,0x0d,0x06,0x0d,0x0d,0x06,0x06,0x0d,0x06,0x0d,0x06,0x0d,0x0a,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x0a,0x06,0x06,0x06,0x06,0x00,0x16,0x10,0x19,0x13,0x11,0x0a, 0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0a,0x0a,0x08,0x16,0x10,0x13,0x13,0x11,0x11,0x11,0x0b,0x0b,0x0b,0x0b,0x0d,0x06,0x0d,0x06,0x0d,0x06,0x16,0x10,0x0b,0x0d,0x0b,0x0b,0x0b,0x0d,0x0b,0x0b,0x16,0x16,0x10,0x10,0x08,0x08,0x0b,0x0b,0x0b,0x0b,0x06,0x06,0x06,0x06,0x0e,0x10,0x06,0x06,0x0e,0x10, 0x06,0x06,0x0e,0x10,0x06,0x06,0x0b,0x0b,0x0b,0x0b,0x11,0x06,0x11,0x06,0x0b,0x0d,0x0b,0x0b,0x16,0x16,0x10,0x10,0x16,0x16,0x10,0x10,0x10,0x10,0x0a,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x00,0x05,0x05,0x06,0x05,0x00,0x00,0x00,0x10,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x0b,0x10,0x0b,0x10,0x0b,0x10,0x0b,0x10,0x0d,0x0d,0x0d,0x05,0x05,0x0a,0x08,0x0b,0x0c,0x0b,0x0a,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x0a,0x0a,0x0b,0x0c,0x0c,0x0c,0x0b,0x0b,0x0c,0x0a,0x0d,0x0e,0x0c,0x0e,0x10,0x0c,0x0f,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0a,0x09,0x0a,0x0c,0x0b,0x0d,0x0b,0x0c,0x0b,0x0b,0x0b,0x0a,0x0a,0x0e,0x0d,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x0e,0x0f,0x0e,0x0f,0x12,0x12,0x0d,0x12,0x12,0x0e,0x11,0x10,0x0b,0x0f,0x10,0x0e,0x0b,0x10,0x0e,0x0d,0x0d,0x0b,0x0c,0x0e,0x0f,0x0d,0x0c,0x0d,0x0b,0x0a,0x12,0x11,0x11,0x10,0x12,0x12,0x0d,0x12,0x12,0x0d,0x0f, 0x0f,0x0e,0x0e,0x0e,0x0c,0x11,0x0f,0x10,0x0e,0x0e,0x0b,0x0e,0x0d,0x0d,0x10,0x0e,0x0e,0x11,0x0a,0x0a,0x0b,0x0a,0x0c,0x0c,0x0d,0x0e,0x0b,0x0b,0x0b,0x0a,0x0b,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0b,0x0c,0x0b,0x0b,0x09,0x0b,0x0b,0x0b,0x0c,0x0f,0x10,0x0c,0x0c,0x0c,0x0f,0x0c,0x0d,0x0a,0x09,0x0b,0x0b,0x09,0x09, 0x0a,0x0b,0x09,0x09,0x0c,0x09,0x0a,0x09,0x0a,0x0f,0x0b,0x10,0x0a,0x0b,0x0b,0x0e,0x06,0x0f,0x0d,0x0e,0x0d,0x0b,0x0e,0x0b,0x0f,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x08,0x09,0x09,0x09,0x09,0x09,0x06,0x06,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x0c,0x05,0x05,0x05,0x06,0x06, 0x05,0x05,0x05,0x06,0x05,0x05,0x05,0x11,0x11,0x11,0x11,0x09,0x0e,0x0e,0x09,0x08,0x09,0x0a,0x0b,0x09,0x10,0x10,0x10,0x08,0x13,0x09,0x10,0x10,0x10,0x0f,0x0b,0x09,0x09,0x0f,0x0b,0x0f,0x0d,0x0a,0x09,0x08,0x13,0x08,0x0a,0x09,0x09,0x09,0x09,0x09,0x1a,0x10,0x10,0x08,0x05,0x09,0x05,0x09,0x05,0x05,0x05,0x09,0x0b,0x0b,0x0a,0x07, 0x07,0x04,0x04,0x04,0x07,0x04,0x08,0x10,0x04,0x11,0x11,0x11,0x0b,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x0d,0x16,0x16,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x09, 0x0b,0x09,0x0a,0x08,0x07,0x07,0x0d,0x0a,0x0e,0x08,0x15,0x11,0x0b,0x0b,0x12,0x0f,0x10,0x0e,0x13,0x0f,0x12,0x0f,0x0c,0x09,0x0e,0x0b,0x12,0x0e,0x0e,0x0c,0x0e,0x0b,0x10,0x0d,0x11,0x0d,0x15,0x10,0x0e,0x0b,0x0e,0x0b,0x17,0x11,0x0f,0x00,0x13,0x13,0x13,0x09,0x00,0x00,0x0b,0x0a,0x0d,0x0b,0x0a,0x08,0x14,0x11,0x12,0x10,0x0e,0x0b, 0x0d,0x0b,0x0a,0x08,0x0e,0x0b,0x0a,0x08,0x10,0x0d,0x0d,0x0b,0x13,0x10,0x0a,0x0b,0x0e,0x0e,0x0f,0x09,0x04,0x09,0x0d,0x08,0x13,0x13,0x05,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x08,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x0d,0x0e,0x05,0x04,0x05,0x04,0x0d,0x0b,0x0e,0x0c,0x0b,0x09,0x0a,0x09,0x0b,0x0b,0x08, 0x08,0x15,0x10,0x16,0x11,0x13,0x10,0x11,0x0d,0x11,0x0d,0x11,0x0d,0x0c,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0a,0x06,0x09,0x05,0x0e,0x0b,0x10,0x0d,0x19,0x13,0x0b,0x0b,0x0d,0x0d,0x0f,0x10,0x0e,0x0b,0x13,0x0f,0x0a,0x08,0x0b,0x09,0x0c,0x09,0x12,0x0e,0x0c,0x0a,0x0b,0x0b,0x0b,0x0b,0x09,0x08,0x09,0x07,0x09,0x07,0x0a,0x0a,0x06, 0x0d,0x06,0x12,0x0d,0x07,0x0b,0x0c,0x09,0x0e,0x0b,0x07,0x07,0x0b,0x0b,0x0b,0x09,0x05,0x0e,0x0b,0x07,0x07,0x0c,0x09,0x0d,0x07,0x0f,0x0b,0x0c,0x09,0x0d,0x0b,0x0b,0x09,0x0e,0x0b,0x0b,0x07,0x0a,0x08,0x0e,0x08,0x0a,0x10,0x09,0x0b,0x11,0x05,0x16,0x11,0x11,0x16,0x11,0x11,0x11,0x11,0x11,0x12,0x0a,0x09,0x0c,0x0d,0x11,0x0d,0x12, 0x05,0x09,0x0b,0x10,0x14,0x0d,0x14,0x0c,0x0c,0x0f,0x0d,0x16,0x12,0x0a,0x11,0x06,0x11,0x06,0x0b,0x0b,0x0b,0x0b,0x10,0x10,0x10,0x10,0x13,0x0a,0x0a,0x13,0x0e,0x0a,0x0a,0x0e,0x0d,0x06,0x06,0x0d,0x0b,0x0b,0x0b,0x0b,0x0e,0x06,0x06,0x10,0x0e,0x06,0x06,0x10,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x0a,0x08,0x0b,0x0a,0x0e,0x0b,0x0b,0x11,0x0d,0x0e,0x0e,0x10,0x10,0x0b,0x09,0x13,0x0f,0x14,0x10,0x0d,0x0b,0x06,0x06,0x0b,0x0c,0x08,0x0b,0x0a,0x0b,0x09,0x0e,0x0f,0x08,0x0b,0x08,0x04,0x07,0x0a,0x0a,0x04,0x04,0x03,0x04,0x07, 0x07,0x07,0x09,0x1c,0x26,0x06,0x08,0x03,0x05,0x07,0x08,0x06,0x09,0x0a,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x09,0x09,0x19,0x0a,0x0e,0x11,0x11,0x0c,0x09,0x0b,0x0e,0x0e,0x09,0x06,0x0d,0x0a,0x0d,0x0b,0x0d,0x0a,0x0a,0x0e,0x0b,0x0b,0x0a,0x0e,0x0c,0x10,0x09,0x0a,0x0c,0x06,0x0b,0x06,0x07,0x05,0x11, 0x0b,0x0b,0x0a,0x0a,0x0b,0x12,0x12,0x12,0x13,0x13,0x0a,0x09,0x05,0x0a,0x09,0x0c,0x09,0x0d,0x05,0x0b,0x0b,0x10,0x10,0x0c,0x0a,0x0b,0x0a,0x0a,0x09,0x0a,0x09,0x09,0x06,0x06,0x05,0x04,0x07,0x0b,0x0c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x05,0x05,0x05,0x05,0x05,0x20,0x13,0x11, 0x14,0x05,0x05,0x06,0x08,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x11,0x06,0x06,0x11,0x05,0x0a,0x0a,0x19,0x13,0x13,0x19,0x11,0x0a,0x0a,0x11,0x0a,0x0a,0x08,0x08,0x00,0x00,0x07,0x0e,0x0b,0x0d,0x0b,0x18,0x14,0x0d,0x0a,0x0d,0x0a,0x19,0x13,0x0e,0x0b,0x07,0x06,0x0c,0x00,0x0d,0x0a,0x06,0x06,0x03,0x09, 0x06,0x07,0x05,0x04,0x09,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x04,0x0a,0x08,0x0b,0x0b,0x0a,0x12,0x0f,0x0f,0x0f,0x10,0x12,0x0c,0x0d,0x0b,0x07,0x12,0x15,0x08,0x16,0x0a,0x10,0x11,0x11,0x11,0x08,0x0e,0x13,0x0e,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x0b,0x0b,0x0b,0x10,0x0a, 0x0a,0x11,0x06,0x06,0x11,0x06,0x06,0x11,0x09,0x09,0x00,0x08,0x10,0x06,0x06,0x13,0x0a,0x0a,0x0e,0x0a,0x0a,0x0d,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x1d,0x1d,0x11,0x00,0x00,0x11,0x11,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0c,0x0c,0x0c, 0x11,0x0c,0x0c,0x0f,0x13,0x0c,0x0c,0x14,0x0c,0x0c,0x12,0x0c,0x0d,0x0f,0x0c,0x0f,0x10,0x11,0x0c,0x0f,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0d,0x0c,0x0f,0x0b,0x0d,0x0f,0x0c,0x0c,0x0b,0x0f,0x0c,0x0c,0x0c,0x0d,0x08,0x0a,0x0c,0x0f,0x0f,0x0a,0x00,0x00,0x15,0x2a,0x0e,0x00,0x02,0x06,0x06,0x08,0x0c,0x0b,0x11,0x11,0x05,0x06,0x06,0x09, 0x0e,0x05,0x08,0x05,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x05,0x05,0x0e,0x0e,0x0e,0x09,0x14,0x0e,0x0c,0x0d,0x0f,0x0b,0x0a,0x0e,0x0f,0x06,0x08,0x0c,0x0a,0x13,0x10,0x10,0x0c,0x10,0x0d,0x0b,0x0b,0x0e,0x0d,0x14,0x0c,0x0c,0x0c,0x06,0x08,0x06,0x0e,0x09,0x06,0x0b,0x0c,0x0a,0x0c,0x0b,0x07,0x0c,0x0c,0x05,0x05, 0x0a,0x05,0x12,0x0c,0x0c,0x0c,0x0c,0x07,0x09,0x07,0x0c,0x0a,0x0f,0x0a,0x0a,0x0a,0x06,0x05,0x06,0x0e,0x0e,0x0e,0x0d,0x0b,0x10,0x10,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x0b,0x0b,0x05,0x05,0x05,0x05,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x08,0x08,0x0b,0x0b,0x09,0x09,0x0a,0x0b,0x08,0x13,0x13,0x10, 0x06,0x09,0x0e,0x12,0x10,0x11,0x0e,0x0e,0x0e,0x0b,0x0c,0x0b,0x0d,0x10,0x0b,0x08,0x09,0x10,0x11,0x0c,0x09,0x06,0x06,0x0e,0x0e,0x0b,0x0e,0x0e,0x0b,0x0b,0x0f,0x0e,0x0e,0x10,0x14,0x13,0x0b,0x15,0x08,0x08,0x05,0x05,0x0e,0x0c,0x0a,0x0c,0x04,0x0b,0x07,0x07,0x0c,0x0c,0x08,0x05,0x05,0x08,0x19,0x0e,0x0b,0x0e,0x0b,0x0b,0x06,0x06, 0x06,0x06,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x05,0x08,0x07,0x07,0x06,0x04,0x06,0x04,0x07,0x04,0x08,0x0a,0x06,0x0b,0x09,0x0c,0x0a,0x05,0x0f,0x0c,0x0c,0x0a,0x0c,0x0c,0x0e,0x0e,0x07,0x08,0x08,0x14,0x13,0x14,0x0a,0x0e,0x0c,0x06,0x0b,0x09,0x0d,0x0a,0x0d,0x0a,0x0c,0x09,0x05,0x0e,0x0b,0x0e,0x0b,0x0f,0x0e,0x0f,0x0b,0x0b,0x0b,0x0b, 0x0a,0x05,0x0a,0x06,0x0a,0x07,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x0d,0x07,0x0d,0x07,0x0b,0x09,0x0b,0x07,0x0b,0x09,0x0e,0x0c,0x0e,0x0c,0x0c,0x0a,0x0c,0x0a,0x0a,0x10,0x10,0x0d,0x0c,0x09,0x0c,0x0a,0x0f,0x09,0x0a,0x08,0x17,0x0d,0x0a,0x0d,0x05,0x08,0x11,0x07,0x0d,0x07,0x07,0x0d,0x07,0x0e,0x0b,0x0d,0x0a,0x0d,0x0a,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0f,0x0c,0x0f,0x0c,0x06,0x05,0x06,0x05,0x06,0x05,0x06,0x05,0x08,0x05,0x0c,0x0a,0x0a,0x0a,0x05,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x0d,0x07,0x0b,0x09,0x0b,0x07,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x14,0x0f,0x0c,0x0a,0x05,0x0e,0x0b,0x12,0x11,0x10,0x0c,0x05,0x14,0x0f, 0x14,0x0f,0x14,0x0f,0x0c,0x0a,0x05,0x09,0x0b,0x0d,0x13,0x13,0x14,0x13,0x08,0x08,0x05,0x06,0x06,0x0e,0x0c,0x10,0x08,0x11,0x0e,0x11,0x06,0x0e,0x0c,0x0b,0x0c,0x0f,0x06,0x0c,0x0d,0x13,0x10,0x0b,0x10,0x0f,0x0c,0x0b,0x0b,0x0c,0x0c,0x10,0x10,0x06,0x0c,0x0d,0x09,0x0c,0x06,0x0c,0x0c,0x0b,0x09,0x0c,0x0c,0x06,0x0b,0x0a,0x0c,0x0b, 0x09,0x0c,0x0c,0x0a,0x0c,0x0b,0x10,0x11,0x06,0x0c,0x0c,0x0c,0x11,0x0b,0x0f,0x0a,0x0d,0x0b,0x06,0x15,0x15,0x0f,0x0c,0x0c,0x0f,0x0e,0x0c,0x0c,0x0a,0x0f,0x0b,0x12,0x0b,0x10,0x10,0x0c,0x0e,0x13,0x0f,0x10,0x0f,0x0c,0x0d,0x0b,0x0c,0x0f,0x0c,0x10,0x0e,0x14,0x15,0x0f,0x10,0x0c,0x0d,0x15,0x0c,0x0b,0x0c,0x0b,0x08,0x0b,0x0b,0x10, 0x09,0x0c,0x0c,0x0a,0x0b,0x0f,0x0c,0x0c,0x0c,0x0c,0x0a,0x09,0x0a,0x0e,0x0a,0x0d,0x0c,0x11,0x11,0x0c,0x0f,0x0b,0x0a,0x11,0x0b,0x0b,0x0c,0x08,0x0a,0x09,0x05,0x11,0x11,0x0c,0x0a,0x0a,0x0c,0x0a,0x08,0x15,0x18,0x0d,0x07,0x08,0x08,0x08,0x05,0x0b,0x09,0x0c,0x10,0x0d,0x0f,0x0c,0x06,0x07,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x06,0x06, 0x06,0x0a,0x06,0x0a,0x06,0x06,0x06,0x0a,0x0a,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x06,0x05,0x06,0x05,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10, 0x0c,0x10,0x0c,0x10,0x0d,0x10,0x0d,0x10,0x0d,0x10,0x0d,0x10,0x0d,0x0e,0x0c,0x0e,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0b,0x07,0x0b,0x0b,0x10,0x0c,0x06,0x08,0x05,0x05,0x0b,0x09,0x13,0x10,0x0d,0x0b,0x0c,0x0a,0x10,0x0d,0x0c,0x0a,0x0c,0x0a,0x0d,0x0a,0x0e,0x0c,0x0e,0x0c,0x0f, 0x0b,0x10,0x0c,0x06,0x06,0x06,0x06,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x06,0x06,0x0b,0x0b,0x0e,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x0a,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x07,0x0e,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f, 0x0c,0x06,0x05,0x06,0x05,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x0a,0x05,0x13,0x12,0x13,0x12,0x13,0x12,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b,0x09,0x0b, 0x07,0x0b,0x07,0x0b,0x07,0x0b,0x07,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0d,0x0a,0x0d,0x0a,0x14,0x0f,0x14,0x0f,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x07,0x0f,0x0a,0x0b,0x05,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x10,0x10,0x10,0x10,0x10,0x10,0x09,0x09,0x09,0x09,0x09, 0x09,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x14,0x14,0x14,0x14,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x14,0x14,0x14,0x14,0x14,0x0d,0x0d,0x09,0x09,0x0c,0x0c,0x06,0x06,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x10,0x10,0x10,0x10,0x10,0x10,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x14,0x14,0x14,0x14,0x14,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x0f,0x0c,0x0c,0x0c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x08,0x08,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0e,0x0e,0x0d,0x0c,0x0c,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x11,0x10,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0d,0x0c,0x0c,0x0c,0x0c,0x0d,0x0d,0x0a,0x0f,0x10,0x0c,0x0c,0x0c,0x0b,0x0b,0x0a,0x0f,0x0d,0x12,0x06,0x06,0x0c,0x0a,0x05,0x0a,0x13,0x10,0x0c,0x10, 0x14,0x11,0x0d,0x0c,0x0c,0x0b,0x09,0x0b,0x06,0x07,0x0b,0x07,0x0b,0x10,0x0f,0x0c,0x0b,0x0c,0x0a,0x0d,0x0d,0x09,0x09,0x0b,0x0b,0x08,0x08,0x0b,0x05,0x08,0x0a,0x06,0x1a,0x18,0x16,0x12,0x0f,0x0b,0x17,0x14,0x11,0x0e,0x0b,0x06,0x05,0x10,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0b,0x0e,0x0b,0x0e,0x0b,0x12,0x11, 0x0e,0x0c,0x0e,0x0c,0x0c,0x0a,0x10,0x0c,0x10,0x0c,0x0d,0x09,0x05,0x1a,0x18,0x16,0x0e,0x0c,0x15,0x0e,0x10,0x0c,0x0e,0x0b,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x06,0x05,0x06,0x05,0x10,0x0c,0x10,0x0c,0x0c,0x07,0x0d,0x07,0x0e,0x0c,0x0e,0x0c,0x0b,0x09,0x0f,0x0c,0x0f,0x0c,0x0c,0x0c,0x0a,0x0e,0x0b,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10, 0x0c,0x0c,0x0a,0x0c,0x0b,0x0c,0x0c,0x0c,0x0b,0x0c,0x0c,0x0c,0x0a,0x0a,0x0c,0x0c,0x0b,0x0d,0x09,0x09,0x0b,0x0c,0x06,0x0c,0x0c,0x0b,0x0a,0x0a,0x0c,0x0c,0x0c,0x06,0x06,0x07,0x06,0x08,0x05,0x0d,0x12,0x12,0x12,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0d,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x08,0x05,0x05,0x06,0x06,0x07,0x07, 0x0d,0x0c,0x0c,0x0a,0x0f,0x0a,0x09,0x0a,0x0b,0x09,0x09,0x08,0x08,0x08,0x0a,0x0d,0x0a,0x0c,0x0b,0x0c,0x05,0x0a,0x08,0x0c,0x08,0x08,0x13,0x14,0x15,0x0d,0x0a,0x0f,0x11,0x0c,0x0c,0x0a,0x0a,0x0c,0x0c,0x0c,0x0e,0x0c,0x0d,0x11,0x0c,0x0f,0x0c,0x0c,0x0a,0x0a,0x09,0x0d,0x0b,0x0d,0x0a,0x13,0x12,0x0d,0x0b,0x0d,0x0b,0x0d,0x0a,0x0d, 0x0a,0x0e,0x0c,0x0c,0x09,0x0c,0x0c,0x0a,0x05,0x10,0x0a,0x0a,0x12,0x0e,0x0e,0x0c,0x13,0x0f,0x0e,0x0a,0x12,0x0f,0x0f,0x0c,0x14,0x10,0x0b,0x09,0x10,0x10,0x10,0x0c,0x0f,0x0c,0x0f,0x0c,0x1c,0x17,0x11,0x0e,0x18,0x13,0x12,0x0e,0x0c,0x09,0x0b,0x08,0x09,0x00,0x00,0x15,0x14,0x0c,0x0b,0x0c,0x0c,0x0c,0x0b,0x0b,0x0a,0x0c,0x0a,0x0f, 0x0c,0x12,0x0e,0x15,0x12,0x0f,0x0c,0x0d,0x0a,0x0b,0x09,0x12,0x0e,0x0e,0x0c,0x12,0x0d,0x12,0x0d,0x06,0x12,0x10,0x0c,0x0b,0x0f,0x0c,0x0e,0x0c,0x0e,0x0b,0x0e,0x0b,0x12,0x11,0x0b,0x0b,0x0f,0x0b,0x0f,0x0b,0x12,0x10,0x0b,0x09,0x0b,0x09,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x10,0x0c,0x0d,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0e,0x0c, 0x10,0x0f,0x0c,0x0c,0x12,0x12,0x11,0x0f,0x0c,0x0a,0x13,0x11,0x15,0x12,0x0f,0x0b,0x0e,0x0d,0x0c,0x0c,0x0c,0x0b,0x0c,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,0x0c,0x07,0x07,0x03,0x04,0x04,0x04,0x06,0x08,0x06,0x05,0x08,0x05,0x05,0x05,0x07,0x07,0x05,0x05,0x0c,0x0c,0x0c,0x0c,0x07,0x06, 0x06,0x07,0x07,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x03,0x05,0x06,0x05,0x08,0x08,0x08,0x08,0x08,0x07,0x07,0x07,0x09,0x07,0x05,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b, 0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b, 0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x0e,0x06,0x0d,0x07,0x0c,0x0c,0x07,0x07,0x07,0x07,0x07,0x06,0x07,0x07,0x07,0x06, 0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x0e,0x11,0x0a,0x0a,0x0c,0x0c,0x09,0x09,0x05,0x06,0x0a,0x08,0x0f,0x0c,0x0c,0x0a,0x0d,0x0d,0x0d,0x14,0x0b,0x0c,0x0c,0x0a,0x0a,0x0a,0x09,0x0b,0x0c,0x0f,0x0c,0x0a,0x0f,0x0a,0x09,0x09,0x0b,0x08,0x0a,0x0c,0x0a,0x0c,0x0c, 0x08,0x0a,0x07,0x08,0x09,0x06,0x06,0x09,0x09,0x04,0x05,0x07,0x06,0x0b,0x09,0x09,0x09,0x08,0x07,0x07,0x06,0x09,0x0b,0x07,0x07,0x07,0x0a,0x07,0x07,0x07,0x07,0x06,0x06,0x07,0x03,0x06,0x0a,0x07,0x07,0x06,0x07,0x07,0x07,0x04,0x07,0x07,0x0a,0x06,0x07,0x07,0x06,0x07,0x09,0x06,0x03,0x04,0x07,0x06,0x07,0x06,0x07,0x09,0x06,0x0c, 0x03,0x07,0x0b,0x12,0x0d,0x0b,0x0b,0x12,0x0e,0x12,0x10,0x0b,0x0c,0x0b,0x09,0x18,0x0a,0x0c,0x13,0x14,0x14,0x0d,0x0e,0x0d,0x0a,0x0a,0x0b,0x09,0x0a,0x0b,0x04,0x00,0x00,0x00,0x00,0x0c,0x0d,0x0d,0x0d,0x0a,0x08,0x0c,0x0c,0x07,0x12,0x0c,0x0c,0x07,0x07,0x0a,0x07,0x0a,0x0c,0x0a,0x0c,0x13,0x0e,0x07,0x06,0x0c,0x0b,0x0c,0x0c,0x0c, 0x07,0x0c,0x0a,0x05,0x12,0x0c,0x0c,0x07,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0c,0x0c,0x0b,0x09,0x09,0x0f,0x05,0x0a,0x05,0x0c,0x09,0x07,0x06,0x06,0x07,0x06,0x04,0x03,0x07,0x07,0x03,0x04,0x04,0x04,0x03,0x04,0x03,0x05,0x0a,0x0a,0x07,0x07,0x07,0x07,0x08,0x05,0x03,0x04,0x07,0x07,0x07,0x07,0x06,0x05,0x05,0x06,0x05,0x07,0x00,0x00, 0x00,0x00,0x05,0x07,0x07,0x07,0x06,0x07,0x0b,0x0b,0x0b,0x0b,0x07,0x00,0x00,0x00,0x00,0x0a,0x07,0x06,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x06,0x06,0x06,0x06,0x0c,0x0c,0x0c,0x0c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x0b,0x08, 0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x04,0x08,0x08,0x07,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x08,0x07,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x10,0x0d,0x0f,0x0c,0x10,0x0d,0x14,0x10,0x0b,0x08,0x0b,0x0e,0x0b,0x11,0x0f,0x00,0x00,0x00,0x00,0x05,0x05,0x05,0x05,0x07,0x07,0x07, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x12,0x12,0x15,0x09,0x05,0x0b,0x0c,0x09,0x0b,0x0b,0x0c,0x0c,0x0b,0x15,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0e,0x0b,0x0b,0x0b,0x07,0x0c,0x07,0x10,0x0e,0x0b,0x07,0x12,0x0b,0x12,0x05,0x07,0x0c,0x0c,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x12,0x05,0x0c,0x05,0x0b,0x09,0x05,0x05,0x0b,0x05,0x10,0x05, 0x13,0x0b,0x13,0x13,0x0c,0x0c,0x0c,0x0b,0x0b,0x09,0x09,0x19,0x19,0x1c,0x1c,0x12,0x12,0x0b,0x0b,0x04,0x15,0x10,0x12,0x0e,0x0c,0x0e,0x0b,0x0b,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x05,0x0e,0x00,0x0e,0x0e,0x0e,0x07,0x0b,0x0b,0x13,0x07,0x13,0x07,0x0c,0x0e,0x0c,0x09,0x13,0x0b,0x13,0x0b,0x10,0x12,0x07,0x0b, 0x0b,0x09,0x05,0x0b,0x0c,0x0b,0x0c,0x0b,0x0c,0x0c,0x0b,0x0e,0x0e,0x13,0x07,0x0b,0x09,0x0e,0x0b,0x07,0x0b,0x0b,0x0b,0x13,0x07,0x13,0x07,0x05,0x0c,0x08,0x15,0x0b,0x0b,0x0e,0x0e,0x15,0x0b,0x00,0x00,0x00,0x0e,0x00,0x0e,0x0e,0x0e,0x0e,0x10,0x0e,0x00,0x00,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x09,0x0b,0x0b,0x10,0x12,0x13,0x07, 0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x0b,0x09,0x09,0x09,0x19,0x12,0x19,0x12,0x19,0x12,0x1c,0x15,0x1c,0x15,0x12,0x0b,0x0c,0x0c,0x0c,0x15,0x15,0x0b,0x0b,0x15,0x0b, 0x0b,0x15,0x0b,0x0b,0x15,0x0b,0x0b,0x10,0x10,0x17,0x15,0x13,0x0b,0x12,0x0b,0x12,0x0b,0x12,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x0e,0x07,0x0e,0x07,0x0b,0x0e,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x12,0x13,0x10,0x12,0x07,0x0b,0x10,0x12,0x10, 0x12,0x00,0x00,0x00,0x00,0x00,0x18,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x09,0x00,0x00,0x0d,0x00,0x00,0x00,0x19,0x12,0x1c,0x15,0x0b,0x0c,0x0c,0x0c,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x13,0x13,0x08,0x0c,0x0c,0x0c,0x1a,0x11,0x0b,0x20,0x17,0x07,0x0c,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x0b,0x09,0x09,0x10,0x0e,0x0e,0x0b,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x1a,0x20,0x00,0x00,0x00,0x00,0x00,0x0c,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x09,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0c,0x0c,0x0e,0x0c,0x0b,0x0b,0x09,0x19,0x12,0x0b,0x0c,0x0c, 0x0c,0x0b,0x0c,0x0c,0x0c,0x0b,0x0c,0x0c,0x0c,0x15,0x0b,0x0b,0x15,0x0b,0x0b,0x13,0x0b,0x0b,0x13,0x0b,0x0b,0x13,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x0e,0x07,0x07,0x09,0x09,0x19,0x12,0x0e,0x0c,0x0c,0x00,0x0b,0x0b,0x0b,0x08,0x0c,0x0e,0x0d,0x0b,0x0b,0x08,0x05,0x10,0x0c,0x0d,0x07,0x0c,0x0a,0x0a, 0x0a,0x0a,0x05,0x0b,0x09,0x0d,0x0a,0x0c,0x0a,0x0b,0x09,0x0e,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x09,0x0a,0x0a,0x06,0x0b,0x0c,0x0d,0x0b,0x07,0x10,0x0c,0x0d,0x0b,0x0d,0x0a,0x0c,0x0b,0x08,0x0f,0x08,0x09,0x09,0x0a,0x0d,0x0d,0x0b,0x15,0x0b,0x15,0x07,0x05,0x04,0x0b,0x05,0x03,0x00,0x03,0x05,0x00,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x13,0x09,0x10,0x0c,0x14,0x0f,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x13,0x12,0x0a,0x12,0x0a,0x12,0x0e,0x0e,0x0f,0x0f,0x10,0x12,0x15,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x0e,0x0e,0x0e,0x10,0x0c,0x16,0x11,0x0a,0x0a,0x06,0x06,0x06,0x08,0x05, 0x0c,0x05,0x05,0x12,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x05,0x00,0x00,0x0d,0x0c,0x09,0x0a,0x0e,0x06,0x07,0x0e,0x0e,0x06,0x0c,0x0b,0x0c,0x0f,0x0e,0x06,0x08,0x0e,0x0d,0x0d,0x0d,0x0c,0x0c,0x0e,0x0c,0x10,0x0f,0x0b,0x0b,0x0b,0x05,0x08,0x0c,0x0c,0x0c,0x0c,0x0b,0x0d, 0x0d,0x0a,0x0e,0x0b,0x0c,0x0f,0x0c,0x0f,0x0c,0x10,0x10,0x10,0x10,0x0d,0x0d,0x0d,0x0c,0x09,0x0a,0x0e,0x06,0x07,0x0e,0x06,0x0c,0x0b,0x0c,0x0e,0x08,0x0e,0x0d,0x0d,0x0c,0x0e,0x0c,0x10,0x0f,0x06,0x0c,0x0b,0x0d,0x0e,0x19,0x00,0x0d,0x0c,0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x06,0x00,0x10,0x0d,0x0e,0x0f,0x0c,0x0e,0x10,0x10,0x0a,0x0d,0x10,0x0f,0x0e,0x10,0x11,0x10,0x0e,0x0c,0x0c,0x10,0x0f,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x0c,0x0d,0x0e,0x0e,0x10,0x0d,0x0d,0x0d,0x0e,0x11,0x0a,0x0c,0x0c,0x12,0x0b,0x0b, 0x10,0x13,0x0d,0x0b,0x16,0x0c,0x0c,0x10,0x0b,0x0b,0x10,0x0c,0x10,0x11,0x12,0x0b,0x10,0x0b,0x0e,0x0b,0x0d,0x0c,0x0d,0x0b,0x0d,0x10,0x0b,0x0d,0x0e,0x0b,0x0b,0x0d,0x14,0x0b,0x0b,0x0c,0x0c,0x09,0x07,0x0c,0x0c,0x0c,0x0b,0x0c,0x13,0x0c,0x13,0x0a,0x0c,0x13,0x0e,0x0c,0x13,0x10,0x10,0x13,0x0c,0x0c,0x13,0x13,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x13,0x13,0x0c,0x0c,0x0c,0x13,0x0d,0x0b,0x0c,0x0c,0x13,0x10,0x0e,0x0f,0x0f,0x0e,0x0f,0x0d,0x0e,0x10,0x0f,0x0e,0x0b,0x11,0x0e,0x0e,0x0c,0x0e,0x0f,0x10,0x0f,0x0c,0x0f,0x0e,0x0f,0x0e,0x10,0x0f,0x0f,0x0f,0x0e,0x0d,0x0f,0x0e,0x0f,0x11,0x0e,0x10,0x0f,0x02,0x02,0x03,0x04,0x03,0x06,0x07,0x12,0x0c,0x0d,0x0d,0x0c,0x0d, 0x0c,0x0c,0x0e,0x0d,0x0c,0x06,0x12,0x0c,0x0c,0x0c,0x0b,0x0d,0x0b,0x0c,0x06,0x0c,0x0b,0x0c,0x09,0x12,0x0c,0x0c,0x0c,0x0c,0x11,0x0c,0x0c,0x08,0x11,0x0c,0x0c,0x0e,0x0e,0x05,0x06,0x18,0x18,0x18,0x18,0x1e,0x0b,0x0b,0x05,0x0b,0x08,0x0b,0x0b,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x08,0x0b,0x0b,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0a,0x0b,0x0c,0x09,0x09,0x0c,0x0d,0x05,0x07,0x0a,0x09,0x10,0x0e,0x0d,0x0a,0x0d,0x0a,0x09,0x09,0x0c,0x0b,0x11,0x0b,0x0a,0x0a,0x0f,0x10,0x09,0x0d,0x0a,0x0c,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x09,0x05,0x05,0x05,0x05,0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c,0x0c,0x0c,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0b,0x0d,0x0d,0x05,0x05,0x05,0x05,0x05,0x0c,0x07,0x0a,0x09,0x09,0x09,0x09,0x0e,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0a,0x0a,0x0a, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x11,0x11,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0f,0x0d,0x0b,0x0a,0x08,0x0b,0x09,0x0a,0x0d,0x0d,0x05,0x0a,0x0b,0x10,0x0e,0x09,0x0d,0x0d,0x0a,0x0a,0x09,0x0a,0x0d,0x0b,0x0e,0x0d,0x0b,0x09,0x0d,0x05,0x0d,0x0a,0x0d,0x05,0x0a,0x09,0x0c,0x08,0x0b, 0x09,0x05,0x05,0x07,0x11,0x11,0x0d,0x0a,0x0a,0x0d,0x0b,0x0a,0x0a,0x08,0x0c,0x09,0x10,0x09,0x0e,0x0e,0x0a,0x0c,0x10,0x0d,0x0d,0x0d,0x0a,0x0b,0x09,0x0a,0x0d,0x0b,0x0d,0x0b,0x11,0x11,0x0c,0x0f,0x0a,0x0b,0x12,0x0a,0x08,0x0c,0x0c,0x0d,0x13,0x13,0x0e,0x0b,0x0c,0x09,0x0c,0x0c,0x0c,0x0f,0x0b,0x0b,0x0e,0x0c,0x0c,0x08,0x0d,0x0d, 0x0c,0x0a,0x0a,0x13,0x10,0x0a,0x0b,0x0d,0x0d,0x0d,0x0d,0x0f,0x0e,0x08,0x14,0x0c,0x0c,0x0c,0x0e,0x0e,0x0b,0x0b,0x06,0x10,0x0e,0x0e,0x0a,0x0f,0x05,0x05,0x09,0x09,0x05,0x05,0x0d,0x08,0x06,0x10,0x0f,0x06,0x05,0x05,0x09,0x08,0x08,0x05,0x05,0x05,0x08,0x0e,0x0a,0x06,0x0d,0x0e,0x0c,0x0c,0x0a,0x10,0x0c,0x0d,0x07,0x09,0x0b,0x09, 0x05,0x05,0x08,0x0b,0x07,0x0e,0x0e,0x0e,0x13,0x10,0x13,0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x12,0x07,0x07,0x0b,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0c,0x0b,0x0b,0x19,0x12,0x19,0x12,0x1c,0x15,0x1c,0x15,0x12,0x12,0x12,0x12,0x12,0x12,0x13,0x13,0x0b,0x0b,0x13,0x13,0x0b,0x0b,0x10,0x12,0x07,0x07,0x10,0x12,0x07, 0x07,0x10,0x12,0x07,0x07,0x15,0x10,0x12,0x0b,0x0c,0x0c,0x0e,0x07,0x0e,0x10,0x0b,0x0b,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x13,0x07,0x10,0x0b,0x0b,0x05,0x0b,0x0b,0x0b,0x0b,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x19,0x12,0x19,0x12,0x19,0x12,0x1c,0x15,0x1c,0x15,0x12,0x12,0x12,0x15,0x15,0x15,0x15,0x15,0x15,0x10,0x0b,0x0b,0x10,0x0b,0x0b,0x13,0x0b,0x17,0x15,0x13,0x0b,0x12,0x0b,0x12,0x0b,0x12,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x13,0x0b,0x0e,0x0e,0x0e,0x0e,0x0e, 0x07,0x0e,0x0e,0x07,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x0b,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x0b,0x07,0x07,0x07,0x07,0x00,0x19,0x12,0x1c,0x15,0x13,0x0b,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0b,0x0b,0x09,0x19,0x12,0x15,0x15,0x13,0x13,0x13,0x0c,0x0c,0x0c,0x0c, 0x0e,0x07,0x0e,0x07,0x0e,0x07,0x19,0x12,0x0c,0x0e,0x0c,0x0c,0x0c,0x0e,0x0c,0x0c,0x19,0x19,0x12,0x12,0x09,0x09,0x0c,0x0c,0x0c,0x0c,0x07,0x07,0x07,0x07,0x10,0x12,0x07,0x07,0x10,0x12,0x07,0x07,0x10,0x12,0x07,0x07,0x0c,0x0c,0x0c,0x0c,0x13,0x07,0x13,0x07,0x0c,0x0e,0x0c,0x0c,0x19,0x19,0x12,0x12,0x19,0x19,0x12,0x12,0x12,0x12, 0x0b,0x0b,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x00,0x00,0x05,0x05,0x07,0x05,0x00,0x00,0x00,0x12,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x09,0x09,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x05,0x05, 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x12,0x0c,0x12,0x0c,0x12,0x0c,0x12,0x0e,0x0e,0x0e,0x05,0x05,0x0b,0x09,0x0c,0x0d,0x0c,0x0b,0x0c,0x0c,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0c,0x0b,0x0c,0x0d,0x0d,0x0e,0x0c,0x0c,0x0e,0x0b,0x0e,0x10,0x0d,0x10,0x11,0x0d,0x10,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0a,0x0b,0x0d,0x0d,0x0e,0x0c,0x0e,0x0c,0x0c,0x0d,0x0b,0x0b,0x10,0x0e,0x0f,0x0e,0x0e,0x0c,0x0c,0x0c,0x0f,0x10,0x10,0x10,0x13, 0x13,0x0f,0x13,0x13,0x0f,0x12,0x12,0x0c,0x10,0x12,0x10,0x0c,0x12,0x10,0x0f,0x0f,0x0d,0x0e,0x10,0x11,0x0f,0x0d,0x0f,0x0c,0x0b,0x13,0x13,0x13,0x11,0x13,0x13,0x0e,0x13,0x13,0x0f,0x10,0x10,0x10,0x0f,0x0f,0x0e,0x13,0x10,0x11,0x0f,0x0f,0x0c,0x10,0x0f,0x0f,0x12,0x10,0x0f,0x13,0x0b,0x0b,0x0c,0x0b,0x0d,0x0d,0x0f,0x0f,0x0c,0x0c, 0x0c,0x0b,0x0c,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0c,0x0d,0x0d,0x0d,0x0a,0x0c,0x0c,0x0c,0x0d,0x10,0x12,0x0e,0x0e,0x0d,0x10,0x0d,0x0e,0x0b,0x0a,0x0c,0x0c,0x0a,0x0a,0x0c,0x0c,0x0a,0x0a,0x0d,0x0a,0x0b,0x0a,0x0c,0x10,0x0c,0x11,0x0b,0x0c,0x0c,0x10,0x07,0x11,0x0e,0x0f,0x0e,0x0c,0x10,0x0d,0x10,0x0d,0x0d,0x0d, 0x0d,0x0d,0x0d,0x0c,0x0d,0x0d,0x0d,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x0a,0x09,0x0a,0x0a,0x0a,0x06,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0d,0x06,0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x13,0x13,0x13,0x13,0x0a,0x10,0x0f,0x0a,0x09,0x0a,0x0b,0x0c,0x0a,0x12,0x11,0x12,0x09,0x15,0x0a,0x12,0x12, 0x12,0x11,0x0c,0x0a,0x0a,0x10,0x0c,0x10,0x0e,0x0b,0x0a,0x09,0x15,0x09,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x1d,0x12,0x12,0x09,0x05,0x0a,0x05,0x0a,0x05,0x05,0x05,0x0a,0x0c,0x0c,0x0b,0x08,0x08,0x05,0x05,0x05,0x08,0x05,0x09,0x12,0x05,0x13,0x13,0x13,0x0c,0x0c,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x19,0x19,0x0e,0x19, 0x19,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0a,0x0c,0x0a,0x0b,0x09,0x07,0x07,0x0e,0x0c,0x0f,0x09,0x18,0x13,0x0c,0x0c,0x13,0x11,0x12,0x10,0x15,0x11,0x13,0x10,0x0e,0x0a,0x0f,0x0c,0x13,0x0f, 0x10,0x0d,0x10,0x0d,0x12,0x0e,0x12,0x0e,0x17,0x12,0x10,0x0c,0x10,0x0c,0x19,0x13,0x11,0x00,0x15,0x15,0x15,0x0a,0x00,0x00,0x0c,0x0b,0x0f,0x0c,0x0b,0x09,0x17,0x13,0x14,0x12,0x0f,0x0c,0x0f,0x0c,0x0b,0x09,0x10,0x0d,0x0b,0x09,0x11,0x0e,0x0e,0x0c,0x15,0x11,0x0b,0x0c,0x0f,0x0f,0x11,0x09,0x04,0x0a,0x0e,0x09,0x15,0x15,0x05,0x00, 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x08,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x0a,0x0e,0x0f,0x06,0x04,0x06,0x04,0x0f,0x0c,0x10,0x0d,0x0c,0x0a,0x0b,0x0a,0x0c,0x0c,0x09,0x09,0x18,0x11,0x18,0x13,0x15,0x12,0x13,0x0e,0x13,0x0e,0x13,0x0e,0x0d,0x0a,0x0c,0x0a,0x0c,0x0a,0x0c,0x0a,0x0b,0x07,0x0a,0x05,0x10,0x0c,0x12, 0x0e,0x1c,0x15,0x0c,0x0c,0x0e,0x0f,0x11,0x12,0x10,0x0c,0x15,0x10,0x0b,0x08,0x0c,0x0a,0x0d,0x0a,0x14,0x0f,0x0d,0x0b,0x0c,0x0c,0x0c,0x0c,0x0a,0x08,0x0a,0x08,0x0a,0x08,0x0b,0x0b,0x06,0x0e,0x07,0x14,0x0e,0x07,0x0c,0x0d,0x0a,0x10,0x0c,0x08,0x07,0x0c,0x0c,0x0c,0x0a,0x05,0x10,0x0d,0x08,0x07,0x0d,0x0a,0x0f,0x08,0x10,0x0d,0x0d, 0x0a,0x0e,0x0c,0x0c,0x0a,0x10,0x0c,0x0d,0x07,0x0b,0x09,0x10,0x09,0x0b,0x12,0x0a,0x0c,0x13,0x06,0x18,0x13,0x13,0x19,0x13,0x13,0x13,0x12,0x13,0x13,0x0b,0x0a,0x0d,0x0f,0x13,0x0f,0x14,0x05,0x0a,0x0c,0x12,0x16,0x0f,0x16,0x0d,0x0d,0x11,0x0f,0x18,0x13,0x0b,0x13,0x07,0x13,0x07,0x0c,0x0c,0x0c,0x0c,0x12,0x12,0x12,0x12,0x15,0x0b, 0x0b,0x15,0x10,0x0b,0x0b,0x10,0x0e,0x07,0x07,0x0e,0x0c,0x0c,0x0c,0x0c,0x10,0x07,0x07,0x12,0x10,0x07,0x07,0x12,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x0b,0x08,0x0c,0x0b,0x10,0x0c,0x0c,0x12, 0x0e,0x10,0x10,0x11,0x11,0x0c,0x0a,0x15,0x11,0x16,0x12,0x0e,0x0c,0x07,0x07,0x0c,0x0e,0x09,0x0d,0x0b,0x0c,0x0a,0x10,0x11,0x08,0x0c,0x09,0x04,0x08,0x0b,0x0c,0x05,0x05,0x04,0x05,0x08,0x08,0x08,0x09,0x1f,0x2a,0x07,0x09,0x03,0x06,0x08,0x09,0x07,0x0a,0x0b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a, 0x0a,0x1c,0x0b,0x10,0x13,0x13,0x0e,0x0a,0x0c,0x0f,0x0f,0x0a,0x07,0x0e,0x0b,0x0e,0x0c,0x0e,0x0b,0x0b,0x10,0x0c,0x0c,0x0b,0x10,0x0d,0x11,0x0a,0x0b,0x0d,0x07,0x0c,0x07,0x07,0x05,0x12,0x0c,0x0c,0x0b,0x0b,0x0c,0x13,0x13,0x14,0x15,0x15,0x0c,0x0a,0x06,0x0b,0x0a,0x0d,0x0a,0x0e,0x05,0x0c,0x0d,0x12,0x12,0x0d,0x0b,0x0c,0x0b,0x0b, 0x0a,0x0b,0x0a,0x0a,0x06,0x07,0x05,0x05,0x08,0x0c,0x0d,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x00,0x06,0x06,0x06,0x05,0x05,0x23,0x15,0x12,0x16,0x06,0x06,0x07,0x08,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x13,0x07,0x07,0x13,0x05,0x0b,0x0b,0x1c,0x15,0x15, 0x1c,0x13,0x0b,0x0b,0x13,0x0b,0x0b,0x09,0x09,0x00,0x00,0x08,0x10,0x0d,0x0f,0x0c,0x1a,0x16,0x0f,0x0b,0x0f,0x0c,0x1c,0x15,0x10,0x0c,0x08,0x07,0x0d,0x00,0x0e,0x0b,0x07,0x06,0x03,0x0a,0x07,0x07,0x05,0x04,0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x05,0x0b,0x09,0x0c,0x0c,0x0c,0x14,0x11,0x11,0x11,0x11,0x14,0x0d,0x0e,0x0d, 0x08,0x14,0x18,0x09,0x18,0x0b,0x12,0x13,0x13,0x13,0x09,0x10,0x15,0x10,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x0c,0x0c,0x0c,0x12,0x0b,0x0b,0x13,0x07,0x07,0x13,0x07,0x07,0x13,0x0a,0x0a,0x00,0x09,0x12,0x07,0x07,0x15,0x0b,0x0b,0x10,0x0b,0x0b,0x0e,0x06,0x06,0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x20,0x20,0x12,0x00,0x00,0x12,0x12,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0e,0x0d,0x0e,0x0e,0x13,0x0e,0x0d,0x11,0x14,0x0e,0x0d,0x16,0x0d,0x0d,0x14,0x0d,0x0e,0x11,0x0d,0x10,0x12,0x13,0x0d,0x10,0x0e,0x0f,0x0d,0x0f,0x0d,0x0e,0x0e,0x0d, 0x10,0x0d,0x0e,0x10,0x0d,0x0d,0x0c,0x10,0x0d,0x0e,0x0e,0x0f,0x09,0x0b,0x0d,0x10,0x10,0x0b,0x00,0x00,0x18,0x30,0x10,0x00,0x02,0x07,0x07,0x09,0x0e,0x0d,0x14,0x13,0x06,0x07,0x07,0x0a,0x10,0x05,0x0a,0x05,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x05,0x05,0x10,0x10,0x10,0x0b,0x17,0x0f,0x0e,0x0f,0x11,0x0c,0x0c, 0x10,0x11,0x06,0x09,0x0e,0x0b,0x16,0x12,0x12,0x0d,0x12,0x0e,0x0d,0x0d,0x10,0x0f,0x16,0x0e,0x0d,0x0e,0x07,0x09,0x07,0x10,0x0a,0x06,0x0c,0x0e,0x0b,0x0e,0x0d,0x08,0x0e,0x0e,0x06,0x06,0x0c,0x06,0x15,0x0e,0x0e,0x0e,0x0e,0x08,0x0a,0x08,0x0e,0x0c,0x11,0x0b,0x0c,0x0b,0x07,0x06,0x07,0x10,0x0f,0x0f,0x0f,0x0c,0x12,0x12,0x10,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0d,0x0d,0x0d,0x0d,0x06,0x06,0x06,0x06,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x09,0x09,0x0d,0x0d,0x0b,0x0a,0x0b,0x0d,0x0a,0x15,0x15,0x13,0x07,0x0a,0x10,0x15,0x12,0x14,0x10,0x10,0x10,0x0d,0x0e,0x0d,0x0f,0x12,0x0d,0x09,0x0a,0x12,0x14,0x0e,0x0b,0x07,0x07,0x10,0x10,0x0d,0x10,0x0f, 0x0c,0x0c,0x12,0x0f,0x0f,0x12,0x16,0x16,0x0c,0x18,0x09,0x09,0x06,0x06,0x10,0x0e,0x0c,0x0d,0x04,0x0d,0x08,0x08,0x0d,0x0d,0x09,0x05,0x06,0x09,0x1d,0x0f,0x0c,0x0f,0x0c,0x0c,0x06,0x06,0x06,0x06,0x12,0x12,0x12,0x10,0x10,0x10,0x06,0x09,0x08,0x07,0x07,0x05,0x07,0x05,0x08,0x04,0x09,0x0b,0x07,0x0d,0x0a,0x0e,0x0b,0x06,0x11,0x0d, 0x0d,0x0c,0x0d,0x0e,0x10,0x10,0x08,0x09,0x09,0x16,0x16,0x17,0x0c,0x10,0x0e,0x06,0x0d,0x0a,0x0f,0x0b,0x0f,0x0b,0x0e,0x0a,0x05,0x0f,0x0c,0x0f,0x0c,0x11,0x10,0x11,0x0c,0x0d,0x0c,0x0d,0x0b,0x06,0x0b,0x07,0x0b,0x08,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0e,0x08,0x0e,0x08,0x0d,0x0a,0x0d,0x08,0x0d,0x0b,0x10,0x0e,0x10,0x0e,0x0e,0x0b, 0x0e,0x0b,0x0b,0x12,0x12,0x0f,0x0e,0x0b,0x0e,0x0c,0x11,0x0a,0x0c,0x09,0x1b,0x0f,0x0c,0x0f,0x06,0x09,0x13,0x08,0x0f,0x09,0x09,0x0f,0x09,0x0f,0x0c,0x0f,0x0b,0x0f,0x0b,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x11,0x0e,0x11,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x06,0x0e,0x0c,0x0c,0x0b,0x06, 0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0e,0x08,0x0d,0x0a,0x0d,0x08,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x16,0x11,0x0d,0x0c,0x06,0x0f,0x0c,0x15,0x14,0x12,0x0e,0x05,0x16,0x11,0x16,0x11,0x16,0x11,0x0d,0x0c,0x06,0x0a,0x0d,0x0e,0x16,0x16,0x16,0x15,0x09,0x09,0x05,0x07,0x07,0x0f,0x0e,0x13,0x09,0x13,0x10,0x14,0x06,0x0f, 0x0e,0x0c,0x0e,0x11,0x06,0x0e,0x0f,0x16,0x12,0x0c,0x12,0x11,0x0d,0x0c,0x0d,0x0d,0x0e,0x13,0x12,0x06,0x0d,0x0f,0x0b,0x0e,0x06,0x0d,0x0d,0x0c,0x0b,0x0e,0x0e,0x06,0x0d,0x0c,0x0e,0x0d,0x0b,0x0e,0x0e,0x0b,0x0d,0x0d,0x12,0x13,0x06,0x0d,0x0e,0x0d,0x13,0x0c,0x11,0x0b,0x0f,0x0d,0x06,0x18,0x18,0x11,0x0e,0x0e,0x11,0x0f,0x0e,0x0e, 0x0b,0x11,0x0c,0x15,0x0d,0x12,0x12,0x0e,0x10,0x16,0x11,0x12,0x11,0x0d,0x0f,0x0d,0x0e,0x11,0x0e,0x12,0x10,0x17,0x18,0x11,0x13,0x0e,0x0f,0x18,0x0e,0x0c,0x0e,0x0d,0x09,0x0d,0x0d,0x12,0x0b,0x0e,0x0e,0x0c,0x0d,0x11,0x0e,0x0e,0x0e,0x0e,0x0b,0x0a,0x0c,0x10,0x0b,0x0e,0x0e,0x13,0x14,0x0e,0x11,0x0c,0x0b,0x14,0x0c,0x0d,0x0e,0x09, 0x0b,0x0a,0x06,0x13,0x13,0x0e,0x0c,0x0c,0x0e,0x0b,0x09,0x18,0x1b,0x0f,0x08,0x09,0x09,0x09,0x06,0x0d,0x0a,0x0d,0x12,0x0e,0x11,0x0e,0x07,0x08,0x06,0x06,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x07,0x0b,0x07,0x0b,0x07,0x07,0x07,0x0b,0x0b,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f, 0x0c,0x0f,0x0c,0x0f,0x0c,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x06,0x06,0x06,0x06,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x10,0x0e,0x10,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x0d, 0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x08,0x0c,0x0d,0x12,0x0e,0x06,0x09,0x06,0x06,0x0c,0x0a,0x16,0x13,0x0f,0x0d,0x0e,0x0c,0x12,0x0e,0x0d,0x0c,0x0d,0x0c,0x0f,0x0c,0x10,0x0e,0x10,0x0e,0x11,0x0d,0x12,0x0e,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x06,0x06,0x07,0x07,0x07,0x07,0x0c,0x0d,0x0f,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0f,0x0b,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x08,0x10,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x06,0x06,0x06,0x06,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x0b,0x06,0x16,0x15,0x16,0x15,0x16,0x15,0x12,0x0e,0x12, 0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0d,0x0e,0x0d,0x0e,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0e,0x08,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x0a,0x0d,0x08,0x0d,0x08,0x0d,0x08,0x0d,0x08,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x0f,0x0c,0x0f,0x0c,0x16,0x11,0x16,0x11,0x0e,0x0b,0x0e, 0x0b,0x0d,0x0c,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x08,0x11,0x0c,0x0c,0x06,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x12,0x12,0x12,0x12,0x12,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x11,0x11,0x11,0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x16,0x16,0x16,0x16,0x16,0x16,0x06,0x06,0x06,0x06,0x06, 0x06,0x06,0x06,0x09,0x09,0x0c,0x0c,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x17,0x17,0x17,0x17,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x10,0x14,0x14,0x14,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x0f,0x0f,0x0b,0x0b,0x0e,0x0e,0x06,0x06,0x0e,0x0e,0x0d,0x0d,0x13, 0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x14,0x17,0x17,0x17,0x17,0x17,0x17,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x11,0x0e,0x0e,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x09,0x09,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x10,0x10,0x0f,0x0e,0x0e,0x0e,0x13,0x13,0x13,0x13,0x13,0x14,0x14,0x14,0x14,0x12,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0f,0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,0x0b,0x11,0x12,0x0e,0x0e,0x0e,0x0c,0x0d,0x0c,0x11,0x0f,0x15,0x07,0x07,0x0e,0x0c,0x06,0x0c,0x15,0x12,0x0e,0x12,0x17,0x13,0x0e,0x0e,0x0e,0x0d,0x0a,0x0c,0x07,0x08,0x0d,0x08,0x0d,0x12,0x11,0x0e,0x0c,0x0e,0x0b,0x0f,0x0f,0x0b,0x0a,0x0d,0x0d,0x09,0x09,0x0d, 0x06,0x09,0x0b,0x07,0x1e,0x1b,0x19,0x15,0x11,0x0c,0x1a,0x17,0x13,0x0f,0x0c,0x06,0x06,0x12,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x0d,0x0f,0x0c,0x0f,0x0c,0x15,0x14,0x10,0x0e,0x10,0x0e,0x0e,0x0c,0x12,0x0e,0x12,0x0e,0x0f,0x0b,0x06,0x1e,0x1b,0x19,0x10,0x0e,0x18,0x11,0x12,0x0e,0x0f,0x0c,0x0f,0x0c,0x0c,0x0d, 0x0c,0x0d,0x06,0x06,0x06,0x06,0x12,0x0e,0x12,0x0e,0x0e,0x08,0x0e,0x08,0x10,0x0e,0x10,0x0e,0x0c,0x0a,0x11,0x0e,0x12,0x0e,0x0e,0x0e,0x0b,0x0f,0x0c,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0d,0x0c,0x0e,0x0c,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0e,0x0b,0x0b,0x0e,0x0e,0x0d,0x0f,0x0a,0x0a,0x0c,0x0d,0x07,0x0e,0x0e,0x0d,0x0c,0x0b, 0x0e,0x0e,0x0e,0x06,0x07,0x08,0x07,0x09,0x06,0x0e,0x15,0x15,0x15,0x0d,0x0d,0x0e,0x0e,0x11,0x11,0x0f,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0a,0x06,0x06,0x07,0x07,0x08,0x08,0x0e,0x0e,0x0d,0x0c,0x11,0x0c,0x0a,0x0b,0x0c,0x0b,0x0b,0x09,0x09,0x09,0x0b,0x0f,0x0c,0x0d,0x0d,0x0e,0x06,0x0c,0x09,0x0e,0x09,0x09,0x16,0x17, 0x17,0x0f,0x0b,0x11,0x13,0x0e,0x0e,0x0c,0x0c,0x0d,0x0e,0x0e,0x10,0x0e,0x0f,0x13,0x0e,0x11,0x0e,0x0e,0x0b,0x0c,0x0b,0x0e,0x0c,0x0f,0x0c,0x15,0x15,0x0f,0x0c,0x0f,0x0d,0x0f,0x0b,0x0e,0x0c,0x10,0x0e,0x0e,0x0a,0x0e,0x0e,0x0b,0x06,0x12,0x0b,0x0b,0x15,0x10,0x10,0x0e,0x16,0x11,0x10,0x0c,0x15,0x11,0x11,0x0e,0x16,0x12,0x0d,0x0b, 0x13,0x12,0x12,0x0e,0x11,0x0e,0x11,0x0e,0x1f,0x1b,0x14,0x10,0x1b,0x15,0x15,0x10,0x0e,0x0b,0x0c,0x09,0x0a,0x00,0x00,0x18,0x17,0x0e,0x0c,0x0d,0x0e,0x0e,0x0c,0x0d,0x0b,0x0e,0x0c,0x11,0x0e,0x14,0x10,0x18,0x14,0x11,0x0d,0x0f,0x0b,0x0d,0x0a,0x15,0x10,0x10,0x0e,0x14,0x0f,0x14,0x0f,0x06,0x15,0x12,0x0e,0x0c,0x11,0x0e,0x10,0x0e, 0x0f,0x0c,0x0f,0x0c,0x15,0x14,0x0c,0x0d,0x11,0x0d,0x11,0x0d,0x15,0x12,0x0d,0x0b,0x0d,0x0b,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x0f,0x0b,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x10,0x0e,0x13,0x11,0x0e,0x0e,0x14,0x15,0x13,0x11,0x0d,0x0b,0x16,0x13,0x18,0x14,0x11,0x0d,0x10,0x0e,0x0e,0x0e,0x0e,0x0c,0x0e,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x0e,0x08,0x08,0x04,0x05,0x05,0x05,0x07,0x0a,0x07,0x06,0x09,0x05,0x05,0x05,0x08,0x08,0x05,0x05,0x0e,0x0e,0x0e,0x0e,0x08,0x07,0x06,0x08,0x07,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x07,0x08,0x08,0x07,0x04,0x06,0x07,0x05,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08, 0x0a,0x08,0x06,0x06,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d, 0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d, 0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x00,0x00,0x00,0x00,0x00,0x0f,0x07,0x0f,0x08,0x0e,0x0e,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0e,0x0b,0x10,0x14,0x0c,0x0b,0x0d,0x0d,0x0a, 0x0a,0x06,0x07,0x0c,0x09,0x11,0x0e,0x0e,0x0b,0x0f,0x0f,0x0f,0x16,0x0d,0x0e,0x0e,0x0b,0x0b,0x0b,0x0a,0x0d,0x0e,0x11,0x0e,0x0c,0x11,0x0b,0x0a,0x0a,0x0d,0x09,0x0b,0x0e,0x0b,0x0e,0x0d,0x09,0x0c,0x08,0x09,0x0a,0x07,0x07,0x0a,0x0a,0x04,0x05,0x09,0x07,0x0d,0x0b,0x0b,0x0a,0x09,0x08,0x08,0x07,0x0a,0x0d,0x08,0x08,0x08,0x0c,0x08, 0x08,0x07,0x07,0x06,0x06,0x08,0x04,0x07,0x0c,0x08,0x08,0x06,0x08,0x08,0x08,0x05,0x08,0x08,0x0c,0x07,0x08,0x08,0x07,0x08,0x0a,0x07,0x04,0x05,0x08,0x07,0x08,0x07,0x08,0x0a,0x07,0x0e,0x04,0x08,0x0d,0x15,0x0f,0x0d,0x0d,0x15,0x10,0x15,0x12,0x0d,0x0e,0x0c,0x0b,0x1b,0x0b,0x0e,0x15,0x16,0x16,0x0f,0x0f,0x0f,0x0b,0x0b,0x0d,0x0a, 0x0b,0x0c,0x05,0x00,0x00,0x00,0x00,0x0e,0x0f,0x0f,0x0f,0x0b,0x09,0x0e,0x0e,0x08,0x15,0x0e,0x0e,0x08,0x08,0x0b,0x08,0x0b,0x0e,0x0b,0x0e,0x16,0x10,0x08,0x06,0x0e,0x0d,0x0e,0x0e,0x0e,0x08,0x0e,0x0c,0x06,0x15,0x0e,0x0e,0x08,0x0a,0x0a,0x0c,0x0b,0x0b,0x0c,0x0e,0x0e,0x0d,0x0b,0x0b,0x12,0x06,0x0b,0x06,0x0e,0x0b,0x08,0x06,0x06, 0x08,0x06,0x04,0x04,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x0c,0x0c,0x08,0x08,0x08,0x08,0x09,0x06,0x04,0x05,0x08,0x08,0x08,0x08,0x07,0x06,0x06,0x07,0x06,0x08,0x00,0x00,0x00,0x00,0x05,0x08,0x07,0x08,0x06,0x07,0x0d,0x0d,0x0d,0x0d,0x08,0x00,0x00,0x00,0x00,0x0b,0x07,0x06,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x06,0x06,0x06,0x06,0x0d,0x0d,0x0d,0x0d,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0d,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x04,0x09,0x09,0x08,0x09,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x09,0x08,0x09,0x09,0x08, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x07,0x07,0x13,0x0f,0x11,0x0e,0x12,0x0f,0x16,0x12,0x0d,0x09,0x0c,0x10,0x0d,0x14,0x11,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x08,0x08,0x08,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x14,0x14,0x18,0x0a,0x06,0x0c,0x0e,0x0a,0x0c,0x0c,0x0e,0x0e,0x0c,0x18,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c, 0x10,0x0c,0x0c,0x0c,0x08,0x0e,0x08,0x12,0x10,0x0c,0x08,0x14,0x0c,0x14,0x06,0x08,0x0e,0x0e,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x14,0x06,0x0e,0x06,0x0c,0x0a,0x06,0x06,0x0c,0x06,0x12,0x06,0x16,0x0c,0x16,0x16,0x0e,0x0e,0x0e,0x0c,0x0c,0x0a,0x0a,0x1c,0x1c,0x20,0x20,0x14,0x14,0x0c,0x0c,0x04,0x18,0x12,0x14,0x10,0x0e,0x10,0x0c,0x0c, 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x06,0x10,0x00,0x10,0x10,0x10,0x08,0x0c,0x0c,0x16,0x08,0x16,0x08,0x0e,0x10,0x0e,0x0a,0x16,0x0c,0x16,0x0c,0x12,0x14,0x08,0x0c,0x0c,0x0a,0x06,0x0c,0x0e,0x0c,0x0e,0x0c,0x0e,0x0e,0x0c,0x10,0x10,0x16,0x08,0x0c,0x0a,0x10,0x0c,0x08,0x0c,0x0c,0x0c,0x16,0x08,0x16,0x08,0x06, 0x0e,0x09,0x18,0x0c,0x0c,0x10,0x10,0x18,0x0c,0x00,0x00,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x12,0x10,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0c,0x0c,0x12,0x14,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x10,0x0e, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0c,0x0a,0x0a,0x0a,0x1c,0x14,0x1c,0x14,0x1c,0x14,0x20,0x18,0x20,0x18,0x14,0x0c,0x0e,0x0e,0x0e,0x18,0x18,0x0c,0x0c,0x18,0x0c,0x0c,0x18,0x0c,0x0c,0x18,0x0c,0x0c,0x12,0x12,0x1a,0x18,0x16,0x0c,0x14,0x0c,0x14,0x0c,0x14,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x16, 0x0c,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0x10,0x08,0x0d,0x10,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x14,0x16,0x12,0x14,0x08,0x0c,0x12,0x14,0x12,0x14,0x00,0x00,0x00,0x00,0x00,0x1b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0a,0x00,0x00,0x0e,0x00,0x00,0x00,0x1c,0x14,0x20,0x18,0x0c,0x0e, 0x0e,0x0e,0x0a,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x16,0x16,0x09,0x0e,0x0e,0x0e,0x1d,0x14,0x0d,0x25,0x1a,0x08,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x0a,0x12,0x10,0x10,0x0c,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x1e,0x24,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x0a,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x0e,0x0e,0x0e,0x0e,0x10,0x0e,0x0c,0x0c,0x0a,0x1c,0x14,0x0c,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0e,0x18,0x0c,0x0c,0x18,0x0c,0x0c,0x16,0x0c,0x0c,0x16,0x0c,0x0c,0x16,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e, 0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0x08,0x0a,0x0a,0x1c,0x14,0x10,0x0e,0x0e,0x00,0x0c,0x0c,0x0c,0x09,0x0e,0x10,0x0f,0x0c,0x0d,0x09,0x06,0x12,0x0e,0x0e,0x08,0x0d,0x0c,0x0b,0x0b,0x0b,0x06,0x0c,0x0a,0x0f,0x0c,0x0e,0x0b,0x0d,0x0b,0x10,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x0b,0x0b,0x0b,0x07,0x0c, 0x0d,0x0e,0x0c,0x08,0x12,0x0e,0x0f,0x0d,0x0f,0x0c,0x0e,0x0c,0x0a,0x11,0x09,0x0a,0x0a,0x0c,0x0e,0x0e,0x0c,0x18,0x0c,0x18,0x08,0x06,0x04,0x0d,0x05,0x03,0x00,0x03,0x05,0x00,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x16,0x0a,0x12,0x0e,0x16,0x11,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x16,0x16,0x15,0x0b,0x15,0x0b,0x15,0x0f,0x10,0x11,0x11,0x12,0x15,0x18,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x10,0x10,0x10,0x10,0x12,0x0e,0x19,0x14,0x0b,0x0b,0x07,0x07,0x07,0x09,0x05,0x0e,0x06,0x06,0x14,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x05,0x00,0x00,0x05,0x00,0x00,0x0f,0x0e, 0x0b,0x0c,0x10,0x06,0x08,0x10,0x10,0x06,0x0d,0x0d,0x0d,0x11,0x10,0x06,0x0a,0x10,0x0f,0x0f,0x0f,0x0e,0x0e,0x10,0x0d,0x13,0x11,0x0d,0x0d,0x0d,0x06,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0f,0x0f,0x0c,0x10,0x0d,0x0d,0x11,0x0d,0x11,0x0d,0x13,0x13,0x13,0x13,0x0f,0x0f,0x0f,0x0e,0x0b,0x0c,0x10,0x07,0x09,0x10,0x07,0x0d,0x0d,0x0d,0x10, 0x0a,0x10,0x0f,0x0f,0x0e,0x10,0x0d,0x13,0x11,0x06,0x0e,0x0d,0x0f,0x10,0x1d,0x00,0x0f,0x0d,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x06,0x00,0x12,0x0f,0x10,0x11,0x0d,0x10,0x12,0x12, 0x0b,0x0f,0x12,0x12,0x10,0x12,0x13,0x13,0x10,0x0d,0x0d,0x12,0x11,0x0e,0x10,0x10,0x10,0x10,0x10,0x12,0x0e,0x0f,0x10,0x10,0x13,0x0f,0x0f,0x0f,0x10,0x14,0x0c,0x0e,0x0e,0x15,0x0d,0x0d,0x13,0x15,0x0f,0x0d,0x19,0x0e,0x0e,0x12,0x0d,0x0d,0x12,0x0d,0x12,0x14,0x15,0x0d,0x13,0x0d,0x10,0x0d,0x0f,0x0e,0x0f,0x0d,0x0f,0x12,0x0d,0x0f, 0x10,0x0d,0x0d,0x0e,0x17,0x0d,0x0d,0x0e,0x0e,0x0a,0x08,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x0d,0x15,0x0c,0x0d,0x15,0x10,0x0d,0x15,0x12,0x12,0x15,0x0e,0x0d,0x15,0x15,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x15,0x0e,0x0d,0x0e,0x15,0x0e,0x0d,0x0d,0x0d,0x15,0x13,0x10,0x11,0x11,0x10,0x11,0x0f,0x10,0x13,0x11,0x10,0x0d,0x13,0x10,0x10, 0x0e,0x10,0x11,0x12,0x11,0x0e,0x11,0x10,0x11,0x10,0x13,0x11,0x11,0x11,0x10,0x0f,0x11,0x10,0x11,0x13,0x10,0x12,0x11,0x02,0x03,0x04,0x05,0x04,0x06,0x08,0x15,0x0e,0x0f,0x0e,0x0e,0x0f,0x0e,0x0e,0x10,0x0e,0x0e,0x07,0x14,0x0e,0x0e,0x0e,0x0d,0x0e,0x0c,0x0e,0x06,0x0e,0x0c,0x0e,0x0a,0x15,0x0d,0x0e,0x0e,0x0e,0x14,0x0e,0x0e,0x09, 0x14,0x0e,0x0e,0x10,0x10,0x05,0x07,0x1b,0x1b,0x1b,0x1b,0x22,0x0d,0x0d,0x06,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x0c,0x0c,0x0c,0x0e,0x0a,0x0a,0x0e,0x0f,0x06,0x08,0x0c,0x0a,0x12,0x10,0x0f,0x0c,0x0f,0x0c,0x0a,0x0b,0x0e,0x0c,0x13,0x0c,0x0b,0x0c,0x11,0x13,0x0a,0x0f,0x0c,0x0e,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x06,0x06,0x06,0x06,0x10,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0e,0x0b,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0e,0x0e,0x0e,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x0c,0x0f,0x0f,0x06,0x06,0x06,0x06,0x06,0x0e,0x08,0x0c,0x0a,0x0a,0x0a,0x0a,0x10,0x10,0x10,0x10,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x13,0x13,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x11,0x0f,0x0c, 0x0c,0x09,0x0d,0x0a,0x0c,0x0f,0x0f,0x06,0x0c,0x0c,0x12,0x10,0x0b,0x0f,0x0f,0x0c,0x0b,0x0b,0x0b,0x0f,0x0c,0x10,0x0f,0x0c,0x0a,0x0f,0x06,0x0f,0x0b,0x0f,0x06,0x0b,0x0a,0x0e,0x0a,0x0c,0x0a,0x06,0x06,0x08,0x14,0x14,0x0f,0x0c,0x0c,0x0f,0x0c,0x0c,0x0c,0x0a,0x0e,0x0a,0x12,0x0b,0x10,0x10,0x0c,0x0e,0x12,0x0f,0x0f,0x0f,0x0c,0x0c, 0x0b,0x0c,0x0f,0x0c,0x0f,0x0d,0x13,0x14,0x0e,0x11,0x0c,0x0c,0x15,0x0c,0x0a,0x0e,0x0e,0x0f,0x15,0x15,0x10,0x0c,0x0e,0x0a,0x0e,0x0d,0x0d,0x11,0x0d,0x0d,0x10,0x0e,0x0e,0x09,0x0f,0x0f,0x0e,0x0c,0x0c,0x16,0x12,0x0b,0x0d,0x0e,0x0e,0x0f,0x0f,0x11,0x10,0x09,0x16,0x0e,0x0d,0x0e,0x0f,0x0f,0x0c,0x0c,0x06,0x12,0x10,0x10,0x0b,0x11, 0x05,0x05,0x0a,0x0a,0x05,0x05,0x0f,0x0a,0x06,0x12,0x11,0x07,0x05,0x05,0x0b,0x09,0x09,0x06,0x06,0x06,0x09,0x10,0x0b,0x07,0x0f,0x10,0x0e,0x0e,0x0c,0x12,0x0e,0x0e,0x08,0x0b,0x0d,0x0a,0x05,0x06,0x09,0x0d,0x08,0x10,0x10,0x10,0x16,0x12,0x16,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x12,0x14,0x08,0x08,0x0c,0x08,0x16,0x08,0x16,0x08, 0x16,0x08,0x0e,0x0e,0x0e,0x0c,0x0c,0x1c,0x14,0x1c,0x14,0x20,0x18,0x20,0x18,0x14,0x14,0x14,0x14,0x14,0x14,0x16,0x16,0x0c,0x0c,0x16,0x16,0x0c,0x0c,0x12,0x14,0x08,0x08,0x12,0x14,0x08,0x08,0x12,0x14,0x08,0x08,0x18,0x12,0x14,0x0c,0x0e,0x0e,0x10,0x08,0x10,0x12,0x0c,0x0c,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x06,0x16,0x08,0x12,0x0c,0x0c,0x06,0x0c,0x0c,0x0c,0x0c,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1c,0x14,0x1c,0x14,0x1c,0x14,0x20,0x18,0x20,0x18,0x14,0x14,0x14,0x18,0x18,0x18,0x18,0x18, 0x18,0x12,0x0c,0x0c,0x12,0x0c,0x0c,0x16,0x0c,0x1a,0x18,0x16,0x0c,0x14,0x0c,0x14,0x0c,0x14,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x16,0x0c,0x10,0x10,0x10,0x10,0x10,0x08,0x10,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x08,0x08,0x0c,0x08,0x08,0x08, 0x08,0x00,0x1c,0x14,0x20,0x18,0x16,0x0c,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x16,0x08,0x0e,0x0e,0x0c,0x0c,0x0a,0x1c,0x14,0x18,0x18,0x16,0x16,0x16,0x0e,0x0e,0x0e,0x0e,0x10,0x08,0x10,0x08,0x10,0x08,0x1c,0x14,0x0e,0x10,0x0e,0x0e,0x0e,0x10,0x0e,0x0e,0x1c,0x1c,0x14,0x14,0x0a,0x0a,0x0e,0x0e,0x0e,0x0e,0x08,0x08, 0x08,0x08,0x12,0x14,0x08,0x08,0x12,0x14,0x08,0x08,0x12,0x14,0x08,0x08,0x0e,0x0e,0x0e,0x0e,0x16,0x08,0x16,0x08,0x0e,0x10,0x0e,0x0e,0x1c,0x1c,0x14,0x14,0x1c,0x1c,0x14,0x14,0x14,0x14,0x0c,0x0c,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x06,0x06,0x08,0x06,0x00,0x00,0x00,0x14,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, 0x0a,0x0a,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x12,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x14,0x0e,0x14,0x0e,0x14,0x0e,0x14,0x10,0x10,0x10,0x06,0x06,0x0c,0x0a,0x0e,0x0f,0x0e,0x0d,0x0d,0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0b,0x0d,0x0d,0x0e,0x0f,0x0f,0x10,0x0e,0x0e,0x10,0x0c,0x10,0x12,0x0f,0x12,0x14,0x0f,0x12,0x11, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0d,0x0b,0x0d,0x0f,0x0e,0x10,0x0e,0x10,0x0e,0x0e,0x0e,0x0c,0x0c,0x12,0x10,0x11,0x10,0x10,0x0e,0x0e,0x0e,0x12,0x13,0x12,0x12,0x16,0x16,0x11,0x16,0x16,0x12,0x15,0x14,0x0d,0x12,0x14,0x12,0x0e,0x14,0x12,0x11,0x11,0x0f,0x0f,0x12,0x13,0x11,0x0f,0x11,0x0e,0x0d,0x16,0x16,0x16, 0x14,0x16,0x16,0x10,0x16,0x16,0x11,0x12,0x13,0x12,0x11,0x11,0x0f,0x15,0x12,0x14,0x11,0x11,0x0e,0x12,0x11,0x11,0x14,0x12,0x11,0x16,0x0d,0x0c,0x0d,0x0d,0x0f,0x0f,0x11,0x12,0x0e,0x0e,0x0e,0x0d,0x0e,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0d,0x0e,0x0f,0x0e,0x0e,0x0b,0x0e,0x0e,0x0e,0x0f,0x12,0x14,0x10,0x10,0x0f,0x12, 0x0f,0x10,0x0c,0x0b,0x0e,0x0e,0x0b,0x0c,0x0d,0x0d,0x0c,0x0b,0x0f,0x0b,0x0d,0x0c,0x0d,0x13,0x0e,0x14,0x0d,0x0e,0x0e,0x12,0x08,0x13,0x10,0x11,0x10,0x0d,0x12,0x0e,0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0f,0x0f,0x0f,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x06, 0x06,0x06,0x0f,0x06,0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x07,0x06,0x06,0x06,0x16,0x16,0x16,0x16,0x0c,0x12,0x11,0x0c,0x0a,0x0c,0x0d,0x0d,0x0c,0x14,0x14,0x15,0x0b,0x18,0x0c,0x14,0x14,0x14,0x13,0x0e,0x0c,0x0c,0x13,0x0e,0x13,0x10,0x0d,0x0b,0x0a,0x18,0x0a,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x21,0x14,0x14,0x0a,0x06,0x0b,0x06,0x0b, 0x06,0x06,0x06,0x0c,0x0e,0x0e,0x0d,0x09,0x09,0x06,0x06,0x06,0x09,0x06,0x0a,0x15,0x05,0x16,0x16,0x16,0x0e,0x0e,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x1c,0x1c,0x10,0x1c,0x1c,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0b,0x0e,0x0b,0x0d,0x0a,0x09,0x08,0x10,0x0d,0x11,0x0a,0x1b,0x15,0x0e,0x0d,0x16,0x13,0x14,0x12,0x18,0x14,0x16,0x13,0x0f,0x0b,0x11,0x0e,0x16,0x12,0x12,0x0f,0x12,0x0e,0x15,0x10,0x15,0x10,0x1a,0x14,0x12,0x0e,0x12,0x0e,0x1d,0x15,0x13,0x00,0x18,0x18,0x18,0x0b,0x00,0x00,0x0e,0x0c,0x11,0x0d, 0x0d,0x0a,0x1a,0x16,0x17,0x15,0x11,0x0e,0x11,0x0e,0x0d,0x0a,0x12,0x0e,0x0d,0x0a,0x14,0x10,0x10,0x0e,0x17,0x14,0x0d,0x0e,0x12,0x12,0x13,0x0b,0x05,0x0b,0x10,0x0a,0x18,0x18,0x06,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x0a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x0c,0x10,0x11,0x07,0x05,0x07,0x05,0x11,0x0e,0x12, 0x0f,0x0d,0x0b,0x0d,0x0c,0x0e,0x0e,0x0a,0x0a,0x1b,0x14,0x1c,0x15,0x18,0x14,0x16,0x10,0x16,0x10,0x16,0x10,0x0f,0x0b,0x0e,0x0c,0x0e,0x0c,0x0e,0x0c,0x0d,0x08,0x0b,0x06,0x12,0x0e,0x15,0x10,0x20,0x18,0x0d,0x0e,0x11,0x11,0x13,0x15,0x12,0x0e,0x17,0x13,0x0d,0x0a,0x0d,0x0c,0x0f,0x0c,0x16,0x11,0x0f,0x0d,0x0d,0x0e,0x0d,0x0e,0x0c, 0x0a,0x0b,0x09,0x0b,0x09,0x0c,0x0d,0x07,0x10,0x08,0x17,0x10,0x08,0x0e,0x0f,0x0b,0x12,0x0d,0x09,0x08,0x0e,0x0e,0x0e,0x0b,0x06,0x12,0x0e,0x09,0x08,0x0f,0x0b,0x11,0x09,0x13,0x0e,0x0f,0x0b,0x10,0x0e,0x0e,0x0c,0x12,0x0e,0x0e,0x08,0x0d,0x0a,0x12,0x0a,0x0d,0x15,0x0c,0x0d,0x16,0x06,0x1c,0x15,0x16,0x1c,0x15,0x16,0x16,0x15,0x15, 0x16,0x0c,0x0b,0x0f,0x11,0x16,0x11,0x17,0x06,0x0b,0x0e,0x15,0x19,0x11,0x19,0x0f,0x0f,0x13,0x11,0x1b,0x16,0x0c,0x16,0x08,0x16,0x08,0x0e,0x0e,0x0e,0x0e,0x14,0x14,0x14,0x14,0x18,0x0c,0x0c,0x18,0x12,0x0c,0x0c,0x12,0x10,0x08,0x08,0x10,0x0e,0x0e,0x0e,0x0e,0x12,0x08,0x08,0x14,0x12,0x08,0x08,0x14,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x0c,0x0a,0x0e,0x0d,0x12,0x0e,0x0e,0x15,0x10,0x12,0x12,0x14,0x14,0x0e,0x0c,0x18,0x13,0x19,0x15,0x10,0x0e,0x08,0x08,0x0e,0x10,0x0a,0x0e,0x0c,0x0e,0x0c,0x12,0x13,0x0a,0x0e,0x0a,0x05, 0x09,0x0d,0x0d,0x05,0x05,0x04,0x05,0x09,0x09,0x09,0x0b,0x24,0x30,0x08,0x0a,0x03,0x06,0x09,0x0a,0x08,0x0c,0x0d,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x20,0x0d,0x12,0x16,0x16,0x0f,0x0b,0x0e,0x11,0x12,0x0c,0x08,0x10,0x0c,0x10,0x0d,0x10,0x0d,0x0d,0x12,0x0e,0x0e,0x0d,0x12,0x0f,0x14,0x0b, 0x0d,0x0f,0x08,0x0e,0x08,0x08,0x06,0x15,0x0e,0x0e,0x0d,0x0d,0x0e,0x16,0x16,0x17,0x18,0x18,0x0d,0x0c,0x07,0x0c,0x0b,0x0f,0x0b,0x10,0x06,0x0e,0x0e,0x15,0x15,0x0f,0x0d,0x0e,0x0d,0x0d,0x0b,0x0d,0x0b,0x0c,0x07,0x08,0x06,0x05,0x09,0x0e,0x0f,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x00, 0x07,0x07,0x07,0x06,0x06,0x28,0x18,0x15,0x19,0x07,0x07,0x08,0x0a,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x16,0x08,0x08,0x16,0x06,0x0c,0x0c,0x20,0x18,0x18,0x20,0x16,0x0c,0x0c,0x16,0x0c,0x0c,0x0a,0x0a,0x00,0x00,0x09,0x12,0x0e,0x11,0x0e,0x1e,0x19,0x11,0x0d,0x11,0x0d,0x20,0x18,0x12,0x0e,0x09,0x08, 0x0f,0x00,0x10,0x0d,0x08,0x07,0x04,0x0c,0x08,0x08,0x06,0x05,0x0b,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x05,0x0d,0x0a,0x0e,0x0e,0x0d,0x17,0x13,0x13,0x13,0x14,0x17,0x0f,0x10,0x0e,0x09,0x16,0x1b,0x0b,0x1c,0x0c,0x14,0x16,0x16,0x16,0x0a,0x12,0x18,0x12,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x0d,0x00,0x0e,0x0e,0x0e,0x14,0x0c,0x0c,0x16,0x08,0x08,0x16,0x08,0x08,0x16,0x0c,0x0c,0x00,0x0a,0x14,0x08,0x08,0x18,0x0c,0x0c,0x12,0x0c,0x0c,0x10,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x24,0x24,0x15,0x00,0x00,0x15,0x15,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x10,0x0f,0x0f,0x10,0x15,0x0f,0x0f,0x13,0x17,0x10,0x0f,0x1a,0x0f,0x0f,0x16,0x0f,0x10,0x13,0x0f,0x12,0x14,0x16,0x0f,0x12,0x10,0x11,0x0f,0x11,0x0f,0x10,0x10,0x0f,0x13,0x0e,0x10,0x13,0x0f,0x0f,0x0e,0x13,0x0f,0x10,0x10,0x11,0x0b,0x0d,0x0f,0x13,0x13,0x0d,0x00,0x00,0x1b,0x36,0x11,0x00,0x03,0x07,0x08,0x0b, 0x10,0x0f,0x16,0x16,0x06,0x08,0x08,0x0b,0x12,0x06,0x0b,0x06,0x0b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x06,0x06,0x12,0x12,0x12,0x0c,0x1a,0x11,0x0f,0x11,0x13,0x0e,0x0d,0x13,0x13,0x07,0x0a,0x10,0x0d,0x18,0x14,0x14,0x0f,0x14,0x10,0x0e,0x0e,0x13,0x11,0x19,0x10,0x0f,0x0f,0x08,0x0a,0x08,0x12,0x0b,0x07,0x0e,0x10, 0x0c,0x10,0x0e,0x08,0x10,0x0f,0x07,0x07,0x0d,0x07,0x17,0x0f,0x10,0x10,0x10,0x09,0x0b,0x09,0x0f,0x0d,0x14,0x0c,0x0d,0x0c,0x08,0x06,0x08,0x12,0x11,0x11,0x11,0x0e,0x14,0x14,0x13,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0e,0x0e,0x07,0x07,0x07,0x07,0x0f,0x10,0x10,0x10,0x10,0x10,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x0f,0x0f, 0x0c,0x0b,0x0c,0x0f,0x0b,0x18,0x18,0x15,0x08,0x0b,0x13,0x17,0x14,0x16,0x12,0x13,0x13,0x0f,0x10,0x0e,0x11,0x14,0x0f,0x0b,0x0c,0x14,0x16,0x10,0x0c,0x07,0x08,0x12,0x12,0x0f,0x13,0x11,0x0e,0x0e,0x14,0x11,0x11,0x14,0x19,0x19,0x0e,0x1b,0x0a,0x0a,0x06,0x06,0x12,0x10,0x0d,0x0f,0x05,0x0f,0x09,0x09,0x0f,0x0f,0x0a,0x06,0x06,0x0a, 0x21,0x11,0x0e,0x11,0x0e,0x0e,0x07,0x07,0x07,0x07,0x14,0x14,0x14,0x13,0x13,0x13,0x07,0x0a,0x09,0x08,0x08,0x05,0x08,0x06,0x09,0x05,0x0a,0x0d,0x07,0x0e,0x0b,0x0f,0x0c,0x06,0x13,0x0f,0x0f,0x0d,0x0f,0x10,0x12,0x12,0x09,0x0a,0x0a,0x19,0x18,0x1a,0x0d,0x13,0x10,0x07,0x0e,0x0b,0x11,0x0c,0x11,0x0c,0x10,0x0b,0x06,0x11,0x0e,0x11, 0x0e,0x13,0x12,0x13,0x0e,0x0e,0x0e,0x0e,0x0d,0x07,0x0d,0x08,0x0d,0x09,0x14,0x0f,0x14,0x0f,0x14,0x10,0x10,0x09,0x10,0x09,0x0e,0x0b,0x0e,0x09,0x0e,0x0c,0x13,0x0f,0x13,0x0f,0x0f,0x0c,0x0f,0x0c,0x0d,0x14,0x14,0x11,0x10,0x0c,0x10,0x0d,0x13,0x0b,0x0d,0x0b,0x1e,0x11,0x0d,0x10,0x06,0x0a,0x16,0x09,0x10,0x0a,0x0a,0x10,0x0a,0x11, 0x0e,0x11,0x0c,0x11,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x10,0x13,0x10,0x13,0x10,0x13,0x0f,0x13,0x0f,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x07,0x10,0x0d,0x0d,0x0d,0x07,0x14,0x0f,0x14,0x0f,0x14,0x10,0x14,0x10,0x10,0x09,0x0e,0x0b,0x0e,0x09,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x19,0x14,0x0f,0x0d,0x07,0x11, 0x0e,0x17,0x16,0x14,0x10,0x06,0x19,0x14,0x19,0x14,0x19,0x14,0x0f,0x0d,0x06,0x0b,0x0f,0x10,0x19,0x19,0x19,0x18,0x0b,0x0b,0x06,0x07,0x07,0x11,0x0f,0x15,0x0a,0x16,0x12,0x16,0x07,0x11,0x0f,0x0e,0x0f,0x13,0x07,0x10,0x11,0x18,0x14,0x0e,0x14,0x13,0x0f,0x0e,0x0e,0x0f,0x10,0x15,0x14,0x07,0x0f,0x11,0x0c,0x10,0x07,0x0f,0x0f,0x0e, 0x0c,0x10,0x10,0x07,0x0e,0x0d,0x10,0x0e,0x0c,0x10,0x10,0x0c,0x0f,0x0f,0x14,0x16,0x07,0x0f,0x10,0x0f,0x16,0x0e,0x13,0x0d,0x11,0x0e,0x07,0x1a,0x1b,0x14,0x10,0x0f,0x13,0x11,0x0f,0x0f,0x0d,0x13,0x0e,0x17,0x0f,0x14,0x14,0x10,0x12,0x18,0x13,0x14,0x13,0x0f,0x11,0x0e,0x0f,0x14,0x10,0x14,0x12,0x1a,0x1a,0x13,0x15,0x10,0x11,0x1c, 0x10,0x0e,0x10,0x0e,0x0a,0x0f,0x0e,0x14,0x0c,0x10,0x10,0x0d,0x0e,0x13,0x10,0x10,0x10,0x10,0x0c,0x0b,0x0d,0x13,0x0c,0x10,0x0f,0x16,0x16,0x10,0x13,0x0e,0x0c,0x16,0x0e,0x0e,0x10,0x0a,0x0c,0x0b,0x07,0x15,0x16,0x0f,0x0d,0x0d,0x10,0x0d,0x0b,0x1b,0x1e,0x11,0x09,0x0a,0x0a,0x0a,0x07,0x0e,0x0b,0x0f,0x15,0x10,0x13,0x10,0x08,0x09, 0x07,0x07,0x0d,0x0d,0x0d,0x0d,0x08,0x08,0x08,0x0d,0x08,0x0d,0x08,0x08,0x08,0x0d,0x0d,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x07,0x07,0x07,0x07,0x14,0x10,0x14, 0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x13,0x0f,0x13,0x0f,0x13,0x10,0x13,0x10,0x13,0x10,0x13,0x10,0x13,0x10,0x0f,0x0d,0x0f,0x0d,0x0f,0x0d,0x0e,0x09,0x0e,0x0e,0x14,0x10,0x07,0x0a,0x07,0x07,0x0e,0x0b,0x19,0x15,0x11,0x0e,0x10,0x0d,0x14,0x10,0x0f,0x0d,0x0f, 0x0d,0x11,0x0d,0x12,0x0f,0x12,0x0f,0x13,0x0e,0x14,0x10,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x07,0x07,0x08,0x08,0x08,0x08,0x0e,0x0e,0x11,0x0e,0x0f,0x10,0x0f,0x10,0x0f,0x10,0x11,0x0c,0x13,0x10,0x13,0x10,0x13,0x10,0x13,0x10,0x13,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0d,0x08,0x13,0x10,0x13, 0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x07,0x07,0x07,0x07,0x10,0x0d,0x10,0x0d,0x10,0x0d,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x0d,0x07,0x18,0x17,0x18,0x17,0x18,0x17,0x14,0x0f,0x14,0x0f,0x14,0x0f,0x14,0x0f,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x0f,0x10,0x0f,0x10,0x10,0x09,0x10,0x09,0x10,0x09,0x10,0x09,0x0e,0x0b,0x0e, 0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x0b,0x0e,0x09,0x0e,0x09,0x0e,0x09,0x0e,0x09,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x11,0x0d,0x11,0x0d,0x19,0x14,0x19,0x14,0x10,0x0c,0x10,0x0c,0x0f,0x0d,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x09,0x14,0x0d,0x0e,0x07,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x14,0x14, 0x14,0x14,0x14,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x13,0x13,0x13,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x15,0x15,0x19,0x19,0x19,0x19,0x19,0x19,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x10,0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x1a,0x1a,0x1a,0x1a,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x11,0x11,0x0c,0x0c,0x10,0x10,0x07,0x07,0x10,0x10,0x0f,0x0f,0x16,0x16,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x14,0x14,0x14,0x14,0x14,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x15,0x15,0x19, 0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x0f,0x15,0x15,0x13,0x10,0x10,0x10,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0a,0x0a,0x10,0x10,0x10, 0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x0f,0x0f,0x0f,0x0f,0x12,0x12,0x11,0x10,0x10,0x10,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x16,0x14,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11,0x0f,0x10,0x10,0x10,0x11,0x11,0x0d,0x13,0x14,0x0f,0x10,0x10,0x0e,0x0f,0x0d,0x13,0x11,0x18,0x08,0x08, 0x10,0x0d,0x07,0x0d,0x18,0x14,0x10,0x14,0x1a,0x15,0x10,0x10,0x10,0x0e,0x0b,0x0e,0x08,0x09,0x0e,0x09,0x0e,0x14,0x13,0x0f,0x0e,0x0f,0x0c,0x10,0x10,0x0c,0x0b,0x0f,0x0f,0x0a,0x0b,0x0f,0x06,0x0a,0x0c,0x08,0x21,0x1f,0x1c,0x17,0x13,0x0e,0x1d,0x1a,0x16,0x11,0x0e,0x07,0x07,0x14,0x10,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13, 0x0f,0x0e,0x11,0x0e,0x11,0x0e,0x17,0x16,0x13,0x10,0x13,0x10,0x10,0x0d,0x14,0x10,0x14,0x10,0x10,0x0c,0x07,0x21,0x1f,0x1c,0x13,0x10,0x1b,0x13,0x14,0x0f,0x11,0x0e,0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x07,0x07,0x07,0x07,0x14,0x10,0x14,0x10,0x10,0x09,0x10,0x09,0x13,0x0f,0x13,0x0f,0x0e,0x0c,0x13,0x0f,0x14,0x10,0x0f,0x0f,0x0c,0x11, 0x0e,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x0f,0x0d,0x10,0x0e,0x0f,0x0f,0x10,0x0e,0x10,0x10,0x10,0x0d,0x0d,0x10,0x10,0x0e,0x11,0x0b,0x0b,0x0e,0x0f,0x07,0x10,0x10,0x0e,0x0d,0x0c,0x0f,0x0f,0x0f,0x07,0x08,0x09,0x08,0x0a,0x07,0x10,0x17,0x17,0x17,0x0f,0x0f,0x10,0x10,0x13,0x13,0x11,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c, 0x0c,0x0b,0x07,0x07,0x08,0x08,0x09,0x09,0x10,0x10,0x0f,0x0d,0x14,0x0d,0x0b,0x0c,0x0e,0x0c,0x0c,0x0a,0x0a,0x0a,0x0d,0x11,0x0d,0x0f,0x0e,0x0f,0x07,0x0d,0x0a,0x10,0x0a,0x0a,0x19,0x1a,0x1a,0x11,0x0d,0x13,0x15,0x10,0x0f,0x0d,0x0d,0x0f,0x10,0x0f,0x12,0x0f,0x11,0x16,0x0f,0x13,0x10,0x10,0x0c,0x0d,0x0c,0x10,0x0e,0x11,0x0d,0x18, 0x17,0x10,0x0e,0x11,0x0e,0x10,0x0c,0x10,0x0d,0x12,0x10,0x0f,0x0b,0x0f,0x10,0x0c,0x07,0x14,0x0d,0x0d,0x17,0x12,0x11,0x10,0x19,0x13,0x12,0x0d,0x18,0x13,0x14,0x0f,0x19,0x14,0x0f,0x0c,0x15,0x15,0x14,0x10,0x13,0x10,0x13,0x10,0x23,0x1e,0x16,0x12,0x1e,0x18,0x17,0x12,0x10,0x0c,0x0e,0x0b,0x0b,0x00,0x00,0x1b,0x1a,0x10,0x0e,0x0f, 0x10,0x0f,0x0e,0x0f,0x0c,0x10,0x0d,0x13,0x10,0x17,0x12,0x1b,0x17,0x13,0x0f,0x11,0x0c,0x0e,0x0b,0x18,0x12,0x13,0x10,0x17,0x11,0x17,0x11,0x07,0x17,0x14,0x10,0x0e,0x13,0x10,0x12,0x0f,0x11,0x0e,0x11,0x0e,0x17,0x16,0x0e,0x0e,0x13,0x0e,0x13,0x0e,0x17,0x14,0x0f,0x0c,0x0e,0x0c,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x11,0x0c, 0x0f,0x0d,0x0f,0x0d,0x0f,0x0d,0x12,0x0f,0x15,0x13,0x0f,0x10,0x17,0x17,0x16,0x13,0x0f,0x0d,0x18,0x15,0x1b,0x17,0x13,0x0e,0x12,0x10,0x10,0x0f,0x0f,0x0e,0x10,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x10,0x09,0x09,0x04,0x06,0x06,0x06,0x08,0x0b,0x08,0x06,0x0a,0x06,0x06,0x06,0x09,0x09, 0x06,0x06,0x10,0x10,0x10,0x10,0x09,0x08,0x07,0x09,0x08,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x09,0x09,0x08,0x09,0x09,0x08,0x04,0x07,0x08,0x06,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x0b,0x09,0x07,0x07,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x11,0x08,0x11,0x09,0x10,0x10,0x09,0x09, 0x09,0x09,0x09,0x07,0x09,0x09,0x09,0x08,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x10,0x0d,0x12,0x16,0x0d,0x0c,0x0f,0x0f,0x0b,0x0b,0x07,0x08,0x0d,0x0b,0x13,0x10,0x10,0x0d,0x11,0x11,0x11,0x19,0x0e,0x10,0x10,0x0c,0x0c,0x0c,0x0b,0x0e,0x0f,0x13,0x0f,0x0d,0x14,0x0c,0x0b, 0x0b,0x0e,0x0a,0x0d,0x10,0x0c,0x10,0x0f,0x0a,0x0d,0x09,0x0a,0x0b,0x08,0x08,0x0b,0x0b,0x05,0x06,0x0a,0x08,0x0e,0x0c,0x0c,0x0c,0x0a,0x09,0x09,0x08,0x0b,0x0e,0x09,0x09,0x09,0x0d,0x09,0x09,0x08,0x08,0x07,0x07,0x09,0x04,0x08,0x0d,0x09,0x09,0x07,0x09,0x09,0x09,0x05,0x09,0x09,0x0d,0x08,0x09,0x09,0x08,0x09,0x0b,0x08,0x04,0x06, 0x09,0x08,0x09,0x08,0x09,0x0b,0x08,0x10,0x04,0x09,0x0f,0x18,0x11,0x0f,0x0f,0x17,0x11,0x17,0x14,0x0e,0x10,0x0e,0x0c,0x1e,0x0c,0x10,0x18,0x19,0x19,0x11,0x11,0x11,0x0c,0x0d,0x0e,0x0b,0x0c,0x0e,0x05,0x00,0x00,0x00,0x00,0x10,0x11,0x11,0x11,0x0d,0x0a,0x10,0x10,0x08,0x17,0x0f,0x10,0x09,0x09,0x0d,0x09,0x0c,0x10,0x0c,0x10,0x18, 0x11,0x09,0x07,0x10,0x0e,0x10,0x10,0x10,0x08,0x10,0x0d,0x07,0x17,0x0f,0x10,0x09,0x0b,0x0c,0x0d,0x0c,0x0c,0x0e,0x10,0x10,0x0e,0x0c,0x0c,0x14,0x07,0x0d,0x07,0x0f,0x0c,0x09,0x07,0x07,0x09,0x07,0x05,0x04,0x09,0x09,0x04,0x05,0x05,0x05,0x04,0x05,0x04,0x06,0x0d,0x0d,0x09,0x09,0x0a,0x09,0x0a,0x06,0x04,0x05,0x09,0x09,0x09,0x09, 0x08,0x07,0x07,0x08,0x07,0x09,0x00,0x00,0x00,0x00,0x06,0x09,0x08,0x09,0x07,0x08,0x0f,0x0f,0x0f,0x0f,0x09,0x00,0x00,0x00,0x00,0x0d,0x08,0x07,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x07,0x07,0x07,0x07,0x0f,0x0f,0x0f,0x0f,0x24,0x24,0x24,0x24, 0x24,0x24,0x24,0x24,0x24,0x24,0x0f,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x05,0x0a,0x0a,0x09,0x0a,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x0a,0x09,0x0a,0x0a,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x15,0x11,0x13,0x10,0x14,0x11,0x19,0x14,0x0f,0x0a,0x0e,0x12,0x0e,0x16,0x13,0x00,0x00,0x00, 0x00,0x07,0x07,0x07,0x07,0x09,0x09,0x09,0x10,0x10,0x10,0x10,0x10,0x10,0x17,0x17,0x1b,0x0b,0x07,0x0e,0x10,0x0b,0x0e,0x0e,0x10,0x10,0x0e,0x1b,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x0e,0x11,0x0e,0x0e,0x0e,0x09,0x10,0x09,0x14,0x12,0x0e,0x09,0x17,0x0e,0x17,0x07,0x09,0x10,0x10,0x11,0x11,0x11,0x10,0x10,0x10,0x17,0x07,0x10,0x07, 0x0e,0x0b,0x07,0x07,0x0e,0x07,0x14,0x07,0x19,0x0e,0x19,0x19,0x10,0x10,0x10,0x0e,0x0e,0x0b,0x0b,0x20,0x20,0x24,0x24,0x17,0x17,0x0e,0x0e,0x05,0x1b,0x14,0x17,0x12,0x10,0x12,0x0e,0x0e,0x14,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x11,0x00,0x11,0x11,0x11,0x09,0x0e,0x0e,0x19,0x09,0x19,0x09,0x10,0x12,0x10,0x0b, 0x19,0x0e,0x19,0x0e,0x14,0x17,0x09,0x0e,0x0e,0x0b,0x07,0x0e,0x10,0x0e,0x10,0x0e,0x10,0x10,0x0e,0x12,0x11,0x19,0x09,0x0e,0x0b,0x12,0x0e,0x09,0x0e,0x0e,0x0e,0x19,0x09,0x19,0x09,0x07,0x10,0x0b,0x1b,0x0e,0x0e,0x11,0x11,0x1b,0x0e,0x00,0x00,0x00,0x11,0x00,0x11,0x11,0x11,0x11,0x14,0x11,0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07, 0x0b,0x0b,0x0e,0x0e,0x14,0x17,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x12,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0b,0x0e,0x0b,0x0b,0x0b,0x20,0x17,0x20,0x17,0x20,0x17,0x24,0x1b,0x24,0x1b,0x17,0x0e,0x10, 0x10,0x10,0x1b,0x1b,0x0e,0x0e,0x1b,0x0e,0x0e,0x1b,0x0e,0x0e,0x1b,0x0e,0x0e,0x14,0x14,0x1d,0x1b,0x19,0x0e,0x17,0x0e,0x17,0x0e,0x17,0x0e,0x19,0x0e,0x19,0x0e,0x19,0x0e,0x19,0x0e,0x19,0x0e,0x12,0x09,0x12,0x09,0x12,0x09,0x12,0x09,0x12,0x09,0x12,0x12,0x09,0x12,0x09,0x0f,0x12,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x17, 0x19,0x14,0x17,0x09,0x0e,0x14,0x17,0x14,0x17,0x00,0x00,0x00,0x00,0x00,0x1e,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0b,0x00,0x00,0x10,0x00,0x00,0x00,0x20,0x17,0x24,0x1b,0x0e,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x19,0x19,0x0a,0x10,0x10,0x10,0x21,0x16, 0x0e,0x29,0x1d,0x09,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0b,0x0b,0x14,0x12,0x12,0x0e,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x22,0x29,0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x0b,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x10,0x10,0x10,0x10,0x12,0x10, 0x0e,0x0e,0x0b,0x20,0x17,0x0e,0x10,0x10,0x10,0x0e,0x10,0x10,0x10,0x0e,0x10,0x10,0x10,0x1b,0x0e,0x0e,0x1b,0x0e,0x0e,0x19,0x0e,0x0e,0x19,0x0e,0x0e,0x19,0x0e,0x0e,0x10,0x10,0x10,0x10,0x12,0x09,0x12,0x09,0x12,0x09,0x12,0x12,0x09,0x09,0x0b,0x0b,0x20,0x17,0x11,0x10,0x10,0x00,0x0e,0x0e,0x0e,0x0a,0x0f,0x13,0x11,0x0e,0x0e,0x0a, 0x07,0x14,0x10,0x10,0x09,0x0f,0x0d,0x0d,0x0c,0x0d,0x07,0x0e,0x0b,0x11,0x0d,0x10,0x0c,0x0f,0x0c,0x12,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x0c,0x0d,0x0d,0x08,0x0e,0x0f,0x10,0x0e,0x09,0x14,0x10,0x11,0x0e,0x11,0x0d,0x0f,0x0e,0x0b,0x13,0x0a,0x0b,0x0b,0x0d,0x10,0x10,0x0e,0x1b,0x0e,0x1b,0x09,0x07,0x05,0x0f, 0x06,0x03,0x00,0x04,0x06,0x00,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x19,0x0b,0x14,0x10,0x19,0x14,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x19,0x17,0x0d,0x17,0x0d,0x17,0x11,0x12,0x13,0x13,0x15,0x17,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x12,0x12,0x12,0x12,0x14,0x10,0x1d, 0x16,0x0d,0x0d,0x08,0x08,0x08,0x0a,0x06,0x0f,0x06,0x06,0x17,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x05,0x00,0x00,0x06,0x00,0x00,0x11,0x0f,0x0c,0x0d,0x12,0x07,0x09,0x12,0x12,0x07,0x0f,0x0f,0x0f,0x13,0x12,0x07,0x0b,0x12,0x10,0x11,0x11,0x0f,0x10,0x12,0x0f,0x15,0x14,0x0e,0x0e,0x0e, 0x06,0x0a,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x11,0x0d,0x12,0x0f,0x0f,0x13,0x0f,0x14,0x0f,0x15,0x15,0x15,0x15,0x11,0x11,0x11,0x0f,0x0c,0x0d,0x12,0x08,0x0a,0x12,0x08,0x0f,0x0f,0x0f,0x12,0x0b,0x12,0x11,0x11,0x10,0x12,0x0f,0x15,0x14,0x07,0x0f,0x0f,0x11,0x12,0x20,0x00,0x11,0x0f,0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x07,0x00,0x14,0x11,0x12,0x13,0x0f,0x12,0x14,0x15,0x0d,0x11,0x14,0x14,0x12,0x14,0x16,0x15,0x12,0x0f,0x0f,0x14,0x13,0x0f,0x13,0x12,0x12,0x12,0x13,0x14,0x10,0x11,0x12,0x12,0x15,0x11,0x11,0x11, 0x12,0x16,0x0d,0x10,0x10,0x18,0x0f,0x0f,0x15,0x18,0x10,0x0f,0x1c,0x0f,0x0f,0x14,0x0f,0x0f,0x14,0x0f,0x14,0x16,0x18,0x0f,0x15,0x0f,0x12,0x0f,0x11,0x0f,0x11,0x0f,0x10,0x15,0x0f,0x11,0x12,0x0f,0x0f,0x10,0x1a,0x0f,0x0f,0x10,0x10,0x0b,0x09,0x0f,0x0f,0x0f,0x0e,0x0f,0x18,0x0f,0x18,0x0d,0x0f,0x18,0x12,0x0f,0x18,0x14,0x14,0x18, 0x10,0x0f,0x18,0x18,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x18,0x18,0x10,0x0f,0x0f,0x18,0x10,0x0f,0x0f,0x0f,0x18,0x15,0x13,0x13,0x13,0x13,0x13,0x11,0x13,0x15,0x13,0x12,0x0f,0x15,0x12,0x13,0x0f,0x12,0x13,0x14,0x13,0x10,0x13,0x12,0x14,0x12,0x15,0x13,0x13,0x14,0x12,0x11,0x13,0x12,0x13,0x15,0x12,0x14,0x14,0x03,0x03,0x04,0x05,0x04, 0x07,0x09,0x17,0x0f,0x11,0x10,0x0f,0x11,0x0f,0x0f,0x11,0x10,0x0f,0x08,0x17,0x10,0x0f,0x0f,0x0f,0x10,0x0e,0x10,0x07,0x10,0x0e,0x0f,0x0b,0x17,0x0f,0x0f,0x0f,0x10,0x16,0x0f,0x10,0x0b,0x16,0x10,0x10,0x13,0x12,0x06,0x08,0x1f,0x1e,0x1e,0x1f,0x26,0x0f,0x0f,0x07,0x0f,0x0b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0d,0x0e,0x10,0x0c,0x0b,0x0f,0x11,0x07,0x08,0x0d,0x0b,0x14,0x11,0x11,0x0d,0x11,0x0d,0x0b,0x0c,0x10,0x0e,0x16,0x0e,0x0d,0x0d,0x13, 0x15,0x0b,0x11,0x0d,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x07,0x07,0x07,0x07,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x10,0x10,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0e,0x11,0x11,0x07,0x07,0x07,0x07,0x07,0x0f,0x08,0x0d,0x0b,0x0b,0x0b,0x0b,0x11,0x11, 0x11,0x12,0x11,0x11,0x11,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x16,0x16,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0e,0x13,0x11,0x0e,0x0d,0x0b,0x0e,0x0c,0x0d,0x11,0x11,0x07,0x0d,0x0e,0x14,0x11,0x0c,0x11,0x11,0x0d,0x0c,0x0c,0x0d,0x11,0x0e,0x12,0x11,0x0e,0x0c,0x11,0x07,0x11, 0x0d,0x11,0x07,0x0d,0x0c,0x0f,0x0b,0x0e,0x0b,0x07,0x07,0x08,0x16,0x16,0x10,0x0d,0x0d,0x10,0x0e,0x0d,0x0d,0x0b,0x10,0x0c,0x14,0x0c,0x11,0x11,0x0d,0x0f,0x14,0x11,0x11,0x11,0x0d,0x0e,0x0c,0x0d,0x11,0x0e,0x11,0x0f,0x16,0x16,0x0f,0x13,0x0d,0x0e,0x17,0x0d,0x0b,0x10,0x10,0x11,0x18,0x18,0x12,0x0e,0x0f,0x0b,0x0f,0x0f,0x0f,0x13, 0x0e,0x0e,0x13,0x10,0x10,0x0a,0x11,0x11,0x0f,0x0d,0x0d,0x18,0x14,0x0d,0x0e,0x10,0x10,0x11,0x11,0x13,0x13,0x0a,0x19,0x10,0x0f,0x0f,0x11,0x11,0x0e,0x0e,0x07,0x14,0x13,0x13,0x0d,0x13,0x06,0x06,0x0c,0x0c,0x06,0x06,0x11,0x0b,0x07,0x14,0x13,0x08,0x06,0x06,0x0c,0x0a,0x0a,0x06,0x06,0x06,0x0a,0x12,0x0d,0x08,0x10,0x13,0x10,0x10, 0x0d,0x14,0x0f,0x10,0x09,0x0c,0x0e,0x0b,0x06,0x06,0x0b,0x0e,0x09,0x12,0x12,0x12,0x19,0x14,0x19,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x14,0x17,0x09,0x09,0x0e,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x10,0x10,0x10,0x0e,0x0e,0x20,0x17,0x20,0x17,0x24,0x1b,0x24,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x19,0x19,0x0e,0x0e,0x19,0x19,0x0e, 0x0e,0x14,0x17,0x09,0x09,0x14,0x17,0x09,0x09,0x14,0x17,0x09,0x09,0x1b,0x14,0x17,0x0e,0x10,0x10,0x12,0x09,0x12,0x14,0x0e,0x0e,0x09,0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x19,0x09,0x14,0x0e,0x0e,0x07,0x0e,0x0e,0x0e,0x0e,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09, 0x19,0x09,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x20,0x17,0x20,0x17,0x20,0x17,0x24,0x1b,0x24,0x1b,0x17,0x17,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x14,0x0e,0x0e,0x14,0x0e,0x0e,0x19,0x0e,0x1d,0x1b,0x19,0x0e,0x17,0x0e,0x17,0x0e,0x17,0x0e,0x19,0x0e,0x19,0x0e,0x19,0x0e,0x19,0x0e,0x19, 0x0e,0x19,0x0e,0x12,0x12,0x12,0x12,0x12,0x09,0x12,0x12,0x09,0x09,0x12,0x09,0x12,0x09,0x12,0x0e,0x10,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x09,0x09,0x0e,0x09,0x09,0x09,0x09,0x00,0x20,0x17,0x24,0x1b,0x19,0x0e,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x19,0x09,0x10,0x10,0x0e,0x0e,0x0b,0x20,0x17,0x1b, 0x1b,0x19,0x19,0x19,0x10,0x10,0x10,0x10,0x12,0x09,0x12,0x09,0x12,0x09,0x20,0x17,0x10,0x12,0x10,0x10,0x10,0x12,0x10,0x10,0x20,0x20,0x17,0x17,0x0b,0x0b,0x10,0x10,0x10,0x10,0x09,0x09,0x09,0x09,0x14,0x17,0x09,0x09,0x14,0x17,0x09,0x09,0x14,0x17,0x09,0x09,0x10,0x10,0x10,0x10,0x19,0x09,0x19,0x09,0x10,0x12,0x10,0x10,0x20,0x20, 0x17,0x17,0x20,0x20,0x17,0x17,0x17,0x17,0x0e,0x0e,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x09,0x07,0x00,0x00,0x00,0x17,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0b,0x0b,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x19,0x19,0x19,0x19, 0x19,0x19,0x19,0x19,0x19,0x19,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x14,0x12,0x12,0x12,0x12,0x12,0x12,0x10,0x17,0x10,0x17,0x10,0x17,0x10,0x17,0x12,0x12,0x12,0x07,0x07,0x0e,0x0b,0x10,0x11, 0x0f,0x0f,0x0f,0x10,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0c,0x0f,0x0e,0x10,0x10,0x11,0x12,0x10,0x0f,0x12,0x0e,0x12,0x14,0x11,0x14,0x16,0x11,0x15,0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0c,0x0f,0x10,0x10,0x12,0x0f,0x11,0x10,0x10,0x10,0x0e,0x0e,0x14,0x12,0x13,0x12,0x12, 0x10,0x10,0x10,0x14,0x15,0x14,0x15,0x19,0x19,0x13,0x19,0x19,0x14,0x18,0x17,0x0f,0x15,0x17,0x15,0x10,0x17,0x14,0x13,0x13,0x10,0x11,0x14,0x15,0x13,0x11,0x13,0x10,0x0e,0x19,0x19,0x19,0x16,0x19,0x19,0x12,0x19,0x19,0x13,0x15,0x15,0x14,0x14,0x14,0x11,0x18,0x15,0x16,0x13,0x13,0x10,0x14,0x13,0x13,0x17,0x14,0x14,0x18,0x0f,0x0e, 0x0f,0x0e,0x11,0x11,0x13,0x14,0x10,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x0f,0x0f,0x0f,0x0e,0x0e,0x10,0x11,0x10,0x10,0x0c,0x0f,0x0f,0x10,0x10,0x15,0x17,0x12,0x12,0x11,0x15,0x11,0x12,0x0e,0x0d,0x10,0x0f,0x0d,0x0d,0x0f,0x0f,0x0d,0x0d,0x11,0x0c,0x0f,0x0d,0x0f,0x15,0x0f,0x16,0x0e,0x0f,0x0f,0x14,0x08,0x15,0x13,0x13, 0x12,0x0f,0x14,0x10,0x15,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0c,0x0c,0x0c,0x0c,0x0d,0x0c,0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x11,0x07,0x07,0x07,0x08,0x08,0x07,0x07,0x07,0x08,0x07,0x07,0x07,0x18,0x18,0x18,0x18,0x0d,0x14,0x14,0x0d,0x0b,0x0d,0x0e,0x0f,0x0d, 0x17,0x16,0x17,0x0c,0x1b,0x0d,0x17,0x17,0x17,0x16,0x0f,0x0d,0x0d,0x15,0x10,0x15,0x12,0x0e,0x0c,0x0b,0x1c,0x0b,0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x25,0x17,0x17,0x0c,0x07,0x0c,0x06,0x0c,0x06,0x06,0x06,0x0d,0x10,0x10,0x0f,0x0a,0x0a,0x06,0x06,0x06,0x0a,0x06,0x0b,0x17,0x06,0x18,0x18,0x18,0x10,0x10,0x17,0x17,0x17,0x17,0x17,0x17, 0x17,0x17,0x17,0x17,0x20,0x20,0x12,0x20,0x20,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x0d,0x10,0x0d,0x0e,0x0b,0x0a,0x09,0x13,0x0f,0x13,0x0c,0x1e,0x18,0x10,0x0f,0x19,0x15,0x17,0x14,0x1c,0x16, 0x19,0x15,0x11,0x0d,0x14,0x10,0x19,0x14,0x14,0x10,0x14,0x10,0x17,0x12,0x18,0x12,0x1e,0x17,0x14,0x10,0x14,0x10,0x21,0x18,0x15,0x00,0x1b,0x1b,0x1b,0x0d,0x00,0x00,0x10,0x0e,0x13,0x0f,0x0e,0x0b,0x1d,0x18,0x1a,0x17,0x13,0x10,0x13,0x10,0x0e,0x0b,0x14,0x10,0x0e,0x0b,0x16,0x12,0x12,0x0f,0x1a,0x16,0x0f,0x10,0x14,0x14,0x16,0x0c, 0x05,0x0c,0x12,0x0c,0x1b,0x1b,0x07,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x0b,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x14,0x14, 0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0d,0x12,0x14,0x08,0x06,0x08,0x06,0x13,0x0f,0x14,0x11,0x0f,0x0d,0x0e,0x0d,0x10,0x0f,0x0b,0x0b,0x1e,0x16,0x1f,0x18,0x1b,0x17,0x18,0x12,0x18,0x12,0x18,0x12,0x11,0x0c,0x10,0x0d,0x10,0x0d,0x10, 0x0d,0x0f,0x08,0x0d,0x07,0x14,0x10,0x17,0x12,0x24,0x1b,0x0f,0x10,0x13,0x13,0x16,0x17,0x14,0x10,0x1a,0x15,0x0f,0x0b,0x0f,0x0d,0x11,0x0d,0x19,0x14,0x11,0x0e,0x0f,0x10,0x0f,0x10,0x0d,0x0b,0x0d,0x0a,0x0d,0x0a,0x0e,0x0e,0x08,0x12,0x09,0x1a,0x12,0x09,0x10,0x11,0x0c,0x14,0x0f,0x0a,0x09,0x10,0x10,0x10,0x0d,0x07,0x15,0x10,0x0a, 0x09,0x11,0x0c,0x13,0x0a,0x15,0x10,0x11,0x0c,0x13,0x10,0x10,0x0d,0x14,0x0f,0x10,0x09,0x0e,0x0b,0x14,0x0b,0x0e,0x17,0x0d,0x0f,0x18,0x07,0x1f,0x18,0x18,0x20,0x18,0x19,0x19,0x18,0x18,0x19,0x0e,0x0d,0x11,0x13,0x18,0x13,0x19,0x07,0x0c,0x10,0x17,0x1c,0x13,0x1c,0x11,0x11,0x15,0x13,0x1f,0x19,0x0e,0x19,0x09,0x19,0x09,0x10,0x10, 0x10,0x10,0x17,0x17,0x17,0x17,0x1b,0x0e,0x0e,0x1b,0x14,0x0e,0x0e,0x14,0x12,0x09,0x09,0x12,0x10,0x10,0x10,0x10,0x14,0x09,0x09,0x17,0x14,0x09,0x09,0x17,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2a, 0x0e,0x0b,0x0f,0x0e,0x14,0x10,0x10,0x18,0x12,0x14,0x14,0x16,0x16,0x10,0x0d,0x1b,0x16,0x1c,0x17,0x13,0x10,0x08,0x08,0x10,0x11,0x0b,0x10,0x0e,0x10,0x0d,0x14,0x16,0x0b,0x10,0x0c,0x06,0x0a,0x0e,0x0f,0x06,0x06,0x05,0x06,0x0a,0x0a,0x0a,0x0c,0x28,0x36,0x09,0x0b,0x04,0x07,0x0a,0x0c,0x09,0x0d,0x0e,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0d,0x0d,0x0d,0x24,0x0f,0x15,0x19,0x18,0x11,0x0c,0x0f,0x13,0x14,0x0d,0x08,0x12,0x0e,0x12,0x0f,0x12,0x0e,0x0f,0x14,0x10,0x10,0x0e,0x14,0x11,0x16,0x0c,0x0e,0x11,0x08,0x10,0x09,0x09,0x07,0x18,0x10,0x0f,0x0e,0x0e,0x10,0x19,0x19,0x19,0x1b,0x1b,0x0f,0x0d,0x08,0x0e,0x0c,0x10,0x0c,0x12,0x07,0x0f, 0x10,0x17,0x17,0x11,0x0f,0x10,0x0f,0x0e,0x0c,0x0e,0x0c,0x0d,0x08,0x09,0x07,0x06,0x0a,0x10,0x11,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x09,0x00,0x08,0x08,0x08,0x07,0x07,0x2d,0x1b,0x18,0x1c,0x08,0x08,0x09,0x0b,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x19,0x09, 0x09,0x19,0x07,0x0e,0x0e,0x24,0x1b,0x1b,0x24,0x19,0x0e,0x0e,0x19,0x0e,0x0e,0x0b,0x0b,0x00,0x00,0x0a,0x14,0x10,0x13,0x10,0x22,0x1c,0x13,0x0f,0x13,0x0f,0x24,0x1b,0x14,0x10,0x0a,0x09,0x11,0x00,0x12,0x0f,0x09,0x08,0x04,0x0d,0x09,0x09,0x07,0x05,0x0c,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x06,0x0e,0x0c,0x10,0x0f,0x0f,0x1a, 0x16,0x16,0x15,0x16,0x19,0x11,0x13,0x10,0x0b,0x19,0x1e,0x0c,0x1f,0x0e,0x17,0x19,0x19,0x19,0x0b,0x14,0x1b,0x14,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x10,0x10,0x10,0x17,0x0e,0x0e,0x19,0x09,0x09,0x19,0x09,0x09,0x19,0x0d,0x0d,0x00,0x0b,0x17,0x09,0x09,0x1b,0x0e,0x0e,0x14,0x0e, 0x0e,0x12,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x29,0x29,0x18,0x00,0x00,0x18,0x18,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x12,0x11,0x11,0x12,0x18,0x11,0x11,0x16,0x1a,0x12,0x11,0x1d,0x11,0x11,0x19,0x11,0x12,0x15,0x11,0x15,0x17,0x19,0x11,0x15, 0x12,0x13,0x11,0x13,0x11,0x12,0x13,0x11,0x15,0x10,0x12,0x15,0x11,0x11,0x0f,0x15,0x11,0x12,0x12,0x13,0x0c,0x0e,0x11,0x15,0x15,0x0f,0x00,0x00,0x1d,0x3a,0x13,0x00,0x03,0x08,0x08,0x0b,0x11,0x10,0x18,0x17,0x07,0x09,0x09,0x0c,0x14,0x06,0x0c,0x06,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x06,0x06,0x14,0x14,0x14, 0x0d,0x1c,0x13,0x11,0x12,0x14,0x0f,0x0e,0x14,0x15,0x08,0x0a,0x11,0x0e,0x1a,0x16,0x16,0x10,0x16,0x11,0x0f,0x0f,0x14,0x12,0x1b,0x11,0x10,0x11,0x09,0x0b,0x09,0x14,0x0c,0x08,0x0f,0x11,0x0d,0x11,0x0f,0x09,0x11,0x10,0x07,0x07,0x0e,0x07,0x19,0x10,0x11,0x11,0x11,0x0a,0x0c,0x0a,0x10,0x0e,0x15,0x0d,0x0e,0x0d,0x09,0x07,0x09,0x14, 0x13,0x13,0x12,0x0f,0x16,0x16,0x14,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0f,0x0f,0x0f,0x0f,0x07,0x07,0x07,0x07,0x10,0x11,0x11,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x0b,0x0b,0x10,0x10,0x0d,0x0c,0x0d,0x10,0x0c,0x1a,0x1a,0x16,0x08,0x0c,0x14,0x19,0x16,0x18,0x14,0x14,0x14,0x10,0x11,0x10,0x12,0x16,0x10,0x0b,0x0c,0x16,0x18,0x11, 0x0d,0x08,0x08,0x14,0x13,0x10,0x14,0x13,0x0f,0x0f,0x15,0x13,0x13,0x16,0x1b,0x1b,0x0f,0x1d,0x0b,0x0b,0x07,0x07,0x14,0x11,0x0e,0x10,0x05,0x10,0x09,0x09,0x10,0x10,0x0b,0x06,0x07,0x0b,0x23,0x13,0x0f,0x13,0x0f,0x0f,0x08,0x08,0x08,0x08,0x16,0x16,0x16,0x14,0x14,0x14,0x07,0x0b,0x0a,0x09,0x09,0x06,0x08,0x06,0x09,0x05,0x0b,0x0e, 0x08,0x0f,0x0c,0x11,0x0d,0x07,0x14,0x10,0x10,0x0e,0x10,0x11,0x14,0x14,0x0a,0x0b,0x0b,0x1b,0x1a,0x1c,0x0e,0x14,0x11,0x08,0x0f,0x0c,0x12,0x0d,0x12,0x0d,0x11,0x0c,0x06,0x13,0x0f,0x13,0x0f,0x14,0x14,0x14,0x0f,0x0f,0x0f,0x0f,0x0e,0x07,0x0e,0x09,0x0e,0x09,0x16,0x10,0x16,0x10,0x16,0x11,0x11,0x0a,0x11,0x0a,0x0f,0x0c,0x0f,0x0a, 0x0f,0x0d,0x14,0x10,0x14,0x10,0x11,0x0d,0x11,0x0d,0x0e,0x16,0x16,0x12,0x11,0x0d,0x11,0x0e,0x14,0x0c,0x0e,0x0b,0x20,0x12,0x0e,0x12,0x07,0x0b,0x17,0x09,0x12,0x0a,0x0a,0x12,0x0a,0x13,0x0f,0x12,0x0d,0x12,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x14,0x11,0x14,0x11,0x14,0x11,0x15,0x10,0x15,0x10,0x08,0x07,0x08,0x07,0x08,0x07,0x08, 0x07,0x0a,0x07,0x11,0x0e,0x0e,0x0e,0x07,0x16,0x10,0x16,0x10,0x16,0x11,0x16,0x11,0x11,0x0a,0x0f,0x0c,0x0f,0x0a,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x1b,0x15,0x10,0x0e,0x07,0x13,0x0f,0x19,0x18,0x16,0x11,0x06,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x10,0x0e,0x07,0x0c,0x10,0x11,0x1b,0x1b,0x1b,0x1a,0x0b,0x0b,0x06,0x08,0x08,0x13, 0x11,0x16,0x0b,0x17,0x13,0x18,0x08,0x13,0x11,0x0f,0x11,0x15,0x08,0x11,0x12,0x1a,0x16,0x0f,0x16,0x15,0x10,0x0f,0x0f,0x10,0x11,0x17,0x16,0x08,0x10,0x12,0x0d,0x11,0x08,0x10,0x10,0x0f,0x0d,0x11,0x11,0x08,0x0f,0x0e,0x11,0x0f,0x0d,0x11,0x11,0x0d,0x10,0x10,0x16,0x17,0x08,0x10,0x11,0x10,0x17,0x0f,0x14,0x0e,0x12,0x0f,0x08,0x1c, 0x1d,0x15,0x11,0x10,0x15,0x13,0x11,0x11,0x0e,0x14,0x0f,0x19,0x10,0x16,0x16,0x11,0x14,0x1a,0x15,0x16,0x15,0x10,0x12,0x0f,0x10,0x15,0x11,0x16,0x13,0x1c,0x1c,0x14,0x17,0x11,0x12,0x1e,0x11,0x0f,0x11,0x0f,0x0b,0x10,0x0f,0x16,0x0d,0x11,0x11,0x0e,0x0f,0x14,0x11,0x11,0x11,0x11,0x0d,0x0c,0x0e,0x14,0x0d,0x11,0x10,0x17,0x18,0x11, 0x15,0x0f,0x0d,0x18,0x0f,0x0f,0x11,0x0b,0x0d,0x0c,0x07,0x17,0x17,0x10,0x0e,0x0e,0x11,0x0e,0x0b,0x1d,0x21,0x12,0x0a,0x0b,0x0b,0x0b,0x07,0x0f,0x0c,0x10,0x16,0x11,0x15,0x11,0x09,0x0a,0x08,0x08,0x0e,0x0e,0x0e,0x0e,0x09,0x09,0x09,0x0e,0x09,0x0e,0x09,0x09,0x09,0x0e,0x0e,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13, 0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x08,0x07,0x08,0x07,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x14,0x10,0x14,0x10,0x15,0x11,0x15, 0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x0f,0x0a,0x0f,0x0f,0x16,0x11,0x08,0x0a,0x07,0x07,0x0f,0x0c,0x1a,0x17,0x12,0x0f,0x11,0x0e,0x16,0x11,0x10,0x0e,0x10,0x0e,0x12,0x0e,0x13,0x10,0x13,0x10,0x15,0x0f,0x16,0x11,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x09,0x09,0x09,0x09,0x0f, 0x0f,0x13,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x0d,0x14,0x11,0x14,0x11,0x14,0x11,0x14,0x11,0x14,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x09,0x14,0x11,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x08,0x07,0x08,0x07,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x0e,0x07,0x1a, 0x19,0x1a,0x19,0x1a,0x19,0x16,0x10,0x16,0x10,0x16,0x10,0x16,0x10,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x10,0x11,0x10,0x11,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x11,0x0a,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0c,0x0f,0x0a,0x0f,0x0a,0x0f,0x0a,0x0f,0x0a,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x12,0x0e,0x12, 0x0e,0x1b,0x15,0x1b,0x15,0x11,0x0d,0x11,0x0d,0x10,0x0e,0x11,0x0d,0x11,0x0d,0x11,0x0d,0x10,0x0a,0x15,0x0e,0x0f,0x07,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13,0x13,0x16,0x16,0x16,0x16,0x16,0x16,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x11,0x11,0x15,0x15,0x15,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x16,0x16,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0e,0x0e,0x0f,0x0f,0x0f,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x17,0x1c,0x1c,0x1c,0x1c,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x13,0x18,0x18,0x18,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x12,0x12,0x0d,0x0d,0x11, 0x11,0x08,0x08,0x11,0x11,0x10,0x10,0x17,0x17,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13,0x13,0x16,0x16,0x16,0x16,0x16,0x16,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x12,0x12,0x12,0x12,0x12,0x12,0x12, 0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x16,0x16,0x15,0x11,0x11,0x11,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0b,0x0b,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x11,0x11,0x10,0x10,0x10,0x10,0x13,0x13,0x12,0x11,0x11,0x11,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x16,0x11,0x11, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x12,0x11,0x11,0x11,0x11,0x12,0x12,0x0e,0x14,0x16,0x11,0x11,0x11,0x0f,0x10,0x0e,0x14,0x12,0x19,0x08,0x08,0x11,0x0e,0x07,0x0e,0x1a,0x16,0x11,0x16,0x1c,0x17,0x11,0x11,0x11,0x0f,0x0c,0x0f,0x09,0x0a,0x0f,0x0a,0x0f,0x16,0x15,0x11,0x0f,0x11,0x0d,0x12, 0x12,0x0d,0x0c,0x10,0x10,0x0b,0x0b,0x10,0x07,0x0b,0x0d,0x08,0x24,0x21,0x1e,0x19,0x15,0x0f,0x1f,0x1c,0x17,0x13,0x0f,0x08,0x07,0x16,0x11,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x0f,0x13,0x0f,0x13,0x0f,0x19,0x18,0x14,0x11,0x14,0x11,0x11,0x0e,0x16,0x11,0x16,0x11,0x12,0x0d,0x07,0x24,0x21,0x1e,0x14,0x11,0x1d,0x14, 0x16,0x10,0x13,0x0f,0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x08,0x07,0x08,0x07,0x16,0x11,0x16,0x11,0x11,0x0a,0x11,0x0a,0x14,0x10,0x14,0x10,0x0f,0x0c,0x15,0x10,0x15,0x11,0x10,0x11,0x0d,0x13,0x0f,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x10,0x0e,0x11,0x0f,0x10,0x10,0x11,0x0f,0x11,0x11,0x11,0x0e,0x0e,0x11,0x11,0x0f,0x12,0x0c,0x0c, 0x0f,0x10,0x08,0x11,0x11,0x0f,0x0e,0x0d,0x10,0x10,0x10,0x08,0x08,0x09,0x08,0x0b,0x07,0x11,0x19,0x19,0x19,0x10,0x10,0x11,0x11,0x14,0x15,0x13,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0c,0x07,0x07,0x08,0x08,0x0a,0x0a,0x11,0x11,0x10,0x0e,0x15,0x0e,0x0c,0x0d,0x0f,0x0d,0x0d,0x0b,0x0b,0x0b,0x0e,0x12,0x0e,0x10,0x0f,0x10, 0x07,0x0e,0x0b,0x11,0x0b,0x0b,0x1b,0x1c,0x1c,0x12,0x0e,0x15,0x17,0x11,0x11,0x0e,0x0e,0x10,0x11,0x10,0x14,0x10,0x13,0x17,0x11,0x14,0x11,0x11,0x0d,0x0e,0x0d,0x11,0x0f,0x12,0x0e,0x1a,0x19,0x12,0x0f,0x12,0x0f,0x12,0x0d,0x11,0x0e,0x13,0x11,0x10,0x0c,0x11,0x11,0x0d,0x07,0x16,0x0e,0x0e,0x19,0x14,0x13,0x11,0x1a,0x15,0x13,0x0e, 0x19,0x14,0x15,0x10,0x1b,0x16,0x10,0x0d,0x17,0x16,0x16,0x11,0x15,0x11,0x15,0x11,0x26,0x20,0x18,0x13,0x21,0x1a,0x19,0x14,0x11,0x0d,0x0f,0x0b,0x0c,0x00,0x00,0x1d,0x1c,0x11,0x0f,0x10,0x11,0x10,0x0f,0x10,0x0d,0x11,0x0e,0x15,0x11,0x18,0x13,0x1d,0x18,0x15,0x10,0x12,0x0d,0x0f,0x0c,0x19,0x14,0x14,0x11,0x18,0x12,0x18,0x12,0x08, 0x19,0x16,0x11,0x0f,0x15,0x11,0x13,0x10,0x13,0x0f,0x13,0x0f,0x19,0x18,0x0f,0x0f,0x15,0x0f,0x15,0x0f,0x19,0x16,0x10,0x0d,0x0f,0x0d,0x16,0x11,0x16,0x11,0x16,0x11,0x16,0x11,0x12,0x0d,0x10,0x0e,0x10,0x0e,0x10,0x0e,0x13,0x10,0x17,0x15,0x11,0x11,0x19,0x19,0x17,0x15,0x10,0x0e,0x1a,0x17,0x1d,0x19,0x15,0x0f,0x14,0x11,0x11,0x10, 0x10,0x0f,0x11,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x11,0x0a,0x0a,0x05,0x06,0x06,0x06,0x08,0x0c,0x08,0x07,0x0b,0x06,0x06,0x06,0x0a,0x0a,0x06,0x06,0x11,0x11,0x11,0x11,0x0a,0x08,0x08,0x0a,0x09,0x08,0x08,0x08,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x09,0x0a,0x0a,0x08,0x05,0x07,0x08,0x06, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0c,0x0a,0x07,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10, 0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10, 0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x13,0x09,0x12,0x0a,0x11,0x11,0x0a,0x0a,0x0a,0x0a,0x0a,0x08,0x09,0x09,0x0a,0x08,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11, 0x0e,0x13,0x18,0x0e,0x0d,0x10,0x10,0x0c,0x0c,0x07,0x09,0x0e,0x0b,0x14,0x11,0x11,0x0e,0x12,0x12,0x12,0x1b,0x10,0x11,0x11,0x0d,0x0d,0x0d,0x0c,0x0f,0x10,0x15,0x10,0x0e,0x15,0x0d,0x0c,0x0c,0x0f,0x0b,0x0e,0x11,0x0d,0x11,0x10,0x0a,0x0e,0x0a,0x0a,0x0c,0x09,0x09,0x0c,0x0c,0x05,0x07,0x0a,0x08,0x0f,0x0d,0x0d,0x0c,0x0b,0x0a,0x0a, 0x08,0x0c,0x0f,0x09,0x09,0x0a,0x0e,0x0a,0x0a,0x09,0x09,0x08,0x08,0x0a,0x05,0x09,0x0e,0x0a,0x0a,0x08,0x0a,0x0a,0x0a,0x06,0x0a,0x09,0x0e,0x08,0x09,0x0a,0x08,0x0a,0x0c,0x09,0x05,0x06,0x0a,0x08,0x0a,0x08,0x0a,0x0c,0x09,0x11,0x05,0x0a,0x10,0x19,0x12,0x10,0x10,0x19,0x13,0x19,0x16,0x0f,0x11,0x0f,0x0d,0x21,0x0d,0x11,0x1a,0x1b, 0x1b,0x12,0x13,0x12,0x0d,0x0e,0x0f,0x0c,0x0d,0x0f,0x06,0x00,0x00,0x00,0x00,0x11,0x12,0x12,0x12,0x0e,0x0b,0x11,0x11,0x09,0x19,0x10,0x11,0x0a,0x0a,0x0d,0x0a,0x0d,0x11,0x0d,0x11,0x1a,0x13,0x09,0x08,0x11,0x0f,0x11,0x11,0x11,0x09,0x11,0x0e,0x07,0x19,0x10,0x11,0x0a,0x0c,0x0d,0x0e,0x0d,0x0d,0x0f,0x11,0x11,0x0f,0x0d,0x0d,0x15, 0x07,0x0e,0x07,0x10,0x0d,0x0a,0x08,0x08,0x0a,0x08,0x05,0x05,0x0a,0x0a,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x07,0x0e,0x0e,0x0a,0x0a,0x0a,0x0a,0x0b,0x07,0x05,0x06,0x0a,0x0a,0x0a,0x09,0x08,0x08,0x08,0x09,0x08,0x0a,0x00,0x00,0x00,0x00,0x06,0x09,0x09,0x0a,0x08,0x09,0x10,0x10,0x10,0x10,0x0a,0x00,0x00,0x00,0x00,0x0d,0x09,0x08, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x08,0x08,0x10,0x10,0x10,0x10,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x10,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x05,0x0b,0x0b,0x0a,0x0b,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x09,0x09,0x0b,0x0a,0x0b,0x0b,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x17,0x12,0x15,0x11,0x16,0x12,0x1b,0x16,0x10,0x0b,0x0f,0x14,0x10,0x18,0x14,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x0a,0x0a,0x0a,0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x18,0x1d,0x0c,0x07,0x0f,0x11,0x0c,0x0f,0x0f,0x11,0x11,0x0f,0x1d, 0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x13,0x0f,0x0f,0x0f,0x0a,0x11,0x0a,0x16,0x13,0x0f,0x0a,0x18,0x0f,0x18,0x07,0x0a,0x11,0x11,0x13,0x13,0x13,0x11,0x11,0x11,0x18,0x07,0x11,0x07,0x0f,0x0c,0x07,0x07,0x0f,0x07,0x16,0x07,0x1b,0x0f,0x1b,0x1b,0x11,0x11,0x11,0x0f,0x0f,0x0c,0x0c,0x22,0x22,0x27,0x27,0x18,0x18,0x0f,0x0f,0x05, 0x1d,0x16,0x18,0x13,0x11,0x13,0x0f,0x0f,0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x07,0x13,0x00,0x13,0x13,0x13,0x0a,0x0f,0x0f,0x1b,0x0a,0x1b,0x0a,0x11,0x13,0x11,0x0c,0x1b,0x0f,0x1b,0x0f,0x16,0x18,0x0a,0x0f,0x0f,0x0c,0x07,0x0f,0x11,0x0f,0x11,0x0f,0x11,0x11,0x0f,0x13,0x13,0x1b,0x0a,0x0f,0x0c,0x13,0x0f,0x0a, 0x0f,0x0f,0x0f,0x1b,0x0a,0x1b,0x0a,0x07,0x11,0x0b,0x1d,0x0f,0x0f,0x13,0x13,0x1d,0x0f,0x00,0x00,0x00,0x13,0x00,0x13,0x13,0x13,0x13,0x16,0x13,0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x0c,0x0c,0x0f,0x0f,0x16,0x18,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x13,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0f,0x0c,0x0c,0x0c,0x22,0x18,0x22,0x18,0x22,0x18,0x27,0x1d,0x27,0x1d,0x18,0x0f,0x11,0x11,0x11,0x1d,0x1d,0x0f,0x0f,0x1d,0x0f,0x0f,0x1d,0x0f,0x0f,0x1d,0x0f,0x0f,0x16,0x16,0x1f,0x1d,0x1b,0x0f,0x18,0x0f,0x18,0x0f,0x18,0x0f,0x1b, 0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x13,0x0a,0x13,0x0a,0x13,0x0a,0x13,0x0a,0x13,0x0a,0x13,0x13,0x0a,0x13,0x0a,0x10,0x13,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x18,0x1b,0x16,0x18,0x0a,0x0f,0x16,0x18,0x16,0x18,0x00,0x00,0x00,0x00,0x00,0x21,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0c,0x00,0x00,0x11,0x00, 0x00,0x00,0x22,0x18,0x27,0x1d,0x0f,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x1b,0x1b,0x0b,0x11,0x11,0x11,0x24,0x18,0x0f,0x2c,0x1f,0x0a,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0c,0x0c,0x16,0x13,0x13,0x0f,0x00,0x00,0x00,0x0a,0x0a,0x0a, 0x0a,0x24,0x2c,0x00,0x00,0x00,0x00,0x00,0x11,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x0c,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x11,0x11,0x13,0x11,0x0f,0x0f,0x0c,0x22,0x18,0x0f,0x11,0x11,0x11,0x0f,0x11,0x11,0x11,0x0f,0x11,0x11,0x11,0x1d,0x0f,0x0f,0x1d,0x0f,0x0f,0x1b,0x0f,0x0f,0x1b,0x0f, 0x0f,0x1b,0x0f,0x0f,0x11,0x11,0x11,0x11,0x13,0x0a,0x13,0x0a,0x13,0x0a,0x13,0x13,0x0a,0x0a,0x0c,0x0c,0x22,0x18,0x13,0x11,0x11,0x00,0x0f,0x0f,0x0f,0x0b,0x11,0x14,0x12,0x0f,0x0f,0x0a,0x07,0x16,0x11,0x11,0x0a,0x10,0x0e,0x0e,0x0d,0x0e,0x07,0x0f,0x0c,0x12,0x0e,0x11,0x0d,0x10,0x0d,0x14,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x15,0x0d,0x0e,0x0e,0x08,0x0f,0x10,0x11,0x0f,0x0a,0x16,0x11,0x13,0x10,0x12,0x0e,0x11,0x0f,0x0b,0x14,0x0b,0x0c,0x0c,0x0e,0x11,0x11,0x0f,0x1d,0x0f,0x1d,0x0a,0x07,0x05,0x10,0x06,0x04,0x00,0x04,0x06,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x1b,0x0c,0x16,0x11,0x1b,0x15,0x12, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x1b,0x19,0x0e,0x19,0x0e,0x19,0x13,0x14,0x14,0x14,0x16,0x19,0x1d,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x14,0x14,0x14,0x14,0x15,0x11,0x1f,0x18,0x0e,0x0e,0x08,0x08,0x08,0x0b,0x06,0x10,0x07,0x07,0x18,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00, 0x06,0x00,0x00,0x06,0x00,0x00,0x12,0x11,0x0d,0x0e,0x14,0x08,0x0a,0x14,0x14,0x08,0x10,0x10,0x10,0x14,0x14,0x08,0x0c,0x14,0x12,0x12,0x12,0x10,0x11,0x13,0x10,0x17,0x15,0x0f,0x0f,0x0f,0x07,0x0b,0x10,0x10,0x10,0x10,0x10,0x12,0x12,0x0e,0x14,0x10,0x10,0x14,0x10,0x15,0x10,0x17,0x17,0x17,0x17,0x12,0x12,0x12,0x11,0x0d,0x0e,0x14, 0x09,0x0a,0x14,0x09,0x10,0x10,0x10,0x14,0x0c,0x14,0x12,0x12,0x11,0x13,0x10,0x17,0x15,0x08,0x11,0x10,0x12,0x13,0x23,0x00,0x12,0x10,0x13,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x08,0x00, 0x16,0x13,0x13,0x14,0x10,0x13,0x16,0x16,0x0e,0x12,0x16,0x15,0x13,0x16,0x18,0x17,0x13,0x10,0x10,0x16,0x14,0x11,0x14,0x14,0x13,0x14,0x14,0x15,0x11,0x12,0x14,0x13,0x16,0x12,0x12,0x13,0x13,0x18,0x0e,0x11,0x11,0x19,0x10,0x10,0x16,0x1a,0x12,0x10,0x1e,0x10,0x10,0x16,0x10,0x10,0x16,0x10,0x16,0x18,0x19,0x10,0x16,0x10,0x13,0x10, 0x12,0x10,0x12,0x10,0x12,0x16,0x10,0x12,0x13,0x10,0x10,0x11,0x1c,0x10,0x10,0x11,0x11,0x0c,0x0a,0x10,0x10,0x10,0x10,0x10,0x1a,0x10,0x1a,0x0e,0x10,0x1a,0x13,0x10,0x1a,0x16,0x16,0x1a,0x11,0x10,0x1a,0x1a,0x10,0x10,0x10,0x10,0x10,0x10,0x1a,0x1a,0x11,0x10,0x10,0x1a,0x11,0x10,0x10,0x10,0x1a,0x17,0x14,0x14,0x14,0x14,0x15,0x12, 0x14,0x17,0x14,0x13,0x10,0x17,0x14,0x14,0x11,0x13,0x14,0x16,0x15,0x11,0x14,0x13,0x15,0x13,0x16,0x14,0x15,0x15,0x14,0x12,0x14,0x14,0x15,0x17,0x13,0x16,0x15,0x03,0x03,0x04,0x06,0x04,0x08,0x0a,0x19,0x10,0x12,0x11,0x10,0x12,0x10,0x10,0x13,0x11,0x10,0x09,0x18,0x11,0x10,0x10,0x10,0x12,0x0f,0x11,0x08,0x11,0x0f,0x10,0x0c,0x19, 0x10,0x10,0x10,0x11,0x18,0x10,0x11,0x0b,0x18,0x11,0x11,0x14,0x14,0x06,0x08,0x21,0x21,0x21,0x21,0x29,0x10,0x10,0x07,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x10,0x10,0x10,0x10,0x10,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0e,0x0f,0x11,0x0c,0x0c,0x11,0x12,0x07,0x09,0x0e,0x0c,0x16,0x13,0x12,0x0e,0x12,0x0e,0x0c,0x0d,0x11,0x0f,0x17,0x0f,0x0e,0x0e,0x14,0x16,0x0c,0x12,0x0e,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x07,0x07,0x07,0x07,0x13,0x12,0x12,0x12,0x12,0x12,0x11, 0x11,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x11,0x11,0x11,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x0f,0x12,0x12,0x07,0x07,0x07,0x07,0x07,0x10,0x09,0x0e,0x0c,0x0c,0x0c,0x0c,0x13,0x13,0x13,0x13,0x12,0x12,0x12,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x17,0x17,0x17,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0f,0x14,0x12,0x0f,0x0e,0x0b,0x10,0x0c,0x0e,0x12,0x12,0x07,0x0e,0x0f,0x16,0x13,0x0d,0x12,0x12,0x0e,0x0d,0x0d,0x0e,0x12,0x0f,0x13,0x12,0x0f,0x0c,0x12,0x07,0x12,0x0e,0x12,0x07,0x0e,0x0c,0x11,0x0c,0x0f,0x0c,0x07,0x07,0x09,0x18,0x18,0x12,0x0e,0x0e,0x12,0x0f,0x0e,0x0e,0x0c,0x11,0x0c,0x15,0x0d,0x13,0x13, 0x0e,0x10,0x16,0x12,0x12,0x12,0x0e,0x0f,0x0d,0x0e,0x12,0x0f,0x12,0x10,0x17,0x18,0x10,0x14,0x0e,0x0f,0x19,0x0e,0x0c,0x11,0x11,0x12,0x1a,0x1a,0x13,0x0f,0x11,0x0c,0x11,0x10,0x10,0x14,0x0f,0x0f,0x14,0x11,0x11,0x0a,0x12,0x12,0x11,0x0e,0x0e,0x1a,0x16,0x0e,0x0f,0x11,0x11,0x12,0x12,0x15,0x14,0x0a,0x1b,0x11,0x10,0x11,0x13,0x13, 0x0f,0x0f,0x08,0x16,0x14,0x14,0x0e,0x14,0x06,0x06,0x0d,0x0d,0x06,0x06,0x12,0x0c,0x08,0x16,0x14,0x08,0x06,0x06,0x0d,0x0b,0x0b,0x07,0x07,0x07,0x0b,0x14,0x0e,0x09,0x12,0x14,0x11,0x11,0x0e,0x16,0x10,0x11,0x0a,0x0d,0x0f,0x0c,0x06,0x07,0x0b,0x0f,0x0a,0x13,0x13,0x13,0x1b,0x16,0x1b,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x16,0x18, 0x0a,0x0a,0x0f,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x11,0x0f,0x0f,0x22,0x18,0x22,0x18,0x27,0x1d,0x27,0x1d,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0f,0x0f,0x1b,0x1b,0x0f,0x0f,0x16,0x18,0x0a,0x0a,0x16,0x18,0x0a,0x0a,0x16,0x18,0x0a,0x0a,0x1d,0x16,0x18,0x0f,0x11,0x11,0x13,0x0a,0x13,0x16,0x0f,0x0f,0x0a,0x0a,0x0a, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1b,0x0a,0x16,0x0f,0x0f,0x07,0x0f,0x0f,0x0f,0x0f,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x22,0x18,0x22,0x18,0x22,0x18,0x27,0x1d,0x27,0x1d, 0x18,0x18,0x18,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x16,0x0f,0x0f,0x16,0x0f,0x0f,0x1b,0x0f,0x1f,0x1d,0x1b,0x0f,0x18,0x0f,0x18,0x0f,0x18,0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x1b,0x0f,0x13,0x13,0x13,0x13,0x13,0x0a,0x13,0x13,0x0a,0x0a,0x13,0x0a,0x13,0x0a,0x13,0x0f,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0a,0x0a,0x0f,0x0a,0x0a,0x0a,0x0a,0x00,0x22,0x18,0x27,0x1d,0x1b,0x0f,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x0f,0x0f,0x0c,0x22,0x18,0x1d,0x1d,0x1b,0x1b,0x1b,0x11,0x11,0x11,0x11,0x13,0x0a,0x13,0x0a,0x13,0x0a,0x22,0x18,0x11,0x13,0x11,0x11,0x11,0x13,0x11,0x11,0x22,0x22,0x18,0x18, 0x0c,0x0c,0x11,0x11,0x11,0x11,0x0a,0x0a,0x0a,0x0a,0x16,0x18,0x0a,0x0a,0x16,0x18,0x0a,0x0a,0x16,0x18,0x0a,0x0a,0x11,0x11,0x11,0x11,0x1b,0x0a,0x1b,0x0a,0x11,0x13,0x11,0x11,0x22,0x22,0x18,0x18,0x22,0x22,0x18,0x18,0x18,0x18,0x0f,0x0f,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x07,0x07,0x0a,0x07,0x00,0x00,0x00,0x18, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x18,0x11,0x18,0x11,0x18,0x11,0x18,0x13,0x13,0x13,0x07,0x07,0x0f,0x0c,0x11,0x12,0x11,0x10,0x10,0x11,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x0d,0x10,0x0f,0x11,0x12,0x12,0x13,0x11,0x10,0x13,0x0f, 0x13,0x16,0x13,0x16,0x18,0x12,0x16,0x14,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x0d,0x10,0x12,0x11,0x13,0x11,0x13,0x11,0x11,0x11,0x0f,0x0f,0x16,0x14,0x14,0x14,0x14,0x11,0x11,0x11,0x15,0x16,0x16,0x16,0x1b,0x1b,0x14,0x1b,0x1b,0x15,0x19,0x19,0x10,0x16,0x19,0x16,0x11,0x19,0x15,0x14,0x14,0x12,0x13,0x16,0x17, 0x14,0x12,0x14,0x11,0x0f,0x1b,0x1b,0x1b,0x18,0x1b,0x1b,0x14,0x1b,0x1b,0x15,0x16,0x17,0x16,0x15,0x15,0x13,0x1a,0x16,0x18,0x15,0x15,0x11,0x15,0x14,0x14,0x19,0x16,0x15,0x1a,0x10,0x0f,0x10,0x10,0x12,0x12,0x14,0x15,0x11,0x11,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x10,0x10,0x10,0x0f,0x0f,0x11,0x12,0x11,0x11,0x0d,0x10,0x10, 0x11,0x12,0x16,0x18,0x13,0x13,0x12,0x16,0x13,0x14,0x0f,0x0e,0x11,0x10,0x0e,0x0e,0x10,0x10,0x0e,0x0d,0x12,0x0d,0x10,0x0e,0x10,0x17,0x10,0x18,0x10,0x10,0x11,0x16,0x09,0x17,0x14,0x15,0x13,0x10,0x16,0x11,0x17,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x12,0x12,0x12,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0d,0x0d,0x0d,0x0e,0x0d, 0x09,0x09,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x12,0x08,0x08,0x08,0x09,0x09,0x08,0x08,0x08,0x09,0x08,0x08,0x08,0x1a,0x1a,0x1a,0x1a,0x0e,0x16,0x15,0x0e,0x0c,0x0e,0x0f,0x10,0x0e,0x18,0x18,0x19,0x0d,0x1d,0x0e,0x18,0x18,0x18,0x17,0x10,0x0e,0x0e,0x17,0x11,0x17,0x14,0x0f,0x0d,0x0c,0x1e,0x0c,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e, 0x28,0x18,0x18,0x0c,0x07,0x0d,0x07,0x0d,0x07,0x07,0x07,0x0e,0x11,0x11,0x10,0x0b,0x0b,0x07,0x07,0x07,0x0b,0x07,0x0c,0x19,0x06,0x1a,0x1a,0x1a,0x11,0x11,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x22,0x22,0x13,0x22,0x22,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x0e,0x11,0x0e,0x0f,0x0c,0x0a,0x0a,0x14,0x10,0x15,0x0c,0x21,0x1a,0x11,0x10,0x1b,0x17,0x18,0x16,0x1e,0x18,0x1b,0x16,0x13,0x0e,0x15,0x11,0x1b,0x15,0x16,0x12,0x16,0x11,0x19,0x13,0x19,0x13,0x20,0x18,0x16,0x11,0x16,0x11,0x23,0x1a,0x17,0x00,0x1d,0x1d, 0x1d,0x0e,0x00,0x00,0x11,0x0f,0x14,0x10,0x0f,0x0c,0x1f,0x1a,0x1b,0x19,0x15,0x11,0x14,0x11,0x0f,0x0c,0x15,0x11,0x0f,0x0c,0x18,0x13,0x13,0x10,0x1c,0x18,0x10,0x11,0x15,0x15,0x17,0x0d,0x06,0x0d,0x14,0x0d,0x1d,0x1d,0x07,0x00,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x0c,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, 0x21,0x10,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x17, 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0e,0x14, 0x15,0x08,0x06,0x08,0x06,0x15,0x10,0x16,0x12,0x10,0x0e,0x0f,0x0e,0x11,0x11,0x0c,0x0c,0x21,0x18,0x21,0x1a,0x1d,0x19,0x1a,0x13,0x1a,0x13,0x1a,0x13,0x12,0x0d,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x10,0x09,0x0e,0x07,0x16,0x11,0x19,0x14,0x27,0x1d,0x10,0x11,0x14,0x14,0x17,0x19,0x16,0x11,0x1c,0x17,0x10,0x0c,0x10,0x0e,0x12,0x0e,0x1b, 0x15,0x12,0x0f,0x10,0x11,0x10,0x11,0x0e,0x0c,0x0e,0x0b,0x0e,0x0b,0x0f,0x0f,0x09,0x14,0x0a,0x1c,0x13,0x0a,0x11,0x12,0x0d,0x16,0x10,0x0b,0x0a,0x11,0x11,0x11,0x0e,0x07,0x16,0x11,0x0b,0x0a,0x12,0x0d,0x15,0x0b,0x17,0x11,0x12,0x0d,0x14,0x11,0x11,0x0e,0x16,0x10,0x11,0x0a,0x0f,0x0c,0x16,0x0c,0x0f,0x19,0x0e,0x10,0x1a,0x08,0x21, 0x1a,0x1a,0x22,0x1a,0x1b,0x1b,0x19,0x1a,0x1b,0x0f,0x0e,0x12,0x14,0x1a,0x14,0x1b,0x07,0x0d,0x11,0x19,0x1e,0x14,0x1e,0x12,0x12,0x17,0x14,0x21,0x1b,0x0f,0x1b,0x0a,0x1b,0x0a,0x11,0x11,0x11,0x11,0x18,0x18,0x18,0x18,0x1d,0x0f,0x0f,0x1d,0x16,0x0f,0x0f,0x16,0x13,0x0a,0x0a,0x13,0x11,0x11,0x11,0x11,0x16,0x0a,0x0a,0x18,0x16,0x0a, 0x0a,0x18,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0x0f,0x0b,0x10,0x0f,0x16,0x11,0x11,0x19,0x13,0x16,0x16,0x18,0x18,0x11,0x0e,0x1d,0x17,0x1e,0x19,0x14,0x11,0x09,0x09,0x11,0x13,0x0c,0x11,0x0f, 0x11,0x0e,0x15,0x17,0x0c,0x11,0x0c,0x06,0x0b,0x0f,0x10,0x06,0x06,0x05,0x06,0x0b,0x0b,0x0b,0x0d,0x2b,0x3a,0x0a,0x0c,0x04,0x08,0x0b,0x0c,0x09,0x0e,0x0f,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x0e,0x0e,0x27,0x10,0x16,0x1b,0x1a,0x13,0x0d,0x10,0x15,0x15,0x0e,0x09,0x13,0x0f,0x14,0x10,0x13,0x0f,0x10, 0x16,0x11,0x11,0x0f,0x16,0x12,0x18,0x0d,0x0f,0x12,0x09,0x11,0x0a,0x0a,0x07,0x19,0x11,0x10,0x0f,0x0f,0x11,0x1b,0x1b,0x1b,0x1d,0x1d,0x10,0x0e,0x08,0x0f,0x0d,0x12,0x0d,0x13,0x07,0x10,0x11,0x19,0x19,0x12,0x10,0x11,0x10,0x0f,0x0d,0x0f,0x0d,0x0e,0x09,0x0a,0x07,0x06,0x0a,0x11,0x12,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x00,0x08,0x08,0x08,0x07,0x07,0x31,0x1d,0x19,0x1e,0x08,0x08,0x09,0x0b,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x1b,0x0a,0x0a,0x1b,0x08,0x0f,0x0f,0x27,0x1d,0x1d,0x27,0x1b,0x0f,0x0f,0x1b,0x0f,0x0f,0x0c,0x0c,0x00,0x00,0x0a,0x16,0x11,0x15,0x11,0x24,0x1e,0x14,0x10, 0x14,0x10,0x27,0x1d,0x16,0x11,0x0b,0x09,0x12,0x00,0x14,0x10,0x0a,0x09,0x05,0x0e,0x0a,0x0a,0x07,0x06,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x06,0x0f,0x0c,0x11,0x11,0x10,0x1c,0x17,0x17,0x17,0x18,0x1b,0x12,0x14,0x11,0x0b,0x1b,0x21,0x0d,0x21,0x0f,0x18,0x1b,0x1b,0x1b,0x0c,0x16,0x1d,0x16,0x13,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x11,0x11,0x11,0x18,0x0f,0x0f,0x1b,0x0a,0x0a,0x1b,0x0a,0x0a,0x1b,0x0e,0x0e,0x00,0x0c,0x18,0x0a,0x0a,0x1d,0x0f,0x0f,0x16,0x0f,0x0f,0x13,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x2c,0x2c,0x1a,0x00,0x00,0x1a,0x1a,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x13,0x12,0x13,0x13,0x1a,0x13,0x12,0x17,0x1c,0x13,0x12,0x1f,0x12,0x12,0x1b,0x12,0x14,0x17,0x13,0x16,0x19,0x1a,0x13,0x16,0x13,0x14,0x12,0x14,0x12,0x13,0x14,0x12,0x17,0x11,0x13,0x17,0x12,0x12,0x11,0x17,0x13,0x13,0x13,0x14,0x0d,0x0f,0x13,0x17,0x17,0x10,0x00,0x00, 0x20,0x40,0x15,0x00,0x03,0x09,0x09,0x0d,0x13,0x11,0x1a,0x1a,0x07,0x0a,0x0a,0x0d,0x16,0x07,0x0d,0x07,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x16,0x16,0x16,0x0e,0x1f,0x15,0x12,0x14,0x16,0x10,0x10,0x16,0x17,0x09,0x0b,0x13,0x0f,0x1d,0x18,0x18,0x12,0x18,0x13,0x11,0x11,0x16,0x14,0x1e,0x13,0x12,0x12, 0x0a,0x0c,0x0a,0x16,0x0d,0x09,0x10,0x13,0x0f,0x13,0x11,0x0a,0x13,0x12,0x08,0x08,0x10,0x08,0x1c,0x12,0x13,0x13,0x13,0x0b,0x0e,0x0b,0x12,0x0f,0x17,0x0f,0x0f,0x0e,0x0a,0x08,0x0a,0x16,0x15,0x15,0x14,0x10,0x18,0x18,0x16,0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x11,0x11,0x11,0x11,0x08,0x08,0x08,0x08,0x12,0x13,0x13,0x13,0x13,0x13, 0x12,0x12,0x12,0x12,0x0c,0x0c,0x11,0x11,0x0e,0x0d,0x0f,0x11,0x0d,0x1c,0x1c,0x19,0x09,0x0d,0x16,0x1c,0x18,0x1a,0x16,0x16,0x16,0x11,0x12,0x11,0x14,0x18,0x11,0x0d,0x0e,0x18,0x1b,0x13,0x0e,0x09,0x09,0x16,0x15,0x11,0x16,0x15,0x10,0x10,0x17,0x15,0x15,0x18,0x1e,0x1e,0x10,0x20,0x0c,0x0c,0x07,0x07,0x16,0x13,0x0f,0x12,0x06,0x11, 0x0a,0x0a,0x12,0x12,0x0c,0x07,0x07,0x0c,0x27,0x15,0x10,0x15,0x10,0x10,0x09,0x09,0x09,0x09,0x18,0x18,0x18,0x16,0x16,0x16,0x08,0x0c,0x0b,0x0a,0x0a,0x06,0x09,0x07,0x0a,0x06,0x0c,0x0f,0x09,0x11,0x0e,0x12,0x0e,0x08,0x16,0x12,0x12,0x0f,0x12,0x13,0x16,0x16,0x0b,0x0c,0x0c,0x1e,0x1d,0x1e,0x10,0x16,0x13,0x09,0x11,0x0e,0x14,0x0f, 0x14,0x0f,0x13,0x0d,0x07,0x15,0x10,0x15,0x10,0x16,0x16,0x16,0x10,0x11,0x10,0x11,0x0f,0x08,0x0f,0x0a,0x0f,0x0a,0x18,0x12,0x18,0x12,0x18,0x13,0x13,0x0b,0x13,0x0b,0x11,0x0e,0x11,0x0b,0x11,0x0e,0x16,0x12,0x16,0x12,0x12,0x0e,0x12,0x0e,0x0f,0x18,0x18,0x14,0x13,0x0e,0x12,0x10,0x16,0x0d,0x0f,0x0d,0x24,0x14,0x10,0x13,0x07,0x0c, 0x1a,0x0a,0x13,0x0b,0x0b,0x13,0x0b,0x15,0x10,0x14,0x0f,0x14,0x0f,0x10,0x11,0x10,0x11,0x10,0x11,0x16,0x13,0x16,0x13,0x16,0x13,0x17,0x12,0x17,0x12,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x0b,0x08,0x13,0x10,0x10,0x0f,0x08,0x18,0x12,0x18,0x12,0x18,0x13,0x18,0x13,0x13,0x0b,0x11,0x0e,0x11,0x0b,0x16,0x12,0x16,0x12,0x16,0x12, 0x16,0x12,0x1e,0x17,0x12,0x0f,0x08,0x15,0x10,0x1c,0x1b,0x18,0x13,0x07,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x12,0x0f,0x07,0x0d,0x11,0x13,0x1e,0x1e,0x1e,0x1d,0x0c,0x0c,0x07,0x09,0x09,0x15,0x12,0x19,0x0c,0x1a,0x15,0x1a,0x09,0x15,0x12,0x10,0x12,0x17,0x09,0x13,0x14,0x1d,0x18,0x10,0x18,0x17,0x12,0x11,0x11,0x12,0x13,0x19,0x18,0x09, 0x12,0x14,0x0e,0x12,0x09,0x12,0x12,0x11,0x0e,0x12,0x13,0x09,0x11,0x10,0x12,0x11,0x0e,0x13,0x13,0x0f,0x12,0x11,0x18,0x1a,0x09,0x12,0x13,0x12,0x1a,0x10,0x16,0x0f,0x14,0x11,0x09,0x1f,0x1f,0x17,0x13,0x12,0x17,0x15,0x12,0x12,0x0f,0x16,0x10,0x1c,0x11,0x18,0x18,0x13,0x16,0x1d,0x17,0x18,0x17,0x12,0x14,0x11,0x12,0x17,0x13,0x18, 0x15,0x1e,0x1f,0x17,0x19,0x12,0x14,0x21,0x13,0x10,0x13,0x11,0x0c,0x12,0x11,0x18,0x0e,0x13,0x13,0x10,0x11,0x16,0x12,0x13,0x12,0x13,0x0f,0x0d,0x0f,0x16,0x0f,0x13,0x12,0x1a,0x1a,0x13,0x17,0x10,0x0f,0x1a,0x10,0x11,0x12,0x0c,0x0f,0x0e,0x08,0x19,0x1a,0x12,0x10,0x0f,0x12,0x0f,0x0d,0x20,0x24,0x14,0x0b,0x0c,0x0c,0x0c,0x08,0x11, 0x0e,0x12,0x18,0x13,0x17,0x13,0x0a,0x0b,0x09,0x09,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x0a,0x0f,0x0a,0x0f,0x0a,0x0a,0x0a,0x0f,0x0f,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x15,0x10,0x10,0x11,0x10,0x11,0x10,0x11,0x10,0x11,0x10,0x11,0x10,0x11,0x10,0x11,0x10, 0x11,0x09,0x08,0x09,0x08,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x16,0x12,0x16,0x12,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x12,0x0f,0x12,0x0f,0x12,0x0f,0x11,0x0b,0x10,0x11,0x18,0x13,0x09,0x0b,0x08,0x08,0x10,0x0d,0x1d,0x19,0x14, 0x11,0x13,0x10,0x18,0x13,0x12,0x0f,0x12,0x0f,0x14,0x10,0x15,0x12,0x15,0x12,0x17,0x11,0x18,0x13,0x0a,0x0a,0x0a,0x0a,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x10,0x11,0x15,0x10,0x12,0x13,0x12,0x13,0x12,0x13,0x14,0x0f,0x16,0x13,0x16,0x13,0x16,0x13,0x16,0x13,0x16,0x13,0x10,0x11,0x10,0x11,0x10,0x11,0x10, 0x11,0x10,0x11,0x10,0x0a,0x16,0x13,0x17,0x12,0x17,0x12,0x17,0x12,0x17,0x12,0x17,0x12,0x09,0x08,0x09,0x08,0x13,0x10,0x13,0x10,0x13,0x10,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x0f,0x08,0x1d,0x1c,0x1d,0x1c,0x1d,0x1c,0x18,0x12,0x18,0x12,0x18,0x12,0x18,0x12,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x12,0x13,0x12,0x13,0x13,0x0b,0x13, 0x0b,0x13,0x0b,0x13,0x0b,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0e,0x11,0x0b,0x11,0x0b,0x11,0x0b,0x11,0x0b,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x14,0x0f,0x14,0x0f,0x1e,0x17,0x1e,0x17,0x13,0x0f,0x13,0x0f,0x12,0x0f,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0b,0x17,0x0f,0x10,0x08,0x14,0x14,0x14,0x14,0x14, 0x14,0x14,0x14,0x15,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x12,0x12,0x17,0x17,0x17,0x17,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x19,0x19,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x10,0x10,0x11,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x1a,0x1a,0x1f, 0x1f,0x1f,0x1f,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x15,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x14,0x14,0x0e,0x0e,0x12,0x12,0x09,0x09,0x13,0x13,0x12,0x12,0x1a,0x1a,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x19,0x19,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,0x15,0x13,0x13,0x13,0x13,0x13,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x19,0x19,0x17,0x13,0x13,0x13,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x0c,0x0c,0x13,0x13,0x13,0x12,0x12,0x12,0x12,0x13,0x13,0x12,0x12,0x12,0x12,0x15,0x15,0x14,0x13,0x13,0x13,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1a,0x18,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x14,0x12,0x13,0x12,0x13,0x14,0x14,0x0f,0x16,0x18,0x12,0x13,0x13, 0x10,0x11,0x10,0x16,0x14,0x1c,0x09,0x09,0x13,0x10,0x08,0x10,0x1d,0x18,0x12,0x18,0x1f,0x19,0x13,0x13,0x12,0x11,0x0e,0x11,0x09,0x0b,0x11,0x0b,0x11,0x18,0x17,0x12,0x11,0x12,0x0e,0x14,0x14,0x0e,0x0d,0x11,0x11,0x0c,0x0d,0x11,0x08,0x0c,0x0f,0x09,0x28,0x24,0x21,0x1b,0x17,0x10,0x22,0x1f,0x1a,0x15,0x10,0x09,0x08,0x18,0x13,0x16, 0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x11,0x15,0x10,0x15,0x10,0x1c,0x1b,0x16,0x13,0x16,0x13,0x13,0x10,0x18,0x13,0x18,0x13,0x14,0x0e,0x08,0x28,0x24,0x21,0x16,0x13,0x20,0x16,0x18,0x12,0x15,0x10,0x15,0x10,0x10,0x11,0x10,0x11,0x09,0x08,0x09,0x08,0x18,0x13,0x18,0x13,0x12,0x0b,0x13,0x0b,0x16,0x12,0x16,0x12,0x10,0x0e, 0x17,0x12,0x17,0x13,0x12,0x12,0x0e,0x15,0x10,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x12,0x0f,0x13,0x10,0x12,0x12,0x13,0x10,0x13,0x13,0x13,0x0f,0x0f,0x13,0x13,0x11,0x14,0x0d,0x0d,0x10,0x12,0x09,0x13,0x13,0x11,0x0f,0x0f,0x12,0x12,0x12,0x08,0x09,0x0a,0x09,0x0c,0x08,0x13,0x1c,0x1c,0x1c,0x12,0x12,0x13,0x13,0x16,0x17,0x14, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x0d,0x08,0x08,0x09,0x09,0x0b,0x0b,0x13,0x13,0x12,0x0f,0x17,0x0f,0x0d,0x0e,0x10,0x0e,0x0e,0x0c,0x0c,0x0c,0x0f,0x14,0x0f,0x12,0x11,0x12,0x08,0x10,0x0c,0x13,0x0c,0x0c,0x1d,0x1e,0x1f,0x14,0x0f,0x17,0x19,0x13,0x12,0x10,0x10,0x12,0x13,0x12,0x16,0x12,0x14,0x1a,0x12,0x16,0x13,0x13, 0x0f,0x10,0x0e,0x13,0x10,0x14,0x10,0x1d,0x1c,0x13,0x10,0x14,0x11,0x14,0x0f,0x13,0x10,0x15,0x13,0x12,0x0d,0x12,0x13,0x0f,0x08,0x18,0x0f,0x0f,0x1c,0x16,0x15,0x13,0x1d,0x17,0x15,0x10,0x1c,0x16,0x17,0x12,0x1e,0x18,0x11,0x0e,0x19,0x18,0x18,0x13,0x17,0x13,0x17,0x13,0x2a,0x24,0x1a,0x15,0x24,0x1d,0x1c,0x16,0x13,0x0e,0x10,0x0d, 0x0d,0x00,0x00,0x20,0x1e,0x12,0x10,0x12,0x13,0x12,0x10,0x11,0x0f,0x13,0x10,0x17,0x13,0x1b,0x15,0x20,0x1b,0x17,0x12,0x14,0x0f,0x11,0x0d,0x1c,0x16,0x16,0x13,0x1b,0x14,0x1b,0x14,0x09,0x1c,0x18,0x13,0x10,0x17,0x12,0x15,0x12,0x15,0x10,0x15,0x10,0x1c,0x1b,0x10,0x11,0x17,0x11,0x17,0x11,0x1c,0x18,0x11,0x0e,0x11,0x0e,0x18,0x13, 0x18,0x13,0x18,0x13,0x18,0x13,0x14,0x0f,0x12,0x0f,0x12,0x0f,0x12,0x0f,0x15,0x12,0x19,0x17,0x12,0x13,0x1b,0x1c,0x1a,0x17,0x12,0x0f,0x1d,0x19,0x20,0x1b,0x17,0x11,0x16,0x13,0x13,0x12,0x12,0x10,0x13,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x13,0x0b,0x0b,0x05,0x07,0x07,0x07,0x09,0x0d, 0x09,0x07,0x0c,0x07,0x07,0x07,0x0b,0x0b,0x07,0x07,0x13,0x13,0x13,0x13,0x0b,0x09,0x09,0x0b,0x0a,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0a,0x0b,0x0b,0x09,0x05,0x08,0x09,0x07,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0b,0x0b,0x0d,0x0b,0x08,0x08,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c, 0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11, 0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00, 0x15,0x0a,0x14,0x0b,0x13,0x13,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x0a,0x0a,0x0b,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x13,0x0f,0x15,0x1b,0x0f,0x0f,0x12,0x12,0x0d,0x0d,0x08,0x0a,0x10,0x0d,0x16,0x13,0x13,0x0f,0x14,0x14,0x14,0x1e,0x11,0x13,0x13,0x0f,0x0f,0x0f,0x0d, 0x11,0x12,0x17,0x12,0x0f,0x17,0x0e,0x0d,0x0d,0x11,0x0c,0x0f,0x12,0x0f,0x13,0x12,0x0c,0x10,0x0b,0x0b,0x0d,0x0a,0x0a,0x0d,0x0e,0x06,0x07,0x0b,0x09,0x11,0x0e,0x0e,0x0e,0x0c,0x0b,0x0b,0x09,0x0d,0x11,0x0a,0x0a,0x0b,0x0f,0x0b,0x0b,0x0a,0x0a,0x08,0x08,0x0b,0x05,0x0a,0x10,0x0b,0x0b,0x09,0x0b,0x0b,0x0b,0x06,0x0b,0x0a,0x10,0x09, 0x0a,0x0b,0x09,0x0b,0x0d,0x0a,0x05,0x07,0x0b,0x09,0x0b,0x09,0x0b,0x0d,0x0a,0x13,0x05,0x0b,0x11,0x1c,0x14,0x11,0x11,0x1c,0x15,0x1b,0x18,0x11,0x13,0x10,0x0e,0x24,0x0f,0x13,0x1c,0x1e,0x1e,0x14,0x15,0x14,0x0f,0x0f,0x11,0x0e,0x0e,0x10,0x06,0x00,0x00,0x00,0x00,0x13,0x14,0x14,0x14,0x0f,0x0c,0x13,0x13,0x0a,0x1c,0x12,0x13,0x0b, 0x0b,0x0f,0x0b,0x0e,0x13,0x0f,0x12,0x1d,0x15,0x0a,0x09,0x13,0x11,0x13,0x13,0x13,0x0a,0x13,0x10,0x08,0x1c,0x12,0x13,0x0b,0x0e,0x0e,0x0f,0x0f,0x0e,0x10,0x13,0x13,0x11,0x0e,0x0e,0x18,0x08,0x0f,0x08,0x12,0x0e,0x0b,0x09,0x09,0x0b,0x08,0x06,0x05,0x0b,0x0b,0x05,0x06,0x06,0x06,0x05,0x06,0x05,0x07,0x10,0x10,0x0b,0x0b,0x0b,0x0b, 0x0c,0x07,0x05,0x06,0x0b,0x0b,0x0b,0x0a,0x09,0x08,0x08,0x09,0x08,0x0b,0x00,0x00,0x00,0x00,0x07,0x0a,0x0a,0x0b,0x09,0x0a,0x11,0x11,0x11,0x11,0x0b,0x00,0x00,0x00,0x00,0x0f,0x0a,0x09,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x09,0x09,0x09,0x09, 0x12,0x12,0x12,0x12,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x11,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x06,0x0c,0x0c,0x0b,0x0c,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0c,0x0b,0x0c,0x0c,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x19,0x14,0x17,0x12,0x18,0x14,0x1e,0x18,0x11,0x0c, 0x10,0x16,0x11,0x1a,0x16,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x1b,0x1b,0x20,0x0d,0x08,0x10,0x13,0x0d,0x10,0x10,0x13,0x13,0x10,0x20,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x10,0x15,0x10,0x10,0x10,0x0b,0x13,0x0b,0x18,0x15,0x10,0x0b,0x1b,0x10,0x1b,0x08,0x0b,0x13,0x13,0x15,0x15, 0x15,0x13,0x13,0x13,0x1b,0x08,0x13,0x08,0x10,0x0d,0x08,0x08,0x10,0x08,0x18,0x08,0x1d,0x10,0x1d,0x1d,0x13,0x13,0x13,0x10,0x10,0x0d,0x0d,0x25,0x25,0x2b,0x2b,0x1b,0x1b,0x10,0x10,0x05,0x20,0x18,0x1b,0x15,0x13,0x15,0x10,0x10,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x08,0x15,0x00,0x15,0x15,0x15,0x0b,0x10,0x10, 0x1d,0x0b,0x1d,0x0b,0x13,0x15,0x13,0x0d,0x1d,0x10,0x1d,0x10,0x18,0x1b,0x0b,0x10,0x10,0x0d,0x08,0x10,0x13,0x10,0x13,0x10,0x13,0x13,0x10,0x15,0x15,0x1d,0x0b,0x10,0x0d,0x15,0x10,0x0b,0x10,0x10,0x10,0x1d,0x0b,0x1d,0x0b,0x08,0x13,0x0c,0x20,0x10,0x10,0x15,0x15,0x20,0x10,0x00,0x00,0x00,0x15,0x00,0x15,0x15,0x15,0x15,0x18,0x15, 0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0d,0x10,0x10,0x18,0x1b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0d,0x0d,0x0d,0x10,0x0d,0x0d,0x0d,0x25,0x1b,0x25,0x1b,0x25, 0x1b,0x2b,0x20,0x2b,0x20,0x1b,0x10,0x13,0x13,0x13,0x20,0x20,0x10,0x10,0x20,0x10,0x10,0x20,0x10,0x10,0x20,0x10,0x10,0x18,0x18,0x23,0x20,0x1d,0x10,0x1b,0x10,0x1b,0x10,0x1b,0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x15,0x0b,0x15,0x0b,0x15,0x0b,0x15,0x0b,0x15,0x0b,0x15,0x15,0x0b,0x15,0x0b,0x11,0x15,0x13,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1b,0x1d,0x18,0x1b,0x0b,0x10,0x18,0x1b,0x18,0x1b,0x00,0x00,0x00,0x00,0x00,0x24,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0d,0x00,0x00,0x13,0x00,0x00,0x00,0x25,0x1b,0x2b,0x20,0x10,0x13,0x13,0x13,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10, 0x1d,0x1d,0x0c,0x13,0x13,0x13,0x27,0x1b,0x11,0x31,0x23,0x0b,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x0d,0x0d,0x18,0x15,0x15,0x10,0x00,0x00,0x00,0x0b,0x0b,0x0b,0x0b,0x28,0x30,0x00,0x00,0x00,0x00,0x00,0x13,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x0d,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b, 0x1d,0x0b,0x13,0x13,0x13,0x13,0x15,0x13,0x10,0x10,0x0d,0x25,0x1b,0x10,0x13,0x13,0x13,0x10,0x13,0x13,0x13,0x10,0x13,0x13,0x13,0x20,0x10,0x10,0x20,0x10,0x10,0x1d,0x10,0x10,0x1d,0x10,0x10,0x1d,0x10,0x10,0x13,0x13,0x13,0x13,0x15,0x0b,0x15,0x0b,0x15,0x0b,0x15,0x15,0x0b,0x0b,0x0d,0x0d,0x25,0x1b,0x15,0x13,0x13,0x00,0x10,0x10, 0x10,0x0c,0x12,0x16,0x14,0x10,0x11,0x0b,0x08,0x18,0x13,0x13,0x0b,0x12,0x0f,0x0f,0x0f,0x0f,0x08,0x10,0x0d,0x14,0x10,0x13,0x0f,0x11,0x0e,0x16,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0e,0x0f,0x0f,0x09,0x10,0x12,0x13,0x10,0x0b,0x18,0x13,0x14,0x11,0x14,0x10,0x12,0x10,0x0d,0x16,0x0c,0x0d,0x0d,0x0f,0x13,0x13, 0x10,0x20,0x10,0x20,0x0b,0x08,0x05,0x11,0x07,0x04,0x00,0x04,0x07,0x00,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x10,0x10,0x1e,0x0e,0x18,0x13,0x1e,0x17,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x1e,0x1c,0x0f,0x1c,0x0f,0x1c,0x15,0x16,0x16,0x16,0x18,0x1c,0x20,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, 0x1c,0x16,0x16,0x16,0x16,0x18,0x13,0x22,0x1a,0x0f,0x0f,0x09,0x09,0x09,0x0c,0x07,0x12,0x07,0x07,0x1b,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x06,0x00,0x00,0x07,0x00,0x00,0x14,0x12,0x0e,0x0f,0x16,0x09,0x0b,0x16,0x16,0x09,0x12,0x11,0x12,0x16,0x16,0x09,0x0d,0x16,0x13,0x14,0x14,0x12, 0x13,0x15,0x12,0x19,0x17,0x11,0x11,0x11,0x07,0x0c,0x12,0x12,0x12,0x12,0x11,0x13,0x14,0x0f,0x16,0x11,0x12,0x16,0x12,0x17,0x12,0x19,0x19,0x19,0x19,0x14,0x14,0x14,0x12,0x0e,0x0f,0x16,0x0a,0x0b,0x16,0x0a,0x12,0x11,0x12,0x16,0x0d,0x16,0x14,0x14,0x13,0x15,0x12,0x19,0x17,0x09,0x12,0x11,0x14,0x15,0x26,0x00,0x14,0x12,0x15,0x15, 0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x09,0x00,0x18,0x15,0x15,0x17,0x12,0x15,0x18,0x18,0x0f,0x14,0x18,0x18,0x15,0x18,0x1a,0x19,0x15,0x12,0x12,0x18,0x17,0x12,0x16,0x16,0x15,0x16,0x16,0x18, 0x12,0x14,0x16,0x15,0x19,0x14,0x14,0x15,0x15,0x1a,0x10,0x13,0x13,0x1c,0x11,0x11,0x19,0x1d,0x14,0x11,0x22,0x12,0x12,0x18,0x11,0x11,0x18,0x12,0x18,0x1a,0x1c,0x11,0x19,0x11,0x15,0x11,0x14,0x12,0x14,0x11,0x13,0x19,0x11,0x14,0x15,0x11,0x11,0x13,0x1f,0x11,0x11,0x13,0x13,0x0e,0x0b,0x12,0x12,0x12,0x11,0x12,0x1c,0x12,0x1c,0x10, 0x12,0x1c,0x15,0x12,0x1c,0x18,0x18,0x1c,0x12,0x12,0x1c,0x1c,0x12,0x12,0x12,0x12,0x12,0x12,0x1c,0x1c,0x13,0x12,0x12,0x1c,0x13,0x11,0x12,0x12,0x1c,0x19,0x16,0x16,0x16,0x16,0x17,0x14,0x16,0x19,0x16,0x15,0x11,0x19,0x16,0x16,0x12,0x15,0x16,0x18,0x17,0x13,0x16,0x15,0x17,0x15,0x19,0x16,0x17,0x17,0x16,0x14,0x16,0x16,0x17,0x19, 0x15,0x18,0x17,0x03,0x04,0x05,0x06,0x05,0x09,0x0b,0x1c,0x12,0x14,0x13,0x12,0x14,0x12,0x12,0x15,0x13,0x12,0x0a,0x1b,0x13,0x12,0x12,0x11,0x13,0x10,0x13,0x09,0x13,0x11,0x12,0x0d,0x1c,0x12,0x12,0x12,0x13,0x1b,0x12,0x13,0x0d,0x1b,0x13,0x13,0x16,0x16,0x07,0x09,0x24,0x24,0x24,0x24,0x2e,0x11,0x11,0x08,0x11,0x0c,0x11,0x11,0x12, 0x11,0x11,0x10,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x11,0x11,0x12,0x11,0x11,0x10,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x10,0x10,0x10,0x13,0x0e,0x0d,0x12,0x14,0x08,0x0a,0x10,0x0d,0x18,0x15,0x14,0x10,0x14,0x10,0x0d, 0x0e,0x13,0x10,0x1a,0x10,0x0f,0x0f,0x16,0x19,0x0d,0x14,0x10,0x13,0x11,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x08,0x08,0x15,0x14,0x14,0x14,0x14,0x14,0x13,0x13,0x13,0x13,0x0f,0x10,0x10,0x10,0x10,0x10,0x12,0x13,0x13,0x0e,0x0e,0x0e,0x0e,0x0e,0x12,0x12,0x10,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x12, 0x0a,0x10,0x0d,0x0d,0x0d,0x0d,0x15,0x15,0x15,0x15,0x14,0x14,0x14,0x10,0x10,0x10,0x0d,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x13,0x13,0x13,0x13,0x1a,0x1a,0x1a,0x1a,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x16,0x14,0x10,0x10,0x0d,0x11,0x0e,0x0f,0x14,0x14,0x08,0x10,0x10,0x18,0x15,0x0e,0x14,0x14,0x10,0x0f,0x0e,0x0f,0x14, 0x10,0x15,0x14,0x10,0x0e,0x14,0x08,0x14,0x0f,0x14,0x08,0x0f,0x0e,0x12,0x0d,0x10,0x0d,0x08,0x08,0x0a,0x1a,0x1a,0x14,0x10,0x10,0x13,0x10,0x10,0x10,0x0d,0x13,0x0e,0x18,0x0e,0x15,0x15,0x10,0x12,0x18,0x14,0x14,0x14,0x10,0x10,0x0e,0x10,0x14,0x10,0x14,0x12,0x1a,0x1b,0x12,0x17,0x10,0x10,0x1c,0x10,0x0d,0x13,0x13,0x14,0x1c,0x1c, 0x15,0x10,0x12,0x0d,0x12,0x12,0x12,0x16,0x11,0x11,0x16,0x13,0x13,0x0b,0x14,0x14,0x12,0x10,0x10,0x1d,0x18,0x0f,0x11,0x13,0x13,0x14,0x14,0x17,0x16,0x0b,0x1e,0x13,0x12,0x12,0x15,0x15,0x10,0x10,0x09,0x18,0x16,0x16,0x0f,0x16,0x07,0x07,0x0e,0x0e,0x07,0x07,0x14,0x0d,0x09,0x18,0x17,0x09,0x07,0x07,0x0e,0x0c,0x0c,0x07,0x07,0x07, 0x0c,0x16,0x0f,0x0a,0x13,0x16,0x13,0x13,0x10,0x18,0x12,0x13,0x0b,0x0e,0x11,0x0e,0x07,0x07,0x0c,0x11,0x0b,0x15,0x15,0x15,0x1d,0x18,0x1d,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x18,0x1b,0x0b,0x0b,0x10,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x13,0x13,0x13,0x10,0x10,0x25,0x1b,0x25,0x1b,0x2b,0x20,0x2b,0x20,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1d,0x1d,0x10,0x10,0x1d,0x1d,0x10,0x10,0x18,0x1b,0x0b,0x0b,0x18,0x1b,0x0b,0x0b,0x18,0x1b,0x0b,0x0b,0x20,0x18,0x1b,0x10,0x13,0x13,0x15,0x0b,0x15,0x18,0x10,0x10,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0x0b,0x18,0x10,0x10,0x08,0x10,0x10,0x10,0x10,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b, 0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x25,0x1b,0x25,0x1b,0x25,0x1b,0x2b,0x20,0x2b,0x20,0x1b,0x1b,0x1b,0x20,0x20,0x20,0x20,0x20,0x20,0x18,0x10,0x10,0x18,0x10,0x10,0x1d,0x10,0x23,0x20,0x1d,0x10,0x1b,0x10,0x1b,0x10,0x1b,0x10,0x1d, 0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x1d,0x10,0x15,0x15,0x15,0x15,0x15,0x0b,0x15,0x15,0x0b,0x0b,0x15,0x0b,0x15,0x0b,0x15,0x10,0x13,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0b,0x0b,0x10,0x0b,0x0b,0x0b,0x0b,0x00,0x25,0x1b,0x2b,0x20,0x1d,0x10,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b,0x1d,0x0b, 0x13,0x13,0x10,0x10,0x0d,0x25,0x1b,0x20,0x20,0x1d,0x1d,0x1d,0x13,0x13,0x13,0x13,0x15,0x0b,0x15,0x0b,0x15,0x0b,0x25,0x1b,0x13,0x15,0x13,0x13,0x13,0x15,0x13,0x13,0x25,0x25,0x1b,0x1b,0x0d,0x0d,0x13,0x13,0x13,0x13,0x0b,0x0b,0x0b,0x0b,0x18,0x1b,0x0b,0x0b,0x18,0x1b,0x0b,0x0b,0x18,0x1b,0x0b,0x0b,0x13,0x13,0x13,0x13,0x1d,0x0b, 0x1d,0x0b,0x13,0x15,0x13,0x13,0x25,0x25,0x1b,0x1b,0x25,0x25,0x1b,0x1b,0x1b,0x1b,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x08,0x08,0x0b,0x08,0x00,0x00,0x00,0x1b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0d,0x0d,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x18,0x15,0x15,0x15,0x15,0x15,0x15,0x13,0x1b,0x13,0x1b,0x13,0x1b,0x13,0x1b,0x15, 0x15,0x15,0x08,0x08,0x10,0x0d,0x13,0x14,0x12,0x11,0x12,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x12,0x11,0x13,0x14,0x14,0x15,0x13,0x12,0x15,0x10,0x15,0x18,0x14,0x18,0x1b,0x14,0x18,0x16,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0f,0x11,0x13,0x13,0x15,0x12,0x15,0x12,0x13, 0x13,0x10,0x10,0x18,0x16,0x16,0x16,0x16,0x13,0x13,0x13,0x18,0x19,0x18,0x18,0x1e,0x1e,0x16,0x1e,0x1e,0x17,0x1c,0x1b,0x12,0x19,0x1b,0x18,0x13,0x1b,0x18,0x16,0x16,0x13,0x15,0x18,0x19,0x16,0x14,0x17,0x13,0x11,0x1e,0x1d,0x1d,0x1a,0x1e,0x1e,0x16,0x1e,0x1e,0x17,0x19,0x19,0x18,0x17,0x17,0x15,0x1c,0x18,0x1a,0x17,0x17,0x13,0x18, 0x16,0x16,0x1b,0x18,0x17,0x1d,0x11,0x10,0x12,0x11,0x14,0x14,0x16,0x17,0x13,0x12,0x12,0x11,0x12,0x11,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x10,0x11,0x13,0x14,0x13,0x13,0x0f,0x12,0x12,0x13,0x13,0x18,0x1b,0x15,0x15,0x14,0x19,0x14,0x16,0x10,0x0f,0x13,0x12,0x0f,0x10,0x12,0x12,0x0f,0x0f,0x14,0x0f,0x11,0x10,0x12,0x19,0x12,0x1a, 0x11,0x12,0x12,0x18,0x0a,0x19,0x16,0x17,0x15,0x12,0x18,0x13,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x13,0x13,0x13,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0e,0x0e,0x0e,0x0e,0x0f,0x0e,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x14,0x09,0x09,0x09,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x1d,0x1d,0x1d,0x1d,0x10, 0x18,0x17,0x10,0x0d,0x10,0x11,0x12,0x10,0x1b,0x1a,0x1c,0x0e,0x20,0x10,0x1b,0x1b,0x1b,0x1a,0x12,0x10,0x10,0x19,0x13,0x19,0x16,0x11,0x0f,0x0d,0x21,0x0d,0x11,0x10,0x10,0x10,0x10,0x10,0x2c,0x1b,0x1b,0x0e,0x08,0x0f,0x08,0x0f,0x08,0x08,0x08,0x0f,0x13,0x13,0x11,0x0c,0x0c,0x07,0x07,0x07,0x0c,0x07,0x0d,0x1c,0x07,0x1d,0x1d,0x1d, 0x13,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x25,0x25,0x15,0x25,0x25,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x0f,0x13,0x0f,0x11,0x0e,0x0b,0x0b,0x16,0x12,0x17,0x0e,0x24,0x1d, 0x13,0x12,0x1d,0x19,0x1b,0x18,0x21,0x1a,0x1e,0x19,0x15,0x0f,0x17,0x13,0x1e,0x17,0x18,0x13,0x18,0x13,0x1c,0x15,0x1c,0x15,0x23,0x1b,0x18,0x13,0x18,0x13,0x27,0x1c,0x19,0x00,0x20,0x20,0x20,0x0f,0x00,0x00,0x13,0x10,0x16,0x12,0x11,0x0e,0x22,0x1d,0x1e,0x1c,0x17,0x13,0x16,0x13,0x11,0x0d,0x18,0x13,0x11,0x0d,0x1a,0x15,0x15,0x12, 0x1f,0x1a,0x11,0x12,0x17,0x17,0x1a,0x0e,0x06,0x0f,0x16,0x0e,0x20,0x20,0x08,0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x0d,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x13,0x13,0x13,0x13,0x13,0x13, 0x13,0x13,0x13,0x13,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x0f,0x16,0x17,0x09,0x07,0x09,0x07,0x17,0x12,0x18,0x14,0x12,0x0f,0x11,0x0f,0x13,0x12,0x0d,0x0d,0x24,0x1a,0x25,0x1c,0x20,0x1b,0x1d,0x15,0x1d,0x15,0x1d, 0x15,0x14,0x0f,0x13,0x10,0x13,0x10,0x13,0x10,0x11,0x0a,0x0f,0x08,0x18,0x13,0x1b,0x16,0x2b,0x20,0x12,0x13,0x16,0x17,0x1a,0x1c,0x18,0x13,0x1f,0x19,0x11,0x0d,0x12,0x10,0x14,0x0f,0x1e,0x17,0x14,0x11,0x12,0x13,0x12,0x13,0x0f,0x0d,0x0f,0x0c,0x0f,0x0c,0x11,0x11,0x0a,0x16,0x0a,0x1f,0x15,0x0b,0x13,0x14,0x0f,0x18,0x12,0x0c,0x0b, 0x13,0x13,0x12,0x0f,0x08,0x18,0x13,0x0c,0x0b,0x14,0x0f,0x17,0x0c,0x19,0x13,0x14,0x0f,0x16,0x13,0x13,0x10,0x18,0x12,0x13,0x0b,0x11,0x0e,0x18,0x0e,0x11,0x1c,0x10,0x12,0x1d,0x09,0x25,0x1d,0x1d,0x26,0x1c,0x1d,0x1d,0x1c,0x1c,0x1e,0x11,0x0f,0x14,0x16,0x1d,0x16,0x1e,0x08,0x0f,0x13,0x1c,0x21,0x16,0x21,0x14,0x14,0x19,0x16,0x24, 0x1e,0x11,0x1d,0x0b,0x1d,0x0b,0x13,0x13,0x13,0x13,0x1b,0x1b,0x1b,0x1b,0x20,0x10,0x10,0x20,0x18,0x10,0x10,0x18,0x15,0x0b,0x0b,0x15,0x13,0x13,0x13,0x13,0x18,0x0b,0x0b,0x1b,0x18,0x0b,0x0b,0x1b,0x0d,0x0d,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x10,0x0d,0x12,0x11,0x18,0x13,0x13,0x1c,0x15,0x18,0x18,0x1b,0x1a,0x13,0x10,0x20,0x1a,0x21,0x1b,0x16,0x13,0x0a,0x0a,0x13,0x15,0x0d,0x13,0x11,0x13,0x0f,0x18,0x1a,0x0d,0x13,0x0e,0x07,0x0c,0x11,0x12,0x07,0x07,0x06,0x07,0x0c,0x0c,0x0c,0x0e,0x30,0x40,0x0b,0x0d,0x04,0x09,0x0c,0x0e,0x0a, 0x10,0x11,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x0f,0x0f,0x2b,0x11,0x18,0x1d,0x1d,0x15,0x0f,0x12,0x17,0x18,0x10,0x0a,0x15,0x11,0x16,0x12,0x15,0x11,0x11,0x18,0x13,0x13,0x11,0x18,0x14,0x1b,0x0f,0x11,0x14,0x0a,0x13,0x0b,0x0b,0x08,0x1c,0x13,0x12,0x11,0x11,0x13,0x1e,0x1e,0x1e,0x20,0x20,0x12,0x10, 0x09,0x10,0x0f,0x13,0x0f,0x15,0x08,0x12,0x13,0x1c,0x1c,0x14,0x11,0x12,0x11,0x11,0x0f,0x11,0x0f,0x0f,0x0a,0x0b,0x08,0x07,0x0c,0x13,0x14,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0a,0x00,0x09,0x09,0x09,0x08,0x08,0x36,0x20,0x1c,0x22,0x09,0x09,0x0a,0x0d,0x08,0x09,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x09,0x09,0x09,0x00,0x1d,0x0b,0x0b,0x1d,0x08,0x10,0x10,0x2b,0x20,0x20,0x2b,0x1d,0x10,0x10,0x1d,0x10,0x10,0x0d,0x0d,0x00,0x00,0x0b,0x18,0x13,0x17,0x12,0x28,0x21,0x16,0x12,0x16,0x12,0x2b,0x20,0x18,0x13,0x0c,0x0a,0x14,0x00,0x16,0x11,0x0b,0x0a,0x05,0x10,0x0b,0x0b,0x08,0x06,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x07,0x11,0x0e,0x13,0x12,0x12,0x1f,0x1a,0x1a,0x19,0x1a,0x1e,0x14,0x16,0x13,0x0d,0x1e,0x24,0x0e,0x25,0x10,0x1b,0x1d,0x1d,0x1d,0x0d,0x18,0x20,0x18,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x13,0x13,0x13,0x1b,0x10,0x10,0x1d,0x0b,0x0b,0x1d,0x0b,0x0b,0x1d,0x10,0x10,0x00,0x0d, 0x1b,0x0b,0x0b,0x20,0x10,0x10,0x18,0x10,0x10,0x15,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x30,0x30,0x1c,0x00,0x00,0x1c,0x1c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x14,0x15,0x15,0x1c,0x15,0x14,0x1a,0x1f,0x15,0x14,0x22,0x14,0x14,0x1e,0x14, 0x16,0x19,0x14,0x19,0x1b,0x1d,0x14,0x19,0x15,0x16,0x14,0x16,0x14,0x15,0x16,0x14,0x19,0x13,0x15,0x19,0x14,0x14,0x12,0x19,0x15,0x15,0x15,0x16,0x0e,0x11,0x15,0x19,0x19,0x11,0x00,0x00,0x21,0x42,0x15,0x00,0x03,0x09,0x09,0x0d,0x14,0x12,0x1b,0x1a,0x08,0x0a,0x0a,0x0e,0x17,0x07,0x0d,0x07,0x0d,0x12,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x07,0x07,0x17,0x17,0x17,0x0f,0x20,0x15,0x13,0x14,0x17,0x11,0x10,0x17,0x17,0x09,0x0c,0x13,0x10,0x1e,0x19,0x19,0x12,0x19,0x14,0x12,0x11,0x17,0x15,0x1f,0x13,0x12,0x13,0x0a,0x0d,0x0a,0x17,0x0e,0x09,0x11,0x13,0x0f,0x13,0x11,0x0a,0x13,0x13,0x08,0x08,0x10,0x08,0x1c,0x13,0x13,0x13,0x13,0x0b,0x0e,0x0b,0x13,0x10, 0x18,0x0f,0x10,0x0f,0x0a,0x08,0x0a,0x17,0x15,0x15,0x14,0x11,0x19,0x19,0x17,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x11,0x11,0x11,0x11,0x08,0x08,0x08,0x08,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0c,0x0c,0x12,0x12,0x0f,0x0d,0x0f,0x12,0x0d,0x1d,0x1d,0x1a,0x09,0x0e,0x17,0x1c,0x19,0x1b,0x17,0x17,0x17,0x12,0x13,0x12, 0x14,0x19,0x12,0x0d,0x0e,0x19,0x1b,0x13,0x0f,0x09,0x09,0x17,0x15,0x12,0x17,0x15,0x11,0x11,0x18,0x15,0x15,0x19,0x1f,0x1f,0x11,0x21,0x0c,0x0c,0x08,0x08,0x17,0x13,0x10,0x12,0x06,0x12,0x0a,0x0a,0x12,0x12,0x0c,0x07,0x08,0x0c,0x28,0x15,0x11,0x15,0x11,0x11,0x09,0x09,0x09,0x09,0x19,0x19,0x19,0x17,0x17,0x17,0x08,0x0c,0x0b,0x0a, 0x0a,0x07,0x09,0x07,0x0b,0x06,0x0c,0x10,0x09,0x12,0x0e,0x13,0x0f,0x08,0x17,0x12,0x12,0x10,0x12,0x13,0x17,0x17,0x0c,0x0c,0x0c,0x1f,0x1e,0x1f,0x10,0x17,0x13,0x09,0x12,0x0e,0x14,0x0f,0x14,0x0f,0x13,0x0e,0x07,0x15,0x11,0x15,0x11,0x17,0x16,0x17,0x11,0x11,0x11,0x11,0x10,0x08,0x10,0x0a,0x10,0x0a,0x19,0x13,0x19,0x13,0x19,0x13, 0x14,0x0b,0x14,0x0b,0x12,0x0e,0x11,0x0b,0x11,0x0f,0x17,0x13,0x17,0x13,0x13,0x0f,0x13,0x0f,0x10,0x19,0x19,0x14,0x13,0x0e,0x13,0x10,0x17,0x0e,0x10,0x0d,0x25,0x15,0x10,0x14,0x08,0x0c,0x1b,0x0b,0x14,0x0c,0x0c,0x14,0x0c,0x15,0x11,0x14,0x0f,0x14,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17, 0x13,0x09,0x08,0x09,0x08,0x09,0x08,0x09,0x08,0x0c,0x08,0x13,0x10,0x10,0x10,0x08,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x14,0x0b,0x12,0x0e,0x11,0x0b,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x1f,0x18,0x12,0x10,0x08,0x15,0x11,0x1c,0x1b,0x19,0x13,0x07,0x1f,0x18,0x1f,0x18,0x1f,0x18,0x12,0x10,0x08,0x0e,0x12,0x14,0x1e,0x1e, 0x1f,0x1d,0x0d,0x0d,0x07,0x09,0x09,0x15,0x13,0x1a,0x0c,0x1a,0x16,0x1b,0x09,0x15,0x13,0x11,0x13,0x17,0x09,0x13,0x15,0x1e,0x19,0x11,0x19,0x18,0x12,0x11,0x11,0x12,0x13,0x1a,0x19,0x09,0x12,0x14,0x0e,0x13,0x09,0x12,0x12,0x11,0x0f,0x13,0x13,0x09,0x11,0x10,0x13,0x11,0x0f,0x13,0x13,0x0f,0x12,0x12,0x19,0x1b,0x09,0x12,0x13,0x12, 0x1b,0x11,0x17,0x10,0x14,0x12,0x09,0x20,0x20,0x18,0x13,0x13,0x17,0x15,0x13,0x13,0x10,0x17,0x11,0x1d,0x12,0x19,0x19,0x13,0x16,0x1e,0x17,0x19,0x18,0x12,0x14,0x11,0x13,0x18,0x13,0x19,0x16,0x1f,0x20,0x17,0x1a,0x13,0x14,0x22,0x14,0x11,0x13,0x11,0x0d,0x12,0x11,0x19,0x0f,0x13,0x13,0x10,0x11,0x17,0x13,0x13,0x13,0x13,0x0f,0x0e, 0x10,0x17,0x0f,0x14,0x13,0x1a,0x1b,0x14,0x17,0x11,0x0f,0x1b,0x11,0x11,0x13,0x0d,0x0f,0x0e,0x08,0x1a,0x1b,0x13,0x10,0x10,0x13,0x0f,0x0d,0x21,0x25,0x15,0x0c,0x0c,0x0c,0x0c,0x08,0x12,0x0e,0x12,0x19,0x14,0x17,0x13,0x0a,0x0b,0x09,0x09,0x10,0x10,0x10,0x10,0x0a,0x0a,0x0a,0x10,0x0a,0x10,0x0a,0x0a,0x0a,0x10,0x10,0x15,0x11,0x15, 0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x08,0x09,0x08,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x14,0x19,0x14,0x19,0x14,0x19,0x14,0x19, 0x14,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x12,0x10,0x12,0x10,0x12,0x10,0x11,0x0b,0x11,0x11,0x19,0x13,0x09,0x0c,0x08,0x08,0x11,0x0e,0x1e,0x1a,0x14,0x12,0x13,0x10,0x19,0x14,0x12,0x10,0x12,0x10,0x15,0x10,0x16,0x13,0x16,0x13,0x18,0x11,0x19,0x13,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x10,0x10,0x10, 0x10,0x09,0x09,0x0a,0x0a,0x0a,0x0a,0x11,0x11,0x15,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x0f,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x0a,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x09,0x08,0x09,0x08,0x13,0x10,0x13,0x10,0x13,0x10,0x10, 0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x1e,0x1c,0x1e,0x1c,0x1e,0x1c,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x12,0x13,0x12,0x13,0x14,0x0b,0x14,0x0b,0x14,0x0b,0x14,0x0b,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x12,0x0e,0x11,0x0b,0x11,0x0b,0x11,0x0b,0x11,0x0b,0x17,0x13,0x17,0x13,0x17, 0x13,0x17,0x13,0x17,0x13,0x15,0x10,0x15,0x10,0x1f,0x18,0x1f,0x18,0x13,0x0f,0x13,0x0f,0x12,0x10,0x13,0x0f,0x13,0x0f,0x13,0x0f,0x13,0x0b,0x18,0x10,0x11,0x08,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x18,0x18,0x18,0x18,0x13,0x13,0x13,0x13,0x13, 0x13,0x13,0x13,0x1a,0x1a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x10,0x10,0x11,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x1b,0x1b,0x1f,0x1f,0x1f,0x1f,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x20,0x20,0x20, 0x20,0x20,0x20,0x14,0x14,0x0e,0x0e,0x13,0x13,0x09,0x09,0x13,0x13,0x12,0x12,0x1b,0x1b,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1a,0x1a,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x20,0x20,0x20,0x20,0x20, 0x20,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,0x15,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1a,0x1a,0x17,0x13,0x13,0x13,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0c,0x0c,0x13,0x13,0x13,0x12,0x12,0x12,0x12,0x13,0x13,0x12,0x12,0x12,0x12,0x16,0x16,0x15,0x13,0x13,0x13,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1c,0x1b,0x19,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x14,0x13,0x13,0x13,0x13,0x14,0x14,0x0f,0x17,0x18,0x13,0x13,0x14,0x11,0x12,0x10,0x17,0x15,0x1d,0x0a,0x09,0x13,0x10,0x08,0x10,0x1d,0x19,0x13,0x19,0x20,0x1a,0x14,0x13,0x13,0x12,0x0e,0x11,0x0a,0x0b,0x11,0x0b, 0x11,0x19,0x18,0x13,0x11,0x13,0x0f,0x14,0x14,0x0f,0x0e,0x12,0x12,0x0d,0x0d,0x12,0x08,0x0d,0x0f,0x09,0x29,0x26,0x22,0x1c,0x18,0x11,0x23,0x20,0x1b,0x15,0x11,0x09,0x08,0x19,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x17,0x13,0x11,0x15,0x11,0x15,0x11,0x1c,0x1b,0x17,0x13,0x17,0x13,0x13,0x10,0x19,0x13,0x19,0x13,0x14,0x0f, 0x08,0x29,0x26,0x22,0x17,0x13,0x21,0x17,0x19,0x13,0x15,0x11,0x15,0x11,0x11,0x11,0x11,0x11,0x09,0x08,0x09,0x08,0x19,0x13,0x19,0x13,0x13,0x0b,0x14,0x0b,0x17,0x13,0x17,0x13,0x11,0x0e,0x17,0x13,0x18,0x13,0x13,0x13,0x0f,0x15,0x11,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x12,0x10,0x13,0x11,0x13,0x13,0x13,0x11,0x13,0x13,0x13, 0x0f,0x0f,0x13,0x13,0x11,0x14,0x0e,0x0e,0x11,0x12,0x09,0x13,0x13,0x11,0x10,0x0f,0x13,0x13,0x13,0x09,0x09,0x0b,0x09,0x0c,0x08,0x14,0x1c,0x1c,0x1c,0x12,0x12,0x13,0x13,0x17,0x18,0x15,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x0d,0x08,0x09,0x0a,0x09,0x0b,0x0b,0x14,0x14,0x12,0x10,0x18,0x10,0x0e,0x0f,0x11,0x0f,0x0f,0x0c, 0x0c,0x0c,0x0f,0x14,0x10,0x12,0x11,0x13,0x08,0x10,0x0d,0x13,0x0c,0x0c,0x1e,0x1f,0x20,0x14,0x10,0x18,0x1a,0x13,0x13,0x10,0x10,0x12,0x14,0x13,0x16,0x13,0x15,0x1a,0x13,0x17,0x13,0x13,0x0f,0x10,0x0f,0x14,0x11,0x14,0x10,0x1d,0x1c,0x14,0x11,0x15,0x12,0x14,0x0f,0x14,0x10,0x16,0x13,0x13,0x0d,0x13,0x13,0x0f,0x08,0x19,0x0f,0x0f, 0x1c,0x16,0x15,0x13,0x1e,0x18,0x16,0x10,0x1d,0x17,0x18,0x13,0x1f,0x19,0x12,0x0f,0x1a,0x19,0x19,0x13,0x18,0x13,0x18,0x13,0x2b,0x25,0x1b,0x15,0x25,0x1e,0x1c,0x16,0x13,0x0e,0x11,0x0d,0x0e,0x00,0x00,0x21,0x1f,0x13,0x11,0x13,0x13,0x13,0x11,0x12,0x0f,0x13,0x10,0x17,0x13,0x1c,0x16,0x21,0x1c,0x18,0x12,0x14,0x0f,0x11,0x0e,0x1d, 0x17,0x17,0x13,0x1c,0x15,0x1c,0x15,0x09,0x1d,0x19,0x13,0x11,0x17,0x13,0x16,0x13,0x15,0x11,0x15,0x11,0x1c,0x1b,0x11,0x11,0x18,0x11,0x18,0x11,0x1d,0x19,0x12,0x0f,0x11,0x0f,0x19,0x13,0x19,0x13,0x19,0x13,0x19,0x13,0x14,0x0f,0x13,0x10,0x13,0x10,0x13,0x10,0x16,0x13,0x1a,0x17,0x13,0x13,0x1c,0x1c,0x1b,0x18,0x12,0x10,0x1e,0x1a, 0x21,0x1c,0x18,0x12,0x16,0x14,0x13,0x13,0x13,0x11,0x13,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x13,0x0b,0x0b,0x05,0x07,0x07,0x07,0x09,0x0d,0x09,0x08,0x0c,0x07,0x07,0x07,0x0b,0x0b,0x07,0x07,0x13,0x13,0x13,0x13,0x0b,0x09,0x09,0x0b,0x0a,0x09,0x09,0x09,0x09,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0a,0x0b,0x0b,0x0a,0x05,0x08,0x09,0x07,0x0d,0x0d,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x0e,0x0b,0x08,0x09,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0d, 0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x15,0x0a,0x15,0x0b,0x14,0x14,0x0b,0x0b,0x0b,0x0b,0x0b,0x09,0x0b,0x0b,0x0b,0x09,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x13,0x0f,0x16,0x1b,0x10,0x0f,0x12,0x12,0x0e,0x0e,0x08,0x0a,0x10,0x0d,0x17,0x13,0x13,0x10,0x14,0x14,0x14,0x1f,0x12,0x14,0x14,0x0f,0x0f,0x0f,0x0e,0x12,0x13,0x18,0x13,0x10,0x18,0x0f,0x0e,0x0e,0x11,0x0d,0x0f,0x13,0x0f,0x14,0x13,0x0c,0x10,0x0b,0x0c,0x0e,0x0a,0x0a,0x0e,0x0e,0x06,0x08,0x0c, 0x09,0x11,0x0e,0x0e,0x0e,0x0d,0x0b,0x0b,0x0a,0x0e,0x11,0x0a,0x0a,0x0b,0x10,0x0b,0x0b,0x0a,0x0a,0x09,0x09,0x0b,0x05,0x0a,0x10,0x0b,0x0b,0x09,0x0b,0x0b,0x0b,0x07,0x0b,0x0b,0x10,0x09,0x0b,0x0b,0x0a,0x0b,0x0d,0x0a,0x05,0x07,0x0b,0x09,0x0b,0x0a,0x0b,0x0d,0x0a,0x13,0x05,0x0b,0x12,0x1d,0x15,0x12,0x12,0x1c,0x15,0x1c,0x19,0x11, 0x13,0x11,0x0f,0x25,0x0f,0x13,0x1d,0x1f,0x1f,0x15,0x15,0x14,0x0f,0x10,0x11,0x0e,0x0f,0x11,0x07,0x00,0x00,0x00,0x00,0x13,0x14,0x14,0x14,0x10,0x0d,0x13,0x13,0x0a,0x1c,0x13,0x13,0x0b,0x0b,0x0f,0x0b,0x0f,0x13,0x0f,0x13,0x1e,0x15,0x0b,0x09,0x13,0x12,0x14,0x13,0x13,0x0a,0x13,0x10,0x08,0x1c,0x13,0x13,0x0b,0x0e,0x0e,0x10,0x0f, 0x0f,0x11,0x13,0x13,0x11,0x0e,0x0f,0x18,0x08,0x0f,0x08,0x13,0x0f,0x0b,0x09,0x09,0x0b,0x09,0x06,0x05,0x0b,0x0b,0x05,0x06,0x06,0x06,0x05,0x06,0x05,0x07,0x10,0x10,0x0b,0x0b,0x0c,0x0b,0x0c,0x08,0x05,0x07,0x0b,0x0b,0x0b,0x0b,0x09,0x09,0x09,0x0a,0x09,0x0b,0x00,0x00,0x00,0x00,0x07,0x0a,0x0a,0x0b,0x09,0x0a,0x12,0x12,0x12,0x12, 0x0b,0x00,0x00,0x00,0x00,0x0f,0x0a,0x09,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x09,0x09,0x09,0x09,0x12,0x12,0x12,0x12,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x12,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x06,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0a,0x1a,0x15,0x17,0x13,0x19,0x15,0x1f,0x19,0x12,0x0c,0x11,0x17,0x12,0x1b,0x17,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x0b,0x0b,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x1c,0x1c,0x21,0x0e,0x08,0x11, 0x13,0x0e,0x11,0x11,0x13,0x13,0x11,0x21,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x15,0x11,0x11,0x11,0x0b,0x13,0x0b,0x19,0x16,0x11,0x0b,0x1c,0x11,0x1c,0x08,0x0b,0x13,0x13,0x15,0x15,0x15,0x13,0x13,0x13,0x1c,0x08,0x13,0x08,0x11,0x0e,0x08,0x08,0x11,0x08,0x19,0x08,0x1e,0x11,0x1e,0x1e,0x13,0x13,0x13,0x11,0x11,0x0e,0x0e,0x27, 0x27,0x2c,0x2c,0x1c,0x1c,0x11,0x11,0x06,0x21,0x19,0x1c,0x16,0x13,0x16,0x11,0x11,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x08,0x15,0x00,0x15,0x15,0x15,0x0b,0x11,0x11,0x1e,0x0b,0x1e,0x0b,0x13,0x16,0x13,0x0e,0x1e,0x11,0x1e,0x11,0x19,0x1c,0x0b,0x11,0x11,0x0e,0x08,0x11,0x13,0x11,0x13,0x11,0x13,0x13,0x11,0x16, 0x15,0x1e,0x0b,0x11,0x0e,0x16,0x11,0x0b,0x11,0x11,0x11,0x1e,0x0b,0x1e,0x0b,0x08,0x13,0x0d,0x21,0x11,0x11,0x15,0x15,0x21,0x11,0x00,0x00,0x00,0x15,0x00,0x15,0x15,0x15,0x15,0x19,0x15,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x0e,0x0e,0x11,0x11,0x19,0x1c,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x13,0x13, 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0e,0x0e,0x0e,0x11,0x0e,0x0e,0x0e,0x27,0x1c,0x27,0x1c,0x27,0x1c,0x2c,0x21,0x2c,0x21,0x1c,0x11,0x13,0x13,0x13,0x21,0x21,0x11,0x11,0x21,0x11,0x11,0x21,0x11,0x11,0x21,0x11,0x11,0x19,0x19,0x24,0x21,0x1e, 0x11,0x1c,0x11,0x1c,0x11,0x1c,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x16,0x0b,0x16,0x0b,0x12,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x1c,0x1e,0x19,0x1c,0x0b,0x11,0x19,0x1c,0x19,0x1c,0x00,0x00,0x00,0x00,0x00,0x25,0x24,0x00,0x00,0x00,0x00, 0x00,0x00,0x08,0x0e,0x00,0x00,0x14,0x00,0x00,0x00,0x27,0x1c,0x2c,0x21,0x11,0x13,0x13,0x13,0x0e,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x1e,0x1e,0x0c,0x13,0x13,0x14,0x28,0x1b,0x12,0x32,0x24,0x0b,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x0e,0x0e,0x19,0x16, 0x16,0x11,0x00,0x00,0x00,0x0b,0x0b,0x0b,0x0b,0x29,0x32,0x00,0x00,0x00,0x00,0x00,0x13,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x0e,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x13,0x13,0x13,0x13,0x16,0x13,0x11,0x11,0x0e,0x27,0x1c,0x11,0x13,0x13,0x13,0x11,0x13,0x13,0x13,0x11,0x13,0x13,0x13,0x21,0x11,0x11, 0x21,0x11,0x11,0x1e,0x11,0x11,0x1e,0x11,0x11,0x1e,0x11,0x11,0x13,0x13,0x13,0x13,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x16,0x0b,0x0b,0x0e,0x0e,0x27,0x1c,0x15,0x13,0x13,0x00,0x11,0x11,0x11,0x0c,0x13,0x17,0x15,0x11,0x11,0x0c,0x08,0x19,0x13,0x14,0x0b,0x12,0x10,0x10,0x0f,0x10,0x08,0x11,0x0e,0x14,0x10,0x13,0x0f,0x12,0x0e,0x16, 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0f,0x10,0x10,0x09,0x11,0x12,0x14,0x11,0x0b,0x19,0x13,0x15,0x12,0x14,0x10,0x13,0x11,0x0d,0x17,0x0c,0x0e,0x0e,0x10,0x14,0x14,0x11,0x21,0x11,0x21,0x0b,0x08,0x06,0x12,0x07,0x04,0x00,0x05,0x07,0x00,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x11, 0x11,0x1f,0x0e,0x19,0x13,0x1f,0x18,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x1e,0x1c,0x10,0x1c,0x10,0x1c,0x15,0x17,0x17,0x17,0x19,0x1c,0x21,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x17,0x17,0x17,0x17,0x18,0x13,0x23,0x1b,0x10,0x10,0x09,0x09,0x09,0x0c,0x07,0x13,0x08,0x08,0x1c,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x07,0x00,0x00,0x15,0x13,0x0e,0x10,0x16,0x09,0x0b,0x16,0x16,0x09,0x12,0x12,0x12,0x17,0x16,0x09,0x0d,0x16,0x14,0x14,0x15,0x13,0x13,0x16,0x12,0x1a,0x18,0x11,0x11,0x11,0x08,0x0c,0x12,0x12,0x12,0x12,0x12,0x14,0x15,0x10,0x16,0x12,0x12,0x17,0x12,0x18,0x12,0x1a,0x1a,0x1a, 0x1a,0x15,0x15,0x15,0x13,0x0e,0x10,0x16,0x0a,0x0c,0x16,0x0a,0x12,0x12,0x12,0x16,0x0d,0x16,0x14,0x15,0x13,0x16,0x12,0x1a,0x18,0x09,0x13,0x12,0x15,0x16,0x28,0x00,0x15,0x12,0x16,0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x0d,0x09,0x00,0x19,0x15,0x16,0x17,0x12,0x16,0x19,0x19,0x10,0x15,0x19,0x18,0x16,0x19,0x1b,0x1a,0x16,0x12,0x12,0x19,0x17,0x13,0x17,0x16,0x16,0x16,0x17,0x18,0x13,0x15,0x16,0x16,0x1a,0x15,0x14,0x15,0x16,0x1b,0x10,0x13,0x13,0x1d,0x12,0x12,0x19,0x1d,0x14,0x12,0x23,0x13,0x13,0x19,0x12,0x12,0x19,0x13, 0x19,0x1b,0x1d,0x12,0x19,0x12,0x16,0x12,0x14,0x13,0x15,0x12,0x14,0x19,0x12,0x14,0x16,0x12,0x12,0x14,0x20,0x12,0x12,0x13,0x13,0x0e,0x0b,0x12,0x12,0x12,0x12,0x12,0x1d,0x12,0x1d,0x10,0x12,0x1d,0x16,0x12,0x1d,0x19,0x19,0x1d,0x13,0x12,0x1d,0x1d,0x12,0x12,0x12,0x12,0x12,0x12,0x1d,0x1d,0x13,0x12,0x13,0x1d,0x14,0x12,0x12,0x12, 0x1d,0x1a,0x17,0x17,0x17,0x17,0x17,0x15,0x17,0x1a,0x17,0x15,0x12,0x1a,0x16,0x17,0x13,0x16,0x17,0x19,0x18,0x13,0x17,0x16,0x18,0x16,0x1a,0x17,0x18,0x18,0x17,0x15,0x17,0x16,0x18,0x1a,0x16,0x19,0x18,0x03,0x04,0x05,0x06,0x05,0x09,0x0c,0x1c,0x13,0x14,0x14,0x13,0x14,0x13,0x13,0x15,0x14,0x13,0x0a,0x1c,0x13,0x13,0x13,0x12,0x14, 0x11,0x13,0x09,0x13,0x11,0x13,0x0e,0x1c,0x12,0x13,0x13,0x14,0x1b,0x13,0x13,0x0d,0x1b,0x13,0x13,0x17,0x16,0x07,0x09,0x25,0x25,0x25,0x25,0x2f,0x12,0x12,0x08,0x12,0x0d,0x12,0x12,0x13,0x12,0x12,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0d,0x12,0x12,0x13,0x12,0x12,0x11,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x10,0x11,0x13,0x0e,0x0e,0x13,0x14,0x08,0x0a,0x10,0x0e,0x19,0x15,0x14,0x10,0x14,0x10,0x0e,0x0f,0x14,0x11,0x1a,0x11,0x0f,0x10,0x17,0x1a,0x0e,0x15,0x10,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0e,0x0e,0x0e,0x0e,0x08,0x08,0x08, 0x08,0x15,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0f,0x11,0x11,0x11,0x11,0x11,0x13,0x13,0x13,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x11,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x13,0x0a,0x10,0x0e,0x0e,0x0e,0x0e,0x15,0x15,0x15,0x16,0x14,0x14,0x14,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x0f,0x14,0x14,0x14,0x14, 0x14,0x14,0x1a,0x1a,0x1a,0x1a,0x0f,0x0f,0x0f,0x10,0x10,0x10,0x11,0x17,0x15,0x11,0x10,0x0d,0x12,0x0e,0x10,0x14,0x14,0x08,0x10,0x11,0x19,0x15,0x0f,0x14,0x14,0x10,0x0f,0x0f,0x0f,0x15,0x11,0x16,0x15,0x11,0x0e,0x14,0x08,0x14,0x0f,0x15,0x08,0x0f,0x0e,0x13,0x0d,0x11,0x0e,0x08,0x08,0x0a,0x1b,0x1b,0x14,0x10,0x10,0x14,0x11,0x10, 0x10,0x0d,0x13,0x0e,0x18,0x0f,0x15,0x15,0x10,0x13,0x19,0x14,0x14,0x14,0x10,0x11,0x0f,0x10,0x15,0x11,0x15,0x12,0x1b,0x1b,0x13,0x17,0x10,0x11,0x1c,0x10,0x0d,0x13,0x13,0x15,0x1d,0x1d,0x16,0x11,0x13,0x0e,0x13,0x12,0x12,0x17,0x11,0x11,0x17,0x13,0x13,0x0c,0x14,0x14,0x13,0x10,0x10,0x1e,0x19,0x10,0x12,0x14,0x14,0x15,0x15,0x17, 0x17,0x0c,0x1f,0x13,0x12,0x13,0x15,0x15,0x11,0x11,0x09,0x19,0x17,0x17,0x10,0x17,0x07,0x07,0x0e,0x0e,0x07,0x07,0x14,0x0d,0x09,0x19,0x17,0x09,0x07,0x07,0x0f,0x0c,0x0c,0x08,0x08,0x08,0x0c,0x16,0x10,0x0a,0x14,0x17,0x13,0x13,0x10,0x19,0x13,0x14,0x0b,0x0f,0x12,0x0e,0x07,0x08,0x0d,0x11,0x0b,0x16,0x16,0x16,0x1e,0x19,0x1e,0x08, 0x00,0x00,0x00,0x00,0x00,0x08,0x19,0x1c,0x0b,0x0b,0x11,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x13,0x13,0x13,0x11,0x11,0x27,0x1c,0x27,0x1c,0x2c,0x21,0x2c,0x21,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1e,0x1e,0x11,0x11,0x1e,0x1e,0x11,0x11,0x19,0x1c,0x0b,0x0b,0x19,0x1c,0x0b,0x0b,0x19,0x1c,0x0b,0x0b,0x21,0x19,0x1c,0x11,0x13,0x13,0x16, 0x0b,0x16,0x19,0x11,0x11,0x0b,0x0b,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1e,0x0b,0x19,0x11,0x11,0x08,0x11,0x11,0x11,0x11,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x27,0x1c, 0x27,0x1c,0x27,0x1c,0x2c,0x21,0x2c,0x21,0x1c,0x1c,0x1c,0x21,0x21,0x21,0x21,0x21,0x21,0x19,0x11,0x11,0x19,0x11,0x11,0x1e,0x11,0x24,0x21,0x1e,0x11,0x1c,0x11,0x1c,0x11,0x1c,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x16,0x16,0x16,0x16,0x16,0x0b,0x16,0x16,0x0b,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x11,0x13, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x0b,0x11,0x0b,0x0b,0x0b,0x0b,0x00,0x27,0x1c,0x2c,0x21,0x1e,0x11,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x1e,0x0b,0x13,0x13,0x11,0x11,0x0e,0x27,0x1c,0x21,0x21,0x1e,0x1e,0x1e,0x13,0x13,0x13,0x13,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x27,0x1c,0x13,0x16,0x13,0x13, 0x13,0x16,0x13,0x13,0x27,0x27,0x1c,0x1c,0x0e,0x0e,0x13,0x13,0x13,0x13,0x0b,0x0b,0x0b,0x0b,0x19,0x1c,0x0b,0x0b,0x19,0x1c,0x0b,0x0b,0x19,0x1c,0x0b,0x0b,0x13,0x13,0x13,0x13,0x1e,0x0b,0x1e,0x0b,0x13,0x16,0x13,0x13,0x27,0x27,0x1c,0x1c,0x27,0x27,0x1c,0x1c,0x1c,0x1c,0x11,0x11,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, 0x08,0x08,0x0b,0x08,0x00,0x00,0x00,0x1c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0e,0x0e, 0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x1c,0x13,0x1c,0x13,0x1c,0x13,0x1c,0x16,0x16,0x16,0x08,0x08,0x11,0x0e,0x13,0x15,0x13,0x12,0x12,0x13,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x0f,0x12,0x11, 0x13,0x14,0x14,0x16,0x13,0x13,0x15,0x11,0x16,0x19,0x15,0x19,0x1b,0x15,0x19,0x17,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x12,0x14,0x14,0x16,0x13,0x15,0x13,0x14,0x14,0x11,0x11,0x19,0x16,0x17,0x16,0x16,0x14,0x13,0x13,0x18,0x19,0x19,0x19,0x1e,0x1e,0x17,0x1e,0x1e,0x18,0x1d,0x1c,0x12,0x19,0x1c,0x19,0x14, 0x1c,0x18,0x17,0x17,0x14,0x15,0x19,0x1a,0x17,0x14,0x17,0x13,0x12,0x1e,0x1e,0x1e,0x1b,0x1e,0x1e,0x17,0x1e,0x1e,0x17,0x19,0x1a,0x19,0x18,0x18,0x15,0x1d,0x19,0x1b,0x18,0x18,0x13,0x18,0x17,0x17,0x1c,0x19,0x18,0x1e,0x12,0x11,0x12,0x12,0x14,0x15,0x17,0x18,0x13,0x13,0x13,0x12,0x13,0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x11, 0x11,0x13,0x14,0x14,0x14,0x0f,0x13,0x13,0x13,0x14,0x19,0x1c,0x16,0x16,0x15,0x19,0x15,0x17,0x11,0x10,0x13,0x13,0x10,0x10,0x12,0x12,0x10,0x0f,0x15,0x0f,0x12,0x10,0x12,0x1a,0x13,0x1b,0x12,0x13,0x13,0x19,0x0a,0x1a,0x17,0x18,0x16,0x13,0x19,0x14,0x1a,0x14,0x14,0x14,0x14,0x14,0x14,0x13,0x14,0x14,0x14,0x09,0x09,0x09,0x09,0x09, 0x09,0x09,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0a,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x15,0x09,0x09,0x09,0x0a,0x0a,0x09,0x09,0x09,0x0a,0x09,0x09,0x09,0x1e,0x1e,0x1e,0x1e,0x10,0x18,0x18,0x10,0x0d,0x10,0x11,0x12,0x10,0x1c,0x1b,0x1c,0x0f,0x21,0x10,0x1c,0x1c,0x1c,0x1b,0x13,0x10,0x10,0x1a,0x13,0x1a,0x16,0x12,0x0f,0x0d, 0x22,0x0e,0x12,0x10,0x10,0x10,0x10,0x10,0x2d,0x1c,0x1c,0x0e,0x08,0x0f,0x08,0x0f,0x08,0x08,0x08,0x10,0x13,0x13,0x12,0x0c,0x0c,0x08,0x08,0x08,0x0c,0x08,0x0e,0x1c,0x07,0x1e,0x1e,0x1e,0x13,0x13,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x27,0x27,0x16,0x27,0x27,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x0f,0x13,0x0f,0x12,0x0e,0x0c,0x0b,0x17,0x12,0x18,0x0e,0x25,0x1d,0x14,0x12,0x1e,0x1a,0x1c,0x19,0x22,0x1b,0x1f,0x1a,0x15,0x10,0x18,0x13,0x1f,0x18,0x19,0x14,0x19,0x14,0x1c,0x16,0x1d,0x16,0x24,0x1c,0x19,0x13, 0x19,0x13,0x28,0x1d,0x1a,0x00,0x21,0x21,0x21,0x10,0x00,0x00,0x13,0x11,0x17,0x12,0x12,0x0e,0x24,0x1e,0x1f,0x1c,0x18,0x13,0x17,0x13,0x11,0x0e,0x18,0x14,0x11,0x0e,0x1b,0x16,0x16,0x13,0x20,0x1b,0x12,0x13,0x18,0x18,0x1b,0x0f,0x07,0x0f,0x17,0x0e,0x21,0x21,0x08,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0d, 0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1e,0x1e,0x1e,0x1e, 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, 0x17,0x17,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x00, 0x00,0x00,0x00,0x00,0x00,0x0e,0x10,0x16,0x18,0x09,0x07,0x09,0x07,0x17,0x13,0x19,0x15,0x12,0x10,0x12,0x10,0x14,0x13,0x0e,0x0e,0x25,0x1b,0x26,0x1d,0x21,0x1c,0x1e,0x16,0x1e,0x16,0x1e,0x16,0x14,0x0f,0x13,0x10,0x13,0x10,0x13,0x10,0x12,0x0a,0x10,0x08,0x19,0x13,0x1c,0x16,0x2c,0x21,0x12,0x13,0x17,0x17,0x1b,0x1c,0x19,0x13,0x20, 0x1a,0x12,0x0d,0x12,0x10,0x15,0x10,0x1f,0x18,0x14,0x11,0x12,0x13,0x12,0x13,0x10,0x0d,0x10,0x0d,0x10,0x0c,0x11,0x11,0x0a,0x16,0x0b,0x20,0x16,0x0b,0x13,0x14,0x0f,0x19,0x12,0x0d,0x0b,0x13,0x13,0x13,0x10,0x08,0x19,0x14,0x0c,0x0b,0x15,0x0f,0x17,0x0d,0x1a,0x14,0x14,0x0f,0x17,0x13,0x13,0x10,0x19,0x13,0x14,0x0b,0x12,0x0e,0x19, 0x0e,0x12,0x1c,0x10,0x12,0x1e,0x09,0x26,0x1d,0x1e,0x27,0x1d,0x1e,0x1e,0x1d,0x1d,0x1e,0x11,0x10,0x14,0x17,0x1e,0x17,0x1f,0x08,0x0f,0x13,0x1c,0x22,0x17,0x22,0x14,0x14,0x1a,0x17,0x26,0x1e,0x11,0x1e,0x0b,0x1e,0x0b,0x13,0x13,0x13,0x13,0x1c,0x1c,0x1c,0x1c,0x21,0x11,0x11,0x21,0x19,0x11,0x11,0x19,0x16,0x0b,0x0b,0x16,0x13,0x13, 0x13,0x13,0x19,0x0b,0x0b,0x1c,0x19,0x0b,0x0b,0x1c,0x0e,0x0e,0x11,0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x11,0x0d,0x13,0x11,0x19,0x13,0x13,0x1d,0x16,0x19,0x19,0x1b,0x1b,0x13,0x10,0x21,0x1b,0x22,0x1c,0x17, 0x13,0x0a,0x0a,0x13,0x15,0x0d,0x14,0x11,0x13,0x10,0x18,0x1a,0x0d,0x13,0x0e,0x07,0x0c,0x12,0x12,0x07,0x07,0x06,0x07,0x0c,0x0c,0x0c,0x0f,0x31,0x42,0x0b,0x0e,0x04,0x09,0x0d,0x0e,0x0a,0x10,0x11,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x10,0x10,0x10,0x10,0x10,0x2c,0x12,0x19,0x1e,0x1e,0x15,0x0f,0x13,0x18,0x18,0x10, 0x0a,0x16,0x11,0x16,0x12,0x16,0x12,0x12,0x19,0x14,0x13,0x11,0x19,0x14,0x1b,0x0f,0x11,0x15,0x0a,0x13,0x0b,0x0b,0x08,0x1d,0x13,0x13,0x11,0x11,0x13,0x1f,0x1f,0x1f,0x21,0x21,0x12,0x10,0x09,0x11,0x0f,0x14,0x0f,0x16,0x08,0x13,0x14,0x1c,0x1c,0x14,0x12,0x13,0x12,0x11,0x0f,0x11,0x0f,0x10,0x0a,0x0b,0x08,0x07,0x0c,0x13,0x15,0x0a, 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x00,0x0a,0x0a,0x0a,0x08,0x08,0x38,0x21,0x1d,0x23,0x0a,0x0a,0x0b,0x0d,0x08,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x00,0x1e,0x0b,0x0b,0x1e,0x09,0x11,0x11,0x2c,0x21,0x21,0x2c,0x1e,0x11,0x11,0x1e,0x11,0x11,0x0e,0x0e,0x00,0x00,0x0c, 0x19,0x14,0x17,0x13,0x29,0x22,0x17,0x12,0x17,0x12,0x2c,0x21,0x19,0x13,0x0d,0x0a,0x14,0x00,0x17,0x12,0x0b,0x0a,0x05,0x10,0x0b,0x0b,0x08,0x07,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x07,0x11,0x0e,0x13,0x13,0x12,0x20,0x1b,0x1b,0x1a,0x1b,0x1f,0x15,0x17,0x14,0x0d,0x1f,0x25,0x0f,0x26,0x11,0x1c,0x1e,0x1e,0x1e,0x0e,0x19, 0x21,0x19,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x13,0x13,0x13,0x1c,0x11,0x11,0x1e,0x0b,0x0b,0x1e,0x0b,0x0b,0x1e,0x10,0x10,0x00,0x0e,0x1c,0x0b,0x0b,0x21,0x11,0x11,0x19,0x11,0x11,0x16,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x32,0x32,0x1d, 0x00,0x00,0x1d,0x1d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x16,0x14,0x15,0x15,0x1d,0x15,0x15,0x1a,0x20,0x15,0x15,0x23,0x15,0x15,0x1f,0x15,0x16,0x1a,0x15,0x19,0x1c,0x1e,0x15,0x19,0x15,0x17,0x15,0x17,0x15,0x16,0x17,0x15,0x1a,0x14,0x16,0x1a,0x14,0x15,0x13,0x1a,0x15,0x15,0x15,0x17, 0x0f,0x11,0x15,0x1a,0x1a,0x12,0x00,0x00,0x25,0x4a,0x18,0x00,0x04,0x0a,0x0b,0x0f,0x16,0x14,0x1e,0x1e,0x09,0x0b,0x0b,0x0f,0x19,0x08,0x0f,0x08,0x0e,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x08,0x08,0x19,0x19,0x19,0x11,0x23,0x18,0x15,0x17,0x1a,0x13,0x12,0x19,0x1a,0x0a,0x0d,0x15,0x11,0x21,0x1c,0x1c,0x15,0x1c,0x16, 0x14,0x13,0x19,0x17,0x23,0x16,0x14,0x15,0x0b,0x0e,0x0b,0x19,0x0f,0x0a,0x13,0x16,0x11,0x16,0x13,0x0c,0x16,0x15,0x09,0x09,0x12,0x09,0x20,0x15,0x16,0x16,0x16,0x0d,0x10,0x0d,0x15,0x12,0x1b,0x11,0x12,0x11,0x0b,0x09,0x0b,0x19,0x18,0x18,0x17,0x13,0x1c,0x1c,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x13,0x13,0x13,0x13,0x09,0x09, 0x09,0x09,0x15,0x16,0x16,0x16,0x16,0x16,0x15,0x15,0x15,0x15,0x0e,0x0e,0x14,0x14,0x11,0x0f,0x11,0x14,0x0f,0x21,0x21,0x1d,0x0a,0x0f,0x19,0x20,0x1c,0x1e,0x19,0x19,0x19,0x14,0x15,0x14,0x17,0x1c,0x14,0x0f,0x10,0x1c,0x1f,0x16,0x11,0x0a,0x0b,0x19,0x18,0x14,0x19,0x18,0x13,0x13,0x1b,0x18,0x18,0x1c,0x22,0x22,0x13,0x25,0x0e,0x0e, 0x08,0x08,0x19,0x16,0x12,0x14,0x06,0x14,0x0c,0x0c,0x15,0x15,0x0e,0x08,0x08,0x0e,0x2d,0x18,0x13,0x18,0x13,0x13,0x0a,0x0a,0x0a,0x0a,0x1c,0x1c,0x1c,0x19,0x19,0x19,0x09,0x0e,0x0c,0x0b,0x0b,0x07,0x0a,0x08,0x0c,0x07,0x0e,0x11,0x0a,0x14,0x10,0x15,0x11,0x09,0x1a,0x15,0x14,0x12,0x15,0x16,0x19,0x19,0x0d,0x0e,0x0e,0x22,0x22,0x23, 0x12,0x19,0x16,0x0a,0x14,0x10,0x17,0x11,0x17,0x11,0x16,0x0f,0x08,0x18,0x13,0x18,0x13,0x1a,0x19,0x1a,0x13,0x13,0x13,0x13,0x11,0x09,0x11,0x0b,0x11,0x0c,0x1c,0x15,0x1c,0x15,0x1c,0x16,0x16,0x0d,0x16,0x0d,0x14,0x10,0x13,0x0d,0x13,0x10,0x19,0x15,0x19,0x15,0x15,0x11,0x15,0x11,0x11,0x1c,0x1c,0x17,0x16,0x10,0x15,0x12,0x1a,0x0f, 0x12,0x0f,0x29,0x17,0x12,0x16,0x08,0x0e,0x1e,0x0c,0x16,0x0d,0x0d,0x16,0x0d,0x18,0x13,0x17,0x11,0x17,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x16,0x19,0x16,0x19,0x16,0x1a,0x15,0x1a,0x15,0x0a,0x09,0x0a,0x09,0x0a,0x09,0x0a,0x09,0x0d,0x09,0x15,0x12,0x12,0x11,0x09,0x1c,0x15,0x1c,0x15,0x1c,0x16,0x1c,0x16,0x16,0x0d,0x14,0x10, 0x13,0x0d,0x19,0x15,0x19,0x15,0x19,0x15,0x19,0x15,0x23,0x1b,0x14,0x12,0x09,0x18,0x13,0x20,0x1f,0x1c,0x16,0x08,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x14,0x12,0x08,0x0f,0x14,0x16,0x22,0x22,0x22,0x21,0x0e,0x0e,0x08,0x0a,0x0a,0x18,0x15,0x1d,0x0e,0x1e,0x19,0x1f,0x0a,0x18,0x15,0x13,0x15,0x1a,0x0a,0x15,0x17,0x21,0x1c,0x13,0x1c,0x1a, 0x15,0x13,0x13,0x14,0x16,0x1d,0x1c,0x0a,0x14,0x17,0x10,0x15,0x0a,0x14,0x14,0x13,0x10,0x15,0x16,0x0a,0x13,0x12,0x15,0x13,0x10,0x16,0x16,0x11,0x14,0x14,0x1c,0x1e,0x0a,0x14,0x16,0x14,0x1e,0x13,0x1a,0x11,0x17,0x14,0x0a,0x24,0x24,0x1b,0x15,0x15,0x1a,0x18,0x15,0x15,0x11,0x1a,0x13,0x20,0x14,0x1c,0x1c,0x15,0x19,0x21,0x1a,0x1c, 0x1a,0x15,0x17,0x13,0x15,0x1b,0x16,0x1b,0x18,0x23,0x24,0x1a,0x1d,0x15,0x17,0x26,0x16,0x13,0x15,0x14,0x0e,0x14,0x13,0x1c,0x11,0x16,0x16,0x12,0x14,0x1a,0x15,0x16,0x15,0x16,0x11,0x0f,0x12,0x19,0x11,0x16,0x15,0x1e,0x1f,0x16,0x1a,0x13,0x11,0x1e,0x13,0x13,0x15,0x0e,0x11,0x10,0x09,0x1d,0x1e,0x15,0x12,0x12,0x15,0x11,0x0e,0x25, 0x2a,0x17,0x0d,0x0e,0x0e,0x0e,0x09,0x14,0x10,0x15,0x1c,0x16,0x1a,0x16,0x0b,0x0c,0x0a,0x0a,0x12,0x12,0x12,0x12,0x0b,0x0b,0x0b,0x12,0x0b,0x12,0x0b,0x0b,0x0b,0x12,0x12,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0a,0x09,0x0a,0x09,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x19,0x15,0x19,0x15,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x14,0x12,0x14,0x12,0x14,0x12,0x13,0x0d,0x13,0x13,0x1c,0x16,0x0a, 0x0d,0x09,0x09,0x13,0x0f,0x22,0x1d,0x17,0x14,0x15,0x12,0x1b,0x16,0x14,0x12,0x14,0x12,0x17,0x12,0x18,0x15,0x18,0x15,0x1b,0x13,0x1c,0x16,0x0b,0x0b,0x0b,0x0b,0x0f,0x0f,0x12,0x12,0x12,0x12,0x0a,0x0a,0x0b,0x0b,0x0b,0x0b,0x13,0x13,0x18,0x13,0x15,0x16,0x15,0x16,0x15,0x16,0x17,0x11,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x1a, 0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0c,0x19,0x16,0x1a,0x15,0x1a,0x15,0x1a,0x15,0x1a,0x15,0x1a,0x15,0x0a,0x09,0x0a,0x09,0x15,0x12,0x15,0x12,0x15,0x12,0x11,0x09,0x11,0x09,0x11,0x09,0x11,0x09,0x21,0x20,0x21,0x20,0x21,0x20,0x1c,0x15,0x1c,0x15,0x1c,0x15,0x1c,0x15,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c, 0x16,0x15,0x16,0x15,0x16,0x16,0x0d,0x16,0x0d,0x16,0x0d,0x16,0x0d,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x14,0x10,0x13,0x0d,0x13,0x0d,0x13,0x0d,0x13,0x0d,0x19,0x15,0x19,0x15,0x19,0x15,0x19,0x15,0x19,0x15,0x17,0x12,0x17,0x12,0x23,0x1b,0x23,0x1b,0x16,0x11,0x16,0x11,0x14,0x12,0x15,0x11,0x15,0x11,0x15,0x11,0x15,0x0d,0x1b, 0x12,0x13,0x09,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x10,0x10,0x10,0x10,0x10,0x10,0x15,0x15,0x1a,0x1a,0x1a,0x1a,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1d,0x1d,0x22,0x22,0x22,0x22,0x22,0x22,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0e,0x0e,0x12,0x12,0x13,0x13,0x13,0x13,0x16, 0x16,0x16,0x16,0x16,0x16,0x1e,0x1e,0x23,0x23,0x23,0x23,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x19,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1f,0x1f,0x23,0x23,0x23,0x23,0x23,0x23,0x17,0x17,0x10,0x10,0x15,0x15,0x0a,0x0a,0x16,0x16,0x14,0x14,0x1e,0x1e,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1d,0x1d,0x22,0x22,0x22,0x22,0x22,0x22,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1f,0x1f,0x23,0x23,0x23,0x23,0x23,0x23,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x18,0x16,0x16,0x16,0x16,0x16,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1d,0x1d,0x1a, 0x16,0x16,0x16,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0d,0x0e,0x16,0x16,0x16,0x14,0x14,0x14,0x14,0x16,0x16,0x14,0x14,0x14,0x14,0x19,0x19,0x17,0x16,0x16,0x16,0x1e,0x1e,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x1f,0x1c,0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x17,0x15,0x16,0x15,0x16, 0x17,0x17,0x11,0x1a,0x1b,0x15,0x16,0x16,0x13,0x14,0x12,0x1a,0x17,0x20,0x0b,0x0a,0x15,0x12,0x09,0x12,0x21,0x1c,0x15,0x1c,0x24,0x1d,0x16,0x16,0x15,0x14,0x10,0x13,0x0b,0x0d,0x13,0x0d,0x13,0x1c,0x1a,0x15,0x13,0x15,0x11,0x17,0x17,0x10,0x0f,0x14,0x14,0x0e,0x0f,0x14,0x09,0x0e,0x11,0x0b,0x2e,0x2a,0x26,0x20,0x1b,0x13,0x28,0x24, 0x1e,0x18,0x13,0x0a,0x09,0x1c,0x16,0x19,0x15,0x19,0x15,0x19,0x15,0x19,0x15,0x19,0x15,0x13,0x18,0x13,0x18,0x13,0x20,0x1f,0x19,0x16,0x19,0x16,0x15,0x12,0x1c,0x16,0x1c,0x16,0x17,0x10,0x09,0x2e,0x2a,0x26,0x19,0x16,0x25,0x19,0x1c,0x15,0x18,0x13,0x18,0x13,0x13,0x13,0x13,0x13,0x0a,0x09,0x0a,0x09,0x1c,0x16,0x1c,0x16,0x15,0x0d, 0x16,0x0d,0x19,0x15,0x19,0x15,0x13,0x10,0x1a,0x15,0x1b,0x16,0x15,0x15,0x11,0x18,0x13,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x14,0x12,0x16,0x13,0x15,0x15,0x16,0x13,0x16,0x16,0x16,0x11,0x11,0x16,0x16,0x13,0x17,0x0f,0x0f,0x13,0x14,0x0a,0x16,0x16,0x14,0x12,0x11,0x15,0x15,0x15,0x0a,0x0a,0x0c,0x0a,0x0e,0x09,0x16,0x20,0x20, 0x20,0x15,0x15,0x16,0x16,0x1a,0x1b,0x18,0x0d,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c,0x11,0x11,0x0f,0x09,0x0a,0x0b,0x0a,0x0d,0x0d,0x16,0x16,0x15,0x12,0x1b,0x12,0x0f,0x11,0x13,0x10,0x10,0x0e,0x0e,0x0e,0x11,0x17,0x12,0x14,0x14,0x15,0x09,0x12,0x0e,0x16,0x0e,0x0e,0x22,0x23,0x24,0x17,0x12,0x1b,0x1d,0x15,0x15,0x12,0x12,0x14,0x16,0x15, 0x19,0x15,0x18,0x1e,0x15,0x1a,0x16,0x16,0x11,0x12,0x11,0x16,0x13,0x17,0x12,0x21,0x20,0x16,0x13,0x18,0x14,0x17,0x11,0x16,0x12,0x19,0x16,0x15,0x0f,0x15,0x16,0x11,0x09,0x1c,0x11,0x11,0x20,0x19,0x18,0x15,0x22,0x1a,0x19,0x12,0x20,0x1a,0x1b,0x15,0x22,0x1c,0x14,0x11,0x1d,0x1c,0x1c,0x16,0x1b,0x15,0x1b,0x15,0x31,0x29,0x1f,0x18, 0x2a,0x21,0x20,0x19,0x16,0x10,0x13,0x0f,0x0f,0x00,0x00,0x24,0x23,0x15,0x13,0x15,0x16,0x15,0x13,0x14,0x11,0x15,0x12,0x1a,0x16,0x1f,0x19,0x25,0x1f,0x1b,0x15,0x17,0x11,0x13,0x0f,0x20,0x19,0x19,0x16,0x1f,0x17,0x1f,0x17,0x0a,0x20,0x1c,0x15,0x13,0x1a,0x15,0x18,0x15,0x18,0x13,0x18,0x13,0x20,0x1f,0x13,0x13,0x1b,0x13,0x1b,0x13, 0x20,0x1c,0x14,0x11,0x13,0x10,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x1c,0x16,0x17,0x11,0x15,0x12,0x15,0x12,0x15,0x12,0x18,0x15,0x1d,0x1a,0x15,0x16,0x20,0x20,0x1e,0x1b,0x15,0x12,0x22,0x1d,0x25,0x1f,0x1a,0x14,0x19,0x16,0x16,0x15,0x15,0x13,0x16,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x16, 0x0c,0x0c,0x06,0x08,0x08,0x08,0x0a,0x0f,0x0a,0x08,0x0e,0x08,0x08,0x08,0x0c,0x0c,0x08,0x08,0x16,0x16,0x16,0x16,0x0c,0x0a,0x0a,0x0c,0x0b,0x0a,0x0a,0x0a,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0b,0x0c,0x0c,0x0b,0x06,0x09,0x0a,0x08,0x0e,0x0e,0x0e,0x0e,0x0e,0x0c,0x0c,0x0c,0x0f,0x0c,0x09,0x0a,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, 0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14, 0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x14,0x14,0x14,0x0e,0x14, 0x14,0x14,0x14,0x00,0x00,0x00,0x00,0x00,0x18,0x0b,0x17,0x0d,0x16,0x16,0x0c,0x0c,0x0c,0x0c,0x0c,0x0a,0x0c,0x0c,0x0c,0x0a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x16,0x11,0x18,0x1f,0x12,0x11,0x14,0x15,0x0f,0x0f,0x09,0x0b,0x12,0x0f,0x1a,0x16,0x16,0x12,0x17,0x17,0x17, 0x22,0x14,0x16,0x16,0x11,0x11,0x11,0x0f,0x14,0x15,0x1b,0x15,0x12,0x1b,0x11,0x0f,0x0f,0x14,0x0e,0x11,0x15,0x11,0x16,0x15,0x0d,0x12,0x0d,0x0d,0x0f,0x0b,0x0b,0x0f,0x10,0x07,0x08,0x0d,0x0a,0x13,0x10,0x10,0x10,0x0e,0x0d,0x0d,0x0b,0x0f,0x13,0x0c,0x0c,0x0d,0x12,0x0d,0x0d,0x0c,0x0c,0x0a,0x0a,0x0d,0x06,0x0b,0x12,0x0c,0x0d,0x0a, 0x0d,0x0d,0x0d,0x07,0x0c,0x0c,0x12,0x0a,0x0c,0x0c,0x0b,0x0d,0x0f,0x0b,0x06,0x08,0x0c,0x0a,0x0c,0x0b,0x0d,0x0f,0x0b,0x16,0x06,0x0d,0x14,0x20,0x17,0x14,0x14,0x20,0x18,0x20,0x1c,0x14,0x16,0x13,0x11,0x2a,0x11,0x16,0x21,0x23,0x23,0x17,0x18,0x17,0x11,0x11,0x13,0x10,0x11,0x13,0x07,0x00,0x00,0x00,0x00,0x16,0x17,0x17,0x17,0x11, 0x0e,0x16,0x16,0x0c,0x20,0x15,0x16,0x0d,0x0c,0x11,0x0d,0x11,0x16,0x11,0x15,0x21,0x18,0x0c,0x0a,0x16,0x14,0x16,0x16,0x16,0x0c,0x16,0x12,0x09,0x20,0x15,0x16,0x0d,0x10,0x10,0x12,0x11,0x11,0x13,0x16,0x16,0x13,0x10,0x11,0x1b,0x09,0x11,0x09,0x15,0x10,0x0d,0x0a,0x0a,0x0d,0x0a,0x07,0x06,0x0d,0x0c,0x06,0x07,0x06,0x06,0x06,0x07, 0x06,0x08,0x12,0x12,0x0c,0x0c,0x0d,0x0c,0x0e,0x09,0x06,0x07,0x0c,0x0d,0x0c,0x0c,0x0a,0x0a,0x0a,0x0b,0x0a,0x0d,0x00,0x00,0x00,0x00,0x08,0x0c,0x0c,0x0d,0x0a,0x0c,0x14,0x14,0x14,0x14,0x0c,0x00,0x00,0x00,0x00,0x11,0x0b,0x0a,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x14,0x14,0x14,0x14, 0x14,0x14,0x14,0x14,0x0a,0x0a,0x0a,0x0a,0x14,0x14,0x14,0x14,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x14,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x06,0x0e,0x0e,0x0d,0x0e,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x0e,0x0d,0x0e,0x0e,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0b,0x1d,0x17, 0x1a,0x15,0x1c,0x17,0x23,0x1c,0x14,0x0e,0x13,0x19,0x14,0x1e,0x1a,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x0c,0x0c,0x0c,0x16,0x16,0x16,0x16,0x16,0x16,0x1f,0x1f,0x25,0x0f,0x09,0x13,0x16,0x0f,0x13,0x13,0x16,0x16,0x13,0x25,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x13,0x18,0x13,0x13,0x13,0x0c,0x16,0x0c,0x1c,0x19,0x13,0x0c,0x1f, 0x13,0x1f,0x09,0x0c,0x16,0x16,0x18,0x18,0x18,0x16,0x16,0x16,0x1f,0x09,0x16,0x09,0x13,0x0f,0x09,0x09,0x13,0x09,0x1c,0x09,0x22,0x13,0x22,0x22,0x16,0x16,0x16,0x13,0x13,0x0f,0x0f,0x2b,0x2b,0x31,0x31,0x1f,0x1f,0x13,0x13,0x06,0x25,0x1c,0x1f,0x19,0x16,0x19,0x13,0x13,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x09, 0x18,0x00,0x18,0x18,0x18,0x0c,0x13,0x13,0x22,0x0c,0x22,0x0c,0x16,0x19,0x16,0x0f,0x22,0x13,0x22,0x13,0x1c,0x1f,0x0c,0x13,0x13,0x0f,0x09,0x13,0x16,0x13,0x16,0x13,0x16,0x16,0x13,0x19,0x18,0x22,0x0c,0x13,0x0f,0x19,0x13,0x0c,0x13,0x13,0x13,0x22,0x0c,0x22,0x0c,0x09,0x16,0x0e,0x25,0x13,0x13,0x18,0x18,0x25,0x13,0x00,0x00,0x00, 0x18,0x00,0x18,0x18,0x18,0x18,0x1c,0x18,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x0f,0x0f,0x13,0x13,0x1c,0x1f,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x0f,0x13, 0x0f,0x0f,0x0f,0x2b,0x1f,0x2b,0x1f,0x2b,0x1f,0x31,0x25,0x31,0x25,0x1f,0x13,0x16,0x16,0x16,0x25,0x25,0x13,0x13,0x25,0x13,0x13,0x25,0x13,0x13,0x25,0x13,0x13,0x1c,0x1c,0x28,0x25,0x22,0x13,0x1f,0x13,0x1f,0x13,0x1f,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x19,0x0c,0x19,0x0c,0x19,0x0c,0x19,0x0c,0x19,0x0c,0x19, 0x19,0x0c,0x19,0x0c,0x14,0x19,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1f,0x22,0x1c,0x1f,0x0c,0x13,0x1c,0x1f,0x1c,0x1f,0x00,0x00,0x00,0x00,0x00,0x2a,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x0f,0x00,0x00,0x16,0x00,0x00,0x00,0x2b,0x1f,0x31,0x25,0x13,0x16,0x16,0x16,0x0f,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x22,0x22,0x0e,0x16,0x16,0x16,0x2d,0x1f,0x14,0x38,0x28,0x0c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x13,0x0f,0x0f,0x1c,0x19,0x19,0x13,0x00,0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x2e,0x38,0x00,0x00,0x00,0x00,0x00,0x16,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x0f,0x22,0x0c, 0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x16,0x16,0x16,0x16,0x19,0x16,0x13,0x13,0x0f,0x2b,0x1f,0x13,0x16,0x16,0x16,0x13,0x16,0x16,0x16,0x13,0x16,0x16,0x16,0x25,0x13,0x13,0x25,0x13,0x13,0x22,0x13,0x13,0x22,0x13,0x13,0x22,0x13,0x13,0x16,0x16,0x16,0x16,0x19,0x0c,0x19,0x0c,0x19,0x0c,0x19,0x19,0x0c,0x0c,0x0f,0x0f, 0x2b,0x1f,0x18,0x16,0x16,0x00,0x13,0x13,0x13,0x0e,0x15,0x19,0x17,0x13,0x13,0x0d,0x09,0x1c,0x16,0x16,0x0d,0x14,0x12,0x12,0x11,0x12,0x09,0x13,0x0f,0x17,0x12,0x16,0x11,0x14,0x10,0x19,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x11,0x12,0x11,0x0b,0x13,0x15,0x16,0x13,0x0d,0x1b,0x16,0x18,0x14,0x17,0x12,0x15,0x13, 0x0f,0x1a,0x0e,0x0f,0x10,0x12,0x16,0x16,0x13,0x25,0x13,0x25,0x0c,0x09,0x06,0x14,0x08,0x05,0x00,0x05,0x08,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x13,0x13,0x22,0x10,0x1c,0x16,0x23,0x1b,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x22,0x20,0x11,0x20,0x11,0x20,0x18,0x19,0x1a,0x1a,0x1c, 0x20,0x25,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x19,0x19,0x19,0x19,0x1b,0x15,0x27,0x1f,0x11,0x11,0x0b,0x0b,0x0b,0x0e,0x08,0x15,0x09,0x09,0x1f,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x07,0x00,0x00,0x08,0x00,0x00,0x18,0x15,0x10,0x12,0x19,0x0a,0x0c,0x19,0x19,0x0a,0x15,0x14,0x14,0x1a, 0x19,0x0a,0x0f,0x19,0x16,0x17,0x17,0x15,0x16,0x19,0x15,0x1d,0x1b,0x13,0x13,0x13,0x08,0x0e,0x15,0x15,0x14,0x14,0x14,0x16,0x18,0x12,0x19,0x14,0x14,0x1a,0x15,0x1b,0x14,0x1d,0x1d,0x1d,0x1d,0x18,0x18,0x18,0x15,0x10,0x12,0x19,0x0b,0x0d,0x19,0x0b,0x15,0x14,0x14,0x19,0x0f,0x19,0x17,0x17,0x16,0x19,0x15,0x1d,0x1b,0x0a,0x15,0x14, 0x17,0x18,0x2c,0x00,0x18,0x14,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0a,0x00,0x1c,0x18,0x19,0x1a,0x14,0x19,0x1c,0x1c,0x11,0x17,0x1c,0x1b,0x18,0x1c,0x1e,0x1d,0x19,0x14,0x15,0x1c, 0x1a,0x15,0x19,0x19,0x18,0x19,0x19,0x1b,0x15,0x18,0x19,0x18,0x1d,0x17,0x17,0x18,0x19,0x1e,0x12,0x16,0x16,0x20,0x14,0x14,0x1d,0x21,0x17,0x14,0x27,0x15,0x15,0x1c,0x14,0x14,0x1c,0x15,0x1c,0x1e,0x20,0x14,0x1d,0x14,0x18,0x14,0x17,0x15,0x17,0x14,0x16,0x1c,0x14,0x17,0x19,0x14,0x14,0x16,0x23,0x14,0x14,0x16,0x16,0x10,0x0c,0x15, 0x15,0x15,0x14,0x15,0x21,0x15,0x21,0x12,0x15,0x21,0x19,0x15,0x21,0x1c,0x1c,0x21,0x15,0x15,0x21,0x21,0x15,0x15,0x15,0x15,0x15,0x15,0x21,0x21,0x16,0x15,0x15,0x21,0x16,0x14,0x15,0x15,0x21,0x1d,0x19,0x1a,0x1a,0x19,0x1a,0x17,0x19,0x1d,0x1a,0x18,0x14,0x1d,0x19,0x19,0x15,0x19,0x1a,0x1c,0x1b,0x16,0x1a,0x19,0x1b,0x19,0x1d,0x1a, 0x1b,0x1b,0x19,0x18,0x1a,0x19,0x1b,0x1d,0x18,0x1c,0x1b,0x04,0x04,0x06,0x07,0x06,0x0a,0x0d,0x20,0x15,0x17,0x16,0x15,0x17,0x15,0x15,0x18,0x16,0x15,0x0b,0x1f,0x16,0x15,0x15,0x14,0x16,0x13,0x15,0x0a,0x16,0x13,0x15,0x0f,0x20,0x14,0x15,0x15,0x16,0x1f,0x15,0x16,0x0f,0x1f,0x16,0x16,0x19,0x19,0x08,0x0a,0x2a,0x29,0x29,0x2a,0x35, 0x14,0x14,0x09,0x14,0x0e,0x14,0x14,0x15,0x14,0x14,0x13,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0e,0x14,0x14,0x15,0x14,0x14,0x13,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x13,0x12,0x13,0x16,0x10,0x10,0x15,0x17,0x09,0x0c,0x12, 0x0f,0x1c,0x18,0x17,0x12,0x17,0x12,0x10,0x10,0x16,0x13,0x1e,0x13,0x11,0x12,0x1a,0x1d,0x0f,0x17,0x12,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x10,0x10,0x10,0x09,0x09,0x09,0x09,0x18,0x17,0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x16,0x11,0x13,0x13,0x13,0x13,0x13,0x15,0x16,0x16,0x10,0x10,0x10,0x10,0x10,0x15,0x15,0x13, 0x17,0x17,0x09,0x09,0x09,0x09,0x09,0x15,0x0c,0x12,0x0f,0x0f,0x0f,0x0f,0x18,0x18,0x18,0x18,0x17,0x17,0x17,0x12,0x12,0x12,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x16,0x16,0x16,0x16,0x1e,0x1e,0x1e,0x1e,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x1a,0x17,0x13,0x12,0x0e,0x14,0x10,0x12,0x17,0x17,0x09,0x12,0x13,0x1c,0x18, 0x11,0x17,0x17,0x12,0x11,0x10,0x11,0x17,0x13,0x18,0x17,0x13,0x10,0x17,0x09,0x17,0x11,0x17,0x09,0x11,0x10,0x15,0x0f,0x13,0x10,0x09,0x09,0x0c,0x1e,0x1e,0x17,0x12,0x12,0x17,0x13,0x12,0x12,0x0f,0x16,0x10,0x1b,0x10,0x18,0x18,0x12,0x15,0x1c,0x17,0x17,0x17,0x12,0x13,0x10,0x12,0x17,0x13,0x17,0x14,0x1e,0x1f,0x15,0x1a,0x12,0x13, 0x20,0x12,0x0f,0x15,0x16,0x17,0x21,0x21,0x18,0x13,0x15,0x10,0x15,0x15,0x15,0x1a,0x13,0x13,0x19,0x15,0x15,0x0d,0x17,0x17,0x15,0x12,0x12,0x21,0x1c,0x11,0x14,0x16,0x16,0x17,0x17,0x1a,0x19,0x0d,0x23,0x16,0x14,0x15,0x18,0x18,0x13,0x13,0x0a,0x1c,0x19,0x19,0x11,0x1a,0x08,0x08,0x10,0x10,0x08,0x08,0x17,0x0f,0x0a,0x1c,0x1a,0x0b, 0x08,0x08,0x11,0x0e,0x0e,0x08,0x08,0x08,0x0e,0x19,0x11,0x0b,0x16,0x19,0x16,0x15,0x12,0x1c,0x15,0x16,0x0d,0x10,0x14,0x10,0x08,0x08,0x0e,0x13,0x0d,0x19,0x19,0x19,0x22,0x1c,0x22,0x09,0x00,0x00,0x00,0x00,0x00,0x09,0x1c,0x1f,0x0c,0x0c,0x13,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x16,0x16,0x16,0x13,0x13,0x2b,0x1f,0x2b,0x1f,0x31, 0x25,0x31,0x25,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x22,0x22,0x13,0x13,0x22,0x22,0x13,0x13,0x1c,0x1f,0x0c,0x0c,0x1c,0x1f,0x0c,0x0c,0x1c,0x1f,0x0c,0x0c,0x25,0x1c,0x1f,0x13,0x16,0x16,0x19,0x0c,0x19,0x1c,0x13,0x13,0x0c,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x22,0x0c,0x1c,0x13,0x13,0x09,0x13,0x13, 0x13,0x13,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x2b,0x1f,0x2b,0x1f,0x2b,0x1f,0x31,0x25,0x31,0x25,0x1f,0x1f,0x1f,0x25,0x25,0x25,0x25,0x25,0x25,0x1c,0x13,0x13,0x1c,0x13,0x13,0x22,0x13,0x28,0x25,0x22, 0x13,0x1f,0x13,0x1f,0x13,0x1f,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x22,0x13,0x19,0x19,0x19,0x19,0x19,0x0c,0x19,0x19,0x0c,0x0c,0x19,0x0c,0x19,0x0c,0x19,0x13,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0c,0x0c,0x13,0x0c,0x0c,0x0c,0x0c,0x00,0x2b,0x1f,0x31,0x25,0x22,0x13,0x22,0x0c,0x22,0x0c, 0x22,0x0c,0x22,0x0c,0x22,0x0c,0x22,0x0c,0x16,0x16,0x13,0x13,0x0f,0x2b,0x1f,0x25,0x25,0x22,0x22,0x22,0x16,0x16,0x16,0x16,0x19,0x0c,0x19,0x0c,0x19,0x0c,0x2b,0x1f,0x16,0x19,0x16,0x16,0x16,0x19,0x16,0x16,0x2b,0x2b,0x1f,0x1f,0x0f,0x0f,0x16,0x16,0x16,0x16,0x0c,0x0c,0x0c,0x0c,0x1c,0x1f,0x0c,0x0c,0x1c,0x1f,0x0c,0x0c,0x1c,0x1f, 0x0c,0x0c,0x16,0x16,0x16,0x16,0x22,0x0c,0x22,0x0c,0x16,0x19,0x16,0x16,0x2b,0x2b,0x1f,0x1f,0x2b,0x2b,0x1f,0x1f,0x1f,0x1f,0x13,0x13,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x00,0x00,0x09,0x09,0x0c,0x09,0x00,0x00,0x00,0x1f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x19,0x19,0x19,0x19,0x19,0x19,0x16, 0x1f,0x16,0x1f,0x16,0x1f,0x16,0x1f,0x19,0x19,0x19,0x09,0x09,0x13,0x0f,0x16,0x18,0x15,0x14,0x15,0x16,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x14,0x13,0x16,0x17,0x17,0x18,0x15,0x15,0x18,0x13,0x19,0x1c,0x18,0x1c,0x1f,0x18,0x1c,0x19,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x14,0x11, 0x14,0x16,0x16,0x18,0x15,0x18,0x15,0x16,0x16,0x13,0x13,0x1c,0x19,0x1a,0x19,0x19,0x16,0x16,0x15,0x1b,0x1d,0x1c,0x1c,0x22,0x22,0x1a,0x22,0x22,0x1b,0x20,0x1f,0x15,0x1c,0x1f,0x1c,0x16,0x1f,0x1b,0x1a,0x1a,0x16,0x18,0x1c,0x1d,0x1a,0x17,0x1a,0x16,0x14,0x22,0x22,0x22,0x1e,0x22,0x22,0x19,0x22,0x22,0x1a,0x1c,0x1d,0x1c,0x1b,0x1b, 0x18,0x21,0x1c,0x1f,0x1a,0x1a,0x15,0x1b,0x1a,0x1a,0x20,0x1c,0x1b,0x21,0x14,0x13,0x15,0x14,0x17,0x17,0x1a,0x1b,0x15,0x15,0x15,0x14,0x15,0x14,0x14,0x15,0x15,0x15,0x15,0x15,0x15,0x13,0x14,0x16,0x17,0x16,0x16,0x11,0x15,0x15,0x16,0x16,0x1c,0x1f,0x18,0x18,0x17,0x1c,0x18,0x19,0x13,0x12,0x16,0x15,0x12,0x12,0x14,0x14,0x12,0x11, 0x17,0x11,0x14,0x12,0x14,0x1d,0x15,0x1f,0x14,0x15,0x15,0x1c,0x0c,0x1d,0x19,0x1b,0x18,0x15,0x1c,0x16,0x1d,0x16,0x16,0x16,0x16,0x16,0x16,0x15,0x16,0x16,0x16,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x10,0x11,0x11,0x11,0x11,0x11,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x17,0x0a,0x0a,0x0a,0x0b,0x0b,0x0a,0x0a,0x0a,0x0b, 0x0a,0x0a,0x0a,0x21,0x21,0x21,0x21,0x12,0x1b,0x1b,0x12,0x0f,0x12,0x13,0x15,0x12,0x1f,0x1e,0x20,0x10,0x25,0x12,0x1f,0x1f,0x1f,0x1e,0x15,0x12,0x12,0x1d,0x16,0x1d,0x19,0x14,0x11,0x0f,0x26,0x0f,0x14,0x12,0x12,0x12,0x12,0x12,0x32,0x1f,0x1f,0x10,0x09,0x11,0x09,0x11,0x09,0x09,0x09,0x12,0x16,0x16,0x14,0x0e,0x0e,0x08,0x08,0x08, 0x0e,0x08,0x0f,0x20,0x08,0x21,0x21,0x21,0x16,0x16,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x2b,0x2b,0x19,0x2b,0x2b,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x11,0x16,0x11,0x14,0x10, 0x0d,0x0d,0x19,0x14,0x1b,0x10,0x2a,0x21,0x16,0x14,0x22,0x1d,0x1f,0x1c,0x26,0x1e,0x22,0x1d,0x18,0x12,0x1b,0x16,0x22,0x1b,0x1c,0x17,0x1b,0x16,0x20,0x19,0x20,0x19,0x29,0x1f,0x1c,0x16,0x1c,0x16,0x2d,0x21,0x1d,0x00,0x24,0x24,0x24,0x12,0x00,0x00,0x16,0x13,0x1a,0x15,0x14,0x10,0x28,0x21,0x23,0x20,0x1b,0x15,0x1a,0x16,0x13,0x0f, 0x1b,0x16,0x13,0x0f,0x1e,0x19,0x18,0x15,0x24,0x1e,0x14,0x15,0x1b,0x1b,0x1e,0x11,0x07,0x11,0x19,0x10,0x25,0x25,0x09,0x00,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x0f,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x14,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, 0x1c,0x1c,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x21,0x21, 0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, 0x1c,0x1c,0x1c,0x1c,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x12,0x19,0x1b,0x0a,0x08,0x0a,0x08,0x1a,0x15,0x1b,0x17,0x14,0x11,0x14,0x12,0x16,0x15,0x10,0x10,0x2a,0x1e,0x2b, 0x21,0x25,0x1f,0x21,0x18,0x21,0x18,0x21,0x18,0x17,0x11,0x15,0x12,0x15,0x12,0x15,0x12,0x14,0x0c,0x11,0x09,0x1c,0x16,0x20,0x19,0x31,0x25,0x15,0x16,0x19,0x1a,0x1e,0x20,0x1c,0x16,0x24,0x1d,0x14,0x0f,0x15,0x12,0x17,0x12,0x23,0x1b,0x17,0x13,0x15,0x16,0x15,0x16,0x12,0x0f,0x12,0x0e,0x11,0x0e,0x13,0x13,0x0b,0x19,0x0c,0x23,0x19, 0x0d,0x16,0x17,0x11,0x1c,0x15,0x0e,0x0d,0x15,0x15,0x15,0x11,0x09,0x1c,0x16,0x0e,0x0d,0x17,0x11,0x1a,0x0e,0x1d,0x16,0x17,0x11,0x19,0x16,0x15,0x12,0x1c,0x15,0x16,0x0d,0x14,0x10,0x1c,0x10,0x14,0x20,0x12,0x15,0x21,0x0a,0x2a,0x21,0x21,0x2c,0x21,0x22,0x22,0x21,0x21,0x22,0x13,0x11,0x17,0x1a,0x21,0x1a,0x23,0x09,0x11,0x16,0x20, 0x26,0x1a,0x26,0x17,0x17,0x1d,0x1a,0x2a,0x22,0x13,0x22,0x0c,0x22,0x0c,0x16,0x16,0x16,0x16,0x1f,0x1f,0x1f,0x1f,0x25,0x13,0x13,0x25,0x1c,0x13,0x13,0x1c,0x19,0x0c,0x0c,0x19,0x16,0x16,0x16,0x16,0x1c,0x0c,0x0c,0x1f,0x1c,0x0c,0x0c,0x1f,0x0f,0x0f,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x13,0x0f,0x15,0x14,0x1c,0x16,0x15,0x20,0x19,0x1c,0x1c,0x1f,0x1e,0x15,0x12,0x25,0x1e,0x27,0x20,0x19,0x16,0x0c,0x0c,0x16,0x18,0x0f,0x16,0x13,0x15,0x12,0x1b,0x1e,0x0f,0x16,0x10,0x08,0x0e,0x14,0x14,0x08,0x08,0x07,0x08,0x0e,0x0e,0x0e,0x11,0x37, 0x4a,0x0d,0x0f,0x05,0x0a,0x0e,0x10,0x0c,0x12,0x14,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x11,0x11,0x11,0x11,0x11,0x31,0x14,0x1c,0x22,0x21,0x18,0x11,0x15,0x1b,0x1b,0x12,0x0c,0x18,0x13,0x19,0x15,0x18,0x14,0x14,0x1c,0x16,0x15,0x13,0x1c,0x17,0x1f,0x11,0x13,0x17,0x0c,0x16,0x0d,0x0d,0x09,0x20,0x16,0x15,0x13,0x13, 0x16,0x22,0x22,0x23,0x25,0x25,0x14,0x12,0x0a,0x13,0x11,0x17,0x11,0x19,0x09,0x15,0x16,0x20,0x20,0x17,0x14,0x15,0x14,0x13,0x11,0x13,0x11,0x12,0x0b,0x0c,0x09,0x08,0x0d,0x15,0x17,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0c,0x00,0x0b,0x0b,0x0b,0x09,0x09,0x3e,0x25,0x20,0x27,0x0b,0x0b,0x0c, 0x0f,0x09,0x0a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x22,0x0c,0x0c,0x22,0x0a,0x13,0x13,0x31,0x25,0x25,0x31,0x22,0x13,0x13,0x22,0x13,0x13,0x0f,0x0f,0x00,0x00,0x0d,0x1c,0x16,0x1a,0x15,0x2e,0x26,0x1a,0x14,0x1a,0x14,0x31,0x25,0x1c,0x16,0x0e,0x0c,0x17,0x00,0x19,0x14,0x0c,0x0b,0x06,0x12,0x0c,0x0d,0x09,0x07, 0x11,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x08,0x13,0x10,0x16,0x15,0x14,0x24,0x1e,0x1e,0x1d,0x1e,0x23,0x17,0x19,0x16,0x0f,0x22,0x2a,0x10,0x2b,0x13,0x1f,0x22,0x22,0x22,0x0f,0x1c,0x25,0x1c,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x16,0x16,0x16,0x1f,0x13,0x13,0x22,0x0c,0x0c, 0x22,0x0c,0x0c,0x22,0x12,0x12,0x00,0x0f,0x1f,0x0c,0x0c,0x25,0x13,0x13,0x1c,0x13,0x13,0x19,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x38,0x38,0x21,0x00,0x00,0x21,0x21,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x19,0x17,0x18,0x18,0x21,0x18,0x17,0x1e, 0x24,0x18,0x17,0x28,0x17,0x17,0x23,0x17,0x19,0x1d,0x18,0x1c,0x1f,0x22,0x18,0x1c,0x18,0x1a,0x17,0x1a,0x17,0x18,0x19,0x17,0x1d,0x16,0x19,0x1d,0x17,0x17,0x15,0x1d,0x18,0x18,0x18,0x1a,0x11,0x14,0x18,0x1d,0x1d,0x14,0x00,0x00,0x2a,0x54,0x1b,0x00,0x04,0x0c,0x0c,0x10,0x19,0x17,0x22,0x22,0x0a,0x0d,0x0d,0x12,0x1d,0x09,0x11,0x09, 0x10,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x09,0x09,0x1d,0x1d,0x1d,0x13,0x28,0x1b,0x18,0x1a,0x1d,0x15,0x15,0x1d,0x1e,0x0b,0x0f,0x18,0x14,0x26,0x1f,0x20,0x18,0x20,0x19,0x16,0x16,0x1d,0x1a,0x27,0x19,0x17,0x18,0x0d,0x10,0x0d,0x1d,0x11,0x0b,0x15,0x19,0x13,0x19,0x16,0x0d,0x19,0x18,0x0a,0x0a,0x15,0x0a,0x24,0x18, 0x19,0x19,0x19,0x0f,0x12,0x0e,0x18,0x14,0x1e,0x13,0x14,0x13,0x0d,0x0a,0x0d,0x1d,0x1b,0x1b,0x1a,0x15,0x1f,0x20,0x1d,0x15,0x15,0x15,0x15,0x15,0x15,0x13,0x16,0x16,0x16,0x16,0x0a,0x0a,0x0a,0x0a,0x18,0x19,0x19,0x19,0x19,0x19,0x18,0x18,0x18,0x18,0x10,0x10,0x17,0x17,0x13,0x11,0x13,0x17,0x11,0x25,0x25,0x20,0x0c,0x11,0x1d,0x24, 0x20,0x22,0x1d,0x1d,0x1d,0x17,0x18,0x16,0x1a,0x20,0x17,0x10,0x12,0x20,0x23,0x19,0x13,0x0c,0x0c,0x1d,0x1b,0x17,0x1d,0x1b,0x15,0x15,0x1f,0x1b,0x1b,0x20,0x27,0x27,0x15,0x2a,0x10,0x10,0x0a,0x0a,0x1d,0x19,0x14,0x17,0x07,0x17,0x0d,0x0d,0x17,0x17,0x10,0x09,0x0a,0x10,0x33,0x1b,0x15,0x1b,0x15,0x15,0x0b,0x0b,0x0b,0x0b,0x20,0x20, 0x20,0x1d,0x1d,0x1d,0x0a,0x10,0x0e,0x0d,0x0d,0x08,0x0c,0x09,0x0e,0x08,0x10,0x14,0x0c,0x16,0x12,0x18,0x13,0x0a,0x1d,0x17,0x17,0x14,0x18,0x19,0x1d,0x1d,0x0f,0x0f,0x0f,0x27,0x26,0x28,0x15,0x1d,0x19,0x0b,0x16,0x12,0x1a,0x13,0x1a,0x13,0x19,0x11,0x09,0x1b,0x15,0x1b,0x15,0x1d,0x1c,0x1d,0x15,0x16,0x15,0x16,0x14,0x0a,0x14,0x0d, 0x14,0x0d,0x1f,0x18,0x1f,0x18,0x20,0x19,0x19,0x0f,0x19,0x0f,0x16,0x12,0x16,0x0e,0x16,0x12,0x1d,0x18,0x1d,0x18,0x18,0x13,0x18,0x13,0x14,0x20,0x20,0x1a,0x19,0x12,0x18,0x14,0x1d,0x11,0x14,0x10,0x2f,0x1a,0x15,0x19,0x0a,0x10,0x22,0x0e,0x19,0x0f,0x0f,0x19,0x0f,0x1b,0x15,0x1a,0x13,0x1a,0x13,0x15,0x16,0x15,0x16,0x15,0x16,0x1d, 0x19,0x1d,0x19,0x1d,0x19,0x1e,0x18,0x1e,0x18,0x0b,0x0a,0x0b,0x0a,0x0b,0x0a,0x0b,0x0a,0x0f,0x0a,0x18,0x15,0x15,0x14,0x0a,0x1f,0x18,0x1f,0x18,0x20,0x19,0x20,0x19,0x19,0x0f,0x16,0x12,0x16,0x0e,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x27,0x1e,0x17,0x14,0x0a,0x1b,0x15,0x24,0x23,0x20,0x19,0x09,0x27,0x1e,0x27,0x1e,0x27,0x1e, 0x17,0x14,0x0a,0x11,0x17,0x19,0x27,0x27,0x27,0x25,0x10,0x10,0x09,0x0b,0x0b,0x1b,0x18,0x21,0x10,0x22,0x1c,0x23,0x0b,0x1b,0x18,0x15,0x18,0x1e,0x0b,0x18,0x1a,0x26,0x1f,0x15,0x20,0x1e,0x18,0x16,0x16,0x17,0x19,0x21,0x20,0x0b,0x17,0x1a,0x12,0x18,0x0b,0x17,0x17,0x16,0x13,0x18,0x19,0x0b,0x16,0x15,0x18,0x16,0x13,0x19,0x19,0x13, 0x17,0x17,0x20,0x22,0x0b,0x17,0x19,0x17,0x22,0x15,0x1d,0x14,0x1a,0x16,0x0b,0x29,0x29,0x1e,0x18,0x18,0x1e,0x1b,0x18,0x18,0x14,0x1d,0x15,0x24,0x17,0x1f,0x1f,0x18,0x1c,0x26,0x1e,0x20,0x1e,0x18,0x1a,0x16,0x18,0x1f,0x19,0x1f,0x1c,0x28,0x29,0x1e,0x21,0x18,0x1a,0x2b,0x19,0x15,0x18,0x16,0x10,0x17,0x16,0x1f,0x13,0x18,0x18,0x15, 0x16,0x1d,0x18,0x19,0x18,0x19,0x13,0x11,0x14,0x1d,0x13,0x19,0x18,0x22,0x23,0x19,0x1e,0x15,0x13,0x22,0x15,0x16,0x18,0x10,0x13,0x12,0x0a,0x21,0x22,0x18,0x15,0x14,0x18,0x14,0x10,0x2a,0x2f,0x1a,0x0f,0x0f,0x0f,0x0f,0x0a,0x16,0x12,0x17,0x20,0x19,0x1e,0x19,0x0d,0x0e,0x0b,0x0b,0x14,0x14,0x14,0x14,0x0d,0x0d,0x0d,0x14,0x0d,0x14, 0x0d,0x0d,0x0d,0x14,0x14,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x0b,0x0a,0x0b,0x0a,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20, 0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x1d,0x18,0x1d,0x18,0x1e,0x19,0x1e,0x19,0x1e,0x19,0x1e,0x19,0x1e,0x19,0x17,0x14,0x17,0x14,0x17,0x14,0x16,0x0e,0x15,0x16,0x1f,0x18,0x0b,0x0f,0x0a,0x0a,0x16,0x11,0x26,0x21,0x1a,0x16,0x18,0x15,0x1f,0x19,0x17,0x14,0x17,0x14,0x1a,0x15,0x1c,0x18,0x1c,0x18,0x1e,0x16,0x20,0x19,0x0d, 0x0d,0x0d,0x0d,0x11,0x11,0x14,0x14,0x14,0x14,0x0b,0x0b,0x0d,0x0d,0x0d,0x0d,0x15,0x16,0x1b,0x15,0x18,0x19,0x18,0x19,0x18,0x19,0x1a,0x13,0x1d,0x19,0x1d,0x19,0x1d,0x19,0x1d,0x19,0x1d,0x19,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x16,0x15,0x0d,0x1d,0x19,0x1e,0x18,0x1e,0x18,0x1e,0x18,0x1e,0x18,0x1e,0x18,0x0b,0x0a,0x0b, 0x0a,0x18,0x15,0x18,0x15,0x18,0x15,0x14,0x0a,0x14,0x0a,0x14,0x0a,0x14,0x0a,0x26,0x24,0x26,0x24,0x26,0x24,0x1f,0x18,0x1f,0x18,0x1f,0x18,0x1f,0x18,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x18,0x19,0x18,0x19,0x19,0x0f,0x19,0x0f,0x19,0x0f,0x19,0x0f,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x12,0x16,0x0e,0x16,0x0e,0x16, 0x0e,0x16,0x0e,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1a,0x14,0x1a,0x14,0x27,0x1e,0x27,0x1e,0x19,0x13,0x19,0x13,0x17,0x14,0x18,0x13,0x18,0x13,0x18,0x13,0x18,0x0e,0x1e,0x14,0x15,0x0a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x12,0x12,0x12,0x12,0x12,0x12,0x18,0x18,0x1e, 0x1e,0x1e,0x1e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x20,0x20,0x27,0x27,0x27,0x27,0x27,0x27,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x10,0x10,0x15,0x15,0x16,0x16,0x16,0x16,0x19,0x19,0x19,0x19,0x19,0x19,0x22,0x22,0x28,0x28,0x28,0x28,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1c,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, 0x22,0x22,0x22,0x23,0x23,0x28,0x28,0x28,0x28,0x28,0x28,0x1a,0x1a,0x12,0x12,0x18,0x18,0x0b,0x0b,0x19,0x19,0x17,0x17,0x22,0x22,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x21,0x20,0x27,0x27,0x27,0x27,0x27,0x27,0x22,0x22,0x22,0x22,0x22,0x22,0x22, 0x22,0x23,0x23,0x28,0x28,0x28,0x28,0x28,0x28,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x19,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x21,0x21,0x1e,0x19,0x19,0x19,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x10,0x19,0x19,0x19,0x17,0x17,0x17,0x17,0x19,0x19,0x17,0x17,0x17,0x17,0x1c,0x1c, 0x1a,0x19,0x19,0x19,0x22,0x22,0x22,0x22,0x22,0x23,0x23,0x23,0x23,0x20,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x1a,0x18,0x19,0x18,0x19,0x1a,0x1a,0x14,0x1d,0x1f,0x18,0x19,0x19,0x15,0x17,0x15,0x1d,0x1a,0x25,0x0c,0x0c,0x18,0x15,0x0a,0x15,0x25,0x1f,0x18,0x20,0x29,0x21,0x19,0x19, 0x18,0x16,0x12,0x16,0x0c,0x0e,0x16,0x0e,0x16,0x20,0x1e,0x18,0x16,0x18,0x13,0x1a,0x1a,0x13,0x11,0x17,0x17,0x10,0x11,0x17,0x0a,0x10,0x13,0x0c,0x34,0x30,0x2b,0x24,0x1e,0x15,0x2d,0x29,0x22,0x1b,0x15,0x0b,0x0a,0x20,0x19,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x1d,0x18,0x16,0x1b,0x15,0x1b,0x15,0x24,0x23,0x1d,0x19,0x1d,0x19, 0x18,0x15,0x20,0x19,0x20,0x19,0x1a,0x13,0x0a,0x34,0x30,0x2b,0x1d,0x19,0x2a,0x1d,0x1f,0x18,0x1b,0x15,0x1b,0x15,0x15,0x16,0x15,0x16,0x0b,0x0a,0x0b,0x0a,0x20,0x19,0x20,0x19,0x18,0x0f,0x19,0x0f,0x1d,0x18,0x1d,0x18,0x15,0x12,0x1e,0x18,0x1f,0x19,0x18,0x18,0x13,0x1b,0x15,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x17,0x14,0x19, 0x15,0x18,0x18,0x19,0x15,0x19,0x19,0x19,0x14,0x14,0x19,0x19,0x16,0x1a,0x11,0x11,0x15,0x17,0x0c,0x19,0x19,0x16,0x14,0x13,0x18,0x18,0x18,0x0b,0x0c,0x0d,0x0c,0x10,0x0a,0x19,0x24,0x24,0x24,0x17,0x17,0x19,0x19,0x1d,0x1e,0x1b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x13,0x13,0x11,0x0a,0x0b,0x0c,0x0c,0x0e,0x0e,0x19,0x19,0x17,0x14, 0x1e,0x14,0x12,0x13,0x16,0x13,0x13,0x0f,0x0f,0x0f,0x14,0x1a,0x14,0x17,0x16,0x18,0x0a,0x15,0x10,0x19,0x0f,0x0f,0x26,0x28,0x29,0x1a,0x14,0x1e,0x21,0x18,0x18,0x15,0x15,0x17,0x19,0x18,0x1c,0x18,0x1b,0x22,0x18,0x1d,0x19,0x18,0x13,0x15,0x13,0x19,0x15,0x1a,0x15,0x25,0x24,0x19,0x15,0x1b,0x16,0x1a,0x13,0x19,0x14,0x1c,0x19,0x18, 0x11,0x18,0x18,0x13,0x0a,0x20,0x14,0x14,0x24,0x1c,0x1b,0x18,0x26,0x1e,0x1c,0x15,0x25,0x1d,0x1f,0x18,0x27,0x1f,0x17,0x13,0x21,0x20,0x20,0x19,0x1e,0x18,0x1e,0x18,0x37,0x2f,0x23,0x1b,0x2f,0x26,0x24,0x1c,0x19,0x12,0x15,0x11,0x11,0x00,0x00,0x29,0x28,0x18,0x15,0x18,0x19,0x18,0x15,0x17,0x13,0x18,0x15,0x1e,0x18,0x23,0x1c,0x2a, 0x23,0x1e,0x17,0x1a,0x13,0x16,0x11,0x25,0x1d,0x1d,0x19,0x23,0x1b,0x23,0x1b,0x0b,0x24,0x1f,0x18,0x15,0x1e,0x18,0x1c,0x18,0x1b,0x15,0x1b,0x15,0x24,0x23,0x15,0x16,0x1e,0x16,0x1e,0x16,0x24,0x1f,0x17,0x13,0x16,0x13,0x1f,0x18,0x1f,0x18,0x20,0x19,0x20,0x19,0x1a,0x13,0x18,0x14,0x18,0x14,0x18,0x14,0x1c,0x18,0x21,0x1e,0x18,0x19, 0x24,0x24,0x22,0x1e,0x17,0x14,0x26,0x21,0x2a,0x24,0x1e,0x16,0x1c,0x19,0x19,0x18,0x18,0x15,0x19,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x0a,0x19,0x0e,0x0e,0x07,0x09,0x09,0x09,0x0c,0x11,0x0c,0x0a,0x10,0x09,0x09,0x09,0x0e,0x0e,0x09,0x09,0x19,0x19,0x19,0x19,0x0e,0x0c,0x0b,0x0e,0x0d,0x0b, 0x0c,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x0e,0x0d,0x0e,0x0e,0x0c,0x07,0x0a,0x0c,0x09,0x10,0x10,0x10,0x10,0x10,0x0e,0x0e,0x0e,0x11,0x0e,0x0a,0x0b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17, 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17, 0x10,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x1b,0x0c,0x1b,0x0e,0x19,0x19,0x0e,0x0e,0x0e,0x0e,0x0e,0x0b,0x0e,0x0e,0x0e,0x0c,0x0e,0x0e,0x0e,0x0e, 0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x19,0x14,0x1c,0x23,0x14,0x13,0x17,0x17,0x12,0x11,0x0a,0x0d,0x15,0x10,0x1d,0x18,0x19,0x14,0x1a,0x1a,0x1a,0x27,0x17,0x19,0x19,0x13,0x13,0x13,0x11,0x16,0x18,0x1e,0x18,0x14,0x1e,0x13,0x12,0x11,0x16,0x10,0x14,0x18,0x13,0x19,0x18,0x0f,0x14,0x0f,0x0f, 0x11,0x0d,0x0d,0x11,0x12,0x08,0x0a,0x0f,0x0c,0x16,0x12,0x12,0x12,0x10,0x0e,0x0e,0x0c,0x11,0x16,0x0d,0x0d,0x0f,0x14,0x0f,0x0f,0x0d,0x0d,0x0b,0x0b,0x0f,0x07,0x0d,0x15,0x0e,0x0e,0x0b,0x0e,0x0e,0x0e,0x08,0x0e,0x0e,0x15,0x0c,0x0d,0x0e,0x0c,0x0e,0x11,0x0d,0x07,0x09,0x0e,0x0c,0x0e,0x0c,0x0f,0x11,0x0d,0x18,0x07,0x0f,0x17,0x25, 0x1a,0x17,0x17,0x24,0x1b,0x24,0x1f,0x16,0x19,0x15,0x13,0x2f,0x13,0x19,0x25,0x27,0x27,0x1a,0x1b,0x1a,0x13,0x14,0x16,0x12,0x13,0x15,0x08,0x00,0x00,0x00,0x00,0x19,0x1a,0x1a,0x1a,0x14,0x10,0x19,0x19,0x0d,0x24,0x18,0x19,0x0f,0x0e,0x13,0x0e,0x13,0x19,0x13,0x18,0x26,0x1b,0x0d,0x0b,0x19,0x16,0x19,0x19,0x19,0x0d,0x19,0x15,0x0a, 0x24,0x18,0x19,0x0f,0x12,0x12,0x14,0x13,0x13,0x15,0x19,0x19,0x16,0x12,0x13,0x1f,0x0a,0x14,0x0a,0x18,0x13,0x0f,0x0b,0x0b,0x0e,0x0b,0x08,0x07,0x0f,0x0e,0x07,0x08,0x07,0x07,0x07,0x08,0x07,0x09,0x15,0x15,0x0e,0x0e,0x0f,0x0e,0x0f,0x0a,0x07,0x08,0x0e,0x0e,0x0e,0x0e,0x0c,0x0b,0x0b,0x0c,0x0b,0x0e,0x00,0x00,0x00,0x00,0x09,0x0d, 0x0d,0x0e,0x0b,0x0d,0x17,0x17,0x17,0x17,0x0e,0x00,0x00,0x00,0x00,0x13,0x0d,0x0b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x0b,0x0b,0x0b,0x0b,0x17,0x17,0x17,0x17,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x17,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0d,0x0d,0x07,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0d,0x0d,0x21,0x1b,0x1e,0x18,0x1f,0x1a,0x27,0x20,0x17,0x10,0x16,0x1d,0x16,0x22,0x1d,0x00,0x00,0x00,0x00,0x0b,0x0b,0x0b,0x0b,0x0e,0x0e,0x0e,0x19,0x19,0x19,0x19, 0x19,0x19,0x23,0x23,0x2a,0x12,0x0b,0x15,0x19,0x12,0x15,0x15,0x19,0x19,0x15,0x2a,0x19,0x19,0x19,0x19,0x19,0x19,0x15,0x15,0x1b,0x15,0x15,0x15,0x0e,0x19,0x0e,0x20,0x1c,0x15,0x0e,0x23,0x15,0x23,0x0b,0x0e,0x19,0x19,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x23,0x0b,0x19,0x0b,0x15,0x12,0x0b,0x0b,0x15,0x0b,0x20,0x0b,0x27,0x15,0x27,0x27, 0x19,0x19,0x19,0x15,0x15,0x12,0x12,0x31,0x31,0x38,0x38,0x23,0x23,0x15,0x15,0x07,0x2a,0x20,0x23,0x1c,0x19,0x1c,0x15,0x15,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x0b,0x1b,0x00,0x1b,0x1b,0x1b,0x0e,0x15,0x15,0x27,0x0e,0x27,0x0e,0x19,0x1c,0x19,0x12,0x27,0x15,0x27,0x15,0x20,0x23,0x0e,0x15,0x15,0x12,0x0b,0x15, 0x19,0x15,0x19,0x15,0x19,0x19,0x15,0x1c,0x1b,0x27,0x0e,0x15,0x12,0x1c,0x15,0x0e,0x15,0x15,0x15,0x27,0x0e,0x27,0x0e,0x0b,0x19,0x10,0x2a,0x15,0x15,0x1b,0x1b,0x2a,0x15,0x00,0x00,0x00,0x1b,0x00,0x1b,0x1b,0x1b,0x1b,0x20,0x1b,0x00,0x00,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x12,0x12,0x15,0x15,0x20,0x23,0x27,0x0e,0x27,0x0e,0x27,0x0e, 0x27,0x0e,0x27,0x0e,0x27,0x0e,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x19,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x12,0x12,0x12,0x15,0x12,0x12,0x12,0x31,0x23,0x31,0x23,0x31,0x23,0x38,0x2a,0x38,0x2a,0x23,0x15,0x19,0x19,0x19,0x2a,0x2a,0x15,0x15,0x2a,0x15,0x15,0x2a,0x15,0x15, 0x2a,0x15,0x15,0x20,0x20,0x2e,0x2a,0x27,0x15,0x23,0x15,0x23,0x15,0x23,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x1c,0x0e,0x1c,0x0e,0x1c,0x0e,0x1c,0x0e,0x1c,0x0e,0x1c,0x1c,0x0e,0x1c,0x0e,0x17,0x1c,0x19,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x23,0x27,0x20,0x23,0x0e,0x15,0x20,0x23,0x20,0x23,0x00,0x00,0x00, 0x00,0x00,0x2f,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x12,0x00,0x00,0x19,0x00,0x00,0x00,0x31,0x23,0x38,0x2a,0x15,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x15,0x27,0x27,0x10,0x19,0x19,0x19,0x34,0x23,0x16,0x40,0x2e,0x0e,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x15,0x15,0x12,0x12,0x20,0x1c,0x1c,0x15,0x00,0x00,0x00,0x0e,0x0e,0x0e,0x0e,0x35,0x3f,0x00,0x00,0x00,0x00,0x00,0x19,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x12,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x19,0x19,0x19,0x19,0x1c,0x19,0x15,0x15,0x12,0x31,0x23,0x15,0x19,0x19,0x19,0x15,0x19,0x19, 0x19,0x15,0x19,0x19,0x19,0x2a,0x15,0x15,0x2a,0x15,0x15,0x27,0x15,0x15,0x27,0x15,0x15,0x27,0x15,0x15,0x19,0x19,0x19,0x19,0x1c,0x0e,0x1c,0x0e,0x1c,0x0e,0x1c,0x1c,0x0e,0x0e,0x12,0x12,0x31,0x23,0x1b,0x19,0x19,0x00,0x15,0x15,0x15,0x10,0x18,0x1d,0x1a,0x15,0x16,0x0f,0x0a,0x20,0x19,0x19,0x0f,0x17,0x14,0x14,0x13,0x14,0x0a,0x16, 0x11,0x1a,0x14,0x19,0x13,0x17,0x12,0x1c,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x13,0x14,0x14,0x0c,0x16,0x18,0x19,0x15,0x0e,0x1f,0x19,0x1b,0x17,0x1a,0x15,0x18,0x16,0x11,0x1d,0x10,0x11,0x12,0x14,0x19,0x19,0x15,0x2a,0x15,0x2a,0x0e,0x0b,0x07,0x17,0x09,0x05,0x00,0x06,0x09,0x00,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x15,0x15,0x27,0x12,0x20,0x19,0x27,0x1e,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x27,0x24,0x14,0x24,0x14,0x24,0x1b,0x1d,0x1d,0x1d,0x20,0x24,0x2a,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x1d,0x1d,0x1d,0x1d,0x1f,0x18,0x2d,0x23,0x14,0x14,0x0c,0x0c,0x0c,0x10,0x09,0x18,0x0a,0x0a,0x23, 0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x08,0x00,0x00,0x09,0x00,0x00,0x1b,0x18,0x12,0x14,0x1c,0x0b,0x0e,0x1c,0x1d,0x0b,0x17,0x17,0x17,0x1d,0x1c,0x0b,0x11,0x1c,0x19,0x1a,0x1b,0x18,0x19,0x1c,0x17,0x21,0x1f,0x16,0x16,0x16,0x0a,0x10,0x17,0x17,0x17,0x17,0x17,0x19,0x1b,0x14,0x1c,0x17, 0x17,0x1d,0x17,0x1f,0x17,0x21,0x21,0x21,0x21,0x1b,0x1b,0x1b,0x18,0x12,0x14,0x1c,0x0d,0x0f,0x1d,0x0d,0x17,0x17,0x17,0x1c,0x11,0x1c,0x1a,0x1b,0x19,0x1c,0x17,0x21,0x1f,0x0b,0x18,0x17,0x1b,0x1b,0x32,0x00,0x1b,0x17,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x0b,0x00,0x20,0x1b,0x1c,0x1e,0x17,0x1c,0x1f,0x20,0x14,0x1a,0x1f,0x1f,0x1c,0x20,0x22,0x21,0x1c,0x17,0x18,0x20,0x1e,0x18,0x1d,0x1c,0x1c,0x1c,0x1d,0x1f,0x18,0x1b,0x1c,0x1b,0x21,0x1b,0x1a,0x1b,0x1c,0x22,0x15,0x19,0x19,0x25,0x17,0x17,0x20,0x25,0x1a,0x17, 0x2c,0x18,0x18,0x20,0x17,0x17,0x20,0x18,0x20,0x22,0x25,0x17,0x20,0x17,0x1b,0x17,0x1a,0x18,0x1b,0x17,0x19,0x20,0x17,0x1a,0x1c,0x17,0x17,0x19,0x28,0x17,0x17,0x19,0x19,0x12,0x0e,0x17,0x17,0x17,0x16,0x17,0x25,0x17,0x25,0x15,0x17,0x25,0x1c,0x17,0x25,0x1f,0x1f,0x25,0x18,0x17,0x25,0x25,0x17,0x17,0x17,0x17,0x17,0x17,0x25,0x25, 0x19,0x17,0x18,0x25,0x19,0x17,0x17,0x17,0x25,0x21,0x1d,0x1d,0x1d,0x1d,0x1e,0x1a,0x1d,0x21,0x1d,0x1b,0x17,0x21,0x1c,0x1d,0x18,0x1c,0x1d,0x1f,0x1e,0x19,0x1d,0x1c,0x1f,0x1c,0x21,0x1d,0x1e,0x1f,0x1d,0x1b,0x1d,0x1d,0x1e,0x21,0x1c,0x20,0x1e,0x04,0x05,0x06,0x08,0x06,0x0b,0x0f,0x24,0x18,0x1a,0x19,0x18,0x1a,0x18,0x18,0x1b,0x19, 0x18,0x0d,0x23,0x19,0x18,0x18,0x17,0x19,0x16,0x18,0x0b,0x19,0x16,0x18,0x11,0x24,0x17,0x18,0x18,0x19,0x23,0x18,0x19,0x11,0x23,0x19,0x19,0x1d,0x1d,0x09,0x0c,0x30,0x2f,0x2f,0x30,0x3c,0x17,0x17,0x0a,0x17,0x10,0x17,0x17,0x18,0x17,0x17,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x10,0x17,0x17,0x18, 0x17,0x17,0x16,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x15,0x15,0x15,0x19,0x12,0x12,0x18,0x1a,0x0b,0x0d,0x15,0x11,0x20,0x1b,0x1a,0x14,0x1a,0x15,0x12,0x12,0x19,0x15,0x22,0x15,0x14,0x14,0x1e,0x21,0x11,0x1a,0x14,0x19,0x16,0x15,0x15,0x15,0x15,0x15,0x15, 0x15,0x12,0x12,0x12,0x12,0x0b,0x0b,0x0b,0x0b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x19,0x19,0x19,0x14,0x15,0x15,0x15,0x15,0x15,0x18,0x19,0x19,0x12,0x12,0x12,0x12,0x12,0x18,0x18,0x15,0x1a,0x1a,0x0b,0x0b,0x0b,0x0b,0x0b,0x18,0x0d,0x15,0x11,0x11,0x11,0x11,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x15,0x15,0x15,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x22,0x22,0x22,0x22,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x1e,0x1a,0x15,0x15,0x10,0x17,0x12,0x14,0x1a,0x1a,0x0b,0x15,0x15,0x20,0x1b,0x13,0x1a,0x1a,0x14,0x13,0x12,0x14,0x1a,0x15,0x1c,0x1b,0x15,0x12,0x1a,0x0b,0x1a,0x14,0x1b,0x0b,0x14,0x12,0x18,0x11,0x16,0x12,0x0b,0x0b,0x0d, 0x22,0x23,0x1a,0x15,0x15,0x1a,0x15,0x14,0x15,0x11,0x19,0x12,0x1f,0x13,0x1b,0x1b,0x15,0x18,0x20,0x1a,0x1a,0x1a,0x14,0x15,0x12,0x15,0x1a,0x15,0x1b,0x17,0x22,0x23,0x18,0x1e,0x15,0x16,0x24,0x15,0x11,0x18,0x18,0x1a,0x25,0x25,0x1c,0x15,0x18,0x12,0x18,0x18,0x18,0x1d,0x16,0x16,0x1d,0x18,0x18,0x0f,0x1a,0x1a,0x18,0x15,0x15,0x26, 0x1f,0x14,0x16,0x19,0x19,0x1a,0x1a,0x1e,0x1d,0x0f,0x27,0x19,0x17,0x18,0x1b,0x1b,0x15,0x15,0x0b,0x20,0x1d,0x1d,0x14,0x1d,0x09,0x09,0x12,0x12,0x09,0x09,0x1a,0x11,0x0b,0x20,0x1e,0x0c,0x09,0x09,0x13,0x10,0x10,0x0a,0x0a,0x0a,0x10,0x1c,0x14,0x0d,0x19,0x1d,0x19,0x18,0x15,0x1f,0x18,0x19,0x0f,0x12,0x16,0x12,0x09,0x0a,0x10,0x16, 0x0e,0x1c,0x1c,0x1c,0x27,0x20,0x27,0x0b,0x00,0x00,0x00,0x00,0x00,0x0b,0x20,0x23,0x0e,0x0e,0x15,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x19,0x19,0x19,0x15,0x15,0x31,0x23,0x31,0x23,0x38,0x2a,0x38,0x2a,0x23,0x23,0x23,0x23,0x23,0x23,0x27,0x27,0x15,0x15,0x27,0x27,0x15,0x15,0x20,0x23,0x0e,0x0e,0x20,0x23,0x0e,0x0e,0x20,0x23,0x0e, 0x0e,0x2a,0x20,0x23,0x15,0x19,0x19,0x1c,0x0e,0x1c,0x20,0x15,0x15,0x0e,0x0e,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x27,0x0e,0x20,0x15,0x15,0x0b,0x15,0x15,0x15,0x15,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x15,0x15,0x15, 0x15,0x15,0x15,0x15,0x15,0x15,0x31,0x23,0x31,0x23,0x31,0x23,0x38,0x2a,0x38,0x2a,0x23,0x23,0x23,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x20,0x15,0x15,0x20,0x15,0x15,0x27,0x15,0x2e,0x2a,0x27,0x15,0x23,0x15,0x23,0x15,0x23,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x27,0x15,0x1c,0x1c,0x1c,0x1c,0x1c,0x0e,0x1c,0x1c,0x0e, 0x0e,0x1c,0x0e,0x1c,0x0e,0x1c,0x15,0x19,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x0e,0x0e,0x15,0x0e,0x0e,0x0e,0x0e,0x00,0x31,0x23,0x38,0x2a,0x27,0x15,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x27,0x0e,0x19,0x19,0x15,0x15,0x12,0x31,0x23,0x2a,0x2a,0x27,0x27,0x27,0x19,0x19,0x19,0x19,0x1c,0x0e,0x1c,0x0e, 0x1c,0x0e,0x31,0x23,0x19,0x1c,0x19,0x19,0x19,0x1c,0x19,0x19,0x31,0x31,0x23,0x23,0x12,0x12,0x19,0x19,0x19,0x19,0x0e,0x0e,0x0e,0x0e,0x20,0x23,0x0e,0x0e,0x20,0x23,0x0e,0x0e,0x20,0x23,0x0e,0x0e,0x19,0x19,0x19,0x19,0x27,0x0e,0x27,0x0e,0x19,0x1c,0x19,0x19,0x31,0x31,0x23,0x23,0x31,0x31,0x23,0x23,0x23,0x23,0x15,0x15,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x00,0x00,0x0b,0x0b,0x0e,0x0b,0x00,0x00,0x00,0x23,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x12,0x12,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x27,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x20,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x19,0x23,0x19,0x23,0x19,0x23,0x19,0x23,0x1c,0x1c,0x1c,0x0b,0x0b,0x15,0x12,0x18,0x1b,0x18,0x17,0x17,0x19,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, 0x17,0x17,0x17,0x17,0x16,0x13,0x17,0x16,0x19,0x1a,0x1a,0x1c,0x18,0x18,0x1b,0x16,0x1c,0x20,0x1b,0x1f,0x23,0x1b,0x20,0x1d,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x16,0x13,0x17,0x19,0x19,0x1c,0x18,0x1b,0x18,0x19,0x19,0x15,0x15,0x20,0x1d,0x1d,0x1c,0x1d,0x19,0x18,0x18,0x1f,0x20,0x20,0x20,0x27,0x27,0x1d,0x27,0x27, 0x1f,0x25,0x24,0x17,0x20,0x24,0x20,0x19,0x24,0x1f,0x1d,0x1d,0x19,0x1b,0x1f,0x21,0x1d,0x1a,0x1e,0x18,0x16,0x27,0x27,0x27,0x23,0x27,0x27,0x1d,0x27,0x27,0x1e,0x20,0x21,0x1f,0x1e,0x1e,0x1b,0x25,0x20,0x23,0x1e,0x1e,0x18,0x1f,0x1d,0x1d,0x24,0x20,0x1e,0x26,0x17,0x15,0x17,0x17,0x1a,0x1a,0x1d,0x1f,0x18,0x18,0x18,0x17,0x18,0x17, 0x17,0x18,0x18,0x18,0x18,0x18,0x18,0x15,0x16,0x19,0x1a,0x19,0x19,0x13,0x18,0x18,0x19,0x19,0x20,0x23,0x1b,0x1b,0x1a,0x20,0x1b,0x1d,0x16,0x14,0x19,0x18,0x14,0x15,0x17,0x17,0x14,0x14,0x1a,0x13,0x17,0x15,0x17,0x21,0x18,0x23,0x17,0x18,0x18,0x1f,0x0d,0x21,0x1d,0x1e,0x1c,0x18,0x20,0x19,0x21,0x19,0x19,0x19,0x19,0x19,0x19,0x18, 0x19,0x19,0x19,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x13,0x13,0x13,0x13,0x14,0x13,0x0d,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x1a,0x0b,0x0b,0x0b,0x0d,0x0d,0x0b,0x0b,0x0b,0x0c,0x0b,0x0b,0x0b,0x26,0x26,0x26,0x26,0x15,0x1f,0x1e,0x15,0x11,0x15,0x16,0x17,0x15,0x23,0x23,0x24,0x13,0x2a,0x15,0x23,0x23,0x23,0x22,0x18,0x15, 0x15,0x21,0x19,0x21,0x1c,0x16,0x13,0x11,0x2b,0x11,0x16,0x15,0x15,0x15,0x15,0x15,0x39,0x23,0x23,0x12,0x0b,0x13,0x0a,0x13,0x0a,0x0a,0x0a,0x14,0x19,0x19,0x17,0x10,0x10,0x0a,0x0a,0x0a,0x10,0x0a,0x11,0x24,0x09,0x26,0x26,0x26,0x19,0x19,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x31,0x31,0x1c,0x31,0x31,0x1c,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x14,0x18,0x14,0x16,0x12,0x0f,0x0f,0x1d,0x17,0x1e,0x12,0x2f,0x26,0x19,0x17,0x27,0x21,0x23,0x1f,0x2b,0x22,0x27,0x20,0x1b,0x14,0x1f,0x19,0x27,0x1f,0x20,0x1a,0x1f,0x19, 0x24,0x1c,0x25,0x1c,0x2e,0x23,0x20,0x19,0x20,0x19,0x33,0x25,0x21,0x00,0x29,0x29,0x29,0x14,0x00,0x00,0x18,0x15,0x1d,0x17,0x16,0x12,0x2d,0x26,0x28,0x24,0x1e,0x18,0x1d,0x19,0x16,0x11,0x1f,0x19,0x16,0x11,0x22,0x1c,0x1c,0x18,0x29,0x22,0x17,0x18,0x1f,0x1f,0x22,0x13,0x08,0x13,0x1d,0x12,0x2a,0x2a,0x0a,0x00,0x29,0x29,0x29,0x29, 0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x11,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x17,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x14,0x1c,0x1f,0x0c,0x09,0x0c,0x09,0x1e,0x18,0x1f,0x1a,0x17,0x14,0x16,0x14,0x19,0x18,0x12,0x12,0x2f,0x22,0x30,0x25,0x29,0x24,0x26,0x1c,0x26,0x1c,0x26,0x1c,0x1a,0x13,0x18,0x15,0x18,0x15,0x18,0x15,0x17,0x0d,0x14,0x0a,0x20,0x19,0x24,0x1c,0x38,0x2a,0x18, 0x19,0x1d,0x1e,0x22,0x24,0x20,0x19,0x29,0x21,0x17,0x11,0x17,0x15,0x1a,0x14,0x27,0x1e,0x1a,0x16,0x18,0x19,0x18,0x19,0x14,0x11,0x14,0x10,0x14,0x0f,0x16,0x16,0x0d,0x1c,0x0e,0x28,0x1c,0x0f,0x18,0x1a,0x13,0x20,0x17,0x10,0x0f,0x18,0x18,0x18,0x14,0x0a,0x20,0x19,0x10,0x0f,0x1a,0x13,0x1e,0x10,0x21,0x19,0x1a,0x13,0x1d,0x19,0x18, 0x15,0x1f,0x18,0x19,0x0f,0x16,0x12,0x20,0x12,0x16,0x24,0x15,0x18,0x26,0x0b,0x30,0x26,0x26,0x32,0x25,0x26,0x26,0x25,0x25,0x27,0x16,0x14,0x1a,0x1d,0x26,0x1d,0x28,0x0a,0x13,0x19,0x24,0x2b,0x1d,0x2b,0x1a,0x1a,0x21,0x1d,0x30,0x27,0x16,0x27,0x0e,0x27,0x0e,0x19,0x19,0x19,0x19,0x23,0x23,0x23,0x23,0x2a,0x15,0x15,0x2a,0x20,0x15, 0x15,0x20,0x1c,0x0e,0x0e,0x1c,0x19,0x19,0x19,0x19,0x20,0x0e,0x0e,0x23,0x20,0x0e,0x0e,0x23,0x12,0x12,0x15,0x15,0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x16,0x11,0x18,0x16,0x1f,0x18,0x18,0x25,0x1c,0x1f,0x20,0x23, 0x22,0x18,0x15,0x2a,0x22,0x2c,0x24,0x1d,0x19,0x0d,0x0d,0x19,0x1b,0x11,0x19,0x16,0x18,0x14,0x1f,0x22,0x11,0x19,0x12,0x09,0x10,0x16,0x17,0x09,0x09,0x08,0x09,0x10,0x10,0x10,0x13,0x3f,0x54,0x0e,0x11,0x06,0x0b,0x10,0x12,0x0d,0x15,0x16,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x14,0x14,0x14,0x14,0x14,0x38,0x17,0x20, 0x27,0x26,0x1b,0x13,0x18,0x1e,0x1f,0x15,0x0d,0x1c,0x16,0x1d,0x17,0x1c,0x16,0x17,0x1f,0x19,0x18,0x16,0x1f,0x1a,0x23,0x13,0x16,0x1b,0x0d,0x19,0x0e,0x0f,0x0a,0x25,0x18,0x18,0x16,0x16,0x19,0x27,0x27,0x28,0x2a,0x2a,0x17,0x15,0x0c,0x15,0x13,0x1a,0x13,0x1c,0x0a,0x18,0x19,0x24,0x24,0x1a,0x17,0x18,0x17,0x16,0x13,0x16,0x13,0x14, 0x0d,0x0e,0x0a,0x09,0x0f,0x18,0x1b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x0d,0x00,0x0c,0x0c,0x0c,0x0b,0x0b,0x47,0x2a,0x25,0x2c,0x0c,0x0c,0x0e,0x11,0x0b,0x0b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x27,0x0e,0x0e,0x27,0x0b,0x15,0x15,0x38,0x2a,0x2a,0x38,0x27,0x15,0x15, 0x27,0x15,0x15,0x12,0x12,0x00,0x00,0x0f,0x1f,0x19,0x1e,0x18,0x35,0x2b,0x1d,0x17,0x1d,0x17,0x38,0x2a,0x20,0x19,0x10,0x0d,0x1a,0x00,0x1d,0x17,0x0e,0x0d,0x07,0x15,0x0e,0x0e,0x0b,0x08,0x13,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x09,0x16,0x12,0x19,0x18,0x17,0x28,0x22,0x22,0x21,0x22,0x28,0x1a,0x1d,0x19,0x11,0x27,0x2f,0x12, 0x31,0x15,0x23,0x27,0x27,0x27,0x12,0x20,0x2a,0x20,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x19,0x19,0x19,0x23,0x15,0x15,0x27,0x0e,0x0e,0x27,0x0e,0x0e,0x27,0x15,0x15,0x00,0x12,0x23,0x0e,0x0e,0x2a,0x15,0x15,0x20,0x15,0x15,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x0c,0x3f,0x3f,0x25,0x00,0x00,0x25,0x25,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x1c,0x1a,0x1b,0x1b,0x25,0x1b,0x1a,0x22,0x29,0x1b,0x1a,0x2d,0x1b,0x1b,0x27,0x1a,0x1c,0x21,0x1b,0x20,0x24,0x26,0x1b,0x20,0x1b,0x1d,0x1a,0x1d,0x1a,0x1c,0x1d,0x1a,0x21,0x19,0x1c,0x21, 0x1a,0x1a,0x18,0x21,0x1b,0x1b,0x1b,0x1d,0x13,0x16,0x1b,0x21,0x21,0x17,0x00,0x00,0x2e,0x5c,0x1e,0x00,0x04,0x0d,0x0d,0x12,0x1b,0x19,0x26,0x25,0x0b,0x0e,0x0e,0x13,0x1f,0x0a,0x12,0x0a,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x0a,0x0a,0x1f,0x1f,0x1f,0x15,0x2c,0x1e,0x1a,0x1c,0x20,0x17,0x16,0x20,0x21,0x0c,0x10, 0x1b,0x16,0x29,0x22,0x23,0x1a,0x23,0x1c,0x18,0x18,0x20,0x1d,0x2b,0x1b,0x19,0x1a,0x0e,0x11,0x0e,0x1f,0x13,0x0c,0x17,0x1b,0x15,0x1b,0x18,0x0e,0x1b,0x1a,0x0b,0x0b,0x17,0x0b,0x28,0x1a,0x1b,0x1b,0x1b,0x10,0x14,0x10,0x1a,0x16,0x21,0x15,0x16,0x15,0x0e,0x0b,0x0e,0x1f,0x1e,0x1e,0x1c,0x17,0x22,0x23,0x20,0x17,0x17,0x17,0x17,0x17, 0x17,0x15,0x18,0x18,0x18,0x18,0x0b,0x0b,0x0b,0x0b,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x11,0x11,0x19,0x19,0x15,0x13,0x15,0x19,0x12,0x29,0x29,0x24,0x0d,0x13,0x20,0x28,0x23,0x26,0x1f,0x20,0x20,0x19,0x1b,0x19,0x1c,0x23,0x19,0x12,0x14,0x23,0x26,0x1b,0x15,0x0d,0x0d,0x1f,0x1e,0x19,0x20,0x1e,0x17,0x17,0x22,0x1e, 0x1e,0x23,0x2b,0x2b,0x17,0x2e,0x11,0x11,0x0b,0x0b,0x1f,0x1b,0x16,0x19,0x08,0x19,0x0f,0x0f,0x1a,0x1a,0x11,0x0a,0x0b,0x11,0x38,0x1e,0x17,0x1e,0x17,0x17,0x0c,0x0c,0x0c,0x0c,0x23,0x23,0x23,0x20,0x20,0x20,0x0b,0x11,0x10,0x0e,0x0e,0x09,0x0d,0x09,0x0f,0x09,0x11,0x16,0x0d,0x18,0x14,0x1a,0x15,0x0b,0x20,0x1a,0x19,0x16,0x1a,0x1b, 0x1f,0x1f,0x10,0x11,0x11,0x2b,0x2a,0x2c,0x16,0x20,0x1b,0x0c,0x18,0x14,0x1c,0x15,0x1c,0x15,0x1b,0x13,0x0a,0x1e,0x17,0x1e,0x17,0x20,0x1f,0x20,0x17,0x18,0x17,0x18,0x16,0x0b,0x16,0x0e,0x16,0x0e,0x22,0x1a,0x22,0x1a,0x23,0x1b,0x1c,0x10,0x1c,0x10,0x18,0x14,0x18,0x10,0x18,0x14,0x20,0x1a,0x20,0x1a,0x1a,0x15,0x1a,0x15,0x16,0x23, 0x23,0x1c,0x1b,0x14,0x1a,0x16,0x20,0x13,0x16,0x12,0x33,0x1d,0x17,0x1c,0x0b,0x11,0x25,0x0f,0x1c,0x10,0x10,0x1c,0x10,0x1e,0x17,0x1c,0x15,0x1c,0x15,0x17,0x18,0x17,0x18,0x17,0x18,0x20,0x1b,0x20,0x1b,0x20,0x1b,0x21,0x1a,0x21,0x1a,0x0c,0x0b,0x0c,0x0b,0x0c,0x0b,0x0c,0x0b,0x10,0x0b,0x1b,0x17,0x17,0x16,0x0b,0x22,0x1a,0x22,0x1a, 0x23,0x1b,0x23,0x1b,0x1c,0x10,0x18,0x14,0x18,0x10,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x2b,0x21,0x19,0x16,0x0b,0x1e,0x17,0x28,0x26,0x23,0x1b,0x0a,0x2b,0x21,0x2b,0x21,0x2b,0x21,0x19,0x16,0x0b,0x13,0x19,0x1c,0x2a,0x2a,0x2b,0x29,0x12,0x12,0x0a,0x0d,0x0d,0x1e,0x1a,0x24,0x11,0x25,0x1f,0x26,0x0c,0x1e,0x1a,0x17,0x1a,0x21, 0x0c,0x1b,0x1d,0x29,0x22,0x17,0x23,0x21,0x1a,0x18,0x18,0x19,0x1b,0x24,0x23,0x0c,0x19,0x1c,0x14,0x1a,0x0c,0x19,0x19,0x18,0x14,0x1a,0x1b,0x0c,0x18,0x17,0x1b,0x18,0x14,0x1b,0x1b,0x15,0x19,0x19,0x23,0x25,0x0c,0x19,0x1b,0x19,0x25,0x17,0x20,0x16,0x1c,0x18,0x0c,0x2d,0x2d,0x21,0x1b,0x1a,0x21,0x1e,0x1a,0x1a,0x16,0x20,0x17,0x28, 0x19,0x22,0x22,0x1b,0x1f,0x29,0x21,0x23,0x21,0x1a,0x1c,0x18,0x1a,0x21,0x1b,0x22,0x1e,0x2c,0x2d,0x20,0x24,0x1b,0x1c,0x2f,0x1b,0x17,0x1b,0x18,0x12,0x19,0x18,0x22,0x15,0x1b,0x1b,0x17,0x18,0x20,0x1b,0x1b,0x1b,0x1b,0x15,0x13,0x16,0x20,0x15,0x1c,0x1a,0x25,0x26,0x1b,0x21,0x17,0x15,0x25,0x17,0x18,0x1b,0x12,0x15,0x14,0x0b,0x24, 0x25,0x1a,0x17,0x16,0x1b,0x16,0x12,0x2e,0x34,0x1d,0x10,0x11,0x11,0x11,0x0b,0x18,0x14,0x1a,0x23,0x1b,0x21,0x1b,0x0e,0x0f,0x0c,0x0c,0x16,0x16,0x16,0x16,0x0e,0x0e,0x0e,0x16,0x0e,0x16,0x0e,0x0e,0x0e,0x16,0x16,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e,0x17,0x1e, 0x17,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x0c,0x0b,0x0c,0x0b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x20,0x1a,0x20,0x1a,0x21,0x1b,0x21,0x1b,0x21,0x1b,0x21,0x1b,0x21,0x1b,0x19,0x16,0x19,0x16,0x19, 0x16,0x18,0x10,0x17,0x18,0x22,0x1b,0x0c,0x10,0x0b,0x0b,0x18,0x13,0x2a,0x24,0x1c,0x18,0x1b,0x17,0x22,0x1c,0x19,0x16,0x19,0x16,0x1d,0x17,0x1e,0x1a,0x1e,0x1a,0x21,0x18,0x23,0x1b,0x0e,0x0e,0x0e,0x0e,0x13,0x13,0x16,0x16,0x16,0x16,0x0c,0x0c,0x0e,0x0e,0x0e,0x0e,0x17,0x18,0x1e,0x17,0x1a,0x1b,0x1a,0x1b,0x1a,0x1b,0x1c,0x15,0x20, 0x1b,0x20,0x1b,0x20,0x1b,0x20,0x1b,0x20,0x1b,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x17,0x18,0x16,0x0e,0x20,0x1b,0x21,0x1a,0x21,0x1a,0x21,0x1a,0x21,0x1a,0x21,0x1a,0x0c,0x0b,0x0c,0x0b,0x1b,0x17,0x1b,0x17,0x1b,0x17,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x16,0x0b,0x29,0x28,0x29,0x28,0x29,0x28,0x22,0x1a,0x22,0x1a,0x22,0x1a,0x22, 0x1a,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x1a,0x1b,0x1a,0x1b,0x1c,0x10,0x1c,0x10,0x1c,0x10,0x1c,0x10,0x18,0x14,0x18,0x14,0x18,0x14,0x18,0x14,0x18,0x14,0x18,0x10,0x18,0x10,0x18,0x10,0x18,0x10,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x1d,0x16,0x1d,0x16,0x2b,0x21,0x2b,0x21,0x1b,0x15,0x1b,0x15,0x19,0x16,0x1a, 0x15,0x1a,0x15,0x1a,0x15,0x1a,0x10,0x21,0x16,0x17,0x0b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1e,0x1e,0x22,0x22,0x22,0x22,0x22,0x22,0x14,0x14,0x14,0x14,0x14,0x14,0x1a,0x1a,0x21,0x21,0x21,0x21,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x24,0x24,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11, 0x11,0x17,0x17,0x18,0x18,0x18,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x25,0x25,0x2c,0x2c,0x2c,0x2c,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1f,0x26,0x26,0x26,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x26,0x26,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x1c,0x1c,0x14,0x14,0x1a,0x1a,0x0c,0x0c,0x1b,0x1b,0x19,0x19,0x25,0x25,0x1c,0x1c,0x1c, 0x1c,0x1c,0x1c,0x1c,0x1c,0x1e,0x1e,0x22,0x22,0x22,0x22,0x22,0x22,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x24,0x24,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x26,0x26,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1e,0x1e,0x1e,0x1e,0x1e,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a, 0x1a,0x1a,0x1a,0x1a,0x1a,0x24,0x24,0x21,0x1b,0x1b,0x1b,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x11,0x11,0x1b,0x1b,0x1b,0x19,0x19,0x19,0x19,0x1b,0x1b,0x19,0x19,0x19,0x19,0x1f,0x1f,0x1d,0x1b,0x1b,0x1b,0x25,0x25,0x25,0x25,0x25,0x26,0x26,0x27,0x26,0x23,0x1b,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x1b,0x1c,0x1a,0x1b,0x1b,0x1b,0x1d,0x1d,0x15,0x20,0x22,0x1a,0x1b,0x1b,0x17,0x19,0x16,0x20,0x1d,0x28,0x0d,0x0d,0x1b,0x17,0x0b,0x17,0x29,0x22,0x1a,0x23,0x2d,0x24,0x1c,0x1b,0x1b,0x18,0x14,0x18,0x0e,0x10,0x18,0x10,0x18,0x23,0x21,0x1a,0x18,0x1a,0x15,0x1c,0x1c,0x14,0x13,0x19,0x19,0x11,0x12,0x19,0x0b,0x12,0x15,0x0d, 0x39,0x34,0x2f,0x27,0x21,0x17,0x31,0x2d,0x25,0x1e,0x17,0x0c,0x0b,0x23,0x1b,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x20,0x1a,0x18,0x1e,0x17,0x1e,0x17,0x28,0x26,0x20,0x1b,0x20,0x1b,0x1b,0x17,0x23,0x1b,0x23,0x1b,0x1c,0x14,0x0b,0x39,0x34,0x2f,0x20,0x1b,0x2e,0x20,0x22,0x1a,0x1e,0x17,0x1e,0x17,0x17,0x18,0x17,0x18,0x0c,0x0b, 0x0c,0x0b,0x23,0x1b,0x23,0x1b,0x1a,0x10,0x1c,0x10,0x20,0x1a,0x20,0x1a,0x17,0x14,0x21,0x1a,0x22,0x1b,0x1a,0x1a,0x15,0x1e,0x17,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x23,0x1b,0x19,0x16,0x1b,0x17,0x1a,0x1a,0x1b,0x17,0x1b,0x1b,0x1b,0x15,0x15,0x1b,0x1b,0x18,0x1c,0x13,0x13,0x17,0x19,0x0d,0x1b,0x1b,0x18,0x16,0x15,0x1a,0x1a,0x1a,0x0c, 0x0d,0x0f,0x0d,0x11,0x0b,0x1c,0x28,0x28,0x28,0x1a,0x1a,0x1b,0x1b,0x20,0x21,0x1d,0x10,0x10,0x10,0x10,0x10,0x0f,0x0f,0x15,0x15,0x12,0x0b,0x0c,0x0d,0x0d,0x10,0x10,0x1c,0x1b,0x1a,0x16,0x21,0x16,0x13,0x15,0x18,0x14,0x14,0x11,0x11,0x11,0x15,0x1c,0x16,0x19,0x18,0x1a,0x0b,0x17,0x12,0x1b,0x11,0x11,0x2a,0x2c,0x2d,0x1c,0x16,0x21, 0x24,0x1b,0x1a,0x17,0x17,0x19,0x1b,0x1a,0x1f,0x1a,0x1d,0x25,0x1a,0x20,0x1b,0x1b,0x15,0x17,0x15,0x1b,0x17,0x1c,0x17,0x29,0x28,0x1c,0x17,0x1d,0x19,0x1c,0x15,0x1b,0x16,0x1e,0x1b,0x1a,0x13,0x1a,0x1b,0x15,0x0b,0x23,0x15,0x15,0x28,0x1f,0x1e,0x1b,0x2a,0x21,0x1f,0x17,0x28,0x20,0x21,0x1a,0x2b,0x22,0x19,0x15,0x24,0x23,0x23,0x1b, 0x21,0x1b,0x21,0x1b,0x3c,0x33,0x26,0x1e,0x34,0x29,0x28,0x1f,0x1b,0x14,0x17,0x12,0x13,0x00,0x00,0x2d,0x2c,0x1b,0x17,0x1a,0x1b,0x1a,0x17,0x19,0x15,0x1b,0x17,0x21,0x1b,0x27,0x1f,0x2f,0x26,0x21,0x1a,0x1c,0x15,0x18,0x13,0x28,0x1f,0x20,0x1b,0x26,0x1d,0x26,0x1d,0x0c,0x28,0x22,0x1b,0x17,0x21,0x1b,0x1e,0x1a,0x1e,0x17,0x1e,0x17, 0x28,0x26,0x17,0x18,0x21,0x18,0x21,0x18,0x28,0x22,0x19,0x15,0x18,0x14,0x22,0x1b,0x22,0x1b,0x23,0x1b,0x23,0x1b,0x1c,0x15,0x1a,0x16,0x1a,0x16,0x1a,0x16,0x1e,0x1a,0x24,0x21,0x1a,0x1b,0x27,0x28,0x25,0x21,0x1a,0x16,0x2a,0x25,0x2e,0x27,0x21,0x18,0x1f,0x1c,0x1b,0x1a,0x1a,0x17,0x1b,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x0b,0x0b,0x1b,0x0f,0x0f,0x08,0x0a,0x0a,0x0a,0x0d,0x12,0x0d,0x0b,0x11,0x0a,0x0a,0x0a,0x0f,0x0f,0x0a,0x0a,0x1b,0x1b,0x1b,0x1b,0x0f,0x0d,0x0c,0x0f,0x0e,0x0c,0x0d,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0e,0x0f,0x0f,0x0d,0x07,0x0b,0x0d,0x0a,0x12,0x12,0x12,0x12,0x12,0x0f,0x0f,0x0f,0x13,0x0f,0x0b,0x0c, 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19, 0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x19, 0x12,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x1e,0x0e,0x1d,0x10,0x1b,0x1b,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c,0x0f,0x0f,0x10,0x0d,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x1b,0x16,0x1e,0x26,0x16,0x15,0x19,0x1a,0x13,0x13,0x0b,0x0e,0x17, 0x12,0x20,0x1b,0x1b,0x16,0x1c,0x1c,0x1c,0x2b,0x19,0x1b,0x1b,0x15,0x15,0x15,0x13,0x19,0x1a,0x21,0x1a,0x16,0x21,0x15,0x13,0x13,0x18,0x12,0x16,0x1b,0x15,0x1b,0x1a,0x11,0x16,0x10,0x10,0x13,0x0e,0x0e,0x13,0x14,0x08,0x0a,0x10,0x0d,0x18,0x14,0x14,0x14,0x12,0x10,0x10,0x0d,0x13,0x18,0x0e,0x0e,0x10,0x16,0x10,0x10,0x0e,0x0e,0x0c, 0x0c,0x10,0x08,0x0e,0x17,0x0f,0x10,0x0c,0x10,0x10,0x10,0x09,0x0f,0x0f,0x17,0x0d,0x0f,0x0f,0x0d,0x10,0x13,0x0e,0x08,0x0a,0x0f,0x0d,0x0f,0x0d,0x10,0x13,0x0e,0x1b,0x08,0x10,0x19,0x28,0x1d,0x19,0x19,0x28,0x1e,0x27,0x22,0x18,0x1b,0x17,0x15,0x34,0x15,0x1b,0x29,0x2b,0x2b,0x1d,0x1e,0x1c,0x15,0x16,0x18,0x14,0x15,0x18,0x09,0x00, 0x00,0x00,0x00,0x1b,0x1c,0x1c,0x1c,0x16,0x12,0x1b,0x1b,0x0e,0x28,0x1a,0x1b,0x10,0x0f,0x15,0x10,0x15,0x1b,0x15,0x1b,0x2a,0x1e,0x0f,0x0c,0x1b,0x19,0x1b,0x1b,0x1b,0x0e,0x1b,0x17,0x0b,0x28,0x1a,0x1b,0x10,0x14,0x14,0x16,0x15,0x15,0x17,0x1b,0x1b,0x18,0x14,0x15,0x22,0x0b,0x15,0x0b,0x1a,0x14,0x10,0x0c,0x0c,0x10,0x0c,0x08,0x08, 0x10,0x0f,0x08,0x08,0x08,0x08,0x08,0x08,0x07,0x0a,0x17,0x17,0x0f,0x0f,0x10,0x0f,0x11,0x0b,0x08,0x09,0x0f,0x10,0x0f,0x0f,0x0d,0x0c,0x0c,0x0e,0x0c,0x10,0x00,0x00,0x00,0x00,0x0a,0x0e,0x0e,0x10,0x0c,0x0e,0x19,0x19,0x19,0x19,0x0f,0x00,0x00,0x00,0x00,0x15,0x0e,0x0c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x0c,0x0c,0x0c,0x0c, 0x0c,0x0c,0x0c,0x0c,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x0c,0x0c,0x0c,0x0c,0x19,0x19,0x19,0x19,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x3d,0x19,0x11,0x11,0x11,0x11,0x11,0x11,0x0e,0x0e,0x08,0x11,0x11,0x10,0x11,0x10,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0e,0x0e,0x11,0x10,0x11,0x11,0x10,0x11,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x0e,0x0e,0x24,0x1d,0x21,0x1b,0x22,0x1d,0x2b,0x23,0x19,0x11,0x18,0x1f,0x19,0x26,0x20,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x0f,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x26,0x26,0x2e,0x13,0x0c,0x17,0x1b,0x13,0x17,0x17,0x1b,0x1b,0x17,0x2e,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x1e,0x17,0x17,0x17, 0x0f,0x1b,0x0f,0x23,0x1f,0x17,0x0f,0x26,0x17,0x26,0x0c,0x0f,0x1b,0x1b,0x1e,0x1e,0x1e,0x1b,0x1b,0x1b,0x26,0x0c,0x1b,0x0c,0x17,0x13,0x0c,0x0c,0x17,0x0c,0x23,0x0c,0x2a,0x17,0x2a,0x2a,0x1b,0x1b,0x1b,0x17,0x17,0x13,0x13,0x36,0x36,0x3d,0x3d,0x26,0x26,0x17,0x17,0x08,0x2e,0x23,0x26,0x1f,0x1b,0x1f,0x17,0x17,0x23,0x23,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x0c,0x1e,0x00,0x1e,0x1e,0x1e,0x0f,0x17,0x17,0x2a,0x0f,0x2a,0x0f,0x1b,0x1f,0x1b,0x13,0x2a,0x17,0x2a,0x17,0x23,0x26,0x0f,0x17,0x17,0x13,0x0c,0x17,0x1b,0x17,0x1b,0x17,0x1b,0x1b,0x17,0x1f,0x1e,0x2a,0x0f,0x17,0x13,0x1f,0x17,0x0f,0x17,0x17,0x17,0x2a,0x0f,0x2a,0x0f,0x0c,0x1b,0x12,0x2e,0x17, 0x17,0x1e,0x1e,0x2e,0x17,0x00,0x00,0x00,0x1e,0x00,0x1e,0x1e,0x1e,0x1e,0x23,0x1e,0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x13,0x13,0x17,0x17,0x23,0x26,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1f,0x1b,0x17,0x17,0x17,0x17, 0x17,0x17,0x17,0x17,0x13,0x13,0x13,0x17,0x13,0x13,0x13,0x36,0x26,0x36,0x26,0x36,0x26,0x3d,0x2e,0x3d,0x2e,0x26,0x17,0x1b,0x1b,0x1b,0x2e,0x2e,0x17,0x17,0x2e,0x17,0x17,0x2e,0x17,0x17,0x2e,0x17,0x17,0x23,0x23,0x32,0x2e,0x2a,0x17,0x26,0x17,0x26,0x17,0x26,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x1f,0x0f,0x1f, 0x0f,0x1f,0x0f,0x1f,0x0f,0x1f,0x0f,0x1f,0x1f,0x0f,0x1f,0x0f,0x19,0x1f,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x26,0x2a,0x23,0x26,0x0f,0x17,0x23,0x26,0x23,0x26,0x00,0x00,0x00,0x00,0x00,0x34,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x13,0x00,0x00,0x1c,0x00,0x00,0x00,0x36,0x26,0x3d,0x2e,0x17,0x1b,0x1b,0x1b,0x13,0x1b, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x2a,0x2a,0x11,0x1b,0x1b,0x1b,0x38,0x26,0x18,0x46,0x32,0x0f,0x1b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x17,0x13,0x13,0x23,0x1f,0x1f,0x17,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x3a,0x45,0x00,0x00,0x00,0x00,0x00,0x1b,0x17,0x00,0x00, 0x00,0x00,0x00,0x00,0x2a,0x13,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b,0x1b,0x1b,0x1f,0x1b,0x17,0x17,0x13,0x36,0x26,0x17,0x1b,0x1b,0x1b,0x17,0x1b,0x1b,0x1b,0x17,0x1b,0x1b,0x1b,0x2e,0x17,0x17,0x2e,0x17,0x17,0x2a,0x17,0x17,0x2a,0x17,0x17,0x2a,0x17,0x17,0x1b,0x1b,0x1b,0x1b,0x1f,0x0f,0x1f,0x0f, 0x1f,0x0f,0x1f,0x1f,0x0f,0x0f,0x13,0x13,0x36,0x26,0x1e,0x1b,0x1b,0x00,0x17,0x17,0x17,0x11,0x1a,0x20,0x1d,0x17,0x18,0x10,0x0b,0x23,0x1b,0x1c,0x10,0x19,0x16,0x16,0x15,0x16,0x0b,0x18,0x13,0x1c,0x16,0x1b,0x15,0x19,0x14,0x1f,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x15,0x16,0x16,0x0d,0x18,0x1a,0x1c,0x17,0x10, 0x22,0x1b,0x1d,0x19,0x1d,0x17,0x1a,0x18,0x12,0x20,0x11,0x13,0x13,0x16,0x1c,0x1c,0x17,0x2e,0x17,0x2e,0x0f,0x0c,0x08,0x19,0x0a,0x06,0x00,0x06,0x0a,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x17,0x17,0x2b,0x14,0x23,0x1b,0x2b,0x21,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0x2a,0x28,0x16, 0x28,0x16,0x28,0x1e,0x1f,0x20,0x20,0x23,0x28,0x2e,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x1f,0x1f,0x1f,0x1f,0x22,0x1b,0x31,0x26,0x16,0x16,0x0d,0x0d,0x0d,0x11,0x0a,0x1a,0x0b,0x0b,0x26,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x09,0x00,0x00,0x0a,0x00,0x00,0x1d,0x1a,0x14,0x16,0x1f,0x0c, 0x10,0x1f,0x1f,0x0c,0x1a,0x19,0x19,0x20,0x1f,0x0c,0x12,0x1f,0x1c,0x1c,0x1d,0x1a,0x1b,0x1f,0x1a,0x24,0x21,0x18,0x18,0x18,0x0b,0x11,0x1a,0x1a,0x19,0x19,0x19,0x1c,0x1d,0x16,0x1f,0x19,0x19,0x20,0x1a,0x21,0x19,0x24,0x24,0x24,0x24,0x1d,0x1d,0x1d,0x1a,0x14,0x16,0x1f,0x0e,0x10,0x1f,0x0e,0x1a,0x19,0x19,0x1f,0x12,0x1f,0x1c,0x1d, 0x1b,0x1f,0x1a,0x24,0x21,0x0c,0x1a,0x19,0x1d,0x1e,0x37,0x00,0x1d,0x19,0x1e,0x1e,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x0c,0x00,0x23,0x1e,0x1f,0x20,0x19,0x1f,0x22,0x23,0x16,0x1d,0x22,0x22, 0x1e,0x23,0x25,0x24,0x1f,0x19,0x1a,0x23,0x20,0x1a,0x20,0x1f,0x1e,0x1f,0x20,0x22,0x1b,0x1d,0x1f,0x1e,0x24,0x1d,0x1c,0x1e,0x1f,0x26,0x17,0x1b,0x1b,0x28,0x19,0x19,0x23,0x29,0x1c,0x19,0x30,0x1a,0x1a,0x23,0x19,0x19,0x23,0x1a,0x23,0x25,0x28,0x19,0x24,0x19,0x1e,0x19,0x1c,0x1a,0x1d,0x19,0x1c,0x23,0x19,0x1d,0x1f,0x19,0x19,0x1b, 0x2c,0x19,0x19,0x1b,0x1b,0x14,0x0f,0x1a,0x1a,0x1a,0x19,0x1a,0x29,0x1a,0x29,0x17,0x1a,0x29,0x1f,0x1a,0x29,0x22,0x22,0x29,0x1b,0x1a,0x29,0x29,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x29,0x29,0x1b,0x1a,0x1a,0x29,0x1b,0x19,0x1a,0x1a,0x29,0x24,0x20,0x20,0x20,0x20,0x21,0x1d,0x20,0x24,0x20,0x1e,0x19,0x24,0x1f,0x20,0x1a,0x1f,0x20,0x22, 0x21,0x1b,0x20,0x1f,0x21,0x1f,0x24,0x20,0x21,0x21,0x1f,0x1d,0x20,0x1f,0x21,0x24,0x1e,0x23,0x21,0x05,0x05,0x07,0x09,0x07,0x0c,0x10,0x28,0x1a,0x1c,0x1b,0x1a,0x1c,0x1a,0x1a,0x1e,0x1c,0x1a,0x0e,0x26,0x1b,0x1a,0x1a,0x19,0x1c,0x18,0x1b,0x0c,0x1b,0x18,0x1a,0x13,0x28,0x19,0x1a,0x1a,0x1b,0x26,0x1a,0x1b,0x12,0x26,0x1b,0x1b,0x20, 0x1f,0x0a,0x0d,0x34,0x34,0x34,0x34,0x42,0x19,0x19,0x0b,0x19,0x12,0x19,0x19,0x1a,0x19,0x19,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x12,0x19,0x19,0x1a,0x19,0x19,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x17,0x17, 0x1b,0x14,0x13,0x1a,0x1c,0x0c,0x0e,0x17,0x13,0x23,0x1e,0x1c,0x16,0x1c,0x17,0x13,0x14,0x1b,0x17,0x25,0x17,0x15,0x16,0x20,0x24,0x13,0x1d,0x16,0x1b,0x18,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x14,0x14,0x14,0x14,0x0c,0x0c,0x0c,0x0c,0x1e,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x15,0x17,0x17,0x17,0x17,0x17,0x1a,0x1b,0x1b, 0x14,0x14,0x14,0x14,0x14,0x1a,0x1a,0x17,0x1c,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1a,0x0e,0x17,0x13,0x13,0x13,0x13,0x1e,0x1e,0x1e,0x1e,0x1c,0x1c,0x1c,0x17,0x17,0x17,0x13,0x13,0x13,0x13,0x14,0x14,0x14,0x14,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x25,0x25,0x25,0x25,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x20,0x1d,0x17,0x17,0x12,0x19,0x14, 0x16,0x1c,0x1c,0x0c,0x17,0x17,0x23,0x1e,0x15,0x1c,0x1c,0x16,0x15,0x14,0x15,0x1d,0x17,0x1e,0x1d,0x17,0x14,0x1c,0x0c,0x1c,0x15,0x1d,0x0c,0x15,0x14,0x1a,0x12,0x18,0x13,0x0c,0x0c,0x0e,0x25,0x26,0x1c,0x17,0x17,0x1c,0x17,0x16,0x17,0x12,0x1b,0x14,0x22,0x14,0x1e,0x1e,0x17,0x1a,0x23,0x1c,0x1c,0x1c,0x16,0x17,0x14,0x17,0x1d,0x17, 0x1d,0x19,0x25,0x26,0x1a,0x20,0x17,0x18,0x28,0x16,0x12,0x1b,0x1b,0x1d,0x29,0x29,0x1e,0x17,0x1a,0x13,0x1a,0x1a,0x1a,0x20,0x18,0x18,0x20,0x1b,0x1b,0x10,0x1c,0x1c,0x1a,0x16,0x16,0x29,0x22,0x16,0x18,0x1c,0x1c,0x1d,0x1d,0x21,0x20,0x10,0x2b,0x1b,0x19,0x1a,0x1e,0x1e,0x17,0x17,0x0c,0x23,0x20,0x20,0x16,0x20,0x0a,0x0a,0x14,0x14, 0x0a,0x0a,0x1c,0x12,0x0c,0x23,0x20,0x0d,0x0a,0x0a,0x15,0x11,0x11,0x0b,0x0b,0x0b,0x11,0x1f,0x16,0x0e,0x1c,0x20,0x1b,0x1b,0x17,0x22,0x1a,0x1c,0x10,0x14,0x18,0x14,0x0a,0x0b,0x12,0x18,0x10,0x1f,0x1f,0x1f,0x2a,0x23,0x2a,0x0c,0x00,0x00,0x00,0x00,0x00,0x0c,0x23,0x26,0x0f,0x0f,0x17,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b, 0x1b,0x17,0x17,0x36,0x26,0x36,0x26,0x3d,0x2e,0x3d,0x2e,0x26,0x26,0x26,0x26,0x26,0x26,0x2a,0x2a,0x17,0x17,0x2a,0x2a,0x17,0x17,0x23,0x26,0x0f,0x0f,0x23,0x26,0x0f,0x0f,0x23,0x26,0x0f,0x0f,0x2e,0x23,0x26,0x17,0x1b,0x1b,0x1f,0x0f,0x1f,0x23,0x17,0x17,0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c, 0x2a,0x0f,0x23,0x17,0x17,0x0c,0x17,0x17,0x17,0x17,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x36,0x26,0x36,0x26,0x36,0x26,0x3d,0x2e,0x3d,0x2e,0x26,0x26,0x26,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x23,0x17,0x17, 0x23,0x17,0x17,0x2a,0x17,0x32,0x2e,0x2a,0x17,0x26,0x17,0x26,0x17,0x26,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x2a,0x17,0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x1f,0x1f,0x0f,0x0f,0x1f,0x0f,0x1f,0x0f,0x1f,0x17,0x1b,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x0f,0x0f,0x17,0x0f,0x0f,0x0f,0x0f,0x00,0x36,0x26, 0x3d,0x2e,0x2a,0x17,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b,0x17,0x17,0x13,0x36,0x26,0x2e,0x2e,0x2a,0x2a,0x2a,0x1b,0x1b,0x1b,0x1b,0x1f,0x0f,0x1f,0x0f,0x1f,0x0f,0x36,0x26,0x1b,0x1f,0x1b,0x1b,0x1b,0x1f,0x1b,0x1b,0x36,0x36,0x26,0x26,0x13,0x13,0x1b,0x1b,0x1b,0x1b,0x0f,0x0f,0x0f,0x0f,0x23,0x26, 0x0f,0x0f,0x23,0x26,0x0f,0x0f,0x23,0x26,0x0f,0x0f,0x1b,0x1b,0x1b,0x1b,0x2a,0x0f,0x2a,0x0f,0x1b,0x1f,0x1b,0x1b,0x36,0x36,0x26,0x26,0x36,0x36,0x26,0x26,0x26,0x26,0x17,0x17,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x0f,0x0c,0x00,0x00,0x00,0x26,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x13,0x13,0x23,0x23, 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, 0x23,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1b,0x26,0x1b,0x26,0x1b,0x26,0x1b,0x26,0x1f,0x1f,0x1f,0x0c,0x0c,0x17,0x13,0x1b,0x1d,0x1a,0x19,0x1a,0x1b,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x15,0x19,0x18,0x1b,0x1c,0x1c,0x1e,0x1b,0x1a,0x1e,0x18,0x1f,0x23,0x1d,0x22,0x26,0x1d,0x23,0x20,0x1a,0x1a,0x1a,0x1a, 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x15,0x19,0x1c,0x1c,0x1e,0x1a,0x1e,0x1a,0x1b,0x1c,0x17,0x17,0x23,0x1f,0x20,0x1f,0x1f,0x1b,0x1b,0x1b,0x22,0x23,0x23,0x23,0x2a,0x2a,0x20,0x2a,0x2a,0x22,0x28,0x27,0x1a,0x23,0x27,0x23,0x1b,0x27,0x22,0x20,0x20,0x1c,0x1e,0x22,0x25,0x20,0x1c,0x21,0x1b,0x19,0x2a,0x2a,0x2a,0x26,0x2a,0x2a,0x1f, 0x2a,0x2a,0x21,0x23,0x24,0x22,0x21,0x21,0x1e,0x29,0x23,0x26,0x21,0x21,0x1b,0x22,0x20,0x20,0x27,0x23,0x21,0x29,0x19,0x17,0x1a,0x19,0x1c,0x1d,0x20,0x22,0x1b,0x1a,0x1a,0x19,0x1a,0x19,0x19,0x1a,0x1a,0x1b,0x1a,0x1a,0x1a,0x17,0x18,0x1b,0x1d,0x1c,0x1c,0x15,0x1a,0x1a,0x1b,0x1c,0x23,0x27,0x1e,0x1e,0x1d,0x23,0x1d,0x1f,0x18,0x16, 0x1b,0x1a,0x16,0x17,0x19,0x19,0x16,0x15,0x1d,0x15,0x19,0x17,0x19,0x24,0x1a,0x26,0x19,0x1a,0x1a,0x22,0x0e,0x24,0x20,0x21,0x1e,0x1a,0x23,0x1c,0x24,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x1c,0x1c,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x14,0x15,0x15,0x15,0x15,0x15,0x0e,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1d,0x0c, 0x0c,0x0c,0x0e,0x0e,0x0c,0x0c,0x0c,0x0e,0x0c,0x0c,0x0c,0x2a,0x2a,0x2a,0x2a,0x16,0x22,0x21,0x16,0x13,0x16,0x18,0x1a,0x16,0x27,0x26,0x28,0x14,0x2e,0x16,0x26,0x26,0x27,0x25,0x1a,0x16,0x16,0x24,0x1b,0x24,0x1f,0x19,0x15,0x13,0x2f,0x13,0x19,0x16,0x16,0x16,0x16,0x16,0x3f,0x26,0x26,0x14,0x0c,0x15,0x0b,0x15,0x0b,0x0b,0x0b,0x16, 0x1b,0x1b,0x19,0x11,0x11,0x0b,0x0b,0x0b,0x11,0x0b,0x13,0x28,0x0a,0x2a,0x2a,0x2a,0x1b,0x1b,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x36,0x36,0x1f,0x36,0x36,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x1b,0x16,0x1b,0x16,0x18,0x14,0x10,0x10,0x20,0x19,0x21,0x14,0x34,0x29,0x1b,0x19,0x2a,0x24,0x27,0x22,0x2f,0x25,0x2b,0x24,0x1e,0x16,0x21,0x1b,0x2b,0x22,0x23,0x1c,0x22,0x1c,0x28,0x1f,0x28,0x1f,0x33,0x27,0x23,0x1b,0x23,0x1b,0x38,0x29,0x24,0x00,0x2d,0x2d,0x2d,0x16,0x00,0x00,0x1b,0x17,0x20,0x1a,0x18,0x14,0x32,0x2a, 0x2b,0x28,0x21,0x1b,0x20,0x1b,0x18,0x13,0x22,0x1b,0x18,0x13,0x26,0x1f,0x1e,0x1a,0x2d,0x26,0x19,0x1a,0x22,0x22,0x25,0x15,0x09,0x15,0x1f,0x14,0x2e,0x2e,0x0b,0x00,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x12,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x22,0x22,0x22,0x22, 0x22,0x22,0x22,0x22,0x22,0x22,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x29,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, 0x1a,0x1a,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x16,0x1f,0x21,0x0d,0x0a,0x0d,0x0a,0x21,0x1a,0x22,0x1d,0x19,0x16,0x19, 0x16,0x1b,0x1a,0x13,0x13,0x34,0x26,0x35,0x29,0x2d,0x27,0x29,0x1e,0x29,0x1e,0x29,0x1e,0x1c,0x15,0x1b,0x17,0x1b,0x17,0x1b,0x17,0x19,0x0e,0x16,0x0b,0x23,0x1b,0x28,0x1f,0x3d,0x2e,0x1a,0x1b,0x20,0x20,0x25,0x28,0x23,0x1b,0x2d,0x24,0x19,0x12,0x1a,0x17,0x1d,0x16,0x2b,0x21,0x1c,0x18,0x1a,0x1b,0x1a,0x1b,0x16,0x12,0x16,0x12,0x16, 0x11,0x18,0x18,0x0e,0x1f,0x0f,0x2c,0x1e,0x10,0x1b,0x1c,0x15,0x23,0x1a,0x11,0x10,0x1b,0x1b,0x1b,0x16,0x0b,0x23,0x1c,0x11,0x10,0x1d,0x15,0x21,0x12,0x24,0x1c,0x1c,0x15,0x20,0x1b,0x1b,0x17,0x22,0x1a,0x1c,0x10,0x18,0x14,0x23,0x14,0x18,0x28,0x16,0x1a,0x29,0x0c,0x35,0x29,0x29,0x36,0x29,0x2a,0x2a,0x28,0x29,0x2a,0x18,0x16,0x1c, 0x20,0x29,0x20,0x2b,0x0b,0x15,0x1b,0x28,0x2f,0x20,0x2f,0x1c,0x1c,0x25,0x20,0x34,0x2a,0x18,0x2a,0x0f,0x2a,0x0f,0x1b,0x1b,0x1b,0x1b,0x26,0x26,0x26,0x26,0x2e,0x17,0x17,0x2e,0x23,0x17,0x17,0x23,0x1f,0x0f,0x0f,0x1f,0x1b,0x1b,0x1b,0x1b,0x23,0x0f,0x0f,0x26,0x23,0x0f,0x0f,0x26,0x13,0x13,0x17,0x17,0x18,0x18,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x18,0x12,0x1a,0x18,0x22,0x1b,0x1b,0x28,0x1f,0x22,0x23,0x26,0x26,0x1b,0x17,0x2e,0x25,0x30,0x27,0x20,0x1b,0x0e,0x0e,0x1b,0x1e,0x13,0x1c,0x18,0x1b,0x16,0x22,0x25,0x12,0x1b,0x14,0x0a,0x11,0x18,0x19,0x0a, 0x0a,0x08,0x0a,0x11,0x11,0x11,0x15,0x44,0x5c,0x10,0x13,0x06,0x0c,0x12,0x14,0x0f,0x17,0x18,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x3d,0x19,0x23,0x2a,0x29,0x1e,0x15,0x1a,0x21,0x22,0x16,0x0e,0x1e,0x18,0x1f,0x1a,0x1e,0x19,0x19,0x22,0x1b,0x1b,0x18,0x22,0x1c,0x26,0x15,0x18,0x1d,0x0e,0x1b, 0x10,0x10,0x0b,0x28,0x1b,0x1a,0x18,0x18,0x1b,0x2b,0x2b,0x2b,0x2e,0x2e,0x19,0x17,0x0d,0x17,0x15,0x1c,0x15,0x1f,0x0b,0x1a,0x1c,0x28,0x28,0x1c,0x19,0x1b,0x19,0x18,0x15,0x18,0x15,0x16,0x0e,0x10,0x0b,0x0a,0x11,0x1b,0x1d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0f,0x0f,0x00,0x0d,0x0d,0x0d,0x0c, 0x0c,0x4d,0x2e,0x28,0x30,0x0d,0x0d,0x0f,0x12,0x0c,0x0c,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x00,0x2a,0x0f,0x0f,0x2a,0x0c,0x17,0x17,0x3d,0x2e,0x2e,0x3d,0x2a,0x17,0x17,0x2a,0x17,0x17,0x13,0x13,0x00,0x00,0x10,0x22,0x1c,0x21,0x1b,0x3a,0x30,0x20,0x19,0x20,0x19,0x3d,0x2e,0x23,0x1b,0x12,0x0f,0x1c,0x00,0x1f,0x19, 0x0f,0x0e,0x07,0x17,0x0f,0x10,0x0c,0x09,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0a,0x18,0x14,0x1b,0x1a,0x19,0x2c,0x25,0x25,0x24,0x26,0x2b,0x1d,0x20,0x1c,0x12,0x2b,0x34,0x14,0x35,0x17,0x26,0x2a,0x2a,0x2a,0x13,0x23,0x2e,0x23,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x1b, 0x1b,0x1b,0x26,0x17,0x17,0x2a,0x0f,0x0f,0x2a,0x0f,0x0f,0x2a,0x17,0x17,0x00,0x13,0x26,0x0f,0x0f,0x2e,0x17,0x17,0x23,0x17,0x17,0x1f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x45,0x45,0x28,0x00,0x00,0x28,0x28,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, 0x1f,0x1c,0x1e,0x1e,0x29,0x1e,0x1d,0x25,0x2d,0x1e,0x1d,0x31,0x1d,0x1d,0x2b,0x1d,0x1f,0x24,0x1d,0x23,0x27,0x2a,0x1d,0x23,0x1e,0x20,0x1d,0x20,0x1d,0x1e,0x20,0x1d,0x24,0x1c,0x1f,0x24,0x1c,0x1d,0x1a,0x24,0x1e,0x1e,0x1e,0x20,0x15,0x18,0x1e,0x24,0x24,0x19,0x00,0x00,0x32,0x64,0x20,0x00,0x05,0x0e,0x0e,0x14,0x1e,0x1b,0x29,0x28, 0x0c,0x0f,0x0f,0x15,0x22,0x0b,0x14,0x0b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x0b,0x0b,0x22,0x22,0x22,0x16,0x30,0x20,0x1d,0x1f,0x23,0x19,0x18,0x22,0x24,0x0d,0x12,0x1d,0x18,0x2d,0x25,0x26,0x1c,0x26,0x1e,0x1b,0x1a,0x22,0x1f,0x2f,0x1e,0x1c,0x1d,0x0f,0x13,0x0f,0x22,0x15,0x0d,0x19,0x1d,0x17,0x1d,0x1a,0x10, 0x1d,0x1c,0x0c,0x0c,0x19,0x0c,0x2b,0x1c,0x1d,0x1d,0x1d,0x11,0x15,0x11,0x1c,0x18,0x24,0x17,0x18,0x17,0x0f,0x0c,0x0f,0x22,0x20,0x20,0x1f,0x19,0x25,0x26,0x22,0x19,0x19,0x19,0x19,0x19,0x19,0x17,0x1a,0x1a,0x1a,0x1a,0x0c,0x0c,0x0c,0x0c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x13,0x13,0x1b,0x1b,0x16,0x14,0x17,0x1b, 0x14,0x2d,0x2d,0x27,0x0e,0x15,0x22,0x2b,0x26,0x29,0x22,0x22,0x22,0x1b,0x1d,0x1b,0x1f,0x26,0x1b,0x14,0x16,0x26,0x2a,0x1d,0x16,0x0e,0x0e,0x22,0x21,0x1b,0x22,0x20,0x19,0x19,0x25,0x20,0x20,0x26,0x2f,0x2e,0x19,0x32,0x13,0x13,0x0b,0x0b,0x22,0x1d,0x18,0x1c,0x09,0x1b,0x10,0x10,0x1c,0x1c,0x13,0x0b,0x0b,0x13,0x3d,0x20,0x19,0x20, 0x19,0x19,0x0d,0x0d,0x0d,0x0d,0x26,0x26,0x26,0x22,0x22,0x22,0x0c,0x13,0x11,0x10,0x0f,0x0a,0x0e,0x0a,0x10,0x09,0x13,0x18,0x0e,0x1b,0x15,0x1d,0x17,0x0c,0x23,0x1c,0x1c,0x18,0x1c,0x1d,0x22,0x22,0x12,0x12,0x12,0x2f,0x2d,0x30,0x18,0x22,0x1d,0x0d,0x1b,0x15,0x1f,0x17,0x1f,0x17,0x1d,0x15,0x0b,0x20,0x19,0x20,0x19,0x23,0x22,0x23, 0x19,0x1a,0x19,0x1a,0x18,0x0c,0x18,0x0f,0x18,0x10,0x25,0x1c,0x25,0x1c,0x26,0x1d,0x1e,0x11,0x1e,0x11,0x1b,0x15,0x1a,0x11,0x1a,0x16,0x22,0x1c,0x22,0x1c,0x1d,0x17,0x1d,0x17,0x18,0x26,0x26,0x1f,0x1d,0x16,0x1d,0x18,0x23,0x15,0x18,0x14,0x38,0x1f,0x19,0x1e,0x0b,0x13,0x28,0x10,0x1e,0x12,0x12,0x1e,0x12,0x20,0x19,0x1f,0x17,0x1f, 0x17,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x22,0x1d,0x22,0x1d,0x22,0x1d,0x24,0x1c,0x24,0x1c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x0d,0x0c,0x12,0x0c,0x1d,0x19,0x19,0x18,0x0c,0x25,0x1c,0x25,0x1c,0x26,0x1d,0x26,0x1d,0x1e,0x11,0x1b,0x15,0x1a,0x11,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x2f,0x24,0x1c,0x18,0x0c,0x20,0x19,0x2b,0x2a,0x26, 0x1d,0x0b,0x2f,0x24,0x2f,0x24,0x2f,0x24,0x1c,0x18,0x0b,0x15,0x1b,0x1e,0x2e,0x2e,0x2e,0x2d,0x13,0x13,0x0b,0x0e,0x0e,0x20,0x1d,0x27,0x13,0x28,0x21,0x29,0x0d,0x20,0x1d,0x19,0x1d,0x24,0x0d,0x1d,0x1f,0x2d,0x25,0x19,0x26,0x24,0x1c,0x1a,0x1a,0x1c,0x1e,0x27,0x26,0x0d,0x1c,0x1f,0x16,0x1d,0x0d,0x1c,0x1b,0x1a,0x16,0x1d,0x1d,0x0d, 0x1a,0x19,0x1d,0x1a,0x16,0x1d,0x1d,0x17,0x1c,0x1b,0x26,0x28,0x0d,0x1c,0x1d,0x1c,0x28,0x19,0x23,0x18,0x1f,0x1b,0x0d,0x31,0x31,0x24,0x1d,0x1c,0x23,0x20,0x1d,0x1d,0x18,0x23,0x19,0x2b,0x1b,0x25,0x25,0x1d,0x22,0x2d,0x24,0x26,0x24,0x1c,0x1f,0x1a,0x1c,0x24,0x1e,0x25,0x21,0x2f,0x31,0x23,0x27,0x1d,0x1f,0x33,0x1e,0x19,0x1d,0x1a, 0x13,0x1b,0x1a,0x25,0x16,0x1d,0x1d,0x19,0x1a,0x23,0x1d,0x1d,0x1d,0x1d,0x17,0x15,0x18,0x22,0x17,0x1e,0x1c,0x28,0x29,0x1e,0x23,0x19,0x17,0x29,0x19,0x1a,0x1d,0x13,0x17,0x15,0x0c,0x28,0x28,0x1c,0x19,0x18,0x1d,0x17,0x14,0x32,0x38,0x1f,0x12,0x12,0x12,0x12,0x0c,0x1b,0x15,0x1c,0x26,0x1e,0x23,0x1d,0x0f,0x11,0x0d,0x0d,0x18,0x18, 0x18,0x18,0x0f,0x0f,0x0f,0x18,0x0f,0x18,0x0f,0x0f,0x0f,0x18,0x18,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x20,0x19,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x0d,0x0c,0x0d,0x0c,0x26,0x1d,0x26,0x1d,0x26,0x1d,0x26, 0x1d,0x26,0x1d,0x26,0x1d,0x26,0x1d,0x26,0x1e,0x26,0x1e,0x26,0x1e,0x26,0x1e,0x26,0x1e,0x22,0x1c,0x22,0x1c,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x1c,0x18,0x1c,0x18,0x1c,0x18,0x1a,0x11,0x19,0x1a,0x25,0x1d,0x0d,0x12,0x0c,0x0c,0x1a,0x15,0x2e,0x27,0x1f,0x1b,0x1d,0x19,0x25,0x1e,0x1c,0x18,0x1c,0x18,0x1f,0x19,0x21, 0x1c,0x21,0x1c,0x24,0x1a,0x26,0x1d,0x0f,0x0f,0x0f,0x0f,0x15,0x15,0x18,0x18,0x18,0x18,0x0d,0x0d,0x0f,0x0f,0x0f,0x0f,0x19,0x1a,0x20,0x19,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1f,0x17,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x23,0x1d,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x19,0x1a,0x18,0x10,0x22,0x1d,0x24,0x1c,0x24,0x1c,0x24, 0x1c,0x24,0x1c,0x24,0x1c,0x0d,0x0c,0x0d,0x0c,0x1d,0x19,0x1d,0x19,0x1d,0x19,0x18,0x0c,0x18,0x0c,0x18,0x0c,0x18,0x0c,0x2d,0x2b,0x2d,0x2b,0x2d,0x2b,0x25,0x1c,0x25,0x1c,0x25,0x1c,0x25,0x1c,0x26,0x1d,0x26,0x1d,0x26,0x1d,0x26,0x1d,0x1c,0x1d,0x1c,0x1d,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1e,0x11,0x1b,0x15,0x1b,0x15,0x1b,0x15,0x1b, 0x15,0x1b,0x15,0x1a,0x11,0x1a,0x11,0x1a,0x11,0x1a,0x11,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x1f,0x18,0x1f,0x18,0x2f,0x24,0x2f,0x24,0x1e,0x17,0x1e,0x17,0x1c,0x18,0x1d,0x17,0x1d,0x17,0x1d,0x17,0x1c,0x11,0x24,0x18,0x19,0x0c,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x20,0x20,0x25,0x25,0x25,0x25,0x25,0x25,0x16, 0x16,0x16,0x16,0x16,0x16,0x1d,0x1d,0x24,0x24,0x24,0x24,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x27,0x27,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x13,0x13,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x28,0x28,0x30,0x30,0x30,0x30,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x21, 0x29,0x29,0x29,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x29,0x29,0x30,0x30,0x30,0x30,0x30,0x30,0x1f,0x1f,0x16,0x16,0x1d,0x1d,0x0d,0x0d,0x1d,0x1d,0x1c,0x1c,0x28,0x28,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x20,0x20,0x25,0x25,0x25,0x25,0x25,0x25,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x27,0x27,0x2e,0x2e,0x2e,0x2e,0x2e, 0x2e,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x29,0x29,0x30,0x30,0x30,0x30,0x30,0x30,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x20,0x20,0x20,0x20,0x20,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x27,0x27,0x24,0x1d,0x1d,0x1d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x12,0x13,0x1d,0x1d,0x1d,0x1c,0x1c,0x1c,0x1c, 0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x21,0x21,0x1f,0x1d,0x1d,0x1d,0x28,0x28,0x28,0x28,0x28,0x29,0x29,0x2a,0x29,0x26,0x1d,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x1f,0x1d,0x1d,0x1d,0x1d,0x1f,0x1f,0x17,0x23,0x25,0x1d,0x1d,0x1e,0x19,0x1b,0x18,0x23,0x1f,0x2c,0x0e,0x0e,0x1d,0x19,0x0c,0x19, 0x2d,0x25,0x1d,0x26,0x30,0x28,0x1e,0x1d,0x1d,0x1b,0x15,0x1a,0x0f,0x11,0x1a,0x11,0x1a,0x26,0x24,0x1c,0x1a,0x1d,0x17,0x1f,0x1f,0x16,0x14,0x1b,0x1b,0x13,0x14,0x1b,0x0c,0x13,0x17,0x0e,0x3e,0x39,0x33,0x2b,0x24,0x19,0x36,0x30,0x28,0x20,0x19,0x0d,0x0c,0x26,0x1d,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x22,0x1c,0x1a,0x20,0x19, 0x20,0x19,0x2b,0x29,0x22,0x1d,0x22,0x1d,0x1d,0x19,0x26,0x1d,0x26,0x1d,0x1f,0x16,0x0c,0x3e,0x39,0x33,0x22,0x1d,0x32,0x22,0x25,0x1c,0x20,0x19,0x20,0x19,0x19,0x1a,0x19,0x1a,0x0d,0x0c,0x0d,0x0c,0x26,0x1d,0x26,0x1d,0x1d,0x11,0x1e,0x11,0x22,0x1c,0x22,0x1c,0x19,0x15,0x24,0x1c,0x25,0x1e,0x1c,0x1d,0x17,0x20,0x19,0x26,0x1d,0x26, 0x1d,0x26,0x1d,0x26,0x1d,0x1c,0x18,0x1d,0x19,0x1c,0x1c,0x1d,0x19,0x1d,0x1d,0x1d,0x17,0x17,0x1d,0x1d,0x1a,0x1f,0x15,0x15,0x19,0x1c,0x0e,0x1d,0x1d,0x1a,0x18,0x17,0x1c,0x1c,0x1c,0x0d,0x0e,0x10,0x0e,0x13,0x0c,0x1e,0x2b,0x2b,0x2b,0x1c,0x1c,0x1d,0x1d,0x23,0x24,0x20,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x17,0x14,0x0c,0x0d, 0x0e,0x0e,0x11,0x11,0x1e,0x1e,0x1c,0x18,0x24,0x18,0x15,0x17,0x1a,0x16,0x16,0x12,0x12,0x12,0x17,0x1f,0x18,0x1b,0x1a,0x1c,0x0c,0x19,0x13,0x1d,0x12,0x12,0x2e,0x2f,0x31,0x1f,0x18,0x24,0x28,0x1d,0x1c,0x19,0x19,0x1b,0x1e,0x1c,0x22,0x1c,0x20,0x28,0x1d,0x23,0x1d,0x1d,0x17,0x19,0x17,0x1e,0x19,0x1f,0x19,0x2d,0x2b,0x1e,0x19,0x20, 0x1b,0x1f,0x17,0x1e,0x18,0x21,0x1d,0x1c,0x14,0x1d,0x1d,0x17,0x0c,0x26,0x17,0x17,0x2b,0x22,0x20,0x1d,0x2d,0x24,0x21,0x19,0x2c,0x23,0x24,0x1c,0x2e,0x25,0x1b,0x16,0x27,0x26,0x26,0x1d,0x24,0x1d,0x24,0x1d,0x42,0x38,0x29,0x21,0x38,0x2d,0x2b,0x22,0x1d,0x16,0x19,0x14,0x15,0x00,0x00,0x31,0x2f,0x1d,0x19,0x1c,0x1d,0x1c,0x19,0x1b, 0x17,0x1d,0x19,0x24,0x1d,0x2a,0x21,0x33,0x2a,0x24,0x1c,0x1f,0x17,0x1a,0x15,0x2c,0x22,0x22,0x1d,0x2a,0x20,0x2a,0x20,0x0d,0x2b,0x25,0x1d,0x19,0x24,0x1d,0x21,0x1c,0x20,0x19,0x20,0x19,0x2b,0x2a,0x19,0x1a,0x24,0x1a,0x24,0x1a,0x2b,0x25,0x1b,0x16,0x1a,0x16,0x25,0x1d,0x25,0x1d,0x26,0x1d,0x26,0x1d,0x1f,0x17,0x1c,0x18,0x1c,0x18, 0x1c,0x18,0x21,0x1c,0x27,0x23,0x1c,0x1d,0x2b,0x2b,0x28,0x24,0x1c,0x18,0x2d,0x28,0x31,0x2a,0x24,0x1b,0x22,0x1e,0x1d,0x1c,0x1c,0x19,0x1d,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x0b,0x1d,0x11,0x11,0x08,0x0b,0x0b,0x0b,0x0e,0x14,0x0e,0x0b,0x13,0x0b,0x0b,0x0b,0x11,0x11,0x0b,0x0b,0x1d,0x1d, 0x1d,0x1d,0x11,0x0e,0x0d,0x11,0x10,0x0d,0x0e,0x0e,0x0e,0x11,0x11,0x11,0x11,0x11,0x10,0x11,0x11,0x0f,0x08,0x0c,0x0e,0x0b,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x11,0x15,0x11,0x0c,0x0d,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13, 0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b, 0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00,0x00,0x20,0x0f,0x20,0x11,0x1e,0x1e,0x11,0x11,0x11,0x11,0x11,0x0d, 0x10,0x10,0x11,0x0e,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x1d,0x17,0x21,0x29,0x18,0x17,0x1b,0x1c,0x15,0x15,0x0c,0x0f,0x19,0x14,0x23,0x1d,0x1d,0x18,0x1f,0x1f,0x1f,0x2e,0x1b,0x1e,0x1e,0x17,0x17,0x17,0x15,0x1b,0x1c,0x24,0x1c,0x18,0x24,0x17,0x15,0x15,0x1a,0x13,0x17, 0x1d,0x17,0x1e,0x1c,0x12,0x18,0x11,0x12,0x14,0x0f,0x0f,0x14,0x15,0x09,0x0b,0x12,0x0e,0x1a,0x16,0x16,0x15,0x13,0x11,0x11,0x0f,0x15,0x1a,0x10,0x10,0x11,0x18,0x11,0x11,0x10,0x10,0x0d,0x0d,0x11,0x08,0x0f,0x19,0x11,0x11,0x0e,0x11,0x11,0x11,0x0a,0x11,0x10,0x19,0x0e,0x10,0x11,0x0f,0x11,0x14,0x0f,0x08,0x0b,0x11,0x0e,0x11,0x0f, 0x11,0x14,0x0f,0x1d,0x08,0x11,0x1b,0x2c,0x1f,0x1b,0x1b,0x2b,0x20,0x2b,0x25,0x1a,0x1d,0x19,0x16,0x38,0x17,0x1d,0x2d,0x2f,0x2f,0x1f,0x20,0x1f,0x17,0x18,0x1a,0x15,0x17,0x1a,0x0a,0x00,0x00,0x00,0x00,0x1d,0x1f,0x1f,0x1f,0x18,0x13,0x1d,0x1d,0x10,0x2b,0x1c,0x1d,0x11,0x11,0x17,0x11,0x17,0x1d,0x17,0x1d,0x2d,0x20,0x10,0x0d,0x1d, 0x1b,0x1e,0x1d,0x1d,0x10,0x1d,0x19,0x0c,0x2b,0x1c,0x1d,0x11,0x15,0x16,0x18,0x17,0x17,0x19,0x1d,0x1d,0x1a,0x16,0x16,0x25,0x0c,0x17,0x0c,0x1c,0x16,0x11,0x0d,0x0d,0x11,0x0d,0x09,0x08,0x11,0x11,0x08,0x09,0x09,0x09,0x08,0x09,0x08,0x0b,0x19,0x19,0x11,0x11,0x12,0x11,0x12,0x0c,0x08,0x0a,0x11,0x11,0x10,0x10,0x0e,0x0d,0x0d,0x0f, 0x0d,0x11,0x00,0x00,0x00,0x00,0x0b,0x10,0x10,0x11,0x0d,0x10,0x1b,0x1b,0x1b,0x1b,0x11,0x00,0x00,0x00,0x00,0x17,0x10,0x0d,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x0d,0x0d,0x0d,0x0d,0x1c,0x1c,0x1c,0x1c,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, 0x42,0x42,0x1b,0x12,0x12,0x12,0x12,0x12,0x12,0x0f,0x0f,0x09,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0f,0x0f,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0f,0x0f,0x27,0x20,0x23,0x1d,0x25,0x1f,0x2f,0x26,0x1b,0x13,0x1a,0x22,0x1b,0x29,0x23,0x00,0x00,0x00,0x00,0x0d,0x0d,0x0d, 0x0d,0x11,0x11,0x11,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x2a,0x2a,0x32,0x15,0x0d,0x19,0x1d,0x15,0x19,0x19,0x1d,0x1d,0x19,0x32,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x19,0x19,0x20,0x19,0x19,0x19,0x11,0x1d,0x11,0x26,0x21,0x19,0x11,0x2a,0x19,0x2a,0x0d,0x11,0x1d,0x1d,0x20,0x20,0x20,0x1d,0x1d,0x1d,0x2a,0x0d,0x1d,0x0d,0x19,0x15,0x0d,0x0d, 0x19,0x0d,0x26,0x0d,0x2e,0x19,0x2e,0x2e,0x1d,0x1d,0x1d,0x19,0x19,0x15,0x15,0x3a,0x3a,0x43,0x43,0x2a,0x2a,0x19,0x19,0x08,0x32,0x26,0x2a,0x21,0x1d,0x21,0x19,0x19,0x26,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x0d,0x20,0x00,0x20,0x20,0x20,0x11,0x19,0x19,0x2e,0x11,0x2e,0x11,0x1d,0x21,0x1d,0x15,0x2e,0x19,0x2e,0x19, 0x26,0x2a,0x11,0x19,0x19,0x15,0x0d,0x19,0x1d,0x19,0x1d,0x19,0x1d,0x1d,0x19,0x21,0x20,0x2e,0x11,0x19,0x15,0x21,0x19,0x11,0x19,0x19,0x19,0x2e,0x11,0x2e,0x11,0x0d,0x1d,0x13,0x32,0x19,0x19,0x20,0x20,0x32,0x19,0x00,0x00,0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x26,0x20,0x00,0x00,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x15,0x19,0x19, 0x26,0x2a,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x21,0x1d,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x15,0x15,0x15,0x19,0x15,0x15,0x15,0x3a,0x2a,0x3a,0x2a,0x3a,0x2a,0x43,0x32,0x43,0x32,0x2a,0x19,0x1d,0x1d,0x1d,0x32,0x32, 0x19,0x19,0x32,0x19,0x19,0x32,0x19,0x19,0x32,0x19,0x19,0x26,0x26,0x36,0x32,0x2e,0x19,0x2a,0x19,0x2a,0x19,0x2a,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x21,0x11,0x21,0x11,0x21,0x11,0x21,0x11,0x21,0x11,0x21,0x21,0x11,0x21,0x11,0x1b,0x21,0x1d,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x2a,0x2e,0x26,0x2a,0x11, 0x19,0x26,0x2a,0x26,0x2a,0x00,0x00,0x00,0x00,0x00,0x38,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x15,0x00,0x00,0x1e,0x00,0x00,0x00,0x3a,0x2a,0x43,0x32,0x19,0x1d,0x1d,0x1d,0x15,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x19,0x2e,0x2e,0x13,0x1d,0x1d,0x1e,0x3d,0x2a,0x1b,0x4c,0x36,0x11, 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x19,0x15,0x15,0x26,0x21,0x21,0x19,0x00,0x00,0x00,0x11,0x11,0x11,0x11,0x3f,0x4b,0x00,0x00,0x00,0x00,0x00,0x1d,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x15,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x1d,0x1d,0x1d,0x1d,0x21,0x1d,0x19,0x19,0x15,0x3a, 0x2a,0x19,0x1d,0x1d,0x1d,0x19,0x1d,0x1d,0x1d,0x19,0x1d,0x1d,0x1d,0x32,0x19,0x19,0x32,0x19,0x19,0x2e,0x19,0x19,0x2e,0x19,0x19,0x2e,0x19,0x19,0x1d,0x1d,0x1d,0x1d,0x21,0x11,0x21,0x11,0x21,0x11,0x21,0x21,0x11,0x11,0x15,0x15,0x3a,0x2a,0x20,0x1d,0x1d,0x00,0x19,0x19,0x19,0x12,0x1d,0x22,0x1f,0x19,0x1a,0x12,0x0c,0x26,0x1d,0x1e, 0x11,0x1c,0x18,0x18,0x17,0x18,0x0c,0x1a,0x15,0x1f,0x18,0x1e,0x17,0x1b,0x16,0x22,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x17,0x18,0x18,0x0e,0x1a,0x1c,0x1e,0x19,0x11,0x25,0x1d,0x20,0x1b,0x1f,0x19,0x1c,0x1a,0x14,0x23,0x13,0x15,0x15,0x18,0x1e,0x1e,0x19,0x32,0x19,0x32,0x11,0x0d,0x08,0x1b,0x0b,0x06,0x00,0x07, 0x0b,0x00,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x19,0x19,0x2e,0x15,0x26,0x1d,0x2f,0x24,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x2e,0x2b,0x18,0x2b,0x18,0x2b,0x20,0x22,0x23,0x23,0x26,0x2b,0x32,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x22,0x22,0x22,0x22,0x25,0x1d,0x35,0x29,0x18,0x18,0x0e, 0x0e,0x0e,0x13,0x0b,0x1c,0x0c,0x0c,0x2a,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x0a,0x00,0x00,0x0b,0x00,0x00,0x20,0x1d,0x16,0x18,0x22,0x0d,0x11,0x22,0x22,0x0d,0x1c,0x1b,0x1c,0x23,0x22,0x0d,0x14,0x22,0x1e,0x1f,0x20,0x1c,0x1d,0x21,0x1c,0x27,0x24,0x1a,0x1a,0x1a,0x0b,0x13,0x1c,0x1c, 0x1c,0x1c,0x1b,0x1e,0x20,0x18,0x22,0x1b,0x1c,0x23,0x1c,0x24,0x1c,0x27,0x27,0x27,0x27,0x20,0x20,0x20,0x1d,0x16,0x18,0x22,0x0f,0x12,0x22,0x0f,0x1c,0x1b,0x1c,0x22,0x14,0x22,0x1f,0x20,0x1d,0x21,0x1c,0x27,0x24,0x0d,0x1d,0x1b,0x20,0x21,0x3c,0x00,0x20,0x1c,0x21,0x21,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x0d,0x00,0x26,0x20,0x21,0x23,0x1c,0x21,0x25,0x26,0x18,0x1f,0x25,0x25,0x21,0x26,0x29,0x27,0x21,0x1c,0x1c,0x26,0x23,0x1d,0x22,0x22,0x21,0x22,0x22,0x25,0x1d,0x20,0x22,0x21,0x27,0x20,0x1f,0x20,0x21,0x29,0x19,0x1d, 0x1d,0x2c,0x1b,0x1b,0x27,0x2d,0x1f,0x1b,0x34,0x1c,0x1c,0x26,0x1b,0x1b,0x26,0x1c,0x26,0x29,0x2c,0x1b,0x27,0x1b,0x21,0x1b,0x1f,0x1c,0x20,0x1b,0x1e,0x26,0x1b,0x1f,0x21,0x1b,0x1b,0x1e,0x30,0x1b,0x1b,0x1d,0x1d,0x15,0x11,0x1c,0x1c,0x1c,0x1b,0x1c,0x2c,0x1c,0x2c,0x19,0x1c,0x2c,0x21,0x1c,0x2c,0x25,0x25,0x2c,0x1d,0x1c,0x2c,0x2c, 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x2c,0x2c,0x1d,0x1c,0x1c,0x2c,0x1e,0x1b,0x1c,0x1c,0x2c,0x27,0x22,0x23,0x23,0x22,0x23,0x1f,0x22,0x27,0x23,0x21,0x1b,0x28,0x22,0x22,0x1d,0x21,0x23,0x25,0x24,0x1d,0x23,0x21,0x24,0x21,0x27,0x23,0x24,0x24,0x22,0x20,0x23,0x22,0x24,0x28,0x21,0x26,0x24,0x05,0x06,0x08,0x0a,0x08,0x0e,0x12,0x2b,0x1c, 0x1f,0x1e,0x1c,0x1f,0x1c,0x1c,0x20,0x1e,0x1c,0x0f,0x2a,0x1d,0x1c,0x1c,0x1b,0x1e,0x1a,0x1d,0x0d,0x1d,0x1a,0x1c,0x15,0x2b,0x1b,0x1c,0x1c,0x1e,0x2a,0x1c,0x1d,0x14,0x2a,0x1d,0x1d,0x22,0x22,0x0b,0x0e,0x39,0x38,0x38,0x39,0x47,0x1b,0x1b,0x0c,0x1b,0x13,0x1b,0x1b,0x1c,0x1b,0x1b,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, 0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b,0x1c,0x1b,0x1b,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x19,0x19,0x19,0x1d,0x15,0x15,0x1d,0x1f,0x0d,0x10,0x19,0x15,0x26,0x20,0x1f,0x18,0x1f,0x19,0x15,0x16,0x1e,0x1a,0x28,0x19,0x17,0x18,0x23,0x27,0x15,0x1f,0x18, 0x1d,0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x15,0x15,0x15,0x15,0x0d,0x0d,0x0d,0x0d,0x20,0x1f,0x1f,0x1f,0x1f,0x1f,0x1e,0x1e,0x1e,0x1e,0x17,0x19,0x19,0x19,0x19,0x19,0x1d,0x1d,0x1d,0x15,0x15,0x15,0x15,0x15,0x1d,0x1d,0x19,0x1f,0x1f,0x0d,0x0d,0x0d,0x0d,0x0d,0x1c,0x10,0x19,0x15,0x15,0x15,0x15,0x20,0x20,0x20,0x21,0x1f,0x1f, 0x1f,0x19,0x19,0x19,0x15,0x15,0x15,0x15,0x16,0x16,0x16,0x16,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x28,0x28,0x28,0x28,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x23,0x1f,0x19,0x19,0x14,0x1b,0x15,0x18,0x1f,0x1f,0x0d,0x19,0x1a,0x26,0x20,0x16,0x1f,0x1f,0x18,0x17,0x16,0x17,0x1f,0x19,0x21,0x20,0x19,0x15,0x1f,0x0d,0x1f,0x17,0x20,0x0d,0x17, 0x15,0x1c,0x14,0x1a,0x15,0x0d,0x0d,0x10,0x29,0x29,0x1f,0x19,0x19,0x1e,0x19,0x18,0x19,0x14,0x1d,0x15,0x25,0x16,0x20,0x20,0x19,0x1c,0x26,0x1f,0x1f,0x1f,0x18,0x19,0x16,0x19,0x1f,0x19,0x20,0x1b,0x28,0x2a,0x1c,0x23,0x19,0x1a,0x2b,0x18,0x14,0x1d,0x1d,0x1f,0x2c,0x2c,0x21,0x19,0x1d,0x15,0x1d,0x1c,0x1c,0x23,0x1a,0x1a,0x22,0x1d, 0x1d,0x12,0x1f,0x1f,0x1d,0x18,0x18,0x2d,0x25,0x18,0x1b,0x1e,0x1e,0x1f,0x1f,0x24,0x22,0x12,0x2f,0x1e,0x1c,0x1d,0x20,0x20,0x19,0x19,0x0d,0x26,0x22,0x22,0x18,0x23,0x0b,0x0b,0x16,0x16,0x0b,0x0b,0x1f,0x14,0x0d,0x26,0x23,0x0e,0x0b,0x0b,0x16,0x13,0x13,0x0b,0x0b,0x0b,0x13,0x22,0x18,0x0f,0x1e,0x22,0x1d,0x1d,0x19,0x25,0x1c,0x1e, 0x11,0x16,0x1b,0x15,0x0b,0x0b,0x14,0x1a,0x11,0x21,0x21,0x21,0x2e,0x26,0x2e,0x0d,0x00,0x00,0x00,0x00,0x00,0x0d,0x26,0x2a,0x11,0x11,0x19,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x1d,0x1d,0x1d,0x19,0x19,0x3a,0x2a,0x3a,0x2a,0x43,0x32,0x43,0x32,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2e,0x2e,0x19,0x19,0x2e,0x2e,0x19,0x19,0x26,0x2a,0x11, 0x11,0x26,0x2a,0x11,0x11,0x26,0x2a,0x11,0x11,0x32,0x26,0x2a,0x19,0x1d,0x1d,0x21,0x11,0x21,0x26,0x19,0x19,0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x2e,0x11,0x26,0x19,0x19,0x0d,0x19,0x19,0x19,0x19,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x1d,0x1d, 0x1d,0x1d,0x1d,0x1d,0x1d,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x3a,0x2a,0x3a,0x2a,0x3a,0x2a,0x43,0x32,0x43,0x32,0x2a,0x2a,0x2a,0x32,0x32,0x32,0x32,0x32,0x32,0x26,0x19,0x19,0x26,0x19,0x19,0x2e,0x19,0x36,0x32,0x2e,0x19,0x2a,0x19,0x2a,0x19,0x2a,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x2e,0x19,0x21, 0x21,0x21,0x21,0x21,0x11,0x21,0x21,0x11,0x11,0x21,0x11,0x21,0x11,0x21,0x19,0x1d,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x11,0x11,0x19,0x11,0x11,0x11,0x11,0x00,0x3a,0x2a,0x43,0x32,0x2e,0x19,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x2e,0x11,0x1d,0x1d,0x19,0x19,0x15,0x3a,0x2a,0x32,0x32,0x2e,0x2e,0x2e, 0x1d,0x1d,0x1d,0x1d,0x21,0x11,0x21,0x11,0x21,0x11,0x3a,0x2a,0x1d,0x21,0x1d,0x1d,0x1d,0x21,0x1d,0x1d,0x3a,0x3a,0x2a,0x2a,0x15,0x15,0x1d,0x1d,0x1d,0x1d,0x11,0x11,0x11,0x11,0x26,0x2a,0x11,0x11,0x26,0x2a,0x11,0x11,0x26,0x2a,0x11,0x11,0x1d,0x1d,0x1d,0x1d,0x2e,0x11,0x2e,0x11,0x1d,0x21,0x1d,0x1d,0x3a,0x3a,0x2a,0x2a,0x3a,0x3a, 0x2a,0x2a,0x2a,0x2a,0x19,0x19,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x00,0x00,0x0d,0x0d,0x11,0x0d,0x00,0x00,0x00,0x2a,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x15,0x15,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e, 0x2e,0x2e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x26,0x21,0x21,0x21,0x21,0x21,0x21,0x1d,0x2a,0x1d,0x2a,0x1d,0x2a,0x1d,0x2a,0x21,0x21,0x21,0x0d,0x0d,0x19,0x15,0x1d,0x20,0x1d,0x1b,0x1c,0x1d, 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1b,0x1a,0x1d,0x1f,0x1f,0x21,0x1d,0x1c,0x21,0x1a,0x21,0x26,0x20,0x25,0x29,0x20,0x26,0x22,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x17,0x1b,0x1e,0x1e,0x21,0x1d,0x20,0x1d,0x1e,0x1e,0x1a,0x1a,0x26,0x22,0x23,0x22,0x22,0x1e,0x1d,0x1d,0x25, 0x27,0x26,0x26,0x2e,0x2e,0x23,0x2e,0x2e,0x25,0x2c,0x2a,0x1c,0x26,0x2a,0x26,0x1e,0x2b,0x25,0x23,0x23,0x1e,0x20,0x25,0x28,0x23,0x1f,0x23,0x1d,0x1b,0x2e,0x2e,0x2e,0x29,0x2e,0x2e,0x22,0x2e,0x2e,0x23,0x26,0x27,0x25,0x24,0x24,0x20,0x2c,0x26,0x29,0x24,0x24,0x1d,0x25,0x23,0x23,0x2b,0x26,0x24,0x2d,0x1b,0x19,0x1c,0x1b,0x1f,0x1f, 0x23,0x25,0x1d,0x1c,0x1c,0x1b,0x1c,0x1b,0x1b,0x1c,0x1c,0x1d,0x1c,0x1c,0x1c,0x19,0x1a,0x1e,0x1f,0x1e,0x1e,0x17,0x1c,0x1c,0x1d,0x1e,0x26,0x2a,0x21,0x21,0x1f,0x26,0x20,0x22,0x1a,0x18,0x1d,0x1c,0x18,0x19,0x1b,0x1c,0x18,0x17,0x1f,0x17,0x1b,0x19,0x1b,0x27,0x1c,0x29,0x1b,0x1c,0x1c,0x25,0x10,0x27,0x22,0x24,0x21,0x1c,0x26,0x1e, 0x27,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x1e,0x1e,0x1e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x16,0x17,0x16,0x17,0x17,0x17,0x0f,0x10,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x1f,0x0d,0x0d,0x0d,0x10,0x10,0x0d,0x0d,0x0d,0x0f,0x0d,0x0d,0x0d,0x2d,0x2d,0x2d,0x2d,0x18,0x25,0x24,0x18,0x14,0x18,0x1a,0x1c,0x18,0x2a,0x29,0x2b,0x16, 0x32,0x18,0x2a,0x2a,0x2a,0x28,0x1c,0x18,0x18,0x27,0x1d,0x27,0x22,0x1b,0x17,0x14,0x33,0x15,0x1b,0x18,0x18,0x18,0x18,0x18,0x44,0x2a,0x2a,0x15,0x0d,0x17,0x0c,0x17,0x0c,0x0c,0x0c,0x18,0x1d,0x1d,0x1b,0x13,0x13,0x0b,0x0b,0x0b,0x13,0x0b,0x15,0x2b,0x0b,0x2d,0x2d,0x2d,0x1d,0x1d,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, 0x3a,0x3a,0x21,0x3a,0x3a,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x17,0x1d,0x17,0x1b,0x15,0x12,0x11,0x22,0x1b,0x24,0x16,0x38,0x2d,0x1e,0x1c,0x2e,0x28,0x2a,0x25,0x33,0x29,0x2e,0x27,0x20,0x18, 0x24,0x1d,0x2e,0x25,0x26,0x1e,0x25,0x1e,0x2b,0x21,0x2c,0x21,0x37,0x2a,0x26,0x1d,0x26,0x1d,0x3d,0x2c,0x28,0x00,0x31,0x31,0x31,0x18,0x00,0x00,0x1d,0x19,0x23,0x1c,0x1b,0x15,0x36,0x2d,0x2f,0x2b,0x24,0x1d,0x23,0x1d,0x1a,0x15,0x25,0x1e,0x1a,0x15,0x29,0x21,0x21,0x1c,0x31,0x29,0x1b,0x1d,0x25,0x25,0x28,0x16,0x0a,0x17,0x22,0x16, 0x32,0x32,0x0c,0x00,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x14,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x1b,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x2c,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28, 0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x28,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x24,0x24,0x24,0x24,0x24,0x24, 0x24,0x24,0x24,0x24,0x24,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x18,0x22,0x24,0x0e,0x0a,0x0e,0x0a,0x24,0x1c,0x25,0x1f,0x1c,0x18,0x1b,0x18,0x1e,0x1d,0x15,0x15,0x38,0x29,0x3a,0x2c,0x31,0x2a,0x2d,0x21,0x2d,0x21,0x2d,0x21,0x1f,0x17,0x1d,0x19,0x1d,0x19,0x1d,0x19,0x1b,0x10,0x18, 0x0c,0x26,0x1d,0x2b,0x22,0x43,0x32,0x1c,0x1d,0x22,0x23,0x28,0x2b,0x26,0x1d,0x31,0x27,0x1b,0x14,0x1c,0x19,0x1f,0x18,0x2f,0x24,0x1f,0x1a,0x1c,0x1d,0x1c,0x1d,0x18,0x14,0x18,0x13,0x18,0x12,0x1a,0x1a,0x0f,0x22,0x10,0x30,0x21,0x11,0x1d,0x1f,0x17,0x26,0x1c,0x13,0x11,0x1d,0x1d,0x1d,0x18,0x0c,0x26,0x1e,0x12,0x11,0x1f,0x17,0x24, 0x13,0x27,0x1e,0x1f,0x17,0x22,0x1d,0x1d,0x19,0x25,0x1c,0x1e,0x11,0x1b,0x15,0x26,0x15,0x1b,0x2b,0x18,0x1c,0x2d,0x0d,0x39,0x2d,0x2d,0x3b,0x2c,0x2e,0x2e,0x2c,0x2c,0x2e,0x1a,0x18,0x1f,0x23,0x2d,0x23,0x2f,0x0c,0x17,0x1d,0x2b,0x33,0x23,0x33,0x1f,0x1f,0x28,0x23,0x39,0x2e,0x1a,0x2e,0x11,0x2e,0x11,0x1d,0x1d,0x1d,0x1d,0x2a,0x2a, 0x2a,0x2a,0x32,0x19,0x19,0x32,0x26,0x19,0x19,0x26,0x21,0x11,0x11,0x21,0x1d,0x1d,0x1d,0x1d,0x26,0x11,0x11,0x2a,0x26,0x11,0x11,0x2a,0x15,0x15,0x19,0x19,0x1a,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x1a,0x14,0x1c,0x1a, 0x25,0x1d,0x1d,0x2c,0x21,0x25,0x26,0x2a,0x29,0x1d,0x19,0x32,0x28,0x34,0x2b,0x22,0x1d,0x10,0x10,0x1d,0x20,0x14,0x1e,0x1a,0x1d,0x18,0x25,0x28,0x14,0x1d,0x15,0x0b,0x13,0x1b,0x1c,0x0b,0x0b,0x09,0x0b,0x13,0x13,0x13,0x16,0x4a,0x64,0x11,0x15,0x07,0x0d,0x13,0x16,0x10,0x19,0x1a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, 0x18,0x18,0x18,0x18,0x18,0x42,0x1b,0x26,0x2e,0x2d,0x20,0x17,0x1c,0x24,0x25,0x18,0x10,0x21,0x1a,0x22,0x1c,0x21,0x1b,0x1b,0x25,0x1e,0x1d,0x1a,0x25,0x1f,0x2a,0x17,0x1a,0x20,0x10,0x1d,0x11,0x11,0x0c,0x2c,0x1d,0x1c,0x1a,0x1a,0x1d,0x2e,0x2e,0x2f,0x32,0x32,0x1b,0x19,0x0e,0x19,0x17,0x1e,0x17,0x21,0x0c,0x1c,0x1e,0x2b,0x2b,0x1f, 0x1b,0x1d,0x1b,0x1a,0x17,0x1a,0x17,0x18,0x0f,0x11,0x0c,0x0b,0x12,0x1d,0x20,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x00,0x0e,0x0e,0x0e,0x0d,0x0d,0x54,0x32,0x2c,0x34,0x0e,0x0e,0x10,0x14,0x0d,0x0d,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x00,0x2e,0x11,0x11,0x2e,0x0d,0x19, 0x19,0x43,0x32,0x32,0x43,0x2e,0x19,0x19,0x2e,0x19,0x19,0x15,0x15,0x00,0x00,0x12,0x25,0x1e,0x24,0x1d,0x3f,0x34,0x23,0x1b,0x23,0x1b,0x43,0x32,0x26,0x1d,0x13,0x10,0x1f,0x00,0x22,0x1b,0x11,0x0f,0x08,0x19,0x11,0x11,0x0d,0x0a,0x17,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x0b,0x1a,0x15,0x1e,0x1d,0x1b,0x30,0x28,0x28,0x27,0x29, 0x2f,0x1f,0x22,0x1e,0x14,0x2e,0x38,0x16,0x3a,0x19,0x2a,0x2e,0x2e,0x2e,0x15,0x26,0x32,0x26,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x1d,0x1d,0x1d,0x2a,0x19,0x19,0x2e,0x11,0x11,0x2e,0x11,0x11,0x2e,0x19,0x19,0x00,0x15,0x2a,0x11,0x11,0x32,0x19,0x19,0x26,0x19,0x19,0x21,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x4b,0x4b,0x2c,0x00,0x00,0x2c,0x2c,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x21,0x1f,0x20,0x20,0x2c,0x20,0x20,0x28,0x31,0x21,0x20,0x35,0x20,0x20,0x2f,0x20,0x22,0x28,0x20,0x26,0x2a,0x2e,0x20,0x26,0x20,0x23,0x1f,0x23, 0x1f,0x21,0x22,0x1f,0x27,0x1e,0x21,0x27,0x1f,0x1f,0x1c,0x27,0x20,0x20,0x20,0x23,0x16,0x1a,0x20,0x27,0x27,0x1b,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x14,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x04,0x1c,0xd0,0x00,0x00,0x01,0x42,0x01,0x00,0x00,0x07,0x00,0x42,0x00,0x0d,0x00,0x7e,0x03,0x77, 0x03,0x7f,0x03,0x8a,0x03,0x8c,0x03,0xa1,0x05,0x2f,0x05,0x56,0x05,0x5f,0x05,0x87,0x05,0x8a,0x05,0x8f,0x05,0xc7,0x05,0xea,0x05,0xf4,0x06,0x1c,0x06,0xff,0x07,0x7f,0x07,0xc9,0x08,0xb4,0x08,0xbd,0x08,0xff,0x09,0x6f,0x09,0xef,0x09,0xf3,0x0a,0x6f,0x0a,0xef,0x0a,0xf1,0x0b,0x6f,0x0b,0xef,0x0b,0xf9,0x0c,0x6f,0x0c,0xef,0x0d,0x6f, 0x0e,0x3f,0x0e,0x59,0x0e,0xd9,0x0f,0x29,0x10,0x49,0x10,0xc5,0x10,0xc7,0x10,0xcd,0x10,0xff,0x17,0xdb,0x17,0xe9,0x18,0x19,0x19,0xda,0x1c,0xbf,0x1d,0xca,0x1f,0x15,0x1f,0x1d,0x1f,0x45,0x1f,0x4d,0x1f,0x57,0x1f,0x59,0x1f,0x5b,0x1f,0x5d,0x1f,0x7d,0x1f,0xb4,0x1f,0xc4,0x1f,0xd3,0x1f,0xdb,0x1f,0xef,0x1f,0xf4,0x1f,0xfe,0x20,0x22, 0x20,0x26,0x20,0x30,0x20,0x34,0x20,0x3a,0x20,0x3e,0x20,0x44,0x20,0x5f,0x20,0x71,0x20,0x8e,0x20,0x9c,0x20,0xbf,0x20,0xe3,0x20,0xf0,0x21,0x05,0x21,0x13,0x21,0x17,0x21,0x22,0x21,0x26,0x21,0x2e,0x21,0x33,0x21,0x4e,0x21,0x5f,0x21,0x6f,0x21,0x89,0x21,0x94,0x21,0x97,0x21,0x99,0x22,0x02,0x22,0x06,0x22,0x0f,0x22,0x12,0x22,0x15, 0x22,0x1a,0x22,0x1f,0x22,0x29,0x22,0x2b,0x22,0x34,0x22,0x36,0x22,0x48,0x22,0x61,0x22,0x65,0x22,0xf2,0x24,0xff,0x25,0xa1,0x25,0xac,0x25,0xb2,0x25,0xba,0x25,0xbc,0x25,0xc4,0x25,0xcc,0x25,0xcf,0x25,0xd9,0x25,0xe6,0x26,0x61,0x26,0x63,0x26,0x66,0x26,0x6f,0x27,0x7f,0x2c,0x7f,0x2d,0x25,0x2d,0x27,0x2d,0x2d,0x2d,0xff,0x2e,0x17, 0x2e,0x3b,0xa4,0xff,0xa6,0x29,0xa6,0x9f,0xa7,0xae,0xa7,0xb7,0xa7,0xff,0xab,0x65,0xfb,0x06,0xfb,0x17,0xfb,0x36,0xfb,0x3c,0xfb,0x3e,0xfb,0x41,0xfb,0x44,0xfb,0xc1,0xfb,0xff,0xfc,0x63,0xfc,0xf4,0xfd,0x3f,0xfd,0xf2,0xfd,0xf4,0xfd,0xfd,0xfe,0x23,0xfe,0x58,0xfe,0x74,0xfe,0xfc,0xfe,0xff,0xff,0xfd,0xff,0xff,0x00,0x00,0x00,0x0d, 0x00,0x20,0x00,0xa0,0x03,0x7a,0x03,0x84,0x03,0x8c,0x03,0x8e,0x03,0xa3,0x05,0x31,0x05,0x59,0x05,0x61,0x05,0x89,0x05,0x8d,0x05,0x91,0x05,0xd0,0x05,0xef,0x06,0x00,0x06,0x1e,0x07,0x50,0x07,0xc0,0x08,0xa0,0x08,0xb6,0x08,0xd4,0x09,0x66,0x09,0xe6,0x09,0xf2,0x0a,0x66,0x0a,0xe6,0x0a,0xf1,0x0b,0x66,0x0b,0xe6,0x0b,0xf9,0x0c,0x66, 0x0c,0xe6,0x0d,0x66,0x0e,0x3f,0x0e,0x50,0x0e,0xd0,0x0f,0x20,0x10,0x40,0x10,0xa0,0x10,0xc7,0x10,0xcd,0x10,0xd0,0x17,0xdb,0x17,0xe0,0x18,0x10,0x19,0xd0,0x1c,0x90,0x1d,0x00,0x1d,0xfe,0x1f,0x18,0x1f,0x20,0x1f,0x48,0x1f,0x50,0x1f,0x59,0x1f,0x5b,0x1f,0x5d,0x1f,0x5f,0x1f,0x80,0x1f,0xb6,0x1f,0xc6,0x1f,0xd6,0x1f,0xdd,0x1f,0xf2, 0x1f,0xf6,0x20,0x00,0x20,0x26,0x20,0x28,0x20,0x32,0x20,0x39,0x20,0x3c,0x20,0x44,0x20,0x5e,0x20,0x70,0x20,0x74,0x20,0x90,0x20,0xa0,0x20,0xe3,0x20,0xf0,0x21,0x05,0x21,0x13,0x21,0x16,0x21,0x22,0x21,0x26,0x21,0x2e,0x21,0x33,0x21,0x4d,0x21,0x50,0x21,0x6c,0x21,0x7a,0x21,0x90,0x21,0x97,0x21,0x99,0x22,0x02,0x22,0x06,0x22,0x0f, 0x22,0x11,0x22,0x15,0x22,0x19,0x22,0x1e,0x22,0x29,0x22,0x2b,0x22,0x34,0x22,0x36,0x22,0x48,0x22,0x60,0x22,0x64,0x22,0xf2,0x24,0xff,0x25,0xa0,0x25,0xaa,0x25,0xb2,0x25,0xba,0x25,0xbc,0x25,0xc4,0x25,0xca,0x25,0xcf,0x25,0xd8,0x25,0xe6,0x26,0x60,0x26,0x63,0x26,0x65,0x26,0x6f,0x27,0x76,0x2c,0x60,0x2d,0x00,0x2d,0x27,0x2d,0x2d, 0x2d,0xe0,0x2e,0x17,0x2e,0x32,0xa4,0xd0,0xa6,0x20,0xa6,0x40,0xa7,0x00,0xa7,0xb0,0xa7,0xf7,0xab,0x30,0xfb,0x00,0xfb,0x13,0xfb,0x1d,0xfb,0x38,0xfb,0x3e,0xfb,0x40,0xfb,0x43,0xfb,0x46,0xfb,0xd3,0xfc,0x5e,0xfc,0xf2,0xfd,0x3c,0xfd,0xf2,0xfd,0xf4,0xfd,0xfa,0xfe,0x20,0xfe,0x58,0xfe,0x70,0xfe,0x76,0xfe,0xff,0xff,0xfc,0xff,0xff, 0xff,0xf5,0xff,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x19,0x00,0x00,0x00,0x00,0x07,0x2a,0x07,0x28,0x07,0x27,0x07,0x26,0x00,0x00,0x00,0x00,0x05,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0c,0x00,0x00,0x0b,0x9f,0x00,0x00,0x06,0x70,0x05,0xfa,0x0a,0x5b,0x05,0x84,0x05,0x0e,0x09,0x5e,0x04,0x98,0x04,0x22,0x08,0x57, 0x03,0xac,0x03,0x36,0x02,0xc0,0xfa,0x4d,0x01,0xe0,0x01,0x6a,0x01,0x24,0x00,0x0e,0xfb,0x42,0xfe,0xfe,0xfe,0xf9,0x00,0x00,0xfc,0x76,0xf8,0x82,0xf8,0x5c,0xf6,0xa6,0xf8,0x1f,0x00,0x00,0x00,0x00,0xe4,0x77,0xe4,0x75,0xe4,0x73,0xe4,0x71,0xe4,0x70,0xe4,0x6f,0xe4,0x6e,0xe4,0x6d,0xe4,0x6b,0xe4,0x6a,0xe4,0x69,0xe4,0x67,0xe4,0x66, 0xe4,0x64,0xe4,0x63,0x00,0x00,0xe0,0x86,0x00,0x00,0x00,0x00,0xe0,0x85,0x00,0x00,0xe0,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xaa,0xea,0x32,0xe0,0x39,0xe0,0x2c,0x00,0x00,0xdf,0x6b,0xdf,0x79,0xe0,0x69,0xf3,0x1f,0xe9,0x97,0x00,0x00,0xf1,0x80,0x00,0x00,0xe9,0x9c,0xef,0xeb,0xef,0xea,0xde,0x97,0xe9,0x2b, 0xde,0x8c,0x00,0x00,0xde,0xa7,0x00,0x00,0x00,0x00,0xe9,0x0a,0xde,0x71,0xe9,0x00,0xee,0xc4,0xde,0x60,0x00,0x00,0xde,0x31,0xe8,0x43,0xe3,0x83,0x00,0x00,0x00,0x00,0xe5,0x86,0xe5,0x7f,0xe5,0x7e,0xe5,0x77,0x00,0x00,0xdb,0x74,0xe5,0x65,0xdb,0x5e,0x00,0x00,0xe4,0xdd,0xe4,0xdc,0xeb,0x1a,0x00,0x00,0x00,0x00,0xdf,0x35,0xe2,0xa3, 0xe2,0x9e,0xe3,0x30,0xda,0x43,0xe5,0x3b,0x68,0xf2,0x6a,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x9e,0x00,0x00,0x10,0x6c,0x10,0x6b,0x10,0x6a,0x10,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0xf8,0x00,0x00,0x0c,0x71,0x15,0xfb,0x00,0x00,0x09,0x1a,0x14,0xa7,0x15,0x83,0x00,0x00,0x0c,0x0c,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x3e,0x06,0xec,0x06,0xf6,0x00,0x00,0x07,0x00,0x07,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x36,0x0a,0x3a,0x00,0x00,0x0a,0xa4,0x0a,0xae,0x0a,0xe6,0x0c,0xa8,0x00,0x00,0x0d,0x04,0x00,0x00,0x0d,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xac,0x0f,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x50,0x00,0x00,0x11,0x92,0x11,0xa2,0x00,0x00,0x11,0xa4,0x00,0x00,0x11,0xa6,0x11,0xa8,0x11,0xaa,0x11,0xde,0x11,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x24,0x00,0x00,0x12,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x12,0x52,0x00,0x00,0x12,0x52,0x12,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x48,0x12,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x40,0x12,0x52,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x80,0x13,0x3e,0x14,0x9a,0x14,0xa8,0x14,0xb8,0x15,0x22,0x00,0x00,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x56,0x16,0x4c,0x16,0xa4,0x00,0x00,0x16,0xac,0x00,0x00,0x00,0x00,0x16,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0xae,0x00,0x00, 0x17,0xb8,0x00,0x00,0x00,0xa3,0x00,0xa4,0x00,0x84,0x00,0x85,0x02,0x3f,0x00,0x97,0x00,0xe7,0x00,0x86,0x00,0x8f,0x00,0x8c,0x00,0x9d,0x00,0xaa,0x00,0xa5,0x00,0x8a,0x00,0x8b,0x01,0x01,0x00,0x83,0x00,0x94,0x08,0x96,0x08,0x97,0x00,0x8e,0x00,0x98,0x00,0x88,0x00,0xc3,0x00,0xdd,0x08,0x98,0x00,0x9e,0x00,0xab,0x00,0xf4,0x00,0xf3, 0x00,0xf5,0x00,0xa2,0x00,0xad,0x00,0xc9,0x00,0xc7,0x00,0xae,0x00,0x62,0x00,0x63,0x00,0x91,0x00,0x64,0x00,0xcb,0x00,0x65,0x00,0xc8,0x00,0xca,0x00,0xcf,0x00,0xcc,0x00,0xcd,0x00,0xce,0x00,0xe8,0x00,0x66,0x00,0xd2,0x00,0xd0,0x00,0xd1,0x00,0xaf,0x00,0x67,0x00,0xef,0x00,0x92,0x00,0xd5,0x00,0xd3,0x00,0xd4,0x00,0x68,0x00,0xea, 0x00,0xec,0x00,0x89,0x00,0x6a,0x00,0x69,0x00,0x6b,0x00,0x6d,0x00,0x6c,0x00,0x6e,0x00,0xa0,0x00,0x6f,0x00,0x71,0x00,0x70,0x00,0x72,0x00,0x73,0x00,0x75,0x00,0x74,0x00,0x76,0x00,0x77,0x00,0xe9,0x00,0x78,0x00,0x7a,0x00,0x79,0x00,0x7b,0x00,0x7d,0x00,0x7c,0x00,0xb8,0x00,0xa1,0x00,0x7f,0x00,0x7e,0x00,0x80,0x00,0x81,0x00,0xeb, 0x00,0xed,0x00,0xba,0x01,0x45,0x01,0x46,0x01,0x03,0x01,0x04,0x01,0x05,0x01,0x06,0x00,0xfc,0x00,0xfd,0x01,0x47,0x01,0x48,0x01,0x49,0x01,0x4a,0x00,0xfe,0x00,0xff,0x01,0x07,0x01,0x08,0x01,0x09,0x01,0x00,0x01,0x4b,0x01,0x4c,0x01,0x4d,0x01,0x4e,0x01,0x4f,0x01,0x50,0x01,0x0a,0x01,0x0b,0x01,0x0c,0x01,0x0d,0x01,0x51,0x01,0x52, 0x00,0xf7,0x00,0xf8,0x01,0x53,0x01,0x54,0x01,0x55,0x01,0x56,0x01,0x57,0x01,0x58,0x01,0x59,0x01,0x5a,0x01,0x5b,0x01,0x5c,0x01,0x5d,0x01,0x5e,0x01,0x5f,0x01,0x60,0x01,0x61,0x01,0x62,0x00,0xf9,0x00,0xd6,0x01,0x39,0x01,0x3a,0x01,0x63,0x01,0x64,0x01,0x65,0x01,0x66,0x01,0x67,0x01,0x0e,0x01,0x0f,0x01,0x68,0x01,0x69,0x01,0x10, 0x01,0x11,0x01,0x12,0x01,0x13,0x00,0xe1,0x00,0xe2,0x01,0x14,0x01,0x15,0x01,0x6a,0x01,0x6b,0x01,0x16,0x01,0x17,0x01,0x3b,0x01,0x6c,0x01,0x6d,0x01,0x6e,0x01,0x6f,0x01,0x70,0x01,0x71,0x01,0x18,0x01,0x19,0x00,0xb0,0x00,0xb1,0x01,0x1a,0x01,0x1b,0x01,0x72,0x01,0x73,0x01,0x1c,0x01,0x1d,0x01,0x1e,0x01,0x1f,0x01,0x74,0x01,0x75, 0x00,0xfa,0x00,0xfb,0x00,0xe3,0x00,0xe4,0x01,0x20,0x01,0x21,0x01,0x22,0x01,0x23,0x01,0x76,0x01,0x77,0x01,0x78,0x01,0x79,0x01,0x7a,0x01,0x7b,0x01,0x7c,0x01,0x7d,0x01,0x24,0x01,0x25,0x01,0x26,0x01,0x27,0x01,0x7e,0x01,0x7f,0x01,0x80,0x01,0x81,0x01,0x82,0x01,0x83,0x00,0xbb,0x01,0x28,0x01,0x29,0x01,0x2a,0x01,0x2b,0x00,0xe5, 0x00,0xe6,0x01,0x84,0x04,0xb0,0x04,0xb1,0x04,0xb2,0x04,0xb3,0x04,0xb4,0x04,0xb5,0x04,0xb6,0x04,0xb7,0x04,0xb8,0x04,0xb9,0x04,0xba,0x04,0xbb,0x04,0xbc,0x04,0xbd,0x04,0xbe,0x02,0xcd,0x04,0xbf,0x04,0xc0,0x00,0xa7,0x04,0xc1,0x04,0xc2,0x04,0xc3,0x04,0xc4,0x04,0xc5,0x04,0xc6,0x04,0xc7,0x04,0xc8,0x04,0xc9,0x04,0xca,0x04,0xcb, 0x04,0xcc,0x04,0xcd,0x02,0x40,0x02,0x41,0x04,0xce,0x04,0xcf,0x04,0xd0,0x04,0xd1,0x04,0xd2,0x04,0xd3,0x04,0xd4,0x04,0xd5,0x04,0xd6,0x04,0xd7,0x04,0xd8,0x04,0xd9,0x04,0xda,0x02,0x42,0x02,0x43,0x04,0xdb,0x04,0xdc,0x04,0xdd,0x04,0xde,0x04,0xdf,0x04,0xe0,0x04,0xe1,0x04,0xe2,0x04,0xe3,0x04,0xe4,0x04,0xe5,0x04,0xe6,0x04,0xe7, 0x04,0xe8,0x04,0xe9,0x04,0xea,0x04,0xeb,0x04,0xec,0x04,0xed,0x04,0xee,0x04,0xef,0x04,0xf0,0x04,0xf1,0x04,0xf2,0x04,0xf3,0x04,0xf4,0x04,0xf5,0x04,0xf6,0x04,0xf7,0x04,0xf8,0x04,0xf9,0x04,0xfa,0x04,0xfb,0x04,0xfc,0x04,0xfd,0x04,0xfe,0x04,0xff,0x05,0x00,0x05,0x01,0x05,0x02,0x05,0x03,0x05,0x04,0x05,0x05,0x05,0x06,0x05,0x07, 0x05,0x08,0x05,0x09,0x05,0x0a,0x05,0x0b,0x05,0x0c,0x05,0x0d,0x05,0x0e,0x05,0x0f,0x05,0x10,0x05,0x11,0x05,0x12,0x05,0x13,0x05,0x14,0x05,0x15,0x05,0x16,0x05,0x17,0x05,0x18,0x05,0x19,0x05,0x1a,0x05,0x1b,0x05,0x1c,0x05,0x1d,0x05,0x1e,0x05,0x1f,0x05,0x20,0x05,0x21,0x05,0x22,0x05,0x23,0x01,0x85,0x01,0x86,0x01,0x87,0x01,0x88, 0x01,0x89,0x01,0x8a,0x05,0x24,0x05,0x25,0x05,0x26,0x05,0x27,0x05,0x28,0x05,0x29,0x05,0x2a,0x05,0x2b,0x05,0x2c,0x05,0x2d,0x05,0x2e,0x05,0x2f,0x05,0x30,0x05,0x31,0x05,0x32,0x05,0x33,0x05,0x34,0x05,0x35,0x05,0x36,0x05,0x37,0x05,0x38,0x05,0x39,0x05,0x3a,0x05,0x3b,0x02,0x3d,0x02,0x3e,0x02,0xaf,0x02,0xb0,0x05,0x3c,0x05,0x3d, 0x05,0x3e,0x05,0x3f,0x05,0x40,0x07,0x3e,0x05,0x41,0x05,0x42,0x05,0x43,0x05,0x44,0x05,0x45,0x05,0x46,0x02,0xe1,0x02,0xe2,0x05,0x47,0x05,0x48,0x05,0x49,0x05,0x4a,0x05,0x4b,0x05,0x4c,0x05,0x4d,0x05,0x4e,0x05,0x4f,0x05,0x50,0x07,0x3f,0x07,0x40,0x07,0x41,0x06,0xac,0x07,0xe1,0x07,0xe2,0x07,0xe4,0x07,0xe5,0x07,0xe6,0x07,0xe7, 0x07,0xe8,0x07,0xe9,0x07,0xea,0x07,0xeb,0x0a,0xbf,0x0a,0xc0,0x0a,0xc1,0x0a,0xc2,0x0a,0xc3,0x0a,0xc4,0x0a,0xc5,0x0a,0xc6,0x0a,0xc7,0x0a,0xc8,0x0a,0xc9,0x0a,0xca,0x0a,0xcb,0x0a,0xcc,0x05,0x56,0x05,0x57,0x05,0x58,0x05,0x59,0x05,0x5a,0x05,0x5b,0x05,0x5c,0x05,0x5d,0x05,0x5e,0x02,0xce,0x05,0x5f,0x05,0x60,0x05,0x61,0x05,0x62, 0x05,0x63,0x05,0x64,0x05,0x65,0x05,0x66,0x05,0x67,0x05,0x68,0x05,0x69,0x05,0x6a,0x05,0x6b,0x05,0x6c,0x05,0x6d,0x05,0x6e,0x05,0x6f,0x05,0x70,0x05,0x71,0x05,0x72,0x05,0x73,0x05,0x74,0x05,0x75,0x05,0x76,0x05,0x77,0x05,0x78,0x05,0x79,0x05,0x7a,0x05,0x7b,0x05,0x7c,0x05,0x7d,0x05,0x7e,0x05,0x7f,0x05,0x80,0x05,0x81,0x05,0x82, 0x05,0x83,0x05,0x84,0x05,0x85,0x05,0x86,0x05,0x87,0x05,0x88,0x05,0x89,0x05,0x8a,0x05,0x8b,0x05,0x8c,0x05,0x8d,0x05,0x8e,0x05,0x8f,0x05,0x90,0x05,0x91,0x05,0x92,0x05,0x93,0x05,0x94,0x05,0x95,0x05,0x96,0x05,0x97,0x05,0x98,0x05,0x99,0x05,0x9a,0x05,0x9b,0x05,0x9c,0x05,0x9d,0x05,0x9e,0x05,0x9f,0x05,0xa0,0x05,0xa1,0x05,0xa2, 0x05,0xa3,0x05,0xa4,0x05,0xa5,0x05,0xa6,0x05,0xa7,0x05,0xa8,0x05,0xa9,0x05,0xaa,0x05,0xab,0x05,0xac,0x05,0xad,0x05,0xae,0x05,0xaf,0x05,0xb0,0x05,0xb1,0x05,0xb2,0x07,0x42,0x07,0x43,0x06,0x76,0x06,0x77,0x06,0x78,0x06,0x79,0x06,0x7a,0x06,0x7b,0x06,0x7c,0x06,0x7d,0x06,0x7e,0x06,0x7f,0x06,0x80,0x06,0x81,0x06,0x82,0x06,0x83, 0x06,0x84,0x06,0x85,0x06,0x86,0x06,0x87,0x06,0x88,0x06,0x89,0x06,0x8a,0x06,0x8b,0x00,0xd7,0x00,0xe0,0x06,0x8c,0x00,0xd9,0x06,0x8d,0x06,0x8e,0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x06,0x9a,0x00,0xda,0x00,0xdb,0x00,0xdc,0x00,0xdf,0x00,0xd8,0x00,0xde, 0x06,0x9b,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0x9f,0x06,0xa0,0x06,0xa1,0x06,0xa2,0x06,0xa3,0x06,0xa4,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x07,0x44,0x07,0x45,0x07,0x46,0x07,0x47,0x07,0x48,0x07,0x49,0x07,0x4a,0x07,0x4b,0x07,0x4c,0x07,0x4d,0x07,0x4e,0x07,0x4f,0x07,0x50,0x07,0x51,0x07,0x52, 0x07,0x53,0x07,0x54,0x02,0x46,0x02,0x47,0x04,0x62,0x04,0x63,0x04,0x64,0x04,0x65,0x04,0x66,0x04,0x67,0x04,0x68,0x02,0x44,0x04,0x69,0x04,0x6a,0x04,0x6b,0x04,0x6c,0x04,0x6d,0x04,0x6e,0x04,0x6f,0x04,0x70,0x04,0x71,0x04,0x72,0x04,0x73,0x04,0x74,0x04,0x75,0x04,0x76,0x04,0x77,0x04,0x78,0x04,0x79,0x04,0x7a,0x04,0x7b,0x04,0x7c, 0x04,0x7d,0x04,0x7e,0x04,0x7f,0x04,0x80,0x04,0x81,0x02,0x45,0x04,0x82,0x04,0x83,0x04,0x84,0x04,0x85,0x04,0x86,0x04,0x87,0x04,0x88,0x04,0x89,0x04,0x8a,0x04,0x8b,0x04,0x8c,0x04,0x8d,0x04,0x8e,0x04,0x8f,0x04,0x90,0x04,0x91,0x04,0x92,0x04,0x93,0x04,0x94,0x04,0x95,0x04,0x96,0x04,0x97,0x04,0x98,0x04,0x99,0x04,0x9a,0x04,0x9b, 0x04,0x9c,0x04,0x9d,0x04,0x9e,0x04,0x9f,0x04,0xa0,0x04,0xa1,0x04,0xa2,0x04,0xa3,0x04,0xa4,0x04,0xa5,0x04,0xa6,0x04,0xa7,0x04,0xa8,0x04,0xa9,0x04,0xaa,0x04,0xab,0x04,0xac,0x07,0x39,0x07,0x55,0x07,0x56,0x07,0x57,0x07,0x58,0x07,0x59,0x07,0x5a,0x07,0x5b,0x07,0x5c,0x07,0xec,0x07,0xed,0x07,0xee,0x07,0xef,0x07,0xf0,0x07,0x5d, 0x07,0x5e,0x07,0x5f,0x04,0xad,0x04,0xae,0x04,0xaf,0x06,0x66,0x06,0x67,0x06,0x68,0x06,0x69,0x06,0x6a,0x06,0x6b,0x06,0x6c,0x06,0x6d,0x06,0x6e,0x06,0x6f,0x06,0x70,0x06,0x71,0x06,0x72,0x13,0x46,0x13,0x47,0x13,0x48,0x13,0x49,0x06,0x73,0x06,0x74,0x13,0x4a,0x13,0x4b,0x06,0x75,0x0a,0xcd,0x0a,0xce,0x0a,0xcf,0x01,0x9e,0x14,0x19, 0x01,0x9f,0x01,0xa0,0x01,0xa1,0x01,0x8b,0x01,0xa2,0x01,0xa3,0x01,0xa4,0x01,0xa6,0x01,0xa7,0x01,0xa8,0x01,0xa9,0x01,0xaa,0x01,0x2c,0x00,0xa9,0x01,0xab,0x01,0xac,0x01,0xad,0x01,0x2d,0x01,0xae,0x01,0xaf,0x01,0xb0,0x01,0xb1,0x01,0xb2,0x01,0xb3,0x01,0xb4,0x01,0xb5,0x01,0xb6,0x01,0xb7,0x01,0xb8,0x01,0xb9,0x01,0x2e,0x01,0xba, 0x01,0xbb,0x01,0xbc,0x01,0xbd,0x01,0xbe,0x01,0xbf,0x01,0xc0,0x01,0xc1,0x01,0xc2,0x01,0xc3,0x01,0x2f,0x01,0xc4,0x01,0xc5,0x01,0x30,0x01,0x31,0x01,0xc6,0x01,0xc7,0x01,0xc8,0x01,0xc9,0x01,0xca,0x01,0xcb,0x01,0xcc,0x01,0xcd,0x01,0xce,0x01,0xcf,0x02,0x37,0x01,0xd0,0x01,0xd1,0x01,0x32,0x01,0x33,0x01,0xd2,0x01,0x34,0x01,0xd3, 0x01,0xd4,0x01,0xd5,0x01,0xd6,0x01,0xd7,0x01,0xd8,0x01,0xd9,0x01,0xda,0x13,0x4c,0x05,0xb3,0x05,0xb4,0x05,0xb5,0x05,0xb6,0x05,0xb7,0x05,0xb8,0x05,0xb9,0x05,0xba,0x05,0xbb,0x05,0xbc,0x05,0xbd,0x05,0xbe,0x05,0xbf,0x05,0xc0,0x05,0xc1,0x05,0xc2,0x05,0xc3,0x05,0xc4,0x05,0xc5,0x05,0xc6,0x05,0xc7,0x05,0xc8,0x05,0xc9,0x05,0xca, 0x05,0xcb,0x05,0xcc,0x05,0xcd,0x05,0xce,0x05,0xcf,0x05,0xd0,0x05,0xd1,0x05,0xd2,0x05,0xd3,0x05,0xd4,0x05,0xd5,0x05,0xd6,0x05,0xd7,0x05,0xd8,0x05,0xd9,0x07,0x60,0x07,0x61,0x08,0xc0,0x08,0xc1,0x08,0xc2,0x07,0xf1,0x07,0xf2,0x07,0xf3,0x07,0xf4,0x02,0xb1,0x01,0xdb,0x01,0xdc,0x01,0xdd,0x01,0xde,0x01,0xdf,0x02,0xb5,0x01,0xe0, 0x02,0xb6,0x01,0xe1,0x01,0xe2,0x01,0xe3,0x01,0xe4,0x02,0xb3,0x01,0xe5,0x01,0xe6,0x01,0xe7,0x01,0xe8,0x01,0xe9,0x01,0xea,0x01,0xeb,0x01,0xec,0x01,0xed,0x01,0xee,0x01,0xef,0x01,0xf0,0x01,0xf1,0x01,0xf2,0x01,0xf3,0x01,0xf4,0x01,0xf5,0x01,0xf6,0x01,0xf7,0x01,0xf8,0x01,0xf9,0x01,0xfa,0x01,0xfb,0x01,0xfc,0x01,0xfd,0x01,0xfe, 0x01,0xff,0x02,0x00,0x02,0x01,0x02,0x02,0x02,0x03,0x02,0x04,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x08,0x02,0x09,0x02,0x0a,0x02,0x0b,0x02,0x0c,0x02,0x0d,0x02,0x0e,0x02,0x0f,0x02,0x10,0x02,0x11,0x02,0x12,0x02,0x13,0x02,0x14,0x02,0x15,0x02,0x16,0x02,0x17,0x02,0x18,0x02,0x19,0x02,0x1a,0x02,0x1b,0x02,0x1c,0x02,0x1d,0x02,0x1e, 0x02,0x1f,0x02,0x20,0x02,0x21,0x02,0x22,0x02,0x23,0x02,0x24,0x02,0x25,0x02,0x26,0x02,0xb2,0x02,0x27,0x02,0x28,0x02,0x29,0x02,0x2a,0x02,0x2b,0x02,0xb7,0x02,0x2c,0x02,0xb8,0x02,0x2d,0x02,0x2e,0x02,0x2f,0x02,0x30,0x02,0xb4,0x02,0x31,0x02,0x32,0x05,0xda,0x05,0xdb,0x05,0xdc,0x05,0xdd,0x05,0xde,0x05,0xdf,0x05,0xe0,0x05,0xe1, 0x05,0xe2,0x05,0xe3,0x05,0xe4,0x05,0xe5,0x05,0xe6,0x05,0xe7,0x05,0xe8,0x05,0xe9,0x05,0xea,0x05,0xeb,0x05,0xec,0x05,0xed,0x05,0xee,0x05,0xef,0x05,0xf0,0x05,0xf1,0x05,0xf2,0x05,0xf3,0x05,0xf4,0x05,0xf5,0x05,0xf6,0x05,0xf7,0x05,0xf8,0x05,0xf9,0x05,0xfa,0x05,0xfb,0x05,0xfc,0x05,0xfd,0x05,0xfe,0x05,0xff,0x06,0x00,0x0b,0x1c, 0x06,0x01,0x06,0x02,0x08,0xb4,0x08,0xb5,0x06,0x03,0x06,0x04,0x06,0x05,0x06,0x06,0x02,0x33,0x02,0x34,0x02,0xb9,0x02,0xba,0x06,0x07,0x06,0x08,0x02,0xbb,0x02,0xbc,0x06,0x09,0x06,0x0a,0x02,0xbd,0x02,0xbe,0x02,0xbf,0x02,0xc0,0x06,0x0b,0x06,0x0c,0x06,0x0d,0x06,0x0e,0x02,0xc1,0x02,0xc2,0x06,0x0f,0x06,0x10,0x06,0x11,0x06,0x12, 0x06,0x13,0x06,0x14,0x06,0x15,0x06,0x16,0x06,0x17,0x06,0x18,0x02,0xc3,0x02,0xc4,0x02,0xc5,0x02,0xc6,0x02,0xc7,0x02,0xc8,0x06,0x19,0x06,0x1a,0x06,0x1b,0x06,0x1c,0x02,0xc9,0x02,0xca,0x02,0xcb,0x02,0xcc,0x06,0x1d,0x06,0x1e,0x06,0x1f,0x06,0x20,0x06,0x21,0x06,0x22,0x06,0x23,0x06,0x24,0x06,0x25,0x08,0xb6,0x08,0xb7,0x06,0x26, 0x06,0x27,0x08,0xb8,0x08,0xb9,0x06,0x28,0x06,0x29,0x08,0xba,0x08,0xbb,0x0a,0xd0,0x06,0x2a,0x06,0x2b,0x06,0x2c,0x06,0x2d,0x06,0x2e,0x06,0x2f,0x06,0x30,0x06,0x31,0x06,0x32,0x06,0x33,0x06,0x34,0x06,0x35,0x06,0x36,0x06,0x37,0x06,0x38,0x06,0x39,0x06,0x3a,0x06,0x3b,0x06,0x3c,0x06,0x3d,0x06,0x3e,0x06,0x3f,0x06,0x40,0x06,0x41, 0x02,0xcf,0x02,0xd0,0x06,0x42,0x06,0x43,0x06,0x44,0x06,0x45,0x06,0x46,0x06,0x47,0x06,0x48,0x06,0x49,0x06,0x4a,0x06,0x4b,0x06,0x4c,0x06,0x4d,0x07,0xf5,0x07,0xf6,0x06,0x4e,0x06,0x4f,0x0a,0xd1,0x0a,0xd2,0x0a,0xd3,0x0a,0xd4,0x0a,0xd5,0x0a,0xd6,0x06,0x50,0x06,0x51,0x06,0x52,0x06,0x53,0x06,0x54,0x06,0x55,0x06,0x56,0x06,0x57, 0x06,0x58,0x06,0x59,0x06,0x5a,0x06,0x5b,0x06,0x5c,0x06,0x5d,0x06,0x5e,0x06,0x5f,0x0a,0xd7,0x0a,0xd8,0x0a,0xd9,0x0a,0xda,0x13,0x4d,0x13,0x4e,0x13,0x4f,0x13,0x50,0x13,0x51,0x13,0x52,0x0b,0x1d,0x0b,0x1e,0x0b,0x1f,0x0b,0x20,0x13,0x53,0x13,0x54,0x13,0x55,0x13,0x56,0x13,0x57,0x13,0x58,0x14,0x1a,0x14,0x1b,0x13,0x59,0x13,0x5a, 0x14,0x1c,0x14,0x1d,0x14,0x1e,0x14,0x1f,0x14,0x20,0x14,0x21,0x14,0x22,0x14,0x23,0x11,0x8a,0x11,0x8b,0x0f,0xc4,0x0b,0xbf,0x0b,0xc0,0x0b,0xc1,0x0b,0xc2,0x0b,0xc3,0x0b,0xc4,0x0b,0xc5,0x0b,0xc6,0x0b,0xc7,0x0b,0xc8,0x0b,0xc9,0x0b,0xca,0x0b,0xcb,0x0b,0xcc,0x0b,0xcd,0x0b,0xce,0x0b,0xcf,0x0b,0xd0,0x0b,0xd1,0x0b,0xd2,0x0b,0xd3, 0x0b,0xd4,0x0b,0xd5,0x0b,0xd6,0x0b,0xd7,0x0b,0xd8,0x0b,0xd9,0x0b,0xda,0x0b,0xdb,0x0b,0xdc,0x0b,0xdd,0x0b,0x53,0x0b,0x54,0x0b,0x55,0x0b,0x56,0x0b,0x57,0x0b,0x58,0x0b,0x59,0x0b,0x5a,0x0b,0x5b,0x0b,0x5c,0x0b,0xde,0x0b,0x5d,0x0b,0x5e,0x0b,0x5f,0x0b,0x60,0x0b,0x61,0x0b,0x62,0x0b,0x63,0x0b,0x64,0x0b,0x65,0x0b,0x66,0x0b,0x67, 0x0b,0xdf,0x0b,0xb9,0x14,0xdf,0x0b,0x83,0x0b,0x84,0x0b,0x85,0x0b,0x86,0x0b,0x87,0x0a,0x44,0x0a,0x45,0x0a,0x46,0x0a,0x47,0x13,0x45,0x14,0x03,0x0e,0x13,0x0e,0x14,0x0e,0x16,0x0e,0x17,0x0e,0x18,0x0a,0x6a,0x08,0xf8,0x0a,0x49,0x0a,0x48,0x0a,0x4a,0x0a,0x4b,0x0a,0x4c,0x0a,0x4d,0x0a,0x4e,0x0a,0x4f,0x0a,0x53,0x0e,0x1a,0x0e,0x1b, 0x0e,0x1c,0x0e,0x1d,0x0e,0x1e,0x09,0x05,0x13,0x92,0x0a,0x6b,0x09,0x06,0x0e,0x20,0x09,0x07,0x09,0x08,0x09,0x09,0x09,0x0a,0x09,0x0b,0x09,0x0c,0x09,0x0d,0x09,0x0e,0x09,0x0f,0x09,0x10,0x09,0x11,0x09,0x12,0x09,0x13,0x09,0x14,0x09,0x15,0x09,0x16,0x09,0x17,0x09,0x18,0x09,0x19,0x09,0x1a,0x09,0x1b,0x09,0x1c,0x09,0x1d,0x09,0x1e, 0x09,0x1f,0x09,0x20,0x0e,0x3f,0x0e,0x43,0x0e,0x47,0x0e,0x4b,0x0e,0x4f,0x09,0x21,0x09,0x22,0x09,0x23,0x09,0x24,0x09,0x25,0x09,0x26,0x09,0x27,0x09,0x28,0x09,0x29,0x09,0x2a,0x09,0x2b,0x09,0x2c,0x09,0x2d,0x09,0x2e,0x09,0x2f,0x09,0x30,0x09,0x31,0x09,0x32,0x09,0x33,0x09,0x37,0x09,0x7e,0x09,0x7f,0x0a,0x50,0x0a,0x51,0x0a,0x52, 0x0a,0x6c,0x0a,0x6d,0x0a,0x6e,0x0a,0x6f,0x0a,0x70,0x0a,0x71,0x09,0x77,0x08,0xd7,0x08,0xd8,0x08,0xd9,0x08,0xda,0x08,0xdb,0x08,0xdc,0x08,0xdd,0x08,0xde,0x08,0xdf,0x08,0xe0,0x09,0x6a,0x09,0x03,0x0e,0x6d,0x09,0x6b,0x09,0x3e,0x09,0x7c,0x09,0x73,0x09,0x80,0x09,0x82,0x09,0x84,0x0e,0x73,0x09,0x86,0x09,0x88,0x09,0x89,0x09,0x8a, 0x09,0x5b,0x09,0x8c,0x09,0x8e,0x09,0x90,0x09,0x92,0x09,0x40,0x09,0x94,0x09,0x96,0x09,0x98,0x09,0x9b,0x09,0x9e,0x09,0xa1,0x09,0xa4,0x09,0x42,0x09,0xa7,0x09,0x5d,0x09,0xaa,0x09,0xab,0x09,0xac,0x09,0xad,0x09,0xae,0x09,0xaf,0x09,0xb0,0x09,0xb1,0x09,0x5e,0x09,0xb2,0x09,0xb3,0x09,0xb4,0x09,0xb5,0x09,0xb6,0x09,0xb7,0x09,0x45, 0x09,0xb8,0x09,0xb9,0x09,0xbb,0x09,0xbd,0x09,0xbf,0x09,0xc1,0x09,0xc3,0x09,0xc4,0x09,0xc8,0x09,0xc9,0x09,0xcc,0x09,0x6c,0x09,0xcf,0x09,0xd2,0x09,0xd5,0x09,0xd6,0x09,0x46,0x09,0xd7,0x09,0xd9,0x09,0xdb,0x09,0xdd,0x09,0xdf,0x09,0x48,0x09,0xe1,0x09,0xe3,0x09,0xe5,0x09,0xe7,0x09,0xe9,0x09,0xeb,0x09,0xed,0x09,0xef,0x09,0xf1, 0x09,0xf3,0x09,0x5f,0x09,0xf5,0x09,0xf6,0x09,0xf8,0x08,0xf1,0x09,0xfa,0x09,0x4e,0x09,0x60,0x09,0x63,0x09,0x64,0x09,0xfd,0x09,0xfe,0x09,0xff,0x0a,0x00,0x0a,0x01,0x0a,0x02,0x0a,0x03,0x0a,0x04,0x09,0x4a,0x0a,0x05,0x0a,0x07,0x0a,0x0a,0x0a,0x0b,0x0a,0x0d,0x09,0x65,0x09,0x67,0x09,0x69,0x0b,0x19,0x09,0x74,0x0a,0x0f,0x0a,0x10, 0x09,0x75,0x0a,0x11,0x0a,0x12,0x0a,0x13,0x0a,0x14,0x0a,0x15,0x0a,0x16,0x0a,0x17,0x0a,0x18,0x0a,0x19,0x0a,0x1a,0x0a,0x1b,0x0a,0x1c,0x0a,0x1d,0x0a,0x1e,0x0a,0x1f,0x0a,0x20,0x0a,0x21,0x0a,0x22,0x0e,0xeb,0x0a,0x23,0x0a,0x54,0x0a,0x56,0x09,0x4f,0x09,0x50,0x09,0x51,0x09,0x52,0x09,0x53,0x09,0x54,0x09,0x55,0x09,0x56,0x09,0x57, 0x09,0x58,0x0a,0x24,0x0a,0x26,0x0a,0x28,0x0a,0x2c,0x0a,0x2d,0x0a,0x58,0x0a,0x72,0x0a,0x74,0x0a,0x76,0x0a,0x78,0x0a,0x7a,0x0a,0x7c,0x0a,0x7e,0x0a,0x80,0x0a,0x83,0x0a,0x86,0x0a,0x87,0x0a,0x88,0x0a,0x89,0x0a,0x8b,0x0a,0x8f,0x0a,0x93,0x0a,0x97,0x0a,0x9a,0x0a,0x9d,0x0a,0xa0,0x0a,0xa3,0x0a,0xa6,0x0a,0xa8,0x0a,0xaa,0x0a,0xac, 0x0a,0xae,0x0a,0xb0,0x0a,0xb4,0x0a,0xb5,0x0a,0xb6,0x0f,0x16,0x0f,0x1a,0x0f,0x1e,0x0f,0x22,0x0f,0x24,0x0f,0x28,0x0f,0x2a,0x0f,0x2c,0x0f,0x30,0x0f,0x34,0x0f,0x38,0x0f,0x3a,0x0f,0x3c,0x0f,0x3e,0x0f,0x40,0x0f,0x44,0x0f,0x48,0x0f,0x4c,0x13,0x02,0x14,0x04,0x13,0x04,0x13,0x08,0x13,0x0c,0x13,0x10,0x13,0x14,0x13,0x18,0x13,0x1c, 0x13,0x20,0x13,0x24,0x13,0x26,0x13,0x28,0x14,0x08,0x14,0x09,0x14,0x0b,0x14,0x0f,0x14,0x13,0x14,0x15,0x14,0x53,0x14,0x54,0x14,0x5d,0x14,0x5e,0x14,0x5f,0x14,0x60,0x14,0x61,0x14,0x62,0x14,0x63,0x14,0x64,0x14,0x65,0x14,0x66,0x14,0x67,0x14,0x68,0x14,0x69,0x14,0x6a,0x14,0x6b,0x14,0x6c,0x13,0x2a,0x13,0x2b,0x13,0x2c,0x13,0x2d, 0x13,0x2e,0x13,0x2f,0x13,0x30,0x13,0x31,0x13,0x32,0x13,0x33,0x13,0x34,0x13,0x35,0x13,0x36,0x13,0x37,0x13,0x38,0x13,0x39,0x13,0x3a,0x13,0x3b,0x13,0x3c,0x13,0x3d,0x13,0x3e,0x13,0x3f,0x13,0x40,0x13,0x41,0x13,0x42,0x13,0x43,0x13,0x44,0x14,0x17,0x0c,0x08,0x0c,0x09,0x0c,0x0a,0x0c,0x0b,0x0c,0x0c,0x0c,0x0d,0x0c,0x0e,0x0c,0x0f, 0x0c,0x10,0x0c,0x11,0x0c,0x12,0x0c,0x13,0x0c,0x14,0x0c,0x15,0x0c,0x16,0x0c,0x17,0x0c,0x18,0x0c,0x19,0x0c,0x1a,0x0c,0x1b,0x0c,0x1c,0x0c,0x1d,0x0c,0x1e,0x0c,0x1f,0x0c,0x20,0x0c,0x21,0x0c,0x22,0x0c,0x23,0x0c,0x24,0x0c,0x25,0x0c,0x26,0x0c,0x27,0x0c,0x28,0x0c,0x29,0x0c,0x2a,0x0c,0x2b,0x0c,0x2c,0x0c,0x2d,0x0c,0x2e,0x0c,0x2f, 0x0c,0x30,0x0c,0x31,0x0c,0x32,0x0c,0x33,0x0c,0x34,0x0f,0xc7,0x0f,0xc8,0x0f,0xc9,0x07,0x62,0x07,0x63,0x07,0x64,0x07,0x65,0x07,0x66,0x07,0x67,0x07,0x68,0x07,0x69,0x07,0x6a,0x07,0x6b,0x07,0x6c,0x07,0x6d,0x07,0x6e,0x07,0x6f,0x07,0x70,0x07,0x71,0x07,0x72,0x07,0x73,0x07,0x74,0x07,0x75,0x07,0x76,0x07,0x77,0x07,0x78,0x07,0x79, 0x07,0x7a,0x07,0x7b,0x07,0x7c,0x07,0x7d,0x07,0x7e,0x07,0x7f,0x07,0x80,0x07,0x81,0x07,0x82,0x07,0x83,0x07,0x84,0x07,0x85,0x07,0x86,0x07,0x87,0x07,0x88,0x07,0x89,0x07,0x8a,0x07,0x8b,0x07,0x8c,0x07,0x8d,0x07,0x8e,0x07,0x8f,0x07,0x90,0x07,0x91,0x07,0x92,0x07,0x93,0x07,0x94,0x07,0x95,0x07,0x96,0x07,0x97,0x07,0x98,0x07,0x99, 0x07,0x9a,0x07,0x9b,0x07,0x9c,0x07,0x9d,0x07,0x9e,0x07,0x9f,0x07,0xa0,0x07,0xa1,0x07,0xa2,0x07,0xa3,0x07,0xa4,0x07,0xa5,0x07,0xa6,0x07,0xa7,0x07,0xa8,0x07,0xa9,0x07,0xaa,0x07,0xab,0x07,0xac,0x07,0xad,0x07,0xae,0x07,0xaf,0x07,0xb0,0x07,0xb1,0x07,0xb2,0x07,0xb3,0x07,0xb4,0x07,0xb5,0x07,0xb6,0x07,0xb7,0x07,0xb8,0x07,0xb9, 0x07,0xba,0x07,0xbb,0x07,0xbc,0x07,0xbd,0x07,0xbe,0x07,0xbf,0x07,0xc0,0x07,0xc1,0x07,0xc2,0x07,0xc3,0x07,0xc4,0x07,0xc5,0x07,0xc6,0x07,0xc7,0x07,0xc8,0x07,0xc9,0x07,0xca,0x07,0xcb,0x07,0xcc,0x07,0xd1,0x07,0xf7,0x07,0xf8,0x07,0xf9,0x07,0xfa,0x07,0xfb,0x07,0xfc,0x07,0xfd,0x07,0xfe,0x07,0xff,0x08,0x00,0x08,0x01,0x08,0x02, 0x08,0x03,0x08,0x04,0x08,0x05,0x08,0x07,0x08,0x08,0x08,0x09,0x08,0x0a,0x08,0x0b,0x08,0x0c,0x08,0x0d,0x08,0x0e,0x08,0x0f,0x08,0x10,0x08,0x11,0x08,0x12,0x08,0x13,0x08,0x14,0x08,0x15,0x08,0x16,0x08,0x17,0x08,0x18,0x08,0x19,0x08,0x1a,0x08,0x1b,0x08,0x1c,0x08,0x1d,0x08,0x1e,0x08,0x1f,0x08,0x20,0x08,0x21,0x08,0x22,0x08,0x23, 0x08,0x24,0x08,0x25,0x08,0x26,0x08,0x27,0x08,0x28,0x08,0x29,0x08,0x2a,0x08,0x2b,0x08,0x2c,0x08,0x2d,0x08,0x2e,0x08,0x2f,0x08,0x30,0x08,0x31,0x08,0x32,0x08,0x33,0x08,0x34,0x08,0x35,0x08,0x36,0x08,0x37,0x08,0x38,0x08,0x39,0x08,0x3a,0x08,0x3b,0x08,0x3c,0x08,0x3d,0x08,0x3e,0x08,0x3f,0x08,0x40,0x08,0x41,0x08,0x42,0x08,0x43, 0x08,0x44,0x08,0x45,0x08,0x46,0x08,0x47,0x08,0x48,0x08,0x49,0x08,0x4a,0x08,0x4b,0x08,0x4c,0x08,0x4d,0x08,0x4e,0x08,0x4f,0x0a,0xdb,0x0a,0xdc,0x0a,0xdd,0x0a,0xde,0x0a,0xdf,0x0a,0xe0,0x0a,0xe1,0x0a,0xe2,0x0a,0xe3,0x02,0xe3,0x02,0xe4,0x02,0xe5,0x02,0xe6,0x02,0xe7,0x02,0xe8,0x02,0xe9,0x02,0xea,0x02,0xeb,0x02,0xec,0x02,0xed, 0x02,0xee,0x02,0xef,0x02,0xf0,0x02,0xf1,0x02,0xf2,0x02,0xf3,0x02,0xf4,0x02,0xf5,0x02,0xf6,0x02,0xf7,0x02,0xf8,0x02,0xf9,0x02,0xfa,0x02,0xfb,0x02,0xfc,0x02,0xfd,0x02,0xfe,0x02,0xff,0x03,0x00,0x03,0x01,0x03,0x02,0x03,0x03,0x03,0x04,0x03,0x05,0x03,0x06,0x03,0x07,0x03,0x08,0x03,0x09,0x03,0x0a,0x03,0x0b,0x03,0x0c,0x03,0x0d, 0x03,0x0e,0x03,0x0f,0x03,0x10,0x03,0x11,0x03,0x12,0x03,0x13,0x03,0x14,0x03,0x15,0x03,0x16,0x03,0x17,0x03,0x18,0x03,0x19,0x03,0x1a,0x03,0x1b,0x03,0x1c,0x03,0x1d,0x03,0x1e,0x03,0x1f,0x03,0x20,0x03,0x21,0x03,0x22,0x03,0x23,0x03,0x24,0x03,0x25,0x03,0x26,0x03,0x27,0x03,0x28,0x03,0x29,0x03,0x2a,0x03,0x2b,0x03,0x2c,0x03,0x2d, 0x03,0x2e,0x03,0x2f,0x03,0x30,0x03,0x31,0x03,0x32,0x03,0x33,0x03,0x34,0x03,0x35,0x03,0x36,0x03,0x37,0x03,0x38,0x03,0x39,0x03,0x3a,0x03,0x3b,0x03,0x3c,0x03,0x3d,0x03,0x3e,0x03,0x3f,0x03,0x40,0x03,0x41,0x03,0x42,0x03,0x43,0x03,0x44,0x03,0x45,0x03,0x46,0x03,0x47,0x03,0x48,0x03,0x49,0x03,0x4a,0x03,0x4b,0x03,0x4c,0x03,0x4d, 0x03,0x4e,0x03,0x4f,0x03,0x50,0x03,0x51,0x03,0x52,0x03,0x53,0x03,0x54,0x03,0x55,0x03,0x56,0x03,0x57,0x03,0x58,0x03,0x59,0x03,0x5a,0x03,0x5b,0x03,0x5c,0x03,0x5d,0x03,0x5e,0x03,0x5f,0x03,0x60,0x03,0x61,0x03,0x62,0x01,0x8c,0x01,0x8d,0x01,0x8e,0x01,0x8f,0x01,0x90,0x01,0x91,0x03,0x63,0x03,0x64,0x03,0x65,0x03,0x66,0x03,0x67, 0x03,0x68,0x03,0x69,0x03,0x6a,0x03,0x6b,0x03,0x6c,0x03,0x6d,0x03,0x6e,0x03,0x6f,0x03,0x70,0x03,0x71,0x03,0x72,0x03,0x73,0x03,0x74,0x03,0x75,0x03,0x76,0x03,0x77,0x03,0x78,0x13,0x5b,0x13,0x5c,0x0b,0x21,0x13,0x5d,0x02,0x57,0x02,0x58,0x02,0x59,0x02,0x5a,0x02,0x5b,0x02,0x5c,0x02,0x5d,0x02,0x5e,0x02,0x5f,0x02,0x60,0x02,0x61, 0x02,0x62,0x02,0x63,0x02,0x64,0x02,0x65,0x02,0x66,0x02,0x67,0x02,0x68,0x02,0x69,0x02,0x6a,0x02,0x6b,0x02,0x6c,0x02,0x6d,0x02,0x6e,0x02,0x6f,0x02,0x70,0x02,0x71,0x02,0x72,0x02,0x73,0x02,0x74,0x02,0x75,0x02,0x76,0x02,0x77,0x02,0x78,0x02,0x79,0x02,0x7a,0x02,0x7b,0x02,0x7c,0x02,0x7d,0x02,0x7e,0x02,0x7f,0x02,0x80,0x02,0x81, 0x02,0x82,0x02,0x83,0x02,0x84,0x02,0x85,0x02,0x86,0x02,0x87,0x02,0x88,0x02,0x89,0x02,0x8a,0x02,0x8b,0x02,0x8c,0x02,0x8d,0x02,0x8e,0x02,0x8f,0x02,0x90,0x02,0x91,0x02,0x92,0x02,0x93,0x02,0x94,0x02,0x95,0x02,0x96,0x02,0x97,0x02,0x98,0x02,0x99,0x02,0x9a,0x02,0x9b,0x02,0x9c,0x02,0x9d,0x02,0x9e,0x02,0x9f,0x02,0xa0,0x02,0xa1, 0x02,0xa2,0x02,0xa3,0x02,0xa4,0x02,0xa5,0x02,0xa6,0x02,0xa7,0x02,0xa8,0x01,0x92,0x01,0x93,0x02,0xa9,0x02,0xaa,0x02,0xab,0x02,0xac,0x02,0xad,0x02,0xae,0x13,0x5e,0x13,0x5f,0x13,0x60,0x13,0x61,0x13,0x62,0x13,0x63,0x03,0x79,0x03,0x7a,0x03,0x7b,0x03,0x7c,0x03,0x7d,0x03,0x7e,0x03,0x7f,0x03,0x80,0x03,0x81,0x03,0x82,0x03,0x83, 0x03,0x84,0x03,0x85,0x03,0x86,0x03,0x87,0x03,0x88,0x03,0x89,0x03,0x8a,0x03,0x8b,0x03,0x8c,0x03,0x8d,0x03,0x8e,0x0a,0xfe,0x0a,0xff,0x0b,0x00,0x0b,0x01,0x0b,0x02,0x0b,0x03,0x0b,0x04,0x0b,0x05,0x0b,0x06,0x11,0x86,0x0b,0x07,0x0b,0x08,0x08,0xc3,0x08,0xc4,0x08,0xc5,0x08,0xc6,0x00,0x10,0x11,0x99,0x08,0xbc,0x00,0xb2,0x00,0xb3, 0x02,0x35,0x11,0x87,0x01,0x35,0x00,0xb6,0x00,0xb7,0x00,0xc4,0x01,0x94,0x00,0xb4,0x00,0xb5,0x00,0xc5,0x08,0xbd,0x00,0x82,0x00,0xc2,0x00,0x87,0x0b,0x23,0x0b,0x24,0x0b,0x25,0x0b,0x26,0x0b,0x27,0x0b,0x28,0x0b,0x29,0x0b,0x09,0x00,0xc6,0x01,0x3c,0x01,0x3d,0x08,0xbe,0x01,0x36,0x11,0x85,0x01,0x95,0x08,0x50,0x0b,0x0a,0x08,0x99, 0x08,0x95,0x08,0x9a,0x08,0x9b,0x08,0x9c,0x08,0x9d,0x08,0x9e,0x08,0x9f,0x08,0xa0,0x08,0xa1,0x08,0xa2,0x08,0xa3,0x08,0xa4,0x01,0x37,0x08,0xa5,0x08,0xa6,0x08,0xa7,0x08,0xa8,0x08,0xa9,0x08,0xaa,0x08,0xab,0x08,0xac,0x08,0xad,0x08,0xae,0x08,0xaf,0x08,0xb0,0x08,0xb1,0x08,0xb2,0x08,0xb3,0x08,0x51,0x08,0x52,0x08,0x53,0x08,0x54, 0x08,0x55,0x14,0x2e,0x14,0x2f,0x14,0x30,0x14,0x31,0x14,0x32,0x14,0x33,0x14,0x34,0x14,0x35,0x07,0xd2,0x07,0xd3,0x07,0xd4,0x00,0xf6,0x01,0x96,0x07,0xd5,0x07,0xd6,0x01,0x38,0x07,0xd7,0x07,0xd8,0x07,0xd9,0x07,0xda,0x00,0xbd,0x07,0xdb,0x07,0xdc,0x07,0xdd,0x07,0xde,0x07,0xdf,0x08,0x56,0x08,0x57,0x08,0x58,0x08,0x59,0x11,0x80, 0x11,0x81,0x0c,0xb7,0x0c,0xb6,0x11,0xa3,0x14,0x2a,0x13,0x91,0x13,0x90,0x14,0x2c,0x14,0x2d,0x02,0x36,0x07,0xe0,0x12,0xe2,0x12,0xe3,0x12,0xe4,0x0b,0x2a,0x0b,0x2b,0x12,0xe5,0x12,0xe6,0x12,0xe7,0x12,0xe8,0x12,0xe9,0x12,0xea,0x01,0x98,0x01,0x99,0x01,0x9a,0x01,0x9b,0x12,0xeb,0x12,0xf0,0x12,0xf1,0x12,0xf2,0x12,0xf3,0x12,0xf4, 0x12,0xf5,0x12,0xf6,0x12,0xf7,0x12,0xf8,0x12,0xf9,0x0a,0xe6,0x12,0xfa,0x12,0xfb,0x12,0xfc,0x12,0xfd,0x12,0xfe,0x00,0x9a,0x00,0xee,0x01,0x02,0x00,0xa6,0x00,0x93,0x0b,0x32,0x00,0x90,0x08,0xbf,0x0b,0x36,0x01,0x40,0x01,0x41,0x01,0x42,0x0b,0x37,0x00,0xb9,0x0b,0x3c,0x0a,0x43,0x0b,0x3f,0x11,0x88,0x08,0x83,0x08,0x84,0x08,0x85, 0x08,0x86,0x08,0x87,0x08,0x88,0x08,0x89,0x08,0x8a,0x08,0x8b,0x13,0x8f,0x0a,0xe7,0x0a,0xe8,0x0a,0xe9,0x0a,0xea,0x0a,0xeb,0x0a,0xec,0x0a,0xed,0x0a,0xee,0x0a,0xef,0x0a,0xf0,0x0a,0xf1,0x0a,0xf2,0x0a,0xf3,0x0b,0x43,0x13,0x93,0x13,0x94,0x13,0x64,0x0b,0x44,0x0b,0x45,0x0b,0x46,0x0a,0xf4,0x0a,0xf5,0x0a,0xf6,0x0a,0xf7,0x13,0x65, 0x13,0x66,0x13,0x67,0x13,0x68,0x13,0x69,0x13,0x6a,0x13,0x6b,0x13,0x6c,0x11,0x30,0x11,0x31,0x11,0x32,0x11,0x33,0x11,0x34,0x11,0x35,0x11,0x36,0x11,0x37,0x11,0x38,0x11,0x39,0x11,0x3a,0x11,0x3b,0x11,0x3c,0x11,0x3d,0x11,0x3e,0x11,0x3f,0x11,0x40,0x11,0x41,0x11,0x42,0x11,0x43,0x11,0x44,0x11,0x45,0x11,0x46,0x11,0x47,0x11,0x48, 0x11,0x49,0x11,0x4a,0x11,0x4b,0x11,0x4c,0x11,0x4d,0x11,0x4e,0x11,0x4f,0x11,0x50,0x11,0x51,0x11,0x52,0x11,0x53,0x11,0x54,0x11,0x55,0x11,0x56,0x11,0x57,0x11,0x58,0x11,0x59,0x11,0x5a,0x11,0x5b,0x11,0x5c,0x11,0x5d,0x11,0x5e,0x11,0x5f,0x11,0x60,0x11,0x61,0x11,0x62,0x11,0x63,0x13,0x77,0x13,0x78,0x13,0x79,0x13,0x7a,0x13,0x7b, 0x13,0x7c,0x13,0x7d,0x13,0x7e,0x11,0x64,0x11,0x65,0x11,0x66,0x11,0x67,0x11,0x68,0x11,0x69,0x11,0x6a,0x11,0x6b,0x11,0x6c,0x11,0x6d,0x11,0x6e,0x11,0x6f,0x11,0x70,0x11,0x71,0x11,0x72,0x11,0x73,0x11,0x74,0x11,0x75,0x11,0x76,0x11,0x77,0x11,0x78,0x11,0x79,0x11,0x7a,0x11,0x7b,0x11,0x7c,0x11,0x7d,0x11,0x7e,0x11,0x7f,0x14,0x24, 0x14,0x25,0x14,0x26,0x14,0x27,0x14,0x28,0x14,0x29,0x14,0x36,0x13,0x7f,0x14,0x37,0x14,0x38,0x14,0x39,0x14,0x3a,0x14,0x3b,0x14,0x3c,0x14,0x3d,0x14,0x3e,0x13,0x80,0x13,0x81,0x13,0x82,0x13,0x83,0x13,0x84,0x13,0x85,0x13,0x86,0x13,0x87,0x13,0x88,0x13,0x89,0x13,0x8a,0x13,0x8b,0x13,0x8c,0x13,0x8d,0x13,0x8e,0x0a,0xf8,0x0a,0xf9, 0x0a,0xfa,0x0a,0xfb,0x0b,0x47,0x0b,0x48,0x0b,0x49,0x0b,0x4a,0x0b,0x4b,0x0a,0xfc,0x0a,0xfd,0x12,0x63,0x12,0x64,0x12,0x65,0x12,0x66,0x12,0x67,0x12,0x68,0x12,0x69,0x12,0x6a,0x12,0x6b,0x12,0x6c,0x12,0x6d,0x12,0x6e,0x12,0x6f,0x12,0x70,0x12,0x71,0x12,0x72,0x12,0x73,0x12,0x74,0x12,0x75,0x12,0x76,0x12,0x77,0x12,0x78,0x12,0x79, 0x12,0x7a,0x12,0x7b,0x12,0x7c,0x12,0x7d,0x12,0x7e,0x12,0x7f,0x12,0x80,0x12,0x81,0x12,0x82,0x12,0x83,0x12,0x84,0x12,0x85,0x12,0x86,0x12,0x87,0x12,0x88,0x12,0x89,0x12,0x8a,0x12,0x8b,0x12,0x8c,0x12,0x8d,0x12,0x8e,0x12,0x8f,0x12,0x90,0x12,0x91,0x12,0x92,0x12,0x93,0x12,0x94,0x12,0x95,0x12,0x96,0x12,0x97,0x12,0x98,0x12,0x99, 0x12,0x9a,0x12,0x9b,0x12,0x9c,0x12,0x9d,0x12,0x9e,0x12,0x9f,0x12,0xa0,0x12,0xa1,0x12,0xa2,0x12,0xa3,0x12,0xa4,0x12,0xa5,0x12,0xa6,0x12,0xa7,0x12,0xa8,0x12,0xa9,0x12,0xaa,0x12,0xab,0x12,0xac,0x12,0xad,0x12,0xae,0x12,0xaf,0x12,0xb0,0x12,0xb1,0x12,0xb2,0x12,0xb3,0x12,0xb4,0x12,0xb5,0x12,0xb6,0x12,0xb7,0x12,0xb8,0x12,0xb9, 0x12,0xba,0x12,0xbb,0x12,0xbc,0x12,0xbd,0x12,0xbe,0x12,0xbf,0x12,0xc0,0x12,0xc1,0x12,0xc2,0x12,0xc3,0x12,0xc4,0x12,0xc5,0x12,0xc6,0x12,0xc7,0x12,0xc8,0x0b,0x4c,0x0b,0x4d,0x0b,0x4e,0x0b,0x4f,0x0b,0x50,0x12,0xc9,0x12,0xca,0x14,0x3f,0x12,0xcb,0x12,0xcc,0x12,0xcd,0x12,0xce,0x13,0x95,0x13,0x96,0x13,0x97,0x13,0x98,0x13,0x99, 0x13,0x9a,0x13,0x9b,0x13,0x9c,0x13,0x9d,0x13,0x9e,0x13,0x9f,0x13,0xa0,0x12,0xcf,0x12,0xd0,0x12,0xd1,0x12,0xd2,0x12,0xd3,0x12,0xd4,0x12,0xd5,0x12,0xd6,0x12,0xd7,0x12,0xd8,0x12,0xd9,0x13,0xa1,0x13,0xa2,0x13,0xa3,0x14,0x40,0x13,0xa4,0x13,0xa5,0x14,0x41,0x14,0x42,0x14,0x43,0x14,0x44,0x14,0x45,0x14,0x46,0x13,0xa6,0x12,0xda, 0x12,0xdb,0x12,0xdc,0x12,0xdd,0x12,0xde,0x12,0xdf,0x12,0xe0,0x12,0xe1,0x13,0xa7,0x13,0xa8,0x13,0xa9,0x13,0xaa,0x13,0xab,0x13,0xac,0x13,0xad,0x13,0xae,0x13,0xaf,0x13,0xb0,0x13,0xb1,0x13,0xb2,0x13,0xb3,0x13,0xb4,0x13,0xb5,0x13,0xb6,0x13,0xb7,0x13,0xb8,0x13,0xb9,0x13,0xba,0x13,0xbb,0x13,0xbc,0x13,0xbd,0x13,0xbe,0x13,0xbf, 0x13,0xc0,0x13,0xc1,0x13,0xc2,0x13,0xc3,0x13,0xc4,0x13,0xc5,0x13,0xc6,0x13,0xc7,0x13,0xc8,0x13,0xc9,0x13,0xca,0x13,0xcb,0x13,0xcc,0x13,0xcd,0x13,0xce,0x13,0xcf,0x13,0xd0,0x13,0xd1,0x13,0xd2,0x13,0xd3,0x13,0xd4,0x13,0xd5,0x13,0xd6,0x14,0x47,0x14,0x48,0x14,0x49,0x14,0x4a,0x13,0xd7,0x13,0xd8,0x0d,0xbb,0x00,0xc0,0x00,0xc1, 0x0d,0xbc,0x0d,0xbd,0x14,0x4b,0x14,0x4c,0x0b,0xe0,0x0b,0xe1,0x0b,0x8c,0x0b,0x8d,0x0b,0x8e,0x0b,0x8f,0x0b,0x90,0x0b,0x91,0x0b,0x92,0x0b,0x93,0x0b,0x94,0x0b,0x95,0x0b,0x96,0x0b,0x97,0x0b,0x98,0x0b,0x99,0x0b,0x9a,0x0b,0x9b,0x0b,0x9c,0x0b,0x9d,0x0b,0x9e,0x0b,0x9f,0x0b,0xa0,0x0b,0xa1,0x0b,0xa2,0x0b,0xa3,0x0b,0xae,0x0b,0xaf, 0x0b,0xb0,0x0b,0xb1,0x0b,0xb2,0x0b,0xb3,0x0b,0xb4,0x0b,0xb5,0x0b,0xb6,0x0b,0xb7,0x09,0x80,0x09,0x81,0x09,0x8e,0x0e,0x7c,0x09,0x8f,0x0e,0x7d,0x09,0x40,0x0e,0x82,0x09,0x41,0x0e,0x83,0x09,0x96,0x0e,0x86,0x09,0x97,0x0e,0x87,0x09,0x8c,0x0e,0x7a,0x09,0x8d,0x0e,0x7b,0x09,0x94,0x0e,0x84,0x09,0x95,0x0e,0x85,0x09,0x5b,0x0e,0x78, 0x09,0x5c,0x0e,0x79,0x09,0x6c,0x0e,0xa8,0x09,0x6d,0x09,0x6e,0x09,0xd2,0x0e,0xaa,0x09,0xd3,0x09,0xd4,0x09,0xa1,0x09,0xa2,0x09,0xa3,0x0e,0x8b,0x09,0x9e,0x09,0x9f,0x09,0xa0,0x0e,0x8a,0x09,0x42,0x09,0x43,0x09,0x44,0x0e,0x8d,0x09,0xa7,0x09,0xa8,0x09,0xa9,0x0e,0x8e,0x09,0xae,0x0e,0x94,0x09,0xad,0x0e,0x93,0x09,0xaf,0x0e,0x95, 0x09,0x5d,0x0e,0x8f,0x09,0x45,0x0b,0x0e,0x09,0x5e,0x0b,0x0f,0x09,0x46,0x0e,0xb1,0x09,0x47,0x0e,0xb2,0x09,0x48,0x0e,0xbd,0x09,0x49,0x0e,0xbe,0x09,0xe7,0x0e,0xc5,0x09,0xe8,0x0e,0xc6,0x09,0xe3,0x0e,0xc1,0x09,0xe4,0x0e,0xc2,0x09,0x5f,0x0e,0xcf,0x09,0xf5,0x0e,0xd0,0x0e,0xd1,0x0e,0xd2,0x09,0x4e,0x09,0x4d,0x09,0x60,0x09,0x72, 0x09,0x61,0x09,0x62,0x08,0xf1,0x08,0xf2,0x0e,0xd7,0x0e,0xd8,0x09,0x65,0x09,0x66,0x09,0x67,0x09,0x68,0x13,0xd9,0x13,0xda,0x13,0xdb,0x13,0xdc,0x13,0xdd,0x13,0xde,0x13,0xdf,0x13,0xe0,0x13,0xe1,0x13,0xe2,0x13,0xe3,0x13,0xe4,0x13,0xe5,0x13,0xe6,0x13,0xe7,0x13,0xe8,0x09,0xdd,0x0e,0xb9,0x09,0xde,0x0e,0xba,0x0a,0x00,0x0e,0xdf, 0x09,0xff,0x0e,0xde,0x0a,0x01,0x0e,0xe0,0x09,0x89,0x0a,0x04,0x0e,0xe3,0x09,0xfe,0x0e,0xdd,0x0a,0x02,0x0e,0xe1,0x0a,0x0b,0x0a,0x0c,0x0e,0xe7,0x0e,0xe8,0x0e,0x5f,0x0e,0x60,0x10,0xfe,0x10,0xff,0x11,0x00,0x11,0x01,0x11,0x02,0x11,0x03,0x11,0x04,0x11,0x05,0x11,0x06,0x11,0x07,0x11,0x08,0x11,0x09,0x11,0x0a,0x11,0x0b,0x11,0x0c, 0x11,0x0d,0x11,0x0e,0x11,0x0f,0x09,0x4a,0x09,0x4b,0x09,0x4c,0x0e,0xe4,0x0a,0x68,0x0a,0x69,0x0a,0x65,0x0a,0x66,0x0a,0x67,0x13,0xe9,0x13,0xed,0x13,0xee,0x00,0x0b,0x00,0x0c,0x13,0xf0,0x13,0xf1,0x0a,0x64,0x13,0xf2,0x13,0xf8,0x13,0xf9,0x13,0xfa,0x13,0xfb,0x13,0xfc,0x13,0xfd,0x13,0xfe,0x13,0xff,0x14,0x00,0x14,0x01,0x09,0x07, 0x09,0x08,0x08,0xc9,0x09,0x09,0x08,0xc8,0x09,0x0a,0x0e,0x24,0x09,0x0b,0x08,0xca,0x09,0x0c,0x09,0x02,0x08,0xf9,0x0e,0x25,0x09,0x0d,0x08,0xc7,0x09,0x0e,0x0e,0x26,0x08,0xcb,0x0e,0x27,0x09,0x0f,0x08,0xf6,0x09,0x10,0x0e,0x28,0x08,0xcc,0x0e,0x29,0x09,0x11,0x0e,0x2a,0x08,0xcd,0x0e,0x2b,0x09,0x12,0x08,0xcf,0x08,0xce,0x0e,0x2c, 0x09,0x13,0x08,0xd1,0x08,0xd0,0x0e,0x2d,0x09,0x14,0x08,0xd3,0x08,0xd2,0x0e,0x2e,0x09,0x15,0x0e,0x2f,0x09,0x16,0x0e,0x30,0x09,0x17,0x0b,0x0c,0x09,0x18,0x0b,0x0d,0x09,0x19,0x0e,0x31,0x08,0xd4,0x0e,0x32,0x09,0x1a,0x0e,0x33,0x08,0xd5,0x0e,0x34,0x09,0x1b,0x0e,0x35,0x08,0xd6,0x0e,0x36,0x09,0x1c,0x0e,0x37,0x08,0xe1,0x0e,0x38, 0x09,0x1d,0x0e,0x39,0x0e,0x3a,0x0e,0x3b,0x09,0x1e,0x0e,0x3c,0x0e,0x3d,0x0e,0x3e,0x09,0x1f,0x08,0xe4,0x08,0xe2,0x08,0xe3,0x09,0x20,0x08,0xe7,0x08,0xe5,0x08,0xe6,0x09,0x22,0x0e,0x53,0x08,0xe8,0x08,0xe9,0x09,0x23,0x0e,0x54,0x08,0xeb,0x08,0xec,0x09,0x24,0x0e,0x55,0x08,0xed,0x0e,0x56,0x09,0x25,0x09,0x59,0x08,0xee,0x09,0x3f, 0x09,0x26,0x0e,0x57,0x08,0xef,0x0e,0x58,0x09,0x27,0x0e,0x59,0x08,0xf0,0x0e,0x5a,0x09,0x28,0x08,0xf3,0x0e,0x5b,0x0e,0x5d,0x09,0x29,0x0e,0x5e,0x09,0x2a,0x08,0xf7,0x09,0x2b,0x08,0xf5,0x08,0xf4,0x0e,0x61,0x09,0x01,0x09,0x04,0x08,0xff,0x09,0x00,0x09,0x34,0x09,0x35,0x08,0xfa,0x08,0xfb,0x0b,0xb8,0x0b,0x1b,0x40,0x55,0x85,0x64, 0x5b,0x5a,0x59,0x54,0x52,0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x43,0x42,0x41,0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13, 0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0x45,0x6a,0xb0,0x19,0x43,0x60,0xb0,0x0c,0x23,0x44,0x23,0x10,0x20,0xb0,0x0c,0x4e,0xf0,0x4d,0x2f,0xb0,0x00,0x12,0x1b,0x21,0x23,0x11,0x20,0x33,0x2f,0x59,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58, 0xb0,0x05,0x2b,0xb0,0x00,0x13,0x4b,0xb0,0x14,0x50,0x58,0xb1,0x00,0x40,0x38,0x59,0xb0,0x06,0x2b,0x1b,0x21,0x23,0x11,0x20,0x33,0x2f,0x59,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0x4e,0xb0,0x03,0x25,0x10,0xf2,0x21,0xb0,0x00,0x12,0x4d,0x1b,0x20,0x45,0xb0,0x04,0x25,0xb0,0x04,0x25,0x23,0x4a,0x61,0x64,0xb0,0x28,0x52,0x58,0x21, 0x23,0x10,0xd6,0x1b,0xb0,0x03,0x25,0x10,0xf2,0x21,0xb0,0x00,0x12,0x59,0x59,0x2d,0x2c,0xb0,0x1a,0x43,0x58,0x21,0x21,0x1b,0xb0,0x02,0x25,0xb0,0x02,0x25,0x49,0xb0,0x03,0x25,0xb0,0x03,0x25,0x4a,0x61,0x20,0x64,0xb0,0x10,0x50,0x58,0x21,0x21,0x21,0x1b,0xb0,0x03,0x25,0xb0,0x03,0x25,0x49,0xb0,0x00,0x50,0x58,0xb0,0x00,0x50,0x58, 0xb8,0xff,0xe2,0x38,0x21,0x1b,0xb0,0x00,0x38,0x21,0x59,0x1b,0xb0,0x00,0x52,0x58,0xb0,0x1e,0x38,0x21,0x1b,0xb0,0x00,0x38,0x21,0x59,0x59,0x59,0x59,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0xb0,0x05,0x2b,0xb0,0x00,0x13,0x4b,0xb0,0x14,0x50,0x58,0xb9,0x00,0x00,0xff,0xc0,0x38,0x59,0xb0,0x06,0x2b,0x1b,0x21,0x23,0x11,0x20,0x33, 0x2f,0x59,0x2d,0x2c,0x4e,0x01,0x8a,0x10,0xb1,0x0c,0x19,0x43,0x44,0xb0,0x00,0x14,0xb1,0x00,0x0c,0xe2,0xb0,0x00,0x15,0xb9,0x00,0x00,0xff,0xf0,0x38,0x00,0xb0,0x00,0x3c,0xb0,0x28,0x2b,0xb0,0x02,0x25,0x10,0xb0,0x00,0x3c,0x2d,0x2c,0x01,0x18,0xb0,0x00,0x2f,0xb0,0x01,0x14,0xf2,0xb0,0x01,0x13,0xb0,0x01,0x15,0x4d,0xb0,0x00,0x12, 0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0xb0,0x05,0x2b,0xb0,0x00,0x13,0xb9,0x00,0x00,0xff,0xe0,0x38,0xb0,0x06,0x2b,0x1b,0x21,0x23,0x11,0x20,0x33,0x2f,0x59,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0x45,0x64,0x6a,0x23,0x45,0x64,0x69,0xb0,0x19,0x43,0x64,0x60,0x60,0xb0,0x0c,0x23,0x44,0x23,0x10,0x20,0xb0,0x0c,0xf0,0x2f,0xb0, 0x00,0x12,0x1b,0x21,0x21,0x20,0x8a,0x20,0x8a,0x52,0x58,0x11,0x33,0x1b,0x21,0x21,0x59,0x59,0x2d,0x2c,0x01,0x4b,0xb0,0xc8,0x51,0x58,0xb1,0x0b,0x0a,0x43,0x23,0x43,0x65,0x0a,0x59,0x2d,0x2c,0x00,0x4b,0xb0,0xc8,0x51,0x58,0x00,0xb1,0x0a,0x0b,0x43,0x23,0x43,0x0b,0x59,0x2d,0x2c,0x00,0xb0,0x0c,0x23,0x70,0xb1,0x01,0x0c,0x3e,0x01, 0xb0,0x0c,0x23,0x70,0xb1,0x02,0x0c,0x45,0x3a,0xb1,0x02,0x00,0x08,0x0d,0x2d,0x2c,0xb0,0x12,0x2b,0xb0,0x02,0x25,0x45,0xb0,0x02,0x25,0x45,0x6a,0xb0,0x40,0x8b,0x60,0xb0,0x02,0x25,0x23,0x44,0x21,0x21,0x21,0x2d,0x2c,0xb0,0x13,0x2b,0xb0,0x02,0x25,0x45,0xb0,0x02,0x25,0x45,0x6a,0xb8,0xff,0xc0,0x8c,0x60,0xb0,0x02,0x25,0x23,0x44, 0x21,0x21,0x21,0x2d,0x2c,0xb0,0x00,0xb0,0x12,0x2b,0x21,0x21,0x21,0x2d,0x2c,0xb0,0x00,0xb0,0x13,0x2b,0x21,0x21,0x21,0x2d,0x2c,0x01,0x4b,0xb0,0xc8,0x51,0x58,0xb0,0x06,0x43,0xb0,0x07,0x43,0x65,0x0a,0x59,0x2d,0x2c,0x20,0x69,0xb0,0x40,0x61,0xb0,0x00,0x8b,0x20,0xb1,0x2c,0xc0,0x8a,0x8c,0xb8,0x10,0x00,0x62,0x60,0x2b,0x0c,0x64, 0x23,0x64,0x61,0x5c,0x58,0xb0,0x03,0x61,0x59,0x2d,0x2c,0xb1,0x00,0x03,0x25,0x45,0x68,0x54,0xb0,0x1c,0x4b,0x50,0x5a,0x58,0xb0,0x03,0x25,0x45,0xb0,0x03,0x25,0x45,0x60,0x68,0x20,0xb0,0x04,0x25,0x23,0x44,0xb0,0x04,0x25,0x23,0x44,0x1b,0xb0,0x03,0x25,0x20,0x45,0x68,0x20,0x8a,0x23,0x44,0xb0,0x03,0x25,0x45,0x68,0x60,0xb0,0x03, 0x25,0x23,0x44,0x59,0x2d,0x2c,0xb0,0x03,0x25,0x20,0x45,0x68,0x20,0x8a,0x23,0x44,0xb0,0x03,0x25,0x45,0x64,0x68,0x65,0x60,0xb0,0x04,0x25,0xb0,0x01,0x60,0x23,0x44,0x2d,0x2c,0xb0,0x09,0x43,0x58,0x87,0x21,0xc0,0x1b,0xb0,0x12,0x43,0x58,0x87,0x45,0xb0,0x11,0x2b,0xb0,0x0d,0x23,0x44,0xb0,0x0d,0x7a,0xe4,0x1b,0x03,0x8a,0x45,0x18, 0x69,0x20,0xb0,0x0d,0x23,0x44,0x8a,0x8a,0x87,0x20,0xb0,0xa0,0x51,0x58,0xb0,0x11,0x2b,0xb0,0x0d,0x23,0x44,0xb0,0x0d,0x7a,0xe4,0x1b,0x21,0xb0,0x0d,0x7a,0xe4,0x59,0x59,0x59,0x18,0x2d,0x2c,0x20,0x8a,0x45,0x23,0x45,0x68,0x60,0x44,0x2d,0x2c,0x45,0x6a,0x42,0x2d,0x2c,0x01,0x18,0x2f,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0xb0, 0x04,0x25,0xb0,0x04,0x25,0x49,0x64,0x23,0x45,0x64,0x69,0xb0,0x40,0x8b,0x61,0x20,0xb0,0x80,0x62,0x6a,0xb0,0x02,0x25,0xb0,0x02,0x25,0x61,0x8c,0xb0,0x19,0x43,0x60,0xb0,0x0c,0x23,0x44,0x21,0x8a,0x10,0xb0,0x0c,0xf6,0x21,0x1b,0x21,0x21,0x21,0x21,0x59,0x2d,0x2c,0x01,0xb0,0x18,0x43,0x58,0xb0,0x02,0x25,0x45,0xb0,0x02,0x25,0x45, 0x64,0x60,0x6a,0xb0,0x03,0x25,0x45,0x6a,0x61,0x20,0xb0,0x04,0x25,0x45,0x6a,0x20,0x8a,0x8b,0x65,0xb0,0x04,0x25,0x23,0x44,0x8c,0xb0,0x03,0x25,0x23,0x44,0x21,0x21,0x1b,0x20,0x45,0x6a,0x44,0x20,0x45,0x6a,0x44,0x59,0x2d,0x2c,0x01,0x20,0x45,0xb0,0x00,0x55,0xb0,0x18,0x43,0x5a,0x58,0x45,0x68,0x23,0x45,0x69,0xb0,0x40,0x8b,0x61, 0x20,0xb0,0x80,0x62,0x6a,0x20,0x8a,0x23,0x61,0x20,0xb0,0x03,0x25,0x8b,0x65,0xb0,0x04,0x25,0x23,0x44,0x8c,0xb0,0x03,0x25,0x23,0x44,0x21,0x21,0x1b,0x21,0x21,0xb0,0x19,0x2b,0x59,0x2d,0x2c,0x01,0x8a,0x8a,0x45,0x64,0x23,0x45,0x64,0x61,0x64,0x42,0x2d,0x2c,0xb0,0x04,0x25,0xb0,0x04,0x25,0xb0,0x19,0x2b,0xb0,0x18,0x43,0x58,0xb0, 0x04,0x25,0xb0,0x04,0x25,0xb0,0x03,0x25,0xb0,0x1b,0x2b,0x01,0xb0,0x02,0x25,0x43,0xb0,0x40,0x54,0xb0,0x02,0x25,0x43,0xb0,0x00,0x54,0x5a,0x58,0xb0,0x03,0x25,0x20,0x45,0xb0,0x40,0x61,0x44,0x59,0xb0,0x02,0x25,0x43,0xb0,0x00,0x54,0xb0,0x02,0x25,0x43,0xb0,0x40,0x54,0x5a,0x58,0xb0,0x04,0x25,0x20,0x45,0xb0,0x40,0x60,0x44,0x59, 0x59,0x21,0x21,0x21,0x21,0x2d,0x2c,0xb0,0x03,0x25,0x20,0xb0,0x07,0x25,0x87,0x05,0x2e,0x23,0x20,0x8a,0xb0,0x04,0x25,0xb0,0x07,0x25,0xb0,0x14,0x2b,0x10,0x21,0xc4,0x21,0x2d,0x2c,0xc0,0x2d,0x2c,0x4b,0x52,0x58,0x45,0x44,0x1b,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43,0x58,0x3d,0xed,0x18,0x1b,0xed,0x59,0x2d,0x2c,0x4b,0x50,0x58, 0x45,0x44,0x1b,0x21,0x21,0x59,0x2d,0x2c,0x01,0x18,0x4b,0x52,0x58,0x8a,0x2f,0xed,0x1b,0x21,0x21,0x21,0x59,0x2d,0x2c,0x4b,0x53,0x23,0x4b,0x51,0x5a,0x58,0xb0,0x03,0x25,0x45,0x68,0xb0,0x03,0x25,0x45,0x68,0xb0,0x03,0x25,0x60,0x54,0x58,0x21,0x21,0x21,0x1b,0xb0,0x02,0x25,0x45,0x68,0x60,0xb0,0x03,0x25,0x23,0x44,0x21,0x21,0x59, 0x1b,0x21,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43,0x58,0x3d,0xcd,0x18,0x1b,0xcd,0x59,0x2d,0x2c,0x46,0x23,0x46,0x60,0x8a,0x8a,0x46,0x23,0x20,0x46,0x8a,0x60,0x8a,0x61,0xb8,0xff,0x80,0x62,0x23,0x20,0x10,0x23,0x8a,0xb1,0x0c,0x0c,0x8a,0x70,0x45,0x60,0x20,0xb0,0x00,0x50,0x58,0xb0,0x01,0x61,0xb8,0xff,0xba,0x8b,0x1b,0xb0,0x46, 0x8c,0x59,0xb0,0x10,0x60,0x68,0x01,0x3a,0x2d,0x2c,0x20,0x45,0xb0,0x03,0x25,0x46,0x52,0x4b,0xb0,0x13,0x51,0x5b,0x58,0xb0,0x02,0x25,0x46,0x20,0x68,0x61,0xb0,0x03,0x25,0xb0,0x03,0x25,0x3f,0x23,0x21,0x38,0x1b,0x21,0x11,0x59,0x2d,0x2c,0x20,0x45,0xb0,0x03,0x25,0x46,0x50,0x58,0xb0,0x02,0x25,0x46,0x20,0x68,0x61,0xb0,0x03,0x25, 0xb0,0x03,0x25,0x3f,0x23,0x21,0x38,0x1b,0x21,0x11,0x59,0x2d,0x2c,0x00,0x4b,0xb0,0xc8,0x51,0x58,0x00,0xb0,0x07,0x43,0xb0,0x06,0x43,0x0b,0x59,0x2d,0x2c,0x8a,0x10,0xec,0x2d,0x2c,0xb0,0x0c,0x43,0x58,0x21,0x1b,0x20,0x46,0xb0,0x00,0x52,0x58,0xb8,0xff,0xf0,0x38,0x1b,0xb0,0x10,0x38,0x59,0x59,0x2d,0x2c,0x20,0xb0,0x00,0x55,0x58, 0xb8,0x10,0x00,0x63,0xb0,0x03,0x25,0x45,0x64,0xb0,0x03,0x25,0x45,0x64,0x61,0xb0,0x00,0x53,0x58,0xb0,0x02,0x1b,0xb0,0x40,0x61,0xb0,0x03,0x59,0x25,0x45,0x69,0x53,0x58,0x45,0x44,0x1b,0x21,0x21,0x59,0x1b,0x21,0xb0,0x02,0x25,0x45,0xb0,0x02,0x25,0x45,0x61,0x64,0xb0,0x28,0x51,0x58,0x45,0x44,0x1b,0x21,0x21,0x59,0x59,0x2d,0x2c, 0x21,0x21,0x0c,0x64,0x23,0x64,0x8b,0xb8,0x40,0x00,0x62,0x2d,0x2c,0x21,0xb0,0x80,0x51,0x58,0x0c,0x64,0x23,0x64,0x8b,0xb8,0x20,0x00,0x62,0x1b,0xb2,0x00,0x40,0x2f,0x2b,0x59,0xb0,0x02,0x60,0x2d,0x2c,0x21,0xb0,0xc0,0x51,0x58,0x0c,0x64,0x23,0x64,0x8b,0xb8,0x15,0x55,0x62,0x1b,0xb2,0x00,0x80,0x2f,0x2b,0x59,0xb0,0x02,0x60,0x2d, 0x2c,0x0c,0x64,0x23,0x64,0x8b,0xb8,0x40,0x00,0x62,0x60,0x23,0x21,0x2d,0x2c,0x18,0x4b,0x53,0x58,0xb0,0x04,0x25,0xb0,0x04,0x25,0x49,0x64,0x23,0x45,0x64,0x69,0xb0,0x40,0x8b,0x61,0x20,0xb0,0x80,0x62,0x6a,0xb0,0x02,0x25,0xb0,0x02,0x25,0x61,0x8c,0xb0,0x0c,0x23,0x44,0x21,0x8a,0x10,0xb0,0x0c,0xf6,0x21,0x1b,0x21,0x8a,0x11,0x23, 0x12,0x20,0x39,0x2f,0x59,0x2d,0x2c,0xb0,0x02,0x25,0xb0,0x02,0x25,0x49,0x64,0xb0,0xc0,0x54,0x58,0xb8,0xff,0xf8,0x38,0xb0,0x08,0x38,0x1b,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x13,0x43,0x58,0x03,0x1b,0x02,0x59,0x2d,0x2c,0xb0,0x13,0x43,0x58,0x02,0x1b,0x03,0x59,0x2d,0x2c,0xb0,0x0a,0x2b,0x23,0x10,0x20,0x3c,0xb0,0x17,0x2b,0x2d,0x2c, 0xb0,0x02,0x25,0xb8,0xff,0xf0,0x38,0xb0,0x28,0x2b,0x8a,0x10,0x23,0x20,0xd0,0x23,0xb0,0x10,0x2b,0xb0,0x05,0x43,0x58,0xc0,0x1b,0x3c,0x59,0x20,0x10,0x11,0xb0,0x00,0x12,0x01,0x2d,0x2c,0xb0,0x48,0x2b,0x2d,0x2c,0x01,0xb0,0x02,0x25,0x10,0xd0,0x23,0xc9,0x01,0xb0,0x01,0x13,0xb0,0x00,0x14,0x10,0xb0,0x01,0x3c,0xb0,0x01,0x16,0x2d, 0x2c,0x01,0xb0,0x00,0x13,0xb0,0x01,0xb0,0x03,0x25,0x49,0xb0,0x03,0x17,0x38,0xb0,0x01,0x13,0x2d,0x2c,0x4b,0x53,0x23,0x4b,0x51,0x5a,0x58,0x20,0x45,0x8a,0x60,0x44,0x1b,0x21,0x21,0x59,0x2d,0x2c,0x18,0x4b,0x53,0x58,0xb0,0x04,0x25,0xb0,0x04,0x25,0x49,0x64,0xb0,0x03,0x25,0xb0,0x03,0x25,0x49,0x64,0x68,0xb0,0x40,0x8b,0x61,0x20, 0xb0,0x80,0x62,0x6a,0xb0,0x02,0x25,0xb0,0x02,0x25,0x61,0x8c,0xb0,0x0c,0x23,0x44,0x21,0xb0,0x04,0x25,0x10,0x23,0xb0,0x0c,0xf6,0x1b,0xb0,0x04,0x25,0xb0,0x04,0x25,0x11,0x12,0x23,0x20,0x39,0x2f,0x59,0xcc,0x21,0x21,0x2d,0x2c,0x01,0x18,0xb0,0x18,0x43,0x58,0xb0,0x05,0x25,0x46,0x23,0x45,0x64,0x61,0x1b,0x21,0xb0,0x04,0x25,0xb0, 0x04,0x25,0x4a,0x59,0xb0,0x0e,0x23,0x44,0x23,0x10,0xb0,0x0e,0xec,0x23,0x10,0xb0,0x0e,0xec,0x2d,0x2c,0xb0,0x1b,0x43,0x58,0x20,0xb0,0x01,0x60,0x45,0xb0,0x00,0x51,0x58,0x20,0xb0,0x01,0x60,0x20,0x45,0x20,0x68,0xb0,0x00,0x55,0x58,0xb0,0x20,0x60,0x44,0x21,0x1b,0x21,0x21,0x21,0x59,0x1b,0x20,0xb0,0x01,0x60,0x20,0x45,0x20,0x68, 0xb0,0x00,0x55,0x58,0xb8,0xff,0xe0,0x60,0x44,0xb0,0x1c,0x4b,0x50,0x58,0x20,0x45,0xb0,0x20,0x60,0x44,0x1b,0x21,0x59,0x1b,0x21,0x21,0x21,0x59,0x59,0x1b,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x25,0x46,0x20,0x68,0x61,0xb0,0x03,0x25,0xb0,0x03,0x25,0x3f,0x23,0x21,0x38,0x2d,0x2c,0x46,0x23,0x46,0x60,0x8a,0x8a,0x46,0x23,0x20,0x46,0x8a, 0x60,0x8a,0x61,0xb8,0xff,0x80,0x62,0x23,0x20,0x10,0x23,0x8a,0xb1,0x0c,0x0c,0x8a,0x70,0x45,0x60,0x20,0xb0,0x00,0x50,0x58,0xb0,0x01,0x61,0xb8,0xff,0x80,0x8b,0x1b,0xb0,0x81,0x8c,0x59,0x68,0x3a,0x2d,0x2c,0xb0,0x40,0x2a,0x21,0x2d,0x2c,0x20,0x35,0xb0,0x01,0x60,0x2d,0x2c,0xb0,0x02,0x43,0x54,0x58,0x4b,0x53,0x23,0x4b,0x51,0x5a, 0x58,0x38,0x1b,0x21,0x21,0x59,0x1b,0x21,0x21,0x21,0x21,0x59,0x2d,0x2c,0x49,0xb0,0x0e,0x23,0x44,0x2d,0x2c,0xb0,0x02,0x43,0x54,0x58,0x4b,0x53,0x23,0x4b,0x51,0x5a,0x58,0x20,0x45,0x8a,0x60,0x44,0x1b,0x21,0x21,0x59,0x1b,0x21,0x21,0x21,0x21,0x59,0x2d,0x2c,0x4b,0x53,0x23,0x4b,0x51,0x5a,0x58,0x20,0x45,0x8a,0x60,0x44,0x1b,0x21, 0x21,0x59,0x2d,0x2c,0x4b,0x54,0x58,0x20,0x45,0x8a,0x60,0x44,0x1b,0x21,0x21,0x59,0x2d,0x2c,0x4b,0x53,0x23,0x4b,0x51,0x5a,0x58,0x38,0x1b,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x00,0x21,0x4b,0x54,0x58,0x38,0x1b,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43,0x54,0x58,0xb0,0x46,0x2b,0x1b,0x21,0x21,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43, 0x54,0x58,0xb0,0x47,0x2b,0x1b,0x21,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43,0x54,0x58,0xb0,0x48,0x2b,0x1b,0x21,0x21,0x21,0x21,0x59,0x2d,0x2c,0xb0,0x02,0x43,0x54,0x58,0xb0,0x49,0x2b,0x1b,0x21,0x21,0x21,0x59,0x2d,0x2c,0x00,0xb0,0x02,0x25,0x20,0x11,0x49,0xb0,0x00,0x51,0x58,0xb8,0xff,0xc0,0x38,0x1b,0x21,0x59,0x2d,0x2c,0x00, 0xb0,0x02,0x25,0x20,0x11,0x49,0xb0,0x00,0x53,0x58,0xb0,0x40,0x38,0x1b,0x21,0x59,0x2d,0x2c,0x4b,0x52,0x58,0x7d,0x1b,0x7a,0x59,0x2d,0x2c,0xb1,0x02,0x01,0x42,0xb1,0x23,0x01,0x88,0x51,0xb1,0x40,0x01,0x88,0x53,0x5a,0x58,0xb1,0x02,0x00,0x42,0xb9,0x10,0x00,0x00,0x20,0x88,0x54,0x58,0xb2,0x02,0x01,0x02,0x43,0x60,0x42,0x59,0xb1, 0x24,0x01,0x88,0x51,0x58,0xb9,0x20,0x00,0x00,0x40,0x88,0x54,0x58,0xb2,0x02,0x02,0x02,0x43,0x60,0x42,0xb1,0x24,0x01,0x88,0x54,0x58,0xb2,0x02,0x20,0x02,0x43,0x60,0x42,0x00,0x4b,0x01,0x4b,0x52,0x58,0xb2,0x02,0x08,0x02,0x43,0x60,0x42,0x59,0x1b,0xb9,0x40,0x00,0x00,0x80,0x88,0x54,0x58,0xb2,0x02,0x04,0x02,0x43,0x60,0x42,0x59, 0xb9,0x40,0x00,0x00,0x80,0x63,0xb8,0x01,0x00,0x88,0x54,0x58,0xb2,0x02,0x08,0x02,0x43,0x60,0x42,0x59,0xb9,0x40,0x00,0x01,0x00,0x63,0xb8,0x02,0x00,0x88,0x54,0x58,0xb2,0x02,0x10,0x02,0x43,0x60,0x42,0x59,0xb1,0x26,0x01,0x88,0x51,0x58,0xb9,0x40,0x00,0x02,0x00,0x63,0xb8,0x04,0x00,0x88,0x54,0x58,0xb2,0x02,0x40,0x02,0x43,0x60, 0x42,0x59,0xb9,0x40,0x00,0x04,0x00,0x63,0xb8,0x08,0x00,0x88,0x54,0x58,0xb2,0x02,0x80,0x02,0x43,0x60,0x42,0x59,0x59,0x59,0x59,0x59,0x59,0xb1,0x00,0x02,0x43,0x54,0x58,0x40,0x0a,0x05,0x40,0x08,0x40,0x09,0x40,0x0c,0x02,0x0d,0x02,0x1b,0xb1,0x01,0x02,0x43,0x54,0x58,0xb2,0x05,0x40,0x08,0xba,0x01,0x00,0x00,0x09,0x01,0x00,0xb3, 0x0c,0x01,0x0d,0x01,0x1b,0xb1,0x80,0x02,0x43,0x52,0x58,0xb2,0x05,0x40,0x08,0xb8,0x01,0x80,0xb1,0x09,0x40,0x1b,0xb2,0x05,0x40,0x08,0xba,0x01,0x80,0x00,0x09,0x01,0x40,0x59,0xb9,0x40,0x00,0x00,0x80,0x88,0x55,0xb9,0x40,0x00,0x02,0x00,0x63,0xb8,0x04,0x00,0x88,0x55,0x5a,0x58,0xb3,0x0c,0x00,0x0d,0x01,0x1b,0xb3,0x0c,0x00,0x0d, 0x01,0x59,0x59,0x59,0x42,0x42,0x42,0x42,0x42,0x2d,0x2c,0xb0,0x80,0xb0,0x02,0x43,0x50,0xb0,0x01,0xb0,0x02,0x43,0x54,0x5b,0xb0,0x10,0x4b,0x51,0x5a,0x58,0x21,0x23,0x10,0xb0,0x20,0x1a,0xc9,0x1b,0x8a,0x10,0xed,0x59,0x2d,0x2c,0xb0,0x59,0x2b,0x2d,0x2c,0x8a,0x10,0xe5,0x2d,0x2c,0x20,0x45,0x69,0x44,0x2d,0x2c,0xb1,0x25,0x01,0x88, 0x50,0x58,0xb9,0x40,0x00,0x02,0x00,0x63,0xb8,0x04,0x00,0x88,0x54,0x5c,0xb0,0x14,0x4b,0x52,0x5b,0x1b,0xb0,0x01,0x59,0x2d,0xb9,0x00,0x20,0x01,0x3e,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x3c,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x34,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x32,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01, 0x2f,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x2e,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x2c,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x0c,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x04,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x03,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb8,0x01,0x01,0x40,0xfb,0x09,0x18,0x01,0x4a,0x20,0xff,0x09, 0x18,0x01,0x4a,0x20,0xfe,0x09,0x18,0x01,0x4a,0x20,0xfc,0x09,0x18,0x01,0x4a,0x20,0xf3,0x09,0x18,0x01,0x4a,0x20,0xf1,0x09,0x18,0x01,0x4a,0x20,0xf0,0x09,0x18,0x01,0x4a,0x20,0xef,0x09,0x18,0x01,0x4a,0x20,0xed,0x09,0x18,0x01,0x4a,0x20,0xea,0x09,0x18,0x01,0x4a,0x20,0xdc,0x09,0x18,0x01,0x4a,0x20,0xda,0x09,0x18,0x01,0x4a,0x20, 0xd8,0x09,0x18,0x01,0x4a,0x20,0xd3,0x09,0x18,0x01,0x4a,0x20,0xcd,0x09,0x18,0x01,0x4a,0x20,0xcc,0x09,0x18,0x01,0x4a,0x20,0xca,0x09,0x18,0x01,0x4a,0x20,0xc9,0x09,0x18,0x01,0x4a,0x20,0xc8,0x09,0x18,0x01,0x4a,0x20,0xc6,0x09,0x18,0x01,0x4a,0x20,0xc4,0x09,0x18,0x01,0x4a,0x20,0xc2,0x09,0x18,0x01,0x4a,0x20,0xc0,0x09,0x18,0x01, 0x4a,0x20,0xbd,0x09,0x18,0x01,0x4a,0x20,0xb4,0x09,0x18,0x01,0x4a,0x20,0xb1,0x09,0x18,0x01,0x4a,0x20,0xaf,0x09,0x18,0x01,0x4a,0x20,0x8c,0x09,0x18,0x01,0x4a,0x20,0x8b,0x09,0x18,0x01,0x4a,0x20,0x8a,0x09,0x18,0x01,0x4a,0x20,0x89,0x09,0x18,0x01,0x4a,0x20,0x38,0x09,0x18,0x01,0x4a,0x20,0x37,0x09,0x18,0x01,0x4a,0x20,0x84,0x09, 0x18,0x01,0x4a,0x20,0x83,0x09,0x18,0x01,0x4a,0x20,0x7f,0x09,0x18,0x01,0x4a,0x20,0x7e,0x09,0x18,0x01,0x4a,0x20,0x7d,0x09,0x18,0x01,0x4a,0x20,0x62,0x09,0x18,0x01,0x4a,0x20,0x50,0x09,0x18,0x01,0x4a,0x20,0x48,0x09,0x18,0x01,0x4a,0x20,0x0e,0x09,0x18,0x01,0x4a,0x2f,0xbe,0x04,0xed,0x00,0x01,0x00,0x4f,0x04,0xec,0x00,0x01,0x00, 0x40,0x04,0xeb,0x40,0x61,0x09,0x0d,0x39,0xdf,0xe0,0x16,0x17,0x1c,0xd4,0xd5,0x16,0x17,0x1c,0x7b,0x7c,0x16,0x1b,0x7b,0x7c,0x19,0xd1,0xd2,0x16,0x17,0x1c,0x76,0x77,0x16,0x17,0x1c,0x6d,0x70,0x16,0x17,0x1c,0x6c,0x6f,0x16,0x17,0x1c,0x6b,0x6e,0x16,0x1b,0x6b,0x6e,0x7f,0x72,0x1a,0x74,0x75,0x14,0x15,0x1c,0x67,0x6a,0x14,0x15,0x1c, 0x66,0x69,0x14,0x15,0x1c,0x65,0x68,0x14,0x1b,0x65,0x68,0x85,0x71,0x1a,0x19,0x73,0x16,0x7a,0x43,0x19,0x21,0x79,0x43,0x19,0x21,0x3b,0x39,0x00,0x2b,0x3a,0x39,0x00,0x2b,0x39,0x95,0x48,0x1f,0x2f,0xbc,0x04,0xe6,0x00,0x2f,0x05,0x03,0x00,0x02,0x05,0x03,0xb3,0x13,0xff,0x1f,0xe0,0xbe,0x04,0xf7,0x00,0x01,0x00,0xe0,0x04,0xf7,0x00, 0x01,0x00,0x20,0x04,0xf0,0xb3,0x0d,0x11,0x39,0x40,0xb8,0x04,0xea,0xb2,0x0b,0x14,0x39,0xb9,0xff,0xc0,0x04,0xef,0xb3,0x1b,0x22,0x39,0x3f,0x41,0x0d,0x04,0xf4,0x00,0x01,0x00,0x8f,0x04,0xf3,0x00,0x01,0x00,0x30,0x04,0xf3,0x00,0x01,0x00,0x30,0x04,0xef,0x00,0x01,0x00,0x40,0x04,0xe8,0xb3,0x0b,0x10,0x39,0x30,0xbd,0x01,0x55,0x00, 0x01,0x00,0x80,0x01,0x55,0x00,0x01,0x01,0x54,0xb3,0x95,0x24,0x1f,0x3f,0xbf,0x01,0x42,0x00,0x01,0x00,0x0f,0x01,0x41,0x00,0xa0,0x01,0x41,0x00,0x02,0xff,0xe0,0xb4,0xf1,0x29,0x2b,0x39,0x40,0xb8,0x01,0x40,0xb3,0x3d,0x43,0x39,0x40,0xb8,0x01,0x40,0xb3,0x24,0x28,0x39,0x40,0xb8,0x01,0x3f,0xb3,0x2c,0x2f,0x39,0x40,0xb8,0x01,0x3f, 0xb3,0x17,0x1c,0x39,0x40,0xb8,0x01,0x3d,0x40,0x16,0x26,0x2b,0x39,0xe6,0xe7,0x03,0x2b,0x40,0xe7,0x2c,0x2e,0x39,0x40,0xe7,0x1b,0x1c,0x39,0x40,0x54,0x1f,0x1f,0x39,0xb8,0xff,0xc0,0x40,0x16,0xcb,0x23,0x23,0x39,0x40,0xd9,0x29,0x2a,0x39,0x53,0x52,0x02,0x2b,0x52,0xe2,0x02,0x2b,0x20,0xb0,0x0b,0x0d,0x39,0xb9,0x01,0x02,0x01,0x01, 0x40,0x1b,0x02,0x2b,0xfd,0xfc,0x0a,0x2b,0xfb,0xaf,0x05,0x2b,0xf2,0xe2,0x02,0x2b,0xc3,0xc5,0x02,0x2b,0x40,0xda,0x17,0x19,0x39,0xdb,0xe2,0x02,0x2b,0xb8,0xff,0xc0,0xb3,0xe2,0x30,0x31,0x39,0xb8,0xff,0xc0,0x40,0x11,0xe2,0x1d,0x1e,0x39,0x40,0xd6,0x17,0x17,0x39,0xeb,0xbe,0x02,0x2b,0xbe,0x9a,0x02,0x2b,0xb8,0x01,0x84,0xb2,0x99, 0x0a,0x2b,0xb8,0x01,0x81,0xb2,0x99,0x0a,0x2b,0xb8,0x01,0x80,0xb2,0x99,0x0a,0x2b,0xb8,0x01,0x7f,0x40,0x0f,0x99,0x0a,0x2b,0x9b,0x99,0x0a,0x2b,0x99,0x9a,0x02,0x2b,0x9a,0x95,0x05,0x2b,0xb8,0xff,0xe0,0xb7,0xee,0x14,0x16,0x39,0x92,0x91,0x03,0x2b,0xb8,0xff,0xe0,0x40,0x0c,0xf4,0x13,0x16,0x39,0xec,0x95,0x04,0x2b,0x91,0x95,0x24, 0x1f,0xb8,0xff,0xe0,0x40,0x0b,0x63,0x18,0x19,0x39,0x66,0x63,0x01,0x96,0x95,0x02,0x2b,0xb8,0xff,0xe0,0x40,0x0c,0x95,0x25,0x28,0x39,0x38,0x37,0x00,0x2b,0x37,0x84,0xff,0x1f,0xb8,0x01,0x01,0xb6,0x7d,0x02,0x2b,0xfc,0xdb,0x0a,0x2b,0xb9,0x01,0x3e,0x01,0x3c,0xb2,0x02,0x2b,0x40,0xb8,0x01,0x3c,0xb2,0x1f,0x24,0x39,0xb8,0x01,0x2f, 0xb2,0x7d,0x03,0x2b,0xb8,0x01,0x2e,0xb3,0x84,0x03,0x2b,0xd0,0xb8,0x01,0x2c,0xb5,0x01,0x40,0xd8,0x17,0x19,0x39,0xb8,0xff,0xc0,0x40,0x09,0xc4,0x22,0x25,0x39,0x40,0xc2,0x17,0x17,0x39,0xb8,0xff,0xc0,0xb3,0xc0,0x1a,0x1b,0x39,0xb8,0xff,0xc0,0xb7,0xc0,0x10,0x12,0x39,0xcd,0xcc,0x03,0x2b,0xb8,0xff,0xc0,0xb7,0xc9,0x23,0x23,0x39, 0xca,0xc8,0x03,0x2b,0xb8,0xff,0xc0,0x40,0x16,0xf0,0x0b,0x0d,0x39,0xea,0x7e,0x02,0x2b,0x30,0x62,0x0c,0x0c,0x06,0x43,0xb1,0xaf,0x02,0x2b,0xaf,0x7e,0x02,0x2b,0xb8,0xff,0xc0,0xb3,0xd3,0x0f,0x12,0x39,0xb8,0xff,0xc0,0xb3,0xbd,0x27,0x28,0x39,0xbc,0x01,0x86,0x00,0x89,0x01,0x00,0x00,0x2b,0x01,0x85,0xb2,0x8a,0x0a,0x2b,0xb8,0xff, 0xc0,0x40,0x1c,0x8c,0x1e,0x1e,0x39,0x89,0x8a,0x04,0x2b,0x8a,0x84,0x0a,0x2b,0x8b,0x84,0x03,0x2b,0x81,0x7f,0x01,0x2b,0x7d,0x7e,0x04,0x2b,0x7e,0x84,0x03,0x2b,0xb8,0xff,0xe0,0x40,0x41,0x62,0x18,0x19,0x39,0x62,0x84,0x01,0x2b,0x88,0x84,0x01,0x2b,0x87,0x84,0x01,0x2b,0x85,0x84,0x01,0x2b,0x83,0x84,0x04,0x2b,0xe9,0x84,0xf9,0x84, 0x02,0x69,0x84,0x01,0x27,0x84,0x01,0x1b,0x37,0x15,0x18,0x36,0x15,0x15,0x35,0x15,0x12,0x34,0x15,0x0f,0x33,0x15,0x0c,0x32,0x15,0x09,0x31,0x15,0x06,0x30,0x15,0x03,0x2f,0x15,0x00,0x2e,0x15,0x41,0x26,0x01,0x4a,0x01,0x4b,0x00,0x15,0x00,0x50,0x01,0x4c,0x00,0x01,0x00,0x70,0x01,0x4a,0x00,0x01,0x01,0x3a,0x01,0x3b,0x00,0x0f,0x01, 0x38,0x01,0x39,0x00,0x0e,0x01,0x36,0x01,0x37,0x00,0x0e,0x00,0x0b,0x01,0x38,0x00,0x3b,0x01,0x38,0x00,0x4b,0x01,0x38,0x00,0xcb,0x01,0x38,0x00,0x04,0x00,0x0b,0x01,0x36,0x00,0x3b,0x01,0x36,0x00,0x5b,0x01,0x36,0x00,0x03,0x00,0x10,0x01,0x3a,0x00,0x01,0x01,0x06,0xb2,0x03,0xff,0x1f,0x41,0x21,0x01,0x0a,0x01,0x0b,0x00,0x0f,0x01, 0x08,0x01,0x09,0x00,0x0e,0x01,0x06,0x01,0x07,0x00,0x0e,0x00,0x6b,0x01,0x08,0x00,0x01,0x00,0x0b,0x01,0x08,0x00,0x3b,0x01,0x08,0x00,0x4b,0x01,0x08,0x00,0xbb,0x01,0x08,0x00,0xeb,0x01,0x08,0x00,0xfb,0x01,0x08,0x00,0x06,0x00,0x0b,0x01,0x0a,0x00,0x5b,0x01,0x0a,0x00,0x8b,0x01,0x0a,0x00,0x03,0x01,0x06,0x40,0x22,0x03,0xff,0x1f, 0x26,0x27,0x0e,0x28,0x27,0x0f,0x35,0x36,0x0e,0x33,0x36,0x0f,0x2a,0x2b,0x0e,0x2c,0x2b,0x0f,0x22,0x23,0x0e,0x24,0x23,0x0f,0x1e,0x1f,0x0e,0x20,0x1f,0x0f,0x00,0xbf,0x01,0x31,0x00,0x10,0x01,0x31,0x00,0x20,0x01,0x31,0x00,0x03,0x00,0x00,0x01,0x30,0x40,0x80,0x01,0x70,0x2a,0xe0,0x2a,0x02,0x00,0x3c,0x01,0x10,0x24,0x40,0x24,0x70, 0x24,0xa0,0x24,0x04,0x0f,0x10,0x11,0x0c,0x09,0x0a,0x0b,0x0c,0x06,0x07,0x08,0x0c,0x03,0x04,0x05,0x0c,0x00,0x01,0x02,0x0c,0x26,0x06,0x1c,0x1f,0x06,0x03,0x18,0x1f,0x0f,0x03,0x3f,0x03,0xdf,0x03,0x03,0x9f,0x00,0xdf,0x00,0x02,0x0f,0x17,0x1f,0x17,0x2f,0x17,0x03,0x0f,0x14,0x1f,0x14,0x2f,0x14,0x03,0x1b,0x01,0x1d,0x0d,0x18,0x07, 0x1a,0x0d,0x15,0x10,0x17,0x0d,0x12,0x04,0x14,0x0d,0x2f,0x1b,0x01,0x2c,0x3c,0x2a,0x3c,0x28,0x3c,0x26,0x3c,0x24,0x3c,0x22,0x3c,0x20,0x3c,0x1e,0x3c,0x1b,0x3c,0x18,0x3c,0x15,0x3c,0x12,0x3c,0x0f,0x3c,0x09,0x3c,0x06,0x3c,0x03,0x3c,0x00,0x3c,0x50,0x33,0x54,0x01,0xb0,0x12,0x4b,0x00,0x4b,0x54,0x42,0xb0,0x13,0x01,0x4b,0x00,0x4b, 0x53,0x42,0xb0,0x33,0x2b,0x4b,0xb8,0x03,0x20,0x52,0xb0,0x32,0x2b,0x4b,0xb0,0x09,0x50,0x5b,0x58,0xb1,0x01,0x01,0x8e,0x59,0xb0,0x33,0x2b,0xb0,0x02,0x88,0xb8,0x01,0x00,0x54,0xb0,0x04,0x88,0xb8,0x02,0x00,0x54,0xb0,0x12,0x43,0x5a,0x5b,0x58,0xb8,0x01,0x19,0xb1,0x01,0x01,0x8e,0x85,0x1b,0xb9,0x00,0x01,0x01,0x00,0xb0,0x4b,0x60, 0x85,0x8d,0x59,0x2b,0x2b,0x1d,0xb0,0x64,0x4b,0x53,0x58,0xb0,0x80,0x1d,0x59,0xb0,0x32,0x4b,0x53,0x58,0xb0,0x90,0x1d,0x59,0x00,0x4b,0xb0,0x32,0x51,0xb0,0x1b,0x23,0x42,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x73,0x2b,0x2b,0x2b,0x2b,0x73,0x73,0x73,0x73,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x73,0x73,0x73,0x73,0x73,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0xb1,0x28,0x26,0x45,0xb0,0x2a,0x45,0x61,0xb0,0x2c,0x45,0x60,0x44,0x2b,0x2b,0x2b,0x73,0x73,0x74,0xb8,0x01,0x06,0x45,0x69,0xb8,0x01,0x0a,0x45,0x69,0x61,0xb8,0x01,0x0a,0x23,0x44,0xb8,0x01,0x08,0x45,0x69,0xb8,0x01,0x0a,0x45,0x60,0xb8,0x01,0x08,0x23, 0x44,0x2b,0x2b,0x2b,0x2b,0x73,0x73,0x73,0xb8,0x01,0x3a,0x45,0x69,0xb8,0x01,0x38,0x45,0x69,0x60,0xb8,0x01,0x38,0x23,0x44,0xb8,0x01,0x3a,0x45,0x69,0xb8,0x01,0x36,0x45,0x69,0x60,0xb8,0x01,0x36,0x23,0x44,0x2b,0x2b,0x2b,0x73,0x73,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x01,0x73,0x74,0x75,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x73,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x2b,0x2b,0x73,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x73,0x73,0x2b,0x73,0x74,0x2b,0x73,0x73,0x73,0x73,0x2b,0x2b,0x2b,0x73,0x74,0x2b,0x73,0x2b,0x2b,0x2b,0x2b,0x2b,0xb0,0x18,0xb0,0x3f,0x4b,0x53,0x42,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x73,0x73,0xb1, 0x09,0x32,0x2b,0x4b,0xb0,0x50,0x52,0x42,0x4b,0xb0,0x08,0x52,0x4b,0xb0,0x08,0x50,0x5b,0xb0,0x1a,0x23,0x42,0x4b,0xb0,0xc8,0x52,0x4b,0xb0,0x36,0x50,0x5b,0xb0,0x0c,0x23,0x42,0xb1,0x00,0x02,0x43,0x54,0xb1,0x02,0x02,0x43,0x54,0xb1,0x06,0x02,0x43,0x54,0x5b,0x5b,0x58,0x41,0x15,0x01,0x3e,0x00,0x64,0x01,0x3c,0x00,0x64,0x01,0x34, 0x00,0x64,0x01,0x32,0x00,0x64,0x01,0x2f,0x00,0x64,0x01,0x2e,0x00,0x64,0x01,0x2c,0x00,0x64,0x01,0x0c,0x00,0x64,0x01,0x04,0x00,0x64,0x01,0x03,0x00,0x64,0x01,0x01,0x40,0x4f,0x64,0xff,0x64,0xfe,0x64,0xfc,0x64,0xf3,0x64,0xf1,0x64,0xf0,0x64,0xef,0x64,0xed,0x64,0xea,0x64,0xdc,0x64,0xda,0x64,0xd8,0x64,0xd3,0x64,0xcd,0x64,0xcc, 0x64,0xca,0x64,0xc9,0x64,0xc8,0x64,0xc6,0x64,0xc4,0x64,0xc2,0x64,0xc0,0x64,0xbd,0x64,0xb4,0x64,0xb1,0x64,0xaf,0x64,0x8c,0x64,0x8b,0x64,0x8a,0x64,0x89,0x64,0x84,0x64,0x83,0x64,0x7f,0x64,0x7e,0x64,0x7d,0x64,0x62,0x64,0x50,0x64,0x48,0x64,0x0e,0x64,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x59,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x05,0xec,0x00,0x16,0x00,0x00,0x05,0x9a,0x00,0x18,0x00,0x00,0x05,0x9a,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0xff,0xe8, 0xff,0x89,0x00,0x00,0xff,0xe8,0xff,0x89,0x00,0x00,0xff,0xe8,0xfe,0x4e,0xfe,0x29,0xff,0xf5,0x00,0x00,0x05,0x9a,0x00,0x00,0xfe,0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xcd,0xff,0xed,0x05,0xa1,0x00,0x0d,0x02,0x48,0xff,0xeb,0x03,0x59,0x00,0x0d,0x00,0x00,0xff,0xeb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xff,0xed,0x04,0x33,0x00,0x12,0x00,0xa4,0x00,0xab,0x00,0x8b,0x00,0x81,0x00,0x77,0xfe,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x71,0x00,0x80, 0x00,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd6,0x00,0xd6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x00,0xa8,0x00,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0xa4,0x00,0x9b,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x97,0x00,0x8c,0x00,0x00, 0x00,0x00,0x00,0x8a,0x00,0x83,0x00,0x00,0x00,0x00,0x00,0x94,0x00,0x8a,0x00,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xe0,0x00,0xa0,0x00,0xe4,0x01,0xbe, 0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0x00,0x86,0x00,0x00,0x00,0xc5,0x00,0xc3,0x00,0x81,0x00,0x4a,0x00,0x5a,0x00,0x51,0x05,0xdb,0x05,0xdb,0x00,0x86,0x00,0x58,0x00,0x90,0x00,0x58,0x00,0x8a,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf, 0x00,0x00,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0x78,0x00,0x77,0x00,0x7a,0x00,0x61,0x00,0x7a,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x6d,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x81,0x00,0x92,0x00,0x8b,0x00,0xa0,0x00,0x97,0x01,0xd3,0x00,0x4c,0x00,0x74,0x00,0x64, 0x00,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x23,0x00,0xc9,0x00,0x6a,0x00,0x6d,0x00,0x4c,0x00,0x61,0x00,0x69,0x00,0xc8,0x00,0xa2,0x00,0x80,0x00,0x7e,0x00,0x6b,0x05,0x9a,0x00,0x11,0x02,0x24,0x00,0x11,0x03,0x00,0xff,0xef,0x00,0x81,0x00,0x67,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0x00,0x63,0x00,0x96,0x00,0xc0,0xfe,0xbc,0xfe,0xf2,0x00,0x64,0x00,0x64, 0x00,0x76,0x00,0x7c,0x02,0xf6,0x00,0x0d,0x02,0x00,0x00,0x0d,0x04,0x96,0xff,0xf3,0x00,0x54,0x00,0x46,0x00,0x6a,0x00,0x6b,0x00,0x4c,0x07,0x69,0xfe,0x31,0x00,0xe4,0x00,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xcd,0x00,0x11,0x06,0xa0,0x00,0x00,0xff,0xed,0xfe,0x00,0x00,0xaa,0x00,0xb6,0x00,0x6c,0x00,0x00, 0x00,0xaa,0x00,0xb8,0x00,0x6c,0x00,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xfe,0x63,0xfd,0x6d, 0xfd,0x76,0xff,0x82,0xff,0x83,0x05,0xe9,0x05,0xe3,0x04,0xbe,0x04,0xec,0x03,0x64,0x04,0x19,0x00,0x6e,0x00,0x7f,0x00,0x8c,0x00,0x9b,0x00,0xa7,0x00,0x6e,0x00,0x7f,0x00,0x91,0x00,0xa0,0x00,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x00,0xbc,0x00,0x94,0x00,0x94,0xff,0x85,0xff,0xae,0x00,0x52,0x00,0x29,0x06,0x14,0x00,0xae,0x00,0x46,0x00,0x46,0xfe,0x58, 0x05,0x60,0x00,0x8f,0x00,0x85,0x00,0x85,0x00,0x5c,0x00,0x54,0x00,0x46,0x00,0xa7,0x00,0x98,0x00,0x58,0x00,0xe1,0x00,0x9e,0x00,0x4b,0x00,0x69,0x00,0xb4,0xff,0xe8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x64,0x00,0xe1,0x00,0x5a,0x00,0x4b,0x00,0x00,0x05,0x4e,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0xbe,0x00,0x00,0x01,0x0a,0x00,0x00,0x02,0x3e,0x00,0x00,0x03,0x84,0x00,0x00,0x04,0xd2,0x00,0x00,0x06,0xca,0x00,0x00,0x06,0xf2,0x00,0x00,0x07,0x66,0x00,0x00,0x07,0xe2,0x00,0x00,0x08,0x8e,0x00,0x00,0x09,0x08,0x00,0x00,0x09,0x6a, 0x00,0x00,0x09,0xa2,0x00,0x00,0x09,0xea,0x00,0x00,0x0a,0x22,0x00,0x00,0x0a,0xa6,0x00,0x00,0x0a,0xf8,0x00,0x00,0x0b,0xb0,0x00,0x00,0x0c,0x9c,0x00,0x00,0x0d,0x28,0x00,0x00,0x0d,0xe8,0x00,0x00,0x0e,0xc4,0x00,0x00,0x0f,0x3a,0x00,0x00,0x10,0x66,0x00,0x00,0x11,0x42,0x00,0x00,0x11,0xca,0x00,0x00,0x12,0x6a,0x00,0x00,0x12,0xda, 0x00,0x00,0x13,0x36,0x00,0x00,0x13,0xa6,0x00,0x00,0x14,0x80,0x00,0x00,0x15,0xfc,0x00,0x00,0x17,0x10,0x00,0x00,0x18,0x52,0x00,0x00,0x19,0x3e,0x00,0x00,0x1a,0x18,0x00,0x00,0x1a,0xb8,0x00,0x00,0x1b,0x4c,0x00,0x00,0x1c,0x58,0x00,0x00,0x1d,0x00,0x00,0x00,0x1d,0x28,0x00,0x00,0x1d,0xc6,0x00,0x00,0x1e,0xa4,0x00,0x00,0x1f,0x4a, 0x00,0x00,0x20,0x64,0x00,0x00,0x21,0x58,0x00,0x00,0x22,0x42,0x00,0x00,0x23,0x18,0x00,0x00,0x23,0xd0,0x00,0x00,0x25,0x02,0x00,0x00,0x26,0x66,0x00,0x00,0x27,0x0a,0x00,0x00,0x27,0xbc,0x00,0x00,0x28,0xbe,0x00,0x00,0x2a,0x6c,0x00,0x00,0x2b,0x84,0x00,0x00,0x2c,0x28,0x00,0x00,0x2c,0xfe,0x00,0x00,0x2d,0x5c,0x00,0x00,0x2d,0x90, 0x00,0x00,0x2d,0xea,0x00,0x00,0x2e,0x3a,0x00,0x00,0x2e,0x64,0x00,0x00,0x2e,0x9c,0x00,0x00,0x2f,0xaa,0x00,0x00,0x30,0xa2,0x00,0x00,0x31,0x70,0x00,0x00,0x32,0x66,0x00,0x00,0x33,0x6e,0x00,0x00,0x34,0x38,0x00,0x00,0x35,0x74,0x00,0x00,0x36,0x46,0x00,0x00,0x36,0xce,0x00,0x00,0x37,0x8a,0x00,0x00,0x38,0x5a,0x00,0x00,0x38,0xac, 0x00,0x00,0x39,0xe8,0x00,0x00,0x3a,0xba,0x00,0x00,0x3b,0x98,0x00,0x00,0x3c,0x90,0x00,0x00,0x3d,0x82,0x00,0x00,0x3e,0x16,0x00,0x00,0x3f,0x38,0x00,0x00,0x3f,0xfa,0x00,0x00,0x40,0xd6,0x00,0x00,0x41,0x8a,0x00,0x00,0x42,0xc4,0x00,0x00,0x43,0xf8,0x00,0x00,0x44,0xe4,0x00,0x00,0x45,0xb8,0x00,0x00,0x46,0x6c,0x00,0x00,0x46,0x9a, 0x00,0x00,0x47,0x54,0x00,0x00,0x47,0xde,0x00,0x00,0x48,0x1a,0x00,0x00,0x49,0xee,0x00,0x00,0x4a,0x06,0x00,0x00,0x4a,0x34,0x00,0x00,0x4a,0x62,0x00,0x00,0x4a,0x98,0x00,0x00,0x4a,0xca,0x00,0x00,0x4a,0xf8,0x00,0x00,0x4b,0x26,0x00,0x00,0x4b,0x56,0x00,0x00,0x4b,0x88,0x00,0x00,0x4b,0xb8,0x00,0x00,0x4b,0xec,0x00,0x00,0x4c,0x04, 0x00,0x00,0x4c,0x32,0x00,0x00,0x4c,0x60,0x00,0x00,0x4c,0x90,0x00,0x00,0x4c,0xc2,0x00,0x00,0x4c,0xee,0x00,0x00,0x4d,0x1a,0x00,0x00,0x4d,0x4a,0x00,0x00,0x4d,0x7e,0x00,0x00,0x4d,0xae,0x00,0x00,0x4d,0xde,0x00,0x00,0x4e,0x0c,0x00,0x00,0x4e,0x3a,0x00,0x00,0x4e,0x6c,0x00,0x00,0x4e,0x9a,0x00,0x00,0x4e,0xca,0x00,0x00,0x4e,0xf8, 0x00,0x00,0x4f,0x26,0x00,0x00,0x4f,0x58,0x00,0x00,0x4f,0xc8,0x00,0x00,0x50,0x4e,0x00,0x00,0x51,0x30,0x00,0x00,0x51,0xec,0x00,0x00,0x53,0x48,0x00,0x00,0x53,0x8e,0x00,0x00,0x54,0x42,0x00,0x00,0x55,0x52,0x00,0x00,0x55,0x62,0x00,0x00,0x56,0x80,0x00,0x00,0x57,0xa2,0x00,0x00,0x58,0x6e,0x00,0x00,0x58,0xa0,0x00,0x00,0x59,0x16, 0x00,0x00,0x59,0xec,0x00,0x00,0x5a,0xee,0x00,0x00,0x5c,0x78,0x00,0x00,0x5d,0x82,0x00,0x00,0x5e,0x1e,0x00,0x00,0x5e,0xb4,0x00,0x00,0x5f,0x4c,0x00,0x00,0x60,0x4a,0x00,0x00,0x60,0xf2,0x00,0x00,0x61,0xd2,0x00,0x00,0x62,0x52,0x00,0x00,0x62,0xb4,0x00,0x00,0x63,0x3c,0x00,0x00,0x64,0x0a,0x00,0x00,0x64,0x82,0x00,0x00,0x65,0xb6, 0x00,0x00,0x67,0x24,0x00,0x00,0x68,0x74,0x00,0x00,0x69,0x4c,0x00,0x00,0x69,0x4c,0x00,0x00,0x69,0xc4,0x00,0x00,0x6a,0x10,0x00,0x00,0x6a,0x82,0x00,0x00,0x6b,0x68,0x00,0x00,0x6c,0x7e,0x00,0x00,0x6c,0xfc,0x00,0x00,0x6d,0x66,0x00,0x00,0x6d,0xd0,0x00,0x00,0x6e,0x90,0x00,0x00,0x6e,0xbe,0x00,0x00,0x6e,0xee,0x00,0x00,0x6f,0x1c, 0x00,0x00,0x70,0x4e,0x00,0x00,0x71,0xe0,0x00,0x00,0x72,0x0a,0x00,0x00,0x72,0x34,0x00,0x00,0x72,0x82,0x00,0x00,0x72,0xd0,0x00,0x00,0x73,0x06,0x00,0x00,0x73,0x38,0x00,0x00,0x73,0xda,0x00,0x00,0x74,0x3c,0x00,0x00,0x74,0x6c,0x00,0x00,0x74,0xa0,0x00,0x00,0x74,0xce,0x00,0x00,0x76,0x0e,0x00,0x00,0x76,0x50,0x00,0x00,0x76,0x92, 0x00,0x00,0x77,0xae,0x00,0x00,0x78,0xa0,0x00,0x00,0x79,0x54,0x00,0x00,0x79,0x96,0x00,0x00,0x79,0xde,0x00,0x00,0x7a,0x56,0x00,0x00,0x7c,0x38,0x00,0x00,0x7c,0x68,0x00,0x00,0x7c,0x98,0x00,0x00,0x7c,0xc8,0x00,0x00,0x7c,0xfa,0x00,0x00,0x7d,0x2a,0x00,0x00,0x7d,0x58,0x00,0x00,0x7d,0x86,0x00,0x00,0x7d,0xb8,0x00,0x00,0x7d,0xe6, 0x00,0x00,0x7e,0x14,0x00,0x00,0x7e,0x42,0x00,0x00,0x7e,0x70,0x00,0x00,0x7e,0x9e,0x00,0x00,0x7e,0xcc,0x00,0x00,0x7e,0xfc,0x00,0x00,0x7f,0x46,0x00,0x00,0x7f,0x86,0x00,0x00,0x80,0x16,0x00,0x00,0x80,0x42,0x00,0x00,0x80,0xa4,0x00,0x00,0x80,0xe2,0x00,0x00,0x81,0x7c,0x00,0x00,0x82,0x16,0x00,0x00,0x82,0x8e,0x00,0x00,0x82,0xe4, 0x00,0x00,0x83,0x26,0x00,0x00,0x84,0x22,0x00,0x00,0x84,0xb6,0x00,0x00,0x84,0xe4,0x00,0x00,0x85,0x10,0x00,0x00,0x85,0x3e,0x00,0x00,0x85,0x6a,0x00,0x00,0x85,0xb2,0x00,0x00,0x86,0xb4,0x00,0x00,0x88,0x30,0x00,0x00,0x88,0x5e,0x00,0x00,0x88,0x8c,0x00,0x00,0x89,0x50,0x00,0x00,0x8a,0x4a,0x00,0x00,0x8a,0x96,0x00,0x00,0x8a,0xf6, 0x00,0x00,0x8b,0x40,0x00,0x00,0x8b,0xd8,0x00,0x00,0x8c,0x94,0x00,0x00,0x8c,0xbe,0x00,0x00,0x8c,0xea,0x00,0x00,0x8d,0x16,0x00,0x00,0x8d,0xd4,0x00,0x00,0x8e,0x04,0x00,0x00,0x8e,0x32,0x00,0x00,0x8e,0x60,0x00,0x00,0x8e,0x78,0x00,0x00,0x8e,0x90,0x00,0x00,0x8e,0xbe,0x00,0x00,0x8e,0xec,0x00,0x00,0x8f,0x1a,0x00,0x00,0x8f,0x48, 0x00,0x00,0x90,0x80,0x00,0x00,0x90,0xac,0x00,0x00,0x90,0xbc,0x00,0x00,0x90,0xec,0x00,0x00,0x91,0x1c,0x00,0x00,0x91,0x34,0x00,0x00,0x91,0x4c,0x00,0x00,0x91,0x7a,0x00,0x00,0x91,0xa6,0x00,0x00,0x91,0xb6,0x00,0x00,0x91,0xce,0x00,0x00,0x91,0xe6,0x00,0x00,0x92,0x16,0x00,0x00,0x92,0x44,0x00,0x00,0x92,0x72,0x00,0x00,0x92,0xa2, 0x00,0x00,0x92,0xd0,0x00,0x00,0x92,0xfc,0x00,0x00,0x93,0x24,0x00,0x00,0x93,0x4a,0x00,0x00,0x93,0x78,0x00,0x00,0x93,0xa8,0x00,0x00,0x93,0xd8,0x00,0x00,0x94,0x06,0x00,0x00,0x94,0x3a,0x00,0x00,0x94,0x6c,0x00,0x00,0x94,0x8e,0x00,0x00,0x94,0xbc,0x00,0x00,0x94,0xde,0x00,0x00,0x95,0x0a,0x00,0x00,0x95,0x2c,0x00,0x00,0x95,0x4e, 0x00,0x00,0x95,0x74,0x00,0x00,0x95,0x8c,0x00,0x00,0x95,0xba,0x00,0x00,0x96,0x82,0x00,0x00,0x96,0xc0,0x00,0x00,0x96,0xf2,0x00,0x00,0x97,0x52,0x00,0x00,0x97,0x86,0x00,0x00,0x97,0xb6,0x00,0x00,0x97,0xe4,0x00,0x00,0x98,0x14,0x00,0x00,0x98,0x42,0x00,0x00,0x98,0xb0,0x00,0x00,0x99,0xd6,0x00,0x00,0x9b,0x46,0x00,0x00,0x9c,0xc6, 0x00,0x00,0x9e,0x22,0x00,0x00,0x9f,0x28,0x00,0x00,0x9f,0xf6,0x00,0x00,0xa0,0xb2,0x00,0x00,0xa2,0x28,0x00,0x00,0xa2,0x7c,0x00,0x00,0xa2,0x94,0x00,0x00,0xa2,0xfc,0x00,0x00,0xa4,0x9a,0x00,0x00,0xa4,0xc2,0x00,0x00,0xa5,0x12,0x00,0x00,0xa5,0x44,0x00,0x00,0xa5,0x7a,0x00,0x00,0xa5,0xe0,0x00,0x00,0xa6,0xd6,0x00,0x00,0xa7,0x86, 0x00,0x00,0xa7,0xea,0x00,0x00,0xa8,0x2c,0x00,0x00,0xa8,0x98,0x00,0x00,0xa8,0xf2,0x00,0x00,0xa9,0x86,0x00,0x00,0xa9,0xb4,0x00,0x00,0xa9,0xe2,0x00,0x00,0xaa,0x10,0x00,0x00,0xaa,0x40,0x00,0x00,0xaa,0x6e,0x00,0x00,0xaa,0x9c,0x00,0x00,0xaa,0xca,0x00,0x00,0xaa,0xf8,0x00,0x00,0xab,0x26,0x00,0x00,0xab,0x56,0x00,0x00,0xab,0x86, 0x00,0x00,0xab,0xb4,0x00,0x00,0xab,0xe2,0x00,0x00,0xac,0x10,0x00,0x00,0xac,0x3e,0x00,0x00,0xac,0x6c,0x00,0x00,0xac,0x92,0x00,0x00,0xad,0xd0,0x00,0x00,0xae,0x00,0x00,0x00,0xae,0x30,0x00,0x00,0xaf,0x18,0x00,0x00,0xb0,0x24,0x00,0x00,0xb0,0x52,0x00,0x00,0xb0,0x80,0x00,0x00,0xb0,0xae,0x00,0x00,0xb0,0xdc,0x00,0x00,0xb1,0x0a, 0x00,0x00,0xb1,0x38,0x00,0x00,0xb1,0x5c,0x00,0x00,0xb1,0x80,0x00,0x00,0xb1,0xae,0x00,0x00,0xb1,0xd0,0x00,0x00,0xb1,0xf6,0x00,0x00,0xb2,0x1c,0x00,0x00,0xb2,0xb8,0x00,0x00,0xb2,0xd0,0x00,0x00,0xb2,0xe8,0x00,0x00,0xb3,0x10,0x00,0x00,0xb3,0x36,0x00,0x00,0xb4,0x4a,0x00,0x00,0xb5,0x38,0x00,0x00,0xb5,0x66,0x00,0x00,0xb5,0x94, 0x00,0x00,0xb5,0xc2,0x00,0x00,0xb5,0xf0,0x00,0x00,0xb6,0x08,0x00,0x00,0xb6,0x2c,0x00,0x00,0xb6,0x4e,0x00,0x00,0xb6,0x6e,0x00,0x00,0xb7,0x4a,0x00,0x00,0xb8,0x38,0x00,0x00,0xb8,0x66,0x00,0x00,0xb8,0x94,0x00,0x00,0xb8,0xc2,0x00,0x00,0xb8,0xf2,0x00,0x00,0xb9,0x22,0x00,0x00,0xb9,0x52,0x00,0x00,0xb9,0x6a,0x00,0x00,0xb9,0x82, 0x00,0x00,0xb9,0xb0,0x00,0x00,0xb9,0xe0,0x00,0x00,0xba,0x0e,0x00,0x00,0xba,0x3c,0x00,0x00,0xba,0xa6,0x00,0x00,0xbc,0x2c,0x00,0x00,0xbc,0x82,0x00,0x00,0xbc,0xb0,0x00,0x00,0xbc,0xde,0x00,0x00,0xbd,0x0c,0x00,0x00,0xbd,0x3c,0x00,0x00,0xbd,0x7e,0x00,0x00,0xbd,0xae,0x00,0x00,0xbd,0xde,0x00,0x00,0xbe,0x10,0x00,0x00,0xbe,0x3e, 0x00,0x00,0xbe,0x72,0x00,0x00,0xbe,0xa6,0x00,0x00,0xbe,0xda,0x00,0x00,0xbf,0x0a,0x00,0x00,0xbf,0x42,0x00,0x00,0xbf,0x6e,0x00,0x00,0xc0,0x66,0x00,0x00,0xc1,0x16,0x00,0x00,0xc1,0x44,0x00,0x00,0xc1,0x72,0x00,0x00,0xc1,0xa0,0x00,0x00,0xc1,0xce,0x00,0x00,0xc2,0x02,0x00,0x00,0xc2,0x36,0x00,0x00,0xc2,0x46,0x00,0x00,0xc2,0x72, 0x00,0x00,0xc2,0xf8,0x00,0x00,0xc3,0x24,0x00,0x00,0xc3,0x54,0x00,0x00,0xc3,0x84,0x00,0x00,0xc3,0xa8,0x00,0x00,0xc3,0xd4,0x00,0x00,0xc4,0x04,0x00,0x00,0xc4,0x34,0x00,0x00,0xc4,0x6a,0x00,0x00,0xc4,0x7a,0x00,0x00,0xc4,0x8a,0x00,0x00,0xc4,0x9a,0x00,0x00,0xc4,0xaa,0x00,0x00,0xc4,0xba,0x00,0x00,0xc4,0xca,0x00,0x00,0xc4,0xda, 0x00,0x00,0xc5,0x6e,0x00,0x00,0xc5,0x7e,0x00,0x00,0xc5,0x8e,0x00,0x00,0xc6,0x18,0x00,0x00,0xc6,0x28,0x00,0x00,0xc6,0xbc,0x00,0x00,0xc6,0xcc,0x00,0x00,0xc7,0x62,0x00,0x00,0xc7,0x72,0x00,0x00,0xc7,0x82,0x00,0x00,0xc7,0x92,0x00,0x00,0xc8,0xb4,0x00,0x00,0xc8,0xc4,0x00,0x00,0xc8,0xf6,0x00,0x00,0xc9,0x2a,0x00,0x00,0xc9,0x58, 0x00,0x00,0xc9,0x86,0x00,0x00,0xc9,0xb4,0x00,0x00,0xc9,0xe2,0x00,0x00,0xca,0x1a,0x00,0x00,0xcb,0x52,0x00,0x00,0xcc,0x3e,0x00,0x00,0xcc,0xfc,0x00,0x00,0xcd,0xc0,0x00,0x00,0xce,0xea,0x00,0x00,0xcf,0x60,0x00,0x00,0xd0,0x4a,0x00,0x00,0xd0,0xe6,0x00,0x00,0xd1,0xde,0x00,0x00,0xd2,0x80,0x00,0x00,0xd3,0xbe,0x00,0x00,0xd3,0xce, 0x00,0x00,0xd4,0xac,0x00,0x00,0xd5,0x98,0x00,0x00,0xd6,0x96,0x00,0x00,0xd7,0x8e,0x00,0x00,0xd8,0xd4,0x00,0x00,0xda,0x1e,0x00,0x00,0xda,0x50,0x00,0x00,0xda,0x84,0x00,0x00,0xda,0xb4,0x00,0x00,0xda,0xe2,0x00,0x00,0xdb,0x10,0x00,0x00,0xdb,0x42,0x00,0x00,0xdc,0x4c,0x00,0x00,0xdc,0x7e,0x00,0x00,0xdd,0x70,0x00,0x00,0xdd,0x80, 0x00,0x00,0xdd,0xb2,0x00,0x00,0xde,0xe2,0x00,0x00,0xdf,0xf2,0x00,0x00,0xe0,0xf8,0x00,0x00,0xe1,0x2a,0x00,0x00,0xe1,0x58,0x00,0x00,0xe2,0x3a,0x00,0x00,0xe2,0x4a,0x00,0x00,0xe3,0x32,0x00,0x00,0xe3,0x42,0x00,0x00,0xe3,0x52,0x00,0x00,0xe4,0x70,0x00,0x00,0xe4,0x80,0x00,0x00,0xe5,0x9e,0x00,0x00,0xe6,0xdc,0x00,0x00,0xe7,0xc4, 0x00,0x00,0xe7,0xf2,0x00,0x00,0xe8,0x02,0x00,0x00,0xe8,0xbc,0x00,0x00,0xe8,0xcc,0x00,0x00,0xe8,0xdc,0x00,0x00,0xe8,0xec,0x00,0x00,0xe8,0xfc,0x00,0x00,0xe9,0x0c,0x00,0x00,0xe9,0x1c,0x00,0x00,0xe9,0x2c,0x00,0x00,0xe9,0xd4,0x00,0x00,0xeb,0x50,0x00,0x00,0xeb,0x60,0x00,0x00,0xec,0x44,0x00,0x00,0xed,0x02,0x00,0x00,0xed,0xd8, 0x00,0x00,0xef,0x12,0x00,0x00,0xef,0xf4,0x00,0x00,0xf0,0xf6,0x00,0x00,0xf1,0xc0,0x00,0x00,0xf2,0xd2,0x00,0x00,0xf4,0x1c,0x00,0x00,0xf5,0x22,0x00,0x00,0xf5,0x32,0x00,0x00,0xf6,0x46,0x00,0x00,0xf7,0x42,0x00,0x00,0xf7,0xaa,0x00,0x00,0xf8,0xac,0x00,0x00,0xf8,0xbc,0x00,0x00,0xf9,0xd6,0x00,0x00,0xfa,0xde,0x00,0x00,0xfb,0xa8, 0x00,0x00,0xfb,0xd4,0x00,0x00,0xfb,0xe4,0x00,0x00,0xfc,0xb2,0x00,0x00,0xfd,0xac,0x00,0x00,0xfe,0x44,0x00,0x00,0xfe,0x54,0x00,0x00,0xfe,0xd8,0x00,0x00,0xfe,0xe8,0x00,0x00,0xfe,0xf8,0x00,0x00,0xff,0x66,0x00,0x00,0xff,0x76,0x00,0x01,0x00,0xd8,0x00,0x01,0x00,0xe8,0x00,0x01,0x01,0xac,0x00,0x01,0x02,0x4a,0x00,0x01,0x03,0x26, 0x00,0x01,0x04,0x54,0x00,0x01,0x05,0x16,0x00,0x01,0x06,0x12,0x00,0x01,0x06,0xc4,0x00,0x01,0x07,0xae,0x00,0x01,0x08,0xc8,0x00,0x01,0x09,0xc8,0x00,0x01,0x09,0xf8,0x00,0x01,0x0b,0x1c,0x00,0x01,0x0b,0x4a,0x00,0x01,0x0c,0x24,0x00,0x01,0x0c,0x34,0x00,0x01,0x0c,0x66,0x00,0x01,0x0d,0x98,0x00,0x01,0x0e,0xa4,0x00,0x01,0x0f,0xa6, 0x00,0x01,0x0f,0xd4,0x00,0x01,0x10,0x00,0x00,0x01,0x10,0xcc,0x00,0x01,0x11,0x68,0x00,0x01,0x11,0xf0,0x00,0x01,0x12,0x00,0x00,0x01,0x13,0x64,0x00,0x01,0x14,0x6c,0x00,0x01,0x14,0xf8,0x00,0x01,0x15,0x9a,0x00,0x01,0x15,0xf4,0x00,0x01,0x17,0x08,0x00,0x01,0x17,0x18,0x00,0x01,0x17,0x2e,0x00,0x01,0x17,0x44,0x00,0x01,0x18,0x2a, 0x00,0x01,0x19,0x62,0x00,0x01,0x1a,0x6c,0x00,0x01,0x1b,0x42,0x00,0x01,0x1c,0x28,0x00,0x01,0x1c,0x8c,0x00,0x01,0x1c,0xce,0x00,0x01,0x1c,0xf6,0x00,0x01,0x1d,0x1e,0x00,0x01,0x1d,0x7c,0x00,0x01,0x1d,0xe2,0x00,0x01,0x1e,0x76,0x00,0x01,0x1f,0x08,0x00,0x01,0x1f,0x78,0x00,0x01,0x1f,0xe8,0x00,0x01,0x20,0xa2,0x00,0x01,0x21,0x50, 0x00,0x01,0x21,0xc6,0x00,0x01,0x22,0x68,0x00,0x01,0x22,0xde,0x00,0x01,0x23,0x56,0x00,0x01,0x24,0x1a,0x00,0x01,0x24,0xd4,0x00,0x01,0x25,0x82,0x00,0x01,0x25,0xa8,0x00,0x01,0x25,0xd0,0x00,0x01,0x26,0x00,0x00,0x01,0x26,0x2e,0x00,0x01,0x26,0x62,0x00,0x01,0x26,0x94,0x00,0x01,0x26,0xc8,0x00,0x01,0x26,0xf8,0x00,0x01,0x27,0x2c, 0x00,0x01,0x27,0x60,0x00,0x01,0x27,0x94,0x00,0x01,0x27,0xc4,0x00,0x01,0x28,0x04,0x00,0x01,0x28,0x42,0x00,0x01,0x28,0x76,0x00,0x01,0x28,0xa8,0x00,0x01,0x28,0xdc,0x00,0x01,0x29,0x0e,0x00,0x01,0x29,0x54,0x00,0x01,0x29,0x88,0x00,0x01,0x29,0xba,0x00,0x01,0x29,0xea,0x00,0x01,0x2a,0x28,0x00,0x01,0x2a,0x66,0x00,0x01,0x2a,0x8c, 0x00,0x01,0x2a,0xb2,0x00,0x01,0x2a,0xe0,0x00,0x01,0x2b,0x0e,0x00,0x01,0x2b,0x40,0x00,0x01,0x2b,0x6e,0x00,0x01,0x2b,0xa0,0x00,0x01,0x2b,0xd4,0x00,0x01,0x2c,0x06,0x00,0x01,0x2c,0x36,0x00,0x01,0x2c,0x68,0x00,0x01,0x2c,0x9a,0x00,0x01,0x2c,0xcc,0x00,0x01,0x2c,0xfc,0x00,0x01,0x2d,0x3c,0x00,0x01,0x2d,0x7a,0x00,0x01,0x2d,0xa8, 0x00,0x01,0x2d,0xd4,0x00,0x01,0x2d,0xf8,0x00,0x01,0x2e,0x1e,0x00,0x01,0x2e,0x46,0x00,0x01,0x2e,0x6c,0x00,0x01,0x2e,0x9c,0x00,0x01,0x2e,0xcc,0x00,0x01,0x2e,0xfe,0x00,0x01,0x2f,0x30,0x00,0x01,0x2f,0x62,0x00,0x01,0x2f,0x94,0x00,0x01,0x2f,0xc8,0x00,0x01,0x2f,0xfc,0x00,0x01,0x30,0x2e,0x00,0x01,0x30,0x60,0x00,0x01,0x30,0x9e, 0x00,0x01,0x30,0xde,0x00,0x01,0x31,0x0c,0x00,0x01,0x31,0x3c,0x00,0x01,0x31,0x6a,0x00,0x01,0x31,0x9a,0x00,0x01,0x31,0xc8,0x00,0x01,0x31,0xf8,0x00,0x01,0x32,0x26,0x00,0x01,0x32,0x54,0x00,0x01,0x32,0x7a,0x00,0x01,0x32,0xa0,0x00,0x01,0x32,0xc6,0x00,0x01,0x32,0xee,0x00,0x01,0x33,0x1c,0x00,0x01,0x33,0x4a,0x00,0x01,0x33,0x78, 0x00,0x01,0x33,0xa6,0x00,0x01,0x33,0xd4,0x00,0x01,0x34,0x02,0x00,0x01,0x34,0x32,0x00,0x01,0x34,0x62,0x00,0x01,0x34,0x90,0x00,0x01,0x34,0xbe,0x00,0x01,0x34,0xe4,0x00,0x01,0x35,0x0a,0x00,0x01,0x35,0x30,0x00,0x01,0x35,0x58,0x00,0x01,0x35,0x86,0x00,0x01,0x35,0xb4,0x00,0x01,0x35,0xe2,0x00,0x01,0x36,0x12,0x00,0x01,0x36,0x38, 0x00,0x01,0x36,0x5e,0x00,0x01,0x36,0x8e,0x00,0x01,0x36,0xbe,0x00,0x01,0x36,0xee,0x00,0x01,0x37,0x1e,0x00,0x01,0x37,0x2e,0x00,0x01,0x37,0x3e,0x00,0x01,0x37,0x4e,0x00,0x01,0x37,0x5e,0x00,0x01,0x37,0xee,0x00,0x01,0x38,0x82,0x00,0x01,0x39,0xaa,0x00,0x01,0x3a,0xb0,0x00,0x01,0x3b,0x86,0x00,0x01,0x3c,0x44,0x00,0x01,0x3d,0x44, 0x00,0x01,0x3e,0x0e,0x00,0x01,0x3f,0x00,0x00,0x01,0x3f,0xd6,0x00,0x01,0x3f,0xe6,0x00,0x01,0x40,0x8a,0x00,0x01,0x41,0x58,0x00,0x01,0x42,0x02,0x00,0x01,0x42,0xc8,0x00,0x01,0x43,0x84,0x00,0x01,0x44,0x72,0x00,0x01,0x45,0x4a,0x00,0x01,0x45,0xf6,0x00,0x01,0x46,0x06,0x00,0x01,0x46,0xe0,0x00,0x01,0x47,0x8e,0x00,0x01,0x48,0x60, 0x00,0x01,0x49,0x2a,0x00,0x01,0x49,0x80,0x00,0x01,0x49,0xce,0x00,0x01,0x4a,0x22,0x00,0x01,0x4a,0x6e,0x00,0x01,0x4b,0x0c,0x00,0x01,0x4b,0xa0,0x00,0x01,0x4c,0x3e,0x00,0x01,0x4c,0xc6,0x00,0x01,0x4d,0xa8,0x00,0x01,0x4e,0x62,0x00,0x01,0x4e,0xba,0x00,0x01,0x4f,0x12,0x00,0x01,0x4f,0x88,0x00,0x01,0x4f,0xf4,0x00,0x01,0x50,0x88, 0x00,0x01,0x51,0x12,0x00,0x01,0x51,0x2a,0x00,0x01,0x51,0x42,0x00,0x01,0x51,0x84,0x00,0x01,0x51,0xc6,0x00,0x01,0x51,0xf6,0x00,0x01,0x52,0x24,0x00,0x01,0x52,0x58,0x00,0x01,0x52,0x8c,0x00,0x01,0x52,0xc0,0x00,0x01,0x52,0xf2,0x00,0x01,0x53,0x1c,0x00,0x01,0x53,0x46,0x00,0x01,0x53,0x76,0x00,0x01,0x53,0xa6,0x00,0x01,0x53,0xda, 0x00,0x01,0x54,0x0c,0x00,0x01,0x54,0x40,0x00,0x01,0x54,0x72,0x00,0x01,0x54,0xa2,0x00,0x01,0x54,0xd0,0x00,0x01,0x55,0x00,0x00,0x01,0x55,0x2e,0x00,0x01,0x55,0x60,0x00,0x01,0x55,0x92,0x00,0x01,0x55,0xc4,0x00,0x01,0x55,0xf6,0x00,0x01,0x56,0x24,0x00,0x01,0x56,0x52,0x00,0x01,0x56,0x82,0x00,0x01,0x56,0xb0,0x00,0x01,0x56,0xe8, 0x00,0x01,0x57,0x1e,0x00,0x01,0x57,0x4e,0x00,0x01,0x57,0x7c,0x00,0x01,0x57,0xaa,0x00,0x01,0x57,0xd8,0x00,0x01,0x58,0x08,0x00,0x01,0x58,0x36,0x00,0x01,0x58,0x68,0x00,0x01,0x58,0x9c,0x00,0x01,0x58,0xce,0x00,0x01,0x59,0x00,0x00,0x01,0x59,0x16,0x00,0x01,0x59,0x2c,0x00,0x01,0x59,0x5a,0x00,0x01,0x59,0x88,0x00,0x01,0x59,0xae, 0x00,0x01,0x59,0xd4,0x00,0x01,0x5a,0x0a,0x00,0x01,0x5a,0x40,0x00,0x01,0x5a,0x70,0x00,0x01,0x5a,0x9e,0x00,0x01,0x5a,0xd2,0x00,0x01,0x5b,0x06,0x00,0x01,0x5b,0x3a,0x00,0x01,0x5b,0x6e,0x00,0x01,0x5b,0xa2,0x00,0x01,0x5b,0xd2,0x00,0x01,0x5c,0x20,0x00,0x01,0x5c,0x6a,0x00,0x01,0x5c,0x9c,0x00,0x01,0x5c,0xce,0x00,0x01,0x5c,0xfc, 0x00,0x01,0x5d,0x2a,0x00,0x01,0x5d,0x42,0x00,0x01,0x5d,0x70,0x00,0x01,0x5d,0x88,0x00,0x01,0x5d,0xb8,0x00,0x01,0x5d,0xd0,0x00,0x01,0x5d,0xf6,0x00,0x01,0x5e,0x26,0x00,0x01,0x5e,0x54,0x00,0x01,0x5e,0x7c,0x00,0x01,0x5e,0xa2,0x00,0x01,0x5e,0xda,0x00,0x01,0x5f,0x10,0x00,0x01,0x5f,0x3e,0x00,0x01,0x5f,0x6c,0x00,0x01,0x5f,0x9e, 0x00,0x01,0x5f,0xce,0x00,0x01,0x60,0x04,0x00,0x01,0x60,0x38,0x00,0x01,0x60,0x6a,0x00,0x01,0x60,0x9c,0x00,0x01,0x60,0xce,0x00,0x01,0x61,0x02,0x00,0x01,0x61,0x32,0x00,0x01,0x61,0x62,0x00,0x01,0x61,0x92,0x00,0x01,0x61,0xc2,0x00,0x01,0x61,0xe4,0x00,0x01,0x62,0x14,0x00,0x01,0x62,0x2c,0x00,0x01,0x62,0x42,0x00,0x01,0x62,0x6c, 0x00,0x01,0x62,0xac,0x00,0x01,0x62,0xd8,0x00,0x01,0x63,0x0e,0x00,0x01,0x63,0x30,0x00,0x01,0x63,0x52,0x00,0x01,0x63,0x6a,0x00,0x01,0x63,0x80,0x00,0x01,0x63,0xa4,0x00,0x01,0x63,0xc8,0x00,0x01,0x63,0xec,0x00,0x01,0x64,0x10,0x00,0x01,0x64,0x3a,0x00,0x01,0x64,0x64,0x00,0x01,0x64,0x92,0x00,0x01,0x64,0xc6,0x00,0x01,0x64,0xec, 0x00,0x01,0x65,0x10,0x00,0x01,0x65,0x46,0x00,0x01,0x65,0x7c,0x00,0x01,0x65,0xaa,0x00,0x01,0x65,0xd8,0x00,0x01,0x66,0x14,0x00,0x01,0x66,0x50,0x00,0x01,0x66,0x80,0x00,0x01,0x66,0xb0,0x00,0x01,0x66,0xe0,0x00,0x01,0x67,0x10,0x00,0x01,0x67,0x42,0x00,0x01,0x67,0x72,0x00,0x01,0x67,0xa8,0x00,0x01,0x67,0xe0,0x00,0x01,0x68,0x0e, 0x00,0x01,0x68,0x3c,0x00,0x01,0x68,0x62,0x00,0x01,0x68,0x8a,0x00,0x01,0x68,0xb8,0x00,0x01,0x68,0xe6,0x00,0x01,0x69,0x0c,0x00,0x01,0x69,0x32,0x00,0x01,0x69,0x60,0x00,0x01,0x69,0x8e,0x00,0x01,0x69,0xc0,0x00,0x01,0x69,0xf0,0x00,0x01,0x6a,0x20,0x00,0x01,0x6a,0x50,0x00,0x01,0x6a,0x7e,0x00,0x01,0x6a,0xaa,0x00,0x01,0x6a,0xd0, 0x00,0x01,0x6a,0xf6,0x00,0x01,0x6b,0x2c,0x00,0x01,0x6b,0x62,0x00,0x01,0x6b,0x98,0x00,0x01,0x6b,0xce,0x00,0x01,0x6c,0x00,0x00,0x01,0x6c,0x34,0x00,0x01,0x6c,0x62,0x00,0x01,0x6c,0x92,0x00,0x01,0x6c,0xbe,0x00,0x01,0x6c,0xec,0x00,0x01,0x6d,0x1e,0x00,0x01,0x6d,0x50,0x00,0x01,0x6d,0x80,0x00,0x01,0x6d,0xb2,0x00,0x01,0x6d,0xe4, 0x00,0x01,0x6e,0x16,0x00,0x01,0x6e,0x46,0x00,0x01,0x6e,0x76,0x00,0x01,0x6e,0xac,0x00,0x01,0x6e,0xe2,0x00,0x01,0x6f,0x18,0x00,0x01,0x6f,0x4e,0x00,0x01,0x6f,0x84,0x00,0x01,0x6f,0xba,0x00,0x01,0x6f,0xe6,0x00,0x01,0x70,0x12,0x00,0x01,0x70,0x42,0x00,0x01,0x70,0x74,0x00,0x01,0x70,0xa4,0x00,0x01,0x70,0xd4,0x00,0x01,0x71,0x06, 0x00,0x01,0x71,0x38,0x00,0x01,0x71,0x6e,0x00,0x01,0x71,0xa4,0x00,0x01,0x71,0xda,0x00,0x01,0x72,0x10,0x00,0x01,0x72,0x3c,0x00,0x01,0x72,0x6a,0x00,0x01,0x72,0x9c,0x00,0x01,0x72,0xce,0x00,0x01,0x72,0xfe,0x00,0x01,0x73,0x2e,0x00,0x01,0x73,0x60,0x00,0x01,0x73,0x92,0x00,0x01,0x73,0xc4,0x00,0x01,0x73,0xf6,0x00,0x01,0x74,0x2c, 0x00,0x01,0x74,0x62,0x00,0x01,0x74,0x98,0x00,0x01,0x74,0xce,0x00,0x01,0x75,0x04,0x00,0x01,0x75,0x3a,0x00,0x01,0x75,0x6a,0x00,0x01,0x75,0x9a,0x00,0x01,0x75,0xce,0x00,0x01,0x76,0x02,0x00,0x01,0x76,0x36,0x00,0x01,0x76,0x6a,0x00,0x01,0x76,0x9e,0x00,0x01,0x76,0xd2,0x00,0x01,0x76,0xf6,0x00,0x01,0x77,0x1a,0x00,0x01,0x77,0x40, 0x00,0x01,0x77,0x66,0x00,0x01,0x77,0x8c,0x00,0x01,0x77,0xb2,0x00,0x01,0x77,0xd8,0x00,0x01,0x77,0xfe,0x00,0x01,0x78,0x2a,0x00,0x01,0x78,0x58,0x00,0x01,0x78,0x8a,0x00,0x01,0x78,0xbc,0x00,0x01,0x78,0xec,0x00,0x01,0x79,0x1e,0x00,0x01,0x79,0x4e,0x00,0x01,0x79,0x7e,0x00,0x01,0x79,0xb4,0x00,0x01,0x79,0xea,0x00,0x01,0x7a,0x20, 0x00,0x01,0x7a,0x54,0x00,0x01,0x7a,0x82,0x00,0x01,0x7a,0xb0,0x00,0x01,0x7a,0xe2,0x00,0x01,0x7b,0x14,0x00,0x01,0x7b,0x46,0x00,0x01,0x7b,0x78,0x00,0x01,0x7b,0xaa,0x00,0x01,0x7b,0xdc,0x00,0x01,0x7c,0x0e,0x00,0x01,0x7c,0x44,0x00,0x01,0x7c,0x7a,0x00,0x01,0x7c,0xb0,0x00,0x01,0x7c,0xde,0x00,0x01,0x7d,0x0e,0x00,0x01,0x7d,0x42, 0x00,0x01,0x7d,0x76,0x00,0x01,0x7d,0xa8,0x00,0x01,0x7d,0xda,0x00,0x01,0x7e,0x0e,0x00,0x01,0x7e,0x42,0x00,0x01,0x7e,0x74,0x00,0x01,0x7e,0xa6,0x00,0x01,0x7e,0xdc,0x00,0x01,0x7f,0x12,0x00,0x01,0x7f,0x48,0x00,0x01,0x7f,0x7c,0x00,0x01,0x7f,0xb0,0x00,0x01,0x7f,0xe4,0x00,0x01,0x80,0x12,0x00,0x01,0x80,0x3e,0x00,0x01,0x80,0x6c, 0x00,0x01,0x80,0x98,0x00,0x01,0x80,0xc6,0x00,0x01,0x80,0xf2,0x00,0x01,0x81,0x22,0x00,0x01,0x81,0x52,0x00,0x01,0x81,0x80,0x00,0x01,0x81,0xac,0x00,0x01,0x81,0xda,0x00,0x01,0x82,0x08,0x00,0x01,0x82,0x38,0x00,0x01,0x82,0x66,0x00,0x01,0x82,0xa0,0x00,0x01,0x82,0xdc,0x00,0x01,0x83,0x1c,0x00,0x01,0x83,0x5c,0x00,0x01,0x83,0x9a, 0x00,0x01,0x83,0xda,0x00,0x01,0x84,0x1a,0x00,0x01,0x84,0x5a,0x00,0x01,0x84,0x9c,0x00,0x01,0x84,0xde,0x00,0x01,0x85,0x26,0x00,0x01,0x85,0x6e,0x00,0x01,0x85,0xb8,0x00,0x01,0x86,0x00,0x00,0x01,0x86,0x48,0x00,0x01,0x86,0x90,0x00,0x01,0x86,0xcc,0x00,0x01,0x87,0x0a,0x00,0x01,0x87,0x4c,0x00,0x01,0x87,0x8e,0x00,0x01,0x87,0xce, 0x00,0x01,0x88,0x0e,0x00,0x01,0x88,0x50,0x00,0x01,0x88,0x92,0x00,0x01,0x88,0xd8,0x00,0x01,0x89,0x1e,0x00,0x01,0x89,0x68,0x00,0x01,0x89,0xb2,0x00,0x01,0x89,0xfc,0x00,0x01,0x8a,0x46,0x00,0x01,0x8a,0x90,0x00,0x01,0x8a,0xda,0x00,0x01,0x8b,0x18,0x00,0x01,0x8b,0x58,0x00,0x01,0x8b,0x9c,0x00,0x01,0x8b,0xe0,0x00,0x01,0x8c,0x22, 0x00,0x01,0x8c,0x64,0x00,0x01,0x8c,0xa8,0x00,0x01,0x8c,0xec,0x00,0x01,0x8d,0x32,0x00,0x01,0x8d,0x78,0x00,0x01,0x8d,0xc2,0x00,0x01,0x8e,0x0c,0x00,0x01,0x8e,0x56,0x00,0x01,0x8e,0x9e,0x00,0x01,0x8e,0xe6,0x00,0x01,0x8f,0x2e,0x00,0x01,0x8f,0x5e,0x00,0x01,0x8f,0x8e,0x00,0x01,0x8f,0xca,0x00,0x01,0x8f,0xee,0x00,0x01,0x90,0x28, 0x00,0x01,0x90,0x56,0x00,0x01,0x90,0x92,0x00,0x01,0x90,0xc0,0x00,0x01,0x90,0xee,0x00,0x01,0x91,0x1e,0x00,0x01,0x91,0x4e,0x00,0x01,0x91,0x74,0x00,0x01,0x91,0xca,0x00,0x01,0x92,0x1c,0x00,0x01,0x92,0x78,0x00,0x01,0x92,0xc2,0x00,0x01,0x93,0x64,0x00,0x01,0x93,0xa4,0x00,0x01,0x93,0xcc,0x00,0x01,0x94,0x0a,0x00,0x01,0x94,0x36, 0x00,0x01,0x94,0x76,0x00,0x01,0x94,0xa8,0x00,0x01,0x94,0xda,0x00,0x01,0x95,0x0c,0x00,0x01,0x95,0x3e,0x00,0x01,0x95,0x64,0x00,0x01,0x95,0xd2,0x00,0x01,0x96,0x4a,0x00,0x01,0x96,0xec,0x00,0x01,0x97,0x1c,0x00,0x01,0x97,0x4c,0x00,0x01,0x97,0x84,0x00,0x01,0x97,0xbc,0x00,0x01,0x97,0xec,0x00,0x01,0x98,0x24,0x00,0x01,0x98,0x52, 0x00,0x01,0x98,0x80,0x00,0x01,0x98,0xb0,0x00,0x01,0x98,0xe0,0x00,0x01,0x99,0x54,0x00,0x01,0x99,0xca,0x00,0x01,0x9a,0x6c,0x00,0x01,0x9a,0x9c,0x00,0x01,0x9a,0xcc,0x00,0x01,0x9b,0x02,0x00,0x01,0x9b,0x38,0x00,0x01,0x9b,0x66,0x00,0x01,0x9b,0x94,0x00,0x01,0x9b,0xc2,0x00,0x01,0x9b,0xf8,0x00,0x01,0x9c,0x26,0x00,0x01,0x9c,0x54, 0x00,0x01,0x9c,0x86,0x00,0x01,0x9c,0xb8,0x00,0x01,0x9c,0xea,0x00,0x01,0x9d,0x70,0x00,0x01,0x9d,0xf8,0x00,0x01,0x9e,0x24,0x00,0x01,0x9e,0x64,0x00,0x01,0x9e,0x8a,0x00,0x01,0x9e,0xc8,0x00,0x01,0x9e,0xf6,0x00,0x01,0x9f,0x34,0x00,0x01,0x9f,0x64,0x00,0x01,0x9f,0x94,0x00,0x01,0x9f,0xc6,0x00,0x01,0x9f,0xf8,0x00,0x01,0xa0,0x1e, 0x00,0x01,0xa0,0x4c,0x00,0x01,0xa0,0xa6,0x00,0x01,0xa0,0xde,0x00,0x01,0xa1,0x3c,0x00,0x01,0xa1,0x64,0x00,0x01,0xa1,0x8c,0x00,0x01,0xa1,0xdc,0x00,0x01,0xa2,0x16,0x00,0x01,0xa2,0x7c,0x00,0x01,0xa2,0xf0,0x00,0x01,0xa3,0x46,0x00,0x01,0xa3,0x7c,0x00,0x01,0xa3,0xa4,0x00,0x01,0xa3,0xe4,0x00,0x01,0xa4,0x3c,0x00,0x01,0xa4,0xb2, 0x00,0x01,0xa4,0xfc,0x00,0x01,0xa5,0x56,0x00,0x01,0xa5,0xb2,0x00,0x01,0xa6,0x0c,0x00,0x01,0xa6,0x68,0x00,0x01,0xa6,0x9a,0x00,0x01,0xa6,0xce,0x00,0x01,0xa7,0x1a,0x00,0x01,0xa7,0x6a,0x00,0x01,0xa7,0x9e,0x00,0x01,0xa7,0xdc,0x00,0x01,0xa8,0x2e,0x00,0x01,0xa8,0x72,0x00,0x01,0xa8,0xb6,0x00,0x01,0xa9,0x16,0x00,0x01,0xa9,0x28, 0x00,0x01,0xa9,0x64,0x00,0x01,0xa9,0xa2,0x00,0x01,0xaa,0x08,0x00,0x01,0xaa,0x1a,0x00,0x01,0xaa,0x82,0x00,0x01,0xaa,0x94,0x00,0x01,0xaa,0xa6,0x00,0x01,0xaa,0xd6,0x00,0x01,0xab,0x1c,0x00,0x01,0xab,0x9e,0x00,0x01,0xab,0xdc,0x00,0x01,0xac,0x1a,0x00,0x01,0xac,0x74,0x00,0x01,0xac,0x86,0x00,0x01,0xac,0xe6,0x00,0x01,0xac,0xf8, 0x00,0x01,0xad,0x20,0x00,0x01,0xad,0x32,0x00,0x01,0xad,0x90,0x00,0x01,0xad,0xb8,0x00,0x01,0xad,0xca,0x00,0x01,0xae,0x14,0x00,0x01,0xae,0x5e,0x00,0x01,0xae,0xb2,0x00,0x01,0xae,0xfa,0x00,0x01,0xaf,0x44,0x00,0x01,0xaf,0xd2,0x00,0x01,0xb0,0x0e,0x00,0x01,0xb0,0x6e,0x00,0x01,0xb0,0xb0,0x00,0x01,0xb0,0xda,0x00,0x01,0xb1,0x06, 0x00,0x01,0xb1,0x18,0x00,0x01,0xb1,0x78,0x00,0x01,0xb2,0x00,0x00,0x01,0xb2,0x50,0x00,0x01,0xb2,0x90,0x00,0x01,0xb2,0xc8,0x00,0x01,0xb3,0x10,0x00,0x01,0xb3,0x40,0x00,0x01,0xb3,0xcc,0x00,0x01,0xb4,0x80,0x00,0x01,0xb5,0x20,0x00,0x01,0xb5,0x80,0x00,0x01,0xb5,0xb8,0x00,0x01,0xb6,0x20,0x00,0x01,0xb6,0x66,0x00,0x01,0xb6,0xaa, 0x00,0x01,0xb7,0x62,0x00,0x01,0xb8,0x2c,0x00,0x01,0xb8,0xa2,0x00,0x01,0xb9,0x3a,0x00,0x01,0xb9,0xb0,0x00,0x01,0xba,0x48,0x00,0x01,0xba,0xba,0x00,0x01,0xbb,0x6e,0x00,0x01,0xbc,0x1e,0x00,0x01,0xbc,0xb8,0x00,0x01,0xbd,0x46,0x00,0x01,0xbd,0xba,0x00,0x01,0xbe,0x50,0x00,0x01,0xbf,0x0c,0x00,0x01,0xbf,0x6e,0x00,0x01,0xc0,0x20, 0x00,0x01,0xc0,0x94,0x00,0x01,0xc1,0x76,0x00,0x01,0xc1,0xfa,0x00,0x01,0xc2,0xa4,0x00,0x01,0xc2,0xec,0x00,0x01,0xc3,0x54,0x00,0x01,0xc3,0xd4,0x00,0x01,0xc4,0x50,0x00,0x01,0xc4,0xb8,0x00,0x01,0xc5,0x8a,0x00,0x01,0xc6,0x2a,0x00,0x01,0xc6,0xb6,0x00,0x01,0xc7,0x30,0x00,0x01,0xc7,0xd8,0x00,0x01,0xc8,0x88,0x00,0x01,0xc9,0x2e, 0x00,0x01,0xc9,0xcc,0x00,0x01,0xca,0x7a,0x00,0x01,0xcb,0x16,0x00,0x01,0xcb,0xe8,0x00,0x01,0xcc,0xae,0x00,0x01,0xcd,0x1e,0x00,0x01,0xcd,0xbc,0x00,0x01,0xce,0x56,0x00,0x01,0xce,0xc0,0x00,0x01,0xcf,0x4a,0x00,0x01,0xcf,0xb8,0x00,0x01,0xd0,0x62,0x00,0x01,0xd0,0xe0,0x00,0x01,0xd1,0x5c,0x00,0x01,0xd1,0xf0,0x00,0x01,0xd2,0x92, 0x00,0x01,0xd3,0x32,0x00,0x01,0xd3,0xd0,0x00,0x01,0xd4,0x6c,0x00,0x01,0xd4,0xfe,0x00,0x01,0xd5,0xc2,0x00,0x01,0xd6,0x8a,0x00,0x01,0xd7,0x26,0x00,0x01,0xd7,0xbc,0x00,0x01,0xd8,0x5c,0x00,0x01,0xd8,0xd6,0x00,0x01,0xd9,0x00,0x00,0x01,0xd9,0x4e,0x00,0x01,0xd9,0xe4,0x00,0x01,0xd9,0xf4,0x00,0x01,0xda,0x2a,0x00,0x01,0xda,0x60, 0x00,0x01,0xda,0x96,0x00,0x01,0xda,0xbe,0x00,0x01,0xda,0xe8,0x00,0x01,0xdb,0x00,0x00,0x01,0xdb,0x28,0x00,0x01,0xdb,0x52,0x00,0x01,0xdb,0x7c,0x00,0x01,0xdb,0xac,0x00,0x01,0xdb,0xd8,0x00,0x01,0xdc,0x06,0x00,0x01,0xdc,0x34,0x00,0x01,0xdc,0x62,0x00,0x01,0xdc,0x90,0x00,0x01,0xdc,0xbe,0x00,0x01,0xdc,0xec,0x00,0x01,0xdd,0x22, 0x00,0x01,0xdd,0x56,0x00,0x01,0xdd,0x8c,0x00,0x01,0xdd,0xc0,0x00,0x01,0xdd,0xfa,0x00,0x01,0xde,0x2e,0x00,0x01,0xde,0x66,0x00,0x01,0xde,0x9a,0x00,0x01,0xdf,0x3a,0x00,0x01,0xdf,0x72,0x00,0x01,0xdf,0xa6,0x00,0x01,0xdf,0xd8,0x00,0x01,0xe0,0x08,0x00,0x01,0xe0,0x38,0x00,0x01,0xe0,0x66,0x00,0x01,0xe1,0x38,0x00,0x01,0xe2,0x3a, 0x00,0x01,0xe2,0x68,0x00,0x01,0xe2,0x96,0x00,0x01,0xe2,0xc6,0x00,0x01,0xe2,0xf6,0x00,0x01,0xe3,0xd0,0x00,0x01,0xe4,0x92,0x00,0x01,0xe4,0xc0,0x00,0x01,0xe4,0xee,0x00,0x01,0xe5,0x1e,0x00,0x01,0xe5,0x4c,0x00,0x01,0xe5,0x7a,0x00,0x01,0xe5,0xa2,0x00,0x01,0xe5,0xca,0x00,0x01,0xe5,0xf2,0x00,0x01,0xe6,0x20,0x00,0x01,0xe6,0x4e, 0x00,0x01,0xe6,0xe0,0x00,0x01,0xe7,0x62,0x00,0x01,0xe7,0x92,0x00,0x01,0xe7,0xc2,0x00,0x01,0xe7,0xf6,0x00,0x01,0xe8,0x2a,0x00,0x01,0xe8,0x58,0x00,0x01,0xe8,0x84,0x00,0x01,0xe8,0xb8,0x00,0x01,0xe8,0xec,0x00,0x01,0xe9,0x1c,0x00,0x01,0xe9,0x4a,0x00,0x01,0xe9,0x7e,0x00,0x01,0xe9,0xb2,0x00,0x01,0xe9,0xe0,0x00,0x01,0xea,0x0e, 0x00,0x01,0xea,0x42,0x00,0x01,0xea,0x76,0x00,0x01,0xea,0xa4,0x00,0x01,0xea,0xd0,0x00,0x01,0xea,0xf4,0x00,0x01,0xeb,0x28,0x00,0x01,0xeb,0x4a,0x00,0x01,0xeb,0x78,0x00,0x01,0xeb,0xac,0x00,0x01,0xeb,0xe0,0x00,0x01,0xec,0x0e,0x00,0x01,0xec,0x3a,0x00,0x01,0xed,0x02,0x00,0x01,0xed,0xc2,0x00,0x01,0xed,0xf0,0x00,0x01,0xee,0x20, 0x00,0x01,0xee,0x90,0x00,0x01,0xef,0x72,0x00,0x01,0xf0,0x48,0x00,0x01,0xf0,0xb8,0x00,0x01,0xf1,0x2c,0x00,0x01,0xf1,0x5a,0x00,0x01,0xf1,0x88,0x00,0x01,0xf1,0xbe,0x00,0x01,0xf1,0xf2,0x00,0x01,0xf2,0x24,0x00,0x01,0xf2,0x54,0x00,0x01,0xf2,0x82,0x00,0x01,0xf2,0xb0,0x00,0x01,0xf2,0xe2,0x00,0x01,0xf3,0x12,0x00,0x01,0xf3,0x40, 0x00,0x01,0xf3,0x6e,0x00,0x01,0xf3,0xfa,0x00,0x01,0xf4,0x5a,0x00,0x01,0xf4,0xf6,0x00,0x01,0xf5,0x88,0x00,0x01,0xf6,0x10,0x00,0x01,0xf6,0xbe,0x00,0x01,0xf7,0x62,0x00,0x01,0xf8,0x06,0x00,0x01,0xf8,0xb4,0x00,0x01,0xf9,0x20,0x00,0x01,0xf9,0xea,0x00,0x01,0xfa,0x98,0x00,0x01,0xfb,0x46,0x00,0x01,0xfb,0xe6,0x00,0x01,0xfc,0xda, 0x00,0x01,0xfd,0x82,0x00,0x01,0xfe,0x2c,0x00,0x01,0xff,0x1e,0x00,0x01,0xff,0xce,0x00,0x02,0x00,0x5c,0x00,0x02,0x01,0x30,0x00,0x02,0x01,0x40,0x00,0x02,0x01,0xd4,0x00,0x02,0x02,0x46,0x00,0x02,0x02,0xdc,0x00,0x02,0x03,0x42,0x00,0x02,0x03,0xca,0x00,0x02,0x04,0x76,0x00,0x02,0x05,0x16,0x00,0x02,0x05,0x5e,0x00,0x02,0x05,0xbc, 0x00,0x02,0x06,0x66,0x00,0x02,0x07,0x04,0x00,0x02,0x07,0x58,0x00,0x02,0x08,0x0e,0x00,0x02,0x08,0xb2,0x00,0x02,0x09,0x5a,0x00,0x02,0x0a,0x22,0x00,0x02,0x0a,0xa8,0x00,0x02,0x0b,0x2c,0x00,0x02,0x0b,0x98,0x00,0x02,0x0c,0x2a,0x00,0x02,0x0c,0xd6,0x00,0x02,0x0d,0x8a,0x00,0x02,0x0e,0x44,0x00,0x02,0x0e,0x98,0x00,0x02,0x0e,0xec, 0x00,0x02,0x0f,0x68,0x00,0x02,0x0f,0xc2,0x00,0x02,0x10,0x3e,0x00,0x02,0x10,0x8a,0x00,0x02,0x10,0xd6,0x00,0x02,0x11,0x66,0x00,0x02,0x12,0x04,0x00,0x02,0x12,0xda,0x00,0x02,0x13,0x4c,0x00,0x02,0x13,0xf6,0x00,0x02,0x14,0x5c,0x00,0x02,0x15,0x32,0x00,0x02,0x15,0xa6,0x00,0x02,0x16,0x1a,0x00,0x02,0x16,0xc4,0x00,0x02,0x17,0x56, 0x00,0x02,0x17,0xce,0x00,0x02,0x18,0x20,0x00,0x02,0x18,0xbe,0x00,0x02,0x19,0x36,0x00,0x02,0x19,0xa4,0x00,0x02,0x1a,0x28,0x00,0x02,0x1b,0x06,0x00,0x02,0x1b,0x9c,0x00,0x02,0x1c,0xbe,0x00,0x02,0x1d,0x38,0x00,0x02,0x1d,0xba,0x00,0x02,0x1e,0x3a,0x00,0x02,0x1e,0xb0,0x00,0x02,0x1f,0x6c,0x00,0x02,0x20,0x02,0x00,0x02,0x20,0xb2, 0x00,0x02,0x21,0x80,0x00,0x02,0x21,0xe4,0x00,0x02,0x22,0xca,0x00,0x02,0x23,0x2e,0x00,0x02,0x23,0x66,0x00,0x02,0x24,0x14,0x00,0x02,0x24,0xc4,0x00,0x02,0x25,0x72,0x00,0x02,0x26,0x3a,0x00,0x02,0x27,0x50,0x00,0x02,0x28,0xca,0x00,0x02,0x29,0xa0,0x00,0x02,0x2a,0x68,0x00,0x02,0x2b,0x74,0x00,0x02,0x2c,0x4c,0x00,0x02,0x2c,0xf4, 0x00,0x02,0x2d,0x56,0x00,0x02,0x2e,0x36,0x00,0x02,0x2e,0xac,0x00,0x02,0x2f,0x56,0x00,0x02,0x30,0x5e,0x00,0x02,0x31,0x02,0x00,0x02,0x31,0x32,0x00,0x02,0x31,0x66,0x00,0x02,0x32,0x1e,0x00,0x02,0x32,0xfe,0x00,0x02,0x34,0x18,0x00,0x02,0x34,0xb6,0x00,0x02,0x35,0x4e,0x00,0x02,0x36,0x10,0x00,0x02,0x36,0xc8,0x00,0x02,0x37,0x3e, 0x00,0x02,0x37,0xa0,0x00,0x02,0x38,0x02,0x00,0x02,0x38,0xd0,0x00,0x02,0x39,0xc4,0x00,0x02,0x3a,0xa8,0x00,0x02,0x3b,0xba,0x00,0x02,0x3c,0xc8,0x00,0x02,0x3d,0x58,0x00,0x02,0x3d,0xea,0x00,0x02,0x3e,0xb2,0x00,0x02,0x40,0x00,0x00,0x02,0x40,0xd4,0x00,0x02,0x41,0xb8,0x00,0x02,0x42,0xf4,0x00,0x02,0x43,0xd0,0x00,0x02,0x44,0xce, 0x00,0x02,0x45,0xd2,0x00,0x02,0x46,0x4c,0x00,0x02,0x46,0xd6,0x00,0x02,0x47,0xba,0x00,0x02,0x48,0x70,0x00,0x02,0x48,0x80,0x00,0x02,0x48,0x90,0x00,0x02,0x48,0xa0,0x00,0x02,0x49,0x1c,0x00,0x02,0x49,0x96,0x00,0x02,0x4a,0x52,0x00,0x02,0x4a,0xf6,0x00,0x02,0x4b,0x92,0x00,0x02,0x4c,0x2c,0x00,0x02,0x4c,0xfa,0x00,0x02,0x4d,0xc8, 0x00,0x02,0x4e,0x80,0x00,0x02,0x4f,0x38,0x00,0x02,0x50,0x42,0x00,0x02,0x51,0x58,0x00,0x02,0x52,0x78,0x00,0x02,0x53,0x64,0x00,0x02,0x54,0x86,0x00,0x02,0x55,0xb0,0x00,0x02,0x56,0xe0,0x00,0x02,0x58,0x0e,0x00,0x02,0x58,0xa4,0x00,0x02,0x59,0x40,0x00,0x02,0x5a,0x18,0x00,0x02,0x5a,0xee,0x00,0x02,0x5b,0x6c,0x00,0x02,0x5b,0xec, 0x00,0x02,0x5c,0x20,0x00,0x02,0x5c,0x54,0x00,0x02,0x5d,0x9c,0x00,0x02,0x5e,0xbc,0x00,0x02,0x5f,0xa4,0x00,0x02,0x60,0x72,0x00,0x02,0x61,0xbc,0x00,0x02,0x62,0xf2,0x00,0x02,0x63,0x14,0x00,0x02,0x63,0x44,0x00,0x02,0x63,0xca,0x00,0x02,0x64,0x42,0x00,0x02,0x65,0x62,0x00,0x02,0x65,0xb6,0x00,0x02,0x66,0x08,0x00,0x02,0x66,0x1a, 0x00,0x02,0x66,0x2c,0x00,0x02,0x68,0x1a,0x00,0x02,0x69,0x42,0x00,0x02,0x69,0xda,0x00,0x02,0x6a,0x6e,0x00,0x02,0x6b,0x40,0x00,0x02,0x6c,0x2e,0x00,0x02,0x6c,0xc4,0x00,0x02,0x6d,0x56,0x00,0x02,0x6e,0x58,0x00,0x02,0x6f,0x4a,0x00,0x02,0x6f,0xee,0x00,0x02,0x70,0x82,0x00,0x02,0x71,0x0c,0x00,0x02,0x71,0x8a,0x00,0x02,0x71,0xfc, 0x00,0x02,0x72,0x6e,0x00,0x02,0x73,0x12,0x00,0x02,0x73,0xb0,0x00,0x02,0x74,0xda,0x00,0x02,0x75,0xf8,0x00,0x02,0x76,0xc0,0x00,0x02,0x77,0x78,0x00,0x02,0x77,0xea,0x00,0x02,0x78,0x5c,0x00,0x02,0x78,0xe8,0x00,0x02,0x79,0x74,0x00,0x02,0x79,0xf6,0x00,0x02,0x7a,0x76,0x00,0x02,0x7b,0x4a,0x00,0x02,0x7c,0x1e,0x00,0x02,0x7c,0x34, 0x00,0x02,0x7c,0x4a,0x00,0x02,0x7c,0x5a,0x00,0x02,0x7c,0x88,0x00,0x02,0x7c,0xb6,0x00,0x02,0x7d,0x56,0x00,0x02,0x7d,0xf2,0x00,0x02,0x7e,0x84,0x00,0x02,0x7f,0x12,0x00,0x02,0x7f,0x8c,0x00,0x02,0x80,0x0a,0x00,0x02,0x80,0x2c,0x00,0x02,0x80,0x4e,0x00,0x02,0x80,0x82,0x00,0x02,0x80,0xb2,0x00,0x02,0x80,0xc2,0x00,0x02,0x80,0xd2, 0x00,0x02,0x81,0x00,0x00,0x02,0x81,0x2e,0x00,0x02,0x81,0xd0,0x00,0x02,0x81,0xe0,0x00,0x02,0x82,0x14,0x00,0x02,0x82,0x44,0x00,0x02,0x82,0x76,0x00,0x02,0x82,0xaa,0x00,0x02,0x82,0xde,0x00,0x02,0x83,0x10,0x00,0x02,0x83,0x9c,0x00,0x02,0x83,0xac,0x00,0x02,0x83,0xda,0x00,0x02,0x84,0x08,0x00,0x02,0x84,0x3a,0x00,0x02,0x84,0x6c, 0x00,0x02,0x84,0x9e,0x00,0x02,0x84,0xd0,0x00,0x02,0x85,0x02,0x00,0x02,0x85,0x34,0x00,0x02,0x85,0x68,0x00,0x02,0x85,0x9a,0x00,0x02,0x85,0xc8,0x00,0x02,0x85,0xf6,0x00,0x02,0x86,0x28,0x00,0x02,0x86,0x58,0x00,0x02,0x86,0x8a,0x00,0x02,0x86,0xbc,0x00,0x02,0x86,0xee,0x00,0x02,0x87,0x22,0x00,0x02,0x87,0x54,0x00,0x02,0x87,0x88, 0x00,0x02,0x87,0xee,0x00,0x02,0x87,0xfe,0x00,0x02,0x88,0xa6,0x00,0x02,0x89,0x5c,0x00,0x02,0x8a,0x18,0x00,0x02,0x8a,0xcc,0x00,0x02,0x8b,0x7a,0x00,0x02,0x8c,0x22,0x00,0x02,0x8c,0xba,0x00,0x02,0x8d,0x5a,0x00,0x02,0x8d,0xea,0x00,0x02,0x8e,0x7c,0x00,0x02,0x8f,0x20,0x00,0x02,0x8f,0xb8,0x00,0x02,0x90,0x38,0x00,0x02,0x90,0xb6, 0x00,0x02,0x91,0x46,0x00,0x02,0x92,0x10,0x00,0x02,0x92,0xb0,0x00,0x02,0x93,0x1e,0x00,0x02,0x93,0xa6,0x00,0x02,0x94,0x08,0x00,0x02,0x94,0xc8,0x00,0x02,0x95,0x7e,0x00,0x02,0x95,0xec,0x00,0x02,0x96,0x5c,0x00,0x02,0x96,0xc6,0x00,0x02,0x97,0x34,0x00,0x02,0x97,0xc8,0x00,0x02,0x98,0x34,0x00,0x02,0x98,0xdc,0x00,0x02,0x99,0x40, 0x00,0x02,0x99,0xb8,0x00,0x02,0x9a,0x48,0x00,0x02,0x9a,0xb0,0x00,0x02,0x9a,0xda,0x00,0x02,0x9b,0x16,0x00,0x02,0x9b,0x66,0x00,0x02,0x9b,0xd8,0x00,0x02,0x9c,0x74,0x00,0x02,0x9c,0xec,0x00,0x02,0x9d,0x4e,0x00,0x02,0x9d,0xb2,0x00,0x02,0x9e,0x36,0x00,0x02,0x9e,0xd0,0x00,0x02,0x9f,0x4c,0x00,0x02,0x9f,0xbe,0x00,0x02,0x9f,0xf4, 0x00,0x02,0xa0,0x48,0x00,0x02,0xa0,0x7c,0x00,0x02,0xa0,0x8c,0x00,0x02,0xa0,0xbe,0x00,0x02,0xa1,0x0a,0x00,0x02,0xa1,0x56,0x00,0x02,0xa1,0xca,0x00,0x02,0xa2,0x40,0x00,0x02,0xa2,0x9e,0x00,0x02,0xa2,0xfc,0x00,0x02,0xa3,0x46,0x00,0x02,0xa3,0x94,0x00,0x02,0xa3,0xc0,0x00,0x02,0xa3,0xd0,0x00,0x02,0xa3,0xe0,0x00,0x02,0xa4,0x10, 0x00,0x02,0xa4,0x3e,0x00,0x02,0xa4,0x50,0x00,0x02,0xa4,0x62,0x00,0x02,0xa4,0xaa,0x00,0x02,0xa4,0xda,0x00,0x02,0xa4,0xec,0x00,0x02,0xa4,0xfe,0x00,0x02,0xa5,0x42,0x00,0x02,0xa5,0x84,0x00,0x02,0xa5,0xd6,0x00,0x02,0xa6,0x02,0x00,0x02,0xa6,0x70,0x00,0x02,0xa6,0xee,0x00,0x02,0xa7,0x96,0x00,0x02,0xa7,0xc6,0x00,0x02,0xa8,0x7a, 0x00,0x02,0xa8,0xdc,0x00,0x02,0xa8,0xec,0x00,0x02,0xa9,0x24,0x00,0x02,0xa9,0x66,0x00,0x02,0xa9,0xa8,0x00,0x02,0xa9,0xea,0x00,0x02,0xaa,0x22,0x00,0x02,0xaa,0x52,0x00,0x02,0xaa,0x92,0x00,0x02,0xaa,0xd2,0x00,0x02,0xab,0x1c,0x00,0x02,0xab,0x7a,0x00,0x02,0xab,0xe4,0x00,0x02,0xac,0x3e,0x00,0x02,0xac,0xb6,0x00,0x02,0xad,0x3c, 0x00,0x02,0xad,0xac,0x00,0x02,0xae,0x0e,0x00,0x02,0xae,0x94,0x00,0x02,0xae,0xf4,0x00,0x02,0xaf,0x5e,0x00,0x02,0xaf,0xd2,0x00,0x02,0xb0,0x42,0x00,0x02,0xb0,0xa0,0x00,0x02,0xb1,0x46,0x00,0x02,0xb1,0xde,0x00,0x02,0xb2,0x4a,0x00,0x02,0xb2,0xd8,0x00,0x02,0xb3,0x32,0x00,0x02,0xb3,0xa0,0x00,0x02,0xb4,0x4a,0x00,0x02,0xb4,0xf0, 0x00,0x02,0xb5,0x86,0x00,0x02,0xb5,0xf6,0x00,0x02,0xb6,0x78,0x00,0x02,0xb6,0xdc,0x00,0x02,0xb7,0x88,0x00,0x02,0xb8,0x46,0x00,0x02,0xb8,0xf2,0x00,0x02,0xb9,0x84,0x00,0x02,0xb9,0xe2,0x00,0x02,0xba,0x4e,0x00,0x02,0xba,0xa4,0x00,0x02,0xbb,0x26,0x00,0x02,0xbb,0xa4,0x00,0x02,0xbc,0x2a,0x00,0x02,0xbc,0xb6,0x00,0x02,0xbd,0x10, 0x00,0x02,0xbd,0x7c,0x00,0x02,0xbd,0xec,0x00,0x02,0xbe,0x5a,0x00,0x02,0xbe,0xca,0x00,0x02,0xbf,0x4e,0x00,0x02,0xbf,0xde,0x00,0x02,0xc0,0x44,0x00,0x02,0xc0,0xbe,0x00,0x02,0xc1,0x3a,0x00,0x02,0xc1,0xb2,0x00,0x02,0xc2,0x58,0x00,0x02,0xc2,0xf0,0x00,0x02,0xc3,0x80,0x00,0x02,0xc3,0xde,0x00,0x02,0xc4,0x7c,0x00,0x02,0xc4,0xf8, 0x00,0x02,0xc5,0x8a,0x00,0x02,0xc6,0x2e,0x00,0x02,0xc6,0xd8,0x00,0x02,0xc7,0x70,0x00,0x02,0xc7,0xcc,0x00,0x02,0xc8,0x20,0x00,0x02,0xc8,0x88,0x00,0x02,0xc9,0x2e,0x00,0x02,0xc9,0xd8,0x00,0x02,0xca,0xa2,0x00,0x02,0xcb,0x48,0x00,0x02,0xcb,0xaa,0x00,0x02,0xcc,0x0a,0x00,0x02,0xcc,0x98,0x00,0x02,0xcd,0x1e,0x00,0x02,0xcd,0xac, 0x00,0x02,0xce,0x0c,0x00,0x02,0xce,0x70,0x00,0x02,0xce,0xda,0x00,0x02,0xcf,0x42,0x00,0x02,0xcf,0xaa,0x00,0x02,0xd0,0x22,0x00,0x02,0xd0,0xaa,0x00,0x02,0xd1,0x3e,0x00,0x02,0xd1,0xaa,0x00,0x02,0xd2,0x12,0x00,0x02,0xd2,0x76,0x00,0x02,0xd3,0x22,0x00,0x02,0xd3,0xe2,0x00,0x02,0xd4,0x90,0x00,0x02,0xd5,0x1e,0x00,0x02,0xd5,0x7c, 0x00,0x02,0xd5,0xe8,0x00,0x02,0xd6,0x58,0x00,0x02,0xd6,0xfc,0x00,0x02,0xd7,0xa2,0x00,0x02,0xd8,0x66,0x00,0x02,0xd9,0x08,0x00,0x02,0xd9,0x6c,0x00,0x02,0xd9,0xfc,0x00,0x02,0xda,0x6e,0x00,0x02,0xdb,0x06,0x00,0x02,0xdb,0x84,0x00,0x02,0xdb,0xfe,0x00,0x02,0xdc,0x6a,0x00,0x02,0xdc,0xf8,0x00,0x02,0xdd,0x54,0x00,0x02,0xdd,0xb2, 0x00,0x02,0xde,0x38,0x00,0x02,0xde,0xb4,0x00,0x02,0xdf,0x1c,0x00,0x02,0xdf,0x80,0x00,0x02,0xdf,0xd4,0x00,0x02,0xe0,0x42,0x00,0x02,0xe0,0xaa,0x00,0x02,0xe1,0x28,0x00,0x02,0xe1,0x9e,0x00,0x02,0xe2,0x18,0x00,0x02,0xe2,0x98,0x00,0x02,0xe2,0xf4,0x00,0x02,0xe3,0x5a,0x00,0x02,0xe3,0xbe,0x00,0x02,0xe4,0x5e,0x00,0x02,0xe5,0x00, 0x00,0x02,0xe5,0xbe,0x00,0x02,0xe6,0x6e,0x00,0x02,0xe6,0xca,0x00,0x02,0xe7,0x42,0x00,0x02,0xe7,0xa0,0x00,0x02,0xe8,0x2a,0x00,0x02,0xe8,0xc2,0x00,0x02,0xe9,0x50,0x00,0x02,0xe9,0xb6,0x00,0x02,0xea,0x14,0x00,0x02,0xea,0xa2,0x00,0x02,0xeb,0x14,0x00,0x02,0xeb,0xae,0x00,0x02,0xec,0x42,0x00,0x02,0xec,0xb2,0x00,0x02,0xed,0x22, 0x00,0x02,0xed,0x9a,0x00,0x02,0xed,0xf8,0x00,0x02,0xee,0x58,0x00,0x02,0xee,0xd2,0x00,0x02,0xef,0x2c,0x00,0x02,0xef,0x8c,0x00,0x02,0xef,0xe6,0x00,0x02,0xf0,0x42,0x00,0x02,0xf0,0xaa,0x00,0x02,0xf0,0xaa,0x00,0x02,0xf0,0xfa,0x00,0x02,0xf1,0x4e,0x00,0x02,0xf1,0xa0,0x00,0x02,0xf1,0xf0,0x00,0x02,0xf3,0xf0,0x00,0x02,0xf5,0x5c, 0x00,0x02,0xf7,0x10,0x00,0x02,0xf8,0xba,0x00,0x02,0xf9,0x3e,0x00,0x02,0xf9,0xde,0x00,0x02,0xfa,0x1a,0x00,0x02,0xfa,0x56,0x00,0x02,0xfa,0x8c,0x00,0x02,0xfa,0xc2,0x00,0x02,0xfb,0x3c,0x00,0x02,0xfb,0x4e,0x00,0x02,0xfb,0x60,0x00,0x02,0xfb,0x72,0x00,0x02,0xfb,0x84,0x00,0x02,0xfb,0x96,0x00,0x02,0xfb,0xd2,0x00,0x02,0xfc,0x0a, 0x00,0x02,0xfc,0x44,0x00,0x02,0xfc,0x7c,0x00,0x02,0xfc,0xd2,0x00,0x02,0xfd,0x1a,0x00,0x02,0xfd,0x92,0x00,0x02,0xfd,0xd0,0x00,0x02,0xfe,0x1a,0x00,0x02,0xfe,0x9a,0x00,0x02,0xff,0x72,0x00,0x02,0xff,0x84,0x00,0x02,0xff,0x96,0x00,0x03,0x00,0x08,0x00,0x03,0x00,0x54,0x00,0x03,0x00,0xa8,0x00,0x03,0x00,0xdc,0x00,0x03,0x01,0x10, 0x00,0x03,0x01,0x20,0x00,0x03,0x01,0x30,0x00,0x03,0x01,0xb0,0x00,0x03,0x02,0x5c,0x00,0x03,0x03,0x6e,0x00,0x03,0x04,0x24,0x00,0x03,0x04,0x34,0x00,0x03,0x04,0x90,0x00,0x03,0x05,0x1e,0x00,0x03,0x05,0x80,0x00,0x03,0x06,0x20,0x00,0x03,0x06,0x7c,0x00,0x03,0x06,0xc6,0x00,0x03,0x06,0xd6,0x00,0x03,0x07,0x50,0x00,0x03,0x07,0x60, 0x00,0x03,0x07,0x70,0x00,0x03,0x07,0x80,0x00,0x03,0x07,0xfa,0x00,0x03,0x08,0x6e,0x00,0x03,0x08,0xde,0x00,0x03,0x09,0xd6,0x00,0x03,0x0a,0xc6,0x00,0x03,0x0b,0x84,0x00,0x03,0x0b,0xd6,0x00,0x03,0x0c,0x28,0x00,0x03,0x0c,0x8e,0x00,0x03,0x0d,0x20,0x00,0x03,0x0d,0xac,0x00,0x03,0x0d,0xbc,0x00,0x03,0x0e,0x10,0x00,0x03,0x0e,0x76, 0x00,0x03,0x0f,0x3e,0x00,0x03,0x0f,0xda,0x00,0x03,0x0f,0xea,0x00,0x03,0x0f,0xfa,0x00,0x03,0x10,0x0a,0x00,0x03,0x10,0x94,0x00,0x03,0x11,0x44,0x00,0x03,0x11,0xd4,0x00,0x03,0x11,0xe4,0x00,0x03,0x12,0x30,0x00,0x03,0x12,0x40,0x00,0x03,0x12,0x50,0x00,0x03,0x12,0xe6,0x00,0x03,0x13,0x4e,0x00,0x03,0x13,0xe0,0x00,0x03,0x14,0xa2, 0x00,0x03,0x15,0x4c,0x00,0x03,0x16,0x12,0x00,0x03,0x16,0x7c,0x00,0x03,0x16,0xf0,0x00,0x03,0x17,0x62,0x00,0x03,0x18,0x00,0x00,0x03,0x18,0x7a,0x00,0x03,0x18,0xaa,0x00,0x03,0x18,0xfc,0x00,0x03,0x19,0x5e,0x00,0x03,0x19,0xa2,0x00,0x03,0x1a,0x28,0x00,0x03,0x1a,0x96,0x00,0x03,0x1b,0x04,0x00,0x03,0x1b,0x7e,0x00,0x03,0x1c,0x4c, 0x00,0x03,0x1c,0xbc,0x00,0x03,0x1d,0x50,0x00,0x03,0x1d,0xa2,0x00,0x03,0x1e,0x02,0x00,0x03,0x1e,0x7c,0x00,0x03,0x1f,0x36,0x00,0x03,0x1f,0xf0,0x00,0x03,0x20,0x84,0x00,0x03,0x21,0xb8,0x00,0x03,0x22,0x4c,0x00,0x03,0x22,0xe2,0x00,0x03,0x23,0x7c,0x00,0x03,0x24,0x12,0x00,0x03,0x24,0xc4,0x00,0x03,0x25,0x6e,0x00,0x03,0x26,0x24, 0x00,0x03,0x26,0x74,0x00,0x03,0x26,0xd6,0x00,0x03,0x27,0x86,0x00,0x03,0x28,0x14,0x00,0x03,0x28,0x8e,0x00,0x03,0x29,0x00,0x00,0x03,0x29,0x58,0x00,0x03,0x29,0xb0,0x00,0x03,0x2a,0x42,0x00,0x03,0x2a,0xc4,0x00,0x03,0x2b,0x34,0x00,0x03,0x2b,0x9e,0x00,0x03,0x2c,0x5c,0x00,0x03,0x2c,0xac,0x00,0x03,0x2d,0x4c,0x00,0x03,0x2e,0x1c, 0x00,0x03,0x2e,0x96,0x00,0x03,0x2f,0x46,0x00,0x03,0x30,0x04,0x00,0x03,0x30,0xa0,0x00,0x03,0x30,0xb2,0x00,0x03,0x30,0xc4,0x00,0x03,0x30,0xd6,0x00,0x03,0x30,0xe8,0x00,0x03,0x30,0xfa,0x00,0x03,0x31,0x0c,0x00,0x03,0x31,0x1e,0x00,0x03,0x31,0x30,0x00,0x03,0x31,0x42,0x00,0x03,0x31,0x8a,0x00,0x03,0x31,0xdc,0x00,0x03,0x32,0x5c, 0x00,0x03,0x32,0xb4,0x00,0x03,0x34,0x10,0x00,0x03,0x34,0xde,0x00,0x03,0x36,0x48,0x00,0x03,0x37,0x56,0x00,0x03,0x38,0x70,0x00,0x03,0x39,0xa2,0x00,0x03,0x3b,0x12,0x00,0x03,0x3d,0x2e,0x00,0x03,0x3d,0xe0,0x00,0x03,0x3e,0xd2,0x00,0x03,0x3f,0x6e,0x00,0x03,0x40,0x32,0x00,0x03,0x42,0x44,0x00,0x03,0x43,0x82,0x00,0x03,0x44,0x9e, 0x00,0x03,0x45,0xc8,0x00,0x03,0x46,0xb0,0x00,0x03,0x47,0x98,0x00,0x03,0x47,0xd0,0x00,0x03,0x47,0xe6,0x00,0x03,0x47,0xfc,0x00,0x03,0x48,0x14,0x00,0x03,0x48,0x2c,0x00,0x03,0x48,0x42,0x00,0x03,0x49,0x44,0x00,0x03,0x49,0xbe,0x00,0x03,0x4a,0x3a,0x00,0x03,0x4a,0x4a,0x00,0x03,0x4a,0x90,0x00,0x03,0x4b,0x58,0x00,0x03,0x4b,0x92, 0x00,0x03,0x4b,0xa4,0x00,0x03,0x4b,0xce,0x00,0x03,0x4c,0x4c,0x00,0x03,0x4c,0x7c,0x00,0x03,0x4c,0xac,0x00,0x03,0x4c,0xfe,0x00,0x03,0x4d,0x50,0x00,0x03,0x4d,0x7a,0x00,0x03,0x4d,0xa6,0x00,0x03,0x4d,0xca,0x00,0x03,0x4f,0x2c,0x00,0x03,0x50,0x20,0x00,0x03,0x50,0x4c,0x00,0x03,0x50,0x78,0x00,0x03,0x50,0xa4,0x00,0x03,0x50,0xba, 0x00,0x03,0x50,0xe8,0x00,0x03,0x51,0x16,0x00,0x03,0x51,0xcc,0x00,0x03,0x52,0x38,0x00,0x03,0x53,0x38,0x00,0x03,0x53,0x56,0x00,0x03,0x53,0x7e,0x00,0x03,0x53,0xae,0x00,0x03,0x53,0xde,0x00,0x03,0x54,0xb0,0x00,0x03,0x55,0x42,0x00,0x03,0x56,0x1c,0x00,0x03,0x56,0x34,0x00,0x03,0x56,0x58,0x00,0x03,0x56,0x7c,0x00,0x03,0x56,0xba, 0x00,0x03,0x56,0xde,0x00,0x03,0x57,0x02,0x00,0x03,0x57,0x26,0x00,0x03,0x57,0x4a,0x00,0x03,0x57,0x62,0x00,0x03,0x57,0x86,0x00,0x03,0x57,0xba,0x00,0x03,0x57,0xf8,0x00,0x03,0x58,0x2c,0x00,0x03,0x58,0x50,0x00,0x03,0x58,0x74,0x00,0x03,0x58,0x98,0x00,0x03,0x58,0xbc,0x00,0x03,0x58,0xe0,0x00,0x03,0x59,0x04,0x00,0x03,0x59,0x28, 0x00,0x03,0x59,0x4c,0x00,0x03,0x59,0x80,0x00,0x03,0x59,0xa4,0x00,0x03,0x59,0xc8,0x00,0x03,0x5a,0x4e,0x00,0x03,0x5a,0x72,0x00,0x03,0x5b,0x30,0x00,0x03,0x5b,0xca,0x00,0x03,0x5c,0x42,0x00,0x03,0x5d,0x0e,0x00,0x03,0x5d,0xec,0x00,0x03,0x5e,0x96,0x00,0x03,0x5f,0x0a,0x00,0x03,0x5f,0x92,0x00,0x03,0x5f,0xa2,0x00,0x03,0x60,0x0e, 0x00,0x03,0x60,0x94,0x00,0x03,0x60,0xe0,0x00,0x03,0x61,0x3a,0x00,0x03,0x61,0xba,0x00,0x03,0x62,0x74,0x00,0x03,0x62,0xbc,0x00,0x03,0x63,0x28,0x00,0x03,0x63,0x6a,0x00,0x03,0x64,0x3c,0x00,0x03,0x64,0xea,0x00,0x03,0x65,0x74,0x00,0x03,0x66,0x00,0x00,0x03,0x66,0x6c,0x00,0x03,0x67,0x10,0x00,0x03,0x67,0xe6,0x00,0x03,0x68,0xae, 0x00,0x03,0x69,0x20,0x00,0x03,0x69,0xc6,0x00,0x03,0x6a,0x72,0x00,0x03,0x6b,0x10,0x00,0x03,0x6b,0x6a,0x00,0x03,0x6b,0xe4,0x00,0x03,0x6c,0x30,0x00,0x03,0x6c,0x92,0x00,0x03,0x6d,0x26,0x00,0x03,0x6d,0xda,0x00,0x03,0x6e,0x74,0x00,0x03,0x6f,0x0a,0x00,0x03,0x6f,0x8e,0x00,0x03,0x70,0x12,0x00,0x03,0x70,0xd6,0x00,0x03,0x71,0x3c, 0x00,0x03,0x71,0x66,0x00,0x03,0x71,0x78,0x00,0x03,0x71,0x8a,0x00,0x03,0x71,0x9c,0x00,0x03,0x71,0xae,0x00,0x03,0x71,0xc0,0x00,0x03,0x72,0x78,0x00,0x03,0x73,0x84,0x00,0x03,0x74,0xd6,0x00,0x03,0x75,0x98,0x00,0x03,0x75,0xe6,0x00,0x03,0x76,0x26,0x00,0x03,0x76,0x64,0x00,0x03,0x76,0xa2,0x00,0x03,0x76,0xe0,0x00,0x03,0x77,0x42, 0x00,0x03,0x77,0x6a,0x00,0x03,0x77,0xb6,0x00,0x03,0x77,0xe8,0x00,0x03,0x78,0x1a,0x00,0x03,0x78,0x4c,0x00,0x03,0x78,0x7e,0x00,0x03,0x78,0xbc,0x00,0x03,0x78,0xfa,0x00,0x03,0x79,0x38,0x00,0x03,0x79,0x76,0x00,0x03,0x79,0xa8,0x00,0x03,0x79,0xda,0x00,0x03,0x7a,0x0c,0x00,0x03,0x7a,0x3e,0x00,0x03,0x7a,0x7c,0x00,0x03,0x7a,0xba, 0x00,0x03,0x7a,0xf8,0x00,0x03,0x7b,0x36,0x00,0x03,0x7b,0x68,0x00,0x03,0x7b,0x9a,0x00,0x03,0x7b,0xcc,0x00,0x03,0x7b,0xfe,0x00,0x03,0x7c,0x3c,0x00,0x03,0x7c,0x7a,0x00,0x03,0x7c,0xb8,0x00,0x03,0x7c,0xf6,0x00,0x03,0x7d,0x4a,0x00,0x03,0x7d,0x9e,0x00,0x03,0x7d,0xfc,0x00,0x03,0x7e,0x5a,0x00,0x03,0x7e,0xb0,0x00,0x03,0x7f,0x06, 0x00,0x03,0x7f,0x62,0x00,0x03,0x7f,0xbe,0x00,0x03,0x80,0x70,0x00,0x03,0x81,0x08,0x00,0x03,0x81,0xfa,0x00,0x03,0x83,0x00,0x00,0x03,0x83,0xe8,0x00,0x03,0x84,0xea,0x00,0x03,0x85,0xe4,0x00,0x03,0x86,0x8c,0x00,0x03,0x88,0x02,0x00,0x03,0x88,0xfc,0x00,0x03,0x89,0xec,0x00,0x03,0x8a,0x50,0x00,0x03,0x8b,0x26,0x00,0x03,0x8c,0x02, 0x00,0x03,0x8c,0x46,0x00,0x03,0x8c,0x7c,0x00,0x03,0x8c,0xc4,0x00,0x03,0x8d,0x0a,0x00,0x03,0x8d,0x50,0x00,0x03,0x8d,0xa6,0x00,0x03,0x8d,0xb8,0x00,0x03,0x8d,0xca,0x00,0x03,0x8d,0xdc,0x00,0x03,0x8d,0xee,0x00,0x03,0x8e,0x00,0x00,0x03,0x8e,0x12,0x00,0x03,0x8e,0x24,0x00,0x03,0x8e,0x36,0x00,0x03,0x8e,0x48,0x00,0x03,0x8e,0x5a, 0x00,0x03,0x8e,0x6c,0x00,0x03,0x8e,0x7e,0x00,0x03,0x8e,0x90,0x00,0x03,0x8e,0xa2,0x00,0x03,0x8e,0xb4,0x00,0x03,0x8e,0xd6,0x00,0x03,0x8e,0xf6,0x00,0x03,0x8f,0x16,0x00,0x03,0x8f,0x36,0x00,0x03,0x8f,0x58,0x00,0x03,0x8f,0x78,0x00,0x03,0x8f,0x9a,0x00,0x03,0x8f,0xba,0x00,0x03,0x8f,0xe0,0x00,0x03,0x90,0x02,0x00,0x03,0x90,0x22, 0x00,0x03,0x90,0x42,0x00,0x03,0x90,0x64,0x00,0x03,0x90,0x84,0x00,0x03,0x90,0xa4,0x00,0x03,0x91,0x94,0x00,0x03,0x92,0x46,0x00,0x03,0x92,0xfa,0x00,0x03,0x93,0x74,0x00,0x03,0x93,0xfc,0x00,0x03,0x94,0x82,0x00,0x03,0x95,0x1a,0x00,0x03,0x95,0x9e,0x00,0x03,0x95,0xc8,0x00,0x03,0x96,0x10,0x00,0x03,0x96,0x6a,0x00,0x03,0x96,0xe2, 0x00,0x03,0x97,0x52,0x00,0x03,0x98,0x02,0x00,0x03,0x98,0x82,0x00,0x03,0x98,0xae,0x00,0x03,0x99,0x2e,0x00,0x03,0x99,0x8e,0x00,0x03,0x99,0xf0,0x00,0x03,0x9a,0x40,0x00,0x03,0x9a,0x56,0x00,0x03,0x9a,0x6c,0x00,0x03,0x9a,0x82,0x00,0x03,0x9a,0x9a,0x00,0x03,0x9a,0xb2,0x00,0x03,0x9a,0xca,0x00,0x03,0x9a,0xe2,0x00,0x03,0x9a,0xfa, 0x00,0x03,0x9b,0x98,0x00,0x03,0x9c,0xa6,0x00,0x03,0x9c,0xbe,0x00,0x03,0x9c,0xd6,0x00,0x03,0x9d,0xe8,0x00,0x03,0x9e,0x00,0x00,0x03,0x9f,0x24,0x00,0x03,0x9f,0x78,0x00,0x03,0x9f,0xca,0x00,0x03,0xa0,0x2c,0x00,0x03,0xa1,0x2a,0x00,0x03,0xa1,0xf4,0x00,0x03,0xa2,0x9e,0x00,0x03,0xa3,0x06,0x00,0x03,0xa3,0x68,0x00,0x03,0xa3,0xd6, 0x00,0x03,0xa4,0xa6,0x00,0x03,0xa4,0xbe,0x00,0x03,0xa5,0x74,0x00,0x03,0xa6,0x5e,0x00,0x03,0xa7,0x8e,0x00,0x03,0xa7,0xa6,0x00,0x03,0xa7,0xbe,0x00,0x03,0xa7,0xd6,0x00,0x03,0xa7,0xee,0x00,0x03,0xa8,0x06,0x00,0x03,0xa8,0x16,0x00,0x03,0xa8,0x2e,0x00,0x03,0xa8,0x46,0x00,0x03,0xa8,0xde,0x00,0x03,0xa9,0x44,0x00,0x03,0xaa,0x10, 0x00,0x03,0xaa,0x28,0x00,0x03,0xaa,0x38,0x00,0x03,0xab,0x76,0x00,0x03,0xac,0x34,0x00,0x03,0xac,0x4c,0x00,0x03,0xac,0x64,0x00,0x03,0xac,0x7c,0x00,0x03,0xad,0x7e,0x00,0x03,0xad,0xdc,0x00,0x03,0xae,0x00,0x00,0x03,0xae,0x18,0x00,0x03,0xae,0x30,0x00,0x03,0xae,0x40,0x00,0x03,0xae,0x50,0x00,0x03,0xae,0x60,0x00,0x03,0xae,0x7e, 0x00,0x03,0xae,0x9c,0x00,0x03,0xae,0xc6,0x00,0x03,0xae,0xea,0x00,0x03,0xaf,0x28,0x00,0x03,0xaf,0x52,0x00,0x03,0xaf,0x6a,0x00,0x03,0xb0,0x52,0x00,0x03,0xb0,0xea,0x00,0x03,0xb1,0x00,0x00,0x03,0xb1,0x16,0x00,0x03,0xb1,0x3a,0x00,0x03,0xb1,0x50,0x00,0x03,0xb1,0x68,0x00,0x03,0xb1,0x96,0x00,0x03,0xb1,0xae,0x00,0x03,0xb1,0xc6, 0x00,0x03,0xb1,0xde,0x00,0x03,0xb1,0xf6,0x00,0x03,0xb2,0x0e,0x00,0x03,0xb2,0xdc,0x00,0x03,0xb2,0xf4,0x00,0x03,0xb3,0x6a,0x00,0x03,0xb3,0x82,0x00,0x03,0xb3,0xfa,0x00,0x03,0xb4,0x12,0x00,0x03,0xb5,0x5a,0x00,0x03,0xb5,0x72,0x00,0x03,0xb6,0xb4,0x00,0x03,0xb6,0xcc,0x00,0x03,0xb7,0xa2,0x00,0x03,0xb7,0xba,0x00,0x03,0xb8,0xaa, 0x00,0x03,0xb8,0xc2,0x00,0x03,0xb8,0xfc,0x00,0x03,0xb9,0x14,0x00,0x03,0xb9,0x2c,0x00,0x03,0xba,0x64,0x00,0x03,0xba,0xe4,0x00,0x03,0xbb,0xc6,0x00,0x03,0xbb,0xde,0x00,0x03,0xbc,0x92,0x00,0x03,0xbd,0x74,0x00,0x03,0xbe,0x48,0x00,0x03,0xbe,0x60,0x00,0x03,0xbe,0xa4,0x00,0x03,0xbf,0x76,0x00,0x03,0xbf,0xba,0x00,0x03,0xbf,0xe6, 0x00,0x03,0xc0,0xae,0x00,0x03,0xc0,0xd8,0x00,0x03,0xc1,0xba,0x00,0x03,0xc2,0x42,0x00,0x03,0xc2,0x60,0x00,0x03,0xc2,0x7e,0x00,0x03,0xc2,0x8e,0x00,0x03,0xc3,0x04,0x00,0x03,0xc3,0x14,0x00,0x03,0xc3,0x24,0x00,0x03,0xc3,0x34,0x00,0x03,0xc3,0xb6,0x00,0x03,0xc4,0x84,0x00,0x03,0xc5,0x7c,0x00,0x03,0xc6,0x18,0x00,0x03,0xc6,0x9a, 0x00,0x03,0xc6,0xb2,0x00,0x03,0xc6,0xca,0x00,0x03,0xc7,0xf2,0x00,0x03,0xc9,0x62,0x00,0x03,0xc9,0x7a,0x00,0x03,0xc9,0x92,0x00,0x03,0xca,0x66,0x00,0x03,0xca,0x76,0x00,0x03,0xca,0x8e,0x00,0x03,0xca,0xa4,0x00,0x03,0xca,0xb4,0x00,0x03,0xca,0xc4,0x00,0x03,0xca,0xdc,0x00,0x03,0xca,0xf4,0x00,0x03,0xcb,0x18,0x00,0x03,0xcb,0x28, 0x00,0x03,0xcb,0x38,0x00,0x03,0xcb,0x48,0x00,0x03,0xcb,0x58,0x00,0x03,0xcc,0x3e,0x00,0x03,0xcd,0x2e,0x00,0x03,0xcd,0xea,0x00,0x03,0xcd,0xfa,0x00,0x03,0xce,0x0a,0x00,0x03,0xce,0x1a,0x00,0x03,0xce,0xc6,0x00,0x03,0xce,0xd6,0x00,0x03,0xce,0xee,0x00,0x03,0xcf,0x06,0x00,0x03,0xcf,0x1e,0x00,0x03,0xcf,0x36,0x00,0x03,0xcf,0xcc, 0x00,0x03,0xcf,0xdc,0x00,0x03,0xcf,0xf2,0x00,0x03,0xd0,0xc6,0x00,0x03,0xd0,0xea,0x00,0x03,0xd1,0x02,0x00,0x03,0xd1,0x9e,0x00,0x03,0xd2,0x2a,0x00,0x03,0xd2,0x4e,0x00,0x03,0xd2,0x66,0x00,0x03,0xd2,0x94,0x00,0x03,0xd3,0x00,0x00,0x03,0xd3,0x48,0x00,0x03,0xd3,0x60,0x00,0x03,0xd3,0x78,0x00,0x03,0xd3,0x90,0x00,0x03,0xd3,0xa0, 0x00,0x03,0xd3,0xb0,0x00,0x03,0xd5,0xda,0x00,0x03,0xd6,0x5c,0x00,0x03,0xd6,0x8c,0x00,0x03,0xd8,0x0e,0x00,0x03,0xd8,0x7e,0x00,0x03,0xd8,0x8e,0x00,0x03,0xd9,0x40,0x00,0x03,0xd9,0x50,0x00,0x03,0xd9,0x60,0x00,0x03,0xd9,0x70,0x00,0x03,0xd9,0x80,0x00,0x03,0xda,0x94,0x00,0x03,0xda,0xa4,0x00,0x03,0xdb,0x20,0x00,0x03,0xdb,0xa2, 0x00,0x03,0xdb,0xb8,0x00,0x03,0xdb,0xce,0x00,0x03,0xdb,0xf2,0x00,0x03,0xdc,0x16,0x00,0x03,0xdc,0x2c,0x00,0x03,0xdc,0x42,0x00,0x03,0xdc,0x66,0x00,0x03,0xdc,0x92,0x00,0x03,0xdc,0xaa,0x00,0x03,0xdc,0xca,0x00,0x03,0xdc,0xe2,0x00,0x03,0xdc,0xfa,0x00,0x03,0xdd,0x12,0x00,0x03,0xdd,0x2a,0x00,0x03,0xdd,0x42,0x00,0x03,0xdd,0x5a, 0x00,0x03,0xdd,0x88,0x00,0x03,0xdd,0xb6,0x00,0x03,0xdd,0xce,0x00,0x03,0xdd,0xe6,0x00,0x03,0xdd,0xfe,0x00,0x03,0xde,0x16,0x00,0x03,0xde,0x2e,0x00,0x03,0xde,0x46,0x00,0x03,0xde,0x5e,0x00,0x03,0xde,0x76,0x00,0x03,0xde,0x9a,0x00,0x03,0xde,0xb2,0x00,0x03,0xde,0xca,0x00,0x03,0xde,0xe2,0x00,0x03,0xde,0xfa,0x00,0x03,0xdf,0x12, 0x00,0x03,0xdf,0x2a,0x00,0x03,0xdf,0x50,0x00,0x03,0xdf,0x76,0x00,0x03,0xdf,0x8e,0x00,0x03,0xdf,0xa6,0x00,0x03,0xdf,0xbe,0x00,0x03,0xdf,0xd6,0x00,0x03,0xe1,0x1a,0x00,0x03,0xe2,0x80,0x00,0x03,0xe2,0x98,0x00,0x03,0xe2,0xbe,0x00,0x03,0xe2,0xd6,0x00,0x03,0xe2,0xf6,0x00,0x03,0xe3,0x0e,0x00,0x03,0xe3,0x26,0x00,0x03,0xe3,0x3e, 0x00,0x03,0xe3,0x56,0x00,0x03,0xe3,0x6e,0x00,0x03,0xe3,0x86,0x00,0x03,0xe3,0x9e,0x00,0x03,0xe3,0xb6,0x00,0x03,0xe3,0xda,0x00,0x03,0xe3,0xf8,0x00,0x03,0xe4,0x10,0x00,0x03,0xe4,0x28,0x00,0x03,0xe4,0x48,0x00,0x03,0xe4,0x68,0x00,0x03,0xe4,0x80,0x00,0x03,0xe4,0x98,0x00,0x03,0xe4,0xb8,0x00,0x03,0xe4,0xd8,0x00,0x03,0xe4,0xf0, 0x00,0x03,0xe5,0x08,0x00,0x03,0xe5,0x20,0x00,0x03,0xe5,0x38,0x00,0x03,0xe5,0x50,0x00,0x03,0xe5,0x68,0x00,0x03,0xe5,0x80,0x00,0x03,0xe5,0x98,0x00,0x03,0xe5,0xb0,0x00,0x03,0xe6,0xca,0x00,0x03,0xe6,0xe2,0x00,0x03,0xe6,0xfa,0x00,0x03,0xe7,0x12,0x00,0x03,0xe7,0x32,0x00,0x03,0xe7,0x52,0x00,0x03,0xe7,0x72,0x00,0x03,0xe7,0x8a, 0x00,0x03,0xe7,0xa2,0x00,0x03,0xe7,0xba,0x00,0x03,0xe7,0xd2,0x00,0x03,0xe7,0xea,0x00,0x03,0xe8,0x02,0x00,0x03,0xe8,0x1a,0x00,0x03,0xe8,0x32,0x00,0x03,0xe9,0x24,0x00,0x03,0xea,0x2a,0x00,0x03,0xea,0x42,0x00,0x03,0xea,0x5a,0x00,0x03,0xea,0x72,0x00,0x03,0xea,0x8a,0x00,0x03,0xea,0xa2,0x00,0x03,0xea,0xba,0x00,0x03,0xea,0xd2, 0x00,0x03,0xea,0xea,0x00,0x03,0xeb,0x0a,0x00,0x03,0xeb,0x28,0x00,0x03,0xeb,0x56,0x00,0x03,0xeb,0x82,0x00,0x03,0xeb,0xa2,0x00,0x03,0xeb,0xc0,0x00,0x03,0xeb,0xe0,0x00,0x03,0xeb,0xfe,0x00,0x03,0xec,0x34,0x00,0x03,0xec,0x68,0x00,0x03,0xec,0x80,0x00,0x03,0xec,0x98,0x00,0x03,0xec,0xb0,0x00,0x03,0xec,0xc8,0x00,0x03,0xec,0xf0, 0x00,0x03,0xed,0x18,0x00,0x03,0xed,0xfe,0x00,0x03,0xee,0x16,0x00,0x03,0xee,0x38,0x00,0x03,0xee,0x58,0x00,0x03,0xee,0x70,0x00,0x03,0xee,0x92,0x00,0x03,0xee,0xb2,0x00,0x03,0xee,0xca,0x00,0x03,0xee,0xe2,0x00,0x03,0xee,0xfa,0x00,0x03,0xef,0x12,0x00,0x03,0xef,0x32,0x00,0x03,0xef,0x48,0x00,0x03,0xf0,0x5e,0x00,0x03,0xf0,0x82, 0x00,0x03,0xf0,0xa8,0x00,0x03,0xf0,0xc0,0x00,0x03,0xf0,0xe4,0x00,0x03,0xf0,0xfc,0x00,0x03,0xf1,0x14,0x00,0x03,0xf1,0xe8,0x00,0x03,0xf2,0xfc,0x00,0x03,0xf3,0x14,0x00,0x03,0xf3,0x2c,0x00,0x03,0xf3,0x4c,0x00,0x03,0xf3,0x64,0x00,0x03,0xf3,0x7e,0x00,0x03,0xf3,0xa0,0x00,0x03,0xf3,0xba,0x00,0x03,0xf3,0xd2,0x00,0x03,0xf5,0x4e, 0x00,0x03,0xf6,0x0e,0x00,0x03,0xf6,0xd0,0x00,0x03,0xf7,0x2c,0x00,0x03,0xf8,0x42,0x00,0x03,0xf9,0xc4,0x00,0x03,0xfb,0x5e,0x00,0x03,0xfb,0xd0,0x00,0x03,0xfc,0x46,0x00,0x03,0xfc,0xc8,0x00,0x03,0xfd,0x94,0x00,0x03,0xfe,0xae,0x00,0x03,0xff,0x2c,0x00,0x03,0xff,0xf8,0x00,0x04,0x00,0x0a,0x00,0x04,0x00,0x92,0x00,0x04,0x01,0x2c, 0x00,0x04,0x02,0x62,0x00,0x04,0x02,0xb4,0x00,0x04,0x02,0xfe,0x00,0x04,0x03,0xca,0x00,0x04,0x03,0xea,0x00,0x04,0x04,0x0a,0x00,0x04,0x04,0x2a,0x00,0x04,0x04,0x4a,0x00,0x04,0x04,0x6a,0x00,0x04,0x04,0x8a,0x00,0x04,0x04,0xaa,0x00,0x04,0x04,0xca,0x00,0x04,0x04,0xe2,0x00,0x04,0x04,0xfa,0x00,0x04,0x05,0x26,0x00,0x04,0x05,0x52, 0x00,0x04,0x05,0x70,0x00,0x04,0x05,0x8e,0x00,0x04,0x05,0xae,0x00,0x04,0x05,0xce,0x00,0x04,0x05,0xee,0x00,0x04,0x06,0x0e,0x00,0x04,0x06,0x2e,0x00,0x04,0x06,0x4e,0x00,0x04,0x06,0x7e,0x00,0x04,0x06,0xae,0x00,0x04,0x06,0xce,0x00,0x04,0x06,0xee,0x00,0x04,0x07,0xb0,0x00,0x04,0x08,0x12,0x00,0x04,0x08,0x2a,0x00,0x04,0x08,0x42, 0x00,0x04,0x08,0x6e,0x00,0x04,0x08,0x8c,0x00,0x04,0x08,0xaa,0x00,0x04,0x0b,0x1c,0x00,0x04,0x0b,0x66,0x00,0x04,0x0c,0x5e,0x00,0x04,0x0c,0xf4,0x00,0x04,0x0d,0xd6,0x00,0x04,0x0e,0x96,0x00,0x04,0x0e,0xda,0x00,0x04,0x10,0x3e,0x00,0x04,0x11,0x0a,0x00,0x04,0x11,0xda,0x00,0x04,0x12,0xa4,0x00,0x04,0x13,0xdc,0x00,0x04,0x14,0x86, 0x00,0x04,0x14,0xb6,0x00,0x04,0x15,0x7c,0x00,0x04,0x15,0xfe,0x00,0x04,0x16,0x28,0x00,0x04,0x16,0x4c,0x00,0x04,0x16,0x70,0x00,0x04,0x16,0x88,0x00,0x04,0x16,0xa0,0x00,0x04,0x16,0xb8,0x00,0x04,0x16,0xdc,0x00,0x04,0x17,0x00,0x00,0x04,0x17,0x24,0x00,0x04,0x18,0x08,0x00,0x04,0x18,0xa0,0x00,0x04,0x19,0x52,0x00,0x04,0x19,0x6a, 0x00,0x04,0x19,0x82,0x00,0x04,0x19,0xaa,0x00,0x04,0x19,0xc2,0x00,0x04,0x19,0xda,0x00,0x04,0x1b,0x8a,0x00,0x04,0x1c,0x82,0x00,0x04,0x1e,0x16,0x00,0x04,0x1f,0x10,0x00,0x04,0x20,0xae,0x00,0x04,0x21,0xbc,0x00,0x04,0x22,0xd0,0x00,0x04,0x23,0x76,0x00,0x04,0x23,0xa6,0x00,0x04,0x23,0xe0,0x00,0x04,0x24,0x1a,0x00,0x04,0x24,0x5c, 0x00,0x04,0x25,0x26,0x00,0x04,0x25,0x90,0x00,0x04,0x25,0xa8,0x00,0x04,0x25,0xc0,0x00,0x04,0x25,0xe0,0x00,0x04,0x26,0x00,0x00,0x04,0x26,0x18,0x00,0x04,0x26,0x30,0x00,0x04,0x26,0x50,0x00,0x04,0x26,0x70,0x00,0x04,0x26,0x90,0x00,0x04,0x26,0xb0,0x00,0x04,0x26,0xd4,0x00,0x04,0x26,0xf8,0x00,0x04,0x27,0x10,0x00,0x04,0x27,0x28, 0x00,0x04,0x27,0x40,0x00,0x04,0x27,0x58,0x00,0x04,0x27,0x70,0x00,0x04,0x28,0x98,0x00,0x04,0x29,0xfc,0x00,0x04,0x2a,0x14,0x00,0x04,0x2a,0x34,0x00,0x04,0x2a,0x58,0x00,0x04,0x2a,0x70,0x00,0x04,0x2a,0x88,0x00,0x04,0x2a,0xa0,0x00,0x04,0x2a,0xb8,0x00,0x04,0x2a,0xd0,0x00,0x04,0x2a,0xe8,0x00,0x04,0x2b,0x00,0x00,0x04,0x2b,0x18, 0x00,0x04,0x2b,0x30,0x00,0x04,0x2b,0x48,0x00,0x04,0x2b,0x60,0x00,0x04,0x2b,0x78,0x00,0x04,0x2b,0x90,0x00,0x04,0x2b,0xa8,0x00,0x04,0x2b,0xc0,0x00,0x04,0x2b,0xd8,0x00,0x04,0x2b,0xf0,0x00,0x04,0x2c,0x08,0x00,0x04,0x2c,0x20,0x00,0x04,0x2c,0x38,0x00,0x04,0x2c,0x50,0x00,0x04,0x2c,0x68,0x00,0x04,0x2c,0x80,0x00,0x04,0x2c,0x98, 0x00,0x04,0x2c,0xb0,0x00,0x04,0x2c,0xc8,0x00,0x04,0x2c,0xe0,0x00,0x04,0x2c,0xf8,0x00,0x04,0x2d,0x10,0x00,0x04,0x2d,0x28,0x00,0x04,0x2d,0x40,0x00,0x04,0x2d,0x58,0x00,0x04,0x2d,0x70,0x00,0x04,0x2d,0x88,0x00,0x04,0x2d,0xaa,0x00,0x04,0x2d,0xca,0x00,0x04,0x2d,0xea,0x00,0x04,0x2e,0x16,0x00,0x04,0x2e,0x42,0x00,0x04,0x2e,0x78, 0x00,0x04,0x2e,0x90,0x00,0x04,0x2e,0xa8,0x00,0x04,0x2e,0xbe,0x00,0x04,0x2e,0xd4,0x00,0x04,0x2e,0xec,0x00,0x04,0x2f,0x04,0x00,0x04,0x2f,0x1c,0x00,0x04,0x2f,0x34,0x00,0x04,0x2f,0x44,0x00,0x04,0x2f,0x64,0x00,0x04,0x2f,0x84,0x00,0x04,0x2f,0xc0,0x00,0x04,0x2f,0xfc,0x00,0x04,0x30,0x32,0x00,0x04,0x30,0x68,0x00,0x04,0x30,0xf6, 0x00,0x04,0x31,0xf0,0x00,0x04,0x32,0x88,0x00,0x04,0x32,0x98,0x00,0x04,0x32,0xce,0x00,0x04,0x32,0xf2,0x00,0x04,0x33,0xaa,0x00,0x04,0x34,0x86,0x00,0x04,0x35,0x44,0x00,0x04,0x35,0xf8,0x00,0x04,0x37,0x28,0x00,0x04,0x37,0xb4,0x00,0x04,0x38,0x7c,0x00,0x04,0x39,0x56,0x00,0x04,0x39,0x66,0x00,0x04,0x39,0x9c,0x00,0x04,0x39,0xd2, 0x00,0x04,0x39,0xe2,0x00,0x04,0x3a,0x06,0x00,0x04,0x3a,0x2a,0x00,0x04,0x3a,0x42,0x00,0x04,0x3a,0x5a,0x00,0x04,0x3b,0x5e,0x00,0x04,0x3c,0x10,0x00,0x04,0x3c,0x20,0x00,0x04,0x3c,0x30,0x00,0x04,0x3c,0x54,0x00,0x04,0x3c,0x78,0x00,0x04,0x3c,0x90,0x00,0x04,0x3c,0xa8,0x00,0x04,0x3c,0xcc,0x00,0x04,0x3c,0xf2,0x00,0x04,0x3d,0x12, 0x00,0x04,0x3d,0x32,0x00,0x04,0x3d,0x44,0x00,0x04,0x3d,0x78,0x00,0x04,0x3d,0xe2,0x00,0x04,0x3f,0x42,0x00,0x04,0x3f,0x9a,0x00,0x04,0x3f,0xaa,0x00,0x04,0x40,0x76,0x00,0x04,0x41,0x02,0x00,0x04,0x41,0x1a,0x00,0x04,0x41,0xc4,0x00,0x04,0x41,0xe8,0x00,0x04,0x42,0x0c,0x00,0x04,0x42,0x30,0x00,0x04,0x42,0x40,0x00,0x04,0x42,0x64, 0x00,0x04,0x42,0x7c,0x00,0x04,0x42,0x94,0x00,0x04,0x42,0xac,0x00,0x04,0x42,0xc4,0x00,0x04,0x43,0xb4,0x00,0x04,0x43,0xfc,0x00,0x04,0x44,0x44,0x00,0x04,0x44,0xe0,0x00,0x04,0x45,0x3e,0x00,0x04,0x45,0xba,0x00,0x04,0x46,0x1c,0x00,0x04,0x46,0x54,0x00,0x04,0x46,0xa6,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa, 0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x46,0xfa,0x00,0x04,0x47,0x98,0x00,0x04,0x47,0xb0,0x00,0x04,0x47,0xc8,0x00,0x04,0x47,0xe0, 0x00,0x04,0x47,0xf8,0x00,0x04,0x48,0x10,0x00,0x04,0x48,0x28,0x00,0x04,0x48,0x4c,0x00,0x04,0x48,0x6a,0x00,0x04,0x48,0x82,0x00,0x04,0x48,0x9a,0x00,0x04,0x48,0xb2,0x00,0x04,0x48,0xca,0x00,0x04,0x48,0xda,0x00,0x04,0x48,0xea,0x00,0x04,0x49,0xb8,0x00,0x04,0x4a,0x20,0x00,0x04,0x4a,0x30,0x00,0x04,0x4a,0x40,0x00,0x04,0x4a,0x50, 0x00,0x04,0x4a,0x60,0x00,0x04,0x4b,0x4e,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x60,0x00,0x04,0x4b,0x8a,0x00,0x04,0x4b,0xb4,0x00,0x04,0x4b,0xfe,0x00,0x04,0x4c,0x3c,0x00,0x04,0x4c,0x82,0x00,0x04,0x4c,0xc2, 0x00,0x04,0x4d,0x24,0x00,0x04,0x4d,0x34,0x00,0x04,0x4d,0x66,0x00,0x04,0x4d,0xd6,0x00,0x04,0x4e,0xac,0x00,0x04,0x4f,0x30,0x00,0x04,0x4f,0x58,0x00,0x04,0x4f,0x80,0x00,0x04,0x4f,0xa8,0x00,0x04,0x4f,0xd0,0x00,0x04,0x4f,0xf8,0x00,0x04,0x50,0x20,0x00,0x04,0x50,0xc0,0x00,0x04,0x51,0x2a,0x00,0x04,0x51,0xd8,0x00,0x04,0x52,0x74, 0x00,0x04,0x53,0x2a,0x00,0x04,0x53,0x9e,0x00,0x04,0x53,0xcc,0x00,0x04,0x54,0x80,0x00,0x04,0x54,0x90,0x00,0x04,0x55,0x78,0x00,0x04,0x56,0x5c,0x00,0x04,0x56,0x98,0x00,0x04,0x56,0xd4,0x00,0x04,0x57,0x32,0x00,0x04,0x57,0x8e,0x00,0x04,0x57,0xee,0x00,0x04,0x58,0x2a,0x00,0x04,0x58,0x3a,0x00,0x04,0x58,0x7c,0x00,0x04,0x58,0xb6, 0x00,0x04,0x58,0xc6,0x00,0x04,0x58,0xec,0x00,0x04,0x59,0x12,0x00,0x04,0x59,0x8c,0x00,0x04,0x5a,0x38,0x00,0x04,0x5a,0xca,0x00,0x04,0x5b,0x6c,0x00,0x04,0x5b,0xb4,0x00,0x04,0x5c,0x30,0x00,0x04,0x5c,0xe2,0x00,0x04,0x5d,0x0e,0x00,0x04,0x5d,0x4a,0x00,0x04,0x5d,0x8e,0x00,0x04,0x5e,0x34,0x00,0x04,0x5e,0x76,0x00,0x04,0x5e,0xa0, 0x00,0x04,0x5e,0xd0,0x00,0x04,0x5e,0xf8,0x00,0x04,0x5f,0x26,0x00,0x04,0x5f,0x6a,0x00,0x04,0x5f,0xae,0x00,0x04,0x60,0x30,0x00,0x04,0x60,0x74,0x00,0x04,0x60,0xba,0x00,0x04,0x61,0x84,0x00,0x04,0x62,0x2a,0x00,0x04,0x62,0xe0,0x00,0x04,0x63,0x52,0x00,0x04,0x63,0xe4,0x00,0x04,0x64,0x14,0x00,0x04,0x64,0xa4,0x00,0x04,0x65,0x1e, 0x00,0x04,0x65,0xd4,0x00,0x04,0x66,0x02,0x00,0x04,0x66,0x6c,0x00,0x04,0x67,0x16,0x00,0x04,0x67,0xd6,0x00,0x04,0x68,0x5c,0x00,0x04,0x69,0x3c,0x00,0x04,0x69,0x6e,0x00,0x04,0x69,0xf2,0x00,0x04,0x6a,0x9a,0x00,0x04,0x6b,0x26,0x00,0x04,0x6b,0xbc,0x00,0x04,0x6c,0x86,0x00,0x04,0x6d,0x3e,0x00,0x04,0x6d,0xda,0x00,0x04,0x6e,0xaa, 0x00,0x04,0x6f,0x12,0x00,0x04,0x70,0x04,0x00,0x04,0x70,0xce,0x00,0x04,0x70,0xe6,0x00,0x04,0x70,0xfe,0x00,0x04,0x71,0x16,0x00,0x04,0x71,0x44,0x00,0x04,0x71,0x90,0x00,0x04,0x71,0xa8,0x00,0x04,0x71,0xc0,0x00,0x04,0x71,0xd6,0x00,0x04,0x71,0xf4,0x00,0x04,0x72,0x5a,0x00,0x04,0x72,0xe0,0x00,0x04,0x72,0xf0,0x00,0x04,0x73,0x00, 0x00,0x04,0x73,0x10,0x00,0x04,0x73,0x20,0x00,0x04,0x73,0x30,0x00,0x04,0x73,0x40,0x00,0x04,0x73,0x50,0x00,0x04,0x73,0x60,0x00,0x04,0x73,0xa0,0x00,0x04,0x73,0xb8,0x00,0x04,0x73,0xd0,0x00,0x04,0x73,0xf0,0x00,0x04,0x74,0x10,0x00,0x04,0x74,0x28,0x00,0x04,0x74,0x40,0x00,0x04,0x74,0x58,0x00,0x04,0x74,0x70,0x00,0x04,0x74,0x88, 0x00,0x04,0x74,0xa0,0x00,0x04,0x74,0xb8,0x00,0x04,0x74,0xce,0x00,0x04,0x74,0xe4,0x00,0x04,0x74,0xfc,0x00,0x04,0x75,0x14,0x00,0x04,0x75,0x2c,0x00,0x04,0x75,0x44,0x00,0x04,0x75,0x5c,0x00,0x04,0x75,0x74,0x00,0x04,0x75,0x8c,0x00,0x04,0x75,0xa4,0x00,0x04,0x75,0xbc,0x00,0x04,0x75,0xd4,0x00,0x04,0x75,0xec,0x00,0x04,0x76,0x04, 0x00,0x04,0x76,0x1c,0x00,0x04,0x76,0x34,0x00,0x04,0x76,0x4c,0x00,0x04,0x76,0x64,0x00,0x04,0x76,0x7c,0x00,0x04,0x76,0x94,0x00,0x04,0x76,0xac,0x00,0x04,0x77,0x4e,0x00,0x04,0x79,0x8e,0x00,0x04,0x79,0xcc,0x00,0x04,0x79,0xf6,0x00,0x04,0x7a,0x06,0x00,0x04,0x7a,0x1e,0x00,0x04,0x7a,0x36,0x00,0x04,0x7a,0x4e,0x00,0x04,0x7a,0xc2, 0x00,0x04,0x7b,0x6c,0x00,0x04,0x7b,0xc2,0x00,0x04,0x7c,0x38,0x00,0x04,0x7c,0xc4,0x00,0x04,0x7d,0x04,0x00,0x04,0x7d,0x30,0x00,0x04,0x7d,0xea,0x00,0x04,0x7e,0x2a,0x00,0x04,0x7e,0x8a,0x00,0x04,0x7e,0xfc,0x00,0x04,0x7f,0x3c,0x00,0x04,0x7f,0x7c,0x00,0x04,0x7f,0xee,0x00,0x04,0x80,0xd4,0x00,0x04,0x81,0x50,0x00,0x04,0x81,0xb8, 0x00,0x04,0x82,0x30,0x00,0x04,0x82,0x64,0x00,0x04,0x82,0xc4,0x00,0x04,0x83,0x04,0x00,0x04,0x83,0x76,0x00,0x04,0x83,0xcc,0x00,0x04,0x84,0x0c,0x00,0x04,0x84,0x86,0x00,0x04,0x84,0x96,0x00,0x04,0x84,0xe6,0x00,0x04,0x85,0x18,0x00,0x04,0x85,0x58,0x00,0x04,0x86,0x14,0x00,0x04,0x86,0x78,0x00,0x04,0x86,0x88,0x00,0x04,0x87,0x06, 0x00,0x04,0x87,0x1e,0x00,0x04,0x87,0x66,0x00,0x04,0x88,0x4c,0x00,0x04,0x88,0xf0,0x00,0x04,0x89,0x9a,0x00,0x04,0x8a,0x92,0x00,0x04,0x8b,0x26,0x00,0x04,0x8b,0xe8,0x00,0x04,0x8c,0xa6,0x00,0x04,0x8d,0x6a,0x00,0x04,0x8d,0xa2,0x00,0x04,0x8e,0x72,0x00,0x04,0x8f,0x44,0x00,0x04,0x90,0x30,0x00,0x04,0x90,0xbc,0x00,0x04,0x92,0x1a, 0x00,0x04,0x92,0x9e,0x00,0x04,0x93,0x30,0x00,0x04,0x93,0xe4,0x00,0x04,0x94,0x76,0x00,0x04,0x95,0x16,0x00,0x04,0x96,0x70,0x00,0x04,0x97,0x68,0x00,0x04,0x97,0xe8,0x00,0x04,0x98,0x56,0x00,0x04,0x98,0xd0,0x00,0x04,0x99,0x92,0x00,0x04,0x9a,0x12,0x00,0x04,0x9a,0xfa,0x00,0x04,0x9b,0xd6,0x00,0x04,0x9c,0x8a,0x00,0x04,0x9d,0xc4, 0x00,0x04,0x9e,0x52,0x00,0x04,0x9f,0x02,0x00,0x04,0x9f,0x98,0x00,0x04,0xa0,0x2e,0x00,0x04,0xa0,0xe4,0x00,0x04,0xa1,0x66,0x00,0x04,0xa1,0xea,0x00,0x04,0xa2,0xe4,0x00,0x04,0xa3,0xc0,0x00,0x04,0xa4,0xbe,0x00,0x04,0xa6,0x06,0x00,0x04,0xa7,0xe6,0x00,0x04,0xa8,0xd0,0x00,0x04,0xaa,0x1e,0x00,0x04,0xab,0x34,0x00,0x04,0xac,0xb0, 0x00,0x04,0xad,0x90,0x00,0x04,0xae,0x9e,0x00,0x04,0xb1,0x10,0x00,0x04,0xb2,0x16,0x00,0x04,0xb3,0x1a,0x00,0x04,0xb4,0x7e,0x00,0x04,0xb5,0xc2,0x00,0x04,0xb6,0xd6,0x00,0x04,0xb8,0xb0,0x00,0x04,0xb9,0x70,0x00,0x04,0xbb,0x5c,0x00,0x04,0xbd,0x34,0x00,0x04,0xbf,0x22,0x00,0x04,0xc0,0x4c,0x00,0x04,0xc1,0xf0,0x00,0x04,0xc3,0x60, 0x00,0x04,0xc4,0xa0,0x00,0x04,0xc5,0x9a,0x00,0x04,0xc6,0xf4,0x00,0x04,0xc7,0xcc,0x00,0x04,0xc9,0x6e,0x00,0x04,0xcb,0x30,0x00,0x04,0xcc,0x28,0x00,0x04,0xce,0x26,0x00,0x04,0xcf,0x78,0x00,0x04,0xd1,0x0a,0x00,0x04,0xd2,0x8c,0x00,0x04,0xd3,0xa4,0x00,0x04,0xd5,0x42,0x00,0x04,0xd6,0x64,0x00,0x04,0xd7,0xf0,0x00,0x04,0xd9,0x3c, 0x00,0x04,0xda,0x58,0x00,0x04,0xdb,0xb2,0x00,0x04,0xdc,0xda,0x00,0x04,0xdd,0x7c,0x00,0x04,0xde,0x6a,0x00,0x04,0xdf,0x8c,0x00,0x04,0xe0,0xb2,0x00,0x04,0xe2,0x08,0x00,0x04,0xe3,0xbe,0x00,0x04,0xe4,0xbe,0x00,0x04,0xe6,0x0e,0x00,0x04,0xe7,0x6e,0x00,0x04,0xe9,0x48,0x00,0x04,0xe9,0xfc,0x00,0x04,0xeb,0x40,0x00,0x04,0xec,0xe8, 0x00,0x04,0xee,0x6c,0x00,0x04,0xef,0xaa,0x00,0x04,0xf1,0x0c,0x00,0x04,0xf2,0x3a,0x00,0x04,0xf3,0x6a,0x00,0x04,0xf4,0xe6,0x00,0x04,0xf5,0xe2,0x00,0x04,0xf7,0x42,0x00,0x04,0xf8,0xc6,0x00,0x04,0xfa,0xc8,0x00,0x04,0xfc,0x22,0x00,0x04,0xfd,0x16,0x00,0x04,0xfe,0x04,0x00,0x04,0xff,0x1c,0x00,0x05,0x00,0x54,0x00,0x05,0x01,0x9c, 0x00,0x05,0x03,0x02,0x00,0x05,0x04,0x58,0x00,0x05,0x05,0xf8,0x00,0x05,0x07,0x50,0x00,0x05,0x08,0x46,0x00,0x05,0x09,0xaa,0x00,0x05,0x0a,0xb2,0x00,0x05,0x0b,0x62,0x00,0x05,0x0c,0x98,0x00,0x05,0x0d,0x88,0x00,0x05,0x0f,0x2a,0x00,0x05,0x10,0x08,0x00,0x05,0x10,0xc4,0x00,0x05,0x11,0xa0,0x00,0x05,0x12,0x42,0x00,0x05,0x12,0xe8, 0x00,0x05,0x13,0xee,0x00,0x05,0x14,0x5e,0x00,0x05,0x14,0xe0,0x00,0x05,0x16,0x2a,0x00,0x05,0x16,0xfe,0x00,0x05,0x17,0xb0,0x00,0x05,0x18,0x04,0x00,0x05,0x18,0xc0,0x00,0x05,0x1a,0x34,0x00,0x05,0x1a,0xca,0x00,0x05,0x1b,0xa8,0x00,0x05,0x1d,0x26,0x00,0x05,0x1d,0xb8,0x00,0x05,0x1e,0x9a,0x00,0x05,0x1f,0x2e,0x00,0x05,0x20,0x76, 0x00,0x05,0x21,0x06,0x00,0x05,0x22,0x18,0x00,0x05,0x22,0xa6,0x00,0x05,0x23,0xae,0x00,0x05,0x24,0x5e,0x00,0x05,0x25,0xc4,0x00,0x05,0x26,0x6e,0x00,0x05,0x26,0xfe,0x00,0x05,0x27,0x96,0x00,0x05,0x28,0xf2,0x00,0x05,0x29,0x78,0x00,0x05,0x2a,0xd4,0x00,0x05,0x2b,0x7e,0x00,0x05,0x2c,0x88,0x00,0x05,0x2d,0xae,0x00,0x05,0x2e,0x98, 0x00,0x05,0x2f,0xba,0x00,0x05,0x30,0x3a,0x00,0x05,0x30,0x94,0x00,0x05,0x30,0xd4,0x00,0x05,0x31,0x44,0x00,0x05,0x31,0x90,0x00,0x05,0x32,0xae,0x00,0x05,0x32,0xfe,0x00,0x05,0x33,0xee,0x00,0x05,0x34,0x92,0x00,0x05,0x35,0x6a,0x00,0x05,0x36,0x0e,0x00,0x05,0x36,0xb8,0x00,0x05,0x37,0x80,0x00,0x05,0x37,0xd0,0x00,0x05,0x38,0x6e, 0x00,0x05,0x39,0x96,0x00,0x05,0x3a,0x5a,0x00,0x05,0x3a,0xe4,0x00,0x05,0x3b,0x1e,0x00,0x05,0x3b,0xf6,0x00,0x05,0x3d,0x38,0x00,0x05,0x3d,0xae,0x00,0x05,0x3e,0x82,0x00,0x05,0x3f,0xa2,0x00,0x05,0x40,0x3e,0x00,0x05,0x41,0x46,0x00,0x05,0x41,0xc8,0x00,0x05,0x42,0x08,0x00,0x05,0x42,0x88,0x00,0x05,0x43,0x7a,0x00,0x05,0x44,0x4e, 0x00,0x05,0x45,0x3a,0x00,0x05,0x45,0xf6,0x00,0x05,0x47,0x36,0x00,0x05,0x47,0xda,0x00,0x05,0x48,0xba,0x00,0x05,0x49,0x40,0x00,0x05,0x4a,0x02,0x00,0x05,0x4a,0x92,0x00,0x05,0x4b,0xaa,0x00,0x05,0x4b,0xe4,0x00,0x05,0x4c,0xaa,0x00,0x05,0x4d,0x7a,0x00,0x05,0x4e,0x54,0x00,0x05,0x4f,0x90,0x00,0x05,0x50,0x14,0x00,0x05,0x50,0x96, 0x00,0x05,0x50,0xf4,0x00,0x05,0x51,0xd8,0x00,0x05,0x52,0xde,0x00,0x05,0x53,0xca,0x00,0x05,0x54,0xbe,0x00,0x05,0x55,0xda,0x00,0x05,0x56,0xb6,0x00,0x05,0x57,0x24,0x00,0x05,0x57,0x34,0x00,0x05,0x57,0xac,0x00,0x05,0x58,0x04,0x00,0x05,0x58,0xa2,0x00,0x05,0x59,0x60,0x00,0x05,0x59,0xde,0x00,0x05,0x5a,0x80,0x00,0x05,0x5b,0x4c, 0x00,0x05,0x5b,0xb6,0x00,0x05,0x5c,0xce,0x00,0x05,0x5d,0x96,0x00,0x05,0x5d,0xa6,0x00,0x05,0x5d,0xfe,0x00,0x05,0x5e,0x0e,0x00,0x05,0x5e,0x1e,0x00,0x05,0x5e,0x2e,0x00,0x05,0x5e,0x3e,0x00,0x05,0x5e,0x4e,0x00,0x05,0x5e,0x5e,0x00,0x05,0x5e,0x6e,0x00,0x05,0x5e,0x7e,0x00,0x05,0x5e,0xfa,0x00,0x05,0x5f,0x58,0x00,0x05,0x60,0x02, 0x00,0x05,0x60,0xd0,0x00,0x05,0x61,0x4c,0x00,0x05,0x61,0xf6,0x00,0x05,0x62,0xc2,0x00,0x05,0x63,0x2e,0x00,0x05,0x64,0x46,0x00,0x05,0x65,0x10,0x00,0x05,0x65,0xe4,0x00,0x05,0x66,0x8e,0x00,0x05,0x67,0x82,0x00,0x05,0x68,0xcc,0x00,0x05,0x69,0x9e,0x00,0x05,0x6a,0x9e,0x00,0x05,0x6b,0xbc,0x00,0x05,0x6c,0xa0,0x00,0x05,0x6e,0x1c, 0x00,0x05,0x6f,0x50,0x00,0x05,0x6f,0xb4,0x00,0x05,0x6f,0xd0,0x00,0x05,0x6f,0xec,0x00,0x05,0x70,0x08,0x00,0x05,0x70,0x26,0x00,0x05,0x70,0x42,0x00,0x05,0x71,0x0c,0x00,0x05,0x71,0x28,0x00,0x05,0x71,0x48,0x00,0x05,0x72,0x18,0x00,0x05,0x72,0x90,0x00,0x05,0x73,0x46,0x00,0x05,0x73,0xba,0x00,0x05,0x74,0x2a,0x00,0x05,0x74,0x96, 0x00,0x05,0x74,0xec,0x00,0x05,0x75,0x82,0x00,0x05,0x75,0xd8,0x00,0x05,0x76,0x00,0x00,0x05,0x76,0x52,0x00,0x05,0x76,0xcc,0x00,0x05,0x77,0x02,0x00,0x05,0x77,0x94,0x00,0x05,0x78,0x02,0x00,0x05,0x78,0x88,0x00,0x05,0x78,0xfa,0x00,0x05,0x79,0x98,0x00,0x05,0x7a,0x36,0x00,0x05,0x7a,0xf6,0x00,0x05,0x7b,0x3a,0x00,0x05,0x7b,0x9c, 0x00,0x05,0x7b,0xee,0x00,0x05,0x7c,0x80,0x00,0x05,0x7c,0xf0,0x00,0x05,0x7d,0x50,0x00,0x05,0x7d,0xa6,0x00,0x05,0x7e,0x4c,0x00,0x05,0x7f,0x26,0x00,0x05,0x7f,0x92,0x00,0x05,0x80,0x5c,0x00,0x05,0x80,0xda,0x00,0x05,0x81,0x74,0x00,0x05,0x82,0x50,0x00,0x05,0x82,0x74,0x00,0x05,0x82,0x98,0x00,0x05,0x82,0xbc,0x00,0x05,0x82,0xe0, 0x00,0x05,0x83,0x04,0x00,0x05,0x83,0x28,0x00,0x05,0x83,0x40,0x00,0x05,0x83,0x62,0x00,0x05,0x83,0x86,0x00,0x05,0x83,0xa8,0x00,0x05,0x83,0xcc,0x00,0x05,0x83,0xee,0x00,0x05,0x84,0x10,0x00,0x05,0x84,0x32,0x00,0x05,0x84,0x58,0x00,0x05,0x84,0x7c,0x00,0x05,0x84,0xa0,0x00,0x05,0x84,0xc4,0x00,0x05,0x84,0xe8,0x00,0x05,0x85,0x0c, 0x00,0x05,0x85,0x32,0x00,0x05,0x85,0x56,0x00,0x05,0x85,0x7a,0x00,0x05,0x85,0x9e,0x00,0x05,0x85,0xc4,0x00,0x05,0x85,0xe8,0x00,0x05,0x86,0x0c,0x00,0x05,0x86,0x30,0x00,0x05,0x86,0x48,0x00,0x05,0x86,0x6c,0x00,0x05,0x86,0x90,0x00,0x05,0x86,0xb4,0x00,0x05,0x86,0xd8,0x00,0x05,0x86,0xe8,0x00,0x05,0x87,0x0c,0x00,0x05,0x87,0x30, 0x00,0x05,0x87,0x54,0x00,0x05,0x87,0x6c,0x00,0x05,0x87,0x8e,0x00,0x05,0x87,0xb2,0x00,0x05,0x87,0xca,0x00,0x05,0x87,0xee,0x00,0x05,0x88,0x12,0x00,0x05,0x88,0xa4,0x00,0x05,0x88,0xc6,0x00,0x05,0x88,0xe8,0x00,0x05,0x89,0x0a,0x00,0x05,0x89,0x20,0x00,0x05,0x89,0x42,0x00,0x05,0x89,0x5a,0x00,0x05,0x89,0x7c,0x00,0x05,0x89,0x94, 0x00,0x05,0x89,0xb6,0x00,0x05,0x89,0xcc,0x00,0x05,0x89,0xe4,0x00,0x05,0x89,0xfc,0x00,0x05,0x8a,0x20,0x00,0x05,0x8a,0x38,0x00,0x05,0x8a,0x5c,0x00,0x05,0x8b,0x04,0x00,0x05,0x8b,0x28,0x00,0x05,0x8b,0x4c,0x00,0x05,0x8b,0x72,0x00,0x05,0x8b,0x96,0x00,0x05,0x8b,0xae,0x00,0x05,0x8b,0xd2,0x00,0x05,0x8b,0xf6,0x00,0x05,0x8c,0x18, 0x00,0x05,0x8c,0x30,0x00,0x05,0x8c,0x52,0x00,0x05,0x8c,0x6a,0x00,0x05,0x8c,0x80,0x00,0x05,0x8c,0xa2,0x00,0x05,0x8d,0x1c,0x00,0x05,0x8d,0x40,0x00,0x05,0x8d,0x64,0x00,0x05,0x8d,0x88,0x00,0x05,0x8d,0xae,0x00,0x05,0x8d,0xd4,0x00,0x05,0x8d,0xec,0x00,0x05,0x8e,0x10,0x00,0x05,0x8e,0x34,0x00,0x05,0x8e,0x58,0x00,0x05,0x8e,0x7e, 0x00,0x05,0x8e,0xa0,0x00,0x05,0x8e,0xc4,0x00,0x05,0x8e,0xe6,0x00,0x05,0x8f,0x0a,0x00,0x05,0x8f,0x2e,0x00,0x05,0x8f,0x52,0x00,0x05,0x8f,0x9e,0x00,0x05,0x8f,0xc2,0x00,0x05,0x8f,0xe6,0x00,0x05,0x8f,0xf6,0x00,0x05,0x90,0x06,0x00,0x05,0x90,0x40,0x00,0x05,0x90,0xa6,0x00,0x05,0x90,0xb6,0x00,0x05,0x90,0xc6,0x00,0x05,0x90,0xd6, 0x00,0x05,0x91,0x7c,0x00,0x05,0x91,0x8c,0x00,0x05,0x91,0x9c,0x00,0x05,0x91,0xfa,0x00,0x05,0x92,0x0a,0x00,0x05,0x92,0x1a,0x00,0x05,0x92,0x82,0x00,0x05,0x92,0x92,0x00,0x05,0x92,0xd2,0x00,0x05,0x92,0xe2,0x00,0x05,0x93,0x4e,0x00,0x05,0x93,0x5e,0x00,0x05,0x93,0x6e,0x00,0x05,0x94,0x4e,0x00,0x05,0x94,0x5e,0x00,0x05,0x94,0xe8, 0x00,0x05,0x95,0x8e,0x00,0x05,0x95,0xb2,0x00,0x05,0x95,0xd6,0x00,0x05,0x95,0xfa,0x00,0x05,0x96,0x1c,0x00,0x05,0x96,0x40,0x00,0x05,0x96,0x64,0x00,0x05,0x96,0x88,0x00,0x05,0x96,0xae,0x00,0x05,0x96,0xd2,0x00,0x05,0x96,0xf6,0x00,0x05,0x97,0x8c,0x00,0x05,0x97,0xb0,0x00,0x05,0x98,0x36,0x00,0x05,0x98,0x46,0x00,0x05,0x98,0x56, 0x00,0x05,0x98,0x7c,0x00,0x05,0x98,0x8c,0x00,0x05,0x99,0x5c,0x00,0x05,0x9a,0x0a,0x00,0x05,0x9a,0x7e,0x00,0x05,0x9a,0xa2,0x00,0x05,0x9a,0xc6,0x00,0x05,0x9b,0x24,0x00,0x05,0x9b,0x34,0x00,0x05,0x9b,0xba,0x00,0x05,0x9b,0xca,0x00,0x05,0x9b,0xda,0x00,0x05,0x9c,0x78,0x00,0x05,0x9c,0x88,0x00,0x05,0x9d,0x0c,0x00,0x05,0x9d,0xc6, 0x00,0x05,0x9e,0x38,0x00,0x05,0x9e,0x5c,0x00,0x05,0x9e,0x6c,0x00,0x05,0x9e,0xf0,0x00,0x05,0x9f,0x00,0x00,0x05,0x9f,0x10,0x00,0x05,0x9f,0x20,0x00,0x05,0x9f,0x30,0x00,0x05,0x9f,0x40,0x00,0x05,0x9f,0x50,0x00,0x05,0x9f,0x60,0x00,0x05,0x9f,0xdc,0x00,0x05,0x9f,0xec,0x00,0x05,0x9f,0xfc,0x00,0x05,0xa0,0x56,0x00,0x05,0xa0,0xc8, 0x00,0x05,0xa1,0x26,0x00,0x05,0xa1,0x9a,0x00,0x05,0xa2,0x20,0x00,0x05,0xa2,0xae,0x00,0x05,0xa3,0x20,0x00,0x05,0xa3,0xa6,0x00,0x05,0xa4,0x66,0x00,0x05,0xa5,0x1a,0x00,0x05,0xa5,0x5e,0x00,0x05,0xa5,0xee,0x00,0x05,0xa6,0x78,0x00,0x05,0xa7,0x4c,0x00,0x05,0xa8,0x3e,0x00,0x05,0xa9,0x24,0x00,0x05,0xaa,0xb0,0x00,0x05,0xaa,0xd4, 0x00,0x05,0xaa,0xf8,0x00,0x05,0xab,0x0e,0x00,0x05,0xab,0x1e,0x00,0x05,0xab,0x2e,0x00,0x05,0xab,0x4e,0x00,0x05,0xab,0x5e,0x00,0x05,0xab,0x6e,0x00,0x05,0xab,0x8e,0x00,0x05,0xab,0x9e,0x00,0x05,0xab,0xae,0x00,0x05,0xab,0xcc,0x00,0x05,0xab,0xdc,0x00,0x05,0xab,0xec,0x00,0x05,0xac,0x0a,0x00,0x05,0xac,0x1a,0x00,0x05,0xac,0x2a, 0x00,0x05,0xac,0x48,0x00,0x05,0xac,0x58,0x00,0x05,0xac,0x68,0x00,0x05,0xac,0x78,0x00,0x05,0xac,0x88,0x00,0x05,0xac,0x98,0x00,0x05,0xac,0xb8,0x00,0x05,0xac,0xd6,0x00,0x05,0xac,0xe6,0x00,0x05,0xac,0xf6,0x00,0x05,0xad,0x14,0x00,0x05,0xad,0x32,0x00,0x05,0xad,0x42,0x00,0x05,0xad,0x52,0x00,0x05,0xad,0x62,0x00,0x05,0xad,0x84, 0x00,0x05,0xad,0x94,0x00,0x05,0xad,0xb4,0x00,0x05,0xad,0xc4,0x00,0x05,0xad,0xe2,0x00,0x05,0xad,0xf2,0x00,0x05,0xae,0x02,0x00,0x05,0xae,0x12,0x00,0x05,0xae,0x30,0x00,0x05,0xae,0x4e,0x00,0x05,0xae,0x6e,0x00,0x05,0xae,0x7e,0x00,0x05,0xae,0x8e,0x00,0x05,0xae,0xa6,0x00,0x05,0xae,0xbe,0x00,0x05,0xae,0xce,0x00,0x05,0xae,0xde, 0x00,0x05,0xae,0xf6,0x00,0x05,0xaf,0x0e,0x00,0x05,0xaf,0x9c,0x00,0x05,0xb0,0xde,0x00,0x05,0xb2,0x14,0x00,0x05,0xb2,0x84,0x00,0x05,0xb2,0xe0,0x00,0x05,0xb3,0x7c,0x00,0x05,0xb4,0x44,0x00,0x05,0xb4,0xf6,0x00,0x05,0xb5,0xa2,0x00,0x05,0xb6,0x02,0x00,0x05,0xb6,0x5c,0x00,0x05,0xb6,0xbc,0x00,0x05,0xb7,0x64,0x00,0x05,0xb7,0x92, 0x00,0x05,0xb7,0xc2,0x00,0x05,0xb7,0xf0,0x00,0x05,0xb8,0x20,0x00,0x05,0xb8,0x38,0x00,0x05,0xb8,0x6a,0x00,0x05,0xb8,0x82,0x00,0x05,0xb8,0x9a,0x00,0x05,0xb8,0xb2,0x00,0x05,0xb8,0xca,0x00,0x05,0xb8,0xe2,0x00,0x05,0xb8,0xf8,0x00,0x05,0xb9,0x28,0x00,0x05,0xb9,0x3e,0x00,0x05,0xb9,0x54,0x00,0x05,0xb9,0x64,0x00,0x05,0xb9,0xc2, 0x00,0x05,0xba,0x16,0x00,0x05,0xba,0x2c,0x00,0x05,0xba,0x42,0x00,0x05,0xbb,0x5c,0x00,0x05,0xbc,0x64,0x00,0x05,0xbd,0x4c,0x00,0x05,0xbe,0x84,0x00,0x05,0xbf,0x26,0x00,0x05,0xbf,0xe0,0x00,0x05,0xc0,0x0c,0x00,0x05,0xc0,0xc2,0x00,0x05,0xc1,0x3a,0x00,0x05,0xc1,0x60,0x00,0x05,0xc2,0x26,0x00,0x05,0xc2,0x4c,0x00,0x05,0xc2,0x64, 0x00,0x05,0xc2,0x7c,0x00,0x05,0xc2,0x94,0x00,0x05,0xc2,0xac,0x00,0x05,0xc2,0xc4,0x00,0x05,0xc2,0xe8,0x00,0x05,0xc3,0x0c,0x00,0x05,0xc3,0x24,0x00,0x05,0xc3,0x3c,0x00,0x05,0xc3,0x54,0x00,0x05,0xc3,0x6c,0x00,0x05,0xc3,0x84,0x00,0x05,0xc3,0x9c,0x00,0x05,0xc3,0xb4,0x00,0x05,0xc4,0x88,0x00,0x05,0xc4,0xa0,0x00,0x05,0xc5,0x36, 0x00,0x05,0xc5,0x4e,0x00,0x05,0xc6,0xbe,0x00,0x05,0xc7,0xf2,0x00,0x05,0xc8,0x0a,0x00,0x05,0xc8,0x22,0x00,0x05,0xc9,0xa0,0x00,0x05,0xca,0xec,0x00,0x05,0xcb,0x04,0x00,0x05,0xcb,0x1c,0x00,0x05,0xcc,0x1c,0x00,0x05,0xcd,0x00,0x00,0x05,0xce,0x08,0x00,0x05,0xce,0x20,0x00,0x05,0xce,0x38,0x00,0x05,0xce,0x50,0x00,0x05,0xce,0x68, 0x00,0x05,0xce,0x80,0x00,0x05,0xce,0x98,0x00,0x05,0xce,0xb0,0x00,0x05,0xce,0xc8,0x00,0x05,0xce,0xe0,0x00,0x05,0xce,0xf8,0x00,0x05,0xcf,0x10,0x00,0x05,0xcf,0x28,0x00,0x05,0xcf,0x4c,0x00,0x05,0xcf,0x6c,0x00,0x05,0xcf,0x8c,0x00,0x05,0xcf,0xa4,0x00,0x05,0xcf,0xbc,0x00,0x05,0xcf,0xdc,0x00,0x05,0xcf,0xfc,0x00,0x05,0xd0,0x14, 0x00,0x05,0xd0,0x2c,0x00,0x05,0xd0,0x4c,0x00,0x05,0xd0,0x6c,0x00,0x05,0xd0,0x84,0x00,0x05,0xd0,0x9c,0x00,0x05,0xd1,0xe0,0x00,0x05,0xd2,0x8e,0x00,0x05,0xd3,0x98,0x00,0x05,0xd4,0x7c,0x00,0x05,0xd4,0x94,0x00,0x05,0xd4,0xac,0x00,0x05,0xd5,0xf4,0x00,0x05,0xd7,0x38,0x00,0x05,0xd8,0x62,0x00,0x05,0xd9,0x5a,0x00,0x05,0xd9,0x6a, 0x00,0x05,0xd9,0x7a,0x00,0x05,0xd9,0x92,0x00,0x05,0xda,0x94,0x00,0x05,0xdb,0xa4,0x00,0x05,0xdd,0x8c,0x00,0x05,0xde,0x7e,0x00,0x05,0xdf,0xc0,0x00,0x05,0xe0,0x5a,0x00,0x05,0xe1,0x94,0x00,0x05,0xe2,0x3e,0x00,0x05,0xe3,0x32,0x00,0x05,0xe3,0xd8,0x00,0x05,0xe4,0x68,0x00,0x05,0xe4,0x78,0x00,0x05,0xe5,0x3a,0x00,0x05,0xe5,0x9e, 0x00,0x05,0xe6,0xb8,0x00,0x05,0xe6,0xc8,0x00,0x05,0xe6,0xd8,0x00,0x05,0xe6,0xea,0x00,0x05,0xe7,0x0e,0x00,0x05,0xe7,0x3e,0x00,0x05,0xe7,0x62,0x00,0x05,0xe7,0x8e,0x00,0x05,0xe7,0xa6,0x00,0x05,0xe7,0xbe,0x00,0x05,0xe7,0xd6,0x00,0x05,0xe7,0xee,0x00,0x05,0xe8,0x06,0x00,0x05,0xe8,0x1e,0x00,0x05,0xe8,0x3e,0x00,0x05,0xe8,0x5e, 0x00,0x05,0xe8,0x76,0x00,0x05,0xe8,0x8e,0x00,0x05,0xe8,0xa6,0x00,0x05,0xe8,0xbe,0x00,0x05,0xe8,0xd6,0x00,0x05,0xe8,0xee,0x00,0x05,0xe9,0x06,0x00,0x05,0xe9,0x1e,0x00,0x05,0xe9,0x42,0x00,0x05,0xe9,0x5a,0x00,0x05,0xe9,0x72,0x00,0x05,0xe9,0x8a,0x00,0x05,0xe9,0xa2,0x00,0x05,0xe9,0xba,0x00,0x05,0xe9,0xd2,0x00,0x05,0xe9,0xea, 0x00,0x05,0xea,0x02,0x00,0x05,0xea,0x1a,0x00,0x05,0xea,0x3a,0x00,0x05,0xea,0x52,0x00,0x05,0xea,0x6a,0x00,0x05,0xea,0x82,0x00,0x05,0xea,0x9a,0x00,0x05,0xea,0xb2,0x00,0x05,0xea,0xd2,0x00,0x05,0xea,0xf2,0x00,0x05,0xeb,0x0a,0x00,0x05,0xeb,0x22,0x00,0x05,0xeb,0x42,0x00,0x05,0xeb,0x62,0x00,0x05,0xeb,0x7a,0x00,0x05,0xeb,0x92, 0x00,0x05,0xeb,0xaa,0x00,0x05,0xeb,0xc2,0x00,0x05,0xeb,0xda,0x00,0x05,0xeb,0xf2,0x00,0x05,0xec,0x0a,0x00,0x05,0xed,0x52,0x00,0x05,0xed,0x6a,0x00,0x05,0xed,0x8a,0x00,0x05,0xed,0xa2,0x00,0x05,0xed,0xba,0x00,0x05,0xed,0xd2,0x00,0x05,0xed,0xea,0x00,0x05,0xee,0x02,0x00,0x05,0xee,0x1a,0x00,0x05,0xee,0x32,0x00,0x05,0xee,0x4a, 0x00,0x05,0xee,0x62,0x00,0x05,0xef,0x6a,0x00,0x05,0xef,0x7a,0x00,0x05,0xf0,0x94,0x00,0x05,0xf1,0xca,0x00,0x05,0xf1,0xe2,0x00,0x05,0xf1,0xfa,0x00,0x05,0xf2,0x12,0x00,0x05,0xf2,0x2a,0x00,0x05,0xf2,0x42,0x00,0x05,0xf2,0x5a,0x00,0x05,0xf2,0x72,0x00,0x05,0xf2,0x8a,0x00,0x05,0xf2,0xa2,0x00,0x05,0xf2,0xb8,0x00,0x05,0xf2,0xd8, 0x00,0x05,0xf2,0xf6,0x00,0x05,0xf3,0x24,0x00,0x05,0xf3,0x50,0x00,0x05,0xf3,0x70,0x00,0x05,0xf3,0x8e,0x00,0x05,0xf3,0xae,0x00,0x05,0xf3,0xcc,0x00,0x05,0xf4,0x02,0x00,0x05,0xf4,0x36,0x00,0x05,0xf4,0x4e,0x00,0x05,0xf4,0x66,0x00,0x05,0xf4,0x8e,0x00,0x05,0xf5,0x9a,0x00,0x05,0xf6,0xa4,0x00,0x05,0xf6,0xc4,0x00,0x05,0xf7,0x8c, 0x00,0x05,0xf7,0xa4,0x00,0x05,0xf7,0xbc,0x00,0x05,0xf7,0xd4,0x00,0x05,0xf9,0x26,0x00,0x05,0xf9,0x46,0x00,0x05,0xf9,0x5e,0x00,0x05,0xf9,0x76,0x00,0x05,0xf9,0x86,0x00,0x05,0xf9,0x96,0x00,0x05,0xf9,0xb6,0x00,0x05,0xf9,0xce,0x00,0x05,0xf9,0xe6,0x00,0x05,0xf9,0xfc,0x00,0x05,0xfb,0x1e,0x00,0x05,0xfb,0x42,0x00,0x05,0xfb,0x68, 0x00,0x05,0xfb,0x80,0x00,0x05,0xfb,0xa4,0x00,0x05,0xfb,0xbc,0x00,0x05,0xfb,0xd4,0x00,0x05,0xfb,0xec,0x00,0x05,0xfc,0x0c,0x00,0x05,0xfc,0x24,0x00,0x05,0xfc,0x3c,0x00,0x05,0xfc,0x54,0x00,0x05,0xfc,0x6c,0x00,0x05,0xfc,0x84,0x00,0x05,0xfc,0xde,0x00,0x05,0xfc,0xfe,0x00,0x05,0xfd,0x1e,0x00,0x05,0xfd,0x3e,0x00,0x05,0xfd,0x5e, 0x00,0x05,0xfd,0x76,0x00,0x05,0xfd,0x96,0x00,0x05,0xfd,0xb6,0x00,0x05,0xfd,0xd6,0x00,0x05,0xfd,0xee,0x00,0x05,0xfe,0x06,0x00,0x05,0xfe,0x26,0x00,0x05,0xfe,0x46,0x00,0x05,0xfe,0x66,0x00,0x05,0xfe,0x86,0x00,0x05,0xfe,0xaa,0x00,0x05,0xfe,0xce,0x00,0x05,0xfe,0xe6,0x00,0x05,0xfe,0xfe,0x00,0x05,0xff,0x16,0x00,0x05,0xff,0x2e, 0x00,0x05,0xff,0x4e,0x00,0x05,0xff,0x72,0x00,0x05,0xff,0x8a,0x00,0x05,0xff,0xa2,0x00,0x05,0xff,0xba,0x00,0x05,0xff,0xd2,0x00,0x05,0xff,0xea,0x00,0x06,0x00,0x02,0x00,0x06,0x00,0x1a,0x00,0x06,0x00,0x32,0x00,0x06,0x00,0x4a,0x00,0x06,0x00,0x62,0x00,0x06,0x00,0x7a,0x00,0x06,0x00,0x92,0x00,0x06,0x01,0xbe,0x00,0x06,0x01,0xde, 0x00,0x06,0x01,0xfe,0x00,0x06,0x02,0x2a,0x00,0x06,0x02,0x56,0x00,0x06,0x02,0x8c,0x00,0x06,0x02,0xa4,0x00,0x06,0x02,0xbc,0x00,0x06,0x04,0x04,0x00,0x06,0x05,0x88,0x00,0x06,0x05,0xa0,0x00,0x06,0x05,0xb8,0x00,0x06,0x07,0x4a,0x00,0x06,0x09,0x18,0x00,0x06,0x0a,0x9e,0x00,0x06,0x0c,0x5c,0x00,0x06,0x0c,0x8a,0x00,0x06,0x0c,0xb8, 0x00,0x06,0x0c,0xe6,0x00,0x06,0x0d,0x14,0x00,0x06,0x0d,0x42,0x00,0x06,0x0d,0x70,0x00,0x06,0x0d,0x88,0x00,0x06,0x0d,0xa0,0x00,0x06,0x0d,0xb8,0x00,0x06,0x0d,0xd0,0x00,0x06,0x0d,0xe8,0x00,0x06,0x0e,0x00,0x00,0x06,0x0e,0x18,0x00,0x06,0x0e,0x30,0x00,0x06,0x0e,0x54,0x00,0x06,0x0e,0x7c,0x00,0x06,0x0e,0xa8,0x00,0x06,0x0e,0xd4, 0x00,0x06,0x0e,0xf8,0x00,0x06,0x0f,0x20,0x00,0x06,0x0f,0x4c,0x00,0x06,0x0f,0x78,0x00,0x06,0x0f,0x9e,0x00,0x06,0x0f,0xc2,0x00,0x06,0x0f,0xe6,0x00,0x06,0x10,0x0a,0x00,0x06,0x10,0x24,0x00,0x06,0x10,0x3e,0x00,0x06,0x10,0x58,0x00,0x06,0x10,0x72,0x00,0x06,0x10,0x9a,0x00,0x06,0x10,0xbe,0x00,0x06,0x10,0xe6,0x00,0x06,0x11,0x0a, 0x00,0x06,0x12,0x42,0x00,0x06,0x13,0xbc,0x00,0x06,0x13,0xe0,0x00,0x06,0x14,0x04,0x00,0x06,0x14,0x28,0x00,0x06,0x14,0x4c,0x00,0x06,0x14,0x70,0x00,0x06,0x14,0x94,0x00,0x06,0x14,0xac,0x00,0x06,0x14,0xc4,0x00,0x06,0x14,0xdc,0x00,0x06,0x14,0xf4,0x00,0x06,0x15,0x0c,0x00,0x06,0x15,0x24,0x00,0x06,0x15,0x3c,0x00,0x06,0x15,0x54, 0x00,0x06,0x15,0x86,0x00,0x06,0x15,0xd2,0x00,0x06,0x16,0x1a,0x00,0x06,0x16,0x8a,0x00,0x06,0x16,0xf2,0x00,0x06,0x17,0x56,0x00,0x06,0x17,0xd0,0x00,0x06,0x18,0x8c,0x00,0x06,0x19,0x34,0x00,0x06,0x19,0x60,0x00,0x06,0x19,0xd0,0x00,0x06,0x1a,0x48,0x00,0x06,0x1a,0x74,0x00,0x06,0x1a,0xbc,0x00,0x06,0x1b,0x08,0x00,0x06,0x1b,0xde, 0x00,0x06,0x1c,0x78,0x00,0x06,0x1d,0x76,0x00,0x06,0x1d,0x98,0x00,0x06,0x1d,0xae,0x00,0x06,0x1d,0xc4,0x00,0x06,0x1d,0xee,0x00,0x06,0x1e,0x04,0x00,0x06,0x1e,0x28,0x00,0x06,0x1e,0x3e,0x00,0x06,0x1e,0x56,0x00,0x06,0x1e,0x7a,0x00,0x06,0x1e,0x9e,0x00,0x06,0x1f,0x82,0x00,0x06,0x20,0x96,0x00,0x06,0x20,0xae,0x00,0x06,0x20,0xc6, 0x00,0x06,0x20,0xe6,0x00,0x06,0x21,0x06,0x00,0x06,0x21,0x1e,0x00,0x06,0x21,0x36,0x00,0x06,0x21,0x56,0x00,0x06,0x21,0x76,0x00,0x06,0x21,0x96,0x00,0x06,0x21,0xb6,0x00,0x06,0x21,0xce,0x00,0x06,0x21,0xe6,0x00,0x06,0x21,0xfe,0x00,0x06,0x22,0x16,0x00,0x06,0x22,0x44,0x00,0x06,0x22,0x72,0x00,0x06,0x22,0x96,0x00,0x06,0x22,0xba, 0x00,0x06,0x22,0xd2,0x00,0x06,0x22,0xea,0x00,0x06,0x23,0xec,0x00,0x06,0x25,0x12,0x00,0x06,0x25,0x2a,0x00,0x06,0x25,0x42,0x00,0x06,0x25,0x5a,0x00,0x06,0x25,0x72,0x00,0x06,0x25,0x8a,0x00,0x06,0x25,0xa2,0x00,0x06,0x25,0xc2,0x00,0x06,0x25,0xe2,0x00,0x06,0x26,0x42,0x00,0x06,0x26,0xc8,0x00,0x06,0x26,0xde,0x00,0x06,0x26,0xf4, 0x00,0x06,0x27,0x0c,0x00,0x06,0x27,0x24,0x00,0x06,0x27,0x4c,0x00,0x06,0x27,0x74,0x00,0x06,0x27,0x8c,0x00,0x06,0x27,0xa4,0x00,0x06,0x27,0xbc,0x00,0x06,0x27,0xd4,0x00,0x06,0x28,0x68,0x00,0x06,0x28,0x80,0x00,0x06,0x28,0x98,0x00,0x06,0x28,0xb0,0x00,0x06,0x28,0xc8,0x00,0x06,0x28,0xe0,0x00,0x06,0x29,0x04,0x00,0x06,0x29,0x24, 0x00,0x06,0x29,0x3c,0x00,0x06,0x29,0x54,0x00,0x06,0x29,0x6c,0x00,0x06,0x29,0x84,0x00,0x06,0x29,0x9c,0x00,0x06,0x29,0xb4,0x00,0x06,0x29,0xe2,0x00,0x06,0x2a,0x06,0x00,0x06,0x2a,0x2a,0x00,0x06,0x2a,0x42,0x00,0x06,0x2a,0x5a,0x00,0x06,0x2b,0x30,0x00,0x06,0x2b,0x48,0x00,0x06,0x2b,0x60,0x00,0x06,0x2c,0x54,0x00,0x06,0x2c,0x6c, 0x00,0x06,0x2c,0x84,0x00,0x06,0x2c,0xac,0x00,0x06,0x2c,0xd4,0x00,0x06,0x2c,0xf8,0x00,0x06,0x2d,0xc4,0x00,0x06,0x2e,0x52,0x00,0x06,0x2e,0xe0,0x00,0x06,0x2e,0xf8,0x00,0x06,0x2f,0x10,0x00,0x06,0x2f,0x34,0x00,0x06,0x2f,0x58,0x00,0x06,0x2f,0x7c,0x00,0x06,0x2f,0xa0,0x00,0x06,0x2f,0xb0,0x00,0x06,0x2f,0xc8,0x00,0x06,0x2f,0xe0, 0x00,0x06,0x30,0x2c,0x00,0x06,0x30,0xa6,0x00,0x06,0x31,0x7a,0x00,0x06,0x31,0x92,0x00,0x06,0x32,0x5e,0x00,0x06,0x33,0xde,0x00,0x06,0x34,0xa2,0x00,0x06,0x35,0xf2,0x00,0x06,0x37,0x50,0x00,0x06,0x38,0x28,0x00,0x06,0x39,0x6a,0x00,0x06,0x39,0xde,0x00,0x06,0x3a,0x5a,0x00,0x06,0x3a,0xe2,0x00,0x06,0x3b,0x60,0x00,0x06,0x3b,0xd8, 0x00,0x06,0x3c,0x58,0x00,0x06,0x3c,0xc0,0x00,0x06,0x3d,0x30,0x00,0x06,0x3d,0x9e,0x00,0x06,0x3e,0x18,0x00,0x06,0x3e,0xae,0x00,0x06,0x3f,0x26,0x00,0x06,0x3f,0xec,0x00,0x06,0x40,0x96,0x00,0x06,0x41,0x80,0x00,0x06,0x42,0x66,0x00,0x06,0x43,0x28,0x00,0x06,0x44,0x24,0x00,0x06,0x44,0xf2,0x00,0x06,0x45,0x76,0x00,0x06,0x46,0x2e, 0x00,0x06,0x46,0xb2,0x00,0x06,0x47,0x5a,0x00,0x06,0x48,0x2a,0x00,0x06,0x48,0xd6,0x00,0x06,0x49,0xc6,0x00,0x06,0x4a,0xc0,0x00,0x06,0x4b,0xa6,0x00,0x06,0x4c,0x7a,0x00,0x06,0x4d,0xa0,0x00,0x06,0x4e,0xb8,0x00,0x06,0x4f,0x2e,0x00,0x06,0x4f,0xc4,0x00,0x06,0x50,0x7a,0x00,0x06,0x51,0x64,0x00,0x06,0x52,0x40,0x00,0x06,0x52,0xde, 0x00,0x06,0x53,0xc8,0x00,0x06,0x54,0x5a,0x00,0x06,0x54,0xe8,0x00,0x06,0x55,0xa4,0x00,0x06,0x56,0x1e,0x00,0x06,0x56,0xc2,0x00,0x06,0x57,0x8e,0x00,0x06,0x58,0x6a,0x00,0x06,0x59,0x28,0x00,0x06,0x59,0xda,0x00,0x06,0x5a,0xe6,0x00,0x06,0x5b,0xbe,0x00,0x06,0x5c,0x3e,0x00,0x06,0x5c,0xf6,0x00,0x06,0x5d,0x74,0x00,0x06,0x5e,0x1c, 0x00,0x06,0x5e,0xce,0x00,0x06,0x5f,0xb8,0x00,0x06,0x60,0x86,0x00,0x06,0x61,0xae,0x00,0x06,0x62,0x92,0x00,0x06,0x63,0x7e,0x00,0x06,0x63,0xb4,0x00,0x06,0x64,0x46,0x00,0x06,0x64,0xc2,0x00,0x06,0x65,0xa8,0x00,0x06,0x66,0xae,0x00,0x06,0x67,0x64,0x00,0x06,0x68,0x2c,0x00,0x06,0x69,0x40,0x00,0x06,0x6a,0x72,0x00,0x06,0x6b,0x30, 0x00,0x06,0x6c,0x6a,0x00,0x06,0x6d,0xd4,0x00,0x06,0x6e,0x64,0x00,0x06,0x6f,0x08,0x00,0x06,0x6f,0xd2,0x00,0x06,0x70,0x9c,0x00,0x06,0x71,0xa0,0x00,0x06,0x72,0xde,0x00,0x06,0x73,0x72,0x00,0x06,0x74,0x4c,0x00,0x06,0x74,0xfa,0x00,0x06,0x75,0x8e,0x00,0x06,0x76,0x1e,0x00,0x06,0x76,0xbc,0x00,0x06,0x77,0x76,0x00,0x06,0x78,0x9c, 0x00,0x06,0x79,0xc0,0x00,0x06,0x7b,0x2a,0x00,0x06,0x7c,0x0c,0x00,0x06,0x7c,0xc2,0x00,0x06,0x7d,0xb2,0x00,0x06,0x7e,0xb4,0x00,0x06,0x7f,0x2e,0x00,0x06,0x7f,0xd4,0x00,0x06,0x80,0x7c,0x00,0x06,0x81,0x5a,0x00,0x06,0x82,0x82,0x00,0x06,0x83,0xce,0x00,0x06,0x84,0xf2,0x00,0x06,0x85,0xd2,0x00,0x06,0x86,0xc0,0x00,0x06,0x88,0x22, 0x00,0x06,0x88,0x9e,0x00,0x06,0x89,0x9e,0x00,0x06,0x8a,0xdc,0x00,0x06,0x8b,0xf4,0x00,0x06,0x8d,0x42,0x00,0x06,0x8e,0xea,0x00,0x06,0x8f,0xe6,0x00,0x06,0x91,0x2a,0x00,0x06,0x92,0x82,0x00,0x06,0x93,0xc2,0x00,0x06,0x94,0x4c,0x00,0x06,0x95,0x4e,0x00,0x06,0x96,0x3c,0x00,0x06,0x97,0xc8,0x00,0x06,0x99,0x3c,0x00,0x06,0x9b,0x16, 0x00,0x06,0x9c,0xdc,0x00,0x06,0x9e,0x20,0x00,0x06,0xa0,0x10,0x00,0x06,0xa1,0x2e,0x00,0x06,0xa1,0xa8,0x00,0x06,0xa2,0x44,0x00,0x06,0xa2,0xee,0x00,0x06,0xa3,0xe6,0x00,0x06,0xa4,0x90,0x00,0x06,0xa5,0x24,0x00,0x06,0xa5,0xec,0x00,0x06,0xa6,0xb8,0x00,0x06,0xa7,0x38,0x00,0x06,0xa7,0xec,0x00,0x06,0xa8,0x66,0x00,0x06,0xa8,0xf2, 0x00,0x06,0xa9,0x54,0x00,0x06,0xaa,0x04,0x00,0x06,0xaa,0xb0,0x00,0x06,0xab,0xa2,0x00,0x06,0xac,0xba,0x00,0x06,0xad,0x8e,0x00,0x06,0xae,0x4a,0x00,0x06,0xaf,0x66,0x00,0x06,0xaf,0xe4,0x00,0x06,0xb0,0x40,0x00,0x06,0xb0,0xd8,0x00,0x06,0xb1,0x46,0x00,0x06,0xb1,0xac,0x00,0x06,0xb2,0x40,0x00,0x06,0xb2,0xd6,0x00,0x06,0xb3,0x2a, 0x00,0x06,0xb4,0x1e,0x00,0x06,0xb5,0x10,0x00,0x06,0xb5,0x92,0x00,0x06,0xb6,0x6e,0x00,0x06,0xb7,0xdc,0x00,0x06,0xb8,0xc8,0x00,0x06,0xb9,0xe6,0x00,0x06,0xbb,0x7e,0x00,0x06,0xbc,0x9e,0x00,0x06,0xbd,0xca,0x00,0x06,0xbe,0xf6,0x00,0x06,0xc0,0x34,0x00,0x06,0xc0,0xb8,0x00,0x06,0xc1,0x84,0x00,0x06,0xc2,0x8a,0x00,0x06,0xc3,0xbe, 0x00,0x06,0xc4,0x62,0x00,0x06,0xc5,0x48,0x00,0x06,0xc6,0x4a,0x00,0x06,0xc7,0x48,0x00,0x06,0xc8,0x20,0x00,0x06,0xc9,0x02,0x00,0x06,0xc9,0x7c,0x00,0x06,0xc9,0xec,0x00,0x06,0xca,0xb6,0x00,0x06,0xcb,0x68,0x00,0x06,0xcc,0x1e,0x00,0x06,0xcd,0x0a,0x00,0x06,0xcd,0xf0,0x00,0x06,0xce,0xe0,0x00,0x06,0xcf,0x48,0x00,0x06,0xd0,0x06, 0x00,0x06,0xd0,0xbc,0x00,0x06,0xd1,0xc8,0x00,0x06,0xd1,0xf2,0x00,0x06,0xd3,0x3c,0x00,0x06,0xd4,0x46,0x00,0x06,0xd4,0xea,0x00,0x06,0xd5,0x96,0x00,0x06,0xd6,0x70,0x00,0x06,0xd7,0x4a,0x00,0x06,0xd8,0x6a,0x00,0x06,0xd9,0xb0,0x00,0x06,0xda,0x42,0x00,0x06,0xda,0xec,0x00,0x06,0xdb,0xc6,0x00,0x06,0xdc,0xaa,0x00,0x06,0xdd,0x6e, 0x00,0x06,0xde,0x6e,0x00,0x06,0xdf,0x10,0x00,0x06,0xdf,0xa8,0x00,0x06,0xe0,0x40,0x00,0x06,0xe0,0xb6,0x00,0x06,0xe0,0xc6,0x00,0x06,0xe0,0xec,0x00,0x06,0xe1,0x1a,0x00,0x06,0xe1,0x4e,0x00,0x06,0xe1,0x5e,0x00,0x06,0xe1,0x8e,0x00,0x06,0xe1,0xbc,0x00,0x06,0xe1,0xf2,0x00,0x06,0xe2,0x28,0x00,0x06,0xe2,0x5e,0x00,0x06,0xe2,0x94, 0x00,0x06,0xe2,0xca,0x00,0x06,0xe3,0x00,0x00,0x06,0xe3,0x2e,0x00,0x06,0xe3,0x5c,0x00,0x06,0xe3,0x8a,0x00,0x06,0xe3,0xbc,0x00,0x06,0xe3,0xee,0x00,0x06,0xe4,0x20,0x00,0x06,0xe4,0x30,0x00,0x06,0xe4,0x54,0x00,0x06,0xe4,0x64,0x00,0x06,0xe4,0x92,0x00,0x06,0xe4,0xaa,0x00,0x06,0xe4,0xd8,0x00,0x06,0xe4,0xfc,0x00,0x06,0xe5,0x2c, 0x00,0x06,0xe5,0x5a,0x00,0x06,0xe5,0x88,0x00,0x06,0xe5,0xbe,0x00,0x06,0xe5,0xec,0x00,0x06,0xe6,0x1a,0x00,0x06,0xe6,0x48,0x00,0x06,0xe6,0x76,0x00,0x06,0xe6,0xa4,0x00,0x06,0xe6,0xd2,0x00,0x06,0xe8,0x96,0x00,0x06,0xea,0x76,0x00,0x06,0xec,0x72,0x00,0x06,0xee,0x4e,0x00,0x06,0xef,0x2e,0x00,0x06,0xf0,0x3c,0x00,0x06,0xf1,0xda, 0x00,0x06,0xf2,0x78,0x00,0x06,0xf3,0x62,0x00,0x06,0xf4,0x36,0x00,0x06,0xf4,0xaa,0x00,0x06,0xf5,0x16,0x00,0x06,0xf5,0xe0,0x00,0x06,0xf6,0xcc,0x00,0x06,0xf7,0xc0,0x00,0x06,0xf9,0x00,0x00,0x06,0xf9,0x86,0x00,0x06,0xfa,0xe8,0x00,0x06,0xfb,0xce,0x00,0x06,0xfd,0x0c,0x00,0x06,0xfe,0xa2,0x00,0x07,0x00,0x16,0x00,0x07,0x01,0x4c, 0x00,0x07,0x02,0x24,0x00,0x07,0x03,0x26,0x00,0x07,0x04,0x1a,0x00,0x07,0x05,0x08,0x00,0x07,0x06,0x42,0x00,0x07,0x07,0xa8,0x00,0x07,0x08,0xea,0x00,0x07,0x09,0xe4,0x00,0x07,0x0a,0x7e,0x00,0x07,0x0b,0x2c,0x00,0x07,0x0d,0x52,0x00,0x07,0x0e,0x90,0x00,0x07,0x0f,0xa8,0x00,0x07,0x10,0xa4,0x00,0x07,0x11,0x64,0x00,0x07,0x12,0x8a, 0x00,0x07,0x13,0x32,0x00,0x07,0x14,0x3a,0x00,0x07,0x15,0xcc,0x00,0x07,0x16,0xda,0x00,0x07,0x18,0x22,0x00,0x07,0x18,0x6a,0x00,0x07,0x18,0x98,0x00,0x07,0x18,0xee,0x00,0x07,0x19,0x1a,0x00,0x07,0x19,0x44,0x00,0x07,0x19,0x7c,0x00,0x07,0x19,0xde,0x00,0x07,0x1a,0x34,0x00,0x07,0x1a,0x5e,0x00,0x07,0x1a,0xa6,0x00,0x07,0x1a,0xee, 0x00,0x07,0x1b,0x1a,0x00,0x07,0x1b,0xcc,0x00,0x07,0x1c,0x78,0x00,0x07,0x1c,0xd8,0x00,0x07,0x1d,0x32,0x00,0x07,0x1d,0x92,0x00,0x07,0x1e,0x3a,0x00,0x07,0x1e,0x98,0x00,0x07,0x1f,0x42,0x00,0x07,0x20,0x52,0x00,0x07,0x20,0x64,0x00,0x07,0x23,0xe8,0x00,0x07,0x27,0x46,0x00,0x07,0x2a,0xd6,0x00,0x07,0x2b,0x02,0x00,0x07,0x2b,0x2e, 0x00,0x07,0x2b,0x5a,0x00,0x07,0x2b,0x86,0x00,0x07,0x2b,0xb2,0x00,0x07,0x2b,0xde,0x00,0x07,0x2c,0x16,0x00,0x07,0x2c,0x4e,0x00,0x07,0x2c,0x84,0x00,0x07,0x2c,0xba,0x00,0x07,0x2c,0xee,0x00,0x07,0x2d,0x22,0x00,0x07,0x2d,0x56,0x00,0x07,0x2d,0x8a,0x00,0x07,0x2d,0xbe,0x00,0x07,0x2d,0xea,0x00,0x07,0x2e,0x16,0x00,0x07,0x2e,0x42, 0x00,0x07,0x2e,0xe0,0x00,0x07,0x2f,0x62,0x00,0x07,0x2f,0x98,0x00,0x07,0x30,0x0a,0x00,0x07,0x30,0x80,0x00,0x07,0x31,0x16,0x00,0x07,0x31,0x70,0x00,0x07,0x31,0xc4,0x00,0x07,0x32,0x1e,0x00,0x07,0x32,0x72,0x00,0x07,0x32,0xd4,0x00,0x07,0x33,0x16,0x00,0x07,0x33,0x9e,0x00,0x07,0x33,0xfe,0x00,0x07,0x34,0x3e,0x00,0x07,0x34,0x9a, 0x00,0x07,0x34,0xf2,0x00,0x07,0x35,0x4a,0x00,0x07,0x35,0xa2,0x00,0x07,0x36,0x12,0x00,0x07,0x36,0xd0,0x00,0x07,0x37,0x4a,0x00,0x07,0x37,0xe0,0x00,0x07,0x38,0x5a,0x00,0x07,0x38,0xee,0x00,0x07,0x39,0x88,0x00,0x07,0x3a,0x10,0x00,0x07,0x3a,0x9c,0x00,0x07,0x3b,0x6a,0x00,0x07,0x3b,0xfc,0x00,0x07,0x3c,0xa2,0x00,0x07,0x3d,0x6a, 0x00,0x07,0x3e,0x1c,0x00,0x07,0x3e,0xc6,0x00,0x07,0x3f,0xac,0x00,0x07,0x40,0x8c,0x00,0x07,0x41,0x2c,0x00,0x07,0x41,0xbc,0x00,0x07,0x42,0x16,0x00,0x07,0x42,0x72,0x00,0x07,0x43,0x16,0x00,0x07,0x43,0xae,0x00,0x07,0x44,0xac,0x00,0x07,0x45,0x58,0x00,0x07,0x46,0x46,0x00,0x07,0x47,0x0a,0x00,0x07,0x47,0x96,0x00,0x07,0x48,0x1a, 0x00,0x07,0x48,0xb2,0x00,0x07,0x49,0x48,0x00,0x07,0x49,0xf6,0x00,0x07,0x4a,0xa0,0x00,0x07,0x4b,0x50,0x00,0x07,0x4b,0xe8,0x00,0x07,0x4c,0x8e,0x00,0x07,0x4d,0x66,0x00,0x07,0x4d,0xe4,0x00,0x07,0x4e,0x5a,0x00,0x07,0x4f,0x4e,0x00,0x07,0x50,0x40,0x00,0x07,0x50,0xea,0x00,0x07,0x51,0x94,0x00,0x07,0x52,0x22,0x00,0x07,0x52,0xb0, 0x00,0x07,0x53,0x0a,0x00,0x07,0x53,0x64,0x00,0x07,0x53,0xf4,0x00,0x07,0x54,0x80,0x00,0x07,0x54,0xfa,0x00,0x07,0x55,0x60,0x00,0x07,0x56,0x0e,0x00,0x07,0x56,0x9c,0x00,0x07,0x57,0x4e,0x00,0x07,0x57,0xee,0x00,0x07,0x58,0xca,0x00,0x07,0x59,0x94,0x00,0x07,0x5a,0xd0,0x00,0x07,0x5b,0xf8,0x00,0x07,0x5f,0x70,0x00,0x07,0x5f,0xbc, 0x00,0x07,0x61,0x1e,0x00,0x07,0x61,0x9c,0x00,0x07,0x62,0xf2,0x00,0x07,0x63,0xa8,0x00,0x07,0x63,0xee,0x00,0x07,0x64,0x54,0x00,0x07,0x64,0x9a,0x00,0x07,0x65,0x00,0x00,0x07,0x65,0x9a,0x00,0x07,0x66,0x2e,0x00,0x07,0x66,0xbe,0x00,0x07,0x67,0x50,0x00,0x07,0x68,0x5e,0x00,0x07,0x69,0x64,0x00,0x07,0x69,0xfe,0x00,0x07,0x6a,0x9e, 0x00,0x07,0x6b,0x7c,0x00,0x07,0x6c,0x60,0x00,0x07,0x6c,0xfa,0x00,0x07,0x6d,0x90,0x00,0x07,0x6d,0xf0,0x00,0x07,0x6e,0x50,0x00,0x07,0x6f,0x04,0x00,0x07,0x6f,0xb4,0x00,0x07,0x70,0x26,0x00,0x07,0x70,0x94,0x00,0x07,0x71,0x10,0x00,0x07,0x71,0x88,0x00,0x07,0x72,0x04,0x00,0x07,0x72,0x88,0x00,0x07,0x73,0x5a,0x00,0x07,0x74,0x24, 0x00,0x07,0x74,0xc4,0x00,0x07,0x76,0x6c,0x00,0x07,0x76,0xaa,0x00,0x07,0x76,0xec,0x00,0x07,0x77,0x6e,0x00,0x07,0x78,0x3c,0x00,0x07,0x78,0x3c,0x00,0x07,0x78,0x54,0x00,0x07,0x79,0x28,0x00,0x07,0x79,0xb4,0x00,0x07,0x7b,0x6e,0x00,0x07,0x7d,0x2a,0x00,0x07,0x7d,0x4e,0x00,0x07,0x7d,0x78,0x00,0x07,0x7e,0x02,0x00,0x07,0x7e,0x74, 0x00,0x07,0x7e,0xf6,0x00,0x07,0x7f,0xaa,0x00,0x07,0x80,0x04,0x00,0x07,0x80,0x8e,0x00,0x07,0x81,0x4c,0x00,0x07,0x81,0x92,0x00,0x07,0x82,0x84,0x00,0x07,0x83,0x42,0x00,0x07,0x83,0xba,0x00,0x07,0x83,0xca,0x00,0x07,0x85,0x86,0x00,0x07,0x87,0x42,0x00,0x07,0x89,0x66,0x00,0x07,0x8b,0x76,0x00,0x07,0x8d,0x72,0x00,0x07,0x8f,0x3e, 0x00,0x07,0x91,0x0c,0x00,0x07,0x92,0xda,0x00,0x07,0x94,0xf4,0x00,0x07,0x95,0xc6,0x00,0x07,0x96,0x1e,0x00,0x07,0x96,0x9a,0x00,0x07,0x97,0x08,0x00,0x07,0x97,0x92,0x00,0x07,0x98,0x28,0x00,0x07,0x98,0xa0,0x00,0x07,0x99,0x3a,0x00,0x07,0x99,0xbc,0x00,0x07,0x9a,0x10,0x00,0x07,0x9a,0x86,0x00,0x07,0x9a,0xea,0x00,0x07,0x9b,0x5c, 0x00,0x07,0x9b,0xe8,0x00,0x07,0x9c,0x5c,0x00,0x07,0x9d,0x06,0x00,0x07,0x9d,0xa6,0x00,0x07,0x9e,0x32,0x00,0x07,0x9e,0xc2,0x00,0x07,0x9f,0x78,0x00,0x07,0xa0,0x2a,0x00,0x07,0xa0,0x76,0x00,0x07,0xa0,0xd6,0x00,0x07,0xa1,0x3e,0x00,0x07,0xa1,0xc0,0x00,0x07,0xa2,0x4a,0x00,0x07,0xa2,0xa0,0x00,0x07,0xa3,0x22,0x00,0x07,0xa3,0x74, 0x00,0x07,0xa3,0xc6,0x00,0x07,0xa4,0x38,0x00,0x07,0xa4,0x8c,0x00,0x07,0xa4,0xf4,0x00,0x07,0xa5,0x6a,0x00,0x07,0xa5,0xec,0x00,0x07,0xa6,0x52,0x00,0x07,0xa6,0xba,0x00,0x07,0xa7,0x56,0x00,0x07,0xa7,0xda,0x00,0x07,0xa8,0x28,0x00,0x07,0xa8,0x88,0x00,0x07,0xa8,0xe4,0x00,0x07,0xa9,0x52,0x00,0x07,0xa9,0xc6,0x00,0x07,0xaa,0x58, 0x00,0x07,0xaa,0xd2,0x00,0x07,0xab,0x8a,0x00,0x07,0xac,0x18,0x00,0x07,0xac,0xb4,0x00,0x07,0xac,0xd4,0x00,0x07,0xad,0x2a,0x00,0x07,0xad,0x86,0x00,0x07,0xae,0x14,0x00,0x07,0xae,0xb8,0x00,0x07,0xaf,0x1c,0x00,0x07,0xaf,0x94,0x00,0x07,0xb0,0x46,0x00,0x07,0xb0,0xfe,0x00,0x07,0xb1,0x7a,0x00,0x07,0xb2,0x3c,0x00,0x07,0xb3,0x16, 0x00,0x07,0xb3,0x82,0x00,0x07,0xb3,0xe8,0x00,0x07,0xb4,0x6c,0x00,0x07,0xb4,0xe4,0x00,0x07,0xb5,0x82,0x00,0x07,0xb6,0x42,0x00,0x07,0xb6,0x9e,0x00,0x07,0xb7,0x24,0x00,0x07,0xb7,0x90,0x00,0x07,0xb7,0xec,0x00,0x07,0xb8,0x58,0x00,0x07,0xb8,0xc0,0x00,0x07,0xb9,0x36,0x00,0x07,0xb9,0xe2,0x00,0x07,0xba,0x94,0x00,0x07,0xbb,0x66, 0x00,0x07,0xbb,0xe4,0x00,0x07,0xbc,0x58,0x00,0x07,0xbc,0xf0,0x00,0x07,0xbd,0x82,0x00,0x07,0xbd,0xda,0x00,0x07,0xbe,0x4a,0x00,0x07,0xbe,0xb4,0x00,0x07,0xbf,0x42,0x00,0x07,0xbf,0xfe,0x00,0x07,0xc0,0xda,0x00,0x07,0xc1,0x94,0x00,0x07,0xc2,0x2c,0x00,0x07,0xc2,0xc2,0x00,0x07,0xc3,0xa0,0x00,0x07,0xc3,0xfc,0x00,0x07,0xc4,0x9e, 0x00,0x07,0xc5,0x6c,0x00,0x07,0xc6,0x12,0x00,0x07,0xc6,0xdc,0x00,0x07,0xc7,0xda,0x00,0x07,0xc8,0x72,0x00,0x07,0xc9,0x3c,0x00,0x07,0xca,0x16,0x00,0x07,0xca,0xdc,0x00,0x07,0xcb,0x46,0x00,0x07,0xcb,0xe6,0x00,0x07,0xcc,0x7a,0x00,0x07,0xcd,0x7e,0x00,0x07,0xce,0x68,0x00,0x07,0xcf,0x88,0x00,0x07,0xd0,0xa2,0x00,0x07,0xd1,0x60, 0x00,0x07,0xd2,0xaa,0x00,0x07,0xd3,0x64,0x00,0x07,0xd3,0xc0,0x00,0x07,0xd4,0x26,0x00,0x07,0xd4,0x98,0x00,0x07,0xd5,0x2c,0x00,0x07,0xd5,0xa2,0x00,0x07,0xd5,0xfc,0x00,0x07,0xd6,0x86,0x00,0x07,0xd7,0x0c,0x00,0x07,0xd7,0x5c,0x00,0x07,0xd7,0xd2,0x00,0x07,0xd8,0x2a,0x00,0x07,0xd8,0x82,0x00,0x07,0xd8,0xc0,0x00,0x07,0xd9,0x28, 0x00,0x07,0xd9,0x90,0x00,0x07,0xda,0x26,0x00,0x07,0xda,0xce,0x00,0x07,0xdb,0x60,0x00,0x07,0xdb,0xd4,0x00,0x07,0xdc,0x7e,0x00,0x07,0xdc,0xd8,0x00,0x07,0xdd,0x08,0x00,0x07,0xdd,0x6e,0x00,0x07,0xdd,0xb0,0x00,0x07,0xdd,0xe0,0x00,0x07,0xde,0x3e,0x00,0x07,0xde,0x9e,0x00,0x07,0xde,0xc8,0x00,0x07,0xdf,0x64,0x00,0x07,0xdf,0xfc, 0x00,0x07,0xe0,0x58,0x00,0x07,0xe0,0xde,0x00,0x07,0xe1,0xc6,0x00,0x07,0xe2,0x54,0x00,0x07,0xe3,0x04,0x00,0x07,0xe3,0xfa,0x00,0x07,0xe4,0xa4,0x00,0x07,0xe5,0x5a,0x00,0x07,0xe6,0x1a,0x00,0x07,0xe6,0xd4,0x00,0x07,0xe7,0x38,0x00,0x07,0xe7,0xc6,0x00,0x07,0xe8,0x7e,0x00,0x07,0xe9,0x66,0x00,0x07,0xe9,0xde,0x00,0x07,0xea,0x7a, 0x00,0x07,0xeb,0x32,0x00,0x07,0xeb,0xe6,0x00,0x07,0xec,0x7e,0x00,0x07,0xed,0x20,0x00,0x07,0xed,0x76,0x00,0x07,0xed,0xc0,0x00,0x07,0xee,0x3a,0x00,0x07,0xee,0xac,0x00,0x07,0xef,0x1c,0x00,0x07,0xef,0xae,0x00,0x07,0xf0,0x44,0x00,0x07,0xf0,0xd6,0x00,0x07,0xf1,0x14,0x00,0x07,0xf1,0x86,0x00,0x07,0xf1,0xf0,0x00,0x07,0xf2,0xa0, 0x00,0x07,0xf2,0xb8,0x00,0x07,0xf3,0x82,0x00,0x07,0xf4,0x1e,0x00,0x07,0xf4,0x66,0x00,0x07,0xf4,0xc8,0x00,0x07,0xf5,0x44,0x00,0x07,0xf5,0xc6,0x00,0x07,0xf6,0x78,0x00,0x07,0xf7,0x3c,0x00,0x07,0xf7,0x5c,0x00,0x07,0xf7,0x80,0x00,0x07,0xf7,0xa4,0x00,0x07,0xf7,0xb4,0x00,0x07,0xf7,0xce,0x00,0x07,0xf7,0xde,0x00,0x07,0xf7,0xf6, 0x00,0x07,0xf8,0x0e,0x00,0x07,0xf8,0x26,0x00,0x07,0xf8,0x3e,0x00,0x07,0xf8,0xe2,0x00,0x07,0xf9,0x6e,0x00,0x07,0xf9,0xc0,0x00,0x07,0xfa,0x14,0x00,0x07,0xfa,0x96,0x00,0x07,0xfb,0x18,0x00,0x07,0xfb,0xe0,0x00,0x07,0xfc,0xb4,0x00,0x07,0xfd,0x74,0x00,0x07,0xfe,0x36,0x00,0x07,0xfe,0xd4,0x00,0x07,0xff,0x68,0x00,0x08,0x00,0x3e, 0x00,0x08,0x01,0x08,0x00,0x08,0x01,0x5a,0x00,0x08,0x01,0xf4,0x00,0x08,0x02,0xd2,0x00,0x08,0x03,0xf6,0x00,0x08,0x04,0xd6,0x00,0x08,0x05,0xce,0x00,0x08,0x06,0x6e,0x00,0x08,0x07,0x4e,0x00,0x08,0x07,0xe8,0x00,0x08,0x08,0xaa,0x00,0x08,0x09,0x68,0x00,0x08,0x0a,0x42,0x00,0x08,0x0b,0x0c,0x00,0x08,0x0b,0xf8,0x00,0x08,0x0c,0xa2, 0x00,0x08,0x0d,0x40,0x00,0x08,0x0d,0xda,0x00,0x08,0x0e,0x66,0x00,0x08,0x0f,0x06,0x00,0x08,0x0f,0x92,0x00,0x08,0x10,0x54,0x00,0x08,0x11,0x0c,0x00,0x08,0x11,0x62,0x00,0x08,0x11,0xb4,0x00,0x08,0x12,0x0e,0x00,0x08,0x12,0x62,0x00,0x08,0x13,0x1e,0x00,0x08,0x13,0xc4,0x00,0x08,0x14,0xa6,0x00,0x08,0x15,0x72,0x00,0x08,0x16,0x6a, 0x00,0x08,0x17,0x3c,0x00,0x08,0x17,0xdc,0x00,0x08,0x18,0x98,0x00,0x08,0x19,0x38,0x00,0x08,0x19,0xe8,0x00,0x08,0x1a,0xac,0x00,0x08,0x1b,0x86,0x00,0x08,0x1c,0x62,0x00,0x08,0x1d,0x20,0x00,0x08,0x1e,0x26,0x00,0x08,0x1f,0x12,0x00,0x08,0x1f,0xa2,0x00,0x08,0x20,0x2e,0x00,0x08,0x20,0xda,0x00,0x08,0x21,0x82,0x00,0x08,0x22,0x12, 0x00,0x08,0x22,0xaa,0x00,0x08,0x23,0x94,0x00,0x08,0x24,0x74,0x00,0x08,0x25,0x4c,0x00,0x08,0x26,0x24,0x00,0x08,0x26,0xd4,0x00,0x08,0x27,0x92,0x00,0x08,0x28,0x2e,0x00,0x08,0x28,0xe8,0x00,0x08,0x29,0x40,0x00,0x08,0x29,0x94,0x00,0x08,0x2a,0x4a,0x00,0x08,0x2b,0x04,0x00,0x08,0x2b,0xb2,0x00,0x08,0x2c,0x60,0x00,0x08,0x2d,0x0e, 0x00,0x08,0x2d,0xba,0x00,0x08,0x2e,0x68,0x00,0x08,0x2f,0x2a,0x00,0x08,0x2f,0x8a,0x00,0x08,0x30,0x60,0x00,0x08,0x30,0xfc,0x00,0x08,0x31,0x86,0x00,0x08,0x32,0x52,0x00,0x08,0x33,0x20,0x00,0x08,0x33,0xfa,0x00,0x08,0x34,0x8e,0x00,0x08,0x35,0x2c,0x00,0x08,0x35,0xa0,0x00,0x08,0x36,0x10,0x00,0x08,0x36,0xe6,0x00,0x08,0x37,0xba, 0x00,0x08,0x38,0x80,0x00,0x08,0x38,0xba,0x00,0x08,0x38,0xea,0x00,0x08,0x39,0x7c,0x00,0x08,0x3a,0x06,0x00,0x08,0x3a,0x64,0x00,0x08,0x3a,0xc0,0x00,0x08,0x3b,0x56,0x00,0x08,0x3b,0xd0,0x00,0x08,0x3c,0x20,0x00,0x08,0x3c,0xfa,0x00,0x08,0x3d,0x8c,0x00,0x08,0x3e,0x08,0x00,0x08,0x3e,0xaa,0x00,0x08,0x3f,0x34,0x00,0x08,0x40,0x22, 0x00,0x08,0x41,0x1a,0x00,0x08,0x41,0xe2,0x00,0x08,0x42,0x96,0x00,0x08,0x43,0x7a,0x00,0x08,0x44,0x30,0x00,0x08,0x45,0x20,0x00,0x08,0x45,0xb8,0x00,0x08,0x46,0x96,0x00,0x08,0x47,0x70,0x00,0x08,0x47,0xf4,0x00,0x08,0x48,0x9c,0x00,0x08,0x49,0xa6,0x00,0x08,0x4a,0x40,0x00,0x08,0x4a,0x94,0x00,0x08,0x4b,0x02,0x00,0x08,0x4b,0x9c, 0x00,0x08,0x4b,0xce,0x00,0x08,0x4c,0xa8,0x00,0x08,0x4c,0xd2,0x00,0x08,0x4c,0xfe,0x00,0x08,0x4d,0x36,0x00,0x08,0x4d,0x60,0x00,0x08,0x4d,0x8a,0x00,0x08,0x4d,0xb4,0x00,0x08,0x4d,0xde,0x00,0x08,0x4e,0x0a,0x00,0x08,0x4e,0x36,0x00,0x08,0x4e,0x4e,0x00,0x08,0x4e,0x5e,0x00,0x08,0x4e,0x6e,0x00,0x08,0x4e,0x7e,0x00,0x08,0x4e,0x8e, 0x00,0x08,0x4e,0xa6,0x00,0x08,0x4e,0xc6,0x00,0x08,0x4e,0xd6,0x00,0x08,0x4e,0xe6,0x00,0x08,0x4e,0xf6,0x00,0x08,0x4f,0x06,0x00,0x08,0x4f,0xaa,0x00,0x08,0x50,0x6e,0x00,0x08,0x51,0xc8,0x00,0x08,0x52,0x4e,0x00,0x08,0x52,0xec,0x00,0x08,0x53,0x44,0x00,0x08,0x54,0x5c,0x00,0x08,0x56,0x3a,0x00,0x08,0x56,0x64,0x00,0x08,0x56,0x8e, 0x00,0x08,0x57,0x2e,0x00,0x08,0x57,0xa2,0x00,0x08,0x58,0x2c,0x00,0x08,0x58,0x8a,0x00,0x08,0x59,0x3e,0x00,0x08,0x5a,0x14,0x00,0x08,0x5a,0xaa,0x00,0x08,0x5b,0x62,0x00,0x08,0x5c,0x16,0x00,0x08,0x5c,0xd0,0x00,0x08,0x5d,0xa0,0x00,0x08,0x5e,0x6c,0x00,0x08,0x5f,0x6c,0x00,0x08,0x60,0x3a,0x00,0x08,0x61,0x24,0x00,0x08,0x62,0x40, 0x00,0x08,0x63,0x1e,0x00,0x08,0x63,0xe0,0x00,0x08,0x64,0xc0,0x00,0x08,0x65,0x9c,0x00,0x08,0x66,0x1e,0x00,0x08,0x66,0x8c,0x00,0x08,0x67,0x10,0x00,0x08,0x67,0xac,0x00,0x08,0x68,0x70,0x00,0x08,0x69,0x26,0x00,0x08,0x69,0xfc,0x00,0x08,0x6a,0xd6,0x00,0x08,0x6b,0xc0,0x00,0x08,0x6c,0x5e,0x00,0x08,0x6d,0x12,0x00,0x08,0x6e,0x22, 0x00,0x08,0x6e,0xd8,0x00,0x08,0x6f,0x42,0x00,0x08,0x6f,0xc2,0x00,0x08,0x70,0x9e,0x00,0x08,0x71,0x44,0x00,0x08,0x72,0x00,0x00,0x08,0x72,0xa8,0x00,0x08,0x73,0x58,0x00,0x08,0x74,0x4c,0x00,0x08,0x75,0x34,0x00,0x08,0x75,0x88,0x00,0x08,0x76,0x2c,0x00,0x08,0x76,0x80,0x00,0x08,0x77,0x1a,0x00,0x08,0x78,0x46,0x00,0x08,0x78,0xe0, 0x00,0x08,0x78,0xfa,0x00,0x08,0x79,0x20,0x00,0x08,0x79,0xa8,0x00,0x08,0x79,0xc2,0x00,0x08,0x79,0xe8,0x00,0x08,0x7a,0x70,0x00,0x08,0x7a,0x9e,0x00,0x08,0x7b,0xb2,0x00,0x08,0x7b,0xe0,0x00,0x08,0x7c,0x7a,0x00,0x08,0x7c,0xe2,0x00,0x08,0x7d,0x08,0x00,0x08,0x7d,0x2e,0x00,0x08,0x7d,0x52,0x00,0x08,0x7d,0x78,0x00,0x08,0x7d,0x9c, 0x00,0x08,0x7d,0xc2,0x00,0x08,0x7d,0xfe,0x00,0x08,0x7e,0x46,0x00,0x08,0x7e,0x78,0x00,0x08,0x7f,0x14,0x00,0x08,0x7f,0xfc,0x00,0x08,0x80,0x22,0x00,0x08,0x80,0x48,0x00,0x08,0x80,0x78,0x00,0x08,0x80,0xa6,0x00,0x08,0x80,0xb6,0x00,0x08,0x80,0xc6,0x00,0x08,0x81,0x14,0x00,0x08,0x81,0xa4,0x00,0x08,0x82,0x1e,0x00,0x08,0x82,0x7e, 0x00,0x08,0x83,0x0e,0x00,0x08,0x83,0x9e,0x00,0x08,0x84,0x46,0x00,0x08,0x84,0xa4,0x00,0x08,0x84,0xf2,0x00,0x08,0x85,0x7c,0x00,0x08,0x85,0xfe,0x00,0x08,0x86,0x6c,0x00,0x08,0x86,0xe0,0x00,0x08,0x87,0x28,0x00,0x08,0x87,0x6a,0x00,0x08,0x87,0xbc,0x00,0x08,0x88,0x06,0x00,0x08,0x88,0xa8,0x00,0x08,0x88,0xd4,0x00,0x08,0x89,0x12, 0x00,0x08,0x89,0x84,0x00,0x08,0x89,0xf6,0x00,0x08,0x8a,0x7e,0x00,0x08,0x8b,0x08,0x00,0x08,0x8b,0x90,0x00,0x08,0x8c,0x38,0x00,0x08,0x8c,0xa4,0x00,0x08,0x8d,0x54,0x00,0x08,0x8d,0x84,0x00,0x08,0x8d,0xd4,0x00,0x08,0x8e,0x04,0x00,0x08,0x8e,0xd0,0x00,0x08,0x8f,0x2e,0x00,0x08,0x8f,0x7a,0x00,0x08,0x8f,0xba,0x00,0x08,0x8f,0xd8, 0x00,0x08,0x90,0x28,0x00,0x08,0x90,0x56,0x00,0x08,0x90,0x86,0x00,0x08,0x90,0xc0,0x00,0x08,0x91,0x4a,0x00,0x08,0x91,0x66,0x00,0x08,0x91,0x82,0x00,0x08,0x91,0xe2,0x00,0x08,0x92,0x10,0x00,0x08,0x92,0x66,0x00,0x08,0x92,0xb4,0x00,0x08,0x92,0xfe,0x00,0x08,0x93,0x52,0x00,0x08,0x93,0x98,0x00,0x08,0x94,0x1e,0x00,0x08,0x94,0x94, 0x00,0x08,0x94,0xe0,0x00,0x08,0x95,0x2e,0x00,0x08,0x95,0x7c,0x00,0x08,0x95,0xca,0x00,0x08,0x96,0x18,0x00,0x08,0x96,0x66,0x00,0x08,0x96,0xb4,0x00,0x08,0x97,0x02,0x00,0x08,0x97,0x50,0x00,0x08,0x97,0x9e,0x00,0x08,0x97,0xc0,0x00,0x08,0x97,0xe6,0x00,0x08,0x98,0x0c,0x00,0x08,0x98,0x32,0x00,0x08,0x98,0x52,0x00,0x08,0x99,0x8c, 0x00,0x08,0x9a,0x5c,0x00,0x08,0x9b,0x26,0x00,0x08,0x9c,0xa0,0x00,0x08,0x9d,0x40,0x00,0x08,0x9d,0xa4,0x00,0x08,0x9d,0xbc,0x00,0x08,0x9d,0xd4,0x00,0x08,0x9e,0xa8,0x00,0x08,0x9f,0x86,0x00,0x08,0x9f,0xf0,0x00,0x08,0xa0,0x76,0x00,0x08,0xa1,0x46,0x00,0x08,0xa2,0x16,0x00,0x08,0xa2,0xd6,0x00,0x08,0xa3,0x98,0x00,0x08,0xa4,0x34, 0x00,0x08,0xa4,0xd0,0x00,0x08,0xa4,0xe0,0x00,0x08,0xa5,0xa4,0x00,0x08,0xa6,0x5c,0x00,0x08,0xa6,0xb8,0x00,0x08,0xa6,0xec,0x00,0x08,0xa7,0x0e,0x00,0x08,0xa7,0xec,0x00,0x08,0xa8,0xee,0x00,0x08,0xa9,0x9a,0x00,0x08,0xaa,0x4c,0x00,0x08,0xaa,0xfc,0x00,0x08,0xab,0x0c,0x00,0x08,0xac,0x2e,0x00,0x08,0xac,0xda,0x00,0x08,0xac,0xfa, 0x00,0x08,0xad,0x92,0x00,0x08,0xae,0x8a,0x00,0x08,0xaf,0x44,0x00,0x08,0xb0,0x2e,0x00,0x08,0xb0,0xd0,0x00,0x08,0xb1,0x98,0x00,0x08,0xb2,0x50,0x00,0x08,0xb3,0x2c,0x00,0x08,0xb4,0x50,0x00,0x08,0xb5,0x4c,0x00,0x08,0xb6,0x22,0x00,0x08,0xb7,0x38,0x00,0x08,0xb7,0x90,0x00,0x08,0xb8,0x46,0x00,0x08,0xb8,0x8c,0x00,0x08,0xb9,0x06, 0x00,0x08,0xb9,0xbe,0x00,0x08,0xba,0x9e,0x00,0x08,0xbb,0x02,0x00,0x08,0xbb,0xb0,0x00,0x08,0xbb,0xc0,0x00,0x08,0xbc,0x18,0x00,0x08,0xbc,0xa0,0x00,0x08,0xbd,0x70,0x00,0x08,0xbe,0x40,0x00,0x08,0xbe,0xc0,0x00,0x08,0xbe,0xd0,0x00,0x08,0xbf,0xb4,0x00,0x08,0xc0,0x46,0x00,0x08,0xc1,0x26,0x00,0x08,0xc1,0x9a,0x00,0x08,0xc2,0x7e, 0x00,0x08,0xc3,0x1a,0x00,0x08,0xc3,0x82,0x00,0x08,0xc3,0xfe,0x00,0x08,0xc4,0x74,0x00,0x08,0xc5,0x16,0x00,0x08,0xc5,0xc2,0x00,0x08,0xc6,0x46,0x00,0x08,0xc6,0xd8,0x00,0x08,0xc6,0xe8,0x00,0x08,0xc6,0xfa,0x00,0x08,0xc7,0x0c,0x00,0x08,0xc7,0x1e,0x00,0x08,0xc7,0x30,0x00,0x08,0xc7,0x42,0x00,0x08,0xc7,0x54,0x00,0x08,0xc7,0x66, 0x00,0x08,0xc7,0x78,0x00,0x08,0xc7,0x8a,0x00,0x08,0xc7,0x9c,0x00,0x08,0xc7,0xac,0x00,0x08,0xc7,0xbe,0x00,0x08,0xc7,0xd0,0x00,0x08,0xc7,0xe0,0x00,0x08,0xc7,0xf2,0x00,0x08,0xc8,0x04,0x00,0x08,0xc8,0x16,0x00,0x08,0xc8,0x2e,0x00,0x08,0xc8,0x46,0x00,0x08,0xc8,0x5e,0x00,0x08,0xc8,0x74,0x00,0x08,0xc8,0x8a,0x00,0x08,0xca,0x64, 0x00,0x08,0xd0,0x7e,0x00,0x08,0xd2,0xb4,0x00,0x08,0xd9,0xd8,0x00,0x08,0xd9,0xea,0x00,0x08,0xda,0x02,0x00,0x08,0xda,0x14,0x00,0x08,0xda,0x64,0x00,0x08,0xda,0x74,0x00,0x08,0xda,0x86,0x00,0x08,0xda,0x9e,0x00,0x08,0xda,0xb0,0x00,0x08,0xda,0xc8,0x00,0x08,0xda,0xd8,0x00,0x08,0xda,0xee,0x00,0x08,0xdb,0x00,0x00,0x08,0xdb,0x18, 0x00,0x08,0xdb,0x2a,0x00,0x08,0xdb,0x42,0x00,0x08,0xdb,0x76,0x00,0x08,0xdb,0xe0,0x00,0x08,0xdc,0x00,0x00,0x08,0xdc,0x20,0x00,0x08,0xdc,0x40,0x00,0x08,0xdc,0x60,0x00,0x08,0xdc,0x72,0x00,0x08,0xdc,0x8a,0x00,0x08,0xdc,0xa2,0x00,0x08,0xdc,0xba,0x00,0x08,0xdc,0xd2,0x00,0x08,0xdc,0xea,0x00,0x08,0xdd,0x02,0x00,0x08,0xdd,0x1a, 0x00,0x08,0xdd,0x32,0x00,0x08,0xdd,0x4a,0x00,0x08,0xdd,0x62,0x00,0x08,0xdd,0xf4,0x00,0x08,0xde,0x98,0x00,0x08,0xde,0xb8,0x00,0x08,0xde,0xd8,0x00,0x08,0xdf,0x32,0x00,0x08,0xdf,0x5a,0x00,0x08,0xdf,0x6a,0x00,0x08,0xdf,0x82,0x00,0x08,0xdf,0x9a,0x00,0x08,0xdf,0xfe,0x00,0x08,0xe0,0x68,0x00,0x08,0xe1,0x3a,0x00,0x08,0xe1,0xe8, 0x00,0x08,0xe2,0x86,0x00,0x08,0xe3,0x22,0x00,0x08,0xe3,0x3a,0x00,0x08,0xe3,0x52,0x00,0x08,0xe3,0x62,0x00,0x08,0xe3,0x72,0x00,0x08,0xe4,0x36,0x00,0x08,0xe4,0xe0,0x00,0x08,0xe4,0xf0,0x00,0x08,0xe5,0x00,0x00,0x08,0xe6,0x9c,0x00,0x08,0xe6,0xc6,0x00,0x08,0xe7,0x9c,0x00,0x08,0xe8,0x80,0x00,0x08,0xe8,0xd2,0x00,0x08,0xe8,0xe4, 0x00,0x08,0xe9,0x06,0x00,0x08,0xe9,0x18,0x00,0x08,0xe9,0x6c,0x00,0x08,0xe9,0x7e,0x00,0x08,0xea,0x14,0x00,0x08,0xea,0x26,0x00,0x08,0xea,0xde,0x00,0x08,0xeb,0x30,0x00,0x08,0xeb,0x96,0x00,0x08,0xeb,0xea,0x00,0x08,0xec,0x50,0x00,0x08,0xec,0xa2,0x00,0x08,0xed,0x08,0x00,0x08,0xed,0x5a,0x00,0x08,0xed,0xc0,0x00,0x08,0xed,0xd0, 0x00,0x08,0xee,0x14,0x00,0x08,0xee,0xbe,0x00,0x08,0xee,0xce,0x00,0x08,0xef,0x72,0x00,0x08,0xef,0x82,0x00,0x08,0xf0,0x60,0x00,0x08,0xf0,0x70,0x00,0x08,0xf0,0xe0,0x00,0x08,0xf1,0x84,0x00,0x08,0xf2,0x52,0x00,0x08,0xf3,0x0a,0x00,0x08,0xf3,0xa2,0x00,0x08,0xf4,0x72,0x00,0x08,0xf4,0xb6,0x00,0x08,0xf5,0x92,0x00,0x08,0xf6,0xe4, 0x00,0x08,0xf8,0x9a,0x00,0x08,0xf9,0xc2,0x00,0x08,0xfb,0x6a,0x00,0x08,0xfb,0x82,0x00,0x08,0xfb,0x9a,0x00,0x08,0xfb,0xba,0x00,0x08,0xfb,0xda,0x00,0x08,0xfb,0xf2,0x00,0x08,0xfc,0x0a,0x00,0x08,0xfc,0x2a,0x00,0x08,0xfc,0x3a,0x00,0x08,0xfc,0x4a,0x00,0x08,0xfc,0x5a,0x00,0x08,0xfd,0xb0,0x00,0x08,0xfe,0x98,0x00,0x08,0xff,0x4a, 0x00,0x09,0x00,0x2a,0x00,0x09,0x00,0xb8,0x00,0x09,0x00,0xca,0x00,0x09,0x02,0x4a,0x00,0x09,0x04,0x28,0x00,0x09,0x05,0xf4,0x00,0x09,0x07,0x6a,0x00,0x09,0x08,0x98,0x00,0x09,0x0a,0x78,0x00,0x09,0x0b,0x12,0x00,0x09,0x0b,0xd4,0x00,0x09,0x0c,0x8e,0x00,0x09,0x0c,0xa0,0x00,0x09,0x0c,0xbc,0x00,0x09,0x0c,0xd4,0x00,0x09,0x0c,0xec, 0x00,0x09,0x0d,0x04,0x00,0x09,0x0d,0x1c,0x00,0x09,0x0d,0x34,0x00,0x09,0x0d,0x54,0x00,0x09,0x0d,0x74,0x00,0x09,0x0d,0x94,0x00,0x09,0x0d,0xb4,0x00,0x09,0x0d,0xd4,0x00,0x09,0x0d,0xf4,0x00,0x09,0x0e,0x0c,0x00,0x09,0x0f,0x08,0x00,0x09,0x0f,0xe2,0x00,0x09,0x10,0x80,0x00,0x09,0x10,0x98,0x00,0x09,0x10,0xb8,0x00,0x09,0x10,0xd8, 0x00,0x09,0x10,0xf8,0x00,0x09,0x11,0x08,0x00,0x09,0x11,0x20,0x00,0x09,0x11,0x38,0x00,0x09,0x11,0x48,0x00,0x09,0x11,0x60,0x00,0x09,0x11,0x78,0x00,0x09,0x11,0x88,0x00,0x09,0x11,0xd2,0x00,0x09,0x12,0x0c,0x00,0x09,0x12,0x4e,0x00,0x09,0x13,0x00,0x00,0x09,0x13,0x92,0x00,0x09,0x14,0x14,0x00,0x09,0x14,0x5e,0x00,0x09,0x14,0xb0, 0x00,0x09,0x15,0x02,0x00,0x09,0x15,0x9a,0x00,0x09,0x16,0x2a,0x00,0x09,0x16,0xd4,0x00,0x09,0x17,0x66,0x00,0x09,0x17,0xea,0x00,0x09,0x18,0x2e,0x00,0x09,0x1a,0x76,0x00,0x09,0x1c,0x24,0x00,0x09,0x1c,0x68,0x00,0x09,0x1c,0x98,0x00,0x09,0x1c,0xc8,0x00,0x09,0x1c,0xd8,0x00,0x09,0x1c,0xe8,0x00,0x09,0x1d,0x32,0x00,0x09,0x1d,0x6e, 0x00,0x09,0x1d,0xb2,0x00,0x09,0x1e,0x72,0x00,0x09,0x1f,0x06,0x00,0x09,0x1f,0x86,0x00,0x09,0x1f,0xd4,0x00,0x09,0x20,0x2e,0x00,0x09,0x20,0x8a,0x00,0x09,0x21,0x32,0x00,0x09,0x21,0xd2,0x00,0x09,0x22,0x8a,0x00,0x09,0x23,0x1c,0x00,0x09,0x23,0xa4,0x00,0x09,0x23,0xee,0x00,0x09,0x24,0x06,0x00,0x09,0x24,0x26,0x00,0x09,0x24,0xbe, 0x00,0x09,0x25,0x8e,0x00,0x09,0x26,0x66,0x00,0x09,0x27,0x7e,0x00,0x09,0x28,0x24,0x00,0x09,0x28,0xf6,0x00,0x09,0x29,0xdc,0x00,0x09,0x2a,0xa8,0x00,0x09,0x2b,0x2a,0x00,0x09,0x2b,0xe8,0x00,0x09,0x2d,0x1c,0x00,0x09,0x2d,0xde,0x00,0x09,0x2e,0xbc,0x00,0x09,0x2f,0x8a,0x00,0x09,0x30,0x5a,0x00,0x09,0x31,0x46,0x00,0x09,0x32,0x6a, 0x00,0x09,0x32,0xf4,0x00,0x09,0x34,0x44,0x00,0x09,0x35,0x52,0x00,0x09,0x36,0x94,0x00,0x09,0x37,0x42,0x00,0x09,0x38,0x46,0x00,0x09,0x39,0x0a,0x00,0x09,0x3a,0x26,0x00,0x09,0x3a,0xf8,0x00,0x09,0x3b,0xcc,0x00,0x09,0x3c,0x52,0x00,0x09,0x3d,0x76,0x00,0x09,0x3e,0x9e,0x00,0x09,0x3f,0x20,0x00,0x09,0x40,0x62,0x00,0x09,0x41,0x64, 0x00,0x09,0x42,0x74,0x00,0x09,0x43,0x46,0x00,0x09,0x44,0x02,0x00,0x09,0x44,0xe6,0x00,0x09,0x45,0xdc,0x00,0x09,0x46,0xa4,0x00,0x09,0x47,0x60,0x00,0x09,0x48,0x26,0x00,0x09,0x48,0xfe,0x00,0x09,0x49,0x8e,0x00,0x09,0x49,0x8e,0x00,0x09,0x49,0x8e,0x00,0x09,0x4a,0x4a,0x00,0x09,0x4b,0x1e,0x00,0x09,0x4b,0xac,0x00,0x09,0x4b,0xfc, 0x00,0x02,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x00,0x03,0x00,0x07,0x00,0x1a,0x40,0x0b,0x07,0x01,0x03,0x04,0x00,0x03,0x05,0x05,0x09,0x04,0x00,0x2f,0xcd,0x12,0x39,0x2f,0xcd,0x00,0x2f,0xcd,0x3f,0xcd,0x31,0x30,0x33,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0xa6,0x03,0xde,0xfc,0xb6,0x02,0xb6,0xfd,0x4a,0x05,0x76,0xfa,0x8a,0x94, 0x04,0x4e,0x00,0x02,0x00,0xb4,0xff,0xee,0x01,0x92,0x05,0x9a,0x00,0x03,0x00,0x0f,0x00,0x3f,0x40,0x20,0x03,0x03,0x02,0x0a,0x40,0x04,0x0a,0xb0,0x5b,0x04,0x13,0x01,0x02,0x00,0x7d,0x1f,0x03,0x2f,0x03,0x02,0x03,0x0d,0xaf,0x7f,0x07,0x01,0x10,0x07,0x20,0x07,0x02,0x07,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x07,0x2f,0x2b,0x72,0x5d, 0xe1,0xd4,0x72,0xe1,0x39,0x39,0x00,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xce,0x3f,0x31,0x30,0x01,0x03,0x23,0x03,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x77,0x13,0x87,0x12,0x58,0x2e,0x41,0x41,0x2e,0x2d,0x42,0x42,0x05,0x9a,0xfb,0xfa,0x04,0x06,0xfa,0x54,0x40,0x2e,0x2e,0x41,0x41,0x2e,0x2e,0x40,0x00,0x02, 0x00,0xa3,0x03,0xdb,0x02,0x80,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x23,0x40,0x14,0x0f,0x04,0x1f,0x04,0x2f,0x04,0xbf,0x04,0xcf,0x04,0x05,0x04,0x04,0x09,0x03,0x06,0x02,0x07,0x03,0x03,0x00,0x3f,0x33,0xcd,0x32,0x01,0x2f,0x12,0x39,0x2f,0x5d,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x01,0x34,0x91,0x01,0xdd,0x91,0x05, 0x9a,0xfe,0x41,0x01,0xbf,0xfe,0x41,0x01,0xbf,0x00,0x00,0x02,0x00,0x21,0x00,0x7b,0x04,0x8e,0x05,0x9a,0x00,0x1b,0x00,0x1f,0x00,0xbf,0x40,0x6b,0x0f,0x17,0x01,0x00,0x06,0x01,0x10,0x06,0x1b,0x02,0x03,0x06,0x07,0x1a,0x07,0x18,0x1c,0x1f,0x09,0x08,0x19,0x08,0x17,0x1d,0x1e,0x0a,0x0b,0x16,0x0b,0x14,0x11,0x10,0x0d,0x0c,0x15,0x0c, 0x09,0x0d,0x10,0x1f,0x04,0x06,0x03,0x06,0x03,0xe2,0x59,0x11,0x14,0x17,0x1d,0x04,0x02,0x1b,0x1b,0x02,0xe2,0x59,0x1b,0x06,0x1b,0x06,0x1a,0x0b,0x00,0x07,0x10,0x07,0x02,0x09,0x07,0x07,0x21,0x16,0x1a,0x03,0x04,0x00,0x00,0x19,0x1a,0x0e,0x07,0x0f,0x08,0x01,0x0c,0x03,0x08,0x08,0x21,0x0c,0x0c,0x16,0x42,0x12,0x0e,0x0e,0x15,0x16, 0x0b,0x60,0x0c,0x70,0x0c,0x02,0x0c,0x2f,0x5d,0x33,0xcd,0x32,0x33,0x2f,0xc6,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0xe1,0x32,0x32,0x2f,0xc6,0x00,0x3f,0xc4,0x12,0x39,0x2f,0x5e,0x5d,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x2b,0x11,0x12,0x00,0x17,0x39,0x2b,0x11,0x12,0x00,0x17,0x39,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0, 0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x01,0x5f,0x5e,0x5d,0x5d,0x01,0x07,0x21,0x03,0x21,0x07,0x21,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x21,0x37,0x21,0x13,0x21,0x37,0x21,0x13,0x33,0x03,0x33,0x13,0x33,0x03,0x07,0x23,0x03,0x33,0x04,0x8e,0x17,0xfe,0xfb,0x3f,0x01, 0x19,0x1b,0xfe,0xed,0x58,0x7e,0x56,0xfa,0x54,0x7d,0x54,0xfe,0xfa,0x14,0x01,0x09,0x3d,0xfe,0xeb,0x15,0x01,0x15,0x54,0x7e,0x54,0xfc,0x56,0x7b,0x54,0x91,0xfc,0x42,0xfe,0x04,0x08,0x6a,0xfe,0xd4,0x6a,0xfe,0x73,0x01,0x8d,0xfe,0x73,0x01,0x8d,0x6a,0x01,0x2c,0x6a,0x01,0x92,0xfe,0x6e,0x01,0x92,0xfe,0x6e,0x6a,0xfe,0xd4,0x00,0x03, 0x00,0xa2,0xff,0x2f,0x03,0xd1,0x06,0x50,0x00,0x1e,0x00,0x25,0x00,0x2a,0x00,0xc1,0x40,0x1b,0x09,0x26,0x01,0x06,0x1f,0x01,0x0a,0x1d,0x01,0x05,0x15,0x01,0x03,0x00,0x0e,0x01,0x0f,0x05,0x01,0x10,0x05,0x2a,0x20,0x0c,0x00,0x4d,0x25,0xb8,0xff,0xe0,0xb3,0x0c,0x00,0x4d,0x15,0xb8,0xff,0xd0,0x40,0x56,0x0c,0x00,0x4d,0x05,0x30,0x0c, 0x00,0x4d,0x1f,0x19,0x09,0x26,0x0a,0x03,0x13,0x16,0x16,0x20,0x18,0x13,0x18,0x9a,0x59,0x10,0x12,0x40,0x13,0x06,0x00,0x06,0x10,0x06,0x20,0x06,0x03,0x09,0x03,0x06,0x06,0x27,0x09,0x03,0x09,0x9a,0x59,0x00,0x02,0x03,0x18,0x09,0x10,0x13,0x19,0x1f,0x27,0x06,0x01,0x8c,0x02,0x02,0x1c,0x0d,0x16,0x40,0x0c,0x11,0x00,0x4c,0x16,0x16, 0x1c,0x89,0x7f,0x29,0x01,0x2f,0x29,0x01,0x29,0x05,0x23,0x89,0x20,0x0d,0x01,0x0d,0x2f,0x5d,0xe1,0xc4,0xd4,0x5d,0x5d,0xf1,0xc0,0x2f,0x2b,0x11,0x12,0x39,0x2f,0xe1,0x17,0x39,0x00,0x3f,0xcd,0x33,0x2b,0x11,0x00,0x33,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x1a,0xcd,0x33,0x2b,0x11,0x00,0x33,0x33,0x18,0x2f,0x11,0x12,0x39,0x39,0x12, 0x39,0x39,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x25,0x15,0x23,0x35,0x22,0x27,0x35,0x16,0x16,0x33,0x11,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x15,0x26,0x27,0x11,0x16,0x16,0x15,0x14,0x06,0x01,0x11,0x06,0x06,0x15,0x14,0x16,0x13,0x11,0x36,0x35,0x34,0x02,0x68,0x68,0xd5, 0x85,0x3a,0xc9,0x57,0xdc,0x82,0xc6,0x98,0x68,0xc4,0x4b,0x66,0xa9,0xd0,0x99,0xbf,0xfe,0xee,0x54,0x62,0x50,0xce,0xc1,0x08,0xd9,0xd1,0x56,0xae,0x33,0x45,0x02,0x00,0x6a,0xb3,0x7a,0x91,0xd3,0x15,0xb4,0xb0,0x06,0x32,0xaa,0x50,0x06,0xfd,0xf0,0x63,0xb9,0x76,0x8e,0xc1,0x03,0x19,0x01,0xd2,0x11,0x73,0x52,0x56,0x6e,0xfe,0xe4,0xfe, 0x3c,0x2a,0xa6,0x8a,0x00,0x05,0x00,0x50,0xff,0xea,0x06,0x40,0x05,0xb0,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x27,0x00,0x33,0x00,0xaf,0x40,0x32,0x19,0x18,0x03,0x22,0x28,0x52,0x59,0x22,0x0e,0x1c,0x1c,0x2e,0x52,0x59,0x1c,0x13,0x06,0x00,0x42,0x00,0x12,0x52,0x59,0x00,0x06,0x06,0x0c,0x52,0x59,0x06,0x04,0x3f,0x18,0x4f,0x18,0x02, 0x1a,0x18,0x1a,0x18,0x25,0x03,0x1f,0xbd,0x2b,0x0c,0x0d,0x06,0x4d,0x2b,0xb8,0xff,0xf9,0xb6,0x0b,0x06,0x4d,0x2b,0x31,0xbd,0x25,0xb8,0xff,0xe0,0x40,0x14,0x0d,0x06,0x4d,0x25,0x18,0x0c,0x06,0x4d,0x25,0x09,0x0b,0x06,0x4d,0x25,0x25,0x35,0x03,0x09,0xbd,0x15,0xb8,0xff,0xec,0x40,0x16,0x0d,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15, 0x0f,0xbd,0x03,0x1c,0x0d,0x06,0x4d,0x03,0x1c,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xe4,0xb3,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0xd4,0x2b,0x2b,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0xd4,0x2b,0x2b,0xe1,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc4,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18, 0x10,0xe4,0x2b,0x00,0x18,0x3f,0x2f,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x25,0x01,0x23,0x01,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x94,0x94, 0xb0,0xba,0x9e,0x99,0xa9,0xbd,0x8b,0x5f,0x6e,0x6c,0x5d,0x5e,0x6a,0x69,0x03,0x57,0xfc,0x68,0x8f,0x03,0x97,0x26,0x94,0xb0,0xbc,0x9c,0x98,0xaa,0xbd,0x8b,0x60,0x6d,0x6c,0x5d,0x5e,0x6a,0x69,0x02,0xcb,0xc3,0xa3,0xb2,0xcd,0xbe,0xac,0xac,0xcf,0x02,0x77,0x8d,0x7b,0x79,0x87,0x8c,0x7c,0x79,0x87,0x58,0xfa,0x5c,0x05,0xa4,0xfa,0x50, 0xc4,0xa2,0xb2,0xcf,0xc0,0xad,0xab,0xcf,0x02,0x76,0x8c,0x7c,0x77,0x87,0x8d,0x7b,0x7a,0x84,0x00,0x03,0x00,0x77,0xff,0xe9,0x06,0x3e,0x05,0xb2,0x00,0x43,0x00,0x57,0x00,0x67,0x00,0xd7,0x40,0x1c,0x58,0x4f,0x01,0x5c,0x4c,0x01,0x03,0x59,0x4b,0x01,0x5d,0x4a,0x01,0x50,0x37,0x01,0x52,0x36,0x01,0x5b,0x0d,0x01,0x4a,0x40,0x0b,0x00, 0x4d,0x51,0xb8,0xff,0xe8,0x40,0x0c,0x0b,0x00,0x4d,0x1d,0x4d,0x01,0x02,0x1f,0x01,0x0b,0x04,0x10,0xb8,0xff,0xe0,0x40,0x5c,0x0b,0x00,0x4d,0x05,0x49,0x4e,0x12,0x04,0x0a,0x2f,0x38,0x29,0x24,0x65,0x2f,0x05,0x1c,0x44,0x1c,0x5d,0x96,0x59,0x1c,0x04,0x0a,0x44,0x95,0x59,0x0a,0x13,0x00,0x3d,0xec,0x59,0x00,0x13,0x3a,0x49,0x01,0x38, 0x05,0x33,0x0f,0x29,0x49,0x2c,0x53,0x12,0x4e,0x65,0x24,0x04,0x21,0x17,0x33,0xef,0x2c,0x21,0xef,0x58,0x60,0xef,0x17,0x17,0x58,0x2c,0x03,0x0f,0x70,0x40,0x01,0x40,0x40,0x69,0x53,0x08,0x0d,0x06,0x4d,0x53,0x08,0x0c,0x06,0x4d,0x53,0x08,0x0b,0x06,0x4d,0x53,0x83,0x0f,0x2f,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x12,0x17,0x39, 0x2f,0xe1,0x2f,0xe1,0x2f,0xe1,0x11,0x12,0x17,0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x17,0x39,0x18,0x2f,0x11,0x17,0x39,0x31,0x30,0x2b,0x5f,0x5e,0x5d,0x5d,0x2b,0x01,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x00,0x5f,0x5d,0x5d,0x05,0x22,0x2e,0x02,0x27, 0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x17,0x36,0x12,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x14,0x0e,0x02,0x07,0x1e,0x03,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x25,0x32,0x3e,0x02,0x37,0x2e,0x03,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02, 0x01,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x14,0x1e,0x02,0x17,0x36,0x36,0x05,0xa5,0x39,0x57,0x4a,0x45,0x26,0x28,0x69,0x80,0x98,0x59,0x6c,0xb4,0x80,0x47,0xae,0x9f,0x1e,0x3c,0x2f,0x1d,0x39,0x64,0x88,0x4f,0x4e,0x81,0x5d,0x34,0x89,0x89,0x45,0x70,0x5f,0x52,0x28,0x51,0x52,0x09,0x08,0x9f,0x08,0x03,0x02,0x26,0x40,0x55,0x2f,0x23, 0x3a,0x3b,0x3f,0x28,0x1e,0x3e,0x21,0x24,0x4f,0xfc,0x93,0x4c,0x80,0x6c,0x58,0x24,0x3d,0x67,0x69,0x77,0x4e,0x3f,0x6a,0x4d,0x2c,0x32,0x57,0x74,0x01,0x3d,0x25,0x39,0x46,0x22,0x62,0x75,0x01,0x19,0x2d,0x3c,0x22,0x7e,0x7c,0x17,0x1f,0x39,0x52,0x34,0x2b,0x50,0x3e,0x25,0x36,0x69,0x9a,0x64,0x99,0xd9,0x45,0x16,0x3b,0x4b,0x5b,0x36, 0x4f,0x7a,0x54,0x2b,0x2b,0x50,0x70,0x45,0x78,0x9f,0x38,0x1b,0x4e,0x60,0x6e,0x3b,0x71,0x01,0x10,0x95,0x26,0x43,0x21,0x21,0x3b,0x29,0x5b,0xb8,0xad,0x9c,0x41,0x30,0x47,0x30,0x17,0x10,0x0c,0x98,0x0e,0x0e,0x8e,0x21,0x37,0x49,0x28,0x5f,0x87,0x62,0x46,0x1e,0x19,0x3d,0x53,0x6e,0x4a,0x44,0x68,0x45,0x23,0x03,0xfd,0x32,0x46,0x2e, 0x15,0x6a,0x5b,0x29,0x48,0x3e,0x30,0x11,0x2c,0x75,0x00,0x01,0x00,0xa3,0x03,0xdb,0x01,0x34,0x05,0x9a,0x00,0x03,0x00,0x0c,0xb3,0x03,0x02,0x03,0x03,0x00,0x3f,0xcd,0x01,0x2f,0x31,0x30,0x01,0x11,0x23,0x11,0x01,0x34,0x91,0x05,0x9a,0xfe,0x41,0x01,0xbf,0x00,0x00,0x01,0x00,0x8c,0xfe,0xba,0x02,0x56,0x05,0x9a,0x00,0x09,0x00,0x41, 0x40,0x2b,0x05,0x10,0x0b,0x01,0x4d,0x01,0x10,0x0b,0x01,0x4d,0x38,0x02,0x01,0x06,0x03,0x00,0x20,0x05,0xea,0x06,0x01,0xea,0x00,0x00,0x0b,0x08,0x08,0x0c,0x06,0x4d,0x08,0x10,0x0b,0x06,0x4d,0x08,0xea,0x03,0x10,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0xe1,0xd6,0xe1,0x00,0x3f,0x3f,0x31,0x30,0x01,0x5d,0x2b, 0x2b,0x01,0x23,0x00,0x11,0x10,0x01,0x33,0x00,0x11,0x10,0x02,0x54,0x92,0xfe,0xca,0x01,0x36,0x94,0xfe,0xc6,0xfe,0xba,0x01,0x62,0x02,0x07,0x02,0x09,0x01,0x6e,0xfe,0x84,0xfe,0x07,0xfe,0x0b,0x00,0x00,0x01,0x00,0x16,0xfe,0xba,0x01,0xe2,0x05,0x9a,0x00,0x09,0x00,0x4a,0xb9,0x00,0x06,0xff,0xf0,0xb3,0x0b,0x01,0x4d,0x00,0xb8,0xff, 0xf0,0x40,0x0b,0x0b,0x01,0x4d,0x37,0x09,0x01,0x06,0x03,0x00,0x20,0x03,0xb8,0xff,0xf0,0xb5,0x0b,0x06,0x4d,0x03,0xea,0x08,0xb8,0xff,0xf8,0x40,0x0d,0x0b,0x06,0x4d,0x08,0x08,0x0b,0x01,0x06,0xea,0x05,0x00,0xea,0x01,0x2f,0xe1,0xd6,0xe1,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x00,0x3f,0x3f,0x31,0x30,0x01,0x5d,0x2b,0x2b,0x13,0x23, 0x00,0x11,0x10,0x01,0x33,0x00,0x11,0x10,0xaa,0x92,0x01,0x38,0xfe,0xc6,0x94,0x01,0x38,0xfe,0xba,0x01,0x76,0x01,0xf5,0x01,0xf9,0x01,0x7c,0xfe,0x92,0xfd,0xf7,0xfd,0xf9,0x00,0x00,0x01,0x00,0x4c,0x02,0xd9,0x03,0x0c,0x05,0x9a,0x00,0x0e,0x00,0x67,0x40,0x31,0x03,0x04,0x01,0x10,0x03,0x03,0x05,0x08,0x0a,0x0d,0x0e,0x00,0x04,0x08, 0x09,0x09,0x08,0x53,0x59,0x0f,0x09,0x01,0x10,0x03,0x09,0x0c,0x03,0x02,0x02,0x00,0x0e,0x0c,0x06,0x06,0x0b,0x08,0x0b,0x08,0x42,0x08,0x04,0x0a,0x0d,0x03,0x01,0x0d,0x0c,0x48,0x0b,0xb8,0xff,0xf8,0xb5,0x0d,0x06,0x4d,0x07,0x0a,0x0b,0x2f,0x33,0x33,0x2b,0xed,0x32,0x32,0x17,0x39,0xc4,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0x10,0xe4, 0x39,0x2f,0x00,0x3f,0xc4,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x17,0x39,0x18,0x10,0xd4,0xc4,0x31,0x30,0x5f,0x5e,0x5d,0x01,0x05,0x17,0x07,0x03,0x03,0x27,0x37,0x25,0x37,0x05,0x03,0x33,0x03,0x25,0x03,0x0c,0xfe,0xee,0xbe,0x6e,0x9c,0x9e,0x6e,0xbe,0xfe,0xec,0x2d,0x01,0x06,0x17,0x8a,0x17,0x01,0x07,0x04,0x50,0x38,0xf3,0x4c,0x01, 0x09,0xfe,0xf7,0x4c,0xf3,0x38,0x7d,0x63,0x01,0x30,0xfe,0xd0,0x63,0x00,0x00,0x01,0x00,0xe8,0x00,0x7f,0x04,0x94,0x04,0x2b,0x00,0x0b,0x00,0x49,0x40,0x21,0x03,0x0e,0x04,0x08,0x0e,0x07,0x40,0x0a,0x01,0x04,0x07,0x07,0x04,0xbe,0x59,0x0f,0x07,0x01,0x0d,0x03,0x07,0x00,0x0e,0x01,0x04,0x05,0x42,0x05,0x0a,0x07,0x01,0xbd,0x04,0xb8, 0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x04,0x2f,0x2b,0xe1,0x39,0x39,0xcd,0x2b,0x01,0x10,0xe1,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x04,0x94,0xfe,0x6c,0x85,0xfe,0x6d,0x01,0x93,0x85,0x01,0x94,0x02,0x12,0xfe, 0x6d,0x01,0x93,0x86,0x01,0x93,0xfe,0x6d,0x00,0x01,0x00,0x27,0xfe,0xf8,0x01,0x3c,0x00,0xe4,0x00,0x03,0x00,0x45,0x40,0x1d,0x39,0x03,0x01,0x39,0x00,0x01,0x02,0x40,0x03,0xb2,0x04,0x00,0x20,0x0c,0x06,0x4d,0x00,0x28,0x0b,0x06,0x4d,0x00,0x80,0x02,0x40,0x11,0x19,0x48,0x02,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xea, 0xb6,0x0b,0x06,0x4d,0x02,0x2f,0x05,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0x1a,0xcd,0x2b,0x2b,0x00,0x10,0xf6,0x1a,0xcd,0x31,0x30,0x01,0x5d,0x5d,0x25,0x03,0x23,0x13,0x01,0x3c,0xa0,0x75,0x75,0xe4,0xfe,0x14,0x01,0xec,0x00,0x00,0x01,0x00,0x90,0x01,0xfa,0x02,0xb2,0x02,0x7b,0x00,0x03,0x00,0x1c,0x40,0x10,0x02,0x01,0x53,0x59,0x4f,0x02, 0x01,0x02,0x20,0x00,0x01,0x00,0x20,0x01,0x01,0x01,0x2f,0x5d,0x2f,0x5d,0x00,0x2f,0x5d,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0xb2,0xfd,0xde,0x02,0x22,0x01,0xfa,0x81,0x00,0x00,0x01,0x00,0x70,0xff,0xea,0x01,0x50,0x00,0xcb,0x00,0x0b,0x00,0x1c,0x40,0x11,0x00,0x06,0xb0,0x5b,0x00,0x13,0x09,0xaf,0x1f,0x03,0x2f,0x03,0x02,0x03, 0x2f,0x0d,0x01,0x5d,0x2f,0x71,0xe1,0x00,0x3f,0x2b,0x31,0x30,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x16,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x00,0x00,0x01,0xff,0xe4,0xff,0x12,0x03,0x2d,0x05,0x9a,0x00,0x03,0x00,0x19,0x40,0x0d,0x77,0x01,0x01,0x00,0x10,0x0b, 0x00,0x4d,0x01,0x00,0x03,0x00,0x02,0x2f,0x2f,0x00,0x3f,0x2f,0x31,0x30,0x01,0x2b,0x5d,0x01,0x01,0x23,0x01,0x03,0x2d,0xfd,0x50,0x99,0x02,0xae,0x05,0x9a,0xf9,0x78,0x06,0x88,0x00,0x02,0x00,0x56,0xff,0xe7,0x03,0xfc,0x05,0xb2,0x00,0x10,0x00,0x18,0x00,0x29,0x40,0x15,0x00,0x89,0x11,0x11,0x1a,0x15,0x89,0x40,0x0a,0x0f,0x13,0x9a, 0x59,0x0f,0x07,0x05,0x17,0x9a,0x59,0x05,0x19,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x01,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x02,0x06,0x06,0x23,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x20,0x03,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x03,0xfc,0x41,0x7b,0xb3,0x72,0x6c,0xa9,0x74,0x3c,0x3f,0x7a, 0xb5,0x75,0x01,0xc3,0xa8,0xfe,0xdd,0xfe,0xcd,0x01,0x2d,0x01,0x29,0x02,0xd3,0xb4,0xfe,0xea,0xbf,0x63,0x5f,0xb6,0x01,0x09,0xab,0xbc,0x01,0x20,0xc3,0x63,0xfd,0x11,0x02,0x64,0xfd,0x91,0xfd,0xbb,0x00,0x01,0x00,0xe4,0x00,0x00,0x02,0xd4,0x05,0xba,0x00,0x0e,0x00,0x1d,0x40,0x0d,0x0d,0x07,0x00,0x8a,0x01,0x08,0x07,0x07,0x01,0x0d, 0x07,0x01,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x33,0x01,0x2f,0xed,0xc6,0x33,0x31,0x30,0x21,0x23,0x11,0x0e,0x03,0x07,0x35,0x3e,0x03,0x37,0x33,0x02,0xd4,0xa4,0x13,0x49,0x5b,0x65,0x30,0x36,0x79,0x75,0x68,0x26,0x3e,0x04,0xd7,0x13,0x31,0x30,0x2a,0x0c,0xa6,0x0f,0x33,0x3f,0x45,0x21,0x00,0x00,0x01,0x00,0x6d,0x00,0x00,0x03,0xe2, 0x05,0xb2,0x00,0x2a,0x00,0x3c,0x40,0x1e,0x1e,0x13,0x89,0x0a,0x21,0x00,0x00,0x2c,0x1d,0x89,0x40,0x21,0x00,0x1d,0x0e,0x20,0x1d,0x99,0x59,0x20,0x18,0x0a,0x0a,0x05,0x0e,0x05,0x9a,0x59,0x0e,0x07,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x01,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x32, 0x31,0x30,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x03,0x15,0x21,0x15,0x21,0x35,0x34,0x3e,0x02,0x37,0x3e,0x03,0x03,0x04,0x29,0x47,0x60,0x38,0x30,0x5c,0x57,0x51,0x23,0x45,0xab,0x7b,0x58,0x96,0x6e,0x3f,0x27,0x4f,0x78,0x51,0x65,0x83,0x4d,0x1f,0x02,0xca, 0xfc,0x8b,0x28,0x5c,0x95,0x6c,0x4e,0x69,0x40,0x1b,0x04,0x22,0x42,0x62,0x41,0x20,0x1a,0x2e,0x40,0x27,0xb0,0x43,0x47,0x33,0x62,0x90,0x5d,0x55,0x8a,0x7a,0x70,0x3a,0x48,0x66,0x59,0x59,0x3a,0x93,0x47,0x5c,0x8c,0x7e,0x7e,0x4f,0x38,0x66,0x66,0x69,0x00,0x01,0x00,0x7b,0xff,0xe7,0x03,0xb9,0x05,0xb2,0x00,0x29,0x00,0x72,0x40,0x41, 0x16,0x89,0x1a,0x13,0x24,0x03,0x08,0x22,0x22,0x08,0x00,0x89,0x40,0x0f,0x0f,0x2b,0x08,0x19,0x1a,0x01,0x0f,0x1a,0x01,0x0b,0x03,0x1a,0x1a,0x18,0x1d,0x18,0x9a,0x59,0x24,0x12,0x13,0x13,0x12,0x9a,0x59,0x13,0x13,0x0a,0x1d,0x07,0x36,0x08,0x01,0x00,0x08,0x10,0x08,0x20,0x08,0x03,0x09,0x03,0x08,0x08,0x0a,0x05,0x0a,0x9a,0x59,0x05, 0x19,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x5d,0x3f,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x5d,0x01,0x2f,0x12,0x39,0x2f,0x1a,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x10,0x21, 0x23,0x35,0x33,0x20,0x11,0x34,0x21,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x10,0x05,0x15,0x1e,0x03,0x03,0xb9,0x49,0x85,0xba,0x70,0xcd,0x79,0x91,0xbb,0x4b,0x79,0x57,0x2f,0xfe,0x70,0x77,0x71,0x01,0x62,0xfe,0xf2,0x98,0x85,0x89,0xbd,0x5a,0x92,0x68,0x39,0xfe,0xe2,0x49,0x7c,0x5a,0x33,0x01,0x96,0x61,0x9f,0x71,0x3e,0x4e, 0xb0,0x72,0x26,0x48,0x66,0x40,0x01,0x19,0x8b,0x01,0x08,0xf4,0x66,0x9f,0x52,0x32,0x5a,0x7e,0x4c,0xfe,0xe5,0x51,0x04,0x08,0x37,0x58,0x77,0x00,0x00,0x02,0x00,0x0e,0x00,0x00,0x04,0x0a,0x05,0x9a,0x00,0x0e,0x00,0x15,0x00,0x3e,0x40,0x1e,0x03,0x01,0x05,0x8a,0x06,0x40,0x10,0x0e,0x06,0x06,0x0f,0x17,0x08,0x04,0x08,0x0f,0x08,0x9a, 0x59,0x09,0x01,0x11,0x0e,0x0f,0x0f,0x06,0x0e,0x06,0x06,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0x33,0x33,0x2b,0x11,0x00,0x33,0x01,0x18,0x2f,0x12,0x39,0x39,0x11,0x33,0x33,0x1a,0x10,0xfd,0x32,0xc6,0x31,0x30,0x01,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x35,0x3e,0x03,0x37,0x01,0x21,0x11,0x0e,0x03,0x03,0x52,0xb8,0xb8, 0xa2,0xfd,0x5e,0x5e,0xc0,0xaf,0x95,0x33,0xfe,0x24,0x01,0xe9,0x4b,0x86,0x79,0x6e,0x05,0x9a,0xfc,0x4d,0x96,0xfe,0xaf,0x01,0x51,0x8e,0x6a,0xf1,0xf8,0xf7,0x71,0xfc,0x4d,0x02,0xbe,0x83,0xce,0xa8,0x88,0x00,0x00,0x01,0x00,0xa4,0xff,0xe7,0x03,0xc9,0x05,0x9a,0x00,0x23,0x00,0x52,0x40,0x2c,0x1c,0x8a,0x1a,0x17,0x17,0x08,0x00,0x89, 0x40,0x0f,0x0f,0x25,0x08,0x1f,0x12,0x9a,0x59,0x1f,0x1f,0x0a,0x18,0x18,0x1b,0x99,0x59,0x18,0x06,0x12,0x08,0x01,0x00,0x08,0x01,0x0b,0x03,0x08,0x08,0x0a,0x05,0x0a,0x9a,0x59,0x05,0x19,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x5d,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x01,0x18,0x2f,0x12,0x39,0x2f,0x1a, 0xed,0x11,0x39,0x2f,0x39,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x13,0x21,0x15,0x21,0x03,0x36,0x36,0x33,0x32,0x1e,0x02,0x03,0xc9,0x48,0x85,0xbc,0x73,0xc8,0x61,0x92,0x99,0x4e,0x7d,0x58,0x2f,0xbc,0xb3,0x1d,0x40,0x40,0x3d,0x19,0x31,0x02,0x97, 0xfd,0xf7,0x1d,0x20,0x48,0x1c,0x72,0xb4,0x7d,0x41,0x01,0xb6,0x69,0xaa,0x7a,0x42,0x3c,0xae,0x5e,0x2e,0x52,0x74,0x45,0x8c,0x9f,0x02,0x03,0x04,0x03,0x02,0xcf,0x94,0xfe,0x5b,0x02,0x03,0x3c,0x6f,0xa1,0x00,0x00,0x02,0x00,0x6f,0xff,0xe7,0x03,0xfe,0x05,0xb2,0x00,0x20,0x00,0x34,0x00,0x46,0x40,0x24,0x12,0x0a,0x00,0x89,0x21,0x21, 0x36,0x2b,0x19,0x89,0x40,0x0a,0x1c,0x26,0x9a,0x59,0x1a,0x1c,0x1c,0x30,0x0f,0x12,0x12,0x14,0x0f,0x14,0x9a,0x59,0x0f,0x07,0x05,0x30,0x9a,0x59,0x05,0x19,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x11,0x12,0x39,0x2f,0x39,0x2b,0x01,0x18,0x2f,0x1a,0xed,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x14, 0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xfe,0x44,0x78,0xa6,0x61,0x6c,0xab,0x77,0x3e,0x53,0x99,0xd8,0x85,0x94,0x5a,0x6f,0x7b,0x60,0x9a,0x6e, 0x3b,0x04,0x63,0xe4,0x5e,0x97,0x6b,0x3a,0xa8,0x26,0x47,0x68,0x42,0x3d,0x68,0x4c,0x2b,0x2a,0x4c,0x69,0x40,0x3e,0x66,0x48,0x28,0x01,0xc7,0x69,0xb0,0x80,0x47,0x5a,0xa9,0xf4,0x99,0xbb,0x01,0x31,0xd9,0x76,0x29,0x9b,0x39,0x56,0x9d,0xde,0x88,0xb3,0x40,0x75,0xa2,0x78,0x4b,0x78,0x54,0x2d,0x2e,0x4f,0x69,0x3b,0x4a,0x81,0x60,0x37, 0x2f,0x54,0x75,0x00,0x00,0x01,0x00,0x62,0x00,0x00,0x03,0xf2,0x05,0x9a,0x00,0x12,0x00,0x2d,0xb9,0x00,0x07,0x01,0x86,0x40,0x12,0x40,0x0f,0x08,0x08,0x00,0x10,0x00,0x00,0x10,0x11,0x11,0x10,0x99,0x59,0x11,0x06,0x08,0x18,0x00,0x3f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x01,0x18,0x2f,0x2f,0x12,0x39,0x2f,0x39,0x1a,0xed,0x31,0x30,0x01, 0x0e,0x03,0x02,0x02,0x07,0x23,0x36,0x12,0x12,0x3e,0x02,0x37,0x21,0x35,0x21,0x03,0xf2,0x21,0x5d,0x68,0x6c,0x5e,0x47,0x10,0xb0,0x12,0x4b,0x5f,0x6a,0x64,0x53,0x19,0xfd,0x31,0x03,0x90,0x05,0x3b,0x39,0xaa,0xd4,0xf4,0xfe,0xfc,0xfe,0xf5,0x81,0x80,0x01,0x0b,0x01,0x01,0xee,0xc8,0x99,0x2b,0x94,0x00,0x00,0x03,0x00,0x5a,0xff,0xe9, 0x03,0xfc,0x05,0xb2,0x00,0x23,0x00,0x37,0x00,0x4b,0x00,0x5b,0x40,0x2f,0x38,0x89,0x08,0x42,0x8a,0x12,0x05,0x15,0x12,0x08,0x12,0x08,0x12,0x00,0x1a,0x89,0x2e,0x2e,0x4d,0x24,0x89,0x40,0x00,0x15,0x05,0x33,0x3d,0x3d,0x33,0x9a,0x59,0x3d,0x3d,0x29,0x0d,0x1f,0x29,0x99,0x59,0x1f,0x19,0x0d,0x47,0x9a,0x59,0x0d,0x07,0x00,0x3f,0x2b, 0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x01,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02, 0x23,0x22,0x2e,0x02,0x37,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x5a,0x24,0x43,0x63,0x3f,0x5d,0x6e,0x3d,0x6c,0x94,0x56,0x57,0x94,0x6c,0x3c,0x6e,0x5b,0x3e,0x62,0x43,0x24,0x44,0x7b,0xab,0x67,0x66,0xaa,0x7c, 0x45,0xb2,0x29,0x4b,0x6b,0x41,0x3f,0x6a,0x4d,0x2b,0x29,0x4c,0x6a,0x42,0x3e,0x69,0x4d,0x2c,0x33,0x25,0x41,0x56,0x31,0x31,0x57,0x40,0x26,0x25,0x40,0x57,0x32,0x35,0x57,0x3f,0x22,0x01,0x90,0x39,0x73,0x64,0x52,0x18,0x34,0xa3,0x63,0x4f,0x86,0x62,0x37,0x38,0x62,0x86,0x4e,0x63,0xa3,0x34,0x18,0x52,0x64,0x73,0x39,0x5e,0x9c,0x6f, 0x3e,0x3e,0x6f,0x9c,0x6c,0x43,0x6c,0x4c,0x29,0x2a,0x4c,0x6c,0x42,0x3c,0x69,0x50,0x2e,0x2b,0x4d,0x6b,0x02,0x59,0x33,0x57,0x41,0x25,0x26,0x41,0x57,0x32,0x34,0x58,0x40,0x25,0x26,0x41,0x58,0x00,0x00,0x02,0x00,0x5e,0xff,0xe7,0x03,0xec,0x05,0xb2,0x00,0x20,0x00,0x34,0x00,0x46,0x40,0x24,0x21,0x00,0x89,0x08,0x17,0x10,0x10,0x36, 0x2b,0x89,0x40,0x17,0x12,0x30,0x99,0x59,0x0f,0x12,0x12,0x26,0x05,0x1c,0x26,0x9a,0x59,0x1c,0x07,0x08,0x08,0x0a,0x05,0x0a,0x9a,0x59,0x05,0x19,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x39,0x2b,0x01,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x31,0x30,0x01,0x14,0x02,0x06, 0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xec,0x4e,0x96,0xd8,0x8a,0x8e,0x6c,0x77,0x87,0x61,0x99,0x6a,0x38,0x04,0x5c,0xe4,0x5c,0x9a,0x70,0x3e,0x45,0x7b, 0xa9,0x64,0x6c,0xa7,0x72,0x3c,0xb1,0x2b,0x4c,0x69,0x3e,0x3b,0x66,0x4b,0x2b,0x29,0x4c,0x6b,0x41,0x39,0x65,0x4b,0x2b,0x03,0x23,0xc5,0xfe,0xcd,0xd5,0x6f,0x32,0x9d,0x43,0x50,0x99,0xe0,0x91,0xb9,0x41,0x77,0xa4,0x63,0x6a,0xb0,0x7f,0x46,0x57,0xa7,0xf4,0x0a,0x53,0x88,0x61,0x35,0x2f,0x55,0x75,0x45,0x4c,0x78,0x53,0x2c,0x2b,0x49, 0x63,0x00,0x00,0x02,0x00,0x70,0xff,0xea,0x01,0x50,0x04,0x16,0x00,0x0b,0x00,0x17,0x00,0x3c,0x40,0x16,0x06,0x00,0xb0,0x5b,0x06,0x10,0x0c,0x12,0xb0,0x5b,0x0c,0x13,0x09,0x03,0x15,0xaf,0x1f,0x0f,0x2f,0x0f,0x02,0x0f,0xb8,0xff,0xec,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xec,0xb6,0x0b,0x06,0x4d,0x0f,0x2f,0x19,0x01,0x5d,0x2f,0x2b, 0x2b,0x71,0xe1,0x39,0x39,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x03,0x38,0x42,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x42, 0xfc,0xb2,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x00,0x02,0x00,0x27,0xfe,0xf8,0x01,0x52,0x04,0x16,0x00,0x0b,0x00,0x0f,0x00,0x63,0x40,0x16,0x0f,0x0f,0x01,0x0f,0x0c,0x01,0x0c,0x05,0x06,0x00,0xb0,0x5b,0x06,0x10,0x0e,0x40,0x0f,0xb2,0x10,0x09,0xaf,0x03,0xb8,0xff,0xec,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xec,0x40,0x11,0x0b, 0x06,0x4d,0x03,0x0c,0x20,0x0c,0x06,0x4d,0x0c,0x28,0x0b,0x06,0x4d,0x0c,0x80,0x0e,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x0e,0xb8,0xff,0xea,0xb6,0x0b,0x06,0x4d,0x0e,0x2f,0x11,0x01,0x5d,0x2f,0x2b,0x2b,0x1a,0xcd,0x2b,0x2b,0x2f,0x2b,0x2b,0xe1,0x00,0x10,0xf6,0x1a,0xcd,0x3f,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5d,0x13,0x22,0x26, 0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x03,0x23,0x13,0xe2,0x2f,0x41,0x41,0x2f,0x2e,0x42,0x42,0x2c,0xa0,0x75,0x75,0x03,0x38,0x42,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x42,0xfd,0xac,0xfe,0x14,0x01,0xec,0x00,0x00,0x01,0x01,0x10,0x00,0x7f,0x04,0x6c,0x04,0x4c,0x00,0x07,0x00,0x43,0x40,0x0c,0x78,0x01,0x01,0x07,0x10,0x0b, 0x00,0x4d,0x02,0x01,0x00,0x00,0xb8,0xff,0xc0,0x40,0x0b,0x0c,0x00,0x4d,0x70,0x03,0x01,0x03,0x03,0x00,0x04,0x00,0xb8,0xff,0xe0,0xb5,0x0c,0x06,0x4d,0x00,0x05,0x01,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x01,0x2f,0x2b,0x33,0x2f,0x2b,0xc4,0x00,0x2f,0x33,0x2f,0x5d,0x2b,0x12,0x39,0x39,0x31,0x30,0x2b,0x5d,0x25,0x01,0x35,0x01,0x15, 0x01,0x15,0x01,0x04,0x6c,0xfc,0xa4,0x03,0x5c,0xfd,0x7e,0x02,0x82,0x7f,0x01,0xb0,0x3b,0x01,0xe2,0x96,0xfe,0x9c,0x04,0xfe,0xc6,0x00,0x00,0x02,0x00,0xe8,0x01,0x3e,0x04,0x94,0x03,0x6c,0x00,0x03,0x00,0x07,0x00,0x33,0x40,0x0f,0x06,0x05,0xbe,0x59,0x06,0x02,0x02,0x01,0xbe,0x59,0x02,0x01,0x00,0x05,0x04,0xb8,0xff,0xe0,0xb4,0x0c, 0x06,0x4d,0x04,0x05,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x05,0x2f,0x2b,0x2f,0x2b,0x12,0x39,0x39,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x04,0x94,0xfc,0x54,0x03,0xac,0xfc,0x54,0x03,0xac,0x02,0xe8,0x84,0xfd,0xd2,0x84,0x00,0x00,0x01,0x01,0x10,0x00,0x7f,0x04,0x6c,0x04,0x4c, 0x00,0x07,0x00,0x43,0x40,0x0c,0x78,0x00,0x01,0x02,0x10,0x0b,0x00,0x4d,0x07,0x00,0x01,0x01,0xb8,0xff,0xc0,0x40,0x0b,0x0c,0x00,0x4d,0x70,0x06,0x01,0x06,0x06,0x01,0x04,0x00,0xb8,0xff,0xe0,0xb5,0x0c,0x06,0x4d,0x00,0x05,0x02,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x02,0x2f,0x2b,0xc4,0x2f,0x2b,0x33,0x00,0x2f,0x33,0x2f,0x5d,0x2b, 0x12,0x39,0x39,0x31,0x30,0x2b,0x5d,0x01,0x01,0x35,0x01,0x35,0x01,0x35,0x01,0x04,0x6c,0xfc,0xa4,0x02,0x84,0xfd,0x7c,0x03,0x5c,0x02,0x2f,0xfe,0x50,0x95,0x01,0x38,0x06,0x01,0x64,0x96,0xfe,0x1e,0x00,0x02,0x00,0x83,0xff,0xee,0x03,0x31,0x05,0xb2,0x00,0x23,0x00,0x33,0x00,0x46,0x40,0x26,0x00,0x12,0x01,0x10,0x05,0x11,0x0f,0x14, 0x0f,0x95,0x59,0x14,0x04,0x00,0x2c,0x24,0x2c,0xb0,0x5b,0x24,0x13,0x20,0xef,0x03,0x30,0xaf,0x7f,0x28,0x01,0x28,0x28,0x11,0x19,0x84,0x0a,0x0a,0x35,0x11,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x5d,0xe1,0xd4,0xe1,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x31,0x30,0x5f,0x5e,0x5d,0x01,0x26,0x26,0x35, 0x34,0x3e,0x04,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x15,0x14,0x16,0x17,0x03,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07,0x06,0x01,0x4f,0x09,0x0e,0x33,0x4c,0x5a,0x4c,0x33,0x25,0x40,0x54,0x2f,0xa9,0x7c,0x99,0xa4,0x4c,0x86,0x65,0x3a,0x34,0x4f,0x5c, 0x4f,0x34,0x16,0x0b,0x47,0x2c,0x22,0x21,0x21,0x21,0x2d,0x2d,0x21,0x21,0x21,0x22,0x01,0x8e,0x1a,0x53,0x29,0x40,0x67,0x5a,0x53,0x55,0x5d,0x38,0x30,0x4a,0x32,0x19,0x85,0xb0,0x60,0x28,0x4f,0x76,0x4e,0x4a,0x74,0x61,0x54,0x53,0x5a,0x36,0x2e,0x4b,0x1a,0xfe,0x60,0x20,0x20,0x2e,0x2f,0x1f,0x21,0x21,0x1f,0x2f,0x2e,0x20,0x20,0x00, 0x00,0x02,0x00,0xac,0xff,0x44,0x06,0xfc,0x05,0xae,0x00,0x32,0x00,0x3d,0x00,0xb9,0x40,0x10,0x0a,0x27,0x01,0x0a,0x32,0x01,0x03,0x00,0x1b,0x01,0x0f,0x19,0x01,0x10,0x05,0x1e,0xb8,0xff,0xc0,0x40,0x0f,0x0b,0x0c,0x00,0x4c,0x1c,0x40,0x0b,0x00,0x4d,0x18,0x40,0x0c,0x00,0x4d,0x16,0xb8,0xff,0xc0,0x40,0x4b,0x0c,0x00,0x4d,0x04,0x18, 0x0b,0x00,0x4d,0x0d,0x00,0x03,0x09,0x09,0x33,0x4c,0x59,0x09,0x0f,0x31,0x14,0x03,0x39,0x03,0x39,0x4c,0x59,0x0f,0x03,0x0f,0x03,0x25,0x2b,0x2b,0x1a,0x4c,0x59,0x2b,0x04,0x00,0x22,0x10,0x22,0x02,0x0d,0x03,0x22,0x20,0x25,0x20,0x4c,0x59,0x25,0x00,0x0d,0x0f,0x10,0x12,0x05,0x3c,0x3c,0x2e,0x36,0x48,0x06,0x22,0x06,0x22,0x06,0x28, 0x17,0x48,0x2e,0x1d,0x48,0x28,0x2f,0xe1,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x12,0x39,0x2f,0x17,0x33,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x2f,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x10,0xc4,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x2b, 0x01,0x5f,0x5e,0x5d,0x5d,0x5f,0x5d,0x00,0x5d,0x01,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x33,0x32,0x16,0x17,0x33,0x36,0x37,0x33,0x02,0x15,0x14,0x33,0x32,0x36,0x35,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x37,0x15,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x14,0x02,0x23,0x22,0x03,0x22,0x06,0x15, 0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x04,0x8c,0x05,0x49,0xd6,0x89,0xa7,0xe7,0xbc,0x48,0x71,0x10,0x04,0x02,0x08,0x7d,0x2f,0x77,0x6c,0x8f,0xfe,0xa4,0xfe,0xcc,0xfe,0xd7,0xfe,0x7c,0x01,0x71,0x01,0x39,0xf7,0xaf,0xad,0xfe,0xfd,0xfe,0x94,0xfe,0x43,0x01,0xd3,0x01,0x6b,0x01,0x54,0x01,0xbe,0xeb,0xa9,0xdb,0xb4,0x7c,0x99,0x67,0x56, 0x7c,0x91,0x01,0xa4,0xee,0xca,0xab,0xe2,0x01,0x2b,0x4a,0x38,0x1c,0x57,0xfd,0xd9,0x0a,0xcf,0xea,0xba,0x01,0x13,0x01,0x5c,0xfe,0x60,0xfe,0xc8,0xfe,0xcd,0xfe,0x87,0x52,0x7c,0x4a,0x01,0xb7,0x01,0x63,0x01,0x6e,0x01,0xe2,0xfe,0x6c,0xfe,0xbb,0xee,0xfe,0xcf,0x03,0x0e,0xec,0xaf,0x76,0x88,0xf7,0xcc,0xd6,0x00,0x00,0x02,0x00,0x16, 0x00,0x00,0x05,0x12,0x05,0x9a,0x00,0x07,0x00,0x0f,0x00,0xd0,0x40,0x2c,0x07,0x07,0x01,0x08,0x06,0x01,0x09,0x10,0x0c,0x00,0x4d,0x02,0x08,0x09,0x0a,0x0b,0x01,0x0b,0x0d,0x0e,0x0f,0x03,0x04,0x0c,0x03,0x04,0x01,0x0c,0x01,0x01,0x10,0x03,0x01,0x10,0x0c,0x00,0x4d,0x04,0x18,0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe8,0xb4,0x0b,0x0d, 0x01,0x4c,0x0c,0xb8,0xff,0xc0,0xb4,0x0b,0x0d,0x01,0x4c,0x0b,0xb8,0xff,0xc0,0x40,0x39,0x0b,0x0d,0x01,0x4c,0x0e,0x0d,0x09,0x0a,0x04,0x05,0x0b,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x40,0x12,0x16,0x48,0x0c,0x06,0x40,0x08,0x0f,0x02,0x03,0x0f,0x03,0x91,0x59,0x0f,0x0f,0x06,0x03,0x01,0x05,0x08,0x0f,0x0c,0x0b,0x03,0x02,0x0e,0x09,0x0d, 0x0a,0x0a,0x05,0x77,0x05,0x01,0x78,0x00,0x01,0x05,0xb8,0xff,0xe8,0x40,0x0e,0x0b,0x0c,0x00,0x4c,0x00,0x18,0x0b,0x0c,0x00,0x4c,0x00,0x00,0x11,0x05,0x2f,0x11,0x33,0x2f,0x2b,0x2b,0x5d,0x5d,0x12,0x17,0x39,0x00,0x2f,0x2f,0x3f,0x39,0x2f,0x2b,0x00,0x10,0x18,0xc4,0x10,0xc4,0x1a,0x10,0xdd,0x2b,0x2b,0xc4,0x12,0x17,0x39,0x31,0x30, 0x2b,0x2b,0x01,0x2b,0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x87,0xc0,0xc0,0x0e,0xc0,0xc0,0x10,0x87,0x0e,0xc0,0xc0,0x05,0xc0,0xc0,0x01,0x2b,0x5d,0x5d,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x33,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x05,0x12,0xba,0x98,0xfd,0xa0,0x8f,0xbb,0x02,0x26,0xae,0x9f,0xe1,0x0b,0x0b,0x04,0x0a,0x0d,0xdf,0x01, 0x92,0xfe,0x6e,0x05,0x9a,0xfc,0x8f,0x02,0x63,0x1e,0x42,0x3d,0x23,0xfd,0x9d,0x00,0x00,0x03,0x00,0xbc,0x00,0x00,0x04,0x2f,0x05,0x9a,0x00,0x0f,0x00,0x17,0x00,0x1f,0x00,0xdc,0x40,0x0c,0x09,0x0d,0x01,0x06,0x0b,0x01,0x03,0x04,0x01,0x10,0x03,0x04,0xb8,0xff,0xe8,0x40,0x2e,0x0b,0x00,0x4d,0x08,0x18,0x11,0x11,0x18,0x91,0x59,0x11, 0x11,0x19,0x01,0x00,0x19,0x91,0x59,0x00,0x12,0x01,0x10,0x91,0x59,0x01,0x03,0x09,0x19,0x0c,0x06,0x0d,0x06,0x4d,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x7d,0x1d,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x1d,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x1d,0xb8,0xff,0xf0,0x40,0x2f,0x0b,0x06,0x4d,0x1d,0x1d,0x05,0x06,0x0c, 0x06,0x4d,0x05,0x7d,0x7f,0x15,0x01,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x15,0x21,0x11,0x19,0x08,0x0d,0x06,0x4d,0x19,0x08,0x0c,0x06,0x4d,0x19,0x08,0x0b,0x06,0x4d,0x19,0x7e,0x00,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xf6,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xf8,0x40,0x09,0x0b,0x06,0x4d,0x00, 0x21,0x40,0x0b,0x00,0x4d,0x2b,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe9,0x2b,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x11,0x39,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x01,0x2b,0x00,0x5f,0x5e,0x5d,0x5d,0x5d,0x33,0x11, 0x21,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x04,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0xbc,0x01,0x98,0xba,0xda,0x84,0x74,0x91,0xae,0xfe,0xf8,0xc9,0xfa,0xac,0x8a,0x9e,0xfe,0xed,0xc1,0xe4,0x94,0xa3,0xfe,0xa6,0x05,0x9a,0xb6,0x92,0x7a,0xb4,0x26,0x04,0x11,0xb9, 0x94,0xb8,0xe4,0x05,0x02,0xfe,0x31,0x85,0x79,0xd1,0xfd,0x9a,0xfd,0xfc,0x8c,0x7a,0xfe,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x00,0x15,0x00,0x99,0x40,0x0f,0x45,0x0a,0x01,0x49,0x00,0x01,0x4a,0x03,0x01,0x0f,0x17,0x01,0x0c,0x03,0x09,0xb8,0xff,0xc0,0x40,0x0c,0x0c,0x00,0x4d,0x03,0x18,0x0b,0x00,0x4d,0x0a,0x0b, 0x00,0x15,0xb8,0xff,0xc0,0x40,0x43,0x0b,0x00,0x4d,0x15,0x15,0x13,0x02,0x13,0x91,0x59,0x02,0x13,0x00,0x0b,0x01,0x0c,0x03,0x0b,0x0b,0x0d,0x08,0x0d,0x91,0x59,0x08,0x04,0x00,0x0b,0x30,0x0b,0x0d,0x01,0x4c,0x3f,0x0b,0x01,0x0b,0x0b,0x17,0x10,0x06,0x0d,0x06,0x4d,0x10,0x06,0x0c,0x06,0x4d,0x10,0x7d,0x05,0x10,0x0d,0x06,0x4d,0x05, 0x08,0x0c,0x06,0x4d,0x05,0x13,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x33,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x33,0x11,0x33,0x31,0x30,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x00,0x5d,0x5d,0x25,0x06,0x23,0x20,0x00,0x11,0x10, 0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x04,0x8c,0x9f,0xed,0xfe,0xce,0xfe,0x90,0x01,0x9e,0x01,0x3e,0xcc,0x86,0x9a,0xba,0xf7,0xfe,0xcd,0x01,0x1f,0xe9,0xd8,0x9e,0x3c,0x54,0x01,0x8a,0x01,0x40,0x01,0x58,0x01,0xa8,0x3b,0xb3,0x56,0xfe,0xb6,0xfe,0xec,0xfe,0xfa,0xfe,0xc9,0x60,0x00,0x00,0x02, 0x00,0xbc,0x00,0x00,0x05,0x3e,0x05,0x9a,0x00,0x07,0x00,0x0f,0x00,0x97,0x40,0x26,0x00,0x03,0x01,0x00,0x03,0x01,0x10,0x05,0x00,0x09,0x91,0x59,0x00,0x12,0x01,0x08,0x91,0x59,0x01,0x03,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x7d,0x0d,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x0d,0xb8,0xff, 0xf0,0xb3,0x0d,0x06,0x4d,0x0d,0xb8,0xff,0xf6,0xb3,0x0c,0x06,0x4d,0x0d,0xb8,0xff,0xea,0x40,0x18,0x0b,0x06,0x4d,0x0d,0x0d,0x11,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x7e,0x00,0xb8,0xff,0xf6,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xfe,0xb3,0x0b, 0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x33,0x11,0x21,0x20,0x11,0x10,0x00,0x21,0x03,0x11,0x33,0x20,0x00,0x11,0x10,0x21,0xbc,0x01,0x8c,0x02,0xf6,0xfe,0x5b,0xfe,0x9f,0xd4,0xd6, 0x01,0x1a,0x01,0x3a,0xfd,0xb6,0x05,0x9a,0xfd,0x45,0xfe,0xb4,0xfe,0x6d,0x05,0x02,0xfb,0x96,0x01,0x2e,0x01,0x15,0x02,0x27,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xb4,0x05,0x9a,0x00,0x0b,0x00,0x70,0x40,0x34,0x06,0x09,0x91,0x59,0x06,0x02,0x01,0x06,0x91,0x2b,0x30,0x06,0x0a,0x02,0x01,0x0a,0x91,0x59,0x01,0x12,0x02,0x05,0x91,0x59, 0x02,0x03,0x04,0x08,0x04,0x08,0x00,0x00,0x0d,0x06,0x0a,0x06,0x0d,0x06,0x4d,0x0a,0x06,0x0c,0x06,0x4d,0x0a,0x06,0x0b,0x06,0x4d,0x0a,0x7e,0x01,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xfa,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xfa,0xb3,0x0b,0x06,0x4d,0x01,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f, 0x33,0x33,0x2f,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x21,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x03,0xb4,0xfd,0x08,0x02,0xd8,0xfd,0xd0,0x02,0x06,0xfd,0xfa,0x02,0x50,0x05,0x9a,0x98,0xfe,0x23,0x97,0xfe,0x0a,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0x94, 0x05,0x9a,0x00,0x09,0x00,0x67,0x40,0x2c,0x02,0x05,0x91,0x59,0x0f,0x02,0x01,0x0b,0x03,0x02,0x02,0x08,0x07,0x12,0x08,0x01,0x91,0x59,0x08,0x03,0x04,0x04,0x00,0x00,0x0b,0x02,0x06,0x06,0x0d,0x06,0x4d,0x06,0x06,0x0c,0x06,0x4d,0x06,0x06,0x0b,0x06,0x4d,0x06,0x7e,0x07,0xb8,0xff,0xfb,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf6,0xb3, 0x0c,0x06,0x4d,0x07,0xb8,0xff,0xf6,0xb6,0x0b,0x06,0x4d,0x07,0x2f,0x0b,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x33,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x03,0x94,0xfd,0xd0,0x02,0x06,0xfd,0xfa,0xa8, 0x02,0xd8,0x05,0x02,0xfe,0x10,0x97,0xfd,0x85,0x05,0x9a,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0xec,0x05,0xb2,0x00,0x19,0x00,0xae,0x40,0x09,0x00,0x0a,0x01,0x0f,0x04,0x01,0x10,0x05,0x09,0xb8,0xff,0xc0,0x40,0x3b,0x0c,0x00,0x4d,0x18,0x17,0x91,0x59,0x18,0x18,0x08,0x00,0x15,0x13,0x02,0x13,0x91,0x59,0x02,0x13,0x0f,0x0b,0x1f, 0x0b,0x02,0x0a,0x03,0x0b,0x0b,0x0d,0x08,0x0d,0x91,0x59,0x08,0x04,0x17,0x17,0x15,0x10,0x0b,0x0b,0x00,0x04,0x0d,0x06,0x4d,0x00,0x04,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x7e,0x15,0xb8,0xff,0xee,0xb3,0x0c,0x06,0x4d,0x15,0xb8,0xff,0xee,0x40,0x22,0x0b,0x06,0x4d,0x15,0x15,0x1b,0x10,0x06,0x0d,0x06,0x4d,0x10,0x06,0x0c, 0x06,0x4d,0x10,0x7d,0x05,0x10,0x0c,0x06,0x4d,0x05,0x10,0x0d,0x06,0x4d,0x05,0x10,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x33,0x12,0x39,0x18,0x2f,0x2b, 0x31,0x30,0x00,0x2b,0x5f,0x5e,0x5d,0x5d,0x25,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x11,0x21,0x35,0x21,0x04,0xec,0xd8,0xfe,0xf8,0xfe,0xcd,0xfe,0x85,0x01,0xa5,0x01,0x43,0xea,0x9f,0xae,0xee,0xf1,0xfe,0xcc,0x01,0x1e,0xf5,0xa8,0x7b,0xfe,0xc6,0x01,0xe2,0x62, 0x7a,0x01,0x8c,0x01,0x46,0x01,0x4d,0x01,0xab,0x4c,0xba,0x6e,0xfe,0xb4,0xfe,0xf8,0xfe,0xf0,0xfe,0xc9,0x43,0x01,0x92,0x98,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xf2,0x05,0x9a,0x00,0x0b,0x00,0x79,0x40,0x48,0x08,0x03,0x91,0x59,0x08,0x06,0x05,0x08,0x91,0x2b,0x30,0x01,0x12,0x05,0x12,0x0a,0x03,0x06,0x03,0x09,0x00,0x06,0x0d,0x06, 0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x01,0x01,0x01,0x10,0x0d,0x06,0x4d,0x01,0x12,0x0c,0x06,0x4d,0x01,0x01,0x0d,0x08,0x04,0x06,0x0d,0x06,0x4d,0x04,0x06,0x0c,0x06,0x4d,0x04,0x06,0x0b,0x06,0x4d,0x04,0x7e,0x05,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x05, 0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x3f,0x3f,0x3f,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x04,0xf2,0xa8,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0xa8,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0x00, 0x00,0x01,0x00,0xbc,0x00,0x00,0x01,0x64,0x05,0x9a,0x00,0x03,0x00,0x10,0xb6,0x00,0x7e,0x01,0x01,0x12,0x02,0x03,0x00,0x3f,0x3f,0x01,0x2f,0xe1,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x64,0xa8,0xa8,0x05,0x9a,0x00,0x01,0x00,0x14,0xff,0xe8,0x02,0x2b,0x05,0x9a,0x00,0x0c,0x00,0x6d,0x40,0x17,0x00,0x09,0x01,0x00,0x01,0x01,0x0f,0x09, 0x01,0x10,0x05,0x06,0x06,0x08,0x03,0x08,0x91,0x59,0x03,0x13,0x0b,0x03,0x05,0xb8,0xff,0xf0,0x40,0x1c,0x0d,0x06,0x4d,0x05,0x05,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x0a,0x18,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xf6,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xfa,0xb6,0x0b,0x06,0x4d,0x0a, 0x0a,0x0e,0x0d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x2f,0x2b,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x5d,0x01,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x02,0x2b,0xd8,0xb5,0x54,0x36,0x36,0x56,0xe3,0xa8,0x02,0x02,0xff,0xfe,0xe5,0x18, 0xa6,0x27,0x01,0x81,0x03,0x9a,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x10,0x00,0x9c,0x40,0x1c,0x7d,0x0e,0x01,0x29,0x0e,0x39,0x0e,0x02,0x7e,0x01,0x01,0x2a,0x01,0x3a,0x01,0x02,0x10,0x18,0x0c,0x0d,0x01,0x4c,0x10,0x10,0x0b,0x01,0x4d,0x0e,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe8,0x40,0x18, 0x0b,0x0d,0x01,0x4c,0x0a,0x0e,0x10,0x01,0x05,0x05,0x08,0x07,0x12,0x08,0x03,0x0e,0x0f,0x0f,0x01,0x10,0x70,0x00,0x01,0x00,0xb8,0xff,0xe8,0x40,0x19,0x0d,0x06,0x4d,0x00,0x00,0x12,0x0a,0x05,0x06,0x0d,0x06,0x4d,0x05,0x06,0x0c,0x06,0x4d,0x05,0x06,0x0b,0x06,0x4d,0x05,0x7e,0x07,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff, 0xf8,0x40,0x09,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x11,0x33,0x2f,0x2b,0x5d,0x39,0x33,0x33,0x2f,0x33,0x00,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33, 0x01,0x04,0xa2,0xea,0xfd,0xd6,0x1f,0x07,0x04,0xa8,0xa8,0x04,0x0e,0x18,0x02,0x18,0xd1,0xfd,0x99,0x02,0x90,0x25,0x0d,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x16,0x1b,0x02,0x71,0xfd,0x50,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x00,0x05,0x00,0x86,0x40,0x09,0x01,0x04,0x91,0x59,0x01,0x12,0x02,0x03,0x05,0xb8,0xff,0xf0, 0xb3,0x10,0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb3,0x0b,0x06,0x4d,0x05,0xb8,0xff,0xe8,0xb3,0x0a,0x06,0x4d,0x05,0xb8,0xff,0xe0,0xb3,0x09,0x06,0x4d,0x05,0xb8,0xff,0xc0,0x40,0x18,0x0a,0x1f,0x48,0x05,0x05,0x07,0x04,0x06,0x0d,0x06,0x4d,0x04,0x06,0x0c, 0x06,0x4d,0x04,0x06,0x0b,0x06,0x4d,0x04,0x7e,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf2,0x40,0x09,0x0c,0x06,0x4d,0x01,0x05,0x0b,0x06,0x4d,0x01,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x2b,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x03,0xa4, 0xfd,0x18,0xa8,0x02,0x40,0x05,0x9a,0xfa,0xfe,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x06,0x72,0x05,0x9a,0x00,0x1b,0x00,0xba,0x40,0x15,0x7a,0x1a,0x01,0x75,0x13,0x01,0x26,0x13,0x36,0x13,0x02,0x72,0x16,0x01,0x16,0x18,0x0b,0x0d,0x01,0x4c,0x0d,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x05,0xb8,0xff,0xe8,0x40,0x37,0x0b,0x0d,0x01, 0x4c,0x16,0x1a,0x01,0x05,0x09,0x0d,0x06,0x12,0x11,0x12,0x12,0x03,0x04,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x1a,0x08,0x0d,0x06,0x4d,0x1a,0x7f,0x01,0x01,0x01,0x18,0x0d,0x06,0x4d,0x01,0x01,0x06,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xfa,0xb5,0x0b,0x06,0x4d,0x01,0x1d,0x13,0xb8,0xff, 0xf8,0x40,0x17,0x0d,0x06,0x4d,0x13,0x0d,0x10,0x06,0x0d,0x06,0x4d,0x10,0x06,0x0c,0x06,0x4d,0x10,0x06,0x0b,0x06,0x4d,0x10,0x7e,0x11,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x11,0xb8,0xff,0xf6,0xb3,0x0c,0x06,0x4d,0x11,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x32,0x2b,0x12,0x39,0x2b,0x2b,0x2f,0x2b,0x5d,0x33,0x2b,0xe9,0x2b,0x2b, 0x2b,0x39,0x00,0x3f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x2b,0x5d,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x06,0x72,0xa7,0x0e,0x04,0x18,0x13,0xfe,0x16,0x52,0xfe,0x17,0x15,0x16,0x04,0x08,0xa2,0xde, 0x01,0xb8,0x33,0x0f,0x06,0x2b,0x1a,0x01,0xc1,0xd2,0x03,0xc2,0x72,0xa5,0x61,0x2a,0xfb,0xb2,0x04,0x46,0x30,0x63,0x56,0xc3,0xfc,0x40,0x05,0x9a,0xfc,0x18,0x73,0x39,0x76,0x3a,0x03,0xe4,0x00,0x01,0x00,0xbc,0x00,0x00,0x05,0x40,0x05,0x9a,0x00,0x13,0x00,0xad,0x40,0x0d,0x77,0x0c,0x01,0x72,0x0b,0x01,0x78,0x02,0x01,0x7d,0x01,0x01, 0x0b,0xb8,0xff,0xf0,0x40,0x0a,0x0b,0x00,0x4d,0x0f,0x08,0x0b,0x0d,0x01,0x4c,0x05,0xb8,0xff,0xf8,0x40,0x2f,0x0b,0x0d,0x01,0x4c,0x0e,0x12,0x01,0x05,0x04,0x09,0x0a,0x03,0x09,0x01,0x0f,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x11,0x01,0x11,0x18,0x0d,0x06,0x4d,0x11,0x11,0x08, 0x0c,0x06,0x4d,0x11,0xb8,0xff,0xf8,0x40,0x19,0x0b,0x06,0x4d,0x11,0x15,0x0b,0x05,0x08,0x06,0x0d,0x06,0x4d,0x08,0x06,0x0c,0x06,0x4d,0x08,0x06,0x0b,0x06,0x4d,0x08,0x7e,0x09,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b, 0x39,0x32,0x12,0x39,0x2b,0x2b,0x2f,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x39,0x33,0x00,0x2f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x31,0x30,0x01,0x2b,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x26,0x35,0x11,0x33,0x05,0x40,0xce,0xfd,0x1e,0x1c,0x12,0x06,0x08,0xa8,0xda,0x02,0xce, 0x2d,0x0d,0x04,0x0a,0xa8,0x04,0x77,0x2b,0x2f,0x2e,0x97,0xfb,0xf4,0x05,0x9a,0xfb,0x9b,0x46,0x1a,0x3e,0x95,0x03,0xf2,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x17,0x00,0x81,0x40,0x1e,0x00,0x12,0x91,0x59,0x00,0x13,0x06,0x0c,0x91,0x59,0x06,0x04,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d, 0x09,0x06,0x0b,0x06,0x4d,0x09,0x7d,0x15,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x15,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x15,0xb8,0xff,0xea,0x40,0x2f,0x0b,0x06,0x4d,0x20,0x15,0x30,0x15,0x02,0x15,0x15,0x19,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x03,0x10,0x0d,0x06,0x4d,0x03,0x10, 0x0c,0x06,0x4d,0x03,0x10,0x0b,0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10, 0x00,0x02,0xfe,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0x8c,0xfe,0xd4,0xe2,0xfe,0xe6,0x01,0x13,0xdd,0xec,0x01,0x10,0xfe,0xf8,0x18,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0x05,0x32,0xfe,0xba,0xfe,0xf7,0xfe,0xf7,0xfe,0xbd,0x01,0x34,0x01,0x15,0x01,0x1c,0x01, 0x36,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x0a,0x00,0x12,0x00,0x90,0x40,0x29,0x46,0x06,0x01,0x02,0x0f,0x01,0x0c,0x04,0x0c,0x00,0x91,0x59,0x0c,0x0c,0x03,0x02,0x12,0x03,0x0b,0x91,0x59,0x03,0x03,0x07,0x08,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x7d,0x10,0xb8,0xff,0xe8, 0xb3,0x0d,0x06,0x4d,0x10,0xb8,0xff,0xe8,0x40,0x1e,0x0c,0x06,0x4d,0x10,0x10,0x0b,0x06,0x4d,0x10,0x10,0x14,0x0c,0x01,0x06,0x0d,0x06,0x4d,0x01,0x06,0x0c,0x06,0x4d,0x01,0x06,0x0b,0x06,0x4d,0x01,0x7e,0x02,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf4,0x40,0x09,0x0c,0x06,0x4d,0x02,0x04,0x0b,0x06,0x4d,0x02,0x2f,0x2b, 0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x12,0x39,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x01,0x11,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0xa8,0x01,0x8a,0xe6,0xfd,0xfe,0xe7,0xef,0xbd, 0xb0,0xae,0xb7,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x05,0x9a,0xe0,0xcc,0xcc,0xfe,0xfc,0x02,0xe4,0xfd,0xb4,0x9f,0x91,0x01,0x1c,0x00,0x02,0x00,0x5e,0xff,0x3f,0x06,0x25,0x05,0xb2,0x00,0x14,0x00,0x24,0x00,0x36,0x40,0x1a,0x13,0x10,0x04,0x11,0x0c,0x0c,0x21,0x19,0x04,0x13,0x10,0x00,0x08,0x08,0x15,0x91,0x59,0x08,0x04,0x00,0x1d,0x91, 0x59,0x12,0x00,0x13,0x00,0x3f,0xc6,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x01,0x18,0x2f,0x33,0x2f,0x33,0x10,0xc6,0x12,0x39,0x39,0x31,0x30,0x05,0x20,0x27,0x26,0x11,0x10,0x37,0x36,0x21,0x20,0x17,0x16,0x11,0x10,0x07,0x06,0x07,0x01,0x21,0x25,0x06,0x03,0x22,0x07,0x06,0x11,0x10,0x17,0x16,0x33,0x32,0x37,0x36,0x11, 0x10,0x27,0x26,0x02,0xfe,0xfe,0xd0,0xb9,0xb7,0xbb,0xbc,0x01,0x41,0x01,0x28,0xb6,0xb6,0xba,0x2c,0x32,0x01,0x93,0xfe,0xcf,0xfe,0xf2,0x6a,0x72,0xe2,0x8d,0x8d,0x89,0x8a,0xdd,0xec,0x88,0x88,0x84,0x84,0x18,0xc9,0xc9,0x01,0x42,0x01,0x5b,0xcd,0xce,0xc8,0xc8,0xfe,0xbd,0xfe,0xa1,0xcc,0x31,0x23,0xfe,0xdf,0xca,0x21,0x05,0x32,0xa3, 0xa3,0xfe,0xf7,0xfe,0xf8,0xa3,0xa1,0x9a,0x9a,0x01,0x15,0x01,0x1d,0x9a,0x9b,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0xc0,0x05,0x9a,0x00,0x1c,0x00,0x27,0x00,0xbb,0x40,0x3a,0x45,0x0f,0x01,0x03,0x40,0x0e,0x01,0x0f,0x02,0x01,0x0c,0x05,0x17,0x1e,0x08,0x08,0x1e,0x91,0x59,0x08,0x08,0x0a,0x1d,0x0b,0x1d,0x91,0x59,0x0b,0x03,0x01, 0x0a,0x17,0x09,0x11,0x08,0x0d,0x06,0x4d,0x11,0x08,0x0c,0x06,0x4d,0x11,0x08,0x0b,0x06,0x4d,0x24,0x7d,0x11,0x79,0x02,0x01,0x7a,0x01,0x01,0x02,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe8,0x40,0x26,0x0b,0x0d,0x01,0x4c,0x01,0x1c,0x02,0x11,0x04,0x70,0x00,0x01,0x00,0x08,0x0d,0x06,0x4d,0x00,0x29,0x1e,0x09,0x06, 0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x7e,0x0a,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xfa,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xfa,0xb3,0x0b,0x06,0x4d,0x0a,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x10,0xc6,0x2b,0x5d,0x17,0x32,0x2b,0x2b,0x5d,0x5d,0x2f,0xe1,0x2b,0x2b,0x2b, 0x12,0x39,0x00,0x2f,0x33,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x01,0x5d,0x5f,0x5d,0x21,0x23,0x03,0x2e,0x03,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x17,0x01,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x04,0xc0,0xc8,0xf0, 0x21,0x3e,0x41,0x4b,0x2f,0x8a,0xa8,0x01,0xac,0x5e,0x9f,0x75,0x42,0x2d,0x53,0x75,0x49,0x24,0x35,0x30,0x2f,0x1d,0xfd,0xb1,0xe4,0x3f,0x6b,0x4e,0x2c,0x95,0x8d,0x01,0x92,0x38,0x4f,0x32,0x17,0xfd,0x9e,0x05,0x9a,0x2f,0x60,0x8f,0x60,0x4b,0x7d,0x62,0x45,0x13,0x04,0x10,0x29,0x38,0x47,0x2f,0x03,0x53,0xfd,0xf8,0x26,0x47,0x67,0x40, 0x73,0x81,0x00,0x01,0x00,0x79,0xff,0xe8,0x03,0xde,0x05,0xb2,0x00,0x35,0x00,0xd2,0x40,0x15,0x4b,0x35,0x01,0x4a,0x2e,0x01,0x46,0x25,0x01,0x44,0x1a,0x01,0x46,0x15,0x01,0x34,0x18,0x0c,0x00,0x4d,0x2a,0xb8,0xff,0xe8,0xb3,0x0c,0x00,0x4d,0x28,0xb8,0xff,0xf0,0xb3,0x0c,0x00,0x4d,0x19,0xb8,0xff,0xe8,0x40,0x56,0x0c,0x00,0x4d,0x11, 0x18,0x0c,0x00,0x4d,0x09,0x2c,0x13,0x22,0x04,0x18,0x31,0x1a,0x00,0x01,0x00,0x1b,0x01,0x0c,0x03,0x1b,0x18,0x40,0x18,0x1d,0x91,0x59,0x18,0x04,0x00,0x01,0x01,0x0b,0x03,0x01,0x31,0x31,0x06,0x91,0x59,0x31,0x13,0x1b,0x1b,0x2c,0x22,0x08,0x0d,0x06,0x4d,0x22,0x08,0x0c,0x06,0x4d,0x22,0x08,0x0b,0x06,0x4d,0x22,0x7d,0x13,0x13,0x01, 0x2c,0x08,0x0d,0x06,0x4d,0x2c,0x08,0x0c,0x06,0x4d,0x2c,0x08,0x0b,0x06,0x4d,0x2c,0x7d,0x09,0xb8,0xff,0xf0,0x40,0x0f,0x0b,0x06,0x4d,0x20,0x09,0x01,0x09,0x09,0x37,0x01,0x08,0x0b,0x06,0x4d,0x01,0x2f,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18, 0x10,0xc4,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xcd,0x5f,0x5e,0x5d,0x11,0x33,0x32,0x11,0x12,0x17,0x39,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x37,0x35,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e, 0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x79,0x22,0x5f,0x69,0x6a,0x2d,0x9b,0x99,0x33,0x5a,0x7b,0x47,0x4b,0x82,0x60,0x37,0x56,0x8c,0xb3,0x5d,0xd4,0x61,0x7f,0xc7,0x37,0x6e,0x56,0x36,0x29,0x50,0x73,0x4b,0x4d,0x8a,0x68,0x3d,0x53,0x8d,0xb8,0x66,0x22,0x64,0x68,0x5d,0x3a,0xc6,0x1e,0x30,0x21,0x12,0x73,0x6c, 0x3a,0x56,0x47,0x41,0x24,0x26,0x4e,0x5e,0x77,0x50,0x62,0x91,0x5e,0x2e,0x33,0xbd,0x58,0x17,0x34,0x52,0x3b,0x37,0x50,0x42,0x3e,0x25,0x26,0x54,0x66,0x7c,0x50,0x6a,0x93,0x5c,0x29,0x0b,0x15,0x1f,0x00,0x01,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x00,0x07,0x00,0x7e,0x40,0x0b,0x03,0x12,0x01,0x05,0x06,0x05,0x91,0x59,0x06,0x03, 0x05,0xb8,0xff,0xfa,0xb3,0x0b,0x06,0x4d,0x00,0xb8,0xff,0xfa,0x40,0x28,0x0b,0x06,0x4d,0x00,0x05,0x00,0x0e,0x02,0x03,0x05,0x42,0xcf,0x05,0x01,0x05,0x05,0x08,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x7e,0x03,0x04,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf8,0x40,0x0d,0x0b,0x06,0x4d,0x03,0x03, 0x09,0x08,0x09,0x40,0x0c,0x00,0x4d,0x09,0xb8,0xff,0xc0,0xb2,0x0b,0x00,0x4d,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x01,0x10,0xe2,0x18,0x2f,0x2e,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x04,0x0c,0xfe,0x62,0xa8,0xfe, 0x63,0x03,0xe3,0x05,0x02,0xfa,0xfe,0x05,0x02,0x98,0x00,0x01,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x05,0x9a,0x00,0x0d,0x00,0x7a,0x40,0x31,0x02,0x0a,0x12,0x0a,0x02,0x02,0x08,0x12,0x08,0x02,0x0b,0x04,0x02,0x09,0x91,0x59,0x02,0x13,0x0c,0x03,0x05,0x03,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00, 0x7e,0x7f,0x0b,0x01,0x0b,0x0c,0x0d,0x06,0x4d,0x0b,0x0b,0xb8,0xff,0xfa,0x40,0x17,0x0c,0x06,0x4d,0x0b,0x0f,0x07,0x06,0x0d,0x06,0x4d,0x07,0x06,0x0c,0x06,0x4d,0x07,0x06,0x0b,0x06,0x4d,0x07,0x7e,0x04,0xb8,0xff,0xfe,0x40,0x09,0x0d,0x06,0x4d,0x04,0x04,0x0c,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2b,0x2f, 0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x3f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x01,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x04,0xd5,0xfd,0xdf,0xfd,0xf6,0xa8,0x01,0x74,0x01,0x67,0xa8,0x02,0x44,0xfd,0xa4,0x02,0x45,0x03,0x6d,0xfc,0x9e,0xfe,0x47,0x01,0xaa,0x03,0x71,0x00,0x01,0x00,0x12, 0x00,0x00,0x04,0xe6,0x05,0x9a,0x00,0x0b,0x00,0xc8,0x40,0x0a,0x7b,0x0b,0x01,0x74,0x04,0x01,0x78,0x02,0x01,0x0b,0xb8,0xff,0xd0,0xb3,0x0c,0x01,0x4d,0x0b,0xb8,0xff,0xe0,0xb3,0x0d,0x01,0x4d,0x0b,0xb8,0xff,0xe0,0x40,0x22,0x0b,0x01,0x4d,0x04,0x30,0x0c,0x01,0x4d,0x04,0x20,0x0d,0x01,0x4d,0x04,0x20,0x0b,0x01,0x4d,0x39,0x0b,0x01, 0x36,0x04,0x01,0x74,0x07,0x01,0x07,0x28,0x0b,0x0d,0x01,0x4c,0x07,0xb8,0xff,0xf0,0x40,0x19,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x0b,0x07,0x02,0x03,0x03,0x02,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xfc,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xfc,0x40,0x11,0x0b,0x06,0x4d,0x0b,0x28,0x00,0x01,0x00, 0x08,0x0c,0x0d,0x01,0x4c,0x00,0x00,0x0d,0x04,0xb8,0xff,0xf8,0x40,0x0f,0x0d,0x06,0x4d,0x04,0x04,0x0c,0x06,0x4d,0x04,0x04,0x0b,0x06,0x4d,0x04,0x03,0xb8,0xff,0xf8,0xb7,0x0c,0x0d,0x01,0x4c,0x27,0x03,0x01,0x03,0x2f,0x5d,0x2b,0x33,0x2b,0x2b,0x2b,0x11,0x33,0x2f,0x2b,0x5d,0x32,0x2b,0x2b,0x2b,0x00,0x2f,0x3f,0x12,0x39,0x39,0x2b, 0x2b,0x2b,0x2b,0x5d,0x31,0x30,0x01,0x5d,0x5d,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x01,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x04,0xe6,0xfd,0xed,0xb9,0xfd,0xf8,0xbb,0x01,0x8d,0x13,0x0a,0x04,0x08,0x19,0x01,0x95,0x05,0x9a,0xfa,0x66,0x05,0x9a,0xfb,0x8f,0x37,0x48,0x3c,0x45,0x04,0x6f,0x00,0x00,0x01, 0x00,0x1a,0x00,0x00,0x07,0x60,0x05,0x9a,0x00,0x1b,0x01,0x41,0x40,0x20,0x7b,0x1b,0x01,0x79,0x1a,0x01,0x76,0x14,0x01,0x76,0x0d,0x01,0x73,0x0c,0x01,0x75,0x09,0x01,0x7b,0x02,0x01,0x1b,0x20,0x0c,0x00,0x4d,0x1a,0x20,0x0c,0x00,0x4d,0x14,0xb8,0xff,0xe8,0x40,0x09,0x0b,0x00,0x4d,0x13,0x18,0x0b,0x00,0x4d,0x0d,0xb8,0xff,0xe0,0xb3, 0x0c,0x00,0x4d,0x0c,0xb8,0xff,0xe0,0x40,0x0a,0x0c,0x00,0x4d,0x0a,0x08,0x0b,0x0c,0x00,0x4c,0x09,0xb8,0xff,0xe8,0x40,0x0e,0x0b,0x00,0x4d,0x08,0x10,0x0b,0x00,0x4d,0x02,0x10,0x0b,0x00,0x4d,0x01,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x00,0x4d,0x00,0x10,0x0c,0x00,0x4d,0x1b,0xb8,0xff,0xd0,0xb3,0x0c,0x01,0x4d,0x1b,0xb8,0xff,0xe0,0xb3, 0x0d,0x01,0x4d,0x1b,0xb8,0xff,0xe8,0x40,0x13,0x0b,0x01,0x4d,0x0c,0x30,0x0c,0x01,0x4d,0x0c,0x20,0x0d,0x01,0x4d,0x0c,0x18,0x0b,0x01,0x4d,0x05,0xb8,0xff,0xc8,0x40,0x22,0x0b,0x0d,0x01,0x4c,0x17,0x38,0x0b,0x0d,0x01,0x4c,0x0f,0x38,0x0b,0x0d,0x01,0x4c,0x17,0x40,0x0b,0x0c,0x00,0x4c,0x0f,0x40,0x0b,0x0c,0x00,0x4c,0x05,0x10,0x0d, 0x06,0x4d,0x17,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0f,0xb8,0xff,0xf0,0x40,0x1d,0x0d,0x06,0x4d,0x00,0x01,0x05,0x0f,0x13,0x17,0x06,0x0a,0x0b,0x03,0x0a,0x14,0x13,0x06,0x01,0x02,0x17,0x09,0x0a,0x0f,0x17,0x20,0x0b,0x00,0x4d,0x0f,0xb8,0xff,0xe0,0xb3,0x0b,0x00,0x4d,0x17,0xb8,0xff,0xe0,0x40,0x14,0x0c,0x00,0x4d,0x0f,0x20,0x0c, 0x00,0x4d,0x0f,0x06,0x17,0x03,0x0b,0x00,0x00,0x1d,0x0b,0x2f,0x1d,0x01,0x5d,0x2f,0x11,0x33,0x2f,0x12,0x17,0x39,0x2b,0x2b,0x2b,0x2b,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x00,0x2f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x01,0x23,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x07,0x60,0xfe,0x6b,0xc5,0xfe,0xd9,0x13,0x04,0x04,0x06,0x14,0xfe,0xd7,0xc3,0xfe,0x5c,0xb9,0x01,0x31,0x13,0x05,0x05, 0x05,0x1a,0x01,0x3d,0xa1,0x01,0x30,0x10,0x08,0x04,0x04,0x17,0x01,0x25,0x05,0x9a,0xfa,0x66,0x04,0x18,0x43,0x4f,0x4a,0x46,0xfb,0xe6,0x05,0x9a,0xfb,0xb4,0x45,0x4b,0x35,0x5b,0x04,0x4c,0xfb,0xac,0x39,0x4d,0x34,0x56,0x04,0x50,0x00,0x01,0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x00,0x15,0x00,0xc0,0x40,0x19,0x7b,0x13,0x01,0x7a, 0x12,0x01,0x75,0x0d,0x01,0x74,0x0c,0x01,0x74,0x08,0x01,0x75,0x07,0x01,0x79,0x02,0x01,0x7b,0x01,0x01,0x13,0xb8,0xff,0xe0,0x40,0x11,0x0b,0x0d,0x01,0x4c,0x0c,0x20,0x0b,0x0d,0x01,0x4c,0x08,0x20,0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe0,0x40,0x0a,0x0b,0x0d,0x01,0x4c,0x13,0x08,0x0c,0x00,0x4d,0x0c,0xb8,0xff,0xf8,0x40,0x09,0x0c, 0x00,0x4d,0x0a,0x10,0x0b,0x00,0x4d,0x08,0xb8,0xff,0xf8,0x40,0x0f,0x0c,0x00,0x4d,0x01,0x08,0x0c,0x00,0x4d,0x0f,0x18,0x0b,0x0d,0x01,0x4c,0x05,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x0f,0xb8,0xff,0xf0,0x40,0x1f,0x0d,0x06,0x4d,0x05,0x10,0x0d,0x06,0x4d,0x01,0x05,0x0f,0x13,0x04,0x09,0x0b,0x03,0x09,0x15,0x0a,0x0b,0x14,0x00, 0x10,0x0b,0x00,0x4d,0x00,0x00,0x17,0x0b,0x09,0xb8,0xff,0xf0,0xb3,0x0b,0x00,0x4d,0x09,0x2f,0x2b,0xc6,0x11,0x33,0x2f,0x2b,0xc6,0x11,0x39,0x39,0x00,0x2f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x2b,0x2b,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x26,0x27,0x23, 0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x04,0x9a,0xcd,0xfe,0xb6,0x0f,0x12,0x04,0x0a,0x18,0xfe,0xac,0xce,0x01,0xe0,0xfe,0x46,0xce,0x01,0x25,0x1d,0x16,0x04,0x20,0x18,0x01,0x31,0xc1,0xfe,0x3d,0x02,0x25,0x19,0x2e,0x17,0x30,0xfd,0xdb,0x02,0xd1,0x02,0xc9,0xfe,0x08,0x32,0x32,0x42,0x26, 0x01,0xf4,0xfd,0x39,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x00,0x0d,0x00,0x65,0x40,0x21,0x73,0x06,0x01,0x04,0x09,0x01,0x01,0x05,0x03,0x12,0x0d,0x03,0x05,0x03,0x09,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06,0x4d,0x02,0x7e,0x03,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xfe, 0x40,0x16,0x0b,0x06,0x4d,0x03,0x03,0x05,0x0d,0x7d,0x00,0x00,0x0f,0x06,0x18,0x0b,0x0d,0x01,0x4c,0x06,0x05,0x20,0x0f,0x01,0x5d,0x2f,0x33,0x2b,0x11,0x33,0x2f,0xe9,0x11,0x39,0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x39,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0xcd,0x33,0x31,0x30,0x01,0x5d,0x01,0x01,0x11,0x23,0x11,0x01,0x33,0x01,0x16, 0x17,0x33,0x36,0x37,0x01,0x04,0x60,0xfe,0x27,0xa8,0xfe,0x33,0xbf,0x01,0x41,0x06,0x1d,0x03,0x0a,0x1c,0x01,0x50,0x05,0x9a,0xfc,0x78,0xfd,0xee,0x02,0x0e,0x03,0x8c,0xfd,0x78,0x0c,0x4c,0x22,0x36,0x02,0x88,0x00,0x01,0x00,0x21,0x00,0x00,0x04,0x64,0x05,0x9a,0x00,0x09,0x00,0xa6,0x40,0x0e,0x0c,0x06,0x01,0x04,0x01,0x01,0x10,0x01, 0x20,0x0b,0x0d,0x01,0x4c,0x06,0xb8,0xff,0xe0,0x40,0x31,0x0b,0x0d,0x01,0x4c,0x35,0x00,0x45,0x00,0x02,0x03,0x00,0x13,0x00,0x23,0x00,0x03,0x3a,0x05,0x4a,0x05,0x02,0x0c,0x05,0x1c,0x05,0x2c,0x05,0x03,0x17,0x03,0x05,0x01,0x04,0x04,0x01,0x91,0x59,0x04,0x12,0x00,0x08,0x07,0x08,0x07,0x91,0x59,0x08,0x03,0x06,0xb8,0xff,0xf8,0x40, 0x09,0x0d,0x06,0x4d,0x01,0x08,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x09,0x0c,0x06,0x4d,0x01,0x0c,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x14,0x0b,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x03,0x07,0x07,0x01,0x06,0x03,0x04,0x04,0x00,0x00,0x0b,0x04,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d,0x01,0x2b,0x2b,0x5e,0x5d,0x5d,0x01,0x01,0x21,0x15,0x21,0x35,0x01,0x21,0x35,0x21,0x04,0x64,0xfc,0xb8,0x03,0x34,0xfb,0xd1,0x03,0x41,0xfd,0x02,0x04,0x00,0x05,0x72,0xfb,0x26,0x98,0x2f,0x04,0xd3,0x98,0x00,0x00,0x01, 0x00,0xc8,0xfe,0xba,0x02,0x38,0x05,0x9a,0x00,0x07,0x00,0x39,0x40,0x11,0x02,0x05,0xd9,0x59,0x02,0x03,0x01,0x06,0xd9,0x59,0x01,0x20,0x04,0x00,0x06,0xea,0x01,0xb8,0xff,0xec,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xe8,0x40,0x09,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x2f,0x2b,0x2b,0x2b,0xe1,0xdd,0xc4,0x00,0x3f,0x2b,0x00, 0x18,0x3f,0x2b,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x23,0x11,0x33,0x02,0x38,0xfe,0x90,0x01,0x70,0xde,0xde,0xfe,0xba,0x06,0xe0,0x77,0xfa,0x0e,0x00,0x01,0xff,0xe6,0xff,0x10,0x03,0x1e,0x05,0x9a,0x00,0x03,0x00,0x19,0x40,0x0d,0x78,0x01,0x01,0x00,0x08,0x0b,0x00,0x4d,0x00,0x02,0x03,0x00,0x02,0x2f,0x2f,0x00,0x3f,0x2f,0x31,0x30, 0x01,0x2b,0x5d,0x05,0x23,0x01,0x33,0x03,0x1e,0x97,0xfd,0x5f,0x9b,0xf0,0x06,0x8a,0x00,0x01,0x00,0x35,0xfe,0xba,0x01,0xa4,0x05,0x9a,0x00,0x07,0x00,0x35,0x40,0x1b,0x06,0x05,0xd9,0x59,0x06,0x03,0x01,0x02,0xd9,0x59,0x01,0x20,0x05,0x01,0x00,0xea,0x03,0x08,0x0d,0x06,0x4d,0x03,0x08,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xee,0xb3,0x0b, 0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0xdd,0xc4,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x01,0x21,0x35,0x33,0x11,0x23,0x35,0x21,0x01,0xa4,0xfe,0x91,0xdd,0xdd,0x01,0x6f,0xfe,0xba,0x77,0x05,0xf2,0x77,0x00,0x00,0x01,0x00,0xe6,0x02,0x70,0x04,0x96,0x05,0xb2,0x00,0x07,0x00,0x26,0x40,0x16,0x79,0x06,0x01,0x79,0x01,0x01, 0x07,0x10,0x0b,0x0c,0x00,0x4c,0x00,0x05,0x03,0x07,0x04,0x2f,0x00,0x01,0x00,0x05,0x2f,0x2f,0x5d,0x00,0x3f,0x33,0x2f,0xc4,0x31,0x30,0x01,0x2b,0x5d,0x5d,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x33,0x04,0x96,0x96,0xfe,0xb4,0x06,0xfe,0xcb,0x93,0x01,0xa6,0x41,0x02,0x70,0x02,0x6b,0xfd,0x95,0x03,0x42,0x00,0x01,0x00,0x00,0xfe,0xd7, 0x03,0x52,0xff,0x4e,0x00,0x03,0x00,0x0f,0xb6,0x01,0x02,0xd9,0x59,0x01,0x00,0x01,0x2f,0x2f,0x00,0x2f,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x52,0xfc,0xae,0x03,0x52,0xfe,0xd7,0x77,0x00,0x01,0x00,0x52,0x04,0xc2,0x01,0xd7,0x06,0x0a,0x00,0x03,0x00,0x1c,0xb7,0x77,0x03,0x01,0x03,0x80,0x01,0x00,0x02,0xb8,0xff,0xc0,0xb3,0x0d, 0x10,0x48,0x02,0x2f,0x2b,0xcd,0x00,0x2f,0x1a,0xcd,0x31,0x30,0x01,0x5d,0x01,0x23,0x01,0x33,0x01,0xd7,0x7f,0xfe,0xfa,0xa8,0x04,0xc2,0x01,0x48,0x00,0x02,0x00,0x5a,0xff,0xe8,0x03,0x83,0x04,0x18,0x00,0x14,0x00,0x1f,0x00,0xaa,0x40,0x52,0x06,0x10,0x01,0x00,0x09,0x01,0x10,0x04,0x06,0x18,0x0b,0x0c,0x00,0x4c,0x0b,0x15,0x96,0x59, 0x0b,0x10,0x0d,0x06,0x4d,0x0b,0x0b,0x1c,0x12,0x01,0x15,0x03,0x1c,0x05,0x1c,0x95,0x59,0x05,0x16,0x0f,0x40,0x09,0x0c,0x48,0x0f,0x0f,0x0d,0x12,0x0d,0x95,0x59,0x12,0x10,0x20,0x0f,0x30,0x0f,0x02,0x0f,0x0b,0x1f,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0x02,0x0d,0x06,0x4d,0x01, 0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xee,0x40,0x17,0x0b,0x06,0x4d,0x01,0x01,0x21,0x0f,0x19,0x83,0x08,0x0c,0x0c,0x06,0x4d,0x08,0x04,0x0b,0x06,0x4d,0x2f,0x08,0x01,0x08,0x2f,0x5d,0x2b,0x2b,0xe9,0x33,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x33,0x2f,0x5d,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f, 0x2b,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x31,0x30,0x00,0x2b,0x5f,0x5e,0x5d,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x07,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x03,0x83,0xa4,0x04,0x6b,0xd0,0x99,0xad,0x01,0x52, 0x01,0x33,0xd3,0xb9,0x95,0x97,0xc5,0x01,0x69,0xa4,0xf7,0x72,0x74,0x6b,0x59,0x7a,0x9f,0xa0,0xb8,0xa2,0x86,0x01,0x1f,0x2f,0x2b,0x01,0x05,0x7e,0xa8,0x60,0xfe,0x82,0x94,0x22,0x10,0x51,0x67,0x4b,0x5f,0xab,0x83,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x54,0x05,0xec,0x00,0x10,0x00,0x1d,0x00,0x9c,0x40,0x2b,0x00,0x0a,0x01,0x10, 0x06,0x03,0x15,0x01,0x15,0x0f,0x15,0x95,0x59,0x0f,0x16,0x07,0x1b,0x09,0x1b,0x95,0x59,0x09,0x10,0x04,0x00,0x0c,0x06,0x0d,0x06,0x4d,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x83,0x18,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x18,0xb8,0xff,0xf2,0xb3,0x0c,0x06,0x4d,0x18,0xb8,0xff,0xe3,0x40,0x1a,0x0b,0x06,0x4d,0x18, 0x18,0x1f,0x06,0x02,0x12,0x06,0x0d,0x06,0x4d,0x12,0x06,0x0c,0x06,0x4d,0x12,0x06,0x0b,0x06,0x4d,0x12,0x84,0x03,0xb8,0xff,0xf8,0x40,0x11,0x0d,0x06,0x4d,0x03,0x02,0x0c,0x06,0x4d,0x03,0x01,0x0b,0x06,0x4d,0x03,0x2f,0x1f,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b, 0x2b,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x25,0x23,0x15,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4e,0x04,0xa4,0xa4,0x04,0x79,0xe9,0xc5,0xdf,0xfa,0xd9, 0xcb,0x6c,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0x94,0x94,0x05,0xec,0xfd,0x60,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x02,0x49,0x8f,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0xc7,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x00,0x15,0x00,0x85,0x40,0x5b,0x58,0x03,0x01,0x09,0x0f,0x19,0x0f,0x02,0x0b,0x00,0x15,0x01,0x0c,0x03, 0x15,0x15,0x13,0x02,0x13,0x95,0x59,0x02,0x16,0x0b,0x0b,0x0d,0x08,0x0d,0x95,0x59,0x08,0x10,0x00,0x20,0x0c,0x01,0x4d,0x00,0x00,0x0b,0x0c,0x0c,0x06,0x4d,0x0b,0x02,0x0b,0x06,0x4d,0x70,0x0b,0x01,0x0b,0x20,0x0c,0x01,0x4d,0x0b,0x10,0x06,0x0d,0x06,0x4d,0x10,0x06,0x0c,0x06,0x4d,0x10,0x06,0x0b,0x06,0x4d,0x10,0x83,0x05,0x14,0x0d, 0x06,0x4d,0x05,0x0c,0x0c,0x06,0x4d,0x05,0x23,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x2f,0x2b,0x5d,0x2b,0x2b,0x33,0x2f,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x31,0x30,0x5e,0x5d,0x01,0x5d,0x25,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17, 0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x03,0x60,0x76,0xa2,0xdb,0xfe,0xf3,0x01,0x22,0xf2,0x87,0x67,0x72,0x82,0x9d,0xc9,0xbd,0x9f,0x86,0x76,0x2f,0x47,0x01,0x1d,0xe3,0xfd,0x01,0x33,0x32,0xa8,0x50,0xe1,0xb7,0xb4,0xd0,0x59,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x10,0x05,0xec,0x00,0x10,0x00,0x1d,0x00,0x9b, 0x40,0x38,0x0f,0x06,0x01,0x10,0x06,0x1c,0x18,0x0b,0x0c,0x00,0x4c,0x02,0x1b,0x05,0x1b,0x95,0x59,0x05,0x16,0x01,0x15,0x0e,0x15,0x0b,0x15,0x95,0x59,0x0b,0x10,0x0f,0x00,0x11,0x0d,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0x05,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06, 0x4d,0x01,0xb8,0xff,0xf0,0x40,0x2a,0x0b,0x06,0x4d,0x01,0x01,0x1f,0x18,0x06,0x0d,0x06,0x4d,0x18,0x06,0x0c,0x06,0x4d,0x18,0x06,0x0b,0x06,0x4d,0x18,0x83,0x08,0x10,0x0d,0x06,0x4d,0x08,0x0e,0x0c,0x06,0x4d,0x08,0x1a,0x0b,0x06,0x4d,0x08,0x2f,0x1f,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b, 0xe9,0x2b,0x2b,0x2b,0x33,0x33,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0xa4,0x04,0x72,0xee,0xc1, 0xe7,0x01,0x00,0xd5,0xd3,0x60,0x04,0xa4,0xa4,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0xab,0xae,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x02,0x7a,0xfb,0xe3,0x97,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0xc6,0x00,0x02,0x00,0x60,0xff,0xe8,0x03,0xdd,0x04,0x18,0x00,0x12,0x00,0x19,0x00,0xaf,0xb5,0x0f,0x07,0x01,0x10,0x06,0x06,0xb8,0xff,0xc0, 0x40,0x2d,0x0b,0x0e,0x48,0x06,0x06,0x01,0x04,0x19,0x01,0x95,0x59,0x19,0x19,0x04,0x0f,0x09,0x04,0x95,0x59,0x09,0x16,0x0f,0x16,0x95,0x59,0x0f,0x10,0x7f,0x07,0x01,0x07,0x16,0x0c,0x06,0x4d,0x07,0x20,0x0c,0x01,0x4d,0x07,0x07,0x00,0x83,0x13,0xb8,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x13,0xb8,0xff,0xd0,0xb3,0x0c,0x01,0x4d,0x13, 0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x13,0xb8,0xff,0xe8,0x40,0x28,0x0b,0x06,0x4d,0x13,0x13,0x1b,0x19,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x83,0x0c,0x10,0x0d,0x06,0x4d,0x0c,0x10,0x0c,0x06,0x4d,0x0c,0x1d,0x0b,0x06,0x4d,0x0c,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39, 0x2f,0x2b,0x2b,0x2b,0x2b,0xe9,0x32,0x2f,0x2b,0x2b,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x31,0x30,0x5f,0x5e,0x5d,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x12,0x15,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x03, 0xdd,0xfd,0x2d,0x04,0xb0,0x9a,0xad,0x91,0x87,0xde,0xd9,0xf8,0x01,0x0f,0xc9,0xc9,0xdc,0xa8,0x01,0x87,0x78,0x74,0xa2,0x13,0x01,0xd7,0xab,0xba,0x72,0x9a,0x62,0x01,0x17,0xfd,0xef,0x01,0x2d,0xfe,0xfc,0xe7,0x35,0x8e,0x9e,0xa6,0x86,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x02,0xa0,0x06,0x02,0x00,0x14,0x00,0x8a,0xb9,0x00,0x10,0xff, 0xc0,0x40,0x3a,0x0b,0x00,0x4d,0x0a,0x15,0x00,0x00,0x02,0x08,0x0c,0x05,0x0d,0x0d,0x0c,0x95,0x59,0x0d,0x0f,0x12,0x02,0x95,0x59,0x12,0x01,0x07,0x07,0x00,0x0c,0x0c,0x06,0x4d,0x2f,0x00,0x01,0x00,0x0c,0x00,0x0c,0x05,0x0e,0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x84,0x0a,0xb8,0xff,0xe8, 0xb3,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xe6,0x40,0x0a,0x0b,0x06,0x4d,0x0a,0x0a,0x16,0x15,0x2f,0x16,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x32,0x33,0x33,0x2f,0x2f,0x5d,0x2b,0x33,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x11,0x33,0x12,0x39, 0x18,0x2f,0x3f,0x31,0x30,0x2b,0x01,0x26,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x02,0xa0,0x30,0x3d,0xac,0xf0,0xf0,0xa3,0xaf,0xaf,0xba,0x8b,0x4b,0x2c,0x05,0x5c,0x1b,0xd9,0x9e,0x8c,0xfc,0x8c,0x03,0x74,0x8c,0xa6,0xa1,0xbb,0x12,0x00,0x02,0x00,0x60,0xfe,0x1e,0x04,0x10, 0x04,0x18,0x00,0x18,0x00,0x25,0x00,0xca,0x40,0x10,0x0a,0x04,0x01,0x03,0x0f,0x0e,0x01,0x10,0x06,0x24,0x18,0x0b,0x0c,0x00,0x4c,0x08,0xb8,0xff,0xe0,0xb4,0x0b,0x0c,0x00,0x4c,0x05,0xb8,0xff,0xc0,0x40,0x3a,0x0b,0x0f,0x48,0x05,0x05,0x07,0x02,0x07,0x95,0x59,0x02,0x1c,0x0a,0x23,0x0d,0x23,0x95,0x59,0x0d,0x16,0x17,0x0f,0x15,0x1d, 0x13,0x1d,0x95,0x59,0x13,0x10,0x04,0x15,0x19,0x16,0x03,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x09,0x05,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xf0,0x40,0x2b,0x0b,0x06,0x4d,0x09,0x09,0x27,0x04,0x20,0x06,0x0d,0x06,0x4d,0x20,0x06,0x0c,0x06,0x4d, 0x20,0x06,0x0b,0x06,0x4d,0x20,0x83,0x10,0x10,0x0d,0x06,0x4d,0x10,0x0e,0x0c,0x06,0x4d,0x10,0x1a,0x0b,0x06,0x4d,0x10,0x2f,0x27,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x17,0x33,0x2f,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f, 0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x31,0x30,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x00,0x5f,0x5d,0x25,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x20,0x11,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x12,0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0xfd,0xe4,0xbe,0x8e,0xad,0x9d, 0x01,0x7a,0x04,0x75,0xeb,0xbf,0xe9,0xfb,0xda,0xcf,0x64,0x04,0xa4,0xa4,0xa5,0x7b,0x98,0xac,0xa5,0x88,0x8a,0xad,0x52,0xfd,0xcc,0x48,0xa4,0x60,0x01,0x92,0x70,0xc4,0x01,0x11,0xe6,0x01,0x05,0x01,0x34,0xa6,0x8e,0xfd,0xcf,0x97,0x7a,0xae,0xdd,0xc7,0xab,0xcd,0xc4,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x11, 0x00,0x96,0x40,0x28,0x02,0x10,0x01,0x02,0x10,0x01,0x10,0x04,0x01,0x15,0x09,0x15,0x0c,0x04,0x0f,0x04,0x95,0x59,0x0f,0x10,0x0a,0x00,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40, 0x1e,0x0b,0x06,0x4d,0x01,0x01,0x13,0x0c,0x08,0x06,0x0d,0x06,0x4d,0x08,0x06,0x0c,0x06,0x4d,0x08,0x06,0x0b,0x06,0x4d,0x08,0x84,0x09,0x02,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x13,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b, 0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xa4,0xee,0x78,0xa4,0xa4,0xa4,0x04,0x76,0xda,0x01,0x5a,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfd,0xbc,0x05, 0xec,0xfd,0x6a,0xc2,0xfe,0x5f,0x00,0x02,0x00,0x90,0x00,0x00,0x01,0x66,0x05,0xd9,0x00,0x0b,0x00,0x0f,0x00,0x4e,0x40,0x23,0x00,0x06,0x63,0x5b,0x00,0x0e,0x0f,0x0d,0x09,0x62,0x03,0x0d,0x0c,0x03,0x62,0xff,0x30,0x0c,0x06,0x0d,0x06,0x4d,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x84,0x0d,0xb8,0xff,0xfe,0xb3,0x0c, 0x06,0x4d,0x0d,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x0d,0x0d,0x11,0x10,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xe1,0x00,0x18,0x2f,0x3f,0xc6,0x2b,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x23,0x11,0x33,0xfa,0x2c,0x3e,0x3e,0x2c,0x2d,0x3f,0x3f,0x23,0xa4,0xa4,0x05, 0x04,0x3c,0x2e,0x2e,0x3d,0x3d,0x2e,0x2c,0x3e,0xfa,0xfc,0x04,0x00,0x00,0x00,0x02,0xff,0x3a,0xfe,0x1e,0x01,0x66,0x05,0xd9,0x00,0x0c,0x00,0x18,0x00,0x6b,0x40,0x34,0x02,0x02,0x01,0x10,0x04,0x0d,0x13,0x63,0x5b,0x0d,0x0b,0x0f,0x06,0x06,0x08,0x03,0x08,0x95,0x59,0x03,0x1c,0x16,0x62,0x10,0x0a,0x00,0x10,0x62,0xff,0x30,0x06,0x00, 0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x0a,0x01,0x0a,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x0a,0x0a,0x1a,0x19,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0xc6,0x2b,0x01,0x10,0xe1,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f, 0x3f,0xc6,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x25,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x4a,0xcb,0xbd,0x46,0x42,0x4a,0x42,0xe0,0xa4,0x50,0x2c,0x3e,0x3e,0x2c,0x2d,0x3f,0x3f,0x2b,0xfc,0xfe,0xef,0x20,0x99,0x2d,0x01,0x66,0x03,0xf0,0x01, 0x04,0x3c,0x2e,0x2e,0x3d,0x3d,0x2e,0x2c,0x3e,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x0c,0x00,0x9b,0x40,0x10,0x7a,0x0c,0x01,0x77,0x0b,0x01,0x79,0x02,0x01,0x7d,0x0a,0x01,0x7e,0x01,0x01,0x0c,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x00,0x4d,0x01,0x10,0x0b,0x00,0x4d,0x00,0xb8,0xff,0xf0,0x40,0x22,0x0c,0x00,0x4d, 0x09,0x02,0x0a,0x05,0x01,0x15,0x05,0x15,0x0a,0x0f,0x06,0x00,0x0a,0x0b,0x0b,0x01,0x70,0x00,0x01,0x00,0x14,0x0b,0x06,0x4d,0x00,0x40,0x0b,0x01,0x4d,0x00,0x0c,0xb8,0xff,0xe8,0x40,0x1c,0x0d,0x06,0x4d,0x0c,0x08,0x04,0x06,0x0d,0x06,0x4d,0x04,0x06,0x0c,0x06,0x4d,0x04,0x06,0x0b,0x06,0x4d,0x04,0x84,0x05,0x04,0x0d,0x06,0x4d,0x05, 0xb8,0xff,0xff,0xb6,0x0b,0x06,0x4d,0x05,0x2f,0x0e,0x01,0x5d,0x2f,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x2b,0x2f,0x2b,0x2b,0x5d,0x33,0x33,0x2f,0x33,0x00,0x3f,0x3f,0x3f,0x3f,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x5d,0x5d,0x00,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x01,0x33,0x01, 0x03,0xf8,0xe6,0xfe,0x3c,0x04,0xa4,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0x01,0xec,0xfe,0x14,0x05,0xec,0xfc,0x3f,0x01,0xd5,0xfe,0x12,0x00,0x01,0x00,0xa6,0x00,0x00,0x01,0x4a,0x05,0xec,0x00,0x03,0x00,0x3a,0x40,0x16,0x01,0x15,0x02,0x00,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01, 0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x01,0x01,0x05,0x04,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x4a,0xa4,0xa4,0x05,0xec,0x00,0x01,0x00,0xa6,0x00,0x00,0x06,0x54,0x04,0x18,0x00,0x1f,0x00,0xdd,0xb6,0x49,0x0c,0x01,0x49,0x04, 0x01,0x1e,0xb8,0xff,0xe8,0xb7,0x0b,0x00,0x4d,0x0f,0x21,0x01,0x03,0x1c,0xb8,0xff,0xd0,0x40,0x2c,0x0c,0x00,0x4d,0x02,0x16,0x01,0x0c,0x04,0x05,0x15,0x16,0x1b,0x04,0x0d,0x18,0x0d,0x95,0x59,0x1d,0x18,0x10,0x13,0x0f,0x0a,0x01,0x12,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8, 0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xec,0x40,0x1c,0x0b,0x06,0x4d,0x01,0x0e,0x0a,0x12,0x0a,0x42,0x14,0x11,0x06,0x0d,0x06,0x4d,0x11,0x06,0x0c,0x06,0x4d,0x11,0x06,0x0b,0x06,0x4d,0x11,0x84,0x12,0xb8,0xff,0xfa,0x40,0x31,0x0c,0x06,0x4d,0x12,0x0e,0x0b,0x06,0x4d,0x12,0x1b,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06, 0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x84,0x0a,0x0a,0x04,0x0d,0x06,0x4d,0x0a,0x40,0x0d,0x01,0x4d,0x0f,0x0a,0x01,0x0c,0x03,0x20,0x21,0x0a,0x84,0x30,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x2b,0x2b,0x10,0xe1,0x2b,0x2b,0x2b,0x39,0x18,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18, 0x2f,0x33,0x33,0x3f,0x3f,0x33,0x2b,0x11,0x00,0x17,0x33,0x5f,0x5e,0x5d,0x31,0x30,0x2b,0x01,0x5f,0x5d,0x2b,0x5d,0x5d,0x21,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x20,0x11,0x06,0x54,0xa4,0x69,0x7c,0x69,0x93,0xa4,0xe9, 0x6c,0x8c,0xa4,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0x01,0x52,0x02,0x4c,0xaa,0x98,0xc0,0x86,0xfd,0xb8,0x02,0x60,0x01,0x2e,0xb5,0x91,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x75,0x5f,0xd4,0xfe,0x5f,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x18,0x00,0x12,0x00,0x96,0x40,0x28,0x02,0x11,0x01,0x02,0x10,0x01,0x10,0x04, 0x01,0x15,0x09,0x15,0x0a,0x0f,0x0c,0x04,0x0f,0x04,0x95,0x59,0x0f,0x10,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf6,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x1e,0x0b,0x06,0x4d,0x01,0x01,0x14,0x0c,0x08,0x06,0x0d,0x06, 0x4d,0x08,0x06,0x0c,0x06,0x4d,0x08,0x06,0x0b,0x06,0x4d,0x08,0x84,0x09,0x02,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x14,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33, 0x18,0x3f,0x3f,0x3f,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0x02,0x48,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd9,0xcd,0x00,0x02,0x00,0x60,0xff,0xe8, 0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x17,0x00,0x89,0x40,0x23,0x19,0x40,0x0b,0x02,0x4d,0x00,0x12,0x95,0x59,0x00,0x16,0x06,0x0c,0x95,0x59,0x06,0x10,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x83,0x15,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x15,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x06,0x4d,0x20, 0x15,0x30,0x15,0x02,0x15,0xb8,0xff,0xde,0x40,0x2a,0x0b,0x06,0x4d,0x15,0x15,0x19,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x0a,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x83,0x03,0x10,0x0d,0x06,0x4d,0x03,0x0c,0x0c,0x06,0x4d,0x03,0x19,0x0b,0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f, 0x2b,0x5d,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x01,0x2b,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x52,0xe3,0xfe,0xf1,0x01,0x1a,0xf0,0xe5,0x01,0x01,0xfe,0xeb,0xdd,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab, 0x18,0x01,0x1f,0xed,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x03,0xa6,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0x00,0x02,0x00,0xa6,0xfe,0x29,0x04,0x54,0x04,0x18,0x00,0x10,0x00,0x1d,0x00,0x9c,0x40,0x2b,0x00,0x0a,0x01,0x10,0x06,0x03,0x1b,0x01,0x15,0x0f,0x15,0x95,0x59,0x0f,0x16,0x04,0x0f,0x06,0x1b,0x09,0x1b,0x95, 0x59,0x09,0x10,0x0c,0x06,0x0d,0x06,0x4d,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x83,0x18,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x18,0xb8,0xff,0xf2,0xb3,0x0c,0x06,0x4d,0x18,0xb8,0xff,0xe3,0x40,0x1a,0x0b,0x06,0x4d,0x18,0x18,0x1f,0x06,0x12,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06, 0x4d,0x02,0x84,0x03,0xb8,0xff,0xf8,0x40,0x11,0x0d,0x06,0x4d,0x03,0x02,0x0c,0x06,0x4d,0x03,0x01,0x0b,0x06,0x4d,0x03,0x2f,0x1f,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x31,0x30, 0x01,0x5f,0x5e,0x5d,0x25,0x23,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4e,0x04,0xa4,0xa4,0x04,0x79,0xe9,0xc6,0xde,0xfa,0xd9,0xc7,0x70,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0x94,0xfd,0x95,0x05,0xd7,0xb4,0xcc,0xfe, 0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x02,0x49,0x8f,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0xc7,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0x10,0x04,0x18,0x00,0x10,0x00,0x1d,0x00,0x95,0x40,0x35,0x1c,0x18,0x0b,0x0c,0x00,0x4c,0x01,0x1b,0x03,0x1b,0x05,0x1b,0x95,0x59,0x05,0x16,0x0f,0x0f,0x0d,0x15,0x0b,0x15,0x95,0x59,0x0b,0x10,0x0d,0x11,0x0e,0x03, 0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0x05,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf0,0x40,0x2a,0x0b,0x06,0x4d,0x01,0x01,0x1f,0x18,0x06,0x0d,0x06,0x4d,0x18,0x06,0x0c,0x06,0x4d,0x18,0x06,0x0b,0x06,0x4d,0x18,0x83,0x08,0x10,0x0d,0x06,0x4d, 0x08,0x0e,0x0c,0x06,0x4d,0x08,0x1a,0x0b,0x06,0x4d,0x08,0x2f,0x1f,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x17,0x33,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x31,0x30,0x2b,0x01,0x23,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00, 0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0xa4,0x04,0x6b,0xf3,0xc1,0xe9,0x01,0x00,0xd8,0xd2,0x5e,0x04,0xa4,0xa4,0xa5,0x7f,0x94,0xac,0xa6,0x83,0x90,0xab,0xfe,0x29,0x02,0x87,0xc8,0x01,0x13,0xed,0xff,0x01,0x31,0xa6,0x8e,0xfd,0xcd,0x95,0x7e,0xae,0xdb,0xc7,0xb1, 0xc9,0xc5,0x00,0x01,0x00,0xa6,0x00,0x00,0x02,0xbc,0x04,0x12,0x00,0x10,0x00,0x59,0xb9,0x00,0x0c,0xff,0xe8,0x40,0x27,0x0b,0x0c,0x00,0x4c,0x07,0x15,0x08,0x0f,0x00,0x00,0x0a,0x02,0x0e,0x10,0x70,0x00,0x01,0x00,0x00,0x12,0x0a,0x06,0x06,0x0d,0x06,0x4d,0x06,0x06,0x0c,0x06,0x4d,0x06,0x06,0x0b,0x06,0x4d,0x06,0x84,0x07,0xb8,0xff, 0xf3,0x40,0x0e,0x0d,0x06,0x4d,0x07,0x04,0x0c,0x06,0x4d,0x07,0x05,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x11,0x39,0x2f,0x5d,0x00,0x3f,0xcd,0x32,0x32,0x2f,0x3f,0x3f,0x31,0x30,0x2b,0x01,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x02,0xbc,0x2b,0x51,0x69,0x8d, 0xa4,0xa4,0x04,0x23,0x90,0x59,0x40,0x22,0x03,0x5a,0x21,0xc6,0xab,0xfd,0xf6,0x04,0x00,0xd3,0x6c,0x79,0x0e,0x00,0x00,0x01,0x00,0x68,0xff,0xe8,0x03,0x0f,0x04,0x18,0x00,0x2e,0x00,0xa1,0x40,0x19,0x07,0x26,0x01,0x03,0x16,0x01,0x03,0x09,0x0c,0x01,0x09,0x09,0x01,0x0f,0x00,0x01,0x10,0x04,0x2b,0x10,0x0b,0x0c,0x00,0x4c,0x12,0xb8, 0xff,0xf0,0x40,0x35,0x0b,0x0c,0x00,0x4c,0x0a,0x38,0x0b,0x0c,0x00,0x4c,0x05,0x28,0x0f,0x1e,0x04,0x14,0x2d,0x17,0x19,0x14,0x19,0x95,0x59,0x14,0x10,0x00,0x01,0x10,0x01,0x20,0x01,0x03,0x0b,0x03,0x01,0x03,0x2d,0x03,0x95,0x59,0x2d,0x16,0x17,0x17,0x28,0x1e,0x83,0x0f,0x0f,0x00,0x28,0x83,0x05,0xb8,0xff,0xe0,0x40,0x16,0x0b,0x06, 0x4d,0x20,0x05,0x30,0x05,0x02,0x05,0x05,0x30,0x00,0x10,0x0d,0x06,0x4d,0x00,0x1c,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x11,0x39,0x2f,0x5d,0x2b,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x17,0x39,0x2b,0x31,0x30,0x2b,0x2b,0x5f,0x5e,0x5d, 0x5d,0x5d,0x5f,0x5d,0x5d,0x37,0x35,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x68,0x86,0xa1,0xd8,0x25,0x3f,0x55,0x31,0x44,0x67,0x45,0x23,0x42,0x6e,0x8d,0x4b,0x85,0x69,0x71,0x93,0x2e, 0x4a,0x35,0x1d,0x1d,0x38,0x50,0x33,0x44,0x6c,0x4c,0x29,0x43,0x70,0x92,0x50,0x9e,0x25,0xb0,0x63,0x90,0x29,0x39,0x2c,0x23,0x13,0x1b,0x37,0x45,0x58,0x3b,0x48,0x6f,0x4b,0x26,0x2e,0xa6,0x4a,0x15,0x26,0x35,0x20,0x28,0x36,0x2a,0x22,0x14,0x1a,0x37,0x45,0x5a,0x3e,0x4c,0x70,0x4a,0x24,0x00,0x00,0x01,0x00,0x2b,0xff,0xea,0x02,0x81, 0x05,0x2f,0x00,0x14,0x00,0x7c,0x40,0x3b,0x03,0x18,0x0b,0x0c,0x00,0x4c,0x14,0x14,0x12,0x02,0x12,0x95,0x59,0x02,0x16,0x0a,0x0a,0x07,0x0e,0x06,0x0b,0x07,0x07,0x06,0x95,0x59,0x07,0x0f,0x00,0x00,0x0d,0x40,0x0b,0x00,0x4d,0x0d,0x06,0x0d,0x06,0x0b,0x08,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d, 0x0f,0x84,0x04,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x04,0xb8,0xff,0xee,0xb3,0x0b,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x32,0x33,0x32,0x2f,0x2f,0x2b,0x33,0x2f,0x00,0x3f,0x2b,0x11,0x00,0x33,0x11,0x33,0x11,0x33,0x18,0x2f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x31, 0x30,0x2b,0x25,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x02,0x81,0x3a,0x5f,0xfe,0xf3,0xb0,0xb0,0xa4,0x01,0x02,0xfe,0xfe,0x46,0x51,0x3e,0x2d,0x0a,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0xfd,0xbf,0x67,0x58,0x22,0x00,0x00,0x01,0x00,0x90,0xff,0xe8, 0x03,0xe2,0x04,0x00,0x00,0x11,0x00,0xa1,0x40,0x36,0x49,0x06,0x01,0x49,0x06,0x01,0x03,0x0d,0x10,0x0b,0x0c,0x00,0x4c,0x0f,0x03,0x01,0x0c,0x06,0x01,0x15,0x03,0x0c,0x05,0x0c,0x95,0x59,0x05,0x16,0x10,0x0f,0x08,0x0f,0x01,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x0f,0x01,0x0f, 0xb8,0xff,0xfa,0xb3,0x0d,0x06,0x4d,0x0f,0xb8,0xff,0xfc,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xfc,0x40,0x2a,0x0b,0x06,0x4d,0x0f,0x0f,0x13,0x0a,0x06,0x0d,0x06,0x4d,0x0a,0x06,0x0c,0x06,0x4d,0x0a,0x06,0x0b,0x06,0x4d,0x0a,0x84,0x07,0x0a,0x0d,0x06,0x4d,0x07,0x06,0x0c,0x06,0x4d,0x07,0x02,0x0b,0x06,0x4d,0x07,0x2f,0x13,0x01,0x5d, 0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x5f,0x5e,0x5d,0x31,0x30,0x2b,0x01,0x5f,0x5d,0x00,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xe2,0xa4,0x04,0x66, 0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0xa4,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0x00,0x01,0x00,0x0e,0x00,0x00,0x03,0xcb,0x04,0x00,0x00,0x0b,0x00,0x7b,0x40,0x0d,0x79,0x0b,0x01,0x79,0x02,0x01,0x77,0x01,0x01,0x76,0x04,0x01,0x0b,0xb8,0xff,0xe0,0x40,0x0b,0x0b,0x0d,0x01,0x4c,0x04,0x20,0x0b,0x0d, 0x01,0x4c,0x02,0xb8,0xff,0xf4,0x40,0x19,0x0b,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x76,0x07,0x01,0x07,0x30,0x0b,0x0d,0x01,0x4c,0x0b,0x07,0x03,0x02,0x15,0x03,0x0f,0x0b,0xb8,0xff,0xf4,0x40,0x14,0x0b,0x06,0x4d,0x0b,0x00,0x10,0x0b,0x0c,0x00,0x4c,0x00,0x00,0x0d,0x04,0x0c,0x0b,0x06,0x4d,0x04,0x03,0xb8,0xff,0xf0,0xb3,0x0c,0x00, 0x4d,0x03,0x2f,0x2b,0x33,0x2b,0x11,0x33,0x2f,0x2b,0x32,0x2b,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2b,0x5d,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x01,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x03,0xcb,0xfe,0x68,0xa1,0xfe,0x7c,0xb4,0x01,0x04,0x1d,0x07,0x04,0x0a,0x16,0x01,0x10,0x04,0x00,0xfc,0x00, 0x04,0x00,0xfd,0x18,0x52,0x3d,0x4d,0x3e,0x02,0xec,0x00,0x01,0x00,0x18,0x00,0x00,0x05,0xb0,0x04,0x00,0x00,0x1b,0x00,0xd2,0x40,0x16,0x78,0x1b,0x01,0x77,0x14,0x01,0x76,0x0c,0x01,0x7b,0x0a,0x01,0x74,0x01,0x01,0x38,0x09,0x01,0x37,0x0c,0x01,0x1b,0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x13,0xb8,0xff,0xfe,0xb3,0x0b,0x06,0x4d,0x0a, 0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x02,0xb8,0xff,0xfa,0x40,0x18,0x0b,0x06,0x4d,0x14,0x02,0x0b,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x08,0xb8,0xff,0xc0,0xb3,0x0b,0x00,0x4d,0x14,0xb8,0xff,0xf0,0x40,0x09,0x0b,0x00,0x4d,0x13,0x18,0x0b,0x00,0x4d,0x0c,0xb8,0xff,0xf8,0x40,0x09, 0x0b,0x00,0x4d,0x09,0x10,0x0b,0x00,0x4d,0x1b,0xb8,0xff,0xe0,0x40,0x0b,0x0b,0x0d,0x01,0x4c,0x0c,0x20,0x0b,0x0d,0x01,0x4c,0x06,0xb8,0xff,0xd0,0x40,0x23,0x0b,0x0d,0x01,0x4c,0x17,0x30,0x0b,0x0d,0x01,0x4c,0x0f,0x30,0x0b,0x0d,0x01,0x4c,0x02,0x06,0x0f,0x17,0x13,0x1b,0x00,0x07,0x0a,0x0b,0x0f,0x0a,0x00,0x00,0x1d,0x0b,0x2f,0x1d, 0x01,0x5d,0x2f,0x11,0x33,0x2f,0x00,0x2f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x2b,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x2b,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x01,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x01,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13, 0x16,0x17,0x33,0x36,0x37,0x13,0x05,0xb0,0xfe,0xcd,0xaa,0xd3,0x0c,0x04,0x04,0x03,0x12,0xe5,0xa4,0xfe,0xca,0xac,0xd4,0x0a,0x04,0x08,0x03,0x0f,0xec,0x96,0xd4,0x0a,0x05,0x08,0x02,0x0f,0xd0,0x04,0x00,0xfc,0x00,0x02,0xdd,0x2a,0x35,0x24,0x39,0xfd,0x21,0x04,0x00,0xfc,0xfe,0x23,0x39,0x2c,0x32,0x03,0x00,0xfc,0xfc,0x25,0x37,0x27, 0x35,0x03,0x04,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0x92,0x04,0x00,0x00,0x13,0x00,0xe0,0x40,0x13,0x7b,0x13,0x01,0x73,0x0e,0x01,0x79,0x0c,0x01,0x74,0x0a,0x01,0x7b,0x03,0x01,0x75,0x01,0x01,0x13,0xb8,0xff,0xf8,0x40,0x09,0x0b,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0c,0xb8,0xff,0xf8,0x40,0x09,0x0b,0x06,0x4d,0x0a,0x08,0x0b, 0x06,0x4d,0x03,0xb8,0xff,0xf8,0x40,0x09,0x0b,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x0d,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0c,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xf0,0x40,0x13,0x0c,0x06,0x4d,0x02,0x10,0x0c,0x06,0x4d,0x01,0x10,0x0c,0x06,0x4d,0x00,0x10,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf0,0xb3,0x0b,0x00,0x4d, 0x13,0xb8,0xff,0xf0,0x40,0x11,0x0b,0x0d,0x01,0x4c,0x0e,0x10,0x0b,0x0d,0x01,0x4c,0x0a,0x10,0x0b,0x0d,0x01,0x4c,0x03,0xb8,0xff,0xf0,0x40,0x0a,0x0b,0x0d,0x01,0x4c,0x11,0x18,0x0b,0x01,0x4d,0x06,0xb8,0xff,0xe8,0x40,0x15,0x0b,0x01,0x4d,0x03,0x06,0x11,0x13,0x04,0x0b,0x0d,0x0f,0x0b,0x00,0x02,0x0d,0x0b,0x02,0x02,0x15,0x0b,0x15, 0xb8,0xff,0xc0,0xb2,0x0c,0x00,0x4d,0x2b,0x2f,0x11,0x33,0x2f,0x11,0x33,0x11,0x33,0x00,0x2f,0x3f,0x12,0x17,0x39,0x2b,0x2b,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x09,0x02,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x01,0x01,0x33, 0x13,0x16,0x17,0x33,0x01,0x03,0x92,0xfe,0xa8,0x01,0x52,0xbf,0xc9,0x13,0x1a,0x04,0x05,0x2a,0xcd,0xbd,0x01,0x5d,0xfe,0xb2,0xbf,0xc6,0x16,0x15,0x04,0x01,0x00,0x04,0x00,0xfd,0xfa,0xfe,0x06,0x01,0x4c,0x1f,0x2f,0x09,0x45,0xfe,0xb4,0x01,0xf6,0x02,0x0a,0xfe,0xa2,0x27,0x29,0x01,0xae,0x00,0x00,0x01,0x00,0x0e,0xfe,0x1e,0x03,0xd5, 0x04,0x00,0x00,0x14,0x00,0x9b,0x40,0x0a,0x0d,0x14,0x01,0x00,0x0d,0x01,0x06,0x02,0x01,0x14,0xb8,0xff,0xe0,0x40,0x2c,0x0b,0x0d,0x01,0x4c,0x0d,0x20,0x0b,0x0d,0x01,0x4c,0x02,0x20,0x0b,0x00,0x4d,0x02,0x10,0x01,0x10,0x04,0x00,0x0f,0x0c,0x0f,0x10,0x30,0x0b,0x0d,0x01,0x4c,0x10,0x01,0x0b,0x06,0x06,0x08,0x03,0x08,0x95,0x59,0x03, 0x1c,0x06,0x0b,0xb8,0xff,0xf4,0x40,0x0e,0x0b,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x01,0x06,0x0b,0x03,0x0c,0x14,0xb8,0xff,0xf4,0x40,0x14,0x0b,0x06,0x4d,0x14,0x00,0x10,0x0b,0x0c,0x00,0x4c,0x00,0x00,0x16,0x0d,0x0c,0x0b,0x06,0x4d,0x0d,0x0c,0xb8,0xff,0xf0,0xb3,0x0c,0x00,0x4d,0x0c,0x2f,0x2b,0x33,0x2b,0x11,0x33,0x2f,0x2b,0x32, 0x2b,0x12,0x17,0x39,0x2b,0x2b,0x2f,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2f,0x33,0x33,0x2b,0x3f,0x3f,0x5f,0x5e,0x5d,0x31,0x30,0x2b,0x01,0x2b,0x2b,0x5d,0x5d,0x5d,0x01,0x01,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x03,0xd5,0xfe,0x29,0x7e,0xe4,0x40,0x2b,0x35,0x2c, 0x7c,0x3e,0x52,0xfe,0x70,0xb6,0x01,0x15,0x05,0x10,0x06,0x05,0x0f,0x01,0x23,0x04,0x00,0xfb,0x5c,0xfe,0xc2,0x0d,0x93,0x12,0x94,0xc2,0x03,0xfe,0xfc,0xec,0x0f,0x3f,0x18,0x34,0x03,0x16,0x00,0x01,0x00,0x21,0x00,0x00,0x03,0x70,0x04,0x00,0x00,0x09,0x00,0xa5,0x40,0x0e,0x0a,0x06,0x01,0x06,0x01,0x01,0x10,0x01,0x18,0x0b,0x0d,0x01, 0x4c,0x06,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x06,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x01,0x08,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x09,0x0c,0x06,0x4d,0x01,0x0c,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x40,0x0b,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x35,0x00,0x45,0x00,0x02,0x03,0x00,0x13,0x00,0x23,0x00,0x03, 0x3a,0x05,0x4a,0x05,0x02,0x0c,0x05,0x1c,0x05,0x2c,0x05,0x03,0x17,0x03,0x05,0x01,0x04,0x04,0x01,0x95,0x59,0x04,0x15,0x00,0x08,0x07,0x08,0x07,0x95,0x59,0x08,0x0f,0x03,0x07,0x07,0x01,0x06,0x03,0x04,0x04,0x00,0x00,0x0b,0x04,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x2b,0x11, 0x12,0x00,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x5e,0x5d,0x5d,0x01,0x01,0x21,0x15,0x21,0x35,0x01,0x21,0x35,0x21,0x03,0x70,0xfd,0xa2,0x02,0x58,0xfc,0xb7,0x02,0x5e,0xfd,0xdb,0x03,0x16,0x03,0xd1,0xfc,0xbb,0x8c,0x33,0x03,0x41,0x8c,0x00,0x01,0x00,0x5c,0xfe,0xba,0x02,0x2b, 0x05,0x9a,0x00,0x18,0x00,0x5f,0x40,0x2c,0x11,0x05,0x06,0x06,0x05,0x52,0x59,0x06,0x0b,0x00,0x06,0x4c,0x14,0x30,0x0b,0x0c,0x53,0x59,0x0b,0x03,0x00,0x18,0x53,0x59,0x00,0x20,0x12,0x15,0x05,0x0c,0x18,0x18,0x15,0x05,0x0f,0x08,0x15,0xea,0x02,0x18,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xdc,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf7,0xb3, 0x0b,0x06,0x4d,0x02,0x2f,0x2b,0x2b,0x2b,0xe1,0x39,0x39,0xce,0x10,0xc2,0x2f,0x32,0x11,0x12,0x39,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x01,0x24,0x11,0x11,0x34,0x27,0x35,0x36,0x35,0x11,0x10,0x25,0x15,0x06,0x15,0x11,0x14,0x07,0x15,0x16,0x15,0x11,0x14,0x16,0x17,0x02,0x2b, 0xfe,0xcd,0x9c,0x9c,0x01,0x33,0x9f,0x96,0x96,0x47,0x58,0xfe,0xba,0x04,0x01,0x32,0x01,0x2c,0xca,0x0a,0x74,0x0a,0xce,0x01,0x24,0x01,0x36,0x04,0x80,0x04,0xc2,0xfe,0xdb,0xd2,0x30,0x04,0x2d,0xd3,0xfe,0xdf,0x6f,0x5f,0x02,0x00,0x00,0x01,0x00,0xac,0xfe,0x1e,0x01,0x40,0x06,0x1e,0x00,0x03,0x00,0x13,0x40,0x09,0x03,0x00,0x1c,0x00, 0xea,0x90,0x01,0x01,0x01,0x2f,0x5d,0xe1,0x00,0x3f,0x2f,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x40,0x94,0x94,0xfe,0x1e,0x08,0x00,0x00,0x00,0x01,0x00,0x42,0xfe,0xba,0x02,0x10,0x05,0x9a,0x00,0x18,0x00,0x66,0x40,0x26,0x0c,0x00,0x18,0x18,0x00,0x52,0x59,0x18,0x13,0x05,0x18,0x4c,0x14,0x30,0x13,0x12,0x53,0x59,0x13,0x03,0x05,0x06, 0x53,0x59,0x05,0x20,0x0c,0x09,0x00,0x00,0x03,0x12,0x06,0x16,0x0f,0x03,0xea,0x09,0xb8,0xff,0xe0,0x40,0x0f,0x0d,0x06,0x4d,0x50,0x09,0x01,0x3f,0x09,0x01,0x09,0x20,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfc,0xb3,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x2b,0x5d,0x5d,0x2b,0xe1,0x39,0x39,0xc6,0x32,0x10,0xca,0x2f,0x12,0x39,0x00,0x3f,0x2b,0x00, 0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x01,0x06,0x15,0x11,0x10,0x05,0x35,0x36,0x36,0x35,0x11,0x34,0x37,0x35,0x26,0x35,0x11,0x34,0x27,0x35,0x04,0x11,0x11,0x14,0x17,0x02,0x10,0x9c,0xfe,0xce,0x57,0x49,0x95,0x95,0xa0,0x01,0x32,0x9c,0x01,0xf0,0x0a,0xca,0xfe,0xd4,0xfe,0xce,0x04,0x7e,0x02,0x60, 0x6e,0x01,0x21,0xd3,0x2d,0x04,0x30,0xd2,0x01,0x25,0xc2,0x04,0x80,0x04,0xfe,0xca,0xfe,0xdc,0xce,0x0a,0x00,0x01,0x00,0xd1,0x01,0xb8,0x04,0xaa,0x02,0xee,0x00,0x14,0x00,0x44,0xb9,0x00,0x01,0xff,0xe0,0x40,0x23,0x09,0x0c,0x48,0x0b,0x20,0x09,0x0c,0x48,0x09,0x03,0x03,0x11,0xbe,0x59,0x03,0x07,0x40,0x0d,0x07,0xbe,0x59,0x14,0x0d, 0x14,0xbd,0x00,0x09,0xbd,0x0a,0x15,0x16,0x0a,0x00,0xff,0x3a,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x00,0x18,0x2f,0xc4,0x2b,0x00,0x1a,0x18,0x10,0xcc,0x2b,0x00,0x10,0x18,0xc4,0x31,0x30,0x01,0x2b,0x2b,0x01,0x06,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x37,0x04,0xaa,0x07,0x93,0x7e, 0x6d,0x9c,0x61,0x3e,0x8c,0x06,0x87,0x05,0x95,0x7f,0x6a,0x81,0x84,0x41,0x3d,0x4a,0x02,0x02,0xee,0x94,0xa2,0x6d,0x43,0xb0,0x8f,0xa7,0x58,0x5a,0x62,0x50,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0xe2,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xe6,0x01,0x5b,0x00,0x22,0xb7,0x03,0x70,0x1f,0x01,0x02,0x7f,0x1f, 0x01,0xb8,0xff,0xf3,0x40,0x0a,0x1f,0x19,0x06,0x07,0x3e,0x03,0x02,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x5d,0x35,0x5d,0x35,0x00,0x03,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0xcd,0x00,0x10,0x00,0x1b,0x00,0x23,0x01,0x5d,0x40,0x18,0x76,0x22,0x01,0x79,0x1d,0x01,0x74,0x0c,0x01,0x7b,0x0a,0x01,0x7b,0x07,0x01,0x77,0x06,0x01, 0x10,0x06,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xfa,0x40,0x09,0x0d,0x06,0x4d,0x10,0x06,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xfa,0x40,0x09,0x0c,0x06,0x4d,0x10,0x06,0x0b,0x06,0x4d,0x06,0xb8,0xff,0xfa,0x40,0x2c,0x0b,0x06,0x4d,0x1d,0x08,0x0c,0x00,0x4d,0x02,0x08,0x0c,0x00,0x4d,0x1d,0x1c,0x02,0x01,0x20,0x01,0x22,0x23,0x03,0x04,0x20,0x04, 0x73,0x04,0x01,0x7c,0x01,0x01,0x10,0x08,0x0b,0x0c,0x00,0x4c,0x04,0x18,0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe8,0xb4,0x0b,0x0d,0x01,0x4c,0x20,0xb8,0xff,0xc0,0xb4,0x0b,0x0d,0x01,0x4c,0x1f,0xb8,0xff,0xc0,0x40,0x1e,0x0b,0x0d,0x01,0x4c,0x10,0x20,0x0b,0x0d,0x01,0x4c,0x06,0x20,0x0b,0x0d,0x01,0x4c,0x00,0x16,0x01,0x09,0x03,0x1d, 0x1e,0x1f,0x21,0x22,0x05,0x05,0x20,0x20,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x20,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x20,0xb8,0xff,0xf0,0x40,0x2a,0x0b,0x06,0x4d,0x20,0x20,0x12,0x16,0x48,0x20,0x00,0x16,0x1c,0x02,0x91,0x59,0x1c,0x1c,0x16,0x00,0x0b,0x11,0xc5,0x59,0x0b,0x10,0x06,0x16,0x03,0x04,0x00,0x12,0x19,0xc4,0x0e,0x40, 0x09,0x0c,0x48,0x0e,0x14,0xc4,0x08,0xb8,0xff,0xc0,0x40,0x12,0x0c,0x00,0x4d,0x08,0x08,0x1c,0x23,0x06,0x10,0x04,0x05,0x77,0x05,0x01,0x79,0x00,0x01,0x05,0xb8,0xff,0xe8,0x40,0x0e,0x0b,0x0c,0x00,0x4c,0x00,0x18,0x0b,0x0c,0x00,0x4c,0x00,0x00,0x25,0x05,0x2f,0x11,0x33,0x2f,0x2b,0x2b,0x5d,0x5d,0x12,0x17,0x39,0x39,0x2f,0x2b,0xe9, 0xd4,0x2b,0xe9,0x00,0x3f,0xc4,0x3f,0xcd,0x39,0xc4,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x2b,0x2b,0x2b,0x2b,0x11,0x12,0x17,0x39,0x5f,0x5e,0x5d,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x01,0x2b,0x2b,0x2b,0x5d,0x5d,0x10,0x87,0xc0,0xc0,0x0e,0xc0,0x10,0x87,0x05,0xc0,0xc0,0x0e,0xc0,0x01,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x05,0x12,0xba,0x98,0xfd,0xa0,0x8f,0xbb,0x02,0x11,0x65,0x78,0x5c,0x58,0x70,0x60,0x6e,0x32,0x40, 0x72,0x30,0x42,0x42,0xc9,0xe1,0x0b,0x0b,0x04,0x0a,0x0d,0xdf,0x01,0x92,0xfe,0x6e,0x05,0x62,0x34,0x70,0x59,0x6e,0x6d,0x54,0x70,0x36,0x01,0x15,0x3f,0x30,0x72,0x42,0x30,0x31,0x3e,0xfb,0xae,0x02,0x63,0x1e,0x42,0x3d,0x23,0xfd,0x9d,0x00,0xff,0xff,0x00,0x5e,0xfe,0x50,0x04,0x8c,0x05,0xb2,0x02,0x26,0x00,0x26,0x00,0x00,0x00,0x07, 0x00,0xdd,0x02,0x39,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x65,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x17,0x01,0x5b,0x00,0x13,0x40,0x0b,0x01,0x38,0x0e,0x0c,0x02,0x03,0x3e,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x0b,0x02,0x26, 0x00,0x31,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0xb5,0x01,0x59,0x00,0x13,0x40,0x0b,0x01,0x00,0x1e,0x14,0x0b,0x12,0x25,0x01,0x1e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x06,0xe0,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x66,0x01,0x59,0x00,0x1b,0x40,0x10,0x03,0x70, 0x27,0x01,0x02,0x00,0x27,0x21,0x03,0x09,0x25,0x03,0x02,0x24,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x5d,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x06,0xe4,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x1d,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x1d,0x17,0x05,0x0d,0x25,0x02,0x01,0x1a,0x05, 0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0x0a,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xe9,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x12,0x22,0x20,0x10,0x00,0x25,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83, 0x06,0x0a,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xcb,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x11,0x22,0x20,0x10,0x0b,0x25,0x02,0x21,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0x0e,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0x96,0x00,0x00,0x00,0x16, 0xb9,0x00,0x02,0xff,0xec,0x40,0x09,0x24,0x20,0x0f,0x14,0x25,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0x87,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x06,0x00,0x8f,0x62,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xe2,0x40,0x0a,0x2f,0x29,0x0f,0x14,0x25,0x03,0x02,0x2c,0x11,0x26, 0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0xb2,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xa8,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xeb,0x40,0x09,0x2a,0x20,0x0f,0x14,0x25,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83, 0x06,0x1c,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xdc,0x00,0xe9,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xe9,0x40,0x0a,0x23,0x29,0x0f,0x14,0x25,0x03,0x02,0x20,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xfe,0x50,0x03,0x62,0x04,0x18,0x02,0x26,0x00,0x46,0x00,0x00,0x00,0x07,0x00,0xdd, 0x01,0x83,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x0a,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x0f,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x27,0x1b,0x1d,0x0c,0x12,0x25,0x02,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x0a,0x02,0x26,0x00,0x48, 0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xfe,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x09,0x1d,0x1b,0x0c,0x12,0x25,0x02,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x0e,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xb8,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xf7,0x40, 0x09,0x1f,0x20,0x16,0x0f,0x25,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0x87,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x88,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x0a,0x29,0x23,0x0c,0x12,0x25,0x03,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35, 0x35,0x00,0xff,0xff,0x00,0x58,0x00,0x00,0x01,0xdd,0x06,0x0a,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06,0x00,0x8e,0xd1,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x06,0x05,0x02,0x03,0x25,0x01,0x06,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xec,0x00,0x00,0x01,0x71,0x06,0x0a,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06, 0x00,0x43,0x9a,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x05,0x04,0x02,0x03,0x25,0x01,0x05,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xd3,0x00,0x00,0x02,0x07,0x06,0x0e,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x00,0xd7,0xff,0x77,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf5,0x40,0x09,0x08,0x04,0x02,0x03,0x25, 0x01,0x08,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xc9,0x00,0x00,0x02,0x10,0x05,0x87,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x4c,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf4,0x40,0x0a,0x13,0x0d,0x02,0x03,0x25,0x02,0x01,0x10,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff, 0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xb2,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xe8,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x1d,0x13,0x0a,0x12,0x25,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x0a,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07, 0x00,0x8e,0x01,0x42,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe4,0x40,0x09,0x19,0x19,0x0c,0x06,0x3e,0x02,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x0a,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x14,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x14,0x19,0x19,0x03,0x09, 0x25,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x0e,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xe5,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x1d,0x1e,0x03,0x09,0x25,0x02,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8, 0x04,0x50,0x05,0x87,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xb7,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x27,0x21,0x03,0x09,0x25,0x03,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0xb2,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xd8, 0x00,0xff,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0a,0x22,0x18,0x03,0x09,0x25,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x0a,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x3c,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfb,0x40,0x09,0x14,0x12,0x09,0x11,0x25, 0x01,0x14,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x0a,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xea,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x17,0x14,0x12,0x08,0x10,0x25,0x01,0x13,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2, 0x06,0x0e,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xc6,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x03,0x16,0x12,0x08,0x11,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x05,0x87,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xa0,0x00,0x00,0x00,0x17, 0x40,0x0d,0x02,0x01,0x07,0x21,0x1b,0x08,0x11,0x25,0x02,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x00,0x01,0x00,0x30,0x00,0xe5,0x02,0xd8,0x05,0x99,0x00,0x0b,0x00,0x36,0x40,0x1b,0x0b,0x01,0x09,0x06,0x40,0x04,0x00,0x08,0x10,0x08,0x02,0x0a,0x03,0x08,0x00,0x05,0x06,0x05,0x91,0x59,0x0b,0x06,0x06,0x03, 0x08,0x03,0x03,0x00,0x2f,0x3f,0x12,0x39,0x2f,0x33,0x2b,0x11,0x00,0x33,0x01,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0x1a,0xce,0xdd,0x32,0xce,0x31,0x30,0x01,0x25,0x03,0x23,0x03,0x05,0x35,0x05,0x03,0x33,0x03,0x25,0x02,0xd8,0xfe,0xfa,0x28,0x4c,0x28,0xfe,0xfa,0x01,0x2e,0x28,0x9c,0x28,0x01,0x2e,0x03,0x7d,0x1e,0xfd,0x4a,0x02,0xb6,0x1e, 0x96,0x14,0x01,0x9a,0xfe,0x66,0x14,0x00,0x00,0x02,0x00,0x6c,0x03,0x81,0x02,0x96,0x05,0xaa,0x00,0x0b,0x00,0x17,0x00,0x38,0x40,0x21,0x00,0x12,0xd8,0x59,0x00,0x0e,0x06,0x06,0x0c,0xd8,0x59,0x06,0x04,0x03,0x09,0x42,0x15,0xd8,0x09,0x0f,0xd8,0x03,0x0f,0x09,0x01,0x17,0x03,0x18,0x19,0x03,0x09,0xff,0x3a,0x2b,0x01,0x5f,0x5e,0x5d, 0x10,0xe1,0x10,0xe1,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x10,0xe4,0x2b,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x81,0x73,0xa2,0xa0,0x73,0x74,0xa3,0xa2,0x73,0x41,0x5c,0x5a,0x41,0x41,0x5e,0x5c,0x03,0x81,0xa3,0x74,0x73,0x9f,0xa0, 0x72,0x74,0xa3,0x01,0xb4,0x5c,0x41,0x43,0x5f,0x60,0x42,0x42,0x5b,0x00,0x00,0x02,0x00,0xb8,0xff,0xcf,0x03,0xb8,0x05,0x85,0x00,0x16,0x00,0x1d,0x00,0x7f,0x40,0x42,0x05,0x10,0x01,0x03,0x0f,0x00,0x01,0x10,0x05,0x16,0x16,0x17,0x14,0x02,0x14,0x9a,0x59,0x05,0x02,0x02,0x11,0x12,0x11,0x02,0x0c,0x03,0x11,0x11,0x18,0x13,0x0e,0x13, 0x99,0x59,0x0b,0x0e,0x02,0x0e,0x02,0x0c,0x04,0x1e,0x0c,0x0b,0x0e,0x14,0x17,0x04,0x02,0xdc,0x70,0x05,0x01,0x02,0x05,0x01,0x05,0x05,0x08,0x11,0x00,0x00,0x1f,0x1b,0x89,0x08,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x08,0x2f,0x2b,0xe1,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x5d,0x5d,0xe1,0x17,0x39,0x00,0x2f,0x10,0xc6,0x11,0x39,0x39, 0x2f,0x2f,0x33,0x2b,0x11,0x00,0x33,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x11,0x33,0x2b,0x11,0x00,0x33,0x33,0x18,0x2f,0x31,0x30,0x5f,0x5e,0x5d,0x5f,0x5d,0x25,0x06,0x07,0x15,0x23,0x35,0x26,0x02,0x35,0x34,0x12,0x37,0x35,0x33,0x15,0x16,0x17,0x15,0x26,0x27,0x11,0x36,0x37,0x05,0x11,0x06,0x06,0x15,0x14,0x16,0x03,0xb8,0x60,0x7d,0x7d, 0xc1,0xe5,0xe5,0xc1,0x7d,0x7b,0x62,0x65,0x78,0x7a,0x63,0xfe,0xa6,0x77,0x87,0x88,0xd1,0x3b,0x0a,0xbd,0xbf,0x16,0x01,0x16,0xcf,0xdb,0x01,0x27,0x25,0xd5,0xcb,0x02,0x31,0xac,0x47,0x07,0xfc,0xef,0x0c,0x4a,0x4b,0x02,0xf9,0x1f,0xcd,0x96,0x96,0xc6,0x00,0x01,0x00,0x6a,0x00,0x00,0x03,0xee,0x05,0xb2,0x00,0x1b,0x00,0x6a,0x40,0x39, 0x02,0x0e,0x01,0x03,0x00,0x12,0x01,0x10,0x05,0x17,0x14,0x05,0x08,0x08,0x05,0x9a,0x59,0x08,0x08,0x1b,0x0f,0x0c,0x40,0x0c,0x11,0x9a,0x59,0x0c,0x04,0x02,0x00,0x1b,0x00,0x1b,0x9a,0x59,0x00,0x12,0x15,0x15,0x18,0x7f,0x0e,0x01,0x0e,0x00,0x1a,0x02,0x06,0x14,0x08,0x18,0x8a,0x20,0x04,0x01,0x04,0x2f,0x5d,0xe1,0x39,0x39,0xc6,0xc6, 0x32,0x2f,0xc4,0x5d,0x11,0x39,0x2f,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xcd,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5f,0x5d,0x21,0x21,0x35,0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x15,0x21,0x15,0x21, 0x15,0x14,0x07,0x21,0x03,0xee,0xfc,0x7c,0xda,0xc5,0xc5,0xda,0xad,0x75,0x60,0x64,0x6f,0xe5,0x01,0x28,0xfe,0xd8,0xc1,0x02,0xc7,0x87,0x45,0xf4,0xbb,0x8d,0xfe,0xbc,0xf0,0x29,0x9b,0x39,0xfe,0xcd,0xec,0x8d,0x9c,0xf2,0x61,0x00,0x00,0x02,0x00,0x83,0xff,0xbe,0x03,0x27,0x05,0xd3,0x00,0x26,0x00,0x30,0x00,0xcf,0x40,0x1b,0x24,0x22, 0x01,0x23,0x1b,0x01,0x2c,0x0f,0x01,0x2b,0x07,0x01,0x2c,0x30,0x01,0x25,0x2b,0x01,0x25,0x26,0x01,0x11,0x20,0x0c,0x00,0x4d,0x23,0xb8,0xff,0xe0,0xb3,0x0c,0x00,0x4d,0x17,0xb8,0xff,0xf0,0x40,0x5d,0x0b,0x0c,0x00,0x4c,0x03,0x10,0x0b,0x0c,0x00,0x4c,0x2c,0x00,0x0a,0x27,0x14,0x05,0x19,0x00,0x08,0x01,0x0e,0x03,0x08,0x08,0x0a,0x05, 0x0a,0x9a,0x59,0x05,0x00,0x1c,0x10,0x1c,0x02,0x0f,0x03,0x1c,0x1c,0x1e,0x19,0x1e,0x9a,0x59,0x19,0x2c,0x00,0x02,0x29,0x27,0x14,0x2e,0x16,0x0d,0x7e,0x02,0x1c,0x40,0x0b,0x10,0x01,0x4c,0x02,0x40,0x0c,0x10,0x01,0x4c,0x1c,0x02,0x1c,0x02,0x2e,0x7e,0x25,0x40,0x0b,0x0c,0x01,0x4c,0x25,0x25,0x32,0x12,0x20,0x7e,0x16,0x08,0x16,0x08, 0x29,0x7e,0x12,0x2f,0xe1,0x39,0x39,0x2f,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x39,0x39,0x2f,0x2f,0x2b,0x2b,0x10,0xe1,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x2f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x2f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x11,0x12,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x2b,0x2b, 0x2b,0x2b,0x01,0x5d,0x5d,0x5d,0x00,0x5d,0x5d,0x5d,0x5d,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x14,0x16,0x17,0x16,0x15,0x14,0x01,0x06,0x15,0x14,0x16,0x17,0x36,0x35,0x34,0x26,0x02,0x92,0x5a,0xc8, 0x9b,0x83,0x6c,0x82,0x78,0x54,0x5c,0x47,0x91,0xe9,0x93,0x6a,0xbb,0x99,0x82,0x59,0x65,0x7a,0xa8,0x51,0xa3,0xdf,0xfe,0x67,0x65,0x71,0x8d,0x58,0x69,0x01,0xa0,0x4a,0x70,0x84,0xa4,0x38,0x9e,0x4a,0x4f,0x3c,0x35,0x49,0x4d,0x7a,0xc3,0xa3,0x51,0x53,0x8c,0x7f,0xa4,0x2b,0x9e,0x3e,0x90,0x37,0x5a,0x4e,0x6b,0xba,0xaa,0x01,0x7f,0x33, 0x6c,0x48,0x6d,0x3f,0x44,0x68,0x48,0x65,0x00,0x01,0x00,0xa4,0x01,0x98,0x02,0x9c,0x03,0x90,0x00,0x0b,0x00,0x19,0x40,0x0c,0x00,0x0e,0x40,0x06,0x03,0x09,0x42,0x09,0x20,0x03,0x01,0x03,0x2f,0x5d,0xcd,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0xa2,0x68,0x96,0x96, 0x68,0x68,0x92,0x92,0x01,0x98,0x92,0x68,0x67,0x97,0x96,0x68,0x68,0x92,0x00,0x01,0x00,0x54,0x00,0x00,0x03,0x42,0x05,0x9a,0x00,0x0f,0x00,0x7c,0x40,0x38,0x08,0x08,0x0f,0x02,0x04,0x00,0x0f,0x00,0xe2,0x59,0x0f,0x03,0x06,0x02,0x12,0x00,0x00,0x02,0x10,0x0d,0x06,0x4d,0x02,0x8c,0x03,0x18,0x0d,0x06,0x4d,0x03,0x10,0x0c,0x06,0x4d, 0x03,0x26,0x0b,0x06,0x4d,0x2f,0x03,0x01,0x03,0x06,0x10,0x0d,0x06,0x4d,0x06,0x8c,0x08,0x03,0x0d,0x06,0x4d,0x08,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x08,0xb8,0xff,0xec,0xb4,0x0b,0x06,0x4d,0x08,0x0b,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xe4,0xb3,0x0b,0x06,0x4d,0x0b,0x2f,0x2b,0x2b,0xdd,0x2b,0x2b,0x2b,0xe1,0x2b, 0xd4,0x5d,0x2b,0x2b,0x2b,0xf1,0x2b,0xca,0x2f,0x00,0x3f,0x33,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x03,0x42,0x80,0x6a,0x9e,0x6c,0x6c,0x8e,0x95,0x6b,0x01,0xee,0x05,0x33,0xfa,0xcd,0x05,0x33,0xfa,0xcd,0x03,0x87,0x98,0x73, 0x75,0x93,0x00,0x01,0x00,0xa6,0xff,0xe8,0x04,0x14,0x06,0x02,0x00,0x25,0x00,0xa2,0x40,0x09,0x0f,0x22,0x01,0x00,0x11,0x01,0x10,0x05,0x20,0xb8,0xff,0xe0,0xb4,0x0b,0x0c,0x00,0x4c,0x1a,0xb8,0xff,0xe8,0x40,0x32,0x0b,0x00,0x4d,0x1f,0x09,0x0a,0x0a,0x09,0x96,0x59,0x18,0x24,0x0a,0x95,0x14,0x30,0x18,0x10,0x95,0x59,0x18,0x01,0x01, 0x03,0x24,0x03,0x95,0x59,0x24,0x16,0x14,0x15,0x1f,0x1b,0x09,0x00,0x00,0x13,0x0d,0x83,0x1b,0x10,0x0c,0x06,0x4d,0x1b,0x1b,0x06,0x83,0x21,0xb8,0xff,0xe8,0x40,0x16,0x0c,0x06,0x4d,0x21,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x08,0x0b,0x06,0x4d,0x13,0x84,0x14,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x14,0x06, 0x0b,0x06,0x4d,0x14,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2f,0x2b,0xe1,0x39,0x2f,0x2b,0xe1,0x11,0x39,0x2f,0xc4,0x11,0x39,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x2b,0x2b,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x25,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x35,0x36,0x36,0x35, 0x34,0x26,0x23,0x22,0x11,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x04,0x11,0x14,0x06,0x23,0x22,0x01,0xcd,0x4b,0x5f,0x6d,0x88,0xc8,0xb2,0x76,0x98,0x6e,0x61,0xe7,0xa4,0xdc,0xba,0xa6,0xc6,0x96,0x78,0x01,0x7a,0xde,0xb7,0x65,0x02,0xa0,0x30,0x93,0x7c,0x96,0xbb,0x14,0x82,0x14,0xa6,0x72,0x6c,0x77,0xfe, 0xcb,0xfb,0xbe,0x04,0x5a,0xc0,0xe8,0xbe,0x9c,0x7f,0xca,0x27,0x05,0x4b,0xfe,0xa1,0xb1,0xf0,0xff,0xff,0x00,0x90,0x01,0xfa,0x02,0xb2,0x02,0x7b,0x02,0x06,0x00,0x10,0x00,0x00,0x00,0x04,0x01,0x38,0x00,0xff,0x05,0xe7,0x05,0xae,0x00,0x0b,0x00,0x17,0x00,0x2a,0x00,0x32,0x00,0x79,0x40,0x40,0x09,0xc6,0x15,0x2a,0x18,0x50,0x19,0x1a, 0x19,0x27,0x24,0x50,0x2f,0x2c,0x1e,0x50,0x1f,0x15,0x19,0x2f,0x1f,0x1f,0x2f,0x19,0x15,0x04,0x34,0x0f,0xc6,0x40,0x03,0x28,0x2c,0x1d,0x2c,0x1d,0x51,0x59,0x2c,0x2c,0x20,0x1f,0x20,0x2b,0x52,0x59,0x20,0x20,0x0c,0x06,0x0c,0xc7,0x59,0x06,0x28,0x19,0x1f,0x1f,0x12,0x00,0x12,0xc7,0x59,0x00,0x00,0x2f,0x2b,0x11,0x00,0x33,0x18,0x2f, 0x33,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x01,0x18,0x2f,0x1a,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x10,0xed,0x33,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x25,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x00,0x15,0x14, 0x00,0x33,0x32,0x00,0x35,0x34,0x00,0x13,0x23,0x27,0x26,0x23,0x23,0x11,0x23,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x17,0x01,0x15,0x33,0x32,0x35,0x34,0x26,0x23,0x03,0x90,0xf9,0xfe,0xa1,0x01,0x5f,0xf9,0xf8,0x01,0x5f,0xfe,0xa1,0xf7,0xd2,0xfe,0xd7,0x01,0x29,0xd2,0xd1,0x01,0x27,0xfe,0xd9,0x51,0x8a,0x53,0x3f,0x49, 0x34,0x75,0xd7,0x85,0x91,0x66,0x5b,0x3f,0x3f,0xfe,0xcb,0x5e,0x9e,0x55,0x5c,0xff,0x01,0x5e,0xf9,0xf9,0x01,0x5f,0xfe,0xa1,0xf9,0xf9,0xfe,0xa2,0x04,0x51,0xfe,0xd8,0xd2,0xd1,0xfe,0xd8,0x01,0x28,0xd1,0xd2,0x01,0x28,0xfc,0x8f,0xb7,0x8a,0xfe,0xbf,0x02,0xfb,0x70,0x60,0x4e,0x6f,0x13,0x03,0x0e,0x7f,0x01,0xcd,0xf5,0x7b,0x47,0x33, 0x00,0x03,0x00,0xa2,0xff,0xdf,0x06,0x7d,0x05,0xbb,0x00,0x0b,0x00,0x17,0x00,0x2d,0x00,0x7b,0xb9,0x00,0x12,0xff,0xe8,0x40,0x46,0x0c,0x00,0x4d,0x0c,0x18,0x0c,0x00,0x4d,0x22,0x0f,0x2d,0x01,0x0f,0x03,0x2d,0x2d,0x15,0x28,0xca,0x1d,0x1d,0x15,0x0f,0xc9,0x03,0x15,0xc9,0x40,0x09,0xc6,0x03,0x1a,0x2b,0x53,0x59,0x0f,0x1a,0x1f,0x1a, 0x2f,0x1a,0x03,0x0f,0x03,0x1a,0x1a,0x25,0x12,0x20,0x25,0x53,0x59,0x20,0x20,0x0c,0x12,0x06,0x0c,0xcb,0x59,0x00,0x12,0xcb,0x59,0x06,0x00,0xc7,0x59,0x06,0x04,0x00,0x3f,0x2b,0x2b,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x01,0x18,0x2f,0xf0,0x1a,0xe9,0x10,0xe9,0x11,0x39,0x2f, 0xe1,0x11,0x39,0x2f,0x5f,0x5e,0x5d,0xc6,0x00,0x2b,0x2b,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x03,0x06,0x23,0x22,0x24,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x03,0x90,0xfe,0xc9,0xfe, 0x49,0x01,0xb7,0x01,0x37,0x01,0x36,0x01,0xb7,0xfe,0x49,0xfe,0xca,0xfe,0xee,0xfe,0x7c,0x01,0x84,0x01,0x12,0x01,0x12,0x01,0x83,0xfe,0x7d,0x03,0x69,0x8f,0xc0,0xfe,0xfc,0x01,0x0a,0xd5,0x79,0x60,0x56,0x8f,0x8d,0xb7,0xbb,0x90,0x84,0x5e,0x21,0x01,0xb7,0x01,0x37,0x01,0x37,0x01,0xb7,0xfe,0x49,0xfe,0xc9,0xfe,0xc9,0xfe,0x49,0x05, 0x84,0xfe,0x7c,0xfe,0xee,0xfe,0xee,0xfe,0x7d,0x01,0x83,0x01,0x12,0x01,0x12,0x01,0x84,0xfb,0xe6,0x45,0xfa,0xbc,0xda,0x01,0x04,0x35,0x96,0x48,0xb4,0x98,0x94,0xb2,0x4e,0x00,0x00,0x02,0x00,0x4c,0x03,0x04,0x05,0x74,0x05,0x9a,0x00,0x0f,0x00,0x17,0x00,0x79,0x40,0x49,0x0f,0x0c,0x01,0x10,0x04,0x0d,0x28,0x0b,0x0c,0x00,0x4c,0x0c, 0x28,0x0b,0x0c,0x00,0x4c,0x02,0x07,0x0c,0x03,0x16,0x01,0x05,0x09,0x03,0x13,0x11,0x15,0x16,0x15,0x54,0x59,0x0e,0x0a,0x16,0x03,0x0e,0x00,0x50,0x50,0x01,0x01,0x0f,0x01,0x01,0x0b,0x01,0x01,0x0b,0x08,0x50,0x0f,0x09,0x01,0x10,0x03,0x09,0x09,0x13,0x10,0x0e,0x12,0x50,0x13,0x13,0x15,0x42,0x15,0x20,0x13,0x01,0x13,0x2f,0x5d,0xc6, 0x2b,0x01,0x10,0xf1,0xe2,0x11,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0xe1,0x32,0x33,0x2f,0x5e,0x5d,0x5d,0xe1,0x33,0x00,0x3f,0x33,0x33,0x2b,0x11,0x00,0x33,0x18,0x2f,0x17,0x33,0x12,0x17,0x39,0x31,0x30,0x2b,0x2b,0x5f,0x5e,0x5d,0x01,0x23,0x11,0x23,0x03,0x23,0x03,0x23,0x11,0x23,0x11,0x33,0x13,0x33,0x13,0x33,0x05,0x23,0x11,0x23,0x11, 0x23,0x35,0x21,0x05,0x74,0x6c,0x04,0xdb,0x3b,0xd6,0x04,0x66,0x7f,0xe1,0x04,0xe4,0x7e,0xfc,0xe6,0xd1,0x6f,0xce,0x02,0x0e,0x03,0x04,0x01,0xde,0xfe,0x22,0x01,0xde,0xfe,0x22,0x02,0x96,0xfe,0x10,0x01,0xf0,0x62,0xfd,0xcc,0x02,0x34,0x62,0x00,0x01,0x00,0x87,0x04,0xc2,0x02,0x0c,0x06,0x0a,0x00,0x03,0x00,0x13,0xb7,0x78,0x03,0x01, 0x03,0x02,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0xcd,0x31,0x30,0x01,0x5d,0x01,0x01,0x23,0x13,0x02,0x0c,0xfe,0xfa,0x7f,0xdf,0x06,0x0a,0xfe,0xb8,0x01,0x48,0x00,0x00,0x02,0x00,0x7d,0x04,0xc2,0x02,0xc4,0x05,0x87,0x00,0x0b,0x00,0x17,0x00,0x2a,0x40,0x16,0x06,0x00,0x12,0xc1,0x0c,0x09,0xc0,0x03,0x0f,0xc0,0x10,0x15,0x01,0x0f, 0x03,0x01,0x15,0x03,0x15,0x03,0x19,0x18,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0xe1,0x10,0xe1,0x00,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x62,0x28,0x3a,0x38,0x28,0x2a,0x3a,0x38,0xfe,0x56,0x2a,0x3b,0x39, 0x29,0x29,0x3c,0x3a,0x04,0xc2,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x3b,0x28,0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0x01,0x00,0xe8,0x00,0x00,0x04,0x94,0x04,0xa4,0x00,0x13,0x00,0x89,0x40,0x3b,0x0e,0x11,0x12,0x01,0x02,0x0d,0x02,0x0b,0x08,0x07,0x04,0x03,0x0c,0x03,0x04,0x40,0x12,0x01,0x04,0x07,0x07,0x04,0xbe,0x59,0x07,0x0b, 0x40,0x11,0x0e,0x08,0x0b,0x0b,0x08,0xbe,0x59,0x0c,0x40,0x0b,0x01,0x02,0x04,0x07,0x08,0x0b,0x0c,0x0e,0x11,0x12,0x0a,0x03,0x0d,0x03,0x0d,0x03,0x10,0x09,0x00,0x05,0x00,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x05,0xb8,0xff,0xe0,0x40,0x09,0x0c,0x06,0x4d,0x14,0x15,0x05,0x00,0xff,0x3a,0x2b,0x01,0x2b,0x2b,0x11,0x12,0x39,0x39,0x39, 0x39,0x18,0x2f,0x2f,0x12,0x17,0x39,0x00,0x2f,0x1a,0xcd,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xcd,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xdd,0x31,0x30,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x01,0x21,0x03,0x23,0x13,0x23,0x35,0x21,0x13,0x21,0x35,0x21,0x13,0x33,0x03,0x21,0x15,0x21,0x03, 0x21,0x04,0x94,0xfd,0xda,0xa3,0x8d,0xa4,0xfa,0x01,0x3f,0x95,0xfe,0x2c,0x02,0x1a,0x9e,0x8d,0x9f,0x01,0x06,0xfe,0xb6,0x98,0x01,0xe2,0x01,0x3e,0xfe,0xc2,0x01,0x3e,0x84,0x01,0x26,0x84,0x01,0x38,0xfe,0xc8,0x84,0xfe,0xda,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x06,0x83,0x05,0x9a,0x00,0x0f,0x00,0x13,0x00,0xb3,0x40,0x0e,0x13,0x03, 0x04,0x12,0x04,0x02,0x12,0x01,0x00,0x04,0x01,0x10,0x04,0x12,0xb8,0xff,0xf0,0x40,0x21,0x0c,0x00,0x4d,0x0c,0x08,0x00,0x00,0x15,0x01,0x12,0x06,0x06,0x05,0x11,0x09,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x7e,0x01,0xb8,0xff,0xd8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06, 0x4d,0x01,0xb8,0xff,0xd6,0x40,0x2b,0x0b,0x06,0x4d,0x01,0x01,0x15,0x04,0x05,0x13,0x03,0x91,0x59,0x13,0x13,0x07,0x00,0x0b,0x0c,0x91,0x59,0x0b,0x07,0x00,0x0b,0x91,0x2b,0x30,0x12,0x08,0x07,0x08,0x91,0x59,0x07,0x03,0x05,0x00,0x00,0x0f,0x91,0x59,0x00,0x12,0x00,0x3f,0x2b,0x00,0x10,0x18,0xc4,0x3f,0x2b,0x11,0x00,0x33,0x2b,0x00, 0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x01,0x18,0x2f,0x33,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x2f,0xc4,0xc4,0x31,0x30,0x2b,0x5f,0x5e,0x5d,0x5d,0x10,0x87,0xc0,0xc0,0x21,0x21,0x11,0x21,0x03,0x23,0x01,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x01, 0x11,0x23,0x01,0x06,0x83,0xfd,0x09,0xfe,0x02,0xc1,0xc3,0x02,0xbc,0x03,0x9c,0xfd,0xd1,0x02,0x07,0xfd,0xf9,0x02,0x50,0xfd,0x09,0x5f,0xfe,0xa6,0x01,0x92,0xfe,0x6e,0x05,0x9a,0x98,0xfe,0x23,0x97,0xfe,0x0a,0x01,0x91,0x02,0xd9,0xfd,0x27,0x00,0x03,0x00,0x5e,0xff,0xcd,0x05,0xaa,0x05,0xd3,0x00,0x13,0x00,0x1b,0x00,0x23,0x01,0x03, 0x40,0x0a,0x57,0x09,0x01,0x57,0x0e,0x01,0x58,0x0d,0x01,0x1d,0xb8,0xff,0xe8,0xb3,0x0c,0x00,0x4d,0x0d,0xb8,0xff,0xf0,0xb3,0x0b,0x00,0x4d,0x0c,0xb8,0xff,0xe8,0xb4,0x0b,0x0c,0x00,0x4c,0x0a,0xb8,0xff,0xf0,0x40,0x21,0x0b,0x00,0x4d,0x14,0x1d,0x22,0x19,0x01,0x02,0x0b,0x0c,0x02,0x0c,0x02,0x05,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06, 0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x22,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x22,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x22,0xb8,0xff,0xea,0x40,0x0b,0x0b,0x06,0x4d,0x00,0x22,0x10,0x22,0x02,0x0b,0x03,0x22,0xb8,0xff,0xf8,0x40,0x4b,0x0b,0x06,0x4d,0x22,0x22,0x25,0x19,0x06,0x0d,0x06,0x4d,0x19,0x06,0x0c,0x06,0x4d, 0x19,0x06,0x0b,0x06,0x4d,0x19,0x7d,0x05,0x10,0x0d,0x06,0x4d,0x05,0x10,0x0c,0x06,0x4d,0x05,0x18,0x0b,0x06,0x4d,0x05,0x0c,0x0b,0x08,0x02,0x01,0x12,0x40,0x14,0x1b,0x1c,0x1d,0x04,0x1f,0x16,0x00,0x03,0x0a,0x0d,0x04,0x12,0x08,0x08,0x16,0x91,0x59,0x08,0x04,0x12,0x1f,0x91,0x59,0x12,0x13,0x2f,0x25,0x01,0x5d,0x00,0x3f,0x2b,0x00, 0x18,0x3f,0x2b,0x11,0x12,0x00,0x17,0x39,0x11,0x12,0x17,0x39,0x1a,0x18,0x10,0xce,0x32,0x10,0xce,0x32,0x01,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5f,0x5e,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x39,0x2f,0x2f,0x33,0x11,0x33,0x11,0x12,0x39,0x39,0x31,0x30,0x00,0x2b,0x2b,0x2b,0x2b,0x01,0x5d, 0x5d,0x00,0x5d,0x25,0x07,0x27,0x37,0x26,0x11,0x10,0x00,0x21,0x32,0x17,0x37,0x17,0x07,0x16,0x11,0x10,0x00,0x21,0x20,0x01,0x26,0x23,0x22,0x00,0x11,0x14,0x17,0x01,0x01,0x16,0x33,0x32,0x00,0x11,0x10,0x01,0x44,0x98,0x4e,0x9e,0x9e,0x01,0x75,0x01,0x43,0xea,0xa8,0x87,0x4e,0x8b,0xb8,0xfe,0x8c,0xfe,0xc8,0xfe,0xf6,0x02,0x4e,0x7e, 0xba,0xe3,0xfe,0xe7,0x62,0x03,0x15,0xfd,0x2b,0x83,0xcb,0xec,0x01,0x10,0x83,0xb6,0x41,0xbf,0xc3,0x01,0x2c,0x01,0x57,0x01,0x9f,0x81,0xa2,0x3f,0xa6,0xc8,0xfe,0xb9,0xfe,0xa1,0xfe,0x68,0x04,0xcc,0x66,0xfe,0xb8,0xfe,0xf9,0xdf,0x96,0x03,0x14,0xfc,0x9e,0x89,0x01,0x35,0x01,0x14,0x01,0x04,0x00,0x03,0x00,0x52,0x00,0xcf,0x06,0x3a, 0x03,0xd9,0x00,0x13,0x00,0x1d,0x00,0x27,0x00,0x8e,0x40,0x15,0x57,0x25,0x01,0x57,0x21,0x01,0x58,0x1b,0x01,0x58,0x17,0x01,0x14,0x00,0x23,0x1e,0x0a,0x05,0x19,0xbd,0x0f,0xb8,0xff,0xe0,0x40,0x0c,0x0c,0x06,0x4d,0x00,0x0f,0x01,0x0f,0x0f,0x29,0x23,0xbd,0x05,0xb8,0xff,0xe0,0x40,0x11,0x0c,0x06,0x4d,0x0f,0x05,0x1f,0x05,0x02,0x0b, 0x03,0x05,0x00,0x40,0x0c,0x00,0x4d,0x0a,0xb8,0xff,0xe0,0x40,0x1a,0x0c,0x00,0x4d,0x1e,0x26,0x14,0x00,0x0c,0x16,0x12,0x02,0x26,0x02,0x26,0xeb,0x59,0x02,0x1c,0x0c,0x20,0x08,0x08,0x20,0xeb,0x59,0x08,0x00,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x11,0x39,0x39,0x12,0x39,0x2b,0x2b,0x01,0x18, 0x2f,0x5f,0x5e,0x5d,0x2b,0xe1,0x12,0x39,0x2f,0x5d,0x2b,0xe1,0x12,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x02,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x13,0x12,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x03,0x12,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x01,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32, 0x03,0x44,0xa8,0xd6,0xa5,0xcf,0xd8,0x9c,0xec,0x96,0xa4,0xd8,0xa6,0xd0,0xd8,0x9e,0xe2,0x5d,0x83,0xbc,0x6d,0x83,0x88,0x68,0xad,0xfe,0xef,0x84,0xbc,0x6e,0x83,0x87,0x6a,0xb0,0x01,0xe2,0xfe,0xed,0xd5,0xac,0xa2,0xe7,0xfe,0xef,0x01,0x11,0xd5,0xac,0xa1,0xe8,0x01,0x85,0xfe,0xfc,0x91,0x77,0x70,0x94,0xfe,0xfa,0x01,0x06,0x96,0x76, 0x6e,0x92,0x00,0x02,0x00,0xe8,0x00,0x00,0x04,0x94,0x04,0xa4,0x00,0x0b,0x00,0x0f,0x00,0x5d,0x40,0x2e,0x03,0x0e,0x04,0x08,0x0e,0x07,0x40,0x0a,0x01,0x04,0x07,0x07,0x04,0xbe,0x59,0x0f,0x07,0x1f,0x07,0xaf,0x07,0x03,0x0d,0x03,0x07,0x0f,0x0c,0x0f,0xbe,0x59,0x0c,0x12,0x0f,0x00,0x0e,0x0a,0x07,0x01,0xbd,0x04,0x04,0x05,0x42,0x0e, 0x05,0x04,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x04,0x2f,0x2b,0xcd,0x32,0x2b,0x01,0x10,0xf1,0x39,0x39,0xe1,0x32,0x00,0x18,0x3f,0x2b,0x00,0x18,0x10,0xc4,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x11,0x21,0x35,0x21,0x04, 0x94,0xfe,0x6c,0x83,0xfe,0x6b,0x01,0x95,0x83,0x01,0x94,0xfc,0x54,0x03,0xac,0x02,0x8c,0xfe,0x6c,0x01,0x94,0x84,0x01,0x94,0xfe,0x6c,0xfc,0xf0,0x85,0x00,0x00,0x02,0x00,0xe8,0x00,0x00,0x04,0x94,0x04,0xcb,0x00,0x07,0x00,0x0b,0x00,0x5c,0x40,0x0b,0x08,0x01,0x01,0x07,0x10,0x0b,0x00,0x4d,0x02,0x01,0x00,0xb8,0xff,0xc0,0x40,0x15, 0x0c,0x00,0x4d,0x00,0x03,0x01,0x10,0x03,0x03,0x03,0x00,0x0a,0x09,0x0a,0xbe,0x59,0x09,0x12,0x03,0x07,0x08,0xb8,0xff,0xe0,0xb6,0x0c,0x06,0x4d,0x08,0x05,0x01,0x09,0xb8,0xff,0xe0,0x40,0x09,0x0c,0x06,0x4d,0x09,0x40,0x0c,0x00,0x4d,0x09,0x2f,0x2b,0x2b,0xc4,0x32,0x2f,0x2b,0xc4,0xc4,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x32,0x2f, 0x5f,0x5e,0x5d,0x2b,0x39,0x39,0x31,0x30,0x2b,0x5d,0x25,0x01,0x35,0x01,0x15,0x01,0x15,0x01,0x13,0x21,0x35,0x21,0x04,0x6c,0xfc,0xa4,0x03,0x5c,0xfd,0x7e,0x02,0x82,0x28,0xfc,0x54,0x03,0xac,0xfe,0x01,0xb2,0x3a,0x01,0xe1,0x96,0xfe,0x9e,0x04,0xfe,0xc7,0xfe,0x6a,0x85,0x00,0x02,0x00,0xe8,0x00,0x00,0x04,0x94,0x04,0xcd,0x00,0x07, 0x00,0x0b,0x00,0x5c,0x40,0x10,0x08,0x00,0x01,0x02,0x10,0x0b,0x00,0x4d,0x07,0x00,0x00,0x06,0x01,0x10,0x03,0x01,0xb8,0xff,0xc0,0x40,0x10,0x0c,0x00,0x4d,0x06,0x06,0x01,0x0a,0x09,0x0a,0xbe,0x59,0x09,0x12,0x04,0x00,0x08,0xb8,0xff,0xe0,0xb6,0x0c,0x06,0x4d,0x08,0x05,0x01,0x09,0xb8,0xff,0xe0,0x40,0x09,0x0c,0x06,0x4d,0x09,0x40, 0x0c,0x00,0x4d,0x09,0x2f,0x2b,0x2b,0xd4,0xc4,0x2f,0x2b,0xc4,0x32,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x32,0x2f,0x2b,0x5f,0x5e,0x5d,0x39,0x39,0x31,0x30,0x2b,0x5d,0x01,0x01,0x35,0x01,0x35,0x01,0x35,0x01,0x13,0x21,0x35,0x21,0x04,0x6c,0xfc,0xa4,0x02,0x84,0xfd,0x7c,0x03,0x5c,0x28,0xfc,0x54,0x03,0xac,0x02,0xb2,0xfe,0x4e,0x98, 0x01,0x35,0x06,0x01,0x65,0x95,0xfe,0x1f,0xfd,0x14,0x85,0x00,0x00,0x01,0x00,0x44,0x00,0x00,0x04,0x12,0x05,0x9a,0x00,0x1b,0x00,0x9d,0x40,0x4f,0x0f,0x1b,0x01,0x00,0x14,0x01,0x10,0x05,0x01,0x08,0x0b,0x00,0x4d,0x01,0x04,0x00,0x04,0x12,0x0f,0x13,0x0f,0x04,0x01,0x0f,0x17,0x12,0x12,0x0f,0x9a,0x59,0x08,0x05,0x0b,0x0e,0x0e,0x0b, 0x9a,0x59,0x04,0x01,0x0f,0x12,0x0e,0x12,0x0e,0x09,0x14,0x00,0x03,0x09,0x12,0x03,0x03,0x07,0x0e,0x09,0x0a,0x0c,0x42,0x10,0x0c,0x0c,0x0a,0x13,0x00,0x0e,0x09,0x0a,0x13,0x42,0x13,0x13,0x05,0x0e,0x17,0x03,0x09,0x7e,0x0a,0xb8,0xff,0xe0,0xb6,0x0c,0x06,0x4d,0x20,0x0a,0x01,0x0a,0x2f,0x5d,0x2b,0xe1,0x17,0x39,0x33,0x2f,0x2b,0x01, 0x10,0xe0,0x11,0x12,0x39,0x18,0x2f,0xc4,0x2b,0x01,0x10,0xf2,0xc2,0x18,0x2f,0x00,0x3f,0x3f,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x2b,0x11,0x12,0x00,0x39,0x39,0x2b,0x11,0x00,0x33,0x12,0x39,0x39,0x31,0x30,0x10,0x87,0x05,0xc0,0x10,0x87,0xc0,0x01,0x2b,0x5f,0x5e,0x5d,0x5d,0x01,0x01,0x21,0x15,0x21,0x15,0x21,0x15,0x21, 0x11,0x23,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x01,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x04,0x12,0xfe,0x9c,0x01,0x1d,0xfe,0xb2,0x01,0x4e,0xfe,0xb2,0xa4,0xfe,0xa8,0x01,0x58,0xfe,0xa8,0x01,0x23,0xfe,0xa0,0xc0,0xfa,0x1c,0x13,0x04,0x0d,0x24,0xfc,0x05,0x9a,0xfd,0x70,0x8b,0xcf,0x8b,0xfe,0xdb,0x01,0x25,0x8b,0xcf,0x8b, 0x02,0x90,0xfd,0xfe,0x3a,0x35,0x2a,0x4b,0x01,0xfc,0x00,0x01,0x00,0xa6,0xfe,0x74,0x04,0x18,0x04,0x00,0x00,0x18,0x00,0x5d,0x40,0x13,0x0f,0x08,0x01,0x10,0x05,0x03,0x14,0x00,0x89,0x01,0x01,0x17,0x8a,0x14,0x10,0x0d,0x06,0x4d,0x14,0xb8,0xff,0xfa,0xb7,0x0b,0x06,0x4d,0x14,0x0e,0x0a,0x8a,0x0b,0xb8,0xff,0xf8,0x40,0x16,0x0d,0x06, 0x4d,0x0b,0x0c,0x16,0x0f,0x0b,0x08,0x04,0x11,0x06,0x11,0x99,0x59,0x06,0x16,0x00,0x15,0x2f,0x1a,0x01,0x5d,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x33,0x18,0x2f,0x3f,0xc4,0x01,0x2f,0x2b,0xe1,0x32,0x2f,0x2b,0x2b,0xe1,0x39,0x2f,0xe1,0x12,0x39,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x21,0x23,0x26,0x35,0x23,0x06,0x23,0x22,0x27,0x23,0x11, 0x23,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x04,0x18,0xaa,0x17,0x05,0x54,0xc3,0xa7,0x47,0x04,0xa3,0xa3,0x8a,0x6f,0x79,0x97,0xa6,0x48,0x60,0xbf,0x7b,0xfe,0x10,0x05,0x8c,0xfd,0x8e,0x7f,0x96,0xac,0x91,0x02,0x4a,0xfd,0x09,0xbc,0x00,0x02,0x00,0x4e,0xff,0xe8,0x04,0x04,0x05,0xd1,0x00,0x16,0x00,0x21, 0x00,0x6e,0x40,0x0f,0x06,0x1a,0x01,0x0f,0x02,0x01,0x10,0x04,0x05,0x05,0x12,0x17,0x0b,0x8a,0x01,0xb8,0xff,0xe0,0x40,0x09,0x0c,0x06,0x4d,0x01,0x01,0x23,0x1c,0x89,0x12,0xb8,0xff,0xe8,0x40,0x20,0x0c,0x06,0x4d,0x12,0x17,0x01,0x19,0x15,0x19,0x9a,0x59,0x15,0x10,0x0f,0x05,0x01,0x0d,0x03,0x05,0x05,0x03,0x08,0x03,0x9a,0x59,0x08, 0x0f,0x1f,0x9a,0x59,0x0f,0x13,0x00,0x3f,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x33,0x01,0x18,0x2f,0x2b,0xe1,0x12,0x39,0x2f,0x2b,0xe1,0x33,0x12,0x39,0x19,0x2f,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x01,0x33,0x12,0x21,0x22,0x07,0x37,0x36,0x33,0x32,0x12,0x11,0x14,0x02,0x00,0x23, 0x22,0x26,0x35,0x10,0x00,0x33,0x32,0x13,0x26,0x23,0x22,0x02,0x15,0x14,0x16,0x33,0x32,0x12,0x03,0x5e,0x04,0x1a,0xfe,0xdc,0x7b,0x7b,0x27,0x77,0x81,0xc2,0xc1,0x82,0xfe,0xf2,0xb8,0xa6,0xc8,0x01,0x27,0xe3,0xb2,0x48,0x3a,0xac,0xa0,0xd6,0x71,0x61,0x97,0xd8,0x03,0x68,0x01,0xdc,0x50,0x9c,0x41,0xfe,0xf8,0xfe,0xdd,0xdd,0xfe,0x20, 0xfe,0xff,0xd5,0xb5,0x01,0x10,0x01,0x8e,0xfe,0xa4,0xd1,0xfe,0xc6,0xd2,0x7a,0x8d,0x01,0x3f,0x00,0x01,0x00,0x33,0xfe,0x2b,0x04,0xba,0x05,0x9a,0x00,0x0b,0x00,0x46,0x40,0x25,0x03,0x0a,0x01,0x04,0x09,0x01,0x03,0x08,0x01,0x10,0x03,0x06,0x00,0x00,0x0d,0x08,0x04,0x0a,0x02,0x04,0x06,0x07,0x06,0x07,0x91,0x59,0x06,0x03,0x02,0x00, 0x0b,0x00,0x0b,0x91,0x59,0x00,0x1b,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x01,0x18,0x2f,0x33,0xc6,0x32,0x12,0x39,0x2f,0xc4,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x5d,0x01,0x21,0x35,0x01,0x01,0x35,0x21,0x15,0x21,0x01,0x01,0x21,0x04,0xba,0xfb,0x79,0x02,0xa4,0xfd,0x81,0x04,0x3a,0xfc,0xbc,0x02,0x52, 0xfd,0x8f,0x03,0x8b,0xfe,0x2b,0x4e,0x03,0x73,0x03,0x54,0x5a,0x9a,0xfc,0xf0,0xfc,0xd4,0x00,0x00,0x01,0x00,0xbc,0xfe,0x2b,0x05,0x52,0x05,0x9a,0x00,0x07,0x00,0x3b,0x40,0x0d,0x00,0x7e,0x01,0x18,0x0d,0x06,0x4d,0x01,0x01,0x09,0x04,0x7e,0x05,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf8,0x40,0x0d,0x0c,0x06,0x4d,0x05, 0x07,0x02,0x91,0x59,0x07,0x03,0x04,0x00,0x1b,0x00,0x3f,0xc4,0x3f,0x2b,0x01,0x18,0x2f,0x2b,0x2b,0xe1,0x12,0x39,0x2f,0x2b,0xe1,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x05,0x52,0xa8,0xfc,0xba,0xa8,0x04,0x96,0xfe,0x2b,0x06,0xd5,0xf9,0x2b,0x07,0x6f,0x00,0x00,0x01,0x00,0xbe,0xfe,0x1a,0x03,0x94,0x06,0x02,0x00,0x15, 0x00,0x43,0x40,0x0a,0x00,0x0e,0x05,0x8a,0x0f,0x0f,0x0b,0x42,0x0b,0x0f,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xe0,0x40,0x13,0x0b,0x06,0x4d,0x0f,0x0f,0x17,0x16,0x13,0x02,0x9a,0x59,0x13,0x01,0x08,0x0d,0x9a,0x59,0x08,0x1c,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0x2b,0x2b,0xc6,0x2b,0x01, 0x10,0xf1,0xe2,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x03,0x94,0x30,0x3f,0xaa,0xbb,0x8b,0x4b,0x2c,0x30,0x3d,0xac,0xbb,0x8a,0x4c,0x2c,0x05,0x5c,0x1b,0xd9,0xfa,0xd6,0x9e,0xbc,0x13,0x93,0x1a,0xd9,0x05,0x27,0xa0,0xbc,0x12,0x00,0x02,0x00,0x52, 0x02,0xba,0x02,0xb0,0x05,0xb0,0x00,0x15,0x00,0x1f,0x00,0x6e,0x40,0x42,0x00,0x13,0x01,0x0f,0x06,0x01,0x10,0x05,0x0b,0x16,0x54,0x59,0x00,0x0b,0x10,0x0b,0x20,0x0b,0x03,0x09,0x03,0x0b,0x0b,0x12,0x1c,0x00,0x24,0x02,0x1c,0x05,0x1c,0x54,0x59,0x05,0x25,0x0f,0x30,0x0d,0x11,0x48,0x0f,0x0f,0x0d,0x12,0x0d,0x52,0x59,0x12,0x04,0x0b, 0x02,0x1f,0xc2,0xc0,0x00,0x01,0xd0,0x00,0x01,0x00,0x21,0x0f,0x0f,0x19,0xc2,0x08,0x2f,0xe1,0x39,0x2f,0x10,0xde,0x5d,0x71,0xe1,0x32,0x32,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x11,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5d,0x01,0x23,0x35,0x23,0x06,0x23, 0x22,0x26,0x35,0x34,0x37,0x37,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x07,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x02,0xb0,0x81,0x04,0x4f,0x98,0x6d,0x85,0xf8,0xe5,0x97,0x88,0x76,0x6f,0x9b,0x7e,0x8e,0x81,0xb4,0xa8,0x4d,0x40,0x52,0x7d,0x02,0xcd,0x64,0x77,0x77,0x5d,0xca,0x21,0x1f,0xa8,0x56,0x80,0x46,0x90, 0x82,0x6b,0x19,0x17,0x6f,0x33,0x40,0x7a,0x55,0x00,0x00,0x02,0x00,0x4e,0x02,0xb8,0x03,0x23,0x05,0xae,0x00,0x0b,0x00,0x17,0x00,0x2b,0x40,0x1a,0x00,0x12,0x52,0x59,0x00,0x25,0x06,0x0c,0x52,0x59,0x06,0x04,0x15,0xc8,0x90,0x09,0xb0,0x09,0xc0,0x09,0x03,0x09,0x19,0x0f,0xc8,0x03,0x2f,0xe1,0x10,0xde,0x71,0xe1,0x00,0x3f,0x2b,0x00, 0x18,0x3f,0x2b,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0xb4,0xa7,0xbf,0xcd,0xa9,0xa3,0xbc,0xc7,0xa0,0x6a,0x7d,0x77,0x6e,0x69,0x7b,0x79,0x02,0xb8,0xc9,0xac,0xb5,0xcc,0xc7,0xab,0xb2,0xd2,0x02,0x88,0x90,0x7f,0x7c,0x8c,0x8f,0x7b, 0x7e,0x8f,0x00,0x01,0x00,0x64,0x00,0x00,0x05,0xa9,0x05,0xb2,0x00,0x1b,0x00,0xc9,0x40,0x0c,0x59,0x19,0x01,0x59,0x11,0x01,0x10,0x10,0x0c,0x00,0x4d,0x1a,0xb8,0xff,0xf0,0x40,0x27,0x0c,0x00,0x4d,0x0c,0x08,0x0c,0x00,0x4d,0x02,0x08,0x0c,0x00,0x4d,0x1a,0x18,0x02,0x10,0x12,0x0c,0x02,0x0c,0x02,0x04,0x0a,0x1b,0x1b,0x18,0x08,0x0d, 0x06,0x4d,0x18,0x08,0x0c,0x06,0x4d,0x18,0x7d,0x04,0xb8,0xff,0xf4,0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x04,0xb8,0xff,0xdc,0x40,0x40,0x0b,0x06,0x4d,0x00,0x04,0x10,0x04,0x02,0x0b,0x03,0x04,0x04,0x1d,0x0a,0x08,0x0d,0x06,0x4d,0x0a,0x08,0x0c,0x06,0x4d,0x0a,0x7d,0x0f,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08, 0x0c,0x06,0x4d,0x12,0x12,0x0b,0x06,0x4d,0x12,0x15,0x07,0x99,0x59,0x15,0x04,0x02,0x0c,0x0e,0x10,0x04,0x00,0x1b,0x00,0x1b,0x99,0x59,0x00,0x12,0x2f,0x1d,0x01,0x5d,0x00,0x3f,0x2b,0x11,0x12,0x00,0x17,0x39,0x18,0x3f,0x2b,0x01,0x18,0x2f,0x2b,0x2b,0x2b,0xc4,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x2b,0x2b,0xf1,0x2b, 0x2b,0xc1,0x2f,0x11,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x11,0x12,0x39,0x31,0x30,0x00,0x2b,0x2b,0x01,0x2b,0x2b,0x00,0x5d,0x5d,0x21,0x21,0x35,0x24,0x11,0x34,0x00,0x23,0x22,0x00,0x15,0x10,0x01,0x15,0x21,0x35,0x05,0x24,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x05,0x25,0x05,0xa9,0xfd,0xf9,0x01,0x59,0xfe,0xea,0xdb,0xde,0xfe, 0xe6,0x01,0x5a,0xfd,0xf8,0x01,0x5c,0xfe,0xa4,0x01,0x72,0x01,0x2e,0x01,0x35,0x01,0x70,0xfe,0xa5,0x01,0x5b,0x93,0xff,0x01,0x7a,0xf5,0x01,0x1d,0xfe,0xe4,0xf5,0xfe,0x86,0xff,0x00,0x93,0x94,0x01,0xeb,0x01,0x93,0x01,0x39,0x01,0x68,0xfe,0x9b,0xfe,0xc5,0xfe,0x6e,0xed,0x01,0x00,0x00,0x03,0x00,0x5a,0xff,0xe8,0x06,0x56,0x04,0x18, 0x00,0x23,0x00,0x2a,0x00,0x35,0x00,0xcd,0x40,0x21,0x56,0x19,0x01,0x51,0x12,0x01,0x59,0x07,0x01,0x58,0x1f,0x01,0x58,0x0a,0x01,0x0f,0x40,0x0b,0x00,0x4d,0x5f,0x07,0x01,0x07,0x07,0x00,0x83,0x24,0x08,0x0c,0x06,0x4d,0x24,0xb8,0xff,0xc0,0x40,0x59,0x0b,0x0c,0x00,0x4c,0x24,0x24,0x37,0x0b,0x14,0x1d,0x2a,0x04,0x01,0x84,0x2b,0x2b, 0x37,0x11,0x00,0x18,0x01,0x18,0x18,0x30,0x83,0x11,0x10,0x0c,0x06,0x4d,0x0f,0x11,0x01,0x0b,0x03,0x11,0x2c,0x14,0x00,0x24,0x24,0x00,0x95,0x59,0x24,0x24,0x04,0x18,0x40,0x09,0x0c,0x48,0x18,0x18,0x16,0x1b,0x16,0x20,0x1e,0x27,0x20,0x27,0x95,0x59,0x20,0x10,0x00,0x06,0x10,0x06,0x20,0x06,0x03,0x0c,0x03,0x06,0x06,0x01,0x0b,0x33, 0x0e,0x09,0x04,0x09,0x04,0x95,0x59,0x09,0x16,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x33,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x12,0x39,0x39,0x18,0x2f,0x33,0x2f,0x2b,0x11,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x01,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0xe1,0x39,0x2f,0x5d,0x11,0x12,0x39,0x2f,0xe1,0x17, 0x39,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x32,0x2f,0x5d,0x30,0x31,0x00,0x2b,0x01,0x5d,0x5d,0x00,0x5d,0x5d,0x5d,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x27,0x23,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x33,0x36,0x33,0x32,0x12,0x15,0x27,0x26,0x26,0x23,0x22,0x06,0x07, 0x07,0x35,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x06,0x56,0xfd,0x2b,0x03,0xb0,0x99,0xb1,0x90,0x84,0xe2,0xfe,0xf2,0x71,0x04,0x91,0xf2,0x99,0xaf,0x01,0x7f,0x01,0x06,0xd7,0xaf,0x9b,0x94,0xc8,0xe8,0x44,0x04,0x74,0xf0,0xca,0xde,0xa8,0x02,0x85,0x77,0x74,0xa6,0x13,0xa4,0xcb,0x8b,0x89,0x6a,0x5a,0x77,0xa4,0x01,0xd7,0xab, 0xba,0x72,0x9a,0x62,0xe5,0xe5,0xa1,0x87,0x01,0x2c,0x18,0x10,0x01,0x2a,0x7a,0xa4,0x60,0xc8,0xc8,0xfe,0xfb,0xe8,0x37,0x90,0x9c,0xa4,0x88,0xc8,0x3f,0x0c,0x08,0x52,0x5f,0x49,0x59,0xa9,0x00,0x03,0x00,0x31,0xff,0xae,0x04,0x96,0x04,0x66,0x00,0x13,0x00,0x1b,0x00,0x23,0x00,0xd4,0xb6,0x58,0x1c,0x01,0x57,0x1b,0x01,0x1d,0xb8,0xff, 0xf0,0x40,0x2b,0x0b,0x0c,0x00,0x4c,0x1d,0x14,0x22,0x19,0x0b,0x08,0x12,0x01,0x04,0x03,0x0d,0x13,0x00,0x00,0x03,0x06,0x0d,0x06,0x4d,0x03,0x06,0x0c,0x06,0x4d,0x03,0x06,0x0b,0x06,0x4d,0x03,0x83,0x00,0x22,0x10,0x22,0x02,0x0b,0x03,0x22,0xb8,0xff,0xec,0xb3,0x0d,0x06,0x4d,0x22,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x22,0xb8,0xff, 0xde,0x40,0x47,0x0b,0x06,0x4d,0x22,0x22,0x25,0x19,0x07,0x0d,0x06,0x4d,0x19,0x0a,0x0c,0x06,0x4d,0x19,0x83,0x09,0x0a,0x0d,0x11,0x0d,0x06,0x4d,0x0d,0x0c,0x0c,0x06,0x4d,0x0d,0x19,0x0b,0x06,0x4d,0x0d,0x14,0x1b,0x1c,0x1d,0x04,0x1f,0x16,0x01,0x08,0x0b,0x12,0x04,0x10,0x0a,0x09,0x06,0x00,0x13,0x10,0x40,0x10,0x16,0x95,0x59,0x10, 0x10,0x06,0x1f,0x95,0x59,0x06,0x16,0x2f,0x25,0x01,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xce,0x32,0x10,0xce,0x32,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x01,0x2f,0x2b,0x2b,0x2b,0xce,0x32,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5f,0x5e,0x5d,0xf1,0x2b,0x2b,0x2b,0xca,0x2f,0x32,0x11,0x12,0x17,0x39, 0x11,0x12,0x39,0x39,0x31,0x30,0x00,0x2b,0x5d,0x5d,0x01,0x07,0x16,0x15,0x14,0x00,0x23,0x22,0x27,0x07,0x27,0x37,0x26,0x35,0x10,0x00,0x33,0x32,0x17,0x37,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x01,0x01,0x16,0x33,0x32,0x36,0x35,0x34,0x04,0x96,0xa8,0x62,0xfe,0xea,0xe8,0xc0,0x7e,0x91,0x52,0x95,0x66,0x01,0x1c,0xf0,0xb8,0x7c, 0xa2,0xfe,0xf3,0x4f,0x88,0x9f,0xb7,0x32,0x02,0x41,0xfe,0x04,0x57,0x86,0xa3,0xab,0x04,0x18,0xb4,0x8a,0xd0,0xfc,0xfe,0xda,0x66,0xa0,0x4e,0xa4,0x89,0xcb,0x01,0x02,0x01,0x22,0x62,0xb0,0xfe,0xde,0x4a,0xd7,0xbd,0x84,0x5c,0x01,0xcc,0xfd,0xd8,0x4c,0xd0,0xbe,0x86,0x00,0x00,0x02,0x00,0x8f,0xfe,0x52,0x03,0x3d,0x04,0x16,0x00,0x23, 0x00,0x33,0x00,0x45,0x40,0x25,0x0f,0x12,0x01,0x10,0x05,0x11,0x0f,0x14,0x0f,0x95,0x59,0x14,0x00,0x2c,0x24,0x2c,0xb0,0x5b,0x24,0x10,0x20,0xef,0x03,0x30,0xaf,0x70,0x28,0x01,0x28,0x28,0x11,0x19,0x84,0x0a,0x0a,0x34,0x11,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x5d,0xe1,0xd4,0xe1,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x2f,0x2b, 0x00,0x18,0x10,0xc6,0x31,0x30,0x5f,0x5e,0x5d,0x01,0x16,0x16,0x15,0x14,0x0e,0x04,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x35,0x34,0x26,0x27,0x13,0x32,0x17,0x16,0x15,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x02,0x71,0x09,0x0e,0x33,0x4c,0x5a,0x4c,0x33,0x25,0x40, 0x54,0x2f,0xa9,0x7c,0x99,0xa4,0x4c,0x86,0x64,0x3b,0x34,0x4f,0x5c,0x4f,0x34,0x16,0x0b,0x47,0x2c,0x22,0x21,0x21,0x21,0x2d,0x2d,0x21,0x21,0x21,0x22,0x02,0x76,0x1a,0x53,0x29,0x40,0x67,0x5a,0x53,0x55,0x5d,0x38,0x30,0x4a,0x32,0x19,0x85,0xb0,0x60,0x28,0x4f,0x76,0x4e,0x4a,0x74,0x61,0x54,0x53,0x5a,0x36,0x2e,0x4b,0x1a,0x01,0xa0, 0x20,0x1f,0x2f,0x2e,0x20,0x21,0x21,0x20,0x2e,0x2f,0x1f,0x20,0x00,0x02,0x00,0xb4,0xfe,0x6a,0x01,0x92,0x04,0x16,0x00,0x0b,0x00,0x0f,0x00,0x3d,0x40,0x12,0x0d,0x0c,0x0e,0x0f,0xff,0x3a,0x0c,0x7d,0x0d,0x0d,0x09,0xaf,0x0f,0x03,0x01,0x10,0x03,0x03,0xb8,0xff,0xe8,0x40,0x0e,0x0d,0x06,0x4d,0x03,0x0e,0x00,0x40,0x06,0x00,0xb0,0x5b, 0x06,0x10,0x0c,0x00,0x2f,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xce,0x01,0x2f,0x2b,0x5f,0x5e,0x5d,0xe1,0x39,0x2f,0xe1,0x2b,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x23,0x13,0x33,0x01,0x23,0x2e,0x41,0x41,0x2e,0x2d,0x42,0x42,0x2b,0xac,0x13,0x86,0x03,0x3a,0x40,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x40, 0xfb,0x30,0x04,0x06,0x00,0x01,0x00,0xe8,0x00,0xfe,0x04,0x94,0x03,0x31,0x00,0x05,0x00,0x2c,0xb2,0x01,0xbd,0x00,0xb8,0xff,0xc8,0xb4,0x0c,0x06,0x4d,0x00,0x03,0xb8,0xff,0xe0,0x40,0x0b,0x0c,0x06,0x4d,0x03,0x00,0x03,0x04,0x03,0xbe,0x59,0x04,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc4,0x01,0x2f,0x2b,0x2f,0x2b,0xe1,0x31,0x30,0x25,0x23, 0x11,0x21,0x35,0x21,0x04,0x94,0x84,0xfc,0xd8,0x03,0xac,0xfe,0x01,0xae,0x85,0x00,0x00,0x01,0x00,0x7b,0x00,0x00,0x04,0x5a,0x05,0xec,0x00,0x08,0x00,0x41,0x40,0x22,0x0a,0x03,0x01,0x0b,0x02,0x01,0x03,0x0f,0x01,0x01,0x10,0x05,0x01,0x02,0x00,0x03,0x03,0x04,0x08,0x00,0x04,0x07,0x01,0x05,0x04,0xd9,0x59,0x05,0x05,0x01,0x00,0x00, 0x01,0x12,0x00,0x3f,0x3f,0x11,0x39,0x2f,0x2b,0x11,0x00,0x33,0x01,0x18,0x2f,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5f,0x5d,0x5d,0x01,0x01,0x23,0x01,0x23,0x35,0x21,0x01,0x01,0x04,0x5a,0xfe,0x7b,0x71,0xfe,0xc1,0xaa,0x01,0x08,0x01,0x13,0x01,0x4e,0x05,0xec,0xfa,0x14,0x02,0xee,0x78,0xfd,0x6b,0x05, 0x1b,0x00,0x00,0x01,0x00,0x5e,0xfe,0xea,0x03,0xb8,0x05,0x9a,0x00,0x1c,0x00,0x89,0x40,0x12,0x79,0x13,0x01,0x79,0x11,0x01,0x77,0x09,0x01,0x77,0x03,0x01,0x0a,0x30,0x0c,0x00,0x4d,0x04,0xb8,0xff,0xf0,0x40,0x3c,0x0c,0x00,0x4d,0x0f,0x06,0x01,0x09,0x06,0x06,0x04,0x08,0x05,0x04,0x03,0x09,0x13,0x16,0x17,0x09,0x04,0x12,0x00,0x14, 0x20,0x14,0x30,0x14,0x03,0x0a,0x03,0x14,0x14,0x12,0x12,0x0d,0x1c,0x0d,0x08,0x05,0x13,0x16,0x16,0x13,0x95,0x59,0x16,0x16,0x1d,0x1a,0x1a,0x02,0x95,0x59,0x1a,0x03,0x0b,0x10,0x95,0x59,0x0b,0x00,0x2f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x01,0x18,0x2f,0x2f,0x12,0x39,0x11,0x33, 0x2f,0x5f,0x5e,0x5d,0x11,0x17,0x33,0x11,0x17,0x33,0x11,0x33,0x2f,0x5e,0x5d,0x31,0x30,0x2b,0x00,0x2b,0x01,0x5d,0x5d,0x5d,0x5d,0x01,0x26,0x23,0x22,0x07,0x07,0x33,0x15,0x23,0x03,0x02,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x13,0x23,0x35,0x33,0x37,0x36,0x36,0x33,0x32,0x17,0x03,0xb8,0x30,0x3c,0x92,0x18,0x1f,0xa6,0xbb,0x5a, 0x3a,0xfe,0xde,0x1f,0x3b,0x24,0x32,0x96,0x28,0x5b,0x67,0x7c,0x1c,0x11,0xaf,0x86,0x40,0x34,0x04,0xf2,0x1c,0xa0,0xd0,0x8a,0xfd,0x78,0xfe,0x5e,0x10,0x8f,0x15,0x01,0x24,0x02,0x7c,0x8a,0xdb,0x83,0x9e,0x13,0x00,0x02,0x00,0xd1,0x00,0xf0,0x04,0xaa,0x03,0xc0,0x00,0x14,0x00,0x29,0x00,0x97,0xb9,0x00,0x16,0xff,0xe0,0xb3,0x09,0x0c, 0x48,0x01,0xb8,0xff,0xe0,0x40,0x3a,0x09,0x0c,0x48,0x20,0x20,0x09,0x0c,0x48,0x0b,0x20,0x09,0x0c,0x48,0x1e,0x18,0x18,0x26,0xbe,0x59,0x18,0x1c,0x40,0x22,0x1c,0xbe,0x59,0x15,0x00,0x22,0x01,0x0c,0x03,0x22,0x0d,0x09,0x03,0x03,0x11,0xbe,0x59,0x03,0x07,0x40,0x0d,0x07,0xbe,0x59,0x14,0x00,0x0d,0xa0,0x0d,0xb0,0x0d,0x03,0x0c,0x03, 0x0d,0xb8,0xff,0xc0,0x40,0x14,0x0e,0x11,0x48,0x0d,0x29,0x15,0x14,0xbd,0x00,0x1f,0x1e,0x09,0xbd,0x0a,0x2a,0x2b,0x0a,0x00,0xff,0x3a,0x2b,0x01,0x10,0xe1,0x39,0x39,0x10,0xe1,0x39,0x39,0x00,0x18,0x2f,0x2b,0x5f,0x5e,0x5d,0xc4,0x2b,0x00,0x1a,0x18,0x10,0xcc,0x2b,0x00,0x10,0x18,0xc4,0x10,0xd4,0x5f,0x5e,0x5d,0xc4,0x2b,0x00,0x1a, 0x18,0x10,0xcc,0x2b,0x00,0x10,0x18,0xc4,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x01,0x06,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x37,0x13,0x06,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x37,0x04,0xaa,0x07,0x93,0x7e,0x6d,0x9c, 0x61,0x3e,0x8c,0x06,0x87,0x05,0x95,0x7f,0x6a,0x81,0x84,0x41,0x3d,0x4a,0x02,0x87,0x07,0x93,0x7e,0x6d,0x9c,0x5e,0x41,0x8c,0x06,0x87,0x05,0x95,0x7f,0x6a,0x81,0x84,0x41,0x3d,0x4a,0x02,0x03,0xc0,0x92,0xa2,0x6c,0x44,0xb0,0x90,0xa4,0x58,0x5a,0x62,0x50,0xfe,0x65,0x93,0xa2,0x6c,0x42,0xae,0x8f,0xa6,0x58,0x5b,0x64,0x4f,0x00,0x02, 0x00,0x33,0x00,0x00,0x04,0xf8,0x05,0x9a,0x00,0x05,0x00,0x0d,0x00,0x3f,0x40,0x22,0x00,0x0d,0x01,0x00,0x0c,0x01,0x0f,0x07,0x01,0x0f,0x06,0x01,0x10,0x04,0x0d,0x06,0x02,0x05,0x05,0x0f,0x02,0x09,0x03,0x03,0x05,0x02,0x01,0x0d,0x01,0x0d,0x99,0x59,0x01,0x12,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0x33,0x01,0x2f,0x12, 0x39,0x2f,0x12,0x39,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x35,0x01,0x33,0x01,0x27,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x04,0xf8,0xfb,0x3b,0x02,0x09,0xae,0x02,0x0e,0xd7,0xfe,0x97,0x21,0x05,0x04,0x06,0x22,0xfe,0xa0,0x4c,0x05,0x4e,0xfa,0xb2,0x4c,0x03,0xc8,0x58,0x36,0x30,0x5e,0xfc,0x38,0x00,0x02,0x00,0x5c, 0x00,0xc8,0x03,0xb4,0x03,0x70,0x00,0x05,0x00,0x0b,0x00,0x2b,0x40,0x15,0x06,0x0a,0x00,0x04,0x00,0x00,0x04,0xf0,0x05,0x02,0x08,0x80,0x0a,0x0a,0x06,0xf0,0x0b,0x0f,0x08,0x01,0x08,0x2f,0x5d,0x33,0xf1,0xc0,0x2f,0x1a,0x10,0xdc,0x32,0xf1,0xc2,0x2f,0x00,0x2f,0xc6,0x39,0x39,0x31,0x30,0x25,0x23,0x01,0x01,0x33,0x01,0x03,0x23,0x01, 0x01,0x33,0x01,0x03,0xb2,0xa8,0xfe,0xd5,0x01,0x2b,0xaa,0xfe,0xcd,0x54,0xa6,0xfe,0xd5,0x01,0x2b,0xa6,0xfe,0xd1,0xc8,0x01,0x50,0x01,0x58,0xfe,0xa8,0xfe,0xb0,0x01,0x50,0x01,0x58,0xfe,0xa8,0x00,0x00,0x02,0x00,0x5a,0x00,0xc8,0x03,0xb4,0x03,0x70,0x00,0x05,0x00,0x0b,0x00,0x2b,0x40,0x17,0x07,0x0b,0x02,0x04,0x03,0x00,0xf0,0x04, 0x02,0x80,0x09,0x06,0xf0,0x0a,0x50,0x08,0x70,0x08,0x02,0x2f,0x08,0x01,0x08,0x2f,0x5d,0x5d,0xc4,0xe1,0x32,0x1a,0xdc,0xc4,0xe1,0x32,0x00,0x2f,0xc4,0x39,0x39,0x31,0x30,0x01,0x01,0x23,0x01,0x01,0x33,0x03,0x01,0x23,0x01,0x01,0x33,0x03,0xb4,0xfe,0xd3,0xa5,0x01,0x2e,0xfe,0xd2,0xa5,0x58,0xfe,0xd5,0xaa,0x01,0x34,0xfe,0xcc,0xaa, 0x02,0x1a,0xfe,0xae,0x01,0x52,0x01,0x56,0xfe,0xaa,0xfe,0xae,0x01,0x52,0x01,0x56,0x00,0x03,0x00,0x8c,0xff,0xee,0x05,0x52,0x00,0xcd,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x56,0xb2,0x03,0xaf,0x09,0xb8,0xff,0xfd,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfb,0x40,0x27,0x0b,0x06,0x4d,0x09,0x0e,0x15,0x0f,0x1b,0x42,0x21,0xaf,0x1b,0x1b, 0x24,0x15,0xaf,0x0f,0x0f,0x25,0x24,0x0c,0x12,0x18,0x1e,0x04,0x00,0x06,0x00,0x06,0xb0,0x5b,0x00,0x13,0x40,0x25,0x01,0x2f,0x25,0x01,0x5d,0x5d,0x00,0x3f,0x2b,0x11,0x12,0x00,0x17,0x39,0x11,0x12,0x01,0x39,0x18,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0xe1,0x31,0x30,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x04,0xe4,0x2e,0x3f,0x3f,0x2e,0x2d,0x41,0x41,0xfd,0xdd,0x2e,0x41,0x41,0x2e,0x2d,0x41,0x41,0xfd,0xdd,0x2e,0x3e,0x3e,0x2e,0x2d,0x41,0x40,0x12,0x40,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x40, 0x40,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x40,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x66,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x1f,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x23,0x11,0x10,0x06,0x07,0x3e,0x02,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x0b,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x2d,0x01,0x59,0x00,0x16,0xb9,0x00,0x02,0xff,0xfd,0x40,0x09,0x1a,0x10,0x06,0x07,0x25,0x02,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x0a,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07, 0x00,0xd8,0x01,0xab,0x01,0x58,0x00,0x13,0x40,0x0b,0x02,0x0a,0x22,0x18,0x03,0x09,0x25,0x02,0x22,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x07,0x12,0x05,0xb2,0x00,0x18,0x00,0x23,0x00,0xb7,0x40,0x1d,0x06,0x18,0x0b,0x00,0x4d,0x14,0x11,0x00,0x00,0x25,0x13,0x17,0x08,0x0d,0x06,0x4d,0x17,0x08, 0x0c,0x06,0x4d,0x17,0x08,0x0b,0x06,0x4d,0x17,0x7e,0x19,0xb8,0xff,0xd0,0xb3,0x0d,0x06,0x4d,0x19,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x19,0xb8,0xff,0xd8,0x40,0x4f,0x0b,0x06,0x4d,0x00,0x19,0x01,0x0b,0x03,0x19,0x19,0x25,0x1f,0x08,0x0d,0x06,0x4d,0x1f,0x08,0x0c,0x06,0x4d,0x1f,0x08,0x0b,0x06,0x4d,0x1f,0x7d,0x08,0x10,0x0d,0x06, 0x4d,0x08,0x10,0x0c,0x06,0x4d,0x08,0x18,0x0b,0x06,0x4d,0x08,0x14,0x15,0x91,0x59,0x14,0x10,0x00,0x14,0x91,0x2b,0x30,0x0b,0x1c,0x91,0x59,0x0b,0x04,0x10,0x11,0x91,0x59,0x10,0x03,0x05,0x22,0x91,0x59,0x05,0x13,0x00,0x18,0x91,0x59,0x00,0x12,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00, 0x18,0x2f,0x2b,0x01,0x18,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0xc4,0xc4,0x31,0x30,0x2b,0x21,0x21,0x22,0x07,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x16,0x33,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x25,0x11,0x26,0x23, 0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x07,0x12,0xfd,0x30,0x10,0x7a,0x62,0x54,0xfe,0xc8,0xfe,0x94,0x01,0x7b,0x01,0x45,0x5a,0x58,0x70,0x02,0x02,0xb0,0xfd,0xd0,0x02,0x06,0xfd,0xfa,0x02,0x50,0xfd,0x08,0xa0,0x6c,0xe5,0xfe,0xe5,0x01,0x17,0xe3,0x74,0x0e,0x0a,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0x0a,0x0e,0x98,0xfe,0x23,0x97, 0xfe,0x0a,0x08,0x04,0x5e,0x1c,0xfe,0xb4,0xfe,0xfd,0xfe,0xfe,0xfe,0xb6,0x00,0x03,0x00,0x60,0xff,0xe8,0x07,0x21,0x04,0x18,0x00,0x1c,0x00,0x23,0x00,0x2f,0x00,0xfb,0xb3,0x58,0x07,0x01,0x0b,0xb8,0xff,0xe8,0xb3,0x0c,0x00,0x4d,0x02,0xb8,0xff,0xe8,0x40,0x0d,0x0c,0x00,0x4d,0x06,0x40,0x0f,0x12,0x48,0x06,0x06,0x1c,0x83,0x1d,0xb8, 0xff,0xc0,0xb3,0x0c,0x00,0x4d,0x1d,0xb8,0xff,0xd0,0xb3,0x0c,0x01,0x4d,0x1d,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x1d,0xb8,0xff,0xee,0x40,0x1b,0x0b,0x06,0x4d,0x1d,0x40,0x0c,0x00,0x4d,0x00,0x1d,0x01,0x0b,0x1d,0x1d,0x31,0x0b,0x17,0x23,0x03,0x01,0x08,0x0b,0x06,0x4d,0x01,0x84,0x2d,0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x2d,0xb8, 0xff,0xc0,0x40,0x51,0x0c,0x00,0x4d,0x2d,0x2d,0x31,0x27,0x0a,0x0d,0x06,0x4d,0x27,0x0a,0x0c,0x06,0x4d,0x27,0x0a,0x0b,0x06,0x4d,0x27,0x83,0x11,0x10,0x0d,0x06,0x4d,0x11,0x0d,0x0c,0x06,0x4d,0x11,0x1f,0x0b,0x06,0x4d,0x11,0x00,0x06,0x10,0x06,0x20,0x06,0x03,0x0c,0x03,0x06,0x06,0x01,0x04,0x1d,0x00,0x95,0x59,0x1d,0x1d,0x04,0x17, 0x24,0x14,0x20,0x19,0x19,0x20,0x95,0x59,0x19,0x10,0x0b,0x2a,0x0e,0x09,0x04,0x09,0x04,0x95,0x59,0x09,0x16,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x33,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x32,0x12,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x01,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39, 0x2f,0x2b,0x2b,0xe1,0x2b,0x17,0x39,0x12,0x39,0x2f,0x5e,0x5d,0x2b,0x2b,0x2b,0x2b,0x2b,0xf1,0xc0,0x2f,0x2b,0x31,0x30,0x00,0x2b,0x2b,0x5d,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x27,0x23,0x06,0x21,0x22,0x00,0x35,0x10,0x00,0x33,0x20,0x17,0x33,0x36,0x21,0x32,0x12,0x15,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x01, 0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x07,0x21,0xfd,0x2b,0x03,0xb1,0x9a,0xaf,0x90,0x88,0xdd,0xfe,0xf2,0x70,0x04,0x83,0xfe,0xe3,0xe5,0xfe,0xf3,0x01,0x1c,0xf0,0x01,0x26,0x6c,0x04,0x77,0x01,0x0a,0xc4,0xda,0xa8,0x02,0x86,0x74,0x78,0xa7,0x10,0xfe,0x10,0x9e,0xb8,0xb8,0x9c,0x9f,0xad,0xad,0x01,0xd7,0xab,0xba, 0x72,0x9a,0x62,0xed,0xed,0x01,0x1e,0xec,0x01,0x02,0x01,0x24,0xeb,0xeb,0xfe,0xf9,0xe2,0x33,0x8e,0x9e,0xab,0x81,0x01,0x2c,0xd9,0xbf,0xb4,0xd0,0xcd,0xbd,0xc2,0xd0,0x00,0x01,0x00,0x00,0x01,0xfa,0x04,0x00,0x02,0x7b,0x00,0x03,0x00,0x0f,0xb6,0x02,0x01,0xeb,0x59,0x02,0x00,0x01,0x2f,0x2f,0x00,0x2f,0x2b,0x31,0x30,0x01,0x21,0x35, 0x21,0x04,0x00,0xfc,0x00,0x04,0x00,0x01,0xfa,0x81,0x00,0x01,0x00,0x00,0x01,0xfa,0x08,0x00,0x02,0x7b,0x00,0x03,0x00,0x0f,0xb6,0x02,0x01,0xeb,0x59,0x02,0x00,0x01,0x2f,0x2f,0x00,0x2f,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x08,0x00,0xf8,0x00,0x08,0x00,0x01,0xfa,0x81,0x00,0x02,0x00,0x6a,0x03,0xf4,0x02,0x9c,0x05,0xb2,0x00,0x03, 0x00,0x07,0x00,0x23,0x40,0x13,0x03,0x02,0x06,0xb3,0x40,0x07,0x04,0x00,0xb4,0x02,0x04,0xb4,0x80,0x10,0x06,0x20,0x06,0x02,0x06,0x2f,0x5d,0x1a,0xe9,0xdc,0xe9,0x00,0x3f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0x9c,0x6f,0x93,0x8d,0xbb,0x6c,0x96,0x8c,0x05,0xb2,0xfe,0x42,0x01,0xbe,0xfe,0x42, 0x01,0xbe,0x00,0x02,0x00,0x6e,0x03,0xf4,0x02,0xa0,0x05,0xb2,0x00,0x03,0x00,0x07,0x00,0x23,0x40,0x13,0x03,0x02,0x06,0xb3,0x40,0x07,0x04,0x00,0xb4,0x02,0x04,0xb4,0x80,0x10,0x06,0x20,0x06,0x02,0x06,0x2f,0x5d,0x1a,0xe9,0xdc,0xe9,0x00,0x3f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0xa0,0x8c, 0x76,0x6c,0x9a,0x8c,0x76,0x6f,0x05,0xb2,0xfe,0x42,0x01,0xbe,0xfe,0x42,0x01,0xbe,0x00,0x01,0x00,0x6a,0x03,0xf4,0x01,0x6c,0x05,0xb2,0x00,0x03,0x00,0x18,0x40,0x0c,0x02,0xb3,0x40,0x03,0x04,0x00,0xb4,0x80,0xaf,0x02,0x01,0x02,0x2f,0x5d,0x1a,0xe9,0x00,0x3f,0x1a,0xed,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x6c,0x6c,0x96,0x8c,0x05, 0xb2,0xfe,0x42,0x01,0xbe,0x00,0x00,0x01,0x00,0x6e,0x03,0xf4,0x01,0x70,0x05,0xb2,0x00,0x03,0x00,0x14,0x40,0x09,0x02,0xb3,0x40,0x03,0x04,0x00,0xb4,0x80,0x02,0x2f,0x1a,0xe9,0x00,0x3f,0x1a,0xed,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x70,0x8c,0x76,0x6f,0x05,0xb2,0xfe,0x42,0x01,0xbe,0x00,0x00,0x03,0x00,0xe8,0x00,0x70,0x04,0x94, 0x04,0x3a,0x00,0x0a,0x00,0x0e,0x00,0x19,0x00,0x4b,0x40,0x25,0x15,0x0f,0xd6,0x5b,0x15,0x15,0x0c,0x0d,0x0c,0xbe,0x59,0x0d,0x00,0x42,0x00,0x06,0xd6,0x5b,0x00,0x0f,0x0d,0x01,0x0d,0x03,0x0d,0x0b,0x0e,0x17,0x12,0x0c,0x42,0x0c,0x08,0x03,0x17,0xd3,0x12,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x12,0x2f,0x2b,0xe1,0x39,0x39,0xc6,0x2b, 0x01,0x10,0xe2,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0xc6,0x2b,0x2b,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x06,0x01,0x21,0x35,0x21,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x06,0x02,0xc4,0x2c,0x3c,0x3a,0x2e,0x67,0x3d,0x01,0xa6,0xfc,0x54,0x03,0xac,0xfe,0x2c,0x2c, 0x3e,0x3c,0x2e,0x65,0x3a,0x03,0x64,0x3d,0x2c,0x2d,0x40,0x6b,0x2f,0x3c,0xfe,0xae,0x86,0xfd,0xd8,0x3c,0x2b,0x2d,0x42,0x6d,0x2d,0x3c,0x00,0x02,0x00,0x6c,0x00,0x00,0x04,0x40,0x05,0x9a,0x00,0x05,0x00,0x09,0x00,0x28,0x40,0x11,0x03,0x08,0x06,0x00,0x00,0x01,0x05,0x03,0x01,0x12,0x08,0x06,0x03,0x00,0x00,0x0b,0x03,0x2f,0x12,0x39, 0x2f,0x12,0x39,0x39,0x00,0x3f,0x3f,0x12,0x39,0x3d,0x2f,0x18,0xc4,0xc4,0x3d,0xc4,0x31,0x30,0x01,0x01,0x23,0x01,0x01,0x33,0x09,0x03,0x04,0x40,0xfe,0x3b,0x4c,0xfe,0x3d,0x01,0xc3,0x4c,0x01,0x3f,0xfe,0x9c,0xfe,0x9c,0x01,0x64,0x02,0xcd,0xfd,0x33,0x02,0xcb,0x02,0xcf,0xfd,0x33,0x02,0x3f,0xfd,0xc1,0xfd,0xbf,0xff,0xff,0x00,0x0e, 0xfe,0x1e,0x03,0xd5,0x05,0x87,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x06,0x00,0x8f,0x4f,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x24,0x1e,0x0c,0x00,0x25,0x02,0x01,0x21,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x06,0xe2,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0x8f, 0x00,0x95,0x01,0x5b,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfc,0x40,0x0a,0x1d,0x17,0x05,0x00,0x25,0x02,0x01,0x1a,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x01,0xfe,0xc8,0x00,0x00,0x02,0xb2,0x05,0x9a,0x00,0x03,0x00,0x0e,0xb5,0x00,0x03,0x02,0x12,0x00,0x02,0x2f,0x2f,0x00,0x3f,0x3f,0x31,0x30,0x01,0x01,0x23,0x01, 0x02,0xb2,0xfc,0xa6,0x90,0x03,0x5b,0x05,0x9a,0xfa,0x66,0x05,0x9a,0x00,0x00,0x01,0x00,0x66,0xff,0xe8,0x03,0xf6,0x05,0xb2,0x00,0x25,0x00,0xcb,0x40,0x0c,0x02,0x13,0x01,0x0b,0x00,0x01,0x02,0x22,0x01,0x10,0x04,0x0f,0xb8,0xff,0xe8,0x40,0x65,0x0b,0x00,0x4d,0x03,0x10,0x0b,0x0c,0x00,0x4c,0x13,0x14,0x00,0x25,0x21,0x1e,0x04,0x07, 0x07,0x04,0x9a,0x59,0x07,0x0e,0x40,0x1c,0x19,0x0b,0x0e,0x0e,0x0b,0x9a,0x59,0x0f,0x0e,0x5f,0x0e,0x7f,0x0e,0x8f,0x0e,0x04,0x0b,0x03,0x0e,0x0e,0x11,0x23,0x00,0x14,0x10,0x14,0x02,0x0c,0x04,0x14,0x14,0x16,0x11,0x16,0x9a,0x59,0x11,0x07,0x00,0x25,0x10,0x25,0x02,0x0c,0x04,0x25,0x25,0x23,0x02,0x23,0x9a,0x59,0x02,0x19,0x1f,0x1a, 0x14,0x00,0x00,0x27,0x19,0x1c,0x1e,0x21,0x04,0x1d,0x8a,0x09,0x0c,0x06,0x04,0x07,0x0b,0x0e,0x04,0x09,0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x17,0x33,0xde,0xc4,0x10,0xe1,0x17,0x32,0x12,0x39,0x2f,0xd4,0xd6,0xc4,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e, 0x5d,0x11,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xcd,0x2b,0x11,0x12,0x00,0x39,0x39,0x11,0x33,0x11,0x33,0x30,0x31,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x5d,0x25,0x06,0x23,0x20,0x03,0x23,0x35,0x33,0x26,0x35,0x34,0x37,0x23,0x35,0x33,0x36,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06, 0x07,0x21,0x15,0x21,0x06,0x17,0x21,0x15,0x21,0x12,0x21,0x32,0x37,0x03,0xf6,0x85,0x95,0xfe,0x55,0x52,0x79,0x6c,0x04,0x06,0x6e,0x83,0x33,0x01,0x1b,0xca,0x89,0x6c,0x72,0x8e,0x7d,0xc3,0x27,0x01,0xf1,0xfd,0xf9,0x08,0x07,0x02,0x08,0xfe,0x08,0x48,0x01,0x16,0x83,0x8d,0x32,0x4a,0x01,0xfa,0x8c,0x1f,0x2e,0x30,0x3c,0x8c,0xf0,0x01, 0x0f,0x38,0xa2,0x4e,0xc9,0xaa,0x8c,0x63,0x56,0x8c,0xfe,0x92,0x57,0x00,0x00,0x01,0x00,0x5c,0x00,0xc8,0x02,0x2f,0x03,0x70,0x00,0x05,0x00,0x1c,0x40,0x0e,0x00,0x04,0x00,0x00,0x04,0xf0,0x05,0x20,0x02,0x01,0x0f,0x02,0x01,0x02,0x2f,0x5d,0x5d,0x33,0xf1,0xc2,0x2f,0x00,0x2f,0xc6,0x31,0x30,0x25,0x23,0x01,0x01,0x33,0x01,0x02,0x2d, 0xa6,0xfe,0xd5,0x01,0x2b,0xa8,0xfe,0xcf,0xc8,0x01,0x50,0x01,0x58,0xfe,0xa8,0x00,0x00,0x01,0x00,0x5c,0x00,0xc8,0x02,0x2f,0x03,0x70,0x00,0x05,0x00,0x1c,0x40,0x0f,0x02,0x04,0x03,0x00,0xf0,0x04,0x50,0x02,0x70,0x02,0x02,0x0f,0x02,0x01,0x02,0x2f,0x5d,0x5d,0xc4,0xe1,0x32,0x00,0x2f,0xc6,0x31,0x30,0x01,0x01,0x23,0x01,0x01,0x33, 0x02,0x2f,0xfe,0xd3,0xa6,0x01,0x30,0xfe,0xd0,0xa6,0x02,0x1a,0xfe,0xae,0x01,0x52,0x01,0x56,0x00,0x03,0x00,0x35,0x00,0x00,0x03,0xea,0x06,0x02,0x00,0x14,0x00,0x20,0x00,0x24,0x00,0xaf,0xb9,0x00,0x11,0xff,0xe8,0x40,0x3d,0x0b,0x00,0x4d,0x15,0x1b,0x63,0x59,0x15,0x23,0x12,0x02,0x95,0x59,0x12,0x01,0x05,0x08,0x23,0x03,0x0b,0x0e, 0x0e,0x0b,0x95,0x59,0x0e,0x0f,0x09,0x21,0x15,0x1e,0x62,0x18,0x21,0x08,0x0d,0x06,0x4d,0x21,0x08,0x0c,0x06,0x4d,0x21,0x08,0x0b,0x06,0x4d,0x21,0x84,0x22,0x08,0x0d,0x06,0x4d,0x22,0x08,0x0c,0x06,0x4d,0x22,0xb8,0xff,0xf1,0x40,0x1e,0x0b,0x06,0x4d,0x22,0x22,0x26,0x0a,0x06,0x00,0x0c,0x0e,0x05,0x09,0x08,0x0d,0x06,0x4d,0x09,0x08, 0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x84,0x0a,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xf4,0xb3,0x0b,0x06,0x4d,0x0a,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0xc6,0xd4,0xc6,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xd4,0xe1,0x00,0x3f,0xc4, 0x3f,0x2b,0x11,0x12,0x00,0x17,0x39,0x18,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x31,0x30,0x00,0x2b,0x01,0x26,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x23,0x11,0x33,0x02,0xa0,0x30,0x3d,0xac,0xf0,0xf0,0xa3, 0xaf,0xaf,0xba,0x8b,0x4b,0x2c,0xdd,0x2d,0x3e,0x3e,0x2d,0x2d,0x40,0x40,0x23,0xa4,0xa4,0x05,0x5c,0x1b,0xd9,0x9e,0x8c,0xfc,0x8c,0x03,0x74,0x8c,0xa6,0xa1,0xbb,0x12,0xec,0x3c,0x2e,0x2d,0x3e,0x3d,0x2e,0x2c,0x3e,0xfa,0xfc,0x04,0x00,0x00,0x00,0x02,0x00,0x35,0x00,0x00,0x03,0xcf,0x06,0x02,0x00,0x14,0x00,0x18,0x00,0xa4,0xb9,0x00, 0x11,0xff,0xe8,0x40,0x37,0x0b,0x00,0x4d,0x08,0x05,0x0b,0x0e,0x0e,0x0b,0x95,0x59,0x0e,0x0f,0x12,0x02,0x95,0x59,0x12,0x01,0x18,0x00,0x09,0x15,0x15,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x84,0x70,0x16,0x01,0x16,0x08,0x0d,0x06,0x4d,0x16,0x08,0x0c,0x06,0x4d,0x16,0xb8,0xff,0xf1,0x40, 0x1e,0x0b,0x06,0x4d,0x16,0x16,0x1a,0x0a,0x06,0x00,0x0c,0x0e,0x05,0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x84,0x0a,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xf4,0xb3,0x0b,0x06,0x4d,0x0a,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39, 0x39,0xc6,0xd4,0xc6,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x32,0x3f,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x01,0x26,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x01,0x23,0x11,0x33,0x02,0xa0,0x30,0x3d,0xac, 0xf0,0xf0,0xa3,0xaf,0xaf,0xba,0x8b,0x4b,0x2c,0x01,0x2f,0xa2,0xa2,0x05,0x5c,0x1b,0xd9,0x9e,0x8c,0xfc,0x8c,0x03,0x74,0x8c,0xa6,0xa1,0xbb,0x12,0xfa,0x10,0x05,0xec,0x00,0x01,0x00,0x30,0x00,0xe5,0x02,0xd8,0x05,0x99,0x00,0x15,0x00,0x5a,0x40,0x2e,0x15,0x10,0x14,0x13,0x12,0x02,0x0e,0x06,0x0b,0x40,0x09,0x08,0x07,0x03,0x00,0x0d, 0x10,0x0d,0x02,0x0a,0x03,0x0d,0x15,0x06,0x05,0x06,0x91,0x59,0x00,0x05,0x11,0x0a,0x0b,0x0a,0x91,0x59,0x10,0x0b,0x05,0x0b,0x05,0x0b,0x03,0x0d,0x03,0x03,0x00,0x2f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x2b,0x11,0x00,0x33,0x11,0x33,0x2b,0x11,0x00,0x33,0x01,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0x33,0x33,0x33,0x1a,0xce,0x32,0xdd, 0x32,0x32,0x32,0x32,0xce,0x32,0x31,0x30,0x01,0x25,0x13,0x23,0x13,0x05,0x35,0x05,0x37,0x27,0x05,0x35,0x05,0x03,0x33,0x03,0x25,0x15,0x25,0x07,0x17,0x25,0x02,0xd8,0xfe,0xd2,0x28,0x9c,0x28,0xfe,0xd2,0x01,0x06,0x3a,0x3a,0xfe,0xfa,0x01,0x2e,0x28,0x9c,0x28,0x01,0x2e,0xfe,0xfa,0x3a,0x3a,0x01,0x06,0x02,0x07,0x14,0xfe,0xca,0x01, 0x36,0x14,0x96,0x1e,0xc0,0xc0,0x1e,0x96,0x14,0x01,0x36,0xfe,0xca,0x14,0x96,0x1e,0xc0,0xc0,0x1e,0x00,0x00,0x01,0x00,0x70,0x01,0xfe,0x01,0x50,0x02,0xdf,0x00,0x0b,0x00,0x15,0x40,0x0b,0x06,0x00,0xb0,0x5b,0x06,0x09,0xaf,0x03,0x2f,0x0d,0x01,0x5d,0x2f,0xe1,0x00,0x2f,0x2b,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16, 0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x01,0xfe,0x42,0x2e,0x2f,0x42,0x42,0x2f,0x2e,0x42,0x00,0x00,0x01,0x00,0x58,0xff,0x1c,0x01,0x5a,0x00,0xd9,0x00,0x03,0x00,0x2c,0x40,0x1c,0x00,0x10,0x10,0x00,0x4d,0x00,0x10,0x0c,0x00,0x4d,0x03,0x10,0x10,0x00,0x4d,0x03,0x10,0x0c,0x00,0x4d,0x02,0xb3,0x40,0x03,0x00,0xb4, 0x80,0x02,0x2f,0x1a,0xe9,0x00,0x2f,0x1a,0xed,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x25,0x03,0x23,0x13,0x01,0x5a,0x8d,0x75,0x6e,0xd9,0xfe,0x43,0x01,0xbd,0x00,0x02,0x00,0x58,0xff,0x1c,0x02,0x89,0x00,0xd9,0x00,0x03,0x00,0x07,0x00,0x4d,0x40,0x35,0x04,0x10,0x10,0x00,0x4d,0x04,0x10,0x0c,0x00,0x4d,0x07,0x10,0x10,0x00,0x4d,0x07, 0x10,0x0c,0x00,0x4d,0x00,0x10,0x10,0x00,0x4d,0x00,0x10,0x0c,0x00,0x4d,0x03,0x10,0x10,0x00,0x4d,0x03,0x10,0x0c,0x00,0x4d,0x03,0x02,0x06,0xb3,0x40,0x07,0x00,0xb4,0x02,0x04,0xb4,0x80,0x06,0x2f,0x1a,0xe9,0xdc,0xe9,0x00,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x25,0x03,0x23,0x13,0x23, 0x03,0x23,0x13,0x02,0x89,0x8b,0x77,0x6d,0x9a,0x8d,0x75,0x6e,0xd9,0xfe,0x43,0x01,0xbd,0xfe,0x43,0x01,0xbd,0x00,0x00,0x07,0x00,0x50,0xff,0xea,0x09,0x5e,0x05,0xb0,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x27,0x00,0x33,0x00,0x3f,0x00,0x4b,0x01,0x01,0x40,0x3c,0x18,0x03,0x1a,0x3a,0x40,0x52,0x59,0x3a,0x0e,0x34,0x34,0x46,0x52,0x59, 0x34,0x1c,0x22,0x28,0x52,0x59,0x22,0x0e,0x1c,0x1c,0x2e,0x52,0x59,0x1c,0x13,0x1b,0x03,0x06,0x00,0x42,0x00,0x12,0x52,0x59,0x00,0x06,0x06,0x0c,0x52,0x59,0x06,0x04,0x1a,0x18,0x1a,0x18,0x3d,0x03,0x37,0xbd,0x43,0x10,0x0d,0x06,0x4d,0x43,0xb8,0xff,0xf4,0x40,0x0a,0x0b,0x06,0x4d,0x43,0x49,0xc8,0x1f,0x3d,0x01,0x3d,0xb8,0xff,0xf4, 0xb3,0x0d,0x06,0x4d,0x3d,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x3d,0xb8,0xff,0xee,0x40,0x0e,0x0b,0x06,0x4d,0x3d,0x3d,0x03,0x1f,0xbd,0x2b,0x10,0x0d,0x06,0x4d,0x2b,0xb8,0xff,0xf4,0xb6,0x0b,0x06,0x4d,0x2b,0x31,0xc2,0x25,0xb8,0xff,0xe0,0x40,0x14,0x0d,0x06,0x4d,0x25,0x1c,0x0c,0x06,0x4d,0x25,0x07,0x0b,0x06,0x4d,0x25,0x25,0x4d, 0x03,0x09,0xbd,0x15,0xb8,0xff,0xec,0x40,0x16,0x0d,0x06,0x4d,0x15,0x0c,0x0b,0x06,0x4d,0x15,0x0f,0xc8,0x03,0x1c,0x0d,0x06,0x4d,0x03,0x1c,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xe4,0xb3,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0xd4,0x2b,0x2b,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0xd4,0x2b,0x2b,0xe1,0x11,0x39,0x2f,0x2b, 0x2b,0x2b,0x5d,0xe1,0xd4,0x2b,0x2b,0xe1,0x11,0x12,0x39,0x39,0x2f,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc4,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xe4,0x2b,0x00,0x10,0x18,0xc4,0x2b,0x00,0x18,0x10,0xe4,0x2b,0x00,0x18,0x2f,0x3f,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x25,0x01,0x23,0x01,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x94,0x94, 0xb0,0xba,0x9e,0x99,0xa9,0xbd,0x8b,0x5f,0x6e,0x6c,0x5d,0x5e,0x6a,0x69,0x03,0x59,0xfc,0x66,0x8f,0x03,0x99,0x03,0x42,0x94,0xb0,0xbd,0x9b,0x99,0xa9,0xbc,0x8c,0x60,0x6c,0x6b,0x5d,0x5f,0x6a,0x6a,0xfc,0x79,0x94,0xb0,0xbc,0x9c,0x98,0xaa,0xbd,0x8b,0x60,0x6d,0x6c,0x5d,0x5e,0x6a,0x69,0x02,0xcb,0xc3,0xa3,0xb2,0xcd,0xbe,0xac,0xac, 0xcf,0x02,0x77,0x8d,0x7b,0x79,0x87,0x8c,0x7c,0x79,0x87,0x58,0xfa,0x5c,0x05,0xa4,0xfa,0x50,0xc4,0xa2,0xb1,0xd0,0xbf,0xae,0xab,0xcf,0x02,0x76,0x8d,0x7b,0x78,0x86,0x8d,0x7b,0x79,0x85,0xfd,0x8a,0xc4,0xa2,0xb2,0xcf,0xc0,0xad,0xab,0xcf,0x02,0x76,0x8c,0x7c,0x77,0x87,0x8d,0x7b,0x7a,0x84,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12, 0x07,0x69,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x0f,0x01,0x5b,0x00,0x16,0xb9,0x00,0x02,0xff,0xf1,0x40,0x09,0x12,0x12,0x0c,0x0b,0x25,0x02,0x14,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x6b,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xab,0x01,0x5d, 0x00,0x16,0xb9,0x00,0x01,0xff,0xf5,0x40,0x09,0x0e,0x0e,0x02,0x03,0x25,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x66,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x57,0x01,0x5c,0x00,0x16,0xb9,0x00,0x02,0xff,0xfa,0x40,0x09,0x11,0x13,0x06,0x07,0x25,0x02,0x12, 0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x06,0xe3,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x8b,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x05,0x21,0x0f,0x02,0x03,0x3e,0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00, 0x03,0xb4,0x07,0x66,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xe8,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xe9,0x40,0x09,0x0f,0x0d,0x02,0x03,0x25,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x78,0x00,0x00,0x01,0xfd,0x07,0x66,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x8e,0xff,0xf1, 0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x06,0x05,0x02,0x03,0x25,0x01,0x06,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x02,0x30,0x07,0x6b,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xd7,0xff,0xa0,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x06,0x08,0x04,0x02,0x03,0x25,0x01,0x08,0x05,0x26,0x00, 0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xf1,0x00,0x00,0x02,0x38,0x06,0xe3,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x74,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x04,0x13,0x0d,0x02,0x03,0x25,0x02,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x1b,0x00,0x00,0x01,0xa0, 0x07,0x66,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x43,0xff,0xc9,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x05,0x04,0x02,0x03,0x25,0x01,0x05,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x66,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xf8,0x01,0x5c,0x00,0x13, 0x40,0x0b,0x02,0x1e,0x19,0x1b,0x0c,0x06,0x3e,0x02,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x6a,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x97,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x05,0x1a,0x1a,0x03,0x09,0x25,0x02,0x1c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x66,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x99,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x2c,0x19,0x18,0x03,0x09,0x25,0x02,0x19,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x65,0x02,0x26,0x00,0x38,0x00,0x00, 0x01,0x07,0x00,0x8e,0x01,0xb4,0x01,0x5b,0x00,0x13,0x40,0x0b,0x01,0x2b,0x0f,0x11,0x05,0x0d,0x25,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x6b,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x4b,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x10,0x10,0x05,0x0d, 0x25,0x01,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x66,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x67,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xd1,0x40,0x09,0x11,0x0f,0x05,0x0d,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x01,0x00,0xa6, 0x00,0x00,0x01,0x4a,0x04,0x00,0x00,0x03,0x00,0x31,0x40,0x16,0x03,0x0f,0x00,0x15,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xfe,0xb6,0x0c,0x06,0x4d,0x01,0x01,0x05,0x04,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x31,0x30,0x21,0x23,0x11,0x33,0x01, 0x4a,0xa4,0xa4,0x04,0x00,0x00,0x00,0x01,0x00,0x5c,0x04,0xc2,0x02,0x90,0x06,0x0e,0x00,0x06,0x00,0x1c,0xb3,0x00,0x00,0x08,0x04,0xb8,0xff,0xc0,0xb6,0x10,0x00,0x4d,0x04,0x05,0x80,0x03,0x00,0x2f,0x1a,0xcd,0x01,0x2f,0x2b,0x12,0x39,0x2f,0x31,0x30,0x01,0x23,0x27,0x07,0x23,0x13,0x33,0x02,0x90,0x7a,0xa4,0xa5,0x71,0xd7,0x85,0x04, 0xc2,0xe6,0xe6,0x01,0x4c,0x00,0x00,0x01,0x00,0x23,0x04,0xb2,0x02,0xa4,0x05,0xb2,0x00,0x13,0x00,0x50,0x40,0x0f,0x0a,0x0c,0x01,0x03,0x00,0x02,0x01,0x10,0x05,0x0c,0x40,0x0c,0x00,0x4d,0x02,0xb8,0xff,0xc0,0x40,0x1b,0x0c,0x00,0x4d,0x13,0xc4,0x00,0x00,0x15,0x09,0xc4,0x40,0x0a,0x13,0x0d,0x0d,0x07,0xda,0x59,0x0d,0x11,0x40,0x03, 0x11,0xda,0x59,0x09,0x03,0x00,0x2f,0xc6,0x2b,0x00,0x1a,0x18,0x10,0xcc,0x2b,0x00,0x18,0x10,0xc6,0x01,0x2f,0x1a,0xe9,0x12,0x39,0x2f,0xe9,0x31,0x30,0x2b,0x2b,0x5f,0x5e,0x5d,0x5f,0x5d,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x02,0xa4,0x60,0x52,0x47,0x5b,0x4d,0x2a, 0x58,0x5e,0x60,0x56,0x41,0x54,0x4a,0x36,0x54,0x05,0xb2,0x69,0x85,0x34,0x2b,0x71,0x6b,0x81,0x34,0x2c,0x74,0x00,0x00,0x01,0x00,0x3e,0x04,0xc2,0x02,0x3a,0x05,0x2f,0x00,0x03,0x00,0x11,0xb6,0x00,0x01,0x01,0x02,0xe2,0x59,0x01,0x00,0x2f,0x2b,0x01,0x18,0x2f,0x2f,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0x3a,0xfe,0x04,0x01,0xfc,0x04, 0xc2,0x6d,0x00,0x01,0x00,0x25,0x04,0xc2,0x02,0x4a,0x05,0xbe,0x00,0x0c,0x00,0x2f,0x40,0x17,0x0c,0xc4,0x0f,0x00,0x01,0x0b,0x03,0x00,0x00,0x0e,0x07,0xc4,0x40,0x06,0x0c,0x06,0x03,0x80,0x03,0x09,0xdb,0x59,0x03,0x00,0x2f,0x2b,0x00,0x1a,0x18,0x10,0xdc,0xc4,0x01,0x2f,0x1a,0xe9,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0xe9,0x31,0x30,0x01, 0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x02,0x4a,0x0a,0x9d,0x70,0x75,0x94,0x05,0x64,0x0c,0xa0,0x44,0x61,0x0a,0x05,0xbe,0x71,0x8b,0x8a,0x72,0x9b,0x54,0x47,0x00,0x00,0x01,0x00,0x6c,0x04,0xc2,0x01,0x31,0x05,0x85,0x00,0x0b,0x00,0x12,0xb7,0x09,0xc0,0x03,0x00,0x06,0xc1,0x5b,0x00,0x00,0x2f,0x2b,0x01,0x18, 0x2f,0xe1,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xcf,0x28,0x3b,0x3a,0x29,0x29,0x39,0x39,0x04,0xc2,0x39,0x2a,0x28,0x38,0x37,0x29,0x29,0x3a,0x00,0x02,0x00,0x52,0x04,0x98,0x01,0xee,0x06,0x1c,0x00,0x0b,0x00,0x16,0x00,0x4f,0x40,0x31,0x04,0x0b,0x01,0x04,0x07,0x01,0x0b,0x05,0x01,0x0b,0x01,0x01, 0x10,0x14,0xc4,0x40,0x00,0x09,0x50,0x09,0xa0,0x09,0xb0,0x09,0x04,0x1c,0x03,0x09,0xc0,0x0f,0xc4,0x40,0x03,0x06,0x0c,0xc5,0x59,0x06,0x40,0x09,0x0d,0x48,0x06,0x00,0x00,0x11,0xc5,0x59,0x00,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc4,0x2b,0x2b,0x01,0x18,0x2f,0x1a,0xe9,0x1a,0xdc,0x5f,0x5e,0x5d,0x1a,0xe9,0x31,0x30,0x5e,0x5d,0x5d,0x5d, 0x5d,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x1c,0x57,0x73,0x76,0x5b,0x59,0x72,0x7a,0x58,0x30,0x40,0x70,0x32,0x42,0x42,0x04,0x98,0x69,0x55,0x5a,0x6c,0x6c,0x54,0x54,0x70,0x01,0x33,0x41,0x30,0x70,0x40,0x30,0x31,0x40,0x00,0x00,0x01,0x00,0x33, 0xfe,0x50,0x01,0x87,0x00,0x00,0x00,0x12,0x00,0x5d,0x40,0x0c,0x03,0x12,0x01,0x03,0x00,0x01,0x01,0x10,0x05,0x09,0xc2,0x00,0xb8,0xff,0xc0,0x40,0x0d,0x0b,0x0f,0x48,0x00,0x10,0x05,0x40,0x0d,0x02,0x07,0xc5,0x59,0x02,0xb8,0xff,0xc0,0x40,0x1a,0x09,0x0f,0x48,0x02,0x10,0x0f,0x0b,0x1f,0x0b,0x2f,0x0b,0x03,0x09,0x03,0x10,0x0b,0xc3, 0x59,0x10,0x40,0x0a,0x0e,0x48,0x10,0x0e,0x12,0x00,0x3f,0xc5,0x2b,0x2b,0x00,0x5f,0x5e,0x5d,0x18,0x10,0xc4,0x2b,0x2b,0x01,0x18,0x2f,0x1a,0xce,0xcd,0xd4,0x2b,0xe1,0x30,0x31,0x5f,0x5e,0x5d,0x5f,0x5d,0x01,0x14,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35,0x33,0x15,0x32,0x16,0x01,0x87,0xfe,0xed,0x26,0x1b, 0x2b,0x1b,0x8d,0x81,0x0a,0x1f,0x6c,0x58,0x67,0xff,0x00,0xb0,0x02,0x5a,0x06,0x5a,0x4e,0x04,0xb6,0x68,0x50,0x00,0x00,0x02,0x00,0x40,0x04,0xc2,0x02,0x87,0x06,0x00,0x00,0x03,0x00,0x07,0x00,0x4d,0x40,0x30,0x00,0x0e,0x02,0x28,0x0d,0x06,0x4d,0x02,0x18,0x0c,0x06,0x4d,0x02,0x18,0x0b,0x06,0x4d,0x02,0x30,0x0a,0x06,0x4d,0x02,0x30, 0x09,0x06,0x4d,0x0f,0x02,0x01,0x10,0x03,0x02,0x06,0x80,0x06,0x04,0x42,0x04,0x70,0x06,0x01,0x06,0x03,0x02,0x07,0x80,0x06,0x00,0x2f,0x1a,0xcd,0x39,0x39,0x01,0x2f,0x5d,0xcd,0x2b,0x01,0x1a,0x18,0x10,0xdc,0x5f,0x5e,0x5d,0x2b,0x2b,0x2b,0x2b,0x2b,0xe9,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0x87,0xf5,0x61,0xd1, 0x72,0xf0,0x60,0xce,0x06,0x00,0xfe,0xc2,0x01,0x3e,0xfe,0xc2,0x01,0x3e,0x00,0x01,0x00,0x3e,0xfe,0x70,0x01,0x52,0x00,0x00,0x00,0x0e,0x00,0x24,0x40,0x12,0x0f,0x0b,0x01,0x10,0x04,0x00,0x06,0x06,0x02,0xc2,0x0c,0x09,0x04,0xe2,0x59,0x09,0x0e,0x12,0x00,0x3f,0x2f,0x2b,0x01,0x18,0x2f,0xf1,0xc2,0x2f,0xc6,0x31,0x30,0x5f,0x5e,0x5d, 0x21,0x06,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x01,0x52,0x96,0x44,0x1e,0x1a,0x1e,0x34,0x4c,0x5c,0x9d,0x8d,0x52,0x46,0x0d,0x6b,0x0d,0x50,0x46,0x7a,0x80,0x00,0x01,0x00,0x66,0x04,0xc2,0x02,0x98,0x06,0x0c,0x00,0x06,0x00,0x1c,0xb3,0x00,0x00,0x08,0x03,0xb8,0xff,0xc0,0xb6,0x10,0x00,0x4d,0x03,0x03, 0x80,0x02,0x00,0x2f,0x1a,0xcd,0x01,0x2f,0x2b,0x11,0x39,0x2f,0x31,0x30,0x01,0x03,0x23,0x03,0x33,0x17,0x37,0x02,0x98,0xd6,0x84,0xd8,0x73,0xa4,0xa4,0x06,0x0c,0xfe,0xb6,0x01,0x4a,0xe5,0xe5,0x00,0x00,0x01,0x00,0x21,0x00,0x00,0x03,0xa4,0x05,0x9a,0x00,0x0d,0x00,0xc5,0x40,0x16,0x0f,0x0a,0x01,0x00,0x04,0x01,0x10,0x05,0x0b,0x02, 0x03,0x0a,0x03,0x08,0x05,0x04,0x09,0x04,0x0a,0x0a,0x0c,0x00,0xb8,0xff,0xf0,0xb3,0x10,0x06,0x4d,0x00,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xf0,0xb3,0x0b,0x06,0x4d,0x00,0xb8,0xff,0xe8,0xb3,0x0a,0x06,0x4d,0x00,0xb8,0xff,0xe0,0xb3,0x09,0x06,0x4d,0x00,0xb8,0xff,0xc0,0x40, 0x1b,0x0a,0x1f,0x48,0x00,0x00,0x0f,0x03,0x08,0x05,0x0c,0x06,0x0d,0x06,0x4d,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x7e,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf2,0x40,0x19,0x0c,0x06,0x4d,0x01,0x06,0x0b,0x06,0x4d,0x01,0x04,0x03,0x0a,0x09,0x03,0x09,0x03,0x00,0x06,0x03,0x00,0x0d,0x91,0x59, 0x00,0x12,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x33,0x11,0x33,0x01,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0xc6,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x31,0x30,0x10,0x87,0x04,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x00,0x5f,0x5e,0x5d,0x5d,0x21,0x21,0x11,0x07,0x35,0x37,0x11, 0x33,0x11,0x25,0x15,0x05,0x11,0x21,0x03,0xa4,0xfd,0x18,0x9b,0x9b,0xa8,0x01,0x48,0xfe,0xb8,0x02,0x40,0x02,0x23,0x61,0x98,0x60,0x02,0xe0,0xfd,0x89,0xcb,0x9a,0xc8,0xfe,0x0c,0x00,0x01,0x00,0x16,0x00,0x00,0x02,0x12,0x05,0xec,0x00,0x0b,0x00,0x62,0x40,0x3c,0x0a,0x07,0x06,0x0b,0x06,0x04,0x01,0x05,0x00,0x00,0x00,0x02,0x05,0x0a, 0x07,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06,0x4d,0x02,0x84,0x70,0x03,0x01,0x03,0x08,0x0d,0x06,0x4d,0x03,0x02,0x0c,0x06,0x4d,0x03,0x06,0x05,0x00,0x0b,0x0b,0x05,0x02,0x09,0x00,0x02,0x15,0x40,0x0d,0x01,0x5d,0x00,0x3f,0x3f,0x12,0x39,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b, 0x2b,0x2b,0x39,0x39,0xc6,0x10,0xc2,0x2f,0x31,0x30,0x87,0x04,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x01,0x07,0x11,0x23,0x11,0x07,0x35,0x37,0x11,0x33,0x11,0x37,0x02,0x12,0xae,0xa4,0xaa,0xaa,0xa4,0xae,0x03,0x2b,0x7b,0xfd,0x50,0x02,0x42,0x77,0x9d,0x77,0x03,0x0d,0xfd,0x62,0x7a,0x00,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x07,0x6a, 0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xa2,0x01,0x5e,0x00,0x14,0xb4,0x01,0x38,0x05,0x26,0x01,0xb8,0xff,0xf4,0xb4,0x39,0x36,0x13,0x2c,0x25,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x06,0x0c,0x02,0x26,0x00,0x56,0x00,0x00,0x01,0x06,0x00,0xe0,0x12,0x00,0x00,0x14,0xb4,0x01,0x31,0x11, 0x26,0x01,0xb8,0xff,0xec,0xb4,0x32,0x2f,0x0f,0x16,0x25,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x07,0x67,0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xec,0x01,0x5b,0x00,0x13,0x40,0x0b,0x01,0x05,0x0f,0x0f,0x08,0x09,0x25,0x01,0x0c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x21,0x00,0x00,0x03,0x70,0x06,0x0c,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x06,0x00,0xe0,0x76,0x00,0x00,0x13,0x40,0x0b,0x01,0x0e,0x0f,0x0f,0x08,0x09,0x25,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0xac,0xfe,0x1e,0x01,0x40,0x06,0x1e,0x00,0x03,0x00,0x07,0x00,0x21,0x40,0x0f,0x01,0x00,0x04,0xca, 0x05,0x00,0x0e,0x40,0x03,0x04,0x07,0x42,0x07,0x04,0x1c,0x00,0x3f,0xcd,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x01,0x2f,0xe1,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x33,0x11,0x23,0x11,0x33,0x01,0x40,0x94,0x94,0x94,0x94,0x02,0xcb,0x03,0x53,0xf8,0x00,0x03,0x54,0x00,0x00,0x02,0x00,0x1c,0x00,0x00,0x05,0x3e,0x05,0x9a,0x00,0x0b,0x00,0x17, 0x00,0xaa,0x40,0x38,0x00,0x07,0x01,0x00,0x07,0x01,0x10,0x05,0x10,0x0d,0x01,0x04,0x04,0x01,0x91,0x59,0x04,0x05,0x00,0x04,0x91,0x2b,0x30,0x05,0x0c,0x91,0x59,0x05,0x03,0x00,0x11,0x91,0x59,0x00,0x12,0x0f,0x0f,0x00,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x7d,0x15,0xb8,0xff,0xf0,0xb3, 0x0d,0x06,0x4d,0x15,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x15,0xb8,0xff,0xea,0x40,0x1b,0x0b,0x06,0x4d,0x15,0x15,0x19,0x02,0x0d,0x04,0x11,0x06,0x0d,0x06,0x4d,0x11,0x06,0x0c,0x06,0x4d,0x11,0x06,0x0b,0x06,0x4d,0x11,0x7e,0x00,0xb8,0xff,0xf6,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0xe1, 0x2b,0x2b,0x2b,0x39,0x39,0xce,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x20,0x11,0x10,0x00,0x21,0x03,0x11,0x21,0x15,0x21,0x11,0x33,0x20, 0x00,0x11,0x10,0x21,0xbc,0xa0,0xa0,0x01,0x8c,0x02,0xf6,0xfe,0x5b,0xfe,0x9f,0xd4,0x01,0x50,0xfe,0xb0,0xd6,0x01,0x1a,0x01,0x3a,0xfd,0xb6,0x02,0x81,0x9b,0x02,0x7e,0xfd,0x45,0xfe,0xb2,0xfe,0x6f,0x05,0x02,0xfe,0x1a,0x9b,0xfe,0x17,0x01,0x2e,0x01,0x15,0x02,0x27,0x00,0x00,0x02,0x00,0x60,0xff,0xea,0x04,0x18,0x05,0xf4,0x00,0x1a, 0x00,0x25,0x00,0xfa,0x40,0x17,0x00,0x0e,0x01,0x10,0x06,0x0b,0x0b,0x0a,0x06,0x06,0x07,0x05,0x0c,0x05,0x0e,0x0e,0x0f,0x03,0x03,0x02,0x04,0x0d,0x06,0xb8,0xff,0xf0,0xb3,0x0b,0x06,0x4d,0x03,0xb8,0xff,0xc0,0xb3,0x0b,0x06,0x4d,0x03,0xb8,0xff,0xc0,0xb3,0x0a,0x06,0x4d,0x03,0xb8,0xff,0xc0,0x40,0x46,0x09,0x06,0x4d,0x05,0x04,0x30, 0x09,0x12,0x48,0x04,0x04,0x19,0x0d,0x0c,0x09,0x00,0x01,0x1b,0x19,0x1b,0x95,0x59,0x19,0x10,0x13,0x21,0x95,0x59,0x13,0x16,0x0e,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0d,0x06,0x4d,0x0d,0x0d,0x10,0x05,0x01,0x24,0x0f,0x08,0x01,0x08,0x08,0x16,0x10,0x04,0x0d,0x06,0x4d,0x10,0x04,0x0c,0x06,0x4d,0x10,0x04,0x0b,0x06,0x4d,0x10,0x83,0x24, 0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x24,0xb8,0xff,0xe3,0x40,0x2a,0x0b,0x06,0x4d,0x24,0x24,0x27,0x1e,0x0a,0x0d,0x06,0x4d,0x1e,0x0a,0x0c,0x06,0x4d,0x1e,0x0a,0x0b,0x06,0x4d,0x1e,0x83,0x16,0x10,0x0d,0x06,0x4d,0x16,0x0c,0x0c,0x06,0x4d,0x16,0x15,0x0b,0x06,0x4d,0x16,0x2f,0x27,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b, 0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x12,0x39,0xc6,0x11,0x39,0x2f,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0xc6,0x32,0x12,0x39,0x2f,0x2b,0x33,0x01,0x2b,0x2b,0x2b,0x2b,0x31,0x30,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x01,0x5f,0x5e,0x5d,0x01,0x37, 0x26,0x27,0x05,0x27,0x25,0x26,0x27,0x33,0x16,0x17,0x25,0x17,0x05,0x00,0x11,0x14,0x00,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x07,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x10,0x03,0x12,0x04,0x5a,0x6c,0xfe,0xd5,0x33,0x01,0x0e,0x76,0x92,0xdd,0x4b,0x61,0x01,0x21,0x37,0xfe,0xf8,0x01,0x47,0xfe,0xfe,0xde,0xde,0xfa,0x01, 0x04,0xdc,0x7b,0x75,0x94,0xaa,0xa6,0x94,0x8b,0xa3,0x03,0xc8,0x03,0xa2,0x68,0x97,0x62,0x83,0x69,0x60,0x34,0x54,0x90,0x5e,0x82,0xfe,0xcd,0xfe,0x2d,0xf0,0xfe,0xcc,0x01,0x18,0xf2,0xf3,0x01,0x2f,0x88,0xd9,0xbb,0xb5,0xd3,0xd8,0xb4,0x01,0x90,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x07,0x66,0x02,0x26,0x00,0x3c,0x00,0x00, 0x01,0x07,0x00,0x8e,0x01,0x33,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x30,0x0f,0x11,0x05,0x00,0x25,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x0a,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xee,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x33,0x16,0x18,0x0c,0x00, 0x25,0x01,0x17,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x0c,0x00,0x14,0x00,0x7b,0x40,0x20,0x00,0x08,0x01,0x10,0x06,0x05,0x0d,0x91,0x59,0x00,0x05,0x10,0x05,0x02,0x0c,0x03,0x05,0x0c,0x0e,0x91,0x59,0x0c,0x05,0x0c,0x03,0x02,0x12,0x03,0x03,0x09,0x7d,0x12,0xb8,0xff, 0xf0,0x40,0x1a,0x0d,0x06,0x4d,0x12,0x12,0x16,0x05,0x0e,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x7e,0x02,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf4,0x40,0x09,0x0c,0x06,0x4d,0x02,0x04,0x0b,0x06,0x4d,0x02,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x12,0x39,0x2f, 0x2b,0xe9,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2b,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x01,0x11,0x23,0x11,0x33,0x15,0x33,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0xa8,0xa8,0xe2,0xe8,0xfb,0xfe,0xe5,0xf0,0xba,0xb0,0xad,0xb8,0xfe,0xb0,0x01,0x3e,0xfe,0xc2, 0x05,0x9a,0xe2,0xdf,0xcd,0xcc,0xfe,0xfe,0x02,0xe3,0xfd,0xb4,0x9c,0x91,0x01,0x1f,0x00,0x02,0x00,0xa6,0xfe,0x29,0x04,0x54,0x05,0xec,0x00,0x10,0x00,0x1d,0x00,0x9c,0x40,0x2b,0x00,0x0a,0x01,0x10,0x06,0x03,0x1b,0x01,0x15,0x0f,0x15,0x95,0x59,0x0f,0x16,0x04,0x00,0x06,0x1b,0x09,0x1b,0x95,0x59,0x09,0x10,0x0c,0x06,0x0d,0x06,0x4d, 0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x06,0x0b,0x06,0x4d,0x0c,0x83,0x18,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x18,0xb8,0xff,0xf2,0xb3,0x0c,0x06,0x4d,0x18,0xb8,0xff,0xe3,0x40,0x1a,0x0b,0x06,0x4d,0x18,0x18,0x1f,0x06,0x12,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06,0x4d,0x02,0x84,0x03,0xb8,0xff,0xf8,0x40, 0x11,0x0d,0x06,0x4d,0x03,0x02,0x0c,0x06,0x4d,0x03,0x01,0x0b,0x06,0x4d,0x03,0x2f,0x1f,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x25,0x23,0x11,0x23, 0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4e,0x04,0xa4,0xa4,0x04,0x79,0xe9,0xc6,0xde,0xfa,0xd9,0xc7,0x70,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0x94,0xfd,0x95,0x07,0xc3,0xfd,0x60,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x02, 0x49,0x8f,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0xc7,0x00,0x00,0x01,0x00,0xe8,0x02,0x12,0x04,0x94,0x02,0x98,0x00,0x03,0x00,0x30,0x40,0x0b,0x02,0x01,0xbe,0x59,0x0f,0x02,0x01,0x0d,0x03,0x02,0x00,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xe0,0x40,0x09,0x0c,0x06,0x4d,0x04,0x05,0x01,0x00,0xff,0x3a,0x2b,0x01,0x2b,0x2b,0x00, 0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x04,0x94,0xfc,0x54,0x03,0xac,0x02,0x12,0x86,0x00,0x00,0x01,0x01,0x0c,0x00,0xa4,0x04,0x6e,0x04,0x06,0x00,0x0b,0x00,0x1d,0xb6,0x0b,0x4f,0x05,0x01,0x05,0x02,0x08,0xb8,0xff,0xd8,0xb3,0x0c,0x06,0x4d,0x08,0x19,0x2f,0x2b,0x18,0xc4,0x00,0x19,0x2f,0x5d,0x18,0xc4,0x31, 0x30,0x01,0x07,0x01,0x01,0x27,0x01,0x01,0x37,0x01,0x01,0x17,0x01,0x04,0x6e,0x5e,0xfe,0xac,0xfe,0xae,0x5e,0x01,0x54,0xfe,0xac,0x5e,0x01,0x52,0x01,0x54,0x5e,0xfe,0xac,0x01,0x02,0x5e,0x01,0x54,0xfe,0xac,0x5e,0x01,0x52,0x01,0x54,0x5e,0xfe,0xac,0x01,0x54,0x5e,0xfe,0xac,0x00,0x00,0x01,0x00,0x50,0x02,0x48,0x01,0xc2,0x05,0xb0, 0x00,0x0c,0x00,0x17,0x40,0x0a,0x0c,0xcc,0x04,0x00,0x0c,0x28,0x05,0x04,0x0b,0x27,0x00,0x3f,0xdd,0xcd,0x3f,0x01,0x2f,0xce,0xed,0x30,0x31,0x01,0x11,0x06,0x06,0x07,0x35,0x3e,0x03,0x37,0x33,0x11,0x01,0x40,0x39,0x78,0x3f,0x26,0x46,0x48,0x4c,0x2c,0x46,0x02,0x48,0x02,0xc2,0x2e,0x47,0x1b,0x87,0x0d,0x22,0x2b,0x35,0x20,0xfc,0x98, 0x00,0x01,0x00,0x68,0x02,0x48,0x02,0x92,0x05,0xae,0x00,0x1f,0x00,0x3c,0x40,0x24,0x1f,0x16,0xcc,0x09,0x09,0x21,0x1d,0xcc,0x0e,0x02,0x0f,0x0e,0x2b,0x1d,0x3b,0x1d,0x4b,0x1d,0x9b,0x1d,0xab,0x1d,0xbb,0x1d,0x06,0x1d,0x09,0x01,0x0c,0xe6,0x11,0x27,0x1f,0xe6,0x01,0x28,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x5d,0xcc,0x32,0x01, 0x2f,0x33,0xed,0x12,0x39,0x2f,0xed,0x32,0x30,0x31,0x01,0x21,0x35,0x34,0x3e,0x04,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x15,0x15,0x21,0x02,0x92,0xfd,0xd6,0x3b,0x59,0x68,0x59,0x3b,0x4b,0x3f,0x77,0x61,0x53,0x98,0x38,0x5e,0x44,0x26,0x39,0x56,0x64,0x56,0x39,0x01,0x93,0x02,0x48,0x52, 0x3d,0x61,0x54,0x4b,0x50,0x5a,0x38,0x3a,0x40,0x66,0x95,0x4c,0x22,0x3f,0x58,0x37,0x4a,0x73,0x5c,0x48,0x3d,0x37,0x1c,0x0b,0x00,0x01,0x00,0x81,0x02,0x33,0x02,0x8e,0x05,0xae,0x00,0x20,0x00,0x61,0x40,0x35,0x00,0x16,0x01,0x10,0x05,0x19,0x09,0x0a,0x0a,0x09,0xe6,0x59,0x0a,0x0a,0x03,0x14,0x0f,0x11,0x1f,0x11,0x02,0x0f,0x03,0x11, 0x0f,0x14,0x0f,0xe6,0x59,0x14,0x27,0x01,0x03,0x1f,0x03,0xe6,0x59,0x1f,0x29,0x19,0x0a,0x0d,0xcd,0x17,0x17,0x1c,0xcc,0x06,0x06,0x22,0x0a,0x11,0x00,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x39,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x11,0x12, 0x00,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x81,0x67,0x72,0x50,0x5c,0xdb,0x54,0x50,0xc5,0x90,0x5e,0x5c,0x57,0x7e,0x71,0x86,0x91,0xb1,0xaa,0x8e,0x89,0x02,0x68,0x8e, 0x4c,0x4b,0x40,0x8d,0x76,0x86,0x77,0x45,0x8b,0x33,0x77,0x60,0x97,0x36,0x04,0x2a,0xa0,0x75,0x94,0x00,0xff,0xff,0x00,0x50,0x00,0x00,0x06,0xd4,0x05,0xb0,0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x07,0x00,0xf1,0x04,0x42,0xfd,0xb9,0x00,0x07,0xb2,0x02,0x11,0x2c,0x00,0x3f,0x35,0x00,0xff,0xff, 0x00,0x50,0x00,0x00,0x06,0xaa,0x05,0xb0,0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x07,0x02,0x38,0x04,0x00,0xfd,0xb8,0x00,0x09,0xb3,0x03,0x02,0x14,0x2c,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x81,0x00,0x00,0x06,0xeb,0x05,0xae,0x00,0x26,0x00,0xf2,0x00,0x00,0x00,0x27,0x00,0xbc,0x03,0x06, 0x00,0x00,0x01,0x07,0x02,0x38,0x04,0x41,0xfd,0xb8,0x00,0x09,0xb3,0x03,0x02,0x28,0x2c,0x00,0x3f,0x35,0x35,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x03,0x94,0x05,0x9a,0x00,0x11,0x00,0x80,0x40,0x3e,0x10,0x01,0x04,0x07,0x07,0x04,0x91,0x59,0x07,0x07,0x0c,0x02,0x0c,0x0f,0x91,0x59,0x0c,0x09,0x02,0x0c,0x91,0x2b,0x30,0x09,0x0a,0x91, 0x59,0x09,0x03,0x02,0x12,0x0d,0x0d,0x09,0x09,0x13,0x03,0x00,0x00,0x07,0x0c,0x10,0x03,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06,0x4d,0x02,0x7e,0x05,0x03,0xb8,0xff,0xfb,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf6,0x40,0x09,0x0c,0x06,0x4d,0x03,0x0a,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xce,0xf1, 0x2b,0x2b,0x2b,0x17,0x39,0xc2,0x2f,0x11,0x12,0x39,0x2f,0x33,0x2f,0x00,0x3f,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x15,0x33,0x02,0x58,0xf4,0xa8,0xa0,0xa0,0x02,0xd8,0xfd,0xd0, 0x02,0x06,0xfd,0xfa,0xf4,0x01,0x16,0xfe,0xea,0x01,0x16,0x9c,0x03,0xe8,0x98,0xfe,0x10,0x97,0xc9,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0xec,0x07,0x19,0x02,0x26,0x00,0x2a,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0xe2,0x01,0x5b,0x00,0x16,0xb9,0x00,0x01,0xff,0xda,0x40,0x09,0x1d,0x23,0x0d,0x08,0x25,0x01,0x1d,0x05,0x26,0x00,0x2b, 0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x05,0xbe,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x1a,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x17,0x2c,0x26,0x20,0x17,0x25,0x02,0x29,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xad,0x00,0x00,0x01,0x72,0x06,0xe2,0x02,0x26,0x00,0x2c, 0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0x41,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x07,0x0d,0x02,0x03,0x25,0x01,0x04,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x79,0xfe,0x50,0x03,0xde,0x05,0xb2,0x02,0x26,0x00,0x36,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x76,0x00,0x00,0xff,0xff,0x00,0x68,0xfe,0x50,0x03,0x0f, 0x04,0x18,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x03,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x07,0x66,0x02,0x26,0x00,0x26,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xd5,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x3e,0x17,0x19,0x10,0x0b,0x25,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x60,0xff,0xe8,0x03,0x62,0x06,0x0a,0x02,0x26,0x00,0x46,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x23,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x24,0x17,0x19,0x10,0x0a,0x25,0x01,0x18,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x07,0x68,0x02,0x26,0x00,0x26,0x00,0x00,0x01,0x07,0x00,0xe0, 0x01,0x86,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x36,0x1b,0x1b,0x10,0x0b,0x25,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x06,0x0c,0x02,0x26,0x00,0x46,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xc2,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x0a,0x1b,0x1b,0x10,0x0b,0x25,0x01,0x18,0x11, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x98,0x05,0xec,0x00,0x18,0x00,0x25,0x00,0xcb,0x40,0x55,0x0f,0x06,0x01,0x10,0x05,0x24,0x18,0x0c,0x00,0x4d,0x18,0x15,0x0f,0x12,0x12,0x0f,0x96,0x59,0x0f,0x12,0x1f,0x12,0x2f,0x12,0x03,0x09,0x03,0x12,0x12,0x0b,0x14,0x00,0x0d,0x1d,0x0b,0x1d,0x95,0x59, 0x0b,0x10,0x02,0x23,0x05,0x23,0x95,0x59,0x05,0x16,0x00,0x15,0x10,0x10,0x01,0x08,0x17,0x17,0x0f,0x12,0x15,0x18,0x19,0x05,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0x05,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf0,0x40,0x2a,0x0b,0x06,0x4d,0x01, 0x01,0x27,0x20,0x06,0x0d,0x06,0x4d,0x20,0x06,0x0c,0x06,0x4d,0x20,0x06,0x0b,0x06,0x4d,0x20,0x83,0x08,0x10,0x0d,0x06,0x4d,0x08,0x0e,0x0c,0x06,0x4d,0x08,0x1a,0x0b,0x06,0x4d,0x08,0x2f,0x27,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0x17,0x39,0xca,0x2f,0x11,0x12,0x39, 0x2f,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x21,0x35,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x03,0x35,0x34,0x26, 0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0xa4,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5,0xd0,0x63,0x04,0xfe,0xb5,0x01,0x4b,0xa4,0x88,0x88,0xa4,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x88,0xac,0xae,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x01,0x40,0x86,0xb4,0xb4,0x86,0xfd,0x1d,0x97,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0xc6, 0x00,0x01,0x00,0x00,0x05,0x74,0x03,0x52,0x05,0xec,0x00,0x03,0x00,0x10,0xb7,0x02,0x01,0xd9,0x59,0x02,0x00,0x00,0x01,0x2f,0x2f,0x00,0x3f,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x52,0xfc,0xae,0x03,0x52,0x05,0x74,0x78,0x00,0xff,0xff,0x00,0x70,0x01,0xfe,0x01,0x50,0x02,0xdf,0x02,0x06,0x00,0xc3,0x00,0x00,0xff,0xff,0x00,0x16, 0x00,0x00,0x05,0x12,0x07,0x1b,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x5a,0x01,0x5d,0x00,0x16,0xb9,0x00,0x02,0xff,0xfb,0x40,0x09,0x13,0x19,0x06,0x07,0x25,0x02,0x13,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0xbe,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xda, 0x00,0xdb,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xf2,0x40,0x09,0x26,0x20,0x10,0x14,0x25,0x02,0x23,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x16,0xfe,0x70,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x07,0x00,0xdf,0x03,0x79,0x00,0x00,0xff,0xff,0x00,0x5a,0xfe,0x70,0x03,0x83,0x04,0x18,0x02,0x26, 0x00,0x44,0x00,0x00,0x00,0x07,0x00,0xdf,0x02,0x00,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x3e,0x07,0x68,0x02,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x2a,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x04,0x13,0x10,0x01,0x0d,0x25,0x02,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8, 0x05,0xb3,0x05,0xec,0x00,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x01,0x9c,0x03,0xb7,0x06,0x63,0x00,0x12,0x40,0x0a,0x02,0x21,0x00,0x02,0x82,0x20,0x20,0x10,0x10,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0x00,0x1c,0x00,0x00,0x05,0x3e,0x05,0x9a,0x02,0x06,0x00,0xe8,0x00,0x00,0xff,0xff,0x00,0xbc,0xfe,0x70,0x03,0xb4,0x05,0x9a, 0x02,0x26,0x00,0x28,0x00,0x00,0x00,0x07,0x00,0xdf,0x02,0x0f,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x70,0x03,0xdd,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x00,0x07,0x00,0xdf,0x01,0xa1,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x68,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xb1,0x01,0x5c,0x00,0x16, 0xb9,0x00,0x01,0xff,0xf8,0x40,0x09,0x0f,0x0c,0x02,0x0b,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x0c,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xb4,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x1c,0x1b,0x16,0x0f,0x25,0x02,0x1c,0x11,0x26,0x00,0x2b,0x35, 0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x07,0x66,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x4c,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x11,0x08,0x06,0x03,0x05,0x3e,0x01,0x08,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x8e,0x00,0x00,0x02,0x13,0x07,0xbb,0x02,0x26,0x00,0x4f, 0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0x07,0x01,0xb1,0x00,0x16,0xb9,0x00,0x01,0xff,0xd5,0x40,0x09,0x06,0x05,0x02,0x03,0x25,0x01,0x06,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x01,0x9c,0x01,0x8d,0x06,0x11,0x00,0x14,0xb3,0x01,0x09,0x03, 0x01,0xb8,0xff,0xe5,0xb4,0x06,0x06,0x05,0x05,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0xc3,0x05,0xec,0x00,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x01,0x9c,0x00,0xc7,0x06,0x5d,0x00,0x12,0x40,0x0a,0x01,0x07,0x00,0x01,0x58,0x06,0x06,0x03,0x03,0x25,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0x00,0xbc, 0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x11,0xfd,0xd8,0x00,0x0e,0xb9,0x00,0x01,0xff,0x9e,0xb4,0x0f,0x0f,0x05,0x05,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0x87,0x05,0xec,0x00,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x56,0xfd,0xd8,0x00,0x0b,0xb6,0x01, 0x78,0x07,0x07,0x00,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x66,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xe2,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x15,0x17,0x0b,0x12,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8, 0x06,0x0a,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x38,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xec,0x40,0x09,0x14,0x16,0x04,0x0f,0x25,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x68,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x7e,0x01,0x5c, 0x00,0x16,0xb9,0x00,0x01,0xff,0xe4,0x40,0x09,0x19,0x19,0x0b,0x12,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x0c,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xda,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x08,0x18,0x18,0x0b,0x02,0x25,0x01,0x15,0x11,0x26,0x00, 0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x5e,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xde,0x01,0xe1,0x01,0x5e,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfc,0x40,0x0a,0x1a,0x1a,0x06,0x06,0x25,0x03,0x02,0x1e,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8, 0x04,0x50,0x06,0x00,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xde,0x01,0x3f,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x06,0x1a,0x1a,0x06,0x06,0x25,0x03,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xc0,0x07,0x66,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x00,0x8e, 0x01,0x5f,0x01,0x5c,0x00,0x08,0xb3,0x02,0x2a,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0xbc,0x06,0x0a,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xa4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x20,0x13,0x12,0x09,0x09,0x25,0x01,0x13,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc, 0x00,0x00,0x04,0xc0,0x07,0x68,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xe3,0x01,0x5c,0x00,0x08,0xb3,0x02,0x2a,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x97,0x00,0x00,0x02,0xc9,0x06,0x0c,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x06,0x00,0xe0,0x31,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x13,0x12,0x08,0x10,0x25,0x01, 0x13,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x07,0x65,0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x29,0x01,0x5b,0x00,0x08,0xb3,0x01,0x38,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x06,0x0a,0x02,0x26,0x00,0x56,0x00,0x00,0x01,0x07,0x00,0x8e, 0x00,0xbe,0x00,0x00,0x00,0x08,0xb3,0x01,0x31,0x11,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x29,0xfe,0x50,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x00,0xdd,0x01,0x75,0x00,0x00,0x00,0x0b,0xb6,0x01,0x16,0x16,0x0c,0x06,0x4d,0x16,0x11,0x2b,0x35,0x00,0xff,0xff,0x00,0x2b,0xfe,0x50,0x02,0x9a,0x05,0x2f,0x02,0x26, 0x00,0x57,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x13,0x00,0x00,0xff,0xff,0x00,0x29,0x00,0x00,0x04,0x0c,0x07,0x68,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0x9d,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x03,0x0a,0x09,0x04,0x01,0x3e,0x01,0x0a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0x2b,0xff,0xea, 0x03,0xd3,0x05,0x72,0x00,0x14,0x00,0x18,0x00,0x71,0x40,0x31,0x18,0x80,0x17,0x07,0x14,0x14,0x12,0x95,0x02,0x16,0x0a,0x0a,0x0e,0x0b,0x06,0x95,0x40,0x07,0x0f,0x15,0x80,0x17,0x0c,0x00,0x00,0x0d,0x06,0x0d,0x06,0x0b,0x08,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x84,0x04,0xb8,0xff,0xe6, 0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf2,0xb3,0x0c,0x06,0x4d,0x04,0xb8,0xff,0xf2,0xb3,0x0b,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x32,0x33,0x32,0x2f,0x2f,0x33,0x2f,0x10,0xd6,0x1a,0xcd,0x00,0x3f,0x1a,0xed,0x33,0x32,0x33,0x2f,0x3f,0xed,0x32,0x2f,0x10,0xd4,0x1a,0xcd,0x31,0x30,0x25,0x06,0x23,0x20,0x11, 0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x01,0x03,0x23,0x13,0x02,0x81,0x3a,0x5f,0xfe,0xf3,0xb0,0xb0,0xa4,0x01,0x02,0xfe,0xfe,0x46,0x51,0x3e,0x2d,0x01,0x52,0xa6,0x7b,0x75,0x0a,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0xfd,0xbf,0x67,0x58,0x22,0x04,0xdc,0xfe,0xfc,0x01, 0x04,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0xa3,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xdc,0x01,0x8e,0x01,0x87,0x00,0x24,0xb1,0x02,0x01,0xb8,0xff,0xef,0x40,0x13,0x11,0x17,0x05,0x0d,0x25,0x02,0x01,0x00,0x0e,0x10,0x0e,0x20,0x0e,0x30,0x0e,0x04,0x0e,0x05,0x26,0x00,0x2b,0x5d,0x35,0x35,0x01,0x2b,0x35,0x35, 0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x1c,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xdc,0x01,0x18,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x15,0x1b,0x08,0x11,0x25,0x02,0x01,0x12,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x5c,0x02,0x26,0x00,0x38, 0x00,0x00,0x01,0x07,0x00,0xde,0x01,0x93,0x01,0x5c,0x00,0x45,0x40,0x12,0x01,0x10,0x0c,0x0d,0x06,0x4d,0x10,0x16,0x0c,0x06,0x4d,0x10,0x12,0x0b,0x06,0x4d,0x02,0x10,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x10,0xb8,0xff,0xf2,0xb3,0x0c,0x06,0x4d,0x10,0xb8,0xff,0xf4,0x40,0x0e,0x0b,0x06,0x4d,0x05,0x10,0x10,0x05,0x0d,0x25,0x02,0x01, 0x14,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x2b,0x2b,0x2b,0x35,0x2b,0x2b,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xde,0x01,0x05,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfd,0x40,0x0a,0x14,0x14,0x08,0x11,0x25,0x02,0x01,0x18,0x11,0x26,0x00,0x2b, 0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x07,0x67,0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x58,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xfa,0x40,0x09,0x0b,0x0b,0x08,0x09,0x3e,0x01,0x0c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x21,0x00,0x00,0x03,0x70,0x06,0x0a, 0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xc7,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x05,0x0b,0x0b,0x05,0x09,0x25,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x06,0xe1,0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x83,0x01,0x5c,0x00,0x16,0xb9,0x00, 0x01,0xff,0xed,0x40,0x09,0x0d,0x13,0x08,0x09,0x25,0x01,0x0a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x21,0x00,0x00,0x03,0x70,0x05,0x85,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x17,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x0d,0x13,0x08,0x09,0x25,0x01,0x0a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x00,0x05,0x00,0x4c,0x40,0x20,0x02,0x12,0x05,0x00,0x91,0x59,0x05,0x03,0x70,0x00,0x01,0x00,0x00,0x07,0x02,0x06,0x0d,0x06,0x4d,0x02,0x06,0x0c,0x06,0x4d,0x02,0x06,0x0b,0x06,0x4d,0x02,0x7e,0x03,0xb8,0xff,0xf6,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf2,0x40,0x09,0x0c, 0x06,0x4d,0x03,0x04,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x03,0xa4,0xfd,0xc1,0xa9,0x02,0xe8,0x04,0xfe,0xfb,0x02,0x05,0x9a,0x00,0x00,0x03,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x17,0x00,0x1b, 0x00,0xb0,0x40,0x18,0x1a,0x19,0x91,0x59,0x1a,0x06,0x00,0x1a,0x91,0x2b,0x30,0x06,0x0c,0x91,0x59,0x06,0x04,0x00,0x12,0x91,0x59,0x00,0x13,0x18,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x18,0xb8,0xff,0xd0,0xb3,0x0b,0x06,0x4d,0x19,0xb8,0xff,0xe8,0x40,0x1b,0x0b,0x06,0x4d,0x0f,0x15,0x19,0x18,0xff,0x3a,0x09,0x06,0x0d,0x06,0x4d,0x09, 0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x7d,0x15,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x15,0xb8,0xff,0xee,0xb6,0x0c,0x06,0x4d,0x30,0x15,0x01,0x15,0xb8,0xff,0xe0,0x40,0x27,0x0b,0x06,0x4d,0x15,0x15,0x1d,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x03,0x10,0x0d,0x06,0x4d, 0x03,0x10,0x0c,0x06,0x4d,0x03,0x18,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22, 0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x13,0x21,0x35,0x21,0x02,0xfe,0xfe,0xd0,0xfe,0x90,0x01,0x75,0x01,0x43,0x01,0x29,0x01,0x6b,0xfe,0x8d,0xfe,0xd2,0xe1,0xfe,0xe7,0x01,0x12,0xdd,0xec,0x01,0x0f,0xfe,0xf9,0x1f,0xfd,0xe7,0x02,0x19,0x18,0x01,0x8f,0x01,0x45,0x01,0x57,0x01,0x9f,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe, 0x68,0x05,0x32,0xfe,0xba,0xfe,0xf8,0xfe,0xf6,0xfe,0xbd,0x01,0x34,0x01,0x16,0x01,0x18,0x01,0x39,0xfd,0x64,0x9c,0x00,0x03,0x00,0x60,0xff,0xf1,0x05,0xa7,0x05,0xa7,0x00,0x15,0x00,0x1e,0x00,0x27,0x00,0xf6,0x40,0x1a,0x20,0x0b,0x16,0x0e,0x0e,0x16,0x91,0x59,0x1f,0x03,0x00,0x17,0x00,0x17,0x91,0x59,0x0e,0x00,0x0e,0x00,0x01,0x0d, 0x04,0x01,0x13,0x24,0xb8,0xff,0xe8,0x40,0x0b,0x0b,0x0c,0x00,0x4c,0x1b,0x18,0x0b,0x0c,0x00,0x4c,0x1b,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x1b,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1b,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x1b,0x7e,0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf0,0x40,0x25,0x0c,0x06,0x4d,0x12,0x20, 0x0b,0x06,0x4d,0x12,0x0e,0x01,0x02,0x07,0x42,0x24,0x08,0x0d,0x06,0x4d,0x24,0x08,0x0c,0x06,0x4d,0x24,0x7e,0x07,0x10,0x0d,0x06,0x4d,0x07,0x10,0x0c,0x06,0x4d,0x07,0xb8,0xff,0xe8,0x40,0x1d,0x0b,0x06,0x4d,0x07,0x07,0x28,0x0b,0x0e,0x17,0x1f,0x04,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x01, 0x7e,0x02,0xb8,0xff,0xfb,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xfd,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf8,0x40,0x0c,0x0b,0x06,0x4d,0x02,0x02,0x29,0x28,0x20,0x29,0x40,0x29,0x02,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b, 0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x25,0x15,0x23,0x35,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x33,0x35,0x33,0x15,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x03,0x11,0x23, 0x22,0x06,0x15,0x14,0x16,0x33,0x03,0x52,0x9c,0x2b,0xf9,0xfe,0xce,0x01,0x31,0xfc,0x29,0x9c,0x2a,0xfc,0x01,0x2f,0xfe,0xcc,0xf5,0x2c,0x2c,0xb6,0xcf,0xd3,0xb4,0xc6,0x29,0xb3,0xd6,0xcf,0xb8,0xba,0xc9,0xc9,0x01,0x3c,0xfc,0xf6,0x01,0x2a,0x95,0x95,0xfe,0xd5,0xf5,0xfd,0xfe,0xc5,0x03,0xca,0xfc,0xcc,0xdc,0xc4,0xb9,0xdb,0xfc,0xcc, 0x03,0x34,0xda,0xbb,0xc4,0xdb,0x00,0x02,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x04,0x18,0x00,0x19,0x00,0x26,0x01,0x02,0x40,0x0b,0x0d,0x14,0x01,0x10,0x04,0x25,0x10,0x10,0x00,0x4d,0x15,0xb8,0xff,0xf0,0xb3,0x10,0x00,0x4d,0x14,0xb8,0xff,0xd0,0xb3,0x10,0x00,0x4d,0x0e,0xb8,0xff,0xf0,0x40,0x0e,0x10,0x00,0x4d,0x08,0x10,0x10,0x00,0x4d, 0x03,0x28,0x10,0x00,0x4d,0x25,0xb8,0xff,0xe8,0x40,0x36,0x0b,0x0c,0x00,0x4c,0x1f,0x18,0x0b,0x0c,0x00,0x4c,0x1b,0x18,0x0b,0x0c,0x00,0x4c,0x10,0x18,0x0b,0x0c,0x00,0x4c,0x05,0x11,0x14,0x1a,0x04,0x07,0x0d,0x13,0x12,0x0f,0x0d,0x1d,0x95,0x59,0x0d,0x10,0x02,0x17,0xec,0x59,0x02,0x15,0x07,0x23,0xec,0x59,0x07,0x16,0x75,0x11,0x01, 0x1a,0xb8,0xff,0xe8,0xb4,0x09,0x15,0x01,0x4c,0x1a,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1a,0xb8,0xff,0xf8,0x40,0x3d,0x0b,0x06,0x4d,0x14,0x11,0x0a,0x1a,0x05,0x00,0x1a,0x11,0x12,0x20,0x14,0x05,0x0a,0x12,0x83,0x13,0x70,0x00,0x01,0x00,0x00,0x28,0x20,0x08,0x0d,0x06,0x4d,0x20,0x08,0x0c,0x06,0x4d,0x20,0x08,0x0b,0x06,0x4d,0x20, 0x83,0x0a,0x10,0x0d,0x06,0x4d,0x0a,0x10,0x0c,0x06,0x4d,0x0a,0x10,0x0b,0x06,0x4d,0x2f,0x0a,0x01,0x0a,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0xd4,0xe1,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x12,0x39,0x39,0x11,0x39,0x39,0x2b,0x2b,0x2b,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00, 0x18,0x3f,0x33,0x11,0x12,0x17,0x39,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x01,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x5f,0x5e,0x5d,0x25,0x06,0x23,0x22,0x03,0x23,0x02,0x21,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x16,0x17,0x33,0x13,0x33,0x03,0x16,0x16,0x33,0x32,0x37,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x04, 0xc5,0x35,0x2a,0x9a,0x36,0x04,0x94,0xfe,0xf6,0xba,0xe0,0x01,0x02,0xdc,0x7e,0xc6,0x33,0x04,0x55,0xac,0xc1,0x22,0x4c,0x3c,0x17,0x11,0xfe,0xa4,0x26,0x9c,0x6e,0x8e,0xa9,0x8f,0x79,0x6a,0xad,0x3a,0x05,0x0d,0x01,0x25,0xfe,0xcb,0x01,0x1f,0xdb,0xfa,0x01,0x3c,0x96,0x88,0x01,0x06,0xfe,0x0a,0xdb,0x9d,0x05,0x01,0x71,0xbe,0xca,0xf2, 0xb2,0x9e,0xd6,0xb5,0xb0,0x00,0x00,0x02,0x00,0x5c,0xff,0xe7,0x04,0x53,0x05,0xfe,0x00,0x1c,0x00,0x27,0x00,0xdf,0x40,0x0c,0x0d,0x27,0x01,0x0d,0x1e,0x01,0x02,0x00,0x01,0x10,0x04,0x19,0xb8,0xff,0xc0,0x40,0x0a,0x0b,0x0c,0x00,0x4c,0x17,0x30,0x0b,0x00,0x4d,0x00,0xb8,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x09,0xb8,0xff,0xe0,0x40, 0x35,0x0c,0x00,0x4d,0x09,0x1b,0x22,0x1d,0x16,0x10,0x01,0x03,0x1b,0x03,0x95,0x59,0x1b,0x01,0x10,0x22,0x95,0x59,0x10,0x16,0x1d,0x16,0x25,0x18,0x01,0x01,0x0d,0x06,0x83,0x18,0x18,0x13,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x83,0x25,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x25,0xb8,0xff, 0xf0,0xb3,0x0c,0x06,0x4d,0x25,0xb8,0xff,0xe0,0x40,0x2f,0x0b,0x06,0x4d,0x20,0x25,0x30,0x25,0x02,0x25,0x25,0x29,0x1f,0x08,0x0d,0x06,0x4d,0x1f,0x08,0x0c,0x06,0x4d,0x1f,0x08,0x0b,0x06,0x4d,0x1f,0x83,0x13,0x10,0x0d,0x06,0x4d,0x13,0x10,0x0c,0x06,0x4d,0x13,0x10,0x0b,0x06,0x4d,0x13,0x2f,0x29,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1, 0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x11,0x12,0x39,0x39,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x12,0x39,0x39,0x11,0x12,0x39,0x2b,0x31,0x30,0x2b,0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x5d,0x01,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e, 0x02,0x15,0x14,0x00,0x23,0x22,0x00,0x35,0x34,0x12,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x03,0x04,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03,0xe7,0xa8,0xac,0x64,0x79,0x68,0x78,0xa2,0xba,0x61,0xfe,0xe6,0xef,0xdb,0xfe,0xed,0xd4,0xcb,0xee,0xd0,0xb6,0xa4,0xbd,0xfe,0x92,0xb5,0x96,0x9d,0xba,0x8f,0x05,0xbe,0xb7,0x65,0x45, 0x3a,0x2f,0x69,0x49,0x63,0x9a,0xbf,0x6f,0xe9,0xfe,0xef,0x01,0x0b,0xd7,0x9b,0x01,0x02,0x58,0x93,0xa3,0x80,0x8a,0xfd,0x75,0x94,0xfe,0xeb,0x9d,0xb9,0xc0,0xa1,0x75,0xbf,0x00,0x00,0x01,0x00,0x52,0xff,0xe7,0x03,0x3b,0x04,0x19,0x00,0x25,0x00,0x9b,0x40,0x09,0x00,0x11,0x01,0x0f,0x00,0x01,0x10,0x04,0x0d,0xb8,0xff,0xe8,0x40,0x58, 0x0b,0x0c,0x00,0x4c,0x08,0x1e,0x19,0x19,0x1e,0xec,0x59,0x19,0x0f,0x02,0x19,0xec,0x0c,0x30,0x12,0x14,0x0f,0x14,0x95,0x59,0x0f,0x10,0x00,0x25,0x01,0x0e,0x03,0x25,0x23,0x02,0x23,0x95,0x59,0x02,0x16,0x08,0x0c,0x1b,0x12,0x00,0x00,0x27,0x05,0x16,0x83,0x0c,0x20,0x08,0x0d,0x06,0x4d,0x20,0x08,0x0c,0x06,0x4d,0x20,0x08,0x0b,0x06, 0x4d,0x20,0x83,0x05,0x10,0x0d,0x06,0x4d,0x05,0x10,0x0c,0x06,0x4d,0x05,0x10,0x0b,0x06,0x4d,0x2f,0x05,0x3f,0x05,0x02,0x05,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xd4,0xe1,0x11,0x12,0x39,0x2f,0xc4,0xc4,0x11,0x39,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x00,0x18,0x2f,0x2b, 0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x5f,0x5e,0x5d,0x5d,0x25,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x26,0x23,0x20,0x15,0x14,0x16,0x33,0x32,0x37,0x03,0x3b,0x82,0xc3,0xc3,0xe1,0x8b,0x72,0x56,0x80,0xd5,0xb2,0x8f,0x7f,0x85, 0x93,0xd7,0xa2,0x7d,0x49,0x2d,0x49,0x43,0xfe,0xd0,0x8d,0x80,0xa7,0x8f,0x16,0x2f,0xa5,0x89,0x5d,0x88,0x15,0x04,0x12,0x81,0x53,0x88,0x98,0x2d,0xa5,0x47,0x93,0x4b,0x5c,0x04,0x92,0x04,0xb2,0x4b,0x5b,0x49,0x00,0x02,0x00,0x61,0xff,0xe8,0x04,0x82,0x04,0x00,0x00,0x0c,0x00,0x17,0x00,0x7b,0x40,0x22,0x01,0x0e,0x0b,0x0e,0x96,0x59, 0x0b,0x0f,0x06,0x13,0x95,0x59,0x06,0x16,0x00,0x00,0x03,0x08,0x0d,0x06,0x4d,0x03,0x08,0x0c,0x06,0x4d,0x03,0x08,0x0b,0x06,0x4d,0x03,0x83,0x16,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x16,0xb8,0xff,0xf0,0x40,0x2a,0x0b,0x06,0x4d,0x16,0x16,0x19,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06,0x4d,0x10,0x83, 0x09,0x10,0x0d,0x06,0x4d,0x09,0x10,0x0c,0x06,0x4d,0x09,0x10,0x0b,0x06,0x4d,0x09,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xca,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x31,0x30,0x01,0x21,0x16,0x15,0x14,0x02,0x23,0x22,0x00,0x35,0x10,0x21,0x21, 0x05,0x23,0x20,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x04,0x82,0xff,0x00,0x8e,0xfc,0xd4,0xdb,0xfe,0xfc,0x02,0x09,0x02,0x18,0xfe,0x6c,0x76,0xfe,0x92,0xa9,0x8d,0x89,0x9f,0x03,0x7c,0xb6,0xdd,0xe3,0xfe,0xe2,0x01,0x1f,0xef,0x02,0x0a,0x84,0xfe,0x73,0xac,0xcf,0xd1,0xaf,0xdc,0x00,0x01,0x00,0x22,0xff,0xf4,0x03,0xc5,0x04,0x00, 0x00,0x13,0x00,0x7a,0x40,0x43,0x53,0x10,0x01,0x00,0x0f,0x01,0x0b,0x03,0x0f,0x0d,0x00,0x13,0x00,0x96,0x59,0x13,0x0f,0x06,0x04,0x09,0x04,0xec,0x59,0x09,0x30,0x00,0x70,0x00,0x02,0x00,0x00,0x15,0x02,0x0f,0x0f,0x0b,0x14,0x06,0x06,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x0b,0x08, 0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xfa,0xb6,0x0b,0x06,0x4d,0x0b,0x0b,0x15,0x14,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x5d,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x10,0x18,0xd4,0xc6,0x5f,0x5e,0x5d,0x31,0x30,0x5d,0x01,0x21, 0x11,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x11,0x11,0x23,0x22,0x07,0x35,0x36,0x33,0x21,0x03,0xc5,0xfe,0x79,0x74,0x36,0x36,0x42,0x48,0xf9,0x8d,0x72,0x7a,0x4c,0xa4,0x02,0xb3,0x03,0x7c,0xfd,0x96,0x8e,0x14,0x8e,0x16,0x01,0x20,0x02,0x68,0x58,0x94,0x48,0x00,0x02,0x00,0x60,0xfe,0x1e,0x05,0x38,0x04,0x18,0x00,0x1b,0x00,0x25, 0x00,0xfe,0x40,0x0f,0x06,0x17,0x01,0x09,0x15,0x01,0x09,0x0e,0x01,0x0d,0x0c,0x01,0x10,0x03,0x1f,0xb8,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x15,0xb8,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x10,0xb8,0xff,0xc0,0x40,0x2a,0x0b,0x0c,0x00,0x4c,0x16,0x23,0x95,0x59,0x16,0x10,0x0d,0x0f,0x13,0x05,0x02,0x1c,0x02,0x1c,0x95,0x59,0x02,0x16, 0x03,0x1c,0x19,0x08,0x0d,0x06,0x4d,0x19,0x08,0x0c,0x06,0x4d,0x19,0x08,0x0b,0x06,0x4d,0x20,0x83,0x19,0xb8,0xff,0xec,0xb3,0x0d,0x06,0x4d,0x19,0xb8,0xff,0xec,0xb3,0x0c,0x06,0x4d,0x19,0xb8,0xff,0xe0,0x40,0x56,0x0b,0x06,0x4d,0x19,0x0e,0x02,0x05,0x0a,0x42,0x02,0x0d,0x01,0x0d,0x0d,0x05,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x08,0x0c, 0x06,0x4d,0x0f,0x08,0x0b,0x06,0x4d,0x0f,0x83,0x50,0x0a,0x60,0x0a,0x02,0x0f,0x0a,0x01,0x0a,0x10,0x0d,0x06,0x4d,0x0a,0x10,0x0c,0x06,0x4d,0x0a,0x18,0x0b,0x06,0x4d,0x0a,0x0a,0x26,0x1c,0x13,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x10,0x0b,0x06,0x4d,0x02,0x84,0x05,0x05,0x27,0x26,0x2f,0x27,0x3f,0x27,0x02,0x5d, 0x11,0x12,0x39,0x2f,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0x5d,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x2f,0x5d,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0x3f,0x2b,0x31,0x30,0x00,0x2b,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d, 0x05,0x06,0x27,0x11,0x23,0x11,0x06,0x27,0x22,0x00,0x35,0x10,0x37,0x33,0x06,0x11,0x14,0x16,0x33,0x33,0x11,0x10,0x21,0x32,0x12,0x15,0x14,0x00,0x25,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x15,0x03,0x36,0x04,0x1e,0x94,0x18,0x04,0xec,0xfe,0xe8,0xd2,0xc2,0xec,0xbf,0x9b,0x1e,0x01,0x12,0xbc,0xea,0xfe,0xe7,0xfe,0xf5,0x22,0x98, 0xc2,0x93,0x67,0x82,0x18,0x04,0x04,0xfe,0x36,0x01,0xca,0x04,0x04,0x01,0x20,0xf6,0x01,0x3b,0xc7,0xd8,0xfe,0xd2,0xb8,0xce,0x02,0x95,0x01,0x0f,0xfe,0xd7,0xfb,0xe9,0xfe,0xdd,0x8c,0xd3,0xb5,0xb4,0xdc,0x81,0x00,0x02,0x00,0x00,0xfd,0xfe,0x03,0x52,0xff,0x62,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x1a,0x03,0x02,0xd9,0x59,0x0f,0x03, 0x01,0x0c,0x03,0x03,0x07,0x40,0x07,0x06,0xd9,0x59,0x1f,0x07,0x2f,0x07,0x02,0x07,0x07,0x03,0x04,0x00,0x2f,0x32,0x2f,0x33,0x00,0x2f,0x5d,0x2b,0x00,0x1a,0x18,0x10,0xcd,0x5f,0x5e,0x5d,0x2b,0x31,0x30,0x11,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x03,0x52,0xfc,0xae,0x03,0x52,0xfe,0xeb,0x77,0x77,0xed,0x77,0x77,0xff,0xff,0x00,0xb4, 0xff,0xee,0x03,0x23,0x05,0x9a,0x00,0x26,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x04,0x01,0x91,0x00,0x00,0x00,0x01,0x00,0x6e,0x02,0xcd,0x02,0xc2,0x05,0xb0,0x00,0x12,0x00,0x2b,0x40,0x16,0x00,0x0b,0x24,0x04,0x0f,0x07,0x0f,0x52,0x59,0x07,0x04,0x03,0x03,0x0b,0xc2,0x0c,0x0c,0x14,0x04,0x00,0xc2,0x01,0x2f,0xe1,0x32,0x12,0x39,0x2f, 0xe1,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0xc4,0x31,0x30,0x13,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0xee,0x80,0x80,0x04,0x43,0x8f,0x78,0x86,0x82,0x97,0x4a,0x71,0x02,0xcd,0x02,0xcf,0x73,0x87,0x94,0x84,0xfe,0x35,0x01,0xc3,0xb0,0x79,0x55,0x00,0x00,0x04,0x00,0xbc, 0xff,0xe8,0x08,0xa0,0x05,0x9a,0x00,0x09,0x00,0x10,0x00,0x25,0x00,0x45,0x00,0xd6,0x40,0x1e,0x2b,0x41,0x30,0x3b,0x04,0x33,0x44,0x36,0x38,0x33,0x38,0x95,0x59,0x33,0x1c,0x1d,0x40,0x1a,0x17,0x20,0x1d,0x1d,0x20,0x95,0x59,0x1d,0x1d,0x03,0x13,0x27,0xb8,0xff,0xc0,0x40,0x3e,0x0b,0x0e,0x48,0x27,0x29,0x44,0x29,0x95,0x59,0x44,0x16, 0x25,0x23,0x13,0x23,0x95,0x59,0x13,0x16,0x0b,0x00,0x91,0x59,0x0b,0x0b,0x03,0x02,0x03,0x0a,0x91,0x59,0x03,0x03,0x02,0x12,0x36,0x36,0x41,0x83,0x2b,0x2b,0x47,0x27,0x3b,0x83,0x30,0x30,0x47,0x16,0x25,0x1f,0x1f,0x1d,0x1a,0x21,0x84,0x18,0x16,0x16,0x47,0x02,0x0e,0xb8,0xff,0xf8,0x40,0x11,0x0c,0x06,0x4d,0x06,0x7d,0x0e,0x0e,0x47, 0x0b,0x01,0x08,0x0c,0x06,0x4d,0x01,0x7e,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x02,0x2f,0x2b,0xe1,0x2b,0x32,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x12,0x39,0x2f,0xce,0xf1,0x39,0x39,0xc2,0x2f,0xc4,0x11,0x12,0x39,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x00,0x18,0x3f, 0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x11,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xcd,0xc4,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x17,0x39,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x20,0x11,0x14,0x04,0x23,0x03,0x11,0x33,0x20,0x11,0x10,0x21,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x23,0x35, 0x33,0x35,0x37,0x11,0x33,0x15,0x23,0x11,0x14,0x33,0x32,0x37,0x17,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x01,0x64,0xa8,0x01,0x38,0x01,0xce,0xfe,0xf8,0xeb,0x6b,0x5e,0x01,0x50,0xfe,0xc5,0x04,0x39,0x3a,0x5f,0x83, 0x75,0x9b,0x9b,0xa4,0xed,0xed,0x83,0x3b,0x2f,0x44,0x79,0x89,0xa2,0x40,0xf6,0x6c,0xb8,0x92,0x82,0x4e,0x60,0x72,0x48,0x58,0x6c,0x5e,0x8d,0x4b,0xb0,0x9a,0xa2,0x02,0x1e,0xfd,0xe2,0x05,0x9a,0xfe,0x54,0xd2,0xfe,0x02,0xe4,0xfd,0xb4,0x01,0x30,0x01,0x1c,0xfb,0x08,0x20,0x8e,0x9e,0x01,0xd0,0x8a,0xfa,0x36,0xfe,0xd0,0x8a,0xfe,0x4d, 0xbf,0x22,0x71,0xb0,0x63,0x72,0x28,0x50,0x5c,0x3e,0x74,0x79,0x91,0x2e,0xa0,0x44,0x3f,0x32,0x39,0x2c,0x27,0x3f,0x70,0x4a,0x7d,0x8f,0xff,0xff,0x00,0xbc,0xff,0xe8,0x04,0x4e,0x05,0x9a,0x00,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x2d,0x02,0x23,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0x02,0x32,0xb4,0x0a,0x10,0x02,0x03,0x25,0x01, 0x2b,0x35,0xff,0xff,0x00,0x90,0xfe,0x1e,0x03,0x6c,0x05,0xd9,0x00,0x26,0x00,0x4c,0x00,0x00,0x01,0x07,0x00,0x4d,0x02,0x06,0x00,0x00,0x00,0x36,0xb3,0x03,0x02,0x1a,0x1a,0xb8,0xff,0xee,0xb3,0x0d,0x06,0x4d,0x1a,0xb8,0xff,0xfe,0x40,0x18,0x0c,0x06,0x4d,0x1a,0x0e,0x0b,0x06,0x4d,0x01,0x00,0x0d,0x0d,0x02,0x0c,0x06,0x4d,0x0d,0x02, 0x0b,0x06,0x4d,0x2f,0x2a,0x01,0x5d,0x2b,0x2b,0x11,0x35,0x35,0x2b,0x2b,0x2b,0x11,0x35,0x35,0xff,0xff,0xff,0xd7,0x00,0x00,0x04,0x4a,0x05,0xb2,0x00,0x26,0x00,0x51,0x52,0x00,0x01,0x07,0x00,0xb7,0xff,0x69,0x00,0x00,0x00,0x17,0xb2,0x00,0x00,0x00,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xef,0xb2,0x0b,0x06,0x4d,0x2b, 0x2b,0x11,0x35,0x00,0x00,0x01,0x00,0x82,0x03,0xdb,0x01,0x5e,0x05,0x9a,0x00,0x03,0x00,0x19,0xb9,0x00,0x01,0xff,0xe8,0x40,0x09,0x0e,0x12,0x48,0x01,0xb3,0x03,0x03,0x00,0x02,0x2f,0xcd,0x00,0x3f,0xed,0x31,0x30,0x01,0x2b,0x01,0x03,0x23,0x13,0x01,0x5e,0x68,0x74,0x56,0x05,0x9a,0xfe,0x41,0x01,0xbf,0x00,0x02,0x00,0x8d,0x03,0xdb, 0x02,0x84,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x3b,0xb9,0x00,0x01,0xff,0xe8,0xb3,0x0e,0x12,0x48,0x05,0xb8,0xff,0xe8,0x40,0x17,0x0e,0x12,0x48,0x05,0x01,0xb3,0x40,0x04,0x00,0x03,0x00,0x0e,0x02,0x06,0x80,0x06,0x04,0x42,0x04,0x00,0x06,0x01,0x06,0x2f,0x5d,0xcd,0x2b,0x01,0x1a,0x18,0x10,0xdc,0xe1,0x00,0x3f,0xc4,0x1a,0xfd,0xc4, 0x31,0x30,0x01,0x2b,0x2b,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0x84,0x6a,0x74,0x56,0x93,0x69,0x73,0x55,0x05,0x9a,0xfe,0x41,0x01,0xbf,0xfe,0x41,0x01,0xbf,0x00,0x04,0x00,0x96,0xff,0xec,0x06,0x0e,0x05,0xae,0x00,0x14,0x00,0x18,0x00,0x24,0x00,0x2e,0x00,0x63,0x40,0x35,0x15,0x03,0x09,0x07,0x0c,0x07,0xe6,0x59,0x0c,0x24, 0x00,0x02,0x12,0x02,0xe6,0x59,0x12,0x27,0x17,0x15,0x1f,0x25,0xe7,0x59,0x1f,0x19,0x19,0x2a,0xe7,0x59,0x19,0x2d,0x28,0xcc,0x1c,0x1c,0x15,0x15,0x22,0xcc,0x2d,0x2d,0x30,0x0f,0x17,0x17,0x0f,0x09,0x14,0x14,0x05,0xcc,0x0f,0x2f,0xe1,0x33,0x2f,0xc6,0x11,0x33,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x32,0x2f,0x32,0x2f,0xe1,0x00,0x3f,0x2b, 0x00,0x18,0x10,0xc4,0x2b,0x00,0x18,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x30,0x31,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x32,0x37,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x33,0x32,0x17,0x25,0x01,0x23,0x01,0x03,0x22,0x26,0x35,0x34,0x12,0x33,0x32,0x16,0x15,0x14,0x02,0x03,0x22,0x06,0x15, 0x14,0x33,0x32,0x36,0x35,0x34,0x02,0xf7,0x4f,0x5a,0x76,0x8f,0x9a,0x56,0x76,0x1f,0x66,0x5c,0x80,0x8e,0xe4,0xb8,0x72,0x49,0x02,0xdf,0xfb,0x33,0x93,0x04,0xcc,0xd6,0x8d,0x95,0xe0,0xa9,0x83,0x98,0xdd,0x41,0x6c,0x94,0xa0,0x68,0x8f,0x04,0xf7,0x43,0xc3,0x7f,0xbc,0x4f,0x8d,0x35,0x9f,0x87,0xbf,0x01,0x00,0x32,0x1e,0xfa,0x66,0x05, 0x9a,0xfa,0x52,0xa4,0x84,0xb2,0x01,0x0a,0x9c,0x88,0xb5,0xfe,0xf5,0x02,0x76,0xd2,0x7d,0xb8,0xc6,0x86,0xbb,0x00,0x00,0x02,0x00,0x0e,0xff,0xe8,0x02,0x85,0x05,0xd3,0x00,0x17,0x00,0x20,0x00,0x4b,0x40,0x25,0x18,0x01,0x00,0x16,0x0a,0x05,0x00,0x20,0x17,0x17,0x05,0x13,0x05,0x1d,0xda,0x59,0x05,0x10,0x0e,0x13,0x0e,0xec,0x59,0x13, 0x13,0x10,0x1b,0x48,0x08,0x08,0x22,0x00,0x18,0x01,0x0a,0x83,0x16,0x2f,0xe1,0x39,0x39,0xcd,0x12,0x39,0x2f,0xe1,0xc4,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x1a,0x19,0xcd,0x12,0x39,0x39,0x11,0x39,0x39,0x31,0x30,0x13,0x37,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x01,0x11,0x14,0x16,0x33, 0x32,0x37,0x15,0x06,0x23,0x22,0x35,0x35,0x07,0x13,0x36,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x0e,0xb2,0x7b,0x6f,0x64,0x77,0xfe,0xe3,0x1c,0x1e,0x30,0x96,0x70,0x71,0xc7,0x50,0xf8,0x6d,0x25,0x4c,0x1d,0x29,0x01,0xa6,0xec,0x01,0xc6,0xe2,0x99,0x87,0x68,0xc3,0xfe,0x79,0xfe,0x60,0x5a,0x29,0x6b,0xa2,0x58,0xf1,0xe1,0x62,0x02,0x2b, 0xbb,0x71,0x35,0x76,0x3e,0xb6,0x00,0x02,0x00,0x92,0x00,0x00,0x04,0x42,0x03,0xb0,0x00,0x03,0x00,0x07,0x00,0x3a,0x40,0x0d,0x07,0xf1,0x01,0x0e,0x06,0xf1,0x40,0x02,0x12,0x03,0x02,0x42,0x06,0xb8,0xff,0xe0,0x40,0x14,0x0c,0x06,0x4d,0x06,0xf1,0x02,0x05,0x20,0x0c,0x06,0x4d,0x05,0xf1,0x03,0x08,0x09,0x03,0x02,0xff,0x3a,0x2b,0x01, 0x10,0xe1,0x2b,0x10,0xe1,0x2b,0x2b,0x00,0x18,0x3f,0x1a,0xed,0xfd,0xed,0x31,0x30,0x13,0x21,0x11,0x21,0x13,0x11,0x21,0x11,0x92,0x03,0xb0,0xfc,0x50,0x4b,0x03,0x19,0x03,0xb0,0xfc,0x50,0x03,0x64,0xfc,0xe8,0x03,0x18,0x00,0x01,0x00,0x83,0x01,0xbc,0x02,0x52,0x03,0x8c,0x00,0x03,0x00,0x25,0x40,0x16,0x02,0x0e,0x40,0x03,0x02,0x01, 0x42,0x0f,0x01,0x1f,0x01,0x2f,0x01,0x03,0x09,0x03,0x04,0x05,0x02,0x01,0xff,0x3a,0x2b,0x01,0x5f,0x5e,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x11,0x21,0x11,0x02,0x52,0xfe,0x31,0x03,0x8c,0xfe,0x30,0x01,0xd0,0x00,0x00,0x02,0x00,0x83,0x01,0xbc,0x02,0x52,0x03,0x8c,0x00,0x03,0x00,0x07,0x00,0x41,0x40,0x2a,0x06,0xf1, 0x02,0x0e,0x07,0xf1,0x40,0x01,0x03,0x02,0x42,0x02,0x20,0x0c,0x06,0x4d,0x06,0xf1,0x02,0x05,0x20,0x0c,0x06,0x4d,0x05,0xf1,0x03,0x0f,0x02,0x1f,0x02,0x2f,0x02,0x03,0x09,0x03,0x08,0x09,0x03,0x02,0xff,0x3a,0x2b,0x01,0x5f,0x5e,0x5d,0x10,0xe1,0x2b,0x10,0xe1,0x2b,0x2b,0x00,0x18,0x2f,0x1a,0xed,0xfd,0xed,0x31,0x30,0x13,0x21,0x11, 0x21,0x13,0x11,0x21,0x11,0x83,0x01,0xcf,0xfe,0x31,0x4c,0x01,0x37,0x03,0x8c,0xfe,0x30,0x01,0x84,0xfe,0xc8,0x01,0x38,0x00,0x00,0x01,0x00,0xb2,0x00,0x89,0x04,0x23,0x03,0xfa,0x00,0x0b,0x00,0x25,0x40,0x15,0x03,0x0e,0x40,0x09,0x06,0x00,0x42,0x20,0x00,0x01,0x0f,0x06,0x01,0x09,0x03,0x0c,0x0d,0x06,0x00,0xff,0x3a,0x2b,0x01,0x5f, 0x5e,0x5d,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x14,0x00,0x23,0x22,0x00,0x35,0x34,0x24,0x33,0x32,0x00,0x04,0x23,0xfe,0xff,0xb6,0xb8,0xfe,0xfe,0x01,0x06,0xb2,0xb7,0x01,0x02,0x02,0x42,0xb8,0xfe,0xff,0x01,0x01,0xb8,0xb9,0xff,0xfe,0xfc,0x00,0x00,0x02,0x00,0x70,0x01,0xaa,0x02,0x66,0x03,0xa0,0x00,0x0b,0x00,0x17, 0x00,0x46,0x40,0x2d,0x0f,0xf1,0x03,0x0e,0x15,0xf1,0x40,0x09,0x00,0x20,0x0c,0x06,0x4d,0x06,0x00,0x42,0x12,0xf1,0x00,0x0c,0x20,0x0c,0x06,0x4d,0x0c,0xf1,0x06,0x0f,0x06,0x1f,0x06,0x02,0x0b,0x03,0x00,0x40,0x09,0x0c,0x48,0x18,0x19,0x06,0x00,0xff,0x3a,0x2b,0x01,0x2b,0x5f,0x5e,0x5d,0x10,0xe1,0x2b,0x10,0xe1,0x2b,0x01,0x2b,0x00, 0x18,0x2f,0x1a,0xed,0xf4,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x66,0x92,0x69,0x67,0x94,0x92,0x69,0x67,0x94,0xfe,0x56,0x67,0x49,0x4a,0x64,0x66,0x4a,0x48,0x66,0x02,0xa6,0x6a,0x92,0x94,0x68,0x66,0x94,0x94,0x66,0x4a,0x66, 0x66,0x4a,0x49,0x65,0x67,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0x8c,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x56,0x01,0x5d,0x00,0x13,0x40,0x0b,0x02,0x00,0x12,0x13,0x06,0x07,0x25,0x02,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0x2f,0x02,0x26, 0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xe6,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x22,0x23,0x10,0x14,0x25,0x02,0x21,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x07,0x6c,0x02,0x26,0x00,0x26,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x87,0x01,0x5e,0x00,0x13,0x40,0x0b,0x01,0x30, 0x1a,0x16,0x10,0x0a,0x25,0x01,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x06,0x0e,0x02,0x26,0x00,0x46,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xb8,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf9,0x40,0x09,0x1a,0x16,0x10,0x0a,0x25,0x01,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x06,0xe2,0x02,0x26,0x00,0x26,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x31,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x32,0x19,0x1f,0x10,0x0a,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x05,0x85,0x02,0x26,0x00,0x46,0x00,0x00,0x01,0x07, 0x00,0xdb,0x01,0x84,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x1d,0x19,0x1f,0x10,0x0a,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x06,0x8b,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xfe,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x12,0x0d,0x0c,0x02,0x03,0x25,0x01, 0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0x2f,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xfa,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x16,0x1c,0x1d,0x19,0x13,0x25,0x02,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4, 0x07,0x1c,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xf3,0x01,0x5e,0x00,0x13,0x40,0x0b,0x01,0x00,0x12,0x0c,0x02,0x03,0x3e,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0xbe,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xf5,0x00,0x00,0x00,0x16, 0xb9,0x00,0x02,0x01,0x1f,0x40,0x09,0x1a,0x1a,0x19,0x13,0x3e,0x02,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x06,0xe2,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x57,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xfd,0x40,0x09,0x0f,0x15,0x02,0x03,0x3e,0x01,0x0c,0x05,0x26, 0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0x85,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x71,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x08,0x1a,0x1a,0x0f,0x0f,0x3e,0x02,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0xec,0x07,0x6c,0x02,0x26, 0x00,0x2a,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x95,0x01,0x5e,0x00,0x13,0x40,0x0b,0x01,0x1d,0x1e,0x1a,0x10,0x0a,0x3e,0x01,0x1e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x06,0x0e,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xd1,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0d, 0x2a,0x26,0x20,0x17,0x3e,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0xec,0x06,0xe2,0x02,0x26,0x00,0x2a,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x4f,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x2f,0x1d,0x23,0x10,0x0a,0x3e,0x01,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x60,0xfe,0x1e,0x04,0x10,0x05,0x85,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x70,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0a,0x26,0x26,0x13,0x13,0x3e,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xfe,0x85,0x04,0xec,0x05,0xb2,0x02,0x26,0x00,0x2a,0x00,0x00,0x01,0x07,0x01,0x9c, 0x01,0x79,0x00,0x00,0x00,0x0b,0xb6,0x01,0x3f,0x1c,0x1a,0x05,0x19,0x25,0x01,0x2b,0x35,0x00,0x00,0x03,0x00,0x60,0xfe,0x1e,0x04,0x10,0x05,0xc6,0x00,0x18,0x00,0x25,0x00,0x29,0x00,0xbc,0xb6,0x24,0x18,0x0b,0x0c,0x00,0x4c,0x08,0xb8,0xff,0xe0,0x40,0x0e,0x0b,0x0c,0x00,0x4c,0x28,0x26,0x26,0x19,0x10,0x28,0x80,0x26,0x13,0x05,0xb8, 0xff,0xc0,0x40,0x31,0x0b,0x0f,0x48,0x05,0x05,0x07,0x95,0x02,0x1c,0x0a,0x23,0x95,0x0d,0x16,0x17,0x0f,0x15,0x1d,0x95,0x13,0x10,0x04,0x15,0x19,0x16,0x03,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x09,0x05,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xf0, 0x40,0x2b,0x0b,0x06,0x4d,0x09,0x09,0x2b,0x04,0x20,0x06,0x0d,0x06,0x4d,0x20,0x06,0x0c,0x06,0x4d,0x20,0x06,0x0b,0x06,0x4d,0x20,0x83,0x10,0x10,0x0d,0x06,0x4d,0x10,0x0e,0x0c,0x06,0x4d,0x10,0x1a,0x0b,0x06,0x4d,0x10,0x2f,0x2b,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b, 0x2b,0x17,0x33,0x2f,0x00,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x2f,0x2b,0x10,0xde,0x1a,0xcd,0x11,0x12,0x01,0x39,0x2f,0xcd,0x31,0x30,0x00,0x2b,0x2b,0x25,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x20,0x11,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x12,0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x13,0x33,0x03,0x04,0x10,0xfd,0xe4,0xc1,0x8b,0xae,0x9c,0x01,0x7a,0x04,0x74,0xec,0xbe,0xea,0xfb,0xda,0xd1,0x62,0x04,0xa4,0xa4,0xa4,0x7c,0x9a,0xaa,0xa6,0x87,0x8b,0xac,0xfe,0x6b,0xa6,0x7b,0x75,0x52,0xfd,0xcc,0x48,0xa4,0x60,0x01,0x92,0x70,0xc4,0x01,0x13,0xe4,0x01,0x05,0x01,0x34,0xa6,0x8e, 0xfd,0xcf,0x97,0x79,0xaf,0xde,0xc6,0xaa,0xce,0xc3,0x03,0x8d,0x01,0x04,0xfe,0xfc,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x07,0x6a,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x5e,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xfd,0x40,0x09,0x10,0x0c,0x06,0x0b,0x3e,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x07,0xbb,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x00,0x01,0xad,0x00,0x16,0xb9,0x00,0x01,0xff,0xf3,0x40,0x09,0x17,0x18,0x04,0x0f,0x3e,0x01,0x16,0x02,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x02,0x00,0x1c,0x00,0x00,0x05,0x92,0x05,0x9a,0x00,0x13,0x00,0x17,0x00,0xa0, 0x40,0x5d,0x06,0x09,0x0d,0x17,0x04,0x13,0x10,0x10,0x13,0x91,0x59,0x10,0x10,0x0f,0x16,0x16,0x02,0x91,0x59,0x16,0x0f,0x00,0x16,0x91,0x2b,0x30,0x0b,0x0f,0x03,0x04,0x00,0x12,0x0d,0x10,0x16,0x03,0x00,0x01,0x12,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x01,0x12,0x0d,0x06,0x4d, 0x01,0x12,0x0c,0x06,0x4d,0x01,0x01,0x19,0x09,0x0c,0x14,0x03,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x7e,0x07,0x05,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0xce,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0xf1,0x2b, 0x2b,0x2b,0xca,0x2f,0x11,0x12,0x17,0x39,0x00,0x3f,0xc4,0x3f,0xc4,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x17,0x39,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x21,0x15,0x21,0x35,0x04,0xf2,0xa8,0xfd,0x1a,0xa8,0xa0,0xa0, 0xa8,0x02,0xe6,0xa8,0xa0,0xa0,0xfc,0x72,0x02,0xe6,0x02,0x8e,0xfd,0x72,0x04,0x04,0x98,0xfe,0xfe,0xfe,0xfe,0x98,0xdf,0xdf,0x00,0x01,0x00,0x1e,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x1a,0x00,0xbd,0x40,0x40,0x00,0x19,0x01,0x03,0x02,0x18,0x01,0x10,0x04,0x0d,0x0a,0x13,0x10,0x10,0x13,0x96,0x59,0x0f,0x10,0x1f,0x10,0x2f,0x10,0x03, 0x09,0x03,0x10,0x10,0x0f,0x17,0x15,0x04,0x17,0x04,0x95,0x59,0x17,0x10,0x0f,0x00,0x08,0x00,0x15,0x12,0x12,0x08,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x1d,0x0b,0x06,0x4d, 0x01,0x01,0x1c,0x0d,0x10,0x13,0x03,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x84,0x0b,0x09,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x1c,0x01,0x5d,0x2f,0x2b,0x2b,0xce,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b, 0x2b,0x2b,0x12,0x39,0x2f,0x00,0x3f,0xc4,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5f,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8, 0xa4,0xee,0x78,0xa4,0xa4,0x88,0x88,0xa4,0x01,0x4c,0xfe,0xb4,0x04,0x78,0xd8,0xa8,0xb2,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfd,0xbc,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfe,0xa4,0xc2,0xd6,0xcb,0xff,0xff,0xff,0xd0,0x00,0x00,0x02,0x51,0x07,0x0c,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xad,0x01,0x5a,0x00,0x13,0x40,0x0b, 0x01,0x00,0x0e,0x04,0x02,0x03,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xad,0x00,0x00,0x02,0x2e,0x05,0xb2,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06,0x00,0xd8,0x8a,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf5,0x40,0x09,0x0e,0x04,0x02,0x03,0x25,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x13,0x00,0x00,0x02,0x0f,0x06,0x8b,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xd9,0xff,0xd5,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x06,0x07,0x02,0x03,0x25,0x01,0x05,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xef,0x00,0x00,0x01,0xeb,0x05,0x2f,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06, 0x00,0xd9,0xb1,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf5,0x40,0x09,0x06,0x07,0x02,0x03,0x25,0x01,0x05,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xfe,0x00,0x00,0x02,0x23,0x07,0x1a,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xda,0xff,0xd9,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x0a,0x04,0x02,0x03,0x25,0x01, 0x07,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xdb,0x00,0x00,0x02,0x00,0x05,0xbe,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06,0x00,0xda,0xb6,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf5,0x40,0x09,0x0a,0x04,0x02,0x03,0x25,0x01,0x07,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x50,0xfe,0x70,0x01,0x64, 0x05,0x9a,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x06,0x00,0xdf,0x12,0x00,0x00,0x0b,0xb6,0x01,0x00,0x04,0x04,0x00,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x37,0xfe,0x70,0x01,0x66,0x05,0xd9,0x02,0x26,0x00,0x4c,0x00,0x00,0x01,0x06,0x00,0xdf,0xf9,0x00,0x00,0x0b,0xb6,0x02,0x00,0x1e,0x10,0x0e,0x0f,0x25,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x14,0xff,0xe8,0x02,0xf2,0x07,0x6a,0x02,0x26,0x00,0x2d,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0x62,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x12,0x13,0x0b,0x0c,0x3e,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0x3a,0xfe,0x1e,0x02,0x0f,0x06,0x0e,0x02,0x26,0x06,0xac,0x00,0x00,0x01,0x07, 0x00,0xd7,0xff,0x7f,0x00,0x00,0x00,0x08,0xb3,0x01,0x11,0x11,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0x85,0x04,0xa2,0x05,0x9a,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x01,0x9c,0x00,0xea,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x14,0x11,0x06,0x01,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0xfe,0x85,0x03,0xf8,0x05,0xec, 0x02,0x26,0x00,0x4e,0x00,0x00,0x01,0x07,0x01,0x9c,0x00,0x87,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x10,0x0d,0x04,0x01,0x3e,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x00,0x0c,0x00,0x66,0x40,0x45,0x7a,0x0c,0x01,0x77,0x0b,0x01,0x79,0x02,0x01,0x7d,0x0a,0x01,0x7e,0x01,0x01,0x36,0x0c,0x01,0x2a,0x01, 0x01,0x36,0x00,0x01,0x05,0x15,0x06,0x0f,0x0a,0x0b,0x0b,0x01,0x70,0x00,0x01,0x00,0x14,0x0b,0x06,0x4d,0x00,0x0c,0x08,0x04,0x06,0x0d,0x06,0x4d,0x04,0x06,0x0c,0x06,0x4d,0x04,0x06,0x0b,0x06,0x4d,0x04,0x84,0x05,0x04,0x0d,0x06,0x4d,0x05,0x2f,0x0e,0x01,0x5d,0x2f,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x32,0x2f,0x2b,0x5d,0x33,0x33,0x2f, 0x33,0x00,0x3f,0x3f,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x03,0xf8,0xe6,0xfe,0x3c,0x04,0xa4,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0x01,0xec,0xfe,0x14,0x04,0x00,0xfe,0x2b,0x01,0xd5,0xfe,0x12,0x00,0xff,0xff,0x00,0xbc,0xfe,0x85,0x03,0xa4, 0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x00,0x07,0x01,0x9c,0x00,0x96,0x00,0x00,0xff,0xff,0x00,0x27,0xfe,0x85,0x01,0x4a,0x05,0xec,0x02,0x26,0x00,0x4f,0x00,0x00,0x00,0x07,0x01,0x9c,0xff,0x4c,0x00,0x00,0xff,0xff,0x00,0xbc,0xfe,0x85,0x05,0x40,0x05,0x9a,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x01,0x9c,0x01,0x6a,0x00,0x00, 0x00,0x0e,0xb9,0x00,0x01,0xff,0xea,0xb4,0x16,0x14,0x08,0x01,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0x85,0x03,0xf8,0x04,0x18,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x01,0x9c,0x00,0xb9,0x00,0x00,0x00,0x0b,0xb6,0x01,0x10,0x16,0x13,0x08,0x01,0x3e,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xbc,0xfe,0x5a,0x05,0x40,0x05,0x9a, 0x00,0x1b,0x00,0xb8,0xb5,0x02,0x09,0x01,0x10,0x04,0x0c,0xb8,0xff,0xc0,0xb3,0x10,0x00,0x4d,0x0c,0xb8,0xff,0xe8,0x40,0x3d,0x0c,0x00,0x4d,0x02,0x20,0x10,0x00,0x4d,0x17,0x19,0x14,0x19,0x91,0x59,0x14,0x02,0x0c,0x1b,0x10,0x08,0x03,0x1b,0x07,0x12,0x16,0x16,0x12,0x1b,0x1b,0x0c,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08,0x0c,0x06,0x4d, 0x12,0x08,0x0b,0x06,0x4d,0x12,0x7e,0x7f,0x0f,0x01,0x0f,0x18,0x0d,0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xf8,0x40,0x1a,0x0b,0x06,0x4d,0x0f,0x0f,0x1d,0x09,0x03,0x06,0x06,0x0d,0x06,0x4d,0x06,0x06,0x0c,0x06,0x4d,0x06,0x06,0x0b,0x06,0x4d,0x06,0x7e,0x07,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf8,0x40, 0x09,0x0c,0x06,0x4d,0x07,0x06,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x39,0x33,0x2f,0x10,0xc0,0x2f,0x00,0x3f,0xc4,0x3f,0xc4,0x12,0x39,0x39,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x2b,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x01,0x26,0x27,0x23, 0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x26,0x35,0x11,0x33,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x01,0x90,0x16,0x18,0x06,0x08,0xa8,0xda,0x02,0xce,0x02,0x38,0x04,0x0a,0xa8,0xfe,0x93,0x4c,0x3d,0x4e,0x3f,0xbd,0x04,0x77,0x20,0x3a,0x35,0x90,0xfb,0xf4,0x05,0x9a,0xfb,0xd6,0x02,0x66,0x48,0x94,0x03,0xb6, 0xfa,0xa6,0xfe,0x1a,0x1f,0xa5,0x2c,0x01,0x0e,0x00,0x00,0x01,0x00,0xa6,0xfe,0x5a,0x03,0xf8,0x04,0x18,0x00,0x19,0x00,0x9c,0x40,0x2b,0x00,0x18,0x01,0x10,0x03,0x05,0x07,0x02,0x07,0x91,0x59,0x02,0x14,0x0c,0x17,0x0c,0x95,0x59,0x17,0x10,0x12,0x0f,0x11,0x15,0x04,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b, 0x06,0x4d,0x00,0x84,0x09,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xf8,0x40,0x1e,0x0b,0x06,0x4d,0x09,0x09,0x1b,0x13,0x10,0x06,0x0d,0x06,0x4d,0x10,0x06,0x0c,0x06,0x4d,0x10,0x06,0x0b,0x06,0x4d,0x10,0x84,0x11,0x02,0x0d,0x06,0x4d,0x11,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x11, 0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x11,0x2f,0x1b,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc4,0x00,0x3f,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x31,0x30,0x5f,0x5e,0x5d,0x25,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x10, 0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xfe,0x9a,0x4c,0x3e,0x4e,0x40,0xbe,0xee,0x7a,0xa2,0xa4,0xa4,0x04,0x75,0xdb,0x01,0x5a,0x1a,0xfe,0x40,0x1f,0xa5,0x2c,0x01,0x0e,0x02,0x48,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xfe,0x5a,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa, 0x06,0x8b,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0xce,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x06,0x1a,0x1b,0x03,0x09,0x3e,0x02,0x19,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0x2f,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x26,0x00,0x00,0x00,0x13, 0x40,0x0b,0x02,0x0a,0x1a,0x1b,0x03,0x09,0x3e,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x1c,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0xd7,0x01,0x5e,0x00,0x13,0x40,0x0b,0x02,0x00,0x1b,0x1b,0x0c,0x0c,0x3e,0x02,0x1b,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0xbe,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x35,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x21,0x21,0x06,0x06,0x3e,0x02,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x85,0x04,0xc0,0x05,0x9a,0x02,0x26,0x00,0x35,0x00,0x00, 0x00,0x07,0x01,0x9c,0x00,0xe4,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x85,0x02,0xbc,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x06,0x01,0x9c,0x19,0x00,0x00,0x0b,0xb6,0x01,0x1f,0x14,0x14,0x06,0x06,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x07,0x6a,0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x00,0xd7, 0x00,0xb1,0x01,0x5c,0x00,0x08,0xb3,0x01,0x3a,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x06,0x0e,0x02,0x26,0x00,0x56,0x00,0x00,0x01,0x06,0x00,0xd7,0x37,0x00,0x00,0x08,0xb3,0x01,0x30,0x11,0x26,0x00,0x2b,0x35,0x00,0x01,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x00,0x0f,0x00,0xa3,0x40,0x1a,0x0b,0x08, 0x05,0x02,0x02,0x05,0x91,0x59,0x02,0x0f,0x06,0x02,0x91,0x2b,0x30,0x0c,0x00,0x0f,0x00,0x91,0x59,0x0f,0x03,0x06,0x12,0x0d,0xb8,0xff,0xfa,0xb3,0x0b,0x06,0x4d,0x00,0xb8,0xff,0xfa,0x40,0x2f,0x0b,0x06,0x4d,0x04,0x0e,0x06,0x07,0x09,0x42,0x09,0x07,0x00,0x0e,0x06,0x07,0x0d,0x42,0x2f,0x0d,0x3f,0x0d,0xcf,0x0d,0x03,0x0d,0x0d,0x10, 0x0b,0x02,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x7e,0x07,0x04,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf8,0x40,0x0d,0x0b,0x06,0x4d,0x07,0x07,0x11,0x10,0x11,0x40,0x0c,0x00,0x4d,0x11,0xb8,0xff,0xc0,0xb2,0x0b,0x00,0x4d,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x5d,0x2b,0x01, 0x10,0xe0,0x18,0x10,0xc6,0x2b,0x01,0x10,0xe2,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x01,0x21,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x21,0x35,0x21,0x04,0x0c,0xfe,0x62,0xf6,0xf6,0xa8,0xf9,0xf9,0xfe,0x63,0x03,0xe3,0x05,0x02,0xfe,0x1a, 0x9b,0xfd,0x7f,0x02,0x81,0x9b,0x01,0xe6,0x98,0x00,0x00,0x01,0x00,0x2b,0xff,0xea,0x02,0x81,0x05,0x2f,0x00,0x1e,0x00,0x93,0x40,0x45,0x0b,0x18,0x0b,0x0c,0x00,0x4c,0x1d,0x01,0x0d,0x10,0x10,0x0d,0x96,0x59,0x10,0x18,0x14,0x40,0x1c,0x19,0x11,0x14,0x14,0x11,0x95,0x59,0x14,0x0f,0x07,0x05,0x0a,0x05,0x95,0x59,0x0a,0x16,0x07,0x1e, 0x2f,0x1b,0x01,0x1b,0x1b,0x02,0x0e,0x12,0x10,0x14,0x19,0x1d,0x04,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x0c,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0c,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0c,0xb8,0xff,0xee,0xb6,0x0b,0x06,0x4d,0x0c,0x0c,0x20,0x1f,0x11,0x12,0x39,0x2f,0x2b,0x2b, 0x2b,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0xdc,0xc6,0x10,0xc0,0x2f,0x5d,0xc6,0xc4,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a,0x18,0x10,0xcd,0xc6,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x01,0x23,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x23,0x35,0x33, 0x35,0x36,0x37,0x37,0x11,0x21,0x15,0x21,0x15,0x33,0x02,0x77,0xf8,0x45,0x52,0x3c,0x2f,0x3a,0x5f,0xfe,0xf3,0xa3,0xa3,0xb0,0xb0,0x04,0x4e,0x52,0x01,0x02,0xfe,0xfe,0xf8,0x02,0x23,0xf0,0x67,0x58,0x22,0x8c,0x20,0x01,0x2c,0x01,0x0d,0x85,0xcc,0x8c,0xfa,0x02,0x19,0x1a,0xfe,0xd1,0x8c,0xcc,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5, 0x07,0x0e,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x5f,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x03,0x18,0x0e,0x05,0x0d,0x25,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x05,0xb2,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xd6,0x00,0x00,0x00,0x13, 0x40,0x0b,0x01,0x00,0x1c,0x12,0x08,0x11,0x25,0x01,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x06,0x8b,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x81,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x10,0x11,0x05,0x0d,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x05,0x2f,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xf9,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x14,0x15,0x08,0x11,0x25,0x01,0x13,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x1a,0x02,0x26,0x00,0x38, 0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x84,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x14,0x0e,0x05,0x0d,0x25,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x05,0xbe,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xfd,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff, 0xfb,0x40,0x09,0x18,0x12,0x08,0x11,0x25,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xfe,0x70,0x04,0xd5,0x05,0x9a,0x02,0x26,0x00,0x38,0x00,0x00,0x00,0x07,0x00,0xdf,0x02,0x10,0x00,0x00,0xff,0xff,0x00,0x90,0xfe,0x70,0x03,0xe2,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x00,0x07,0x00,0xdf,0x02,0x90, 0x00,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x60,0x07,0x6a,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x00,0xd7,0x02,0x5b,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x1e,0x1e,0x13,0x14,0x25,0x01,0x20,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x06,0x0e,0x02,0x26,0x00,0x5a,0x00,0x00, 0x01,0x07,0x00,0xd7,0x01,0x80,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfb,0x40,0x09,0x1e,0x1e,0x13,0x14,0x25,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x07,0x69,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xc5,0x01,0x5b,0x00,0x13,0x40,0x0b,0x01,0x00,0x13,0x14, 0x05,0x00,0x25,0x01,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x0e,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0x8c,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x10,0x1a,0x1b,0x0c,0x00,0x25,0x01,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xa6, 0x00,0x00,0x02,0x62,0x06,0x02,0x00,0x0c,0x00,0x39,0x40,0x23,0x00,0x02,0x0a,0x02,0x95,0x59,0x0a,0x01,0x05,0x15,0x2f,0x00,0x01,0x00,0x05,0x08,0x0d,0x06,0x4d,0x05,0x08,0x0c,0x06,0x4d,0x05,0x08,0x0b,0x06,0x4d,0x05,0x84,0x06,0x06,0x0e,0x0d,0x11,0x12,0x39,0x2f,0xe1,0x2b,0x2b,0x2b,0xc4,0x5d,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x10, 0xc6,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x17,0x02,0x62,0x2e,0x3e,0xac,0xa4,0xbd,0x89,0x4a,0x2c,0x05,0x5c,0x1b,0xd9,0xfb,0x62,0x04,0xa6,0xa1,0xbb,0x12,0x00,0x00,0x04,0x00,0x16,0x00,0x00,0x05,0x12,0x08,0x52,0x00,0x10,0x00,0x1b,0x00,0x23,0x00,0x27,0x00,0xfe,0x40,0x39,0x78,0x27,0x01,0x76, 0x22,0x01,0x79,0x1d,0x01,0x74,0x0c,0x01,0x7b,0x0a,0x01,0x7b,0x07,0x01,0x77,0x06,0x01,0x02,0x08,0x0c,0x00,0x4d,0x1c,0x02,0x01,0x20,0x01,0x23,0x03,0x04,0x20,0x04,0x73,0x04,0x01,0x7c,0x01,0x01,0x20,0x30,0x0c,0x00,0x4d,0x00,0x16,0x01,0x90,0x27,0x01,0xa0,0x27,0x01,0x27,0xb8,0xff,0xc0,0xb3,0x1d,0x21,0x48,0x27,0xb8,0xff,0xc0, 0x40,0x39,0x16,0x19,0x48,0x27,0xa0,0x26,0xd0,0x26,0xe0,0x26,0x03,0x10,0x26,0x20,0x26,0x30,0x26,0x80,0x26,0x90,0x26,0x05,0x26,0x0b,0x02,0x91,0x1c,0x1c,0x16,0x00,0x11,0xc5,0x0b,0x10,0x06,0x40,0x16,0x03,0x04,0x00,0x12,0x24,0x80,0x26,0x26,0x14,0x19,0xc4,0x0e,0x40,0x09,0x0c,0x48,0x0e,0x14,0xc4,0x08,0xb8,0xff,0xc0,0xb5,0x0c, 0x00,0x4d,0x08,0x08,0x06,0xb8,0xff,0xf8,0x40,0x15,0x0c,0x00,0x4d,0x10,0x08,0x0c,0x00,0x4d,0x1c,0x23,0x06,0x10,0x04,0x05,0x77,0x05,0x01,0x79,0x00,0x01,0x05,0xb8,0xff,0xe8,0x40,0x0c,0x0c,0x00,0x4d,0x00,0x18,0x0c,0x00,0x4d,0x00,0x00,0x29,0x05,0x2f,0x11,0x33,0x2f,0x2b,0x2b,0x5d,0x5d,0x12,0x17,0x39,0x2b,0x2b,0x39,0x2f,0x2b, 0xe9,0xd4,0x2b,0xe9,0x10,0xc0,0x2f,0x1a,0xcd,0x00,0x3f,0xc4,0x3f,0x1a,0xcd,0x39,0xd4,0xed,0x11,0x12,0x39,0x2f,0xed,0x10,0xd6,0x5d,0x72,0xcd,0x2b,0x2b,0x71,0x72,0x5d,0x2b,0x31,0x30,0x01,0x5d,0x5d,0x10,0x87,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x01,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x26, 0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x01,0x01,0x23,0x13,0x05,0x12,0xba,0x98,0xfd,0xa0,0x8f,0xbb,0x02,0x11,0x65,0x78,0x5c,0x58,0x70,0x60,0x6e,0x32,0x40,0x72,0x30,0x42,0x42,0xc9,0xe1,0x0b,0x0b,0x04,0x0a,0x0d,0xdf,0x02, 0x04,0xfe,0xfa,0x7f,0xdf,0x01,0x92,0xfe,0x6e,0x05,0x62,0x34,0x70,0x59,0x6e,0x6d,0x54,0x70,0x36,0x01,0x15,0x3f,0x30,0x72,0x42,0x30,0x31,0x3e,0xfb,0xae,0x02,0x63,0x1e,0x42,0x3d,0x23,0xfd,0x9d,0x06,0x29,0xfe,0xb8,0x01,0x48,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x07,0x66,0x02,0x26,0x00,0x44,0x00,0x00,0x00,0x27,0x00,0xdc, 0x00,0xe9,0xff,0xc2,0x01,0x07,0x00,0x8e,0x01,0x0c,0x01,0x5c,0x00,0x33,0x40,0x25,0x04,0x0f,0x39,0x1f,0x39,0x3f,0x39,0x5f,0x39,0x90,0x39,0x05,0x20,0x39,0x5f,0x39,0x02,0x39,0x26,0x03,0x02,0x20,0x40,0x11,0x15,0x48,0x0f,0x20,0x01,0x10,0x20,0x4f,0x20,0xef,0x20,0x03,0x20,0x00,0x11,0x5d,0x71,0x2b,0x35,0x35,0x10,0xde,0x5d,0x5d, 0x34,0x00,0xff,0xff,0x00,0x0a,0x00,0x00,0x06,0x83,0x07,0x66,0x02,0x26,0x00,0x91,0x00,0x00,0x01,0x07,0x00,0x8e,0x03,0x30,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x17,0x16,0x15,0x11,0x09,0x25,0x02,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x06,0x56,0x06,0x0a,0x02,0x26,0x00,0xa0,0x00,0x00, 0x01,0x07,0x00,0x8e,0x02,0x55,0x00,0x00,0x00,0x13,0x40,0x0b,0x03,0x11,0x37,0x37,0x1e,0x1e,0x25,0x03,0x38,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xcd,0x05,0xaa,0x07,0x66,0x02,0x26,0x00,0x92,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xfa,0x01,0x5c,0x00,0x13,0x40,0x0b,0x03,0x20,0x25,0x27,0x16,0x08, 0x25,0x03,0x26,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x31,0xff,0xae,0x04,0x96,0x06,0x0a,0x02,0x26,0x00,0xa1,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x58,0x00,0x00,0x00,0x16,0xb9,0x00,0x03,0xff,0xf9,0x40,0x09,0x25,0x25,0x16,0x10,0x3e,0x03,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x01,0x00,0x70, 0x01,0xfe,0x01,0x50,0x02,0xdf,0x00,0x0b,0x00,0x15,0x40,0x0b,0x06,0x00,0xb0,0x5b,0x06,0x09,0xaf,0x03,0x2f,0x0d,0x01,0x5d,0x2f,0xe1,0x00,0x2f,0x2b,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x01,0xfe,0x42,0x2e,0x2f,0x42,0x42,0x2f,0x2e,0x42,0x00,0xff,0xff, 0x00,0x1a,0x00,0x00,0x07,0x60,0x07,0x66,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x00,0x43,0x02,0xa0,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x1f,0x1d,0x13,0x14,0x25,0x01,0x1d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x06,0x0a,0x02,0x26,0x00,0x5a,0x00,0x00,0x01,0x07, 0x00,0x43,0x01,0xb5,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xe7,0x40,0x09,0x1f,0x1d,0x13,0x14,0x25,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x60,0x07,0x66,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x96,0x01,0x5c,0x00,0x17,0x40,0x0e,0x01,0x5f,0x1d,0x01,0x00,0x1d, 0x1f,0x13,0x14,0x25,0x01,0x1e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x5d,0x35,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x06,0x0a,0x02,0x26,0x00,0x5a,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xc4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x03,0x1d,0x1f,0x13,0x14,0x25,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x1a,0x00,0x00,0x07,0x60,0x06,0xe4,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x00,0x8f,0x02,0x1c,0x01,0x5d,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf1,0x40,0x0a,0x31,0x1f,0x13,0x14,0x25,0x02,0x01,0x28,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x05,0x87,0x02,0x26,0x00,0x5a, 0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x44,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xef,0x40,0x0a,0x31,0x1f,0x13,0x14,0x25,0x02,0x01,0x28,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x07,0x66,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xf6,0x01,0x5c,0x00,0x1a, 0xb3,0x01,0x00,0x11,0x01,0xb8,0xff,0xe6,0x40,0x09,0x11,0x0f,0x05,0x00,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x5d,0x35,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x0a,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0x9e,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xd6,0x40,0x09,0x18,0x16,0x0c,0x00,0x25, 0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x01,0x00,0x6e,0x03,0xf4,0x01,0x70,0x05,0xb2,0x00,0x03,0x00,0x1c,0x40,0x10,0x00,0xb3,0x40,0x03,0x04,0x00,0xb4,0x80,0x10,0x02,0x50,0x02,0x60,0x02,0x03,0x02,0x2f,0x5d,0x1a,0xe9,0x00,0x3f,0x1a,0xed,0x31,0x30,0x01,0x23,0x03,0x33,0x01,0x70,0x74,0x8e,0x94,0x03,0xf4,0x01, 0xbe,0x00,0x00,0x01,0x00,0x00,0x05,0x74,0x03,0x52,0x05,0xec,0x00,0x03,0x00,0x10,0xb7,0x02,0x01,0xd9,0x59,0x02,0x00,0x03,0x02,0x2f,0x2f,0x00,0x3f,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x52,0xfc,0xae,0x03,0x52,0x05,0x74,0x78,0x00,0x00,0x01,0x00,0x6a,0x00,0x00,0x03,0xee,0x05,0xb2,0x00,0x23,0x00,0x92,0x40,0x57,0x01,0x02, 0x22,0x03,0x0b,0x0e,0x0e,0x0b,0x9a,0x59,0x00,0x0e,0x10,0x0e,0x20,0x0e,0x03,0x09,0x03,0x0e,0x12,0x40,0x21,0x1e,0x0f,0x12,0x12,0x0f,0x9a,0x59,0x0f,0x12,0x1f,0x12,0x02,0x09,0x03,0x12,0x12,0x16,0x06,0x19,0x1b,0x16,0x1b,0x9a,0x59,0x16,0x04,0x06,0x05,0x9a,0x59,0x06,0x12,0x00,0x1f,0x4f,0x18,0x01,0x18,0x06,0x06,0x25,0x0f,0x12, 0x1e,0x21,0x04,0x01,0x08,0x0c,0x06,0x4d,0x01,0x8a,0x04,0x08,0x0b,0x10,0x0c,0x0b,0x10,0x0c,0x06,0x4d,0x0b,0x2f,0x2b,0xdd,0xc4,0x10,0xc6,0x32,0xe1,0x2b,0x17,0x39,0x12,0x39,0x2f,0xd4,0x5d,0xd4,0xc4,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x1a, 0x18,0x10,0xcd,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x17,0x39,0x31,0x30,0x01,0x21,0x15,0x14,0x07,0x21,0x15,0x21,0x35,0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x15,0x21,0x15,0x21,0x15,0x21,0x03,0x10,0xfe,0xd8,0xc1,0x02,0xc7,0xfc,0x7c,0xda,0xc5,0xc5,0xc5,0xc5, 0xda,0xad,0x76,0x5f,0x63,0x70,0xe5,0x01,0x28,0xfe,0xd8,0x01,0x28,0x01,0xe8,0x09,0xf3,0x60,0x8c,0x87,0x47,0xf2,0x28,0x8c,0x88,0x8d,0x7d,0xbc,0xf0,0x29,0x9b,0x39,0xfe,0xcd,0x6b,0x8d,0x88,0x00,0x00,0x02,0x00,0x55,0xff,0xdd,0x04,0x78,0x04,0x48,0x00,0x12,0x00,0x19,0x00,0x53,0x40,0x2e,0x00,0x06,0x10,0x06,0x02,0x09,0x03,0x06, 0x06,0x00,0x04,0x13,0x00,0xc3,0x59,0x13,0x13,0x10,0x04,0x10,0x16,0xc3,0x59,0x10,0x0a,0x04,0xc3,0x59,0x0a,0x19,0x07,0x40,0x10,0x1e,0x48,0x07,0x07,0x00,0xaf,0x13,0x13,0x1b,0x19,0x01,0xaf,0x0d,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12, 0x00,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x31,0x30,0x01,0x21,0x13,0x16,0x33,0x32,0x37,0x17,0x06,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x00,0x07,0x11,0x26,0x23,0x22,0x07,0x11,0x04,0x78,0xfc,0xc4,0x01,0x78,0xb0,0xff,0x8c,0x48,0x68,0xdb,0x8f,0xee,0xfe,0xdd,0x01,0x29,0xe4,0xd8,0x01,0x30,0xda,0x82,0xad,0xaf,0x76,0x02,0x12, 0xfe,0x8e,0x79,0xf5,0x2a,0x98,0x7d,0x01,0x43,0xf2,0xfe,0x01,0x38,0xfe,0xe4,0xd0,0x01,0x29,0x7b,0x7b,0xfe,0xd7,0xff,0xff,0x00,0x50,0xff,0xec,0x06,0xe2,0x05,0xb0,0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x07,0x02,0x3b,0x04,0x35,0xfd,0xb8,0x00,0x0b,0xb4,0x04,0x03,0x02,0x30,0x2d,0x00,0x3f, 0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x81,0xff,0xec,0x07,0x2a,0x05,0xae,0x00,0x26,0x00,0xf2,0x00,0x00,0x00,0x27,0x00,0xbc,0x03,0x07,0x00,0x00,0x01,0x07,0x02,0x3b,0x04,0x7d,0xfd,0xb8,0x00,0x0b,0xb4,0x04,0x03,0x02,0x44,0x2d,0x00,0x3f,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x8c,0xff,0xec,0x07,0x2c,0x05,0x9e,0x00,0x26,0x02,0x39, 0x11,0x00,0x00,0x27,0x00,0xbc,0x03,0x09,0x00,0x00,0x01,0x07,0x02,0x3b,0x04,0x7f,0xfd,0xb8,0x00,0x0b,0xb4,0x04,0x03,0x02,0x48,0x2d,0x00,0x3f,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0xa2,0xff,0xec,0x06,0xa5,0x05,0xa4,0x00,0x26,0x02,0x3a,0x55,0x00,0x00,0x27,0x00,0xbc,0x02,0x82,0x00,0x00,0x01,0x07,0x02,0x3b,0x03,0xf8,0xfd,0xb8, 0x00,0x0b,0xb4,0x04,0x03,0x02,0x2e,0x2d,0x00,0x3f,0x35,0x35,0x35,0x00,0x00,0x01,0x00,0xdb,0xfe,0x85,0x01,0xfc,0xff,0x89,0x00,0x03,0x00,0x17,0x40,0x0c,0x02,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x05,0x03,0x23,0x13,0x01,0xfc,0xa6,0x7b,0x75,0x77,0xfe,0xfc,0x01, 0x04,0x00,0x00,0x01,0x00,0xdb,0xfe,0x85,0x01,0xfc,0xff,0x89,0x00,0x03,0x00,0x17,0x40,0x0c,0x02,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x05,0x03,0x23,0x13,0x01,0xfc,0xa6,0x7b,0x75,0x77,0xfe,0xfc,0x01,0x04,0x00,0xff,0xff,0x00,0x27,0xfe,0xf8,0x01,0x52,0x04,0x16, 0x02,0x06,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0xce,0x04,0x96,0x01,0xdb,0x06,0x01,0x00,0x03,0x00,0x0f,0xb5,0x01,0x00,0x01,0x02,0x80,0x00,0x2f,0x1a,0xcd,0x00,0x3f,0xcd,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0xdb,0xaf,0x5e,0x66,0x06,0x01,0xfe,0x95,0x01,0x6b,0x00,0x03,0xff,0xda,0x04,0xa4,0x02,0x84,0x06,0x0f,0x00,0x03,0x00,0x0f, 0x00,0x1b,0x00,0x2a,0x40,0x14,0x0a,0x04,0x16,0xc1,0x40,0x10,0x03,0x01,0x0d,0xc0,0x07,0x07,0x00,0x13,0xc0,0x19,0x19,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x33,0x2f,0xe1,0x11,0x33,0x2f,0xe1,0x00,0x2f,0xcd,0xd4,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x13,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0xd6,0xaf,0x5d,0x65,0xf2,0x28,0x39,0x39,0x27,0x2a,0x3a,0x3a,0xfd,0xf2,0x28,0x3a,0x3a,0x28,0x29,0x3b,0x3a,0x06,0x0f,0xfe,0x95,0x01,0x6b,0xfe,0xb9,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12, 0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x01,0x9f,0xff,0x5f,0xff,0x99,0x00,0x12,0x40,0x0a,0x02,0x13,0x03,0x02,0x17,0x12,0x12,0x05,0x05,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xc5,0x00,0x00,0x04,0x36,0x05,0x9a,0x00,0x27,0x00,0x28,0x00,0x82,0x00,0x00,0x01,0x07,0x01,0x9f,0xfe,0xf7,0xff,0x99,0x00,0x14, 0xb3,0x01,0x0f,0x03,0x01,0xb8,0xff,0x94,0xb4,0x0c,0x0c,0x02,0x02,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xc5,0x00,0x00,0x05,0x74,0x05,0x9a,0x00,0x27,0x00,0x2b,0x00,0x82,0x00,0x00,0x01,0x07,0x01,0x9f,0xfe,0xf7,0xff,0x99,0x00,0x14,0xb3,0x01,0x0f,0x03,0x01,0xb8,0xff,0x94,0xb4,0x0c,0x0c,0x06,0x06,0x3e,0x01,0x2b, 0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xc6,0x00,0x00,0x02,0x4a,0x05,0x9a,0x00,0x27,0x00,0x2c,0x00,0xe6,0x00,0x00,0x01,0x07,0x01,0x9f,0xfe,0xf8,0xff,0x99,0x00,0x07,0xb2,0x01,0x07,0x03,0x00,0x3f,0x35,0x00,0xff,0xff,0xff,0xd1,0xff,0xe8,0x06,0x10,0x05,0xb2,0x00,0x26,0x00,0x32,0x66,0x00,0x01,0x07,0x01,0x9f,0xff,0x03,0xff,0x99, 0x00,0x12,0x40,0x0a,0x02,0x1b,0x03,0x02,0x1a,0x18,0x18,0x03,0x03,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xb3,0x00,0x00,0x05,0x48,0x05,0x9a,0x00,0x27,0x00,0x3c,0x00,0xe8,0x00,0x00,0x01,0x07,0x01,0x9f,0xfe,0xe5,0xff,0x99,0x00,0x14,0xb3,0x01,0x11,0x03,0x01,0xb8,0xff,0xc6,0xb4,0x0e,0x0e,0x05,0x05,0x3e,0x01,0x2b, 0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xd1,0x00,0x00,0x06,0x3b,0x05,0xb2,0x00,0x27,0x00,0x9f,0x00,0x92,0x00,0x00,0x01,0x07,0x01,0x9f,0xff,0x03,0xff,0x99,0x00,0x14,0xb3,0x01,0x1f,0x03,0x01,0xb8,0xff,0xe8,0xb4,0x1c,0x1c,0x12,0x12,0x3e,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0xff,0xb2,0xff,0xf4,0x02,0x5c,0x06,0x0f,0x02,0x26, 0x01,0xc9,0x00,0x00,0x01,0x06,0x01,0xa0,0xd8,0x00,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xfc,0x40,0x0b,0x0e,0x0e,0x05,0x05,0x3e,0x03,0x02,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0x9a,0x02,0x06,0x00,0x24,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00, 0x04,0x2f,0x05,0x9a,0x02,0x06,0x00,0x25,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x05,0x9a,0x02,0x06,0x00,0x28,0x00,0x00,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x05,0x9a,0x02,0x06,0x00,0x3d,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x05,0x9a,0x02,0x06,0x00,0x2b,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00, 0x01,0x64,0x05,0x9a,0x02,0x06,0x00,0x2c,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x02,0x06,0x00,0x2e,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x04,0xef,0x05,0x9a,0x00,0x0b,0x00,0x5f,0x40,0x18,0x77,0x09,0x01,0x71,0x08,0x01,0x76,0x07,0x01,0x79,0x02,0x01,0x7e,0x01,0x01,0x78,0x00,0x01,0x0a,0x08,0x0c,0x00, 0x4d,0x07,0xb8,0xff,0xf0,0x40,0x0b,0x0b,0x0c,0x00,0x4c,0x02,0x10,0x0b,0x0c,0x00,0x4c,0x0b,0xb8,0xff,0xf8,0x40,0x0e,0x0c,0x00,0x4d,0x0b,0x03,0x00,0x12,0x00,0x18,0x0b,0x0c,0x00,0x4c,0x09,0xb8,0xff,0xe8,0xb7,0x0b,0x0c,0x00,0x4c,0x00,0x00,0x0d,0x09,0x2f,0x12,0x39,0x2f,0x2b,0x2b,0x00,0x3f,0x3f,0x31,0x30,0x01,0x2b,0x2b,0x2b, 0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x33,0x04,0xef,0xbb,0xfe,0x6c,0x10,0x0c,0x04,0x0a,0x14,0xfe,0x6a,0xb4,0x02,0x0e,0xbe,0x04,0x7e,0x2f,0x47,0x3e,0x39,0xfb,0x83,0x05,0x9a,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x06,0x72,0x05,0x9a,0x02,0x06,0x00,0x30,0x00,0x00,0xff,0xff, 0x00,0xbc,0x00,0x00,0x05,0x40,0x05,0x9a,0x02,0x06,0x00,0x31,0x00,0x00,0x00,0x03,0x00,0x3a,0x00,0x00,0x03,0xdb,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x52,0x40,0x32,0x06,0x05,0x91,0x59,0x06,0x02,0x09,0x06,0x91,0x2b,0x30,0x02,0x01,0xee,0x59,0x02,0x03,0x09,0x0a,0xee,0x59,0x09,0x12,0x0f,0x04,0x5f,0x04,0x02,0x0b,0x03, 0x09,0x08,0x05,0x04,0xff,0x3a,0x30,0x01,0x70,0x01,0x02,0x00,0x01,0x00,0x01,0x0a,0x08,0x08,0x0d,0x09,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x2b,0x01,0x5f,0x5e,0x5d,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x21,0x35,0x21,0x13,0x21,0x35,0x21,0x03,0xc0, 0xfc,0x94,0x03,0x6c,0x8a,0xfd,0xa9,0x02,0x57,0xa5,0xfc,0x5f,0x03,0xa1,0x04,0xfa,0xa0,0xfc,0xee,0x99,0xfc,0xdf,0xa2,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x02,0x06,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xfc,0x05,0x9a,0x00,0x07,0x00,0x6f,0x40,0x3c,0x07,0x02,0x91,0x59,0x07,0x03,0x04,0x00, 0x12,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x01,0x01,0x01,0x10,0x0d,0x06,0x4d,0x01,0x12,0x0c,0x06,0x4d,0x01,0x01,0x09,0x04,0x06,0x0d,0x06,0x4d,0x04,0x06,0x0c,0x06,0x4d,0x04,0x06,0x0b,0x06,0x4d,0x04,0x7e,0x05,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf4,0xb3, 0x0c,0x06,0x4d,0x05,0xb8,0xff,0xfe,0xb3,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x32,0x3f,0x2b,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x04,0xfc,0xaa,0xfd,0x13,0xa9,0x04,0x40,0x04,0xfe,0xfb,0x02,0x05,0x9a,0x00,0xff,0xff,0x00,0xbc, 0x00,0x00,0x04,0x29,0x05,0x9a,0x02,0x06,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x2e,0x00,0x00,0x03,0xf0,0x05,0x9a,0x00,0x0b,0x00,0x5e,0x40,0x0c,0x05,0x0a,0x01,0x04,0x08,0x01,0x0c,0x03,0x01,0x10,0x03,0x0a,0xb8,0xff,0xe8,0xb3,0x0c,0x00,0x4d,0x08,0xb8,0xff,0xe8,0x40,0x22,0x0c,0x00,0x4d,0x03,0x18,0x0c,0x00,0x4d,0x04,0x07,0x06, 0x06,0x07,0x91,0x59,0x06,0x03,0x02,0x00,0x0b,0x00,0x0b,0x91,0x59,0x00,0x12,0x07,0x00,0x00,0x0d,0x08,0x04,0x0a,0x02,0x2f,0x33,0xc6,0x32,0x12,0x39,0x2f,0xc4,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x5d,0x21,0x21,0x35,0x01,0x01,0x35,0x21,0x15, 0x21,0x01,0x01,0x21,0x03,0xf0,0xfc,0x3e,0x01,0xd1,0xfe,0x59,0x03,0x5a,0xfd,0x9b,0x01,0x7b,0xfe,0x5c,0x02,0xcc,0x4e,0x02,0x94,0x02,0x5e,0x5a,0x9b,0xfd,0xe9,0xfd,0xac,0x00,0xff,0xff,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x02,0x06,0x00,0x37,0x00,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x02,0x06,0x00,0x3c, 0x00,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x02,0x06,0x00,0x3b,0x00,0x00,0x00,0x01,0x00,0x88,0x00,0x00,0x05,0xae,0x05,0x9a,0x00,0x19,0x00,0xca,0xb9,0x00,0x16,0xff,0xc0,0xb3,0x0c,0x00,0x4d,0x03,0xb8,0xff,0xc0,0x40,0x1a,0x0c,0x00,0x4d,0x18,0x0e,0x0b,0x01,0x0b,0x01,0x91,0x59,0x0b,0x0b,0x0c,0x14,0x00,0x06, 0x03,0x0c,0x12,0x07,0x08,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x04,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x04,0x7e,0x07,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x07,0xb8,0xff,0xf4,0x40,0x40,0x0b,0x06,0x4d,0x07,0x0e,0x0c,0x0d,0x12,0x42,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d, 0x15,0x7e,0x12,0x0d,0x0c,0x06,0x4d,0x12,0x08,0x0d,0x06,0x4d,0x12,0x0d,0x0b,0x06,0x4d,0x12,0x12,0x1a,0x18,0x01,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x7e,0x0d,0xb8,0xff,0xfb,0x40,0x0a,0x0b,0x06,0x4d,0x0d,0x0d,0x1b,0x1a,0x4f,0x1b,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b, 0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x33,0x33,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x2b,0x01,0x11,0x33,0x20,0x11,0x11,0x33,0x11,0x14,0x00,0x23,0x23,0x11,0x23,0x11,0x23,0x22,0x00,0x35,0x11,0x33,0x11, 0x10,0x21,0x33,0x11,0x03,0x68,0x39,0x01,0x6a,0xa3,0xfe,0xe2,0xef,0x39,0x9b,0x39,0xf0,0xfe,0xe4,0xa2,0x01,0x6a,0x39,0x05,0x9a,0xfc,0x80,0x01,0x6e,0x02,0x12,0xfd,0xee,0xe3,0xfe,0xe1,0xfe,0x7a,0x01,0x86,0x01,0x1f,0xe3,0x02,0x12,0xfd,0xee,0xfe,0x92,0x03,0x80,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x05,0xa9,0x05,0xb2,0x02,0x06, 0x00,0x9f,0x00,0x00,0xff,0xff,0xff,0xf1,0x00,0x00,0x02,0x38,0x06,0xe3,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x74,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x04,0x13,0x0d,0x02,0x03,0x25,0x02,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x06,0xe2, 0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x95,0x01,0x5b,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfc,0x40,0x0a,0x1d,0x17,0x05,0x00,0x25,0x02,0x01,0x1a,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x01,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x07,0x01,0x9f,0x01,0x41, 0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0e,0x29,0x27,0x0a,0x13,0x25,0x02,0x29,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x01,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x07,0x01,0x9f,0x00,0xe6,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x77,0x28,0x26,0x0c,0x11,0x25,0x01,0x28,0x11,0x26,0x00, 0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x01,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x07,0x01,0x9f,0x01,0x44,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x4b,0x17,0x15,0x07,0x02,0x25,0x01,0x17,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0xff,0xf4,0x02,0x08,0x06,0x01,0x02,0x26, 0x01,0xc9,0x00,0x00,0x01,0x06,0x01,0x9f,0xe1,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xe7,0x40,0x09,0x0e,0x0d,0x05,0x06,0x25,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x0f,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x07,0x01,0xa0,0x01,0x07,0x00,0x00,0x00,0x1e,0xb2,0x03,0x02,0x01, 0xb8,0xff,0xd8,0x40,0x0b,0x30,0x2a,0x00,0x16,0x25,0x03,0x02,0x01,0x1f,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0x02,0x00,0xa7,0xfe,0x1f,0x04,0x15,0x05,0xfc,0x00,0x14,0x00,0x25,0x00,0xc7,0xb5,0x02,0x1c,0x01,0x10,0x04,0x0f,0xb8,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x07,0xb8,0xff,0xe8,0x40,0x3e,0x0b, 0x00,0x4d,0x0d,0x15,0x16,0x16,0x15,0x96,0x59,0x16,0x16,0x06,0x13,0x06,0x1b,0x95,0x59,0x06,0x01,0x00,0x1f,0x21,0x13,0x21,0x95,0x59,0x13,0x16,0x01,0x1c,0x0c,0x15,0x15,0x01,0x09,0x08,0x0c,0x06,0x4d,0x19,0x84,0x09,0x09,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06,0x4d,0x10,0x83,0x24,0xb8,0xff,0xf0, 0xb3,0x0d,0x06,0x4d,0x24,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x24,0xb8,0xff,0xf8,0x40,0x19,0x0b,0x06,0x4d,0x24,0x24,0x27,0x1f,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x84,0x02,0xb8,0xff,0xfa,0x40,0x09,0x0c,0x06,0x4d,0x02,0x0a,0x0b,0x06,0x4d,0x02,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b, 0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x2f,0xe1,0x2b,0x11,0x39,0x2f,0x39,0x00,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x33,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x2b,0x01,0x5f,0x5e,0x5d,0x25,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16, 0x16,0x15,0x14,0x06,0x23,0x22,0x13,0x35,0x36,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x11,0x16,0x33,0x32,0x36,0x35,0x10,0x01,0x49,0xa2,0xdc,0xb9,0xad,0xc7,0x99,0x7a,0xb5,0xc3,0xf2,0xc5,0x98,0x2b,0x7b,0x9f,0xd2,0x74,0x7c,0x8c,0x86,0x81,0x91,0x2e,0xfd,0xf1,0x06,0x3c,0xbf,0xe2,0xb5,0xa0,0x78,0xd1,0x27,0x04,0x1d,0xd7,0xa6,0xc1, 0xf1,0x02,0xfe,0x83,0x11,0xad,0x6d,0xdd,0x9a,0x8c,0xfc,0x80,0x57,0x95,0x86,0x01,0x2f,0x00,0x00,0x01,0x00,0x05,0xfe,0x1f,0x03,0xe6,0x04,0x00,0x00,0x18,0x00,0x95,0xb3,0x7c,0x00,0x01,0x0c,0xb8,0xff,0xc0,0x40,0x1c,0x0b,0x0c,0x00,0x4c,0x00,0x05,0x0b,0x03,0x03,0x11,0x08,0x0f,0x03,0x1c,0x11,0x14,0x08,0x0c,0x06,0x4d,0x14,0x08, 0x0b,0x06,0x4d,0x14,0x83,0x0f,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x0f,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xe8,0x40,0x20,0x0b,0x06,0x4d,0x0f,0x0f,0x1a,0x05,0x09,0x08,0x08,0x19,0x0b,0x00,0x03,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x84,0x05,0x18,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb3,0x0c, 0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb6,0x0b,0x06,0x4d,0x05,0x05,0x1a,0x19,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0xc6,0x12,0x39,0x12,0x39,0x2f,0xcd,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0xc6,0x00,0x3f,0x3f,0xc4,0x12,0x17,0x39,0x31,0x30,0x2b,0x5d,0x05,0x10,0x07,0x23,0x36,0x11,0x26,0x02,0x27,0x33,0x12, 0x13,0x33,0x36,0x12,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x02,0x06,0x07,0x02,0x37,0x04,0xaf,0x0f,0x28,0xec,0x7a,0xbc,0xf9,0x5e,0x04,0xa6,0x7d,0x0a,0xab,0x06,0x3c,0x7f,0x31,0x45,0xfe,0xc0,0x5c,0xa9,0x01,0x46,0xd7,0x02,0x59,0xc2,0xfe,0x44,0xfe,0x4b,0xf4,0x01,0x57,0xa4,0x3e,0x44,0x35,0x20,0x86,0xfe,0xfe,0xfd,0x47,0x00,0x01, 0x00,0x4c,0xfe,0xcb,0x03,0x7f,0x05,0xec,0x00,0x17,0x00,0x69,0x40,0x41,0x0f,0x10,0x01,0x0f,0x07,0x01,0x10,0x06,0x13,0x06,0x0f,0x0b,0x0e,0x0b,0x96,0x59,0x0e,0x00,0x00,0x0c,0x0c,0x08,0x0b,0x0e,0x0e,0x16,0x01,0x16,0xed,0x03,0x03,0x19,0x11,0x08,0x0d,0x06,0x4d,0x11,0x08,0x0c,0x06,0x4d,0x11,0x08,0x0b,0x06,0x4d,0x11,0x83,0x08, 0x18,0x0d,0x06,0x4d,0x08,0x20,0x0c,0x06,0x4d,0x08,0x18,0x0b,0x06,0x4d,0x08,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0xe1,0xc6,0x10,0xc0,0x2f,0x32,0x12,0x39,0x2f,0x00,0x2f,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x33,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x01,0x23,0x36,0x35,0x34,0x26,0x27,0x24,0x11,0x10,0x01, 0x35,0x21,0x35,0x21,0x15,0x00,0x11,0x14,0x05,0x16,0x16,0x15,0x14,0x03,0x39,0xb3,0x62,0x7d,0x8a,0xfe,0x6b,0x02,0x54,0xfe,0x4c,0x02,0x5b,0xfd,0xaf,0x01,0x20,0xd3,0x96,0xfe,0xcb,0x4f,0x4d,0x44,0x3f,0x12,0x32,0x01,0x95,0x01,0xb2,0x01,0xee,0x04,0x85,0x87,0xfd,0xfb,0xfe,0x66,0xfa,0x2f,0x23,0x8b,0x6f,0x64,0x00,0x01,0x00,0x82, 0xfe,0x6c,0x03,0xf8,0x04,0x18,0x00,0x14,0x00,0x7f,0x40,0x2a,0x02,0x13,0x01,0x02,0x13,0x01,0x10,0x04,0x10,0x04,0x12,0x04,0xec,0x59,0x12,0x10,0x0c,0x0f,0x08,0x15,0x00,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x83,0x7f,0x01,0x01,0x01,0xb8,0xff,0xfc,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff, 0xfa,0x40,0x22,0x0c,0x06,0x4d,0x01,0x01,0x16,0x0c,0x0f,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x84,0x09,0x04,0x0d,0x06,0x4d,0x09,0x2f,0x16,0x01,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0xc6,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x2f,0x3f,0x3f,0x3f,0x2b,0x11,0x00, 0x33,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x01,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x27,0x33,0x16,0x15,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xa6,0xec,0x7c,0xa1,0xa3,0x24,0xa8,0x1c,0x04,0x6f,0xe5,0x01,0x5a,0xfe,0x6c,0x03,0xd0,0x01,0x47,0xb1,0x87,0xfd,0xb5,0x02,0xb6,0xea,0x60,0x4a,0x63,0xc5,0xfe,0x5e, 0x00,0x03,0x00,0x61,0xff,0xe8,0x04,0x50,0x05,0xfe,0x00,0x0a,0x00,0x10,0x00,0x17,0x00,0xc7,0x40,0x10,0x09,0x16,0x01,0x06,0x14,0x01,0x03,0x00,0x0e,0x01,0x0f,0x0a,0x01,0x10,0x06,0x09,0xb8,0xff,0xe8,0xb3,0x0c,0x00,0x4d,0x15,0xb8,0xff,0xe8,0x40,0x33,0x0b,0x0c,0x00,0x4c,0x0d,0x18,0x0c,0x00,0x4d,0x0b,0x11,0x96,0x59,0x0b,0x06, 0x00,0x0b,0x96,0x2b,0x30,0x06,0x0d,0x95,0x59,0x06,0x01,0x00,0x15,0x95,0x59,0x00,0x16,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x83,0x0b,0x11,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x11,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x11,0xb8,0xff,0xf0,0x40,0x30,0x0b,0x06,0x4d,0x20,0x11,0x30,0x11, 0x02,0x11,0x11,0x19,0x10,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08,0x0c,0x06,0x4d,0x12,0x08,0x0b,0x06,0x4d,0x12,0x83,0x03,0x10,0x0d,0x06,0x4d,0x03,0x10,0x0c,0x06,0x4d,0x03,0x10,0x0b,0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x00, 0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x2b,0x00,0x18,0x2f,0x2b,0x00,0x2b,0x2b,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x5f,0x5d,0x5d,0x05,0x22,0x00,0x11,0x10,0x00,0x33,0x20,0x11,0x10,0x00,0x13,0x02,0x21,0x22,0x02,0x07,0x05,0x21,0x12,0x12,0x33,0x32,0x12,0x02,0x4e,0xe9,0xfe,0xfc,0x01,0x0f,0xfe,0x01,0xe2,0xfe,0xf3,0x63,0x12,0xfe, 0xc9,0x96,0xb4,0x0a,0x02,0x9e,0xfd,0x61,0x05,0xb2,0x9d,0x99,0xad,0x18,0x01,0x92,0x01,0x6c,0x01,0x7f,0x01,0x99,0xfd,0x01,0xfe,0x86,0xfe,0x63,0x03,0x5c,0x02,0x2e,0xfe,0xd1,0xff,0x84,0xfe,0xe1,0xfe,0xd3,0x01,0x31,0x00,0x01,0x00,0xa6,0xff,0xf4,0x02,0x08,0x04,0x00,0x00,0x0b,0x00,0x49,0x40,0x32,0x03,0x40,0x0b,0x0c,0x00,0x4c, 0x05,0x0f,0x0b,0x09,0x02,0x09,0xec,0x59,0x02,0x0b,0x0b,0x07,0x08,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x84,0x04,0x0c,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x00,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x31,0x30, 0x2b,0x25,0x06,0x23,0x22,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x02,0x08,0x3e,0x3b,0xe9,0xa3,0x65,0x2a,0x30,0x0a,0x16,0x01,0x15,0x02,0xf7,0xfd,0x0e,0x8a,0x12,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x13,0x04,0x0e,0x00,0x14,0x00,0xa1,0x40,0x15,0x09,0x03,0x01,0x0d,0x02,0x01,0x06,0x13,0x01,0x0d,0x01,0x01,0x10,0x04,0x03,0x18, 0x0b,0x0c,0x00,0x4c,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x15,0x0b,0x06,0x4d,0x14,0x02,0x11,0x03,0x03,0x00,0x06,0x0c,0x11,0xec,0x59,0x0c,0x06,0x0f,0x04,0x00,0x15,0x14,0xb8,0xff,0xe0,0x40,0x21,0x0b,0x0c,0x00,0x4c,0x14,0x02,0x02,0x00,0x0e,0x0e,0x70,0x00,0x01,0x00,0x08,0x04,0x08,0x0d,0x06,0x4d, 0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x84,0x05,0xb8,0xff,0xfa,0x40,0x0e,0x0d,0x06,0x4d,0x05,0x06,0x0c,0x06,0x4d,0x05,0x06,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x2f,0x5d,0x33,0x2f,0x11,0x39,0x2f,0x33,0x2b,0x00,0x3f,0x33,0x3f,0xc4,0x2b,0x11,0x12,0x00,0x39,0x11,0x12,0x39,0x39, 0x31,0x30,0x01,0x2b,0x2b,0x00,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x00,0x5d,0x5d,0x21,0x23,0x01,0x07,0x11,0x23,0x11,0x33,0x11,0x01,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x07,0x04,0x13,0xcb,0xfe,0x8e,0x8d,0xa3,0xa3,0x01,0x13,0x75,0x71,0x2e,0x48,0x22,0x1e,0x32,0x42,0x90,0x73,0x01,0xf4,0x98,0xfe,0xa4,0x04,0x00,0xfe, 0x0e,0x01,0x38,0x85,0x43,0x07,0x91,0x08,0x9c,0x7d,0x00,0x01,0xff,0xfe,0x00,0x00,0x03,0xdf,0x05,0xee,0x00,0x10,0x00,0x5b,0x40,0x23,0x0b,0x02,0x01,0x07,0x10,0x01,0x08,0x05,0x01,0x06,0x03,0x01,0x03,0x0f,0x01,0x01,0x10,0x06,0x02,0x05,0x05,0x00,0x0d,0x0a,0x08,0x0d,0x08,0xec,0x59,0x0d,0x00,0x03,0x00,0x15,0x10,0xb8,0xff,0xe0, 0x40,0x0e,0x0c,0x00,0x4d,0x0a,0x02,0x05,0x0a,0x10,0x04,0x11,0x00,0x00,0x12,0x04,0x2f,0x11,0x33,0x2f,0x12,0x17,0x39,0x2f,0x2b,0x00,0x3f,0x33,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x39,0x11,0x33,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5f,0x5d,0x5d,0x5d,0x00,0x5d,0x21,0x23,0x01,0x01,0x23,0x01,0x27,0x26,0x23,0x22,0x07,0x35,0x36, 0x33,0x32,0x16,0x17,0x03,0xdf,0xb1,0xfe,0xe9,0xfe,0x9c,0xb5,0x01,0xcf,0x43,0x35,0x67,0x36,0x44,0x40,0x42,0x70,0x8b,0x3e,0x03,0x3b,0xfc,0xc5,0x03,0xf8,0xc5,0x9b,0x13,0x9d,0x0c,0x7f,0xb2,0x00,0x00,0x01,0x00,0xa7,0xfe,0x1f,0x04,0x78,0x04,0x00,0x00,0x1d,0x00,0x9f,0x40,0x6e,0x0f,0x03,0x01,0x10,0x05,0x0e,0x18,0x0b,0x0c,0x00, 0x4c,0x01,0x18,0x0b,0x0c,0x00,0x4c,0x11,0x08,0x0f,0x04,0x00,0x0d,0x02,0x0d,0x95,0x59,0x02,0x16,0x1a,0x15,0x95,0x59,0x1a,0x16,0x07,0x1c,0x17,0x17,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x08,0x0b,0x06,0x4d,0x13,0x84,0x00,0x7f,0x10,0x01,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06, 0x4d,0x10,0x10,0x1f,0x07,0x0a,0x0a,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x07,0x04,0x0d,0x06,0x4d,0x07,0x40,0x1f,0x01,0x2f,0x1f,0x01,0x5d,0x5d,0x2f,0x2b,0xf1,0x2b,0x2b,0x2b,0xc1,0x2f,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0x33,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x00,0x3f,0x3f, 0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x33,0x18,0x3f,0xc4,0x31,0x30,0x2b,0x2b,0x5f,0x5e,0x5d,0x25,0x06,0x23,0x22,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x27,0x03,0x48,0x58,0xc7,0x9b,0x40,0x04,0xa3,0xa3,0x83,0x6c,0x74,0x86,0xa3,0x7a, 0x17,0x11,0x35,0x2a,0x55,0x60,0x16,0xae,0xc6,0x7c,0xfd,0xbb,0x05,0xe1,0xfd,0x90,0x7a,0x9a,0xb0,0x8c,0x02,0x48,0xfd,0x2f,0xa6,0x05,0x89,0x0d,0x58,0x5e,0x00,0x01,0x00,0x0c,0x00,0x00,0x03,0xc6,0x04,0x00,0x00,0x0c,0x00,0x6b,0x40,0x0a,0x74,0x03,0x01,0x79,0x01,0x01,0x76,0x00,0x01,0x03,0xb8,0xff,0xf8,0x40,0x0c,0x0c,0x00,0x4d, 0x03,0x09,0x0f,0x04,0x00,0x15,0x08,0x08,0x06,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x06,0x83,0x0b,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xf8,0x40,0x0d,0x0b,0x06,0x4d,0x0b,0x0b,0x0e,0x03,0x08,0x0b,0x06,0x4d,0x03,0x02,0x2f,0x33,0x2b, 0x12,0x39,0x2f,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x00,0x3f,0x33,0x3f,0x33,0x31,0x30,0x01,0x2b,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x33,0x01,0x00,0x11,0x34,0x27,0x33,0x16,0x15,0x10,0x02,0x48,0xa4,0xfe,0x68,0xb5,0x01,0x4f,0x01,0x10,0x22,0xb1,0x17,0x04,0x00,0xfc,0x9c,0x01,0x57,0x01,0x3b,0x7a,0x58,0x46,0x74,0xfe,0x86,0x00, 0x00,0x01,0x00,0x4d,0xfe,0xc4,0x03,0x76,0x05,0xed,0x00,0x2f,0x00,0xb3,0x40,0x28,0x0f,0x08,0x01,0x10,0x05,0x28,0x18,0x0b,0x0c,0x00,0x4c,0x0b,0x18,0x0b,0x0c,0x00,0x4c,0x0c,0x26,0x1f,0x1f,0x26,0x95,0x59,0x1f,0x1f,0x16,0x06,0x18,0x15,0x13,0x16,0x15,0x16,0x15,0x95,0x59,0x16,0x00,0x2b,0xb8,0xff,0xf0,0x40,0x1e,0x0f,0x16,0x48, 0x2b,0x06,0x15,0x00,0x0c,0x23,0x12,0x18,0x15,0x1b,0x08,0x0c,0x06,0x4d,0x1b,0x83,0x0f,0x0f,0x09,0x23,0x18,0x18,0x2e,0x01,0x2e,0x84,0x03,0xb8,0xff,0xf8,0x40,0x27,0x0c,0x06,0x4d,0x03,0x03,0x31,0x29,0x08,0x0d,0x06,0x4d,0x29,0x08,0x0c,0x06,0x4d,0x29,0x08,0x0b,0x06,0x4d,0x29,0x83,0x09,0x18,0x0d,0x06,0x4d,0x09,0x20,0x0c,0x06, 0x4d,0x09,0x20,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0xe1,0xc6,0x10,0xc0,0x2f,0xc6,0x12,0x39,0x2f,0xe1,0x2b,0xc6,0x12,0x39,0x12,0x39,0x00,0x2f,0x3f,0x33,0x2b,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x10,0xc4,0x11,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x2b,0x5f,0x5e, 0x5d,0x01,0x23,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x04,0x23,0x35,0x21,0x15,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x36,0x33,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x05,0x16,0x16,0x15,0x14,0x03,0x30,0xb3,0x61,0x5d,0xa2,0xc1,0xd1,0xa3,0x96,0x6b,0x73,0xc0,0xa4,0xfe, 0xc0,0x26,0x02,0x5e,0xc7,0xee,0x58,0x89,0x2d,0x17,0x32,0x31,0x1d,0x30,0x41,0xaa,0xe3,0x01,0x1c,0xc9,0x9b,0xfe,0xc4,0x4e,0x53,0x3b,0x49,0x14,0x19,0xd7,0xad,0x84,0xce,0x37,0x1d,0x83,0x59,0x70,0xb2,0x27,0x07,0x05,0x86,0x89,0x1f,0xa5,0x73,0x47,0x62,0x28,0x03,0x03,0x96,0x03,0xa1,0x87,0xdb,0x2d,0x20,0x8b,0x76,0x69,0xff,0xff, 0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x02,0x06,0x00,0x52,0x00,0x00,0x00,0x02,0x00,0xa1,0xfe,0x74,0x04,0x50,0x04,0x18,0x00,0x0e,0x00,0x1a,0x00,0x83,0x40,0x27,0x0f,0x06,0x01,0x10,0x06,0x07,0x17,0x95,0x59,0x07,0x10,0x0f,0x00,0x12,0x0d,0x12,0x95,0x59,0x0d,0x16,0x02,0x0a,0x08,0x0d,0x06,0x4d,0x0a,0x08,0x0c,0x06,0x4d,0x0a, 0x08,0x0b,0x06,0x4d,0x0a,0x83,0x14,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x14,0xb8,0xff,0xe8,0x40,0x19,0x0b,0x06,0x4d,0x14,0x14,0x1c,0x0f,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x03,0xb8,0xff,0xfc,0x40,0x0c,0x0d,0x06,0x4d,0x03,0x06,0x0c,0x06,0x4d,0x03,0x2f,0x1c,0x01,0x5d,0x2f, 0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x2f,0x3f,0x2b,0x11,0x00,0x33,0x33,0x18,0x3f,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x25,0x23,0x11,0x23,0x11,0x34,0x12,0x33,0x32,0x00,0x15,0x10,0x02,0x23,0x22,0x03,0x16,0x16,0x33,0x20,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x48,0x04,0xa3, 0xe6,0xde,0xdf,0x01,0x0c,0xf7,0xdd,0xc1,0x77,0x27,0xa4,0x59,0x01,0x3e,0xb2,0x8c,0x8f,0x95,0x63,0xfe,0x11,0x03,0x9a,0xf7,0x01,0x13,0xfe,0xda,0xe1,0xfe,0xfb,0xfe,0xdc,0x01,0x1b,0x3e,0x51,0x01,0x94,0xaa,0xda,0xc6,0xba,0x00,0x00,0x01,0x00,0x57,0xfe,0xc4,0x03,0x81,0x04,0x19,0x00,0x1c,0x00,0x8f,0x40,0x14,0x0f,0x07,0x01,0x10, 0x04,0x13,0x30,0x0b,0x0c,0x00,0x4c,0x0f,0x11,0x0c,0x11,0x95,0x59,0x0c,0x10,0x18,0xb8,0xff,0xf0,0x40,0x0a,0x10,0x16,0x48,0x18,0x06,0x15,0x00,0x01,0x01,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf8,0x40,0x37,0x0c,0x06,0x4d,0x03,0xef,0x1b,0x10,0x0d,0x06,0x4d,0x1b,0x10,0x0c,0x06,0x4d,0x1b,0x0e,0x0e,0x1e,0x14, 0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14,0x08,0x0b,0x06,0x4d,0x14,0x83,0x09,0x10,0x0d,0x06,0x4d,0x09,0x10,0x0c,0x06,0x4d,0x09,0x18,0x0b,0x06,0x4d,0x2f,0x09,0x01,0x09,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0xd4,0x2b,0x2b,0xf1,0x2b,0x2b,0xc2,0x2f,0x00,0x2f,0x3f,0x33,0x2b,0x3f,0x2b,0x00,0x18, 0x10,0xc6,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x01,0x23,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x10,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x02,0x15,0x14,0x1e,0x02,0x05,0x16,0x15,0x14,0x03,0x3b,0xb5,0x62,0x7b,0x84,0xc2,0xd0,0x01,0x2f,0xec,0x7f,0x65,0x72,0x81,0x99,0xc9,0x2e,0x58,0x3b,0x01,0x19,0xa6,0xfe,0xc4,0x4c,0x58, 0x46,0x3f,0x11,0x19,0xe6,0xb2,0x01,0x18,0x01,0x52,0x34,0xa7,0x4f,0xfe,0xfa,0xc5,0x47,0x6c,0x45,0x12,0x4b,0x3e,0xb1,0x69,0x00,0x01,0x00,0x14,0xff,0xe6,0x04,0x0e,0x04,0x07,0x00,0x1c,0x00,0xa4,0xb7,0x0a,0x1a,0x01,0x05,0x09,0x01,0x10,0x09,0xb8,0xff,0xe0,0x40,0x2d,0x0b,0x0c,0x00,0x4c,0x13,0x0f,0x0f,0x03,0x01,0x16,0x03,0x03, 0x40,0x24,0x28,0x48,0x03,0x40,0x08,0x0f,0x19,0x0e,0xec,0x59,0x19,0x16,0x13,0x16,0x08,0x0d,0x06,0x4d,0x16,0x08,0x0c,0x06,0x4d,0x16,0x08,0x0b,0x06,0x4d,0x16,0x84,0x11,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x11,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x11,0xb8,0xff,0xf0,0x40,0x19,0x0b,0x06,0x4d,0x11,0x11,0x1e,0x05,0x0c,0x08,0x0d, 0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x84,0x1c,0xb8,0xff,0xfa,0xb3,0x0c,0x06,0x4d,0x1c,0xb8,0xff,0xfa,0xb6,0x0b,0x06,0x4d,0x1c,0x2f,0x1e,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc6,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc6,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x1a,0xcd,0x2b,0x5f, 0x5e,0x5d,0x3f,0x31,0x30,0x2b,0x01,0x5e,0x5d,0x5d,0x13,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x11,0x10,0x21,0x32,0x36,0x35,0x10,0x03,0x33,0x16,0x11,0x14,0x02,0x23,0x22,0x26,0x35,0xae,0x29,0x38,0x1a,0x1f,0x30,0x2f,0x7c,0x61,0x01,0x0d,0x7f,0x8d,0x93,0xb7,0x81,0xe8,0xc9,0xd0,0xdf,0x02,0xc7,0x5b,0x55,0x07, 0x8a,0x0d,0x94,0xa5,0xfe,0xff,0xfe,0xab,0xb1,0xa1,0x01,0x2b,0x01,0x0b,0xfa,0xfe,0xcb,0xe3,0xfe,0xf8,0xec,0xde,0x00,0x01,0x00,0x0c,0xfe,0x21,0x04,0x46,0x04,0x18,0x00,0x1d,0x00,0x8c,0xb9,0x00,0x13,0xff,0xe8,0x40,0x4e,0x0b,0x0c,0x00,0x4c,0x09,0x08,0x10,0x00,0x4d,0x03,0x18,0x0b,0x0c,0x00,0x4c,0x18,0x18,0x19,0x06,0x06,0x05, 0x07,0x17,0x07,0x15,0x15,0x14,0x09,0x09,0x0a,0x08,0x16,0x08,0x0d,0x16,0x01,0x02,0x07,0x01,0x10,0x04,0x0e,0x0c,0x11,0x0c,0xec,0x59,0x11,0x10,0x17,0x0f,0x1d,0x1b,0x02,0x1b,0xec,0x59,0x02,0x1c,0x08,0x1b,0x19,0x05,0x14,0x0a,0x05,0x0a,0x0e,0x16,0x17,0x17,0x00,0x00,0x1f,0x0e,0x07,0x0e,0x08,0x2f,0x33,0x33,0x2f,0x11,0x33,0x2f, 0x32,0x2f,0x33,0x11,0x39,0x39,0x11,0x33,0x11,0x33,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5d,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x01,0x2b,0x2b,0x2b,0x01,0x06,0x23,0x22,0x26,0x27,0x03,0x01,0x23,0x01,0x03,0x26,0x23,0x22,0x07,0x35, 0x36,0x33,0x32,0x16,0x17,0x13,0x01,0x33,0x01,0x13,0x16,0x33,0x32,0x37,0x04,0x46,0x2b,0x31,0x5a,0x82,0x4b,0x9f,0xfe,0xa1,0xb9,0x01,0xc6,0xae,0x42,0x48,0x30,0x28,0x22,0x49,0x56,0x6b,0x33,0x8c,0x01,0x11,0xb9,0xfe,0x89,0xec,0x44,0x48,0x25,0x29,0xfe,0x2a,0x09,0x86,0xac,0x01,0x6b,0xfd,0x6f,0x03,0x38,0x01,0x89,0x94,0x0e,0x9a, 0x0a,0x5c,0x78,0xfe,0xb6,0x02,0x06,0xfd,0x58,0xfd,0xf4,0x96,0x10,0x00,0x00,0x01,0x00,0x98,0xfe,0x1e,0x05,0x68,0x05,0x33,0x00,0x1b,0x00,0xec,0xb9,0x00,0x18,0xff,0xc0,0xb4,0x0b,0x0c,0x00,0x4c,0x0f,0xb8,0xff,0xc0,0x40,0x15,0x0b,0x0c,0x00,0x4c,0x0d,0x1b,0x0f,0x14,0x12,0x07,0x04,0x15,0x04,0x15,0xec,0x59,0x04,0x16,0x05,0x1c, 0x1a,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x1a,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1a,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x1a,0x83,0x1b,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x1b,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1b,0xb8,0xff,0xf0,0x40,0x40,0x0b,0x06,0x4d,0x1b,0x0e,0x04,0x07,0x0c,0x42,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08, 0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x83,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x0c,0x1c,0x15,0x12,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x18,0x0b,0x06,0x4d,0x04,0xef,0x07,0xb8,0xff,0xfa,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xfa,0xb3,0x0c,0x06,0x4d,0x07, 0xb8,0xff,0xfc,0x40,0x0d,0x0b,0x06,0x4d,0x07,0x07,0x1d,0x1c,0x40,0x1d,0x01,0x2f,0x1d,0x01,0x5d,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39, 0x18,0x2f,0x3f,0x33,0x31,0x30,0x2b,0x2b,0x01,0x10,0x00,0x23,0x23,0x11,0x23,0x11,0x23,0x22,0x00,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x32,0x36,0x35,0x11,0x33,0x05,0x68,0xfe,0xe3,0xe9,0x18,0x94,0x18,0xeb,0xfe,0xe5,0xa6,0xc8,0x98,0x18,0x94,0x18,0x96,0xca,0xa6,0x02,0x2c,0xfe,0xf4,0xfe,0xc9,0xfe,0x35, 0x01,0xcb,0x01,0x36,0x01,0x0d,0x01,0xd4,0xfe,0x2c,0xc4,0xef,0x04,0xba,0xfb,0x46,0xee,0xc5,0x01,0xd4,0x00,0x01,0x00,0x77,0xff,0xe9,0x06,0x00,0x04,0x00,0x00,0x21,0x00,0xe3,0x40,0x2a,0x0b,0x21,0x01,0x04,0x1f,0x01,0x0b,0x04,0x01,0x04,0x02,0x01,0x0d,0x00,0x01,0x10,0x04,0x12,0x12,0x20,0x09,0x1b,0x0f,0x00,0x0e,0x03,0x20,0x15, 0x20,0x15,0xec,0x59,0x20,0x16,0x0d,0x1a,0x01,0x09,0x03,0x1a,0x1a,0x18,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x18,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x18,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x18,0x83,0x1d,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1d,0xb8,0xff,0xe8,0x40,0x4f,0x0b,0x06,0x4d,0x1d,0x0e,0x12,0x11,0x06,0x42,0x02,0x09, 0x01,0x09,0x09,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x83,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x18,0x0b,0x06,0x4d,0x06,0x06,0x22,0x00,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08,0x0c,0x06,0x4d,0x12,0x08,0x0b,0x06,0x4d,0x12,0x84,0x11,0x06,0x0c,0x06,0x4d,0x11,0x11,0x23, 0x22,0x3f,0x23,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x5d,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc2,0x18,0x2f,0x5f,0x5e,0x5d,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x33,0x18,0x3f,0xc4,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x31,0x30, 0x01,0x5d,0x5d,0x5d,0x5d,0x25,0x23,0x06,0x23,0x22,0x26,0x35,0x10,0x13,0x33,0x02,0x15,0x14,0x16,0x33,0x32,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x34,0x03,0x33,0x12,0x11,0x14,0x06,0x23,0x22,0x03,0x3d,0x04,0x67,0xca,0xbd,0xd4,0x7e,0xb7,0x8f,0x7a,0x6d,0xe6,0xa4,0xe5,0x6b,0x7b,0x8e,0xb6,0x7f,0xd5,0xbf,0xca,0xa8,0xbf, 0xff,0xe0,0x01,0x02,0x01,0x36,0xfe,0xc1,0xff,0x9f,0xaa,0x01,0x5a,0x01,0x1b,0xfe,0xe5,0xfe,0xa6,0xaa,0x9f,0xff,0x01,0x3f,0xfe,0xc9,0xfe,0xff,0xe1,0xfe,0xff,0xff,0xff,0xed,0xff,0xf4,0x02,0x34,0x05,0x77,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x70,0xff,0xf0,0x00,0x17,0x40,0x0d,0x02,0x01,0x19,0x1b,0x15,0x05, 0x06,0x3e,0x02,0x01,0x18,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x05,0x77,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x96,0xff,0xf0,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xd8,0x40,0x0a,0x2c,0x26,0x00,0x16,0x25,0x02,0x01,0x29,0x11,0x26,0x00,0x2b,0x35,0x35, 0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x01,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x01,0x9f,0x01,0x28,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xf6,0x40,0x09,0x19,0x19,0x0c,0x0c,0x3e,0x02,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x01,0x02,0x26, 0x01,0xd2,0x00,0x00,0x01,0x07,0x01,0x9f,0x01,0x0f,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x05,0x1f,0x1d,0x00,0x16,0x25,0x01,0x1f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xff,0xe9,0x06,0x00,0x06,0x01,0x02,0x26,0x01,0xd5,0x00,0x00,0x01,0x07,0x01,0x9f,0x02,0x02,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x1b, 0x24,0x22,0x06,0x1d,0x25,0x01,0x24,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x06,0xe3,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x8b,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x05,0x21,0x0f,0x02,0x03,0x3e,0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35, 0x35,0x00,0x00,0x01,0x00,0x29,0xff,0xee,0x05,0x1e,0x05,0x9a,0x00,0x1b,0x00,0xb6,0x40,0x2f,0x00,0x16,0x01,0x10,0x05,0x13,0x0a,0x91,0x59,0x13,0x13,0x10,0x0b,0x0d,0x11,0x10,0x11,0x91,0x59,0x10,0x03,0x01,0x03,0x1a,0x03,0x91,0x59,0x1a,0x13,0x0b,0x12,0x00,0x00,0x0b,0x17,0x08,0x0d,0x06,0x4d,0x17,0x08,0x0c,0x06,0x4d,0x17,0x7d, 0x06,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf8,0x40,0x1d,0x0b,0x06,0x4d,0x06,0x06,0x1d,0x13,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x7e,0x0c,0x11,0x11,0x1d,0x0e,0xb8,0xff,0xe8,0x40,0x0a,0x0d,0x06,0x4d,0x0e,0x0c,0x20,0x0d,0x06, 0x4d,0x0c,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0c,0xb8,0xff,0xf0,0xb3,0x0b,0x06,0x4d,0x0c,0x2f,0x2b,0x2b,0x2b,0xc6,0x2b,0x12,0x39,0x2f,0x10,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x2b, 0x31,0x30,0x00,0x5f,0x5e,0x5d,0x25,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x33,0x32,0x04,0x15,0x14,0x06,0x23,0x22,0x02,0xfe,0x42,0x5e,0x61,0x73,0xa9,0x98,0xf9,0xa8,0xfe,0x99,0x03,0xe3,0xfe,0x2c,0xfd,0xe2,0x01,0x07,0xc7,0xb5,0x5c,0x06,0x9a,0x21,0x8b,0x77,0x8b,0x9a, 0xfd,0x5a,0x05,0x02,0x98,0x98,0xfe,0x38,0xe6,0xd1,0xc0,0xd5,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x07,0x66,0x02,0x26,0x01,0x2c,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x50,0x01,0x5c,0x00,0x17,0x40,0x0e,0x01,0x15,0x08,0x06,0x01,0x05,0x3e,0x01,0x00,0x08,0x01,0x08,0x05,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0x00,0x01, 0x00,0x5e,0xff,0xe8,0x04,0x85,0x05,0xb2,0x00,0x18,0x00,0x97,0x40,0x5f,0x55,0x0a,0x01,0x59,0x00,0x01,0x5a,0x03,0x01,0x03,0x0f,0x03,0x01,0x0b,0x05,0x10,0x13,0x91,0x59,0x10,0x08,0x02,0x10,0x91,0x2b,0x30,0x00,0x0b,0x01,0x0c,0x03,0x0b,0x0b,0x0d,0x08,0x0d,0x91,0x59,0x08,0x04,0x00,0x18,0x01,0x0b,0x03,0x18,0x18,0x16,0x02,0x16, 0x91,0x59,0x02,0x13,0x11,0x11,0x13,0x00,0x0a,0x0a,0x1a,0x10,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x08,0x0b,0x06,0x4d,0x13,0x7d,0x05,0x10,0x0d,0x06,0x4d,0x05,0x18,0x0c,0x06,0x4d,0x05,0x18,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x00,0x3f,0x2b, 0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x01,0x5f,0x5d,0x00,0x5d,0x5d,0x25,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x07,0x21,0x15,0x21,0x16,0x00,0x33,0x32,0x37,0x04,0x85,0x9e,0xeb, 0xfe,0xd1,0xfe,0x91,0x01,0x85,0x01,0x35,0xd6,0x97,0xa3,0xcc,0xd7,0xfe,0xeb,0x18,0x02,0x7a,0xfd,0x84,0x10,0x01,0x11,0xd7,0xe0,0x9d,0x3c,0x54,0x01,0x8b,0x01,0x3f,0x01,0x5b,0x01,0xa5,0x3b,0xb3,0x56,0xfe,0xed,0xf1,0x97,0xef,0xfe,0xef,0x60,0x00,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x05,0xb2,0x02,0x06,0x00,0x36,0x00,0x00, 0xff,0xff,0xff,0xf1,0x00,0x00,0x02,0x38,0x06,0xe3,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x74,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x04,0x13,0x0d,0x02,0x03,0x25,0x02,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x00,0x02,0x00,0x10,0xff,0xe9,0x07,0x77,0x05,0x9a,0x00,0x19,0x00,0x21, 0x00,0xc0,0x40,0x49,0x0d,0x05,0x01,0x00,0x03,0x01,0x0b,0x17,0x01,0x0b,0x16,0x01,0x02,0x0d,0x01,0x10,0x04,0x12,0x14,0x0f,0x14,0x91,0x59,0x0f,0x13,0x00,0x1a,0x91,0x59,0x00,0x00,0x18,0x1b,0x18,0x0a,0x91,0x59,0x18,0x03,0x08,0x1b,0x91,0x59,0x08,0x12,0x0a,0x08,0x0b,0x06,0x4d,0x0a,0x18,0x18,0x08,0x11,0x04,0x08,0x0d,0x06,0x4d, 0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x7d,0x1f,0xb8,0xff,0xf0,0x40,0x23,0x0d,0x06,0x4d,0x1f,0x10,0x0b,0x06,0x4d,0x1f,0x1f,0x23,0x00,0x1b,0x08,0x0d,0x06,0x4d,0x1b,0x08,0x0c,0x06,0x4d,0x1b,0x08,0x0b,0x06,0x4d,0x1b,0x7e,0x08,0x18,0x0d,0x06,0x4d,0x08,0xb8,0xff,0xf8,0x40,0x0c,0x0c,0x06,0x4d,0x08,0x18,0x0b, 0x06,0x4d,0x08,0x08,0x23,0x11,0x2f,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x33,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5d,0x5d,0x00, 0x5d,0x5d,0x01,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x21,0x02,0x02,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x12,0x13,0x21,0x11,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x04,0xa4,0x01,0x10,0xd7,0xec,0xf8,0xd9,0xfe,0x56,0xfe,0x72,0x45,0x50,0x52,0x8c,0x62,0x4f,0x3a,0x33,0x3e,0x3e,0x6d,0x71,0x45,0x02,0xc2,0xeb, 0x96,0xa2,0xfe,0xc8,0x03,0x39,0xce,0xbf,0xc4,0xe8,0x05,0x02,0xfd,0xe2,0xfe,0x40,0xd4,0x67,0x15,0x9e,0x1d,0x94,0x02,0x6e,0x02,0x19,0xfd,0x08,0xfd,0xf6,0x8d,0x7d,0x01,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x07,0x7d,0x05,0x9a,0x00,0x12,0x00,0x1a,0x00,0xb7,0x40,0x2f,0x0d,0x10,0x01,0x00,0x0e,0x01,0x10,0x04,0x13,0x0b,0x01,0x08, 0x08,0x01,0x91,0x59,0x08,0x08,0x14,0x06,0x0a,0x03,0x00,0x14,0x91,0x59,0x03,0x00,0x12,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x18,0xb8,0xff,0xe8,0x40,0x3e,0x0d,0x06,0x4d,0x18,0x10,0x0b,0x06,0x4d,0x18,0x18,0x1c,0x0b,0x08,0x14,0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14, 0x08,0x0b,0x06,0x4d,0x14,0x7e,0x00,0x20,0x0d,0x06,0x4d,0x00,0x18,0x0b,0x06,0x4d,0x00,0x00,0x1c,0x07,0x03,0x08,0x0d,0x06,0x4d,0x03,0x08,0x0c,0x06,0x4d,0x03,0x08,0x0b,0x06,0x4d,0x03,0x7e,0x04,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39, 0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0xc4,0x2b,0x00,0x18,0x3f,0xc4,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x21,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32, 0x36,0x35,0x10,0x21,0x04,0x02,0xfd,0x62,0xa8,0xa8,0x02,0x9e,0xa8,0x01,0x10,0xd5,0xee,0xf9,0xd8,0xfe,0xfe,0xec,0x95,0xa2,0xfe,0xc9,0x02,0xa0,0xfd,0x60,0x05,0x9a,0xfd,0x9e,0x02,0x62,0xfd,0xa0,0xce,0xc0,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8d,0x7d,0x01,0x00,0x00,0x01,0x00,0x29,0x00,0x00,0x05,0x4a,0x05,0x9a,0x00,0x11,0x00,0xc6, 0x40,0x1c,0x02,0x10,0x01,0x02,0x10,0x01,0x10,0x04,0x0e,0x05,0x91,0x59,0x0e,0x0e,0x00,0x0b,0x08,0x0c,0x0b,0x0c,0x91,0x59,0x0b,0x03,0x06,0x00,0x12,0x0c,0xb8,0xff,0xf9,0xb3,0x0b,0x06,0x4d,0x09,0xb8,0xff,0xf9,0x40,0x15,0x0b,0x06,0x4d,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x01, 0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf0,0x40,0x32,0x0b,0x06,0x4d,0x00,0x01,0x01,0x09,0x03,0x01,0x01,0x13,0x07,0x0c,0x0e,0x0e,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x7e,0x07,0x07,0x09,0x42,0x09,0x09,0x12,0x07,0x12,0x0d,0x06, 0x4d,0x07,0x0d,0x0c,0x06,0x4d,0x07,0xb8,0xff,0xe4,0xb3,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x01,0x10,0xf1,0x2b,0x2b,0x2b,0x32,0xe0,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x3f,0xc4,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x2b,0x31,0x30, 0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x21,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x21,0x20,0x11,0x05,0x4a,0xa8,0xfe,0xe3,0xfe,0xe9,0xa8,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x01,0x19,0x01,0xc3,0x01,0x85,0x01,0x27,0xfd,0x54,0x05,0x02,0x98,0x98,0xfe,0x3e,0xfe,0x45,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2, 0x07,0x66,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x8e,0x01,0x5c,0x00,0x17,0x40,0x0e,0x01,0x0f,0x12,0x12,0x09,0x0e,0x25,0x01,0x00,0x13,0x01,0x13,0x05,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x3c,0xff,0xe7,0x04,0x96,0x07,0x4f,0x02,0x26,0x01,0xfa,0x00,0x00,0x01,0x07,0x07,0xcd,0x00,0x16, 0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x0d,0x1c,0x16,0x0d,0x00,0x25,0x01,0x19,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xbc,0xfe,0x80,0x04,0xf2,0x05,0x9a,0x00,0x0b,0x00,0xb2,0xb9,0x00,0x02,0x01,0x30,0x40,0x1b,0x07,0x0b,0x03,0x04,0x00,0x00,0x09,0x91,0x59,0x00,0x12,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c, 0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0xb8,0x01,0x2c,0xb6,0x04,0x04,0x10,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x08,0x09,0x04,0xb8,0x01,0x2c,0x40,0x1e,0xff,0x30,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x09,0x10,0x0d,0x06,0x4d,0x09,0x10,0x0c,0x06,0x4d,0x09, 0xb8,0xff,0xf8,0x40,0x1b,0x0b,0x06,0x4d,0x7f,0x09,0x01,0x09,0x09,0x0d,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x7e,0x05,0xb8,0xff,0xf4,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b, 0x2b,0x2b,0x2b,0x01,0x2b,0x2b,0x10,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x33,0x3f,0x31,0x30,0x21,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x04,0xf2,0xfe,0x30,0x9a,0xfe,0x34,0xa8,0x02,0xe6,0xa8,0xfe,0x80,0x01,0x80,0x05,0x9a,0xfa,0xfe,0x05,0x02,0x00,0xff,0xff,0x00,0x16,0x00,0x00, 0x05,0x12,0x05,0x9a,0x02,0x06,0x00,0x24,0x00,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x38,0x05,0x9a,0x00,0x0c,0x00,0x14,0x00,0x9f,0x40,0x31,0x0d,0x0a,0x01,0x00,0x08,0x01,0x10,0x04,0x05,0x0d,0x91,0x59,0x05,0x05,0x0e,0x02,0x02,0x03,0x91,0x59,0x02,0x03,0x00,0x0e,0x91,0x59,0x00,0x12,0x03,0x03,0x0e,0x09,0x08,0x0d,0x06,0x4d, 0x09,0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x7d,0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf8,0x40,0x1e,0x0c,0x06,0x4d,0x12,0x10,0x0b,0x06,0x4d,0x12,0x12,0x16,0x05,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x7e,0x00,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x00, 0xb8,0xff,0xf6,0x40,0x09,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x33,0x11,0x21,0x15,0x21,0x11,0x21, 0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0xbc,0x02,0xfe,0xfd,0xaa,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa2,0xfe,0xc9,0x05,0x9a,0x98,0xfe,0x38,0xcf,0xbf,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8c,0x7e,0x01,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x2f,0x05,0x9a,0x02,0x06,0x00,0x25, 0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x06,0x01,0x2c,0x00,0x00,0x00,0x02,0x00,0x0f,0xfe,0x7f,0x05,0x48,0x05,0x9a,0x00,0x0d,0x00,0x13,0x00,0xcf,0xb7,0x0b,0x0f,0x91,0x59,0x0b,0x03,0x04,0x01,0xb8,0x01,0x30,0x40,0x22,0x0e,0x07,0x02,0x0c,0x02,0x0c,0x91,0x59,0x02,0x12,0x75,0x13,0x01,0x10,0x0a,0x0a, 0x0e,0x07,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x18,0x0b,0x06,0x4d,0x0d,0xba,0x01,0x2c,0x00,0x02,0xff,0xee,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xe0,0x40,0x17,0x0b,0x06,0x4d,0x02,0x02,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c, 0x7e,0x0e,0xb8,0xff,0xf0,0x40,0x21,0x0d,0x06,0x4d,0x0e,0x18,0x0c,0x06,0x4d,0x0e,0x20,0x0b,0x06,0x4d,0x0e,0x0e,0x15,0x07,0x03,0x08,0x0d,0x06,0x4d,0x03,0x08,0x0c,0x06,0x4d,0x03,0x10,0x0b,0x06,0x4d,0x06,0xb8,0x01,0x2c,0xb2,0x03,0x13,0x07,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x07,0x2f, 0x2b,0x2b,0x33,0xd5,0xe1,0x2b,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc1,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x33,0x5d,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0xc4,0x3f,0x2b,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x12,0x12,0x13,0x21,0x11,0x33,0x21, 0x11,0x21,0x06,0x02,0x07,0x05,0x48,0x9b,0xfb,0xfd,0x9b,0x6f,0x90,0xc9,0x0d,0x02,0xa3,0xc1,0xfe,0x97,0xfe,0x94,0x10,0xbc,0x73,0xfe,0x7f,0x01,0x81,0xfe,0x7f,0x02,0x19,0x01,0x07,0x02,0xbf,0x01,0x3c,0xfa,0xfe,0x04,0x6a,0xf7,0xfd,0x6a,0xdd,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x05,0x9a,0x02,0x06,0x00,0x28,0x00,0x00, 0x00,0x01,0xff,0xea,0x00,0x00,0x07,0x02,0x05,0x9a,0x00,0x1d,0x00,0xb1,0xb9,0x00,0x1d,0xff,0xf0,0x40,0x72,0x0c,0x06,0x4d,0x0e,0x10,0x0c,0x06,0x4d,0x5c,0x1b,0x01,0x1a,0x1b,0x01,0x53,0x10,0x01,0x15,0x10,0x01,0x53,0x0c,0x01,0x05,0x0c,0x15,0x0c,0x02,0x5c,0x01,0x01,0x03,0x0d,0x01,0x1d,0x01,0x02,0x10,0x1a,0x01,0x10,0x11,0x01, 0x0f,0x0b,0x1f,0x0b,0x02,0x0f,0x02,0x1f,0x02,0x02,0x0b,0x04,0x1b,0x10,0x16,0x03,0x0c,0x01,0x06,0x12,0x1d,0x00,0x06,0x0e,0x0d,0x07,0x1c,0x1c,0x00,0x20,0x0b,0x06,0x4d,0x00,0x0e,0x06,0x07,0x0d,0x42,0x0f,0x0d,0x0d,0x1e,0x16,0x15,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x7e,0x07,0x07, 0x1f,0x1e,0x2f,0x1f,0x3f,0x1f,0x02,0x5d,0x11,0x12,0x39,0x2f,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x11,0x33,0x2f,0xc6,0x2b,0x01,0x10,0xf0,0x2b,0xc2,0x18,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x3f,0x33,0x33,0x3f,0x33,0x33,0x31,0x30,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x2b,0x2b,0x21, 0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x01,0x16,0x17,0x33,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x07,0x02,0xe1,0xfd,0xcf,0x18,0x0d,0x05,0x9f,0x04,0x0f,0x16,0xfd,0xcf,0xe3,0x02,0x91,0xfd,0x9b,0xce,0x02,0x1a,0x16,0x0f,0x04,0x9f,0x05,0x0d,0x18,0x02,0x1a,0xcd,0xfd,0x9b,0x02, 0x90,0x1c,0x16,0xfd,0x3e,0x02,0xc2,0x19,0x19,0xfd,0x70,0x02,0xe8,0x02,0xb2,0xfd,0x93,0x19,0x18,0x02,0x9e,0xfd,0x62,0x16,0x1b,0x02,0x6d,0xfd,0x4e,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0xe2,0x05,0xb2,0x00,0x23,0x00,0xd7,0x40,0x13,0x09,0x20,0x01,0x06,0x1e,0x01,0x04,0x18,0x01,0x03,0x00,0x14,0x01,0x0f,0x00,0x01,0x10,0x05, 0x14,0xb8,0xff,0xc0,0x40,0x3c,0x0c,0x00,0x4d,0x00,0x40,0x0c,0x00,0x4d,0x1c,0x09,0x0a,0x0a,0x09,0x92,0x59,0x0a,0x0a,0x03,0x16,0x0f,0x13,0x1f,0x13,0x2f,0x13,0x03,0x09,0x03,0x13,0x11,0x16,0x11,0x92,0x59,0x16,0x04,0x00,0x01,0x10,0x01,0x20,0x01,0x03,0x09,0x03,0x01,0x03,0x22,0x03,0x92,0x59,0x22,0x13,0x1b,0x1f,0x09,0x09,0x06, 0x00,0x0e,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x0e,0xb8,0xff,0xf8,0x40,0x19,0x0b,0x06,0x4d,0x0e,0x7d,0x19,0x19,0x1f,0x08,0x0d,0x06,0x4d,0x1f,0x08,0x0c,0x06,0x4d,0x1f,0x08,0x0b,0x06,0x4d,0x1f,0x7d,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf8,0x40,0x0e,0x0b,0x06,0x4d,0x20,0x06,0x01,0x06,0x06,0x25,0x13,0x00, 0x3f,0x25,0x01,0x5d,0x2f,0xc4,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x2f,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x5f, 0x5d,0x5d,0x5d,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x10,0x05,0x15,0x16,0x16,0x15,0x14,0x04,0x23,0x22,0x60,0xa8,0xd5,0x9b,0xb7,0xfe,0x8b,0x95,0x89,0x9f,0xaf,0x91,0x7f,0xb4,0xaa,0x9e,0xce,0xcc,0xea,0xfe,0xf0,0x94,0xae,0xfe,0xe8, 0xf3,0xf3,0x3c,0xb6,0x7b,0x96,0x7f,0x01,0x14,0x8b,0x8a,0x7e,0x6c,0x82,0x71,0xaa,0x58,0xc2,0x9e,0xfe,0xe9,0x49,0x04,0x11,0xbc,0x8b,0xc5,0xe9,0x00,0x01,0x00,0xbc,0x00,0x00,0x05,0x40,0x05,0x9a,0x00,0x13,0x00,0xa1,0x40,0x12,0x7a,0x12,0x01,0x79,0x11,0x01,0x75,0x08,0x01,0x75,0x07,0x01,0x12,0x08,0x0b,0x00,0x4d,0x08,0xb8,0xff, 0xf8,0x40,0x2c,0x0b,0x00,0x4d,0x0e,0x04,0x0b,0x13,0x03,0x09,0x00,0x12,0x12,0x04,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x01,0x01,0x01,0x18,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf4,0x40,0x1a,0x0b,0x06,0x4d,0x01,0x01,0x15,0x08,0x0e,0x0c,0x08,0x0d,0x06, 0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x7e,0x09,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x09,0x04,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x39,0x33,0x00,0x3f,0x32,0x3f,0x33, 0x39,0x39,0x31,0x30,0x01,0x2b,0x2b,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x01,0x23,0x11,0x33,0x11,0x14,0x07,0x33,0x36,0x37,0x01,0x33,0x05,0x40,0xa8,0x0a,0x06,0x13,0x1b,0xfd,0x1e,0xd0,0xa8,0x08,0x04,0x16,0x22,0x02,0xd0,0xd8,0x04,0x0c,0x8c,0x39,0x31,0x29,0xfb,0x89,0x05,0x9a,0xfc,0x0e,0xa2,0x31,0x2c, 0x34,0x04,0x65,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x4e,0x02,0x26,0x01,0xef,0x00,0x00,0x01,0x07,0x07,0xcd,0x00,0xa8,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x0a,0x1a,0x14,0x0a,0x13,0x25,0x01,0x17,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x02,0x06,0x00,0x2e, 0x00,0x00,0x00,0x01,0x00,0x10,0xff,0xe9,0x04,0xa4,0x05,0x9a,0x00,0x12,0x00,0x74,0x40,0x43,0x0d,0x10,0x01,0x0b,0x0f,0x01,0x02,0x06,0x01,0x10,0x04,0x07,0x18,0x0b,0x00,0x4d,0x12,0x02,0x91,0x59,0x12,0x03,0x0b,0x0d,0x08,0x0d,0x91,0x59,0x08,0x13,0x00,0x12,0x03,0x11,0x11,0x0b,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d, 0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x01,0x01,0x01,0x18,0x0d,0x06,0x4d,0x01,0x04,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf4,0xb6,0x0b,0x06,0x4d,0x01,0x01,0x14,0x0b,0x2f,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x33,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x31,0x30,0x00,0x2b,0x01,0x5f, 0x5e,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x02,0x02,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x12,0x13,0x21,0x04,0xa4,0xa8,0xfe,0x72,0x45,0x50,0x52,0x8c,0x62,0x4f,0x3a,0x33,0x3e,0x3e,0x6d,0x71,0x45,0x02,0xc2,0x05,0x02,0xfd,0xe2,0xfe,0x40,0xd4,0x67,0x15,0x9e,0x1d,0x94,0x02,0x6e,0x02,0x19,0x00,0xff,0xff,0x00,0xbc, 0x00,0x00,0x06,0x72,0x05,0x9a,0x02,0x06,0x00,0x30,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x05,0x9a,0x02,0x06,0x00,0x2b,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x02,0x06,0x00,0x32,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xfc,0x05,0x9a,0x02,0x06,0x01,0xb5,0x00,0x00,0xff,0xff,0x00,0xbc, 0x00,0x00,0x04,0x29,0x05,0x9a,0x02,0x06,0x00,0x33,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x02,0x06,0x00,0x26,0x00,0x00,0xff,0xff,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x02,0x06,0x00,0x37,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0xe7,0x04,0x96,0x05,0x9a,0x00,0x15,0x00,0x53,0x40,0x2e,0x0a,0x15,0x01,0x05, 0x0e,0x01,0x03,0x03,0x10,0x0c,0x00,0x4d,0x00,0x10,0x01,0x10,0x05,0x10,0x0c,0x04,0x0e,0x00,0x03,0x07,0x09,0x04,0x09,0x91,0x59,0x04,0x13,0x76,0x11,0x01,0x11,0x0c,0x14,0x06,0x14,0x00,0x00,0x16,0x06,0x06,0x0e,0x0d,0x2f,0x33,0x33,0x2f,0x11,0x33,0x2f,0x32,0x11,0x12,0x39,0x39,0x5d,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x33, 0x12,0x39,0x39,0x5f,0x5e,0x5d,0x31,0x30,0x2b,0x01,0x5f,0x5d,0x5d,0x01,0x01,0x02,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x04,0x96,0xfe,0x45,0x76,0xdc,0x82,0x6b,0x48,0x56,0x50,0x51,0x88,0x4f,0xfe,0x1a,0xbf,0x01,0x58,0x09,0x1c,0x02,0x03,0x26,0x01,0x3f,0x05,0x9a,0xfc, 0x17,0xfe,0xf6,0xc0,0x1f,0xaa,0x33,0x7d,0x9e,0x04,0x02,0xfd,0x02,0x13,0x4a,0x09,0x58,0x02,0xfa,0x00,0x00,0x03,0x00,0x5e,0x00,0x00,0x05,0x81,0x05,0xc2,0x00,0x15,0x00,0x1e,0x00,0x27,0x01,0x02,0xb9,0x00,0x13,0xff,0xe8,0x40,0x23,0x0c,0x00,0x4d,0x1f,0x03,0x00,0x17,0x00,0x17,0x91,0x59,0x20,0x0b,0x16,0x0e,0x0e,0x16,0x91,0x59, 0x0e,0x00,0x0e,0x00,0x01,0x0d,0x03,0x01,0x12,0x1b,0x18,0x0b,0x0c,0x00,0x4c,0x24,0xb8,0xff,0xe8,0xb4,0x0b,0x0c,0x00,0x4c,0x1b,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x1b,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x1b,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x1b,0x7d,0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf8,0x40,0x2a, 0x0c,0x06,0x4d,0x12,0x20,0x0b,0x06,0x4d,0x12,0x0e,0x01,0x02,0x07,0x42,0x24,0x08,0x0d,0x06,0x4d,0x24,0x08,0x0c,0x06,0x4d,0x24,0x08,0x0b,0x06,0x4d,0x24,0x7d,0x07,0x18,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0xb8,0xff,0xe0,0x40,0x1d,0x0b,0x06,0x4d,0x07,0x07,0x28,0x0b,0x0e,0x16,0x20,0x04,0x01,0x08,0x0d,0x06,0x4d,0x01, 0x08,0x0c,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x01,0xef,0x02,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf5,0x40,0x0a,0x0b,0x06,0x4d,0x02,0x02,0x29,0x28,0x20,0x29,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1, 0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x2b,0x25,0x15,0x23,0x35,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x33,0x35,0x33,0x15,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x03,0x11, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x03,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x03,0x3e,0x9c,0x1b,0xf0,0xfe,0xc7,0x01,0x38,0xf3,0x19,0x9c,0x18,0xf6,0x01,0x35,0xfe,0xc7,0xf0,0x1a,0x1a,0xab,0xce,0xce,0xad,0xb4,0x19,0xaa,0xd1,0xce,0xab,0xbc,0xbc,0xbc,0x01,0x47,0xef,0xe4,0x01,0x38,0xb4,0xb4,0xfe,0xcd,0xe9,0xec,0xfe,0xb6, 0x03,0xc5,0xfc,0xcf,0xe3,0xbd,0xb4,0xdd,0xfc,0xcf,0x03,0x31,0xe0,0xb1,0xbe,0xe2,0xff,0xff,0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x02,0x06,0x00,0x3b,0x00,0x00,0x00,0x01,0x00,0xbc,0xfe,0x7f,0x05,0xb2,0x05,0x9a,0x00,0x0b,0x00,0xb4,0xb9,0x00,0x00,0x01,0x30,0x40,0x1c,0x05,0x09,0x03,0x07,0x02,0x0a,0x02,0x0a,0x91,0x59,0x02, 0x12,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x10,0x0b,0x06,0x4d,0x0b,0xba,0x01,0x2c,0x00,0x02,0xff,0xe4,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xec,0x40,0x17,0x0b,0x06,0x4d,0x02,0x02,0x0a,0x08,0x0d,0x06,0x4d,0x0a,0x08,0x0c,0x06,0x4d,0x0a,0x08,0x0b,0x06,0x4d,0x0a,0x7e, 0x07,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xe0,0x40,0x1d,0x0c,0x06,0x4d,0x07,0x10,0x0b,0x06,0x4d,0x07,0x07,0x0d,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x7e,0x03,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0xe1,0x2b, 0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc1,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x05,0xb2,0x9b,0xfb,0xa5,0xa8,0x02,0xe6,0xa8,0xc0,0xfe,0x7f,0x01,0x81,0x05,0x9a,0xfa,0xfe, 0x05,0x02,0xfa,0xfe,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x81,0x05,0x9a,0x00,0x10,0x00,0x85,0x40,0x34,0x0f,0x06,0x01,0x10,0x04,0x0e,0x02,0x0c,0x04,0x0c,0x91,0x59,0x04,0x04,0x00,0x09,0x10,0x03,0x00,0x12,0x02,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06,0x4d,0x10,0x7e,0x7f,0x0f,0x01,0x0f,0x20,0x0d, 0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xf8,0x40,0x18,0x0b,0x06,0x4d,0x0f,0x0f,0x12,0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x7e,0x08,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x08,0x0c,0x0b,0x06,0x4d,0x08,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b, 0x5d,0xe1,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x3f,0x32,0x12,0x39,0x2f,0x2b,0x11,0x00,0x33,0x33,0x31,0x30,0x5f,0x5e,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x04,0x81,0xa8,0xe5,0xc5,0xbc,0xcd,0xa8,0xf6,0xb2,0xe3,0xa8,0x02,0x85,0x79,0xc3,0xb0,0x02,0x1b,0xfd,0xed,0xe7,0x6e,0x02, 0x8c,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x06,0xd9,0x05,0x9a,0x00,0x0b,0x00,0xa7,0x40,0x0e,0x07,0x03,0x0b,0x03,0x05,0x00,0x09,0x00,0x09,0x91,0x59,0x00,0x12,0x09,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xf8,0x40,0x22,0x0b,0x06,0x4d,0x09,0x7e,0x00,0x12,0x0d,0x06,0x4d,0x00, 0x0e,0x08,0x01,0x05,0x42,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x7e,0x01,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x28,0x0c,0x06,0x4d,0x01,0x01,0x0c,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x7e,0x05,0x06,0x0d,0x06,0x4d, 0x10,0x05,0x01,0x05,0x05,0x0d,0x0c,0x2f,0x0d,0x4f,0x0d,0x02,0x5d,0x11,0x12,0x39,0x2f,0x5d,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf1,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x3f,0x33,0x33,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11, 0x21,0x11,0x33,0x06,0xd9,0xf9,0xe3,0xa8,0x02,0x13,0xa7,0x02,0x13,0xa8,0x05,0x9a,0xfa,0xfe,0x05,0x02,0xfa,0xfe,0x05,0x02,0x00,0x01,0x00,0xbc,0xfe,0x7f,0x07,0x9a,0x05,0x9a,0x00,0x0f,0x00,0xff,0xb9,0x00,0x01,0x01,0x30,0x40,0x1e,0x09,0x05,0x0d,0x03,0x0b,0x07,0x02,0x0e,0x02,0x0e,0x91,0x59,0x02,0x12,0x0f,0x08,0x0d,0x06,0x4d, 0x0f,0x08,0x0c,0x06,0x4d,0x0f,0x10,0x0b,0x06,0x4d,0x0f,0xba,0x01,0x2c,0x00,0x02,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xe8,0xb5,0x0b,0x06,0x4d,0x02,0x02,0x0b,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xf8,0xb5,0x0b,0x06,0x4d, 0x0b,0x7e,0x0e,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x0e,0xb8,0xff,0xf8,0x40,0x23,0x0c,0x06,0x4d,0x0e,0x06,0x0b,0x06,0x4d,0x0e,0x0e,0x0a,0x07,0x03,0x42,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x7e,0x6f,0x03,0x01,0x03,0xb8,0xff,0xf0,0x40,0x18,0x0d,0x06,0x4d,0x03,0x03,0x10,0x0a,0x08, 0x0d,0x06,0x4d,0x0a,0x08,0x0c,0x06,0x4d,0x0a,0x08,0x0b,0x06,0x4d,0x0a,0x7e,0x07,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf0,0x40,0x0f,0x0c,0x06,0x4d,0x07,0x06,0x0b,0x06,0x4d,0x07,0x07,0x11,0x10,0x4f,0x11,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b, 0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc1,0x18,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0x33,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x07,0x9a,0x9b,0xf9,0xbd,0xa8,0x02,0x13,0xa8,0x02,0x12, 0xa8,0xc1,0xfe,0x7f,0x01,0x81,0x05,0x9a,0xfa,0xfe,0x05,0x02,0xfa,0xfe,0x05,0x02,0xfa,0xfe,0x00,0x02,0x00,0x29,0x00,0x00,0x05,0x42,0x05,0x9a,0x00,0x0c,0x00,0x14,0x00,0x98,0x40,0x29,0x0d,0x0a,0x01,0x00,0x08,0x01,0x10,0x04,0x05,0x0d,0x91,0x59,0x05,0x05,0x0e,0x04,0x04,0x01,0x91,0x59,0x04,0x03,0x00,0x0e,0x91,0x59,0x00,0x12, 0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06,0x4d,0x09,0x7d,0x12,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf8,0x40,0x25,0x0c,0x06,0x4d,0x12,0x12,0x16,0x00,0x02,0x02,0x15,0x05,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x7e,0x70,0x00,0x01,0x00,0x10,0x0d,0x06,0x4d,0x00,0xb8, 0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xe0,0xb3,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x21,0x11,0x21,0x35,0x21,0x11, 0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0xc6,0xfe,0x63,0x02,0x45,0x01,0x11,0xd5,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa3,0xfe,0xc8,0x05,0x00,0x9a,0xfd,0xa0,0xce,0xc0,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8d,0x7d,0x01,0x00,0x00,0x00,0x03,0x00,0xbc,0x00,0x00,0x05,0x87,0x05,0x9a,0x00,0x03, 0x00,0x0e,0x00,0x16,0x00,0xb0,0x40,0x44,0x0d,0x0c,0x01,0x00,0x0a,0x01,0x10,0x04,0x07,0x0f,0x91,0x59,0x07,0x07,0x10,0x02,0x05,0x03,0x01,0x04,0x04,0x10,0x91,0x59,0x04,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x7f,0x01,0x01,0x01,0x10,0x0d,0x06,0x4d,0x01,0x01,0x18,0x04,0x0b, 0x08,0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x7d,0x14,0xb8,0xff,0xe8,0x40,0x1e,0x0d,0x06,0x4d,0x00,0x14,0x10,0x14,0x02,0x14,0x14,0x18,0x07,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06,0x4d,0x10,0x7e,0x04,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xfa,0xb3,0x0c,0x06,0x4d,0x04,0xb8, 0xff,0xfd,0xb3,0x0b,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x5d,0x2b,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x33,0x12,0x39,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x21,0x23,0x11,0x33,0x01,0x11,0x33,0x11,0x21,0x32, 0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x05,0x87,0xa8,0xa8,0xfb,0x35,0xa8,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa2,0xfe,0xc9,0x05,0x9a,0xfa,0x66,0x05,0x9a,0xfd,0xa0,0xcf,0xbf,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8c,0x7e,0x01,0x00,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x38,0x05,0x9a, 0x00,0x0a,0x00,0x12,0x00,0x87,0x40,0x29,0x0d,0x08,0x01,0x00,0x06,0x01,0x10,0x04,0x03,0x0b,0x91,0x59,0x03,0x03,0x0c,0x01,0x03,0x00,0x0c,0x91,0x59,0x00,0x12,0x07,0x08,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x7d,0x10,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x10,0xb8,0xff,0xf8,0x40,0x1e,0x0c,0x06, 0x4d,0x10,0x18,0x0b,0x06,0x4d,0x10,0x10,0x14,0x03,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x7e,0x00,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00, 0x18,0x3f,0x12,0x39,0x2f,0x2b,0x31,0x30,0x00,0x5f,0x5e,0x5d,0x5d,0x33,0x11,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0xbc,0xa8,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa2,0xfe,0xc9,0x05,0x9a,0xfd,0xa0,0xcf,0xbf,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8c,0x7e,0x01,0x00,0x00, 0x00,0x01,0x00,0x68,0xff,0xe8,0x04,0x90,0x05,0xb2,0x00,0x18,0x00,0xb9,0x40,0x14,0x02,0x0f,0x01,0x0d,0x00,0x01,0x02,0x16,0x01,0x02,0x12,0x01,0x10,0x04,0x16,0x10,0x0b,0x00,0x4d,0x0f,0xb8,0xff,0xc0,0x40,0x45,0x0c,0x00,0x4d,0x00,0x40,0x0c,0x00,0x4d,0x08,0x07,0x91,0x59,0x08,0x11,0x17,0x08,0x91,0x2b,0x30,0x00,0x0e,0x01,0x0c, 0x03,0x0e,0x0e,0x0c,0x11,0x0c,0x91,0x59,0x11,0x04,0x00,0x01,0x01,0x0b,0x03,0x01,0x01,0x03,0x17,0x03,0x91,0x59,0x17,0x13,0x07,0x07,0x00,0x09,0x14,0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14,0x08,0x0b,0x06,0x4d,0x14,0x7d,0x06,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff, 0xe8,0x40,0x0b,0x0b,0x06,0x4d,0x20,0x06,0x01,0x06,0x06,0x1a,0x0e,0x00,0x2f,0xc4,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x33,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x00,0x18,0x2f,0x2b,0x31,0x30,0x00,0x2b,0x2b,0x2b,0x01, 0x5f,0x5e,0x5d,0x5d,0x00,0x5d,0x5d,0x37,0x35,0x16,0x33,0x32,0x00,0x37,0x21,0x35,0x21,0x26,0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x68,0x9d,0xe1,0xd6,0x01,0x11,0x10,0xfd,0x85,0x02,0x79,0x1a,0xfe,0xf1,0xd9,0xcb,0xa6,0x9a,0xd7,0x01,0x35,0x01,0x82,0xfe,0x8d,0xfe,0xd1,0xe7,0x3c,0xa3,0x60,0x01, 0x0f,0xf1,0x97,0xf5,0x01,0x0f,0x56,0xb0,0x3e,0xfe,0x61,0xfe,0xa5,0xfe,0xc1,0xfe,0x6f,0x00,0x00,0x02,0x00,0xbc,0xff,0xe8,0x07,0xc6,0x05,0xb2,0x00,0x12,0x00,0x1e,0x00,0xcf,0x40,0x2d,0x0a,0x13,0x91,0x59,0x0a,0x04,0x06,0x01,0x91,0x59,0x06,0x04,0x02,0x06,0x91,0x2b,0x30,0x04,0x03,0x10,0x19,0x91,0x59,0x10,0x13,0x02,0x12,0x0d, 0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x7d,0x1c,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x1c,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x1c,0xb8,0xff,0xe7,0x40,0x19,0x0b,0x06,0x4d,0x1c,0x1c,0x20,0x16,0x08,0x0d,0x06,0x4d,0x16,0x08,0x0c,0x06,0x4d,0x16,0x08,0x0b,0x06,0x4d,0x16,0x7d,0x07,0x00,0xb8, 0xff,0xf0,0x40,0x26,0x0d,0x06,0x4d,0x00,0x04,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x20,0x00,0x01,0x00,0x00,0x20,0x06,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x7e,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x03,0x03,0x0b,0x06,0x4d,0x03, 0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x2f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x12,0x00,0x21,0x20,0x00,0x11,0x10, 0x00,0x21,0x20,0x00,0x01,0x22,0x00,0x11,0x10,0x12,0x33,0x32,0x12,0x11,0x10,0x02,0x02,0xb2,0xfe,0xb2,0xa8,0xa8,0x01,0x54,0x1e,0x01,0x5e,0x01,0x18,0x01,0x21,0x01,0x59,0xfe,0x9e,0xfe,0xcf,0xfe,0xe2,0xfe,0xa5,0x02,0x8c,0xe3,0xfe,0xff,0xf4,0xdd,0xe6,0xfd,0xf3,0x02,0x9e,0xfd,0x62,0x05,0x9a,0xfd,0x9b,0x01,0x2c,0x01,0x51,0xfe, 0x75,0xfe,0xb8,0xfe,0x9d,0xfe,0x6c,0x01,0x7c,0x03,0xb6,0xfe,0xc8,0xfe,0xef,0xfe,0xe5,0xfe,0xc9,0x01,0x32,0x01,0x17,0x01,0x20,0x01,0x32,0x00,0x00,0x02,0x00,0x3d,0x00,0x00,0x03,0xfd,0x05,0x9a,0x00,0x14,0x00,0x1d,0x00,0xa6,0x40,0x6d,0x04,0x11,0x01,0x0b,0x0f,0x01,0x0d,0x0a,0x01,0x0f,0x09,0x01,0x02,0x07,0x01,0x10,0x04,0x06, 0x18,0x0b,0x00,0x4d,0x0c,0x02,0x15,0x15,0x02,0x91,0x59,0x15,0x15,0x13,0x00,0x13,0x17,0x91,0x59,0x13,0x03,0x07,0x00,0x12,0x07,0x08,0x0b,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x09,0x0c,0x09,0x01,0x08,0x1a,0x08,0x0c,0x06,0x4d,0x1a,0x08,0x0b,0x06,0x4d,0x1a,0x7d,0x10,0x10,0x08,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06, 0x4d,0x00,0x08,0x0b,0x06,0x4d,0x15,0x00,0x7e,0x7f,0x01,0x01,0x01,0x18,0x0d,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x01,0x1f,0x07,0x08,0x2f,0x33,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x33,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x39,0x11,0x33,0x2b,0x2b,0x00,0x3f,0x33,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18, 0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x5d,0x00,0x5d,0x5d,0x21,0x23,0x11,0x23,0x22,0x06,0x07,0x03,0x23,0x13,0x36,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x21,0x03,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x03,0xfd,0xa8,0xd1,0x3c,0x5b,0x34,0xb4,0xc8,0xda,0x15,0x57,0x3a,0x8f,0x9f,0xff, 0xcf,0x01,0xa0,0xa8,0xe9,0x8e,0x9d,0xa0,0x87,0x02,0x62,0x41,0x71,0xfe,0x50,0x01,0xdf,0x2f,0x69,0x16,0x04,0x1f,0xc8,0x8e,0xb7,0xdd,0xfd,0x60,0x02,0x08,0x86,0x7a,0x7a,0x8e,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x04,0x18,0x02,0x06,0x00,0x44,0x00,0x00,0x00,0x02,0x00,0x77,0xff,0xe8,0x04,0x40,0x05,0xf8,0x00,0x19,0x00,0x27, 0x00,0x96,0x40,0x2c,0x1a,0x07,0x26,0x0a,0x26,0x95,0x59,0x0a,0x0a,0x20,0x00,0x00,0x01,0xec,0x59,0x00,0x01,0x10,0x20,0x95,0x59,0x10,0x16,0x00,0x00,0x1b,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x83,0x23,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x23,0xb8,0xff,0xe8,0x40,0x30,0x0b,0x06,0x4d, 0x20,0x23,0x30,0x23,0x02,0x23,0x23,0x29,0x07,0x1b,0x08,0x0d,0x06,0x4d,0x1b,0x08,0x0c,0x06,0x4d,0x1b,0x08,0x0b,0x06,0x4d,0x1b,0x83,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x08,0x0b,0x06,0x4d,0x13,0x2f,0x29,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0xe1,0x2b,0x2b, 0x2b,0x11,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x00,0x33,0x33,0x31,0x30,0x01,0x15,0x06,0x07,0x0e,0x02,0x07,0x33,0x36,0x33,0x32,0x12,0x15,0x14,0x00,0x23,0x22,0x02,0x11,0x34,0x12,0x36,0x36,0x37,0x36,0x01,0x15,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x03,0xbe,0x29, 0x5b,0xe1,0xb3,0x73,0x10,0x04,0x78,0xde,0xcb,0xf8,0xfe,0xfd,0xdb,0xec,0xff,0x5c,0xa3,0xc7,0xf2,0x60,0xfd,0x92,0x01,0x2e,0x56,0x75,0x4b,0x89,0xa9,0xad,0x93,0xce,0x05,0xf8,0x9a,0x1e,0x0f,0x22,0x3f,0xce,0xc6,0xae,0xfe,0xea,0xe4,0xeb,0xfe,0xe3,0x01,0x4f,0x01,0x37,0xf2,0x01,0x51,0xaa,0x40,0x2b,0x16,0xfc,0xbe,0x8e,0x50,0x9a, 0x76,0x3a,0xcd,0xa0,0xb0,0xcf,0x00,0x03,0x00,0xa6,0x00,0x00,0x03,0xd1,0x04,0x00,0x00,0x0c,0x00,0x13,0x00,0x1a,0x00,0xa5,0xb9,0x00,0x03,0xff,0xe8,0x40,0x33,0x0b,0x0c,0x00,0x4c,0x07,0x14,0x0e,0x0e,0x14,0x95,0x59,0x0e,0x0e,0x01,0x15,0x01,0x0d,0x95,0x59,0x01,0x0f,0x00,0x15,0x95,0x59,0x00,0x15,0x07,0x15,0x11,0x84,0x05,0x05, 0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x84,0x18,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x18,0xb8,0xff,0xe8,0x40,0x1e,0x0c,0x06,0x4d,0x20,0x18,0x30,0x18,0x02,0x18,0x18,0x1c,0x0e,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x84,0x00,0xb8,0xff,0xfc, 0x40,0x0e,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc0,0x2f,0xe1,0x12,0x39,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x33,0x11,0x21, 0x32,0x16,0x15,0x14,0x07,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x01,0x11,0x21,0x32,0x35,0x34,0x23,0xa6,0x01,0xbe,0x97,0xaf,0xc4,0xeb,0xc1,0x8f,0xfe,0xc9,0xf6,0xc6,0xb2,0xfe,0xf6,0x01,0x1c,0xc7,0xdf,0x04,0x00,0x86,0x74,0xc7,0x2b,0x1e,0xcf,0x7d,0xaa,0x03,0x74,0xfe,0xe0,0x9a,0x86,0xfe,0x54,0xfe,0xc4, 0xa1,0x9b,0x00,0x01,0x00,0xa6,0x00,0x00,0x02,0xdf,0x04,0x00,0x00,0x05,0x00,0x47,0x40,0x20,0x05,0x00,0x95,0x59,0x05,0x0f,0x02,0x15,0x70,0x00,0x01,0x00,0x00,0x07,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x03,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xf8,0xb6,0x0b,0x06, 0x4d,0x03,0x2f,0x07,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x33,0x2f,0x5d,0x00,0x3f,0x3f,0x2b,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x02,0xdf,0xfe,0x6b,0xa4,0x02,0x39,0x03,0x74,0xfc,0x8c,0x04,0x00,0x00,0x02,0x00,0x12,0xfe,0x8b,0x04,0x23,0x04,0x00,0x00,0x0c,0x00,0x11,0x00,0xba,0x40,0x0d,0x00,0x11,0x01,0x10, 0x05,0x0a,0x0e,0x95,0x59,0x0a,0x0f,0x04,0x00,0xb8,0x01,0x31,0x40,0x1c,0x0d,0x07,0x02,0x0b,0x02,0x0b,0x95,0x59,0x02,0x15,0x0f,0x09,0x09,0x0d,0x07,0x0c,0x0c,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0xed,0x02,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf8,0x40,0x20,0x0b, 0x06,0x4d,0x02,0x02,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x84,0x0d,0x12,0x0d,0x06,0x4d,0x0d,0x0d,0x13,0x07,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb3,0x0b,0x06,0x4d,0x06,0xb8,0x01,0x2c,0x40,0x0d,0x03,0x08,0x0b,0x06,0x4d,0x03,0x03,0x11,0x11,0x07,0x30,0x13, 0x01,0x5d,0x2f,0x33,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0xf1,0x2b,0x2b,0x2b,0xc1,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0xc4,0x3f,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x00,0x13,0x21,0x11, 0x33,0x21,0x11,0x23,0x02,0x03,0x04,0x23,0x8b,0xfd,0x06,0x8c,0x5b,0x01,0x06,0x04,0x02,0x14,0x98,0xfe,0xc4,0xe3,0x1b,0xce,0xfe,0x8b,0x01,0x75,0xfe,0x8b,0x02,0x00,0x01,0x7a,0x01,0xfb,0xfc,0x8b,0x02,0xea,0xfe,0x62,0xfe,0xb4,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x04,0x18,0x02,0x06,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x04, 0x00,0x00,0x05,0xf6,0x04,0x00,0x00,0x15,0x00,0xc5,0x40,0x21,0x0a,0x15,0x01,0x07,0x14,0x01,0x07,0x0b,0x01,0x0a,0x0a,0x01,0x09,0x07,0x01,0x09,0x02,0x01,0x0d,0x13,0x01,0x02,0x0c,0x01,0x01,0x08,0x01,0x0e,0x01,0x01,0x10,0x03,0x15,0xb8,0xff,0xf8,0x40,0x0b,0x0b,0x0c,0x00,0x4c,0x0a,0x08,0x0b,0x0c,0x00,0x4c,0x08,0xb8,0xff,0xe8, 0x40,0x45,0x0c,0x00,0x4d,0x01,0x18,0x0c,0x00,0x4d,0x02,0x10,0x0c,0x00,0x4d,0x14,0x0b,0x10,0x0f,0x09,0x00,0x04,0x15,0x15,0x00,0x04,0x0a,0x05,0x09,0x14,0x14,0x00,0x18,0x0b,0x06,0x4d,0x00,0x0e,0x04,0x05,0x09,0x42,0x0b,0x09,0x08,0x0c,0x00,0x4d,0x09,0x09,0x16,0x10,0x0f,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04, 0x08,0x0b,0x06,0x4d,0x04,0x84,0x05,0xb8,0xff,0xfc,0x40,0x0a,0x0b,0x06,0x4d,0x05,0x40,0x17,0x01,0x2f,0x17,0x01,0x5d,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0xc6,0x2b,0x01,0x10,0xf0,0x2b,0xc2,0x18,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x3f,0x33,0x33,0x3f,0x33,0x33,0x31,0x30,0x2b,0x01,0x2b,0x2b, 0x2b,0x2b,0x5f,0x5e,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x23,0x01,0x23,0x01,0x01,0x33,0x01,0x33,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x05,0xf6,0xde,0xfe,0x36,0x04,0x9c,0x04,0xfe,0x35,0xdb,0x01,0xfc,0xfe,0x23,0xd1,0x01,0xb6,0x04,0x9c,0x04,0x01,0xb6,0xd3,0xfe,0x21,0x01, 0xfa,0xfe,0x06,0x01,0xfa,0xfe,0x06,0x02,0x10,0x01,0xf0,0xfe,0x21,0x01,0xdf,0xfe,0x21,0x01,0xdf,0xfe,0x10,0x00,0x00,0x01,0x00,0x50,0xff,0xe7,0x03,0x3b,0x04,0x19,0x00,0x21,0x00,0xa7,0x40,0x09,0x05,0x12,0x01,0x0c,0x00,0x01,0x10,0x03,0x15,0xb8,0xff,0xe0,0x40,0x3a,0x0b,0x0c,0x00,0x4c,0x19,0x08,0x09,0x09,0x08,0x95,0x59,0x09, 0x09,0x14,0x03,0x11,0x0f,0x14,0x0f,0x95,0x59,0x14,0x10,0x01,0x03,0x20,0x03,0x95,0x59,0x20,0x16,0x19,0x16,0x08,0x08,0x11,0x0c,0x84,0x16,0x16,0x1d,0x08,0x0d,0x06,0x4d,0x1d,0x08,0x0c,0x06,0x4d,0x1d,0x08,0x0b,0x06,0x4d,0x1d,0x84,0x05,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x05,0xb8,0xff, 0xf0,0x40,0x0d,0x0b,0x06,0x4d,0x20,0x05,0x30,0x05,0x02,0x05,0x05,0x23,0x11,0x00,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x00,0x2f,0x2b,0xc4,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0xc0,0x2f,0xe1,0x11,0x39,0x2f,0x12,0x39,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x39,0x2f,0x2b, 0x11,0x12,0x00,0x39,0x31,0x30,0x2b,0x5f,0x5e,0x5d,0x5d,0x37,0x35,0x16,0x33,0x20,0x35,0x34,0x21,0x23,0x35,0x33,0x20,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x50,0x86,0xb3,0x01,0x0f,0xfe,0xd7,0x65,0x60,0x01,0x05,0x78,0x68,0x95,0x96,0xaa,0x8e,0x01,0x76, 0x6f,0x64,0x72,0x8a,0xe2,0xc6,0xd3,0x1d,0xa1,0x4b,0xac,0xaa,0x8b,0xa2,0x45,0x52,0x4b,0x99,0x3e,0xfe,0xed,0x59,0x81,0x15,0x05,0x09,0x88,0x68,0x8c,0xa6,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x00,0x04,0x00,0x00,0x0d,0x00,0x92,0x40,0x2d,0x7c,0x0c,0x01,0x79,0x0b,0x01,0x73,0x05,0x01,0x76,0x04,0x01,0x46,0x09,0x01,0x4a,0x02,0x01, 0x09,0x02,0x08,0x0d,0x0f,0x05,0x00,0x15,0x0c,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x10,0x0b,0x06,0x4d,0x00,0xef,0x01,0xb8,0xff,0xf4,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf4,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xfa,0x40,0x29,0x0b,0x06,0x4d,0x01,0x01,0x0f,0x05,0x09,0x08,0x0d,0x06,0x4d,0x09,0x08,0x0c,0x06, 0x4d,0x09,0x10,0x0b,0x06,0x4d,0x09,0xef,0x06,0x05,0x0d,0x06,0x4d,0x06,0x01,0x0b,0x06,0x4d,0x06,0x40,0x0f,0x01,0x2f,0x0f,0x01,0x5d,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x32,0x3f,0x33,0x39,0x39,0x5d,0x5d,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x21,0x23, 0x11,0x06,0x07,0x01,0x23,0x11,0x33,0x11,0x36,0x37,0x01,0x33,0x04,0x00,0x94,0x16,0x2d,0xfe,0x27,0xaa,0x96,0x0c,0x28,0x01,0xe6,0xaa,0x03,0x31,0x2b,0x4e,0xfd,0x48,0x04,0x00,0xfc,0xd9,0x1d,0x46,0x02,0xc4,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x00,0x05,0xf2,0x02,0x26,0x02,0x0f,0x00,0x00,0x01,0x06,0x07,0xcd,0x00,0x00,0x00,0x13, 0x40,0x0b,0x01,0x0d,0x14,0x0e,0x07,0x0d,0x25,0x01,0x11,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x02,0x06,0x01,0x67,0x00,0x00,0x00,0x01,0x00,0x10,0xff,0xf2,0x03,0x91,0x04,0x00,0x00,0x0e,0x00,0x96,0x40,0x27,0x00,0x04,0x01,0x10,0x06,0x05,0x20,0x0b,0x0c,0x00,0x4c,0x0e, 0x02,0x95,0x59,0x0e,0x0f,0x09,0x0b,0x06,0x0b,0x95,0x59,0x06,0x00,0x15,0x03,0x08,0x0c,0x06,0x4d,0x03,0x08,0x0b,0x06,0x4d,0x03,0xed,0x0d,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x0d,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0d,0xb8,0xff,0xf0,0x40,0x22,0x0b,0x06,0x4d,0x0d,0x0d,0x08,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d, 0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0x08,0x0d,0x06,0x4d,0x01,0x0c,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x0a,0x0b,0x06,0x4d,0x01,0x01,0x10,0x08,0x3f,0x10,0x01,0x5d,0x2f,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x00,0x3f,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b, 0x31,0x30,0x00,0x2b,0x01,0x5f,0x5e,0x5d,0x21,0x23,0x11,0x23,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x03,0x91,0xa3,0xee,0x29,0xc7,0xa8,0x33,0x25,0x23,0x29,0xdc,0x3f,0x02,0x1a,0x03,0x75,0xfe,0x0f,0xfe,0x6e,0x0e,0x8d,0x12,0x03,0x85,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0xf8,0x04,0x00,0x00,0x13,0x00,0xad, 0x40,0x0a,0x79,0x12,0x01,0x77,0x0e,0x01,0x75,0x0d,0x01,0x0d,0xb8,0xff,0xf0,0x40,0x0a,0x0b,0x00,0x4d,0x06,0x10,0x0b,0x0c,0x00,0x4c,0x05,0xb8,0xff,0xf0,0x40,0x2f,0x0b,0x0c,0x00,0x4c,0x10,0x40,0x0c,0x00,0x4d,0x02,0x09,0x10,0x03,0x0d,0x13,0x0f,0x0a,0x05,0x00,0x15,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00, 0x08,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x01,0x01,0x01,0x08,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf0,0x40,0x19,0x0b,0x06,0x4d,0x01,0x01,0x15,0x0d,0x0a,0x06,0x0d,0x06,0x4d,0x0a,0x12,0x0c,0x06,0x4d,0x0a,0x12,0x0b,0x06,0x4d,0x0a,0xed,0x0b,0xb8,0xff,0xfe,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xfc,0x40,0x0c,0x0c,0x06,0x4d,0x0b,0x07,0x0b, 0x06,0x4d,0x0b,0x3f,0x15,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x32,0x32,0x3f,0x33,0x17,0x39,0x2b,0x31,0x30,0x01,0x2b,0x2b,0x2b,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x37,0x01, 0x33,0x04,0xf8,0xa2,0x16,0x2e,0xff,0x00,0x93,0xfe,0xf8,0x15,0x2f,0x8d,0xd1,0x01,0x0e,0x1d,0x2d,0x49,0x01,0x06,0xda,0x03,0x4c,0x40,0x7c,0xfd,0x70,0x02,0x90,0x35,0x87,0xfc,0xb4,0x04,0x00,0xfd,0x64,0x49,0x81,0xc6,0x02,0xa0,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x00,0x0b,0x00,0x6a,0x40,0x22,0x09,0x02,0x95,0x59, 0x09,0x09,0x07,0x0b,0x0f,0x04,0x00,0x15,0x09,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x01,0x01,0x01,0xb8,0xff,0xfb,0x40,0x24,0x0b,0x06,0x4d,0x01,0x01,0x0d,0x08,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x84,0x05,0x04,0x0d,0x06,0x4d, 0x05,0x40,0x0d,0x01,0x2f,0x0d,0x01,0x5d,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x32,0x3f,0x33,0x39,0x2f,0x2b,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x03,0xf8,0xa4,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0xa4,0x01,0xd1,0xfe,0x2f,0x04,0x00, 0xfe,0x5c,0x01,0xa4,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x02,0x06,0x00,0x52,0x00,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x00,0x07,0x00,0x60,0x40,0x1e,0x07,0x02,0x95,0x59,0x07,0x0f,0x04,0x00,0x15,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x01, 0x01,0x01,0xb8,0xff,0xfb,0x40,0x23,0x0b,0x06,0x4d,0x01,0x01,0x09,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x84,0x05,0x05,0x0d,0x06,0x4d,0x05,0x40,0x09,0x01,0x2f,0x09,0x01,0x5d,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x32,0x3f,0x2b, 0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x03,0xf8,0xa4,0xfd,0xf6,0xa4,0x03,0x52,0x03,0x74,0xfc,0x8c,0x04,0x00,0xff,0xff,0x00,0xa6,0xfe,0x29,0x04,0x54,0x04,0x18,0x02,0x06,0x00,0x53,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x02,0x06,0x00,0x46,0x00,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x03,0x29, 0x04,0x00,0x00,0x07,0x00,0x47,0x40,0x2d,0x04,0x00,0x07,0x00,0x95,0x59,0x07,0x0f,0x02,0x15,0x00,0x0e,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x03,0x03,0x05,0x42,0x1f,0x05,0x01,0x05,0x05,0x08,0x03,0x04,0x0d,0x06,0x4d,0x03,0x2f,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x01,0x10,0xf1,0x2b, 0x2b,0x2b,0xe2,0x00,0x18,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x03,0x29,0xfe,0xcd,0xa4,0xfe,0xcc,0x03,0x0b,0x03,0x74,0xfc,0x8c,0x03,0x74,0x8c,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x04,0x00,0x02,0x06,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x60,0xfe,0x1e,0x05,0x1c,0x05,0xb2, 0x00,0x15,0x00,0x1e,0x00,0x27,0x00,0xe4,0x40,0x19,0x20,0x0b,0x16,0x0e,0x0e,0x16,0x95,0x59,0x0e,0x10,0x1f,0x03,0x00,0x17,0x00,0x17,0x95,0x59,0x00,0x16,0x0d,0x04,0x01,0x1c,0x24,0xb8,0xff,0xf0,0x40,0x1c,0x0b,0x0c,0x00,0x4c,0x1b,0x10,0x0b,0x0c,0x00,0x4c,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08,0x0c,0x06,0x4d,0x12,0x08,0x0b,0x06, 0x4d,0x1b,0x83,0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x12,0xb8,0xff,0xe8,0x40,0x43,0x0b,0x06,0x4d,0x12,0x0e,0x01,0x02,0x07,0x42,0x24,0x08,0x0d,0x06,0x4d,0x24,0x08,0x0c,0x06,0x4d,0x24,0x08,0x0b,0x06,0x4d,0x24,0x83,0x07,0x10,0x0d,0x06,0x4d,0x07,0x10,0x0c,0x06,0x4d,0x07,0x18,0x0b, 0x06,0x4d,0x07,0x07,0x28,0x0c,0x0d,0x16,0x20,0x04,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x10,0x0b,0x06,0x4d,0x01,0xed,0x02,0xb8,0xff,0xfb,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xfd,0x40,0x0c,0x0b,0x06,0x4d,0x2f,0x02,0x01,0x02,0x2f,0x29,0x3f,0x29,0x02,0x5d,0x2f,0x5d,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x17,0x39, 0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x3f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x05,0x11,0x23,0x11,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x33,0x11,0x33,0x11,0x33,0x32,0x00,0x15,0x14, 0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x03,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x03,0x08,0x94,0x20,0xe0,0xfe,0xec,0x01,0x17,0xe5,0x18,0x94,0x16,0xe7,0x01,0x17,0xfe,0xee,0xdf,0x23,0x16,0x9c,0xba,0xb7,0x9a,0xaf,0x18,0x9a,0xba,0xbb,0x9d,0x18,0xfe,0x36,0x01,0xca,0x01,0x22,0xea,0xf9,0x01,0x2b,0x01,0x9a, 0xfe,0x66,0xfe,0xd7,0xfb,0xea,0xfe,0xde,0x03,0xa6,0xfc,0xe4,0xd3,0xb5,0xbe,0xd6,0xfc,0xe4,0x03,0x1c,0xd7,0xbd,0xb3,0xd5,0xff,0xff,0x00,0x1a,0x00,0x00,0x03,0x92,0x04,0x00,0x02,0x06,0x00,0x5b,0x00,0x00,0x00,0x01,0x00,0xa6,0xfe,0x8b,0x04,0x8f,0x04,0x00,0x00,0x0b,0x00,0x93,0xb9,0x00,0x01,0x01,0x31,0x40,0x17,0x05,0x09,0x0f, 0x07,0x02,0x0a,0x02,0x0a,0x95,0x59,0x02,0x15,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x10,0x0b,0x06,0x4d,0x0b,0xba,0x01,0x2c,0x00,0x02,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf0,0x40,0x38,0x0b,0x06,0x4d,0x02,0x02,0x0a,0x08,0x0c,0x06,0x4d,0x0a,0x08,0x0b,0x06,0x4d,0x0a,0x84,0x07,0x08, 0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x07,0x0d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x03,0x08,0x0d,0x06,0x4d,0x03,0x04,0x0c,0x06,0x4d,0x03,0x40,0x0d,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xf1,0x2b,0x2b,0xc1,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x00,0x3f,0x2b,0x11, 0x12,0x00,0x39,0x18,0x3f,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x04,0x8f,0x8d,0xfc,0xa4,0xa4,0x02,0x0a,0xa4,0x97,0xfe,0x8b,0x01,0x75,0x04,0x00,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x00,0x00,0x01,0x00,0x98,0x00,0x00,0x03,0xdf,0x04,0x00,0x00,0x0f,0x00,0x67,0x40,0x46,0x0d,0x02,0x0b,0x04, 0x0b,0xec,0x59,0x04,0x04,0x00,0x08,0x0f,0x0f,0x00,0x15,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d,0x0f,0x08,0x0b,0x06,0x4d,0x02,0x0f,0x84,0x7f,0x0e,0x01,0x0e,0x0e,0x11,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x84,0x07,0x05,0x0d,0x06,0x4d,0x07,0x05,0x0c,0x06,0x4d,0x07,0x2f, 0x11,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0xe1,0x33,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x32,0x12,0x39,0x2f,0x2b,0x11,0x00,0x33,0x33,0x31,0x30,0x21,0x23,0x11,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x03,0xdf,0xa3,0xb4,0x98,0xfe,0xa8,0xa4,0xc2,0x94,0xaa,0xa3,0x01,0x9c,0x62, 0x01,0x6c,0x01,0x5a,0xfe,0xae,0xe1,0x56,0x01,0xdd,0x00,0x01,0x00,0xa6,0x00,0x00,0x05,0xc0,0x04,0x00,0x00,0x0b,0x00,0xad,0x40,0x1f,0x07,0x03,0x0b,0x0f,0x05,0x00,0x09,0x00,0x09,0x95,0x59,0x00,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x09,0x84,0x00,0xb8,0xff,0xf8,0x40,0x1b,0x0b,0x06, 0x4d,0x00,0x0e,0x08,0x01,0x05,0x42,0x04,0x08,0x0d,0x06,0x4d,0x04,0x08,0x0c,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x84,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x22,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x01,0x0c,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d, 0x08,0x84,0x05,0x04,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xfc,0x40,0x0c,0x0b,0x06,0x4d,0x05,0x05,0x0d,0x0c,0x3f,0x0d,0x4f,0x0d,0x02,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf1,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18, 0x3f,0x33,0x33,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x05,0xc0,0xfa,0xe6,0xa4,0x01,0x98,0xa3,0x01,0x97,0xa4,0x04,0x00,0xfc,0x8c,0x03,0x74,0xfc,0x8c,0x03,0x74,0x00,0x01,0x00,0xa6,0xfe,0x8b,0x06,0x5a,0x04,0x00,0x00,0x0f,0x00,0xf2,0xb9,0x00,0x01,0x01,0x31,0x40,0x1e,0x09,0x05,0x0d,0x0f,0x0b, 0x07,0x02,0x0e,0x02,0x0e,0x95,0x59,0x02,0x15,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d,0x0f,0x10,0x0b,0x06,0x4d,0x0f,0xba,0x01,0x2c,0x00,0x02,0xff,0xf4,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x02,0xb8,0xff,0xf0,0x40,0x1c,0x0b,0x06,0x4d,0x02,0x02,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06, 0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0b,0x84,0x0e,0x07,0x0d,0x06,0x4d,0x0e,0xb8,0xff,0xf9,0x40,0x1b,0x0b,0x06,0x4d,0x0e,0x0e,0x0a,0x07,0x03,0x42,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf8,0x40,0x32,0x0c,0x06,0x4d,0x03,0x08, 0x0b,0x06,0x4d,0x03,0x03,0x10,0x0a,0x08,0x0d,0x06,0x4d,0x0a,0x08,0x0c,0x06,0x4d,0x0a,0x08,0x0b,0x06,0x4d,0x0a,0x84,0x07,0x0e,0x0d,0x06,0x4d,0x07,0x10,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x07,0x11,0x10,0x3f,0x11,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1, 0x2b,0x2b,0x2b,0x2b,0x01,0x10,0xf0,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc1,0x18,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x12,0x00,0x39,0x39,0x18,0x3f,0x33,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x06,0x5a,0x8f,0xfa,0xdb,0xa4,0x01,0x97,0xa4,0x01, 0x98,0xa4,0x99,0xfe,0x8b,0x01,0x75,0x04,0x00,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x04,0x64,0x04,0x00,0x00,0x0c,0x00,0x13,0x00,0x7e,0x40,0x26,0x05,0x0d,0x95,0x59,0x05,0x05,0x04,0x0e,0x04,0x01,0x95,0x59,0x04,0x0f,0x00,0x0e,0x95,0x59,0x00,0x15,0x09,0x08,0x0d,0x06,0x4d,0x09, 0x08,0x0c,0x06,0x4d,0x09,0x08,0x0b,0x06,0x4d,0x09,0x83,0x11,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x11,0xb8,0xff,0xf8,0x40,0x1d,0x0c,0x06,0x4d,0x11,0x11,0x15,0x05,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x84,0x00,0x02,0x02,0x14,0x00,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x00,0x2f,0x2b, 0x12,0x39,0x2f,0x10,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x31,0x30,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x01,0x56,0xfe,0xc8,0x01,0xdc,0x01,0x14,0x9d,0xb9, 0xba,0x8e,0xfe,0xde,0xf6,0xcc,0xce,0x03,0x74,0x8c,0xfe,0x77,0xa3,0x94,0x94,0xac,0x01,0xea,0xfe,0xa2,0xb4,0xaa,0x00,0x03,0x00,0xa6,0x00,0x00,0x05,0x06,0x04,0x00,0x00,0x03,0x00,0x0e,0x00,0x15,0x00,0xb0,0xb9,0x00,0x09,0xff,0xe8,0x40,0x2f,0x0b,0x00,0x4d,0x07,0x0f,0x95,0x59,0x07,0x07,0x10,0x02,0x05,0x0f,0x01,0x04,0x04,0x10, 0x95,0x59,0x04,0x15,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x01,0x01,0x01,0x04,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf4,0x40,0x1c,0x0b,0x06,0x4d,0x01,0x01,0x17,0x04,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08,0x0c,0x06,0x4d,0x0b,0x83,0x10,0x13,0x01,0x13,0x08,0x0d,0x06,0x4d,0x13,0xb8, 0xff,0xf8,0x40,0x19,0x0c,0x06,0x4d,0x13,0x13,0x17,0x07,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0x08,0x0b,0x06,0x4d,0x10,0x84,0x04,0xb8,0xff,0xfc,0x40,0x09,0x0c,0x06,0x4d,0x04,0x04,0x0b,0x06,0x4d,0x04,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x2f, 0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x33,0x12,0x39,0x2f,0x2b,0x31,0x30,0x00,0x2b,0x21,0x23,0x11,0x33,0x01,0x11,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x05,0x06,0xa2,0xa2,0xfb,0xa0,0xa4,0x01,0x14,0x9d,0xb9,0xba,0x8e,0xfe,0xde,0xf6,0xcc,0xce, 0x04,0x00,0xfc,0x00,0x04,0x00,0xfe,0x77,0xa4,0x93,0x94,0xac,0x01,0xea,0xfe,0xa2,0xb4,0xaa,0x00,0x02,0x00,0xa6,0x00,0x00,0x03,0xb4,0x04,0x00,0x00,0x0a,0x00,0x11,0x00,0x74,0x40,0x21,0x03,0x0b,0x95,0x59,0x03,0x03,0x0c,0x01,0x0f,0x00,0x0c,0x95,0x59,0x00,0x15,0x07,0x08,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b, 0x06,0x4d,0x07,0x83,0x0f,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xf0,0x40,0x19,0x0d,0x06,0x4d,0x0f,0x0f,0x13,0x03,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x84,0x00,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x00,0x02,0x0c,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b, 0x32,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x12,0x39,0x2f,0x2b,0x31,0x30,0x33,0x11,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0xa6,0xa4,0x01,0x14,0x9d,0xb9,0xba,0x8e,0xfe,0xde,0xf6,0xcc,0xce,0x04,0x00,0xfe,0x77,0xa4,0x93,0x94,0xac,0x01,0xea,0xfe, 0xa2,0xb4,0xaa,0x00,0x00,0x01,0x00,0x5a,0xff,0xe8,0x03,0x5a,0x04,0x18,0x00,0x18,0x00,0x99,0x40,0x09,0x00,0x16,0x01,0x00,0x12,0x01,0x10,0x05,0x05,0xb8,0xff,0xe8,0xb4,0x0b,0x0c,0x00,0x4c,0x09,0xb8,0xff,0xf0,0x40,0x36,0x0c,0x06,0x4d,0x09,0x06,0x95,0x59,0x09,0x09,0x03,0x11,0x0e,0x0c,0x11,0x0c,0x95,0x59,0x11,0x10,0x00,0x01, 0x01,0x0c,0x03,0x01,0x03,0x17,0x03,0x95,0x59,0x17,0x16,0x07,0x07,0x00,0x14,0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14,0x08,0x0b,0x06,0x4d,0x14,0x83,0x09,0x06,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf8,0x40,0x0d,0x0c,0x06,0x4d,0x20,0x06,0x30,0x06,0x02,0x06,0x06,0x1a,0x0e,0x00,0x2f,0xc4,0x12,0x39,0x2f, 0x5d,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x11,0x12,0x39,0x2f,0x2b,0x01,0x2b,0x31,0x30,0x00,0x2b,0x01,0x5f,0x5e,0x5d,0x5d,0x37,0x35,0x16,0x33,0x32,0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x11, 0x14,0x00,0x23,0x22,0x5a,0x74,0x96,0x91,0xb3,0x08,0xfe,0x4c,0x01,0xb4,0x0c,0xb2,0x94,0x8f,0x69,0x6a,0x90,0xf4,0x01,0x06,0xfe,0xf3,0xe3,0x9d,0x2d,0x9b,0x56,0xb3,0x99,0x8c,0x98,0xac,0x4e,0xa2,0x36,0xfe,0xe3,0xfe,0xfd,0xf1,0xfe,0xe1,0x00,0x02,0x00,0xa6,0xff,0xe8,0x06,0x1e,0x04,0x18,0x00,0x12,0x00,0x1a,0x00,0xb7,0x40,0x33, 0x00,0x0b,0x01,0x10,0x06,0x0a,0x13,0x95,0x59,0x0a,0x10,0x10,0x17,0x95,0x59,0x10,0x16,0x06,0x01,0x95,0x59,0x06,0x06,0x03,0x04,0x0f,0x03,0x15,0x07,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x83,0x19,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x19,0xb8,0xff,0xe0,0x40,0x19, 0x0b,0x06,0x4d,0x19,0x19,0x1c,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x83,0x07,0x00,0xb8,0xff,0xe0,0x40,0x19,0x0b,0x06,0x4d,0x00,0x00,0x1c,0x06,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x03,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x03, 0x08,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x2b,0x00,0x18,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x36,0x24,0x33, 0x32,0x12,0x11,0x14,0x00,0x23,0x22,0x02,0x01,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x02,0x6c,0xfe,0xde,0xa4,0xa4,0x01,0x24,0x1a,0x01,0x01,0xc9,0xdb,0xf1,0xfe,0xfe,0xe2,0xd5,0xef,0x01,0xce,0xfe,0xce,0x01,0x36,0x01,0x2f,0x01,0xd1,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0xd2,0xea,0xfe,0xec,0xff,0x00,0xf9,0xfe,0xdd,0x01,0x01,0x02,0xa5, 0xfe,0x70,0xfe,0x74,0x01,0x8c,0x01,0x90,0x00,0x02,0x00,0x3e,0x00,0x00,0x03,0x62,0x04,0x00,0x00,0x11,0x00,0x18,0x00,0xae,0x40,0x5a,0x02,0x06,0x01,0x10,0x04,0x0a,0x02,0x12,0x02,0x12,0x95,0x59,0x02,0x02,0x11,0x00,0x11,0x13,0x95,0x59,0x11,0x0f,0x06,0x00,0x15,0x05,0x08,0x0c,0x06,0x4d,0x05,0x08,0x0b,0x06,0x4d,0x06,0x08,0x0b, 0x06,0x4d,0x05,0x08,0x0a,0x08,0x01,0x07,0x16,0x08,0x0c,0x06,0x4d,0x16,0x08,0x0b,0x06,0x4d,0x16,0x83,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x0d,0x07,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0x0c,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb6, 0x0b,0x06,0x4d,0x01,0x01,0x1a,0x07,0xb8,0xff,0xf0,0xb5,0x0c,0x06,0x4d,0x06,0x07,0x19,0x10,0xce,0x32,0x2b,0x11,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x33,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x11,0x12,0x39,0x39,0x11,0x33,0x2b,0x2b,0x2b,0x00,0x3f,0x33,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39, 0x31,0x30,0x01,0x5f,0x5e,0x5d,0x21,0x23,0x11,0x23,0x22,0x07,0x03,0x23,0x13,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x21,0x03,0x11,0x23,0x22,0x15,0x14,0x33,0x03,0x62,0xa4,0x89,0x63,0x51,0x85,0xbe,0xac,0x3c,0x55,0x78,0x7e,0xc5,0xb2,0x01,0x66,0xa4,0xc2,0xcf,0xc9,0x01,0xa8,0xa0,0xfe,0xf8,0x01,0x3c,0x6e,0x23,0x10,0x90,0x6c, 0x88,0x9f,0xfe,0x31,0x01,0x43,0x9d,0xa6,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0x87,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x06,0x00,0x8f,0x7f,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x29,0x23,0x0c,0x12,0x3e,0x03,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x00,0x01,0x00,0x27,0xfe,0x62,0x04,0x14, 0x05,0xec,0x00,0x21,0x00,0xbc,0x40,0x40,0x11,0x0e,0x17,0x14,0x14,0x17,0x96,0x59,0x0f,0x14,0x1f,0x14,0x2f,0x14,0x03,0x09,0x03,0x14,0x14,0x13,0x1b,0x18,0x08,0x1b,0x08,0x95,0x59,0x1b,0x0f,0x13,0x00,0x01,0x03,0x20,0x03,0xec,0x59,0x20,0x0c,0x15,0x15,0x15,0x0c,0x00,0x00,0x0d,0x1d,0x08,0x0d,0x06,0x4d,0x1d,0x08,0x0c,0x06,0x4d, 0x1d,0x08,0x0b,0x06,0x4d,0x1d,0x83,0x06,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf0,0x40,0x1d,0x0b,0x06,0x4d,0x06,0x06,0x23,0x11,0x14,0x17,0x03,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x84,0x0f,0x0d,0xb8,0xff,0xfc,0x40,0x0a,0x0b, 0x06,0x4d,0x0d,0x40,0x23,0x01,0x2f,0x23,0x01,0x5d,0x5d,0x2f,0x2b,0xce,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x10,0xc0,0x2f,0x00,0x3f,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39, 0x31,0x30,0x01,0x35,0x16,0x33,0x32,0x12,0x11,0x10,0x21,0x22,0x06,0x15,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x36,0x33,0x20,0x11,0x10,0x02,0x23,0x22,0x01,0xd5,0x43,0x3a,0x92,0x8a,0xfe,0xfa,0x76,0xa2,0xa4,0x85,0x85,0xa4,0x01,0x4e,0xfe,0xb2,0x04,0x69,0xd3,0x01,0x84,0xdb,0xe9,0x3a,0xfe,0x7b, 0x9d,0x24,0x01,0x2b,0x01,0x64,0x01,0xef,0xbb,0x8a,0xfd,0xd3,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfe,0x8a,0xc2,0xfd,0x87,0xfe,0x5a,0xfe,0x83,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0xdf,0x06,0x0a,0x02,0x26,0x02,0x0a,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0x94,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x1b,0x08,0x06,0x04,0x05,0x3e,0x01, 0x08,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x60,0x04,0x18,0x00,0x18,0x00,0x86,0xb9,0x00,0x14,0xff,0xf0,0x40,0x52,0x0b,0x0c,0x00,0x4c,0x03,0x08,0x10,0x00,0x4d,0x11,0x12,0x95,0x59,0x11,0x11,0x16,0x08,0x00,0x0b,0x01,0x0d,0x03,0x0b,0x0d,0x08,0x0d,0x95,0x59,0x08,0x10,0x00,0x18,0x01, 0x0c,0x03,0x18,0x16,0x02,0x16,0x95,0x59,0x02,0x16,0x12,0x12,0x13,0x0b,0x00,0x30,0x00,0x01,0x00,0x1a,0x10,0x10,0x0c,0x06,0x4d,0x10,0x13,0x08,0x0d,0x06,0x4d,0x13,0x83,0x05,0x10,0x0d,0x06,0x4d,0x05,0x10,0x0c,0x06,0x4d,0x05,0x18,0x0b,0x06,0x4d,0x05,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x32,0x2b,0x11,0x33,0x5d,0x2f,0xc4,0x12,0x39, 0x2f,0x00,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x3f,0x2b,0x00,0x18,0x10,0xc6,0x5f,0x5e,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x31,0x30,0x00,0x2b,0x2b,0x25,0x06,0x23,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x33,0x32,0x37,0x03,0x60,0x73,0x9f,0xe5,0xfe,0xf7,0x01,0x14, 0xf2,0x89,0x67,0x64,0x92,0x93,0xb6,0x0d,0x01,0xb4,0xfe,0x4a,0x08,0xb2,0x94,0x92,0x78,0x2d,0x45,0x01,0x1b,0xef,0x01,0x02,0x01,0x24,0x32,0xa2,0x4a,0xb0,0x94,0x8c,0x97,0xb5,0x5b,0x00,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x04,0x18,0x02,0x06,0x00,0x56,0x00,0x00,0xff,0xff,0xff,0xd3,0x00,0x00,0x02,0x1a,0x05,0x87,0x02,0x26, 0x00,0xd6,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x56,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x13,0x0d,0x02,0x03,0x25,0x02,0x01,0x10,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x00,0x02,0x00,0x10,0xff,0xf2,0x05,0xfc,0x04,0x00,0x00,0x15,0x00,0x1c,0x00,0xd5,0x40,0x34,0x00,0x03,0x01,0x10,0x06,0x04,0x18,0x0b, 0x0c,0x00,0x4c,0x08,0x0a,0x05,0x0a,0x95,0x59,0x05,0x00,0x0e,0x16,0x95,0x59,0x0e,0x0e,0x0c,0x17,0x0c,0x02,0x95,0x59,0x0c,0x0f,0x00,0x17,0x95,0x59,0x00,0x15,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0xed,0x0c,0xb8,0xff,0xe8,0x40,0x19,0x0d,0x06,0x4d,0x0c,0x0c,0x00,0x07,0x12,0x08,0x0d,0x06,0x4d,0x12,0x08,0x0c, 0x06,0x4d,0x12,0x08,0x0b,0x06,0x4d,0x12,0x83,0x1a,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x1a,0xb8,0xff,0xfc,0x40,0x19,0x0c,0x06,0x4d,0x1a,0x1a,0x1e,0x0e,0x17,0x08,0x0d,0x06,0x4d,0x17,0x08,0x0c,0x06,0x4d,0x17,0x08,0x0b,0x06,0x4d,0x17,0x84,0x00,0xb8,0xff,0xfc,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x00, 0xb8,0xff,0xf4,0x40,0x0a,0x0b,0x06,0x4d,0x00,0x00,0x1e,0x07,0x4f,0x1e,0x01,0x5d,0x2f,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x00,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x00,0x18,0x10,0xc4,0x2b, 0x00,0x18,0x10,0xc6,0x31,0x30,0x2b,0x01,0x5f,0x5e,0x5d,0x21,0x11,0x23,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x02,0xee,0xee,0x29,0xc7,0xa8,0x33,0x25,0x23,0x29,0xdc,0x3f,0x02,0x1a,0x01,0x15,0x9d,0xb9,0xbb,0x8d,0xfe,0xdd,0xf6,0xcd, 0xcf,0x03,0x75,0xfe,0x0f,0xfe,0x6e,0x0e,0x8d,0x12,0x03,0x85,0xfe,0x77,0xa4,0x94,0x92,0xad,0x01,0xe9,0xfe,0xa2,0xb4,0xaa,0x00,0x02,0x00,0xa6,0x00,0x00,0x06,0x14,0x04,0x00,0x00,0x12,0x00,0x19,0x00,0xb7,0x40,0x28,0x08,0x01,0x13,0x0b,0x0b,0x13,0x95,0x59,0x0b,0x0b,0x14,0x06,0x0a,0x0f,0x03,0x00,0x00,0x14,0x95,0x59,0x00,0x15, 0x0f,0x04,0x0d,0x06,0x4d,0x0f,0x04,0x0c,0x06,0x4d,0x0f,0x04,0x0b,0x06,0x4d,0x0f,0x83,0x17,0xb8,0xff,0xf0,0x40,0x1a,0x0d,0x06,0x4d,0x17,0x17,0x1b,0x0b,0x08,0x14,0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14,0x08,0x0b,0x06,0x4d,0x14,0x84,0x00,0xb8,0xff,0xf9,0x40,0x09,0x0d,0x06,0x4d,0x00,0x14,0x0c,0x06,0x4d,0x00,0xb8, 0xff,0xf0,0x40,0x19,0x0b,0x06,0x4d,0x00,0x00,0x1b,0x07,0x03,0x08,0x0d,0x06,0x4d,0x03,0x08,0x0c,0x06,0x4d,0x03,0x08,0x0b,0x06,0x4d,0x03,0x84,0x04,0xb8,0xff,0xf8,0x40,0x0c,0x0d,0x06,0x4d,0x04,0x08,0x0b,0x06,0x4d,0x04,0x4f,0x1b,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b, 0x2b,0x39,0x39,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x33,0x12,0x39,0x2f,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x21,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x03,0x06,0xfe,0x44,0xa4,0xa4,0x01, 0xbc,0xa4,0x01,0x14,0xa1,0xb5,0xb8,0x8f,0xfe,0xdd,0xf6,0xcc,0xce,0x01,0xdd,0xfe,0x23,0x04,0x00,0xfe,0x6a,0x01,0x96,0xfe,0x6a,0x9e,0x92,0x93,0xa7,0x01,0xdd,0xfe,0xaf,0xae,0xa3,0x00,0x00,0x01,0x00,0x27,0x00,0x00,0x03,0xfe,0x05,0xec,0x00,0x19,0x00,0xb4,0x40,0x3f,0x02,0x18,0x01,0x02,0x18,0x01,0x10,0x04,0x0d,0x0a,0x13,0x10, 0x10,0x13,0x96,0x59,0x0f,0x10,0x1f,0x10,0x2f,0x10,0x03,0x09,0x03,0x10,0x10,0x0f,0x17,0x15,0x04,0x17,0x04,0x95,0x59,0x17,0x0f,0x0f,0x00,0x08,0x00,0x15,0x12,0x12,0x08,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c, 0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x1d,0x0b,0x06,0x4d,0x01,0x01,0x1b,0x0d,0x10,0x13,0x03,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x84,0x0b,0x09,0xb8,0xff,0xfc,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x1b,0x01,0x5d,0x2f,0x2b,0xce,0xe1,0x2b,0x2b,0x2b,0x17,0x39,0x12,0x39,0x2f,0x2b,0x2b,0x2b, 0xe1,0x2b,0x2b,0x2b,0x10,0xc0,0x2f,0x00,0x3f,0x33,0x3f,0x3f,0x2b,0x11,0x00,0x33,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x2b,0x11,0x12,0x00,0x39,0x39,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x36,0x33,0x20,0x11, 0x03,0xfe,0xa4,0xec,0x7b,0xa3,0xa4,0x85,0x85,0xa4,0x01,0x4e,0xfe,0xb2,0x04,0x77,0xd9,0x01,0x5a,0x02,0x33,0x01,0x41,0xba,0x95,0xfd,0xdb,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfe,0x8c,0xc2,0xfe,0x5e,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x0a,0x02,0x26,0x01,0x67,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x1f,0x00,0x00,0x00,0x13, 0x40,0x0b,0x01,0x00,0x0e,0x0e,0x07,0x0a,0x3e,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0xf2,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x06,0x07,0xcd,0xa0,0x00,0x00,0x13,0x40,0x0b,0x01,0x0f,0x1b,0x15,0x0c,0x00,0x25,0x01,0x18,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0x00,0x01,0x00,0xa6,0xfe,0x8b,0x03,0xf8,0x04,0x00,0x00,0x0b,0x00,0x9c,0xb3,0x07,0x0b,0x0f,0x02,0xb8,0x01,0x31,0x40,0x18,0x04,0x00,0x00,0x09,0x95,0x59,0x00,0x15,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x10,0x0b,0x06,0x4d,0x01,0xbb,0x01,0x2c,0x00,0x04,0x00,0x04,0xff,0xf8,0xb5,0x0b,0x06,0x4d,0x08,0x09,0x04, 0xb8,0x01,0x2c,0x40,0x17,0xff,0x30,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x09,0x01,0x09,0xb8,0xff,0xf8,0x40,0x23,0x0b,0x06,0x4d,0x09,0x09,0x0d,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x84,0x05,0x04,0x0d,0x06,0x4d,0x05,0x40,0x0d, 0x01,0x2f,0x0d,0x01,0x5d,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x2b,0x10,0xe1,0x2b,0x2b,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x00,0x33,0x18,0x3f,0x3f,0x33,0x31,0x30,0x21,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x03,0xf8,0xfe,0x9e,0x8e,0xfe,0x9e,0xa4,0x02,0x0a, 0xa4,0xfe,0x8b,0x01,0x75,0x04,0x00,0xfc,0x8b,0x03,0x75,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xa4,0x06,0xa2,0x00,0x07,0x00,0x75,0x40,0x19,0x05,0x00,0x91,0x59,0x06,0x05,0x03,0x02,0x12,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x10,0x0b,0x06,0x4d,0x05,0xb8,0x01,0x2c,0x40,0x09,0x70,0x00,0x01,0x00,0x08,0x0d, 0x06,0x4d,0x00,0xb8,0xff,0xfa,0x40,0x18,0x0b,0x06,0x4d,0x00,0x00,0x09,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x7e,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x06,0x4d,0x03,0x04,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x33, 0x2f,0x2b,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0xcd,0x2b,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x03,0xa4,0xfd,0xc0,0xa8,0x02,0x58,0x90,0x05,0x02,0xfa,0xfe,0x05,0x9a,0x01,0x08,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x02,0xe6,0x05,0x0e,0x00,0x07,0x00,0x62,0x40,0x19,0x05,0x00,0x95,0x59,0x06,0x05,0x0f,0x02, 0x15,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x10,0x0b,0x06,0x4d,0x05,0xb8,0x01,0x2c,0x40,0x1d,0x70,0x00,0x01,0x00,0x18,0x0d,0x06,0x4d,0x00,0x00,0x09,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x03,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x03,0x12,0x0b,0x06,0x4d, 0x03,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x33,0x2f,0x2b,0x5d,0xe1,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0xcd,0x2b,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x02,0xe6,0xfe,0x64,0xa4,0x01,0xb0,0x90,0x03,0x74,0xfc,0x8c,0x04,0x00,0x01,0x0e,0xff,0xff,0x00,0x00,0x01,0xfa,0x08,0x00,0x02,0x7b,0x02,0x06,0x00,0xb3,0x00,0x00, 0x00,0x04,0x00,0xbc,0x00,0x00,0x08,0x9a,0x05,0xae,0x00,0x0b,0x00,0x14,0x00,0x26,0x00,0x2a,0x00,0xd8,0x40,0x52,0x06,0x20,0x01,0x0a,0x16,0x01,0x04,0x0b,0x01,0x03,0x07,0x01,0x03,0x0f,0x05,0x01,0x0f,0x01,0x01,0x10,0x04,0x29,0x28,0x96,0x59,0x29,0x00,0x00,0x11,0x96,0x59,0x00,0x00,0x06,0x06,0x0c,0x96,0x59,0x06,0x04,0x20,0x26, 0x03,0x1d,0x15,0x12,0x2a,0x29,0x2a,0x29,0x03,0x09,0x8b,0x13,0x13,0x2c,0x0f,0x8b,0x03,0x03,0x2c,0x1e,0x16,0x22,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x7e,0x24,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x24,0xb8,0xff,0xf0,0x40,0x1f,0x0c,0x06,0x4d,0x24,0x0a,0x0b,0x06,0x4d,0x24,0x24,0x2c, 0x20,0x1a,0x1d,0x08,0x0d,0x06,0x4d,0x1d,0x08,0x0c,0x06,0x4d,0x1d,0x08,0x0b,0x06,0x4d,0x1d,0x7e,0x1e,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x1e,0xb8,0xff,0xfc,0x40,0x09,0x0c,0x06,0x4d,0x1e,0x04,0x0b,0x06,0x4d,0x1e,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x33, 0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x3f,0x33,0x3f,0x33,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x2b,0x00,0x18,0x10,0xc6,0x2b,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x10,0x33,0x32,0x11, 0x10,0x01,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x33,0x26,0x35,0x11,0x33,0x01,0x21,0x35,0x21,0x07,0x1c,0xaf,0xc3,0xcb,0xba,0xb0,0xbb,0xcb,0xa8,0x6c,0x79,0xe1,0xdd,0xfd,0x02,0xd1,0xfd,0x5f,0x20,0x0e,0x06,0x08,0xa8,0xdc,0x02,0xc6,0x04,0x08,0xa8,0x03,0x79,0xfd,0x4d,0x02,0xb3,0x02,0x5c,0xde,0xc4,0xd1, 0xdf,0xda,0xc8,0xc6,0xea,0x02,0xcb,0x99,0x8c,0xfe,0xe2,0x01,0x20,0x01,0x23,0xfa,0xd9,0x04,0x70,0x37,0x21,0x2e,0x94,0xfb,0xfa,0x05,0x9a,0xfb,0x43,0x31,0xa0,0x03,0xec,0xfb,0xa4,0x84,0x00,0x01,0x00,0x11,0xff,0xf4,0x04,0xaf,0x04,0x00,0x00,0x1a,0x00,0xb2,0x40,0x36,0x00,0x18,0x01,0x0d,0x0a,0x01,0x10,0x04,0x16,0x00,0x14,0x0d, 0x00,0x1a,0x00,0x95,0x59,0x1a,0x0f,0x06,0x04,0x09,0x04,0xec,0x59,0x09,0x10,0x15,0x00,0x00,0x02,0x06,0x06,0x02,0x08,0x0d,0x06,0x4d,0x02,0x08,0x0c,0x06,0x4d,0x02,0x08,0x0b,0x06,0x4d,0x02,0x84,0x7f,0x0b,0x01,0x0b,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xf0,0x40,0x27,0x0b, 0x06,0x4d,0x0b,0x0b,0x1c,0x13,0x16,0x16,0x1b,0x11,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x84,0x13,0x17,0x0d,0x06,0x4d,0x13,0x12,0x0c,0x06,0x4d,0x13,0xb8,0xff,0xe8,0xb3,0x0b,0x06,0x4d,0x13,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0xc6,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x2b,0x2b, 0x2b,0x5d,0xf1,0x2b,0x2b,0x2b,0xc2,0x2f,0x10,0xc2,0x2f,0x00,0x3f,0xc4,0x2b,0x00,0x18,0x10,0xc6,0x3f,0x2b,0x11,0x00,0x33,0x33,0x18,0x10,0xc4,0x31,0x30,0x01,0x5f,0x5e,0x5d,0x00,0x5d,0x01,0x23,0x11,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x11,0x11,0x21,0x11,0x14,0x07,0x23,0x36,0x35,0x11,0x06,0x07,0x35,0x36,0x33,0x21,0x04, 0xaf,0xde,0x65,0x22,0x36,0x3d,0x3d,0xe8,0xfe,0x7b,0x20,0xa7,0x24,0x7b,0x78,0x4b,0xaa,0x03,0xa9,0x03,0x7b,0xfd,0x95,0x8c,0x13,0x8c,0x17,0x01,0x15,0x02,0x72,0xfd,0x9d,0xc0,0x58,0x57,0xc1,0x02,0x63,0x03,0x56,0x96,0x48,0x00,0x00,0x02,0x00,0x2f,0x02,0x48,0x02,0xaa,0x05,0x9a,0x00,0x0c,0x00,0x11,0x00,0x4a,0x40,0x18,0x0c,0x0b, 0x0b,0x02,0xcc,0x0d,0x06,0x09,0x16,0x09,0x02,0x09,0x03,0x03,0x13,0x11,0x4f,0x06,0x7f,0x06,0x02,0x06,0x04,0x01,0xb8,0x01,0x56,0x40,0x0f,0x0c,0x06,0x0f,0x0d,0x1f,0x0d,0x02,0x0d,0x0d,0x02,0x0e,0x0a,0x27,0x02,0x28,0x00,0x3f,0x3f,0x33,0x12,0x39,0x2f,0x5d,0x33,0x33,0xed,0x32,0x01,0x2f,0x5d,0x33,0x12,0x39,0x2f,0x33,0x5d,0x33, 0xed,0x32,0x11,0x33,0x30,0x31,0x01,0x23,0x15,0x23,0x35,0x21,0x35,0x36,0x12,0x37,0x33,0x11,0x33,0x23,0x11,0x06,0x06,0x07,0x02,0xaa,0x6e,0x84,0xfe,0x77,0x69,0xba,0x4e,0x9c,0x6e,0xf2,0x3e,0x80,0x42,0x03,0x14,0xcc,0xcc,0x5c,0x79,0x01,0x13,0x9e,0xfd,0xe7,0x01,0x73,0x71,0xb3,0x4f,0x00,0x00,0x01,0x00,0x7b,0x02,0x33,0x02,0x8a, 0x05,0x9e,0x00,0x24,0x00,0x37,0x40,0x1e,0x04,0x1c,0x14,0x1c,0x02,0x12,0x1e,0xcc,0x08,0x08,0x26,0x14,0xcc,0x01,0x0f,0x0a,0xe6,0x19,0x19,0x10,0x01,0x03,0xe6,0x00,0x23,0x29,0x12,0xe6,0x10,0x27,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0xed,0x12,0x39,0x2f,0xed,0x32,0x30,0x31,0x5d,0x13,0x35,0x16, 0x33,0x32,0x3e,0x02,0x35,0x34,0x23,0x22,0x0e,0x02,0x07,0x13,0x21,0x15,0x21,0x07,0x32,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x7e,0x71,0x57,0x2a,0x45,0x31,0x1a,0xcc,0x14,0x30,0x31,0x31,0x13,0x30,0x01,0xb7,0xfe,0xb5,0x19,0x07,0x15,0x17,0x16,0x06,0x40,0x74,0x56,0x33,0x36,0x5b,0x76,0x3f,0x7d,0x02,0x5e, 0x92,0x46,0x18,0x2a,0x3b,0x23,0x98,0x01,0x03,0x03,0x01,0x01,0xc4,0x7c,0xc8,0x01,0x01,0x01,0x22,0x43,0x65,0x43,0x48,0x6b,0x47,0x23,0x00,0x01,0x00,0x4d,0x02,0x48,0x02,0xa0,0x05,0xa4,0x00,0x0a,0x00,0x2a,0x40,0x15,0x03,0x06,0x0a,0xcc,0x00,0x06,0x00,0x06,0x00,0x0c,0x1f,0x05,0x01,0x05,0x0a,0x28,0x07,0x03,0xe6,0x05,0x27,0x00, 0x3f,0xed,0x32,0x3f,0x01,0x2f,0x5d,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x30,0x31,0x13,0x36,0x12,0x37,0x21,0x35,0x21,0x15,0x06,0x02,0x07,0xb3,0x38,0x99,0x70,0xfe,0x59,0x02,0x53,0x79,0xaf,0x33,0x02,0x48,0xc6,0x01,0x75,0xab,0x76,0x35,0xb9,0xfe,0x6e,0xdc,0x00,0x03,0x00,0x41,0x02,0x34,0x02,0xad,0x05,0xae,0x00,0x23, 0x00,0x31,0x00,0x45,0x00,0x53,0x40,0x30,0x15,0x05,0x08,0x3c,0xcc,0x12,0x12,0x1a,0xcc,0x60,0x2a,0x01,0x2a,0x2a,0x47,0x00,0x32,0xcc,0x08,0x08,0x24,0xcc,0x00,0x40,0x0a,0x0f,0x48,0x00,0x15,0x05,0x2f,0xe6,0x0f,0x37,0x1f,0x37,0x02,0x37,0x37,0x0d,0x27,0xe6,0x1f,0x29,0x41,0xe6,0x0d,0x27,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f, 0x5d,0xed,0x39,0x39,0x01,0x2f,0x2b,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0xed,0x12,0x39,0x39,0x30,0x31,0x13,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02, 0x23,0x22,0x06,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x41,0x14,0x27,0x39,0x25,0x34,0x3c,0x27,0x47,0x63,0x3c,0x3d,0x63,0x46,0x27,0x3b,0x35,0x23,0x39,0x28,0x15,0x2c,0x51,0x73,0x46,0x46,0x72,0x51,0x2d,0x90,0x58,0x4e,0x4e,0x5c,0x17,0x2c,0x3f,0x28,0x4a,0x5c,0x20,0x14,0x24,0x31,0x1d, 0x1d,0x32,0x25,0x15,0x14,0x25,0x32,0x1e,0x1f,0x32,0x22,0x13,0x03,0x32,0x21,0x41,0x3b,0x32,0x11,0x21,0x5d,0x38,0x31,0x55,0x3d,0x23,0x23,0x3e,0x54,0x31,0x39,0x5d,0x20,0x11,0x33,0x3b,0x41,0x20,0x3b,0x5e,0x42,0x23,0x23,0x42,0x5e,0x47,0x48,0x49,0x4b,0x46,0x20,0x38,0x29,0x17,0x51,0x01,0x3b,0x1a,0x2e,0x22,0x14,0x14,0x22,0x2e, 0x1a,0x1b,0x2c,0x20,0x12,0x13,0x20,0x2d,0xff,0xff,0x00,0xa6,0x00,0x00,0x01,0x4a,0x04,0x00,0x02,0x06,0x00,0xd6,0x00,0x00,0xff,0xff,0x00,0x79,0xfe,0x85,0x03,0xde,0x05,0xb2,0x02,0x26,0x00,0x36,0x00,0x00,0x00,0x06,0x01,0x9c,0x7b,0x00,0xff,0xff,0x00,0x68,0xfe,0x85,0x03,0x0f,0x04,0x18,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x06, 0x01,0x9c,0x09,0x00,0x00,0x02,0x00,0x64,0x01,0x02,0x04,0x0e,0x04,0xaa,0x00,0x1b,0x00,0x27,0x00,0x68,0x40,0x3b,0x02,0x06,0x09,0x0d,0x10,0x14,0x17,0x1b,0x08,0x04,0x12,0x01,0x07,0x04,0x40,0x22,0x04,0xbe,0x59,0x22,0x0e,0x12,0x12,0x1c,0xbe,0x59,0x15,0x0f,0x12,0x16,0x00,0x00,0x19,0x0e,0x08,0x0b,0x40,0x02,0x06,0x09,0x0d,0x10, 0x14,0x17,0x1b,0x08,0x0b,0x19,0xbd,0x25,0x0b,0x25,0x42,0x25,0x25,0x29,0x1f,0xbd,0x0b,0x2f,0xe1,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x11,0x17,0x39,0x1a,0x18,0x10,0xde,0xc4,0x10,0xca,0x2f,0xc4,0x00,0x2f,0xde,0xc4,0x2b,0x00,0x18,0x10,0xe4,0x2b,0x00,0x1a,0x18,0x10,0xde,0xc4,0x11,0x12,0x17,0x39,0x31,0x30,0x01,0x07,0x27,0x06, 0x23,0x22,0x27,0x07,0x27,0x37,0x26,0x35,0x34,0x37,0x27,0x37,0x17,0x36,0x33,0x32,0x17,0x37,0x17,0x07,0x16,0x15,0x14,0x07,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x04,0x0e,0x5c,0x89,0x69,0x86,0x88,0x68,0x8a,0x5c,0x8a,0x4c,0x4c,0x8a,0x5c,0x8a,0x6e,0x82,0x81,0x6c,0x8b,0x5c,0x89,0x4e,0x4e,0xfe,0xb5,0x74, 0x9f,0xa1,0x72,0x71,0xa3,0xa6,0x01,0x62,0x60,0x8a,0x4c,0x4c,0x8a,0x60,0x86,0x71,0x7c,0x81,0x6c,0x88,0x60,0x89,0x4d,0x4d,0x89,0x60,0x88,0x70,0x7d,0x79,0x74,0x02,0x02,0xa2,0x71,0x71,0xa2,0xa2,0x71,0x71,0xa2,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x06,0x3a,0x06,0x3e,0x00,0x19,0x00,0x25,0x00,0xb2,0xb9,0x00,0x0d,0xff,0xf0,0xb3, 0x0b,0x00,0x4d,0x0a,0xb8,0xff,0xf0,0x40,0x14,0x0b,0x00,0x4d,0x06,0xc0,0x02,0xf2,0x0d,0x1a,0x91,0x0f,0x0d,0x12,0x18,0x04,0x20,0x91,0x12,0x13,0x0d,0xb8,0xff,0xe8,0x40,0x1e,0x0c,0x06,0x4d,0x06,0x06,0x04,0xc2,0x09,0x09,0x0d,0x00,0x15,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x23, 0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x23,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x23,0xb8,0xff,0xf4,0x40,0x2a,0x0b,0x06,0x4d,0x23,0x23,0x27,0x1d,0x06,0x0d,0x06,0x4d,0x1d,0x06,0x0c,0x06,0x4d,0x1d,0x06,0x0b,0x06,0x4d,0x1d,0x7d,0x15,0x10,0x0d,0x06,0x4d,0x15,0x10,0x0c,0x06,0x4d,0x15,0x10,0x0b,0x06,0x4d,0x15,0x2f,0x27,0x01,0x5d, 0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x39,0x32,0x2f,0xf1,0xc2,0x2f,0x2b,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0xed,0x2f,0xed,0x1a,0xcc,0x31,0x30,0x01,0x2b,0x2b,0x01,0x16,0x33,0x32,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x23,0x23,0x16,0x11,0x10,0x00,0x21,0x20, 0x00,0x11,0x10,0x00,0x21,0x32,0x07,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x04,0x8f,0x30,0x20,0xd6,0x15,0x88,0x12,0x8c,0x7a,0x22,0x98,0xfe,0x8c,0xfe,0xc8,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0xd8,0xe4,0xe2,0xfe,0xe6,0x01,0x13,0xdd,0xec,0x01,0x10,0xfe,0xf8,0x05,0x43,0x09,0x82,0x48,0x3a,0x36,0x50,0x6c, 0x86,0xc2,0xfe,0xdb,0xfe,0xa1,0xfe,0x68,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0x98,0xfe,0xba,0xfe,0xf7,0xfe,0xf7,0xfe,0xbd,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0xa9,0x04,0xfc,0x00,0x18,0x00,0x24,0x00,0x95,0x40,0x2b,0x00,0x80,0x14,0xf2,0x05,0x19,0x95,0x07,0x05,0x0a,0x10,0x10, 0x1f,0x95,0x0a,0x16,0x00,0x00,0x17,0xc2,0x03,0x03,0x10,0x05,0x0d,0x07,0x06,0x0d,0x06,0x4d,0x07,0x06,0x0c,0x06,0x4d,0x07,0x06,0x0b,0x06,0x4d,0x07,0x83,0x22,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x22,0xb8,0xff,0xf7,0xb6,0x0c,0x06,0x4d,0x30,0x22,0x01,0x22,0xb8,0xff,0xe4,0x40,0x27,0x0b,0x06,0x4d,0x22,0x22,0x26,0x1c,0x0a,0x0d, 0x06,0x4d,0x1c,0x0a,0x0c,0x06,0x4d,0x1c,0x0a,0x0b,0x06,0x4d,0x1c,0x83,0x0d,0x10,0x0d,0x06,0x4d,0x0d,0x0e,0x0c,0x06,0x4d,0x0d,0x19,0x0b,0x06,0x4d,0x0d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x39,0x32,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39, 0xed,0x2f,0xed,0x1a,0xcc,0x31,0x30,0x01,0x33,0x16,0x15,0x14,0x07,0x16,0x15,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x04,0x10,0x86,0x13,0xdb,0x82,0xfe,0xeb,0xe9,0xe3,0xfe,0xf1,0x01,0x1a,0xf0,0x30,0x56,0x3d,0x6d,0x3b, 0x4f,0xfe,0x3a,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab,0x04,0xfc,0x38,0x50,0xc0,0x28,0x8d,0xfb,0xf5,0xfe,0xd9,0x01,0x1f,0xed,0x01,0x02,0x01,0x22,0x0e,0x0a,0x47,0x32,0x49,0xfe,0xcc,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0x00,0x00,0x01,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x06,0x96,0x00,0x17,0x00,0x86,0x40,0x33,0x25,0x0a,0x35,0x0a, 0x02,0x25,0x08,0x35,0x08,0x02,0x12,0x80,0x17,0xda,0x0c,0x0c,0x05,0x03,0x09,0x91,0x02,0x13,0x12,0x12,0x10,0xc2,0x15,0x15,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x0b,0x18,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xd8,0x40,0x18,0x0c,0x06,0x4d,0x0b,0x0b,0x19,0x07,0x08,0x0d,0x06,0x4d,0x07, 0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x7e,0x04,0xb8,0xff,0xfc,0x40,0x0c,0x0c,0x06,0x4d,0x04,0x04,0x0b,0x06,0x4d,0x04,0x30,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0x33,0x10,0xfd,0x1a,0xcc,0x31,0x30,0x5d,0x5d, 0x01,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x04,0xd5,0xfd,0xdf,0xfd,0xf6,0xa8,0x01,0x74,0x01,0x67,0x93,0x3c,0x4f,0x15,0x88,0x12,0xfb,0x02,0x44,0xfd,0xa4,0x02,0x45,0x03,0x6d,0xfc,0x9e,0xfe,0x47,0x01,0xaa,0x03,0x71,0x47,0x31,0x4a,0x3a,0x38,0x50, 0xd2,0x1f,0x00,0x01,0x00,0x90,0xff,0xe8,0x04,0xc7,0x04,0xfc,0x00,0x1b,0x00,0x92,0x40,0x32,0x06,0x40,0x10,0x00,0x4d,0x0d,0x10,0x0b,0x0c,0x00,0x4c,0x17,0x80,0x1b,0xf2,0x10,0x08,0x0f,0x02,0x0c,0x95,0x05,0x16,0x00,0x15,0x16,0x16,0x14,0xc2,0x19,0x19,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d, 0x00,0x84,0x02,0x0f,0xb8,0xff,0xe0,0x40,0x32,0x0d,0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d,0x0f,0x08,0x0b,0x06,0x4d,0x7f,0x0f,0x01,0x0f,0x0f,0x1d,0x0a,0x06,0x0d,0x06,0x4d,0x0a,0x06,0x0c,0x06,0x4d,0x0a,0x06,0x0b,0x06,0x4d,0x0a,0x84,0x07,0x09,0x0c,0x06,0x4d,0x07,0x06,0x0b,0x06,0x4d,0x07,0x2f,0x1d,0x01,0x5d,0x2f,0x2b,0x2b,0xe1, 0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xd4,0xfd,0x1a,0xcd,0x31,0x30,0x2b,0x2b,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x03,0xe2, 0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x7a,0x3b,0x4f,0x14,0x86,0x13,0xe5,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0x47,0x32,0x49,0x3a,0x38,0x50,0xc6,0x24,0x00,0x00,0x01,0x00,0xab,0x04,0xc2,0x01,0xc4,0x06,0x27,0x00,0x11,0x00,0x2b,0x40,0x16,0x0f,0xe2,0x40,0x02,0xc0,0x0b,0x40,0x08, 0x09,0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05,0x01,0x05,0x80,0x08,0x11,0x0b,0x2f,0xc6,0xcd,0x1a,0xdc,0x5d,0x71,0xe1,0x00,0x2f,0xd5,0x1a,0xcd,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0xab,0x25,0x2b,0x58,0x71,0x4d,0x39,0x6c,0x70,0x5e,0x11,0x28,0x06, 0x23,0x04,0x54,0x47,0x3d,0x54,0x07,0x32,0x73,0x4c,0x3f,0x08,0x00,0x01,0x00,0xf2,0xfe,0xc6,0x01,0xb8,0xff,0x89,0x00,0x0b,0x00,0x15,0x40,0x09,0x00,0xc1,0x06,0x09,0xc0,0x03,0x03,0x0d,0x0c,0x11,0x12,0x39,0x2f,0xe1,0x00,0x2f,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x55,0x29,0x3a,0x3c, 0x27,0x29,0x3a,0x3a,0xfe,0xc6,0x3a,0x29,0x29,0x37,0x37,0x29,0x29,0x3a,0x00,0x01,0x00,0x66,0x04,0xc2,0x01,0xc2,0x05,0xb8,0x00,0x03,0x00,0x0e,0xb4,0x03,0x01,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0xcd,0x31,0x30,0x01,0x23,0x27,0x33,0x01,0xc2,0x7e,0xde,0xa8,0x04,0xc2,0xf6,0x00,0x01,0x00,0x64,0x04,0xc2,0x01,0xc0,0x05,0xb8, 0x00,0x03,0x00,0x0e,0xb4,0x01,0x03,0x02,0x80,0x00,0x2f,0x1a,0xcd,0x00,0x2f,0xcd,0x31,0x30,0x13,0x37,0x33,0x07,0x64,0xb4,0xa8,0xdc,0x04,0xc2,0xf6,0xf6,0x00,0x02,0x00,0x42,0x04,0xc2,0x03,0x90,0x06,0x50,0x00,0x03,0x00,0x0a,0x00,0x2e,0xb1,0x01,0x00,0xb8,0xff,0xc0,0x40,0x15,0x09,0x0c,0x48,0x00,0x00,0x0a,0x04,0x02,0x80,0x00, 0x00,0x80,0x04,0x90,0x04,0xa0,0x04,0x03,0x04,0xc0,0x08,0x2f,0x1a,0xcc,0x5d,0x39,0x2f,0x1a,0xcd,0x00,0x2f,0xcd,0x39,0x2f,0x2b,0xcd,0x31,0x30,0x01,0x37,0x33,0x07,0x07,0x23,0x27,0x07,0x23,0x37,0x33,0x02,0x34,0xb4,0xa8,0xdd,0x3d,0x79,0xa4,0xa6,0x71,0xd8,0x84,0x05,0x5a,0xf6,0xf6,0x98,0x94,0x94,0xfa,0x00,0x00,0x02,0x00,0x42, 0x04,0xc2,0x03,0x90,0x06,0x50,0x00,0x03,0x00,0x0a,0x00,0x36,0xb1,0x03,0x00,0xb8,0xff,0xc0,0x40,0x1b,0x09,0x0c,0x48,0x00,0x00,0x06,0x80,0x07,0x80,0x07,0x90,0x07,0xa0,0x07,0x03,0x07,0xc0,0x04,0x40,0x0f,0x13,0x48,0x04,0x04,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x39,0x2f,0x2b,0x1a,0xcc,0x5d,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x2b,0xcd, 0x31,0x30,0x01,0x23,0x27,0x33,0x13,0x37,0x33,0x17,0x23,0x27,0x07,0x01,0x9e,0x7e,0xde,0xa8,0x73,0xd7,0x86,0xd6,0x70,0xa6,0xa4,0x05,0x5a,0xf6,0xfe,0x72,0xfa,0xfa,0x94,0x94,0x00,0x02,0x00,0x6c,0x04,0xc2,0x03,0x68,0x06,0xbe,0x00,0x11,0x00,0x18,0x00,0x45,0x40,0x26,0x0f,0xe2,0x40,0x02,0xc0,0x0b,0x40,0x08,0x09,0x09,0x17,0x16, 0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05,0x01,0x05,0x80,0x08,0x40,0x11,0x11,0x0b,0x0b,0x80,0x12,0x90,0x12,0xa0,0x12,0x03,0x12,0xc0,0x16,0x2f,0x1a,0xcc,0x5d,0x39,0x2f,0xc6,0xc6,0x1a,0xcd,0x1a,0xdc,0x5d,0x71,0xe1,0x00,0x2f,0xcd,0x39,0x2f,0xd5,0x1a,0xcd,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07, 0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0x13,0x23,0x27,0x07,0x23,0x37,0x33,0x02,0x50,0x24,0x2c,0x59,0x6f,0x4b,0x39,0x6d,0x71,0x5f,0x11,0x28,0x4e,0x78,0xa4,0xa6,0x70,0xd6,0x86,0x06,0xba,0x04,0x53,0x48,0x3c,0x54,0x07,0x32,0x73,0x4b,0x40,0x08,0xfe,0x72,0x94,0x94,0xfa,0x00,0x02,0x00,0xa9,0x04,0xc2,0x03,0x2a,0x06,0xe4, 0x00,0x12,0x00,0x19,0x00,0x41,0x40,0x23,0x12,0x07,0xda,0x0c,0x10,0xda,0x40,0x03,0x09,0x40,0x0d,0x10,0x48,0x09,0x19,0x80,0x13,0x13,0x00,0x17,0x0a,0x12,0xc4,0x00,0x09,0xc4,0x0f,0x00,0x01,0x0a,0x00,0x0a,0x00,0x1b,0x1a,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xe1,0x10,0xe1,0x10,0xc6,0x10,0xc4,0x00,0x2f,0x1a,0xdd,0xd6,0x2b,0xd6, 0x1a,0xfd,0xdc,0xed,0xc6,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x13,0x23,0x27,0x07,0x23,0x37,0x33,0x03,0x2a,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x3b,0x79,0xa4,0xa6,0x70,0xd7,0x85,0x06,0xe4,0x65,0x75,0x25,0x25,0x5c,0xd7, 0x26,0x26,0x61,0xfd,0xde,0x94,0x94,0xfa,0x00,0x02,0x00,0x25,0x04,0xc2,0x02,0x4a,0x06,0xa0,0x00,0x03,0x00,0x0f,0x00,0x34,0x40,0x19,0x02,0x80,0x00,0x04,0x0a,0x0d,0xd9,0x40,0x07,0x02,0x80,0x00,0x00,0x0b,0x0f,0xf3,0x04,0x0b,0xf3,0x0a,0x04,0x0a,0x04,0x11,0x10,0x11,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x10,0xe1,0x11,0x39,0x2f,0x1a, 0xcd,0x00,0x2f,0x1a,0xfd,0xdc,0xc4,0xd4,0x1a,0xcd,0x31,0x30,0x13,0x37,0x33,0x07,0x37,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x37,0xd7,0xb5,0xa7,0xdd,0xf4,0x0a,0x9d,0x70,0x75,0x94,0x05,0x64,0x0b,0xa1,0x9d,0x12,0x05,0xaa,0xf6,0xf6,0x14,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x00,0x02,0x00,0x38,0x04,0xc2,0x02,0x5c, 0x06,0xa0,0x00,0x03,0x00,0x0f,0x00,0x36,0x40,0x1a,0x03,0x80,0x01,0x0a,0x04,0x07,0xd9,0x40,0x0d,0x02,0x80,0x00,0x00,0x05,0x09,0xf3,0x0a,0x05,0xf3,0x04,0x0a,0x04,0x0a,0x04,0x11,0x10,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x12,0x39,0x2f,0x1a,0xcd,0x00,0x2f,0x1a,0xfd,0xdc,0xc4,0xd4,0x1a,0xcd,0x31,0x30,0x01,0x23, 0x27,0x33,0x07,0x33,0x16,0x33,0x32,0x37,0x33,0x06,0x06,0x23,0x22,0x26,0x01,0xaa,0x7f,0xdd,0xa8,0xbe,0x66,0x10,0x9e,0xa2,0x0a,0x64,0x04,0x96,0x74,0x70,0x9c,0x05,0xaa,0xf6,0xe2,0x86,0x86,0x72,0x8a,0x8c,0x00,0x02,0x00,0x25,0x04,0xc2,0x02,0x4a,0x07,0x0a,0x00,0x11,0x00,0x1d,0x00,0x5e,0x40,0x37,0x0f,0xe2,0x40,0x00,0x02,0x10, 0x02,0x20,0x02,0x03,0x02,0xc0,0x00,0x0b,0x10,0x0b,0x20,0x0b,0x03,0x0b,0x08,0x09,0x09,0x1b,0x12,0x18,0x1b,0xd9,0x40,0x15,0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05,0x01,0x05,0x80,0x08,0x11,0x0b,0x0b,0x18,0x1d,0xf3,0x12,0x19,0xf3,0x18,0x18,0x12,0x1f,0x1e,0x11,0x12,0x39,0x39,0x10,0xe1,0x10,0xe1,0x11,0x39,0x2f,0xc6,0xcd,0x1a,0xdc, 0x5d,0x71,0xe1,0x00,0x2f,0x1a,0xfd,0xd4,0xc4,0x12,0x39,0x2f,0xd5,0xcd,0x5d,0x1a,0xdc,0x5d,0x1a,0xed,0x31,0x30,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0x05,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x37,0xcd,0x25,0x2a,0x5b,0x6f,0x50,0x36,0x6c,0x70,0x5e,0x11,0x28, 0x01,0x7d,0x0a,0x9d,0x70,0x75,0x94,0x05,0x64,0x0b,0xa1,0x9d,0x12,0x07,0x06,0x04,0x54,0x48,0x3c,0x54,0x07,0x31,0x72,0x4c,0x40,0x08,0xde,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x00,0x02,0x00,0xa9,0x04,0xc2,0x03,0x2a,0x06,0xe4,0x00,0x12,0x00,0x1e,0x00,0x50,0x40,0x2c,0x12,0x07,0xda,0x0c,0x10,0xda,0x03,0x0a,0x40,0x0d,0x11,0x48, 0x0a,0x1e,0x19,0x1c,0xd9,0x16,0x1e,0xf3,0x13,0x13,0x00,0x12,0x1a,0xf3,0x19,0x19,0x09,0x0a,0x12,0xc4,0x00,0x09,0xc4,0x0f,0x00,0x01,0x0a,0x00,0x0a,0x00,0x20,0x1f,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xe1,0x10,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x00,0x2f,0xfd,0xdc,0xc4,0xd6,0x2b,0xd4,0xfd,0xdc,0xed,0xc6, 0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x13,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x37,0x03,0x2a,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x34,0x0a,0x9d,0x6f,0x76,0x94,0x05,0x65,0x0a,0xa2,0x9c,0x12,0x06,0xe4,0x65, 0x75,0x25,0x25,0x5c,0xd7,0x26,0x26,0x61,0xfe,0xda,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x01,0x00,0xab,0x04,0xc2,0x01,0xc4,0x06,0x27,0x00,0x11,0x00,0x3d,0xb3,0x0f,0xe2,0x40,0x02,0xb8,0xff,0xc0,0xb5,0x09,0x0c,0x48,0x02,0xc0,0x0b,0xb8,0xff,0xe8,0x40,0x14,0x09,0x0c,0x48,0x0b,0x40,0x08,0x09,0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05, 0x01,0x05,0x80,0x08,0x11,0x0b,0x2f,0xc6,0xcd,0x1a,0xdc,0x5d,0x71,0xe1,0x00,0x2f,0xd5,0x1a,0xcd,0x2b,0x1a,0xdc,0x2b,0x1a,0xed,0x31,0x30,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0xab,0x25,0x2b,0x58,0x71,0x4d,0x39,0x6c,0x70,0x5e,0x11,0x28,0x06,0x23,0x04,0x54,0x47,0x3d,0x54, 0x07,0x32,0x73,0x4c,0x3f,0x08,0x00,0x02,0x00,0xa9,0x04,0xc2,0x03,0x2a,0x06,0xe4,0x00,0x12,0x00,0x19,0x00,0x50,0xb3,0x00,0x07,0xda,0x0c,0xb8,0xff,0xc0,0x40,0x09,0x09,0x0c,0x48,0x0c,0x10,0xda,0x40,0x03,0x09,0xb8,0xff,0xc0,0x40,0x1a,0x09,0x0c,0x48,0x09,0x19,0x80,0x17,0x13,0x13,0x00,0x17,0x0a,0x12,0xc4,0x00,0x09,0xc4,0x0f, 0x00,0x01,0x0a,0x00,0x0a,0x00,0x1b,0x1a,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xe1,0x10,0xe1,0x10,0xc6,0x10,0xc4,0x00,0x2f,0xc4,0x1a,0xdd,0xd6,0x2b,0xd6,0x1a,0xfd,0xdc,0x2b,0xed,0xc4,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x13,0x23,0x27,0x07,0x23,0x37,0x33, 0x03,0x2a,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x3b,0x79,0xa4,0xa6,0x70,0xd7,0x85,0x06,0xe4,0x65,0x75,0x25,0x25,0x5c,0xd7,0x26,0x26,0x61,0xfd,0xde,0x94,0x94,0xfa,0x00,0x00,0x02,0x00,0x25,0x04,0xc2,0x02,0x4a,0x06,0xa0,0x00,0x03,0x00,0x0f,0x00,0x3b,0xb3,0x02,0x00,0x04,0x0a,0xb8,0xff,0xc0, 0x40,0x18,0x09,0x0c,0x48,0x0a,0x0d,0xd9,0x40,0x07,0x02,0x80,0x00,0x00,0x0b,0x0f,0xf3,0x04,0x0b,0xf3,0x0a,0x04,0x0a,0x04,0x11,0x10,0x11,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x10,0xe1,0x11,0x39,0x2f,0x1a,0xcd,0x00,0x2f,0x1a,0xfd,0xdc,0x2b,0xc4,0xd4,0xcd,0x31,0x30,0x13,0x37,0x33,0x07,0x37,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16, 0x33,0x32,0x37,0xd7,0xb5,0xa7,0xdd,0xf4,0x0a,0x9d,0x70,0x75,0x94,0x05,0x64,0x0b,0xa1,0x9d,0x12,0x05,0xaa,0xf6,0xf6,0x14,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x02,0x00,0x38,0x04,0xc2,0x02,0x5c,0x06,0xa0,0x00,0x03,0x00,0x0f,0x00,0x3d,0xb3,0x03,0x01,0x0a,0x04,0xb8,0xff,0xc0,0x40,0x19,0x09,0x0c,0x48,0x04,0x07,0xd9,0x40,0x0d, 0x02,0x80,0x00,0x00,0x05,0x09,0xf3,0x0a,0x05,0xf3,0x04,0x0a,0x04,0x0a,0x04,0x11,0x10,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x12,0x39,0x2f,0x1a,0xcd,0x00,0x2f,0x1a,0xfd,0xdc,0x2b,0xc4,0xd4,0xcd,0x31,0x30,0x01,0x23,0x27,0x33,0x07,0x33,0x16,0x33,0x32,0x37,0x33,0x06,0x06,0x23,0x22,0x26,0x01,0xaa,0x7f,0xdd,0xa8, 0xbe,0x66,0x10,0x9e,0xa2,0x0a,0x64,0x04,0x96,0x74,0x70,0x9c,0x05,0xaa,0xf6,0xe2,0x86,0x86,0x72,0x8a,0x8c,0x00,0x00,0x02,0x00,0x25,0x04,0xc2,0x02,0x4a,0x07,0x0a,0x00,0x11,0x00,0x1d,0x00,0x68,0x40,0x0d,0x0f,0xe2,0x10,0x02,0x20,0x02,0x30,0x02,0xf0,0x02,0x04,0x02,0x0b,0xb8,0xff,0xd8,0x40,0x0a,0x0d,0x10,0x48,0x0b,0x08,0x09, 0x09,0x1b,0x12,0x18,0xb8,0xff,0xc0,0x40,0x21,0x09,0x0c,0x48,0x18,0x1b,0xd9,0x40,0x15,0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05,0x01,0x05,0x80,0x08,0x11,0x0b,0x0b,0x18,0x1d,0xf3,0x12,0x19,0xf3,0x18,0x18,0x12,0x1f,0x1e,0x11,0x12,0x39,0x39,0x10,0xe1,0x10,0xe1,0x11,0x39,0x2f,0xc6,0xcd,0x1a,0xdc,0x5d,0x71,0xe1,0x00,0x2f,0x1a,0xfd, 0xd4,0x2b,0xc4,0x12,0x39,0x2f,0xd5,0xcd,0x2b,0xd4,0x5d,0xed,0x31,0x30,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0x05,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x37,0xcd,0x25,0x2a,0x5b,0x6f,0x50,0x36,0x6c,0x70,0x5e,0x11,0x28,0x01,0x7d,0x0a,0x9d,0x70,0x75,0x94,0x05, 0x64,0x0b,0xa1,0x9d,0x12,0x07,0x06,0x04,0x54,0x48,0x3c,0x54,0x07,0x31,0x72,0x4c,0x40,0x08,0xde,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x00,0x02,0x00,0xa9,0x04,0xc2,0x03,0x2a,0x06,0xe4,0x00,0x12,0x00,0x1e,0x00,0x5c,0xb3,0x12,0x07,0xda,0x0c,0xb8,0xff,0xc0,0xb7,0x09,0x0c,0x48,0x0c,0x10,0xda,0x03,0x0a,0xb8,0xff,0xc0,0x40,0x23, 0x09,0x0c,0x48,0x0a,0x1e,0x19,0x1c,0xd9,0x16,0x1e,0xf3,0x13,0x13,0x00,0x12,0x1a,0xf3,0x19,0x19,0x09,0x0a,0x12,0xc4,0x00,0x09,0xc4,0x0f,0x00,0x01,0x0a,0x00,0x0a,0x00,0x20,0x1f,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xe1,0x10,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x00,0x2f,0xfd,0xdc,0xc4,0xd6,0x2b,0xd4,0xfd, 0xdc,0x2b,0xed,0xc6,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x13,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x37,0x03,0x2a,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x34,0x0a,0x9d,0x6f,0x76,0x94,0x05,0x65,0x0a,0xa2,0x9c, 0x12,0x06,0xe4,0x65,0x75,0x25,0x25,0x5c,0xd7,0x26,0x26,0x61,0xfe,0xda,0x71,0x8b,0x8a,0x72,0x86,0x86,0x00,0x02,0x00,0x6c,0x04,0xc2,0x03,0x68,0x06,0xbe,0x00,0x11,0x00,0x18,0x00,0x5e,0x40,0x0c,0x0f,0xe2,0x0f,0x02,0x01,0x02,0x40,0x0d,0x10,0x48,0x02,0x0b,0xb8,0xff,0xe8,0xb6,0x09,0x0c,0x48,0x0b,0x40,0x08,0x09,0xb8,0xff,0xc0, 0x40,0x21,0x09,0x0c,0x48,0x09,0x09,0x17,0x16,0x0d,0xc2,0x4f,0x05,0x01,0xcf,0x05,0x01,0x05,0x80,0x08,0x40,0x11,0x11,0x0b,0x0b,0x80,0x12,0x90,0x12,0xa0,0x12,0x03,0x12,0xc0,0x16,0x2f,0x1a,0xcc,0x5d,0x39,0x2f,0xc6,0xc6,0x1a,0xcd,0x1a,0xdc,0x5d,0x71,0xe1,0x00,0x2f,0xcd,0x39,0x2f,0x2b,0xd5,0x1a,0xcd,0x2b,0xdc,0x2b,0x5d,0xed, 0x31,0x30,0x01,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x32,0x35,0x34,0x23,0x22,0x07,0x13,0x23,0x27,0x07,0x23,0x37,0x33,0x02,0x50,0x24,0x2c,0x59,0x6f,0x4b,0x39,0x6d,0x71,0x5f,0x11,0x28,0x4e,0x78,0xa4,0xa6,0x70,0xd6,0x86,0x06,0xba,0x04,0x53,0x48,0x3c,0x54,0x07,0x32,0x73,0x4b,0x40,0x08,0xfe,0x72,0x94,0x94, 0xfa,0x00,0xff,0xff,0x00,0x16,0xfe,0xc6,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x56,0x00,0x00,0x00,0x0b,0xb6,0x02,0x18,0x13,0x19,0x06,0x07,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0xc6,0x03,0x83,0x04,0x18,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xc2,0x00,0x00, 0x00,0x0e,0xb9,0x00,0x02,0xff,0xf7,0xb4,0x23,0x29,0x0f,0x00,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x85,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x50,0x01,0x7c,0x01,0x5e,0x00,0x16,0xb9,0x00,0x02,0xff,0xf2,0x40,0x09,0x1a,0x19,0x0b,0x0b,0x3e,0x02,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0x27,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x44,0x00,0xf4,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0b,0x31,0x25,0x10,0x14,0x25,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0xad,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07, 0x02,0x48,0x01,0x2e,0x01,0x5d,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf4,0x40,0x0a,0x16,0x16,0x06,0x07,0x25,0x03,0x02,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0x52,0x06,0x50,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x48,0x00,0xc2,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02, 0x00,0x28,0x24,0x10,0x14,0x25,0x03,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0xad,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x49,0x00,0x13,0x01,0x5d,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf7,0x40,0x0a,0x15,0x16,0x06,0x07,0x25,0x03,0x02,0x1a,0x05,0x26, 0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xe8,0xff,0xe8,0x03,0x83,0x06,0x50,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x06,0x02,0x49,0xa6,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x09,0x25,0x26,0x0d,0x12,0x25,0x03,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12, 0x08,0x1c,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x56,0x01,0x07,0x01,0x5e,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf9,0x40,0x0a,0x27,0x28,0x06,0x07,0x25,0x03,0x02,0x26,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0xe9,0x06,0xbe,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x4a, 0x00,0x81,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf3,0x40,0x0a,0x37,0x38,0x0d,0x12,0x25,0x03,0x02,0x36,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x08,0x3f,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x51,0x00,0xa3,0x01,0x5b,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf9, 0x40,0x0a,0x28,0x29,0x06,0x07,0x25,0x03,0x02,0x27,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0xe4,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x06,0x02,0x4b,0x2f,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x05,0x38,0x39,0x0d,0x12,0x25,0x03,0x02,0x37,0x11,0x26,0x00,0x2b,0x35,0x35,0x01, 0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0xfe,0xc6,0x05,0x12,0x07,0x6b,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x27,0x00,0xd7,0x01,0x11,0x01,0x5d,0x01,0x07,0x02,0x45,0x01,0x56,0x00,0x00,0x00,0x1e,0x40,0x0c,0x02,0x14,0x05,0x26,0x03,0x17,0x1a,0x20,0x05,0x00,0x3e,0x02,0xb8,0xff,0xf4,0xb4,0x14,0x10,0x06,0x07,0x3e,0x2b,0x35,0x2b, 0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x5a,0xfe,0xc6,0x03,0x83,0x06,0x0e,0x02,0x26,0x00,0x44,0x00,0x00,0x00,0x27,0x00,0xd7,0x00,0x97,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xc2,0x00,0x00,0x00,0x1b,0x40,0x12,0x02,0x24,0x11,0x26,0x03,0x29,0x2a,0x30,0x08,0x14,0x3e,0x02,0x1f,0x24,0x20,0x08,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b, 0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0xfb,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x52,0x01,0x59,0x01,0x5b,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfd,0x40,0x0a,0x1a,0x14,0x06,0x07,0x25,0x03,0x02,0x17,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0xa0, 0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x4c,0x00,0xe5,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x06,0x27,0x2d,0x0d,0x12,0x25,0x03,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0xfc,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x53,0x01,0x43,0x01,0x5c, 0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfa,0x40,0x0a,0x14,0x1a,0x06,0x07,0x25,0x03,0x02,0x1d,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0xa0,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x4d,0x00,0xe5,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x1f,0x27,0x2d,0x0d,0x12,0x25, 0x03,0x02,0x2d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x08,0x65,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x54,0x01,0x64,0x01,0x5b,0x00,0x2c,0xb1,0x03,0x02,0xb8,0xff,0xfb,0x40,0x1a,0x1a,0x19,0x06,0x07,0x25,0x03,0x6f,0x25,0x8f,0x25,0x02,0x02,0x20,0x25,0x30,0x25, 0x50,0x25,0x60,0x25,0x80,0x25,0x05,0x25,0x05,0x26,0x00,0x2b,0x71,0x35,0x71,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x07,0x0a,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x02,0x4e,0x00,0xe5,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfc,0x40,0x0a,0x2a,0x29,0x0d,0x12,0x25,0x03,0x02,0x35,0x11,0x26, 0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x08,0x3f,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x02,0x55,0x00,0xad,0x01,0x5b,0x00,0x17,0x40,0x0d,0x03,0x02,0x03,0x1a,0x10,0x06,0x07,0x25,0x03,0x02,0x26,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8, 0x03,0x83,0x06,0xe4,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x06,0x02,0x4f,0x35,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x09,0x36,0x3c,0x0d,0x12,0x25,0x03,0x02,0x36,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0xfe,0xc6,0x05,0x12,0x07,0x1a,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x27,0x00,0xda,0x01,0x5e, 0x01,0x5c,0x01,0x07,0x02,0x45,0x01,0x56,0x00,0x00,0x00,0x1b,0x40,0x12,0x02,0x13,0x05,0x26,0x03,0x17,0x20,0x26,0x05,0x00,0x3e,0x02,0x02,0x16,0x10,0x06,0x07,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0xc6,0x03,0x83,0x05,0xbe,0x02,0x26,0x00,0x44,0x00,0x00,0x00,0x27,0x00,0xda,0x00,0xdc,0x00,0x00, 0x01,0x07,0x02,0x45,0x00,0xc2,0x00,0x00,0x00,0x1b,0x40,0x12,0x02,0x23,0x11,0x26,0x03,0x29,0x30,0x36,0x08,0x14,0x3e,0x02,0x25,0x26,0x20,0x08,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x03,0xb4,0x05,0x9a,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xf3,0x00,0x00,0x00,0x0b, 0xb6,0x01,0x10,0x0f,0x15,0x02,0x0b,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0xc6,0x03,0xdd,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xf2,0x00,0x00,0x00,0x0b,0xb6,0x02,0x27,0x1d,0x23,0x19,0x13,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x83,0x02,0x26,0x00,0x28, 0x00,0x00,0x01,0x07,0x02,0x50,0x01,0x0d,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x0c,0x1d,0x11,0x02,0x0b,0x3e,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x27,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0x44,0x01,0x19,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x30,0x2b,0x1f, 0x19,0x13,0x3e,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x0e,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xdc,0x01,0x5c,0x00,0x17,0x40,0x0e,0x01,0x07,0x16,0x0c,0x02,0x0b,0x3e,0x01,0x00,0x16,0x01,0x16,0x05,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0xb2,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xc8,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0d,0x24,0x1a,0x0c,0x12,0x25,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x6f,0x07,0xab,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07, 0x02,0x48,0x00,0xdf,0x01,0x5b,0x00,0x17,0x40,0x0d,0x02,0x01,0x13,0x14,0x10,0x02,0x03,0x25,0x02,0x01,0x14,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x5a,0x06,0x50,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0x48,0x00,0xca,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf0, 0x40,0x0a,0x23,0x24,0x16,0x0f,0x25,0x03,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x0e,0x00,0x00,0x03,0xb4,0x07,0xad,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x02,0x49,0xff,0xcc,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x19,0x10,0x13,0x02,0x03,0x25,0x02,0x01,0x16,0x05,0x26,0x00,0x2b,0x35, 0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x0c,0xff,0xe8,0x03,0xdd,0x06,0x50,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x06,0x02,0x49,0xca,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x0a,0x1f,0x20,0x16,0x0f,0x25,0x03,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x20,0x08,0x1a, 0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x02,0x56,0x00,0xb8,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x15,0x22,0x1e,0x02,0x03,0x25,0x02,0x01,0x22,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x32,0x06,0xbe,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0x4a,0x00,0xca,0x00,0x00, 0x00,0x17,0x40,0x0d,0x03,0x02,0x19,0x31,0x32,0x16,0x0f,0x25,0x03,0x02,0x30,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x08,0x40,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x02,0x51,0x00,0x4e,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x0f,0x23,0x1f,0x02,0x03,0x25,0x02,0x01, 0x23,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0xe4,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x06,0x02,0x4b,0x47,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x10,0x31,0x2d,0x19,0x13,0x25,0x03,0x02,0x31,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc, 0xfe,0xc6,0x03,0xb4,0x07,0x6b,0x02,0x26,0x00,0x28,0x00,0x00,0x00,0x27,0x00,0xd7,0x00,0xbf,0x01,0x5d,0x01,0x07,0x02,0x45,0x00,0xea,0x00,0x00,0x00,0x1e,0x40,0x0c,0x01,0x10,0x05,0x26,0x02,0x07,0x16,0x1c,0x01,0x00,0x3e,0x01,0xb8,0xff,0xfd,0xb4,0x10,0x0c,0x01,0x00,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x60, 0xfe,0xc6,0x03,0xdd,0x06,0x0e,0x02,0x26,0x00,0x48,0x00,0x00,0x00,0x27,0x00,0xd7,0x00,0xb4,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xef,0x00,0x00,0x00,0x1b,0x40,0x12,0x02,0x1e,0x11,0x26,0x03,0x26,0x24,0x2a,0x0c,0x12,0x3e,0x02,0x0c,0x1e,0x1a,0x0c,0x12,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x9a,0x00,0x00, 0x01,0xb3,0x07,0x83,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x02,0x50,0xff,0xef,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x0e,0x0d,0x02,0x03,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x88,0x00,0x00,0x01,0xa1,0x06,0x27,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06,0x02,0x44,0xdd,0x00,0x00,0x13, 0x40,0x0b,0x01,0x00,0x0e,0x0d,0x02,0x03,0x25,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xb2,0xfe,0xc6,0x01,0x78,0x05,0x9a,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x06,0x02,0x45,0xc0,0x00,0x00,0x0b,0xb6,0x01,0x05,0x07,0x0d,0x02,0x03,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xfe,0xc6,0x01,0x66, 0x05,0xd9,0x02,0x26,0x00,0x4c,0x00,0x00,0x01,0x06,0x02,0x45,0xa3,0x00,0x00,0x0e,0xb9,0x00,0x02,0xff,0xfd,0xb4,0x13,0x19,0x03,0x09,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xfe,0xc6,0x05,0xaa,0x05,0xb2,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0xa8,0x00,0x00,0x00,0x0e,0xb9,0x00,0x02,0xff,0xf9,0xb4,0x1b,0x21, 0x03,0x09,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0xc6,0x04,0x50,0x04,0x18,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x06,0x00,0x00,0x00,0x0b,0xb6,0x02,0x03,0x1b,0x21,0x03,0x09,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x83,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0x50, 0x01,0xf6,0x01,0x5c,0x00,0x16,0xb9,0x00,0x02,0xff,0xee,0x40,0x09,0x22,0x21,0x0c,0x06,0x3e,0x02,0x22,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x27,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0x44,0x01,0x43,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe7,0x40,0x09,0x22,0x21,0x0c, 0x06,0x25,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0xad,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0x48,0x01,0xb3,0x01,0x5d,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1e,0x1e,0x0c,0x0c,0x25,0x03,0x02,0x20,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff, 0x00,0x60,0xff,0xe8,0x04,0x98,0x06,0x50,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0x48,0x01,0x08,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x03,0x1e,0x1e,0x0c,0x0c,0x25,0x03,0x02,0x20,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0xad,0x02,0x26,0x00,0x32,0x00,0x00, 0x01,0x07,0x02,0x49,0x00,0x94,0x01,0x5d,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x21,0x21,0x0c,0x06,0x25,0x03,0x02,0x22,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x30,0xff,0xe8,0x04,0x50,0x06,0x50,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x02,0x49,0xee,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfd, 0x40,0x0a,0x21,0x21,0x06,0x06,0x25,0x03,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x08,0x1a,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0x56,0x01,0x78,0x01,0x5c,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xed,0x40,0x0a,0x2f,0x30,0x0c,0x06,0x25,0x03,0x02,0x2e,0x05,0x26, 0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0xbe,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0x4a,0x00,0xe5,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfd,0x40,0x0a,0x2c,0x2c,0x06,0x06,0x25,0x03,0x02,0x2e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5e, 0xff,0xe8,0x05,0xaa,0x08,0x40,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0x51,0x01,0x29,0x01,0x5c,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x2d,0x2d,0x0c,0x06,0x25,0x03,0x02,0x2f,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0xe4,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06, 0x02,0x4b,0x70,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf5,0x40,0x0a,0x30,0x31,0x0c,0x06,0x25,0x03,0x02,0x2f,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5e,0xfe,0xc6,0x05,0xaa,0x07,0x6b,0x02,0x26,0x00,0x32,0x00,0x00,0x00,0x27,0x00,0xd7,0x01,0xa4,0x01,0x5d,0x01,0x07,0x02,0x45,0x01,0xb0,0x00,0x00, 0x00,0x1b,0x40,0x12,0x02,0x1c,0x05,0x26,0x03,0x01,0x22,0x28,0x03,0x09,0x3e,0x02,0x16,0x1c,0x18,0x03,0x09,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0xc6,0x04,0x50,0x06,0x0e,0x02,0x26,0x00,0x52,0x00,0x00,0x00,0x27,0x00,0xd7,0x00,0xf7,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xfe,0x00,0x00,0x00,0x1e, 0xb4,0x02,0x1c,0x11,0x26,0x03,0xb8,0xff,0xfb,0x40,0x0c,0x22,0x28,0x03,0x09,0x3e,0x02,0x15,0x1c,0x18,0x03,0x09,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x06,0x3a,0x07,0x67,0x02,0x26,0x02,0x40,0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x0e,0x01,0x5d,0x00,0x13,0x40,0x0b,0x02,0x00,0x27,0x27,0x18,0x18, 0x25,0x02,0x28,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0xa9,0x06,0x0a,0x02,0x26,0x02,0x41,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x61,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xfd,0x40,0x09,0x26,0x26,0x10,0x10,0x25,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e, 0xff,0xe8,0x06,0x3a,0x07,0x67,0x02,0x26,0x02,0x40,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0xc8,0x01,0x5d,0x00,0x13,0x40,0x0b,0x02,0x0a,0x27,0x27,0x18,0x18,0x25,0x02,0x27,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0xa9,0x06,0x0a,0x02,0x26,0x02,0x41,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x02, 0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xfc,0x40,0x09,0x26,0x26,0x19,0x19,0x25,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x06,0x3a,0x07,0x83,0x02,0x26,0x02,0x40,0x00,0x00,0x01,0x07,0x02,0x50,0x02,0x0c,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x00,0x30,0x2f,0x18,0x18,0x25,0x02,0x2f,0x05, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0xa9,0x06,0x27,0x02,0x26,0x02,0x41,0x00,0x00,0x01,0x07,0x02,0x44,0x01,0x45,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe9,0x40,0x09,0x2f,0x2e,0x19,0x10,0x25,0x02,0x2f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x06,0x3a, 0x07,0x0e,0x02,0x26,0x02,0x40,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0xb0,0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x0f,0x30,0x26,0x15,0x0f,0x25,0x02,0x30,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0xa9,0x05,0xb2,0x02,0x26,0x02,0x41,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xf8,0x00,0x00,0x00,0x13, 0x40,0x0b,0x02,0x03,0x2f,0x25,0x0d,0x07,0x3e,0x02,0x2f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xfe,0xc6,0x06,0x3a,0x06,0x3e,0x02,0x26,0x02,0x40,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0xac,0x00,0x00,0x00,0x0b,0xb6,0x02,0x03,0x2c,0x2c,0x12,0x12,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0xc6, 0x04,0xa9,0x04,0xfc,0x02,0x26,0x02,0x41,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x02,0x00,0x00,0x00,0x0b,0xb6,0x02,0x05,0x2b,0x2b,0x0a,0x0a,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xfe,0xc6,0x04,0xd5,0x05,0x9a,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x66,0x00,0x00,0x00,0x0b,0xb6,0x01,0x07,0x14,0x14,0x02, 0x02,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xfe,0xc6,0x03,0xe2,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xd1,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0xff,0xfb,0xb4,0x18,0x18,0x0c,0x0c,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x83,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07, 0x02,0x50,0x01,0x97,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x0f,0x1f,0x13,0x05,0x0d,0x3e,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x27,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x02,0x44,0x01,0x22,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x20,0x23,0x17,0x08,0x11,0x3e,0x01, 0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x07,0x67,0x02,0x26,0x02,0x42,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xb8,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x19,0x19,0x06,0x0c,0x3e,0x01,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x04,0xc7, 0x06,0x0a,0x02,0x26,0x02,0x43,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x38,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x06,0x1d,0x1d,0x09,0x10,0x3e,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x07,0x67,0x02,0x26,0x02,0x42,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x7a,0x01,0x5d,0x00,0x13, 0x40,0x0b,0x01,0x13,0x19,0x19,0x06,0x0c,0x3e,0x01,0x19,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x04,0xc7,0x06,0x0a,0x02,0x26,0x02,0x43,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xc4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x23,0x1d,0x1c,0x09,0x10,0x3e,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x07,0x83,0x02,0x26,0x02,0x42,0x00,0x00,0x01,0x07,0x02,0x50,0x01,0x9d,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xe6,0x40,0x09,0x22,0x21,0x06,0x0c,0x3e,0x01,0x22,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x90,0xff,0xe8,0x04,0xc7,0x06,0x27,0x02,0x26,0x02,0x43, 0x00,0x00,0x01,0x07,0x02,0x44,0x01,0x27,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf7,0x40,0x09,0x26,0x25,0x09,0x10,0x3e,0x01,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x07,0x0e,0x02,0x26,0x02,0x42,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x66,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x0a, 0x22,0x18,0x06,0x0c,0x3e,0x01,0x22,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x04,0xc7,0x05,0xb2,0x02,0x26,0x02,0x43,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xdd,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x07,0x26,0x1c,0x08,0x1b,0x3e,0x01,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0xaa,0xfe,0xc6,0x05,0xd0,0x06,0x96,0x02,0x26,0x02,0x42,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x66,0x00,0x00,0x00,0x0b,0xb6,0x01,0x07,0x1e,0x1e,0x02,0x02,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xfe,0xc6,0x04,0xc7,0x04,0xfc,0x02,0x26,0x02,0x43,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xe5,0x00,0x00,0x00,0x0b,0xb6,0x01, 0x00,0x1f,0x25,0x0a,0x01,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12,0xfe,0xc6,0x04,0x60,0x05,0x9a,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xdf,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x11,0x17,0x03,0x02,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x04,0x00,0x02,0x26,0x00,0x5c,0x00,0x00, 0x01,0x07,0x02,0x45,0x01,0xc2,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0xff,0xec,0xb4,0x15,0x1b,0x14,0x14,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x07,0x83,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x02,0x50,0x01,0x1a,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x18,0x1f,0x13,0x05,0x00,0x3e,0x01,0x18,0x05,0x26,0x00, 0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x27,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x02,0x44,0x00,0xc9,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x0f,0x26,0x1a,0x0c,0x00,0x3e,0x01,0x1f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x07,0x0e,0x02,0x26, 0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xde,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x08,0x18,0x0e,0x05,0x00,0x3e,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0xb2,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0x8b,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff, 0xfd,0x40,0x09,0x1f,0x15,0x0c,0x00,0x3e,0x01,0x1f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x29,0xfe,0x85,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x01,0x9c,0x00,0x93,0x00,0x00,0x00,0x0b,0xb6,0x01,0x1d,0x0b,0x0b,0x03,0x03,0x3e,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x2b,0xfe,0x85,0x02,0x81, 0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x06,0x01,0x9c,0x2a,0x00,0x00,0x0e,0xb9,0x00,0x01,0xff,0xe7,0xb4,0x17,0x15,0x04,0x00,0x3e,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x67,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x14,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xf0,0x40,0x09,0x0e, 0x0c,0x02,0x0b,0x3e,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x0a,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xe5,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xd9,0x40,0x09,0x1c,0x1a,0x19,0x13,0x3e,0x02,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff, 0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x67,0x02,0x26,0x01,0xef,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0xda,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xf0,0x40,0x09,0x16,0x14,0x0b,0x01,0x3e,0x01,0x15,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x00,0x06,0x0a,0x02,0x26,0x02,0x0f,0x00,0x00,0x01,0x07, 0x00,0x43,0x00,0xde,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xb4,0x40,0x09,0x11,0x0f,0x07,0x0d,0x3e,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x01,0x64,0x05,0x9a,0x02,0x06,0x00,0x2c,0x00,0x00,0xff,0xff,0x00,0x14,0xff,0xe8,0x02,0x2b,0x05,0x9a,0x02,0x06,0x00,0x2d,0x00,0x00,0xff,0xff, 0x00,0x90,0x00,0x00,0x01,0x66,0x05,0xd9,0x02,0x06,0x00,0x4c,0x00,0x00,0xff,0xff,0xff,0x3a,0xfe,0x1e,0x01,0x66,0x05,0xd9,0x02,0x06,0x00,0x4d,0x00,0x00,0x00,0x01,0x00,0x29,0x00,0x00,0x03,0xf6,0x05,0x9a,0x00,0x0d,0x00,0x5b,0x40,0x2c,0x05,0x08,0x91,0x02,0x0b,0x0b,0x07,0x01,0x91,0x0c,0x03,0x07,0x09,0x08,0x04,0x00,0x04,0x00, 0x0f,0x02,0x05,0x08,0x0d,0x06,0x4d,0x05,0x08,0x0c,0x06,0x4d,0x05,0x08,0x0b,0x06,0x4d,0x05,0x7e,0x0b,0x08,0x08,0x0d,0x06,0x4d,0x08,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x08,0xb8,0xff,0xe0,0xb3,0x0b,0x06,0x4d,0x08,0x2f,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x11,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x00,0x2f,0x3f,0xed,0x12, 0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x21,0x03,0xf6,0xfd,0xc0,0x01,0x5a,0xfe,0xa6,0xa8,0xe5,0xe5,0x02,0xe8,0x05,0x02,0xfe,0x36,0x9a,0xfd,0x62,0x02,0x9e,0x9a,0x02,0x62,0x00,0x01,0x00,0x1e,0x00,0x00,0x03,0x29,0x04,0x00,0x00,0x0d,0x00,0x5e,0x40,0x27,0x05,0x08, 0x96,0x02,0x0b,0x0b,0x07,0x01,0x95,0x0c,0x0f,0x07,0x09,0x07,0x04,0x00,0x04,0x00,0x0f,0x02,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x0b,0x07,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xe4,0xb3,0x0c,0x06,0x4d,0x07,0xb8,0xff,0xe4,0xb3,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b, 0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x11,0x39,0x39,0x2f,0x2f,0x10,0xc6,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x21,0x03,0x29,0xfe,0x6b,0x01,0x02,0xfe,0xfe,0xa4,0xd2,0xd2,0x02,0x39,0x03,0x74,0xfe,0xe2,0x85,0xfe,0x2f,0x01,0xd1,0x85,0x01, 0xaa,0x00,0x00,0x01,0xff,0xea,0xfe,0x80,0x07,0x0a,0x05,0x9a,0x00,0x21,0x00,0xae,0x40,0x13,0x13,0x0d,0x1c,0x04,0x04,0x10,0x1f,0x10,0x0e,0x12,0x20,0x91,0x03,0x40,0x1d,0x17,0x12,0x03,0x01,0xb8,0x01,0x30,0xb3,0x09,0x03,0x0e,0x02,0xb8,0x01,0x2c,0x40,0x09,0x21,0x1d,0x1e,0x1e,0x08,0x20,0x03,0x02,0x21,0xb8,0xff,0xf8,0x40,0x26, 0x0c,0x06,0x4d,0x21,0x0e,0x08,0x12,0x11,0x11,0x09,0x0e,0x0f,0x0f,0x09,0x42,0x0f,0x1f,0x18,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x7e,0x17,0x10,0x09,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xf4,0x40,0x11,0x0c,0x06,0x4d,0x09,0x13,0x0b,0x06,0x4d,0x09,0x09,0x23,0x22,0x2f, 0x23,0x3f,0x23,0x02,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x33,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x32,0x2f,0x2b,0x11,0x01,0x33,0x12,0x39,0x18,0x2f,0x33,0x10,0xe0,0x2b,0x11,0x33,0x33,0x11,0x39,0x2f,0x33,0x10,0xe1,0x00,0x2f,0x33,0x33,0x3f,0x3f,0x33,0x33,0x1a,0x10,0xed,0x11,0x12,0x39,0x39,0x11,0x17,0x33,0x31,0x30,0x01,0x23, 0x11,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x01,0x16,0x17,0x33,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x01,0x33,0x07,0x0a,0x99,0x50,0xfd,0xcf,0x18,0x0d,0x05,0x9f,0x04,0x0f,0x16,0xfd,0xcf,0xe3,0x02,0x91,0xfd,0x9b,0xce,0x02,0x1a,0x17,0x0e,0x04,0x9f,0x05,0x0d,0x18,0x02,0x1a, 0xcd,0xfd,0x9b,0x02,0x0d,0x8b,0xfe,0x80,0x01,0x80,0x02,0x90,0x1c,0x16,0xfd,0x3e,0x02,0xc2,0x19,0x19,0xfd,0x70,0x02,0xe8,0x02,0xb2,0xfd,0x93,0x1b,0x16,0x02,0x9e,0xfd,0x62,0x16,0x1b,0x02,0x6d,0xfd,0x4e,0xfd,0xae,0x00,0x01,0x00,0x04,0xfe,0x8b,0x06,0x00,0x04,0x00,0x00,0x19,0x00,0xa4,0xb9,0x00,0x01,0x01,0x31,0x40,0x15,0x04, 0x09,0x0f,0x14,0x04,0x0c,0x17,0x0c,0x07,0x15,0x0e,0x11,0x0f,0x18,0x96,0x03,0x40,0x0a,0x03,0x07,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x19,0xb8,0x01,0x2c,0x40,0x2c,0x02,0x15,0x16,0x16,0x06,0x18,0x03,0x02,0x02,0x19,0x0e,0x06,0x0e,0x0d,0x0d,0x07,0x0a,0x0b,0x0b,0x07,0x42,0x0b,0x17,0x12,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08, 0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x11,0x0c,0x07,0xb8,0xff,0xf0,0x40,0x11,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x0c,0x0b,0x06,0x4d,0x07,0x07,0x1a,0x1b,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x33,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x32,0x2f,0x2b,0x11,0x01,0x33,0x12,0x39,0x18,0x2f,0x33,0x10,0xe0,0x32,0x2f, 0x33,0x33,0x11,0x39,0x2f,0x33,0x10,0xe1,0x2b,0x00,0x2f,0x33,0x33,0x1a,0x10,0xed,0x3f,0x33,0x33,0x12,0x39,0x39,0x11,0x17,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x01,0x23,0x11,0x23,0x11,0x23,0x01,0x23,0x01,0x01,0x33,0x01,0x33,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x01,0x33,0x06,0x00,0x8c,0x5c,0xfe,0x36,0x04,0x9c,0x04,0xfe, 0x35,0xdb,0x01,0xfc,0xfe,0x23,0xd1,0x01,0xb6,0x04,0x9c,0x04,0x01,0xb6,0xd3,0xfe,0x21,0x01,0x81,0x87,0xfe,0x8b,0x01,0x75,0x01,0xfa,0xfe,0x06,0x01,0xfa,0xfe,0x06,0x02,0x10,0x01,0xf0,0xfe,0x21,0x01,0xdf,0xfe,0x21,0x01,0xdf,0xfe,0x10,0xfe,0x71,0x00,0x01,0x00,0xbc,0xfe,0x80,0x04,0xa8,0x05,0x9a,0x00,0x14,0x00,0x87,0xb9,0x00, 0x01,0x01,0x30,0x40,0x1c,0x0f,0x04,0x12,0x12,0x08,0x10,0x0b,0x03,0x13,0x91,0x02,0x02,0x08,0x10,0x11,0x11,0x08,0x14,0x08,0x0d,0x06,0x4d,0x14,0x08,0x0c,0x06,0x4d,0x14,0xb8,0x01,0x2c,0xb2,0x13,0x03,0x02,0xb8,0xff,0xf8,0x40,0x1a,0x0d,0x06,0x4d,0x02,0x02,0x16,0x12,0x0b,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08, 0x08,0x0b,0x06,0x4d,0x08,0x7e,0x09,0xb8,0xff,0xf4,0xb3,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xfc,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfc,0xb3,0x0b,0x06,0x4d,0x09,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x32,0x11,0x33,0x2f,0x2b,0x33,0x33,0xe1,0x2b,0x2b,0x11,0x39,0x2f,0x33,0x00,0x2f,0x33,0x10,0xed,0x3f,0x33,0x12,0x39,0x11, 0x33,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x01,0x33,0x04,0xa8,0x9a,0x50,0xfd,0xd0,0x1b,0x0b,0x04,0xa8,0xa8,0x04,0x0e,0x18,0x02,0x18,0xd1,0xfd,0x99,0x02,0x0c,0x8c,0xfe,0x80,0x01,0x80,0x02,0x90,0x20,0x12,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x16,0x1b, 0x02,0x71,0xfd,0x4e,0xfd,0xae,0x00,0x01,0x00,0xa6,0xfe,0x8b,0x04,0x00,0x04,0x00,0x00,0x10,0x00,0x7b,0xb9,0x00,0x01,0x01,0x31,0x40,0x1d,0x0f,0x96,0x03,0x0b,0x04,0x0e,0x0e,0x06,0x0c,0x09,0x0f,0x11,0x03,0x06,0x0c,0x0d,0x0d,0x06,0x10,0x08,0x0d,0x06,0x4d,0x10,0x08,0x0c,0x06,0x4d,0x10,0xb8,0x01,0x2c,0x40,0x19,0x0f,0x03,0x02, 0x02,0x12,0x0e,0x09,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x07,0xb8,0xff,0xf8,0x40,0x0e,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x32,0x11,0x39,0x2f,0x33,0x33,0xe1,0x2b,0x2b,0x11,0x39,0x2f,0x33,0x00, 0x2f,0x33,0x33,0x3f,0x33,0x12,0x39,0x11,0x33,0x33,0x10,0xed,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x01,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x01,0x33,0x04,0x00,0x8c,0x64,0xfe,0x3e,0x04,0xa4,0xa4,0x04,0x01,0xae,0xd9,0xfe,0x23,0x01,0x7f,0x89,0xfe,0x8b,0x01,0x75,0x01,0xea,0xfe,0x16,0x04,0x00,0xfe,0x2d,0x01,0xd3, 0xfe,0x10,0xfe,0x71,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x18,0x00,0xaa,0x40,0x51,0x00,0x03,0x10,0x03,0x20,0x03,0x03,0x03,0x03,0x02,0x0a,0x0f,0x14,0x1f,0x14,0x2f,0x14,0x03,0x14,0x14,0x0d,0x15,0x12,0x11,0x0f,0x16,0x0f,0x11,0x16,0x0f,0x06,0x05,0x02,0x01,0x08,0x01,0x06,0x08,0x01,0x0f,0x08,0x18,0x18,0x0a, 0x16,0x0d,0x03,0x01,0x0a,0x15,0x02,0x12,0x0f,0x05,0x01,0x05,0x05,0x00,0x16,0x17,0x17,0x01,0x19,0x00,0x29,0x00,0x02,0x0f,0x00,0x01,0x00,0x00,0x1a,0x08,0x0d,0x0f,0x18,0x04,0x0a,0x7e,0x0b,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x2f,0x2b,0x2b,0x2b,0xe1, 0x17,0x32,0x11,0x39,0x2f,0x5d,0x5d,0x33,0x39,0x2f,0x33,0x11,0x39,0x2f,0x5d,0x33,0xcd,0x32,0x00,0x2f,0x33,0x3f,0x33,0x12,0x39,0x11,0x33,0x33,0x11,0x12,0x01,0x39,0x10,0x87,0x04,0xc0,0xc0,0xc0,0x11,0x12,0x01,0x39,0x10,0x87,0x04,0xc0,0xc0,0xc0,0x11,0x00,0x39,0x2f,0x5d,0x11,0x12,0x39,0x2f,0x5d,0x31,0x30,0x21,0x23,0x01,0x11, 0x23,0x11,0x27,0x26,0x35,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x37,0x37,0x11,0x33,0x15,0x01,0x33,0x01,0x04,0xa2,0xea,0xfe,0x58,0x4c,0x36,0x26,0x04,0xa8,0xa8,0x04,0x0e,0x18,0x36,0x4c,0x01,0x96,0xd1,0xfd,0x99,0x01,0xf4,0xfe,0xf2,0x01,0x68,0x42,0x2f,0x03,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x16,0x1b,0x3f,0x01,0x52,0xf8,0x01, 0xd8,0xfd,0x50,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf4,0x04,0x00,0x00,0x14,0x00,0x81,0x40,0x4c,0x1f,0x04,0x01,0x50,0x04,0x60,0x04,0x02,0x04,0x04,0x02,0x08,0x5f,0x0f,0x6f,0x0f,0x02,0x0f,0x0f,0x0b,0x11,0x0e,0x0d,0x12,0x0d,0x05,0x02,0x01,0x06,0x01,0x0d,0x06,0x14,0x14,0x08,0x12,0x0b,0x0f,0x01,0x08,0x11,0x02,0x0e,0x05, 0x05,0x00,0x12,0x38,0x13,0x48,0x13,0x02,0x13,0x13,0x01,0x0f,0x00,0xaf,0x00,0x02,0x39,0x00,0x49,0x00,0x02,0x00,0x00,0x16,0x06,0x0b,0x0d,0x14,0x04,0x08,0x84,0x09,0x2f,0xe1,0x17,0x32,0x11,0x39,0x2f,0x5d,0x5d,0x33,0x39,0x2f,0x5d,0x33,0x11,0x39,0x2f,0x33,0xcd,0x32,0x00,0x2f,0x33,0x3f,0x33,0x12,0x39,0x11,0x33,0x33,0x10,0x87, 0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x11,0x00,0x39,0x2f,0x5d,0x11,0x12,0x39,0x2f,0x5d,0x5d,0x31,0x30,0x21,0x23,0x01,0x15,0x23,0x11,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x37,0x35,0x33,0x15,0x01,0x33,0x01,0x03,0xf4,0xe4,0xfe,0xe6,0x4c,0x5c,0x04,0xa4,0xa4,0x04,0x5c,0x4c,0x01,0x06,0xd9,0xfe,0x23,0x01,0x33,0xc1,0x01,0x13,0x65, 0xfe,0x16,0x04,0x00,0xfe,0x2d,0x65,0xed,0x9b,0x01,0x1c,0xfe,0x10,0x00,0x00,0x01,0x00,0xbc,0xfe,0x80,0x05,0xb2,0x05,0x9a,0x00,0x0f,0x00,0xb7,0x40,0x0b,0x05,0x91,0x40,0x0a,0x09,0x06,0x0a,0x91,0x2b,0x30,0x01,0xb8,0x01,0x30,0x40,0x13,0x0e,0x91,0x03,0x0c,0x09,0x03,0x03,0x06,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x08,0x0c,0x06,0x4d, 0x0f,0xba,0x01,0x2c,0x00,0x02,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xe8,0x40,0x19,0x0c,0x06,0x4d,0x02,0x02,0x11,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x7e,0x0b,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xe0,0x40,0x1e,0x0c,0x06,0x4d,0x03,0x10,0x0b,0x06,0x4d, 0x03,0x03,0x11,0x09,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x7e,0x07,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x07,0xb8,0xff,0xf7,0xb3,0x0c,0x06,0x4d,0x07,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x7d,0x2f,0x2b,0x2b,0xe1, 0x2b,0x2b,0x00,0x18,0x2f,0x33,0x3f,0x33,0x10,0xed,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x05,0xb2,0x9b,0xcd,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0xa8,0xc0,0xfe,0x80,0x01,0x80,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfa,0xfe,0x00, 0x00,0x01,0x00,0xa6,0xfe,0x8b,0x04,0x90,0x04,0x00,0x00,0x0f,0x00,0x9c,0xb9,0x00,0x01,0x01,0x31,0x40,0x13,0x0e,0x95,0x03,0x05,0x95,0x40,0x0a,0x09,0x06,0x0a,0x95,0x2b,0x30,0x0c,0x09,0x0f,0x03,0x06,0x02,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x02,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x0f,0xba,0x01,0x2c,0x00,0x02,0xff,0xf8,0x40, 0x40,0x0d,0x06,0x4d,0x02,0x02,0x11,0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x84,0x0b,0x03,0x03,0x0d,0x06,0x4d,0x03,0x03,0x0b,0x06,0x4d,0x03,0x03,0x11,0x0a,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x84,0x07,0x08,0x0d,0x06,0x4d,0x07,0x40,0x11, 0x01,0x5d,0x2f,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x11,0x39,0x2f,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x11,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x00,0x2f,0x33,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x10,0xed,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x04,0x90,0x8e,0xae,0xfd,0xf6, 0xa4,0xa4,0x02,0x0a,0xa4,0x98,0xfe,0x8b,0x01,0x75,0x01,0xd1,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4,0xfc,0x8c,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x02,0x06,0x00,0x3c,0x00,0x00,0x00,0x01,0x00,0x0e,0xfe,0x29,0x03,0xd5,0x04,0x00,0x00,0x0c,0x00,0x68,0x40,0x0c,0x03,0x1b,0x04,0x42,0x01,0x01,0x0d,0x0c,0x06,0x0f, 0x0c,0x00,0xb8,0xff,0xf8,0x40,0x24,0x0c,0x06,0x4d,0x00,0x0e,0x01,0x06,0x05,0x04,0x05,0x42,0x05,0x08,0x01,0x08,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0x08,0x0b,0x06,0x4d,0x01,0x84,0x04,0x07,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xf4,0x40,0x0a,0x0c,0x06,0x4d,0x04,0x04,0x0e,0x0d,0x4f,0x0e,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b, 0x2b,0xe1,0x2b,0x2b,0x2b,0x39,0x2f,0x2b,0x11,0x01,0x33,0x10,0xe1,0x2b,0x32,0x00,0x18,0x3f,0x33,0x12,0x39,0x7d,0x2f,0x18,0xe5,0x3f,0x31,0x30,0x01,0x01,0x11,0x23,0x11,0x01,0x33,0x01,0x17,0x33,0x36,0x37,0x01,0x03,0xd5,0xfe,0x69,0xa4,0xfe,0x74,0xb6,0x01,0x0d,0x1d,0x02,0x0a,0x16,0x01,0x1b,0x04,0x00,0xfc,0x06,0xfe,0x23,0x01, 0xdf,0x03,0xf8,0xfd,0x04,0x64,0x22,0x46,0x02,0xf8,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x00,0x14,0x00,0x7d,0x40,0x16,0x11,0x0d,0x07,0x04,0x97,0x40,0x0a,0x01,0x01,0x06,0x14,0x0d,0x03,0x06,0x11,0x10,0x05,0x06,0x03,0x03,0x14,0x00,0xb8,0xff,0xd8,0x40,0x23,0x0b,0x06,0x4d,0x00,0x0e,0x05,0x08,0x08,0x06,0x0d,0x0c, 0x06,0x0c,0x42,0x0c,0x01,0x05,0x08,0x0d,0x06,0x4d,0x05,0x08,0x0c,0x06,0x4d,0x05,0x08,0x0b,0x06,0x4d,0x05,0x7e,0x0b,0x06,0xb8,0xff,0xf8,0x40,0x0a,0x0b,0x06,0x4d,0x06,0x06,0x16,0x15,0x20,0x16,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x32,0x2f,0x2b,0x11,0x01,0x33,0x12,0x39,0x18,0x2f,0x10,0xe0,0x2b,0x32, 0x39,0x2f,0x11,0x12,0x39,0x39,0x00,0x2f,0x3f,0x33,0x12,0x39,0x2f,0x33,0x1a,0xed,0x32,0x12,0x39,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x35,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x04,0x60,0xfe,0x27,0x01,0x52,0xfe,0xae,0xa8,0xfe,0xb7,0x01,0x49,0xfe,0x33,0xbf,0x01,0x41,0x06,0x1d,0x03,0x0a, 0x1c,0x01,0x50,0x05,0x9a,0xfc,0x72,0x85,0xfe,0x79,0x01,0x87,0x85,0x02,0x03,0x8c,0xfd,0x78,0x0c,0x4c,0x22,0x36,0x02,0x88,0x00,0x01,0x00,0x0e,0xfe,0x29,0x03,0xd5,0x04,0x00,0x00,0x12,0x00,0x60,0x40,0x35,0x04,0x1b,0x02,0x05,0x96,0x08,0x40,0x0c,0x0c,0x08,0x10,0x0a,0x0f,0x12,0x08,0x00,0x00,0x10,0x11,0x0e,0x02,0x07,0x07,0x05, 0x0a,0x09,0x09,0x05,0x42,0x09,0x0d,0x0c,0x12,0x02,0x08,0x0d,0x06,0x4d,0x02,0x84,0x08,0x05,0x07,0x0d,0x06,0x4d,0x05,0x05,0x14,0x13,0x4f,0x14,0x01,0x5d,0x11,0x12,0x39,0x2f,0x2b,0x33,0xe1,0x2b,0x32,0x39,0x39,0x2f,0x2b,0x11,0x01,0x33,0x12,0x39,0x18,0x2f,0x10,0xe0,0x32,0x39,0x2f,0x00,0x2f,0x33,0x3f,0x33,0x12,0x39,0x2f,0x1a, 0x10,0xed,0x32,0x3f,0x31,0x30,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x01,0x33,0x01,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x03,0x92,0xfe,0xac,0xa4,0xfe,0xb4,0x01,0x4c,0xfe,0x74,0xb6,0x01,0x0d,0x1d,0x02,0x0a,0x16,0x01,0x1b,0xaa,0xfe,0x69,0x85,0xfe,0xae,0x01,0x52,0x85,0x04,0x00,0xfd,0x04,0x64,0x22,0x46,0x02,0xf8,0xfc, 0x00,0x00,0x00,0x01,0x00,0x1a,0xfe,0x80,0x04,0xc6,0x05,0x9a,0x00,0x19,0x00,0x5f,0xb9,0x00,0x01,0x01,0x30,0x40,0x20,0x06,0x11,0x17,0x03,0x0c,0x0c,0x0a,0x15,0x0e,0x03,0x18,0x91,0x03,0x1a,0x03,0x0a,0x06,0x0c,0x11,0x17,0x04,0x0d,0x15,0x16,0x0e,0x0d,0x16,0x0d,0x16,0x0d,0x0b,0x19,0xb8,0x01,0x2c,0x40,0x0d,0x18,0x03,0x03,0x02, 0x10,0x0d,0x06,0x4d,0x02,0x02,0x1b,0x0a,0x0b,0x2f,0x33,0x12,0x39,0x2f,0x2b,0x33,0x11,0x33,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x12,0x17,0x39,0x00,0x2f,0x33,0x33,0x10,0xed,0x3f,0x33,0x12,0x39,0x11,0x17,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x01,0x16, 0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x01,0x33,0x04,0xc6,0x98,0x61,0xfe,0xb6,0x0f,0x12,0x04,0x0a,0x18,0xfe,0xac,0xce,0x01,0xe0,0xfe,0x46,0xce,0x01,0x25,0x1d,0x16,0x04,0x20,0x18,0x01,0x31,0xc1,0xfe,0x3d,0x01,0x6b,0x8a,0xfe,0x80,0x01,0x80,0x02,0x25,0x19,0x2e,0x17,0x30,0xfd,0xdb,0x02,0xd1,0x02,0xc9,0xfe,0x08,0x32,0x32,0x42, 0x26,0x01,0xf4,0xfd,0x39,0xfd,0xc3,0x00,0x00,0x01,0x00,0x1a,0xfe,0x8b,0x03,0xb4,0x04,0x00,0x00,0x17,0x00,0x5f,0xb9,0x00,0x01,0x01,0x31,0x40,0x20,0x06,0x11,0x15,0x03,0x0c,0x0c,0x0a,0x13,0x0e,0x0f,0x16,0x96,0x02,0x18,0x02,0x0a,0x06,0x0c,0x11,0x15,0x04,0x0d,0x13,0x14,0x0e,0x0d,0x14,0x0d,0x14,0x0d,0x0b,0x17,0xb8,0x01,0x2c, 0x40,0x0d,0x16,0x03,0x03,0x02,0x08,0x0d,0x06,0x4d,0x02,0x02,0x19,0x0a,0x0b,0x2f,0x33,0x12,0x39,0x2f,0x2b,0x33,0x11,0x33,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x12,0x17,0x39,0x00,0x2f,0x33,0x33,0x10,0xed,0x3f,0x33,0x12,0x39,0x11,0x17,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03, 0x23,0x01,0x01,0x33,0x13,0x16,0x17,0x33,0x01,0x33,0x01,0x13,0x33,0x03,0xb4,0x8b,0x5c,0xc9,0x15,0x18,0x04,0x05,0x2a,0xcd,0xbd,0x01,0x5d,0xfe,0xb2,0xbf,0xc6,0x15,0x16,0x04,0x01,0x00,0xb5,0xfe,0xa8,0xfb,0x7f,0xfe,0x8b,0x01,0x75,0x01,0x4c,0x23,0x2b,0x09,0x45,0xfe,0xb4,0x01,0xf6,0x02,0x0a,0xfe,0xa2,0x26,0x2a,0x01,0xae,0xfd, 0xfa,0xfe,0x87,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x81,0x05,0x9a,0x00,0x17,0x00,0xa0,0x40,0x40,0x11,0x11,0x0c,0x0f,0x06,0x06,0x01,0x04,0x02,0x15,0x07,0x91,0x0f,0x15,0x15,0x13,0x16,0x0f,0x0f,0x01,0x16,0x0c,0x03,0x01,0x05,0x06,0x12,0x11,0x40,0x0c,0x15,0x11,0x7f,0x2b,0x30,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06, 0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x15,0x01,0x1e,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x18,0x0b,0x06,0x4d,0x01,0x01,0x19,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x7e,0x0b,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x0b,0x0c,0x0b,0x06,0x4d,0x0b,0x2f, 0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x1a,0x18,0x10,0xcd,0x33,0x32,0x00,0x2f,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x10,0xed,0x11,0x39,0x39,0x11,0x39,0x2f,0x11,0x12,0x39,0x2f,0x31,0x30,0x21,0x23,0x11,0x06,0x07,0x11,0x23,0x11,0x06,0x26,0x35,0x11,0x33,0x11, 0x14,0x33,0x33,0x11,0x33,0x11,0x36,0x37,0x11,0x33,0x04,0x81,0xa8,0xa7,0x88,0x4c,0xce,0xea,0xa8,0xf6,0x1a,0x4c,0x86,0xa9,0xa8,0x02,0x85,0x58,0x17,0xfe,0xae,0x01,0x4a,0x0f,0xc3,0xbd,0x02,0x1b,0xfd,0xed,0xe7,0x01,0x6a,0xfe,0x9e,0x14,0x52,0x02,0x8c,0x00,0x00,0x01,0x00,0x98,0x00,0x00,0x03,0xdf,0x04,0x00,0x00,0x16,0x00,0x8e, 0x40,0x5b,0x10,0x10,0x0b,0x0e,0x06,0x06,0x01,0x04,0x02,0x07,0x14,0x14,0x12,0x15,0x0e,0x95,0x07,0x07,0x01,0x15,0x0b,0x0f,0x01,0x05,0x06,0x11,0x10,0x40,0x0b,0x14,0x10,0x85,0x2b,0x30,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x84,0x14,0x01,0x01,0x18,0x0b,0x08,0x0d,0x06,0x4d,0x0b,0x08, 0x0c,0x06,0x4d,0x0b,0x08,0x0b,0x06,0x4d,0x0b,0x84,0x0a,0x05,0x0d,0x06,0x4d,0x0a,0x05,0x0c,0x06,0x4d,0x0a,0x04,0x0b,0x06,0x4d,0x0a,0x2f,0x18,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x33,0xe1,0x2b,0x2b,0x2b,0x2b,0x01,0x1a,0x18,0x10,0xcd,0x33,0x32,0x00,0x2f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x11,0x39, 0x39,0x2f,0x12,0x39,0x39,0x11,0x39,0x2f,0x11,0x12,0x39,0x2f,0x31,0x30,0x21,0x23,0x11,0x06,0x07,0x15,0x23,0x35,0x04,0x11,0x11,0x33,0x11,0x14,0x33,0x33,0x11,0x33,0x11,0x36,0x37,0x11,0x33,0x03,0xdf,0xa3,0x76,0x66,0x4c,0xfe,0x84,0xa4,0xc2,0x16,0x4c,0x6e,0x6e,0xa3,0x01,0x9c,0x40,0x16,0xd4,0xca,0x1c,0x01,0x86,0x01,0x5a,0xfe, 0xae,0xe1,0x01,0x25,0xfe,0xe5,0x14,0x38,0x01,0xdd,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x81,0x05,0x9a,0x00,0x10,0x00,0x73,0x40,0x27,0x0b,0x06,0x04,0x91,0x0d,0x0d,0x07,0x0a,0x03,0x01,0x07,0x00,0x08,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x01,0x1e,0x0d,0x06,0x4d,0x01,0x08,0x0c,0x06,0x4d, 0x01,0xb8,0xff,0xfc,0x40,0x19,0x0b,0x06,0x4d,0x01,0x01,0x12,0x0b,0x07,0x08,0x0d,0x06,0x4d,0x07,0x08,0x0c,0x06,0x4d,0x07,0x08,0x0b,0x06,0x4d,0x07,0x7e,0x08,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x08,0x0c,0x0b,0x06,0x4d,0x08,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x00, 0x2f,0x33,0x3f,0x12,0x39,0x2f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x34,0x23,0x22,0x07,0x11,0x23,0x11,0x33,0x11,0x36,0x33,0x32,0x16,0x15,0x04,0x81,0xa8,0xf5,0xb4,0xe2,0xa8,0xa8,0xe4,0xc6,0xba,0xcf,0x02,0x12,0xe8,0x6e,0xfd,0x74,0x05,0x9a,0xfd,0x7a,0x7a,0xc2,0xb2,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec, 0x02,0x06,0x00,0x4b,0x00,0x00,0x00,0x02,0x00,0x56,0xff,0xe8,0x05,0x66,0x05,0xb2,0x00,0x11,0x00,0x18,0x00,0x77,0x40,0x29,0x12,0x91,0x01,0x20,0x01,0x50,0x01,0x02,0x01,0x09,0x16,0x2f,0x06,0x01,0x06,0x06,0x04,0x91,0x09,0x04,0x16,0x91,0x0f,0x13,0x06,0x06,0x00,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x7d,0x01, 0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf8,0x40,0x1d,0x0c,0x06,0x4d,0x12,0x12,0x1a,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x7d,0x00,0x10,0x0d,0x06,0x4d,0x00,0x08,0x0c,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0xe1,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x33,0xe1,0x2b,0x2b,0x11,0x39,0x2f,0x00,0x3f,0xed, 0x3f,0xed,0x32,0x2f,0x5d,0x11,0x12,0x39,0x5d,0x2f,0xed,0x31,0x30,0x13,0x21,0x26,0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x25,0x21,0x16,0x12,0x33,0x32,0x00,0x56,0x04,0x5e,0x11,0xfe,0xe5,0xda,0xd8,0x9c,0x9e,0xe2,0x01,0x3f,0x01,0x6d,0xfe,0x94,0xfe,0xd3,0xfe,0xd1,0xfe,0xb8,0x04,0x5e,0xfc, 0x56,0x04,0xf2,0xcf,0xcf,0x01,0x02,0x03,0x1a,0xed,0x01,0x13,0x60,0xa4,0x54,0xfe,0x76,0xfe,0xa5,0xfe,0xbe,0xfe,0x5d,0x01,0x9f,0xfc,0xeb,0xfe,0xe7,0x01,0x18,0x00,0x00,0x02,0x00,0x52,0xff,0xe8,0x03,0xcf,0x04,0x18,0x00,0x12,0x00,0x19,0x00,0x56,0x40,0x23,0x06,0x40,0x0b,0x0e,0x48,0x06,0x06,0x04,0x13,0x95,0x01,0x01,0x17,0x04, 0x95,0x09,0x10,0x17,0x95,0x0f,0x16,0x80,0x06,0x90,0x06,0x02,0x06,0x06,0x0c,0x00,0x13,0x14,0x0c,0x83,0x01,0xb8,0xff,0xf8,0x40,0x0e,0x0d,0x06,0x4d,0x01,0x01,0x1b,0x14,0x83,0x00,0x10,0x0d,0x06,0x4d,0x00,0x2f,0x2b,0xe1,0x12,0x39,0x2f,0x2b,0xe1,0x12,0x39,0x11,0x12,0x39,0x2f,0x5d,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed, 0x12,0x39,0x2f,0x2b,0x31,0x30,0x13,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x12,0x15,0x14,0x00,0x23,0x22,0x02,0x35,0x05,0x21,0x16,0x16,0x33,0x32,0x36,0x52,0x02,0xd3,0x04,0xb0,0x9a,0xae,0x90,0x86,0xdf,0xd9,0xf8,0xfe,0xf1,0xc8,0xcb,0xdb,0x02,0xd1,0xfd,0xd7,0x02,0x84,0x7a,0x74,0xa3,0x02,0x29,0xab,0xba,0x72,0x9a, 0x62,0xfe,0xea,0xfe,0xf2,0xfe,0xd6,0x01,0x06,0xe5,0x35,0x8d,0x9f,0xa6,0x00,0x03,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x12,0x00,0x19,0x00,0x63,0x40,0x18,0x14,0x91,0x40,0x12,0x06,0x00,0x12,0x91,0x2b,0x30,0x0f,0x91,0x06,0x04,0x17,0x91,0x00,0x13,0x09,0x7d,0x12,0x0c,0x14,0x13,0xb8,0xff,0xf0,0xb3,0x0d,0x06, 0x4d,0x13,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x13,0xb8,0xff,0xe0,0x40,0x18,0x0b,0x06,0x4d,0x13,0x13,0x1b,0x14,0x7d,0x03,0x10,0x0d,0x06,0x4d,0x03,0x10,0x0c,0x06,0x4d,0x03,0x18,0x0b,0x06,0x4d,0x03,0x2f,0x2b,0x2b,0x2b,0xe1,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x12,0x39,0x39,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a, 0xed,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x13,0x26,0x00,0x23,0x22,0x00,0x07,0x05,0x21,0x16,0x00,0x33,0x32,0x00,0x02,0xfe,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0x8c,0xc0,0x12,0xfe,0xfd,0xd7,0xd0,0xfe,0xee,0x16,0x03,0xe4,0xfc,0x1c,0x15,0x01,0x0c,0xcb,0xdc,0x01, 0x09,0x18,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0x03,0x30,0xf5,0x01,0x0d,0xfe,0xe8,0xea,0x9b,0xea,0xfe,0xec,0x01,0x0b,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x6b,0x40,0x18,0x13,0x95,0x40,0x11,0x06,0x00,0x11,0x95,0x2b,0x30,0x0e,0x95, 0x06,0x10,0x16,0x95,0x00,0x16,0x11,0x0c,0x13,0x09,0x83,0x12,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xf0,0xb6,0x0c,0x06,0x4d,0x30,0x12,0x01,0x12,0xb8,0xff,0xde,0x40,0x1b,0x0b,0x06,0x4d,0x12,0x12,0x19,0x13,0x83,0x03,0x10,0x0d,0x06,0x4d,0x03,0x0c,0x0c,0x06,0x4d,0x03,0x19,0x0b,0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d, 0x2f,0x2b,0x2b,0x2b,0xe1,0x12,0x39,0x2f,0x2b,0x5d,0x2b,0x2b,0xe1,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x13,0x02,0x21,0x22,0x06,0x07,0x05,0x21,0x16,0x16,0x33,0x20,0x02,0x52,0xe4,0xfe,0xf2,0x01,0x1a,0xf0,0xe5,0x01,0x01, 0xfe,0xeb,0x67,0x29,0xfe,0xe5,0x88,0xb1,0x17,0x02,0x98,0xfd,0x64,0x0a,0xb7,0x93,0x01,0x33,0x18,0x01,0x20,0xec,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x02,0x74,0x01,0x32,0xa0,0x92,0x8b,0xa3,0xbc,0x00,0x00,0x02,0x00,0x3e,0x06,0x1e,0x02,0x3a,0x07,0xcf,0x00,0x03,0x00,0x07,0x00,0x2d,0xb2,0x02,0x80,0x01,0xb8,0xff, 0xc0,0x40,0x12,0x09,0x0c,0x48,0x01,0x06,0xe2,0x05,0x02,0x62,0x00,0x01,0x00,0x00,0x05,0x04,0x04,0x09,0x05,0x2f,0x12,0x39,0x2f,0x12,0x39,0x2f,0x5d,0xcd,0x00,0x2f,0xfd,0xd6,0x2b,0x1a,0xcd,0x31,0x30,0x01,0x23,0x27,0x33,0x01,0x21,0x35,0x21,0x01,0xaa,0x7f,0xdd,0xa8,0x01,0x44,0xfe,0x04,0x01,0xfc,0x06,0xd9,0xf6,0xfe,0x4f,0x6e, 0x00,0x02,0x00,0x3e,0x04,0xc2,0x02,0x3a,0x06,0x72,0x00,0x03,0x00,0x07,0x00,0x24,0x40,0x11,0x02,0x80,0x01,0x06,0xe2,0x05,0x02,0x62,0x00,0x01,0x00,0x00,0x05,0x04,0x04,0x09,0x05,0x2f,0x12,0x39,0x2f,0x12,0x39,0x2f,0x5d,0xcd,0x00,0x2f,0xfd,0xde,0x1a,0xcd,0x31,0x30,0x01,0x23,0x27,0x33,0x01,0x21,0x35,0x21,0x01,0xaa,0x7f,0xdd, 0xa8,0x01,0x44,0xfe,0x04,0x01,0xfc,0x05,0x7d,0xf5,0xfe,0x50,0x6d,0x00,0x00,0x02,0x00,0x3e,0x06,0x1e,0x02,0x3a,0x07,0xcf,0x00,0x03,0x00,0x07,0x00,0x2d,0xb2,0x01,0x80,0x00,0xb8,0xff,0xc0,0x40,0x12,0x09,0x0c,0x48,0x00,0x05,0xe2,0x04,0x02,0x6d,0x00,0x01,0x00,0x00,0x04,0x07,0x07,0x09,0x04,0x2f,0x12,0x39,0x2f,0x12,0x39,0x2f, 0x5d,0xcd,0x00,0x2f,0xfd,0xd6,0x2b,0x1a,0xcd,0x31,0x30,0x13,0x37,0x33,0x07,0x05,0x35,0x21,0x15,0xcd,0xb4,0xa8,0xdd,0xfe,0xf2,0x01,0xfc,0x06,0xd9,0xf6,0xf6,0xbb,0x6e,0x6e,0x00,0x02,0x00,0x3e,0x04,0xc2,0x02,0x3a,0x06,0x72,0x00,0x03,0x00,0x07,0x00,0x24,0x40,0x11,0x01,0x80,0x00,0x05,0xe2,0x04,0x02,0x6d,0x00,0x01,0x00,0x00, 0x04,0x07,0x07,0x09,0x04,0x2f,0x12,0x39,0x2f,0x12,0x39,0x2f,0x5d,0xcd,0x00,0x2f,0xfd,0xde,0x1a,0xcd,0x31,0x30,0x13,0x37,0x33,0x07,0x05,0x35,0x21,0x15,0xcd,0xb4,0xa8,0xdd,0xfe,0xf2,0x01,0xfc,0x05,0x7d,0xf5,0xf5,0xbb,0x6d,0x6d,0x00,0x00,0x03,0x00,0x7d,0x06,0x1e,0x02,0xc4,0x07,0xd1,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x44, 0xb2,0x01,0x80,0x00,0xb8,0xff,0xc0,0x40,0x20,0x09,0x0c,0x48,0x00,0x00,0x0a,0x16,0xc1,0x04,0x10,0x02,0x02,0x01,0x0f,0x03,0x02,0x40,0x00,0x00,0x19,0x0d,0xc0,0x07,0x13,0xc0,0x19,0x1c,0x1d,0x19,0x07,0x2b,0x3a,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x12,0x39,0x18,0x2f,0x1a,0xcd,0x5f,0x5e,0x5d,0x00,0x2f,0x33,0xed,0x32,0x39,0x2f,0x2b, 0x1a,0xcd,0x31,0x30,0x01,0x37,0x33,0x07,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x50,0xb4,0xa8,0xdd,0x93,0x28,0x3a,0x38,0x28,0x2a,0x3a,0x38,0xfe,0x56,0x2a,0x3b,0x3b,0x27,0x29,0x3c,0x3a,0x06,0xdb,0xf6,0xf6,0xbd,0x39,0x2a,0x2a,0x39,0x3a, 0x29,0x29,0x3a,0x3b,0x28,0x2a,0x39,0x3a,0x29,0x29,0x3a,0x00,0x00,0x03,0x00,0x7d,0x04,0xc2,0x02,0xc4,0x06,0x74,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x3b,0x40,0x1f,0x01,0x80,0x00,0x00,0x0a,0x16,0xc1,0x04,0x10,0x02,0x02,0x01,0x0f,0x03,0x02,0x40,0x00,0x00,0x19,0x0d,0xc0,0x07,0x13,0xc0,0x19,0x1c,0x1d,0x19,0x07,0x2b,0x3a,0x2b, 0x01,0x10,0xe1,0x10,0xe1,0x12,0x39,0x18,0x2f,0x1a,0xcd,0x5f,0x5e,0x5d,0x00,0x2f,0x33,0xed,0x32,0x39,0x2f,0x1a,0xcd,0x31,0x30,0x01,0x37,0x33,0x07,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x50,0xb4,0xa8,0xdd,0x93,0x28,0x3a,0x38,0x28,0x2a, 0x3a,0x38,0xfe,0x56,0x2a,0x3b,0x39,0x29,0x29,0x3c,0x3a,0x05,0x7f,0xf5,0xf5,0xbd,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x3b,0x28,0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0x02,0x00,0xa9,0x06,0x0c,0x03,0x2a,0x08,0x08,0x00,0x03,0x00,0x16,0x00,0x54,0xb9,0x00,0x01,0xff,0xc0,0x40,0x0f,0x09,0x0d,0x48,0x01,0x80,0x03,0x40,0x10,0x15, 0x48,0x03,0x16,0x10,0xda,0x0b,0xb8,0xff,0xc0,0x40,0x1e,0x09,0x0c,0x48,0x0b,0x14,0xda,0x07,0x0d,0x02,0x20,0x0a,0x0d,0x48,0x02,0x5f,0x00,0x6f,0x00,0x02,0x00,0x00,0x0e,0x04,0xc4,0x16,0x16,0x18,0x0d,0xc4,0x0e,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x5d,0xcd,0x2b,0x00,0x2f,0xd6,0xed,0xdc,0x2b,0xfd,0xc6,0xd6,0x2b,0x1a, 0xcd,0x2b,0x31,0x30,0x01,0x37,0x33,0x07,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x62,0xb4,0xa8,0xdc,0x01,0x48,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x07,0x12,0xf6,0xf6,0x1a,0x65,0x75,0x25,0x25,0x5c,0xd8,0x26,0x26,0x60,0x00,0x02, 0x00,0xa9,0x04,0xb2,0x03,0x2a,0x06,0xae,0x00,0x03,0x00,0x16,0x00,0x3e,0xb2,0x01,0x80,0x00,0xb8,0xff,0xc0,0x40,0x1d,0x09,0x0c,0x48,0x00,0x16,0x10,0xda,0x0b,0x14,0xda,0x07,0x0d,0x02,0x5f,0x00,0x6f,0x00,0x02,0x00,0x00,0x0e,0x04,0xc4,0x16,0x16,0x18,0x0d,0xc4,0x0e,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x5d,0xcd,0x00, 0x2f,0xd6,0xed,0xdc,0xfd,0xc6,0xde,0x2b,0x1a,0xcd,0x31,0x30,0x01,0x37,0x33,0x07,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x62,0xb4,0xa8,0xdc,0x01,0x48,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x05,0xb8,0xf6,0xf6,0x1a,0x65,0x75,0x25, 0x25,0x5c,0xd7,0x25,0x26,0x60,0x00,0x03,0x00,0xa9,0x06,0x0c,0x03,0x2a,0x08,0x02,0x00,0x0b,0x00,0x17,0x00,0x2a,0x00,0x66,0x40,0x10,0x06,0x12,0xc1,0x00,0x00,0x0c,0x10,0x0c,0x02,0x0c,0x03,0x0c,0x2a,0x24,0xda,0x1f,0xb8,0xff,0xc0,0x40,0x10,0x09,0x0c,0x48,0x1f,0x28,0xda,0x40,0x1b,0x21,0x09,0xc0,0x03,0x0f,0xc0,0x15,0x03,0xb8, 0xff,0xc0,0xb3,0x0a,0x0d,0x48,0x15,0xb8,0xff,0xc0,0x40,0x11,0x0a,0x0d,0x48,0x18,0x22,0x03,0x15,0x2b,0x3a,0x18,0xc4,0x2a,0x2a,0x2c,0x21,0xc4,0x22,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x2b,0x2b,0x10,0xe1,0x10,0xe1,0x00,0x18,0x2f,0xd6,0x1a,0xed,0xdc,0x2b,0xfd,0xc6,0xd6,0x5f,0x5e,0x5d,0x32,0xed,0x32,0x31,0x30,0x01,0x22, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x02,0xab,0x29,0x3a,0x39,0x28,0x29,0x3c,0x3a,0xfe,0x56,0x28,0x3c,0x3a,0x28,0x2a,0x3a,0x38,0x01,0xd6,0x5d,0x55,0x43, 0x56,0x57,0x29,0x58,0x5e,0xb6,0x3f,0x52,0x51,0x33,0x54,0x07,0x3e,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0x46,0x65,0x75,0x25,0x25,0x5c,0xd8,0x26,0x26,0x60,0x00,0x00,0x03,0x00,0xa9,0x04,0xb2,0x03,0x2a,0x06,0xa8,0x00,0x0b,0x00,0x17,0x00,0x2a,0x00,0x3f,0x40,0x22,0x06,0x12,0xc1,0x00, 0x0c,0x2a,0x24,0xda,0x1f,0x28,0xda,0x40,0x1b,0x21,0x09,0xc0,0x03,0x0f,0xc0,0x15,0x18,0x22,0x03,0x15,0x2b,0x3a,0x18,0xc4,0x2a,0x2a,0x2c,0x21,0xc4,0x22,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x00,0x18,0x2f,0xd6,0x1a,0xed,0xdc,0xfd,0xc6,0xde,0x32,0xed,0x32,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x02,0xab,0x29,0x3a,0x39,0x28,0x29,0x3c,0x3a,0xfe,0x56,0x28,0x3c,0x3a,0x28,0x2a,0x3a,0x38,0x01,0xd6,0x5d,0x55,0x43,0x56,0x57,0x29,0x58,0x5e, 0xb6,0x3f,0x52,0x51,0x33,0x54,0x05,0xe4,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0x38,0x2a,0x2a,0x38,0x39,0x29,0x2a,0x38,0x46,0x65,0x75,0x25,0x25,0x5c,0xd7,0x25,0x26,0x60,0x00,0x02,0x00,0x14,0x06,0x1e,0x02,0x12,0x07,0x6a,0x00,0x0b,0x00,0x0f,0x00,0x1f,0x40,0x0e,0x06,0xc1,0x40,0x00,0x00,0x0e,0x80,0x0c,0x03,0xc0,0x09,0x09, 0x0e,0x0c,0x2f,0xcd,0x39,0x2f,0xe1,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x17,0x37,0x33,0x07,0x76,0x28,0x3a,0x39,0x29,0x28,0x3a,0x3a,0x17,0xb5,0xa8,0xde,0x06,0xa8,0x38,0x2a,0x29,0x37,0x37,0x29,0x28,0x3a,0x8a,0xf6,0xf6,0x00,0x02,0x00,0x14,0x04,0xc2, 0x02,0x12,0x06,0x0e,0x00,0x0b,0x00,0x0f,0x00,0x1f,0x40,0x0e,0x06,0xc1,0x40,0x00,0x00,0x0e,0x80,0x0c,0x03,0xc0,0x09,0x09,0x0e,0x0c,0x2f,0xcd,0x39,0x2f,0xe1,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x17,0x37,0x33,0x07,0x76,0x28,0x3a,0x39,0x29,0x28,0x3a, 0x3a,0x17,0xb5,0xa8,0xde,0x05,0x4c,0x38,0x2a,0x29,0x37,0x37,0x29,0x29,0x39,0x8a,0xf6,0xf6,0x00,0x02,0x00,0x1e,0x06,0x1e,0x02,0x51,0x07,0xd7,0x00,0x0b,0x00,0x12,0x00,0x33,0xb3,0x06,0xc1,0x40,0x00,0xb8,0xff,0xc0,0x40,0x15,0x09,0x0c,0x48,0x00,0x00,0x0f,0x80,0x0e,0x03,0xc0,0x09,0x0c,0x0f,0x09,0xc0,0x2b,0x30,0x0c,0x0c,0x14, 0x0f,0x2f,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x00,0x18,0x2f,0x1a,0xcd,0x39,0x2f,0x2b,0x1a,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x07,0x23,0x27,0x33,0x17,0x37,0x01,0x34,0x28,0x3a,0x39,0x29,0x29,0x39,0x39,0xf4,0xd7,0x86,0xd6,0x70,0xa6,0xa4,0x07,0x14,0x39,0x2a,0x28,0x38,0x37,0x29, 0x29,0x3a,0x04,0xfa,0xfa,0x93,0x93,0x00,0x00,0x02,0x00,0x1e,0x04,0xc2,0x02,0x51,0x06,0x7b,0x00,0x0b,0x00,0x12,0x00,0x2a,0x40,0x15,0x06,0xc1,0x40,0x00,0x00,0x0f,0x80,0x0e,0x03,0xc0,0x09,0x0c,0x0f,0x09,0xc0,0x2b,0x30,0x0c,0x0c,0x14,0x0f,0x2f,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x00,0x18,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed, 0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x07,0x23,0x27,0x33,0x17,0x37,0x01,0x34,0x28,0x3a,0x39,0x29,0x29,0x39,0x39,0xf4,0xd7,0x86,0xd6,0x70,0xa6,0xa4,0x05,0xb8,0x39,0x29,0x29,0x38,0x37,0x2a,0x28,0x3a,0x04,0xfa,0xfa,0x93,0x93,0x00,0x03,0x00,0x14,0x06,0x1e,0x02,0x5b,0x07,0x9e,0x00,0x0b, 0x00,0x17,0x00,0x1b,0x00,0x39,0xb4,0x06,0x12,0xc1,0x00,0x0c,0xb8,0xff,0xc0,0x40,0x18,0x09,0x0c,0x48,0x0c,0x1a,0xe2,0x40,0x19,0x09,0xc0,0x03,0x0f,0xc0,0x15,0x18,0x19,0x03,0x15,0x2b,0x3a,0x18,0x18,0x1d,0x19,0x2f,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x00,0x18,0x2f,0x1a,0xfd,0xde,0x2b,0x32,0xed,0x32,0x31,0x30,0x01, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x21,0x35,0x21,0x01,0xf9,0x29,0x3a,0x39,0x28,0x29,0x3b,0x39,0xfe,0x56,0x2b,0x39,0x39,0x29,0x29,0x3b,0x39,0x01,0x99,0xfe,0x04,0x01,0xfc,0x06,0xd9,0x38,0x2b,0x2a,0x38,0x3a,0x28,0x2a,0x39,0x39,0x2a,0x29, 0x39,0x3a,0x28,0x2a,0x39,0xbb,0x6e,0x00,0x00,0x03,0x00,0x14,0x04,0xc2,0x02,0x5b,0x06,0x42,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x30,0x40,0x19,0x06,0x12,0xc1,0x00,0x0c,0x1a,0xe2,0x40,0x19,0x09,0xc0,0x03,0x0f,0xc0,0x15,0x18,0x19,0x03,0x15,0x2b,0x3a,0x18,0x18,0x1d,0x19,0x2f,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x00, 0x18,0x2f,0x1a,0xfd,0xde,0x32,0xed,0x32,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x21,0x35,0x21,0x01,0xf9,0x29,0x3a,0x39,0x28,0x29,0x3b,0x39,0xfe,0x56,0x2a,0x3a,0x3a,0x28,0x29,0x3b,0x39,0x01,0x99,0xfe,0x04,0x01,0xfc,0x05,0x7d, 0x38,0x2a,0x2a,0x39,0x3a,0x29,0x29,0x39,0x38,0x2a,0x2a,0x39,0x3a,0x29,0x29,0x39,0xbb,0x6d,0xff,0xff,0x00,0xbc,0xfe,0x50,0x03,0xb4,0x05,0x9a,0x02,0x26,0x00,0x28,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x8a,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x50,0x03,0xdd,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x7d, 0x00,0x00,0xff,0xff,0x00,0x16,0xfe,0x04,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xdc,0x01,0x75,0xf9,0x6c,0x00,0x27,0x40,0x1a,0x03,0x02,0x00,0x13,0x19,0x06,0x07,0x25,0x03,0x02,0x16,0x40,0x09,0x0d,0x36,0x16,0x40,0x0a,0x0b,0x36,0x20,0x16,0x01,0x16,0x14,0x26,0x00,0x2b,0x5d,0x2b,0x2b,0x35,0x35,0x01, 0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0x05,0x03,0x83,0x04,0x18,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xdc,0x00,0xe9,0xf9,0x6d,0x00,0x27,0x40,0x1a,0x03,0x02,0x1b,0x23,0x29,0x08,0x00,0x25,0x03,0x02,0x26,0x40,0x09,0x0d,0x36,0x26,0x40,0x0a,0x0b,0x36,0x20,0x26,0x01,0x26,0x17,0x26,0x00,0x2b,0x5d,0x2b,0x2b,0x35, 0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x2f,0x06,0xe2,0x02,0x26,0x00,0x25,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x47,0x01,0x5d,0x00,0x16,0xb9,0x00,0x03,0xff,0xc3,0x40,0x09,0x23,0x29,0x01,0x05,0x25,0x03,0x20,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xff,0xe8,0x04,0x54,0x05,0xec, 0x02,0x26,0x00,0x45,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x8b,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0xad,0x21,0x21,0x05,0x05,0x25,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x04,0x2f,0x05,0x9a,0x02,0x26,0x00,0x25,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xe1,0x00,0x00,0x00,0x1a,0xb9,0x00, 0x03,0xff,0xc1,0x40,0x0c,0x23,0x29,0x00,0x0c,0x25,0x03,0x20,0x26,0x01,0x26,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x04,0x54,0x05,0xec,0x02,0x26,0x00,0x45,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x1a,0x00,0x00,0x00,0x1a,0xb9,0x00,0x02,0xff,0xf2,0x40,0x0c,0x21,0x27,0x03,0x0c,0x25,0x02,0x20, 0x24,0x01,0x24,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xff,0x1e,0x04,0x2f,0x05,0x9a,0x02,0x26,0x00,0x25,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x1c,0xfa,0x5c,0x00,0x1a,0xb9,0x00,0x03,0xff,0xe3,0x40,0x0c,0x21,0x20,0x00,0x0c,0x25,0x03,0x20,0x22,0x01,0x22,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0xa6,0xff,0x1e,0x04,0x54,0x05,0xec,0x02,0x26,0x00,0x45,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x3f,0xfa,0x5c,0x00,0x17,0x40,0x0e,0x02,0x00,0x1f,0x1e,0x03,0x0c,0x25,0x02,0x20,0x20,0x01,0x20,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xfe,0x50,0x04,0x8c,0x07,0x67,0x02,0x26,0x00,0x26, 0x00,0x00,0x00,0x27,0x00,0xdd,0x02,0x39,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0xf5,0x01,0x5d,0x00,0x08,0xb3,0x02,0x2a,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0x50,0x03,0x62,0x06,0x0a,0x02,0x26,0x00,0x46,0x00,0x00,0x00,0x27,0x00,0xdd,0x01,0x83,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x2f,0x00,0x00,0x00,0x08,0xb3,0x02, 0x2a,0x11,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x3e,0x06,0xe2,0x02,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0xd2,0x01,0x5d,0x00,0x16,0xb9,0x00,0x02,0xff,0xa3,0x40,0x09,0x13,0x19,0x01,0x04,0x25,0x02,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x10,0x05,0xec, 0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x64,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0x29,0x40,0x09,0x27,0x27,0x0f,0x0f,0x25,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x05,0x3e,0x05,0x9a,0x02,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x54,0x00,0x00,0x00,0x1a, 0xb9,0x00,0x02,0xff,0xac,0x40,0x0c,0x13,0x19,0x00,0x04,0x25,0x02,0x20,0x16,0x01,0x16,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0xc6,0x04,0x10,0x05,0xec,0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x02,0x00,0x00,0x00,0x17,0x40,0x0e,0x02,0x1f,0x21,0x27,0x08,0x00,0x25,0x02,0x20,0x24, 0x01,0x24,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xff,0x1e,0x05,0x3e,0x05,0x9a,0x02,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x46,0xfa,0x5c,0x00,0x1a,0xb9,0x00,0x02,0xff,0x85,0x40,0x0c,0x11,0x10,0x00,0x04,0x25,0x02,0x20,0x12,0x01,0x12,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x60,0xff,0x1e,0x04,0x10,0x05,0xec,0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x1c,0xfa,0x5c,0x00,0x17,0x40,0x0e,0x02,0x20,0x1f,0x1e,0x08,0x00,0x25,0x02,0x20,0x20,0x01,0x20,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x85,0x05,0x3e,0x05,0x9a,0x02,0x26,0x00,0x27, 0x00,0x00,0x01,0x07,0x01,0x9d,0x01,0x4a,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xb8,0x40,0x09,0x12,0x10,0x00,0x04,0x25,0x02,0x13,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0x85,0x04,0x10,0x05,0xec,0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x01,0x9d,0x00,0xdd,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x4b, 0x21,0x1e,0x08,0x00,0x25,0x02,0x21,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x3d,0x05,0x3e,0x05,0x9a,0x02,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x3f,0xf9,0x7b,0x00,0x16,0xb9,0x00,0x02,0xff,0xb8,0x40,0x09,0x14,0x10,0x00,0x04,0x25,0x02,0x15,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x60,0xfe,0x3e,0x04,0x10,0x05,0xec,0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xe0,0xf9,0x7c,0x00,0x13,0x40,0x0b,0x02,0x1e,0x22,0x1e,0x08,0x00,0x25,0x02,0x23,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0xcf,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07, 0x02,0xd1,0x00,0xec,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x11,0x10,0x02,0x03,0x25,0x02,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x72,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0xd2,0x00,0xe4,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x20, 0x21,0x0c,0x12,0x25,0x03,0x02,0x1f,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0xcf,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x02,0xd3,0x00,0xfd,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x11,0x13,0x02,0x0b,0x25,0x02,0x01,0x13,0x05,0x26,0x00,0x2b,0x35,0x35,0x01, 0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x06,0x72,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x02,0xd4,0x00,0xe4,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1f,0x21,0x0c,0x12,0x25,0x03,0x02,0x21,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x3c,0x03,0xb4,0x05,0x9a, 0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xd9,0xf9,0x7a,0x00,0x13,0x40,0x0b,0x01,0x17,0x10,0x0c,0x01,0x00,0x25,0x01,0x11,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0x3d,0x03,0xdd,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xda,0xf9,0x7b,0x00,0x13,0x40,0x0b, 0x02,0x32,0x1e,0x1a,0x0c,0x00,0x25,0x02,0x1f,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x9a,0x03,0xb4,0x05,0x9a,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xd1,0xf9,0xe8,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x16,0x0c,0x01,0x00,0x25,0x01,0x1f,0x14,0x26,0x00,0x2b,0x35,0x01, 0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0x99,0x03,0xdd,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xe1,0xf9,0xe7,0x00,0x13,0x40,0x0b,0x02,0x26,0x24,0x1a,0x0c,0x00,0x25,0x02,0x2d,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x50,0x03,0xb4,0x07,0x1c,0x02,0x26,0x00,0x28,0x00,0x00, 0x00,0x27,0x00,0xdd,0x01,0x8a,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xec,0x01,0x5e,0x00,0x16,0xb9,0x00,0x02,0xff,0xfb,0x40,0x09,0x25,0x1f,0x02,0x03,0x25,0x02,0x22,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xfe,0x50,0x03,0xdd,0x05,0xbe,0x02,0x26,0x00,0x48,0x00,0x00,0x00,0x27,0x00,0xdd,0x01,0x7d,0x00,0x00, 0x01,0x07,0x00,0xda,0x00,0xe5,0x00,0x00,0x00,0x13,0x40,0x0b,0x03,0x06,0x33,0x2d,0x0c,0x12,0x25,0x03,0x30,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0x94,0x06,0xe2,0x02,0x26,0x00,0x29,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x4a,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xf0,0x40,0x09,0x0d, 0x13,0x08,0x09,0x25,0x01,0x0a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x35,0x00,0x00,0x02,0xa0,0x06,0xe2,0x02,0x26,0x00,0x49,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0x03,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x1e,0x1e,0x0a,0x09,0x25,0x01,0x15,0x02,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e, 0xff,0xe8,0x04,0xec,0x06,0x8c,0x02,0x26,0x00,0x2a,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0xda,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x80,0x1b,0x1a,0x05,0x0a,0x25,0x01,0x1b,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x05,0x2f,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x17, 0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x1b,0x27,0x26,0x10,0x18,0x25,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x06,0xe2,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x01,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xf8,0x40,0x09,0x0f,0x15,0x06,0x0b,0x25,0x01,0x0c, 0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x8c,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0xae,0x15,0x15,0x0b,0x0b,0x25,0x01,0x12,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x04,0xf2,0x05,0x9a, 0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x8f,0x00,0x00,0x00,0x17,0x40,0x0e,0x01,0x0d,0x0f,0x15,0x05,0x00,0x25,0x01,0x20,0x12,0x01,0x12,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xe7,0x00,0x00, 0x00,0x1a,0xb9,0x00,0x01,0xff,0xed,0x40,0x0c,0x15,0x1b,0x09,0x00,0x25,0x01,0x20,0x18,0x01,0x18,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x06,0xe4,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x38,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x1b,0x15,0x06,0x0b,0x25, 0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0xe4,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xe3,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x16,0x21,0x21,0x0b,0x0b,0x25,0x02,0x01,0x1e,0x02,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00, 0xff,0xff,0x00,0xa0,0xfe,0x50,0x04,0xf2,0x05,0x9a,0x02,0x26,0x00,0x2b,0x00,0x00,0x00,0x06,0x00,0xdd,0x6d,0x00,0xff,0xff,0x00,0x8c,0xfe,0x50,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x00,0x06,0x00,0xdd,0x59,0x00,0xff,0xff,0x00,0xbc,0xfe,0x8c,0x04,0xf2,0x05,0x9a,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x00,0xda, 0x01,0xa6,0xf9,0xca,0x00,0x13,0x40,0x0b,0x01,0x06,0x12,0x0c,0x05,0x00,0x25,0x01,0x12,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0xfe,0x8c,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x27,0xf9,0xca,0x00,0x13,0x40,0x0b,0x01,0x0f,0x18,0x12,0x09,0x00,0x25,0x01,0x18,0x17, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xcf,0xfe,0x9c,0x02,0x50,0x05,0x9a,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xac,0xf9,0xea,0x00,0x0b,0xb6,0x01,0x00,0x0e,0x04,0x02,0x03,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xb9,0xfe,0x9c,0x02,0x3a,0x05,0xd9,0x02,0x26,0x00,0x4c,0x00,0x00,0x01,0x07, 0x00,0xd8,0xff,0x96,0xf9,0xea,0x00,0x0b,0xb6,0x02,0x00,0x1a,0x10,0x03,0x09,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xf2,0x00,0x00,0x02,0x39,0x07,0xd1,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x02,0xd5,0xff,0x75,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x05,0x17,0x11,0x02,0x03,0x25,0x03,0x02,0x01,0x14,0x05,0x26,0x00, 0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0xff,0xd4,0x00,0x00,0x02,0x1b,0x06,0x74,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x02,0xd6,0xff,0x57,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x00,0x17,0x11,0x02,0x03,0x25,0x03,0x02,0x01,0x14,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00, 0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2,0x07,0x65,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x62,0x01,0x5b,0x00,0x16,0xb9,0x00,0x01,0xff,0x8f,0x40,0x09,0x13,0x12,0x08,0x0f,0x25,0x01,0x13,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x07,0x67,0x02,0x26,0x00,0x4e,0x00,0x00, 0x01,0x07,0x00,0x8e,0x00,0xe2,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x1f,0x0f,0x0f,0x07,0x07,0x25,0x01,0x0f,0x02,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x04,0xa2,0x05,0x9a,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x29,0x00,0x00,0x00,0x1a,0xb9,0x00,0x01,0xff,0xcf,0x40,0x0c,0x14, 0x1a,0x07,0x00,0x25,0x01,0x20,0x17,0x01,0x17,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4e,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xc8,0x00,0x00,0x00,0x1a,0xb9,0x00,0x01,0xff,0xce,0x40,0x0c,0x10,0x16,0x05,0x00,0x25,0x01,0x20,0x13,0x01,0x13,0x17,0x26,0x00, 0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xff,0x1c,0x04,0xa2,0x05,0x9a,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x4f,0xfa,0x5a,0x00,0x1a,0xb9,0x00,0x01,0xff,0xdc,0x40,0x0c,0x13,0x14,0x07,0x00,0x25,0x01,0x20,0x13,0x01,0x13,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xff,0x1c, 0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4e,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x00,0xfa,0x5a,0x00,0x1a,0xb9,0x00,0x01,0xff,0xed,0x40,0x0c,0x0f,0x10,0x05,0x00,0x25,0x01,0x20,0x0f,0x01,0x0f,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07, 0x02,0x45,0x00,0xcd,0x00,0x00,0x00,0x1a,0xb9,0x00,0x01,0xff,0xf2,0x40,0x0c,0x09,0x0f,0x01,0x00,0x25,0x01,0x20,0x0c,0x01,0x0c,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x95,0xfe,0xc6,0x01,0x5b,0x05,0xec,0x02,0x26,0x00,0x4f,0x00,0x00,0x01,0x06,0x02,0x45,0xa3,0x00,0x00,0x17,0x40,0x0e,0x01,0x00,0x07,0x0d, 0x01,0x00,0x25,0x01,0x20,0x0a,0x01,0x0a,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x03,0xa4,0x06,0x8c,0x02,0x26,0x00,0x2f,0x00,0x00,0x00,0x27,0x00,0xd9,0x00,0xcf,0x01,0x5d,0x01,0x07,0x02,0x45,0x00,0xcd,0x00,0x00,0x00,0x2c,0xb9,0x00,0x02,0xff,0xf2,0xb5,0x0d,0x13,0x01,0x00,0x25,0x01, 0xb8,0xff,0xdb,0x40,0x10,0x07,0x06,0x02,0x00,0x25,0x02,0x20,0x10,0x01,0x10,0x14,0x26,0x01,0x07,0x05,0x26,0x00,0x2b,0x35,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x2b,0x35,0xff,0xff,0xff,0xfa,0xfe,0xc6,0x01,0xf6,0x06,0x8c,0x02,0x26,0x00,0x4f,0x00,0x00,0x00,0x27,0x00,0xd9,0xff,0xbc,0x01,0x5d,0x01,0x06,0x02,0x45,0xa2,0x00,0x00,0x29, 0xb9,0x00,0x02,0xff,0xff,0x40,0x17,0x0b,0x11,0x01,0x00,0x3e,0x01,0x00,0x05,0x04,0x01,0x00,0x3e,0x02,0x20,0x0e,0x01,0x0e,0x17,0x26,0x01,0x05,0x02,0x26,0x00,0x2b,0x35,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xff,0x1c,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xfe, 0xfa,0x5a,0x00,0x17,0x40,0x0e,0x01,0x0a,0x08,0x09,0x01,0x00,0x25,0x01,0x20,0x08,0x01,0x08,0x14,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xfc,0xff,0x1c,0x01,0xf8,0x05,0xec,0x02,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x00,0xd9,0xff,0xbe,0xfa,0x5a,0x00,0x17,0x40,0x0e,0x01,0x00,0x06,0x07,0x01,0x00,0x25,0x01, 0x20,0x06,0x01,0x06,0x17,0x26,0x00,0x2b,0x5d,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x3d,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xbb,0xf9,0x7b,0x00,0x13,0x40,0x0b,0x01,0x00,0x0a,0x06,0x01,0x00,0x25,0x01,0x0b,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xdf, 0xfe,0x3e,0x02,0x13,0x05,0xec,0x02,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x00,0xd7,0xff,0x83,0xf9,0x7c,0x00,0x13,0x40,0x0b,0x01,0x00,0x08,0x04,0x01,0x00,0x25,0x01,0x09,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x06,0x72,0x07,0x67,0x02,0x26,0x00,0x30,0x00,0x00,0x00,0x07,0x00,0x8e,0x02,0x48, 0x01,0x5d,0xff,0xff,0x00,0xa6,0x00,0x00,0x06,0x54,0x06,0x0a,0x02,0x26,0x00,0x50,0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x32,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x22,0x20,0x13,0x1f,0x25,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x06,0x72,0x06,0xe2,0x02,0x26,0x00,0x30,0x00,0x00, 0x00,0x07,0x00,0xdb,0x02,0x78,0x01,0x5d,0xff,0xff,0x00,0xa6,0x00,0x00,0x06,0x54,0x05,0x85,0x02,0x26,0x00,0x50,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0xac,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfd,0x40,0x09,0x23,0x29,0x13,0x1f,0x25,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x06,0x72, 0x05,0x9a,0x02,0x26,0x00,0x30,0x00,0x00,0x00,0x07,0x02,0x45,0x01,0xf2,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x06,0x54,0x04,0x18,0x02,0x26,0x00,0x50,0x00,0x00,0x01,0x07,0x02,0x45,0x02,0x27,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x23,0x29,0x12,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x06,0xe3, 0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x27,0x01,0x5e,0x00,0x16,0xb9,0x00,0x01,0xff,0xf7,0x40,0x09,0x17,0x1d,0x0a,0x13,0x25,0x01,0x14,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0x85,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x8a,0x00,0x00,0x00,0x13, 0x40,0x0b,0x01,0x09,0x16,0x1c,0x0a,0x12,0x25,0x01,0x13,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x05,0x40,0x05,0x9a,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0xa0,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0xff,0xf7,0xb4,0x17,0x1d,0x09,0x00,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6, 0xfe,0xc6,0x03,0xf8,0x04,0x18,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x04,0x00,0x00,0x00,0x0b,0xb6,0x01,0x0a,0x16,0x1c,0x0a,0x12,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xff,0x1c,0x05,0x40,0x05,0x9a,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0xbf,0xfa,0x5a,0x00,0x1e,0xb9,0x00,0x01,0xff, 0xfd,0xb6,0x16,0x17,0x0a,0x13,0x25,0x01,0x16,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x16,0x14,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xff,0x1c,0x03,0xf8,0x04,0x18,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x21,0xfa,0x5a,0x00,0x1c,0x40,0x09,0x01,0x0e,0x15,0x16,0x0a,0x12,0x25,0x01,0x15,0xb8, 0xff,0xc0,0xb5,0x09,0x0b,0x36,0x15,0x17,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0x3c,0x05,0x40,0x05,0x9a,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x91,0xf9,0x7a,0x00,0x13,0x40,0x0b,0x01,0x09,0x18,0x14,0x0a,0x13,0x25,0x01,0x19,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0xa6,0xfe,0x3c,0x03,0xf8,0x04,0x18,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xe2,0xf9,0x7a,0x00,0x13,0x40,0x0b,0x01,0x09,0x17,0x13,0x0a,0x12,0x25,0x01,0x18,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x08,0x08,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0xd7, 0x01,0x1e,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x03,0x26,0x1c,0x03,0x09,0x25,0x03,0x02,0x26,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0xae,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x02,0xd8,0x6d,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x26,0x1c,0x03,0x09,0x25, 0x03,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x08,0x02,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0xd9,0x01,0x1b,0x00,0x00,0x00,0x1b,0x40,0x0f,0x04,0x03,0x02,0x00,0x3a,0x30,0x03,0x09,0x25,0x04,0x03,0x02,0x3a,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b, 0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0xa8,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x02,0xda,0x73,0x00,0x00,0x1b,0x40,0x0f,0x04,0x03,0x02,0x04,0x3a,0x30,0x03,0x09,0x25,0x04,0x03,0x02,0x3a,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa, 0x07,0xcf,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0xd1,0x01,0xca,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1d,0x1c,0x03,0x09,0x25,0x03,0x02,0x1d,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x72,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0xd2,0x01,0x1c, 0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1d,0x1f,0x03,0x09,0x25,0x03,0x02,0x1d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0xcf,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x02,0xd3,0x01,0xca,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1c,0x1f,0x03,0x09,0x25, 0x03,0x02,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x72,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x02,0xd4,0x01,0x13,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf7,0x40,0x0a,0x1d,0x1f,0x03,0x09,0x25,0x03,0x02,0x1f,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x29,0x07,0x67,0x02,0x26,0x00,0x33,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xe2,0x01,0x5d,0x00,0x16,0xb9,0x00,0x02,0xff,0xb9,0x40,0x09,0x15,0x13,0x03,0x07,0x25,0x02,0x15,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0x29,0x04,0x54,0x06,0x0a,0x02,0x26,0x00,0x53, 0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x1b,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe7,0x40,0x09,0x20,0x1e,0x04,0x0c,0x25,0x02,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x29,0x06,0xe2,0x02,0x26,0x00,0x33,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x5c,0x01,0x5d,0x00,0x16,0xb9,0x00,0x02,0xff, 0xb8,0x40,0x09,0x16,0x1c,0x03,0x07,0x25,0x02,0x13,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0x29,0x04,0x54,0x05,0x85,0x02,0x26,0x00,0x53,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x9f,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xf0,0x40,0x09,0x21,0x27,0x04,0x0c,0x25,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01, 0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xc0,0x06,0xe2,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x87,0x01,0x5d,0x00,0x08,0xb3,0x02,0x28,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0xbc,0x05,0x85,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0xb6,0x00,0x00,0x00,0x16,0xb9,0x00, 0x01,0xff,0xd3,0x40,0x09,0x14,0x1a,0x08,0x10,0x25,0x01,0x11,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x04,0xc0,0x05,0x9a,0x02,0x26,0x00,0x35,0x00,0x00,0x00,0x07,0x02,0x45,0x01,0x33,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x02,0xbc,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x00,0x06,0x02,0x45, 0x5a,0x00,0xff,0xff,0x00,0xbc,0xfe,0xc6,0x04,0xc0,0x06,0x8c,0x02,0x26,0x00,0x35,0x00,0x00,0x00,0x27,0x00,0xd9,0x01,0x23,0x01,0x5d,0x01,0x07,0x02,0x45,0x01,0x33,0x00,0x00,0x00,0x08,0xb3,0x02,0x29,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0xa6,0xfe,0xc6,0x02,0xbc,0x05,0x2f,0x02,0x26,0x00,0x55,0x00,0x00,0x00,0x26,0x00,0xd9, 0x6c,0x00,0x01,0x06,0x02,0x45,0x5a,0x00,0x00,0x22,0xb9,0x00,0x02,0xff,0xfe,0xb5,0x18,0x1e,0x08,0x10,0x3e,0x01,0xb8,0xff,0xf7,0x40,0x09,0x12,0x11,0x08,0x10,0x3e,0x01,0x12,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x2b,0x35,0xff,0xff,0x00,0xbc,0xff,0x1b,0x04,0xc0,0x05,0x9a,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x00,0xd9, 0x01,0x5c,0xfa,0x59,0x00,0x11,0xb1,0x02,0x2a,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x2a,0x14,0x26,0x00,0x2b,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0xff,0x1d,0x02,0xc7,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0x8d,0xfa,0x5b,0x00,0x1c,0x40,0x09,0x01,0x18,0x13,0x14,0x08,0x10,0x25,0x01,0x13,0xb8,0xff,0xc0, 0xb5,0x09,0x0b,0x36,0x13,0x17,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x06,0xe2,0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x83,0x01,0x5d,0x00,0x08,0xb3,0x01,0x36,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x05,0x85,0x02,0x26,0x00,0x56,0x00,0x00, 0x01,0x07,0x00,0xdb,0x01,0x05,0x00,0x00,0x00,0x08,0xb3,0x01,0x2f,0x11,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x79,0xfe,0xc6,0x03,0xde,0x05,0xb2,0x02,0x26,0x00,0x36,0x00,0x00,0x00,0x07,0x02,0x45,0x00,0xd3,0x00,0x00,0xff,0xff,0x00,0x68,0xfe,0xc6,0x03,0x0f,0x04,0x18,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x06,0x02,0x45,0x72,0x00, 0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x07,0x6a,0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x02,0xdb,0x01,0x5a,0x00,0x00,0x00,0x0a,0xb4,0x02,0x01,0x42,0x05,0x26,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x06,0x0e,0x02,0x26,0x00,0x56,0x00,0x00,0x01,0x07,0x02,0xdc,0x00,0xdb,0x00,0x00,0x00,0x0a,0xb4,0x02, 0x01,0x3e,0x11,0x26,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde,0x07,0xd7,0x02,0x26,0x00,0x36,0x00,0x00,0x01,0x07,0x02,0xdd,0x01,0x16,0x00,0x00,0x00,0x0a,0xb4,0x02,0x01,0x44,0x05,0x26,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x68,0xff,0xe8,0x03,0x0f,0x06,0x7b,0x02,0x26,0x00,0x56,0x00,0x00,0x01,0x07,0x02,0xde, 0x00,0x8c,0x00,0x00,0x00,0x0a,0xb4,0x02,0x01,0x3d,0x11,0x26,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x79,0xfe,0xc6,0x03,0xde,0x06,0xe2,0x02,0x26,0x00,0x36,0x00,0x00,0x00,0x27,0x00,0xdb,0x01,0x93,0x01,0x5d,0x01,0x07,0x02,0x45,0x01,0x0b,0x00,0x00,0x00,0x08,0xb3,0x01,0x36,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x68,0xfe,0xc6, 0x03,0x0f,0x05,0x85,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x27,0x02,0x45,0x00,0x82,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0xff,0x00,0x00,0x00,0x08,0xb3,0x01,0x3b,0x14,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x29,0x00,0x00,0x04,0x0c,0x06,0xe2,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x4d,0x01,0x5d,0x00,0x13,0x40,0x0b, 0x01,0x00,0x0b,0x11,0x06,0x07,0x25,0x01,0x08,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x2b,0xff,0xea,0x02,0x81,0x06,0x55,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0x5e,0x00,0xd0,0x00,0x19,0xb9,0x00,0x01,0xff,0xd6,0xb6,0x18,0x1e,0x07,0x14,0x25,0x01,0x15,0xb9,0x01,0x2d,0x00,0x0a,0x00,0x10, 0xfe,0x34,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x29,0xfe,0xc6,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xc4,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x0b,0x11,0x06,0x07,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x2b,0xfe,0xc6,0x02,0x81,0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x06,0x02,0x45, 0x13,0x00,0x00,0x0b,0xb6,0x01,0x12,0x18,0x1e,0x07,0x14,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x29,0xff,0x1c,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xe0,0xfa,0x5a,0x00,0x1c,0x40,0x09,0x01,0x00,0x0a,0x0b,0x06,0x07,0x25,0x01,0x0a,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x0a,0x14,0x26,0x00, 0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x2b,0xff,0x1b,0x02,0x95,0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0x5b,0xfa,0x59,0x00,0x1c,0x40,0x09,0x01,0x41,0x17,0x18,0x07,0x14,0x25,0x01,0x17,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x17,0x17,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x29, 0xfe,0x3d,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xa7,0xf9,0x7b,0x00,0x13,0x40,0x0b,0x01,0x03,0x0c,0x08,0x06,0x07,0x25,0x01,0x0d,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x2b,0xfe,0x3e,0x02,0x86,0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x00,0xd7,0xff,0xf6, 0xf9,0x7c,0x00,0x13,0x40,0x0b,0x01,0x16,0x19,0x15,0x07,0x14,0x25,0x01,0x1a,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xfe,0xc3,0x04,0xd5,0x05,0x9a,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x17,0xfa,0x01,0x00,0x22,0xb1,0x02,0x01,0xb8,0xff,0xf8,0xb7,0x1d,0x17,0x05,0x0d,0x25,0x02,0x01, 0x20,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x20,0x14,0x26,0x00,0x2b,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x90,0xfe,0xc4,0x03,0xe2,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x7f,0xfa,0x02,0x00,0x22,0xb1,0x02,0x01,0xb8,0xff,0xe6,0xb7,0x21,0x1b,0x08,0x11,0x25,0x02,0x01,0x24,0xb8,0xff,0xc0, 0xb5,0x09,0x0b,0x36,0x24,0x17,0x26,0x00,0x2b,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xaa,0xfe,0x9e,0x04,0xd5,0x05,0x9a,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x4c,0xf9,0xec,0x00,0x16,0xb9,0x00,0x01,0xff,0xf0,0x40,0x09,0x18,0x0e,0x05,0x0d,0x25,0x01,0x21,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x90,0xfe,0x9e,0x03,0xe2,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xd3,0xf9,0xec,0x00,0x16,0xb9,0x00,0x01,0xff,0xfd,0x40,0x09,0x1c,0x12,0x08,0x11,0x25,0x01,0x25,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xfe,0x3d,0x04,0xd5,0x05,0x9a,0x02,0x26,0x00,0x38,0x00,0x00, 0x01,0x07,0x00,0xd7,0x01,0x42,0xf9,0x7b,0x00,0x16,0xb9,0x00,0x01,0xff,0xf9,0x40,0x09,0x12,0x0e,0x05,0x0d,0x25,0x01,0x13,0x14,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x90,0xfe,0x3d,0x03,0xe2,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xbb,0xf9,0x7b,0x00,0x16,0xb9,0x00,0x01,0xff,0xf8,0x40, 0x09,0x16,0x12,0x08,0x11,0x25,0x01,0x17,0x17,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x08,0x08,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x02,0xd7,0x00,0xdc,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x06,0x1c,0x12,0x05,0x0d,0x25,0x02,0x01,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35, 0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0xae,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x02,0xd8,0x59,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x09,0x20,0x16,0x08,0x11,0x25,0x02,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x9e,0x02,0x26,0x00,0x38, 0x00,0x00,0x01,0x07,0x02,0xdf,0x01,0x8c,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x04,0x1d,0x17,0x05,0x0d,0x25,0x03,0x02,0x01,0x27,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x42,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x02,0xe0,0x00,0xff,0x00,0x00, 0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xfd,0x40,0x0b,0x21,0x1b,0x08,0x11,0x25,0x03,0x02,0x01,0x2b,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0xe6,0x07,0x0f,0x02,0x26,0x00,0x39,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x1d,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x04,0x16,0x0c, 0x03,0x00,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0x00,0x00,0x03,0xcb,0x05,0xb2,0x02,0x26,0x00,0x59,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0x8c,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x03,0x16,0x0c,0x03,0x00,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12, 0xfe,0xc6,0x04,0xe6,0x05,0x9a,0x02,0x26,0x00,0x39,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x29,0x00,0x00,0x00,0x0b,0xb6,0x01,0x00,0x0f,0x15,0x03,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0xc6,0x03,0xcb,0x04,0x00,0x02,0x26,0x00,0x59,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0x92,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0xff, 0xfb,0xb4,0x0f,0x15,0x03,0x00,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x60,0x06,0xe2,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0xfd,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x0e,0x1f,0x25,0x0b,0x00,0x25,0x01,0x1c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0, 0x05,0x85,0x02,0x26,0x00,0x5a,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x24,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x0e,0x1f,0x25,0x0b,0x00,0x25,0x01,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x1a,0xfe,0xc6,0x07,0x60,0x05,0x9a,0x02,0x26,0x00,0x3a,0x00,0x00,0x01,0x07,0x02,0x45,0x02,0x75,0x00,0x00,0x00,0x0b, 0xb6,0x01,0x0d,0x1f,0x25,0x0b,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x18,0xfe,0xc6,0x05,0xb0,0x04,0x00,0x02,0x26,0x00,0x5a,0x00,0x00,0x01,0x07,0x02,0x45,0x01,0x95,0x00,0x00,0x00,0x0b,0xb6,0x01,0x06,0x1f,0x25,0x0b,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x04,0x9a,0x06,0xe2,0x02,0x26,0x00,0x3b, 0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x93,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x07,0x19,0x1f,0x09,0x00,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x03,0x92,0x05,0x85,0x02,0x26,0x00,0x5b,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x0e,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x06,0x17,0x1d, 0x0b,0x00,0x25,0x01,0x14,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x04,0x9a,0x06,0xe4,0x02,0x26,0x00,0x3b,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xcd,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x13,0x25,0x1f,0x09,0x00,0x25,0x02,0x01,0x22,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00, 0xff,0xff,0x00,0x1a,0x00,0x00,0x03,0x92,0x05,0x87,0x02,0x26,0x00,0x5b,0x00,0x00,0x01,0x06,0x00,0x8f,0x43,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x0d,0x23,0x1d,0x0b,0x00,0x25,0x02,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x06,0xe2,0x02,0x26,0x00,0x3c,0x00,0x00, 0x01,0x07,0x00,0xdb,0x01,0x67,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x11,0x17,0x05,0x00,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0x85,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x1f,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40, 0x09,0x18,0x1e,0x0c,0x00,0x25,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x07,0x6b,0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xdb,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x0f,0x0e,0x0a,0x05,0x09,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x21,0x00,0x00,0x03,0x70,0x06,0x0e,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x06,0x00,0xd7,0x6f,0x00,0x00,0x13,0x40,0x0b,0x01,0x1d,0x0e,0x0a,0x05,0x09,0x25,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x21,0xfe,0xc6,0x04,0x64,0x05,0x9a,0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0xfd, 0x00,0x00,0x00,0x0b,0xb6,0x01,0x10,0x0d,0x13,0x05,0x09,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x21,0xfe,0xc6,0x03,0x70,0x04,0x00,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x02,0x45,0x00,0x87,0x00,0x00,0x00,0x0b,0xb6,0x01,0x14,0x0d,0x13,0x05,0x09,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x21,0xff,0x1c,0x04,0x64,0x05,0x9a, 0x02,0x26,0x00,0x3d,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x0c,0xfa,0x5a,0x00,0x1c,0x40,0x09,0x01,0x06,0x0c,0x0d,0x05,0x09,0x25,0x01,0x0c,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x0c,0x14,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x21,0xff,0x1b,0x03,0x70,0x04,0x00,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x00,0xd9, 0x00,0x9c,0xfa,0x59,0x00,0x1c,0x40,0x09,0x01,0x10,0x0c,0x0d,0x05,0x09,0x25,0x01,0x0c,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x0c,0x17,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xff,0x1c,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x1c,0xfa,0x5a,0x00,0x1c,0x40,0x09,0x01,0x09, 0x14,0x15,0x0a,0x11,0x25,0x01,0x14,0xb8,0xff,0xc0,0xb5,0x09,0x0b,0x36,0x14,0x17,0x26,0x00,0x2b,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x2b,0xff,0xea,0x02,0x81,0x06,0x57,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0xb8,0x00,0xd0,0x00,0x1b,0x40,0x0b,0x02,0x01,0x00,0x24,0x1e,0x07,0x14,0x25,0x02,0x01,0x15,0xb9, 0x01,0x2d,0x00,0x0a,0x00,0x10,0xfe,0x34,0x34,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x06,0x1c,0x02,0x26,0x00,0x5a,0x00,0x00,0x01,0x07,0x00,0xdc,0x01,0xcc,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x08,0x1f,0x25,0x0b,0x00,0x25,0x02,0x01,0x1c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00, 0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x1c,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xdc,0x00,0xcb,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfa,0x40,0x0a,0x18,0x1e,0x0c,0x00,0x25,0x02,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x06,0x1f,0x02,0x26, 0x00,0x44,0x00,0x00,0x01,0x07,0x06,0x84,0x00,0xc9,0xff,0xf0,0x00,0x13,0x40,0x0b,0x02,0x30,0x26,0x29,0x08,0x14,0x25,0x02,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x4e,0x00,0x00,0x02,0x62,0x06,0xe2,0x02,0x26,0x01,0x84,0x00,0x00,0x01,0x07,0x00,0xdb,0xff,0xe2,0x01,0x5d,0x00,0x16,0xb9,0x00,0x01,0xff, 0x2c,0x40,0x09,0x10,0x16,0x07,0x0c,0x25,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x23,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x29,0x29,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x2d,0x33,0x0a,0x13,0x25,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x23,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x61,0xe8,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xb3,0x40,0x09,0x2b,0x31,0x0a,0x13,0x25,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x36, 0x0c,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xde,0x40,0x0a,0x2d,0x34,0x0a,0x13,0x25,0x03,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x43,0xf2,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xc3,0x40,0x0a,0x2a,0x34, 0x0a,0x13,0x25,0x03,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x37,0x37,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x09,0x2d,0x34,0x0a,0x13,0x25,0x03,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00, 0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x44,0x27,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf9,0x40,0x0a,0x2a,0x34,0x0a,0x13,0x25,0x03,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x83,0x02,0x26,0x01,0x2f, 0x00,0x00,0x01,0x06,0x04,0x38,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xd1,0x40,0x0a,0x2d,0x27,0x0a,0x13,0x25,0x03,0x02,0x33,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x83,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x45,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8, 0xff,0xd1,0x40,0x0a,0x2d,0x27,0x0a,0x13,0x25,0x03,0x02,0x36,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0xa0,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x27,0xfe,0x3f,0xff,0x7d,0x00,0x16,0xb4,0x02,0x19,0x04,0x19,0x02,0xb8,0xfe,0x04,0xb4,0x11,0x1c,0x05,0x00,0x25,0x01, 0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0xa0,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x61,0xfe,0x44,0xff,0x7d,0x00,0x16,0xb4,0x02,0x17,0x04,0x17,0x02,0xb8,0xfe,0x08,0xb4,0x14,0x10,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x05,0xd7,0x05,0x9e, 0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x72,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x19,0x04,0x19,0x03,0x02,0xb8,0xfe,0xd7,0xb4,0x1d,0x1d,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x05,0xd7,0x05,0x9e,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07, 0x04,0x43,0xfe,0x7a,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x15,0x04,0x15,0x03,0x02,0xb8,0xfe,0xe5,0xb4,0x1d,0x1d,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x05,0xd7,0x05,0x9e,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7a,0xff,0x98,0x00,0x1a,0xb6,0x03, 0x02,0x19,0x04,0x19,0x03,0x02,0xb8,0xfe,0xe7,0xb4,0x1d,0x1d,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x05,0xd7,0x05,0x9e,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x86,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x15,0x04,0x15,0x03,0x02,0xb8,0xff,0x00,0xb4, 0x1d,0x1d,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x05,0xd7,0x05,0xb2,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x89,0xff,0x2f,0x00,0x1a,0xb6,0x03,0x02,0x19,0x04,0x19,0x03,0x02,0xb8,0xff,0x05,0xb4,0x10,0x10,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00, 0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x05,0xd7,0x05,0xb2,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x89,0xff,0x2f,0x00,0x1a,0xb6,0x03,0x02,0x19,0x04,0x19,0x03,0x02,0xb8,0xfd,0x88,0xb4,0x16,0x10,0x05,0x00,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x52,0xff,0xe7, 0x03,0x3b,0x06,0x23,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x27,0xb2,0x00,0x00,0x13,0x40,0x0b,0x01,0x4d,0x2c,0x32,0x0c,0x11,0x25,0x01,0x26,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x23,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x61,0x82,0x00,0x00,0x13,0x40,0x0b, 0x01,0x11,0x2a,0x30,0x0c,0x11,0x25,0x01,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x06,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x36,0x8b,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x21,0x2c,0x33,0x0c,0x11,0x25,0x02,0x01,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35, 0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x06,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x07,0x04,0x43,0xff,0x71,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x06,0x29,0x33,0x0c,0x11,0x25,0x02,0x01,0x27,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x06,0x02,0x26, 0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x37,0xc4,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x5a,0x2c,0x33,0x0c,0x11,0x25,0x02,0x01,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x06,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x44,0xa8,0x00,0x00,0x17,0x40,0x0d,0x02,0x01, 0x3e,0x29,0x33,0x0c,0x11,0x25,0x02,0x01,0x27,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xbd,0x00,0x00,0x04,0x35,0x05,0xa0,0x00,0x27,0x00,0x28,0x00,0x81,0x00,0x00,0x01,0x07,0x04,0x27,0xfd,0xd9,0xff,0x7d,0x00,0x16,0xb4,0x01,0x15,0x04,0x15,0x01,0xb8,0xff,0x6b,0xb4,0x18,0x18,0x02,0x02,0x25,0x01, 0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x04,0x35,0x05,0xa0,0x00,0x27,0x00,0x28,0x00,0x81,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x01,0x13,0x04,0x13,0x01,0xb8,0xfd,0x7b,0xb4,0x10,0x0c,0x02,0x0b,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x05,0x5a, 0x05,0x9e,0x00,0x27,0x00,0x28,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x72,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xff,0x76,0xb4,0x19,0x19,0x02,0x02,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xc0,0x00,0x00,0x05,0x5a,0x05,0x9e,0x00,0x27,0x00,0x28,0x01,0xa6,0x00,0x00, 0x01,0x07,0x04,0x43,0xfe,0x7c,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x11,0x04,0x11,0x02,0x01,0xb8,0xff,0x86,0xb4,0x19,0x19,0x02,0x02,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x05,0x5a,0x05,0x9e,0x00,0x27,0x00,0x28,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7b,0xff,0x98,0x00,0x1a, 0xb6,0x02,0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xfc,0xf5,0xb4,0x0d,0x19,0x02,0x0b,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbf,0x00,0x00,0x05,0x5a,0x05,0x9e,0x00,0x27,0x00,0x28,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x87,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x11,0x04,0x11,0x02,0x01,0xb8,0xff, 0xa0,0xb4,0x19,0x19,0x02,0x02,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x23,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x27,0x1f,0x00,0x00,0x13,0x40,0x0b,0x01,0x3b,0x16,0x21,0x0c,0x14,0x25,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x82, 0xfe,0x6c,0x03,0xf8,0x06,0x23,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x61,0xdc,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xf7,0x40,0x09,0x19,0x15,0x0c,0x14,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x36,0xdd,0x00, 0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf8,0x40,0x0a,0x16,0x22,0x0c,0x14,0x25,0x02,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x43,0xca,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xe5,0x40,0x0a,0x18,0x22,0x0c,0x14, 0x25,0x02,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x37,0x29,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x44,0x16,0x22,0x0c,0x14,0x25,0x02,0x01,0x15,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff, 0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x44,0x08,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x24,0x18,0x22,0x0c,0x14,0x25,0x02,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x83,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06, 0x04,0x38,0xdf,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfa,0x40,0x0a,0x1b,0x15,0x0c,0x14,0x25,0x02,0x01,0x21,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x83,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x45,0xdf,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xfa,0x40,0x0a, 0x1b,0x15,0x0c,0x14,0x25,0x02,0x01,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x05,0x73,0x05,0xa0,0x00,0x27,0x00,0x2b,0x00,0x81,0x00,0x00,0x01,0x07,0x04,0x27,0xfd,0xd9,0xff,0x7d,0x00,0x16,0xb4,0x01,0x15,0x04,0x15,0x01,0xb8,0xff,0x6b,0xb4,0x18,0x18,0x06,0x06,0x25,0x01,0x2b,0x35, 0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x05,0x73,0x05,0xa0,0x00,0x27,0x00,0x2b,0x00,0x81,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x01,0x13,0x04,0x13,0x01,0xb8,0xff,0x6e,0xb4,0x0c,0x0c,0x06,0x06,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x06,0x98,0x05,0x9e, 0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x72,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xff,0x76,0xb4,0x19,0x19,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xc0,0x00,0x00,0x06,0x98,0x05,0x9e,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07, 0x04,0x43,0xfe,0x7c,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x11,0x04,0x11,0x02,0x01,0xb8,0xff,0x86,0xb4,0x19,0x19,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x06,0x98,0x05,0x9e,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7b,0xff,0x98,0x00,0x1a,0xb6,0x02, 0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xfc,0x56,0xb4,0x0d,0x19,0x06,0x0b,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbf,0x00,0x00,0x06,0x98,0x05,0x9e,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x87,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x11,0x04,0x11,0x02,0x01,0xb8,0xff,0xa0,0xb4, 0x19,0x19,0x06,0x06,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x06,0x98,0x05,0xb2,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x89,0xff,0x2f,0x00,0x1a,0xb6,0x02,0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xfc,0x64,0xb4,0x12,0x0c,0x06,0x0b,0x25,0x01,0x2b,0x35,0x35,0x00, 0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x06,0x98,0x05,0xb2,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x89,0xff,0x2f,0x00,0x1a,0xb6,0x02,0x01,0x15,0x04,0x15,0x02,0x01,0xb8,0xfc,0x64,0xb4,0x12,0x0c,0x06,0x0b,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x94,0xff,0xf4, 0x02,0x08,0x06,0x23,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x27,0xfe,0xb0,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xb2,0x40,0x09,0x0d,0x18,0x05,0x0b,0x25,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x6e,0xff,0xf4,0x02,0x08,0x06,0x23,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x61,0xfe,0x8c, 0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0x8d,0x40,0x09,0x10,0x0c,0x05,0x0b,0x25,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xdd,0xff,0xf4,0x02,0x08,0x06,0x06,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x93,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x94,0x40,0x0a,0x0d,0x19,0x05,0x0b, 0x25,0x02,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xb3,0xff,0xf4,0x02,0x08,0x06,0x06,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x6f,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x70,0x40,0x0a,0x0f,0x19,0x05,0x0b,0x25,0x02,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0x00,0x1b,0xff,0xf4,0x02,0x47,0x06,0x06,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0xd9,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xda,0x40,0x0a,0x0d,0x19,0x05,0x0b,0x25,0x02,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xea,0xff,0xf4,0x02,0x2d,0x06,0x06, 0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0xb2,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xb4,0x40,0x0a,0x0f,0x19,0x05,0x0b,0x25,0x02,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xc0,0xff,0xf4,0x02,0x0a,0x06,0x83,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x8d, 0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x8e,0x40,0x0a,0x12,0x0c,0x05,0x0b,0x25,0x02,0x01,0x18,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xc0,0xff,0xf4,0x02,0x0a,0x06,0x83,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x8d,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x8e,0x40,0x0a, 0x12,0x0c,0x05,0x0b,0x25,0x02,0x01,0x1b,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x02,0x4a,0x05,0xa0,0x00,0x27,0x00,0x2c,0x00,0xe6,0x00,0x00,0x01,0x07,0x04,0x27,0xfd,0xd9,0xff,0x7d,0x00,0x07,0xb2,0x01,0x0d,0x03,0x00,0x3f,0x35,0x00,0xff,0xff,0xff,0xbe,0x00,0x00,0x02,0x48,0x05,0xa0, 0x00,0x27,0x00,0x2c,0x00,0xe4,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x07,0xb2,0x01,0x0b,0x04,0x00,0x3f,0x35,0x00,0xff,0xff,0xff,0xbd,0x00,0x00,0x03,0x3a,0x05,0xa0,0x00,0x27,0x00,0x2c,0x01,0xd6,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x73,0xff,0x9a,0x00,0x09,0xb3,0x02,0x01,0x14,0x03,0x00,0x3f,0x35,0x35,0x00, 0xff,0xff,0xff,0xc0,0x00,0x00,0x03,0x3a,0x05,0xa0,0x00,0x27,0x00,0x2c,0x01,0xd6,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x7c,0xff,0x9a,0x00,0x09,0xb3,0x02,0x01,0x14,0x03,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0x00,0x00,0x03,0x6e,0x05,0xa0,0x00,0x27,0x00,0x2c,0x02,0x0a,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7a,0xff,0x9a, 0x00,0x09,0xb3,0x02,0x01,0x14,0x03,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbf,0x00,0x00,0x03,0x77,0x05,0xa0,0x00,0x27,0x00,0x2c,0x02,0x13,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x87,0xff,0x9a,0x00,0x09,0xb3,0x02,0x01,0x14,0x03,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbd,0x00,0x00,0x03,0x6e,0x05,0xb2,0x00,0x27,0x00,0x2c, 0x02,0x0a,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x8a,0xff,0x2f,0x00,0x09,0xb3,0x02,0x01,0x0d,0x04,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbd,0x00,0x00,0x03,0x6e,0x05,0xb2,0x00,0x27,0x00,0x2c,0x02,0x0a,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x8a,0xff,0x2f,0x00,0x09,0xb3,0x02,0x01,0x0d,0x04,0x00,0x3f,0x35,0x35,0x00,0xff,0xff, 0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x23,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x27,0x0a,0x00,0x00,0x13,0x40,0x0b,0x02,0x0b,0x19,0x24,0x03,0x09,0x25,0x02,0x18,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x23,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x61,0xd4,0x00, 0x00,0x16,0xb9,0x00,0x02,0xff,0xd4,0x40,0x09,0x1c,0x18,0x03,0x09,0x25,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x06,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x36,0xe9,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xe9,0x40,0x0a,0x19,0x25,0x03,0x09,0x25,0x03,0x02,0x18, 0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x06,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x43,0xb9,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xb9,0x40,0x0a,0x1b,0x25,0x03,0x09,0x25,0x03,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60, 0xff,0xe8,0x04,0x50,0x06,0x06,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x37,0x21,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x21,0x19,0x25,0x03,0x09,0x25,0x03,0x02,0x18,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x06,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x44, 0xfc,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xfd,0x40,0x0a,0x1b,0x25,0x03,0x09,0x25,0x03,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xbd,0xff,0xe8,0x06,0x10,0x05,0xb2,0x00,0x26,0x00,0x32,0x66,0x00,0x01,0x07,0x04,0x27,0xfd,0xd9,0xff,0x7d,0x00,0x16,0xb4,0x02,0x21,0x04,0x21,0x02,0xb8,0xfc, 0xc8,0xb4,0x19,0x24,0x03,0x09,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbe,0xff,0xe8,0x06,0x10,0x05,0xb2,0x00,0x26,0x00,0x32,0x66,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x02,0x1f,0x04,0x1f,0x02,0xb8,0xfc,0xca,0xb4,0x1c,0x18,0x03,0x09,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff, 0xff,0xbc,0xff,0xe8,0x07,0x42,0x05,0xb2,0x00,0x27,0x00,0x32,0x01,0x98,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x72,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x21,0x04,0x21,0x03,0x02,0xb8,0xff,0xe2,0xb4,0x25,0x25,0x03,0x03,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbe,0xff,0xe8,0x07,0x42,0x05,0xb2,0x00,0x27, 0x00,0x32,0x01,0x98,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x7a,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x1d,0x04,0x1d,0x03,0x02,0xb8,0xff,0xf0,0xb4,0x25,0x25,0x03,0x03,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0xff,0xe8,0x07,0x42,0x05,0xb2,0x00,0x27,0x00,0x32,0x01,0x98,0x00,0x00,0x01,0x07,0x04,0x37, 0xfe,0x7a,0xff,0x98,0x00,0x1a,0xb6,0x03,0x02,0x21,0x04,0x21,0x03,0x02,0xb8,0xfc,0x36,0xb4,0x19,0x25,0x03,0x09,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbe,0xff,0xe8,0x07,0x42,0x05,0xb2,0x00,0x27,0x00,0x32,0x01,0x98,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x86,0xff,0x98,0x00,0x18,0x40,0x0d,0x03,0x02, 0x1d,0x04,0x1d,0x03,0x02,0x0b,0x25,0x25,0x03,0x03,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x23,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x27,0xed,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xed,0x40,0x09,0x23,0x29,0x00,0x16,0x25,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01, 0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x23,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x61,0x90,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0x84,0x40,0x09,0x21,0x27,0x00,0x16,0x25,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x06,0x02,0x26,0x01,0xd2,0x00,0x00, 0x01,0x06,0x04,0x36,0xae,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xa9,0x40,0x0a,0x23,0x2a,0x00,0x16,0x25,0x02,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x06,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x43,0xa5,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x9f, 0x40,0x0a,0x20,0x2a,0x00,0x16,0x25,0x02,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x06,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x37,0xee,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xe9,0x40,0x0a,0x23,0x2a,0x00,0x16,0x25,0x02,0x01,0x1d,0x11,0x26,0x00,0x2b, 0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x06,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x44,0xcf,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xca,0x40,0x0a,0x20,0x2a,0x00,0x16,0x25,0x02,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e, 0x06,0x83,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x38,0xb0,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xaa,0x40,0x0a,0x23,0x1d,0x00,0x16,0x25,0x02,0x01,0x29,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x83,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x45,0xaa,0x00, 0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xa4,0x40,0x0a,0x23,0x1d,0x00,0x16,0x25,0x02,0x01,0x2c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x05,0x48,0x05,0xa0,0x00,0x27,0x00,0x3c,0x00,0xe8,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x01,0x15,0x04,0x15,0x01,0xb8,0xfd, 0x13,0xb4,0x12,0x0e,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xc0,0x00,0x00,0x06,0x7d,0x05,0x9e,0x00,0x27,0x00,0x3c,0x02,0x1d,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x7c,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x13,0x04,0x13,0x02,0x01,0xb8,0xff,0xb9,0xb4,0x1b,0x1b,0x05,0x05,0x25,0x01,0x2b,0x35,0x35,0x00, 0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbf,0x00,0x00,0x06,0x7d,0x05,0x9e,0x00,0x27,0x00,0x3c,0x02,0x1d,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x87,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x13,0x04,0x13,0x02,0x01,0xb8,0xff,0xd3,0xb4,0x1b,0x1b,0x05,0x05,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00, 0x06,0x7d,0x05,0xb2,0x00,0x27,0x00,0x3c,0x02,0x1d,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x89,0xff,0x2f,0x00,0x1a,0xb6,0x02,0x01,0x17,0x04,0x17,0x02,0x01,0xb8,0xfc,0x8b,0xb4,0x14,0x0e,0x05,0x00,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x23,0x02,0x26,0x01,0xd5,0x00,0x01, 0x01,0x07,0x04,0x27,0x00,0xf7,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x1a,0x28,0x2e,0x06,0x1d,0x25,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x23,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x61,0x00,0xca,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xe1,0x40,0x09,0x26, 0x2c,0x06,0x1d,0x25,0x01,0x23,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x36,0x00,0xcc,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xea,0x40,0x0a,0x28,0x2f,0x06,0x1d,0x25,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x43,0x00,0xb3,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xd0,0x40,0x0a,0x25,0x2f,0x06,0x1d,0x25,0x02,0x01,0x23,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x06, 0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x37,0x01,0x27,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x45,0x28,0x2f,0x06,0x1d,0x25,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x44,0x00,0xf9,0x00,0x00, 0x00,0x17,0x40,0x0d,0x02,0x01,0x17,0x25,0x2f,0x06,0x1d,0x25,0x02,0x01,0x23,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x83,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x38,0x00,0xd5,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf2,0x40,0x0a,0x28,0x22,0x06,0x1d, 0x25,0x02,0x01,0x2e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x83,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x45,0x00,0xd5,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf2,0x40,0x0a,0x28,0x22,0x06,0x1d,0x25,0x02,0x01,0x31,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x06,0x3c,0x05,0xb2,0x00,0x27,0x00,0x9f,0x00,0x93,0x00,0x00,0x01,0x07,0x04,0x27,0xfd,0xd9,0xff,0x7d,0x00,0x16,0xb4,0x01,0x25,0x04,0x25,0x01,0xb8,0xff,0xb1,0xb4,0x28,0x28,0x12,0x12,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x06,0x3c,0x05,0xb2,0x00,0x27, 0x00,0x9f,0x00,0x93,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x01,0x23,0x04,0x23,0x01,0xb8,0xff,0xb4,0xb4,0x1c,0x1c,0x12,0x12,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x72,0xff,0x98, 0x00,0x1a,0xb6,0x02,0x01,0x25,0x04,0x25,0x02,0x01,0xb8,0xff,0xd7,0xb4,0x29,0x29,0x12,0x12,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xc0,0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x7c,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x21,0x04,0x21,0x02,0x01, 0xb8,0xff,0xe7,0xb4,0x29,0x29,0x12,0x12,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbd,0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7b,0xff,0x98,0x00,0x1a,0xb6,0x02,0x01,0x25,0x04,0x25,0x02,0x01,0xb8,0xff,0xe8,0xb4,0x29,0x29,0x12,0x12,0x25,0x01, 0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbf,0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x87,0xff,0x98,0x00,0x18,0x40,0x0d,0x02,0x01,0x21,0x04,0x21,0x02,0x01,0x00,0x29,0x29,0x12,0x12,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc, 0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x89,0xff,0x2f,0x00,0x18,0x40,0x0d,0x02,0x01,0x25,0x04,0x25,0x02,0x01,0x05,0x1c,0x1c,0x12,0x12,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0xff,0xbc,0x00,0x00,0x07,0x46,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9d, 0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x89,0xff,0x2f,0x00,0x18,0x40,0x0d,0x02,0x01,0x25,0x04,0x25,0x02,0x01,0x05,0x1c,0x1c,0x12,0x12,0x25,0x01,0x2b,0x35,0x35,0x00,0x11,0x3f,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x00,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x55,0xbe,0x00,0x00,0x16,0xb9,0x00,0x02,0xff, 0x8f,0x40,0x09,0x29,0x27,0x0a,0x13,0x25,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x06,0x00,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x60,0x35,0x00,0x00,0x13,0x40,0x0b,0x02,0x06,0x29,0x27,0x0a,0x13,0x25,0x02,0x29,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x00,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x07,0x04,0x55,0xff,0x6c,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x28,0x26,0x0c,0x11,0x25,0x01,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x06,0x00,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x06,0x04,0x60, 0xda,0x00,0x00,0x13,0x40,0x0b,0x01,0x6f,0x28,0x26,0x0c,0x11,0x25,0x01,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x00,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x55,0xbe,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xd9,0x40,0x09,0x17,0x15,0x0c,0x14,0x25,0x01,0x16,0x11,0x26, 0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x82,0xfe,0x6c,0x03,0xf8,0x06,0x00,0x02,0x26,0x01,0xc7,0x00,0x00,0x01,0x06,0x04,0x60,0x40,0x00,0x00,0x13,0x40,0x0b,0x01,0x5b,0x17,0x15,0x0c,0x14,0x25,0x01,0x17,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x34,0xff,0xf4,0x02,0x08,0x06,0x00,0x02,0x26,0x01,0xc9, 0x00,0x00,0x01,0x07,0x04,0x55,0xfe,0x63,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0x64,0x40,0x09,0x0e,0x0c,0x05,0x0b,0x25,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0xff,0xf4,0x02,0x08,0x06,0x00,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x60,0xfe,0xdd,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff, 0xde,0x40,0x09,0x0e,0x0c,0x05,0x0b,0x25,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x00,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x55,0xd2,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xd2,0x40,0x09,0x1a,0x18,0x03,0x09,0x25,0x02,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35, 0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x00,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x60,0x24,0x00,0x00,0x13,0x40,0x0b,0x02,0x24,0x1a,0x18,0x03,0x09,0x25,0x02,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x00,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x55, 0x8c,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0x86,0x40,0x09,0x1f,0x1d,0x00,0x16,0x25,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x00,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x60,0x02,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xfc,0x40,0x09,0x1f,0x1d,0x00,0x16,0x25,0x01,0x1f, 0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x06,0x00,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x55,0x00,0xaf,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xcc,0x40,0x09,0x24,0x22,0x06,0x1d,0x25,0x01,0x23,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00, 0x06,0x00,0x02,0x26,0x01,0xd5,0x00,0x01,0x01,0x07,0x04,0x60,0x01,0x1f,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x3c,0x24,0x22,0x06,0x1d,0x25,0x01,0x24,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x23,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x27,0x29,0x00,0x01,0x06,0x04,0x28, 0x5c,0x00,0x00,0x1b,0x40,0x12,0x02,0x27,0x11,0x26,0x03,0x25,0x3c,0x36,0x0a,0x00,0x3e,0x02,0x00,0x2d,0x33,0x0a,0x13,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x23,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x61,0xe9,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x1e,0x40,0x0c, 0x02,0x28,0x11,0x26,0x03,0x25,0x3b,0x35,0x0a,0x00,0x3e,0x02,0xb8,0xff,0xb4,0xb4,0x2b,0x31,0x0a,0x13,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x36,0x0c,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x22,0x40,0x0e,0x03,0x02,0x27,0x11, 0x26,0x04,0x25,0x3e,0x38,0x0a,0x00,0x3e,0x03,0x02,0xb8,0xff,0xde,0xb4,0x2d,0x34,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x43,0xf4,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x22,0x40,0x0e,0x03,0x02,0x28,0x11, 0x26,0x04,0x25,0x3e,0x38,0x0a,0x00,0x3e,0x03,0x02,0xb8,0xff,0xc5,0xb4,0x2a,0x34,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x37,0x38,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x1f,0x40,0x14,0x03,0x02,0x27,0x11, 0x26,0x04,0x25,0x3e,0x38,0x0a,0x00,0x3e,0x03,0x02,0x0a,0x2d,0x34,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x06,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x44,0x26,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x22,0x40,0x0e,0x03,0x02,0x28,0x11,0x26,0x04, 0x25,0x3e,0x38,0x0a,0x00,0x3e,0x03,0x02,0xb8,0xff,0xf8,0xb4,0x2a,0x34,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x83,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x38,0x00,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x22,0x40,0x0e,0x03,0x02,0x33,0x11,0x26,0x04, 0x25,0x45,0x3f,0x0a,0x00,0x3e,0x03,0x02,0xb8,0xff,0xd1,0xb4,0x2d,0x27,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x83,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x45,0x00,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x22,0x40,0x0e,0x03,0x02,0x36,0x11,0x26,0x04, 0x25,0x45,0x3f,0x0a,0x00,0x3e,0x03,0x02,0xb8,0xff,0xd1,0xb4,0x2d,0x27,0x0a,0x13,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x16,0xfe,0x40,0x05,0x12,0x05,0xa0,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x27,0x04,0x29,0xfe,0x40,0xff,0x7d,0x01,0x07,0x04,0x28,0x00,0xa4,0x00,0x00,0x00,0x1f,0x40,0x0c,0x02,0x19, 0x04,0x19,0x03,0x07,0x25,0x26,0x05,0x00,0x3e,0x02,0xb8,0xfe,0xd3,0xb4,0x1c,0x1c,0x06,0x06,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0x00,0x16,0xfe,0x40,0x05,0x12,0x05,0xa0,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x27,0x04,0x61,0xfe,0x46,0xff,0x7d,0x01,0x07,0x04,0x28,0x00,0xa4,0x00,0x00,0x00,0x1f,0x40,0x0c, 0x02,0x17,0x04,0x17,0x03,0x07,0x24,0x25,0x05,0x00,0x3e,0x02,0xb8,0xfe,0xcc,0xb4,0x1a,0x1a,0x06,0x06,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0xff,0xbd,0xfe,0x40,0x05,0xd7,0x05,0x9d,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x00,0x27,0x04,0x36,0xfe,0x73,0xff,0x97,0x01,0x07,0x04,0x28,0x01,0x75,0x00,0x00, 0x00,0x23,0x40,0x0e,0x03,0x02,0x19,0x04,0x19,0x04,0x13,0x27,0x28,0x05,0x00,0x3e,0x03,0x02,0xb8,0xfe,0xd8,0xb4,0x1d,0x1d,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xc1,0xfe,0x40,0x05,0xd7,0x05,0x9d,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x00,0x27,0x04,0x43,0xfe,0x7d,0xff,0x97, 0x01,0x07,0x04,0x28,0x01,0x84,0x00,0x00,0x00,0x23,0x40,0x0e,0x03,0x02,0x15,0x04,0x15,0x04,0x22,0x27,0x28,0x05,0x00,0x3e,0x03,0x02,0xb8,0xfe,0xe8,0xb4,0x1d,0x1d,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbd,0xfe,0x40,0x05,0xd7,0x05,0x9d,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00, 0x00,0x27,0x04,0x37,0xfe,0x7b,0xff,0x97,0x01,0x07,0x04,0x28,0x01,0x50,0x00,0x00,0x00,0x25,0xb5,0x03,0x02,0x19,0x04,0x19,0x04,0xb8,0xff,0xee,0xb6,0x27,0x28,0x05,0x00,0x3e,0x03,0x02,0xb8,0xfe,0xe8,0xb4,0x1d,0x1d,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbf,0xfe,0x40,0x05,0xd7, 0x05,0x9d,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x00,0x27,0x04,0x44,0xfe,0x87,0xff,0x97,0x01,0x07,0x04,0x28,0x01,0x69,0x00,0x00,0x00,0x23,0x40,0x0e,0x03,0x02,0x15,0x04,0x15,0x04,0x07,0x27,0x28,0x05,0x00,0x3e,0x03,0x02,0xb8,0xff,0x01,0xb4,0x1d,0x1d,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00, 0xff,0xff,0xff,0xbd,0xfe,0x40,0x05,0xd7,0x05,0xb2,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x00,0x27,0x04,0x38,0xfe,0x8a,0xff,0x2f,0x01,0x07,0x04,0x28,0x01,0x64,0x00,0x00,0x00,0x23,0x40,0x0e,0x03,0x02,0x19,0x04,0x19,0x04,0x02,0x2e,0x2f,0x05,0x00,0x3e,0x03,0x02,0xb8,0xff,0x06,0xb4,0x10,0x10,0x06,0x06,0x3e,0x2b,0x35,0x35, 0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x05,0xd7,0x05,0xb1,0x00,0x27,0x00,0x24,0x00,0xc5,0x00,0x00,0x00,0x27,0x04,0x45,0xfe,0x89,0xff,0x2e,0x01,0x07,0x04,0x28,0x01,0x68,0x00,0x00,0x00,0x23,0x40,0x0e,0x03,0x02,0x19,0x04,0x19,0x04,0x06,0x2e,0x2f,0x05,0x00,0x3e,0x03,0x02,0xb8,0xff,0x05,0xb4, 0x10,0x10,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x23,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x27,0x1f,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x1b,0x40,0x12,0x01,0x15,0x11,0x26,0x02,0x01,0x2b,0x2b,0x08,0x08,0x3e,0x01,0x2e,0x1b, 0x21,0x09,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x23,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x61,0xdd,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x1e,0x40,0x0c,0x01,0x16,0x11,0x26,0x02,0x01,0x2a,0x2a,0x08,0x08,0x3e,0x01,0xb8,0xff,0xe0,0xb4,0x19,0x1f, 0x09,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x36,0xde,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x15,0x11,0x26,0x03,0x01,0x2d,0x2d,0x08,0x08,0x3e,0x02,0x01,0xb8,0xff,0xe8,0xb4,0x1b,0x22, 0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x43,0xca,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x16,0x11,0x26,0x03,0x01,0x2d,0x2d,0x08,0x08,0x3e,0x02,0x01,0xb8,0xff,0xd3,0xb4, 0x18,0x22,0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x37,0x27,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x1f,0x40,0x14,0x02,0x01,0x15,0x11,0x26,0x03,0x01,0x2d,0x2d,0x08,0x08,0x3e,0x02,0x01,0x31,0x1b, 0x22,0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x06,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x44,0x08,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x1f,0x40,0x14,0x02,0x01,0x16,0x11,0x26,0x03,0x01,0x2d,0x2d,0x08,0x08,0x3e,0x02,0x01,0x12,0x18, 0x22,0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x83,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x38,0xe0,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x21,0x11,0x26,0x03,0x01,0x34,0x34,0x08,0x08,0x3e,0x02,0x01,0xb8,0xff, 0xe9,0xb4,0x1b,0x15,0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x82,0xfe,0x40,0x03,0xf8,0x06,0x83,0x02,0x26,0x01,0xc7,0x00,0x00,0x00,0x26,0x04,0x45,0xdf,0x00,0x01,0x07,0x04,0x28,0xff,0x15,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x24,0x11,0x26,0x03,0x01,0x34,0x34,0x08,0x08,0x3e,0x02,0x01, 0xb8,0xff,0xe8,0xb4,0x1b,0x15,0x09,0x14,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0xff,0xbc,0xfe,0x40,0x05,0x73,0x05,0xa0,0x00,0x27,0x00,0x2b,0x00,0x81,0x00,0x00,0x00,0x27,0x04,0x27,0xfd,0xd8,0xff,0x7d,0x01,0x07,0x04,0x28,0x01,0x5d,0x00,0x00,0x00,0x21,0xb4,0x01,0x15,0x04,0x15,0x02,0xb8,0xff,0xfc,0xb5, 0x21,0x22,0x05,0x00,0x3e,0x01,0xb8,0xff,0x6a,0xb4,0x18,0x18,0x06,0x06,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0xff,0xbe,0xfe,0x40,0x05,0x73,0x05,0xa0,0x00,0x27,0x00,0x2b,0x00,0x81,0x00,0x00,0x00,0x27,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x01,0x07,0x04,0x28,0x01,0x5f,0x00,0x00,0x00,0x21,0xb4,0x01,0x13,0x04, 0x13,0x02,0xb8,0xff,0xfe,0xb5,0x20,0x21,0x05,0x00,0x3e,0x01,0xb8,0xff,0x61,0xb4,0x16,0x16,0x06,0x06,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x06,0x97,0x05,0x9f,0x00,0x27,0x00,0x2b,0x01,0xa5,0x00,0x00,0x00,0x27,0x04,0x36,0xfe,0x72,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0x84,0x00,0x00, 0x00,0x25,0xb5,0x02,0x01,0x15,0x04,0x15,0x03,0xb8,0xff,0xff,0xb6,0x23,0x24,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0x77,0xb4,0x19,0x19,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbe,0xfe,0x40,0x06,0x96,0x05,0x9f,0x00,0x27,0x00,0x2b,0x01,0xa4,0x00,0x00,0x00,0x27,0x04,0x43,0xfe,0x7a, 0xff,0x99,0x01,0x07,0x04,0x28,0x02,0x83,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x11,0x04,0x11,0x03,0xb8,0xff,0xff,0xb6,0x23,0x24,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0x86,0xb4,0x19,0x19,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x06,0x97,0x05,0x9f,0x00,0x27,0x00,0x2b, 0x01,0xa5,0x00,0x00,0x00,0x27,0x04,0x37,0xfe,0x7a,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0x75,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x15,0x04,0x15,0x03,0xb8,0xff,0xf0,0xb6,0x23,0x24,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0x87,0xb4,0x19,0x19,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbe, 0xfe,0x40,0x06,0x96,0x05,0x9f,0x00,0x27,0x00,0x2b,0x01,0xa4,0x00,0x00,0x00,0x27,0x04,0x44,0xfe,0x86,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0x83,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x11,0x04,0x11,0x03,0xb8,0xff,0xff,0xb6,0x23,0x24,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0xa1,0xb4,0x19,0x19,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35, 0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x06,0x98,0x05,0xb3,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x00,0x27,0x04,0x38,0xfe,0x89,0xff,0x30,0x01,0x07,0x04,0x28,0x02,0x85,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x15,0x04,0x15,0x03,0xb8,0xff,0xff,0xb6,0x2a,0x2b,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0xa4,0xb4, 0x0c,0x0c,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x06,0x98,0x05,0xb3,0x00,0x27,0x00,0x2b,0x01,0xa6,0x00,0x00,0x00,0x27,0x04,0x45,0xfe,0x89,0xff,0x30,0x01,0x07,0x04,0x28,0x02,0x85,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x15,0x04,0x15,0x03,0xb8,0xff,0xff,0xb6,0x2a, 0x2b,0x05,0x00,0x3e,0x02,0x01,0xb8,0xff,0xa4,0xb4,0x0c,0x0c,0x06,0x06,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x23,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x29,0x00,0xf7,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x1b,0x40,0x12,0x01,0x22, 0x11,0x26,0x02,0x0b,0x37,0x38,0x06,0x1d,0x3e,0x01,0x1a,0x28,0x2e,0x06,0x1d,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x23,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x61,0x00,0xca,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x1e,0x40,0x0c,0x01,0x23,0x11,0x26, 0x02,0x0b,0x36,0x37,0x06,0x1d,0x3e,0x01,0xb8,0xff,0xe1,0xb4,0x26,0x2c,0x06,0x1d,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x36,0x00,0xcc,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x22,0x11, 0x26,0x03,0x0b,0x39,0x3a,0x06,0x1d,0x3e,0x02,0x01,0xb8,0xff,0xea,0xb4,0x28,0x2f,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x43,0x00,0xb3,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x22,0x40,0x0e, 0x02,0x01,0x23,0x11,0x26,0x03,0x0b,0x39,0x3a,0x06,0x1d,0x3e,0x02,0x01,0xb8,0xff,0xd0,0xb4,0x25,0x2f,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x37,0x01,0x27,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00, 0x00,0x1f,0x40,0x14,0x02,0x01,0x22,0x11,0x26,0x03,0x0b,0x39,0x3a,0x06,0x1d,0x3e,0x02,0x01,0x45,0x28,0x2f,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x06,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x44,0x00,0xfa,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f, 0x00,0x00,0x00,0x1f,0x40,0x14,0x02,0x01,0x23,0x11,0x26,0x03,0x0b,0x39,0x3a,0x06,0x1d,0x3e,0x02,0x01,0x18,0x25,0x2f,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x83,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x38,0x00,0xd5,0x00,0x00,0x01,0x07,0x04,0x28, 0x01,0x4f,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x2e,0x11,0x26,0x03,0x0b,0x40,0x41,0x06,0x1d,0x3e,0x02,0x01,0xb8,0xff,0xf2,0xb4,0x28,0x22,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x83,0x02,0x26,0x01,0xd5,0x00,0x01,0x00,0x27,0x04,0x45,0x00,0xd5,0x00,0x00, 0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x22,0x40,0x0e,0x02,0x01,0x31,0x11,0x26,0x03,0x0b,0x40,0x41,0x06,0x1d,0x3e,0x02,0x01,0xb8,0xff,0xf2,0xb4,0x28,0x22,0x06,0x1d,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x2b,0x35,0x35,0xff,0xff,0xff,0xbc,0xfe,0x40,0x06,0x3c,0x05,0xb2,0x00,0x27,0x00,0x9f,0x00,0x93,0x00,0x00,0x00,0x27, 0x04,0x27,0xfd,0xd8,0xff,0x7d,0x01,0x07,0x04,0x28,0x01,0x9f,0x00,0x00,0x00,0x21,0xb4,0x01,0x25,0x04,0x25,0x02,0xb8,0xff,0xfd,0xb5,0x31,0x32,0x0e,0x00,0x3e,0x01,0xb8,0xff,0xb0,0xb4,0x28,0x28,0x12,0x12,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0xff,0xbe,0xfe,0x40,0x06,0x3c,0x05,0xb2,0x00,0x27,0x00,0x9f, 0x00,0x93,0x00,0x00,0x00,0x27,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x01,0x07,0x04,0x28,0x01,0x9f,0x00,0x00,0x00,0x21,0xb4,0x01,0x23,0x04,0x23,0x02,0xb8,0xff,0xfd,0xb5,0x30,0x31,0x0e,0x00,0x3e,0x01,0xb8,0xff,0xa7,0xb4,0x26,0x26,0x12,0x12,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x07,0x45, 0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9c,0x00,0x00,0x00,0x27,0x04,0x36,0xfe,0x72,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0xa8,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x25,0x04,0x25,0x03,0xb8,0xff,0xfd,0xb6,0x33,0x34,0x0e,0x00,0x3e,0x02,0x01,0xb8,0xff,0xd8,0xb4,0x29,0x29,0x12,0x12,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35, 0x35,0x00,0xff,0xff,0xff,0xbe,0xfe,0x40,0x07,0x44,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9b,0x00,0x00,0x00,0x27,0x04,0x43,0xfe,0x7a,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0xa7,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x21,0x04,0x21,0x03,0xb8,0xff,0xfd,0xb6,0x33,0x34,0x0e,0x00,0x3e,0x02,0x01,0xb8,0xff,0xe7,0xb4,0x29,0x29,0x12,0x12, 0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x07,0x45,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9c,0x00,0x00,0x00,0x27,0x04,0x37,0xfe,0x7a,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0xa8,0x00,0x00,0x00,0x25,0xb5,0x02,0x01,0x25,0x04,0x25,0x03,0xb8,0xff,0xfd,0xb6,0x33,0x34,0x0e,0x00,0x3e, 0x02,0x01,0xb8,0xff,0xe8,0xb4,0x29,0x29,0x12,0x12,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbe,0xfe,0x40,0x07,0x44,0x05,0xb2,0x00,0x27,0x00,0x9f,0x01,0x9b,0x00,0x00,0x00,0x27,0x04,0x44,0xfe,0x86,0xff,0x99,0x01,0x07,0x04,0x28,0x02,0xa7,0x00,0x00,0x00,0x23,0xb5,0x02,0x01,0x21,0x04,0x21, 0x03,0xb8,0xff,0xfd,0x40,0x0d,0x33,0x34,0x0e,0x00,0x3e,0x02,0x01,0x02,0x29,0x29,0x12,0x12,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x07,0x46,0x05,0xb3,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x00,0x27,0x04,0x38,0xfe,0x89,0xff,0x30,0x01,0x07,0x04,0x28,0x02,0xa9,0x00,0x00, 0x00,0x23,0xb5,0x02,0x01,0x25,0x04,0x25,0x03,0xb8,0xff,0xfd,0x40,0x0d,0x3a,0x3b,0x0e,0x00,0x3e,0x02,0x01,0x05,0x1c,0x1c,0x12,0x12,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0xff,0xbc,0xfe,0x40,0x07,0x46,0x05,0xb3,0x00,0x27,0x00,0x9f,0x01,0x9d,0x00,0x00,0x00,0x27,0x04,0x45,0xfe,0x89,0xff,0x30, 0x01,0x07,0x04,0x28,0x02,0xa9,0x00,0x00,0x00,0x23,0xb5,0x02,0x01,0x25,0x04,0x25,0x03,0xb8,0xff,0xfd,0x40,0x0d,0x3a,0x3b,0x0e,0x00,0x3e,0x02,0x01,0x05,0x1c,0x1c,0x12,0x12,0x3e,0x2b,0x35,0x35,0x2b,0x35,0x00,0x11,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x05,0xbe,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x07, 0x04,0x66,0x02,0x6a,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe3,0x40,0x09,0x2d,0x27,0x0a,0x13,0x25,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x05,0x2f,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x07,0x04,0x64,0x02,0x68,0x00,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xe1,0x40,0x09,0x28, 0x27,0x0a,0x13,0x25,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x00,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x55,0xbd,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x1e,0x40,0x0c,0x02,0x28,0x11,0x26,0x03,0x25,0x31,0x2b,0x0a,0x00,0x3e,0x02,0xb8,0xff,0x8e,0xb4,0x29,0x27, 0x0a,0x13,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x04,0x18,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x28,0x5b,0x00,0x00,0x0b,0xb6,0x02,0x24,0x2d,0x27,0x0a,0x00,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x06,0x00,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26, 0x04,0x60,0x35,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x1b,0x40,0x12,0x02,0x29,0x11,0x26,0x03,0x25,0x31,0x2b,0x0a,0x00,0x3e,0x02,0x06,0x29,0x27,0x0a,0x13,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x05,0x94,0x02,0x26,0x01,0x2f,0x00,0x00,0x01,0x06,0x04,0x2a,0x0a,0x00,0x00,0x16, 0xb9,0x00,0x02,0xff,0xdb,0x40,0x09,0x2d,0x27,0x0a,0x13,0x25,0x02,0x2d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x5a,0xfe,0x40,0x04,0xc5,0x05,0x94,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x26,0x04,0x2a,0x0a,0x00,0x01,0x06,0x04,0x28,0x5c,0x00,0x00,0x1e,0x40,0x0c,0x02,0x2d,0x11,0x26,0x03,0x25,0x39,0x33,0x0a,0x00, 0x3e,0x02,0xb8,0xff,0xdb,0xb4,0x2d,0x27,0x0a,0x13,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x0a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x66,0x02,0x94,0x01,0x4c,0x00,0x13,0x40,0x0b,0x02,0x00,0x16,0x10,0x05,0x00,0x25,0x02,0x13,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0x79,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x64,0x02,0x96,0x01,0x4a,0x00,0x13,0x40,0x0b,0x02,0x00,0x12,0x13,0x05,0x00,0x25,0x02,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xfb,0x00,0x00,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07, 0x04,0x55,0xfe,0x2a,0xff,0x99,0x00,0x16,0xb4,0x02,0x12,0x03,0x12,0x02,0xb8,0xfd,0xee,0xb4,0x12,0x10,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x60,0xfe,0x5c,0xff,0x99,0x00,0x16,0xb4,0x02,0x13,0x03,0x13,0x02,0xb8,0xfe, 0x20,0xb4,0x12,0x10,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0x00,0x16,0xfe,0x40,0x05,0x12,0x05,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x28,0x00,0xa3,0x00,0x00,0x00,0x0b,0xb6,0x02,0x67,0x16,0x10,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x00,0x01,0x01,0xe4,0x04,0x7b,0x02,0xcf,0x06,0x23,0x00,0x0e, 0x00,0x1f,0xb5,0x03,0x03,0x00,0x09,0xfa,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x0d,0x48,0x01,0x03,0x0c,0xaf,0x06,0x2f,0xe1,0x39,0xc6,0x2b,0x00,0x3f,0xc4,0x39,0x2f,0x31,0x30,0x01,0x27,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x0a,0x26,0x68,0x10,0x30,0x3e,0x3a,0x2c,0x35,0x46,0x73,0x04,0x7b,0x3f,0x38, 0x68,0x02,0x38,0x2a,0x2b,0x3a,0x49,0x38,0x57,0xa8,0x00,0x01,0x01,0xba,0xfe,0x40,0x02,0xf6,0xff,0x89,0x00,0x0c,0x00,0x23,0x40,0x13,0x0c,0x0a,0xc3,0x40,0x02,0x80,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0x00,0x07,0xc2,0x06,0x2f,0xf1,0xc2,0x2f,0x00,0x2f,0x5d,0x1a,0xdc,0x1a,0xed,0x32,0x31,0x30,0x01,0x06,0x23,0x22,0x26, 0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x37,0x02,0xf6,0x3c,0x56,0x4b,0x5f,0x7b,0x44,0x29,0x29,0xfe,0x90,0x50,0x53,0x46,0xb0,0xba,0x43,0x2a,0x00,0x00,0x01,0x01,0xe4,0x04,0x7b,0x02,0xcf,0x06,0x23,0x00,0x0e,0x00,0x25,0x40,0x0b,0x01,0x18,0x09,0x0d,0x48,0x00,0x03,0xfb,0x09,0xfa,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x12,0x48,0x01,0x03, 0x0c,0xaf,0x06,0x2f,0xe1,0x39,0xc6,0x2b,0x00,0x3f,0xfd,0xc4,0x31,0x30,0x2b,0x01,0x27,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x0a,0x26,0x68,0x10,0x30,0x3e,0x3a,0x2c,0x35,0x46,0x73,0x04,0x7b,0x3f,0x38,0x68,0x02,0x38,0x2a,0x2b,0x3a,0x49,0x38,0x57,0xa8,0x00,0x01,0x01,0x40,0x04,0xa6,0x03,0x70, 0x05,0x94,0x00,0x0b,0x00,0x1c,0x40,0x0d,0x03,0xdb,0x40,0x09,0x80,0x00,0x06,0x00,0xfc,0x01,0x05,0xfc,0x06,0x2f,0xe1,0xd4,0xe1,0x00,0x2f,0x33,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x03,0x70,0x6a,0x18,0x96,0x96,0x18,0x6a,0x0a,0x9a,0x74,0x74,0x9a,0x04,0xa6,0x8b,0x8b,0x6a, 0x84,0x85,0x00,0x03,0x01,0x33,0x04,0x7f,0x03,0x7d,0x06,0x5a,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x35,0x40,0x1b,0x03,0xdb,0x40,0x09,0x80,0x00,0x06,0x12,0x0c,0x1e,0xc1,0x18,0x0f,0xc0,0x15,0x15,0x00,0x21,0xc0,0x1b,0x06,0x00,0xfc,0x01,0x05,0xfc,0x06,0x2f,0xe1,0xd4,0xe1,0x10,0xd6,0xe1,0x10,0xc2,0x2f,0xe1,0x00,0x2f,0xfd,0x39, 0x39,0xde,0x32,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x7d,0x69,0x2a,0x92,0x92,0x2a,0x69,0x1a,0x9e,0x6d,0x6c,0xa0,0x4c,0x28,0x38,0x39,0x27,0x2a, 0x3b,0x3b,0xfe,0x56,0x29,0x3a,0x3a,0x29,0x29,0x3b,0x3b,0x05,0x8e,0x6c,0x6c,0x5f,0x6d,0x6e,0xfe,0x93,0x38,0x2b,0x29,0x39,0x3a,0x28,0x2a,0x39,0x38,0x2b,0x28,0x3a,0x3a,0x28,0x2a,0x39,0xff,0xff,0x00,0x83,0xfe,0x40,0x03,0xf9,0x06,0x00,0x02,0x26,0x01,0xc7,0x01,0x00,0x00,0x26,0x04,0x55,0xbe,0x00,0x01,0x07,0x04,0x28,0xff,0x14, 0x00,0x00,0x00,0x20,0xb4,0x01,0x15,0x11,0x26,0x02,0xb8,0xff,0xff,0xb5,0x20,0x20,0x08,0x08,0x3e,0x01,0xb8,0xff,0xc6,0xb4,0x17,0x15,0x09,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x83,0xfe,0x40,0x03,0xf9,0x04,0x18,0x02,0x26,0x01,0xc7,0x01,0x00,0x01,0x07,0x04,0x28,0xff,0x14,0x00,0x00,0x00,0x0e,0xb9,0x00, 0x01,0xff,0x2e,0xb4,0x1b,0x15,0x0c,0x14,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0x83,0xfe,0x40,0x03,0xf9,0x06,0x00,0x02,0x26,0x01,0xc7,0x01,0x00,0x00,0x26,0x04,0x60,0x40,0x00,0x01,0x07,0x04,0x28,0xff,0x14,0x00,0x00,0x00,0x1e,0xb4,0x01,0x16,0x11,0x26,0x02,0xb8,0xff,0xff,0x40,0x0c,0x20,0x20,0x08,0x08,0x3e,0x01,0x48,0x17,0x15, 0x09,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x83,0xfe,0x6c,0x03,0xf9,0x05,0x94,0x02,0x26,0x01,0xc7,0x01,0x00,0x01,0x06,0x04,0x2a,0xf5,0x00,0x00,0x13,0x40,0x0b,0x01,0x0f,0x1b,0x15,0x0c,0x14,0x25,0x01,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x83,0xfe,0x40,0x03,0xf9,0x05,0x94, 0x02,0x26,0x01,0xc7,0x01,0x00,0x00,0x26,0x04,0x2a,0xf5,0x00,0x01,0x07,0x04,0x28,0xff,0x14,0x00,0x00,0x00,0x20,0xb4,0x01,0x15,0x11,0x26,0x02,0xb8,0xff,0xff,0xb5,0x28,0x28,0x08,0x08,0x3e,0x01,0xb8,0xff,0xfd,0xb4,0x1b,0x15,0x09,0x14,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0xff,0xac,0x00,0x00,0x04,0x37,0x05,0x9a, 0x00,0x27,0x00,0x28,0x00,0x83,0x00,0x00,0x01,0x07,0x04,0x55,0xfd,0xdb,0xff,0x99,0x00,0x16,0xb4,0x01,0x0e,0x03,0x0e,0x01,0xb8,0xfd,0x78,0xb4,0x0e,0x0c,0x02,0x0b,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xc4,0x00,0x00,0x04,0x36,0x05,0x9a,0x00,0x27,0x00,0x28,0x00,0x82,0x00,0x00,0x01,0x07,0x04,0x60,0xfd,0xf3, 0xff,0x99,0x00,0x16,0xb4,0x01,0x0f,0x03,0x0f,0x01,0xb8,0xff,0x94,0xb4,0x0c,0x0c,0x02,0x02,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xac,0x00,0x00,0x05,0x74,0x05,0x9a,0x00,0x27,0x00,0x2b,0x00,0x82,0x00,0x00,0x01,0x07,0x04,0x55,0xfd,0xdb,0xff,0x99,0x00,0x16,0xb4,0x01,0x0e,0x03,0x0e,0x01,0xb8,0xff,0x7c,0xb4, 0x0c,0x0c,0x06,0x06,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xc4,0x00,0x00,0x05,0x74,0x05,0x9a,0x00,0x27,0x00,0x2b,0x00,0x82,0x00,0x00,0x01,0x07,0x04,0x60,0xfd,0xf3,0xff,0x99,0x00,0x16,0xb4,0x01,0x0f,0x03,0x0f,0x01,0xb8,0xfc,0xf2,0xb4,0x0e,0x0c,0x06,0x0b,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff, 0x00,0xbc,0xfe,0x40,0x04,0xf2,0x05,0x9a,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x04,0x28,0x00,0xdd,0x00,0x00,0x00,0x0b,0xb6,0x01,0x5e,0x12,0x0c,0x06,0x0b,0x25,0x01,0x2b,0x35,0x00,0x00,0x02,0x01,0x4a,0x04,0x92,0x03,0x66,0x06,0x06,0x00,0x0c,0x00,0x10,0x00,0x30,0x40,0x0e,0x03,0x03,0x09,0x0e,0x00,0x0f,0x09,0xfa,0x0d,0x80, 0x0f,0x0f,0x0b,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x12,0x48,0x01,0x03,0x0b,0xaf,0x06,0x2f,0xe1,0x39,0xc6,0x2b,0x10,0xc2,0x2f,0x1a,0xcd,0x00,0x3f,0xc4,0xd4,0xc6,0x12,0x39,0x2f,0x31,0x30,0x01,0x27,0x36,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x05,0x23,0x03,0x33,0x01,0x68,0x1e,0x5d,0x17,0x31,0x41,0x36,0x2c,0x77,0x01, 0x41,0x5e,0xae,0xa6,0x04,0x92,0x3d,0x28,0x4f,0x36,0x2c,0x28,0x36,0x7a,0xa8,0x4e,0x01,0x6a,0x00,0x02,0x01,0x42,0x04,0x92,0x03,0x6e,0x06,0x06,0x00,0x0c,0x00,0x10,0x00,0x37,0x40,0x13,0x10,0x18,0x09,0x0e,0x48,0x03,0x03,0x09,0x0f,0x00,0x10,0x09,0xfa,0x0d,0x80,0x0f,0x0f,0x0b,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x12,0x48,0x01,0x03, 0x0b,0xaf,0x06,0x2f,0xe1,0x39,0xc6,0x2b,0x10,0xc2,0x2f,0x1a,0xcd,0x00,0x3f,0xc4,0xd4,0xc6,0x12,0x39,0x2f,0x31,0x30,0x01,0x2b,0x01,0x27,0x36,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x01,0x03,0x23,0x13,0x01,0x60,0x1e,0x5d,0x17,0x32,0x40,0x36,0x2c,0x76,0x01,0x52,0xb0,0x5e,0x66,0x04,0x92,0x3d,0x28,0x4f,0x36,0x2c, 0x28,0x36,0x7a,0xa8,0x01,0x1c,0xfe,0x96,0x01,0x6a,0x00,0x02,0x01,0x33,0x04,0x77,0x03,0x7d,0x06,0x83,0x00,0x0b,0x00,0x17,0x00,0x53,0x40,0x0d,0x0d,0x18,0x09,0x12,0x48,0x03,0xdb,0x40,0x09,0x80,0x00,0x06,0x0f,0xb8,0x01,0x02,0x40,0x0d,0x0f,0x13,0x1f,0x13,0x02,0x13,0x40,0x13,0x18,0x48,0x13,0x0c,0x0d,0xb8,0xff,0xc0,0xb5,0x09, 0x12,0x48,0x0d,0x0f,0x16,0xb8,0x01,0x01,0x40,0x09,0x11,0x11,0x06,0x00,0xfc,0x01,0x05,0xfc,0x06,0x2f,0xe1,0xd4,0xe1,0x11,0x39,0x2f,0xe1,0x39,0xc4,0x2b,0x00,0x2f,0xd4,0x2b,0x5d,0xed,0xd6,0x32,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x2b,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x27,0x36,0x37,0x22,0x35,0x34, 0x33,0x32,0x16,0x15,0x14,0x03,0x7d,0x69,0x2a,0x92,0x92,0x2a,0x69,0x19,0xa0,0x6c,0x6c,0xa0,0xfe,0xb4,0x16,0x56,0x06,0x60,0x5a,0x30,0x3e,0x05,0xb6,0x6d,0x6d,0x5f,0x6e,0x6e,0xfe,0x62,0x35,0x16,0x3a,0x50,0x52,0x41,0x30,0x91,0xff,0xff,0xff,0xec,0xff,0xf4,0x02,0x10,0x05,0xbe,0x00,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x66, 0x00,0xfe,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xa7,0x40,0x09,0x12,0x0c,0x05,0x0b,0x25,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xfa,0xff,0xf4,0x02,0x08,0x05,0x2f,0x00,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x64,0x00,0xf8,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xa1,0x40,0x09,0x0e,0x0f,0x05, 0x0b,0x25,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xb2,0xff,0xf4,0x02,0x5e,0x06,0x0e,0x00,0x26,0x01,0xc9,0x01,0x00,0x01,0x07,0x04,0x53,0xfe,0xb0,0x00,0x0e,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xb0,0x40,0x0b,0x1f,0x19,0x05,0x0b,0x25,0x03,0x02,0x01,0x0d,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01, 0x2b,0x35,0x35,0x35,0xff,0xff,0xff,0xb2,0xff,0xf4,0x02,0x5e,0x06,0x0e,0x00,0x26,0x01,0xc9,0x01,0x00,0x01,0x07,0x04,0x54,0xfe,0xb0,0x00,0x0e,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xb0,0x40,0x0b,0x1f,0x19,0x05,0x0b,0x25,0x03,0x02,0x01,0x0e,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0xff,0xdf, 0xff,0xf4,0x02,0x0f,0x05,0x94,0x00,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x2a,0xfe,0x9f,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xa0,0x40,0x09,0x12,0x0c,0x05,0x0b,0x25,0x01,0x12,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xd5,0xff,0xf4,0x02,0x1f,0x06,0x5a,0x00,0x26,0x01,0xc9,0x00,0x00,0x01,0x07,0x04,0x2b, 0xfe,0xa2,0x00,0x00,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xa3,0x40,0x0b,0x12,0x21,0x05,0x0b,0x25,0x03,0x02,0x01,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0xff,0xfe,0x00,0x00,0x02,0x22,0x07,0x0a,0x00,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x04,0x66,0x01,0x10,0x01,0x4c,0x00,0x13,0x40,0x0b, 0x01,0x00,0x0a,0x04,0x02,0x03,0x25,0x01,0x07,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x02,0x0e,0x06,0x79,0x00,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x04,0x64,0x01,0x10,0x01,0x4a,0x00,0x13,0x40,0x0b,0x01,0x00,0x06,0x07,0x02,0x03,0x25,0x01,0x05,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0xff,0xae,0x00,0x00,0x02,0x2c,0x05,0x9a,0x00,0x27,0x00,0x2c,0x00,0xc8,0x00,0x00,0x01,0x07,0x04,0x55,0xfd,0xdd,0xff,0x9a,0x00,0x14,0xb9,0x00,0x01,0xfe,0x5d,0xb7,0x06,0x04,0x02,0x03,0x25,0x01,0x07,0x03,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xc6,0x00,0x00,0x02,0x4a,0x05,0x9a,0x00,0x27,0x00,0x2c,0x00,0xe6, 0x00,0x00,0x01,0x07,0x04,0x60,0xfd,0xf5,0xff,0x9a,0x00,0x14,0xb9,0x00,0x01,0xfe,0x57,0xb7,0x06,0x04,0x02,0x03,0x25,0x01,0x07,0x03,0x00,0x3f,0x35,0x01,0x2b,0x35,0x00,0x02,0x01,0x44,0x04,0x92,0x03,0x6c,0x06,0x06,0x00,0x0c,0x00,0x10,0x00,0x35,0x40,0x1d,0x0b,0x0b,0x05,0x0e,0x01,0x0f,0x05,0xfa,0x0d,0x80,0x0f,0x40,0x09,0x0e, 0x48,0x0f,0x0f,0x08,0x00,0x40,0x09,0x12,0x48,0x00,0x00,0x0b,0x08,0xaf,0x03,0x2f,0xf1,0x39,0xc2,0x2f,0x2b,0x10,0xc2,0x2f,0x2b,0x1a,0xcd,0x00,0x3f,0xc4,0xd4,0xc6,0x12,0x39,0x2f,0x31,0x30,0x01,0x07,0x26,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x16,0x05,0x23,0x03,0x33,0x02,0x1e,0x20,0xba,0x76,0x2c,0x36,0x40,0x32,0x18, 0x01,0xaa,0x5c,0xb0,0xa8,0x04,0xcf,0x3d,0x50,0xaa,0x7a,0x35,0x29,0x2c,0x36,0x4f,0x61,0x01,0x6a,0x00,0x00,0x02,0x01,0x38,0x04,0x92,0x03,0x7b,0x06,0x06,0x00,0x0c,0x00,0x10,0x00,0x35,0x40,0x1d,0x0b,0x0b,0x05,0x0f,0x01,0x10,0x05,0xfa,0x0d,0x80,0x0f,0x0f,0x1f,0x0f,0x02,0x0f,0x0f,0x08,0x00,0x40,0x09,0x12,0x48,0x00,0x00,0x0b, 0x08,0xaf,0x03,0x2f,0xf1,0x39,0xc2,0x2f,0x2b,0x10,0xc2,0x2f,0x5d,0x1a,0xcd,0x00,0x3f,0xc4,0xd4,0xc6,0x12,0x39,0x2f,0x31,0x30,0x01,0x07,0x26,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x16,0x01,0x03,0x23,0x13,0x02,0x12,0x1e,0xbc,0x76,0x2c,0x36,0x40,0x32,0x17,0x01,0xc6,0xb0,0x5f,0x67,0x04,0xcf,0x3d,0x52,0xa8,0x7a,0x36, 0x28,0x2c,0x36,0x4f,0x01,0x09,0xfe,0x96,0x01,0x6a,0x00,0x02,0x01,0x33,0x04,0x77,0x03,0x7d,0x06,0x83,0x00,0x0b,0x00,0x17,0x00,0x52,0x40,0x0d,0x0e,0x18,0x09,0x12,0x48,0x03,0xdb,0x40,0x09,0x80,0x00,0x06,0x0c,0xb8,0x01,0x02,0x40,0x15,0x0f,0x14,0x1f,0x14,0x02,0x14,0x40,0x13,0x18,0x48,0x14,0x0f,0x0e,0x40,0x09,0x12,0x48,0x0e, 0x0e,0x0c,0x16,0xb8,0x01,0x01,0x40,0x09,0x11,0x11,0x06,0x00,0xfc,0x01,0x05,0xfc,0x06,0x2f,0xe1,0xd4,0xe1,0x11,0x39,0x2f,0xf1,0x39,0xc0,0x2f,0x2b,0x00,0x2f,0xd4,0x2b,0x5d,0xed,0xd6,0x32,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x2b,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x16,0x17,0x07,0x26,0x35,0x34,0x36, 0x33,0x32,0x15,0x14,0x03,0x7d,0x69,0x2a,0x92,0x92,0x2a,0x69,0x19,0xa0,0x6c,0x6c,0xa0,0xfe,0xf8,0x06,0x54,0x14,0xb0,0x3e,0x30,0x5a,0x05,0xb6,0x6d,0x6d,0x5f,0x6e,0x6e,0xfe,0xe7,0x3a,0x16,0x35,0x25,0x91,0x30,0x41,0x52,0x50,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x05,0xbe,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x07,0x04,0x66, 0x02,0x08,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xaa,0x40,0x09,0x23,0x1d,0x00,0x16,0x25,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x05,0x2f,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x07,0x04,0x64,0x02,0x0e,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xb0,0x40,0x09,0x1e,0x1d,0x00, 0x16,0x25,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x0e,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x53,0xc3,0x0e,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xbd,0x40,0x0b,0x30,0x2a,0x00,0x16,0x25,0x03,0x02,0x01,0x1e,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35, 0x35,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x0e,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x54,0xd6,0x0e,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xd0,0x40,0x0b,0x30,0x2a,0x00,0x16,0x25,0x03,0x02,0x01,0x1f,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0xa1,0xfe,0x74,0x04,0x50, 0x06,0x23,0x02,0x26,0x01,0xd0,0x00,0x00,0x01,0x06,0x04,0x29,0x14,0x00,0x00,0x16,0xb9,0x00,0x02,0xff,0xf4,0x40,0x09,0x1c,0x27,0x04,0x0a,0x25,0x02,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa1,0xfe,0x74,0x04,0x50,0x06,0x23,0x02,0x26,0x01,0xd0,0x00,0x00,0x01,0x06,0x04,0x61,0xd4,0x00,0x00,0x16,0xb9,0x00, 0x02,0xff,0xb3,0x40,0x09,0x1f,0x1b,0x04,0x0a,0x25,0x02,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x05,0x94,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x2a,0xba,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xb4,0x40,0x09,0x23,0x1d,0x00,0x16,0x25,0x01,0x23,0x11,0x26,0x00,0x2b,0x35,0x01, 0x2b,0x35,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x06,0x5a,0x02,0x26,0x01,0xd2,0x00,0x00,0x01,0x06,0x04,0x2b,0xa9,0x00,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xa4,0x40,0x0b,0x38,0x32,0x00,0x16,0x25,0x03,0x02,0x01,0x35,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60, 0x07,0x0a,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x04,0x66,0x02,0x37,0x01,0x4c,0x00,0x13,0x40,0x0b,0x01,0x00,0x14,0x0e,0x05,0x00,0x25,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x06,0x81,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x04,0x64,0x02,0x38,0x01,0x52,0x00,0x13, 0x40,0x0b,0x01,0x00,0x10,0x11,0x05,0x00,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0x96,0x00,0x00,0x05,0x49,0x05,0x9a,0x00,0x27,0x00,0x3c,0x00,0xe9,0x00,0x00,0x01,0x07,0x04,0x55,0xfd,0xc5,0xff,0x99,0x00,0x16,0xb4,0x01,0x10,0x03,0x10,0x01,0xb8,0xfc,0xfb,0xb4,0x10,0x0e,0x05,0x00,0x25,0x01, 0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xb2,0x00,0x00,0x05,0x49,0x05,0x9a,0x00,0x27,0x00,0x3c,0x00,0xe9,0x00,0x00,0x01,0x07,0x04,0x60,0xfd,0xe1,0xff,0x99,0x00,0x16,0xb4,0x01,0x0e,0x03,0x0e,0x01,0xb8,0xfd,0x17,0xb4,0x10,0x0e,0x05,0x00,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x04,0xb0, 0x05,0xa0,0x00,0x27,0x00,0x33,0x00,0x87,0x00,0x00,0x01,0x07,0x04,0x61,0xfd,0xdc,0xff,0x7d,0x00,0x16,0xb4,0x02,0x1a,0x04,0x1a,0x02,0xb8,0xfd,0x3b,0xb4,0x17,0x13,0x03,0x07,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0x00,0x03,0x01,0x02,0x04,0x96,0x03,0xae,0x06,0x00,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x2c,0x40,0x15,0x0a,0x04, 0x16,0xc1,0x40,0x10,0x10,0x02,0x80,0x01,0x0d,0xc0,0x07,0x00,0x40,0x13,0xc0,0x19,0x00,0x80,0x02,0x2f,0x1a,0xcd,0xd4,0xe1,0x1a,0x10,0xde,0xe1,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x03,0x33,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x14,0x06,0x02,0xc0,0x5e,0xb0,0xa8,0xf0,0x28,0x38,0x38,0x28,0x29,0x3b,0x3a,0xfd,0xf0,0x28,0x3a,0x3a,0x28,0x2a,0x3a,0x3a,0x04,0x96,0x01,0x6a,0xfe,0xba,0x36,0x2a,0x2a,0x39,0x39,0x2a,0x28,0x38,0x37,0x29,0x2a,0x39,0x39,0x2a,0x28,0x38,0x00,0x03,0x01,0x02,0x04,0x96,0x03,0xae,0x06,0x00,0x00,0x03,0x00,0x0f,0x00,0x1b, 0x00,0x2c,0x40,0x15,0x0a,0x04,0x16,0xc1,0x40,0x10,0x10,0x03,0x80,0x02,0x13,0xc0,0x19,0x02,0x40,0x0d,0xc0,0x07,0x00,0x80,0x02,0x2f,0x1a,0xdd,0xd4,0xe1,0x1a,0x10,0xde,0xe1,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x13,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x00,0xb0,0x5e,0x66,0xf2,0x28,0x38,0x38,0x28,0x29,0x3b,0x3a,0xfd,0xf0,0x28,0x3a,0x3a,0x28,0x2a,0x3a,0x3a,0x06,0x00,0xfe,0x96,0x01,0x6a,0xfe,0xba,0x36,0x2a,0x2a,0x39,0x39,0x2a,0x28,0x38,0x37,0x29,0x2a,0x39,0x39,0x2a,0x28,0x38,0x00,0x01,0x01,0xd1,0x04,0x96,0x02,0xdf, 0x06,0x00,0x00,0x03,0x00,0x11,0xb6,0x01,0x40,0x02,0x01,0x02,0x80,0x00,0x2f,0x1a,0xcd,0x00,0x3f,0x1a,0xcd,0x31,0x30,0x01,0x23,0x03,0x33,0x02,0xdf,0x5e,0xb0,0xa8,0x04,0x96,0x01,0x6a,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x00,0x02,0x26,0x01,0xd5,0x00,0x00,0x00,0x27,0x04,0x55,0x00,0xb0,0x00,0x00,0x01,0x07,0x04,0x28, 0x01,0x4f,0x00,0x00,0x00,0x1e,0x40,0x0c,0x01,0x23,0x11,0x26,0x02,0x0b,0x2c,0x2d,0x06,0x1d,0x3e,0x01,0xb8,0xff,0xcd,0xb4,0x24,0x22,0x06,0x1d,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x04,0x00,0x02,0x26,0x01,0xd5,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x0b,0xb6,0x01, 0x0b,0x28,0x29,0x06,0x1d,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x06,0x00,0x02,0x26,0x01,0xd5,0x00,0x00,0x00,0x27,0x04,0x60,0x01,0x1f,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x1b,0x40,0x12,0x01,0x24,0x11,0x26,0x02,0x0b,0x2c,0x2d,0x06,0x1d,0x3e,0x01,0x3c,0x24,0x22,0x06,0x1d,0x3e, 0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xff,0xe9,0x06,0x00,0x05,0x94,0x02,0x26,0x01,0xd5,0x00,0x00,0x01,0x07,0x04,0x2a,0x00,0xeb,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x08,0x28,0x22,0x06,0x1d,0x25,0x01,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x77,0xfe,0x40,0x06,0x00,0x05,0x94, 0x02,0x26,0x01,0xd5,0x00,0x00,0x00,0x27,0x04,0x2a,0x00,0xeb,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x4f,0x00,0x00,0x00,0x1b,0x40,0x12,0x01,0x28,0x11,0x26,0x02,0x0b,0x34,0x35,0x06,0x1d,0x3e,0x01,0x08,0x28,0x22,0x06,0x1d,0x3e,0x2b,0x35,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0xff,0xac,0xff,0xe8,0x06,0x11,0x05,0xb2,0x00,0x26, 0x00,0x32,0x67,0x00,0x01,0x07,0x04,0x55,0xfd,0xdb,0xff,0x99,0x00,0x16,0xb4,0x02,0x1a,0x03,0x1a,0x02,0xb8,0xfc,0xc8,0xb4,0x1a,0x18,0x03,0x09,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xd1,0xff,0xe8,0x06,0x11,0x05,0xb2,0x00,0x26,0x00,0x32,0x67,0x00,0x01,0x07,0x04,0x60,0xfe,0x00,0xff,0x99,0x00,0x16,0xb4,0x02, 0x1b,0x03,0x1b,0x02,0xb8,0xfc,0xed,0xb4,0x1a,0x18,0x03,0x09,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xac,0x00,0x00,0x06,0x53,0x05,0xb2,0x00,0x27,0x00,0x9f,0x00,0xaa,0x00,0x00,0x01,0x07,0x04,0x55,0xfd,0xdb,0xff,0x99,0x00,0x16,0xb4,0x01,0x1e,0x03,0x1e,0x01,0xb8,0xff,0xac,0xb4,0x1c,0x1c,0x12,0x12,0x25,0x01, 0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0xff,0xd1,0x00,0x00,0x06,0x3d,0x05,0xb2,0x00,0x27,0x00,0x9f,0x00,0x94,0x00,0x00,0x01,0x07,0x04,0x60,0xfe,0x00,0xff,0x99,0x00,0x16,0xb4,0x01,0x1f,0x03,0x1f,0x01,0xb8,0xff,0xe7,0xb4,0x1c,0x1c,0x12,0x12,0x25,0x01,0x2b,0x35,0x00,0x11,0x3f,0x35,0xff,0xff,0x00,0x64,0xfe,0x40,0x05,0xa9, 0x05,0xb2,0x02,0x26,0x00,0x9f,0x00,0x00,0x01,0x07,0x04,0x28,0x01,0x0e,0x00,0x00,0x00,0x0b,0xb6,0x01,0x5e,0x22,0x1c,0x12,0x18,0x25,0x01,0x2b,0x35,0x00,0x00,0x01,0x01,0xd1,0x04,0x96,0x02,0xdf,0x06,0x00,0x00,0x03,0x00,0x11,0xb6,0x02,0x40,0x03,0x01,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x3f,0x1a,0xcd,0x31,0x30,0x01,0x03,0x23, 0x13,0x02,0xdf,0xb0,0x5e,0x67,0x06,0x00,0xfe,0x96,0x01,0x6a,0x00,0x01,0x01,0xe2,0x04,0x7b,0x02,0xcf,0x06,0x23,0x00,0x0d,0x00,0x25,0x40,0x15,0x00,0x18,0x09,0x0d,0x48,0x0c,0x0c,0x01,0x07,0xfa,0x00,0x40,0x09,0x0d,0x48,0x00,0x00,0x0c,0x0a,0xaf,0x04,0x2f,0xf1,0x39,0xc2,0x2f,0x2b,0x00,0x3f,0xc4,0x39,0x2f,0x31,0x30,0x2b,0x01, 0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x02,0xcf,0x29,0x53,0x71,0x45,0x35,0x2c,0x3a,0x6c,0x10,0x04,0xba,0x3f,0x28,0xa7,0x58,0x39,0x48,0x3a,0x2b,0x5d,0x07,0x68,0x00,0x00,0x01,0xfe,0xe8,0x04,0xc2,0x01,0x1a,0x06,0x0e,0x00,0x06,0x00,0x15,0xb7,0x00,0xc0,0x04,0x02,0x00,0x05,0x80,0x04,0x00,0x2f,0x1a, 0xcd,0x39,0x39,0x01,0x2f,0x1a,0xcc,0x31,0x30,0x01,0x23,0x27,0x07,0x23,0x13,0x33,0x01,0x1a,0x78,0xa4,0xa6,0x70,0xd6,0x86,0x04,0xc2,0xe6,0xe6,0x01,0x4c,0x00,0x01,0xfe,0xc0,0x04,0xb2,0x01,0x42,0x05,0xb2,0x00,0x13,0x00,0x1e,0x40,0x0e,0x13,0xc4,0x00,0x09,0xc4,0x0a,0x13,0x07,0xda,0x0d,0x11,0xda,0x09,0x03,0x00,0x2f,0xc6,0xfd, 0xdc,0xed,0xc6,0x01,0x2f,0xe1,0xd4,0xe1,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x42,0x60,0x52,0x47,0x5b,0x4d,0x2a,0x59,0x5e,0x61,0x56,0x41,0x54,0x4a,0x36,0x53,0x05,0xb2,0x69,0x85,0x34,0x2b,0x71,0x6a,0x82,0x34,0x2c,0x74,0x00,0x00,0x01,0xff,0x02, 0x04,0xc2,0x00,0xfe,0x05,0x2f,0x00,0x03,0x00,0x0e,0xb4,0x00,0x01,0x02,0xe2,0x01,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x13,0x21,0x35,0x21,0xfe,0xfe,0x04,0x01,0xfc,0x04,0xc2,0x6d,0x00,0x01,0xfe,0x58,0x05,0x74,0x01,0xaa,0x05,0xec,0x00,0x03,0x00,0x0d,0xb4,0x02,0xda,0x01,0x00,0x01,0x2f,0x2f,0x00,0x2f,0xed,0x31,0x30,0x01, 0x21,0x35,0x21,0x01,0xaa,0xfc,0xae,0x03,0x52,0x05,0x74,0x78,0x00,0x01,0xfe,0xee,0x04,0xc2,0x01,0x12,0x05,0xbe,0x00,0x0c,0x00,0x1d,0x40,0x0d,0x0c,0xc4,0x00,0xc0,0x07,0xc4,0x06,0x0c,0x06,0x80,0x09,0xdb,0x03,0x00,0x2f,0xed,0x1a,0xdc,0xc4,0x01,0x2f,0xe1,0x1a,0xdc,0xe1,0x31,0x30,0x01,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16, 0x33,0x32,0x36,0x37,0x01,0x12,0x0a,0x9c,0x70,0x75,0x95,0x04,0x64,0x0c,0xa0,0x44,0x61,0x09,0x05,0xbe,0x70,0x8c,0x8a,0x72,0x9b,0x54,0x47,0x00,0x00,0x01,0xff,0x9e,0x04,0xc2,0x00,0x62,0x05,0x85,0x00,0x0b,0x00,0x0f,0xb5,0x09,0xc0,0x03,0x06,0xc1,0x00,0x00,0x2f,0xed,0x01,0x2f,0xe1,0x31,0x30,0x11,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x28,0x3a,0x3a,0x28,0x29,0x39,0x39,0x04,0xc2,0x3a,0x29,0x29,0x37,0x37,0x29,0x29,0x3a,0x00,0x02,0xfe,0xdd,0x04,0xc2,0x01,0x25,0x05,0x87,0x00,0x0b,0x00,0x17,0x00,0x1a,0x40,0x0c,0x06,0x00,0x12,0xc1,0x0c,0x09,0xc0,0x03,0x0f,0xc0,0x03,0x15,0x2f,0xc6,0xe1,0x10,0xe1,0x00,0x2f,0xed,0x39,0x39,0x31,0x30, 0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xc2,0x28,0x3a,0x38,0x28,0x2a,0x3b,0x39,0xfe,0x56,0x29,0x3c,0x39,0x2a,0x29,0x3b,0x39,0x04,0xc2,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39,0x2a,0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0x00,0x02,0xff,0x33, 0x04,0x98,0x00,0xcf,0x06,0x1c,0x00,0x0b,0x00,0x16,0x00,0x2a,0x40,0x18,0x14,0xc4,0x30,0x09,0x80,0x09,0xd0,0x09,0xe0,0x09,0x04,0x09,0xc0,0x0f,0xc4,0x03,0x0c,0xc5,0x40,0x06,0xc0,0x11,0xc5,0x00,0x00,0x2f,0xed,0x1a,0xdc,0x1a,0xed,0x01,0x2f,0xe1,0x1a,0xdc,0x71,0xe1,0x31,0x30,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x59,0x72,0x76,0x5b,0x59,0x72,0x7a,0x57,0x31,0x3f,0x70,0x31,0x41,0x41,0x04,0x98,0x6b,0x53,0x58,0x6e,0x6c,0x54,0x54,0x70,0x01,0x33,0x41,0x30,0x70,0x40,0x30,0x31,0x40,0x00,0x00,0x02,0xfe,0xdd,0x04,0xc2,0x01,0x25,0x06,0x00,0x00,0x03,0x00,0x07,0x00,0x2b, 0x40,0x14,0x00,0x0e,0x0f,0x02,0x01,0x10,0x03,0x02,0x06,0x80,0x06,0x04,0x42,0x04,0x06,0x03,0x02,0x07,0x80,0x06,0x00,0x2f,0x1a,0xcd,0x39,0x39,0x01,0x2f,0xcd,0x2b,0x01,0x1a,0x18,0x10,0xdc,0x5f,0x5e,0x5d,0xe9,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x01,0x25,0xf6,0x60,0xd1,0x73,0xef,0x61,0xcf,0x06,0x00,0xfe,0xc2, 0x01,0x3e,0xfe,0xc2,0x01,0x3e,0x00,0x01,0xfe,0xe8,0x04,0xc2,0x01,0x18,0x06,0x0c,0x00,0x06,0x00,0x11,0xb5,0x00,0xc0,0x03,0x03,0x80,0x02,0x00,0x2f,0x1a,0xcd,0x01,0x2f,0x1a,0xcc,0x31,0x30,0x01,0x03,0x23,0x03,0x33,0x17,0x37,0x01,0x18,0xd4,0x86,0xd6,0x72,0xa4,0xa4,0x06,0x0c,0xfe,0xb6,0x01,0x4a,0xe5,0xe5,0x00,0x01,0xff,0xcb, 0x04,0x96,0x00,0x35,0x06,0x00,0x00,0x03,0x00,0x0e,0xb5,0x01,0x02,0x01,0x00,0xfc,0x01,0x2f,0xe1,0x00,0x3f,0xcd,0x31,0x30,0x13,0x23,0x11,0x33,0x35,0x6a,0x6a,0x04,0x96,0x01,0x6a,0x00,0x00,0x02,0xff,0x58,0x04,0x96,0x00,0xa8,0x06,0x00,0x00,0x03,0x00,0x07,0x00,0x1a,0x40,0x0c,0x02,0x01,0x05,0x06,0x01,0x00,0xfc,0x01,0x01,0x04, 0xfc,0x05,0x2f,0xf1,0xca,0x2f,0xe1,0x00,0x3f,0xcd,0x39,0x39,0x31,0x30,0x13,0x23,0x11,0x33,0x03,0x23,0x11,0x33,0xa8,0x6a,0x6a,0xe6,0x6a,0x6a,0x04,0x96,0x01,0x6a,0xfe,0x96,0x01,0x6a,0x00,0x02,0xfe,0xdd,0x04,0xc2,0x01,0x25,0x06,0x00,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x17,0x00,0x0e,0x0f,0x02,0x01,0x10,0x03,0x02,0x06,0x80, 0x06,0x04,0x42,0x60,0x04,0x01,0x04,0x06,0x07,0x04,0x03,0x80,0x00,0x00,0x2f,0x1a,0xcd,0x39,0x39,0x01,0x2f,0xcd,0x5d,0x2b,0x01,0x1a,0x18,0x10,0xdc,0x5f,0x5e,0x5d,0xe1,0x31,0x30,0x01,0x23,0x03,0x33,0x03,0x23,0x03,0x33,0x01,0x25,0x61,0xef,0x81,0x23,0x60,0xf6,0x85,0x04,0xc2,0x01,0x3e,0xfe,0xc2,0x01,0x3e,0x00,0x02,0xfe,0xee, 0x04,0xc2,0x01,0x12,0x06,0x68,0x00,0x0b,0x00,0x18,0x00,0x26,0x40,0x13,0x06,0xc1,0x00,0x0c,0x12,0x15,0xdb,0x0f,0x0c,0xfc,0x18,0x18,0x09,0x12,0xfc,0x13,0x09,0xc0,0x03,0x2f,0xe1,0xde,0xe1,0x10,0xca,0x2f,0xe1,0x00,0x2f,0xfd,0xd4,0x32,0xd4,0xed,0x31,0x30,0x11,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x06, 0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x28,0x3a,0x3a,0x28,0x29,0x39,0x39,0xe9,0x0a,0x9c,0x70,0x75,0x95,0x04,0x64,0x0c,0xa0,0x44,0x61,0x09,0x05,0xa6,0x39,0x29,0x2a,0x36,0x37,0x29,0x28,0x3a,0x18,0x70,0x8c,0x8a,0x72,0x9b,0x54,0x47,0x00,0x00,0x01,0xfe,0xee,0x04,0xc2,0x01,0x12,0x05,0xbe,0x00,0x0c,0x00,0x18, 0x40,0x0b,0x0a,0xdb,0x04,0x00,0x07,0x00,0xfc,0x01,0x06,0xfc,0x07,0x2f,0xe1,0xd4,0xe1,0x00,0x2f,0x33,0xd4,0xed,0x31,0x30,0x01,0x23,0x26,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x12,0x66,0x09,0x61,0x44,0xa0,0x0c,0x64,0x04,0x95,0x75,0x71,0x9b,0x04,0xc2,0x48,0x54,0x9c,0x72,0x8a,0x8a,0x00,0x00,0x01,0xff,0x8c, 0x04,0x7b,0x00,0x77,0x06,0x23,0x00,0x0d,0x00,0x27,0xb9,0x00,0x00,0xff,0xe8,0x40,0x13,0x09,0x0d,0x48,0x07,0xfb,0x02,0x0d,0xfa,0x00,0x40,0x09,0x0d,0x48,0x00,0x00,0x02,0x04,0xaf,0x0a,0x2f,0xf1,0x39,0xc2,0x2f,0x2b,0x00,0x3f,0xd4,0xed,0x31,0x30,0x2b,0x13,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x77, 0x69,0x10,0x6e,0x3a,0x2c,0x35,0x45,0x71,0x53,0x05,0xe4,0x38,0x68,0x08,0x5d,0x2a,0x3a,0x47,0x3a,0x58,0xa7,0x28,0x00,0x01,0xff,0x8c,0x03,0xf8,0x00,0x77,0x05,0xa0,0x00,0x0e,0x00,0x25,0x40,0x0b,0x01,0x18,0x09,0x0d,0x48,0x00,0x03,0xfb,0x09,0x03,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x0d,0x48,0x01,0x03,0x0c,0xaf,0x06,0x2f,0xe1,0x39, 0xc6,0x2b,0x00,0x3f,0xfd,0xc4,0x31,0x30,0x2b,0x03,0x27,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x4e,0x26,0x68,0x10,0x30,0x3c,0x38,0x2c,0x35,0x46,0x72,0x03,0xf8,0x40,0x36,0x69,0x01,0x39,0x2b,0x2a,0x3a,0x48,0x3a,0x57,0xa7,0x00,0x00,0x01,0xff,0x8c,0x03,0xf8,0x00,0x77,0x05,0xa0,0x00,0x0e,0x00,0x24, 0x40,0x15,0x00,0x18,0x09,0x0d,0x48,0x01,0x0d,0xfb,0x07,0xfa,0x00,0x40,0x09,0x0d,0x48,0x00,0x00,0x0d,0x0a,0xaf,0x04,0x2f,0xf1,0x39,0xc2,0x2f,0x2b,0x00,0x3f,0xfd,0xc4,0x31,0x30,0x2b,0x13,0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x77,0x27,0x54,0x70,0x45,0x35,0x2c,0x38,0x3c,0x30,0x10,0x04,0x38, 0x40,0x29,0xa6,0x57,0x3b,0x47,0x3a,0x2a,0x2b,0x39,0x01,0x69,0x00,0x01,0x00,0x2f,0x03,0xf8,0x01,0x1a,0x05,0xa0,0x00,0x0e,0x00,0x25,0x40,0x0b,0x01,0x18,0x09,0x0d,0x48,0x00,0x03,0xfb,0x09,0x03,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x0d,0x48,0x01,0x03,0x0c,0xaf,0x06,0x2f,0xe1,0x39,0xc6,0x2b,0x00,0x3f,0xfd,0xc4,0x31,0x30,0x2b,0x13, 0x27,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x56,0x27,0x69,0x10,0x30,0x3c,0x38,0x2c,0x35,0x45,0x70,0x03,0xf8,0x40,0x36,0x69,0x01,0x39,0x2b,0x2a,0x3a,0x47,0x3b,0x57,0xa6,0x00,0x00,0x01,0xff,0x3e,0xfe,0x42,0x00,0xc2,0xff,0x89,0x00,0x03,0x00,0x17,0x40,0x0c,0x00,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03, 0x03,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x13,0x23,0x01,0x33,0xc2,0x7e,0xfe,0xfa,0xa8,0xfe,0x42,0x01,0x47,0x00,0x01,0xff,0x3e,0xfe,0x42,0x00,0xc2,0xff,0x89,0x00,0x03,0x00,0x17,0x40,0x0c,0x02,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x17, 0x01,0x23,0x13,0xc2,0xfe,0xfa,0x7e,0xde,0x77,0xfe,0xb9,0x01,0x47,0x00,0x00,0x01,0xff,0x48,0xfe,0x58,0x00,0xb8,0xff,0xc2,0x00,0x07,0x00,0x2a,0x40,0x17,0x01,0x0e,0x02,0xfd,0x05,0x40,0x05,0x06,0x42,0x05,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0xfc,0x05,0x02,0x04,0x2f,0xdd,0x32,0xe1,0x00,0x2f,0x5d,0xcd,0x2b,0x00,0x1a, 0x18,0x10,0xfd,0xed,0x31,0x30,0x13,0x23,0x35,0x21,0x35,0x21,0x35,0x33,0xb8,0x6a,0xfe,0xfa,0x01,0x06,0x6a,0xfe,0x58,0x7f,0x6d,0x7e,0x00,0x01,0xff,0x48,0xfe,0x58,0x00,0xb8,0xff,0xc2,0x00,0x07,0x00,0x2c,0x40,0x18,0x02,0x0e,0x01,0xfd,0x06,0x40,0x06,0x05,0x42,0x06,0x0f,0x05,0x1f,0x05,0x2f,0x05,0x03,0x05,0x03,0xfc,0x01,0x01, 0x06,0x07,0x2f,0xcd,0x32,0x10,0xe1,0x00,0x2f,0x5d,0xcd,0x2b,0x00,0x1a,0x18,0x10,0xfd,0xed,0x31,0x30,0x13,0x21,0x15,0x23,0x11,0x33,0x15,0x21,0xb8,0xfe,0xfa,0x6a,0x6a,0x01,0x06,0xfe,0xd7,0x7f,0x01,0x6a,0x7e,0x00,0x00,0x01,0xff,0x16,0x04,0x96,0x00,0xea,0x06,0x68,0x00,0x05,0x00,0x14,0x40,0x09,0x00,0x03,0xfd,0x04,0x01,0x00, 0xfc,0x02,0x03,0x2f,0xdd,0xe1,0x00,0x3f,0xed,0xc4,0x31,0x30,0x13,0x23,0x11,0x21,0x35,0x21,0xea,0x6a,0xfe,0x96,0x01,0xd4,0x04,0x96,0x01,0x6a,0x68,0x00,0x00,0x01,0xff,0x52,0x04,0x96,0x00,0xae,0x06,0x0e,0x00,0x0b,0x00,0x12,0xb7,0x05,0x01,0xda,0x00,0x08,0xc2,0x03,0x00,0x2f,0xd4,0xe1,0x00,0x2f,0xed,0xc4,0x31,0x30,0x03,0x37, 0x32,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x23,0xae,0x02,0xd5,0x15,0x88,0x12,0x8e,0x78,0x04,0x96,0x74,0x82,0x48,0x3a,0x37,0x50,0x6c,0x85,0x00,0x01,0xff,0xa6,0xfe,0x5c,0x00,0x5a,0xff,0xc8,0x00,0x0b,0x00,0x28,0x40,0x16,0x0b,0xcb,0x40,0x00,0xc0,0x07,0xcb,0x40,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0x06,0x80,0x09, 0xc9,0x03,0x2f,0xe1,0x1a,0xcc,0x32,0x00,0x2f,0x5d,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x15,0x22,0x15,0x14,0x33,0x5a,0x4d,0x67,0x66,0x4e,0x5e,0x5e,0xfe,0x5c,0x69,0x4d,0x4d,0x69,0x5e,0x58,0x5a,0x00,0x01,0xff,0x4c,0xfe,0x56,0x00,0xb6,0xff,0xc6,0x00,0x07,0x00,0x22,0x40,0x10,0x05,0x00, 0xfd,0x02,0x40,0x03,0x06,0x0e,0x05,0xfc,0x02,0x02,0x01,0x42,0x02,0x01,0x2f,0xcd,0x2b,0x01,0x10,0xf1,0xe1,0x00,0x18,0x2f,0x1a,0xdd,0xed,0x33,0x31,0x30,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0xb4,0x7f,0x6d,0x7e,0xfe,0x56,0x6a,0x01,0x06,0xfe,0xfa,0x6a,0x00,0x01,0xff,0x4c,0xfe,0x56,0x00,0xb6,0xff,0xc6,0x00,0x07,0x00,0x22, 0x40,0x10,0x04,0x02,0x06,0xfd,0x40,0x07,0x01,0x0e,0x02,0xfc,0x05,0x05,0x06,0x42,0x05,0x06,0x2f,0xcd,0x2b,0x01,0x10,0xf1,0xe1,0x00,0x18,0x2f,0x1a,0xfd,0x32,0xc6,0x31,0x30,0x17,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0xb6,0x7e,0x6d,0x7f,0x3a,0x6a,0xfe,0xfa,0x01,0x06,0x6a,0x00,0x00,0x01,0xff,0x4c,0xfe,0x5e,0x00,0xb6,0xff,0xc6, 0x00,0x0b,0x00,0x38,0x40,0x1f,0x03,0x0e,0x0a,0x01,0x04,0xfd,0x07,0x0e,0x40,0x0f,0x08,0x1f,0x08,0x2f,0x08,0x03,0x09,0x03,0x08,0x00,0x0e,0x01,0x04,0x05,0x42,0x05,0x0a,0x07,0x01,0xfc,0x04,0x2f,0xe1,0x39,0x39,0xcd,0x2b,0x01,0x10,0xe1,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0x1a,0xfd,0xfd,0x39,0x39,0xed,0x31,0x30,0x13,0x23,0x15,0x23, 0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0xb6,0x7e,0x6d,0x7f,0x7f,0x6d,0x7e,0xfe,0xdd,0x7f,0x7f,0x6b,0x7e,0x7e,0xff,0xff,0xff,0x03,0xff,0x53,0x00,0xff,0xff,0xbf,0x00,0x07,0x06,0x9a,0xfe,0xc5,0xfd,0x5f,0x00,0x01,0xff,0x1a,0xfe,0x96,0x00,0xe6,0x00,0x35,0x00,0x0a,0x00,0x12,0xb7,0x08,0x91,0x03,0x0a,0x00,0x7e,0x0a,0x06,0x2f, 0xd6,0xe1,0x00,0x2f,0xd4,0xed,0x31,0x30,0x37,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0xe6,0xb3,0x9f,0x42,0x38,0x33,0x3f,0xb2,0x35,0xbd,0xe2,0x14,0xa0,0x1d,0x01,0x08,0x00,0x00,0x01,0xff,0x1a,0xfe,0x96,0x00,0xe6,0x00,0x35,0x00,0x0a,0x00,0x15,0x40,0x09,0x03,0x91,0x08,0x00,0x05,0x05,0x01,0x7e,0x00,0x2f,0xf1,0xc2, 0x2f,0x00,0x2f,0xd4,0xed,0x31,0x30,0x27,0x33,0x10,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0xe6,0xa8,0xb2,0x3f,0x33,0x38,0x42,0x9f,0xb3,0x35,0xfe,0xf8,0x1d,0xa0,0x14,0xe2,0x00,0x02,0xfe,0xdd,0xfe,0xc4,0x01,0x25,0xff,0x89,0x00,0x0b,0x00,0x17,0x00,0x1a,0x40,0x0c,0x06,0x00,0x0c,0xc1,0x12,0x09,0xc0,0x03,0x0f,0xc0,0x03,0x15, 0x2f,0xc6,0xe1,0x10,0xe1,0x00,0x2f,0xed,0x39,0x39,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xc2,0x28,0x3a,0x38,0x28,0x2a,0x3b,0x39,0xfe,0x56,0x29,0x3c,0x39,0x2a,0x29,0x3b,0x39,0xfe,0xc4,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39, 0x2a,0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0xff,0xff,0xff,0x35,0xfe,0x7e,0x00,0xd1,0x00,0x02,0x00,0x07,0x00,0xdc,0xfe,0xe3,0xf9,0xe6,0x00,0x01,0xff,0x9c,0xfe,0x62,0x00,0x64,0xff,0x89,0x00,0x0b,0x00,0x3b,0xb5,0x01,0x18,0x09,0x12,0x48,0x00,0xb8,0xff,0xc0,0xb4,0x13,0x16,0x48,0x00,0x03,0xb8,0x01,0x02,0x40,0x09,0x0f,0x07,0x1f, 0x07,0x2f,0x07,0x03,0x07,0x01,0xb8,0xff,0xc0,0xb5,0x09,0x12,0x48,0x01,0x03,0x0a,0xb9,0x01,0x01,0x00,0x05,0x2f,0xe1,0x39,0xc4,0x2b,0x00,0x2f,0x5d,0xfd,0xc4,0x2b,0x31,0x30,0x2b,0x03,0x27,0x36,0x37,0x22,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x4a,0x16,0x56,0x06,0x60,0x5a,0x30,0x3e,0xfe,0x62,0x36,0x16,0x3a,0x50,0x51,0x41,0x30, 0x91,0x00,0xff,0xff,0xff,0x56,0xfe,0x50,0x00,0xaa,0x00,0x00,0x00,0x07,0x00,0xdd,0xff,0x23,0x00,0x00,0xff,0xff,0xff,0x5d,0xfe,0x70,0x00,0x71,0x00,0x00,0x00,0x07,0x00,0xdf,0xff,0x1f,0x00,0x00,0x00,0x01,0xff,0xcb,0xfe,0x1e,0x00,0x35,0xff,0x89,0x00,0x03,0x00,0x16,0x40,0x0c,0x01,0x0f,0x02,0x1f,0x02,0x2f,0x02,0x03,0x02,0x00, 0xfc,0x01,0x2f,0xe1,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x13,0x23,0x11,0x33,0x35,0x6a,0x6a,0xfe,0x1e,0x01,0x6b,0x00,0x00,0x01,0xfe,0x9c,0xfe,0x5c,0x01,0x64,0xff,0x89,0x00,0x07,0x00,0x22,0x40,0x13,0x00,0x05,0x80,0x03,0xfd,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0xfc,0x01,0x04,0xfc,0x05,0x2f,0xe1,0xd4,0xe1,0x00,0x2f,0x5d, 0xed,0x1a,0xcd,0x32,0x31,0x30,0x01,0x23,0x35,0x21,0x15,0x23,0x11,0x21,0x01,0x64,0x68,0xfe,0x08,0x68,0x02,0xc8,0xfe,0x5c,0xc5,0xc5,0x01,0x2d,0x00,0x01,0xfe,0xb1,0xfe,0xbc,0x01,0x4f,0xff,0x89,0x00,0x14,0x00,0x44,0x40,0x26,0x00,0x05,0x10,0x03,0x0a,0x12,0x03,0x0d,0xc5,0x40,0x07,0x80,0x0f,0x0a,0x1f,0x0a,0x2f,0x0a,0x03,0x09, 0x03,0x0a,0x14,0xff,0x00,0x0e,0x10,0x0b,0xff,0x0a,0x0a,0x0f,0x42,0x0a,0x80,0x10,0xfe,0x0f,0x2f,0xe1,0x1a,0xcc,0x2b,0x01,0x10,0xe1,0x10,0xf0,0xe1,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0x1a,0xdc,0x1a,0xed,0x39,0x39,0x12,0x17,0x39,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x33,0x14,0x33,0x32,0x35,0x33,0x14, 0x33,0x32,0x35,0x01,0x4f,0x6a,0x57,0x5a,0x34,0x35,0x5b,0x57,0x68,0x61,0x5f,0x69,0x4c,0x6a,0x5e,0x77,0x59,0x74,0x44,0x44,0x72,0x5b,0x75,0x75,0x75,0x75,0x00,0x01,0xfe,0xe8,0xfe,0x40,0x01,0x18,0xff,0x89,0x00,0x06,0x00,0x1a,0x40,0x0d,0x00,0xc0,0x03,0x02,0x80,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x00,0x2f,0x5d,0x1a,0xcd, 0x01,0x2f,0x1a,0xcc,0x31,0x30,0x05,0x03,0x23,0x03,0x33,0x17,0x37,0x01,0x18,0xd4,0x86,0xd6,0x72,0xa4,0xa4,0x77,0xfe,0xb7,0x01,0x49,0xe5,0xe5,0x00,0x01,0xfe,0xe8,0xfe,0x3e,0x01,0x1a,0xff,0x89,0x00,0x06,0x00,0x1a,0x40,0x0d,0x00,0xc0,0x04,0x04,0x80,0x0f,0x05,0x1f,0x05,0x2f,0x05,0x03,0x05,0x00,0x2f,0x5d,0x1a,0xcd,0x01,0x2f, 0x1a,0xcc,0x31,0x30,0x01,0x23,0x27,0x07,0x23,0x13,0x33,0x01,0x1a,0x78,0xa4,0xa6,0x70,0xd6,0x86,0xfe,0x3e,0xe5,0xe5,0x01,0x4b,0x00,0x00,0x01,0xfe,0xee,0xfe,0x8e,0x01,0x12,0xff,0x89,0x00,0x0c,0x00,0x29,0x40,0x16,0x0c,0xc4,0x00,0xc0,0x07,0xc4,0x06,0x0c,0x06,0x09,0xdb,0x40,0x03,0x80,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06, 0x00,0x2f,0x5d,0x1a,0xdc,0x1a,0xed,0x10,0xc4,0x01,0x2f,0xe1,0x1a,0xdc,0xe1,0x31,0x30,0x05,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x01,0x12,0x0a,0x9b,0x71,0x75,0x95,0x04,0x64,0x0c,0xa0,0x44,0x61,0x09,0x77,0x72,0x89,0x89,0x72,0x9b,0x54,0x47,0xff,0xff,0xfe,0xe9,0xff,0x13,0x01,0x19,0x00,0x01,0x00,0x07, 0x04,0x2a,0xfd,0xa9,0xfa,0x6d,0x00,0x01,0xfe,0xc0,0xfe,0x9e,0x01,0x42,0xff,0x9e,0x00,0x13,0x00,0x22,0x40,0x11,0x13,0xc4,0x00,0x09,0xc4,0x0a,0x09,0x11,0xda,0x03,0x07,0xda,0x0d,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xd4,0xfd,0xdc,0xed,0xc6,0x01,0x2f,0xe1,0xd4,0xe1,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15, 0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x42,0x60,0x52,0x47,0x5b,0x4d,0x2a,0x59,0x5e,0x61,0x56,0x41,0x54,0x4a,0x36,0x53,0x62,0x69,0x85,0x34,0x2a,0x70,0x69,0x82,0x33,0x2d,0x75,0xff,0xff,0xff,0x05,0xff,0x51,0x01,0x01,0xff,0xbe,0x00,0x07,0x00,0xd9,0xfe,0xc7,0xfa,0x8f,0x00,0x01,0xfe,0x57,0xfe,0xd7,0x01,0xa9, 0xff,0x4e,0x00,0x03,0x00,0x0d,0xb4,0x01,0xda,0x02,0x00,0x01,0x2f,0x2f,0x00,0x2f,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x01,0xa9,0xfc,0xae,0x03,0x52,0xfe,0xd7,0x77,0xff,0xff,0xfe,0x57,0xfd,0xfe,0x01,0xa9,0xff,0x62,0x00,0x07,0x01,0x35,0xfe,0x57,0x00,0x00,0x00,0x01,0xfe,0xc0,0x01,0x9e,0x01,0x42,0x02,0x9e,0x00,0x13,0x00,0x1e, 0x40,0x0e,0x13,0xc4,0x00,0x09,0xc4,0x0a,0x13,0x07,0xda,0x0d,0x11,0xda,0x09,0x03,0x00,0x2f,0xc6,0xfd,0xdc,0xed,0xc6,0x01,0x2f,0xe1,0xd4,0xe1,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x42,0x60,0x52,0x47,0x5b,0x4d,0x2a,0x59,0x5e,0x61,0x56,0x41,0x54, 0x4a,0x36,0x53,0x02,0x9e,0x69,0x85,0x34,0x2a,0x70,0x69,0x82,0x33,0x2d,0x75,0x00,0x00,0x01,0xff,0x02,0x01,0xe6,0x00,0xfe,0x02,0x52,0x00,0x03,0x00,0x0e,0xb4,0x00,0x01,0x02,0xe2,0x01,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x13,0x21,0x35,0x21,0xfe,0xfe,0x04,0x01,0xfc,0x01,0xe6,0x6c,0xff,0xff,0xfe,0x58,0xff,0xc5,0x01,0xaa, 0x00,0x3d,0x00,0x07,0x01,0x95,0xfe,0x58,0xfa,0x51,0x00,0x01,0xfe,0x66,0x00,0x77,0x01,0x9c,0x03,0xc2,0x00,0x03,0x00,0x2a,0xb6,0x03,0x02,0x01,0x00,0x03,0x00,0x01,0xb8,0x01,0x00,0x40,0x0a,0x02,0x03,0x14,0x02,0x03,0x01,0x02,0x00,0x00,0x02,0x2f,0xcd,0x00,0x2f,0x2f,0xc1,0x87,0x05,0x2b,0x10,0x00,0xc1,0x87,0x05,0x7d,0x10,0xc4, 0x31,0x30,0x01,0x01,0x23,0x01,0x01,0x9c,0xfd,0x50,0x86,0x02,0xae,0x03,0xc2,0xfc,0xb5,0x03,0x4b,0x00,0x00,0x01,0xfe,0x70,0xff,0x12,0x01,0x92,0x05,0x9a,0x00,0x03,0x00,0x2b,0xb6,0x03,0x02,0x01,0x00,0x03,0x00,0x01,0xb8,0x01,0x00,0x40,0x0b,0x02,0x03,0x14,0x02,0x03,0x01,0x02,0x00,0x03,0x00,0x02,0x2f,0xcd,0x00,0x3f,0x2f,0xc1, 0x87,0x05,0x2b,0x10,0x00,0xc1,0x87,0x05,0x7d,0x10,0xc4,0x31,0x30,0x01,0x01,0x23,0x01,0x01,0x92,0xfd,0x50,0x72,0x02,0xae,0x05,0x9a,0xf9,0x78,0x06,0x88,0x00,0x01,0xff,0xa6,0xfe,0x5c,0x00,0x5a,0xff,0xc8,0x00,0x0b,0x00,0x2a,0x40,0x17,0x01,0xcb,0x40,0x00,0xc0,0x05,0xcb,0x40,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0x06, 0x06,0x80,0x09,0xc9,0x03,0x2f,0xf1,0x1a,0xc8,0x2f,0x32,0x00,0x2f,0x5d,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x03,0x35,0x32,0x35,0x34,0x23,0x35,0x32,0x16,0x15,0x14,0x06,0x5a,0x5e,0x5e,0x4f,0x65,0x67,0xfe,0x5c,0x5c,0x5a,0x58,0x5e,0x67,0x4f,0x4d,0x69,0x00,0x01,0xfe,0x9c,0xfe,0x5c,0x01,0x64,0xff,0x89,0x00,0x07,0x00,0x24, 0x40,0x14,0x04,0xfd,0x40,0x01,0x80,0x06,0x0f,0x02,0x1f,0x02,0x2f,0x02,0x03,0x02,0x07,0xfc,0x06,0x03,0xfc,0x02,0x2f,0xe1,0xd4,0xe1,0x00,0x2f,0x5d,0x33,0x1a,0xdd,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x15,0x21,0x35,0x33,0x01,0x64,0xfd,0x38,0x68,0x01,0xf8,0x68,0xfe,0x5c,0x01,0x2d,0xc5,0xc5,0x00,0x02,0xff,0x44,0xfe,0x10, 0x00,0xbc,0xff,0x89,0x00,0x03,0x00,0x07,0x00,0x23,0x40,0x14,0x01,0xc4,0x2f,0x07,0x01,0x07,0x06,0xc4,0x02,0x40,0x09,0x0d,0x48,0x02,0x03,0xc4,0x05,0x06,0xc4,0x02,0x2f,0xe1,0xdd,0xe1,0x00,0x2f,0x2b,0xed,0xdd,0x5d,0xed,0x31,0x30,0x13,0x21,0x11,0x21,0x03,0x35,0x23,0x15,0xbc,0xfe,0x88,0x01,0x78,0x5a,0xc4,0xfe,0x10,0x01,0x79, 0xfe,0xe1,0xc5,0xc5,0x00,0x01,0xfe,0xa5,0xfe,0xa8,0x01,0x5b,0xff,0x89,0x00,0x16,0x00,0x45,0x40,0x25,0x00,0x0d,0x0d,0x12,0x07,0x80,0x14,0x03,0x0a,0xc5,0x40,0x0f,0x10,0x1f,0x10,0x2f,0x10,0x03,0x09,0x03,0x10,0x01,0xff,0x00,0x0e,0x06,0x0c,0xff,0x0d,0x0d,0x07,0x42,0x0d,0x80,0x06,0xfe,0x07,0x2f,0xe1,0x1a,0xce,0x2b,0x01,0x10, 0xe1,0x10,0xf2,0xe1,0x00,0x18,0x2f,0x5f,0x5e,0x5d,0x1a,0xed,0x39,0x39,0x1a,0xcc,0x39,0x39,0x7c,0x2f,0x33,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x16,0x01,0x5b,0x62,0x11,0x4f,0x32,0x40,0x4e,0x41,0x32,0x4e,0x11,0x62,0x0b,0x6e,0x48,0x70,0x2a, 0x28,0x72,0x46,0x70,0xfe,0xee,0x43,0x55,0x34,0x35,0x54,0x43,0x43,0x58,0x64,0x64,0x5a,0x00,0x00,0x01,0xff,0x30,0x04,0xc2,0x00,0xd2,0x06,0x65,0x00,0x0b,0x00,0x09,0xb1,0x07,0x04,0x19,0x2f,0x00,0x2f,0x31,0x30,0x13,0x07,0x17,0x07,0x27,0x07,0x27,0x37,0x27,0x37,0x17,0x37,0xd2,0x85,0x85,0x4c,0x86,0x85,0x4b,0x85,0x85,0x4c,0x86, 0x85,0x06,0x1a,0x86,0x84,0x4e,0x86,0x86,0x4c,0x85,0x85,0x4d,0x85,0x85,0x00,0x01,0xff,0x9e,0x05,0x08,0x00,0x62,0x07,0x1c,0x00,0x11,0x00,0x27,0x40,0x13,0x0a,0xc5,0x40,0x09,0xc0,0x01,0xc5,0x40,0x00,0x09,0x03,0xc4,0x10,0x00,0x80,0x0c,0xc4,0x07,0x00,0x2f,0xd4,0xe1,0x1a,0x10,0xdd,0xe1,0xc4,0x00,0x2f,0x1a,0xed,0x1a,0xdc,0x1a, 0xed,0x31,0x30,0x03,0x35,0x32,0x35,0x34,0x27,0x26,0x35,0x34,0x33,0x15,0x22,0x15,0x14,0x17,0x16,0x15,0x14,0x62,0x6e,0x35,0x35,0xc0,0x6a,0x35,0x35,0x05,0x08,0x5e,0x42,0x1c,0x42,0x41,0x36,0x9f,0x5e,0x41,0x1b,0x40,0x40,0x3a,0xa0,0x00,0x00,0x02,0xfe,0x57,0x05,0x74,0x01,0xa9,0x07,0x04,0x00,0x03,0x00,0x07,0x00,0x19,0x40,0x0b, 0x02,0xda,0x01,0x06,0xda,0x05,0x07,0x06,0x01,0x00,0x01,0x2f,0x2f,0x12,0x39,0x39,0x00,0x2f,0xfd,0xd6,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x01,0xa9,0xfc,0xae,0x03,0x52,0xfc,0xae,0x03,0x52,0x06,0x8e,0x76,0xfe,0x70,0x78,0x00,0x00,0x01,0xfe,0x70,0x04,0xc2,0xff,0xf6,0x06,0x0a,0x00,0x03,0x00,0x0e,0xb4,0x03, 0x80,0x01,0x02,0x00,0x2f,0xcd,0x00,0x2f,0x1a,0xcd,0x31,0x30,0x03,0x23,0x01,0x33,0x0a,0x7f,0xfe,0xf9,0xa8,0x04,0xc2,0x01,0x48,0x00,0x00,0x01,0x00,0x0a,0x04,0xc2,0x01,0x90,0x06,0x0a,0x00,0x03,0x00,0x0e,0xb4,0x03,0x02,0x00,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0xcd,0x31,0x30,0x01,0x01,0x23,0x13,0x01,0x90,0xfe,0xf9,0x7f,0xe0, 0x06,0x0a,0xfe,0xb8,0x01,0x48,0xff,0xff,0xfe,0xc0,0x04,0xb2,0x01,0x41,0x05,0xb2,0x00,0x07,0x00,0xd8,0xfe,0x9d,0x00,0x00,0x00,0x01,0xff,0x9c,0x04,0xc2,0x00,0x64,0x05,0xea,0x00,0x0b,0x00,0x33,0xb5,0x01,0x18,0x09,0x12,0x48,0x00,0xb8,0xff,0xc0,0xb4,0x13,0x16,0x48,0x00,0x03,0xb8,0x01,0x02,0xb2,0x07,0x00,0x01,0xb8,0xff,0xc0, 0xb5,0x09,0x12,0x48,0x01,0x03,0x0a,0xb9,0x01,0x01,0x00,0x05,0x2f,0xe1,0x39,0xc4,0x2b,0x00,0x3f,0xfd,0xc4,0x2b,0x31,0x30,0x2b,0x03,0x27,0x36,0x37,0x22,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x4a,0x16,0x56,0x06,0x60,0x5a,0x30,0x3e,0x04,0xc2,0x36,0x16,0x3a,0x50,0x52,0x42,0x2f,0x91,0x00,0x00,0x03,0xfe,0xaa,0x04,0x96,0x01,0x56, 0x06,0x00,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x2c,0x40,0x15,0x0a,0x04,0x16,0xc1,0x40,0x10,0x10,0x03,0x80,0x02,0x13,0xc0,0x19,0x02,0x40,0x0d,0xc0,0x07,0x00,0x80,0x02,0x2f,0x1a,0xdd,0xd4,0xe1,0x1a,0x10,0xde,0xe1,0x00,0x2f,0x1a,0xcd,0x39,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x13,0x03,0x23,0x13,0x13,0x22,0x26,0x35,0x34,0x36, 0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xa8,0xb0,0x5e,0x66,0xf2,0x29,0x37,0x38,0x28,0x29,0x3b,0x3a,0xfd,0xf0,0x28,0x3a,0x3a,0x28,0x2a,0x3a,0x3a,0x06,0x00,0xfe,0x96,0x01,0x6a,0xfe,0xba,0x36,0x2a,0x2a,0x39,0x39,0x2a,0x28,0x38,0x37,0x29,0x2a,0x39,0x39,0x2a,0x28,0x38,0x00, 0x00,0x01,0xff,0x64,0xfe,0x40,0x00,0x9c,0xff,0x89,0x00,0x0c,0x00,0x23,0x40,0x13,0x0c,0x0a,0xc3,0x40,0x02,0x80,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0x00,0x07,0xc2,0x06,0x2f,0xf1,0xc2,0x2f,0x00,0x2f,0x5d,0x1a,0xdc,0x1a,0xed,0x32,0x31,0x30,0x13,0x06,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x37,0x9c,0x3b, 0x55,0x4b,0x5d,0x78,0x46,0x27,0x29,0xfe,0x90,0x50,0x52,0x47,0xb0,0xba,0x43,0x2a,0x00,0x01,0xfe,0x9c,0x04,0xc2,0x01,0x64,0x05,0xf0,0x00,0x07,0x00,0x1b,0x40,0x0d,0x00,0x05,0x80,0x03,0xfd,0x06,0x00,0x00,0xfc,0x01,0x04,0xfc,0x05,0x2f,0xe1,0xd4,0xe1,0x00,0x3f,0xed,0x1a,0xcd,0x32,0x31,0x30,0x01,0x23,0x35,0x21,0x15,0x23,0x11, 0x21,0x01,0x64,0x68,0xfe,0x08,0x68,0x02,0xc8,0x04,0xc2,0xc5,0xc5,0x01,0x2e,0x00,0x00,0x02,0xfe,0x2a,0xfd,0xfe,0x01,0xd6,0xff,0xaa,0x00,0x03,0x00,0x07,0x00,0x10,0xb6,0x06,0x05,0x02,0x50,0x01,0x01,0x01,0x00,0x2f,0x5d,0xcd,0x2f,0xcd,0x31,0x30,0x05,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x01,0xd6,0xfc,0x54,0x03,0xac,0xfc,0x54, 0x03,0xac,0xda,0x84,0xfe,0x54,0x84,0x00,0x00,0x02,0xff,0x58,0xfe,0x1e,0x00,0xa8,0xff,0x89,0x00,0x03,0x00,0x07,0x00,0x21,0x40,0x12,0x02,0x01,0x05,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x00,0xfc,0x01,0x01,0x04,0xfc,0x05,0x2f,0xf1,0xca,0x2f,0xe1,0x00,0x2f,0x5d,0xcd,0x39,0x39,0x31,0x30,0x13,0x23,0x11,0x33,0x03,0x23,0x11, 0x33,0xa8,0x6a,0x6a,0xe6,0x6a,0x6a,0xfe,0x1e,0x01,0x6b,0xfe,0x95,0x01,0x6b,0x00,0x00,0x01,0xff,0x4c,0xfe,0x56,0x00,0xb6,0xff,0xc6,0x00,0x05,0x00,0x12,0xb7,0x01,0x04,0xfd,0x05,0x01,0xfc,0x02,0x05,0x2f,0xd4,0xe1,0x00,0x2f,0xfd,0xc4,0x31,0x30,0x17,0x11,0x23,0x11,0x23,0x35,0xb6,0x6c,0xfe,0x3a,0xfe,0x90,0x01,0x06,0x6a,0x00, 0x00,0x01,0xfe,0xc0,0x04,0xc4,0x01,0x40,0x06,0x74,0x00,0x19,0x00,0x3c,0x40,0x1d,0x05,0xc4,0x06,0x12,0xc4,0x13,0x0e,0x0b,0x09,0x10,0x18,0x01,0x03,0x16,0x0d,0x00,0x0c,0x19,0x06,0x0c,0x13,0x06,0x10,0xda,0x16,0x03,0xda,0x09,0x13,0x00,0x2f,0xd4,0xfd,0xdc,0xed,0xc4,0x10,0xc6,0x10,0xc6,0x11,0x39,0x39,0x11,0x12,0x39,0x39,0x11, 0x12,0x39,0x39,0x01,0x2f,0xe1,0xd4,0xe1,0x31,0x30,0x13,0x07,0x16,0x33,0x32,0x35,0x33,0x14,0x06,0x23,0x22,0x27,0x07,0x27,0x37,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x37,0xa6,0x58,0x1e,0x1e,0x54,0x62,0x5f,0x53,0x3c,0x44,0x5a,0x5a,0x56,0x1e,0x1c,0x58,0x5e,0x60,0x56,0x3a,0x40,0x5c,0x06,0x3a,0x88,0x0a,0x74,0x68, 0x85,0x21,0x8c,0x3a,0x84,0x0c,0x72,0x6e,0x7e,0x23,0x8f,0x00,0x00,0x03,0xfe,0xc0,0x04,0xc4,0x01,0x40,0x07,0x62,0x00,0x0b,0x00,0x1f,0x00,0x2b,0x00,0x35,0x40,0x1b,0x09,0x03,0x29,0xc0,0x23,0x23,0x16,0x1f,0xc4,0x0c,0x15,0xc4,0x16,0x06,0xc1,0x00,0x0c,0x13,0xda,0x19,0x1d,0xda,0x0f,0x16,0x26,0xc1,0x20,0x00,0x2f,0xfd,0xd6,0xd4, 0xfd,0xdc,0xed,0xd4,0xd6,0xed,0x01,0x2f,0xe1,0xd4,0xe1,0x12,0x39,0x2f,0xe1,0x39,0x39,0x31,0x30,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01, 0x28,0x3b,0x3c,0x27,0x29,0x3a,0x3a,0x01,0x18,0x5f,0x53,0x46,0x5c,0x4c,0x2a,0x58,0x5e,0x60,0x56,0x42,0x54,0x49,0x35,0x54,0xdf,0x29,0x3a,0x3c,0x27,0x29,0x3a,0x3a,0x06,0xa0,0x39,0x29,0x2a,0x36,0x37,0x29,0x29,0x39,0x0a,0x69,0x85,0x33,0x2b,0x70,0x6c,0x7f,0x33,0x2d,0x75,0xfe,0x2e,0x3a,0x29,0x29,0x37,0x37,0x29,0x29,0x3a,0x00, 0x00,0x02,0xfe,0xc0,0x04,0xb2,0x01,0x40,0x06,0xa0,0x00,0x12,0x00,0x25,0x00,0x34,0x40,0x1a,0x25,0x13,0x12,0xc4,0x00,0x1c,0x1d,0x09,0xc4,0x0a,0x00,0x07,0xda,0x0c,0x10,0xda,0x09,0x03,0x13,0x1a,0xda,0x1f,0x23,0xda,0x1d,0x16,0x00,0x2f,0xc4,0xfd,0xdc,0xed,0xd4,0xd6,0xc6,0xfd,0xdc,0xed,0xc4,0x01,0x2f,0xe1,0x39,0x39,0xd4,0xe1, 0x39,0x39,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x13,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x01,0x40,0x5c,0x56,0x42,0x57,0x57,0x28,0x58,0x5e,0xb6,0x3e,0x52,0x52,0x32,0x54,0x62,0x5c,0x56,0x42,0x57,0x57, 0x28,0x58,0x5e,0xb6,0x3e,0x52,0x52,0x32,0x54,0x06,0xa0,0x64,0x76,0x25,0x25,0x5c,0xd8,0x26,0x26,0x60,0xfe,0xfe,0x64,0x76,0x25,0x25,0x5c,0xd7,0x25,0x26,0x60,0x00,0x00,0x01,0xfe,0xa8,0xfe,0x6e,0x01,0x58,0xff,0xb6,0x00,0x09,0x00,0x35,0x40,0x1c,0x07,0x05,0x02,0x00,0x0e,0x09,0xfd,0x03,0x40,0x03,0x02,0x42,0x03,0x0f,0x02,0x1f, 0x02,0x2f,0x02,0x03,0x02,0x04,0x03,0x09,0x08,0x06,0x09,0x01,0x2f,0xcd,0x2f,0xcd,0x11,0x39,0x39,0x00,0x2f,0x5d,0xcd,0x2b,0x00,0x1a,0x18,0x10,0xfd,0xed,0x11,0x39,0x39,0x31,0x30,0x03,0x27,0x37,0x15,0x21,0x35,0x17,0x07,0x35,0x21,0xa8,0xb0,0xb0,0x01,0x50,0xb0,0xb0,0xfe,0xb0,0xfe,0x6e,0xa4,0xa4,0x6e,0x6e,0xa4,0xa4,0x6f,0x00, 0x00,0x01,0xff,0x5c,0xfe,0x5c,0x00,0xa4,0xff,0xdb,0x00,0x06,0x00,0x18,0x40,0x0a,0x00,0x04,0x02,0x03,0x04,0x04,0x05,0xfc,0x01,0x02,0x2f,0xdd,0xf1,0xc1,0x2f,0x00,0x2f,0xdd,0x32,0xc6,0x31,0x30,0x03,0x35,0x23,0x37,0x17,0x23,0x15,0x35,0x6f,0xa4,0xa4,0x6f,0xfe,0x5c,0xcf,0xb0,0xb0,0xcf,0x00,0x01,0xfd,0x0e,0x05,0xc2,0x02,0xf2, 0x07,0x00,0x00,0x15,0x00,0x1d,0x40,0x0e,0x00,0x07,0xda,0x0e,0x12,0xda,0x03,0x0b,0x15,0xda,0x00,0x0a,0xda,0x0b,0x2f,0xe1,0x2f,0xe1,0x00,0x2f,0xd4,0xfd,0xd4,0xed,0xc4,0x31,0x30,0x01,0x06,0x06,0x23,0x22,0x25,0x24,0x23,0x22,0x06,0x15,0x23,0x36,0x36,0x33,0x32,0x05,0x04,0x33,0x32,0x36,0x35,0x02,0xf2,0x02,0xb6,0x86,0x92,0xfe, 0xde,0xfe,0xde,0x90,0x58,0x71,0x77,0x02,0xb4,0x88,0x95,0x01,0x23,0x01,0x22,0x8c,0x57,0x72,0x07,0x00,0x86,0xb2,0x5b,0x5a,0x6b,0x50,0x88,0xb0,0x5b,0x5b,0x6c,0x50,0x00,0x01,0xfc,0xe6,0x05,0xc2,0x03,0x1a,0x07,0x40,0x00,0x09,0x00,0x16,0x40,0x09,0x03,0xda,0x08,0x00,0x06,0x01,0x00,0x05,0x06,0x2f,0x33,0x2f,0x32,0x00,0x2f,0xc4, 0xd4,0xed,0x31,0x30,0x01,0x23,0x02,0x21,0x20,0x03,0x23,0x12,0x21,0x20,0x03,0x1a,0xa2,0xba,0xfe,0x41,0xfe,0x43,0xba,0xa2,0xf0,0x02,0x2a,0x02,0x2a,0x05,0xc2,0x01,0x02,0xfe,0xfe,0x01,0x7e,0x00,0x00,0x01,0xfd,0xaf,0xfe,0x6e,0x02,0x51,0xff,0xb6,0x00,0x06,0x00,0x22,0x40,0x12,0x04,0x05,0xfd,0x01,0x40,0x0f,0x02,0x1f,0x02,0x2f, 0x02,0x03,0x02,0x01,0x05,0x80,0x03,0x00,0x2f,0x2f,0x1a,0xcd,0x32,0x00,0x2f,0x5d,0x1a,0xdd,0xfd,0xcd,0x31,0x30,0x05,0x21,0x35,0x17,0x07,0x35,0x21,0xfd,0xaf,0x03,0xf2,0xb0,0xb0,0xfc,0x0e,0xb8,0x6e,0xa4,0xa4,0x6f,0x00,0x02,0x00,0x21,0xff,0xe8,0x04,0x54,0x05,0xec,0x00,0x18,0x00,0x25,0x00,0x4c,0x40,0x2b,0x0d,0x0a,0x04,0x95, 0x40,0x07,0x08,0x11,0x07,0x95,0x09,0x30,0x03,0x15,0x01,0x1d,0x95,0x17,0x16,0x0e,0x23,0x95,0x11,0x10,0x08,0x00,0x0b,0x0b,0x0a,0x14,0x83,0x20,0x20,0x27,0x02,0x0d,0x0a,0x07,0x04,0x19,0x84,0x05,0x03,0x2f,0xc6,0xe9,0x17,0x39,0x12,0x39,0x2f,0xe9,0x11,0x39,0x2f,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x2b,0x00,0x18,0x2f, 0x1a,0xed,0x39,0x39,0x31,0x30,0x25,0x23,0x15,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4c,0x04,0xa2,0x85,0x85,0xa2,0xf8,0xf8,0x04,0x79,0xe9,0xc5,0xe1,0xfb,0xda,0xc7,0x70,0xa4,0x80, 0x94,0xac,0x9e,0x89,0x8f,0xae,0x94,0x94,0x04,0xb4,0x8c,0xac,0xac,0x8c,0xfe,0x98,0xcc,0xfe,0xef,0xe9,0xff,0x00,0xfe,0xca,0x02,0x49,0x8f,0x7f,0xb1,0xe1,0xc5,0xaf,0xc7,0xc7,0x00,0x03,0xff,0xac,0x00,0x00,0x04,0x81,0x05,0x9a,0x00,0x1b,0x00,0x23,0x00,0x2b,0x00,0x48,0x40,0x26,0x08,0x08,0x00,0x0d,0x14,0x24,0x91,0x1d,0x1d,0x0d, 0x25,0x91,0x00,0x12,0x1c,0x01,0x91,0x0d,0x03,0x14,0x25,0x18,0x7d,0x29,0x29,0x11,0x7d,0x21,0x21,0x2d,0x00,0x05,0x7e,0x0a,0x1d,0x25,0x7e,0x00,0x2f,0xe9,0x32,0xd4,0xe1,0x11,0x12,0x39,0x2f,0xe9,0x39,0x2f,0xe9,0x11,0x39,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x11,0x12,0x39,0x2f,0x31,0x30,0x21,0x11,0x23,0x22, 0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x04,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x01,0x0e,0x18,0x51,0x59,0x14,0x9e,0x16,0xc3,0xa1,0x01,0x96,0xba,0xda,0x84,0x74,0x91,0xae,0xfe,0xf8,0xc9,0xfa,0xac,0x8a, 0x9d,0xfe,0xee,0xc1,0xe4,0x94,0xa3,0xfe,0xa6,0x05,0x02,0x5d,0x4d,0x37,0x33,0x38,0x42,0x84,0xae,0xb6,0x92,0x7a,0xb4,0x26,0x04,0x11,0xb9,0x94,0xb8,0xe4,0x05,0x02,0xfe,0x31,0x85,0x79,0xd1,0xfd,0x9a,0xfd,0xfc,0x8c,0x7a,0xfe,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x38,0x05,0x9a,0x00,0x0c,0x00,0x14,0x00,0x2e,0x40,0x18,0x0d,0x91, 0x05,0x05,0x01,0x0e,0x91,0x00,0x12,0x04,0x91,0x01,0x03,0x02,0x02,0x09,0x7d,0x12,0x12,0x16,0x05,0x0e,0x7e,0x00,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0xbc, 0x02,0xfe,0xfd,0xaa,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa2,0xfe,0xc9,0x05,0x9a,0x98,0xfe,0x38,0xcf,0xbf,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8c,0x7e,0x01,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x54,0x05,0xec,0x00,0x12,0x00,0x1f,0x00,0x36,0x40,0x1d,0x08,0x00,0x0b,0x17,0x95,0x11,0x16,0x03,0x15,0x1d,0x95,0x0b, 0x10,0x07,0x95,0x04,0x00,0x05,0x05,0x0e,0x83,0x1a,0x1a,0x21,0x14,0x01,0x08,0x84,0x03,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x25,0x23,0x15,0x23,0x11,0x21,0x15,0x21,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33, 0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4c,0x04,0xa2,0x03,0x25,0xfd,0x7d,0x04,0x79,0xe9,0xc5,0xe1,0xfb,0xda,0xc7,0x70,0xa4,0x80,0x94,0xac,0x9e,0x89,0x8f,0xae,0x94,0x94,0x05,0xec,0x8c,0xfd,0xec,0xcc,0xfe,0xef,0xe9,0xff,0x00,0xfe,0xca,0x02,0x49,0x8f,0x7f,0xb1,0xe1,0xc5,0xaf,0xc7,0xc7,0x00,0x02,0x00,0x33,0x00,0x00, 0x04,0x38,0x05,0xb2,0x00,0x0d,0x00,0x15,0x00,0x2b,0x40,0x16,0x0e,0x91,0x06,0x06,0x05,0x0f,0x91,0x00,0x12,0x03,0x05,0x04,0x0a,0x7d,0x13,0x13,0x17,0x02,0x06,0x0f,0x7e,0x00,0x2f,0xe1,0x32,0xc6,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xcd,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x33,0x11,0x27,0x35,0x25,0x33,0x11,0x21,0x32,0x16,0x15, 0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0xbc,0x89,0x01,0x1b,0x16,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe,0xec,0x95,0xa0,0xfe,0xcb,0x04,0x81,0x77,0x16,0xa4,0xfd,0x86,0xcd,0xbf,0xc6,0xe6,0x02,0xa4,0xfd,0xf2,0x8e,0x7e,0x01,0x02,0x00,0x02,0x00,0x21,0xff,0xe8,0x04,0x54,0x05,0xec,0x00,0x13,0x00,0x20,0x00,0x33, 0x40,0x1b,0x09,0x01,0x0c,0x18,0x95,0x12,0x16,0x03,0x15,0x1e,0x95,0x0c,0x10,0x06,0x08,0x00,0x0f,0x83,0x1b,0x1b,0x22,0x14,0x01,0x09,0x84,0x05,0x03,0x2f,0xc6,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xcd,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x25,0x23,0x15,0x23,0x11,0x27,0x35,0x25,0x33,0x11,0x33,0x36,0x33, 0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4c,0x04,0xa2,0x85,0x01,0x10,0x17,0x04,0x79,0xe9,0xc5,0xe1,0xfb,0xda,0xc7,0x70,0xa4,0x80,0x94,0xac,0x9e,0x89,0x8f,0xae,0x94,0x94,0x04,0xc2,0x73,0x17,0xa0,0xfd,0x60,0xcc,0xfe,0xef,0xe9,0xff,0x00,0xfe,0xca,0x02,0x49, 0x8f,0x7f,0xb1,0xe1,0xc5,0xaf,0xc7,0xc7,0x00,0x01,0x00,0x6a,0xff,0xe8,0x04,0x98,0x05,0xb2,0x00,0x15,0x00,0x22,0x40,0x11,0x01,0x03,0x91,0x14,0x13,0x0b,0x09,0x91,0x0e,0x04,0x11,0x7d,0x06,0x06,0x17,0x0b,0x00,0x2f,0x32,0x11,0x39,0x2f,0xe9,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x00,0x11,0x10, 0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x6a,0x9a,0xba,0xf6,0x01,0x34,0xfe,0xe1,0xea,0xd8,0x9d,0x9f,0xed,0x01,0x31,0x01,0x71,0xfe,0x64,0xfe,0xc0,0xcc,0x23,0xb2,0x56,0x01,0x4b,0x01,0x13,0x01,0x07,0x01,0x36,0x60,0xa4,0x54,0xfe,0x76,0xfe,0xc0,0xfe,0xa8,0xfe,0x58,0x00,0x01,0x00,0x5e,0xff,0xe8, 0x05,0x42,0x06,0x83,0x00,0x21,0x00,0x43,0x40,0x24,0x20,0x11,0x01,0x11,0x0f,0x91,0x14,0x13,0x21,0x92,0x00,0x02,0x92,0x1f,0x1a,0x1c,0x1a,0x07,0x09,0x91,0x1a,0x04,0x19,0x06,0x17,0x00,0x1c,0x7f,0x04,0x06,0x12,0x12,0x23,0x0c,0x7d,0x17,0x2f,0xe1,0x12,0x39,0x2f,0xd6,0xd6,0xe1,0xc6,0x11,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x11,0x39, 0x10,0xd4,0xfd,0xd6,0xed,0x3f,0xfd,0xc6,0x5d,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x14,0x17,0x07,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x36,0x36,0x33,0x32,0x17,0x05,0x42,0x2a,0x24,0x71,0x0f,0x09,0xa5,0xb7,0xf1,0xfe,0xd2,0x01,0x1f,0xe9,0xd8,0x9e,0x9f,0xed, 0xfe,0xce,0xfe,0x90,0x01,0x9c,0x01,0x3e,0x5c,0x5e,0x03,0x85,0x68,0x30,0x30,0x05,0xe4,0x14,0x9e,0x3c,0x58,0x06,0x5a,0xfe,0xb5,0xfe,0xed,0xfe,0xfa,0xfe,0xc9,0x60,0xa3,0x54,0x01,0x8a,0x01,0x40,0x01,0x57,0x01,0xa9,0x18,0x5f,0x8a,0x13,0x00,0x01,0x00,0x60,0xff,0xe8,0x04,0x0e,0x04,0xd5,0x00,0x21,0x00,0x48,0x40,0x1d,0x30,0x11, 0x01,0x11,0x11,0x0f,0x95,0x14,0x16,0x21,0x96,0x00,0x02,0x96,0x1f,0x1a,0x1c,0x1a,0x40,0x07,0x01,0x07,0x07,0x09,0x95,0x1a,0x10,0x00,0x1c,0xb8,0x01,0x03,0xb7,0x04,0x06,0x11,0x11,0x23,0x0c,0x83,0x17,0x2f,0xe1,0x12,0x39,0x2f,0xd6,0xd6,0xe1,0xc6,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x12,0x39,0x10,0xd4,0xfd,0xd6,0xed,0x3f,0xed,0x32, 0x2f,0x5d,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x14,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x17,0x04,0x0e,0x23,0x20,0x65,0x08,0x06,0x93,0x7d,0x95,0xbb,0xbd,0x9f,0x86,0x76,0x76,0xa2,0xdd,0xfe,0xf5,0x01,0x1a,0xe0,0x4b,0x41,0x02, 0x77,0x59,0x28,0x2e,0x04,0x42,0x12,0x8e,0x54,0x2e,0x04,0x4e,0xdf,0xb9,0xb4,0xd0,0x59,0x9c,0x47,0x01,0x1f,0xe5,0xef,0x01,0x3d,0x14,0x57,0x7a,0x13,0x00,0x00,0x02,0x00,0x1c,0x00,0x00,0x05,0x3e,0x05,0x9a,0x00,0x0b,0x00,0x17,0x00,0x43,0x40,0x0a,0x10,0x0d,0x01,0x91,0x40,0x04,0x05,0x00,0x04,0x91,0xb8,0x01,0x00,0x40,0x17,0x30, 0x11,0x91,0x00,0x12,0x0c,0x91,0x05,0x03,0x0f,0x0f,0x11,0x08,0x7d,0x15,0x15,0x19,0x0d,0x04,0x11,0x7e,0x02,0x00,0x2f,0xc6,0xe1,0x39,0x39,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x20,0x11,0x10,0x00,0x21,0x03,0x11,0x21, 0x15,0x21,0x11,0x33,0x20,0x00,0x11,0x10,0x21,0xbc,0xa0,0xa0,0x01,0x8c,0x02,0xf6,0xfe,0x5b,0xfe,0x9f,0xd4,0x01,0x50,0xfe,0xb0,0xd6,0x01,0x1a,0x01,0x3a,0xfd,0xb6,0x02,0x81,0x9b,0x02,0x7e,0xfd,0x45,0xfe,0xb2,0xfe,0x6f,0x05,0x02,0xfe,0x1a,0x9b,0xfe,0x17,0x01,0x2e,0x01,0x15,0x02,0x27,0x00,0x02,0xff,0xac,0x00,0x00,0x05,0x90, 0x05,0x9a,0x00,0x13,0x00,0x1b,0x00,0x2e,0x40,0x18,0x08,0x08,0x0d,0x15,0x91,0x00,0x12,0x14,0x01,0x91,0x0d,0x03,0x05,0x7e,0x0a,0x00,0x10,0x7d,0x19,0x19,0x1d,0x15,0x7e,0x00,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x10,0xd4,0xe1,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0x31,0x30,0x21,0x11,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26, 0x35,0x34,0x36,0x33,0x21,0x20,0x11,0x10,0x00,0x21,0x03,0x11,0x33,0x20,0x00,0x11,0x10,0x21,0x01,0x0e,0x18,0x51,0x59,0x14,0x9e,0x16,0xc3,0xa1,0x01,0x8a,0x02,0xf6,0xfe,0x5b,0xfe,0x9e,0xd3,0xd6,0x01,0x1a,0x01,0x39,0xfd,0xb7,0x05,0x02,0x5d,0x4d,0x37,0x33,0x38,0x42,0x84,0xae,0xfd,0x45,0xfe,0xb4,0xfe,0x6d,0x05,0x02,0xfb,0x96, 0x01,0x2e,0x01,0x15,0x02,0x27,0x00,0x02,0x00,0x5c,0x00,0x00,0x03,0xd7,0x05,0x9a,0x00,0x0c,0x00,0x13,0x00,0x2c,0x40,0x17,0x0e,0x91,0x08,0x08,0x0c,0x0d,0x91,0x00,0x12,0x09,0x91,0x0c,0x03,0x00,0x7e,0x08,0x0d,0x0d,0x15,0x0a,0x11,0x7d,0x04,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed, 0x31,0x30,0x21,0x21,0x22,0x26,0x35,0x34,0x24,0x33,0x33,0x11,0x21,0x35,0x21,0x03,0x11,0x23,0x20,0x11,0x10,0x21,0x03,0xd7,0xfe,0x5c,0xe5,0xf2,0x01,0x0a,0xe0,0xe9,0xfd,0xaa,0x02,0xfe,0xa8,0xe7,0xfe,0xc6,0x01,0x36,0xce,0xc2,0xc2,0xe6,0x01,0xc8,0x9a,0xfa,0xfa,0x02,0x0e,0xfe,0xf4,0xfe,0xfe,0x00,0x00,0x02,0x00,0x60,0xff,0xe8, 0x04,0x0e,0x05,0xec,0x00,0x12,0x00,0x1f,0x00,0x34,0x40,0x1c,0x0e,0x02,0x0b,0x1d,0x95,0x05,0x16,0x00,0x15,0x17,0x95,0x0b,0x10,0x0f,0x95,0x12,0x00,0x00,0x84,0x13,0x02,0x0e,0x0e,0x21,0x1a,0x83,0x10,0x08,0x2f,0xc4,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x21,0x23, 0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x21,0x35,0x21,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x0e,0xa2,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5,0xd3,0x60,0x04,0xfd,0x7e,0x03,0x24,0xa2,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0xab,0xae,0xc6,0x01,0x13,0xed,0xfe,0x01, 0x32,0xa6,0x01,0xee,0x8c,0xfb,0xe3,0x97,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0xc6,0x00,0x00,0x02,0x00,0x60,0xfe,0x1e,0x04,0x5c,0x04,0x18,0x00,0x1a,0x00,0x26,0x00,0x44,0x40,0x25,0x00,0x0d,0x1b,0x03,0x06,0x16,0x10,0x09,0x01,0x09,0x0b,0x95,0x06,0x1c,0x21,0x95,0x16,0x10,0x1b,0x00,0x24,0x0d,0x83,0x03,0x03,0x13,0x08,0x08,0x13,0x19, 0x83,0x1e,0x1e,0x28,0x24,0x83,0x13,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x11,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xfd,0xc6,0x5d,0x11,0x12,0x17,0x39,0x31,0x30,0x25,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x00,0x33,0x32,0x00,0x15,0x10,0x05, 0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0xdd,0x7b,0x56,0xd9,0xac,0xad,0x90,0x96,0xab,0xd9,0x58,0xc8,0xd3,0xb3,0x01,0x22,0xe4,0xdf,0x01,0x17,0xfe,0x00,0xc6,0x92,0xba,0x9c,0x9a,0xbc,0x81,0x48,0x53,0x7e,0x50,0x71,0x98,0x4c,0xac,0x6c,0x7f,0x34,0x5d,0x77,0x7e,0xf7,0x92,0xcf,0x01,0x11,0xfe,0xfc,0xc4,0xfe, 0xd9,0x8f,0x6f,0xca,0x73,0x96,0xb2,0xb3,0x95,0x6e,0xbe,0x00,0x00,0x01,0x00,0x5a,0x00,0x00,0x03,0x52,0x05,0x9a,0x00,0x0b,0x00,0x32,0x40,0x1b,0x04,0x91,0x40,0x07,0x0b,0x00,0x07,0x91,0x2b,0x30,0x03,0x91,0x00,0x12,0x08,0x91,0x0b,0x03,0x00,0x7e,0x07,0x03,0x03,0x0d,0x05,0x09,0x01,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0x33,0xe1,0x00, 0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x21,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x03,0x52,0xfd,0x08,0x02,0x50,0xfd,0xfa,0x02,0x06,0xfd,0xd1,0x02,0xd7,0x98,0x01,0xe9,0x97,0x01,0xea,0x98,0x00,0x00,0x01,0x00,0x70,0xff,0xe8,0x03,0xf4,0x05,0xb2,0x00,0x23,0x00,0x49,0x40,0x28,0x08,0x1b, 0x91,0x40,0x1a,0x0e,0x02,0x1a,0x91,0x09,0x30,0x20,0x23,0x01,0x23,0x21,0x91,0x02,0x13,0x11,0x13,0x91,0x0e,0x04,0x08,0x05,0x1b,0x1b,0x1e,0x10,0x00,0x00,0x25,0x05,0x16,0x7d,0x0b,0x1e,0x7d,0x05,0x2f,0xe1,0xd4,0xe1,0x11,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x5d,0x2b,0x00,0x18,0x2f, 0x1a,0xed,0x39,0x31,0x30,0x25,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x37,0x35,0x24,0x35,0x34,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x20,0x11,0x14,0x16,0x33,0x32,0x37,0x03,0xf4,0xa6,0xcf,0xf5,0xfe,0xe6,0xa2,0x90,0xff,0x00,0x01,0x11,0xd9,0xb2,0x91,0x99,0xaf,0x8d,0xaa,0xcb,0xab,0x69, 0x6b,0xfe,0x5d,0xbf,0xa5,0xc8,0xa7,0x35,0x4d,0xdd,0xb8,0x85,0xc4,0x26,0x06,0x50,0xed,0xa7,0xdc,0x46,0xaa,0x58,0x7e,0x6b,0x70,0x92,0x97,0xfe,0xf1,0x7d,0x8d,0x5c,0x00,0x01,0xff,0x9a,0xfe,0x96,0x03,0x94,0x05,0x9a,0x00,0x11,0x00,0x33,0x40,0x1b,0x05,0x91,0x40,0x02,0x10,0x12,0x02,0x91,0x09,0x30,0x0b,0x0d,0x91,0x08,0x01,0x91, 0x10,0x03,0x03,0x11,0x11,0x13,0x02,0x06,0x7e,0x0b,0x0f,0x2f,0xc6,0xe1,0x32,0x12,0x39,0x2f,0xc4,0x00,0x3f,0xed,0x2f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x21,0x03,0x94,0xfd,0xd0,0x02,0x06,0xfd,0xfa,0xfe,0xae,0x41,0x37,0x32, 0x3e,0xb2,0x02,0xd8,0x05,0x02,0xfe,0x10,0x97,0xfd,0xba,0xfe,0x61,0x14,0xa0,0x1d,0x01,0x08,0x05,0x65,0x00,0x01,0x00,0x5e,0xff,0xe8,0x05,0x85,0x06,0x83,0x00,0x25,0x00,0x63,0x40,0x37,0x12,0x91,0x40,0x15,0x1e,0x0f,0x15,0x91,0x08,0x30,0x16,0x11,0x0f,0x91,0x18,0x13,0x00,0x20,0x07,0x1e,0x02,0x92,0x23,0x1e,0x1f,0x07,0x2f,0x07, 0x02,0x07,0x09,0x91,0x1e,0x04,0x1d,0x06,0x1b,0x00,0x20,0x7f,0x04,0x06,0x06,0x16,0x13,0x13,0x0c,0x16,0x7e,0x11,0x11,0x27,0x0c,0x7d,0x1b,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x10,0xc0,0x2f,0xd6,0xe1,0xc6,0x11,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x5d,0x10,0xd4,0xfd,0x11,0x12,0x39,0xc6,0x3f,0xed,0x32,0x32,0x2b,0x00,0x18, 0x2f,0x1a,0xed,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x14,0x17,0x07,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x11,0x21,0x35,0x21,0x11,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x36,0x36,0x33,0x32,0x17,0x05,0x85,0x29,0x24,0x72,0x0f,0x08,0xbf,0xd2,0xf6,0xfe,0xc8,0x01,0x1e,0xf5,0xa8,0x7b,0xfe,0xc6,0x01,0xe4, 0xd8,0xfe,0xf6,0xfe,0xcd,0xfe,0x85,0x01,0xa5,0x01,0x43,0x79,0x76,0x03,0x86,0x67,0x30,0x30,0x05,0xe4,0x14,0xa8,0x48,0x54,0x06,0x6c,0xfe,0xb6,0xfe,0xf6,0xfe,0xf0,0xfe,0xc9,0x43,0x01,0x92,0x98,0xfd,0x76,0x7a,0x01,0x8c,0x01,0x46,0x01,0x4d,0x01,0xab,0x22,0x64,0x8f,0x13,0x00,0x00,0x02,0x00,0x12,0xfe,0x1e,0x04,0xe6,0x05,0x9a, 0x00,0x17,0x00,0x1f,0x00,0x16,0x40,0x0a,0x1c,0x91,0x07,0x1c,0x00,0x0f,0x03,0x00,0x21,0x0f,0x2f,0x10,0xc6,0x00,0x3f,0x33,0x3f,0xed,0x31,0x30,0x01,0x01,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x01,0x06,0x15,0x14,0x33,0x32,0x35,0x34,0x04,0xe6,0xfd,0xfe, 0x06,0x72,0x89,0x63,0x60,0x82,0x29,0x4d,0x08,0xfe,0x06,0xbb,0x01,0x8d,0x15,0x08,0x04,0x0d,0x14,0x01,0x95,0xfe,0x43,0x43,0x43,0x44,0x05,0x9a,0xfa,0xc8,0x0c,0xe4,0x6e,0x61,0x85,0x82,0x64,0x3d,0x75,0x9a,0x10,0x05,0x3a,0xfb,0xbc,0x3a,0x36,0x39,0x37,0x04,0x44,0xfa,0x3f,0x8d,0x44,0x58,0x58,0x44,0x00,0x01,0x00,0xa6,0xff,0xe8, 0x06,0x87,0x05,0xec,0x00,0x20,0x00,0x45,0x40,0x27,0x04,0x01,0x07,0x0c,0x95,0x17,0x16,0x01,0x15,0x11,0x0f,0x1d,0x95,0x40,0x07,0x10,0x02,0x00,0x0a,0x84,0x19,0x00,0x0f,0x19,0x84,0x09,0x30,0x12,0x83,0x11,0x14,0x84,0x0f,0x0f,0x22,0x04,0x00,0x84,0x01,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0xd6,0xe1,0x2b,0x01,0x10,0xe1,0x00,0x18, 0x3f,0x3f,0x1a,0xed,0x3f,0x3f,0x3f,0xed,0x11,0x12,0x39,0x31,0x30,0x21,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x20,0x11,0x15,0x10,0x33,0x32,0x36,0x35,0x10,0x03,0x33,0x12,0x11,0x14,0x02,0x23,0x20,0x11,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x4a,0xa4,0xa4,0x04,0x62,0xcb,0x01,0x50,0xf7,0x84,0x9e,0x90,0xb2,0x81,0xfe,0xcb,0xfe, 0x69,0x69,0x7c,0x6c,0x8c,0x05,0xec,0xfd,0x72,0xba,0xfe,0x5f,0xaa,0xfe,0xaa,0xc2,0xa4,0x01,0x19,0x01,0x0a,0xfe,0xf6,0xfe,0xee,0xe5,0xfe,0xe9,0x01,0xda,0x8a,0xaa,0x98,0xb5,0x91,0x00,0x00,0x01,0x00,0xb8,0xff,0xee,0x02,0x25,0x05,0x9a,0x00,0x0b,0x00,0x1b,0x40,0x0d,0x0b,0x09,0x91,0x02,0x16,0x05,0x03,0x00,0x00,0x0d,0x06,0x7e, 0x05,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0x3f,0xfd,0xc6,0x31,0x30,0x25,0x06,0x23,0x22,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x02,0x25,0x3c,0x3b,0xf6,0xa8,0x68,0x30,0x2d,0x04,0x16,0x01,0x22,0x04,0x8a,0xfb,0x7a,0x8f,0x15,0x00,0x01,0x00,0x29,0x00,0x00,0x02,0x10,0x05,0x9a,0x00,0x0b,0x00,0x3b,0x40,0x20,0x0a,0x01,0x04,0x91, 0x40,0x07,0x08,0x03,0x07,0x91,0x14,0x30,0x03,0x12,0x08,0x03,0x0b,0x0a,0x06,0x07,0x40,0x0a,0x07,0x02,0x7e,0x03,0x0c,0x0d,0x03,0x7e,0x08,0x30,0x2b,0x01,0x10,0xe1,0x39,0x39,0x1a,0x18,0x10,0xcd,0x10,0xcd,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x11, 0x33,0x02,0x10,0xa0,0xa8,0x9f,0x9f,0xa8,0xa0,0x02,0x8e,0xfd,0x72,0x02,0x8e,0x97,0x02,0x75,0xfd,0x8b,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0xb2,0x00,0x17,0x00,0x2e,0x40,0x18,0x0a,0x17,0x05,0x03,0x08,0x01,0x07,0x12,0x08,0x03,0x12,0x14,0x91,0x0f,0x04,0x17,0x06,0x12,0x00,0x19,0x09,0x06,0x7e,0x07,0x2f,0xe1,0x32,0x10, 0xd6,0xc6,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0x3f,0x33,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x01,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x01,0x04,0xa2,0xea,0xfd,0xd6,0x1f,0x07,0x04,0xa8,0xa8,0x04,0x01,0x3c,0x8d,0x94,0x5c,0x38,0x37,0x38,0x3e,0x50,0x76,0xfe,0xc4, 0x02,0x90,0x25,0x0d,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x01,0xa4,0xbc,0x5a,0x1a,0x9c,0x1e,0x99,0xfe,0x65,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x02,0x00,0x15,0x00,0x31,0x40,0x1a,0x01,0x03,0x11,0x15,0x04,0x14,0x05,0x15,0x14,0x0f,0x0c,0x0e,0x95,0x09,0x01,0x15,0x04,0x14,0x00,0x17,0x0c,0x10,0x10,0x04,0x84,0x05,0x2f,0xe1, 0x32,0x10,0xc6,0x10,0xd6,0xc6,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x11,0x33,0x01,0x33,0x01,0x03,0xf8,0xe6,0xfe,0x3c,0x04,0xa4,0xb3,0x8b,0x47,0x2f,0x37,0x35,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0x01,0xec,0xfe, 0x14,0x04,0xb2,0x99,0xb7,0x12,0x94,0x1b,0xcf,0xfd,0x83,0x01,0xd5,0xfe,0x12,0x00,0x00,0x01,0x00,0x14,0x00,0x00,0x01,0xdb,0x05,0xec,0x00,0x0b,0x00,0x3b,0x40,0x20,0x0a,0x01,0x04,0x95,0x40,0x07,0x08,0x03,0x07,0x95,0x14,0x30,0x03,0x15,0x08,0x00,0x0b,0x0a,0x06,0x07,0x40,0x0a,0x07,0x02,0x84,0x03,0x0c,0x0d,0x03,0x84,0x08,0x30, 0x2b,0x01,0x10,0xe1,0x39,0x39,0x1a,0x18,0x10,0xcd,0x10,0xcd,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x01,0xdb,0x91,0xa4,0x92,0x92,0xa4,0x91,0x02,0xc4,0xfd,0x3c,0x02,0xc4,0x8c,0x02,0x9c,0xfd,0x64,0x00,0x01,0xff,0xfe,0x00,0x00,0x03,0xdf, 0x05,0xee,0x00,0x16,0x00,0x7c,0x40,0x44,0x16,0x12,0x00,0x06,0x05,0x02,0x07,0x15,0x07,0x13,0x12,0x00,0x09,0x05,0x02,0x08,0x14,0x08,0x16,0x13,0x12,0x00,0x12,0x09,0x06,0x05,0x02,0x05,0x06,0x08,0x09,0x13,0x15,0x16,0x06,0x07,0x14,0x10,0x07,0x07,0x05,0x05,0x02,0x0b,0x00,0x04,0x15,0x0d,0x0b,0x95,0x10,0x00,0x14,0x07,0x08,0x15, 0x00,0x08,0x0d,0x0d,0x02,0x05,0x12,0x03,0x04,0x00,0x18,0x04,0x2f,0x10,0xc6,0x11,0x17,0x39,0x39,0x2f,0xc6,0x10,0xc6,0x11,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0x33,0x12,0x39,0x39,0x11,0x33,0x2f,0x10,0xc4,0x11,0x17,0x39,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0, 0x31,0x30,0x21,0x23,0x01,0x01,0x23,0x01,0x27,0x05,0x27,0x25,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x17,0x37,0x17,0x05,0x03,0xdf,0xb0,0xfe,0xe7,0xfe,0x9c,0xb4,0x01,0xcf,0x1b,0xfe,0xf2,0x3a,0x01,0x1f,0x35,0x66,0x3e,0x3c,0x3c,0x46,0x68,0x80,0x36,0xf4,0x3a,0xff,0x00,0x03,0x3c,0xfc,0xc4,0x03,0xf8,0x4c,0x84,0x71,0x8b, 0x9c,0x12,0x99,0x0f,0x69,0x85,0x77,0x71,0x7d,0x00,0x00,0x01,0x00,0xb8,0xff,0xe8,0x06,0x66,0x05,0x9a,0x00,0x1e,0x00,0x45,0x40,0x27,0x02,0x07,0x15,0x1e,0x04,0x0c,0x19,0x05,0x11,0x91,0x40,0x09,0x13,0x00,0x12,0x0c,0x03,0x01,0x1e,0x7e,0x1d,0x0e,0x15,0x0c,0x15,0x42,0x0d,0x7e,0x0c,0x07,0x16,0x7e,0x15,0x1f,0x20,0x15,0x7e,0x08, 0x30,0x2b,0x01,0x10,0xe1,0x39,0x18,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0xe1,0x33,0x00,0x18,0x3f,0x3f,0x3f,0x1a,0xed,0x39,0x39,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x27,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x06,0x66,0xa4,0x04, 0x6c,0xd1,0xd7,0x48,0x72,0xe4,0xfe,0xac,0xa8,0x67,0x7d,0x67,0x91,0xa8,0xe2,0x6c,0x8c,0xa8,0xa2,0xba,0xd4,0xd4,0x01,0xc4,0x03,0xee,0xfc,0x26,0xa5,0x9c,0xbf,0x86,0x03,0xd6,0xfc,0x12,0xfe,0xd3,0xb5,0x90,0x03,0xd6,0x00,0x01,0xff,0x9a,0xfe,0x96,0x05,0x42,0x05,0x9a,0x00,0x1b,0x00,0x30,0x40,0x19,0x0d,0x0f,0x91,0x0a,0x04,0x16, 0x1b,0x03,0x13,0x01,0x12,0x13,0x03,0x13,0x01,0x07,0x1b,0x7e,0x1a,0x1a,0x1d,0x0d,0x07,0x7e,0x12,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0x3f,0x12,0x17,0x39,0x2f,0xfd,0xc6,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x01,0x16,0x17,0x33, 0x26,0x35,0x11,0x33,0x05,0x42,0xd0,0xfd,0x1e,0x1c,0x12,0x06,0x08,0xfe,0xae,0x41,0x37,0x32,0x3e,0xb2,0xda,0x02,0xce,0x2d,0x0d,0x04,0x0a,0xaa,0x04,0x77,0x2b,0x2f,0x2e,0x97,0xfc,0x29,0xfe,0x61,0x14,0xa0,0x1d,0x01,0x08,0x05,0x65,0xfb,0x9b,0x46,0x1a,0x3e,0x95,0x03,0xf2,0x00,0x00,0x01,0x00,0x83,0xfe,0x6c,0x03,0xf8,0x04,0x18, 0x00,0x15,0x00,0x34,0x40,0x1b,0x0f,0x09,0x12,0x01,0x09,0x15,0x0c,0x0f,0x04,0x95,0x12,0x10,0x00,0x83,0x01,0x01,0x17,0x09,0x10,0x0d,0x08,0x84,0x09,0x0d,0x83,0x0c,0x09,0x2f,0xd6,0xe1,0x10,0xe1,0x11,0x39,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0x2f,0x11,0x12,0x39,0x31,0x30,0x01,0x23,0x11,0x10,0x23,0x22,0x06,0x15, 0x11,0x23,0x11,0x34,0x27,0x33,0x16,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa6,0xec,0x7d,0x9f,0xa4,0x23,0xa8,0x1b,0x04,0x70,0xe4,0xa7,0xb3,0xfe,0x6c,0x03,0xd0,0x01,0x47,0xb1,0x86,0xfd,0xb4,0x02,0xb6,0xef,0x5b,0x47,0x67,0xc6,0xd6,0xcb,0x00,0x03,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x12,0x00,0x19, 0x00,0x38,0xb7,0x14,0x91,0x40,0x12,0x06,0x00,0x12,0x91,0xb8,0x01,0x00,0x40,0x14,0x30,0x17,0x91,0x00,0x13,0x0f,0x91,0x06,0x04,0x12,0x0c,0x14,0x09,0x7d,0x13,0x13,0x1b,0x14,0x7d,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00, 0x21,0x20,0x00,0x11,0x10,0x00,0x13,0x26,0x00,0x23,0x22,0x00,0x07,0x05,0x21,0x16,0x00,0x33,0x32,0x00,0x02,0xfe,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0x8c,0xc2,0x13,0xfe,0xfd,0xd8,0xd0,0xfe,0xee,0x16,0x03,0xe6,0xfc,0x1a,0x15,0x01,0x0c,0xcb,0xdc,0x01,0x0b,0x18,0x01,0x92,0x01,0x42,0x01,0x5a,0x01, 0x9c,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0x03,0x30,0xf6,0x01,0x0c,0xfe,0xe8,0xea,0x9b,0xea,0xfe,0xec,0x01,0x0b,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x07,0x04,0x05,0xb2,0x00,0x15,0x00,0x20,0x00,0x3e,0x40,0x22,0x16,0x07,0x1f,0x91,0x09,0x13,0x00,0x12,0x02,0x06,0x17,0x03,0x19,0x04,0x91,0x13,0x15,0x19,0x91,0x0f,0x04,0x07, 0x7e,0x16,0x16,0x0c,0x01,0x7e,0x00,0x00,0x22,0x1c,0x7d,0x0c,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x33,0xd4,0xed,0x11,0x17,0x39,0x3f,0x3f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x06,0x23,0x22,0x27,0x11,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x16,0x33,0x32,0x37,0x01,0x11,0x26,0x23, 0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x07,0x04,0xa8,0x76,0x82,0x36,0x4f,0xf9,0xe8,0xfe,0xce,0xfe,0x92,0x01,0x83,0x01,0x37,0x70,0xbe,0xbe,0x6c,0xd8,0xbc,0xfd,0x34,0xca,0x5e,0xe4,0xfe,0xe2,0x01,0x17,0xe5,0xa0,0x04,0xf4,0x19,0x09,0xfb,0x7e,0x7a,0x01,0x90,0x01,0x44,0x01,0x4c,0x01,0xaa,0x22,0x22,0x44,0xfb,0x0a,0x04,0x3e,0x20, 0xfe,0xba,0xfe,0xf7,0xfe,0xf6,0xfe,0xbe,0x00,0x02,0x00,0x60,0xff,0xe8,0x05,0xac,0x04,0x18,0x00,0x15,0x00,0x20,0x00,0x3e,0x40,0x22,0x16,0x07,0x1f,0x95,0x09,0x16,0x00,0x15,0x02,0x06,0x17,0x03,0x19,0x04,0x95,0x13,0x15,0x19,0x95,0x0f,0x10,0x07,0x84,0x16,0x16,0x0c,0x00,0x84,0x01,0x01,0x22,0x1c,0x83,0x0c,0x2f,0xe1,0x12,0x39, 0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x33,0xd4,0xed,0x11,0x17,0x39,0x3f,0x3f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x06,0x23,0x22,0x27,0x11,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x01,0x11,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x05,0xac,0xa4,0x64,0x5c,0x3e,0x3d,0xaf,0xb8, 0xec,0xfe,0xe6,0x01,0x28,0xec,0x54,0x98,0x98,0x54,0xb2,0xae,0xfd,0x81,0x7f,0x46,0x9e,0xc2,0xc5,0xa7,0x6e,0x03,0x62,0x18,0x08,0xfc,0xec,0x56,0x01,0x1b,0xf3,0xfa,0x01,0x28,0x21,0x22,0x43,0xfc,0x80,0x02,0xd8,0x1e,0xd7,0xbd,0xb8,0xd0,0x00,0x02,0xff,0xac,0x00,0x00,0x04,0x7b,0x05,0x9a,0x00,0x16,0x00,0x1d,0x00,0x3c,0x40,0x1f, 0x09,0x09,0x0f,0x02,0x00,0x91,0x18,0x18,0x0f,0x02,0x12,0x17,0x03,0x91,0x0f,0x03,0x13,0x7d,0x1b,0x1b,0x1f,0x02,0x09,0x09,0x07,0x7e,0x0c,0x18,0x01,0x7e,0x02,0x2f,0xe1,0x32,0xd4,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0xed,0x11,0x12,0x39,0x2f,0x31,0x30,0x01,0x11,0x23,0x11,0x23,0x22, 0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x20,0x11,0x10,0x21,0x01,0xb6,0xa8,0x18,0x51,0x59,0x14,0x9e,0x16,0xc3,0xa1,0x01,0x88,0xe6,0xfd,0xfe,0xe6,0xef,0xbc,0xb0,0x01,0x65,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x05,0x02,0x5d,0x4d,0x37,0x33,0x38,0x42,0x84,0xae,0xe1,0xcb, 0xcb,0xfe,0xfb,0x02,0xe4,0xfd,0xb4,0x01,0x30,0x01,0x1c,0x00,0x00,0x02,0x00,0xa6,0xfe,0x29,0x04,0x54,0x06,0x02,0x00,0x19,0x00,0x26,0x00,0x3c,0x40,0x20,0x0f,0x01,0x18,0x12,0x03,0x1b,0x1e,0x95,0x18,0x16,0x24,0x95,0x12,0x10,0x0a,0x0c,0x95,0x07,0x01,0x0a,0x0a,0x02,0x15,0x83,0x21,0x21,0x28,0x1b,0x0e,0x02,0x84,0x03,0x2f,0xe1, 0x32,0x32,0x12,0x39,0x2f,0xe1,0x10,0xc0,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0xed,0x3f,0x11,0x12,0x39,0x39,0x31,0x30,0x25,0x23,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01, 0x4e,0x04,0xa4,0xb2,0x8c,0x47,0x2f,0x37,0x35,0xa4,0x04,0x76,0xec,0xc5,0xdf,0xfa,0xd9,0xc9,0x6e,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0x94,0xfd,0x95,0x06,0x89,0x98,0xb8,0x12,0x94,0x1b,0xcf,0xfe,0xa4,0xcc,0xfe,0xef,0xe9,0xfe,0xff,0xfe,0xcb,0x02,0x49,0x8f,0x7e,0xb2,0xe3,0xcc,0xab,0xc2,0xc6,0x00,0x02,0x00,0xbc,0xff,0x68, 0x04,0x62,0x05,0x9a,0x00,0x13,0x00,0x1b,0x00,0x40,0x40,0x22,0x11,0x05,0x91,0x40,0x15,0x0a,0x07,0x15,0x91,0x08,0x30,0x00,0x07,0x12,0x14,0x91,0x0a,0x08,0x03,0x10,0x15,0x01,0x00,0x00,0x0e,0x7d,0x19,0x19,0x1d,0x15,0x0a,0x06,0x7e,0x07,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x32,0x12,0x39,0x00,0x3f,0xdd,0xed,0x3f, 0x2f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x05,0x23,0x03,0x26,0x23,0x23,0x11,0x23,0x11,0x33,0x15,0x21,0x32,0x16,0x15,0x10,0x05,0x15,0x16,0x17,0x01,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x04,0x62,0xc8,0xc5,0x5d,0xa1,0x73,0xa8,0xa8,0x01,0x04,0xcd,0xe7,0xfe,0xc1,0x57,0x47,0xfd,0xe9,0xde,0x89,0xa1,0xfe,0xde,0x98,0x01, 0xb6,0xce,0xfe,0x14,0x05,0x9a,0x98,0xcd,0xb0,0xfe,0xe0,0x4d,0x04,0x36,0x92,0x03,0x1e,0xfe,0x19,0x80,0x74,0xf3,0x00,0x01,0x00,0x62,0xff,0xe8,0x03,0xc7,0x05,0xb2,0x00,0x35,0x00,0x3e,0x40,0x23,0x0a,0x2d,0x14,0x23,0x04,0x05,0x30,0x1b,0x01,0x1b,0x19,0x91,0x1e,0x04,0x20,0x35,0x01,0x35,0x30,0x91,0x05,0x13,0x23,0xb1,0x14,0x1b, 0x14,0x1b,0x0a,0x35,0x35,0x37,0x2d,0xb1,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x00,0x3f,0xed,0xc4,0x5d,0x3f,0xed,0xcd,0x5d,0x12,0x17,0x39,0x31,0x30,0x25,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e, 0x02,0x07,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x03,0xc7,0x1c,0x5d,0x68,0x63,0x23,0x66,0xb8,0x8d,0x53,0x3d,0x68,0x8a,0x4d,0x4b,0x73,0x50,0x29,0x36,0x56,0x6d,0x38,0xc7,0x7f,0x62,0xd3,0x5d,0xb3,0x8c,0x56,0x37,0x60,0x82,0x4b,0x47,0x7b,0x5a,0x33,0x99,0x9b,0x2d,0x6a,0x69,0x5f,0x22,0x3a,0x13,0x1f,0x15,0x0b,0x29, 0x5c,0x93,0x6a,0x50,0x7c,0x66,0x54,0x26,0x25,0x3e,0x42,0x50,0x37,0x3b,0x52,0x34,0x17,0x58,0xbd,0x33,0x2e,0x5e,0x91,0x62,0x50,0x77,0x5e,0x4e,0x26,0x24,0x41,0x47,0x56,0x3a,0x6c,0x73,0x12,0x21,0x30,0x1e,0x00,0x01,0x00,0x56,0xff,0xe8,0x02,0xfd,0x04,0x18,0x00,0x2e,0x00,0x43,0xb7,0x0b,0x20,0x07,0x2a,0x04,0x02,0x1b,0x2e,0xb8, 0xff,0xc0,0x40,0x1b,0x0b,0x0e,0x48,0x2e,0x2e,0x2c,0x95,0x02,0x16,0x18,0x18,0x16,0x95,0x1b,0x10,0x11,0x83,0x20,0x20,0x18,0x00,0x00,0x30,0x18,0x2a,0x83,0x07,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x32,0x2f,0x2b,0x11,0x12,0x17,0x39,0x31,0x30,0x25,0x06,0x23,0x22,0x2e,0x02,0x35, 0x34,0x3e,0x02,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x03,0x15,0x14,0x33,0x32,0x37,0x02,0xfd,0x74,0x9e,0x4f,0x93,0x70,0x43,0x29,0x4c,0x6d,0x43,0x33,0x50,0x38,0x1d,0x1d,0x35,0x4a,0x2e,0x93,0x71,0x69,0x85,0x4b,0x8d,0x6e,0x42,0x23,0x45,0x67,0x44,0x31, 0x55,0x3f,0x25,0xd8,0xa2,0x85,0x25,0x3d,0x24,0x4a,0x70,0x4c,0x3e,0x5a,0x45,0x37,0x1a,0x14,0x22,0x2a,0x36,0x28,0x20,0x35,0x26,0x15,0x4a,0xa6,0x2e,0x26,0x4b,0x6f,0x48,0x3b,0x58,0x45,0x37,0x1b,0x13,0x23,0x2c,0x39,0x29,0x90,0x63,0x00,0x00,0x01,0x00,0x2d,0x00,0x00,0x03,0xf0,0x05,0x9a,0x00,0x0b,0x00,0x38,0x40,0x1b,0x03,0x09, 0x09,0x05,0x02,0x0a,0x91,0x01,0x12,0x04,0x08,0x91,0x05,0x03,0x08,0x04,0x0a,0x03,0x09,0x09,0x02,0x07,0x00,0x00,0x0d,0x04,0x02,0x2f,0xc6,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x33,0x32,0x11,0x33,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x12,0x39,0x19,0x2f,0x33,0x31,0x30,0x21,0x21,0x35,0x01,0x01,0x35,0x21,0x15,0x21,0x01,0x01,0x21, 0x03,0xf0,0xfc,0x3d,0x01,0xd3,0xfe,0x58,0x03,0x5a,0xfd,0x9c,0x01,0x78,0xfe,0x5f,0x02,0xcb,0x4e,0x02,0x96,0x02,0x5c,0x5a,0x9a,0xfd,0xe8,0xfd,0xac,0x00,0x00,0x02,0xff,0x83,0xfe,0x1e,0x02,0x87,0x06,0x02,0x00,0x15,0x00,0x20,0x00,0x39,0x40,0x1f,0x15,0x13,0x95,0x02,0x1c,0x1f,0x95,0x40,0x07,0xc0,0x19,0x95,0x40,0x0d,0x01,0x15, 0x04,0x16,0x04,0x1c,0x84,0x0a,0x11,0x84,0x04,0x21,0x22,0x04,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x18,0xd4,0xe1,0x11,0x33,0x10,0xc4,0x00,0x3f,0x1a,0xed,0x1a,0xdc,0x1a,0xed,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x20,0x11,0x11,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x33,0x32,0x37,0x01,0x35,0x34, 0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x02,0x87,0x39,0x5c,0xfe,0xfc,0x39,0x43,0x65,0x8a,0x90,0x6c,0x80,0x91,0x91,0x38,0x2e,0xfe,0x67,0x71,0x2a,0x39,0x3e,0x31,0x35,0xfe,0x3e,0x20,0x01,0x34,0x04,0xe6,0x1c,0x87,0x67,0x68,0x90,0xab,0x95,0xfa,0xac,0xc4,0x21,0x05,0xf7,0x0d,0xa8,0x3c,0x2b,0x2c,0x3c,0x00,0x00,0x01,0x00,0x2b, 0xfe,0x96,0x02,0x81,0x05,0x2f,0x00,0x1e,0x00,0x3e,0x40,0x22,0x06,0x08,0x95,0x03,0x1e,0x1c,0x95,0x0b,0x16,0x18,0x15,0x0e,0x95,0x14,0x11,0x0f,0x0b,0x40,0x13,0x16,0x48,0x0b,0x84,0x1e,0x17,0x17,0x18,0x06,0x15,0x11,0x18,0x84,0x0f,0x0e,0x2f,0xcd,0xe1,0x39,0x39,0xc4,0x10,0xc1,0x2f,0xd4,0xe1,0x2b,0x00,0x3f,0xcd,0xed,0x39,0x39, 0x3f,0xfd,0xc6,0x2f,0xfd,0xc6,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x36,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x02,0x81,0x99,0x7e,0x3c,0x34,0x34,0x3c,0x7e,0xfe,0xf3,0xb0,0xb0,0x4d,0x57,0x01,0x02,0xfe,0xfe,0x45,0x52,0x3c,0x2f,0x44,0x87, 0x9f,0x18,0x92,0x1f,0x9f,0x28,0x01,0x2c,0x02,0x60,0x8c,0xfa,0x18,0x1d,0xfe,0xd1,0x8c,0xfd,0xbd,0x67,0x58,0x22,0x00,0x01,0xff,0xcd,0x00,0x00,0x04,0x0c,0x05,0x9a,0x00,0x11,0x00,0x2d,0x40,0x18,0x03,0x12,0x0a,0x04,0x01,0x91,0x40,0x11,0x03,0x08,0x7e,0x0d,0x0d,0x02,0x00,0x02,0x7e,0x03,0x12,0x13,0x03,0x7e,0x08,0x30,0x2b,0x01, 0x10,0xe1,0x18,0xc4,0x10,0xc0,0x2f,0xe1,0x00,0x3f,0x1a,0xed,0x32,0xc4,0x3f,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x21,0x04,0x0c,0xfe,0x62,0xa8,0x9b,0x5a,0x65,0x15,0x9d,0x17,0xc2,0xa2,0x02,0xdb,0x05,0x02,0xfa,0xfe,0x05,0x02,0x5c,0x4e,0x37,0x33,0x38,0x42,0x85,0xad, 0x00,0x01,0x00,0x2b,0xff,0xea,0x02,0x81,0x06,0x02,0x00,0x1d,0x00,0x32,0x40,0x1a,0x1d,0x1b,0x95,0x02,0x16,0x0f,0x11,0x95,0x0c,0x01,0x17,0x14,0x05,0x95,0x08,0x0f,0x1d,0x0f,0x16,0x16,0x14,0x08,0x17,0x84,0x06,0x05,0x2f,0xcd,0xf1,0x39,0x39,0xc1,0x2f,0xc4,0xc4,0x00,0x3f,0xed,0x39,0x39,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30, 0x25,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x15,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x02,0x81,0x3a,0x5f,0xfe,0xf3,0xb0,0xb0,0x98,0x83,0x4a,0x41,0x3d,0x40,0x85,0x01,0x02,0xfe,0xfe,0x45,0x52,0x3c,0x2f,0x0a,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xc0,0x93,0xaf,0x1c, 0x92,0x23,0xbf,0xb8,0x8c,0xfd,0xbf,0x67,0x58,0x22,0x00,0x01,0x00,0x27,0xfe,0x96,0x04,0x0c,0x05,0x9a,0x00,0x0f,0x00,0x32,0x40,0x1a,0x06,0x04,0x91,0x09,0x01,0x0c,0x91,0x40,0x0e,0x03,0x06,0x06,0x02,0x00,0x0b,0x0d,0x0d,0x02,0x7e,0x0b,0x10,0x11,0x0b,0x7e,0x08,0x30,0x2b,0x01,0x10,0xf1,0xc0,0x18,0x2f,0x10,0xc4,0x11,0x39,0x2f, 0x00,0x3f,0x1a,0xed,0x32,0x2f,0xfd,0xc6,0x31,0x30,0x01,0x21,0x11,0x10,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x11,0x11,0x21,0x35,0x21,0x04,0x0c,0xfe,0x62,0xaa,0x46,0x34,0x3a,0x4e,0xfe,0xbc,0xfe,0x61,0x03,0xe5,0x05,0x02,0xfb,0x33,0xfe,0xf8,0x17,0x94,0x1a,0x01,0x95,0x04,0xd7,0x98,0x00,0x00,0x01,0x00,0x62,0xff,0xe8,0x05,0xa8, 0x05,0x9a,0x00,0x1b,0x00,0x42,0x40,0x24,0x09,0x91,0x17,0x13,0x04,0x0e,0x10,0x11,0x04,0x01,0x91,0x02,0x03,0x12,0x7d,0x0e,0x0e,0x0c,0x06,0x00,0x7e,0x04,0x04,0x0c,0x06,0x11,0x11,0x14,0x7d,0x0c,0x0c,0x1d,0x01,0x06,0x7d,0x1a,0x2f,0xe1,0x33,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x00, 0x3f,0xed,0x17,0x39,0x3f,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x15,0x04,0x11,0x14,0x00,0x33,0x32,0x00,0x35,0x10,0x01,0x35,0x21,0x15,0x21,0x04,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x01,0xbe,0xfe,0xa4,0x02,0x06,0xfe,0xa8,0x01,0x15,0xdd,0xe0,0x01,0x18,0xfe,0xa6,0x02,0x06,0xfe,0xa6,0x01,0x5c,0xfe,0x8e,0xfe,0xd0,0xfe,0xcd, 0xfe,0x8f,0x05,0x06,0x94,0x94,0xfe,0xfe,0x86,0xf7,0xfe,0xe6,0x01,0x1c,0xf5,0x01,0x78,0x01,0x00,0x94,0x94,0xec,0xfe,0x6f,0xfe,0xca,0xfe,0x95,0x01,0x66,0x01,0x39,0x01,0x93,0x00,0x01,0x00,0xb8,0xff,0xe8,0x05,0x54,0x05,0xb2,0x00,0x16,0x00,0x2a,0x40,0x16,0x04,0x91,0x14,0x13,0x00,0x03,0x0b,0x09,0x91,0x0e,0x04,0x0b,0x0b,0x01, 0x11,0x7d,0x07,0x07,0x18,0x01,0x7e,0x00,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0x3f,0xed,0x31,0x30,0x13,0x33,0x11,0x10,0x21,0x32,0x00,0x11,0x10,0x21,0x22,0x07,0x35,0x36,0x33,0x32,0x12,0x11,0x10,0x00,0x21,0x20,0x11,0xb8,0xa8,0x01,0x58,0xd9,0x01,0x17,0xfe,0xf8,0x48,0x40,0x4d,0x57,0xba,0xde, 0xfe,0x81,0xfe,0xdb,0xfe,0x08,0x05,0x9a,0xfc,0xac,0xfe,0x39,0x01,0x91,0x01,0x25,0x01,0xe5,0x1c,0x9a,0x1a,0xfe,0xad,0xfe,0xe3,0xfe,0x99,0xfe,0x0d,0x02,0x56,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x04,0xd6,0x05,0xb2,0x00,0x15,0x00,0x2b,0x40,0x16,0x00,0x15,0x14,0x03,0x14,0x0c,0x11,0x7e,0x14,0x03,0x14,0x11,0x03,0x13,0x15,0x03, 0x13,0x12,0x0e,0x91,0x09,0x03,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x17,0x39,0x01,0x2f,0xfd,0xc6,0x12,0x39,0x10,0xcd,0x32,0x31,0x30,0x13,0x01,0x16,0x17,0x33,0x37,0x13,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x01,0x11,0x23,0x11,0x01,0xc1,0x01,0x50,0x1b,0x0c,0x02,0x23,0xc7,0x46,0x8e,0x6b,0x39,0x3a,0x2f,0x3a,0x5a,0x54, 0xfe,0xd1,0xa8,0xfe,0x27,0x05,0x9a,0xfd,0x78,0x33,0x25,0x58,0x01,0x9a,0x91,0x75,0x18,0x9c,0x1c,0xaa,0xfd,0x9e,0xfd,0xf2,0x02,0x12,0x03,0x88,0x00,0x01,0x00,0x0e,0xfe,0x1e,0x04,0x60,0x04,0x18,0x00,0x1c,0x00,0x2f,0x40,0x19,0x14,0x05,0x0f,0x0a,0x0c,0x95,0x07,0x1c,0x10,0x0f,0x00,0x02,0x95,0x1a,0x10,0x0a,0x05,0x0a,0x0f,0x14, 0x04,0x10,0x00,0x1e,0x10,0x2f,0x10,0xc6,0x11,0x17,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0x3f,0xfd,0xc6,0x2f,0x33,0x33,0x31,0x30,0x01,0x26,0x23,0x22,0x07,0x01,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x12,0x33,0x32,0x17,0x04,0x60,0x2c,0x2c,0x66,0x42,0xfe,0x9e,0x7d,0xe5, 0x42,0x29,0x33,0x2e,0x7c,0x3e,0x52,0xfe,0x70,0xb6,0x01,0x15,0x0a,0x0b,0x06,0x05,0x0f,0xc0,0x6d,0xd1,0x29,0x31,0x03,0x79,0x13,0xa8,0xfc,0x78,0xfe,0xc2,0x0d,0x93,0x12,0x94,0xc2,0x03,0xfe,0xfc,0xec,0x1c,0x32,0x1a,0x34,0x02,0x06,0x01,0x26,0x10,0x00,0x01,0x00,0x21,0x00,0x00,0x04,0x64,0x05,0x9a,0x00,0x11,0x00,0x5a,0x40,0x2e, 0x02,0x02,0x01,0x04,0x01,0x05,0x00,0x05,0x0b,0x0b,0x0a,0x0d,0x0a,0x09,0x0e,0x09,0x04,0x01,0x0a,0x91,0x40,0x0d,0x10,0x08,0x0d,0x91,0x14,0x30,0x09,0x05,0x91,0x08,0x12,0x00,0x0e,0x91,0x10,0x03,0x06,0x0e,0x00,0x00,0x13,0x05,0x0f,0x09,0x2f,0xc6,0x33,0x12,0x39,0x2f,0x33,0xc6,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x2b,0x00,0x18, 0x2f,0x1a,0xed,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x11,0x01,0x33,0x2f,0x10,0x87,0xc0,0xc0,0x11,0x01,0x33,0x2f,0x31,0x30,0x01,0x01,0x33,0x15,0x21,0x01,0x21,0x15,0x21,0x35,0x01,0x23,0x35,0x21,0x01,0x21,0x35,0x21,0x04,0x64,0xfe,0x71,0xfc,0xfe,0x9d,0xfe,0xae,0x03,0x34,0xfb,0xd1,0x01,0x99,0xe3,0x01,0x4a,0x01,0x41,0xfd,0x00, 0x04,0x02,0x05,0x72,0xfd,0xb3,0x97,0xfe,0x0a,0x98,0x2f,0x02,0x5f,0x97,0x01,0xdd,0x98,0x00,0x00,0x01,0x00,0x21,0x00,0x00,0x03,0x70,0x04,0x00,0x00,0x11,0x00,0x5a,0x40,0x2e,0x02,0x02,0x01,0x04,0x01,0x05,0x00,0x05,0x0b,0x0b,0x0a,0x0d,0x0a,0x09,0x0e,0x09,0x04,0x01,0x0a,0x95,0x40,0x0d,0x10,0x08,0x0d,0x95,0x14,0x30,0x09,0x05, 0x95,0x08,0x15,0x00,0x0e,0x95,0x10,0x0f,0x06,0x0e,0x00,0x00,0x13,0x05,0x0f,0x09,0x2f,0xc6,0x33,0x12,0x39,0x2f,0x33,0xc6,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x11,0x01,0x33,0x2f,0x10,0x87,0xc0,0xc0,0x11,0x01,0x33,0x2f,0x31,0x30,0x01,0x01,0x33,0x15,0x21,0x03, 0x21,0x15,0x21,0x35,0x01,0x23,0x35,0x21,0x13,0x21,0x35,0x21,0x03,0x70,0xfe,0xec,0xbc,0xfe,0xe0,0xe6,0x02,0x58,0xfc,0xb7,0x01,0x27,0xa8,0x01,0x0c,0xd3,0xfd,0xdb,0x03,0x16,0x03,0xd1,0xfe,0x83,0x8c,0xfe,0xc4,0x8c,0x33,0x01,0x95,0x8c,0x01,0x20,0x8c,0x00,0x00,0x01,0x00,0x0a,0xfe,0x1e,0x04,0x83,0x05,0x9a,0x00,0x18,0x00,0x44, 0x40,0x24,0x0b,0x0a,0x91,0x40,0x11,0x0e,0x17,0x11,0x91,0x09,0x30,0x01,0x03,0x91,0x17,0x1c,0x10,0x0c,0x91,0x0e,0x03,0x11,0x0b,0x0b,0x06,0x00,0x0c,0x10,0x10,0x14,0x7d,0x06,0x06,0x1a,0x0d,0x00,0x2f,0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0xed,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a, 0xed,0x39,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x24,0x35,0x34,0x24,0x21,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x04,0x00,0x15,0x10,0x00,0x21,0x22,0x0a,0xe0,0xde,0xe9,0x01,0x22,0xfe,0xd1,0xfe,0xf6,0x5c,0x01,0xf5,0xfc,0xf4,0x04,0x02,0xfe,0x02,0x01,0x11,0x01,0x47,0xfe,0x6f,0xfe,0xd4,0xe8,0xfe,0x89,0xb5,0x88,0xef,0xbf,0xcc, 0xe2,0x4c,0x02,0xa4,0x98,0x4c,0xfd,0x52,0x17,0xfe,0xd0,0xef,0xff,0x00,0xfe,0xb4,0x00,0x01,0x00,0x5e,0xfe,0x1e,0x04,0xd7,0x05,0x9a,0x00,0x18,0x00,0x40,0x40,0x22,0x0e,0x0f,0x91,0x40,0x08,0x0a,0x02,0x08,0x91,0x09,0x30,0x18,0x16,0x91,0x02,0x1c,0x09,0x0d,0x91,0x0a,0x03,0x08,0x0e,0x0e,0x13,0x0c,0x18,0x18,0x1a,0x0d,0x09,0x13, 0x7d,0x05,0x2f,0xe1,0xc4,0x32,0x12,0x39,0x2f,0xc6,0x12,0x39,0x2f,0x33,0x00,0x3f,0xed,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x06,0x23,0x20,0x00,0x11,0x34,0x00,0x25,0x01,0x35,0x21,0x15,0x21,0x01,0x15,0x23,0x20,0x04,0x15,0x14,0x04,0x33,0x32,0x37,0x04,0xd7,0xd5,0xfc,0xfe,0xd5,0xfe,0x83,0x01, 0x4e,0x01,0x0a,0xfe,0x02,0x04,0x02,0xfc,0xf6,0x01,0xf4,0x5c,0xfe,0xf8,0xfe,0xce,0x01,0x22,0xe8,0xf0,0xcf,0xfe,0x89,0x6b,0x01,0x3e,0x01,0x02,0xeb,0x01,0x40,0x17,0x02,0xae,0x4c,0x98,0xfd,0x5c,0x4c,0xe5,0xc9,0xbf,0xef,0x7d,0x00,0x01,0x00,0x1e,0xfe,0x21,0x03,0xaa,0x04,0x00,0x00,0x18,0x00,0x3e,0x40,0x21,0x0e,0x0f,0x96,0x40, 0x08,0x0a,0x02,0x08,0x96,0x09,0x30,0x18,0x16,0x95,0x02,0x1c,0x09,0x0d,0x95,0x0a,0x0f,0x08,0x0e,0x0e,0x13,0x0c,0x18,0x1a,0x0d,0x09,0x13,0x83,0x05,0x2f,0xe1,0xc4,0x32,0x10,0xd6,0xc6,0x12,0x39,0x2f,0x33,0x00,0x3f,0xed,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x24,0x35,0x34,0x36, 0x37,0x01,0x35,0x21,0x15,0x21,0x01,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x03,0xaa,0x9a,0xca,0xf4,0xfe,0xcc,0xf7,0xcf,0xfe,0x76,0x03,0x2d,0xfd,0xc5,0x01,0x7a,0x54,0xc8,0xe4,0xda,0xaa,0xc4,0x9c,0xfe,0x72,0x51,0xf9,0xcc,0xb0,0xfb,0x1d,0x02,0x1f,0x33,0x8c,0xfd,0xec,0x33,0xab,0x96,0x8d,0xb3,0x62,0x00,0x00,0x01, 0x00,0x0a,0xfe,0x1e,0x03,0x08,0x04,0x00,0x00,0x22,0x00,0x58,0x40,0x30,0x19,0x0b,0x06,0x1f,0x04,0x03,0x10,0x0f,0x96,0x40,0x16,0x13,0x03,0x16,0x96,0x08,0x30,0x00,0x21,0x95,0x03,0x1c,0x15,0x11,0x95,0x13,0x0f,0x16,0x11,0x15,0x10,0x10,0x0b,0x06,0x15,0x15,0x19,0x00,0x00,0x19,0x84,0x0b,0x0b,0x24,0x12,0x1f,0x83,0x06,0x2f,0xe1, 0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x10,0xc0,0x2f,0x11,0x12,0x39,0x2f,0x12,0x39,0x39,0x00,0x3f,0xed,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x12,0x17,0x39,0x31,0x30,0x05,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x06, 0x07,0x06,0x06,0x15,0x14,0x33,0x32,0x02,0x9e,0x89,0xb9,0xa0,0xb2,0x01,0x38,0xa4,0x7e,0x9e,0x8e,0x52,0x01,0x1a,0xfe,0x0a,0x02,0xd8,0xfe,0xda,0x9e,0xae,0xa6,0xc4,0x93,0x59,0xb8,0xaa,0xfc,0x9e,0x48,0x7d,0x6f,0xc5,0x66,0x36,0x6d,0x59,0x5a,0x67,0x3d,0x01,0x45,0x8c,0x46,0xfe,0xae,0x12,0xa2,0x81,0x7e,0xaf,0x44,0x32,0x45,0x35, 0x6c,0x00,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0xc2,0x05,0xb2,0x00,0x1b,0x00,0x6e,0x40,0x38,0x1a,0x01,0x02,0x18,0x02,0x0a,0x07,0x06,0x0d,0x06,0x01,0x1a,0x07,0x99,0x0a,0x0a,0x02,0x10,0x18,0x0d,0x15,0x06,0x02,0x99,0x05,0x18,0x12,0x10,0x9a,0x15,0x07,0x08,0x08,0x12,0x07,0x1a,0x01,0x18,0x02,0x0a,0x07,0x0d,0x06,0x00,0x00,0x18, 0x04,0x04,0x18,0x8a,0x0d,0x0d,0x1d,0x12,0x02,0x06,0x2f,0x33,0xc6,0x12,0x39,0x2f,0xf9,0xc0,0x2f,0x10,0xc2,0x2f,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x32,0x12,0x39,0x39,0x11,0x12,0x39,0x2f,0xed,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x31,0x30,0x01,0x21, 0x01,0x21,0x15,0x21,0x35,0x01,0x23,0x35,0x21,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x33,0x03,0xc2,0xfe,0xde,0xfe,0x85,0x02,0x9b,0xfc,0xa0,0x01,0x7f,0xfd,0x01,0x84,0x69,0x52,0x90,0x81,0xbe,0xb2,0xa2,0xe5,0xc0,0xdb,0x9f,0x9f,0x02,0x2b,0xfe,0x69,0x94,0x92,0x01,0x99,0x93,0x77,0x9d, 0x55,0x78,0x88,0xa4,0xac,0x83,0xcf,0xb0,0xaf,0xc6,0x00,0x01,0x00,0x74,0xff,0xe8,0x03,0xc8,0x05,0x9a,0x00,0x1d,0x00,0x42,0x40,0x24,0x0d,0x14,0x09,0x9a,0x40,0x16,0x10,0x1c,0x16,0x9a,0x08,0x30,0x01,0x03,0x95,0x1c,0x16,0x13,0x0e,0x99,0x10,0x06,0x11,0x11,0x19,0x89,0x06,0x06,0x1f,0x0e,0x13,0x14,0x03,0x0d,0x0f,0x00,0x2f,0xc6, 0xc4,0x17,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x32,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x33,0x32,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x23,0x13,0x23,0x35,0x21,0x15,0x21,0x03,0x36,0x33,0x32,0x16,0x15,0x14,0x04,0x23,0x22,0xa4,0x93,0x98,0x99,0xb9,0xbe,0xb1,0x32, 0x4d,0x5f,0x07,0x45,0x9e,0x03,0x13,0xfe,0x25,0x33,0x41,0x2c,0xe7,0xfb,0xfe,0xf1,0xec,0xbd,0x23,0xae,0x5f,0xad,0x8d,0x8e,0x9d,0x05,0x07,0x02,0x3b,0x94,0x94,0xfe,0x5c,0x04,0xe6,0xca,0xd0,0xfe,0x00,0x01,0x00,0x48,0xff,0xe8,0x02,0xcd,0x04,0x00,0x00,0x1b,0x00,0x42,0x40,0x24,0x0b,0x12,0x09,0x95,0x40,0x14,0x0e,0x1a,0x14,0x95, 0x08,0x30,0x01,0x03,0x95,0x1a,0x16,0x11,0x0c,0x95,0x0e,0x0f,0x10,0x10,0x17,0x83,0x06,0x06,0x1d,0x0c,0x11,0x12,0x03,0x0b,0x0d,0x00,0x2f,0xc6,0xc4,0x17,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x32,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x33,0x32,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23, 0x22,0x07,0x13,0x23,0x35,0x21,0x15,0x21,0x07,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x5a,0x72,0x7a,0x64,0x7b,0x83,0x73,0x17,0xa6,0x3e,0x68,0x02,0x5c,0xfe,0xa2,0x28,0x32,0x14,0x9d,0xcc,0xd5,0xb2,0x9e,0x18,0xa6,0x4c,0x6c,0x57,0x54,0x65,0x08,0x01,0x8e,0x8c,0x8c,0xfd,0x02,0xa7,0x94,0x97,0xbf,0x00,0x00,0x01,0x00,0x1e, 0xff,0xe8,0x02,0xe4,0x05,0x2f,0x00,0x20,0x00,0x41,0x40,0x21,0x1c,0x05,0x1f,0x0f,0x01,0x03,0x95,0x1f,0x16,0x11,0x15,0x12,0x0c,0x95,0x0f,0x0f,0x14,0x14,0x15,0x1c,0x83,0x05,0x05,0x22,0x12,0x0f,0x15,0x84,0x0c,0x01,0x01,0x0d,0x0c,0x2f,0xcd,0x39,0x2f,0x10,0xe1,0x39,0x39,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x39, 0x39,0xcd,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x39,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x35,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x70,0x76,0x95,0xc3,0x38,0x7d,0x92,0x5b,0x7e,0x7e,0xa4,0x01,0x02,0xfe,0xfe,0x46,0x66,0x89,0x6f,0xc9, 0xad,0x96,0x25,0xb0,0x63,0x90,0x2e,0x4b,0x3f,0x4c,0x9b,0x6d,0x66,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0x62,0x4b,0x5e,0x31,0x44,0x8c,0x5e,0x7f,0xa3,0x00,0x02,0x00,0xa6,0xfe,0x29,0x04,0x16,0x04,0x18,0x00,0x0c,0x00,0x15,0x00,0x2c,0x40,0x17,0x02,0x1b,0x05,0x07,0x0e,0x95,0x00,0x03,0x0f,0x14,0x95,0x07,0x10,0x0a,0x83,0x11,0x11,0x17, 0x0e,0x05,0x01,0x84,0x02,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x2f,0xed,0x12,0x39,0x3f,0x31,0x30,0x05,0x11,0x23,0x11,0x33,0x15,0x36,0x33,0x32,0x16,0x15,0x14,0x00,0x01,0x11,0x36,0x00,0x35,0x34,0x26,0x23,0x22,0x01,0x4a,0xa4,0xa4,0xac,0xc2,0x97,0xc7,0xfe,0x84,0xfe,0xb0,0xf2,0x01,0x32,0x70,0x5c,0x9e, 0x2d,0xfe,0x56,0x05,0xd7,0x81,0x99,0xc4,0x92,0xdf,0xfe,0x72,0x02,0x80,0xfd,0x9b,0x61,0x01,0x34,0xad,0x5d,0x7a,0x00,0x01,0x00,0xac,0xfe,0x1e,0x01,0x40,0x06,0x1e,0x00,0x03,0x00,0x0f,0xb6,0x03,0xfa,0x00,0x1c,0x00,0xca,0x01,0x2f,0xe1,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x40,0x94,0x94,0xfe,0x1e,0x08,0x00,0x00, 0x00,0x02,0x00,0xac,0xfe,0x1e,0x02,0x66,0x06,0x1e,0x00,0x03,0x00,0x07,0x00,0x25,0x40,0x12,0x02,0x01,0x06,0x05,0x1c,0x06,0xfa,0x00,0xca,0x01,0x01,0x09,0x04,0xca,0x00,0x05,0x01,0x05,0x2f,0x5d,0xe1,0x12,0x39,0x7c,0x2f,0xe1,0x00,0x18,0x3f,0x3f,0x12,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x23,0x11,0x33,0x02,0x66,0x93, 0x93,0xfe,0xda,0x94,0x94,0xfe,0x1e,0x08,0x00,0xf8,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x33,0xfe,0x1e,0x03,0x72,0x06,0x1e,0x00,0x13,0x00,0x4f,0x40,0x2c,0x12,0x01,0x04,0x95,0x07,0x11,0x0e,0x0b,0x95,0x08,0x40,0x0c,0x03,0x08,0x07,0x08,0x3a,0x03,0x1c,0x0c,0xfa,0x10,0x09,0x00,0x05,0x08,0x0b,0x0e,0x11,0x04,0x02,0x00,0x03,0x05, 0x05,0x02,0xca,0x03,0x14,0x15,0x03,0xca,0x08,0x30,0x2b,0x01,0x10,0xf1,0xc0,0x18,0x2f,0x10,0xc4,0x12,0x17,0x39,0x11,0x12,0x39,0x39,0x00,0x3f,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xed,0x39,0x39,0x10,0xed,0x39,0x39,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x03, 0x72,0xfe,0xaa,0x93,0xfe,0xaa,0x01,0x56,0xfe,0xaa,0x01,0x56,0x93,0x01,0x56,0xfe,0xaa,0x01,0x56,0x01,0x46,0xfc,0xd8,0x03,0x28,0x8b,0x01,0x17,0x8a,0x02,0xac,0xfd,0x54,0x8a,0xfe,0xe9,0xff,0xff,0x00,0xb4,0xff,0xee,0x01,0x92,0x05,0x9a,0x02,0x06,0x00,0x04,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x09,0xbc,0x07,0x62,0x00,0x26, 0x00,0x27,0x00,0x00,0x00,0x27,0x00,0x3d,0x05,0x58,0x00,0x00,0x01,0x07,0x00,0xe0,0x06,0x43,0x01,0x56,0x00,0x13,0x40,0x0b,0x03,0x05,0x1f,0x1f,0x18,0x19,0x25,0x03,0x1c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x08,0xef,0x06,0x0c,0x00,0x26,0x00,0x27,0x00,0x00,0x00,0x27,0x00,0x5d,0x05,0x7f, 0x00,0x00,0x01,0x07,0x00,0xe0,0x05,0xf5,0x00,0x00,0x00,0x13,0x40,0x0b,0x03,0x0e,0x1f,0x1f,0x18,0x19,0x25,0x03,0x1c,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x08,0x05,0x06,0x0c,0x00,0x26,0x00,0x47,0x00,0x00,0x00,0x27,0x00,0x5d,0x04,0x95,0x00,0x00,0x01,0x07,0x00,0xe0,0x05,0x0c,0x00,0x00, 0x00,0x13,0x40,0x0b,0x03,0x0e,0x2d,0x2d,0x26,0x27,0x25,0x03,0x2a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xff,0xe8,0x06,0x29,0x05,0x9a,0x00,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0x2d,0x03,0xfe,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0x02,0xed,0xb4,0x0c,0x12,0x02,0x05,0x25,0x01,0x2b,0x35,0xff,0xff, 0x00,0xbc,0xfe,0x1e,0x05,0x39,0x05,0xd9,0x00,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x00,0x4d,0x03,0xd3,0x00,0x00,0x00,0x10,0xb1,0x02,0x01,0xb8,0x01,0xf3,0xb4,0x18,0x0f,0x02,0x05,0x25,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xa6,0xfe,0x1e,0x03,0x77,0x05,0xec,0x00,0x26,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x4d,0x02,0x11,0x00,0x00, 0xff,0xff,0x00,0xbc,0xff,0xe8,0x07,0xe4,0x05,0x9a,0x00,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0x2d,0x05,0xb9,0x00,0x00,0x00,0x0e,0xb9,0x00,0x01,0x03,0xda,0xb4,0x1a,0x20,0x0a,0x13,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0xfe,0x1e,0x07,0x34,0x05,0xd9,0x00,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0x4d,0x05,0xce,0x00,0x00, 0x00,0x10,0xb1,0x02,0x01,0xb8,0x03,0x20,0xb4,0x26,0x1d,0x0a,0x13,0x25,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xa6,0xfe,0x1e,0x05,0xed,0x05,0xd9,0x00,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0x4d,0x04,0x87,0x00,0x00,0x00,0x10,0xb1,0x02,0x01,0xb8,0x02,0x88,0xb4,0x25,0x1c,0x0a,0x12,0x25,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x16, 0x00,0x00,0x05,0x12,0x07,0x62,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x12,0x01,0x56,0x00,0x16,0xb9,0x00,0x02,0xff,0xfd,0x40,0x09,0x13,0x10,0x05,0x00,0x25,0x02,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x06,0x0c,0x00,0x26,0x00,0x44,0xf8,0x00,0x01,0x06,0x00,0xe0, 0x7f,0x00,0x00,0x13,0x40,0x0b,0x02,0x18,0x23,0x20,0x08,0x14,0x25,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xf7,0x00,0x00,0x02,0x29,0x07,0x62,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x00,0xe0,0xff,0x91,0x01,0x56,0x00,0x13,0x40,0x0b,0x01,0x00,0x07,0x04,0x02,0x03,0x25,0x01,0x06,0x05,0x26,0x00, 0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xdf,0x00,0x00,0x02,0x11,0x06,0x0c,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x00,0xe0,0xff,0x79,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x07,0x04,0x02,0x03,0x25,0x01,0x06,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x62,0x02,0x26, 0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x85,0x01,0x56,0x00,0x13,0x40,0x0b,0x02,0x00,0x1b,0x18,0x03,0x09,0x25,0x02,0x1a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x0c,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xd9,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00, 0x1b,0x18,0x03,0x09,0x25,0x02,0x1a,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x62,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x41,0x01,0x56,0x00,0x13,0x40,0x0b,0x01,0x00,0x11,0x0e,0x05,0x0d,0x25,0x01,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff, 0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x0c,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xc4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x0a,0x15,0x12,0x08,0x11,0x25,0x01,0x14,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x9a,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x05,0x51, 0x00,0x69,0x01,0x60,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x00,0x21,0x1b,0x05,0x0d,0x25,0x03,0x02,0x01,0x1e,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x3a,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x06,0x60,0xe9,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x07, 0x25,0x1f,0x08,0x11,0x25,0x03,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x08,0x42,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x05,0x54,0x00,0x80,0x01,0x60,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x0a,0x21,0x0e,0x05,0x0d,0x25,0x03,0x02,0x01,0x1e,0x05, 0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0xe2,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x05,0x54,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x10,0x25,0x12,0x08,0x11,0x25,0x03,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00, 0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x08,0x5a,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x05,0x53,0x00,0x80,0x01,0x60,0x00,0x1f,0x40,0x12,0x03,0x02,0x01,0x00,0x24,0x1e,0x05,0x0d,0x25,0x03,0x02,0x01,0x30,0x21,0x01,0x21,0x05,0x26,0x00,0x2b,0x71,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8, 0x03,0xe2,0x06,0xfa,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x06,0x61,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x07,0x28,0x22,0x08,0x11,0x25,0x03,0x02,0x01,0x25,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x08,0x42,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07, 0x06,0x62,0x00,0x6d,0x01,0x60,0x00,0x1e,0xb2,0x03,0x02,0x01,0xb8,0xff,0xf7,0x40,0x0b,0x10,0x1b,0x05,0x0d,0x25,0x03,0x02,0x01,0x1e,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0xe2,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x06,0x62,0xee,0x00,0x00,0x1b,0x40,0x0f, 0x03,0x02,0x01,0x00,0x14,0x1f,0x08,0x11,0x25,0x03,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0x00,0x02,0x00,0x52,0xff,0xe8,0x03,0xcf,0x04,0x18,0x00,0x12,0x00,0x19,0x00,0x48,0x40,0x21,0x06,0x40,0x0b,0x0e,0x48,0x06,0x06,0x04,0x13,0x95,0x40,0x01,0x09,0x0f,0x01,0x95,0x08,0x30,0x17,0x95, 0x0f,0x16,0x04,0x95,0x09,0x10,0x0c,0x83,0x01,0x13,0x13,0x1b,0x06,0xb8,0xff,0xc0,0xb6,0x0e,0x12,0x48,0x06,0x14,0x83,0x00,0x2f,0xe1,0xc6,0x2b,0x12,0x39,0x2f,0xc5,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0x2b,0x31,0x30,0x13,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x12,0x15,0x14, 0x00,0x23,0x22,0x02,0x35,0x05,0x21,0x16,0x16,0x33,0x32,0x36,0x52,0x02,0xd3,0x05,0xae,0x9b,0xad,0x90,0x86,0xde,0xd9,0xf8,0xfe,0xf1,0xc8,0xcb,0xdb,0x02,0xd1,0xfd,0xd7,0x02,0x86,0x78,0x74,0xa2,0x02,0x29,0xab,0xba,0x72,0x9a,0x62,0xfe,0xe9,0xfd,0xf1,0xfe,0xd5,0x01,0x06,0xe5,0x35,0x8f,0x9d,0xa6,0xff,0xff,0x00,0x16,0x00,0x00, 0x05,0x12,0x07,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x05,0x51,0x00,0x33,0x01,0x60,0x00,0x1e,0xb2,0x04,0x03,0x02,0xb8,0xff,0xf6,0x40,0x0b,0x23,0x1d,0x05,0x00,0x25,0x04,0x03,0x02,0x20,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x06,0x3a,0x00,0x26,0x00,0x44, 0xf8,0x00,0x01,0x06,0x06,0x60,0xa3,0x00,0x00,0x1b,0x40,0x0f,0x04,0x03,0x02,0x14,0x33,0x2d,0x08,0x14,0x25,0x04,0x03,0x02,0x30,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x9a,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x05,0x52,0x00,0x90,0x01,0x65,0x00,0x17, 0x40,0x0d,0x03,0x02,0x00,0x12,0x13,0x05,0x00,0x25,0x03,0x02,0x14,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x06,0x35,0x00,0x26,0x00,0x44,0xf8,0x00,0x01,0x06,0x06,0x63,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x20,0x22,0x23,0x08,0x14,0x25,0x03,0x02,0x24,0x11,0x26,0x00, 0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x0a,0x00,0x00,0x06,0x83,0x06,0x8c,0x02,0x26,0x00,0x91,0x00,0x00,0x01,0x07,0x00,0xd9,0x03,0x5a,0x01,0x5d,0x00,0x16,0xb9,0x00,0x02,0x01,0x50,0x40,0x09,0x16,0x17,0x05,0x0f,0x25,0x02,0x15,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x52,0xff,0xe8,0x06,0x4e, 0x05,0x2f,0x00,0x26,0x00,0xa0,0xf8,0x00,0x01,0x07,0x00,0xd9,0x02,0x1a,0x00,0x00,0x00,0x13,0x40,0x0b,0x03,0x06,0x38,0x39,0x11,0x23,0x25,0x03,0x37,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x05,0x7d,0x05,0xb2,0x00,0x21,0x00,0x61,0x40,0x37,0x01,0x20,0x18,0x92,0x0f,0x1b,0x1f,0x1b,0x2f,0x1b, 0x03,0x1b,0x1b,0x17,0x1c,0x91,0x1e,0x1e,0x0a,0x02,0x17,0x15,0x91,0x04,0x13,0x1f,0x0d,0x2f,0x0d,0x02,0x0d,0x0f,0x91,0x0a,0x04,0x00,0x00,0x1f,0x1a,0x1d,0x1d,0x1c,0x12,0x0d,0x0d,0x01,0x18,0x1f,0x7e,0x1c,0x1c,0x23,0x12,0x7d,0x07,0x2f,0xe9,0x12,0x39,0x2f,0xf9,0x39,0x39,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xc6,0x10,0xc0,0x2f,0x00, 0x3f,0xfd,0xc6,0x5d,0x3f,0xed,0x32,0x32,0x11,0x39,0x2f,0xed,0x11,0x39,0x2f,0x5d,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x15,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x35,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x05,0x7d,0x91,0xd8,0xfe,0xf8,0xfe,0xcd,0xfe, 0x85,0x01,0xa5,0x01,0x43,0xea,0x9f,0xae,0xee,0xf1,0xfe,0xcc,0x01,0x1e,0xf5,0xa8,0x7b,0xfe,0xc8,0x01,0x38,0xfe,0xc6,0x01,0xe2,0x91,0x01,0x31,0xcf,0x7a,0x01,0x8c,0x01,0x46,0x01,0x4d,0x01,0xab,0x4c,0xba,0x6e,0xfe,0xb4,0xfe,0xf8,0xfe,0xf0,0xfe,0xc9,0x43,0x6f,0x8b,0x98,0x98,0xfe,0xd0,0x00,0x02,0x00,0x60,0xfe,0x1e,0x04,0xb6, 0x04,0x18,0x00,0x22,0x00,0x2f,0x00,0x77,0x40,0x12,0x22,0x00,0x0f,0x0b,0x01,0x17,0x03,0x0b,0x95,0x40,0x0c,0x13,0x08,0x0c,0x95,0x08,0x30,0x06,0xb8,0xff,0xc0,0x40,0x2d,0x0b,0x0f,0x48,0x06,0x06,0x08,0x95,0x03,0x1c,0x1c,0x10,0x19,0x2d,0x95,0x13,0x1e,0x0f,0x27,0x95,0x19,0x10,0x21,0x01,0x1f,0x0d,0x0a,0x0f,0x06,0x22,0x22,0x1f, 0x0c,0x0c,0x16,0x1f,0x84,0x23,0x1d,0x0f,0x0f,0x31,0x2a,0x83,0x06,0x16,0x2f,0xc4,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x12,0x39,0x2f,0x10,0xc2,0x2f,0x11,0x12,0x39,0x39,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0x2f,0xed,0x12,0x39,0x39,0x3f,0xed,0x32,0x2f,0x2b,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x5f,0x5e,0x5d,0x39,0x39,0x31,0x30,0x05, 0x23,0x02,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x21,0x35,0x21,0x36,0x35,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x14,0x07,0x33,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xb6,0xdb,0x77,0xfe,0x90,0xbe,0x8e,0xad,0x9d,0xda,0x5d,0xfe,0xb4,0x01,0x83,0x0c, 0x04,0x75,0xeb,0xbd,0xeb,0x01,0x00,0xd5,0xcf,0x64,0x04,0xa4,0x0c,0xb2,0xfe,0xb6,0xa5,0x7b,0x97,0xad,0xa7,0x86,0x8a,0xad,0xd1,0xfe,0xef,0x48,0xa4,0x60,0x85,0x8b,0x3d,0x45,0x99,0xc5,0x01,0x0c,0xd8,0xf5,0x01,0x2f,0xa6,0x8e,0xfc,0x52,0x50,0x48,0x02,0x3e,0x6e,0x7a,0xae,0xd6,0xba,0x9d,0xc5,0xc2,0xff,0xff,0x00,0x5e,0xff,0xe8, 0x04,0xec,0x07,0x62,0x02,0x26,0x00,0x2a,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x5c,0x01,0x56,0x00,0x13,0x40,0x0b,0x01,0x36,0x1d,0x1a,0x05,0x19,0x25,0x01,0x1c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x06,0x0c,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xc2,0x00,0x00, 0x00,0x13,0x40,0x0b,0x02,0x09,0x29,0x26,0x10,0x18,0x25,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2,0x07,0x62,0x02,0x26,0x00,0x2e,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xdd,0x01,0x56,0x00,0x16,0xb9,0x00,0x01,0xff,0xad,0x40,0x09,0x14,0x11,0x08,0x00,0x25,0x01,0x13,0x05,0x26, 0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x07,0x62,0x02,0x26,0x00,0x4e,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0x81,0x01,0x56,0x00,0x16,0xb9,0x00,0x01,0xff,0xb1,0x40,0x09,0x10,0x0d,0x06,0x00,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x02,0x00,0x5e,0xfe,0x70,0x05,0xaa,0x05,0xb2, 0x00,0x19,0x00,0x25,0x00,0x50,0xb1,0x06,0x04,0xb8,0x01,0x05,0x40,0x0b,0x09,0x20,0x91,0x0e,0x00,0x13,0x1a,0x91,0x14,0x04,0x0e,0xb8,0x01,0x04,0xb5,0x00,0x00,0x02,0x06,0x06,0x02,0xb8,0x01,0x04,0x40,0x0f,0x0c,0x0c,0x19,0x0f,0x19,0x0f,0x11,0x17,0x7d,0x23,0x23,0x27,0x1d,0x7d,0x11,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39, 0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x10,0xc2,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x33,0xed,0x2f,0xfd,0xc6,0x31,0x30,0x05,0x06,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x24,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x03,0x48,0x80,0x44, 0x1e,0x1a,0x1e,0x34,0x4c,0x5c,0x83,0xfe,0xe5,0xfe,0xac,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0xb9,0xfe,0xa7,0xe2,0xfe,0xe6,0x01,0x13,0xdd,0xec,0x01,0x10,0xfe,0xf8,0x14,0x7e,0x4d,0x46,0x0d,0x6b,0x0d,0x50,0x46,0x6f,0x75,0x11,0x01,0x8d,0x01,0x34,0x01,0x5a,0x01,0x9c,0xfe,0x70,0xfe,0xbd,0xfe,0xba,0xfe,0x6b,0x05,0x16, 0xfe,0xba,0xfe,0xf7,0xfe,0xf7,0xfe,0xbd,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0x00,0x02,0x00,0x60,0xfe,0x70,0x04,0x50,0x04,0x18,0x00,0x19,0x00,0x25,0x00,0x4c,0xb1,0x06,0x04,0xb8,0x01,0x05,0x40,0x0b,0x09,0x20,0x95,0x00,0x0e,0x16,0x1a,0x95,0x14,0x10,0x0e,0xb8,0x01,0x04,0xb3,0x00,0x06,0x06,0x02,0xb8,0x01,0x04,0x40,0x0f, 0x0c,0x0c,0x19,0x0f,0x19,0x0f,0x11,0x17,0x83,0x23,0x23,0x27,0x1d,0x83,0x11,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0xd6,0xe1,0x00,0x3f,0xed,0x3f,0x33,0xed,0x2f,0xfd,0xc6,0x31,0x30,0x05,0x06,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x02,0x35,0x10,0x00, 0x33,0x32,0x00,0x15,0x14,0x02,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0xa2,0x81,0x43,0x1e,0x1a,0x1e,0x34,0x4c,0x5c,0x83,0xd0,0xf5,0x01,0x1a,0xf0,0xe5,0x01,0x01,0xe6,0xfe,0xf4,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab,0x14,0x80,0x4b,0x46,0x0d,0x6b,0x0d,0x50,0x46,0x6f,0x75,0x0e,0x01,0x1c,0xe0,0x01,0x02, 0x01,0x22,0xfe,0xe6,0xfa,0xde,0xfe,0xdf,0x03,0x89,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0xff,0xff,0x00,0x5e,0xfe,0x70,0x05,0xaa,0x06,0x8c,0x02,0x26,0x05,0x14,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0xd2,0x01,0x5d,0x00,0x13,0x40,0x0b,0x02,0x0a,0x28,0x29,0x11,0x17,0x25,0x02,0x27,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x60,0xfe,0x70,0x04,0x50,0x05,0x2f,0x02,0x26,0x05,0x15,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x26,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x0a,0x28,0x29,0x11,0x17,0x25,0x02,0x27,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0a,0xfe,0x1e,0x04,0x83,0x07,0x62,0x02,0x26,0x04,0xe1,0x00,0x00,0x01,0x07, 0x00,0xe0,0x00,0x8b,0x01,0x56,0x00,0x16,0xb9,0x00,0x01,0xff,0xc4,0x40,0x09,0x1c,0x19,0x01,0x14,0x25,0x01,0x1b,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xdd,0xfe,0x21,0x03,0x68,0x06,0x0c,0x00,0x26,0x05,0x97,0x00,0x00,0x01,0x06,0x00,0xe0,0xf8,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0xd5,0x40,0x09,0x1c,0x19,0x01, 0x14,0x25,0x01,0x1b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0x3a,0xfe,0x1e,0x02,0x10,0x06,0x0c,0x02,0x26,0x06,0xac,0x00,0x00,0x01,0x07,0x00,0xe0,0xff,0x78,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0xb5,0x10,0x0d,0x06,0x0c,0x25,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00, 0x09,0xbc,0x05,0x9a,0x00,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0x3d,0x05,0x58,0x00,0x00,0x00,0x0e,0xb9,0x00,0x02,0x04,0x9d,0xb4,0x15,0x19,0x01,0x04,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x08,0xf0,0x05,0x9a,0x00,0x26,0x00,0x27,0x00,0x00,0x01,0x07,0x00,0x5d,0x05,0x80,0x00,0x00,0x00,0x0e,0xb9,0x00,0x02,0x04, 0x4b,0xb4,0x15,0x19,0x01,0x04,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x08,0x06,0x05,0xec,0x00,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x00,0x5d,0x04,0x96,0x00,0x00,0x00,0x0e,0xb9,0x00,0x02,0x04,0x26,0xb4,0x23,0x27,0x08,0x10,0x25,0x01,0x2b,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0xec,0x07,0x68,0x02,0x26,0x00,0x2a, 0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x27,0x01,0x5e,0x00,0x13,0x40,0x0b,0x01,0xcb,0x1c,0x1a,0x05,0x19,0x25,0x01,0x1c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x06,0x0a,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x56,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x67,0x28,0x26, 0x10,0x18,0x25,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xbc,0xff,0xe8,0x07,0x79,0x05,0x9a,0x00,0x17,0x00,0x43,0x40,0x25,0x08,0x91,0x40,0x0d,0x0b,0x0a,0x0d,0x91,0x2b,0x30,0x13,0x91,0x03,0x13,0x0a,0x12,0x17,0x0f,0x10,0x0b,0x03,0x0e,0x0d,0x09,0x10,0x7e,0x07,0x07,0x0a,0x17,0x7e,0x16,0x16,0x19, 0x09,0x7e,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0x33,0x3f,0x3f,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x07,0x79,0xe8,0xcd,0xc9,0xda,0xfd,0x43,0xa8, 0xa8,0x02,0xbd,0xa7,0x01,0x05,0x01,0x04,0xa8,0x01,0xac,0xd6,0xee,0xe5,0xd3,0xee,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfc,0x14,0xfe,0xd1,0x01,0x29,0x02,0x58,0x00,0x02,0x00,0xbc,0xfe,0x29,0x05,0x27,0x05,0xb2,0x00,0x0c,0x00,0x15,0x00,0x2e,0x40,0x18,0x05,0x00,0x07,0x02,0x1b,0x0e,0x91,0x00,0x03,0x03,0x14,0x91,0x07,0x04, 0x0a,0x7d,0x11,0x11,0x17,0x0e,0x05,0x01,0x7e,0x02,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x2f,0xed,0x3f,0x11,0x12,0x39,0x31,0x30,0x05,0x11,0x23,0x11,0x33,0x15,0x36,0x21,0x32,0x12,0x15,0x10,0x00,0x01,0x11,0x24,0x00,0x11,0x34,0x26,0x23,0x22,0x01,0x64,0xa8,0xa8,0xeb,0x01,0x1d,0xc2,0xf9,0xfe,0x03,0xfe, 0x3a,0x01,0x61,0x01,0xb2,0xa3,0x88,0xea,0x3a,0xfe,0x63,0x07,0x71,0xe2,0xfa,0xfe,0xf2,0xc7,0xfe,0xbf,0xfd,0xdb,0x03,0x7f,0xfc,0x78,0x91,0x01,0xc9,0x01,0x03,0x8e,0xbd,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x07,0x68,0x02,0x26,0x00,0x31,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x7d,0x01,0x5e,0x00,0x16,0xb9,0x00,0x01,0xff, 0x93,0x40,0x09,0x16,0x14,0x0a,0x13,0x25,0x01,0x15,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x0a,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0xcb,0x00,0x00,0x00,0x16,0xb9,0x00,0x01,0xff,0x90,0x40,0x09,0x15,0x13,0x0a,0x12,0x25,0x01,0x14,0x11,0x26,0x00,0x2b,0x35,0x01, 0x2b,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x5e,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x6e,0x02,0x1d,0x01,0x5e,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0x8a,0x40,0x0a,0x16,0x10,0x05,0x00,0x25,0x03,0x02,0x15,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x06,0x00, 0x00,0x26,0x00,0x44,0xf8,0x00,0x01,0x07,0x04,0x6e,0x01,0xa1,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xbc,0x40,0x0a,0x26,0x20,0x08,0x14,0x25,0x03,0x02,0x25,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0xf0,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x04,0x2a,0x00,0x00, 0x01,0x5c,0x00,0x13,0x40,0x0b,0x02,0x00,0x17,0x10,0x05,0x00,0x25,0x02,0x17,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x05,0xbc,0x00,0x26,0x00,0x44,0xf8,0x00,0x01,0x06,0x04,0x2a,0xae,0x28,0x00,0x13,0x40,0x0b,0x02,0x20,0x26,0x20,0x08,0x14,0x25,0x02,0x26,0x11,0x26,0x00,0x2b,0x35, 0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x9e,0x00,0x00,0x03,0xb4,0x07,0x5e,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0xc1,0x01,0x5e,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x8a,0x40,0x0a,0x12,0x0c,0x02,0x0b,0x25,0x02,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd, 0x06,0x00,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0xbf,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xa2,0x40,0x0a,0x20,0x1a,0x0c,0x12,0x25,0x03,0x02,0x1f,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x18,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x04,0x2a, 0xff,0xd3,0x01,0x84,0x00,0x16,0xb9,0x00,0x01,0xff,0xf3,0x40,0x09,0x12,0x0c,0x02,0x0b,0x25,0x01,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0xbc,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x06,0x04,0x2a,0xc0,0x28,0x00,0x16,0xb9,0x00,0x02,0xff,0xfa,0x40,0x09,0x20,0x1a,0x0c,0x12,0x25, 0x02,0x20,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0x86,0x00,0x00,0x01,0xce,0x07,0x5e,0x02,0x26,0x00,0x2c,0x00,0x00,0x01,0x07,0x04,0x6e,0x00,0xa9,0x01,0x5e,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x9a,0x40,0x0a,0x0a,0x04,0x02,0x03,0x25,0x02,0x01,0x09,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff, 0xff,0x6e,0x00,0x00,0x01,0xb6,0x06,0x00,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x04,0x6e,0x00,0x91,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x9a,0x40,0x0a,0x0a,0x04,0x02,0x03,0x25,0x02,0x01,0x09,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0xff,0xf8,0x00,0x00,0x02,0x28,0x07,0x18,0x02,0x26,0x00,0x2c, 0x00,0x00,0x01,0x07,0x04,0x2a,0xfe,0xb8,0x01,0x84,0x00,0x13,0x40,0x0b,0x01,0x00,0x0a,0x04,0x02,0x03,0x25,0x01,0x0a,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xe6,0x00,0x00,0x02,0x0a,0x05,0xbe,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x07,0x04,0x70,0x00,0xf8,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x0b,0x04, 0x02,0x03,0x25,0x01,0x0b,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x5e,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x04,0x6e,0x02,0x91,0x01,0x5e,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0x8e,0x40,0x0a,0x1e,0x18,0x03,0x09,0x25,0x03,0x02,0x1d,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x00,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0xe3,0x00,0x00,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0x8c,0x40,0x0a,0x1e,0x18,0x03,0x09,0x25,0x03,0x02,0x1d,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x18, 0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x04,0x2a,0x00,0xac,0x01,0x84,0x00,0x13,0x40,0x0b,0x02,0x00,0x1e,0x18,0x03,0x09,0x25,0x02,0x1e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0xbc,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x04,0x2a,0x00,0x28,0x00,0x13,0x40,0x0b,0x02,0x00, 0x1e,0x18,0x03,0x09,0x25,0x02,0x1e,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa0,0x00,0x00,0x04,0xc0,0x07,0x5e,0x00,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0xc3,0x01,0x5e,0x00,0x0a,0xb4,0x03,0x02,0x2d,0x05,0x26,0x00,0x2b,0x35,0x35,0xff,0xff,0x00,0x04,0x00,0x00,0x02,0xbc,0x06,0x00,0x02,0x26, 0x00,0x55,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0x27,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x77,0x40,0x0a,0x17,0x11,0x08,0x10,0x25,0x02,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xc0,0x07,0x18,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x04,0x2a,0xff,0xfe,0x01,0x84, 0x00,0x08,0xb3,0x02,0x2e,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x9a,0x00,0x00,0x02,0xca,0x05,0xbc,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x04,0x2a,0xff,0x5a,0x00,0x28,0x00,0x13,0x40,0x0b,0x01,0x00,0x17,0x11,0x08,0x10,0x25,0x01,0x17,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5, 0x07,0x5e,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x04,0x6e,0x02,0x54,0x01,0x5e,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x96,0x40,0x0a,0x14,0x0e,0x05,0x0d,0x25,0x02,0x01,0x13,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x06,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x04,0x6e, 0x01,0xd1,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x99,0x40,0x0a,0x18,0x12,0x08,0x11,0x25,0x02,0x01,0x17,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x07,0x18,0x02,0x26,0x00,0x38,0x00,0x00,0x01,0x07,0x04,0x2a,0x00,0x68,0x01,0x84,0x00,0x13,0x40,0x0b,0x01,0x00,0x14,0x0e, 0x05,0x0d,0x25,0x01,0x14,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x90,0xff,0xe8,0x03,0xe2,0x05,0xbc,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x06,0x04,0x2a,0xeb,0x28,0x00,0x13,0x40,0x0b,0x01,0x0a,0x18,0x12,0x08,0x11,0x25,0x01,0x18,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0x10,0xfe,0x21, 0x03,0xcb,0x05,0xb2,0x00,0x24,0x00,0x53,0x40,0x2d,0x1d,0x0c,0x0f,0x09,0x01,0x1f,0x03,0x09,0x0b,0x91,0x40,0x0c,0x17,0x23,0x0c,0x91,0x08,0x30,0x01,0x03,0x91,0x23,0x1b,0x14,0x12,0x91,0x17,0x04,0x1d,0x1a,0x0b,0x0b,0x06,0x01,0x0f,0x7d,0x1a,0x1a,0x20,0x7d,0x06,0x06,0x26,0x14,0x01,0x2f,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1, 0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xfd,0xc6,0x5f,0x5e,0x5d,0x12,0x39,0x31,0x30,0x13,0x35,0x16,0x33,0x20,0x00,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x37,0x24,0x11,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x04,0x15,0x10,0x05,0x15,0x16,0x16,0x15,0x10,0x00,0x21,0x22, 0x10,0x4c,0x66,0x01,0x00,0x01,0x58,0xe4,0xb7,0x5a,0x73,0x71,0x01,0xae,0xc2,0xa7,0xac,0xa2,0x9a,0xbe,0xf6,0x01,0x15,0xfe,0xd7,0xad,0xca,0xfe,0x47,0xfe,0xb4,0x67,0xfe,0x2f,0x9c,0x13,0x01,0x11,0xcf,0xa0,0xca,0x20,0x97,0x19,0x5f,0x01,0x09,0x83,0x9d,0x5a,0xa4,0x4e,0xec,0xc2,0xfe,0xe7,0x72,0x09,0x29,0xf9,0xb0,0xfe,0xf8,0xfe, 0x8b,0x00,0x00,0x01,0x00,0x1e,0xfe,0x21,0x03,0x3e,0x04,0x18,0x00,0x25,0x00,0x51,0x40,0x2d,0x1e,0x0c,0x09,0x40,0x1f,0x22,0x48,0x09,0x0b,0x95,0x40,0x0c,0x18,0x24,0x0c,0x95,0x08,0x30,0x01,0x03,0x95,0x24,0x1c,0x15,0x13,0x95,0x18,0x10,0x1e,0x1b,0x0b,0x0b,0x06,0x01,0x10,0x84,0x1b,0x1b,0x21,0x83,0x06,0x06,0x27,0x01,0x15,0x2f, 0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xfd,0xc6,0x2b,0x12,0x39,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x24,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15, 0x16,0x16,0x15,0x14,0x00,0x21,0x22,0x2f,0x42,0x55,0xcb,0x01,0x05,0xa4,0x8c,0x58,0x5e,0x60,0x9e,0xb0,0x93,0x89,0x96,0x8e,0x86,0xb0,0xc7,0xe7,0xe8,0x84,0xa0,0xfe,0xa4,0xfe,0xeb,0x61,0xfe,0x2d,0x91,0x12,0xc8,0x9e,0x7d,0x9a,0x1d,0x8c,0x12,0x1e,0x92,0x62,0x62,0x70,0x52,0x97,0x45,0xbd,0x97,0xc7,0x6d,0x07,0x1e,0xc7,0x8c,0xd9, 0xfe,0xe2,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x07,0x62,0x02,0x26,0x00,0x2b,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x58,0x01,0x56,0x00,0x13,0x40,0x0b,0x01,0x00,0x0f,0x0c,0x06,0x0b,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x07,0x62,0x02,0x26,0x00,0x4b,0x00,0x00, 0x01,0x07,0x00,0xe0,0x00,0x81,0x01,0x56,0x00,0x16,0xb9,0x00,0x01,0xff,0xb1,0x40,0x09,0x15,0x12,0x0a,0x11,0x25,0x01,0x14,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x01,0x00,0xbc,0xfe,0x29,0x05,0x27,0x05,0xb2,0x00,0x12,0x00,0x2a,0x40,0x16,0x0c,0x09,0x0f,0x01,0x1b,0x09,0x12,0x0a,0x03,0x04,0x91,0x0f,0x04,0x00,0x7e,0x01, 0x01,0x14,0x0c,0x08,0x7e,0x09,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0x11,0x12,0x39,0x31,0x30,0x01,0x23,0x11,0x10,0x21,0x22,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x12,0x21,0x32,0x12,0x11,0x05,0x27,0xa8,0xfe,0x9f,0xc0,0xfa,0xa8,0xa8,0x06,0x9e,0x01,0x3e,0xe9,0xf8,0xfe,0x29,0x05,0x0c,0x01,0xe5, 0xfe,0xe6,0xd5,0xfc,0xd5,0x05,0x9a,0xfe,0xfa,0x01,0x1e,0xfe,0xcd,0xfe,0xe3,0x00,0x00,0x02,0x00,0x3e,0xff,0xe8,0x04,0x81,0x05,0x9a,0x00,0x1e,0x00,0x2a,0x00,0x62,0x40,0x36,0x14,0x00,0x1f,0x91,0x40,0x0a,0x04,0x1a,0x0a,0x91,0x08,0x30,0x25,0x91,0x1a,0x13,0x10,0x04,0x03,0x14,0x00,0x12,0x02,0x10,0x7d,0x0f,0x0f,0x0d,0x7e,0x12, 0x12,0x17,0x28,0x04,0x7d,0x8f,0x05,0x01,0x05,0x05,0x07,0x7e,0x02,0x02,0x22,0x1d,0x17,0x7d,0x28,0x28,0x2c,0x22,0x7d,0x1d,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x5d,0xe1,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0xe1,0x11,0x12,0x39,0x39,0x00,0x3f,0x33,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39, 0x31,0x30,0x01,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x25,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x56,0xcd,0x37,0xac,0x3b,0xa4,0x89,0x8a,0xa6,0x3e,0xae,0x37,0xd1,0x86,0x97,0xfe,0xc8,0xef, 0xf2,0xfe,0xd6,0x02,0x20,0x9e,0xd2,0xd8,0x98,0x9f,0xd4,0xda,0x03,0x60,0x6a,0xde,0x78,0x7a,0x70,0x7a,0x74,0x96,0x96,0x74,0x76,0x74,0x7c,0x76,0xce,0x7a,0x34,0xd6,0x8b,0xd7,0xfe,0xf4,0x01,0x01,0xd9,0x01,0x1e,0x2a,0xaf,0x95,0x95,0xb2,0xb1,0x96,0x95,0xaf,0x00,0x02,0x00,0x48,0xff,0xe8,0x04,0x42,0x05,0xec,0x00,0x1e,0x00,0x2a, 0x00,0x54,0x40,0x2f,0x15,0x00,0x1f,0x95,0x40,0x0b,0x05,0x1a,0x0b,0x95,0x08,0x30,0x25,0x95,0x1a,0x16,0x11,0x05,0x00,0x11,0x84,0x10,0x10,0x01,0x10,0x10,0x0e,0x84,0x13,0x13,0x17,0x83,0x28,0x28,0x2c,0x1d,0x05,0x84,0x06,0x06,0x08,0x84,0x03,0x03,0x22,0x83,0x1d,0x2f,0xe1,0x39,0x2f,0xf1,0xc2,0x2f,0xe1,0x11,0x12,0x39,0x2f,0xe1, 0x39,0x2f,0xf1,0xc2,0x2f,0x71,0xe1,0x00,0x3f,0x33,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x26,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x04,0x11,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x25,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x01,0x52,0x5f,0x6e,0x2b,0xa0,0x27,0x98,0x85,0x85,0x95,0x26,0x9f,0x2b,0xcc,0x01,0x0a,0xfe,0xd7,0xdb,0xdf,0xfe,0xe9,0x01,0xfe,0x92,0xc4,0xc8,0x8c,0x91,0xc5,0xc8,0x03,0x74,0x30,0xc6,0x7c,0x80,0x86,0x78,0x84,0x8e,0xae,0xaf,0x8d,0x84,0x78,0x86,0x80,0xf5,0x7d,0x7e,0xfe,0xdb,0xd7,0xfe,0xee,0x01,0x0b,0xda,0x01,0x26,0x36, 0xbd,0x9d,0x9c,0xc1,0xc0,0x9d,0x99,0xc1,0x00,0x01,0x00,0x21,0xff,0x0c,0x04,0x7b,0x05,0x9a,0x00,0x11,0x00,0x30,0x40,0x18,0x01,0x07,0x0d,0x91,0x06,0x12,0x0c,0x08,0x91,0x0a,0x03,0x08,0x0c,0x10,0x01,0x01,0x03,0x7e,0x10,0x10,0x13,0x09,0x0d,0x07,0x2f,0x33,0xc6,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x10,0xc4,0x32,0x00,0x3f,0xed,0x39, 0x3f,0xed,0x39,0x2f,0x31,0x30,0x05,0x23,0x36,0x35,0x34,0x23,0x21,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x20,0x15,0x14,0x04,0x5a,0xa4,0x27,0x91,0xfc,0xd5,0x03,0x41,0xfd,0x02,0x04,0x00,0xfc,0xb8,0x02,0x3c,0x01,0x23,0xf4,0x46,0x3c,0x72,0x2f,0x04,0xd3,0x98,0x28,0xfb,0x26,0xfc,0x47,0x00,0x01,0x00,0x21,0xff,0x1e,0x03,0x9e, 0x04,0x00,0x00,0x11,0x00,0x33,0x40,0x1b,0x01,0x07,0x0d,0x95,0x06,0x15,0x0c,0x08,0x95,0x0a,0x0f,0x08,0x0c,0x10,0x01,0xa0,0x03,0xb0,0x03,0x02,0x03,0x10,0x10,0x13,0x09,0x0d,0x07,0x2f,0x33,0xc6,0x12,0x39,0x2f,0xdd,0x5d,0xc6,0x10,0xc4,0x32,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x2f,0x31,0x30,0x05,0x23,0x36,0x35,0x34,0x23,0x21, 0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x20,0x15,0x14,0x03,0x7f,0x95,0x22,0x85,0xfd,0x9a,0x02,0x5e,0xfd,0xdb,0x03,0x16,0xfd,0xa2,0x01,0x80,0x01,0x0c,0xe2,0x40,0x38,0x6a,0x33,0x03,0x41,0x8c,0x2f,0xfc,0xbb,0xe8,0x41,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0xea,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xdb, 0x01,0xc7,0x01,0x65,0x00,0x13,0x40,0x0b,0x02,0x00,0x13,0x19,0x05,0x00,0x25,0x02,0x10,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0x7b,0x05,0x85,0x00,0x26,0x00,0x44,0xf8,0x00,0x01,0x07,0x00,0xdb,0x01,0x38,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x20,0x23,0x29,0x08,0x14,0x25,0x02,0x20,0x11, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0xa3,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x05,0x51,0x00,0xb0,0x01,0x69,0x00,0x1b,0x40,0x0f,0x04,0x03,0x02,0x03,0x2b,0x25,0x03,0x09,0x25,0x04,0x03,0x02,0x28,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff, 0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x3a,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x06,0x60,0x00,0x00,0x00,0x1b,0x40,0x0f,0x04,0x03,0x02,0x00,0x2b,0x25,0x03,0x09,0x25,0x04,0x03,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0xb7,0x02,0x26,0x00,0x32, 0x00,0x00,0x01,0x07,0x05,0x55,0x00,0xaa,0x01,0x62,0x00,0x17,0x40,0x0d,0x03,0x02,0x09,0x22,0x18,0x03,0x09,0x25,0x03,0x02,0x22,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x55,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x06,0x64,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02, 0x0b,0x22,0x18,0x03,0x09,0x25,0x03,0x02,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x06,0xea,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x36,0x01,0x65,0x00,0x13,0x40,0x0b,0x02,0x00,0x1b,0x21,0x03,0x09,0x25,0x02,0x18,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b, 0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0x85,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x8a,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x1b,0x21,0x03,0x09,0x25,0x02,0x18,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x07,0x9a,0x02,0x26,0x00,0x32,0x00,0x00, 0x01,0x07,0x05,0x52,0x00,0xfe,0x01,0x65,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1a,0x1b,0x03,0x09,0x25,0x03,0x02,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x35,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x06,0x06,0x63,0x52,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x1a, 0x1b,0x03,0x09,0x25,0x03,0x02,0x1c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x06,0x8c,0x02,0x26,0x00,0x3c,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xfb,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x10,0x11,0x05,0x00,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0x2f,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xb4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x17,0x18,0x0c,0x00,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x03,0x01,0x33,0x04,0xc2,0x03,0x7b,0x06,0x3a,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x32, 0xb2,0x02,0xe2,0x01,0xb8,0xff,0xc0,0x40,0x15,0x09,0x0c,0x48,0x01,0x04,0x0a,0x16,0xc1,0x10,0x00,0x01,0x00,0x01,0x13,0x0d,0xc0,0x07,0x13,0xc0,0x07,0x19,0x2f,0xc6,0xe1,0x10,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x2f,0xfd,0x39,0x39,0xde,0x2b,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x56,0xfe,0x04,0x01,0xfc,0x3e,0x28,0x3a,0x39,0x27,0x2a,0x3b,0x39,0xfe,0x56,0x29,0x3c,0x39,0x2a,0x29,0x3b,0x39,0x05,0xcd,0x6d,0xfe,0x88,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39,0x2a,0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0x02,0x01,0x08,0x04,0xc2, 0x03,0x04,0x06,0x35,0x00,0x03,0x00,0x0f,0x00,0x25,0xb2,0x02,0xe2,0x01,0xb8,0xff,0xc0,0x40,0x0e,0x09,0x0c,0x48,0x01,0x0a,0xc1,0x04,0x01,0x01,0x0d,0x00,0x0d,0xc0,0x07,0x2f,0xe1,0xc4,0x10,0xc0,0x2f,0x00,0x2f,0xfd,0xde,0x2b,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03, 0x04,0xfe,0x04,0x01,0xfc,0xfe,0x28,0x3a,0x3a,0x28,0x29,0x39,0x39,0x05,0xc8,0x6d,0xfe,0x8d,0x39,0x2a,0x29,0x37,0x37,0x29,0x29,0x3a,0x00,0x03,0x01,0x1c,0x04,0xc2,0x03,0x64,0x06,0xfa,0x00,0x06,0x00,0x12,0x00,0x1e,0x00,0x37,0xb4,0x05,0x00,0x03,0x80,0x01,0xb8,0xff,0xc0,0x40,0x15,0x09,0x0c,0x48,0x01,0x07,0x0d,0x19,0xc1,0x13, 0x00,0x03,0x00,0x03,0x16,0x10,0xc0,0x0a,0x16,0xc0,0x0a,0x1c,0x2f,0xc6,0xe1,0x10,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x2f,0xfd,0x39,0x39,0xd6,0x2b,0x1a,0xcd,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x03,0x33,0x17,0x37,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x03,0x5a,0xd5,0x85,0xd7,0x73,0xa4,0xa4,0x1e,0x28,0x3a,0x37,0x29,0x2a,0x3a,0x38,0xfe,0x55,0x29,0x3c,0x39,0x2a,0x29,0x3c,0x3a,0x06,0xfa,0xfe,0xb6,0x01,0x4a,0xe6,0xe6,0xfd,0xc8,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39,0x2a,0x29,0x39,0x39,0x29,0x29,0x3a,0x00,0x00,0x03,0x01,0x1c,0x04,0xc2,0x03,0x77,0x06,0xe2, 0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x35,0xb2,0x00,0x80,0x01,0xb8,0xff,0xc0,0x40,0x16,0x09,0x0c,0x48,0x01,0x04,0x0a,0x16,0xc1,0x40,0x10,0x00,0x80,0x02,0x02,0x19,0x0d,0xc0,0x07,0x13,0xc0,0x07,0x19,0x2f,0xc6,0xe1,0x10,0xe1,0x12,0x39,0x2f,0x1a,0xcd,0x00,0x2f,0x1a,0xfd,0x39,0x39,0xd6,0x2b,0x1a,0xcd,0x31,0x30,0x01,0x01,0x23, 0x13,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x77,0xfe,0xf9,0x7e,0xdf,0x31,0x28,0x3a,0x37,0x29,0x2a,0x3a,0x38,0xfe,0x55,0x29,0x3c,0x39,0x2a,0x29,0x3c,0x3a,0x06,0xe2,0xfe,0xb8,0x01,0x48,0xfd,0xe0,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a, 0x39,0x2a,0x29,0x39,0x39,0x29,0x29,0x3a,0x00,0x02,0x01,0x23,0x04,0xb2,0x03,0xa4,0x06,0x55,0x00,0x13,0x00,0x17,0x00,0x3c,0x40,0x17,0x14,0x15,0x14,0x15,0x0a,0x13,0xc4,0x00,0x09,0xc4,0x0a,0x17,0xe2,0x14,0x40,0x0d,0x12,0x48,0x14,0x13,0x07,0xda,0x0d,0xb8,0xff,0xc0,0xb7,0x09,0x0c,0x48,0x0d,0x11,0xda,0x09,0x03,0x00,0x2f,0xc6, 0xfd,0xdc,0x2b,0xed,0xd6,0xd6,0x2b,0xed,0x01,0x2f,0xe1,0xd4,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x37,0x21,0x35,0x21,0x03,0xa4,0x60,0x52,0x47,0x5b,0x4d,0x2a,0x58,0x5e,0x60,0x56,0x41,0x54,0x4a,0x36,0x54,0x1a,0xfe,0x04, 0x01,0xfc,0x05,0xb2,0x69,0x85,0x34,0x2b,0x71,0x6b,0x81,0x34,0x2c,0x74,0x36,0x6d,0x00,0x02,0x00,0x90,0xff,0xe8,0x03,0xb8,0x04,0x18,0x00,0x15,0x00,0x20,0x00,0x46,0xb9,0x00,0x04,0xff,0xc0,0x40,0x23,0x09,0x0c,0x48,0x04,0x04,0x02,0x0d,0x10,0x16,0x96,0x00,0x00,0x1d,0x02,0x95,0x08,0x16,0x0b,0x0f,0x1d,0x95,0x10,0x10,0x04,0x04, 0x13,0x83,0x1a,0x1a,0x22,0x16,0x0c,0x00,0x84,0x0b,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x11,0x39,0x2f,0xed,0x12,0x39,0x11,0x33,0x2f,0x2b,0x31,0x30,0x01,0x10,0x33,0x32,0x37,0x15,0x06,0x06,0x23,0x20,0x11,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x10,0x05,0x25,0x37,0x36,0x36, 0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x31,0xd5,0xba,0x94,0x37,0xcb,0x5a,0xfe,0x98,0xa3,0x05,0x6a,0xd0,0x99,0xad,0xfe,0xae,0xfe,0xcb,0xfa,0x6e,0x77,0x6a,0x5a,0x7c,0x9f,0x01,0x77,0xfe,0xfb,0x7e,0xa8,0x27,0x39,0x01,0x7e,0x02,0x9a,0xa0,0xb8,0xa2,0x86,0xfe,0xe1,0x2f,0x58,0x22,0x0f,0x51,0x68,0x4c,0x5e,0xad,0x81,0x00,0x02, 0x00,0x60,0xff,0xe8,0x04,0x10,0x04,0x18,0x00,0x10,0x00,0x1d,0x00,0x49,0x40,0x18,0x02,0x1b,0x95,0x05,0x16,0x01,0x15,0x0e,0x15,0x95,0x0b,0x10,0x0f,0x0f,0x11,0x0d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf8,0x40,0x13,0x0c,0x06,0x4d,0x01,0x01,0x1f,0x18,0x08,0x0c,0x06,0x4d,0x18,0x83,0x08,0x0e,0x0c,0x06,0x4d,0x08, 0x2f,0x2b,0xe9,0x2b,0x12,0x39,0x2f,0x2b,0xe9,0x2b,0x33,0x33,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x32,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0xa4,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5, 0xd3,0x60,0x04,0xa4,0xa4,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0xab,0xae,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x8e,0xfd,0xcf,0x97,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0xc6,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x54,0x04,0x18,0x00,0x10,0x00,0x1d,0x00,0x49,0x40,0x16,0x03,0x15,0x01,0x15,0x95,0x0f,0x16,0x07,0x1b,0x95,0x09,0x10, 0x04,0x0f,0x0c,0x06,0x0c,0x06,0x4d,0x0c,0x83,0x18,0xb8,0xff,0xec,0x40,0x15,0x0c,0x06,0x4d,0x18,0x18,0x1f,0x06,0x02,0x12,0x06,0x0c,0x06,0x4d,0x12,0x84,0x03,0x02,0x0c,0x06,0x4d,0x03,0x2f,0x2b,0xe9,0x2b,0x32,0x32,0x12,0x39,0x2f,0x2b,0xe9,0x2b,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x31,0x30,0x25,0x23,0x15,0x23,0x11, 0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x4e,0x04,0xa4,0xa4,0x04,0x79,0xe9,0xc5,0xdf,0xfa,0xd9,0xcb,0x6c,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0x94,0x94,0x04,0x00,0xb4,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x02,0x49,0x8f,0x7f, 0xb1,0xe4,0xcb,0xab,0xc2,0xc7,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x56,0x06,0x02,0x00,0x1a,0x00,0x27,0x00,0x38,0x40,0x1e,0x10,0x01,0x13,0x1f,0x95,0x19,0x16,0x03,0x15,0x25,0x95,0x13,0x10,0x0a,0x0c,0x95,0x07,0x01,0x0a,0x0a,0x16,0x83,0x22,0x22,0x29,0x10,0x02,0x1c,0x83,0x03,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f, 0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x25,0x23,0x15,0x23,0x11,0x10,0x12,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0x50,0x04,0xa6,0xfd,0xdc,0x8a,0x7e,0x84,0x88, 0x87,0xa8,0x04,0x79,0xe9,0xc5,0xdf,0xfa,0xd9,0xca,0x6d,0xa5,0x7f,0x95,0xab,0x9f,0x88,0x8f,0xae,0x94,0x94,0x03,0xdd,0x01,0x14,0x01,0x11,0x37,0x98,0x44,0xa5,0xf3,0x93,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x02,0x49,0x8f,0x7f,0xb1,0xe5,0xca,0xaa,0xc3,0xc7,0x00,0x00,0x01,0x00,0x5a,0xff,0xe8,0x03,0x5a,0x04,0x18,0x00,0x15, 0x00,0x26,0x40,0x14,0x30,0x01,0x01,0x01,0x03,0x95,0x14,0x16,0x0b,0x09,0x95,0x0e,0x10,0x11,0x83,0x06,0x06,0x17,0x0b,0x00,0x2f,0xc6,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x5d,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x5c,0x78, 0x84,0x99,0xc1,0xbd,0x9f,0x83,0x79,0x78,0x9e,0xdb,0x01,0x0f,0xfe,0xe7,0xed,0x8c,0x21,0xa5,0x54,0xdc,0xb8,0xb4,0xd4,0x54,0x9b,0x43,0xfe,0xe3,0xe5,0xfe,0xfe,0xd0,0x00,0x02,0x00,0x60,0xff,0x70,0x03,0xa0,0x04,0x18,0x00,0x1d,0x00,0x26,0x00,0x57,0x40,0x1e,0x14,0x12,0x20,0x0f,0x05,0x00,0x1c,0x0a,0x03,0x16,0x96,0x25,0x20,0x96, 0x1c,0x16,0x0d,0x0f,0x95,0x0a,0x10,0x1e,0x14,0x23,0x12,0x00,0x05,0x19,0x07,0x02,0xb8,0x01,0x03,0x40,0x0c,0x03,0x07,0x0d,0x0d,0x19,0x84,0x23,0x23,0x28,0x12,0x83,0x07,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x10,0xd4,0xe1,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xd6,0xed,0x2f,0x11,0x12,0x39, 0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x25,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x01,0x68,0x1c,0x06,0x8c,0x0d,0x31,0x98,0x01,0x22,0xf2,0x87,0x67,0x72,0x82,0x9d,0xc9,0x46, 0x8a,0xbc,0x76,0x96,0xbc,0x9a,0x7c,0x24,0x4c,0x60,0x55,0x63,0x7e,0x88,0x18,0x50,0x58,0x86,0x70,0x90,0xf2,0xfd,0x01,0x33,0x32,0xa8,0x50,0xe1,0xb7,0x9c,0x64,0xb4,0x79,0x5c,0x66,0x87,0xb4,0x30,0x37,0x2e,0x56,0x00,0x00,0x02,0x00,0x60,0xfe,0x1e,0x05,0x21,0x05,0xec,0x00,0x19,0x00,0x26,0x00,0x38,0x40,0x1e,0x19,0x17,0x95,0x02, 0x1c,0x12,0x06,0x0f,0x24,0x95,0x09,0x16,0x1e,0x95,0x0f,0x10,0x14,0x00,0x19,0x19,0x15,0x84,0x1a,0x12,0x06,0x06,0x28,0x21,0x83,0x0c,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xf1,0xc2,0x2f,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x10, 0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x21,0x41,0x42,0x92,0xa0,0x04,0x72,0xee,0xc2,0xe6,0x01,0x04,0xd6,0xcc,0x62,0x04,0xa4,0xa0,0x3c,0x35,0xfe,0x4b,0xa2,0x80,0x99,0xa9,0xa4,0x89,0x8a,0xad,0xfe,0x3a,0x1c,0xaf,0x9f,0x01,0x48,0xcc, 0x01,0x16,0xe8,0x01,0x00,0x01,0x32,0xa8,0x02,0x7c,0xf9,0x86,0xc8,0x1a,0x03,0x13,0x87,0x7f,0xb1,0xe0,0xc2,0xac,0xce,0xcb,0x00,0x02,0x00,0x60,0xff,0xe8,0x05,0x21,0x06,0x02,0x00,0x19,0x00,0x26,0x00,0x38,0x40,0x1e,0x13,0x07,0x10,0x24,0x95,0x0a,0x16,0x05,0x15,0x1e,0x95,0x10,0x10,0x00,0x02,0x95,0x17,0x01,0x00,0x00,0x05,0x84, 0x1a,0x13,0x06,0x06,0x28,0x21,0x83,0x0d,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xf1,0xc2,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x00,0x33,0x32,0x17,0x33,0x11,0x34,0x36,0x33,0x32,0x17,0x01,0x35,0x34,0x26,0x23,0x22, 0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x21,0x37,0x36,0xa4,0xa4,0x04,0x72,0xee,0xc2,0xe6,0x01,0x04,0xd6,0xcc,0x62,0x04,0xb4,0x8a,0x48,0x2f,0xfe,0x4b,0xa2,0x80,0x99,0xa9,0xa4,0x89,0x8a,0xad,0x05,0x5c,0x1b,0xcf,0xfb,0x58,0xb4,0xcc,0x01,0x16,0xe8,0x01,0x00,0x01,0x32,0xa8,0x01,0x42,0x99,0xb7,0x12,0xfb,0xe7,0x87,0x7f,0xb1, 0xe0,0xc2,0xac,0xce,0xcb,0x00,0x00,0x02,0x00,0x52,0xff,0xe8,0x03,0xcf,0x04,0x18,0x00,0x12,0x00,0x18,0x00,0x4b,0xb9,0x00,0x01,0xff,0xc0,0x40,0x1f,0x0b,0x0e,0x48,0x01,0x01,0x03,0x07,0x95,0x40,0x18,0x0b,0x11,0x18,0x95,0x08,0x30,0x03,0x95,0x11,0x16,0x15,0x95,0x0b,0x10,0x0e,0x83,0x13,0x06,0x06,0x1a,0x01,0xb8,0xff,0xc0,0xb6, 0x0e,0x12,0x48,0x01,0x18,0x83,0x07,0x2f,0xe1,0xc6,0x2b,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x39,0x2f,0x2b,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x37,0x21,0x35,0x34,0x12,0x33,0x32,0x12,0x15,0x14,0x00,0x23,0x22,0x01,0x02,0x23,0x22,0x06,0x07,0x9a,0x9a,0xb4,0x97,0xa7,0x03, 0xfd,0x29,0xeb,0xcd,0xcd,0xf8,0xfe,0xfb,0xd8,0xc2,0x01,0xf3,0x28,0xfb,0x7a,0x8a,0x02,0x42,0xa2,0x72,0xbd,0xa8,0x56,0xe0,0x01,0x0b,0xfe,0xe3,0xfb,0xf7,0xfe,0xdf,0x02,0x7a,0x01,0x2c,0xa1,0x8b,0x00,0x02,0x00,0x50,0xff,0xe8,0x05,0x16,0x04,0x18,0x00,0x1d,0x00,0x26,0x00,0x77,0x40,0x14,0x05,0x05,0x06,0x1e,0x1e,0x26,0x1f,0x04, 0x1f,0x17,0x17,0x16,0x0e,0x0e,0x0f,0x0d,0x18,0x0d,0x1d,0x02,0xb8,0x01,0x04,0x40,0x2c,0x1b,0x1e,0x05,0x1f,0x04,0x18,0x04,0x0d,0x18,0x1f,0x04,0x15,0x22,0x95,0x0a,0x16,0x12,0x40,0x09,0x0e,0x48,0x12,0x10,0x95,0x15,0x10,0x1e,0x0e,0x25,0x17,0x05,0x07,0x12,0x00,0x00,0x07,0x83,0x25,0x25,0x28,0x12,0x1f,0x83,0x0d,0x2f,0xe1,0xc6, 0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x39,0x12,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x2b,0x3f,0xed,0x12,0x17,0x39,0x2f,0x11,0x12,0x39,0x39,0xd6,0xed,0xc6,0x31,0x30,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x01,0x06,0x23,0x22,0x27,0x07,0x16,0x15,0x14,0x00,0x23,0x22,0x26,0x27,0x01,0x26,0x23,0x22,0x07, 0x35,0x36,0x33,0x32,0x17,0x37,0x17,0x16,0x33,0x32,0x37,0x05,0x01,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x05,0x16,0x38,0x34,0x88,0x3c,0x3e,0x23,0xfe,0xf5,0xcc,0xbe,0xd9,0x0d,0x02,0x85,0x5b,0xa9,0xa4,0x99,0x9e,0xbe,0xf0,0x86,0xc3,0x21,0x22,0x4c,0x30,0x2e,0xfd,0xfc,0xfd,0xe8,0x0a,0x8b,0x6b,0x8f,0x9c,0x02,0x98,0x1f,0x8d,0x22, 0x61,0x7f,0xf4,0xfe,0xd8,0xee,0xdc,0x01,0x60,0x7c,0x72,0x9a,0x62,0xb8,0x68,0x68,0x6a,0x22,0x84,0xfe,0xda,0x6c,0x90,0xd4,0xb8,0x56,0x00,0x01,0x00,0x60,0xff,0xe8,0x02,0xf4,0x04,0x18,0x00,0x22,0x00,0x45,0x40,0x25,0x07,0x1a,0x95,0x40,0x19,0x0d,0x02,0x19,0x95,0x0c,0x30,0x22,0x20,0x95,0x02,0x16,0x10,0x12,0x95,0x0d,0x10,0x07, 0x05,0x1a,0x1a,0x1d,0x10,0x00,0x00,0x24,0x05,0x15,0x83,0x0a,0x1d,0x83,0x05,0x2f,0xe1,0xd4,0xe1,0x11,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x25,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x35,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23, 0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x20,0x15,0x14,0x16,0x33,0x32,0x37,0x02,0xf4,0x72,0x98,0xba,0xd0,0xde,0xbb,0xc9,0xa4,0x82,0x67,0x6d,0x7c,0x5a,0x6d,0x8c,0x78,0x50,0x52,0xfe,0xdd,0x80,0x72,0x86,0x74,0x1a,0x32,0xa1,0x87,0xcf,0x37,0x04,0x40,0xa8,0x7d,0x99,0x2e,0x9a,0x3e,0x51,0x43,0x4c,0x58,0x8e,0xac,0x4e,0x5c, 0x3e,0x00,0x00,0x01,0x00,0x5a,0xff,0xe8,0x02,0xee,0x04,0x18,0x00,0x21,0x00,0x4d,0x40,0x2a,0x1b,0x09,0x95,0x40,0x0a,0x15,0x20,0x0a,0x95,0x0c,0x30,0x70,0x01,0x01,0x01,0x03,0x95,0x20,0x16,0x12,0x10,0x95,0x15,0x10,0x1b,0x1d,0x09,0x0e,0x83,0x18,0x18,0x1d,0x09,0x09,0x00,0x1d,0x83,0x06,0x06,0x23,0x12,0x00,0x2f,0xc4,0x12,0x39, 0x2f,0xe1,0x12,0x39,0x2f,0x10,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x5a, 0x72,0x8e,0x6f,0x7d,0xfe,0xdf,0x54,0x50,0x79,0x8b,0xc9,0x76,0x72,0x73,0x81,0xa2,0xc1,0xb9,0xdc,0xdb,0xbb,0x8c,0x1a,0x9a,0x42,0x5f,0x4b,0xac,0x8e,0x59,0x4b,0x94,0x3c,0x98,0x2e,0x97,0x7b,0xa5,0x45,0x04,0x33,0xcb,0x88,0xaa,0x00,0x01,0x00,0x5a,0xff,0xe8,0x04,0x35,0x04,0x18,0x00,0x2c,0x00,0x72,0x40,0x3d,0x04,0x05,0x27,0x08, 0x2c,0x02,0x96,0x2a,0x26,0x19,0x27,0x27,0x24,0x08,0x08,0x18,0x95,0x40,0x19,0x24,0x0d,0x19,0x95,0x0c,0x30,0x70,0x10,0x01,0x10,0x12,0x95,0x0d,0x16,0x21,0x1f,0x95,0x24,0x10,0x27,0x04,0x26,0x00,0x00,0x0a,0x08,0x0a,0x18,0x18,0x15,0x0f,0x1d,0x84,0x26,0x26,0x0a,0x83,0x15,0x15,0x2e,0x21,0x0f,0x2f,0xc4,0x12,0x39,0x2f,0xf1,0xc0, 0x2f,0xe1,0x11,0x12,0x39,0x2f,0x12,0x39,0x10,0xc2,0x2f,0x12,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x11,0x12,0x39,0x2f,0x12,0x39,0xd6,0xed,0xc6,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x27,0x07,0x06,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32, 0x36,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x17,0x37,0x17,0x16,0x33,0x32,0x37,0x04,0x35,0x39,0x2f,0x7a,0x3d,0x54,0x54,0x5c,0xdc,0xdb,0xbb,0x8c,0x72,0x72,0x8e,0x6f,0x7d,0xfe,0xdf,0x54,0x52,0x73,0x8f,0xc9,0x76,0x72,0x73,0x81,0x01,0x1d,0x3d,0x86,0x20,0x27,0x4e,0x2a,0x2e,0x02, 0x98,0x1f,0x79,0x56,0x56,0x2a,0x04,0x34,0xca,0x88,0xaa,0x32,0x9a,0x42,0x5f,0x4b,0xac,0x8e,0x5d,0x49,0x92,0x3c,0x98,0x2e,0xdc,0x8c,0x5e,0x74,0x22,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x0c,0x04,0x18,0x00,0x10,0x00,0x23,0x00,0x44,0x40,0x25,0x01,0x11,0x95,0x40,0x12,0x0c,0x06,0x12,0x95,0x0c,0x30,0x1e,0x95,0x06,0x16,0x18, 0x95,0x0c,0x10,0x01,0x03,0x11,0x11,0x21,0x1b,0x15,0x84,0x0f,0x0f,0x03,0x83,0x21,0x21,0x25,0x1b,0x83,0x09,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32, 0x16,0x15,0x14,0x05,0x35,0x33,0x32,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x3a,0xd2,0xe8,0xc2,0xee,0xfe,0xec,0x01,0x26,0xee,0xa8,0xd2,0xfe,0x24,0x44,0xf4,0x7a,0x62,0xa4,0xc2,0xc2,0xa0,0x74,0x86,0xfe,0xf6,0x02,0x1c,0x04,0x30,0xca,0x87,0xaf,0x01,0x1a,0xf0,0xfc,0x01,0x2a,0x9b,0x7b, 0xa2,0x98,0x8e,0xa0,0x43,0x55,0xd5,0xbf,0xb6,0xd2,0x60,0x4a,0xac,0x00,0x00,0x01,0xff,0x81,0xfe,0x1e,0x02,0x1c,0x04,0x00,0x00,0x14,0x00,0x4b,0x40,0x29,0x13,0x01,0x0d,0x95,0x40,0x10,0x11,0x05,0x10,0x95,0x08,0x30,0x08,0x0a,0x95,0x40,0x05,0x1c,0x11,0x0f,0x08,0x0c,0x13,0x10,0x0c,0x00,0x0e,0x02,0x0e,0x0c,0x42,0x0e,0x02,0x84, 0x0c,0x15,0x16,0x0c,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x18,0xc6,0x2b,0x01,0x10,0xe2,0x12,0x39,0x39,0x18,0x10,0xc6,0x00,0x3f,0x3f,0x1a,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x02,0x1c,0xae,0xc3, 0xad,0x48,0x35,0x3d,0x42,0xcb,0xaf,0xaf,0xa3,0xae,0x01,0xdb,0xfe,0x04,0xd6,0xeb,0x1a,0x99,0x27,0x01,0x31,0x02,0x00,0x8b,0x01,0x9a,0xfe,0x66,0x00,0x02,0x00,0x60,0xfe,0x1e,0x05,0x21,0x06,0x02,0x00,0x21,0x00,0x2e,0x00,0x4a,0xb9,0x00,0x0a,0xff,0xc0,0x40,0x26,0x0b,0x0f,0x48,0x0a,0x0a,0x0c,0x95,0x07,0x1c,0x1b,0x0f,0x18,0x2c, 0x95,0x12,0x16,0x26,0x95,0x18,0x10,0x00,0x02,0x95,0x1f,0x01,0x00,0x00,0x05,0x84,0x22,0x1b,0x0f,0x0f,0x30,0x0a,0x29,0x83,0x15,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0x33,0x33,0xf1,0xc2,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0xed,0x32,0x2f,0x2b,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x10,0x21,0x22,0x27, 0x35,0x16,0x33,0x20,0x11,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x12,0x33,0x32,0x17,0x33,0x11,0x34,0x36,0x33,0x32,0x17,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x21,0x37,0x36,0xa4,0xfd,0xe4,0xbe,0x8e,0xad,0x9d,0x01,0x7a,0x04,0x75,0xeb,0xbf,0xe9,0xfb,0xda,0xcf,0x64,0x04,0xb4,0x8a,0x48,0x2f, 0xfe,0x4b,0xa5,0x7b,0x98,0xac,0xa5,0x88,0x8a,0xad,0x05,0x5c,0x1b,0xcf,0xfb,0xaa,0xfd,0xcc,0x48,0xa4,0x60,0x01,0x92,0x70,0xc4,0x01,0x11,0xe6,0x01,0x05,0x01,0x34,0xa6,0x01,0x40,0x99,0xb7,0x12,0xfb,0xdf,0x97,0x7a,0xae,0xdd,0xc7,0xab,0xcd,0xc4,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10,0x04,0x18,0x02,0x06,0x00,0x4a,0x00,0x00, 0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0xcd,0x04,0x18,0x00,0x19,0x00,0x41,0x40,0x23,0x17,0x95,0x40,0x18,0x08,0x02,0x18,0x95,0x08,0x30,0x15,0x00,0x13,0x95,0x02,0x16,0x0b,0x0d,0x95,0x08,0x10,0x17,0x17,0x15,0x10,0x0b,0x0b,0x00,0x84,0x15,0x15,0x1b,0x10,0x83,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0x00, 0x3f,0xfd,0xc6,0x3f,0xed,0x32,0x32,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x25,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x11,0x23,0x35,0x21,0x03,0xcd,0xaf,0xb8,0xec,0xfe,0xe6,0x01,0x38,0xf6,0x9a,0x82,0x82,0xa3,0xa9,0xd4,0xc5,0xa7,0x6e,0x4b,0xdf,0x01,0x7f, 0x3e,0x56,0x01,0x18,0xf0,0xf1,0x01,0x37,0x30,0x9c,0x42,0xe0,0xb4,0xb8,0xd0,0x26,0x01,0x04,0x8b,0x00,0x00,0x02,0x00,0x0e,0xfe,0x52,0x03,0xc6,0x04,0x00,0x00,0x11,0x00,0x19,0x00,0x16,0x40,0x0a,0x16,0x95,0x07,0x00,0x0f,0x0e,0x0f,0x00,0x1b,0x0e,0x2f,0x10,0xc6,0x00,0x3f,0x3f,0x2f,0xed,0x31,0x30,0x01,0x01,0x17,0x16,0x15,0x14, 0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x01,0x33,0x09,0x02,0x06,0x15,0x14,0x33,0x32,0x35,0x34,0x03,0xc6,0xfe,0x78,0x22,0x5e,0x7c,0x63,0x5f,0x78,0x62,0x22,0xfe,0x82,0xb2,0x01,0x26,0x01,0x2e,0xfe,0xd0,0x40,0x40,0x41,0x04,0x00,0xfc,0xa0,0x44,0xbc,0x68,0x63,0x83,0x83,0x63,0x5a,0xca,0x44,0x03,0x60,0xfd,0x42,0x02,0xbe,0xfc, 0x10,0x8b,0x49,0x63,0x63,0x40,0x00,0x02,0x00,0x0a,0xff,0xe8,0x03,0x9e,0x04,0x18,0x00,0x1b,0x00,0x23,0x00,0x2a,0x40,0x17,0x20,0x95,0x09,0x16,0x00,0x12,0x19,0x02,0x10,0x95,0x15,0x10,0x0c,0x1e,0x22,0x06,0x0e,0x04,0x06,0x12,0x00,0x25,0x12,0x2f,0x10,0xc6,0x11,0x17,0x39,0x00,0x3f,0xfd,0x39,0x39,0xd6,0xc4,0x3f,0xed,0x31,0x30, 0x01,0x26,0x23,0x22,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x17,0x01,0x06,0x15,0x14,0x33,0x32,0x35,0x34,0x03,0x9e,0x46,0x33,0x75,0x7d,0x95,0x85,0x74,0x6f,0x7e,0x92,0x82,0x73,0x3f,0x36,0x40,0x4a,0x9e,0xa3,0xa5,0x9e,0x48,0x3e,0xfe,0x37,0x58,0x58, 0x58,0x03,0x60,0x2e,0xbf,0xef,0xca,0x88,0xa6,0xa4,0x86,0xd2,0xeb,0xbf,0x2c,0x96,0x20,0xce,0xce,0x20,0xfe,0x60,0xa3,0x97,0xac,0xac,0x92,0x00,0x00,0x01,0x00,0x90,0xfe,0x29,0x03,0xe2,0x04,0x00,0x00,0x11,0x00,0x27,0x40,0x14,0x00,0x1b,0x11,0x02,0x08,0x0c,0x95,0x05,0x16,0x08,0x0f,0x11,0x84,0x02,0x10,0x10,0x13,0x09,0x84,0x08, 0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xe2,0xa4,0x04,0x78,0xda,0xfe,0xa8,0xa3,0xeb,0x7a,0xa6,0xa4,0xfe,0x29,0x02,0x81,0xc2,0x01,0xa1,0x02,0x77,0xfd,0xb2,0xfe,0xc0,0xbb,0x8f,0x02, 0x44,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x02,0x00,0x1b,0x00,0x32,0x40,0x1a,0x16,0x00,0x19,0x09,0x15,0x04,0x95,0x19,0x10,0x10,0x12,0x95,0x0d,0x01,0x10,0x10,0x16,0x00,0x84,0x01,0x01,0x1d,0x16,0x08,0x84,0x09,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0x12,0x39,0x39, 0x31,0x30,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x12,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xa4,0xee,0x78,0xa4,0xa4,0xfc,0xdb,0x8a,0x7e,0x84,0x88,0x87,0xa8,0x04,0x76,0xda,0x01,0x5a,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfd,0xbc,0x03,0xdd,0x01,0x14,0x01,0x11, 0x37,0x98,0x44,0xa5,0xf3,0x89,0xc2,0xfe,0x5f,0x00,0x00,0x01,0x00,0xa6,0xfe,0x1e,0x03,0xf8,0x06,0x02,0x00,0x24,0x00,0x40,0x40,0x22,0x06,0x08,0x95,0x03,0x1c,0x1f,0x22,0x12,0x15,0x0d,0x95,0x22,0x10,0x19,0x1b,0x95,0x16,0x01,0x19,0x19,0x1f,0x00,0x06,0x06,0x11,0x00,0x84,0x0a,0x0a,0x26,0x1f,0x11,0x84,0x12,0x2f,0xe1,0x32,0x12, 0x39,0x2f,0xe1,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0x12,0x39,0x3f,0xfd,0xc6,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x12,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xbf, 0xad,0x4c,0x36,0x3e,0x44,0xc8,0xee,0x78,0xa4,0xa4,0xfc,0xdb,0x8a,0x7e,0x84,0x88,0x87,0xa8,0x04,0x76,0xda,0x01,0x5a,0x04,0xe6,0xf8,0x1a,0x99,0x27,0x01,0x3e,0x02,0x66,0x01,0x40,0xb9,0x91,0xfd,0xbc,0x03,0xdd,0x01,0x14,0x01,0x11,0x37,0x98,0x44,0xa5,0xf3,0x89,0xc2,0xfe,0x5f,0x00,0x02,0x00,0x0a,0x00,0x00,0x02,0x0e,0x05,0xd9, 0x00,0x0b,0x00,0x17,0x00,0x52,0x40,0x2f,0x16,0x0d,0x10,0x95,0x40,0x13,0x14,0x0f,0x13,0x95,0x0c,0x30,0x0f,0x15,0x06,0x63,0x40,0x00,0x14,0x0f,0x09,0x62,0x03,0x0f,0x0e,0x03,0x62,0xff,0x30,0x0c,0x0e,0x0e,0x0f,0x11,0x42,0x11,0x16,0x13,0x0e,0x84,0x0f,0x18,0x19,0x0f,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x39,0x39,0x18,0xc6,0x2b, 0x01,0x10,0xe2,0x2b,0x01,0x10,0xe1,0x00,0x18,0x3f,0xd6,0x1a,0xed,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x01,0x10,0x2c,0x40,0x40,0x2c,0x2e,0x3d,0x3d,0xd0,0xb0,0xa4,0xb0,0xb0,0xa4,0xb0, 0x05,0x04,0x3c,0x2e,0x2e,0x3d,0x3d,0x2e,0x2c,0x3e,0xfc,0xd7,0xfe,0x25,0x01,0xdb,0x8b,0x01,0x9a,0xfe,0x66,0x00,0x00,0x01,0x00,0x94,0xff,0xea,0x02,0x2f,0x04,0x00,0x00,0x0b,0x00,0x19,0x40,0x0c,0x0b,0x09,0x95,0x02,0x16,0x05,0x0f,0x0b,0x0b,0x06,0x84,0x05,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0x3f,0xfd,0xc6,0x31,0x30,0x25,0x06,0x23, 0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x02,0x2f,0x39,0x5c,0xfe,0xfa,0xa4,0x90,0x3c,0x2b,0x08,0x1e,0x01,0x28,0x02,0xee,0xfd,0x2f,0xbb,0x20,0x00,0x00,0x01,0x00,0x4c,0x00,0x00,0x02,0x44,0x04,0x00,0x00,0x0b,0x00,0x33,0x40,0x1b,0x0a,0x02,0x95,0x01,0x15,0x09,0x05,0x95,0x06,0x0f,0x08,0x05,0x02,0x0b,0x0b,0x0a,0x02,0x40, 0x0a,0x84,0x03,0x0c,0x0d,0x03,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x1a,0x18,0xcd,0x10,0xc1,0x2f,0x12,0x39,0x39,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x31,0x30,0x21,0x21,0x35,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x33,0x02,0x44,0xfe,0x08,0xaa,0xaa,0x01,0xf8,0xaa,0xaa,0x8c,0x02,0xe8,0x8c,0x8c,0xfd,0x18,0x00,0x01,0xff,0xec, 0x00,0x00,0x02,0x52,0x05,0xec,0x00,0x17,0x00,0x5c,0x40,0x33,0x13,0x10,0x15,0x0e,0x07,0x04,0x09,0x15,0x95,0x02,0x0c,0x91,0x0b,0x09,0x00,0x91,0x17,0x09,0x95,0x40,0x0e,0x11,0x06,0x0e,0x95,0x08,0x30,0x06,0x15,0x11,0x00,0x00,0x00,0x01,0x0e,0x03,0x00,0x00,0x05,0x0b,0x12,0x11,0x05,0x84,0x06,0x18,0x19,0x06,0x84,0x08,0x30,0x2b, 0x01,0x10,0xe1,0x39,0x39,0x18,0xc6,0x10,0xc2,0x2f,0x5f,0x5e,0x5d,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0xd4,0xed,0x10,0xd6,0xed,0xd4,0xed,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x27,0x11,0x23,0x11,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x11,0x33,0x11,0x16,0x33,0x32,0x37,0x02,0x52, 0x44,0x58,0x23,0x29,0xa4,0x2e,0x17,0x4d,0x48,0x46,0x55,0x1d,0x22,0xa4,0x2e,0x24,0x4e,0x48,0x02,0xd9,0x39,0x0a,0xfd,0x56,0x02,0xd9,0x0d,0x46,0x95,0x3b,0x08,0x02,0x84,0xfd,0x4c,0x0d,0x45,0x00,0x00,0x02,0xff,0xec,0x00,0x00,0x02,0xee,0x05,0xec,0x00,0x11,0x00,0x19,0x00,0x4a,0x40,0x29,0x0d,0x12,0x15,0x96,0x40,0x0b,0x12,0x80, 0x12,0x04,0x01,0x95,0x40,0x10,0x0e,0x03,0x10,0x95,0x08,0x30,0x03,0x15,0x0e,0x00,0x00,0x00,0x0d,0x10,0x12,0x03,0x02,0x84,0x0f,0x03,0x01,0x03,0x03,0x1b,0x17,0x84,0x08,0x2f,0xe1,0x12,0x39,0x2f,0x5d,0xf1,0x17,0x39,0xc2,0x2f,0x00,0x3f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x1a,0x10,0xdc,0x1a,0xed,0x12,0x39,0x31,0x30, 0x01,0x21,0x11,0x23,0x11,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x11,0x33,0x11,0x21,0x21,0x26,0x26,0x23,0x22,0x15,0x14,0x33,0x02,0xee,0xff,0x00,0xa4,0x42,0x88,0x94,0x75,0x59,0x56,0x3a,0xa4,0x01,0x00,0xfe,0x5c,0x04,0x49,0x32,0x4c,0x8b,0x02,0x87,0xfd,0x79,0x02,0x87,0x74,0x67,0x55,0x78,0x3b,0x01,0xf8,0xfd,0x26,0x44, 0x5c,0x4a,0x56,0x00,0x00,0x01,0x00,0xa6,0xfe,0x1e,0x02,0x5a,0x05,0xec,0x00,0x0c,0x00,0x24,0x40,0x13,0x0c,0x0a,0x95,0x40,0x02,0x1c,0x06,0x00,0x0c,0x0c,0x08,0x84,0x05,0x0d,0x0e,0x05,0x84,0x08,0x30,0x2b,0x01,0x10,0xf1,0xc2,0x18,0x2f,0x00,0x3f,0x3f,0x1a,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14, 0x33,0x32,0x37,0x02,0x5a,0x40,0x43,0x93,0x9e,0xa4,0xa0,0x3c,0x34,0xfe,0x3a,0x1c,0xaf,0x9f,0x06,0x80,0xf9,0x86,0xc8,0x1a,0x00,0x01,0x00,0xa6,0xfe,0x21,0x04,0xb2,0x05,0xec,0x00,0x1c,0x00,0x57,0x40,0x30,0x0b,0x0a,0x96,0x40,0x15,0x12,0x1b,0x15,0x96,0x08,0x30,0x10,0x01,0x01,0x01,0x03,0x95,0x1b,0x1c,0x0f,0x15,0x14,0x0c,0x95, 0x12,0x0f,0x10,0x00,0x15,0x0b,0x0b,0x06,0x01,0x01,0x0e,0x0f,0x0c,0x14,0x14,0x18,0x83,0x06,0x06,0x1e,0x12,0x0e,0x84,0x0f,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x11,0x39,0x2f,0x33,0x00,0x3f,0x3f,0xed,0x39,0x3f,0x3f,0xfd,0xc6,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x35,0x16, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x01,0x27,0xa5,0xb1,0xae,0xdf,0xdf,0xcd,0x52,0x01,0x80,0xfd,0xbe,0xa4,0xa4,0x03,0x2d,0xfe,0x77,0xd8,0xec,0xfe,0xbc,0xf7,0xb6,0xfe,0x72,0xa2,0x68,0xb6,0x90,0x96,0xa5,0x33,0x02,0x14,0xfc,0x8c, 0x05,0xec,0xfe,0x14,0x33,0xfd,0xe1,0x1a,0xeb,0xb3,0xcc,0xfe,0xf7,0x00,0x00,0x01,0x00,0xa6,0xff,0xe8,0x06,0x54,0x04,0x00,0x00,0x1f,0x00,0x45,0x40,0x25,0x02,0x08,0x0d,0x1a,0x05,0x12,0x95,0x40,0x0a,0x10,0x00,0x1e,0x16,0x0d,0x0f,0x1f,0x84,0x01,0x1e,0x0e,0x16,0x0d,0x16,0x42,0x0e,0x84,0x0d,0x08,0x17,0x84,0x16,0x20,0x21,0x16, 0x84,0x30,0x30,0x2b,0x01,0x10,0xe1,0x39,0x18,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0x32,0xe1,0x00,0x18,0x3f,0x33,0x33,0x2f,0x3f,0x1a,0xed,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11, 0x33,0x06,0x54,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0xfe,0xae,0xa4,0x69,0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0xa2,0xba,0x75,0x5f,0xd4,0x01,0xa1,0x02,0x77,0xfd,0xb4,0xaa,0x98,0xc0,0x86,0x02,0x48,0xfd,0xa0,0xfe,0xd2,0xb5,0x91,0x02,0x48,0x00,0x00,0x01,0x00,0xa6,0xfe,0x29,0x06,0x54,0x04,0x00,0x00,0x1f,0x00,0x46, 0x40,0x26,0x02,0x08,0x0d,0x1a,0x05,0x12,0x95,0x40,0x0a,0x10,0x00,0x1b,0x1e,0x16,0x0d,0x0f,0x1f,0x84,0x01,0x1e,0x0e,0x16,0x0d,0x16,0x42,0x0e,0x84,0x0d,0x08,0x17,0x84,0x16,0x20,0x21,0x16,0x84,0x30,0x30,0x2b,0x01,0x10,0xe1,0x39,0x18,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0x32,0xe1,0x00,0x18,0x3f,0x33,0x33,0x3f,0x3f,0x1a,0xed,0x39, 0x39,0x12,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x06,0x54,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0xfe,0xae,0xa4,0x69,0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0xfe,0x29,0x02, 0x79,0xba,0x75,0x5f,0xd4,0x01,0xa1,0x02,0x77,0xfd,0xb4,0xaa,0x98,0xc0,0x86,0x02,0x48,0xfd,0xa0,0xfe,0xd2,0xb5,0x91,0x02,0x48,0x00,0x00,0x01,0x00,0xa6,0xfe,0x1e,0x06,0x54,0x04,0x18,0x00,0x28,0x00,0x50,0x40,0x2d,0x26,0x28,0x95,0x23,0x1c,0x05,0x15,0x16,0x1b,0x04,0x0d,0x95,0x40,0x1d,0x18,0x10,0x13,0x0f,0x0a,0x12,0x26,0x26, 0x09,0x20,0x84,0x01,0x0e,0x0a,0x12,0x0a,0x42,0x14,0x11,0x84,0x12,0x1b,0x09,0x84,0x0a,0x29,0x2a,0x0a,0x84,0x30,0x30,0x2b,0x01,0x10,0xe1,0x39,0x18,0x2f,0xe1,0x32,0x2b,0x01,0x10,0xf2,0xe1,0x12,0x39,0x18,0x2f,0x00,0x2f,0x33,0x3f,0x3f,0x33,0x1a,0xed,0x17,0x32,0x3f,0xfd,0xc6,0x31,0x30,0x00,0x11,0x11,0x34,0x26,0x23,0x22,0x06, 0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x20,0x11,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x05,0xb0,0x69,0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0x01,0x52,0xbf,0xad,0x4c,0x36,0x3e,0x44,0xfe,0xaa,0x01, 0x3e,0x02,0x64,0xaa,0x98,0xc0,0x86,0xfd,0xb8,0x02,0x60,0x01,0x2e,0xb5,0x91,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x75,0x5f,0xd4,0xfe,0x5f,0xfd,0x85,0xe6,0xf8,0x1a,0x99,0x27,0x00,0x00,0x01,0xff,0x96,0xfe,0x1e,0x03,0xf8,0x04,0x18,0x00,0x1a,0x00,0x35,0x40,0x1c,0x15,0x00,0x18,0x0e,0x10,0x95,0x0b,0x1c,0x00,0x15,0x13,0x0f,0x04,0x95, 0x18,0x10,0x00,0x84,0x01,0x01,0x1c,0x12,0x15,0x08,0x0e,0x08,0x84,0x12,0x2f,0xe1,0xc6,0x11,0x33,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x31,0x30,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0x15,0x33,0x36,0x33,0x20,0x11, 0x03,0xf8,0xa4,0xec,0x7b,0xa3,0xb3,0x8b,0x48,0x2e,0x36,0x36,0xa4,0xa4,0x04,0x74,0xde,0x01,0x58,0x02,0x48,0x01,0x46,0xb9,0x8d,0xfd,0x24,0x99,0xb5,0x13,0x93,0x1a,0xcd,0x04,0x89,0xaa,0xc2,0xfe,0x5a,0x00,0x00,0x01,0x00,0xa6,0xfe,0x1e,0x05,0x08,0x04,0x18,0x00,0x1a,0x00,0x31,0x40,0x1a,0x1a,0x18,0x95,0x02,0x1c,0x10,0x13,0x0d, 0x15,0x0e,0x0f,0x08,0x95,0x13,0x10,0x1a,0x1a,0x16,0x84,0x05,0x05,0x1c,0x10,0x0c,0x84,0x0d,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x20,0x11,0x11,0x14,0x33, 0x32,0x37,0x05,0x08,0x40,0x43,0x93,0x9e,0xec,0x7b,0xa3,0xa4,0xa4,0x04,0x74,0xde,0x01,0x58,0xa0,0x3c,0x34,0xfe,0x3a,0x1c,0xaf,0x9f,0x02,0xdc,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xfe,0x5a,0xfd,0x00,0xc8,0x1a,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x0a,0x04,0x00,0x00,0x13,0x00,0x26,0x40,0x14,0x01,0x04,0x0f,0x13, 0x04,0x0b,0x09,0x15,0x0b,0x0f,0x01,0x13,0x84,0x12,0x12,0x15,0x0b,0x08,0x84,0x09,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x33,0x00,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x26,0x35,0x11,0x33,0x04,0x0a,0x9c,0xfe,0x06,0x24,0x0c,0x04,0x04,0x9e,0xa4,0x01, 0xf2,0x20,0x10,0x04,0x06,0xa0,0x02,0xd1,0x33,0x18,0x35,0x4d,0xfd,0x66,0x04,0x00,0xfd,0x40,0x2d,0x21,0x33,0x3f,0x02,0x9c,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x33,0x40,0x1c,0x13,0x95,0x40,0x11,0x06,0x00,0x11,0x95,0x1b,0x30,0x16,0x95,0x00,0x16,0x0e,0x95,0x06,0x10,0x09,0x83, 0x0c,0x12,0x12,0x19,0x11,0x13,0x83,0x03,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x13,0x02,0x21,0x22,0x06,0x07,0x05,0x21,0x16,0x16,0x33,0x20,0x02,0x52,0xe3,0xfe,0xf1,0x01,0x1a,0xf0,0xe5,0x01,0x01, 0xfe,0xeb,0x69,0x1e,0xfe,0xd8,0x8d,0xb1,0x12,0x02,0x98,0xfd,0x66,0x0a,0xb4,0x94,0x01,0x34,0x18,0x01,0x1f,0xed,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x02,0x68,0x01,0x3e,0xa6,0x98,0x8c,0x9e,0xb4,0x00,0x00,0x02,0x00,0x60,0xff,0xea,0x05,0x60,0x04,0x16,0x00,0x13,0x00,0x1e,0x00,0x47,0x40,0x28,0x10,0x95,0x40,0x0f, 0x0b,0x00,0x0f,0x95,0x1b,0x30,0x1d,0x96,0x02,0x16,0x13,0x95,0x00,0x15,0x0c,0x95,0x0b,0x0f,0x17,0x96,0x08,0x10,0x0e,0x12,0x84,0x14,0x14,0x05,0x0c,0x10,0x00,0x00,0x20,0x1a,0x83,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0xe1,0x32,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31, 0x30,0x21,0x21,0x07,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x21,0x11,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x05,0x60,0xfd,0xd3,0xd7,0xeb,0xfe,0xef,0x01,0x1a,0xee,0x31,0x9a,0x02,0x15,0xfe,0x76,0x01,0x6f,0xfe,0x91,0x01,0xa2,0xfd,0xbc,0x60,0x52,0x9f,0xc1,0xba,0xa2,0x46, 0x16,0x01,0x21,0xeb,0xf3,0x01,0x2d,0x16,0x8c,0xfe,0xd6,0x8c,0xfe,0xce,0x02,0xed,0x19,0xe1,0xb3,0xb4,0xdc,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x05,0x64,0x04,0x18,0x00,0x11,0x00,0x22,0x00,0x43,0x40,0x25,0x01,0x03,0x12,0x12,0x1b,0x16,0x0f,0x20,0x95,0x03,0x16,0x1b,0x95,0x40,0x09,0x10,0x18,0x84,0x0c,0x0e,0x13,0x12,0x06,0x42, 0x00,0x13,0x84,0x12,0x23,0x24,0x12,0x84,0x08,0x30,0x1e,0x84,0x06,0x2f,0xe1,0x2b,0x01,0x10,0xe1,0x39,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x1a,0xed,0x3f,0xed,0x39,0x39,0x11,0x39,0x2f,0x12,0x39,0x31,0x30,0x25,0x23,0x06,0x23,0x22,0x26,0x35,0x10,0x00,0x21,0x20,0x00,0x11,0x14,0x06,0x23,0x22,0x26,0x03,0x33,0x15,0x10,0x33, 0x32,0x11,0x34,0x26,0x23,0x22,0x00,0x15,0x10,0x33,0x32,0x11,0x02,0xdf,0x06,0x57,0xcc,0x9e,0xb8,0x01,0x65,0x01,0x2d,0x01,0x1c,0x01,0x56,0xc8,0xb0,0x6a,0x7b,0x75,0x9f,0xb9,0xd6,0xfa,0xe0,0xde,0xfe,0xfc,0xcf,0xbf,0xb2,0xca,0xeb,0xd5,0x01,0x17,0x01,0x59,0xfe,0xb6,0xfe,0xf0,0xe1,0xf5,0x5c,0x01,0xc2,0x5a,0xfe,0xc6,0x01,0x44, 0xdf,0xf9,0xfe,0xfe,0xd8,0xfe,0xbe,0x01,0x3a,0x00,0x00,0x03,0x00,0x60,0xfe,0x29,0x04,0xba,0x05,0xec,0x00,0x11,0x00,0x18,0x00,0x1f,0x00,0x48,0x40,0x2a,0x02,0x1b,0x13,0x00,0x19,0x95,0x03,0x16,0x12,0x0c,0x1a,0x95,0x40,0x09,0x10,0x0a,0x00,0x16,0x83,0x0f,0x0e,0x00,0x06,0x03,0x42,0x09,0x0c,0x13,0x19,0x04,0x00,0x84,0x03,0x20, 0x21,0x03,0x84,0x08,0x30,0x1d,0x83,0x06,0x2f,0xe1,0x2b,0x01,0x10,0xe1,0x17,0x39,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x3f,0x1a,0xed,0x39,0x39,0x3f,0xed,0x39,0x39,0x3f,0x31,0x30,0x05,0x11,0x23,0x11,0x26,0x02,0x35,0x34,0x00,0x37,0x11,0x33,0x11,0x16,0x12,0x15,0x14,0x00,0x03,0x11,0x36,0x36,0x35,0x34,0x26,0x01,0x11,0x06, 0x06,0x15,0x14,0x16,0x02,0xdf,0xa3,0xdd,0xff,0x01,0x04,0xd8,0xa3,0xdf,0xfc,0xfe,0xfe,0xd9,0x93,0xa0,0xa0,0xfe,0xca,0x91,0xa3,0xa3,0x18,0xfe,0x41,0x01,0xbf,0x11,0x01,0x22,0xdf,0xe7,0x01,0x20,0x17,0x01,0xd4,0xfe,0x2c,0x10,0xfe,0xe1,0xe5,0xe3,0xfe,0xdc,0x03,0x91,0xfc,0xe4,0x12,0xd0,0xac,0xab,0xd1,0xfc,0xf6,0x03,0x1c,0x12, 0xd2,0xac,0xa6,0xd3,0x00,0x01,0x00,0x0c,0xff,0xee,0x02,0x23,0x04,0x00,0x00,0x0f,0x00,0x20,0x40,0x10,0x08,0x0a,0x95,0x05,0x16,0x00,0x15,0x0e,0x0f,0x02,0x0f,0x84,0x0e,0x0e,0x11,0x08,0x2f,0x12,0x39,0x2f,0xe1,0x33,0x00,0x3f,0x3f,0x3f,0xfd,0xc6,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35, 0x11,0x33,0x02,0x23,0xa4,0x04,0x53,0xba,0x40,0x22,0x2c,0x51,0x69,0x8d,0xa4,0xc8,0xda,0x0e,0xaa,0x21,0xc8,0xa9,0x02,0x0a,0x00,0x01,0x00,0x0c,0xff,0xee,0x02,0x23,0x05,0xec,0x00,0x0f,0x00,0x20,0x40,0x10,0x08,0x0a,0x95,0x05,0x16,0x00,0x15,0x0e,0x00,0x02,0x0f,0x84,0x0e,0x0e,0x11,0x08,0x2f,0x12,0x39,0x2f,0xe1,0x33,0x00,0x3f, 0x3f,0x3f,0xfd,0xc6,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x02,0x23,0xa4,0x04,0x53,0xba,0x40,0x22,0x2c,0x51,0x69,0x8d,0xa4,0xc8,0xda,0x0e,0xaa,0x21,0xc8,0xa9,0x03,0xf6,0x00,0x01,0x00,0x0c,0xfe,0x1e,0x03,0x33,0x04,0x00,0x00,0x18,0x00,0x2f,0x40,0x18,0x18,0x16,0x95,0x02, 0x1c,0x07,0x09,0x12,0x0c,0x0e,0x95,0x09,0x16,0x12,0x0f,0x18,0x18,0x06,0x13,0x84,0x12,0x12,0x1a,0x0c,0x2f,0x12,0x39,0x2f,0xf1,0x33,0xc2,0x2f,0x00,0x3f,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x23,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x33, 0x32,0x37,0x03,0x33,0x40,0x43,0x92,0x9f,0x04,0x52,0xbb,0x40,0x22,0x2c,0x51,0x68,0x8e,0xa4,0x9f,0x3d,0x34,0xfe,0x3a,0x1c,0xaf,0x9f,0x01,0x58,0xd6,0x0e,0xaa,0x21,0xc7,0xaa,0x02,0x0a,0xfb,0x72,0xc8,0x1a,0x00,0x01,0x00,0xa6,0xfe,0x29,0x02,0xbc,0x04,0x12,0x00,0x0f,0x00,0x23,0x40,0x11,0x07,0x1b,0x08,0x0f,0x00,0x00,0x0a,0x02, 0x0d,0x10,0x00,0x00,0x11,0x0a,0x06,0x84,0x07,0x2f,0xe9,0x32,0x11,0x39,0x2f,0x00,0x3f,0xcd,0x32,0x32,0x2f,0x3f,0x3f,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x02,0xbc,0x2b,0x51,0x69,0x8d,0xa4,0xa4,0x04,0x4a,0xc2,0x40,0x22,0x03,0x5a,0x21,0xc6,0xab,0xfc,0x1f,0x05,0xd7,0xd3, 0xe5,0x0e,0x00,0x01,0x00,0xa6,0xfe,0x1e,0x02,0xbc,0x04,0x12,0x00,0x19,0x00,0x2c,0x40,0x16,0x14,0x1a,0x17,0x0a,0x08,0x95,0x0d,0x1c,0x11,0x0f,0x00,0x02,0x17,0x10,0x0a,0x00,0x00,0x1b,0x13,0x06,0x84,0x10,0x2f,0xe1,0x32,0x11,0x39,0x2f,0xc6,0x00,0x3f,0xdd,0xc6,0x3f,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x31,0x30,0x01,0x26,0x23,0x22, 0x06,0x15,0x11,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x02,0xbc,0x2b,0x51,0x69,0x8d,0xa0,0x3c,0x34,0x40,0x43,0x93,0x9e,0xa4,0x04,0x23,0x90,0x59,0x40,0x22,0x03,0x5a,0x21,0xc6,0xab,0xfd,0x68,0xc8,0x1a,0x8a,0x1c,0xaf,0x9f,0x04,0x94,0xd3,0x6c,0x79,0x0e,0x00,0x00,0x01, 0x00,0x90,0x00,0x00,0x02,0xa2,0x04,0x18,0x00,0x0c,0x00,0x1b,0x40,0x0d,0x06,0x15,0x00,0x02,0x95,0x0a,0x10,0x00,0x00,0x0e,0x05,0x84,0x06,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0x31,0x30,0x01,0x26,0x23,0x22,0x11,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x17,0x02,0xa2,0x46,0x54,0xd7,0xa1,0xce,0xaa,0x56,0x44,0x03,0x68, 0x26,0xfe,0xed,0xfd,0x85,0x02,0x7b,0xbd,0xe0,0x1e,0x00,0x01,0x00,0x0c,0xfe,0x29,0x02,0x1e,0x04,0x18,0x00,0x0c,0x00,0x1b,0x40,0x0d,0x00,0x1b,0x06,0x04,0x95,0x09,0x10,0x00,0x84,0x01,0x01,0x0e,0x06,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0x31,0x30,0x01,0x23,0x11,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15, 0x02,0x1e,0xa1,0xd7,0x4c,0x4e,0x50,0x54,0xb0,0xbe,0xfe,0x29,0x04,0x4e,0x01,0x17,0x28,0x92,0x20,0xd2,0xc5,0x00,0x00,0x02,0x00,0xa6,0x00,0x00,0x03,0x83,0x04,0x00,0x00,0x11,0x00,0x18,0x00,0x3e,0x40,0x20,0x0f,0x05,0x95,0x13,0x13,0x07,0x08,0x01,0x15,0x07,0x15,0x12,0x95,0x08,0x0f,0x03,0x10,0x10,0x0f,0x06,0x01,0x00,0x00,0x0c, 0x84,0x16,0x16,0x1a,0x13,0x06,0x84,0x07,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x32,0x2f,0x33,0x12,0x39,0x39,0x11,0x33,0x00,0x3f,0xed,0x3f,0x3f,0x11,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x21,0x23,0x03,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x17,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x03,0x83,0xb8, 0x75,0x3e,0x78,0x56,0xa4,0x01,0x52,0xa5,0xb7,0xea,0x53,0x39,0xfe,0x54,0x9a,0xcc,0xc4,0x01,0x14,0x92,0xfe,0x5a,0x04,0x00,0x98,0x84,0xda,0x31,0x04,0x21,0x7c,0x02,0x3c,0xfe,0xbd,0xa8,0x9b,0x00,0x00,0x02,0x00,0xa6,0x00,0x00,0x03,0x83,0x04,0x00,0x00,0x12,0x00,0x1a,0x00,0x43,0x40,0x24,0x04,0x13,0x95,0x40,0x0d,0x0b,0x0a,0x0d, 0x95,0x08,0x30,0x14,0x95,0x0a,0x15,0x00,0x0f,0x0b,0x0f,0x10,0x02,0x03,0x02,0x0d,0x12,0x00,0x00,0x06,0x84,0x17,0x17,0x1c,0x0d,0x14,0x84,0x0a,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x32,0x12,0x39,0x39,0x11,0x33,0x00,0x3f,0x3f,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x03,0x06,0x07,0x15,0x16,0x15, 0x14,0x06,0x23,0x21,0x11,0x33,0x11,0x33,0x32,0x36,0x37,0x13,0x01,0x11,0x33,0x32,0x35,0x34,0x26,0x23,0x03,0x83,0x8d,0x33,0x55,0xe6,0xc7,0xae,0xfe,0xc7,0xa4,0x56,0x41,0x53,0x22,0x79,0xfe,0x7b,0x95,0xd1,0x6e,0x5e,0x04,0x00,0xfe,0xcb,0x71,0x29,0x04,0x2b,0xd7,0x88,0xa3,0x04,0x00,0xfe,0x5a,0x41,0x51,0x01,0x14,0xfd,0xcf,0xfe, 0xbd,0x9d,0x4f,0x57,0x00,0x01,0x00,0x68,0xfe,0xb6,0x02,0xdb,0x04,0x18,0x00,0x2b,0x00,0x5d,0x40,0x0e,0x05,0x03,0x00,0x08,0x01,0x08,0x10,0x16,0x21,0x27,0x04,0x2a,0x19,0x0c,0xb8,0xff,0xc0,0x40,0x13,0x0b,0x0e,0x48,0x0c,0x0c,0x0e,0x95,0x2a,0x16,0x1c,0x1c,0x1e,0x95,0x19,0x10,0x05,0x05,0x27,0x00,0xb8,0x01,0x03,0x40,0x0d,0x0c, 0x1c,0x1c,0x27,0x83,0x10,0x10,0x2d,0x0c,0x21,0x83,0x16,0x0c,0x2f,0xd6,0xe1,0x11,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x10,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x32,0x2f,0x2b,0x11,0x12,0x17,0x39,0x2f,0x5d,0xdd,0xc6,0x31,0x30,0x17,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x11,0x16,0x33,0x32,0x35, 0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0xee,0x95,0x3b,0x3c,0x41,0x49,0x7b,0x8d,0x82,0x88,0xc3,0x56,0x7d,0x93,0x65,0xca,0x9f,0x7a,0x61,0x66,0x82,0x52,0x62,0x45,0x7e,0x94,0x72,0xc2,0xa9,0x41,0x02,0x27,0xaa,0x23,0x7b,0x1f,0x8f, 0x83,0x01,0x0d,0x63,0x90,0x3c,0x4e,0x36,0x41,0x89,0x64,0x80,0xa8,0x2e,0xa6,0x4a,0x50,0x40,0x3e,0x4b,0x35,0x40,0x8c,0x62,0x82,0xa8,0x00,0x01,0xff,0x92,0xfe,0x1e,0x02,0x68,0x06,0x02,0x00,0x15,0x00,0x2d,0x40,0x18,0x0b,0x0d,0x95,0x08,0x1c,0x00,0x02,0x95,0x40,0x13,0x01,0x00,0x00,0x05,0x0a,0x05,0x84,0x0f,0x16,0x17,0x0f,0x84, 0x08,0x30,0x2b,0x01,0x10,0xe1,0x18,0xc4,0x10,0xc2,0x2f,0x00,0x3f,0x1a,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x02,0x68,0x32,0x3c,0xaa,0xb9,0x8f,0x4c,0x2a,0x32,0x3c,0xac,0xb8,0x8e,0x4c,0x2a,0x05,0x5c,0x1b,0xdf,0xfa, 0xe7,0xa2,0xbf,0x13,0x93,0x1a,0xdf,0x05,0x17,0xa4,0xbe,0x12,0x00,0x01,0xff,0x9e,0xfe,0x1e,0x02,0x72,0x06,0x02,0x00,0x1d,0x00,0x53,0x40,0x2d,0x08,0x05,0x14,0x95,0x40,0x17,0x1b,0x0c,0x17,0x95,0x08,0x30,0x0f,0x11,0x95,0x0c,0x1c,0x00,0x02,0x95,0x40,0x1b,0x01,0x15,0x15,0x13,0x0f,0x06,0x06,0x09,0x00,0x00,0x09,0x0f,0x17,0x05, 0x09,0x84,0x13,0x1e,0x1f,0x13,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x39,0x39,0x18,0xc6,0x10,0xc0,0x2f,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0x1a,0xfd,0xc6,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x33,0x15,0x23,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32, 0x35,0x11,0x23,0x35,0x33,0x11,0x34,0x36,0x33,0x32,0x17,0x02,0x72,0x32,0x3a,0xac,0xb0,0xb0,0xb7,0x8f,0x4b,0x2b,0x32,0x3a,0xac,0xb0,0xb0,0xb8,0x8e,0x4c,0x2a,0x05,0x5c,0x1b,0xdf,0xfd,0xce,0x8b,0xfd,0xa4,0xa4,0xbd,0x13,0x93,0x1a,0xdf,0x02,0x52,0x8b,0x02,0x3a,0xa2,0xc0,0x12,0x00,0x01,0xff,0xa6,0xfe,0x1e,0x02,0x48,0x04,0x18, 0x00,0x14,0x00,0x22,0x40,0x11,0x14,0x12,0x95,0x02,0x1c,0x09,0x07,0x95,0x0c,0x10,0x14,0x14,0x10,0x09,0x10,0x84,0x04,0x2f,0xe1,0xc6,0x10,0xc2,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x20,0x11,0x11,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x33,0x32,0x37,0x02,0x48,0x3a,0x5c,0xfe, 0xfa,0x9a,0x3a,0x32,0x40,0x3d,0x90,0x9d,0x92,0x38,0x2e,0xfe,0x3c,0x1e,0x01,0x28,0x03,0x82,0xc5,0x19,0x8c,0x18,0xae,0x9c,0xfc,0x95,0xbb,0x22,0x00,0x02,0xff,0x44,0xfe,0x1e,0x02,0x8e,0x06,0x02,0x00,0x1b,0x00,0x23,0x00,0x68,0xb7,0x15,0x05,0x07,0x13,0x1c,0x0a,0x1e,0x07,0xb8,0xff,0xc0,0x40,0x30,0x13,0x16,0x48,0x07,0x08,0x08, 0x22,0x1e,0x96,0x0f,0x13,0x1f,0x13,0x02,0x09,0x03,0x13,0x22,0x96,0x0d,0x1c,0x00,0x02,0x95,0x40,0x19,0x01,0x1c,0x15,0x0a,0x05,0x10,0x07,0x00,0x00,0x05,0x20,0x84,0x10,0x05,0x84,0x15,0x24,0x25,0x15,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x18,0xd4,0xe1,0x10,0xc2,0x2f,0xc6,0x11,0x12,0x39,0x11,0x33,0x00,0x3f,0x1a,0xfd,0xc6,0x3f, 0xed,0x2f,0x5f,0x5e,0x5d,0xed,0x11,0x39,0x2f,0xcd,0x2b,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x16,0x17,0x15,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x11,0x34,0x36,0x33,0x32,0x17,0x01,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0x02,0x8e,0x32,0x3e,0xaa,0x7a,0x74,0x7a, 0x80,0x10,0xa3,0x82,0x69,0x86,0xb4,0x91,0x27,0x21,0xb8,0x8d,0x4c,0x2c,0xfe,0x43,0x23,0x25,0xae,0x63,0x8e,0x05,0x5c,0x1b,0xdf,0xfb,0x2a,0x2c,0x54,0xa6,0x68,0x34,0x81,0x99,0x79,0x5d,0x6d,0x91,0x04,0x04,0xb2,0xa2,0xc0,0x12,0xf9,0x78,0x06,0x70,0x5a,0x00,0x00,0x01,0x00,0x38,0xfe,0xd1,0x02,0x8e,0x04,0x16,0x00,0x14,0x00,0x30, 0x40,0x18,0x03,0x04,0x07,0x04,0x13,0x95,0x01,0x15,0x0d,0x0b,0x95,0x10,0x10,0x14,0x14,0x04,0x01,0x13,0x84,0x07,0x07,0x16,0x06,0x0d,0x2f,0x33,0x12,0x39,0x2f,0xf1,0x39,0x39,0xc1,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x39,0x10,0xcd,0x31,0x30,0x21,0x23,0x15,0x07,0x11,0x21,0x35,0x21,0x11,0x34,0x26,0x23,0x22,0x07,0x35,0x36, 0x33,0x20,0x11,0x11,0x33,0x02,0x8e,0xb1,0xa1,0xfe,0xfc,0x01,0x04,0x48,0x52,0x3e,0x2c,0x39,0x60,0x01,0x0c,0xb1,0xfa,0x35,0x01,0x2f,0x8c,0x02,0x41,0x67,0x58,0x22,0x8c,0x20,0xfe,0xd4,0xfd,0xa2,0x00,0x01,0x00,0x2b,0xfe,0x1e,0x02,0x81,0x05,0x2f,0x00,0x14,0x00,0x2e,0x40,0x17,0x14,0x12,0x95,0x02,0x1c,0x0a,0x0e,0x0b,0x06,0x95, 0x07,0x0f,0x00,0x00,0x0d,0x06,0x0d,0x06,0x0b,0x08,0x0f,0x84,0x04,0x2f,0xe9,0x33,0x32,0x33,0x32,0x2f,0x2f,0x33,0x2f,0x00,0x3f,0xed,0x33,0x32,0xc4,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x02,0x81,0x3a,0x5f,0xfe,0xf3,0xb0,0xb0,0xa4, 0x01,0x02,0xfe,0xfe,0x46,0x51,0x3b,0x30,0xfe,0x40,0x22,0x01,0x2e,0x04,0x28,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0xfb,0xf4,0x67,0x57,0x23,0x00,0x02,0x00,0x21,0xff,0xe8,0x04,0xa4,0x04,0x00,0x00,0x15,0x00,0x1d,0x00,0x4c,0x40,0x2b,0x01,0x10,0x14,0x18,0x04,0x0a,0x95,0x40,0x0d,0x0e,0x07,0x0d,0x95,0x08,0x30,0x13,0x04,0x0e,0x1b,0x95, 0x07,0x16,0x02,0x15,0x0e,0x0f,0x00,0x01,0x01,0x04,0x17,0x03,0x13,0x84,0x12,0x12,0x1f,0x0c,0x18,0x0a,0x0f,0x84,0x0e,0x2f,0xe1,0x39,0x39,0xc6,0x12,0x39,0x2f,0xe1,0x17,0x39,0x10,0xcd,0x00,0x3f,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x17,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11, 0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x05,0x35,0x21,0x15,0x10,0x33,0x32,0x36,0x04,0xa4,0x98,0xa4,0x04,0x66,0xd5,0xfe,0x8f,0x97,0x97,0xa4,0x02,0x0c,0xa4,0x98,0xfe,0xc4,0xfd,0xf4,0xfa,0x78,0x9a,0x01,0xdb,0xfe,0x25,0xa2,0xba,0x01,0xb4,0x3f,0x8b,0x01,0x9a,0xfe,0x66,0x01,0x9a,0xfe,0x66,0xb4,0x29,0x25, 0xfe,0xbc,0xb0,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x04,0x62,0x04,0x00,0x00,0x1b,0x00,0x38,0x40,0x1e,0x09,0x95,0x17,0x16,0x04,0x0e,0x11,0x03,0x10,0x0f,0x01,0x95,0x02,0x0f,0x12,0x0e,0x11,0x14,0x84,0x0c,0x0c,0x1d,0x1a,0x00,0x04,0x04,0x01,0x06,0x84,0x1a,0x2f,0xf1,0x33,0xc2,0x2f,0x32,0x11,0x12,0x39,0x2f,0xe1,0x32,0xc6,0x32, 0x00,0x3f,0xed,0x3f,0x17,0x32,0x3f,0xed,0x31,0x30,0x01,0x23,0x35,0x21,0x15,0x06,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x10,0x27,0x35,0x21,0x15,0x23,0x16,0x11,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x01,0x1c,0xbc,0x01,0x7f,0xdb,0xbd,0xa1,0xa6,0xb6,0xda,0x01,0x7e,0xb8,0xb8,0xfe,0xec,0xf2,0xed,0xfe,0xf1,0x03,0x74,0x8c,0x8e,0x64, 0xfe,0xe6,0xaf,0xd3,0xcc,0xb6,0x01,0x1a,0x64,0x8e,0x8c,0x89,0xfe,0xfb,0xe3,0xfe,0xe5,0x01,0x16,0xe1,0x01,0x07,0x00,0x01,0x00,0x90,0xff,0xe8,0x04,0x16,0x04,0x18,0x00,0x17,0x00,0x2a,0x40,0x16,0x04,0x95,0x15,0x16,0x00,0x0f,0x0c,0x0a,0x95,0x0f,0x10,0x0c,0x0c,0x01,0x12,0x83,0x07,0x07,0x19,0x01,0x84,0x00,0x2f,0xe1,0x12,0x39, 0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0x3f,0xed,0x31,0x30,0x13,0x33,0x11,0x10,0x21,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x12,0x15,0x14,0x00,0x23,0x20,0x11,0x90,0xa3,0x01,0x0b,0x93,0x9f,0x60,0x56,0x3b,0x35,0x3e,0x4f,0x96,0xa9,0xff,0x00,0xe3,0xfe,0x5d,0x04,0x00,0xfd,0xb4,0xfe,0xbe,0xdb, 0xc1,0xba,0xc8,0x1c,0x8a,0x1a,0xfe,0xe7,0xeb,0xfd,0xfe,0xd1,0x01,0xbe,0x00,0x01,0x00,0x0c,0x00,0x00,0x03,0xc8,0x04,0x00,0x00,0x0b,0x00,0x1d,0x40,0x0d,0x00,0x05,0x0a,0x09,0x15,0x0a,0x0f,0x01,0x00,0x00,0x0d,0x08,0x09,0x2f,0x33,0x11,0x33,0x2f,0x32,0x00,0x3f,0x3f,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x06, 0x07,0x01,0x23,0x01,0x33,0x03,0xc8,0xb4,0xfe,0xfc,0x1c,0x06,0x04,0x09,0x1b,0xfe,0xf2,0xac,0x01,0x96,0xa4,0x02,0xe8,0x51,0x3e,0x43,0x48,0xfd,0x14,0x04,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x05,0xb0,0x04,0x00,0x00,0x1b,0x00,0x3c,0x40,0x20,0x00,0x04,0x09,0x0c,0x16,0x1a,0x06,0x12,0x11,0x15,0x12,0x0f,0x1b,0x1a,0x04,0x09, 0x08,0x16,0x13,0x12,0x0c,0x16,0x04,0x0c,0x03,0x11,0x01,0x00,0x00,0x1d,0x10,0x11,0x2f,0x33,0x11,0x33,0x2f,0x32,0x12,0x17,0x39,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x00,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x01,0x33,0x13,0x16, 0x17,0x33,0x36,0x37,0x13,0x33,0x05,0xb0,0xac,0xd3,0x0b,0x03,0x09,0x02,0x10,0xec,0x95,0xd5,0x0a,0x04,0x08,0x02,0x0e,0xd2,0xa2,0x01,0x36,0xa8,0xd2,0x0c,0x05,0x04,0x03,0x12,0xe5,0xa4,0x03,0x02,0x28,0x34,0x2c,0x32,0xfd,0x00,0x03,0x04,0x24,0x38,0x27,0x35,0xfc,0xfc,0x04,0x00,0xfd,0x23,0x2b,0x34,0x24,0x39,0x02,0xdf,0x00,0x01, 0x00,0x0c,0x00,0x00,0x03,0xd1,0x05,0xec,0x00,0x14,0x00,0x2c,0x40,0x17,0x00,0x15,0x09,0x15,0x04,0x0a,0x14,0x0f,0x0f,0x0f,0x11,0x95,0x0c,0x00,0x0f,0x0a,0x0f,0x14,0x03,0x09,0x00,0x16,0x09,0x2f,0x10,0xc6,0x11,0x17,0x39,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x3f,0x33,0x33,0x3f,0x3f,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x06,0x07, 0x01,0x23,0x01,0x12,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x07,0x03,0xd1,0xb5,0xfe,0xea,0x02,0x10,0x06,0x06,0x11,0xfe,0xdf,0xaa,0x01,0xdc,0x7e,0xe4,0x3d,0x2b,0x34,0x2a,0x7f,0x3f,0x54,0x03,0x14,0x07,0x47,0x18,0x34,0xfc,0xea,0x04,0xae,0x01,0x3e,0x0d,0x93,0x12,0x98,0xc8,0x00,0x01,0x00,0x0a,0x00,0x00,0x03,0x4c,0x04,0x00, 0x00,0x0d,0x00,0x30,0x40,0x1a,0x00,0x01,0x04,0x09,0x04,0x05,0x03,0x15,0x05,0x0f,0x09,0x01,0x00,0x04,0x40,0x05,0x05,0x01,0x84,0x04,0x0e,0x0f,0x04,0x84,0x08,0x30,0x2b,0x01,0x10,0xf1,0xc1,0x18,0x2f,0x1a,0x10,0xcd,0x12,0x39,0x00,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x01,0x01,0x11,0x23,0x11,0x01,0x33,0x13,0x16,0x17,0x33,0x36, 0x37,0x13,0x03,0x4c,0xfe,0xb0,0xa4,0xfe,0xb2,0xb0,0xb8,0x29,0x11,0x04,0x18,0x20,0xbc,0x04,0x00,0xfd,0x77,0xfe,0x89,0x01,0x77,0x02,0x89,0xfe,0x7f,0x57,0x2e,0x46,0x3f,0x01,0x81,0x00,0x00,0x01,0x00,0x21,0xfe,0xfa,0x03,0xfe,0x04,0x00,0x00,0x16,0x00,0x36,0x40,0x0f,0x16,0x14,0x02,0x09,0x0f,0x95,0x08,0x15,0x0e,0x0a,0x95,0x0c, 0x0f,0x16,0x05,0xb8,0x01,0x03,0x40,0x09,0x12,0x0a,0x0e,0x10,0x10,0x18,0x0b,0x0f,0x09,0x2f,0x33,0xc6,0x12,0x39,0x2f,0xc6,0x32,0xd6,0xe1,0xc6,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x2f,0xdd,0xc6,0x31,0x30,0x05,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x21,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x06,0x15,0x14,0x33,0x32,0x37,0x03, 0xfe,0x34,0x41,0x58,0x6b,0x09,0xfd,0x52,0x02,0x5e,0xfd,0xdb,0x03,0x16,0xfd,0xa2,0x02,0x58,0x22,0x5a,0x2c,0x30,0xee,0x18,0x6f,0x51,0x22,0x24,0x33,0x03,0x41,0x8c,0x2f,0xfc,0xbb,0x78,0x3d,0x69,0x1b,0x00,0x00,0x02,0x00,0x21,0xff,0x81,0x04,0x25,0x04,0x00,0x00,0x17,0x00,0x1e,0x00,0x7d,0x40,0x32,0x07,0x28,0x09,0x0d,0x48,0x04, 0x1e,0x14,0x1e,0x02,0x34,0x0d,0x44,0x0d,0x02,0x06,0x0d,0x16,0x0d,0x26,0x0d,0x03,0x1d,0x96,0x40,0x11,0x0d,0x80,0x02,0x00,0x18,0x00,0x07,0x0d,0x95,0x06,0x15,0x0c,0x08,0x95,0x0a,0x0f,0x18,0x00,0x1b,0x02,0x0e,0x05,0x14,0x02,0xb8,0x01,0x03,0x40,0x0b,0x0f,0x03,0x01,0x03,0x03,0x14,0x0d,0x08,0x0c,0x0c,0x14,0xb8,0x01,0x03,0xb5, 0x1b,0x1b,0x20,0x09,0x0d,0x07,0x2f,0x33,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x5d,0xe1,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x39,0x39,0x10,0xce,0x1a,0x10,0xdc,0x1a,0xed,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x00,0x2b,0x21,0x06,0x07,0x23,0x36,0x37,0x21,0x35,0x01,0x21,0x35, 0x21,0x15,0x01,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x35,0x34,0x23,0x22,0x02,0x06,0x0f,0x03,0x8e,0x04,0x0d,0xfe,0xaa,0x02,0x5e,0xfd,0xdb,0x03,0x16,0xfd,0xa2,0x90,0x3d,0xca,0x78,0x76,0x8e,0xac,0x9c,0xaa,0xac,0xb7,0x78,0x9a,0x46,0x39,0x48,0x37,0x33,0x03,0x41,0x8c,0x2f,0xfc,0xbb,0x8f,0x9f,0x78, 0x5c,0x6a,0x7c,0x8c,0x5a,0x54,0x00,0x01,0xff,0xdd,0xfe,0x21,0x03,0x68,0x04,0x00,0x00,0x18,0x00,0x44,0x40,0x24,0x0b,0x0a,0x96,0x40,0x11,0x0e,0x17,0x11,0x91,0x09,0x30,0x01,0x03,0x95,0x17,0x1c,0x10,0x0c,0x95,0x0e,0x0f,0x11,0x0b,0x0b,0x06,0x00,0x0c,0x10,0x10,0x14,0x83,0x06,0x06,0x1a,0x0d,0x00,0x2f,0xc4,0x12,0x39,0x2f,0xf1, 0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0xed,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x03,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x23,0xa5,0xb1,0xae,0xdf,0xde,0xce,0x52,0x01,0x80,0xfd,0xbe,0x03,0x2d,0xfe, 0x77,0xda,0xea,0xfe,0xbc,0xf7,0xb6,0xfe,0x72,0xa2,0x68,0xb6,0x90,0x95,0xa6,0x33,0x02,0x14,0x8c,0x33,0xfd,0xe1,0x1a,0xea,0xb4,0xcc,0xfe,0xf7,0x00,0x02,0xff,0xea,0xfe,0x21,0x03,0x8c,0x04,0x00,0x00,0x20,0x00,0x29,0x00,0xa0,0xb5,0x19,0x20,0x0b,0x01,0x4d,0x14,0xb8,0xff,0xe0,0x40,0x0a,0x0b,0x01,0x4d,0x02,0x00,0x23,0x1e,0x0c, 0x0a,0x20,0xb8,0xff,0xc0,0x40,0x47,0x12,0x16,0x48,0x20,0x00,0x04,0x23,0x95,0x0f,0x0a,0x1f,0x0a,0x02,0x09,0x03,0x0a,0x0a,0x04,0x13,0x12,0x96,0x40,0x19,0x40,0x09,0x0c,0x48,0x19,0x16,0x04,0x19,0x96,0x09,0x30,0x28,0x95,0x04,0x1c,0x18,0x14,0x95,0x16,0x0f,0x19,0x13,0x13,0x0e,0x07,0x14,0x18,0x18,0x1c,0x21,0x0c,0x0e,0x26,0x1e, 0x02,0x1c,0x07,0x20,0x20,0x1c,0x83,0x0e,0x0e,0x2b,0x15,0x26,0x84,0x07,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x10,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0xed,0x39,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x2b,0x1a,0xed,0x39,0x11,0x39,0x2f,0x5f,0x5e,0x5d,0xed,0x10,0xd4,0xcd, 0x2b,0x11,0x39,0x39,0x11,0x12,0x39,0x31,0x30,0x01,0x2b,0x2b,0x01,0x26,0x27,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x07,0x16,0x17,0x25,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x32,0x03,0x8c,0x55,0x64,0xa6,0xfe,0xfe,0x94,0xad,0xb0, 0x8b,0xb3,0xc8,0x20,0xe1,0xcb,0x52,0x01,0x80,0xfd,0xbe,0x03,0x2d,0xfe,0x77,0xd6,0xee,0x43,0x3e,0x29,0xfe,0xc2,0xa8,0x81,0x4d,0x59,0xb4,0xab,0xfe,0x21,0x4f,0x46,0x95,0x7c,0x67,0x64,0x82,0x76,0x3e,0x46,0x92,0xa3,0x33,0x02,0x14,0x8c,0x33,0xfd,0xe1,0x1a,0xe7,0xb1,0x75,0x6b,0x2e,0x21,0x39,0x5c,0x32,0x28,0x5e,0x00,0x00,0x01, 0x00,0x1c,0x00,0x00,0x02,0xe8,0x06,0x02,0x00,0x19,0x00,0x2a,0x40,0x15,0x13,0x08,0x10,0x01,0x15,0x0d,0x0b,0x95,0x10,0x01,0x00,0x84,0x01,0x01,0x0d,0x13,0x83,0x08,0x08,0x1b,0x0d,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x11,0x34,0x36,0x37,0x36,0x36,0x35,0x34, 0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x01,0x89,0xa3,0x4c,0x6e,0x6a,0x38,0x97,0x7e,0x8f,0x82,0x84,0x9c,0xc2,0xea,0x4f,0x81,0x50,0x3f,0x01,0xee,0x87,0xa2,0x6c,0x69,0x6e,0x3e,0x5f,0x80,0x4c,0x97,0x40,0xc8,0x98,0x5b,0x9f,0x7b,0x4d,0x83,0x6f,0x00,0x01,0x00,0x04,0x00,0x00,0x02,0xcf, 0x06,0x02,0x00,0x19,0x00,0x2e,0x40,0x18,0x14,0x05,0x17,0x0d,0x15,0x4f,0x00,0x01,0x00,0x02,0x95,0x17,0x01,0x0c,0x84,0x0d,0x0d,0x14,0x00,0x00,0x1b,0x05,0x83,0x14,0x2f,0xe1,0x12,0x39,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0x12,0x39,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15, 0x11,0x23,0x11,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x02,0xcf,0x87,0x94,0x7a,0x90,0x32,0x72,0x70,0x48,0xa4,0x39,0x5c,0x7a,0x4f,0xf0,0xc0,0x94,0x87,0x05,0x29,0x4e,0x78,0x59,0x38,0x72,0x75,0x73,0xa2,0x84,0xfe,0x12,0x01,0xee,0x5f,0x82,0x5c,0x79,0x9f,0x5f,0x95,0xcb,0x3e,0x00,0x00,0x01,0x00,0x00,0xff,0xea, 0x02,0xcb,0x05,0xec,0x00,0x19,0x00,0x30,0x40,0x19,0x15,0x06,0x18,0x0d,0x40,0x01,0x01,0x01,0x03,0x95,0x18,0x16,0x0d,0x00,0x0e,0x84,0x0d,0x0d,0x01,0x15,0x83,0x06,0x06,0x1b,0x01,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x00,0x3f,0x3f,0xfd,0xc6,0x5d,0x11,0x12,0x39,0x39,0x31,0x30,0x35,0x35,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x27,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x86,0x94,0x7a,0x91,0x3c,0x68,0x6f,0x4a,0xa4,0x3e,0x58,0x7a,0x4f,0xef,0xc2,0x93,0x27,0x9b,0x4e,0x76,0x5c,0x45,0x6e,0x6b,0x73,0xa0,0x87,0x01,0xee,0xfe,0x12,0x5e,0x88,0x58,0x77,0xa0,0x5f,0x97,0xc9,0x00,0x00,0x01,0x00,0x60,0xfe,0x21, 0x03,0x60,0x04,0x18,0x00,0x13,0x00,0x2e,0x40,0x1b,0x10,0x13,0x20,0x13,0x30,0x13,0x03,0x13,0x11,0x95,0x02,0x1c,0x3f,0x0b,0x01,0x0b,0x0d,0x95,0x08,0x10,0x0b,0x13,0x13,0x15,0x0f,0x83,0x05,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0xfd,0xc6,0x5d,0x31,0x30,0x01,0x06,0x23,0x22,0x02,0x11,0x10,0x00,0x33,0x32, 0x17,0x15,0x26,0x23,0x20,0x11,0x10,0x21,0x32,0x37,0x03,0x60,0x84,0x9c,0xe8,0xf8,0x01,0x07,0xf7,0x87,0x7b,0x7e,0x84,0xfe,0xac,0x01,0x4a,0x8c,0x80,0xfe,0x77,0x56,0x01,0x7b,0x01,0x6c,0x01,0x7f,0x01,0x91,0x41,0xa4,0x5b,0xfd,0x86,0xfd,0x96,0x66,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x92,0x06,0x02,0x00,0x0b,0x00,0x15,0x00,0x21, 0x00,0x3f,0x40,0x24,0x16,0x63,0x40,0x1c,0x06,0x00,0x1c,0x63,0x14,0x30,0x11,0x95,0x00,0x16,0x0c,0x95,0x40,0x06,0x01,0x1f,0x62,0x19,0x0f,0x14,0x19,0x62,0x08,0x30,0x09,0x83,0x14,0x14,0x23,0x0f,0x83,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xe1,0x00,0x18,0x3f,0x1a,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31, 0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x03,0x22,0x02,0x11,0x10,0x21,0x32,0x12,0x11,0x10,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x74,0xfe,0xfe,0xfe,0xee,0x01,0x1b,0x01,0x04,0x01,0x02,0x01,0x11,0xfe,0xe6,0xff,0xb4,0xbd,0x01,0x71,0xb4,0xbd,0xfe,0x8f,0x2f,0x40,0x40,0x2f, 0x2e,0x43,0x43,0x18,0x01,0x8c,0x01,0x76,0x01,0x7c,0x01,0x9c,0xfe,0x76,0xfe,0x86,0xfe,0x83,0xfe,0x67,0x05,0x8f,0xfe,0xb3,0xfe,0xc8,0xfd,0x80,0x01,0x4c,0x01,0x38,0x02,0x81,0xfd,0x0e,0x42,0x2f,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x00,0x03,0x00,0xa6,0x00,0x00,0x03,0x7f,0x04,0x00,0x00,0x0d,0x00,0x14,0x00,0x1b,0x00,0x40,0x40,0x23, 0x08,0x15,0x95,0x40,0x0f,0x01,0x00,0x0f,0x95,0x09,0x30,0x16,0x95,0x00,0x15,0x0e,0x95,0x01,0x0f,0x08,0x0a,0x0f,0x12,0x83,0x05,0x05,0x0a,0x83,0x19,0x19,0x1d,0x0f,0x16,0x84,0x00,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x33,0x11, 0x21,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x03,0x11,0x33,0x32,0x35,0x34,0x23,0x03,0x11,0x33,0x32,0x35,0x34,0x23,0xa6,0x01,0x56,0xa4,0xb0,0xac,0xdb,0xca,0xaf,0xbc,0xa2,0xbe,0xb8,0xa8,0xba,0xd3,0xe3,0x04,0x00,0x85,0x79,0xac,0x35,0x05,0x27,0xca,0x89,0xa2,0x03,0x74,0xfe,0xe2,0x94,0x8a,0xfe,0x57,0xfe,0xc1, 0x9d,0xa2,0x00,0x02,0x00,0x5c,0xff,0xe8,0x04,0x02,0x04,0x18,0x00,0x10,0x00,0x24,0x00,0x42,0x40,0x24,0x00,0x12,0x95,0x40,0x11,0x06,0x0c,0x11,0x95,0x0c,0x30,0x18,0x95,0x0c,0x16,0x1e,0x95,0x06,0x10,0x00,0x0f,0x12,0x12,0x15,0x09,0x83,0x1b,0x1b,0x26,0x0f,0x21,0x83,0x03,0x15,0x83,0x0f,0x2f,0xe1,0xd4,0xe1,0x11,0x12,0x39,0x2f, 0xe1,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x35,0x26,0x35,0x34,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x26,0x35,0x34,0x25,0x15,0x23,0x20,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x01,0x2f,0xbd,0xd9,0xb5,0xee,0x01, 0x14,0xfe,0xe1,0xf3,0xc0,0xd4,0x02,0x10,0x56,0xfe,0xee,0x81,0x71,0xa6,0xbe,0xbf,0xa3,0x68,0x78,0x88,0x78,0x02,0x14,0x04,0x3d,0xa9,0x7e,0x9c,0xfe,0xe6,0xf4,0xf5,0xfe,0xd3,0x9e,0x8a,0xce,0x78,0x8e,0xaa,0x4f,0x5d,0xd2,0xc0,0xb9,0xd1,0x54,0x44,0x48,0x58,0x00,0x01,0x00,0x60,0xff,0xe8,0x04,0x54,0x04,0xe2,0x00,0x27,0x00,0x57, 0x40,0x1c,0x12,0x95,0x40,0x15,0x1e,0x18,0x15,0x95,0x08,0x30,0x16,0x11,0x0f,0x95,0x18,0x16,0x07,0x09,0x00,0x02,0x96,0x25,0x09,0x95,0x1e,0x10,0x00,0x22,0xb8,0x01,0x03,0x40,0x10,0x04,0x06,0x13,0x13,0x11,0x0c,0x06,0x06,0x16,0x84,0x11,0x11,0x29,0x0c,0x83,0x1b,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0x10, 0xd6,0xe1,0xc6,0x00,0x3f,0xed,0x2f,0xfd,0xc6,0x10,0xc6,0x3f,0xed,0x32,0x32,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x14,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x11,0x23,0x35,0x21,0x11,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x04, 0x54,0x30,0x2a,0x5e,0x16,0x06,0x9c,0x8f,0xa8,0xd1,0xc5,0xa7,0x6e,0x4b,0xdf,0x01,0x7f,0xaf,0xb8,0xec,0xfe,0xe6,0x01,0x34,0xf5,0x51,0x49,0x05,0x70,0x56,0x3c,0x34,0x04,0x52,0x1a,0x76,0x42,0x68,0x06,0x48,0xe1,0xb3,0xb8,0xd0,0x26,0x01,0x04,0x8b,0xfe,0x17,0x56,0x01,0x18,0xf0,0xef,0x01,0x39,0x16,0x22,0x03,0x4c,0x6f,0x1a,0x00, 0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xe2,0x04,0x00,0x00,0x0b,0x00,0x35,0x40,0x1c,0x03,0x95,0x40,0x08,0x06,0x05,0x08,0x95,0x0c,0x30,0x0b,0x00,0x06,0x05,0x15,0x06,0x0f,0x09,0x08,0x04,0x00,0x84,0x01,0x01,0x0d,0x04,0x84,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2b,0x00,0x18,0x2f,0x1a, 0xed,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x03,0xe2,0xa4,0xfe,0x0c,0xa4,0xa4,0x01,0xf4,0xa4,0x01,0xc6,0xfe,0x3a,0x04,0x00,0xfe,0x52,0x01,0xae,0x00,0x00,0x03,0xff,0x18,0xfe,0x1e,0x02,0x38,0x05,0xd9,0x00,0x0b,0x00,0x1d,0x00,0x25,0x00,0x70,0xb7,0x1e,0x0e,0x0c,0x20,0x1b,0x18,0x16,0x1d,0xb8, 0xff,0xc0,0x40,0x36,0x13,0x16,0x48,0x1d,0x0c,0x0c,0x10,0x20,0x96,0x0f,0x16,0x1f,0x16,0x02,0x09,0x03,0x16,0x24,0x96,0x10,0x1c,0x06,0x63,0x40,0x00,0x19,0x0f,0x09,0x62,0x03,0x18,0x1b,0x03,0x62,0xff,0x30,0x0c,0x0c,0x1b,0x0e,0x1b,0x22,0x84,0x13,0x1e,0x1b,0x84,0x18,0x26,0x27,0x18,0x84,0x08,0x30,0x2b,0x01,0x10,0xe1,0x33,0x18, 0xd4,0xe1,0x12,0x39,0x10,0xc1,0x2f,0x2b,0x01,0x10,0xe1,0x00,0x18,0x3f,0xd6,0x1a,0xed,0x3f,0xed,0x2f,0x5f,0x5e,0x5d,0xed,0x12,0x39,0x2f,0xcd,0x2b,0x11,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x26,0x27,0x02,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x11, 0x33,0x11,0x16,0x17,0x25,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0xfa,0x2c,0x3e,0x3e,0x2c,0x2d,0x3f,0x3f,0x01,0x11,0x7c,0x7e,0x2d,0xfe,0xf7,0x68,0x88,0xb5,0x91,0x27,0x21,0xa4,0x7a,0x74,0xfe,0x6e,0x24,0x24,0xae,0x62,0x8f,0x05,0x04,0x3c,0x2e,0x2e,0x3d,0x3d,0x2e,0x2c,0x3e,0xf9,0x98,0x68,0x34,0xfe,0xe6,0x78,0x5e,0x6d,0x91,0x04, 0x04,0x12,0xfb,0xc2,0x2c,0x54,0x26,0x06,0x70,0x5a,0x00,0x01,0x00,0x04,0xfe,0x14,0x03,0x56,0x04,0x00,0x00,0x0c,0x00,0x2a,0x40,0x16,0x00,0x1c,0x02,0x06,0x0a,0x03,0x07,0x05,0x15,0x0c,0x0f,0x07,0x0f,0x0c,0x84,0x06,0x02,0x0a,0x0a,0x0e,0x05,0x07,0x2f,0xc6,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0x3f,0x3f,0x12,0x17,0x39,0x3f, 0x31,0x30,0x01,0x23,0x11,0x23,0x01,0x23,0x01,0x01,0x33,0x01,0x33,0x11,0x33,0x03,0x56,0xa4,0x04,0xfe,0x52,0xd7,0x01,0xdb,0xfe,0x00,0xe6,0x01,0xc4,0x04,0xa4,0xfe,0x14,0x03,0xc1,0xfe,0x2b,0x01,0xee,0x02,0x12,0xfe,0x14,0x01,0xec,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x02,0xf8,0x04,0x00,0x00,0x05,0x00,0x19,0x40,0x0c,0x04,0x95, 0x01,0x15,0x02,0x0f,0x00,0x00,0x07,0x04,0x84,0x01,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0x3f,0xed,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x02,0xf8,0xfd,0xae,0xa4,0x01,0xae,0x04,0x00,0xfc,0x8c,0x00,0x02,0x00,0x60,0xfe,0x29,0x05,0x21,0x06,0x02,0x00,0x19,0x00,0x26,0x00,0x38,0x40,0x1e,0x05,0x1b,0x13,0x07,0x10,0x24,0x95,0x0a, 0x16,0x1e,0x95,0x10,0x10,0x00,0x02,0x95,0x17,0x01,0x00,0x00,0x05,0x84,0x1a,0x13,0x07,0x07,0x28,0x21,0x83,0x0d,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xf1,0xc2,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x23,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x12,0x33,0x32, 0x17,0x33,0x11,0x34,0x36,0x33,0x32,0x17,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x21,0x37,0x36,0xa4,0xa4,0x04,0x6e,0xee,0xc2,0xea,0xff,0xd6,0xd3,0x60,0x04,0xb4,0x8a,0x48,0x2f,0xfe,0x4b,0xa7,0x7b,0x98,0xaa,0xa7,0x84,0x8b,0xae,0x05,0x5c,0x1b,0xcf,0xf9,0x81,0x02,0x85,0xc6,0x01,0x12,0xee,0x01, 0x00,0x01,0x30,0xa6,0x01,0x40,0x99,0xb7,0x12,0xfb,0xdb,0x9b,0x7b,0xad,0xde,0xc4,0xb3,0xc7,0xc2,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x02,0xe8,0x06,0x02,0x00,0x1f,0x00,0x50,0x40,0x2a,0x03,0x00,0x06,0x95,0x40,0x09,0x17,0x05,0x09,0x95,0x08,0x30,0x1a,0x0f,0x17,0x05,0x15,0x14,0x12,0x95,0x17,0x01,0x02,0x02,0x1a,0x04,0x07,0x07, 0x14,0x09,0x00,0x04,0x84,0x05,0x05,0x14,0x1a,0x83,0x0f,0x0f,0x21,0x14,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0x12,0x39,0x39,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x34,0x36,0x37,0x36, 0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x01,0x89,0xc5,0xc5,0xa3,0xae,0xae,0x51,0x69,0x6a,0x38,0x97,0x7e,0x8f,0x82,0x84,0x9c,0xc2,0xea,0x4f,0x81,0x4e,0x41,0x02,0x04,0x8b,0xfe,0x87,0x01,0x79,0x8b,0x7a,0x9d,0x68,0x69,0x6e,0x3e,0x5f,0x80,0x4c,0x97,0x40,0xc8,0x98,0x5b,0x9f, 0x7b,0x4b,0x7d,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x02,0xcf,0x06,0x02,0x00,0x1f,0x00,0x4e,0x40,0x2a,0x0e,0x0b,0x11,0x95,0x40,0x14,0x1d,0x10,0x14,0x95,0x08,0x30,0x10,0x15,0x4f,0x00,0x01,0x00,0x02,0x95,0x1d,0x01,0x13,0x13,0x10,0x1a,0x0c,0x0c,0x00,0x14,0x0b,0x10,0x84,0x0f,0x0f,0x05,0x00,0x00,0x21,0x05,0x83,0x1a,0x2f,0xe1, 0x12,0x39,0x2f,0x12,0x39,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17, 0x02,0xcf,0x87,0x94,0x7a,0x90,0x32,0x72,0x6b,0x4d,0xb0,0xb0,0xa4,0xc6,0xc6,0x41,0x54,0x7a,0x4f,0xf0,0xc0,0x94,0x87,0x05,0x29,0x4e,0x78,0x59,0x38,0x72,0x75,0x6e,0x9d,0x78,0x8b,0xfe,0x87,0x01,0x79,0x8b,0x54,0x80,0x53,0x79,0x9f,0x5f,0x95,0xcb,0x3e,0x00,0x00,0x03,0x00,0x60,0xff,0xe8,0x07,0x27,0x05,0xec,0x00,0x15,0x00,0x22, 0x00,0x25,0x00,0x4a,0x40,0x29,0x11,0x05,0x0e,0x20,0x95,0x08,0x16,0x25,0x01,0x95,0x04,0x15,0x00,0x23,0x95,0x14,0x0f,0x1a,0x95,0x0e,0x10,0x12,0x00,0x11,0x14,0x16,0x03,0x01,0x25,0x84,0x04,0x04,0x0b,0x23,0x00,0x03,0x03,0x27,0x1d,0x83,0x0b,0x2f,0xe1,0x12,0x39,0x2f,0xc6,0x32,0x12,0x39,0x2f,0xe1,0x32,0x17,0x39,0x00,0x3f,0x3f, 0xed,0x3f,0xed,0x39,0x3f,0xed,0x39,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x21,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x21,0x11,0x07,0x27,0xfd,0x9f,0x02,0x58,0xfc,0x4e,0x04,0x72,0xee,0xc2, 0xe6,0x01,0x02,0xd6,0xce,0x62,0x04,0xa4,0x03,0x17,0xfc,0x45,0xa4,0x80,0x98,0xa8,0xa4,0x89,0x8a,0xad,0x02,0xc9,0xfd,0xdb,0x03,0xd1,0xfc,0xbb,0x8c,0xb4,0xcc,0x01,0x16,0xe8,0x01,0x00,0x01,0x32,0xa8,0x02,0x7c,0xfe,0x14,0xfd,0xd7,0x87,0x7f,0xb1,0xdf,0xc3,0xac,0xce,0xcb,0x02,0x37,0xfd,0x0f,0x00,0x00,0x02,0x00,0x60,0xfe,0x21, 0x07,0x77,0x05,0xec,0x00,0x29,0x00,0x36,0x00,0x72,0x40,0x40,0x0b,0x0a,0x96,0x40,0x22,0x1f,0x28,0x22,0x96,0x08,0x30,0x01,0x03,0x95,0x28,0x1c,0x1c,0x10,0x19,0x34,0x95,0x13,0x16,0x0e,0x15,0x21,0x0c,0x95,0x1f,0x0f,0x2e,0x95,0x19,0x10,0x1d,0x00,0x22,0x0b,0x0b,0x06,0x01,0x0c,0x21,0x21,0x25,0x01,0x01,0x1c,0x1f,0x2a,0x03,0x0e, 0x84,0x0f,0x0f,0x16,0x25,0x83,0x06,0x06,0x38,0x31,0x83,0x16,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x17,0x39,0x39,0x2f,0x10,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x39,0x3f,0x3f,0xed,0x12,0x39,0x39,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x35,0x16,0x33, 0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xee,0xa4,0xb2,0xae,0xdf,0xdf,0xcd,0x52,0x01,0x7f,0xfd,0xbe, 0xa4,0x04,0x72,0xee,0xc2,0xe6,0x01,0x02,0xd6,0xce,0x62,0x04,0xa4,0x03,0x2e,0xfe,0x76,0xd7,0xec,0xfe,0xbd,0xf6,0xb6,0xfe,0xe4,0xa4,0x80,0x98,0xa8,0xa4,0x89,0x8a,0xad,0xfe,0x72,0xa2,0x68,0xb6,0x90,0x95,0xa6,0x33,0x02,0x14,0xfc,0x8c,0xb4,0xcc,0x01,0x16,0xe8,0x01,0x00,0x01,0x32,0xa8,0x02,0x7c,0xfe,0x14,0x33,0xfd,0xe1,0x1a, 0xe9,0xb5,0xcc,0xfe,0xf7,0x03,0xb6,0x87,0x7f,0xb1,0xdf,0xc3,0xac,0xce,0xcb,0x00,0x00,0x04,0x00,0x60,0xff,0x81,0x07,0xdb,0x05,0xec,0x00,0x22,0x00,0x2f,0x00,0x32,0x00,0x39,0x00,0xcb,0xb9,0x00,0x30,0xff,0xd8,0x40,0x4e,0x0b,0x10,0x01,0x4c,0x19,0x18,0x0b,0x10,0x01,0x4c,0x04,0x39,0x14,0x39,0x24,0x39,0x03,0x34,0x19,0x44,0x19, 0x02,0x06,0x19,0x16,0x19,0x26,0x19,0x03,0x09,0x13,0x07,0x10,0x2d,0x95,0x0a,0x16,0x02,0x00,0x00,0x32,0x33,0x03,0x06,0x19,0x38,0x96,0x40,0x1c,0x80,0x19,0x95,0x06,0x15,0x18,0x30,0x95,0x16,0x0f,0x27,0x95,0x40,0x10,0x10,0x14,0x00,0x30,0x18,0x18,0x1f,0x33,0x00,0x36,0x02,0x1a,0x05,0x1f,0x02,0xb8,0x01,0x03,0x40,0x0b,0x03,0x0f, 0x03,0x1f,0x03,0x02,0x0a,0x03,0x32,0x1f,0x03,0xb8,0x01,0x03,0x40,0x11,0x08,0x30,0x19,0x13,0x16,0x23,0x03,0x32,0x84,0x06,0x06,0x1f,0x0d,0x30,0x18,0x18,0x1f,0xb8,0x01,0x03,0xb5,0x36,0x36,0x3b,0x2a,0x83,0x0d,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x32,0x11,0x12,0x39,0x2f,0xe1,0x17,0x39,0x32,0x2b,0x01,0x5f,0x5e,0x5d,0x10, 0xe1,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x10,0xc0,0x18,0x2f,0x32,0x00,0x3f,0x3f,0x1a,0xed,0x3f,0xed,0x39,0x3f,0xfd,0x1a,0xdc,0x1a,0xed,0x11,0x12,0x17,0x39,0x10,0xce,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x5e,0x5d,0x5d,0x5d,0x2b,0x2b,0x21,0x06,0x07,0x23,0x36,0x37,0x21,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x10,0x00,0x33, 0x32,0x17,0x33,0x11,0x33,0x11,0x21,0x15,0x01,0x33,0x12,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x21,0x11,0x25,0x33,0x32,0x35,0x34,0x23,0x22,0x05,0xba,0x0c,0x04,0x90,0x04,0x0f,0xfe,0x3f,0x04,0x72,0xee,0xc2,0xe6,0x01,0x02,0xd6,0xce,0x62,0x04,0xa4,0x03,0x17, 0xfd,0x9f,0x92,0x86,0xf9,0x76,0x8e,0xac,0x9b,0xfc,0xd8,0xa4,0x80,0x98,0xa8,0xa4,0x89,0x8a,0xad,0x02,0xc9,0xfd,0xdb,0x01,0xd8,0xae,0xb4,0x75,0x9d,0x39,0x46,0x3b,0x44,0xb4,0xcc,0x01,0x16,0xe8,0x01,0x00,0x01,0x32,0xa8,0x02,0x7c,0xfe,0x14,0x2f,0xfc,0xbb,0x01,0x2e,0x78,0x5c,0x6b,0x7b,0x01,0xd7,0x87,0x7f,0xb1,0xdf,0xc3,0xac, 0xce,0xcb,0x02,0x37,0xfd,0x0f,0x09,0x5a,0x54,0x00,0x00,0x02,0x00,0x2b,0xff,0xe8,0x04,0x94,0x05,0x2f,0x00,0x1d,0x00,0x2c,0x00,0x53,0x40,0x2d,0x11,0x17,0x25,0x2b,0x04,0x09,0x23,0x95,0x1a,0x16,0x05,0x06,0x1f,0x06,0x00,0x95,0x03,0x0f,0x0c,0x0e,0x95,0x09,0x10,0x1e,0x07,0x0c,0x11,0x83,0x2b,0x2b,0x17,0x1f,0x0c,0x0c,0x17,0x83, 0x25,0x25,0x2e,0x02,0x1f,0x00,0x06,0x84,0x03,0x2f,0xe1,0x39,0x39,0xcd,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x39,0x10,0xcd,0x3f,0xed,0x12,0x17,0x39,0x31,0x30,0x13,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14, 0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x01,0x23,0x11,0x14,0x16,0x33,0x20,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0xdb,0xb0,0xb0,0xa4,0x01,0x73,0x46,0x54,0x7c,0x60,0x64,0x85,0x52,0x60,0x47,0x7a,0x94,0x72,0xf1,0xef,0xfb,0xde,0x01,0x6d,0xc9,0x9f,0x9e,0x01,0x30,0x59,0x79,0x8a,0x6b,0x03,0x74,0x8c,0xfa,0x35, 0xfe,0xd1,0x18,0x2e,0xa6,0x4a,0x4f,0x3f,0x3e,0x4b,0x33,0x40,0x8c,0x62,0x84,0xaa,0xcd,0xd7,0x01,0xe8,0xfe,0x24,0x9d,0x89,0xa0,0x39,0x4b,0x30,0x38,0x8b,0x69,0x48,0x00,0x02,0x00,0x2b,0xfe,0x1e,0x04,0x3e,0x06,0x02,0x00,0x22,0x00,0x2a,0x00,0x49,0x40,0x27,0x0b,0x0d,0x95,0x08,0x1c,0x23,0x29,0x95,0x12,0x16,0x1a,0x1b,0x25,0x1b, 0x15,0x95,0x18,0x0f,0x00,0x02,0x95,0x20,0x01,0x00,0x00,0x04,0x84,0x0b,0x24,0x10,0x1c,0x1c,0x2c,0x25,0x15,0x1b,0x84,0x17,0x18,0x2f,0xcd,0xe1,0x39,0x39,0x12,0x39,0x2f,0x33,0x33,0xc4,0xf1,0xc2,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x39,0x10,0xcd,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x14, 0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x35,0x34,0x36,0x33,0x32,0x17,0x01,0x11,0x21,0x11,0x14,0x16,0x33,0x32,0x04,0x3e,0x32,0x3d,0xaa,0xb9,0x8f,0x4b,0x2c,0x32,0x3d,0xac,0x3a,0x5f,0xfe,0xf3,0xb0,0xb0,0xa4,0x01,0x02,0xb8,0x8d,0x4c,0x2c,0xfe,0x43,0xfe, 0xfe,0x46,0x51,0x3e,0x05,0x5c,0x1b,0xdf,0xfa,0xe7,0xa3,0xbe,0x13,0x93,0x1a,0xdf,0x81,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xfa,0x35,0xfe,0xd1,0xa0,0xa2,0xc0,0x12,0xfa,0xa6,0x02,0xde,0xfd,0xbf,0x67,0x58,0x00,0x00,0x02,0x00,0x2b,0xff,0xe8,0x05,0xaa,0x05,0x2f,0x00,0x2b,0x00,0x34,0x00,0x77,0x40,0x41,0x22,0x13,0x24,0x13,0x00,0x2a, 0x18,0x33,0x96,0x0f,0x24,0x1f,0x24,0x02,0x24,0x24,0x18,0x2e,0x96,0x2a,0x16,0x11,0x95,0x02,0x16,0x0a,0x0b,0x0e,0x0b,0x05,0x95,0x08,0x0f,0x1b,0x1d,0x95,0x18,0x10,0x0c,0x2c,0x22,0x31,0x20,0x13,0x00,0x27,0x20,0x83,0x15,0x15,0x27,0x0e,0x1b,0x1b,0x27,0x84,0x31,0x31,0x36,0x0e,0x05,0x0b,0x84,0x07,0x08,0x2f,0xcd,0xe1,0x39,0x39, 0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0xc4,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x39,0x10,0xcd,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x31,0x30,0x25,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14, 0x33,0x32,0x37,0x26,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x03,0x18,0xa0,0x8a,0xfe,0xed,0xb0,0xb0,0xa4,0x01,0x02,0xfe,0xfe,0x93,0x4a,0x66,0x58,0x01,0x22,0xf3,0x87,0x66,0x72,0x81,0x9e,0xc9,0x38,0xd2, 0x86,0x75,0x93,0xbd,0x9b,0xba,0x02,0x54,0x70,0x54,0x66,0x78,0x60,0x52,0x6a,0x01,0x3d,0x02,0x4f,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0xfd,0xc1,0xc3,0x42,0x84,0xb0,0xfd,0x01,0x33,0x32,0xa8,0x50,0xe1,0xb7,0x81,0x61,0x96,0x7a,0x5b,0x67,0x86,0xc6,0x42,0x3a,0x2b,0x56,0x00,0x00,0x01,0x00,0x35,0xfe,0x1e,0x05,0xc8,0x06,0x02,0x00,0x2e, 0x00,0x58,0x40,0x30,0x06,0x08,0x95,0x03,0x1c,0x28,0x2b,0x12,0x15,0x16,0x15,0x0d,0x95,0x2b,0x10,0x26,0x14,0x17,0x95,0x1a,0x0f,0x21,0x23,0x95,0x1e,0x01,0x06,0x06,0x0a,0x21,0x21,0x28,0x11,0x84,0x12,0x12,0x1a,0x00,0x84,0x0a,0x0a,0x30,0x17,0x14,0x26,0x84,0x19,0x1a,0x2f,0xcd,0xe1,0x39,0x39,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f, 0xe1,0x32,0x39,0x2f,0x11,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x39,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x3f,0xfd,0xc6,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15, 0x15,0x21,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x05,0xc8,0xbe,0xae,0x4c,0x35,0x3d,0x44,0xc9,0xed,0x7c,0xa2,0xa3,0xf0,0xa3,0xaf,0xaf,0xbf,0x97,0x4f,0x33,0x3a,0x40,0xbb,0x01,0x93,0x04,0x74,0xdc,0xa8,0xb2,0x04,0xe7,0xf7,0x1a,0x99,0x27,0x01,0x3e,0x02,0x60,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x03,0x74,0xfc,0x8c,0x03,0x74,0x8c,0x92, 0xa8,0xc8,0x16,0x94,0x1f,0xee,0x89,0xaa,0xc2,0xd8,0xce,0x00,0x00,0x01,0x00,0x98,0xff,0xe8,0x04,0x50,0x05,0xfc,0x00,0x24,0x00,0x3c,0x40,0x21,0x07,0x0d,0x18,0x1e,0x04,0x10,0x05,0x95,0x21,0x16,0x13,0x15,0x95,0x10,0x10,0x00,0x01,0x18,0x83,0x0d,0x0d,0x1e,0x00,0x13,0x13,0x1e,0x83,0x07,0x07,0x26,0x01,0x84,0x00,0x2f,0xe1,0x12, 0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x3f,0xfd,0xc6,0x3f,0xed,0x12,0x17,0x39,0x31,0x30,0x13,0x33,0x11,0x14,0x16,0x33,0x20,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x98,0xa4,0x9f,0xa0,0x01, 0x2d,0x58,0x79,0x8c,0x69,0xc8,0x9e,0x7c,0x61,0x65,0x84,0x52,0x61,0x47,0x7a,0x97,0x6f,0xf1,0xef,0xfb,0xdd,0x05,0xfc,0xfb,0x9c,0x9d,0x89,0xa0,0x39,0x4b,0x30,0x39,0x89,0x6a,0x81,0xa5,0x2e,0xa6,0x4a,0x4f,0x3f,0x3e,0x4b,0x33,0x41,0x8b,0x62,0x86,0xa8,0xcc,0xd8,0x00,0x00,0x02,0x00,0xa6,0x00,0x00,0x04,0x60,0x05,0xec,0x00,0x08, 0x00,0x0b,0x00,0x2b,0x40,0x16,0x0b,0x01,0x95,0x04,0x15,0x00,0x09,0x95,0x07,0x0f,0x05,0x00,0x09,0x00,0x03,0x03,0x0d,0x01,0x07,0x0b,0x84,0x04,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xc6,0x32,0x00,0x3f,0x3f,0xed,0x39,0x3f,0xed,0x39,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x11,0x33,0x11,0x21,0x07,0x21,0x11,0x04,0x60,0xfd,0xa0,0x02, 0x58,0xfc,0x4e,0xa4,0x03,0x16,0xf2,0xfd,0xdc,0x03,0xd1,0xfc,0xbb,0x8c,0x05,0xec,0xfe,0x14,0x8c,0xfd,0x0f,0x00,0x00,0x02,0x00,0x31,0x00,0x00,0x03,0xc2,0x05,0x9a,0x00,0x1b,0x00,0x37,0x00,0x22,0x40,0x10,0x27,0x0e,0x40,0x26,0x12,0x0a,0x0b,0x42,0x0a,0x0b,0x03,0x00,0x1c,0x39,0x0b,0x27,0x2f,0x33,0x10,0xc6,0x32,0x00,0x3f,0xcd, 0x2b,0x00,0x18,0x3f,0x1a,0xed,0x31,0x30,0x01,0x03,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x13,0x03,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13, 0x03,0xc2,0xb6,0x93,0x6b,0x09,0x05,0x04,0x03,0x0f,0x73,0x91,0xb5,0x8b,0x6b,0x09,0x03,0x05,0x02,0x10,0x76,0x8c,0x6c,0x08,0x04,0x04,0x01,0x10,0x67,0x82,0xb6,0x93,0x6b,0x09,0x05,0x04,0x03,0x0f,0x73,0x91,0xb5,0x8b,0x6b,0x09,0x03,0x05,0x02,0x10,0x76,0x8c,0x6c,0x08,0x04,0x04,0x01,0x10,0x67,0x05,0x9a,0xfd,0x78,0x01,0x90,0x21, 0x3b,0x24,0x36,0xfe,0x6e,0x02,0x88,0xfe,0x5a,0x24,0x34,0x21,0x39,0x01,0xa4,0xfe,0x5a,0x20,0x38,0x16,0x42,0x01,0xa6,0xfc,0xed,0xfd,0x79,0x01,0x90,0x21,0x3b,0x24,0x36,0xfe,0x6e,0x02,0x87,0xfe,0x5b,0x24,0x35,0x21,0x3a,0x01,0xa3,0xfe,0x5b,0x20,0x39,0x17,0x42,0x01,0xa5,0x00,0x00,0x02,0x00,0x74,0x00,0x00,0x03,0x7f,0x05,0x9a, 0x00,0x07,0x00,0x0f,0x00,0x37,0x40,0x1c,0x0b,0x96,0x0e,0x08,0x0d,0x12,0x00,0x05,0x03,0x96,0x06,0x03,0x01,0x00,0x08,0x09,0x05,0x04,0x0c,0x0d,0x08,0x7f,0x09,0x09,0x11,0x0c,0x7f,0x0d,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x3f,0xed,0xcd,0x32,0x3f,0x33,0xdd,0xed,0x31,0x30,0x01,0x23,0x11, 0x21,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x03,0x7f,0x89,0xfe,0x06,0x88,0x03,0x0b,0x89,0xfe,0x06,0x88,0x03,0x0b,0x03,0xa2,0x01,0x74,0xfe,0x8c,0x01,0xf8,0xfa,0x66,0x01,0x74,0xfe,0x8c,0x01,0xf8,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x14,0x05,0xfc,0x00,0x13,0x00,0x23,0x00,0x3d,0x40,0x20,0x01,0x00, 0x14,0x96,0x15,0x15,0x1f,0x1a,0x95,0x0e,0x01,0x1f,0xec,0x07,0x16,0x01,0x14,0x11,0x83,0x18,0x14,0x18,0x14,0x1d,0x04,0x83,0x22,0x22,0x25,0x1d,0x84,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x11,0x39,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x15,0x16,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x35,0x36,0x36,0x35,0x34,0x23,0x22,0x11,0x11,0x10,0x21,0x32,0x36,0x35,0x10,0x02,0x9e,0xb4,0xc2,0xf7,0xcd,0xcd,0xdd,0xda,0xbc,0xa6,0xc6,0x95,0xfe,0xdf,0x78,0x98,0xd1,0xe7,0x01,0x10,0x83,0x8f,0x03,0x38,0x05,0x1d,0xd8,0xa6,0xc3,0xed,0xfb,0xea,0x02,0x8d, 0xbe,0xe4,0xb9,0x9b,0x7e,0xcc,0x78,0x82,0x14,0xa5,0x73,0xdc,0xfe,0xda,0xfd,0x87,0xfe,0xa6,0x90,0x87,0x01,0x30,0x00,0x02,0x00,0x14,0xff,0xe8,0x04,0xc4,0x06,0x02,0x00,0x2a,0x00,0x32,0x00,0x6b,0x40,0x3b,0x02,0x20,0x00,0x28,0x2b,0x00,0xec,0x2a,0x2b,0xec,0x20,0x20,0x1d,0x10,0x0e,0x95,0x13,0x10,0x2d,0x95,0x26,0x01,0x1d,0xec, 0x05,0x16,0x30,0x84,0x23,0x40,0x0b,0x0e,0x48,0x23,0x23,0x2b,0x0c,0x2a,0x2a,0x28,0x02,0x28,0x08,0x20,0x2b,0x1a,0x84,0x08,0x16,0x84,0x0c,0x0c,0x10,0x28,0x84,0x2b,0x2b,0x34,0x10,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0xd4,0xe1,0x11,0x39,0x11,0x12,0x39,0x10,0xca,0x2f,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x00,0x3f,0xed,0x3f, 0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0xfd,0xd4,0xed,0x12,0x39,0x11,0x12,0x39,0x31,0x30,0x01,0x06,0x07,0x02,0x00,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x12,0x13,0x26,0x00,0x35,0x34,0x36,0x33,0x20,0x13,0x36,0x37,0x05,0x02,0x23,0x22, 0x06,0x15,0x14,0x16,0x04,0xc4,0x42,0x59,0x0b,0xfe,0xed,0xea,0xbe,0xdc,0x16,0x15,0x58,0x26,0x20,0x32,0x31,0x65,0x7a,0x15,0x16,0x89,0x75,0x9e,0xb5,0x09,0xeb,0xfe,0xda,0xad,0x87,0x01,0x70,0x13,0x4d,0x4c,0xfe,0xc3,0x0e,0xd3,0x3f,0x4f,0xc7,0x02,0xe6,0x19,0x0f,0xfe,0xa6,0xfe,0x84,0xdc,0xc1,0x55,0x81,0x81,0x3a,0x78,0x11,0x89, 0x12,0x8a,0x6b,0x3f,0x81,0x81,0x50,0x84,0x97,0x01,0x29,0x01,0x12,0x08,0x01,0x18,0xd0,0x97,0xc9,0xfd,0x4a,0x0c,0x1f,0x35,0x02,0x35,0x71,0x5a,0x98,0xc9,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0xb8,0x05,0xb2,0x00,0x16,0x00,0x4f,0x40,0x27,0x12,0x0d,0x14,0x03,0x05,0x02,0x08,0x05,0x0d,0x0d,0x0a,0x07,0x00,0x02,0x91,0x14,0x04,0x0a, 0x03,0x07,0x00,0x12,0x00,0x03,0x03,0x18,0x05,0x0a,0x09,0x09,0x17,0x0e,0x0d,0x05,0x7e,0x08,0x08,0x18,0x17,0x11,0x12,0x39,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x11,0x33,0x33,0x2f,0x00,0x2f,0x3f,0x3f,0xed,0x32,0x11,0x12,0x39,0x2f,0x33,0x33,0x11,0x12,0x39,0x11,0x12,0x39,0x31,0x30,0x01,0x26,0x23,0x22,0x07, 0x01,0x11,0x23,0x11,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x36,0x36,0x33,0x32,0x17,0x04,0xb8,0x2c,0x2c,0x52,0x60,0xfe,0xd9,0xa8,0xfe,0x33,0xbf,0x01,0x41,0x06,0x1d,0x03,0x08,0x1a,0xc7,0x4b,0x8c,0x5e,0x36,0x2c,0x05,0x06,0x14,0xbe,0xfd,0xb2,0xfd,0xf2,0x02,0x0e,0x03,0x8c,0xfd,0x78,0x0c,0x4c,0x1c,0x3c,0x01,0x8e,0x96, 0x7c,0x14,0xff,0xff,0xff,0xb1,0x00,0x00,0x05,0xa0,0x05,0xb2,0x00,0x27,0x05,0xb5,0x00,0xe8,0x00,0x00,0x01,0x07,0x01,0x9f,0xfe,0xe3,0xff,0x99,0x00,0x14,0xb3,0x01,0x17,0x03,0x01,0xb8,0xff,0xc4,0xb4,0x17,0x17,0x09,0x09,0x25,0x01,0x2b,0x35,0x00,0x3f,0x35,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0xb8,0x06,0xf7,0x02,0x26,0x05,0xb5, 0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x96,0x01,0x70,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xd1,0x40,0x0a,0x26,0x20,0x09,0x16,0x25,0x02,0x01,0x23,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x03,0x00,0x60,0xfe,0x29,0x04,0xba,0x05,0xec,0x00,0x11,0x00,0x18,0x00,0x1f,0x00,0x45,0x40,0x25,0x0a,0x00,0x12,0x1a,0x95,0x0c, 0x09,0x10,0x02,0x1b,0x13,0x19,0x95,0x40,0x00,0x03,0x16,0x0f,0x83,0x16,0x0e,0x00,0x1d,0x03,0x42,0x13,0x0c,0x00,0x84,0x19,0x09,0x03,0x03,0x21,0x1d,0x83,0x06,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x32,0x32,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x33,0x1a,0xed,0x32,0x3f,0x3f,0x33,0xed,0x32,0x3f,0x31,0x30,0x05,0x11,0x23, 0x11,0x26,0x02,0x35,0x34,0x00,0x37,0x11,0x33,0x11,0x16,0x12,0x15,0x14,0x00,0x03,0x11,0x36,0x36,0x35,0x34,0x26,0x01,0x11,0x06,0x06,0x15,0x14,0x16,0x02,0xdf,0xa3,0xdd,0xff,0x01,0x04,0xd8,0xa3,0xdf,0xfc,0xfe,0xfe,0xd9,0x93,0xa0,0xa0,0xfe,0xca,0x91,0xa3,0xa3,0x18,0xfe,0x41,0x01,0xbf,0x11,0x01,0x22,0xdf,0xe7,0x01,0x20,0x17, 0x01,0xd4,0xfe,0x2c,0x10,0xfe,0xe1,0xe5,0xe3,0xfe,0xdc,0x03,0x91,0xfc,0xe4,0x12,0xd0,0xac,0xab,0xd1,0xfc,0xf6,0x03,0x1c,0x12,0xd2,0xac,0xa6,0xd3,0x00,0x00,0x02,0x00,0x00,0xff,0xea,0x06,0x2d,0x04,0x00,0x00,0x16,0x00,0x28,0x00,0x69,0x40,0x38,0x08,0x0b,0x20,0x20,0x0b,0x0f,0x12,0x01,0x09,0x04,0x12,0x18,0x01,0x10,0x95,0x15, 0x0f,0x24,0x1d,0xec,0x06,0x0b,0x16,0x17,0x83,0x01,0x01,0x03,0x18,0x83,0x10,0x0e,0x40,0x00,0x00,0x03,0x83,0x27,0x0e,0x22,0x1a,0x1f,0x42,0x09,0x08,0x22,0x84,0x1f,0x1f,0x2a,0x1a,0x83,0x0e,0x0e,0x2a,0x12,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x39,0x39,0x2b,0x01,0x10,0xf2,0xe1,0x32,0x18,0x2f,0x1a,0x10,0xdd,0xe1,0x10, 0xc9,0x2f,0xe1,0x00,0x3f,0x33,0xed,0x32,0x3f,0xed,0x32,0x32,0x32,0x5f,0x5e,0x5d,0x11,0x39,0x2f,0x11,0x39,0x31,0x30,0x01,0x23,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x22,0x07,0x35,0x36,0x33,0x21,0x05,0x21,0x06,0x15,0x14,0x16,0x33,0x32,0x11,0x35,0x33,0x15,0x10,0x33,0x32,0x36,0x35,0x34, 0x06,0x2d,0xb6,0x83,0xd5,0xbf,0xcf,0x64,0x04,0x67,0xce,0xb9,0xd1,0x84,0x7e,0x76,0x6a,0x96,0x05,0x2d,0xfe,0xa0,0xfc,0xd1,0x88,0x7b,0x6d,0xe8,0xa1,0xe5,0x6c,0x7c,0x03,0x74,0xdc,0xda,0xda,0xfa,0xbe,0xbe,0xfb,0xd9,0xd5,0xe1,0x58,0x9c,0x48,0x8c,0xe6,0xd6,0x96,0xa9,0x01,0x5a,0xfc,0xfc,0xfe,0xa6,0xaa,0x95,0xd6,0x00,0x00,0x01, 0x00,0x00,0xfe,0x96,0x04,0x90,0x04,0x18,0x00,0x33,0x00,0x83,0x40,0x28,0x06,0x08,0x95,0x40,0x03,0x34,0x80,0x11,0x29,0x27,0x15,0x29,0x15,0x17,0x2b,0x1f,0x1d,0x95,0x22,0x10,0x2b,0x0f,0x33,0x31,0x95,0x40,0x0c,0x16,0x17,0x29,0x11,0x2b,0x0f,0x27,0x15,0x25,0x17,0x06,0x06,0x0b,0xb8,0x01,0x2e,0x40,0x1a,0x33,0x2b,0x83,0x2c,0x2c, 0x00,0x2e,0x84,0x0f,0x0e,0x33,0x17,0x83,0x18,0x18,0x1a,0x1f,0x1f,0x25,0x42,0x25,0x84,0x1a,0x1a,0x35,0x1f,0x2f,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0xe1,0x2f,0xf0,0xe1,0x11,0x39,0x2f,0xe1,0x10,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x2f,0x3f,0x1a,0xed,0x32,0x3f,0x3f,0xed,0x32,0x11, 0x12,0x39,0x39,0x11,0x33,0x11,0x33,0x1a,0x10,0xdc,0x1a,0xed,0x32,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x35,0x26,0x26,0x35,0x34,0x37,0x06,0x07,0x06,0x07,0x06,0x07,0x23,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x00,0x37,0x36,0x37,0x33,0x02,0x15,0x14,0x16, 0x33,0x32,0x37,0x04,0x90,0x98,0x7d,0x3f,0x34,0x34,0x3b,0x39,0x46,0x77,0x85,0x14,0x06,0xf1,0x94,0x56,0x14,0x27,0xac,0xb0,0x56,0x50,0x2a,0x26,0x32,0x3e,0x8a,0x9c,0x15,0x01,0x8d,0x54,0x14,0x28,0xac,0xb0,0x57,0x4f,0x2a,0x26,0x44,0x87,0x9f,0x18,0x92,0x1f,0x57,0x48,0x2a,0x10,0xdb,0xb0,0x69,0x6a,0x06,0xdb,0x87,0x62,0x35,0x59, 0x01,0x72,0xf4,0x89,0x9f,0x15,0x89,0x16,0xde,0xbf,0x69,0x6a,0x01,0x65,0x65,0x35,0x59,0xfe,0x8e,0xf4,0x8c,0x9c,0x0f,0x00,0x00,0x02,0x00,0x56,0x00,0x00,0x05,0x48,0x05,0xb2,0x00,0x0e,0x00,0x1a,0x00,0x3c,0x40,0x1f,0x15,0x91,0x00,0x03,0x03,0x02,0x0f,0x91,0x40,0x09,0x04,0x02,0x0c,0x7d,0x18,0x0e,0x01,0x12,0x02,0x42,0x12,0x7d, 0x06,0x06,0x1b,0x01,0x7e,0x02,0x02,0x1c,0x1b,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x2f,0x3f,0x1a,0xed,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x01,0x11,0x23,0x11,0x26,0x00,0x35,0x34,0x00,0x21,0x20,0x00,0x15,0x14,0x00,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03, 0x23,0xa8,0xfc,0xfe,0xd7,0x01,0x63,0x01,0x18,0x01,0x1e,0x01,0x59,0xfe,0xd2,0xfe,0xb5,0xd2,0xf7,0xf8,0xd1,0xd2,0xf7,0xf7,0x01,0x64,0xfe,0x9c,0x01,0x64,0x17,0x01,0x29,0xdf,0xf1,0x01,0x3e,0xfe,0xcf,0xf1,0xde,0xfe,0xcc,0x03,0x9c,0xde,0xb3,0xb1,0xe0,0xde,0xb3,0xb1,0xe0,0x00,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0x50,0x04,0x18, 0x00,0x0e,0x00,0x1a,0x00,0x3a,0x40,0x1f,0x0f,0x95,0x09,0x10,0x02,0x1b,0x15,0x96,0x40,0x00,0x03,0x16,0x0c,0x83,0x18,0x0e,0x00,0x12,0x03,0x42,0x00,0x84,0x03,0x03,0x1c,0x12,0x83,0x06,0x06,0x1c,0x1b,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x33,0x1a,0xed,0x3f,0x3f,0xed,0x31,0x30, 0x05,0x11,0x23,0x11,0x26,0x02,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x02,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0xaa,0xa4,0xc5,0xe1,0x01,0x1a,0xf0,0xe5,0x01,0x01,0xe2,0xfe,0xf0,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab,0x14,0xfe,0x3d,0x01,0xc3,0x18,0x01,0x18,0xd8,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa, 0xdc,0xfe,0xe0,0x03,0x86,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0x00,0x00,0x02,0x00,0x5e,0xfe,0xae,0x04,0xa8,0x06,0x60,0x00,0x20,0x00,0x21,0x00,0x4d,0xb9,0x00,0x0d,0xff,0xd8,0x40,0x0f,0x13,0x1d,0x48,0x01,0x22,0x80,0x11,0x16,0x1c,0x0b,0x07,0x22,0x21,0x04,0x1c,0xb8,0xff,0xf0,0x40,0x15,0x10,0x16,0x48,0x1c,0x06,0x13,0x1f, 0x7e,0x01,0x03,0x03,0x08,0x13,0x7e,0x10,0x0e,0x0e,0x23,0x1a,0x7d,0x08,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0x33,0x2b,0x3f,0x12,0x39,0x39,0x12,0x39,0xc4,0x1a,0x10,0xce,0x31,0x30,0x2b,0x01,0x23,0x36,0x35,0x34,0x26,0x27,0x24,0x11,0x10,0x00,0x37,0x24,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14, 0x06,0x07,0x06,0x06,0x02,0x15,0x10,0x05,0x16,0x16,0x15,0x14,0x13,0x04,0x44,0xb4,0x4f,0x88,0xa3,0xfd,0xaa,0x01,0x15,0xfb,0x01,0x28,0x62,0x08,0x97,0x0d,0x84,0xca,0xca,0xdf,0x8f,0x01,0xcf,0xef,0xbb,0x21,0xfe,0xae,0x54,0x4c,0x3a,0x45,0x1b,0x62,0x02,0x68,0x01,0x13,0x01,0x79,0x47,0x3e,0x37,0x2f,0x1b,0x1c,0x24,0x28,0x5d,0x6c, 0x2f,0x2d,0x6e,0xfe,0xfa,0xbf,0xfe,0x23,0x57,0x2d,0x80,0x77,0x5a,0x06,0xa8,0x00,0x00,0x02,0x00,0x60,0xfe,0xc4,0x03,0xa4,0x04,0xc6,0x00,0x1e,0x00,0x1f,0x00,0x4f,0xb9,0x00,0x17,0xff,0xd8,0x40,0x1f,0x13,0x1d,0x48,0x1b,0x01,0x10,0x10,0x16,0x48,0x01,0x15,0x15,0x20,0x1f,0x10,0x0c,0x20,0x80,0x06,0xec,0x11,0x15,0x0b,0x0c,0x0c, 0x09,0x84,0x0e,0x0e,0x13,0x1d,0xb8,0x01,0x2e,0xb6,0x1a,0x18,0x18,0x21,0x04,0x83,0x13,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x12,0x39,0x2f,0xe1,0x33,0x11,0x33,0x00,0x3f,0xed,0x1a,0x10,0xce,0x3f,0x12,0x39,0x11,0x33,0x2b,0xc4,0x31,0x30,0x2b,0x01,0x0e,0x02,0x15,0x14,0x05,0x16,0x16,0x15,0x14,0x07,0x23,0x36,0x35,0x34,0x26,0x27, 0x24,0x11,0x10,0x25,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x37,0x03,0x10,0xb1,0xe2,0x75,0x01,0x25,0xc4,0xa3,0x50,0xb4,0x62,0x73,0x8d,0xfe,0x6e,0x01,0x52,0xd4,0x7a,0x0a,0x98,0x0c,0x0a,0x03,0xbe,0x36,0x5f,0xc8,0x94,0xfd,0x3a,0x28,0x7d,0x76,0x5f,0x58,0x50,0x54,0x3f,0x40,0x19,0x48,0x01,0x70,0x01,0x9e,0x8e,0x41,0x38, 0x33,0x1c,0x1a,0x24,0x25,0x85,0x20,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xa8,0x05,0x9a,0x00,0x11,0x00,0x38,0x40,0x0d,0x01,0x06,0x91,0x0d,0x0d,0x08,0x0c,0x91,0x09,0x03,0x08,0x01,0x10,0xb8,0x01,0x2c,0x40,0x0d,0xaf,0x03,0x01,0x03,0x03,0x08,0x0b,0x0b,0x13,0x0d,0x07,0x7e,0x08,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x12,0x39,0x2f, 0x5d,0xe1,0xc6,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0xfd,0xc6,0x31,0x30,0x01,0x23,0x36,0x35,0x34,0x23,0x21,0x11,0x23,0x11,0x21,0x15,0x21,0x11,0x21,0x32,0x15,0x14,0x03,0x70,0x8c,0x08,0x69,0xfe,0xe1,0xa8,0x02,0xec,0xfd,0xbc,0x01,0x25,0xf6,0x02,0x0e,0x1e,0x28,0x5a,0xfd,0x52,0x05,0x9a,0x98,0xfe,0x40,0xce,0x34,0x00,0x00,0x01, 0x00,0x90,0xfe,0x29,0x03,0x54,0x04,0x18,0x00,0x0e,0x00,0x2a,0x40,0x15,0x07,0x95,0x04,0x04,0x0f,0x01,0x95,0x0d,0x10,0x09,0x1b,0x05,0x05,0x00,0x00,0x10,0x04,0x04,0x07,0x84,0x0a,0x2f,0xe1,0x32,0x11,0x12,0x39,0x2f,0x33,0x2f,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x23,0x20,0x11,0x15,0x21,0x15,0x21,0x11,0x23, 0x11,0x34,0x12,0x33,0x33,0x03,0x54,0xee,0xfe,0xcd,0x01,0xf8,0xfe,0x08,0xa3,0xf4,0xe4,0xec,0x03,0x8e,0xfe,0xb0,0x4c,0x8c,0xfc,0xc3,0x04,0x02,0xea,0x01,0x03,0x00,0x00,0x01,0x00,0x48,0x00,0x00,0x04,0x7d,0x05,0x9a,0x00,0x07,0x00,0x36,0x40,0x1b,0x04,0x91,0x40,0x07,0x05,0x02,0x07,0x91,0x2b,0x30,0x05,0x03,0x02,0x03,0x00,0x02, 0x07,0x06,0x04,0x02,0x00,0x06,0x04,0x00,0x00,0x09,0x04,0x2f,0x12,0x39,0x2f,0x10,0xcd,0x10,0xcd,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x2f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x01,0x23,0x13,0x21,0x01,0x33,0x03,0x04,0x7d,0xfe,0xdb,0xb4,0xf2,0xfc,0xb2,0x01,0x1c,0xb4,0xe9,0x03,0x25,0xfc,0xdb,0x02,0x8e,0x03,0x0c, 0xfd,0x8b,0x00,0x01,0x00,0x33,0xfe,0x1e,0x03,0xd1,0x06,0x02,0x00,0x23,0x00,0x5e,0x40,0x32,0x12,0x95,0x40,0x23,0x1d,0x0b,0x23,0x95,0x2b,0x30,0x1a,0x18,0x95,0x1d,0x01,0x08,0x06,0x95,0x40,0x0b,0x1c,0x11,0x00,0x0e,0x08,0x08,0x00,0x03,0x84,0x0e,0x0e,0x00,0x1a,0x1a,0x15,0x12,0x12,0x20,0x42,0x23,0x12,0x20,0x84,0x15,0x15,0x00, 0x00,0x25,0x12,0x24,0x10,0xce,0x11,0x39,0x2f,0x39,0x2f,0xe1,0x11,0x39,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0x10,0xf1,0xe1,0x11,0x39,0x2f,0x11,0x12,0x39,0x00,0x3f,0x1a,0xed,0x32,0x3f,0xed,0x32,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x03,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x13,0x37, 0x21,0x13,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x03,0x07,0x03,0xd1,0x5d,0x7a,0x41,0x39,0x2b,0x21,0x2c,0x38,0x74,0x92,0x81,0x21,0xfd,0x3b,0x5d,0x7a,0x41,0x39,0x2a,0x22,0x2c,0x38,0x74,0x92,0x81,0x21,0x02,0x56,0xfe,0xfc,0xfe,0xab,0x91,0x56,0x6c,0x14,0x89,0x17,0xb3,0x87,0xaa,0x01,0x6c,0x5d, 0x01,0x04,0x01,0x55,0x90,0x5a,0x69,0x15,0x8a,0x16,0xb2,0x88,0xaa,0xfe,0x94,0x5c,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x85,0x05,0xb2,0x00,0x18,0x00,0x94,0x40,0x5c,0x5d,0x05,0x6d,0x05,0x7d,0x05,0x03,0x05,0x08,0x0a,0x0d,0x0e,0x04,0x0e,0x2c,0x04,0x5c,0x04,0x02,0x04,0x0e,0x01,0x5b,0x08,0x01,0x06,0x05,0x08,0x03,0x07,0x29,0x0d, 0x01,0x29,0x0a,0x79,0x0a,0x89,0x0a,0x03,0x0b,0x0a,0x0d,0x03,0x0c,0x0a,0x07,0x01,0x05,0x0c,0x01,0x5f,0x0c,0x01,0x07,0x0c,0x07,0x0c,0x0f,0x01,0x11,0x0f,0x91,0x14,0x04,0x06,0x07,0x07,0x0b,0x0f,0x0c,0x01,0x0c,0x0c,0x3a,0x0e,0x01,0x0e,0x05,0x08,0x0a,0x0d,0x04,0x06,0x11,0x01,0x17,0x7d,0x03,0x03,0x1a,0x11,0x2f,0x12,0x39,0x2f, 0xe1,0x33,0x12,0x17,0x39,0x5d,0x39,0x2f,0x5d,0x33,0x33,0x2f,0x33,0x00,0x3f,0xfd,0xc6,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x5d,0x11,0x17,0x33,0x5d,0x5d,0x11,0x17,0x33,0x5d,0x11,0x39,0x39,0x5d,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x31,0x30,0x00,0x5d,0x21,0x23,0x12,0x11,0x34,0x27,0x01,0x27,0x01,0x26,0x27,0x01,0x27,0x01, 0x26,0x23,0x22,0x07,0x35,0x36,0x21,0x20,0x00,0x11,0x10,0x03,0xfc,0xba,0x97,0x0e,0xfe,0x4d,0x54,0x01,0xe4,0x20,0x32,0xfd,0xfa,0x56,0x02,0x00,0x7c,0xb1,0xff,0xce,0xd2,0x01,0x03,0x01,0x3c,0x01,0x74,0x01,0x01,0x01,0x4d,0x58,0x5a,0xfe,0xae,0x6c,0x01,0x7c,0x60,0x4e,0xfe,0x6c,0x6c,0x01,0x92,0x6c,0xda,0xc2,0xb0,0xfe,0x1a,0xfe, 0x94,0xfe,0xc4,0x00,0x00,0x01,0xff,0x7b,0xfe,0x29,0x03,0x77,0x06,0x02,0x00,0x14,0x00,0x8d,0x40,0x5a,0x05,0x08,0x0a,0x0d,0x0e,0x04,0x0e,0x06,0x08,0x05,0x03,0x07,0x66,0x0d,0x01,0x0a,0x0d,0x01,0x0a,0x0a,0x01,0x0b,0x0d,0x0a,0x03,0x0c,0x16,0x07,0x76,0x07,0x02,0x07,0x76,0x0c,0x01,0x1d,0x0c,0x01,0x0c,0x0b,0x0e,0x7b,0x0e,0x02, 0x0c,0x04,0x2c,0x04,0x5c,0x04,0x6c,0x04,0xcc,0x04,0xdc,0x04,0x06,0x0e,0x0c,0x07,0x04,0x04,0x01,0x1b,0x0f,0xee,0x10,0x01,0x06,0x07,0x07,0x0b,0x0c,0x0c,0x04,0x0e,0x01,0x05,0x08,0x0a,0x0d,0x04,0x0f,0x13,0x84,0x03,0x03,0x16,0x15,0x0f,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x12,0x17,0x39,0x33,0x39,0x39,0x39,0x2f,0x33,0x33,0x2f,0x33, 0x00,0x3f,0xed,0x3f,0x17,0x39,0x5d,0x5d,0x2f,0x5d,0x5d,0x2f,0x5d,0x11,0x17,0x33,0x5d,0x5d,0x5d,0x11,0x17,0x33,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x31,0x30,0x01,0x23,0x12,0x11,0x34,0x27,0x05,0x27,0x25,0x26,0x27,0x05,0x27,0x25,0x02,0x25,0x35,0x04,0x00,0x11,0x10,0x02,0xa4,0xbc,0xed,0x08,0xfe,0x2f,0x31,0x01,0xe7,0x1e,0x3e, 0xfe,0x1a,0x30,0x01,0xd0,0xfa,0xfe,0x65,0x01,0xc2,0x02,0x3a,0xfe,0x29,0x01,0x4b,0x01,0x8a,0x4f,0x41,0xaa,0x82,0xb2,0x7c,0x7a,0xb2,0x81,0xac,0x01,0x88,0x4b,0xa6,0x58,0xfd,0x27,0xfe,0x2f,0xfe,0x94,0x00,0x00,0x01,0x00,0xb8,0xfe,0x1e,0x06,0x66,0x05,0x9a,0x00,0x2f,0x00,0x85,0x40,0x4b,0x3a,0x23,0x01,0x0c,0x91,0x00,0x07,0x10, 0x07,0x02,0x09,0x03,0x07,0x03,0x0a,0x91,0x09,0x10,0x91,0x09,0x03,0x1c,0x0d,0x18,0x01,0x0d,0x04,0x18,0x14,0x1e,0x2a,0x22,0x91,0x40,0x16,0x1a,0x13,0x2e,0x26,0x1e,0x03,0x03,0x10,0x10,0x40,0x09,0x14,0x48,0x10,0x02,0x13,0x0a,0x18,0x27,0x26,0x0a,0x0a,0x1d,0x2f,0x7e,0x13,0x2e,0x0e,0x27,0x1e,0x26,0x42,0x27,0x7e,0x26,0x26,0x31, 0x1e,0x7e,0x1d,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf2,0x32,0xe1,0x11,0x39,0x18,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x39,0x2b,0x11,0x33,0x00,0x3f,0x33,0x33,0x3f,0x33,0x1a,0xed,0x32,0x12,0x39,0x39,0x5f,0x5e,0x5d,0x3f,0x33,0xed,0x10,0xed,0x10,0xdc,0x5f,0x5e,0x5d,0xed,0x31,0x30,0x01,0x5d,0x01,0x10,0x00,0x21,0x22, 0x27,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x37,0x23,0x06,0x23,0x22,0x27,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x06,0x66,0xfe,0xc1,0xfe,0xa4,0x47,0x7a,0x7a,0x30,0x68,0x56,0x56,0x70,0x38,0x72,0x71,0x50,0xf7,0xe5,0x0f, 0x06,0x6d,0xca,0xd7,0x48,0x72,0xe4,0xfe,0xac,0xa8,0x67,0x7d,0x67,0x91,0xa8,0xe2,0x6c,0x8c,0xa8,0x01,0x29,0xfe,0x62,0xfe,0x93,0x0c,0x0b,0x17,0x96,0x19,0x0b,0x0c,0xe8,0xfc,0xb2,0xd4,0xd4,0x01,0xc4,0x03,0xee,0xfc,0x26,0xa5,0x9c,0xbf,0x86,0x03,0xd6,0xfc,0x12,0xfe,0xd3,0xb5,0x90,0x03,0xd6,0x00,0x00,0x01,0x00,0xa6,0xfe,0x1c, 0x06,0x54,0x04,0x00,0x00,0x30,0x00,0x7d,0x40,0x49,0x0c,0x95,0x04,0x07,0x14,0x07,0x02,0x07,0x03,0x0a,0x95,0x09,0x10,0x95,0x09,0x42,0x03,0x1c,0x19,0x13,0x1b,0x2f,0x27,0x1f,0x0f,0x2b,0x23,0x95,0x40,0x16,0x1b,0x16,0x03,0x10,0x2d,0x10,0x01,0x02,0x0f,0x10,0x1f,0x10,0x02,0x09,0x03,0x10,0x40,0x0c,0x15,0x48,0x10,0x13,0x0a,0x0a, 0x1e,0x30,0x84,0x13,0x2f,0x0e,0x28,0x1f,0x27,0x42,0x19,0x28,0x84,0x27,0x27,0x32,0x1f,0x84,0x1e,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x39,0x2b,0x01,0x10,0xf2,0x32,0xe1,0x11,0x39,0x18,0x2f,0x12,0x39,0x2b,0x5f,0x5e,0x5d,0x5f,0x5d,0x11,0x33,0x00,0x3f,0x33,0x1a,0xed,0x32,0x3f,0x33,0x33,0x12,0x39,0x39,0x3f,0xe6,0xed,0x10,0xed,0x10, 0xdc,0x5d,0xed,0x31,0x30,0x01,0x10,0x00,0x21,0x22,0x27,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x13,0x23,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x06,0x54,0xfe,0xc9,0xfe,0xa5,0x46,0x6f,0x6f,0x34, 0x70,0x4a,0x56,0x6c,0x33,0x6c,0x6b,0x51,0xef,0xe8,0x0c,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0xfe,0xae,0xa4,0x69,0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0x01,0x5c,0xfe,0x3d,0xfe,0x85,0x0c,0x0b,0x19,0x8e,0x16,0x0b,0x0b,0xf5,0x01,0x03,0xba,0x75,0x5f,0xd4,0x01,0xa1,0x02,0x77,0xfd,0xb4,0xaa,0x98,0xc0,0x86,0x02,0x48,0xfd, 0xa0,0xfe,0xd2,0xb5,0x91,0x02,0x48,0x00,0x00,0x01,0x00,0x33,0x00,0x00,0x04,0x2f,0x05,0xb2,0x00,0x18,0x00,0x42,0x40,0x23,0x0b,0x09,0x1b,0x09,0x02,0x02,0x16,0x16,0x14,0x91,0x04,0x04,0x17,0x01,0x0d,0x0f,0x91,0x0a,0x04,0x17,0x03,0x01,0x0d,0x0d,0x16,0x11,0x00,0x7e,0x16,0x01,0x01,0x1a,0x11,0x7e,0x07,0x2f,0xe1,0x12,0x39,0x2f, 0x33,0xe1,0x11,0x12,0x39,0x2f,0x00,0x2f,0x3f,0x3f,0xed,0x32,0x11,0x12,0x39,0x2f,0xed,0x32,0x12,0x39,0x31,0x30,0x01,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x00,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x14,0x16,0x33,0x32,0x37,0x11,0x33,0x04,0x2f,0xa8,0xbc,0xc3,0xd5,0xff,0x00,0xb4,0x98,0x40,0x3f,0x3d,0x3a,0xac, 0xa9,0x94,0xb2,0xbd,0xa8,0x02,0x7b,0x73,0x01,0x06,0xd8,0xcf,0xfd,0x18,0x96,0x1a,0xfe,0xce,0x98,0xb4,0x70,0x02,0x8a,0x00,0x00,0x01,0x00,0x33,0xfe,0x29,0x03,0x85,0x04,0x18,0x00,0x18,0x00,0x42,0x40,0x26,0x0a,0x08,0x1a,0x08,0x02,0x0a,0x06,0x1a,0x06,0x02,0x01,0x1b,0x03,0x05,0x17,0x0c,0x0e,0x95,0x09,0x10,0x17,0x0f,0x13,0x95, 0x05,0x16,0x0c,0x0c,0x10,0x18,0x84,0x01,0x17,0x17,0x1a,0x10,0x84,0x07,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x32,0x11,0x12,0x39,0x3f,0x31,0x30,0x01,0x5d,0x5d,0x01,0x23,0x11,0x23,0x06,0x23,0x20,0x11,0x10,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11, 0x33,0x03,0x85,0xa3,0x05,0x71,0xd4,0xfe,0x9b,0x01,0x48,0x3a,0x35,0x34,0x35,0xaa,0x71,0x7c,0x7a,0xa4,0xa3,0xfe,0x29,0x02,0x73,0xb4,0x02,0x18,0x02,0x18,0x14,0x8d,0x17,0xfe,0x7a,0xd4,0xc2,0xbc,0x8e,0x02,0x44,0x00,0x00,0x01,0x00,0x00,0xfe,0x1e,0x04,0xb8,0x05,0x9a,0x00,0x22,0x00,0x5e,0x40,0x37,0x2b,0x10,0x3b,0x10,0x02,0x44, 0x01,0x01,0x0b,0x91,0x00,0x06,0x10,0x06,0x02,0x06,0x02,0x09,0x91,0x08,0x0f,0x91,0x08,0x02,0x1c,0x1d,0x18,0x18,0x16,0x91,0x1f,0x1f,0x19,0x1c,0x03,0x19,0x02,0x0f,0x0f,0x40,0x09,0x12,0x48,0x0f,0x09,0x22,0x7e,0x13,0x13,0x24,0x1d,0x18,0x7e,0x1a,0x09,0x2f,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2b,0x11,0x33,0x00,0x2f, 0x3f,0x12,0x39,0x2f,0xed,0x32,0x12,0x39,0x3f,0x33,0xed,0x10,0xed,0x10,0xdc,0x5d,0xed,0x31,0x30,0x01,0x5d,0x5d,0x25,0x10,0x21,0x22,0x27,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x12,0x11,0x35,0x34,0x26,0x23,0x22,0x07,0x11,0x23,0x11,0x33,0x11,0x36,0x33,0x32,0x12,0x15,0x04,0xb8,0xfd,0x71,0x45,0x77,0x77, 0x38,0x68,0x56,0x56,0x70,0x36,0x73,0x72,0x50,0xf7,0xe8,0xaa,0x97,0xbf,0xac,0xa8,0xa8,0xb9,0xcd,0xd3,0xfb,0xec,0xfd,0x32,0x0c,0x0b,0x17,0x96,0x19,0x0b,0x0c,0x01,0x13,0x01,0x21,0xc8,0xb0,0xcf,0x71,0xfd,0x40,0x05,0x9a,0xfd,0xb6,0x78,0xfe,0xec,0xe5,0x00,0x00,0x02,0xff,0xec,0xff,0xe8,0x03,0xe8,0x04,0x18,0x00,0x26,0x00,0x2f, 0x00,0xc5,0x40,0x59,0x1c,0x1d,0x16,0x1b,0x0d,0x0e,0x1a,0x0e,0x27,0x0c,0x28,0x18,0x17,0x1d,0x16,0x2f,0x19,0x2f,0x1c,0x17,0x1d,0x16,0x1d,0x27,0x0d,0x0c,0x28,0x0c,0x1d,0x21,0x15,0x0c,0x08,0x29,0x0e,0x0f,0x95,0x2e,0x2f,0x2e,0x25,0xec,0x04,0x00,0x04,0x10,0x04,0x02,0x2e,0x04,0x2e,0x04,0x08,0x28,0x29,0x95,0x16,0x19,0x1a,0x03, 0x15,0x10,0x08,0xec,0x21,0x16,0x00,0x1d,0x16,0x1e,0x12,0x28,0x0c,0x0b,0x2c,0x0d,0x0e,0x1b,0x1c,0x04,0x1a,0x12,0x17,0x18,0x27,0x2f,0x04,0x2c,0x1a,0xb8,0x01,0x2e,0xb3,0x19,0x19,0x0b,0x2c,0xb8,0x01,0x2e,0x40,0x0b,0x12,0x12,0x01,0x1e,0x84,0x0b,0x0b,0x31,0x00,0x84,0x01,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12, 0x39,0x2f,0xe1,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x2f,0x3f,0xed,0x3f,0x17,0x33,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0x87,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x10,0x87,0x08,0xc0,0x04,0xc0,0x08,0xc0,0x10,0x87, 0xc0,0x04,0xc0,0x08,0xc0,0x31,0x30,0x33,0x23,0x36,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x37,0x33,0x06,0x07,0x16,0x15,0x14,0x02,0x23,0x22,0x27,0x26,0x23,0x22,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x32,0x8c,0xa0,0x13,0x85,0x68,0x65,0x6f,0x62,0x38, 0x5e,0x8c,0x38,0xa6,0xbe,0x78,0xa2,0xb9,0x96,0xa6,0x8b,0x1d,0x15,0x9b,0x27,0x42,0x76,0xec,0xa6,0x82,0x70,0x56,0x22,0x48,0x02,0x14,0x62,0x7d,0x52,0x5e,0x87,0x8c,0x8f,0xa4,0x64,0x58,0xdc,0x9d,0x78,0x63,0xa8,0x83,0x68,0x71,0x99,0x6c,0x32,0x3a,0x6f,0x61,0x98,0xc0,0xd6,0xfe,0xce,0x6a,0x52,0x02,0x91,0x59,0x43,0x35,0x68,0x00, 0x00,0x01,0x00,0x48,0xff,0xe8,0x04,0xae,0x05,0xb2,0x00,0x29,0x00,0x52,0x40,0x2e,0x03,0x28,0x13,0x28,0x02,0x0c,0x1c,0x06,0x23,0x04,0x03,0x29,0x29,0x19,0x26,0x13,0x13,0x03,0x0f,0x91,0x19,0x04,0x26,0x91,0x03,0x13,0x13,0x11,0x7e,0x16,0x1c,0x7d,0x0c,0x16,0x0c,0x16,0x0c,0x06,0x00,0x7e,0x29,0x29,0x2b,0x23,0x7d,0x06,0x2f,0xe1, 0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x32,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x11,0x12,0x39,0x2f,0x11,0x17,0x39,0x31,0x30,0x5d,0x01,0x06,0x00,0x21,0x22,0x24,0x35,0x34,0x36,0x36,0x25,0x36,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x32,0x00,0x15,0x14,0x06,0x06, 0x07,0x05,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x04,0xae,0x17,0xfe,0xb7,0xfe,0xf4,0xe9,0xfe,0xef,0x68,0xb4,0x01,0x4e,0xda,0xd0,0x78,0x9c,0x14,0xa4,0x16,0xa7,0x93,0xbf,0x01,0x41,0x3a,0x72,0x33,0xfe,0x73,0xd8,0xb4,0xa0,0xc0,0xf2,0x0c,0x02,0x0a,0xfe,0xfe,0xdc,0xfd,0xbb,0x78,0xaf,0x5c,0x4d,0x30,0x68,0x6a,0xa8,0x6c,0x25, 0x2f,0x30,0x32,0x69,0x8d,0xff,0x00,0xaa,0x46,0x6c,0x4d,0x0c,0x61,0x46,0xb4,0x80,0xa3,0xd3,0xb8,0x00,0x00,0x01,0x00,0x3e,0xff,0xe8,0x03,0x90,0x04,0x18,0x00,0x27,0x00,0x6e,0x40,0x29,0x05,0x09,0x15,0x09,0x02,0x0b,0x09,0x24,0x1f,0x1e,0x03,0x20,0x27,0x30,0x27,0x02,0x27,0x27,0x19,0x24,0x13,0x40,0x09,0x0c,0x48,0x13,0x13,0x03, 0x0f,0x95,0x19,0x10,0x24,0x95,0x03,0x16,0x1c,0x84,0x0c,0x13,0x11,0xb8,0x01,0x2e,0x40,0x0d,0x10,0x16,0x20,0x16,0x30,0x16,0x03,0x16,0x0c,0x16,0x0c,0x06,0x00,0xb8,0x01,0x2e,0xb5,0x27,0x27,0x29,0x21,0x84,0x06,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xe1,0x32,0x10,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39, 0x2f,0x2b,0x11,0x12,0x39,0x2f,0x5d,0x11,0x39,0x39,0x11,0x39,0x39,0x5d,0x31,0x30,0x01,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x32,0x04,0x15,0x14,0x06,0x04,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x03,0x90,0x0a,0xf6,0xd2,0xad,0xd3,0x4a, 0x85,0xe1,0x97,0xa2,0x51,0x5d,0x21,0x98,0x1e,0x7c,0x6b,0x9d,0x01,0x05,0x6b,0xfe,0xa0,0x7c,0x7c,0x68,0x8c,0xa8,0x04,0x01,0xa0,0xd0,0xe8,0xb0,0x89,0x56,0x7e,0x47,0x34,0x23,0x44,0x41,0x78,0x46,0x29,0x31,0x31,0x37,0x53,0x6d,0xca,0x75,0x52,0x76,0x47,0x58,0x4b,0x50,0x65,0x9f,0x8f,0x00,0x00,0x02,0x00,0x14,0x00,0x00,0x04,0xb0, 0x05,0xb2,0x00,0x1c,0x00,0x1f,0x00,0xce,0x40,0x7a,0x1d,0x1e,0x8d,0x1e,0xbd,0x1e,0x03,0x74,0x0f,0xe4,0x0f,0x02,0x1e,0x1b,0x1f,0x19,0x0f,0x02,0x10,0x1c,0x0e,0x1c,0x1e,0x1f,0x19,0x04,0x03,0x02,0x10,0x1d,0x05,0x1d,0x0f,0x03,0x02,0x10,0x02,0x1e,0x1b,0x1a,0x1f,0x19,0x1f,0x10,0x42,0x0e,0x72,0x0e,0x82,0x0e,0x02,0x16,0x0e,0x46, 0x0e,0x56,0x0e,0x03,0x0e,0x1c,0x0c,0x19,0x42,0x05,0x76,0x05,0x01,0x05,0x04,0x1a,0x03,0x1b,0x1e,0x1d,0x07,0x1f,0x17,0x09,0x15,0x03,0x07,0x91,0x12,0x0c,0x04,0x1c,0x02,0x76,0x02,0x01,0x0f,0x02,0x1f,0x02,0x02,0x02,0x1f,0x91,0x01,0x10,0x19,0x19,0x1f,0x1f,0x02,0x15,0x0e,0x05,0x05,0x1d,0x1d,0x1c,0x09,0x15,0x09,0x15,0x09,0x02, 0x1c,0x1c,0x21,0x02,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x12,0x39,0x11,0x33,0x11,0x12,0x39,0x12,0x39,0x11,0x33,0x00,0x2f,0xed,0x39,0x5d,0x5d,0x11,0x33,0x3f,0x33,0xed,0x17,0x32,0x11,0x17,0x39,0x5d,0x10,0xe4,0x11,0x12,0x39,0x5d,0x5d,0x10,0xe6,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0x0e,0xc0, 0x10,0x87,0x08,0xc0,0x05,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x01,0x3d,0x2f,0x31,0x30,0x00,0x5d,0x5d,0x21,0x21,0x35,0x01,0x27,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x07,0x01,0x27,0x01,0x01,0x04,0xb0,0xfb,0x64,0x01,0xf4,0x37,0x3b,0x46,0x2d, 0x2c,0x2c,0x2b,0x37,0x5a,0x8a,0x51,0x52,0x8b,0x59,0x36,0x2c,0x2c,0x2c,0x2c,0x4a,0x3c,0x36,0x01,0xf6,0xee,0xfe,0x9e,0xfe,0x9e,0x31,0x03,0xc1,0x6a,0x72,0x4c,0x14,0x98,0x14,0x76,0x9c,0x9e,0x74,0x14,0x98,0x14,0x49,0x75,0x66,0xfc,0x3b,0x67,0x02,0xb4,0xfd,0x4c,0x00,0x00,0x02,0x00,0x14,0x00,0x00,0x03,0xcd,0x04,0x18,0x00,0x1a, 0x00,0x1d,0x00,0x76,0x40,0x47,0x03,0x0e,0x33,0x0e,0x43,0x0e,0xd3,0x0e,0x04,0x0e,0x0b,0x19,0x03,0xcb,0x1c,0xdb,0x1c,0x02,0x8f,0x1c,0x01,0x14,0x1c,0x01,0x1c,0x03,0x1d,0x08,0x14,0x16,0x03,0x06,0x95,0x11,0x0b,0x10,0x1a,0x02,0x0b,0x02,0x2b,0x02,0x02,0x02,0x1d,0x95,0x01,0x19,0x03,0x1a,0x1d,0x14,0x02,0x1b,0x1a,0x08,0x0f,0x14, 0x01,0x00,0x08,0x01,0x14,0x08,0x14,0x08,0x02,0x1a,0x1a,0x1f,0x02,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x11,0x12,0x39,0x11,0x12,0x39,0x12,0x39,0x39,0x00,0x2f,0xed,0x39,0x5d,0x11,0x33,0x3f,0x33,0xed,0x17,0x32,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x11,0x33,0x12,0x39,0x5d,0x31,0x30,0x21,0x21,0x35,0x01,0x27,0x26, 0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x07,0x01,0x27,0x03,0x03,0x03,0xcd,0xfc,0x47,0x01,0x88,0x25,0x3b,0x40,0x21,0x21,0x20,0x2c,0x50,0x66,0x34,0x35,0x67,0x4f,0x2b,0x21,0x21,0x20,0x46,0x3c,0x22,0x01,0x8b,0xe3,0xfc,0xfc,0x23,0x02,0xba,0x44,0x6d,0x0f,0x8b,0x0e,0x48, 0x5e,0x5f,0x47,0x0e,0x8b,0x0f,0x6d,0x3f,0xfd,0x41,0x69,0x01,0xc6,0xfe,0x3a,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x04,0xee,0x06,0x04,0x00,0x1e,0x00,0x2a,0x00,0x74,0x40,0x34,0x33,0x18,0x43,0x18,0x53,0x18,0x03,0x0c,0x09,0x1c,0x09,0x2c,0x09,0x03,0x99,0x05,0x01,0x0b,0x13,0x1f,0x91,0x0d,0x0d,0x19,0x25,0x03,0x91,0x0f,0x1d,0x1f, 0x1d,0x2f,0x1d,0x03,0x1d,0x19,0x01,0x91,0x00,0x07,0x91,0x00,0x42,0x19,0x01,0x25,0x91,0x13,0x13,0x1b,0x05,0x05,0xb8,0xff,0xc0,0x40,0x0e,0x0c,0x12,0x48,0x01,0x05,0x01,0x0a,0x10,0x7d,0x28,0x28,0x2c,0x0a,0x22,0xb9,0x01,0x2f,0x00,0x16,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x2f,0x2b,0x11,0x33,0x00,0x3f,0xed,0x3f, 0xe6,0xed,0x10,0xed,0x10,0xdc,0x5d,0xed,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x01,0x15,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x06,0x03,0x33,0x36,0x21,0x32,0x00,0x15,0x14,0x00,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x16,0x33,0x32,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x04, 0xc2,0x50,0x68,0x33,0x6a,0x6b,0x4a,0xc2,0xc7,0x15,0x09,0xa3,0x01,0x07,0xf6,0x01,0x2b,0xfe,0xb9,0xff,0xfe,0xe6,0xfe,0xd0,0x01,0x23,0x01,0x3d,0x44,0x6e,0x6d,0x35,0x60,0xfe,0x3e,0xb4,0xe2,0xd7,0xb9,0xb7,0xdd,0xd7,0x06,0x04,0x96,0x18,0x0a,0x0a,0xe7,0xfe,0xef,0xc8,0xfe,0xce,0xf0,0xf2,0xfe,0xc2,0x01,0x58,0x01,0x45,0x01,0xda, 0x01,0xa3,0x0a,0x0a,0xfd,0xb4,0xd8,0xa5,0xbe,0xe8,0xe0,0xb1,0xb2,0xe0,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x50,0x06,0x06,0x00,0x1e,0x00,0x2c,0x00,0x75,0x40,0x2f,0x6b,0x1e,0x7b,0x1e,0x02,0x0c,0x09,0x1c,0x09,0x2c,0x09,0x8c,0x09,0x04,0x0b,0x1f,0x1f,0x2a,0x95,0x0d,0x0d,0x19,0x24,0x03,0x95,0x1d,0x40,0x09,0x0e,0x48,0x1d,0x19, 0x01,0x95,0x00,0x42,0x07,0x95,0x19,0x01,0x24,0x95,0x13,0x16,0x1b,0x05,0x05,0xb8,0xff,0xc0,0x40,0x18,0x0f,0x24,0x48,0x0a,0x05,0x21,0x6f,0x01,0x7f,0x01,0x8f,0x01,0x03,0x01,0x01,0x16,0x10,0x83,0x27,0x27,0x2e,0x21,0x83,0x16,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x5d,0x12,0x39,0x39,0x2b,0x11,0x33,0x00,0x3f,0xed,0x3f, 0xed,0xf6,0xed,0x10,0xdc,0x2b,0xed,0x11,0x12,0x39,0x2f,0xed,0x32,0x12,0x39,0x31,0x30,0x5d,0x5d,0x01,0x15,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x02,0x03,0x33,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x16,0x33,0x32,0x01,0x06,0x15,0x14,0x12,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06, 0x03,0xdb,0x38,0x4f,0x18,0x39,0x3a,0x2f,0xac,0xc6,0x1a,0x04,0x81,0xe1,0xdc,0x01,0x00,0xfe,0xe8,0xea,0xed,0xfe,0xff,0x01,0x21,0x01,0x21,0x20,0x45,0x45,0x1e,0x44,0xfd,0x5e,0x04,0xb1,0x9f,0xa0,0xb0,0xb3,0xa3,0x63,0xb3,0x06,0x06,0x8b,0x11,0x04,0x04,0xfe,0xfc,0xfe,0xfc,0xae,0xfe,0xe4,0xf8,0xf4,0xfe,0xd8,0x01,0x57,0x01,0x40, 0x01,0xc1,0x01,0xc2,0x04,0x04,0xfc,0xcc,0x41,0x35,0xd8,0xfe,0xfa,0xcf,0xbd,0xc3,0xcd,0x71,0x00,0x01,0x00,0x0a,0x00,0x00,0x04,0x7b,0x05,0x9a,0x00,0x13,0x00,0x36,0x40,0x17,0x09,0x01,0x04,0x91,0x12,0x0f,0x0f,0x03,0x10,0x03,0x03,0x12,0x01,0x7e,0x0f,0x04,0x04,0x0c,0x00,0x00,0x15,0x09,0x07,0xb9,0x01,0x2e,0x00,0x0c,0x2f,0xe1, 0x32,0x12,0x39,0x2f,0x12,0x39,0x2f,0x33,0xe1,0x32,0x00,0x2f,0x3f,0x12,0x39,0x2f,0x33,0xfd,0x32,0xc6,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x22,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x21,0x33,0x11,0x33,0x11,0x21,0x04,0x7b,0xfe,0x33,0xa8,0xff,0x00,0x68,0x08,0x8e,0x0e,0x01,0x00,0xfc,0xa8,0x01,0xcd,0x04,0x00,0xfc,0x00,0x04, 0x00,0x5a,0x28,0x1e,0x32,0x34,0xd2,0x01,0x02,0xfe,0xfe,0x00,0x00,0x01,0x00,0x00,0xfe,0x96,0x03,0x4e,0x05,0x2f,0x00,0x18,0x00,0x3a,0x40,0x1d,0x05,0xec,0x40,0x04,0x19,0x80,0x0e,0x09,0x16,0x01,0x09,0x95,0x17,0x14,0x0f,0x05,0x17,0x01,0x84,0x14,0x09,0x09,0x11,0x00,0x1a,0x0e,0x0c,0xed,0x11,0x2f,0xe1,0x32,0x10,0xc6,0x11,0x39, 0x2f,0x33,0xe1,0x32,0xc6,0x00,0x3f,0x33,0xed,0x32,0xcd,0x10,0xc6,0x1a,0x10,0xde,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x10,0x05,0x35,0x36,0x36,0x35,0x11,0x23,0x22,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x33,0x33,0x35,0x37,0x11,0x21,0x03,0x4e,0xfe,0xc0,0xfe,0xa0,0x68,0x54,0x7a,0x60,0x06,0x8c,0x0a,0xf0,0x7a,0xa4,0x01,0x40,0x03, 0x74,0xfc,0xd6,0xfe,0x90,0x44,0x9f,0x16,0x7e,0x7f,0x03,0x2c,0x53,0x21,0x1e,0x30,0x2e,0xc0,0xfa,0x35,0xfe,0xd1,0x00,0x01,0x00,0x00,0xff,0xe8,0x04,0x90,0x04,0x18,0x00,0x29,0x00,0x65,0x40,0x35,0x1d,0x0b,0x07,0x1f,0x1f,0x0b,0x0e,0x21,0x0f,0x15,0x13,0x95,0x18,0x10,0x29,0x27,0x95,0x40,0x02,0x16,0x0e,0x1f,0x07,0x21,0x05,0x1d, 0x0b,0x1b,0x0d,0x21,0x83,0x22,0x22,0x29,0x24,0x84,0x05,0x0e,0x29,0x15,0x1b,0x42,0x0d,0x83,0x0e,0x0e,0x15,0x1b,0x84,0x10,0x10,0x2b,0x15,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x18,0x2f,0xf0,0xe1,0x11,0x39,0x2f,0xe1,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x2f,0x3f,0x1a,0xed,0x32,0x3f,0xed,0x32,0x3f, 0x12,0x39,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x05,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x06,0x07,0x06,0x07,0x06,0x07,0x23,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x00,0x37,0x36,0x37,0x33,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x04,0x90,0x33,0x3f,0x88,0x9c,0x14,0x06,0xf1,0x94,0x56,0x14,0x27, 0xac,0xb0,0x56,0x50,0x2a,0x26,0x32,0x3e,0x8a,0x9c,0x15,0x01,0x8d,0x54,0x14,0x28,0xac,0xb0,0x57,0x4f,0x2a,0x26,0x02,0x16,0xde,0xbf,0x69,0x6a,0x06,0xdb,0x87,0x62,0x35,0x59,0x01,0x72,0xf4,0x89,0x9f,0x15,0x89,0x16,0xde,0xbf,0x69,0x6a,0x01,0x65,0x65,0x35,0x59,0xfe,0x8e,0xf4,0x8c,0x9c,0x15,0x00,0x00,0x02,0x00,0xa2,0xfe,0x1e, 0x04,0x50,0x04,0x18,0x00,0x19,0x00,0x25,0x00,0x39,0x40,0x20,0x05,0x03,0x15,0x03,0x02,0x22,0x95,0x12,0x10,0x00,0x1a,0x1a,0x1d,0x95,0x18,0x16,0x07,0x95,0x08,0x1c,0x07,0x07,0x0f,0x15,0x83,0x1f,0x1f,0x27,0x01,0x25,0x84,0x0f,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x3f,0xed, 0x31,0x30,0x5d,0x25,0x23,0x1e,0x02,0x17,0x16,0x17,0x15,0x26,0x27,0x26,0x24,0x02,0x11,0x11,0x34,0x12,0x33,0x32,0x00,0x15,0x10,0x02,0x23,0x22,0x03,0x16,0x16,0x33,0x20,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x48,0x04,0x09,0x76,0xd1,0xc7,0x78,0x43,0x40,0x7f,0xf2,0xfe,0xee,0xb1,0xf4,0xe1,0xd9,0x01,0x00,0xf8,0xdd,0xc1,0x76, 0x26,0xa5,0x59,0x01,0x3e,0xa7,0x8f,0x90,0x9c,0x62,0x92,0xc0,0x56,0x04,0x02,0x08,0x8e,0x08,0x02,0x04,0x66,0x01,0x24,0x01,0x54,0x01,0x04,0xf4,0x01,0x16,0xfe,0xde,0xe6,0xfe,0xfc,0xfe,0xdc,0x01,0x1a,0x3d,0x53,0x01,0x96,0xb0,0xd6,0xcf,0xb3,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x02,0x06,0x00,0x46,0x00,0x00, 0xff,0xff,0xff,0x3a,0xfe,0x1e,0x01,0x66,0x05,0xd9,0x02,0x06,0x00,0x4d,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x02,0x06,0x02,0xcf,0x00,0x00,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0x5c,0x04,0x00,0x00,0x12,0x00,0x39,0x40,0x1e,0x0e,0x95,0x40,0x0d,0x08,0x00,0x0d,0x95,0x2b,0x30,0x09,0x95,0x08,0x0f,0x12,0x95, 0x00,0x0c,0x08,0x0d,0x08,0x0d,0x08,0x0f,0x00,0x00,0x14,0x0f,0x83,0x04,0x2f,0xe1,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x00,0x2f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x21,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x33,0x15,0x23,0x20,0x03,0x21,0x15,0x21,0x12,0x21,0x33,0x03,0x5c,0xe3,0xf9,0xfe,0xe0, 0x01,0x2d,0xff,0xc6,0xc9,0xfe,0xb6,0x33,0x02,0x1f,0xfd,0xdb,0x1b,0x01,0x68,0xd3,0x01,0x09,0xe3,0xf3,0x01,0x21,0x8c,0xfe,0xe0,0x8c,0xfe,0xc4,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0x5c,0x04,0x00,0x00,0x12,0x00,0x37,0x40,0x1d,0x05,0x95,0x40,0x06,0x0b,0x00,0x06,0x95,0x2b,0x30,0x0a,0x95,0x0b,0x0f,0x01,0x95,0x00,0x0f,0x83,0x04, 0x0a,0x05,0x0a,0x05,0x07,0x04,0x04,0x14,0x00,0x2f,0x11,0x39,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x00,0x2f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x33,0x35,0x33,0x20,0x13,0x21,0x35,0x21,0x02,0x21,0x23,0x35,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x60,0xd3,0x01,0x5d,0x24,0xfd,0xde,0x02,0x22,0x2a,0xfe,0xa9, 0xc9,0xda,0xf8,0x01,0x20,0xfe,0xd4,0xff,0x8c,0x01,0x3c,0x8c,0x01,0x20,0x8c,0xfe,0xf7,0xe3,0xf4,0xfe,0xe0,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x06,0xca,0x05,0x9a,0x00,0x33,0x00,0x2b,0x40,0x15,0x32,0x10,0x15,0x25,0x7e,0x24,0x16,0x7e,0x15,0x15,0x07,0x24,0x24,0x35,0x08,0x7e,0x07,0x07,0x03,0x00,0x12,0x00,0x3f,0x3f,0x01,0x2f, 0xed,0x11,0x33,0x2f,0x12,0x39,0x2f,0xed,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x21,0x2e,0x05,0x27,0x33,0x1e,0x05,0x17,0x13,0x2e,0x03,0x27,0x33,0x1e,0x05,0x17,0x3e,0x05,0x37,0x33,0x0e,0x05,0x07,0x23,0x2e,0x03,0x27,0x03,0x01,0xe2,0x4d,0x75,0x5a,0x40,0x32,0x25,0x11,0xa8,0x10,0x26,0x2e,0x38,0x46,0x57,0x35,0xe0,0x15,0x21,0x1c, 0x18,0x0c,0xa8,0x10,0x26,0x2e,0x38,0x46,0x57,0x35,0x35,0x57,0x46,0x38,0x2e,0x25,0x11,0xa8,0x11,0x25,0x32,0x40,0x5a,0x75,0x4d,0xa4,0x2b,0x4a,0x40,0x37,0x17,0xd5,0x95,0xf8,0xdd,0xd0,0xdc,0xf3,0x91,0x8a,0xe5,0xc7,0xb5,0xb5,0xbd,0x6d,0x02,0x3c,0x48,0x94,0x9f,0xb0,0x63,0x8a,0xe5,0xc7,0xb5,0xb5,0xbd,0x6d,0x6d,0xbd,0xb5,0xb5, 0xc7,0xe5,0x8a,0x92,0xf2,0xdc,0xd0,0xde,0xf7,0x95,0x53,0x95,0x89,0x7f,0x3c,0xfd,0xd4,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x05,0x5e,0x04,0x00,0x00,0x14,0x00,0x4c,0x40,0x25,0x0d,0x03,0x02,0x0f,0x14,0x08,0x03,0x0d,0x02,0x0f,0x0f,0x02,0x0c,0x13,0x03,0x04,0x02,0x01,0x13,0x05,0x04,0x0c,0x13,0x0c,0x00,0x08,0x10,0x0f,0x0f,0x14, 0x08,0x14,0x00,0x00,0x16,0x09,0x08,0x2f,0x33,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x39,0x11,0x33,0x33,0x11,0x33,0x33,0x00,0x2f,0x17,0x33,0x3f,0x12,0x39,0x39,0x33,0x33,0x87,0x05,0xc0,0xc0,0x31,0x30,0x01,0x01,0x23,0x03,0x03,0x23,0x02,0x02,0x27,0x33,0x16,0x12,0x13,0x13,0x26,0x27,0x33,0x16,0x12,0x17, 0x01,0x05,0x5e,0xfe,0xaa,0xa6,0xb8,0xb6,0x94,0xb5,0x72,0x1b,0xa8,0x1a,0x58,0x7c,0xaa,0x47,0x1b,0xac,0x20,0x77,0x75,0x01,0x08,0x04,0x00,0xfc,0x00,0x01,0xaa,0xfe,0x56,0x01,0x9b,0x01,0x76,0xef,0xcf,0xfe,0xce,0xfe,0xce,0x01,0x87,0xcb,0xe1,0xe2,0xfe,0xad,0xfe,0x03,0x33,0x00,0x00,0x02,0x00,0x29,0x00,0x00,0x04,0xc6,0x05,0x9a, 0x00,0x12,0x00,0x1a,0x00,0x45,0x40,0x23,0x0a,0x01,0x91,0x07,0x04,0x04,0x05,0x13,0x91,0x0b,0x0b,0x05,0x03,0x14,0x91,0x00,0x02,0x00,0x09,0x09,0x14,0x0f,0x7d,0x18,0x18,0x1c,0x0b,0x07,0x14,0x7e,0x04,0x00,0x00,0x1c,0x1b,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x10,0xc6,0x00,0x2f,0xed,0x3f, 0x39,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x11,0x21,0x35,0x21,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x4c,0xfe,0xdd,0x01,0x23,0xa8,0x01,0x5a,0xfe,0xa6,0x01,0x10,0xd4,0xee,0xf8,0xd8,0xfe,0xfe,0xeb,0x96,0xa1,0xfe,0xc9,0x04,0x74, 0x9a,0x8c,0x8c,0x9a,0xfe,0xc6,0xcd,0xc1,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8d,0x7d,0x01,0x00,0x00,0x02,0x00,0x29,0x00,0x00,0x04,0x4e,0x05,0xec,0x00,0x12,0x00,0x19,0x00,0x47,0x40,0x24,0x0a,0x01,0x96,0x07,0x04,0x04,0x06,0x0b,0x95,0x13,0x13,0x00,0x06,0x00,0x14,0x95,0x00,0x02,0x00,0x09,0x09,0x14,0x0f,0x83,0x17,0x17,0x1b,0x0b, 0x07,0x14,0x84,0x04,0x00,0x00,0x1b,0x1a,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0x32,0x11,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x10,0xc6,0x00,0x2f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x11,0x21,0x35,0x21,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32, 0x35,0x34,0x23,0x01,0x40,0xfe,0xe9,0x01,0x17,0xa4,0x01,0x38,0xfe,0xc8,0x01,0x12,0x9d,0xbb,0xbb,0x8d,0xfe,0xde,0xf5,0xcd,0xcf,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfd,0xc5,0xa3,0x94,0x93,0xad,0x01,0xea,0xfe,0xa2,0xb4,0xaa,0x00,0x00,0x01,0x00,0xbc,0xff,0xe8,0x06,0xd9,0x05,0xb2,0x00,0x1f,0x00,0x5e,0x40,0x34,0x1a,0x17,0x06,0x91, 0x40,0x0b,0x0a,0x08,0x0b,0x91,0x2b,0x30,0x30,0x12,0x01,0x12,0x12,0x14,0x91,0x0f,0x04,0x0a,0x03,0x20,0x1f,0x01,0x1f,0x1f,0x1d,0x91,0x02,0x13,0x08,0x19,0x19,0x17,0x12,0x1a,0x7d,0x0c,0x12,0x05,0x05,0x08,0x12,0x00,0x00,0x21,0x0b,0x07,0x7e,0x08,0x2f,0xe1,0x32,0x11,0x39,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0xe1,0x11,0x39,0x39, 0x2f,0x00,0x2f,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0x3f,0xed,0x32,0x2f,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x33,0x32,0x31,0x30,0x25,0x06,0x23,0x20,0x00,0x03,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x12,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x07,0x21,0x15,0x21,0x16,0x00,0x33,0x32,0x37,0x06,0xd9,0x9f,0xea,0xfe,0xde,0xfe,0x95, 0x0f,0xfe,0xb0,0xa8,0xa8,0x01,0x52,0x1d,0x01,0x7e,0x01,0x1b,0xd6,0x97,0xa3,0xcc,0xd7,0xfe,0xeb,0x18,0x02,0x79,0xfd,0x85,0x10,0x01,0x11,0xd7,0xe0,0x9d,0x3c,0x54,0x01,0x69,0x01,0x2e,0xfd,0x81,0x05,0x9a,0xfd,0x7c,0x01,0x34,0x01,0x68,0x3b,0xb3,0x56,0xfe,0xed,0xf1,0x97,0xef,0xfe,0xed,0x60,0x00,0x00,0x01,0x00,0xa6,0xff,0xe8, 0x05,0x66,0x04,0x18,0x00,0x1f,0x00,0x68,0x40,0x3a,0x17,0x1a,0x06,0x95,0x40,0x0b,0x0a,0x08,0x0b,0x95,0x2b,0x30,0x0a,0x0f,0x40,0x12,0x50,0x12,0x02,0x12,0x12,0x14,0x95,0x0f,0x10,0x30,0x1f,0x01,0x1f,0x1f,0x1d,0x95,0x02,0x16,0x08,0x17,0x12,0x1a,0x83,0x05,0x0c,0x12,0x05,0x18,0x12,0x18,0x12,0x00,0x05,0x05,0x08,0x00,0x00,0x21, 0x0b,0x06,0x84,0x08,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xe1,0x11,0x39,0x00,0x2f,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x32,0x33,0x31,0x30,0x25,0x06,0x23,0x22,0x24,0x27,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x36,0x24,0x33, 0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x33,0x32,0x37,0x05,0x66,0x72,0xa0,0xd6,0xfe,0xf9,0x0f,0xfe,0xe2,0xa4,0xa4,0x01,0x20,0x18,0x01,0x0e,0xdc,0x89,0x67,0x64,0x92,0x93,0xb6,0x0d,0x01,0xb4,0xfe,0x4a,0x08,0xb2,0x94,0x92,0x78,0x2d,0x45,0xfb,0xdb,0xfe,0x42,0x04,0x00,0xfe,0x4a,0xdb,0xf3,0x32,0xa2, 0x4a,0xb0,0x94,0x8c,0x97,0xb5,0x5b,0x00,0x00,0x02,0x00,0x16,0x00,0x00,0x05,0x3c,0x05,0x9a,0x00,0x0b,0x00,0x14,0x00,0x66,0x40,0x37,0x0d,0x0c,0x02,0x0a,0x01,0x0a,0x0d,0x01,0x0a,0x13,0x12,0x07,0x08,0x0b,0x08,0x12,0x0b,0x08,0x02,0x03,0x06,0x07,0x0c,0x10,0x13,0x14,0x08,0x0b,0x0a,0x03,0x05,0x01,0x08,0x0a,0x0b,0x0f,0x10,0x14, 0x05,0x05,0x01,0x00,0x0e,0x04,0x08,0x09,0x09,0x05,0x42,0x04,0x7e,0x05,0x05,0x16,0x09,0x2f,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x01,0x33,0x10,0xe0,0x32,0x12,0x17,0x39,0x00,0x18,0x2f,0x33,0x33,0x3f,0x33,0x17,0x39,0x11,0x12,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x31,0x30,0x21,0x23, 0x03,0x07,0x11,0x23,0x11,0x27,0x01,0x23,0x01,0x33,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x17,0x05,0x3c,0xbb,0xfc,0x8f,0xa8,0x83,0xff,0x00,0xb5,0x02,0x3e,0xb6,0x3e,0x7d,0x12,0x0b,0x04,0x0a,0x17,0x7d,0x9c,0x02,0x8e,0xb7,0xfe,0x29,0x01,0xd3,0xb6,0xfd,0x77,0x05,0x9a,0xfd,0x91,0x01,0x45,0x2f,0x51,0x47,0x3b,0xfe,0xc3,0xd7, 0x00,0x02,0x00,0x0c,0x00,0x00,0x03,0xf2,0x04,0x00,0x00,0x0b,0x00,0x14,0x00,0x68,0x40,0x37,0x0d,0x0c,0x02,0x0a,0x01,0x0a,0x0d,0x01,0x0a,0x13,0x12,0x07,0x08,0x0b,0x08,0x12,0x0b,0x02,0x03,0x06,0x07,0x0c,0x13,0x06,0x14,0x14,0x08,0x0b,0x0a,0x0f,0x05,0x01,0x08,0x0a,0x0b,0x0f,0x10,0x14,0x05,0x05,0x01,0x00,0x0e,0x04,0x08,0x09, 0x09,0x05,0x42,0x04,0x8b,0x05,0x05,0x16,0x09,0x2f,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x01,0x33,0x10,0xe0,0x32,0x12,0x17,0x39,0x00,0x18,0x2f,0x33,0x33,0x3f,0x33,0x12,0x39,0x2f,0x17,0x33,0x11,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x31,0x30,0x21,0x23,0x03,0x07,0x11,0x23,0x11,0x27, 0x03,0x23,0x01,0x33,0x13,0x27,0x26,0x27,0x23,0x06,0x07,0x07,0x17,0x03,0xf2,0xb0,0x98,0x60,0x96,0x64,0x9c,0xa8,0x01,0xac,0xa2,0x18,0x4d,0x1b,0x08,0x04,0x0b,0x16,0x51,0x7a,0x01,0x8c,0x76,0xfe,0xea,0x01,0x16,0x78,0xfe,0x72,0x04,0x00,0xfe,0x1a,0xd2,0x4a,0x45,0x55,0x36,0xcd,0x8d,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x06,0xe6, 0x05,0x9a,0x00,0x13,0x00,0x1c,0x00,0xa1,0x40,0x59,0x15,0x14,0x02,0x12,0x01,0x12,0x15,0x01,0x12,0x1b,0x1a,0x07,0x08,0x13,0x08,0x1a,0x13,0x08,0x11,0x0a,0x09,0x12,0x09,0x02,0x03,0x06,0x07,0x14,0x1b,0x1c,0x07,0x0c,0x12,0x0a,0x91,0x40,0x11,0x0f,0x0c,0x11,0x91,0x2b,0x30,0x12,0x13,0x17,0x18,0x04,0x0f,0x03,0x01,0x05,0x08,0x09, 0x04,0x0c,0x13,0x17,0x12,0x18,0x17,0x18,0x1c,0x03,0x05,0x01,0x00,0x0e,0x04,0x08,0x09,0x09,0x05,0x42,0x04,0x7e,0x05,0x05,0x1e,0x0f,0x09,0x01,0x09,0x09,0x1e,0x10,0x0c,0x7e,0x0d,0x2f,0xe1,0x32,0x11,0x39,0x2f,0x5d,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x01,0x33,0x10,0xe0,0x32,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0x00,0x18,0x2f,0x17, 0x33,0x3f,0x17,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x12,0x17,0x39,0x10,0x87,0x05,0xc0,0xc0,0x11,0x12,0x00,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x31,0x30,0x21,0x23,0x03,0x07,0x11,0x23,0x11,0x27,0x01,0x23,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x13,0x33,0x13,0x03,0x26, 0x27,0x23,0x06,0x07,0x03,0x17,0x06,0xe6,0xbb,0xfc,0x8f,0xa8,0x84,0xff,0x00,0xb4,0x01,0x0d,0xfe,0x97,0xa8,0xa8,0x01,0xa4,0xf6,0xb6,0x3e,0x7e,0x10,0x0c,0x04,0x0a,0x17,0x7d,0x9c,0x02,0x8e,0xb7,0xfe,0x29,0x01,0xd3,0xb6,0xfd,0x77,0x02,0x9e,0xfd,0x62,0x05,0x9a,0xfd,0x9b,0x02,0x65,0xfd,0x91,0x01,0x45,0x2a,0x56,0x47,0x3b,0xfe, 0xc3,0xd7,0x00,0x02,0x00,0xa6,0x00,0x00,0x05,0x7b,0x04,0x00,0x00,0x13,0x00,0x1c,0x00,0xb0,0x40,0x50,0x11,0x0a,0x09,0x12,0x15,0x14,0x02,0x12,0x01,0x12,0x15,0x01,0x12,0x1b,0x1a,0x07,0x08,0x13,0x08,0x1a,0x13,0x08,0x02,0x03,0x06,0x07,0x14,0x1b,0x06,0x00,0x1c,0x01,0x13,0x03,0x1c,0x1c,0x0c,0x0f,0x0a,0x96,0x40,0x11,0x0f,0x0c, 0x11,0x96,0x2b,0x30,0x12,0x13,0x17,0x18,0x04,0x0f,0x0f,0x01,0x05,0x08,0x09,0x04,0x0c,0x13,0x17,0x12,0x18,0x17,0x18,0x1c,0x03,0x05,0x01,0x00,0x0e,0x04,0x08,0x09,0x09,0x05,0x42,0x04,0xb8,0x01,0x2e,0x40,0x11,0x05,0x05,0x1e,0x2f,0x09,0x3f,0x09,0x4f,0x09,0x03,0x09,0x09,0x1e,0x10,0x0c,0x84,0x0d,0x2f,0xe1,0x32,0x11,0x39,0x2f, 0x5d,0x12,0x39,0x2f,0xe1,0x2b,0x11,0x01,0x33,0x10,0xe0,0x32,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0x00,0x18,0x2f,0x17,0x33,0x3f,0x17,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x12,0x39,0x2f,0x5f,0x5e,0x5d,0x17,0x33,0x11,0x12,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0x87,0xc0,0xc0, 0x31,0x30,0x21,0x23,0x03,0x07,0x11,0x23,0x11,0x27,0x03,0x23,0x13,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x13,0x33,0x13,0x27,0x26,0x27,0x23,0x06,0x07,0x07,0x17,0x05,0x7b,0xb0,0x98,0x60,0x95,0x65,0x9b,0xa8,0xc2,0xfe,0xf2,0xa4,0xa4,0x01,0x46,0xb2,0xa2,0x18,0x4e,0x1b,0x07,0x05,0x0b,0x16,0x52,0x7c,0x01,0x8c,0x76,0xfe,0xea,0x01, 0x16,0x78,0xfe,0x72,0x01,0xd5,0xfe,0x2b,0x04,0x00,0xfe,0x58,0x01,0xa8,0xfe,0x1a,0xd2,0x49,0x46,0x55,0x36,0xcd,0x8d,0x00,0x00,0x02,0x00,0x29,0x00,0x00,0x05,0xaa,0x05,0x9a,0x00,0x12,0x00,0x1a,0x00,0xb3,0x40,0x30,0x10,0x03,0x0f,0x03,0x1a,0x19,0x06,0x13,0x06,0x1a,0x19,0x13,0x06,0x16,0x15,0x14,0x03,0x14,0x16,0x15,0x03,0x14, 0x0d,0x0e,0x06,0x0d,0x18,0x10,0x03,0x17,0x17,0x0e,0x03,0x06,0x06,0x09,0x13,0x14,0x91,0x40,0x0f,0x0e,0x03,0x05,0x01,0x09,0x13,0x0f,0xb8,0xff,0xd8,0x40,0x14,0x0b,0x01,0x4d,0x0f,0x0f,0x00,0x03,0x14,0x00,0x0e,0x10,0x0e,0x02,0x09,0x03,0x0e,0x0e,0x06,0x0a,0x00,0xb8,0x01,0x2f,0xb6,0x01,0x0e,0x03,0x09,0x06,0x42,0x09,0xb8,0x01, 0x2f,0x40,0x0b,0x0a,0x0a,0x1b,0x18,0x17,0x03,0x7e,0x06,0x06,0x1c,0x1b,0x11,0x12,0x39,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf2,0xe1,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0x11,0x12,0x39,0x2f,0x2b,0x33,0x00,0x2f,0x33,0x33,0x3f,0x33,0x1a,0xed,0x32,0x12,0x39,0x2f,0x33,0x12,0x39,0x11,0x17,0x33,0x87, 0x05,0xc0,0x11,0x12,0x00,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x11,0x12,0x00,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0x31,0x30,0x21,0x23,0x02,0x25,0x11,0x23,0x11,0x06,0x02,0x03,0x23,0x12,0x12,0x37,0x01,0x21,0x01,0x16,0x12,0x01,0x21,0x01,0x16,0x17,0x33,0x36,0x37,0x05,0xaa,0xc0,0x32,0xfe,0x8a,0xa8,0xcb,0xcb,0x1a, 0xc1,0x33,0xfd,0xe9,0xfe,0x62,0x04,0xa0,0xfe,0x52,0xea,0xf7,0xfe,0xb0,0xfd,0x9f,0x01,0x07,0x0d,0x16,0x02,0x10,0x16,0x02,0x0a,0x66,0xfd,0x90,0x02,0x72,0x39,0xfe,0xd3,0xfe,0xf4,0x01,0x50,0x01,0x67,0x45,0x02,0x9e,0xfd,0x60,0x48,0xfe,0x9a,0x03,0xb6,0xfe,0x52,0x22,0x36,0x35,0x23,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x04,0x66, 0x04,0x00,0x00,0x11,0x00,0x18,0x00,0x87,0x40,0x26,0x0f,0x0e,0x03,0x0e,0x0c,0x0d,0x06,0x0d,0x0f,0x42,0x0c,0x0c,0x08,0x16,0x16,0x0d,0x03,0x42,0x06,0x06,0x08,0x13,0x95,0x40,0x0e,0x0d,0x0f,0x05,0x01,0x08,0x12,0x13,0x0d,0x0e,0x0e,0x00,0x03,0x0d,0xb8,0xff,0xc0,0x40,0x16,0x0b,0x0f,0x48,0x0d,0x0d,0x06,0x09,0x00,0x83,0x01,0x0e, 0x03,0x08,0x06,0x42,0x08,0x83,0x09,0x09,0x19,0x16,0x03,0xb8,0x01,0x2e,0xb6,0x10,0x06,0x01,0x06,0x06,0x1a,0x19,0x11,0x12,0x39,0x2f,0x5d,0xe1,0x39,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xf2,0xe1,0x11,0x12,0x39,0x18,0x2f,0x2b,0x11,0x12,0x39,0x2f,0x12,0x39,0x39,0x00,0x2f,0x33,0x33,0x3f,0x32,0x1a,0xed,0x12,0x39,0x2f,0xe5,0x12, 0x39,0x11,0x12,0x39,0x10,0xe5,0x10,0x87,0x05,0xc0,0x10,0x87,0xc0,0x31,0x30,0x21,0x23,0x02,0x25,0x11,0x23,0x11,0x04,0x03,0x23,0x36,0x12,0x37,0x01,0x21,0x01,0x16,0x12,0x01,0x21,0x13,0x16,0x17,0x36,0x37,0x04,0x66,0xae,0x21,0xfe,0xfd,0x9c,0xfe,0xf8,0x23,0xaf,0x29,0xb9,0xae,0xfe,0xc2,0x03,0xb5,0xfe,0xb8,0xab,0xb7,0xfe,0xd7, 0xfe,0x6f,0xb5,0x04,0x0a,0x04,0x0c,0x01,0x64,0x4e,0xfe,0x4e,0x01,0xb4,0x4b,0xfe,0x97,0xf6,0x01,0x01,0x34,0x01,0xd5,0xfe,0x29,0x36,0xff,0x00,0x02,0x86,0xfe,0xdd,0x06,0x18,0x0a,0x14,0x00,0x02,0x00,0xbc,0x00,0x00,0x07,0x48,0x05,0x9a,0x00,0x18,0x00,0x1f,0x00,0xa9,0x40,0x3f,0x0c,0x0a,0x13,0x0a,0x16,0x03,0x15,0x03,0x13,0x14, 0x06,0x14,0x16,0x42,0x1c,0x1c,0x13,0x03,0x42,0x06,0x06,0x05,0x0c,0x91,0x40,0x13,0x11,0x0e,0x13,0x91,0x2b,0x30,0x1a,0x91,0x14,0x40,0x15,0x14,0x11,0x03,0x01,0x05,0x0a,0x03,0x0e,0x19,0x15,0x15,0x00,0x03,0x1a,0x00,0x14,0x10,0x14,0x02,0x0b,0x03,0x14,0x14,0x06,0x0a,0x00,0xb8,0x01,0x2f,0xb6,0x01,0x0e,0x03,0x09,0x06,0x42,0x09, 0xb8,0x01,0x2f,0x40,0x13,0x0f,0x0a,0x1f,0x0a,0x02,0x0a,0x0a,0x0e,0x1d,0x1c,0x03,0x7e,0x06,0x06,0x21,0x12,0x0e,0x7e,0x0f,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0x5d,0xe1,0x2b,0x01,0x10,0xf2,0xe1,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0x11,0x12,0x39,0x2f,0x33,0x00,0x2f,0x17,0x33,0x3f,0x33,0x33, 0x1a,0x10,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x39,0x2f,0xe5,0x12,0x39,0x10,0xe5,0x10,0x87,0x05,0xc0,0x10,0x87,0xc0,0x10,0x87,0xc0,0x31,0x30,0x21,0x23,0x02,0x25,0x11,0x23,0x11,0x06,0x02,0x03,0x23,0x12,0x25,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x01,0x21,0x01,0x16,0x12,0x01,0x21,0x01,0x17,0x33,0x36,0x37,0x07,0x48,0xc1, 0x2f,0xfe,0x87,0xa7,0xcb,0xcb,0x1b,0xc1,0x54,0x01,0x34,0xfe,0x16,0xa8,0xa8,0x02,0x54,0xfe,0x8a,0x04,0xa0,0xfe,0x51,0xea,0xf8,0xfe,0xaf,0xfd,0xa0,0x01,0x06,0x24,0x02,0x10,0x16,0x02,0x09,0x67,0xfd,0x90,0x02,0x72,0x39,0xfe,0xd3,0xfe,0xf4,0x02,0x0e,0x92,0xfd,0x60,0x05,0x9a,0xfd,0xa2,0x02,0x5e,0xfd,0x60,0x48,0xfe,0x9c,0x03, 0xb4,0xfe,0x52,0x58,0x35,0x23,0x00,0x02,0x00,0xa6,0x00,0x00,0x05,0xdf,0x04,0x00,0x00,0x17,0x00,0x1d,0x00,0xb8,0x40,0x4c,0x0b,0x09,0x12,0x09,0x15,0x03,0x14,0x03,0x12,0x13,0x06,0x15,0x05,0x1c,0x1c,0x13,0x03,0x42,0x06,0x06,0x05,0x0b,0x96,0x40,0x12,0x10,0x0d,0x12,0x96,0x2b,0x30,0x19,0x95,0x13,0x40,0x14,0x13,0x10,0x0f,0x01, 0x05,0x09,0x03,0x0d,0x18,0x14,0x14,0x00,0x03,0x19,0x00,0x13,0x10,0x13,0x20,0x13,0x60,0x13,0x04,0x0d,0x03,0x13,0x13,0x06,0x09,0x00,0x83,0x01,0x0e,0x03,0x08,0x06,0x42,0x08,0x83,0x09,0xb8,0xff,0xc8,0x40,0x0e,0x0b,0x0c,0x01,0x4c,0x09,0x40,0x09,0x0c,0x48,0x09,0x09,0x0d,0x1c,0x03,0xb8,0x01,0x2e,0x40,0x0c,0x0f,0x06,0x1f,0x06, 0x02,0x06,0x06,0x1f,0x11,0x0d,0x84,0x0e,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x5d,0xe1,0x39,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x2b,0x01,0x10,0xf2,0xe1,0x11,0x12,0x39,0x18,0x2f,0x5f,0x5e,0x5d,0x33,0x11,0x12,0x39,0x2f,0x33,0x00,0x2f,0x17,0x33,0x3f,0x33,0x33,0x1a,0x10,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x39,0x2f,0xe5,0x12,0x39, 0x11,0x12,0x39,0x87,0x05,0xc0,0x10,0x87,0xc0,0x10,0x87,0xc0,0x31,0x30,0x21,0x23,0x02,0x25,0x11,0x23,0x11,0x04,0x03,0x23,0x12,0x37,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x01,0x21,0x01,0x16,0x16,0x01,0x21,0x13,0x16,0x17,0x37,0x05,0xdf,0xae,0x23,0xfe,0xfe,0x9c,0xfe,0xf7,0x21,0xae,0x3e,0xe2,0xfe,0x92,0xa4,0xa4,0x01,0xbc,0xfe, 0xe4,0x03,0xb4,0xfe,0xb8,0xab,0xb6,0xfe,0xd9,0xfe,0x6e,0xb4,0x07,0x07,0x11,0x01,0x66,0x4c,0xfe,0x4e,0x01,0xb4,0x4d,0xfe,0x99,0x01,0x72,0x67,0xfe,0x27,0x04,0x00,0xfe,0x58,0x01,0xa8,0xfe,0x29,0x36,0xff,0x02,0x85,0xfe,0xdd,0x0b,0x13,0x1e,0x00,0x00,0x01,0x00,0x31,0xfe,0x66,0x03,0xe2,0x06,0xcb,0x00,0x43,0x00,0x75,0x40,0x41, 0x32,0x7d,0x13,0x00,0x7d,0x01,0x2e,0x17,0x2c,0x7d,0x1b,0x13,0x01,0x1b,0x17,0x20,0x20,0x17,0x1b,0x01,0x13,0x05,0x45,0x3b,0x7e,0x09,0x03,0x9a,0x42,0x42,0x35,0x3e,0x0c,0x9a,0x39,0x39,0x35,0x2f,0x2e,0x16,0x9a,0x17,0x17,0x29,0x10,0x9a,0x35,0x27,0x26,0x0f,0x24,0x1f,0x24,0x02,0x24,0x20,0x1e,0x99,0x23,0x29,0x03,0x3e,0x9a,0x01, 0x07,0x00,0x2f,0x33,0xed,0x3f,0x33,0xed,0x32,0xc4,0x5d,0x39,0x39,0x2f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x11,0x39,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed,0x01,0x2f,0xe1,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x10,0xe1,0x10,0xe1,0x31,0x30,0x01,0x23,0x34,0x23,0x22,0x07,0x06,0x23,0x20,0x11,0x34,0x36,0x33, 0x32,0x17,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x37,0x03,0x33,0x17,0x37,0x33,0x03,0x36,0x16,0x15,0x10,0x05,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x33,0x32,0x03,0xd3,0xb7,0x4d,0x2c,0x6f,0x70,0x45,0xfe, 0xb2,0xa6,0xa0,0x17,0x4b,0x4b,0x18,0x72,0x81,0xfe,0x8b,0x95,0x89,0x9f,0xaf,0x91,0x7f,0xb4,0xaa,0x82,0xa2,0xb9,0x73,0xa4,0xa4,0x77,0xbd,0x58,0xea,0xfe,0xf0,0x94,0xae,0xdb,0xbd,0x18,0x58,0x58,0x18,0x93,0x56,0x4c,0x2b,0x7b,0x7b,0x4a,0xef,0xfe,0x66,0x4c,0x26,0x26,0x01,0x23,0x80,0x91,0x06,0x06,0x89,0x75,0x01,0x14,0x8b,0x8a, 0x7e,0x6c,0x82,0x71,0xaa,0x48,0x0d,0x01,0x1c,0xe5,0xe5,0xfe,0xdd,0x0a,0xc2,0x9e,0xfe,0xe9,0x49,0x04,0x11,0xbc,0x8b,0xb4,0xe2,0x06,0x06,0x89,0x3f,0x50,0x25,0x25,0x00,0x01,0x00,0x21,0xfe,0x66,0x03,0x3c,0x05,0x35,0x00,0x42,0x00,0x79,0xb3,0x31,0x84,0x13,0x00,0xb8,0x01,0x2e,0x40,0x13,0x01,0x2d,0x17,0x2a,0x84,0x1a,0x13,0x01, 0x1a,0x17,0x1f,0x1f,0x17,0x1a,0x01,0x13,0x05,0x44,0x3a,0xb8,0x01,0x2e,0x40,0x27,0x0a,0x03,0x96,0x41,0x41,0x34,0x3d,0x2e,0x2d,0x16,0x95,0x17,0x17,0x28,0x0d,0x96,0x38,0x38,0x28,0x11,0x96,0x34,0x15,0x1f,0x1d,0x95,0x0f,0x23,0x1f,0x23,0x02,0x23,0x22,0x28,0x0f,0x3d,0x95,0x01,0x07,0x00,0x2f,0x33,0xed,0x3f,0x33,0xc4,0x5d,0xed, 0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x11,0x12,0x39,0x2f,0xed,0x01,0x2f,0xe1,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x10,0xe1,0x10,0xe1,0x31,0x30,0x01,0x23,0x34,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x34,0x21,0x23,0x35,0x33, 0x20,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x37,0x03,0x33,0x17,0x37,0x33,0x03,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x33,0x32,0x03,0x1e,0x95,0x3d,0x2e,0x55,0x55,0x38,0x82,0x99,0x9b,0x82,0x13,0x3b,0x3a,0x13,0xbf,0xfe,0xd6,0x64,0x60,0x01, 0x04,0x77,0x67,0x96,0x96,0x81,0x71,0xb6,0x73,0xa4,0xa4,0x77,0xb9,0xf9,0x71,0x61,0x70,0x8c,0xb0,0xa4,0x14,0x45,0x45,0x12,0x86,0x4b,0x41,0x2c,0x55,0x55,0x44,0xc6,0xfe,0x66,0x50,0x28,0x28,0x99,0x82,0x71,0x9a,0x07,0x08,0xa1,0xaa,0x8a,0xa4,0x45,0x53,0x4c,0x99,0x2e,0x0b,0x01,0x17,0xe5,0xef,0xfe,0xd9,0x29,0xdf,0x5b,0x80,0x15, 0x04,0x09,0x87,0x6a,0x89,0x97,0x07,0x07,0x85,0x42,0x51,0x25,0x25,0x00,0x00,0x01,0x00,0x66,0x00,0x00,0x05,0xc0,0x05,0x9a,0x00,0x19,0x00,0x3d,0x40,0x1e,0x14,0x11,0x91,0x04,0x07,0x07,0x06,0x18,0x12,0x0c,0x03,0x06,0x00,0x7e,0x17,0x17,0x1b,0x06,0x0c,0x0b,0x0b,0x1a,0x14,0x05,0x7e,0x11,0x06,0x06,0x1b,0x1a,0x11,0x12,0x39,0x2f, 0x33,0xe1,0x32,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x2f,0xe1,0x00,0x2f,0x3f,0x33,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x14,0x00,0x23,0x23,0x11,0x23,0x11,0x23,0x20,0x03,0x03,0x33,0x13,0x16,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x20,0x11,0x11,0x33,0x05,0xc0,0xfe,0xe1,0xf1,0x39,0x9c,0x54,0xfe,0xd9,0x54,0xa6,0xa4, 0xa0,0x1d,0x6b,0x6e,0x3b,0x9c,0x39,0x01,0x68,0xa8,0x03,0x87,0xdf,0xfe,0xdd,0xfe,0x7b,0x01,0x85,0x01,0x5f,0x02,0xb6,0xfd,0x5e,0x79,0x65,0x03,0x80,0xfc,0x80,0x01,0x6d,0x02,0x13,0x00,0x00,0x01,0x00,0x66,0xfe,0x1e,0x05,0x7b,0x05,0x33,0x00,0x1b,0x00,0x40,0x40,0x19,0x06,0x1c,0x13,0x13,0x1a,0x0d,0x0f,0x15,0x12,0x95,0x04,0x07, 0x16,0x00,0x84,0x19,0x19,0x1d,0x06,0x0d,0x0c,0x0c,0x1c,0x14,0x05,0xb8,0x01,0x2e,0xb4,0x13,0x06,0x06,0x1d,0x1c,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0x33,0x2f,0x3f,0x31,0x30,0x01,0x10,0x00,0x23,0x23,0x11,0x23,0x11,0x23,0x22,0x26,0x27,0x03,0x33, 0x13,0x16,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x32,0x36,0x35,0x11,0x33,0x05,0x7b,0xfe,0xe4,0xe8,0x19,0x93,0x15,0xac,0xd4,0x3c,0x94,0xa6,0x94,0x2a,0x81,0x6f,0x11,0x93,0x19,0x96,0xca,0xa4,0x02,0x2d,0xfe,0xf4,0xfe,0xc9,0xfe,0x34,0x01,0xcc,0xca,0xf6,0x02,0x56,0xfd,0xaa,0xa9,0x88,0x04,0xba,0xfb,0x46,0xef,0xc3,0x01,0xd5,0x00, 0x00,0x03,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x19,0x00,0x27,0x00,0x48,0x40,0x25,0x12,0x18,0x91,0x40,0x22,0x1c,0x0e,0x25,0x0f,0x14,0x42,0x0c,0x1a,0x14,0x91,0x20,0x20,0x00,0x0f,0x91,0x06,0x04,0x25,0x91,0x00,0x13,0x22,0x1a,0x12,0x09,0x7d,0x0c,0x0c,0x29,0x12,0x7d,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12, 0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x7c,0x2f,0x18,0xed,0x33,0x32,0x2b,0x00,0x18,0x10,0xf6,0x32,0x1a,0xed,0x32,0x31,0x30,0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x13,0x26,0x24,0x23,0x22,0x00,0x07,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x17,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x05,0x16,0x00,0x33, 0x32,0x00,0x02,0xfe,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0x8c,0xbe,0x1a,0xfe,0xff,0xcf,0xd6,0xfe,0xea,0x0e,0xfc,0x46,0x3c,0x88,0x88,0x24,0x3d,0xfb,0xf0,0x52,0x3a,0x84,0x84,0x2e,0x2a,0xfe,0xf6,0x1a,0x01,0x09,0xc7,0xe4,0x01,0x0e,0x18,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0xfe,0x70,0xfe,0xbd, 0xfe,0xa1,0xfe,0x68,0x03,0x52,0xe7,0xf9,0xfe,0xd8,0xf4,0x52,0x3a,0x3b,0x39,0x5a,0x3a,0x3a,0x56,0xe0,0xfe,0xf9,0x01,0x21,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x18,0x00,0x25,0x00,0x57,0x40,0x30,0x0b,0x25,0x1b,0x25,0x02,0x00,0x0f,0x10,0x0f,0x02,0x0c,0x03,0x11,0x17,0x95,0x40,0x21,0x1b,0x0e,0x24, 0x0e,0x13,0x42,0x0c,0x13,0x95,0x19,0x1f,0x1f,0x00,0x0e,0x95,0x06,0x10,0x24,0x95,0x00,0x16,0x09,0x83,0x0c,0x19,0x19,0x27,0x11,0x21,0x83,0x03,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x7c,0x2f,0x33,0x18,0xed,0x32,0x2b,0x00,0x18,0x10,0xf6,0x32,0x1a,0xed,0x32,0x31,0x30,0x01,0x5f,0x5e,0x5d, 0x5d,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x13,0x02,0x21,0x22,0x06,0x07,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x17,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x16,0x16,0x33,0x20,0x02,0x52,0xe3,0xfe,0xf1,0x01,0x1a,0xf0,0xe5,0x01,0x01,0xfe,0xeb,0x69,0x22,0xfe,0xdc,0x8b,0xb5,0x12,0x8e,0x35,0x30,0x6c,0x6b, 0x1e,0x22,0x8e,0x84,0x34,0x30,0x68,0x68,0x26,0x1e,0x9c,0x12,0xb4,0x8c,0x01,0x26,0x18,0x01,0x1f,0xed,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x02,0x64,0x01,0x42,0xaa,0x9a,0x31,0x34,0x35,0x5a,0x33,0x35,0x34,0x38,0x9a,0xaa,0x00,0x01,0x00,0x12,0x00,0x00,0x05,0xb8,0x05,0xb2,0x00,0x13,0x00,0x31,0x40,0x17,0x01,0x03, 0x91,0x12,0x04,0x09,0x03,0x0c,0x07,0x07,0x06,0x0c,0x0c,0x08,0x10,0x05,0x00,0x7e,0x01,0x01,0x15,0x09,0x08,0x2f,0x33,0x12,0x39,0x2f,0xe1,0xc6,0x32,0x11,0x39,0x19,0x2f,0x33,0x33,0x00,0x18,0x2f,0x33,0x3f,0x3f,0xfd,0xce,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x36,0x33, 0x32,0x05,0xb8,0x9a,0x0c,0x47,0x41,0x2a,0xfe,0x77,0xbd,0xfd,0xf8,0xbb,0x01,0x8d,0x13,0x0a,0x04,0x07,0x1a,0x01,0x3b,0x3f,0xbb,0xd1,0x04,0xc0,0x63,0x7d,0xfb,0x5a,0x05,0x9a,0xfb,0x8f,0x37,0x48,0x32,0x4f,0x03,0xc7,0xc0,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x04,0x9a,0x04,0x18,0x00,0x13,0x00,0x34,0x40,0x11,0x01,0x03,0x95,0x12, 0x10,0x09,0x0f,0x0c,0x07,0x07,0x06,0x0d,0x0d,0x08,0x10,0x05,0x00,0xb8,0x01,0x2e,0xb4,0x01,0x01,0x15,0x09,0x08,0x2f,0x33,0x12,0x39,0x2f,0xe1,0xc6,0x32,0x11,0x39,0x19,0x2f,0x33,0x33,0x00,0x18,0x2f,0x33,0x3f,0x3f,0xfd,0xce,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x36, 0x33,0x32,0x04,0x9a,0x96,0x08,0x42,0x37,0x31,0xfe,0xe8,0xa8,0xfe,0x7c,0xb4,0x01,0x04,0x1d,0x07,0x04,0x08,0x18,0xbf,0x47,0xaa,0xc6,0x03,0x3c,0x54,0x88,0xfc,0xf8,0x04,0x00,0xfd,0x18,0x52,0x3d,0x45,0x46,0x02,0x32,0xd2,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x05,0xb8,0x07,0x5c,0x02,0x26,0x05,0xee,0x00,0x00,0x01,0x07,0x04,0x6e, 0x02,0x2f,0x01,0x5c,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x4b,0x40,0x0a,0x1a,0x14,0x08,0x00,0x25,0x02,0x01,0x19,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x0e,0x00,0x00,0x04,0x9a,0x06,0x00,0x02,0x26,0x05,0xef,0x00,0x00,0x01,0x07,0x04,0x6e,0x01,0xc1,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x6e, 0x40,0x0a,0x1a,0x14,0x08,0x00,0x25,0x02,0x01,0x19,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x04,0x00,0x5e,0xfe,0x66,0x0a,0x7f,0x05,0xdb,0x00,0x0d,0x00,0x1b,0x00,0x30,0x00,0x31,0x00,0x8f,0x40,0x33,0x0e,0x91,0x08,0x0e,0x00,0x0f,0x91,0x07,0x0e,0x01,0x16,0x91,0x00,0x15,0x91,0x40,0x01,0x01,0x07,0x32,0x31,0x24, 0x42,0x31,0x04,0x23,0x29,0x24,0x16,0x1d,0x1f,0x95,0x2f,0x10,0x26,0x0f,0x29,0x24,0x22,0x23,0x23,0x21,0x25,0x2e,0x20,0x06,0x20,0x01,0x20,0x26,0x1c,0xb8,0x01,0x2e,0x40,0x17,0x1d,0x1d,0x26,0x25,0x25,0x33,0x19,0x16,0x01,0x08,0x0f,0x01,0x0f,0x01,0x04,0x0b,0x7d,0x19,0x19,0x33,0x12,0x7d,0x04,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x11, 0x39,0x39,0x2f,0x2f,0x33,0x11,0x33,0x11,0x12,0x39,0x2f,0x33,0x39,0x2f,0xe1,0x12,0x39,0x5d,0x11,0x33,0x11,0x12,0x39,0x2f,0x33,0x39,0x39,0x00,0x3f,0x3f,0xfd,0xce,0x3f,0x33,0x2f,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x1a,0xed,0xdd,0xe6,0x10,0xf4,0xed,0x10,0xf4,0xe6,0x31,0x30,0x05,0x35,0x20,0x00,0x11,0x10,0x00,0x21,0x15, 0x20,0x00,0x11,0x10,0x00,0x01,0x35,0x22,0x00,0x11,0x10,0x00,0x33,0x15,0x32,0x00,0x11,0x10,0x00,0x01,0x23,0x26,0x23,0x22,0x07,0x01,0x23,0x13,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x36,0x33,0x32,0x13,0x02,0xfe,0xfe,0xd0,0xfe,0x90,0x01,0x7f,0x01,0x33,0x01,0x37,0x01,0x63,0xfe,0x8e,0xfe,0xd8,0xe7,0xfe,0xe5,0x01,0x12, 0xde,0xec,0x01,0x10,0xfe,0xfe,0x06,0x81,0x95,0x0a,0x40,0x3c,0x2d,0xfe,0x75,0xac,0x8f,0xfe,0x79,0xb4,0x01,0x04,0x1c,0x07,0x05,0x06,0x1a,0xaa,0x40,0xb2,0xc6,0x1b,0x42,0x52,0x01,0x93,0x01,0x43,0x01,0x52,0x01,0xa3,0x52,0xfe,0x76,0xfe,0xb7,0xfe,0xa2,0xfe,0x66,0x05,0x34,0x52,0xfe,0xb3,0xfe,0xfd,0xfe,0xf7,0xfe,0xbd,0x52,0x01, 0x34,0x01,0x16,0x01,0x1a,0x01,0x38,0xfe,0x4a,0x54,0x88,0xfb,0x5e,0x01,0x82,0x04,0x18,0xfd,0x18,0x51,0x3e,0x36,0x55,0x02,0x32,0xd2,0x01,0x9a,0x00,0x03,0x00,0x58,0xfe,0x66,0x08,0xec,0x04,0x38,0x00,0x0d,0x00,0x1a,0x00,0x2f,0x00,0x83,0x40,0x2b,0x0e,0x95,0x08,0x0e,0x00,0x0f,0x95,0x07,0x0e,0x01,0x16,0x95,0x00,0x15,0x95,0x40, 0x01,0x2e,0x23,0x42,0x22,0x29,0x23,0x16,0x1c,0x1e,0x95,0x2e,0x10,0x25,0x0f,0x29,0x23,0x2c,0x21,0x22,0x22,0x24,0x2c,0x20,0x20,0x25,0x1b,0xb8,0x01,0x2e,0x40,0x17,0x1c,0x1c,0x25,0x24,0x24,0x31,0x19,0x15,0x00,0x0e,0x07,0x00,0x07,0x00,0x04,0x0b,0x83,0x19,0x19,0x31,0x12,0x83,0x04,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39, 0x2f,0x2f,0x33,0x11,0x33,0x11,0x12,0x39,0x2f,0x33,0x39,0x2f,0xe1,0x12,0x39,0x11,0x33,0x12,0x39,0x2f,0x33,0x12,0x39,0x39,0x00,0x3f,0x3f,0xfd,0xce,0x3f,0x33,0x2f,0x2b,0x00,0x7d,0x2f,0x1a,0x18,0xed,0xdd,0xed,0x10,0xf4,0xed,0x10,0xf4,0xed,0x31,0x30,0x05,0x35,0x22,0x00,0x35,0x34,0x00,0x33,0x15,0x32,0x00,0x15,0x14,0x00,0x03, 0x35,0x22,0x06,0x15,0x14,0x16,0x33,0x15,0x32,0x36,0x35,0x10,0x05,0x23,0x26,0x23,0x22,0x07,0x01,0x23,0x13,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x36,0x33,0x32,0x02,0x4e,0xe7,0xfe,0xf1,0x01,0x1a,0xea,0xeb,0x01,0x01,0xfe,0xeb,0xd7,0xa2,0xba,0xb3,0x9b,0xa1,0xb1,0x05,0x4c,0x96,0x08,0x42,0x3b,0x2d,0xfe,0x74,0xac,0x90, 0xfe,0x78,0xb5,0x01,0x04,0x1c,0x07,0x04,0x07,0x19,0xaa,0x40,0xb2,0xc6,0x38,0x3e,0x01,0x20,0xec,0xfa,0x01,0x2c,0x3e,0xfe,0xe6,0xfa,0xf6,0xfe,0xd8,0x03,0xa6,0x3e,0xd3,0xc1,0xb8,0xce,0x3e,0xd0,0xbb,0x01,0x8f,0x32,0x54,0x88,0xfb,0x5e,0x01,0x82,0x04,0x18,0xfd,0x18,0x51,0x3e,0x36,0x55,0x02,0x32,0xd2,0x00,0x00,0x02,0x00,0x5e, 0xff,0xb4,0x06,0x3e,0x05,0xec,0x00,0x13,0x00,0x26,0x00,0x5b,0x40,0x31,0x20,0x1e,0x16,0x18,0x0c,0x0a,0x02,0x04,0x14,0x18,0x91,0x0e,0x42,0x0a,0x04,0x22,0x1e,0x91,0x40,0x00,0x04,0x13,0x11,0x7d,0x25,0x0e,0x0e,0x1b,0x04,0x42,0x22,0x18,0x14,0x0a,0x00,0x00,0x0a,0x14,0x18,0x22,0x05,0x0e,0x1e,0x04,0x04,0x28,0x1b,0x7d,0x07,0x2f, 0xe1,0x12,0x39,0x2f,0x33,0xc4,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x33,0x1a,0xed,0x32,0x3f,0xe5,0xed,0x32,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x31,0x30,0x05,0x06,0x23,0x22,0x27,0x24,0x00,0x11,0x10,0x00,0x25,0x36,0x33,0x32,0x17,0x04,0x00,0x11,0x10,0x00,0x01,0x06,0x23,0x22,0x27, 0x06,0x00,0x15,0x14,0x12,0x17,0x36,0x33,0x32,0x17,0x36,0x12,0x35,0x10,0x03,0xb0,0x26,0x42,0x42,0x27,0xfe,0xd0,0xfe,0xaf,0x01,0x53,0x01,0x39,0x25,0x49,0x48,0x24,0x01,0x2c,0x01,0x4e,0xfe,0xad,0xfe,0xd1,0x26,0x3e,0x3e,0x26,0xe5,0xfe,0xff,0xf5,0xdc,0x27,0x42,0x42,0x26,0xe5,0xf9,0x14,0x38,0x38,0x1b,0x01,0x7e,0x01,0x37,0x01, 0x46,0x01,0x8b,0x1f,0x40,0x3e,0x1b,0xfe,0x82,0xfe,0xca,0xfe,0xb3,0xfe,0x76,0x05,0x0c,0x30,0x30,0x18,0xfe,0xc9,0xfa,0xf9,0xfe,0xcf,0x1c,0x37,0x37,0x1b,0x01,0x2a,0xfe,0x02,0x16,0x00,0x00,0x02,0x00,0x60,0xff,0xb0,0x04,0xd3,0x04,0x4e,0x00,0x11,0x00,0x21,0x00,0x59,0x40,0x31,0x0b,0x09,0x14,0x12,0x42,0x16,0x95,0x0d,0x09,0x10, 0x02,0x04,0x1c,0x1e,0x1a,0x95,0x40,0x00,0x42,0x04,0x16,0x0f,0x83,0x20,0x0e,0x0d,0x18,0x04,0x42,0x1e,0x1a,0x16,0x12,0x09,0x00,0x00,0x09,0x12,0x16,0x1a,0x1e,0x06,0x0d,0x04,0x04,0x23,0x18,0x83,0x07,0x2f,0xe1,0x12,0x39,0x2f,0xc4,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x3f,0xe5,0x1a,0xfd, 0x32,0xcd,0x10,0xcd,0x3f,0x33,0xfd,0xf5,0xcd,0x10,0xcd,0x31,0x30,0x05,0x06,0x23,0x22,0x27,0x26,0x02,0x35,0x10,0x25,0x36,0x33,0x32,0x17,0x04,0x11,0x14,0x02,0x03,0x06,0x23,0x22,0x27,0x04,0x11,0x10,0x05,0x36,0x33,0x32,0x17,0x24,0x11,0x10,0x03,0x0a,0x26,0x48,0x46,0x27,0xe3,0xec,0x01,0xdc,0x26,0x46,0x46,0x26,0x01,0xbf,0xf0, 0xd1,0x26,0x44,0x46,0x26,0xfe,0xcc,0x01,0x29,0x27,0x44,0x44,0x26,0x01,0x25,0x10,0x40,0x3e,0x19,0x01,0x0f,0xde,0x01,0xe8,0x36,0x3c,0x3c,0x32,0xfe,0x24,0xde,0xfe,0xe9,0x03,0x74,0x37,0x3b,0x2f,0xfe,0xa2,0xfe,0xb2,0x31,0x37,0x37,0x2f,0x01,0x54,0x01,0x4e,0x00,0x03,0x00,0x5e,0xff,0xe8,0x08,0xaa,0x08,0x05,0x00,0x29,0x00,0x41, 0x00,0x4d,0x00,0x5e,0x40,0x31,0x36,0x37,0x37,0x4c,0x47,0x2a,0x2a,0x47,0x20,0x0a,0x05,0x25,0x7d,0x1a,0x47,0x1a,0x47,0x1a,0x4f,0x10,0x7d,0x05,0x1d,0x91,0x22,0x04,0x42,0x42,0x08,0x49,0x49,0x2c,0x31,0x96,0x3c,0x3c,0x2a,0x96,0x37,0x2c,0x2c,0x0d,0x91,0x08,0x04,0x13,0x91,0x02,0x13,0x00,0x3f,0xed,0x3f,0xed,0x33,0x2f,0x33,0xed, 0x32,0x2f,0xed,0x11,0x33,0x2f,0x12,0x39,0x2f,0x3f,0xed,0x01,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x39,0x11,0x33,0x2f,0x11,0x33,0x33,0x2f,0x33,0x31,0x30,0x25,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x16,0x33,0x32,0x00,0x11,0x10,0x00,0x23, 0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x13,0x15,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x33,0x01,0x27,0x36,0x37,0x22,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x04,0x85,0xc2,0xcb,0xfe,0xd3,0xfe,0x93,0x01,0x66,0x01,0x32,0x9e,0x6e,0x6a,0xa4,0xdf,0xfe,0xf9,0x01, 0x0e,0xf0,0xdd,0x9a,0x9a,0xdf,0xf0,0x01,0x0e,0xfe,0xfa,0xe0,0xa4,0x6a,0x6e,0x9e,0x01,0x31,0x01,0x67,0xfe,0x93,0xfe,0xd3,0xc8,0xc9,0x29,0x4a,0x85,0x78,0x6b,0x30,0x16,0x22,0x18,0x0c,0x80,0x18,0x33,0x53,0x3a,0x40,0x76,0x77,0x79,0x43,0xfe,0x59,0x16,0x56,0x06,0x60,0x5a,0x30,0x3e,0x3e,0x56,0x01,0x8e,0x01,0x4c,0x01,0x4c,0x01, 0xa4,0x2b,0xb2,0x45,0xfe,0xba,0xfe,0xf2,0xfe,0xeb,0xfe,0xce,0x60,0x60,0x01,0x31,0x01,0x16,0x01,0x0d,0x01,0x47,0x45,0xb2,0x2b,0xfe,0x5e,0xfe,0xb4,0xfe,0xb4,0xfe,0x70,0x07,0xa3,0x7f,0x26,0x2e,0x26,0x13,0x21,0x2d,0x19,0x2f,0x5a,0x46,0x2a,0x26,0x2e,0x26,0xfe,0x54,0x35,0x16,0x3a,0x50,0x52,0x41,0x30,0x91,0x00,0x03,0x00,0x60, 0xff,0xe8,0x06,0xc6,0x06,0x9d,0x00,0x29,0x00,0x41,0x00,0x4d,0x00,0x5d,0x40,0x31,0x36,0x37,0x37,0x4c,0x47,0x2a,0x2a,0x47,0x0b,0x1f,0x05,0x25,0x83,0x1a,0x47,0x1a,0x47,0x1a,0x4f,0x10,0x83,0x05,0x42,0x42,0x08,0x49,0x49,0x2c,0x31,0x96,0x3c,0x3c,0x41,0x96,0x36,0x2c,0x00,0x1d,0xec,0x22,0x10,0x0d,0xec,0x08,0x10,0x13,0x95,0x02, 0x16,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0x33,0xed,0x32,0x2f,0xed,0x11,0x33,0x2f,0x12,0x39,0x2f,0x01,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x39,0x11,0x33,0x2f,0x11,0x33,0x33,0x2f,0x33,0x31,0x30,0x25,0x06,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32, 0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x13,0x15,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x33,0x01,0x27,0x36,0x37,0x22,0x35,0x34,0x33,0x32,0x16,0x15,0x14,0x03,0x96,0x96,0xac,0xe8,0xfe,0xf4,0x01,0x08,0xde,0x84, 0x63,0x69,0x82,0x93,0xa7,0xbb,0xad,0xa2,0x82,0x81,0xa1,0xad,0xbb,0xa6,0x92,0x83,0x69,0x63,0x85,0xde,0x01,0x06,0xfe,0xf5,0xe8,0xa9,0xf1,0x29,0x4a,0x85,0x78,0x6b,0x30,0x16,0x22,0x18,0x0c,0x80,0x18,0x33,0x53,0x3a,0x40,0x76,0x77,0x79,0x43,0xfe,0x59,0x16,0x56,0x06,0x60,0x5a,0x30,0x3e,0x42,0x5a,0x01,0x25,0xed,0xf0,0x01,0x2e, 0x30,0xaa,0x49,0xd2,0xb9,0xb3,0xd5,0x63,0x63,0xd2,0xb6,0xb9,0xd2,0x49,0xaa,0x30,0xfe,0xd1,0xef,0xec,0xfe,0xda,0x06,0x3b,0x7f,0x26,0x2e,0x26,0x13,0x21,0x2d,0x19,0x2f,0x5a,0x46,0x2a,0x26,0x2e,0x26,0xfe,0x54,0x35,0x16,0x3a,0x50,0x52,0x41,0x30,0x91,0x00,0xff,0xff,0x00,0x1e,0x00,0x00,0x06,0xca,0x06,0xdb,0x02,0x26,0x05,0xda, 0x00,0x00,0x01,0x07,0x06,0x65,0x02,0x1f,0x01,0x0a,0x00,0x08,0xb3,0x01,0x3e,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x1e,0x00,0x00,0x05,0x5e,0x05,0x7f,0x02,0x26,0x05,0xdb,0x00,0x00,0x01,0x07,0x06,0x65,0x01,0x53,0xff,0xae,0x00,0x16,0xb9,0x00,0x01,0xff,0xea,0x40,0x09,0x20,0x15,0x08,0x00,0x25,0x01,0x1f,0x11,0x26,0x00,0x2b, 0x35,0x01,0x2b,0x35,0x00,0x01,0x00,0x5e,0xfe,0x66,0x04,0x8c,0x05,0xb2,0x00,0x15,0x00,0x31,0x40,0x1a,0x30,0x00,0x01,0x00,0x00,0x02,0x91,0x13,0x04,0x0c,0x0a,0x08,0x91,0x0d,0x13,0x0a,0x7e,0x0d,0x0d,0x10,0x00,0x00,0x17,0x05,0x7d,0x10,0x2f,0xe1,0x11,0x39,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x2f,0x3f,0xed,0x32,0x2f, 0x5d,0x31,0x30,0x01,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x11,0x23,0x11,0x24,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x04,0x8c,0x9a,0xba,0xf7,0xfe,0xcd,0x01,0x1f,0xe9,0x20,0x2e,0xa8,0xfe,0xe8,0xfe,0xba,0x01,0x9e,0x01,0x3e,0xcc,0x86,0x04,0xc4,0x56,0xfe,0xb6,0xfe,0xec,0xfe,0xfa,0xfe,0xc9,0x04,0xfd,0xe3,0x01,0x82, 0x16,0x01,0x85,0x01,0x2f,0x01,0x58,0x01,0xa8,0x3b,0x00,0x01,0x00,0x60,0xfe,0x66,0x03,0x62,0x04,0x18,0x00,0x15,0x00,0x2d,0x40,0x17,0x00,0x00,0x02,0x95,0x13,0x10,0x0c,0x0a,0x08,0x96,0x0d,0x16,0x0a,0x84,0x0d,0x0d,0x10,0x00,0x00,0x17,0x05,0x83,0x10,0x2f,0xe1,0x12,0x39,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x2f,0x3f, 0xed,0x32,0x2f,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x11,0x23,0x11,0x26,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x03,0x62,0x72,0x82,0x9d,0xc9,0xbd,0x9f,0x1e,0x28,0xa2,0xc0,0xe8,0x01,0x22,0xf2,0x87,0x67,0x03,0x3e,0x50,0xe1,0xb7,0xb4,0xd0,0x09,0xfd,0xeb,0x01,0x88,0x15,0x01,0x17,0xce,0xfd,0x01,0x33, 0x32,0x00,0x00,0x01,0x00,0x2d,0x00,0x00,0x03,0xd5,0x05,0x9a,0x00,0x13,0x00,0xc8,0x40,0x6b,0x09,0x08,0x11,0x06,0x07,0x12,0x05,0x0a,0x05,0x0c,0x08,0x11,0x03,0x07,0x12,0x04,0x0b,0x04,0x0d,0x08,0x11,0x02,0x01,0x0e,0x01,0x13,0x07,0x12,0x10,0x08,0x11,0x00,0x0f,0x0f,0x0e,0x0e,0x00,0x04,0x0a,0x42,0x05,0x04,0x04,0x03,0x13,0x06, 0x03,0x02,0x07,0x12,0x07,0x02,0x03,0x06,0x13,0x04,0x12,0x07,0x10,0x0d,0x0c,0x09,0x08,0x11,0x08,0x09,0x0c,0x0d,0x10,0x04,0x11,0x08,0x00,0x01,0x0f,0x0a,0x0b,0x05,0x40,0x04,0x05,0x0e,0x0f,0x05,0x0f,0x05,0x08,0x12,0x11,0x03,0x07,0x08,0x11,0x12,0x07,0x0b,0x0a,0x0e,0x08,0x12,0x00,0x42,0x00,0x12,0x12,0x15,0x08,0x2f,0x12,0x39, 0x2f,0xce,0x2b,0x01,0x10,0xe2,0x32,0x33,0x11,0x33,0x00,0x18,0x2f,0x33,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x33,0x11,0x33,0x1a,0x10,0xcd,0x32,0x10,0xcd,0x32,0x11,0x12,0x17,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x17,0x39,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x11,0x01,0x33,0x2f,0x33,0x2b,0x01,0x10,0xe1,0x32, 0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x31,0x30,0x01,0x07,0x25,0x03,0x05,0x07,0x25,0x03,0x23,0x13,0x25,0x37,0x05,0x13,0x25,0x37,0x05,0x13,0x33,0x03,0x03,0xd5,0x37,0xfe,0xe5,0x99,0x01,0x16,0x38,0xfe,0xec,0xac,0x91,0xc3,0xfe,0xf3,0x37,0x01,0x0a,0x9a, 0xfe,0xfa,0x38,0x01,0x04,0xa1,0x93,0xba,0x03,0x6a,0x7a,0x7e,0xfe,0x9c,0x7c,0x7c,0x7c,0xfe,0x72,0x01,0xc4,0x78,0x7c,0x76,0x01,0x62,0x74,0x7e,0x75,0x01,0x79,0xfe,0x50,0x00,0x00,0x01,0x00,0x52,0x04,0xc2,0x02,0xd7,0x05,0xcb,0x00,0x11,0x00,0x18,0x40,0x0a,0x0b,0x08,0xe2,0x00,0x02,0x09,0x0e,0x00,0x0e,0x05,0x2f,0xcd,0xcd,0x10, 0xcd,0x00,0x2f,0xdd,0xfd,0xcc,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x0a,0x0a,0x52,0x26,0x36,0x36,0x26,0x01,0x73,0x0b,0x4f,0x26,0x36,0x36,0x26,0x05,0x12,0x50,0x36,0x26,0x27,0x36,0x50,0x36,0x27,0x26,0x36,0x00,0x01,0x00,0x5e,0x04,0xc2,0x03,0x0a,0x05,0xbe, 0x00,0x0f,0x00,0x1c,0x40,0x0d,0x0e,0x4c,0x03,0x09,0x99,0x00,0x08,0x00,0xc2,0x01,0x01,0x11,0x08,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x2f,0x33,0xed,0xdc,0xed,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x06,0x23,0x23,0x35,0x33,0x32,0x37,0x36,0x33,0x32,0x03,0x0a,0x7a,0x32,0x64,0x32,0x61,0x61,0x42,0x66,0x50,0x3d,0x6a,0x69,0x4c,0x97, 0x04,0xc2,0x88,0x44,0x44,0x9a,0x31,0x31,0xff,0xff,0xff,0x90,0x04,0x7b,0x00,0x7d,0x06,0x23,0x00,0x07,0x04,0x61,0xfd,0xae,0x00,0x00,0xff,0xff,0xff,0x86,0x04,0x7b,0x00,0x71,0x06,0x23,0x00,0x07,0x04,0x29,0xfd,0xa2,0x00,0x00,0x00,0x08,0x00,0x21,0xfe,0xcf,0x07,0xbc,0x05,0x5a,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x3b, 0x00,0x47,0x00,0x53,0x00,0x5f,0x00,0xd5,0x40,0x74,0x0d,0x11,0x19,0x03,0x1d,0x0f,0x1b,0xc3,0x15,0x21,0x21,0x09,0x39,0x3d,0x41,0x49,0x03,0x4d,0x3f,0x4b,0xc3,0x45,0x51,0x51,0x39,0x5d,0x55,0x59,0x57,0xc3,0x40,0x5d,0x0e,0x30,0x39,0x05,0x42,0x09,0xc3,0x03,0x01,0x05,0x2d,0x39,0xc3,0x27,0x33,0x40,0x24,0x2a,0x35,0x03,0x30,0x3c, 0x0c,0xc4,0x3d,0x0d,0x0d,0x80,0x41,0x11,0xc4,0x42,0x12,0x0e,0x2a,0x30,0x18,0x42,0x48,0x18,0xc4,0x49,0x19,0x4d,0x1d,0xc4,0x4e,0x1e,0x1e,0x06,0x36,0x24,0xc4,0x25,0x25,0x80,0x29,0xc4,0x2a,0x0e,0x06,0x30,0x00,0x42,0x54,0x00,0xc4,0x55,0x01,0x59,0x05,0xc4,0x5a,0x06,0x06,0x61,0x36,0x30,0xc4,0x31,0x80,0x35,0xc4,0x36,0x2f,0xe1, 0x1a,0xdc,0xe1,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0xdc,0x32,0xe1,0x32,0x2b,0x01,0x10,0xf2,0xe1,0x1a,0xc8,0x18,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0xdc,0x32,0xe1,0x32,0x2b,0x01,0x10,0xf2,0x32,0xe1,0x32,0x1a,0xc8,0x18,0x2f,0x32,0xe1,0x32,0x00,0x2f,0x17,0x33,0x1a,0xdc,0x32,0xed,0x32,0x2f,0x33,0xde,0xed,0x2b,0x00, 0x18,0x10,0xf6,0x1a,0xfd,0xce,0x32,0x11,0x12,0x39,0x2f,0x33,0xfd,0x32,0xce,0x17,0x32,0x11,0x12,0x39,0x2f,0x33,0xfd,0x32,0xce,0x17,0x32,0x31,0x30,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x05,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32, 0x16,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x05,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x05,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x01,0x23,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x04,0xa2,0x50, 0x08,0x68,0x64,0x0e,0x4f,0x07,0x6d,0x4f,0x52,0x68,0x02,0x8f,0x50,0x08,0x67,0x62,0x0e,0x52,0x08,0x6b,0x4f,0x52,0x6a,0xfa,0xfd,0x50,0x08,0x67,0x63,0x0d,0x52,0x08,0x6b,0x4f,0x52,0x6a,0x05,0x98,0x50,0x08,0x66,0x64,0x0c,0x52,0x07,0x6b,0x50,0x52,0x69,0xf9,0xe9,0x50,0x08,0x68,0x64,0x0e,0x4f,0x07,0x6d,0x4f,0x52,0x68,0x05,0x8f, 0x50,0x08,0x67,0x62,0x0e,0x52,0x08,0x6b,0x4f,0x52,0x6a,0xfa,0xfd,0x50,0x08,0x67,0x63,0x0d,0x52,0x08,0x6b,0x4f,0x52,0x6a,0x02,0x7e,0x50,0x08,0x68,0x64,0x0e,0x4f,0x07,0x6d,0x4f,0x52,0x68,0x04,0xa4,0x6a,0x6a,0x53,0x63,0x63,0xfe,0xaf,0x6a,0x6a,0x52,0x64,0x63,0x53,0x6a,0x6a,0x52,0x64,0x63,0xfd,0xc3,0x6b,0x6b,0x52,0x64,0x62, 0x54,0x6b,0x6b,0x53,0x63,0x62,0xfd,0xc1,0x6b,0x6b,0x52,0x64,0x63,0x53,0x6b,0x6b,0x52,0x64,0x63,0xfe,0xab,0x6b,0x6b,0x53,0x63,0x63,0x00,0x08,0x00,0x35,0xfe,0x66,0x07,0x68,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x95,0x40,0x4d,0x4f,0x15,0x5f,0x15,0x02,0x15,0x17,0x19, 0x1b,0x17,0x1b,0x17,0x1f,0x12,0x0b,0x09,0x40,0x07,0x50,0x07,0x02,0x07,0x05,0x09,0x05,0x09,0x05,0x0c,0x02,0x1e,0x2f,0x1f,0x01,0x1f,0x0c,0x03,0x02,0x12,0x10,0x0e,0x0c,0x14,0x16,0x08,0x0a,0x06,0x04,0x1a,0x18,0x1e,0x1c,0x00,0x02,0x16,0x0a,0x16,0x0a,0x11,0x02,0x18,0x04,0x18,0x04,0x1c,0x02,0x1c,0x02,0x0c,0x10,0x11,0x11,0x21, 0x0d,0x0c,0x0c,0x21,0x20,0x11,0x12,0x39,0x2f,0xcd,0x12,0x39,0x2f,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x10,0xcd,0x00,0x2f,0xcd,0xd6,0xdd,0xd6,0xcd,0x10,0xd6,0x5d,0xcd,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x5d,0x10,0xcd,0x11, 0x12,0x39,0x39,0x2f,0x2f,0xcd,0x10,0xcd,0x5d,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x07,0x03,0x37,0x05,0x05,0x27,0x25,0x01,0x25,0x35,0x05,0x05,0x25,0x35,0x05,0x01,0x07,0x03,0x37,0x05,0x05,0x27,0x25,0x05,0x03,0x23,0x13,0x04,0x4c,0x5c,0x7c,0x76,0xfe,0x6a,0x58,0xa6,0x46,0x05,0x16,0xfe,0xc7,0x58,0x01,0x4d,0xfb,0x28,0xfe,0x9f, 0x01,0x61,0x05,0xd2,0xfe,0xa0,0x01,0x60,0xfe,0xe0,0x46,0xb8,0x58,0xfc,0xdb,0xfe,0xb2,0x43,0x01,0x39,0x02,0x04,0x75,0x62,0x5c,0x05,0x9a,0xfe,0xa0,0x01,0x60,0xfe,0x10,0x58,0x01,0x4e,0x44,0xb1,0xb8,0x58,0xa6,0xfd,0x2d,0x74,0x63,0x5c,0x9e,0x5c,0x7b,0x74,0xfd,0x7a,0x44,0x01,0x3a,0x58,0x81,0xa6,0x46,0xb8,0xbf,0xfe,0xa0,0x01, 0x60,0x00,0x00,0x02,0x00,0x29,0x00,0x00,0x04,0x38,0x05,0x9a,0x00,0x12,0x00,0x1a,0x00,0x45,0x40,0x23,0x0a,0x01,0x91,0x07,0x04,0x04,0x05,0x13,0x91,0x0b,0x0b,0x05,0x03,0x14,0x91,0x00,0x02,0x00,0x09,0x09,0x14,0x0f,0x7d,0x18,0x18,0x1c,0x0b,0x07,0x14,0x7e,0x04,0x00,0x00,0x1c,0x1b,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0x32,0x12, 0x39,0x2f,0xe1,0x11,0x39,0x2f,0x10,0xc6,0x00,0x2f,0xed,0x3f,0x39,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0xbc,0x93,0x93,0xa8,0xa2,0xa2,0x01,0x10,0xd6,0xee,0xfa,0xd8,0xfe,0xfe, 0xec,0x95,0xa2,0xfe,0xc9,0x04,0x74,0x9a,0x8c,0x8c,0x9a,0xfe,0xc6,0xcf,0xbf,0xc6,0xe6,0x02,0xa2,0xfd,0xf6,0x8c,0x7e,0x01,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x00,0x03,0xb4,0x05,0xec,0x00,0x12,0x00,0x19,0x00,0x47,0x40,0x24,0x0a,0x01,0x96,0x07,0x04,0x04,0x06,0x0b,0x95,0x13,0x13,0x00,0x06,0x00,0x14,0x95,0x00,0x02,0x00,0x09, 0x09,0x14,0x0f,0x83,0x17,0x17,0x1b,0x0b,0x07,0x14,0x84,0x04,0x00,0x00,0x1b,0x1a,0x11,0x12,0x39,0x2f,0x33,0xe1,0x32,0x32,0x11,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x10,0xc6,0x00,0x2f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x21,0x32,0x16, 0x15,0x14,0x06,0x23,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0xa6,0x79,0x79,0xa4,0x81,0x81,0x01,0x14,0x9d,0xb9,0xba,0x8e,0xfe,0xde,0xf6,0xcc,0xce,0x04,0xd1,0x85,0x96,0x96,0x85,0xfd,0xa6,0xa4,0x93,0x94,0xac,0x01,0xea,0xfe,0xa2,0xb4,0xaa,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x0e,0x00,0x1a,0x00,0x75,0x40,0x3f, 0x16,0x00,0x15,0x01,0x15,0x13,0x03,0x14,0x02,0x14,0x03,0x00,0x06,0x09,0x16,0x13,0x10,0x0f,0x01,0x02,0x06,0x14,0x0f,0x15,0x1f,0x15,0x2f,0x15,0x03,0x15,0x15,0x0f,0x06,0x91,0x10,0x10,0x08,0x0f,0x91,0x09,0x03,0x08,0x02,0x01,0x01,0x0d,0x07,0x15,0x00,0x14,0x01,0x14,0x14,0x10,0x0d,0x7d,0x18,0x18,0x1c,0x10,0x07,0x7e,0x08,0x2f, 0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x5d,0x33,0x11,0x12,0x39,0x2f,0x33,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x5d,0x33,0x10,0xc6,0x32,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x31,0x30,0x01,0x17,0x07,0x27,0x06,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x16, 0x15,0x14,0x01,0x11,0x33,0x32,0x37,0x27,0x37,0x17,0x36,0x35,0x10,0x21,0x03,0x81,0x75,0x73,0x7d,0x67,0x7e,0xbd,0xa8,0x01,0x8a,0xe6,0xfd,0xfd,0x3b,0xb0,0x52,0x46,0x66,0x72,0x6f,0x52,0xfe,0xb0,0x02,0x89,0xb0,0x4d,0xba,0x28,0xfd,0xe2,0x05,0x9a,0xe0,0xcc,0xe3,0x01,0xf7,0xfd,0xb4,0x15,0x97,0x4e,0xa4,0x4e,0x8c,0x01,0x1c,0x00, 0x00,0x02,0x00,0xa6,0xfe,0x23,0x04,0x54,0x04,0x18,0x00,0x14,0x00,0x25,0x00,0x7c,0x40,0x44,0x18,0x00,0x17,0x01,0x17,0x15,0x03,0x16,0x02,0x16,0x03,0x00,0x05,0x10,0x18,0x15,0x24,0x1d,0x09,0x1c,0x01,0x02,0x05,0x16,0x17,0x40,0x09,0x0c,0x48,0x17,0x17,0x1d,0x24,0x95,0x05,0x16,0x0e,0x1d,0x95,0x10,0x10,0x0c,0x0f,0x02,0xdf,0x01, 0x01,0x01,0x01,0x13,0x09,0x17,0x00,0x16,0x01,0x16,0x16,0x21,0x13,0x83,0x1a,0x1a,0x27,0x21,0x0c,0x09,0x84,0x0a,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x5d,0x33,0x11,0x12,0x39,0x2f,0x5d,0x33,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x11,0x39,0x2f,0x2b,0x33,0x10,0xc6,0x32,0x3f,0x11,0x12,0x39,0x39,0x11,0x12,0x39, 0x39,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x31,0x30,0x25,0x17,0x07,0x27,0x06,0x23,0x22,0x27,0x23,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x05,0x27,0x37,0x17,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x03,0xae,0x70,0x72,0x72,0x52,0x67,0xd7,0x5c,0x04,0xa4,0xa4,0x04,0x74, 0xee,0xc0,0xe4,0xfe,0x92,0x78,0x74,0x72,0x5a,0xa2,0x85,0x8d,0xb0,0xa6,0x80,0x42,0x56,0xa8,0x4e,0xaa,0x22,0xac,0xfd,0x8f,0x05,0xdd,0xb4,0xcc,0xfe,0xf2,0xe3,0xfe,0xc9,0x69,0xb1,0x4d,0xaa,0x71,0xd0,0xa9,0xc9,0xc9,0x98,0x8f,0x7f,0xad,0x00,0x01,0x00,0xbc,0xfe,0x66,0x04,0x33,0x05,0x9a,0x00,0x19,0x00,0x40,0x40,0x24,0x18,0x91, 0x04,0x01,0x14,0x01,0x24,0x01,0x03,0x01,0x03,0x0b,0x0a,0x91,0x11,0x11,0x0b,0x10,0x91,0x0d,0x03,0x0b,0x0f,0x0f,0x0c,0x15,0x7d,0x06,0x06,0x1b,0x11,0x0b,0x7e,0x01,0x42,0x0c,0x2f,0xe2,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x10,0xde,0x32,0x5d,0xed,0x31,0x30,0x13,0x35,0x16,0x33, 0x32,0x36,0x35,0x34,0x02,0x23,0x23,0x11,0x23,0x11,0x21,0x15,0x21,0x11,0x33,0x20,0x00,0x11,0x14,0x00,0x21,0x22,0xbe,0xa4,0x9a,0xbd,0xca,0xfe,0xdb,0x46,0xa8,0x02,0xd0,0xfd,0xd8,0x4a,0x01,0x27,0x01,0x5e,0xfe,0xd9,0xfe,0xf4,0xae,0xfe,0xb2,0xb8,0x6c,0xdf,0xcb,0xd5,0x01,0x25,0xfd,0x5e,0x05,0x9a,0x9a,0xfe,0x3a,0xfe,0x97,0xfe, 0xdd,0xfd,0xfe,0xb5,0x00,0x01,0x00,0xa6,0xfe,0x66,0x03,0xaa,0x04,0x00,0x00,0x19,0x00,0x3f,0x40,0x23,0x18,0x95,0x04,0x01,0x14,0x01,0x24,0x01,0x03,0x01,0x03,0x0b,0x0a,0x95,0x11,0x11,0x0b,0x10,0x95,0x0d,0x0f,0x0b,0x0e,0x0e,0x0c,0x15,0x83,0x06,0x06,0x1b,0x11,0x0b,0x84,0x01,0x0c,0x2f,0x33,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11, 0x39,0x2f,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x10,0xde,0x32,0x5d,0xed,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x15,0x21,0x11,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0xa6,0x75,0x8b,0xa7,0xb5,0xda,0xbe,0x20,0xa4,0x02,0x76,0xfe,0x2e,0x42,0xf7,0x01,0x27,0xfe,0xe9,0xef,0x99, 0xfe,0xa0,0xa0,0x4e,0xbb,0xa9,0xb9,0xd7,0xfe,0x1a,0x04,0x00,0x8c,0xff,0x00,0xfe,0xdd,0xf9,0xd7,0xfe,0xe5,0x00,0x00,0x01,0x00,0x60,0xfe,0xae,0x03,0xe2,0x05,0xb2,0x00,0x31,0x00,0x79,0x40,0x46,0x08,0x0a,0xe2,0x40,0x05,0x32,0x80,0x00,0x0e,0x26,0x2c,0x2b,0x18,0x92,0x1b,0x1b,0x26,0x00,0x11,0x10,0x11,0x20,0x11,0x03,0x11,0x13, 0x92,0x0e,0x13,0x0f,0x23,0x1f,0x23,0x2f,0x23,0x03,0x23,0x21,0x92,0x26,0x04,0x08,0x02,0xc2,0x0c,0x00,0xc2,0x0e,0x0e,0x2f,0x10,0x2b,0x19,0x29,0x7d,0x1e,0x23,0x1e,0x19,0x19,0x1e,0x23,0x03,0x10,0x2f,0x7d,0x16,0x16,0x33,0x10,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x11,0x12,0x39,0x2f,0xe1, 0xd6,0xe1,0xc6,0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0xfd,0xc6,0x5d,0x12,0x39,0x2f,0xed,0x39,0x39,0x11,0x12,0x39,0x1a,0x10,0xdc,0x1a,0xfd,0xc6,0x31,0x30,0x05,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x27,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22, 0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x10,0x05,0x15,0x16,0x16,0x15,0x14,0x06,0x02,0x4c,0x35,0x5a,0x4c,0x47,0x38,0x32,0x30,0x44,0x2d,0xf1,0x84,0xa8,0xd5,0x9b,0xb7,0xfe,0x8b,0x95,0x89,0x9f,0xaf,0x91,0x7f,0xb4,0xaa,0x9e,0xce,0xcc,0xea,0xfe,0xf0,0x94,0xae,0xd8,0x10,0x56,0x40,0x4f,0x5d,0x16,0x6d,0x19,0x42,0x3e,0x50,0x54,0xb6, 0x7b,0x96,0x7f,0x01,0x14,0x8b,0x8a,0x7e,0x6c,0x82,0x71,0xaa,0x58,0xc2,0x9e,0xfe,0xe9,0x49,0x04,0x11,0xbc,0x8b,0xab,0xe1,0x00,0x01,0x00,0x58,0xfe,0xae,0x03,0x44,0x04,0x18,0x00,0x2e,0x00,0x70,0x40,0x3d,0x08,0x0a,0xe2,0x40,0x05,0x2f,0x80,0x00,0x0e,0x24,0x29,0x28,0x17,0x95,0x40,0x1a,0x24,0x0e,0x1a,0x95,0x2b,0x30,0x11,0x13, 0x95,0x0e,0x16,0x21,0x1f,0x95,0x24,0x10,0x08,0x02,0xc2,0x0c,0x00,0xc2,0x0e,0x0e,0x2c,0x11,0x29,0x18,0x26,0x84,0x1c,0x21,0x1c,0x18,0x18,0x1c,0x21,0x03,0x11,0x2c,0x84,0x15,0x15,0x30,0x11,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xe1,0x11,0x39,0x11,0x12,0x39,0x2f,0xe1,0xd6,0xe1,0xc6,0x00,0x3f,0xfd,0xc6, 0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x11,0x12,0x39,0x1a,0x10,0xdc,0x1a,0xfd,0xc6,0x31,0x30,0x05,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x27,0x26,0x27,0x35,0x16,0x33,0x20,0x35,0x34,0x21,0x23,0x35,0x33,0x20,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x14,0x07,0x15, 0x16,0x16,0x15,0x14,0x06,0x02,0x00,0x33,0x5a,0x4b,0x48,0x38,0x32,0x30,0x44,0x2d,0xc9,0x66,0x86,0xb4,0x01,0x0e,0xfe,0xd7,0x65,0x60,0x01,0x05,0x77,0x68,0x96,0x96,0xaa,0x8e,0x01,0x76,0xd2,0x70,0x8c,0xac,0x12,0x53,0x41,0x4f,0x5d,0x16,0x6d,0x19,0x42,0x3e,0x50,0x04,0x30,0xa2,0x4c,0xac,0xaa,0x8c,0xa2,0x44,0x54,0x4c,0x99,0x3d, 0xfe,0xee,0xbe,0x32,0x04,0x09,0x87,0x6a,0x77,0xa0,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x18,0x00,0x52,0x40,0x2a,0x08,0x11,0x96,0x0b,0x0e,0x0e,0x0d,0x13,0x04,0x18,0x04,0x18,0x01,0x18,0x06,0x16,0x0d,0x03,0x01,0x06,0x10,0x10,0x16,0x11,0x16,0x17,0x17,0x06,0x01,0x00,0x00,0x1a,0x19,0x09,0x0e,0x11,0x18,0x03, 0x06,0x7e,0x0b,0x07,0x2f,0x33,0xe1,0x17,0x32,0xc6,0x11,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x33,0x11,0x12,0x39,0x2f,0x00,0x2f,0x33,0x3f,0x33,0x12,0x39,0x5d,0x11,0x33,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x36,0x37, 0x01,0x33,0x01,0x04,0xa2,0xea,0xfd,0xd6,0x1f,0x07,0x04,0xa8,0xaa,0xaa,0xa8,0xe8,0xe8,0x04,0x0e,0x18,0x02,0x18,0xd1,0xfd,0x99,0x02,0x90,0x25,0x0d,0xfd,0x3e,0x04,0x9c,0x85,0x79,0x79,0x85,0xfe,0x5c,0x16,0x1b,0x02,0x71,0xfd,0x50,0x00,0x00,0x01,0x00,0x27,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x14,0x00,0x4d,0x40,0x27,0x0f,0x06, 0x96,0x0c,0x09,0x09,0x0b,0x00,0x11,0x02,0x14,0x14,0x04,0x12,0x0f,0x01,0x04,0x0e,0x0e,0x12,0x0f,0x07,0x05,0x12,0x13,0x13,0x04,0x01,0x00,0x00,0x16,0x0c,0x0f,0x14,0x03,0x04,0x84,0x09,0x05,0x2f,0x33,0xe1,0x17,0x32,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x33,0x10,0xc6,0x11,0x12,0x39,0x2f,0x00,0x2f,0x33,0x3f,0x11,0x39,0x11,0x33, 0x33,0x3f,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x01,0x33,0x01,0x03,0xf8,0xe6,0xfe,0x3c,0x04,0xa4,0x7f,0x7f,0xa4,0x01,0x54,0xfe,0xac,0x04,0x01,0xae,0xd7,0xfe,0x25,0x01,0xec,0xfe,0x14,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfd,0x79,0x01,0xd5, 0xfe,0x12,0x00,0x01,0x00,0x29,0x00,0x00,0x05,0xac,0x05,0x9a,0x00,0x12,0x00,0x42,0x40,0x20,0x0d,0x04,0x12,0x12,0x06,0x08,0x91,0x10,0x0b,0x03,0x01,0x06,0x10,0x11,0x11,0x06,0x01,0x00,0x00,0x14,0x07,0x09,0x09,0x13,0x12,0x0b,0x06,0x7e,0x07,0x07,0x14,0x13,0x11,0x12,0x39,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f, 0x33,0x12,0x39,0x2f,0x33,0x00,0x2f,0x32,0x3f,0x33,0xed,0x12,0x39,0x11,0x33,0x33,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x05,0xac,0xea,0xfd,0xd6,0x1b,0x0b,0x04,0xa8,0xfe,0x63,0x02,0x45,0x04,0x0e,0x18,0x02,0x18,0xd1,0xfd,0x99,0x02,0x90,0x20,0x12,0xfd,0x3e, 0x05,0x00,0x9a,0xfd,0x5e,0x16,0x1b,0x02,0x71,0xfd,0x50,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x04,0xa4,0x04,0x00,0x00,0x0e,0x00,0x42,0x40,0x20,0x0b,0x02,0x0e,0x0e,0x04,0x06,0x95,0x0c,0x09,0x0f,0x01,0x04,0x0c,0x0d,0x0d,0x04,0x01,0x00,0x00,0x10,0x05,0x07,0x07,0x0f,0x0e,0x09,0x04,0x84,0x05,0x05,0x10,0x0f,0x11,0x12,0x39,0x2f, 0xe1,0x32,0x32,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x33,0x00,0x2f,0x32,0x3f,0x33,0xed,0x12,0x39,0x11,0x33,0x33,0x31,0x30,0x21,0x23,0x01,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x01,0x33,0x01,0x04,0xa4,0xe4,0xfe,0x3e,0x04,0xa4,0xfe,0xc8,0x01,0xdc,0x04,0x01,0xae,0xd9,0xfe,0x23,0x01,0xea,0xfe,0x16, 0x03,0x74,0x8c,0xfe,0x2d,0x01,0xd3,0xfe,0x10,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x06,0x90,0x05,0x9a,0x00,0x0d,0x00,0x3b,0x40,0x1f,0x05,0x91,0x40,0x0a,0x09,0x06,0x0a,0x91,0x2b,0x30,0x01,0x91,0x0c,0x0c,0x09,0x03,0x03,0x06,0x00,0x00,0x0f,0x02,0x7e,0x0b,0x03,0x03,0x0f,0x0a,0x06,0x7e,0x07,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33, 0xe1,0x11,0x39,0x2f,0x00,0x2f,0x33,0x3f,0x33,0x10,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x21,0x06,0x90,0xfe,0x62,0xa8,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0x02,0x46,0x05,0x00,0xfb,0x00,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0x00,0x01,0x00,0xa6, 0x00,0x00,0x05,0x2f,0x04,0x00,0x00,0x0d,0x00,0x3b,0x40,0x1f,0x05,0x95,0x40,0x0a,0x09,0x06,0x0a,0x95,0x2b,0x30,0x01,0x95,0x0c,0x0c,0x09,0x0f,0x03,0x06,0x00,0x00,0x0f,0x02,0x84,0x0b,0x03,0x03,0x0f,0x0a,0x05,0x84,0x07,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xe1,0x11,0x39,0x2f,0x00,0x2f,0x33,0x3f,0x33,0x10,0xed,0x2b,0x00,0x18, 0x2f,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x21,0x05,0x2f,0xfe,0xc9,0xa4,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0x01,0xdb,0x03,0x74,0xfc,0x8c,0x01,0xd1,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4,0x00,0x01,0x00,0xbc,0xfe,0x66,0x07,0xbe,0x05,0x9a,0x00,0x1b,0x00,0x45,0x40,0x27,0x0a,0x91, 0x13,0x13,0x0c,0x0e,0x91,0x11,0x03,0x1a,0x91,0x04,0x01,0x14,0x01,0x24,0x01,0x03,0x01,0x03,0x0c,0x0c,0x0f,0x13,0x0b,0x7e,0x01,0x42,0x0c,0x0c,0x10,0x17,0x7d,0x06,0x06,0x1d,0x0f,0x7e,0x10,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe2,0xe1,0x32,0x00,0x2f,0x33,0x10,0xde,0x32,0x5d,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31, 0x30,0x01,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x00,0x23,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x20,0x00,0x11,0x14,0x00,0x21,0x22,0x04,0x4c,0xa4,0x99,0xbc,0xcd,0xff,0x00,0xda,0x46,0xa8,0xfd,0x1a,0xa8,0x04,0x36,0x4a,0x01,0x26,0x01,0x5c,0xfe,0xd6,0xfe,0xfa,0xae,0xfe,0xb2,0xae,0x6c,0xe7,0xcd,0xd3,0x01,0x29, 0xfd,0x5c,0x05,0x04,0xfa,0xfc,0x05,0x9a,0xfd,0x9e,0xfe,0x99,0xfe,0xdd,0xff,0xfe,0xb7,0x00,0x00,0x01,0x00,0xa6,0xfe,0x66,0x06,0x56,0x04,0x00,0x00,0x1b,0x00,0x44,0x40,0x26,0x0a,0x95,0x14,0x14,0x0c,0x0d,0x95,0x12,0x0f,0x1a,0x95,0x04,0x01,0x14,0x01,0x24,0x01,0x03,0x01,0x03,0x0c,0x0c,0x0f,0x13,0x0b,0x84,0x01,0x0c,0x0c,0x10, 0x17,0x83,0x06,0x06,0x1d,0x0f,0x84,0x10,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x32,0x00,0x2f,0x33,0x10,0xde,0x32,0x5d,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22, 0x03,0x54,0x72,0x8e,0xa7,0xb5,0xda,0xbe,0x20,0xa4,0xfd,0xf6,0xa4,0x03,0x52,0x42,0xf7,0x01,0x25,0xfe,0xeb,0xef,0x99,0xfe,0xa0,0xa4,0x4c,0xb6,0xa8,0xb9,0xd7,0xfe,0x1a,0x03,0x74,0xfc,0x8c,0x04,0x00,0xfe,0x74,0xfe,0xdb,0xf7,0xd5,0xfe,0xe3,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0xb6,0x05,0xb2,0x00,0x3b,0x00,0x4f,0x00,0x4a, 0x40,0x29,0x46,0x7d,0x21,0x1c,0x3a,0x2e,0x03,0x21,0x2b,0x7d,0x3c,0x21,0x0c,0x3c,0x3c,0x0c,0x21,0x03,0x51,0x15,0x7d,0x05,0x31,0x91,0x37,0x13,0x4b,0x1a,0x41,0x91,0x26,0x26,0x1a,0x10,0x91,0x0a,0x04,0x1a,0x91,0x00,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f, 0x2f,0x10,0xed,0x11,0x17,0x39,0x10,0xed,0x31,0x30,0x05,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x02,0x07,0x16,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x26,0x27,0x06, 0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x3e,0x03,0x02,0xff,0x8e,0xf6,0xb5,0x68,0x57,0xa9,0xf8,0xa0,0x24,0x23,0x0e,0x26,0x13,0x73,0xb5,0x7e,0x42,0x44,0x80,0xb6,0x72,0x41,0x3a,0x38,0x57,0x3b,0x1f,0x33,0x5e,0x89,0x55,0x5c,0x8a,0x5c,0x2f,0x76,0x62,0x18,0x32,0x1b,0x31,0x66,0x26,0x50,0x7a,0x42,0x74, 0x35,0x78,0x01,0x33,0x18,0x2f,0x47,0x30,0x31,0x49,0x30,0x18,0x1c,0x35,0x4d,0x31,0x33,0x44,0x29,0x11,0x18,0x5f,0xb7,0x01,0x0f,0xaf,0xaa,0x01,0x17,0xc7,0x6e,0x08,0x99,0x04,0x05,0x53,0x9a,0xdb,0x87,0x81,0xd8,0x9c,0x58,0x0e,0x38,0x8b,0x9c,0xa6,0x52,0x86,0xd2,0x91,0x4c,0x4c,0x91,0xd2,0x86,0xc6,0xfe,0xd4,0x62,0x07,0x07,0x18, 0x16,0x9b,0x28,0x1e,0x1b,0x3d,0x02,0xfb,0x5a,0x97,0x6f,0x3e,0x3c,0x6d,0x9a,0x5f,0x4f,0x96,0x87,0x71,0x29,0x2c,0x76,0x89,0x95,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x55,0x04,0x1a,0x00,0x38,0x00,0x48,0x00,0x54,0x40,0x31,0x1b,0x36,0x1e,0x28,0xef,0x39,0x43,0x84,0x1e,0x4f,0x39,0x01,0x39,0x0c,0x1e,0x1e,0x0c,0x39,0x03,0x4a, 0x14,0x83,0x40,0x05,0x50,0x05,0x60,0x05,0x03,0x05,0x2e,0x95,0x34,0x16,0x46,0x19,0x3e,0x95,0x23,0x23,0x19,0x0f,0x95,0x0a,0x0f,0x19,0x95,0x00,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x3f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x05,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x27,0x06,0x06,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x02, 0x53,0x6a,0xb6,0x86,0x4d,0x43,0x7e,0xb4,0x71,0x1d,0x1a,0x19,0x1e,0x48,0x76,0x53,0x2d,0x2a,0x52,0x77,0x4d,0x1e,0x1c,0x44,0x4d,0x22,0x45,0x69,0x47,0x48,0x69,0x45,0x21,0x4d,0x42,0x0e,0x1d,0x10,0x23,0x4b,0x1c,0x39,0x5c,0x61,0x56,0x2a,0x5c,0x01,0x02,0x10,0x20,0x2c,0x1d,0x21,0x2f,0x1e,0x0e,0x44,0x3f,0x3d,0x35,0x18,0x44,0x85, 0xc4,0x7f,0x7a,0xca,0x91,0x51,0x08,0x8d,0x09,0x3d,0x6b,0x92,0x54,0x57,0x91,0x6a,0x3b,0x03,0x4a,0xd5,0x86,0x44,0x84,0x69,0x41,0x3e,0x67,0x85,0x47,0x86,0xd4,0x4a,0x02,0x03,0x11,0x10,0x88,0x23,0x28,0x14,0x15,0x02,0x25,0x38,0x5b,0x41,0x24,0x28,0x44,0x5a,0x32,0x7e,0xb0,0x31,0x31,0xaf,0x00,0x01,0x00,0x5e,0xfe,0xae,0x04,0x8c, 0x05,0xb2,0x00,0x23,0x00,0x52,0x40,0x2c,0x0a,0x0c,0xe2,0x40,0x07,0x10,0x80,0x02,0x10,0x16,0x30,0x19,0x01,0x19,0x19,0x1b,0x91,0x16,0x04,0x20,0x23,0x01,0x23,0x23,0x21,0x91,0x10,0x13,0x0a,0x0a,0x10,0x0e,0xc2,0x02,0x04,0x04,0x13,0x18,0x00,0x00,0x25,0x1e,0x7d,0x13,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x33,0xf1,0x32, 0xc2,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0xed,0x32,0x2f,0x5d,0x11,0x12,0x39,0x1a,0x10,0xdc,0x1a,0xfd,0xc6,0x31,0x30,0x25,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x27,0x24,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x37,0x04,0x8c,0x72,0xae, 0x34,0x5a,0x4c,0x47,0x38,0x31,0x31,0x44,0x2d,0xfe,0xd1,0xfe,0x99,0x01,0x9e,0x01,0x3e,0xcc,0x86,0x9a,0xba,0xf7,0xfe,0xcd,0x01,0x1f,0xe9,0xd8,0x9e,0x3c,0x3c,0x12,0x54,0x40,0x4e,0x5e,0x16,0x6d,0x19,0x42,0x3e,0x50,0x04,0x01,0x89,0x01,0x3d,0x01,0x58,0x01,0xa8,0x3b,0xb3,0x56,0xfe,0xb6,0xfe,0xec,0xfe,0xfa,0xfe,0xc9,0x60,0x00, 0x00,0x01,0x00,0x60,0xfe,0xae,0x03,0x62,0x04,0x18,0x00,0x23,0x00,0x4c,0x40,0x28,0x15,0x17,0xe2,0x40,0x12,0x24,0x80,0x0d,0x1b,0x21,0x00,0x00,0x02,0x95,0x21,0x10,0x30,0x0a,0x01,0x0a,0x0a,0x08,0x95,0x1b,0x16,0x15,0x15,0x1b,0x19,0xc2,0x0d,0x0f,0x0f,0x0a,0x1e,0x0b,0x00,0x05,0x83,0x1e,0x2f,0xe1,0x2f,0x33,0x11,0x12,0x39,0x2f, 0x33,0xf1,0x32,0xc2,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0xed,0x32,0x2f,0x11,0x12,0x39,0x1a,0x10,0xdc,0x1a,0xfd,0xc6,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x27,0x26,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x03,0x62, 0x72,0x82,0x9d,0xc9,0xbd,0x9f,0x86,0x76,0x58,0x72,0x32,0x59,0x4c,0x47,0x38,0x31,0x31,0x44,0x2e,0xc8,0xf4,0x01,0x22,0xf2,0x87,0x67,0x03,0x3e,0x50,0xe1,0xb7,0xb4,0xd0,0x59,0x9c,0x35,0x0e,0x54,0x3e,0x4f,0x5d,0x16,0x6d,0x19,0x42,0x40,0x50,0x0e,0x01,0x19,0xd7,0xfd,0x01,0x33,0x32,0x00,0x00,0x01,0x00,0x29,0xfe,0x80,0x04,0x0c, 0x05,0x9a,0x00,0x0b,0x00,0x42,0xb9,0x00,0x05,0x01,0x30,0x40,0x14,0x01,0x08,0x91,0x0a,0x03,0x02,0x91,0x40,0x07,0x00,0x0e,0x02,0x09,0x07,0x42,0x09,0x09,0x07,0x0c,0x03,0xb8,0x01,0x2c,0xb7,0x06,0x06,0x02,0x7e,0x07,0x07,0x0d,0x0c,0x11,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f, 0x1a,0xed,0x3f,0xed,0x32,0x3f,0x31,0x30,0x01,0x21,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x04,0x0c,0xfe,0x62,0xc1,0x9b,0xce,0xfe,0x63,0x03,0xe3,0x05,0x02,0xfb,0x96,0xfd,0xe8,0x01,0x80,0x05,0x02,0x98,0x00,0x01,0x00,0x1e,0xfe,0x8a,0x03,0x29,0x04,0x00,0x00,0x0b,0x00,0x42,0xb9,0x00,0x05,0x01,0x31,0x40,0x14,0x01, 0x08,0x95,0x0a,0x0f,0x02,0x95,0x40,0x07,0x00,0x0e,0x02,0x09,0x07,0x42,0x09,0x09,0x07,0x0c,0x03,0xb8,0x01,0x2c,0xb7,0x06,0x06,0x02,0x84,0x07,0x07,0x0d,0x0c,0x11,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a,0xed,0x3f,0xed,0x32,0x3f,0x31,0x30,0x01,0x21,0x11,0x33,0x11,0x23, 0x11,0x23,0x11,0x21,0x35,0x21,0x03,0x29,0xfe,0xcd,0x98,0x8e,0xae,0xfe,0xcc,0x03,0x0b,0x03,0x74,0xfd,0x18,0xfd,0xfe,0x01,0x76,0x03,0x74,0x8c,0x00,0x01,0x00,0x29,0xfe,0x80,0x06,0xbc,0x05,0x9a,0x00,0x0f,0x00,0x50,0xb6,0x09,0x04,0x91,0x0c,0x07,0x03,0x01,0xb8,0x01,0x30,0x40,0x10,0x0e,0x0a,0x91,0x40,0x03,0x05,0x0e,0x03,0x0a, 0x08,0x42,0x08,0x08,0x0b,0x0a,0x0f,0xb8,0x01,0x2c,0x40,0x0d,0x02,0x02,0x0e,0x7e,0x0b,0x0b,0x11,0x0a,0x7e,0x03,0x03,0x11,0x10,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a,0xed,0x32,0x3f,0x3f,0x33,0xed,0x32,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x21, 0x35,0x21,0x15,0x21,0x11,0x21,0x11,0x33,0x11,0x33,0x06,0xbc,0x9b,0xfb,0xa5,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x02,0xe6,0xa8,0xc0,0xfe,0x80,0x01,0x80,0x05,0x02,0x98,0x98,0xfb,0x96,0x05,0x02,0xfa,0xfe,0x00,0x00,0x01,0x00,0x1e,0xfe,0x8b,0x05,0x3c,0x04,0x00,0x00,0x0f,0x00,0x50,0xb9,0x00,0x01,0x01,0x31,0x40,0x16,0x09,0x04,0x95, 0x0c,0x06,0x0f,0x0e,0x0a,0x95,0x40,0x03,0x05,0x0e,0x03,0x0a,0x08,0x42,0x08,0x08,0x0b,0x0a,0x0f,0xb8,0x01,0x2c,0x40,0x0d,0x02,0x02,0x0e,0x84,0x0b,0x0b,0x11,0x0a,0x84,0x03,0x03,0x11,0x10,0x11,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a,0xed,0x32,0x3f, 0x33,0xed,0x32,0x3f,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x21,0x11,0x33,0x11,0x33,0x05,0x3c,0x8e,0xfc,0xa4,0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0x02,0x0a,0xa4,0x98,0xfe,0x8b,0x01,0x75,0x03,0x74,0x8c,0x8c,0xfd,0x18,0x03,0x74,0xfc,0x8c,0x00,0x00,0x01,0x00,0xa6,0xfe,0x80,0x05,0x42,0x05,0x9a,0x00,0x14, 0x00,0x3d,0x40,0x0b,0x10,0x04,0x0e,0x91,0x06,0x06,0x03,0x11,0x0b,0x03,0x01,0xb8,0x01,0x30,0xb3,0x13,0x91,0x03,0x14,0xb8,0x01,0x2c,0x40,0x0b,0x02,0x02,0x12,0x7e,0x04,0x11,0x11,0x16,0x0b,0x7e,0x0a,0x2f,0xe1,0x11,0x39,0x2f,0x33,0xe1,0x32,0x2f,0xe1,0x00,0x2f,0xed,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x32,0x32,0x31,0x30,0x01, 0x23,0x11,0x23,0x11,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x11,0x33,0x05,0x42,0x9c,0xcd,0xe5,0xc5,0xbc,0xcd,0xa8,0xf6,0xb2,0xe3,0xa8,0xc1,0xfe,0x80,0x01,0x80,0x02,0x85,0x79,0xc3,0xb0,0x02,0x1b,0xfd,0xed,0xe7,0x6e,0x02,0x8c,0xfa,0xfe,0x00,0x00,0x01,0x00,0x98,0xfe,0x8b,0x04,0x77,0x04,0x00, 0x00,0x13,0x00,0x3d,0x40,0x0b,0x0f,0x04,0x0d,0xec,0x06,0x06,0x03,0x10,0x0a,0x0f,0x01,0xb8,0x01,0x31,0xb3,0x12,0x95,0x03,0x13,0xb8,0x01,0x2c,0x40,0x0b,0x02,0x02,0x11,0x84,0x04,0x0f,0x0f,0x15,0x0a,0x84,0x09,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x32,0x2f,0xe1,0x00,0x2f,0xed,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x32,0x32,0x31, 0x30,0x01,0x23,0x11,0x23,0x11,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x11,0x33,0x04,0x77,0x8d,0xae,0xb4,0x98,0xfe,0xa8,0xa4,0xc2,0x94,0xaa,0xa3,0x98,0xfe,0x8b,0x01,0x75,0x01,0x9c,0x62,0x01,0x6c,0x01,0x5a,0xfe,0xae,0xe1,0x56,0x01,0xdd,0xfc,0x8c,0x00,0x02,0x00,0x29,0xff,0xe8,0x06,0x58,0x05,0xb2, 0x00,0x1c,0x00,0x23,0x00,0x56,0x40,0x19,0x13,0x0c,0x18,0x01,0x91,0x40,0x23,0x1b,0x09,0x23,0x91,0x2b,0x30,0x20,0x91,0x1b,0x04,0x06,0x04,0x91,0x40,0x09,0x13,0x13,0x15,0xb8,0x01,0x2c,0x40,0x13,0x10,0x0c,0x80,0x06,0x06,0x0c,0x00,0x7d,0x1d,0x1d,0x25,0x0c,0x23,0x42,0x01,0x7d,0x18,0x42,0x0c,0x2f,0xe1,0xf1,0xe1,0x11,0x12,0x39, 0x2f,0xe1,0x11,0x39,0x2f,0x1a,0x10,0xdd,0xe1,0x32,0x00,0x3f,0x1a,0xfd,0xc6,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x33,0x32,0xc4,0x31,0x30,0x01,0x21,0x16,0x00,0x33,0x20,0x37,0x15,0x06,0x21,0x20,0x00,0x03,0x23,0x22,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x33,0x12,0x00,0x21,0x20,0x03,0x26,0x02,0x23,0x22,0x00,0x07, 0x06,0x58,0xfb,0xa2,0x10,0x01,0x1c,0xda,0x01,0x09,0xc2,0xc5,0xfe,0xe4,0xfe,0xda,0xfe,0x95,0x0f,0x1d,0x7c,0x88,0x27,0x8f,0x29,0x84,0x12,0x1d,0x01,0x6f,0x01,0x16,0x02,0x6a,0xb4,0x08,0xe7,0xc9,0xd0,0xfe,0xf6,0x16,0x02,0x7f,0xeb,0xfe,0xeb,0xa4,0xaa,0x91,0x01,0x6a,0x01,0x2d,0x8b,0x7d,0x5e,0x4a,0x47,0x52,0x80,0x01,0x30,0x01, 0x6c,0xfd,0x64,0xed,0x01,0x17,0xfe,0xe4,0xe8,0x00,0x00,0x02,0x00,0x29,0xff,0xe8,0x04,0xc4,0x04,0x18,0x00,0x1e,0x00,0x25,0x00,0x5f,0x40,0x0e,0x13,0x0c,0x0c,0x01,0x95,0x18,0x25,0x25,0x04,0x22,0x95,0x1b,0x10,0x06,0xb8,0xff,0xc0,0x40,0x15,0x09,0x0e,0x48,0x06,0x06,0x04,0x95,0x09,0x16,0x18,0x00,0x0c,0x25,0x1f,0x01,0x06,0x06, 0x00,0x0c,0x13,0x15,0xb8,0x01,0x2c,0x40,0x0a,0x10,0x0c,0x00,0x83,0x1f,0x1f,0x27,0x01,0x83,0x0c,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x10,0xdd,0xe1,0x32,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x3f,0xed,0x32,0x2f,0x2b,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xc4,0x31,0x30,0x01,0x21,0x16,0x16,0x33,0x32,0x37, 0x15,0x06,0x23,0x22,0x02,0x27,0x23,0x22,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x33,0x36,0x24,0x33,0x32,0x12,0x15,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x04,0xc4,0xfd,0x2e,0x04,0xaf,0x9b,0xac,0x91,0x87,0xde,0xd0,0xf7,0x09,0x1b,0x77,0x8d,0x27,0x89,0x29,0x8a,0x14,0x1c,0x01,0x04,0xb0,0xca,0xdc,0xa8,0x01,0x85,0x7a,0x74, 0xa2,0x12,0x01,0xd7,0xab,0xba,0x72,0x9a,0x62,0x01,0x04,0xeb,0x85,0x6f,0x55,0x4a,0x47,0x4a,0x77,0xc8,0xee,0xfe,0xfc,0xe7,0x35,0x8d,0x9f,0xa6,0x86,0x00,0xff,0xff,0x00,0x29,0xfe,0x80,0x06,0x58,0x05,0xb2,0x02,0x26,0x06,0x1d,0x00,0x00,0x00,0x06,0x0b,0x51,0x00,0x00,0xff,0xff,0x00,0x29,0xfe,0x8a,0x04,0xc4,0x04,0x18,0x02,0x26, 0x06,0x1e,0x00,0x00,0x00,0x06,0x0b,0x52,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x01,0x64,0x05,0x9a,0x02,0x06,0x00,0x2c,0x00,0x00,0xff,0xff,0xff,0xea,0x00,0x00,0x07,0x02,0x07,0x1a,0x02,0x26,0x01,0xed,0x00,0x00,0x01,0x07,0x00,0xda,0x02,0x3f,0x01,0x5c,0x00,0x13,0x40,0x0b,0x01,0x00,0x24,0x1e,0x0d,0x00,0x25,0x01,0x21,0x05, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x04,0x00,0x00,0x05,0xf6,0x05,0xbe,0x02,0x26,0x02,0x0d,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0xc7,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x00,0x1c,0x16,0x09,0x00,0x25,0x01,0x19,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x01,0x00,0xbe,0xfe,0x66,0x04,0x4c,0x05,0x9a, 0x00,0x19,0x00,0x42,0x40,0x24,0x01,0x15,0x18,0x91,0x13,0x13,0x15,0x19,0x17,0x03,0x07,0x91,0x04,0x0a,0x14,0x0a,0x24,0x0a,0x03,0x0a,0x0c,0x15,0x19,0x00,0x00,0x04,0x7d,0x0f,0x0f,0x1b,0x01,0x18,0x14,0x7e,0x0a,0x15,0x2f,0x33,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x32,0x2f,0x33,0x00,0x2f,0xde,0x32,0x5d,0xed,0x3f,0x33,0x12,0x39, 0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x01,0x16,0x00,0x11,0x14,0x00,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x00,0x23,0x23,0x11,0x23,0x11,0x33,0x11,0x01,0x04,0x4c,0xfd,0xce,0xfa,0x01,0x1d,0xfe,0xd6,0xfe,0xf9,0xae,0x94,0xa4,0x9a,0xbc,0xcd,0xfe,0xff,0xda,0x46,0xa6,0xa6,0x02,0x17,0x05,0x9a,0xfd,0x97,0x21,0xfe,0xa1, 0xfe,0xfd,0xff,0xfe,0xb7,0x4c,0xae,0x6c,0xea,0xca,0xd6,0x01,0x26,0xfd,0x5c,0x05,0x9a,0xfd,0xa0,0x02,0x60,0x00,0x00,0x01,0x00,0xa6,0xfe,0x66,0x03,0xae,0x04,0x00,0x00,0x1a,0x00,0x42,0x40,0x24,0x01,0x14,0x19,0x95,0x13,0x13,0x14,0x1a,0x17,0x0f,0x07,0xec,0x04,0x0a,0x14,0x0a,0x24,0x0a,0x03,0x0a,0x0c,0x14,0x1a,0x00,0x00,0x04, 0x83,0x0f,0x0f,0x1c,0x17,0x01,0x14,0x84,0x0a,0x15,0x2f,0x33,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x32,0x2f,0x33,0x00,0x2f,0xde,0x32,0x5d,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x01,0x16,0x12,0x15,0x14,0x00,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x33,0x11,0x33, 0x01,0x03,0xae,0xfe,0x4c,0xc8,0xe6,0xfe,0xea,0xee,0x99,0x65,0x72,0x8e,0xa7,0xb5,0xda,0xbe,0x20,0xa4,0xa4,0x02,0x01,0x87,0x04,0x00,0xfe,0x6c,0x20,0xfe,0xe5,0xd9,0xd6,0xfe,0xe4,0x3a,0xa4,0x4c,0xb6,0xa8,0xb9,0xd7,0xfe,0x1a,0x04,0x00,0xfe,0x74,0x01,0x8c,0x00,0x01,0x00,0xbc,0xfe,0x66,0x04,0xf2,0x05,0x9a,0x00,0x18,0x00,0x40, 0x40,0x22,0x0a,0x7e,0x18,0x07,0x18,0x11,0x18,0x11,0x18,0x1a,0x06,0x02,0x7e,0x03,0x11,0x13,0x92,0x0e,0x08,0x03,0x01,0x91,0x06,0x40,0x04,0x03,0x06,0x91,0x2b,0x30,0x04,0x03,0x03,0x12,0x00,0x3f,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xed,0x3f,0x2f,0xed,0x32,0x01,0x2f,0xe1,0x32,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xe1,0x31,0x30, 0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x14,0x07,0x06,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x37,0x36,0x35,0x04,0x4a,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0xa8,0x95,0x94,0xfe,0xf8,0xae,0x94,0xa4,0x9a,0x5e,0x95,0x33,0x67,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfb,0x14,0xff,0xa4,0xa5,0x4c,0xae,0x6c, 0x3a,0x3b,0x74,0xcb,0x00,0x01,0x00,0xa6,0xfe,0x66,0x03,0xf8,0x04,0x00,0x00,0x19,0x00,0x3a,0x40,0x1f,0x0a,0x84,0x07,0x12,0x03,0x19,0x19,0x1b,0x06,0x02,0x84,0x03,0x14,0x95,0x0f,0x08,0x0f,0x01,0x95,0x06,0x40,0x04,0x03,0x06,0x95,0x2b,0x30,0x04,0x0f,0x03,0x15,0x00,0x3f,0x3f,0x2b,0x00,0x1a,0x18,0x10,0xed,0x3f,0x2f,0xed,0x01, 0x2f,0xe1,0x32,0x12,0x39,0x2f,0x12,0x39,0x33,0xe1,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x14,0x06,0x07,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x03,0x54,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0xa4,0x46,0x46,0x8b,0xef,0x9a,0x64,0x75,0x8b,0x54,0x83,0x5a,0x2f,0x01,0xd1,0xfe,0x2f,0x04,0x00, 0xfe,0x5c,0x01,0xa4,0xfc,0x69,0x72,0xbc,0x47,0x8e,0x3a,0xa0,0x4e,0x31,0x5c,0x85,0x54,0x00,0x00,0x01,0x00,0xa6,0xfe,0x80,0x04,0x81,0x05,0x9a,0x00,0x14,0x00,0x38,0xb9,0x00,0x02,0x01,0x30,0x40,0x0f,0x10,0x91,0x08,0x08,0x01,0x13,0x0d,0x03,0x05,0x91,0x01,0x00,0x7e,0x12,0x01,0xb8,0x01,0x2c,0xb7,0x04,0x12,0x06,0x06,0x16,0x0e, 0x7e,0x0b,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xd6,0xe1,0x10,0xe1,0x00,0x2f,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x3f,0x31,0x30,0x21,0x23,0x11,0x23,0x11,0x33,0x11,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x04,0x81,0xd7,0x9c,0xcb,0xe5,0xc5,0xbc,0xcd,0xa8,0xf6,0xb2,0xe3,0xa8,0xfe,0x80,0x02,0x18,0x01, 0xed,0x79,0xc3,0xb0,0x02,0x1b,0xfd,0xed,0xe7,0x6e,0x02,0x8c,0x00,0x01,0x00,0x98,0xfe,0x8a,0x03,0xdf,0x04,0x00,0x00,0x13,0x00,0x3d,0x40,0x0b,0x11,0x06,0x0f,0xec,0x08,0x08,0x01,0x12,0x0c,0x0f,0x02,0xb8,0x01,0x31,0xb3,0x05,0x95,0x01,0x01,0xb8,0x01,0x2c,0x40,0x0b,0x04,0x00,0x84,0x06,0x06,0x11,0x11,0x15,0x0c,0x84,0x0b,0x2f, 0xe1,0x12,0x39,0x2f,0x33,0x10,0xe1,0xd6,0xe1,0x00,0x2f,0xed,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x23,0x11,0x33,0x11,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x03,0xdf,0xb0,0x8b,0x98,0xb4,0x98,0xfe,0xa8,0xa4,0xc2,0x94,0xaa,0xa3,0xfe,0x8a,0x02,0x02,0x01,0x10,0x62, 0x01,0x6c,0x01,0x5a,0xfe,0xae,0xe1,0x56,0x01,0xdd,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x07,0x19,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x55,0x01,0x5b,0x00,0x08,0xb3,0x02,0x13,0x05,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0xbe,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x00,0xda, 0x00,0xc6,0x00,0x00,0x00,0x08,0xb3,0x02,0x23,0x11,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x06,0xe2,0x02,0x26,0x00,0x24,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xe6,0x01,0x5b,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xf2,0x40,0x0a,0x1f,0x19,0x05,0x00,0x25,0x03,0x02,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b, 0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x83,0x05,0x87,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x06,0x00,0x8f,0x62,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x14,0x2f,0x29,0x08,0x14,0x25,0x03,0x02,0x2c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x0a,0x00,0x00,0x06,0x83,0x05,0x9a,0x02,0x06,0x00,0x91, 0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x06,0x56,0x04,0x18,0x02,0x06,0x00,0xa0,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x07,0x1b,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x13,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x12,0x12,0x0c,0x02,0x0b,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00, 0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xdd,0x05,0xbe,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xe5,0x00,0x00,0x00,0x13,0x40,0x0b,0x02,0x00,0x20,0x1a,0x0c,0x12,0x25,0x02,0x1d,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x02,0x00,0x56,0xff,0xe8,0x05,0x66,0x05,0xb2,0x00,0x11,0x00,0x18,0x00,0x3f,0x40,0x23, 0x12,0x91,0x40,0x01,0x09,0x0f,0x01,0x91,0x2b,0x30,0x2f,0x06,0x01,0x06,0x06,0x04,0x91,0x09,0x04,0x16,0x91,0x0f,0x13,0x06,0x06,0x00,0x0c,0x7d,0x01,0x12,0x12,0x1a,0x13,0x7d,0x00,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x5d,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x13,0x21,0x26, 0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x25,0x21,0x16,0x12,0x33,0x32,0x00,0x56,0x04,0x5e,0x11,0xfe,0xe5,0xda,0xd8,0x9c,0x9e,0xe2,0x01,0x3f,0x01,0x6d,0xfe,0x94,0xfe,0xd3,0xfe,0xd1,0xfe,0xb8,0x04,0x5e,0xfc,0x56,0x04,0xf2,0xcf,0xcf,0x01,0x02,0x03,0x1a,0xed,0x01,0x13,0x60,0xa4,0x54,0xfe, 0x76,0xfe,0xa5,0xfe,0xbe,0xfe,0x5d,0x01,0x9f,0xfc,0xeb,0xfe,0xe7,0x01,0x18,0x00,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0xcf,0x04,0x18,0x02,0x06,0x05,0x07,0x00,0x00,0xff,0xff,0x00,0x56,0xff,0xe8,0x05,0x66,0x06,0xe4,0x02,0x26,0x06,0x32,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x2a,0x01,0x5d,0x00,0x1a,0xb1,0x03,0x02,0xb8,0xff,0xec, 0x40,0x0a,0x28,0x22,0x00,0x0c,0x25,0x03,0x02,0x25,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x52,0xff,0xe8,0x03,0xcf,0x05,0x87,0x02,0x26,0x05,0x07,0x00,0x00,0x01,0x06,0x00,0x8f,0x7a,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x0a,0x29,0x23,0x12,0x0c,0x25,0x03,0x02,0x26,0x11,0x26,0x00,0x2b,0x35,0x35,0x01, 0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xea,0x00,0x00,0x07,0x02,0x06,0xe4,0x02,0x26,0x01,0xed,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0xd6,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x2d,0x27,0x0d,0x00,0x25,0x02,0x01,0x2a,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x04,0x00,0x00,0x05,0xf6,0x05,0x87, 0x02,0x26,0x02,0x0d,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x54,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf7,0x40,0x0a,0x25,0x1f,0x09,0x00,0x25,0x02,0x01,0x22,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xe2,0x06,0xe4,0x02,0x26,0x01,0xee,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x61, 0x01,0x5d,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xe0,0x40,0x0a,0x33,0x2d,0x01,0x1f,0x25,0x02,0x01,0x30,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x50,0xff,0xe7,0x03,0x3b,0x05,0x87,0x02,0x26,0x02,0x0e,0x00,0x00,0x01,0x06,0x00,0x8f,0x11,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf6,0x40,0x0a,0x31,0x2b, 0x12,0x16,0x25,0x02,0x01,0x2e,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x01,0x00,0x52,0xff,0xe8,0x03,0xd3,0x05,0x9a,0x00,0x16,0x00,0x3f,0x40,0x20,0x0f,0x96,0x09,0x09,0x15,0x0b,0x91,0x0c,0x03,0x01,0x03,0x91,0x15,0x13,0x0a,0x0f,0x0e,0x09,0x09,0x06,0x01,0x0e,0x0b,0x0e,0x0b,0x01,0x12,0x7d,0x06,0x06,0x18,0x01, 0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x2f,0x12,0x39,0x39,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x01,0x21,0x35,0x21,0x15,0x01,0x32,0x16,0x15,0x14,0x04,0x23,0x22,0x52,0xa8,0xd5,0x9f,0xb3,0xfe,0xa1,0x91,0x01,0x8f,0xfd,0xaa, 0x03,0x56,0xfe,0x7a,0xc0,0xd9,0xfe,0xee,0xf9,0xf2,0x3c,0xb6,0x7b,0xa4,0x83,0x01,0x1e,0x02,0x46,0x98,0x28,0xfd,0xc8,0xdc,0xb6,0xca,0xf6,0x00,0xff,0xff,0xff,0xdd,0xfe,0x21,0x03,0x68,0x04,0x00,0x02,0x06,0x05,0x97,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x06,0x8c,0x02,0x26,0x01,0xef,0x00,0x00,0x01,0x07,0x00,0xd9, 0x01,0xd6,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x14,0x16,0x17,0x0a,0x13,0x25,0x01,0x15,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x00,0x05,0x2f,0x02,0x26,0x02,0x0f,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x1e,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x07,0x10,0x11,0x07,0x0d,0x25,0x01,0x0f,0x11, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x06,0xe4,0x02,0x26,0x01,0xef,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x6f,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x11,0x23,0x1d,0x0a,0x13,0x25,0x02,0x01,0x20,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00, 0x04,0x00,0x05,0x87,0x02,0x26,0x02,0x0f,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xce,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x1b,0x1d,0x17,0x07,0x0d,0x25,0x02,0x01,0x1a,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x06,0xe4,0x02,0x26,0x00,0x32,0x00,0x00,0x01,0x07,0x00,0x8f, 0x01,0x67,0x01,0x5d,0x00,0x17,0x40,0x0d,0x03,0x02,0x03,0x27,0x21,0x03,0x09,0x25,0x03,0x02,0x24,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0x87,0x02,0x26,0x00,0x52,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xb7,0x00,0x00,0x00,0x17,0x40,0x0d,0x03,0x02,0x00,0x27,0x21,0x03, 0x09,0x25,0x03,0x02,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x06,0xe4,0x02,0x26,0x02,0xcf,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x67,0x01,0x5d,0x00,0x17,0x40,0x0d,0x04,0x03,0x03,0x29,0x23,0x03,0x09,0x25,0x04,0x03,0x26,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35, 0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0x87,0x02,0x26,0x02,0xd0,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xb7,0x00,0x00,0x00,0x17,0x40,0x0d,0x04,0x03,0x00,0x27,0x21,0x03,0x09,0x25,0x04,0x03,0x24,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x68,0xff,0xe8,0x04,0x90,0x06,0xe4,0x02,0x26, 0x02,0x04,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0x76,0x01,0x5d,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x9a,0x40,0x0a,0x28,0x22,0x0f,0x14,0x25,0x02,0x01,0x25,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x5a,0x05,0x87,0x02,0x26,0x02,0x24,0x00,0x00,0x01,0x06,0x00,0x8f,0xf0,0x00,0x00,0x1a, 0xb1,0x02,0x01,0xb8,0xff,0xb6,0x40,0x0a,0x28,0x22,0x01,0x14,0x25,0x02,0x01,0x25,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x3c,0xff,0xe7,0x04,0x96,0x06,0x8c,0x02,0x26,0x01,0xfa,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x32,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x05,0x17,0x16,0x0d,0x00,0x25,0x01,0x17,0x05, 0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0x2f,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xc4,0x00,0x00,0x00,0x13,0x40,0x0b,0x01,0x0f,0x17,0x18,0x0c,0x00,0x25,0x01,0x16,0x11,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x3c,0xff,0xe7,0x04,0x96,0x06,0xe4, 0x02,0x26,0x01,0xfa,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xca,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x00,0x25,0x1f,0x0d,0x00,0x25,0x02,0x01,0x22,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x05,0x87,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x06,0x00,0x8f,0x50,0x00,0x00,0x17, 0x40,0x0d,0x02,0x01,0x00,0x24,0x1e,0x0c,0x00,0x25,0x02,0x01,0x21,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x3c,0xff,0xe7,0x04,0x96,0x07,0x5c,0x02,0x26,0x01,0xfa,0x00,0x00,0x01,0x07,0x00,0xde,0x01,0x52,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x4c,0x1c,0x16,0x0d,0x00,0x25,0x02,0x01,0x1c,0x05, 0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x0e,0xfe,0x1e,0x03,0xd5,0x06,0x00,0x02,0x26,0x00,0x5c,0x00,0x00,0x01,0x07,0x00,0xde,0x00,0xf0,0x00,0x00,0x00,0x17,0x40,0x0d,0x02,0x01,0x62,0x1b,0x15,0x0c,0x00,0x25,0x02,0x01,0x1b,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xa6, 0x00,0x00,0x04,0x81,0x06,0xe4,0x02,0x26,0x01,0xfe,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xf6,0x01,0x5d,0x00,0x17,0x40,0x0d,0x02,0x01,0x03,0x20,0x1a,0x08,0x10,0x25,0x02,0x01,0x1d,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x98,0x00,0x00,0x03,0xdf,0x05,0x87,0x02,0x26,0x02,0x1e,0x00,0x00,0x01,0x07, 0x00,0x8f,0x00,0x92,0x00,0x00,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0xf7,0x40,0x0a,0x1f,0x19,0x07,0x0f,0x25,0x02,0x01,0x1c,0x11,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x87,0x06,0xe3,0x02,0x26,0x02,0x02,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x87,0x01,0x5c,0x00,0x17,0x40,0x0d,0x04,0x03, 0x06,0x26,0x20,0x05,0x03,0x25,0x04,0x03,0x23,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x05,0x06,0x05,0x87,0x02,0x26,0x02,0x22,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x33,0x00,0x00,0x00,0x1a,0xb1,0x04,0x03,0xb8,0xff,0xfd,0x40,0x0a,0x25,0x1f,0x05,0x03,0x25,0x04,0x03,0x22,0x11,0x26, 0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0x02,0x00,0x56,0x00,0x00,0x03,0xd1,0x05,0x9a,0x00,0x0a,0x00,0x12,0x00,0x24,0x40,0x12,0x0c,0x91,0x08,0x08,0x09,0x03,0x0b,0x91,0x00,0x00,0x7e,0x08,0x0b,0x0b,0x14,0x0f,0x7d,0x04,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x2f,0xed,0x3f,0x39,0x2f,0xed,0x31,0x30,0x21,0x21,0x22,0x26, 0x35,0x34,0x36,0x33,0x21,0x11,0x33,0x03,0x11,0x23,0x20,0x11,0x14,0x16,0x33,0x03,0xd1,0xfe,0x56,0xd8,0xf9,0xee,0xd4,0x01,0x11,0xa8,0xa8,0xeb,0xfe,0xc8,0xa3,0x95,0xe6,0xc6,0xc1,0xcd,0x02,0x60,0xfa,0xfe,0x02,0x0a,0xff,0x00,0x7d,0x8d,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x10,0x05,0xec,0x02,0x06,0x00,0x47,0x00,0x00,0x00,0x02, 0x00,0x64,0xff,0xe8,0x06,0x58,0x05,0x9a,0x00,0x19,0x00,0x22,0x00,0x3a,0x40,0x1e,0x06,0x08,0x1b,0x91,0x18,0x0f,0x0f,0x11,0x03,0x15,0x20,0x91,0x03,0x08,0x13,0x06,0x12,0x7e,0x0f,0x1a,0x1a,0x0b,0x00,0x7e,0x17,0x17,0x24,0x1e,0x7d,0x0b,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x39,0x00,0x3f,0x33,0xed,0x32,0x3f, 0x39,0x2f,0x33,0xed,0x12,0x39,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x11,0x11,0x33,0x01,0x11,0x23,0x20,0x11,0x10,0x21,0x32,0x36,0x06,0x58,0xd1,0xbf,0x69,0xad,0x2b,0x73,0xed,0xd2,0xf1,0xf2,0xd1,0x01,0x11,0xa7,0x7f,0x6d,0xe5,0xa8,0xfc, 0xe0,0xec,0xfe,0xc8,0x01,0x2a,0x63,0x97,0x01,0x92,0xc8,0xe2,0x63,0x5d,0xc0,0xeb,0xcb,0xc2,0xda,0x02,0x60,0xfb,0xf6,0x79,0x98,0x01,0x1f,0x01,0x9c,0xfe,0x38,0x01,0x30,0xfe,0xf2,0xfe,0xeb,0x82,0x00,0x02,0x00,0x60,0xff,0xe8,0x06,0x70,0x05,0xec,0x00,0x1a,0x00,0x27,0x00,0x3f,0x40,0x21,0x19,0x19,0x0d,0x25,0x11,0x00,0x0f,0x1f, 0x95,0x0d,0x10,0x16,0x05,0x25,0x95,0x03,0x07,0x16,0x05,0x13,0x84,0x11,0x1b,0x1b,0x0a,0x1a,0x83,0x19,0x19,0x29,0x22,0x83,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x39,0x00,0x3f,0x33,0xed,0x32,0x32,0x3f,0xed,0x32,0x3f,0x11,0x12,0x39,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x22,0x02,0x35, 0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x11,0x35,0x33,0x05,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x06,0x70,0xca,0xb6,0xf4,0x4e,0x7c,0xfe,0xf1,0xd9,0xea,0x01,0x00,0xd5,0xd3,0x60,0x04,0xa4,0x7e,0x64,0xd6,0xa8,0xfc,0xfc,0xa4,0x7e,0x96,0xac,0xa6,0x8a,0x89,0xab,0x01,0x83,0xbf, 0xdc,0xe3,0xe3,0x01,0x14,0xec,0xfe,0x01,0x32,0xa6,0x02,0x7a,0xfb,0x95,0x75,0x9a,0x01,0x1a,0xa1,0x5e,0x97,0x7c,0xac,0xdc,0xc2,0xb2,0xcc,0xc6,0x00,0x01,0x00,0x29,0xff,0xe8,0x05,0xf6,0x05,0xb2,0x00,0x24,0x00,0x4b,0x40,0x27,0x1c,0x1b,0x08,0x91,0x0b,0x0b,0x03,0x23,0x23,0x20,0x13,0x11,0x91,0x16,0x04,0x20,0x91,0x03,0x13,0x1c, 0x09,0x19,0x7d,0x0e,0x09,0x0e,0x09,0x13,0x1e,0x7d,0x06,0x06,0x13,0x24,0x7e,0x23,0x23,0x26,0x13,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x11,0x39,0x00,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x12,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x27,0x02,0x21,0x23,0x35, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x10,0x05,0x15,0x04,0x13,0x12,0x33,0x32,0x11,0x11,0x33,0x05,0xf6,0xd2,0xbe,0xb9,0xdd,0x05,0x09,0xfe,0x94,0x96,0x8a,0x9f,0xaf,0x92,0x7f,0xb3,0xab,0x9e,0xcf,0xcc,0xea,0xfe,0xf0,0x01,0x32,0x0f,0x0c,0xdf,0xe6,0xa8,0x01,0x92,0xc9,0xe1,0xeb,0xb9,0x01, 0x14,0x8b,0x8c,0x7c,0x6d,0x81,0x71,0xaa,0x58,0xc3,0x9d,0xfe,0xe9,0x49,0x04,0x26,0xfe,0xce,0xfe,0xe9,0x01,0x1f,0x01,0x9c,0x00,0x01,0x00,0x1e,0xff,0xe8,0x05,0x56,0x04,0x18,0x00,0x22,0x00,0x4b,0x40,0x27,0x22,0x22,0x03,0x1a,0x19,0x09,0x95,0x0a,0x0a,0x1e,0x12,0x10,0x95,0x15,0x10,0x1e,0x95,0x03,0x16,0x1a,0x09,0x17,0x84,0x0d, 0x09,0x0d,0x09,0x12,0x1c,0x84,0x05,0x05,0x12,0x22,0x83,0x21,0x21,0x24,0x12,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x11,0x39,0x00,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x39,0x39,0x12,0x39,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x20,0x03,0x26,0x26,0x23,0x23,0x35,0x33,0x20,0x35,0x34, 0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x14,0x07,0x15,0x16,0x17,0x16,0x33,0x32,0x11,0x35,0x33,0x05,0x56,0xcc,0xb5,0xfe,0xb7,0x3a,0x0e,0x7c,0x9f,0x65,0x61,0x01,0x04,0x77,0x68,0x96,0x96,0xaa,0x8e,0x01,0x77,0xd3,0xda,0x20,0x20,0xbf,0xdb,0xa8,0x01,0x83,0xbf,0xdc,0x01,0x4b,0x52,0x43,0x8c,0xa2,0x44,0x54,0x4c,0x99,0x3d, 0xfe,0xee,0xbd,0x33,0x04,0x12,0xc2,0xcc,0x01,0x1a,0xa1,0x00,0x00,0x01,0x00,0x29,0xfe,0x80,0x04,0x3a,0x05,0xb2,0x00,0x1f,0x00,0x4e,0x40,0x0d,0x1a,0x19,0x07,0x91,0x08,0x08,0x03,0x11,0x0f,0x91,0x14,0x04,0x01,0xb8,0x01,0x30,0x40,0x0e,0x1e,0x91,0x03,0x1a,0x07,0x17,0x7d,0x0c,0x07,0x0c,0x07,0x03,0x11,0x1f,0xb8,0x01,0x2c,0xb7, 0x02,0x02,0x1e,0x7e,0x03,0x03,0x21,0x11,0x2f,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x11,0x39,0x00,0x2f,0xed,0x3f,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x10,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15, 0x10,0x05,0x15,0x16,0x16,0x15,0x15,0x33,0x04,0x3a,0x9c,0xcd,0xfe,0x85,0x96,0x8a,0x9f,0xaf,0x92,0x7f,0xb3,0xab,0x9e,0xcf,0xcc,0xea,0xfe,0xf0,0x93,0xaa,0xc1,0xfe,0x80,0x01,0x80,0x01,0x8c,0x01,0x14,0x8b,0x8c,0x7c,0x6d,0x81,0x71,0xaa,0x58,0xc3,0x9d,0xfe,0xe9,0x49,0x04,0x11,0xbb,0x8e,0xfc,0x00,0x00,0x01,0x00,0x1e,0xfe,0x8b, 0x03,0x8e,0x04,0x18,0x00,0x1d,0x00,0x4e,0x40,0x0d,0x18,0x17,0x07,0x95,0x08,0x08,0x03,0x10,0x0e,0x95,0x13,0x10,0x01,0xb8,0x01,0x31,0x40,0x0e,0x1c,0x95,0x03,0x18,0x07,0x15,0x84,0x0b,0x07,0x0b,0x07,0x03,0x10,0x1d,0xb8,0x01,0x2c,0xb7,0x02,0x02,0x1c,0x84,0x03,0x03,0x1f,0x10,0x2f,0x12,0x39,0x2f,0xe1,0x32,0x2f,0xe1,0x11,0x12, 0x39,0x39,0x2f,0x2f,0xe1,0x11,0x39,0x00,0x2f,0xed,0x3f,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x34,0x21,0x23,0x35,0x33,0x20,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x14,0x07,0x15,0x16,0x16,0x15,0x15,0x33,0x03,0x8e,0x8e,0xae,0xfe,0xd7,0x65,0x61,0x01,0x04,0x77,0x68, 0x96,0x96,0xaa,0x8e,0x01,0x77,0xd3,0x71,0x8b,0x98,0xfe,0x8b,0x01,0x75,0x01,0x1c,0xac,0x8c,0xa2,0x44,0x54,0x4c,0x99,0x3d,0xfe,0xee,0xbd,0x33,0x04,0x09,0x87,0x6a,0x8c,0x00,0x00,0x01,0x00,0x18,0xff,0xe8,0x06,0xc2,0x05,0x9a,0x00,0x1c,0x00,0x3c,0x40,0x20,0x1c,0x1c,0x18,0x07,0x91,0x14,0x03,0x18,0x91,0x03,0x13,0x0e,0x10,0x91, 0x0b,0x13,0x15,0x7e,0x06,0x06,0x1a,0x09,0x7e,0x12,0x00,0x7e,0x1a,0x12,0x1a,0x12,0x1e,0x0e,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xe1,0x10,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11, 0x21,0x11,0x14,0x16,0x33,0x32,0x11,0x11,0x33,0x06,0xc2,0xd2,0xbd,0xba,0xdb,0xfe,0x2d,0xfe,0x97,0x28,0x22,0x1c,0x20,0xd7,0x03,0x1b,0x7e,0x71,0xe5,0xa8,0x01,0x9a,0xcb,0xe7,0xf2,0xb8,0x03,0x70,0xfd,0x36,0xfd,0xb6,0x0a,0x96,0x0b,0x01,0xae,0x03,0x69,0xfc,0x08,0x81,0xa2,0x01,0x21,0x01,0x9a,0x00,0x00,0x01,0x00,0x14,0xff,0xe8, 0x05,0xee,0x04,0x00,0x00,0x1c,0x00,0x46,0x40,0x1a,0x1c,0x1c,0x18,0x07,0x95,0x14,0x0f,0x0e,0x10,0x95,0x0b,0x0b,0x1d,0x18,0x95,0x03,0x16,0x15,0x84,0x06,0x06,0x12,0x1c,0x83,0x1b,0x09,0xb8,0x01,0x2e,0xb6,0x12,0x1b,0x12,0x1b,0x12,0x1e,0x0e,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed, 0x12,0x39,0x7c,0x2f,0x18,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x21,0x11,0x14,0x16,0x33,0x32,0x11,0x35,0x33,0x05,0xee,0xcc,0xb6,0xb1,0xd3,0xfe,0xa4,0xfe,0xc6,0x25,0x19,0x15,0x25,0xa4,0x02,0x9a,0x77,0x67,0xdc,0xa8, 0x01,0x83,0xbd,0xde,0xdd,0xb6,0x01,0xf9,0xfe,0x2a,0xfe,0x54,0x08,0x8b,0x0a,0x01,0x17,0x02,0x6e,0xfd,0x85,0x7f,0x94,0x01,0x1a,0xa1,0x00,0x01,0x00,0xbc,0xff,0xe8,0x07,0x6e,0x05,0x9a,0x00,0x18,0x00,0x41,0x40,0x23,0x17,0x17,0x08,0x91,0x40,0x0d,0x0c,0x09,0x0d,0x91,0x2b,0x30,0x0f,0x0c,0x03,0x14,0x91,0x03,0x13,0x09,0x10,0x7e, 0x0e,0x07,0x07,0x0a,0x00,0x7e,0x16,0x16,0x1a,0x0d,0x08,0x7e,0x0a,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x2f,0x3f,0xed,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x33,0x2f,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x11, 0x11,0x33,0x07,0x6e,0xd3,0xbc,0xba,0xdb,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0xa8,0x7e,0x72,0xe4,0xa8,0x01,0x9a,0xcd,0xe5,0xf2,0xb8,0xfc,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfc,0x08,0x81,0xa2,0x01,0x21,0x01,0x9a,0x00,0x01,0x00,0xa6,0xff,0xe8,0x06,0x5a,0x04,0x00,0x00,0x18,0x00,0x44,0x40,0x24,0x17,0x17,0x03,0x08,0x95,0x40, 0x0d,0x0c,0x09,0x0d,0x95,0x2b,0x30,0x0f,0x0c,0x0f,0x14,0x95,0x03,0x16,0x09,0x11,0x84,0x0e,0x07,0x07,0x0a,0x00,0x83,0x16,0x16,0x1a,0x0d,0x08,0x84,0x0a,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x2f,0x3f,0xed,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x12,0x39,0x7c,0x2f,0x31,0x30,0x01,0x14,0x06,0x23, 0x22,0x26,0x35,0x35,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x11,0x35,0x33,0x06,0x5a,0xcc,0xb5,0xb1,0xd4,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0xa4,0x78,0x67,0xdb,0xa8,0x01,0x83,0xbf,0xdc,0xdc,0xb7,0x56,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4,0xfd,0x85,0x7f,0x94,0x01,0x1a,0xa1,0x00,0x01,0x00,0x5e, 0xff,0xe8,0x05,0x62,0x05,0xb2,0x00,0x1a,0x00,0x3e,0x40,0x22,0x18,0x91,0x19,0x19,0x09,0x14,0x1f,0x0c,0x2f,0x0c,0x02,0x0c,0x0c,0x0e,0x91,0x09,0x04,0x14,0x91,0x03,0x13,0x18,0x0c,0x18,0x0c,0x06,0x00,0x7e,0x17,0x17,0x1c,0x11,0x7d,0x06,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f, 0x5d,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x12,0x37,0x21,0x35,0x21,0x05,0x62,0xfe,0xb5,0xfe,0xdd,0xfe,0xc9,0xfe,0xa1,0x01,0xa5,0x01,0x43,0xea,0x9f,0xae,0xee,0xf1,0xfe,0xcc,0x01,0x07,0xe5,0xcc,0xf2,0x04,0xfe,0x46, 0x02,0x60,0x02,0x8e,0xfe,0xd0,0xfe,0x8a,0x01,0x8a,0x01,0x48,0x01,0x4d,0x01,0xab,0x4c,0xba,0x6e,0xfe,0xb4,0xfe,0xf8,0xfe,0xef,0xfe,0xca,0x01,0x07,0xd8,0x98,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0xf4,0x04,0x18,0x00,0x1a,0x00,0x40,0x40,0x24,0x18,0x95,0x19,0x19,0x09,0x14,0x3f,0x0c,0x4f,0x0c,0x5f,0x0c,0x03,0x0c,0x0c,0x0e, 0x95,0x09,0x10,0x14,0x95,0x03,0x16,0x19,0x0c,0x19,0x0c,0x11,0x1a,0x83,0x17,0x17,0x1c,0x11,0x83,0x06,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x5d,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x02,0x23,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15, 0x14,0x16,0x33,0x32,0x36,0x37,0x21,0x35,0x21,0x03,0xf4,0xe4,0xcc,0xd9,0xfe,0xf5,0x01,0x22,0xf2,0x9c,0x6b,0x77,0x96,0x9d,0xc9,0xb0,0x8e,0x7b,0x89,0x02,0xfe,0x98,0x02,0x10,0x01,0xd3,0xe3,0xfe,0xf8,0x01,0x1b,0xe5,0xfd,0x01,0x33,0x3f,0xa8,0x5d,0xe1,0xb7,0xaf,0xd5,0xa3,0x89,0x8b,0x00,0x00,0x01,0x00,0x29,0xff,0xe8,0x04,0xec, 0x05,0x9a,0x00,0x14,0x00,0x3a,0x40,0x1e,0x13,0x13,0x10,0x0c,0x07,0x91,0x09,0x03,0x10,0x91,0x40,0x03,0x13,0x0b,0x0e,0x0d,0x08,0x06,0x42,0x0d,0x7e,0x06,0x06,0x08,0x00,0x7e,0x12,0x12,0x16,0x08,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xe2,0x00,0x18,0x3f,0x1a,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x31,0x30, 0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x11,0x11,0x33,0x04,0xec,0xd3,0xbd,0xba,0xdc,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x7f,0x71,0xe6,0xa8,0x01,0x9a,0xca,0xe8,0xf1,0xb9,0x03,0x70,0x98,0x98,0xfc,0xa0,0x80,0xa3,0x01,0x21,0x01,0x9a,0x00,0x00,0x01,0x00,0x1e,0xff,0xe8,0x04,0x58, 0x04,0x00,0x00,0x14,0x00,0x3a,0x40,0x1e,0x13,0x13,0x10,0x0c,0x07,0x95,0x09,0x0f,0x10,0x95,0x40,0x03,0x16,0x0b,0x0e,0x0d,0x08,0x06,0x42,0x0d,0x84,0x06,0x06,0x08,0x00,0x83,0x12,0x12,0x16,0x08,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x2b,0x01,0x10,0xe2,0x00,0x18,0x3f,0x1a,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x31,0x30, 0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x11,0x35,0x33,0x04,0x58,0xcc,0xb5,0xb2,0xd3,0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0x78,0x67,0xdb,0xa8,0x01,0x83,0xbf,0xdc,0xdd,0xb6,0x01,0xf9,0x8c,0x8c,0xfe,0x11,0x7f,0x94,0x01,0x1a,0xa1,0x00,0x03,0x01,0x33,0x04,0xc2,0x03,0x7b,0x06,0x3a, 0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x36,0x40,0x1c,0x01,0xe2,0x40,0x02,0x80,0x0a,0x16,0xc1,0x40,0x04,0x10,0x01,0x00,0x01,0x00,0x13,0x0d,0xc0,0x07,0x13,0xc0,0x19,0x1d,0x1c,0x07,0x19,0x2b,0x3a,0x2b,0x01,0x10,0xe1,0x10,0xe1,0x11,0x39,0x39,0x18,0x2f,0x2f,0x00,0x2f,0x33,0x1a,0xfd,0x32,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x21, 0x35,0x21,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x56,0xfe,0x04,0x01,0xfc,0x3e,0x28,0x3a,0x39,0x27,0x2a,0x3b,0x39,0xfe,0x56,0x29,0x3c,0x39,0x2a,0x29,0x3b,0x39,0x05,0xcd,0x6d,0xfe,0x88,0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39,0x2a, 0x2a,0x38,0x39,0x29,0x29,0x3a,0x00,0x03,0x01,0x1c,0x04,0xc2,0x03,0x64,0x06,0xfa,0x00,0x06,0x00,0x12,0x00,0x1e,0x00,0x66,0x40,0x3d,0x06,0x70,0x03,0x01,0x03,0x80,0x09,0x05,0x19,0x05,0x02,0x09,0x05,0x02,0x40,0x09,0x10,0x48,0x02,0x02,0x0d,0x19,0xc1,0x40,0x07,0x13,0x00,0xe0,0x03,0x01,0x03,0x03,0x00,0x05,0x05,0x1c,0x10,0xc0, 0x0a,0x16,0xc0,0x1c,0x00,0x1c,0x01,0x0f,0x0f,0x0a,0x1f,0x0a,0x2f,0x0a,0x03,0x10,0x03,0x20,0x1f,0x0a,0x1c,0x2b,0x3a,0x2b,0x01,0x5f,0x5e,0x5d,0x5e,0x5d,0x10,0xe1,0x10,0xe1,0x12,0x39,0x3d,0x2f,0x33,0x33,0x18,0x2f,0x5d,0x2f,0x00,0x2f,0x33,0x1a,0xed,0x32,0x32,0x2f,0x2b,0x33,0x5e,0x5d,0x1a,0xcd,0x5d,0x32,0x31,0x30,0x01,0x03, 0x23,0x03,0x33,0x17,0x37,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x5a,0xd5,0x85,0xd7,0x73,0xa4,0xa4,0x1e,0x28,0x3a,0x37,0x29,0x2a,0x3a,0x38,0xfe,0x55,0x29,0x3c,0x39,0x2a,0x29,0x3c,0x3a,0x06,0xfa,0xfe,0xb6,0x01,0x4a,0xe6,0xe6,0xfd,0xc8, 0x38,0x2b,0x2a,0x38,0x39,0x29,0x29,0x3a,0x39,0x2a,0x29,0x39,0x39,0x29,0x29,0x3a,0x00,0x03,0x01,0x1c,0x04,0xc2,0x03,0x77,0x06,0xe2,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x44,0xb2,0x03,0x80,0x00,0xb8,0xff,0xc0,0x40,0x20,0x09,0x0c,0x48,0x00,0x00,0x0a,0x16,0xc1,0x04,0x10,0x02,0x40,0x00,0x00,0x19,0x0d,0xc0,0x07,0x13,0xc0,0x19, 0x0f,0x07,0x01,0x10,0x03,0x1d,0x1c,0x07,0x19,0x2b,0x3a,0x2b,0x01,0x5f,0x5e,0x5d,0x10,0xe1,0x10,0xe1,0x12,0x39,0x18,0x2f,0x1a,0xcd,0x00,0x2f,0x33,0xed,0x32,0x32,0x2f,0x2b,0x1a,0xcd,0x31,0x30,0x01,0x23,0x01,0x33,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x02,0xa2,0x7f,0xfe,0xf9,0xa6,0x01,0x50,0x29,0x39,0x3b,0x29,0x2a,0x39,0x3c,0xfe,0x57,0x2a,0x39,0x3b,0x2a,0x27,0x39,0x3a,0x05,0x9a,0x01,0x48,0xfd,0xe0,0x3a,0x29,0x29,0x39,0x39,0x29,0x2a,0x39,0x3a,0x29,0x29,0x39,0x38,0x2a,0x2b,0x38,0x00,0x02,0x01,0x08,0x04,0xc2,0x03,0x04,0x06,0x35,0x00,0x03,0x00,0x0f,0x00,0x32, 0x40,0x1a,0x01,0xe2,0x40,0x02,0x80,0x0a,0xc1,0x40,0x04,0x00,0x0e,0x0d,0x01,0x07,0x42,0x01,0x01,0x07,0xc0,0x0d,0x11,0x10,0x0d,0xc0,0x2b,0x30,0x2b,0x01,0x10,0xe1,0x32,0x18,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a,0xfd,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x03,0x04,0xfe,0x04,0x01,0xfc,0xfe,0x28,0x3a,0x3a,0x28,0x29,0x39,0x39,0x05,0xc8,0x6d,0xfe,0x8d,0x39,0x2a,0x29,0x37,0x37,0x29,0x29,0x3a,0x00,0x00,0x02,0x01,0x23,0x04,0xb2,0x03,0xa4,0x06,0x55,0x00,0x13,0x00,0x17,0x00,0x3c,0x40,0x20,0x15,0xe2,0x40,0x16,0x80,0x13,0x0d,0xda,0x07,0x11,0xda,0x03,0x09,0x17,0x16,0x17, 0x16,0x0a,0x00,0xc4,0x0f,0x13,0x01,0x13,0x13,0x19,0x09,0xc4,0x20,0x0a,0x01,0x0a,0x2f,0x5d,0xe1,0x12,0x39,0x2f,0x5d,0xe1,0x11,0x39,0x39,0x2f,0x2f,0x00,0x2f,0xd6,0xed,0xdc,0xfd,0xc6,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x35,0x37,0x21, 0x35,0x21,0x03,0xa4,0x60,0x52,0x47,0x5b,0x4d,0x2a,0x58,0x5e,0x60,0x56,0x41,0x54,0x4a,0x36,0x54,0x1a,0xfe,0x04,0x01,0xfc,0x05,0xb2,0x69,0x85,0x34,0x2b,0x71,0x6b,0x81,0x34,0x2c,0x74,0x36,0x6d,0x00,0x01,0xff,0x8c,0x05,0x0e,0x03,0x1e,0x05,0xd1,0x00,0x0b,0x00,0x32,0x40,0x19,0x0b,0xdb,0x04,0x08,0x40,0x05,0x01,0x09,0x03,0x03, 0x00,0x0e,0x05,0x0b,0x06,0x42,0x08,0x40,0x0b,0x0c,0x0d,0x06,0x05,0x2b,0x3a,0x2b,0x01,0x18,0x2f,0x1a,0xcd,0x2b,0x01,0x10,0xf0,0xc1,0x18,0x2f,0x00,0x2f,0x33,0x33,0x1a,0xdd,0x32,0xed,0x31,0x30,0x01,0x07,0x23,0x27,0x23,0x07,0x23,0x27,0x23,0x07,0x23,0x27,0x03,0x1e,0x5a,0x22,0x30,0xdc,0x30,0x22,0x30,0xdc,0x30,0x22,0x5a,0x05, 0xd1,0xc3,0x64,0x64,0x64,0x64,0xc3,0x00,0x00,0x02,0xff,0x27,0x04,0x89,0x00,0xbc,0x06,0xa2,0x00,0x14,0x00,0x1e,0x00,0x65,0x40,0x0d,0x02,0x09,0x12,0x09,0x22,0x09,0x03,0x03,0x05,0x0f,0x0f,0x0d,0x0b,0xba,0x01,0x3d,0x00,0x16,0xff,0xf0,0xb6,0x0c,0x0f,0x48,0x16,0x16,0x01,0x0d,0x41,0x0a,0x01,0x3d,0x00,0x12,0x01,0x39,0x00,0x1c, 0x01,0x3d,0x00,0x40,0x00,0x05,0x01,0x3b,0x00,0x01,0x01,0x3a,0xb3,0x0f,0x0f,0x08,0x14,0xb8,0x01,0x3c,0xb4,0x16,0x01,0x0b,0x80,0x1a,0xb9,0x01,0x3c,0x00,0x08,0x2f,0xe1,0x1a,0xdc,0x32,0x32,0xe1,0x11,0x39,0x2f,0x00,0x3f,0x3f,0x1a,0xed,0x3f,0xed,0x11,0x39,0x2f,0x2b,0xed,0x11,0x39,0x2f,0x11,0x39,0x31,0x30,0x5d,0x13,0x23,0x35, 0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x15,0x07,0x35,0x07,0x06,0x06,0x15,0x14,0x33,0x32,0x36,0xbc,0x52,0x02,0x35,0x68,0x4d,0x57,0xaa,0x99,0x6a,0x5d,0x49,0x41,0x6d,0xb4,0x52,0x7c,0x43,0x30,0x62,0x3e,0x4f,0x04,0x96,0x50,0x5d,0x52,0x43,0x8f,0x17,0x17,0x81,0x3e,0x54,0x30,0xbe, 0x7e,0x34,0x13,0x0a,0x2b,0x2d,0x56,0x57,0x00,0x02,0xff,0x21,0x04,0x89,0x00,0xdf,0x06,0xa2,0x00,0x11,0x00,0x17,0x00,0x68,0x40,0x14,0x02,0x01,0x12,0x01,0x22,0x01,0x03,0x0f,0x01,0x1f,0x01,0x2f,0x01,0x03,0x09,0x03,0x05,0x05,0x03,0x01,0xb8,0x01,0x3d,0xb4,0x40,0x17,0x0e,0x08,0x17,0xb8,0x01,0x3d,0xb2,0x2b,0x30,0x14,0xbe,0x01, 0x3d,0x00,0x0e,0x01,0x39,0x00,0x03,0x01,0x3d,0x00,0x08,0x01,0x3b,0xb3,0x05,0x05,0x0b,0x11,0xb8,0x01,0x3c,0xb7,0x60,0x12,0xc0,0x12,0x02,0x12,0x17,0x01,0xb9,0x01,0x3c,0x00,0x0b,0x2f,0xe1,0x32,0xdd,0x71,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x39,0x2f,0x5f,0x5e,0x5d,0x31,0x30,0x5d, 0x13,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x27,0x26,0x23,0x22,0x06,0x07,0xdf,0xfe,0x98,0x04,0xa1,0x57,0x49,0x42,0x70,0x6c,0x7d,0x87,0x64,0x64,0x6f,0x53,0x02,0x7e,0x3a,0x52,0x09,0x05,0x81,0xb2,0x39,0x4e,0x31,0x8c,0x7f,0x78,0x96,0x81,0x75,0x1a,0x96,0x52,0x44,0x00,0x00,0x02, 0xff,0xcb,0x04,0x96,0x00,0x35,0x07,0x83,0x00,0x07,0x00,0x0b,0x00,0x41,0xb9,0x00,0x00,0x01,0x3f,0x40,0x09,0x40,0x04,0x80,0x00,0x0a,0x01,0x0c,0x03,0x0a,0xbc,0x01,0x38,0x00,0x09,0x01,0x3a,0x00,0x0b,0x01,0x3c,0xb3,0x0a,0x02,0x06,0x0a,0xb8,0x01,0x3c,0xb2,0x2b,0x30,0x02,0xb8,0x01,0x3e,0xb1,0x06,0x0d,0x10,0xd4,0xe1,0x2b,0x01, 0x10,0xe1,0x00,0x18,0x3f,0x3f,0x5f,0x5e,0x5d,0x1a,0xdc,0x1a,0xed,0x31,0x30,0x11,0x22,0x35,0x34,0x33,0x32,0x15,0x14,0x03,0x23,0x11,0x33,0x35,0x35,0x35,0x0e,0x52,0x52,0x07,0x18,0x36,0x35,0x35,0x36,0xfd,0x7e,0x02,0x00,0x00,0x00,0x02,0xff,0x04,0x04,0x89,0x00,0xfc,0x06,0xa2,0x00,0x0b,0x00,0x15,0x00,0x29,0x41,0x0e,0x00,0x0c, 0x01,0x3d,0x00,0x06,0x01,0x39,0x00,0x12,0x01,0x3d,0x00,0x00,0x01,0x3b,0x00,0x09,0x01,0x3c,0x00,0x14,0x00,0x0f,0x01,0x3c,0x00,0x03,0x2f,0xe1,0xd4,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x02,0x72,0x88,0x8e,0x78, 0x72,0x80,0x89,0x6f,0x4f,0x5d,0x5c,0x50,0xa4,0x04,0x89,0x90,0x77,0x7f,0x93,0x8e,0x7c,0x7b,0x94,0x01,0xd3,0x6a,0x5e,0x5a,0x6b,0xc7,0xc6,0x00,0x00,0x01,0xff,0x2b,0x04,0x89,0x00,0xd5,0x06,0x96,0x00,0x11,0x00,0x31,0xb1,0x10,0x09,0xb8,0x01,0x38,0xb2,0x0f,0x02,0x0c,0xbe,0x01,0x3d,0x00,0x05,0x01,0x3b,0x00,0x01,0x01,0x3a,0x00, 0x11,0x01,0x3c,0xb2,0x01,0x10,0x09,0xb9,0x01,0x3c,0x00,0x08,0x2f,0xe1,0xd4,0x32,0xe1,0x00,0x3f,0x3f,0xed,0x32,0x32,0x3f,0x33,0x31,0x30,0x13,0x23,0x35,0x23,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0xd5,0x52,0x02,0x33,0x6a,0xb9,0x52,0x7d,0x3c,0x4d,0x52,0x04,0x96,0x52,0x5f,0xdb,0x01,0x32,0xfe, 0xda,0xa1,0x57,0x48,0x01,0x28,0x00,0x01,0xff,0x2b,0x04,0x89,0x00,0xac,0x06,0xa2,0x00,0x15,0x00,0x2a,0xb1,0x00,0x02,0xbf,0x01,0x3d,0x00,0x13,0x01,0x39,0x00,0x0a,0x00,0x08,0x01,0x3d,0x00,0x0d,0x01,0x3b,0xb2,0x00,0x0a,0x05,0xb9,0x01,0x3c,0x00,0x10,0x2f,0xe1,0xc4,0x32,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x31,0x30,0x13,0x26, 0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0xac,0x38,0x41,0x4f,0x65,0x5f,0x4f,0x43,0x3c,0x3d,0x51,0x6d,0x86,0x91,0x79,0x45,0x32,0x06,0x35,0x27,0x6f,0x5b,0x5a,0x69,0x2d,0x4e,0x25,0x8f,0x71,0x7e,0x9b,0x19,0x00,0x02,0xff,0x14,0x04,0x89,0x00,0xec,0x07,0x8c,0x00,0x10, 0x00,0x1c,0x00,0x3e,0xb9,0x00,0x0f,0x01,0x36,0xb3,0x0d,0x03,0x05,0x15,0x41,0x0b,0x01,0x3d,0x00,0x0b,0x01,0x39,0x00,0x1a,0x01,0x3d,0x00,0x05,0x01,0x3b,0x00,0x01,0x01,0x3a,0x00,0x10,0x01,0x3c,0xb3,0x12,0x01,0x0f,0x17,0xb9,0x01,0x3c,0x00,0x08,0x2f,0xe1,0xd4,0x32,0x32,0xe1,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f, 0x31,0x30,0x13,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x11,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x16,0x33,0x32,0x36,0xec,0x52,0x02,0x3a,0x76,0x60,0x74,0x80,0x6a,0x6a,0x30,0x02,0x52,0x52,0x53,0x3f,0xa0,0x54,0x44,0x45,0x55,0x04,0x96,0x58,0x65,0x8b,0x75,0x80,0x99,0x52,0x01,0x3c,0xfd, 0xf1,0x4b,0x3f,0x55,0xce,0x59,0x66,0x64,0x00,0x01,0xff,0x2b,0x04,0x96,0x00,0xd5,0x07,0x8c,0x00,0x11,0x00,0x32,0xb9,0x00,0x0b,0x01,0x36,0xb2,0x0d,0x08,0x04,0xbf,0x01,0x3d,0x00,0x0f,0x01,0x39,0x00,0x01,0x00,0x08,0x01,0x3a,0x00,0x00,0x01,0x3c,0xb2,0x01,0x0b,0x08,0xb9,0x01,0x3c,0x00,0x09,0x2f,0xe1,0x32,0xd4,0xe1,0x00,0x3f, 0x33,0x3f,0xed,0x12,0x39,0x3f,0x31,0x30,0x13,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x15,0xd5,0x52,0x77,0x3d,0x52,0x52,0x52,0x02,0x3b,0x6d,0xae,0x04,0x96,0x01,0x26,0xa0,0x5c,0x48,0xfe,0xde,0x02,0xf6,0xfe,0xb6,0x60,0xd1,0x00,0x01,0xfe,0x96,0x04,0x96,0x01,0x6c,0x06,0xa2,0x00,0x1d, 0x00,0x51,0xb4,0x04,0x15,0x19,0x03,0x0c,0xb8,0x01,0x3d,0xb2,0x40,0x1b,0x17,0xba,0x01,0x39,0x00,0x13,0x01,0x38,0xb2,0x08,0x00,0x10,0xba,0x01,0x3a,0x00,0x00,0x01,0x3c,0xb7,0x01,0x0e,0x08,0x10,0x09,0x42,0x19,0x08,0xb8,0x01,0x3c,0xb4,0x09,0x09,0x1e,0x13,0x10,0xb9,0x01,0x3c,0x00,0x11,0x2f,0xe1,0x32,0x11,0x39,0x2f,0xe1,0x39, 0x2b,0x01,0x10,0xf2,0xe1,0x00,0x18,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x1a,0xed,0x17,0x32,0x31,0x30,0x01,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x15,0x01,0x6c,0x52,0x72,0x35,0x4a,0x52,0x75,0x35,0x45,0x52,0x52,0x02,0x36,0x67, 0x71,0x20,0x3a,0x70,0xaa,0x04,0x96,0x01,0x26,0xa0,0x5e,0x44,0xfe,0xdc,0x01,0x30,0x96,0x59,0x49,0xfe,0xdc,0x02,0x00,0x50,0x5c,0x6a,0x6a,0xd1,0x00,0x01,0xff,0x9c,0x04,0x96,0x00,0xa8,0x06,0xa0,0x00,0x0f,0x00,0x2d,0xb3,0x0a,0x07,0x00,0x02,0xbe,0x01,0x40,0x00,0x0d,0x01,0x39,0x00,0x08,0x01,0x38,0x00,0x07,0x01,0x3a,0xb3,0x00, 0x00,0x09,0x06,0xb9,0x01,0x3c,0x00,0x07,0x2f,0xf1,0x32,0xc2,0x2f,0x00,0x3f,0x3f,0x3f,0xed,0x32,0x12,0x39,0x31,0x30,0x13,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0xa8,0x16,0x2a,0x35,0x45,0x52,0x52,0x02,0x24,0x63,0x1d,0x14,0x06,0x44,0x10,0x64,0x54,0xfe,0xfa,0x02,0x00,0x69,0x73,0x08,0x00, 0x00,0x01,0xff,0x6a,0x04,0x8c,0x00,0x96,0x07,0x2d,0x00,0x13,0x00,0x3a,0xb2,0x0a,0x0e,0x05,0x41,0x09,0x01,0x3d,0x00,0x0b,0x00,0x08,0x01,0x38,0x00,0x13,0x00,0x11,0x01,0x3d,0x00,0x02,0x01,0x3b,0xb6,0x13,0x0d,0x0d,0x0e,0x06,0x0b,0x0e,0xb8,0x01,0x3c,0xb1,0x08,0x05,0x2f,0x33,0xe1,0x32,0xcd,0x10,0xc1,0x2f,0x32,0x00,0x3f,0xed, 0x32,0x3f,0x33,0xed,0x32,0xcd,0x31,0x30,0x13,0x06,0x23,0x22,0x35,0x11,0x23,0x35,0x33,0x35,0x37,0x15,0x33,0x15,0x23,0x11,0x14,0x33,0x32,0x37,0x96,0x1e,0x2e,0x88,0x58,0x58,0x52,0x82,0x82,0x4c,0x1f,0x17,0x04,0x9c,0x10,0x95,0x01,0x2f,0x46,0x7c,0x1b,0x97,0x46,0xfe,0xdf,0x5e,0x11,0x00,0x00,0x01,0xff,0x10,0x04,0x96,0x00,0xf0, 0x06,0x96,0x00,0x0b,0x00,0x5b,0x40,0x0e,0x07,0x40,0x0e,0x11,0x48,0x07,0x18,0x09,0x0d,0x48,0x07,0x02,0x0b,0x04,0xba,0x01,0x38,0x00,0x02,0x01,0x3a,0x40,0x25,0x00,0x0b,0x10,0x0b,0x20,0x0b,0x03,0x0b,0x00,0x0e,0x07,0x0f,0x04,0x1f,0x04,0x2f,0x04,0x03,0x09,0x05,0x04,0x03,0x03,0x07,0x42,0x03,0x01,0x18,0x09,0x0d,0x48,0x00,0x01, 0x02,0x03,0x04,0x07,0x19,0x2f,0x17,0x33,0x2b,0x18,0x2f,0x2b,0x11,0x01,0x33,0x5f,0x5e,0x5d,0x10,0xe0,0x32,0x5d,0x00,0x18,0x3f,0x3f,0x33,0x12,0x39,0x2b,0x2b,0x31,0x30,0x13,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0xf0,0xcd,0x50,0xc3,0x5a,0x84,0x0c,0x04,0x02,0x05,0x0b,0x8a,0x06,0x96,0xfe,0x00,0x02,0x00,0xfe, 0x8d,0x21,0x27,0x26,0x20,0x01,0x75,0x00,0x00,0x01,0xff,0x23,0x04,0x96,0x00,0xdd,0x06,0x96,0x00,0x14,0x00,0x1c,0xbb,0x00,0x0e,0x01,0x38,0x00,0x0a,0x01,0x3a,0x40,0x09,0x0f,0x02,0x1f,0x02,0x2f,0x02,0x03,0x02,0x0b,0x2f,0xc4,0x5d,0x00,0x3f,0x3f,0x31,0x30,0x13,0x03,0x17,0x23,0x27,0x26,0x27,0x23,0x06,0x07,0x07,0x23,0x37,0x03, 0x33,0x17,0x16,0x17,0x33,0x37,0x37,0xdd,0xac,0xaa,0x60,0x65,0x0f,0x07,0x02,0x07,0x0f,0x67,0x5e,0xae,0xa8,0x60,0x63,0x08,0x0e,0x02,0x16,0x69,0x06,0x96,0xfe,0xfe,0xfe,0xa6,0x19,0x0d,0x0e,0x18,0xa6,0xfc,0x01,0x04,0xae,0x0e,0x1c,0x2a,0xae,0x00,0x00,0x01,0x00,0x72,0x03,0xc6,0x01,0x62,0x05,0x9a,0x00,0x03,0x00,0x0d,0xb4,0x02, 0x03,0x03,0x00,0x02,0x2f,0xcd,0x00,0x3f,0xcd,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x62,0x7c,0x74,0x54,0x05,0x9a,0xfe,0x2c,0x01,0xd4,0x00,0x01,0x00,0x72,0xfd,0xfe,0x01,0x62,0xff,0xc6,0x00,0x03,0x00,0x20,0xb9,0x00,0x03,0xff,0xc0,0x40,0x0e,0x0e,0x11,0x48,0x03,0x03,0x04,0x1f,0x02,0x2f,0x02,0x02,0x02,0x00,0x02,0x2f,0xcd,0x00, 0x2f,0x5d,0x12,0x39,0x2f,0x2b,0x31,0x30,0x05,0x03,0x23,0x13,0x01,0x62,0x54,0x9c,0x7e,0x3a,0xfe,0x38,0x01,0xc8,0x00,0x01,0x01,0xba,0xfe,0x40,0x02,0xf6,0xff,0x89,0x00,0x0c,0x00,0x21,0x40,0x11,0x0c,0x0a,0xc3,0x40,0x02,0x80,0x06,0x40,0x09,0x0d,0x48,0x06,0x00,0x00,0x07,0xc2,0x06,0x2f,0xf1,0xc2,0x2f,0x00,0x2f,0x2b,0x1a,0xdc, 0x1a,0xed,0x32,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x37,0x02,0xf6,0x3c,0x56,0x4b,0x5f,0x7b,0x44,0x29,0x29,0xfe,0x90,0x50,0x53,0x46,0xb0,0xba,0x43,0x2a,0x00,0x00,0x01,0x00,0x66,0x02,0x9a,0x02,0x50,0x05,0xc4,0x00,0x11,0x00,0x36,0xbc,0x00,0x0a,0x01,0x07,0x00,0x09,0x00,0x01,0x01,0x0a,0xb2, 0x0a,0x0c,0x04,0xbc,0x01,0x0d,0x00,0x0f,0x01,0x09,0x00,0x00,0x01,0x0c,0xb4,0x01,0x01,0x13,0x0c,0x08,0xb9,0x01,0x0c,0x00,0x09,0x2f,0xe9,0x32,0x12,0x39,0x2f,0xe9,0x00,0x3f,0xed,0x32,0x32,0x3f,0x33,0x3f,0x31,0x30,0x01,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0x7f,0x6d, 0x39,0x45,0x80,0x80,0x02,0x3b,0x79,0xb4,0x02,0x9a,0x01,0x33,0x97,0x54,0x3f,0xfe,0xc9,0x03,0x2a,0xfe,0xa4,0x67,0xe7,0x00,0x00,0x01,0x00,0x66,0x02,0x9a,0x02,0x50,0x05,0xc4,0x00,0x1a,0x00,0x4d,0xb1,0x09,0x01,0xbd,0x01,0x0a,0x00,0x15,0x00,0x04,0x01,0x0d,0x00,0x18,0xff,0xc0,0xb3,0x09,0x0d,0x48,0x18,0xb8,0x01,0x09,0xb2,0x10, 0x10,0x12,0xba,0x01,0x0d,0x00,0x0d,0x01,0x07,0xb3,0x10,0x10,0x08,0x00,0xb8,0x01,0x0c,0xb4,0x01,0x01,0x1c,0x15,0x08,0xb9,0x01,0x0c,0x00,0x09,0x2f,0xe9,0x32,0x12,0x39,0x2f,0xe9,0x11,0x39,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x3f,0x2b,0xed,0x32,0x3f,0x33,0x31,0x30,0x01,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x36, 0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x15,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0x7f,0x6d,0x39,0x45,0x80,0x96,0x87,0x3d,0x3c,0x3a,0x3d,0x9f,0x02,0x3b,0x79,0xb4,0x02,0x9a,0x01,0x33,0x97,0x54,0x3f,0xfe,0xc9,0x02,0x0a,0x88,0x98,0x18,0x68,0x1c,0xb2,0x46,0x67,0xe7,0x00,0x02,0xff,0xbe,0x01,0x98,0x00,0xf6,0x05,0xc4,0x00,0x07, 0x00,0x13,0x00,0x38,0xb2,0x0d,0x0d,0x0f,0xb8,0x01,0x0d,0xb5,0x0a,0x12,0x04,0x00,0x40,0x12,0xb8,0x01,0x08,0x40,0x0b,0x02,0x06,0x0c,0x11,0x08,0x02,0x06,0xff,0x3a,0x0c,0x08,0xb9,0x01,0x0c,0x00,0x11,0x2f,0xe9,0x33,0x2b,0x01,0x18,0x2f,0x2f,0x2f,0x00,0x3f,0x1a,0xde,0xcd,0x10,0xd4,0xed,0x32,0x2f,0x31,0x30,0x13,0x22,0x35,0x34, 0x33,0x32,0x15,0x14,0x03,0x10,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0xa6,0x4e,0x50,0x4e,0x0e,0xda,0x2b,0x25,0x22,0x24,0x64,0x80,0x05,0x2d,0x4c,0x4b,0x4b,0x4c,0xfd,0x79,0xfe,0xf2,0x10,0x68,0x14,0x9e,0x02,0x24,0x00,0x01,0x00,0x66,0x02,0x9a,0x01,0xa8,0x04,0xc8,0x00,0x0e,0x00,0x2d,0xbb,0x00,0x06,0x01,0x0a,0x00, 0x07,0x01,0x08,0xb5,0x0e,0xda,0x00,0x09,0x00,0x02,0xbe,0x01,0x0e,0x00,0x0c,0x01,0x09,0x00,0x09,0x00,0x05,0x01,0x0c,0x00,0x06,0x2f,0xe9,0x32,0x00,0x3f,0xed,0x32,0x32,0x2f,0xed,0x3f,0x3f,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x01,0xa8,0x1e,0x26,0x7e,0x80,0x80,0x02,0x28,0x69, 0x1b,0x14,0x04,0x46,0x12,0xb4,0xfe,0xf6,0x02,0x24,0x6c,0x76,0x08,0x00,0x00,0x01,0x00,0x0a,0x02,0x90,0x01,0x4c,0x04,0xbe,0x00,0x0e,0x00,0x31,0xb5,0x08,0x02,0x08,0x0a,0x52,0x05,0xbc,0x01,0x0b,0x00,0x01,0x01,0x0a,0x00,0x0d,0x01,0x08,0xb3,0x07,0x07,0x0c,0x00,0xb8,0x01,0x0c,0xb3,0x01,0x01,0x10,0x0f,0x11,0x12,0x39,0x2f,0xe9, 0x33,0x33,0x2f,0x00,0x3f,0x3f,0x3f,0xed,0x32,0x32,0x2f,0x31,0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0x01,0x4c,0x7f,0x02,0x29,0x68,0x1c,0x14,0x1e,0x26,0x7f,0x7f,0x02,0x9a,0x6c,0x76,0x08,0x7a,0x12,0xb4,0x01,0x0a,0x00,0x01,0x00,0x0a,0x01,0x94,0x01,0xcf,0x04,0xbe,0x00,0x16,0x00,0x3e, 0xb2,0x16,0x16,0x14,0xb8,0x01,0x0d,0xb7,0x02,0x08,0x0b,0x05,0x0b,0x0d,0x52,0x08,0xba,0x01,0x0b,0x00,0x10,0x01,0x08,0xb5,0x00,0x0a,0x00,0x0a,0x0f,0x12,0xb8,0x01,0x0c,0xb3,0x04,0x04,0x18,0x17,0x11,0x12,0x39,0x2f,0xe9,0x33,0x33,0x32,0x2f,0x2f,0x00,0x3f,0x3f,0xed,0x32,0x32,0x2f,0x10,0xd4,0xed,0x32,0x2f,0x31,0x30,0x01,0x06, 0x23,0x22,0x35,0x35,0x23,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x01,0xcf,0x23,0x40,0x9f,0x02,0x29,0x68,0x1c,0x14,0x1e,0x26,0x7f,0x7f,0x4a,0x1e,0x1b,0x01,0xa6,0x12,0xbe,0xb4,0x76,0x08,0x7a,0x12,0xb4,0x01,0x0a,0xfd,0x9e,0x5e,0x10,0x00,0x02,0x00,0x66,0x02,0x9a,0x02,0x29,0x04,0xbe, 0x00,0x10,0x00,0x17,0x00,0x4d,0xb1,0x03,0x11,0xb8,0x01,0x0d,0xb3,0x0c,0x0c,0x0a,0x12,0xbd,0x01,0x0d,0x00,0x09,0x01,0x0a,0x00,0x00,0x00,0x0a,0x01,0x08,0x40,0x09,0x01,0x0f,0x0f,0x12,0x10,0xc2,0x00,0x00,0x06,0xb8,0x01,0x0c,0xb5,0x15,0x15,0x19,0x04,0x0c,0x12,0xb9,0x01,0x0c,0x00,0x09,0x2f,0xe9,0x32,0x32,0x12,0x39,0x2f,0xe9, 0x32,0x2f,0xe9,0x11,0x39,0x11,0x33,0x00,0x3f,0x33,0x3f,0xed,0x11,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x07,0x06,0x07,0x15,0x16,0x15,0x14,0x23,0x23,0x11,0x33,0x15,0x33,0x32,0x37,0x37,0x03,0x15,0x33,0x32,0x35,0x34,0x23,0x02,0x29,0x47,0x1a,0x36,0x7c,0xdf,0xc9,0x80,0x2a,0x3e,0x1c,0x3c,0xc0,0x43,0x67,0x61,0x04,0xbe,0xa2,0x3c, 0x15,0x03,0x14,0x6e,0xac,0x02,0x24,0xd0,0x43,0x8d,0xfe,0xce,0x90,0x48,0x48,0x00,0x00,0x01,0x00,0x14,0x02,0x9a,0x03,0x18,0x04,0xbe,0x00,0x1b,0x00,0x17,0xbb,0x00,0x0a,0x01,0x0a,0x00,0x0b,0x01,0x08,0xb3,0x00,0x00,0x1d,0x0b,0x2f,0x11,0x33,0x2f,0x00,0x3f,0x3f,0x31,0x30,0x01,0x03,0x23,0x03,0x34,0x27,0x23,0x06,0x07,0x03,0x23, 0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x03,0x18,0x8c,0x9c,0x4a,0x0c,0x04,0x04,0x09,0x51,0x9c,0x88,0x8a,0x48,0x03,0x05,0x04,0x02,0x0a,0x58,0x92,0x50,0x03,0x05,0x04,0x02,0x08,0x4a,0x04,0xbe,0xfd,0xdc,0x01,0x41,0x01,0x45,0x19,0x2b,0xfe,0xbd,0x02,0x24,0xfe,0x9e,0x10,0x36,0x20, 0x28,0x01,0x60,0xfe,0x9e,0x0b,0x3b,0x20,0x26,0x01,0x62,0x00,0x00,0x01,0x00,0x0a,0x01,0x94,0x02,0x2f,0x04,0xbe,0x00,0x14,0x00,0x25,0xb2,0x06,0x06,0x08,0xb8,0x01,0x0d,0xb6,0x11,0x14,0x0b,0x01,0x04,0x03,0x0c,0xb8,0x01,0x08,0xb3,0x00,0x00,0x16,0x0c,0x2f,0x11,0x33,0x2f,0x00,0x3f,0xd4,0x17,0x39,0xed,0x32,0x2f,0x31,0x30,0x01, 0x03,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x37,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x02,0x2f,0xeb,0x48,0xa2,0x22,0x26,0x1e,0x20,0x57,0x24,0x14,0xd5,0x8a,0x78,0x0a,0x06,0x05,0x09,0x09,0x79,0x04,0xbe,0xfd,0x94,0xbe,0x0c,0x6c,0x0e,0x60,0x38,0x02,0x28,0xfe,0xa0,0x1e,0x34,0x37,0x1b,0x01,0x60,0x00,0x00,0x01, 0x00,0x82,0x03,0xdb,0x01,0x5e,0x05,0x9a,0x00,0x03,0x00,0x18,0xb7,0x02,0x03,0x03,0x03,0xbd,0x00,0x00,0x01,0xb9,0x01,0x34,0x00,0x02,0x2f,0xe9,0x32,0x2f,0xe9,0x00,0x3f,0xcd,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x5e,0x68,0x74,0x56,0x05,0x9a,0xfe,0x41,0x01,0xbf,0x00,0x00,0x02,0x00,0x8d,0x03,0xdb,0x02,0x84,0x05,0x9a,0x00,0x03, 0x00,0x07,0x00,0x28,0x40,0x12,0x06,0x03,0x02,0x07,0x04,0x03,0x00,0x00,0x01,0x02,0x02,0x09,0x06,0x07,0x04,0x04,0x05,0x06,0x2f,0xcd,0x32,0x2f,0xcd,0x11,0x12,0x39,0x2f,0xcd,0x32,0x2f,0xcd,0x00,0x3f,0xc4,0x33,0x32,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0x84,0x6a,0x74,0x56,0x93,0x69,0x73,0x55,0x05,0x9a,0xfe, 0x41,0x01,0xbf,0xfe,0x41,0x01,0xbf,0x00,0x00,0x01,0x00,0x6a,0x03,0xf4,0x01,0x6c,0x05,0xb2,0x00,0x03,0x00,0x16,0x40,0x09,0x02,0x03,0x04,0x03,0x00,0x00,0x01,0x01,0x02,0x2f,0x33,0x11,0x33,0x2f,0xcd,0x00,0x3f,0xcd,0x31,0x30,0x01,0x03,0x23,0x13,0x01,0x6c,0x6c,0x96,0x8c,0x05,0xb2,0xfe,0x42,0x01,0xbe,0x00,0xff,0xff,0x00,0x6e, 0x03,0xf4,0x01,0x70,0x05,0xb2,0x00,0x06,0x00,0xb7,0x00,0x00,0x00,0x01,0x00,0x6e,0x03,0xf4,0x01,0x70,0x05,0xb2,0x00,0x03,0x00,0x16,0x40,0x09,0x01,0x02,0x04,0x01,0x00,0x00,0x03,0x03,0x02,0x2f,0x33,0x11,0x33,0x2f,0xcd,0x00,0x3f,0xcd,0x31,0x30,0x01,0x23,0x03,0x33,0x01,0x70,0x74,0x8e,0x94,0x03,0xf4,0x01,0xbe,0x00,0x00,0x01, 0x00,0xfb,0x04,0xc2,0x01,0xaf,0x06,0x2f,0x00,0x0b,0x00,0x22,0x40,0x10,0x05,0xcb,0x40,0x06,0xc0,0x01,0xcb,0x40,0x00,0x00,0x06,0x06,0x80,0x09,0xc9,0x03,0x2f,0xf1,0x1a,0xc8,0x2f,0x32,0x00,0x2f,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x13,0x35,0x32,0x35,0x34,0x23,0x35,0x32,0x16,0x15,0x14,0x06,0xfb,0x5e,0x5e,0x4e,0x66,0x66, 0x04,0xc2,0x5c,0x5b,0x58,0x5e,0x68,0x4e,0x4e,0x69,0x00,0x01,0x00,0xfb,0x04,0xc2,0x01,0xaf,0x06,0x2f,0x00,0x0b,0x00,0x20,0x40,0x0f,0x07,0xcb,0x40,0x06,0xc0,0x0b,0xcb,0x40,0x00,0x00,0x06,0x80,0x09,0xc9,0x03,0x2f,0xe1,0x1a,0xcc,0x32,0x00,0x2f,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x15, 0x22,0x15,0x14,0x33,0x01,0xaf,0x4e,0x66,0x65,0x4f,0x5e,0x5e,0x04,0xc2,0x69,0x4e,0x4d,0x69,0x5e,0x58,0x5b,0x00,0x00,0x01,0x00,0x14,0x02,0x9a,0x01,0xb0,0x05,0xc4,0x00,0x15,0x00,0x2f,0xb1,0x0b,0x09,0xbe,0x01,0x0d,0x00,0x0e,0x01,0x07,0x00,0x01,0x01,0x0a,0x00,0x00,0x01,0x0c,0xb3,0x01,0x01,0x0b,0x11,0xb8,0x01,0x0c,0xb3,0x07, 0x07,0x17,0x0b,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x3f,0xed,0x32,0x31,0x30,0x13,0x23,0x11,0x34,0x36,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0xfc,0x7f,0x24,0x41,0x4d,0x87,0x4a,0x4a,0x4a,0x5a,0x73,0x85,0x6a,0x4a,0x02,0x9a,0x01,0x08,0x40,0x59,0x3c,0x49,0x36, 0x64,0x2b,0x73,0x22,0x6e,0x58,0x62,0x60,0x44,0x56,0x00,0x01,0x00,0x0a,0x02,0x9a,0x01,0xa6,0x05,0xc4,0x00,0x15,0x00,0x2f,0xb1,0x00,0x02,0xbe,0x01,0x0d,0x00,0x13,0x01,0x07,0x00,0x0b,0x01,0x0a,0x00,0x09,0x01,0x0c,0xb6,0x0c,0x0c,0x10,0x00,0x00,0x17,0x04,0xb9,0x01,0x0c,0x00,0x10,0x2f,0xe1,0x11,0x39,0x2f,0x12,0x39,0x2f,0xe1, 0x00,0x3f,0x3f,0xed,0x32,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x14,0x17,0x16,0x16,0x15,0x11,0x23,0x11,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x01,0xa6,0x48,0x52,0x80,0x4f,0x3a,0x29,0x80,0x50,0x64,0x8b,0x73,0x52,0x4c,0x05,0x2f,0x2b,0x5e,0x33,0x50,0x3a,0x58,0x45,0xfe,0xf8,0x01,0x06,0x4c,0x50,0x64,0x5a,0x58,0x72,0x22, 0x00,0x01,0x00,0x72,0x00,0xe4,0x04,0x3c,0x04,0xc2,0x00,0x06,0x00,0x32,0x40,0x16,0x04,0x03,0x0e,0x05,0x20,0x06,0x00,0x05,0x00,0x42,0x00,0x00,0x02,0x01,0x05,0x05,0x01,0x04,0x00,0x00,0x08,0x07,0x11,0x12,0x39,0x2f,0x33,0xcd,0x39,0x00,0x19,0x2f,0x33,0x33,0x33,0x18,0x2f,0x2b,0x11,0x00,0x33,0x1a,0x19,0x10,0xed,0x32,0x31,0x30, 0x25,0x01,0x35,0x01,0x17,0x01,0x01,0x04,0x3c,0xfc,0x36,0x03,0xc8,0x01,0xfc,0xff,0x03,0x00,0xe4,0x01,0x9b,0xa8,0x01,0x9b,0xb2,0xfe,0xc3,0xfe,0xc3,0x00,0x00,0x01,0x00,0x70,0x00,0xe4,0x04,0x3c,0x04,0xc2,0x00,0x06,0x00,0x32,0x40,0x17,0x04,0x05,0x0e,0x03,0x20,0x02,0x01,0x03,0x01,0x42,0x01,0x00,0x01,0x06,0x03,0x03,0x03,0x00, 0x04,0x01,0x01,0x08,0x07,0x11,0x12,0x39,0x2f,0x33,0xcd,0x39,0x00,0x19,0x2f,0x17,0x33,0x18,0x2f,0x2b,0x11,0x00,0x33,0x1a,0x19,0x10,0xed,0x32,0x31,0x30,0x01,0x01,0x35,0x01,0x01,0x35,0x01,0x04,0x3a,0xfc,0x36,0x03,0x02,0xfc,0xfe,0x03,0xcc,0x02,0x7f,0xfe,0x65,0xb2,0x01,0x3d,0x01,0x3d,0xb2,0xfe,0x65,0x00,0x00,0x01,0x00,0x66, 0x00,0xee,0x04,0x46,0x04,0xb8,0x00,0x06,0x00,0x23,0x40,0x0f,0x02,0x05,0x01,0x03,0x06,0x05,0x02,0x02,0x04,0x01,0x00,0x00,0x08,0x03,0x04,0x2f,0x33,0x12,0x39,0x2f,0x33,0x12,0x39,0x11,0x33,0x33,0x00,0x2f,0x33,0xcd,0x32,0x31,0x30,0x25,0x23,0x01,0x01,0x23,0x01,0x33,0x04,0x46,0xb2,0xfe,0xc2,0xfe,0xc2,0xb2,0x01,0x9c,0xa8,0xee, 0x03,0x02,0xfc,0xfe,0x03,0xca,0x00,0x01,0x00,0x66,0x00,0xee,0x04,0x46,0x04,0xb8,0x00,0x06,0x00,0x23,0x40,0x0f,0x06,0x04,0x05,0x02,0x02,0x01,0x05,0x05,0x03,0x06,0x00,0x00,0x08,0x04,0x03,0x2f,0x33,0x12,0x39,0x2f,0x33,0x12,0x39,0x11,0x33,0x33,0x00,0x2f,0x33,0xcd,0x32,0x31,0x30,0x01,0x01,0x23,0x01,0x33,0x01,0x01,0x04,0x46, 0xfe,0x64,0xa8,0xfe,0x64,0xb2,0x01,0x3e,0x01,0x3e,0x04,0xb8,0xfc,0x36,0x03,0xca,0xfc,0xfe,0x03,0x02,0x00,0x01,0x01,0x20,0x04,0x96,0x01,0x8a,0x06,0x00,0x00,0x03,0x00,0x11,0xb3,0x01,0x02,0x01,0x00,0xb9,0x01,0x32,0x00,0x01,0x2f,0xe1,0x00,0x3f,0xcd,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x8a,0x6a,0x6a,0x04,0x96,0x01,0x6a,0x00, 0xff,0xff,0x00,0x87,0x04,0xc2,0x02,0x0c,0x06,0x0a,0x02,0x06,0x00,0x8e,0x00,0x00,0xff,0xff,0x00,0x52,0x04,0xc2,0x01,0xd7,0x06,0x0a,0x02,0x06,0x00,0x43,0x00,0x00,0x00,0x01,0x01,0x20,0xfe,0x1e,0x01,0x8a,0xff,0x89,0x00,0x03,0x00,0x15,0xb5,0x02,0x02,0x04,0x01,0x1c,0x03,0xb9,0x01,0x32,0x00,0x02,0x2f,0xe1,0x00,0x3f,0x12,0x39, 0x2f,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x8a,0x6a,0x6a,0xfe,0x1e,0x01,0x6b,0x00,0x00,0x01,0x00,0x3e,0xff,0x1c,0x02,0x3a,0xff,0x89,0x00,0x03,0x00,0x13,0xb7,0x01,0xe2,0x02,0x04,0x03,0x03,0x05,0x02,0x2f,0x12,0x39,0x2f,0x00,0x10,0xde,0xed,0x31,0x30,0x05,0x21,0x35,0x21,0x02,0x3a,0xfe,0x04,0x01,0xfc,0xe4,0x6d,0x00,0xff,0xff, 0x00,0x52,0xfe,0x43,0x01,0xd7,0xff,0x8b,0x00,0x07,0x00,0x43,0x00,0x00,0xf9,0x81,0xff,0xff,0x00,0x87,0xfe,0x42,0x02,0x0c,0xff,0x8a,0x00,0x07,0x00,0x8e,0x00,0x00,0xf9,0x80,0x00,0x02,0x00,0xb6,0x00,0x00,0x01,0x83,0x04,0x25,0x00,0x03,0x00,0x07,0x00,0x1f,0x40,0x11,0x02,0x63,0x03,0x06,0x63,0x05,0x00,0x42,0x04,0x40,0x13,0x19, 0x48,0x04,0x62,0x03,0x05,0x2f,0x33,0xf1,0x2b,0xe2,0x00,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x07,0x23,0x27,0x13,0x23,0x37,0x33,0x01,0x83,0x5a,0x19,0x5a,0xcc,0xcc,0x5a,0x18,0x04,0x25,0xcd,0xcd,0xfb,0xdb,0xcd,0x00,0x00,0x01,0x00,0xb6,0x01,0xc8,0x01,0x83,0x02,0x96,0x00,0x03,0x00,0x15,0x40,0x0b,0x03,0x63,0x02,0x00,0x40,0x13, 0x19,0x48,0x00,0x62,0x03,0x2f,0xe1,0x2b,0x00,0x2f,0xed,0x31,0x30,0x01,0x07,0x23,0x27,0x01,0x83,0x58,0x1b,0x5a,0x02,0x96,0xce,0xce,0xff,0xff,0x00,0xfb,0x01,0x75,0x01,0xaf,0x02,0xe2,0x00,0x07,0x06,0x84,0x00,0x00,0xfc,0xb3,0xff,0xff,0x00,0xfb,0x01,0x75,0x01,0xaf,0x02,0xe2,0x00,0x07,0x06,0x85,0x00,0x00,0xfc,0xb3,0x00,0x01, 0x00,0xa0,0x01,0x74,0x02,0x0a,0x02,0xe6,0x00,0x07,0x00,0x22,0xb3,0x03,0xc0,0x05,0x02,0xb8,0x01,0x33,0xb5,0x00,0x06,0x06,0x05,0x01,0x05,0xb9,0x01,0x32,0x00,0x02,0x2f,0xe1,0xcd,0x10,0xc9,0x2f,0x00,0x2f,0xed,0x32,0x1a,0xcc,0x31,0x30,0x13,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0xa0,0x7e,0x6e,0x7e,0x01,0x74,0x6b,0x01,0x07,0xfe, 0xf9,0x6b,0x00,0x01,0x00,0xa0,0x01,0x74,0x02,0x0a,0x02,0xe6,0x00,0x07,0x00,0x1f,0x40,0x0e,0x01,0x06,0xe2,0x40,0x07,0xc0,0x04,0x01,0x01,0x02,0x06,0x02,0x50,0x05,0x2f,0xe1,0xcd,0x10,0xc1,0x2f,0x00,0x2f,0x1a,0xdc,0x1a,0xed,0x32,0x31,0x30,0x01,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x02,0x0a,0x7e,0x6e,0x7e,0x02,0xe6,0x6b,0xfe, 0xf9,0x01,0x07,0x6b,0x00,0x01,0x00,0xa0,0x01,0x74,0x02,0x0a,0x02,0xdd,0x00,0x0b,0x00,0x29,0x40,0x13,0x08,0x80,0x01,0x04,0xfd,0x40,0x0a,0x07,0x03,0x00,0x04,0x05,0x05,0x80,0x0a,0x01,0xfc,0x07,0x04,0x2f,0x33,0xf1,0x32,0x1a,0xc8,0x2f,0x10,0xcc,0x00,0x2f,0xde,0x32,0x1a,0xfd,0x32,0x1a,0xce,0x31,0x30,0x01,0x23,0x15,0x23,0x35, 0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x02,0x0a,0x7e,0x6e,0x7e,0x7e,0x6e,0x7e,0x01,0xf4,0x80,0x80,0x6a,0x7f,0x7f,0x00,0x01,0x00,0x3e,0x01,0xf4,0x02,0x3a,0x02,0x60,0x00,0x03,0x00,0x11,0xb6,0x02,0xe2,0x01,0x00,0x00,0x05,0x01,0x2f,0x12,0x39,0x2f,0x00,0x2f,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0x3a,0xfe,0x04,0x01,0xfc,0x01, 0xf4,0x6c,0x00,0x01,0x00,0x79,0x02,0x79,0x02,0x31,0x03,0xc8,0x00,0x0c,0x00,0x3d,0xb7,0x0c,0x0c,0x09,0x01,0x01,0x0b,0x06,0x04,0xb8,0x01,0x35,0x40,0x09,0x09,0x01,0x06,0x40,0x0b,0x0e,0x48,0x06,0x00,0xb8,0xff,0xc0,0x40,0x09,0x09,0x0d,0x48,0x00,0x00,0x01,0x06,0x03,0x0b,0x19,0x2f,0x17,0x33,0x18,0x2f,0x2b,0x2f,0x2b,0x19,0x2f, 0x00,0x18,0x2f,0xed,0x32,0xcd,0x32,0x2f,0x11,0x39,0x2f,0x31,0x30,0x13,0x37,0x17,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x27,0x07,0x79,0xcb,0x20,0x27,0x4e,0x29,0x2f,0x39,0x30,0x7a,0x3c,0x54,0x02,0xf0,0xd8,0x5e,0x74,0x22,0x80,0x1f,0x79,0x56,0x00,0x01,0x00,0x48,0x03,0xa4,0x02,0x68,0x05,0xc4,0x00,0x0b,0x00,0x4a,0x40,0x16, 0x00,0x01,0x04,0x03,0x03,0x06,0x09,0x0a,0x03,0x07,0x02,0x03,0x07,0x08,0x0b,0x05,0xe4,0x05,0xf4,0x05,0x02,0x05,0xb8,0xff,0xe0,0x40,0x15,0x2c,0x30,0x48,0x05,0x00,0x09,0x0a,0x03,0x01,0x04,0x06,0x07,0x03,0x03,0x01,0x02,0x03,0x05,0x0b,0x05,0x08,0x19,0x2f,0x17,0x33,0x11,0x17,0x33,0x11,0x17,0x33,0x00,0x2f,0x2b,0x5d,0x17,0x33, 0x11,0x17,0x33,0x11,0x17,0x33,0x31,0x30,0x01,0x07,0x27,0x07,0x27,0x37,0x27,0x37,0x17,0x37,0x17,0x07,0x02,0x68,0x54,0xbc,0xbc,0x54,0xbc,0xbc,0x54,0xbc,0xbc,0x54,0xbc,0x03,0xf8,0x54,0xbc,0xbc,0x54,0xbc,0xbc,0x54,0xbc,0xbc,0x54,0xbc,0x00,0x02,0x00,0x0a,0x01,0xb8,0x02,0x4c,0x04,0xbe,0x00,0x11,0x00,0x19,0x00,0x4f,0x40,0x12, 0x01,0x0d,0x10,0x12,0x04,0x11,0x0f,0x07,0x16,0x01,0x0d,0x10,0x12,0x04,0x04,0x0a,0x11,0x00,0xb8,0xff,0xc0,0x40,0x10,0x09,0x0c,0x48,0x00,0x00,0x04,0x0f,0x0e,0x40,0x09,0x0c,0x48,0x0e,0x0e,0x0a,0x04,0xbc,0x01,0x34,0x00,0x18,0x00,0x0a,0x01,0x34,0x00,0x14,0x2f,0xe1,0xde,0xe1,0x10,0xc2,0x2f,0x2b,0x32,0x10,0xc2,0x2f,0x2b,0x32, 0x11,0x12,0x17,0x39,0x00,0x2f,0xcd,0xc4,0x32,0x17,0x39,0x31,0x30,0x01,0x03,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x03,0x33,0x13,0x13,0x03,0x06,0x15,0x14,0x33,0x32,0x35,0x34,0x02,0x4c,0xdc,0x19,0x3b,0x5c,0x43,0x45,0x52,0x3d,0x19,0xda,0x8a,0x95,0x99,0x99,0x29,0x29,0x29,0x04,0xbe,0xfe,0x50,0x28,0x5e, 0x3c,0x3a,0x5a,0x52,0x3e,0x37,0x67,0x28,0x01,0xb0,0xfe,0xb9,0x01,0x47,0xfd,0xf6,0x44,0x22,0x34,0x34,0x22,0x00,0x00,0x01,0x00,0x66,0x02,0x9a,0x00,0xe6,0x05,0xc4,0x00,0x03,0x00,0x16,0xbe,0x00,0x02,0x01,0x06,0x00,0x01,0x01,0x0a,0x00,0x00,0x01,0x0c,0x00,0x01,0x2f,0xe1,0x00,0x3f,0x3f,0x31,0x30,0x13,0x23,0x11,0x33,0xe6,0x80, 0x80,0x02,0x9a,0x03,0x2a,0x00,0x00,0x01,0x00,0x3e,0x02,0x89,0x01,0xbc,0x04,0xcf,0x00,0x1d,0x00,0x5d,0x40,0x17,0x25,0x17,0x01,0x17,0x15,0x03,0x0b,0x09,0x1b,0x09,0x2b,0x09,0x03,0x0b,0x07,0x1b,0x07,0x02,0x09,0x07,0x1c,0x10,0x12,0xbf,0x01,0x0d,0x00,0x0d,0x01,0x09,0x00,0x01,0x00,0x03,0x01,0x0d,0x00,0x1c,0x01,0x0b,0xb3,0x10, 0x10,0x0a,0x19,0xb8,0x01,0x0c,0xb4,0x05,0x05,0x1f,0x01,0x14,0xb8,0x01,0x0c,0xb2,0x0a,0x0a,0x01,0x2f,0x33,0x10,0xe1,0x11,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x39,0x5d,0x5d,0x12,0x39,0x39,0x5d,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x36,0x33,0x32, 0x17,0x15,0x26,0x23,0x22,0x15,0x14,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x3e,0x48,0x55,0x63,0x27,0x4a,0x8f,0x79,0x5d,0x47,0x43,0x42,0x4a,0x56,0x60,0x69,0x37,0x7f,0x66,0x4f,0x02,0xac,0x70,0x30,0x39,0x1b,0x21,0x1e,0x38,0x6c,0x4a,0x62,0x1d,0x6e,0x28,0x3d,0x31,0x27,0x2a,0x4e,0x30,0x46,0x60,0x00,0x01,0x00,0x14,0x02,0x9a, 0x02,0x2d,0x04,0xbe,0x00,0x13,0x00,0x17,0xbb,0x00,0x0e,0x01,0x08,0x00,0x0a,0x01,0x0a,0xb3,0x02,0x02,0x15,0x0b,0x2f,0x11,0x33,0x2f,0x00,0x3f,0x3f,0x31,0x30,0x01,0x03,0x13,0x23,0x27,0x26,0x27,0x23,0x06,0x07,0x07,0x23,0x13,0x03,0x33,0x1f,0x02,0x33,0x37,0x02,0x2d,0xb9,0xb7,0x8f,0x62,0x02,0x15,0x05,0x08,0x0e,0x64,0x90,0xbd, 0xae,0x8f,0x5e,0x01,0x14,0x04,0x7d,0x04,0xbe,0xfe,0xf0,0xfe,0xec,0xa4,0x02,0x2a,0x12,0x18,0xa6,0x01,0x0e,0x01,0x16,0xae,0x02,0x28,0xd8,0x00,0xff,0xff,0x00,0x0a,0x02,0x9a,0x01,0xa6,0x05,0xc4,0x02,0x06,0x06,0x87,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x05,0x00,0x1a,0x40,0x0b,0x01,0x03,0x04,0x04, 0x03,0x03,0x00,0x01,0x01,0x07,0x06,0x11,0x12,0x39,0x2f,0xcd,0x33,0x2f,0x00,0x3f,0xcd,0x2f,0x31,0x30,0x21,0x23,0x11,0x21,0x35,0x21,0x02,0x7a,0x9c,0xfe,0xb8,0x01,0xe4,0x05,0x1e,0x9c,0x00,0x01,0x00,0x96,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x1e,0x40,0x0d,0x01,0x03,0x04,0x06,0x04,0x03,0x03,0x05,0x00,0x01,0x01,0x09, 0x08,0x11,0x12,0x39,0x2f,0xcd,0x33,0x33,0x2f,0x00,0x3f,0x2f,0xcd,0x2f,0x31,0x30,0x21,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x01,0x48,0x9c,0x03,0xd5,0x9d,0x01,0x48,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x1e,0x40,0x0d,0x01,0x06,0x04,0x03,0x04,0x03,0x03,0x05,0x00,0x01, 0x01,0x09,0x08,0x11,0x12,0x39,0x2f,0xcd,0x33,0x33,0x2f,0x00,0x2f,0xcd,0x3f,0x2f,0x31,0x30,0x21,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x01,0x48,0x9c,0x02,0x90,0x9b,0x02,0x8f,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x1e,0x40,0x0d,0x01,0x06,0x04,0x03,0x04,0x03,0x03,0x05, 0x00,0x01,0x01,0x09,0x08,0x11,0x12,0x39,0x2f,0xcd,0x33,0x33,0x2f,0x00,0x2f,0xcd,0x3f,0x2f,0x31,0x30,0x21,0x23,0x11,0x21,0x35,0x21,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x01,0x48,0x9c,0x01,0x48,0x9c,0x03,0xd6,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x05,0x00,0x1a,0x40,0x0b,0x01,0x02,0x05,0x04,0x02,0x02, 0x05,0x04,0x04,0x07,0x06,0x11,0x12,0x39,0x2f,0xcd,0x33,0x2f,0x00,0x3f,0x2f,0xcd,0x31,0x30,0x21,0x21,0x35,0x21,0x11,0x33,0x02,0x79,0xfe,0x1d,0x01,0x48,0x9c,0x9c,0x05,0x1e,0x00,0x01,0x00,0x62,0x00,0x00,0x02,0x48,0x03,0x70,0x00,0x05,0x00,0x10,0xb5,0x02,0x04,0x01,0x05,0x04,0x01,0x2f,0xcd,0x2f,0x00,0x2f,0xcd,0x2f,0x31,0x30, 0x21,0x21,0x11,0x33,0x03,0x21,0x02,0x48,0xfe,0x1a,0x5e,0x02,0x01,0x8a,0x03,0x70,0xfc,0xee,0x00,0x01,0x00,0x62,0x00,0x00,0x02,0x48,0x03,0x70,0x00,0x07,0x00,0x19,0x40,0x0a,0x03,0x04,0x01,0x06,0x00,0x00,0x09,0x06,0x02,0x03,0x2f,0xcd,0x32,0x11,0x39,0x2f,0x00,0x2f,0xcd,0x2f,0x2f,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x33,0x03, 0x21,0x02,0x48,0xfe,0x78,0x5e,0x5e,0x02,0x01,0x8a,0x01,0x89,0xfe,0x77,0x03,0x70,0xfe,0x78,0x00,0x01,0x00,0x3c,0xfe,0x40,0x02,0x6e,0xff,0x89,0x00,0x06,0x00,0x1c,0x40,0x0e,0x00,0x00,0x08,0x03,0x02,0x80,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x00,0x2f,0x5d,0x1a,0xcd,0x01,0x2f,0x12,0x39,0x2f,0x31,0x30,0x05,0x03,0x23,0x03, 0x33,0x17,0x37,0x02,0x6e,0xd6,0x84,0xd8,0x73,0xa4,0xa4,0x77,0xfe,0xb7,0x01,0x49,0xe5,0xe5,0x00,0x02,0x00,0x00,0x04,0x5c,0x03,0x52,0x05,0xec,0x00,0x03,0x00,0x07,0x00,0x22,0x40,0x13,0x05,0xd9,0x00,0x06,0x10,0x06,0x20,0x06,0x03,0x06,0x06,0x01,0xd9,0x02,0x00,0x04,0x01,0x00,0x05,0x2f,0xc4,0x33,0x32,0x00,0x3f,0xed,0x33,0x2f, 0x5d,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x03,0x52,0xfc,0xae,0x03,0x52,0xfc,0xae,0x03,0x52,0x05,0x74,0x78,0xfe,0x70,0x77,0x00,0x02,0x00,0x6e,0x03,0xf4,0x02,0xa0,0x05,0xb2,0x00,0x03,0x00,0x07,0x00,0x33,0x40,0x0a,0x02,0x03,0x06,0x07,0x04,0x03,0xea,0x00,0x00,0x01,0xb8,0x01,0x34,0x40,0x09,0x02,0x02,0x09, 0x06,0x07,0xea,0x04,0x04,0x05,0xb9,0x01,0x34,0x00,0x06,0x2f,0xe9,0x32,0x2f,0xe9,0x11,0x12,0x39,0x2f,0xe9,0x32,0x2f,0xe9,0x00,0x3f,0xcd,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0xa0,0x8c,0x76,0x6c,0x9a,0x8c,0x76,0x6f,0x05,0xb2,0xfe,0x42,0x01,0xbe,0xfe,0x42,0x01,0xbe,0x00,0x01,0xff,0x3a,0xfe,0x1e, 0x01,0x4a,0x04,0x00,0x00,0x0c,0x00,0x3a,0x40,0x19,0x0b,0x0f,0x06,0x06,0x08,0x03,0x08,0x95,0x59,0x03,0x1c,0x06,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x84,0x0a,0xb8,0xff,0xfe,0xb6,0x0c,0x06,0x4d,0x0a,0x0a,0x0e,0x0d,0x11,0x12,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0xc6,0x00,0x3f,0x2b,0x11,0x00,0x33,0x18,0x2f,0x3f, 0x31,0x30,0x25,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x01,0x4a,0xcb,0xbd,0x46,0x42,0x4a,0x42,0xe0,0xa4,0x2b,0xfc,0xfe,0xef,0x20,0x99,0x2d,0x01,0x66,0x03,0xf0,0x00,0x01,0x00,0x0a,0x00,0x00,0x02,0x0e,0x04,0x00,0x00,0x0b,0x00,0x2d,0x40,0x17,0x01,0x0a,0x04,0x95,0x40,0x07,0x08,0x03,0x07,0x95,0x30,0x30, 0x08,0x0f,0x03,0x00,0x00,0x09,0x08,0x02,0x84,0x05,0x03,0x2f,0xc6,0xf1,0x39,0x39,0xc2,0x2f,0x00,0x2f,0x3f,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x02,0x0e,0xb0,0xa4,0xb0,0xb0,0xa4,0xb0,0x01,0xdb,0xfe,0x25,0x01,0xdb,0x8b,0x01,0x9a,0xfe,0x66,0x00,0x01, 0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x4a,0x40,0x2e,0x74,0x06,0x84,0x06,0x02,0x36,0x06,0x46,0x06,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x00,0x04,0x10,0x04,0x02,0x04,0x34,0x07,0x44,0x07,0x54,0x07,0x74,0x07,0x84,0x07,0x94,0x07,0x06,0x07,0x02,0x04,0x06,0x08,0x02,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12, 0x39,0x2f,0x10,0xd4,0xcd,0x12,0x39,0x5d,0x01,0x2f,0x5d,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x5d,0x31,0x30,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0x65,0x01,0x2a,0x9c,0x03,0xd6,0x01,0x48,0x9c,0xfe,0xd6,0x01,0x2a,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba, 0x00,0x09,0x00,0x5a,0x40,0x39,0x24,0x03,0x01,0x16,0x03,0x01,0x94,0x06,0xa4,0x06,0x02,0x72,0x06,0x01,0x43,0x06,0x01,0x14,0x06,0x24,0x06,0x34,0x06,0x03,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x00,0x04,0x10,0x04,0x02,0x04,0x03,0x06,0x08,0x90,0x07,0xa0,0x07,0x02,0x84,0x07,0x01,0x70,0x07,0x01,0x07,0x02,0x02,0x01,0x08,0x01,0x00, 0x2f,0x2f,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x10,0xd4,0xcd,0x01,0x2f,0x5d,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0xa1,0xee,0x9c,0x02,0x8f,0x02,0x8f,0x9c,0xfe,0x07,0x01,0xf9,0x00,0x01,0x00,0x96, 0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x44,0x40,0x29,0x04,0x06,0x14,0x06,0x94,0x06,0xa4,0x06,0x04,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x00,0x04,0x10,0x04,0x02,0x04,0x03,0x06,0x09,0xa1,0x07,0x01,0x70,0x07,0x80,0x07,0x90,0x07,0x03,0x07,0x02,0x02,0x01,0x09,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x10,0xd4, 0xcd,0x01,0x2f,0x5d,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x31,0x30,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0xa1,0xee,0x9c,0x01,0x47,0x03,0xd7,0x9c,0xfd,0x37,0x02,0xc9,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x38,0x40,0x20,0xa6,0x05,0x01,0x02, 0x05,0x03,0x01,0x06,0x08,0x0a,0x00,0x03,0x10,0x03,0x02,0x03,0x02,0x05,0x07,0xa0,0x06,0x01,0x91,0x06,0x01,0x70,0x06,0x80,0x06,0x02,0x06,0x01,0x00,0x2f,0x33,0x5d,0x5d,0x5d,0x2f,0xd4,0xcd,0x01,0x2f,0x5d,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x31,0x30,0x21,0x23,0x01,0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8, 0xfe,0xb9,0x01,0xa1,0xee,0x9c,0x05,0x1e,0x9c,0xfc,0x4a,0x03,0xb6,0x00,0x00,0x01,0x00,0x43,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x56,0x40,0x33,0xb7,0x06,0x01,0x03,0x06,0x04,0xb6,0x07,0x01,0x99,0x07,0x01,0x07,0x02,0x08,0x0a,0x05,0x04,0xb7,0x04,0x01,0xa8,0x04,0x01,0x04,0x05,0x08,0x93,0x06,0x01,0x86,0x06,0x01,0x77, 0x06,0x01,0x06,0x03,0x03,0x01,0xc6,0x02,0x01,0x48,0x02,0x58,0x02,0x02,0x02,0x08,0x01,0x00,0x2f,0x2f,0x33,0x5d,0x5d,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x10,0xc4,0x32,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x5d,0x5d,0x12,0x39,0x39,0x5d,0x31,0x30,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb8, 0xfe,0x66,0x53,0x01,0x47,0x01,0x48,0x9c,0x05,0x0a,0xfe,0xcc,0x01,0x85,0x5f,0xfe,0xcc,0x01,0x34,0x00,0x00,0x01,0x00,0x43,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x32,0x40,0x18,0xaa,0x03,0x01,0x56,0x06,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x06,0x02,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12, 0x39,0x2f,0xcd,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x5d,0x31,0x30,0x21,0x23,0x11,0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x9a,0xfe,0x84,0x53,0x01,0x47,0x01,0x48,0x9c,0x03,0xd6,0x01,0x85,0x5f,0xfe,0xb8,0x01,0x48,0x00,0x01,0x00,0x43,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07, 0x00,0x42,0x40,0x26,0x02,0x05,0x07,0x09,0x04,0x03,0xb6,0x03,0x01,0x03,0x04,0x06,0xc8,0x05,0x01,0x93,0x05,0x01,0x74,0x05,0x01,0x65,0x05,0x01,0x46,0x05,0x56,0x05,0x02,0x37,0x05,0x01,0x05,0x02,0x02,0x01,0x06,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x10,0xc4,0x32,0x5d,0x01,0x2f,0x33,0x10,0xde, 0xdd,0xc4,0x31,0x30,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfd,0x1e,0x53,0x02,0x8f,0x9c,0x02,0x8f,0x02,0xcc,0x5f,0xfd,0x8f,0x02,0x71,0x00,0x01,0x00,0x43,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x42,0x40,0x23,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0xb6,0x03,0x01,0x9b,0x03,0x01,0xa7,0x06,0x01, 0x56,0x06,0x01,0x03,0x06,0x02,0xb6,0x04,0x01,0x04,0x05,0x08,0x07,0x02,0x02,0x08,0x00,0x00,0x2f,0x2f,0x39,0x2f,0x33,0x10,0xc4,0x32,0x5d,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x66,0x53, 0x01,0x9a,0xf5,0x9c,0x01,0x47,0x02,0x8f,0x01,0x85,0x5f,0xfe,0x7e,0xfe,0x0f,0x03,0x73,0x00,0x00,0x01,0x00,0x43,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x42,0x40,0x25,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x04,0x03,0xb6,0x02,0x01,0x96,0x05,0x01,0x67,0x05,0x77,0x05,0x02,0x55,0x05,0x01,0x02,0x05,0x01,0xb6,0x03,0x01,0x03, 0x04,0x07,0x90,0x06,0x01,0x06,0x01,0x00,0x2f,0x33,0x5d,0x2f,0xc4,0x32,0x5d,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x01,0x01,0x37,0x01,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x66,0x53,0x01,0xae,0xe1,0x9c,0x03,0xd6,0x01,0x85,0x5f,0xfe,0x6a,0xfd,0x5e, 0x04,0x38,0x00,0x01,0x00,0x43,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x36,0x40,0x1e,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0x01,0x03,0xb6,0x03,0x01,0x03,0x04,0x06,0x84,0x05,0x94,0x05,0x02,0x56,0x05,0x66,0x05,0x02,0x05,0x02,0x02,0x06,0x00,0x00,0x2f,0x2f,0x39,0x2f,0x33,0x5d,0x5d,0x10,0xc4,0x32,0x5d,0x01,0x2f,0x5d,0x33, 0x10,0xde,0xdd,0xc4,0x31,0x30,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x65,0x53,0x01,0x48,0x9c,0x03,0xd6,0x01,0x85,0x5f,0xfe,0xcc,0x01,0x34,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x76,0x40,0x4a,0x68,0x07,0x01,0x88,0x04,0x01,0x83,0x03,0x01,0x77,0x03,0x01,0x58,0x03,0x68,0x03, 0x02,0x04,0x03,0x34,0x03,0x44,0x03,0x03,0x77,0x06,0x01,0x03,0x03,0x06,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0xc7,0x04,0x01,0x26,0x04,0x01,0x04,0x05,0x07,0x93,0x06,0xa3,0x06,0x02,0x02,0x83,0x06,0x01,0x74,0x06,0x01,0x27,0x06,0x01,0x06,0x03,0x03,0x01,0x7b,0x02,0x01,0x48,0x02,0x01,0x02,0x07,0x01,0x00,0x2f,0x2f,0x33,0x5d,0x5d, 0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x5f,0x5d,0x10,0xc4,0x32,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x00,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x67,0x01,0x47,0x01,0x48,0x9c,0x04,0xc4,0xfd,0xcb,0x02,0xe4, 0x47,0xfd,0xcb,0x02,0x35,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x66,0x40,0x40,0x86,0x03,0xc6,0x03,0xd6,0x03,0xe6,0x03,0x04,0x58,0x03,0x68,0x03,0x02,0x36,0x03,0x46,0x03,0x02,0x04,0x03,0x01,0x85,0x06,0x95,0x06,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0xb6,0x04,0x01,0x79,0x04,0x01, 0x04,0x05,0x08,0xa2,0x06,0x01,0x74,0x06,0x94,0x06,0x02,0x06,0x03,0x07,0x02,0x03,0x02,0x03,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x5d,0x5d,0x10,0xc4,0x32,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x21,0x23,0x11,0x01,0x01,0x37, 0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x67,0x01,0x61,0x01,0x2e,0x9c,0x03,0xd6,0xfe,0xb9,0x02,0xe4,0x47,0xfd,0xa0,0x01,0x40,0x01,0x20,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x3e,0x40,0x22,0x9c,0x03,0x01,0x79,0x03,0x89,0x03,0x02,0xa6,0x06,0x01,0x57,0x06,0x67,0x06,0x02,0x03,0x06, 0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x06,0x02,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0xcd,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x21,0x23,0x11,0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x67,0x01,0x7d,0x01,0x12, 0x9c,0x02,0x8f,0x02,0xe4,0x47,0xfd,0x71,0x02,0x8f,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5d,0x40,0x37,0xa3,0x06,0x01,0x02,0x9a,0x02,0xaa,0x02,0x02,0x7b,0x02,0x8b,0x02,0x02,0x68,0x02,0x01,0x5b,0x02,0x01,0x4a,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x91,0x06,0x01,0x85,0x06,0x01, 0x76,0x06,0x01,0x03,0x06,0x02,0x04,0x05,0x08,0x37,0x07,0x01,0x07,0x02,0x02,0x08,0x00,0x00,0x2f,0x2f,0x39,0x2f,0x33,0x5d,0x10,0xc4,0x32,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x17,0x11,0x33,0x03, 0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x67,0x01,0x97,0xf8,0x9c,0x01,0x47,0x01,0x48,0x02,0xe4,0x47,0xfd,0x40,0xf9,0x03,0xb9,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x06,0x00,0x34,0x40,0x1d,0x01,0x04,0x06,0x08,0x03,0x02,0x02,0x03,0x05,0x93,0x04,0xa3,0x04,0x02,0x02,0x80,0x04,0x01,0x73,0x04,0x01,0x64,0x04,0x01, 0x56,0x04,0x01,0x04,0x00,0x00,0x2f,0x32,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x2f,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x21,0x23,0x01,0x37,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfd,0x0a,0x67,0x02,0x8f,0x9c,0x05,0x73,0x47,0xfb,0x5b,0x04,0xa5,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x45, 0x40,0x29,0x88,0x03,0x98,0x03,0x02,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0xd0,0x03,0x02,0x03,0x26,0x03,0x01,0x03,0x04,0x06,0x90,0x05,0xa0,0x05,0x02,0x72,0x05,0x82,0x05,0x02,0x63,0x05,0x01,0x05,0x02,0x02,0x01,0x06,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x10,0xc4,0x32,0x5d,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd, 0xc4,0x31,0x30,0x00,0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x51,0x67,0x01,0x48,0x9c,0x02,0x8f,0x02,0xe4,0x47,0xfd,0xd5,0x02,0x2b,0x00,0x00,0x01,0x00,0x25,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x7a,0x40,0x4d,0x29,0x07,0x01,0x89,0x04,0xa9,0x04,0x02,0x75,0x03,0x85,0x03,0x02,0x68,0x03,0x01, 0x45,0x03,0x01,0x36,0x03,0x01,0x2a,0x03,0x01,0x07,0x03,0x17,0x03,0x02,0x03,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x78,0x04,0x98,0x04,0x02,0x04,0x05,0x07,0xa3,0x06,0x01,0x02,0x90,0x06,0x01,0x81,0x06,0x01,0x74,0x06,0x01,0x06,0x03,0x03,0x01,0x7b,0x02,0x01,0x1c,0x02,0x01,0x0b,0x02,0x01,0x02,0x07,0x01,0x00,0x2f,0x2f, 0x33,0x5d,0x5d,0x5d,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x5f,0x5d,0x10,0xc4,0x32,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x00,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x48,0x71,0x01,0x47,0x01,0x48,0x9c,0x04,0x6a, 0xfc,0xdd,0x04,0x3c,0x37,0xfc,0xdd,0x03,0x23,0x00,0x00,0x01,0x00,0x25,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x75,0x40,0x49,0xa4,0x07,0x01,0x95,0x07,0x01,0x89,0x04,0x99,0x04,0xa9,0x04,0x03,0x78,0x04,0x01,0x85,0x02,0x01,0x76,0x02,0x01,0x84,0x03,0x01,0x35,0x03,0x45,0x03,0x75,0x03,0x03,0x03,0x06,0x03,0x16,0x03,0x02, 0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x94,0x06,0xa4,0x06,0x02,0x83,0x06,0x01,0x02,0x70,0x06,0x01,0x06,0x03,0x07,0x02,0x03,0x02,0x03,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x5d,0x5f,0x5d,0x5d,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39, 0x5d,0x5f,0x5d,0x5d,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x48,0x71,0x01,0x51,0x01,0x3e,0x9c,0x03,0xd6,0xfd,0x71,0x04,0x3c,0x37,0xfc,0xc5,0x02,0x89,0xb2,0x00,0x01,0x00,0x25,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x64,0x40,0x3b, 0x36,0x03,0x46,0x03,0x02,0x17,0x03,0x01,0x04,0x03,0x01,0x91,0x06,0xa1,0x06,0x02,0xa9,0x04,0x01,0x9b,0x04,0x01,0x89,0x04,0x01,0x79,0x02,0x01,0x6c,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x72,0x06,0x82,0x06,0x02,0x06,0x03,0x07,0x02,0x03,0x02,0x03,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39, 0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x5d,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x48,0x71,0x01,0x71,0x01,0x1e,0x9c,0x02,0x8f,0xfe,0xb8,0x04,0x3c,0x37, 0xfc,0x82,0x01,0x0d,0x02,0x71,0x00,0x01,0x00,0x25,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x42,0x40,0x25,0xa6,0x06,0x01,0x94,0x06,0x01,0x76,0x06,0x86,0x06,0x02,0xad,0x03,0x01,0x99,0x03,0x01,0x88,0x03,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x06,0x02,0x02,0x08,0x00,0x00,0x2f,0x2f,0x39,0x2f, 0xcd,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x37,0x01,0x33,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x48,0x71,0x01,0x96,0xf9,0x9c,0x01,0x47,0x04,0x3c,0x37,0xfc,0x29,0x03,0xd7,0x00,0x00,0x01,0x00,0x25,0x00,0x00,0x03,0xc1,0x05,0xba, 0x00,0x08,0x00,0x55,0x40,0x35,0x74,0x06,0x01,0x56,0x06,0x01,0xa5,0x05,0x01,0x57,0x05,0x01,0xaa,0x03,0x01,0x99,0x03,0x01,0x8a,0x03,0x01,0xab,0x02,0x01,0x9c,0x02,0x01,0x8a,0x02,0x01,0x68,0x02,0x78,0x02,0x02,0x39,0x02,0x49,0x02,0x02,0x01,0x06,0x08,0x0a,0x04,0x03,0x03,0x04,0x02,0x05,0x07,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39, 0x39,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x37,0x01,0x17,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x48,0x71,0x01,0xb4,0xdb,0x9c,0x01,0x47,0x04,0x3c,0x37,0xfb,0xde,0xde,0x05,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x7a, 0x05,0xba,0x00,0x07,0x00,0x3b,0x40,0x20,0xa2,0x05,0x01,0x95,0x05,0x01,0x82,0x05,0x01,0x77,0x05,0x01,0xa9,0x03,0x01,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0x01,0x03,0x03,0x04,0x06,0x05,0x02,0x02,0x06,0x00,0x00,0x2f,0x2f,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d, 0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x51,0x67,0x01,0x48,0x9c,0x01,0x47,0x04,0x3c,0x37,0xfc,0xc9,0x03,0x37,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x7c,0x40,0x50,0x89,0x06,0x01,0x76,0x06,0x01,0xca,0x03,0x01,0x97,0x03,0x01,0x8a,0x03,0x01,0x74,0x03,0x01,0x35,0x03, 0x45,0x03,0x02,0x28,0x03,0x01,0x15,0x03,0x01,0x07,0x03,0x01,0x47,0x06,0x01,0x9b,0x04,0xab,0x04,0x02,0x89,0x04,0x01,0x7a,0x04,0x01,0x10,0x04,0x01,0x48,0x02,0x01,0x03,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x04,0x05,0x02,0x07,0xa3,0x06,0x01,0x02,0x70,0x06,0x80,0x06,0x90,0x06,0x03,0x06,0x03,0x01,0x00,0x2f,0xc4,0x32, 0x5d,0x5f,0x5d,0x2f,0x33,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x3d,0x76,0x01,0x4d,0x01,0x48,0x9c,0x04,0x10,0xfb,0xf0, 0x05,0x8c,0x2e,0xfb,0xf0,0x04,0x10,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x8c,0x40,0x59,0x8a,0x06,0x01,0x76,0x06,0x01,0xa8,0x04,0x01,0x8a,0x03,0x01,0x74,0x03,0x01,0x58,0x03,0x01,0x36,0x03,0x46,0x03,0x02,0x28,0x03,0x01,0x15,0x03,0x01,0x03,0x07,0x03,0x01,0xa3,0x06,0x01,0x02,0x90,0x06,0x01, 0x82,0x06,0x01,0xaa,0x04,0x01,0x03,0x79,0x04,0x89,0x04,0x99,0x04,0x03,0x14,0x04,0x01,0x9a,0x02,0xaa,0x02,0x02,0x22,0x02,0x01,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x09,0x07,0x02,0x02,0x01,0x09,0x70,0x06,0x01,0x06,0x03,0x01,0x00,0x2f,0xc4,0x32,0x5d,0x2f,0x12,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f, 0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5f,0x5d,0x01,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x3d,0x79,0x01,0x55,0x01,0x3d,0x9c,0x03,0xd6,0xfc,0x2a,0x05,0x8c,0x2e, 0xfb,0xc9,0x03,0xb7,0x80,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x7a,0x40,0x4b,0x76,0x06,0x01,0x07,0x06,0x01,0x8a,0x03,0x01,0x74,0x03,0x01,0x35,0x03,0x45,0x03,0x02,0x03,0x06,0x03,0x16,0x03,0x02,0xa7,0x07,0x01,0x93,0x06,0xa3,0x06,0x02,0x02,0x82,0x06,0x01,0xab,0x04,0x01,0x9a,0x04,0x01,0x03, 0x02,0x04,0x01,0x02,0x7b,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x07,0x02,0x02,0x00,0x08,0x70,0x06,0x01,0x54,0x06,0x01,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x5d,0x5d,0x2f,0x12,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5f,0x5d,0x5f, 0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x01,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x3d,0x76,0x01,0x69,0x01,0x2c,0x9c,0x02,0x8f,0xfd,0x71,0x05,0x8c,0x2e,0xfb,0x90,0x02,0x6d,0x02,0x03,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x60, 0x40,0x39,0xa6,0x06,0x01,0x94,0x06,0x01,0x97,0x05,0x01,0x36,0x03,0x46,0x03,0x02,0x17,0x03,0x01,0x06,0x03,0x01,0x90,0x06,0xa0,0x06,0x02,0x82,0x06,0x01,0x71,0x06,0x01,0xab,0x04,0x01,0x89,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x05,0x08,0x07,0x02,0x02,0x00,0x08,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f, 0x12,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x3d,0x79,0x01,0x81,0x01,0x11,0x9c,0x01,0x47,0xfe,0xb9,0x05,0x8c,0x2e,0xfb,0x43, 0x01,0x04,0x03,0xb9,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x36,0x40,0x1e,0x94,0x04,0x01,0x76,0x04,0x86,0x04,0x02,0xa6,0x03,0x01,0x97,0x03,0x01,0xa9,0x01,0x01,0x01,0x04,0x02,0x06,0x07,0x09,0x03,0x02,0x02,0x03,0x06,0x05,0x00,0x00,0x2f,0xcd,0x2f,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39, 0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x01,0x37,0x01,0x33,0x11,0x33,0x03,0xc1,0xfe,0x1c,0xfe,0x3d,0x79,0x01,0xa1,0xf1,0x9c,0x05,0x8c,0x2e,0xfa,0xe2,0x05,0x1e,0x00,0x01,0x00,0x1a,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x46,0x40,0x29,0x78,0x01,0x01,0x03,0x07,0x01,0x01,0xa4,0x04,0x01,0x83,0x04,0x93,0x04, 0x02,0x02,0xab,0x02,0x01,0x89,0x02,0x99,0x02,0x02,0x04,0x02,0x01,0x01,0x04,0x06,0x08,0x03,0x00,0x02,0x01,0x02,0x02,0x03,0x05,0x04,0x00,0x00,0x2f,0x32,0x2f,0xc4,0x32,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x01,0x5d,0x5f,0x5d,0x21,0x23,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c, 0xfe,0x3c,0x74,0x01,0x50,0x9c,0x05,0x8c,0x2e,0xfb,0xdc,0x04,0x24,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x2c,0x40,0x15,0xab,0x06,0x01,0x58,0x06,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x04,0x05,0x05,0x04,0x04,0x01,0x02,0x07,0x01,0x00,0x2f,0x2f,0xcd,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde, 0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0xb5,0x51,0x01,0x7e,0x02,0x01,0x05,0x1e,0xfe,0xb8,0x6b,0x01,0x79,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x4f,0x40,0x2d,0x93,0x07,0x01,0x47,0x07,0x57,0x07,0x02,0xa6,0x05,0x01,0x9b, 0x03,0x01,0x89,0x03,0x01,0x78,0x03,0x01,0xb6,0x02,0xc6,0x02,0x02,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x08,0x07,0x02,0x05,0x04,0x04,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0x33,0xc4,0x32,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb0,0x4b,0x01,0x9b,0x01,0x48,0x9c,0x03,0xd6,0x01,0x34,0xfe,0xcc,0x6b,0x01,0x79,0xfe,0xcc,0x01,0x34,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x4b,0x40,0x28,0xbb,0x07,0xcb,0x07,0x02,0x76,0x07,0x01,0x67,0x07, 0x01,0xa6,0x05,0x01,0x9b,0x03,0x01,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x08,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21, 0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xa5,0xfe,0xc0,0x48,0x01,0x9b,0x01,0x48,0x9c,0x02,0x8f,0x02,0x6a,0xfe,0xdd,0x6b,0x01,0x79,0xfd,0xc1,0x02,0x3f,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x54,0x40,0x2e,0x28,0x06,0x01,0x19,0x06,0x01,0x0b,0x06,0x01,0xcf,0x07,0x01, 0xbb,0x07,0x01,0xa6,0x05,0x01,0xa9,0x03,0x01,0x9b,0x03,0x01,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x08,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x08,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d, 0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x8e,0xfe,0xda,0x4b,0x01,0x9b,0x01,0x48,0x9c,0x01,0x47,0x03,0x95,0xfe,0xfa,0x6b,0x01,0x79,0xfc,0xd3,0x03,0x2d,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x5e,0x40,0x39,0x88,0x05,0x01,0x29,0x05,0x01, 0x0b,0x05,0x01,0x79,0x02,0x89,0x02,0x02,0x38,0x02,0x48,0x02,0x68,0x02,0x03,0xed,0x06,0x01,0xdb,0x06,0x01,0xcf,0x06,0x01,0xa6,0x04,0x01,0xad,0x02,0x01,0x9b,0x02,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x05,0x07,0x04,0x03,0x03,0x07,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33, 0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x05,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x81,0xfe,0xe7,0x4b,0x01,0x9b,0x01,0x48,0x9c,0x04,0xce,0xf8,0x6b,0x01,0x79,0xfb,0xe6,0x04,0x1a,0x00,0x01,0x00,0x42,0x00,0x00,0x02,0x7a,0x05,0xba, 0x00,0x06,0x00,0x35,0x40,0x1c,0xa6,0x04,0x01,0x9b,0x02,0x01,0x8a,0x02,0x01,0x69,0x02,0x01,0x58,0x02,0x01,0x05,0x02,0x06,0x08,0x03,0x04,0x04,0x03,0x03,0x01,0x02,0x06,0x01,0x00,0x2f,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x33, 0x02,0x7a,0x9c,0xfe,0xaf,0x4b,0x01,0x9c,0x9c,0x05,0x14,0xfe,0xc2,0x6b,0x01,0x79,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x42,0x40,0x25,0x59,0x07,0x99,0x07,0x02,0x9a,0x06,0x01,0x88,0x06,0x01,0x79,0x06,0x01,0x38,0x06,0x48,0x06,0x02,0x18,0x02,0x01,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x04,0x05,0x03, 0x03,0x01,0x02,0x08,0x01,0x00,0x2f,0x2f,0x33,0x12,0x39,0x2f,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xd6,0xfe,0x9b,0x01,0x47,0x01,0x48,0x9c,0x05,0x00,0xfe,0xd6,0x9c,0x01,0x48,0x00,0x01,0x00,0x96, 0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x42,0x40,0x24,0x38,0x03,0x48,0x03,0x02,0x92,0x07,0xa2,0x07,0x02,0x65,0x07,0x75,0x07,0x02,0x88,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x04,0x07,0x02,0x05,0x03,0x02,0x03,0x02,0x03,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x11,0x33,0x01,0x2f,0x10,0xde,0xdd, 0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0x65,0x01,0x2a,0x9c,0x02,0x8f,0x01,0x47,0x9c,0xfe,0xd7,0x02,0x71,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x42,0x40,0x23,0x97,0x06,0xa7,0x06, 0x02,0xa3,0x07,0x01,0x82,0x07,0x92,0x07,0x02,0x73,0x07,0x01,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x04,0x07,0x02,0x05,0x03,0x02,0x03,0x02,0x03,0x08,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x11,0x33,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01, 0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0xa1,0xee,0x9c,0x01,0x47,0x02,0x8f,0x9c,0xfe,0x07,0x03,0x41,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x46,0x40,0x28,0x94,0x05,0xa4,0x05,0x02,0x76,0x05,0x01,0x38,0x01,0x48,0x01,0x02,0x03,0xa4,0x06,0x01,0x93,0x06,0x01,0x02,0x70, 0x06,0x80,0x06,0x02,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x02,0x07,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5f,0x5d,0x5d,0x01,0x5f,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0xa1, 0xee,0x9c,0x03,0xd6,0x9c,0xfd,0x38,0x04,0x10,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x55,0x40,0x31,0x84,0x06,0x94,0x06,0x02,0x47,0x06,0x01,0x47,0x05,0x01,0x08,0x05,0x01,0x89,0x04,0xa9,0x04,0x02,0x9b,0x02,0x01,0x7a,0x02,0x01,0x69,0x02,0x01,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x06, 0x03,0x05,0x04,0x03,0x04,0x03,0x04,0x01,0x02,0x08,0x01,0x00,0x2f,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x64,0x54,0x01,0x2e, 0x01,0x61,0x9c,0x04,0xc4,0xfd,0xcb,0x01,0x9c,0x6f,0xfe,0xc0,0x02,0x60,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5d,0x40,0x36,0xba,0x07,0x01,0xb8,0x06,0x01,0x84,0x06,0x94,0x06,0xa4,0x06,0x03,0xa2,0x05,0x01,0x93,0x05,0x01,0x86,0x05,0x01,0x47,0x05,0x01,0x08,0x05,0x01,0x59,0x02,0x01,0x06,0x03,0x04, 0x02,0x07,0x09,0x0b,0x05,0x04,0x06,0x03,0x05,0x04,0x02,0x07,0x02,0x03,0x02,0x03,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xc4,0x32,0x11,0x33,0x01,0x2f,0x32,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01, 0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x65,0x51,0x01,0x4a,0x01,0x48,0x9c,0x03,0xd6,0xfe,0xb9,0x01,0x9c,0x5e,0xfe,0xb6,0x01,0x47,0x01,0x34,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x37,0x40,0x1b,0xa3,0x05,0x01,0x86,0x05,0x01,0x08,0x05,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04, 0x07,0x05,0x04,0x03,0x04,0x03,0x04,0x08,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x9a,0xfe,0x83,0x51,0x01,0x4a,0x01,0x48,0x9c,0x02,0x8f,0x01,0x9c,0x62,0xfe, 0x9e,0x02,0x8f,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x51,0x40,0x31,0x72,0x05,0x92,0x05,0x02,0x64,0x05,0x01,0x56,0x05,0x01,0x44,0x05,0x01,0x35,0x05,0x01,0x27,0x05,0x01,0x64,0x04,0x74,0x04,0x02,0x46,0x04,0x01,0x88,0x03,0xa8,0x03,0x02,0x02,0x05,0x07,0x09,0x04,0x03,0x05,0x02,0x04,0x03,0x02, 0x03,0x02,0x03,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfd,0x1d,0x54,0x02,0x8f,0x9c,0x01,0x47,0x02,0xe4,0x65,0xfd,0x71,0x03,0xb9,0x00,0x00,0x01, 0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x4d,0x40,0x2c,0x54,0x06,0x94,0x06,0xa4,0x06,0x03,0x08,0x04,0x01,0xa9,0x02,0x01,0x9a,0x02,0x01,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x04,0x03,0x05,0x02,0x04,0x03,0x84,0x03,0x01,0x36,0x03,0x46,0x03,0x02,0x02,0x03,0x02,0x03,0x07,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x39, 0x2f,0x2f,0x5d,0x5d,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x37,0x01,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x65,0x4b,0x01,0xb7,0xe1,0x9c,0x02,0x8f,0x01,0x9c,0x64,0xfe,0x4e,0xfe,0x55,0x04,0x88,0x00,0x00,0x01,0x00,0x42,0x00,0x00, 0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x4f,0x40,0x30,0x94,0x05,0x01,0x75,0x05,0x01,0x46,0x05,0x56,0x05,0x66,0x05,0x03,0x56,0x04,0x76,0x04,0x02,0x47,0x04,0x01,0x08,0x04,0x01,0x88,0x03,0xa8,0x03,0x02,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0x01,0x03,0x05,0x02,0x04,0x03,0x02,0x03,0x02,0x03,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f, 0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x64,0x48,0x01,0x54,0x9c,0x02,0x8f,0x01,0x9c,0x5d,0xfe,0xad,0x02,0x85,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x76, 0x40,0x4a,0x86,0x06,0x01,0x77,0x06,0x01,0xc9,0x05,0x01,0x75,0x03,0x85,0x03,0xc5,0x03,0x03,0x68,0x03,0x01,0x36,0x03,0x46,0x03,0x02,0x28,0x03,0x01,0xa2,0x06,0x01,0x94,0x06,0x01,0xdb,0x05,0xfb,0x05,0x02,0xcc,0x05,0x01,0xc0,0x02,0x01,0x9c,0x02,0x01,0x8b,0x02,0x01,0x78,0x02,0x01,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04, 0x06,0x03,0x05,0x04,0x03,0x04,0x03,0x04,0x01,0x02,0x08,0x01,0x00,0x2f,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03, 0xc1,0x9c,0xfe,0xb9,0xfe,0x51,0x5d,0x01,0x48,0x01,0x51,0x9c,0x04,0x6a,0xfc,0xdd,0x03,0x47,0x3e,0xfd,0x77,0x03,0x77,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x66,0x40,0x3d,0x85,0x06,0x01,0x76,0x06,0x01,0x85,0x03,0x01,0x74,0x03,0x01,0x35,0x03,0x45,0x03,0x02,0x29,0x03,0x01,0xa0,0x06,0x01,0x94, 0x06,0x01,0xcb,0x05,0xdb,0x05,0x02,0x8e,0x02,0x01,0x7a,0x02,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x06,0x03,0x07,0x02,0x05,0x04,0x03,0x02,0x04,0x04,0x02,0x03,0x03,0x09,0x00,0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00, 0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x5d,0x01,0x51,0x01,0x48,0x9c,0x03,0xd6,0xfd,0x71,0x03,0x47,0x3e,0xfd,0x71,0x02,0x8f,0xee,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5e,0x40,0x37, 0x76,0x06,0x01,0x76,0x03,0x01,0x37,0x03,0x47,0x03,0x02,0xa4,0x06,0x01,0x93,0x06,0x01,0x84,0x06,0x01,0xcb,0x05,0xdb,0x05,0x02,0xa6,0x05,0x01,0x6c,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x06,0x03,0x07,0x02,0x05,0x04,0x03,0x02,0x04,0x04,0x02,0x03,0x03,0x08,0x00,0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11, 0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x5d,0x01,0x6b,0x01,0x2e,0x9c,0x02,0x8f,0xfe,0xb8,0x03,0x47,0x3e,0xfd,0x46,0x01,0x41,0x02,0x67, 0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x2f,0x40,0x15,0xa6,0x05,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x05,0x04,0x03,0x04,0x03,0x04,0x08,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x21,0x23,0x11, 0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x5d,0x01,0x87,0x01,0x12,0x9c,0x01,0x47,0x03,0x4a,0x3b,0xfd,0x17,0x03,0xd7,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x71,0x40,0x46,0xa0,0x06,0x01,0x93,0x06,0x01,0x74,0x06,0x01,0x65,0x06,0x01,0x56,0x06,0x01,0xa1,0x05,0x01, 0x90,0x05,0x01,0x85,0x05,0x01,0x44,0x05,0x01,0x36,0x05,0x01,0xdb,0x04,0x01,0xc9,0x04,0x01,0x96,0x04,0xa6,0x04,0x02,0x77,0x04,0x01,0x94,0x02,0x01,0x88,0x02,0x01,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x04,0x03,0x05,0x02,0x04,0x03,0x02,0x03,0x02,0x03,0x07,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33, 0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x37,0x01,0x17,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x5d,0x01,0xa1,0xf8,0x9c,0x01,0x47,0x03,0x47,0x3e,0xfc,0xe6,0xf8,0x05,0x00,0x00,0x01,0x00,0x2f, 0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x54,0x40,0x32,0xfa,0x04,0x01,0xd9,0x04,0xe9,0x04,0x02,0x77,0x04,0x01,0xa2,0x05,0x01,0x91,0x05,0x01,0x80,0x05,0x01,0xcb,0x04,0x01,0xa7,0x04,0x01,0x94,0x04,0x01,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0xd0,0x03,0x02,0x03,0x05,0x02,0x04,0x03,0x02,0x03,0x02,0x03,0x07,0x00,0x00,0x2f, 0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x51,0x5d,0x01,0x52,0x9c,0x01,0x47,0x03,0x47,0x42,0xfd,0x77,0x03,0x73,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1, 0x05,0xba,0x00,0x08,0x00,0x62,0x40,0x3c,0x85,0x06,0x01,0x75,0x03,0x85,0x03,0x02,0x58,0x03,0x01,0x35,0x03,0x45,0x03,0x02,0x28,0x03,0x01,0x07,0x03,0x17,0x03,0x02,0x03,0x94,0x06,0xa4,0x06,0x02,0x76,0x06,0x86,0x06,0x02,0x9b,0x02,0x01,0x8c,0x02,0x01,0x02,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x05,0x04,0x04,0x01,0x02, 0x08,0x06,0x03,0x01,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5d,0x5d,0x01,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x51,0x6a,0x01,0x3a,0x01,0x52,0x9c,0x04,0x10, 0xfb,0xf0,0x05,0x10,0x2a,0xfc,0x49,0x04,0x37,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x72,0x40,0x47,0x85,0x06,0x01,0x76,0x06,0x01,0xd8,0x05,0x01,0x75,0x03,0x85,0x03,0x02,0x58,0x03,0x01,0x34,0x03,0x44,0x03,0x02,0x28,0x03,0x01,0x07,0x03,0x17,0x03,0x02,0xa0,0x06,0x01,0x92,0x06,0x01,0x70,0x06, 0x80,0x06,0x02,0xb9,0x05,0x01,0x7f,0x02,0x8f,0x02,0x02,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d, 0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x6a,0x01,0x44,0x01,0x48,0x9c,0x03,0xd6,0xfc,0x2a,0x05,0x10,0x24,0xfc,0x3a,0x03,0xcc,0x80,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x78,0x40,0x4c,0xa7,0x06, 0x01,0x76,0x06,0x01,0xb8,0x05,0x01,0x8a,0x03,0x01,0x45,0x03,0x75,0x03,0x02,0x36,0x03,0x01,0x28,0x03,0x01,0x07,0x03,0x17,0x03,0x02,0xa1,0x06,0x01,0x70,0x06,0x80,0x06,0x90,0x06,0x03,0x54,0x06,0x64,0x06,0x02,0x9e,0x02,0xae,0x02,0x02,0x8f,0x02,0x01,0x7d,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05, 0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1, 0x9c,0xfe,0xb8,0xfe,0x52,0x6a,0x01,0x5a,0x01,0x32,0x9c,0x02,0x8f,0xfd,0x71,0x05,0x10,0x2d,0xfc,0x19,0x02,0x6b,0x01,0xf9,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x66,0x40,0x3e,0x57,0x06,0x01,0x76,0x05,0x01,0x79,0x03,0x89,0x03,0x02,0x36,0x03,0x46,0x03,0x02,0x07,0x03,0x17,0x03,0x02,0x92,0x06,0xa2, 0x06,0x02,0x84,0x06,0x01,0x75,0x06,0x01,0x9a,0x04,0xaa,0x04,0x02,0x8a,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30, 0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x52,0x6a,0x01,0x7b,0x01,0x11,0x9c,0x01,0x47,0xfe,0xb9,0x05,0x10,0x2d,0xfb,0xc4,0x01,0x00,0x03,0xb9,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x34,0x40,0x1c, 0x86,0x04,0xa6,0x04,0x02,0x77,0x04,0x01,0x98,0x01,0xa8,0x01,0x02,0x01,0x04,0x02,0x05,0x07,0x09,0x03,0x02,0x03,0x02,0x02,0x00,0x07,0x05,0x00,0x00,0x2f,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x21,0x21,0x01,0x37,0x01,0x33,0x11,0x33,0x03,0xc1,0xfe,0x1c,0xfe,0x52, 0x6a,0x01,0x9d,0xef,0x9c,0x05,0x10,0x2a,0xfb,0x62,0x05,0x1e,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x2e,0x40,0x18,0x01,0x04,0x06,0x08,0x03,0x04,0x02,0x01,0x02,0x03,0x02,0x02,0x06,0xa3,0x04,0x01,0x02,0x80,0x04,0x90,0x04,0x02,0x04,0x00,0x00,0x2f,0x32,0x5d,0x5f,0x5d,0x2f,0x39,0x2f,0x33,0x01,0x2f, 0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x21,0x23,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x51,0x6a,0x01,0x45,0x9c,0x05,0x10,0x27,0xfc,0x23,0x04,0x60,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x3e,0x40,0x24,0x8b,0x06,0x9b,0x06,0xab,0x06,0x03,0x59,0x06,0x69,0x06,0x02,0xa5,0x04,0x01,0x86, 0x04,0x01,0x76,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x04,0x05,0x05,0x04,0x04,0x01,0x02,0x07,0x01,0x00,0x2f,0x2f,0xcd,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0xb2,0x6a,0x01,0x5e,0x02,0x3d, 0x05,0x1e,0xfd,0x71,0x50,0x02,0xdb,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x74,0x40,0x47,0xc9,0x06,0x01,0x46,0x06,0x01,0x37,0x06,0x01,0xa6,0x04,0x01,0x95,0x04,0x01,0xc9,0x07,0x01,0x94,0x07,0x01,0x47,0x07,0x57,0x07,0x02,0xc6,0x03,0x01,0xb7,0x03,0x01,0xac,0x03,0x01,0x8b,0x03,0x9b,0x03,0x02, 0x7d,0x03,0x01,0x59,0x03,0x69,0x03,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x08,0x05,0x04,0x07,0x02,0x04,0x02,0x04,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd6,0xfe,0x95,0x6a,0x01,0xb8,0x01,0x47,0x9c,0x03,0xd6,0x01,0x23,0xfd,0x99,0x4d,0x02,0xdb,0xfe,0xcc,0x01,0x34,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x78,0x40,0x4c,0xf9,0x06, 0x01,0x76,0x06,0x86,0x06,0xc6,0x06,0x03,0x45,0x06,0x01,0x34,0x06,0x01,0x2a,0x06,0x01,0xc7,0x03,0x01,0x74,0x07,0x94,0x07,0x02,0x66,0x07,0x01,0x45,0x07,0x01,0xa6,0x05,0x01,0x87,0x05,0x01,0x66,0x05,0x01,0x57,0x05,0x01,0x9f,0x03,0xaf,0x03,0x02,0x8b,0x03,0x01,0x7d,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03, 0x06,0x08,0x05,0x04,0x07,0x02,0x02,0x01,0x08,0x01,0x00,0x2f,0x2f,0x12,0x39,0x2f,0x33,0xc4,0x32,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1, 0x9c,0xfe,0xb8,0xfe,0xb3,0x6a,0x01,0xb7,0x01,0x48,0x9c,0x02,0x8f,0x02,0x35,0xfd,0xcb,0x50,0x02,0xdb,0xfd,0xcb,0x02,0x35,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x98,0x40,0x63,0xf5,0x06,0x01,0xc6,0x06,0x01,0x84,0x06,0x01,0x75,0x06,0x01,0x59,0x06,0x01,0x36,0x06,0x46,0x06,0x02,0x2a,0x06,0x01,0xf5, 0x03,0x01,0xc7,0x03,0x01,0x85,0x03,0x01,0x76,0x03,0x01,0xa6,0x07,0x01,0x90,0x07,0x01,0x74,0x07,0x84,0x07,0x02,0x6c,0x07,0x01,0x57,0x07,0x01,0x2b,0x07,0x01,0x94,0x05,0x01,0x66,0x05,0x86,0x05,0x02,0x54,0x05,0x01,0xad,0x03,0x01,0x7b,0x03,0x9b,0x03,0x02,0x69,0x03,0x01,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06, 0x08,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x08,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23, 0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xa2,0xfe,0xc9,0x6a,0x01,0xb7,0x01,0x48,0x9c,0x01,0x47,0x03,0x57,0xfd,0xf9,0x48,0x02,0xdb,0xfc,0xdd,0x03,0x23,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x76,0x40,0x4b,0xc5,0x05,0x01,0x8b,0x05,0x01,0x7a,0x05,0x01,0x68,0x05,0x01,0x5a,0x05, 0x01,0x36,0x05,0x46,0x05,0x02,0x2a,0x05,0x01,0xc6,0x02,0x01,0x8b,0x02,0x01,0x7a,0x02,0x01,0x59,0x02,0x01,0xc9,0x06,0x01,0x90,0x06,0x01,0x84,0x04,0x94,0x04,0x02,0x9f,0x02,0xaf,0x02,0x02,0x8b,0x02,0x01,0x7e,0x02,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x05,0x07,0x04,0x03,0x03,0x07,0x06,0x00,0x00,0x2f,0x32, 0x2f,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x96,0xfe,0xd5,0x6a,0x01,0xb8,0x01,0x47,0x9c,0x04,0x81,0xfe,0x19, 0x45,0x02,0xdb,0xfb,0xf0,0x04,0x10,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x3d,0x40,0x23,0x87,0x04,0x97,0x04,0x02,0xac,0x02,0x01,0x02,0x8f,0x02,0x9f,0x02,0x02,0x6d,0x02,0x7d,0x02,0x02,0x05,0x02,0x06,0x08,0x03,0x00,0x04,0x01,0x04,0x04,0x03,0x03,0x01,0x02,0x06,0x01,0x00,0x2f,0x2f,0x33,0x12, 0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5f,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x33,0x02,0x7a,0x9c,0xfe,0xb2,0x6a,0x01,0xb8,0x9c,0x04,0xba,0xfd,0xd7,0x4e,0x02,0xdb,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x32,0x40,0x18,0x69,0x06,0x79,0x06,0x02,0x06, 0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x05,0x04,0x06,0x02,0x04,0x02,0x04,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0xb8,0x54,0x01,0x7e,0x01,0x65, 0x9c,0x03,0xd6,0xfe,0xbc,0x67,0x01,0x79,0x01,0x48,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5b,0x40,0x35,0xc9,0x07,0x01,0x65,0x07,0x75,0x07,0x02,0x47,0x07,0x01,0xb9,0x06,0x01,0x87,0x06,0x01,0x75,0x06,0x01,0x66,0x06,0x01,0xb9,0x05,0x01,0xa9,0x03,0x01,0x9b,0x02,0x01,0x06,0x03,0x05,0x02,0x07,0x09, 0x0b,0x04,0x05,0x05,0x04,0x07,0x02,0x06,0x03,0x02,0x03,0x02,0x03,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0xc6,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c, 0xfe,0xb8,0xfe,0xb9,0x54,0x01,0x9b,0x01,0x48,0x9c,0x02,0x8f,0x01,0x47,0xfe,0xc9,0x5a,0x01,0x8d,0xfe,0xb9,0x02,0x7b,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x53,0x40,0x2f,0xcc,0x07,0x01,0x02,0xbc,0x07,0x01,0xbb,0x06,0x01,0x96,0x06,0x01,0x89,0x03,0x01,0x58,0x03,0x68,0x03,0x78,0x03,0x03,0x03, 0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x05,0x04,0x06,0x03,0x02,0x04,0x03,0x03,0x04,0x02,0x03,0x09,0x00,0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01, 0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xa5,0xfe,0xcc,0x54,0x01,0x9b,0x01,0x48,0x9c,0x01,0x47,0x02,0x8f,0xfe,0xc9,0x5a,0x01,0x9e,0xfd,0x9c,0x03,0x87,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x5e,0x40,0x38,0x54,0x05,0x01,0x27,0x05,0x01,0x19,0x05,0x01,0xeb,0x06,0x01,0xdf,0x06,0x01,0xcd,0x06,0x01, 0xa2,0x06,0x01,0x64,0x06,0x74,0x06,0x94,0x06,0x03,0x1f,0x06,0x01,0x94,0x05,0xa4,0x05,0x02,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x08,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x8f,0xfe,0xe2,0x54,0x01,0x9c,0x01,0x47,0x9c,0x03,0xd6,0xfe,0xc9,0x5a,0x01,0xd2,0xfc,0x85,0x04,0x6a,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x38,0x40,0x1e,0xf6,0x04,0x01,0xc7, 0x04,0x01,0x87,0x03,0xa7,0x03,0x02,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x54, 0x01,0x9c,0x9c,0x03,0xd6,0xfe,0xd2,0x51,0x01,0x83,0x01,0x3e,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x3a,0x40,0x1f,0x96,0x03,0xa6,0x03,0x02,0xa9,0x02,0x01,0x8b,0x02,0x9b,0x02,0x02,0x7c,0x02,0x01,0x02,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x04,0x06,0x03,0x03,0x02,0x08,0x00,0x00,0x2f,0x2f,0x33,0x39, 0x2f,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x03,0x21,0x35,0x21,0x01,0x33,0x03,0xc1,0x9c,0xee,0xfe,0x5f,0x01,0x47,0x01,0x48,0x9c,0x04,0x88,0xfe,0x07,0x9c,0x02,0x8f,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x3d,0x40,0x20, 0x46,0x07,0x01,0x37,0x07,0x01,0x09,0x07,0x01,0x8b,0x02,0x01,0x09,0x02,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x03,0x02,0x03,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x21, 0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd6,0xfe,0x9b,0x01,0x47,0x01,0x48,0x9c,0x03,0xd6,0xfe,0xb9,0x9c,0x01,0x65,0x01,0x2a,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x3b,0x40,0x1f,0xa6,0x07,0x01,0x95,0x07,0x01,0x46,0x07,0x01,0x34,0x07,0x01,0x78,0x02,0x01,0x03,0x06,0x04,0x02,0x07,0x09,0x0b, 0x04,0x05,0x03,0x02,0x03,0x02,0x03,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0x65,0x01,0x2a,0x9c,0x01,0x47,0x01,0x48,0x9c,0xfe,0xd6, 0x03,0xb9,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x3e,0x40,0x23,0x74,0x05,0x01,0x89,0x02,0x99,0x02,0xa9,0x02,0x03,0x78,0x02,0x01,0x94,0x06,0xa4,0x06,0x02,0x53,0x06,0x01,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x02,0x08,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0xcd,0x01,0x2f,0x10,0xde, 0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x21,0x35,0x21,0x13,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0xa1,0xee,0x9c,0x02,0x8f,0x9c,0xfe,0x07,0x04,0x88,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x49,0x40,0x28,0xa2,0x06,0x01,0x94,0x06,0x01, 0x46,0x06,0x01,0x92,0x05,0xa2,0x05,0x02,0x74,0x05,0x01,0x65,0x05,0x01,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x06,0x03,0x05,0x04,0x03,0x04,0x03,0x04,0x02,0x08,0x00,0x00,0x2f,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x65,0x54,0x01,0x1d,0x01,0x72,0x9c,0x04,0x74,0xfc,0xd3,0x01,0x9c,0x70,0xfe,0xd2,0x03,0x95,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x57,0x40,0x33,0xa0,0x06,0x01,0x92,0x06,0x01,0x44,0x06,0x74,0x06,0x84,0x06,0x03,0x92, 0x05,0xa2,0x05,0x02,0x76,0x05,0x01,0x65,0x05,0x01,0x37,0x05,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x06,0x03,0x05,0x04,0x07,0x02,0x03,0x04,0x02,0x02,0x04,0x03,0x03,0x09,0x00,0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x64,0x54,0x01,0x2e,0x01,0x61,0x9c,0x03,0xd6,0xfd,0x71,0x01,0x9c,0x70,0xfe,0xd3,0x02,0xba,0xda,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x61,0x40,0x3b,0xa2,0x06,0x01,0x93,0x06,0x01, 0x87,0x06,0x01,0x64,0x06,0x74,0x06,0x02,0x46,0x06,0x01,0xa1,0x05,0x01,0x92,0x05,0x01,0x36,0x05,0x46,0x05,0x66,0x05,0x76,0x05,0x04,0xb7,0x02,0xd7,0x02,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x06,0x03,0x05,0x04,0x02,0x07,0x02,0x03,0x02,0x03,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xc4, 0x32,0x11,0x33,0x01,0x2f,0x32,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x65,0x54,0x01,0x51,0x01,0x3e,0x9c,0x02,0x8f,0xfe,0xb8,0x01,0x9c,0x70,0xfe,0xaa,0x01,0x42,0x02,0x7b,0x00,0x00,0x01, 0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x3e,0x40,0x20,0xa2,0x05,0x01,0x94,0x05,0x01,0x96,0x05,0x01,0x67,0x05,0x77,0x05,0x02,0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x05,0x04,0x03,0x04,0x03,0x04,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12, 0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x9a,0xfe,0x83,0x54,0x01,0x47,0x01,0x48,0x9c,0x01,0x47,0x01,0x9c,0x61,0xfe,0x9f,0x03,0xd7,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x06,0x00,0x42,0x40,0x28,0x98,0x01,0xa8,0x01,0x02,0x36, 0x04,0x46,0x04,0x56,0x04,0x03,0x27,0x04,0x01,0x46,0x03,0x01,0x37,0x03,0x01,0x68,0x02,0x78,0x02,0x88,0x02,0x03,0x01,0x04,0x06,0x08,0x03,0x02,0x03,0x02,0x02,0x06,0x04,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x01,0x37,0x01,0x11, 0x33,0x03,0xc1,0x9c,0xfd,0x1d,0x54,0x02,0x8f,0x9c,0x02,0xe3,0x66,0xfd,0x71,0x05,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x3b,0x40,0x21,0x85,0x05,0x01,0x48,0x03,0x58,0x03,0x68,0x03,0x98,0x03,0xa8,0x03,0x05,0x02,0x05,0x07,0x09,0x04,0x00,0x03,0x01,0x03,0x05,0x02,0x04,0x03,0x02,0x03,0x02, 0x03,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x21,0x23,0x11,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x64,0x54,0x01,0x48,0x9c,0x01,0x47,0x01,0x9c,0x52,0xfe,0xb8,0x03,0xcd,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba, 0x00,0x08,0x00,0x7c,0x40,0x4f,0x8a,0x06,0x01,0x29,0x06,0x79,0x06,0x02,0xf9,0x03,0x01,0xc5,0x03,0x01,0x7b,0x03,0x8b,0x03,0x02,0x36,0x03,0x46,0x03,0x02,0x29,0x03,0x01,0x07,0x03,0x17,0x03,0x02,0x03,0x93,0x06,0xa3,0x06,0x02,0x02,0x81,0x06,0x01,0x70,0x06,0x01,0x94,0x05,0xa4,0x05,0x02,0x87,0x05,0x01,0x03,0x9b,0x02,0x01,0x20, 0x02,0x01,0x02,0x03,0x06,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x05,0x04,0x04,0x00,0x02,0x08,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x01,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x48,0x70,0x01,0x2c,0x01,0x63,0x9c,0x04,0x10,0xfb,0xf0,0x03,0x6e,0x49,0xfd,0x93,0x04,0x70,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x8e,0x40,0x5c,0xc5,0x06,0x01,0x89,0x06,0x01,0x56,0x06,0x76,0x06,0x02,0x29,0x06,0x01, 0xf9,0x03,0x01,0xc5,0x03,0x01,0x8b,0x03,0x01,0x36,0x03,0x46,0x03,0x76,0x03,0x03,0x29,0x03,0x01,0x17,0x03,0x01,0x03,0x07,0x03,0x01,0x77,0x07,0x01,0xa4,0x06,0x01,0x92,0x06,0x01,0x02,0x70,0x06,0x80,0x06,0x02,0x64,0x06,0x01,0xa2,0x05,0x01,0x94,0x05,0x01,0x86,0x05,0x01,0x8a,0x04,0x01,0x03,0x23,0x02,0x01,0x02,0x06,0x03,0x04, 0x02,0x07,0x09,0x0b,0x05,0x04,0x04,0x02,0x04,0x02,0x00,0x09,0x03,0x00,0x00,0x2f,0xc4,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5f,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x01,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23, 0x11,0x01,0x01,0x37,0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x48,0x70,0x01,0x32,0x01,0x5d,0x9c,0x03,0xd6,0xfc,0x2a,0x03,0x6e,0x4c,0xfd,0x9c,0x03,0xee,0x76,0x00,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x7c,0x40,0x4f,0x76,0x06,0x86,0x06,0x02,0xf9,0x03,0x01,0x85,0x03,0xc5,0x03,0x02,0x74, 0x03,0x01,0x35,0x03,0x45,0x03,0x02,0x07,0x03,0x17,0x03,0x02,0xa1,0x06,0x01,0x80,0x06,0x90,0x06,0x02,0x74,0x06,0x01,0x55,0x06,0x01,0xa2,0x05,0x01,0x94,0x05,0x01,0xae,0x02,0x01,0x8f,0x02,0x9f,0x02,0x02,0x7b,0x02,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03, 0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x49,0x70,0x01,0x47, 0x01,0x48,0x9c,0x02,0x8f,0xfd,0x71,0x03,0x6e,0x52,0xfd,0x59,0x02,0xad,0x01,0xf4,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5c,0x40,0x36,0x57,0x06,0x01,0x07,0x03,0x17,0x03,0x37,0x03,0x47,0x03,0x04,0xa2,0x06,0x01,0x80,0x06,0x90,0x06,0x02,0x72,0x06,0x01,0xa2,0x05,0x01,0x94,0x05,0x01,0x89,0x02,0x01, 0x03,0x06,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37, 0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x49,0x70,0x01,0x65,0x01,0x2a,0x9c,0x01,0x47,0xfe,0xb9,0x03,0x6e,0x49,0xfd,0x2e,0x01,0x3a,0x03,0x9b,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x36,0x40,0x1e,0xa5,0x03,0x01,0x84,0x03,0x94,0x03,0x02,0x59,0x01,0x79,0x01,0xa9,0x01,0x03,0x01,0x04,0x02, 0x05,0x07,0x09,0x03,0x02,0x03,0x02,0x02,0x00,0x07,0x05,0x00,0x00,0x2f,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x21,0x21,0x01,0x37,0x01,0x33,0x11,0x33,0x03,0xc1,0xfe,0x1c,0xfe,0x49,0x70,0x01,0x91,0xfe,0x9c,0x03,0x6e,0x49,0xfc,0xe5,0x05,0x1e,0x00,0x01,0x00,0x26, 0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x46,0x40,0x2c,0x84,0x03,0x94,0x03,0xa4,0x03,0x03,0x80,0x04,0x90,0x04,0xa0,0x04,0x03,0x72,0x04,0x01,0x64,0x04,0x01,0x46,0x04,0x01,0x64,0x03,0x74,0x03,0x84,0x03,0x03,0x01,0x04,0x06,0x08,0x00,0x02,0x01,0x02,0x03,0x02,0x02,0x06,0x04,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0x33,0x01, 0x2f,0x5d,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x48,0x70,0x01,0x48,0x9c,0x03,0x6e,0x4f,0xfd,0x57,0x04,0xa6,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x48,0x40,0x2b,0x9d,0x06,0xad,0x06,0x02,0x8b,0x06,0x01, 0x79,0x06,0x01,0x94,0x04,0xa4,0x04,0x02,0x86,0x04,0x01,0x75,0x04,0x01,0x57,0x04,0x01,0x67,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x04,0x05,0x05,0x04,0x04,0x00,0x02,0x07,0x00,0x00,0x2f,0x2f,0xcd,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23, 0x11,0x23,0x01,0x27,0x01,0x21,0x03,0xc1,0x9c,0xef,0xfe,0x60,0x73,0x01,0xba,0x01,0xe4,0x05,0x1e,0xfc,0x29,0x48,0x04,0x2b,0x00,0x01,0x00,0x23,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x72,0x40,0x48,0x36,0x06,0x01,0x07,0x06,0x17,0x06,0x02,0x96,0x03,0xa6,0x03,0x02,0x90,0x07,0x01,0x55,0x07,0x01,0x36,0x07,0x01,0xa4,0x05, 0x01,0x92,0x05,0x01,0x74,0x05,0x84,0x05,0x02,0x8f,0x03,0x9f,0x03,0xaf,0x03,0x03,0x7d,0x03,0x01,0x4b,0x03,0x5b,0x03,0x6b,0x03,0x03,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x09,0x05,0x04,0x07,0x02,0x04,0x02,0x04,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f, 0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x25,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xef,0xfe,0x82,0x73,0x01,0xba,0x01,0x48,0x9c,0x03,0xd6,0xe3,0xfc,0x8e,0x41,0x04,0x32,0xfe,0xea,0x01,0x16,0x00,0x00,0x01,0x00,0x23, 0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x74,0x40,0x4a,0x79,0x06,0x89,0x06,0x02,0x44,0x06,0x01,0x33,0x06,0x01,0x07,0x06,0x17,0x06,0x02,0x79,0x03,0x89,0x03,0x02,0x45,0x03,0x01,0x36,0x03,0x01,0x74,0x07,0xa4,0x07,0x02,0x45,0x07,0x55,0x07,0x65,0x07,0x03,0x94,0x05,0xa4,0x05,0x02,0x9f,0x03,0xaf,0x03,0x02,0x89,0x03,0x01, 0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x09,0x05,0x04,0x07,0x02,0x04,0x02,0x04,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23, 0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xcb,0xfe,0xa6,0x73,0x01,0xba,0x01,0x48,0x9c,0x02,0x8f,0x02,0x02,0xfc,0xb6,0x3b,0x04,0x38,0xfd,0xe9,0x02,0x17,0x00,0x01,0x00,0x23,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x92,0x40,0x5f,0xf9,0x06,0x01,0xca,0x06,0x01,0x75,0x06,0x85,0x06,0x02,0x36,0x06,0x46, 0x06,0x02,0x07,0x06,0x17,0x06,0x02,0x76,0x03,0x86,0x03,0x02,0x90,0x07,0x01,0x72,0x07,0x82,0x07,0x02,0x2d,0x07,0x01,0x13,0x07,0x01,0x03,0x06,0x07,0x01,0xa7,0x05,0x01,0x95,0x05,0x01,0x86,0x05,0x01,0x77,0x05,0x01,0xac,0x03,0x01,0x02,0x8f,0x03,0x9f,0x03,0x02,0x6d,0x03,0x7d,0x03,0x02,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04, 0x05,0x5b,0x03,0x01,0x03,0x06,0x09,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc4,0x32,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x73,0x01,0xba,0x01,0x48,0x9c,0x01,0x47,0x03,0x05,0xfc,0xfb,0x3e,0x04,0x35,0xfc,0xdd,0x03,0x23,0x00,0x01,0x00,0x23,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x72,0x40,0x4b,0x07,0x05,0x01,0xf9,0x05,0x01,0x35,0x05,0x45,0x05, 0x75,0x05,0x85,0x05,0xc5,0x05,0x05,0x28,0x05,0x01,0x07,0x05,0x17,0x05,0x02,0x76,0x02,0x86,0x02,0x02,0x84,0x06,0x01,0x92,0x04,0xa2,0x04,0x02,0x84,0x04,0x01,0x76,0x04,0x01,0xae,0x02,0x01,0x8f,0x02,0x9f,0x02,0x02,0x5d,0x02,0x7d,0x02,0x02,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x05,0x08,0x04,0x03,0x03,0x08,0x06, 0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xae,0xfe,0xc3,0x73,0x01,0xbb,0x01,0x47,0x9c,0x04,0x37,0xfd,0x10, 0x3e,0x04,0x35,0xfb,0xf0,0x04,0x10,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x3e,0x40,0x22,0x67,0x03,0x01,0xa3,0x04,0x01,0xae,0x02,0x01,0x03,0x8b,0x02,0x9b,0x02,0x02,0x7c,0x02,0x01,0x02,0x05,0x02,0x06,0x08,0x03,0x00,0x04,0x01,0x04,0x04,0x03,0x03,0x02,0x06,0x00,0x00,0x2f,0x2f,0x33,0x39,0x2f, 0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5f,0x5d,0x5d,0x5f,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x73,0x01,0xbb,0x9c,0x04,0x74,0xfc,0xd3,0x38,0x04,0x3b,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x61,0x40,0x3a,0x92,0x06,0x01,0x76, 0x06,0x86,0x06,0x02,0x67,0x06,0x01,0xa2,0x05,0x01,0x93,0x05,0x01,0x86,0x05,0x01,0x74,0x05,0x01,0xaf,0x03,0x01,0x99,0x03,0x01,0x8b,0x03,0x01,0x78,0x03,0x01,0x5b,0x02,0x01,0x06,0x03,0x05,0x07,0x02,0x08,0x0a,0x04,0x05,0x05,0x04,0x06,0x03,0x04,0x03,0x04,0x03,0x02,0x08,0x00,0x00,0x2f,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x11,0x33, 0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x33,0x03,0xc1,0x9c,0xf8,0xfe,0x69,0x67,0x01,0xae,0x01,0x48,0x9c,0x04,0xf6,0xfe,0xe0,0xfd,0x71,0x51,0x02,0xbd,0x01,0x65,0x00,0x00,0x01,0x00,0x2f, 0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x44,0x40,0x26,0xaf,0x06,0x01,0x9b,0x06,0x01,0x7a,0x06,0x8a,0x06,0x02,0x95,0x04,0x01,0x57,0x03,0x67,0x03,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x05,0x04,0x06,0x02,0x04,0x02,0x04,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x11,0x33,0x01,0x2f,0x33, 0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xee,0xfe,0x83,0x67,0x01,0xae,0x01,0x48,0x9c,0x03,0xd6,0xfd,0x71,0x4e,0x02,0xdd,0x01,0x48,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x66,0x40,0x3d,0x49,0x06, 0x01,0x38,0x06,0x01,0x07,0x06,0x01,0xa0,0x07,0x01,0x91,0x07,0x01,0x74,0x07,0x01,0x65,0x07,0x01,0x94,0x06,0xa4,0x06,0x02,0x99,0x03,0xa9,0x03,0x02,0x8a,0x03,0x01,0x78,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x05,0x04,0x07,0x02,0x06,0x03,0x04,0x02,0x03,0x03,0x02,0x04,0x03,0x09,0x00,0x00,0x2f,0x2f,0x17,0x39, 0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd2,0xfe,0x9f,0x67,0x01,0xae,0x01,0x48,0x9c,0x02,0x8f,0x01,0x47,0xfd,0x71,0x41, 0x03,0x19,0xfe,0xa8,0x02,0x71,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x4b,0x40,0x2a,0x84,0x07,0xa4,0x07,0x02,0x76,0x07,0x01,0xa1,0x06,0x01,0x70,0x06,0x80,0x06,0x90,0x06,0x03,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x05,0x04,0x06,0x03,0x02,0x04,0x03,0x03,0x04,0x02,0x03,0x09,0x00, 0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x67,0x01,0xae,0x01,0x48,0x9c,0x01,0x47,0x02,0x8f,0xfd,0x71,0x32,0x03,0x67,0xfd, 0x5d,0x03,0x7d,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x4b,0x40,0x2a,0xa6,0x06,0x01,0x74,0x06,0x84,0x06,0x02,0x93,0x05,0xa3,0x05,0x02,0x02,0x70,0x05,0x80,0x05,0x02,0x64,0x05,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x08,0x06,0x00,0x00,0x2f, 0x32,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xa3,0xfe,0xce,0x67,0x01,0xaf,0x01,0x47,0x9c,0x03,0xd6,0xfd,0x71,0x41,0x03,0x9a,0xfc,0x4c,0x04,0x4c,0x00,0x01, 0x00,0x2f,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x45,0x40,0x28,0x94,0x04,0xa4,0x04,0x02,0x86,0x04,0x01,0x9f,0x02,0xaf,0x02,0x02,0x8d,0x02,0x01,0x6a,0x02,0x7a,0x02,0x02,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11, 0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x35,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x67,0x01,0xaf,0x9c,0x03,0xd6,0xfd,0x71,0x44,0x03,0x7d,0xb2,0x00,0x01,0x00,0x4b,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x5f,0x40,0x39,0x92,0x06,0xa2,0x06,0x02,0x84, 0x06,0x01,0x67,0x06,0x77,0x06,0x02,0x46,0x06,0x01,0x37,0x06,0x01,0xa6,0x05,0x01,0x94,0x05,0x01,0x58,0x03,0x01,0xaf,0x02,0x01,0x9d,0x02,0x01,0x8b,0x02,0x01,0x06,0x03,0x05,0x07,0x02,0x08,0x0a,0x04,0x05,0x05,0x04,0x06,0x03,0x04,0x03,0x04,0x03,0x02,0x08,0x00,0x00,0x2f,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01, 0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x33,0x03,0xc1,0x9c,0xff,0xfe,0x70,0x4b,0x01,0x7d,0x01,0x5d,0x9c,0x04,0x88,0xfe,0x07,0xfe,0xb8,0x73,0x01,0x40,0x02,0xc0,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x03,0xc1, 0x05,0xba,0x00,0x07,0x00,0x33,0x40,0x19,0xb9,0x05,0x01,0x65,0x05,0x01,0x56,0x05,0x01,0x02,0x05,0x07,0x09,0x03,0x04,0x05,0x02,0x04,0x03,0x02,0x03,0x02,0x03,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11, 0x33,0x03,0xc1,0x9c,0xfd,0x71,0x4b,0x02,0xda,0x9c,0x03,0xd6,0xfd,0x71,0x6d,0x02,0xdc,0x01,0x2a,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x30,0x40,0x16,0x88,0x06,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x05,0x04,0x06,0x02,0x04,0x02,0x04,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f, 0x2f,0x10,0xcd,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x4b,0x01,0x7e,0x01,0x5c,0x9c,0x02,0x8f,0xfe,0xb8,0x67,0x01,0x7d,0x02,0x8f,0x00,0x01,0x00,0x4b,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x53, 0x40,0x2f,0x84,0x07,0x01,0x56,0x07,0x01,0x47,0x07,0x01,0x84,0x06,0x01,0x77,0x06,0x01,0xb9,0x05,0x01,0x99,0x03,0xa9,0x03,0x02,0x03,0x06,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x05,0x04,0x06,0x03,0x02,0x04,0x03,0x03,0x04,0x02,0x03,0x09,0x00,0x00,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01, 0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x4b,0x01,0x92,0x01,0x48,0x9c,0x01,0x47,0x01,0x48,0xfe,0xb8,0x63,0x01,0x95,0xfe,0xb8,0x03,0xc3,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x03,0xc1, 0x05,0xba,0x00,0x08,0x00,0x4d,0x40,0x2b,0xa2,0x06,0x01,0x94,0x06,0x01,0x85,0x06,0x01,0x57,0x06,0x01,0xa2,0x05,0x01,0x74,0x05,0x94,0x05,0x02,0xa4,0x04,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x08,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01, 0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0x9f,0xfe,0xd2,0x4b,0x01,0x93,0x01,0x47,0x9c,0x02,0x8f,0xfe,0xb8,0x70,0x01,0xa3,0xfd,0x9c,0x04,0xc4,0x00,0x01,0x00,0x4b,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07, 0x00,0x3f,0x40,0x23,0xe9,0x05,0x01,0xbb,0x05,0xcb,0x05,0x02,0xb9,0x04,0xe9,0x04,0x02,0x79,0x02,0x01,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x04,0x03,0x05,0x02,0x03,0x02,0x03,0x02,0x07,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d, 0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x4b,0x01,0x93,0x9c,0x02,0x8f,0xfe,0xb8,0x5a,0x01,0x94,0x02,0x85,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x3a,0x40,0x1f,0x38,0x07,0x01,0x9b,0x06,0xab,0x06,0x02,0x9f,0x02,0x01,0x8b,0x02,0x01,0x7c,0x02,0x01,0x06,0x03,0x04, 0x07,0x02,0x08,0x0a,0x04,0x06,0x03,0x03,0x02,0x08,0x00,0x00,0x2f,0x2f,0x33,0x39,0x2f,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x03,0x21,0x35,0x21,0x01,0x33,0x03,0xc1,0x9c,0xee,0xfe,0x5f,0x01,0x47,0x01,0x48,0x9c,0x04,0x10,0xfd,0x37,0x9c,0x03,0xd7,0x00, 0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x28,0x40,0x11,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x04,0x06,0x07,0x02,0x03,0x02,0x03,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x11,0x03,0x21,0x35,0x21,0x01,0x35,0x33, 0x03,0xc1,0x9c,0xf8,0xfe,0x69,0x01,0x51,0x01,0x3e,0x9c,0x03,0xd6,0xfd,0x71,0x9c,0x03,0x39,0x9e,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x41,0x40,0x23,0x65,0x07,0x01,0x37,0x07,0x01,0x18,0x07,0x01,0x7a,0x02,0x01,0x48,0x02,0x01,0x19,0x02,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x04,0x05,0x07, 0x02,0x03,0x02,0x03,0x02,0x09,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33,0xcd,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd6,0xfe,0x9b,0x01,0x47,0x01,0x48,0x9c,0x02,0x8f,0xfe,0xb8,0x9c,0x01,0x66, 0x02,0x71,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x3e,0x40,0x23,0x38,0x02,0x48,0x02,0x88,0x02,0x03,0xa2,0x06,0x01,0x93,0x06,0x01,0x65,0x06,0x75,0x06,0x02,0x56,0x06,0x01,0x02,0x05,0x03,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x02,0x08,0x06,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0xcd,0x01,0x2f,0x10,0xde, 0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x01,0x65,0x01,0x2a,0x9c,0x01,0x47,0x9c,0xfe,0xd7,0x05,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x4e,0x40,0x2d,0x68,0x06,0x78,0x06,0x02,0x46, 0x05,0x01,0x28,0x03,0xc8,0x03,0x02,0xa2,0x06,0x01,0x94,0x06,0x01,0x99,0x04,0xa9,0x04,0x02,0xab,0x02,0x01,0x06,0x03,0x04,0x07,0x02,0x08,0x0a,0x05,0x04,0x05,0x04,0x04,0x00,0x02,0x08,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d, 0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x33,0x03,0xc1,0x9c,0xfe,0xb9,0xfe,0x64,0x54,0x01,0x11,0x01,0x7e,0x9c,0x04,0x10,0xfb,0xf0,0x01,0x9b,0x66,0xfe,0xfc,0x04,0xbd,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x44,0x40,0x23,0x46,0x05,0x01,0x28,0x03,0xc8,0x03,0x02, 0x99,0x04,0xa9,0x04,0x02,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x05,0x04,0x05,0x04,0x07,0x02,0x04,0x02,0x04,0x02,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37, 0x01,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0x65,0x54,0x01,0x1d,0x01,0x72,0x9c,0x03,0xd6,0xfc,0x2a,0x01,0x9b,0x66,0xfe,0xe7,0x04,0x5c,0x76,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x48,0x40,0x25,0x47,0x05,0x01,0x28,0x03,0x01,0x93,0x06,0x01,0xa9,0x04,0x01,0x98,0x04,0x01,0x06,0x03,0x04, 0x02,0x07,0x09,0x0b,0x05,0x04,0x05,0x04,0x07,0x02,0x04,0x02,0x04,0x02,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1, 0x9c,0xfe,0xb8,0xfe,0x65,0x54,0x01,0x34,0x01,0x5b,0x9c,0x02,0x8f,0xfd,0x71,0x01,0x9b,0x66,0xfe,0xca,0x02,0xc4,0x02,0x2b,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x4d,0x40,0x2a,0xb9,0x07,0x01,0xb8,0x06,0x01,0x77,0x06,0x01,0x46,0x05,0x01,0x99,0x04,0xa9,0x04,0x02,0x8c,0x02,0x01,0x06,0x03,0x04,0x02, 0x07,0x09,0x0b,0x05,0x04,0x07,0x02,0x05,0x04,0x02,0x04,0x02,0x04,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x37,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c, 0xfe,0xb8,0xfe,0x65,0x54,0x01,0x47,0x01,0x48,0x9c,0x01,0x47,0xfe,0xb9,0x01,0x9b,0x66,0xfe,0xb9,0x01,0x47,0x03,0xb9,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x32,0x40,0x18,0xa7,0x04,0x01,0xab,0x02,0x01,0x9a,0x02,0x01,0x01,0x04,0x02,0x05,0x07,0x09,0x03,0x02,0x03,0x02,0x02,0x00,0x07,0x04,0x00, 0x00,0x2f,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x21,0x21,0x01,0x37,0x01,0x21,0x11,0x33,0x03,0xc1,0xfd,0xff,0xfe,0x82,0x54,0x01,0x48,0x01,0x47,0x9c,0x01,0xa4,0x5d,0xfe,0x9b,0x05,0x1e,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06, 0x00,0x41,0x40,0x27,0x84,0x04,0x01,0x65,0x04,0x01,0xa9,0x02,0x01,0x78,0x02,0x98,0x02,0x02,0x59,0x02,0x01,0x28,0x02,0x38,0x02,0x48,0x02,0x03,0x01,0x04,0x06,0x08,0x03,0x00,0x02,0x01,0x02,0x03,0x02,0x02,0x06,0x04,0x00,0x00,0x2f,0x32,0x2f,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x21,0x23,0x01,0x37,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0x64,0x54,0x01,0x48,0x9c,0x01,0x9b,0x66,0xfe,0xb9,0x05,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x3c,0x40,0x24,0xab,0x06,0x01,0x89,0x06,0x99,0x06,0x02,0x58,0x06,0x78,0x06,0x02,0x96,0x04,0xa6,0x04,0x02,0x77,0x04,0x87,0x04, 0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x04,0x05,0x02,0x07,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0xcd,0x01,0x2f,0x33,0x10,0xde,0xcd,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x23,0x01,0x27,0x01,0x21,0x03,0xc1,0x9c,0xf1,0xfe,0x62,0x7c,0x01,0xc3,0x01,0xe4,0x05,0x1e,0xfa,0xe2,0x2e,0x05,0x8c,0x00,0x01, 0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x6e,0x40,0x45,0x36,0x06,0x46,0x06,0x02,0x07,0x06,0x17,0x06,0x02,0xa6,0x03,0x01,0x57,0x03,0x01,0x91,0x07,0x01,0x55,0x07,0x01,0x36,0x07,0x46,0x07,0x02,0xa4,0x05,0x01,0x95,0x05,0x01,0x74,0x05,0x84,0x05,0x02,0xaf,0x03,0x01,0x8d,0x03,0x9d,0x03,0x02,0x7b,0x03,0x01,0x06, 0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x09,0x07,0x02,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x25,0x01,0x27, 0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xf1,0xfe,0x80,0x7c,0x01,0xc3,0x01,0x48,0x9c,0x03,0xd6,0xf1,0xfb,0x39,0x2e,0x05,0x8c,0xfe,0xe0,0x01,0x20,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x70,0x40,0x48,0x79,0x06,0x89,0x06,0xc9,0x06,0x03,0x36,0x06,0x46,0x06,0x02,0x07,0x06,0x17,0x06,0x02,0x78, 0x03,0x01,0x41,0x07,0x01,0x32,0x07,0x01,0xa2,0x05,0x01,0x84,0x05,0x94,0x05,0x02,0x76,0x05,0x01,0x9f,0x03,0xaf,0x03,0x02,0x5d,0x03,0x6d,0x03,0x7d,0x03,0x03,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x8d,0x03,0x01,0x03,0x06,0x09,0x07,0x02,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x10, 0xc4,0x32,0x5d,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd8,0xfe,0x99,0x7c,0x01,0xc3,0x01,0x48,0x9c,0x02,0x8f,0x01,0xed,0xfb,0x84,0x2e,0x05,0x8c,0xfd,0xdf,0x02,0x21, 0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x8c,0x40,0x5b,0xf9,0x06,0x01,0xca,0x06,0x01,0x89,0x06,0x01,0x75,0x06,0x01,0x16,0x06,0x36,0x06,0x46,0x06,0x03,0x05,0x06,0x01,0x89,0x03,0x01,0x75,0x03,0x01,0x36,0x03,0x46,0x03,0x02,0xa4,0x07,0x01,0x72,0x07,0x01,0x2b,0x07,0x01,0x14,0x07,0x01,0x07,0x07,0x01, 0x03,0xa5,0x05,0x01,0x86,0x05,0x96,0x05,0x02,0xac,0x03,0x01,0x02,0x8f,0x03,0x9f,0x03,0x02,0x5d,0x03,0x7d,0x03,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x03,0x06,0x09,0x07,0x02,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x10,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39, 0x39,0x31,0x30,0x00,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xc7,0xfe,0xaa,0x7c,0x01,0xc3,0x01,0x48,0x9c,0x01,0x47,0x02,0xf8,0xfb,0xc1,0x2e,0x05,0x8c,0xfc,0xd3,0x03,0x2d,0x00,0x01, 0x00,0x1a,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x80,0x40,0x53,0xf9,0x05,0x01,0x8a,0x05,0xca,0x05,0x02,0x35,0x05,0x45,0x05,0x75,0x05,0x03,0x28,0x05,0x01,0x16,0x05,0x01,0x07,0x05,0x01,0xc9,0x02,0x01,0x88,0x02,0x01,0x76,0x02,0x01,0x94,0x06,0x01,0x47,0x06,0x01,0x15,0x06,0x01,0x03,0xa5,0x04,0x01,0x96,0x04,0x01,0x85, 0x04,0x01,0x9b,0x02,0xab,0x02,0x02,0x8c,0x02,0x01,0x02,0x7f,0x02,0x01,0x5b,0x02,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x02,0x05,0x08,0x04,0x03,0x06,0x00,0x00,0x2f,0x32,0xc4,0x32,0x2f,0xc4,0x32,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d, 0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xb8,0xfe,0xb9,0x7c,0x01,0xc3,0x01,0x48,0x9c,0x04,0x10,0xfb,0xf0,0x2e,0x05,0x8c,0xfb,0xf0,0x04,0x10,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x06,0x00,0x36,0x40,0x1f,0x77,0x03, 0x01,0x84,0x04,0x94,0x04,0xa4,0x04,0x03,0x8f,0x02,0x9f,0x02,0xaf,0x02,0x03,0x05,0x02,0x06,0x08,0x03,0x00,0x04,0x01,0x04,0x02,0x06,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x7c,0x01, 0xc4,0x9c,0x04,0x24,0xfb,0xdc,0x2e,0x05,0x8c,0x00,0x00,0x01,0x00,0x24,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x49,0x40,0x2a,0xa5,0x06,0x01,0x86,0x06,0x96,0x06,0x02,0x57,0x06,0x01,0x6b,0x03,0x7b,0x03,0xab,0x03,0x03,0x59,0x03,0x01,0xab,0x02,0x01,0x06,0x03,0x05,0x07,0x02,0x08,0x0a,0x04,0x05,0x06,0x03,0x03,0x00,0x02, 0x08,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x33,0x03,0xc1,0x9c,0xdb,0xfe,0x4c,0x72,0x01,0xb9,0x01,0x48,0x9c,0x04,0xf6,0xfe,0xe0,0xfc,0x2a,0x32,0x03,0xf5,0x01, 0x93,0x00,0x00,0x01,0x00,0x24,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x30,0x40,0x18,0x89,0x06,0x99,0x06,0xa9,0x06,0x03,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x06,0x02,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d, 0x21,0x23,0x11,0x23,0x01,0x27,0x01,0x21,0x11,0x33,0x03,0xc1,0x9c,0xf9,0xfe,0x6a,0x72,0x01,0xb9,0x01,0x48,0x9c,0x03,0xd6,0xfc,0x2a,0x32,0x04,0x40,0x01,0x48,0x00,0x00,0x01,0x00,0x24,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x57,0x40,0x33,0xb8,0x07,0x01,0x64,0x07,0x74,0x07,0x02,0xa0,0x06,0x01,0x74,0x06,0x84,0x06,0x94, 0x06,0x03,0x66,0x06,0x01,0xa2,0x05,0x01,0x84,0x05,0x94,0x05,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x06,0x03,0x02,0x03,0x02,0x03,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xe2,0xfe,0x8f,0x72,0x01,0xb9,0x01,0x48,0x9c,0x02,0x8f,0x01,0x47,0xfc,0x2a,0x32,0x04,0x99,0xfe,0x88,0x02,0x67,0x00,0x00,0x01,0x00,0x24,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x66,0x40,0x3c,0x79,0x06,0x01,0x46,0x06,0x01, 0x15,0x06,0x35,0x06,0x02,0x03,0x07,0x06,0x01,0xa4,0x07,0x01,0x93,0x06,0xa3,0x06,0x02,0x02,0x80,0x06,0x01,0x74,0x06,0x01,0x94,0x05,0xa4,0x05,0x02,0x87,0x05,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x06,0x03,0x02,0x03,0x02,0x03,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f, 0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x01,0x5d,0x5f,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd9,0xfe,0x98,0x72,0x01,0xc3,0x01,0x3e,0x9c,0x01,0x47,0x02,0x8f,0xfc,0x2a,0x32,0x04,0xf8,0xfd,0x45, 0x03,0x4b,0x00,0x01,0x00,0x24,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x5e,0x40,0x37,0x46,0x05,0x01,0x34,0x05,0x01,0x15,0x05,0x01,0x03,0xa6,0x06,0x01,0xa2,0x05,0x01,0x93,0x05,0x01,0x02,0x80,0x05,0x01,0x74,0x05,0x01,0xa4,0x04,0x01,0x92,0x04,0x01,0x74,0x04,0x84,0x04,0x02,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04, 0x05,0x02,0x02,0x00,0x08,0x04,0x03,0x06,0x00,0x00,0x2f,0x32,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x01,0x5f,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xcc,0xfe,0xa5,0x72,0x01, 0xcd,0x01,0x34,0x9c,0x03,0xd6,0xfc,0x2a,0x32,0x05,0x1c,0xfc,0x20,0x04,0x4c,0x00,0x00,0x01,0x00,0x24,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x3e,0x40,0x24,0x67,0x03,0x77,0x03,0x02,0x84,0x04,0x94,0x04,0xa4,0x04,0x03,0x8f,0x02,0x9f,0x02,0xaf,0x02,0x03,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x05,0x02,0x02,0x00, 0x07,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x35,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x72,0x01,0xba,0x9c,0x03,0xd6,0xfc,0x2a,0x32,0x05,0x26,0x62,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba, 0x00,0x06,0x00,0x39,0x40,0x21,0xa2,0x04,0x01,0x95,0x04,0x01,0xad,0x02,0x01,0x8f,0x02,0x9f,0x02,0x02,0x7b,0x02,0x01,0x59,0x02,0x69,0x02,0x02,0x05,0x02,0x06,0x08,0x03,0x04,0x02,0x06,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11, 0x01,0x27,0x01,0x33,0x03,0xc1,0x9c,0xfd,0x71,0x67,0x02,0xf6,0x9c,0x04,0xa5,0xfb,0x5b,0x4f,0x05,0x6b,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x5d,0x40,0x38,0x96,0x06,0x01,0x87,0x06,0x01,0x94,0x05,0xa4,0x05,0x02,0x76,0x05,0x86,0x05,0x02,0xad,0x03,0x01,0x8b,0x03,0x9b,0x03,0x02,0x59,0x03,0x69,0x03, 0x79,0x03,0x03,0x89,0x02,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x06,0x03,0x07,0x02,0x03,0x02,0x03,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21, 0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xf8,0xfe,0x69,0x67,0x01,0xae,0x01,0x48,0x9c,0x03,0xd6,0xfe,0xb9,0xfd,0x71,0x4f,0x02,0xab,0x01,0xaa,0x01,0x16,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x44,0x40,0x26,0xab,0x06,0x01,0x9e,0x06,0x01,0x8b,0x06,0x01,0x58,0x06,0x01,0xa5,0x04, 0x01,0x75,0x03,0x01,0x67,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x03,0x03,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21,0x11,0x33,0x03,0xc1, 0x9c,0xfe,0xee,0xfe,0x83,0x67,0x01,0xa4,0x01,0x52,0x9c,0x02,0x8f,0xfd,0x71,0x4f,0x02,0xdc,0x02,0x8f,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x67,0x40,0x3d,0x83,0x07,0x01,0x03,0x67,0x07,0x01,0x56,0x07,0x01,0xa3,0x06,0x01,0x02,0x90,0x06,0x01,0x74,0x06,0x84,0x06,0x02,0x56,0x06,0x01,0xa6,0x05,0x01, 0x94,0x05,0x01,0x76,0x05,0x86,0x05,0x02,0x68,0x03,0x01,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x02,0x06,0x03,0x02,0x03,0x02,0x03,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5f,0x5d,0x5d,0x5d,0x5f,0x5d,0x21,0x23,0x11,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xf0,0xfe,0x81,0x67,0x01,0xd1,0x01,0x25,0x9c,0x01,0x47,0x01,0x48,0xfd,0x71,0x4f,0x03,0x1f,0xfe,0x9d,0x03,0xaf,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x64,0x40,0x3d,0x36,0x05, 0x46,0x05,0x02,0x27,0x02,0x01,0x54,0x06,0x84,0x06,0x02,0x15,0x06,0x01,0x07,0x06,0x01,0x03,0xa3,0x05,0x01,0x02,0x80,0x05,0x90,0x05,0x02,0x72,0x05,0x01,0x24,0x05,0x01,0x84,0x04,0x94,0x04,0x02,0xa9,0x02,0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x05,0x02,0x02,0x00,0x08,0x04,0x03,0x06,0x00,0x00,0x2f,0x32,0xc4,0x32, 0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x5f,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xcc,0xfe,0xa5,0x67,0x01,0xc5,0x01,0x31,0x9c,0x02,0x8f,0xfd,0x71,0x4f,0x03,0x54,0xfd,0x85,0x04, 0x92,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x48,0x40,0x29,0xa6,0x03,0x01,0xa3,0x05,0x01,0x02,0x80,0x05,0x90,0x05,0x02,0x74,0x05,0x01,0x66,0x05,0x01,0x9b,0x02,0x01,0x8a,0x02,0x01,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x05,0x02,0x02,0x00,0x07,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f, 0x12,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5f,0x5d,0x01,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x67,0x01,0xaf,0x9c,0x02,0x8f,0xfd,0x71,0x4f,0x03,0x54,0x02,0x17,0x00,0x01,0x00,0x4e,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x41, 0x40,0x23,0xa2,0x06,0x01,0x96,0x06,0x01,0x57,0x06,0x67,0x06,0x02,0x9a,0x03,0x01,0x88,0x03,0x01,0x06,0x03,0x05,0x07,0x02,0x08,0x0a,0x04,0x05,0x06,0x03,0x03,0x00,0x02,0x08,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d, 0x5d,0x21,0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x33,0x03,0xc1,0x9c,0xe1,0xfe,0x52,0x48,0x01,0x95,0x01,0x42,0x9c,0x04,0x38,0xfd,0x0f,0xfe,0xb9,0x7b,0x01,0x32,0x04,0x0d,0x00,0x00,0x01,0x00,0x4e,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x47,0x40,0x26,0xa2,0x06,0x01,0x94,0x06,0x01,0x99,0x03,0xa9,0x03,0x02,0x58,0x03,0x68, 0x03,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x06,0x03,0x07,0x02,0x03,0x02,0x03,0x02,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x03,0x01,0x27,0x01,0x01,0x35, 0x33,0x03,0xc1,0x9c,0xf5,0xfe,0x66,0x48,0x01,0x8f,0x01,0x48,0x9c,0x03,0xd6,0xfd,0x71,0xfe,0xb9,0x7b,0x01,0x2e,0x03,0x73,0x9e,0x00,0x00,0x01,0x00,0x4e,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x07,0x00,0x35,0x40,0x1c,0x46,0x05,0x66,0x05,0x02,0xa6,0x04,0x01,0x97,0x04,0x01,0x6b,0x02,0x01,0x02,0x05,0x07,0x09,0x03,0x04,0x05,0x02, 0x02,0x00,0x07,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfd,0x71,0x48,0x02,0xd7,0x9c,0x02,0x8f,0xfd,0x71,0x7b,0x02,0xce,0x02,0x71,0x00,0x00,0x01,0x00,0x4e,0x00,0x00,0x03,0xc1, 0x05,0xba,0x00,0x09,0x00,0x32,0x40,0x19,0xa9,0x06,0x01,0x96,0x03,0xa6,0x03,0x02,0x06,0x03,0x05,0x02,0x07,0x09,0x0b,0x04,0x05,0x07,0x03,0x03,0x00,0x09,0x05,0x04,0x00,0x00,0x2f,0xc4,0x32,0x2f,0x12,0x39,0x2f,0xcd,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x21,0x23,0x11,0x21,0x01,0x27,0x01,0x21, 0x11,0x33,0x03,0xc1,0x9c,0xfe,0xe0,0xfe,0x91,0x48,0x01,0x99,0x01,0x3e,0x9c,0x01,0x47,0xfe,0xb9,0x7b,0x01,0x68,0x03,0xd7,0x00,0x01,0x00,0x4e,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x4b,0x40,0x2b,0x74,0x06,0x01,0x53,0x06,0x01,0x36,0x06,0x01,0xbb,0x05,0x01,0x74,0x05,0x01,0x87,0x04,0x97,0x04,0xa7,0x04,0x03,0x69,0x02, 0x01,0x02,0x05,0x04,0x01,0x06,0x08,0x0a,0x03,0x04,0x05,0x02,0x02,0x00,0x08,0x04,0x03,0x06,0x00,0x00,0x2f,0x32,0xc4,0x32,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x01,0x01,0x27,0x01,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xcc,0xfe, 0xa5,0x48,0x01,0xa7,0x01,0x30,0x9c,0x01,0x47,0xfe,0xb9,0x7b,0x01,0x7c,0xfe,0xcd,0x04,0xf6,0x00,0x01,0x00,0x4e,0x00,0x00,0x02,0x7a,0x05,0xba,0x00,0x07,0x00,0x31,0x40,0x19,0xb9,0x05,0x01,0x97,0x04,0xa7,0x04,0x02,0x02,0x05,0x07,0x09,0x03,0x00,0x04,0x01,0x04,0x05,0x02,0x02,0x00,0x07,0x04,0x03,0x00,0x00,0x2f,0xc4,0x32,0x2f, 0x12,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x11,0x33,0x02,0x7a,0x9c,0xfe,0xb8,0x48,0x01,0x90,0x9c,0x01,0x47,0xfe,0xb9,0x7b,0x01,0x86,0x03,0xb9,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x08,0x00,0x36,0x40,0x1d,0xa9,0x06,0x01,0x76, 0x03,0x86,0x03,0x02,0xad,0x02,0x01,0x8f,0x02,0x9f,0x02,0x02,0x06,0x03,0x05,0x07,0x02,0x08,0x0a,0x05,0x02,0x08,0x06,0x03,0x00,0x00,0x2f,0xd4,0xcd,0x2f,0x33,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x11,0x03,0x21,0x35,0x21,0x01,0x33,0x03,0xc1,0x9c,0xee,0xfe,0x5f,0x01, 0x47,0x01,0x48,0x9c,0x03,0xb6,0xfc,0x4a,0x9c,0x05,0x1e,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x2d,0x40,0x15,0x9b,0x02,0xab,0x02,0x02,0x06,0x03,0x04,0x07,0x02,0x09,0x0b,0x04,0x07,0x02,0x02,0x00,0x09,0x05,0x03,0x00,0x00,0x2f,0xd4,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x10,0xde,0xdd,0xc4, 0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x35,0x33,0x03,0xc1,0x9c,0xfe,0xfe,0xfe,0x73,0x01,0x47,0x01,0x48,0x9c,0x03,0xd6,0xfc,0x2a,0x9c,0x04,0xd0,0x4e,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x2f,0x40,0x16,0xaf,0x02,0x01,0x99,0x02,0x01,0x06,0x03,0x04,0x02, 0x07,0x09,0x0b,0x04,0x07,0x02,0x02,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xd4,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x10,0xde,0xdd,0xc4,0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x21,0x23,0x11,0x03,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xee,0xfe,0x5f,0x01,0x5b,0x01,0x34,0x9c,0x02,0x8f,0xfd,0x71,0x9c,0x03,0x61,0x01, 0xbd,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x09,0x00,0x3b,0x40,0x1f,0x46,0x07,0x01,0x37,0x07,0x01,0x0b,0x07,0x01,0x8b,0x02,0x01,0x09,0x02,0x01,0x06,0x03,0x04,0x02,0x07,0x09,0x0b,0x04,0x07,0x02,0x02,0x00,0x09,0x06,0x03,0x00,0x00,0x2f,0xd4,0xcd,0x2f,0x12,0x39,0x2f,0x33,0x01,0x2f,0x10,0xde,0xdd,0xc4, 0x12,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x21,0x35,0x21,0x01,0x11,0x33,0x03,0xc1,0x9c,0xfe,0xd6,0xfe,0x9b,0x01,0x47,0x01,0x48,0x9c,0x01,0x47,0xfe,0xb9,0x9c,0x01,0x65,0x03,0xb9,0x00,0x01,0xff,0x54,0x05,0xc2,0x02,0x6c,0x07,0x40,0x00,0x05,0x00,0x2c,0xb1,0x03,0x00,0xb8,0x01,0x35,0x40,0x16, 0x05,0x04,0x01,0x02,0x01,0x12,0x01,0x22,0x01,0x52,0x01,0x04,0x01,0x02,0x18,0x1a,0x1e,0x48,0x00,0x03,0x84,0x02,0x2f,0xe1,0xc6,0x2b,0x39,0x5d,0x11,0x33,0x00,0x2f,0xed,0xc4,0x31,0x30,0x01,0x20,0x03,0x23,0x12,0x21,0x02,0x6c,0xfe,0x44,0xba,0xa2,0xf0,0x02,0x28,0x06,0xc4,0xfe,0xfe,0x01,0x7e,0x00,0x00,0x01,0xff,0x54,0x05,0xc2, 0x02,0x6c,0x07,0x40,0x00,0x05,0x00,0x33,0xb2,0x00,0x80,0x03,0xb8,0x01,0x35,0x40,0x0f,0x04,0x05,0x02,0x0d,0x02,0x1d,0x02,0x2d,0x02,0x5d,0x02,0x04,0x02,0x03,0x01,0xb8,0xff,0xe8,0xb6,0x1a,0x1e,0x48,0x00,0x84,0x01,0x03,0x2f,0xd6,0xe1,0x2b,0x12,0x39,0x5d,0x11,0x33,0x00,0x2f,0xed,0x1a,0xcc,0x31,0x30,0x01,0x23,0x02,0x21,0x35, 0x20,0x02,0x6c,0xa1,0xba,0xfe,0x43,0x02,0x28,0x05,0xc2,0x01,0x02,0x7c,0x00,0x01,0xfd,0xa7,0x05,0xc2,0x00,0xc0,0x06,0xfa,0x00,0x0b,0x00,0x22,0xb2,0x06,0x80,0x02,0xbb,0x01,0x35,0x00,0x09,0x00,0x00,0x01,0x35,0xb2,0x0b,0x0b,0x06,0xb9,0x01,0x34,0x00,0x05,0x2f,0xe1,0xc4,0x00,0x2f,0xed,0xd5,0xed,0x1a,0xcd,0x31,0x30,0x13,0x24, 0x23,0x22,0x06,0x15,0x23,0x36,0x36,0x33,0x32,0x05,0xc0,0xfe,0xb3,0x8d,0x58,0x70,0x77,0x01,0xb4,0x88,0x93,0x01,0x49,0x06,0x16,0x67,0x6b,0x50,0x88,0xb0,0x66,0x00,0x00,0x01,0xff,0x68,0x05,0xc8,0x02,0x32,0x07,0x00,0x00,0x0b,0x00,0x22,0xb2,0x05,0x80,0x02,0xbe,0x01,0x35,0x00,0x09,0x00,0x0b,0x01,0x35,0x00,0x00,0x00,0x06,0x01, 0x34,0xb1,0x05,0x0b,0x2f,0xd4,0xe1,0x00,0x2f,0xfd,0xd5,0xed,0x1a,0xcc,0x31,0x30,0x03,0x04,0x33,0x32,0x36,0x35,0x33,0x06,0x06,0x23,0x22,0x27,0x98,0x01,0x00,0x8a,0x58,0x72,0x76,0x02,0xb6,0x86,0x8e,0xfe,0x06,0x94,0x50,0x6c,0x50,0x86,0xb2,0x4f,0x00,0x03,0x00,0x60,0xfe,0x1e,0x06,0x1c,0x05,0xec,0x00,0x22,0x00,0x2f,0x00,0x37, 0x01,0x5d,0x40,0x2c,0x30,0x31,0x18,0x00,0x22,0x06,0x01,0x37,0x01,0x19,0x31,0x18,0x05,0x22,0x06,0x04,0x1a,0x04,0x30,0x19,0x31,0x18,0x31,0x05,0x00,0x22,0x06,0x22,0x0b,0x01,0x01,0xbb,0x01,0xcb,0x01,0xdb,0x01,0xfb,0x01,0x04,0x37,0x01,0x36,0x04,0xb8,0xff,0xe8,0x40,0x33,0x09,0x13,0x48,0x1a,0x04,0x03,0x1b,0x0a,0x18,0x01,0xea, 0x18,0xfa,0x18,0x02,0x03,0x18,0x18,0x09,0x13,0x48,0x31,0x18,0x32,0x15,0x0d,0x06,0x01,0xed,0x06,0xfd,0x06,0x02,0x02,0x06,0x18,0x09,0x14,0x48,0x22,0x06,0x21,0x08,0x1b,0x96,0x36,0x36,0x38,0x32,0x95,0x21,0xb8,0xff,0xc0,0x40,0x4f,0x17,0x1c,0x48,0x21,0x21,0x38,0x03,0x1c,0x15,0x00,0x13,0x08,0x0b,0x27,0x95,0x11,0x10,0x2d,0x95, 0x0b,0x16,0xb5,0x37,0x01,0x0b,0x37,0x01,0xfb,0x37,0x01,0x37,0x20,0x09,0x16,0x48,0x37,0x01,0x34,0x02,0x5b,0x1a,0x01,0x1a,0x40,0x09,0x1d,0x48,0x1a,0x04,0x1e,0x03,0xa0,0x31,0x01,0x0b,0x31,0x01,0xeb,0x31,0xfb,0x31,0x02,0x44,0x31,0x01,0x31,0x18,0x34,0x16,0xa0,0x22,0x01,0xc3,0x22,0x01,0x22,0x1e,0x23,0x02,0xba,0x01,0x2c,0x00, 0x03,0xff,0xc0,0xb3,0x17,0x25,0x48,0x03,0xb8,0xff,0xc0,0xb6,0x09,0x13,0x48,0x03,0x03,0x23,0x34,0xb8,0x01,0x2c,0x40,0x14,0xa0,0x1e,0xd0,0x1e,0x02,0x1e,0x1e,0x16,0x84,0x15,0x06,0x07,0x15,0x03,0x23,0x23,0x39,0x2a,0x83,0x0e,0x2f,0xe1,0x12,0x39,0x2f,0x17,0x33,0x10,0xf1,0xc0,0x2f,0x5d,0xe1,0x11,0x39,0x2f,0x2b,0x2b,0xe1,0x11, 0x12,0x39,0x5d,0x5d,0x11,0x12,0x39,0x39,0x71,0x5d,0x71,0x5d,0x11,0x12,0x39,0x39,0x2b,0x71,0x11,0x12,0x39,0x39,0x2b,0x5d,0x71,0x5d,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0x3f,0x12,0x39,0x2f,0x2b,0xed,0x11,0x39,0x2f,0xed,0x11,0x12,0x39,0x39,0x2b,0x5f,0x5d,0x71,0x11,0x12,0x39,0x39,0x2b,0x5f,0x5d,0x71,0x11,0x12,0x39, 0x39,0x2b,0x11,0x39,0x39,0x5d,0x71,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x31,0x30,0x01,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x23,0x22,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x04,0x38,0x0f,0x02,0x91,0x07,0x27,0x58,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5,0xd3,0x60,0x04,0xa4,0x13,0x67,0x97,0x6f,0x8c,0xa2,0x80,0x70,0xfe,0xe2,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0xab,0x01,0x02,0x3c, 0x50,0x92,0x70,0x6a,0xfe,0x85,0x40,0x27,0x66,0x64,0x78,0xb4,0x9a,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x02,0x7a,0xfa,0x28,0x4e,0x41,0x7b,0x75,0x5c,0x5f,0x7e,0x03,0x7d,0x97,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0xc6,0xfd,0xd2,0x2f,0x54,0x4c,0x00,0x00,0x02,0x00,0xa6,0xfe,0x1e,0x03,0x56,0x05,0xec,0x00,0x15,0x00,0x1d,0x01,0x0f, 0x40,0x37,0x16,0x17,0x0b,0x00,0x15,0x06,0x01,0x1d,0x01,0x0c,0x17,0x0b,0x05,0x15,0x06,0x04,0x0d,0x04,0x16,0x0c,0x17,0x0b,0x17,0x05,0x00,0x15,0x06,0x15,0xbb,0x01,0xcb,0x01,0xdb,0x01,0x03,0x1d,0x01,0x1c,0x0d,0x0b,0x01,0xed,0x0b,0xfd,0x0b,0x02,0x0a,0x0b,0x01,0x0b,0x18,0x0e,0x13,0x48,0x04,0xb8,0xff,0xe8,0x40,0x1b,0x09,0x13, 0x48,0x0d,0x06,0x01,0xed,0x06,0xfd,0x06,0x02,0x04,0x06,0x0b,0x0d,0x04,0x03,0x0e,0x96,0x1c,0x1c,0x1e,0x17,0x18,0x95,0x15,0x14,0xb8,0xff,0xc0,0x40,0x34,0x17,0x1c,0x48,0x14,0x14,0x1e,0x03,0x08,0x00,0x03,0x1c,0xa0,0x17,0x01,0x15,0x17,0x01,0x17,0x0b,0x1a,0x0a,0xa0,0x15,0x01,0xc3,0x15,0x01,0x15,0x06,0x11,0x07,0xb5,0x1d,0x01, 0x1d,0x20,0x09,0x16,0x48,0x1d,0x01,0x1a,0x02,0x0d,0x40,0x09,0x1d,0x48,0x0d,0x04,0x11,0x02,0xba,0x01,0x2c,0x00,0x03,0xff,0xc0,0xb3,0x17,0x25,0x48,0x03,0xb8,0xff,0xc0,0xb6,0x09,0x13,0x48,0x03,0x03,0x07,0x1a,0xb8,0x01,0x2c,0x40,0x0a,0xa0,0x11,0xd0,0x11,0x02,0x11,0x11,0x0a,0x84,0x07,0x2f,0xf1,0xc0,0x2f,0x5d,0xe1,0x12,0x39, 0x2f,0x2b,0x2b,0xe1,0x12,0x39,0x39,0x2b,0x11,0x12,0x39,0x39,0x2b,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d,0x00,0x3f,0x3f,0x11,0x12,0x39,0x2f,0x2b,0x33,0xed,0x32,0x11,0x39,0x2f,0xed,0x11,0x17,0x39,0x5d,0x71,0x2b,0x2b,0x5d,0x5d,0x71,0x12,0x39,0x39,0x5d,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x0e,0xc0, 0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x31,0x30,0x01,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x11,0x33,0x11,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x01,0x70,0x0e,0x02,0x91,0x07,0x28,0x58,0xa4,0x12,0x67,0x97,0x72,0x8a,0xa4,0x7f,0x6f,0x1c,0x3b, 0x50,0x91,0x6e,0x6b,0xfe,0x85,0x40,0x27,0x66,0x64,0x78,0xb4,0x05,0xd8,0xfa,0x28,0x4e,0x41,0x7b,0x76,0x5b,0x5e,0x7f,0xb8,0x2f,0x54,0x4c,0x00,0x00,0x02,0x00,0xa6,0xfe,0x1e,0x06,0x04,0x04,0x18,0x00,0x24,0x00,0x2c,0x01,0x33,0x40,0x4c,0x25,0x26,0x1a,0x00,0x24,0x06,0x01,0x2c,0x01,0x1b,0x26,0x1a,0x05,0x24,0x06,0x04,0x1c,0x04, 0x25,0x1b,0x26,0x1a,0x26,0x05,0x00,0x24,0x06,0x24,0xb9,0x01,0xc9,0x01,0xd9,0x01,0x03,0x2c,0x01,0x03,0x2b,0x26,0x27,0x1a,0x0e,0x06,0x01,0xae,0x06,0xee,0x06,0xfe,0x06,0x03,0x02,0x24,0x06,0x23,0x0a,0x0d,0x1a,0x01,0xed,0x1a,0xfd,0x1a,0x02,0x0a,0x1a,0x5a,0x1a,0x02,0x1a,0x18,0x10,0x13,0x48,0x04,0xb8,0xff,0xe8,0x40,0x10,0x09, 0x13,0x48,0x04,0x1a,0x1c,0x03,0x03,0x1d,0x96,0x2b,0x2b,0x2d,0x27,0x95,0x23,0xb8,0xff,0xc0,0x40,0x39,0x17,0x1c,0x48,0x23,0x23,0x2d,0x03,0x1c,0x13,0x0a,0x95,0x15,0x10,0x11,0x0f,0x0e,0xa0,0x26,0x01,0x15,0x26,0x01,0x26,0x1a,0x29,0x18,0xa0,0x24,0x01,0xc3,0x24,0x01,0x24,0x06,0x20,0x08,0xb5,0x2c,0x01,0x2c,0x20,0x09,0x16,0x48, 0x2c,0x01,0x29,0x02,0x1c,0x40,0x09,0x1d,0x48,0x1c,0x04,0x20,0x02,0xba,0x01,0x2c,0x00,0x03,0xff,0xc0,0xb3,0x17,0x25,0x48,0x03,0xb8,0xff,0xc0,0xb6,0x09,0x13,0x48,0x03,0x03,0x08,0x29,0xb8,0x01,0x2c,0x40,0x10,0xa0,0x20,0xd0,0x20,0x02,0x20,0x20,0x18,0x84,0x08,0x08,0x2e,0x11,0x0e,0x84,0x0f,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1, 0xc0,0x2f,0x5d,0xe1,0x12,0x39,0x2f,0x2b,0x2b,0xe1,0x12,0x39,0x39,0x2b,0x11,0x12,0x39,0x39,0x2b,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d,0x00,0x2f,0x3f,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x2b,0xed,0x11,0x39,0x2f,0xed,0x11,0x17,0x39,0x2b,0x2b,0x5d,0x5d,0x71,0x11,0x12,0x39,0x39,0x5f,0x5d,0x71,0x11, 0x12,0x39,0x11,0x12,0x39,0x39,0x5d,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x31,0x30,0x01,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x17,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x23,0x22,0x27,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x04,0x1e,0x0e,0x02,0x91,0x07,0x28,0x58,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0x12,0x67,0x97,0x70,0x8c,0xa4,0x7e,0x70,0x1c,0x3b,0x51,0x90,0x6e,0x6b,0xfe,0x85,0x40,0x27,0x66,0x64,0x78,0xb4,0x02,0x34,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2, 0xd9,0xcd,0xfd,0xa2,0x4e,0x41,0x7b,0x75,0x5c,0x5e,0x7f,0xb8,0x2f,0x54,0x4c,0x00,0x00,0x02,0x00,0x2b,0xfe,0x1e,0x03,0x8c,0x05,0x2f,0x00,0x1d,0x00,0x25,0x01,0x39,0x40,0x48,0x1e,0x13,0x1f,0x00,0x06,0x1d,0x01,0x25,0x01,0x14,0x13,0x1f,0x05,0x06,0x1d,0x04,0x15,0x04,0x1e,0x14,0x13,0x1f,0x13,0x05,0x00,0x06,0x1d,0x06,0xb9,0x01, 0xc9,0x01,0xd9,0x01,0x03,0x25,0x01,0x03,0x24,0x0e,0x06,0x01,0xee,0x06,0xfe,0x06,0x02,0x02,0x1d,0x06,0x1c,0x08,0x1f,0x20,0x13,0x0d,0x13,0x01,0xed,0x13,0xfd,0x13,0x02,0x0a,0x13,0x01,0x13,0x18,0x0e,0x13,0x48,0x04,0xb8,0xff,0xe8,0x40,0x10,0x09,0x13,0x48,0x04,0x13,0x15,0x03,0x03,0x16,0x96,0x24,0x24,0x26,0x20,0x95,0x1c,0xb8, 0xff,0xc0,0x40,0x3a,0x17,0x1c,0x48,0x1c,0x1c,0x26,0x03,0x1c,0x0d,0x0e,0x11,0x08,0x95,0x0e,0x0b,0x0f,0xb5,0x25,0x01,0x25,0x20,0x09,0x16,0x48,0x25,0x01,0x22,0x02,0x15,0x40,0x09,0x1d,0x48,0x15,0x04,0x19,0x03,0xa0,0x1f,0x01,0x15,0x1f,0x01,0x1f,0x13,0x22,0x12,0xa0,0x1d,0x01,0xc3,0x1d,0x01,0x1d,0x06,0x19,0x07,0x02,0xba,0x01, 0x2c,0x00,0x03,0xff,0xc0,0xb3,0x17,0x25,0x48,0x03,0xb8,0xff,0xc0,0xb6,0x09,0x13,0x48,0x03,0x03,0x07,0x22,0xb8,0x01,0x2c,0x40,0x13,0xa0,0x19,0xd0,0x19,0x02,0x19,0x19,0x12,0x0f,0x0f,0x27,0x0e,0x0a,0x0b,0x0e,0x12,0x84,0x0b,0x07,0x2f,0x33,0xe1,0x32,0x10,0xcd,0x11,0x12,0x39,0x2f,0x10,0xc0,0x2f,0x5d,0xe1,0x12,0x39,0x2f,0x2b, 0x2b,0xe1,0x11,0x12,0x39,0x39,0x5d,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d,0x11,0x12,0x39,0x39,0x2b,0x11,0x12,0x39,0x39,0x2b,0x5d,0x00,0x3f,0x33,0xed,0x32,0x10,0xcd,0x3f,0x12,0x39,0x2f,0x2b,0xed,0x11,0x39,0x2f,0xed,0x11,0x17,0x39,0x2b,0x2b,0x5d,0x5d,0x71,0x11,0x12,0x39,0x11,0x12,0x39,0x39,0x5f,0x5d,0x71,0x11,0x12,0x39,0x39, 0x5d,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x0e,0xc0,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x31,0x30,0x01,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x01, 0xa6,0x0e,0x02,0x92,0x08,0x27,0x58,0xb0,0xb0,0xa4,0x01,0x02,0xfe,0xfe,0x13,0x66,0x98,0x6f,0x8d,0xa4,0x80,0x6f,0x1c,0x3b,0x50,0x92,0x6e,0x6c,0xfe,0x85,0x40,0x27,0x66,0x64,0x78,0xb4,0x03,0x60,0x8c,0xfa,0x35,0xfe,0xd1,0x8c,0xfc,0xa0,0x4e,0x41,0x7b,0x75,0x5c,0x5e,0x7f,0xb8,0x2f,0x54,0x4c,0x00,0x00,0x01,0xff,0xdb,0xfe,0x23, 0x04,0x16,0x04,0x18,0x00,0x19,0x00,0x31,0x40,0x1a,0x18,0x0f,0x0c,0x0a,0x95,0x0f,0x10,0x01,0x1c,0x03,0x14,0x95,0x05,0x16,0x19,0x84,0x01,0x18,0x18,0x1b,0x11,0x84,0x08,0x08,0x1b,0x0c,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x32,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x06,0x23,0x20, 0x11,0x11,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x04,0x16,0xa4,0x04,0x76,0xda,0xfe,0xa6,0x80,0x38,0x31,0x46,0x43,0x01,0x04,0xea,0x7a,0xa6,0xa4,0xfe,0x23,0x02,0x87,0xc2,0x01,0xa1,0x01,0x54,0xb1,0x1e,0x8c,0x1c,0xfe,0xd0,0xfe,0xca,0xfe,0xc0,0xbb,0x8f,0x02,0x44,0x00,0x00,0x01, 0xff,0xdb,0xfe,0x1e,0x05,0x27,0x04,0x18,0x00,0x22,0x00,0x38,0x40,0x1e,0x22,0x20,0x95,0x02,0x1c,0x1c,0x0f,0x10,0x0e,0x95,0x13,0x10,0x07,0x18,0x95,0x09,0x16,0x22,0x1d,0x84,0x05,0x1c,0x1c,0x24,0x15,0x84,0x0c,0x0c,0x24,0x10,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0xe1,0xc4,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x3f, 0xed,0x32,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x23,0x06,0x23,0x20,0x11,0x11,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x05,0x27,0x40,0x43,0x92,0xa0,0x04,0x76,0xda,0xfe,0xa6,0x80,0x38,0x31,0x46,0x43,0x01,0x04,0xea,0x7a,0xa6,0xa4,0xa0,0x3c,0x35, 0xfe,0x3a,0x1c,0xaf,0x9f,0x01,0x3e,0xc2,0x01,0xa1,0x01,0x54,0xb1,0x1e,0x8c,0x1c,0xfe,0xd0,0xfe,0xca,0xfe,0xc0,0xbb,0x8f,0x02,0x44,0xfb,0x72,0xc8,0x1a,0x00,0x01,0x00,0x85,0xfe,0xa0,0x02,0x22,0xff,0xb8,0x00,0x06,0x00,0x19,0x40,0x0d,0x05,0x80,0x30,0x06,0x40,0x06,0x50,0x06,0x03,0x06,0x03,0xc0,0x06,0x2f,0x1a,0xcc,0x00,0x2f, 0x5d,0x1a,0xcd,0x31,0x30,0x17,0x17,0x37,0x33,0x03,0x23,0x03,0xf0,0x64,0x64,0x6a,0xb4,0x34,0xb5,0x48,0xaa,0xaa,0xfe,0xe8,0x01,0x18,0x00,0x01,0x00,0x85,0xfe,0xa0,0x02,0x22,0xff,0xb8,0x00,0x06,0x00,0x19,0x40,0x0d,0x01,0x80,0x30,0x02,0x40,0x02,0x50,0x02,0x03,0x02,0x04,0xc0,0x01,0x2f,0x1a,0xcc,0x00,0x2f,0x5d,0x1a,0xcd,0x31, 0x30,0x13,0x23,0x13,0x33,0x13,0x23,0x27,0xf0,0x6b,0xb5,0x34,0xb4,0x6a,0x64,0xfe,0xa0,0x01,0x18,0xfe,0xe8,0xaa,0x00,0x01,0x00,0xc8,0xfe,0x5e,0x01,0xe0,0xff,0xfb,0x00,0x06,0x00,0x12,0xb7,0x30,0x01,0x01,0x01,0x04,0x05,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0xce,0x5d,0x31,0x30,0x01,0x15,0x25,0x35,0x25,0x15,0x07,0x01,0xe0,0xfe, 0xe8,0x01,0x18,0xaa,0xfe,0xc8,0x6a,0xb4,0x34,0xb5,0x6b,0x64,0x00,0x01,0x00,0xc8,0xfe,0x5e,0x01,0xe0,0xff,0xfb,0x00,0x06,0x00,0x12,0xb7,0x30,0x06,0x01,0x06,0x03,0x05,0x80,0x02,0x2f,0x1a,0xcd,0x00,0x2f,0xce,0x5d,0x31,0x30,0x13,0x37,0x27,0x35,0x05,0x15,0x05,0xc8,0xaa,0xaa,0x01,0x18,0xfe,0xe8,0xfe,0xc8,0x64,0x64,0x6b,0xb5, 0x34,0xb4,0x00,0x02,0x00,0x87,0xfe,0x2d,0x02,0x23,0xff,0xb2,0x00,0x0b,0x00,0x16,0x00,0x2f,0x40,0x1c,0x11,0xc5,0x40,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x8f,0x00,0x04,0x00,0x80,0x0c,0xc5,0x40,0x4f,0x06,0x01,0x06,0x09,0xc4,0x14,0x80,0x0f,0xc4,0x03,0x2f,0xe1,0x1a,0xdc,0xe1,0x00,0x2f,0x5d,0x1a,0xfd,0x1a,0xdc,0x5d,0x1a,0xed,0x31, 0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x52,0x59,0x72,0x76,0x5b,0x59,0x72,0x7b,0x56,0x31,0x3f,0x70,0x31,0x41,0x41,0xfe,0x2d,0x6b,0x54,0x57,0x6f,0x6c,0x54,0x54,0x71,0x01,0x33,0x40,0x30,0x71,0x41,0x30,0x30,0x40,0x00,0xff,0xff,0x00,0x52, 0x01,0x74,0x01,0xd7,0x02,0xbc,0x02,0x07,0x00,0x43,0x00,0x00,0xfc,0xb2,0xff,0xff,0x00,0x28,0x01,0x7f,0x02,0x70,0x02,0xbd,0x00,0x07,0x04,0x6e,0x01,0x4b,0xfc,0xbd,0xff,0xff,0x00,0x28,0x01,0x7f,0x02,0x6f,0x02,0xbd,0x00,0x07,0x00,0xde,0xff,0xe8,0xfc,0xbd,0xff,0xff,0x00,0x23,0x01,0x9e,0x02,0xa4,0x02,0x9e,0x00,0x07,0x00,0xd8, 0x00,0x00,0xfc,0xec,0xff,0xff,0x00,0xad,0x01,0x8e,0x01,0x8d,0x05,0xba,0x00,0x07,0x00,0x1d,0x00,0x3d,0x01,0xa4,0x00,0x01,0x00,0x98,0x04,0x42,0x02,0x12,0x05,0xba,0x00,0x05,0x00,0x1b,0xb1,0x02,0x01,0xb8,0x01,0x33,0xb4,0x04,0x04,0x00,0x00,0x02,0xb9,0x01,0x32,0x00,0x03,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0xfd,0xcd,0x31,0x30,0x01, 0x21,0x11,0x23,0x11,0x21,0x02,0x12,0xfe,0xf0,0x6a,0x01,0x7a,0x05,0x52,0xfe,0xf0,0x01,0x78,0x00,0x01,0x00,0x98,0x04,0x42,0x02,0x12,0x05,0xba,0x00,0x05,0x00,0x19,0xb1,0x04,0x05,0xb8,0x01,0x33,0xb2,0x02,0x04,0x02,0xb8,0x01,0x32,0xb1,0x05,0x00,0x2f,0xdd,0xe1,0x00,0x3f,0xfd,0xcd,0x31,0x30,0x13,0x35,0x21,0x11,0x23,0x11,0x98, 0x01,0x7a,0x6a,0x05,0x52,0x68,0xfe,0x88,0x01,0x10,0x00,0x01,0x00,0x98,0x00,0x00,0x02,0x12,0x01,0x79,0x00,0x05,0x00,0x1a,0xb1,0x04,0x05,0xb8,0x01,0x33,0xb3,0x02,0x00,0x00,0x05,0xb9,0x01,0x32,0x00,0x02,0x2f,0xf1,0xc1,0x2f,0x00,0x2f,0xfd,0xcd,0x31,0x30,0x25,0x15,0x21,0x11,0x33,0x11,0x02,0x12,0xfe,0x86,0x6a,0x68,0x68,0x01, 0x79,0xfe,0xef,0x00,0x00,0x01,0x00,0x98,0x00,0x00,0x02,0x12,0x01,0x79,0x00,0x05,0x00,0x18,0xb1,0x02,0x00,0xbb,0x01,0x33,0x00,0x05,0x00,0x03,0x01,0x32,0xb1,0x01,0x05,0x2f,0xdd,0xe1,0x00,0x2f,0xfd,0xc6,0x31,0x30,0x37,0x21,0x11,0x33,0x11,0x21,0x98,0x01,0x10,0x6a,0xfe,0x86,0x68,0x01,0x11,0xfe,0x87,0x00,0x00,0x01,0xff,0xf0, 0xfe,0x5c,0x02,0xba,0xff,0x89,0x00,0x07,0x00,0x31,0xb9,0x00,0x04,0x01,0x33,0x40,0x0d,0x40,0x01,0x80,0x06,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x07,0xb8,0x01,0x32,0xb3,0x06,0x06,0x09,0x03,0xb9,0x01,0x32,0x00,0x02,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x2f,0x5d,0x33,0x1a,0xdd,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x15, 0x21,0x35,0x33,0x02,0xba,0xfd,0x36,0x69,0x01,0xf8,0x69,0xfe,0x5c,0x01,0x2d,0xc5,0xc5,0x00,0x00,0x01,0xff,0xf2,0xfe,0x5c,0x02,0xba,0xff,0x89,0x00,0x05,0x00,0x27,0xb9,0x00,0x04,0x01,0x33,0x40,0x0e,0x40,0x01,0x80,0x0f,0x02,0x1f,0x02,0x2f,0x02,0x03,0x02,0x05,0x07,0x03,0xb9,0x01,0x32,0x00,0x02,0x2f,0xe1,0x10,0xc6,0x00,0x2f, 0x5d,0x1a,0xdd,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x15,0x21,0x02,0xba,0xfd,0x38,0x68,0x02,0x60,0xfe,0x5c,0x01,0x2d,0xc5,0x00,0x00,0x01,0x00,0x3a,0xfe,0x5c,0x02,0x6e,0x00,0xa0,0x00,0x09,0x00,0x4b,0x40,0x2f,0x4f,0x02,0xcf,0x02,0x02,0x02,0x01,0x40,0x07,0xc0,0x07,0x02,0x07,0x01,0xdb,0x08,0x01,0x08,0x08,0x20,0x09,0x0c, 0x48,0x08,0x05,0x02,0x42,0x4f,0x07,0x01,0x07,0x40,0x16,0x19,0x48,0x07,0x07,0x05,0x0f,0x09,0x1f,0x09,0x02,0x09,0x09,0x0b,0x05,0x2f,0x12,0x39,0x2f,0x5d,0x12,0x39,0x2f,0x2b,0x5d,0xe0,0x12,0x39,0x2b,0x11,0x33,0x00,0x2f,0xed,0xcd,0x5d,0x10,0xcd,0x5d,0x31,0x30,0x05,0x21,0x17,0x23,0x03,0x35,0x13,0x33,0x07,0x21,0x02,0x6e,0xfe, 0x4a,0xa8,0x5e,0xc8,0xc6,0x5e,0xa6,0x01,0xb6,0xb0,0xf4,0x01,0x1b,0x0e,0x01,0x1b,0xf4,0x00,0x00,0x01,0xff,0x74,0x04,0xba,0x00,0x8c,0x06,0x58,0x00,0x06,0x00,0x1a,0x40,0x0b,0x02,0x00,0x06,0xc0,0x03,0x03,0x02,0x00,0x05,0x80,0x06,0x2f,0x1a,0xcd,0x00,0x3f,0x33,0x2f,0x1a,0xce,0x39,0x39,0x31,0x30,0x03,0x37,0x27,0x35,0x05,0x15, 0x05,0x8c,0xaa,0xaa,0x01,0x18,0xfe,0xe8,0x05,0x25,0x65,0x64,0x6a,0xb5,0x33,0xb6,0x00,0x01,0xff,0xa6,0x04,0x98,0x00,0x5a,0x06,0x04,0x00,0x0b,0x00,0x20,0x40,0x0f,0x07,0xcb,0x40,0x06,0xc0,0x0b,0xcb,0x40,0x00,0x00,0x06,0x80,0x09,0xc9,0x03,0x2f,0xe1,0x1a,0xcc,0x32,0x00,0x2f,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x13,0x22, 0x26,0x35,0x34,0x36,0x33,0x15,0x22,0x15,0x14,0x33,0x5a,0x4d,0x67,0x66,0x4e,0x5e,0x5e,0x04,0x98,0x68,0x4e,0x4c,0x6a,0x5e,0x58,0x5a,0x00,0x02,0xfe,0xee,0x04,0xc2,0x01,0x12,0x06,0x68,0x00,0x0c,0x00,0x18,0x00,0x2f,0x40,0x18,0x0a,0xdb,0x04,0x01,0x06,0x06,0x0d,0xc1,0x40,0x13,0x00,0xc4,0x01,0x0e,0x10,0x06,0x16,0x42,0x06,0xc4, 0x07,0x10,0xc0,0x16,0x2f,0xe1,0xd6,0xe1,0x2b,0x01,0x10,0xf2,0xe1,0x00,0x18,0x2f,0x1a,0xed,0x32,0x2f,0x33,0xde,0xed,0x31,0x30,0x01,0x23,0x26,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x05,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x01,0x12,0x66,0x09,0x61,0x44,0xa0,0x0c,0x64,0x04,0x95,0x75,0x71,0x9b, 0xfe,0xf8,0x29,0x39,0x39,0x29,0x28,0x3a,0x38,0x05,0x6c,0x48,0x54,0x9c,0x72,0x8a,0x8a,0x59,0x39,0x29,0x29,0x38,0x38,0x29,0x28,0x3a,0x00,0x01,0xff,0x30,0xfd,0xfe,0x00,0xd2,0xff,0xa1,0x00,0x0b,0x00,0xa5,0x40,0x17,0x01,0x42,0x05,0x03,0x02,0x03,0x06,0x09,0x0b,0x00,0x03,0x08,0x56,0x06,0x01,0xd4,0x06,0xe4,0x06,0xf4,0x06,0x03, 0x06,0xb8,0xff,0xe0,0x40,0x42,0x09,0x0c,0x48,0x59,0x08,0x01,0xdb,0x08,0xeb,0x08,0xfb,0x08,0x03,0x08,0x20,0x09,0x0c,0x48,0x08,0x06,0x04,0x0a,0x04,0x0f,0x07,0x1f,0x07,0x2f,0x07,0xcf,0x07,0x04,0x07,0x0a,0x42,0x02,0x00,0x0b,0x03,0x03,0x06,0x08,0x09,0x03,0x05,0x29,0x03,0x59,0x03,0x02,0x03,0x20,0x15,0x1a,0x48,0x03,0x20,0x09, 0x0c,0x48,0x26,0x05,0x56,0x05,0x02,0x05,0xb8,0xff,0xe0,0xb3,0x15,0x1a,0x48,0x05,0xb8,0xff,0xe0,0x40,0x09,0x09,0x0c,0x48,0x05,0x03,0x07,0x01,0x04,0x04,0xb8,0xff,0xe0,0xb3,0x17,0x1b,0x48,0x04,0x19,0x2f,0x2b,0x17,0x33,0x2b,0x2b,0x71,0x2b,0x2b,0x71,0x11,0x17,0x33,0x11,0x17,0x33,0xe1,0x00,0x2f,0x5d,0x17,0x33,0x2b,0x5d,0x71, 0x2b,0x5d,0x71,0x11,0x17,0x33,0x11,0x17,0x33,0x18,0xe5,0x31,0x30,0x17,0x07,0x17,0x07,0x27,0x07,0x27,0x37,0x27,0x37,0x17,0x37,0xd2,0x85,0x85,0x4c,0x86,0x85,0x4b,0x85,0x85,0x4c,0x86,0x85,0xaa,0x86,0x84,0x4e,0x86,0x86,0x4c,0x85,0x85,0x4d,0x85,0x85,0x00,0xff,0xff,0xff,0x74,0xfe,0x5e,0x00,0x8c,0xff,0xfb,0x00,0x07,0x07,0x46, 0xfe,0xac,0x00,0x00,0xff,0xff,0xff,0x74,0xfe,0x5e,0x00,0x8c,0xff,0xfb,0x00,0x07,0x07,0x47,0xfe,0xac,0x00,0x00,0x00,0x02,0xfe,0xa1,0xfe,0x5e,0x01,0x5f,0xff,0xfb,0x00,0x06,0x00,0x0d,0x00,0x35,0x40,0x1e,0x07,0x09,0x80,0x0f,0x0b,0x1f,0x0b,0x2f,0x0b,0x03,0x0b,0x0e,0x40,0x0f,0x06,0x1f,0x06,0x2f,0x06,0x03,0x06,0x03,0x0d,0xc0, 0x0a,0x0a,0x02,0x06,0x80,0x05,0x2f,0x1a,0xcd,0x32,0x33,0x2f,0x1a,0xcc,0x00,0x2f,0xce,0x5d,0x1a,0x10,0xde,0x5d,0x1a,0xcd,0x32,0x31,0x30,0x01,0x37,0x27,0x35,0x05,0x15,0x05,0x25,0x27,0x07,0x23,0x13,0x33,0x13,0xfe,0xa1,0xaa,0xaa,0x01,0x19,0xfe,0xe7,0x02,0x53,0x64,0x64,0x6a,0xb5,0x33,0xb5,0xfe,0xc8,0x64,0x64,0x6b,0xb5,0x34, 0xb4,0x2e,0xa9,0xa9,0x01,0x18,0xfe,0xe8,0x00,0x01,0xff,0xa6,0x04,0x98,0x00,0x5a,0x06,0x04,0x00,0x0b,0x00,0x22,0x40,0x10,0x05,0xcb,0x40,0x06,0xc0,0x01,0xcb,0x40,0x00,0x00,0x06,0x06,0x80,0x09,0xc9,0x03,0x2f,0xf1,0x1a,0xc8,0x2f,0x32,0x00,0x2f,0x1a,0xed,0x1a,0xde,0x1a,0xed,0x31,0x30,0x03,0x35,0x32,0x35,0x34,0x23,0x35,0x32, 0x16,0x15,0x14,0x06,0x5a,0x5e,0x5e,0x4d,0x67,0x67,0x04,0x98,0x5c,0x5a,0x58,0x5e,0x69,0x4d,0x4e,0x68,0x00,0x01,0xfc,0xe6,0x05,0xc2,0x03,0x1a,0x07,0x40,0x00,0x09,0x00,0x23,0x40,0x11,0x09,0x05,0x07,0xda,0x40,0x02,0x00,0x84,0x09,0x0e,0x0a,0x05,0x0a,0x42,0x05,0x84,0x04,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0xe1,0x00,0x18,0x2f,0x1a, 0xed,0xc4,0x32,0x31,0x30,0x01,0x02,0x21,0x20,0x03,0x33,0x12,0x21,0x20,0x13,0x03,0x1a,0xf0,0xfd,0xd6,0xfd,0xd6,0xf0,0xa2,0xba,0x01,0xbd,0x01,0xbf,0xba,0x07,0x40,0xfe,0x82,0x01,0x7e,0xfe,0xfe,0x01,0x02,0x00,0x01,0xfc,0xe6,0x05,0xc2,0x03,0x1a,0x06,0x58,0x00,0x03,0x00,0x19,0x40,0x0b,0x02,0x91,0x40,0x01,0x00,0x0e,0x04,0x04, 0x01,0x42,0x01,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x1a,0xf9,0xcc,0x06,0x34,0x05,0xc2,0x96,0x00,0x01,0xfc,0xe6,0xfe,0x70,0x03,0x1a,0xff,0x04,0x00,0x03,0x00,0x19,0x40,0x0b,0x01,0x91,0x40,0x02,0x03,0x0e,0x04,0x02,0x04,0x42,0x02,0x2f,0x2b,0x01,0x10,0xe2,0x00,0x18,0x2f,0x1a, 0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x1a,0xf9,0xcc,0x06,0x34,0xfe,0x70,0x94,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a,0x02,0x06,0x00,0xec,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x29,0x04,0x54,0x05,0xec,0x00,0x06,0x00,0xed,0x00,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x03,0xb6,0x04,0x00,0x00,0x07,0x00,0x0f,0x00,0x3c, 0x40,0x1e,0x0a,0x07,0x01,0x02,0x08,0x0c,0x01,0x0c,0x0f,0x03,0x04,0x0c,0x04,0x08,0x95,0x02,0x02,0x01,0x07,0x0f,0x04,0x01,0x15,0x0f,0x08,0x05,0x00,0x00,0x11,0x05,0x2f,0x11,0x33,0x2f,0x12,0x39,0x39,0x00,0x3f,0x33,0x3f,0x12,0x39,0x2f,0xed,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x01,0x5d,0x21,0x23,0x03,0x21, 0x03,0x23,0x01,0x33,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x03,0xb6,0xb4,0x58,0xfe,0x66,0x56,0xb0,0x01,0x75,0xc3,0x3b,0x87,0x02,0x12,0x07,0x05,0x10,0x88,0x01,0x02,0xfe,0xfe,0x04,0x00,0xfd,0x8e,0x01,0x8c,0x06,0x4e,0x1a,0x3a,0xfe,0x74,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x04,0xe4,0x04,0x00,0x00,0x0f,0x00,0x13,0x00,0x5e, 0x40,0x31,0x13,0x03,0x04,0x12,0x04,0x0c,0x95,0x40,0x0b,0x07,0x00,0x0b,0x95,0x1a,0x30,0x10,0x95,0x02,0x02,0x00,0x11,0x08,0x95,0x07,0x0f,0x04,0x0f,0x95,0x00,0x12,0x06,0x06,0x01,0x14,0x08,0x0c,0x00,0x00,0x15,0x10,0x0a,0x0e,0x84,0x01,0x01,0x15,0x14,0x04,0x05,0x2f,0x33,0x11,0x12,0x39,0x2f,0xe1,0x39,0x39,0x11,0x33,0x2f,0xc4, 0xc4,0x11,0x12,0x39,0x2f,0x33,0x00,0x2f,0xed,0xc4,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0,0x21,0x21,0x11,0x21,0x03,0x23,0x01,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x01,0x11,0x23,0x03,0x04,0xe4,0xfd,0xb6,0xfe,0xa2,0x82,0xba,0x02,0x23,0x02,0xaa,0xfe,0x6f, 0x01,0x74,0xfe,0x8c,0x01,0xa8,0xfd,0xb6,0x1d,0xfa,0x01,0x02,0xfe,0xfe,0x04,0x00,0x8c,0xfe,0xd4,0x8c,0xfe,0xd0,0x01,0x02,0x01,0xe6,0xfe,0x1a,0x00,0x03,0x00,0x52,0xff,0xe8,0x06,0x50,0x04,0x18,0x00,0x23,0x00,0x2e,0x00,0x35,0x00,0x71,0x40,0x1d,0x16,0x40,0x0b,0x0e,0x48,0x16,0x16,0x14,0x24,0x00,0x11,0x95,0x2f,0x2f,0x0c,0x14, 0x95,0x19,0x10,0x2b,0x95,0x1e,0x10,0x09,0x33,0x95,0x0c,0x16,0x04,0xb8,0xff,0xd0,0x40,0x1a,0x09,0x0c,0x48,0x04,0x02,0x95,0x07,0x16,0x05,0x05,0x21,0x83,0x28,0x28,0x37,0x00,0x09,0x1c,0x2f,0x04,0x24,0x83,0x11,0x11,0x37,0x17,0xb8,0xff,0xc0,0xb6,0x0e,0x12,0x48,0x17,0x30,0x83,0x0f,0x2f,0xe1,0xc4,0x2b,0x12,0x39,0x2f,0xe1,0x17, 0x39,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xfd,0xc6,0x2b,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x11,0x39,0x2f,0x2b,0x31,0x30,0x01,0x10,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x27,0x23,0x06,0x23,0x22,0x02,0x35,0x35,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x17,0x33,0x36,0x33,0x32,0x16, 0x15,0x10,0x05,0x25,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x07,0x21,0x16,0x16,0x33,0x32,0x36,0x03,0xcb,0xd7,0xb1,0x9b,0x94,0xc8,0xee,0x42,0x04,0x73,0xf1,0xca,0xde,0x02,0xd3,0x03,0xb0,0x99,0xaf,0x90,0x84,0xe2,0x01,0x0a,0x77,0x04,0x8d,0xf6,0x99,0xaf,0xfe,0x81,0xfe,0xfa,0xcd,0x85,0x8d,0x6a,0x5a,0x78,0xa3,0xa6, 0xfd,0xd5,0x02,0x85,0x77,0x74,0xa6,0x01,0x9c,0xfe,0xd6,0x7a,0xa4,0x60,0xc6,0xc6,0x01,0x05,0xe8,0x54,0xab,0xba,0x72,0x9a,0x62,0xe0,0xe0,0xa1,0x87,0xfe,0xd2,0x16,0x7d,0x0a,0x06,0x52,0x61,0x49,0x59,0xab,0x85,0xc0,0x90,0x9c,0xa4,0x00,0x00,0x03,0x00,0x3e,0x00,0x00,0x03,0x92,0x04,0x00,0x00,0x13,0x00,0x1b,0x00,0x23,0x00,0x48, 0x40,0x27,0x01,0x12,0x15,0x1c,0x04,0x08,0x95,0x0b,0x0b,0x1d,0x14,0x95,0x0c,0x0f,0x1d,0x95,0x07,0x15,0x12,0x01,0x19,0x83,0x10,0x10,0x03,0x20,0x00,0x00,0x03,0x83,0x20,0x20,0x25,0x15,0x0b,0x1d,0x84,0x09,0x07,0x2f,0xce,0xe1,0x39,0x39,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed, 0x12,0x39,0x2f,0xed,0x17,0x39,0x31,0x30,0x01,0x23,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x23,0x35,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x07,0x33,0x01,0x11,0x33,0x32,0x36,0x35,0x34,0x23,0x03,0x11,0x33,0x32,0x35,0x34,0x26,0x23,0x03,0x92,0x7e,0x6b,0xc4,0xab,0xfe,0x96,0x68,0x68,0x01,0x5e,0x99,0xb5,0x60,0xa0,0xfd,0xb6,0xac,0x54, 0x64,0xb8,0xac,0xba,0xd7,0x7b,0x64,0x01,0xcb,0x37,0x78,0x7f,0x9d,0x01,0xcb,0x8b,0x01,0xaa,0x8a,0x70,0x75,0x3b,0x01,0x1e,0xfe,0xe2,0x51,0x47,0x86,0xfe,0x57,0xfe,0xc1,0x99,0x4c,0x5a,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x02,0x06,0x00,0x46,0x00,0x00,0x00,0x02,0x00,0xa6,0x00,0x00,0x04,0x06,0x04,0x00,0x00,0x07, 0x00,0x0e,0x00,0x1f,0x40,0x10,0x08,0x95,0x01,0x0f,0x09,0x95,0x00,0x15,0x04,0x83,0x0c,0x0c,0x10,0x09,0x84,0x00,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x33,0x11,0x21,0x20,0x11,0x14,0x00,0x23,0x03,0x11,0x33,0x20,0x11,0x10,0x21,0xa6,0x01,0x40,0x02,0x20,0xfe,0xd5,0xfc,0x97,0x8f,0x01,0x89,0xfe,0x7b, 0x04,0x00,0xfe,0x0a,0xeb,0xfe,0xe1,0x03,0x74,0xfd,0x18,0x01,0x7a,0x01,0x6e,0x00,0x00,0x02,0x00,0x3c,0x00,0x00,0x04,0x10,0x04,0x00,0x00,0x0b,0x00,0x16,0x00,0x3f,0x40,0x22,0x10,0x0d,0x01,0x95,0x40,0x04,0x05,0x00,0x04,0x95,0x1a,0x30,0x0c,0x95,0x05,0x0f,0x11,0x95,0x00,0x15,0x0f,0x0f,0x11,0x08,0x83,0x14,0x14,0x18,0x0d,0x04, 0x11,0x84,0x02,0x00,0x2f,0xc6,0xe1,0x39,0x39,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x20,0x11,0x14,0x00,0x23,0x03,0x11,0x33,0x15,0x23,0x11,0x33,0x20,0x11,0x10,0x21,0xb0,0x74,0x74,0x01,0x40,0x02,0x20,0xfe,0xd6,0xfc, 0x98,0xec,0xec,0x90,0x01,0x88,0xfe,0x7c,0x01,0xba,0x8c,0x01,0xba,0xfe,0x0a,0xea,0xfe,0xe0,0x03,0x74,0xfe,0xd2,0x8c,0xfe,0xd2,0x01,0x7a,0x01,0x6e,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x02,0xf0,0x04,0x00,0x00,0x0b,0x00,0x32,0x40,0x1b,0x08,0x95,0x40,0x07,0x03,0x00,0x07,0x95,0x1a,0x30,0x04,0x95,0x03,0x0f,0x0b,0x95,0x00,0x15, 0x04,0x08,0x00,0x00,0x0d,0x06,0x0a,0x84,0x01,0x2f,0xe1,0x39,0x11,0x33,0x2f,0xc4,0xc4,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x21,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x02,0xf0,0xfd,0xb6,0x02,0x33,0xfe,0x6f,0x01,0x74,0xfe,0x8c,0x01,0xa8,0x04,0x00,0x8c,0xfe,0xd4,0x8c,0xfe,0xd0, 0x00,0x01,0x00,0x5a,0xff,0xe8,0x02,0xec,0x04,0x18,0x00,0x22,0x00,0x3e,0x40,0x20,0x01,0x12,0x95,0x13,0x13,0x1e,0x0b,0x1b,0x19,0x95,0x1e,0x10,0x09,0x0b,0x95,0x06,0x16,0x00,0x21,0x12,0x0e,0x83,0x03,0x03,0x21,0x83,0x16,0x16,0x24,0x12,0x08,0x1b,0x2f,0xc6,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x00,0x3f,0xfd, 0xc6,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x20,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x10,0xbb,0xca,0xa3,0x82,0x68,0x6e,0x7c,0x5a,0x6d,0x8c,0x78,0x50,0x52,0x01,0x21, 0x7e,0x72,0x86,0x74,0x72,0x98,0xb9,0xcf,0x01,0xea,0x04,0x40,0xa8,0x7d,0x99,0x2e,0x9a,0x3e,0x51,0x43,0x4b,0x59,0x8e,0xac,0x4d,0x5d,0x3e,0x96,0x32,0xa0,0x88,0xd0,0x00,0x02,0x00,0x8e,0xfe,0x27,0x01,0x64,0x04,0x00,0x00,0x03,0x00,0x0f,0x00,0x23,0x40,0x12,0x0a,0x63,0x04,0x1b,0x00,0x15,0x03,0x0f,0x0d,0x62,0x07,0x07,0x00,0x84, 0x01,0x01,0x11,0x10,0x11,0x12,0x39,0x2f,0xe1,0x33,0x2f,0xe1,0x00,0x3f,0x3f,0x3f,0xed,0x31,0x30,0x21,0x23,0x11,0x33,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x48,0xa2,0xa2,0x50,0x2c,0x3e,0x3e,0x2c,0x2d,0x3f,0x3f,0x04,0x00,0xfa,0x27,0x3d,0x2e,0x2e,0x3c,0x3e,0x2c,0x2e,0x3d,0x00,0x00,0x01,0x00,0x14, 0xff,0xec,0x01,0xd3,0x04,0x00,0x00,0x0b,0x00,0x1b,0x40,0x0d,0x0b,0x0f,0x05,0x07,0x95,0x02,0x16,0x09,0x84,0x00,0x00,0x0d,0x04,0x2f,0x11,0x33,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0x31,0x30,0x01,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x01,0xd3,0xfe,0xb9,0x40,0x38,0x32,0x3d,0xac,0xa4,0x01,0x72,0xfe,0x7a,0x14, 0x94,0x1d,0x01,0x00,0x02,0x89,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x02,0x06,0x01,0x67,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0x04,0x04,0x00,0x00,0x0d,0x00,0x45,0x40,0x23,0x0b,0x02,0x03,0x0a,0x03,0x08,0x05,0x04,0x09,0x0a,0x09,0x04,0x03,0x09,0x03,0x09,0x03,0x01,0x06,0x0f,0x0c,0x95,0x01,0x15,0x0a,0x0a, 0x00,0x00,0x0f,0x08,0x05,0x0c,0x84,0x03,0x01,0x2f,0xce,0xe1,0x39,0x39,0x11,0x33,0x2f,0x39,0x2f,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x87,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0x21,0x21,0x11,0x07,0x35,0x37,0x11,0x33,0x11,0x37,0x15,0x07,0x11,0x21,0x03,0x04,0xfd,0xa2,0x64,0x64,0xa2,0xf0,0xf0, 0x01,0xbc,0x01,0x74,0x38,0x8a,0x3a,0x02,0x00,0xfe,0x5c,0x88,0x8e,0x87,0xfe,0xbd,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0xf8,0x04,0x00,0x02,0x06,0x02,0x13,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x00,0x04,0x00,0x02,0x06,0x02,0x0f,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x02,0x06,0x00,0x52,0x00,0x00, 0x00,0x01,0x00,0x5a,0xff,0xe8,0x03,0x6c,0x04,0x18,0x00,0x15,0x00,0x34,0x40,0x1f,0x40,0x0b,0x50,0x0b,0x02,0x0b,0x0b,0x09,0x95,0x0e,0x10,0x4f,0x01,0x5f,0x01,0x6f,0x01,0x03,0x01,0x01,0x03,0x95,0x14,0x16,0x11,0x83,0x06,0x06,0x17,0x0b,0x00,0x2f,0xc4,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x3f,0xed,0x32,0x2f,0x5d, 0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x5a,0x6c,0x86,0xa6,0xd2,0xcd,0x9f,0x8e,0x70,0x7c,0x9a,0xe6,0x01,0x16,0xfe,0xcd,0xeb,0x84,0x18,0x9a,0x40,0xda,0xb8,0xb3,0xd7,0x46,0x95,0x3b,0xfe,0xde,0xea,0xef,0xfe,0xcb,0x00,0x02,0x00,0x60,0x00,0x08, 0x04,0x92,0x03,0xf8,0x00,0x0b,0x00,0x17,0x00,0x1f,0x40,0x10,0x0c,0xf4,0x06,0x0f,0x12,0xf4,0x00,0x15,0x09,0xed,0x15,0x15,0x19,0x0f,0xed,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x25,0x22,0x00,0x35,0x34,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x02,0x79,0xf2,0xfe,0xd9,0x01,0x28,0xf1,0xf2,0x01,0x27,0xfe,0xd7,0xf2,0xb9,0xd2,0xd2,0xbd,0xb7,0xd4,0xd2,0x08,0x01,0x15,0xe5,0xe7,0x01,0x0f,0xfe,0xeb,0xe5,0xe5,0xfe,0xef,0x03,0x48,0xb6,0x9a,0xa2,0xae,0xb5,0x9b,0xa1,0xaf,0x00,0x00,0x01,0x00,0x60,0x00,0xb6,0x04,0x92,0x03,0xf8,0x00,0x15,0x00,0x29,0x40,0x14,0x0b,0x00, 0x00,0x17,0x06,0xf4,0x11,0x0f,0x01,0x14,0xed,0x03,0x03,0x17,0x0e,0x0b,0x0b,0x09,0xed,0x0e,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xe1,0xc6,0x00,0x3f,0xed,0x12,0x39,0x2f,0xc4,0x31,0x30,0x25,0x23,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x00,0x33,0x32,0x00,0x15,0x14,0x04,0x50,0x92,0x48,0xd8, 0xb5,0xb3,0xda,0x47,0x91,0x42,0x01,0x2f,0xec,0xec,0x01,0x2b,0xb6,0x7a,0xab,0xab,0xcc,0xd0,0xa7,0xa5,0x80,0x8e,0x9b,0xf0,0x01,0x29,0xfe,0xdf,0xe9,0xae,0x00,0x03,0x00,0x4c,0xff,0xe8,0x04,0xa6,0x04,0x18,0x00,0x13,0x00,0x1b,0x00,0x23,0x00,0x7d,0x40,0x47,0x15,0x15,0x16,0x14,0x14,0x1b,0x13,0x13,0x12,0x0c,0x0c,0x0d,0x0b,0x00, 0x0b,0x1d,0x1d,0x1e,0x1c,0x1c,0x23,0x09,0x09,0x08,0x02,0x02,0x03,0x0a,0x01,0x0a,0x00,0x01,0x04,0x0a,0x0b,0x14,0x15,0x1c,0x1d,0x04,0x22,0x1a,0x02,0x09,0x0c,0x13,0x04,0x04,0x1a,0xf4,0x0e,0x0f,0x22,0xf4,0x04,0x15,0x01,0x00,0x00,0x11,0x0b,0x0a,0x07,0x11,0xed,0x17,0x17,0x25,0x1f,0xed,0x07,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x10, 0xc6,0x32,0x10,0xc2,0x2f,0x32,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0xc6,0x32,0x10,0xc6,0x32,0x31,0x30,0x10,0x87,0x08,0xc0,0x08,0xc0,0x08,0xc0,0x08,0xc0,0x10,0x87,0x08,0xc0,0x08,0xc0,0x08,0xc0,0x08,0xc0,0x25,0x07,0x27,0x06,0x23,0x22,0x00,0x35,0x34,0x37,0x27,0x37,0x17,0x36,0x33,0x32,0x00,0x15,0x14, 0x07,0x01,0x01,0x36,0x35,0x34,0x26,0x23,0x22,0x01,0x01,0x06,0x15,0x14,0x16,0x33,0x32,0x04,0xa6,0x48,0x8b,0x8b,0xcf,0xf2,0xfe,0xd9,0x71,0x85,0x48,0x8a,0x8c,0xcf,0xf2,0x01,0x27,0x71,0xfd,0x77,0x02,0x18,0x56,0xd2,0xbd,0x82,0x01,0x65,0xfd,0xe8,0x56,0xd2,0xbd,0x81,0x33,0x4b,0x84,0x64,0x01,0x15,0xe5,0xc8,0x82,0x81,0x4b,0x84, 0x64,0xfe,0xeb,0xe5,0xc8,0x82,0x02,0x6d,0xfd,0xfb,0x5a,0x8a,0xa1,0xaf,0xfd,0x8f,0x02,0x05,0x5a,0x8a,0xa2,0xae,0x00,0x03,0x00,0x52,0xff,0xe8,0x07,0x10,0x04,0x18,0x00,0x1c,0x00,0x28,0x00,0x2f,0x00,0x58,0x40,0x29,0x0d,0x40,0x0b,0x0e,0x48,0x0d,0x0d,0x0b,0x08,0x95,0x29,0x29,0x0b,0x03,0x10,0x0b,0x1d,0x95,0x15,0x10,0x2d,0x03, 0x23,0x95,0x1b,0x16,0x18,0x83,0x26,0x26,0x31,0x00,0x12,0x29,0x03,0x20,0x83,0x08,0x08,0x31,0x0d,0xb8,0xff,0xc0,0xb6,0x0e,0x12,0x48,0x0d,0x2a,0x83,0x06,0x2f,0xe1,0xc4,0x2b,0x12,0x39,0x2f,0xe1,0x17,0x39,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x39,0x39,0x3f,0xed,0x39,0x39,0x11,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x2b,0x31,0x30, 0x25,0x23,0x06,0x21,0x22,0x02,0x35,0x35,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x17,0x33,0x36,0x21,0x32,0x00,0x15,0x10,0x00,0x23,0x20,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x21,0x16,0x16,0x33,0x32,0x36,0x03,0x72,0x04,0x76,0xfe,0xf6,0xc2,0xda,0x02,0xd3,0x03,0xb0,0x9b,0xad,0x90,0x88, 0xda,0x01,0x10,0x71,0x04,0x83,0x01,0x1a,0xe5,0x01,0x0d,0xfe,0xe6,0xf0,0xfe,0xd9,0x01,0x35,0xa0,0xa9,0xab,0x9c,0x9f,0xb9,0xb9,0xfd,0x72,0xfd,0xd7,0x02,0x84,0x74,0x78,0xa6,0xd3,0xeb,0x01,0x05,0xe4,0x58,0xab,0xba,0x72,0x9a,0x62,0xed,0xed,0xfe,0xe4,0xee,0xfe,0xfc,0xfe,0xde,0x03,0xa6,0xcf,0xbb,0xc2,0xd0,0xd9,0xbf,0xb5,0xcf, 0xfe,0x10,0x8e,0x9e,0xa9,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x03,0xea,0x04,0x00,0x00,0x1f,0x00,0x2b,0x00,0x3f,0x40,0x21,0x14,0x00,0x20,0x95,0x0a,0x0a,0x26,0x05,0x10,0x0f,0x26,0x95,0x1a,0x16,0x14,0x00,0x02,0x0d,0x84,0x12,0x12,0x17,0x83,0x29,0x29,0x2d,0x1d,0x07,0x84,0x02,0x23,0x83,0x1d,0x2f,0xe1,0xd4,0xe1,0x11,0x12,0x39, 0x2f,0xf1,0xc0,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xc4,0x12,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x01,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x05,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x01,0x40,0xa6,0x1c,0xa0,0x1c,0x7e,0x6d,0x6d,0x7e,0x1c,0xa2,0x1a,0xa8,0x68,0x7a,0xfe,0xcb,0xd1,0xf0,0x78,0x01,0x4d,0x82,0x9b,0xa0,0x7d,0x81,0x9c,0x9f,0x02,0x7f,0x4b,0xa4,0x46,0x4c,0x45,0x40,0x56,0x6b,0x6b,0x56,0x40,0x45,0x46,0x4c,0x9e,0x51,0x26,0x9f,0x66,0xa2,0xca,0xc1,0xa3,0x65,0xa5,0x27,0x78,0x67,0x66,0x78,0x7a, 0x68,0x63,0x78,0x00,0x00,0x01,0x00,0x60,0x02,0x00,0x04,0x62,0x04,0x18,0x00,0x0d,0x00,0x1d,0x40,0x0e,0x07,0x00,0x04,0x95,0x0b,0x10,0x00,0x83,0x01,0x01,0x0f,0x07,0x83,0x08,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0xc4,0x32,0x31,0x30,0x01,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x00,0x33,0x32,0x00,0x04,0x62,0xa8, 0xb9,0xa1,0x9f,0xb9,0xa8,0x01,0x1f,0xe9,0xe7,0x01,0x13,0x02,0x00,0xbc,0xd2,0xd8,0xb6,0xee,0x01,0x2a,0xfe,0xde,0x00,0x01,0x00,0x60,0xff,0xe8,0x04,0x62,0x02,0x00,0x00,0x0d,0x00,0x1d,0x40,0x0e,0x0d,0x06,0x0a,0x95,0x03,0x16,0x00,0x83,0x0d,0x0d,0x0f,0x07,0x83,0x06,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0xd4,0xc4,0x31, 0x30,0x01,0x14,0x00,0x23,0x22,0x00,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x04,0x62,0xfe,0xe1,0xe9,0xe6,0xfe,0xec,0xa8,0xb9,0xa1,0x9f,0xb9,0x02,0x00,0xef,0xfe,0xd7,0x01,0x22,0xf6,0xbc,0xd2,0xd8,0xb6,0x00,0x02,0x00,0xa6,0x00,0x00,0x03,0x52,0x04,0x00,0x00,0x0a,0x00,0x11,0x00,0x27,0x40,0x14,0x0c,0x95,0x00,0x00,0x01,0x0b, 0x95,0x03,0x0f,0x01,0x15,0x07,0x83,0x0f,0x0f,0x13,0x0c,0x01,0x84,0x02,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x03,0x11,0x33,0x32,0x35,0x34,0x23,0x01,0x48,0xa2,0x01,0x33,0xb4,0xc5,0xd4,0xb8,0x7e,0x7e,0xe6,0xd9,0x01,0x70, 0xfe,0x90,0x04,0x00,0xa1,0x99,0x98,0xbe,0x02,0x04,0xfe,0x88,0xc2,0xb6,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0xfc,0x04,0x00,0x00,0x12,0x00,0x1a,0x00,0x3b,0x40,0x1e,0x0b,0x02,0x95,0x13,0x13,0x00,0x14,0x95,0x12,0x0f,0x07,0x00,0x15,0x06,0x09,0x0b,0x09,0x08,0x13,0x00,0x84,0x01,0x01,0x1c,0x17,0x84,0x0e,0x0e,0x07,0x08,0x2f,0x33, 0x33,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x39,0x12,0x39,0x39,0x11,0x33,0x00,0x3f,0xc4,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x21,0x23,0x11,0x23,0x22,0x06,0x07,0x03,0x23,0x13,0x36,0x37,0x35,0x26,0x35,0x34,0x36,0x33,0x21,0x03,0x11,0x23,0x22,0x15,0x14,0x16,0x33,0x02,0xfc,0xa2,0x58,0x42,0x51,0x23,0x79,0xb5,0x8e,0x34,0x53, 0xe5,0xc6,0xae,0x01,0x3a,0xa2,0x98,0xd0,0x6e,0x5e,0x01,0xa6,0x3f,0x53,0xfe,0xec,0x01,0x35,0x71,0x29,0x04,0x2b,0xd7,0x87,0xa4,0xfe,0x31,0x01,0x43,0x9d,0x4f,0x57,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0xfc,0x04,0x00,0x00,0x11,0x00,0x18,0x00,0x3b,0x40,0x1e,0x06,0x13,0x95,0x0f,0x0f,0x12,0x0b,0x11,0x0f,0x12,0x95,0x00,0x15,0x0c, 0x09,0x09,0x06,0x0a,0x0f,0x00,0x84,0x12,0x12,0x1a,0x16,0x84,0x04,0x04,0x0b,0x0a,0x2f,0x33,0x33,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x33,0x12,0x39,0x39,0x11,0x33,0x00,0x3f,0xed,0x3f,0xc4,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x21,0x21,0x22,0x26,0x35,0x34,0x37,0x35,0x26,0x27,0x03,0x33,0x13,0x16,0x33,0x33,0x11,0x33,0x03,0x11,0x23, 0x22,0x15,0x14,0x33,0x02,0xfc,0xfe,0xae,0xa5,0xb7,0xea,0x53,0x39,0x8e,0xb9,0x75,0x3e,0x78,0x58,0xa2,0xa2,0x9c,0xcc,0xc4,0x98,0x84,0xda,0x31,0x04,0x21,0x7c,0x01,0x38,0xfe,0xec,0x92,0x01,0xa6,0xfc,0x8c,0x01,0x43,0xa8,0x9b,0xff,0xff,0x00,0x1e,0x00,0x00,0x03,0x29,0x04,0x00,0x02,0x06,0x02,0x19,0x00,0x00,0x00,0x01,0x00,0x90, 0xff,0xe8,0x03,0xb6,0x04,0x00,0x00,0x0d,0x00,0x1e,0x40,0x0f,0x06,0x0d,0x0f,0x09,0x95,0x02,0x16,0x0d,0x84,0x0c,0x0c,0x0f,0x06,0x84,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x33,0x31,0x30,0x01,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x11,0x11,0x33,0x03,0xb6,0xfe,0x64,0xfe,0x76,0xa1,0xf2,0xf1,0xa2, 0x01,0xa6,0xfe,0x42,0x01,0xb2,0x02,0x66,0xfd,0xa2,0xfe,0xd0,0x01,0x2a,0x02,0x64,0x00,0x01,0x00,0x66,0x00,0x5a,0x04,0x38,0x03,0xac,0x00,0x12,0x00,0x2a,0x40,0x14,0x00,0xf4,0x01,0x01,0x13,0x0d,0x08,0xf4,0x09,0x0c,0x04,0x0b,0x0b,0x0f,0xed,0x04,0x04,0x14,0x08,0x00,0x2f,0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x33,0x00,0x2f, 0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x37,0x35,0x21,0x20,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x15,0x23,0x15,0x16,0x15,0x14,0x06,0x23,0x66,0x02,0x0c,0x01,0x3a,0xad,0x88,0xfd,0xef,0x03,0xb8,0x80,0x9a,0xef,0xd5,0x5a,0xa4,0xf2,0x74,0xa6,0xa2,0xa2,0x04,0x6b,0xc2,0xb0,0xcf,0x00,0x03,0x00,0x3e,0x00,0x5a,0x05,0x6c,0x03,0xac, 0x00,0x12,0x00,0x1e,0x00,0x2a,0x00,0x49,0x40,0x25,0x19,0x63,0x13,0x1f,0x63,0x25,0x13,0x25,0x13,0x09,0x00,0xf4,0x01,0x01,0x13,0x0d,0x08,0xf4,0x09,0x0c,0x04,0x0b,0x0b,0x0f,0xed,0x04,0x04,0x2c,0x08,0x00,0x00,0x2c,0x1c,0x16,0x28,0x62,0x22,0x2f,0xe1,0x39,0x39,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x33,0x00, 0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0xed,0x10,0xed,0x31,0x30,0x25,0x35,0x21,0x20,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x15,0x23,0x15,0x16,0x15,0x14,0x06,0x23,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x9c,0x02,0x0c, 0x01,0x3a,0xae,0x88,0xfd,0xf0,0x03,0xb8,0x81,0x99,0xed,0xd5,0xfc,0xf6,0x2a,0x38,0x38,0x2a,0x29,0x39,0x38,0x2a,0x2a,0x38,0x38,0x2a,0x29,0x39,0x38,0x5a,0xa4,0xf2,0x73,0xa7,0xa2,0xa2,0x04,0x6b,0xc2,0xb1,0xce,0x02,0x12,0x3b,0x28,0x29,0x3b,0x3b,0x29,0x29,0x3a,0xfe,0x80,0x38,0x28,0x29,0x3b,0x39,0x29,0x28,0x3a,0x00,0x00,0x01, 0x00,0x66,0xff,0x2d,0x04,0x38,0x04,0xd7,0x00,0x1f,0x00,0x3e,0x40,0x1f,0x01,0xf4,0x40,0x00,0x0e,0x09,0x0a,0x12,0x42,0x15,0x11,0xf4,0x12,0x1b,0x09,0xf4,0x0a,0x14,0x14,0x1b,0x15,0x18,0x0d,0x1d,0xed,0x05,0x05,0x21,0x11,0x09,0x00,0x2f,0x32,0x32,0x11,0x39,0x2f,0xf1,0x39,0x39,0x33,0x33,0xc0,0x2f,0x00,0x2f,0xed,0x39,0xd6,0xed, 0x32,0x2b,0x00,0x18,0x10,0xf6,0x1a,0xed,0x31,0x30,0x17,0x35,0x21,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x20,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x15,0x23,0x15,0x16,0x15,0x14,0x06,0x07,0x16,0x15,0x10,0x21,0x66,0x02,0x04,0xab,0x97,0xbc,0x8a,0xfe,0x00,0x02,0x19,0x01,0x2d,0xb4,0x92,0xfe,0x00,0x03,0xb8,0x8c,0xa6,0x76, 0x60,0xd6,0xfe,0x47,0xd3,0xa2,0x6a,0x75,0x6f,0x93,0xa2,0xe6,0x70,0x8d,0xa2,0xa2,0x04,0x5b,0xbc,0x6f,0xab,0x27,0x61,0xd4,0xfe,0x89,0xff,0xff,0x00,0x0e,0x00,0x00,0x03,0xcb,0x04,0x00,0x02,0x06,0x00,0x59,0x00,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x04,0x00,0x02,0x06,0x00,0x5a,0x00,0x00,0xff,0xff,0x00,0x21,0x00,0x00, 0x03,0x70,0x04,0x00,0x02,0x06,0x00,0x5d,0x00,0x00,0x00,0x01,0x00,0x50,0xff,0xe8,0x02,0xf8,0x04,0x00,0x00,0x17,0x00,0x3d,0x40,0x1f,0x0a,0x08,0x52,0x10,0x10,0x03,0x0f,0x0c,0x95,0x0d,0x0f,0x01,0x03,0x95,0x16,0x16,0x10,0x0a,0x0a,0x06,0x0c,0x0b,0x0f,0x0f,0x13,0x84,0x06,0x06,0x19,0x0c,0x00,0x2f,0xc4,0x12,0x39,0x2f,0xf1,0xc0, 0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x39,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x21,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x50,0x6a,0x92,0x7a,0x8e,0xfe,0xdd,0x3d,0x01,0x06,0xfe,0x56,0x02,0x8b,0xfe,0xed,0x8e,0xa2,0xf0, 0xc6,0x89,0x18,0x96,0x3c,0x66,0x59,0xc1,0x3d,0x01,0x45,0x8c,0x46,0xfe,0xac,0x13,0xa4,0x7c,0x92,0xb9,0x00,0x01,0x00,0x50,0xff,0xe8,0x02,0xfa,0x04,0x18,0x00,0x25,0x00,0x42,0x40,0x22,0x14,0x13,0x07,0x01,0x00,0x0c,0x1f,0x1c,0x1a,0x95,0x1f,0x10,0x09,0x07,0x95,0x0c,0x16,0x00,0x83,0x14,0x14,0x18,0x0f,0x09,0x09,0x22,0x83,0x18, 0x18,0x27,0x1c,0x05,0x83,0x0f,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x10,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x01,0x15,0x06,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x37,0x35,0x36,0x37,0x36,0x35,0x34,0x23,0x22, 0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x01,0xf8,0x2e,0x56,0x7e,0xe5,0x9b,0x76,0x7c,0xa5,0xb3,0xc8,0x9e,0x3a,0x2a,0x2e,0x55,0x7f,0xe6,0x9a,0x76,0x7c,0xa5,0xb3,0xc8,0x9e,0x3a,0x02,0x0a,0x54,0x1e,0x28,0x3a,0x4a,0x7a,0x4c,0x97,0x3f,0x8c,0x72,0x90,0x4a,0x1c,0x1a,0x54,0x1e,0x28,0x3a,0x4a,0x7a,0x4c,0x97,0x3f,0x8c, 0x72,0x90,0x4a,0x1c,0x00,0x01,0x00,0x14,0xff,0xe8,0x04,0x25,0x04,0x18,0x00,0x1b,0x00,0x3b,0x40,0x1e,0x12,0x10,0x09,0x1b,0x0b,0x06,0x19,0x95,0x02,0x16,0x04,0x0d,0x17,0x03,0x0f,0x1b,0x0e,0x15,0x0f,0x40,0x0f,0x09,0x42,0x09,0x09,0x1c,0x0f,0x0f,0x1d,0x1c,0x11,0x12,0x39,0x2f,0x12,0x39,0x2f,0x2b,0x01,0x1a,0x18,0x10,0xdd,0xe2, 0x12,0x17,0x39,0x00,0x3f,0xfd,0x39,0x39,0xd6,0xc4,0x3f,0x31,0x30,0x25,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x33,0x32,0x37,0x04,0x25,0x61,0x82,0x99,0x8d,0x8c,0x94,0x81,0x67,0x6e,0x74,0x60,0x62,0xe9,0xb6,0x9c,0x9b,0xae,0xe7,0x63,0x64,0x71, 0x6a,0x38,0x50,0x7a,0x7a,0x4d,0xa8,0x6b,0x54,0xe7,0xf5,0xa4,0xd2,0xcb,0xa5,0xfc,0xe6,0x54,0x67,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0xdf,0x04,0x00,0x02,0x06,0x02,0x0a,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x00,0x03,0xb6,0x04,0x00,0x00,0x0b,0x00,0x17,0x40,0x0a,0x04,0x0b,0x0f,0x00,0x09,0x15,0x00,0x00,0x0d,0x09,0x2f,0x11, 0x33,0x2f,0x00,0x3f,0xc4,0x3f,0x33,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x33,0x03,0xb6,0xb2,0xfe,0xf2,0x02,0x12,0x05,0x05,0x10,0xfe,0xf2,0xb0,0x01,0x79,0xc1,0x03,0x14,0x06,0x4e,0x1b,0x39,0xfc,0xec,0x04,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x02,0x06,0x02,0x16,0x00,0x00, 0xff,0xff,0x00,0xa6,0x00,0x00,0x03,0x52,0x04,0x00,0x02,0x06,0x07,0x7a,0x00,0x00,0x00,0x01,0x00,0x60,0x00,0x00,0x04,0x5a,0x04,0x00,0x00,0x13,0x00,0x4c,0x40,0x29,0x0c,0x05,0x0f,0x96,0x40,0x02,0x02,0x03,0x0e,0x09,0x13,0x0f,0x03,0x15,0x11,0x84,0x00,0x0e,0x03,0x0a,0x84,0x07,0x04,0x07,0x42,0x07,0x07,0x14,0x0f,0x0c,0x03,0x84, 0x4f,0x04,0x5f,0x04,0x02,0x04,0x04,0x15,0x14,0x11,0x12,0x39,0x2f,0x5d,0xe1,0x39,0x39,0x12,0x39,0x2f,0x2b,0x01,0x10,0xe1,0x10,0xf0,0xe1,0x00,0x18,0x3f,0x3f,0x33,0x33,0x12,0x39,0x2f,0x1a,0xed,0x39,0x39,0x31,0x30,0x01,0x10,0x05,0x11,0x23,0x11,0x24,0x11,0x11,0x33,0x11,0x14,0x05,0x11,0x33,0x11,0x24,0x35,0x11,0x33,0x04,0x5a, 0xfe,0x54,0xa2,0xfe,0x54,0xa2,0x01,0x0a,0xa2,0x01,0x0a,0xa2,0x02,0x92,0xfe,0xa0,0x18,0xfe,0xe6,0x01,0x1a,0x12,0x01,0x60,0x01,0x74,0xfe,0x92,0xee,0x08,0x02,0x64,0xfd,0x9c,0x0c,0xea,0x01,0x6e,0x00,0x01,0x00,0x0a,0xff,0xf4,0x03,0xd7,0x04,0x00,0x00,0x10,0x00,0x2a,0x40,0x15,0x02,0x95,0x10,0x0f,0x09,0x0b,0x95,0x06,0x01,0x00, 0x15,0x03,0x0f,0x0f,0x09,0x00,0x84,0x01,0x01,0x12,0x09,0x2f,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x00,0x3f,0x10,0xd4,0xfd,0xc6,0x3f,0xed,0x31,0x30,0x21,0x23,0x11,0x21,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x12,0x11,0x21,0x03,0xd7,0xa2,0xfe,0x67,0x0d,0x94,0xa1,0x26,0x2a,0x20,0x1e,0x41,0x48,0x2b,0x02,0xdb, 0x03,0x74,0xfd,0xb0,0xfe,0xd0,0x0c,0x8c,0x0d,0x7e,0x01,0x90,0x01,0x73,0x00,0x02,0x00,0x0a,0x02,0x9a,0x02,0xd7,0x05,0x9a,0x00,0x07,0x00,0x0f,0x00,0x4e,0x40,0x10,0x02,0x08,0x09,0x0a,0x0b,0x0c,0x01,0x0c,0x0d,0x0e,0x0f,0x03,0x04,0x0c,0x04,0x03,0xb8,0x01,0x0e,0xb2,0x0f,0x0f,0x06,0xbc,0x01,0x06,0x00,0x01,0x01,0x0a,0x00,0x05, 0x01,0x0a,0xb6,0x0f,0x08,0x05,0x00,0x00,0x11,0x05,0x2f,0x11,0x33,0x2f,0x12,0x39,0x39,0x00,0x3f,0x3f,0x3f,0x39,0x2f,0xed,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0,0x0e,0xc0,0xc0,0x10,0x87,0x05,0xc0,0x0e,0xc0,0xc0,0x05,0xc0,0xc0,0x01,0x23,0x27,0x21,0x07,0x23,0x01,0x33,0x13,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x02,0xd7,0x8f,0x44, 0xfe,0xd5,0x3f,0x90,0x01,0x1d,0x97,0x24,0x63,0x03,0x0a,0x04,0x05,0x09,0x64,0x02,0x9a,0xbe,0xbe,0x03,0x00,0xfe,0x2e,0x01,0x22,0x0a,0x31,0x22,0x19,0xfe,0xde,0x00,0x00,0x02,0xff,0xf6,0x02,0x9a,0x03,0x9e,0x05,0x9a,0x00,0x0f,0x00,0x13,0x00,0x76,0xb5,0x13,0x03,0x04,0x12,0x04,0x0d,0xb8,0x01,0x0e,0xb4,0x40,0x0a,0x06,0x01,0x0a, 0xb8,0x01,0x0e,0xb2,0xff,0x30,0x03,0xb8,0x01,0x0e,0xb3,0x13,0x13,0x06,0x0e,0xb8,0x01,0x0e,0xb2,0x01,0x01,0x05,0xbe,0x01,0x0a,0x00,0x09,0x01,0x0e,0x00,0x12,0x01,0x0e,0x00,0x06,0x01,0x06,0x40,0x09,0x03,0x04,0x12,0x13,0x04,0x05,0x10,0x0a,0x0e,0xb8,0x01,0x0c,0x40,0x09,0x01,0x01,0x05,0x08,0x0c,0x00,0x00,0x15,0x05,0x2f,0x12, 0x39,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0xe1,0x39,0x39,0x12,0x17,0x39,0x00,0x3f,0xed,0xed,0x3f,0x33,0x10,0xed,0x12,0x39,0x2f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0,0x01,0x21,0x35,0x21,0x07,0x23,0x01,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x25,0x11,0x23,0x03,0x03,0x9e,0xfe,0x50,0xff,0x00, 0x60,0x98,0x01,0xa2,0x01,0xf6,0xfe,0xe2,0x01,0x09,0xfe,0xf7,0x01,0x2e,0xfe,0x50,0x0f,0xb8,0x02,0x9a,0xbe,0xbe,0x03,0x00,0x71,0xd9,0x6c,0xda,0xbe,0x01,0x63,0xfe,0x9d,0x00,0x00,0x03,0x00,0x7b,0x02,0x9a,0x02,0x89,0x05,0x9a,0x00,0x0c,0x00,0x13,0x00,0x1a,0x00,0x57,0xb1,0x07,0x14,0xb8,0x01,0x0e,0xb4,0x40,0x0e,0x01,0x00,0x0e, 0xb8,0x01,0x0e,0xb2,0x32,0x30,0x15,0xbe,0x01,0x0e,0x00,0x00,0x01,0x0a,0x00,0x0d,0x01,0x0e,0x00,0x01,0x01,0x06,0xb3,0x06,0x09,0x0e,0x11,0xb8,0x01,0x0c,0xb2,0x04,0x04,0x09,0xb8,0x01,0x0c,0xb4,0x18,0x18,0x1c,0x0e,0x15,0xb9,0x01,0x0c,0x00,0x00,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x00,0x3f,0xed, 0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x13,0x11,0x33,0x20,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x03,0x15,0x33,0x32,0x35,0x34,0x23,0x03,0x15,0x33,0x32,0x35,0x34,0x23,0x7b,0xe7,0x01,0x06,0x89,0xaa,0x99,0x84,0x6e,0x5a,0x8a,0x8c,0x58,0x6e,0x96,0xa0,0x02,0x9a,0x03,0x00,0xbf,0x7d,0x29,0x02,0x19,0x9f, 0x68,0x79,0x02,0x8f,0xc9,0x66,0x63,0xfe,0xc7,0xe6,0x71,0x75,0x00,0x03,0x00,0x23,0x02,0x9a,0x02,0xb2,0x05,0x9a,0x00,0x12,0x00,0x19,0x00,0x20,0x00,0x64,0xb5,0x01,0x11,0x14,0x1a,0x04,0x08,0xb8,0x01,0x0e,0xb4,0x40,0x0b,0x0c,0x07,0x0b,0xb8,0x01,0x0e,0xb2,0x32,0x30,0x1b,0xbe,0x01,0x0e,0x00,0x07,0x01,0x0a,0x00,0x13,0x01,0x0e, 0x00,0x0c,0x01,0x06,0xb4,0x11,0x01,0x03,0x14,0x17,0xb8,0x01,0x0c,0xb5,0x0f,0x0f,0x03,0x00,0x00,0x03,0xb8,0x01,0x0c,0xb7,0x1e,0x1e,0x22,0x14,0x0b,0x1b,0x09,0x07,0x2f,0xc6,0xc1,0x39,0x39,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x10,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x17,0x39, 0x31,0x30,0x01,0x23,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x20,0x15,0x14,0x07,0x33,0x25,0x15,0x33,0x32,0x35,0x34,0x23,0x03,0x15,0x33,0x32,0x35,0x34,0x23,0x02,0xb2,0x6a,0x56,0x97,0x86,0xf1,0x6d,0x6d,0xe7,0x01,0x06,0x48,0x7d,0xfe,0x60,0x5a,0x8a,0x8c,0x58,0x6f,0x95,0x9f,0x03,0xf0,0x28,0x58,0x62,0x74, 0x01,0x56,0x70,0x01,0x3a,0xbf,0x53,0x28,0xc9,0xc9,0x66,0x63,0xfe,0xc7,0xe6,0x6d,0x79,0x00,0x00,0x02,0x00,0x7b,0x02,0x9a,0x03,0x08,0x05,0x9a,0x00,0x07,0x00,0x0f,0x00,0x2d,0x41,0x0a,0x00,0x09,0x01,0x0e,0x00,0x00,0x01,0x0a,0x00,0x08,0x01,0x0e,0x00,0x01,0x01,0x06,0x00,0x04,0x01,0x0c,0xb3,0x0d,0x0d,0x11,0x09,0xb9,0x01,0x0c, 0x00,0x00,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x13,0x11,0x33,0x20,0x11,0x14,0x06,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x7b,0xf1,0x01,0x9c,0xe2,0xc0,0x68,0x64,0x89,0x96,0xfe,0xe7,0x02,0x9a,0x03,0x00,0xfe,0x87,0xb1,0xd6,0x02,0x8f,0xfd,0xe1,0x90,0x84,0x01,0x0b,0x00,0x00,0x01,0x00,0x7b, 0x02,0x9a,0x02,0x2b,0x05,0x9a,0x00,0x0b,0x00,0x43,0xb9,0x00,0x09,0x01,0x0e,0xb4,0x40,0x06,0x02,0x01,0x06,0xb8,0x01,0x0e,0xb2,0xff,0x30,0x0a,0xbe,0x01,0x0e,0x00,0x01,0x01,0x0a,0x00,0x05,0x01,0x0e,0x00,0x02,0x01,0x06,0xb6,0x04,0x08,0x00,0x00,0x0d,0x06,0x0a,0xb9,0x01,0x0c,0x00,0x01,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xc4,0xc4, 0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x02,0x2b,0xfe,0x50,0x01,0x9f,0xfe,0xe4,0x01,0x08,0xfe,0xf8,0x01,0x2d,0x02,0x9a,0x03,0x00,0x71,0xd7,0x70,0xd8,0x00,0x00,0x01,0x00,0x48,0x02,0x9a,0x01,0xf8,0x05,0x9a,0x00,0x0b,0x00,0x43,0xb9,0x00, 0x04,0x01,0x0e,0xb4,0x40,0x07,0x0b,0x00,0x07,0xb8,0x01,0x0e,0xb2,0xff,0x30,0x03,0x41,0x09,0x01,0x0e,0x00,0x00,0x01,0x0a,0x00,0x08,0x01,0x0e,0x00,0x0b,0x01,0x06,0x00,0x00,0x01,0x0c,0xb6,0x07,0x03,0x03,0x0d,0x09,0x05,0x01,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31, 0x30,0x01,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x01,0xf8,0xfe,0x50,0x01,0x2c,0xfe,0xf8,0x01,0x08,0xfe,0xe4,0x01,0xa0,0x02,0x9a,0x70,0xd8,0x70,0xd7,0x71,0x00,0x01,0x00,0x3e,0x02,0x89,0x02,0xcb,0x05,0xaa,0x00,0x19,0x00,0x50,0xb9,0x00,0x17,0x01,0x0e,0xb5,0x18,0x18,0x08,0x15,0x00,0x13,0xba,0x01,0x0e,0x00, 0x02,0x01,0x0b,0xb4,0xaf,0x0b,0x01,0x0b,0x0d,0xba,0x01,0x0e,0x00,0x08,0x01,0x07,0xb6,0x17,0x17,0x16,0x10,0x0b,0x0b,0x19,0xb8,0x01,0x0c,0xb3,0x16,0x16,0x1b,0x10,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0xed,0x32,0x32,0x11,0x39,0x2f,0xed,0x31,0x30, 0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x35,0x23,0x35,0x21,0x02,0xcb,0x75,0x96,0xb2,0xd0,0xe7,0xb8,0x77,0x5e,0x62,0x75,0x7a,0x9d,0x8d,0x77,0x49,0x37,0x9c,0x01,0x1f,0x02,0xcb,0x42,0xd0,0xb5,0xb7,0xe5,0x27,0x81,0x38,0xa2,0x82,0x85,0x97,0x1c,0xb2,0x72, 0x00,0x01,0x00,0x7b,0x02,0x9a,0x02,0xea,0x05,0x9a,0x00,0x0b,0x00,0x49,0xb9,0x00,0x03,0x01,0x0e,0xb4,0x40,0x08,0x06,0x05,0x08,0xb8,0x01,0x0e,0xb5,0x32,0x30,0x0b,0x00,0x06,0x05,0xba,0x01,0x0a,0x00,0x06,0x01,0x06,0xb3,0x09,0x08,0x04,0x00,0xbb,0x01,0x0c,0x00,0x01,0x00,0x04,0x01,0x0c,0xb4,0x05,0x01,0x01,0x0d,0x05,0x2f,0x12, 0x39,0x2f,0x10,0xe1,0x10,0xe1,0x12,0x39,0x39,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x02,0xea,0x84,0xfe,0x98,0x83,0x83,0x01,0x68,0x84,0x02,0x9a,0x01,0x4e,0xfe,0xb2,0x03,0x00,0xfe,0xbe,0x01,0x42,0x00,0x00,0x01,0x00,0x7b,0x02,0x9a, 0x00,0xfe,0x05,0x9a,0x00,0x03,0x00,0x16,0xbe,0x00,0x01,0x01,0x0a,0x00,0x02,0x01,0x06,0x00,0x00,0x01,0x0c,0x00,0x01,0x2f,0xe1,0x00,0x3f,0x3f,0x31,0x30,0x13,0x23,0x11,0x33,0xfe,0x83,0x83,0x02,0x9a,0x03,0x00,0x00,0x00,0x01,0x00,0x0a,0x02,0x87,0x01,0x5e,0x05,0x9a,0x00,0x0c,0x00,0x23,0xb1,0x06,0x08,0xbe,0x01,0x0e,0x00,0x03, 0x01,0x0b,0x00,0x0b,0x01,0x06,0x00,0x0c,0x01,0x0c,0xb3,0x0b,0x0b,0x0e,0x06,0x2f,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0x01,0x5e,0x82,0x74,0x35,0x29,0x2a,0x2c,0x7b,0x83,0x03,0xaa,0x8a,0x99,0x15,0x78,0x1c,0xb6,0x01,0xec,0x00,0x01,0x00,0x7b, 0x02,0x9a,0x02,0xc0,0x05,0x9a,0x00,0x10,0x00,0x21,0xbb,0x00,0x07,0x01,0x0a,0x00,0x08,0x01,0x06,0xb5,0x0f,0x00,0x12,0x10,0x0a,0x05,0xb9,0x01,0x0c,0x00,0x07,0x2f,0xe1,0x32,0x32,0x10,0xd6,0xc6,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x03,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x37,0x13,0x33,0x01,0x02,0xc0,0xa8,0xe9, 0x1f,0x0e,0x04,0x83,0x83,0x04,0x10,0x1d,0xe1,0x9c,0xfe,0xd7,0x02,0x9a,0x01,0x31,0x28,0x1d,0xfe,0x8a,0x03,0x00,0xfe,0x99,0x19,0x26,0x01,0x28,0xfe,0x8d,0x00,0x01,0x00,0x7b,0x02,0x9a,0x02,0x25,0x05,0x9a,0x00,0x05,0x00,0x22,0xbd,0x00,0x04,0x01,0x0e,0x00,0x01,0x01,0x0a,0x00,0x02,0x01,0x06,0xb3,0x00,0x00,0x07,0x04,0xb9,0x01, 0x0c,0x00,0x01,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0x3f,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x11,0x21,0x02,0x25,0xfe,0x56,0x83,0x01,0x27,0x02,0x9a,0x03,0x00,0xfd,0x70,0x00,0x00,0x01,0x00,0x7b,0x02,0x9a,0x03,0xb6,0x05,0x9a,0x00,0x1b,0x00,0x27,0xbe,0x00,0x11,0x01,0x0a,0x00,0x13,0x01,0x06,0x00,0x1a,0x00,0x00,0x01,0x0c,0xb4, 0x01,0x01,0x1d,0x13,0x10,0xb9,0x01,0x0c,0x00,0x11,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x33,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x03,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x03,0xb6,0x83,0x07,0x05,0x07,0x10,0xd6,0x62,0xd8,0x0a,0x0e,0x04, 0x04,0x7b,0xbd,0xc6,0x14,0x08,0x04,0x11,0x0f,0xc2,0xb6,0x02,0x9a,0x01,0xe9,0x3b,0x58,0x20,0x36,0xfd,0xda,0x02,0x20,0x18,0x46,0x40,0x6a,0xfe,0x2c,0x03,0x00,0xfe,0x08,0x32,0x2c,0x3e,0x24,0x01,0xf4,0x00,0x00,0x01,0x00,0x7b,0x02,0x9a,0x03,0x06,0x05,0x9a,0x00,0x11,0x00,0x29,0xbb,0x00,0x08,0x01,0x0a,0x00,0x0a,0x01,0x06,0xb3, 0x0a,0x01,0x07,0x11,0xb8,0x01,0x0c,0xb3,0x10,0x10,0x13,0x07,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x01,0x26,0x27,0x23,0x17,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x27,0x11,0x33,0x03,0x06,0x8d,0xfe,0xb2,0x15,0x1c,0x04,0x02,0x7d,0x93,0x01,0x48,0x15,0x1c, 0x05,0x03,0x7d,0x02,0x9a,0x01,0xfc,0x1f,0x3d,0x6f,0xfe,0x17,0x03,0x00,0xfe,0x0e,0x1f,0x3d,0x6e,0x01,0xe0,0x00,0x00,0x01,0x00,0x7b,0x02,0x9a,0x03,0x06,0x05,0x9a,0x00,0x11,0x00,0x29,0xbb,0x00,0x07,0x01,0x0a,0x00,0x09,0x01,0x06,0xb3,0x10,0x07,0x0a,0x00,0xb8,0x01,0x0c,0xb3,0x01,0x01,0x13,0x0a,0xb9,0x01,0x0c,0x00,0x08,0x2f, 0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x11,0x37,0x23,0x06,0x07,0x01,0x23,0x11,0x33,0x11,0x07,0x33,0x36,0x37,0x01,0x33,0x03,0x06,0x7d,0x03,0x05,0x0d,0x24,0xfe,0xb2,0x8d,0x7d,0x02,0x04,0x0e,0x23,0x01,0x47,0x94,0x02,0x9a,0x01,0xe9,0x6f,0x1e,0x3e,0xfe,0x04,0x03,0x00,0xfe,0x20,0x6e,0x1e, 0x3e,0x01,0xf2,0x00,0x00,0x02,0x00,0x3e,0x02,0x89,0x03,0x2b,0x05,0xaa,0x00,0x0b,0x00,0x17,0x00,0x2d,0x41,0x0a,0x00,0x12,0x01,0x0e,0x00,0x00,0x01,0x0b,0x00,0x0c,0x01,0x0e,0x00,0x06,0x01,0x07,0x00,0x09,0x01,0x0c,0xb3,0x15,0x15,0x19,0x0f,0xb9,0x01,0x0c,0x00,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31, 0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0xae,0xa6,0xca,0xd3,0xa9,0xa7,0xca,0xd2,0xa3,0x6c,0x86,0x82,0x6c,0x6c,0x86,0x82,0x02,0x89,0xd9,0xb0,0xb7,0xe1,0xd8,0xb1,0xb5,0xe3,0x02,0xb1,0x9e,0x84,0x83,0x9b,0x9d,0x83,0x83,0x9d,0x00,0x02, 0x00,0x3e,0x02,0x89,0x02,0xcf,0x05,0x9a,0x00,0x1b,0x00,0x27,0x00,0x5c,0xb2,0x12,0x00,0x1c,0xb8,0x01,0x0e,0xb3,0x09,0x09,0x04,0x22,0xbf,0x01,0x0e,0x00,0x17,0x01,0x0b,0x00,0x0e,0x00,0x04,0x01,0x06,0x00,0x0b,0x01,0x0c,0xb6,0x10,0x10,0x14,0x1a,0x05,0x05,0x07,0xb8,0x01,0x0c,0xb5,0x02,0x02,0x12,0x00,0x1a,0x14,0xb8,0x01,0x0c, 0xb3,0x25,0x25,0x29,0x1f,0xb9,0x01,0x0c,0x00,0x1a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x39,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x33,0x3f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x31,0x30,0x13,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x32,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x15,0x14, 0x06,0x23,0x22,0x26,0x35,0x34,0x25,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0xdd,0x75,0x19,0x7d,0x16,0x9d,0x9e,0x15,0x80,0x16,0x73,0x9e,0xba,0x92,0x92,0xb3,0x01,0x47,0x58,0x6d,0x6e,0x57,0x58,0x6f,0x73,0x04,0x7f,0x35,0x75,0x35,0x3c,0x2e,0x37,0x83,0x83,0x3b,0x2a,0x38,0x39,0x70,0x3a,0x3f,0xa2,0x7a,0x9b,0x96, 0x79,0xa0,0x0a,0x59,0x4b,0x4a,0x5a,0x58,0x4c,0x48,0x5c,0x00,0x00,0x02,0x00,0x7b,0x02,0x9a,0x02,0x83,0x05,0x9a,0x00,0x09,0x00,0x10,0x00,0x35,0xb9,0x00,0x00,0x01,0x0e,0xb3,0x0b,0x0b,0x03,0x02,0xbe,0x01,0x0a,0x00,0x0a,0x01,0x0e,0x00,0x03,0x01,0x06,0x00,0x06,0x01,0x0c,0xb4,0x0e,0x0e,0x12,0x0b,0x01,0xb9,0x01,0x0c,0x00,0x02, 0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x31,0x30,0x13,0x11,0x23,0x11,0x33,0x20,0x15,0x14,0x06,0x23,0x03,0x11,0x33,0x32,0x35,0x34,0x23,0xfe,0x83,0xef,0x01,0x19,0xa1,0x86,0x5e,0x54,0xaa,0xa4,0x03,0xa6,0xfe,0xf4,0x03,0x00,0xf2,0x71,0x91,0x01,0x83,0xfe,0xed,0x8e,0x85,0x00,0x02,0x00,0x7b, 0x02,0x9a,0x02,0xa4,0x05,0x9a,0x00,0x11,0x00,0x18,0x00,0x42,0xb1,0x0f,0x05,0xb8,0x01,0x0e,0xb4,0x13,0x13,0x08,0x00,0x07,0xbc,0x01,0x0a,0x00,0x12,0x01,0x0e,0x00,0x08,0x01,0x06,0xb4,0x0f,0x13,0x00,0x00,0x0c,0xb8,0x01,0x0c,0xb4,0x16,0x16,0x1a,0x13,0x06,0xb9,0x01,0x0c,0x00,0x07,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f, 0x12,0x39,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x23,0x27,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x17,0x01,0x15,0x33,0x32,0x35,0x34,0x23,0x02,0xa4,0x96,0x5c,0x2a,0x4a,0x40,0x83,0x01,0x00,0x7f,0x89,0xae,0x37,0x29,0xfe,0xc9,0x68,0x94,0x90,0x02,0x9a,0xd2,0x61,0xfe, 0xcd,0x03,0x00,0x73,0x65,0xa8,0x22,0x02,0x16,0x59,0x01,0xa2,0xeb,0x78,0x73,0x00,0x00,0x01,0x00,0x0a,0x02,0x9a,0x02,0x48,0x05,0x9a,0x00,0x07,0x00,0x2d,0xbe,0x00,0x03,0x01,0x0a,0x00,0x01,0x00,0x04,0x01,0x0e,0x00,0x06,0x01,0x06,0xb4,0x00,0x03,0x05,0x05,0x02,0xb8,0x01,0x0c,0xb3,0x03,0x03,0x09,0x08,0x11,0x12,0x39,0x2f,0xf1, 0xc0,0x2f,0x10,0xc4,0x00,0x3f,0xed,0x32,0x3f,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x35,0x21,0x02,0x48,0xde,0x82,0xde,0x02,0x3e,0x05,0x29,0xfd,0x71,0x02,0x8f,0x71,0x00,0x00,0x01,0x00,0x74,0x02,0x89,0x02,0xdb,0x05,0x9a,0x00,0x0d,0x00,0x2b,0x41,0x09,0x00,0x09,0x01,0x0e,0x00,0x02,0x01,0x0b,0x00,0x0d,0x00,0x05,0x01,0x06, 0x00,0x0d,0x01,0x0c,0xb3,0x0c,0x0c,0x0f,0x06,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x33,0x3f,0xed,0x31,0x30,0x01,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x35,0x11,0x33,0x02,0xdb,0xfe,0xc5,0xfe,0xd4,0x84,0xb0,0xb0,0x83,0x03,0xd3,0xfe,0xb6,0x01,0x3f,0x01,0xd2,0xfe,0x35,0xd5,0xd5,0x01, 0xcb,0x00,0x00,0x01,0x00,0x10,0x02,0x9a,0x04,0x25,0x05,0x9a,0x00,0x1b,0x00,0x15,0xbb,0x00,0x0a,0x01,0x0a,0x00,0x0b,0x01,0x06,0xb2,0x00,0x1d,0x0b,0x2f,0x10,0xc6,0x00,0x3f,0x3f,0x31,0x30,0x01,0x03,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x37, 0x13,0x04,0x25,0xc7,0x9e,0x8f,0x0a,0x02,0x04,0x05,0x0a,0x95,0x9e,0xcf,0x92,0x85,0x09,0x03,0x07,0x02,0x0e,0x9c,0x88,0x8e,0x0a,0x04,0x06,0x02,0x0c,0x82,0x05,0x9a,0xfd,0x00,0x02,0x0e,0x25,0x2d,0x2c,0x24,0xfd,0xf0,0x03,0x00,0xfd,0xdf,0x26,0x2a,0x1f,0x31,0x02,0x21,0xfd,0xda,0x26,0x25,0x19,0x35,0x02,0x23,0x00,0x02,0x00,0x3e, 0x02,0x89,0x02,0x1e,0x04,0xcf,0x00,0x14,0x00,0x1d,0x00,0x61,0x40,0x0c,0x02,0x05,0x16,0x0f,0x30,0x11,0x17,0x48,0x0f,0x0f,0x0d,0x16,0xb8,0x01,0x0d,0xb4,0x40,0x0b,0x12,0x05,0x0b,0xb8,0x01,0x0d,0xb2,0x30,0x30,0x1b,0x41,0x0b,0x01,0x0d,0x00,0x05,0x01,0x0b,0x00,0x00,0x01,0x0a,0x00,0x0d,0x01,0x0d,0x00,0x12,0x01,0x09,0x00,0x00, 0x01,0x0c,0xb6,0x16,0x0b,0x01,0x01,0x1f,0x0f,0x19,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0xc4,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x12,0x39,0x2f,0x2b,0x11,0x12,0x39,0x31,0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x34,0x23,0x22,0x07,0x35,0x36,0x33, 0x32,0x15,0x07,0x35,0x07,0x06,0x15,0x14,0x33,0x32,0x36,0x02,0x1e,0x7e,0x02,0x38,0x76,0x53,0x5f,0xc2,0xa0,0x6f,0x64,0x59,0x56,0x76,0xde,0x7e,0x79,0x6d,0x5e,0x3c,0x4c,0x02,0x9a,0x50,0x61,0x59,0x4b,0x9b,0x1c,0x16,0x72,0x3f,0x71,0x31,0xd7,0x81,0x2f,0x10,0x0e,0x4e,0x50,0x4e,0x00,0x02,0x00,0x66,0x02,0x89,0x02,0x48,0x04,0xcf, 0x00,0x14,0x00,0x1d,0x00,0x61,0xb9,0x00,0x04,0xff,0xd0,0xb6,0x11,0x17,0x48,0x04,0x04,0x02,0x00,0xb8,0x01,0x0d,0x40,0x0c,0x15,0x5f,0x15,0x01,0x15,0x40,0x18,0x1b,0x48,0x15,0x0f,0x02,0x41,0x09,0x01,0x0d,0x00,0x07,0x01,0x0b,0x00,0x0a,0x01,0x08,0x00,0x1a,0x01,0x0d,0x00,0x0f,0x01,0x09,0xb2,0x04,0x04,0x12,0xb8,0x01,0x0c,0xb5, 0x18,0x18,0x1f,0x15,0x00,0x0b,0xb9,0x01,0x0c,0x00,0x0a,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x11,0x39,0x2b,0x71,0x2f,0xed,0x11,0x39,0x2f,0x2b,0x31,0x30,0x13,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x35,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x27,0x37,0x36,0x35, 0x34,0x23,0x22,0x06,0x15,0xe6,0x6e,0x64,0x58,0x54,0x76,0xe0,0x80,0x02,0x37,0x77,0x52,0x60,0xc3,0x9f,0x78,0x6d,0x5f,0x3a,0x4c,0x03,0x5e,0x72,0x3f,0x71,0x31,0xd7,0x01,0x5e,0x50,0x61,0x5c,0x48,0x9b,0x1c,0x3e,0x10,0x0f,0x4d,0x50,0x4e,0x3e,0x00,0x00,0x02,0x00,0x3e,0x02,0x89,0x02,0x60,0x04,0xcf,0x00,0x10,0x00,0x1b,0x00,0x41, 0xb3,0x0e,0x02,0x0b,0x19,0x41,0x0d,0x01,0x0d,0x00,0x05,0x01,0x0b,0x00,0x00,0x01,0x0a,0x00,0x10,0x01,0x08,0x00,0x15,0x01,0x0d,0x00,0x0b,0x01,0x09,0x00,0x00,0x01,0x0c,0xb5,0x11,0x0e,0x01,0x01,0x1d,0x17,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31, 0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0x36,0x02,0x60,0x7e,0x03,0x42,0x76,0x68,0x81,0x8e,0x6e,0x70,0x35,0x03,0x7e,0x7e,0x52,0x40,0x90,0x8e,0x42,0x52,0x02,0x9a,0x50,0x61,0x97,0x80,0x84,0xab,0x54,0x43,0xfe,0xda,0x2e,0x46, 0x5c,0xc2,0xb6,0x5e,0x00,0x03,0x00,0x48,0x02,0x89,0x03,0xa2,0x04,0xcf,0x00,0x22,0x00,0x2b,0x00,0x30,0x00,0xa9,0x40,0x09,0x1a,0x0a,0x0c,0x18,0x15,0x15,0x13,0x10,0x04,0xb8,0xff,0xd0,0xb6,0x11,0x17,0x48,0x04,0x04,0x02,0x00,0xb8,0x01,0x0d,0x40,0x0d,0x23,0x5f,0x23,0x01,0x23,0x40,0x18,0x1b,0x48,0x23,0x1d,0x02,0x10,0xb8,0x01, 0x0d,0x40,0x0c,0x03,0x2d,0x13,0x2d,0x23,0x2d,0x03,0x2d,0x2d,0x13,0x0c,0x02,0xb8,0x01,0x0d,0xb2,0x07,0x07,0x2f,0xbc,0x01,0x0d,0x00,0x0c,0x01,0x0b,0x00,0x28,0x01,0x0d,0xb3,0x1d,0x1d,0x13,0x18,0xb8,0x01,0x09,0xb5,0x00,0x09,0x1a,0x2c,0x04,0x23,0xb8,0x01,0x0c,0xb6,0x11,0x11,0x20,0x10,0x04,0x04,0x20,0xb8,0x01,0x0c,0xb4,0x26, 0x26,0x32,0x15,0x2d,0xb9,0x01,0x0c,0x00,0x10,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x17,0x39,0x00,0x3f,0xcd,0x33,0x10,0xed,0x3f,0xed,0x33,0x10,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x11,0x12,0x39,0x2b,0x71,0x2f,0xed,0x11,0x39,0x2f,0x2b,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x39,0x31,0x30,0x01, 0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x27,0x23,0x06,0x23,0x22,0x26,0x35,0x35,0x21,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x27,0x37,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x07,0x23,0x16,0x33,0x32,0x02,0x40,0x6e,0x64,0x58,0x54,0x76,0x7e,0x32,0x04,0x48,0x6a,0x72,0x80,0x01,0x78, 0x08,0x9c,0x5c,0x4e,0x4a,0x73,0x97,0x44,0x04,0x43,0x8a,0x58,0x6f,0xc3,0x9f,0x78,0x6d,0x5f,0x3a,0x4c,0x80,0xfe,0x02,0x7a,0x78,0x03,0x5e,0x72,0x3f,0x71,0x31,0x50,0x50,0x93,0x7a,0x43,0x8f,0x35,0x6f,0x2d,0x6b,0x6b,0x5e,0x46,0x9b,0x1c,0x3e,0x10,0x0f,0x4d,0x50,0x4e,0x3e,0x6b,0x8b,0x00,0x00,0x02,0x00,0x66,0x02,0x89,0x02,0x89, 0x05,0xc4,0x00,0x10,0x00,0x1b,0x00,0x41,0xb3,0x06,0x01,0x09,0x15,0x41,0x0d,0x01,0x0d,0x00,0x0f,0x01,0x0b,0x00,0x03,0x01,0x0a,0x00,0x19,0x01,0x0d,0x00,0x09,0x01,0x09,0x00,0x04,0x01,0x06,0x00,0x0c,0x01,0x0c,0xb5,0x17,0x17,0x1d,0x12,0x06,0x02,0xb9,0x01,0x0c,0x00,0x03,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0x3f, 0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x13,0x23,0x15,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x06,0xe8,0x02,0x80,0x80,0x02,0x42,0x76,0x68,0x81,0x8f,0x6c,0x72,0x36,0x51,0x40,0x91,0x8d,0x43,0x52,0x02,0xdd,0x43,0x03,0x2a,0xfe,0xaa,0x61, 0x97,0x80,0x84,0xab,0x01,0x37,0x2e,0x46,0x5c,0xc2,0xb6,0x60,0x00,0x02,0x00,0x3e,0x02,0x89,0x02,0x60,0x05,0xc4,0x00,0x10,0x00,0x1b,0x00,0x41,0xb3,0x0e,0x02,0x0b,0x19,0x41,0x0d,0x01,0x0d,0x00,0x05,0x01,0x0b,0x00,0x00,0x01,0x0a,0x00,0x15,0x01,0x0d,0x00,0x0b,0x01,0x09,0x00,0x10,0x01,0x06,0x00,0x10,0x01,0x0c,0xb5,0x12,0x02, 0x0f,0x0f,0x1d,0x17,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x11,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0x36,0x02,0x60,0x7e,0x03,0x42,0x76,0x68, 0x81,0x8e,0x6e,0x70,0x35,0x03,0x7e,0x7e,0x52,0x40,0x92,0x8e,0x42,0x54,0x02,0x9a,0x50,0x61,0x97,0x80,0x84,0xab,0x54,0x01,0x49,0xfd,0xd4,0x2e,0x46,0x5c,0xc2,0xb6,0x60,0x00,0x00,0x02,0x00,0x3e,0x02,0x89,0x02,0x35,0x04,0xcf,0x00,0x11,0x00,0x16,0x00,0x4e,0xb3,0x05,0x05,0x03,0x01,0xb8,0x01,0x0d,0x40,0x0b,0x0c,0x16,0x1c,0x16, 0x2c,0x16,0x03,0x16,0x16,0x0e,0x03,0xbe,0x01,0x0d,0x00,0x08,0x01,0x0b,0x00,0x14,0x01,0x0d,0x00,0x0e,0x01,0x09,0xb2,0x05,0x05,0x00,0xb8,0x01,0x0c,0xb4,0x12,0x12,0x18,0x16,0x01,0xb9,0x01,0x0c,0x00,0x0b,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x5d,0xed,0x11,0x39,0x2f,0x31,0x30, 0x01,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x27,0x26,0x23,0x22,0x07,0x02,0x35,0xfe,0x87,0x0a,0x9a,0x5c,0x4e,0x48,0x78,0x7e,0x8e,0x92,0x72,0x71,0x82,0x7b,0x02,0x78,0x78,0x0c,0x03,0x7f,0x8f,0x35,0x6f,0x2d,0x97,0x88,0x81,0xa6,0x91,0x7c,0x20,0x8a,0x8a,0x00,0x00,0x02,0x00,0x48, 0x02,0x87,0x02,0x40,0x04,0xd1,0x00,0x11,0x00,0x16,0x00,0x4c,0xb3,0x05,0x05,0x03,0x00,0xb8,0x01,0x0d,0x40,0x0b,0x03,0x13,0x13,0x13,0x23,0x13,0x03,0x13,0x13,0x03,0x15,0x41,0x09,0x01,0x0d,0x00,0x0e,0x01,0x0b,0x00,0x03,0x01,0x0d,0x00,0x08,0x01,0x09,0x00,0x0b,0x01,0x0c,0xb5,0x01,0x12,0x12,0x18,0x05,0x13,0xb9,0x01,0x0c,0x00, 0x00,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0x33,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x11,0x39,0x2f,0x31,0x30,0x13,0x21,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x05,0x23,0x16,0x33,0x32,0x48,0x01,0x78,0x09,0x9b,0x5c,0x4e,0x4a,0x77,0x7c,0x91,0x94,0x70,0x72,0x82,0x01,0x78, 0xfe,0x02,0x7a,0x74,0x03,0xd9,0x91,0x35,0x6f,0x2d,0x99,0x88,0x81,0xa8,0x94,0x7b,0x1f,0x8d,0x00,0x01,0x00,0x3e,0x02,0x89,0x01,0xdb,0x04,0xcf,0x00,0x1e,0x00,0x5b,0xb1,0x06,0x17,0xb8,0x01,0x0d,0xb4,0x40,0x16,0x0c,0x02,0x16,0xb8,0x01,0x0d,0xb3,0x30,0x30,0x1e,0x1c,0xbf,0x01,0x0d,0x00,0x02,0x01,0x0b,0x00,0x0f,0x00,0x11,0x01, 0x0d,0x00,0x0c,0x01,0x09,0x40,0x0b,0x06,0x04,0x17,0x17,0x1a,0x0f,0x00,0x00,0x20,0x04,0x13,0xbc,0x01,0x0c,0x00,0x09,0x00,0x1a,0x01,0x0c,0x00,0x04,0x2f,0xe1,0xd4,0xe1,0x11,0x12,0x39,0x2f,0xc4,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x35, 0x34,0x37,0x35,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x14,0x33,0x33,0x15,0x23,0x22,0x15,0x14,0x33,0x32,0x37,0x01,0xdb,0x49,0x58,0xfc,0x7a,0x66,0x80,0x6e,0x4d,0x40,0x3e,0x49,0x71,0x8b,0x32,0x34,0x9e,0x88,0x55,0x3e,0x02,0xa4,0x1b,0xa4,0x6f,0x1c,0x04,0x20,0x59,0x48,0x52,0x17,0x68,0x1c,0x41,0x47,0x63, 0x4c,0x49,0x1c,0x00,0x00,0x01,0x00,0x42,0x02,0x89,0x01,0xdf,0x04,0xcf,0x00,0x1e,0x00,0x54,0xb1,0x01,0x11,0xb8,0x01,0x0d,0xb5,0x10,0x10,0x16,0x06,0x09,0x0b,0xbf,0x01,0x0d,0x00,0x06,0x01,0x0b,0x00,0x18,0x00,0x16,0x01,0x0d,0x00,0x1b,0x01,0x09,0xb6,0x01,0x1d,0x11,0x11,0x14,0x18,0x0d,0xb8,0x01,0x0c,0xb2,0x03,0x03,0x1d,0xb8, 0x01,0x0c,0xb4,0x14,0x14,0x20,0x09,0x18,0x2f,0xc6,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35, 0x36,0x33,0x32,0x15,0x14,0x01,0x64,0x67,0x81,0x6d,0x4d,0x40,0x3e,0x49,0x71,0x8c,0x30,0x32,0x9e,0x87,0x55,0x3e,0x49,0x59,0xfb,0x03,0xa0,0x04,0x1f,0x5a,0x49,0x51,0x17,0x68,0x1c,0x41,0x47,0x63,0x4c,0x49,0x1c,0x64,0x1b,0xa4,0x6f,0x00,0x00,0x02,0x00,0x3e,0x01,0x94,0x02,0x60,0x04,0xcf,0x00,0x18,0x00,0x23,0x00,0x4e,0xb3,0x05, 0x05,0x0d,0x07,0xb8,0x01,0x0d,0xb5,0x02,0x02,0x15,0x0a,0x13,0x21,0x41,0x0b,0x01,0x0d,0x00,0x0d,0x01,0x0b,0x00,0x18,0x01,0x08,0x00,0x1d,0x01,0x0d,0x00,0x13,0x01,0x09,0x00,0x18,0x01,0x0c,0xb5,0x16,0x0a,0x19,0x19,0x25,0x1f,0xb8,0x01,0x0c,0xb1,0x05,0x10,0x2f,0xc4,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x00,0x3f,0xed,0x3f,0x3f, 0xed,0x12,0x39,0x39,0xc4,0x2f,0xed,0x11,0x39,0x2f,0x31,0x30,0x01,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x35,0x33,0x03,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0x36,0x02,0x60,0xfe,0xbe,0x62,0x4a,0x58,0x59,0xbf,0x03,0x42,0x76,0x68,0x81,0x8e,0x6e, 0x70,0x35,0x03,0x7e,0x7e,0x52,0x40,0x90,0x8e,0x42,0x52,0x02,0xbc,0xfe,0xd8,0x22,0x79,0x31,0xbc,0x30,0x61,0x97,0x80,0x84,0xab,0x54,0x43,0xfe,0xda,0x2e,0x46,0x5c,0xc2,0xb6,0x5e,0x00,0x00,0x02,0x00,0x58,0x01,0x94,0x00,0xf6,0x04,0xbe,0x00,0x03,0x00,0x0b,0x00,0x22,0xb4,0x01,0x08,0x40,0x04,0x02,0xb8,0x01,0x08,0xb6,0x01,0x00, 0x06,0x0a,0xff,0x3a,0x00,0xb9,0x01,0x0c,0x00,0x01,0x2f,0xe1,0x2b,0x00,0x18,0x3f,0xd4,0x1a,0xdd,0xce,0x31,0x30,0x13,0x23,0x11,0x33,0x03,0x22,0x35,0x34,0x33,0x32,0x15,0x14,0xe8,0x82,0x82,0x42,0x4e,0x50,0x4e,0x02,0x9a,0x02,0x24,0xfc,0xd6,0x4b,0x4c,0x4c,0x4b,0x00,0x00,0x01,0x00,0x66,0x02,0x9a,0x02,0x56,0x05,0xc4,0x00,0x0c, 0x00,0x2e,0xb5,0x03,0x08,0x0c,0x03,0x05,0x00,0xbc,0x01,0x0a,0x00,0x0b,0x01,0x08,0x00,0x06,0x01,0x07,0xb5,0x0b,0x00,0x0e,0x0c,0x08,0x03,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xe1,0x32,0x32,0x10,0xd6,0xc6,0x00,0x3f,0x3f,0x3f,0x33,0x17,0x39,0x31,0x30,0x01,0x23,0x03,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x37,0x33,0x03,0x02,0x56,0xa0, 0xce,0x02,0x80,0x80,0x02,0xc2,0x9c,0xde,0x02,0x9a,0x01,0x0e,0xfe,0xf2,0x03,0x2a,0xfd,0xfc,0xfe,0xfe,0xfc,0x00,0x00,0x01,0x00,0x66,0x02,0x9a,0x03,0x9a,0x04,0xcf,0x00,0x1d,0x00,0x59,0xb6,0x01,0x09,0x14,0x19,0x04,0x17,0x11,0xba,0x01,0x0a,0x00,0x12,0x01,0x08,0xb2,0x1b,0x04,0x0c,0xbb,0x01,0x0d,0x00,0x40,0x00,0x17,0x01,0x09, 0xb3,0x19,0x08,0x14,0x00,0xb8,0x01,0x0c,0xb7,0x01,0x0e,0x09,0x11,0x09,0x42,0x14,0x10,0xbb,0x01,0x0c,0x00,0x11,0x00,0x08,0x01,0x0c,0xb3,0x09,0x09,0x1f,0x1e,0x11,0x12,0x39,0x2f,0xe1,0x2f,0xe1,0x32,0x2b,0x01,0x10,0xf0,0xe1,0x11,0x12,0x39,0x00,0x18,0x3f,0x1a,0xed,0x39,0x39,0x3f,0x3f,0x12,0x17,0x39,0x31,0x30,0x01,0x23,0x11, 0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x15,0x03,0x9a,0x80,0x68,0x31,0x41,0x80,0x68,0x32,0x40,0x80,0x7e,0x02,0x38,0x72,0x77,0x28,0x3d,0x7c,0xb2,0x02,0x9a,0x01,0x3b,0x8f,0x54,0x3f,0xfe,0xc9,0x01,0x3f,0x8b,0x52,0x45,0xfe,0xcd,0x02, 0x24,0x52,0x63,0x6f,0x6f,0xe3,0x00,0x01,0x00,0x66,0x01,0x98,0x02,0x50,0x04,0xcf,0x00,0x19,0x00,0x40,0xb1,0x05,0x07,0x41,0x0a,0x01,0x0d,0x00,0x02,0x00,0x11,0x01,0x0a,0x00,0x12,0x01,0x08,0x00,0x0c,0x01,0x0d,0x00,0x17,0x01,0x09,0xb3,0x05,0x05,0x10,0x00,0xb8,0x01,0x0c,0xb4,0x09,0x09,0x1b,0x14,0x10,0xb9,0x01,0x0c,0x00,0x11, 0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x00,0x3f,0xed,0x3f,0x3f,0xd4,0xfd,0xc6,0x31,0x30,0x01,0x10,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0xd9,0x2b,0x25,0x22,0x23,0x65,0x6d,0x39,0x45,0x80,0x80,0x02,0x3b,0x79,0xb4,0x02, 0xa6,0xfe,0xf2,0x10,0x68,0x14,0x9e,0x01,0x33,0x97,0x54,0x3f,0xfe,0xc9,0x02,0x24,0x56,0x67,0xe7,0x00,0x00,0x02,0x00,0x3e,0x02,0x89,0x02,0x7f,0x04,0xcf,0x00,0x0b,0x00,0x17,0x00,0x2d,0x41,0x0a,0x00,0x12,0x01,0x0d,0x00,0x00,0x01,0x0b,0x00,0x0c,0x01,0x0d,0x00,0x06,0x01,0x09,0x00,0x09,0x01,0x0c,0xb3,0x15,0x15,0x19,0x0f,0xb9, 0x01,0x0c,0x00,0x03,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x58,0x80,0x9a,0xa2,0x84,0x80,0x9b,0xa3,0x7e,0x49,0x57,0x58,0x48,0x49,0x57,0x57,0x02,0x89,0x9e,0x7f,0x87,0xa2, 0x9f,0x7e,0x88,0xa1,0x01,0xdb,0x62,0x56,0x56,0x62,0x62,0x56,0x58,0x60,0x00,0x01,0x00,0x3e,0x02,0x89,0x01,0xec,0x04,0xcf,0x00,0x15,0x00,0x2e,0xb1,0x01,0x03,0x41,0x0a,0x01,0x0d,0x00,0x14,0x01,0x0b,0x00,0x0b,0x00,0x09,0x01,0x0d,0x00,0x0e,0x01,0x09,0x00,0x11,0x01,0x0c,0xb4,0x06,0x06,0x17,0x0b,0x00,0x2f,0x32,0x11,0x39,0x2f, 0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x3e,0x35,0x45,0x52,0x60,0x5a,0x50,0x49,0x39,0x45,0x56,0x7c,0x97,0xa4,0x88,0x50,0x02,0xa2,0x78,0x26,0x62,0x56,0x56,0x62,0x28,0x70,0x23,0x9f,0x80,0x8b,0x9c,0x00, 0x00,0x01,0x00,0x3e,0x03,0xac,0x02,0x7f,0x04,0xcf,0x00,0x0d,0x00,0x26,0xb2,0x01,0x07,0x04,0xbc,0x01,0x0d,0x00,0x0b,0x01,0x09,0x00,0x00,0x01,0x0c,0xb3,0x01,0x01,0x0f,0x07,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6,0x32,0x31,0x30,0x01,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33, 0x32,0x16,0x02,0x7f,0x81,0x57,0x49,0x49,0x57,0x80,0xa5,0x81,0x82,0x99,0x03,0xac,0x58,0x60,0x62,0x56,0x84,0x9f,0xa1,0x00,0x00,0x01,0x00,0x3e,0x02,0x89,0x02,0x7f,0x03,0xac,0x00,0x0d,0x00,0x26,0xb2,0x00,0x06,0x0a,0xbc,0x01,0x0d,0x00,0x03,0x01,0x0b,0x00,0x00,0x01,0x0c,0xb3,0x0d,0x0d,0x0f,0x07,0xb9,0x01,0x0c,0x00,0x06,0x2f, 0xe1,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc4,0x32,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x02,0x7f,0xa5,0x82,0x80,0x9a,0x80,0x58,0x48,0x49,0x57,0x03,0xac,0x84,0x9f,0xa0,0x83,0x56,0x62,0x62,0x56,0x00,0x00,0x02,0x00,0x66,0x01,0xa4,0x02,0x89,0x04,0xcf,0x00,0x10,0x00,0x1b,0x00,0x3e, 0xb4,0x03,0x06,0x00,0x09,0x15,0x41,0x0b,0x01,0x0d,0x00,0x0f,0x01,0x0b,0x00,0x04,0x01,0x08,0x00,0x19,0x01,0x0d,0x00,0x09,0x01,0x09,0x00,0x0c,0x01,0x0c,0xb5,0x17,0x17,0x1d,0x11,0x01,0x05,0xb9,0x01,0x0c,0x00,0x04,0x2f,0xe1,0x32,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39,0x39,0xc4,0x31,0x30,0x13,0x23, 0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x06,0xe8,0x02,0x80,0x80,0x02,0x42,0x76,0x68,0x81,0x8f,0x6c,0x72,0x36,0x51,0x40,0x91,0x8d,0x43,0x52,0x02,0xdd,0xfe,0xc7,0x03,0x1a,0x50,0x61,0x97,0x80,0x84,0xab,0x01,0x37,0x2e,0x46,0x5c,0xc2,0xb6, 0x60,0x00,0x00,0x01,0x00,0x0a,0x02,0x8e,0x01,0x68,0x05,0x62,0x00,0x13,0x00,0x45,0xb1,0x13,0x11,0xba,0x01,0x0d,0x00,0x02,0x01,0x0b,0xb4,0x0a,0x0b,0x0e,0x0b,0x05,0xba,0x01,0x0d,0x00,0x08,0x01,0x08,0xb7,0x0d,0x13,0x13,0x15,0x05,0x0e,0x05,0x0b,0xb8,0x01,0x0c,0x40,0x09,0x07,0x10,0x08,0x20,0x08,0x30,0x08,0x03,0x08,0x2f,0x5d, 0xcd,0xe1,0x39,0x39,0x11,0x12,0x39,0x2f,0xc4,0x00,0x3f,0xed,0x39,0x39,0x10,0xcd,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x35,0x11,0x23,0x35,0x33,0x35,0x37,0x15,0x33,0x15,0x23,0x15,0x14,0x33,0x32,0x37,0x01,0x68,0x22,0x40,0xa0,0x5c,0x5c,0x80,0x82,0x82,0x49,0x1e,0x1b,0x02,0xa0,0x12,0xbe,0x01,0x08,0x6a,0x80,0x24,0xa4, 0x6a,0xfe,0x5e,0x10,0x00,0x01,0x00,0x5c,0x02,0x89,0x02,0x46,0x04,0xbe,0x00,0x11,0x00,0x36,0xb3,0x11,0x02,0x08,0x0c,0x41,0x0a,0x01,0x0d,0x00,0x05,0x01,0x0b,0x00,0x00,0x01,0x0a,0x00,0x08,0x01,0x08,0x00,0x02,0x00,0x11,0x01,0x0c,0xb3,0x10,0x10,0x13,0x09,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0xc4,0x00,0x3f, 0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x02,0x46,0x80,0x02,0x3b,0x79,0xb4,0x7f,0x6d,0x39,0x45,0x80,0x02,0x9a,0x56,0x67,0xe7,0x01,0x4e,0xfe,0xce,0x98,0x53,0x40,0x01,0x37,0x00,0x01,0x00,0x3e,0x02,0xb8,0x02,0x72,0x04,0xa2,0x00,0x12, 0x00,0x2e,0x40,0x15,0x00,0x0e,0x40,0x01,0x09,0x0d,0x08,0x09,0x08,0x42,0x08,0x09,0x0c,0x00,0x09,0x0a,0x0f,0x04,0x04,0x14,0x09,0x2f,0x12,0x39,0x2f,0xdd,0xc4,0x12,0x39,0x39,0x00,0x2f,0xcd,0x2b,0x00,0x18,0x10,0xc4,0x10,0xd6,0x1a,0xed,0x31,0x30,0x13,0x35,0x21,0x32,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x15,0x23,0x15,0x16,0x15, 0x14,0x06,0x23,0x3e,0x01,0x32,0x98,0x54,0x40,0xfe,0xca,0x02,0x24,0x4c,0x5c,0x7c,0x6a,0x02,0xb8,0x80,0x6c,0x38,0x47,0x7f,0x7f,0x02,0x3f,0x69,0x58,0x69,0x00,0x01,0x00,0x60,0x02,0x89,0x03,0x94,0x04,0xbe,0x00,0x1d,0x00,0x67,0x40,0x09,0x02,0x07,0x14,0x1d,0x04,0x0c,0x18,0x05,0x10,0xbf,0x01,0x0d,0x00,0x40,0x00,0x09,0x01,0x0b, 0x00,0x00,0x01,0x0a,0x00,0x0c,0x01,0x08,0xb4,0x07,0x14,0x02,0x02,0x1d,0xb8,0x01,0x0c,0xb6,0x1c,0x0e,0x14,0x0c,0x14,0x42,0x0d,0xb8,0x01,0x0c,0xb6,0x00,0x0c,0x01,0x0b,0x03,0x0c,0x15,0xb8,0x01,0x0c,0xb3,0x14,0x1e,0x1f,0x14,0xb8,0x01,0x0c,0xb1,0x08,0x30,0x2b,0x01,0x10,0xe1,0x18,0x2f,0x5f,0x5e,0x5d,0xe1,0x2b,0x01,0x10,0xf0, 0xe1,0xc1,0x18,0x2f,0x12,0x39,0x00,0x3f,0x3f,0x3f,0x1a,0xed,0x39,0x39,0x12,0x17,0x39,0x31,0x30,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0x94,0x7e,0x02,0x38,0x72,0x77,0x28,0x3d,0x7c,0xb2,0x7f,0x69,0x31,0x41, 0x80,0x68,0x32,0x40,0x80,0x02,0x9a,0x52,0x63,0x6f,0x6f,0xe3,0x01,0x52,0xfe,0xc5,0x8f,0x54,0x3f,0x01,0x37,0xfe,0xc1,0x8b,0x52,0x46,0x01,0x32,0x00,0x01,0x00,0x0a,0x02,0x9a,0x02,0x35,0x04,0xbe,0x00,0x0b,0x00,0x1b,0xb3,0x07,0x00,0x03,0x02,0xba,0x01,0x0a,0x00,0x03,0x01,0x08,0xb2,0x00,0x0d,0x03,0x2f,0x10,0xc6,0x00,0x3f,0x3f, 0x12,0x39,0x39,0x31,0x30,0x01,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x02,0x35,0xc9,0x9b,0xc7,0x8a,0x78,0x0f,0x03,0x05,0x04,0x11,0x78,0x04,0xbe,0xfd,0xdc,0x02,0x24,0xfe,0x8e,0x2f,0x25,0x22,0x32,0x01,0x72,0x00,0x01,0x00,0x14,0x02,0x89,0x02,0x79,0x04,0xcf,0x00,0x1b,0x00,0x4a,0x40,0x0b,0x17,0x0d,0x0b,0x04, 0x06,0x12,0x1b,0x09,0x19,0x02,0x0b,0xbd,0x01,0x0d,0x00,0x40,0x00,0x06,0x01,0x0b,0x00,0x12,0x01,0x09,0x40,0x10,0x04,0x0d,0x17,0x03,0x0f,0x1b,0x0e,0x15,0x15,0x1d,0x0f,0x08,0x0f,0x42,0x08,0x0f,0x2f,0x2f,0x2b,0x11,0x12,0x01,0x39,0x18,0x2f,0xe2,0x12,0x17,0x39,0x00,0x3f,0x3f,0x1a,0xfd,0x39,0x39,0xd6,0xc4,0x11,0x12,0x39,0x12, 0x39,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x33,0x32,0x37,0x02,0x79,0x3c,0x49,0x60,0x4e,0x4f,0x5b,0x46,0x42,0x43,0x3f,0x36,0x28,0x77,0x6e,0x5d,0x5c,0x6c,0x78,0x2a,0x36,0x41,0x40,0x02,0xb4,0x2b,0x3b,0x3b,0x2b,0x79,0x39, 0x20,0x6b,0x85,0x57,0x74,0x71,0x56,0x84,0x6e,0x22,0x37,0x00,0x00,0x02,0x00,0x60,0x01,0xa4,0x02,0x74,0x05,0xc4,0x00,0x12,0x00,0x25,0x00,0x63,0xb3,0x02,0x11,0x0c,0x13,0xb8,0x01,0x0d,0xb4,0x40,0x14,0x06,0x11,0x14,0xb8,0x01,0x0d,0xb3,0x1e,0x30,0x1d,0x1f,0xbe,0x01,0x0d,0x00,0x11,0x01,0x0b,0x00,0x1a,0x01,0x0d,0x00,0x06,0x01, 0x07,0xb6,0x0c,0x0e,0x13,0x13,0x22,0x1d,0x18,0xb8,0x01,0x0c,0xb2,0x09,0x09,0x0e,0xb8,0x01,0x0c,0xb4,0x22,0x22,0x27,0x1d,0x01,0xb9,0x01,0x0c,0x00,0x02,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0xe1,0x11,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xed,0x3f,0xfd,0xc6,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x39,0x10,0xc4,0x31,0x30,0x13, 0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x13,0x35,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x15,0x11,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0xdf,0x7f,0x8c,0x74,0x70,0x86,0x7f,0x9d,0x93,0x79,0x4a,0x09,0x1d,0x42,0x51,0x79,0x7f,0x3b,0x46,0x42,0x52,0x60,0x50,0x02,0xa6,0xfe,0xfe, 0x03,0x14,0x7a,0x92,0x7c,0x5c,0x81,0x2f,0x04,0x2e,0x93,0x67,0x87,0x01,0x77,0x62,0x46,0x3a,0x7c,0xa2,0xfe,0x5a,0x22,0x46,0x3a,0x40,0x4c,0x00,0x00,0x01,0xff,0xec,0x01,0xa4,0x02,0x23,0x04,0xbe,0x00,0x13,0x00,0x36,0xb4,0x03,0x0a,0x05,0x07,0x00,0xbb,0x01,0x0a,0x00,0x10,0x00,0x07,0x01,0x08,0xb6,0x0a,0x00,0x05,0x07,0x07,0x00, 0x0d,0xbc,0x01,0x0c,0x00,0x12,0x00,0x00,0x01,0x0c,0x00,0x05,0x2f,0xe1,0xd4,0xe1,0x10,0xc1,0x2f,0x11,0x12,0x39,0x00,0x3f,0x33,0x3f,0x11,0x39,0x39,0xcd,0x31,0x30,0x01,0x14,0x07,0x23,0x36,0x35,0x02,0x03,0x33,0x16,0x17,0x33,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x01,0x50,0x02,0x88,0x0b,0x48,0x9d,0x91,0x75,0x39,0x04,0x75, 0x06,0x80,0x05,0x02,0x83,0xb3,0x2c,0x6e,0x94,0x01,0x06,0x01,0x12,0xda,0xc8,0xa5,0xb1,0x2a,0x22,0x20,0x21,0xe8,0x00,0x02,0x00,0x3e,0x02,0x89,0x02,0x7f,0x05,0xc4,0x00,0x17,0x00,0x21,0x00,0x4c,0x40,0x09,0x00,0x02,0x0d,0x10,0x18,0x1f,0x06,0x05,0x1d,0xbf,0x01,0x0d,0x00,0x13,0x01,0x0b,0x00,0x08,0x00,0x0a,0x01,0x0d,0x00,0x05, 0x01,0x07,0xb3,0x08,0x08,0x10,0x0c,0xb8,0x01,0x0c,0xb2,0x02,0x16,0x10,0xb8,0x01,0x0c,0xb3,0x1f,0x1f,0x23,0x1a,0xb9,0x01,0x0c,0x00,0x16,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x10,0xd4,0xe1,0x10,0xc0,0x2f,0x00,0x3f,0xfd,0xc6,0x3f,0xed,0x12,0x17,0x39,0x31,0x30,0x13,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x14, 0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x25,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0xee,0x4a,0x72,0x63,0x5f,0x60,0x5e,0x5b,0x5a,0x8f,0xcb,0xa2,0x83,0x81,0x9b,0x01,0x08,0x88,0x56,0x4a,0xa0,0x48,0x04,0xa0,0x37,0x4e,0x45,0x5a,0x2a,0x75,0x39,0x3b,0x25,0x58,0x7c,0x9c,0x72,0x93,0x8f,0x6f,0xa0,0x3b,0x54,0x80, 0x48,0x52,0x9a,0x36,0x5d,0x00,0x00,0x02,0x00,0x3e,0x01,0xa4,0x03,0x06,0x04,0xcf,0x00,0x15,0x00,0x1d,0x00,0x61,0xb3,0x02,0x1c,0x00,0x0d,0x41,0x0a,0x01,0x0d,0x00,0x03,0x01,0x0b,0x00,0x09,0x01,0x08,0x00,0x19,0x01,0x0d,0x00,0x40,0x00,0x10,0x01,0x09,0xb4,0x09,0x09,0x0d,0x0b,0x16,0xb8,0x01,0x0c,0xb6,0x13,0x0e,0x01,0x06,0x02, 0x42,0x0b,0xb8,0x01,0x0c,0xb3,0x06,0x1c,0x0d,0x01,0xb8,0x01,0x0c,0xb3,0x02,0x1e,0x1f,0x02,0xb8,0x01,0x0c,0xb1,0x08,0x30,0x2b,0x01,0x10,0xe1,0x39,0x39,0x18,0x2f,0xe1,0x2b,0x01,0x10,0xf0,0xe1,0x11,0x12,0x39,0x18,0x2f,0x00,0x3f,0x1a,0xed,0x3f,0x3f,0xed,0x39,0x39,0xcd,0x31,0x30,0x01,0x15,0x23,0x35,0x26,0x26,0x35,0x34,0x37, 0x33,0x06,0x15,0x14,0x17,0x11,0x34,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x34,0x26,0x23,0x22,0x15,0x11,0x36,0x01,0xe2,0x80,0x8a,0x9a,0x56,0x86,0x5e,0xa6,0xba,0x68,0x82,0x9e,0x1f,0x3e,0x2f,0x38,0xa5,0x02,0x89,0xe5,0xe5,0x05,0x9c,0x86,0x8a,0x84,0x78,0x90,0xbc,0x06,0x01,0x24,0xb7,0x9b,0x82,0x84,0x9e,0x01,0x1e,0x54,0x62,0x48, 0xfe,0xd8,0x08,0x00,0x00,0x01,0xff,0xf6,0x01,0x94,0x02,0x62,0x04,0xcf,0x00,0x1c,0x00,0x3c,0x40,0x0b,0x06,0x09,0x14,0x17,0x04,0x08,0x16,0x0e,0x0c,0x1c,0x1a,0xb8,0x01,0x0d,0xb3,0x02,0x08,0x11,0x16,0xbc,0x01,0x08,0x00,0x0c,0x01,0x0d,0x00,0x11,0x01,0x09,0xb4,0x16,0x00,0x1e,0x0e,0x08,0x2f,0xc6,0x10,0xd4,0xc4,0x00,0x3f,0xed, 0x3f,0x10,0xd4,0xd4,0xfd,0xc6,0x10,0xc6,0x11,0x12,0x17,0x39,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x27,0x27,0x03,0x23,0x13,0x27,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x17,0x37,0x33,0x03,0x17,0x16,0x33,0x32,0x37,0x02,0x62,0x20,0x21,0x41,0x4c,0x28,0x47,0xa0,0x8f,0xf0,0x4e,0x29,0x2b,0x13,0x1b,0x1c,0x28,0x6a,0x34,0x3d, 0x7d,0x8c,0xca,0x67,0x2f,0x2e,0x17,0x13,0x01,0x9e,0x0a,0x44,0x5b,0xa8,0xfe,0xc9,0x01,0xb4,0xb0,0x5c,0x0a,0x6c,0x09,0x7b,0x92,0xfc,0xfe,0x8e,0xe6,0x68,0x08,0x00,0xff,0xff,0x00,0x58,0xff,0x42,0x00,0xf6,0x02,0x6c,0x00,0x07,0x07,0xce,0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x66,0xff,0x42,0x01,0xa8,0x01,0x70,0x00,0x07,0x06,0x79, 0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x5c,0xff,0x31,0x02,0x46,0x01,0x66,0x00,0x07,0x07,0xba,0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x0a,0xff,0x42,0x02,0x35,0x01,0x66,0x00,0x07,0x07,0xbd,0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x60,0xfe,0x4c,0x02,0x74,0x02,0x6c,0x00,0x07,0x07,0xbf,0x00,0x00,0xfc,0xa8,0xff,0xff,0xff,0xec,0xfe,0x4c, 0x02,0x23,0x01,0x66,0x00,0x07,0x07,0xc0,0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x66,0xfe,0x4c,0x02,0x89,0x01,0x77,0x00,0x07,0x07,0xcf,0x00,0x00,0xfc,0xa8,0xff,0xff,0x00,0x3e,0xfe,0x4c,0x03,0x06,0x01,0x77,0x00,0x07,0x07,0xc2,0x00,0x00,0xfc,0xa8,0xff,0xff,0xff,0xf6,0xfe,0x3c,0x02,0x62,0x01,0x77,0x00,0x07,0x07,0xc3,0x00,0x00, 0xfc,0xa8,0x00,0x01,0x00,0xfc,0x04,0xc2,0x03,0xc4,0x05,0xf2,0x00,0x0c,0x00,0x16,0x40,0x09,0x00,0x07,0x09,0xf2,0x03,0x00,0x0c,0x07,0x06,0x2f,0xcd,0xd4,0xcd,0x00,0x2f,0xfd,0xd6,0xc4,0x31,0x30,0x01,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x03,0xc4,0x0f,0xc5,0x94,0x98,0xbf,0x09,0xa2,0x0e,0xb2,0x50,0x68, 0x0c,0x05,0xf2,0x8d,0xa3,0xa3,0x8d,0xbc,0x63,0x59,0x00,0x02,0x00,0x58,0x02,0x9a,0x00,0xf6,0x05,0xc4,0x00,0x07,0x00,0x0b,0x00,0x25,0xb3,0x04,0x00,0x40,0x0a,0xba,0x01,0x08,0x00,0x09,0x01,0x0a,0xb6,0x09,0x08,0x02,0x06,0xff,0x3a,0x08,0xb9,0x01,0x0c,0x00,0x09,0x2f,0xe1,0x2b,0x00,0x18,0x3f,0x3f,0x1a,0xde,0xcd,0x31,0x30,0x13, 0x22,0x35,0x34,0x33,0x32,0x15,0x14,0x03,0x23,0x11,0x33,0xa6,0x4e,0x50,0x4e,0x0e,0x82,0x82,0x05,0x2d,0x4c,0x4b,0x4b,0x4c,0xfd,0x6d,0x02,0x24,0x00,0x02,0x00,0x66,0x01,0xa4,0x02,0x89,0x04,0xcf,0x00,0x0e,0x00,0x19,0x00,0x31,0xb1,0x02,0x13,0x41,0x09,0x01,0x0d,0x00,0x0d,0x01,0x0b,0x00,0x17,0x01,0x0d,0x00,0x07,0x01,0x09,0x00, 0x0a,0x01,0x0c,0xb4,0x15,0x15,0x1b,0x0f,0x02,0xb9,0x01,0x0c,0x00,0x03,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xed,0x3f,0xed,0xc6,0x31,0x30,0x13,0x23,0x11,0x23,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x03,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x06,0xe8,0x02,0x80,0x9a,0x7d,0x7a,0x92,0x8f,0x6c, 0x72,0x36,0x51,0x40,0x91,0x91,0x40,0x51,0x02,0xdd,0xfe,0xc7,0x02,0x00,0x8b,0xa0,0x9a,0x7d,0x84,0xab,0x01,0x37,0x2e,0x46,0x5c,0xc2,0xb6,0x60,0x00,0x01,0x00,0x42,0x00,0x00,0x03,0xc1,0x05,0xba,0x00,0x06,0x00,0x33,0x40,0x1c,0x9d,0x02,0x01,0x5b,0x02,0x6b,0x02,0x7b,0x02,0x03,0x49,0x02,0x01,0x38,0x02,0x01,0x05,0x02,0x06,0x08, 0x03,0x04,0x04,0x03,0x03,0x02,0x06,0x00,0x00,0x2f,0x2f,0x33,0x39,0x2f,0x33,0x01,0x2f,0x33,0x10,0xde,0xdd,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x01,0x27,0x01,0x33,0x03,0xc1,0x9c,0xfd,0x71,0x54,0x02,0xe3,0x9c,0x05,0x00,0xfd,0x8f,0x6a,0x02,0xc1,0x00,0x02,0x00,0x8f,0xff,0xe7,0x06,0xb2,0x04,0x19,0x00,0x20, 0x00,0x27,0x00,0xe1,0x40,0x34,0x69,0x23,0x79,0x23,0x02,0xe6,0x1e,0xf6,0x1e,0x02,0x55,0x14,0x65,0x14,0x02,0xaa,0x0f,0x01,0xcf,0x26,0xdf,0x26,0x02,0x9b,0x26,0xfb,0x26,0x02,0x24,0x26,0x34,0x26,0x02,0x05,0x17,0x01,0x7e,0x0f,0x8e,0x0f,0x9e,0x0f,0x03,0x09,0x0f,0x19,0x0f,0x02,0x5b,0x0a,0x01,0x02,0xb8,0xff,0xe8,0x40,0x0e,0x13, 0x16,0x48,0x24,0x02,0x34,0x02,0x44,0x02,0x03,0xe2,0x1b,0x01,0x1b,0xb8,0xff,0xe0,0xb3,0x19,0x1c,0x48,0x1b,0xb8,0xff,0xe0,0x40,0x51,0x0b,0x0e,0x48,0xcb,0x0b,0x01,0x5b,0x0b,0x01,0x1b,0x0b,0x1d,0x0e,0x27,0x95,0xe0,0x01,0xf0,0x01,0x02,0x01,0x01,0x09,0x24,0x95,0x1d,0x10,0x19,0x11,0x0f,0x07,0xec,0x00,0x06,0x10,0x06,0x02,0x06, 0x04,0x95,0x09,0x16,0x15,0x95,0x0e,0x16,0x27,0x01,0x0b,0x03,0x1a,0x84,0x5f,0x19,0x7f,0x19,0x02,0x20,0x19,0xa0,0x19,0x02,0x19,0x19,0x11,0x06,0x40,0x0f,0x12,0x48,0x06,0x21,0x83,0x00,0x29,0x12,0x84,0x00,0x11,0x01,0x11,0x2f,0x5d,0xe1,0x10,0xde,0xe1,0xc6,0x2b,0x12,0x39,0x2f,0x5d,0x5d,0xe1,0x17,0x39,0x00,0x3f,0xed,0x3f,0xfd, 0xd6,0x5d,0xed,0x3f,0xc4,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x11,0x12,0x39,0x39,0x5d,0x5d,0x2b,0x2b,0x5d,0x31,0x30,0x5d,0x2b,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x27,0x06,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33, 0x15,0x36,0x33,0x32,0x12,0x15,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x06,0xb2,0xfd,0x2f,0x05,0xae,0x99,0xac,0x91,0x8a,0xc7,0xfe,0xd9,0x71,0x2a,0xba,0x8d,0xfe,0x7f,0xa4,0xfe,0x7c,0x90,0xa4,0x7d,0xbb,0xc2,0xd7,0xa8,0x02,0x86,0x78,0x71,0xa3,0x15,0x01,0xd7,0xae,0xb6,0x70,0x99,0x63,0xea,0x66,0x84,0x01,0xb5,0x02,0x64,0xfd,0xb6, 0xfe,0xbd,0xb3,0x94,0x02,0x46,0x7b,0x94,0xfe,0xf8,0xe4,0x35,0x91,0x9a,0xa0,0x8b,0x00,0x01,0x00,0x74,0x00,0x00,0x04,0x8b,0x05,0xb4,0x00,0x27,0x00,0x57,0x40,0x2e,0x1d,0x91,0x02,0x02,0x1e,0x00,0x25,0x92,0x40,0x22,0x1e,0x00,0x22,0x92,0x28,0x30,0x21,0x92,0x1e,0x1e,0x0c,0x27,0x92,0x00,0x10,0x13,0x92,0x0c,0x04,0x0f,0x0f,0x1d, 0x22,0x26,0x7e,0x01,0x01,0x07,0x24,0x20,0x00,0x00,0x29,0x18,0x7e,0x07,0x2f,0xe1,0x12,0x39,0x2f,0xc4,0xc4,0x12,0x39,0x2f,0xf1,0x32,0x33,0xc0,0x2f,0x31,0x00,0x3f,0xfd,0xc6,0x2f,0xed,0x12,0x39,0x2f,0xed,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x21,0x11,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32, 0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x04,0x8b,0xfd,0xb6,0x6b,0xab,0x77,0x40,0x49,0x8a,0xc5,0x7c,0x44,0x7d,0x34,0x39,0x80,0x42,0x55,0x86,0x5b,0x30,0x24,0x49,0x6e,0x4a,0x02,0x33,0xfe,0x6f,0x01,0x74,0xfe,0x8c,0x01,0xa8,0x01,0x7e,0x03,0x54, 0x8d,0xb9,0x69,0x7a,0xce,0x95,0x53,0x19,0x19,0xac,0x28,0x26,0x3f,0x6d,0x93,0x53,0x4c,0x81,0x63,0x3f,0x0b,0x01,0xe8,0x8c,0xfe,0xd4,0x8c,0xfe,0xd0,0x00,0x00,0x03,0x00,0x76,0xff,0xb5,0x04,0x18,0x06,0x3d,0x00,0x2e,0x00,0x36,0x00,0x40,0x00,0x97,0x40,0x1d,0x23,0x1e,0x1b,0x1d,0x20,0x22,0x25,0x04,0x1b,0x0e,0x31,0x3b,0x3e,0x04, 0x3f,0x15,0x01,0x15,0x10,0x92,0x1b,0x13,0x04,0x07,0x0a,0x2d,0x04,0x01,0x0b,0xb8,0xff,0xc0,0x40,0x3c,0x0c,0x0f,0x48,0x0b,0x37,0x0d,0x32,0x3a,0x3f,0x04,0x37,0x05,0x2e,0x37,0x92,0x01,0x32,0x3a,0x3f,0x0d,0x04,0x0b,0x31,0x3b,0x3e,0x0e,0x04,0x16,0x2f,0x2d,0x01,0x04,0x07,0x04,0x0b,0x25,0x22,0x20,0x1d,0x04,0x16,0x28,0x05,0x06, 0x1e,0x03,0x1f,0x00,0x23,0x2e,0x03,0x24,0x28,0x0b,0x16,0x16,0x42,0x2f,0x7d,0x28,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x10,0xd4,0x17,0x32,0xc4,0x17,0x32,0x11,0x12,0x17,0x39,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x12,0x17,0x39,0x31,0x00,0x2f,0xed,0xcd,0x32,0x11,0x17,0x33,0x10,0xc4,0x2b,0x11,0x17,0x33,0x3f,0xfd,0xc6,0x5d,0x17,0x33, 0x11,0x17,0x33,0x10,0xce,0x32,0x30,0x01,0x07,0x32,0x16,0x17,0x37,0x33,0x07,0x16,0x16,0x17,0x15,0x26,0x27,0x01,0x16,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x27,0x07,0x23,0x37,0x26,0x27,0x07,0x23,0x13,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x37,0x37,0x01,0x14,0x17,0x01,0x0e,0x03,0x01,0x22,0x06,0x07,0x01,0x16,0x16, 0x17,0x01,0x26,0x03,0x36,0x2b,0x1a,0x2f,0x16,0x2b,0x73,0x31,0x10,0x20,0x11,0x3c,0x30,0xfe,0xa3,0x42,0x52,0x2f,0x4e,0x49,0x48,0x27,0x26,0x4a,0x50,0x57,0x34,0x5a,0x50,0x17,0x71,0x23,0x2a,0x27,0x33,0x71,0x4d,0x4c,0x54,0x52,0x91,0xc7,0x76,0x2d,0xfe,0x63,0x34,0x01,0x0b,0x48,0x76,0x54,0x2d,0x01,0xdf,0x0a,0x12,0x09,0xfe,0xc4, 0x11,0x25,0x14,0x01,0x52,0x1c,0x06,0x3d,0x8b,0x02,0x02,0x8f,0xa2,0x04,0x0a,0x05,0xa5,0x1b,0x10,0xfb,0x82,0x1c,0x0a,0x14,0x1e,0x14,0x96,0x11,0x1a,0x12,0x09,0x18,0x4b,0x74,0x18,0x1e,0xaa,0x01,0x00,0x5e,0x01,0x00,0x9f,0x9a,0x01,0x03,0xc5,0x7f,0x15,0x95,0xfc,0x7f,0xa6,0x80,0x03,0x71,0x1d,0x6d,0x98,0xbd,0x01,0xfe,0x01,0x01, 0xfb,0xf0,0x16,0x25,0x11,0x04,0x5b,0x03,0x00,0x01,0x00,0x76,0xff,0xe8,0x04,0x18,0x05,0xb2,0x00,0x3e,0x00,0x5e,0x40,0x16,0x38,0x37,0x3b,0x00,0x02,0x95,0x3b,0x35,0x35,0x1f,0x15,0x34,0x07,0x3f,0x0f,0x01,0x0f,0x0a,0x92,0x15,0x13,0x25,0xb8,0xff,0xc0,0x40,0x0c,0x0c,0x0f,0x48,0x25,0x2a,0x92,0x1f,0x04,0x38,0x00,0x37,0x07,0xb8, 0x01,0x2e,0x40,0x0b,0x34,0x34,0x1a,0x00,0x25,0x10,0x10,0x40,0x2f,0x7d,0x1a,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0x12,0x39,0x2f,0xe1,0x32,0x12,0x39,0x00,0x3f,0xfd,0xc6,0x2b,0x3f,0xfd,0xc6,0x5d,0x33,0x33,0x11,0x12,0x39,0x2f,0xd4,0xfd,0xc6,0x11,0x33,0x33,0x31,0x30,0x01,0x26,0x23,0x22,0x07,0x06,0x15,0x11,0x16,0x32,0x33,0x32, 0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x04,0x18,0x27,0x48,0x5f,0x3f,0x3f,0x05,0x0c,0x06,0x2f,0x4e,0x49,0x48,0x27,0x26,0x4a,0x50,0x57,0x34,0x83, 0xdc,0x9f,0x59,0x65,0xb1,0xf0,0x8b,0x2c,0x47,0x40,0x3d,0x21,0x27,0x42,0x40,0x43,0x27,0x69,0xaf,0x80,0x47,0x27,0x48,0x66,0x3f,0x92,0x04,0x20,0x80,0x50,0x1d,0x2b,0x10,0x03,0x1c,0x1e,0x59,0x58,0x9a,0xfe,0x86,0x01,0x0a,0x14,0x1e,0x14,0x96,0x11,0x1a,0x12,0x09,0x66,0xba,0x01,0x08,0xa2,0xac,0x01,0x1b,0xca,0x6f,0x05,0x0a,0x10, 0x0b,0xa5,0x12,0x19,0x10,0x08,0x5b,0xa3,0xe3,0x89,0x63,0xae,0x8c,0x68,0x1e,0x03,0x18,0xbd,0x61,0x6c,0x07,0x06,0x00,0x01,0x00,0xa6,0xff,0x12,0x06,0x54,0x05,0x0c,0x00,0x2e,0x00,0x8c,0x40,0x48,0x10,0x13,0x16,0x03,0x12,0x26,0x2e,0x01,0x15,0x12,0x06,0x20,0x2d,0x2b,0x0f,0x0c,0x95,0x01,0x24,0x23,0x19,0x95,0x01,0x26,0x10,0x21, 0x0f,0x2d,0x16,0x15,0x2e,0x15,0x2d,0x16,0x2e,0x15,0x13,0x10,0x0f,0x01,0x14,0x00,0x01,0x0f,0x10,0x13,0x04,0x14,0x2e,0x00,0x00,0x06,0x14,0x15,0x20,0x2b,0x2b,0x17,0x11,0x84,0x12,0x12,0x20,0x06,0x84,0x05,0x05,0x30,0x23,0x1f,0x84,0x20,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xf1,0x33,0xc1,0x2f,0x10,0xc6,0x32,0x10, 0xc0,0x2f,0x32,0x12,0x00,0x17,0x39,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x11,0x12,0x00,0x39,0x39,0x10,0x87,0x05,0xc0,0xc0,0x31,0x00,0x3f,0x3f,0x33,0xed,0x32,0x32,0x10,0xed,0x32,0x33,0x33,0x2f,0x33,0x33,0xc6,0x10,0xcd,0x11,0x12,0x17,0x39,0x31,0x30,0x01,0x07,0x33,0x20,0x11,0x11,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x03, 0x11,0x23,0x35,0x03,0x23,0x01,0x35,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x17,0x36,0x37,0x13,0x05,0x85,0x87,0x04,0x01,0x52,0xa4,0x11,0x32,0x5a,0x48,0x07,0x0d,0x07,0xe1,0xa4,0xf5,0x99,0x01,0x8e,0xe9,0x3f,0x5e,0x3d,0x1e,0xa4,0xa4,0x04,0x6e,0xd0,0x32,0x5d,0x4d,0x38,0x0e,0x3e, 0x5f,0x9f,0x05,0x0c,0xf4,0xfe,0x5f,0xfd,0x89,0x02,0x4c,0x46,0x76,0x56,0x30,0x01,0x01,0xfe,0x69,0xfe,0x0b,0xcc,0xfe,0x46,0x02,0xd0,0x7e,0x01,0x2e,0x39,0x5c,0x75,0x3c,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x1e,0x38,0x4e,0x30,0x73,0x34,0x01,0x21,0x00,0x00,0x05,0x00,0x23,0x00,0x00,0x05,0x0a,0x05,0x9a,0x00,0x1b,0x00,0x1f,0x00,0x23, 0x00,0x29,0x00,0x31,0x00,0x98,0x40,0x5a,0x24,0x25,0x2a,0x2b,0x04,0x15,0x02,0x0f,0x13,0x29,0x03,0x0c,0x1c,0x20,0x03,0x17,0x92,0x18,0x0b,0x1f,0x23,0x03,0x04,0x08,0x2e,0x03,0x1b,0x92,0x2f,0x00,0x01,0x90,0x00,0xa0,0x00,0xc0,0x00,0xd0,0x00,0x04,0x00,0x00,0x02,0x11,0x15,0x06,0x02,0x03,0x12,0x21,0x22,0x2f,0x04,0x2a,0x11,0x29, 0x1c,0x1f,0x04,0x04,0x03,0x24,0x1b,0x17,0x15,0x19,0x01,0x15,0x0c,0x08,0x0a,0x0e,0x25,0x1e,0x13,0x20,0x2a,0x03,0x14,0x03,0x15,0x11,0x06,0x7f,0x10,0x10,0x33,0x14,0x7f,0x15,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x33,0x11,0x33,0x11,0x17,0x33,0x32,0x32,0xc6,0x32,0x33,0x33,0x11,0x33,0x33,0x10,0xc6,0x32,0x11,0x12,0x17,0x39,0x11,0x12, 0x17,0x39,0x31,0x00,0x3f,0x33,0x2f,0x33,0x12,0x39,0x2f,0x5d,0x5d,0xfd,0x17,0x33,0x17,0x32,0xd6,0xed,0x17,0x33,0x17,0x32,0x11,0x12,0x17,0x39,0x31,0x30,0x13,0x33,0x11,0x33,0x13,0x21,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x11,0x23,0x01,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x05,0x33,0x35,0x21,0x05,0x21, 0x27,0x23,0x01,0x33,0x26,0x35,0x35,0x23,0x01,0x23,0x16,0x15,0x15,0x33,0x27,0x26,0x23,0x99,0xcb,0xf1,0x01,0x5f,0x97,0x9c,0x9c,0x9c,0x9c,0xc2,0xfe,0xfb,0xfe,0xac,0x97,0x99,0x99,0x99,0x02,0xde,0xd6,0xfe,0xe7,0xfe,0x95,0x01,0x0f,0x44,0xcb,0x02,0x88,0x03,0x07,0x92,0xfe,0x0c,0x05,0x07,0x85,0x60,0x1b,0x03,0xae,0x01,0xec,0xfe, 0x14,0x01,0xec,0xfe,0x14,0x8d,0x88,0x8c,0xfd,0xf3,0x02,0x0d,0xfd,0xf3,0x02,0x0d,0x8c,0x88,0x88,0x88,0x88,0x88,0xfd,0xbc,0x31,0xa0,0x5f,0x02,0xbb,0x2e,0x94,0x58,0xc2,0x37,0x00,0x03,0x00,0xbc,0xff,0xe8,0x06,0x77,0x05,0x9a,0x00,0x16,0x00,0x21,0x00,0x54,0x00,0x84,0x40,0x12,0x2c,0x47,0x51,0x36,0x60,0x3a,0x70,0x3a,0x02,0x3a, 0x3d,0x95,0x36,0x36,0x36,0x07,0x08,0x22,0xb8,0xff,0xc0,0x40,0x33,0x09,0x0e,0x48,0x22,0x25,0x95,0x51,0x16,0x14,0x13,0x18,0x91,0x05,0x05,0x08,0x01,0x07,0x17,0x91,0x08,0x03,0x22,0x31,0x3a,0x4c,0x42,0x7e,0x31,0x31,0x27,0x1e,0x13,0x13,0x0e,0x01,0x00,0x00,0x0e,0x7d,0x1e,0x1e,0x07,0x27,0x7e,0x4c,0x4c,0x56,0x18,0x06,0x7e,0x07, 0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xf1,0xc2,0x2f,0x32,0x10,0xc1,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x10,0xc4,0x10,0xc6,0x31,0x00,0x3f,0xed,0x2f,0x33,0x12,0x39,0x2f,0xed,0x39,0x39,0x3f,0xfd,0xc6,0x2b,0x11,0x12,0x39,0x2f,0x2f,0xfd,0xc6,0x5d,0x11,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x03,0x26,0x23,0x23,0x11,0x23, 0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x16,0x17,0x01,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x01,0x16,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26, 0x27,0x04,0x04,0xc8,0xb1,0x4e,0x8d,0x4c,0xa8,0x01,0x60,0x5e,0x9e,0x72,0x40,0x29,0x4e,0x72,0x4a,0x51,0x42,0xfe,0x3a,0x92,0x3f,0x6b,0x4e,0x2c,0x8f,0x8d,0x02,0x21,0x3e,0x81,0x44,0xb0,0x1d,0x31,0x40,0x23,0x49,0x61,0x3b,0x18,0x2e,0x57,0x7d,0x4f,0x39,0x73,0x2d,0x33,0x6e,0x3d,0x24,0x3d,0x2b,0x19,0x17,0x2b,0x3c,0x24,0x42,0x64, 0x42,0x22,0x23,0x51,0x84,0x61,0x45,0x84,0x36,0x01,0xb0,0xb2,0xfd,0x9e,0x05,0x9a,0x2f,0x60,0x8f,0x60,0x4b,0x82,0x67,0x48,0x10,0x04,0x1e,0x8c,0x03,0x20,0xfd,0xf8,0x26,0x47,0x67,0x40,0x73,0x81,0xfb,0xcc,0x2a,0x31,0x6e,0x1f,0x2c,0x1f,0x18,0x0c,0x18,0x35,0x41,0x4d,0x2f,0x35,0x5c,0x46,0x28,0x14,0x12,0xa3,0x1f,0x20,0x0f,0x1c, 0x28,0x19,0x21,0x2a,0x1d,0x16,0x0c,0x16,0x2f,0x3e,0x50,0x37,0x31,0x5e,0x4a,0x2d,0x1d,0x1b,0x00,0x07,0x00,0x14,0x00,0x00,0x05,0xe0,0x05,0x9a,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x33,0x00,0x3b,0x00,0x43,0x01,0x3f,0x40,0xb7,0x1a,0x1d,0x1e,0x01,0x02,0x19,0x02,0x17,0x26,0x25,0x3a,0x39,0x18,0x39,0x3b,0x24,0x27,0x16, 0x15,0x34,0x15,0x04,0x29,0x2a,0x41,0x42,0x03,0x42,0x40,0x2b,0x28,0x05,0x06,0x3f,0x06,0x13,0x22,0x21,0x32,0x31,0x14,0x31,0x12,0x23,0x20,0x33,0x2c,0x11,0x2c,0x0f,0x0c,0x0b,0x08,0x07,0x10,0x07,0x2e,0x2f,0x36,0x37,0x04,0x07,0x10,0x01,0x05,0x33,0x3b,0x04,0x1e,0x20,0x24,0x28,0x04,0x09,0x92,0x0a,0x1d,0x23,0x27,0x2b,0x04,0x12, 0x16,0x1a,0x40,0x41,0x05,0x0d,0x92,0x0e,0x0e,0x10,0x03,0x07,0x18,0x14,0x10,0x03,0x04,0x2a,0x41,0x03,0x3c,0x03,0x3b,0x24,0x27,0x16,0x04,0x15,0x37,0x3a,0x25,0x26,0x17,0x04,0x18,0x36,0x01,0x1e,0x1d,0x1a,0x04,0x19,0x02,0x05,0x28,0x2b,0x40,0x04,0x3d,0x06,0x32,0x21,0x22,0x13,0x04,0x14,0x2f,0x12,0x23,0x20,0x33,0x04,0x11,0x2e, 0x08,0x0c,0x0f,0x03,0x10,0x07,0x15,0x14,0x06,0x1c,0x00,0x02,0x0d,0x09,0x07,0x11,0x10,0x07,0x18,0x19,0x03,0x36,0x37,0x19,0x04,0x02,0x02,0x45,0x07,0x11,0x10,0x06,0x2e,0x2f,0x10,0x04,0x07,0x2f,0x17,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0x17,0x33,0x2f,0x33,0x11,0x33,0x33,0x10,0xc6,0x32,0x10,0xc6,0x32,0x10,0xcd,0x32,0x11,0x12, 0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39,0x31,0x00,0x3f,0x33,0x33,0x2f,0x33,0x12,0x39,0x2f,0xfd,0x17,0x33,0x17,0x32,0xd6,0xed,0x17,0x33,0x17,0x32,0x11,0x12,0x17,0x39,0x30,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x10, 0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x31,0x30,0x01,0x21,0x03,0x23,0x03,0x23,0x03,0x23,0x03,0x21,0x35,0x33,0x27,0x23,0x35,0x33,0x03,0x33,0x13,0x21,0x13, 0x33,0x13,0x21,0x13,0x33,0x03,0x33,0x15,0x23,0x07,0x33,0x21,0x33,0x37,0x23,0x05,0x33,0x37,0x23,0x05,0x33,0x27,0x23,0x03,0x16,0x17,0x33,0x36,0x37,0x37,0x23,0x05,0x16,0x17,0x33,0x36,0x37,0x37,0x23,0x03,0x23,0x06,0x07,0x07,0x33,0x27,0x26,0x05,0xe0,0xfe,0xf3,0x63,0xa2,0x63,0xe7,0x63,0xa1,0x67,0xfe,0xfb,0xe9,0x1a,0xcf,0xb3, 0x5f,0x8f,0x5a,0x01,0x0d,0x5e,0x84,0x59,0x01,0x01,0x57,0x8d,0x5c,0xbe,0xd9,0x19,0xf1,0xfb,0xa5,0xa5,0x1a,0xd8,0x02,0x60,0x9e,0x18,0xcf,0xfe,0xed,0xb2,0x19,0x80,0xf7,0x0d,0x03,0x04,0x03,0x11,0x25,0x71,0x02,0x6d,0x0b,0x05,0x02,0x03,0x0f,0x23,0x6c,0xea,0x03,0x04,0x0d,0x14,0x4a,0x13,0x0d,0x02,0x10,0xfd,0xf0,0x02,0x10,0xfd, 0xf0,0x02,0x10,0x8c,0x88,0x8d,0x01,0xe9,0xfe,0x17,0x01,0xe9,0xfe,0x17,0x01,0xe9,0xfe,0x17,0x8d,0x88,0x88,0x88,0x88,0x88,0x88,0xfe,0x2a,0x45,0x4b,0x35,0x5b,0xc2,0xca,0x39,0x4d,0x34,0x56,0xc6,0x02,0x9a,0x4a,0x46,0x69,0x67,0x43,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x03,0xd3,0x04,0x00,0x00,0x0f,0x00,0x1f,0x00,0x4a,0x40,0x23, 0x19,0x01,0xbe,0x0e,0x0e,0x1f,0x0f,0x1e,0xbe,0x06,0x11,0x0f,0x00,0xcd,0x0f,0x0f,0x10,0x18,0xc2,0x19,0x19,0x10,0x06,0xc2,0x2f,0x07,0x3f,0x07,0x02,0x07,0x07,0x21,0x1f,0xcd,0x10,0xb8,0xff,0xc0,0xb3,0x0b,0x10,0x48,0x10,0x2f,0x2b,0xe1,0x12,0x39,0x2f,0x5d,0xe1,0x11,0x39,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x31,0x00,0x3f,0x33,0xfd, 0xc6,0x2f,0x33,0x10,0xfd,0xc6,0x31,0x30,0x01,0x11,0x21,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x21,0x11,0x03,0x11,0x21,0x32,0x1e,0x02,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x21,0x11,0x01,0xe0,0x01,0x07,0x31,0x3a,0x81,0x1a,0x38,0x57,0x3d,0xfe,0x75,0xfe,0x01,0x8b,0x3d,0x57,0x38,0x1a,0x81,0x3a,0x31,0xfe,0xf9,0x03, 0x05,0xfd,0x7f,0x40,0x3b,0x03,0x01,0xfc,0xe4,0x2d,0x52,0x3f,0x26,0x03,0x05,0xfc,0xfb,0x04,0x00,0x25,0x3f,0x53,0x2d,0xfd,0xdf,0x02,0x07,0x3a,0x40,0xfc,0x84,0x00,0x00,0x03,0x00,0x60,0xfe,0xd7,0x04,0x98,0x05,0xec,0x00,0x1c,0x00,0x31,0x00,0x35,0x00,0x5b,0x40,0x33,0x33,0x96,0x34,0x05,0x01,0x02,0x2d,0x95,0x05,0x16,0x11,0x23, 0x95,0x0f,0x10,0x1c,0x19,0x14,0x96,0x0f,0x15,0x1f,0x15,0x2f,0x15,0x03,0x15,0x17,0x00,0x11,0x03,0x0a,0x35,0x00,0x34,0x14,0x0a,0x1b,0x19,0x12,0x16,0x1d,0x03,0x01,0x84,0x00,0x00,0x37,0x28,0x83,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x17,0x32,0x33,0xc6,0x10,0xc4,0xc4,0x10,0xc6,0x12,0x39,0x39,0x31,0x00,0x3f,0xd6,0x5d,0xed,0x33, 0x32,0x3f,0xed,0x33,0x3f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x33,0x11,0x21,0x35,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x13,0x21,0x35,0x21,0x04,0x10,0xa4, 0x04,0x72,0xee,0x6c,0xa0,0x69,0x33,0x3b,0x75,0xb0,0x75,0xd0,0x63,0x04,0xfe,0xb5,0x01,0x4b,0xa4,0x88,0x88,0xa4,0x2c,0x4d,0x6a,0x3f,0x56,0x7a,0x4e,0x24,0x23,0x4a,0x73,0x50,0x47,0x73,0x51,0x2b,0x7b,0xfc,0xae,0x03,0x52,0xae,0xc6,0x52,0x8b,0xba,0x69,0x71,0xcc,0x99,0x5a,0xa6,0x01,0x40,0x86,0xb4,0xb4,0x86,0xfd,0x1d,0x97,0x3e, 0x6c,0x50,0x2e,0x43,0x72,0x96,0x53,0x4c,0x8b,0x69,0x3e,0x39,0x60,0x7e,0xfd,0x4e,0x77,0x00,0x00,0x01,0x00,0x2a,0x00,0x00,0x03,0xfd,0x05,0x9a,0x00,0x19,0x00,0x44,0x40,0x22,0x19,0x06,0x16,0x10,0x0a,0x92,0x0b,0x0b,0x0d,0x01,0x08,0x14,0x0d,0x03,0x05,0x10,0x16,0x19,0x04,0x17,0x08,0x01,0x00,0x14,0x17,0x15,0x15,0x1b,0x0a,0x0f, 0x0c,0x07,0x7e,0x08,0x2f,0xe1,0x33,0x32,0xc6,0x12,0x39,0x2f,0xc6,0x33,0xc6,0x32,0x11,0x12,0x17,0x39,0x31,0x00,0x3f,0x33,0x2f,0x33,0x12,0x39,0x2f,0xed,0x33,0x33,0x32,0x32,0x31,0x30,0x21,0x23,0x01,0x26,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x21,0x15,0x21,0x03,0xfd, 0xdb,0xfe,0x6c,0x10,0x0e,0x08,0x04,0xa8,0x92,0x92,0xa8,0x04,0x08,0x16,0x08,0x01,0x96,0xc2,0xfe,0x36,0x01,0x70,0xfe,0x97,0x02,0x54,0x1a,0x1b,0x0e,0xfd,0x69,0x02,0x9e,0x8d,0x02,0x6f,0xfd,0x8f,0x0e,0x22,0x0c,0x02,0x35,0xfd,0x91,0x8d,0x00,0x01,0x00,0x29,0x00,0x00,0x03,0x6c,0x05,0x9a,0x00,0x17,0x00,0x73,0x40,0x3b,0x08,0x05, 0x09,0x04,0x0b,0x02,0x0a,0x03,0x0c,0x01,0x0d,0x00,0x16,0x0f,0x17,0x0e,0x0d,0x0a,0x09,0x04,0x50,0x03,0x01,0x03,0x00,0x0d,0x00,0x6f,0x17,0x7f,0x17,0x02,0x17,0x17,0x12,0x07,0x15,0x11,0x91,0x12,0x03,0x0a,0x0e,0x11,0x07,0x03,0x17,0x16,0x02,0x06,0x0f,0x0b,0x07,0x14,0x14,0x19,0x06,0x7e,0x07,0x2f,0xe1,0x12,0x39,0x2f,0x11,0x33, 0x33,0x11,0x33,0x33,0xc6,0x32,0x10,0xd4,0xc6,0x32,0x31,0x00,0x3f,0xed,0x32,0x2f,0x12,0x39,0x2f,0x5d,0xcd,0xcd,0x10,0xd6,0x5d,0xcd,0xdd,0xcd,0x10,0xcd,0x11,0x39,0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x07,0x15,0x37,0x15,0x07,0x11,0x23,0x11,0x07,0x35,0x37,0x35,0x07,0x35,0x37,0x11, 0x21,0x35,0x21,0x15,0x21,0x11,0x37,0x03,0x08,0xea,0xea,0xea,0xa8,0xef,0xef,0xef,0xef,0xfe,0xb3,0x03,0x43,0xfe,0xb2,0xea,0x03,0xb5,0x85,0xcc,0x85,0x8e,0x85,0xfe,0x2a,0x01,0x76,0x87,0x8e,0x87,0xcc,0x87,0x8e,0x87,0x01,0xa4,0x98,0x98,0xfe,0xbc,0x85,0x00,0x00,0x05,0x00,0x2c,0xfe,0x9e,0x08,0xe2,0x06,0x77,0x00,0x3a,0x00,0x53, 0x00,0x6a,0x00,0x7e,0x00,0x8e,0x00,0x84,0x40,0x4c,0x1e,0x3e,0x8c,0x0c,0x04,0x0f,0x19,0x29,0x32,0x24,0x36,0x4f,0xe2,0x2f,0x7a,0xe7,0x59,0x70,0x69,0x70,0x52,0x63,0x7f,0xdb,0x0f,0x19,0x1f,0x19,0x02,0x19,0x89,0x43,0xe2,0x07,0x63,0x07,0x89,0xdb,0x0f,0x0c,0x1e,0x24,0x2f,0x36,0x3e,0x4f,0x8c,0x08,0x00,0x14,0x32,0x33,0x33,0x00, 0x29,0x2a,0x14,0x54,0x68,0x69,0x6b,0x04,0x6a,0x00,0xb1,0x4a,0x4a,0x14,0x75,0xea,0x5e,0x5e,0x90,0x84,0xf3,0x14,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0xc4,0x17,0x32,0x10,0xc4,0x32,0x10,0xc0,0x2f,0x32,0x11,0x12,0x17,0x39,0x31,0x00,0x2f,0xed,0x33,0x33,0x10,0xed,0x10,0xd4,0x5d,0xed,0x10,0xed,0xc6,0x10,0xd4,0xed, 0x2f,0xed,0x33,0x32,0xcd,0xc4,0x11,0x12,0x17,0x39,0x31,0x30,0x01,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x36,0x12,0x37,0x36,0x36,0x37,0x0e,0x03,0x07,0x27,0x3e,0x03,0x37,0x36,0x36,0x37,0x17,0x06,0x06,0x07,0x1e,0x03,0x05,0x06,0x02,0x07,0x1e,0x03, 0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x02,0x27,0x0e,0x03,0x01,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x03,0x23,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x05,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x26,0x26,0x06,0x84,0x23,0x4d,0x78, 0xaa,0xdf,0x8c,0x3b,0x66,0x58,0x4c,0x22,0x42,0x94,0x55,0x2e,0x4a,0x34,0x1d,0x23,0x3a,0x4b,0x28,0x26,0x44,0x3d,0x3a,0x1c,0x36,0x58,0x26,0x25,0x5e,0x3c,0x5a,0x9b,0x8a,0x7d,0x3d,0x34,0x45,0x9f,0xb2,0xc2,0x68,0x43,0xa1,0x61,0x37,0x47,0x6c,0x2c,0x8a,0xcf,0x8a,0x45,0xfc,0xcf,0x32,0x74,0x46,0x1e,0x3f,0x48,0x50,0x2e,0x69,0xa8, 0x82,0x5e,0x3d,0x1d,0x3b,0x72,0xa9,0x6d,0x1b,0x31,0x2d,0x2e,0x02,0xf0,0x0f,0x2e,0x51,0x80,0x62,0x3d,0x66,0x4a,0x2a,0x2c,0x55,0x7b,0x4f,0x21,0x3f,0x36,0x2b,0x0d,0x8a,0xa3,0x01,0x64,0x12,0x25,0x39,0x27,0x2c,0x44,0x2f,0x18,0x14,0x25,0x35,0x21,0x35,0x49,0x2d,0x14,0xf9,0xfc,0x15,0x27,0x1e,0x12,0x12,0x1c,0x25,0x12,0x39,0x63, 0x2c,0x32,0x5c,0x03,0x3c,0x59,0xc0,0xb8,0xa4,0x7d,0x49,0x14,0x22,0x2d,0x18,0x3f,0x3c,0x1c,0x33,0x47,0x2b,0x30,0x4a,0x31,0x1a,0x10,0x1c,0x25,0x15,0x5f,0x01,0x0d,0xab,0xa9,0xf9,0x5d,0x0a,0x35,0x49,0x58,0x2d,0x50,0x38,0x69,0x51,0x34,0x03,0x48,0x66,0x26,0x42,0x1f,0x49,0x30,0x0f,0x5f,0x9b,0xd4,0xb1,0xc4,0xfe,0xe4,0x60,0x15, 0x24,0x1b,0x10,0x3f,0x6b,0x8e,0x9c,0xa1,0x4a,0x77,0xbb,0x85,0x4e,0x0a,0x2e,0x71,0x88,0xa3,0xfd,0xba,0x36,0x74,0x60,0x3f,0x25,0x47,0x68,0x43,0x48,0x7f,0x5f,0x36,0x10,0x1f,0x2c,0x1b,0xfe,0x29,0x02,0x7c,0x20,0x3e,0x30,0x1d,0x26,0x3f,0x51,0x2b,0x28,0x43,0x30,0x1a,0x31,0x47,0x52,0x15,0x0e,0x19,0x24,0x16,0x19,0x26,0x1a,0x0e, 0x36,0x35,0x27,0x36,0x00,0x02,0x00,0x30,0xfe,0x52,0x03,0x6a,0x05,0xe2,0x00,0x3c,0x00,0x4e,0x00,0x5d,0x40,0x32,0x01,0x02,0x07,0x1b,0x35,0x3b,0x4a,0x07,0x00,0x11,0x2b,0x25,0x3a,0x00,0x42,0xcb,0x11,0x00,0x4a,0x07,0x3d,0x02,0x35,0x1b,0x16,0x02,0x3a,0x00,0x47,0x48,0x0c,0x0c,0x3d,0x00,0x28,0x28,0x30,0x3d,0xc4,0x16,0x30,0xc0, 0x20,0x20,0x50,0x01,0x3b,0x3c,0x03,0x00,0x2f,0x17,0x32,0x11,0x39,0x2f,0xe1,0xd4,0xe1,0x10,0xc0,0x2f,0x11,0x12,0x39,0x2f,0xe1,0x10,0xc6,0x32,0x11,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x00,0x3f,0xed,0x2f,0xd6,0xd4,0xcd,0x11,0x12,0x17,0x39,0x31,0x30,0x33,0x13,0x13,0x36,0x37,0x36,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33, 0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x35,0x26,0x36,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x27,0x06,0x06,0x07,0x06,0x07,0x03,0x07,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x3e,0x03,0x30,0xfe,0x4c,0x11,0x13,0x11,0x28,0x16,0x26,0x4a,0x3a,0x23,0x20,0x3b,0x54, 0x34,0x30,0x47,0x2f,0x17,0x10,0x1d,0x26,0x16,0x2f,0x62,0x50,0x32,0x3e,0x6e,0x96,0x57,0x0b,0x0b,0x01,0x08,0x0c,0x25,0x51,0x43,0x2c,0x17,0x29,0x35,0x1e,0x23,0x47,0x1c,0x21,0x1e,0x64,0x62,0x01,0xcd,0x0e,0x19,0x22,0x14,0x11,0x21,0x19,0x0f,0x41,0x32,0x0e,0x19,0x12,0x0b,0x02,0x23,0xfe,0xe4,0x37,0x40,0x37,0x90,0x51,0x4b,0x8e, 0x8b,0x8a,0x47,0x3f,0x67,0x49,0x28,0x23,0x40,0x5b,0x38,0x22,0x69,0x85,0x99,0x52,0x54,0xad,0xbc,0xce,0x74,0x50,0x96,0x74,0x46,0x0c,0x09,0x06,0x10,0x03,0x09,0x3b,0x5a,0x78,0x47,0x56,0x9f,0x92,0x88,0x40,0x7d,0xe7,0x5b,0x6a,0x5d,0x01,0x50,0xf6,0x04,0xe1,0x30,0x41,0x28,0x11,0x13,0x29,0x41,0x2f,0x67,0xbf,0x60,0x3b,0x71,0x66, 0x56,0x00,0x00,0x04,0x00,0x26,0x00,0x00,0x04,0x8e,0x05,0x9a,0x00,0x1f,0x00,0x27,0x00,0x2d,0x00,0x33,0x00,0x81,0x40,0x4a,0x2c,0x12,0x24,0x0f,0x1c,0x92,0x1d,0x40,0x09,0x0d,0x48,0x1d,0x1d,0x03,0x18,0x23,0x0a,0x2f,0x07,0x00,0x92,0x00,0x01,0x10,0x01,0x20,0x01,0x03,0x01,0x01,0x03,0x2d,0x91,0x18,0x18,0x03,0x19,0x2e,0x91,0x03, 0x03,0x07,0x0a,0x0f,0x12,0x04,0x0c,0x22,0x25,0x2b,0x30,0x04,0x20,0x24,0x2d,0x2f,0x03,0x19,0x00,0x1c,0x1a,0x1e,0x02,0x1a,0x10,0x09,0x20,0x7d,0x0c,0x0c,0x35,0x19,0x7e,0x1a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0xc6,0x32,0x11,0x33,0x33,0x10,0xc6,0x32,0x11,0x17,0x33,0x11,0x17,0x33,0x11,0x17,0x33,0x31,0x00,0x3f,0xed,0x2f,0x12,0x39, 0x2f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x33,0x33,0x32,0x32,0x11,0x12,0x39,0x2f,0x2b,0xed,0x33,0x33,0x32,0x32,0x31,0x30,0x13,0x35,0x33,0x11,0x21,0x32,0x16,0x17,0x33,0x15,0x23,0x16,0x15,0x14,0x06,0x07,0x33,0x15,0x23,0x0e,0x03,0x23,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x05,0x34,0x27,0x21,0x15,0x21,0x36,0x36,0x01,0x32,0x36, 0x37,0x21,0x15,0x11,0x15,0x21,0x26,0x26,0x23,0x26,0x96,0x01,0x7c,0xa1,0xdb,0x2e,0xac,0x90,0x03,0x03,0x02,0x92,0xb7,0x1b,0x59,0x73,0x8d,0x50,0xaf,0xa8,0x96,0x96,0x02,0x95,0x03,0xfe,0x16,0x01,0xe8,0x02,0x03,0xfe,0xb9,0x67,0x87,0x26,0xfe,0x46,0x01,0xbe,0x23,0x7f,0x64,0x03,0xfd,0x8d,0x01,0x10,0x8b,0x85,0x8d,0x1b,0x1c,0x15, 0x28,0x14,0x8c,0x42,0x69,0x49,0x27,0xfe,0x32,0x02,0xe9,0x8c,0x88,0x3f,0x21,0x1e,0x88,0x11,0x24,0xfe,0xbc,0x45,0x3e,0x83,0x02,0x9c,0x78,0x39,0x3f,0x00,0x00,0x04,0x00,0xa2,0xff,0xdf,0x06,0x7d,0x05,0xbb,0x00,0x1b,0x00,0x33,0x00,0x42,0x00,0x4f,0x00,0x52,0x40,0x2d,0x34,0x4c,0x0f,0x44,0x1f,0x44,0x02,0x44,0x44,0x37,0x36,0x36, 0x28,0x43,0x4c,0x37,0x37,0x1c,0x28,0xcb,0x00,0xc7,0x1c,0xcb,0x0e,0x04,0x3d,0xbd,0x4a,0x4a,0x2d,0x44,0x35,0xc2,0x36,0x36,0x07,0x2d,0xc9,0x15,0x15,0x51,0x21,0xc9,0x07,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x31,0x00,0x3f,0xed,0xf4,0xed,0x11,0x39,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0x2f, 0x5d,0xed,0x31,0x30,0x05,0x22,0x2e,0x04,0x35,0x34,0x3e,0x04,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x04,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x04,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x03,0x11,0x23,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x03,0x90,0x67,0xbf, 0xa7,0x89,0x62,0x36,0x36,0x62,0x8a,0xa6,0xbf,0x67,0x67,0xbe,0xa7,0x89,0x62,0x36,0x36,0x62,0x89,0xa6,0xbf,0x67,0x88,0xf1,0xb4,0x69,0x30,0x56,0x79,0x94,0xa8,0x5b,0x88,0xf1,0xb4,0x68,0x30,0x56,0x79,0x93,0xa9,0xdd,0x83,0x01,0x1d,0x53,0x84,0x5b,0x30,0x29,0x59,0x8c,0x64,0x8a,0x81,0x48,0x5f,0x37,0x16,0x1a,0x3a,0x5a,0x41,0x21, 0x36,0x62,0x89,0xa7,0xbf,0x67,0x67,0xbf,0xa7,0x89,0x62,0x36,0x36,0x62,0x8a,0xa7,0xbf,0x66,0x66,0xbf,0xa7,0x8a,0x62,0x36,0x05,0x84,0x69,0xb4,0xf1,0x88,0x5b,0xa9,0x93,0x78,0x57,0x2f,0x68,0xb4,0xf1,0x88,0x5b,0xa8,0x93,0x79,0x57,0x30,0xfc,0xdb,0xfe,0xba,0x03,0xba,0x28,0x4d,0x71,0x4a,0x3a,0x74,0x5d,0x39,0x02,0x01,0xfe,0x71, 0x23,0x3a,0x49,0x25,0x2d,0x49,0x33,0x1b,0x00,0x03,0x00,0x60,0xff,0xe8,0x07,0x1a,0x05,0xec,0x00,0x1d,0x00,0x2b,0x00,0x39,0x00,0x41,0x40,0x24,0x11,0x00,0x36,0x95,0x16,0x10,0x22,0x95,0x0d,0x10,0x30,0x95,0x1c,0x16,0x28,0x95,0x07,0x16,0x03,0x12,0x2d,0x02,0x84,0x11,0x1e,0x03,0x03,0x0a,0x19,0x83,0x33,0x33,0x3b,0x25,0x83,0x0a, 0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x32,0x32,0x00,0x2f,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0x31,0x30,0x25,0x23,0x15,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x01,0x35,0x34,0x26,0x23,0x22,0x06, 0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x13,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x04,0x14,0x04,0xa4,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5,0xd3,0x60,0x04,0xa4,0x04,0x79,0xe9,0xc5,0xdf,0xfa,0xd9,0xcb,0xfe,0xf0,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0x55,0x51,0xa9,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f, 0x57,0x53,0x94,0x94,0xae,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x02,0x7a,0xfd,0x60,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0x01,0xd8,0xa6,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0x63,0x5e,0x01,0x0d,0x9e,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0x64,0x5e,0x00,0x00,0x03,0x00,0x60,0xfe,0x29,0x07,0x1a,0x04,0x18,0x00,0x1d,0x00,0x2b,0x00,0x39, 0x00,0x42,0x40,0x25,0x11,0x0f,0x36,0x95,0x16,0x10,0x22,0x95,0x0d,0x10,0x30,0x95,0x1c,0x16,0x28,0x95,0x07,0x16,0x03,0x1b,0x12,0x2d,0x02,0x84,0x11,0x1e,0x03,0x03,0x0a,0x19,0x83,0x33,0x33,0x3b,0x25,0x83,0x0a,0x2f,0xe1,0x12,0x39,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x33,0xe1,0x32,0x32,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x3f, 0xed,0x3f,0x31,0x30,0x25,0x23,0x11,0x23,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x35,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x01,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x13,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x04,0x14, 0x04,0xa4,0x04,0x72,0xee,0xc1,0xe7,0x01,0x00,0xd5,0xd3,0x60,0x04,0xa4,0x04,0x79,0xe9,0xc5,0xdf,0xfa,0xd9,0xcb,0xfe,0xf0,0xa4,0x7e,0x96,0xac,0xa5,0x8b,0x89,0x55,0x51,0xa9,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0x57,0x53,0x94,0xfd,0x95,0x02,0x85,0xc6,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x8e,0xb4,0xcc,0xfe,0xed,0xe7,0xfe,0xff, 0xfe,0xcb,0x01,0xd8,0xa6,0x7c,0xac,0xdc,0xc2,0xb1,0xcd,0x63,0x5e,0x01,0x0d,0x9e,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0x64,0x5e,0x00,0x01,0x00,0x16,0xff,0x6a,0x04,0xf0,0x06,0x30,0x00,0x03,0x00,0x18,0x40,0x0c,0x00,0x02,0xa0,0x03,0x01,0x0f,0x03,0x3f,0x03,0x02,0x03,0x02,0x00,0x2f,0x2f,0x5d,0x5d,0x01,0x2f,0xcd,0x31,0x30,0x01,0x01, 0x23,0x01,0x04,0xf0,0xfb,0xca,0xa4,0x04,0x36,0x06,0x30,0xf9,0x3a,0x06,0xc6,0x00,0xff,0xff,0x00,0x16,0xff,0x6a,0x05,0x12,0x06,0x30,0x02,0x26,0x00,0x24,0x00,0x00,0x00,0x06,0x07,0xe3,0x00,0x00,0xff,0xff,0x00,0x16,0xff,0x6a,0x04,0xf0,0x06,0x30,0x02,0x26,0x00,0x26,0x00,0x00,0x00,0x06,0x07,0xe3,0x00,0x00,0xff,0xff,0x00,0x21, 0xff,0x37,0x04,0x0b,0x04,0xd1,0x02,0x26,0x00,0x46,0x00,0x00,0x00,0x07,0x00,0xbc,0x01,0x59,0xff,0x37,0xff,0xff,0x00,0x12,0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x26,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,0xd9,0xff,0xd4,0xfd,0xf5,0xff,0xff,0xff,0xef,0xff,0x6a,0x04,0xc9,0x06,0x30,0x02,0x26,0x00,0x37,0x00,0x00,0x00,0x06,0x07,0xe3, 0xd9,0x00,0x00,0x01,0x00,0x68,0xfe,0x92,0x03,0x0f,0x04,0x18,0x00,0x3c,0x00,0x57,0x40,0x31,0x3c,0x3a,0x95,0x02,0x0d,0x30,0x17,0x26,0x04,0x1c,0x36,0x1f,0x21,0x95,0x1c,0x10,0x08,0x36,0x20,0x09,0x30,0x09,0x40,0x09,0x03,0x09,0x0b,0x95,0x36,0x16,0x3c,0x3c,0x36,0x09,0x1f,0x1f,0x30,0x26,0x83,0x17,0x17,0x09,0x30,0x83,0x0d,0x0d, 0x3e,0x06,0x09,0x2f,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x11,0x39,0x39,0x2f,0x00,0x3f,0xfd,0xc6,0x5d,0x11,0x39,0x3f,0xfd,0xc6,0x11,0x12,0x17,0x39,0x2f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x27,0x26,0x27,0x26,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33, 0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x06,0x06,0x07,0x06,0x07,0x16,0x17,0x16,0x33,0x32,0x37,0x02,0xc7,0x3a,0x5c,0x8c,0x46,0x3d,0x92,0x15,0x13,0x86,0xa1,0xd8,0x25,0x3f,0x55,0x31,0x44,0x67,0x45,0x23,0x42,0x6e,0x8d,0x4b,0x85,0x69,0x71,0x93,0x2e,0x4a,0x35,0x1d,0x1d,0x38,0x50, 0x33,0x44,0x6c,0x4c,0x29,0x43,0x70,0x49,0x40,0x44,0x27,0x16,0x30,0x3c,0x48,0x47,0xfe,0xb7,0x25,0xa4,0x90,0x4b,0x09,0x0b,0xb0,0x63,0x90,0x29,0x39,0x2c,0x23,0x13,0x1b,0x37,0x45,0x58,0x3b,0x48,0x6f,0x4b,0x26,0x2e,0xa6,0x4a,0x15,0x26,0x35,0x20,0x28,0x36,0x2a,0x22,0x14,0x1a,0x37,0x45,0x5a,0x3e,0x4c,0x70,0x4a,0x12,0x0f,0x03, 0x24,0x35,0x71,0x28,0x00,0x01,0x00,0x21,0xfe,0x92,0x03,0x70,0x04,0x00,0x00,0x13,0x00,0x30,0x40,0x19,0x13,0x11,0x95,0x02,0x0c,0x08,0x95,0x0a,0x0f,0x07,0x0d,0x96,0x06,0x13,0x09,0x08,0x09,0x0d,0x13,0x04,0x07,0x0c,0x0c,0x15,0x07,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x00,0x2f,0xed,0x39,0x3f,0xed,0x39,0x2f,0xfd,0xc6, 0x31,0x30,0x01,0x06,0x23,0x22,0x00,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x17,0x16,0x33,0x32,0x37,0x03,0x6a,0x3a,0x5c,0x96,0xfe,0xcf,0xb2,0x3a,0x02,0x5e,0xfd,0xdb,0x03,0x16,0xfd,0x97,0x85,0x81,0x88,0x46,0x48,0x47,0xfe,0xb7,0x25,0x01,0x6e,0x33,0x03,0x41,0x8c,0x2f,0xfc,0xad,0x2b,0x97,0x9e,0x28,0x00,0x00,0x01, 0x00,0x30,0x00,0x00,0x03,0xf6,0x06,0x02,0x00,0x19,0x00,0x29,0x40,0x14,0x13,0x08,0x10,0x01,0x0d,0x0b,0x95,0x10,0x01,0x00,0x84,0x01,0x01,0x0d,0x13,0x83,0x08,0x08,0x1b,0x0d,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0xed,0x00,0x3f,0xfd,0xc6,0x2f,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x11,0x34,0x36,0x37,0x36,0x36,0x35,0x34,0x26, 0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x04,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x02,0x47,0xa3,0x5d,0x88,0x82,0x45,0xc1,0xe1,0xd8,0xa6,0xa1,0xde,0x01,0x29,0x01,0x1e,0x61,0x9e,0x63,0x4d,0x01,0xee,0x87,0xa2,0x6c,0x69,0x6e,0x3e,0x5f,0x80,0x4c,0x97,0x40,0xc8,0x98,0x5b,0x9f,0x7b,0x4d,0x83,0x6f,0x00,0xff,0xff,0x00,0x6c,0x04,0xc2, 0x01,0x31,0x05,0x85,0x02,0x06,0x00,0xdb,0x00,0x00,0x00,0x01,0xff,0x2b,0xfe,0x52,0x00,0xd4,0xff,0xe6,0x00,0x0e,0x00,0x0c,0xb3,0x05,0x0b,0x0c,0x0b,0x2f,0xcd,0x00,0x2f,0xc4,0x31,0x30,0x17,0x07,0x17,0x07,0x27,0x07,0x27,0x37,0x27,0x37,0x17,0x27,0x33,0x07,0x37,0xd4,0x9e,0x6b,0x4f,0x53,0x52,0x4f,0x6a,0x9d,0x1f,0x94,0x0f,0x61, 0x0e,0x94,0xd7,0x23,0x7b,0x39,0x8c,0x8c,0x39,0x7b,0x23,0x5b,0x40,0xa2,0xa2,0x40,0x00,0x03,0xfe,0xbd,0xfe,0x5c,0x01,0x43,0xff,0xc8,0x00,0x1a,0x00,0x26,0x00,0x32,0x00,0x34,0x40,0x1d,0x0e,0x06,0xc3,0x40,0x27,0x0f,0x1b,0x1f,0x1b,0x2f,0x1b,0x03,0x1b,0x80,0x2d,0x21,0xc3,0x13,0x00,0x30,0xf1,0x11,0x2a,0x1e,0xf1,0x03,0x24,0xf1, 0x2a,0x2f,0xfd,0xd4,0xed,0x10,0xd4,0xed,0x00,0x2f,0x33,0xed,0x32,0x1a,0xdc,0x5d,0x32,0x1a,0xed,0x32,0x31,0x30,0x17,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x27,0x06,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x32,0x17,0x16,0x17,0x36,0x37,0x36,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x23,0x32,0x36, 0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x8f,0x4b,0x69,0x69,0x4b,0x4b,0x35,0x08,0x07,0x07,0x09,0x34,0x4b,0x4b,0x69,0x69,0x96,0x34,0x09,0x07,0x07,0x08,0x35,0x4b,0x2c,0x3f,0x3f,0x2c,0x2c,0x3e,0x3e,0xf2,0x2c,0x3f,0x3f,0x2c,0x2c,0x3e,0x3e,0x38,0x6b,0x4b,0x4b,0x6b,0x36,0x08,0x0a,0x0a,0x08,0x36,0x6b,0x4b,0x4b,0x6b,0x35, 0x09,0x09,0x09,0x09,0x35,0xfe,0xdd,0x40,0x2d,0x2c,0x40,0x40,0x2c,0x2d,0x40,0x40,0x2d,0x2c,0x40,0x40,0x2c,0x2d,0x40,0x00,0x00,0x01,0xff,0x60,0x04,0xba,0x00,0xa0,0x06,0x70,0x00,0x07,0x00,0x16,0x40,0x09,0x05,0x06,0xdb,0x40,0x01,0x03,0x07,0x80,0x03,0x2f,0x1a,0xcd,0x00,0x2f,0xc6,0x1a,0xfd,0xcd,0x31,0x30,0x13,0x23,0x37,0x23, 0x13,0x33,0x07,0x33,0x5a,0x64,0x2d,0xc3,0x46,0x64,0x2d,0xc3,0x04,0xba,0xac,0x01,0x0a,0xac,0xff,0xff,0xfc,0xe6,0xfe,0x52,0x03,0x1a,0xff,0xd0,0x02,0x07,0x07,0x5d,0x00,0x00,0xf8,0x90,0xff,0xff,0x00,0x21,0xfe,0x74,0x04,0x50,0x04,0x18,0x02,0x26,0x01,0xd0,0x00,0x00,0x01,0x07,0x00,0xd9,0xff,0xe3,0xfa,0x31,0x00,0x0f,0x40,0x09, 0x02,0x10,0x1c,0x20,0x1c,0x40,0x1c,0x03,0x1c,0x00,0x11,0x5d,0x35,0x00,0x00,0x01,0x00,0x68,0xff,0xe8,0x04,0x96,0x05,0xb2,0x00,0x15,0x00,0x2c,0x40,0x17,0x0b,0x0a,0x08,0x91,0x0d,0x04,0x15,0x20,0x00,0x01,0x00,0x02,0x91,0x13,0x13,0x10,0x7d,0x05,0x05,0x17,0x0a,0x0a,0x00,0x2f,0x32,0x11,0x12,0x39,0x2f,0xe1,0x00,0x3f,0xfd,0xc6, 0x5d,0x32,0x3f,0xfd,0xc6,0x32,0x31,0x30,0x37,0x16,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x27,0x68,0x9e,0xd8,0xe9,0x01,0x1f,0xfe,0xcd,0xf7,0xba,0x9a,0x86,0xcc,0x01,0x3e,0x01,0x9e,0xfe,0x90,0xfe,0xce,0xed,0x9f,0xdf,0x60,0x01,0x37,0x01,0x06,0x01,0x14,0x01,0x4a,0x56, 0xb3,0x3b,0xfe,0x58,0xfe,0xa8,0xfe,0xc0,0xfe,0x76,0x54,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x02,0x26,0x00,0x26,0x00,0x00,0x01,0x07,0x00,0xdb,0x02,0x34,0xfd,0xb0,0x00,0x15,0x40,0x0e,0x01,0x1f,0x1c,0x01,0x0f,0x1c,0x5f,0x1c,0xcf,0x1c,0xff,0x1c,0x04,0x1c,0x00,0x11,0x5d,0x71,0x35,0x00,0xff,0xff,0x00,0x68, 0xff,0xe8,0x04,0x96,0x05,0xb2,0x02,0x26,0x07,0xf2,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x23,0xfd,0xb0,0x00,0x15,0x40,0x0e,0x01,0x1f,0x1c,0x01,0x0f,0x1c,0x5f,0x1c,0xcf,0x1c,0xff,0x1c,0x04,0x1c,0x00,0x11,0x5d,0x71,0x35,0x00,0x00,0x01,0x00,0xbc,0xfe,0x80,0x03,0xa4,0x05,0x9a,0x00,0x09,0x00,0x26,0x40,0x13,0x01,0xee,0x08,0x03, 0x02,0x91,0x06,0x05,0x00,0x00,0x0b,0x07,0x03,0x7f,0x06,0x06,0x02,0x7e,0x07,0x2f,0xf1,0xc1,0x2f,0xed,0x11,0x12,0x39,0x2f,0x00,0x2f,0x2f,0xed,0x3f,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x21,0x03,0xa4,0xfd,0xc1,0x99,0x99,0xa9,0x02,0xe8,0x04,0xfe,0xfb,0x98,0xfd,0xea,0x01,0x80,0x05,0x9a,0x00,0x00,0x01, 0x00,0xa6,0xfe,0x8b,0x02,0xdf,0x04,0x00,0x00,0x09,0x00,0x26,0x40,0x13,0x01,0x95,0x08,0x0f,0x02,0x96,0x06,0x05,0x00,0x00,0x0b,0x07,0x03,0xed,0x06,0x06,0x02,0x84,0x07,0x2f,0xf1,0xc1,0x2f,0xed,0x11,0x12,0x39,0x2f,0x00,0x2f,0x2f,0xed,0x3f,0xed,0x31,0x30,0x01,0x21,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x21,0x02,0xdf,0xfe,0x6b, 0x8c,0x8c,0xa4,0x02,0x39,0x03,0x74,0xfd,0x0d,0xfe,0x0a,0x01,0x75,0x04,0x00,0x00,0xff,0xff,0xff,0xbb,0xff,0xe8,0x04,0x54,0x05,0xec,0x02,0x26,0x00,0x45,0x00,0x00,0x01,0x06,0x00,0xd8,0x98,0xc5,0x00,0x11,0x40,0x0b,0x02,0x10,0x2b,0x20,0x2b,0x70,0x2b,0xaf,0x2b,0x04,0x2b,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0x00,0x60,0xff,0xe8, 0x04,0xff,0x05,0xec,0x02,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x00,0xd8,0x02,0x5b,0xff,0xc5,0x00,0x11,0x40,0x0b,0x02,0x10,0x2b,0x20,0x2b,0x70,0x2b,0xaf,0x2b,0x04,0x2b,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0xff,0xf8,0x00,0x00,0x02,0xa0,0x06,0x02,0x02,0x26,0x00,0x49,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xd5,0xfc,0xb7,0x00,0x0a, 0xb4,0x01,0x10,0x22,0x01,0x22,0x00,0x11,0x5d,0x35,0x00,0x03,0xff,0xc0,0x00,0x00,0x07,0x34,0x04,0x18,0x00,0x2c,0x00,0x36,0x00,0x3f,0x00,0xa3,0x40,0x2b,0x15,0x3e,0x0c,0x09,0x11,0x07,0x04,0x09,0x2c,0x28,0x02,0x96,0x23,0x28,0x35,0x37,0x2d,0x09,0x96,0x28,0x3e,0x3e,0x0b,0x02,0x19,0x01,0x0c,0x04,0x1e,0x31,0x19,0x03,0x3a,0x95, 0x20,0x1b,0x10,0x16,0x0f,0x06,0x01,0x0b,0x27,0xb8,0x01,0x03,0x40,0x0f,0x40,0x28,0x28,0x22,0x2d,0x00,0x84,0x01,0x0e,0x06,0x06,0x0b,0x42,0x14,0x10,0xb8,0x01,0x03,0x40,0x1b,0x40,0x11,0x16,0x17,0x3e,0x03,0x0a,0x84,0x0b,0x37,0x1e,0x35,0x03,0x05,0x84,0x06,0x0f,0x06,0x01,0x0c,0x03,0x40,0x41,0x06,0x84,0x30,0x30,0x2b,0x01,0x5f, 0x5e,0x5d,0x10,0xe1,0x17,0x39,0x18,0x2f,0xe1,0x17,0x39,0xd6,0x1a,0xed,0x33,0x2b,0x01,0x18,0x10,0xf4,0xf1,0x39,0x39,0xc0,0x2f,0x1a,0xed,0x00,0x2f,0x33,0x33,0x3f,0x3f,0x33,0xed,0x17,0x32,0x5f,0x5e,0x5d,0x12,0x39,0x2f,0xc4,0xed,0xd4,0x39,0x39,0x11,0x39,0xfd,0x11,0x39,0x11,0x39,0x39,0xc4,0x11,0x39,0x11,0x39,0x31,0x30,0x21, 0x23,0x11,0x26,0x25,0x11,0x23,0x11,0x24,0x27,0x11,0x23,0x11,0x06,0x07,0x06,0x15,0x23,0x36,0x37,0x36,0x37,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x20,0x11,0x15,0x36,0x37,0x36,0x35,0x33,0x06,0x07,0x06,0x07,0x27,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x04,0x25,0x35,0x10,0x23,0x22,0x07,0x06,0x07,0x16,0x06, 0x54,0xa4,0xb3,0xfe,0xd2,0xa4,0xfe,0xd1,0xb2,0xa4,0x21,0x16,0x38,0x77,0x02,0x5a,0x35,0x55,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0x01,0x52,0x1c,0x14,0x39,0x77,0x02,0x5b,0x34,0x4f,0xa4,0x69,0x7c,0x69,0x93,0x01,0x32,0xfe,0x2a,0xe9,0x6c,0x46,0x35,0x0d,0xb4,0x01,0x5a,0x05,0x42,0xfe,0x5f,0x01,0xc6,0x42,0x06,0xfd,0xf2, 0x01,0xfb,0x0d,0x15,0x35,0x50,0x88,0x58,0x34,0x15,0x01,0x83,0xa2,0xba,0x75,0x5f,0xd4,0xfe,0x5f,0x8a,0x0c,0x13,0x36,0x50,0x86,0x59,0x33,0x16,0x6c,0x76,0xaa,0x98,0xc0,0x86,0x2a,0x43,0x68,0x1d,0x01,0x2e,0x5b,0x44,0x64,0x07,0x00,0x02,0xff,0xc0,0x00,0x00,0x04,0xdc,0x04,0x18,0x00,0x25,0x00,0x30,0x00,0x5f,0x40,0x1a,0x0e,0x06, 0x02,0x13,0x25,0x96,0x1c,0x21,0x2f,0x28,0x09,0x96,0x21,0x12,0x12,0x08,0x16,0x2b,0x95,0x18,0x10,0x13,0x0f,0x01,0x08,0x20,0xb8,0x01,0x03,0x40,0x0b,0x21,0x21,0x1c,0x28,0x00,0x84,0x01,0x01,0x32,0x08,0x0d,0xb8,0x01,0x03,0xb7,0x0e,0x13,0x14,0x2f,0x03,0x07,0x84,0x08,0x2f,0xe1,0x17,0x39,0xd6,0xed,0x11,0x12,0x39,0x2f,0xf1,0x39, 0x39,0xc0,0x2f,0xed,0x00,0x2f,0x33,0x3f,0x3f,0xed,0x32,0x12,0x39,0x2f,0xc4,0xed,0xd4,0x39,0x11,0x39,0xfd,0x11,0x39,0x39,0xc4,0x31,0x30,0x21,0x23,0x11,0x26,0x27,0x26,0x27,0x11,0x23,0x11,0x06,0x07,0x06,0x15,0x23,0x36,0x37,0x36,0x37,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x15,0x36,0x37,0x36,0x35,0x33,0x06,0x07,0x06, 0x07,0x25,0x16,0x17,0x35,0x10,0x23,0x22,0x07,0x06,0x07,0x16,0x03,0xf8,0xa4,0x6c,0x9a,0x9a,0x6a,0xa4,0x27,0x1a,0x2e,0x77,0x02,0x50,0x3b,0x59,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0x25,0x19,0x2f,0x77,0x02,0x51,0x3b,0x56,0xfe,0x59,0x9a,0x69,0xee,0x7b,0x51,0x3f,0x0e,0x6c,0x01,0x63,0x14,0x3d,0x3d,0x14,0xfd,0xfb,0x02,0x04,0x0d,0x1e, 0x35,0x50,0x88,0x58,0x41,0x11,0x01,0x7a,0xaa,0xc2,0xd9,0xcd,0x91,0x0e,0x1d,0x36,0x50,0x86,0x59,0x41,0x12,0xd1,0x3d,0x14,0x68,0x01,0x46,0x5d,0x49,0x67,0x14,0x00,0xff,0xff,0xff,0xbb,0xfe,0x29,0x04,0x54,0x04,0x18,0x02,0x26,0x00,0x53,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0x98,0xf9,0xf2,0x00,0x11,0x40,0x0b,0x02,0x20,0x2b,0x5f, 0x2b,0x70,0x2b,0xe0,0x2b,0x04,0x2b,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0xff,0xbb,0x00,0x00,0x02,0xbc,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0x98,0xfc,0xc8,0x00,0x11,0x40,0x0b,0x01,0x10,0x1e,0x20,0x1e,0x70,0x1e,0xaf,0x1e,0x04,0x1e,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0xff,0xa5,0x00,0x00,0x02,0xa2, 0x04,0x18,0x02,0x26,0x05,0x83,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0x82,0xfc,0xc8,0x00,0x11,0x40,0x0b,0x01,0x10,0x1e,0x20,0x1e,0x70,0x1e,0xaf,0x1e,0x04,0x1e,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0x00,0x27,0xff,0xe8,0x03,0xac,0x04,0x18,0x00,0x26,0x00,0x56,0x28,0x00,0x00,0x06,0x08,0x5f,0x00,0x00,0xff,0xff,0xff,0xef,0xff,0xea, 0x02,0x81,0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xcc,0xfc,0xc8,0x00,0x13,0x40,0x0d,0x01,0x10,0x1e,0x20,0x1e,0x70,0x1e,0x8f,0x1e,0xaf,0x1e,0x05,0x1e,0x00,0x11,0x5d,0x35,0x00,0xff,0xff,0x00,0x21,0x00,0x00,0x03,0x70,0x04,0x00,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0x5f,0xfc,0xc8, 0x00,0x13,0x40,0x0d,0x01,0x10,0x17,0x20,0x17,0x70,0x17,0x8f,0x17,0xaf,0x17,0x05,0x17,0x00,0x11,0x5d,0x35,0x00,0x00,0x02,0x00,0xa6,0xfe,0x1e,0x04,0x56,0x04,0x18,0x00,0x18,0x00,0x25,0x00,0x44,0x40,0x26,0x0a,0x23,0x95,0x0d,0x0d,0x02,0x1d,0x05,0x40,0x0b,0x0f,0x48,0x05,0x07,0x95,0x02,0x10,0x16,0x1d,0x95,0x18,0x13,0x1c,0x05, 0x05,0x09,0x10,0x83,0x20,0x20,0x27,0x09,0x84,0x19,0x84,0x17,0x84,0x18,0x2f,0xe1,0xe1,0xe1,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0x00,0x3f,0xc4,0xed,0x32,0x3f,0xfd,0xc6,0x2b,0x11,0x12,0x39,0x2f,0xed,0x32,0x31,0x30,0x13,0x10,0x21,0x32,0x17,0x15,0x26,0x23,0x20,0x11,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x27, 0x23,0x15,0x23,0x13,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0xa6,0x02,0x1c,0xbe,0x8e,0xad,0x9d,0xfe,0x86,0x04,0x75,0xeb,0xbf,0xe9,0xfb,0xda,0xcf,0x64,0x04,0xa4,0xa4,0xa5,0x7b,0x98,0xac,0xa5,0x88,0x8a,0xad,0x01,0xe4,0x02,0x34,0x48,0xa4,0x60,0xfe,0x6e,0x70,0xc4,0xfe,0xef,0xe6,0xfe,0xfb,0xfe,0xcc,0xa6, 0x8e,0x02,0x31,0x97,0x7a,0xae,0xdd,0xc7,0xab,0xcd,0xc4,0x00,0x00,0x01,0x00,0x7a,0x01,0xf6,0x03,0x37,0x05,0x9a,0x00,0x0b,0x00,0x3b,0x40,0x23,0x03,0x54,0x3f,0x08,0x4f,0x08,0x5f,0x08,0x8f,0x08,0x9f,0x08,0xaf,0x08,0x06,0x08,0x08,0x06,0x01,0x05,0x05,0x0c,0x0a,0x06,0x03,0x00,0x50,0x09,0x01,0x01,0x0d,0x08,0x04,0x50,0x05,0x2f, 0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x00,0x3f,0x33,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x03,0x37,0x6d,0xfe,0x1d,0x6d,0x6d,0x01,0xe3,0x6d,0x01,0xf6,0x01,0xa9,0xfe,0x57,0x03,0xa4,0xfe,0x67,0x01,0x99,0x00,0x00,0x02,0x00,0x60,0xfe,0x21,0x04,0x3f, 0x04,0x00,0x00,0x26,0x00,0x3c,0x00,0x54,0x40,0x30,0x38,0x0e,0x00,0x07,0x00,0x24,0x10,0x24,0x40,0x24,0x50,0x24,0x04,0x24,0x24,0x07,0x2c,0x95,0x1a,0x1b,0x09,0x06,0x95,0x07,0x0f,0x0e,0x84,0x05,0x08,0x38,0x24,0x31,0x00,0x08,0x07,0x07,0x08,0x00,0x03,0x1f,0x15,0x83,0x31,0x31,0x3e,0x27,0x83,0x1f,0x2f,0xe1,0x12,0x39,0x2f,0xe1, 0x11,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x39,0x12,0x39,0xe1,0x00,0x3f,0xed,0x39,0x3f,0xed,0x11,0x39,0x2f,0x5d,0x12,0x39,0x39,0x33,0x31,0x30,0x01,0x34,0x3e,0x02,0x37,0x21,0x35,0x21,0x15,0x0e,0x03,0x15,0x14,0x1e,0x04,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x03,0x14,0x1e,0x02,0x33,0x32, 0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x27,0x0e,0x03,0x01,0xd9,0x1d,0x33,0x45,0x29,0xfe,0x40,0x03,0x2d,0x58,0x90,0x66,0x37,0x42,0x64,0x74,0x64,0x42,0x4f,0x8b,0xbf,0x70,0x5b,0xaa,0x83,0x4e,0x37,0x6a,0x9a,0x63,0x14,0x11,0xd1,0x31,0x54,0x70,0x3f,0x48,0x7f,0x5e,0x36,0x15,0x3a,0x67,0x51,0x21,0x19,0x6e,0x84,0x46,0x16,0x02, 0x73,0x28,0x4d,0x43,0x37,0x12,0x8c,0x47,0x28,0x4f,0x4f,0x53,0x2d,0x32,0x4e,0x4c,0x53,0x6e,0x94,0x66,0x72,0xab,0x74,0x3a,0x37,0x6e,0xa5,0x6e,0x59,0x9b,0x85,0x70,0x2e,0x21,0x41,0xfd,0x87,0x4c,0x71,0x4b,0x25,0x27,0x4e,0x77,0x50,0x34,0x50,0x50,0x5c,0x3f,0x1a,0x17,0x36,0x6e,0x6e,0x6b,0xff,0xff,0x00,0x16,0xff,0xea,0x06,0xae, 0x05,0xec,0x00,0x26,0x00,0x57,0x00,0x00,0x00,0x27,0x00,0x4b,0x02,0xb6,0x00,0x00,0x00,0x06,0x08,0x06,0x00,0x00,0x00,0x01,0x00,0x16,0x00,0x00,0x05,0x18,0x05,0x9a,0x00,0x03,0x00,0x09,0xb2,0x03,0x03,0x02,0x00,0x2f,0x3f,0x31,0x30,0x01,0x01,0x23,0x01,0x05,0x18,0xfb,0xa2,0xa4,0x04,0x5e,0x05,0x9a,0xfa,0x66,0x05,0x9a,0xff,0xff, 0x00,0x4a,0x00,0x00,0x02,0x46,0x04,0x00,0x02,0x26,0x05,0x6f,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0x0c,0xfd,0x17,0x00,0x15,0x40,0x0e,0x01,0x0c,0x2f,0x0c,0x4f,0x0c,0x02,0xaf,0x0c,0xcf,0x0c,0xff,0x0c,0x03,0x00,0x5d,0x71,0x11,0x35,0x00,0xff,0xff,0xff,0xfb,0xff,0xf4,0x02,0x08,0x04,0x00,0x02,0x26,0x01,0xc9,0x00,0x00,0x01,0x07, 0x00,0xd9,0xff,0xbd,0xfd,0x17,0x00,0x15,0x40,0x0e,0x01,0x2f,0x0e,0x4f,0x0e,0x02,0xaf,0x0e,0xcf,0x0e,0xff,0x0e,0x03,0x0e,0x00,0x11,0x5d,0x71,0x35,0x00,0x00,0x03,0x00,0x22,0xfe,0x29,0x04,0xd5,0x04,0x18,0x00,0x19,0x00,0x23,0x00,0x2c,0x00,0x4b,0x40,0x29,0x14,0x21,0x05,0xe2,0x11,0x2a,0x06,0x06,0x1c,0x0a,0x26,0x95,0x0d,0x10, 0x08,0x0f,0x00,0x1c,0x95,0x18,0x16,0x03,0x1b,0x13,0x13,0x11,0x14,0x83,0x2b,0x20,0x20,0x2e,0x07,0x0a,0x2a,0x21,0x04,0x02,0x84,0x05,0x03,0x2f,0xc6,0xe1,0x17,0x39,0x12,0x39,0x2f,0x33,0xf1,0x32,0xc1,0x2f,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x31,0x30,0x25,0x23,0x11,0x23,0x11, 0x23,0x35,0x33,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x16,0x17,0x33,0x15,0x23,0x06,0x07,0x06,0x23,0x22,0x27,0x16,0x33,0x32,0x37,0x36,0x37,0x21,0x15,0x14,0x01,0x26,0x23,0x22,0x07,0x06,0x07,0x21,0x26,0x01,0x4e,0x04,0xa4,0x84,0x84,0xa4,0x04,0x79,0xe9,0xc6,0x6f,0x65,0x09,0x82,0x84,0x0f,0x6b,0x7d,0xd9,0xc7,0x1e,0x53,0x7f, 0x95,0x54,0x45,0x0d,0xfd,0xa1,0x02,0x13,0x4f,0x87,0x8f,0x57,0x51,0x06,0x02,0x61,0x08,0x94,0xfd,0x95,0x03,0xaf,0x6d,0x01,0xbb,0xb4,0xcc,0x8a,0x7d,0xcc,0x6d,0xd1,0x85,0x9a,0xe2,0x58,0x72,0x5c,0x98,0x36,0x7f,0x02,0x0a,0x61,0x64,0x5d,0x88,0x91,0x00,0x02,0x00,0x22,0xff,0xe8,0x04,0x24,0x04,0x00,0x00,0x12,0x00,0x19,0x00,0x3b, 0x40,0x1e,0x01,0x17,0x08,0xe2,0x11,0x0d,0x09,0x09,0x0f,0x0b,0x0f,0x13,0x95,0x04,0x16,0x12,0x12,0x01,0x16,0x10,0x84,0x0f,0x0f,0x1b,0x09,0x17,0x07,0x0c,0x84,0x0b,0x2f,0xe1,0x39,0x39,0xc6,0x12,0x39,0x2f,0xf1,0x39,0x39,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0x33,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x31,0x30,0x01,0x23,0x15,0x10,0x21, 0x20,0x11,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x01,0x32,0x11,0x35,0x21,0x15,0x10,0x04,0x24,0x6e,0xfe,0x64,0xfe,0x76,0x6e,0x6e,0xa1,0x01,0xe3,0xa2,0x6e,0xfd,0xff,0xf1,0xfe,0x1d,0x01,0xd8,0x32,0xfe,0x42,0x01,0xb2,0x3e,0x6d,0x01,0xbb,0xfe,0x45,0x01,0xbb,0xfe,0x45,0xfe,0x2d,0x01,0x2a,0x3c,0x36,0xfe, 0xd0,0x00,0x00,0x02,0x00,0x14,0xff,0xe8,0x04,0xae,0x04,0x00,0x00,0x1e,0x00,0x27,0x00,0x5e,0x40,0x31,0x12,0x26,0x1a,0xe2,0x0f,0x06,0x1d,0x1d,0x21,0x04,0x09,0x0d,0x03,0x01,0x95,0x0a,0x02,0x0f,0x21,0x95,0x16,0x16,0x0d,0x12,0x09,0x00,0x1a,0x04,0x09,0x04,0x12,0x1a,0x11,0x11,0x0c,0x0f,0x12,0x84,0x07,0x25,0x25,0x29,0x06,0x26, 0x84,0x01,0x1d,0x07,0x1a,0x2f,0xcd,0x33,0x33,0xe1,0x32,0x12,0x39,0x2f,0x33,0xf1,0x32,0x32,0xc1,0x2f,0x11,0x12,0x39,0x39,0x2f,0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xed,0x3f,0x33,0xed,0x17,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x31,0x30,0x01,0x23,0x35,0x21,0x15,0x06,0x07,0x21,0x26,0x27,0x35,0x21,0x15,0x23,0x16,0x17, 0x33,0x15,0x23,0x06,0x07,0x06,0x23,0x22,0x27,0x26,0x27,0x23,0x35,0x33,0x36,0x13,0x16,0x33,0x32,0x37,0x36,0x37,0x21,0x16,0x01,0x1c,0xbc,0x01,0x7f,0xba,0x1c,0x02,0xb0,0x1c,0xb9,0x01,0x7e,0xb8,0x95,0x1c,0x53,0x4c,0x04,0x86,0x8a,0xf2,0xed,0x88,0x85,0x02,0x4c,0x54,0x1e,0xdc,0x5f,0xa1,0xa6,0x5b,0x54,0x06,0xfd,0x47,0x07,0x03, 0x74,0x8c,0x8e,0x55,0xd8,0xd8,0x55,0x8e,0x8c,0x6f,0xc0,0x6d,0xda,0x89,0x8d,0x8b,0x89,0xdc,0x6d,0xbe,0xfd,0xd8,0x69,0x66,0x5e,0xa2,0x9c,0x00,0xff,0xff,0x00,0xa6,0xfe,0x96,0x04,0x54,0x05,0xec,0x02,0x26,0x00,0x45,0x00,0x00,0x00,0x07,0x08,0x5b,0x03,0x05,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x96,0x04,0xa9,0x05,0xec,0x02,0x26, 0x00,0x47,0x00,0x00,0x01,0x07,0x08,0x5d,0x03,0xd2,0x00,0x00,0x00,0x09,0xb3,0x02,0x2a,0x2a,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x35,0xfe,0x96,0x02,0xa0,0x06,0x02,0x02,0x26,0x00,0x49,0x00,0x00,0x01,0x07,0x08,0x5d,0x01,0x49,0x00,0x00,0x00,0x09,0xb3,0x01,0x21,0x21,0x09,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x60, 0xfe,0x1e,0x05,0xfc,0x04,0x18,0x02,0x26,0x00,0x4a,0x00,0x00,0x00,0x27,0x08,0x5d,0x05,0x25,0x00,0x00,0x01,0x07,0x08,0x60,0x03,0xc2,0xfb,0x74,0x00,0x1b,0x40,0x0c,0x02,0x32,0x32,0x33,0x02,0x26,0x26,0x36,0x03,0x35,0x35,0x18,0x10,0x3c,0x12,0x34,0x10,0x3c,0x12,0x34,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0xa6,0xfe,0x96, 0x03,0xf9,0x05,0xec,0x02,0x26,0x00,0x4e,0x00,0x00,0x01,0x07,0x08,0x5d,0x03,0x22,0x00,0x00,0x00,0x09,0xb3,0x01,0x0d,0x0d,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x5c,0xfe,0x96,0x01,0xe3,0x05,0xec,0x02,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x08,0x5d,0x01,0x0c,0x00,0x00,0x00,0x09,0xb3,0x01,0x10,0x10,0x00,0x10,0x3c,0x12, 0x34,0x00,0xff,0xff,0x00,0xa6,0xfe,0x96,0x06,0xed,0x04,0x18,0x02,0x26,0x00,0x50,0x00,0x00,0x01,0x07,0x08,0x5d,0x06,0x16,0x00,0x00,0x00,0x09,0xb3,0x01,0x2c,0x2c,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0xa6,0xfe,0x96,0x04,0x91,0x04,0x18,0x02,0x26,0x00,0x51,0x00,0x00,0x01,0x07,0x08,0x5d,0x03,0xba,0x00,0x00,0x00,0x09, 0xb3,0x01,0x1f,0x1f,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0xa6,0xfe,0x29,0x04,0x54,0x04,0x18,0x02,0x26,0x00,0x53,0x00,0x00,0x00,0x07,0x08,0x5b,0x03,0x05,0x00,0x00,0xff,0xff,0x00,0x5c,0xfe,0x96,0x02,0xbc,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x01,0x07,0x08,0x5d,0x01,0x0c,0x00,0x00,0x00,0x09,0xb3,0x01,0x1d,0x1d, 0x06,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x68,0xfe,0x96,0x03,0xad,0x04,0x18,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x27,0x08,0x5d,0x02,0xd6,0x00,0x00,0x01,0x07,0x08,0x60,0x01,0x73,0xfb,0x27,0x00,0x11,0xb7,0x02,0x3d,0x42,0x2d,0x01,0x30,0x30,0x3f,0x10,0x3c,0x12,0x34,0x00,0x10,0xf4,0x34,0x00,0xff,0xff,0xff,0x92,0xfe,0x1e, 0x03,0x4b,0x06,0x02,0x00,0x26,0x05,0x88,0x00,0x00,0x00,0x27,0x08,0x5d,0x02,0x74,0x00,0x00,0x01,0x07,0x08,0x60,0x01,0x11,0xfb,0x74,0x00,0x1b,0x40,0x0c,0x01,0x22,0x22,0x24,0x01,0x17,0x17,0x26,0x02,0x25,0x25,0x04,0x10,0x3c,0x12,0x34,0x10,0x3c,0x12,0x34,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x0e,0xfe,0x96,0x04,0x06, 0x04,0x00,0x02,0x26,0x00,0x59,0x00,0x00,0x00,0x27,0x08,0x5d,0x03,0x2f,0x00,0x00,0x01,0x07,0x08,0x60,0x01,0xcc,0xfb,0x3f,0x00,0x12,0xb7,0x02,0x1a,0x1a,0x02,0x01,0x0c,0x0c,0x1c,0x10,0x3c,0x12,0x34,0x00,0x10,0x3c,0x12,0x34,0xff,0xff,0x00,0x1a,0xfe,0x96,0x03,0x92,0x04,0x00,0x02,0x26,0x00,0x5b,0x00,0x00,0x01,0x07,0x08,0x5d, 0x02,0xbb,0x00,0x00,0x00,0x09,0xb3,0x01,0x14,0x14,0x02,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x21,0xfe,0x96,0x03,0x70,0x04,0x00,0x02,0x26,0x00,0x5d,0x00,0x00,0x01,0x07,0x08,0x5d,0x02,0x93,0x00,0x00,0x00,0x09,0xb3,0x01,0x0a,0x0a,0x03,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x5a,0xfe,0x96,0x04,0x71,0x04,0x18,0x02,0x26, 0x00,0x44,0x00,0x00,0x01,0x07,0x08,0x5e,0x03,0xc1,0x00,0x00,0x00,0x09,0xb3,0x02,0x20,0x20,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x60,0xfe,0x96,0x04,0xfe,0x04,0x18,0x02,0x26,0x05,0x57,0x00,0x00,0x01,0x07,0x08,0x5e,0x04,0x4e,0x00,0x00,0x00,0x09,0xb3,0x02,0x1e,0x1e,0x00,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x60, 0xfe,0x96,0x05,0x21,0x06,0x02,0x02,0x26,0x05,0x5d,0x00,0x00,0x01,0x07,0x08,0x5e,0x04,0x4e,0x00,0x00,0x00,0x09,0xb3,0x02,0x27,0x27,0x05,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x60,0xfe,0xb4,0x04,0x84,0x04,0x18,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x08,0x5e,0x03,0xd4,0x00,0x1e,0x00,0x09,0xb3,0x02,0x1a,0x1a,0x06,0x10, 0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x52,0xfe,0x96,0x04,0x29,0x04,0x19,0x02,0x26,0x01,0x31,0x00,0x00,0x01,0x07,0x08,0x5e,0x03,0x79,0x00,0x00,0x00,0x09,0xb3,0x01,0x26,0x26,0x25,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x50,0xfe,0x96,0x03,0x3b,0x04,0x19,0x02,0x26,0x02,0x0e,0x00,0x00,0x01,0x07,0x08,0x5e,0x01,0x27,0x00,0x00, 0x00,0x09,0xb3,0x01,0x2d,0x2d,0x01,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x52,0xff,0xe8,0x05,0xe0,0x04,0x18,0x00,0x26,0x02,0xce,0x00,0x00,0x00,0x27,0x08,0x5e,0x05,0x30,0x01,0xf4,0x01,0x07,0x08,0x60,0x02,0x70,0xfc,0xdd,0x00,0x12,0xb7,0x02,0x1a,0x1a,0x00,0x03,0x29,0x29,0x00,0x00,0x10,0x3c,0x12,0x34,0x10,0x3c,0x12,0x34, 0xff,0xff,0x00,0x90,0xfe,0x96,0x02,0xd1,0x05,0xd9,0x02,0x26,0x00,0x4c,0x00,0x00,0x01,0x07,0x08,0x5e,0x02,0x21,0x00,0x00,0x00,0x09,0xb3,0x02,0x1c,0x1c,0x0f,0x10,0x3c,0x12,0x34,0x00,0xff,0xff,0x00,0x5a,0xfe,0x96,0x03,0x5a,0x04,0x18,0x02,0x26,0x05,0x5a,0x00,0x00,0x01,0x07,0x08,0x5e,0x01,0x33,0x00,0x00,0x00,0x09,0xb3,0x01, 0x21,0x21,0x01,0x10,0x3c,0x12,0x34,0x00,0x00,0x01,0xff,0x92,0xfe,0x1d,0x02,0x68,0x06,0x02,0x00,0x1f,0x00,0x28,0x40,0x15,0x17,0x95,0x09,0x0c,0x95,0x11,0x1c,0x02,0x95,0x1d,0x00,0x00,0x00,0x05,0x84,0x19,0x0e,0x09,0x83,0x15,0x19,0x2f,0xd6,0xe1,0xc4,0x10,0xf1,0xc2,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x2f,0xed,0x31,0x30,0x01,0x26, 0x23,0x22,0x15,0x11,0x14,0x07,0x06,0x07,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x11,0x16,0x33,0x32,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x02,0x68,0x32,0x3c,0xaa,0x5d,0x4c,0x7d,0x7f,0x3b,0x35,0x34,0x3d,0x7d,0x99,0x32,0x3c,0xac,0xb8,0x8e,0x4c,0x2a,0x05,0x5c,0x1b,0xdf,0xfc,0x71,0xa2,0x60,0x4d,0x0e,0x67,0x9d, 0x1e,0x92,0x17,0xa0,0x8b,0x01,0x06,0x1a,0xdf,0x03,0x8d,0xa4,0xbe,0x12,0xff,0xff,0x00,0x90,0xfe,0x96,0x04,0xd0,0x04,0x00,0x02,0x26,0x00,0x58,0x00,0x00,0x01,0x07,0x08,0x5e,0x04,0x20,0x00,0x00,0x00,0x09,0xb3,0x01,0x13,0x13,0x00,0x10,0x3c,0x12,0x34,0x00,0x00,0x01,0xff,0xdd,0xfe,0x21,0x03,0x68,0x04,0x00,0x00,0x23,0x00,0x53, 0x40,0x2f,0x09,0x96,0x11,0x11,0x0e,0x10,0x01,0x01,0x01,0x17,0x95,0x0f,0x03,0x1f,0x03,0x2f,0x03,0x03,0x03,0x10,0x0d,0x95,0x0e,0x0f,0x1d,0xec,0x21,0x1c,0x11,0x0c,0x0b,0x10,0x0b,0x10,0x0b,0x16,0x0e,0x14,0x83,0x06,0x06,0x25,0x0e,0x1f,0x19,0x83,0x01,0x2f,0xed,0xc4,0x2f,0x12,0x39,0x2f,0xed,0x11,0x12,0x39,0x39,0x2f,0x2f,0x12, 0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x39,0x2f,0x5d,0xed,0xc6,0x5d,0x12,0x39,0x2f,0xed,0x31,0x30,0x07,0x11,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x04,0x23,0x22,0x27,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x23,0xa5,0xb1,0xae,0xdf,0xde,0xce,0x52,0x01, 0x63,0xfd,0xdb,0x03,0x2d,0xfe,0x95,0xbc,0xea,0xfe,0xbc,0xf7,0x5f,0x58,0x7e,0x3c,0x34,0x34,0x3c,0x7f,0x98,0xb7,0x01,0x01,0x68,0x84,0x72,0x81,0x74,0x33,0x01,0x74,0x8c,0x33,0xfe,0x81,0x1a,0xb8,0xa0,0xae,0xd7,0x17,0x25,0x9d,0x1f,0x93,0x17,0x9f,0x00,0x02,0x00,0x66,0x02,0x89,0x02,0x88,0x04,0xcf,0x00,0x10,0x00,0x1b,0x00,0x48, 0xb3,0x0e,0x02,0x05,0x13,0x41,0x0d,0x01,0x0d,0x00,0x0b,0x01,0x0b,0x00,0x10,0x01,0x0a,0x00,0x00,0x01,0x08,0x00,0x17,0x01,0x0d,0x00,0x05,0x01,0x09,0x00,0x08,0x01,0x0c,0x40,0x09,0x11,0x0e,0x01,0x15,0x15,0x1d,0x0f,0x02,0x1b,0xb9,0x01,0x0c,0x00,0x10,0x2f,0xed,0x32,0x32,0x12,0x39,0x2f,0x11,0x33,0x33,0xed,0x00,0x3f,0xed,0x3f, 0x3f,0x3f,0xed,0x12,0x39,0x39,0x31,0x30,0x13,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x23,0x15,0x23,0x36,0x16,0x33,0x32,0x35,0x34,0x23,0x22,0x06,0x15,0x15,0x66,0x7e,0x03,0x35,0x70,0x6e,0x8e,0x81,0x68,0x76,0x42,0x03,0x7e,0x7e,0x52,0x42,0x8e,0x90,0x40,0x52,0x04,0xbe,0x43,0x54,0xab,0x84,0x80,0x97, 0x61,0x50,0xb4,0x5e,0xb6,0xc2,0x5c,0x46,0x2e,0x00,0x00,0x01,0x00,0x3e,0x02,0x89,0x01,0xec,0x04,0xd1,0x00,0x15,0x00,0x32,0xb1,0x0b,0x0d,0xba,0x01,0x0d,0x00,0x08,0x01,0x09,0xb6,0xc0,0x15,0xd0,0x15,0x02,0x15,0x13,0xba,0x01,0x0d,0x00,0x02,0x01,0x0b,0xb3,0x0b,0x15,0x17,0x10,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xed,0x10,0xc6,0x32, 0x00,0x3f,0xfd,0xc6,0x5d,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x01,0xec,0x42,0x5b,0x7b,0x96,0xa2,0x87,0x4b,0x3a,0x3a,0x42,0x50,0x60,0x5b,0x51,0x44,0x3c,0x02,0xb2,0x29,0x9b,0x7c,0x8a,0xa7,0x24,0x6c,0x2c,0x6c,0x58,0x56,0x66, 0x31,0x00,0x00,0x02,0x00,0x3d,0x02,0x48,0x02,0x10,0x04,0xd1,0x00,0x1d,0x00,0x26,0x00,0x5b,0xb5,0x05,0x00,0x0a,0x1c,0x0d,0x0f,0xba,0x01,0x0d,0x00,0x0a,0x01,0x09,0x40,0x0d,0x25,0xbf,0x16,0x01,0x00,0x16,0x10,0x16,0x20,0x16,0x03,0x16,0x20,0xbb,0x01,0x0d,0x00,0x03,0x00,0x1c,0x01,0x0b,0x40,0x0f,0x03,0x05,0x00,0x03,0x03,0x19, 0x07,0x1e,0x14,0x12,0x23,0x19,0x0d,0x28,0x12,0xb9,0x01,0x0c,0x00,0x07,0x2f,0xed,0x10,0xd4,0xd4,0xcd,0x11,0x39,0x39,0x11,0x12,0x17,0x39,0x2f,0x00,0x3f,0xc4,0xfd,0xd4,0x5d,0x5d,0xcd,0x3f,0xfd,0xc6,0x11,0x12,0x39,0x39,0x31,0x30,0x13,0x06,0x07,0x23,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15, 0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0xdb,0x10,0x03,0x59,0x07,0x1c,0x55,0xa2,0x88,0x4b,0x3a,0x39,0x40,0x4f,0x64,0x21,0x4d,0x58,0x3d,0x4d,0x6d,0x54,0x45,0x0d,0x2d,0x24,0x1e,0x2f,0x3c,0x36,0x02,0x9e,0x27,0x2f,0x49,0x3d,0x4e,0x84,0x8a,0xa7,0x24,0x6c,0x2c,0x6d, 0x59,0x4c,0x2a,0x4d,0x42,0x32,0x42,0x3f,0x71,0x13,0x0f,0x12,0x20,0x00,0x00,0x02,0x00,0x3e,0x02,0x8a,0x02,0x7f,0x05,0xd4,0x00,0x1c,0x00,0x27,0x00,0x62,0x40,0x10,0x16,0x14,0x17,0x02,0x1c,0x01,0x06,0x15,0x00,0x15,0x00,0x15,0x1a,0x06,0x09,0x1d,0xbe,0x01,0x0d,0x00,0x0f,0x01,0x09,0x00,0x23,0x01,0x0d,0x00,0x09,0x01,0x0b,0x40, 0x10,0x01,0x1c,0x01,0x02,0x03,0x06,0x16,0x17,0x14,0x11,0x03,0x26,0x19,0x19,0x0c,0x06,0xb8,0x01,0x0c,0xb3,0x26,0x26,0x29,0x20,0xb9,0x01,0x0c,0x00,0x0c,0x2f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xc6,0x12,0x17,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0xc4,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x31,0x30, 0x01,0x17,0x07,0x16,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x37,0x26,0x27,0x07,0x27,0x37,0x26,0x27,0x33,0x16,0x17,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x02,0x38,0x21,0x8a,0x22,0x22,0x6c,0x9d,0x86,0x86,0x98,0x9d,0x86,0x32,0x2c,0x02,0x28,0x2e,0xb6,0x1e,0x95,0x43,0x4f,0xa4, 0x2a,0x2b,0x30,0x4d,0x58,0x56,0x4d,0x49,0x54,0x05,0xd4,0x47,0x37,0x26,0x2f,0x94,0xb8,0x83,0xa8,0x99,0x83,0x85,0xa5,0x16,0x02,0x40,0x32,0x48,0x49,0x3b,0x38,0x2e,0x17,0x26,0xfe,0xd1,0x64,0x57,0x53,0x62,0x64,0x53,0xb9,0x00,0x00,0x01,0x00,0x42,0x02,0x89,0x01,0xdf,0x04,0xcf,0x00,0x1e,0x00,0x55,0xb1,0x1d,0x0d,0xb8,0x01,0x0d, 0x40,0x09,0x0e,0x0e,0x18,0x08,0xb0,0x15,0x01,0x15,0x13,0xbf,0x01,0x0d,0x00,0x18,0x01,0x09,0x00,0x06,0x00,0x08,0x01,0x0d,0x00,0x03,0x01,0x0b,0xb2,0x16,0x0e,0x1b,0xb8,0x01,0x0c,0xb6,0x11,0x0e,0x16,0x11,0x03,0x06,0x01,0xb8,0x01,0x0c,0xb3,0x0a,0x0a,0x20,0x06,0x2f,0x12,0x39,0x2f,0xed,0x12,0x17,0x39,0x2f,0xed,0x2f,0x2f,0x00, 0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x71,0x11,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x00,0x15,0x14,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x01,0xdf,0xfb,0x59,0x49,0x3e,0x55,0x87,0x9e,0x32,0x30,0x8c,0x71,0x49,0x3e,0x40,0x4d,0x6d, 0x81,0x67,0x03,0x9c,0x6f,0xa4,0x1b,0x64,0x1c,0x49,0x4c,0x63,0x47,0x41,0x1c,0x68,0x17,0x51,0x49,0x5a,0x1f,0x04,0x00,0x01,0x00,0x0a,0x02,0x9a,0x01,0x83,0x05,0xd3,0x00,0x14,0x00,0x33,0xb9,0x00,0x02,0x01,0x0d,0xb2,0x12,0x08,0x0c,0xbd,0x01,0x0d,0x00,0x05,0x00,0x0d,0x01,0x08,0x00,0x0a,0x01,0x0a,0x40,0x09,0x06,0x06,0x00,0x05, 0x09,0xcd,0x0e,0x0c,0x0a,0x2f,0xc6,0x33,0xfd,0x32,0xc4,0x39,0x2f,0x00,0x3f,0x3f,0x33,0xed,0x32,0xd4,0xed,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x01,0x83,0x1b,0x22,0x60,0x82,0x82,0x80,0x5c,0x5c,0x79,0x62,0x2a,0x18,0x05,0x59,0x0f,0x61,0x49,0x6a, 0xfe,0x46,0x01,0xba,0x6a,0x4d,0x62,0x66,0x0a,0x00,0x00,0x01,0xff,0xdd,0x01,0x94,0x01,0x56,0x04,0xbe,0x00,0x14,0x00,0x48,0x40,0x0b,0x0e,0x0c,0x0a,0xcd,0x09,0x06,0x06,0x00,0x05,0x09,0x09,0xba,0x01,0x08,0x00,0x02,0x01,0x0d,0x40,0x13,0x0f,0x12,0x1f,0x12,0x02,0x2f,0x12,0x3f,0x12,0x9f,0x12,0xaf,0x12,0xbf,0x12,0x05,0x12,0x0b, 0x08,0xbb,0x01,0x0d,0x00,0x0e,0x00,0x05,0x01,0x0a,0x00,0x3f,0x33,0xed,0x32,0xd4,0x5d,0x71,0xed,0x3f,0x01,0x2f,0x33,0xc4,0x39,0x2f,0x10,0xfd,0xc6,0x33,0x31,0x30,0x03,0x16,0x33,0x32,0x35,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x14,0x06,0x23,0x22,0x27,0x23,0x1b,0x22,0x60,0x82,0x82,0x80,0x5c,0x5c,0x79,0x62, 0x2a,0x18,0x02,0x0e,0x0f,0x61,0x58,0x6a,0x01,0x9c,0xfe,0x64,0x6a,0x5c,0x62,0x66,0x0a,0x00,0xff,0xff,0x00,0x3e,0x01,0x94,0x02,0x60,0x04,0xcf,0x02,0x06,0x07,0xaf,0x00,0x00,0x00,0x01,0x00,0x5c,0x01,0xa4,0x02,0x46,0x04,0xbe,0x00,0x11,0x00,0x30,0x41,0x0a,0x00,0x0c,0x01,0x0d,0x00,0x01,0x00,0x05,0x01,0x0b,0x00,0x10,0x00,0x08, 0x01,0x08,0x00,0x11,0x01,0x0c,0xb4,0x01,0x10,0x10,0x13,0x09,0xb9,0x01,0x0c,0x00,0x08,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x00,0x3f,0x33,0x3f,0xc6,0xed,0x31,0x30,0x01,0x23,0x11,0x23,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x02,0x46,0x80,0x02,0x3b,0x79,0xb4,0x7f,0x6d,0x39,0x45,0x80,0x01,0xa4, 0x01,0x4c,0x67,0xe7,0x01,0x4e,0xfe,0xce,0x98,0x53,0x40,0x01,0x37,0x00,0x00,0x02,0x00,0x0f,0x02,0x9a,0x01,0x3f,0x05,0xc4,0x00,0x0b,0x00,0x13,0x00,0x48,0x40,0x19,0x01,0x05,0x0a,0x1f,0x06,0x01,0x06,0x40,0x0c,0x10,0x48,0x06,0x06,0x08,0x03,0x0c,0x0f,0x10,0x1f,0x10,0x2f,0x10,0x03,0x10,0x08,0xba,0x01,0x08,0x00,0x03,0x01,0x0a, 0xb3,0x0b,0x12,0x0a,0x02,0xb8,0x01,0x0c,0xb3,0x0e,0x06,0x07,0x03,0x2f,0xc4,0xc4,0xc4,0xfd,0x32,0xc4,0xc4,0x00,0x3f,0x3f,0xd4,0x5d,0xcd,0x11,0x12,0x39,0x2f,0x2b,0x71,0x33,0xcd,0x32,0x31,0x30,0x01,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x03,0x22,0x35,0x34,0x33,0x32,0x15,0x14,0x01,0x3f,0x57,0x82,0x57,0x57, 0x82,0x57,0x99,0x4e,0x50,0x4e,0x03,0x91,0xf7,0xf7,0x56,0xd7,0xd7,0x01,0x46,0x4c,0x4b,0x4b,0x4c,0x00,0x00,0x01,0x00,0x66,0x02,0x8b,0x01,0x72,0x04,0xbe,0x00,0x0b,0x00,0x1f,0x41,0x0a,0x00,0x05,0x01,0x08,0x00,0x09,0x01,0x0d,0x00,0x02,0x01,0x0b,0x00,0x0b,0x00,0x06,0x01,0x0c,0x00,0x05,0x2f,0xfd,0xc6,0x00,0x3f,0xed,0x3f,0x31, 0x30,0x01,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x01,0x72,0x25,0x3c,0xab,0x82,0x50,0x22,0x18,0x02,0x9b,0x10,0xb5,0x01,0x7e,0xfe,0x8a,0x52,0x12,0x00,0x01,0x00,0x11,0x02,0x9a,0x01,0x51,0x04,0xbe,0x00,0x0b,0x00,0x2e,0xb1,0x0b,0x07,0xbf,0x01,0x0d,0x00,0x08,0x01,0x08,0x00,0x01,0x00,0x04,0x01,0x0d,0x00,0x03, 0x01,0x0a,0xb2,0x0a,0x01,0x00,0xb8,0x01,0x0c,0xb2,0x07,0x04,0x05,0x2f,0xcd,0x32,0xfd,0xcd,0x32,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x31,0x30,0x13,0x33,0x15,0x21,0x35,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0xf2,0x5f,0xfe,0xc0,0x5f,0x5f,0x01,0x40,0x5f,0x02,0xf0,0x56,0x56,0x01,0x78,0x56,0x56,0x00,0x00,0x01,0x00,0x11,0x02,0x9a, 0x01,0x51,0x04,0xbe,0x00,0x13,0x00,0x44,0x40,0x09,0x01,0x09,0xcb,0x12,0x0a,0x0a,0x06,0x11,0x0d,0xbf,0x01,0x0d,0x00,0x0e,0x01,0x08,0x00,0x02,0x00,0x06,0x01,0x0d,0x00,0x05,0x01,0x0a,0xb4,0x00,0x0f,0x03,0x12,0x02,0xb8,0x01,0x0c,0xb4,0x0e,0x0a,0x06,0x0b,0x07,0x2f,0x33,0xcd,0x32,0x32,0xfd,0x32,0xcd,0x32,0x32,0x00,0x3f,0xed, 0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x23,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x21,0x15,0x23,0x15,0x33,0x01,0x49,0x57,0x5f,0xfe,0xc0,0x5f,0x57,0x57,0x5f,0x01,0x40,0x5f,0x57,0x03,0x91,0xa1,0x56,0x56,0xa1,0x56,0x81,0x56,0x56,0x81,0x00,0x00,0x03,0xff,0x87,0x01,0x94, 0x01,0x6d,0x05,0xc4,0x00,0x11,0x00,0x19,0x00,0x21,0x00,0x51,0x40,0x1f,0x02,0x00,0x14,0x0f,0x0c,0x00,0x0a,0x18,0x00,0x18,0x40,0x04,0x50,0x04,0x02,0x2f,0x04,0x3f,0x04,0x02,0x04,0x1a,0x0f,0x1e,0x1f,0x1e,0x2f,0x1e,0x03,0x1e,0x0d,0xb8,0x01,0x0a,0xb3,0x11,0x20,0x02,0x0e,0xb8,0x01,0x0c,0xb5,0x1c,0x0d,0x16,0x07,0x12,0x0d,0x2f, 0x33,0xd4,0xcd,0x10,0xc4,0xfd,0x32,0xc4,0xc6,0x00,0x3f,0xd4,0x5d,0xcd,0x2f,0x5d,0x5d,0xcd,0xc4,0x10,0xd4,0x11,0x39,0x39,0xcd,0x11,0x39,0x31,0x30,0x01,0x26,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x11,0x33,0x11,0x16,0x17,0x25,0x26,0x23,0x22,0x15,0x14,0x33,0x32,0x13,0x22,0x35,0x34,0x33,0x32,0x15,0x14,0x01, 0x6d,0x45,0x47,0x23,0xb1,0x3a,0x4c,0x65,0x52,0x15,0x13,0x82,0x44,0x41,0xfe,0xf9,0x14,0x14,0x58,0x32,0x4b,0x43,0x4e,0x50,0x4e,0x01,0xcf,0x39,0x1c,0x90,0x42,0x33,0x3b,0x4f,0x02,0x02,0x2d,0xfd,0xbb,0x18,0x2e,0x0b,0x03,0x33,0x27,0x03,0x46,0x4c,0x4b,0x4b,0x4c,0x00,0x00,0x01,0x00,0x66,0x01,0x98,0x01,0x72,0x05,0xc4,0x00,0x0b, 0x00,0x1b,0xbb,0x00,0x05,0x01,0x07,0x00,0x09,0x01,0x0d,0xb2,0x02,0x0b,0x06,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xfd,0xc6,0x00,0x2f,0xed,0x3f,0x31,0x30,0x01,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x01,0x72,0x25,0x3c,0xab,0x82,0x50,0x22,0x18,0x01,0xa8,0x10,0xb5,0x03,0x77,0xfc,0x91,0x52,0x12,0x00,0x01,0x00,0x31, 0x01,0xcb,0x01,0x3d,0x05,0xc4,0x00,0x0e,0x00,0x38,0xbb,0x00,0x00,0x01,0x07,0x00,0x0b,0x01,0x0d,0xb3,0x50,0x06,0x01,0x06,0xb8,0xff,0xc0,0xb5,0x09,0x0c,0x48,0x06,0x02,0x0e,0xbf,0x01,0x0a,0x00,0x09,0x00,0x03,0x01,0x0c,0x00,0x0d,0x00,0x01,0x01,0x0c,0x00,0x00,0x2f,0xfd,0xd5,0xfd,0xc4,0x00,0x3f,0xd5,0xd4,0x2b,0x71,0xed,0x3f, 0x31,0x30,0x13,0x33,0x11,0x33,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x23,0x66,0x80,0x57,0x64,0x63,0x25,0x20,0x1d,0x23,0x59,0x0a,0x6e,0x05,0xc4,0xfc,0xf3,0x6f,0x7d,0x0b,0x61,0x10,0x73,0x00,0x00,0x01,0x00,0x66,0x02,0x96,0x01,0xb4,0x04,0xc4,0x00,0x05,0x00,0x20,0xbb,0x00,0x02,0x01,0x06,0x00,0x04,0x01,0x0d,0xb5, 0x01,0xff,0x00,0x00,0x07,0x04,0xb9,0x01,0x0c,0x00,0x01,0x2f,0xed,0x12,0x39,0x2f,0x00,0x3f,0xed,0x3f,0x31,0x30,0x01,0x21,0x11,0x33,0x13,0x33,0x01,0xb3,0xfe,0xb3,0x7f,0x01,0xce,0x02,0x96,0x02,0x2e,0xfe,0x3c,0x00,0x00,0x01,0x00,0x66,0x01,0x98,0x03,0x9a,0x04,0xcf,0x00,0x25,0x00,0x65,0xb9,0x00,0x24,0x01,0x0d,0x40,0x09,0x1f, 0x1d,0x00,0x08,0x13,0x18,0x05,0x16,0x10,0xba,0x01,0x0a,0x00,0x11,0x01,0x08,0xb2,0x1a,0x03,0x0b,0xba,0x01,0x0d,0x00,0x16,0x01,0x09,0xb3,0x18,0x07,0x13,0x1d,0xb8,0x01,0x0c,0x40,0x0a,0x40,0x22,0x00,0x0e,0x08,0x10,0x08,0x42,0x13,0x0f,0xbb,0x01,0x0c,0x00,0x10,0x00,0x07,0x01,0x0c,0xb3,0x08,0x08,0x27,0x26,0x11,0x12,0x39,0x2f, 0xed,0x2f,0xed,0x32,0x2b,0x01,0x18,0x10,0xf4,0xc6,0x1a,0xed,0x11,0x12,0x39,0x00,0x3f,0xed,0x39,0x39,0x3f,0x3f,0x12,0x17,0x39,0xd4,0xed,0x31,0x30,0x01,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x15,0x11,0x02,0x23,0x22,0x27,0x35, 0x16,0x33,0x32,0x03,0x1a,0x68,0x31,0x41,0x80,0x68,0x32,0x40,0x80,0x7e,0x02,0x38,0x72,0x77,0x28,0x3d,0x7c,0xb2,0x01,0xd9,0x2b,0x25,0x22,0x23,0x65,0x02,0x9a,0x01,0x3b,0x8f,0x54,0x3f,0xfe,0xc9,0x01,0x3f,0x8b,0x52,0x45,0xfe,0xcd,0x02,0x24,0x52,0x63,0x6f,0x6f,0xe3,0xfe,0xba,0xfe,0xf2,0x10,0x68,0x14,0x00,0x00,0x01,0x00,0x60, 0x01,0xa4,0x03,0x94,0x04,0xbe,0x00,0x1d,0x00,0x56,0xb4,0x07,0x18,0x02,0x03,0x10,0xb8,0x01,0x0d,0xb2,0x05,0x01,0x09,0xb8,0x01,0x0b,0xb2,0x1c,0x14,0x0c,0xb8,0x01,0x08,0xb3,0x07,0x01,0x14,0x1d,0xb8,0x01,0x0c,0x40,0x09,0x40,0x01,0x1c,0x0e,0x14,0x0c,0x14,0x42,0x0d,0xbb,0x01,0x0c,0x00,0x0c,0x00,0x15,0x01,0x0c,0xb3,0x14,0x14, 0x1f,0x1e,0x11,0x12,0x39,0x2f,0xed,0x2f,0xed,0x2b,0x01,0x18,0x10,0xf4,0x32,0x1a,0xed,0x11,0x12,0x39,0x00,0x3f,0x33,0x33,0x3f,0xc6,0x33,0xed,0x17,0x32,0x31,0x30,0x01,0x23,0x11,0x23,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0x94, 0x7e,0x02,0x38,0x72,0x77,0x28,0x3d,0x7c,0xb2,0x7f,0x69,0x31,0x41,0x80,0x68,0x32,0x40,0x80,0x01,0xa4,0x01,0x48,0x63,0x6f,0x6f,0xe3,0x01,0x52,0xfe,0xc5,0x8f,0x54,0x3f,0x01,0x37,0xfe,0xc1,0x8b,0x52,0x46,0x01,0x32,0x00,0x01,0xff,0xbc,0x01,0x98,0x02,0x50,0x04,0xcf,0x00,0x19,0x00,0x3e,0xb1,0x0c,0x16,0xbe,0x01,0x0d,0x00,0x0f, 0x01,0x09,0x00,0x0a,0x01,0x08,0x00,0x07,0x01,0x0d,0xb3,0x02,0x00,0x09,0x13,0xba,0x01,0x0a,0x00,0x12,0x01,0x0c,0xb4,0x13,0x13,0x1b,0x0b,0x00,0xb8,0x01,0x0c,0xb1,0x05,0x09,0x2f,0xc6,0xed,0x32,0x12,0x39,0x2f,0xed,0x00,0x3f,0x33,0x33,0xd4,0xed,0x3f,0x3f,0xed,0x32,0x31,0x30,0x13,0x10,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35, 0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x06,0x15,0xe6,0xda,0x2b,0x25,0x22,0x23,0x65,0x80,0x02,0x3b,0x79,0xb4,0x7f,0x6d,0x39,0x45,0x02,0xa6,0xfe,0xf2,0x10,0x68,0x14,0x9e,0x02,0x24,0x56,0x67,0xe7,0xfe,0xb2,0x01,0x33,0x97,0x54,0x3f,0x00,0x01,0x00,0x66,0x01,0x98,0x02,0xfa,0x04,0xcf,0x00,0x19, 0x00,0x3f,0xb1,0x14,0x0c,0xbe,0x01,0x0d,0x00,0x17,0x01,0x09,0x00,0x12,0x01,0x08,0x00,0x02,0x01,0x0d,0xb3,0x07,0x00,0x09,0x11,0xbb,0x01,0x0a,0x00,0x04,0x00,0x00,0x01,0x0c,0xb4,0x09,0x09,0x1b,0x13,0x10,0xb9,0x01,0x0c,0x00,0x11,0x2f,0xed,0x32,0x12,0x39,0x2f,0xfd,0xc6,0x00,0x3f,0x33,0x33,0xd4,0xed,0x3f,0x3f,0xed,0x32,0x31, 0x30,0x01,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x11,0x11,0x34,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0x65,0x23,0x22,0x25,0x2b,0xd9,0x6d,0x39,0x45,0x80,0x80,0x02,0x3b,0x79,0xb4,0x02,0x9a,0x9e,0x14,0x68,0x10,0x01,0x0e,0x01,0x27,0x97,0x54,0x3f,0xfe,0xc9,0x02,0x24,0x56,0x67,0xe7, 0x00,0x01,0x00,0x66,0x02,0x9a,0x02,0x6a,0x04,0xbe,0x00,0x13,0x00,0x26,0xbd,0x00,0x0a,0x01,0x08,0x00,0x09,0x01,0x0a,0x00,0x00,0x01,0x0c,0xb5,0x01,0x11,0x11,0x15,0x0b,0x08,0xb9,0x01,0x0c,0x00,0x09,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x00,0x3f,0x3f,0x31,0x30,0x01,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33, 0x13,0x16,0x17,0x33,0x26,0x35,0x11,0x33,0x02,0x6a,0x7f,0xea,0x14,0x07,0x02,0x02,0x80,0x84,0xe5,0x12,0x09,0x02,0x04,0x82,0x02,0x9a,0x01,0x4d,0x1c,0x0d,0x1d,0x2a,0xfe,0xd1,0x02,0x24,0xfe,0xbc,0x18,0x12,0x1c,0x22,0x01,0x30,0x00,0x03,0x00,0x3e,0x02,0x89,0x02,0x7f,0x04,0xcf,0x00,0x0b,0x00,0x14,0x00,0x1d,0x00,0x3f,0xb9,0x00, 0x13,0x01,0x0d,0xb3,0x19,0x19,0x0e,0x15,0xbe,0x01,0x0d,0x00,0x06,0x01,0x09,0x00,0x0e,0x01,0x0d,0x00,0x00,0x01,0x0b,0xb3,0x1a,0x19,0x13,0x09,0xb8,0x01,0x0c,0xb3,0x12,0x12,0x1f,0x13,0xb9,0x01,0x0c,0x00,0x03,0x2f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x26, 0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x16,0x33,0x32,0x37,0x36,0x37,0x21,0x16,0x13,0x22,0x07,0x06,0x07,0x21,0x26,0x27,0x26,0x01,0x58,0x80,0x9a,0xa2,0x84,0x80,0x9b,0xa3,0xf2,0x2c,0x48,0x49,0x2b,0x21,0x08,0xfe,0xc5,0x08,0x96,0x49,0x2c,0x1d,0x0a,0x01,0x38,0x0a,0x1e,0x2b,0x02,0x89,0x9e,0x7f,0x87,0xa2,0x9f,0x7e, 0x88,0xa1,0x97,0x2c,0x2c,0x21,0x40,0x40,0x01,0x23,0x2c,0x1e,0x36,0x37,0x1e,0x2b,0x00,0x03,0x00,0x3e,0x01,0xa4,0x02,0xb1,0x05,0xc4,0x00,0x15,0x00,0x1e,0x00,0x27,0x00,0x54,0xb1,0x1c,0x26,0xb8,0x01,0x0d,0xb2,0x0c,0x0a,0x09,0xbb,0x01,0x09,0x00,0x1d,0x00,0x25,0x01,0x0d,0xb5,0x14,0x40,0x00,0x01,0x00,0x01,0xb8,0x01,0x0b,0xb2, 0x0c,0x1d,0x15,0xb8,0x01,0x0c,0xb5,0x09,0x25,0x00,0x00,0x05,0x10,0xb8,0x01,0x0c,0xb3,0x18,0x18,0x29,0x21,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x00,0x3f,0xcd,0x5d,0x33,0xed,0x32,0x3f,0xcd,0x33,0xed,0x32,0x31,0x30,0x01,0x35,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37, 0x35,0x33,0x15,0x16,0x17,0x16,0x15,0x14,0x07,0x06,0x07,0x15,0x13,0x36,0x35,0x34,0x27,0x26,0x27,0x11,0x36,0x01,0x06,0x15,0x14,0x17,0x16,0x17,0x11,0x06,0x01,0x36,0x6e,0x3d,0x4d,0x51,0x3d,0x6a,0x82,0x6e,0x3d,0x4e,0x52,0x3e,0x69,0x4c,0x2c,0x2c,0x1b,0x31,0x31,0xff,0x00,0x2b,0x2c,0x1b,0x31,0x31,0x01,0xa4,0xe8,0x0d,0x3f,0x4f, 0x7f,0x87,0x51,0x3d,0x0f,0xfa,0xf8,0x0d,0x40,0x4f,0x7e,0x88,0x51,0x3d,0x0f,0xe9,0x01,0x81,0x31,0x56,0x58,0x30,0x1e,0x0b,0xfe,0x9d,0x0c,0x01,0x2d,0x31,0x56,0x56,0x31,0x1f,0x0c,0x01,0x63,0x0b,0x00,0x01,0x00,0x42,0x01,0xe2,0x01,0xa1,0x04,0xd1,0x00,0x2b,0x00,0x4f,0xb1,0x03,0x08,0xb8,0xff,0xc0,0x40,0x0b,0x0c,0x12,0x48,0x08, 0x10,0x27,0x16,0x21,0x04,0x19,0x0e,0xbe,0x01,0x0d,0x00,0x2a,0x01,0x0b,0x00,0x1e,0x01,0x0d,0x00,0x19,0x01,0x09,0xb7,0x1b,0x21,0xcd,0x16,0x1b,0x16,0x0c,0x27,0xb8,0x01,0x0c,0xb5,0x10,0x10,0x2d,0x05,0x01,0x0c,0x2f,0xcd,0xc4,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0xed,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0xd4,0x2b, 0xcd,0x31,0x30,0x13,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x97,0x4a,0x21,0x21,0x24,0x29,0x45,0x4f,0x3f,0x41,0x60,0x2b,0x3c,0x47,0x31,0x71,0x5a, 0x44,0x36,0x31,0x3e,0x31,0x27,0x24,0x3d,0x48,0x37,0x6c,0x5f,0x24,0x02,0x92,0x12,0x53,0x13,0x4d,0x11,0x4e,0x47,0xa7,0x36,0x3b,0x20,0x29,0x1d,0x24,0x4c,0x37,0x45,0x5c,0x19,0x6f,0x29,0x23,0x18,0x21,0x27,0x1d,0x23,0x4e,0x36,0x47,0x5b,0x00,0x01,0xff,0xc9,0x01,0x94,0x01,0x83,0x05,0xd3,0x00,0x15,0x00,0x2d,0xbc,0x00,0x02,0x01, 0x0d,0x00,0x13,0x00,0x0d,0x01,0x0d,0x40,0x0d,0x40,0x08,0x50,0x08,0x02,0x2f,0x08,0x3f,0x08,0x02,0x08,0x01,0x05,0xb8,0x01,0x0c,0xb1,0x0b,0x0f,0x2f,0xc6,0xfd,0xc6,0x00,0x2f,0x5d,0x5d,0xed,0x2f,0xed,0x31,0x30,0x01,0x26,0x23,0x22,0x15,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x01, 0x83,0x1b,0x22,0x60,0x79,0x62,0x2a,0x18,0x1b,0x22,0x60,0x79,0x62,0x2a,0x18,0x05,0x59,0x0f,0x61,0xfd,0x55,0x62,0x66,0x0a,0x70,0x0f,0x61,0x02,0xab,0x62,0x66,0x0a,0x00,0x01,0x00,0x0a,0x01,0xe2,0x01,0x68,0x05,0x62,0x00,0x1d,0x00,0x53,0xb1,0x08,0x03,0xb8,0xff,0xc0,0xb6,0x0c,0x11,0x48,0x03,0x0c,0x1d,0x1b,0xbb,0x01,0x0d,0x00, 0x00,0x00,0x0c,0x01,0x0b,0xb4,0x14,0x15,0x18,0x15,0x0f,0xba,0x01,0x0d,0x00,0x12,0x01,0x08,0x40,0x0a,0x06,0x0a,0x17,0x1d,0x1d,0x1f,0x0f,0x18,0x0f,0x15,0xb8,0x01,0x0c,0xb1,0x11,0x12,0x2f,0xcd,0xed,0x39,0x39,0x11,0x12,0x39,0x2f,0xc4,0xcd,0xc4,0x00,0x3f,0xed,0x39,0x39,0x10,0xcd,0x3f,0x33,0xfd,0xc6,0x10,0xd4,0x2b,0xcd,0x31, 0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0x23,0x22,0x35,0x11,0x23,0x35,0x33,0x35,0x37,0x15,0x33,0x15,0x23,0x15,0x14,0x33,0x32,0x37,0x01,0x68,0x4f,0x45,0x29,0x24,0x21,0x21,0x4a,0x0d,0xa0,0x5c,0x5c,0x80,0x82,0x82,0x49,0x1e,0x1b,0x02,0x77,0x47,0x4e,0x11,0x4d,0x13,0x53,0x0e,0xbe,0x01,0x08,0x6a,0x80, 0x24,0xa4,0x6a,0xfe,0x5e,0x10,0x00,0x02,0x00,0x05,0x02,0x89,0x02,0x9d,0x04,0xbe,0x00,0x15,0x00,0x1d,0x00,0x59,0xb4,0x1b,0x1a,0x01,0x03,0x0a,0xb8,0x01,0x0d,0x40,0x09,0x14,0x10,0x5f,0x0d,0x01,0x0d,0x0d,0x12,0x0e,0xbf,0x01,0x08,0x00,0x04,0x00,0x16,0x01,0x0d,0x00,0x07,0x01,0x0b,0x00,0x03,0x01,0x0a,0xb5,0x15,0x1a,0x03,0x01, 0x03,0x13,0xb8,0x01,0x0c,0xb5,0x12,0x12,0x1f,0x1c,0x0a,0x0f,0xb8,0x01,0x0c,0xb1,0x0c,0x0e,0x2f,0xc6,0xed,0x39,0x39,0x12,0x39,0x2f,0xfd,0x17,0x39,0xc6,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x33,0x39,0x2f,0x71,0x33,0x33,0xed,0x17,0x32,0x31,0x30,0x01,0x23,0x15,0x23,0x35,0x23,0x06,0x23,0x22,0x35,0x35,0x23,0x35,0x33,0x35,0x33,0x15, 0x33,0x35,0x33,0x15,0x33,0x05,0x32,0x36,0x35,0x35,0x23,0x15,0x14,0x02,0x9d,0x57,0x80,0x02,0x3b,0x79,0xb4,0x57,0x57,0x7f,0xeb,0x80,0x57,0xfe,0xab,0x39,0x45,0xeb,0x03,0x91,0xf7,0x56,0x67,0xe7,0x21,0x56,0xd7,0xd7,0xd7,0xd7,0xf3,0x53,0x40,0x0a,0x05,0x98,0x00,0x01,0x00,0x3e,0x02,0x89,0x02,0x7f,0x04,0xbe,0x00,0x1b,0x00,0x4f, 0xb4,0x04,0x0e,0x12,0x03,0x01,0xbf,0x01,0x0d,0x00,0x0f,0x00,0x02,0x01,0x08,0x00,0x09,0x01,0x0d,0x00,0x17,0x01,0x0b,0x40,0x0c,0x12,0x14,0x0f,0x00,0x1a,0x03,0x0f,0x03,0x0c,0x06,0x10,0x14,0xb8,0x01,0x0c,0xb3,0x0c,0x0c,0x1d,0x06,0xb8,0x01,0x0c,0xb1,0x02,0x1a,0x2f,0xc4,0xed,0x12,0x39,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x39,0x2f, 0x12,0x39,0x2f,0x12,0x39,0x00,0x3f,0xed,0x3f,0x33,0xed,0x17,0x32,0x31,0x30,0x13,0x23,0x35,0x33,0x15,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x35,0x33,0x15,0x23,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0xad,0x6f,0xfa,0x7a,0x56,0x4b,0x4c,0x53,0x7a,0xfb,0x6e,0x6e,0x9b,0x89,0x84,0x99,0x04,0x54,0x6a,0x5b,0x31, 0x83,0x5f,0x5c,0x59,0x62,0x83,0x31,0x5b,0x6a,0x41,0x74,0x7c,0x9a,0x97,0x7b,0x75,0x00,0x01,0x00,0x5c,0x02,0x89,0x02,0x46,0x04,0xbe,0x00,0x0d,0x00,0x29,0xb1,0x0c,0x05,0xbe,0x01,0x08,0x00,0x09,0x01,0x0d,0x00,0x02,0x01,0x0b,0x00,0x0d,0x01,0x0c,0xb3,0x0c,0x0c,0x0f,0x06,0xb9,0x01,0x0c,0x00,0x05,0x2f,0xed,0x12,0x39,0x2f,0xed, 0x00,0x3f,0xed,0x3f,0x33,0x31,0x30,0x01,0x14,0x23,0x22,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x35,0x11,0x33,0x02,0x46,0xfb,0xef,0x7f,0x76,0x75,0x80,0x03,0x79,0xf0,0xea,0x01,0x4b,0xfe,0xcf,0x99,0x95,0x01,0x35,0x00,0x00,0x01,0x00,0x5c,0x02,0x89,0x02,0x55,0x04,0xcf,0x00,0x17,0x00,0x33,0x41,0x0c,0x00,0x0a,0x01,0x0d,0x00,0x0f, 0x00,0x00,0x01,0x08,0x00,0x04,0x01,0x0d,0x00,0x15,0x01,0x0b,0x00,0x0d,0x00,0x12,0x01,0x0c,0xb3,0x07,0x07,0x19,0x01,0xb9,0x01,0x0c,0x00,0x00,0x2f,0xed,0x12,0x39,0x2f,0xed,0xc4,0x00,0x3f,0xed,0x3f,0xd4,0xed,0x31,0x30,0x13,0x33,0x11,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x23,0x22,0x35,0x5c,0x7f,0x73,0x4d,0x39,0x1e,0x24,0x21,0x1e,0x23,0x2c,0x5e,0x55,0x86,0x89,0xea,0x04,0xbe,0xfe,0xc6,0x90,0x6b,0x56,0x63,0x4c,0x0f,0x6c,0x0e,0x99,0x7e,0x8a,0xa5,0xf3,0x00,0x01,0x00,0x0b,0x02,0x9a,0x02,0x36,0x04,0xbe,0x00,0x0b,0x00,0x17,0xbb,0x00,0x00,0x01,0x0a,0x00,0x01,0x01,0x08,0xb3,0x03,0x03,0x0d,0x00, 0x2f,0x11,0x39,0x2f,0x00,0x3f,0x3f,0x31,0x30,0x13,0x13,0x33,0x13,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x0b,0xc9,0x9b,0xc7,0x8a,0x78,0x0f,0x03,0x05,0x04,0x11,0x78,0x02,0x9a,0x02,0x24,0xfd,0xdc,0x01,0x72,0x2f,0x25,0x22,0x32,0xfe,0x8e,0x00,0x00,0x01,0x00,0x1a,0x02,0x9a,0x01,0xf5,0x04,0xbe,0x00,0x09,0x00,0x34,0xb1,0x05, 0x01,0xbf,0x01,0x0d,0x00,0x04,0x01,0x0a,0x00,0x00,0x00,0x06,0x01,0x0d,0x00,0x09,0x01,0x08,0x40,0x0c,0x02,0x07,0x06,0x07,0x02,0x01,0x04,0x05,0x00,0x00,0x0b,0x05,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x35,0x01,0x23,0x35,0x21,0x01,0xf5,0xfe,0xe8, 0x01,0x14,0xfe,0x29,0x01,0x18,0xf8,0x01,0xbb,0x04,0x86,0xfe,0x7e,0x6a,0x3a,0x01,0x80,0x6a,0x00,0x01,0x00,0x1a,0x01,0xe2,0x02,0x5a,0x04,0xbe,0x00,0x16,0x00,0x47,0xb1,0x04,0x09,0xb8,0xff,0xc0,0xb5,0x0c,0x10,0x48,0x09,0x10,0x16,0xbf,0x01,0x0d,0x00,0x0f,0x01,0x0a,0x00,0x15,0x00,0x11,0x01,0x0d,0x00,0x14,0x01,0x08,0x40,0x0f, 0x06,0x0c,0x02,0x00,0x12,0x11,0x12,0x00,0x16,0x04,0x10,0x15,0x15,0x18,0x10,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0xd6,0xcd,0xc6,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0xd4,0x2b,0xcd,0x31,0x30,0x01,0x06,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x21,0x35,0x01,0x23,0x35,0x21,0x15,0x01,0x01,0xf1, 0x23,0x4a,0x21,0x21,0x24,0x29,0x45,0x4f,0x04,0xfe,0x9d,0x01,0x18,0xf8,0x01,0xbb,0xfe,0xe8,0x03,0x04,0x41,0x43,0x53,0x13,0x4d,0x11,0x4e,0x47,0x11,0x12,0x3a,0x01,0x80,0x6a,0x38,0xfe,0x7e,0x00,0x00,0x02,0x00,0x1a,0x02,0x55,0x02,0x82,0x04,0xbe,0x00,0x17,0x00,0x1e,0x00,0x52,0xb6,0x1d,0x11,0x07,0x00,0x18,0x03,0x0d,0x41,0x09, 0x01,0x0d,0x00,0x03,0x00,0x06,0x01,0x0a,0x00,0x0c,0x00,0x08,0x01,0x0d,0x00,0x0b,0x01,0x08,0x40,0x15,0x18,0x00,0x1b,0x02,0x0e,0x05,0x14,0x03,0x09,0x1b,0x14,0x08,0x09,0x0d,0x03,0x04,0x07,0x0c,0x0c,0x20,0x07,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0xd4,0xcd,0x2f,0x2f,0x12,0x39,0x39,0xcd,0x11,0x39,0x39,0x00,0x3f,0xed,0x39,0x3f, 0xce,0xfd,0x17,0x39,0xd4,0xcd,0x31,0x30,0x01,0x06,0x07,0x23,0x36,0x37,0x23,0x35,0x01,0x23,0x35,0x21,0x15,0x01,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x36,0x35,0x34,0x23,0x22,0x01,0x4b,0x11,0x07,0x59,0x0b,0x0d,0xd8,0x01,0x18,0xf8,0x01,0xbb,0xfe,0xe8,0x3d,0x2b,0x72,0x44,0x45,0x42,0x60,0x58,0x48,0x54, 0x51,0x2e,0x41,0x02,0x9a,0x26,0x1f,0x27,0x1e,0x3a,0x01,0x80,0x6a,0x38,0xfe,0x7e,0x4e,0x57,0x42,0x32,0x43,0x58,0x6a,0x02,0x2a,0x23,0x00,0x01,0xff,0xfb,0x01,0x94,0x01,0xf7,0x04,0xbe,0x00,0x18,0x00,0x4c,0xb1,0x0b,0x09,0xb8,0x01,0x0d,0xb6,0x11,0x11,0x03,0x10,0x0d,0xe2,0x0e,0xbb,0x01,0x08,0x00,0x01,0x00,0x03,0x01,0x0d,0x40, 0x0d,0x17,0x11,0x0c,0x0f,0x0b,0x0b,0x0e,0x0f,0x0e,0x0f,0x0e,0x01,0x14,0xb8,0x01,0x0c,0xb3,0x06,0x06,0x1a,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0x00,0x2f,0xfd,0xc6,0x3f,0xed,0x39,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x03,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35, 0x37,0x21,0x35,0x21,0x15,0x03,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x05,0x5a,0x5a,0x5e,0x68,0x6c,0x65,0x28,0xa7,0xfe,0xec,0x01,0xc7,0xb3,0x55,0x7f,0xb2,0x8d,0x66,0x01,0xc0,0x76,0x38,0x4d,0x46,0x4a,0x44,0x3a,0xfb,0x6a,0x3a,0xfe,0xf7,0x0c,0x79,0x62,0x70,0x90,0x00,0x00,0x03,0x00,0x3e,0x02,0x89,0x02,0x7f,0x05,0xd3,0x00,0x0a, 0x00,0x10,0x00,0x17,0x00,0x3f,0xb9,0x00,0x12,0x01,0x0d,0xb3,0x10,0x10,0x15,0x0d,0xbe,0x01,0x0d,0x00,0x06,0x01,0x07,0x00,0x15,0x01,0x0d,0x00,0x00,0x01,0x0b,0xb3,0x0b,0x10,0x12,0x08,0xb8,0x01,0x0c,0xb3,0x11,0x11,0x19,0x12,0xb9,0x01,0x0c,0x00,0x03,0x2f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x12, 0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x20,0x11,0x14,0x06,0x13,0x02,0x23,0x22,0x06,0x07,0x05,0x21,0x16,0x16,0x33,0x32,0x36,0x01,0x58,0x85,0x95,0x9c,0x91,0x01,0x14,0x99,0x14,0x08,0x91,0x46,0x54,0x05,0x01,0x39,0xfe,0xc5,0x03,0x52,0x4a,0x48,0x51,0x02,0x89,0xd9,0xc5,0xcf,0xdd,0xfe,0x61,0xcc,0xdf,0x01, 0xdd,0x01,0x02,0x8c,0x76,0x63,0x85,0x8a,0x8c,0x00,0x00,0x03,0xff,0x3e,0x04,0xba,0x00,0xc2,0x05,0xd3,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x27,0x40,0x11,0x00,0x07,0x40,0x0d,0x80,0x02,0x19,0x13,0x01,0x03,0x01,0x03,0x16,0x0a,0x04,0x10,0x16,0x2f,0xcd,0xd4,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x00,0x2f,0xcd,0xc4,0x1a,0xdc,0x1a,0xcd, 0xc4,0x31,0x30,0x03,0x05,0x07,0x25,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x6a,0x01,0x02,0x2e,0xfe,0xfe,0x01,0x5a,0x22,0x19,0x19,0x22,0x22,0x19,0x19,0x22,0xfe,0xf2,0x22,0x19,0x19,0x22,0x22,0x19,0x19,0x22,0x05,0xd3,0xe7,0x32,0xe7,0x09,0x19, 0x22,0x22,0x19,0x19,0x22,0x22,0xbc,0x19,0x22,0x22,0x19,0x19,0x22,0x22,0x00,0x03,0xff,0x3e,0x04,0xba,0x00,0xc2,0x05,0xd3,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x27,0x40,0x11,0x0d,0x40,0x03,0x07,0x80,0x01,0x13,0x19,0x00,0x02,0x00,0x02,0x04,0x10,0x16,0x0a,0x04,0x2f,0xcd,0xd4,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x00,0x2f,0xcd,0xc4, 0x1a,0xdc,0xc4,0x1a,0xcd,0x31,0x30,0x13,0x05,0x27,0x25,0x05,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x05,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x98,0xfe,0xfe,0x2e,0x01,0x02,0xfe,0xd4,0x22,0x19,0x19,0x22,0x22,0x19,0x19,0x22,0x01,0x0e,0x22,0x19,0x19,0x22,0x22,0x19,0x19,0x22,0x05,0xa1,0xe7, 0x32,0xe7,0x3b,0x19,0x22,0x22,0x19,0x19,0x22,0x22,0x8a,0x19,0x22,0x22,0x19,0x19,0x22,0x22,0x00,0x01,0xff,0x9c,0xfe,0x51,0x00,0x5b,0xff,0xc9,0x00,0x36,0x00,0x2c,0x40,0x15,0x30,0x1c,0x00,0x33,0x03,0x21,0x16,0x26,0x11,0x2b,0x0c,0x0c,0x11,0x16,0x1b,0x04,0x00,0x30,0x06,0x36,0x00,0x2f,0xcd,0xd4,0xcd,0x12,0x17,0x39,0x2f,0xcd, 0x2f,0xcd,0x2f,0xcd,0x00,0x2f,0xcd,0xcd,0xc4,0x39,0x31,0x30,0x07,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x07,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x35,0x34,0x2e,0x02,0x35,0x34,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x64,0x13,0x39,0x24, 0x24,0x2b,0x0e,0x13,0x15,0x18,0x12,0x17,0x12,0x12,0x15,0x12,0x0f,0x17,0x1b,0x0b,0x01,0x1b,0x35,0x28,0x19,0x12,0x15,0x12,0x12,0x15,0x11,0x18,0x1d,0x18,0x11,0x0f,0x0f,0x18,0x04,0x87,0x2a,0x26,0x26,0x14,0x14,0x1d,0x0b,0x0c,0x13,0x08,0x07,0x0c,0x0f,0x17,0x11,0x10,0x15,0x12,0x10,0x0b,0x0b,0x0f,0x0c,0x08,0x04,0x0d,0x04,0x0c, 0x15,0x10,0x0f,0x14,0x11,0x0f,0x0b,0x0a,0x11,0x12,0x15,0x0e,0x0f,0x17,0x14,0x13,0x0c,0x0a,0x0d,0x10,0x0b,0x00,0x00,0x01,0xfe,0xdd,0x04,0xd2,0x01,0x29,0x05,0xbc,0x00,0x19,0x00,0x19,0x40,0x0a,0x0d,0x40,0x0c,0x0c,0x19,0x80,0x05,0x14,0x0d,0x19,0x2f,0xc4,0x00,0x2f,0xcd,0x1a,0xcd,0x39,0x2f,0x1a,0xcd,0x31,0x30,0x03,0x14,0x1e, 0x02,0x33,0x32,0x3e,0x04,0x33,0x17,0x22,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0xbe,0x0c,0x18,0x22,0x16,0x14,0x3a,0x43,0x48,0x44,0x3d,0x16,0x1b,0x19,0x40,0x47,0x4b,0x48,0x43,0x1b,0x29,0x45,0x31,0x1c,0x05,0x7b,0x10,0x29,0x26,0x1a,0x1b,0x28,0x2e,0x28,0x1b,0x29,0x1c,0x29,0x31,0x29,0x1c,0x36,0x4b,0x50,0x19,0xff,0xff,0x00,0x70, 0xfe,0x3c,0x01,0x50,0x05,0xd1,0x02,0x27,0x00,0x11,0x00,0x00,0x00,0x8d,0x00,0x27,0x00,0x11,0x00,0x00,0xfe,0x52,0x00,0x27,0x00,0x11,0x00,0x00,0x02,0xca,0x00,0x07,0x00,0x11,0x00,0x00,0x05,0x06,0xff,0xff,0x00,0x3e,0xfe,0xde,0x02,0x1e,0x01,0x24,0x02,0x07,0x07,0xa5,0x00,0x00,0xfc,0x55,0xff,0xff,0x00,0x3e,0xfe,0xde,0x02,0x35, 0x01,0x24,0x02,0x07,0x07,0xab,0x00,0x00,0xfc,0x55,0xff,0xff,0x00,0x3e,0xfe,0xde,0x02,0x7f,0x01,0x24,0x02,0x07,0x07,0xb4,0x00,0x00,0xfc,0x55,0xff,0xff,0x00,0x12,0xfe,0xef,0x02,0x11,0x01,0x13,0x02,0x07,0x08,0x61,0x00,0x00,0xfc,0x55,0xff,0xff,0x00,0x48,0xfe,0xdc,0x02,0x40,0x01,0x26,0x02,0x07,0x07,0xac,0x00,0x00,0xfc,0x55, 0x00,0x03,0x00,0x54,0xff,0x2f,0x03,0xf2,0x06,0x50,0x00,0x1c,0x00,0x27,0x00,0x2e,0x00,0x1f,0xb7,0x17,0x39,0x2d,0x28,0x22,0x2e,0x39,0x1c,0xb8,0x01,0x4d,0xb3,0x23,0x16,0x39,0x0f,0xb8,0x01,0x06,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0xed,0x31,0x30,0x05,0x23,0x37,0x2e,0x03,0x35,0x34,0x12,0x36,0x36,0x37,0x37,0x33,0x07,0x16, 0x16,0x17,0x15,0x26,0x26,0x27,0x03,0x21,0x11,0x06,0x23,0x23,0x01,0x14,0x1e,0x02,0x17,0x13,0x0e,0x03,0x01,0x32,0x36,0x37,0x11,0x23,0x03,0x02,0x39,0x6d,0x13,0x64,0x95,0x62,0x30,0x43,0x83,0xc1,0x7f,0x11,0x6d,0x11,0x51,0x8e,0x39,0x3d,0x94,0x53,0x2e,0x01,0x65,0xb9,0xe1,0x0c,0xfe,0xb0,0x1b,0x39,0x5b,0x41,0x62,0x56,0x7f,0x54, 0x29,0x01,0x67,0x43,0x7d,0x31,0xd4,0x28,0xd1,0xe2,0x15,0x6e,0xae,0xe9,0x8f,0xa5,0x01,0x07,0xbb,0x69,0x08,0xbe,0xbe,0x05,0x25,0x20,0xb0,0x2f,0x35,0x07,0xfd,0xe9,0xfd,0x94,0x7a,0x02,0xc0,0x70,0xb7,0x8a,0x5c,0x15,0x04,0x5e,0x0b,0x59,0x95,0xc9,0xfd,0x53,0x21,0x22,0x01,0x88,0xfe,0x35,0x00,0x03,0x00,0x0c,0x00,0x00,0x04,0x44, 0x05,0x9a,0x00,0x17,0x00,0x1b,0x00,0x23,0x00,0x91,0x40,0x4d,0x06,0x03,0x02,0x17,0x16,0x07,0x16,0x23,0x22,0x21,0x1a,0x19,0x09,0x08,0x1c,0x08,0x1d,0x1e,0x1f,0x20,0x1b,0x18,0x0a,0x0b,0x1c,0x0b,0x14,0x11,0x10,0x0d,0x0c,0x15,0x0c,0x02,0x1b,0x11,0x92,0x17,0x20,0x14,0x06,0x0a,0x0d,0x92,0x03,0x18,0x00,0x10,0x10,0x10,0x80,0x10, 0x03,0x10,0x10,0x14,0x1c,0x03,0x15,0x03,0x08,0x0c,0x01,0x05,0x13,0x0e,0x0e,0x15,0x16,0x1d,0x05,0x05,0x0c,0x07,0x07,0x25,0x0c,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x33,0x2f,0x33,0x00,0x2f,0x32,0x3f,0x17,0x39,0x2f,0x5d,0x33,0x33,0xed,0x32,0x32,0x2f,0x33,0x33,0xed,0x32,0x32,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0, 0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x0e,0xc0,0xc0,0x05,0xc0,0x10,0x87,0xc0,0xc0,0xc0,0xc0,0x0e,0xc0,0xc0,0x10,0x87,0x05,0xc0,0xc0,0xc0,0xc0,0x01,0x15,0x23,0x17,0x33,0x15,0x23,0x13,0x23,0x03,0x21,0x03,0x23,0x13,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x13,0x33,0x13,0x01,0x21,0x27,0x21,0x13,0x23,0x06,0x07,0x03,0x33,0x03,0x26,0x04, 0x2c,0xcd,0x39,0x94,0x68,0x80,0xba,0x76,0xfe,0x25,0x72,0xbb,0x7f,0x67,0x93,0x39,0xcc,0xf8,0xb5,0xad,0xb5,0xfe,0x2e,0x01,0x8a,0x34,0xfe,0xdd,0x92,0x03,0x08,0x0b,0x53,0xd1,0x55,0x09,0x03,0x5f,0x8d,0xb3,0x8d,0xfe,0x6e,0x01,0x92,0xfe,0x6e,0x01,0x92,0x8d,0xb3,0x8d,0x02,0x3b,0xfd,0xc5,0xfe,0xc0,0xb3,0x02,0x10,0x3d,0x23,0xfe, 0xdd,0x01,0x23,0x1e,0x00,0x01,0x00,0x69,0xff,0xe8,0x03,0xe2,0x05,0xb2,0x00,0x47,0x00,0x89,0xb1,0x01,0x2f,0xb8,0x01,0x05,0xb6,0x46,0x2f,0x30,0x01,0x30,0x09,0x26,0xb8,0x01,0x05,0x40,0x44,0x06,0xd0,0x27,0xe0,0x27,0x02,0x27,0x21,0x0e,0x35,0x44,0x27,0x30,0x06,0x3f,0x1c,0x3d,0x3c,0x3a,0x91,0x3f,0x04,0x17,0x00,0x16,0x10,0x16, 0x20,0x16,0x03,0x16,0x11,0x91,0x1c,0x13,0x3c,0x09,0x06,0x01,0x46,0x04,0x44,0x0e,0x25,0x28,0x2e,0x31,0x3c,0x05,0x35,0x21,0x16,0x16,0x44,0x08,0x00,0x00,0x44,0x7d,0x35,0x35,0x49,0x48,0x30,0x27,0x0e,0x7d,0x21,0x2f,0xe1,0xc4,0x32,0x11,0x12,0x39,0x2f,0xf1,0xc0,0x2f,0x32,0x10,0xc0,0x2f,0x11,0x12,0x17,0x39,0x11,0x12,0x17,0x39, 0x2f,0x00,0x3f,0xfd,0xc6,0x5d,0x32,0x3f,0xfd,0xc6,0x32,0x11,0x12,0x17,0x39,0x2f,0x5d,0x33,0xed,0x32,0x2f,0x5d,0x33,0xed,0x32,0x31,0x30,0x01,0x23,0x07,0x06,0x07,0x06,0x07,0x21,0x15,0x21,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x36,0x37,0x23,0x35,0x33, 0x36,0x37,0x36,0x37,0x36,0x37,0x21,0x35,0x21,0x36,0x37,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x33,0x03,0xe2,0x6f,0x04,0x30,0x41,0x34,0x3a,0x01,0x52,0xfd,0xe2,0x24,0x1d,0x2d,0x33,0x99,0x9b,0x2d,0x6a,0x69,0x5f,0x22,0x1c,0x5d,0x68,0x64,0x22,0x66,0xb8,0x8d,0x53,0x1e,0x12,0x1a, 0x54,0xc7,0x16,0x17,0x45,0x4d,0x2e,0x28,0xfe,0x24,0x02,0x80,0x19,0x0f,0x15,0x36,0x56,0x6e,0x37,0xc7,0x7f,0x61,0xd4,0x5d,0xb3,0x8c,0x56,0x1a,0x26,0x03,0x41,0x04,0x2f,0x27,0x1f,0x1f,0x6b,0x16,0x17,0x23,0x56,0x3a,0x6c,0x73,0x12,0x21,0x30,0x1e,0xc6,0x13,0x1f,0x15,0x0b,0x29,0x5c,0x93,0x6a,0x50,0x3e,0x25,0x21,0x6b,0x0f,0x0e, 0x2a,0x26,0x17,0x14,0x6b,0x19,0x1e,0x28,0x37,0x3b,0x52,0x34,0x17,0x58,0xbd,0x33,0x2e,0x5e,0x91,0x62,0x4d,0x3a,0x00,0x02,0x00,0x56,0xff,0x2f,0x03,0xe6,0x06,0x50,0x00,0x18,0x00,0x21,0x00,0x4f,0x40,0x2d,0x13,0x20,0x15,0x91,0x0d,0x9f,0x0f,0xaf,0x0f,0x02,0x0f,0x10,0x04,0x20,0x18,0x01,0x18,0x1f,0x16,0x91,0x05,0x60,0x03,0x70, 0x03,0x02,0x03,0x02,0x13,0x10,0x16,0x03,0x8c,0x0d,0x1f,0x04,0x04,0x09,0x13,0x00,0x00,0x23,0x1b,0x7e,0x09,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x00,0x3f,0xcd,0x5d,0x33,0xfd,0x32,0xc6,0x5d,0x3f,0xcd,0x5d,0x33,0xfd,0x32,0xc6,0x31,0x30,0x25,0x06,0x07,0x15,0x23,0x35,0x26,0x27,0x26,0x11,0x10, 0x37,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x15,0x26,0x27,0x11,0x36,0x37,0x01,0x06,0x11,0x10,0x17,0x16,0x17,0x11,0x06,0x03,0xe6,0x73,0xa7,0x68,0xe6,0x8d,0x9b,0xaf,0x8e,0xd1,0x68,0xad,0x6d,0x7d,0x9d,0xa4,0x76,0xfd,0x97,0x7f,0x77,0x5f,0x90,0x8a,0x3c,0x48,0x0a,0xbb,0xbb,0x11,0xb2,0xc5,0x01,0x40,0x01,0x58,0xd4,0xad,0x1f,0xa6, 0x9e,0x01,0x3a,0xb3,0x55,0x01,0xfb,0x65,0x07,0x59,0x03,0x96,0xa5,0xfe,0xec,0xfe,0xfa,0x9c,0x7c,0x19,0x04,0x89,0x1f,0x00,0x00,0x02,0x00,0x42,0x00,0xc8,0x02,0x68,0x03,0x49,0x00,0x03,0x00,0x07,0x00,0x23,0x40,0x11,0x01,0x00,0x03,0x10,0x03,0x02,0x03,0x03,0x08,0x05,0x07,0x03,0x07,0x07,0x09,0x02,0x06,0x2f,0x33,0x12,0x39,0x2f, 0x33,0x00,0x2f,0xcd,0x12,0x39,0x2f,0x5d,0xcd,0x31,0x30,0x01,0x05,0x35,0x25,0x35,0x05,0x35,0x25,0x02,0x68,0xfd,0xda,0x02,0x26,0xfd,0xda,0x02,0x26,0x01,0x9a,0xd2,0x83,0xd2,0xa9,0xd2,0x83,0xd2,0x00,0x01,0xff,0x50,0xfe,0x96,0x00,0xd7,0x00,0xc1,0x00,0x0c,0x00,0x12,0xb7,0x09,0x95,0x04,0x00,0x00,0x84,0x07,0x0c,0x2f,0xc6,0xed, 0x00,0x2f,0x2f,0xed,0x31,0x30,0x37,0x11,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0xd7,0x98,0x7f,0x3c,0x34,0x34,0x3c,0x7e,0xc1,0xfe,0xfd,0x89,0x9f,0x17,0x93,0x1f,0x9d,0x01,0x03,0x00,0x01,0xff,0x50,0xfe,0x96,0x00,0xd7,0x00,0x8f,0x00,0x0c,0x00,0x12,0xb7,0x09,0x95,0x04,0x00,0x00,0x84,0x07,0x0c,0x2f,0xc6,0xed, 0x00,0x2f,0x2f,0xed,0x31,0x30,0x37,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0xd7,0x98,0x7f,0x3c,0x34,0x34,0x3c,0x7e,0x8f,0xd1,0x89,0x9f,0x17,0x93,0x1f,0x9d,0xd1,0x00,0x01,0xff,0x50,0xfe,0x96,0x00,0xd7,0x00,0x35,0x00,0x0c,0x00,0x12,0xb7,0x09,0x95,0x04,0x00,0x00,0x84,0x07,0x0c,0x2f,0xc6,0xed,0x00,0x2f, 0x2f,0xed,0x31,0x30,0x37,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x35,0xd7,0x98,0x7f,0x3c,0x34,0x34,0x3c,0x7e,0x35,0x77,0x89,0x9f,0x17,0x93,0x1f,0x9d,0x77,0x00,0x01,0xff,0x29,0xfe,0x96,0x00,0xb0,0x00,0x35,0x00,0x0c,0x00,0x12,0xb7,0x03,0x95,0x08,0x00,0x05,0x00,0x84,0x0c,0x2f,0xfd,0xc6,0x00,0x2f,0x2f,0xed, 0x31,0x30,0x27,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x35,0x3e,0x7e,0x3c,0x34,0x34,0x3c,0x7f,0x98,0x35,0x77,0x9d,0x1f,0x93,0x17,0x9f,0x89,0x77,0x00,0x01,0x00,0x27,0x01,0x83,0x03,0xac,0x02,0x83,0x00,0x11,0x00,0x27,0x40,0x0c,0x09,0x0f,0x96,0x03,0x06,0x96,0x11,0x2f,0x0c,0x01,0x0c,0x00,0xbc,0x01,0x03,0x00, 0x11,0x00,0x08,0x01,0x03,0x00,0x09,0x2f,0xed,0x2f,0xed,0x00,0x2f,0x5d,0xc6,0xfd,0xdc,0xed,0xc4,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x24,0x23,0x22,0x15,0x23,0x34,0x36,0x33,0x32,0x04,0x33,0x32,0x35,0x03,0xac,0x60,0x7a,0x47,0xfe,0xc2,0x48,0x80,0x5e,0x60,0x7e,0x5f,0x01,0x34,0x36,0x7c,0x02,0x83,0x69,0x85,0x5f,0x71,0x6b,0x81, 0x60,0x74,0x00,0x01,0x00,0x3e,0x04,0xc2,0x02,0x3a,0x05,0x4d,0x00,0x03,0x00,0x0d,0xb4,0x02,0x95,0x01,0x03,0x02,0x2f,0x2f,0x00,0x2f,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0x3a,0xfe,0x04,0x01,0xfc,0x04,0xc2,0x8b,0x00,0x01,0x00,0x12,0x02,0x9a,0x02,0x11,0x04,0xbe,0x00,0x0d,0x00,0x13,0xbb,0x00,0x07,0x01,0x0a,0x00,0x09,0x01, 0x08,0xb1,0x02,0x07,0x2f,0x2f,0x00,0x3f,0x3f,0x31,0x30,0x01,0x03,0x13,0x23,0x27,0x23,0x07,0x23,0x13,0x03,0x33,0x17,0x33,0x37,0x02,0x11,0xbc,0xb8,0x91,0x6a,0x02,0x6e,0x90,0xbe,0xb6,0x92,0x67,0x02,0x6f,0x04,0xbe,0xfe,0xeb,0xfe,0xf1,0xb2,0xb2,0x01,0x0c,0x01,0x18,0xbd,0xbd,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x07,0x32, 0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x83,0x00,0x00,0x01,0x07,0x04,0x36,0x00,0x29,0x01,0x2c,0x00,0x10,0xb7,0x04,0x03,0x38,0x2a,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x07,0x32,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x83,0x00,0x00, 0x01,0x07,0x04,0x37,0x00,0x29,0x01,0x2c,0x00,0x10,0xb7,0x04,0x03,0x39,0x2a,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x07,0x32,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x83,0x00,0x00,0x01,0x07,0x04,0x43,0x00,0x29,0x01,0x2c,0x00,0x10,0xb7,0x04,0x03,0x38, 0x2a,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5,0x07,0x32,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x83,0x00,0x00,0x01,0x07,0x04,0x44,0x00,0x29,0x01,0x2c,0x00,0x10,0xb7,0x04,0x03,0x39,0x2a,0x02,0x28,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff, 0x00,0x5a,0xff,0xe8,0x04,0xc5,0x07,0x46,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x83,0xff,0xcf,0x01,0x07,0x04,0x36,0x00,0x29,0x01,0x40,0x00,0x1b,0x40,0x10,0x04,0x03,0x2f,0x41,0x01,0x0f,0x41,0x10,0x41,0x02,0x41,0x27,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x5a, 0xff,0xe8,0x04,0xc5,0x07,0x46,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x83,0xff,0xcf,0x01,0x07,0x04,0x37,0x00,0x29,0x01,0x40,0x00,0x1b,0x40,0x10,0x04,0x03,0x2f,0x42,0x01,0x0f,0x42,0x10,0x42,0x02,0x42,0x27,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8, 0x04,0xc5,0x07,0x46,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x83,0xff,0xcf,0x01,0x07,0x04,0x43,0x00,0x29,0x01,0x40,0x00,0x1b,0x40,0x10,0x04,0x03,0x2f,0x42,0x01,0x0f,0x42,0x10,0x42,0x02,0x42,0x27,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x04,0xc5, 0x07,0x46,0x02,0x26,0x01,0x2f,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x83,0xff,0xcf,0x01,0x07,0x04,0x44,0x00,0x29,0x01,0x40,0x00,0x1b,0x40,0x10,0x04,0x03,0x2f,0x42,0x01,0x0f,0x42,0x10,0x42,0x02,0x42,0x27,0x02,0x2a,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0xff,0xf9,0xff,0xf4,0x02,0x15,0x07,0x32, 0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x64,0x01,0x00,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0xaf,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x1e,0x0f,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x02,0xff,0xf4,0x02,0x32,0x07,0x32,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x64,0x01,0x00,0x00,0x00, 0x01,0x07,0x04,0x37,0xfe,0xc4,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x1e,0x0f,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0xff,0xfc,0xff,0xf4,0x02,0x24,0x07,0x32,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x64,0x01,0x00,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0xb8,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x1e, 0x0f,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0xff,0xe5,0xff,0xf4,0x02,0x28,0x07,0x32,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x64,0x01,0x00,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0xad,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x1e,0x0f,0x01,0x0c,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff, 0xff,0xee,0xff,0xf4,0x02,0x1a,0x07,0x46,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x66,0x01,0x00,0xff,0xcf,0x01,0x07,0x04,0x36,0xfe,0xb4,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x27,0x01,0x0f,0x27,0x10,0x27,0x02,0x27,0x0c,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0xff,0xee, 0xff,0xf4,0x02,0x2d,0x07,0x46,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x66,0x01,0x00,0xff,0xcf,0x01,0x07,0x04,0x37,0xfe,0xbf,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x27,0x01,0x0f,0x27,0x10,0x27,0x02,0x27,0x0c,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0xff,0xee,0xff,0xf4, 0x02,0x20,0x07,0x46,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x66,0x01,0x00,0xff,0xcf,0x01,0x07,0x04,0x43,0xfe,0xb4,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x27,0x01,0x0f,0x27,0x10,0x27,0x02,0x27,0x0c,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0xff,0xee,0xff,0xf4,0x02,0x3a, 0x07,0x46,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x66,0x01,0x00,0xff,0xcf,0x01,0x07,0x04,0x44,0xfe,0xbf,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x27,0x01,0x0f,0x27,0x10,0x27,0x02,0x27,0x0c,0x01,0x0f,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x32, 0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0x00,0x01,0x07,0x04,0x36,0xff,0xcc,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x2f,0x20,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x32,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0x00, 0x01,0x07,0x04,0x37,0xff,0xd9,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x2f,0x20,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x32,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0x00,0x01,0x07,0x04,0x43,0xff,0xcd,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x2f, 0x20,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x32,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0x00,0x01,0x07,0x04,0x44,0xff,0xd0,0x01,0x2c,0x00,0x10,0xb7,0x03,0x02,0x2f,0x20,0x01,0x1d,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x34,0x34,0xff,0xff, 0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x46,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x1b,0xff,0xcf,0x01,0x07,0x04,0x36,0xff,0xc7,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x38,0x01,0x0f,0x38,0x10,0x38,0x02,0x38,0x1d,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x14, 0xff,0xe6,0x04,0x0e,0x07,0x46,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x1b,0xff,0xcf,0x01,0x07,0x04,0x37,0xff,0xd0,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x38,0x01,0x0f,0x38,0x10,0x38,0x02,0x38,0x1d,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x14,0xff,0xe6, 0x04,0x0e,0x07,0x46,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x1b,0xff,0xcf,0x01,0x07,0x04,0x43,0xff,0xc5,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x38,0x01,0x0f,0x38,0x10,0x38,0x02,0x38,0x1d,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e, 0x07,0x46,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x66,0x02,0x1b,0xff,0xcf,0x01,0x07,0x04,0x44,0xff,0xd0,0x01,0x40,0x00,0x1b,0x40,0x10,0x03,0x02,0x2f,0x38,0x01,0x0f,0x38,0x10,0x38,0x02,0x38,0x1d,0x01,0x20,0x11,0x26,0x00,0x2b,0x35,0x10,0xda,0x5d,0x5d,0x34,0x34,0x00,0xff,0xff,0xff,0xd3,0xff,0xf4,0x02,0x1b,0x07,0x40, 0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x68,0x00,0xf6,0xff,0xcf,0x00,0x27,0x04,0x64,0x00,0xf6,0x00,0xd2,0x01,0x07,0x02,0x46,0xff,0xc1,0x01,0x88,0x00,0x29,0x40,0x1a,0x04,0x0f,0x2b,0x3f,0x2b,0x8f,0x2b,0x03,0x2b,0x40,0x0d,0x15,0x36,0x2b,0x03,0x24,0x12,0x02,0x01,0x70,0x0c,0x90,0x0c,0x02,0x0c,0x05,0x00,0x10,0xda,0x5d, 0x34,0x34,0x10,0xda,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0xff,0xd3,0xff,0xf4,0x02,0x1b,0x07,0x40,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x68,0x00,0xf6,0xff,0xcf,0x00,0x27,0x04,0x64,0x00,0xf6,0x00,0xd2,0x01,0x07,0x02,0x47,0xff,0xf3,0x01,0x88,0x00,0x29,0x40,0x1a,0x04,0x0f,0x2b,0x3f,0x2b,0x8f,0x2b,0x03,0x2b,0x40, 0x0d,0x15,0x36,0x2b,0x03,0x24,0x12,0x02,0x01,0x70,0x0c,0x90,0x0c,0x02,0x0c,0x05,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xda,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0xff,0xd3,0xff,0xf4,0x02,0x1b,0x07,0x40,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x68,0x00,0xf6,0xff,0xcf,0x00,0x27,0x04,0x66,0x00,0xf6,0x00,0xaa,0x01,0x07, 0x02,0x46,0xff,0x8f,0x01,0x88,0x00,0x33,0x40,0x22,0x04,0x4f,0x32,0x8f,0x32,0x02,0x32,0x40,0x0c,0x15,0x36,0x32,0x03,0x7f,0x27,0x8f,0x27,0x02,0x27,0x40,0x0d,0x11,0x36,0x27,0x12,0x02,0x01,0x70,0x0c,0x90,0x0c,0x02,0x0c,0x06,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xd2,0x2b,0x5d,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0xff,0xd3, 0xff,0xf4,0x02,0x1b,0x07,0x40,0x02,0x26,0x01,0xc9,0x00,0x00,0x00,0x27,0x04,0x68,0x00,0xf6,0xff,0xcf,0x00,0x27,0x04,0x66,0x00,0xf6,0x00,0xaa,0x01,0x07,0x02,0x47,0x00,0x19,0x01,0x88,0x00,0x33,0x40,0x22,0x04,0x4f,0x32,0x8f,0x32,0x02,0x32,0x40,0x0c,0x15,0x36,0x32,0x03,0x7f,0x27,0x8f,0x27,0x02,0x27,0x40,0x0d,0x11,0x36,0x27, 0x12,0x02,0x01,0x70,0x0c,0x90,0x0c,0x02,0x0c,0x06,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xd2,0x2b,0x5d,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x40,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x68,0x02,0x18,0xff,0xcf,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0xd2,0x01,0x07,0x02,0x46,0x00,0xef, 0x01,0x88,0x00,0x2b,0x40,0x1b,0x04,0x4f,0x3c,0x8f,0x3c,0x02,0x3c,0x40,0x0c,0x15,0x36,0x3c,0x03,0x00,0x35,0x01,0x35,0x23,0x02,0x01,0x70,0x1d,0x90,0x1d,0x02,0x1d,0x14,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xda,0x5d,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x40,0x02,0x26,0x01,0xd2,0x00,0x00, 0x00,0x27,0x04,0x68,0x02,0x18,0xff,0xcf,0x00,0x27,0x04,0x64,0x02,0x1b,0x00,0xd2,0x01,0x07,0x02,0x47,0x01,0x20,0x01,0x88,0x00,0x2b,0x40,0x1b,0x04,0x4f,0x3c,0x8f,0x3c,0x02,0x3c,0x40,0x0c,0x15,0x36,0x3c,0x03,0x00,0x35,0x01,0x35,0x23,0x02,0x01,0x70,0x1d,0x90,0x1d,0x02,0x1d,0x14,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xda,0x5d, 0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x40,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x68,0x02,0x18,0xff,0xcf,0x00,0x27,0x04,0x66,0x02,0x1b,0x00,0xaa,0x01,0x07,0x02,0x46,0x00,0xd1,0x01,0x88,0x00,0x31,0x40,0x20,0x04,0x8f,0x45,0x01,0x45,0x40,0x0c,0x15,0x36,0x45,0x03,0x7f,0x38,0x8f, 0x38,0x02,0x38,0x40,0x0e,0x11,0x36,0x38,0x23,0x02,0x01,0x70,0x1d,0x90,0x1d,0x02,0x1d,0x14,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xd2,0x2b,0x5d,0x34,0x11,0x2b,0x5d,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe6,0x04,0x0e,0x07,0x40,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x27,0x04,0x68,0x02,0x18,0xff,0xcf,0x00,0x27,0x04,0x66,0x02,0x1b, 0x00,0xaa,0x01,0x07,0x02,0x47,0x01,0x48,0x01,0x88,0x00,0x31,0x40,0x20,0x04,0x8f,0x45,0x01,0x45,0x40,0x0c,0x15,0x36,0x45,0x03,0x7f,0x38,0x8f,0x38,0x02,0x38,0x40,0x0e,0x11,0x36,0x38,0x23,0x02,0x01,0x70,0x1d,0x90,0x1d,0x02,0x1d,0x14,0x00,0x10,0xda,0x5d,0x34,0x34,0x10,0xd2,0x2b,0x5d,0x34,0x11,0x2b,0x5d,0x35,0x00,0x00,0x03, 0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x16,0x00,0x1e,0x00,0x39,0xbc,0x00,0x0f,0x01,0x43,0x00,0x19,0x00,0x1d,0x01,0x43,0xb5,0x14,0x19,0x14,0x06,0x00,0x17,0xb8,0x01,0x44,0xb2,0x11,0x07,0x1b,0xb8,0x01,0x44,0xb2,0x0c,0x19,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0x3f,0xe6,0x01,0x2f, 0xc4,0x39,0x39,0x2f,0xe6,0x2f,0xe6,0x31,0x30,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x01,0x32,0x12,0x11,0x10,0x21,0x22,0x02,0x11,0x10,0x12,0x13,0x32,0x11,0x10,0x23,0x22,0x11,0x10,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x04,0x8e,0xe4,0xfe,0xfe,0x3e,0xeb, 0xf9,0xef,0xec,0xe7,0xed,0xf1,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0xff,0x00,0x01,0x7f,0x01,0x6c,0x02,0xdf,0xfe,0x7a,0xfe,0x84,0xfe,0xa6,0xfe,0x92,0x05,0x0d,0xfd,0xcd,0xfd,0xe2,0x02,0x14,0x02,0x3d,0x00,0x02,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x1a,0x00,0x32, 0xb9,0x00,0x1a,0x01,0x43,0x40,0x11,0x13,0x19,0x19,0x00,0x06,0x00,0x1a,0x18,0x04,0x18,0x01,0x18,0x12,0x13,0x0c,0x07,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xde,0xce,0x33,0x5d,0x3f,0x01,0x2f,0x2f,0x12,0x39,0x2f,0xcd,0xe6,0x30,0x31,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x01,0x23, 0x0e,0x03,0x07,0x15,0x3e,0x03,0x37,0x11,0x33,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x05,0x15,0x7a,0x26,0x68,0x75,0x79,0x36,0x30,0x65,0x5b,0x49,0x13,0xe0,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0x04,0xd2,0x21,0x45,0x3f,0x33,0x0f,0xce, 0x0c,0x2a,0x30,0x31,0x13,0xfb,0x51,0x00,0x00,0x02,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0f,0x00,0x32,0x00,0x4e,0xb1,0x23,0x11,0xb8,0x01,0x43,0xb2,0x31,0x10,0x1b,0xb8,0x01,0x43,0x40,0x0c,0x27,0x31,0x27,0x31,0x27,0x00,0x08,0x00,0x12,0x27,0x20,0x10,0xb8,0x01,0x44,0xb3,0x31,0x18,0x23,0x25,0xb8,0x01,0x44,0xb3,0x22, 0x20,0x07,0x0c,0xba,0x01,0x42,0x00,0x04,0x01,0x41,0x00,0x3f,0x3f,0x3f,0x33,0xe6,0x32,0x3f,0xe6,0x12,0x39,0x39,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe6,0x32,0x10,0xe6,0x33,0x30,0x31,0x13,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x11,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x05,0x21,0x35,0x34,0x3e,0x06,0x35,0x34,0x2e,0x02, 0x23,0x22,0x07,0x15,0x36,0x33,0x32,0x15,0x14,0x0e,0x06,0x15,0x15,0x21,0xb4,0x01,0x5b,0x01,0x5c,0x01,0xe5,0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe,0xa4,0xfe,0xa5,0xfe,0x1b,0xfe,0x1b,0xfe,0xa4,0xfe,0xa5,0x06,0x52,0xfd,0x88,0x36,0x58,0x70,0x75,0x70,0x58,0x36,0x41,0x71,0x96,0x54,0xde,0xa9,0xb0,0xc0,0xce,0x38,0x5b,0x74,0x7a,0x74, 0x5b,0x38,0x03,0x74,0x02,0xcd,0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe,0xa4,0xfe,0xa5,0xfe,0x1b,0xfe,0x1a,0xfe,0xa6,0xfe,0xa4,0x01,0x5c,0x01,0x5b,0x22,0x16,0x27,0x4a,0x4d,0x52,0x5f,0x6e,0x85,0x9f,0x60,0x5d,0x8c,0x5d,0x2f,0x83,0xde,0xa4,0xda,0x4b,0x7b,0x6b,0x61,0x61,0x66,0x76,0x8c,0x55,0x6b,0x00,0x00,0x02,0x00,0xb4,0xfe,0x31, 0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x2d,0x00,0x73,0xb2,0x15,0x25,0x17,0xb8,0x01,0x43,0x40,0x09,0x21,0x1d,0x25,0x25,0x1d,0x21,0x03,0x0c,0x11,0xb8,0x01,0x43,0x40,0x09,0x28,0x0c,0x28,0x0c,0x06,0x00,0x15,0x1a,0x25,0xb8,0x01,0x44,0x40,0x0d,0x24,0x24,0x2b,0x80,0x1d,0x01,0x2b,0x1d,0x3b,0x1d,0x02,0x1d,0x1f,0xb8,0x01,0x44,0x40, 0x09,0x1a,0x07,0x24,0x2d,0x34,0x2d,0x02,0x2d,0x2b,0xb8,0x01,0x44,0xb2,0x0e,0x19,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0xc6,0x5d,0x3f,0xe6,0xc6,0x5d,0x5d,0x12,0x39,0x2f,0xe6,0x11,0x39,0x01,0x2f,0xc4,0x39,0x39,0x2f,0x2f,0xe6,0x12,0x17,0x39,0x2f,0x2f,0x2f,0xe6,0x11,0x39,0x31,0x30,0x13,0x10,0x00, 0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x05,0x16,0x33,0x32,0x24,0x35,0x34,0x26,0x27,0x35,0x24,0x11,0x34,0x26,0x23,0x22,0x07,0x15,0x36,0x33,0x32,0x15,0x14,0x21,0x23,0x15,0x33,0x20,0x15,0x14,0x06,0x23,0x22,0x27,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x03,0x0b,0x79,0xcc, 0xe3,0x01,0x15,0xb7,0x9b,0x01,0x20,0xd9,0xb5,0xbc,0x8a,0x86,0x97,0xd2,0xfe,0xda,0x71,0x77,0x01,0x53,0x92,0x7b,0xb9,0x93,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0xb3,0x4d,0xed,0xc1,0x8c,0xbb,0x0f,0x04,0x51,0x01,0x1b,0x96,0xc0,0x52,0xd2,0x67,0xda,0xd7,0xbd,0xe9,0x6a,0x90,0x74,0x00, 0x00,0x03,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0f,0x00,0x1c,0x00,0x27,0x00,0x4f,0xb3,0x10,0x11,0x11,0x1a,0xb8,0x01,0x43,0x40,0x0e,0x27,0x13,0x19,0x1d,0x17,0x19,0x17,0x19,0x17,0x00,0x08,0x00,0x1b,0x18,0xb8,0x01,0x44,0x40,0x0b,0x16,0x11,0x1d,0x1d,0x12,0x1a,0x18,0x22,0x12,0x07,0x0c,0xba,0x01,0x42,0x00,0x04,0x01, 0x41,0x00,0x3f,0x3f,0x3f,0x33,0x3f,0x12,0x39,0x2f,0x33,0x33,0xe6,0x32,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x33,0xe6,0x32,0x11,0x33,0x30,0x31,0x13,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x11,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x01,0x23,0x11,0x21,0x02,0x00,0x07,0x15,0x21,0x11,0x33,0x11,0x33,0x25,0x3e, 0x03,0x37,0x33,0x06,0x06,0x15,0x11,0xb4,0x01,0x5b,0x01,0x5c,0x01,0xe5,0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe,0xa4,0xfe,0xa5,0xfe,0x1b,0xfe,0x1b,0xfe,0xa4,0xfe,0xa5,0x06,0x68,0xae,0xfe,0xfe,0xa4,0xfe,0xda,0x82,0x02,0x70,0xde,0xae,0xfc,0xde,0x35,0x6f,0x69,0x61,0x28,0x04,0x02,0x02,0x02,0xcd,0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe, 0xa4,0xfe,0xa5,0xfe,0x1b,0xfe,0x1a,0xfe,0xa6,0xfe,0xa4,0x01,0x5c,0x01,0x5b,0x01,0x4c,0x03,0x66,0xfe,0xe0,0xfe,0x4e,0xa4,0xa7,0xfe,0x83,0x01,0x7d,0xb7,0x3b,0x95,0xa4,0xa8,0x4e,0x2a,0x49,0x21,0xfe,0x2a,0x00,0x02,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0f,0x00,0x34,0x00,0x50,0xb1,0x23,0x17,0xb8,0x01,0x43,0xb2,0x2d, 0x34,0x21,0xb8,0x01,0x43,0x40,0x09,0x26,0x2d,0x26,0x2d,0x26,0x00,0x08,0x00,0x28,0xb8,0x01,0x44,0xb3,0x1c,0x1c,0x12,0x23,0xb8,0x01,0x44,0xb2,0x25,0x06,0x32,0xb8,0x01,0x44,0xb2,0x12,0x19,0x0c,0xba,0x01,0x42,0x00,0x04,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0x3f,0xe6,0x12,0x39,0x2f,0xe6,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f, 0x10,0xe6,0x33,0x10,0xe6,0x32,0x30,0x31,0x13,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x11,0x10,0x01,0x00,0x21,0x20,0x01,0x00,0x05,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x22,0x06,0x06,0x07,0x13,0x21,0x35,0x21,0x03,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x27,0xb4,0x01,0x5b,0x01,0x5c,0x01,0xe5, 0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe,0xa4,0xfe,0xa5,0xfe,0x1b,0xfe,0x1b,0xfe,0xa4,0xfe,0xa5,0x03,0x22,0x62,0xc7,0x6d,0xba,0x87,0x4d,0x4c,0x83,0xb0,0x63,0x07,0x1b,0x1f,0x1c,0x09,0x1b,0x01,0xec,0xfd,0x5e,0x3c,0xa5,0x3c,0x4a,0x7f,0x5d,0x35,0x2c,0x4c,0x65,0x39,0x97,0x94,0x02,0xcd,0x01,0xe5,0x01,0x5b,0x01,0x5c,0xfe,0xa4,0xfe, 0xa5,0xfe,0x1b,0xfe,0x1a,0xfe,0xa6,0xfe,0xa4,0x01,0x5c,0x01,0x5b,0xc5,0x3b,0x3f,0x77,0xab,0x6d,0x6f,0xa3,0x6a,0x34,0x01,0x02,0x01,0x01,0x72,0xc6,0xfc,0xff,0x0c,0x22,0x40,0x5d,0x3b,0x3e,0x62,0x44,0x23,0x5f,0x00,0x00,0x03,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x22,0x00,0x2e,0x00,0x5a,0xb5,0x0c,0x2c,0x0c, 0x2c,0x1d,0x17,0xbb,0x01,0x43,0x00,0x26,0x00,0x1d,0x01,0x43,0xb5,0x11,0x26,0x11,0x06,0x00,0x23,0xb8,0x01,0x44,0x40,0x0b,0x1a,0x1a,0x0e,0x29,0x22,0x20,0x09,0x12,0x48,0x22,0x20,0xb8,0x01,0x44,0xb2,0x0e,0x07,0x29,0xb8,0x01,0x44,0xb2,0x14,0x19,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0x3f,0xf6,0xcd, 0x2b,0x11,0x12,0x39,0x2f,0xe6,0x01,0x2f,0xc4,0x39,0x39,0x2f,0xe6,0x2f,0xe6,0x11,0x39,0x39,0x2f,0x2f,0x31,0x30,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x01,0x26,0x23,0x20,0x00,0x11,0x10,0x12,0x33,0x32,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x23,0x34,0x12,0x33,0x32,0x17,0x01,0x32,0x16,0x15,0x14,0x06,0x23, 0x22,0x26,0x35,0x34,0x36,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x05,0xf2,0x58,0x96,0xfe,0xf8,0xfe,0xbe,0xf6,0xd8,0xc4,0xfe,0xde,0xbc,0xad,0x61,0x03,0xc5,0xa4,0x7b,0x6f,0xfe,0x99,0x68,0x73,0x78,0x61,0x66,0x7c,0x7c,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b, 0xfd,0x49,0x02,0xb7,0x04,0xa1,0x29,0xfe,0x3e,0xfe,0x87,0xfe,0xc9,0xfe,0xa8,0x01,0x0b,0xd3,0xca,0xf1,0x8f,0xe0,0x01,0x23,0x39,0xfe,0x08,0x91,0x81,0x75,0x99,0xb0,0x7c,0x63,0x91,0x00,0x00,0x02,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x1a,0x00,0x3a,0xb2,0x0f,0x0c,0x15,0xb8,0x01,0x43,0x40,0x0e,0x14,0x0c,0x14, 0x0d,0x0d,0x14,0x0c,0x03,0x00,0x06,0x00,0x15,0x18,0x0f,0xb8,0x01,0x44,0xb2,0x0d,0x06,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0x3f,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xe6,0x11,0x33,0x30,0x31,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x01,0x21,0x15,0x21,0x06,0x0a, 0x02,0x07,0x33,0x36,0x1a,0x02,0x37,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x06,0x78,0xfc,0x64,0x02,0x91,0x66,0x9c,0x75,0x55,0x1f,0xec,0x11,0x4e,0x80,0xb4,0x77,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0x04,0xb2,0xc6,0xad,0xfe,0xbc,0xfe, 0xce,0xfe,0xdc,0x8d,0x94,0x01,0x38,0x01,0x4c,0x01,0x60,0xbc,0x00,0x04,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x25,0x00,0x39,0x00,0x4d,0x00,0x59,0x00,0x71,0xb3,0x21,0x0f,0x1e,0x44,0xb8,0x01,0x43,0xb2,0x14,0x14,0x0a,0xbb,0x01,0x43,0x00,0x30,0x00,0x3a,0x01,0x43,0xb2,0x1e,0x1e,0x26,0xb8,0x01,0x43,0x40,0x0b,0x00,0x30, 0x00,0x30,0x00,0x4e,0x54,0x4e,0x21,0x0f,0x2b,0xb8,0x01,0x44,0x40,0x09,0x60,0x49,0x70,0x49,0x02,0x49,0x49,0x51,0x57,0xbc,0x01,0x42,0x00,0x51,0x01,0x41,0x00,0x3f,0x01,0x44,0xb2,0x19,0x07,0x35,0xb8,0x01,0x44,0xb1,0x05,0x19,0x00,0x3f,0xe6,0x3f,0xe6,0x3f,0x3f,0x12,0x39,0x2f,0x5d,0xe6,0x39,0x39,0x01,0x2f,0x2f,0x12,0x39,0x39, 0x2f,0x2f,0x10,0xe6,0x33,0x2f,0xe6,0x10,0xe6,0x32,0x2f,0xe6,0x12,0x39,0x39,0x30,0x31,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x0e,0x03,0x17,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x13,0x34, 0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x01,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x03,0x76,0x47,0x7d,0xac,0x66,0x67,0xac,0x7c,0x44,0x1d,0x38,0x4f,0x32,0x24,0x3a,0x29,0x17,0x3e,0x6e,0x97,0x58,0x57,0x95,0x6f,0x3f,0x52,0x4d,0x32,0x51,0x39,0x1f,0xe8,0x24,0x40,0x57,0x34,0x37, 0x59,0x3f,0x22,0x23,0x40,0x59,0x35,0x37,0x59,0x3e,0x21,0x2d,0x1c,0x33,0x48,0x2b,0x29,0x46,0x34,0x1d,0x1e,0x34,0x46,0x28,0x28,0x46,0x35,0x1f,0xfc,0x29,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x01,0x97,0x5f,0xa0,0x76,0x42,0x42,0x76,0xa0,0x5f,0x34,0x6c,0x65,0x55,0x1d,0x1b,0x43,0x4e, 0x55,0x2c,0x4f,0x89,0x65,0x3a,0x39,0x65,0x89,0x50,0x5a,0x9e,0x35,0x1d,0x56,0x64,0x6c,0x26,0x35,0x5e,0x46,0x29,0x2b,0x48,0x5d,0x32,0x38,0x5e,0x43,0x26,0x25,0x43,0x5e,0x02,0xc3,0x28,0x47,0x35,0x1e,0x1d,0x33,0x48,0x2a,0x29,0x4a,0x3a,0x22,0x22,0x39,0x4b,0xfe,0xc7,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49, 0x02,0xb7,0x00,0x03,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0b,0x00,0x22,0x00,0x2e,0x00,0x5c,0xb5,0x0c,0x2c,0x0c,0x2c,0x1d,0x26,0xbb,0x01,0x43,0x00,0x17,0x00,0x11,0x01,0x43,0xb5,0x1d,0x1d,0x17,0x06,0x00,0x23,0xb8,0x01,0x44,0xb4,0x1a,0x1a,0x0e,0x29,0x22,0xb8,0xff,0xe0,0xb4,0x09,0x12,0x48,0x22,0x20,0xb8,0x01,0x44, 0xb2,0x0e,0x19,0x29,0xb8,0x01,0x44,0xb2,0x14,0x07,0x09,0xba,0x01,0x42,0x00,0x03,0x01,0x41,0x00,0x3f,0x3f,0x3f,0xe6,0x3f,0xf6,0xcd,0x2b,0x11,0x12,0x39,0x2f,0xe6,0x01,0x2f,0xc4,0x39,0x39,0x2f,0xe6,0x2f,0xe6,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x05,0x16,0x33,0x20, 0x00,0x11,0x10,0x02,0x23,0x22,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x33,0x14,0x02,0x23,0x22,0x27,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xb4,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x03,0x33,0x58,0x96,0x01,0x08,0x01,0x42,0xf6,0xd8,0xc4,0xfe,0xde,0xbc,0xad,0x61, 0x03,0xc5,0xa4,0x7b,0x6f,0x01,0x67,0x68,0x73,0x78,0x61,0x66,0x7c,0x7c,0x02,0xcd,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0xd7,0x29,0x01,0xc2,0x01,0x79,0x01,0x37,0x01,0x58,0xfe,0xf5,0xd3,0xca,0xf1,0x8f,0xe0,0xfe,0xdd,0x39,0x01,0xf8,0x91,0x81,0x75,0x99,0xb0,0x7c,0x63,0x91,0x00,0x05,0x00,0xbc, 0xff,0x2f,0x03,0xea,0x06,0x50,0x00,0x17,0x00,0x1e,0x00,0x22,0x00,0x26,0x00,0x2d,0x00,0x5d,0x40,0x34,0x1c,0x0d,0x1f,0x91,0x2c,0x24,0x24,0x20,0x2b,0x23,0x91,0x05,0x80,0x03,0x01,0x03,0x01,0x03,0x1d,0x20,0x91,0x14,0x16,0x00,0x09,0x7d,0x29,0x1d,0x1c,0x0c,0x2c,0x05,0x05,0x15,0x8c,0x21,0x25,0x02,0x03,0x16,0x29,0x16,0x00,0x10, 0x7d,0x1a,0x1a,0x2f,0x24,0x20,0x7e,0x00,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x17,0x33,0xed,0x17,0x32,0x2f,0xe1,0x00,0x2f,0xc6,0x33,0xed,0x32,0x3f,0xc6,0x5d,0x33,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x39,0x32,0x31,0x30,0x33,0x11,0x21,0x35,0x33,0x15,0x16,0x17,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15, 0x14,0x07,0x06,0x07,0x15,0x23,0x35,0x37,0x36,0x35,0x34,0x27,0x11,0x36,0x01,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0x13,0x36,0x35,0x34,0x27,0x11,0x36,0xbc,0x01,0x3a,0x68,0x93,0x5b,0x66,0x84,0x74,0x8a,0xa6,0x7a,0x6e,0xa4,0x68,0xfd,0x47,0xdc,0x5c,0xfe,0xaa,0x92,0x92,0x92,0xc6,0x46,0xa4,0x37,0x05,0x9a,0xb6,0xb7,0x09,0x51,0x5b, 0x92,0x7a,0xb4,0x26,0x04,0x11,0xb9,0x94,0xb8,0x72,0x68,0x09,0xd2,0xd1,0xde,0x46,0x7a,0xd8,0x20,0xfe,0x05,0x0b,0x01,0xf6,0xfd,0xfc,0x02,0x04,0x02,0x66,0xfe,0x31,0x01,0xcf,0xfe,0x73,0x43,0x79,0xab,0x1f,0xfe,0x45,0x10,0x00,0x00,0x02,0x00,0x48,0x02,0x34,0x02,0xa5,0x05,0xae,0x00,0x0a,0x00,0x12,0x00,0x1f,0x40,0x10,0x0b,0xe6, 0x06,0x27,0x0f,0xe6,0x00,0x29,0x08,0xcc,0x11,0x11,0x14,0x0d,0xcc,0x03,0x2f,0xed,0x12,0x39,0x2f,0xed,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x20,0x11,0x14,0x06,0x03,0x22,0x11,0x10,0x33,0x32,0x11,0x10,0x01,0x6d,0x8b,0x9a,0xa1,0x99,0x01,0x23,0xa3,0x87,0xa9,0xa6,0xa4,0x02,0x34,0xdb,0xd1,0xe5, 0xe9,0xfe,0x47,0xdb,0xe6,0x03,0x03,0xfe,0xaf,0xfe,0xc6,0x01,0x40,0x01,0x4b,0x00,0x00,0x02,0x00,0x49,0x02,0x34,0x02,0xa6,0x05,0xae,0x00,0x26,0x00,0x36,0x00,0x3c,0x40,0x23,0x04,0x10,0x14,0x10,0x02,0x27,0xe6,0x04,0x10,0x14,0x10,0x02,0x10,0x10,0x31,0x06,0xe6,0x24,0x27,0x31,0xe6,0x1a,0x29,0x01,0x01,0x1f,0x15,0xcc,0x34,0x34, 0x38,0x2c,0x0c,0xcc,0x1f,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x5d,0x31,0x30,0x01,0x15,0x2e,0x03,0x23,0x22,0x06,0x07,0x06,0x06,0x15,0x33,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x03,0x22,0x0e, 0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x63,0x0e,0x28,0x2b,0x2c,0x12,0x39,0x55,0x21,0x1f,0x2d,0x04,0x1d,0x6e,0x4e,0x3c,0x5f,0x42,0x23,0x2d,0x4f,0x6b,0x3d,0x3f,0x72,0x56,0x32,0x38,0x65,0x8c,0x54,0x2b,0x52,0xc1,0x22,0x3c,0x2c,0x1a,0x15,0x29,0x3a,0x25,0x4b,0x55,0x4d,0x05,0x8b,0x81,0x09,0x10,0x0c,0x07, 0x24,0x24,0x22,0x7f,0x61,0x32,0x41,0x27,0x47,0x63,0x3d,0x3d,0x68,0x4d,0x2b,0x31,0x63,0x99,0x67,0x75,0xb5,0x7c,0x40,0x12,0xfe,0x59,0x15,0x28,0x38,0x24,0x22,0x41,0x32,0x1e,0x5b,0x49,0x4e,0x5a,0x00,0x02,0x00,0x49,0x02,0x33,0x02,0xa6,0x05,0xae,0x00,0x27,0x00,0x39,0x00,0x3c,0x40,0x23,0x0b,0x0b,0x1b,0x0b,0x02,0x30,0xe6,0x0b, 0x0b,0x1b,0x0b,0x02,0x0b,0x0b,0x1f,0x28,0xe6,0x15,0x27,0x00,0xe6,0x1f,0x29,0x23,0x23,0x10,0x1a,0xcc,0x35,0x06,0x06,0x3b,0x2d,0xcc,0x10,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x11,0x39,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x5d,0xed,0x5d,0x31,0x30,0x01,0x32,0x3e,0x02,0x35,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34, 0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x1e,0x03,0x13,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x01,0x34,0x42,0x5e,0x3c,0x1b,0x04,0x0d,0x2b,0x37,0x42,0x24,0x3c,0x61,0x46,0x26,0x2a,0x4d,0x6c,0x41,0x40,0x72,0x55,0x32,0x30,0x5d,0x8a,0x5b,0x30,0x61,0x26,0x13, 0x2e,0x30,0x30,0x52,0x21,0x39,0x2a,0x18,0x52,0x45,0x20,0x3d,0x2f,0x1d,0x19,0x2c,0x3c,0x02,0xaa,0x33,0x5c,0x7e,0x4b,0x1c,0x2f,0x21,0x13,0x26,0x47,0x63,0x3c,0x3f,0x6a,0x4c,0x2a,0x33,0x65,0x96,0x64,0x69,0xb4,0x82,0x4a,0x17,0x16,0x7f,0x0b,0x13,0x0f,0x08,0x02,0x8e,0x17,0x2b,0x3f,0x28,0x4c,0x56,0x16,0x26,0x33,0x1d,0x2a,0x47, 0x32,0x1c,0x00,0x01,0x00,0x5d,0x02,0xcb,0x02,0x91,0x04,0xff,0x00,0x0b,0x00,0x1b,0x40,0x10,0x04,0x7f,0x07,0x9f,0x07,0x02,0x3f,0x07,0xdf,0x07,0xff,0x07,0x03,0x07,0x02,0x03,0x2f,0xcd,0x00,0x2f,0x5d,0x71,0xcd,0x31,0x30,0x01,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x02,0x91,0xe8,0x64,0xe8,0xe8,0x64,0xe8,0x03, 0xb3,0xe8,0xe8,0x64,0xe8,0xe8,0x00,0x01,0x00,0x5d,0x03,0xb3,0x02,0x91,0x04,0x17,0x00,0x03,0x00,0x1b,0x40,0x10,0x02,0x7f,0x01,0x9f,0x01,0x02,0x3f,0x01,0xdf,0x01,0xff,0x01,0x03,0x01,0x02,0x03,0x2f,0xcd,0x00,0x2f,0x5d,0x71,0xcd,0x31,0x30,0x13,0x21,0x15,0x21,0x5d,0x02,0x34,0xfd,0xcc,0x04,0x17,0x64,0x00,0x00,0x02,0x00,0x5d, 0x03,0x22,0x02,0x91,0x04,0xa8,0x00,0x03,0x00,0x07,0x00,0x21,0x40,0x11,0x03,0x40,0x00,0x80,0x07,0x0f,0x04,0x2f,0x04,0x3f,0x04,0x03,0x04,0x06,0x07,0x02,0x03,0x2f,0xcd,0x33,0x32,0x00,0x2f,0x5d,0xcd,0x1a,0xde,0x1a,0xcd,0x31,0x30,0x13,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x5d,0x02,0x34,0xfd,0xcc,0x02,0x34,0xfd,0xcc,0x03,0x86, 0x64,0x01,0x86,0x64,0x00,0x01,0x00,0xcc,0x01,0xce,0x02,0x06,0x05,0xee,0x00,0x09,0x00,0x1a,0x40,0x0d,0xdf,0x05,0x01,0x40,0x05,0x01,0x05,0x01,0x06,0x00,0x08,0xcd,0x03,0x2f,0xed,0xd4,0xc6,0x00,0x2f,0x2f,0x5d,0x5d,0x31,0x30,0x01,0x23,0x26,0x11,0x10,0x37,0x33,0x06,0x11,0x10,0x02,0x05,0x7f,0xba,0xba,0x80,0xbc,0x01,0xce,0xd4, 0x01,0x38,0x01,0x38,0xdc,0xe4,0xfe,0xd1,0xfe,0xd3,0x00,0x01,0x00,0x64,0x01,0xce,0x01,0x9e,0x05,0xee,0x00,0x09,0x00,0x1a,0x40,0x0d,0xdf,0x03,0x01,0x40,0x03,0x01,0x03,0x09,0x09,0x03,0x06,0xcd,0x01,0x2f,0xfd,0xd4,0xc6,0x00,0x2f,0x2f,0x5d,0x5d,0x31,0x30,0x00,0x11,0x10,0x27,0x33,0x16,0x11,0x10,0x07,0x23,0x01,0x20,0xbc,0x80, 0xba,0xba,0x7f,0x02,0xae,0x01,0x2d,0x01,0x2f,0xe4,0xdc,0xfe,0xc8,0xfe,0xc8,0xd4,0x00,0x02,0x00,0x5b,0x02,0xcd,0x01,0x05,0x06,0xeb,0x00,0x0b,0x00,0x0f,0x00,0x1c,0x40,0x0d,0x0d,0x24,0x00,0x40,0x06,0x80,0x0e,0x03,0x09,0x0c,0xc2,0x03,0x0d,0x2f,0xc4,0xfd,0xc4,0x00,0x3f,0x1a,0xdc,0x1a,0xcd,0x3f,0x31,0x30,0x13,0x22,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x23,0x11,0x33,0xaf,0x25,0x2f,0x2f,0x25,0x26,0x30,0x30,0x19,0x80,0x80,0x06,0x54,0x2b,0x21,0x1f,0x2c,0x2c,0x1f,0x20,0x2c,0xfc,0x79,0x02,0xcf,0x00,0xff,0xff,0x00,0x68,0x03,0x74,0x02,0x92,0x06,0xda,0x02,0x07,0x00,0xf1,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x81,0x03,0x5f,0x02,0x8e, 0x06,0xda,0x02,0x07,0x00,0xf2,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x50,0x03,0x74,0x01,0xc2,0x06,0xdc,0x02,0x07,0x00,0xf0,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x48,0x03,0x60,0x02,0xa5,0x06,0xda,0x02,0x07,0x08,0x8d,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x2f,0x03,0x74,0x02,0xaa,0x06,0xc6,0x02,0x07,0x02,0x38,0x00,0x00,0x01,0x2c, 0xff,0xff,0x00,0x7b,0x03,0x5f,0x02,0x8a,0x06,0xca,0x02,0x07,0x02,0x39,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x49,0x03,0x60,0x02,0xa6,0x06,0xda,0x02,0x07,0x08,0x8e,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x4d,0x03,0x74,0x02,0xa0,0x06,0xd0,0x02,0x07,0x02,0x3a,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x41,0x03,0x60,0x02,0xad,0x06,0xda, 0x02,0x07,0x02,0x3b,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x49,0x03,0x5f,0x02,0xa6,0x06,0xda,0x02,0x07,0x08,0x8f,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x5d,0x03,0xf7,0x02,0x91,0x06,0x2b,0x02,0x07,0x08,0x90,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x5d,0x04,0xdf,0x02,0x91,0x05,0x43,0x02,0x07,0x08,0x91,0x00,0x00,0x01,0x2c,0xff,0xff, 0x00,0x5d,0x04,0x4e,0x02,0x91,0x05,0xd4,0x02,0x07,0x08,0x92,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0xcc,0x02,0xfa,0x02,0x06,0x07,0x1a,0x02,0x07,0x08,0x93,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x64,0x02,0xfa,0x01,0x9e,0x07,0x1a,0x02,0x07,0x08,0x94,0x00,0x00,0x01,0x2c,0xff,0xff,0x00,0x48,0xfe,0xfa,0x02,0xa5,0x02,0x74,0x03,0x07, 0x08,0x8d,0x00,0x00,0xfc,0xc6,0x00,0x0e,0xb7,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x50,0xff,0x0e,0x01,0xc2,0x02,0x76,0x03,0x07,0x00,0xf0,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x68,0xff,0x0e,0x02,0x92,0x02,0x74, 0x03,0x07,0x00,0xf1,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x81,0xfe,0xf9,0x02,0x8e,0x02,0x74,0x03,0x07,0x00,0xf2,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x2f,0xff,0x0e,0x02,0xaa,0x02,0x60, 0x03,0x07,0x02,0x38,0x00,0x00,0xfc,0xc6,0x00,0x0e,0xb7,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x7b,0xfe,0xf9,0x02,0x8a,0x02,0x64,0x03,0x07,0x02,0x39,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x49,0xfe,0xfa,0x02,0xa6, 0x02,0x74,0x03,0x07,0x08,0x8e,0x00,0x00,0xfc,0xc6,0x00,0x0e,0xb7,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x4d,0xff,0x0e,0x02,0xa0,0x02,0x6a,0x03,0x07,0x02,0x3a,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x41,0xfe,0xfa, 0x02,0xad,0x02,0x74,0x03,0x07,0x02,0x3b,0x00,0x00,0xfc,0xc6,0x00,0x11,0x40,0x09,0x02,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x49,0xfe,0xf9,0x02,0xa6,0x02,0x74,0x03,0x07,0x08,0x8f,0x00,0x00,0xfc,0xc6,0x00,0x0e,0xb7,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d, 0x35,0x35,0xff,0xff,0x00,0x5d,0xff,0x91,0x02,0x91,0x01,0xc5,0x03,0x07,0x08,0x90,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x5d,0x00,0x79,0x02,0x91,0x00,0xdd,0x03,0x07,0x08,0x91,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0x5d,0xff,0xe8,0x02,0x91,0x01,0x6e,0x03,0x07,0x08,0x92,0x00,0x00,0xfc,0xc6,0x00,0x0e,0xb7,0x01,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xcc,0xfe,0x94,0x02,0x06,0x02,0xb4,0x03,0x07,0x08,0x93,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00, 0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x64,0xfe,0x94,0x01,0x9e,0x02,0xb4,0x03,0x07,0x08,0x94,0x00,0x00,0xfc,0xc6,0x00,0x0c,0xb6,0x00,0x60,0x00,0x70,0x00,0x02,0x00,0x00,0x11,0x5d,0x35,0x00,0x02,0x00,0xbc,0xfe,0x7e,0x06,0x12,0x07,0x4e,0x00,0x17,0x00,0x24,0x00,0x77,0x40,0x16,0x24,0xc4,0x18,0x1e,0xc4,0x1f,0x1f,0x00,0x0c,0x0f, 0x04,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7e,0x0e,0xb8,0xff,0xfe,0x40,0x17,0x0b,0x06,0x4d,0x0e,0x04,0x03,0x40,0x01,0x01,0x00,0x04,0x0c,0x06,0x4d,0x00,0x08,0x0b,0x06,0x4d,0x00,0x7e,0x16,0x05,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x05,0xb8,0xff,0xdc,0x40,0x11,0x0b,0x06,0x4d,0x05,0x24,0x1e,0x80,0x21,0xda,0x1b,0x17, 0x03,0x00,0x91,0x05,0x12,0x03,0x00,0x2f,0x3f,0xed,0x3f,0xd6,0xed,0x1a,0xcc,0x32,0x01,0x2f,0x2b,0x2b,0x33,0xf1,0x2b,0x2b,0xc1,0x2f,0x1a,0xcd,0x39,0x2f,0x2b,0xe1,0x2b,0x2b,0x32,0x12,0x39,0x2f,0xfd,0xd4,0xed,0x31,0x30,0x25,0x33,0x03,0x23,0x13,0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x01,0x23,0x11,0x33,0x11,0x14,0x07,0x33,0x36, 0x37,0x01,0x33,0x03,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x05,0x40,0xd2,0xb8,0xc1,0xab,0xac,0x0a,0x06,0x13,0x1b,0xfd,0x1e,0xd0,0xa8,0x08,0x04,0x16,0x22,0x02,0xd0,0xd8,0xd4,0x0f,0xc5,0x94,0x98,0xbf,0x09,0xa2,0x0e,0xb2,0x50,0x68,0x0c,0x96,0xfd,0xe8,0x01,0x82,0x04,0x0c,0x8c,0x39,0x31,0x29,0xfb,0x89, 0x05,0x9a,0xfc,0x0e,0xa2,0x31,0x2c,0x34,0x04,0x65,0x01,0xb4,0x8d,0xa3,0xa3,0x8d,0xbc,0x63,0x59,0x00,0x00,0x02,0x00,0xa6,0xfe,0x8b,0x04,0xda,0x05,0xf2,0x00,0x11,0x00,0x1e,0x00,0x49,0x40,0x0a,0x1e,0xc4,0x12,0x18,0xc4,0x19,0x19,0x01,0x05,0x08,0xb8,0x01,0x2e,0xb6,0x07,0x00,0x11,0x0f,0x0f,0x40,0x0e,0xb8,0x01,0x2e,0x40,0x0f, 0x0c,0x01,0x11,0x1e,0x18,0x80,0x1b,0xda,0x15,0x0d,0x0f,0x0e,0xec,0x01,0x15,0x00,0x3f,0xed,0x3f,0xd6,0xed,0x1a,0xcc,0x32,0x2f,0x01,0x2f,0x33,0xf1,0x1a,0xc9,0x2f,0xcd,0x39,0x2f,0xe1,0x32,0x12,0x39,0x2f,0xfd,0xd4,0xed,0x31,0x30,0x21,0x23,0x11,0x06,0x07,0x01,0x23,0x11,0x33,0x11,0x36,0x37,0x01,0x33,0x11,0x33,0x03,0x23,0x13, 0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x04,0x19,0xad,0x16,0x2d,0xfe,0x27,0xaa,0x96,0x0c,0x28,0x01,0xe6,0xaa,0xda,0xb0,0xb4,0x4e,0x0f,0xc5,0x94,0x98,0xbf,0x09,0xa2,0x0e,0xb2,0x50,0x68,0x0c,0x03,0x31,0x2b,0x4e,0xfd,0x48,0x04,0x00,0xfc,0xd9,0x1d,0x46,0x02,0xc4,0xfc,0x96,0xfd,0xf5,0x07,0x67,0x8d,0xa3, 0xa3,0x8d,0xbc,0x63,0x59,0x00,0x00,0x01,0x00,0x10,0xfe,0x7e,0x05,0x76,0x05,0x9a,0x00,0x16,0x00,0x62,0x40,0x19,0x0b,0x18,0x0b,0x00,0x4d,0x04,0x03,0x01,0x01,0x00,0x08,0x0b,0x0d,0x06,0x4c,0x00,0x7e,0x07,0x15,0x05,0x28,0x0d,0x06,0x4d,0x05,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x05,0xb8,0xff,0xda,0x40,0x1a,0x0b,0x06,0x4d,0x20, 0x05,0x01,0x05,0x15,0x05,0x15,0x18,0x0f,0x06,0x91,0x16,0x03,0x0f,0x11,0x91,0x0c,0x13,0x00,0x91,0x05,0x12,0x03,0x00,0x2f,0x3f,0xed,0x3f,0xfd,0xc6,0x3f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x2b,0x2b,0x2b,0x11,0x33,0xf1,0x2b,0xc1,0x2f,0xcd,0x39,0x31,0x30,0x00,0x2b,0x25,0x33,0x03,0x23,0x13,0x23,0x11,0x21,0x02,0x02, 0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x12,0x13,0x21,0x04,0xa4,0xd2,0xb8,0xc1,0xab,0xac,0xfe,0x72,0x45,0x50,0x52,0x8c,0x62,0x4f,0x3a,0x33,0x3e,0x3e,0x6d,0x71,0x45,0x02,0xc2,0x96,0xfd,0xe8,0x01,0x82,0x05,0x02,0xfd,0xe2,0xfe,0x40,0xd4,0x67,0x15,0x9e,0x1d,0x94,0x02,0x6e,0x02,0x19,0x00,0x01,0x00,0x10,0xfe,0x8b, 0x04,0x6c,0x04,0x00,0x00,0x12,0x00,0x36,0x40,0x1c,0x07,0xed,0x11,0x04,0x03,0x01,0x01,0x00,0x84,0x11,0x0d,0x05,0x05,0x14,0x0d,0x06,0x95,0x12,0x0f,0x0f,0x95,0x0a,0x15,0x00,0xec,0x05,0x15,0x03,0x00,0x2f,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x01,0x2f,0x12,0x39,0x2f,0x12,0x39,0xf1,0xc1,0x2f,0xcd,0x39,0x10,0xed,0x31,0x30,0x25,0x33, 0x03,0x23,0x13,0x23,0x11,0x23,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x03,0x91,0xdb,0xb0,0xb4,0xa3,0xbd,0xee,0x29,0xc7,0xa8,0x33,0x25,0x23,0x29,0xdc,0x3f,0x02,0x1a,0x96,0xfd,0xf5,0x01,0x75,0x03,0x75,0xfe,0x0f,0xfe,0x6e,0x0e,0x8d,0x12,0x03,0x85,0x00,0x01,0x00,0xbc,0xfe,0x7e,0x05,0xc4,0x05,0x9a,0x00,0x0f, 0x00,0x4c,0x40,0x17,0x02,0x06,0x91,0x40,0x0b,0x0a,0x07,0x0b,0x91,0x2b,0x30,0x0d,0x0a,0x03,0x0f,0x91,0x04,0x40,0x04,0x07,0x03,0x00,0x01,0xb8,0x01,0x2c,0x40,0x0e,0x02,0x80,0x00,0x00,0x0f,0x7e,0x0c,0x05,0x05,0x11,0x0b,0x07,0x7e,0x08,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xf1,0xc1,0x2f,0x1a,0xdd,0xe1,0x12,0x39,0x00,0x2f,0x33, 0x1a,0x10,0xed,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x2f,0x31,0x30,0x25,0x03,0x23,0x13,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x05,0xc4,0xb8,0xc1,0xab,0xac,0xfd,0x1a,0xa8,0xa8,0x02,0xe6,0xa8,0x96,0xfd,0xe8,0x01,0x82,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfa,0xfc,0x00,0x01,0x00,0xa6, 0xfe,0x8b,0x04,0xd3,0x04,0x00,0x00,0x0f,0x00,0x4a,0x40,0x14,0x06,0x95,0x40,0x0b,0x0a,0x07,0x0b,0x95,0x2b,0x30,0x0d,0x0a,0x0f,0x02,0x0f,0xec,0x04,0x04,0x07,0x01,0xb8,0x01,0x2c,0x40,0x10,0x02,0x03,0x00,0x00,0x03,0x03,0x0f,0x84,0x0c,0x05,0x05,0x11,0x0b,0x06,0x84,0x08,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xe1,0x32,0x2f,0x33, 0x2f,0x10,0xdd,0xe1,0x00,0x2f,0x33,0x10,0xed,0x2f,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x31,0x30,0x25,0x03,0x23,0x13,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x04,0xd3,0xb0,0xb4,0xa3,0xbe,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0xa4,0x96,0xfd,0xf5,0x01,0x75,0x01,0xd1,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4, 0xfc,0x96,0x00,0x01,0x00,0xbc,0xfe,0x7e,0x07,0x44,0x05,0x9a,0x00,0x1f,0x00,0x2b,0x40,0x15,0x04,0x03,0x01,0x01,0x00,0x7e,0x1e,0x05,0x05,0x21,0x17,0x14,0x7e,0x15,0x1f,0x03,0x00,0x91,0x05,0x12,0x03,0x00,0x2f,0x3f,0xed,0x3f,0x01,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xf1,0xc1,0x2f,0xcd,0x39,0x31,0x30,0x25,0x33,0x03,0x23,0x13, 0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x06,0x72,0xd2,0xb8,0xc1,0xab,0xab,0x0e,0x04,0x18,0x13,0xfe,0x16,0x52,0xfe,0x17,0x15,0x16,0x04,0x08,0xa2,0xde,0x01,0xb8,0x33,0x0f,0x06,0x2b,0x1a,0x01,0xc1,0xd2,0x96,0xfd,0xe8,0x01,0x82, 0x03,0xc2,0x72,0xa5,0x61,0x2a,0xfb,0xb2,0x04,0x46,0x30,0x63,0x56,0xc3,0xfc,0x40,0x05,0x9a,0xfc,0x18,0x73,0x39,0x76,0x3a,0x03,0xe4,0x00,0x01,0x00,0xa6,0xfe,0x8b,0x05,0xd3,0x04,0x00,0x00,0x17,0x00,0x29,0x40,0x14,0x04,0x03,0x01,0x16,0x00,0x84,0x05,0x05,0x19,0x11,0x0e,0xed,0x0f,0x17,0x0f,0x00,0xec,0x05,0x15,0x03,0x00,0x2f, 0x3f,0xed,0x3f,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xe1,0x33,0xdd,0xcd,0x39,0x31,0x30,0x25,0x33,0x03,0x23,0x13,0x23,0x11,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x37,0x01,0x33,0x04,0xf8,0xdb,0xb0,0xb4,0xa3,0xbc,0x16,0x2e,0xff,0x00,0x93,0xfe,0xf8,0x15,0x2f,0x8d,0xd1,0x01,0x0e,0x1d,0x2d,0x49, 0x01,0x06,0xda,0x96,0xfd,0xf5,0x01,0x75,0x03,0x4c,0x40,0x7c,0xfd,0x70,0x02,0x90,0x35,0x87,0xfc,0xb4,0x04,0x00,0xfd,0x64,0x49,0x81,0xc6,0x02,0xa0,0x00,0x00,0x01,0x00,0x5a,0x01,0xfa,0x03,0xf6,0x02,0x7b,0x00,0x03,0x00,0x0e,0xb4,0x03,0x02,0x01,0xeb,0x02,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0xf6, 0xfc,0x64,0x03,0x9c,0x01,0xfa,0x81,0x00,0x00,0x02,0x00,0x6e,0x03,0xf4,0x02,0xa0,0x05,0xb2,0x00,0x03,0x00,0x07,0x00,0x1c,0x40,0x0e,0x05,0xb4,0x07,0x01,0xb4,0x03,0x06,0xb3,0x07,0x04,0x02,0xb3,0x03,0x04,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x13,0x23,0x03,0x21,0x13,0x23,0x03,0x01,0x04,0x6c,0x76, 0x8c,0x01,0xc3,0x6f,0x76,0x8c,0x05,0xb2,0xfe,0x42,0x01,0xbe,0xfe,0x42,0x01,0xbe,0x00,0x03,0x00,0x8d,0x03,0xdb,0x03,0x9d,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x20,0x40,0x0e,0x08,0x0a,0x04,0x06,0x00,0x02,0x0a,0x06,0x02,0xb3,0x0b,0x07,0x03,0x03,0x00,0x3f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcd,0x2f,0xcd,0x2f,0xcd, 0x31,0x30,0x01,0x03,0x23,0x13,0x21,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x01,0x69,0x69,0x73,0x55,0x02,0xbb,0x6a,0x74,0x56,0x93,0x69,0x73,0x55,0x05,0x9a,0xfe,0x41,0x01,0xbf,0xfe,0x41,0x01,0xbf,0xfe,0x41,0x01,0xbf,0x00,0x03,0x00,0xe8,0x00,0x69,0x04,0x94,0x04,0x3a,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x43,0x40,0x1b,0x02,0x01, 0xbe,0x59,0x0a,0x02,0x0e,0x59,0x0a,0x09,0xbe,0x59,0x06,0x05,0xbe,0x59,0x0a,0x06,0x42,0x06,0x4f,0x0a,0x01,0x0a,0x03,0x0b,0x04,0xb8,0xff,0xe0,0xb6,0x0c,0x06,0x4d,0x04,0x02,0x0a,0x05,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x05,0x2f,0x2b,0x33,0x33,0x2f,0x2b,0x33,0x33,0x00,0x2f,0x5d,0xc6,0x2b,0x2b,0x2b,0x2b,0x2b,0x31,0x30,0x25, 0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x04,0x94,0xfc,0x54,0x03,0xac,0xfc,0x54,0x03,0xac,0xfc,0x54,0x03,0xac,0x69,0x84,0x02,0xc9,0x84,0xfd,0xd9,0x84,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x03,0xdf,0x05,0xb2,0x00,0x15,0x00,0x1f,0x40,0x0f,0x0b,0x15,0x15,0x17,0x10,0x7d,0x05,0x0d,0x91,0x08,0x04,0x13,0x91,0x02, 0x13,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xe1,0x11,0x39,0x2f,0x33,0x31,0x30,0x25,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x37,0x03,0xdf,0x85,0xc7,0xff,0x00,0xfe,0xcb,0x01,0x5b,0x01,0x0b,0xab,0x70,0x7c,0x96,0xc7,0xf8,0xe7,0xbc,0xaf,0x7f,0x3c,0x54,0x01,0x8a,0x01, 0x40,0x01,0x58,0x01,0xa8,0x3b,0xb3,0x56,0xfe,0xb6,0xfe,0xec,0xfe,0xfa,0xfe,0xc9,0x60,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x05,0xd2,0x05,0x9a,0x00,0x25,0x00,0x32,0x40,0x1a,0x0b,0x7e,0x09,0x0c,0x0c,0x27,0x00,0x23,0x7e,0x24,0x04,0x1e,0x10,0x03,0x25,0x18,0x18,0x24,0x25,0x03,0x24,0x12,0x0c,0x12,0x09,0x03,0x00,0x3f,0x3f,0x3f, 0x3f,0x12,0x39,0x2f,0x12,0x17,0x39,0x01,0x2f,0xe1,0x32,0x12,0x39,0x2f,0x33,0xe1,0x31,0x30,0x01,0x01,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x11,0x23,0x11,0x34,0x36,0x37,0x23,0x0e,0x03,0x07,0x01,0x23,0x01,0x2e,0x03,0x27,0x23,0x16,0x16,0x15,0x11,0x23,0x11,0x01,0x95,0x01,0x74,0x19,0x21,0x08,0x06,0x0a,0x1d,0x1a,0x01, 0x64,0xdc,0xa7,0x07,0x07,0x04,0x07,0x18,0x1b,0x16,0x05,0xfe,0x8f,0x52,0xfe,0x90,0x04,0x19,0x1a,0x17,0x05,0x04,0x04,0x04,0xa2,0x05,0x9a,0xfd,0x56,0x2d,0x4e,0x1d,0x1e,0x50,0x2e,0x02,0xa6,0xfa,0x66,0x03,0xc2,0x39,0x91,0x53,0x18,0x3b,0x37,0x2c,0x0b,0xfd,0x58,0x02,0xa6,0x0c,0x2d,0x37,0x3a,0x19,0x2b,0x92,0x62,0xfc,0x40,0x05, 0x9a,0x00,0x00,0x01,0x00,0xa6,0xfe,0x2a,0x04,0xf8,0x04,0x00,0x00,0x13,0x00,0x32,0x40,0x1a,0x13,0x84,0x12,0x02,0x02,0x15,0x0d,0x09,0xed,0x0c,0x12,0x0f,0x10,0x09,0x02,0x03,0x0c,0x06,0x06,0x01,0x0c,0x0f,0x0b,0x1b,0x01,0x15,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x17,0x39,0x3f,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0xe1, 0x31,0x30,0x21,0x23,0x11,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x37,0x01,0x33,0x04,0xf8,0xa2,0x16,0x2e,0xff,0x00,0x93,0xfe,0xf8,0x15,0x2f,0x8d,0xd1,0x01,0x0e,0x1d,0x2d,0x49,0x01,0x06,0xda,0x03,0x4c,0x2c,0x54,0xfe,0x42,0x01,0xbe,0x24,0x5c,0xfa,0xde,0x05,0xd6,0xfe,0x33,0x32,0x59,0x89,0x01, 0xcf,0x00,0x00,0x01,0xff,0xdc,0xfe,0x68,0x00,0x24,0x06,0xd6,0x00,0x03,0x00,0x11,0xb3,0x03,0x02,0x1b,0x01,0xb9,0x04,0xf1,0x00,0x02,0x2f,0xed,0x00,0x3f,0x2f,0x31,0x30,0x13,0x11,0x23,0x11,0x24,0x48,0x06,0xd6,0xf7,0x92,0x08,0x6e,0x00,0x00,0x01,0xff,0x25,0xfe,0x68,0x00,0xdb,0x06,0xd6,0x00,0x0e,0x00,0x44,0x40,0x0c,0x07,0x06, 0x03,0x04,0x01,0x09,0x0a,0x0d,0x0c,0x08,0x0b,0x00,0xb8,0x04,0xf1,0x40,0x13,0x05,0x01,0x0a,0x09,0x07,0x0c,0x0d,0x08,0x0b,0x05,0x02,0x0e,0x05,0x04,0x03,0x06,0x07,0x01,0x1b,0x00,0x3f,0x2f,0x33,0xdc,0x32,0x17,0x39,0xc4,0x32,0x10,0xc4,0x32,0x01,0x2f,0x33,0xfd,0x32,0x39,0xde,0x32,0xc4,0x32,0x10,0xde,0x32,0xc4,0x32,0x31,0x30, 0x13,0x23,0x11,0x07,0x27,0x37,0x27,0x37,0x17,0x37,0x17,0x07,0x17,0x07,0x27,0x24,0x48,0x86,0x31,0xab,0xab,0x31,0xaa,0xaa,0x31,0xab,0xab,0x31,0x86,0xfe,0x68,0x07,0x43,0x88,0x31,0xa9,0xa8,0x31,0xab,0xab,0x31,0xa8,0xa9,0x31,0x88,0x00,0x00,0x01,0xff,0xdc,0xfe,0x68,0x01,0xaf,0x06,0xd6,0x00,0x0a,0x00,0x30,0xb7,0x0a,0x09,0x03, 0x08,0x00,0x01,0x02,0x07,0xb8,0x04,0xf1,0xb4,0x04,0x02,0x01,0x00,0x04,0xb8,0x04,0xf1,0xb4,0x08,0x09,0x0a,0x05,0x1b,0x00,0x3f,0x2f,0x33,0xdd,0xfd,0x39,0xcc,0x32,0x01,0x2f,0xed,0xde,0x32,0xcd,0x39,0x39,0xc4,0x32,0x31,0x30,0x01,0x07,0x27,0x37,0x21,0x11,0x23,0x11,0x21,0x27,0x37,0x01,0xaf,0xd9,0x31,0x89,0xfe,0xf6,0x48,0x01, 0x52,0x89,0x31,0x05,0xff,0xd6,0x31,0x82,0xf8,0x8c,0x07,0xbb,0x82,0x31,0x00,0x01,0xfe,0x51,0xfe,0x68,0x00,0x24,0x06,0xd6,0x00,0x0a,0x00,0x32,0xb7,0x03,0x09,0x06,0x05,0x04,0x07,0x08,0x0a,0xb8,0x04,0xf1,0xb5,0x02,0x06,0x09,0x04,0x05,0x02,0xb8,0x04,0xf1,0xb4,0x09,0x08,0x07,0x00,0x1b,0x00,0x3f,0x2f,0x33,0xdd,0xfd,0xcc,0x32, 0x12,0x39,0x01,0x2f,0xed,0xdc,0x32,0xc4,0x32,0xcd,0x39,0x39,0x31,0x30,0x13,0x23,0x11,0x21,0x17,0x07,0x27,0x37,0x17,0x07,0x21,0x24,0x48,0xfe,0xf6,0x89,0x31,0xd9,0xd9,0x31,0x89,0x01,0x52,0xfe,0x68,0x07,0x74,0x82,0x31,0xd6,0xd7,0x31,0x82,0x00,0x00,0x01,0x00,0xab,0xff,0xf2,0x02,0x01,0x05,0xec,0x00,0x0e,0x00,0x1b,0xb1,0x0e, 0x09,0xb8,0x05,0x0a,0xb2,0x06,0x07,0x0e,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x01,0x2f,0xed,0xc4,0x31,0x30,0x05,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x02,0x01,0x14,0x66,0x7f,0x45,0x18,0x9c,0x0a,0x26,0x4a,0x40,0x0e,0x3e,0x66,0x82,0x45,0x04,0x8f,0xfb,0xac,0x42,0x60,0x3f,0x1e,0x00, 0xff,0xff,0x00,0x49,0xff,0xf2,0x02,0x01,0x07,0xe9,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x09,0x7e,0x00,0x00,0xff,0xff,0xff,0xa2,0xff,0xf2,0x02,0x65,0x07,0x30,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x09,0x37,0x00,0x00,0xff,0xff,0x00,0x49,0xfd,0xfe,0x02,0x01,0x05,0xec,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x09,0x7f, 0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x01,0xf2,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9a,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9a,0x05,0xca,0x02,0x26,0x0e,0x6f, 0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x9c,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0xfe,0xab,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x03,0x54,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0xa3,0xff,0xa7,0x00,0x01,0xff,0xba,0xff,0xf2, 0x04,0x7c,0x03,0x0f,0x00,0x28,0x00,0x2c,0x40,0x0a,0x0c,0x21,0x2a,0x15,0x21,0x0c,0x20,0x03,0x00,0x12,0xb8,0x04,0xff,0xb4,0x2f,0x19,0x01,0x19,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x12,0x17,0x39,0x01,0x2f,0x12,0x39,0x39,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37, 0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x0e,0x05,0x23,0x23,0x23,0x23,0x23,0x3b,0x7b,0xe0,0xcf,0xbf,0x5a,0x39,0x60,0x68,0x7c,0x57,0x4e,0x7e,0x33,0x37,0x84,0x4e,0x50,0x7c,0x6a,0x61,0x69,0x7a,0x4e,0x20,0x2b,0x73,0x92,0xb1,0xd0,0xf1,0x88,0x0e,0x34,0x20,0x20,0x33,0x37,0x59,0x70,0x39, 0x05,0x1b,0x35,0x2b,0x1b,0x14,0x10,0x9d,0x12,0x17,0x1d,0x2b,0x32,0x2c,0x1e,0x01,0xc8,0x0a,0x42,0x59,0x62,0x53,0x36,0x00,0x00,0x01,0x00,0x7e,0xfd,0xff,0x04,0xad,0x03,0x54,0x00,0x40,0x00,0x5c,0xb9,0x00,0x03,0x05,0x0b,0x40,0x0c,0x0f,0x00,0x0f,0x1c,0x0f,0x35,0x35,0x0f,0x1c,0x03,0x09,0x14,0xb8,0x05,0x0a,0xb3,0x25,0x09,0x03, 0x0f,0xb8,0x04,0xfb,0xb5,0x40,0x39,0x2d,0x2d,0x20,0x32,0xbb,0x04,0xff,0x00,0x39,0x00,0x19,0x04,0xfc,0xb6,0x1f,0x20,0x2f,0x20,0x02,0x20,0x08,0xba,0x04,0xfb,0x00,0x09,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0xe4,0x32,0x01,0x2f,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed, 0x31,0x30,0x01,0x06,0x06,0x07,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x04,0x0c,0x22,0x40,0x1e,0x05,0x26,0x46,0x69,0x47,0x18,0x63, 0x8f,0x5f,0x31,0x05,0x8d,0xc0,0x75,0x32,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0x02,0x01,0x09,0x12,0x09,0x60,0x7e,0x49,0x1d,0xa7,0x3f,0x75,0xa6,0x67,0x33,0x6e,0x77,0x80, 0x45,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x7c,0x04,0x61,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x03,0xb1,0xff,0xff, 0x00,0x7e,0xfd,0xff,0x04,0xad,0x04,0xda,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x2a,0x00,0x01,0xff,0xba,0xff,0xf2,0x05,0xf4,0x03,0x0f,0x00,0x42,0x00,0x60,0xb1,0x18,0x00,0xbb,0x05,0x0a,0x00,0x40,0x00,0x0d,0x05,0x0a,0x40,0x09,0x0a,0x21,0x33,0x40,0x0a,0x40,0x0a,0x44,0x36,0xb8,0x05,0x0a,0xb6,0x33, 0x41,0x2f,0x35,0x01,0x35,0x26,0xba,0x05,0x03,0x00,0x1d,0x05,0x03,0xb7,0x3b,0x2e,0x2e,0x2d,0x2d,0x21,0x18,0x05,0xba,0x04,0xfb,0x00,0x12,0x05,0x03,0xb3,0x2f,0x0b,0x01,0x0b,0x00,0x2f,0x5d,0x3f,0xed,0x39,0x39,0x32,0x11,0x33,0x11,0x33,0x3f,0x3f,0x2f,0x5d,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10, 0xed,0x39,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x03,0xf3,0x0b,0x27, 0x48,0x3e,0x26,0x40,0x2e,0x19,0x9c,0x39,0x5d,0x77,0x3f,0x2c,0x4f,0x42,0x34,0x12,0x04,0x1a,0x42,0x47,0x48,0x21,0x64,0x77,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0x0b,0x24,0x44,0x39,0x24,0x43,0x33,0x1f,0x9c,0x01,0x98,0x43,0x60,0x3e,0x1e,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe, 0x37,0x6c,0x85,0x4a,0x19,0x0d,0x1c,0x2f,0x23,0x23,0x2f,0x1d,0x0c,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0x0b,0xc9,0x41,0x5f,0x3e,0x1e,0x10,0x2a,0x48,0x38,0x01,0x0b,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4,0x05,0x1f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xa4,0x03,0x57, 0x00,0x02,0xff,0xba,0xff,0xea,0x07,0x4b,0x03,0x3c,0x00,0x39,0x00,0x4b,0x00,0x52,0xb9,0x00,0x2a,0x05,0x0a,0x40,0x0d,0x3f,0x49,0x1e,0x1e,0x15,0x3f,0x3f,0x4d,0x16,0x15,0x00,0x15,0x31,0xba,0x05,0x03,0x00,0x44,0x04,0xfb,0x40,0x0f,0x2f,0x25,0x01,0x25,0x2f,0x15,0x01,0x15,0x49,0x49,0x3a,0x3a,0x1e,0x1e,0x0c,0xba,0x04,0xfb,0x00, 0x05,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x33,0x11,0x33,0x2f,0x2f,0x5d,0x2f,0x5d,0xed,0x3f,0x12,0x39,0x01,0x2f,0xcd,0x12,0x39,0x2f,0x12,0x39,0x10,0xcd,0x10,0xed,0x31,0x30,0x25,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x17,0x3e,0x05,0x33,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x24,0x26,0x26,0x27,0x26,0x26,0x27,0x25,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x16,0x16,0x01,0x98,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x27,0x42,0x30,0x1c,0x0f,0x0d,0x9a,0x0b,0x0d,0x08,0x03,0x11,0x21,0x36,0x28,0x18,0x4c,0x67,0x81,0x9a,0xb4, 0x65,0x79,0xae,0x70,0x36,0x2d,0x52,0x71,0x88,0x9a,0x52,0xb3,0xff,0x00,0xaf,0x69,0x1b,0x23,0x2e,0x14,0x03,0x61,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x6e,0xbc,0x97,0x6e,0x1f,0x5c,0xee,0x6d,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x18,0x27,0x33,0x1b,0x30,0x6e,0x3d,0x3f,0x72,0x3a,0x17,0x2b,0x22,0x15,0x02,0x41,0x96,0x95, 0x8b,0x6a,0x40,0x4b,0x80,0xab,0x60,0x5d,0x80,0x55,0x2f,0x16,0x05,0x01,0x06,0x0d,0x0c,0x0f,0x31,0x23,0x26,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0x5c,0x92,0xb5,0x5a,0x02,0x01,0x00,0x00,0x01,0x00,0xb9,0x01,0xac,0x02,0x89,0x03,0x7c,0x00,0x13,0x00,0x13,0xb6,0x0f,0x05,0x05,0x15,0x14,0x00,0x0a,0x00,0x2f,0xcd,0x11,0x12,0x01, 0x39,0x2f,0xcd,0x31,0x30,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0xa3,0x29,0x52,0x45,0x2a,0x2b,0x44,0x52,0x29,0x29,0x51,0x43,0x29,0x29,0x43,0x51,0x01,0xac,0x29,0x43,0x51,0x29,0x28,0x53,0x44,0x2b,0x2a,0x45,0x52,0x29,0x29,0x51,0x43,0x29,0x00,0x01,0x00,0x2b,0x00,0x00,0x01,0x56, 0x05,0x9a,0x00,0x0f,0x00,0x19,0xbc,0x00,0x08,0x05,0x0a,0x00,0x09,0x00,0x08,0x04,0xe6,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x3f,0x01,0x2f,0xed,0x31,0x30,0x13,0x1e,0x05,0x15,0x11,0x23,0x11,0x34,0x26,0x26,0x02,0x27,0xcb,0x17,0x26,0x1f,0x18,0x0f,0x08,0x9c,0x11,0x23,0x36,0x25,0x05,0x9a,0x62,0xad,0xa2,0x9f,0xaa,0xb9,0x6c, 0xfe,0x85,0x01,0x73,0x94,0xff,0xf8,0x01,0x03,0x99,0x00,0x01,0x00,0x2b,0x00,0x00,0x03,0x50,0x05,0x9a,0x00,0x0f,0x00,0x28,0xb5,0x03,0x0a,0x01,0x01,0x11,0x09,0xbd,0x05,0x0a,0x00,0x0a,0x00,0x09,0x04,0xe6,0x00,0x02,0x04,0xfb,0xb3,0x2f,0x01,0x01,0x01,0x00,0x2f,0x5d,0xed,0x3f,0x01,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0x31,0x30, 0x13,0x21,0x15,0x21,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x26,0x26,0x02,0x2b,0x03,0x25,0xfd,0xa1,0x19,0x26,0x19,0x0d,0x9c,0x11,0x23,0x36,0x05,0x9a,0xa7,0x71,0xca,0xd0,0xe4,0x89,0xfe,0x85,0x01,0x73,0x94,0xff,0xf8,0x01,0x03,0x00,0x01,0x00,0x2b,0x00,0x00,0x04,0x1a,0x05,0x9a,0x00,0x38,0x00,0x5c,0xb3,0x1c,0x0d,0x32,0x1f,0xbb, 0x05,0x0a,0x00,0x1a,0x00,0x10,0x05,0x0a,0x40,0x0d,0x0b,0x27,0x0b,0x1a,0x0b,0x1a,0x0b,0x3a,0x32,0x03,0x2b,0x2b,0x31,0xbb,0x05,0x0a,0x00,0x32,0x00,0x31,0x04,0xe6,0xb4,0x2b,0x2b,0x29,0x29,0x24,0xb8,0x04,0xfc,0xb7,0x06,0x15,0x1c,0x0d,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0x32,0x2f,0x33,0xed,0x32,0x2f,0x32,0x2f,0x3f,0x01, 0x2f,0xed,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x13,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x27,0x1e, 0x03,0x15,0x11,0x23,0x11,0x34,0x26,0x26,0x02,0x27,0xcb,0x15,0x24,0x0f,0x15,0x26,0x11,0x2a,0x3b,0x26,0x11,0x24,0x9d,0x24,0x1f,0x1d,0x34,0x17,0x2a,0x3b,0x26,0x11,0x24,0x9d,0x24,0x26,0x4a,0x6c,0x46,0x2d,0x67,0x3c,0x47,0x63,0x29,0x2b,0x0b,0x10,0x0b,0x06,0x9c,0x11,0x23,0x36,0x25,0x05,0x9a,0x5b,0xa1,0x4c,0x05,0x04,0x1c,0x30, 0x3f,0x24,0x54,0x4e,0x59,0x56,0x51,0x40,0x09,0x08,0x1c,0x30,0x3f,0x24,0x54,0x4e,0x59,0x56,0x3e,0x6b,0x4f,0x2d,0x18,0x1c,0x33,0x09,0x43,0x88,0x91,0x9f,0x5a,0xfe,0x85,0x01,0x73,0x94,0xff,0xf8,0x01,0x03,0x99,0x00,0x00,0x01,0x00,0x62,0xff,0xea,0x02,0xf5,0x05,0xb8,0x00,0x31,0x00,0x3f,0xb9,0x00,0x2c,0x05,0x0a,0xb2,0x21,0x21, 0x07,0xb8,0x05,0x0a,0xb7,0x17,0x17,0x33,0x32,0x31,0x1c,0x12,0x27,0xb8,0x05,0x02,0xb7,0x2f,0x26,0x01,0x26,0x0f,0x10,0x10,0x0c,0xba,0x04,0xfb,0x00,0x12,0x05,0x03,0x00,0x3f,0xed,0x33,0x11,0x33,0x2f,0x5d,0xed,0x12,0x39,0x39,0x11,0x12,0x01,0x39,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x0e,0x05,0x15,0x14,0x1e,0x02,0x33,0x32, 0x36,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x02,0x67,0x54,0x76,0x50,0x2e,0x18,0x07,0x2b,0x47,0x58,0x2d,0x4b,0x79,0x3a,0x7e,0x8e,0x47,0x8b,0x70,0x45,0x1b,0x42,0x6f,0x54,0x50,0x6b,0x3f,0x1a,0x2c,0x6d,0xb6,0x8a,0x73,0x87,0x45, 0x14,0x1f,0x52,0x90,0x72,0x03,0x13,0x4e,0x7f,0x67,0x50,0x3b,0x29,0x0c,0x2a,0x35,0x1d,0x0a,0x13,0x0f,0xa5,0x2c,0x1d,0x40,0x65,0x47,0x29,0x69,0x7e,0x93,0x53,0x25,0x44,0x45,0x49,0x2a,0x36,0x71,0x6f,0x69,0x2f,0xb0,0x24,0x46,0x3f,0x33,0x10,0x18,0x29,0x35,0x48,0x38,0x00,0x02,0x00,0x4f,0x00,0x9c,0x03,0xa9,0x04,0xd2,0x00,0x15, 0x00,0x29,0x00,0x31,0xb9,0x00,0x1b,0x05,0x0a,0xb3,0x0f,0x0f,0x2a,0x05,0xbb,0x05,0x0a,0x00,0x25,0x00,0x0a,0x04,0xfb,0xb4,0x2f,0x20,0x01,0x20,0x16,0xb8,0x04,0xff,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x11,0x33,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x35,0x34,0x3e,0x04,0x17,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x01,0xf4,0x47,0x9b,0x80,0x53,0x3d,0x72,0xa4,0x67,0x65,0x9b,0x6a,0x36,0x27,0x41,0x56,0x5e,0x5f,0x28,0x28,0x5c,0x4e,0x34,0x2a,0x48,0x5f,0x36,0x4a,0x6a,0x45,0x20,0x3b,0x56,0x62,0x04,0xd2,0x55,0xa5,0xf2,0x9c,0x60,0x9f, 0x71,0x3e,0x38,0x66,0x90,0x59,0x69,0xb7,0x99,0x78,0x52,0x2c,0xa2,0x4a,0x85,0xbb,0x70,0x41,0x5c,0x3a,0x1a,0x22,0x3e,0x58,0x37,0x77,0xbd,0x83,0x45,0x00,0x00,0x01,0xff,0xef,0x00,0x00,0x03,0x92,0x05,0x9a,0x00,0x15,0x00,0x22,0xb1,0x15,0x0e,0xb8,0x05,0x0a,0xb2,0x00,0x09,0x0a,0xb8,0x04,0xfb,0xb4,0x2f,0x0d,0x01,0x0d,0x00,0xb8, 0x04,0xe6,0x00,0x3f,0x2f,0x5d,0xed,0x01,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x2e,0x07,0x27,0x27,0x21,0x35,0x21,0x17,0x1e,0x05,0x17,0x02,0xee,0x18,0x25,0x1c,0x15,0x0e,0x0b,0x07,0x06,0x03,0x03,0xfd,0x9b,0x02,0xfc,0x06,0x04,0x08,0x0d,0x14,0x21,0x31,0x22,0x66,0xa6,0x8e,0x7c,0x79,0x7b,0x8d,0xa4,0x65,0x53,0xa7,0xc6,0x8c,0xd7, 0xb7,0xa6,0xb5,0xd5,0x8a,0x00,0x00,0x01,0xff,0xf4,0x00,0x00,0x03,0xfa,0x05,0x9a,0x00,0x11,0x00,0x14,0xb1,0x04,0x0b,0xb8,0x04,0xe6,0xb4,0x07,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0x3f,0x39,0x31,0x30,0x13,0x12,0x12,0x13,0x33,0x12,0x12,0x13,0x33,0x02,0x02,0x03,0x23,0x26,0x0a,0x02,0x27,0x93,0x65,0xae,0x4e,0x06,0x51,0xad, 0x64,0x9e,0x80,0xd8,0x61,0x94,0x33,0x69,0x6d,0x73,0x3d,0x05,0x9a,0xfe,0xf0,0xfd,0xc1,0xfe,0xcb,0x01,0x36,0x02,0x3f,0x01,0x0f,0xfe,0x9f,0xfd,0x39,0xfe,0x8e,0xc2,0x01,0x71,0x01,0x64,0x01,0x59,0xaa,0x00,0x00,0x01,0x00,0x49,0x00,0x00,0x04,0x4f,0x05,0x9a,0x00,0x11,0x00,0x21,0x40,0x0d,0x11,0x00,0x00,0x13,0x07,0x08,0x04,0x2f, 0x0d,0x01,0x0d,0x07,0x00,0xb8,0x04,0xe6,0x00,0x3f,0x32,0x2f,0x5d,0x39,0x01,0x2f,0x33,0x12,0x39,0x11,0x33,0x31,0x30,0x21,0x02,0x02,0x03,0x23,0x02,0x02,0x03,0x23,0x36,0x1a,0x02,0x37,0x33,0x12,0x12,0x13,0x03,0xb0,0x65,0xae,0x4e,0x06,0x51,0xad,0x64,0x9e,0x40,0x75,0x6d,0x66,0x31,0x94,0x66,0xd8,0x7b,0x01,0x10,0x02,0x3f,0x01, 0x35,0xfe,0xca,0xfd,0xc1,0xfe,0xf1,0xb1,0x01,0x61,0x01,0x65,0x01,0x6a,0xb9,0xfe,0x7d,0xfd,0x3c,0xfe,0xad,0x00,0x00,0x02,0x00,0x22,0x00,0x00,0x03,0xdb,0x05,0xa8,0x00,0x1e,0x00,0x33,0x00,0x3a,0xb9,0x00,0x1a,0x05,0x0a,0xb4,0x06,0x1f,0x1f,0x35,0x2c,0xb8,0x05,0x0a,0xb2,0x0d,0x06,0x08,0xb8,0x04,0xfb,0xb4,0x2f,0x31,0x01,0x31, 0x27,0xb8,0x04,0xfb,0xb4,0x2f,0x12,0x01,0x12,0x00,0xb8,0x04,0xe6,0x00,0x3f,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x21,0x23,0x2e,0x03,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03,0x01,0x2e,0x03,0x27,0x26,0x26,0x23,0x22,0x0e, 0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x03,0xdb,0x9f,0x29,0x36,0x24,0x15,0x08,0x7e,0x78,0x50,0x8d,0x69,0x3e,0x33,0x60,0x8c,0x5a,0x58,0x8d,0x3c,0x20,0x26,0x16,0x0c,0x06,0x07,0x14,0x26,0x3e,0xfe,0xe5,0x04,0x08,0x0a,0x0e,0x0a,0x23,0x6f,0x45,0x2c,0x4b,0x37,0x20,0x28,0x46,0x61,0x39,0x30,0x67,0x61,0xbd,0xb1,0xa3,0x48,0x3b, 0x34,0x61,0x8e,0x5a,0x50,0x9a,0x78,0x4a,0x51,0x5e,0x33,0x63,0x6d,0x7b,0x49,0x52,0xb5,0xcb,0xe2,0x02,0xd4,0x2a,0x42,0x38,0x32,0x1a,0x58,0x61,0x26,0x40,0x58,0x31,0x37,0x56,0x3c,0x1f,0x17,0x00,0xff,0xff,0xff,0xba,0xff,0xea,0x07,0x4b,0x04,0xb2,0x02,0x26,0x08,0xd6,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x1e,0x04,0x02,0x00,0x01, 0xff,0xba,0xff,0xf2,0x04,0x3c,0x03,0x8a,0x00,0x2c,0x00,0x36,0xb9,0x00,0x24,0x05,0x0a,0xb5,0x13,0x13,0x2e,0x2d,0x1c,0x1f,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x18,0x01,0x18,0x00,0x2c,0x2c,0x29,0x29,0x0c,0xba,0x04,0xfb,0x00,0x05,0x05,0x03,0x00,0x3f,0xed,0x32,0x11,0x33,0x11,0x33,0x2f,0x5d,0xed,0x32,0x11,0x12,0x01,0x39,0x2f,0xed, 0x31,0x30,0x25,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x37,0x04,0x3c,0x78,0xd5,0xc9,0xc5,0x67,0xfa,0x23,0x23,0x23,0x23,0x01,0x71,0x01,0x3e,0x4e,0x2c,0x0f,0x45,0x82,0xbc,0x77,0x28, 0x59,0x30,0x2e,0x63,0x36,0x3f,0x76,0x5c,0x37,0x16,0x36,0x5c,0x47,0x80,0xf9,0x8c,0xab,0x37,0x47,0x2a,0x11,0x34,0x20,0x20,0x33,0x06,0x33,0x63,0x5c,0x51,0x21,0x4f,0x8e,0x6b,0x3f,0x08,0x09,0xaa,0x08,0x0b,0x14,0x35,0x5a,0x45,0x21,0x4c,0x53,0x59,0x2e,0x19,0x54,0x42,0x00,0x02,0xff,0xba,0xff,0xf2,0x04,0xad,0x03,0x5e,0x00,0x29, 0x00,0x38,0x00,0x47,0xb3,0x28,0x13,0x23,0x31,0xb8,0x05,0x0a,0xb3,0x16,0x16,0x39,0x23,0xb8,0x05,0x0a,0xb7,0x2a,0x05,0x13,0x28,0x34,0x04,0x01,0x2d,0xb8,0x04,0xff,0xb7,0x2f,0x1c,0x01,0x1c,0x10,0x0f,0x0f,0x00,0xbb,0x04,0xfb,0x00,0x08,0x00,0x01,0x05,0x03,0x00,0x3f,0x33,0xed,0x32,0x11,0x33,0x2f,0x5d,0xed,0x12,0x17,0x39,0x01, 0x2f,0xed,0x11,0x33,0x2f,0xed,0x12,0x39,0x39,0x31,0x30,0x25,0x15,0x23,0x22,0x26,0x27,0x06,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x36,0x37,0x26,0x26,0x27,0x35,0x3e,0x03,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x02,0x07,0x16,0x03,0x34,0x26,0x23,0x22,0x06,0x07,0x15,0x16,0x16,0x17,0x3e,0x03,0x04,0xad,0x3e,0x87, 0xef,0x6d,0x67,0xfe,0xf0,0xae,0x67,0x23,0x23,0x23,0x23,0x71,0x80,0xc7,0x4f,0x6a,0xad,0x45,0x2d,0x72,0x7e,0x85,0x3f,0x27,0x54,0x50,0x47,0x36,0x20,0x19,0x35,0x52,0x39,0xb8,0x7c,0x79,0x67,0x4c,0x9e,0x49,0x45,0xa7,0x69,0x34,0x49,0x2d,0x14,0x99,0xa7,0x4a,0x45,0x40,0x4f,0x34,0x20,0x20,0x33,0x2a,0x23,0x58,0xd0,0x70,0xad,0x07, 0x12,0x0f,0x0b,0x05,0x10,0x1c,0x2d,0x41,0x2c,0x26,0x65,0x70,0x74,0x36,0x55,0x01,0xcb,0x33,0x2a,0x0f,0x08,0x0b,0x6a,0xb1,0x48,0x29,0x58,0x51,0x42,0x00,0x00,0x02,0x00,0x65,0xfd,0xff,0x04,0xad,0x03,0x95,0x00,0x3c,0x00,0x4a,0x00,0x63,0xb3,0x3a,0x23,0x1e,0x35,0xbb,0x05,0x0a,0x00,0x3d,0x00,0x44,0x05,0x0a,0xb2,0x28,0x28,0x0d, 0xb8,0x05,0x0a,0x40,0x0e,0x1e,0x3d,0x1e,0x3d,0x1e,0x4c,0x4b,0x08,0x3a,0x23,0x46,0x04,0x02,0x40,0xb8,0x04,0xff,0xb5,0x2f,0x2e,0x01,0x2e,0x15,0x12,0xb8,0x04,0xfc,0xb7,0x16,0x1f,0x19,0x2f,0x19,0x02,0x19,0x00,0xba,0x04,0xfb,0x00,0x02,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0x33,0xed,0x32,0x2f,0x5d,0xed,0x12,0x17,0x39,0x11,0x12, 0x01,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x25,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x27,0x35,0x3e,0x03,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x02,0x07,0x16,0x16, 0x03,0x34,0x26,0x23,0x22,0x06,0x07,0x15,0x16,0x17,0x3e,0x03,0x04,0x98,0x15,0x3e,0x56,0xa3,0x98,0x8d,0x40,0x4d,0x68,0x40,0x1b,0x2e,0x63,0x9e,0x71,0x61,0xc7,0x64,0x6d,0xbf,0x64,0x98,0xd7,0x89,0x40,0x1c,0x48,0x7e,0x62,0x20,0x46,0x44,0x3e,0x16,0x2d,0x72,0x7f,0x85,0x3f,0x27,0x54,0x4f,0x48,0x35,0x20,0x1b,0x48,0x80,0x66,0x70, 0xf2,0xb6,0x78,0x67,0x4c,0x9f,0x49,0x71,0x87,0x55,0x6e,0x40,0x18,0x99,0xa7,0x26,0x45,0x61,0x3b,0x20,0x46,0x4a,0x4f,0x28,0x40,0x72,0x55,0x32,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5b,0x36,0x69,0x69,0x67,0x33,0x22,0x58,0x5e,0x5d,0x26,0xa5,0x07,0x12,0x0f,0x0b,0x06,0x0f,0x1b,0x2c,0x3e,0x2a,0x23,0x5f,0x6b,0x6f,0x31,0x52, 0x59,0x02,0x07,0x2f,0x29,0x0f,0x08,0x0d,0xb0,0x81,0x26,0x4d,0x44,0x36,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x3c,0x04,0xe4,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x1d,0x04,0x34,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x04,0xb2,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x02,0xff,0xff, 0x00,0x65,0xfd,0xff,0x04,0xad,0x05,0x01,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x51,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x05,0x24,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x05,0x24,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07, 0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x05,0x24,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x05,0x24,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07, 0x0f,0x51,0x00,0xd5,0x04,0x74,0x00,0x01,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0x02,0x00,0x21,0x00,0x33,0xb9,0x00,0x1a,0x05,0x0a,0x40,0x12,0x0c,0x0c,0x23,0x22,0x11,0x12,0x0c,0x1a,0x15,0x12,0x04,0x00,0x14,0x2f,0x13,0x01,0x13,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0x33,0x12,0x17,0x39,0x11,0x33,0x11, 0x12,0x01,0x39,0x2f,0xed,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x35,0x01,0x15,0x01,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x23,0x23,0x23,0x01,0x28,0x61,0x80,0x4c,0x1e,0x58,0xa4,0xe7,0x90,0x03,0x4b,0xfd,0x66,0x8b,0xe1,0x9e,0x56,0x0b,0x23,0x42,0x6d,0xa0,0x6f,0x0e,0x34, 0x20,0x20,0x33,0x16,0x2a,0x3f,0x29,0x4c,0x8c,0x86,0x85,0x46,0x76,0x02,0x22,0xb0,0xfe,0x5f,0x42,0x8a,0x97,0xa6,0x5d,0x1e,0x4a,0x4d,0x49,0x39,0x22,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x01,0xf2,0x05,0xec,0x00,0x16,0x00,0x20,0xb9,0x00,0x08,0x05,0x0a,0xb4,0x05,0x05,0x18,0x17,0x00,0xbb,0x04,0xfb,0x00,0x0f,0x05,0x03,0x00,0x06, 0x00,0x2f,0x3f,0xed,0x11,0x12,0x01,0x39,0x2f,0xed,0x31,0x30,0x37,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x99,0x2e,0x47,0x30,0x18,0x9c,0x1c,0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x99,0x0f,0x2a,0x48,0x39,0x04,0x99,0xfb,0x60,0x4b,0x6e,0x4c,0x31,0x1a,0x0a,0x34, 0x20,0x20,0x33,0x00,0x00,0x02,0xff,0xba,0xff,0xf2,0x03,0xf4,0x02,0xaf,0x00,0x23,0x00,0x33,0x00,0x39,0xb9,0x00,0x16,0x05,0x0a,0x40,0x0a,0x2a,0x2a,0x35,0x34,0x20,0x24,0x0c,0x03,0x11,0x1b,0xba,0x05,0x03,0x00,0x2f,0x04,0xfb,0xb5,0x2f,0x11,0x01,0x11,0x27,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x5d, 0xed,0x3f,0x12,0x17,0x39,0x11,0x12,0x01,0x39,0x2f,0xed,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x01,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x23,0x23,0x23,0x23,0x1a,0x3f,0x57, 0x3b,0x22,0x0b,0x14,0x37,0x54,0x79,0x56,0x61,0x8b,0x58,0x2a,0x2b,0x56,0x81,0x57,0x36,0x63,0x58,0x4b,0x1f,0x35,0x9a,0x5e,0x01,0x6e,0x2a,0x8f,0x55,0x5e,0x6a,0x1a,0x35,0x52,0x38,0x32,0x4e,0x3f,0x2d,0x0e,0x34,0x20,0x20,0x33,0x2e,0x41,0x48,0x1a,0x2f,0x72,0x62,0x42,0x4d,0x74,0x86,0x3a,0x3b,0x72,0x59,0x36,0x17,0x28,0x35,0x1f, 0x50,0x43,0x01,0x13,0x34,0x37,0x44,0x46,0x21,0x50,0x45,0x2f,0x28,0x47,0x5f,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x01,0xf9,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x53,0xff,0xf2,0x05,0x32,0x04,0x53,0x02,0x06,0x0e,0x5c,0x00,0x00,0x00,0x03,0x00,0x67,0xfd,0xff,0x05,0x58, 0x03,0x56,0x00,0x2f,0x00,0x3f,0x00,0x4f,0x00,0x61,0xb1,0x3f,0x40,0xb8,0x05,0x0a,0xb7,0x00,0x0b,0x0b,0x00,0x00,0x50,0x24,0x17,0xb8,0x05,0x0a,0xb4,0x35,0x4a,0x4a,0x35,0x45,0xb8,0x04,0xfb,0xb6,0x1f,0x29,0x2f,0x29,0x02,0x29,0x3a,0xb8,0x04,0xfb,0x40,0x0c,0x2f,0x12,0x01,0x12,0x3f,0x30,0x30,0x1e,0x1e,0x1d,0x1d,0x0b,0xb8,0x04, 0xfb,0xb2,0x40,0x20,0x00,0xb8,0x05,0x03,0x00,0x3f,0x32,0x32,0xed,0x32,0x11,0x33,0x11,0x33,0x11,0x33,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x11,0x33,0x2f,0x33,0x2f,0x10,0xed,0x32,0x31,0x30,0x05,0x22,0x2e,0x02,0x27,0x27,0x1e,0x03,0x33,0x3e,0x05,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x17, 0x21,0x15,0x21,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x04,0x01,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x07,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x02,0x01,0x53,0x7d,0x5b,0x3c,0x13,0x20,0x2c,0x5a,0x65,0x73,0x45,0x15,0x41,0x4e,0x55,0x52,0x49,0x1c,0x2e,0x53,0x3f,0x25,0x17, 0x27,0x34,0x1c,0x02,0x01,0x45,0xfe,0xc0,0x01,0x48,0x40,0x28,0x48,0x64,0x3d,0x26,0x55,0x56,0x50,0x3f,0x29,0x01,0x21,0x30,0x52,0x3a,0x21,0x11,0x1e,0x27,0x15,0x1a,0x48,0x48,0x3c,0x0e,0x0b,0x04,0x2e,0x45,0x52,0x29,0x21,0x2d,0x1c,0x0d,0x20,0x3d,0x58,0x38,0x0e,0x03,0x04,0x06,0x03,0xa9,0x05,0x07,0x04,0x02,0x85,0xcf,0x9c,0x6c, 0x43,0x1e,0x45,0x6e,0x88,0x43,0x35,0x5b,0x4e,0x41,0x19,0x07,0xa7,0x06,0x2d,0x78,0x3e,0x34,0x60,0x4a,0x2c,0x14,0x2e,0x4b,0x6f,0x96,0x01,0x08,0x33,0x53,0x69,0x36,0x28,0x55,0x46,0x2c,0x47,0x87,0xc7,0x7f,0xa7,0x58,0x7d,0x50,0x26,0x16,0x22,0x2c,0x16,0x24,0x4b,0x3c,0x26,0x00,0x00,0x02,0x00,0xa1,0xff,0xf2,0x04,0x02,0x03,0xd7, 0x00,0x1b,0x00,0x29,0x00,0x3f,0xb9,0x00,0x1c,0x05,0x0a,0xb4,0x16,0x16,0x2a,0x24,0x01,0xbb,0x05,0x0a,0x00,0x00,0x00,0x11,0x04,0xfb,0xb4,0x2f,0x21,0x01,0x21,0x07,0xbc,0x04,0xfb,0x00,0x08,0x05,0x03,0x00,0x25,0x04,0xfc,0xb4,0x1b,0x2f,0x01,0x01,0x01,0x00,0x2f,0x5d,0xdd,0xed,0x3f,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x33,0x11, 0x33,0x2f,0xed,0x31,0x30,0x01,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x01,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x11,0x0e,0x03,0x02,0xac,0x9c,0x0f,0x29,0x48,0x3a,0x16,0x38,0x64,0x50,0x3a,0x0e,0x2b,0x62,0x2a,0x45,0x7f,0x62,0x3a,0x58,0x92,0xbc,0x65, 0xfe,0x8b,0x24,0x3a,0x4f,0x2a,0x27,0x55,0x22,0x4c,0x88,0x66,0x3b,0x03,0xd7,0xfd,0xb5,0x3e,0x5c,0x3c,0x1d,0xa7,0x19,0x35,0x52,0x3a,0x11,0x0c,0x20,0x45,0x6c,0x4d,0x5e,0x92,0x68,0x42,0x0f,0xfe,0x66,0x26,0x35,0x21,0x0e,0x0a,0x0b,0x01,0x76,0x0e,0x2f,0x41,0x52,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x48,0x03,0x0f,0x02,0x26, 0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0x9a,0xfd,0xd3,0x06,0xae,0x02,0x13,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0x01,0xfd,0xd8,0xff,0xff,0x00,0xa1,0xff,0xf2,0x04,0x02,0x05,0x64,0x02,0x26,0x08,0xf3,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x29,0x04,0xb4,0x00,0x01,0x00,0x9a, 0xff,0x02,0x06,0xae,0x02,0x13,0x00,0x44,0x00,0x4c,0xb9,0x00,0x36,0x05,0x0a,0xb2,0x0f,0x0f,0x14,0xb8,0x05,0x0a,0xb3,0x31,0x31,0x46,0x27,0xbb,0x05,0x0a,0x00,0x20,0x00,0x0c,0x04,0xff,0xb4,0x2f,0x3b,0x01,0x3b,0x1b,0xb8,0x04,0xfb,0x40,0x09,0x2f,0x2c,0x01,0x2c,0x2f,0x24,0x01,0x24,0x00,0xba,0x04,0xfb,0x00,0x01,0x05,0x03,0x00, 0x3f,0xed,0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x25,0x15,0x23,0x22,0x2e,0x04,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e, 0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x05,0x06,0xae,0x16,0x43,0x67,0x4e,0x3b,0x2d,0x25,0x12,0x17,0x2b,0x18,0x1d,0x27,0x20,0x26,0x20,0x2d,0x4e,0x68,0x77,0x80,0x3e,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x21,0x5a,0xa1,0x81,0x54,0x81,0x59,0x2d,0x20,0x26,0x20,0x26,0x41,0x57,0x30,0x31,0x60,0x27,0x11,0x1e, 0x21,0x2a,0x3b,0x52,0x99,0xa7,0x21,0x35,0x45,0x47,0x44,0x1b,0x23,0x1c,0x22,0x24,0x21,0x2c,0x2f,0x3e,0x34,0x3a,0x5c,0x47,0x31,0x20,0x0e,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6f,0x3e,0x4a,0x7c,0x5c,0x33,0x16,0x27,0x35,0x20,0x1c,0x2b,0x30,0x41,0x32,0x35,0x57,0x3e,0x22,0x2c,0x3a,0x1a,0x3d,0x3d,0x3a,0x2c,0x1a,0x00,0x01, 0x00,0x6f,0xff,0xea,0x01,0x76,0x01,0xe7,0x00,0x12,0x00,0x1c,0xb1,0x09,0x0e,0xb8,0x05,0x0c,0xb5,0x05,0x05,0x14,0x13,0x08,0x00,0xb8,0x05,0x03,0x00,0x3f,0xcd,0x11,0x12,0x01,0x39,0x2f,0xed,0x39,0x31,0x30,0x17,0x22,0x2e,0x02,0x35,0x34,0x37,0x13,0x33,0x03,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0xf1,0x1b,0x2f,0x23,0x15,0x0a,0x6a, 0x75,0x4b,0x64,0x02,0x03,0x15,0x24,0x30,0x16,0x15,0x24,0x2f,0x1b,0x15,0x1e,0x01,0x47,0xfe,0xe3,0x23,0x0e,0x18,0x0b,0x23,0x35,0x23,0x11,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x14,0x05,0x3e,0x02,0x26,0x0e,0x6f,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0x72,0xfd,0x55,0x00,0x0a,0xb4,0x01,0x2f,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35, 0xff,0xff,0x00,0x52,0xff,0xea,0x03,0xf3,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x07,0x0f,0x8c,0x02,0xac,0x00,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xad,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x07,0x0f,0x8d,0x02,0xac,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00, 0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x49,0xff,0xea,0x03,0xf3,0x07,0x78,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x7e,0x00,0x8f,0xff,0xff, 0x00,0x49,0xff,0xea,0x04,0xad,0x07,0x78,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x7e,0x00,0x8f,0xff,0xff,0xff,0xa2,0xff,0xea,0x03,0xf3,0x06,0xbf,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x01,0x06,0x09,0x37,0x00,0x8f,0x00,0x0a,0xb4,0x02,0x2f,0x2d, 0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x82,0xff,0x02,0x06,0xae,0x04,0x21,0x02,0x26,0x08,0xf7,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0x39,0xfc,0x38,0x00,0x0a,0xb4,0x01,0x2f,0x5b,0x01,0x5b,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0x00,0xfe,0xea,0x01,0x77,0x00,0xe4,0x00,0x0f,0x00,0x0a,0xb2,0x02,0x0d,0x07,0x00,0x2f,0x2f,0xcd, 0x30,0x31,0x15,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x36,0x2c,0x4a,0x41,0x2f,0x8c,0x2d,0x94,0x79,0x37,0x33,0x7b,0x0e,0x48,0x47,0x5e,0x80,0x79,0x6e,0x82,0x91,0x15,0xff,0xff,0xff,0xa2,0xff,0xea,0x04,0xad,0x06,0xbf,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00, 0x01,0x06,0x09,0x37,0x00,0x8f,0x00,0x0a,0xb4,0x02,0x2f,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x6f,0xff,0xea,0x01,0x76,0x04,0x00,0x00,0x26,0x00,0x11,0x00,0x00,0x00,0x07,0x08,0xf8,0x00,0x00,0x02,0x19,0x00,0x02,0x00,0xab,0xff,0xee,0x03,0x57,0x05,0xb3,0x00,0x29,0x00,0x3d,0x00,0x3e,0xb5,0x00,0x2f,0x24,0x39,0x39, 0x24,0xb8,0x05,0x0a,0xb3,0x05,0x05,0x3f,0x1d,0xbd,0x05,0x0a,0x00,0x0c,0x00,0x34,0x04,0xfe,0x00,0x2a,0x05,0x03,0xb2,0x14,0x15,0x18,0xb8,0x04,0xfc,0xb3,0x2f,0x11,0x01,0x11,0x00,0x2f,0x5d,0xfd,0xc2,0x32,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x32,0x2f,0x10,0xc4,0x39,0x31,0x30,0x01,0x3e,0x03,0x35,0x34,0x2e,0x04,0x35, 0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x04,0x15,0x14,0x0e,0x02,0x07,0x03,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0xf5,0x04,0x08,0x06,0x04,0x34,0x4e,0x5c,0x4e,0x34,0x3e,0x6c,0x91,0x53,0x48,0x91,0x45,0x3d,0x97,0x46,0x34,0x58,0x41,0x24, 0x33,0x4c,0x58,0x4c,0x33,0x04,0x06,0x09,0x04,0x5a,0x15,0x28,0x1f,0x13,0x12,0x1f,0x28,0x16,0x16,0x28,0x1f,0x12,0x13,0x1f,0x28,0x01,0x8e,0x0c,0x22,0x26,0x25,0x0f,0x3c,0x5b,0x4e,0x4a,0x58,0x6f,0x4b,0x51,0x81,0x5a,0x30,0x23,0x2a,0xac,0x39,0x34,0x1b,0x32,0x48,0x2e,0x38,0x5b,0x53,0x51,0x5c,0x6c,0x44,0x13,0x2a,0x27,0x23,0x0c, 0xfe,0x60,0x11,0x1d,0x28,0x18,0x17,0x29,0x1e,0x11,0x11,0x1e,0x29,0x17,0x18,0x28,0x1d,0x11,0x00,0x01,0x00,0x5a,0x00,0x00,0x02,0xe5,0x02,0xb4,0x00,0x1e,0x00,0x3a,0xb5,0x0c,0x00,0x0c,0x00,0x20,0x08,0xb8,0x05,0x0a,0xb3,0x16,0x1e,0x1e,0x03,0xb8,0x04,0xfb,0x40,0x09,0x2f,0x1b,0x01,0x1b,0x10,0x10,0x0f,0x0f,0x0b,0xba,0x04,0xfb, 0x00,0x0d,0x04,0xe6,0x00,0x3f,0xed,0x32,0x2f,0x33,0x2f,0x2f,0x5d,0xed,0x33,0x2f,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x15,0x21,0x27,0x33,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x02,0xac,0x1d,0x43,0x20,0x30,0x53,0x3d,0x24,0x7b,0x79, 0xa9,0xfd,0x92,0x1d,0xa9,0x01,0x19,0x22,0x15,0x09,0x37,0x66,0x8f,0x58,0x1c,0x41,0x20,0x01,0xff,0x05,0x07,0x13,0x2a,0x42,0x30,0x5b,0x5e,0xa3,0x99,0x06,0x19,0x38,0x3b,0x39,0x19,0x45,0x72,0x52,0x2e,0x05,0x05,0x00,0xff,0xff,0xff,0xa2,0x00,0x00,0x02,0x65,0x07,0x30,0x02,0x26,0x09,0x0d,0x00,0x00,0x00,0x06,0x09,0x37,0x00,0x00, 0xff,0xff,0x00,0x49,0x00,0x00,0x01,0xa2,0x07,0xe9,0x02,0x26,0x09,0x0d,0x00,0x00,0x00,0x06,0x09,0x7e,0x00,0x00,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x05,0x3e,0x02,0x26,0x09,0x29,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0xe4,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x4d,0x01,0x4d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x49,0xfd,0xfe, 0x01,0xa2,0x05,0xec,0x02,0x26,0x09,0x0d,0x00,0x00,0x00,0x06,0x09,0x7f,0x00,0x00,0xff,0xff,0x00,0x82,0xff,0x55,0x05,0x91,0x04,0xcc,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0x39,0xfc,0xe3,0x00,0x01,0x00,0xab,0x00,0x00,0x01,0x47,0x05,0xec,0x00,0x03,0x00,0x15,0xbd,0x00,0x01,0x05,0x0a,0x00,0x00,0x00,0x02,0x04, 0xe6,0x00,0x01,0x00,0x2f,0x3f,0x01,0x2f,0xed,0x31,0x30,0x13,0x33,0x11,0x23,0xab,0x9c,0x9c,0x05,0xec,0xfa,0x14,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xad,0xfe,0xab,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x05,0x5d,0x02,0x26,0x09,0x28,0x00,0x00,0x00,0x07, 0x0f,0x51,0x01,0x01,0x04,0xad,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x04,0xb2,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x05,0xca,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xad,0x04,0x02,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54, 0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0xc8,0xff,0xcf,0x00,0x01,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x00,0x31,0x00,0x40,0x40,0x0a,0x1d,0x00,0x31,0x03,0x16,0x0d,0x0d,0x33,0x26,0x05,0xb8,0x05,0x0a,0xb6,0x16,0x00,0x1d,0x31,0x03,0x11,0x23,0xb8,0x04,0xff,0xb2,0x2a,0x0d,0x0a,0xb8,0x04,0xff,0xb6,0x0e,0x1f, 0x11,0x2f,0x11,0x02,0x11,0x00,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x01,0x2f,0xed,0x39,0x12,0x39,0x2f,0x12,0x17,0x39,0x31,0x30,0x01,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33, 0x32,0x1e,0x04,0x17,0x04,0x0c,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0x02,0x01,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26, 0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x04,0xda,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x2a,0x00,0x01,0x00,0x52,0xff,0xea,0x03,0x4a,0x03,0xba,0x00,0x19, 0x00,0x24,0xb9,0x00,0x11,0x05,0x0a,0xb4,0x08,0x08,0x1b,0x1a,0x03,0xba,0x04,0xfb,0x00,0x16,0x05,0x03,0xb3,0x2f,0x0e,0x01,0x0e,0x00,0x2f,0x5d,0x3f,0xed,0x11,0x12,0x01,0x39,0x2f,0xed,0x31,0x30,0x37,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x12,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x52,0x61,0xa6, 0x39,0x4f,0x6c,0x42,0x1d,0x3b,0x60,0x7b,0x40,0xb9,0x9f,0x9c,0x48,0x7a,0xa0,0x57,0x3a,0x9a,0x4b,0xa9,0x0b,0x0b,0x15,0x2c,0x44,0x2f,0x49,0x9c,0x9f,0xa1,0x4e,0xb1,0xfe,0xbf,0x91,0x63,0x80,0x4c,0x1e,0x0c,0x0a,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x05,0x5d,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xab, 0x04,0xad,0x00,0x01,0x00,0x00,0xfd,0xff,0x02,0x9e,0x02,0x5e,0x00,0x1a,0x00,0x26,0xb9,0x00,0x12,0x05,0x0a,0xb2,0x07,0x00,0x02,0xb8,0x04,0xfb,0x40,0x0b,0x1a,0x1f,0x17,0x2f,0x17,0x02,0x17,0x2f,0x0d,0x01,0x0d,0x00,0x2f,0x5d,0x2f,0x5d,0x33,0xed,0x32,0x01,0x2f,0xed,0x31,0x30,0x11,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02, 0x27,0x33,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x7c,0x59,0x55,0x74,0x45,0x1e,0x13,0x1f,0x29,0x16,0xa1,0x1a,0x28,0x1c,0x0f,0x44,0x79,0xa7,0x62,0x33,0x6c,0x39,0xfe,0xd1,0x27,0x3d,0x6c,0x92,0x56,0x4b,0x8e,0x88,0x83,0x3f,0x41,0x8e,0x8f,0x8b,0x3e,0x8a,0xd4,0x90,0x4a,0x16,0x17,0x00,0xff,0xff,0x00,0x00,0xfd,0xff, 0x02,0x9e,0x04,0x07,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x9a,0x03,0x57,0x00,0x01,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x03,0x0f,0x00,0x4d,0x00,0x74,0xb9,0x00,0x1b,0x05,0x0a,0xb2,0x18,0x26,0x0e,0xb8,0x05,0x0a,0xb3,0x0b,0x2f,0x2f,0x03,0xb8,0x05,0x0a,0x40,0x0a,0x4a,0x18,0x0b,0x4a,0x4a,0x0b,0x18,0x03,0x4f,0x40, 0xb8,0x05,0x0a,0xb5,0x39,0x2f,0x3d,0x01,0x3d,0x45,0xb8,0x04,0xfb,0x40,0x0a,0x1f,0x34,0x2f,0x34,0x02,0x34,0x26,0x2f,0x13,0x06,0xbc,0x04,0xfb,0x00,0x2b,0x05,0x03,0x00,0x20,0x05,0x03,0x40,0x09,0x19,0x20,0x0d,0x01,0x0d,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xd4,0x5d,0xc6,0x3f,0x3f,0xed,0x32,0x39,0x39,0x2f,0x5d,0xed,0x2f,0x5d, 0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x2f,0x10,0xed,0x39,0x10,0xed,0x31,0x30,0x01,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x07,0x0e,0x03,0x23, 0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x04,0x80,0x08,0x0c,0x05,0x06,0x58,0x5e,0x22,0x3f,0x30,0x1d,0x9c,0x0b,0x27,0x48,0x3e,0x26,0x40,0x2e,0x19,0x9c,0x38,0x5d,0x78,0x3f,0x2c,0x4f,0x42,0x34,0x12,0x04,0x19,0x3f,0x44,0x46,0x1f,0x42,0x52,0x19,0x05,0x03, 0x3d,0x80,0xcc,0x91,0x8a,0xb9,0x70,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x93,0x5d,0x2b,0x12,0x10,0x02,0x01,0x3f,0x70,0x38,0x42,0x3f,0x10,0x2a,0x48,0x38,0x01,0x0b,0xc6,0x43,0x60,0x3e,0x1e,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x37,0x6c,0x85,0x4a,0x19,0x0d,0x1c,0x2f,0x23,0x23,0x2f,0x1d,0x0c,0x26,0x20,0x01, 0x84,0xd3,0x93,0x4e,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x53,0xbb,0x78,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x05,0x1f,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0x46,0x03,0x57,0x00,0x02,0x00,0x9b,0xfd,0xff,0x09,0xf7,0x03,0x3c,0x00,0x42,0x00,0x56, 0x00,0x57,0xb3,0x54,0x09,0x13,0x3c,0xbe,0x05,0x0a,0x00,0x48,0x00,0x1a,0x05,0x0a,0x00,0x13,0x00,0x4d,0x04,0xfb,0x40,0x0d,0x2f,0x37,0x01,0x37,0x2f,0x28,0x01,0x28,0x2f,0x17,0x01,0x17,0x1f,0xb8,0x04,0xfb,0x40,0x0c,0x1f,0x0e,0x2f,0x0e,0x02,0x0e,0x54,0x54,0x43,0x43,0x09,0x30,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed, 0x39,0x32,0x11,0x33,0x2f,0x2f,0x5d,0xed,0x2f,0x5d,0x2f,0x5d,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x2f,0xed,0x11,0x39,0x39,0x31,0x30,0x05,0x22,0x2e,0x02,0x27,0x26,0x26,0x27,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x1e, 0x03,0x17,0x3e,0x05,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x27,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x07,0x93,0xa1,0xe7,0x9d,0x5e,0x18,0x1f,0x28,0x12,0x05,0x03,0x3d,0x81,0xcd,0x94,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x93,0x5d,0x2b,0x12,0x17,0x9a,0x0b, 0x0d,0x08,0x03,0x11,0x21,0x36,0x28,0x18,0x4c,0x67,0x81,0x9a,0xb4,0x65,0x79,0xae,0x70,0x36,0x2d,0x52,0x71,0x88,0x9b,0x3b,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x85,0x75,0x65,0x52,0x3f,0x15,0x5c,0xee,0x16,0x01,0x03,0x08,0x07,0x09,0x1d,0x15,0x01,0x84,0xd3,0x93,0x4e,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39, 0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x53,0xc5,0x6e,0x3f,0x72,0x3a,0x17,0x2b,0x22,0x15,0x02,0x41,0x96,0x95,0x8b,0x6a,0x40,0x4b,0x80,0xab,0x60,0x5d,0x80,0x55,0x2f,0x16,0x05,0xa9,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0x2a,0x49,0x63,0x71,0x7a,0x3c,0x02,0x01,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0xf7,0x04,0xb2,0x02,0x26, 0x09,0x1b,0x00,0x00,0x00,0x07,0x0f,0x50,0x05,0xca,0x04,0x02,0x00,0x02,0x00,0x19,0xff,0xea,0x05,0xf5,0x05,0xec,0x00,0x20,0x00,0x34,0x00,0x3a,0xb9,0x00,0x0d,0x05,0x0a,0xb2,0x26,0x32,0x01,0xb8,0x05,0x0a,0xb5,0x00,0x32,0x32,0x21,0x21,0x1d,0xb8,0x04,0xfb,0xb3,0x03,0x1a,0x01,0x14,0xba,0x05,0x03,0x00,0x2b,0x04,0xfb,0xb1,0x08, 0x01,0x00,0x2f,0x2f,0xed,0x3f,0x12,0x39,0x39,0xed,0x32,0x11,0x33,0x2f,0x01,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x33,0x11,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x24,0x26,0x26,0x27,0x27,0x16,0x16,0x17,0x36,0x36,0x37,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16, 0x01,0x55,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x5a,0x79,0xae,0x70,0x36,0x2d,0x52,0x71,0x88,0x9a,0x52,0xb7,0xfe,0xf5,0xc6,0x92,0x3e,0x20,0x2d,0x91,0x58,0x08,0x13,0x0b,0x02,0x52,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5c,0xe9,0x05,0xec,0xfc,0x1d,0x01,0x43,0x7a,0x5d,0x36,0x4f,0x88,0xb5,0x66, 0x5d,0x80,0x55,0x2f,0x16,0x05,0x03,0x06,0x09,0x06,0xa7,0x06,0x07,0x01,0x16,0x2e,0x1a,0x66,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0xff,0xff,0x00,0x19,0xff,0xea,0x05,0xf5,0x05,0xec,0x02,0x26,0x09,0x1d,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xe5,0x04,0x02,0x00,0x01,0x00,0x65,0xfd,0xff, 0x04,0x2d,0x04,0x2a,0x00,0x37,0x00,0x52,0xb4,0x29,0x00,0x16,0x39,0x31,0xb8,0x05,0x0a,0xb2,0x20,0x20,0x05,0xb8,0x05,0x0a,0xb4,0x16,0x28,0x29,0x29,0x2c,0xb8,0x04,0xfb,0x40,0x0d,0x25,0x00,0x34,0x1b,0x37,0x37,0x11,0x2f,0x25,0x01,0x25,0x0d,0x0a,0xb8,0x04,0xfc,0xb6,0x0e,0x1f,0x11,0x2f,0x11,0x02,0x11,0x00,0x2f,0x5d,0x33,0xed, 0x32,0x2f,0x5d,0x12,0x39,0x2f,0x39,0x39,0x33,0x10,0xed,0x32,0x11,0x33,0x01,0x2f,0xed,0x39,0x2f,0xed,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22, 0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x37,0x03,0x5c,0xaf,0xe8,0x8b,0x39,0x2e,0x63,0x9e,0x71,0x61,0xc7,0x64,0x6d,0xbf,0x64,0x98,0xd7,0x89,0x40,0x14,0x31,0x53,0x3f,0x26,0x37,0x23,0x11,0x3d,0x72,0xa6,0x69,0x23,0x4f,0x2a,0x27,0x56,0x2a,0x36,0x65,0x4d,0x2f,0x37,0x33,0x51,0xd1,0x89,0x01,0x9a,0x2e,0x66,0x72,0x7d,0x45,0x40, 0x72,0x55,0x32,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5b,0x31,0x64,0x65,0x64,0x30,0x24,0x51,0x55,0x56,0x29,0x4f,0x92,0x70,0x42,0x08,0x09,0xaa,0x08,0x0b,0x16,0x38,0x5d,0x46,0x4c,0x7f,0x2b,0x2d,0x52,0x24,0x00,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x05,0x8f,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xe4, 0x04,0xdf,0x00,0x01,0xff,0xba,0xff,0xf2,0x01,0x56,0x00,0x99,0x00,0x08,0x00,0x13,0xb2,0x08,0x04,0x07,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x01,0x2f,0xcd,0x31,0x30,0x05,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x01,0x56,0xfe,0xaa,0x23,0x23,0x23,0x23,0x01,0x56,0x0e,0x34,0x20,0x20,0x33,0x00,0xff,0xff,0x00,0xab, 0xff,0xea,0x07,0x4b,0x05,0x24,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x50,0x04,0xd7,0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x4b,0x04,0x79,0x02,0x26,0x09,0x7c,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xd4,0x03,0xc9,0x00,0x02,0x00,0xab,0xff,0xea,0x05,0xf4,0x05,0xec,0x00,0x25,0x00,0x46,0x00,0x71,0xbf,0x00,0x13,0x05, 0x0a,0x00,0x10,0x00,0x41,0x05,0x0b,0x00,0x28,0x00,0x39,0x05,0x0b,0x40,0x10,0x30,0x36,0x10,0x28,0x26,0x30,0x22,0x10,0x28,0x30,0x30,0x28,0x10,0x03,0x48,0x03,0xbe,0x05,0x0a,0x00,0x22,0x00,0x26,0x04,0xfd,0x00,0x46,0x00,0x36,0x04,0xfd,0x40,0x0a,0x28,0x41,0x30,0x39,0x04,0x1a,0x35,0x35,0x11,0x0b,0xba,0x04,0xfb,0x00,0x1a,0x05, 0x03,0xb4,0x11,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0x3f,0xed,0x12,0x39,0x2f,0x12,0x17,0x39,0xed,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e, 0x04,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x25,0x36,0x35,0x34,0x26,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x01,0x62,0x09,0x11,0x1f,0x2f,0x1a,0x4e,0x7b,0xb1,0x7d,0x6d,0xa2,0x6c,0x36,0x9c,0x2d,0x52,0x71,0x88,0x9a,0x51,0x76,0xc2,0x9b, 0x78,0x2c,0x3f,0x30,0x12,0x0b,0x01,0xe4,0xc5,0x1f,0x15,0x10,0x21,0x1b,0x11,0x2e,0x4f,0x69,0x3b,0x5e,0x54,0x21,0x17,0x0f,0x20,0x1a,0x10,0x25,0x4c,0x74,0x4f,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x63,0x23,0x13,0x1a,0x10,0x07,0x0a,0x29,0x53,0x48,0x04,0x8b,0xfb,0x6e,0x5a,0x7c,0x52,0x2d,0x16,0x05,0x06,0x16,0x2c,0x26,0x37,0x98,0x58, 0x3d,0x70,0x33,0x57,0x0b,0x47,0x12,0x16,0x0b,0x08,0x14,0x1b,0x27,0x1b,0x26,0x3e,0x2f,0x1f,0x08,0x5d,0x0c,0x2d,0x21,0x14,0x18,0x0b,0x08,0x12,0x1a,0x23,0x19,0x1f,0x3e,0x33,0x23,0x04,0x00,0x01,0x00,0x9b,0xfe,0xac,0x04,0x9e,0x05,0xec,0x00,0x1d,0x00,0x25,0xbf,0x00,0x03,0x05,0x0a,0x00,0x1a,0x00,0x10,0x05,0x0a,0x00,0x0d,0x00, 0x08,0x04,0xfb,0xb5,0x15,0x0f,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0x2f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x01,0x4e,0x0b,0x0b,0x23,0x4f,0x7d,0x59,0x67,0x93,0x5d,0x2b,0x9c,0x38,0x81, 0xd4,0x9d,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x01,0xa6,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x04,0xc4,0xfb,0x28,0x8f,0xe4,0x9f,0x56,0x45,0x7f,0xb7,0x72,0x3f,0x83,0x4b,0x00,0x02,0x00,0x39,0xfd,0xff,0x03,0xf4,0x02,0xb9,0x00,0x26,0x00,0x38,0x00,0x41,0xb2,0x17,0x1b,0x05,0xbb,0x05,0x0a,0x00,0x2c,0x00,0x12,0x05, 0x0a,0x40,0x0a,0x1b,0x2f,0x17,0x01,0x17,0x20,0x34,0x34,0x00,0x27,0xbd,0x04,0xfb,0x00,0x0f,0x00,0x0a,0x05,0x03,0x00,0x31,0x04,0xfb,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xed,0x3f,0x33,0xed,0x12,0x39,0x11,0x33,0x2f,0x5d,0x01,0x2f,0xed,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x05,0x13,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x1e,0x03,0x02,0xac,0x4c,0x79,0x55,0x2e,0x23,0x47,0x69,0x45,0x31,0x66,0x61,0x59,0x24,0x4e,0x43,0x09,0x11,0x17,0x0e,0xa6,0x19,0x1d,0x24,0x42,0x5d,0x3a,0x17,0x3d,0x45, 0x49,0x44,0x3b,0x2e,0x21,0x35,0x27,0x15,0x1e,0x33,0x45,0x27,0x4b,0x6d,0x29,0x21,0x44,0x44,0x43,0x02,0xb9,0x53,0x7d,0x91,0x3e,0x3b,0x6c,0x52,0x30,0x13,0x17,0x13,0x63,0x5b,0x26,0x5d,0x63,0x61,0x2a,0x67,0xbd,0x45,0x48,0x79,0x5b,0x39,0x09,0x71,0xa2,0x6f,0x43,0x23,0x0b,0xfd,0xdf,0x0c,0x1c,0x30,0x23,0x25,0x59,0x4e,0x34,0xa4, 0xad,0x05,0x0f,0x0d,0x09,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x03,0x5c,0x02,0x26,0x09,0x5f,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x9f,0x02,0xac,0x00,0x02,0x00,0xab,0xff,0xea,0x03,0x57,0x03,0xce,0x00,0x17,0x00,0x29,0x00,0x36,0xb9,0x00,0x06,0x05,0x0a,0xb6,0x20,0x20,0x10,0x2b,0x00,0x00,0x18,0xb8,0x05,0x0a,0xb4,0x10, 0x15,0x25,0x01,0x1d,0xba,0x04,0xfb,0x00,0x0b,0x05,0x03,0xb3,0x2f,0x01,0x01,0x01,0x00,0x2f,0x5d,0x3f,0xed,0x12,0x39,0x39,0x01,0x2f,0xed,0x32,0x2f,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x37,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x03,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34, 0x2e,0x02,0x27,0x0e,0x03,0x01,0x3f,0x60,0x76,0xa7,0x6a,0x31,0x30,0x5a,0x83,0x53,0x51,0x7c,0x54,0x2b,0x2a,0x43,0x56,0x2c,0x15,0x2d,0x13,0x1d,0x32,0x42,0x25,0x66,0x5c,0x12,0x2b,0x46,0x34,0x29,0x47,0x34,0x1d,0x03,0x4f,0x7f,0x4e,0x9f,0xa5,0xaa,0x59,0x4b,0x7b,0x59,0x30,0x2b,0x50,0x70,0x45,0x53,0x96,0x7f,0x65,0x23,0x11,0x22, 0xfd,0xfb,0x2d,0x3e,0x28,0x12,0x58,0x4b,0x2e,0x5a,0x5c,0x5f,0x33,0x1d,0x52,0x60,0x6d,0x00,0x00,0x02,0x00,0x00,0xfd,0xff,0x03,0x49,0x02,0xb7,0x00,0x22,0x00,0x36,0x00,0x47,0xb2,0x23,0x23,0x1a,0xb8,0x05,0x0a,0xb3,0x08,0x08,0x38,0x2f,0xb8,0x05,0x0a,0xb2,0x0f,0x00,0x03,0xb8,0x04,0xfb,0xb7,0x22,0x1f,0x1f,0x2f,0x1f,0x02,0x1f, 0x2a,0xb8,0x04,0xfb,0xb5,0x2f,0x14,0x01,0x14,0x08,0x34,0xba,0x04,0xfb,0x00,0x0a,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d,0xed,0x2f,0x5d,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x33,0x2f,0x31,0x30,0x11,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16, 0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x2e,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x6c,0xad,0x52,0x64,0x7b,0x45,0x1a,0x02,0x53,0x59,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x36,0x36,0x34,0x72,0xb6,0x82,0x5b,0xac,0x64,0x02,0xa9,0x01,0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c, 0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0xfe,0xf9,0x2c,0x23,0x42,0x68,0x82,0x41,0x25,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x55,0xed,0x84,0x74,0xd3,0xa2,0x60,0x26,0x2e,0x02,0x66,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0x00,0x01,0x00,0x9a,0xff,0x55,0x05,0x91,0x04,0x15,0x00,0x35, 0x00,0x42,0xb2,0x09,0x05,0x2f,0xbb,0x05,0x0a,0x00,0x16,0x00,0x28,0x05,0x0a,0xb6,0x1d,0x16,0x1d,0x16,0x1d,0x37,0x0c,0xb8,0x05,0x0a,0xb2,0x05,0x28,0x23,0xbe,0x04,0xff,0x00,0x22,0x00,0x00,0x04,0xfb,0x00,0x11,0x04,0xe6,0x00,0x09,0x00,0x2f,0x3f,0xed,0x2f,0xed,0x2f,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed, 0x11,0x39,0x31,0x30,0x05,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x04,0x15,0x14,0x0e,0x04,0x02,0x9c,0x94,0xc5,0x77,0x32,0x23,0x1d,0x97,0x17,0x23,0x21,0x52,0x8e,0x6d,0x6d,0xbd,0x8d,0x51,0x33,0x4b, 0x59,0x4b,0x33,0x54,0x96,0xd1,0x7e,0x64,0x9c,0x6c,0x38,0x33,0x4d,0x5a,0x4d,0x33,0x27,0x4e,0x73,0x98,0xbc,0xab,0x4e,0x85,0xb1,0x63,0x5b,0xba,0x5b,0x58,0xaf,0x55,0x47,0x7b,0x5c,0x34,0x2e,0x4b,0x5e,0x30,0x26,0x33,0x2c,0x2e,0x40,0x5c,0x45,0x55,0x7f,0x5b,0x3b,0x12,0xa2,0x0d,0x23,0x31,0x41,0x2a,0x29,0x39,0x2f,0x2c,0x3a,0x4f, 0x3a,0x31,0x6a,0x68,0x5e,0x47,0x2a,0x00,0xff,0xff,0x00,0x9a,0xfd,0xfb,0x05,0x91,0x04,0x15,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0x01,0xfe,0x00,0x00,0x02,0x00,0x05,0x06,0x7c,0x02,0x01,0x07,0x8d,0x00,0x03,0x00,0x07,0x00,0x1d,0xb4,0x05,0x01,0x04,0x00,0x02,0xbc,0x04,0xfd,0x00,0x01,0x00,0x06,0x04,0xfd,0x00, 0x05,0x00,0x2f,0xfd,0xde,0xed,0x01,0x2f,0x33,0xcd,0x32,0x31,0x30,0x13,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x05,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04,0x06,0xd4,0x58,0x01,0x11,0x58,0x00,0x02,0xff,0x33,0x06,0x55,0x01,0xca,0x08,0x0e,0x00,0x23,0x00,0x31,0x00,0x3b,0xb2,0x20,0x13,0x1d,0xb8,0x05,0x0d,0xb5,0x24,0x23,0x23,0x24, 0x11,0x2c,0xb8,0x05,0x0d,0xb4,0x13,0x0b,0x08,0x05,0x18,0xb8,0x04,0xfd,0xb3,0x27,0x20,0x2f,0x0e,0xb9,0x04,0xfd,0x00,0x05,0x00,0x2f,0xfd,0x32,0x39,0xd4,0xed,0x11,0x39,0x39,0x01,0x2f,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x31,0x30,0x01,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x07,0x27,0x37,0x16,0x16,0x33,0x32,0x37, 0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x01,0x3c,0x2f,0x21,0x19,0x2f,0x15,0x42,0x5e,0x25,0x61,0x36,0x99,0x31,0x5b,0x34,0x10,0x0f,0x01,0x36,0x1f,0x31,0x3f,0x21,0x1f,0x3b,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x04, 0x33,0x1f,0x10,0x1f,0x19,0x0f,0x23,0x1a,0x30,0x3c,0x06,0x55,0x22,0x22,0x07,0x06,0x34,0x2a,0x59,0x3b,0x8e,0x3c,0x3e,0x03,0x02,0x45,0x45,0x26,0x3b,0x29,0x15,0x14,0x29,0x3d,0x29,0x42,0x5a,0x1a,0x0b,0x10,0x08,0xd6,0x29,0x25,0x09,0x13,0x1c,0x12,0x1d,0x3d,0x1d,0x10,0x39,0x00,0x00,0x02,0x00,0x05,0xfe,0x60,0x02,0x01,0xff,0x71, 0x00,0x03,0x00,0x07,0x00,0x1d,0xb4,0x05,0x01,0x04,0x00,0x02,0xbc,0x04,0xfd,0x00,0x01,0x00,0x06,0x04,0xfd,0x00,0x05,0x00,0x2f,0xfd,0xde,0xed,0x01,0x2f,0x33,0xcd,0x32,0x31,0x30,0x13,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x05,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04,0xfe,0xb8,0x58,0x01,0x11,0x58,0x00,0x01,0x00,0x05,0x06,0x7c, 0x02,0x01,0x06,0xd4,0x00,0x03,0x00,0x11,0xb2,0x01,0x00,0x02,0xb9,0x04,0xfd,0x00,0x01,0x00,0x2f,0xed,0x01,0x10,0xcd,0x31,0x30,0x13,0x21,0x15,0x21,0x05,0x01,0xfc,0xfe,0x04,0x06,0xd4,0x58,0x00,0x00,0x02,0xff,0xbf,0x06,0x55,0x01,0xca,0x08,0x0e,0x00,0x22,0x00,0x30,0x00,0x35,0xb2,0x1f,0x12,0x1c,0xb8,0x05,0x0d,0xb5,0x23,0x22, 0x22,0x23,0x10,0x2b,0xbb,0x05,0x0d,0x00,0x12,0x00,0x17,0x04,0xfd,0xb3,0x26,0x1f,0x2e,0x0c,0xb9,0x04,0xfd,0x00,0x05,0x00,0x2f,0xfd,0x32,0x39,0xd4,0xed,0x01,0x2f,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x31,0x30,0x01,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x32,0x37,0x37,0x26,0x35,0x34,0x3e, 0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x01,0x3c,0x2d,0x23,0x18,0x30,0x15,0x39,0x67,0x30,0x12,0x32,0x5c,0x38,0x01,0x0b,0x06,0x01,0x34,0x1e,0x32,0x3f,0x20,0x1f,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x04,0x33,0x1f,0x10,0x1f,0x19,0x0f, 0x23,0x1a,0x30,0x3c,0x06,0x55,0x22,0x22,0x05,0x03,0x0e,0x0e,0x53,0x0d,0x0f,0x01,0x02,0x43,0x44,0x26,0x3c,0x29,0x15,0x14,0x29,0x3d,0x29,0x42,0x5a,0x1a,0x0b,0x10,0x08,0xd6,0x29,0x25,0x09,0x13,0x1c,0x12,0x1d,0x3d,0x1d,0x10,0x39,0x00,0x00,0x01,0x00,0x05,0xff,0x19,0x02,0x01,0xff,0x71,0x00,0x03,0x00,0x11,0xb2,0x01,0x00,0x02, 0xb9,0x04,0xfd,0x00,0x01,0x00,0x2f,0xed,0x01,0x10,0xcd,0x31,0x30,0x17,0x21,0x15,0x21,0x05,0x01,0xfc,0xfe,0x04,0x8f,0x58,0x00,0x01,0xff,0xd4,0x06,0x76,0x02,0x33,0x07,0xa0,0x00,0x33,0x00,0x53,0xb2,0x00,0x00,0x03,0xb8,0x05,0x0d,0x40,0x09,0x30,0x33,0x33,0x30,0x0a,0x21,0x25,0x25,0x2a,0xb8,0x05,0x0d,0xb4,0x21,0x24,0x24,0x21, 0x1b,0xb8,0x05,0x0b,0x40,0x0b,0x12,0x15,0x15,0x12,0x16,0x25,0x25,0x33,0x0a,0x0d,0x06,0xb8,0x04,0xfd,0xb1,0x1e,0x2d,0x00,0x2f,0x33,0xed,0x32,0x39,0xce,0x32,0x11,0x33,0x01,0x2f,0x33,0x2f,0x10,0xed,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23, 0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x0e,0x02,0x14,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x06,0x06,0x14,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x03, 0x02,0x02,0x26,0x2d,0x2c,0x23,0x02,0x61,0x01,0x01,0x22,0x2d,0x2f,0x25,0x04,0x02,0x07,0xa0,0x14,0x25,0x0e,0x6d,0x76,0x1f,0x20,0x20,0x1f,0x22,0x3a,0x4e,0x2c,0x1a,0x2c,0x0e,0x17,0x1d,0x13,0x0c,0x05,0x33,0x3f,0x3e,0x3b,0x14,0x2e,0x0f,0x07,0x15,0x16,0x16,0x08,0x3d,0x3d,0x3e,0x37,0x17,0x30,0x0e,0x00,0x02,0x00,0x45,0x06,0x76, 0x01,0xc1,0x07,0xe9,0x00,0x13,0x00,0x1f,0x00,0x26,0x41,0x0c,0x00,0x05,0x05,0x0d,0x00,0x17,0x00,0x1d,0x05,0x0d,0x00,0x0f,0x00,0x00,0x04,0xfd,0x00,0x1a,0x00,0x14,0x04,0xfd,0x00,0x0a,0x00,0x2f,0xfd,0xd6,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02, 0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x03,0x29,0x45,0x33,0x1d,0x1d,0x33,0x45,0x29,0x2a,0x46,0x32,0x1c,0x1c,0x33,0x45,0x2a,0x30,0x34,0x34,0x30,0x2f,0x35,0x35,0x07,0xe9,0x1d,0x32,0x44,0x27,0x27,0x44,0x31,0x1d,0x1d,0x31,0x44,0x27,0x27,0x44,0x32,0x1d,0xfe,0xe4,0x36,0x2c,0x2b,0x38,0x38,0x2b,0x2c, 0x36,0x00,0xff,0xff,0x00,0x52,0xfd,0xfe,0x03,0xf3,0x05,0xec,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x7f,0x72,0x00,0xff,0xff,0x00,0x52,0xfd,0xfe,0x04,0xad,0x05,0xec,0x02,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x7f,0x72,0x00,0xff,0xff, 0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xa2,0x06,0x62,0x02,0x65,0x07,0x30,0x00,0x1b,0x00,0x20,0x40,0x0d,0x00,0x0e,0x0e,0x0d,0x0d,0x05,0x00,0x1b,0x1b,0x13,0x0a,0x18,0x05,0x00,0x2f,0xcd,0xd4,0xcd,0x32,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xcd,0x31,0x30,0x01,0x0e,0x03,0x23, 0x22,0x2e,0x02,0x23,0x22,0x06,0x07,0x27,0x3e,0x03,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x37,0x02,0x65,0x1a,0x31,0x2d,0x29,0x12,0x33,0x5c,0x56,0x54,0x2d,0x22,0x31,0x19,0x3e,0x1a,0x31,0x2d,0x29,0x12,0x33,0x5c,0x56,0x54,0x2c,0x23,0x31,0x19,0x06,0xb6,0x1b,0x21,0x12,0x06,0x1e,0x24,0x1e,0x16,0x16,0x46,0x1b,0x21,0x12,0x06,0x1e, 0x24,0x1e,0x15,0x17,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x02,0xac,0x03,0x0f,0x00,0x1f, 0x00,0x26,0xb1,0x0b,0x00,0xb8,0x05,0x0a,0xb7,0x1d,0x2f,0x1f,0x01,0x1f,0x0b,0x17,0x05,0xbb,0x04,0xfb,0x00,0x10,0x00,0x06,0x05,0x03,0x00,0x3f,0x33,0xed,0x32,0x39,0x2f,0x5d,0x01,0x2f,0xed,0x39,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e, 0x02,0x35,0x11,0x33,0x01,0xf2,0x0c,0x27,0x4a,0x3d,0x16,0x64,0x78,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0xbc,0x00,0x02,0xff,0xba,0xff,0xf2,0x03,0x49,0x03,0x62, 0x00,0x24,0x00,0x38,0x00,0x31,0xb9,0x00,0x12,0x05,0x0a,0xb3,0x25,0x25,0x3a,0x31,0xb8,0x05,0x0a,0xb2,0x05,0x36,0x20,0xbc,0x04,0xfb,0x00,0x19,0x05,0x03,0x00,0x2c,0x04,0xfb,0xb3,0x2f,0x0a,0x01,0x0a,0x00,0x2f,0x5d,0xed,0x3f,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32, 0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0xa5,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x14,0x26,0x1d,0x12,0x39,0x61,0x81,0x91,0x97,0x47,0xbf,0x23,0x23,0x23,0x23,0xc8, 0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x37,0x2c,0x1b,0x19,0x41,0x73,0x5a,0x21,0x1d,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x58,0x21,0x4a,0x52,0x5a,0x30,0x60,0x83,0x55,0x2e,0x15,0x04,0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3f,0x42, 0x4a,0x2a,0x18,0x4d,0x00,0x02,0xff,0xba,0xff,0xf2,0x04,0x02,0x03,0x62,0x00,0x2f,0x00,0x43,0x00,0x3e,0xb1,0x15,0x12,0xb8,0x05,0x0a,0xb4,0x30,0x30,0x05,0x19,0x3c,0xb8,0x05,0x0a,0xb5,0x05,0x1f,0x0a,0x41,0x2b,0x18,0xbd,0x04,0xfb,0x00,0x24,0x00,0x19,0x05,0x03,0x00,0x37,0x04,0xfb,0xb3,0x2f,0x0a,0x01,0x0a,0x00,0x2f,0x5d,0xed, 0x3f,0x33,0xed,0x32,0x32,0x12,0x39,0x01,0x2f,0xed,0x2f,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22, 0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0xa5,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x38,0x72,0x43,0x16,0x2c,0x60,0x5f,0x5c,0x27,0x32,0x70,0x75,0x74,0x34,0xbf,0x23,0x23,0x23,0x23,0xc8,0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19, 0x43,0x74,0x5b,0x21,0x19,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x53,0x56,0x21,0x4a,0x53,0x5a,0x30,0x42,0x64,0x26,0x09,0x03,0xa7,0x07,0x0e,0x16,0x0f,0x16,0x17,0x0b,0x02,0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3e,0x44,0x4a,0x2b,0x18,0x4f,0x00,0x01,0x00,0xab, 0xff,0xea,0x06,0x9f,0x03,0x0f,0x00,0x25,0x00,0x2c,0xb9,0x00,0x13,0x05,0x0a,0xb3,0x10,0x10,0x27,0x03,0xbd,0x05,0x0a,0x00,0x22,0x00,0x0b,0x04,0xfb,0x00,0x1a,0x05,0x03,0xb4,0x11,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xc6,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33, 0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x01,0x62,0x09,0x11,0x1e,0x30,0x1d,0x5c,0x91,0xd2,0x93,0x80,0xc0,0x7f,0x3f,0x9c,0x33,0x5d,0x81,0x9a,0xaf,0x5d,0x86,0xde,0xb3,0x87,0x30,0x3f,0x30,0x12,0x0b,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x63,0x23,0x15,0x1b,0x0f,0x05, 0x0a,0x29,0x53,0x48,0x01,0xae,0xfe,0x4b,0x5a,0x7c,0x52,0x2d,0x16,0x05,0x03,0x15,0x2d,0x29,0x37,0x98,0x58,0x3d,0x70,0x33,0x00,0x01,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xec,0x00,0x1f,0x00,0x26,0xb1,0x0b,0x00,0xb8,0x05,0x0a,0xb6,0x1d,0x1e,0x18,0x17,0x17,0x0b,0x05,0xbb,0x04,0xfb,0x00,0x10,0x00,0x06,0x05,0x03,0x00,0x3f,0x33, 0xed,0x39,0x32,0x11,0x33,0x2f,0x01,0x2f,0xed,0x39,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x01,0xf2,0x0c,0x27,0x4a,0x3d,0x16,0x61,0x74,0x1d,0x04,0x1b,0x43,0x48,0x49,0x22,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43, 0x38,0x25,0x9c,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x04,0x99,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x81,0x03,0x0f,0x02,0x26,0x0e,0x6f, 0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0x00,0x04,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x00,0x31,0x00,0x35,0x00,0x39,0x00,0x3d,0x00,0x74,0xb9,0x00,0x3b,0x05,0x0a,0xb2,0x3a,0x3a,0x39,0xb8,0x05,0x0a,0xb3,0x38,0x1d,0x38,0x32,0xb8,0x05,0x0a,0xb7,0x33,0x38,0x33,0x38,0x33,0x3f,0x26,0x05,0xbb,0x05,0x0a,0x00,0x16, 0x00,0x3a,0x05,0x02,0xb2,0x3d,0x36,0x32,0xb8,0x05,0x02,0x40,0x0d,0x38,0x2f,0x35,0x3f,0x35,0x02,0x35,0x31,0x1d,0x00,0x03,0x11,0x23,0xb8,0x04,0xff,0xb2,0x2a,0x0d,0x0a,0xb8,0x04,0xfc,0xb6,0x0e,0x1f,0x11,0x2f,0x11,0x02,0x11,0x00,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x2f,0x5d,0x33,0xfd,0x32,0xd6,0xed,0x01,0x2f, 0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x01,0x23,0x35,0x33,0x05,0x23, 0x35,0x33,0x03,0x23,0x35,0x33,0x04,0x0c,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe,0x6a,0xb5,0xb5,0x01,0x42,0xb5,0xb5,0xa1,0xb5,0xb5,0x02,0x01, 0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfd,0x64,0xb3,0xb3,0xb3,0xfe,0x3f,0xb3,0x00,0x00,0x05,0x00,0x7e,0xfd,0xff,0x05,0x58,0x03,0x54,0x00,0x03,0x00,0x07, 0x00,0x0b,0x00,0x3d,0x00,0x4b,0x00,0x97,0xb1,0x19,0x3e,0xbb,0x05,0x0b,0x00,0x49,0x00,0x09,0x05,0x0a,0xb2,0x08,0x08,0x04,0xbb,0x05,0x0a,0x00,0x05,0x00,0x00,0x05,0x0a,0x40,0x0b,0x01,0x49,0x05,0x01,0x01,0x05,0x49,0x03,0x4d,0x32,0x11,0xbd,0x05,0x0a,0x00,0x22,0x00,0x41,0x04,0xfb,0x00,0x43,0x05,0x03,0xb6,0x3e,0x0c,0x29,0x3d, 0x04,0x1d,0x2f,0xb8,0x04,0xff,0xb2,0x36,0x19,0x16,0xb8,0x04,0xfc,0x40,0x0c,0x1a,0x1f,0x1d,0x2f,0x1d,0x02,0x1d,0x07,0x06,0x06,0x02,0x08,0xb8,0x05,0x02,0xb7,0x0f,0x0b,0x1f,0x0b,0x02,0x0b,0x04,0x00,0xb8,0x05,0x02,0xb5,0x2f,0x02,0x3f,0x02,0x02,0x02,0x00,0x2f,0x5d,0xfd,0x32,0xde,0x5d,0xed,0x11,0x33,0x11,0x33,0x2f,0x5d,0x33, 0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x3f,0xed,0x01,0x2f,0xed,0x39,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x39,0x31,0x30,0x25,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x13,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35, 0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x13,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x36,0x36,0x02,0x78,0xb5,0xb5,0x01,0x2e,0xb5,0xb5,0x97,0xb5,0xb5,0xfd,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19, 0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0x2b,0x06,0x74,0x68,0x1f,0x37,0x4f,0x77,0x52,0x2c,0x04,0x1f,0x3f,0x02,0xb3,0xb3,0xb3,0xfe,0x49,0xb3,0x02,0x50,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38, 0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfe,0x9a,0x68,0x55,0xa7,0x30,0x56,0x74,0x44,0x0b,0x13,0x00,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x00,0xfd,0xff, 0x02,0x9e,0x05,0x1f,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x9a,0x03,0x57,0x00,0x01,0x00,0xab,0xff,0xea,0x06,0xa2,0x06,0x02,0x00,0x36,0x00,0x33,0xb2,0x1e,0x23,0x03,0xbb,0x05,0x0a,0x00,0x33,0x00,0x23,0x05,0x0a,0x40,0x09,0x15,0x1a,0x1e,0x1b,0x03,0x00,0x00,0x1c,0x0b,0xbb,0x04,0xfb,0x00,0x2b,0x05,0x03,0x00, 0x1c,0x00,0x2f,0x3f,0xed,0x12,0x39,0x2f,0x17,0x39,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x27,0x35,0x01,0x15,0x01,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37, 0x01,0x62,0x09,0x11,0x1f,0x2f,0x1a,0x4f,0x7b,0xb1,0x7c,0x4e,0x7e,0x67,0x51,0x20,0x25,0x32,0x1c,0x0c,0x57,0xa3,0xe8,0x91,0x03,0x4b,0xfd,0x66,0x8b,0xe1,0x9e,0x56,0x0f,0x31,0x5d,0x4f,0x57,0xef,0xa5,0x76,0xc2,0x9b,0x78,0x2c,0x3f,0x30,0x12,0x0b,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x63,0x23,0x13,0x1a,0x10,0x07,0x01,0x06,0x0a,0x09, 0x0a,0x1d,0x26,0x2c,0x1a,0x4d,0x8b,0x86,0x85,0x47,0x76,0x02,0x22,0xb0,0xfe,0x5f,0x42,0x8b,0x96,0xa6,0x5e,0x1f,0x56,0x59,0x50,0x19,0x1b,0x0e,0x06,0x16,0x2c,0x26,0x37,0x98,0x58,0x3d,0x70,0x33,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0x02,0x02,0x06,0x08,0xed,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x07,0x38, 0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x07,0x38,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff,0x00,0x9a,0xff,0x55,0x05,0x91,0x04,0x15,0x02,0x06,0x09,0x2a,0x00,0x00,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x02,0x13,0x02,0x06, 0x08,0xf7,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x48,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0xa1,0xff,0xf2,0x04,0x02,0x06,0x19,0x02,0x26,0x08,0xf3,0x00,0x00,0x00,0x07,0x09,0x7e,0x01,0x3e,0xfe,0x30,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x06,0x12,0x02,0x26, 0x09,0x28,0x00,0x00,0x01,0x07,0x09,0x7e,0x01,0x16,0xfe,0x29,0x00,0x0a,0xb4,0x02,0x2f,0x40,0x01,0x40,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb9,0x01,0xac,0x02,0x89,0x03,0x7c,0x02,0x06,0x08,0xd7,0x00,0x00,0xff,0xff,0x00,0x2b,0x00,0x00,0x01,0x56,0x05,0x9a,0x02,0x06,0x08,0xd8,0x00,0x00,0xff,0xff,0x00,0x2b,0x00,0x00,0x03,0x50, 0x05,0x9a,0x02,0x06,0x08,0xd9,0x00,0x00,0xff,0xff,0x00,0x2b,0x00,0x00,0x04,0x1a,0x05,0x9a,0x02,0x06,0x08,0xda,0x00,0x00,0x00,0x01,0x00,0x2b,0x00,0x00,0x03,0x70,0x05,0xb7,0x00,0x36,0x00,0x4a,0xb5,0x1d,0x0b,0x38,0x29,0x02,0x2f,0xb8,0x05,0x0a,0x40,0x09,0x30,0x1e,0x1d,0x1d,0x13,0x02,0x03,0x07,0x2f,0xbb,0x04,0xe6,0x00,0x29, 0x00,0x23,0x04,0xfb,0xb4,0x2f,0x18,0x01,0x18,0x0e,0xb8,0x04,0xfb,0xb7,0x2f,0x07,0x01,0x07,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x39,0x3f,0x12,0x17,0x39,0x11,0x33,0x01,0x2f,0xed,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x13,0x17,0x33,0x3e,0x03,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02, 0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x07,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x26,0x26,0x02,0x27,0xcb,0x30,0x05,0x0e,0x3f,0x5f,0x7d,0x4b,0x20,0x49,0x24,0x23,0x45,0x23,0x43,0x77,0x5a,0x34,0x29,0x41,0x51,0x29,0x32,0x62,0x5b,0x50,0x1f,0x14,0x49,0x5c,0x6b,0x36,0x1e,0x3e,0x39, 0x32,0x13,0x04,0x07,0x0c,0x07,0x04,0x9c,0x11,0x23,0x36,0x25,0x05,0x9a,0xd2,0x2f,0x56,0x42,0x28,0x08,0x09,0xa6,0x08,0x08,0x1b,0x30,0x43,0x28,0x23,0x33,0x21,0x0f,0x14,0x20,0x28,0x14,0xaa,0x11,0x26,0x21,0x15,0x08,0x10,0x19,0x11,0x03,0x38,0x71,0x7a,0x84,0x4a,0xfe,0x85,0x01,0x73,0x94,0xff,0xf8,0x01,0x03,0x99,0x00,0x00,0x02, 0x00,0x72,0xff,0xe9,0x04,0x28,0x05,0x9a,0x00,0x1e,0x00,0x3f,0x00,0x46,0xbf,0x00,0x17,0x05,0x0a,0x00,0x2a,0x00,0x20,0x05,0x0a,0x00,0x1f,0x00,0x38,0x05,0x0a,0xb3,0x09,0x3d,0x3d,0x25,0xb8,0x04,0xfb,0xb7,0x1c,0x00,0x1c,0x20,0x20,0x10,0x04,0x1c,0xba,0x05,0x03,0x00,0x31,0x04,0xff,0xb3,0x2f,0x10,0x01,0x10,0x00,0x2f,0x5d,0xed, 0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x10,0xed,0x32,0x2f,0x01,0x2f,0xed,0xd4,0xed,0xd6,0xed,0x31,0x30,0x25,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x03,0x33,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x23,0x22,0x0e,0x04,0x15,0x14,0x1e,0x02, 0x33,0x32,0x36,0x02,0x51,0x08,0x2a,0x66,0x3d,0x31,0x5f,0x4b,0x2f,0x2c,0x4b,0x62,0x6b,0x6e,0x31,0x30,0x6b,0x68,0x5e,0x48,0x2a,0x32,0x4f,0x64,0x31,0x3b,0x61,0x6c,0x86,0x0f,0x1f,0x2e,0x1f,0x1a,0x2f,0x23,0x15,0x1e,0x32,0x42,0x48,0x4a,0x21,0x21,0x48,0x46,0x3e,0x30,0x1c,0x14,0x23,0x2f,0x1c,0x36,0x41,0x7d,0x51,0x43,0x2c,0x70, 0xbe,0x92,0x8e,0xfd,0xd6,0xac,0x78,0x40,0x3e,0x75,0xa6,0xd1,0xf7,0x8a,0x98,0xc7,0x76,0x30,0x43,0x01,0x39,0x2d,0x4b,0x37,0x1e,0x1a,0x46,0x7a,0x60,0x72,0xd1,0xb3,0x92,0x67,0x38,0x39,0x68,0x91,0xb1,0xcd,0x6e,0x5c,0x7c,0x4c,0x20,0x6a,0x00,0x01,0x00,0x2f,0xff,0xf5,0x03,0x65,0x05,0xa4,0x00,0x28,0x00,0x3d,0xb5,0x00,0x16,0x07, 0x03,0x2a,0x1e,0xbb,0x05,0x0a,0x00,0x0d,0x00,0x08,0x04,0xfc,0x40,0x09,0x2f,0x23,0x01,0x23,0x00,0x28,0x28,0x03,0x19,0xb8,0x04,0xfb,0xb5,0x2f,0x12,0x01,0x12,0x04,0x03,0xb8,0x04,0xe6,0x00,0x3f,0x33,0x2f,0x5d,0xed,0x12,0x39,0x11,0x33,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x31,0x30,0x01,0x06,0x00,0x03,0x27,0x36,0x12, 0x37,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x36,0x36,0x37,0x03,0x65,0xe1,0xfe,0x7d,0xac,0x26,0x5e,0xec,0x84,0x01,0x49,0x74,0x51,0x2b,0x3b,0x6e,0x9e,0x62,0x1d,0x47,0x23,0x20,0x4d,0x21,0x37,0x5f,0x46,0x28,0x21,0x3a,0x51,0x2f,0x45,0x4d, 0x26,0x4a,0x27,0x03,0x0a,0x6e,0xfe,0x77,0xfe,0xe2,0xc2,0x9e,0x01,0x17,0x6b,0x04,0x0c,0x3b,0x5a,0x76,0x46,0x53,0x86,0x5f,0x34,0x05,0x05,0xab,0x05,0x07,0x17,0x31,0x4f,0x39,0x34,0x4e,0x35,0x1a,0x1b,0x17,0x2a,0x14,0xff,0xff,0xff,0xf4,0x00,0x00,0x03,0xfa,0x05,0x9a,0x02,0x06,0x08,0xde,0x00,0x00,0xff,0xff,0x00,0x49,0x00,0x00, 0x04,0x4f,0x05,0x9a,0x02,0x06,0x08,0xdf,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x03,0xdb,0x05,0xa8,0x02,0x06,0x08,0xe0,0x00,0x00,0x00,0x01,0x00,0x9b,0xfe,0xac,0x05,0x58,0x05,0xec,0x00,0x28,0x00,0x36,0xb1,0x1b,0x10,0xb8,0x05,0x0a,0xb3,0x0d,0x0d,0x17,0x03,0xb8,0x05,0x0a,0xb2,0x25,0x17,0x08,0xb8,0x04,0xfb,0xb2,0x20,0x1b, 0x15,0xba,0x04,0xfb,0x00,0x16,0x05,0x03,0xb1,0x0f,0x00,0x00,0x2f,0x2f,0x3f,0xed,0x39,0x2f,0xed,0x01,0x2f,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36, 0x37,0x01,0x4e,0x0b,0x0b,0x23,0x4f,0x7d,0x59,0x67,0x93,0x5d,0x2b,0x9c,0x0c,0x27,0x4a,0x3d,0x13,0x49,0x59,0x1c,0x04,0x11,0x4c,0x7f,0xb7,0x7c,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x01,0xa6,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x04,0xc4,0xfb,0xb0,0x43,0x61,0x40,0x1f,0xa7,0x28,0x26,0x5f,0x95,0x69,0x37,0x45,0x7f, 0xb7,0x72,0x3f,0x83,0x4b,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x05,0xb9,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x57,0x02,0xad,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9e,0x06,0x32,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07, 0x0f,0x57,0x00,0x72,0x03,0xd0,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x07,0x0f,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0xc6,0x05,0xb9,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0x9a,0x03,0x57,0x00,0x01,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x01,0xc1, 0x00,0x20,0x00,0x34,0xb9,0x00,0x02,0x05,0x0a,0xb3,0x1d,0x1d,0x22,0x13,0xb8,0x05,0x0a,0x40,0x0a,0x0c,0x2f,0x20,0x01,0x20,0x2f,0x10,0x01,0x10,0x18,0xb8,0x04,0xfb,0xb5,0x1f,0x07,0x2f,0x07,0x02,0x07,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0x2f,0x5d,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x16,0x15,0x14,0x0e,0x02,0x23,0x22, 0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x04,0x84,0x22,0x37,0x83,0xd6,0x9e,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x94,0x5e,0x2b,0x11,0x10,0x01,0xc1,0xb9,0xa1,0x8f,0xe4,0x9f,0x56,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f, 0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x45,0x9d,0x64,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x03,0xce,0x02,0x06,0x09,0x28,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0x0a,0x01,0xf2,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x06,0x0f,0x5a,0x00,0x00,0x00,0x01,0xff,0xba,0xfd,0xfa,0x04,0x02,0x02,0x01,0x00,0x32,0x00,0x48, 0xb9,0x00,0x1e,0x05,0x0b,0x40,0x0a,0x13,0x09,0x09,0x13,0x13,0x24,0x19,0x28,0x28,0x0e,0xb8,0x05,0x0a,0xb5,0x03,0x24,0x19,0x28,0x18,0x00,0xbb,0x04,0xfb,0x00,0x19,0x00,0x2b,0x05,0x03,0xb7,0x2f,0x1f,0x01,0x1f,0x2f,0x09,0x01,0x09,0x00,0x2f,0x5d,0x2f,0x5d,0x3f,0x33,0xed,0x32,0x39,0x01,0x2f,0x2f,0x33,0xed,0x33,0x2f,0x11,0x12, 0x39,0x2f,0x33,0x2f,0x10,0xed,0x31,0x30,0x37,0x32,0x36,0x37,0x3e,0x03,0x37,0x33,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x3e,0x03,0x33,0x15,0x22,0x0e,0x02,0x15,0x15,0x2e,0x03,0x35,0x34,0x36,0x37,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x9b,0x30,0x3d,0x0e,0x09,0x10,0x1c,0x2e,0x27,0x97,0x2f,0x42,0x28,0x12,0x21, 0x33,0x3e,0x1e,0x07,0x42,0x73,0xa2,0x68,0x57,0x81,0x54,0x2a,0x7c,0xa9,0x68,0x2d,0x07,0x06,0x04,0x1a,0x40,0x2d,0x74,0x23,0x23,0x23,0x23,0x99,0x0a,0x0e,0x09,0x26,0x4b,0x7a,0x5c,0x67,0xa8,0x8b,0x71,0x2e,0x45,0x59,0x38,0x1e,0x09,0x60,0xa9,0x7d,0x48,0xa7,0x3f,0x76,0xa9,0x6a,0x30,0x18,0x47,0x60,0x7b,0x4d,0x20,0x43,0x25,0x02, 0x0c,0x0d,0x34,0x20,0x20,0x33,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x06,0x12,0x02,0x26,0x09,0x28,0x00,0x00,0x01,0x07,0x09,0x7e,0x01,0x16,0xfe,0x29,0x00,0x0a,0xb4,0x02,0x2f,0x40,0x01,0x40,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x05,0x5d,0x02,0x26,0x09,0x28,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x01, 0x04,0xad,0x00,0x01,0x00,0x72,0xff,0xea,0x06,0xe5,0x03,0x5b,0x00,0x2b,0x00,0x1f,0xb9,0x00,0x0a,0x05,0x0a,0xb6,0x21,0x00,0x2f,0x2b,0x01,0x2b,0x0f,0xba,0x04,0xfb,0x00,0x1a,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xcd,0x01,0x2f,0xed,0x31,0x30,0x01,0x0e,0x03,0x07,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e, 0x03,0x23,0x22,0x2e,0x04,0x35,0x34,0x3e,0x02,0x37,0x3e,0x03,0x37,0x03,0x4b,0x3a,0x72,0x69,0x60,0x28,0x24,0x3b,0x2a,0x17,0x45,0x93,0xe5,0xa1,0x7b,0xf4,0xe5,0xcf,0x56,0x72,0xf9,0xf0,0xda,0x54,0x93,0xe1,0xa6,0x70,0x43,0x1d,0x27,0x43,0x5c,0x35,0x2e,0x62,0x63,0x60,0x2c,0x02,0xd3,0x30,0x4e,0x3f,0x34,0x16,0x14,0x25,0x25,0x28, 0x18,0x2e,0x3c,0x23,0x0e,0x07,0x0c,0x10,0x09,0xa5,0x0c,0x12,0x0c,0x06,0x12,0x24,0x35,0x45,0x55,0x32,0x37,0x5a,0x4c,0x43,0x20,0x1c,0x38,0x3c,0x43,0x27,0x00,0x01,0x00,0x72,0xfe,0x28,0x06,0xe5,0x00,0x99,0x00,0x25,0x00,0x23,0xbc,0x00,0x06,0x05,0x0a,0x00,0x1d,0x00,0x0b,0x04,0xfb,0xb4,0x2f,0x16,0x01,0x16,0x24,0xba,0x04,0xfb, 0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x04,0x35,0x34,0x3e,0x04,0x33,0x33,0x02,0xac,0x0d,0x43,0x8e,0x75,0x4b,0x45,0x93,0xe5,0xa1,0x7b,0xf4,0xe5,0xcf,0x56,0x72,0xf9,0xf0,0xda,0x54,0x93, 0xe1,0xa6,0x70,0x43,0x1d,0x3d,0x63,0x7c,0x7d,0x72,0x27,0x08,0x0e,0x04,0x19,0x37,0x32,0x2e,0x3c,0x23,0x0e,0x07,0x0c,0x10,0x09,0xa5,0x0c,0x12,0x0c,0x06,0x12,0x24,0x35,0x45,0x55,0x32,0x4a,0x69,0x45,0x28,0x15,0x05,0xff,0xff,0x00,0x72,0xff,0xea,0x06,0xe5,0x05,0x3e,0x02,0x26,0x09,0x65,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0xab, 0xfd,0x55,0x00,0x0a,0xb4,0x01,0x2f,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x3d,0x02,0x26,0x09,0x66,0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0xab,0xfb,0x54,0x00,0x01,0x00,0x2d,0x00,0x00,0x01,0xab,0x00,0xbc,0x00,0x03,0x00,0x13,0xb2,0x03,0x02,0x02,0xba,0x04,0xfb,0x00,0x00,0x04,0xe6,0x00, 0x3f,0xed,0x01,0x2f,0xcd,0x31,0x30,0x21,0x21,0x27,0x21,0x01,0xab,0xfe,0xaa,0x28,0x01,0x7e,0xbc,0x00,0x00,0x03,0x00,0x7c,0x00,0x00,0x04,0x18,0x05,0x58,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x34,0xbc,0x00,0x05,0x05,0x0c,0x00,0x04,0x00,0x01,0x05,0x0c,0xb5,0x00,0x2f,0x09,0x01,0x09,0x08,0xba,0x04,0xe6,0x00,0x06,0x04,0xfe,0xb4, 0x2f,0x05,0x01,0x05,0x02,0xb9,0x04,0xfe,0x00,0x01,0x00,0x2f,0xed,0x2f,0x5d,0xed,0x3f,0x2f,0x5d,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x13,0x33,0x15,0x23,0x01,0x33,0x15,0x23,0x05,0x01,0x33,0x01,0xc0,0xf7,0xf7,0x02,0x36,0xf7,0xf7,0xfd,0x86,0x03,0x0d,0x8f,0xfc,0xf3,0x04,0xfd,0xf7,0xfd,0x4c,0xf7,0x5b,0x05,0x58,0xfa,0xa8,0x00, 0x00,0x01,0x00,0x42,0x01,0xae,0x02,0xd9,0x04,0x25,0x00,0x0e,0x00,0x0c,0xb4,0x20,0x03,0x01,0x03,0x0c,0x00,0x2f,0xc4,0x5d,0x31,0x30,0x01,0x07,0x17,0x07,0x27,0x07,0x27,0x37,0x27,0x37,0x17,0x27,0x33,0x07,0x37,0x02,0xd9,0xf6,0xa6,0x7b,0x81,0x81,0x7b,0xa6,0xf5,0x2f,0xe7,0x16,0x97,0x16,0xe7,0x02,0xfe,0x37,0xbf,0x5a,0xdb,0xdb, 0x5a,0xbf,0x37,0x8f,0x64,0xfc,0xfc,0x64,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x4b,0x06,0x3c,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x53,0x04,0xd7,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x06,0x3c,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02, 0x06,0x3c,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x04,0x74,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xa1,0xff,0xf2,0x07,0x4a,0x08,0x36,0x00,0x3a,0x00,0x48,0x00,0x4c, 0x00,0x7a,0x00,0xdd,0xb9,0x00,0x0d,0x05,0x0a,0xb3,0x0a,0x66,0x66,0x69,0xb8,0x05,0x0d,0xb6,0x63,0x65,0x65,0x63,0x5a,0x5a,0x5d,0xb8,0x05,0x0d,0x40,0x09,0x4a,0x4b,0x4b,0x56,0x56,0x4a,0x59,0x59,0x49,0xb8,0x05,0x0b,0xb4,0x16,0x70,0x4a,0x4a,0x00,0xb8,0x05,0x0a,0xb3,0x38,0x4d,0x4d,0x50,0xb8,0x05,0x0b,0xb5,0x78,0x7a,0x7a,0x78, 0x43,0x2d,0xb8,0x05,0x0a,0x40,0x0e,0x2c,0x0a,0x63,0x38,0x78,0x2c,0x2c,0x78,0x38,0x63,0x0a,0x05,0x7c,0x3b,0xbb,0x05,0x0a,0x00,0x26,0x00,0x21,0x04,0xfb,0xb6,0x2f,0x40,0x01,0x40,0x16,0x33,0x05,0xbb,0x04,0xfb,0x00,0x19,0x00,0x12,0x05,0x03,0x40,0x0b,0x70,0x60,0x6c,0x30,0x4c,0x01,0x4c,0x49,0x5a,0x53,0x60,0xb8,0x04,0xfd,0xb3, 0x73,0x6c,0x0b,0x44,0xb8,0x04,0xfc,0x40,0x0a,0x2b,0x2f,0x2c,0x01,0x2c,0x3a,0x20,0x0b,0x01,0x0b,0x00,0x2f,0x5d,0xd6,0xd4,0x5d,0xdd,0xed,0x10,0xd4,0x32,0xfd,0x32,0xd6,0xde,0xcd,0x5d,0x11,0x12,0x39,0x3f,0x33,0xed,0x32,0x39,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x33,0x11,0x33,0x2f, 0x10,0xed,0x32,0x2f,0x10,0xed,0x39,0x2f,0x39,0x39,0xed,0x33,0x2f,0x11,0x33,0x2f,0x33,0x2f,0x10,0xe4,0x32,0x2f,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x10,0xed,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x01,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x11,0x0e,0x03,0x01,0x23,0x11,0x33,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x34,0x27,0x33,0x06,0x14,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x16,0x15, 0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x05,0x49,0x0c,0x26,0x46,0x39,0x25,0x42,0x31,0x1c,0x9c,0x3c,0x61,0x7b,0x3e,0x68,0x75,0x1c,0x04,0x31,0x91,0x49,0x38,0x64,0x50,0x3a,0x0e,0x2b,0x62,0x2a,0x45,0x7f,0x62,0x3a,0x58,0x92,0xbc,0x65,0x9c,0x0e,0x26,0x44,0x36,0x1d,0x40,0x36,0x24,0x9c, 0xfb,0xee,0x23,0x3c,0x4e,0x2a,0x27,0x55,0x22,0x4d,0x87,0x66,0x3b,0x04,0x03,0x74,0x74,0xfe,0xf5,0x03,0x01,0x26,0x2d,0x2c,0x23,0x01,0x5f,0x01,0x22,0x2d,0x2f,0x25,0x03,0x5f,0x01,0x01,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x03,0x01,0x8c,0x3b,0x5a,0x3e,0x20,0x16,0x2d,0x46,0x31,0x04,0x2b,0xfb,0xce, 0x65,0x86,0x4f,0x20,0x40,0x3b,0x3f,0x3c,0x19,0x35,0x52,0x3a,0x11,0x0c,0x20,0x45,0x6c,0x4d,0x5e,0x92,0x68,0x42,0x0f,0x61,0xfd,0xb5,0x3d,0x5b,0x3d,0x1e,0x13,0x2c,0x47,0x34,0x03,0x95,0xfc,0xf4,0x26,0x35,0x21,0x0e,0x0a,0x0b,0x01,0x76,0x0e,0x2f,0x41,0x52,0x04,0xd3,0x01,0x56,0xfe,0x57,0x1c,0x18,0x09,0x33,0x3f,0x3e,0x3b,0x0d, 0x1c,0x0d,0x0e,0x1c,0x0b,0x3d,0x3d,0x3e,0x37,0x1f,0x1b,0x0c,0x18,0x08,0x6d,0x76,0x1f,0x20,0x20,0x1f,0x22,0x3a,0x4e,0x2c,0x21,0x18,0x00,0x01,0x00,0x57,0xff,0xaf,0x04,0x02,0x01,0xbb,0x00,0x1e,0x00,0x2a,0xbc,0x00,0x0d,0x05,0x0a,0x00,0x12,0x00,0x08,0x04,0xfb,0x40,0x09,0x2f,0x17,0x01,0x17,0x2f,0x0e,0x01,0x0e,0x1e,0xba,0x04, 0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x05,0x23,0x22,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x04,0x33,0x04,0x02,0x0c,0x42,0x6c,0x60,0x56,0x55,0x58,0x32,0x2a,0x4d,0x3b,0x23,0x83,0x03,0x01,0x42,0x69,0x80,0x3f,0x3f,0x6b, 0x60,0x58,0x56,0x58,0x31,0x0e,0x2b,0x40,0x4c,0x40,0x2b,0x23,0x4e,0x7c,0x58,0x20,0x16,0x1e,0x05,0x7e,0xb2,0x70,0x33,0x2b,0x40,0x4c,0x40,0x2b,0x00,0x01,0x00,0xc4,0x06,0x7c,0x01,0x42,0x08,0x04,0x00,0x03,0x00,0x15,0xbd,0x00,0x00,0x05,0x0b,0x00,0x01,0x00,0x00,0x04,0xfe,0x00,0x03,0x00,0x2f,0xed,0x01,0x10,0xed,0x31,0x30,0x01, 0x23,0x11,0x33,0x01,0x42,0x7e,0x7e,0x06,0x7c,0x01,0x88,0x00,0x00,0x02,0xff,0x17,0x06,0x1d,0x02,0xee,0x08,0xde,0x00,0x53,0x00,0x65,0x00,0x6f,0xb5,0x09,0x26,0x61,0x03,0x47,0x1a,0xb8,0x05,0x0d,0xb2,0x59,0x2d,0x00,0xbb,0x05,0x0d,0x00,0x51,0x00,0x38,0x05,0x0d,0xb2,0x47,0x53,0x15,0xb8,0x05,0x01,0x40,0x11,0x5c,0x54,0x26,0x2d, 0x54,0x1f,0x61,0x61,0x54,0x4c,0x4c,0x54,0x10,0x10,0x0a,0x03,0x54,0xb8,0x05,0x01,0x40,0x09,0x1f,0x35,0x35,0x30,0x30,0x29,0x29,0x1f,0x3b,0xb9,0x05,0x01,0x00,0x42,0x00,0x2f,0xfd,0xce,0x32,0x2f,0x32,0x2f,0x32,0x2f,0x10,0xfd,0x32,0xcc,0x33,0x2f,0x11,0x33,0x2f,0x11,0x33,0x2f,0x11,0x12,0x39,0x39,0x10,0xde,0xfd,0xc6,0x01,0x2f, 0xed,0x2f,0xed,0x39,0x2f,0xed,0x11,0x17,0x39,0x31,0x30,0x13,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x26,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x22,0x06,0x22,0x23,0x22,0x06,0x15, 0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x37,0x36,0x36,0x35,0x11,0x33,0x01,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x32,0x32,0x16,0x32,0x61,0x0e,0x1a,0x1a,0x15,0x05,0x05,0x51,0x06,0x09,0x02,0x04,0x13,0x1d,0x0d,0x2f,0x43,0x57,0x36,0x28,0x3c,0x27,0x13, 0x20,0x46,0x71,0x51,0x48,0x61,0x15,0x0a,0x14,0x06,0x01,0x12,0x31,0x1a,0x1f,0x28,0x0a,0x01,0x11,0x2c,0x16,0x03,0x0e,0x0f,0x0e,0x04,0x18,0x26,0x60,0x69,0x63,0x9b,0x40,0x52,0xab,0x43,0x46,0x6c,0x49,0x26,0x25,0x35,0x3b,0x16,0x1d,0x10,0x0e,0x0c,0x58,0x01,0x9b,0x2e,0x3b,0x23,0x0e,0x34,0x25,0x1f,0x34,0x29,0x1e,0x09,0x08,0x1c, 0x1d,0x1b,0x07,0x7e,0x2a,0x27,0x1c,0x1a,0x0b,0x2a,0x12,0x18,0x2f,0x0b,0x10,0x18,0x02,0x27,0x5f,0x53,0x38,0x22,0x3a,0x50,0x2d,0x3a,0x40,0x1e,0x06,0x03,0x08,0x04,0x14,0x0b,0x18,0x13,0x17,0x14,0x19,0x12,0x01,0x0f,0x12,0x19,0x10,0x09,0x06,0x61,0x08,0x09,0x0c,0x1e,0x33,0x28,0x29,0x35,0x1f,0x0d,0x08,0x08,0x17,0x15,0x01,0x76, 0xfe,0x4d,0x02,0x0e,0x1b,0x1a,0x39,0x33,0x1f,0x33,0x3f,0x1f,0x01,0x00,0x00,0x01,0x00,0x10,0x06,0x71,0x01,0xbb,0x08,0xde,0x00,0x14,0x00,0x27,0xb9,0x00,0x0c,0x05,0x0d,0xb5,0x09,0x06,0x06,0x00,0x00,0x03,0xb8,0x05,0x01,0xb5,0x11,0x14,0x14,0x11,0x0b,0x05,0x00,0x2f,0xc4,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x32,0x2f,0x01,0x2f, 0xed,0x31,0x30,0x13,0x16,0x16,0x33,0x03,0x33,0x13,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x10,0x2e,0x51,0x27,0x99,0x5d,0x98,0x28,0x28,0x59,0x23,0x3d,0x53,0x30,0x2d,0x5e,0x30,0x06,0xe2,0x06,0x04,0x01,0xca,0xfe,0x37,0x02,0x1c,0x2a,0x01,0xbd,0xfe,0x22,0x34,0x3a,0x1b,0x06,0x04,0x06,0x00,0xff,0xff, 0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xc2,0xfd,0xfe,0x01,0xa2,0xff,0x6b,0x00,0x28,0x00,0x3e,0xbc,0x00,0x1b,0x05,0x0d,0x00,0x0d,0x00,0x26,0x04,0xfd,0xb5,0x04,0x04,0x1f,0x14,0x14,0x12,0xb8,0x04,0xfd,0x40,0x0a,0x00,0x18,0x10,0x18,0x02,0x18,0x1f,0x09,0x09,0x1f,0xb8,0x04,0xfd, 0xb3,0x1f,0x20,0x01,0x20,0x00,0x2f,0x5d,0xed,0x32,0x2f,0x10,0xde,0x5d,0xed,0x32,0x2f,0x11,0x39,0x2f,0xed,0x01,0x2f,0xed,0x31,0x30,0x03,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x23,0x22,0x07, 0x3e,0x19,0x28,0x11,0x11,0x1d,0x1f,0x24,0x19,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x0d,0x1d,0x10,0x2d,0x3e,0x46,0x48,0x46,0xc7,0x31,0x40,0x2b,0x1e,0x0f,0x1f,0x2e,0xfe,0x06,0x56,0x15,0x10,0x0c,0x0f,0x0c,0x01,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0x65,0x03,0x04,0x26,0x25,0x30,0x2d,0x61,0x0f,0x11,0x0f,0x28, 0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00, 0x00,0x02,0x00,0x9b,0xfd,0xff,0x05,0x4b,0x02,0xb7,0x00,0x30,0x00,0x44,0x00,0x5b,0xb2,0x31,0x31,0x14,0xbb,0x05,0x0a,0x00,0x00,0x00,0x3d,0x05,0x0a,0xb6,0x07,0x00,0x07,0x00,0x07,0x46,0x25,0xb8,0x05,0x0a,0xb3,0x1e,0x1e,0x13,0x2a,0xb8,0x04,0xfb,0x40,0x0a,0x1f,0x19,0x2f,0x19,0x02,0x19,0x22,0x22,0x02,0x38,0xb8,0x04,0xfb,0xb5, 0x2f,0x0c,0x01,0x0c,0x00,0x42,0xba,0x04,0xfb,0x00,0x02,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x2f,0x5d,0xed,0x3f,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x33,0x2f,0x31,0x30,0x25,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23, 0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x35,0x2e,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x04,0xad,0x50,0x5c,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x1b,0x28,0x1b,0x0e,0x4a,0x98,0xed,0xa3,0xa1,0xdb,0x87,0x3b,0x0f,0x0e,0x97,0x0b,0x0c, 0x2b,0x64,0xa5,0x7a,0x67,0x93,0x64,0x3b,0x21,0x0b,0x01,0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0x17,0x25,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x2a,0x68,0x75,0x7f,0x40,0x95,0xdc,0x91,0x47,0x41,0x7c,0xb7,0x77,0x3f,0x8c,0x4e,0x4b,0x7d,0x36,0x5f,0x84,0x54,0x26,0x1d,0x32, 0x46,0x51,0x5b,0xd0,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x49,0x06,0x7c,0x01,0xa2,0x07,0xe9,0x00,0x18,0x00,0x2f,0xb1,0x0e,0x06,0xb8,0x05,0x0d,0xb6,0x11,0x0e,0x09,0x0a,0x18,0x18,0x16, 0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c,0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x11,0x12,0x39,0x01,0x2f,0xed,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e, 0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x07,0x7e,0x03,0x04,0x25,0x2b,0x58,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0x00,0x01,0x00,0x49,0xfd,0xfe,0x01,0xa2,0xff,0x6b,0x00,0x18,0x00,0x34,0xb1,0x0e,0x06,0xb8,0x05,0x0d,0xb3,0x11,0x18,0x18,0x16,0xb8,0x04,0xfd,0x40,0x0a,0x00,0x03, 0x10,0x03,0x02,0x03,0x09,0x0d,0x0d,0x09,0xb8,0x04,0xfd,0xb3,0x1f,0x0a,0x01,0x0a,0x00,0x2f,0x5d,0xed,0x32,0x2f,0x10,0xde,0x5d,0xed,0x32,0x2f,0x01,0x2f,0xed,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0x73,0x0d,0x1d,0x10,0x2d, 0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xff,0x00,0x03,0x04,0x26,0x27,0x5b,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0x00,0xff,0xff,0xff,0x97,0x00,0x00,0x01,0xf0,0x07,0xe8,0x02,0x26,0x09,0x0d,0x00,0x00,0x00,0x06,0x0f,0x58,0x00,0x00,0xff,0xff,0xff,0x97,0xff,0xf2,0x02,0x01, 0x07,0xe8,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x0f,0x58,0x00,0x00,0xff,0xff,0xff,0xc2,0x00,0x00,0x01,0xa2,0x07,0xe9,0x02,0x26,0x09,0x0d,0x00,0x00,0x01,0x07,0x09,0x77,0x00,0x00,0x08,0x7e,0x00,0x0a,0xb4,0x01,0x20,0x23,0x01,0x23,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xc2,0xff,0xf2,0x02,0x01,0x07,0xe9,0x02,0x26,0x08,0xc7, 0x00,0x00,0x01,0x07,0x09,0x77,0x00,0x00,0x08,0x7e,0x00,0x0a,0xb4,0x01,0x20,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xc2,0xfd,0xfe,0x01,0xa2,0x05,0xec,0x02,0x26,0x09,0x0d,0x00,0x00,0x00,0x06,0x09,0x77,0x00,0x00,0xff,0xff,0xff,0xc2,0xfd,0xfe,0x02,0x01,0x05,0xec,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x09,0x77, 0x00,0x00,0xff,0xff,0x00,0xab,0x00,0x00,0x02,0xf8,0x05,0xec,0x00,0x26,0x09,0x0d,0x00,0x00,0x01,0x07,0x09,0x7e,0x01,0x56,0xfe,0x00,0x00,0x0a,0xb4,0x01,0x20,0x1a,0x01,0x1a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xf2,0x03,0x57,0x05,0xec,0x00,0x26,0x08,0xc7,0x00,0x00,0x00,0x27,0x09,0x21,0x02,0x01,0x00,0x00,0x01,0x07, 0x09,0x7e,0x01,0x56,0xfe,0x00,0x00,0x0a,0xb4,0x02,0x20,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0xa3,0x05,0x3e,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x07,0x09,0x7e,0x02,0x01,0xfd,0x55,0xff,0xff,0xff,0xe7,0xfd,0xff,0x03,0xa3,0x05,0x63,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x27,0x09,0x7e,0x02,0x01, 0xfd,0x55,0x00,0x07,0x09,0x30,0x00,0x28,0xfd,0x55,0xff,0xff,0x00,0x9a,0xff,0x55,0x06,0x4f,0x05,0xe9,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x09,0x7e,0x04,0xad,0xfe,0x00,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xfa,0x05,0x3e,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x09,0x7e,0x05,0x58,0xfd,0x55,0xff,0xff,0x00,0xab,0xff,0xea, 0x06,0x9f,0x05,0xca,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x52,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x01,0xf9,0x05,0xca,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x52,0x02,0xad, 0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x01,0xf2,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0xab,0xfe,0xee,0x06,0x9f,0x04,0xb2,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x27,0x0f,0x5b,0x02,0xad,0x00,0xef,0x01,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0x00,0x0c,0xb5,0x02,0x01,0x20, 0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0x05,0x02,0x9a,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x5b,0x00,0x1a,0x01,0x06,0x01,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0x00,0x0c,0xb5,0x02,0x01,0x20,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x05,0xca, 0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9a,0x05,0xca,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x05,0xca,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x56,0x02,0xad,0x04,0x02,0xff,0xff, 0xff,0xba,0xff,0xf2,0x02,0x9a,0x05,0xca,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x56,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x81,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07, 0x0f,0x56,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x05,0x8f,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x09,0x7e,0x01,0x56,0xfd,0xa6,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x05,0x8f,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x09,0x7e,0x01,0x56,0xfd,0xa6,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x7c,0x05,0x16, 0x02,0x26,0x08,0xd0,0x00,0x00,0x01,0x07,0x09,0x7e,0x01,0x56,0xfd,0x2d,0x00,0x0a,0xb4,0x01,0x2f,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x05,0xf2,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x04,0x2a,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x05,0xf2,0x02,0x26,0x08,0xd1, 0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x04,0x2a,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x7c,0x05,0x79,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x03,0xb1,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0xc8,0xff,0xb1,0xff,0xff,0x00,0x7e,0xfd,0xff, 0x04,0xad,0x03,0x54,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x96,0xff,0x75,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0xfe,0xab,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x02,0x26,0x09,0x13,0x00,0x00,0x01,0x07,0x0f,0x52,0x01,0xc8, 0xff,0x26,0x00,0x0c,0xb5,0x02,0x01,0x20,0x34,0x01,0x34,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x03,0x54,0x02,0x26,0x08,0xd1,0x00,0x00,0x01,0x07,0x0f,0x52,0x01,0x91,0xff,0x14,0x00,0x0c,0xb5,0x02,0x01,0x20,0x43,0x01,0x43,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x7c,0x03,0x0f, 0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x05,0xf2,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x04,0x2a,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x05,0xf2,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x04,0x2a,0xff,0xff, 0xff,0xba,0xff,0xf2,0x04,0x7c,0x05,0x79,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x03,0xb1,0x00,0x05,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x00,0x31,0x00,0x35,0x00,0x39,0x00,0x3d,0x00,0x41,0x00,0x84,0xb1,0x3e,0x36,0xb8,0x05,0x0a,0xb4,0x37,0x3f,0x37,0x3a,0x32,0xb8,0x05,0x0a,0x40,0x0e,0x33,0x3b,0x33, 0x1d,0x00,0x0d,0x03,0x37,0x33,0x37,0x33,0x43,0x26,0x05,0xb8,0x05,0x0a,0xb2,0x16,0x3e,0x3a,0xb8,0x04,0xfb,0x40,0x09,0x40,0x0f,0x3d,0x1f,0x3d,0x02,0x3d,0x36,0x32,0xb8,0x04,0xfb,0x40,0x0d,0x38,0x2f,0x35,0x3f,0x35,0x02,0x35,0x31,0x1d,0x00,0x03,0x11,0x23,0xb8,0x04,0xff,0xb2,0x2a,0x0d,0x0a,0xb8,0x04,0xfc,0xb6,0x0e,0x1f,0x11, 0x2f,0x11,0x02,0x11,0x00,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x2f,0x5d,0x33,0xfd,0x32,0xde,0x5d,0x32,0xed,0x32,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x17,0x39,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x01,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06, 0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x0c,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64, 0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe,0x7e,0xb5,0xb5,0x01,0x1a,0xb5,0xb5,0xfe,0xe6,0xb5,0xb5,0x01,0x1a,0xb5,0xb5,0x02,0x01,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a, 0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfd,0x78,0xb3,0xb3,0xb3,0xfe,0x35,0xb3,0xb3,0xb3,0x00,0x04,0x00,0x7e,0xfd,0xff,0x05,0x58,0x03,0x54,0x00,0x42,0x00,0x46,0x00,0x4a,0x00,0x4e,0x00,0x90,0xb2,0x03,0x43,0x00,0xb8,0x05,0x0a,0xb4,0x01,0x44,0x01,0x4b,0x47,0xb8,0x05,0x0a,0x40,0x0e, 0x48,0x4c,0x48,0x23,0x38,0x13,0x03,0x01,0x48,0x01,0x48,0x50,0x2c,0x0b,0xbd,0x05,0x0a,0x00,0x1c,0x00,0x3c,0x04,0xfb,0x00,0x3e,0x05,0x03,0xb6,0x06,0x38,0x23,0x37,0x04,0x17,0x29,0xb8,0x04,0xff,0xb2,0x30,0x13,0x10,0xb8,0x04,0xfc,0x40,0x09,0x14,0x1f,0x17,0x2f,0x17,0x02,0x17,0x47,0x43,0xb8,0x04,0xfb,0x40,0x09,0x49,0x0f,0x46, 0x1f,0x46,0x02,0x46,0x4b,0x00,0xb8,0x04,0xfb,0xb4,0x4d,0x2f,0x03,0x01,0x03,0x00,0x2f,0x5d,0x33,0xfd,0x32,0xde,0x5d,0x32,0xed,0x32,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x3f,0xed,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x17,0x39,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x39,0x31,0x30,0x25,0x23, 0x35,0x33,0x26,0x26,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x07,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x27,0x11,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x35,0x23,0x35, 0x33,0x03,0xa6,0xb5,0xa9,0x1d,0x2a,0x0f,0x9d,0xd5,0x81,0x37,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0x20,0x4b,0x24,0xc1,0x99,0x19,0x2f,0x84,0xc0,0x3f,0xb5,0xb5,0xfe,0xf0, 0xb5,0xb5,0xb5,0xb5,0x34,0xb3,0x31,0x70,0x3e,0x35,0x72,0x7b,0x86,0x48,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x15,0x9f,0xb4,0xa7,0x7a,0x66,0xfe,0x4a,0xb3,0xb3,0xb3,0x65,0xb3, 0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x52,0xfe,0xf4,0x03,0x4a,0x03,0xba,0x02,0x26,0x09,0x15,0x00,0x00,0x01,0x07,0x0f,0x5b,0x00,0xab,0x00,0xf5,0x00,0x0c,0xb5,0x02,0x01,0x20,0x20,0x01,0x20,0x00,0x11,0x5d,0x35,0x35,0xff,0xff, 0x00,0x52,0xfe,0xa6,0x03,0x4a,0x03,0xba,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0x52,0xfe,0xa6,0x03,0x4a,0x07,0x0f,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0xab,0xfe,0xab,0x00,0x07,0x0f,0x57,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x05,0x5d, 0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x52,0xfe,0xa6,0x03,0x4a,0x03,0xba,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x06,0x75,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xab,0x04,0xad,0xff,0xff, 0x00,0x52,0xff,0xea,0x03,0x4a,0x06,0x75,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x06,0x75,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0xc2,0x04,0xaf,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07, 0x0a,0x6d,0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x31,0x02,0x5e,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x5b,0x01,0x90,0x00,0x00,0xff,0xff,0x00,0x00,0xfd,0xfb,0x03,0x4f,0x02,0x5e,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0xf2,0xfe,0x00,0xff,0xff,0x00,0x00,0xfd,0xe1,0x04,0x31,0x02,0x5e, 0x00,0x26,0x09,0x17,0x00,0x00,0x01,0x07,0x0a,0x6d,0x02,0x09,0xf7,0x65,0x00,0x0a,0xb4,0x01,0x2f,0x1d,0x01,0x1d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xfb,0x03,0x4f,0x02,0x5e,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0xf2,0xfe,0x00,0x00,0x06,0x0f,0x50,0xce,0x05,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0x9e, 0x04,0x07,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0x9e,0x05,0x1f,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x04,0x07,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x27,0x0f,0x50,0x05,0x50,0x03,0x57, 0x00,0x07,0x0f,0x50,0x05,0x50,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x05,0xf4,0x04,0x07,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0xa4,0x03,0x57,0x00,0x07,0x0f,0x50,0x02,0xa4,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x08,0xa0,0x03,0x0f,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x07,0x0f,0x54,0x05,0x50,0xfd,0xce, 0xff,0xff,0xff,0xba,0xfd,0xc9,0x05,0xf4,0x03,0x0f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xa4,0xfd,0xce,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x08,0xa0,0x05,0x1f,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x27,0x0f,0x54,0x05,0x50,0xfd,0xce,0x00,0x07,0x0f,0x53,0x05,0x46,0x03,0x57,0xff,0xff,0xff,0xba,0xfd,0xc9,0x05,0xf4, 0x05,0x1f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x27,0x0f,0x54,0x02,0xa4,0xfd,0xce,0x00,0x07,0x0f,0x53,0x02,0xa4,0x03,0x57,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0xf7,0x03,0x3c,0x02,0x26,0x09,0x1b,0x00,0x00,0x00,0x07,0x0f,0x51,0x06,0x3c,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x07,0x4b,0x03,0x3c,0x02,0x26,0x08,0xd6,0x00,0x00, 0x00,0x07,0x0f,0x51,0x03,0x86,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0xf7,0x05,0xca,0x02,0x26,0x09,0x1b,0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0xca,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xea,0x07,0x4b,0x05,0xca,0x02,0x26,0x08,0xd6,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x1e,0x04,0x02,0xff,0xff,0x00,0x19,0xff,0xea,0x05,0xf5, 0x05,0xec,0x02,0x26,0x09,0x1d,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xe5,0x04,0x02,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x06,0xa7,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xe4,0x04,0xdf,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad,0x06,0x42,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x04,0x7a, 0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x3c,0x05,0xfc,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x1d,0x04,0x34,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0xca,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x04,0x02,0x00,0x02,0x00,0xab,0xff,0xea,0x07,0x4b,0x03,0x62,0x00,0x36,0x00,0x4a,0x00,0x4c, 0xbc,0x00,0x23,0x05,0x0a,0x00,0x37,0x00,0x43,0x05,0x0a,0xb6,0x16,0x37,0x16,0x37,0x16,0x4c,0x03,0xb8,0x05,0x0a,0xb4,0x33,0x48,0x10,0x10,0x0d,0xb8,0x04,0xfb,0xb4,0x2a,0x00,0x00,0x1b,0x2a,0xba,0x05,0x03,0x00,0x3e,0x04,0xfb,0xb3,0x2f,0x1b,0x01,0x1b,0x00,0x2f,0x5d,0xed,0x3f,0x12,0x39,0x2f,0x10,0xed,0x32,0x2f,0x32,0x01,0x2f, 0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x05,0x33,0x32,0x36,0x37,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x05,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14, 0x1e,0x02,0x17,0x36,0x36,0x01,0x62,0x09,0x11,0x20,0x2e,0x17,0x39,0x4f,0x6d,0x96,0xc7,0x82,0x5b,0x8e,0x3b,0x02,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x3a,0x64,0x89,0x9d,0xac,0x55,0xb9,0x86,0xd6,0xaa,0x7f,0x2e,0x3f,0x30,0x12,0x0b,0x05,0xe6,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2c, 0x1a,0x18,0x42,0x73,0x5a,0x21,0x1d,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x66,0x20,0x10,0x17,0x0f,0x08,0x05,0x01,0x02,0x03,0x06,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x57,0x21,0x4a,0x53,0x5a,0x30,0x60,0x84,0x57,0x30,0x17,0x05,0x05,0x15,0x2d,0x27,0x36,0x99,0x58,0x3d,0x70,0x33,0xf2,0x1d,0x47,0x49,0x45,0x36,0x20,0x26, 0x3c,0x4c,0x26,0x20,0x3e,0x44,0x49,0x2a,0x18,0x4d,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x4b,0x03,0x62,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x50,0x05,0x10,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x49,0x03,0x62,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x0e,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6, 0x04,0x02,0x03,0x62,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x0e,0xfe,0xab,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x4b,0x05,0x24,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x27,0x0f,0x50,0x04,0xd7,0x04,0x74,0x00,0x07,0x0f,0x50,0x05,0x10,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x49,0x05,0x24,0x02,0x26,0x09,0x3c, 0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x0e,0xfe,0xab,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x05,0x24,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x0e,0xfe,0xab,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x4b,0x03,0x62,0x02,0x26,0x09,0xc8, 0x00,0x00,0x00,0x07,0x0f,0x54,0x05,0x10,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x49,0x03,0x62,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x0e,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02,0x03,0x62,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x0e,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea, 0x07,0x4b,0x06,0x3c,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x56,0x04,0xd7,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x06,0x3c,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x3c,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0xd5, 0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x4b,0x04,0x79,0x02,0x26,0x09,0x7c,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xd4,0x03,0xc9,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x4b,0x05,0x91,0x02,0x26,0x09,0x7c,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xd4,0x03,0xc9,0x00,0x01,0x00,0x19,0xff,0xea,0x08,0x3d,0x04,0x19,0x00,0x3f,0x00,0x41, 0xb9,0x00,0x2e,0x05,0x0a,0xb6,0x0f,0x0c,0x0c,0x0f,0x0f,0x41,0x23,0xbf,0x05,0x0a,0x00,0x18,0x00,0x07,0x04,0xfb,0x00,0x38,0x05,0x03,0x00,0x12,0x04,0xfb,0xb4,0x2f,0x29,0x01,0x29,0x1e,0xb8,0x04,0xfb,0xb3,0x2f,0x1d,0x01,0x1d,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0x2f,0x10,0xed,0x31, 0x30,0x37,0x1e,0x05,0x33,0x32,0x3e,0x02,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x22,0x2e,0x02,0x35,0x34,0x36,0x36,0x24,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x02,0x04,0x23,0x22,0x2e,0x04,0x27,0x19,0x25,0x83,0xaa,0xc8,0xd8,0xdd,0x69,0xa5,0xf9,0xc5,0x9e,0x4b,0x03, 0x03,0x5d,0x55,0xfb,0xd3,0x56,0x88,0x5e,0x32,0x6b,0xc7,0x01,0x1f,0xb4,0x7f,0xe3,0xac,0x65,0x18,0x4a,0x89,0x71,0x03,0xba,0x46,0x76,0x54,0x2f,0x0d,0x1d,0x2e,0x20,0x3a,0xb4,0xed,0xfe,0xdc,0xaa,0x46,0xb1,0xc0,0xc2,0xae,0x8f,0x2d,0xa9,0x05,0x07,0x06,0x03,0x02,0x01,0x02,0x04,0x08,0x06,0x0b,0x12,0x0b,0x43,0x55,0x07,0x1f,0x40, 0x39,0x52,0xa9,0x92,0x6f,0x19,0xa6,0x10,0x43,0x56,0x61,0x2d,0x12,0x15,0x0a,0x02,0x2e,0x4d,0x66,0x38,0x1c,0x41,0x40,0x3b,0x16,0x05,0x09,0x06,0x04,0x01,0x02,0x03,0x06,0x07,0x05,0x00,0x00,0x01,0xff,0xba,0xff,0xea,0x07,0x92,0x04,0x19,0x00,0x44,0x00,0x48,0xb9,0x00,0x29,0x05,0x0a,0xb3,0x1e,0x1e,0x45,0x34,0xb8,0x05,0x0a,0xb4, 0x15,0x12,0x12,0x15,0x3e,0xba,0x05,0x03,0x00,0x18,0x04,0xfb,0xb4,0x2f,0x2f,0x01,0x2f,0x24,0xb8,0x04,0xfb,0xb5,0x2f,0x23,0x01,0x23,0x0d,0x07,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x3f,0x01,0x2f,0x33,0x2f,0x10,0xed,0x11,0x33,0x2f,0xed,0x31,0x30,0x17,0x23,0x22,0x26,0x35,0x34, 0x36,0x33,0x33,0x32,0x16,0x16,0x04,0x33,0x32,0x3e,0x02,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x22,0x2e,0x02,0x35,0x34,0x36,0x36,0x24,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x02,0x04,0x23,0x22,0x2e,0x04,0x32,0x32,0x23,0x23,0x23,0x23,0x3b,0x1e,0xa2,0xef,0x01,0x2e, 0xab,0x9d,0xf6,0xc3,0x99,0x40,0x03,0x03,0x5d,0x55,0xfb,0xd3,0x56,0x88,0x5e,0x32,0x6b,0xc7,0x01,0x1f,0xb4,0x7f,0xe3,0xac,0x65,0x19,0x4b,0x88,0x70,0x03,0xba,0x46,0x76,0x54,0x2f,0x0d,0x1d,0x2e,0x20,0x34,0xb6,0xec,0xfe,0xe9,0x96,0x50,0xb3,0xb2,0xa8,0x8b,0x66,0x0e,0x34,0x20,0x20,0x33,0x03,0x03,0x02,0x03,0x05,0x07,0x05,0x0b, 0x12,0x0b,0x43,0x55,0x07,0x1f,0x40,0x39,0x52,0xa9,0x92,0x6f,0x19,0xa6,0x10,0x43,0x56,0x61,0x2e,0x12,0x14,0x0a,0x02,0x2e,0x4d,0x66,0x38,0x1c,0x41,0x40,0x3b,0x16,0x05,0x08,0x07,0x04,0x01,0x02,0x02,0x02,0x01,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x06,0x02,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x5b,0x04,0xa6, 0x05,0xb0,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0x02,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x5b,0x01,0x4f,0x05,0xb0,0xff,0xff,0x00,0xab,0xff,0xea,0x05,0xf4,0x06,0xb3,0x02,0x26,0x09,0x24,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x73,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0xb3,0x02,0x26,0x08,0xed, 0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x05,0xf4,0x07,0xcb,0x02,0x26,0x09,0x24,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0x73,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x07,0xcb,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xfd,0xc9, 0x05,0xf4,0x05,0xec,0x02,0x26,0x09,0x24,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0x74,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x4b,0x06,0x02,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xab,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x07,0x38,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x27,0x0f,0x5b,0x04,0xa6, 0x05,0xb0,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x07,0x38,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x27,0x0f,0x5b,0x01,0x4f,0x05,0xb0,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x07,0xc3,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00, 0x01,0x07,0x0f,0x51,0x03,0x90,0x07,0x13,0x00,0x0c,0xb5,0x02,0x03,0x20,0x3e,0x01,0x3e,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x07,0xc3,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x26,0x0f,0x59,0x00,0x00,0x01,0x07,0x0f,0x51,0x00,0x39,0x07,0x13,0x00,0x0c,0xb5,0x02,0x03,0x20,0x28,0x01,0x28,0x00,0x11,0x5d, 0x35,0x35,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0xa2,0x07,0x38,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x4b,0x07,0x38,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x26,0x0f,0x59,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0xfe,0xab, 0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0xa2,0x07,0x38,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x27,0x0f,0x52,0x02,0xad,0xfd,0xce,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x4b,0x07,0x38,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x27,0x0f,0x52,0x00,0xab,0xfd,0xce,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff, 0x00,0xab,0xff,0xea,0x06,0xa2,0x08,0xbd,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00,0x01,0x07,0x0f,0x53,0x03,0x57,0x06,0xf5,0x00,0x13,0x40,0x0a,0x04,0x03,0x02,0x20,0x45,0x01,0x20,0x45,0x01,0x45,0x00,0x11,0x5d,0x5d,0x35,0x35,0x35,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x08,0xbd,0x02,0x26, 0x08,0xed,0x00,0x00,0x00,0x26,0x0f,0x59,0x00,0x00,0x01,0x07,0x0f,0x53,0x00,0x00,0x06,0xf5,0x00,0x13,0x40,0x0a,0x04,0x03,0x02,0x20,0x30,0x01,0x20,0x30,0x01,0x30,0x00,0x11,0x5d,0x5d,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x70,0x08,0x0e,0x02,0x26,0x09,0x25,0x00,0x00,0x00,0x07,0x0a,0x6d,0x03,0x48,0x00,0x32, 0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x08,0x0e,0x02,0x26,0x08,0xee,0x00,0x00,0x00,0x07,0x0a,0x6d,0x00,0x9c,0x00,0x32,0xff,0xff,0x00,0x9b,0xfe,0xac,0x04,0xa5,0x07,0x67,0x02,0x26,0x09,0x25,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x48,0x06,0xb7,0xff,0xff,0xff,0xba,0xff,0xf2,0x01,0xf9,0x07,0x67,0x02,0x26,0x08,0xee,0x00,0x00, 0x00,0x07,0x0f,0x50,0x00,0x9c,0x06,0xb7,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x46,0x08,0x7f,0x02,0x26,0x09,0x25,0x00,0x00,0x01,0x07,0x0f,0x53,0x03,0x48,0x06,0xb7,0x00,0x0e,0xb6,0x03,0x02,0x01,0x20,0x28,0x01,0x28,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9a,0x08,0x7f,0x02,0x26,0x08,0xee,0x00,0x00, 0x01,0x07,0x0f,0x53,0x00,0x9c,0x06,0xb7,0x00,0x0e,0xb6,0x03,0x02,0x01,0x20,0x21,0x01,0x21,0x00,0x11,0x5d,0x35,0x35,0x35,0x00,0x04,0x00,0x9b,0xfd,0xc4,0x04,0x9e,0x05,0xec,0x00,0x1d,0x00,0x21,0x00,0x25,0x00,0x29,0x00,0x65,0xbc,0x00,0x10,0x05,0x0a,0x00,0x0d,0x00,0x27,0x05,0x0c,0xb2,0x26,0x26,0x22,0xbb,0x05,0x0c,0x00,0x23, 0x00,0x1e,0x05,0x0c,0x40,0x0a,0x1f,0x0d,0x23,0x1f,0x1f,0x23,0x0d,0x03,0x2b,0x03,0xbb,0x05,0x0a,0x00,0x1a,0x00,0x26,0x04,0xfb,0xb2,0x29,0x22,0x1e,0xb8,0x04,0xfb,0xb5,0x24,0x20,0x21,0x01,0x21,0x08,0xba,0x04,0xfb,0x00,0x15,0x05,0x03,0xb1,0x0e,0x00,0x00,0x2f,0x2f,0x3f,0xed,0xd6,0x5d,0x32,0xfd,0x32,0xd6,0xed,0x01,0x2f,0xed, 0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x01,0x4e,0x0b,0x0b,0x23,0x4f,0x7d,0x59,0x67, 0x93,0x5d,0x2b,0x9c,0x38,0x81,0xd4,0x9d,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x01,0x9d,0xc9,0xc9,0x01,0x56,0xc9,0xc9,0xab,0xc9,0xc9,0x02,0xec,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x03,0x7e,0xfc,0x6e,0x8f,0xe4,0x9f,0x56,0x45,0x7f,0xb7,0x72,0x3f,0x83,0x4b,0xfb,0xf0,0xbd,0xbd,0xbd,0xfe,0x2b,0xbd,0x00,0xff,0xff, 0xff,0xba,0xfd,0xc9,0x02,0x48,0x05,0xec,0x02,0x26,0x08,0xee,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x4a,0xfd,0xce,0xff,0xff,0x00,0x9b,0xfd,0xfb,0x04,0xa6,0x04,0xb2,0x02,0x27,0x09,0x5f,0x00,0x00,0x01,0x56,0x00,0x27,0x0f,0x50,0x01,0x9f,0x04,0x02,0x00,0x07,0x0f,0x50,0x01,0x9f,0xfe,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x01,0xf9, 0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c,0x04,0x02,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x05,0x0e,0x02,0x26,0x09,0x5f,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x9f,0x02,0xac,0xff,0xff,0x00,0x9b,0xfe,0x55,0x04,0xa6,0x04,0xb2,0x02,0x27,0x09,0x5f,0x00,0x00, 0x01,0x56,0x00,0x27,0x0f,0x5b,0x01,0x9f,0x00,0x56,0x00,0x07,0x0f,0x50,0x01,0x9f,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0x05,0x01,0xf9,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x5b,0x00,0x1a,0x01,0x06,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x04,0x74,0x02,0x26,0x09,0x5f, 0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x9f,0x02,0xac,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x81,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x04,0xda,0x00,0x26,0x09,0x42,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x2a,0xff,0xff,0x00,0x7e,0xfd,0xff, 0x05,0x58,0x04,0xda,0x02,0x26,0x09,0x43,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x04,0x2a,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x7c,0x04,0x61,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x27,0x0f,0x54,0x01,0x56,0xfd,0xce,0x00,0x07,0x0f,0x50,0x01,0x56,0x03,0xb1,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x02,0xb7,0x02,0x26,0x09,0x29, 0x00,0x00,0x00,0x06,0x0f,0x5b,0x66,0x60,0x00,0x02,0x00,0x00,0xfd,0xfe,0x03,0x4b,0x03,0x1c,0x00,0x2a,0x00,0x3f,0x00,0x62,0xb2,0x08,0x20,0x35,0xb8,0x05,0x0a,0xb2,0x09,0x16,0x20,0xb8,0x05,0x0a,0xb7,0x0e,0x3d,0x3d,0x0e,0x0e,0x3a,0x11,0x08,0xb8,0x04,0xfd,0xb3,0x0b,0x0b,0x03,0x11,0xb8,0x04,0xfb,0x40,0x09,0x3d,0x2f,0x3a,0x3f, 0x3a,0x02,0x3a,0x00,0x03,0xb8,0x04,0xfb,0xb7,0x2a,0x1f,0x27,0x2f,0x27,0x02,0x27,0x30,0xb8,0x04,0xfb,0xb3,0x2f,0x1b,0x01,0x1b,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0x33,0xed,0x32,0x2f,0x5d,0x33,0xed,0x11,0x39,0x2f,0xed,0x11,0x12,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x2f,0x33,0xed,0x12,0x39,0x31,0x30,0x11,0x16,0x16,0x33,0x32,0x3e, 0x02,0x37,0x21,0x35,0x21,0x36,0x36,0x37,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x26,0x27,0x01,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x26,0x26,0x67,0xab,0x45,0x3e,0x60,0x48,0x33,0x11,0xfe,0x2a,0x01,0xf4,0x08,0x07,0x01,0x2f,0x58, 0x29,0x42,0x7b,0x5e,0x39,0x30,0x55,0x75,0x45,0x42,0x7f,0x63,0x3d,0x13,0x2c,0x49,0x6e,0x96,0x62,0x58,0xad,0x58,0x02,0x98,0x0f,0x2a,0x32,0x35,0x1a,0x1c,0x37,0x2c,0x1b,0x20,0x3a,0x4e,0x2f,0x1b,0x4b,0x2a,0x02,0x09,0xfe,0xfa,0x2b,0x25,0x1b,0x31,0x43,0x28,0x6d,0x2b,0x58,0x2d,0x16,0x11,0x29,0x4f,0x72,0x48,0x41,0x8e,0x77,0x4d, 0x4f,0x9e,0xee,0x9f,0x51,0xa2,0x96,0x83,0x61,0x37,0x2c,0x2a,0x03,0x34,0x33,0x55,0x3d,0x22,0x26,0x3d,0x4a,0x24,0x26,0x3c,0x29,0x16,0x0c,0x14,0x1d,0x33,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x05,0x31,0x02,0x26,0x09,0x29,0x00,0x00,0x01,0x07,0x0a,0x6d,0x00,0xe5,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x38,0x01,0x38,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x05,0x63,0x02,0x26,0x09,0x29,0x00,0x00,0x01,0x07,0x09,0x30,0x00,0xe4,0xfd,0x55,0x00,0x0c,0xb5,0x03,0x02,0x2f,0x38,0x01,0x38,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x05,0x59,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x07,0x09,0x73,0x00,0xe5,0xfd,0x55, 0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x05,0x31,0x02,0x26,0x09,0x29,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0xe5,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x38,0x01,0x38,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x04,0x79,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xd5,0x03,0xc9,0xff,0xff,0x00,0x00, 0xfd,0xff,0x03,0x49,0x05,0x91,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x03,0xc9,0x00,0x01,0x00,0x32,0xff,0x55,0x06,0x3d,0x04,0x15,0x00,0x37,0x00,0x3a,0xb2,0x0b,0x05,0x31,0xbb,0x05,0x0a,0x00,0x18,0x00,0x2a,0x05,0x0a,0x40,0x09,0x1f,0x25,0x18,0x1f,0x18,0x1f,0x39,0x08,0x0e,0xbd,0x05,0x0a,0x00,0x05,0x00, 0x00,0x04,0xfb,0x00,0x13,0x04,0xe6,0x00,0x3f,0xed,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x39,0x10,0xed,0x10,0xed,0x11,0x39,0x31,0x30,0x05,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05,0x35,0x25,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e, 0x04,0x15,0x14,0x0e,0x04,0x03,0x48,0x91,0xc4,0x78,0x34,0x0e,0x0e,0xfe,0xcf,0x01,0xeb,0x17,0x23,0x21,0x52,0x8e,0x6d,0x6d,0xbd,0x8d,0x51,0x33,0x4b,0x59,0x4b,0x33,0x54,0x96,0xd1,0x7e,0x64,0x9c,0x6c,0x38,0x33,0x4d,0x5a,0x4d,0x33,0x27,0x4e,0x73,0x98,0xbc,0xab,0x4c,0x81,0xad,0x60,0x38,0x72,0x39,0x39,0x72,0x61,0x58,0xaf,0x55, 0x47,0x7b,0x5c,0x34,0x2e,0x4b,0x5e,0x30,0x26,0x33,0x2c,0x2e,0x40,0x5c,0x45,0x55,0x7f,0x5b,0x3b,0x12,0xa2,0x0d,0x23,0x31,0x41,0x2a,0x29,0x39,0x2f,0x2c,0x3a,0x4f,0x3a,0x31,0x6a,0x68,0x5e,0x47,0x2a,0x00,0x00,0x01,0x00,0x1e,0xff,0x02,0x07,0x58,0x02,0x13,0x00,0x44,0x00,0x5a,0xb3,0x26,0x14,0x20,0x38,0xb8,0x05,0x0a,0xb2,0x0f, 0x0f,0x14,0xb8,0x05,0x0a,0xb3,0x33,0x33,0x46,0x29,0xb8,0x05,0x0a,0x40,0x09,0x20,0x23,0x23,0x20,0x26,0x3d,0x23,0x23,0x0c,0xb8,0x04,0xff,0xb4,0x2f,0x3d,0x01,0x3d,0x1b,0xb8,0x04,0xfb,0xb4,0x2f,0x2e,0x01,0x2e,0x00,0xba,0x04,0xfb,0x00,0x01,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x32,0x2f,0x11,0x39,0x01,0x2f, 0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x39,0x2f,0xed,0x11,0x12,0x39,0x31,0x30,0x25,0x15,0x23,0x22,0x2e,0x04,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05,0x35,0x25,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x35,0x34,0x3e, 0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x07,0x58,0x16,0x43,0x67,0x4f,0x3b,0x2e,0x25,0x12,0x17,0x29,0x18,0x1d,0x27,0x20,0x26,0x20,0x2d,0x4e,0x68,0x77,0x80,0x3e,0x97,0xcc,0x7d,0x35,0x04,0x04,0xfe,0xd0,0x01,0xe3,0x0e,0x12,0x23,0x5d,0xa0,0x7d,0x54,0x81,0x59,0x2d,0x20,0x26,0x20,0x26,0x41,0x57,0x30,0x31,0x60,0x27,0x19,0x2c,0x40, 0x66,0x99,0xa7,0x21,0x35,0x45,0x47,0x44,0x1b,0x23,0x1c,0x22,0x24,0x21,0x2c,0x2f,0x3e,0x34,0x3a,0x5c,0x47,0x31,0x20,0x0e,0x4b,0x81,0xad,0x63,0x1f,0x49,0x23,0x39,0x72,0x5f,0x49,0x79,0x3f,0x4d,0x7d,0x5a,0x31,0x16,0x27,0x35,0x20,0x1c,0x2b,0x30,0x41,0x32,0x35,0x57,0x3e,0x22,0x2c,0x3a,0x27,0x60,0x54,0x39,0xff,0xff,0x00,0x9a, 0xff,0x55,0x05,0x91,0x05,0xdc,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0x01,0xfe,0x00,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x04,0x2c,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0x01,0xfc,0x50,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xc4,0x05,0x5a,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0a,0x6d, 0x00,0x9c,0xfd,0x7e,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x49,0x04,0x79,0x02,0x26,0x09,0x29,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x03,0xc9,0xff,0xff,0x00,0x9a,0xfd,0xc9,0x05,0x91,0x04,0xaa,0x02,0x27,0x09,0x2a,0x00,0x00,0x00,0x95,0x00,0x07,0x0f,0x52,0x02,0x01,0xfd,0xce,0xff,0xff, 0x00,0x9a,0xfd,0xc4,0x06,0xae,0x02,0xbd,0x02,0x26,0x0f,0x61,0x00,0x00,0x01,0x07,0x0f,0x52,0x01,0xc8,0xfd,0xc9,0x00,0x08,0xb3,0x02,0x4a,0x14,0x26,0x00,0x2b,0x35,0xff,0xff,0x00,0x9a,0xfd,0xc9,0x05,0x91,0x04,0xaa,0x02,0x27,0x09,0x2a,0x00,0x00,0x00,0x95,0x00,0x07,0x0f,0x54,0x02,0x01,0xfd,0xce,0xff,0xff,0x00,0x9a,0xfd,0xc4, 0x06,0xae,0x02,0xbd,0x02,0x26,0x0f,0x61,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0xc8,0xfd,0xc9,0x00,0x04,0xff,0xa8,0x06,0x1d,0x02,0x5f,0x08,0xde,0x00,0x46,0x00,0x56,0x00,0x5a,0x00,0x5e,0x00,0x7a,0xb9,0x00,0x5c,0x05,0x0d,0xb2,0x5b,0x5b,0x0e,0xb8,0x05,0x0d,0xb5,0x47,0x29,0x29,0x47,0x18,0x3f,0xbe,0x05,0x0d,0x00,0x3c,0x00,0x23, 0x05,0x0d,0x00,0x32,0x00,0x57,0x05,0x0d,0xb2,0x58,0x58,0x51,0xb8,0x05,0x0d,0xb6,0x03,0x5d,0x5a,0x5b,0x57,0x3e,0x08,0xb8,0x05,0x01,0x40,0x0a,0x4c,0x43,0x18,0x13,0x54,0x46,0x46,0x37,0x37,0x43,0xb8,0x05,0x01,0xb4,0x13,0x1b,0x1b,0x13,0x26,0xb9,0x05,0x01,0x00,0x2d,0x00,0x2f,0xfd,0xce,0x32,0x2f,0x10,0xed,0x32,0x2f,0x32,0x2f, 0x32,0x11,0x39,0x10,0xd4,0xfd,0xcc,0xde,0x32,0xcd,0x32,0x01,0x2f,0xed,0x39,0x2f,0xed,0x2f,0xed,0x2f,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x22,0x06,0x22,0x23,0x22, 0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x37,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x32,0x32,0x17,0x37,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x03,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x01,0x98,0x32,0x23,0x14,0x25,0x32, 0x1e,0x1e,0x2f,0x19,0x11,0x1c,0x38,0x55,0x65,0x2e,0x17,0x27,0x30,0x0b,0x01,0x11,0x2c,0x16,0x03,0x0e,0x0f,0x0e,0x04,0x18,0x26,0x60,0x69,0x63,0x9b,0x40,0x52,0xab,0x43,0x46,0x6c,0x49,0x26,0x25,0x35,0x3b,0x16,0x1d,0x10,0x0e,0x0c,0x58,0x10,0x1a,0x1a,0x21,0x2d,0x14,0x6e,0x0a,0x11,0x16,0x0c,0x09,0x11,0x0d,0x09,0x25,0x36,0x09, 0x09,0x58,0x57,0x57,0x8f,0x57,0x57,0x07,0x2f,0x15,0x3a,0x1f,0x1b,0x36,0x2b,0x1c,0x1f,0x25,0x1a,0x46,0x2a,0x3b,0x3f,0x1e,0x05,0x17,0x15,0x19,0x12,0x01,0x0f,0x12,0x19,0x10,0x09,0x06,0x61,0x08,0x09,0x0c,0x1e,0x33,0x28,0x29,0x35,0x1f,0x0d,0x08,0x08,0x17,0x15,0x01,0x76,0xfe,0xa0,0x2f,0x22,0x01,0x40,0x10,0x24,0x1f,0x15,0x0c, 0x12,0x17,0x0c,0x14,0x29,0x18,0x06,0x1b,0x01,0x06,0x56,0x56,0x56,0x00,0x00,0x02,0xff,0xb7,0x06,0x71,0x02,0x28,0x08,0x06,0x00,0x1f,0x00,0x2f,0x00,0x35,0xb9,0x00,0x12,0x05,0x0d,0xb6,0x26,0x1a,0x20,0x08,0x03,0x17,0x0d,0xb8,0x05,0x01,0xb2,0x2b,0x13,0x23,0xbb,0x05,0x01,0x00,0x17,0x00,0x03,0x05,0x01,0xb3,0x1f,0x1f,0x1d,0x17, 0x00,0x2f,0x33,0x33,0x2f,0xed,0x10,0xfd,0x32,0xd6,0xed,0x11,0x17,0x39,0x01,0x2f,0xed,0x31,0x30,0x03,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x49,0x0e,0x1c,0x0b, 0x26,0x30,0x21,0x16,0x0d,0x0a,0x1f,0x30,0x45,0x32,0x37,0x50,0x33,0x18,0x19,0x32,0x4a,0x31,0x3f,0x67,0x24,0x20,0x57,0x31,0x16,0x16,0xfa,0x18,0x53,0x31,0x36,0x3e,0x0f,0x1f,0x2f,0x20,0x1d,0x2e,0x24,0x1a,0x06,0xdc,0x02,0x02,0x11,0x21,0x30,0x1e,0x19,0x3d,0x35,0x23,0x2c,0x43,0x4e,0x21,0x23,0x41,0x34,0x1f,0x32,0x23,0x30,0x25, 0x03,0x9e,0x1d,0x1e,0x26,0x26,0x12,0x2c,0x26,0x19,0x16,0x26,0x34,0x00,0x00,0x02,0x00,0x37,0x06,0x1e,0x01,0x9b,0x08,0x4e,0x00,0x2b,0x00,0x2f,0x00,0x39,0xb1,0x19,0x2c,0xb8,0x05,0x0d,0xb2,0x2d,0x20,0x05,0xb8,0x05,0x0e,0xb4,0x13,0x2b,0x18,0x0e,0x24,0xb8,0x04,0xfd,0xb2,0x1e,0x00,0x2f,0xbc,0x04,0xfd,0x00,0x2c,0x00,0x08,0x05, 0x01,0x00,0x0e,0x00,0x2f,0xfd,0xde,0xfd,0xd6,0xd4,0xed,0x11,0x39,0x39,0x01,0x2f,0xed,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x03,0x23,0x35,0x33,0x01,0x86, 0x49,0x62,0x3c,0x19,0x3b,0x46,0x46,0x4e,0x29,0x48,0x23,0x38,0x4f,0x32,0x17,0x14,0x37,0x5f,0x4b,0x12,0x1d,0x1e,0x25,0x1b,0x35,0x23,0x14,0x2d,0x1a,0x1c,0x2b,0x24,0x20,0x24,0x2a,0x1d,0x50,0x57,0x57,0x07,0x93,0x12,0x29,0x2d,0x31,0x1a,0x29,0x38,0x1a,0x61,0x0e,0x0c,0x1e,0x33,0x42,0x23,0x1f,0x42,0x3f,0x39,0x17,0x03,0x06,0x0e, 0x0c,0x08,0x0d,0x5f,0x06,0x07,0x0a,0x0f,0x13,0x10,0x0b,0x01,0xfe,0xc7,0x56,0x00,0x00,0x03,0x00,0x1d,0x06,0x70,0x01,0xec,0x08,0x17,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x2d,0xbf,0x00,0x09,0x05,0x0a,0x00,0x08,0x00,0x00,0x05,0x0a,0x00,0x01,0x00,0x0b,0x04,0xff,0xb5,0x20,0x08,0x01,0x08,0x06,0x03,0xb8,0x04,0xff,0xb1,0x04,0x00, 0x00,0x2f,0x32,0xfd,0x32,0xde,0x5d,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0xbf,0xa2,0xa2,0x01,0x2d,0xa1,0xa1,0x96,0xa2,0xa2,0x06,0x70,0x9e,0x9e,0x9e,0x6b,0x9e,0x00,0x01,0xff,0x2b,0x06,0x1f,0x02,0xae,0x08,0x2f,0x00,0x43,0x00,0x60,0xb4,0x28,0x28,0x00,0x00,0x03, 0xb8,0x05,0x0d,0xb2,0x40,0x21,0x0b,0xb8,0x05,0x0d,0xb6,0x08,0x40,0x08,0x40,0x08,0x18,0x38,0xbb,0x05,0x0d,0x00,0x32,0x00,0x18,0x05,0x0d,0x40,0x0b,0x15,0x21,0x28,0x10,0x1d,0x17,0x0a,0x0a,0x00,0x05,0x10,0xb8,0x05,0x01,0xb3,0x24,0x1d,0x35,0x3b,0xb9,0x04,0xfd,0x00,0x2d,0x00,0x2f,0xfd,0xc6,0xd4,0x32,0xfd,0x32,0xc4,0x32,0x11, 0x33,0x11,0x12,0x39,0x39,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x32,0x2f,0x32,0x2f,0x31,0x30,0x13,0x16,0x16,0x17,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23, 0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0xe0,0x03,0x05,0x02,0x03,0x3f,0x1d,0x26,0x59,0x04,0x0f,0x1c,0x18,0x10,0x1a,0x12,0x0a,0x59,0x1b,0x2b,0x38,0x1d,0x29,0x3e,0x11,0x01,0x14,0x3a,0x1a,0x1a,0x21,0x0a,0x02,0x02,0x19,0x37,0x56,0x3e,0x3f,0x54,0x32, 0x15,0x0d,0x56,0x05,0x05,0x3b,0x44,0x28,0x38,0x23,0x10,0x07,0x07,0x07,0xbc,0x1a,0x2c,0x17,0x34,0x1e,0x2d,0x6d,0x50,0x1b,0x28,0x19,0x0c,0x06,0x11,0x1e,0x17,0xb8,0xd2,0x2d,0x3a,0x21,0x0c,0x17,0x1d,0x1e,0x16,0x0f,0x0e,0x30,0x4a,0x33,0x1a,0x1b,0x32,0x48,0x2d,0x33,0x3b,0x1b,0x29,0x16,0x41,0x35,0x12,0x28,0x41,0x2f,0x21,0x43, 0x2f,0x00,0x00,0x04,0x00,0x2d,0xfe,0xd2,0x08,0xcf,0x06,0x97,0x00,0x20,0x00,0x48,0x00,0x5c,0x00,0x70,0x00,0x31,0x40,0x16,0x18,0x6c,0x6c,0x15,0x3d,0x62,0x62,0x38,0x42,0x1b,0x15,0x08,0x4e,0x4e,0x0d,0x29,0x58,0x58,0x2e,0x24,0x03,0x0d,0x00,0x2f,0x33,0xcd,0x32,0x32,0x2f,0xcd,0x11,0x33,0x2f,0xcd,0x2f,0x33,0xcd,0x32,0x32,0x2f, 0xcd,0x11,0x33,0x2f,0xcd,0x30,0x31,0x25,0x06,0x04,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x24,0x27,0x24,0x11,0x10,0x25,0x36,0x25,0x36,0x36,0x33,0x32,0x16,0x17,0x04,0x17,0x04,0x11,0x10,0x05,0x16,0x04,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x36,0x24,0x37,0x36,0x12,0x35,0x10,0x25,0x26,0x25,0x0e,0x03,0x23,0x22,0x2e,0x02, 0x27,0x06,0x04,0x07,0x04,0x11,0x10,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0xa1,0x7c,0xfe,0xcc,0xbe,0x08,0x22,0x2f,0x3a,0x20,0x20,0x3a,0x2f,0x22,0x08,0xfe,0x82,0xf7,0xfe,0xd5,0x01,0x2e,0xf1,0x01, 0x83,0x12,0x60,0x3f,0x3e,0x5f,0x13,0x01,0x7a,0xf9,0x01,0x2c,0xf8,0xe8,0x6d,0x01,0x09,0xa1,0x09,0x22,0x2e,0x39,0x20,0x1f,0x3a,0x2e,0x22,0x09,0xa4,0x01,0x0a,0x6a,0x86,0x81,0xfe,0xfd,0xce,0xfe,0xb4,0x07,0x21,0x30,0x3b,0x21,0x21,0x3a,0x30,0x22,0x07,0x9f,0xfe,0xf9,0x6a,0xfe,0xef,0x03,0x5b,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21, 0x13,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21,0x13,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21,0x13,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21,0x13,0x41,0x61,0x72,0x13,0x1e,0x32,0x24,0x15,0x15,0x24,0x32,0x1d,0x24,0xc1,0xed,0x01,0x7c,0x01,0x96,0xf1,0xc1,0x27,0x38,0x48,0x47,0x37,0x21,0xc4,0xec,0xfe,0x83,0xfe,0x65,0xa5,0x55,0x63,0x11,0x1c,0x31, 0x23,0x14,0x14,0x23,0x31,0x1c,0x11,0x5e,0x50,0x66,0x01,0x16,0xb7,0x01,0x72,0xc9,0x9f,0x23,0x1f,0x34,0x26,0x15,0x15,0x25,0x33,0x1e,0x11,0x65,0x53,0xd4,0xfe,0xa6,0xfe,0xa6,0xfe,0x2f,0x19,0x2d,0x21,0x13,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21,0x13,0x13,0x21,0x2d,0x06,0x38,0x19,0x2d,0x21,0x13,0x13,0x21,0x2d,0x19,0x19,0x2d,0x21, 0x13,0x13,0x21,0x2d,0x00,0x0a,0x01,0x46,0xfe,0xa4,0x07,0x66,0x06,0xc8,0x00,0x17,0x00,0x2b,0x00,0x34,0x00,0x3d,0x00,0x45,0x00,0x52,0x00,0x5e,0x00,0x66,0x00,0x6e,0x00,0x76,0x00,0x0c,0xb3,0x3d,0x12,0x31,0x06,0x00,0x2f,0x33,0x2f,0x33,0x30,0x31,0x01,0x34,0x3e,0x02,0x37,0x01,0x01,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x01,0x01, 0x2e,0x03,0x25,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x01,0x32,0x16,0x17,0x13,0x27,0x07,0x13,0x36,0x01,0x03,0x06,0x06,0x23,0x22,0x27,0x03,0x17,0x13,0x16,0x16,0x17,0x25,0x26,0x26,0x27,0x01,0x14,0x16,0x17,0x25,0x26,0x26,0x35,0x34,0x37,0x25,0x06,0x06,0x05,0x14,0x06,0x07,0x05,0x36,0x35, 0x34,0x26,0x27,0x05,0x16,0x01,0x26,0x26,0x27,0x05,0x16,0x16,0x17,0x01,0x06,0x06,0x07,0x13,0x36,0x36,0x37,0x01,0x36,0x36,0x37,0x03,0x06,0x06,0x07,0x01,0x46,0x42,0x78,0xa7,0x65,0x01,0x4a,0x01,0x4a,0x65,0xa7,0x78,0x42,0x43,0x78,0xa7,0x64,0xfe,0xb6,0xfe,0xb4,0x64,0xa6,0x78,0x42,0x01,0xf5,0x2c,0x4d,0x67,0x3b,0x3b,0x67,0x4d, 0x2c,0x2c,0x4d,0x67,0x3b,0x3b,0x67,0x4d,0x2c,0x01,0x1b,0x20,0x3e,0x1d,0x72,0xed,0xee,0x73,0x3c,0x01,0x2c,0x73,0x1d,0x3d,0x20,0x41,0x3a,0x72,0xed,0xb3,0x38,0x58,0x1d,0x01,0x06,0x33,0xa7,0x6c,0xfc,0x3a,0x14,0x14,0x01,0x05,0x09,0x0a,0x14,0xfe,0xfa,0x14,0x14,0x04,0x32,0x0b,0x09,0x01,0x05,0x29,0x14,0x14,0xfe,0xfa,0x14,0xfd, 0xc0,0x38,0x58,0x1d,0xfe,0xfb,0x33,0xa7,0x6c,0x02,0x80,0x1d,0x58,0x38,0x6c,0x6c,0xa7,0x33,0xfc,0x3a,0x1d,0x58,0x38,0x6c,0x6b,0xa8,0x33,0x02,0xb6,0x76,0xda,0xb8,0x91,0x2f,0x01,0x4a,0xfe,0xb5,0x2f,0x91,0xb8,0xd9,0x76,0x76,0xd9,0xb8,0x92,0x2e,0xfe,0xb5,0x01,0x4c,0x2e,0x91,0xb8,0xd9,0x76,0x3b,0x67,0x4d,0x2c,0x2c,0x4d,0x67, 0x3b,0x3b,0x67,0x4d,0x2c,0x2c,0x4d,0x67,0x01,0x51,0x0b,0x09,0x01,0x16,0xee,0xee,0xfe,0xea,0x14,0xfb,0xe5,0x01,0x16,0x09,0x0a,0x14,0xfe,0xe9,0xed,0x04,0xdc,0x1d,0x58,0x38,0x6d,0x6c,0xa7,0x33,0xfd,0x9a,0x3d,0x74,0x36,0x6c,0x1d,0x3e,0x20,0x3f,0x3c,0x6c,0x36,0x74,0x3d,0x20,0x3e,0x1d,0x6c,0x6d,0x7a,0x3d,0x74,0x36,0x6d,0x3a, 0xfe,0x5f,0x1d,0x58,0x38,0x6c,0x6c,0xa7,0x33,0x01,0xb2,0x38,0x58,0x1d,0xfe,0xfc,0x33,0xa6,0x6c,0x01,0xd3,0x38,0x58,0x1d,0x01,0x05,0x33,0xa7,0x6b,0x00,0x00,0x02,0x00,0x63,0x06,0x8f,0x01,0xa4,0x07,0xd0,0x00,0x0b,0x00,0x17,0x00,0x26,0x41,0x0c,0x00,0x03,0x05,0x0e,0x00,0x0f,0x00,0x15,0x05,0x0e,0x00,0x09,0x00,0x00,0x05,0x00, 0x00,0x12,0x00,0x0c,0x05,0x00,0x00,0x06,0x00,0x2f,0xfd,0xd6,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x05,0x41,0x5e,0x5e,0x41,0x45,0x5d,0x5d,0x45,0x23,0x31,0x31,0x23,0x25,0x32,0x32,0x07,0xd0,0x5d, 0x45,0x41,0x5e,0x5e,0x41,0x45,0x5d,0xf6,0x31,0x23,0x25,0x32,0x32,0x25,0x23,0x31,0x00,0x02,0x00,0x63,0x06,0x7b,0x01,0xa4,0x08,0x1c,0x00,0x0b,0x00,0x19,0x00,0x24,0xbf,0x00,0x03,0x05,0x0e,0x00,0x0f,0x00,0x15,0x05,0x0e,0x00,0x09,0x00,0x00,0x05,0x00,0xb2,0x12,0x0c,0x06,0xb8,0x01,0x4c,0x00,0x3f,0xdd,0xd6,0xed,0x01,0x2f,0xed, 0x2f,0xed,0x31,0x30,0x01,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x01,0x02,0x4b,0x57,0x53,0x4f,0x4c,0x53,0x54,0x4e,0x30,0x21,0x22,0x2f,0x30,0x24,0x08,0x14,0x20,0x08,0x1c,0x67,0x69,0x66,0x6b,0x69,0x67,0x6a,0x67,0xfe,0xaa,0x3b,0x49,0x4b,0x3c, 0x3b,0x4b,0x25,0x33,0x1f,0x0e,0x00,0x01,0x00,0x23,0x06,0x71,0x01,0xe3,0x07,0xb8,0x00,0x20,0x00,0x1d,0xb4,0x0b,0x12,0x1b,0x04,0x16,0xbc,0x04,0xfd,0x00,0x10,0x00,0x07,0x05,0x01,0x00,0x00,0x00,0x2f,0xfd,0xd6,0xed,0x01,0x2f,0xc4,0x39,0x39,0x31,0x30,0x13,0x22,0x26,0x27,0x27,0x16,0x16,0x33,0x32,0x36,0x37,0x35,0x2e,0x03,0x23, 0x22,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x07,0x0e,0x03,0x5f,0x0d,0x15,0x0d,0x0d,0x0e,0x1c,0x0d,0x54,0x90,0x39,0x12,0x1f,0x22,0x29,0x1d,0x32,0x24,0x13,0x2e,0x18,0x2b,0x3c,0x36,0x3b,0x2a,0x12,0x15,0x43,0x5c,0x76,0x06,0x71,0x01,0x02,0x67,0x02,0x02,0x34,0x23,0x03,0x06,0x0e,0x0c,0x08,0x0d,0x5f,0x06,0x07,0x16,0x1a, 0x17,0x01,0x73,0x09,0x2e,0x30,0x25,0x00,0x00,0x02,0x00,0x16,0x06,0x1f,0x02,0x28,0x08,0x5e,0x00,0x20,0x00,0x30,0x00,0x40,0xb3,0x06,0x2c,0x03,0x10,0xb8,0x05,0x0d,0xb3,0x24,0x20,0x20,0x1d,0xb8,0x05,0x0d,0x40,0x0a,0x03,0x00,0x00,0x03,0x1a,0x06,0x2c,0x03,0x15,0x0b,0xbb,0x05,0x01,0x00,0x29,0x00,0x21,0x05,0x01,0xb1,0x15,0x20, 0x00,0x2f,0xd6,0xfd,0xd6,0xed,0x11,0x17,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0xed,0x12,0x39,0x39,0x31,0x30,0x13,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x13,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x1e, 0x03,0x1e,0x04,0x04,0x31,0x2b,0x12,0x41,0x48,0x44,0x15,0x33,0x4a,0x2f,0x16,0x16,0x2a,0x3f,0x29,0x1a,0x35,0x31,0x2e,0x13,0x2b,0x24,0x04,0x05,0xfa,0x27,0x34,0x0d,0x1b,0x2b,0x1e,0x35,0x50,0x14,0x16,0x2c,0x2b,0x2b,0x06,0x1f,0x1a,0x31,0x14,0x44,0x61,0x17,0x65,0x74,0x3b,0x10,0x2c,0x44,0x4f,0x23,0x24,0x40,0x30,0x1d,0x0b,0x0c, 0x0b,0x3a,0x34,0x14,0x32,0x1a,0x01,0x12,0x1e,0x2b,0x13,0x2d,0x26,0x19,0x56,0x58,0x01,0x09,0x09,0x07,0x00,0x01,0xff,0x2b,0xfd,0xf5,0x02,0xae,0x00,0x05,0x00,0x43,0x00,0x66,0xb9,0x00,0x18,0x05,0x0d,0xb2,0x15,0x21,0x0b,0xb8,0x05,0x0d,0xb5,0x08,0x28,0x28,0x00,0x00,0x03,0xb8,0x05,0x0d,0x40,0x0a,0x40,0x15,0x08,0x40,0x40,0x08, 0x15,0x03,0x17,0x38,0xb8,0x05,0x0d,0xb4,0x32,0x17,0x38,0x32,0x2d,0xb8,0x04,0xfd,0xb4,0x3b,0x21,0x28,0x24,0x1d,0xb8,0x04,0xfd,0xb6,0x05,0x10,0x16,0x09,0x09,0x35,0x00,0x00,0x2f,0x32,0x32,0x11,0x33,0xd4,0x32,0xed,0x32,0x39,0x39,0xd4,0xed,0x2f,0x2f,0x01,0x2f,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x2f,0x32, 0x2f,0x10,0xed,0x39,0x10,0xed,0x31,0x30,0x17,0x16,0x16,0x17,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e, 0x02,0x35,0x34,0x26,0x27,0xe0,0x03,0x05,0x02,0x03,0x3f,0x1d,0x26,0x59,0x04,0x0f,0x1c,0x18,0x10,0x1a,0x12,0x0a,0x59,0x1b,0x2b,0x38,0x1d,0x29,0x3e,0x11,0x01,0x14,0x3a,0x1a,0x1a,0x21,0x0a,0x02,0x02,0x19,0x37,0x56,0x3e,0x3f,0x54,0x32,0x15,0x0d,0x56,0x05,0x05,0x3b,0x44,0x28,0x38,0x23,0x10,0x07,0x07,0x6e,0x1a,0x2c,0x17,0x34, 0x1e,0x2d,0x6d,0x50,0x1b,0x28,0x19,0x0c,0x06,0x11,0x1e,0x17,0xb8,0xd2,0x2d,0x3a,0x21,0x0c,0x17,0x1d,0x1e,0x16,0x0f,0x0e,0x30,0x4a,0x33,0x1a,0x1b,0x32,0x48,0x2d,0x33,0x3b,0x1b,0x29,0x16,0x41,0x35,0x12,0x28,0x41,0x2f,0x21,0x43,0x2f,0x00,0x01,0xff,0xc9,0x06,0x71,0x02,0x3c,0x07,0x26,0x00,0x1b,0x00,0x28,0x40,0x0a,0x00,0x0e, 0x0e,0x0d,0x0d,0x05,0x00,0x1b,0x1b,0x13,0xbc,0x05,0x01,0x00,0x0a,0x00,0x18,0x05,0x01,0x00,0x05,0x00,0x2f,0xed,0xdc,0xed,0x32,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xcd,0x31,0x30,0x01,0x0e,0x03,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x07,0x27,0x3e,0x03,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x37,0x02,0x3c,0x18,0x2e,0x2a,0x26, 0x10,0x30,0x4b,0x45,0x46,0x29,0x20,0x2d,0x17,0x3a,0x18,0x2d,0x2a,0x26,0x11,0x30,0x4c,0x45,0x44,0x29,0x21,0x2d,0x17,0x06,0xbf,0x19,0x1f,0x10,0x06,0x19,0x1d,0x19,0x15,0x14,0x41,0x19,0x1f,0x10,0x06,0x19,0x1d,0x19,0x13,0x16,0x00,0x02,0x00,0x4d,0x06,0x1f,0x01,0xb8,0x08,0x29,0x00,0x22,0x00,0x32,0x00,0x39,0xb1,0x13,0x2d,0xb8, 0x05,0x0d,0xb4,0x0f,0x0f,0x33,0x23,0x1a,0xb8,0x05,0x0d,0xb2,0x08,0x03,0x14,0xb8,0x05,0x01,0xb2,0x28,0x08,0x30,0xbc,0x04,0xfd,0x00,0x0a,0x00,0x03,0x04,0xfd,0x00,0x1f,0x00,0x2f,0xfd,0xde,0xfd,0x39,0xde,0xed,0x01,0x2f,0x2f,0xed,0x33,0x11,0x33,0x2f,0xed,0x32,0x31,0x30,0x13,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x06,0x23,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x4d,0x2c,0x45,0x21,0x29,0x32,0x1b,0x0a,0x01,0x21,0x28,0x1e,0x36,0x29,0x18,0x16,0x27,0x36,0x20,0x22,0x34,0x1a,0x1a,0x19,0x17,0x31,0x4f,0x38,0x26,0x49, 0x2d,0x01,0x13,0x0c,0x15,0x1b,0x0f,0x0b,0x16,0x11,0x0b,0x2f,0x1c,0x10,0x1f,0x06,0x9c,0x11,0x0c,0x14,0x1f,0x28,0x14,0x0c,0x12,0x23,0x35,0x23,0x1e,0x42,0x36,0x24,0x25,0x25,0x26,0x69,0x3b,0x30,0x59,0x44,0x29,0x0e,0x11,0x01,0x0d,0x0d,0x2b,0x28,0x1d,0x0e,0x16,0x1c,0x0d,0x1d,0x1f,0x04,0xff,0xff,0x00,0x21,0x06,0x70,0x03,0x36, 0x08,0x35,0x00,0x07,0x0a,0x1e,0x00,0x9f,0x00,0x00,0x00,0x01,0xff,0x82,0x06,0x70,0x02,0x97,0x08,0x35,0x00,0x23,0x00,0x1b,0xb9,0x00,0x08,0x05,0x0d,0xb4,0x1b,0x00,0x23,0x23,0x0b,0xb9,0x05,0x01,0x00,0x16,0x00,0x2f,0xed,0x32,0x2f,0x33,0x01,0x2f,0xed,0x31,0x30,0x01,0x0e,0x03,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02, 0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x36,0x36,0x37,0x01,0x02,0x20,0x38,0x33,0x31,0x19,0x2d,0x23,0x81,0x8b,0x38,0x77,0x72,0x66,0x27,0x34,0x7a,0x78,0x6c,0x27,0x63,0x86,0x51,0x22,0x13,0x23,0x2f,0x1b,0x2a,0x68,0x31,0x07,0xe3,0x1a,0x28,0x20,0x1b,0x0d,0x17,0x19,0x12,0x25,0x1b,0x04,0x06,0x08,0x05, 0x65,0x06,0x09,0x07,0x03,0x15,0x29,0x3a,0x25,0x1e,0x2e,0x27,0x21,0x11,0x19,0x40,0x2a,0x00,0x00,0x02,0x00,0x32,0x06,0x71,0x01,0xd4,0x08,0x8c,0x00,0x1e,0x00,0x22,0x00,0x31,0xbc,0x00,0x1f,0x05,0x0b,0x00,0x20,0x00,0x03,0x05,0x0d,0xb3,0x1b,0x11,0x11,0x13,0xb8,0x05,0x0d,0xb5,0x0d,0x22,0x1f,0x1e,0x11,0x16,0xb9,0x05,0x01,0x00, 0x08,0x00,0x2f,0xfd,0xc6,0xd6,0xd6,0xcd,0x01,0x2f,0xed,0x32,0x2f,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x27,0x23,0x35,0x33,0x01,0xc7,0x07,0x06,0x16,0x35,0x56,0x40,0x37,0x4a,0x2d,0x13,0x06, 0x05,0x58,0x09,0x31,0x3b,0x23,0x31,0x20,0x0e,0x07,0x06,0x31,0x73,0x73,0x07,0xe3,0x23,0x43,0x1f,0x37,0x58,0x3d,0x21,0x1a,0x32,0x46,0x2c,0x18,0x35,0x1e,0x3b,0x29,0x35,0x2a,0x0f,0x22,0x37,0x27,0x1a,0x3d,0x26,0x38,0x71,0x00,0x00,0x04,0x00,0x64,0xff,0xe0,0x04,0x68,0x06,0xb4,0x00,0x17,0x00,0x2e,0x00,0x45,0x00,0x5b,0x00,0x14, 0xb7,0x3a,0x23,0x0b,0x52,0x45,0x18,0x17,0x46,0x00,0x2f,0xcd,0xde,0xcd,0x2f,0x33,0xce,0x32,0x30,0x31,0x01,0x26,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x01,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x07,0x11,0x21,0x37,0x11,0x26,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x06,0x06, 0x07,0x11,0x27,0x11,0x36,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x17,0x11,0x07,0x21,0x11,0x36,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x27,0x01,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x17,0x01,0x18,0x41,0x2b,0x23,0x25,0x13,0x24,0x33,0x21,0x01,0x77,0x01,0x75,0x40,0x4d,0x22, 0x23,0x15,0x37,0x23,0xfd,0x64,0xbe,0x34,0x40,0x14,0x16,0x16,0x2a,0x26,0xf4,0xf2,0x24,0x2e,0x17,0x15,0x17,0x44,0x2d,0x44,0x39,0x4c,0x11,0x0e,0x10,0x21,0x19,0xc6,0xc6,0x1c,0x1e,0x0f,0x0e,0x0e,0x4a,0x3f,0x9a,0x01,0xcc,0x33,0x3f,0x0e,0x1a,0x1a,0x3c,0x33,0xfe,0xd5,0xfe,0xd3,0x33,0x3a,0x1c,0x1a,0x1e,0x60,0x02,0xa2,0x29,0x42, 0x35,0x7c,0x42,0x32,0x56,0x4d,0x45,0x21,0x01,0x79,0xfe,0x8b,0x41,0x9f,0x60,0x41,0x7b,0x35,0x20,0x37,0x15,0xfd,0x3e,0xbe,0x02,0x6c,0x15,0x2f,0x19,0x1c,0x4e,0x2d,0x3c,0x5b,0x26,0xf5,0xf2,0x24,0x5e,0x40,0x2d,0x4c,0x1b,0x1d,0x2f,0x14,0xfd,0x96,0x44,0x02,0x52,0x1a,0x2d,0x16,0x12,0x37,0x22,0x30,0x45,0x19,0xc6,0xc8,0x1d,0x41, 0x2c,0x21,0x39,0x12,0x13,0x33,0x14,0xfd,0xaa,0x9a,0x02,0x95,0x1e,0x35,0x17,0x28,0x5e,0x32,0x49,0x7f,0x33,0x01,0x2b,0xfe,0xd2,0x34,0x76,0x4d,0x33,0x60,0x27,0x2e,0x3d,0x00,0x00,0x02,0x00,0x10,0xfd,0xda,0x01,0xf7,0xff,0xc1,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x14,0x00,0x07,0x07,0x05,0x05,0x06,0x01,0x04,0x03,0x02,0x02,0x01, 0x2f,0x03,0x01,0x03,0x2f,0x01,0x01,0x01,0x00,0x2f,0x5d,0x2f,0x5d,0x12,0x39,0x3d,0x2f,0x12,0x39,0x12,0x39,0x33,0x11,0x33,0x11,0x33,0x31,0x30,0x13,0x37,0x17,0x07,0x35,0x37,0x27,0x07,0x10,0xf4,0xf3,0xf4,0x8a,0x89,0x8a,0xfe,0xcd,0xf4,0xf4,0xf3,0x6a,0x89,0x89,0x89,0x00,0x02,0x00,0x10,0x06,0x35,0x01,0xf7,0x08,0x1c,0x00,0x03, 0x00,0x07,0x00,0x22,0x40,0x0e,0x00,0x07,0x07,0x05,0x05,0x06,0x01,0x04,0x03,0x02,0x02,0x01,0x03,0x01,0x00,0x2f,0x2f,0x12,0x39,0x3d,0x2f,0x12,0x39,0x12,0x39,0x33,0x11,0x33,0x11,0x33,0x31,0x30,0x13,0x37,0x17,0x07,0x35,0x37,0x27,0x07,0x10,0xf4,0xf3,0xf4,0x8a,0x89,0x8a,0x07,0x28,0xf4,0xf4,0xf3,0x6a,0x89,0x89,0x89,0x00,0x02, 0x00,0x16,0xfd,0xf5,0x02,0x28,0x00,0x34,0x00,0x20,0x00,0x30,0x00,0x40,0xb9,0x00,0x10,0x05,0x0d,0xb5,0x24,0x20,0x20,0x06,0x06,0x1d,0xb8,0x05,0x0d,0x40,0x09,0x03,0x00,0x00,0x03,0x1a,0x2c,0x0b,0x20,0x15,0xbb,0x04,0xfd,0x00,0x21,0x00,0x29,0x04,0xfd,0xb3,0x2f,0x0b,0x01,0x0b,0x00,0x2f,0x5d,0xfd,0xd6,0xed,0x32,0x11,0x39,0x39, 0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x32,0x2f,0x2f,0xed,0x31,0x30,0x13,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x13,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x1e,0x03,0x1e,0x04,0x04,0x31,0x2b,0x12,0x41,0x48,0x44, 0x15,0x33,0x4a,0x2f,0x16,0x16,0x2a,0x3f,0x29,0x1a,0x35,0x31,0x2e,0x13,0x2b,0x24,0x04,0x05,0xfa,0x27,0x34,0x0d,0x1b,0x2b,0x1e,0x35,0x50,0x14,0x16,0x2c,0x2b,0x2b,0xfd,0xf5,0x1a,0x31,0x14,0x44,0x61,0x17,0x65,0x74,0x3b,0x10,0x2c,0x44,0x4f,0x23,0x24,0x40,0x30,0x1d,0x0b,0x0c,0x0b,0x3a,0x34,0x14,0x32,0x1a,0x01,0x12,0x1e,0x2b, 0x13,0x2d,0x26,0x19,0x56,0x58,0x01,0x09,0x09,0x07,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x05,0x1f,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x27,0x0f,0x53,0x05,0x46,0x03,0x57,0x00,0x07,0x0f,0x50,0x05,0x50,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x05,0xf4,0x05,0x1f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x27,0x0f,0x53,0x02,0xa4, 0x03,0x57,0x00,0x07,0x0f,0x50,0x02,0xa4,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0xf7,0x04,0xb2,0x02,0x26,0x09,0x1b,0x00,0x00,0x00,0x27,0x0f,0x50,0x06,0x3c,0xfe,0xab,0x00,0x07,0x0f,0x50,0x05,0xca,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x07,0x4b,0x04,0xb2,0x02,0x26,0x08,0xd6,0x00,0x00,0x00,0x27,0x0f,0x50,0x03,0x1e, 0x04,0x02,0x00,0x07,0x0f,0x50,0x03,0x90,0xfe,0xab,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x05,0x8f,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0xe4,0x04,0xdf,0x00,0x07,0x0f,0x50,0x01,0x8f,0xff,0xb1,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad,0x05,0x2a,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x56, 0x04,0x7a,0x00,0x07,0x0f,0x50,0x01,0x56,0xff,0x57,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x3c,0x04,0xe4,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x1d,0x04,0x34,0x00,0x07,0x0f,0x50,0x01,0x1d,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0xad,0x04,0xb2,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x56, 0x04,0x02,0x00,0x07,0x0f,0x50,0x01,0x56,0xfe,0xab,0xff,0xff,0x00,0x5a,0xfd,0xff,0x02,0xe5,0x02,0xb4,0x02,0x26,0x09,0x07,0x00,0x00,0x00,0x07,0x0f,0x5d,0x00,0xab,0x00,0x00,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0xf4,0x02,0xb9,0x02,0x26,0x09,0x26,0x00,0x00,0x00,0x07,0x0f,0x5d,0x01,0x99,0x00,0x00,0xff,0xff,0xff,0xc2,0xff,0xea, 0x03,0xf3,0x07,0x77,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x01,0x07,0x09,0x77,0x00,0x00,0x08,0x0c,0x00,0x0a,0xb4,0x02,0x20,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xc2,0xff,0xea,0x04,0xad,0x07,0x77,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x01,0x07, 0x09,0x77,0x00,0x00,0x08,0x0c,0x00,0x0a,0xb4,0x02,0x20,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x34,0xfd,0xfe,0x03,0xf3,0x05,0xec,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x77,0x72,0x00,0xff,0xff,0x00,0x34,0xfd,0xfe,0x04,0xad,0x05,0xec,0x00,0x27,0x0f,0x8d,0x02,0xac, 0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x77,0x72,0x00,0xff,0xff,0x00,0x3a,0xff,0xea,0x03,0xf3,0x05,0xec,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0xc8,0x00,0x00,0x07,0x09,0x7e,0x01,0x56,0xfe,0x00,0xff,0xff,0x00,0x3a,0xff,0xea,0x04,0xad,0x05,0xec,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00, 0x00,0x26,0x0f,0x65,0xc8,0x00,0x00,0x07,0x09,0x7e,0x01,0x56,0xfe,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xc5,0x08,0x0e,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0x9d,0x00,0x32,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xc5,0x08,0x0e,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27, 0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0x9d,0x00,0x32,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0xfa,0x07,0x67,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x9d,0x06,0xb7,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xad,0x07,0x67,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27, 0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x9d,0x06,0xb7,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x9b,0x08,0x7f,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x01,0x07,0x0f,0x53,0x02,0x9d,0x06,0xb7,0x00,0x0e,0xb6,0x04,0x03,0x02,0x20,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff, 0x00,0x52,0xff,0xea,0x04,0xad,0x08,0x7f,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x01,0x07,0x0f,0x53,0x02,0x9d,0x06,0xb7,0x00,0x0e,0xb6,0x04,0x03,0x02,0x20,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0x00,0x52,0xfd,0xc9,0x04,0x9b,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27, 0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0x9d,0xfd,0xce,0xff,0xff,0x00,0x52,0xfd,0xc9,0x04,0xad,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0x9d,0xfd,0xce,0x00,0x01,0x00,0x65,0x00,0x00,0x03,0xf8,0x05,0xa8,0x00,0x2b,0x00,0x40,0xb4,0x04,0x03,0x15, 0x2d,0x1d,0xb8,0x05,0x0a,0xb2,0x0e,0x0e,0x14,0xb8,0x05,0x0a,0xb6,0x15,0x27,0x22,0x04,0x04,0x14,0x09,0xb8,0x04,0xfb,0xb7,0x22,0x00,0x00,0x2f,0x22,0x01,0x22,0x14,0xb8,0x04,0xe6,0x00,0x3f,0x2f,0x5d,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x12,0x39,0x01,0x2f,0xed,0x39,0x2f,0xed,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x06,0x02,0x07, 0x23,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x16,0x12,0x15,0x11,0x23,0x11,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x03,0xf8,0x48,0x6d,0x23,0x9a,0x11,0x38,0x4a,0x5b,0x33,0x1d,0x25,0x14,0x07,0x18,0x1e,0x18,0x9c,0x0d,0x12,0x17,0x12,0x0d,0x21,0x41,0x5f,0x3f,0x46,0x75,0x5c,0x3f, 0x0f,0x05,0x1a,0x43,0x26,0x05,0x9a,0x6f,0xfe,0xfe,0x95,0x4a,0x83,0x62,0x39,0x11,0x1b,0x23,0x11,0x1d,0x72,0xbe,0xfe,0xec,0xc0,0xfe,0x85,0x01,0x73,0x88,0xd5,0xa4,0x7a,0x5c,0x44,0x1c,0x39,0x5d,0x43,0x25,0x3c,0x5d,0x6e,0x33,0x56,0x94,0x42,0x00,0x00,0x01,0x00,0x52,0x00,0x00,0x03,0x81,0x05,0x9a,0x00,0x12,0x00,0x20,0xb9,0x00, 0x08,0x05,0x0a,0xb2,0x07,0x00,0x0f,0xba,0x04,0xfb,0x00,0x11,0x04,0xe6,0xb3,0x2f,0x08,0x01,0x08,0x00,0x2f,0x5d,0x3f,0xed,0x32,0x01,0x2f,0xed,0x31,0x30,0x37,0x3e,0x04,0x12,0x37,0x33,0x06,0x02,0x0e,0x03,0x07,0x21,0x15,0x21,0x52,0x31,0x53,0x45,0x36,0x27,0x19,0x05,0x9c,0x07,0x19,0x23,0x2d,0x37,0x41,0x25,0x02,0x5c,0xfc,0xd1, 0x42,0x5c,0xb1,0xba,0xcd,0xf3,0x01,0x20,0xb1,0xb4,0xfe,0xe2,0xe8,0xba,0xa2,0x92,0x4b,0xa7,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x07,0xcb,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x90,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x07,0xcb,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x90, 0x06,0x03,0x00,0x01,0x00,0x00,0x01,0x87,0x02,0xfe,0x01,0xd9,0x00,0x03,0x00,0x10,0xb9,0x00,0x00,0x04,0xfd,0xb3,0x2f,0x03,0x01,0x03,0x00,0x2f,0x5d,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0xfe,0xfd,0x02,0x02,0xfe,0x01,0x87,0x52,0x00,0xff,0xff,0xff,0x97,0xff,0xea,0x03,0xf3,0x07,0x77,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00, 0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x0f,0x58,0x00,0x8f,0xff,0xff,0xff,0x97,0xff,0xea,0x04,0xad,0x07,0x77,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x0f,0x58,0x00,0x8f,0x00,0x10,0x00,0x66,0x00,0x5a,0x04,0x5b,0x04,0x4e,0x00,0x07,0x00,0x0f,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0x2f, 0x00,0x37,0x00,0x3f,0x00,0x47,0x00,0x4f,0x00,0x57,0x00,0x5f,0x00,0x67,0x00,0x6f,0x00,0x77,0x00,0x7f,0x01,0x23,0xb9,0x00,0x18,0x05,0x0b,0xb2,0x1c,0x30,0x10,0xb8,0x05,0x0b,0xb4,0x34,0x14,0x14,0x40,0x00,0xb8,0x05,0x0b,0xb4,0x04,0x44,0x04,0x48,0x08,0xb8,0x05,0x0b,0xb4,0x0c,0x4c,0x0c,0x60,0x20,0xb8,0x05,0x0b,0xb4,0x24,0x64, 0x24,0x70,0x28,0xb8,0x05,0x0b,0xb4,0x2c,0x74,0x2c,0x78,0x38,0xb8,0x05,0x0b,0xb4,0x3c,0x7c,0x3c,0x68,0x50,0xb8,0x05,0x0b,0x40,0x14,0x54,0x6c,0x54,0x1c,0x04,0x0c,0x24,0x2c,0x3c,0x54,0x54,0x3c,0x2c,0x24,0x0c,0x04,0x1c,0x07,0x81,0x58,0xb8,0x05,0x0b,0xb2,0x5c,0x2a,0x0a,0xb8,0x04,0xfd,0xb4,0x0e,0x2e,0x0e,0x3a,0x02,0xb8,0x04, 0xfd,0xb4,0x06,0x3e,0x06,0x52,0x12,0xb8,0x04,0xfd,0xb4,0x16,0x56,0x16,0x5a,0x1a,0xb8,0x04,0xfd,0xb4,0x1e,0x5e,0x1e,0x6a,0x32,0xb8,0x04,0xfd,0xb4,0x36,0x6e,0x36,0x7a,0x42,0xb8,0x04,0xfd,0xb4,0x46,0x7e,0x46,0x72,0x4a,0xb8,0x04,0xfd,0x40,0x14,0x4e,0x76,0x4e,0x0e,0x06,0x16,0x1e,0x36,0x46,0x4e,0x4e,0x46,0x36,0x1e,0x16,0x06, 0x0e,0x07,0x26,0x62,0xbb,0x04,0xfd,0x00,0x66,0x00,0x22,0x04,0xfd,0xb3,0x3f,0x26,0x01,0x26,0x00,0x2f,0x5d,0xed,0x2f,0xed,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32, 0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x32,0x2f,0x33,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x14,0x23,0x22,0x35,0x34,0x33, 0x32,0x27,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x13,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x17,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x07,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33, 0x32,0x07,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x07,0x16,0x23,0x22,0x35,0x34,0x33,0x32,0x01,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x25,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x13,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x27,0x14,0x23,0x22,0x35,0x34,0x33,0x32,0x03,0xd4,0x30,0x34,0x34,0x30,0x94, 0x30,0x34,0x34,0x30,0xf7,0x33,0x31,0x33,0x31,0x24,0x30,0x34,0x34,0x30,0xfe,0x37,0x32,0x32,0x32,0x32,0xad,0x33,0x31,0x31,0x33,0x02,0x52,0x33,0x31,0x31,0x33,0xfd,0x1a,0x32,0x32,0x32,0x32,0x02,0x83,0x30,0x34,0x34,0x30,0x94,0x30,0x34,0x34,0x30,0xfd,0xae,0x30,0x34,0x32,0x32,0x24,0x01,0x31,0x34,0x34,0x31,0x01,0xc7,0x32,0x32, 0x32,0x32,0xfe,0x5c,0x32,0x32,0x32,0x32,0xf7,0x33,0x31,0x31,0x33,0x94,0x32,0x32,0x32,0x32,0x03,0x96,0x32,0x32,0x32,0x30,0x31,0x31,0x33,0xfe,0xd7,0x33,0x33,0x31,0xdf,0x32,0x32,0x32,0x01,0x97,0x33,0x33,0x31,0x56,0x31,0x31,0x33,0xfd,0x7b,0x31,0x31,0x33,0x01,0xbd,0x32,0x2f,0x35,0xfd,0x48,0x31,0x31,0x33,0x95,0x30,0x30,0x34, 0x02,0x20,0x33,0x33,0x31,0xdf,0x32,0x32,0x32,0xfe,0x07,0x33,0x33,0x31,0xe8,0x31,0x31,0x33,0xfe,0xd9,0x34,0x30,0x34,0x2e,0x31,0x31,0x33,0x00,0x00,0x01,0x00,0x73,0xff,0xf2,0x09,0x63,0x01,0xef,0x00,0x0f,0x00,0x10,0xb2,0x0e,0x0b,0x07,0xb9,0x04,0xfb,0x00,0x00,0x00,0x2f,0xfd,0xcd,0x33,0x30,0x31,0x05,0x21,0x22,0x26,0x27,0x27, 0x37,0x21,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x33,0x09,0x63,0xf8,0x84,0x55,0xb2,0x51,0x1c,0x05,0x07,0x66,0x20,0x23,0x9d,0x25,0x1e,0xe8,0x0e,0x0e,0x0f,0x85,0x05,0x5a,0xa8,0x54,0x5a,0xa3,0x59,0x00,0x01,0x00,0x73,0xff,0xf1,0x08,0x39,0x01,0x60,0x00,0x4d,0x00,0x22,0xb1,0x2e,0x3d,0xb8,0x04,0xfb,0xb5,0x1d,0x00,0x10,0x18,0x06, 0x22,0xb8,0x04,0xfb,0xb2,0x45,0x33,0x29,0x00,0x2f,0x33,0x33,0xfd,0x32,0x32,0xdc,0x32,0x32,0xed,0x32,0x30,0x31,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x1e,0x03,0x33,0x21,0x17,0x07,0x06,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23, 0x22,0x2e,0x02,0x27,0x2e,0x03,0x23,0x22,0x06,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x01,0x24,0x0a,0x0b,0x23,0x1b,0x16,0x2a,0x28,0x25,0x11,0x14,0x2e,0x34,0x3c,0x21,0x20,0x31,0x27,0x1f,0x0e,0x1e,0x30,0x22,0x12,0x29,0x2e,0x32,0x1a,0x36,0x74,0x87,0x9f,0x62,0x01,0x7a,0x05,0x1c,0x51,0xb2,0x55,0x35,0x60,0x8d, 0x71,0x60,0x33,0x20,0x3c,0x38,0x33,0x18,0x21,0x33,0x29,0x20,0x0f,0x12,0x1c,0x1a,0x1b,0x12,0x1d,0x34,0x1d,0x16,0x32,0x3d,0x4c,0x30,0x33,0x48,0x2d,0x15,0x13,0x0f,0x01,0x48,0x1e,0x3b,0x16,0x26,0x20,0x10,0x1b,0x21,0x11,0x13,0x28,0x20,0x15,0x15,0x20,0x29,0x13,0x2a,0x32,0x10,0x26,0x3e,0x2f,0x1d,0x39,0x2c,0x1b,0x05,0x85,0x0f, 0x0e,0x17,0x25,0x31,0x1b,0x2a,0x35,0x1d,0x0b,0x0f,0x1a,0x22,0x13,0x17,0x25,0x19,0x0e,0x28,0x1c,0x15,0x2d,0x25,0x18,0x1b,0x30,0x43,0x28,0x2a,0x52,0x25,0x00,0x02,0x00,0x49,0xff,0xf2,0x05,0xd0,0x02,0x6c,0x00,0x1c,0x00,0x2e,0x00,0x16,0xb9,0x00,0x15,0x04,0xfb,0xb2,0x22,0x2c,0x1c,0xb9,0x04,0xfb,0x00,0x0b,0x00,0x2f,0xfd,0x32, 0xdc,0xed,0x30,0x31,0x25,0x17,0x07,0x06,0x06,0x23,0x23,0x2a,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x04,0x17,0x23,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x05,0xcc,0x04,0x1c,0x51,0xb2,0x55,0x36,0x1c,0x5e,0x7b,0x95,0x52,0x82,0xc1,0x7f,0x3f,0x32,0x5a,0x7c,0x4a,0x3e,0x68,0x55, 0x43,0x33,0x23,0x0b,0x9f,0x0b,0x2b,0x3f,0x53,0x34,0x20,0x43,0x38,0x24,0x20,0x42,0x66,0x47,0x30,0x52,0x99,0x06,0x84,0x0f,0x0e,0x05,0x2a,0x59,0x53,0x55,0x97,0x71,0x42,0x2d,0x4a,0x60,0x68,0x68,0x2c,0x36,0x6a,0x55,0x35,0x17,0x31,0x4c,0x35,0x24,0x28,0x13,0x03,0x01,0x00,0x02,0x00,0x73,0xff,0xed,0x0b,0xbf,0x02,0x6c,0x00,0x32, 0x00,0x46,0x00,0x1c,0xb9,0x00,0x18,0x04,0xfb,0xb4,0x3d,0x42,0x11,0x09,0x00,0xb8,0x04,0xfb,0xb1,0x22,0x2c,0x00,0x2f,0x33,0xfd,0xcc,0x33,0x33,0xdc,0xed,0x30,0x31,0x25,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x17,0x3e,0x05,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x26,0x26,0x27, 0x23,0x06,0x06,0x23,0x21,0x22,0x26,0x27,0x27,0x37,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x32,0x32,0x16,0x32,0x07,0xab,0x2d,0x23,0x02,0x04,0x07,0x04,0x8a,0x0b,0x0e,0x04,0x03,0x0a,0x13,0x20,0x19,0x0f,0x2d,0x3d,0x4c,0x5b,0x6b,0x3d,0x45,0x65,0x43,0x20,0x36,0x78,0xc0,0x8a,0x7c,0xa4,0x24,0x11,0x21, 0x0b,0x02,0x1e,0x53,0x2d,0xfa,0x41,0x55,0xb2,0x51,0x1c,0x05,0x09,0xab,0x4e,0x65,0x3c,0x17,0x18,0x29,0x37,0x1f,0x35,0x59,0x46,0x33,0x0f,0x0d,0x30,0x32,0x2d,0x99,0x2f,0x2d,0x0a,0x1d,0x21,0x22,0x0f,0x2a,0x4e,0x14,0x0d,0x18,0x13,0x0d,0x02,0x2c,0x68,0x67,0x60,0x4a,0x2c,0x3a,0x64,0x87,0x4d,0x63,0x6d,0x33,0x0a,0x05,0x0e,0x06, 0x22,0x13,0x2a,0x1f,0x0e,0x0f,0x85,0x05,0x03,0x04,0x16,0x2f,0x2c,0x31,0x45,0x2d,0x15,0x36,0x55,0x6b,0x36,0x01,0x00,0x02,0x00,0x49,0xff,0xf0,0x08,0x3d,0x02,0x6c,0x00,0x1e,0x00,0x30,0x00,0x36,0xb4,0x1e,0x1f,0x1f,0x32,0x29,0xbb,0x05,0x0a,0x00,0x12,0x00,0x24,0x04,0xfb,0x40,0x0b,0x2f,0x17,0x01,0x17,0x2e,0x2e,0x1f,0x1f,0x1e, 0x1e,0x00,0xb9,0x04,0xfb,0x00,0x07,0x00,0x2f,0xed,0x32,0x11,0x33,0x11,0x33,0x2f,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x10,0xcd,0x30,0x31,0x25,0x32,0x36,0x37,0x07,0x06,0x06,0x23,0x21,0x22,0x06,0x22,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x04,0x17,0x23,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e, 0x02,0x33,0x32,0x36,0x06,0xfe,0x51,0x9c,0x52,0x21,0x23,0x80,0x55,0xfd,0x63,0x5c,0x8c,0x80,0x82,0x53,0x82,0xc1,0x7f,0x3f,0x32,0x5a,0x7c,0x4a,0x3e,0x68,0x55,0x43,0x33,0x23,0x0b,0x9f,0x0b,0x2a,0x40,0x54,0x33,0x20,0x43,0x38,0x24,0x20,0x42,0x66,0x47,0x30,0x53,0x99,0x08,0x0a,0xa9,0x05,0x0b,0x01,0x01,0x07,0x2a,0x5a,0x52,0x55, 0x97,0x71,0x42,0x2d,0x4a,0x60,0x68,0x68,0x2c,0x36,0x6a,0x55,0x35,0x17,0x31,0x4c,0x35,0x24,0x28,0x13,0x03,0x01,0x00,0x01,0x00,0x46,0xfe,0xaa,0x02,0x1e,0x02,0x01,0x00,0x09,0x00,0x18,0x40,0x0a,0x00,0x06,0x06,0x0b,0x0a,0x09,0x2f,0x05,0x01,0x05,0x00,0x2f,0x5d,0xcd,0x11,0x12,0x01,0x39,0x2f,0xcd,0x31,0x30,0x01,0x0e,0x03,0x07, 0x23,0x36,0x12,0x37,0x02,0x1e,0x2c,0x5a,0x56,0x51,0x23,0x88,0x46,0x9f,0x4f,0x02,0x01,0x5a,0xce,0xdb,0xe4,0x70,0xfb,0x01,0xb4,0xa8,0x00,0x02,0x00,0x32,0xfd,0xfe,0x04,0x2e,0x04,0x0c,0x00,0x45,0x00,0x58,0x00,0x6d,0xb2,0x45,0x26,0x13,0xb8,0x05,0x0a,0xb4,0x4b,0x4b,0x5a,0x2e,0x26,0xb8,0x05,0x0a,0xb3,0x09,0x05,0x05,0x3f,0xb8, 0x05,0x0a,0xb7,0x2e,0x1b,0x23,0x55,0x09,0x04,0x18,0x0e,0xbc,0x04,0xfc,0x00,0x50,0x04,0xe6,0x00,0x00,0x04,0xfb,0xb5,0x42,0x2b,0x45,0x45,0x18,0x3a,0xb8,0x04,0xfb,0xb2,0x33,0x20,0x46,0xb8,0x04,0xfc,0x40,0x09,0x18,0x1f,0x1f,0x1f,0x18,0x2f,0x18,0x02,0x18,0x00,0x2f,0x5d,0x33,0x2f,0x10,0xed,0x39,0x2f,0xed,0x12,0x39,0x2f,0x39, 0x39,0xed,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0xed,0x39,0x2f,0x39,0xed,0x11,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x0e,0x03,0x15,0x14,0x16,0x17,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x07,0x06,0x06,0x07,0x23,0x36,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34, 0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x37,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x15,0x16,0x16,0x03,0x5c,0xad,0xe9,0x8c,0x3b,0x08,0x07,0x05,0x3a,0x76,0x78,0x78,0x3d,0x4f,0x77,0x50,0x28,0x40,0x78,0xae,0x6e,0x6f,0xad,0x3f,0x03,0x10,0x1e, 0x10,0x8c,0x1d,0x3b,0x1d,0x21,0x21,0x14,0x32,0x52,0x3f,0x4c,0x45,0x3d,0x72,0xa6,0x69,0x23,0x4f,0x2a,0x27,0x55,0x2b,0x36,0x65,0x4d,0x2f,0x37,0x33,0x51,0xd0,0x8a,0xfb,0x4b,0x72,0x4e,0x27,0x14,0x2c,0x45,0x30,0x2a,0x5c,0x62,0x6a,0x37,0x2d,0x86,0x01,0x9f,0x2e,0x68,0x73,0x7c,0x42,0x1d,0x33,0x1a,0x51,0x70,0x46,0x1f,0x2e,0x4f, 0x68,0x39,0x49,0x87,0x69,0x3f,0x40,0x36,0x01,0x1b,0x39,0x20,0x3d,0x6b,0x30,0x36,0x78,0x40,0x2e,0x65,0x66,0x65,0x30,0x45,0xa3,0x4f,0x4c,0x8c,0x6a,0x40,0x08,0x09,0xaa,0x08,0x0b,0x15,0x34,0x57,0x43,0x48,0x71,0x28,0x2d,0x52,0x24,0xfc,0x55,0x26,0x3d,0x4d,0x26,0x1b,0x33,0x28,0x18,0x17,0x39,0x63,0x4c,0x02,0x2d,0x36,0x00,0x02, 0xff,0xc9,0x06,0x37,0x02,0x29,0x07,0xeb,0x00,0x24,0x00,0x36,0x00,0x2e,0xbc,0x00,0x11,0x05,0x0d,0x00,0x2a,0x00,0x0c,0x05,0x01,0x40,0x09,0x2d,0x25,0x32,0x32,0x25,0x07,0x07,0x01,0x25,0xb8,0x05,0x01,0xb1,0x1f,0x16,0x00,0x2f,0xc6,0xfd,0xc4,0x33,0x2f,0x11,0x33,0x2f,0x10,0xd6,0xed,0x01,0x2f,0xed,0x31,0x30,0x03,0x33,0x16,0x16, 0x17,0x16,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x07,0x06,0x06,0x07,0x23,0x36,0x36,0x35,0x34,0x05,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x32,0x16,0x32,0x32,0x17,0x51,0x06,0x09,0x02,0x04,0x13,0x1d,0x0d,0x2f,0x43,0x57,0x36,0x28,0x3c,0x27,0x13,0x20,0x46,0x71, 0x51,0x30,0x41,0x2c,0x1b,0x0c,0x03,0x05,0x0e,0x07,0x57,0x13,0x17,0x01,0x44,0x2e,0x3b,0x23,0x0e,0x34,0x25,0x1f,0x34,0x29,0x1e,0x09,0x08,0x1c,0x1d,0x1b,0x07,0x56,0x18,0x2f,0x0b,0x10,0x18,0x02,0x27,0x5f,0x53,0x38,0x22,0x3a,0x50,0x2d,0x3a,0x40,0x1e,0x06,0x01,0x04,0x09,0x08,0x01,0x16,0x2b,0x11,0x33,0x63,0x33,0x2f,0x58,0x02, 0x0e,0x1b,0x1a,0x39,0x33,0x1f,0x33,0x3f,0x1f,0x01,0x00,0x01,0xff,0xe9,0x06,0x37,0x01,0xee,0x07,0xeb,0x00,0x2e,0x00,0x4a,0xb1,0x24,0x06,0xb8,0x05,0x0d,0xb4,0x00,0x27,0x27,0x09,0x1e,0xb8,0x05,0x0d,0x40,0x0b,0x18,0x1a,0x1a,0x18,0x09,0x24,0x09,0x0a,0x2e,0x2e,0x2c,0xb8,0x05,0x01,0xb5,0x03,0x09,0x23,0x23,0x1b,0x09,0xb8,0x05, 0x01,0xb1,0x14,0x0a,0x00,0x2f,0xc6,0xfd,0xc4,0x33,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x11,0x12,0x39,0x01,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x39,0xed,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x07,0x06,0x06,0x07,0x23,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x16,0x17, 0x1e,0x03,0x33,0x33,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0xbe,0x0e,0x1d,0x11,0x2e,0x40,0x92,0x48,0xcd,0x30,0x41,0x2c,0x1b,0x0c,0x03,0x05,0x0e,0x07,0x57,0x13,0x17,0x0a,0x51,0x06,0x09,0x02,0x02,0x08,0x12,0x20,0x1b,0x1d,0x12,0x17,0x1d,0x34,0x49,0x2c,0x20,0x22,0x07,0x7e,0x03,0x04,0x26,0x2c,0x5b,0x64,0x01,0x04, 0x09,0x08,0x01,0x16,0x2b,0x11,0x33,0x63,0x33,0x2f,0x27,0x18,0x2f,0x0b,0x0a,0x11,0x0c,0x06,0x1b,0x3b,0x1e,0x23,0x3b,0x2b,0x17,0x06,0x00,0x02,0x00,0x03,0x06,0x1f,0x02,0x20,0x08,0x00,0x00,0x1d,0x00,0x36,0x00,0x2c,0xbf,0x00,0x2e,0x05,0x0d,0x00,0x25,0x00,0x11,0x04,0xfd,0x00,0x18,0x00,0x20,0x04,0xfd,0x40,0x0a,0x33,0x1e,0x00, 0x0c,0x14,0x1d,0x05,0x05,0x28,0x05,0x00,0x2f,0x2f,0x12,0x17,0x39,0x2f,0xfd,0xd4,0xed,0x01,0x2f,0xed,0x31,0x30,0x01,0x0e,0x03,0x07,0x23,0x3e,0x03,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x03,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22, 0x26,0x27,0x01,0x4a,0x49,0x5a,0x34,0x18,0x07,0x51,0x06,0x17,0x32,0x57,0x47,0x14,0x1c,0x1e,0x25,0x1c,0x18,0x2d,0x11,0x14,0x2e,0x17,0x2b,0x39,0x32,0x37,0x2b,0x65,0x38,0x26,0x21,0x2c,0x1a,0x0b,0x1d,0x13,0x5a,0x0c,0x11,0x0c,0x06,0x1f,0x38,0x4b,0x2b,0x17,0x2b,0x1a,0x07,0x2f,0x12,0x29,0x2f,0x36,0x1e,0x1e,0x40,0x3f,0x3a,0x18, 0x03,0x07,0x0e,0x0c,0x07,0x06,0x07,0x5f,0x06,0x07,0x15,0x1b,0x17,0x01,0xfe,0xee,0x11,0x17,0x29,0x37,0x21,0x3e,0x75,0x36,0x1d,0x3d,0x3e,0x3a,0x19,0x3c,0x5c,0x3e,0x20,0x09,0x0a,0x00,0x00,0x04,0xff,0x88,0x06,0x1f,0x02,0xb1,0x08,0xbb,0x00,0x24,0x00,0x36,0x00,0x4d,0x00,0x51,0x00,0x52,0xb2,0x41,0x45,0x4e,0xbb,0x05,0x0d,0x00, 0x4f,0x00,0x45,0x05,0x0d,0xb2,0x3e,0x37,0x11,0xb8,0x05,0x0d,0xb3,0x2a,0x51,0x4e,0x0c,0xb8,0x05,0x01,0x40,0x09,0x2d,0x25,0x32,0x32,0x25,0x07,0x07,0x01,0x25,0xb8,0x05,0x01,0xb3,0x1f,0x16,0x41,0x39,0xb9,0x04,0xfd,0x00,0x4a,0x00,0x2f,0xfd,0xce,0xd4,0xce,0xfd,0xc4,0x33,0x2f,0x11,0x33,0x2f,0x10,0xd6,0xfd,0xd6,0xcd,0x01,0x2f, 0xed,0x39,0x2f,0xed,0x2f,0xed,0x12,0x39,0x31,0x30,0x03,0x33,0x16,0x16,0x17,0x16,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x07,0x06,0x06,0x07,0x23,0x36,0x36,0x35,0x34,0x05,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x32,0x16,0x32,0x32,0x17,0x16,0x33,0x32,0x3e,0x02, 0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x03,0x23,0x35,0x33,0x58,0x51,0x06,0x09,0x02,0x04,0x13,0x1d,0x0c,0x2d,0x40,0x53,0x33,0x27,0x38,0x26,0x12,0x1e,0x42,0x69,0x4b,0x30,0x41,0x2c,0x1b,0x0c,0x03,0x05,0x0e,0x07,0x57,0x13,0x17,0x01,0x3c,0x2a,0x37,0x20,0x0d,0x30,0x22,0x1d,0x2f,0x26,0x1c, 0x08,0x07,0x1a,0x1b,0x18,0xa0,0x36,0x28,0x21,0x2c,0x1a,0x0b,0x1d,0x13,0x5a,0x17,0x18,0x1f,0x38,0x4b,0x2b,0x17,0x2b,0x1a,0x98,0x57,0x57,0x07,0x92,0x18,0x2f,0x0b,0x10,0x18,0x02,0x27,0x5f,0x53,0x38,0x22,0x3a,0x50,0x2d,0x3a,0x40,0x1e,0x06,0x01,0x04,0x09,0x08,0x01,0x16,0x2b,0x11,0x33,0x63,0x33,0x2f,0x58,0x02,0x0e,0x1b,0x1a, 0x39,0x33,0x1f,0x33,0x3f,0x1f,0x01,0x83,0x11,0x17,0x28,0x38,0x20,0x3f,0x74,0x37,0x39,0x7f,0x34,0x3c,0x5b,0x3e,0x20,0x09,0x0a,0x02,0x33,0x56,0x00,0x01,0xff,0xc4,0x06,0x71,0x02,0x22,0x07,0xb0,0x00,0x2a,0x00,0x31,0xb9,0x00,0x01,0x05,0x0d,0xb2,0x29,0x0c,0x1e,0xb8,0x05,0x0d,0xb5,0x1d,0x1e,0x18,0x15,0x15,0x24,0xb8,0x05,0x01, 0xb5,0x06,0x14,0x14,0x11,0x06,0x00,0x00,0x2f,0x2f,0x33,0x33,0x2f,0x10,0xed,0x32,0x2f,0x32,0x2f,0x01,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x27,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x02, 0x22,0x1b,0x2b,0x38,0x1d,0x26,0x33,0x20,0x10,0x03,0x04,0x0b,0x22,0x35,0x4d,0x34,0x10,0x21,0x13,0x0c,0x17,0x2a,0x13,0x3f,0x4f,0x2d,0x10,0x59,0x04,0x0f,0x1c,0x18,0x10,0x1a,0x12,0x0a,0x07,0xb0,0xa7,0x2d,0x3b,0x23,0x0d,0x11,0x1f,0x2b,0x1a,0x19,0x2b,0x1f,0x12,0x02,0x02,0x66,0x02,0x02,0x15,0x29,0x3a,0x25,0x35,0x1b,0x28,0x19, 0x0c,0x06,0x11,0x1e,0x17,0x8d,0x00,0x01,0x00,0xc4,0xfd,0xf6,0x01,0x42,0xff,0x7e,0x00,0x03,0x00,0x15,0xbd,0x00,0x00,0x05,0x0b,0x00,0x01,0x00,0x00,0x04,0xfe,0x00,0x03,0x00,0x2f,0xed,0x01,0x10,0xed,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x42,0x7e,0x7e,0xfd,0xf6,0x01,0x88,0x00,0x00,0x02,0xff,0xbf,0x06,0x73,0x01,0xca,0x08,0x2c, 0x00,0x23,0x00,0x2f,0x00,0x35,0xb2,0x03,0x10,0x06,0xb8,0x05,0x0d,0xb5,0x24,0x00,0x00,0x24,0x14,0x2a,0xb8,0x05,0x0d,0xb3,0x10,0x03,0x23,0x1e,0xbc,0x04,0xfd,0x00,0x17,0x00,0x2d,0x04,0xfd,0x00,0x0b,0x00,0x2f,0xfd,0xd4,0xed,0x32,0x39,0x01,0x2f,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x31,0x30,0x01,0x06,0x06,0x07,0x16, 0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x27,0x26,0x22,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x37,0x13,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x71,0x09,0x14,0x0b,0x39,0x48,0x1d,0x31,0x3e,0x21,0x26,0x3e,0x2c,0x18,0x17,0x1a,0x01,0x06,0x07,0x01,0x38,0x5c, 0x32,0x12,0x30,0x66,0x3c,0x14,0x30,0x17,0x23,0x2d,0x39,0x3c,0x34,0x1d,0x1c,0x29,0x29,0x21,0x36,0x07,0xef,0x08,0x10,0x0b,0x1a,0x59,0x42,0x2a,0x3d,0x29,0x14,0x19,0x2b,0x3b,0x21,0x20,0x46,0x21,0x02,0x01,0x0f,0x0d,0x53,0x0e,0x0e,0x03,0x05,0x22,0x22,0xfe,0xec,0x2a,0x3a,0x10,0x1a,0x3d,0x1c,0x21,0x2d,0x23,0x00,0x01,0x00,0x32, 0x06,0x71,0x01,0xd4,0x07,0xe3,0x00,0x1c,0x00,0x29,0xb2,0x11,0x11,0x13,0xb8,0x05,0x0d,0xb3,0x0d,0x0d,0x1d,0x03,0xb8,0x05,0x0d,0xb3,0x19,0x1c,0x11,0x16,0xb9,0x05,0x01,0x00,0x08,0x00,0x2f,0xfd,0xc6,0xc6,0x01,0x2f,0xed,0x11,0x33,0x2f,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34, 0x36,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x01,0xc7,0x07,0x06,0x16,0x35,0x56,0x40,0x37,0x4a,0x2d,0x13,0x06,0x05,0x58,0x09,0x30,0x3c,0x46,0x3c,0x07,0x06,0x07,0xe3,0x23,0x43,0x1f,0x37,0x58,0x3d,0x21,0x1a,0x32,0x46,0x2c,0x18,0x35,0x1e,0x3b,0x29,0x36,0x29,0x40,0x4f,0x1a,0x3d,0x26,0x00,0xff,0xff, 0xff,0xc6,0x06,0x7c,0x02,0x2c,0x08,0xde,0x01,0x07,0x0f,0x57,0x00,0x00,0x06,0x7c,0x00,0x15,0x40,0x0c,0x01,0x00,0x20,0x00,0x01,0x20,0x00,0x01,0x20,0x00,0x01,0x00,0x00,0x11,0x5d,0x5d,0x5d,0x35,0x35,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x03,0x4a,0x06,0x05,0x02,0x26,0x09,0x15,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0xab,0xfe,0x29, 0x00,0x0a,0xb4,0x01,0x2f,0x20,0x01,0x20,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x06,0x05,0x02,0x26,0x0e,0x2f,0x00,0x00,0x01,0x07,0x0a,0x6e,0x01,0x1d,0xfe,0x29,0x00,0x0a,0xb4,0x01,0x2f,0x2b,0x01,0x2b,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0xc2,0x04,0xaf,0x02,0x26,0x09,0x17,0x00,0x00, 0x00,0x07,0x0a,0x6e,0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x04,0xaf,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0a,0x6e,0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0x53,0xff,0xf2,0x05,0x32,0x06,0x40,0x02,0x26,0x0e,0x5c,0x00,0x00,0x00,0x07,0x0a,0x6e,0x02,0x01,0xfe,0x64,0xff,0xff,0x00,0x67,0xfd,0xff,0x05,0x58, 0x05,0xaa,0x02,0x26,0x08,0xf2,0x00,0x00,0x01,0x07,0x0a,0x6e,0x02,0x73,0xfd,0xce,0x00,0x0a,0xb4,0x03,0x2f,0x56,0x01,0x56,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x87,0x06,0x40,0x02,0x26,0x0e,0x5b,0x00,0x00,0x01,0x07,0x0a,0x6e,0x01,0x56,0xfe,0x64,0x00,0x0a,0xb4,0x03,0x2f,0x57,0x01,0x57,0x00,0x11,0x5d,0x35, 0xff,0xff,0xff,0xba,0xfd,0xff,0x04,0x02,0x05,0xaa,0x02,0x26,0x0e,0x5d,0x00,0x00,0x01,0x07,0x0a,0x6e,0x01,0x1d,0xfd,0xce,0x00,0x0a,0xb4,0x03,0x2f,0x4d,0x01,0x4d,0x00,0x11,0x5d,0x35,0x00,0x06,0xfe,0x93,0xfe,0x64,0x01,0x6d,0xff,0xa4,0x00,0x08,0x00,0x11,0x00,0x15,0x00,0x1f,0x00,0x29,0x00,0x32,0x00,0x57,0xbc,0x00,0x20,0x05, 0x0a,0x00,0x25,0x00,0x2f,0x05,0x0a,0xb2,0x2a,0x2a,0x16,0xbb,0x05,0x0a,0x00,0x1a,0x00,0x12,0x05,0x0d,0xb2,0x13,0x09,0x00,0xb8,0x05,0x0a,0xb3,0x0e,0x04,0x31,0x10,0xb8,0x04,0xfc,0xb5,0x2c,0x12,0x0b,0x23,0x18,0x02,0xb8,0x04,0xfc,0xb6,0x27,0x1d,0x14,0x2f,0x07,0x01,0x07,0x00,0x2f,0x5d,0x33,0x33,0x33,0xed,0x32,0x32,0xd4,0x32, 0x32,0xed,0x32,0x01,0x2f,0x33,0xed,0x32,0x2f,0xed,0x2f,0xed,0x39,0x2f,0xed,0x2f,0xed,0x31,0x30,0x05,0x14,0x23,0x22,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x23,0x22,0x26,0x35,0x34,0x33,0x32,0x07,0x23,0x11,0x33,0x07,0x14,0x23,0x22,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x14,0x06,0x23,0x22,0x35,0x34,0x33,0x32,0x16,0x17,0x14,0x23, 0x22,0x26,0x35,0x34,0x33,0x32,0x01,0x6d,0x41,0x44,0x28,0x1c,0x41,0x41,0x1c,0x28,0x44,0x41,0xe4,0x5c,0x5c,0xbb,0x43,0x44,0x28,0x1c,0x1c,0x27,0xb6,0x28,0x1b,0x42,0x42,0x1c,0x27,0x5a,0x41,0x1c,0x28,0x44,0x41,0xa0,0x41,0x41,0x1c,0x28,0xfc,0x44,0x28,0x1c,0x41,0x85,0x01,0x40,0x44,0x41,0x41,0x1c,0x28,0x28,0x1c,0x1b,0x26,0x41, 0x44,0x28,0xd4,0x44,0x28,0x1c,0x41,0x00,0x00,0x04,0xfe,0xa9,0xfe,0x64,0x01,0x54,0xff,0xa4,0x00,0x08,0x00,0x11,0x00,0x15,0x00,0x19,0x00,0x47,0xbc,0x00,0x16,0x05,0x0c,0x00,0x17,0x00,0x12,0x05,0x0d,0xb2,0x13,0x09,0x00,0xb8,0x05,0x0a,0xb3,0x0e,0x04,0x12,0x0b,0xbb,0x04,0xfc,0x00,0x10,0x00,0x02,0x04,0xfc,0xb4,0x07,0x15,0x07, 0x07,0x16,0xb8,0x04,0xfd,0xb4,0x14,0x2f,0x19,0x01,0x19,0x00,0x2f,0x5d,0x33,0xed,0x33,0x11,0x33,0x10,0xfd,0xd6,0xed,0x32,0x01,0x2f,0x33,0xed,0x32,0x2f,0xed,0x2f,0xed,0x31,0x30,0x05,0x14,0x23,0x22,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x23,0x22,0x26,0x35,0x34,0x33,0x32,0x07,0x23,0x11,0x33,0x07,0x21,0x35,0x21,0x01,0x54,0x41, 0x44,0x28,0x1c,0x41,0x41,0x1c,0x28,0x44,0x41,0xe4,0x5c,0x5c,0xbb,0xfe,0xf4,0x01,0x0c,0xa0,0x41,0x41,0x1c,0x28,0xfc,0x44,0x28,0x1c,0x41,0x85,0x01,0x40,0x52,0x52,0x00,0x04,0xfe,0x91,0xfe,0x64,0x01,0x71,0xff,0xa4,0x00,0x08,0x00,0x11,0x00,0x15,0x00,0x1d,0x00,0x59,0xb9,0x00,0x18,0x05,0x0d,0xb4,0x19,0x19,0x1e,0x1b,0x12,0xb8, 0x05,0x0d,0xb2,0x13,0x09,0x00,0xb8,0x05,0x0a,0xb3,0x0e,0x04,0x1a,0x16,0xb8,0x04,0xfd,0xb2,0x1d,0x15,0x02,0xb8,0x04,0xfc,0xb2,0x07,0x07,0x18,0xb8,0x04,0xfe,0xb6,0x14,0x2f,0x1d,0x01,0x1d,0x12,0x0b,0xb8,0x04,0xfc,0xb3,0x2f,0x10,0x01,0x10,0x00,0x2f,0x5d,0xed,0x32,0x2f,0x5d,0x33,0xe4,0x33,0x10,0xed,0x33,0x10,0xed,0x32,0x01, 0x2f,0x33,0xed,0x32,0x2f,0xed,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x14,0x23,0x22,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x23,0x22,0x26,0x35,0x34,0x33,0x32,0x07,0x23,0x11,0x33,0x07,0x23,0x15,0x23,0x35,0x23,0x35,0x21,0x01,0x71,0x41,0x44,0x28,0x1c,0x41,0x41,0x1c,0x28,0x44,0x41,0xe4,0x5c,0x5c,0xba,0x73,0x5c,0x73,0x01,0x42, 0xa0,0x41,0x41,0x1c,0x28,0xfc,0x44,0x28,0x1c,0x41,0x85,0x01,0x40,0x54,0x85,0x85,0x54,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x08,0x0e,0x02,0x26,0x09,0x3f,0x00,0x00,0x00,0x07,0x0a,0x6d,0x00,0x9c,0x00,0x32,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x07,0x67,0x02,0x26,0x09,0x3f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x9c, 0x06,0xb7,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x08,0x7f,0x02,0x26,0x09,0x3f,0x00,0x00,0x01,0x07,0x0f,0x53,0x00,0x9c,0x06,0xb7,0x00,0x0e,0xb6,0x03,0x02,0x01,0x20,0x2a,0x01,0x2a,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x05,0xec,0x02,0x26,0x09,0x3f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x4a, 0xfd,0xce,0xff,0xff,0x00,0xa1,0xff,0xf2,0x09,0x4b,0x08,0x36,0x00,0x26,0x09,0x71,0x00,0x00,0x00,0x07,0x09,0x0d,0x08,0x04,0x00,0x00,0x00,0x05,0x00,0x9b,0xfd,0xff,0x0b,0x15,0x05,0xec,0x00,0x1d,0x00,0x37,0x00,0x52,0x00,0x56,0x00,0x5a,0x00,0xb2,0xb2,0x44,0x1a,0x4a,0xb8,0x05,0x0a,0xb2,0x3f,0x38,0x24,0xba,0x05,0x0a,0x00,0x58, 0x05,0x0a,0xb6,0x21,0x57,0x57,0x21,0x54,0x54,0x53,0x41,0x09,0x05,0x0a,0x00,0x33,0x05,0x0a,0x00,0x30,0x00,0x10,0x05,0x0a,0x00,0x0d,0x00,0x03,0x05,0x0a,0x40,0x17,0x1a,0x3f,0x21,0x30,0x0d,0x1a,0x1a,0x0d,0x30,0x21,0x3f,0x05,0x5c,0x5b,0x5a,0x5a,0x08,0x55,0x55,0x08,0x08,0x59,0x56,0xb8,0x04,0xfb,0x40,0x0b,0x58,0x53,0x53,0x54, 0x54,0x15,0x15,0x57,0x57,0x38,0x3a,0xb8,0x04,0xfb,0x40,0x0b,0x52,0x1f,0x4f,0x2f,0x4f,0x02,0x4f,0x44,0x33,0x32,0x1e,0xba,0x04,0xfb,0x00,0x29,0x05,0x03,0xb2,0x23,0x0e,0x00,0x00,0x2f,0x2f,0x2f,0x3f,0xed,0x2f,0x2f,0x2f,0x2f,0x5d,0x33,0xed,0x32,0x32,0x2f,0x32,0x2f,0x33,0x2f,0x32,0x2f,0x33,0xed,0x32,0x32,0x2f,0x33,0x2f,0x11, 0x33,0x2f,0x11,0x12,0x01,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0xe4,0x33,0x2f,0x11,0x33,0x2f,0x10,0xe4,0xed,0x39,0x10,0xed,0x11,0x39,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x01,0x32,0x36,0x35, 0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x04,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x01,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x25,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x4e,0x0b,0x0b,0x24,0x4e,0x7d,0x59,0x67,0x93,0x5d,0x2b,0x9c,0x38,0x81,0xd4,0x9d, 0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x06,0x96,0x5d,0x5b,0x9c,0x37,0x5f,0x7e,0x47,0x44,0x65,0x48,0x2d,0x1a,0x0a,0x9c,0x09,0x23,0x45,0x01,0x67,0x7c,0x59,0x55,0x74,0x45,0x1e,0x13,0x1f,0x29,0x16,0xa1,0x1a,0x28,0x1c,0x0f,0x44,0x79,0xa7,0x62,0x33,0x6c,0x39,0xfe,0x48,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x01,0xa6,0x48,0x7a,0x37,0x5f,0x84, 0x51,0x24,0x31,0x6e,0xb3,0x81,0x04,0xc4,0xfb,0x28,0x8f,0xe4,0x9f,0x56,0x45,0x7f,0xb7,0x72,0x3f,0x83,0x4b,0xfe,0xeb,0x68,0x70,0x01,0xa6,0xfe,0x53,0x6b,0x90,0x58,0x25,0x21,0x39,0x4c,0x57,0x5e,0x2e,0x04,0x79,0xfb,0xc2,0x40,0x69,0x4b,0x29,0xfe,0x40,0x27,0x3d,0x6c,0x92,0x56,0x4b,0x8e,0x88,0x83,0x3f,0x41,0x8e,0x8f,0x8b,0x3e, 0x8a,0xd4,0x90,0x4a,0x16,0x17,0x79,0xb5,0xb5,0xb5,0x00,0x02,0xff,0xd4,0x05,0x20,0x02,0x33,0x06,0xf2,0x00,0x2f,0x00,0x33,0x00,0x62,0xb2,0x00,0x00,0x03,0xb8,0x05,0x0d,0x40,0x09,0x2c,0x2f,0x2f,0x2c,0x0a,0x1f,0x23,0x23,0x26,0xb8,0x05,0x0d,0xb6,0x1f,0x22,0x22,0x1f,0x16,0x16,0x19,0xb8,0x05,0x0b,0xb7,0x12,0x15,0x15,0x12,0x0a, 0x29,0x06,0x31,0xb8,0x04,0xfd,0xb6,0x32,0x15,0x23,0x23,0x00,0x1c,0x29,0xb8,0x04,0xfd,0xb1,0x0d,0x06,0x00,0x2f,0x33,0xfd,0x32,0xdc,0x32,0x11,0x33,0xde,0xed,0x11,0x12,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15, 0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x25,0x21,0x15,0x21,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11, 0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0xfe,0x36,0x01,0xfc,0xfe,0x04,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0xbc, 0x58,0x00,0x00,0x03,0xff,0xd4,0x05,0x20,0x02,0x33,0x07,0xfd,0x00,0x2f,0x00,0x53,0x00,0x61,0x00,0x85,0xb9,0x00,0x54,0x05,0x0d,0xb3,0x4d,0x00,0x00,0x03,0xb8,0x05,0x0d,0xb4,0x2c,0x2f,0x2f,0x2c,0x43,0xb8,0x05,0x0d,0x40,0x09,0x0a,0x41,0x1f,0x5c,0x5c,0x1f,0x23,0x23,0x26,0xb8,0x05,0x0d,0xb6,0x1f,0x22,0x22,0x1f,0x16,0x16,0x19, 0xb8,0x05,0x0b,0xb4,0x12,0x15,0x15,0x12,0x48,0xb8,0x04,0xfd,0xb3,0x57,0x50,0x5f,0x3d,0xb8,0x04,0xfd,0x40,0x0a,0x36,0x33,0x33,0x36,0x15,0x00,0x23,0x0a,0x0d,0x06,0xb8,0x04,0xfd,0xb1,0x1c,0x29,0x00,0x2f,0x33,0xed,0x32,0x39,0xde,0x32,0x32,0xce,0x32,0x2f,0x10,0xfd,0x32,0x39,0xd4,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f, 0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x12,0x39,0x39,0xed,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0xed,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14, 0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x32,0x37,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14, 0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0x5a,0x17,0x28,0x11,0x18,0x2f,0x14,0x3c,0x65,0x31,0x12,0x33,0x5a,0x39,0x01,0x0b,0x06,0x01,0x34,0x1e,0x31,0x3e,0x21,0x20,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x02,0x33,0x1f,0x0f,0x1f, 0x18,0x0f,0x23,0x1a,0x30,0x3a,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0x1d,0x11,0x22,0x11,0x05,0x03,0x0e,0x0e,0x53,0x0d,0x0f,0x01,0x02,0x40,0x40,0x24,0x39,0x27,0x14,0x14, 0x27,0x3a,0x27,0x3f,0x56,0x19,0x0b,0x10,0x08,0xcd,0x26,0x22,0x09,0x11,0x1a,0x10,0x1a,0x3a,0x1a,0x0e,0x36,0x00,0x00,0x02,0xff,0xd4,0x05,0x28,0x02,0x33,0x06,0xfc,0x00,0x2f,0x00,0x33,0x00,0x63,0xb2,0x00,0x00,0x03,0xb8,0x05,0x0d,0x40,0x09,0x2c,0x2f,0x2f,0x2c,0x0a,0x1f,0x23,0x23,0x26,0xb8,0x05,0x0d,0xb6,0x1f,0x22,0x22,0x1f, 0x16,0x16,0x19,0xb8,0x05,0x0b,0x40,0x0d,0x12,0x15,0x15,0x12,0x0a,0x29,0x06,0x15,0x22,0x22,0x00,0x1c,0x29,0xb8,0x04,0xfd,0xb2,0x0d,0x06,0x31,0xb9,0x04,0xfd,0x00,0x32,0x00,0x2f,0xfd,0xd6,0x32,0xfd,0x32,0xcc,0x32,0x11,0x33,0x11,0x12,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39, 0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x01,0x21,0x15,0x21,0x02,0x2f,0x02,0x02, 0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0xfe,0x36,0x01,0xfc,0xfe,0x04,0x06,0xfc,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12, 0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0xfe,0x84,0x58,0x00,0x00,0x03,0xff,0x6c,0x05,0x20,0x02,0x33,0x07,0xfd,0x00,0x2f,0x00,0x54,0x00,0x62,0x00,0x8b,0xb2,0x16,0x16,0x19,0xb8,0x05,0x0b,0xb7,0x12,0x15,0x15,0x12,0x12,0x63,0x3b,0x55,0xb8,0x05,0x0d,0xb4,0x4e,0x3b,0x00,0x00,0x03,0xb8,0x05,0x0d,0xb4,0x2c, 0x2f,0x2f,0x2c,0x44,0xb8,0x05,0x0d,0x40,0x09,0x0a,0x42,0x1f,0x5d,0x5d,0x1f,0x23,0x23,0x26,0xb8,0x05,0x0d,0x40,0x0a,0x1f,0x22,0x22,0x1f,0x3c,0x60,0x39,0x03,0x36,0x49,0xbb,0x04,0xfd,0x00,0x58,0x00,0x3f,0x04,0xfd,0xb6,0x36,0x16,0x00,0x22,0x0a,0x1c,0x29,0xb8,0x04,0xfd,0xb1,0x0d,0x06,0x00,0x2f,0x33,0xfd,0x32,0x39,0xd4,0x32, 0x32,0xd6,0xfd,0xd4,0xed,0x11,0x17,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x12,0x39,0x39,0xed,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0x2f,0xed,0x11,0x12,0x39,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34, 0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x07,0x27,0x37,0x16,0x16,0x33,0x32,0x37,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37, 0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0x5a,0x17,0x28,0x11,0x19,0x2f,0x15,0x42,0x5e,0x25,0x61,0x36,0x99,0x31,0x5b,0x34, 0x10,0x0f,0x01,0x36,0x1e,0x31,0x3f,0x20,0x20,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x02,0x33,0x1f,0x0f,0x1f,0x18,0x0f,0x23,0x1a,0x2f,0x3b,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14, 0x2c,0x0d,0x1d,0x11,0x22,0x11,0x07,0x06,0x34,0x2a,0x59,0x3b,0x8e,0x3c,0x3e,0x03,0x02,0x42,0x41,0x24,0x38,0x27,0x14,0x14,0x27,0x3a,0x27,0x3f,0x56,0x19,0x0b,0x10,0x08,0xcd,0x26,0x22,0x09,0x11,0x19,0x11,0x1b,0x38,0x1b,0x0e,0x35,0x00,0x00,0x03,0xff,0xd4,0x05,0x28,0x02,0x33,0x07,0xab,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x6b, 0xb2,0x00,0x00,0x03,0xb8,0x05,0x0d,0x40,0x09,0x2c,0x2f,0x2f,0x2c,0x0a,0x1f,0x23,0x23,0x26,0xb8,0x05,0x0d,0xb6,0x1f,0x22,0x22,0x1f,0x16,0x16,0x19,0xb8,0x05,0x0b,0x40,0x0d,0x12,0x15,0x15,0x12,0x0a,0x29,0x06,0x15,0x23,0x23,0x00,0x1c,0x29,0xb8,0x04,0xfd,0xb2,0x0d,0x06,0x31,0xbc,0x04,0xfd,0x00,0x32,0x00,0x35,0x04,0xfd,0x00, 0x36,0x00,0x2f,0xfd,0xd6,0xfd,0xd6,0x32,0xfd,0x32,0xcc,0x32,0x11,0x33,0x11,0x12,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37, 0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x01,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01, 0x22,0x2d,0x30,0x24,0x04,0x02,0xfe,0x36,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04,0x07,0xab,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0xfe,0x84,0x58,0x57,0x58,0x00,0x00,0x04,0x00,0x35, 0xfd,0xf6,0x03,0xf2,0x05,0x28,0x00,0x27,0x00,0x39,0x00,0x3d,0x00,0x41,0x00,0x58,0xbc,0x00,0x14,0x05,0x0a,0x00,0x28,0x00,0x3e,0x05,0x0b,0xb2,0x3f,0x3f,0x3a,0xbb,0x05,0x0c,0x00,0x3b,0x00,0x32,0x05,0x0a,0x40,0x0b,0x05,0x28,0x3b,0x05,0x05,0x3b,0x28,0x03,0x43,0x42,0x3a,0xb8,0x04,0xfb,0xb4,0x3d,0x3f,0x40,0x37,0x24,0xbd,0x04, 0xfb,0x00,0x1b,0x05,0x03,0x00,0x2d,0x04,0xfb,0x00,0x0c,0x00,0x2f,0xed,0x3f,0xed,0x32,0xd6,0xcd,0x2f,0xed,0x11,0x12,0x01,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x31,0x30,0x25,0x2e,0x03,0x35,0x34,0x3e,0x04,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x27,0x27,0x16, 0x16,0x33,0x32,0x36,0x37,0x25,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x03,0x23,0x35,0x33,0x03,0x23,0x11,0x33,0x02,0x4e,0x49,0x60,0x38,0x16,0x15,0x28,0x3a,0x47,0x54,0x2f,0x45,0x75,0x38,0x14,0x26,0x1d,0x11,0x3c,0x64,0x82,0x8e,0x8f,0x3e,0x39,0x52,0x41,0x36,0x1e,0x20,0x51,0x9e,0x47,0x49,0x77, 0x21,0x01,0x09,0x22,0x38,0x4a,0x27,0x1d,0x37,0x2b,0x1b,0x18,0x42,0x73,0x5a,0x21,0x1d,0xab,0xc9,0xc9,0x23,0x7e,0x7e,0x9e,0x1d,0x45,0x4c,0x52,0x2b,0x2e,0x60,0x5b,0x50,0x3d,0x23,0x51,0x58,0x20,0x4a,0x54,0x5d,0x32,0x5e,0x82,0x56,0x30,0x17,0x05,0x02,0x04,0x06,0x04,0xa7,0x0a,0x08,0x07,0x04,0xc6,0x33,0x78,0x66,0x44,0x26,0x3c, 0x4c,0x26,0x20,0x3e,0x44,0x49,0x2a,0x17,0x52,0x03,0x36,0xbd,0xf8,0xce,0x01,0x88,0x00,0x03,0x00,0x65,0xff,0xea,0x03,0x9d,0x03,0x6c,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x3a,0xb9,0x00,0x21,0x05,0x0c,0xb4,0x13,0x1b,0x1b,0x24,0x15,0xbb,0x05,0x0c,0x00,0x0f,0x00,0x09,0x05,0x0c,0xb2,0x03,0x1e,0x12,0xbe,0x04,0xfe,0x00,0x18,0x00, 0x0c,0x05,0x03,0x00,0x00,0x04,0xfe,0x00,0x06,0x00,0x2f,0xed,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0xd4,0xed,0x11,0x33,0x2f,0xc4,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x02,0x00,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0xfd,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0xfd,0x79,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x02,0x8e,0x42,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x42,0xfd,0x5c,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x00,0x01,0xff,0xe7,0x06,0x7c,0x02,0x1f,0x06,0xe8, 0x00,0x03,0x00,0x15,0xb2,0x01,0x00,0x02,0xb8,0x04,0xfd,0xb3,0x2f,0x01,0x01,0x01,0x00,0x2f,0x5d,0xed,0x01,0x2f,0xcd,0x31,0x30,0x03,0x21,0x15,0x21,0x19,0x02,0x38,0xfd,0xc8,0x06,0xe8,0x6c,0x00,0x00,0x01,0xff,0xdf,0x06,0x7c,0x02,0x28,0x07,0xdc,0x00,0x06,0x00,0x15,0xb7,0x03,0x01,0x05,0x01,0x04,0x02,0x03,0x00,0x00,0x2f,0x32, 0xcd,0x32,0x01,0x2f,0x2f,0x12,0x39,0x31,0x30,0x13,0x03,0x33,0x17,0x37,0x33,0x03,0xcb,0xec,0x7d,0xab,0xa8,0x79,0xe6,0x06,0x7c,0x01,0x60,0xff,0xff,0xfe,0xa0,0x00,0x00,0x01,0xff,0xdf,0x06,0x7c,0x02,0x28,0x07,0xdc,0x00,0x06,0x00,0x15,0xb7,0x03,0x01,0x05,0x01,0x03,0x00,0x04,0x02,0x00,0x2f,0x33,0xcd,0x32,0x01,0x2f,0x2f,0x12, 0x39,0x31,0x30,0x01,0x13,0x23,0x27,0x07,0x23,0x13,0x01,0x3c,0xec,0x7d,0xab,0xa8,0x79,0xe6,0x07,0xdc,0xfe,0xa0,0xff,0xff,0x01,0x60,0x00,0x01,0x00,0x97,0xfe,0x92,0x01,0x6e,0xff,0x69,0x00,0x0b,0x00,0x15,0xbd,0x00,0x06,0x05,0x0c,0x00,0x00,0x00,0x09,0x04,0xfe,0x00,0x03,0x00,0x2f,0xed,0x01,0x10,0xed,0x31,0x30,0x13,0x34,0x36, 0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x97,0x3d,0x2f,0x2f,0x3c,0x3c,0x2f,0x2f,0x3d,0xfe,0xfe,0x2f,0x3c,0x3c,0x2f,0x2f,0x3d,0x3d,0x00,0x00,0x02,0x00,0x3d,0x06,0x55,0x02,0x48,0x08,0x0e,0x00,0x23,0x00,0x2f,0x00,0x39,0xb4,0x14,0x2a,0x03,0x06,0x10,0xb8,0x05,0x0d,0xb3,0x2a,0x00,0x00,0x24,0xbb,0x05,0x0d,0x00,0x06,0x00, 0x0b,0x04,0xfd,0xb3,0x2d,0x03,0x27,0x17,0xb8,0x04,0xfd,0xb3,0x20,0x1e,0x01,0x1e,0x00,0x2f,0x5d,0xfd,0x32,0x39,0xd4,0xed,0x01,0x2f,0xed,0x32,0x2f,0x2f,0xed,0x11,0x39,0x11,0x39,0x31,0x30,0x13,0x36,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x17,0x16,0x32,0x33,0x32,0x36,0x37,0x17,0x06, 0x06,0x23,0x22,0x26,0x27,0x06,0x07,0x03,0x14,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x96,0x09,0x14,0x0b,0x39,0x48,0x1d,0x31,0x3e,0x21,0x26,0x3e,0x2c,0x18,0x17,0x1a,0x01,0x06,0x07,0x01,0x38,0x5c,0x32,0x12,0x30,0x66,0x3c,0x14,0x30,0x17,0x23,0x2d,0x39,0x3c,0x34,0x1d,0x1c,0x29,0x29,0x21,0x36,0x06,0x92,0x08,0x10, 0x0b,0x1a,0x59,0x42,0x2a,0x3d,0x29,0x14,0x19,0x2b,0x3b,0x21,0x20,0x46,0x21,0x02,0x01,0x0f,0x0d,0x53,0x0e,0x0e,0x03,0x05,0x22,0x22,0x01,0x14,0x2a,0x3a,0x10,0x1a,0x3d,0x1c,0x21,0x2d,0x23,0x00,0x00,0x03,0x00,0x05,0x06,0x67,0x02,0x01,0x08,0x31,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x34,0xb9,0x00,0x08,0x05,0x0a,0xb3,0x00,0x09, 0x01,0x04,0xb8,0x05,0x0a,0x40,0x0f,0x05,0x02,0x01,0x03,0x00,0x01,0x00,0x04,0x0b,0x08,0x07,0x20,0x04,0x01,0x04,0x00,0x2f,0x5d,0xdd,0xd4,0xcd,0x11,0x39,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0x32,0x2f,0x33,0xed,0x31,0x30,0x13,0x01,0x15,0x01,0x25,0x23,0x35,0x33,0x25,0x23,0x35,0x33,0x05,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xa1, 0xa1,0xfe,0xa5,0xa1,0xa1,0x06,0xd3,0x01,0x5e,0x6c,0xfe,0xa2,0x01,0x9d,0x8f,0x9d,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x55,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x22,0x03,0x0f,0x00,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x55,0x00,0x83,0xfe,0xab, 0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x05,0xca,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x27,0x0f,0x53,0x02,0xad,0x04,0x02,0x00,0x07,0x0f,0x50,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x9a,0x05,0xca,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x53,0x00,0x9c,0x04,0x02,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab, 0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x81,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0x9f,0x04,0xb2,0x02,0x26,0x09,0x3e,0x00,0x00, 0x00,0x27,0x0f,0x53,0x02,0xad,0xfd,0xce,0x00,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x9a,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x53,0x00,0x83,0xfd,0xce,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x04,0xb2,0x02,0x26,0x09,0x3e,0x00,0x00, 0x00,0x27,0x0f,0x51,0x02,0xad,0xfe,0xab,0x00,0x07,0x0f,0x50,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x81,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x83,0xfe,0xab,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfe,0x13,0x06,0x9f,0x03,0x0f,0x02,0x26,0x09,0x3e,0x00,0x00, 0x01,0x07,0x0a,0x6e,0x02,0xad,0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x2a,0x01,0x2a,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0x13,0x02,0xab,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0x83,0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f, 0x05,0x5a,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0xad,0xfd,0x7e,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x05,0x5a,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0a,0x6d,0x00,0x9c,0xfd,0x7e,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x04,0xda,0x02,0x26,0x09,0x13,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x04,0x2a, 0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x04,0xda,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x04,0x2a,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x7c,0x04,0x61,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x03,0xb1,0x00,0x04,0x00,0x7e,0xfd,0xff,0x04,0x41,0x03,0x54,0x00,0x31,0x00,0x35,0x00,0x39, 0x00,0x3d,0x00,0x75,0xb9,0x00,0x3a,0x05,0x0a,0xb2,0x3b,0x3b,0x33,0xb8,0x05,0x0a,0xb3,0x32,0x1d,0x32,0x37,0xb8,0x05,0x0a,0xb7,0x36,0x32,0x36,0x32,0x36,0x3f,0x26,0x05,0xbb,0x05,0x0a,0x00,0x16,0x00,0x3c,0x04,0xfb,0xb5,0x2f,0x3b,0x01,0x3b,0x38,0x34,0xbb,0x04,0xfb,0x00,0x36,0x00,0x33,0x04,0xe6,0xb5,0x00,0x1d,0x31,0x03,0x11, 0x23,0xb8,0x04,0xff,0xb2,0x2a,0x0d,0x0a,0xb8,0x04,0xfc,0xb6,0x0e,0x1f,0x11,0x2f,0x11,0x02,0x11,0x00,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x3f,0x33,0xed,0x32,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x06,0x04,0x06,0x06,0x15,0x14, 0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x01,0x33,0x15,0x23,0x25,0x33,0x15,0x23,0x13,0x33,0x15,0x23,0x04,0x0c,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7, 0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe,0xf7,0xb5,0xb5,0xfe,0xbe,0xb5,0xb5,0xa1,0xb5,0xb5,0x02,0x01,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a, 0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfd,0x44,0xb3,0xb3,0xb3,0x01,0xc1,0xb3,0x00,0x05,0x00,0x7e,0xfd,0xff,0x05,0x58,0x03,0x54,0x00,0x0d,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x8b,0xb1,0x2b,0x40,0xbb,0x05,0x0a,0x00,0x1b,0x00,0x00,0x05,0x0b,0xb4,0x0b,0x41,0x41,0x0b,0x49, 0xb8,0x05,0x0a,0xb2,0x48,0x48,0x45,0xb8,0x05,0x0a,0xb7,0x44,0x0b,0x44,0x0b,0x44,0x4d,0x34,0x13,0xbb,0x05,0x0a,0x00,0x24,0x00,0x4a,0x04,0xfb,0xb5,0x2f,0x49,0x01,0x49,0x46,0x42,0xbb,0x04,0xfb,0x00,0x44,0x00,0x41,0x04,0xe6,0xb5,0x0e,0x2b,0x3f,0x03,0x1f,0x31,0xb8,0x04,0xff,0xb2,0x38,0x1b,0x18,0xb8,0x04,0xfc,0xb7,0x1c,0x1f, 0x1f,0x2f,0x1f,0x02,0x1f,0x03,0xba,0x04,0xfb,0x00,0x05,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x3f,0x33,0xed,0x32,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0xed,0x11,0x33,0x2f,0x10,0xed,0x39,0xe6,0x32,0x31,0x30,0x01,0x16,0x16,0x33,0x33,0x15,0x23, 0x22,0x2e,0x02,0x27,0x36,0x36,0x27,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x01,0x33,0x15,0x23,0x25,0x33,0x15,0x23,0x13,0x33,0x15,0x23,0x04,0x57,0x06,0x74,0x68,0x1f, 0x37,0x4f,0x77,0x52,0x2c,0x04,0x1f,0x3f,0x2b,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe,0xf7,0xb5,0xb5,0xfe,0xbe,0xb5,0xb5,0xa1,0xb5,0xb5,0x01, 0x56,0x68,0x55,0xa7,0x30,0x56,0x74,0x44,0x0b,0x13,0xb3,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfd,0x44,0xb3,0xb3,0xb3,0x01,0xc1,0xb3,0xff,0xff,0xff,0xba, 0xfd,0xc9,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x52,0xfd,0xc9,0x03,0x4a,0x07,0x0f,0x02,0x26,0x09,0x15,0x00,0x00,0x00,0x27,0x0f,0x52,0x00,0xab,0xfd,0xce,0x00,0x07,0x0f,0x57,0x00,0xab,0x04,0xad,0xff,0xff,0x00,0x52,0xfe,0x13,0x03,0x4a,0x03,0xba,0x02,0x26, 0x09,0x15,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0xab,0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x20,0x01,0x20,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x4e,0x02,0x5e,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x5c,0x00,0xc0,0xfc,0xfa,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x05,0x1f,0x02,0x26,0x09,0x19,0x00,0x00, 0x00,0x07,0x0f,0x56,0x05,0x46,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4,0x05,0x1f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x07,0x0f,0x56,0x02,0xa4,0x03,0x57,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x05,0xa3,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xe4,0x04,0xf3,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad, 0x05,0x20,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x04,0x70,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x3c,0x04,0xe4,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x1d,0x04,0x34,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x04,0xb2,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x04,0x02, 0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x06,0xbb,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xe4,0x04,0xf3,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad,0x06,0x38,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x56,0x04,0x70,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x3c,0x05,0xfc,0x02,0x26,0x08,0xe2,0x00,0x00, 0x00,0x07,0x0f,0x54,0x01,0x1d,0x04,0x34,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0xca,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x56,0x04,0x02,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x06,0xbb,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0xe4,0x04,0xf3,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad, 0x06,0x38,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x04,0x70,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x3c,0x05,0xfc,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x1d,0x04,0x34,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0xca,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x04,0x02, 0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x4b,0x03,0x62,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x51,0x05,0x10,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x49,0x03,0x62,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x0e,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x03,0x62,0x02,0x26,0x09,0x3d,0x00,0x00, 0x00,0x07,0x0f,0x51,0x01,0x0e,0xfe,0xab,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x4b,0x03,0x62,0x02,0x26,0x09,0xc8,0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0x10,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x49,0x03,0x62,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x0e,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02, 0x03,0x62,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x0e,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x06,0xb3,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x90,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0xb3,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x39,0x06,0x03, 0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0xb3,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x07,0xcb,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x90,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x07,0xcb,0x02,0x26,0x08,0xed,0x00,0x00, 0x00,0x07,0x0f,0x53,0x00,0x39,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x07,0xcb,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0xa2,0x06,0x02,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x4b, 0x06,0x02,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xab,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02,0x06,0x02,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xab,0xfd,0xce,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0xf4,0x04,0x79,0x02,0x26,0x09,0x26,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0x03,0xc9, 0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0xf4,0x04,0x79,0x02,0x26,0x08,0xef,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0x03,0xc9,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0xf4,0x02,0xb9,0x02,0x26,0x09,0x26,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0xf4,0x02,0xaf,0x02,0x26,0x08,0xef,0x00,0x00, 0x00,0x07,0x0f,0x50,0x01,0x8f,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xfb,0x04,0xa6,0x04,0xb2,0x02,0x27,0x09,0x5f,0x00,0x00,0x01,0x56,0x00,0x27,0x0f,0x50,0x01,0x9f,0x04,0x02,0x00,0x07,0x0f,0x51,0x01,0x9f,0xfe,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x48,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a, 0xfe,0xab,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x06,0x64,0x02,0x26,0x09,0x5f,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x9f,0x02,0xac,0x00,0x07,0x0f,0x57,0x01,0x9f,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9e,0x07,0xba,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c, 0x04,0x02,0x01,0x07,0x0f,0x57,0x00,0x72,0x05,0x58,0x00,0x0a,0xb4,0x01,0x20,0x18,0x01,0x18,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x05,0x63,0x02,0x26,0x09,0x5f,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x9f,0x02,0xac,0x01,0x07,0x0a,0x6d,0x01,0x9f,0xfd,0x87,0x00,0x0a,0xb4,0x01,0x20,0x22,0x01,0x22,0x00,0x11, 0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x06,0xb9,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c,0x04,0x02,0x01,0x07,0x0a,0x6d,0x00,0x9c,0xfe,0xdd,0x00,0x13,0x40,0x0a,0x02,0x2f,0x1c,0x01,0x1c,0x01,0x20,0x19,0x01,0x19,0x00,0x11,0x5d,0x35,0x11,0x5d,0x35,0x00,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x51, 0x05,0xec,0x02,0x26,0x09,0x25,0x00,0x00,0x00,0x07,0x0f,0x5c,0x02,0xc3,0x00,0x00,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x58,0x05,0xec,0x02,0x26,0x09,0x59,0x00,0x00,0x00,0x07,0x0f,0x5c,0x02,0xc3,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xa5,0x05,0xec,0x02,0x26,0x08,0xee,0x00,0x00,0x00,0x06,0x0f,0x5c,0x17,0x00,0xff,0xff, 0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xec,0x02,0x26,0x09,0x3f,0x00,0x00,0x00,0x06,0x0f,0x5c,0x17,0x00,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0x9e,0x05,0x1f,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0x9e,0x04,0xbc,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x07,0x09,0x7e, 0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x05,0x1f,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x07,0x0f,0x52,0x05,0x46,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4,0x05,0x1f,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x07,0x0f,0x52,0x02,0xa4,0x03,0x57,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x84,0x05,0x76,0x02,0x06, 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xa6,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8c,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x5c,0x02,0x18,0x00,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0xad,0x05,0xec,0x00,0x26,0x0f,0x65,0x00,0x00,0x00,0x27,0x0f,0x8d,0x02,0xac,0x00,0x00,0x00,0x07,0x0f,0x5c, 0x02,0x18,0x00,0x00,0x00,0x01,0xff,0x1a,0xfe,0x96,0x00,0xe6,0x00,0x00,0x00,0x0a,0x00,0x15,0x40,0x09,0x03,0x91,0x08,0x00,0x05,0x05,0x01,0x7e,0x00,0x2f,0xf1,0xc2,0x2f,0x00,0x2f,0xd4,0xed,0x31,0x30,0x23,0x33,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0xe6,0xa8,0xb2,0x3f,0x33,0x38,0x42,0x9f,0xb3,0xd3,0x1d,0xa0,0x14,0xc5, 0x00,0x01,0xff,0x1a,0xfe,0x96,0x00,0xe6,0x00,0x35,0x00,0x0a,0x00,0x12,0xb7,0x08,0x91,0x03,0x0a,0x00,0x7e,0x0a,0x06,0x2f,0xd6,0xe1,0x00,0x2f,0xd4,0xed,0x31,0x30,0x37,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0xe6,0xb3,0x9f,0x42,0x38,0x33,0x3f,0xb2,0x35,0xbd,0xe2,0x14,0xa0,0x1d,0x01,0x08,0x00,0x00,0x01,0x01,0x9f, 0xfe,0x80,0x02,0x60,0x00,0x98,0x00,0x05,0x00,0x18,0xb9,0x00,0x01,0x01,0x2c,0xb5,0x04,0x00,0x91,0x05,0x22,0x03,0xb8,0x01,0x30,0x00,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x31,0x30,0x25,0x33,0x11,0x23,0x11,0x23,0x01,0x9f,0xc1,0x9b,0x26,0x98,0xfd,0xe8,0x01,0x80,0x00,0x01,0x01,0xb3,0xfe,0x8a,0x02,0x4d,0x00,0x8b,0x00,0x05,0x00,0x18, 0xb9,0x00,0x01,0x01,0x2c,0xb5,0x04,0x00,0x95,0x05,0x22,0x03,0xb8,0x01,0x31,0x00,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x31,0x30,0x25,0x33,0x11,0x23,0x11,0x23,0x01,0xb3,0x9a,0x8f,0x0b,0x8b,0xfd,0xff,0x01,0x76,0x00,0x01,0x00,0x14,0x00,0x8b,0x02,0xe8,0x05,0x30,0x00,0x1d,0x00,0x30,0x40,0x17,0x17,0xb1,0x0c,0x00,0xb1,0x05,0x0c,0x05, 0x0c,0x05,0x04,0x01,0x01,0x1f,0x11,0x04,0x0f,0xbe,0x14,0x00,0x04,0xbe,0x03,0x00,0x2f,0xed,0x32,0x2f,0xed,0x01,0x2f,0x33,0x11,0x33,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x21,0x15,0x21,0x35,0x33,0x34,0x37,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x07,0x06,0x07,0x06,0x01,0x89,0x01,0x2f,0xfd,0x5c,0xd2,0x26,0x26,0x6e,0x6a,0x38,0x97,0x7e,0x8f,0x82,0x84,0x9c,0xc2,0xea,0x4f,0x81,0x50,0x20,0x1f,0x01,0x20,0x95,0x95,0x84,0x50,0x51,0x6c,0x69,0x6e,0x3e,0x5f,0x80,0x4c,0x97,0x40,0xc8,0x98,0x5b,0x9f,0x7b,0x4d,0x42,0x40,0x00,0x00,0x03,0x00,0x1c,0x00,0x00,0x04,0x2f,0x05,0x9a, 0x00,0x13,0x00,0x1f,0x00,0x27,0x00,0x84,0x40,0x0b,0x0c,0x19,0x10,0x06,0x0b,0x0d,0x06,0x4c,0x10,0x7d,0x1d,0xb8,0xff,0xf0,0x40,0x42,0x0b,0x0d,0x06,0x4c,0x1d,0x1d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x7d,0x25,0x08,0x0b,0x0c,0x06,0x4c,0x7f,0x25,0x01,0x25,0x25,0x29,0x00,0x29,0x40,0x0b,0x00,0x4d,0x21,0x17,0x17,0x15,0x19,0x7e,0x00, 0x04,0x00,0x02,0x02,0x00,0x0c,0x14,0x91,0x21,0x18,0x01,0x91,0x04,0x15,0x04,0x21,0x04,0x21,0x04,0x19,0x20,0x91,0x05,0x03,0x19,0x91,0x00,0x12,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x39,0x01,0x2f,0x33,0x2f,0x11,0x33,0x10,0xed,0x32,0x32,0x2f,0x32,0x2b,0x11,0x12,0x39,0x2f,0x5d, 0x2b,0xe9,0x2b,0x39,0x2f,0x2b,0xe9,0x2b,0x11,0x39,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x04,0x23,0x03,0x15,0x33,0x15,0x23,0x15,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0xbc,0xa0,0xa0,0x01,0x98,0xba,0xda,0x84,0x74,0x91,0xae,0xfe, 0xf8,0xc9,0xfa,0xfc,0xfc,0xe4,0x94,0xa3,0xfe,0xa6,0xc1,0xac,0x8a,0x9e,0xfe,0xed,0x01,0x4f,0x98,0x03,0xb3,0xb6,0x92,0x7a,0xb4,0x26,0x04,0x11,0xb9,0x94,0xb8,0xe4,0x02,0x9c,0xb5,0x98,0xb7,0x8c,0x7a,0xfe,0x02,0x66,0xfe,0x31,0x85,0x79,0xd1,0x00,0x00,0x02,0x00,0x1e,0xff,0xe8,0x05,0x61,0x05,0x9a,0x00,0x12,0x00,0x19,0x00,0x41, 0x40,0x21,0x12,0x10,0x10,0x0e,0x7e,0x16,0x0d,0x0d,0x1b,0x17,0x0a,0x7e,0x09,0x07,0x07,0x05,0x09,0x0d,0x03,0x17,0x12,0x06,0x91,0x0f,0x0b,0x07,0x07,0x09,0x03,0x13,0x91,0x02,0x12,0x00,0x3f,0xed,0x3f,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x3f,0x01,0x2f,0x33,0x33,0x2f,0x10,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x2f,0x32,0x31, 0x30,0x01,0x10,0x21,0x20,0x11,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x15,0x23,0x01,0x20,0x11,0x35,0x21,0x15,0x10,0x04,0xd5,0xfd,0xdf,0xfd,0xf6,0x8c,0x8c,0xa8,0x02,0xdb,0xa8,0x8c,0x8c,0xfd,0xf1,0x01,0x67,0xfd,0x25,0x02,0x44,0xfd,0xa4,0x02,0x45,0x57,0x98,0x02,0x7e,0xfd,0x82,0x02,0x7e,0xfd,0x82,0x98, 0xfd,0xfb,0x01,0xaa,0x5b,0x4c,0xfe,0x47,0xff,0xff,0x00,0x18,0x00,0x00,0x04,0xef,0x05,0x9a,0x00,0x06,0x01,0xb0,0x00,0x00,0xff,0xff,0x00,0x8b,0xff,0x70,0x03,0xb4,0x05,0xf8,0x02,0x26,0x00,0x28,0x00,0x00,0x01,0x07,0x04,0x96,0x02,0x1b,0x00,0x5e,0x00,0x1b,0x40,0x14,0x20,0x0e,0x30,0x0e,0x02,0x20,0x0d,0x30,0x0d,0x02,0x0f,0x0f, 0x1f,0x0f,0x02,0x0f,0x0c,0x1f,0x0c,0x02,0x00,0x5d,0x5d,0x5d,0x5d,0x00,0xff,0xff,0x00,0x60,0xfe,0xb5,0x03,0xdd,0x05,0x3d,0x02,0x26,0x00,0x48,0x00,0x00,0x01,0x07,0x04,0x96,0x02,0x3a,0xff,0xa3,0x00,0x0a,0xb4,0x02,0x4f,0x1c,0x01,0x1c,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0x14,0xff,0xe8,0x02,0xbd,0x05,0x9a,0x00,0x14,0x00,0x75, 0x40,0x0d,0x79,0x09,0x01,0x76,0x09,0x01,0x76,0x01,0x01,0x13,0x13,0x11,0x05,0xb8,0xff,0xf0,0x40,0x18,0x0d,0x06,0x4d,0x05,0x05,0x00,0x08,0x0b,0x0d,0x06,0x4c,0x00,0x7e,0x0a,0x0e,0x0a,0x0c,0x0c,0x0a,0x18,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xf6,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xfa,0x40,0x15,0x0b,0x06,0x4d,0x0a,0x0a,0x16,0x15, 0x14,0x0c,0x91,0x11,0x0d,0x0d,0x0f,0x03,0x06,0x06,0x08,0x91,0x03,0x13,0x00,0x3f,0xed,0x32,0x2f,0x3f,0x39,0x2f,0x33,0xed,0x32,0x11,0x12,0x01,0x39,0x2f,0x2b,0x2b,0x2b,0x33,0x2f,0x11,0x33,0x10,0xe9,0x2b,0x32,0x2f,0x2b,0x32,0x32,0x2f,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x01,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11, 0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x02,0x2b,0xd8,0xb5,0x54,0x36,0x36,0x56,0xe3,0xd8,0xd8,0xa8,0x92,0x92,0x02,0x02,0xff,0xfe,0xe5,0x18,0xa6,0x27,0x01,0x81,0x81,0x98,0x02,0x81,0xfd,0x7f,0x98,0x00,0x00,0x02,0xff,0x3a,0xfe,0x1e,0x01,0xd4,0x05,0xd9,0x00,0x14,0x00,0x20,0x00,0x7a,0x40,0x28,0x1e,0x62,0x18,0x0a, 0x00,0x18,0x62,0xff,0x30,0x06,0x0a,0x12,0x12,0x11,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x0a,0x0e,0x0a,0x0c,0x0c,0x7f,0x0a,0x01,0x0a,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x0a,0xb8,0xff,0xfe,0x40,0x19,0x0b,0x06,0x4d,0x0a,0x0a,0x22,0x21,0x1b,0x63,0x15,0x0f,0x14,0x0c,0x95,0x11, 0x0d,0x0d,0x0f,0x0f,0x06,0x06,0x08,0x95,0x03,0x1c,0x00,0x3f,0xed,0x32,0x2f,0x3f,0x39,0x2f,0x33,0xed,0x32,0x10,0xde,0xed,0x11,0x12,0x01,0x39,0x2f,0x2b,0x2b,0x5d,0x33,0x2f,0x11,0x33,0x10,0xe1,0x2b,0x2b,0x2b,0x32,0x32,0x2f,0x10,0xc6,0x2b,0x01,0x10,0xe1,0x31,0x30,0x25,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11, 0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x4a,0xcb,0xbd,0x46,0x42,0x4a,0x42,0xe0,0x8a,0x8a,0xa4,0x8a,0x8a,0x50,0x2c,0x3e,0x3e,0x2c,0x2d,0x3f,0x3f,0x2b,0xfc,0xfe,0xef,0x20,0x99,0x2d,0x01,0x66,0x01,0x9d,0x87,0x01,0xcc,0xfe,0x34,0x87,0x03,0x57,0x3c,0x2e, 0x2e,0x3d,0x3d,0x2e,0x2c,0x3e,0x00,0x02,0x00,0x5e,0xfe,0x96,0x06,0x3d,0x05,0xb2,0x00,0x1b,0x00,0x29,0x00,0x30,0x40,0x19,0x05,0x05,0x01,0x7e,0x25,0x1a,0x0b,0x0b,0x2b,0x1f,0x7d,0x13,0x1b,0x03,0x1c,0x91,0x16,0x04,0x22,0x91,0x10,0x13,0x03,0x91,0x08,0x00,0x2f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33, 0x33,0xed,0x32,0x2f,0x31,0x30,0x01,0x11,0x10,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x35,0x06,0x07,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x17,0x16,0x17,0x35,0x05,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x11,0x35,0x02,0x27,0x26,0x05,0x19,0xb2,0x3f,0x33,0x38,0x42,0x9f,0xb3,0x0c,0x0d,0xa2,0xfe,0xf1,0xfe,0xf6, 0xfe,0xc1,0x01,0x45,0x01,0x19,0x01,0x02,0x9e,0x0b,0x0a,0xfe,0x54,0xc3,0xf4,0xed,0xbf,0xcc,0xeb,0x03,0x6f,0x72,0x05,0x9a,0xfa,0x9b,0xfe,0xf8,0x1d,0xa0,0x14,0xe2,0xbd,0xa0,0x11,0x10,0xcc,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0xc8,0x0e,0x0f,0xcd,0x80,0xfe,0xba,0xfe,0xf7,0xfe,0xf7,0xfe,0xbd,0x01,0x34,0x01,0x15,0x0e,0x01, 0x12,0x97,0x9b,0x00,0x00,0x02,0x00,0x60,0xfe,0x96,0x05,0x34,0x04,0x18,0x00,0x1d,0x00,0x2e,0x00,0x2c,0x40,0x17,0x27,0x83,0x12,0x02,0x02,0x1c,0x84,0x1e,0x1a,0x0a,0x1a,0x0f,0x23,0x95,0x16,0x10,0x2b,0x95,0x0e,0x16,0x00,0xec,0x05,0x00,0x2f,0xed,0x3f,0xed,0x3f,0xed,0x3f,0x01,0x2f,0x33,0x33,0xed,0x32,0x2f,0x2f,0xed,0x31,0x30, 0x05,0x32,0x37,0x15,0x06,0x23,0x22,0x27,0x26,0x26,0x35,0x35,0x23,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x10,0x03,0x35,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x04,0xc2,0x3e,0x34,0x39,0x41,0x9f,0x5a,0x2d,0x28,0x04,0x72,0xee,0xc1,0x74,0x73,0x80, 0x80,0xd5,0xd3,0x60,0x04,0xa4,0xa4,0x52,0x53,0x7d,0x96,0x56,0x56,0x52,0x53,0x8b,0x89,0x55,0x56,0xd3,0x1d,0xa0,0x14,0x71,0x39,0x96,0x5f,0x79,0xc6,0x89,0x89,0xee,0xfd,0x9a,0x99,0xa6,0x8e,0xfc,0x35,0xfe,0xf8,0x02,0xa2,0x97,0x7d,0x55,0x56,0x6e,0x6e,0xc2,0xb1,0x67,0x66,0x63,0x64,0x00,0x00,0x02,0x00,0x1c,0x00,0x00,0x04,0xc0, 0x05,0x9a,0x00,0x20,0x00,0x2b,0x00,0xb0,0x40,0x32,0x75,0x13,0x01,0x76,0x12,0x01,0x39,0x02,0x01,0x0e,0x1b,0x22,0x91,0x0b,0x08,0x08,0x0a,0x21,0x91,0x0f,0x03,0x01,0x0a,0x1b,0x09,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x28,0x7d,0x15,0x79,0x02,0x01,0x7a,0x01,0x01,0x02,0xb8,0xff,0xe8,0xb4, 0x0b,0x0d,0x01,0x4c,0x01,0xb8,0xff,0xe8,0x40,0x28,0x0b,0x0d,0x01,0x4c,0x01,0x1c,0x02,0x15,0x04,0x70,0x00,0x01,0x00,0x08,0x0d,0x06,0x4d,0x00,0x2d,0x22,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x0e,0x0d,0x09,0x7e,0x0a,0xb8,0xff,0xf2,0xb3,0x0d,0x06,0x4d,0x0a,0xb8,0xff,0xfa,0xb3,0x0c,0x06, 0x4d,0x0a,0xb8,0xff,0xfa,0xb3,0x0b,0x06,0x4d,0x0a,0x2f,0x2b,0x2b,0x2b,0xe1,0x33,0x33,0x2b,0x2b,0x2b,0x32,0x10,0xc6,0x2b,0x5d,0x17,0x32,0x2b,0x2b,0x5d,0x5d,0x2f,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x00,0x2f,0x33,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0x39,0x32,0x31,0x30,0x5d,0x01,0x5d,0x5d,0x21,0x23,0x03,0x2e,0x03,0x23,0x23,0x11, 0x23,0x11,0x23,0x35,0x33,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x17,0x01,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x04,0xc0,0xc8,0xf0,0x21,0x3e,0x41,0x4b,0x2f,0x8a,0xa8,0xa0,0xa0,0x01,0xac,0x5e,0x9f,0x75,0x42,0x2d,0x53,0x75,0x49,0x24,0x35,0x30,0x2f,0x1d,0xfd,0xb1,0xe4,0x3f,0x6b,0x4e,0x2c, 0x95,0x8d,0x01,0x92,0x38,0x4f,0x32,0x17,0xfd,0x9e,0x02,0x62,0x98,0x02,0xa0,0x2f,0x60,0x8f,0x60,0x4b,0x7d,0x62,0x45,0x13,0x04,0x10,0x29,0x38,0x47,0x2f,0x03,0x53,0xfd,0xf8,0x26,0x47,0x67,0x40,0x73,0x81,0x00,0x01,0x00,0x1c,0x00,0x00,0x02,0xbc,0x04,0x12,0x00,0x18,0x00,0x3f,0x40,0x1f,0x00,0x00,0x1a,0x11,0x06,0x0a,0x84,0x0b, 0x0f,0x0b,0x0d,0x0d,0x0b,0x09,0x0c,0xec,0x06,0x0f,0x0f,0x0b,0x16,0x12,0x00,0x00,0x02,0x16,0x10,0x10,0x0f,0x0b,0x15,0x00,0x3f,0x3f,0x3f,0xcd,0x32,0x2f,0x32,0x11,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x33,0x2f,0x11,0x33,0x10,0xed,0x32,0x32,0x11,0x39,0x2f,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x15,0x21,0x15,0x21,0x11, 0x23,0x11,0x23,0x35,0x33,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x02,0xbc,0x2b,0x51,0x69,0x8d,0x01,0x16,0xfe,0xea,0xa4,0x8a,0x8a,0xa4,0x04,0x23,0x90,0x59,0x40,0x22,0x03,0x5a,0x21,0xc6,0xab,0x23,0x98,0xfe,0xb1,0x01,0x4f,0x98,0x02,0x19,0xd3,0x6c,0x79,0x0e,0x00,0x02,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x00,0x11, 0x00,0x19,0x00,0x68,0x40,0x34,0x18,0x10,0x14,0x11,0x11,0x00,0x0f,0x19,0x0e,0x14,0x14,0x07,0x04,0x01,0x00,0x06,0x7e,0x0c,0x09,0x07,0x07,0x0d,0x00,0x02,0x02,0x00,0x00,0x1b,0x0e,0x0d,0x0b,0x0b,0x0d,0x19,0x04,0x0a,0x91,0x0f,0x01,0x0b,0x0b,0x11,0x11,0x14,0x05,0x08,0x03,0x07,0x0d,0x03,0x07,0x12,0x00,0x3f,0x3f,0x12,0x17,0x39, 0x33,0x11,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x33,0x2f,0x11,0x33,0x11,0x33,0x2f,0x33,0x2f,0x11,0x12,0x39,0x2f,0x39,0x39,0xed,0x11,0x39,0x39,0x11,0x39,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x03,0x33,0x15,0x23,0x03,0x11,0x23,0x11,0x03,0x23,0x35,0x33,0x03,0x33,0x13,0x21,0x13,0x01,0x16, 0x17,0x33,0x36,0x37,0x37,0x21,0x04,0x60,0x8b,0x7a,0xc9,0xff,0xa8,0xfa,0xc9,0x7c,0x86,0xbf,0x83,0x01,0xd0,0x8a,0xfe,0x64,0x06,0x1d,0x03,0x0a,0x1c,0x78,0xfe,0xc9,0x05,0x9a,0xfe,0xf7,0x98,0xfe,0x19,0xfd,0xee,0x02,0x0e,0x01,0xeb,0x98,0x01,0x09,0xfe,0xf7,0x01,0x09,0xfd,0x78,0x0c,0x4c,0x22,0x36,0xe7,0x00,0x00,0x02,0x00,0x0e, 0xfe,0x1e,0x03,0xd5,0x04,0x00,0x00,0x18,0x00,0x20,0x00,0x66,0x40,0x35,0x1f,0x17,0x18,0x18,0x00,0x20,0x16,0x1b,0x15,0x01,0x04,0x05,0x1b,0x0f,0x10,0x13,0x07,0x00,0x0a,0x0a,0x14,0x00,0x02,0x02,0x00,0x00,0x22,0x15,0x14,0x12,0x12,0x14,0x20,0x04,0x11,0x96,0x16,0x01,0x12,0x12,0x21,0x18,0x14,0x0f,0x1b,0x05,0x0f,0x0a,0x0a,0x0c, 0x95,0x07,0x1c,0x00,0x3f,0xed,0x32,0x2f,0x2f,0x33,0x33,0x3f,0x33,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x33,0x2f,0x11,0x33,0x11,0x33,0x2f,0x33,0x2f,0x11,0x12,0x39,0x2f,0x12,0x17,0x39,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x39,0x39,0x31,0x30,0x01,0x03,0x33,0x15,0x23,0x01,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32, 0x37,0x37,0x03,0x23,0x35,0x33,0x03,0x33,0x13,0x21,0x13,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x21,0x03,0xd5,0x8b,0x79,0xae,0xfe,0xe9,0x7e,0xe4,0x40,0x2b,0x35,0x2c,0x7c,0x3e,0x52,0xd3,0xae,0x79,0x88,0xb6,0x7a,0x01,0x6c,0x81,0xfe,0xae,0x05,0x10,0x06,0x05,0x0f,0x71,0xfe,0xf4,0x04,0x00,0xfe,0xa3,0x86,0xfd,0x3f,0xfe,0xc2,0x0d, 0x93,0x12,0x94,0xc2,0x02,0x1b,0x86,0x01,0x5d,0xfe,0xa3,0x01,0x5d,0xfc,0xec,0x0f,0x3f,0x18,0x34,0x01,0x33,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x6c,0x04,0x18,0x02,0x06,0x07,0x72,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x02,0x26,0x00,0x46,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x78,0xfc,0xe6,0x00,0x1b, 0x40,0x14,0x01,0x0f,0x1c,0x1f,0x1c,0x02,0x3f,0x1c,0x6f,0x1c,0x70,0x1c,0x8f,0x1c,0xcf,0x1c,0xdf,0x1c,0x06,0x1c,0x00,0x11,0x5d,0x71,0x35,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x6c,0x04,0x18,0x02,0x26,0x07,0x72,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0xb5,0xfc,0xe6,0x00,0x1b,0x40,0x14,0x01,0x0f,0x1c,0x1f,0x1c,0x02,0x3f,0x1c, 0x6f,0x1c,0x70,0x1c,0x8f,0x1c,0xcf,0x1c,0xdf,0x1c,0x06,0x1c,0x00,0x11,0x5d,0x71,0x35,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x01,0x4a,0x05,0xec,0x02,0x06,0x00,0x4f,0x00,0x00,0xff,0xff,0x00,0x29,0xfe,0x96,0x03,0xf6,0x05,0x9a,0x02,0x26,0x02,0xb9,0x00,0x00,0x01,0x07,0x08,0x5c,0x01,0x78,0x00,0x00,0x00,0x09,0xb3,0x01,0x1a,0x1a, 0x06,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0x1e,0xfe,0x96,0x03,0x29,0x04,0x00,0x02,0x26,0x02,0xba,0x00,0x00,0x01,0x07,0x08,0x5c,0x01,0x56,0x00,0x00,0x00,0x09,0xb3,0x01,0x1a,0x1a,0x06,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0x1a,0xfe,0x96,0x04,0xda,0x05,0x9a,0x00,0x26,0x00,0x3b,0x00,0x00,0x00,0x07,0x08,0x5c,0x04,0x03, 0x00,0x00,0xff,0xff,0x00,0x1a,0xfe,0x96,0x03,0xc6,0x04,0x00,0x00,0x26,0x00,0x5b,0x00,0x00,0x00,0x07,0x08,0x5c,0x02,0xef,0x00,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x00,0x1b,0x00,0x9b,0xb9,0x00,0x16,0xff,0xe0,0x40,0x11,0x0b,0x0d,0x01,0x4c,0x0f,0x20,0x0b,0x0d,0x01,0x4c,0x08,0x20,0x0b,0x0d,0x01,0x4c,0x01, 0xb8,0xff,0xe0,0x40,0x0a,0x0b,0x0d,0x01,0x4c,0x16,0x08,0x0c,0x00,0x4d,0x0f,0xb8,0xff,0xf8,0x40,0x09,0x0c,0x00,0x4d,0x0a,0x10,0x0b,0x00,0x4d,0x08,0xb8,0xff,0xf8,0x40,0x1d,0x0c,0x00,0x4d,0x01,0x08,0x0c,0x00,0x4d,0x0a,0x18,0x0d,0x1b,0x04,0x0e,0x19,0x19,0x17,0x00,0x10,0x0b,0x00,0x4d,0x00,0x00,0x1d,0x0b,0x0b,0x0e,0x09,0xb8, 0xff,0xf0,0x40,0x16,0x0b,0x00,0x4d,0x09,0x1b,0x04,0x0b,0x91,0x18,0x12,0x2f,0x0c,0x01,0x0c,0x0c,0x08,0x16,0x0f,0x03,0x01,0x08,0x12,0x00,0x3f,0x33,0x3f,0x33,0x12,0x39,0x2f,0x5d,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x2b,0xc6,0x33,0x2f,0x11,0x33,0x2f,0x2b,0xc6,0x33,0x2f,0x11,0x17,0x39,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b, 0x2b,0x2b,0x2b,0x21,0x23,0x01,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x21,0x35,0x21,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x21,0x15,0x21,0x04,0x9a,0xcd,0xfe,0xb6,0x0f,0x12,0x04,0x0a,0x18,0xfe,0xac,0xce,0x01,0xb2,0xfe,0x66,0x01,0x94,0xfe,0x7a,0xce,0x01,0x25,0x1d,0x16,0x04,0x20,0x18,0x01,0x31,0xc1,0xfe, 0x71,0x01,0x8b,0xfe,0x6d,0x02,0x25,0x19,0x2e,0x17,0x30,0xfd,0xdb,0x02,0x8d,0x98,0x02,0x75,0xfe,0x08,0x32,0x32,0x42,0x26,0x01,0xf4,0xfd,0x8b,0x98,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x03,0x92,0x04,0x00,0x00,0x19,0x00,0x4e,0x40,0x2f,0x0d,0x0a,0x18,0x01,0x04,0x02,0x09,0x02,0x00,0x17,0x09,0x0c,0x0b,0x0e,0x13,0x0d,0x19,0x96, 0x0a,0x06,0x0f,0x00,0x1f,0x00,0x4f,0x00,0x5f,0x00,0x04,0x2f,0x00,0x3f,0x00,0x6f,0x00,0x7f,0x00,0x04,0x00,0x00,0x03,0x0f,0x16,0x15,0x08,0x03,0x0f,0x00,0x3f,0x33,0x3f,0x33,0x12,0x39,0x2f,0x5d,0x71,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x33,0x33,0x33,0x2f,0x33,0x33,0x11,0x12,0x17,0x39,0x31,0x30,0x13,0x21,0x01,0x33,0x13,0x16, 0x17,0x33,0x01,0x33,0x01,0x21,0x15,0x21,0x01,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x01,0x21,0x28,0x01,0x21,0xfe,0xe0,0xbf,0xc6,0x16,0x15,0x04,0x01,0x00,0xb5,0xfe,0xd4,0x01,0x1e,0xfe,0xe3,0x01,0x25,0xbf,0xc9,0x13,0x1a,0x04,0x05,0x2a,0xcd,0xbd,0x01,0x31,0xfe,0xdd,0x02,0x3d,0x01,0xc3,0xfe,0xa2,0x27,0x29,0x01,0xae, 0xfe,0x3d,0x86,0xfe,0x49,0x01,0x4c,0x1f,0x2f,0x09,0x45,0xfe,0xb4,0x01,0xb7,0x00,0xff,0xff,0x00,0x70,0xff,0xe8,0x03,0xf4,0x05,0xb2,0x02,0x06,0x04,0xbf,0x00,0x00,0xff,0xff,0x00,0x52,0xff,0xe7,0x03,0x3b,0x04,0x19,0x02,0x06,0x01,0x31,0x00,0x00,0xff,0xff,0x00,0x10,0xfe,0x96,0x04,0xa4,0x05,0x9a,0x02,0x26,0x01,0xf2,0x00,0x00, 0x01,0x07,0x04,0x80,0x03,0xbe,0x00,0x00,0x00,0x09,0xb3,0x01,0x1d,0x1d,0x01,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0x10,0xfe,0x96,0x03,0x92,0x04,0x00,0x02,0x26,0x02,0x12,0x00,0x00,0x01,0x07,0x04,0x80,0x02,0xac,0x00,0x00,0x00,0x09,0xb3,0x01,0x19,0x19,0x01,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0x3e,0x04,0xc2,0x03,0x75, 0x06,0x0a,0x00,0x26,0x00,0xd9,0x00,0x00,0x00,0x07,0x00,0x8e,0x01,0x69,0x00,0x00,0xff,0xff,0x00,0x3f,0x04,0xc2,0x03,0x75,0x06,0x0a,0x00,0x27,0x00,0xd9,0x01,0x3b,0x00,0x00,0x00,0x06,0x00,0x43,0xed,0x00,0xff,0xff,0x00,0x3e,0x03,0xe8,0x03,0x68,0x05,0x30,0x00,0x26,0x00,0xd9,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x91,0xff,0x26, 0x00,0x0a,0xb3,0x01,0x06,0x06,0x02,0x00,0x10,0x3c,0x11,0x35,0xff,0xff,0x00,0x3f,0x03,0xe8,0x03,0x68,0x05,0x30,0x00,0x27,0x00,0xd9,0x01,0x2e,0x00,0x00,0x01,0x07,0x00,0x8e,0xff,0xb8,0xff,0x26,0x00,0x0a,0xb3,0x01,0x07,0x07,0x02,0x00,0x10,0x3c,0x11,0x35,0xff,0xff,0x00,0x3f,0x04,0x83,0x03,0xd0,0x05,0xcb,0x00,0x26,0x00,0x43, 0xed,0xc1,0x00,0x27,0x00,0x8e,0x00,0xbd,0xff,0xc1,0x00,0x07,0x00,0x43,0x01,0xf9,0xff,0xc1,0xff,0xff,0x00,0x3f,0x04,0x83,0x03,0xd0,0x05,0xcb,0x00,0x26,0x00,0x8e,0xb8,0xc1,0x00,0x27,0x00,0x43,0x00,0xf3,0xff,0xc1,0x00,0x07,0x00,0x8e,0x01,0xc4,0xff,0xc1,0xff,0xff,0x00,0x66,0xfd,0xfe,0x01,0xa8,0x00,0x2c,0x00,0x07,0x06,0x79, 0x00,0x00,0xfb,0x64,0x00,0x01,0x00,0x77,0x04,0x09,0x02,0x30,0x06,0x83,0x00,0x06,0x00,0x0d,0xb3,0x00,0x01,0x03,0x00,0x00,0x2f,0xce,0x01,0x2f,0xcd,0x31,0x30,0x01,0x25,0x35,0x25,0x15,0x05,0x05,0x02,0x30,0xfe,0x47,0x01,0xb9,0xfe,0xb6,0x01,0x4a,0x04,0x09,0xdd,0xc0,0xdd,0x7c,0xc1,0xc1,0x00,0x02,0x00,0xdb,0xfe,0x05,0x04,0x57, 0x00,0x1b,0x00,0x06,0x00,0x0d,0x00,0x2c,0x40,0x17,0x07,0x0a,0x05,0x40,0x06,0x80,0x0a,0x01,0x0a,0x80,0x30,0x09,0x40,0x09,0x02,0x09,0x09,0x03,0xc0,0x2f,0x06,0x01,0x06,0x00,0x2f,0x5d,0x1a,0xce,0x33,0x2f,0x5d,0x1a,0xcd,0x5d,0x01,0x2f,0x1a,0xcd,0x2f,0xcc,0x31,0x30,0x13,0x37,0x27,0x35,0x05,0x15,0x05,0x01,0x03,0x23,0x03,0x33, 0x17,0x37,0xdb,0xc8,0xc8,0x01,0x37,0xfe,0xc9,0x03,0x7c,0xab,0xc0,0xab,0x7c,0x8f,0x8f,0xfe,0x81,0x8f,0x8f,0x7c,0xab,0xc0,0xab,0x01,0x94,0xfe,0xc9,0x01,0x37,0xc8,0xc8,0x00,0x00,0x04,0x00,0x35,0xff,0xf5,0x05,0xae,0x05,0x9a,0x00,0x07,0x00,0x0a,0x00,0x40,0x00,0x44,0x00,0x8e,0x40,0x0f,0x08,0x02,0x01,0x09,0x01,0x0a,0x03,0x04, 0x09,0x04,0x2c,0x13,0x3b,0x25,0x27,0xb8,0x01,0x0e,0x40,0x0c,0x0f,0x22,0x3f,0x22,0x5f,0x22,0x6f,0x22,0x04,0x22,0x0b,0x10,0xb8,0x01,0x0e,0xb3,0x3b,0x02,0x08,0x03,0xb8,0x01,0x0e,0xb7,0x0a,0x0a,0x06,0x05,0x43,0x44,0x09,0x06,0xbc,0x01,0x06,0x00,0x01,0x01,0x0a,0x00,0x05,0x01,0x0a,0xb3,0x41,0x43,0x0b,0x2c,0xb8,0x01,0x0c,0xb2, 0x1d,0x25,0x36,0xb8,0x01,0x0c,0x40,0x09,0x13,0x13,0x46,0x0a,0x08,0x05,0x00,0x00,0x05,0x2f,0x33,0x2f,0x12,0x39,0x39,0x11,0x33,0x2f,0xed,0x32,0xd4,0xed,0x33,0x2f,0x2f,0x00,0x3f,0x3f,0x3f,0x33,0x33,0x2f,0x11,0x12,0x39,0x2f,0xed,0x33,0x32,0x2f,0xed,0x32,0x2f,0x5d,0xed,0x32,0x12,0x39,0x39,0x31,0x30,0x10,0x87,0x05,0xc0,0xc0, 0x10,0x87,0xc0,0xc0,0x01,0x23,0x27,0x21,0x07,0x23,0x01,0x33,0x13,0x03,0x03,0x01,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x01,0x01,0x23,0x01,0x02,0xd3,0x83, 0x49,0xfe,0xf7,0x46,0x83,0x01,0x17,0x6f,0x23,0x5d,0x5a,0x02,0xbe,0x17,0x36,0x37,0x34,0x15,0x3b,0x46,0x17,0x29,0x37,0x20,0x26,0x42,0x32,0x1c,0x2d,0x49,0x5d,0x30,0x6a,0x3e,0x59,0x57,0x18,0x2e,0x24,0x16,0x13,0x24,0x34,0x20,0x24,0x46,0x37,0x21,0x29,0x46,0x5e,0x35,0x1a,0x38,0x35,0x2f,0x11,0x01,0x4d,0xfc,0xa6,0x90,0x03,0x5b, 0x02,0xc0,0xc2,0xc2,0x02,0xd9,0xfe,0x59,0x01,0x01,0xfe,0xff,0xfc,0xc8,0x14,0x1f,0x16,0x0c,0x2d,0x2b,0x17,0x23,0x1f,0x1d,0x10,0x14,0x27,0x32,0x3f,0x2b,0x35,0x4c,0x32,0x18,0x20,0x8b,0x3b,0x09,0x14,0x20,0x17,0x15,0x21,0x1d,0x1c,0x10,0x13,0x2b,0x35,0x40,0x29,0x38,0x4f,0x33,0x17,0x07,0x0d,0x12,0x0b,0x05,0x74,0xfa,0x66,0x05, 0x9a,0x00,0x00,0x01,0x00,0x48,0x00,0x00,0x03,0x0c,0x04,0x01,0x00,0x09,0x00,0x2d,0x40,0x16,0x07,0x84,0x06,0x02,0x06,0x03,0x06,0x03,0x06,0x0b,0x00,0x02,0x95,0x05,0x05,0x06,0x01,0x95,0x08,0x15,0x06,0x0f,0x00,0x3f,0x3f,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x31,0x30,0x37,0x21,0x11, 0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x48,0x02,0x21,0xfe,0x34,0x01,0xcc,0xa3,0xfd,0x3c,0x8a,0x01,0x5d,0x8c,0x01,0x8e,0xfb,0xff,0x00,0xff,0xff,0x00,0x5a,0xff,0xe8,0x03,0x6c,0x04,0x18,0x02,0x06,0x07,0x72,0x00,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x03,0xa4,0x05,0x9a,0x00,0x15,0x00,0x86,0xb9,0x00,0x15,0xff,0xf0,0xb3,0x10,0x06, 0x4d,0x15,0xb8,0xff,0xf0,0xb4,0x0b,0x0d,0x06,0x4c,0x15,0xb8,0xff,0xe8,0xb3,0x0a,0x06,0x4d,0x15,0xb8,0xff,0xe0,0xb3,0x09,0x06,0x4d,0x15,0xb8,0xff,0xc0,0x40,0x32,0x0a,0x1f,0x48,0x15,0x15,0x17,0x01,0x0e,0x11,0x11,0x10,0x0c,0x14,0x7e,0x01,0x07,0x03,0x03,0x09,0x05,0x01,0x13,0x02,0x91,0x05,0x10,0x05,0x0f,0x06,0x91,0x09,0x0c, 0x09,0x2f,0x09,0x6f,0x09,0x7f,0x09,0x03,0x05,0x09,0x05,0x09,0x0a,0x03,0x14,0x91,0x01,0x12,0x00,0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0x33,0x33,0x33,0x2f,0x33,0x10,0xed,0x32,0x32,0x32,0x2f,0x33,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x31,0x30,0x21,0x21, 0x11,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0x21,0x03,0xa4,0xfd,0x18,0xa0,0xa0,0xa0,0xa0,0xa8,0x01,0x2e,0xfe,0xd2,0x01,0x2e,0xfe,0xd2,0x02,0x40,0x01,0xda,0x98,0x9e,0x98,0x01,0xf2,0xfe,0x0e,0x98,0x9e,0x98,0xfe,0xbe,0x00,0x00,0x01,0x00,0x14,0x00,0x00,0x02,0x36,0x05,0xec, 0x00,0x13,0x00,0x51,0x40,0x2d,0x08,0x03,0x03,0x01,0x0e,0x12,0x12,0x00,0x84,0x09,0x05,0x01,0x0f,0x07,0x96,0x08,0x0c,0x08,0x13,0x03,0x96,0x04,0x10,0x04,0x0f,0x08,0x1f,0x08,0x3f,0x08,0x03,0x6f,0x04,0x8f,0x04,0x02,0x08,0x04,0x08,0x04,0x01,0x0a,0x00,0x01,0x15,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x11,0x33,0x10, 0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0x33,0x33,0xed,0x32,0x2f,0x33,0x11,0x33,0x2f,0x33,0x31,0x30,0x21,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x01,0x77,0xa4,0xbf,0xbf,0xbf,0xbf,0xa4,0xbf,0xbf,0xbf,0xbf,0x01,0xe1,0x86,0x92,0x86,0x02,0x6d,0xfd,0x93,0x86,0x92, 0x86,0x00,0xff,0xff,0x00,0x27,0x00,0x00,0x03,0xf9,0x05,0x9a,0x00,0x26,0x00,0x2f,0x55,0x00,0x00,0x07,0x00,0xd8,0x00,0x04,0xfd,0x66,0x00,0x02,0x00,0x1c,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x0e,0x00,0x1a,0x00,0x51,0x40,0x29,0x12,0x12,0x14,0x0b,0x7d,0x18,0x18,0x1c,0x02,0x10,0x14,0x14,0x00,0x01,0x7e,0x02,0x06,0x02,0x04,0x04, 0x02,0x00,0x91,0x14,0x13,0x03,0x91,0x06,0x10,0x06,0x14,0x06,0x14,0x06,0x02,0x0f,0x91,0x07,0x03,0x02,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x01,0x2f,0x33,0x2f,0x11,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x31,0x30,0x01,0x11,0x23,0x11,0x23, 0x35,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x15,0x21,0x15,0x21,0x15,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0xa8,0xa0,0xa0,0x01,0x8a,0xe6,0xfd,0xfe,0xe7,0xef,0xbd,0x01,0x24,0xfe,0xdc,0xb0,0xae,0xb7,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x03,0x8a,0x98,0x01,0x78,0xe0,0xcc,0xcc,0xfe,0xfc,0x02,0xe4,0xe0,0x98,0xd4,0x9f, 0x91,0x01,0x1c,0x00,0xff,0xff,0x00,0xbc,0xfe,0x96,0x04,0xc0,0x05,0x9a,0x02,0x26,0x00,0x35,0x00,0x00,0x01,0x07,0x0a,0xbb,0x01,0xa2,0x00,0x00,0x00,0x09,0xb3,0x02,0x29,0x29,0x09,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0x5a,0xfe,0xb5,0x03,0x95,0x05,0x3d,0x02,0x26,0x00,0x44,0x00,0x00,0x01,0x07,0x04,0x96,0x02,0x03,0xff,0xa3, 0x00,0x0a,0xb4,0x02,0x4f,0x1f,0x01,0x1f,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xb5,0xff,0x12,0x02,0xd7,0x05,0x9a,0x02,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x04,0x96,0x01,0x45,0x00,0x00,0x00,0x0a,0xb4,0x01,0x4f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xbc,0xfe,0x80,0x05,0xb2,0x05,0x9a,0x02,0x06,0x02,0xc1,0x00,0x00, 0xff,0xff,0x00,0xa6,0xfe,0x8a,0x04,0x92,0x05,0xec,0x00,0x26,0x00,0x4b,0x00,0x00,0x01,0x07,0x0a,0xbe,0x02,0x45,0x00,0x00,0x00,0x09,0xb3,0x01,0x12,0x12,0x00,0x10,0x3c,0x11,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x80,0x04,0xdd,0x05,0x9a,0x00,0x26,0x00,0x2e,0x00,0x00,0x00,0x07,0x0a,0xbd,0x02,0x7d,0x00,0x00,0xff,0xff,0x00,0xa6, 0xfe,0x8a,0x04,0x0c,0x05,0xec,0x00,0x26,0x00,0x4e,0x00,0x00,0x00,0x07,0x0a,0xbe,0x01,0xbf,0x00,0x00,0xff,0xff,0x00,0x21,0xfe,0x80,0x04,0xb6,0x05,0x9a,0x00,0x26,0x00,0x3d,0x00,0x00,0x00,0x07,0x0a,0xbd,0x02,0x56,0x00,0x00,0xff,0xff,0x00,0x21,0xfe,0x8b,0x03,0xbd,0x04,0x00,0x00,0x26,0x00,0x5d,0x00,0x00,0x00,0x07,0x0a,0xbe, 0x01,0x70,0x00,0x01,0x00,0x02,0x00,0x4b,0x00,0x00,0x04,0x3a,0x04,0x23,0x00,0x21,0x00,0x2d,0x00,0x5c,0x40,0x2e,0x0a,0xef,0x1c,0x1f,0x1b,0x00,0x1b,0x0f,0x2b,0x28,0x1a,0x13,0x13,0x19,0x22,0x22,0x00,0x18,0x19,0x19,0x2f,0x28,0xef,0x00,0x1e,0x1e,0x00,0x1f,0x2b,0x1e,0x25,0x1e,0x1c,0x0f,0x05,0x1d,0x1d,0x13,0x1b,0x15,0x18,0x0f, 0x25,0x95,0x05,0x10,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x39,0x2f,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x11,0x33,0x11,0x33,0x12,0x39,0x2f,0x12,0x39,0x11,0x33,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0xed,0x31,0x30,0x13,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x13,0x16,0x16, 0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x23,0x01,0x07,0x27,0x37,0x26,0x26,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0x95,0x26,0x41,0x53,0x2d,0x2c,0x52,0x3e,0x25,0x1d,0x37,0x50,0x32,0x9f,0x14,0x18,0x07,0x04,0x05,0x10,0x0b,0x01,0x10,0xad,0xfe,0x68,0x9a,0xfe,0xf9,0x7a,0x3c,0x7b,0x15,0x1c,0x01,0x31,0x26, 0x24,0x1e,0x31,0x0f,0x10,0x3f,0x3b,0x03,0x3f,0x3c,0x56,0x37,0x1b,0x1a,0x33,0x4d,0x32,0x31,0x4f,0x43,0x3a,0x1d,0xfe,0xd2,0x26,0x42,0x1e,0x26,0x46,0x1f,0x02,0xec,0xfc,0x00,0x01,0xf6,0x41,0x7a,0x3e,0x31,0x68,0x43,0x24,0x2f,0x2f,0x35,0x24,0x3f,0x23,0x23,0x46,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x03,0xfa,0x05,0x9a,0x00,0x07, 0x00,0x22,0x40,0x10,0x07,0x03,0x7e,0x04,0x01,0x01,0x04,0x02,0x91,0x07,0x07,0x04,0x05,0x03,0x04,0x12,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x31,0x30,0x01,0x15,0x21,0x11,0x23,0x11,0x33,0x11,0x03,0xfa,0xfd,0x6a,0xa8,0xa8,0x03,0x25,0x97,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x00,0x00,0x01,0x00,0xa6, 0x00,0x00,0x03,0x04,0x04,0x00,0x00,0x07,0x00,0x22,0x40,0x10,0x07,0x03,0x84,0x04,0x00,0x00,0x04,0x02,0x95,0x07,0x07,0x04,0x05,0x0f,0x04,0x15,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x31,0x30,0x01,0x15,0x21,0x11,0x23,0x11,0x33,0x11,0x03,0x04,0xfe,0x46,0xa4,0xa4,0x02,0x5c,0x8b,0xfe,0x2f,0x04, 0x00,0xfe,0x5c,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x05,0x38,0x04,0x18,0x00,0x15,0x00,0x1f,0x00,0x35,0xb9,0x00,0x1f,0x01,0x2e,0x40,0x18,0x0e,0x07,0x0e,0x07,0x04,0x13,0x83,0x1a,0x1a,0x21,0x09,0x83,0x04,0x1d,0x95,0x10,0x10,0x07,0x0f,0x16,0x0d,0x95,0x01,0x16,0x00,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f, 0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x05,0x23,0x22,0x00,0x35,0x10,0x37,0x33,0x06,0x11,0x14,0x16,0x33,0x33,0x11,0x10,0x21,0x32,0x12,0x15,0x14,0x00,0x25,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x15,0x03,0x36,0xd2,0xec,0xfe,0xe8,0xd2,0xc2,0xec,0xbf,0x9b,0x1e,0x01,0x12,0xbc,0xea,0xfe,0xe7,0xfe,0xf5,0x22,0x98,0xc2, 0x93,0x67,0x82,0x18,0x01,0x20,0xf6,0x01,0x3b,0xc7,0xd8,0xfe,0xd2,0xb8,0xce,0x02,0x95,0x01,0x0f,0xfe,0xd7,0xfb,0xe9,0xfe,0xdd,0x8c,0xd3,0xb5,0xb4,0xdc,0x81,0x00,0x00,0x02,0x00,0xaf,0x03,0xf9,0x02,0x48,0x05,0xf5,0x00,0x03,0x00,0x0f,0x00,0x22,0xb3,0x0d,0xc0,0x07,0x01,0xb8,0x01,0x32,0x40,0x09,0x02,0x0a,0xc1,0x04,0x04,0x02, 0x03,0x03,0x02,0x00,0x2f,0x33,0x2f,0x11,0x33,0x2f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x11,0x23,0x11,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x48,0x6d,0xc9,0x28,0x3b,0x3a,0x29,0x29,0x39,0x39,0x05,0xf5,0xfe,0x04,0x01,0xfc,0xfe,0xa0,0x39,0x2a,0x28,0x38,0x37,0x29,0x29,0x3a,0x00,0x00,0x02, 0x00,0xaf,0x03,0xfd,0x02,0xa0,0x05,0xee,0x00,0x13,0x00,0x17,0x00,0x28,0x40,0x14,0x14,0x14,0x16,0x16,0x0c,0xc0,0x02,0x07,0xc1,0x0f,0x11,0x1f,0x11,0x02,0x11,0x11,0x15,0x17,0x17,0x15,0x00,0x2f,0x33,0x2f,0x11,0x33,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x33,0x2f,0x33,0x2f,0x31,0x30,0x13,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x25,0x01,0x27,0x01,0xcc,0x1d,0x0f,0x19,0x24,0x15,0x15,0x24,0x1b,0x10,0x11,0x1b,0x25,0x13,0x12,0x24,0x01,0xc6,0xfe,0x99,0x4d,0x01,0x67,0x05,0x47,0x1d,0x29,0x13,0x24,0x1a,0x10,0x11,0x1c,0x23,0x13,0x14,0x23,0x1a,0x10,0x0f,0x2c,0xfe,0x98,0x4d,0x01,0x68,0x00,0x00,0x02,0x00,0xaf,0x04,0x2b, 0x02,0xab,0x05,0xc4,0x00,0x03,0x00,0x0f,0x00,0x27,0x40,0x14,0x0a,0xc0,0x04,0x04,0x01,0x00,0x00,0x01,0x07,0xc1,0x0d,0x40,0x09,0x0e,0x48,0x0d,0x0d,0x02,0xe7,0x01,0x00,0x2f,0xed,0x33,0x2f,0x2b,0xed,0x01,0x2f,0x33,0x2f,0x11,0x33,0x2f,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x25,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22, 0x26,0x02,0xab,0xfe,0x04,0x01,0xfc,0xfe,0xa0,0x39,0x2a,0x28,0x38,0x37,0x29,0x29,0x3a,0x04,0x2b,0x6d,0xc9,0x28,0x3b,0x3a,0x29,0x29,0x39,0x39,0x00,0x01,0x00,0x75,0x04,0xfe,0x03,0x69,0x06,0x58,0x00,0x05,0x00,0x18,0x40,0x0a,0x04,0xea,0x01,0x01,0x02,0x05,0x05,0x03,0xbe,0x02,0x00,0x2f,0xed,0x33,0x2f,0x01,0x2f,0x33,0x2f,0xed, 0x31,0x30,0x01,0x11,0x21,0x35,0x21,0x35,0x03,0x69,0xfd,0x0c,0x02,0x5f,0x06,0x58,0xfe,0xa6,0x95,0xc5,0x00,0x01,0x00,0x75,0x04,0x7c,0x04,0x54,0x06,0x58,0x00,0x09,0x00,0x25,0x40,0x11,0x09,0xea,0x00,0x00,0x04,0x07,0x07,0x03,0xea,0x04,0x08,0x02,0xbe,0x05,0x05,0x00,0x04,0x00,0x2f,0x33,0x33,0x2f,0xed,0x32,0x01,0x2f,0xed,0x33, 0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x11,0x21,0x11,0x23,0x11,0x21,0x15,0x21,0x11,0x02,0x23,0xfe,0xe7,0x95,0x03,0xdf,0xfe,0x64,0x04,0x7d,0x01,0x46,0xfe,0xb9,0x01,0xdc,0x95,0xfe,0xba,0x00,0x00,0x01,0x00,0x75,0x04,0x7c,0x04,0x54,0x06,0x58,0x00,0x09,0x00,0x27,0x40,0x12,0x00,0xea,0x09,0x09,0x05,0x02,0x02,0x06,0xea,0x05, 0x01,0x07,0xbe,0x04,0x09,0x05,0x05,0x04,0x00,0x2f,0x33,0x2f,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x33,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x11,0x21,0x15,0x21,0x11,0x33,0x11,0x21,0x11,0x02,0xb8,0x01,0x9c,0xfc,0x21,0x95,0x01,0x19,0x06,0x57,0xfe,0xba,0x95,0x01,0xdc,0xfe,0xb9,0x01,0x46,0x00,0x00,0x01,0x00,0x00,0xfd,0xff, 0x03,0x57,0x02,0x5e,0x00,0x23,0x00,0x34,0xb1,0x05,0x1f,0xb8,0x05,0x0a,0x40,0x09,0x16,0x1f,0x05,0x02,0x2f,0x1b,0x01,0x1b,0x11,0xb8,0x04,0xfb,0xb6,0x1f,0x0b,0x2f,0x0b,0x02,0x0b,0x00,0xba,0x04,0xfb,0x00,0x02,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x2f,0x5d,0x12,0x39,0x39,0x01,0x2f,0xed,0x32,0x31,0x30,0x25,0x15,0x23,0x22, 0x26,0x27,0x07,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x03,0x57,0x16,0x3f,0x4a,0x19,0x05,0x44,0x78,0xa5,0x61,0x33,0x6c,0x39,0x7c,0x59,0x55,0x74,0x45,0x1e,0x13,0x1f,0x29,0x16,0xa1,0x1d,0x2c,0x0e,0x06,0x1c,0x30,0x49,0x99,0xa7,0x24,0x21,0x01, 0x8c,0xd5,0x8e,0x48,0x16,0x17,0xa5,0x27,0x3d,0x6c,0x92,0x56,0x4b,0x8e,0x88,0x83,0x3f,0x4b,0xa0,0x51,0x23,0x34,0x22,0x10,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x04,0x07,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x05,0x1f,0x02,0x26,0x0b,0x0c,0x00,0x00, 0x00,0x07,0x0f,0x53,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x05,0xb9,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x04,0xaf,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0a,0x6d,0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57, 0x02,0x5e,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x5b,0x01,0x90,0x00,0x00,0xff,0xff,0x00,0x00,0xfd,0xfb,0x03,0x57,0x02,0x5e,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0xf2,0xfe,0x00,0xff,0xff,0x00,0x00,0xfd,0xe1,0x04,0x31,0x02,0x5e,0x02,0x26,0x0b,0x0c,0x00,0x00,0x01,0x07,0x0a,0x6d,0x02,0x09,0xf7,0x65, 0x00,0x0a,0xb4,0x01,0x2f,0x25,0x01,0x25,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xfb,0x03,0x57,0x02,0x5e,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0xf2,0xfe,0x00,0x00,0x06,0x0f,0x50,0xce,0x05,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x04,0x07,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x9a, 0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x05,0x1f,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x05,0x1f,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x9a,0x03,0x57,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x04,0xbc,0x02,0x26,0x0b,0x0c, 0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0x9a,0xfc,0xd3,0xff,0xff,0x00,0xab,0xff,0xea,0x03,0x57,0x03,0xce,0x02,0x06,0x09,0x28,0x00,0x00,0xff,0xff,0x00,0xa1,0xff,0xf2,0x04,0x02,0x03,0xd7,0x02,0x06,0x08,0xf3,0x00,0x00,0x00,0x03,0x00,0x79,0xfe,0x1e,0x06,0xf3,0x06,0x02,0x00,0x13,0x00,0x37,0x00,0x3b,0x00,0x1f,0x40,0x0e,0x28,0x23, 0x37,0x0a,0x00,0x23,0x00,0x23,0x00,0x38,0x3a,0x00,0x38,0x1b,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xd6,0xcd,0x11,0x33,0x31,0x30,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x13,0x26,0x26,0x35,0x34,0x3e,0x04,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x15,0x36,0x33,0x32,0x1e,0x02,0x15, 0x14,0x0e,0x04,0x15,0x14,0x16,0x17,0x13,0x09,0x02,0x03,0x91,0x16,0x26,0x1c,0x10,0x11,0x1d,0x25,0x15,0x16,0x26,0x1d,0x10,0x12,0x1d,0x26,0x5b,0x08,0x13,0x2b,0x40,0x4b,0x40,0x2b,0x34,0x57,0x72,0x3e,0x87,0x7c,0x67,0x89,0x24,0x40,0x30,0x1c,0x2a,0x3e,0x49,0x3e,0x2a,0x0c,0x0b,0x78,0xfc,0xc3,0x03,0x3d,0x03,0x3d,0x89,0x12,0x1d, 0x25,0x14,0x15,0x26,0x1d,0x11,0x12,0x1d,0x26,0x14,0x16,0x26,0x1c,0x10,0x01,0x63,0x15,0x3d,0x25,0x2d,0x49,0x45,0x44,0x4f,0x5f,0x3d,0x40,0x60,0x40,0x21,0x54,0x9e,0x6d,0x12,0x24,0x35,0x22,0x2e,0x4d,0x46,0x43,0x4a,0x54,0x34,0x22,0x43,0x15,0xfd,0x44,0x03,0xf2,0x03,0xf2,0xfc,0x0e,0x00,0x00,0x01,0x00,0x3f,0x04,0xc1,0x03,0x26, 0x05,0xba,0x00,0x17,0x00,0x1e,0x40,0x0e,0x0c,0x00,0x0d,0x07,0x96,0x12,0x12,0x17,0x96,0x0c,0x0f,0x02,0x01,0x02,0x00,0x2f,0x5d,0x33,0xed,0x32,0x2f,0xed,0x01,0x2f,0xc4,0xcd,0x31,0x30,0x01,0x15,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x33,0x03,0x26,0x29,0x3f,0x88,0x81,0x71,0x29, 0x16,0x22,0x18,0x0c,0x80,0x18,0x33,0x53,0x3a,0x38,0x7e,0x7f,0x7d,0x37,0x05,0x40,0x7f,0x26,0x2e,0x26,0x13,0x21,0x2d,0x19,0x2f,0x5a,0x46,0x2a,0x26,0x2e,0x26,0x00,0xff,0xff,0x00,0x5e,0xff,0x3f,0x06,0x25,0x05,0xb2,0x02,0x06,0x00,0x34,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x29,0x04,0x10,0x04,0x18,0x02,0x06,0x00,0x54,0x00,0x00, 0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x60,0x05,0x9a,0x02,0x06,0x00,0x3a,0x00,0x00,0xff,0xff,0x00,0x18,0x00,0x00,0x05,0xb0,0x04,0x00,0x02,0x06,0x00,0x5a,0x00,0x00,0x00,0x01,0x00,0xb0,0xff,0xe8,0x04,0x9d,0x05,0xb1,0x00,0x36,0x00,0x57,0x40,0x2e,0x29,0x7d,0x16,0x2f,0x7d,0x0b,0x2c,0x11,0x16,0x01,0x11,0x16,0x0b,0x0b,0x16,0x11, 0x01,0x04,0x38,0x1d,0x7e,0x1e,0x2c,0x10,0x11,0x11,0x10,0x92,0x59,0x11,0x11,0x06,0x24,0x34,0x06,0x91,0x59,0x34,0x13,0x24,0x19,0x91,0x59,0x24,0x04,0x1e,0x00,0x2f,0x3f,0x2b,0x00,0x18,0x3f,0x2b,0x11,0x12,0x00,0x39,0x18,0x2f,0x2b,0x11,0x12,0x00,0x39,0x01,0x18,0x2f,0xe1,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10, 0xe1,0x10,0xe1,0x31,0x30,0x25,0x35,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x35,0x3e,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x04,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x01,0xf6,0x17,0x3a,0x3e,0x40,0x1d,0x3c,0x62,0x46,0x27,0x37,0x71, 0xab,0x74,0x4c,0x7a,0x56,0x2f,0x84,0x77,0x8e,0x90,0xa8,0x4f,0x83,0xa8,0x59,0x5e,0x99,0x6d,0x3b,0x9c,0x98,0x01,0xaf,0x43,0x74,0x9e,0x5c,0x56,0x72,0x0d,0xad,0x0c,0x15,0x11,0x09,0x21,0x40,0x61,0x40,0x41,0x6e,0x54,0x34,0x07,0x7a,0x09,0x2b,0x45,0x61,0x3f,0x66,0x63,0x8d,0x9d,0xfc,0x0f,0x04,0x09,0x79,0xa2,0x63,0x2a,0x2f,0x57, 0x78,0x4a,0x86,0xae,0x29,0x05,0x47,0xfe,0xb3,0x5b,0x93,0x66,0x37,0x16,0xff,0xff,0xfc,0x8c,0x04,0xa7,0xff,0x4c,0x07,0x68,0x00,0x07,0x00,0x0d,0xfc,0x40,0x01,0xce,0xff,0xff,0x00,0x4a,0xff,0xec,0x06,0xd9,0x05,0xb0,0x00,0x26,0x00,0xf0,0xfa,0x00,0x00,0x27,0x00,0xbc,0x03,0x03,0x00,0x00,0x01,0x07,0x00,0xf2,0x04,0x4b,0xfd,0xb9, 0x00,0x07,0xb2,0x02,0x30,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x8d,0xff,0xec,0x06,0xd7,0x05,0xae,0x00,0x26,0x00,0xf1,0x25,0x00,0x00,0x27,0x00,0xbc,0x03,0x01,0x00,0x00,0x01,0x07,0x00,0xf2,0x04,0x49,0xfd,0xb9,0x00,0x07,0xb2,0x02,0x43,0x2d,0x00,0x3f,0x35,0x00,0x00,0x01,0x00,0x96,0x01,0x08,0x06,0x00,0x03,0xa4,0x00,0x09, 0x00,0x1b,0x40,0x0c,0x09,0x08,0x01,0x07,0x03,0x04,0x02,0x05,0x04,0x00,0xbe,0x09,0x00,0x2f,0xed,0x01,0x2f,0x2f,0xcd,0x11,0x17,0x39,0x2f,0x31,0x30,0x01,0x21,0x17,0x15,0x01,0x35,0x01,0x15,0x07,0x21,0x06,0x00,0xfb,0x5a,0x7b,0xfe,0xc1,0x01,0x3f,0x7d,0x04,0xa8,0x02,0x12,0x76,0x94,0x01,0x4c,0x04,0x01,0x4c,0x94,0x78,0x00,0x01, 0x00,0x96,0xff,0xf4,0x03,0x31,0x05,0x5e,0x00,0x09,0x00,0x10,0xb6,0x08,0x01,0x07,0x03,0x03,0x04,0x00,0x00,0x2f,0x2f,0xcd,0x17,0x39,0x31,0x30,0x05,0x11,0x07,0x23,0x01,0x33,0x01,0x23,0x27,0x11,0x01,0xa0,0x77,0x93,0x01,0x4b,0x04,0x01,0x4c,0x93,0x79,0x0c,0x04,0xa4,0x79,0x01,0x3f,0xfe,0xc1,0x7b,0xfb,0x5a,0x00,0x01,0x00,0xe7, 0x01,0x08,0x06,0x52,0x03,0xa4,0x00,0x09,0x00,0x17,0x40,0x0a,0x01,0x02,0x08,0x03,0x07,0x05,0x00,0x09,0xbe,0x00,0x00,0x2f,0xed,0x01,0x2f,0x2f,0xcd,0x17,0x39,0x31,0x30,0x13,0x21,0x27,0x35,0x01,0x15,0x01,0x35,0x37,0x21,0xe7,0x04,0xa6,0x7b,0x01,0x40,0xfe,0xc0,0x79,0xfb,0x5c,0x02,0x98,0x78,0x94,0xfe,0xb4,0x04,0xfe,0xb4,0x94, 0x76,0x00,0x00,0x01,0x00,0x96,0xff,0xf6,0x03,0x31,0x05,0x60,0x00,0x09,0x00,0x10,0xb6,0x09,0x01,0x02,0x08,0x03,0x06,0x05,0x00,0x2f,0xcd,0x17,0x39,0x2f,0x31,0x30,0x01,0x11,0x37,0x33,0x01,0x23,0x01,0x33,0x17,0x11,0x02,0x25,0x79,0x93,0xfe,0xb4,0x04,0xfe,0xb5,0x93,0x77,0x05,0x60,0xfb,0x58,0x7d,0xfe,0xc1,0x01,0x3f,0x7b,0x04, 0xa6,0x00,0x00,0x01,0x00,0x96,0x01,0x08,0x06,0x50,0x03,0xa4,0x00,0x0f,0x00,0x1f,0x40,0x0f,0x01,0x0a,0x0b,0x03,0x00,0x0e,0x09,0x02,0x08,0x03,0x03,0x06,0x02,0xbe,0x09,0x00,0x2f,0xed,0x01,0x2f,0xcd,0x17,0x39,0x2f,0xcd,0x17,0x39,0x31,0x30,0x01,0x37,0x21,0x17,0x15,0x01,0x35,0x01,0x15,0x07,0x21,0x27,0x35,0x01,0x15,0x01,0x05, 0x10,0x79,0xfb,0xd1,0x7b,0xfe,0xc1,0x01,0x3f,0x7d,0x04,0x33,0x7b,0x01,0x40,0xfe,0xc0,0x01,0x9c,0x76,0x76,0x94,0x01,0x4c,0x04,0x01,0x4c,0x94,0x78,0x78,0x94,0xfe,0xb4,0x04,0xfe,0xb4,0xff,0xff,0x00,0x33,0x00,0x00,0x04,0xf8,0x05,0x9a,0x02,0x06,0x00,0xa9,0x00,0x00,0x00,0x01,0x00,0xe6,0x00,0x00,0x04,0x92,0x03,0xac,0x00,0x05, 0x00,0x13,0xb7,0x02,0xbd,0x05,0x03,0x02,0xbe,0x05,0x00,0x00,0x2f,0x2f,0xed,0x01,0x2f,0x2f,0xed,0x31,0x30,0x13,0x33,0x11,0x21,0x15,0x21,0xe6,0x84,0x03,0x28,0xfc,0x54,0x03,0xac,0xfc,0xd7,0x83,0x00,0x01,0x00,0xe6,0x00,0x6a,0x04,0xb7,0x04,0x4f,0x00,0x19,0x00,0x1e,0x40,0x0d,0x13,0x14,0x14,0x1b,0x06,0x07,0x00,0x0d,0x14,0x10, 0x07,0x01,0x07,0x00,0x2f,0x5d,0x33,0x2f,0xcd,0x01,0x2f,0xcd,0x12,0x39,0x2f,0xcd,0x31,0x30,0x01,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x02,0xc8,0x48,0x7f,0x5f,0x38,0x84,0x55,0x8a,0xb0,0x5a,0x5d,0xb0,0x88,0x53,0x84,0x3c,0x64,0x83,0x03,0xd1,0x31,0x65,0x9a, 0x69,0xfe,0x32,0x01,0xcf,0x8a,0xc9,0x83,0x40,0x40,0x83,0xc9,0x8a,0xfe,0x31,0x01,0xce,0x66,0x99,0x67,0x33,0x00,0x00,0x03,0x00,0xe6,0x00,0x70,0x04,0xac,0x04,0x3a,0x00,0x13,0x00,0x27,0x00,0x3b,0x00,0x2e,0x40,0x17,0x37,0xaf,0x2d,0x23,0xaf,0x19,0x2d,0x19,0x2d,0x19,0x3d,0x0f,0xaf,0x05,0x28,0xb0,0x32,0x10,0x1e,0x0a,0xb0,0x14, 0x00,0x00,0x2f,0x32,0xed,0x32,0x3f,0xed,0x01,0x2f,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x31,0x30,0x25,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0x55,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x02,0xcf,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0xfe,0x76,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x70,0x12,0x1e,0x29,0x17,0x17,0x29, 0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x02,0xe9,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x01,0x00,0xe6,0x00,0x6a,0x05,0x38,0x04,0x3b,0x00,0x1b,0x00,0x2e,0x40,0x16,0x15,0x0f,0x1a,0x13, 0x16,0xea,0x08,0x05,0x0f,0xbe,0x0e,0x0e,0x07,0x1a,0xbe,0x1b,0x1b,0x16,0x06,0xbe,0x13,0x07,0x00,0x2f,0x33,0xed,0x32,0x32,0x2f,0xed,0x11,0x33,0x2f,0xed,0x01,0x2f,0x33,0xed,0x32,0x2f,0x33,0x33,0x31,0x30,0x25,0x22,0x2e,0x02,0x27,0x23,0x35,0x33,0x3e,0x03,0x33,0x21,0x15,0x21,0x22,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x33,0x21, 0x15,0x03,0xa8,0x6a,0xb3,0x87,0x53,0x0a,0xc1,0xc1,0x0c,0x5b,0x8a,0xb0,0x60,0x01,0x90,0xfe,0x80,0xad,0xc1,0x11,0x02,0xff,0xfd,0x01,0x11,0xcb,0xc1,0x01,0x62,0x6a,0x37,0x6b,0x9f,0x69,0x84,0x68,0x9d,0x69,0x35,0x84,0x8d,0x92,0x84,0x93,0x93,0x84,0x00,0x01,0x00,0xa5,0x00,0x00,0x06,0x3f,0x05,0x9a,0x00,0x03,0x00,0x0d,0xb3,0x03, 0x02,0x03,0x00,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x13,0x21,0x11,0x21,0xa5,0x05,0x9a,0xfa,0x66,0x05,0x9a,0xfa,0x66,0x00,0x01,0x00,0xa5,0x00,0x00,0x07,0x5b,0x04,0xac,0x00,0x03,0x00,0x0d,0xb3,0x03,0x02,0x03,0x00,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x13,0x21,0x11,0x21,0xa5,0x06,0xb6,0xf9,0x4a,0x04,0xac,0xfb,0x54, 0x00,0x01,0x00,0x50,0x00,0x00,0x06,0x94,0x05,0x9a,0x00,0x02,0x00,0x0d,0xb3,0x01,0x02,0x00,0x02,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x01,0x01,0x21,0x03,0x72,0x03,0x22,0xf9,0xbc,0x05,0x9a,0xfa,0x66,0x00,0x01,0x00,0xa5,0x01,0x61,0x06,0x3f,0x04,0x39,0x00,0x02,0x00,0x0d,0xb3,0x01,0x00,0x02,0x01,0x00,0x2f,0x2f,0x01,0x2f, 0x2f,0x31,0x30,0x01,0x01,0x11,0x06,0x3f,0xfa,0x66,0x02,0xcd,0xfe,0x94,0x02,0xd8,0x00,0x01,0x00,0x50,0x00,0x00,0x06,0x94,0x05,0x9a,0x00,0x02,0x00,0x0d,0xb3,0x01,0x00,0x02,0x00,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x13,0x21,0x01,0x50,0x06,0x44,0xfc,0xde,0x05,0x9a,0xfa,0x66,0x00,0x00,0x01,0x00,0xa5,0x01,0x61,0x06,0x3f, 0x04,0x39,0x00,0x02,0x00,0x0d,0xb3,0x01,0x02,0x01,0x00,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x01,0x11,0x01,0x06,0x3f,0xfa,0x66,0x04,0x39,0xfd,0x28,0x01,0x6c,0x00,0x02,0x00,0x8c,0xff,0xe7,0x06,0x58,0x05,0xb2,0x00,0x1b,0x00,0x33,0x00,0x15,0xb7,0x0e,0x28,0x1c,0x00,0x21,0x15,0x2f,0x07,0x00,0x2f,0xcd,0x2f,0xcd,0x01,0x2f, 0xcd,0x2f,0xcd,0x31,0x30,0x13,0x34,0x3e,0x04,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x04,0x37,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x8c,0x35,0x60,0x87,0xa5,0xbe,0x66,0x66,0xbe,0xa5,0x88,0x61,0x35,0x35,0x61,0x88,0xa5,0xbe,0x66,0x67,0xbd,0xa5,0x87,0x60,0x35,0x7c,0x61, 0xa7,0xe1,0x80,0x55,0x9f,0x89,0x71,0x51,0x2c,0x2c,0x51,0x71,0x89,0x9f,0x55,0x80,0xe1,0xa7,0x61,0x02,0xcc,0x66,0xbe,0xa5,0x87,0x61,0x35,0x35,0x61,0x87,0xa5,0xbe,0x66,0x67,0xbd,0xa5,0x87,0x60,0x35,0x35,0x60,0x87,0xa5,0xbe,0x66,0x80,0xe1,0xa7,0x61,0x2c,0x50,0x70,0x8a,0x9e,0x55,0x55,0x9f,0x89,0x71,0x50,0x2c,0x61,0xa8,0xe1, 0x00,0x02,0x02,0x0d,0x00,0x00,0x04,0xd7,0x05,0x9a,0x00,0x03,0x00,0x17,0x00,0x1a,0x40,0x0a,0x0e,0x02,0x04,0x03,0x13,0x09,0x13,0x09,0x03,0x00,0x00,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x01,0x2f,0xcd,0xdd,0xcd,0x31,0x30,0x01,0x21,0x11,0x21,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x02,0x0d, 0x02,0xca,0xfd,0x36,0x64,0x28,0x46,0x5d,0x36,0x35,0x5d,0x46,0x29,0x29,0x46,0x5d,0x35,0x36,0x5d,0x46,0x28,0x05,0x9a,0xfa,0x66,0x02,0xcd,0x35,0x5e,0x46,0x28,0x28,0x46,0x5e,0x35,0x35,0x5e,0x46,0x28,0x28,0x46,0x5e,0x00,0x03,0x00,0xa5,0x00,0x00,0x06,0x3f,0x05,0x9a,0x00,0x03,0x00,0x1d,0x00,0x31,0x00,0x1f,0x40,0x0d,0x1e,0x04, 0x03,0x28,0x12,0x02,0x2d,0x0b,0x03,0x22,0x23,0x17,0x00,0x00,0x2f,0xdd,0xce,0x3f,0xdd,0xce,0x01,0x2f,0xdd,0xce,0x2f,0xdd,0xce,0x31,0x30,0x13,0x21,0x11,0x21,0x13,0x14,0x1e,0x04,0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x17,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0xa5, 0x05,0x9a,0xfa,0x66,0x64,0x2c,0x50,0x70,0x89,0x9d,0x55,0x55,0x9f,0x89,0x71,0x51,0x2c,0x61,0xa8,0xe2,0x80,0x55,0x9d,0x89,0x70,0x50,0x2c,0x67,0x51,0x8b,0xba,0x6a,0x6b,0xbc,0x8c,0x51,0x51,0x8c,0xbc,0x6b,0x6a,0xba,0x8b,0x51,0x05,0x9a,0xfa,0x66,0x02,0xcb,0x55,0x9d,0x89,0x70,0x50,0x2c,0x2c,0x50,0x70,0x89,0x9d,0x55,0x80,0xe2, 0xa8,0x61,0x2c,0x51,0x71,0x89,0x9f,0x55,0x6b,0xbc,0x8c,0x51,0x51,0x8c,0xbc,0x6b,0x6a,0xbb,0x8b,0x50,0x50,0x8b,0xbb,0x00,0x00,0x01,0x00,0x5e,0x00,0x00,0x05,0x1c,0x05,0xb2,0x00,0x2b,0x00,0x1e,0x40,0x0d,0x0f,0x1c,0x1c,0x07,0x24,0x07,0x0c,0x1f,0x1f,0x16,0x22,0x00,0x26,0x00,0x3f,0x3f,0x39,0x2f,0x33,0x01,0x2f,0x2f,0x12,0x39, 0x2f,0xcd,0x31,0x30,0x01,0x1e,0x05,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x1e,0x03,0x17,0x15,0x21,0x35,0x3e,0x03,0x37,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x02,0xc1,0x2c,0x7b,0x86,0x84,0x69,0x41,0x34,0x55,0x6d,0x39,0x37,0x63,0x27,0x04,0x15,0x26,0x36,0x25,0xfd,0xee,0x25,0x36,0x26,0x15,0x04,0x27,0x63, 0x37,0x39,0x6d,0x55,0x34,0x41,0x69,0x84,0x86,0x7b,0x2c,0x05,0xb2,0x34,0x6b,0x76,0x82,0x93,0xa6,0x5f,0x52,0x7e,0x55,0x2c,0x1c,0x20,0x22,0x4c,0x4c,0x4a,0x1f,0x4b,0x4b,0x1f,0x4a,0x4c,0x4c,0x22,0x20,0x1c,0x2c,0x55,0x7e,0x52,0x5f,0xa6,0x93,0x82,0x76,0x6c,0x33,0x00,0x00,0x01,0x00,0x5e,0x00,0x00,0x05,0x1c,0x05,0x9a,0x00,0x38, 0x00,0x1c,0x40,0x0b,0x32,0x06,0x06,0x10,0x28,0x10,0x2d,0x0b,0x0b,0x1c,0x00,0x00,0x2f,0x2f,0x39,0x2f,0x33,0x01,0x2f,0x2f,0x12,0x39,0x2f,0xcd,0x31,0x30,0x21,0x35,0x3e,0x03,0x35,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02, 0x23,0x22,0x2e,0x02,0x27,0x14,0x1e,0x02,0x17,0x15,0x01,0xb4,0x1c,0x36,0x2a,0x1a,0x13,0x25,0x2a,0x31,0x1f,0x41,0x73,0x55,0x31,0x2d,0x53,0x73,0x45,0x10,0x2d,0x52,0x72,0x46,0x46,0x72,0x52,0x2d,0x10,0x45,0x73,0x53,0x2d,0x31,0x55,0x73,0x41,0x1f,0x31,0x2a,0x25,0x13,0x19,0x2a,0x36,0x1d,0x4b,0x17,0x46,0x5c,0x72,0x44,0x0d,0x14, 0x0f,0x08,0x2c,0x51,0x74,0x48,0x41,0x71,0x55,0x32,0x01,0x34,0x37,0x40,0x73,0x55,0x32,0x32,0x55,0x73,0x40,0x37,0x34,0x01,0x32,0x55,0x71,0x41,0x48,0x74,0x51,0x2c,0x08,0x0f,0x14,0x0d,0x44,0x72,0x5c,0x46,0x17,0x4b,0x00,0x01,0x00,0x5e,0x00,0x78,0x05,0x1c,0x05,0x23,0x00,0x23,0x00,0x0d,0xb3,0x05,0x14,0x19,0x0c,0x00,0x2f,0x2f, 0x01,0x2f,0x2f,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x07,0x23,0x2e,0x05,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x33,0x3e,0x03,0x03,0xea,0x3b,0x6f,0x55,0x33,0x40,0x68,0x83,0x86,0x7d,0x2d,0x09,0x2d,0x7c,0x86,0x83,0x68,0x40,0x33,0x55,0x6f,0x3b,0x39,0x5b,0x49,0x37,0x14,0x09,0x14,0x38,0x49,0x5b,0x05,0x23, 0x2b,0x57,0x84,0x5a,0x64,0xad,0x98,0x85,0x79,0x6f,0x35,0x35,0x6f,0x79,0x85,0x98,0xad,0x64,0x5a,0x84,0x57,0x2b,0x1e,0x33,0x41,0x22,0x22,0x41,0x33,0x1e,0x00,0x01,0x00,0xcd,0x00,0x00,0x04,0xae,0x05,0x9a,0x00,0x03,0x00,0x0d,0xb3,0x02,0x00,0x03,0x01,0x00,0x2f,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x13,0x09,0x02,0xcd,0x01,0xf0,0x01, 0xf1,0xfe,0x0f,0x02,0xcc,0x02,0xce,0xfd,0x32,0xfd,0x34,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0x2c,0x05,0xb2,0x00,0x16,0x00,0x2d,0x00,0x2d,0x40,0x17,0x13,0x12,0x7e,0x10,0x28,0x28,0x2f,0x1c,0x7d,0x05,0x13,0x10,0x03,0x17,0x91,0x0f,0x0a,0x04,0x21,0x91,0x14,0x00,0x13,0x00,0x3f,0x32,0xed,0x3f,0x33,0xed,0x3f,0x2f,0x01,0x2f, 0xe1,0x12,0x39,0x2f,0x33,0xe1,0x33,0x31,0x30,0x05,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x35,0x33,0x11,0x23,0x35,0x06,0x06,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x35,0x11,0x34,0x2e,0x02,0x02,0xb9,0x86,0xde,0x9f,0x58,0x5c,0xaa,0xef,0x94,0x4e,0x80,0x66,0x4d,0x1c,0xa8, 0xa8,0x40,0xe1,0x80,0x6c,0xad,0x7a,0x42,0x42,0x79,0xa9,0x66,0x33,0x67,0x5f,0x53,0x3d,0x23,0x3b,0x6e,0x99,0x18,0x6a,0xbf,0x01,0x0b,0xa0,0xac,0x01,0x18,0xc6,0x6c,0x21,0x39,0x4b,0x2a,0xb7,0xfa,0x66,0xd6,0x6d,0x81,0x05,0x32,0x56,0x9c,0xd9,0x84,0x84,0xd9,0x9a,0x55,0x13,0x2c,0x48,0x6a,0x90,0x5d,0x01,0x0d,0x6c,0xa2,0x6c,0x36, 0xff,0xff,0x00,0x0e,0x00,0x00,0x04,0x9a,0x04,0x18,0x02,0x06,0x05,0xef,0x00,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x08,0x74,0x05,0xb2,0x00,0x2c,0x00,0x54,0x40,0x2b,0x25,0x24,0x1c,0x2c,0x01,0x00,0x19,0x15,0x14,0x06,0x0a,0x09,0x10,0x24,0x2c,0x19,0x06,0x10,0x10,0x06,0x19,0x2c,0x24,0x05,0x2e,0x0c,0x0b,0x27,0x92,0x40,0x25,0x80, 0x21,0x04,0x14,0x05,0x0b,0x03,0x18,0x0f,0x01,0x0a,0x12,0x00,0x3f,0x33,0x33,0x33,0x3f,0x33,0x33,0x3f,0x1a,0xcc,0x1a,0xed,0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x11,0x33,0x31,0x30,0x21,0x23,0x01,0x26,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x33,0x01, 0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x13,0x3e,0x03,0x33,0x32,0x16,0x17,0x23,0x26,0x23,0x22,0x0e,0x02,0x07,0x05,0xcb,0xc5,0xfe,0xd9,0x0a,0x0b,0x02,0x04,0x06,0x14,0xfe,0xd7,0xc3,0xfe,0x5c,0xb9,0x01,0x31,0x14,0x04,0x05,0x02,0x10,0x0d,0x01,0x3d,0xa1,0x01,0x30,0x10,0x08,0x04,0x05,0x16,0xe1, 0x12,0x32,0x45,0x5c,0x3c,0x69,0x79,0x0b,0x9a,0x0c,0x47,0x16,0x23,0x1b,0x17,0x0b,0x04,0x18,0x22,0x48,0x28,0x47,0x49,0xfb,0xe6,0x05,0x9a,0xfb,0xb4,0x45,0x4b,0x1a,0x48,0x2e,0x04,0x4c,0xfb,0xac,0x39,0x4d,0x35,0x55,0x03,0x54,0x46,0x68,0x44,0x22,0x79,0x79,0x63,0x16,0x29,0x3d,0x27,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x06,0x97, 0x04,0x18,0x00,0x2c,0x00,0x54,0x40,0x2b,0x0a,0x09,0x11,0x15,0x14,0x06,0x01,0x00,0x19,0x1d,0x2c,0x26,0x25,0x11,0x06,0x19,0x2c,0x25,0x25,0x2c,0x19,0x06,0x11,0x05,0x2e,0x0c,0x0b,0x29,0x95,0x40,0x26,0x80,0x22,0x10,0x14,0x05,0x0b,0x0f,0x18,0x10,0x01,0x0a,0x15,0x00,0x3f,0x33,0x33,0x33,0x3f,0x33,0x33,0x3f,0x1a,0xcc,0x1a,0xed, 0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x31,0x30,0x21,0x23,0x03,0x26,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x36,0x37,0x13,0x3e,0x03,0x33,0x32,0x16,0x17,0x23,0x26, 0x26,0x23,0x22,0x06,0x07,0x04,0x7d,0xaa,0xd3,0x06,0x08,0x02,0x04,0x03,0x12,0xe5,0xa4,0xfe,0xca,0xac,0xd4,0x05,0x07,0x02,0x08,0x03,0x0f,0xec,0x96,0xd4,0x0b,0x04,0x08,0x01,0x09,0x07,0x9a,0x0d,0x26,0x38,0x4e,0x35,0x5b,0x6b,0x0b,0x96,0x04,0x23,0x1c,0x21,0x2a,0x14,0x02,0xdd,0x15,0x30,0x1a,0x24,0x39,0xfd,0x21,0x04,0x00,0xfc, 0xfe,0x11,0x2e,0x1d,0x2d,0x31,0x03,0x00,0xfc,0xfc,0x26,0x36,0x14,0x2e,0x1a,0x02,0x46,0x32,0x4f,0x38,0x1d,0x6d,0x6f,0x2a,0x2a,0x3f,0x46,0x00,0x00,0x01,0x00,0x96,0x03,0x82,0x03,0x31,0x05,0xd3,0x00,0x09,0x00,0x0d,0xb3,0x09,0x00,0x00,0x04,0x00,0x2f,0xcd,0x01,0x2f,0xcd,0x31,0x30,0x01,0x11,0x07,0x23,0x01,0x33,0x01,0x23,0x27, 0x11,0x01,0xa0,0x77,0x93,0x01,0x4b,0x04,0x01,0x4c,0x93,0x79,0x03,0x82,0x01,0x8b,0x79,0x01,0x3f,0xfe,0xc1,0x7b,0xfe,0x73,0x00,0x01,0x00,0x96,0x03,0x82,0x03,0x31,0x05,0xd3,0x00,0x09,0x00,0x0d,0xb3,0x00,0x09,0x04,0x09,0x00,0x2f,0xcd,0x01,0x2f,0xcd,0x31,0x30,0x01,0x11,0x37,0x33,0x01,0x23,0x01,0x33,0x17,0x11,0x02,0x25,0x79, 0x93,0xfe,0xb4,0x04,0xfe,0xb5,0x93,0x77,0x05,0xd3,0xfe,0x73,0x7b,0xfe,0xc1,0x01,0x3f,0x79,0x01,0x8b,0x00,0x02,0x00,0xb4,0x03,0x83,0x01,0x92,0x06,0x89,0x00,0x03,0x00,0x0f,0x00,0x20,0x40,0x0f,0x00,0x03,0x03,0x0d,0x07,0x02,0x50,0x0a,0x01,0x0a,0x00,0x04,0x01,0x04,0x03,0x00,0x2f,0xd4,0x5d,0xdd,0x5d,0xce,0x01,0x2f,0xcd,0x33, 0x2f,0xcd,0x31,0x30,0x01,0x03,0x23,0x03,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x77,0x13,0x87,0x12,0x58,0x2e,0x41,0x41,0x2e,0x2d,0x42,0x42,0x06,0x89,0xfe,0x2d,0x01,0xd3,0xfc,0xfa,0x40,0x2e,0x2e,0x41,0x41,0x2e,0x2e,0x40,0x00,0x00,0x02,0x00,0xb4,0x03,0x83,0x01,0x92,0x06,0x89,0x00,0x03,0x00,0x0f, 0x00,0x20,0x40,0x0f,0x03,0x00,0x00,0x07,0x0d,0x02,0x5f,0x0a,0x01,0x0a,0x00,0x03,0x01,0x03,0x04,0x00,0x2f,0xc4,0x5d,0xdd,0x5d,0xce,0x01,0x2f,0xcd,0x33,0x2f,0xcd,0x31,0x30,0x13,0x13,0x33,0x13,0x03,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0xcb,0x12,0x87,0x13,0x54,0x2d,0x42,0x42,0x2d,0x2e,0x41,0x41,0x03,0x83, 0x01,0xd3,0xfe,0x2d,0x03,0x06,0x40,0x2e,0x2e,0x41,0x41,0x2e,0x2e,0x40,0x00,0x02,0x00,0xb4,0x01,0xd5,0x01,0x92,0x04,0xdb,0x00,0x03,0x00,0x0f,0x00,0x23,0x40,0x0f,0x03,0x00,0x00,0x07,0x0d,0x01,0x5f,0x0a,0x01,0x0a,0x00,0x00,0x01,0x00,0x04,0xb8,0x01,0x3a,0x00,0x3f,0xc4,0x5d,0xdd,0x5d,0xce,0x01,0x2f,0xcd,0x33,0x2f,0xcd,0x31, 0x30,0x13,0x13,0x33,0x13,0x03,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0xcb,0x12,0x87,0x13,0x54,0x2d,0x42,0x42,0x2d,0x2e,0x41,0x41,0x01,0xd5,0x01,0xd3,0xfe,0x2d,0x03,0x06,0x40,0x2e,0x2e,0x41,0x41,0x2e,0x2e,0x40,0x00,0x00,0x01,0x00,0x63,0xfe,0x3e,0x02,0x95,0xff,0x89,0x00,0x06,0x00,0x18,0x40,0x0c,0x00,0x04, 0x04,0x80,0x0f,0x05,0x1f,0x05,0x2f,0x05,0x03,0x05,0x00,0x2f,0x5d,0x1a,0xcd,0x01,0x2f,0xc4,0x31,0x30,0x01,0x23,0x27,0x07,0x23,0x13,0x33,0x02,0x95,0x78,0xa4,0xa6,0x70,0xd6,0x86,0xfe,0x3e,0xe5,0xe5,0x01,0x4b,0x00,0xff,0xff,0x00,0x70,0xff,0xea,0x01,0x50,0x04,0x16,0x02,0x06,0x00,0x1d,0x00,0x00,0x00,0x02,0x00,0xe8,0x01,0x3e, 0x03,0x9a,0x03,0x6c,0x00,0x03,0x00,0x07,0x00,0x1a,0x40,0x0b,0x00,0x01,0x04,0x05,0x04,0x05,0xbe,0x06,0x01,0xbe,0x02,0x00,0x2f,0xed,0xd6,0xed,0x01,0x2f,0x2f,0x11,0x39,0x39,0x31,0x30,0x01,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x03,0x9a,0xfd,0x4e,0x02,0xb2,0xfd,0x4e,0x02,0xb2,0x02,0xe8,0x84,0xfd,0xd2,0x84,0x00,0x01,0x00,0x94, 0x02,0xc3,0x01,0x43,0x05,0x9a,0x00,0x03,0x00,0x1c,0x40,0x0e,0x00,0x7d,0x03,0x04,0x0d,0x06,0x4d,0x03,0x03,0x05,0x04,0x01,0x00,0x03,0x00,0x3f,0xcd,0x11,0x12,0x01,0x39,0x2f,0x2b,0xe1,0x31,0x30,0x01,0x03,0x23,0x03,0x01,0x43,0x1e,0x73,0x1e,0x05,0x9a,0xfd,0x29,0x02,0xd7,0x00,0xff,0xff,0x00,0xa3,0x03,0xdb,0x01,0x34,0x05,0x9a, 0x02,0x06,0x00,0x0a,0x00,0x00,0x00,0x01,0x03,0x9b,0xfe,0x80,0x04,0x36,0x00,0x00,0x00,0x03,0x00,0x0d,0xb3,0x01,0x00,0x03,0x00,0x00,0x2f,0x2f,0x01,0x2f,0xcd,0x31,0x30,0x21,0x33,0x11,0x23,0x03,0x9b,0x9b,0x9b,0xfe,0x80,0x00,0x00,0x01,0x02,0xd6,0xfe,0x8a,0x03,0x64,0x00,0x00,0x00,0x03,0x00,0x0d,0xb3,0x01,0x00,0x03,0x00,0x00, 0x2f,0x2f,0x01,0x2f,0xcd,0x31,0x30,0x21,0x33,0x11,0x23,0x02,0xd6,0x8e,0x8e,0xfe,0x8a,0x00,0x00,0x02,0x00,0x00,0xfd,0xff,0x00,0xb9,0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x2f,0xb9,0x00,0x00,0x01,0x51,0xb2,0x06,0x06,0x0c,0xb8,0x01,0x51,0xb3,0x12,0x12,0x19,0x03,0xbb,0x01,0x55,0x00,0x09,0x00,0x0f,0x01,0x55,0xb2,0x15,0x15,0x19, 0x11,0x00,0x33,0x2f,0xfd,0xde,0xed,0x11,0x01,0x33,0x2f,0xed,0x33,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x35,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0xb9,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0x5a,0x2a,0x31,0x2f,0x2c, 0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x05,0x00,0x00,0xfd,0xff,0x02,0xdd,0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x3b,0x00,0x00,0x17,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x33,0x32,0x16,0x35,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0xb9,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x01,0x14,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x01,0x10,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x33,0x29,0x2a,0x33,0x31, 0x2a,0x2a,0x34,0xfe,0x67,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x2d,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xfe,0xce,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xfe,0xce,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x03,0x00,0x00,0xfd,0xff,0x02,0xe2, 0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x37,0xb9,0x00,0x0c,0x01,0x51,0xb2,0x12,0x12,0x00,0xb8,0x01,0x51,0xb7,0x06,0x1b,0x1a,0x18,0x1b,0x1b,0x09,0x0f,0xbb,0x01,0x55,0x00,0x15,0x00,0x03,0x01,0x55,0xb2,0x09,0x09,0x1d,0x11,0x00,0x33,0x2f,0xfd,0xde,0xed,0x11,0x33,0x2f,0xcd,0x01,0x2f,0xdd,0xde,0xed,0x33,0x2f,0xed,0x30, 0x31,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x25,0x21,0x35,0x21,0x02,0xdd,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0xce,0xfe,0x50,0x01,0xb0,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xfe,0xce, 0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xb1,0x66,0x00,0x00,0x03,0x00,0x00,0xfd,0xff,0x02,0xe1,0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x1f,0x00,0x40,0xb9,0x00,0x0c,0x01,0x51,0xb2,0x12,0x12,0x00,0xb8,0x01,0x51,0x40,0x0c,0x06,0x1f,0x19,0x1e,0x1c,0x1c,0x1a,0x19,0x1f,0x1f,0x09,0x0f,0xbb,0x01,0x55,0x00,0x15,0x00,0x03,0x01,0x55,0xb2, 0x09,0x09,0x21,0x11,0x00,0x33,0x2f,0xfd,0xde,0xed,0x11,0x33,0x2f,0xdd,0xcd,0x33,0x01,0x2f,0xcd,0xdd,0xdd,0xde,0xed,0x33,0x2f,0xed,0x30,0x31,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x25,0x23,0x15,0x23,0x35,0x23,0x35,0x21,0x02,0xdd,0x33,0x29, 0x2a,0x33,0x31,0x2a,0x2a,0x34,0x04,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0xcf,0xa5,0x66,0xa5,0x01,0xb0,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xfe,0xce,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xb1,0xdf,0xdf,0x66,0x00,0x00,0x01,0x00,0x00,0xff,0x04,0x00,0xb9,0xff,0xbb,0x00,0x0b,0x00,0x1d,0xb9,0x00,0x00,0x01,0x51,0xb3, 0x06,0x06,0x0d,0x03,0xb8,0x01,0x55,0xb2,0x09,0x09,0x0d,0x11,0x00,0x33,0x2f,0xed,0x11,0x01,0x33,0x2f,0xed,0x30,0x31,0x17,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0xb9,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x02,0x00,0x00,0xff,0x04,0x01,0xd6,0xff,0xbb,0x00,0x0b, 0x00,0x17,0x00,0x2f,0xbc,0x00,0x00,0x01,0x51,0x00,0x06,0x00,0x0c,0x01,0x51,0xb3,0x12,0x12,0x19,0x03,0xb8,0x01,0x55,0xb2,0x09,0x09,0x0f,0xb8,0x01,0x55,0xb2,0x15,0x15,0x19,0x11,0x00,0x33,0x2f,0xed,0x33,0x2f,0xed,0x11,0x01,0x33,0x2f,0xfd,0xde,0xed,0x30,0x31,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05, 0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0xd6,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0xe3,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x2d,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x03,0x00,0x00,0xfd,0xff,0x01,0xd6,0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x23, 0x00,0x45,0xb9,0x00,0x00,0x01,0x51,0xb3,0x06,0x06,0x1e,0x0c,0xbb,0x01,0x51,0x00,0x12,0x00,0x18,0x01,0x51,0xb3,0x1e,0x1e,0x25,0x03,0xbe,0x01,0x55,0x00,0x09,0x00,0x1b,0x01,0x55,0x00,0x21,0x00,0x0f,0x01,0x55,0xb4,0x15,0x15,0x21,0x21,0x25,0x11,0x00,0x33,0x2f,0x33,0x2f,0xed,0x10,0xfd,0xde,0xed,0x11,0x01,0x33,0x2f,0xfd,0xde, 0xed,0x12,0x39,0x2f,0xed,0x30,0x31,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x37,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x48,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x8e,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0xe3, 0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xfe,0x5a,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x2d,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x01,0x00,0x00,0xff,0x38,0x01,0xb0,0xff,0x9e,0x00,0x03,0x00,0x11,0xb5,0x00,0x02,0x00,0x02,0x02,0x05,0x11,0x00,0x33,0x2f,0xcd,0x01,0x2f,0xcd,0x30, 0x31,0x05,0x21,0x35,0x21,0x01,0xb0,0xfe,0x50,0x01,0xb0,0xc8,0x66,0x00,0x00,0x01,0x00,0x00,0xfe,0x59,0x01,0xb0,0xff,0x9e,0x00,0x07,0x00,0x1a,0x40,0x0a,0x07,0x01,0x06,0x04,0x02,0x01,0x04,0x06,0x06,0x09,0x11,0x00,0x33,0x2f,0xdd,0x32,0xcd,0x01,0x2f,0xcd,0xdd,0xcd,0x30,0x31,0x05,0x23,0x15,0x23,0x35,0x23,0x35,0x21,0x01,0xb0, 0xa5,0x66,0xa5,0x01,0xb0,0xc8,0xdf,0xdf,0x66,0x00,0x00,0x01,0xff,0xa4,0x05,0x4e,0x00,0x5d,0x06,0x05,0x00,0x0b,0x00,0x17,0xbe,0x00,0x00,0x01,0x51,0x00,0x06,0x00,0x09,0x01,0x55,0x00,0x03,0x05,0x10,0x00,0x3f,0xed,0x01,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x5d,0x33,0x29,0x2a,0x33, 0x31,0x2a,0x2a,0x34,0x05,0xa9,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x03,0x00,0x00,0xfd,0xff,0x02,0x77,0xff,0xbb,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x3d,0xbf,0x00,0x18,0x01,0x51,0x00,0x1e,0x00,0x0c,0x01,0x51,0x00,0x12,0x00,0x00,0x01,0x51,0xb3,0x06,0x06,0x25,0x1b,0xbe,0x01,0x55,0x00,0x21,0x00,0x0f,0x01,0x55,0x00, 0x15,0x00,0x03,0x01,0x55,0xb2,0x09,0x09,0x25,0x11,0x00,0x33,0x2f,0xed,0xdc,0xed,0xdc,0xed,0x11,0x01,0x33,0x2f,0xfd,0xde,0xfd,0xde,0xed,0x30,0x31,0x17,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0xb9,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xdf,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xdf,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xa1,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xaf,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xb0,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x01,0xff,0xa5,0x02,0x18,0x00,0x5e,0x02,0xcf,0x00,0x0b, 0x00,0x15,0xbd,0x00,0x00,0x01,0x51,0x00,0x06,0x00,0x09,0x01,0x55,0x00,0x03,0x00,0x2f,0xed,0x01,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x5e,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x02,0x73,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x01,0xff,0xcd,0xfe,0x09,0x00,0x33,0xff,0xb1, 0x00,0x03,0x00,0x11,0xb5,0x03,0x02,0x00,0x03,0x03,0x05,0x11,0x00,0x33,0x2f,0xcd,0x01,0x2f,0xcd,0x30,0x31,0x13,0x23,0x11,0x33,0x33,0x66,0x66,0xfe,0x09,0x01,0xa8,0x00,0x01,0x00,0x4b,0x04,0x38,0x02,0xe8,0x04,0xcd,0x00,0x03,0x00,0x14,0xb5,0x03,0x05,0x02,0x04,0x01,0x03,0xb8,0x01,0x4a,0x00,0x3f,0xcd,0x11,0x01,0x33,0x11,0x33, 0x30,0x31,0x01,0x21,0x37,0x21,0x02,0xd0,0xfd,0x7b,0x18,0x02,0x85,0x04,0x38,0x95,0x00,0x01,0xfe,0xd2,0x05,0x6b,0x01,0x31,0x05,0xd5,0x00,0x03,0x00,0x0d,0xb3,0x03,0x01,0x03,0x01,0x00,0x2f,0xcd,0x01,0x2f,0xcd,0x30,0x31,0x01,0x21,0x35,0x21,0x01,0x31,0xfd,0xa1,0x02,0x5f,0x05,0x6b,0x6a,0x00,0x01,0x00,0x94,0xff,0x9d,0x01,0x09, 0x05,0x30,0x00,0x03,0x00,0x15,0xbd,0x00,0x03,0x01,0x50,0x00,0x02,0x00,0x03,0x01,0x4b,0x00,0x00,0x00,0x2f,0x3f,0x01,0x2f,0xed,0x30,0x31,0x05,0x23,0x11,0x33,0x01,0x09,0x75,0x75,0x63,0x05,0x93,0x00,0x01,0x02,0x00,0x05,0x4e,0x02,0xb9,0x06,0x05,0x00,0x0b,0x00,0x17,0xbe,0x00,0x00,0x01,0x51,0x00,0x06,0x00,0x09,0x01,0x55,0x00, 0x03,0x05,0x10,0x00,0x3f,0xed,0x01,0x2f,0xed,0x30,0x31,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x02,0xb9,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0xa9,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x01,0xfd,0x3c,0x05,0x4e,0xfd,0xf5,0x06,0x05,0x00,0x0b,0x00,0x17,0xbe,0x00,0x00,0x01,0x51,0x00,0x06,0x00, 0x09,0x01,0x55,0x00,0x03,0x05,0x10,0x00,0x3f,0xed,0x01,0x2f,0xed,0x30,0x31,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0xfd,0xf5,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0xa9,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x02,0x00,0x70,0xff,0xea,0x01,0x50,0x04,0x16,0x00,0x0b,0x00,0x17,0x00,0x36,0x40,0x12, 0x00,0xb0,0x06,0x10,0x12,0xb0,0x0c,0x13,0x09,0x03,0x15,0xaf,0x1f,0x0f,0x2f,0x0f,0x02,0x0f,0xb8,0xff,0xec,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xec,0xb6,0x0b,0x06,0x4d,0x0f,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x71,0xe1,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x03,0x38,0x42,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x42,0xfc,0xb2,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x00,0x01,0xff,0x9c,0x05,0x77,0x00,0x67,0x06,0x40,0x00,0x0b,0x00,0x17,0xbe,0x00, 0x00,0x01,0x51,0x00,0x06,0x00,0x09,0x01,0x55,0x00,0x03,0x05,0x10,0x00,0x3f,0xed,0x01,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x67,0x38,0x2d,0x2e,0x38,0x36,0x2e,0x2e,0x39,0x05,0xdb,0x2e,0x36,0x34,0x30,0x2e,0x37,0x34,0x00,0x00,0x01,0xff,0x9c,0xfe,0x8d,0x00,0x67,0xff,0x56,0x00,0x0b, 0x00,0x19,0xbc,0x00,0x00,0x01,0x51,0x00,0x06,0x00,0x03,0x01,0x57,0xb2,0x09,0x09,0x0d,0x11,0x00,0x33,0x2f,0xed,0x01,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x67,0x38,0x2d,0x2e,0x38,0x36,0x2e,0x2e,0x39,0xfe,0xf1,0x2e,0x36,0x34,0x30,0x2e,0x37,0x34,0x00,0x00,0x01,0x00,0xa5,0x00,0x00, 0x04,0x9a,0x04,0xd4,0x00,0x28,0x00,0x51,0x40,0x0b,0x1e,0x28,0x17,0x00,0x15,0x08,0x16,0x01,0x01,0x00,0x23,0xb8,0x01,0x50,0xb7,0x20,0x20,0x0f,0x2a,0x17,0x16,0x16,0x0e,0xb8,0x01,0x50,0x40,0x0a,0x0f,0x15,0x08,0x1e,0x28,0x04,0x16,0x17,0x17,0x21,0xbb,0x01,0x4a,0x00,0x0f,0x00,0x00,0x01,0x4d,0x00,0x3f,0x32,0x3f,0x33,0x2f,0x33, 0x17,0x39,0x01,0x2f,0xed,0x33,0x11,0x33,0x11,0x12,0x39,0x2f,0xed,0xc4,0x32,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x31,0x30,0x21,0x23,0x2e,0x05,0x27,0x0e,0x03,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x37,0x03,0x37,0x1e,0x03,0x17,0x16,0x17,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x07,0x04,0x9a,0xc5,0x2f,0x51,0x4b,0x4a,0x54, 0x61,0x3c,0x28,0x32,0x1c,0x09,0xa9,0x17,0x34,0x52,0x3c,0xdb,0x8e,0x2d,0x5a,0x54,0x4e,0x22,0x4f,0x46,0xae,0xaa,0x21,0x41,0x61,0x41,0x45,0x75,0x6e,0x6c,0x77,0x88,0x53,0x27,0x4c,0x51,0x5d,0x38,0xfe,0x73,0x01,0x98,0x4c,0x77,0x68,0x5f,0x33,0x01,0x38,0x47,0x3c,0x79,0x74,0x6d,0x30,0x70,0x66,0x63,0xd5,0x01,0x5d,0xfe,0xc1,0x52, 0x85,0x6d,0x5a,0x29,0x00,0x01,0x00,0x50,0x00,0x00,0x04,0x3c,0x04,0xde,0x00,0x24,0x00,0x38,0xb2,0x07,0x07,0x00,0xb8,0x01,0x50,0xb7,0x06,0x12,0x12,0x26,0x09,0x19,0x19,0x16,0x41,0x09,0x01,0x54,0x00,0x1a,0x00,0x1f,0x01,0x4b,0x00,0x06,0x00,0x0a,0x01,0x54,0x00,0x09,0x01,0x4d,0x00,0x3f,0xed,0x32,0x3f,0x33,0xed,0x32,0x01,0x2f, 0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x2f,0x31,0x30,0x01,0x14,0x0e,0x02,0x07,0x07,0x21,0x07,0x21,0x37,0x21,0x32,0x3e,0x04,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x03,0xee,0x17,0x28,0x38,0x20,0x34,0x01,0x19,0x16,0xfc,0x2e,0x18,0x01,0xa6,0x44,0x62,0x44,0x29,0x17,0x07,0xc0,0xb0,0x69, 0xc7,0x53,0x16,0x2a,0x5f,0x60,0x5b,0x27,0x78,0xc7,0x8f,0x4f,0x02,0x66,0x54,0x7b,0x5d,0x47,0x1f,0x32,0xa2,0xa2,0x33,0x52,0x65,0x64,0x59,0x1b,0x86,0xb4,0xad,0x21,0x12,0xa0,0x09,0x0f,0x09,0x05,0x3b,0x7a,0xba,0x7f,0x00,0x01,0x00,0x31,0x00,0x00,0x03,0x17,0x04,0xcd,0x00,0x25,0x00,0x43,0xb3,0x17,0x02,0x02,0x00,0xb8,0x01,0x50, 0xb6,0x01,0x01,0x0b,0x27,0x1e,0x1e,0x0a,0xbb,0x01,0x50,0x00,0x0b,0x00,0x02,0x01,0x56,0xb3,0x17,0x17,0x00,0x1e,0xbd,0x01,0x54,0x00,0x1f,0x01,0x4a,0x00,0x0b,0x00,0x00,0x01,0x4d,0x00,0x3f,0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x33,0x2f,0x11,0x12,0x39,0x2f,0xed,0x33,0x11,0x33,0x31,0x30,0x21,0x23,0x03,0x06,0x06, 0x07,0x0e,0x03,0x07,0x23,0x36,0x37,0x3e,0x03,0x37,0x3e,0x03,0x37,0x03,0x2e,0x03,0x23,0x23,0x37,0x33,0x32,0x1e,0x02,0x17,0x03,0x17,0xa1,0x28,0x4d,0x7b,0x28,0x19,0x29,0x20,0x18,0x0a,0xa9,0x13,0x19,0x0b,0x18,0x1c,0x1f,0x10,0x24,0x54,0x61,0x6b,0x3a,0x1b,0x06,0x2a,0x44,0x5b,0x38,0xc5,0x16,0xaa,0x62,0x99,0x6d,0x3f,0x07,0x01, 0xe0,0x14,0x4e,0x2f,0x1d,0x4f,0x59,0x5e,0x2c,0x4d,0x47,0x1e,0x41,0x3f,0x38,0x15,0x2f,0x45,0x35,0x29,0x13,0x01,0x0e,0x36,0x4c,0x31,0x17,0x91,0x24,0x51,0x84,0x60,0x00,0x01,0x00,0x20,0x00,0x00,0x03,0xab,0x04,0xcd,0x00,0x14,0x00,0x2d,0xb1,0x04,0x14,0xb8,0x01,0x50,0x40,0x09,0x00,0x0c,0x00,0x0c,0x16,0x0a,0x0e,0x04,0x0a,0xbc, 0x01,0x54,0x00,0x0b,0x01,0x4a,0x00,0x00,0x01,0x4d,0x00,0x3f,0x3f,0xed,0x32,0x32,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xed,0x32,0x31,0x30,0x21,0x11,0x34,0x36,0x37,0x22,0x0e,0x02,0x23,0x21,0x37,0x21,0x07,0x23,0x22,0x0e,0x02,0x15,0x11,0x02,0x2e,0x42,0x39,0x0c,0x26,0x27,0x23,0x0a,0xfd,0xfd,0x18,0x03,0x73,0x19,0x37,0x28,0x33, 0x1e,0x0b,0x03,0x32,0x5b,0x81,0x30,0x02,0x02,0x02,0x95,0x95,0x29,0x3e,0x46,0x1e,0xfc,0x93,0x00,0x02,0x00,0xb8,0x00,0x00,0x04,0xc0,0x04,0xde,0x00,0x17,0x00,0x1b,0x00,0x38,0xb9,0x00,0x00,0x01,0x50,0xb3,0x01,0x01,0x1d,0x18,0xb8,0x01,0x50,0xb5,0x19,0x0c,0x0c,0x19,0x0c,0x07,0xb8,0x01,0x54,0xb2,0x1b,0x0d,0x12,0xbb,0x01,0x4b, 0x00,0x19,0x00,0x00,0x01,0x4d,0x00,0x3f,0x32,0x3f,0x33,0xc4,0xed,0x32,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x01,0x23,0x11,0x37,0x04,0xc0,0xab,0x34,0x61,0x8d,0x59,0x3a,0x86,0x83,0x75,0x2a,0x13,0x30,0x73, 0x7f,0x88,0x46,0x6e,0xbc,0x8c,0x4f,0xfc,0xae,0xa9,0xa9,0x02,0xea,0x65,0x88,0x52,0x22,0x0c,0x13,0x17,0x0a,0xa5,0x09,0x10,0x0d,0x08,0x36,0x77,0xba,0x84,0xfd,0x0d,0x02,0xc9,0x51,0x00,0x00,0x01,0x00,0xbe,0x00,0x00,0x01,0x67,0x04,0xcd,0x00,0x03,0x00,0x17,0xbe,0x00,0x00,0x01,0x50,0x00,0x01,0x00,0x00,0x01,0x4d,0x00,0x02,0x01, 0x4a,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x67,0xa9,0xa9,0x04,0xcd,0x00,0x00,0x01,0x00,0x31,0x00,0x00,0x02,0x5f,0x04,0xcd,0x00,0x20,0x00,0x2a,0xb4,0x18,0x0c,0x00,0x00,0x06,0xb8,0x01,0x50,0xb4,0x1e,0x0d,0x13,0x00,0x1e,0xbc,0x01,0x54,0x00,0x1f,0x01,0x4a,0x00,0x0c,0x01,0x4d,0x00,0x3f,0x3f,0xed, 0x32,0x01,0x2f,0x33,0xc6,0xed,0x32,0x2f,0x32,0x32,0x31,0x30,0x01,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x13,0x23,0x03,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x22,0x0e,0x02,0x23,0x23,0x37,0x21,0x02,0x5f,0x31,0x31,0x49,0x31,0x18,0x06,0x07,0x09,0x03,0x6f,0xb1,0x6f,0x02,0x07,0x06,0x04,0x09,0x1e,0x3b,0x31,0x18,0x3b,0x39, 0x33,0x10,0x53,0x13,0x02,0x1b,0x04,0x38,0x1d,0x35,0x4a,0x2c,0x12,0x35,0x39,0x36,0x13,0xfd,0x59,0x02,0xb4,0x0e,0x29,0x31,0x34,0x17,0x1a,0x3c,0x3a,0x34,0x12,0x02,0x01,0x02,0x95,0x00,0x00,0x01,0x00,0xbe,0x00,0x00,0x04,0xba,0x04,0xde,0x00,0x17,0x00,0x30,0xb9,0x00,0x00,0x01,0x50,0xb3,0x01,0x01,0x19,0x0b,0xb8,0x01,0x50,0xb2, 0x0c,0x0a,0x07,0xbe,0x01,0x54,0x00,0x0d,0x00,0x12,0x01,0x4b,0x00,0x0c,0x00,0x00,0x01,0x4d,0x00,0x3f,0x32,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x11,0x23,0x11,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x04,0xba,0xab,0x34,0x60,0x8a,0x57,0x53,0xa4,0x3c, 0xa9,0x30,0x7f,0x86,0x83,0x35,0x7f,0xc4,0x86,0x46,0x02,0xf8,0x63,0x82,0x4d,0x1e,0x14,0x0c,0xfb,0xd8,0x04,0xad,0x0a,0x12,0x0d,0x08,0x36,0x77,0xba,0x84,0x00,0x01,0x00,0xa0,0xff,0xed,0x05,0x01,0x04,0xdd,0x00,0x29,0x00,0x3e,0xb9,0x00,0x00,0x01,0x50,0xb6,0x17,0x20,0x17,0x20,0x17,0x2b,0x0d,0xb8,0x01,0x50,0xb2,0x0a,0x20,0x1d, 0x41,0x0a,0x01,0x54,0x00,0x21,0x00,0x24,0x01,0x4b,0x00,0x0b,0x01,0x4a,0x00,0x12,0x01,0x54,0x00,0x05,0x01,0x4e,0x00,0x3f,0xed,0x3f,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x34, 0x2e,0x02,0x23,0x22,0x06,0x07,0x37,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x05,0x01,0x52,0x98,0xd8,0x86,0x7c,0xc7,0x8c,0x4a,0xaa,0x22,0x54,0x90,0x6d,0x67,0x99,0x66,0x33,0x26,0x47,0x63,0x3d,0x35,0x5e,0x30,0x15,0x2c,0x5d,0x41,0x52,0x95,0x72,0x43,0x02,0x56,0x87,0xe3,0xa3,0x5c,0x52,0x9d,0xe6,0x94,0x02,0x77,0xfd,0x96,0x54,0xaa, 0x8a,0x56,0x49,0x7d,0xa5,0x5c,0x8f,0x4c,0x84,0x62,0x39,0x07,0x09,0x94,0x08,0x0b,0x47,0x86,0xc0,0x79,0x00,0x01,0x00,0xbe,0x02,0x27,0x01,0x67,0x04,0xcd,0x00,0x03,0x00,0x14,0xb9,0x00,0x00,0x01,0x50,0xb2,0x01,0x00,0x02,0xb8,0x01,0x4a,0x00,0x3f,0xcd,0x01,0x2f,0xed,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x67,0xa9,0xa9,0x02,0x27, 0x02,0xa6,0x00,0x01,0x00,0x2f,0xfe,0x00,0x03,0xcd,0x04,0xde,0x00,0x13,0x00,0x27,0xb9,0x00,0x00,0x01,0x50,0xb5,0x01,0x01,0x15,0x08,0x08,0x05,0xbd,0x01,0x54,0x00,0x09,0x00,0x0e,0x01,0x4b,0x00,0x00,0x01,0x4f,0x00,0x3f,0x3f,0x33,0xed,0x32,0x01,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x07, 0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x03,0xcd,0xab,0xc0,0xb0,0x69,0xc7,0x53,0x16,0x2a,0x5f,0x60,0x5b,0x27,0x78,0xc7,0x8f,0x4f,0xfe,0x00,0x04,0xea,0xb4,0xad,0x21,0x12,0xa0,0x09,0x0f,0x09,0x05,0x3b,0x7a,0xba,0x7f,0x00,0x00,0x01,0x00,0x4e,0xff,0xed,0x03,0xeb,0x04,0xde,0x00,0x25,0x00,0x35,0xb9,0x00,0x00,0x01,0x50,0xb6, 0x11,0x11,0x27,0x08,0x1b,0x1b,0x16,0x41,0x0a,0x01,0x54,0x00,0x1c,0x00,0x21,0x01,0x4b,0x00,0x09,0x00,0x0c,0x01,0x54,0x00,0x08,0x00,0x03,0x01,0x4e,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0xed,0x32,0x01,0x2f,0x33,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x10,0x00,0x21,0x22,0x2e,0x02,0x27,0x37,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34, 0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x03,0xeb,0xfe,0xcb,0xfe,0xc4,0x28,0x53,0x4b,0x3d,0x12,0x15,0x2f,0x81,0x46,0x77,0xae,0x72,0x37,0x33,0x6e,0xab,0x78,0x1b,0x4d,0x53,0x51,0x20,0x14,0x1d,0x4a,0x4f,0x51,0x24,0x91,0xe2,0x9a,0x51,0x02,0x5f,0xfe,0xc7,0xfe,0xc7,0x07,0x0b,0x0d,0x07,0x8d,0x0a, 0x12,0x38,0x75,0xb4,0x7d,0x76,0xb5,0x7b,0x40,0x04,0x07,0x0b,0x06,0x8f,0x08,0x0d,0x09,0x05,0x4b,0x9d,0xf1,0x00,0x00,0x01,0x00,0x59,0x00,0x00,0x03,0xeb,0x06,0xa0,0x00,0x2b,0x00,0x39,0xb9,0x00,0x00,0x01,0x50,0xb6,0x1d,0x0e,0x1d,0x0e,0x1d,0x2d,0x26,0x41,0x0c,0x01,0x50,0x00,0x23,0x00,0x23,0x01,0x54,0x00,0x26,0x01,0x4a,0x00, 0x24,0x01,0x4c,0x00,0x0f,0x01,0x54,0x00,0x0e,0x01,0x4d,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x03,0x0e,0x03,0x07,0x0e,0x03,0x07,0x37,0x32,0x3e,0x02,0x37,0x3e,0x03,0x37,0x13,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x21,0x11,0x33,0x11,0x21,0x32,0x1e,0x02, 0x03,0xeb,0x05,0x02,0x1c,0x06,0x1a,0x2d,0x41,0x2d,0x2f,0x7e,0x85,0x7e,0x2f,0x32,0x1a,0x48,0x4f,0x4f,0x1f,0x25,0x38,0x27,0x18,0x05,0x1b,0x01,0x05,0x22,0x3f,0x5a,0x37,0xfe,0x0a,0xa9,0x01,0x6e,0x56,0x8c,0x63,0x36,0x03,0x95,0x1c,0x3e,0x13,0xfe,0xe1,0x3b,0x76,0x6c,0x60,0x25,0x27,0x29,0x13,0x03,0x01,0x8e,0x03,0x0b,0x15,0x12, 0x15,0x42,0x53,0x5f,0x31,0x01,0x1a,0x0a,0x38,0x19,0x30,0x4a,0x32,0x1a,0x02,0x68,0xfe,0x2d,0x2f,0x54,0x72,0x00,0x00,0x02,0x00,0xbe,0x00,0x00,0x04,0xe2,0x04,0xde,0x00,0x0b,0x00,0x16,0x00,0x36,0xb9,0x00,0x00,0x01,0x50,0xb3,0x0c,0x0c,0x18,0x16,0xb8,0x01,0x50,0xb2,0x02,0x15,0x12,0x41,0x09,0x01,0x54,0x00,0x03,0x00,0x06,0x01, 0x4b,0x00,0x00,0x00,0x16,0x01,0x54,0x00,0x02,0x01,0x4d,0x00,0x3f,0xed,0x32,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x07,0x21,0x11,0x36,0x24,0x33,0x32,0x1e,0x02,0x15,0x03,0x11,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x11,0x04,0xe2,0x31,0xfc,0x0d,0x80,0x01,0x00,0x86,0x82,0xca,0x8a,0x48,0xab,0x37, 0x69,0x96,0x60,0x6a,0x9c,0x34,0xa9,0xa9,0x04,0xac,0x17,0x1b,0x42,0x7e,0xb6,0x75,0xfd,0xaf,0x02,0x53,0x5b,0x80,0x52,0x26,0x14,0x0b,0xfc,0x79,0x00,0x01,0x00,0xa4,0xff,0xed,0x04,0xe8,0x04,0xe5,0x00,0x33,0x00,0x4b,0xb9,0x00,0x00,0x01,0x50,0x40,0x09,0x11,0x08,0x11,0x08,0x35,0x28,0x27,0x2b,0x22,0xb8,0x01,0x50,0xb2,0x23,0x21, 0x19,0x41,0x0d,0x01,0x54,0x00,0x2b,0x00,0x2e,0x01,0x4a,0x00,0x27,0x00,0x28,0x01,0x4b,0x00,0x23,0x01,0x4d,0x00,0x0c,0x01,0x54,0x00,0x05,0x01,0x4e,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0x32,0xc6,0x32,0x12,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x37,0x16,0x16, 0x33,0x32,0x3e,0x02,0x35,0x35,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x07,0x06,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x27,0x37,0x16,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x04,0xe8,0x31,0x60,0x8e,0x5c,0x35,0x62,0x26,0x2c,0x21,0x40,0x28,0x38,0x51,0x35,0x1a,0x0e,0x21,0x38,0x52,0x71,0x4a,0x2c,0x5f,0x57,0x4a,0x17,0x09,0x0f, 0xa9,0x0a,0x17,0x94,0x16,0x1a,0x02,0x4a,0xba,0x75,0x7e,0xc1,0x83,0x43,0x01,0xb9,0x6f,0xab,0x75,0x3d,0x13,0x11,0x85,0x08,0x09,0x2a,0x4c,0x69,0x40,0xf8,0x30,0x64,0x5f,0x54,0x3e,0x25,0x15,0x29,0x3d,0x29,0x11,0x27,0x14,0xfc,0xaa,0x03,0xf5,0x2e,0x55,0x2d,0x40,0x20,0x54,0x3f,0x50,0x5c,0x52,0x94,0xcc,0x7a,0x00,0x01,0x00,0xbe, 0xfd,0xff,0x01,0x67,0x04,0xcd,0x00,0x03,0x00,0x17,0xbe,0x00,0x00,0x01,0x50,0x00,0x01,0x00,0x00,0x01,0x4f,0x00,0x02,0x01,0x4a,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x31,0x30,0x01,0x23,0x11,0x33,0x01,0x67,0xa9,0xa9,0xfd,0xff,0x06,0xce,0x00,0x00,0x01,0x00,0x67,0x00,0x00,0x02,0x87,0x04,0xde,0x00,0x19,0x00,0x33,0xb9,0x00,0x00,0x01, 0x50,0x40,0x09,0x03,0x03,0x01,0x1b,0x0e,0x0e,0x01,0x0e,0x09,0xbf,0x01,0x54,0x00,0x0f,0x00,0x12,0x01,0x4b,0x00,0x02,0x01,0x54,0x00,0x01,0x01,0x4d,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x01,0x2f,0x33,0x2f,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x21,0x37,0x21,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x37,0x36,0x36,0x33, 0x32,0x1e,0x04,0x15,0x02,0x87,0xfd,0xe0,0x13,0x01,0x62,0x0d,0x2b,0x52,0x44,0x0f,0x24,0x24,0x1f,0x08,0x18,0x1c,0x56,0x25,0x45,0x65,0x49,0x2f,0x1b,0x0b,0xa2,0x02,0x7b,0x41,0x6d,0x50,0x2c,0x02,0x03,0x04,0x02,0x94,0x06,0x08,0x22,0x3e,0x54,0x64,0x71,0x3a,0x00,0x02,0x00,0x96,0xff,0xed,0x04,0xf7,0x04,0xde,0x00,0x14,0x00,0x27, 0x00,0x32,0xb9,0x00,0x00,0x01,0x50,0xb3,0x15,0x15,0x29,0x1e,0xb8,0x01,0x50,0xb2,0x0a,0x1d,0x1a,0xbf,0x01,0x54,0x00,0x0b,0x00,0x10,0x01,0x4b,0x00,0x23,0x01,0x54,0x00,0x05,0x01,0x4e,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x3e,0x03, 0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x04,0xf7,0x4f,0x96,0xd9,0x8a,0x89,0xca,0x85,0x41,0x3c,0x87,0x8f,0x92,0x45,0x8c,0xd5,0x8f,0x48,0xab,0x2f,0x63,0x9a,0x6b,0x63,0xc4,0x4f,0x22,0x55,0x90,0x6d,0x6f,0x9c,0x61,0x2d,0x02,0x56,0x82,0xe1,0xa7,0x5f,0x5b,0xa4,0xe3, 0x87,0x02,0x59,0x09,0x11,0x0d,0x08,0x61,0xac,0xee,0x8d,0x68,0xb5,0x85,0x4d,0x10,0x0b,0xfe,0x39,0x54,0xaa,0x8a,0x56,0x55,0x86,0xa5,0x00,0x01,0x00,0x59,0xff,0x94,0x04,0x2b,0x04,0xcd,0x00,0x17,0x00,0x3a,0xb2,0x10,0x0d,0x00,0xb8,0x01,0x50,0xb5,0x0d,0x0e,0x15,0x15,0x19,0x0f,0xb8,0x01,0x51,0xb7,0x0e,0x08,0x08,0x0e,0x0d,0x10, 0x16,0x0e,0xbb,0x01,0x4a,0x00,0x08,0x01,0x54,0x00,0x07,0x00,0x2f,0xed,0x3f,0x33,0x39,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x11,0x33,0x31,0x30,0x01,0x14,0x0e,0x04,0x07,0x27,0x3e,0x03,0x37,0x01,0x33,0x01,0x3e,0x03,0x35,0x11,0x33,0x04,0x2b,0x4d,0x86,0xb4,0xcd,0xdb,0x6b,0x2f,0x31,0x68,0x65,0x5f, 0x28,0xfe,0x72,0xb6,0x01,0x70,0x38,0x5e,0x46,0x27,0xa9,0x02,0x64,0x91,0xd3,0x95,0x61,0x3f,0x27,0x10,0xa5,0x05,0x0d,0x13,0x17,0x0d,0x04,0x4b,0xfb,0xe8,0x1b,0x46,0x5f,0x7c,0x50,0x02,0x8c,0x00,0x00,0x01,0x00,0x6c,0xfd,0xff,0x04,0x39,0x04,0xde,0x00,0x1b,0x00,0x3d,0xb9,0x00,0x00,0x01,0x50,0xb6,0x01,0x0e,0x01,0x0e,0x01,0x1d, 0x0d,0xbb,0x01,0x50,0x00,0x10,0x00,0x10,0x01,0x54,0xb4,0x0d,0x0d,0x1c,0x0c,0x07,0xbc,0x01,0x54,0x00,0x11,0x00,0x16,0x01,0x4b,0x00,0x00,0x00,0x2f,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x11,0x21,0x07,0x21, 0x11,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x04,0x39,0xab,0x30,0x6a,0xaa,0x7a,0x16,0x34,0x33,0x2e,0x11,0x01,0x18,0x19,0xfe,0x59,0x24,0x57,0x5e,0x5f,0x2c,0xa5,0xeb,0x94,0x45,0xfd,0xff,0x04,0x73,0x81,0xb3,0x70,0x32,0x04,0x06,0x08,0x04,0xfe,0x65,0x96,0x02,0xaa,0x0b,0x12,0x0e,0x08,0x47,0x98,0xec,0xa5,0x00,0x00,0x01,0x00,0x96, 0xff,0xed,0x04,0x9c,0x04,0xde,0x00,0x27,0x00,0x51,0xb9,0x00,0x00,0x01,0x50,0xb6,0x13,0x1b,0x13,0x1b,0x13,0x29,0x1a,0xb8,0x01,0x50,0xb4,0x1d,0x0a,0x0a,0x1d,0x1d,0xb8,0x01,0x54,0xb4,0x1a,0x1a,0x0e,0x19,0x16,0x41,0x0a,0x01,0x54,0x00,0x1e,0x00,0x23,0x01,0x4b,0x00,0x0b,0x00,0x0e,0x01,0x54,0x00,0x0a,0x00,0x05,0x01,0x4e,0x00, 0x3f,0x33,0xed,0x32,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f,0x32,0x2f,0x10,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x37,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x02,0x23,0x22,0x06,0x07,0x11,0x21,0x07,0x21,0x11,0x3e,0x03,0x33,0x32,0x1e,0x02,0x04,0x9c,0x54, 0x9c,0xde,0x8a,0x2d,0x70,0x74,0x70,0x2d,0x1c,0x4b,0xbc,0x7d,0x6a,0xa4,0x71,0x3a,0xca,0xd4,0x5c,0x94,0x26,0x01,0x4c,0x1c,0xfe,0x2b,0x2c,0x71,0x75,0x70,0x2c,0x8f,0xdf,0x9a,0x50,0x02,0x59,0xa0,0xea,0x98,0x4a,0x06,0x0c,0x14,0x0e,0x96,0x14,0x1c,0x32,0x6d,0xaf,0x7e,0xf2,0x01,0x03,0x11,0x0b,0xfe,0x7f,0x96,0x02,0x8b,0x0f,0x17, 0x10,0x08,0x50,0xa1,0xf2,0x00,0x00,0x01,0x00,0x1e,0xfd,0xff,0x04,0x03,0x04,0xe5,0x00,0x22,0x00,0x44,0xb3,0x17,0x09,0x06,0x0a,0xb8,0x01,0x50,0xb4,0x0b,0x0b,0x12,0x20,0x00,0xb8,0x01,0x50,0x40,0x0e,0x1f,0x1c,0x1c,0x24,0x13,0x12,0x12,0x13,0x13,0x17,0x06,0x0a,0x1f,0x20,0xba,0x01,0x4b,0x00,0x0a,0x01,0x4f,0x00,0x3f,0x3f,0x33, 0x12,0x39,0x39,0x33,0x2f,0x33,0x01,0x2f,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0x32,0x32,0x32,0x31,0x30,0x01,0x14,0x0e,0x02,0x07,0x07,0x16,0x16,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x01,0x37,0x01,0x16,0x16,0x17,0x3e,0x03,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x04,0x03,0x1e,0x44,0x70,0x52,0x61,0x05,0x02, 0xa9,0x0a,0x17,0x27,0x1e,0xfe,0xa8,0xab,0x01,0x36,0x1d,0x32,0x0c,0x4a,0x63,0x3b,0x19,0x1d,0x14,0xa3,0x17,0x1f,0x03,0xd4,0x59,0x96,0x7a,0x61,0x24,0x2b,0x26,0x50,0x20,0xfc,0xda,0x03,0x23,0x3a,0x62,0x5a,0x54,0x2d,0x02,0x05,0x40,0xfe,0x1f,0x2d,0x6b,0x2d,0x20,0x4e,0x60,0x72,0x44,0x4c,0x72,0x29,0x42,0x32,0x8e,0x00,0x00,0x01, 0x00,0x4b,0x00,0x00,0x04,0x25,0x04,0xd4,0x00,0x14,0x00,0x4e,0xb3,0x05,0x0d,0x0c,0x06,0xb8,0x01,0x51,0xb3,0x0a,0x0a,0x08,0x00,0xb8,0x01,0x50,0x40,0x10,0x12,0x12,0x08,0x16,0x0c,0x0b,0x0b,0x08,0x05,0x0d,0x06,0x0c,0x13,0x13,0x0b,0x0c,0xbd,0x01,0x4a,0x00,0x06,0x00,0x09,0x01,0x54,0x00,0x08,0x01,0x4d,0x00,0x3f,0xed,0x32,0x3f, 0x33,0x33,0x2f,0x11,0x12,0x39,0x39,0x01,0x2f,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x31,0x30,0x01,0x14,0x0e,0x02,0x07,0x13,0x07,0x21,0x37,0x21,0x01,0x37,0x01,0x3e,0x03,0x35,0x11,0x33,0x04,0x25,0x28,0x48,0x64,0x3c,0xdc,0x2c,0xfc,0x86,0x2d,0x02,0xb3,0xfd,0x39,0x9a,0x01,0xc9,0x23,0x41, 0x32,0x1e,0xaa,0x03,0xd4,0x60,0x94,0x77,0x62,0x2f,0xfe,0xca,0xa2,0xa2,0x03,0xee,0x44,0xfd,0x74,0x15,0x42,0x5c,0x76,0x47,0x01,0x15,0x00,0x02,0x00,0x42,0xfd,0xff,0x04,0xd2,0x04,0xde,0x00,0x29,0x00,0x2d,0x00,0x46,0xb9,0x00,0x00,0x01,0x50,0xb6,0x15,0x09,0x15,0x09,0x15,0x2f,0x2a,0xb8,0x01,0x50,0xb2,0x1f,0x2b,0x2a,0xb8,0x01, 0x4f,0xb4,0x2c,0x2c,0x0a,0x1f,0x1a,0xbf,0x01,0x54,0x00,0x20,0x00,0x25,0x01,0x4b,0x00,0x0a,0x01,0x54,0x00,0x09,0x01,0x4e,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0x3f,0x01,0x2f,0xc6,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x07,0x0e,0x03,0x07,0x37,0x3e,0x03,0x37,0x37,0x3e,0x03,0x35, 0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x01,0x23,0x11,0x33,0x04,0xd2,0x02,0x02,0x08,0x10,0x60,0x9f,0xdf,0x90,0x15,0x5e,0x99,0x72,0x47,0x0c,0x0d,0x01,0x01,0x01,0x01,0x2a,0x58,0x88,0x5f,0x5b,0xa4,0x9b,0x97,0x4e,0x20,0x2d,0x7f,0x9a,0xad,0x5a,0x91,0xcf,0x85,0x3e,0xfc,0x9c,0xa9,0xa9,0x03, 0x4a,0x10,0x35,0x11,0x68,0xb7,0xf7,0x9a,0x4c,0x0b,0xa1,0x0b,0x35,0x69,0xaa,0x80,0x8a,0x09,0x1a,0x1b,0x1a,0x09,0x44,0x61,0x3e,0x1d,0x0a,0x11,0x18,0x0e,0xa6,0x06,0x10,0x0d,0x0a,0x32,0x65,0x97,0xfa,0x4f,0x04,0xe2,0x00,0x01,0x00,0x2f,0x00,0x00,0x03,0xcd,0x04,0xde,0x00,0x13,0x00,0x27,0xb9,0x00,0x00,0x01,0x50,0xb5,0x01,0x01, 0x15,0x08,0x08,0x05,0xbd,0x01,0x54,0x00,0x09,0x00,0x0e,0x01,0x4b,0x00,0x00,0x01,0x4d,0x00,0x3f,0x3f,0x33,0xed,0x32,0x01,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x03,0xcd,0xab,0xc0,0xb0,0x69,0xc7,0x53,0x16,0x2a,0x5f,0x60,0x5b,0x27,0x78,0xc7, 0x8f,0x4f,0x02,0xea,0xb4,0xad,0x21,0x12,0xa0,0x09,0x0f,0x09,0x05,0x3b,0x7a,0xba,0x7f,0x00,0x00,0x01,0x00,0x6e,0x00,0x00,0x05,0xd8,0x04,0xcd,0x00,0x31,0x00,0x56,0xbc,0x00,0x00,0x01,0x50,0x00,0x31,0x00,0x1b,0x01,0x50,0x40,0x0d,0x1a,0x31,0x1a,0x31,0x1a,0x33,0x0c,0x26,0x25,0x25,0x0e,0x0e,0x0d,0xb8,0x01,0x51,0xb2,0x0b,0x0c, 0x25,0xb8,0x01,0x54,0xb3,0x0e,0x0e,0x00,0x26,0xba,0x01,0x54,0x00,0x0b,0x01,0x4d,0xb2,0x1a,0x0c,0x00,0xb8,0x01,0x4a,0x00,0x3f,0x32,0x32,0x3f,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0x33,0xed,0x32,0x11,0x33,0x11,0x33,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x07,0x06,0x06,0x07,0x0e,0x03,0x23,0x21, 0x03,0x33,0x13,0x3e,0x05,0x37,0x36,0x36,0x37,0x36,0x37,0x33,0x06,0x07,0x06,0x06,0x07,0x0e,0x03,0x07,0x17,0x21,0x32,0x3e,0x02,0x37,0x36,0x36,0x37,0x36,0x37,0x05,0xd8,0x06,0x0a,0x08,0x1a,0x14,0x13,0x4f,0x7e,0xaf,0x73,0xfd,0x97,0xb9,0xb3,0x6b,0x3b,0x5f,0x4a,0x38,0x2a,0x1d,0x09,0x05,0x0a,0x05,0x05,0x05,0xb0,0x04,0x05,0x05, 0x0a,0x06,0x0e,0x3e,0x76,0xb9,0x89,0x18,0x01,0xd6,0x3c,0x6b,0x58,0x40,0x10,0x16,0x1c,0x08,0x0a,0x05,0x04,0xcd,0x33,0x54,0x48,0xe8,0xab,0xa8,0xeb,0x94,0x44,0x04,0xcd,0xfd,0x0e,0x12,0x24,0x31,0x44,0x61,0x85,0x5a,0x2e,0x5d,0x26,0x2d,0x29,0x24,0x2c,0x26,0x62,0x39,0x8a,0xc9,0x93,0x66,0x27,0xa7,0x27,0x64,0xad,0x85,0xa6,0xea, 0x4c,0x59,0x39,0x00,0x00,0x01,0x00,0x34,0xff,0xed,0x05,0x23,0x04,0xde,0x00,0x2d,0x00,0x47,0xb2,0x22,0x22,0x0b,0xb8,0x01,0x50,0xb3,0x1e,0x1e,0x15,0x00,0xb8,0x01,0x50,0x40,0x09,0x01,0x01,0x2f,0x15,0x22,0x0a,0x0a,0x1f,0x07,0x41,0x09,0x01,0x54,0x00,0x23,0x00,0x28,0x01,0x4b,0x00,0x1a,0x01,0x54,0x00,0x12,0x01,0x4e,0x00,0x01, 0x00,0x2f,0x3f,0xed,0x3f,0x33,0xed,0x32,0x32,0x11,0x33,0x01,0x2f,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0xed,0x33,0x2f,0x31,0x30,0x21,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x11,0x14,0x0e,0x04,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x06,0x06,0x07,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x05, 0x23,0xab,0x39,0x71,0xaa,0x71,0x33,0x6f,0x39,0x04,0x12,0x24,0x42,0x64,0x48,0x1d,0x3e,0x21,0x13,0x14,0x20,0x0f,0x2e,0x3e,0x27,0x11,0x2c,0x4c,0x1e,0x13,0x37,0x81,0x8f,0x9a,0x4f,0x7c,0xd5,0x9d,0x5a,0x02,0xea,0x61,0x86,0x54,0x26,0x08,0x06,0xfd,0x73,0x3d,0x72,0x64,0x54,0x3b,0x21,0x04,0x05,0x91,0x04,0x01,0x1f,0x44,0x69,0x49, 0x02,0x90,0x07,0x0f,0x06,0xa5,0x09,0x10,0x0d,0x08,0x36,0x77,0xba,0x84,0xff,0xff,0x00,0xbe,0x00,0x00,0x03,0x70,0x04,0xcd,0x00,0x26,0x0b,0x6d,0x00,0x00,0x00,0x07,0x0b,0x6d,0x02,0x09,0x00,0x00,0xff,0xff,0x00,0xbe,0x00,0x00,0x03,0x70,0x04,0xcd,0x00,0x27,0x0b,0x6d,0x02,0x09,0x00,0x00,0x00,0x06,0x0b,0x71,0x00,0x00,0xff,0xff, 0x00,0xbe,0x02,0x27,0x03,0x70,0x04,0xcd,0x00,0x26,0x0b,0x71,0x00,0x00,0x00,0x07,0x0b,0x71,0x02,0x09,0x00,0x00,0x00,0x01,0x00,0x6e,0x03,0x0e,0x01,0x70,0x04,0xcc,0x00,0x03,0x00,0x11,0xb5,0x03,0x00,0x01,0x02,0x00,0x02,0x00,0x2f,0xcd,0x01,0x2f,0x33,0xcd,0x32,0x30,0x31,0x01,0x03,0x23,0x13,0x01,0x70,0x8c,0x76,0x6f,0x04,0xcc, 0xfe,0x42,0x01,0xbe,0x00,0x02,0x00,0x6e,0x03,0x0e,0x02,0xa0,0x04,0xcc,0x00,0x03,0x00,0x07,0x00,0x20,0x40,0x0d,0x03,0x00,0x01,0x02,0x07,0x04,0x05,0x06,0x00,0x02,0x02,0x04,0x06,0x00,0x2f,0xcd,0x33,0x2f,0xcd,0x01,0x2f,0x33,0xdd,0x32,0xd6,0x32,0xcd,0x32,0x30,0x31,0x01,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x02,0xa0,0x8c,0x76, 0x6c,0x9a,0x8c,0x76,0x6f,0x04,0xcc,0xfe,0x42,0x01,0xbe,0xfe,0x42,0x01,0xbe,0x00,0xff,0xff,0x00,0x2f,0xfe,0x00,0x03,0xcd,0x04,0xde,0x02,0x26,0x0b,0x72,0x00,0x00,0x00,0x07,0x0b,0x53,0x01,0x48,0x02,0xfb,0xff,0xff,0x00,0x2f,0xfe,0x00,0x03,0xcd,0x04,0xde,0x02,0x26,0x0b,0x72,0x00,0x00,0x00,0x07,0x0b,0x5b,0x00,0xce,0x02,0xfb, 0xff,0xff,0xff,0x51,0x00,0x00,0x03,0xeb,0x06,0xa0,0x02,0x26,0x0b,0x74,0x00,0x00,0x00,0x06,0x0b,0x5c,0xad,0x00,0xff,0xff,0xff,0x51,0x00,0x00,0x03,0xeb,0x06,0xa0,0x02,0x26,0x0b,0x74,0x00,0x00,0x00,0x26,0x0b,0x5c,0xad,0x00,0x00,0x07,0x0b,0x5e,0x01,0xc6,0x00,0x00,0x00,0x03,0x00,0xbe,0x01,0x58,0x03,0x95,0x04,0xcd,0x00,0x03, 0x00,0x07,0x00,0x0b,0x00,0x30,0xb1,0x03,0x0b,0xb8,0x01,0x50,0xb3,0x0a,0x0a,0x0d,0x07,0xb8,0x01,0x50,0xb2,0x02,0x06,0x0a,0xb8,0x01,0x4b,0xb4,0x00,0x02,0x09,0x04,0x06,0xb8,0x01,0x4b,0x00,0x3f,0xdd,0x32,0xde,0xcd,0x3f,0x01,0x2f,0x33,0xed,0x12,0x39,0x2f,0xed,0x32,0x30,0x31,0x01,0x21,0x35,0x21,0x25,0x23,0x11,0x33,0x01,0x23, 0x11,0x33,0x03,0x95,0xfd,0x29,0x02,0xd7,0xfd,0xd2,0xa9,0xa9,0x02,0x2e,0xa9,0xa9,0x01,0x58,0x6a,0x65,0x02,0xa6,0xfd,0x5a,0x02,0xa6,0x00,0x01,0x00,0x59,0x00,0x00,0x04,0x2b,0x04,0xcd,0x00,0x16,0x00,0x3a,0xb2,0x0f,0x0c,0x16,0xb8,0x01,0x50,0xb5,0x0c,0x0d,0x15,0x15,0x18,0x0e,0xb8,0x01,0x51,0xb7,0x0d,0x08,0x08,0x0d,0x0c,0x0f, 0x16,0x0e,0xbb,0x01,0x4a,0x00,0x08,0x01,0x54,0x00,0x07,0x00,0x2f,0xed,0x3f,0x33,0x39,0x39,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x11,0x33,0x31,0x30,0x01,0x14,0x0e,0x03,0x23,0x23,0x27,0x33,0x32,0x32,0x37,0x01,0x33,0x01,0x3e,0x03,0x35,0x11,0x33,0x04,0x2b,0x4d,0x86,0xb4,0xaf,0x9a,0xca,0x2f,0xcd,0x33, 0x53,0x2b,0xfe,0x79,0xb6,0x01,0x70,0x38,0x5e,0x46,0x27,0xa9,0x02,0x80,0x91,0xd3,0x95,0x61,0x26,0xa2,0x08,0x04,0x23,0xfc,0x04,0x1b,0x46,0x5f,0x7c,0x50,0x02,0x70,0xff,0xff,0x00,0xa5,0x00,0x00,0x04,0x9a,0x04,0xd4,0x02,0x06,0x0b,0x68,0x00,0x00,0xff,0xff,0x00,0x20,0x00,0x00,0x03,0xab,0x04,0xcd,0x02,0x06,0x0b,0x6b,0x00,0x00, 0xff,0xff,0x00,0xb8,0x00,0x00,0x04,0xc0,0x04,0xde,0x02,0x06,0x0b,0x6c,0x00,0x00,0xff,0xff,0x00,0x4e,0xff,0xed,0x03,0xeb,0x04,0xde,0x02,0x06,0x0b,0x73,0x00,0x00,0xff,0xff,0x00,0x59,0x00,0x00,0x03,0xeb,0x06,0xa0,0x02,0x06,0x0b,0x74,0x00,0x00,0xff,0xff,0x00,0xbe,0x00,0x00,0x04,0xe2,0x04,0xde,0x02,0x06,0x0b,0x75,0x00,0x00, 0xff,0xff,0x00,0x2f,0x00,0x00,0x03,0xcd,0x04,0xde,0x02,0x06,0x0b,0x80,0x00,0x00,0xff,0xff,0x00,0x34,0xff,0xed,0x05,0x23,0x04,0xde,0x02,0x06,0x0b,0x82,0x00,0x00,0x00,0x01,0x00,0x5f,0x02,0x12,0x04,0x0b,0x04,0x2b,0x00,0x07,0x00,0x19,0xb1,0x07,0x05,0xb8,0x01,0x50,0xb5,0x02,0x04,0x06,0x00,0x02,0x04,0x00,0x2f,0xde,0xcd,0x33, 0x01,0x2f,0xce,0xfd,0xce,0x30,0x31,0x01,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x04,0x0b,0xfc,0x54,0x01,0x93,0x85,0x01,0x94,0x02,0x12,0x86,0x01,0x93,0xfe,0x6d,0x00,0xff,0xff,0x00,0x6e,0x00,0x00,0x05,0xde,0x06,0x05,0x02,0x26,0x0b,0x81,0x00,0x00,0x00,0x07,0x0b,0x63,0x03,0x25,0x00,0x00,0xff,0xff,0x00,0x61,0x00,0x00,0x05,0xd8, 0x06,0x05,0x02,0x26,0x0b,0x81,0x00,0x00,0x00,0x07,0x0b,0x64,0x03,0x25,0x00,0x00,0xff,0xff,0x00,0x6e,0x00,0x00,0x05,0xde,0x06,0x05,0x02,0x26,0x0b,0x81,0x00,0x00,0x00,0x27,0x0b,0x63,0x03,0x25,0x00,0x00,0x00,0x07,0x0b,0x5e,0x03,0xc0,0xff,0x2a,0xff,0xff,0x00,0x61,0x00,0x00,0x05,0xd8,0x06,0x05,0x02,0x26,0x0b,0x81,0x00,0x00, 0x00,0x27,0x0b,0x64,0x03,0x25,0x00,0x00,0x00,0x07,0x0b,0x5e,0x03,0xc0,0xff,0x2a,0xff,0xff,0x00,0xa5,0xff,0x38,0x04,0x9a,0x04,0xd4,0x02,0x26,0x0b,0x68,0x00,0x00,0x00,0x07,0x0b,0x5a,0x01,0xae,0x00,0x00,0xff,0xff,0x00,0xa5,0xfe,0x59,0x04,0x9a,0x04,0xd4,0x02,0x26,0x0b,0x68,0x00,0x00,0x00,0x07,0x0b,0x5b,0x01,0xae,0x00,0x00, 0xff,0xff,0x00,0xa5,0x00,0x00,0x04,0x9a,0x04,0xd4,0x02,0x26,0x0b,0x68,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0x3a,0xfe,0x43,0xff,0xff,0x00,0x50,0x00,0x00,0x04,0x3c,0x04,0xde,0x02,0x26,0x0b,0x69,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0xd3,0x00,0x00,0xff,0xff,0x00,0x31,0x00,0x00,0x03,0x17,0x04,0xcd,0x02,0x26,0x0b,0x6a,0x00,0x00, 0x00,0x07,0x0b,0x5e,0x01,0x10,0x00,0x8c,0xff,0xff,0x00,0x20,0x00,0x00,0x03,0xab,0x04,0xcd,0x02,0x26,0x0b,0x6b,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0x36,0x00,0x00,0xff,0xff,0x00,0xb8,0x00,0x00,0x04,0xc0,0x04,0xde,0x02,0x26,0x0b,0x6c,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0xb8,0x00,0x00,0xff,0xff,0xff,0xfb,0x00,0x00,0x01,0xad, 0x04,0xcd,0x00,0x26,0x0b,0x6d,0x46,0x00,0x00,0x06,0x0b,0x5e,0x56,0x00,0xff,0xff,0xff,0xfa,0x00,0x00,0x02,0x87,0x04,0xcd,0x00,0x26,0x0b,0x6e,0x28,0x00,0x00,0x06,0x0b,0x5e,0x55,0x00,0xff,0xff,0x00,0xa0,0xff,0xed,0x05,0x01,0x04,0xdd,0x02,0x26,0x0b,0x70,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0xc7,0x00,0x00,0xff,0xff,0xff,0xfb, 0x02,0x27,0x01,0xad,0x04,0xcd,0x00,0x26,0x0b,0x71,0x46,0x00,0x00,0x07,0x0b,0x5e,0x00,0x56,0x01,0x0e,0xff,0xff,0x00,0x2f,0xfe,0x00,0x03,0xcd,0x04,0xde,0x02,0x26,0x0b,0x72,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0xa4,0x00,0x00,0xff,0xff,0x00,0x4e,0xff,0xed,0x03,0xeb,0x04,0xde,0x02,0x26,0x0b,0x73,0x00,0x00,0x00,0x07,0x0b,0x5e, 0x01,0xa4,0x00,0x00,0xff,0xff,0x00,0x59,0x00,0x00,0x03,0xeb,0x06,0xa0,0x02,0x26,0x0b,0x74,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0xc6,0x00,0x00,0xff,0xff,0x00,0xa4,0xff,0xed,0x04,0xe8,0x04,0xe5,0x02,0x26,0x0b,0x76,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0xd2,0x00,0x00,0xff,0xff,0x00,0x67,0x00,0x00,0x02,0x87,0x04,0xde,0x02,0x26, 0x0b,0x78,0x00,0x00,0x00,0x07,0x0b,0x5e,0x00,0xfa,0x00,0x00,0xff,0xff,0x00,0x96,0xff,0xed,0x04,0xf7,0x04,0xde,0x02,0x26,0x0b,0x79,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0xb2,0x00,0x00,0xff,0xff,0x00,0x6c,0xfd,0xff,0x04,0x39,0x04,0xde,0x02,0x26,0x0b,0x7b,0x00,0x00,0x00,0x07,0x0b,0x5e,0x02,0xd5,0xff,0xd9,0xff,0xff,0x00,0x96, 0xff,0xed,0x04,0x9c,0x04,0xde,0x02,0x26,0x0b,0x7c,0x00,0x00,0x00,0x07,0x0b,0x5e,0x03,0x2f,0xff,0xf7,0xff,0xff,0x00,0x4b,0x00,0x00,0x04,0x25,0x04,0xd4,0x02,0x26,0x0b,0x7e,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0x68,0xff,0x16,0xff,0xff,0x00,0x42,0xfd,0xff,0x04,0xd2,0x04,0xde,0x02,0x26,0x0b,0x7f,0x00,0x00,0x00,0x07,0x0b,0x5e, 0x02,0xad,0x00,0x00,0xff,0xff,0x00,0x2f,0x00,0x00,0x03,0xcd,0x04,0xde,0x02,0x26,0x0b,0x80,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0xb3,0x00,0x00,0xff,0xff,0x00,0x6e,0x00,0x00,0x05,0xd8,0x04,0xcd,0x02,0x26,0x0b,0x81,0x00,0x00,0x00,0x07,0x0b,0x5e,0x03,0xc0,0xff,0x2a,0xff,0xff,0x00,0x34,0xff,0xed,0x05,0x23,0x04,0xde,0x02,0x26, 0x0b,0x82,0x00,0x00,0x00,0x07,0x0b,0x5e,0x03,0x20,0x00,0x00,0xff,0xff,0x00,0xb5,0x00,0x00,0x01,0x6e,0x06,0x05,0x02,0x26,0x0b,0x6d,0x00,0x00,0x00,0x07,0x0b,0x5c,0x01,0x11,0x00,0x00,0xff,0xff,0x00,0x50,0x00,0x00,0x04,0x3c,0x05,0xd5,0x02,0x26,0x0b,0x69,0x00,0x00,0x00,0x07,0x0b,0x61,0x01,0xea,0x00,0x00,0xff,0xff,0x00,0x4e, 0xff,0xed,0x03,0xeb,0x05,0xd5,0x02,0x26,0x0b,0x73,0x00,0x00,0x00,0x07,0x0b,0x61,0x01,0xc7,0x00,0x00,0xff,0xff,0x00,0x96,0xff,0xed,0x04,0x9c,0x05,0xd5,0x02,0x26,0x0b,0x7c,0x00,0x00,0x00,0x07,0x0b,0x61,0x02,0x44,0x00,0x00,0x00,0x01,0x00,0x59,0x00,0x00,0x04,0xba,0x06,0xa0,0x00,0x1b,0x00,0x40,0xb6,0x17,0x06,0x12,0x0c,0x0b, 0x0b,0x01,0xb8,0x01,0x50,0xb3,0x1a,0x1a,0x1d,0x12,0xb8,0x01,0x50,0xb7,0x0f,0x06,0x17,0x0b,0x12,0x12,0x0f,0x1b,0xbc,0x01,0x4a,0x00,0x10,0x01,0x4c,0x00,0x0b,0x01,0x4d,0x00,0x3f,0x3f,0x3f,0x33,0x33,0x11,0x12,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x32,0x2f,0x33,0x12,0x39,0x39,0x31,0x30,0x01,0x11,0x14,0x0e,0x02,0x07, 0x1e,0x03,0x17,0x23,0x02,0x00,0x25,0x11,0x33,0x11,0x16,0x16,0x17,0x16,0x17,0x36,0x36,0x35,0x11,0x04,0x89,0x28,0x4a,0x68,0x41,0x24,0x52,0x57,0x57,0x28,0xcb,0xc4,0xfe,0x36,0xfe,0xf8,0xaa,0x6f,0xc2,0x48,0x54,0x47,0x5c,0x6c,0x04,0xcd,0xfe,0xc1,0x52,0x83,0x6c,0x58,0x29,0x2b,0x6e,0x79,0x7e,0x3c,0x01,0x23,0x02,0x19,0xf6,0x02, 0x6e,0xfd,0xde,0x6f,0xd2,0x51,0x5f,0x55,0x35,0x99,0x6a,0x01,0x5d,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x09,0x9a,0x06,0xe8,0x00,0x04,0x00,0x08,0x00,0x0c,0x00,0x18,0x00,0x1c,0x00,0x21,0x00,0x2c,0x00,0x31,0x00,0x35,0x00,0x41,0x00,0x45,0x00,0x49,0x00,0x4e,0x00,0x55,0x00,0x5c,0x00,0x64,0x00,0xee,0x40,0x10,0x05,0x32,0x06,0x33, 0x0a,0x19,0x46,0x1a,0x47,0x4b,0x2d,0x61,0x4a,0xce,0x3c,0x36,0xb8,0x01,0x50,0xb2,0x5d,0x53,0x5a,0x41,0x0a,0x01,0x52,0x00,0x25,0x00,0x29,0x01,0x52,0x00,0x4f,0x00,0x22,0x01,0x50,0x00,0x56,0x00,0x0d,0x01,0x50,0x40,0x28,0x16,0x02,0x1e,0x3c,0x5d,0x25,0x4f,0x56,0x16,0x1e,0x1e,0x16,0x56,0x4f,0x25,0x5d,0x3c,0x07,0x0a,0x42,0xce, 0x43,0x2f,0x4b,0x09,0x00,0x1d,0xce,0x0a,0x0b,0x44,0x30,0x0a,0x43,0x48,0x20,0x4c,0x0f,0x25,0x39,0xb8,0x01,0x56,0xb4,0x63,0x14,0x5a,0x63,0x59,0xb8,0x01,0x56,0xb2,0x53,0x52,0x5f,0xb8,0x01,0x56,0x40,0x19,0x3f,0x26,0x17,0x3f,0x01,0x2f,0x4c,0x63,0x53,0x3f,0x2f,0x2f,0x3f,0x53,0x63,0x4c,0x05,0x30,0x34,0x48,0x1e,0x33,0x47,0x03, 0x4b,0xb8,0x01,0x4d,0xb6,0x06,0x1a,0x03,0x07,0x1b,0x03,0x30,0x00,0x2f,0x17,0x33,0xc4,0x32,0x3f,0x17,0x33,0xc4,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x33,0x10,0xed,0x32,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x10,0xc6,0x32,0x10,0xc6,0x32,0x01,0x2f,0xe4,0x32,0x32,0x2f,0x33,0x33, 0xe4,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x10,0xe4,0x32,0x32,0x10,0xc4,0x32,0xc4,0x32,0x10,0xc4,0x32,0xc4,0x32,0x31,0x30,0x01,0x23,0x01,0x35,0x21,0x05,0x21,0x35,0x21,0x01,0x23,0x11,0x33,0x01,0x10,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x35,0x11, 0x33,0x01,0x21,0x35,0x21,0x01,0x21,0x35,0x01,0x33,0x01,0x14,0x21,0x21,0x11,0x21,0x20,0x15,0x14,0x07,0x16,0x01,0x01,0x23,0x11,0x21,0x01,0x21,0x35,0x21,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x23,0x11,0x33,0x01,0x21,0x35,0x21,0x05,0x21,0x11,0x33,0x01,0x01,0x34,0x23,0x23,0x15,0x33,0x32,0x17,0x34, 0x23,0x23,0x11,0x33,0x32,0x01,0x10,0x23,0x22,0x11,0x10,0x33,0x32,0x09,0x9a,0x78,0xfe,0xf3,0x01,0x85,0xfd,0x4e,0xfe,0x7d,0x01,0x83,0x02,0xb2,0x78,0x78,0xfe,0xc0,0xfd,0x67,0x3d,0x55,0x20,0x2f,0x71,0x8c,0xfb,0xda,0xfe,0x7e,0x01,0x82,0x05,0x66,0xfe,0x7b,0x01,0x0d,0x78,0xfd,0x12,0xfe,0xb7,0xfe,0xe0,0x01,0x1b,0x01,0x2a,0x6a, 0x8e,0xfa,0xd9,0xfe,0xf3,0x78,0x01,0x85,0x05,0x63,0xfe,0x7d,0x01,0x83,0xfd,0x19,0xc5,0xb8,0xb8,0xc0,0xc0,0xb8,0xb8,0xc5,0xfc,0x77,0x78,0x78,0x03,0xbc,0xfe,0x7e,0x01,0x82,0xfd,0x51,0xfe,0x7b,0x78,0x01,0x0d,0x04,0x79,0xc5,0x6c,0x7a,0xb7,0x22,0xcc,0x87,0x96,0xbd,0xfd,0x54,0xf0,0xec,0xec,0xf0,0x05,0x65,0x01,0x09,0x7a,0x7a, 0x7a,0xfb,0xca,0x01,0x82,0xfe,0xa8,0xfe,0xe1,0x36,0x5e,0x1e,0xa4,0x02,0x45,0x01,0x52,0x7a,0xf9,0x18,0x78,0x01,0x0d,0x01,0x41,0xfa,0x03,0x50,0xe0,0x6f,0x3d,0x36,0x03,0x14,0xfe,0xf7,0x01,0x83,0xf9,0x18,0x78,0x02,0xfa,0xd1,0xe4,0xe4,0xd1,0xd1,0xe7,0xe7,0xfe,0x6f,0x01,0x82,0xfb,0xcc,0x78,0x78,0x01,0x85,0xfe,0xf3,0x03,0xb8, 0x75,0xe6,0xf9,0x82,0xfe,0xf7,0x01,0x33,0x01,0x43,0xfe,0xbd,0xfe,0xc1,0x00,0x01,0x00,0x00,0xfe,0x09,0x01,0xb0,0xff,0x9e,0x00,0x07,0x00,0x1a,0x40,0x0a,0x07,0x01,0x06,0x04,0x02,0x01,0x04,0x06,0x06,0x09,0x11,0x00,0x33,0x2f,0xdd,0x32,0xcd,0x01,0x2f,0xcd,0xdd,0xcd,0x30,0x31,0x05,0x23,0x11,0x23,0x11,0x23,0x35,0x21,0x01,0xb0, 0xa5,0x66,0xa5,0x01,0xb0,0xc8,0xfe,0xd1,0x01,0x2f,0x66,0x00,0xff,0xff,0x00,0xa5,0x00,0x00,0x04,0x9a,0x04,0xd4,0x02,0x26,0x0b,0x68,0x00,0x00,0x01,0x07,0x0b,0x5e,0x02,0x2a,0xfe,0x6f,0x00,0x0f,0xb1,0x01,0x2c,0xb8,0xff,0xc0,0xb3,0x10,0x10,0x36,0x2c,0x00,0x11,0x2b,0x35,0x00,0xff,0xff,0x00,0x59,0x00,0x00,0x03,0xeb,0x06,0xa0, 0x02,0x06,0x0b,0x74,0x00,0x00,0xff,0xff,0x00,0x59,0xff,0x04,0x04,0xba,0x06,0xa0,0x02,0x26,0x0b,0xb7,0x00,0x00,0x00,0x07,0x0b,0x58,0x02,0x3f,0x00,0x00,0xff,0xff,0x00,0x59,0xfd,0xff,0x04,0xba,0x06,0xa0,0x02,0x26,0x0b,0xb7,0x00,0x00,0x00,0x07,0x0b,0x59,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x59,0xfd,0xff,0x05,0x40,0x06,0xa0, 0x02,0x26,0x0b,0xb7,0x00,0x00,0x00,0x07,0x0b,0x54,0x02,0x63,0x00,0x00,0x00,0x01,0xff,0x43,0xfe,0x09,0x00,0xbe,0xff,0xb1,0x00,0x18,0x00,0x2a,0x40,0x12,0x02,0x18,0x12,0x11,0x08,0x0b,0x11,0x13,0x05,0x40,0x10,0x10,0x01,0x0a,0xc0,0x11,0x11,0x1a,0x11,0x00,0x33,0x2f,0x1a,0xcc,0x32,0x39,0x2f,0x1a,0xcd,0x33,0x01,0x2f,0xdc,0xcd, 0x10,0xdd,0xdc,0xcd,0x30,0x31,0x13,0x23,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x15,0x1e,0x03,0x15,0xbe,0x66,0x27,0x30,0x31,0x27,0x66,0x0e,0x20,0x35,0x27,0x66,0x28,0x35,0x20,0x0e,0xfe,0x09,0x76,0x35,0x2f,0x2f,0x35,0x76,0x77,0x26,0x40,0x31,0x20,0x06,0x74,0x74,0x06,0x20,0x31,0x40, 0x26,0x00,0x00,0x03,0xff,0x15,0x05,0x4e,0x00,0xeb,0x07,0x0a,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x3f,0xb9,0x00,0x06,0x01,0x51,0xb3,0x00,0x00,0x0c,0x1e,0xbe,0x01,0x51,0x00,0x18,0x00,0x12,0x01,0x51,0x00,0x0c,0x00,0x1b,0x01,0x55,0xb3,0x21,0x21,0x15,0x03,0xbd,0x01,0x55,0x00,0x09,0x00,0x0f,0x01,0x55,0x00,0x15,0x05,0x10,0x00, 0x3f,0xfd,0xde,0xed,0x11,0x33,0x2f,0xed,0x01,0x2f,0xfd,0xde,0xed,0x12,0x39,0x2f,0xed,0x30,0x31,0x03,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x07,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x25,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x5d,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34, 0x8e,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x01,0x1d,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x06,0xaf,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x2d,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x01,0xff,0x73,0x05,0x4e,0x00,0x8e,0x07,0x0a,0x00,0x0b,0x00,0x24,0x40,0x0f,0x04,0x02,0x00,0x40, 0x0a,0x08,0x06,0x07,0x03,0x09,0x01,0x04,0x0b,0xc0,0x05,0xb8,0x05,0x10,0x00,0x3f,0x1a,0xcc,0x17,0x39,0x01,0x2f,0x33,0x33,0x1a,0xcc,0x32,0x32,0x30,0x31,0x13,0x07,0x17,0x07,0x17,0x07,0x23,0x37,0x27,0x37,0x27,0x37,0x8e,0xa1,0xa1,0xa1,0xa1,0xa1,0x7a,0xa1,0xa1,0xa1,0xa1,0xa1,0x07,0x0a,0x59,0x59,0x58,0x59,0x59,0x59,0x59,0x58, 0x59,0x59,0x00,0x02,0xff,0xa1,0x05,0x4e,0x00,0x5f,0x07,0x0a,0x00,0x0b,0x00,0x17,0x00,0x2a,0xb9,0x00,0x0c,0x01,0x51,0xb2,0x12,0x12,0x00,0x41,0x09,0x01,0x51,0x00,0x06,0x00,0x15,0x01,0x55,0x00,0x0f,0x00,0x09,0x01,0x55,0x00,0x03,0x05,0x10,0x00,0x3f,0xfd,0xde,0xed,0x01,0x2f,0xed,0x33,0x2f,0xed,0x30,0x31,0x13,0x14,0x06,0x23, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x27,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x5f,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0xa9,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x03,0xff,0x49,0x05,0x4e,0x00,0xb8, 0x07,0x0a,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x32,0xb9,0x00,0x04,0x01,0x51,0xb2,0x0a,0x0a,0x10,0xb8,0x01,0x51,0xb4,0x16,0x03,0x02,0x03,0x19,0xbe,0x01,0x55,0x00,0x13,0x00,0x0d,0x01,0x55,0x00,0x00,0x00,0x07,0x05,0x10,0x00,0x3f,0x33,0xfd,0xde,0xed,0x32,0x01,0x2f,0xdd,0xde,0xed,0x33,0x2f,0xed,0x30,0x31,0x03,0x23,0x11,0x33, 0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x27,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x51,0x66,0x66,0x01,0x09,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0x05,0x58,0x01,0xa8,0xfe,0xa9,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0xd8,0x2a,0x31,0x2f,0x2c, 0x2a,0x32,0x2f,0x00,0x00,0x01,0xff,0x45,0xfd,0xff,0x00,0xbb,0xff,0xb1,0x00,0x0b,0x00,0x15,0xb7,0x08,0x05,0x00,0x08,0x09,0x03,0x03,0x0d,0x11,0x00,0x33,0x2f,0xdc,0xcd,0x01,0x2f,0xcd,0xcc,0x30,0x31,0x07,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x15,0x22,0x26,0xbb,0x06,0x64,0x04,0x8b,0x85,0xbf,0xb7,0xa0,0x25,0x2c,0x31,0x23, 0x96,0x64,0x64,0xa7,0x00,0x01,0xff,0x61,0x05,0x4e,0x00,0x9f,0x06,0xdf,0x00,0x03,0x00,0x10,0xb3,0x00,0x02,0x03,0x01,0xb8,0x05,0x10,0x00,0x3f,0xcd,0x01,0x2f,0xcd,0x30,0x31,0x13,0x07,0x27,0x37,0x9f,0x9f,0x9f,0x9f,0x06,0x17,0xc9,0xc9,0xc8,0x00,0x00,0x01,0xfe,0xab,0x05,0x4e,0x01,0x56,0x06,0xa3,0x00,0x31,0x00,0x2d,0x40,0x12, 0x00,0x19,0x0f,0x24,0x21,0x28,0x0b,0x08,0x0f,0x08,0x21,0x2d,0x25,0x05,0x14,0x1e,0x0c,0x2d,0xb8,0x05,0x10,0x00,0x3f,0x33,0xcd,0xdd,0xcd,0x33,0x12,0x39,0x39,0x01,0x2f,0xcd,0x33,0xdc,0xcd,0x33,0x12,0x39,0x39,0x30,0x31,0x03,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02, 0x17,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x1b,0x1c,0x28,0x21,0x1d,0x12,0x27,0x31,0x1e,0x24,0x1a,0x38,0x3e,0x18,0x2c,0x3e,0x24,0x22,0x37,0x31,0x2c,0x17,0x1b,0x28,0x20,0x1d,0x12,0x27,0x31,0x1e,0x24,0x1a,0x38,0x3e,0x18,0x2c,0x3e,0x24,0x22,0x37,0x31,0x2b,0x05, 0xdf,0x26,0x31,0x1b,0x0b,0x32,0x2d,0x29,0x31,0x0d,0x48,0x14,0x56,0x45,0x24,0x3d,0x2c,0x19,0x15,0x26,0x36,0x1f,0x26,0x31,0x1b,0x0b,0x32,0x2c,0x29,0x32,0x0d,0x47,0x14,0x56,0x45,0x23,0x3e,0x2c,0x19,0x15,0x26,0x37,0x00,0x01,0xfe,0x26,0x05,0x57,0xff,0x9c,0x07,0x09,0x00,0x0b,0x00,0x14,0xb5,0x05,0x00,0x09,0x08,0x09,0x02,0xb8, 0x05,0x10,0x00,0x3f,0xdc,0xcd,0x01,0x2f,0xdc,0xcd,0x30,0x31,0x03,0x14,0x07,0x23,0x36,0x35,0x34,0x26,0x23,0x35,0x32,0x16,0x64,0x06,0x64,0x04,0x8b,0x85,0xbf,0xb7,0x05,0xaa,0x26,0x2d,0x32,0x24,0x91,0x67,0x64,0xab,0x00,0x01,0x00,0x64,0xfe,0x09,0x01,0xc4,0xff,0xb1,0x00,0x05,0x00,0x40,0x40,0x22,0xb4,0x02,0x01,0x03,0x01,0x00, 0x44,0x04,0x54,0x04,0x02,0xcb,0x04,0x01,0x04,0x80,0xcb,0x05,0x01,0x85,0x05,0x01,0x05,0x02,0x02,0x07,0x02,0x05,0x05,0x01,0xc0,0x03,0x03,0x07,0x11,0x00,0x33,0x2f,0x1a,0xcc,0x39,0x3d,0x2f,0x33,0x11,0x01,0x33,0x18,0x2f,0x33,0x5d,0x5d,0x1a,0xcd,0x5d,0x71,0x32,0x39,0x39,0x5d,0x30,0x31,0x01,0x23,0x27,0x37,0x33,0x07,0x01,0xc4, 0x8d,0xd3,0xd3,0x8d,0xd2,0xfe,0x09,0xd4,0xd4,0xd4,0x00,0x02,0xff,0x42,0xfd,0xff,0x00,0xbb,0xff,0xb1,0x00,0x0b,0x00,0x17,0x00,0x27,0xb3,0x04,0x00,0x07,0x0c,0xb8,0x01,0x51,0xb5,0x12,0x04,0x03,0x0a,0x0a,0x0f,0xb8,0x01,0x55,0xb2,0x15,0x15,0x19,0x11,0x00,0x33,0x2f,0xed,0x33,0x2f,0xdc,0xcd,0x01,0x2f,0xfd,0xde,0xcd,0xce,0x30, 0x31,0x17,0x14,0x06,0x23,0x35,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x07,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0xbb,0xb7,0xbf,0x85,0x8b,0x04,0x64,0x06,0xc0,0x33,0x29,0x2a,0x33,0x31,0x2a,0x2a,0x34,0xa0,0xba,0xa7,0x64,0x64,0x96,0x23,0x31,0x2c,0x3a,0x2a,0x31,0x2f,0x2c,0x2a,0x32,0x2f,0x00,0x00,0x01,0xff,0x45, 0x05,0x57,0x00,0xbb,0x07,0x09,0x00,0x0b,0x00,0x14,0xb5,0x07,0x03,0x00,0x04,0x03,0x09,0xb8,0x05,0x10,0x00,0x3f,0xdc,0xcd,0x01,0x2f,0xcc,0xcd,0x30,0x31,0x03,0x34,0x36,0x33,0x15,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0xbb,0xb7,0xbf,0x85,0x8b,0x04,0x64,0x06,0x05,0xa8,0xba,0xa7,0x64,0x64,0x97,0x22,0x31,0x2c,0x00,0x01,0x00,0x64, 0x05,0x57,0x01,0xda,0x07,0x09,0x00,0x0b,0x00,0x14,0xb5,0x07,0x03,0x00,0x04,0x03,0x09,0xb8,0x05,0x10,0x00,0x3f,0xdc,0xcd,0x01,0x2f,0xcc,0xcd,0x30,0x31,0x13,0x34,0x36,0x33,0x15,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x64,0xb7,0xbf,0x85,0x8b,0x04,0x64,0x06,0x05,0xa8,0xba,0xa7,0x64,0x64,0x97,0x22,0x31,0x2c,0x00,0x02,0xfe,0xe1, 0x05,0x57,0x01,0x1f,0x07,0x09,0x00,0x0b,0x00,0x17,0x00,0x25,0x40,0x0e,0x13,0x10,0x0c,0x0c,0x03,0x07,0x00,0x10,0x0f,0x0f,0x04,0x03,0x15,0x09,0xb8,0x05,0x10,0x00,0x3f,0x33,0xdc,0xcd,0x33,0x2f,0xcd,0x01,0x2f,0xcd,0xcc,0x32,0x2f,0xcc,0xcd,0x30,0x31,0x01,0x34,0x36,0x33,0x15,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x25,0x34,0x36, 0x33,0x15,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0xfe,0xe1,0x8c,0x92,0x5a,0x5e,0x04,0x64,0x06,0x01,0x20,0x8c,0x92,0x5a,0x5e,0x04,0x64,0x06,0x05,0xa8,0xba,0xa7,0x64,0x64,0x97,0x22,0x31,0x2c,0x25,0xba,0xa7,0x64,0x64,0x97,0x22,0x31,0x2c,0x00,0x04,0xfe,0x06,0x05,0x35,0x01,0xfa,0x07,0x0a,0x00,0x0f,0x00,0x1b,0x00,0x2b,0x00,0x37, 0x00,0x44,0x40,0x1f,0x29,0x32,0x1e,0x2c,0x24,0x2b,0x1e,0x02,0x16,0x00,0x0d,0x10,0x07,0x29,0x2a,0x35,0x2a,0x27,0x27,0x04,0x02,0x01,0x13,0x04,0x2f,0x21,0x21,0x19,0x0a,0x01,0x04,0x00,0x2f,0xce,0xdc,0xcd,0x33,0x2f,0xcd,0x10,0xcd,0x11,0x39,0x11,0x33,0x2f,0xce,0xcd,0x11,0x39,0x01,0x2f,0xcd,0xdc,0xce,0xcd,0x32,0xde,0xce,0xdc, 0xcd,0x10,0xcd,0x32,0x30,0x31,0x03,0x07,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x25,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x05,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x07,0x27,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x28,0x3e, 0x6d,0x29,0x3f,0x4f,0x70,0x71,0x4e,0x54,0x6f,0x1c,0xfe,0xeb,0x43,0x2e,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x02,0x3d,0x1c,0x6f,0x54,0x4e,0x71,0x70,0x4f,0x3f,0x29,0x6d,0x3e,0x01,0x81,0x43,0x2e,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x05,0x73,0x3e,0x6e,0x1e,0x6f,0x53,0x50,0x73,0x70,0x53,0x3e,0x28,0x66,0x2f,0x44,0x44,0x2f,0x2f,0x44,0x44, 0x95,0x28,0x3e,0x53,0x70,0x73,0x50,0x53,0x6f,0x1e,0x6e,0x3e,0xd4,0x2f,0x44,0x44,0x2f,0x2f,0x44,0x44,0x00,0x02,0xff,0x17,0x05,0x35,0x00,0xe9,0x07,0x0a,0x00,0x0f,0x00,0x1b,0x00,0x24,0x40,0x0f,0x0d,0x16,0x02,0x10,0x08,0x0f,0x02,0x0d,0x0e,0x19,0x0e,0x0b,0x13,0x05,0x0b,0x00,0x2f,0xdc,0xcd,0x10,0xce,0xcd,0x11,0x39,0x01,0x2f, 0xce,0xdc,0xcd,0x10,0xcd,0x32,0x30,0x31,0x03,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x07,0x27,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x7d,0x1c,0x6f,0x54,0x4e,0x71,0x70,0x4f,0x3f,0x29,0x6d,0x3e,0x01,0x81,0x43,0x2e,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x05,0xe1,0x28,0x3e,0x53,0x70, 0x73,0x50,0x53,0x6f,0x1e,0x6e,0x3e,0xd4,0x2f,0x44,0x44,0x2f,0x2f,0x44,0x44,0x00,0x00,0x01,0xff,0x5b,0x05,0x58,0x00,0xa6,0x07,0x00,0x00,0x11,0x00,0x2f,0x40,0x15,0x06,0x0a,0x09,0x11,0x40,0x00,0xc0,0x09,0x04,0x40,0x0d,0x40,0x09,0x10,0x48,0x0d,0x0d,0x11,0x09,0xc0,0x07,0xb8,0x05,0x10,0x00,0x3f,0x1a,0xcd,0x32,0x39,0x2f,0x2b, 0x1a,0xcd,0x01,0x2f,0x1a,0xdc,0x1a,0xcd,0x10,0xcd,0x32,0x30,0x31,0x13,0x15,0x14,0x06,0x23,0x22,0x27,0x15,0x23,0x11,0x33,0x15,0x16,0x33,0x32,0x36,0x35,0x35,0xa6,0x57,0x57,0x22,0x17,0x64,0x64,0x0f,0x1c,0x30,0x26,0x07,0x00,0x76,0x58,0x65,0x0a,0x7f,0x01,0xa8,0xcf,0x0b,0x2c,0x39,0x75,0x00,0x01,0xff,0x43,0xfe,0x09,0x00,0xbe, 0xff,0xb1,0x00,0x18,0x00,0x30,0x40,0x17,0x09,0x0a,0x10,0x13,0x01,0x00,0x13,0x10,0x13,0x40,0x05,0x40,0x09,0x10,0x48,0x05,0x05,0x12,0xc0,0x09,0x01,0x01,0x1a,0x11,0x00,0x33,0x2f,0x33,0x1a,0xcc,0x39,0x2f,0x2b,0x1a,0xcd,0x32,0x01,0x2f,0xdd,0xcd,0x10,0xdd,0xdd,0xcd,0x30,0x31,0x07,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35, 0x33,0x15,0x14,0x0e,0x02,0x07,0x15,0x23,0x35,0x2e,0x03,0x35,0xbd,0x66,0x27,0x30,0x31,0x27,0x66,0x0e,0x20,0x35,0x27,0x66,0x28,0x35,0x20,0x0e,0x4f,0x76,0x35,0x2f,0x2f,0x35,0x76,0x77,0x26,0x40,0x31,0x20,0x06,0x74,0x74,0x06,0x20,0x31,0x40,0x26,0x00,0x01,0xff,0x6a,0xfe,0x09,0x00,0x96,0xff,0xb1,0x00,0x05,0x00,0x15,0xb7,0x05, 0x02,0x04,0x02,0x01,0x05,0x05,0x07,0x11,0x00,0x33,0x2f,0xdc,0xcd,0x01,0x2f,0xce,0xcd,0x30,0x31,0x13,0x21,0x35,0x33,0x11,0x33,0x96,0xfe,0xd4,0xc6,0x66,0xfe,0x09,0x66,0x01,0x42,0x00,0x00,0x01,0xff,0x4b,0xfe,0x09,0x00,0xab,0xff,0xb1,0x00,0x05,0x00,0x40,0x40,0x22,0xb4,0x02,0x01,0x03,0x01,0x00,0x44,0x04,0x54,0x04,0x02,0xcb, 0x04,0x01,0x04,0x80,0xcb,0x05,0x01,0x85,0x05,0x01,0x05,0x02,0x02,0x07,0x02,0x05,0x05,0x01,0xc0,0x03,0x03,0x07,0x11,0x00,0x33,0x2f,0x1a,0xcc,0x39,0x3d,0x2f,0x33,0x11,0x01,0x33,0x18,0x2f,0x33,0x5d,0x5d,0x1a,0xcd,0x5d,0x71,0x32,0x39,0x39,0x5d,0x30,0x31,0x13,0x23,0x27,0x37,0x33,0x07,0xab,0x8d,0xd3,0xd3,0x8d,0xd2,0xfe,0x09, 0xd4,0xd4,0xd4,0x00,0x00,0x01,0xff,0x45,0xfd,0xff,0x00,0xbb,0xff,0xb1,0x00,0x0b,0x00,0x15,0xb7,0x04,0x00,0x07,0x04,0x03,0x0a,0x0a,0x0d,0x11,0x00,0x33,0x2f,0xdc,0xcd,0x01,0x2f,0xcd,0xce,0x30,0x31,0x17,0x14,0x06,0x23,0x35,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0xbb,0xb7,0xbf,0x85,0x8b,0x04,0x64,0x06,0xa0,0xba,0xa7,0x64,0x64, 0x96,0x23,0x31,0x2c,0x00,0x02,0xfe,0xe1,0xfd,0xff,0x01,0x1f,0xff,0xb1,0x00,0x0b,0x00,0x17,0x00,0x26,0x40,0x10,0x00,0x07,0x04,0x04,0x0c,0x10,0x13,0x10,0x0f,0x0f,0x04,0x03,0x16,0x0a,0x0a,0x19,0x11,0x00,0x33,0x2f,0x33,0xdc,0xcd,0x33,0x2f,0xcd,0x01,0x2f,0xce,0xcd,0x32,0x10,0xde,0xcd,0x30,0x31,0x05,0x14,0x06,0x23,0x35,0x32, 0x36,0x35,0x34,0x27,0x33,0x16,0x05,0x14,0x06,0x23,0x35,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x01,0x1f,0x8c,0x92,0x5a,0x5e,0x04,0x64,0x06,0xfe,0xe0,0x8c,0x92,0x5a,0x5e,0x04,0x64,0x06,0xa0,0xba,0xa7,0x64,0x64,0x96,0x23,0x31,0x2c,0x25,0xba,0xa7,0x64,0x64,0x96,0x23,0x31,0x2c,0x00,0x01,0xff,0x68,0xfd,0xff,0x00,0x99,0xff,0xbb, 0x00,0x09,0x00,0x2a,0x40,0x11,0x04,0x09,0x00,0x08,0x80,0x05,0x03,0x09,0x07,0x04,0x04,0x03,0x02,0x08,0x07,0x07,0x0b,0x11,0x00,0x33,0x2f,0x33,0xcc,0x32,0x39,0x19,0x2f,0x12,0x39,0x01,0x18,0x2f,0x33,0x1a,0xcc,0x32,0x39,0x39,0x30,0x31,0x13,0x07,0x07,0x35,0x37,0x27,0x37,0x37,0x15,0x07,0x99,0x4d,0xe4,0xa8,0xa8,0x4d,0xe4,0xaa, 0xfe,0x67,0x41,0x27,0x5c,0x1b,0xdd,0x41,0x27,0x59,0x1e,0x00,0x00,0x01,0xff,0x45,0x05,0x4d,0x00,0xbb,0x07,0x09,0x00,0x0b,0x00,0x14,0xb5,0x08,0x00,0x05,0x08,0x09,0x02,0xb8,0x05,0x10,0x00,0x3f,0xdc,0xcd,0x01,0x2f,0xcd,0xce,0x30,0x31,0x13,0x14,0x07,0x23,0x36,0x35,0x34,0x26,0x23,0x35,0x32,0x16,0xbb,0x06,0x64,0x04,0x8b,0x85, 0xbf,0xb7,0x05,0xa0,0x26,0x2d,0x32,0x24,0x9b,0x67,0x64,0xab,0x00,0x02,0xff,0x17,0x05,0x35,0x00,0xe9,0x07,0x0a,0x00,0x0f,0x00,0x1b,0x00,0x22,0x40,0x0e,0x02,0x16,0x00,0x0d,0x10,0x07,0x02,0x01,0x13,0x04,0x19,0x0a,0x01,0x04,0x00,0x2f,0xce,0xdc,0xcd,0x10,0xcd,0x11,0x39,0x01,0x2f,0xcd,0xdc,0xce,0xcd,0x32,0x30,0x31,0x13,0x07, 0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x25,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0xe9,0x3e,0x6d,0x29,0x3f,0x4f,0x70,0x71,0x4e,0x54,0x6f,0x1c,0xfe,0xeb,0x43,0x2e,0x2e,0x42,0x42,0x2e,0x2e,0x43,0x05,0x73,0x3e,0x6e,0x1e,0x6f,0x53,0x50,0x73,0x70,0x53,0x3e,0x28,0x66,0x2f,0x44, 0x44,0x2f,0x2f,0x44,0x44,0x00,0xff,0xff,0xff,0x43,0xfe,0x09,0x00,0xbe,0xff,0xb1,0x02,0x06,0x0b,0xd0,0x00,0x00,0x00,0x01,0xff,0x4b,0x05,0x4d,0x00,0xb5,0x07,0x09,0x00,0x05,0x00,0x31,0x40,0x17,0x00,0x04,0x80,0x84,0x05,0x94,0x05,0x02,0x05,0x34,0x03,0x01,0x03,0x34,0x01,0x01,0x01,0x02,0x05,0x05,0x03,0xc0,0x00,0xb8,0x05,0x10, 0x00,0x3f,0x1a,0xcc,0x39,0x3d,0x2f,0x01,0x18,0x2f,0x33,0x71,0x33,0x71,0x33,0x5d,0x1a,0xcd,0x32,0x30,0x31,0x13,0x23,0x27,0x37,0x33,0x07,0xb5,0x8d,0xdd,0xdd,0x8d,0xdc,0x05,0x4d,0xde,0xde,0xde,0x00,0x01,0xff,0x6a,0x05,0x58,0x00,0x96,0x07,0x00,0x00,0x05,0x00,0x14,0xb5,0x05,0x02,0x04,0x05,0x02,0x00,0xb8,0x05,0x10,0x00,0x3f, 0xcd,0xcd,0x01,0x2f,0xce,0xcd,0x30,0x31,0x13,0x21,0x35,0x33,0x11,0x33,0x96,0xfe,0xd4,0xc6,0x66,0x05,0x58,0x66,0x01,0x42,0x00,0x01,0x00,0x64,0xfd,0xff,0x01,0xda,0xff,0xb1,0x00,0x0b,0x00,0x15,0xb7,0x08,0x05,0x00,0x08,0x09,0x02,0x02,0x0d,0x11,0x00,0x33,0x2f,0xdc,0xcd,0x01,0x2f,0xdd,0xce,0x30,0x31,0x17,0x34,0x37,0x33,0x06, 0x15,0x14,0x16,0x33,0x15,0x22,0x26,0x64,0x06,0x64,0x04,0x8b,0x85,0xbf,0xb7,0xa0,0x25,0x2c,0x31,0x23,0x96,0x64,0x64,0xa7,0x00,0x01,0xfd,0x87,0x05,0x4e,0x00,0x32,0x06,0xa3,0x00,0x31,0x00,0x2d,0x40,0x12,0x00,0x19,0x0f,0x24,0x21,0x28,0x0b,0x08,0x0f,0x08,0x21,0x2d,0x25,0x05,0x14,0x1e,0x0c,0x2d,0xb8,0x05,0x10,0x00,0x3f,0x33, 0xcd,0xdd,0xcd,0x33,0x12,0x39,0x39,0x01,0x2f,0xcd,0x33,0xdc,0xcd,0x33,0x12,0x39,0x39,0x30,0x31,0x01,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0xfe,0xc1,0x1c, 0x28,0x21,0x1d,0x12,0x27,0x31,0x1e,0x24,0x1a,0x38,0x3e,0x18,0x2c,0x3e,0x24,0x22,0x37,0x31,0x2c,0x17,0x1b,0x28,0x20,0x1d,0x12,0x27,0x31,0x1e,0x24,0x1a,0x38,0x3e,0x18,0x2c,0x3e,0x24,0x22,0x37,0x31,0x2b,0x05,0xdf,0x26,0x31,0x1b,0x0b,0x32,0x2d,0x29,0x31,0x0d,0x48,0x14,0x56,0x45,0x24,0x3d,0x2c,0x19,0x15,0x26,0x36,0x1f,0x26, 0x31,0x1b,0x0b,0x32,0x2c,0x29,0x32,0x0d,0x47,0x14,0x56,0x45,0x23,0x3e,0x2c,0x19,0x15,0x26,0x37,0x00,0x00,0x02,0xff,0x29,0x05,0x4e,0x00,0xd8,0x06,0xfd,0x00,0x0b,0x00,0x17,0x00,0x18,0xb7,0x12,0x06,0x0c,0x00,0x15,0x03,0x0f,0x09,0xb8,0x05,0x10,0x00,0x3f,0xcd,0xdc,0xcd,0x01,0x2f,0xcd,0xdc,0xcd,0x30,0x31,0x03,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0xd7,0x78,0x5f,0x5f,0x79,0x79,0x5f,0x5f,0x78,0x60,0x43,0x34,0x35,0x43,0x43,0x35,0x34,0x43,0x06,0x25,0x55,0x83,0x83,0x55,0x55,0x82,0x82,0x55,0x2f,0x48,0x48,0x2f,0x2f,0x49,0x49,0x00,0xff,0xff,0xff,0xa4,0x05,0x4e,0x00,0x5d, 0x06,0x05,0x02,0x06,0x0b,0x5c,0x00,0x00,0x00,0x01,0x00,0xab,0x00,0x00,0x02,0xcb,0x04,0xde,0x00,0x19,0x00,0x2c,0xb5,0x0b,0x0b,0x18,0x18,0x1b,0x15,0x41,0x0a,0x01,0x50,0x00,0x00,0x00,0x16,0x01,0x54,0x00,0x18,0x01,0x4d,0x00,0x10,0x01,0x54,0x00,0x07,0x01,0x4a,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0x2f, 0x31,0x30,0x13,0x34,0x3e,0x04,0x33,0x32,0x16,0x17,0x17,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x11,0x21,0x17,0x21,0xab,0x0b,0x1b,0x2f,0x49,0x65,0x45,0x25,0x56,0x1c,0x18,0x08,0x1f,0x24,0x24,0x0f,0x44,0x52,0x2b,0x0d,0x01,0x62,0x13,0xfd,0xe0,0x03,0x1b,0x3a,0x71,0x64,0x54,0x3e,0x22,0x08,0x06,0x94,0x02,0x04,0x03,0x02,0x2c,0x50, 0x6d,0x41,0xfd,0x85,0xa2,0x00,0xff,0xff,0x00,0xb6,0x00,0xfc,0x01,0x6f,0x04,0xcd,0x02,0x26,0x0b,0x71,0x00,0x00,0x00,0x07,0x0b,0x5e,0x01,0x11,0xfe,0xe4,0x00,0x01,0xfe,0xb2,0x05,0x67,0x01,0x4f,0x06,0x78,0x00,0x0d,0x00,0x15,0xb7,0x00,0x01,0x08,0x07,0x00,0x08,0x0b,0x04,0x00,0x2f,0xcd,0xcc,0x32,0x01,0x2f,0x33,0xcc,0x32,0x30, 0x31,0x13,0x33,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0xc8,0x87,0x17,0xaa,0x8d,0x8e,0xa9,0x18,0x87,0x10,0x60,0x51,0x5e,0x60,0x06,0x78,0x84,0x8d,0x8a,0x87,0x49,0x54,0x51,0x00,0x01,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0x9a,0x00,0x19,0x00,0x8c,0x40,0x5f,0x59,0x17,0x01,0x48,0x17,0x01,0x56,0x13,0x01,0x79, 0x06,0x01,0x6a,0x06,0x01,0x0b,0x06,0x1b,0x06,0x02,0x9a,0x05,0x01,0x68,0x05,0x01,0x2a,0x05,0x01,0x96,0x03,0x01,0x24,0x03,0x01,0x05,0x03,0x15,0x03,0x02,0x66,0x02,0x76,0x02,0x02,0x0d,0x0d,0x00,0x7d,0x10,0x19,0x20,0x19,0x30,0x19,0x03,0x19,0x19,0x1b,0x0f,0x11,0x7d,0x08,0x0b,0x0b,0x8a,0x0a,0x01,0x69,0x0a,0x79,0x0a,0x02,0x4b, 0x0a,0x01,0x0a,0x0f,0x08,0x1f,0x08,0x02,0x08,0x00,0x00,0x15,0x0a,0x0f,0x91,0x0d,0x03,0x15,0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0xfd,0xc4,0x12,0x39,0x2f,0x01,0x2f,0x5d,0x33,0x5d,0x5d,0x5d,0x33,0x2f,0x10,0xed,0x32,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x01,0x10,0x07,0x06,0x21,0x20,0x27,0x26,0x11,0x10,0x13,0x23,0x35,0x21,0x15,0x21,0x04,0x11,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x11,0x05,0xaa,0xac,0xb6,0xfe,0xb6,0xfe,0xc6,0xb6,0xb0,0xf1,0xf1,0x05,0x4c,0xfc,0x89,0xfe,0xdb,0x7a,0x87,0xef,0xfc,0x86,0x7a,0x02,0xc8,0xfe,0xb4,0xc4,0xd0,0xc8,0xc1,0x01,0x3b,0x01,0x55,0x01,0x01, 0x98,0x98,0xef,0xfe,0xa8,0xf4,0x9c,0xac,0xaa,0x9b,0x01,0x04,0x00,0x01,0x00,0x33,0x00,0x00,0x04,0xf0,0x05,0x9a,0x00,0x16,0x00,0x5a,0x40,0x39,0x46,0x0e,0x01,0x37,0x0e,0x01,0x78,0x05,0x01,0x5b,0x05,0x01,0x16,0x15,0x7e,0x12,0x02,0x02,0x18,0x0a,0x0c,0x7e,0x68,0x09,0x78,0x09,0x02,0x09,0x0f,0x07,0x2f,0x07,0x3f,0x07,0x4f,0x07, 0x04,0x07,0x40,0x10,0x13,0x48,0x07,0x02,0x04,0x91,0x12,0x10,0x10,0x15,0x0a,0x13,0x03,0x15,0x91,0x01,0x12,0x00,0x3f,0xed,0x3f,0xc4,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x2b,0x5d,0x33,0x5d,0xed,0x32,0x12,0x39,0x2f,0xc4,0xfd,0xcd,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x11,0x06,0x23,0x22,0x02,0x35,0x34,0x37,0x33,0x06, 0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x11,0x33,0x11,0x33,0x04,0xf0,0xfe,0x97,0xbc,0xc3,0xd7,0xfe,0x5b,0xb0,0x63,0x52,0x55,0x96,0xb2,0xbd,0xa8,0xc1,0x02,0x7b,0x73,0x01,0x08,0xd8,0xfe,0xb4,0xce,0xe0,0x97,0x59,0x5c,0x70,0x02,0x8a,0xfa,0xfe,0x00,0x00,0x01,0x00,0x64,0xff,0x35,0x05,0x23,0x05,0xb2,0x00,0x17,0x00,0x5b,0x40,0x37, 0x82,0x14,0x01,0x8a,0x12,0x01,0x76,0x08,0x01,0x67,0x08,0x01,0x65,0x07,0x01,0x7a,0x05,0x01,0x69,0x05,0x01,0x16,0x7e,0x04,0x17,0x7e,0x02,0x04,0x02,0x04,0x02,0x19,0x0c,0x0a,0x7e,0x0d,0x0f,0x0f,0x1f,0x0f,0x02,0x0f,0x0c,0x0d,0x0d,0x16,0x06,0x91,0x13,0x04,0x16,0x91,0x01,0x03,0x12,0x00,0x3f,0xce,0xed,0x3f,0xed,0x11,0x39,0x2f, 0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x23,0x35,0x21,0x11,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x37,0x36,0x33,0x20,0x11,0x11,0x21,0x05,0x23,0x9c,0xfe,0x89,0xff,0x00,0x8a,0x44,0x36,0x22,0x96,0x34,0x66,0x71, 0xd5,0x01,0xa8,0x01,0x6b,0xcb,0xcb,0x03,0xe0,0x01,0x48,0x6c,0x56,0x83,0x64,0x4e,0x46,0x6a,0x8e,0xc9,0x7c,0x8a,0xfe,0x34,0xfc,0xb2,0x00,0x02,0x00,0x5a,0xff,0xe8,0x05,0x4c,0x05,0x9a,0x00,0x16,0x00,0x26,0x00,0x7c,0x40,0x53,0x29,0x25,0x79,0x25,0x02,0x26,0x21,0x76,0x21,0x02,0x26,0x1d,0x76,0x1d,0x02,0x29,0x19,0x79,0x19,0x02, 0x8a,0x0b,0x01,0x8a,0x0a,0x01,0x89,0x06,0x01,0x86,0x02,0x01,0x12,0x7e,0x0c,0x11,0x11,0x00,0x7d,0x17,0x50,0x0c,0x01,0x10,0x17,0x20,0x17,0x50,0x17,0x60,0x17,0x04,0x0c,0x17,0x0c,0x17,0x28,0x1f,0x7d,0x08,0x0e,0x0e,0x0f,0x08,0x1f,0x08,0x2f,0x08,0x03,0x08,0x1b,0x91,0x0c,0x13,0x12,0x0d,0x91,0x0f,0x03,0x23,0x91,0x04,0x13,0x00, 0x3f,0xed,0x3f,0xfd,0xc4,0xdd,0x32,0xed,0x01,0x2f,0x5d,0x33,0x2f,0x10,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x10,0xed,0x32,0x2f,0x10,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x07,0x06,0x21,0x20,0x27,0x26,0x11,0x34,0x37,0x36,0x37,0x35,0x21,0x35,0x21,0x15,0x21,0x15,0x16,0x17,0x16,0x07,0x34,0x27, 0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x05,0x4c,0xbe,0xb3,0xfe,0xfa,0xfe,0xfc,0xb7,0xc0,0xa0,0x99,0xec,0xfd,0xdb,0x04,0xf2,0xfd,0xdb,0xe9,0x9b,0xa1,0xb0,0x87,0x82,0xc0,0xbf,0x82,0x88,0x87,0x82,0xc0,0xbf,0x82,0x88,0x02,0x28,0xfe,0xfa,0xa2,0x98,0xa0,0xa9,0x01,0x04,0xee,0xa0,0x99,0x16,0x90,0x98, 0x98,0x90,0x19,0xa0,0xa5,0xe5,0xc3,0x79,0x73,0x74,0x7a,0xc1,0xc3,0x79,0x73,0x74,0x79,0x00,0x00,0x01,0x00,0x64,0x00,0x00,0x03,0xb8,0x05,0xb2,0x00,0x13,0x00,0x51,0x40,0x34,0x96,0x12,0x01,0x72,0x12,0x82,0x12,0x02,0x8a,0x10,0x01,0x79,0x10,0x01,0x7a,0x0f,0x01,0x56,0x06,0x66,0x06,0x02,0x59,0x03,0x69,0x03,0x02,0x00,0x7e,0x02, 0x02,0x15,0x0a,0x08,0x7e,0x0b,0x0f,0x0d,0x1f,0x0d,0x02,0x0d,0x0a,0x0b,0x0b,0x01,0x04,0x91,0x11,0x04,0x01,0x12,0x00,0x3f,0x3f,0xed,0x11,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34, 0x37,0x36,0x33,0x20,0x11,0x03,0xb8,0xa8,0xff,0x00,0x8a,0x44,0x36,0x22,0x96,0x34,0x66,0x71,0xd5,0x01,0xa8,0x03,0xe0,0x01,0x48,0x6c,0x56,0x83,0x64,0x4e,0x46,0x6a,0x8e,0xc9,0x7c,0x8a,0xfe,0x34,0x00,0x01,0x00,0x64,0x00,0x00,0x05,0x23,0x05,0xb2,0x00,0x19,0x00,0x6f,0x40,0x44,0xa7,0x16,0x01,0x84,0x16,0x01,0x71,0x16,0x01,0x06, 0x16,0x01,0x7a,0x14,0x8a,0x14,0x02,0x7a,0x13,0x01,0x66,0x0a,0x01,0x6a,0x07,0x01,0x03,0x18,0x7e,0x06,0x19,0x7e,0x01,0x00,0x06,0x01,0x06,0x01,0x06,0x01,0x1b,0x0e,0x0c,0x7e,0x0f,0x0f,0x11,0x1f,0x11,0x02,0x11,0x0e,0x0f,0x19,0x91,0x01,0x03,0x0f,0x03,0x0f,0x03,0x05,0x08,0x91,0x15,0x04,0x05,0x12,0x00,0x3f,0x3f,0xed,0x11,0x39, 0x39,0x2f,0x2f,0x10,0xce,0xed,0x11,0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x10,0xfd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x23,0x11,0x23,0x11,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x37,0x36,0x33,0x20,0x11,0x15,0x21,0x05,0x23,0x9c, 0xcf,0xa8,0xff,0x00,0x8a,0x44,0x36,0x22,0x96,0x34,0x66,0x71,0xd5,0x01,0xa8,0x01,0x6b,0x01,0xc2,0xcb,0xfd,0x73,0x03,0xe0,0x01,0x48,0x6c,0x56,0x83,0x64,0x4e,0x46,0x6a,0x8e,0xc9,0x7c,0x8a,0xfe,0x34,0xc1,0x00,0x02,0x00,0x32,0xff,0xe8,0x05,0x9a,0x05,0x9a,0x00,0x12,0x00,0x22,0x00,0x51,0x40,0x18,0x4a,0x21,0x5a,0x21,0x02,0x45, 0x1d,0x55,0x1d,0x02,0x45,0x19,0x55,0x19,0x02,0x5a,0x15,0x01,0x49,0x15,0x01,0x00,0x7e,0x13,0xb8,0xff,0xc0,0x40,0x19,0x09,0x0c,0x48,0x13,0x13,0x24,0x1b,0x7e,0x0d,0x7e,0x0a,0x08,0x17,0x91,0x0d,0x0f,0x10,0x09,0x91,0x0c,0x03,0x1f,0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0xed,0x01,0x2f,0xce,0xed,0xed,0x12,0x39,0x2f, 0x2b,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x21,0x35,0x21,0x11,0x36,0x33,0x32,0x17,0x16,0x07,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x05,0x9a,0x85,0x8b,0xee,0xe7,0x87,0x84,0xfe,0x88,0x02,0x20,0x88,0xda,0xee,0x80,0x78,0xa8,0x4a,0x55, 0xab,0xaa,0x5b,0x51,0x54,0x5c,0xa6,0xab,0x54,0x4b,0x02,0x04,0xf1,0x93,0x98,0x94,0x8f,0xe9,0x03,0x0e,0x98,0xfe,0x07,0x77,0x95,0x8d,0xf8,0xb3,0x67,0x76,0x78,0x6c,0xb0,0xab,0x6a,0x73,0x74,0x66,0x00,0x02,0x00,0x5e,0x00,0x00,0x05,0xe7,0x05,0x9a,0x00,0x0e,0x00,0x17,0x00,0x6b,0x40,0x45,0x06,0x15,0x86,0x15,0x02,0x9b,0x0a,0x01, 0x89,0x0a,0x01,0x7c,0x0a,0x01,0x6e,0x0a,0x01,0x0a,0x48,0x0e,0x49,0x29,0x0a,0x01,0x1a,0x0a,0x01,0x59,0x07,0x69,0x07,0x02,0x0d,0x03,0x7e,0x0f,0x0e,0x7e,0x02,0x00,0x0f,0x01,0x0f,0x02,0x0f,0x02,0x19,0x13,0x7d,0x0f,0x09,0x1f,0x09,0x02,0x09,0x0e,0x91,0x01,0x03,0x03,0x04,0x10,0x91,0x0c,0x03,0x0f,0x91,0x04,0x12,0x00,0x3f,0xed, 0x3f,0xed,0x11,0x39,0x2f,0xce,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x10,0xfd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x23,0x11,0x21,0x20,0x27,0x26,0x11,0x10,0x21,0x21,0x11,0x21,0x01,0x11,0x23,0x20,0x11,0x10,0x17,0x16,0x21,0x05,0xe7,0x9c,0xcf,0xfe,0xe8,0xfe, 0xa8,0xd4,0xda,0x02,0xf6,0x01,0x28,0x01,0x6b,0xfd,0xed,0x7c,0xfd,0xb6,0x9f,0x9c,0x01,0x19,0x01,0xc2,0xcb,0xfd,0x73,0xc2,0xc8,0x01,0x55,0x02,0xbb,0xfd,0x8b,0xfd,0x73,0x04,0x6a,0xfd,0xd9,0xfe,0xe9,0x98,0x94,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x03,0x08,0x05,0x9a,0x00,0x05,0x00,0x1a,0x40,0x0c,0x05,0x7e,0x02,0x02,0x07,0x03, 0x02,0x91,0x05,0x03,0x01,0x12,0x00,0x3f,0x3f,0xed,0x01,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x21,0x35,0x21,0x03,0x08,0xa8,0xfd,0xc0,0x02,0xe8,0x05,0x02,0x98,0x00,0x02,0x00,0x8c,0x00,0x00,0x04,0x7c,0x05,0x9a,0x00,0x11,0x00,0x21,0x00,0x6a,0x40,0x45,0x35,0x0f,0x01,0x35,0x0e,0x01,0x3a,0x06,0x01,0x3a,0x05,0x01, 0x45,0x0f,0x01,0x46,0x0e,0x01,0x4a,0x06,0x01,0x49,0x05,0x01,0x12,0x7e,0x11,0x7e,0x10,0x02,0x01,0x02,0x02,0x23,0x1a,0x7e,0x0b,0x7e,0x08,0x16,0x91,0x64,0x0b,0x01,0x35,0x0b,0x45,0x0b,0x55,0x0b,0x03,0x0b,0x0d,0x0a,0x03,0x1e,0x91,0x49,0x02,0x59,0x02,0x02,0x3a,0x02,0x01,0x02,0x04,0x01,0x12,0x00,0x3f,0xde,0x32,0x5d,0x5d,0xed, 0x3f,0xde,0x32,0x5d,0x5d,0xed,0x01,0x2f,0xed,0xed,0x12,0x39,0x2f,0x5d,0xfd,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x33,0x11,0x36,0x33,0x32,0x17,0x16,0x15,0x23,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x04,0x7c, 0xa8,0x88,0xda,0xed,0x81,0x78,0xa8,0x88,0xda,0xed,0x81,0x78,0xa8,0x4c,0x55,0xa9,0xa6,0x5c,0x54,0x4c,0x55,0xa9,0xa6,0x5c,0x54,0x01,0x30,0x77,0x96,0x8c,0xf2,0x02,0xcd,0xfe,0xd0,0x77,0x96,0x8c,0xf2,0xaf,0x67,0x74,0x75,0x6a,0xab,0xaf,0x67,0x74,0x75,0x6a,0x00,0x02,0x00,0x32,0xff,0xe8,0x05,0x9a,0x05,0x9a,0x00,0x13,0x00,0x23, 0x00,0x61,0x40,0x3f,0x43,0x12,0x53,0x12,0x02,0x4a,0x06,0x01,0x49,0x05,0x59,0x05,0x02,0x5b,0x02,0x01,0x4a,0x02,0x01,0x00,0x7e,0x10,0x14,0x20,0x14,0x30,0x14,0x03,0x14,0x14,0x07,0x25,0x0c,0x7e,0x0a,0x1c,0x7e,0x0e,0x7e,0x0f,0x07,0x01,0x07,0x18,0x91,0x55,0x0e,0x01,0x46,0x0e,0x01,0x0e,0x10,0x10,0x0a,0x08,0x91,0x0d,0x03,0x20, 0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0xfd,0xce,0x3f,0x33,0x5d,0x5d,0xed,0x01,0x2f,0x5d,0xed,0xed,0xde,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x00,0x35,0x11,0x23,0x15,0x23,0x11,0x21,0x11,0x36,0x33,0x32,0x17,0x16,0x07,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15, 0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x05,0x9a,0x85,0x8b,0xee,0xe2,0xfe,0xf0,0xdc,0x9c,0x02,0x20,0x88,0xda,0xee,0x80,0x78,0xa8,0x4a,0x55,0xab,0xaa,0x5b,0x51,0x54,0x5c,0xa6,0xab,0x54,0x4b,0x02,0x04,0xf1,0x93,0x98,0x01,0x20,0xec,0x03,0x0e,0xcb,0x01,0x63,0xfe,0x07,0x77,0x95,0x8d,0xf8,0xb3,0x67,0x76,0x78,0x6c,0xb0,0xab,0x6a, 0x73,0x74,0x66,0x00,0x00,0x02,0x00,0x5c,0xff,0xe8,0x05,0xb0,0x05,0x9a,0x00,0x17,0x00,0x21,0x00,0x7c,0x40,0x53,0x5b,0x0f,0x01,0x3a,0x0f,0x4a,0x0f,0x02,0x3a,0x0e,0x4a,0x0e,0x5a,0x0e,0x03,0x5a,0x0a,0x01,0x49,0x0a,0x01,0x3a,0x0a,0x01,0x49,0x09,0x01,0x36,0x07,0x46,0x07,0x56,0x07,0x03,0x35,0x06,0x45,0x06,0x55,0x06,0x03,0x17, 0x7e,0x01,0x03,0x16,0x7e,0x11,0x00,0x19,0x10,0x19,0x02,0x19,0x19,0x23,0x1c,0x7e,0x0c,0x13,0x13,0x0f,0x0c,0x1f,0x0c,0x02,0x0c,0x11,0x16,0x91,0x03,0x01,0x19,0x19,0x1e,0x12,0x91,0x15,0x03,0x1e,0x91,0x08,0x13,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xcc,0xc4,0xfd,0xc4,0x01,0x2f,0x5d,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x5d, 0xc4,0xfd,0xc4,0xdc,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x23,0x11,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x01,0x11,0x21,0x20,0x11,0x10,0x21,0x32,0x37,0x36,0x05,0xb0,0x9c,0xc8,0x83,0x87,0xe8,0xef,0x8a,0x85,0x78,0x7e,0xef,0x01, 0x63,0xfc,0xf4,0x03,0xb4,0x01,0x64,0xfd,0xf4,0xfe,0xaf,0xfe,0xb1,0x01,0x4a,0xa7,0x5b,0x54,0x02,0x9d,0xcb,0xfe,0x8c,0xea,0x8f,0x93,0x93,0x8f,0xf0,0xf0,0x87,0x8f,0x01,0x02,0x98,0xfe,0x66,0xfd,0xf8,0x01,0x70,0xfe,0x8c,0xfe,0x7e,0x72,0x69,0x00,0x00,0x01,0x00,0xc9,0x00,0x00,0x04,0xa4,0x05,0x9a,0x00,0x19,0x00,0x3d,0x40,0x20, 0x95,0x17,0x01,0x94,0x0b,0x01,0x0f,0x0f,0x00,0x7e,0x02,0x02,0x08,0x1b,0x13,0x06,0x7e,0x08,0x13,0x15,0x91,0x06,0x04,0x04,0x08,0x10,0x91,0x0e,0x03,0x01,0x08,0x12,0x00,0x3f,0xc4,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xed,0x32,0x2f,0x31,0x30,0x00,0x5d,0x5d,0x21,0x23,0x11,0x34,0x23, 0x22,0x07,0x11,0x23,0x11,0x34,0x37,0x36,0x33,0x21,0x15,0x21,0x22,0x15,0x11,0x36,0x33,0x32,0x17,0x16,0x15,0x04,0xa4,0xa8,0xf5,0xb4,0xe2,0xa8,0x6c,0x67,0xb8,0x02,0x14,0xfd,0xfe,0xf5,0xe4,0xc6,0xb7,0x67,0x6b,0x02,0x12,0xe8,0x6e,0xfd,0x74,0x04,0x28,0xb5,0x60,0x5d,0x98,0xe8,0xfe,0xfa,0x7a,0x5e,0x61,0xb5,0x00,0x02,0x00,0x5e, 0xfe,0xea,0x05,0xaa,0x05,0xb2,0x00,0x1f,0x00,0x2f,0x00,0xc8,0x40,0x8d,0x59,0x2e,0x01,0x99,0x2d,0x01,0x6a,0x2d,0x01,0x54,0x2b,0x64,0x2b,0x02,0x56,0x2a,0x86,0x2a,0x02,0x86,0x26,0x01,0x67,0x26,0x01,0x56,0x26,0x01,0x64,0x25,0x01,0x56,0x25,0x01,0x6a,0x23,0x01,0x59,0x22,0x01,0x86,0x16,0x01,0x75,0x16,0x01,0x76,0x12,0x01,0x27, 0x12,0x01,0x13,0x12,0x01,0x04,0x12,0x01,0x24,0x11,0x94,0x11,0x02,0x07,0x11,0x01,0x29,0x0f,0x99,0x0f,0x02,0x79,0x0e,0x01,0x0a,0x0e,0x1a,0x0e,0x02,0x79,0x0a,0x01,0x1b,0x0a,0x01,0x0a,0x0a,0x01,0x2a,0x09,0x9a,0x09,0x02,0x09,0x09,0x01,0x19,0x7e,0x06,0x1f,0x1f,0x14,0x7d,0x20,0x40,0x06,0x01,0x10,0x20,0x20,0x20,0x30,0x20,0x03, 0x06,0x20,0x06,0x20,0x31,0x28,0x7d,0x0f,0x0c,0x1f,0x0c,0x02,0x0c,0x24,0x91,0x10,0x04,0x1f,0x1d,0x91,0x00,0x02,0x2c,0x91,0x06,0x08,0x13,0x00,0x3f,0x33,0xed,0xdc,0x32,0xed,0x32,0x3f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x10,0xed,0x32,0x2f,0x10,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x06,0x23,0x22,0x27,0x26,0x27,0x06,0x23,0x20,0x27,0x26,0x11,0x10,0x37,0x36,0x21,0x20,0x17,0x16,0x11,0x10,0x07,0x06,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x03,0x10,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16, 0x33,0x32,0x37,0x36,0x05,0xaa,0x34,0x3c,0x88,0x5e,0x61,0x02,0x6e,0x85,0xfe,0xc8,0xb8,0xb0,0xb1,0xbb,0x01,0x4c,0x01,0x35,0xb4,0xab,0xba,0x23,0x43,0x39,0x32,0x45,0x3c,0x34,0xb0,0x73,0x81,0xfc,0xf2,0x8b,0x7f,0x7b,0x88,0xed,0xfc,0x86,0x7a,0xff,0x17,0x51,0x54,0x7e,0x25,0xd1,0xc7,0x01,0x3c,0x01,0x51,0xcd,0xd8,0xd2,0xc7,0xfe, 0xc6,0xfe,0xa1,0xcc,0x22,0x48,0x37,0x4a,0x2c,0x28,0x1f,0x03,0x34,0x01,0x05,0x9d,0xb0,0xb3,0xa3,0xf9,0xf5,0xa3,0xb4,0xaa,0x9b,0x00,0x00,0x01,0x00,0x32,0xff,0xe8,0x05,0xd5,0x05,0x9a,0x00,0x0f,0x00,0x45,0x40,0x2a,0x35,0x0c,0x01,0x26,0x0c,0x01,0x96,0x0a,0x01,0x33,0x0a,0x01,0x25,0x0a,0x01,0x59,0x03,0x01,0x4b,0x03,0x01,0x4a, 0x01,0x01,0x0f,0x7e,0x0d,0x0d,0x11,0x09,0x7e,0x07,0x05,0x0e,0x05,0x91,0x08,0x03,0x0b,0x91,0x02,0x13,0x00,0x3f,0xed,0x3f,0xed,0xc4,0x01,0x2f,0xcd,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x20,0x11,0x11,0x21,0x35,0x21,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x05,0xd5,0xfd, 0xdf,0xfd,0xf6,0xfe,0x88,0x02,0x20,0x01,0x74,0x01,0x67,0xa8,0x02,0x44,0xfd,0xa4,0x02,0x45,0x02,0xd5,0x98,0xfc,0x9e,0xfe,0x47,0x01,0xaa,0x03,0x71,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x05,0x43,0x05,0x9a,0x00,0x16,0x00,0x48,0x40,0x29,0x47,0x10,0x01,0x36,0x10,0x01,0x58,0x06,0x01,0x5a,0x05,0x01,0x14,0x00,0x7e,0x02,0x02,0x18, 0x0c,0x0e,0x7e,0x0a,0x09,0x0f,0x07,0x01,0x07,0x14,0x12,0x91,0x02,0x04,0x04,0x01,0x09,0x91,0x15,0x0c,0x03,0x01,0x12,0x00,0x3f,0x3f,0xc4,0xed,0x11,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x5d,0x33,0xce,0xed,0x32,0x12,0x39,0x2f,0xed,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x02,0x35,0x34,0x37,0x21,0x35, 0x21,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x11,0x33,0x05,0x43,0xa8,0xbc,0xc3,0xd7,0xfe,0x23,0xfe,0xc8,0x02,0x20,0x63,0x52,0x55,0x96,0xb2,0xbd,0xa8,0x02,0x7b,0x73,0x01,0x08,0xd8,0x94,0x86,0x98,0xce,0xe0,0x97,0x59,0x5c,0x70,0x02,0x8a,0x00,0x00,0x01,0x00,0x64,0xff,0xe8,0x05,0x23,0x05,0x9a,0x00,0x19,0x00,0x61,0x40,0x3c, 0x69,0x14,0x79,0x14,0x02,0x66,0x11,0x76,0x11,0x02,0x8a,0x07,0x01,0x96,0x05,0x01,0x80,0x05,0x01,0x05,0x05,0x01,0x19,0x7e,0x01,0x18,0x03,0x7e,0x00,0x15,0x01,0x15,0x15,0x1b,0x0d,0x0f,0x7e,0x0c,0x0f,0x0a,0x1f,0x0a,0x02,0x0a,0x0d,0x0c,0x19,0x91,0x01,0x03,0x0c,0x03,0x0c,0x03,0x16,0x03,0x13,0x91,0x06,0x13,0x00,0x3f,0xed,0x3f, 0x39,0x39,0x2f,0x2f,0x10,0xce,0xed,0x11,0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x12,0x39,0x2f,0x5d,0xfd,0xc4,0xde,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x23,0x15,0x10,0x21,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x11,0x11,0x33,0x11,0x21,0x05,0x23,0x9c,0xcf,0xfe,0x58,0xd5, 0x71,0x66,0x34,0x96,0x22,0x36,0x44,0x8a,0x01,0x00,0xa8,0x01,0x6b,0x01,0xc2,0xcb,0xd9,0xfe,0x34,0x8a,0x7c,0xc9,0x8e,0x6a,0x46,0x4e,0x64,0x83,0x56,0x6c,0x01,0x48,0x03,0xe0,0xfd,0x8b,0x00,0x01,0x00,0xb0,0xff,0xe8,0x04,0x04,0x05,0x9a,0x00,0x13,0x00,0x4b,0x40,0x2f,0x59,0x0d,0x69,0x0d,0x02,0x66,0x0a,0x01,0x57,0x0a,0x01,0x99, 0x05,0x01,0x8a,0x05,0x01,0x7b,0x05,0x01,0x75,0x02,0x01,0x12,0x00,0x7e,0x11,0x10,0x0f,0x20,0x0f,0x02,0x0f,0x0f,0x15,0x09,0x7e,0x06,0x11,0x12,0x12,0x08,0x03,0x0b,0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x2f,0x5d,0x33,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07, 0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x21,0x32,0x37,0x36,0x35,0x34,0x27,0x37,0x16,0x04,0x04,0x65,0x72,0xd5,0xfe,0x58,0xa8,0x01,0x00,0x8a,0x44,0x36,0x22,0x96,0x34,0x01,0xb7,0xc9,0x7c,0x8a,0x01,0xcc,0x03,0xe6,0xfc,0x20,0xfe,0xb8,0x6c,0x56,0x83,0x64,0x4e,0x46,0x6a,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a, 0x00,0x0e,0x00,0x15,0x00,0x53,0x40,0x34,0x38,0x15,0x48,0x15,0x02,0x56,0x09,0x01,0x57,0x06,0x01,0x77,0x05,0x87,0x05,0x02,0x65,0x05,0x01,0x53,0x05,0x01,0x0e,0x0e,0x07,0x7d,0x10,0x0f,0x20,0x0f,0x02,0x0f,0x0f,0x01,0x17,0x13,0x0c,0x7e,0x01,0x0c,0x91,0x14,0x14,0x0d,0x12,0x91,0x02,0x03,0x0d,0x91,0x01,0x12,0x00,0x3f,0xed,0x3f, 0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x11,0x21,0x32,0x17,0x16,0x15,0x14,0x07,0x06,0x23,0x23,0x11,0x21,0x03,0x10,0x21,0x23,0x11,0x33,0x20,0x04,0x29,0xfc,0x93,0x01,0x8a,0xdc,0x7e,0x89,0x99,0x8f,0xe0,0xbd,0x02,0xc5,0xb0,0xfe, 0xb0,0xc5,0xb0,0x01,0x65,0x05,0x9a,0x66,0x70,0xd6,0xdb,0x7f,0x76,0xfe,0x7a,0x03,0x4e,0x01,0x1c,0xfd,0xb4,0x00,0x00,0x02,0x00,0x5e,0xfe,0xea,0x05,0xaa,0x05,0xb2,0x00,0x1d,0x00,0x2d,0x00,0xc8,0x40,0x8d,0x6a,0x2c,0x01,0x59,0x2c,0x01,0x69,0x2b,0x99,0x2b,0x02,0x64,0x29,0x01,0x87,0x28,0x01,0x55,0x28,0x01,0x87,0x24,0x01,0x55, 0x24,0x01,0x63,0x23,0x01,0x56,0x23,0x01,0x6b,0x21,0x01,0x59,0x20,0x01,0x07,0x1c,0x01,0x75,0x18,0x01,0x16,0x18,0x01,0x05,0x18,0x01,0x24,0x17,0x94,0x17,0x02,0x15,0x17,0x01,0x07,0x17,0x01,0x99,0x15,0x01,0x2a,0x15,0x01,0x18,0x15,0x01,0x19,0x14,0x79,0x14,0x02,0x0a,0x14,0x01,0x1a,0x10,0x7a,0x10,0x02,0x0b,0x10,0x01,0x99,0x0f, 0x01,0x2c,0x0f,0x01,0x1a,0x0f,0x01,0x09,0x0f,0x01,0x47,0x1c,0x01,0x1c,0x00,0x7e,0x0c,0x05,0x0a,0x0a,0x1a,0x7d,0x10,0x1e,0x20,0x1e,0x30,0x1e,0x03,0x1e,0x1e,0x2f,0x26,0x7d,0x0f,0x12,0x1f,0x12,0x02,0x12,0x22,0x91,0x16,0x04,0x05,0x91,0x06,0x2a,0x91,0x1c,0x0c,0x0e,0x13,0x00,0x3f,0x33,0x33,0xed,0xde,0xed,0x3f,0xed,0x01,0x2f, 0x5d,0xed,0x12,0x39,0x2f,0x5d,0xed,0x33,0x2f,0xcc,0x33,0xed,0x32,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x14,0x06,0x07,0x06,0x23,0x35,0x16,0x37,0x36,0x35,0x34,0x27,0x06,0x21,0x20,0x27,0x26, 0x11,0x10,0x37,0x36,0x21,0x20,0x17,0x16,0x11,0x10,0x07,0x16,0x03,0x10,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x05,0xaa,0x86,0x6b,0x25,0x4d,0x22,0x27,0x82,0x41,0xb4,0xfe,0xe1,0xfe,0xc8,0xb8,0xb0,0xb1,0xbb,0x01,0x4c,0x01,0x35,0xb4,0xab,0x7b,0x7b,0xb0,0x73,0x81,0xfc,0xf2,0x8b,0x7f,0x7b,0x88, 0xed,0xfc,0x86,0x7a,0x1c,0x64,0xa2,0x21,0x0b,0x87,0x03,0x0c,0x28,0x74,0x52,0x2c,0xac,0xd1,0xc7,0x01,0x3c,0x01,0x51,0xcd,0xd8,0xd2,0xc7,0xfe,0xc6,0xfe,0xe3,0xbc,0x55,0x02,0x17,0x01,0x05,0x9d,0xb0,0xb3,0xa3,0xf9,0xf5,0xa3,0xb4,0xaa,0x9b,0x00,0x00,0x03,0x00,0x5a,0x00,0x00,0x05,0x4c,0x05,0xb2,0x00,0x12,0x00,0x1b,0x00,0x24, 0x00,0x79,0x40,0x51,0x56,0x24,0x01,0x65,0x23,0x75,0x23,0x02,0x65,0x1f,0x75,0x1f,0x02,0x7b,0x1a,0x01,0x6a,0x1a,0x01,0x59,0x16,0x01,0x6a,0x15,0x7a,0x15,0x02,0x97,0x11,0x01,0x85,0x11,0x01,0x89,0x0d,0x01,0x98,0x09,0x01,0x8b,0x09,0x01,0x86,0x02,0x01,0x13,0x7d,0x10,0x00,0x20,0x00,0x02,0x00,0x04,0x18,0x7e,0x07,0x21,0x7d,0x1f, 0x0b,0x2f,0x0b,0x02,0x0b,0x1c,0x07,0x18,0x1c,0x91,0x07,0x04,0x04,0x06,0x17,0x1d,0x91,0x0f,0x04,0x06,0x12,0x00,0x3f,0x3f,0xed,0x32,0x11,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xc4,0xdd,0x5d,0xed,0x10,0xfd,0xc4,0xdc,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x07, 0x11,0x23,0x11,0x26,0x27,0x26,0x35,0x10,0x37,0x36,0x21,0x20,0x17,0x16,0x03,0x34,0x27,0x26,0x27,0x11,0x36,0x37,0x36,0x05,0x11,0x06,0x07,0x06,0x15,0x14,0x17,0x16,0x05,0x4c,0xa1,0x9b,0xe9,0xa8,0xec,0x99,0xa0,0xc0,0xb7,0x01,0x04,0x01,0x06,0xb3,0xbe,0xb0,0x6c,0x67,0xa2,0xa3,0x66,0x6c,0xfd,0xe3,0xa3,0x66,0x6c,0x6c,0x67,0x03, 0x72,0xec,0xa5,0xa0,0x19,0xfe,0xd8,0x01,0x28,0x16,0x99,0xa0,0xee,0x01,0x04,0xa9,0xa0,0x98,0xa2,0xfe,0xf3,0xab,0x75,0x6e,0x1a,0xfc,0xaf,0x19,0x6f,0x75,0xfc,0x03,0x51,0x19,0x6f,0x75,0xac,0xaa,0x75,0x6f,0x00,0x01,0x00,0x32,0x00,0x00,0x04,0x62,0x05,0x9a,0x00,0x0f,0x00,0x46,0x40,0x2b,0x00,0x7e,0x20,0x02,0xa0,0x02,0xb0,0x02, 0xc0,0x02,0x04,0x02,0x03,0x0e,0x7e,0x06,0x07,0x7e,0x2f,0x09,0xaf,0x09,0xbf,0x09,0xcf,0x09,0x04,0x09,0x0b,0x06,0x0e,0x09,0x0b,0x91,0x06,0x01,0x03,0x03,0x05,0x0d,0x03,0x05,0x12,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xce,0xc4,0xfd,0xce,0xc4,0x01,0x2f,0xc4,0xdc,0x5d,0xed,0x10,0xfd,0xc4,0xdd,0x5d,0xed,0x31,0x30,0x01,0x23,0x35,0x21, 0x11,0x23,0x11,0x21,0x11,0x33,0x15,0x21,0x11,0x33,0x11,0x21,0x04,0x62,0x9c,0xfe,0xd8,0xa8,0xfe,0x3c,0x9c,0x01,0x28,0xa8,0x01,0xc4,0x02,0x9d,0xcb,0xfc,0x98,0x03,0x68,0x01,0x63,0xcb,0x01,0x9a,0xfe,0x66,0x00,0x01,0x00,0xaa,0x00,0x00,0x04,0xd5,0x05,0xb2,0x00,0x0d,0x00,0x38,0x40,0x21,0x45,0x0c,0x01,0x44,0x0a,0x01,0x3a,0x05, 0x01,0x29,0x05,0x01,0x3a,0x03,0x01,0x29,0x03,0x01,0x00,0x7e,0x02,0x02,0x0f,0x06,0x7e,0x08,0x04,0x91,0x0b,0x04,0x01,0x07,0x12,0x00,0x3f,0xc4,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x10,0x21,0x20,0x11,0x11,0x23,0x11,0x10,0x21,0x20,0x11,0x04,0xd5,0xa8,0xfe, 0x93,0xfe,0x92,0xa8,0x02,0x17,0x02,0x14,0x03,0x71,0x01,0xaa,0xfe,0x47,0xfc,0x9e,0x03,0x6d,0x02,0x45,0xfd,0xa4,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x12,0x00,0x3a,0x40,0x20,0x36,0x0c,0x01,0x68,0x06,0x01,0x4a,0x06,0x5a,0x06,0x02,0x10,0x00,0x7e,0x02,0x02,0x14,0x09,0x7e,0x07,0x02,0x04,0x91,0x10,0x0e,0x0e, 0x00,0x09,0x11,0x03,0x00,0x12,0x00,0x3f,0x3f,0xc4,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x02,0x35,0x11,0x33,0x11,0x14,0x17,0x16,0x33,0x32,0x37,0x11,0x33,0x04,0xa2,0xa8,0xbc,0xc3,0xd7,0xfe,0xa8,0x52,0x55,0x96,0xb2,0xbd,0xa8,0x02, 0x7b,0x73,0x01,0x08,0xd8,0x01,0xb2,0xfe,0x52,0x97,0x59,0x5c,0x70,0x02,0x8a,0x00,0x00,0x01,0x00,0xa6,0xff,0xe8,0x04,0x81,0x05,0x9a,0x00,0x21,0x00,0x5c,0x40,0x38,0x86,0x1c,0x01,0x36,0x0f,0x01,0x36,0x0b,0x96,0x0b,0x02,0x27,0x0b,0x01,0x49,0x06,0x59,0x06,0x02,0x49,0x02,0x59,0x02,0x02,0x4a,0x01,0x01,0x21,0x7e,0x12,0x1f,0x1f, 0x18,0x23,0x09,0x7e,0x08,0x08,0x1a,0x7e,0x18,0x1f,0x1d,0x91,0x12,0x09,0x14,0x14,0x0d,0x1a,0x20,0x03,0x0d,0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0xc4,0x12,0x39,0x2f,0xce,0x33,0xed,0x32,0x01,0x2f,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xc4,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22, 0x27,0x26,0x35,0x33,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x11,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x04,0x81,0x85,0x88,0xdf,0xdb,0x8d,0x87,0xa8,0x57,0x61,0x8f,0x90,0x5e,0x56,0xe4,0xc6,0xb7,0x67,0x6b,0xa8,0xf5,0xb4,0xe2,0xa8,0x01,0xb4,0xce,0x7e,0x80,0x8a,0x85,0xc0,0x76,0x63,0x6c, 0x6a,0x61,0x7d,0x01,0x12,0x7a,0x5e,0x61,0xb5,0x01,0xd4,0xfe,0x34,0xe8,0x6e,0x02,0x46,0x00,0x00,0x01,0x00,0xc9,0x00,0x00,0x04,0xc5,0x05,0x9a,0x00,0x12,0x00,0x40,0x40,0x24,0x66,0x11,0x76,0x11,0x02,0x59,0x04,0x01,0x4a,0x04,0x01,0x39,0x04,0x01,0x00,0x7e,0x02,0x02,0x0a,0x14,0x0d,0x08,0x7e,0x0a,0x08,0x06,0x91,0x0d,0x0f,0x0f, 0x0a,0x0c,0x03,0x01,0x0a,0x12,0x00,0x3f,0xc4,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x34,0x27,0x26,0x23,0x22,0x07,0x11,0x23,0x11,0x33,0x11,0x36,0x33,0x32,0x12,0x15,0x04,0xc5,0xa8,0x52,0x55,0x96,0xb2,0xbd,0xa8,0xa8,0xbc,0xc3,0xd7, 0xfe,0x01,0xae,0x97,0x59,0x5c,0x70,0xfd,0x76,0x05,0x9a,0xfd,0x85,0x73,0xfe,0xf8,0xd8,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x05,0x00,0x05,0xb2,0x00,0x1f,0x00,0x83,0x40,0x57,0x66,0x18,0x01,0x06,0x17,0x16,0x17,0x56,0x17,0x66,0x17,0x04,0x56,0x13,0x66,0x13,0x02,0x66,0x12,0x01,0x08,0x0b,0x18,0x0b,0x02,0x29,0x05,0x01,0x77,0x0a, 0x01,0x99,0x07,0x01,0x79,0x06,0x01,0x0f,0x0f,0x1f,0x7e,0x02,0x10,0x1d,0x01,0x1d,0x1d,0x21,0x15,0x7d,0x0f,0x08,0x1f,0x08,0x02,0x08,0x1e,0x1e,0x19,0x0f,0x11,0x91,0x96,0x0e,0x01,0x87,0x0e,0x01,0x76,0x0e,0x01,0x0e,0x0c,0x04,0x1d,0x19,0x91,0x69,0x02,0x79,0x02,0x02,0x02,0x04,0x13,0x00,0x12,0x00,0x3f,0x3f,0x33,0x5d,0xed,0x32, 0x3f,0x33,0x5d,0x5d,0x5d,0xed,0x32,0x11,0x39,0x2f,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xc4,0xed,0x32,0x2f,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x35,0x06,0x23,0x20,0x27,0x26,0x11,0x10,0x37,0x36,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x06,0x11,0x10,0x17,0x16,0x33,0x32,0x37,0x36, 0x37,0x11,0x33,0x05,0x00,0xa8,0xa7,0xb9,0xfe,0xc6,0xb4,0xac,0xbf,0xc5,0x01,0x46,0xe0,0x9f,0xae,0xe4,0xf8,0x8d,0x82,0x7b,0x86,0xfe,0x66,0x5f,0x56,0x30,0xa8,0x40,0x58,0xcd,0xc3,0x01,0x42,0x01,0x4e,0xd2,0xd8,0x4c,0xba,0x6e,0xaf,0xa2,0xfe,0xfd,0xfe,0xf8,0x99,0xa6,0x28,0x23,0x34,0x01,0x56,0x00,0x00,0x02,0x00,0x5c,0xff,0xe8, 0x05,0xb0,0x05,0x9a,0x00,0x15,0x00,0x1f,0x00,0x73,0x40,0x4c,0x39,0x1e,0x01,0x39,0x1d,0x01,0x36,0x1b,0x01,0x35,0x19,0x01,0x4b,0x0f,0x5b,0x0f,0x02,0x49,0x0e,0x59,0x0e,0x02,0x59,0x0a,0x01,0x4a,0x0a,0x01,0x5a,0x09,0x01,0x56,0x07,0x01,0x55,0x06,0x01,0x44,0x06,0x01,0x15,0x7e,0x01,0x03,0x14,0x7e,0x11,0x00,0x17,0x10,0x17,0x02, 0x17,0x17,0x21,0x1a,0x7e,0x0f,0x0c,0x1f,0x0c,0x02,0x0c,0x14,0x11,0x91,0x17,0x01,0x03,0x03,0x12,0x03,0x1c,0x91,0x08,0x13,0x00,0x3f,0xed,0x3f,0x39,0x2f,0xce,0xc4,0xfd,0xc4,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xc4,0xfd,0xc4,0xdc,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35, 0x23,0x11,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x21,0x11,0x33,0x11,0x21,0x01,0x11,0x21,0x20,0x11,0x10,0x21,0x32,0x37,0x36,0x05,0xb0,0x9c,0xc8,0x83,0x87,0xe8,0xef,0x8a,0x85,0x78,0x7e,0xef,0x01,0x63,0xa8,0x01,0x64,0xfd,0xf4,0xfe,0xaf,0xfe,0xb1,0x01,0x4a,0xa7,0x5b,0x54,0x02,0x9d,0xcb,0xfe,0x8c,0xea, 0x8f,0x93,0x93,0x8f,0xf0,0xf0,0x87,0x8f,0x01,0x9a,0xfe,0x66,0xfd,0xf8,0x01,0x70,0xfe,0x8c,0xfe,0x7e,0x72,0x69,0x00,0x02,0x00,0xbc,0x00,0x00,0x04,0x38,0x05,0x9a,0x00,0x12,0x00,0x19,0x00,0x5f,0x40,0x3c,0x67,0x19,0x77,0x19,0x02,0x68,0x14,0x78,0x14,0x02,0x85,0x12,0x95,0x12,0x02,0x86,0x11,0x96,0x11,0x02,0x89,0x02,0x99,0x02, 0x02,0x9a,0x01,0x01,0x89,0x01,0x01,0x00,0x7d,0x13,0x13,0x0d,0x1b,0x07,0x7e,0x09,0x17,0x0b,0x06,0x7e,0x0d,0x08,0x0a,0x91,0x07,0x18,0x91,0x05,0x05,0x0d,0x16,0x91,0x0e,0x03,0x0d,0x12,0x00,0x3f,0x3f,0xed,0x11,0x39,0x2f,0xed,0xde,0xfd,0xcd,0x01,0x2f,0xfd,0xc4,0xc4,0xdc,0xed,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x00,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x21,0x15,0x21,0x11,0x23,0x35,0x23,0x11,0x23,0x11,0x21,0x32,0x17,0x16,0x07,0x34,0x21,0x23,0x11,0x33,0x20,0x04,0x38,0x81,0x78,0xcb,0xfe,0xf0,0x01,0x6b,0x9c,0xcf,0xa8,0x01,0xaa,0xd5,0x79,0x84,0xb1,0xfe,0xc9,0xec,0xec,0x01,0x37,0x04,0x2f,0xb2,0x60,0x59,0x99,0xfe,0x9d,0xcb, 0xfe,0x6d,0x05,0x9a,0x56,0x5e,0xb7,0xd3,0xfe,0x5a,0x00,0x01,0x00,0x64,0xff,0xe8,0x04,0xb5,0x05,0xb2,0x00,0x31,0x00,0xa6,0x40,0x68,0x66,0x31,0x76,0x31,0x02,0x76,0x29,0x01,0x7a,0x27,0x01,0x95,0x20,0x01,0x66,0x20,0x86,0x20,0x02,0x9a,0x1c,0x01,0x8b,0x1c,0x01,0x6c,0x1c,0x01,0x89,0x1a,0x01,0x7c,0x12,0x01,0x56,0x0f,0x01,0x89, 0x07,0x01,0x7a,0x07,0x01,0x69,0x07,0x01,0x66,0x02,0x01,0x66,0x01,0x01,0x23,0x21,0x7d,0x24,0x26,0x26,0x13,0x2e,0x2a,0x00,0x7d,0x17,0x1b,0x20,0x13,0x50,0x13,0x02,0x13,0x13,0x33,0x2a,0x7d,0x1b,0x0b,0x0d,0x7d,0x0a,0x08,0x08,0x1b,0x23,0x23,0x2e,0x28,0x2e,0x1d,0x11,0x0a,0x0a,0x17,0x11,0x17,0x04,0x28,0x91,0x1d,0x04,0x11,0x91, 0x04,0x13,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x2f,0x01,0x2f,0x33,0x2f,0x33,0xed,0x32,0x10,0xed,0x12,0x39,0x2f,0x5d,0x12,0x39,0xed,0x11,0x39,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14, 0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x11,0x34,0x27,0x26,0x27,0x26,0x27,0x26,0x35,0x10,0x21,0x32,0x17,0x16,0x15,0x14,0x07,0x23,0x36,0x35,0x34,0x21,0x20,0x15,0x14,0x17,0x16,0x17,0x16,0x17,0x16,0x04,0xb5,0xab,0x8c,0xec,0xe8,0x93,0xb3,0x0f,0xb4,0x12,0x81,0x62,0x9c,0x01,0x71, 0x7a,0x49,0xa5,0xf5,0x70,0xaf,0x01,0xfa,0xcb,0x84,0xa1,0x0a,0xae,0x08,0xfe,0xbe,0xfe,0xb8,0x80,0x48,0xaa,0xee,0x73,0xa9,0x01,0x85,0xdd,0x6a,0x56,0x57,0x6b,0xd9,0x43,0x40,0x43,0x42,0x8e,0x42,0x32,0x01,0x06,0x85,0x44,0x28,0x1f,0x2e,0x43,0x68,0xcc,0x01,0x78,0x4e,0x5f,0xbd,0x25,0x4b,0x45,0x2b,0xd2,0xe0,0x85,0x42,0x26,0x1e, 0x2b,0x48,0x6b,0x00,0x00,0x01,0x00,0xc9,0x00,0x00,0x04,0xc5,0x05,0x9a,0x00,0x14,0x00,0x46,0x40,0x2a,0x39,0x10,0x01,0x66,0x02,0x76,0x02,0x02,0x45,0x02,0x55,0x02,0x02,0x47,0x01,0x57,0x01,0x02,0x07,0x07,0x14,0x7e,0x12,0x12,0x09,0x16,0x0c,0x05,0x7e,0x09,0x0e,0x91,0x03,0x03,0x06,0x13,0x0b,0x03,0x06,0x91,0x09,0x12,0x00,0x3f, 0xed,0x3f,0xc4,0x12,0x39,0x2f,0xed,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xed,0x32,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x02,0x23,0x22,0x27,0x11,0x21,0x15,0x21,0x11,0x33,0x11,0x16,0x33,0x32,0x37,0x36,0x35,0x11,0x33,0x04,0xc5,0xfe,0xd7,0xc3,0xbc,0x02,0xf2,0xfc,0x66,0xa8,0xbd,0xb2,0x96,0x55,0x52,0xa8,0x03,0xe8, 0xd8,0xfe,0xf8,0x73,0xfe,0x1d,0x98,0x05,0x9a,0xfd,0x76,0x70,0x5c,0x59,0x97,0x01,0xae,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x05,0x1d,0x05,0x9a,0x00,0x0a,0x00,0x0d,0x00,0x6b,0x40,0x41,0x0d,0x0b,0x04,0x0c,0x00,0x0a,0x09,0x03,0x0c,0x00,0x05,0x0b,0x04,0x01,0x06,0x02,0x09,0x03,0x01,0x06,0x0b,0x03,0x09,0x03,0x7e,0x04,0x0b,0x14, 0x04,0x04,0x0b,0x09,0x09,0x0c,0x01,0x06,0x01,0x7e,0x00,0x0c,0x14,0x00,0x0c,0x00,0x00,0x04,0x0f,0x07,0x06,0x06,0x0b,0x04,0x01,0x04,0x0c,0x06,0x0b,0x91,0x09,0x03,0x01,0x00,0x03,0x04,0x12,0x00,0x3f,0xc4,0xdc,0xc4,0x3f,0xfd,0xd4,0xc4,0x01,0x2f,0x5d,0x33,0x2f,0xcd,0x11,0x12,0x39,0x2f,0x87,0x2b,0x87,0x7d,0xc4,0x01,0x33,0x18, 0x2f,0x87,0x10,0x2b,0x87,0x7d,0xc4,0x0f,0x0f,0x0f,0x0f,0x31,0x30,0x25,0x23,0x01,0x01,0x23,0x01,0x01,0x21,0x35,0x21,0x01,0x13,0x21,0x13,0x05,0x1d,0xce,0xfe,0xa3,0xfe,0x0e,0xce,0x02,0x59,0xfe,0xad,0xfe,0xfa,0x04,0xeb,0xfe,0x3c,0x86,0xfe,0x27,0xec,0xcc,0x01,0xdb,0xfd,0x59,0x03,0x33,0x01,0xcf,0x98,0xfd,0x99,0x01,0xcf,0xfe, 0xbd,0x00,0x00,0x01,0x00,0x32,0xff,0xe8,0x05,0xd5,0x05,0x9a,0x00,0x11,0x00,0x55,0x40,0x35,0x29,0x0e,0x39,0x0e,0x49,0x0e,0x03,0x96,0x0c,0x01,0x44,0x0c,0x01,0x35,0x0c,0x01,0x26,0x0c,0x01,0x59,0x03,0x01,0x11,0x7e,0x10,0x0f,0x01,0x0f,0x0f,0x04,0x13,0x09,0x7e,0x07,0x0b,0x7e,0x0f,0x04,0x01,0x04,0x11,0x11,0x0a,0x0d,0x07,0x05, 0x91,0x0a,0x03,0x0d,0x91,0x02,0x13,0x00,0x3f,0xed,0x3f,0xfd,0xce,0x11,0x12,0x39,0x2f,0x01,0x2f,0x5d,0xed,0xde,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x20,0x11,0x11,0x23,0x15,0x23,0x11,0x21,0x11,0x10,0x21,0x20,0x11,0x35,0x33,0x05,0xd5,0xfd,0xdf,0xfd,0xf6,0xdc,0x9c,0x02, 0x20,0x01,0x74,0x01,0x67,0xa8,0x02,0x44,0xfd,0xa4,0x02,0x45,0x02,0xd5,0xcb,0x01,0x63,0xfc,0x9e,0xfe,0x47,0x01,0xaa,0x7f,0x00,0x01,0x00,0xc9,0x00,0x00,0x04,0xf0,0x05,0x9a,0x00,0x11,0x00,0x55,0x40,0x34,0x97,0x0f,0xa7,0x0f,0x02,0x86,0x0f,0x01,0x7a,0x02,0x01,0x00,0x10,0x7e,0x01,0x01,0x09,0x13,0x0c,0x07,0x7e,0x09,0x75,0x0c, 0x01,0x56,0x0c,0x66,0x0c,0x02,0x44,0x0c,0x01,0x23,0x0c,0x33,0x0c,0x02,0x0c,0x0e,0x91,0x03,0x10,0x91,0x01,0x03,0x03,0x08,0x0b,0x03,0x08,0x12,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xde,0xed,0x10,0xed,0x32,0x5d,0x5d,0x5d,0x5d,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xfd,0xcd,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x21,0x10,0x23,0x22, 0x07,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x36,0x33,0x20,0x13,0x33,0x04,0xf0,0xfe,0x95,0xf0,0x94,0x4c,0x44,0xa8,0xa8,0x6f,0xb5,0x01,0x49,0x41,0xd1,0x02,0x44,0x01,0x4a,0x78,0x6b,0xb1,0xfe,0x06,0x05,0x9a,0xfe,0x07,0x77,0xfe,0xc4,0x00,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0x9a,0x00,0x15,0x00,0x64,0x40,0x42,0x27,0x15, 0x01,0x86,0x14,0x01,0x37,0x14,0x01,0x25,0x14,0x01,0x6b,0x0d,0x7b,0x0d,0x02,0x59,0x0d,0x01,0x99,0x09,0x01,0x1b,0x09,0x5b,0x09,0x02,0x08,0x09,0x01,0x65,0x02,0x75,0x02,0x02,0x00,0x7d,0x00,0x0b,0x10,0x0b,0x02,0x0b,0x0b,0x17,0x12,0x7e,0x0f,0x06,0x06,0x0f,0x0f,0x91,0x13,0x10,0x03,0x06,0x08,0x91,0x9a,0x05,0x01,0x05,0x03,0x13, 0x00,0x3f,0x33,0x5d,0xed,0x32,0x3f,0xdc,0xed,0x01,0x2f,0x32,0x2f,0x10,0xed,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x00,0x21,0x22,0x27,0x35,0x16,0x33,0x20,0x00,0x11,0x34,0x00,0x23,0x21,0x11,0x33,0x15,0x33,0x20,0x00,0x04,0x8c,0xfe,0x75,0xfe,0xaf,0xcc,0x86,0x9a,0xba, 0x01,0x0a,0x01,0x20,0xfe,0xf1,0xf9,0xfe,0xf4,0x9c,0x86,0x01,0x3c,0x01,0x66,0x02,0xa7,0xfe,0xba,0xfe,0x87,0x3b,0xb3,0x56,0x01,0x1d,0x01,0x00,0xec,0x01,0x00,0x01,0x11,0x79,0xfe,0xb4,0x00,0x01,0x00,0x33,0x00,0x00,0x04,0x2f,0x05,0x9a,0x00,0x14,0x00,0x3f,0x40,0x24,0x36,0x0e,0x46,0x0e,0x02,0x5b,0x05,0x01,0x12,0x00,0x7e,0x02, 0x02,0x16,0x0a,0x0c,0x7e,0x09,0x07,0x40,0x09,0x0d,0x48,0x07,0x02,0x04,0x91,0x12,0x10,0x10,0x01,0x0a,0x13,0x03,0x01,0x12,0x00,0x3f,0x3f,0xce,0x11,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x2b,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0xc4,0x31,0x30,0x5d,0x5d,0x21,0x23,0x11,0x06,0x23,0x22,0x02,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x17, 0x16,0x33,0x32,0x37,0x11,0x33,0x04,0x2f,0xa8,0xbc,0xc3,0xd7,0xfe,0x33,0xb0,0x3b,0x52,0x55,0x96,0xb2,0xbd,0xa8,0x02,0x7b,0x73,0x01,0x08,0xd8,0x72,0x88,0x92,0x64,0x97,0x59,0x5c,0x70,0x02,0x8a,0x00,0x01,0x00,0x96,0x00,0x00,0x04,0xc4,0x05,0x9a,0x00,0x10,0x00,0x41,0x40,0x26,0x96,0x0b,0x01,0x87,0x0b,0x01,0x49,0x06,0x01,0x3a, 0x06,0x01,0x3a,0x01,0x4a,0x01,0x02,0x09,0x7e,0x07,0x04,0x0f,0x7e,0x00,0x02,0x7e,0x04,0x05,0x02,0x91,0x0c,0x0c,0x04,0x0f,0x09,0x03,0x04,0x12,0x00,0x3f,0x3f,0xc4,0x12,0x39,0x2f,0xed,0x32,0x01,0x2f,0xfd,0xdc,0xed,0x10,0xdc,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x05,0x11,0x23,0x11,0x24,0x11,0x11,0x33,0x11, 0x10,0x21,0x20,0x11,0x11,0x33,0x04,0xc4,0xfe,0x3d,0xa8,0xfe,0x3d,0xa8,0x01,0x6f,0x01,0x6f,0xa8,0x04,0x48,0xfd,0xd4,0x2c,0xfe,0x10,0x01,0xf0,0x2e,0x02,0x13,0x01,0x69,0xfe,0xa2,0xfe,0x47,0x01,0xaa,0x01,0x6d,0x00,0x00,0x03,0x00,0x52,0xff,0xe8,0x06,0x3a,0x05,0x9a,0x00,0x17,0x00,0x22,0x00,0x2e,0x00,0x6b,0x40,0x40,0x89,0x2d, 0x01,0x85,0x27,0x01,0x77,0x27,0x01,0x95,0x17,0x01,0x9a,0x11,0x01,0x94,0x0a,0x01,0x94,0x01,0x01,0x1e,0x07,0x03,0x7e,0x24,0x14,0x06,0x06,0x00,0x7d,0x18,0x14,0x18,0x14,0x18,0x30,0x29,0x7e,0x0f,0x0f,0x1f,0x0f,0x02,0x0f,0x07,0x24,0x91,0x04,0x1e,0x91,0x02,0x14,0x04,0x04,0x2b,0x1d,0x91,0x15,0x03,0x2b,0x91,0x0b,0x13,0x00,0x3f, 0xed,0x3f,0xed,0x11,0x39,0x2f,0xc4,0xde,0xed,0x10,0xfd,0xc4,0x01,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x2f,0x10,0xc4,0xfd,0xc4,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x21,0x15,0x21,0x15,0x21,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x33,0x11,0x21,0x20,0x03, 0x34,0x27,0x26,0x23,0x23,0x11,0x33,0x32,0x37,0x36,0x01,0x35,0x23,0x22,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x36,0x06,0x3a,0xfe,0x3c,0xfe,0xf0,0x02,0x23,0xfd,0xdd,0xcd,0xb6,0xb5,0x6b,0x71,0x81,0x74,0xb1,0xc6,0x01,0xaa,0x01,0xd2,0xb1,0x5b,0x45,0x97,0xec,0xec,0xa4,0x45,0x4e,0xfd,0x35,0xc6,0x65,0x45,0x4c,0xe1,0x69,0x3a,0x38, 0x04,0x61,0xfe,0xc7,0x82,0x98,0xa8,0xb5,0xc9,0x57,0x5c,0xa8,0xab,0x60,0x58,0x02,0xf4,0xfe,0xc7,0x60,0x25,0x1c,0xfe,0xbe,0x21,0x24,0xfd,0x61,0xa8,0x32,0x39,0x60,0xc4,0x41,0x3e,0x00,0x00,0x01,0x00,0x60,0xff,0xea,0x03,0x98,0x04,0x00,0x00,0x2d,0x00,0x58,0x40,0x36,0x99,0x16,0x01,0x88,0x16,0x01,0x95,0x29,0x01,0x76,0x29,0x86, 0x29,0x02,0x27,0x29,0x37,0x29,0x02,0x29,0x00,0x24,0x84,0x23,0x00,0x84,0x19,0x6a,0x1e,0x01,0x1e,0x19,0x10,0x19,0x90,0x19,0x02,0x23,0x19,0x23,0x19,0x2f,0x0f,0x84,0x0a,0x0d,0x0c,0x0c,0x24,0x0f,0x14,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x12,0x39,0x5d,0x10,0xed,0x10, 0xed,0x11,0x39,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x27,0x33,0x1e,0x03,0x17,0x1e,0x03,0x03,0x98,0x44,0x72,0x96,0x51,0x51,0x95,0x72,0x43,0x28,0x9c,0x1e,0x27,0x43,0x59,0x32,0x32,0x5a, 0x43,0x28,0x16,0x28,0x39,0x23,0x36,0x41,0x26,0x0f,0x03,0xa4,0x01,0x0e,0x20,0x35,0x28,0x2c,0x47,0x31,0x1b,0x01,0x4a,0x57,0x84,0x58,0x2d,0x2d,0x58,0x84,0x57,0x5f,0x50,0x37,0x38,0x44,0x36,0x4f,0x34,0x19,0x19,0x34,0x4f,0x36,0x2f,0x49,0x42,0x3f,0x25,0x38,0x57,0x59,0x69,0x4b,0x37,0x54,0x48,0x45,0x28,0x2c,0x52,0x57,0x63,0x00, 0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x50,0x05,0xec,0x00,0x16,0x00,0x26,0x00,0x84,0x40,0x59,0x96,0x21,0x01,0x96,0x1d,0x01,0x53,0x15,0x01,0x44,0x15,0x01,0x53,0x14,0x01,0x42,0x14,0x01,0x09,0x0a,0x01,0x5a,0x06,0x01,0x4b,0x06,0x01,0x59,0x05,0x01,0x56,0x03,0x01,0x56,0x02,0x01,0x45,0x02,0x01,0x17,0x83,0x40,0x00,0x50,0x00,0x02, 0x00,0x12,0x84,0x0c,0x10,0x84,0x0e,0x0c,0x1f,0x83,0x0f,0x08,0x3f,0x08,0x02,0x08,0x4f,0x0c,0x01,0x0c,0x0e,0x95,0x11,0x11,0x0f,0x1b,0x95,0x0c,0x00,0x13,0x10,0x13,0x20,0x13,0x03,0x13,0x10,0x0f,0x00,0x23,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x5d,0x33,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x5d,0xdd,0x5d,0xed,0x10,0xde,0xed, 0x10,0xfd,0xdc,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x10,0x37,0x36,0x37,0x35,0x21,0x11,0x33,0x15,0x21,0x11,0x16,0x17,0x16,0x03,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x04,0x50,0x85,0x8b,0xee, 0xe7,0x87,0x84,0x8d,0x71,0xb2,0xfe,0xb8,0xa4,0x01,0x48,0xb1,0x6b,0x80,0xa8,0x4a,0x55,0xab,0xaa,0x5b,0x51,0x54,0x5c,0xa6,0xab,0x54,0x4b,0x02,0x04,0xf1,0x93,0x98,0x94,0x8f,0xe9,0x01,0x02,0x91,0x74,0x17,0xc9,0x01,0x11,0x79,0xfe,0xa1,0x14,0x75,0x8c,0xfe,0xff,0xb3,0x67,0x76,0x78,0x6c,0xb0,0xab,0x6a,0x73,0x74,0x66,0x00,0x02, 0x00,0x60,0xfe,0x1e,0x04,0x50,0x04,0x18,0x00,0x32,0x00,0x42,0x00,0x8d,0x40,0x5b,0x49,0x42,0x59,0x42,0x02,0x59,0x3e,0x01,0x4a,0x3e,0x01,0x55,0x3b,0x01,0x46,0x3b,0x01,0x6a,0x23,0x01,0x76,0x1a,0x01,0x65,0x1a,0x01,0x07,0x1a,0x17,0x1a,0x02,0x48,0x0e,0x58,0x0e,0x02,0x19,0x0e,0x29,0x0e,0x39,0x0e,0x03,0x19,0x16,0x83,0x2e,0x2b, 0x2e,0x1c,0x83,0x40,0x30,0x40,0x01,0x2e,0x40,0x2e,0x40,0x26,0x44,0x08,0x05,0x83,0x09,0x0c,0x0c,0x38,0x83,0x0f,0x26,0x1f,0x26,0x02,0x26,0x08,0x09,0x33,0x95,0x19,0x2b,0x2b,0x00,0x3d,0x95,0x21,0x1c,0x00,0x95,0x11,0x10,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0xce,0x32,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x33,0xed,0x32, 0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02, 0x33,0x36,0x36,0x35,0x34,0x2e,0x02,0x13,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0xc6,0x2a,0x46,0x32,0x1c,0x06,0x0e,0xa6,0x10,0x06,0x35,0x5f,0x83,0x4f,0x4f,0x82,0x5e,0x34,0x17,0x0e,0xa5,0xa7,0x46,0x83,0xbd,0x78,0x74,0xb9,0x81,0x44,0x46,0x85,0xc2,0x7c,0x0e,0x10,0x1d,0x33,0x47,0x6e,0x57,0x81, 0x54,0x2a,0x2b,0x56,0x80,0x55,0x9f,0xab,0xab,0x03,0x8e,0x1f,0x35,0x45,0x27,0x1b,0x2f,0x39,0x1d,0x46,0x3a,0x20,0x4a,0x7a,0x57,0x2f,0x2f,0x58,0x7d,0x4e,0x43,0x60,0x22,0x28,0xfa,0xc3,0x76,0xbd,0x84,0x47,0x44,0x80,0xb7,0x73,0x7c,0xc1,0x84,0x45,0x27,0x4e,0x35,0x33,0x4f,0x35,0x1b,0xfd,0xfa,0x35,0x62,0x8a,0x55,0x53,0x86,0x5e, 0x33,0xb0,0xbe,0xc0,0xb2,0x00,0x00,0x02,0x00,0x60,0xfe,0x1e,0x06,0xa0,0x04,0x18,0x00,0x3e,0x00,0x52,0x01,0x00,0x40,0xa8,0x97,0x11,0x01,0x95,0x10,0x01,0x57,0x50,0x01,0x55,0x4b,0x01,0x58,0x42,0x01,0x65,0x3d,0x01,0x65,0x3c,0x01,0x55,0x37,0x01,0x56,0x34,0x01,0x47,0x34,0x01,0x36,0x34,0x01,0x46,0x33,0x56,0x33,0x02,0x37,0x33, 0x01,0x39,0x2d,0x49,0x2d,0x59,0x2d,0x03,0x29,0x11,0x01,0x28,0x10,0x01,0x69,0x07,0x01,0x69,0x03,0x01,0x68,0x02,0x01,0x49,0x83,0x0a,0x38,0x9a,0x0c,0x01,0x89,0x0c,0x01,0x68,0x0c,0x78,0x0c,0x02,0x0c,0x0a,0x9d,0x2c,0x01,0x8f,0x2c,0x01,0x2c,0x31,0x92,0x1a,0x01,0x70,0x1a,0x01,0x1a,0x13,0x9d,0x20,0x01,0x7a,0x20,0x8a,0x20,0x02, 0x20,0x1f,0x1f,0x00,0x83,0x3f,0x0a,0x3f,0x0a,0x3f,0x54,0x13,0x83,0x31,0x29,0x29,0x31,0x4e,0x95,0x05,0x05,0x2c,0x44,0x95,0x3a,0x0c,0x0e,0x95,0x56,0x38,0x01,0x25,0x38,0x01,0x14,0x38,0x01,0x05,0x38,0x01,0x38,0x36,0x36,0x3a,0x10,0x26,0x1a,0x01,0x1a,0x20,0x2c,0x95,0x25,0x17,0x29,0x01,0x29,0x95,0x28,0x28,0x25,0x1f,0x20,0x1c, 0x00,0x3f,0x33,0xce,0x32,0x2f,0xed,0x5d,0x10,0xed,0x11,0x39,0x5d,0x3f,0x33,0x2f,0x33,0x5d,0x5d,0x5d,0x5d,0xed,0x32,0x10,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x2f,0x33,0x5d,0x5d,0x12,0x39,0x5d,0x5d,0x12,0x39,0x5d,0x5d,0x11,0x33,0x5d,0x5d,0x5d,0x33,0x10,0xed,0x31, 0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x04,0x17,0x1e,0x03,0x17,0x07,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33, 0x32,0x17,0x36,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x06,0xa0,0x3c,0x74,0xa7,0x6b,0x6b,0xad,0x7b,0x43,0x46,0x6a,0x74,0x4d,0x7a,0x54,0x2d,0x2c,0x52,0x73,0x90,0xa7,0x5c,0x5d,0x96,0x7b,0x66,0x2d,0x68,0x64,0xc7,0xd4,0xe5,0x82,0x6c,0xc8,0x4b,0x4e,0xca,0x6b,0x54, 0x83,0x5c,0x30,0x45,0x81,0xbb,0x75,0xb7,0x83,0x7a,0xb4,0x6b,0xa7,0x74,0x3c,0xa8,0x21,0x45,0x6a,0x4a,0x4a,0x71,0x4c,0x27,0x27,0x4c,0x71,0x4a,0x4a,0x6a,0x45,0x21,0x02,0x2e,0x6a,0xb3,0x82,0x49,0x4a,0x83,0xb3,0x6a,0x9e,0x74,0x4c,0x41,0x70,0x94,0x53,0x61,0x98,0x78,0x5d,0x4c,0x3e,0x1d,0x1d,0x38,0x39,0x39,0x1f,0x7d,0x3f,0x5e, 0x3f,0x20,0x3f,0x3f,0xa8,0x31,0x31,0x2e,0x77,0x91,0xaa,0x62,0x7b,0xcd,0x95,0x53,0x64,0x64,0x4a,0x83,0xb4,0x69,0x46,0x80,0x61,0x39,0x39,0x60,0x7f,0x46,0x47,0x7f,0x61,0x39,0x38,0x60,0x7f,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x04,0x18,0x00,0x2d,0x00,0x6b,0x40,0x45,0x07,0x2b,0x17,0x2b,0x02,0x96,0x20,0x01,0x76,0x1f, 0x86,0x1f,0x96,0x1f,0x03,0x9c,0x1c,0x01,0x79,0x1c,0x89,0x1c,0x02,0x6a,0x16,0x01,0x59,0x16,0x01,0x75,0x12,0x01,0x57,0x12,0x67,0x12,0x02,0x77,0x11,0x01,0x2d,0x84,0x19,0x19,0x0a,0x2f,0x22,0x84,0x23,0x23,0x0d,0x0f,0x84,0x0c,0x0a,0x0d,0x0c,0x22,0x0c,0x22,0x14,0x1d,0x95,0x28,0x10,0x14,0x95,0x05,0x1c,0x00,0x3f,0xed,0x3f,0xed, 0x11,0x39,0x39,0x2f,0x2f,0x33,0x01,0x2f,0x33,0xed,0x32,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e, 0x02,0x33,0x32,0x1e,0x02,0x15,0x03,0xf1,0x4a,0x81,0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c,0x2e,0x4b,0x60,0x32,0x43,0x74,0x55,0x30,0x80,0x71,0x32,0x53,0x3c,0x22,0xa6,0x3e,0x6b,0x8f,0x51,0x50,0x92,0x70,0x43,0x22,0x69,0xa6,0x74,0x3d,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x28,0x4d,0x6d,0x45, 0x02,0xc2,0x79,0x83,0x19,0x34,0x51,0x37,0x55,0x83,0x5a,0x2e,0x2b,0x57,0x85,0x59,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x04,0x18,0x00,0x43,0x00,0x9b,0x40,0x61,0x87,0x3d,0x01,0x76,0x3d,0x01,0x76,0x2d,0x86,0x2d,0x96,0x2d,0x03,0x79,0x29,0x89,0x29,0x99,0x29,0x03,0x5b,0x1c,0x01,0x6a,0x16,0x01,0x59,0x16,0x01,0x56,0x12,0x66, 0x12,0x02,0x75,0x11,0x01,0x3f,0x3e,0x1f,0x3b,0x83,0x26,0x26,0x19,0x1f,0x1f,0x0f,0x00,0x83,0x19,0x19,0x0a,0x45,0x30,0x84,0x31,0x40,0x12,0x18,0x48,0x31,0x31,0x0d,0x0f,0x84,0x0c,0x0f,0x0a,0x1f,0x0a,0x02,0x0a,0x0d,0x0c,0x3f,0x3e,0x1e,0x31,0x31,0x2b,0x20,0x95,0x1e,0x0c,0x1e,0x0c,0x1e,0x14,0x2b,0x95,0x36,0x10,0x14,0x95,0x05, 0x1c,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x39,0x2f,0x11,0x39,0x39,0x11,0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x33,0x2f,0x2b,0xed,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x11,0x33,0x2f,0xed,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x03,0xf1,0x4a,0x81,0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c,0x2e,0x4b, 0x60,0x32,0x43,0x73,0x53,0x2f,0x38,0x68,0x94,0x5b,0x3b,0x35,0x59,0x80,0x53,0x28,0x1f,0x3c,0x58,0x39,0x32,0x56,0x40,0x25,0xa6,0x41,0x6f,0x92,0x51,0x55,0x93,0x6d,0x3f,0x98,0x8d,0x49,0x82,0x62,0x39,0x0e,0x75,0xb0,0x75,0x3a,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x26,0x4d,0x77,0x51,0x50,0x7c,0x54, 0x2b,0x8b,0x1a,0x39,0x59,0x3e,0x34,0x57,0x3d,0x22,0x1b,0x35,0x50,0x35,0x5a,0x84,0x57,0x2b,0x2d,0x57,0x80,0x52,0x89,0xa3,0x18,0x04,0x0b,0x43,0x66,0x85,0x00,0x03,0x00,0x3c,0xff,0xe8,0x05,0xcc,0x06,0x02,0x00,0x1a,0x00,0x2a,0x00,0x36,0x00,0x6e,0x40,0x44,0x48,0x36,0x58,0x36,0x02,0x46,0x33,0x56,0x33,0x02,0x47,0x2f,0x57,0x2f, 0x02,0x65,0x19,0x01,0x66,0x02,0x01,0x00,0x83,0x10,0x2b,0x30,0x2b,0x02,0x2b,0x2b,0x08,0x38,0x0f,0x84,0x23,0x31,0x83,0x08,0x1b,0x1b,0x15,0x84,0x0f,0x08,0x01,0x08,0x09,0x0b,0x95,0x27,0x2d,0x95,0x17,0x15,0x17,0x27,0x17,0x27,0x17,0x35,0x1f,0x95,0x12,0x01,0x35,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f, 0x11,0x33,0x10,0xed,0x10,0xed,0x32,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x10,0xed,0xdc,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x21,0x22,0x27,0x26,0x35,0x11,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x36,0x33,0x20,0x11,0x11,0x36,0x33,0x32,0x17,0x16,0x01,0x34,0x27,0x26,0x23,0x22,0x07, 0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x01,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x05,0xcc,0x6c,0x76,0xfe,0xf8,0xe5,0x80,0x79,0x31,0x64,0x91,0x52,0x50,0x9f,0x94,0x01,0x3d,0x88,0xc6,0xea,0x7a,0x6e,0xfc,0x38,0x24,0x28,0x44,0x44,0x28,0x24,0x24,0x28,0x43,0x43,0x29,0x25,0x03,0x20,0xfe,0xca,0xa8,0x53, 0x47,0x4a,0x55,0xa3,0x01,0x36,0x01,0xf0,0xf0,0x81,0x97,0x8f,0x88,0xe1,0x01,0xd3,0x2c,0x57,0x54,0x91,0x94,0xab,0xfe,0xc9,0xfe,0x9a,0x77,0x8d,0x80,0x01,0xf6,0x47,0x32,0x39,0x39,0x32,0x47,0x45,0x33,0x38,0x38,0x33,0xfd,0x6a,0x01,0x68,0x6d,0x5e,0xa1,0x9e,0x63,0x73,0x00,0x02,0x00,0x60,0xff,0xe8,0x06,0xc1,0x04,0x18,0x00,0x2a, 0x00,0x3e,0x00,0xca,0x40,0x8b,0x39,0x3c,0x01,0x36,0x38,0x01,0x37,0x32,0x01,0x38,0x2e,0x01,0x47,0x28,0x57,0x28,0x02,0x57,0x23,0x01,0x45,0x23,0x01,0x57,0x22,0x01,0x5a,0x1e,0x01,0x49,0x1e,0x01,0x48,0x1d,0x58,0x1d,0x02,0x58,0x19,0x01,0x49,0x19,0x01,0x4a,0x18,0x5a,0x18,0x02,0x45,0x14,0x55,0x14,0x02,0x47,0x13,0x57,0x13,0x02, 0x46,0x0f,0x01,0x39,0x0a,0x99,0x0a,0x02,0x2a,0x0a,0x01,0x99,0x09,0x01,0x68,0x05,0x98,0x05,0x02,0x94,0x03,0x01,0x76,0x02,0x86,0x02,0x02,0x03,0x04,0x04,0x07,0x19,0x23,0x01,0x23,0x37,0x0f,0x01,0x0f,0x11,0x83,0x2b,0x00,0x83,0x07,0x10,0x07,0x01,0x2b,0x07,0x2b,0x07,0x40,0x35,0x83,0x1b,0x30,0x95,0x20,0x20,0x0f,0x0c,0x95,0x24, 0x23,0x34,0x23,0x02,0x15,0x23,0x01,0x23,0x26,0x10,0x04,0x03,0x03,0x3a,0x95,0x16,0x16,0x00,0x3f,0xed,0x33,0x2f,0x33,0x3f,0x33,0x5d,0x5d,0xed,0x32,0x33,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x10,0xed,0x32,0x5d,0x32,0x5d,0x11,0x39,0x2f,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x06,0x07,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x05,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02, 0x33,0x32,0x3e,0x02,0x06,0xc1,0x7f,0x76,0x75,0x5d,0x65,0x2c,0x56,0x7e,0x52,0x3f,0x64,0x2d,0x4f,0x43,0x81,0xbc,0x79,0x74,0xb7,0x7f,0x43,0x44,0x83,0xc1,0x7d,0x5e,0x94,0x3c,0x43,0x98,0x5d,0x76,0xbb,0x81,0x44,0xfc,0xdd,0x23,0x4d,0x7c,0x59,0x58,0x7f,0x53,0x27,0x29,0x54,0x7e,0x56,0x59,0x7c,0x4d,0x23,0x01,0xe8,0xa5,0xfe,0x5d, 0x73,0x47,0xcc,0x88,0x4d,0x93,0x72,0x46,0x22,0x23,0x80,0xc5,0x77,0xc6,0x8f,0x50,0x4e,0x8b,0xc1,0x72,0x7b,0xca,0x90,0x4f,0x2e,0x30,0x30,0x2e,0x57,0x97,0xcd,0x5f,0x54,0x92,0x6c,0x3e,0x40,0x6d,0x93,0x54,0x52,0x8f,0x6a,0x3d,0x3d,0x6a,0x91,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x04,0x81,0x04,0x18,0x00,0x19,0x00,0x89,0x40,0x5a, 0x45,0x18,0x01,0x4a,0x14,0x01,0x96,0x0b,0x01,0x99,0x07,0x01,0x28,0x07,0x38,0x07,0x02,0x99,0x10,0x01,0x88,0x10,0x01,0x79,0x10,0x01,0x10,0x12,0x0f,0x96,0x02,0x01,0x87,0x02,0x01,0x76,0x02,0x01,0x02,0x03,0x00,0x67,0x0f,0x01,0x01,0x0f,0x01,0x68,0x03,0x01,0x0e,0x03,0x01,0x0f,0x03,0x0f,0x03,0x0d,0x00,0x83,0x20,0x05,0x30,0x05, 0xa0,0x05,0x03,0x05,0x05,0x1b,0x0d,0x83,0x0f,0x12,0x1f,0x12,0xaf,0x12,0x03,0x12,0x09,0x95,0x16,0x10,0x03,0x02,0x02,0x0f,0x10,0x16,0x00,0x3f,0x33,0x33,0x2f,0x33,0x3f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x5d,0x5d,0x11,0x12,0x39,0x5d,0x5d,0x5d,0x11,0x12,0x39,0x5d,0x5d,0x5d, 0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x07,0x27,0x36,0x11,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x10,0x17,0x07,0x26,0x11,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x04,0x81,0xeb,0x75,0xb8,0x5e,0x65,0xa8,0xa8,0x63,0x5b,0xb8,0x75,0xeb,0x8b,0x90,0xf7,0xf7,0x8e,0x8a,0x01,0xe8,0xfe,0xb8,0xb8,0x73,0x8d,0x01,0x0e,0xab,0x72, 0x7b,0x7b,0x71,0xac,0xfe,0xf2,0x8d,0x73,0xb8,0x01,0x48,0xfa,0x98,0x9e,0x9e,0x98,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x04,0x18,0x00,0x39,0x00,0x72,0x40,0x44,0x86,0x33,0x01,0x77,0x33,0x01,0x79,0x29,0x89,0x29,0x99,0x29,0x03,0x6b,0x16,0x01,0x59,0x16,0x01,0x74,0x12,0x01,0x67,0x12,0x01,0x56,0x12,0x01,0x34,0x35,0x31,0x1f, 0x1f,0x0f,0x00,0x83,0x19,0x19,0x0a,0x3b,0x31,0x83,0x2b,0x26,0x0d,0x0f,0x84,0x0c,0x0a,0x35,0x34,0x20,0x95,0x0d,0x0c,0x1e,0x0c,0x1e,0x0c,0x14,0x2b,0x95,0x2c,0x10,0x14,0x95,0x05,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x39,0x39,0x01,0x2f,0x33,0xed,0x32,0x2f,0xce,0xed,0x11,0x12,0x39,0x2f,0xed, 0x12,0x39,0x2f,0x12,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x35,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03, 0x03,0xf1,0x4a,0x81,0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c,0x2e,0x4b,0x60,0x32,0x43,0x73,0x53,0x2f,0x38,0x68,0x94,0x5b,0x3b,0x35,0x59,0x80,0x53,0x28,0x1f,0x3c,0x58,0x39,0x55,0x93,0x6d,0x3f,0x98,0x8d,0x49,0x82,0x62,0x39,0x0e,0x75,0xb0,0x75,0x3a,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x26, 0x4d,0x77,0x51,0x50,0x7c,0x54,0x2b,0x8b,0x1a,0x39,0x59,0x3e,0x34,0x57,0x3d,0x22,0x8b,0x2d,0x57,0x80,0x52,0x89,0xa3,0x18,0x04,0x0b,0x43,0x66,0x85,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x08,0x06,0x04,0x18,0x00,0x5f,0x01,0x72,0x40,0xf7,0x77,0x5e,0x01,0x86,0x5d,0x01,0x75,0x5d,0x01,0x89,0x58,0x01,0x77,0x53,0x01,0x89,0x50,0x01, 0x78,0x50,0x01,0x99,0x4f,0x01,0x97,0x4b,0x01,0x86,0x4b,0x01,0x99,0x47,0x01,0x88,0x47,0x01,0x79,0x47,0x01,0x78,0x41,0x01,0x66,0x2d,0x01,0x5a,0x29,0x6a,0x29,0x02,0x66,0x1f,0x01,0x64,0x1e,0x01,0x56,0x1e,0x01,0x5a,0x1a,0x6a,0x1a,0x02,0x6a,0x19,0x01,0x97,0x11,0x01,0x56,0x0f,0x66,0x0f,0x02,0x69,0x0b,0x01,0x99,0x07,0x01,0x88, 0x07,0x01,0x69,0x07,0x01,0x44,0x59,0x01,0x45,0x53,0x01,0x45,0x50,0x01,0x45,0x4c,0x01,0x47,0x4b,0x01,0x46,0x10,0x01,0x47,0x0f,0x01,0x4e,0x23,0x84,0x24,0x56,0x15,0x94,0x05,0x01,0x85,0x05,0x01,0x76,0x05,0x01,0x05,0x06,0x06,0x08,0x14,0x84,0x15,0x7f,0x3f,0x8f,0x3f,0x9f,0x3f,0x03,0x5c,0x3f,0x01,0x4b,0x3f,0x01,0x3a,0x3f,0x01, 0x2d,0x3f,0x01,0x3f,0x44,0x9b,0x38,0x01,0x8a,0x38,0x01,0x7b,0x38,0x01,0x6c,0x38,0x01,0x5a,0x38,0x01,0x38,0x93,0x35,0x01,0x85,0x35,0x01,0x62,0x35,0x01,0x35,0x37,0x37,0x30,0x00,0x83,0x08,0x24,0x15,0x08,0x08,0x15,0x24,0x03,0x61,0x30,0x83,0x44,0x3d,0x3d,0x44,0x0d,0x95,0x5b,0x5b,0x51,0x2b,0x95,0x49,0x49,0x70,0x4e,0x01,0x44, 0x4e,0x01,0x70,0x56,0x01,0x44,0x56,0x01,0x4e,0x56,0x23,0x51,0x14,0x14,0x23,0x23,0x05,0x1c,0x95,0x51,0x10,0x35,0x38,0x3f,0x95,0x3a,0x3d,0x95,0x3c,0x3c,0x3a,0x37,0x38,0x1c,0x06,0x05,0x16,0x00,0x3f,0x33,0x3f,0x33,0xce,0x32,0x2f,0xed,0x10,0xed,0x11,0x39,0x3f,0xed,0x11,0x39,0x2f,0x33,0x2f,0x11,0x12,0x39,0x39,0x5d,0x5d,0x5d, 0x5d,0x33,0x2f,0xed,0x11,0x33,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x12,0x39,0x2f,0x39,0x5d,0x5d,0x5d,0x33,0x5d,0x5d,0x5d,0x5d,0x5d,0x12,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x10,0xed,0x11,0x39,0x2f,0x33,0x5d,0x5d,0x5d,0x11,0x39,0x10,0xed,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x07,0x27,0x36,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x2e,0x04,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15, 0x14,0x1e,0x02,0x17,0x04,0x17,0x07,0x24,0x21,0x22,0x07,0x35,0x36,0x33,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x08,0x06,0x1c,0x3a,0x59,0x3c,0x75,0xb8,0x1f,0x36,0x4a,0x2b,0x2b,0x42,0x30,0x20,0x14,0x08,0xa4,0x08,0x14,0x20,0x30,0x42,0x2b,0x29, 0x3f,0x2e,0x1e,0x13,0x08,0xa4,0x08,0x14,0x21,0x30,0x41,0x2b,0x2b,0x4a,0x36,0x1f,0x56,0x9f,0xde,0x89,0x01,0x91,0xb6,0x68,0xfe,0x6f,0xfd,0xf9,0xd7,0x94,0x9b,0xd4,0x54,0x7e,0x53,0x2a,0x29,0x59,0x8d,0x63,0x2f,0x5a,0x4f,0x3f,0x15,0x2a,0x99,0x5d,0x2e,0x59,0x4f,0x3f,0x15,0x15,0x3f,0x4f,0x5a,0x2f,0x55,0x89,0x60,0x34,0x02,0x26, 0x4e,0xa3,0x99,0x85,0x2f,0x73,0x8d,0x01,0x3e,0x5a,0x87,0x5a,0x2d,0x2b,0x46,0x59,0x5d,0x59,0x22,0x22,0x58,0x5d,0x5a,0x46,0x2b,0x2d,0x48,0x5b,0x5d,0x56,0x1f,0x1f,0x56,0x5d,0x5b,0x48,0x2d,0x2d,0x5a,0x87,0x5a,0x91,0xd1,0x98,0x6c,0x2b,0x80,0x7a,0x7d,0xfc,0x7e,0xa8,0x62,0x2d,0x8c,0xaa,0xbe,0x5f,0x5b,0xb2,0x8d,0x58,0x1b,0x33, 0x4a,0x2f,0x5f,0x68,0x1b,0x33,0x4a,0x2f,0x2f,0x4a,0x33,0x1b,0x3e,0x7d,0xbb,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x28,0x06,0x02,0x00,0x25,0x00,0x33,0x00,0x72,0x40,0x4a,0x59,0x31,0x01,0x56,0x2e,0x01,0x59,0x29,0x01,0x99,0x1e,0x01,0x99,0x1d,0x01,0x76,0x18,0x01,0x67,0x17,0x01,0x6a,0x14,0x7a,0x14,0x02,0x69,0x0d,0x01,0x69, 0x0c,0x01,0x26,0x25,0x83,0x30,0x11,0x40,0x11,0x02,0x11,0x11,0x0a,0x35,0x1a,0x84,0x1b,0x1b,0x2d,0x83,0x0f,0x0a,0x1f,0x0a,0x02,0x0a,0x2b,0x95,0x4f,0x1b,0x01,0x1b,0x11,0x0f,0x0f,0x2f,0x15,0x95,0x20,0x01,0x2f,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0xce,0x5d,0xed,0x01,0x2f,0x5d,0xed,0x33,0x2f,0xed,0x11, 0x12,0x39,0x2f,0x5d,0xed,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x03,0x34,0x2e,0x02,0x23,0x20,0x11,0x10,0x21,0x32,0x3e,0x02,0x04,0x28, 0x3f,0x7a,0xb2,0x73,0x75,0xb7,0x7d,0x41,0x3b,0x75,0xae,0x74,0xc5,0x89,0x8d,0x87,0x31,0x56,0x41,0x25,0xa6,0x41,0x6f,0x91,0x50,0x66,0xa5,0x74,0x3f,0xa8,0x26,0x4e,0x7a,0x54,0xfe,0xca,0x01,0x36,0x52,0x79,0x50,0x27,0x01,0xe0,0x70,0xb9,0x85,0x4a,0x4c,0x8a,0xbf,0x73,0x71,0xb6,0x80,0x45,0x77,0xec,0x8a,0x9d,0x1e,0x3b,0x58,0x39, 0x55,0x89,0x61,0x35,0x3d,0x74,0xa6,0x69,0xfd,0xa4,0x50,0x86,0x60,0x36,0xfe,0x98,0xfe,0x88,0x3a,0x65,0x87,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x28,0x06,0x02,0x00,0x1f,0x00,0x2b,0x00,0x7f,0x40,0x2c,0x59,0x2b,0x01,0x56,0x29,0x01,0x47,0x29,0x01,0x56,0x28,0x01,0x55,0x24,0x01,0x5a,0x21,0x01,0x66,0x1e,0x76,0x1e,0x02,0x2b, 0x0a,0x3b,0x0a,0x4b,0x0a,0x03,0x0c,0x0a,0x1c,0x0a,0x02,0x69,0x05,0x01,0x10,0x11,0x11,0x00,0x83,0x20,0xb8,0xff,0xc0,0x40,0x24,0x0a,0x0d,0x48,0x20,0x20,0x2d,0x26,0x83,0x1a,0x84,0x0f,0x08,0x1f,0x08,0x02,0x08,0x22,0x95,0x1a,0x1c,0x1c,0x2a,0x11,0x13,0x95,0x10,0x0e,0x0e,0x16,0x95,0x0b,0x01,0x2a,0x95,0x04,0x16,0x00,0x3f,0xed, 0x3f,0xed,0x33,0x2f,0x33,0xed,0x32,0x11,0x39,0x2f,0x33,0xed,0x01,0x2f,0x5d,0xed,0xed,0x12,0x39,0x2f,0x2b,0xed,0x32,0x2f,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x10,0x21,0x32,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x23,0x22,0x06,0x15,0x11, 0x36,0x33,0x32,0x17,0x16,0x07,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x04,0x28,0x7b,0x84,0xeb,0xe5,0x80,0x79,0x01,0x5a,0x40,0xeb,0x35,0x52,0x72,0x4a,0x83,0x88,0x44,0xf5,0x2d,0x64,0x4b,0x88,0xc6,0xea,0x7a,0x6e,0xa8,0xfe,0xca,0xa8,0x53,0x47,0x4a,0x55,0xa3,0x01,0x36,0x01,0xf0,0xe6,0x8c,0x96,0x8f,0x88,0xe1, 0x02,0xd0,0x01,0x52,0x46,0x46,0x71,0x5f,0x46,0x55,0x64,0xfe,0xa6,0x77,0x8d,0x80,0xe5,0x01,0x68,0x6d,0x5e,0xa1,0x9e,0x63,0x73,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x05,0xae,0x04,0x18,0x00,0x3e,0x00,0xb8,0x40,0x11,0x86,0x3c,0x96,0x3c,0x02,0x77,0x38,0x01,0x66,0x38,0x01,0x47,0x38,0x57,0x38,0x02,0x32,0xb8,0xff,0xf8,0x40,0x65, 0x0d,0x10,0x48,0x96,0x2e,0x01,0x87,0x2e,0x01,0x99,0x27,0x01,0x75,0x24,0x01,0x66,0x24,0x01,0x85,0x23,0x01,0x69,0x20,0x79,0x20,0x02,0x6a,0x0b,0x7a,0x0b,0x02,0x84,0x08,0x01,0x66,0x07,0x76,0x07,0x02,0x99,0x04,0x01,0x88,0x04,0x01,0x26,0x25,0x25,0x16,0x2b,0x83,0x22,0x16,0x35,0x16,0x05,0x06,0x06,0x15,0x00,0x83,0x09,0x15,0x84, 0x16,0x0e,0x95,0x3a,0x3a,0x71,0x35,0x01,0x62,0x35,0x01,0x40,0x35,0x50,0x35,0x02,0x35,0x30,0x16,0x16,0x26,0x1d,0x95,0x30,0x10,0x94,0x06,0x01,0x06,0x05,0x05,0x94,0x25,0x01,0x25,0x26,0x16,0x00,0x3f,0x33,0x5d,0x33,0x2f,0x33,0x5d,0x3f,0xed,0x11,0x39,0x2f,0x12,0x39,0x5d,0x5d,0x5d,0x32,0x2f,0xed,0x01,0x2f,0xfd,0xde,0xed,0x12, 0x39,0x2f,0x33,0x11,0x39,0x10,0xde,0xed,0x12,0x39,0x2f,0x33,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x2b,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x07,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x07,0x2e,0x03, 0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x05,0xae,0x1f,0x3e,0x5c,0x3c,0x75,0x5d,0x65,0x22,0x3a,0x4d,0x2b,0x2d,0x43,0x30,0x20,0x12,0x07,0xa4,0x08,0x14,0x20,0x30,0x42,0x2b,0x2b,0x4d,0x3a,0x22,0x65,0x5d,0x75,0x3c,0x5c,0x3e,0x1f,0x37,0x64,0x8c,0x55,0x2f,0x5a,0x4f,0x3f,0x15,0x15,0x3f,0x4f, 0x59,0x2e,0x55,0x8c,0x64,0x37,0x02,0x26,0x4e,0xa3,0x99,0x85,0x2f,0x73,0x47,0xe4,0xa0,0x5a,0x87,0x5a,0x2d,0x2a,0x45,0x59,0x5d,0x59,0x24,0x26,0x5b,0x5d,0x57,0x44,0x29,0x2d,0x5a,0x87,0x5a,0xa0,0xe4,0x47,0x73,0x2f,0x85,0x99,0xa3,0x4e,0x7c,0xbb,0x7d,0x3e,0x1e,0x37,0x4d,0x2f,0x2f,0x4d,0x37,0x1e,0x3e,0x7d,0xbb,0x00,0x00,0x01, 0x00,0x60,0xff,0xe8,0x03,0xf1,0x06,0x02,0x00,0x3f,0x00,0x99,0x40,0x5b,0x86,0x38,0x01,0x96,0x31,0x01,0x79,0x28,0x01,0x6a,0x16,0x01,0x59,0x16,0x01,0x56,0x12,0x66,0x12,0x02,0x7a,0x08,0x8a,0x08,0x02,0x7a,0x07,0x8a,0x07,0x02,0x46,0x3e,0x01,0x47,0x33,0x01,0x3a,0x3b,0x1f,0x31,0x2d,0x35,0x84,0x29,0x2d,0x26,0x26,0x19,0x2e,0x2d, 0x2d,0x1f,0x1f,0x0f,0x00,0x83,0x19,0x19,0x41,0x0d,0x0f,0x84,0x0c,0x0a,0x3b,0x3a,0x1e,0x18,0x31,0x01,0x09,0x31,0x01,0x29,0x31,0x2e,0x20,0x95,0x0d,0x0c,0x1e,0x0c,0x1e,0x0c,0x2d,0x2e,0x01,0x14,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f,0x33,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x11,0x39,0x39,0x5d,0x5d,0x11,0x39,0x39,0x01,0x2f,0x33, 0xed,0x32,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x33,0x2f,0x33,0x11,0x33,0x2f,0x12,0x39,0xed,0x11,0x39,0x11,0x39,0x39,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23, 0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x27,0x37,0x1e,0x05,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x03,0xf1,0x4a,0x81,0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c,0x2e,0x4b,0x60,0x32,0x43,0x73,0x53,0x2f,0x38,0x68,0x94,0x5b,0x3b,0x35,0x59,0x79,0x49,0x20,0x38,0x59,0x70,0x70,0x65,0x21,0x5e,0x23,0x70,0x7f,0x81,0x68, 0x41,0x1e,0x3f,0x64,0x46,0x49,0x82,0x62,0x39,0x01,0xbc,0x75,0xb0,0x75,0x3a,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x26,0x4d,0x77,0x51,0x50,0x7c,0x54,0x2b,0x8b,0x1d,0x34,0x47,0x2a,0x37,0x46,0x31,0x24,0x2b,0x3b,0x2f,0x56,0x2c,0x3b,0x31,0x31,0x43,0x5f,0x47,0x2c,0x54,0x47,0x35,0x0c,0x04,0x0b,0x43, 0x66,0x85,0x00,0x01,0x00,0x3f,0xfe,0x1e,0x03,0xf1,0x04,0x00,0x00,0x2d,0x00,0x8e,0x40,0x52,0x65,0x13,0x01,0x56,0x13,0x01,0x76,0x0f,0x01,0x57,0x0f,0x67,0x0f,0x02,0x2c,0x2d,0x84,0x16,0x18,0x1a,0x28,0x25,0x27,0x27,0x20,0x1a,0x84,0x25,0x25,0x0d,0x16,0x16,0x08,0x2f,0x20,0x84,0x1f,0x1f,0x0b,0x0d,0x84,0x0a,0x08,0x28,0x95,0x18, 0x27,0x18,0x1f,0x20,0x0b,0x0a,0x0a,0x11,0x1d,0x95,0x22,0x89,0x16,0x99,0x16,0x02,0x16,0x2d,0x00,0x18,0x10,0x18,0x02,0x18,0x20,0x22,0x22,0x20,0x18,0x03,0x2d,0x0f,0x11,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x12,0x39,0x5d,0x10,0xed,0x11,0x39,0x2f,0x33,0x11,0x33,0x11,0x33,0x10,0xed,0x01,0x2f,0x33, 0xed,0x32,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x10,0xed,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x11,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x03,0x37,0x16, 0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x32,0x37,0x36,0x37,0x33,0x03,0xf1,0x8e,0x85,0xcf,0xaa,0x7d,0x88,0x29,0x99,0x1c,0x55,0x4e,0x68,0x88,0x57,0x5d,0x5f,0xab,0x3f,0x8e,0x9b,0xf9,0x21,0x89,0x17,0x7a,0x4c,0x40,0x6f,0x37,0xac,0x62,0x73,0x73,0x50,0x22,0xd2,0x7b,0x73,0x61,0x6a,0xa9,0x5c,0x53,0x37,0x33,0x49,0x68,0x42,0x3c,0x4c, 0x51,0x8a,0x03,0x3b,0x39,0x08,0x4a,0x65,0x75,0x93,0x01,0x1d,0x26,0xb9,0x47,0x47,0x6b,0x3c,0x82,0x1f,0x24,0x6a,0x00,0x01,0x00,0x60,0xff,0xe8,0x05,0xae,0x06,0x02,0x00,0x52,0x00,0xfc,0x40,0xa7,0x96,0x4c,0x01,0x94,0x47,0x01,0x99,0x2f,0x01,0x66,0x4c,0x76,0x4c,0x02,0x84,0x4b,0x01,0x8c,0x48,0x01,0x8a,0x47,0x01,0x69,0x47,0x79, 0x47,0x02,0x4a,0x42,0x5a,0x42,0x6a,0x42,0x03,0x4a,0x39,0x5a,0x39,0x6a,0x39,0x03,0x7b,0x33,0x01,0x6a,0x33,0x01,0x85,0x2f,0x01,0x66,0x2f,0x76,0x2f,0x02,0x89,0x2c,0x01,0x86,0x25,0x96,0x25,0x02,0x77,0x21,0x01,0x25,0x04,0x01,0x55,0x03,0x01,0x46,0x03,0x01,0x34,0x03,0x01,0x26,0x03,0x01,0x9b,0x4e,0x01,0x4e,0x4d,0x4d,0x3e,0x94, 0x17,0x01,0x17,0x11,0x4a,0x07,0x0d,0x00,0x83,0x4a,0x3e,0x94,0x2d,0x01,0x2d,0x2e,0x2e,0x3d,0x31,0x0c,0x0d,0x0d,0x28,0x83,0x31,0x1e,0x3d,0x84,0x3e,0x70,0x1e,0x01,0x1e,0x23,0x3e,0x3e,0x4e,0x2e,0x2d,0x2d,0x4d,0x4e,0x16,0x36,0x95,0x23,0x45,0x95,0x17,0x19,0x19,0x9d,0x11,0x01,0x7a,0x11,0x8a,0x11,0x02,0x96,0x07,0x01,0x09,0x07, 0x19,0x07,0x29,0x07,0x03,0x11,0x07,0x0c,0x23,0x10,0x0d,0x0c,0x01,0x00,0x3f,0x33,0x3f,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x33,0x2f,0x33,0xed,0x10,0xed,0x3f,0x33,0x33,0x2f,0x33,0x11,0x39,0x2f,0x12,0x39,0x5d,0x01,0x2f,0xfd,0x39,0xde,0xed,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x5d,0x10,0xde,0xed,0x11,0x39,0x12,0x39,0x39, 0x5d,0x11,0x39,0x2f,0x33,0x5d,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x13,0x34,0x3e,0x02,0x37,0x3e,0x05,0x37,0x17,0x0e,0x05,0x07,0x06,0x06,0x07,0x36,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07, 0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x07,0x2e,0x03,0x60,0x30,0x64,0x99,0x69,0x3f,0x85,0x81,0x7a,0x67,0x50,0x18,0x76,0x17,0x5d,0x7a,0x8b,0x8b,0x80,0x31,0x3c,0x4a,0x13,0x18,0x18,0x2f,0x5a,0x4f,0x3f,0x15,0x15,0x3f,0x4f,0x59,0x2e,0x55,0x8c, 0x64,0x37,0x1f,0x3e,0x5c,0x3c,0x75,0x5d,0x65,0x22,0x3a,0x4d,0x2b,0x2d,0x43,0x30,0x20,0x12,0x07,0xa4,0x08,0x14,0x20,0x30,0x42,0x2b,0x2b,0x4d,0x3a,0x22,0x65,0x5d,0x75,0x3c,0x5c,0x3e,0x1f,0x02,0x26,0x84,0xe2,0xb8,0x8c,0x2d,0x1b,0x2a,0x24,0x23,0x28,0x30,0x21,0x53,0x25,0x3c,0x33,0x2c,0x29,0x28,0x16,0x1b,0x3f,0x19,0x03,0x1e, 0x37,0x4d,0x2f,0x2f,0x4d,0x37,0x1e,0x3e,0x7d,0xbb,0x7c,0x4e,0xa3,0x99,0x85,0x2f,0x73,0x47,0xe4,0xa0,0x5a,0x87,0x5a,0x2d,0x2a,0x45,0x59,0x5d,0x59,0x24,0x26,0x5b,0x5d,0x57,0x44,0x29,0x2d,0x5a,0x87,0x5a,0xa0,0xe4,0x47,0x73,0x2f,0x85,0x99,0xa3,0x00,0x01,0x00,0x9a,0xff,0xe6,0x04,0x1d,0x05,0xec,0x00,0x19,0x00,0x6b,0x40,0x26, 0x99,0x13,0x01,0x68,0x13,0x78,0x13,0x02,0x69,0x0e,0x01,0x65,0x0c,0x01,0x56,0x0c,0x01,0x79,0x06,0x01,0x89,0x05,0x01,0x96,0x03,0x01,0x76,0x02,0x01,0x14,0x15,0x17,0x84,0x12,0x00,0x84,0x0f,0x12,0xb8,0xff,0xc0,0x40,0x1c,0x0a,0x0d,0x48,0x10,0x0f,0x20,0x0f,0x02,0x12,0x0f,0x12,0x0f,0x1b,0x0b,0x84,0x90,0x08,0x01,0x08,0x15,0x14, 0x10,0x0a,0x00,0x0d,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x01,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x2b,0x10,0xed,0x10,0xfd,0xce,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x33,0x11,0x10,0x21,0x20,0x11,0x34,0x26,0x35,0x34,0x37,0x17,0x06, 0x15,0x14,0x16,0x04,0x1d,0x6a,0x76,0xe0,0xe5,0x74,0x6a,0xa2,0x01,0x21,0x01,0x1b,0x78,0xbf,0x4d,0x5e,0x6f,0x01,0xb3,0xd5,0x78,0x80,0x7b,0x77,0xd8,0x04,0x3c,0xfb,0xe1,0xfe,0xab,0x01,0x34,0x71,0xfb,0x3c,0x87,0x3d,0x87,0x23,0x34,0x1a,0xf7,0x00,0x00,0x02,0x00,0x5e,0xfe,0x1e,0x05,0xaa,0x05,0x31,0x00,0x36,0x00,0x42,0x01,0x23, 0x40,0xc8,0x09,0x13,0x01,0x06,0x10,0x01,0x57,0x35,0x01,0x77,0x2f,0x87,0x2f,0x02,0x77,0x2b,0x87,0x2b,0x02,0x88,0x27,0x01,0x7c,0x15,0x8c,0x15,0x02,0x6a,0x15,0x01,0x66,0x13,0x01,0x65,0x10,0x01,0x56,0x10,0x01,0x47,0x10,0x01,0x65,0x0f,0x85,0x0f,0x95,0x0f,0x03,0x69,0x0d,0x01,0x57,0x0a,0x01,0x79,0x06,0x01,0x79,0x02,0x01,0x1e, 0xa1,0x1f,0xb1,0x1f,0xc1,0x1f,0x03,0x50,0x1f,0x01,0x1f,0x1f,0x18,0x00,0x83,0x14,0x14,0x29,0x44,0x56,0x33,0x01,0x16,0x33,0x18,0x31,0x84,0x5a,0x27,0x01,0x27,0x41,0x25,0x37,0x3f,0x84,0x29,0x18,0x84,0x25,0x25,0x29,0x08,0x83,0x0f,0x0e,0x01,0x0e,0x0b,0x0c,0x29,0x7b,0x0c,0x8b,0x0c,0x9b,0x0c,0x03,0x49,0x0c,0x01,0x0c,0x85,0x41, 0x01,0x74,0x41,0x01,0x48,0x33,0x68,0x33,0x02,0x39,0x33,0x01,0x78,0x27,0x01,0x6a,0x27,0x01,0x58,0x27,0x01,0x3a,0x27,0x4a,0x27,0x02,0x06,0x27,0x16,0x27,0x26,0x27,0x03,0x27,0x33,0x41,0x03,0x3b,0x9c,0x16,0x01,0x8b,0x16,0x01,0x7c,0x16,0x01,0x6a,0x16,0x01,0x38,0x16,0x48,0x16,0x58,0x16,0x03,0x16,0x0b,0x0b,0x1c,0x2d,0x95,0x3b, 0x3b,0x1f,0x21,0x95,0x1e,0x1c,0x12,0x95,0x04,0x1c,0x00,0x3f,0xed,0x2f,0x33,0xed,0x32,0x33,0x2f,0xed,0x12,0x39,0x2f,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x12,0x17,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x33,0x5d,0x5d,0x01,0x2f,0xce,0x32,0xdc,0x5d,0xed,0x11,0x33,0x2f,0xed,0x10,0xfd,0xde,0x11,0x39,0x39,0x5d,0xed,0x11, 0x39,0x39,0x5d,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x5d,0x5d,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x25,0x10,0x07,0x06,0x21,0x20,0x27,0x26,0x11,0x34,0x12,0x37,0x17,0x06,0x11,0x14,0x17,0x16,0x33,0x20,0x11,0x10,0x25,0x06,0x15,0x14,0x17,0x16,0x33, 0x32,0x37,0x17,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x36,0x05,0xaa,0xae,0xb5,0xfe,0xb2,0xfe,0xc5,0xb3,0xad,0xbb,0xb1,0x3b,0xf7,0x78,0x83,0xf0,0x02,0x01,0xfe,0x72,0x60,0x20,0x1d,0x25,0x39, 0x22,0x7a,0x52,0x83,0x62,0x4a,0x52,0x82,0x82,0x53,0x49,0x63,0x5e,0x4a,0x4f,0x87,0xd3,0x78,0x80,0xfe,0x22,0x1f,0x1b,0x23,0x25,0x1d,0x20,0x60,0x5f,0xd9,0xfe,0xb9,0xb7,0xbd,0xc1,0xbb,0x01,0x3a,0xeb,0x01,0x56,0x53,0x96,0x90,0xfe,0xa1,0xf3,0x96,0xa5,0x02,0x0d,0x01,0x67,0xf7,0x5b,0x45,0x28,0x19,0x17,0x2c,0x50,0x6d,0x39,0x40, 0x66,0x79,0x79,0x6e,0x72,0x6d,0x42,0x3a,0x3c,0x40,0x5b,0x62,0x7c,0x7b,0xaa,0xb5,0x02,0xb8,0x21,0x14,0x11,0x14,0x17,0x23,0x46,0x42,0x59,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x06,0x22,0x04,0x18,0x00,0x5a,0x00,0xe8,0x40,0x99,0x17,0x57,0x01,0x7a,0x53,0x01,0x69,0x53,0x01,0x7b,0x52,0x01,0x6a,0x52,0x01,0x48,0x50,0x58,0x50,0x02, 0x96,0x4e,0x01,0x65,0x4e,0x75,0x4e,0x02,0x97,0x4d,0x01,0x86,0x4d,0x01,0x65,0x4d,0x75,0x4d,0x02,0x69,0x49,0x01,0x98,0x3c,0x01,0x89,0x3c,0x01,0x57,0x35,0x01,0x46,0x35,0x01,0x37,0x35,0x01,0x48,0x2c,0x58,0x2c,0x02,0x49,0x2b,0x01,0x8a,0x1d,0x9a,0x1d,0x02,0x48,0x17,0x01,0x5a,0x16,0x01,0x49,0x16,0x01,0x65,0x12,0x75,0x12,0x02, 0x47,0x12,0x57,0x12,0x02,0x5a,0x84,0x19,0x19,0x27,0x5c,0x3d,0x20,0x3e,0x40,0x3e,0x50,0x3e,0x03,0x3e,0x3e,0x48,0x33,0x27,0x43,0x84,0x3b,0x50,0x26,0x84,0x27,0x0d,0x0f,0x84,0x0c,0x0a,0x0a,0x27,0x1f,0x95,0x55,0x55,0x4b,0x3e,0x3d,0x3d,0x4b,0x36,0x95,0x45,0x2e,0x0d,0x0c,0x50,0x26,0x4b,0x0c,0x26,0x0c,0x26,0x14,0x2e,0x95,0x4b, 0x10,0x14,0x95,0x05,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x10,0xdc,0xed,0x11,0x33,0x2f,0x33,0x11,0x33,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x33,0xed,0x32,0x10,0xed,0x39,0xdc,0xed,0x11,0x39,0x39,0x32,0x2f,0x5d,0x33,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x07,0x06,0x06,0x23,0x22,0x2e,0x02, 0x35,0x34,0x37,0x17,0x0e,0x03,0x15,0x14,0x33,0x36,0x36,0x37,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x06,0x22,0x4d,0x85,0xb4,0x66,0x59,0xa0,0x79,0x47,0x29,0x99,0x1c,0x2c,0x4c,0x64,0x39,0x43,0x77,0x59,0x33,0x17,0x2c,0x3d,0x27,0x24,0x38,0x2b,0x1e,0x12,0x09,0xa4,0x0a,0x13,0x1d,0x26,0x30,0x1c, 0x1d,0x2b,0x22,0x1e,0x11,0x21,0x73,0x63,0x32,0x50,0x38,0x1d,0x7f,0x69,0x12,0x20,0x1a,0x0f,0x4d,0x2e,0x45,0x1f,0x1f,0x84,0x58,0x2e,0x4c,0x3e,0x32,0x13,0x15,0x36,0x43,0x52,0x30,0x55,0x7e,0x52,0x29,0x0e,0x73,0xaf,0x76,0x3c,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x28,0x4f,0x76,0x4e,0x02,0x40,0x5f, 0x89,0x59,0x2a,0x2d,0x48,0x5b,0x5d,0x56,0x1f,0x1f,0x56,0x5d,0x5b,0x48,0x2d,0x1a,0x35,0x4e,0x34,0x68,0x69,0x22,0x3c,0x54,0x32,0x88,0x6c,0x59,0x0b,0x20,0x28,0x30,0x1a,0x54,0x01,0x56,0x67,0x68,0x78,0x1f,0x39,0x4f,0x2f,0x2f,0x4f,0x39,0x1f,0x38,0x77,0xbb,0x84,0x00,0x00,0x02,0x00,0x40,0xfe,0x1e,0x06,0x9c,0x04,0x18,0x00,0x55, 0x00,0x69,0x00,0xd9,0x40,0x52,0x5a,0x67,0x01,0x39,0x67,0x49,0x67,0x02,0x36,0x63,0x46,0x63,0x56,0x63,0x03,0x56,0x5d,0x01,0x35,0x5d,0x45,0x5d,0x02,0x39,0x59,0x49,0x59,0x59,0x59,0x03,0x56,0x54,0x01,0x86,0x4f,0x96,0x4f,0x02,0x75,0x4f,0x01,0x95,0x4b,0x01,0x96,0x4a,0x01,0x7b,0x29,0x8b,0x29,0x02,0x69,0x28,0x01,0x58,0x28,0x01, 0x5a,0x16,0x01,0x86,0x11,0x01,0x9a,0x08,0x01,0x0d,0x0f,0x84,0x0a,0x0c,0x0a,0x50,0x51,0x4d,0x1f,0x5a,0x43,0x01,0x43,0x30,0xb8,0xff,0xf0,0x40,0x38,0x0f,0x12,0x48,0x30,0x32,0x83,0x56,0x4d,0x83,0x26,0x00,0x83,0x19,0x0a,0x56,0x26,0x19,0x19,0x26,0x56,0x0a,0x04,0x6b,0x60,0x83,0x3c,0x5b,0x95,0x41,0x41,0x48,0x0d,0x0c,0x65,0x95, 0x37,0x51,0x50,0x20,0x95,0x1e,0x37,0x1e,0x37,0x1e,0x14,0x30,0x2b,0x95,0x43,0x48,0x10,0x14,0x95,0x05,0x1c,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x11,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x39,0x10,0xed,0xce,0x32,0x11,0x33,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xfd,0x32,0x2b,0x32, 0x5d,0xce,0x11,0x39,0x39,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e, 0x02,0x23,0x22,0x0e,0x02,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x06,0x9c,0x4a,0x81,0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c, 0x2e,0x4b,0x60,0x32,0x43,0x73,0x53,0x2f,0x38,0x68,0x94,0x5b,0x3b,0x35,0x59,0x80,0x53,0x28,0x2b,0x4a,0x63,0x38,0x2b,0x47,0x3c,0x35,0x1a,0x46,0x43,0x7b,0xad,0x6b,0x6b,0xad,0x7b,0x43,0x43,0x7b,0xad,0x6b,0xb4,0x7a,0x20,0x53,0x5e,0x64,0x30,0x58,0x9d,0x77,0x46,0x98,0x8d,0x49,0x82,0x62,0x39,0xfc,0xa8,0x27,0x4c,0x71,0x4a,0x4a, 0x71,0x4c,0x27,0x27,0x4c,0x71,0x4a,0x4a,0x71,0x4c,0x27,0x0e,0x75,0xb0,0x75,0x3a,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x26,0x4d,0x77,0x51,0x50,0x7c,0x54,0x2b,0x8b,0x1a,0x39,0x59,0x3e,0x36,0x57,0x3c,0x21,0x0a,0x13,0x1c,0x12,0x74,0x9e,0x6a,0xb3,0x83,0x4a,0x49,0x82,0xb3,0x6a,0x69,0xb4,0x83,0x4a, 0x64,0x17,0x25,0x1a,0x0e,0x2d,0x57,0x80,0x52,0x89,0xa3,0x18,0x04,0x0b,0x43,0x66,0x85,0x01,0xef,0x46,0x7f,0x60,0x39,0x39,0x61,0x80,0x46,0x47,0x7f,0x60,0x38,0x39,0x61,0x7f,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x05,0xec,0x00,0x29,0x00,0xad,0x40,0x70,0x76,0x1b,0x01,0x79,0x18,0x01,0x59,0x13,0x69,0x13,0x02,0x75,0x0f,0x01, 0x57,0x0f,0x67,0x0f,0x02,0x09,0x25,0x01,0x95,0x1f,0x01,0x88,0x1b,0x01,0x28,0x29,0x84,0x74,0x26,0x01,0x26,0x00,0x27,0x70,0x27,0x02,0x27,0x24,0x20,0x16,0x01,0x16,0x16,0x08,0x2b,0x1d,0x84,0x1e,0x1e,0x0b,0x0d,0x84,0x0a,0x30,0x08,0x01,0x0f,0x08,0x1f,0x08,0x02,0x08,0x8b,0x25,0x9b,0x25,0x02,0x7f,0x25,0x01,0x49,0x25,0x59,0x25, 0x02,0x27,0x25,0x28,0x8f,0x26,0x9f,0x26,0x02,0x26,0x22,0x0b,0x0a,0x1d,0x0a,0x1d,0x11,0x19,0x95,0x95,0x24,0x01,0x83,0x24,0x01,0x24,0x22,0x22,0x28,0x00,0x11,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0x39,0x2f,0x33,0x5d,0x5d,0xed,0x11,0x39,0x39,0x2f,0x2f,0x33,0x10,0xce,0x5d,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x01,0x2f,0x5d,0x5d,0x33, 0xed,0x32,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x5d,0xc4,0xcc,0x5d,0x32,0x5d,0xed,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x07,0x06,0x15,0x23,0x34,0x37,0x36,0x33, 0x32,0x17,0x11,0x07,0x27,0x01,0x33,0x03,0xf1,0x8e,0x85,0xcf,0xaa,0x7d,0x88,0x29,0x99,0x1c,0x55,0x4e,0x68,0x88,0x57,0x5d,0x88,0x77,0x66,0x43,0x49,0xa6,0x7d,0x73,0xa8,0x97,0x68,0x81,0x6f,0x01,0x10,0x84,0x22,0xd2,0x7b,0x73,0x61,0x6a,0xa9,0x5c,0x53,0x37,0x33,0x49,0x68,0x42,0x3c,0x4c,0x51,0x8a,0x01,0xfa,0x79,0x83,0x34,0x39, 0x68,0xa8,0x61,0x57,0x3e,0x01,0xd8,0x82,0x70,0x01,0x14,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x05,0xce,0x04,0x18,0x00,0x49,0x00,0xdb,0x40,0x91,0x67,0x3f,0x77,0x3f,0x02,0x49,0x3b,0x59,0x3b,0x02,0x3a,0x3b,0x01,0x6a,0x3a,0x01,0x66,0x31,0x01,0x46,0x30,0x56,0x30,0x66,0x30,0x03,0x35,0x30,0x01,0x69,0x2c,0x79,0x2c,0x02,0x86,0x1e, 0x96,0x1e,0x02,0x79,0x1a,0x01,0x99,0x19,0x01,0x7a,0x19,0x8a,0x19,0x02,0x76,0x15,0x86,0x15,0x96,0x15,0x03,0x75,0x14,0x01,0x89,0x10,0x99,0x10,0x02,0x47,0x42,0x8e,0x08,0x9e,0x08,0x02,0x7b,0x08,0x01,0x59,0x08,0x01,0x3a,0x08,0x4a,0x08,0x02,0x08,0x00,0x06,0x06,0x0d,0x83,0x42,0x36,0x26,0x27,0x27,0x21,0x83,0x29,0x8d,0x01,0x9d, 0x01,0x02,0x01,0x00,0x00,0x29,0x17,0x35,0x84,0x36,0x17,0x35,0x12,0x27,0x26,0x35,0x26,0x35,0x26,0x08,0x3d,0x95,0x12,0x2e,0x95,0x1c,0x1c,0x12,0x10,0x27,0x47,0x01,0x47,0x01,0x08,0x95,0x03,0x06,0xf4,0x05,0x05,0x03,0x00,0x01,0x1c,0x00,0x3f,0x33,0xce,0x32,0x2f,0xed,0x10,0xed,0x11,0x39,0x5d,0x3f,0x33,0x2f,0xed,0x10,0xed,0x11, 0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x12,0x39,0x01,0x2f,0xfd,0x39,0xce,0x32,0x2f,0x33,0x5d,0x10,0xed,0x33,0x2f,0x39,0x10,0xde,0xed,0x32,0x2f,0x11,0x39,0x5d,0x5d,0x5d,0x5d,0x12,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x07,0x24,0x21,0x22,0x07,0x35,0x36,0x33,0x2e,0x03, 0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x27,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x2e,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x16,0x04,0x05,0x42,0x68,0xfe,0x9c,0xfe,0x55,0xd7,0x94,0x9b,0xd4,0x54,0x7e,0x53,0x2a,0x37,0x64,0x8c,0x55, 0x2f,0x5a,0x4f,0x3f,0x15,0x15,0x3f,0x4f,0x59,0x2e,0x55,0x8c,0x64,0x37,0x08,0x0f,0x16,0x0e,0x98,0x2b,0x22,0x3a,0x4d,0x2b,0x2c,0x41,0x30,0x20,0x13,0x09,0xa4,0x01,0x08,0x13,0x20,0x30,0x42,0x2b,0x2b,0x4d,0x3a,0x22,0x48,0x88,0xc7,0x7f,0xab,0x01,0x00,0xfe,0x9b,0x7d,0xfc,0x7e,0xa8,0x62,0x2d,0x8c,0xaa,0xbe,0x5f,0x7c,0xbb,0x7d, 0x3e,0x1e,0x37,0x4d,0x2f,0x2f,0x4d,0x37,0x1e,0x3e,0x7d,0xbb,0x7c,0x28,0x59,0x57,0x4e,0x1e,0x37,0x80,0x8d,0x5a,0x87,0x5a,0x2d,0x33,0x52,0x69,0x6c,0x67,0x27,0x27,0x67,0x6c,0x69,0x52,0x33,0x2d,0x5a,0x88,0x5a,0x89,0xcc,0x9a,0x72,0x2f,0x3f,0x7c,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x04,0x18,0x00,0x3b,0x00,0xcb,0x40,0x77, 0x66,0x32,0x01,0x86,0x31,0x01,0x74,0x31,0x01,0x65,0x31,0x01,0x56,0x31,0x01,0x9a,0x22,0x01,0x98,0x21,0x01,0x55,0x17,0x65,0x17,0x02,0x47,0x16,0x01,0x67,0x11,0x01,0x56,0x11,0x01,0x7a,0x08,0x01,0x79,0x07,0x01,0x3b,0x84,0x1a,0x39,0x39,0x0a,0x3d,0x5c,0x2a,0x6c,0x2a,0x7c,0x2a,0x03,0x3b,0x2a,0x4b,0x2a,0x02,0x2d,0x2a,0x01,0x2a, 0x2f,0x84,0x7c,0x29,0x01,0x6b,0x29,0x01,0x5c,0x29,0x01,0x3d,0x29,0x4d,0x29,0x02,0x2e,0x29,0x01,0x29,0x60,0x24,0x01,0x24,0x24,0x0d,0x0f,0x84,0x0c,0x0a,0x2a,0x29,0x29,0x3a,0x34,0x95,0x6a,0x1a,0x01,0x59,0x1a,0x01,0x3a,0x1a,0x4a,0x1a,0x02,0x2b,0x1a,0x01,0x1a,0x1f,0x0d,0x0c,0x1f,0xb8,0xff,0xc0,0x40,0x0d,0x0b,0x10,0x48,0x1f, 0x0c,0x1f,0x0c,0x3a,0x0f,0x14,0x95,0x05,0x1c,0x00,0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x2b,0x11,0x33,0x11,0x33,0x5d,0x5d,0x5d,0x5d,0xed,0x11,0x33,0x2f,0x33,0x01,0x2f,0x33,0xed,0x32,0x33,0x2f,0x5d,0x33,0x5d,0x5d,0x5d,0x5d,0x5d,0xed,0x32,0x5d,0x5d,0x5d,0x11,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x05,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x36,0x37,0x17,0x06,0x07,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x03,0xf1,0x4a,0x81, 0xb1,0x66,0x52,0x9b,0x79,0x49,0x29,0x99,0x1c,0x2e,0x4b,0x60,0x32,0x43,0x74,0x55,0x30,0x17,0x3f,0x4b,0x53,0x2a,0x57,0x91,0x68,0x39,0x0f,0x0a,0x0b,0x0f,0x99,0x0b,0x08,0x08,0x0b,0x28,0x42,0x56,0x2f,0x3e,0x65,0x48,0x27,0xa4,0x22,0x69,0xa6,0x74,0x3d,0x34,0x60,0x8a,0x56,0x5b,0x54,0x37,0x32,0x4a,0x35,0x55,0x3c,0x20,0x28,0x4d, 0x6d,0x45,0x02,0x41,0x1a,0x2f,0x24,0x15,0x36,0x67,0x96,0x5f,0x33,0x59,0x22,0x28,0x22,0x37,0x1a,0x1e,0x1a,0x43,0x26,0x46,0x66,0x42,0x20,0x3b,0x63,0x80,0x45,0x85,0x00,0x02,0x00,0x32,0xff,0xe8,0x04,0xdb,0x06,0x02,0x00,0x2b,0x00,0x37,0x00,0x9d,0x40,0x65,0x48,0x36,0x58,0x36,0x02,0x39,0x36,0x01,0x37,0x33,0x47,0x33,0x57,0x33, 0x03,0x38,0x2e,0x48,0x2e,0x58,0x2e,0x03,0x88,0x10,0x01,0x69,0x0a,0x01,0x66,0x03,0x01,0x86,0x28,0x96,0x28,0x02,0x86,0x26,0x96,0x26,0x02,0x99,0x10,0x01,0x08,0x83,0x32,0x32,0x16,0x20,0x22,0x84,0x1f,0x1f,0x1d,0x01,0x1d,0x16,0x27,0x16,0x15,0x2c,0x83,0x2b,0x84,0x10,0x0e,0x01,0x0e,0x15,0x84,0x16,0x1a,0x95,0x25,0x25,0x83,0x27, 0x93,0x27,0x02,0x27,0x29,0x1f,0x20,0x20,0x16,0x30,0x95,0x0e,0x0c,0x0c,0x34,0x11,0x95,0x29,0x01,0x34,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0xce,0x32,0x2f,0x33,0x11,0x39,0x5d,0x33,0x2f,0xed,0x01,0x2f,0xfd,0xdc,0x5d,0xfd,0xed,0x11,0x12,0x39,0x10,0xde,0x5d,0x32,0xed,0x32,0x11,0x33,0x2f,0xed,0x31, 0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x35,0x10,0x23,0x22,0x07,0x06,0x15,0x23,0x34,0x27,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x33,0x20,0x11,0x03,0x34,0x27,0x26,0x23,0x20,0x11, 0x10,0x21,0x32,0x37,0x36,0x04,0xdb,0x79,0x80,0xe5,0xeb,0x84,0x7b,0x6e,0x7a,0xea,0xc6,0x88,0xac,0x67,0x30,0x24,0xa4,0x24,0x30,0x67,0x47,0x4c,0x1e,0xa6,0x20,0xad,0x8e,0xb9,0x53,0x53,0xbb,0x01,0x54,0xa8,0x47,0x53,0xa8,0xfe,0xca,0x01,0x36,0xa3,0x55,0x4a,0x01,0xe0,0xe1,0x88,0x8f,0x96,0x8c,0xe6,0xdf,0x80,0x8d,0x77,0xce,0x01, 0x45,0x64,0x49,0x69,0x69,0x49,0x64,0x65,0x51,0x3a,0x53,0x1d,0x52,0x4e,0x95,0xb5,0xbd,0xbd,0xfe,0x22,0xfd,0xc2,0xa1,0x5e,0x6d,0xfe,0x98,0xfe,0x88,0x73,0x63,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x03,0xf8,0x06,0x02,0x00,0x23,0x00,0x2c,0x00,0x72,0x40,0x44,0x85,0x21,0xa5,0x21,0x02,0x87,0x17,0x01,0x88,0x06,0x98,0x06,0x02,0x7b, 0x08,0x01,0x80,0x04,0x90,0x04,0x02,0x76,0x04,0x01,0x04,0x00,0x05,0x05,0x1e,0x00,0x83,0x07,0x07,0x10,0x2e,0x19,0x84,0x24,0x2b,0x0e,0x1e,0x84,0x10,0x2b,0x95,0x1d,0x1d,0x37,0x1e,0x01,0x26,0x1e,0x01,0x1e,0x0a,0x95,0x20,0x20,0x0f,0x26,0x95,0x15,0x01,0x05,0x04,0x04,0x0f,0x15,0x00,0x3f,0x33,0x2f,0x33,0x3f,0xed,0x11,0x39,0x2f, 0xed,0x33,0x5d,0x5d,0x33,0x2f,0xed,0x01,0x2f,0xfd,0xc4,0xc4,0xdc,0xed,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0x5d,0x5d,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x07,0x27,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x15,0x11,0x23,0x11,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07,0x06,0x07, 0x15,0x36,0x33,0x32,0x17,0x16,0x01,0x34,0x23,0x22,0x07,0x06,0x15,0x15,0x36,0x03,0xf8,0x3d,0x3e,0x6b,0x75,0xb7,0x7a,0x74,0x81,0x51,0x4a,0xa4,0x37,0x48,0xb5,0x6b,0x41,0x46,0x7b,0x64,0xa3,0x72,0xe2,0x9c,0x61,0x5d,0xfe,0x32,0x50,0x43,0x28,0x25,0xe0,0x01,0xe3,0x8e,0x89,0x8c,0x58,0x73,0x9f,0xe1,0x88,0x9f,0x70,0x66,0x88,0xfe, 0x5c,0x04,0x83,0xb0,0x59,0x76,0x34,0x38,0x66,0x96,0x69,0x55,0x2b,0xd3,0xae,0x7a,0x77,0x02,0x91,0x4b,0x33,0x2f,0x45,0x8d,0x3c,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x04,0x8b,0x04,0x18,0x00,0x2d,0x00,0xcc,0x40,0x89,0x87,0x2d,0x01,0x65,0x2d,0x01,0x76,0x2c,0x01,0x86,0x29,0x96,0x29,0x02,0x64,0x29,0x74,0x29,0x02,0x46,0x26,0x96, 0x26,0x02,0x96,0x24,0x01,0x9a,0x20,0x01,0x8d,0x1f,0x01,0x39,0x1f,0x01,0x5d,0x17,0x01,0x48,0x16,0x01,0x69,0x13,0x01,0x48,0x13,0x01,0x84,0x10,0x01,0x75,0x0f,0x01,0x07,0x0f,0x17,0x0f,0x67,0x0f,0x03,0x9a,0x06,0x01,0x29,0x06,0x01,0x54,0x02,0x01,0x9a,0x0a,0x01,0x8b,0x0a,0x01,0x7e,0x0a,0x01,0x0a,0x08,0x0b,0x21,0x94,0x22,0x01, 0x22,0x21,0x2a,0x2b,0x19,0x28,0x83,0x1d,0x00,0x83,0x15,0x2f,0x21,0x3f,0x21,0x02,0x21,0x19,0x1d,0x15,0x15,0x1d,0x19,0x21,0x04,0x2f,0x0d,0x83,0x0f,0x08,0x1f,0x08,0x02,0x08,0x2b,0x2a,0x18,0x95,0x1a,0x1a,0x22,0x0b,0x0a,0x0a,0x21,0x22,0x10,0x11,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0x33,0x33,0x2f,0x33,0x11,0x39,0x2f,0xed,0x39, 0x39,0x01,0x2f,0x5d,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x5d,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x11,0x33,0x5d,0x10,0xce,0x11,0x39,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x20,0x27,0x26,0x11,0x10,0x13,0x17, 0x02,0x11,0x10,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x20,0x35,0x34,0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x17,0x16,0x15,0x14,0x05,0x15,0x16,0x16,0x04,0x8b,0x8e,0x85,0xcf,0xfe,0xdf,0x9b,0x8d,0xb0,0x88,0x8a,0x74,0x6d,0xb1,0x89,0x5a,0x60,0xcb,0xb0,0x1d,0x17,0x01,0x4f,0xa2,0x8b,0x4c,0x77,0x3d,0x79, 0x65,0x45,0x4a,0xfe,0xef,0x92,0xb1,0x22,0xd2,0x7b,0x73,0xcc,0xba,0x01,0x35,0x01,0xa5,0x01,0x9a,0x3a,0xfe,0x88,0xfe,0x71,0xfe,0xf4,0x96,0x8d,0x4c,0x51,0x8a,0x8b,0x98,0x8b,0xd9,0x8b,0x2c,0x26,0x85,0x60,0x6d,0x22,0x1c,0x4e,0x52,0x65,0xf3,0x36,0x04,0x0e,0xba,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x28,0x06,0x02,0x00,0x16, 0x00,0x22,0x00,0x68,0x40,0x26,0x59,0x21,0x01,0x56,0x1e,0x01,0x55,0x1c,0x01,0x59,0x19,0x01,0x78,0x0b,0x01,0x69,0x0b,0x01,0x66,0x03,0x01,0x94,0x12,0x01,0x76,0x12,0x86,0x12,0x02,0x12,0x00,0x11,0x0e,0x17,0x83,0x00,0x84,0x0e,0xb8,0xff,0xc0,0x40,0x1a,0x0a,0x0d,0x48,0x0e,0x0e,0x24,0x1d,0x83,0x0f,0x08,0x1f,0x08,0x02,0x08,0x11, 0x12,0x01,0x1b,0x95,0x0e,0x0c,0x0f,0x1f,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x33,0xed,0x3f,0x33,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x2b,0xfd,0xed,0x10,0xce,0x11,0x39,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x35,0x10,0x27,0x37,0x16, 0x17,0x16,0x15,0x03,0x34,0x27,0x26,0x23,0x20,0x11,0x10,0x21,0x32,0x37,0x36,0x04,0x28,0x79,0x80,0xe5,0xeb,0x84,0x7b,0x6e,0x7a,0xea,0xc6,0x88,0xb8,0x75,0x71,0x3f,0x3b,0xa8,0x47,0x53,0xa8,0xfe,0xca,0x01,0x36,0xa3,0x55,0x4a,0x01,0xf4,0xf5,0x88,0x8f,0x96,0x8c,0xfa,0xf3,0x80,0x8d,0x77,0x4c,0x01,0x29,0x8d,0x73,0x58,0xa3,0x97, 0x98,0xfe,0x22,0xb5,0x5e,0x6d,0xfe,0x84,0xfe,0x74,0x73,0x63,0x00,0x02,0x00,0x32,0xfe,0x1e,0x04,0xdb,0x06,0x02,0x00,0x25,0x00,0x28,0x01,0x1e,0x40,0x21,0x98,0x22,0x01,0x96,0x20,0x01,0x86,0x0a,0x01,0x99,0x07,0x01,0x21,0x0d,0x0c,0x19,0x1a,0x18,0x1a,0x06,0x27,0x01,0x27,0x15,0x14,0x28,0x14,0x51,0x18,0x61,0x18,0x02,0x18,0xb8, 0xff,0xc8,0x40,0x90,0x33,0x36,0x48,0x00,0x18,0x10,0x18,0x20,0x18,0x03,0xf1,0x18,0x01,0x58,0x18,0x01,0x29,0x18,0x01,0x18,0x14,0x28,0x14,0x84,0x1a,0x18,0x14,0x1a,0x1a,0x18,0x0c,0x84,0x0d,0x0d,0x26,0x0f,0x1a,0x01,0x1a,0x1a,0x28,0x03,0x05,0x84,0x00,0x31,0x17,0x41,0x17,0x51,0x17,0x71,0x17,0x81,0x17,0x05,0x77,0x17,0x01,0x56, 0x17,0x01,0x47,0x17,0x01,0x25,0x17,0x01,0x16,0x17,0x01,0x3e,0x26,0x4e,0x26,0x02,0x38,0x26,0x01,0x0b,0x26,0x01,0x17,0x26,0x28,0x26,0x84,0x16,0x17,0x14,0x16,0x16,0x17,0x02,0x0e,0x00,0x01,0x00,0x00,0x80,0x16,0x01,0x16,0x16,0x58,0x28,0x01,0x26,0x28,0x01,0x28,0x28,0x1b,0x21,0x0d,0x08,0x95,0x23,0x23,0x1f,0x03,0x02,0x02,0x0d, 0x26,0x27,0x95,0x1a,0x16,0x15,0x14,0x15,0x0d,0x15,0x0d,0x15,0x18,0x11,0x95,0x1f,0x01,0x17,0x18,0x1b,0x00,0x3f,0xc4,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xc4,0x33,0xfd,0xc4,0x11,0x33,0x2f,0x33,0x11,0x33,0x2f,0xed,0x12,0x39,0x3f,0x01,0x3d,0x2f,0x5d,0x5d,0xc9,0x18,0x2f,0x5d,0x32,0x2f,0x5d,0x33,0x87,0x10,0x2b, 0x87,0x7d,0xc4,0x01,0x5d,0x5d,0x72,0x5d,0x5d,0x5d,0x5d,0x5d,0x72,0x18,0x10,0xed,0x32,0x10,0xc9,0x2f,0x5d,0x12,0x39,0x2f,0xed,0x87,0x10,0x2b,0x87,0x7d,0xc4,0x01,0x5d,0x5d,0x71,0x72,0x2b,0x72,0x10,0x87,0xc4,0xc4,0x01,0x5d,0x10,0x87,0x0e,0xc4,0x11,0x12,0x01,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x27,0x36,0x35, 0x34,0x26,0x23,0x22,0x07,0x06,0x15,0x23,0x34,0x27,0x26,0x23,0x22,0x11,0x14,0x17,0x21,0x01,0x23,0x01,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x16,0x01,0x21,0x01,0x04,0xdb,0x20,0xa6,0x1e,0x4c,0x47,0x67,0x30,0x24,0xa4,0x24,0x30,0x67,0xac,0x1c,0x03,0xa7,0xfe,0x25,0xa2,0xfe,0x67,0x55,0x4d,0x57,0xb0,0xbb,0x53, 0x53,0xb9,0x8e,0xad,0xfe,0xf4,0xfd,0x4c,0x01,0x56,0x04,0xb8,0x4e,0x52,0x1d,0x53,0x3a,0x51,0x65,0x64,0x49,0x69,0x69,0x49,0x64,0xfe,0xc5,0x6c,0x5d,0xfa,0xaa,0x04,0x7f,0xef,0xa2,0xd3,0x78,0x89,0xbd,0xbd,0xb5,0xfd,0x9a,0xfb,0xe8,0x00,0x00,0x02,0x00,0x50,0xfe,0x1e,0x04,0x00,0x05,0xec,0x00,0x41,0x00,0x4c,0x00,0xe4,0x40,0x8d, 0x76,0x3f,0x01,0x75,0x3e,0x01,0x86,0x3d,0x01,0x73,0x3d,0x01,0x99,0x18,0x01,0x76,0x13,0x01,0x76,0x0f,0x01,0x67,0x0f,0x01,0x88,0x01,0x01,0x37,0x36,0x39,0x2f,0x36,0x36,0x34,0x31,0x32,0x2f,0x84,0x28,0x1c,0x42,0x00,0x84,0x15,0x42,0x15,0x42,0x15,0x22,0x4e,0x2d,0x84,0x2a,0x2a,0x22,0x0b,0x0d,0x84,0x0a,0x08,0x08,0x48,0x84,0x22, 0x43,0x42,0x45,0x4b,0xb9,0x32,0x01,0xa8,0x32,0x01,0x32,0x31,0x31,0x66,0x2f,0x01,0x37,0x2f,0x47,0x2f,0x57,0x2f,0x03,0x26,0x2f,0x01,0x69,0x39,0x01,0x38,0x39,0x48,0x39,0x58,0x39,0x03,0x29,0x39,0x01,0x1c,0x39,0x34,0x2f,0x28,0x05,0x1e,0x26,0x95,0x45,0x4b,0xb6,0x36,0x01,0xa7,0x36,0x01,0x36,0x37,0x37,0x0b,0x0a,0x0a,0x11,0x1e, 0x95,0x4b,0x4b,0x11,0x29,0x95,0x2e,0x2c,0x00,0x11,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0xde,0xed,0x11,0x39,0x2f,0xed,0x11,0x39,0x2f,0x33,0x32,0x2f,0x33,0x5d,0x5d,0x10,0xde,0xed,0x11,0x17,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x32,0x2f,0x33,0x5d,0x5d,0x11,0x12,0x39,0x39,0x01,0x2f,0xed,0x33,0x2f,0x33,0xed,0x32,0x11,0x33,0x2f, 0xed,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xc4,0xc4,0xfd,0xcd,0x39,0x39,0x32,0x2f,0x10,0xc4,0x11,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x27,0x26,0x26,0x27,0x26,0x35,0x06, 0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x11,0x21,0x11,0x33,0x15,0x21,0x11,0x36,0x37,0x17,0x06,0x07,0x16,0x17,0x07,0x26,0x27,0x15,0x14,0x17,0x16,0x17,0x16,0x17,0x16,0x01,0x35,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x04,0x00,0x9d,0x86,0xb6,0xb3,0x88,0x9c,0x28,0x9c,0x1e,0x68,0x58,0x71,0x74,0x56,0x69, 0x25,0x06,0xb5,0x19,0x28,0x5d,0x5d,0x71,0x43,0x3f,0x3f,0x44,0x70,0x5b,0x5f,0xfe,0x7c,0xa4,0x01,0x84,0x55,0x40,0x81,0x4b,0x56,0x56,0x4b,0x81,0x40,0x55,0x23,0x13,0x42,0x67,0x19,0x2b,0xfe,0x39,0x64,0x56,0x25,0x3d,0x3d,0x25,0x56,0x8c,0xa5,0x5f,0x52,0x57,0x64,0xa5,0x5e,0x51,0x37,0x37,0x45,0x65,0x3b,0x32,0x2d,0x36,0x65,0x51, 0x34,0x09,0xbb,0x2c,0x45,0x66,0x29,0x4b,0x46,0x6d,0x6d,0x47,0x4b,0x2a,0x01,0xa1,0x01,0x11,0x79,0xfd,0x61,0x59,0x69,0x60,0x74,0x5d,0x5d,0x74,0x5f,0x69,0x59,0x6d,0x41,0x34,0x1c,0x41,0x66,0x27,0x46,0x02,0x5f,0x43,0x40,0x3f,0x22,0x22,0x40,0x00,0x00,0x02,0x00,0xae,0xff,0xe8,0x04,0x76,0x05,0xec,0x00,0x11,0x00,0x1d,0x00,0x92, 0x40,0x62,0x5a,0x1d,0x01,0x49,0x1d,0x01,0x45,0x1b,0x55,0x1b,0x02,0x46,0x1a,0x56,0x1a,0x02,0x46,0x16,0x56,0x16,0x02,0x49,0x13,0x59,0x13,0x02,0x69,0x05,0x01,0x37,0x1d,0x01,0x37,0x1a,0x01,0x38,0x16,0x01,0x85,0x0e,0x01,0x74,0x0e,0x01,0x07,0x0e,0x17,0x0e,0x02,0x0e,0x0c,0x0b,0x2e,0x0d,0x01,0x1f,0x0d,0x01,0x0d,0x0d,0x00,0x83, 0x10,0x12,0x20,0x12,0x30,0x12,0x03,0x12,0x12,0x1f,0x0b,0x84,0x18,0x83,0x08,0x0c,0x2e,0x0d,0x01,0x0d,0x0d,0x0a,0x14,0x95,0x66,0x0b,0x01,0x0b,0x0e,0x0f,0x0a,0x00,0x1c,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xc4,0x01,0x2f,0xed,0xed,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x5d,0x5d,0x12,0x39, 0x39,0x5d,0x5d,0x5d,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x33,0x11,0x01,0x33,0x01,0x32,0x17,0x16,0x07,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x04,0x76,0x7b,0x84,0xeb,0xe5,0x80,0x79,0xa8,0x01,0xd8,0xd7,0xfe,0xa0,0xea,0x79, 0x6e,0xa8,0xfe,0xca,0xa8,0x53,0x47,0x4a,0x55,0xa3,0x01,0x36,0x01,0xf0,0xe6,0x8c,0x96,0x8f,0x88,0xe1,0x04,0x0c,0xfd,0x7a,0x01,0x9e,0xfe,0xd8,0x8d,0x80,0xe5,0x01,0x68,0x6d,0x5e,0xa1,0x9e,0x63,0x73,0x00,0x00,0x01,0x00,0x21,0xfe,0x1e,0x05,0xf5,0x04,0x18,0x00,0x43,0x01,0x30,0x40,0xb7,0x75,0x3a,0x01,0x67,0x29,0x01,0x56,0x29, 0x01,0x45,0x29,0x01,0x26,0x29,0x01,0x36,0x17,0x01,0x6a,0x0e,0x01,0x42,0x41,0x41,0x00,0x84,0x3f,0x3b,0x30,0x31,0x31,0x2c,0x3a,0x3b,0x28,0x38,0x08,0x39,0x38,0x08,0x38,0x2a,0x2b,0x17,0x29,0x3b,0x28,0x2b,0x17,0x18,0x06,0x19,0x2b,0x17,0x07,0x06,0x19,0x38,0x08,0xa5,0x2b,0x01,0x2b,0x08,0x38,0x08,0x84,0x17,0x2b,0x14,0x17,0x17, 0x2b,0x2b,0x2c,0x84,0x38,0x37,0x37,0x28,0x06,0x19,0x06,0x84,0x3b,0x28,0x14,0x3b,0x28,0x3b,0x3b,0x17,0x45,0x20,0x1f,0x22,0x84,0x1d,0x1f,0x1f,0x1d,0x19,0x19,0x17,0x10,0x0f,0x08,0x17,0x0a,0x84,0x00,0x15,0x01,0x15,0x15,0x17,0x38,0x2e,0x31,0x33,0x30,0x30,0x2e,0x95,0x33,0x33,0x26,0xc5,0x1f,0x01,0x1f,0x20,0x20,0x19,0x1b,0x95, 0x28,0x26,0x10,0xba,0x41,0x01,0xa9,0x41,0x01,0x41,0x42,0x42,0x3b,0x3d,0x95,0x04,0xd2,0x17,0x01,0x24,0x17,0x44,0x17,0x54,0x17,0x03,0x09,0x17,0x01,0x17,0x76,0x10,0x86,0x10,0x02,0x10,0x12,0x95,0x6c,0x0f,0x01,0x0f,0x0d,0x0d,0x06,0x04,0x1c,0x00,0x3f,0x33,0x33,0x2f,0x33,0x5d,0xed,0x32,0x5d,0x32,0x5d,0x5d,0x5d,0x10,0xed,0x32, 0x32,0x2f,0x33,0x5d,0x5d,0x3f,0x33,0xed,0x32,0x32,0x2f,0x33,0x5d,0x11,0x33,0x2f,0xed,0x32,0x2f,0x12,0x39,0x11,0x33,0x01,0x2f,0x33,0x2f,0x5d,0xed,0x11,0x39,0xcc,0x32,0x11,0x33,0x2f,0xce,0x32,0x2f,0x10,0xed,0x11,0x39,0x11,0x12,0x39,0x2f,0x87,0x2b,0x87,0x7d,0xc4,0x01,0x33,0x18,0x2f,0x33,0xed,0x32,0x87,0x04,0x10,0x2b,0x87, 0x7d,0xc4,0x00,0x5d,0x0f,0x0f,0x0f,0x87,0x0e,0xc4,0x10,0x87,0x0e,0xc4,0x0f,0x11,0x01,0x33,0x18,0x2f,0x33,0x10,0xde,0xed,0x33,0x2f,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x01,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x01,0x01, 0x26,0x23,0x22,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x01,0x01,0x36,0x35,0x34,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07,0x01,0x01,0x16,0x33,0x32,0x35,0x34,0x27,0x37,0x16,0x05,0xf5,0x40,0x3c,0x5b,0x90,0x52,0xfe,0xcf,0xfe,0xa4,0x33,0x8e,0x69,0x77,0x53,0x43,0x3c,0x4b,0x24,0x36,0x83, 0x01,0xef,0xfe,0xc3,0x36,0x2f,0x2b,0x5a,0x7f,0x74,0x40,0x3c,0x5b,0x8b,0x52,0x01,0x3b,0x01,0xd3,0x59,0x38,0x3d,0x87,0x58,0xac,0x64,0x62,0x3a,0x37,0x86,0xfe,0x26,0x01,0x35,0x37,0x30,0x2b,0x5a,0x7f,0x74,0xfe,0xf1,0x62,0x3a,0x37,0x86,0x01,0xf3,0xfe,0xfd,0x38,0x6c,0x5d,0x75,0x47,0x8a,0x47,0x34,0x24,0x6b,0x50,0x01,0x70,0x02, 0x06,0x58,0x38,0x3d,0x87,0x58,0xac,0x64,0x62,0x3a,0x37,0x86,0xfd,0xff,0x01,0x5c,0x42,0x25,0x2b,0x5a,0x7f,0x74,0x40,0x3c,0x5b,0x7e,0x64,0xfe,0x9f,0xfe,0x08,0x59,0x38,0x3d,0x87,0x58,0xac,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0xf3,0x06,0x02,0x00,0x3d,0x00,0xa2,0x40,0x5f,0x94,0x32,0x01,0x87,0x2e,0x01,0x98,0x15,0x01,0x86, 0x12,0x01,0x77,0x12,0x01,0x77,0x0f,0x87,0x0f,0x02,0x99,0x01,0x01,0x36,0x20,0x33,0x84,0x24,0x24,0x13,0x3a,0x19,0x38,0x84,0x1d,0x1d,0x13,0x20,0x20,0x19,0x19,0x0d,0x00,0x84,0x13,0x13,0x08,0x3f,0x2d,0x2c,0x2c,0x0b,0x0d,0x84,0x0a,0x0f,0x08,0x01,0x08,0x36,0x20,0x95,0x22,0x3a,0x19,0x0b,0x0a,0x0a,0x17,0x95,0x19,0x8b,0x2c,0x01, 0x18,0x31,0x01,0x9a,0x28,0x01,0x28,0x31,0x2c,0x03,0x2d,0x22,0x19,0x22,0x19,0x2d,0x01,0x11,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x5d,0x5d,0x5d,0x10,0xed,0x32,0x2f,0x33,0x11,0x39,0x10,0xed,0x39,0x01,0x2f,0x5d,0x33,0xed,0x32,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x33,0x2f, 0x11,0x33,0x2f,0xed,0x11,0x39,0x11,0x33,0x2f,0xed,0x11,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x35,0x34,0x27,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x27,0x26,0x27,0x26, 0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x17,0x04,0x15,0x14,0x06,0x07,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x03,0xf3,0x8f,0x80,0xd5,0xae,0x79,0x88,0x29,0x99,0x1c,0x55,0x4a,0x6c,0x01,0x3f,0x3d,0x40,0x60,0x60,0x60,0x64,0x79,0xdd,0x60,0x60,0xdd,0x55,0x17,0x79,0xa1,0x2f,0x6a,0x3d,0x6d,0x41,0x5f,0x23,0x9d,0x01,0x32,0x6d,0x5c,0xc9, 0xc9,0x58,0x3a,0x37,0x01,0x2b,0xa2,0x55,0x4c,0x57,0x62,0xa7,0x5c,0x53,0x37,0x33,0x49,0x66,0x3a,0x32,0xc9,0x43,0x2f,0x30,0x8b,0x48,0x40,0x82,0x8b,0x84,0x44,0x1e,0x08,0x14,0x1b,0x10,0x24,0x54,0x60,0x48,0x1c,0x0b,0x18,0x2f,0xc9,0x4a,0x6e,0x13,0x2a,0xa1,0xa0,0x2a,0x13,0x4b,0x47,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x95, 0x06,0x02,0x00,0x3d,0x00,0x45,0x00,0xc6,0x40,0x7a,0x76,0x41,0x01,0x57,0x41,0x67,0x41,0x02,0x65,0x30,0x01,0x99,0x2b,0x01,0x98,0x2a,0x01,0x99,0x29,0x01,0x99,0x28,0x01,0x99,0x17,0x01,0x9b,0x14,0x01,0x89,0x14,0x01,0x94,0x12,0x01,0x55,0x12,0x85,0x12,0x02,0x37,0x11,0x01,0x86,0x0d,0x01,0x89,0x07,0x01,0x6b,0x03,0x01,0x36,0x22, 0x33,0x84,0x26,0x26,0x15,0x3a,0x1b,0x00,0x22,0x22,0x2f,0x1b,0x01,0x1b,0x1b,0x42,0x38,0x84,0x1f,0x1f,0x15,0x2d,0x2c,0x3e,0x84,0x0b,0x0b,0x42,0x00,0x84,0x15,0x15,0x47,0x0f,0x42,0x83,0x06,0x3a,0x19,0x95,0x1b,0x42,0x95,0x0f,0x36,0x23,0x95,0x21,0x1b,0x0f,0x21,0x21,0x0f,0x1b,0x03,0x13,0x40,0x95,0x08,0x2c,0x2d,0x2d,0x08,0x01, 0x13,0x95,0x02,0x16,0x00,0x3f,0xed,0x3f,0x33,0x2f,0x33,0x10,0xed,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x10,0xed,0x39,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0xed,0xce,0x32,0x11,0x33,0x2f,0xed,0x12,0x39,0x2f,0x5d,0x33,0x2f,0x11,0x12,0x39,0x11,0x33,0x2f,0xed,0x11,0x39,0x31,0x30,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x20,0x03,0x26,0x11,0x10,0x21,0x32,0x16,0x15,0x14,0x07,0x06,0x07,0x14,0x17,0x12,0x33,0x20,0x35,0x34,0x27,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x27,0x26,0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x17, 0x16,0x15,0x14,0x06,0x07,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x23,0x22,0x11,0x36,0x37,0x36,0x04,0x95,0xfe,0x5f,0xfe,0xb4,0xb4,0x94,0x01,0x4e,0x67,0x7c,0x7d,0x7a,0x8f,0x67,0x87,0xf0,0x01,0x09,0x3d,0x40,0x60,0x60,0x60,0x64,0x79,0xdd,0x60,0x60,0xdd,0x3d,0x40,0x41,0x51,0x21,0x81,0x1a,0x5b,0x88,0x0c,0x49,0x6d,0x5c, 0xc9,0xc9,0x58,0x3a,0x37,0xfd,0x5a,0x41,0xa3,0x65,0x45,0x3a,0x01,0x2b,0xfe,0xbd,0x01,0x30,0xfa,0x01,0x59,0x02,0x97,0x74,0x68,0xa0,0xa0,0x9b,0x26,0xd8,0xcc,0xfe,0xf1,0xc9,0x43,0x2f,0x30,0x8b,0x48,0x40,0x82,0x8b,0x84,0x36,0x29,0x27,0x28,0x39,0x50,0x4a,0x41,0x3c,0x59,0x0b,0x42,0x5c,0x4a,0x6e,0x13,0x2a,0xa1,0xa0,0x2a,0x13, 0x4b,0x47,0x03,0xa4,0x55,0xfe,0x40,0x1b,0x83,0x6f,0x00,0x02,0x00,0x32,0xff,0xe8,0x05,0x1d,0x04,0x18,0x00,0x19,0x00,0x27,0x01,0x04,0x40,0xb7,0x48,0x20,0x58,0x20,0x02,0x48,0x1c,0x58,0x1c,0x02,0x08,0x17,0x01,0x77,0x13,0x01,0x65,0x13,0x01,0x77,0x0f,0x01,0x65,0x0f,0x01,0x08,0x0b,0x01,0x25,0x1a,0x22,0x17,0x04,0x0b,0x03,0x0d, 0x19,0x19,0x15,0x83,0x1a,0x1a,0x29,0x22,0x83,0x0d,0x09,0x09,0x0d,0x1e,0x95,0x11,0x10,0x16,0x25,0x01,0x07,0x25,0x01,0xe7,0x25,0xf7,0x25,0x02,0xc5,0x25,0x01,0x97,0x25,0x01,0x73,0x25,0x83,0x25,0x02,0x64,0x25,0x01,0x47,0x25,0x57,0x25,0x02,0x25,0x09,0xda,0x0b,0x01,0x99,0x0b,0x01,0x0b,0x95,0x06,0x19,0xda,0x17,0x01,0x99,0x17, 0x01,0x17,0x95,0x19,0x00,0x01,0x08,0x00,0x01,0xe9,0x00,0xf9,0x00,0x02,0x9b,0x00,0x01,0x00,0x02,0x02,0x19,0x08,0x01,0x08,0x08,0x01,0xe9,0x08,0xf9,0x08,0x02,0x9b,0x08,0x01,0x08,0x0b,0x04,0x01,0xeb,0x04,0xfb,0x04,0x02,0x04,0x20,0x21,0x24,0x48,0x7c,0x04,0x01,0x5d,0x04,0x6d,0x04,0x02,0x4b,0x04,0x01,0x1a,0x04,0x2a,0x04,0x3a, 0x04,0x03,0x09,0x04,0x01,0xfa,0x04,0x01,0xdb,0x04,0xeb,0x04,0x02,0x9d,0x04,0x01,0x04,0x06,0x16,0x00,0x3f,0x33,0x5d,0x5d,0x5d,0x71,0x71,0x71,0x71,0x71,0x2b,0x71,0x72,0x33,0x5d,0x5d,0x71,0x71,0x33,0x2f,0x33,0x5d,0x5d,0x71,0x71,0xed,0x5d,0x5d,0x32,0x10,0xed,0x5d,0x5d,0x32,0x32,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x71,0x3f, 0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x32,0x2f,0x11,0x17,0x39,0x11,0x12,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x27,0x35,0x16,0x37,0x26,0x11,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x10,0x07,0x16,0x37,0x01,0x34,0x27,0x26,0x23,0x22,0x07,0x06, 0x15,0x14,0x16,0x17,0x36,0x36,0x05,0x1d,0x92,0xec,0x84,0x73,0x73,0x85,0xec,0x92,0x8e,0xfb,0xe8,0x8a,0x7d,0xcc,0xcc,0x7e,0x8c,0xe8,0xfb,0x8e,0xfe,0xb7,0x59,0x4e,0x87,0x86,0x4e,0x57,0xa3,0x8a,0x8a,0xa2,0x1b,0x33,0x1e,0x1e,0x33,0x9c,0x47,0x02,0xa6,0x01,0x2a,0xe8,0x7d,0x71,0x71,0x7d,0xe8,0xfe,0xd6,0xa6,0x02,0x47,0x01,0x8b, 0xaa,0x56,0x4c,0x4c,0x56,0xaa,0x88,0xe0,0x39,0x39,0xe0,0x00,0x00,0x01,0x00,0x5e,0xfe,0x1e,0x03,0xf1,0x04,0x00,0x00,0x28,0x00,0x9a,0x40,0x5d,0x55,0x27,0x01,0x99,0x16,0x01,0x3a,0x16,0x4a,0x16,0x02,0x76,0x0f,0x01,0x57,0x0f,0x67,0x0f,0x02,0x66,0x02,0x01,0x54,0x02,0x01,0x77,0x25,0x01,0x99,0x1a,0x01,0x8a,0x1a,0x01,0x59,0x1a, 0x69,0x1a,0x02,0x25,0x1a,0x24,0x19,0x19,0x0d,0x15,0x24,0x24,0x00,0x83,0x15,0x15,0x08,0x2a,0x1f,0x1e,0x1e,0x0b,0x0d,0x84,0x0a,0x0f,0x08,0x01,0x08,0x1a,0x1c,0x24,0x23,0x23,0x1f,0x19,0x25,0x95,0x0b,0x0a,0x18,0x0a,0x18,0x0a,0x11,0x1c,0x95,0x21,0x21,0x1e,0x95,0x1f,0x0f,0x11,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x33,0x2f, 0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x39,0x11,0x33,0x2f,0x33,0x12,0x39,0x01,0x2f,0x5d,0x33,0xed,0x32,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0xed,0x32,0x2f,0x11,0x12,0x39,0x2f,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17, 0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x10,0x21,0x23,0x35,0x01,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x25,0x15,0x01,0x16,0x17,0x16,0x03,0xf1,0x8e,0x85,0xcf,0xaa,0x7d,0x88,0x29,0x99,0x1c,0x55,0x4e,0x68,0x86,0x57,0x5b,0xfe,0x54,0x52,0x01,0x65,0x77,0x77,0xab,0xb9,0x2b,0x93,0xcb,0xcc,0x01,0x03,0xfe,0x77,0xd2, 0x74,0x7e,0x1d,0xd2,0x7d,0x76,0x61,0x6a,0xa9,0x5c,0x53,0x37,0x33,0x49,0x68,0x42,0x3c,0x54,0x57,0x8c,0x01,0x4e,0x33,0x01,0xea,0x18,0x42,0x8c,0x42,0x42,0x33,0xfd,0xe1,0x19,0x6e,0x77,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x06,0x02,0x00,0x43,0x00,0xe0,0x40,0x8f,0x56,0x43,0x66,0x43,0x02,0x85,0x3d,0x01,0x57,0x3d,0x67,0x3d, 0x02,0x76,0x36,0x86,0x36,0x02,0x79,0x32,0x89,0x32,0x02,0x89,0x22,0x01,0x48,0x17,0x01,0x59,0x13,0x69,0x13,0x02,0x76,0x0f,0x86,0x0f,0x02,0x67,0x0f,0x01,0x56,0x0f,0x01,0x2d,0x2b,0x84,0x2e,0x30,0x30,0x15,0x85,0x3a,0x95,0x3a,0x02,0x3a,0x38,0x3e,0x83,0x9b,0x1f,0x01,0x79,0x1f,0x01,0x08,0x1f,0x01,0x1f,0x23,0x1d,0x1d,0x15,0x54, 0x40,0x01,0x41,0x40,0x00,0x19,0x19,0x0d,0x00,0x83,0x20,0x15,0x01,0x15,0x15,0x08,0x45,0x38,0x83,0x23,0x23,0x0b,0x0d,0x84,0x0a,0x0f,0x08,0x1f,0x08,0x02,0x08,0x2e,0x2d,0x40,0x41,0x1a,0x0b,0x0a,0x0a,0x11,0x18,0x95,0x1a,0x18,0x1f,0x01,0x3a,0x1f,0x1a,0x0f,0x2d,0x1f,0x2d,0x02,0x2d,0x1a,0x2d,0x1a,0x11,0x34,0x95,0x27,0x01,0x11, 0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x5d,0x12,0x39,0x39,0x5d,0x10,0xed,0x11,0x39,0x2f,0x33,0x11,0x39,0x39,0x11,0x33,0x01,0x2f,0x5d,0x33,0xed,0x32,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0x5d,0x11,0x33,0x2f,0x12,0x39,0x5d,0x5d,0x5d,0xed,0x11,0x39,0x5d,0x11, 0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x20,0x35,0x34,0x27,0x24,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07, 0x27,0x36,0x35,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x17,0x16,0x15,0x14,0x05,0x15,0x16,0x16,0x03,0xf1,0x8e,0x85,0xcf,0xaa,0x7d,0x88,0x29,0x99,0x1c,0x55,0x4e,0x68,0x88,0x55,0x5b,0xcb,0xb0,0x1d,0x17,0x01,0x4f,0xa7,0xfe,0xf2,0x2a,0xa7,0x89,0x79,0xaf,0xae,0x79,0x88,0x27,0x9d,0x1e,0x54,0x4a,0x6b,0x6c,0x4a, 0x55,0xa8,0x9c,0x9c,0xa8,0xfe,0xef,0x92,0xb1,0x22,0xd2,0x7b,0x73,0x61,0x6a,0xa9,0x5c,0x53,0x37,0x33,0x49,0x68,0x42,0x3c,0x4c,0x50,0x8b,0x8b,0x98,0x8b,0xd9,0x5d,0x3f,0x66,0x1a,0x6a,0xc6,0xa8,0x61,0x57,0x57,0x62,0xa7,0x60,0x4f,0x37,0x37,0x45,0x67,0x39,0x32,0x32,0x39,0x67,0x98,0x4b,0x38,0x38,0x4d,0x9e,0xf3,0x36,0x04,0x0e, 0xba,0x00,0x00,0x03,0x00,0x52,0xff,0xe8,0x04,0x92,0x06,0x02,0x00,0x21,0x00,0x2c,0x00,0x38,0x00,0x81,0x40,0x50,0x99,0x37,0x01,0x8a,0x37,0x01,0x85,0x31,0x01,0x8a,0x25,0x01,0x79,0x25,0x01,0x96,0x19,0x01,0x9a,0x16,0x01,0x7a,0x12,0x8a,0x12,0x02,0x9a,0x0b,0x01,0x7b,0x0b,0x01,0x7b,0x0a,0x01,0x1e,0x21,0x1c,0x01,0x1f,0x84,0x2e, 0x22,0x0e,0x0e,0x09,0x3a,0x28,0x83,0x14,0x14,0x33,0x83,0x09,0x40,0x09,0x0c,0x48,0x09,0x1c,0x22,0x95,0x0f,0x1f,0x0e,0x2e,0x01,0x95,0x20,0x0e,0x0e,0x35,0x26,0x95,0x18,0x01,0x35,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xc4,0xfd,0xc4,0x10,0xdd,0xc4,0xfd,0xc4,0x01,0x2f,0x2b,0xed,0x33,0x2f,0xed,0x11,0x12,0x39, 0x2f,0xc4,0xc4,0xfd,0xc4,0xc4,0xde,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x33,0x35,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x16,0x15,0x15,0x21,0x15,0x21,0x15,0x21,0x01,0x35,0x34,0x26,0x23,0x22,0x15,0x14,0x17, 0x16,0x33,0x13,0x35,0x23,0x22,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x36,0x04,0x92,0xfe,0xd4,0xcd,0xb6,0xb5,0x6b,0x71,0x81,0x74,0xb1,0xc6,0xc6,0xb1,0x74,0x81,0x71,0x6b,0xb5,0xb6,0xcd,0x01,0x2c,0xfe,0xd4,0x01,0x2c,0xfe,0x2c,0x72,0x69,0xe1,0x4c,0x45,0x65,0xc6,0xc6,0x65,0x45,0x4c,0xe1,0x69,0x3a,0x38,0x02,0x0e,0xa8,0xb5,0xc9, 0x57,0x5c,0xa8,0xab,0x60,0x58,0x9e,0x58,0x60,0xab,0xa8,0x5c,0x57,0xc9,0xb5,0xa8,0x98,0x9e,0x01,0x36,0xa8,0x68,0x7f,0xc4,0x60,0x39,0x32,0xfd,0x8a,0xa8,0x32,0x39,0x60,0xc4,0x41,0x3e,0x00,0x03,0x00,0x60,0xfe,0x1e,0x07,0x48,0x06,0x02,0x00,0x31,0x00,0x3d,0x00,0x49,0x00,0xb9,0x40,0x79,0x46,0x45,0x01,0x46,0x43,0x01,0x49,0x3d, 0x01,0x49,0x33,0x01,0x55,0x45,0x01,0x59,0x43,0x01,0x55,0x3d,0x01,0x5a,0x33,0x01,0x44,0x83,0x0f,0x19,0x1f,0x19,0x3f,0x19,0x03,0x19,0x12,0x32,0x83,0x00,0x00,0x10,0x00,0x30,0x00,0x03,0x00,0x06,0x38,0x38,0x2c,0x0b,0x06,0x84,0x12,0x3e,0x3e,0x24,0x1f,0x12,0x24,0x22,0x95,0x25,0x27,0x01,0x34,0x95,0x44,0x2c,0x54,0x2c,0x02,0x2c, 0x2e,0x2e,0x42,0x95,0x44,0x1f,0x54,0x1f,0x02,0x1f,0x1d,0x0f,0x3c,0x95,0x79,0x06,0x01,0x6a,0x06,0x01,0x4b,0x06,0x5b,0x06,0x02,0x06,0x04,0x04,0x46,0x95,0x69,0x13,0x79,0x13,0x02,0x4b,0x13,0x5b,0x13,0x02,0x13,0x15,0x16,0x0b,0x09,0x95,0x0c,0x0e,0x1c,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0x5d,0x5d,0xed,0x33,0x2f,0x33,0x5d,0x5d, 0x5d,0xed,0x3f,0x33,0x5d,0xed,0x33,0x2f,0x33,0x5d,0xed,0x3f,0x33,0xed,0x32,0x01,0x2f,0xc4,0xcc,0x33,0x2f,0x10,0xfd,0xce,0xc4,0x33,0x2f,0x10,0xdc,0x5d,0xed,0x10,0xdc,0x5d,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x15,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x27, 0x26,0x35,0x35,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x11,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x16,0x15,0x11,0x36,0x33,0x32,0x17,0x16,0x07,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x20,0x01,0x34,0x27,0x26,0x23,0x20,0x11,0x10,0x21,0x32,0x37,0x36,0x07,0x48,0x7b,0x84,0xeb,0xbc,0x7a, 0xac,0x3d,0x30,0x2c,0x4b,0x93,0x5d,0x5a,0x7a,0xbc,0xeb,0x84,0x7b,0x6e,0x7a,0xea,0xc6,0x88,0xac,0x3d,0x30,0x2c,0x4b,0x93,0x5d,0x5a,0x88,0xc6,0xea,0x7a,0x6e,0xa8,0xfe,0xca,0xa8,0x53,0x47,0x4a,0x55,0xa3,0x01,0x36,0xfc,0xe0,0x47,0x53,0xa8,0xfe,0xca,0x01,0x36,0xa1,0x56,0x4b,0x01,0xf0,0xe6,0x8c,0x96,0x63,0xc9,0xd9,0x1b,0x94, 0x12,0x65,0x62,0x95,0xd1,0x63,0x96,0x8c,0xe6,0xdf,0x80,0x8d,0x77,0x01,0x39,0xd9,0x1b,0x94,0x12,0x65,0x62,0x95,0xfe,0xbf,0x77,0x8d,0x80,0xe5,0x01,0x68,0x6d,0x5e,0xa1,0x9e,0x63,0x73,0x01,0x74,0xa1,0x5e,0x6d,0xfe,0x98,0xfe,0x88,0x71,0x62,0x00,0x00,0x01,0x00,0x60,0xfe,0x1e,0x03,0xf1,0x04,0x18,0x00,0x2f,0x00,0xc2,0x40,0x83, 0x79,0x29,0x01,0x68,0x29,0x01,0x59,0x29,0x01,0x56,0x25,0x66,0x25,0x02,0x25,0x1f,0x01,0x77,0x1e,0x01,0x35,0x1e,0x01,0x85,0x1b,0x95,0x1b,0x02,0x8a,0x17,0x9a,0x17,0x02,0x75,0x12,0x01,0x67,0x12,0x01,0x7a,0x0f,0x01,0x2a,0x0a,0x01,0x69,0x09,0x01,0x06,0x02,0x16,0x02,0x02,0x2e,0x00,0x84,0x2d,0x2b,0x2b,0x0e,0x34,0x20,0x54,0x20, 0x64,0x20,0x84,0x20,0x04,0x20,0x23,0x1d,0x83,0x8b,0x0b,0x9b,0x0b,0x02,0x6d,0x0b,0x01,0x4a,0x0b,0x5a,0x0b,0x02,0x2f,0x0b,0x01,0x0b,0x08,0x20,0x0e,0x30,0x0e,0x02,0x0e,0x0e,0x31,0x23,0x83,0x08,0x14,0x84,0x15,0x15,0x0f,0x08,0x1f,0x08,0x02,0x08,0x2d,0x2e,0x2e,0x27,0x20,0x20,0x04,0x15,0x15,0x0b,0x10,0x95,0x0b,0x19,0x10,0x27, 0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0x39,0xed,0x11,0x39,0x2f,0x11,0x39,0x11,0x12,0x39,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x2f,0xed,0x10,0xed,0x12,0x39,0x2f,0x5d,0x12,0x39,0x5d,0x5d,0x5d,0x5d,0xed,0x11,0x39,0x5d,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x05,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x36,0x35,0x34,0x21,0x22,0x07,0x06,0x15,0x23,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x14,0x07,0x06,0x07,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x27,0x37,0x16,0x03,0xf1,0x88,0x7d,0xaa,0xcf,0x85,0x8e,0xbc,0xae,0xae,0xbc,0xfe,0xfb,0x68,0x44, 0x4b,0xa6,0x7f,0x73,0xab,0xba,0x77,0x7c,0xbc,0xae,0xae,0xbc,0x5b,0x55,0x88,0x68,0x4e,0x55,0x1c,0x9a,0x28,0x6e,0xa9,0x6a,0x61,0x73,0x7b,0xd2,0xcd,0x76,0x4d,0x4e,0x58,0x85,0xf4,0x34,0x39,0x68,0xa8,0x61,0x57,0x60,0x63,0xa7,0xe0,0x72,0x4b,0x4b,0x57,0xa0,0x8b,0x50,0x4c,0x3c,0x42,0x68,0x49,0x33,0x37,0x51,0x00,0x01,0x00,0x5f, 0xfe,0x1e,0x03,0xf0,0x04,0x18,0x00,0x3b,0x00,0x76,0x40,0x49,0x56,0x2a,0x66,0x2a,0x76,0x2a,0x03,0x55,0x24,0x65,0x24,0x02,0x47,0x24,0x01,0x99,0x1a,0x01,0x9a,0x19,0x01,0x76,0x0a,0x86,0x0a,0x02,0x2f,0x31,0x84,0x2c,0x12,0x17,0x84,0x11,0x0c,0x0c,0x2e,0x2c,0x2c,0x3d,0x02,0x21,0x84,0x3b,0x6b,0x21,0x01,0x3a,0x21,0x4a,0x21,0x5a, 0x21,0x03,0x21,0x07,0x95,0x2e,0x2f,0x1c,0x2f,0x1c,0x2f,0x01,0x27,0x95,0x36,0x1c,0x11,0x12,0x12,0x01,0x0f,0x00,0x3f,0x33,0x2f,0x33,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x33,0x5d,0x5d,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x13,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x5f,0xa4,0x27,0x48,0x65,0x3e,0x2e,0x57,0x42,0x28,0x0c,0x07, 0x09,0x0a,0x99,0x0e,0x0b,0x0a,0x10,0x39,0x68,0x91,0x57,0x2a,0x53,0x4b,0x40,0x16,0x30,0x55,0x73,0x44,0x32,0x60,0x4b,0x2e,0x1c,0x99,0x29,0x49,0x79,0x9b,0x52,0x66,0xb1,0x81,0x4a,0x04,0x00,0x85,0x45,0x80,0x63,0x3b,0x20,0x42,0x66,0x46,0x26,0x43,0x1a,0x1e,0x1a,0x37,0x22,0x28,0x22,0x59,0x33,0x5f,0x96,0x67,0x36,0x15,0x24,0x2f, 0x1a,0xfd,0xbf,0x45,0x6d,0x4d,0x28,0x20,0x3c,0x55,0x35,0x4a,0x32,0x37,0x54,0x5b,0x56,0x8a,0x60,0x34,0x3d,0x74,0xa6,0x69,0x00,0x02,0x00,0x60,0xfe,0x1e,0x04,0x50,0x04,0x18,0x00,0x36,0x00,0x46,0x00,0x93,0x40,0x60,0x45,0x46,0x55,0x46,0x02,0x55,0x42,0x01,0x46,0x42,0x01,0x5a,0x3f,0x01,0x49,0x3f,0x01,0x59,0x39,0x01,0x4a,0x39, 0x01,0x64,0x27,0x01,0x69,0x23,0x01,0x79,0x1e,0x01,0x6a,0x1e,0x01,0x09,0x1e,0x19,0x1e,0x02,0x16,0x12,0x26,0x12,0x46,0x12,0x56,0x12,0x04,0x2f,0x32,0x84,0x1a,0x1d,0x1a,0x0b,0x10,0x83,0x0a,0x05,0x05,0x2a,0x83,0x3c,0x30,0x3c,0x01,0x1a,0x3c,0x1a,0x3c,0x48,0x44,0x83,0x0f,0x20,0x1f,0x20,0x02,0x20,0x0a,0x0b,0x37,0x95,0x1d,0x2f, 0x2f,0x00,0x41,0x95,0x25,0x10,0x00,0x95,0x15,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0xce,0x32,0x01,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x33,0x2f,0x33,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x32,0x3e,0x02,0x35, 0x34,0x26,0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x06,0x06,0x15,0x14,0x1e,0x02,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0xea,0x2a,0x46,0x32,0x1c,0x06, 0x04,0x04,0x06,0xa6,0x06,0x05,0x04,0x07,0x35,0x5f,0x83,0x4f,0x4f,0x82,0x5e,0x34,0x17,0x0e,0xa5,0xa7,0x46,0x83,0xbd,0x78,0x74,0xb9,0x81,0x44,0x46,0x86,0xc1,0x7c,0x0e,0x10,0x1d,0x33,0x47,0x6e,0x57,0x81,0x54,0x2a,0x2b,0x56,0x80,0x55,0x9f,0xab,0xab,0xfe,0xa8,0x1f,0x35,0x45,0x27,0x1a,0x30,0x12,0x15,0x12,0x1d,0x16,0x1a,0x16, 0x3a,0x20,0x4a,0x7a,0x57,0x2f,0x2f,0x58,0x7d,0x4e,0x43,0x60,0x22,0x28,0xfa,0xc3,0x76,0xbd,0x84,0x47,0x44,0x80,0xb7,0x73,0x7c,0xc1,0x84,0x45,0x27,0x4e,0x35,0x33,0x4f,0x35,0x1b,0x02,0x06,0x35,0x62,0x8a,0x55,0x53,0x86,0x5e,0x33,0xb0,0xbe,0xc0,0xb2,0x00,0x00,0x01,0x00,0x40,0xfe,0x1e,0x04,0x96,0x04,0x18,0x00,0x33,0x00,0x93, 0x40,0x60,0x35,0x27,0x45,0x27,0x55,0x27,0x95,0x27,0x04,0x3a,0x23,0x4a,0x23,0x5a,0x23,0x03,0x65,0x16,0x01,0x94,0x2f,0x01,0x86,0x2f,0x01,0x64,0x2f,0x74,0x2f,0x02,0x2f,0x2a,0x8f,0x0c,0x9f,0x0c,0x02,0x3b,0x0c,0x4b,0x0c,0x5b,0x0c,0x03,0x18,0x0c,0x01,0x0c,0x0f,0x8b,0x01,0x9b,0x01,0x02,0x19,0x01,0x39,0x01,0x02,0x01,0x00,0x00, 0x1c,0x19,0x83,0x1d,0x20,0x20,0x35,0x2a,0x83,0x0f,0x09,0x09,0x0f,0x1d,0x1c,0x1c,0x0c,0x25,0x95,0x14,0x10,0x2f,0x01,0x0c,0x95,0x06,0x09,0x95,0x08,0x08,0x06,0x00,0x01,0x1c,0x00,0x3f,0x33,0xce,0x32,0x2f,0xed,0x10,0xed,0x11,0x39,0x3f,0xed,0x11,0x39,0x2f,0x33,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x32, 0x2f,0x33,0x5d,0x5d,0x12,0x39,0x5d,0x5d,0x5d,0x12,0x39,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x01,0x07,0x2e,0x03,0x23,0x22,0x07,0x35,0x36,0x36,0x33,0x26,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x04,0x96, 0x68,0x4f,0x98,0x9c,0xa4,0x5c,0xd7,0x94,0x4e,0xc0,0x6b,0xa8,0xb1,0x49,0x89,0xc5,0x7d,0x6f,0xb1,0x7b,0x42,0x0a,0x13,0x9d,0x0c,0x06,0x2b,0x52,0x77,0x4d,0x57,0x84,0x58,0x2d,0x43,0x84,0xc4,0x81,0x3a,0x65,0x5c,0x59,0xfe,0x9b,0x7d,0x3f,0x5e,0x3f,0x20,0x7e,0xa8,0x31,0x31,0x5e,0x01,0x30,0xca,0x7c,0xc7,0x8c,0x4b,0x4a,0x8a,0xc2, 0x78,0x28,0x4c,0x61,0x37,0x42,0x3a,0x23,0x56,0x8f,0x66,0x38,0x3b,0x68,0x90,0x54,0x81,0xb9,0x8e,0x71,0x39,0x1a,0x39,0x3e,0x44,0x00,0x00,0x03,0x00,0x70,0xff,0xea,0x02,0xf4,0x04,0x16,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x32,0x40,0x1a,0x0c,0xaf,0x12,0x12,0x1e,0x25,0x00,0xaf,0x06,0x06,0x18,0xaf,0x1e,0x15,0xb0,0x0f,0x0f,0x03, 0x21,0xb0,0x1b,0x16,0x03,0xb0,0x09,0x10,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x01,0x50,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x01,0xa4,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f,0x42,0xfe,0x5c,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x03,0xa8,0x2f,0x41,0x42,0x2e,0x2e,0x40,0x3f,0xfe,0x28,0x2f,0x41,0x42,0x2e,0x2e,0x40,0x3f,0xfe,0x2c,0x2f,0x41,0x42,0x2e,0x2e,0x43,0x42,0x00,0x00,0x02,0x00,0x32, 0x02,0x58,0x02,0x76,0x06,0x02,0x00,0x20,0x00,0x2e,0x00,0x67,0x40,0x3f,0xd7,0x2a,0x01,0x0a,0x1c,0x01,0xea,0x1c,0xfa,0x1c,0x02,0x0a,0x06,0x01,0xeb,0x06,0xfb,0x06,0x02,0x0b,0x05,0x01,0x05,0x02,0x01,0xe5,0x02,0xf5,0x02,0x02,0x10,0x11,0x11,0x00,0x00,0x21,0x10,0x21,0x02,0x21,0x1b,0x29,0x29,0x09,0x1b,0x1b,0x1d,0x25,0x2b,0x04, 0x00,0x25,0x01,0x25,0x16,0x0b,0x11,0x13,0x10,0x0e,0x0e,0x0b,0x01,0x00,0x3f,0x33,0x2f,0x33,0xcd,0x32,0x10,0xdd,0xdc,0x5d,0xdc,0xcd,0x10,0xcd,0x32,0x01,0x2f,0xcd,0x33,0x2f,0x10,0xdc,0x5d,0xcd,0x32,0x2f,0x33,0x31,0x30,0x5d,0x71,0x71,0x5d,0x71,0x5d,0x71,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x11,0x34,0x33,0x32, 0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x23,0x22,0x07,0x06,0x15,0x15,0x36,0x33,0x32,0x17,0x16,0x07,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x36,0x02,0x76,0x4a,0x4f,0x8d,0x89,0x4d,0x48,0xcf,0x26,0x8d,0x20,0x31,0x45,0x2c,0x4f,0x51,0x29,0x93,0x1b,0x35,0x13,0x0d,0x52,0x63,0x8d,0x48,0x42,0x78,0x1d, 0x24,0x65,0x64,0x29,0x21,0xae,0x63,0x26,0x1d,0x03,0x90,0x8a,0x54,0x5a,0x56,0x52,0x87,0x01,0xb0,0xcb,0x2a,0x2a,0x58,0x39,0x2a,0x1f,0x17,0x39,0xbc,0x48,0x55,0x4d,0x89,0x65,0x2a,0x35,0x38,0x2d,0x62,0xcb,0x3b,0x2e,0x00,0x01,0x00,0x28,0xff,0x40,0x04,0x25,0x04,0x18,0x00,0x32,0x00,0x8c,0x40,0x4f,0x96,0x23,0x01,0x1b,0x1c,0x1c, 0x19,0x84,0x1e,0x03,0x00,0x84,0x04,0x07,0x07,0x1e,0x1e,0x28,0x34,0x2c,0x2b,0x2b,0x2a,0x2e,0x0c,0x0d,0x0e,0x2d,0x2d,0x0e,0x0e,0x84,0x28,0x2a,0x14,0x28,0x2a,0xa8,0x2a,0xb8,0x2a,0x02,0x19,0x2a,0x29,0x2a,0x02,0x0a,0x2a,0x01,0x2a,0x1f,0x28,0x01,0x28,0x0c,0x03,0x09,0x95,0x2e,0x31,0x10,0x2a,0x95,0x2d,0x0f,0x16,0x95,0x20,0x25, 0x1c,0x1b,0x1b,0x0e,0x11,0x95,0x28,0x25,0x16,0x00,0x3f,0x33,0xed,0x32,0x33,0x2f,0x33,0x10,0xdc,0xed,0x3f,0xed,0x3f,0x33,0xfd,0xcc,0x33,0x01,0x2f,0x5d,0x33,0x5d,0x5d,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x2f,0x33,0xed,0x32,0x10,0xed,0x33,0x2f, 0x39,0x31,0x30,0x5d,0x01,0x14,0x07,0x07,0x23,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x27,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x04,0x25,0x08,0x0d,0xa8,0x13,0x03,0x33,0x0d, 0x13,0xfe,0x54,0x7c,0x02,0x33,0x0d,0x13,0x01,0x2b,0x4a,0x30,0x40,0x50,0x72,0x7d,0x52,0x33,0x0d,0x13,0xfe,0xd4,0x4e,0x26,0x9f,0x08,0x8d,0xc7,0x1d,0x01,0x6e,0x18,0x01,0x77,0x4a,0x2a,0x9f,0x03,0x64,0x24,0x28,0x41,0x64,0x10,0x0d,0x35,0x05,0x73,0xfd,0xb6,0x09,0x1b,0x35,0x05,0x4d,0x13,0x53,0x41,0x6a,0x99,0x5b,0x57,0x2f,0x31, 0x05,0x51,0x15,0xb4,0x27,0x25,0x02,0x8e,0x8b,0x68,0x6b,0x15,0x00,0x01,0x00,0x28,0xfe,0x1f,0x04,0x4e,0x04,0x00,0x00,0x30,0x00,0x95,0x40,0x54,0x9b,0x17,0x01,0x89,0x17,0x01,0x78,0x17,0x01,0x2f,0x30,0x02,0x00,0x00,0x84,0x30,0x1c,0x14,0x30,0x30,0x1c,0x30,0x1c,0x06,0x84,0x19,0x19,0x1c,0x1c,0x22,0x32,0x27,0x29,0x29,0x84,0x22, 0x24,0x14,0x22,0x22,0x24,0x26,0x25,0x25,0x24,0xa8,0x24,0xb8,0x24,0x02,0x24,0x22,0x10,0x12,0x84,0x0f,0x0d,0x0d,0x1f,0x22,0x01,0x22,0x00,0x30,0x24,0x95,0x27,0x0f,0x2f,0x29,0x2c,0x95,0x10,0x15,0x0f,0x22,0x1c,0x02,0x1f,0x16,0x15,0x95,0x0a,0x1c,0x00,0x3f,0xed,0x3f,0x33,0x33,0x33,0xce,0x11,0x39,0xed,0x32,0x32,0x3f,0xed,0xd4, 0xc4,0x01,0x2f,0x5d,0x33,0x2f,0x33,0xed,0x32,0x11,0x33,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x2f,0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0xc4,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x01,0x03,0x06,0x15,0x14,0x16,0x15,0x14,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x17, 0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x26,0x35,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x23,0x37,0x21,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x04,0x4e,0xb8,0x02,0x9c,0xb3,0x84,0xbc,0x93,0xd5,0x47,0x90,0x30,0x84,0x5a,0x65,0x56,0x75,0x9b,0xfe,0x7f,0x48,0x2c,0x9f,0x08,0x8c,0xc7,0x1d,0x01,0x6e,0xae,0x03, 0x33,0x0d,0x13,0x01,0xad,0xa6,0x04,0x00,0xfc,0x95,0x0a,0x0c,0x32,0xba,0x43,0xa7,0x50,0x3a,0x85,0x5f,0x52,0x4e,0x37,0x33,0x27,0x2c,0x3d,0x21,0x2d,0x55,0x2d,0xa9,0x4a,0x70,0x15,0xb4,0x27,0x25,0x02,0x8e,0x8b,0xfc,0xc4,0x0e,0x0f,0x35,0x05,0x73,0x03,0x16,0x00,0x01,0x00,0x28,0xfe,0x1f,0x04,0x30,0x04,0x18,0x00,0x33,0x00,0xbd, 0x40,0x74,0x78,0x15,0x01,0x9a,0x11,0x01,0x89,0x11,0x01,0x30,0x2d,0x2d,0x84,0x1a,0x17,0x14,0x1a,0x1a,0x17,0xd9,0x1a,0x01,0x78,0x1a,0x01,0x1a,0x17,0x00,0x84,0x13,0x13,0x50,0x17,0x60,0x17,0x02,0x17,0x17,0x22,0x35,0x25,0x24,0x24,0x23,0x20,0x27,0x26,0x21,0x26,0x21,0x21,0x84,0x22,0x23,0x14,0x22,0x22,0x23,0xf7,0x23,0x01,0x88, 0x23,0xa8,0x23,0xc8,0x23,0x03,0x79,0x23,0x01,0x47,0x23,0x57,0x23,0x02,0x23,0x22,0x0a,0x0c,0x84,0x09,0x07,0x07,0x1f,0x22,0x01,0x22,0x40,0x0c,0x10,0x48,0x22,0x20,0x1a,0x1d,0x95,0x2d,0x27,0x2a,0x10,0x23,0x95,0x26,0x0f,0x0a,0x09,0x30,0x21,0x17,0x22,0x15,0x0f,0x95,0x04,0x1c,0x00,0x3f,0xed,0x3f,0x33,0xc4,0x33,0xce,0x32,0x3f, 0xed,0x3f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x2b,0x5d,0x33,0x2f,0x33,0xed,0x32,0x11,0x33,0x5d,0x5d,0x5d,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x5d,0x33,0x2f,0xed,0x11,0x33,0x5d,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x05,0x14,0x07, 0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x16,0x04,0x30,0xb3,0x84,0xbc,0x93,0xd5,0x47,0x90,0x30,0x84,0x5a,0x65,0x56,0x75, 0x9b,0x09,0x83,0x03,0x33,0x0d,0x13,0xfe,0x57,0xa6,0xab,0xbe,0xc7,0x1d,0x01,0x6e,0x16,0x01,0x75,0x4a,0x2a,0x9f,0x08,0x87,0x02,0x9c,0xb0,0xa7,0x50,0x3a,0x85,0x5f,0x52,0x4e,0x37,0x33,0x27,0x2c,0x3d,0x21,0x2d,0x55,0x2c,0xa9,0x4b,0x1d,0x2c,0x02,0x86,0x0f,0x0e,0x35,0x05,0x72,0xfc,0xea,0x03,0x75,0x8b,0x67,0x6a,0x15,0xb4,0x26, 0x26,0xfd,0x7d,0x0a,0x0c,0x32,0xba,0x00,0x00,0x02,0x00,0x30,0xff,0xe7,0x04,0xa7,0x06,0x04,0x00,0x39,0x00,0x48,0x00,0xe4,0x40,0x9a,0x84,0x44,0x01,0x75,0x44,0x01,0x66,0x40,0x01,0x45,0x40,0x55,0x40,0x02,0x85,0x3f,0x01,0x8b,0x3d,0x01,0x7c,0x3d,0x01,0x48,0x3d,0x68,0x3d,0x02,0x79,0x3c,0x89,0x3c,0x02,0x48,0x36,0x58,0x36,0x68, 0x36,0x03,0x79,0x1e,0x89,0x1e,0x02,0x99,0x1d,0x01,0x99,0x1a,0x01,0x76,0x17,0x86,0x17,0x02,0x27,0x17,0x01,0x94,0x11,0x01,0x85,0x11,0x01,0x11,0x15,0x0c,0x0f,0x84,0x22,0x97,0x25,0x01,0x25,0x22,0x15,0x83,0x3a,0x03,0x00,0x84,0x04,0x07,0x07,0x89,0x3e,0x01,0x58,0x3e,0x78,0x3e,0x02,0x20,0x3e,0x3a,0x4f,0x22,0x5f,0x22,0x6f,0x22, 0x03,0x22,0x3a,0x22,0x3a,0x1c,0x4a,0x2e,0x31,0x84,0x2d,0x00,0x2a,0x10,0x2a,0x02,0x2a,0x2a,0x42,0x83,0x0f,0x1c,0x1f,0x1c,0x5f,0x1c,0x6f,0x1c,0x04,0x1c,0x25,0x0c,0x28,0x04,0x09,0x95,0x38,0x01,0x3e,0x95,0x20,0x20,0x45,0x28,0x95,0x33,0x2d,0x00,0x45,0x95,0x19,0x16,0x00,0x3f,0xed,0x3f,0xdc,0xed,0x11,0x39,0x2f,0xed,0x3f,0xfd, 0xce,0x12,0x39,0x39,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x5d,0x33,0xed,0x32,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x12,0x39,0x39,0x5d,0x5d,0x32,0x2f,0x33,0xed,0x32,0x10,0xed,0x11,0x33,0x5d,0x10,0xed,0x32,0x11,0x39,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x07, 0x23,0x37,0x36,0x35,0x34,0x23,0x22,0x0f,0x02,0x06,0x15,0x14,0x17,0x16,0x17,0x16,0x15,0x10,0x07,0x06,0x21,0x22,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x37,0x37,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x37,0x33,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x33,0x32,0x01,0x34,0x27,0x26,0x27,0x06,0x07,0x06,0x15,0x14,0x16, 0x33,0x32,0x37,0x36,0x04,0xa7,0x08,0x0d,0xa8,0x13,0x03,0x33,0x10,0x10,0xaa,0x28,0x02,0x53,0x7c,0x1d,0x53,0x9e,0xa6,0xfe,0xf7,0xbd,0xde,0x90,0x93,0xfd,0x1d,0x09,0x15,0x9b,0x44,0x30,0x9f,0x08,0x0d,0xa8,0x13,0x03,0x33,0x10,0x10,0x01,0xf7,0x44,0x30,0x9f,0xfe,0xc9,0x36,0x20,0x53,0xfe,0x84,0x6d,0x89,0x74,0xb9,0x77,0x6b,0x05, 0x50,0x24,0x28,0x41,0x64,0x10,0x0d,0x35,0x05,0x35,0xc3,0x0a,0x0c,0x3c,0x42,0x63,0x25,0x66,0x95,0xfe,0xf7,0xb5,0xc0,0xc9,0xad,0xf8,0xb0,0xb4,0x2e,0x2f,0x38,0x19,0x30,0x71,0x30,0x15,0xb4,0x24,0x28,0x41,0x64,0x10,0x0d,0x35,0x05,0x9c,0x15,0xfc,0x5c,0x5e,0x48,0x2b,0x41,0x1b,0xa8,0x8b,0xbf,0x6d,0x85,0xa3,0x91,0x00,0x00,0x01, 0x00,0x28,0xfe,0x25,0x04,0x25,0x04,0x18,0x00,0x21,0x00,0x90,0x40,0x57,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0xb8,0x10,0xc8,0x10,0x02,0x10,0x0d,0x08,0x84,0x09,0x09,0x0d,0x0d,0x18,0x23,0x1b,0x1a,0x1a,0x19,0x16,0x1d,0x1c,0x17,0x1c,0x17,0x17,0x84,0x18,0x19,0x14,0x18,0x19,0xf7,0x19,0x01,0x88,0x19,0xa8,0x19,0xc8, 0x19,0x03,0x79,0x19,0x01,0x57,0x19,0x01,0x19,0x1f,0x18,0x01,0x18,0x40,0x0c,0x10,0x48,0x18,0x16,0x10,0x13,0x95,0x1d,0x01,0x20,0x10,0x19,0x95,0x1c,0x0f,0x17,0x0d,0x04,0x18,0x15,0x09,0x1b,0x00,0x3f,0x3f,0x33,0x33,0xc4,0x3f,0xed,0x3f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x2b,0x5d,0x33,0x5d,0x5d,0x5d,0x5d,0x87,0x2b,0x7d,0x10, 0xc4,0x87,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x2f,0xed,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x04,0x25, 0x08,0x87,0x13,0x01,0x14,0xa4,0x14,0x01,0x14,0x88,0x03,0x33,0x0d,0x13,0xfe,0x57,0xa6,0xab,0xbe,0xc7,0x1d,0x01,0x6e,0x16,0x01,0x75,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfd,0x7e,0x5a,0x45,0x37,0x14,0xfe,0x79,0x01,0x87,0x14,0x34,0x40,0x63,0x02,0xa4,0x0f,0x0e,0x35,0x05,0x72,0xfc,0xea,0x03,0x75,0x8b,0x67,0x6a,0x15,0x00,0x01, 0x00,0x28,0xfe,0x25,0x06,0xc0,0x04,0x18,0x00,0x30,0x00,0xb5,0x40,0x69,0x25,0x24,0x24,0x23,0x20,0x27,0x26,0x21,0x26,0x21,0x21,0x84,0x22,0x23,0x14,0x22,0x23,0xc8,0x23,0x01,0x86,0x23,0x01,0x57,0x23,0x77,0x23,0x02,0x23,0x5f,0x22,0x8f,0x22,0xbf,0x22,0x03,0x22,0x17,0x2c,0x0e,0x0c,0x0c,0x84,0x1a,0x17,0x14,0x1a,0x1a,0x17,0xa8, 0x1a,0xc8,0x1a,0x02,0x1a,0x17,0x12,0x84,0x13,0x13,0x17,0x03,0x01,0x01,0x84,0x06,0x04,0x14,0x06,0x06,0x04,0xb8,0x06,0x01,0x06,0x04,0x17,0x0c,0x06,0x09,0x95,0x2c,0x01,0x2f,0x2f,0x20,0x1a,0x1d,0x95,0x27,0x2a,0x10,0x23,0x95,0x26,0x0f,0x03,0x04,0x21,0x17,0x0e,0x22,0x15,0x13,0x1b,0x00,0x3f,0x3f,0x33,0x33,0xc4,0xd4,0xc4,0x3f, 0xed,0x3f,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcc,0x32,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x01,0x33,0x18,0x2f,0xed,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x33,0x18,0x10,0xdc,0x5d,0x32,0x5d,0x5d,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x31, 0x30,0x01,0x14,0x07,0x03,0x23,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x17,0x25,0x36,0x33,0x32,0x06,0xc0,0x08,0xa5,0xa3,0xa6,0x03,0x33,0x0d,0x13,0xfe,0x56,0x86,0x13, 0x01,0x14,0xa4,0x14,0x01,0x14,0x88,0x03,0x33,0x0d,0x13,0xfe,0x57,0xa6,0xab,0xbe,0xc7,0x1d,0x01,0x6e,0x16,0x01,0x75,0x4a,0x2a,0x84,0x17,0x01,0x8c,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfc,0xe8,0x03,0x3b,0x0f,0x0e,0x35,0x05,0x73,0xfd,0x81,0x5a,0x45,0x37,0x14,0xfe,0x79,0x01,0x87,0x14,0x34,0x40,0x63,0x02,0xa4,0x0f,0x0e,0x35, 0x05,0x72,0xfc,0xea,0x03,0x75,0x8b,0x67,0x6a,0x15,0x86,0x71,0x15,0x00,0x00,0x02,0xff,0x3f,0xff,0xe7,0x04,0x25,0x06,0x04,0x00,0x2d,0x00,0x3f,0x00,0xa4,0x40,0x5e,0x87,0x04,0x01,0x76,0x04,0x01,0x64,0x04,0x01,0x53,0x04,0x01,0x03,0x01,0x01,0x84,0x3f,0x3d,0x14,0x3f,0x3f,0x3d,0x08,0x3f,0x18,0x3f,0x02,0x3f,0x3d,0x3d,0x0b,0x41, 0x1b,0x1d,0x84,0x18,0x34,0x33,0x29,0x28,0x27,0x35,0x27,0x35,0x35,0x84,0x0b,0x0e,0x14,0x0b,0x0b,0x0e,0x1a,0x18,0x18,0x0e,0x39,0x0e,0x01,0x2a,0x0e,0x01,0x0e,0x1f,0x0b,0x01,0x0b,0x3f,0x33,0x30,0x95,0x29,0x01,0x2c,0x10,0x0e,0x11,0x95,0x27,0x24,0x01,0x16,0x95,0x1f,0x1b,0x00,0x3d,0x35,0x38,0x95,0x0b,0x03,0x08,0x16,0x00,0x3f, 0x33,0x33,0xed,0x32,0x32,0x3f,0xde,0xed,0x3f,0x33,0xed,0x32,0x3f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x5d,0x33,0x5d,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x01,0x18,0x10,0xed,0x32,0x11,0x12,0x39,0x2f,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x5d,0x5d, 0x5d,0x5d,0x01,0x14,0x07,0x03,0x06,0x07,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x25,0x36,0x33,0x32,0x07,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37, 0x13,0x36,0x04,0x25,0x08,0x6c,0x1f,0xae,0xfe,0x8a,0x53,0x21,0x9f,0x08,0xec,0x03,0x2c,0x0e,0x12,0xbe,0x4d,0x2c,0x90,0x08,0xa3,0x04,0x29,0x0d,0x13,0xbd,0x51,0x23,0x96,0x08,0x51,0x01,0x75,0x4a,0x2a,0x9f,0xa7,0x33,0x0d,0x13,0xfe,0x57,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x6e,0x03,0x03,0x64,0x26,0x26,0xfe,0x03,0x94, 0x2c,0x5f,0x15,0xb4,0x27,0x25,0x04,0x4a,0x10,0x0d,0x2b,0x05,0x34,0x15,0x96,0x21,0x22,0x15,0x0e,0x28,0x05,0x31,0x15,0xaa,0x27,0x25,0xfe,0x8b,0x6a,0x15,0xc0,0x35,0x05,0x72,0xfd,0xae,0x0e,0x0f,0x35,0x05,0x63,0x0e,0x33,0x02,0x20,0x0f,0x00,0x02,0x00,0x5b,0xff,0xa7,0x06,0xc3,0x04,0x58,0x00,0x3a,0x00,0x4c,0x00,0xf0,0x40,0x85, 0x88,0x2c,0x98,0x2c,0x02,0x87,0x1c,0x01,0x76,0x1b,0x86,0x1b,0x96,0x1b,0x03,0x97,0x07,0x01,0x1d,0x1c,0x1c,0x18,0x16,0x36,0x01,0x07,0x36,0x01,0x36,0x16,0x49,0x4a,0x4b,0x4c,0x18,0x16,0x16,0x84,0x4c,0x20,0x14,0x4c,0x4c,0x20,0x4c,0x20,0x40,0x41,0x42,0x31,0x31,0x42,0x42,0x84,0x26,0x29,0x14,0x26,0x26,0x29,0x2e,0x2d,0x2d,0x29, 0x29,0x5f,0x26,0x01,0x26,0x20,0x09,0x08,0x08,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0x10,0x50,0x0d,0x01,0x0d,0x20,0x4c,0x40,0x29,0x3d,0x95,0x34,0x16,0x10,0x13,0x95,0x36,0x01,0x39,0x39,0x34,0x2d,0x2e,0x2e,0x31,0x34,0x10,0x49,0x42,0x45,0x95,0x23,0x0d,0x08,0x04,0x09,0x09,0x96,0x1c,0x01,0x1c,0x1d,0x1d,0x23,0x26, 0x26,0x20,0x18,0x23,0x16,0x00,0x3f,0x33,0x33,0x33,0x2f,0x11,0x33,0x2f,0x33,0x5d,0x33,0x2f,0x33,0x33,0x33,0x10,0xed,0x32,0x32,0x3f,0x33,0x33,0x2f,0x33,0x11,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x10,0xed,0x32,0x32,0x32,0x01,0x2f,0xcc,0x5d,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x10,0xcc,0x5d,0x32,0x11, 0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0x11,0x01,0x33,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0xc4,0x05,0xc4,0x11,0x01,0x33,0x5d,0x5d,0x11,0x33,0x18,0x2f,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x35,0x34,0x37,0x13,0x36,0x35, 0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x17,0x25,0x36,0x33,0x32,0x05,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x13,0x36,0x06,0xc3,0x08,0x81,0x04, 0x15,0x63,0x53,0x90,0x3f,0x07,0x86,0x03,0x33,0x0d,0x13,0xfe,0x53,0x80,0x04,0x15,0x63,0x53,0x90,0x34,0x09,0xfe,0x7e,0x53,0x21,0x9f,0x08,0x83,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0x01,0x7e,0x4b,0x29,0x84,0x17,0x01,0x8f,0x4b,0x29,0x9f,0xfc,0xbb,0x33,0x0d,0x13,0xfe,0x57,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x6e,0x03, 0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1b,0x22,0x02,0x86,0x0e,0x0f,0x35,0x05,0x73,0xfd,0x9f,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x22,0x39,0x62,0x15,0xb4,0x27,0x25,0x02,0x64,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0x85,0x70,0x15,0xc0,0x35,0x05,0x72,0xfd,0xae,0x0e,0x0f, 0x35,0x05,0x63,0x0e,0x33,0x02,0x20,0x0f,0x00,0x01,0x00,0x28,0x00,0x00,0x03,0xa4,0x04,0x00,0x00,0x1f,0x00,0x52,0x40,0x2f,0x03,0x01,0x01,0x84,0x06,0x04,0x14,0x06,0x06,0x04,0xd8,0x06,0x01,0x06,0x00,0x04,0x01,0x04,0x04,0x21,0x15,0x17,0x84,0x14,0x13,0x12,0x10,0x0e,0x95,0x0f,0x19,0x1f,0x19,0x02,0x19,0x06,0x09,0x95,0x01,0x1e, 0x12,0x95,0x15,0x0f,0x03,0x04,0x15,0x00,0x3f,0xc4,0x3f,0xed,0xde,0x32,0xed,0x32,0xdc,0x5d,0xed,0x01,0x2f,0x33,0xce,0x32,0xed,0x32,0x12,0x39,0x2f,0x5d,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x14,0x07,0x03,0x23,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x23,0x37,0x21,0x06,0x15, 0x14,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x03,0xa4,0x08,0x8a,0xa3,0x8e,0x03,0x2c,0x0e,0x12,0xbe,0x4d,0x2c,0x90,0x02,0xc7,0x1d,0x01,0x6e,0x1f,0x29,0x0d,0x13,0xbd,0x51,0x23,0x96,0x02,0xec,0x25,0x27,0xfd,0x60,0x02,0xc3,0x0f,0x0e,0x2b,0x05,0x34,0x15,0x96,0x12,0x10,0x8b,0x78,0x15,0x28,0x05,0x31,0x15,0x00,0x00,0x02,0x00,0x59, 0xfe,0x25,0x04,0x25,0x05,0xec,0x00,0x27,0x00,0x37,0x00,0x95,0x40,0x4e,0x36,0x35,0x0f,0x0e,0x0d,0x04,0x01,0x01,0x84,0x37,0x0d,0x14,0x37,0x37,0x0d,0x37,0x0d,0x08,0x84,0x09,0x09,0x0d,0x0d,0x15,0x39,0x2e,0x2d,0x23,0x22,0x21,0x2f,0x21,0x2f,0x2f,0x84,0x15,0x18,0x14,0x15,0x15,0x18,0x1d,0x84,0x1c,0x1c,0x18,0x87,0x18,0x01,0x18, 0x1f,0x15,0x01,0x15,0x37,0x2d,0x2a,0x95,0x23,0x21,0x18,0x01,0x26,0x10,0x1c,0x00,0x35,0x2f,0x32,0x95,0x15,0x0f,0x0d,0x04,0x12,0x16,0x09,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x5d,0x33,0x5d,0x11,0x33,0x2f,0xed,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e, 0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x2f,0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x31,0x30,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13, 0x16,0x15,0x14,0x07,0x07,0x25,0x36,0x33,0x32,0x07,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x36,0x04,0x25,0x09,0x99,0x13,0x01,0x0c,0xa4,0x0c,0x01,0x14,0x03,0xfe,0x89,0x4a,0x2a,0x9f,0x09,0x99,0x13,0x01,0x14,0xa4,0x14,0x01,0x14,0x03,0x01,0x77,0x4a,0x2a,0x9f,0xa7,0x33,0x0d,0x13,0xfe,0x54,0x7c, 0x03,0x33,0x0d,0x13,0x01,0xac,0x7c,0x03,0x03,0x64,0x22,0x2a,0xfd,0x3b,0x58,0x59,0x09,0x1d,0xfe,0xa9,0x01,0x50,0x16,0x0e,0x35,0x85,0x14,0x6b,0x15,0xb4,0x22,0x2a,0x02,0xc5,0x58,0x59,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x35,0x85,0x14,0x6b,0x15,0xc0,0x35,0x05,0x73,0xfd,0xaf,0x0e,0x0f,0x35,0x05,0x73,0x02,0x51,0x0e,0x00, 0x00,0x02,0x00,0x31,0xff,0xa7,0x06,0xbe,0x04,0x58,0x00,0x30,0x00,0x42,0x00,0xd9,0x40,0x7c,0x79,0x22,0x01,0x87,0x07,0x01,0x76,0x07,0x01,0x24,0x23,0x23,0x1f,0x27,0x1b,0x1c,0x1c,0x84,0x1d,0x1f,0x14,0x1d,0x1f,0x7a,0x1f,0x8a,0x1f,0x9a,0x1f,0x03,0x1f,0x1d,0x12,0x07,0x2c,0x17,0x2c,0x02,0x2c,0x36,0x38,0x38,0x84,0x12,0x15,0x14, 0x12,0x12,0x15,0x15,0x12,0x09,0x08,0x08,0x04,0x41,0x40,0x3f,0x0c,0x42,0x0c,0x97,0x04,0x01,0x04,0x01,0x01,0x84,0x42,0x0c,0x14,0x42,0x42,0x0c,0x42,0x0c,0x12,0x42,0x36,0x33,0x95,0x2c,0x01,0x2f,0x2f,0x2a,0x9a,0x23,0x01,0x8b,0x23,0x01,0x23,0x24,0x24,0x1b,0x15,0x18,0x95,0x27,0x1f,0x2a,0x10,0x1c,0x1d,0x15,0x3f,0x38,0x3b,0x95, 0x0f,0x85,0x08,0x95,0x08,0x02,0x08,0x09,0x09,0x12,0x0c,0x04,0x0f,0x16,0x00,0x3f,0x33,0x33,0x33,0x33,0x2f,0x33,0x5d,0x10,0xed,0x32,0x32,0x3f,0xc4,0x3f,0x33,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0x5d,0x5d,0x11,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcc,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x5d,0x10,0x87,0xc4,0x0e, 0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x5d,0x18,0x10,0xdc,0x32,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x11,0x33,0x18,0x2f,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35, 0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x17,0x25,0x36,0x33,0x32,0x07,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x13,0x36,0x06,0xbe,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x34,0x09,0xfe,0x7e,0x53,0x21,0x9f,0x08,0x80,0x02,0x33, 0x0d,0x13,0xfe,0x57,0xa6,0xab,0xb5,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0x01,0x7e,0x4b,0x29,0x83,0x18,0x01,0x8a,0x4b,0x29,0x9f,0xa7,0x33,0x0d,0x13,0xfe,0x57,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x6e,0x03,0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x21,0x3a,0x62,0x15,0xb4,0x27,0x25,0x02,0x54, 0x09,0x14,0x35,0x05,0x72,0xfc,0xea,0x03,0x4b,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0x83,0x6e,0x15,0xc0,0x35,0x05,0x72,0xfd,0xae,0x0e,0x0f,0x35,0x05,0x63,0x0e,0x33,0x02,0x20,0x0f,0x00,0x00,0x02,0x00,0x30,0xff,0xe7,0x05,0x4c,0x06,0x04,0x00,0x30,0x00,0x3d,0x00,0xcc,0x40,0x7d,0x56,0x3c,0x01,0x95,0x38,0x01, 0x87,0x38,0x01,0x89,0x35,0x01,0x95,0x0e,0x01,0x46,0x0e,0x56,0x0e,0x02,0x8a,0x07,0x01,0x21,0x23,0x84,0x20,0x1e,0x1e,0x14,0x00,0x01,0x01,0x2d,0x31,0x12,0x13,0x14,0x3d,0x14,0x2e,0x2f,0x05,0x06,0x2d,0x06,0x2d,0x2d,0x84,0x14,0x3d,0x14,0x14,0x14,0x3d,0x14,0x3d,0x3d,0x3f,0x37,0x83,0x0c,0x1c,0x95,0x0f,0x25,0x1f,0x25,0x02,0x25, 0x14,0x17,0x95,0x2d,0x2a,0x01,0x20,0x00,0x05,0x31,0x33,0x54,0x00,0x64,0x00,0x02,0x45,0x00,0x01,0x16,0x00,0x26,0x00,0x36,0x00,0x03,0x07,0x00,0x01,0x66,0x2f,0x01,0x12,0x2f,0x00,0x03,0x10,0x01,0x01,0x33,0x95,0x20,0x10,0x01,0x10,0x10,0x47,0x3d,0x01,0x3d,0x39,0x95,0x06,0x0a,0x16,0x00,0x3f,0x33,0xed,0x32,0x5d,0x3f,0x5d,0xed, 0x32,0x2f,0x12,0x17,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x12,0x39,0x39,0x3f,0x3f,0x33,0xed,0x32,0xdc,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x0e,0xc4,0x10,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x00,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x01,0x07,0x26,0x27,0x26,0x27,0x03,0x06,0x07,0x06,0x23,0x20,0x11,0x10,0x37,0x36,0x21,0x32,0x17,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x16,0x05,0x26,0x23,0x20,0x07,0x06,0x15,0x14,0x33,0x32,0x37, 0x36,0x37,0x05,0x4c,0x25,0x1c,0x20,0x4d,0x51,0x7e,0x21,0xc3,0x98,0xa8,0xfe,0x85,0xee,0xf7,0x01,0x75,0x27,0x1b,0x3c,0x03,0x2c,0x0e,0x12,0xbe,0x4d,0x2c,0x90,0x08,0xa3,0x04,0x29,0x0d,0x13,0xbd,0x51,0x23,0x96,0x08,0x3b,0x83,0xfe,0xc0,0x1f,0x1a,0xfe,0xe3,0xc8,0xbb,0xee,0x59,0x73,0x8d,0x10,0x03,0x9b,0xa2,0x15,0x12,0x2d,0x1b, 0xfd,0xb3,0x9c,0x55,0x43,0x01,0x7a,0x01,0x1f,0xc9,0xd0,0x02,0x01,0x1a,0x0e,0x0f,0x2b,0x05,0x34,0x15,0x96,0x21,0x22,0x15,0x0e,0x28,0x05,0x31,0x15,0xaa,0x27,0x25,0xfe,0xee,0x23,0x4f,0x03,0xaf,0xa4,0xcc,0xfb,0x2d,0x36,0x4c,0x00,0x01,0x00,0x31,0x00,0x00,0x04,0x8d,0x06,0x04,0x00,0x33,0x00,0x9e,0x40,0x59,0x03,0x00,0x84,0x06, 0x18,0x15,0x15,0x84,0x24,0x21,0x14,0x24,0x24,0x21,0x04,0x06,0x06,0x24,0x24,0x21,0x1c,0x84,0x1d,0x1d,0x00,0x21,0x01,0x21,0x21,0x2c,0x35,0x2a,0x0f,0x0e,0x2b,0x0e,0x2b,0x2b,0x84,0x2c,0x2d,0x14,0x2c,0x2d,0x08,0x2d,0x01,0x2d,0x2c,0x2f,0x03,0x01,0x03,0x03,0x12,0x19,0x0e,0x01,0x0e,0x09,0x95,0x77,0x2d,0x01,0x26,0x2d,0x01,0x19, 0x2d,0x01,0x2d,0x32,0x01,0x21,0x27,0x18,0x12,0x1d,0x2b,0x2c,0x15,0x2a,0x24,0x27,0x95,0x15,0x0f,0x12,0x10,0x00,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0xc4,0xc4,0x11,0x39,0x11,0x39,0x3f,0x33,0x5d,0x5d,0x5d,0xed,0x32,0x5d,0x11,0x39,0x2f,0x5d,0x01,0x2f,0x33,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x11,0x12,0x01,0x39,0x18, 0x2f,0x5d,0x33,0x2f,0xed,0x11,0x33,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xed,0x32,0x31,0x30,0x01,0x14,0x07,0x07,0x23,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x06,0x07,0x03,0x25,0x36,0x33,0x32,0x15,0x14,0x07,0x07,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x36,0x35,0x34,0x23, 0x22,0x07,0x05,0x03,0x23,0x01,0x36,0x37,0x25,0x36,0x33,0x32,0x04,0x8d,0x08,0x0e,0xa8,0x14,0x03,0x33,0x0d,0x13,0xfe,0x89,0x37,0x0a,0x3e,0x01,0x75,0x4a,0x2a,0x9f,0x08,0x27,0x13,0x03,0x12,0xa4,0x12,0x03,0x14,0x28,0x03,0x33,0x0d,0x13,0xfe,0x57,0xa6,0xab,0x01,0x06,0x1f,0xae,0x01,0x76,0x53,0x21,0x9f,0x05,0x50,0x27,0x25,0x41, 0x64,0x0f,0x0e,0x35,0x05,0x63,0x0f,0x32,0xfe,0xc9,0x6a,0x15,0xb4,0x2a,0x22,0xa7,0x51,0x44,0x30,0x3d,0xfe,0x91,0x01,0x6f,0x3d,0x2d,0x34,0x65,0xc9,0x0f,0x0e,0x35,0x05,0x72,0xfc,0xea,0x04,0xd0,0x94,0x2c,0x5f,0x15,0x00,0x01,0x00,0x5b,0xff,0xa7,0x06,0xea,0x04,0x58,0x00,0x35,0x00,0xba,0x40,0x67,0x96,0x05,0x01,0x07,0x87,0x06, 0x01,0x06,0x06,0x96,0x02,0x01,0x87,0x02,0x01,0x02,0x00,0x00,0x84,0x35,0x34,0x14,0x35,0x35,0x34,0x35,0x0a,0x50,0x34,0x01,0x34,0x2a,0x2c,0x2e,0x2e,0x84,0x2a,0x2b,0x14,0x2a,0x2a,0x2b,0x2b,0x2a,0x21,0x24,0x24,0x84,0x15,0x18,0x14,0x15,0x15,0x18,0x1d,0x1c,0x1c,0x18,0x99,0x18,0x01,0x08,0x18,0x01,0x18,0x5f,0x15,0x01,0x15,0x0f, 0x2a,0x00,0x35,0x2b,0x1c,0x1d,0x1d,0x2c,0x21,0x18,0x2b,0x0f,0x34,0x2e,0x31,0x95,0x0d,0x2a,0x24,0x27,0x95,0x15,0x0f,0x12,0x12,0x0d,0x06,0x07,0x07,0x0a,0x02,0x0d,0x16,0x00,0x3f,0x33,0x33,0x33,0x2f,0x33,0x11,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x10,0xed,0x32,0x32,0x3f,0x33,0x33,0xc4,0x33,0x2f,0x33,0x10,0xd4,0xc4,0x01,0x2f, 0x33,0xcc,0x5d,0x32,0x5d,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x01,0x33,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xcc,0x5d,0x32,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x5d,0x5d,0x32,0x18,0x2f,0x5d,0x33,0x31,0x30,0x5d,0x01,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23, 0x22,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x33,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x06,0xea,0xb2,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0xfe,0x82,0x4b,0x29,0x84,0x17,0xfe,0x71,0x4b,0x29,0x9f,0x08,0x81,0x04, 0x15,0x63,0x53,0x90,0x3f,0x07,0x86,0x03,0x33,0x0d,0x13,0x01,0xad,0xa6,0xa7,0xac,0x03,0x33,0x0d,0x13,0x01,0xa9,0xa5,0x04,0x00,0xfc,0xb4,0x18,0x04,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0x85,0x70,0x15,0xb4,0x26,0x26,0x02,0x64,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1b,0x22,0xfd,0x7a,0x0e,0x0f,0x35,0x05,0x73, 0x03,0x16,0xfc,0xc4,0x0e,0x0f,0x35,0x05,0x72,0x03,0x17,0x00,0x00,0x01,0x00,0x28,0xff,0xa7,0x05,0xa2,0x04,0x18,0x00,0x36,0x00,0x8e,0x40,0x4e,0x86,0x05,0x01,0x07,0x06,0x06,0x02,0x00,0x00,0x84,0x36,0x35,0x14,0x36,0x36,0x35,0x36,0x0a,0x35,0x35,0x10,0x38,0x20,0x22,0x84,0x1d,0xa7,0x2c,0x01,0x2c,0x2f,0x2f,0x84,0x10,0x13,0x14, 0x10,0x10,0x13,0x1f,0x1d,0x1d,0x13,0xd8,0x13,0x01,0x13,0x10,0x00,0x36,0x0f,0x1b,0x95,0x24,0x13,0x16,0x95,0x2c,0x29,0x10,0x1f,0x0f,0x35,0x2f,0x32,0x95,0x0d,0x94,0x06,0x01,0x06,0x07,0x07,0x10,0x0a,0x02,0x0d,0x16,0x00,0x3f,0x33,0x33,0x33,0x33,0x2f,0x33,0x5d,0x10,0xed,0x32,0x32,0x3f,0x3f,0x33,0xed,0x32,0xdc,0xed,0x3f,0xc4, 0x01,0x2f,0x33,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x5d,0x18,0x10,0xed,0x32,0x11,0x12,0x39,0x2f,0x33,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x31,0x30,0x5d,0x01,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22, 0x07,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x05,0xa2,0xb2,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0xfe,0x86,0x4a,0x30,0x9f,0x08,0x81,0x03,0x2c,0x0e,0x12,0xbe,0x4d,0x2c,0x90,0x08,0xa3,0x04,0x29,0x0d,0x13,0xbd,0x51, 0x23,0x96,0x08,0x81,0x03,0x33,0x13,0x13,0x01,0xa8,0xa5,0x04,0x00,0xfc,0xb4,0x18,0x04,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0xb4,0x26,0x26,0x02,0x5e,0x0e,0x0f,0x2b,0x05,0x34,0x15,0x96,0x21,0x22,0x15,0x0e,0x28,0x05,0x31,0x15,0xaa,0x26,0x26,0xfd,0xa2,0x0e,0x0f,0x35,0x05,0x72,0x03,0x17,0x00,0x01,0x00,0x28,0xfe,0x25, 0x05,0xa2,0x04,0x18,0x00,0x39,0x00,0x88,0x40,0x48,0x0c,0x0d,0x38,0x39,0x02,0x00,0x00,0x84,0x39,0x0b,0x14,0x39,0x39,0x0b,0x39,0x0b,0x06,0x84,0x07,0x07,0x0b,0x0b,0x13,0x3b,0x23,0x25,0x84,0x20,0x2f,0x32,0x32,0x84,0x13,0x16,0x14,0x13,0x13,0x16,0x22,0x20,0x20,0x16,0x16,0x13,0x00,0x39,0x0f,0x1e,0x95,0x27,0x16,0x19,0x95,0x2c, 0x2f,0x2c,0x22,0x22,0x2c,0x10,0x38,0x32,0x35,0x95,0x13,0x0d,0x0b,0x02,0x10,0x16,0x07,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x3f,0x33,0x2f,0x11,0x33,0x10,0xed,0x32,0xdc,0xed,0x3f,0xc4,0x01,0x2f,0x33,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xed,0x32,0x11,0x12,0x39,0x2f,0x33,0x2f, 0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0xc4,0xc4,0x0e,0xc4,0x31,0x30,0x01,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x15,0x14, 0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x05,0xa2,0xc3,0x11,0x01,0x0c,0xa4,0x0c,0x01,0x14,0x05,0xfe,0x85,0x4a,0x30,0x9f,0x08,0x81,0x03,0x2c,0x0e,0x12,0xbe,0x4d,0x2c,0x90,0x08,0xa3,0x04,0x29,0x0d,0x13,0xbd,0x51,0x23,0x96,0x08,0x81,0x03,0x33,0x13,0x13,0x01,0xa8,0xa5,0x04,0x00,0xfc,0x53,0x52,0x5f,0x09,0x1d,0xfe, 0xa9,0x01,0x4e,0x18,0x0e,0x61,0x59,0x14,0x6b,0x15,0xb4,0x26,0x26,0x02,0x5e,0x0e,0x0f,0x2b,0x05,0x34,0x15,0x96,0x21,0x22,0x15,0x0e,0x28,0x05,0x31,0x15,0xaa,0x26,0x26,0xfd,0xa2,0x0e,0x0f,0x35,0x05,0x72,0x03,0x17,0x00,0x01,0x00,0x59,0xff,0xa7,0x06,0xbc,0x05,0xec,0x00,0x3b,0x00,0xc6,0x40,0x6e,0x96,0x07,0x01,0x31,0x84,0x30, 0x30,0x19,0x2a,0x2b,0x2c,0x18,0x2c,0x16,0x37,0x36,0x35,0x17,0x35,0x17,0x17,0x84,0x18,0x2c,0x14,0x18,0x18,0x2c,0x57,0x2c,0x01,0x2c,0x18,0x22,0x24,0x24,0x84,0x1f,0x21,0x14,0x1f,0x21,0x38,0x21,0x01,0x09,0x21,0x01,0x21,0x6f,0x1f,0x01,0x1f,0x18,0x09,0x08,0x08,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0x28,0x10,0x01, 0x10,0x20,0x0d,0x50,0x0d,0x02,0x0d,0x18,0x16,0x10,0x13,0x95,0x37,0x35,0x2c,0x01,0x3a,0x10,0x31,0x30,0x00,0x22,0x21,0x0f,0x2a,0x24,0x27,0x95,0x1f,0x19,0x1c,0x16,0x0d,0x08,0x04,0x09,0x09,0x17,0x18,0x15,0x00,0x3f,0xc4,0x33,0x2f,0x33,0x33,0x33,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0xc4,0x3f,0xc4,0x3f,0x33,0x33,0x33,0x33,0xed, 0x32,0x32,0x01,0x2f,0xcc,0x5d,0x32,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x10,0xdc,0x5d,0x32,0x5d,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x11,0x01,0x33,0x5d,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x10,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x01,0x33,0x18,0x2f,0xed,0x31,0x30,0x5d,0x01,0x14, 0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x33,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x07,0x25,0x36,0x33,0x32,0x06,0xbc,0x08,0x81,0x04,0x15, 0x63,0x53,0x90,0x3f,0x07,0x86,0x03,0x33,0x0d,0x13,0xfe,0x54,0xa8,0xa6,0x16,0xfe,0x8e,0x4a,0x2a,0x9f,0x08,0xa5,0xa3,0xa6,0x03,0x33,0x0e,0x12,0x01,0xa7,0x98,0x13,0x01,0x14,0xa4,0x14,0x01,0x14,0x03,0x01,0x77,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1b,0x22,0x02,0x86,0x0e, 0x0f,0x35,0x05,0x73,0xfc,0xeb,0x65,0x69,0x15,0xb4,0x26,0x26,0x03,0x19,0xfc,0xc4,0x0f,0x0e,0x35,0x05,0x72,0x02,0xc3,0x58,0x59,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x35,0x85,0x14,0x6b,0x15,0x00,0x01,0x00,0x59,0xff,0xa7,0x04,0x4c,0x05,0xec,0x00,0x26,0x00,0x7d,0x40,0x45,0x07,0x06,0x06,0x02,0x00,0x00,0x84,0x26,0x25,0x14, 0x26,0x26,0x25,0x18,0x26,0x01,0x26,0x0a,0x25,0x25,0x10,0x28,0x1c,0x1f,0x1f,0x84,0x10,0x13,0x14,0x10,0x10,0x13,0x18,0x84,0x17,0x17,0x13,0x08,0x13,0x28,0x13,0x38,0x13,0x03,0x13,0x1f,0x10,0x01,0x10,0x1c,0x13,0x00,0x26,0x0f,0x17,0x00,0x25,0x1f,0x22,0x95,0x0d,0x06,0x02,0x07,0x07,0x10,0x0a,0x0d,0x16,0x00,0x3f,0x33,0x33,0x33, 0x2f,0x33,0x33,0x10,0xed,0x32,0x32,0x3f,0x3f,0xc4,0x33,0x33,0x01,0x2f,0x5d,0x33,0x5d,0x11,0x33,0x2f,0xed,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x31,0x30,0x01,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23,0x22, 0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x04,0x4c,0xb2,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0xfe,0x86,0x4a,0x30,0x9f,0x08,0x97,0x14,0x01,0x14,0xa4,0x14,0x01,0x14,0x9c,0x03,0x33,0x13,0x13,0x01,0xa8,0xa5,0x04,0x00,0xfc,0xb4,0x18,0x04,0x17,0x0f, 0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0xb4,0x26,0x26,0x02,0xc5,0x5e,0x53,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x5b,0x5f,0xfd,0x18,0x0e,0x0f,0x35,0x05,0x72,0x03,0x17,0x00,0x00,0x02,0x00,0x42,0xfe,0x1f,0x04,0x25,0x04,0x58,0x00,0x27,0x00,0x39,0x00,0xab,0x40,0x64,0x86,0x0e,0x01,0x75,0x0e,0x01,0x88,0x04,0x01,0x03,0x01,0x01, 0x84,0x39,0x37,0x14,0x39,0x39,0x37,0x18,0x39,0x01,0x09,0x39,0x01,0x39,0x37,0x12,0x13,0x13,0x37,0x37,0x18,0x3b,0x23,0x0a,0x2d,0x2f,0x2f,0x84,0x18,0x1b,0x14,0x18,0x18,0x1b,0x20,0x1f,0x1f,0x1b,0x09,0x1b,0x01,0x1b,0x1f,0x18,0x3f,0x18,0x02,0x18,0x39,0x2d,0x2a,0x95,0x26,0x1f,0x1b,0x20,0x20,0x23,0x01,0x26,0x10,0x5a,0x13,0x6a, 0x13,0x9a,0x13,0x03,0x13,0x15,0x12,0x12,0x10,0x95,0x15,0x1c,0x37,0x2f,0x32,0x95,0x18,0x0a,0x79,0x03,0x01,0x03,0x08,0x16,0x00,0x3f,0x33,0x5d,0x33,0x33,0xed,0x32,0x32,0x3f,0xed,0x32,0x2f,0x12,0x39,0x5d,0x3f,0x33,0x33,0x33,0x2f,0x33,0x33,0x10,0xed,0x32,0x32,0x01,0x2f,0x5d,0x33,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d, 0x10,0xc4,0x01,0x33,0x32,0x11,0x12,0x39,0x18,0x2f,0x33,0x2f,0x33,0x11,0x33,0x5d,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x03,0x06,0x07,0x05,0x06,0x23,0x22,0x27,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x07,0x06,0x23,0x20,0x11,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16, 0x17,0x25,0x36,0x33,0x32,0x07,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x13,0x36,0x04,0x25,0x08,0x6c,0x1f,0xae,0xfe,0x8a,0x53,0x21,0x08,0x0b,0x02,0x5a,0x53,0xb6,0xcd,0xb2,0x23,0xb1,0xbd,0xfe,0x0c,0x21,0x83,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0x01,0x7e,0x4b,0x29,0x9f,0xa7,0x33,0x0d,0x13, 0xfe,0x57,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x6e,0x03,0x03,0x64,0x26,0x26,0xfe,0x03,0x94,0x2c,0x5f,0x15,0x01,0x18,0x08,0x9e,0x44,0x3f,0x4c,0xa3,0x31,0x01,0xa9,0x85,0x9a,0x02,0x64,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x25,0x3f,0x6b,0x15,0xc0,0x35,0x05,0x72,0xfd,0xae,0x0e,0x0f,0x35,0x05,0x63,0x0e,0x33,0x02,0x20, 0x0f,0x00,0x00,0x01,0x00,0x5b,0xfe,0x25,0x06,0xea,0x05,0xec,0x00,0x42,0x00,0xb9,0x40,0x64,0x31,0x33,0x33,0x84,0x2f,0x30,0x14,0x2f,0x2f,0x30,0x30,0x2f,0x26,0x29,0x29,0x84,0x1a,0x1d,0x14,0x1a,0x1a,0x1d,0x22,0x21,0x21,0x1d,0x1d,0x5f,0x1a,0x8f,0x1a,0x02,0x1a,0x2f,0x40,0x84,0x3f,0x3f,0x0e,0x0f,0x39,0x3a,0x3b,0x04,0x01,0x01, 0x84,0x3b,0x0d,0x14,0x3b,0x3b,0x0d,0x68,0x3b,0x01,0x3b,0x0d,0x08,0x84,0x09,0x09,0x60,0x0d,0x01,0x0d,0x14,0x2f,0x3f,0x00,0x26,0x21,0x1d,0x22,0x22,0x3b,0x31,0x01,0x30,0x0f,0x39,0x33,0x36,0x95,0x12,0x2f,0x29,0x2c,0x95,0x1a,0x14,0x17,0x17,0x0f,0x0d,0x04,0x12,0x16,0x09,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0x2f,0x33,0x33, 0xed,0x32,0x32,0x10,0xed,0x32,0x32,0x3f,0x33,0xc4,0x33,0x33,0x2f,0x33,0x33,0x33,0x3f,0x01,0x2f,0x33,0xcc,0x5d,0x32,0x2f,0xed,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x01,0x33,0x18,0x2f,0xed,0x10,0xcc,0x5d,0x32,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x01,0x33, 0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x05,0x06,0x23,0x22,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x33,0x03,0x06,0x15,0x14,0x33, 0x32,0x37,0x25,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x06,0xea,0x13,0xb2,0x11,0x01,0x0c,0xa4,0x0c,0x01,0x14,0x05,0xfe,0x83,0x4a,0x2a,0x84,0x17,0xfe,0x71,0x4b,0x29,0x9f,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x3f,0x07,0x86,0x03,0x33,0x0d,0x13,0x01,0xad,0xa6,0xa7,0xac,0x03,0x33,0x0d,0x13,0x01,0xa9,0x96,0x14,0x01,0x14, 0xa4,0x14,0x01,0x04,0x66,0x5f,0x5b,0xfc,0xa7,0x52,0x5f,0x09,0x1d,0xfe,0xa9,0x01,0x4d,0x19,0x0e,0x61,0x59,0x14,0x6b,0x15,0x85,0x70,0x15,0xb4,0x26,0x26,0x02,0x64,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1b,0x22,0xfd,0x7a,0x0e,0x0f,0x35,0x05,0x73,0x03,0x16,0xfc,0xc4,0x0e,0x0f,0x35,0x05,0x72,0x02,0xc3,0x5e,0x53,0x14, 0x12,0x01,0x69,0xfe,0x97,0x12,0x00,0x03,0x00,0x5b,0xfe,0x25,0x06,0xbe,0x04,0x58,0x00,0x32,0x00,0x3e,0x00,0x50,0x01,0x06,0x40,0x94,0x25,0x2e,0x01,0x06,0x2e,0x16,0x2e,0x02,0x2e,0x38,0x18,0x4d,0x4e,0x4f,0x50,0x17,0x50,0x0d,0x38,0x0e,0x38,0x0e,0x0e,0x84,0x17,0x50,0x14,0x17,0x17,0x50,0x50,0x17,0x16,0x29,0x26,0x29,0x02,0x07, 0x29,0x01,0x29,0x44,0x46,0x46,0x84,0x1e,0x21,0x14,0x1e,0x1e,0x21,0x26,0x25,0x25,0x21,0x21,0x1e,0x17,0x12,0x84,0x13,0x13,0x17,0x09,0x08,0x08,0x04,0x3b,0x3c,0x3d,0x3e,0x04,0x01,0x01,0x84,0x3e,0x0c,0x14,0x3e,0x3e,0x0c,0x3e,0x20,0x0c,0x50,0x0c,0x02,0x0c,0x17,0x50,0x44,0x41,0x95,0x2c,0x3e,0x38,0x35,0x95,0x2e,0x01,0x31,0x31, 0x2c,0x25,0x21,0x26,0x26,0x29,0x2c,0x10,0x4d,0x46,0x39,0x49,0x95,0x1b,0x7b,0x3b,0x01,0x3b,0xa9,0x0c,0x01,0x9a,0x0c,0x01,0x7b,0x0c,0x8b,0x0c,0x02,0x0c,0x96,0x08,0x01,0x08,0x04,0x09,0x09,0x1e,0x18,0x17,0x0e,0x0d,0x1b,0x16,0x13,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0x33,0x33,0x2f,0x33,0x33,0x5d,0x33,0x5d,0x5d,0x5d,0x33, 0x5d,0x10,0xed,0x32,0x32,0x32,0x3f,0x33,0x33,0x2f,0x33,0x33,0x11,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x10,0xed,0x32,0x32,0x01,0x2f,0xcd,0x5d,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0xc4,0x05,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x33,0x2f,0xed,0x10,0xcc,0x32,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4, 0x01,0x32,0x5d,0x5d,0x11,0x33,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0x10,0x87,0x0e,0xc4,0xc4,0x05,0xc4,0xc4,0x11,0x01,0x33,0x5d,0x5d,0x31,0x30,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36, 0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x17,0x25,0x36,0x33,0x32,0x07,0x34,0x23,0x22,0x07,0x05,0x03,0x25,0x36,0x37,0x13,0x36,0x25,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x13,0x36,0x06,0xbe,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x34,0x09,0xfd,0xf4,0x03,0x01,0x0c,0xa4, 0x0c,0x01,0x17,0xfe,0x81,0x50,0x24,0x9f,0x08,0x83,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0x01,0x7e,0x4b,0x29,0x85,0x16,0x01,0x8a,0x4e,0x26,0x9f,0xa7,0x33,0x0e,0x12,0xfe,0x58,0x8c,0x01,0xd5,0x36,0x0b,0x6e,0x03,0xfd,0x67,0x33,0x0d,0x13,0xfe,0x57,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x6e,0x03,0x03,0x64,0x26,0x26,0xfd, 0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x21,0x3a,0x77,0x29,0x1c,0x09,0x1d,0xfe,0xa9,0x01,0x39,0x1a,0x21,0x5d,0x6b,0x65,0x15,0xb4,0x27,0x25,0x02,0x64,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0x7f,0x6a,0x15,0xc0,0x35,0x05,0x73,0xfd,0x58,0x6d,0x0d,0x34,0x02,0x20,0x0f,0x0e,0x35,0x05,0x72,0xfd,0xae,0x0e,0x0f, 0x35,0x05,0x63,0x0e,0x33,0x02,0x20,0x0f,0x00,0x01,0x00,0x71,0xfe,0x25,0x04,0x75,0x05,0xec,0x00,0x39,0x00,0xb1,0x40,0x63,0x30,0x84,0x2f,0x2f,0x2b,0x21,0x1e,0x84,0x22,0x2f,0x25,0x01,0x25,0x25,0x2b,0x03,0x00,0x84,0x04,0x7f,0x07,0x01,0x07,0x07,0x34,0x2a,0x19,0x18,0x17,0x2b,0x17,0x0d,0x0c,0x35,0x34,0x0e,0x34,0x0e,0x0e,0x84, 0x17,0x2b,0x14,0x17,0x17,0x2b,0x89,0x2b,0x01,0xf8,0x2b,0x01,0x99,0x2b,0x01,0x85,0x2b,0x01,0x66,0x2b,0x01,0x08,0x2b,0x01,0x2b,0x17,0x12,0x84,0x13,0x13,0x17,0x2a,0x35,0x38,0x27,0x95,0x0c,0x19,0x09,0x1c,0x1c,0x03,0x09,0x95,0x38,0x34,0x2b,0x38,0x22,0x22,0x38,0x10,0x2f,0x00,0x0e,0x17,0x15,0x13,0x1b,0x00,0x3f,0x3f,0x33,0x3f, 0x3f,0x33,0x2f,0x11,0x33,0x33,0x10,0xfd,0xcc,0x32,0x2f,0x12,0x39,0x39,0xed,0x11,0x39,0x39,0x01,0x2f,0x33,0x2f,0xed,0x11,0x33,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x0e,0xc4,0x10,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x5d,0x33,0xed,0x32,0x11,0x33,0x2f,0x5d,0x33,0xed, 0x32,0x11,0x33,0x2f,0xed,0x31,0x30,0x01,0x14,0x07,0x07,0x23,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x07,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x37,0x33,0x07,0x06,0x15,0x14,0x33,0x32,0x37,0x37,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x37,0x36,0x33, 0x32,0x04,0x75,0x08,0x0d,0xa8,0x13,0x03,0x33,0x10,0x10,0xad,0x9f,0x11,0x01,0x0c,0xa4,0x0c,0x01,0x13,0x92,0x9b,0x44,0x30,0x9f,0x08,0x0d,0xa8,0x13,0x03,0x33,0x10,0x10,0xd0,0x15,0x01,0x14,0xa4,0x14,0x01,0x0a,0x78,0x44,0x30,0x9f,0x03,0x64,0x24,0x28,0x41,0x64,0x10,0x0d,0x35,0x05,0x36,0xfd,0x01,0x52,0x5f,0x09,0x1d,0xfe,0xa9, 0x01,0x4d,0x19,0x0e,0x5d,0x5d,0x02,0xc9,0x30,0x15,0xb4,0x24,0x28,0x41,0x64,0x10,0x0d,0x35,0x05,0x41,0x67,0x4e,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x44,0x44,0x25,0x15,0x00,0x01,0x00,0x28,0xff,0xa7,0x04,0x25,0x04,0x18,0x00,0x21,0x00,0x84,0x40,0x4a,0x09,0x08,0x08,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0x10, 0x0d,0x0d,0x18,0x23,0x1b,0x1a,0x1a,0x19,0x16,0x1d,0x1c,0x17,0x1c,0x17,0x17,0x84,0x18,0x19,0x14,0x18,0x19,0x88,0x19,0x01,0x79,0x19,0x01,0x18,0x19,0x01,0x19,0x1f,0x18,0x3f,0x18,0x02,0x18,0x16,0x10,0x13,0x95,0x1d,0x01,0x20,0x10,0x19,0x95,0x1c,0x0f,0x0d,0x96,0x08,0x01,0x08,0x04,0x09,0x09,0x17,0x18,0x15,0x00,0x3f,0xc4,0x33, 0x2f,0x33,0x33,0x5d,0x33,0x3f,0xed,0x3f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x5d,0x33,0x5d,0x5d,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x31,0x30,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26, 0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x04,0x25,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x3f,0x0a,0x83,0x03,0x33,0x0d,0x13,0xfe,0x57,0xa6,0xab,0xbe,0xc7,0x1d,0x01,0x6e,0x16,0x01,0x75,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46, 0x85,0x5c,0x28,0x4d,0x0c,0x31,0x02,0x86,0x0f,0x0e,0x35,0x05,0x72,0xfc,0xea,0x03,0x75,0x8b,0x67,0x6a,0x15,0x00,0x00,0x01,0x00,0x28,0xfe,0x25,0x04,0x4e,0x04,0x00,0x00,0x21,0x00,0x7e,0x40,0x45,0x20,0x0d,0x0c,0x0b,0x00,0x02,0x02,0x84,0x0b,0x21,0x14,0x0b,0x0b,0x21,0xa8,0x21,0x01,0x21,0x0b,0x06,0x84,0x07,0x07,0x0b,0x0b,0x13, 0x23,0x18,0x1a,0x1a,0x84,0x13,0x15,0x14,0x13,0x13,0x15,0x17,0x16,0x16,0x15,0xa9,0x15,0xb9,0x15,0x02,0x15,0x1f,0x13,0x01,0x13,0x00,0x21,0x15,0x95,0x18,0x0f,0x20,0x1a,0x1d,0x95,0x13,0x0d,0x0b,0x02,0x10,0x16,0x07,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x3f,0xed,0xd4,0xc4,0x01,0x2f,0x5d,0x33,0x5d,0x11,0x33, 0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x2f,0xed,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0x05,0xc4,0xc4,0x31,0x30,0x01,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x23,0x37,0x21,0x03,0x06,0x15,0x14,0x33, 0x32,0x37,0x25,0x13,0x04,0x4e,0xc5,0x11,0x01,0x0c,0xa4,0x0c,0x01,0x10,0x06,0xfe,0x84,0x48,0x2c,0x9f,0x08,0x8c,0xc7,0x1d,0x01,0x6e,0xae,0x03,0x33,0x0d,0x13,0x01,0xad,0xa6,0x04,0x00,0xfc,0x53,0x51,0x60,0x09,0x1d,0xfe,0xa9,0x01,0x4d,0x19,0x0e,0x73,0x47,0x19,0x70,0x15,0xb4,0x27,0x25,0x02,0x8e,0x8b,0xfc,0xc4,0x0e,0x0f,0x35, 0x05,0x73,0x03,0x16,0x00,0x01,0x00,0x5b,0xfe,0x1f,0x04,0x4e,0x04,0x00,0x00,0x2c,0x00,0x8e,0x40,0x52,0x75,0x12,0x85,0x12,0x02,0x85,0x11,0x01,0x76,0x11,0x01,0x98,0x0c,0x01,0x95,0x08,0x01,0x95,0x07,0x01,0x2b,0x1a,0x02,0x00,0x00,0x84,0x2c,0x1a,0x14,0x2c,0x2c,0x1a,0x2c,0x1a,0x06,0x84,0x17,0x17,0x1a,0x1a,0x20,0x2e,0x23,0x25, 0x25,0x84,0x20,0x22,0x14,0x20,0x20,0x22,0x22,0x20,0x0f,0x84,0x0e,0x0e,0x1f,0x20,0x01,0x20,0x00,0x2c,0x23,0x22,0x0f,0x2b,0x25,0x28,0x95,0x0e,0x0f,0x20,0x1a,0x02,0x1d,0x16,0x13,0x95,0x0a,0x1c,0x00,0x3f,0xed,0x3f,0x33,0x33,0x33,0xce,0x32,0xed,0x32,0x32,0x3f,0xc4,0xd4,0xc4,0x01,0x2f,0x5d,0x33,0x2f,0xed,0x11,0x33,0x87,0x10, 0x2b,0x7d,0x10,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x2f,0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0xc4,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x03,0x06,0x15,0x14,0x16,0x15,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x27,0x37,0x16,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x26,0x35,0x05,0x06,0x23,0x22,0x35, 0x34,0x37,0x13,0x33,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x04,0x4e,0xb8,0x02,0x1a,0x9f,0x77,0xb5,0x9a,0x6f,0x61,0x12,0x9d,0x08,0x41,0x4c,0x67,0x5d,0x4a,0x61,0x19,0xfe,0x7f,0x48,0x2c,0x9f,0x08,0xa8,0xa8,0xae,0x03,0x33,0x0d,0x13,0x01,0xad,0xa6,0x04,0x00,0xfc,0x95,0x0a,0x0c,0x32,0xb0,0x43,0xae,0x51,0x3c,0x60,0x54, 0x6c,0x19,0x39,0x36,0x40,0x23,0x2f,0x5b,0x2d,0x9f,0x4a,0x70,0x15,0xb4,0x26,0x26,0x03,0x19,0xfc,0xc4,0x0e,0x0f,0x35,0x05,0x73,0x03,0x16,0x00,0x00,0x01,0x00,0x2f,0xfe,0x25,0x04,0x25,0x05,0xec,0x00,0x33,0x00,0x97,0x40,0x52,0x96,0x07,0x01,0x09,0x08,0x08,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0x10,0x0d,0x0d,0x21, 0x35,0x29,0x84,0x28,0x28,0x24,0x17,0x16,0x2f,0x2e,0x2d,0x18,0x2d,0x18,0x18,0x84,0x21,0x24,0x14,0x21,0x21,0x24,0xe6,0x24,0x01,0xd7,0x24,0x01,0x24,0x21,0x1c,0x84,0x1d,0x1d,0x1f,0x21,0x3f,0x21,0x02,0x21,0x16,0x10,0x13,0x95,0x2f,0x2d,0x24,0x01,0x32,0x10,0x28,0x00,0x0d,0x08,0x04,0x09,0x09,0x18,0x21,0x15,0x1d,0x1b,0x00,0x3f, 0x3f,0x33,0x33,0x2f,0x33,0x33,0x33,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x5d,0x33,0x2f,0xed,0x11,0x33,0x5d,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x11,0x01,0x33,0x18,0x2f,0xed,0x11,0x12,0x39,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x31,0x30, 0x5d,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x07,0x25,0x36,0x33,0x32,0x04,0x25,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x3f,0x07, 0x86,0x03,0x33,0x0d,0x13,0xfe,0x54,0x97,0x15,0x01,0x0c,0xa4,0x0c,0x01,0x14,0xb8,0x13,0x01,0x14,0xa4,0x14,0x01,0x14,0x03,0x01,0x77,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1b,0x22,0x02,0x86,0x0e,0x0f,0x35,0x05,0x73,0xfd,0x3e,0x62,0x4f,0x09,0x1d,0xfe,0xa9,0x01,0x4b,0x18, 0x11,0x5d,0x5d,0x03,0x59,0x58,0x59,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x35,0x85,0x14,0x6b,0x15,0x00,0x01,0x00,0x42,0xfe,0x1f,0x04,0x25,0x04,0x58,0x00,0x34,0x00,0xa5,0x40,0x5f,0x9a,0x23,0x01,0x76,0x1b,0x86,0x1b,0x02,0x95,0x07,0x01,0x77,0x07,0x87,0x07,0x02,0x1f,0x20,0x20,0x50,0x20,0x60,0x20,0x03,0x20,0x20,0x09,0x08, 0x08,0x04,0x01,0x01,0x84,0x10,0x0d,0x14,0x10,0x10,0x0d,0x10,0x0d,0x0d,0x25,0x36,0x2d,0x2c,0x2c,0x28,0x30,0x16,0x18,0x18,0x84,0x25,0x28,0x14,0x25,0x28,0x28,0x1f,0x25,0x01,0x25,0x2c,0x28,0x2d,0x2d,0x16,0x10,0x13,0x95,0x30,0x01,0x33,0x10,0x9a,0x20,0x01,0x20,0x22,0x1f,0x1f,0x1d,0x95,0x22,0x1c,0x08,0x09,0x09,0x25,0x18,0x0d, 0x04,0x0a,0x15,0x00,0x3f,0x33,0x33,0x33,0x33,0x33,0x2f,0x33,0x3f,0xed,0x32,0x2f,0x12,0x39,0x5d,0x3f,0x33,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0x33,0x01,0x2f,0x5d,0x33,0x87,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x11,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x32,0x2f,0x5d, 0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x07,0x06,0x23,0x20,0x11,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x04,0x25,0x08,0x81, 0x04,0x15,0x63,0x53,0x90,0x3f,0x0a,0x83,0x03,0x33,0x0d,0x13,0xfe,0x57,0x7a,0x23,0x5a,0x53,0xb6,0xcd,0xb2,0x23,0xb1,0xbd,0xfe,0x0c,0x21,0x83,0x05,0x15,0x63,0x53,0x90,0x37,0x06,0x01,0x7f,0x4b,0x29,0x9f,0x03,0x64,0x26,0x26,0xfd,0x9c,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x0c,0x31,0x02,0x86,0x0f,0x0e,0x35,0x05,0x72, 0xfd,0xba,0xa7,0x61,0x9e,0x44,0x3f,0x4c,0xa3,0x31,0x01,0xa9,0x85,0x9a,0x02,0x64,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x23,0x41,0x6b,0x15,0x00,0x00,0x02,0x00,0x59,0xff,0xe7,0x06,0xbc,0x05,0xec,0x00,0x2a,0x00,0x36,0x00,0xb6,0x40,0x64,0x20,0x84,0x1f,0x1f,0x1b,0x1a,0x2b,0x36,0x0f,0x0e,0x1b,0x0e,0x0c,0x26,0x25,0x24,0x0d,0x24, 0x0d,0x0d,0x84,0x0e,0x1b,0x14,0x0e,0x0e,0x1b,0x88,0x1b,0x01,0x79,0x1b,0x01,0x1b,0x0e,0x2d,0x30,0x30,0x84,0x15,0x18,0x14,0x15,0x18,0x78,0x18,0x01,0x69,0x18,0x01,0x08,0x18,0x01,0x18,0x15,0x0e,0x03,0x01,0x01,0x84,0x06,0x04,0x14,0x06,0x06,0x04,0x06,0x04,0x0e,0x2d,0x2b,0x95,0x24,0x1b,0x18,0x1a,0x1a,0x0c,0x06,0x09,0x95,0x26, 0x01,0x29,0x10,0x1f,0x00,0x36,0x30,0x33,0x95,0x15,0x0f,0x12,0x16,0x03,0x04,0x0d,0x0e,0x15,0x00,0x3f,0xc4,0xd4,0xc4,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0x3f,0x33,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0x33,0x33,0xed,0x32,0x01,0x2f,0xcc,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xdc,0x32,0x5d,0x5d,0x5d,0x87,0x2b,0x7d, 0x10,0xc4,0x11,0x01,0x33,0x5d,0x5d,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x10,0x87,0xc4,0xc4,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0xed,0x31,0x30,0x01,0x14,0x07,0x03,0x23,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x37,0x25,0x36,0x35,0x34, 0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x07,0x25,0x36,0x33,0x32,0x05,0x05,0x06,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x06,0xbc,0x08,0xa5,0xa7,0xaa,0x03,0x33,0x0d,0x13,0xfe,0x54,0xa8,0xa6,0x16,0xfe,0x8e,0x4a,0x2a,0x9f,0x08,0x69,0x20,0xad,0x02,0x0b,0x03,0x01,0x14,0xa4,0x14,0x01,0x14,0x03,0x01,0x77,0x4a,0x2a,0x9f, 0xfc,0xd0,0xfe,0x23,0x37,0x0a,0x6b,0x03,0x33,0x0e,0x12,0x01,0xa7,0x03,0x64,0x26,0x26,0xfc,0xe8,0x03,0x3b,0x0f,0x0e,0x35,0x05,0x73,0xfc,0xeb,0x65,0x69,0x15,0xb4,0x27,0x25,0x01,0xeb,0x94,0x2c,0x86,0x23,0x22,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x35,0x85,0x14,0x6b,0x15,0x87,0x7e,0x0e,0x33,0xfd,0xf2,0x0f,0x0e,0x35,0x05, 0x72,0x00,0x00,0x01,0x00,0x3f,0xfe,0x25,0x06,0xc0,0x04,0x58,0x00,0x35,0x00,0xae,0x40,0x61,0x29,0x28,0x28,0x24,0x15,0x2c,0x01,0x06,0x2c,0x01,0x2c,0x16,0x18,0x18,0x84,0x21,0x24,0x14,0x21,0x21,0x24,0x24,0x21,0x1c,0x84,0x1d,0x1d,0x5f,0x21,0x01,0x21,0x0e,0x06,0x31,0x16,0x31,0x02,0x31,0x0d,0x0c,0x0c,0x84,0x10,0x0e,0x14,0x10, 0x10,0x0e,0x10,0x0e,0x03,0x01,0x01,0x84,0x06,0x04,0x14,0x06,0x06,0x04,0x06,0x50,0x04,0x80,0x04,0x02,0x04,0x0e,0x0c,0x06,0x09,0x95,0x31,0x01,0x34,0x34,0x2f,0x28,0x24,0x29,0x29,0x16,0x10,0x13,0x95,0x2c,0x2f,0x10,0x1d,0x1b,0x03,0x04,0x21,0x18,0x0d,0x0e,0x15,0x00,0x3f,0xc4,0x33,0x33,0xd4,0xc4,0x3f,0x3f,0x33,0xed,0x32,0x32, 0x33,0x2f,0x33,0x33,0x11,0x33,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcc,0x5d,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x01,0x33,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x33,0x5d,0x18,0x10,0xcc,0x5d,0x32,0x2f,0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x5d,0x5d,0x11,0x33,0x18,0x2f,0x33,0x31,0x30,0x01,0x14, 0x07,0x03,0x23,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x17,0x25,0x36,0x33,0x32,0x06,0xc0,0x08,0xa5,0xa3,0xa6,0x03,0x33,0x0d,0x13,0xfe,0x56, 0xa5,0xa3,0xa7,0x03,0x33,0x0d,0x13,0xfe,0x57,0x87,0x18,0x01,0x14,0xa4,0x14,0x01,0x14,0x93,0x05,0x15,0x63,0x53,0x90,0x37,0x06,0x01,0x7f,0x4b,0x29,0x84,0x17,0x01,0x8c,0x4a,0x2a,0x9f,0x03,0x64,0x26,0x26,0xfc,0xe8,0x03,0x3b,0x0f,0x0e,0x35,0x05,0x73,0xfc,0xeb,0x03,0x3b,0x0f,0x0e,0x35,0x05,0x72,0xfd,0x80,0x72,0x2d,0x37,0x14, 0xfe,0x79,0x01,0x87,0x14,0x34,0x45,0x5e,0x02,0xb4,0x18,0x04,0x17,0x0f,0x46,0x85,0x5c,0x23,0x41,0x6b,0x15,0x86,0x71,0x15,0x00,0x01,0x00,0x21,0xfe,0x1f,0x04,0x80,0x04,0x18,0x00,0x44,0x00,0xd9,0x40,0x84,0x97,0x44,0x01,0x7a,0x2c,0x01,0x69,0x2c,0x01,0x9a,0x28,0x01,0x96,0x24,0x01,0x77,0x24,0x87,0x24,0x02,0x46,0x17,0x56,0x17, 0x02,0x85,0x13,0x01,0x36,0x28,0x01,0x01,0x00,0x00,0x42,0x84,0x04,0x3d,0x84,0x09,0x09,0x04,0x04,0x15,0x83,0x2a,0x2a,0x33,0x46,0x36,0x35,0x35,0x34,0x0f,0x0e,0x38,0x37,0x32,0x67,0x32,0x77,0x32,0x02,0x37,0x32,0x32,0x84,0x33,0x34,0x14,0x33,0x33,0x34,0x47,0x34,0x77,0x34,0x97,0x34,0x03,0x34,0x33,0x20,0x22,0x84,0x1f,0x1d,0x1d, 0x4f,0x33,0x5f,0x33,0x02,0x33,0x20,0x1f,0x0f,0x11,0x32,0x33,0x33,0x26,0x2e,0x95,0x00,0x01,0x09,0x01,0x19,0x01,0x29,0x01,0x03,0x11,0x01,0x11,0x01,0x26,0x0e,0x0b,0x95,0x38,0x3b,0x10,0x34,0x95,0x37,0x0f,0x26,0x95,0x19,0x1c,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0xed,0x32,0x11,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0xed,0x11,0x39, 0x2f,0xc4,0x12,0x39,0xce,0x32,0x01,0x2f,0x5d,0x33,0x2f,0x33,0xed,0x32,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x5d,0x87,0xc4,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0xed,0x33,0x2f,0x33,0x2f,0xed,0x10,0xed,0x32,0x2f,0x33,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01, 0x07,0x27,0x26,0x35,0x34,0x37,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x36,0x33,0x32,0x17,0x16,0x15,0x10,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x27,0x26,0x23,0x22,0x07,0x06,0x07,0x23,0x13,0x23,0x37,0x21,0x07,0x25,0x36,0x33,0x32,0x15,0x14,0x07,0x07, 0x06,0x15,0x14,0x17,0x04,0x80,0x53,0x90,0x3f,0x0a,0x13,0x03,0x33,0x0d,0x13,0xfe,0x57,0x5e,0x81,0xca,0xcd,0x74,0x62,0xb8,0x9a,0xf1,0xc7,0x78,0x6f,0x3b,0x90,0x24,0x4b,0x52,0x87,0x8e,0x6b,0x87,0x40,0x4e,0x8c,0x64,0x5f,0x70,0x2d,0xab,0xa8,0xc7,0x1d,0x01,0x6e,0x16,0x01,0x75,0x4a,0x2a,0x9f,0x08,0x11,0x04,0x15,0x02,0x47,0x85, 0x5c,0x28,0x4d,0x06,0x37,0x6b,0x10,0x0d,0x35,0x05,0x72,0xfe,0x3f,0x4a,0x7b,0x69,0x8f,0xfe,0xf2,0x8a,0x75,0x50,0x4b,0x71,0x53,0x52,0x37,0x38,0x27,0x3c,0x29,0x2c,0x52,0x69,0xc4,0x56,0x43,0x54,0x2a,0x31,0x56,0x03,0x11,0x8b,0x67,0x6a,0x15,0xb4,0x28,0x24,0x49,0x11,0x0b,0x17,0x0f,0x00,0x00,0x01,0x00,0x42,0xfe,0x1f,0x04,0x2e, 0x04,0x58,0x00,0x30,0x00,0xbb,0x40,0x6b,0x18,0x25,0x01,0x99,0x2c,0x01,0x88,0x2c,0x01,0x9a,0x0f,0x01,0x77,0x0a,0x87,0x0a,0x02,0x2e,0x2d,0x2d,0x29,0x0e,0x0f,0x0f,0x04,0x01,0x01,0x84,0x29,0x26,0x14,0x29,0x29,0x26,0x18,0x29,0x01,0x09,0x29,0x01,0x29,0x26,0x26,0x14,0x32,0x1c,0x1b,0x1b,0x17,0x21,0x22,0x23,0x24,0x06,0x20,0x20, 0x06,0x06,0x84,0x14,0x17,0x14,0x14,0x17,0x17,0x1f,0x14,0x01,0x14,0x2d,0x2e,0x2e,0x1b,0x1c,0x1c,0x29,0x20,0x17,0x01,0x1d,0x0f,0x7a,0x0f,0x01,0x5b,0x0f,0x6b,0x0f,0x02,0x0f,0x11,0x0e,0x0e,0x0c,0x95,0x11,0x1c,0x26,0x24,0x95,0x14,0x79,0x04,0x01,0x04,0x06,0x16,0x00,0x3f,0x33,0x5d,0x33,0xed,0x32,0x3f,0xed,0x32,0x2f,0x12,0x39, 0x5d,0x5d,0x3f,0x33,0x33,0x33,0x33,0x33,0x2f,0x33,0x33,0x2f,0x33,0x01,0x2f,0x5d,0x33,0x87,0x2b,0x7d,0x10,0xc4,0x87,0xc4,0x0e,0xc4,0xc4,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x5d,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x32,0x18,0x2f,0x33,0x11,0x33,0x2f,0x33,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x01, 0x5d,0x01,0x14,0x07,0x03,0x06,0x07,0x05,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x07,0x06,0x23,0x20,0x11,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x15,0x14,0x07,0x03,0x06,0x07,0x25,0x36,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x04,0x2e,0x06,0x73,0x1f,0xae,0xfd,0xfe,0x01,0x5a,0x53,0xb6,0xcd,0xb2, 0x23,0xb1,0xbd,0xfe,0x0c,0x21,0x84,0x03,0x15,0x63,0x53,0x90,0x3f,0x07,0x85,0x0c,0x07,0x01,0xdb,0x37,0x0a,0x70,0x03,0x15,0x63,0x53,0x90,0x3f,0x03,0x87,0x20,0x1d,0xfd,0xdc,0x95,0x2b,0x7f,0x12,0x0d,0x9e,0x44,0x3f,0x4c,0xa3,0x31,0x01,0xa9,0x86,0x99,0x02,0x64,0x10,0x0c,0x17,0x0f,0x46,0x85,0x5c,0x28,0x4d,0x1c,0x21,0xfd,0x86, 0x38,0x2d,0x7a,0x0e,0x33,0x02,0x25,0x0f,0x0d,0x17,0x0f,0x46,0x85,0x5c,0x28,0x00,0x00,0x02,0xff,0x8a,0xfe,0x25,0x04,0x5a,0x04,0xb5,0x00,0x15,0x00,0x18,0x00,0x95,0x40,0x5d,0x27,0x01,0x01,0x06,0x05,0x18,0x16,0x08,0x17,0x02,0x09,0x16,0x08,0x0a,0x03,0x04,0x00,0x05,0x0a,0x03,0x01,0x00,0x05,0x17,0x02,0x16,0x05,0x00,0x05,0x84, 0x08,0x16,0x14,0x08,0x08,0x16,0x17,0x03,0x0a,0x03,0x84,0x02,0x17,0x14,0x02,0x02,0x17,0x00,0x00,0x0f,0x02,0x4f,0x02,0x6f,0x02,0x7f,0x02,0xbf,0x02,0x05,0x02,0x02,0x08,0x1a,0x10,0x12,0x84,0x0f,0x0d,0x0d,0x0a,0x0a,0x07,0x0f,0x08,0x01,0x08,0x00,0x15,0x17,0x0a,0x16,0x95,0x10,0x15,0x0f,0x07,0x1b,0x08,0x05,0x03,0x02,0x15,0x00, 0x3f,0xc4,0x33,0x33,0x3f,0x3f,0xce,0xfd,0xc4,0xc4,0x12,0x39,0x01,0x2f,0x5d,0x33,0x33,0x2f,0x33,0x2f,0x33,0xed,0x32,0x11,0x12,0x39,0x2f,0x5d,0x33,0x2f,0x87,0x10,0x2b,0x87,0x7d,0xc4,0x87,0x18,0x10,0x2b,0x87,0x7d,0xc4,0x0f,0x0f,0x0f,0x0f,0x11,0x01,0x33,0x31,0x30,0x5d,0x01,0x01,0x13,0x23,0x03,0x00,0x03,0x23,0x12,0x01,0x03, 0x23,0x22,0x37,0x36,0x37,0x33,0x06,0x15,0x14,0x33,0x21,0x05,0x21,0x17,0x04,0x5a,0xfe,0x68,0xe6,0xb5,0xa5,0xfe,0x8d,0x8e,0xc3,0xc9,0x01,0xb5,0xaa,0x86,0x96,0x06,0x02,0x1d,0xa7,0x1f,0x29,0x03,0x42,0xfe,0xf5,0xfe,0xc4,0x6b,0x03,0xd1,0xfe,0x24,0xfe,0x0b,0x01,0x67,0xfe,0x2f,0xfe,0x8f,0x01,0xcd,0x02,0x0d,0x01,0x75,0x94,0x2f, 0x7e,0x78,0x15,0x28,0x8c,0xea,0x00,0x01,0x00,0x31,0xff,0xa7,0x06,0xe6,0x04,0x58,0x00,0x37,0x00,0xb7,0x40,0x65,0x89,0x20,0x01,0x97,0x05,0x01,0x22,0x70,0x21,0x01,0x21,0x21,0x1d,0x25,0x19,0x1a,0x1a,0x84,0x1b,0x1d,0x14,0x1b,0x1d,0x89,0x1d,0x01,0x1d,0x1b,0x10,0x2b,0x2e,0x2e,0x84,0x10,0x13,0x14,0x10,0x10,0x13,0x13,0x10,0x07, 0x06,0x06,0x02,0x36,0x35,0x0a,0x02,0x00,0x00,0x84,0x37,0x0a,0x14,0x37,0x37,0x0a,0x37,0x20,0x0a,0x01,0x0a,0x10,0x00,0x37,0x0f,0x21,0x1d,0x22,0x22,0x19,0x13,0x16,0x95,0x2b,0x25,0x28,0x10,0x1a,0x1b,0x15,0x29,0x35,0x01,0x35,0x2e,0x31,0x95,0x0d,0x06,0x02,0x07,0x07,0x10,0x28,0x0a,0x01,0x0a,0x0d,0x16,0x00,0x3f,0x33,0x5d,0x33, 0x33,0x2f,0x33,0x33,0x10,0xed,0x32,0x32,0x5d,0x3f,0xc4,0x3f,0x33,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0x33,0x3f,0xc4,0x01,0x2f,0xcc,0x5d,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0xc4,0x0e,0xc4,0x11,0x01,0x33,0x18,0x2f,0x33,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xdc,0x32,0x5d,0x87,0x2b,0x7d,0x10,0xc4,0x01, 0x32,0x11,0x33,0x18,0x2f,0x5d,0x33,0x31,0x30,0x5d,0x5d,0x01,0x03,0x06,0x15,0x14,0x17,0x17,0x07,0x27,0x26,0x27,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x03,0x23,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x17,0x25,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25, 0x36,0x37,0x13,0x06,0xe6,0xb1,0x04,0x15,0x63,0x53,0x90,0x34,0x09,0xfe,0x7e,0x53,0x21,0x9f,0x08,0x7f,0x03,0x33,0x0e,0x13,0xfe,0x58,0xa6,0xab,0xb5,0x05,0x15,0x63,0x53,0x90,0x38,0x06,0x01,0x7d,0x4b,0x2a,0x9f,0x0a,0x7d,0x03,0x33,0x0d,0x13,0x01,0x77,0x37,0x0a,0x94,0x04,0x00,0xfc,0xb4,0x13,0x09,0x17,0x0f,0x46,0x85,0x5c,0x21, 0x3a,0x62,0x15,0xb4,0x26,0x26,0x02,0x54,0x0e,0x0f,0x35,0x05,0x72,0xfc,0xea,0x03,0x4b,0x17,0x05,0x17,0x0f,0x46,0x85,0x5c,0x24,0x40,0x6b,0x15,0xb4,0x1e,0x30,0xfd,0xae,0x0e,0x0f,0x35,0x05,0x63,0x0e,0x33,0x02,0xe5,0x00,0x01,0x00,0x2f,0xfe,0x25,0x04,0xbe,0x05,0xec,0x00,0x2d,0x00,0x77,0x40,0x40,0x00,0x01,0x37,0x29,0x97,0x29, 0x02,0x29,0x2b,0x84,0x06,0x04,0x04,0x15,0x2f,0x1d,0x84,0x1c,0x1c,0x18,0x22,0x23,0x0a,0x0b,0x0c,0x21,0x21,0x0c,0x0c,0x84,0x15,0x18,0x14,0x15,0x15,0x18,0x69,0x18,0x01,0x18,0x15,0x10,0x84,0x11,0x11,0x15,0x02,0x95,0x2d,0x0a,0x07,0x95,0x23,0x21,0x18,0x26,0x10,0x1c,0x00,0x0c,0x15,0x15,0x11,0x1b,0x00,0x3f,0x3f,0x33,0x3f,0x3f, 0x33,0x33,0x33,0xed,0x32,0xdc,0xed,0x01,0x2f,0x33,0x2f,0xed,0x11,0x33,0x5d,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x11,0x01,0x33,0x18,0x2f,0xed,0x11,0x12,0x39,0x2f,0x33,0xfd,0x32,0x5d,0xcc,0x32,0x31,0x30,0x01,0x07,0x23,0x22,0x27,0x27,0x26,0x23,0x22,0x07,0x05,0x03,0x06,0x15,0x14,0x17,0x13, 0x23,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x15,0x14,0x07,0x07,0x25,0x36,0x33,0x32,0x17,0x16,0x17,0x17,0x16,0x33,0x04,0xbe,0x1d,0xd3,0x60,0x22,0x38,0x0d,0x2a,0x10,0x10,0xfe,0xc5,0x9a,0x15,0x01,0x0c,0xa4,0x0c,0x01,0x14,0xb8,0x13,0x01,0x14,0xa4,0x14,0x01,0x0f,0x03,0x01,0x04,0x42,0x32,0x4c, 0x27,0x19,0x17,0x32,0x08,0x19,0x02,0x7f,0x8b,0x87,0xde,0x34,0x05,0x63,0xfd,0x2e,0x62,0x4f,0x09,0x1d,0xfe,0xa9,0x01,0x4d,0x18,0x0f,0x5d,0x5d,0x03,0x59,0x58,0x59,0x14,0x12,0x01,0x69,0xfe,0x97,0x12,0x0b,0x3e,0x64,0x14,0x53,0x15,0x36,0x23,0x5a,0xc7,0x1f,0x00,0x01,0x00,0x35,0xff,0xe7,0x03,0xfe,0x04,0x00,0x00,0x1b,0x00,0x58, 0x40,0x35,0x89,0x0b,0x01,0x95,0x08,0x01,0x28,0x05,0x01,0x95,0x02,0x01,0x37,0x02,0x01,0x24,0x02,0x01,0x00,0x83,0x20,0x0d,0x01,0x0d,0x0d,0x1d,0x15,0x17,0x84,0x12,0x07,0x06,0x06,0x14,0x12,0x0f,0x95,0x1a,0x15,0x0f,0x08,0x06,0x18,0x06,0x02,0x06,0x04,0x07,0x07,0x09,0x95,0x04,0x16,0x00,0x3f,0xed,0x32,0x2f,0x12,0x39,0x5d,0x3f, 0xde,0xed,0x01,0x2f,0x33,0x33,0x2f,0x33,0x10,0xed,0x32,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x10,0x07,0x06,0x21,0x22,0x27,0x37,0x16,0x33,0x32,0x37,0x36,0x35,0x34,0x23,0x21,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x33,0x21,0x20,0x03,0xfe,0x9c,0xa5,0xfe,0xe9,0xe9,0x88,0x65,0x81,0x9a,0xbf, 0x77,0x6b,0xbb,0xfe,0xc8,0x90,0x0e,0xa3,0x0a,0x29,0x01,0x2c,0x01,0x2f,0x02,0x41,0xfe,0xfe,0xa7,0xb1,0x8b,0x7f,0x7e,0x91,0x84,0xb5,0xde,0x94,0x1e,0x33,0x25,0x0c,0x28,0x00,0x00,0x01,0x00,0x46,0xfe,0x29,0x04,0x3c,0x05,0xec,0x00,0x33,0x00,0x94,0x40,0x4e,0x9a,0x1b,0x01,0x31,0x84,0x30,0x30,0x2c,0x2b,0x2a,0x0f,0x0e,0x0d,0x04, 0x01,0x01,0x84,0x2c,0x0d,0x14,0x2c,0x2c,0x0d,0x2c,0x0d,0x08,0x84,0x09,0x09,0x0d,0x0d,0x15,0x35,0x21,0x24,0x24,0x84,0x15,0x18,0x14,0x15,0x15,0x18,0x1d,0x1c,0x1c,0x18,0x08,0x18,0x01,0x18,0x1f,0x15,0x01,0x15,0x30,0x00,0x1c,0x1d,0x1d,0x2c,0x21,0x18,0x01,0x1e,0x0f,0x2a,0x24,0x27,0x95,0x15,0x0f,0x0d,0x04,0x12,0x16,0x09,0x1b, 0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x3f,0x33,0x33,0x33,0x33,0x33,0x2f,0x33,0x3f,0x01,0x2f,0x5d,0x33,0x5d,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x11,0x12,0x01,0x39,0x18,0x2f,0x33,0x2f,0xed,0x11,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x10,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x11,0x01,0x33,0x18,0x2f, 0xed,0x31,0x30,0x5d,0x01,0x14,0x07,0x03,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x37,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x35,0x34,0x27,0x27,0x37,0x17,0x16,0x15,0x14,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x13,0x36,0x35,0x34,0x27,0x03,0x33,0x13,0x16,0x04,0x3c,0x14,0xb8,0x13,0x01,0x10,0xa4, 0x10,0x01,0x14,0x03,0xfe,0x89,0x4a,0x2a,0x9f,0x08,0x81,0x04,0x15,0x63,0x53,0x90,0x3f,0x07,0x86,0x03,0x33,0x0d,0x13,0x01,0xac,0x97,0x15,0x01,0x0c,0xa4,0x0c,0x01,0x04,0x66,0x5d,0x5d,0xfc,0xa7,0x58,0x59,0x11,0x15,0xfe,0xad,0x01,0x53,0x15,0x08,0x35,0x85,0x14,0x6b,0x15,0xb4,0x26,0x26,0x02,0x64,0x13,0x09,0x17,0x0f,0x46,0x85, 0x5c,0x28,0x4d,0x1b,0x22,0xfd,0x7a,0x0e,0x0f,0x35,0x05,0x73,0x02,0xc2,0x62,0x4f,0x08,0x1e,0x01,0x69,0xfe,0x97,0x1e,0x00,0x00,0x01,0x00,0x28,0xfe,0x25,0x04,0x4e,0x04,0x00,0x00,0x27,0x00,0x6f,0x40,0x3c,0x02,0x00,0x00,0x84,0x27,0x25,0x14,0x27,0x27,0x25,0x27,0x25,0x0f,0x1c,0x1e,0x1e,0x84,0x17,0x19,0x14,0x17,0x17,0x19,0x1b, 0x1a,0x1a,0x19,0x19,0x17,0x0f,0x0b,0x84,0x0c,0x0c,0x06,0x08,0x84,0x11,0x0f,0x00,0x27,0x19,0x95,0x1c,0x0f,0x67,0x25,0x01,0x25,0x1e,0x21,0x95,0x17,0x11,0x06,0x02,0x14,0x16,0x0c,0x1b,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0xed,0x32,0x32,0x5d,0x3f,0xed,0xd4,0xc4,0x01,0x2f,0x33,0xed,0x32,0x33,0x2f,0xed,0x10,0xcc,0x32,0x11,0x33, 0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xcd,0x32,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x31,0x30,0x01,0x03,0x06,0x07,0x06,0x07,0x07,0x06,0x15,0x14,0x17,0x13,0x23,0x03,0x26,0x35,0x34,0x37,0x07,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x23,0x37,0x21,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x13,0x04,0x4e,0x99, 0x14,0x42,0x27,0x50,0x7e,0x06,0x01,0x14,0xa4,0x14,0x01,0x01,0x53,0x4b,0x29,0x9f,0x08,0x8c,0xc7,0x1d,0x01,0x6e,0xae,0x03,0x33,0x0f,0x11,0x01,0x7b,0x37,0x0a,0x96,0x04,0x00,0xfd,0x26,0x5d,0x31,0x1c,0x16,0x23,0x28,0x24,0x37,0x14,0xfe,0x79,0x01,0x87,0x14,0x34,0x0d,0x12,0x17,0x15,0xb4,0x27,0x25,0x02,0x8e,0x8b,0xfc,0xc4,0x0e, 0x0f,0x35,0x05,0x6e,0x10,0x31,0x02,0xda,0x00,0x02,0x00,0x59,0xff,0xe7,0x07,0x24,0x06,0x04,0x00,0x35,0x00,0x43,0x00,0xcc,0x40,0x71,0x43,0x36,0x2e,0x2f,0x30,0x42,0x30,0x0e,0x0f,0x20,0x21,0x22,0x0d,0x86,0x22,0x01,0x65,0x22,0x01,0x0d,0x22,0x22,0x84,0x42,0x30,0x14,0x42,0x42,0x30,0x3a,0x30,0x01,0x08,0x30,0x18,0x30,0x02,0x30, 0x42,0x38,0x3b,0x3b,0x84,0x29,0x2c,0x14,0x29,0x2c,0x78,0x2c,0x01,0x6a,0x2c,0x01,0x08,0x2c,0x01,0x2c,0x29,0x42,0x03,0x00,0x84,0x07,0x17,0x15,0x15,0x84,0x1a,0x18,0x14,0x1a,0x1a,0x18,0x04,0x07,0x07,0x1a,0x1a,0x18,0x42,0x0d,0x09,0x95,0x30,0x34,0x01,0x42,0x3b,0x3e,0x95,0x29,0x22,0x26,0x16,0x17,0x18,0x15,0x38,0x36,0x95,0x2c, 0x2e,0x2e,0x20,0x1a,0x1d,0x95,0x15,0x0f,0x03,0x12,0x10,0x00,0x3f,0xce,0x33,0x33,0xed,0x32,0x32,0x33,0x2f,0x33,0xed,0x32,0x3f,0xc4,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0x33,0xed,0x32,0x01,0x2f,0xcc,0x32,0x11,0x33,0x2f,0x33,0x87,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x18,0x10,0xed,0x32,0x10,0xdc,0x32,0x5d,0x5d,0x5d,0x87,0x2b,0x7d, 0x10,0xc4,0x11,0x01,0x33,0x5d,0x5d,0x87,0x18,0x10,0x2b,0x7d,0x10,0xc4,0x01,0x5d,0x5d,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x10,0x87,0x0e,0xc4,0x05,0xc4,0xc4,0x0e,0xc4,0x31,0x30,0x01,0x14,0x07,0x07,0x23,0x37,0x36,0x35,0x34,0x23,0x22,0x07,0x05,0x06,0x07,0x03,0x25,0x36,0x33,0x32,0x15,0x14,0x07,0x03,0x23,0x13,0x36,0x35, 0x34,0x23,0x22,0x07,0x05,0x03,0x06,0x07,0x05,0x06,0x23,0x22,0x35,0x34,0x37,0x13,0x36,0x37,0x25,0x37,0x36,0x37,0x25,0x36,0x33,0x32,0x01,0x05,0x06,0x07,0x03,0x06,0x15,0x14,0x33,0x32,0x37,0x25,0x36,0x37,0x07,0x24,0x08,0x0e,0xa8,0x14,0x03,0x33,0x0d,0x13,0xfe,0x89,0x37,0x0a,0x40,0x01,0x77,0x4a,0x2a,0x9f,0x08,0xa5,0xa7,0xaa, 0x03,0x33,0x0d,0x13,0xfe,0x54,0x6c,0x20,0xae,0xfe,0x90,0x55,0x1f,0x9f,0x08,0x69,0x20,0xad,0x02,0x12,0x25,0x1e,0xaf,0x01,0x76,0x53,0x21,0x9f,0xfc,0x68,0xfe,0x23,0x37,0x0a,0x6b,0x03,0x33,0x0f,0x13,0x01,0x6f,0x35,0x0b,0x05,0x50,0x27,0x25,0x41,0x64,0x0f,0x0e,0x35,0x05,0x63,0x0e,0x33,0xfe,0xc8,0x6b,0x15,0xb4,0x26,0x26,0xfc, 0xe8,0x03,0x3b,0x0f,0x0e,0x35,0x05,0x73,0xfe,0x02,0x95,0x2b,0x5b,0x15,0xb4,0x27,0x25,0x01,0xeb,0x94,0x2c,0x86,0xb8,0x93,0x2d,0x5f,0x15,0xfd,0x8d,0x7e,0x0e,0x33,0xfd,0xf2,0x0f,0x0e,0x35,0x05,0x5f,0x0e,0x33,0x00,0x00,0x01,0x00,0xaa,0xff,0xe8,0x06,0x3a,0x05,0x9a,0x00,0x25,0x00,0x70,0x40,0x4b,0x98,0x21,0x01,0x98,0x20,0x01, 0x3a,0x20,0x01,0x29,0x20,0x01,0x94,0x1c,0x01,0x86,0x1c,0x01,0x25,0x1c,0x35,0x1c,0x02,0x87,0x1b,0x97,0x1b,0x02,0x48,0x14,0x01,0x49,0x13,0x01,0x45,0x0e,0x01,0x57,0x0e,0x01,0x07,0x7e,0x00,0x08,0x01,0x08,0x03,0x0c,0x25,0x7e,0x10,0x23,0x20,0x23,0x30,0x23,0x03,0x23,0x23,0x27,0x18,0x7e,0x16,0x24,0x18,0x03,0x1e,0x91,0x11,0x13, 0x03,0x91,0x0c,0x08,0x12,0x00,0x3f,0xde,0xed,0x3f,0xed,0x3f,0xc4,0x01,0x2f,0xed,0x12,0x39,0x2f,0x5d,0xfd,0x32,0x32,0xdc,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x06,0x07,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14, 0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x05,0x25,0x03,0x04,0x83,0x99,0x99,0x47,0x5a,0x1a,0x66,0x8e,0xb1,0x65,0x83,0xd0,0x91,0x4e,0xa8,0x3b,0x6c,0x98,0x5d,0x5a,0x93,0x69,0x39,0xa8,0x02,0x44,0x23,0x40,0x1f,0x03,0x9f,0x9d,0x83,0x83,0x53,0x5c,0x01,0x53,0x7c,0x53,0x29,0x49,0x91,0xda,0x91,0x03,0x6d,0xfc,0x9e,0x6e,0xa6, 0x6e,0x37,0x35,0x6b,0x9f,0x6b,0x03,0x71,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0x07,0x05,0xb2,0x00,0x11,0x00,0x7a,0x40,0x51,0x37,0x10,0x01,0xa8,0x10,0xb8,0x10,0x02,0x56,0x10,0x01,0x45,0x10,0x01,0x58,0x0e,0x01,0x4a,0x0e,0x01,0x26,0x05,0x01,0x97,0x05,0xa7,0x05,0x02,0x34,0x05,0x01,0x26,0x05,0x01,0x99,0x03,0x01,0x3a,0x03,0x01, 0xc0,0x08,0x01,0x08,0x00,0x7e,0x9f,0x01,0x01,0x01,0x01,0x13,0x07,0x0a,0x7e,0x8f,0x0c,0x01,0x0c,0x01,0x01,0x0f,0x08,0x91,0xaf,0x0a,0x01,0x9f,0x0a,0xdf,0x0a,0x02,0x0a,0x0a,0x0b,0x04,0x91,0x0f,0x04,0x0b,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0x5d,0x71,0xed,0x11,0x39,0x2f,0x01,0x2f,0x5d,0xed,0x32,0x12,0x39,0x2f,0x5d,0xfd, 0xc6,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x01,0x23,0x35,0x10,0x21,0x20,0x11,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x10,0x21,0x20,0x11,0x04,0xd5,0xa8,0xfe,0x93,0xfe,0x92,0x03,0xb5,0xfc,0x4b,0xa8,0x02,0x17,0x02,0x14,0x03,0x2a,0x47,0x01,0xaa,0xfe,0x47,0xfe,0xa8,0x98,0xfe,0x8e,0x03,0x6d, 0x02,0x45,0xfd,0xa4,0x00,0x02,0x00,0x5e,0x00,0x00,0x05,0x70,0x05,0xb2,0x00,0x10,0x00,0x19,0x00,0x76,0x40,0x4f,0x26,0x16,0x01,0xa7,0x14,0x01,0x26,0x14,0x01,0x3a,0x12,0x4a,0x12,0x02,0x28,0x12,0x01,0xa8,0x11,0x01,0xa8,0x0d,0x01,0x55,0x0d,0x01,0x3a,0x0a,0x4a,0x0a,0x5a,0x0a,0x03,0x3b,0x06,0x4b,0x06,0x5b,0x06,0x03,0x00,0x00, 0x1b,0x0f,0x01,0x7d,0x18,0x04,0x04,0x1b,0x15,0x7d,0x0f,0x08,0x1f,0x08,0x02,0x08,0x0f,0x18,0x91,0x01,0xaf,0x04,0x01,0x9f,0x04,0xdf,0x04,0x02,0x04,0x04,0x03,0x13,0x91,0x0b,0x04,0x03,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0x5d,0x71,0x33,0xed,0x32,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x11,0x39,0x2f,0x31,0x30, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x11,0x23,0x11,0x21,0x20,0x00,0x35,0x10,0x00,0x21,0x32,0x00,0x15,0x11,0x21,0x00,0x26,0x23,0x20,0x03,0x12,0x21,0x21,0x11,0x05,0x70,0xfe,0xfc,0xa8,0xfe,0x9d,0xfe,0xfd,0xff,0x00,0x01,0x19,0x01,0x03,0xe8,0x01,0x0a,0x01,0x04,0xfe,0x54,0xaf,0xa7,0xfe,0xa2,0x0a,0x0a, 0x01,0x63,0x01,0x51,0x01,0x72,0xfe,0x8e,0x01,0x72,0x01,0x2a,0xf0,0x01,0x04,0x01,0x22,0xfe,0xde,0xfe,0xfe,0x78,0x02,0x43,0xdb,0xfe,0x6a,0xfe,0x78,0x01,0x84,0x00,0x00,0x01,0x00,0x78,0x00,0x00,0x05,0x94,0x05,0xb2,0x00,0x11,0x00,0x62,0x40,0x3e,0x96,0x0e,0x01,0x35,0x0e,0x01,0x26,0x0e,0x01,0x29,0x0c,0x01,0x98,0x0c,0x01,0x3a, 0x0c,0x01,0x29,0x0c,0x01,0x49,0x03,0x01,0x46,0x03,0x56,0x03,0x02,0xa7,0x01,0x01,0x49,0x01,0x59,0x01,0x02,0x07,0x05,0x08,0x7e,0x0a,0x0a,0x13,0x10,0x7e,0x11,0x11,0x11,0x0d,0x0a,0x06,0x91,0x08,0x08,0x02,0x0a,0x12,0x0d,0x91,0x02,0x04,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x11,0x12,0x39,0x2f,0x01,0x2f,0xed,0x12,0x39,0x2f, 0xfd,0x32,0xcd,0x31,0x30,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x13,0x10,0x21,0x20,0x11,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x10,0x21,0x20,0x11,0x15,0x23,0x78,0x02,0x14,0x02,0x17,0xf1,0xf1,0xa8,0xfe,0x92,0xfe,0x93,0xa8,0x03,0x56,0x02,0x5c,0xfd,0xbb,0xfe,0x9d,0x98,0xfe,0x8e,0x03,0x62,0x01,0xb9,0xfe,0x56, 0x47,0x00,0x00,0x01,0x00,0xaa,0xff,0xe8,0x05,0x07,0x05,0x9a,0x00,0x11,0x00,0x64,0x40,0x3e,0x99,0x0e,0x01,0x3a,0x0e,0x01,0x26,0x0c,0x01,0xa7,0x0c,0x01,0x95,0x0c,0x01,0x34,0x0c,0x01,0x26,0x0c,0x01,0x4a,0x03,0x01,0xa8,0x01,0x01,0x45,0x01,0x01,0x09,0x09,0x13,0x11,0x7e,0x9f,0x10,0x01,0x10,0x10,0x13,0x07,0x0a,0x7e,0x8f,0x04, 0x01,0x04,0x10,0x10,0x02,0x0a,0x91,0x08,0x08,0x02,0x05,0x03,0x0d,0x91,0x02,0x13,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x01,0x2f,0x5d,0xed,0x32,0x12,0x39,0x2f,0x5d,0xed,0x11,0x39,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x01,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x21,0x15,0x21,0x11, 0x10,0x21,0x20,0x11,0x35,0x33,0x04,0xd5,0xfd,0xec,0xfd,0xe9,0xa8,0x03,0xb5,0xfc,0x4b,0x01,0x6e,0x01,0x6d,0xa8,0x02,0x44,0xfd,0xa4,0x02,0x45,0x03,0x6d,0xfe,0x8e,0x98,0xfe,0xa8,0xfe,0x47,0x01,0xaa,0x47,0x00,0x01,0x00,0x64,0xff,0x38,0x05,0x44,0x05,0xb2,0x00,0x29,0x00,0x8e,0x40,0x5c,0x55,0x1c,0x01,0x27,0x19,0x01,0x84,0x18, 0x01,0x8c,0x14,0x01,0x99,0x13,0x01,0x24,0x0d,0x01,0x15,0x0d,0x01,0x69,0x09,0x79,0x09,0x02,0x1b,0x09,0x01,0x68,0x08,0x78,0x08,0x02,0x6a,0x04,0x7a,0x04,0x02,0x38,0x04,0x48,0x04,0x02,0x91,0x1d,0x01,0x83,0x1d,0x01,0x54,0x1d,0x01,0x1d,0x00,0x1b,0x7d,0x04,0x02,0x06,0x06,0x23,0x7d,0x24,0x24,0x02,0x2b,0x10,0x7d,0x11,0x11,0x00, 0x7e,0x0f,0x02,0x01,0x02,0x11,0x11,0x04,0x0b,0x91,0x16,0x04,0x1d,0x04,0x91,0x00,0x24,0x02,0x00,0x12,0x00,0x3f,0xdd,0xc4,0x10,0xfd,0xc4,0x3f,0xed,0x11,0x39,0x2f,0x01,0x2f,0x5d,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed,0x33,0x2f,0x12,0x39,0xed,0x11,0x39,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x21,0x15,0x23,0x11,0x21,0x24,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x10,0x05,0x33,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e,0x02,0x23,0x01,0x0e,0xaa,0x01,0x99,0x02,0x6f,0x36,0x69,0x9b,0x66,0x63,0x98,0x67,0x36,0xb0,0x54,0x99,0xd8,0x83,0x88,0xdc,0x99,0x53, 0xfe,0x29,0xc5,0x55,0x78,0x4b,0x22,0xb0,0x12,0x2a,0x43,0x30,0xc8,0x01,0x60,0xe6,0x01,0xbb,0x62,0xaf,0x84,0x4d,0x3e,0x6f,0x9b,0x5d,0x81,0xd3,0x96,0x52,0x5b,0xa3,0xe4,0x88,0xfe,0x3d,0xed,0x37,0x60,0x80,0x49,0x2b,0x49,0x36,0x1e,0x00,0x00,0x01,0x00,0xbc,0xff,0x38,0x04,0x83,0x05,0x9a,0x00,0x13,0x00,0x2d,0x40,0x17,0x12,0x12, 0x06,0x7e,0x07,0x07,0x0d,0x15,0x10,0x13,0x7e,0x0d,0x12,0x91,0x10,0x10,0x0f,0x03,0x07,0x00,0x91,0x0d,0x12,0x00,0x3f,0xed,0xce,0x3f,0x3f,0xed,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xed,0x32,0x2f,0x31,0x30,0x25,0x21,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e,0x02,0x23,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x01,0x64,0x01,0xb3,0x55, 0x78,0x4b,0x22,0xb0,0x12,0x2a,0x43,0x30,0xfd,0xca,0xa8,0x03,0x1f,0xfc,0xe1,0x98,0x37,0x60,0x80,0x49,0x2b,0x49,0x36,0x1e,0x05,0x9a,0xfe,0x8e,0x98,0x00,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0x07,0x05,0xb2,0x00,0x0f,0x00,0x44,0x40,0x29,0xa8,0x0e,0x01,0x45,0x0e,0x01,0x4a,0x0c,0x01,0x25,0x05,0x35,0x05,0x02,0x2a,0x03,0x3a,0x03, 0x02,0x08,0x08,0x11,0x0f,0x7e,0x01,0x01,0x11,0x07,0x7e,0x0b,0x01,0x01,0x0a,0x04,0x91,0x0d,0x04,0x07,0x91,0x0a,0x12,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x10,0x21,0x20,0x11,0x11,0x21,0x15,0x21,0x11,0x10,0x21,0x20,0x11, 0x04,0xd5,0xa8,0xfe,0x93,0xfe,0x92,0x03,0xb5,0xfb,0xa3,0x02,0x17,0x02,0x14,0x03,0x2a,0x47,0x01,0xaa,0xfe,0x47,0xfd,0x36,0x98,0x03,0x6d,0x02,0x45,0xfd,0xa4,0x00,0x00,0x02,0x00,0xaa,0xff,0xe8,0x06,0x2b,0x05,0xb2,0x00,0x2c,0x00,0x3d,0x00,0xa0,0x40,0x6c,0x6a,0x3b,0x01,0x67,0x37,0x01,0x64,0x31,0x01,0x56,0x31,0x01,0x79,0x29, 0x01,0x78,0x28,0x01,0x99,0x24,0x01,0x88,0x24,0x01,0x7a,0x24,0x01,0x8a,0x23,0x9a,0x23,0x02,0x7b,0x23,0x01,0x86,0x1f,0x96,0x1f,0x02,0x75,0x1f,0x01,0x76,0x1e,0x01,0x46,0x14,0x01,0x49,0x10,0x01,0x97,0x08,0x01,0x86,0x07,0x96,0x07,0x02,0x25,0x07,0x35,0x07,0x02,0x16,0x07,0x01,0x98,0x03,0x01,0x2a,0x03,0x3a,0x03,0x02,0x1b,0x1a, 0x18,0x7e,0x2c,0x2e,0x2e,0x0c,0x3f,0x34,0x7e,0x26,0x0a,0x7e,0x0c,0x1b,0x2e,0x91,0x2c,0x18,0x18,0x39,0x05,0x91,0x12,0x04,0x39,0x91,0x21,0x21,0x0c,0x12,0x00,0x3f,0x33,0x2f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xc4,0xfd,0xc4,0x01,0x2f,0xfd,0xde,0xed,0x11,0x12,0x39,0x2f,0xc4,0xfd,0xcd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x15,0x21,0x15,0x21,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x35,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02, 0x17,0x32,0x3e,0x02,0x04,0x7d,0x3a,0x6b,0x95,0x5b,0x5c,0x95,0x6b,0x3a,0xa8,0x4f,0x95,0xd5,0x86,0x85,0xd4,0x94,0x4f,0x01,0x06,0xfe,0xfa,0x35,0x63,0x90,0x5b,0x53,0x89,0x62,0x35,0x3c,0x6d,0x97,0x5c,0xb2,0xb2,0x36,0x58,0x3d,0x21,0x18,0x31,0x49,0x31,0x34,0x52,0x38,0x1d,0x03,0x71,0x6a,0xa0,0x6b,0x35,0x37,0x6e,0xa6,0x6e,0xfc, 0x9e,0x03,0x6d,0x91,0xda,0x91,0x49,0x4b,0x97,0xe3,0x97,0x38,0x98,0xee,0x65,0xa0,0x6f,0x3c,0x3b,0x6a,0x92,0x56,0x5e,0x9d,0x70,0x3e,0xfe,0x7a,0xee,0x2a,0x49,0x64,0x3a,0x33,0x58,0x41,0x27,0x03,0x29,0x4b,0x67,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0x70,0x05,0x9a,0x00,0x10,0x00,0x19,0x00,0x6e,0x40,0x48,0x3a,0x18,0x4a,0x18, 0x9a,0x18,0x03,0x28,0x18,0x01,0x96,0x16,0x01,0x34,0x16,0x44,0x16,0x02,0x26,0x16,0x01,0x96,0x14,0x01,0x34,0x14,0x44,0x14,0x02,0x26,0x14,0x01,0x59,0x09,0x01,0x55,0x04,0x01,0x00,0x00,0x1b,0x0f,0x01,0x7e,0x0c,0x9f,0x11,0x01,0x11,0x11,0x1b,0x15,0x7d,0x0f,0x08,0x1f,0x08,0x02,0x08,0x12,0x01,0x91,0x0f,0x0c,0x0c,0x05,0x0d,0x03, 0x17,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0x33,0xed,0x32,0x11,0x39,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x11,0x14,0x00,0x23,0x20,0x00,0x11,0x34,0x00,0x21,0x21,0x11,0x33,0x11,0x21,0x01,0x11,0x21,0x20,0x03,0x12,0x21, 0x32,0x36,0x05,0x70,0xfe,0xfc,0xfe,0xf6,0xe8,0xfe,0xfd,0xfe,0xe7,0x01,0x00,0x01,0x03,0x01,0x63,0xa8,0x01,0x04,0xfe,0x54,0xfe,0xaf,0xfe,0x9d,0x0a,0x0a,0x01,0x5e,0xa7,0xaf,0x03,0x90,0xfe,0x78,0xfe,0xfe,0xde,0x01,0x22,0x01,0x04,0xf0,0x01,0x2a,0x01,0x72,0xfe,0x8e,0xfd,0xe4,0x01,0x84,0xfe,0x78,0xfe,0x6a,0xdb,0x00,0x00,0x01, 0x00,0xaa,0x00,0x00,0x04,0xd5,0x05,0x9a,0x00,0x1b,0x00,0x5e,0x40,0x3c,0x9c,0x0a,0x01,0x8a,0x0a,0x01,0x89,0x09,0x99,0x09,0x02,0x98,0x05,0x01,0x39,0x05,0x01,0x89,0x04,0x01,0x4b,0x04,0x01,0x39,0x04,0x01,0x2b,0x04,0x01,0x18,0x04,0x01,0x1b,0x7e,0x01,0x01,0x0e,0x1d,0x11,0x0c,0x7e,0x0e,0x36,0x11,0x01,0x15,0x11,0x25,0x11,0x02, 0x11,0x07,0x91,0x16,0x16,0x10,0x03,0x01,0x0d,0x12,0x00,0x3f,0xce,0x3f,0x39,0x2f,0xed,0x33,0x5d,0x5d,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x3e,0x03,0x33,0x32,0x1e,0x02, 0x15,0x04,0xd5,0xa8,0x2b,0x57,0x86,0x5b,0x5c,0x8c,0x5f,0x31,0xa8,0xa8,0x1d,0x4b,0x5e,0x71,0x42,0x85,0xc5,0x81,0x3f,0x01,0x3c,0xe7,0x6a,0xaa,0x75,0x3f,0x41,0x79,0xaf,0x6e,0xfd,0xec,0x05,0x9a,0xfe,0x45,0x21,0x3c,0x2c,0x1a,0x55,0xa2,0xec,0x97,0x00,0x01,0x00,0xbc,0xff,0x38,0x04,0x08,0x05,0x9a,0x00,0x0f,0x00,0x1f,0x40,0x0f, 0x09,0x7e,0x0a,0x0a,0x11,0x03,0x7e,0x00,0x02,0x03,0x0a,0x03,0x91,0x00,0x12,0x00,0x3f,0xed,0xce,0x3f,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x33,0x11,0x33,0x11,0x21,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e,0x02,0x23,0xbc,0xa8,0x01,0x6a,0x55,0x78,0x4b,0x22,0xb0,0x12,0x2a,0x43,0x30,0x05,0x9a,0xfa,0xfe,0x37,0x60,0x80,0x49, 0x2b,0x49,0x36,0x1e,0x00,0x01,0x00,0xbc,0xff,0xe8,0x05,0xc3,0x05,0x9a,0x00,0x1f,0x00,0x5a,0x40,0x38,0x94,0x1e,0x01,0x6a,0x15,0x7a,0x15,0x8a,0x15,0x03,0x59,0x15,0x01,0x84,0x11,0x01,0x65,0x11,0x75,0x11,0x02,0x56,0x11,0x01,0x9a,0x02,0x01,0x0d,0x7e,0x05,0x1a,0x7e,0x18,0x05,0x18,0x05,0x18,0x09,0x21,0x0c,0x07,0x7e,0x09,0x19, 0x06,0x91,0x0d,0x0f,0x0b,0x03,0x13,0x91,0x00,0x00,0x08,0x12,0x00,0x3f,0x33,0x2f,0xed,0x3f,0x3f,0xed,0xc4,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x22,0x2e,0x02,0x35,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e, 0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x04,0x23,0x5d,0x99,0x6c,0x3b,0xfe,0xde,0xa8,0xa8,0x01,0xc5,0x27,0x43,0x5b,0x35,0x35,0x5d,0x44,0x27,0xa3,0x3b,0x6d,0x9a,0x18,0x36,0x6d,0xa4,0x6d,0x01,0xcc,0xfc,0x98,0x05,0x9a,0xfe,0x66,0xfd,0xb6,0x51,0x7a,0x51,0x28,0x28,0x51,0x7a,0x51,0x02,0x4a,0xfd,0x9c,0x6d,0xa4,0x6d,0x36,0x00, 0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0x04,0x05,0xb2,0x00,0x1a,0x00,0x25,0x00,0xf0,0x40,0x33,0x76,0x21,0x01,0x79,0x25,0x01,0x26,0x22,0x76,0x22,0x02,0x3a,0x1f,0x01,0x86,0x1d,0x01,0x39,0x1d,0x01,0x45,0x17,0x55,0x17,0x02,0x05,0x17,0x15,0x17,0x25,0x17,0x03,0x98,0x04,0x01,0x38,0x02,0x88,0x02,0x02,0x89,0x1c,0x01,0x96,0x16,0xa6, 0x16,0xe6,0x16,0x03,0x15,0xb8,0xff,0xe0,0xb3,0x2e,0x31,0x48,0x15,0xb8,0xff,0xc0,0x40,0x6e,0x25,0x28,0x48,0x0c,0x15,0x0a,0x11,0x18,0x7d,0x6b,0x05,0x7b,0x05,0x8b,0x05,0x03,0x08,0x05,0x18,0x05,0x02,0x6b,0x1e,0x01,0x09,0x1e,0x19,0x1e,0x29,0x1e,0x03,0x1e,0x05,0x07,0x10,0x1b,0x20,0x1b,0x30,0x1b,0x03,0x1b,0x1b,0x03,0x27,0x0a, 0x7e,0x07,0x20,0x7d,0x0f,0x03,0x1f,0x03,0x02,0x03,0x1e,0x18,0x1a,0x1f,0x48,0x09,0x1e,0x01,0xe9,0x1e,0xf9,0x1e,0x02,0x1e,0x05,0x07,0x91,0x06,0x15,0x16,0x15,0x26,0x15,0x03,0xb9,0x15,0x01,0x15,0xb9,0x0c,0x01,0x0c,0xb0,0x0a,0xc0,0x0a,0xd0,0x0a,0x03,0x0a,0x0a,0x08,0x11,0x13,0x91,0x10,0x0e,0x04,0x08,0x03,0x23,0x91,0x00,0x13, 0x00,0x3f,0xed,0x3f,0x3f,0x33,0xed,0x32,0x10,0xcd,0x2f,0x5d,0x32,0x5d,0x32,0x71,0x72,0xed,0x32,0x32,0x5d,0x71,0x2b,0x01,0x2f,0x5d,0xed,0xd4,0xed,0x11,0x12,0x39,0x2f,0x5d,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0xfd,0xc4,0x12,0x39,0x39,0x2b,0x2b,0x31,0x30,0x00,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x05,0x20,0x00,0x11,0x10,0x37,0x26,0x27,0x11,0x33,0x15,0x16,0x17,0x36,0x21,0x32,0x17,0x15,0x26,0x23,0x26,0x07,0x16,0x00,0x11,0x10,0x00,0x13,0x10,0x24,0x27,0x06,0x11,0x14,0x16,0x33,0x36,0x36,0x02,0xc0,0xfe,0xf4,0xfe,0xaa,0xd4,0x63,0x71,0x9c,0x79,0x6c,0xed,0x01,0x42,0x86,0x70,0x7f,0x8a,0xad,0x84,0xe7,0x01,0x53,0xfe,0xbb, 0x95,0xfe,0x8e,0xe8,0xec,0xf7,0xb8,0xbd,0xda,0x18,0x01,0x4a,0x01,0x24,0x01,0x45,0xec,0x06,0x01,0x01,0x0c,0x79,0x01,0x0b,0x9d,0x10,0xb0,0x28,0x02,0x30,0x27,0xfe,0xd2,0xfe,0xde,0xfe,0xce,0xfe,0xa5,0x02,0x83,0x01,0x0c,0xef,0x0e,0xcb,0xfe,0xb9,0xea,0xf9,0x01,0xff,0x00,0x01,0x00,0xaa,0x00,0x00,0x04,0xd5,0x05,0x9a,0x00,0x17, 0x00,0x49,0x40,0x2d,0x4b,0x16,0x01,0x95,0x08,0x01,0x84,0x08,0x01,0x34,0x03,0x01,0x25,0x03,0x01,0x0c,0x7e,0x0a,0x0f,0x0f,0x19,0x01,0x7e,0x17,0x8e,0x0f,0x01,0x49,0x0f,0x01,0x2a,0x0f,0x3a,0x0f,0x02,0x0f,0x05,0x91,0x14,0x0e,0x12,0x0b,0x0f,0x01,0x03,0x00,0x3f,0x3f,0x3f,0xde,0xed,0x33,0x5d,0x5d,0x5d,0x01,0x2f,0xed,0x12,0x39, 0x2f,0xc4,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x11,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x11,0x23,0x11,0x0e,0x03,0x23,0x20,0x02,0x11,0xaa,0xa8,0xab,0xb7,0x51,0x8b,0x64,0x39,0xa8,0xa8,0x1b,0x50,0x63,0x71,0x3b,0xfe,0xf6,0xff,0x05,0x9a,0xfd,0xa1,0xd6,0xd4,0x34,0x6c,0xa6,0x73,0xb6,0xfc,0x00,0x01, 0x7f,0x1c,0x30,0x24,0x15,0x01,0x2e,0x01,0x2e,0x00,0x00,0x01,0x00,0x21,0xff,0x68,0x04,0x50,0x06,0x02,0x00,0x0d,0x00,0xa1,0x40,0x5e,0xa6,0x08,0xb6,0x08,0x02,0xa9,0x04,0x01,0xb8,0x04,0x01,0x08,0x07,0x08,0x09,0x07,0x7e,0x06,0x05,0x14,0x06,0x06,0x05,0x06,0x05,0x0b,0x04,0x03,0x04,0x7e,0x0a,0x0b,0x14,0x0a,0x04,0x05,0x0a,0x0b, 0x08,0x09,0x04,0x05,0x08,0x05,0x04,0x7e,0x09,0x08,0x14,0x09,0x08,0x04,0x09,0x09,0x0a,0x61,0x05,0x01,0xc1,0x05,0xd1,0x05,0xe1,0x05,0x03,0x05,0x0a,0x05,0x0a,0x03,0x0d,0x7e,0x00,0x00,0x0f,0x03,0x86,0x0a,0x01,0x48,0x05,0x01,0x07,0x05,0x09,0x0a,0x04,0x06,0x0b,0x91,0x03,0x00,0x02,0x12,0x00,0x3f,0xce,0x33,0xed,0x2f,0x17,0x39, 0x5d,0x5d,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x5d,0x71,0x11,0x33,0x10,0xc1,0x87,0x04,0x2b,0x10,0x01,0xc1,0x87,0x04,0x7d,0x10,0xc4,0x87,0x08,0x18,0x10,0x2b,0x87,0x05,0x7d,0xc4,0x11,0x01,0x33,0x87,0x18,0x10,0x2b,0x08,0x7d,0x10,0xc4,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x05,0x35,0x21,0x35,0x01,0x25,0x13, 0x17,0x07,0x05,0x15,0x01,0x21,0x11,0x03,0xa8,0xfc,0x79,0x02,0xb3,0xfe,0x8c,0x8c,0x95,0x46,0x01,0x6b,0xfd,0x76,0x03,0x34,0x98,0x98,0x2f,0x04,0x03,0xc2,0x01,0x0e,0x4e,0x86,0xba,0x1d,0xfc,0x41,0xfe,0xd0,0x00,0x02,0x00,0x5e,0xff,0xc6,0x05,0x38,0x05,0xb2,0x00,0x35,0x00,0x45,0x00,0xba,0x40,0x7a,0x39,0x34,0x49,0x34,0x59,0x34, 0x03,0x84,0x1f,0x01,0x9b,0x1a,0x01,0x86,0x14,0x01,0x7a,0x10,0x01,0x28,0x10,0x01,0x69,0x0f,0x79,0x0f,0x02,0x56,0x09,0x01,0x37,0x09,0x47,0x09,0x02,0x9d,0x2b,0x01,0x7c,0x2b,0x8c,0x2b,0x02,0x2b,0x2a,0x2a,0x91,0x25,0x01,0x64,0x25,0x74,0x25,0x84,0x25,0x03,0x30,0x25,0x36,0x22,0x7e,0x9e,0x3c,0x01,0x8d,0x3c,0x01,0x7e,0x3c,0x01, 0x6b,0x3c,0x01,0x3c,0x0a,0x36,0x10,0x0d,0x20,0x0d,0x02,0x0d,0x0d,0x47,0x36,0x7e,0x00,0x17,0x7e,0x18,0x18,0x0f,0x00,0x1f,0x00,0x02,0x00,0x3c,0x25,0x39,0x41,0x18,0x18,0x12,0x30,0x0a,0x33,0x05,0x91,0x41,0x39,0x91,0x33,0x2a,0x2b,0x2b,0x33,0x13,0x12,0x91,0x1d,0x04,0x00,0x3f,0xed,0x3f,0x33,0x2f,0x33,0x10,0xfd,0xde,0xed,0x11, 0x39,0x39,0x11,0x39,0x2f,0x11,0x12,0x39,0x39,0x01,0x2f,0x5d,0x33,0x2f,0xed,0x10,0xed,0x12,0x39,0x2f,0x5d,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0xed,0x11,0x39,0x39,0x5d,0x5d,0x32,0x2f,0x33,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x36,0x36,0x35,0x34,0x2e,0x02, 0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x02,0x07,0x1e,0x03,0x17,0x07,0x2e,0x03,0x27,0x06,0x04,0x23,0x22,0x26,0x37,0x14,0x16,0x33,0x36,0x36,0x37,0x2e,0x03,0x23,0x22,0x0e,0x02,0x5e,0x05,0x31,0x5f,0x8e,0x61,0x3f,0x7c,0x78,0x73,0x35,0x41,0x48,0x34,0x67,0x9c,0x69,0x63,0x98,0x67,0x36,0xb0, 0x54,0x99,0xd7,0x84,0x89,0xdb,0x9a,0x52,0x5d,0x53,0x14,0x40,0x45,0x42,0x17,0x73,0x18,0x42,0x46,0x43,0x18,0x74,0xfe,0xff,0x91,0xa9,0xb3,0xa6,0x5b,0x5b,0x6d,0xb5,0x51,0x23,0x4e,0x57,0x5d,0x30,0x38,0x50,0x34,0x18,0xf8,0x3f,0x67,0x49,0x29,0x18,0x2a,0x38,0x1f,0x4f,0xcb,0x8a,0x63,0xb8,0x8f,0x56,0x3f,0x70,0x9d,0x5d,0x81,0xd4, 0x97,0x54,0x63,0xae,0xed,0x8a,0xa7,0xfe,0xfc,0x64,0x0f,0x37,0x3e,0x3c,0x13,0x82,0x16,0x3f,0x41,0x3a,0x12,0x57,0x69,0x92,0x7c,0x29,0x3d,0x01,0x41,0x33,0x12,0x23,0x1c,0x12,0x12,0x1f,0x29,0x00,0x00,0x01,0x00,0x78,0x00,0x00,0x05,0x94,0x05,0xb2,0x00,0x0f,0x00,0x56,0x40,0x38,0x96,0x0c,0x01,0x24,0x0c,0x34,0x0c,0x02,0x98,0x0a, 0x01,0x2a,0x0a,0x3a,0x0a,0x02,0xa8,0x03,0x01,0x57,0x03,0x01,0x45,0x03,0x01,0xa7,0x01,0x01,0x49,0x01,0x59,0x01,0x02,0x06,0x05,0x7e,0xc0,0x09,0x01,0x09,0x09,0x11,0x0e,0x7e,0x0f,0x0e,0x0e,0x02,0x05,0x91,0x08,0x12,0x0b,0x91,0x02,0x04,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x01,0x2f,0xed,0x12,0x39,0x2f,0x5d,0xfd,0xcd,0x31, 0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x10,0x21,0x20,0x11,0x11,0x33,0x15,0x21,0x11,0x10,0x21,0x20,0x11,0x15,0x23,0x78,0x02,0x14,0x02,0x17,0xf1,0xfe,0x67,0xfe,0x92,0xfe,0x93,0xa8,0x03,0x56,0x02,0x5c,0xfd,0xbb,0xfd,0x2b,0x98,0x03,0x62,0x01,0xb9,0xfe,0x56,0x97,0x00,0x00,0x02,0x00,0x62,0x00,0x00,0x05,0x3a, 0x05,0x9a,0x00,0x13,0x00,0x1b,0x00,0x7d,0x40,0x51,0x78,0x17,0x01,0x36,0x12,0x01,0x07,0x12,0x17,0x12,0x02,0x44,0x11,0x84,0x11,0x94,0x11,0x03,0x29,0x03,0x39,0x03,0x02,0x19,0x10,0x14,0x4a,0x04,0x7a,0x04,0x8a,0x04,0x9a,0x04,0x04,0x04,0x09,0x01,0x0d,0x0d,0x00,0x7e,0x15,0x15,0x1d,0x14,0x7e,0x01,0x06,0x06,0x01,0x19,0x20,0x24, 0x2a,0x48,0x19,0x20,0x17,0x1e,0x48,0x19,0x04,0x06,0x91,0x10,0x09,0xd0,0x07,0x01,0x07,0x07,0x01,0x0d,0x91,0x0c,0x03,0x14,0x91,0x01,0x12,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x5d,0x33,0x33,0xed,0x32,0x32,0x2b,0x2b,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x32,0x2f,0x12,0x39,0x39,0x5d,0x12,0x39,0x39,0x31,0x30, 0x71,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x11,0x10,0x37,0x26,0x23,0x35,0x20,0x17,0x36,0x21,0x33,0x15,0x23,0x22,0x07,0x04,0x00,0x11,0x01,0x21,0x11,0x10,0x24,0x27,0x06,0x11,0x05,0x3a,0xfb,0x82,0xca,0x59,0xcb,0x01,0x47,0x76,0xf7,0x01,0x56,0xce,0xe1,0xd4,0xa9,0x01,0x07,0x01,0x57,0xfc,0x2a,0x03,0x2e,0xfe,0xa6,0xfd,0xd7,0x02,0x10, 0x01,0x45,0xe7,0x07,0x9b,0x0f,0xcb,0x98,0x53,0x2c,0xfe,0xde,0xfe,0xce,0xfe,0x69,0x01,0x8d,0x01,0x0f,0xe4,0x18,0xd3,0xfe,0xbf,0x00,0x00,0x01,0x00,0xaa,0xff,0xe8,0x05,0xd0,0x05,0x9a,0x00,0x0f,0x00,0x57,0x40,0x39,0x29,0x0e,0x39,0x0e,0x02,0x96,0x0c,0x01,0x25,0x0c,0x35,0x0c,0x02,0x4a,0x07,0x5a,0x07,0xda,0x07,0x03,0xc8,0x05, 0x01,0xa9,0x05,0x01,0x46,0x05,0x01,0xb7,0x0c,0x01,0x02,0x03,0x7e,0x30,0x0f,0x01,0x0f,0x0f,0x11,0x0a,0x7e,0xb0,0x08,0x01,0x08,0x09,0x03,0x0d,0x91,0x06,0x13,0x03,0x91,0x00,0x03,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xfd,0xcd,0x31,0x30,0x00,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01, 0x21,0x15,0x23,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x10,0x21,0x20,0x11,0x04,0x2d,0x01,0xa3,0xfb,0xfd,0xdf,0xfd,0xf6,0xa8,0x01,0x74,0x01,0x67,0x05,0x9a,0x98,0xfd,0x42,0xfd,0xa4,0x02,0x45,0x03,0x6d,0xfc,0x9e,0xfe,0x47,0x01,0xaa,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0x4d,0x05,0xb2,0x00,0x3f,0x00,0x9b,0x40,0x63,0x49,0x3e, 0x01,0x33,0x10,0x10,0x13,0x48,0x6a,0x33,0x01,0x57,0x2d,0x01,0x67,0x29,0x77,0x29,0x02,0x56,0x29,0x01,0x46,0x24,0x56,0x24,0x02,0x84,0x20,0x01,0x87,0x1f,0x01,0xaa,0x1a,0x01,0x98,0x1a,0x01,0x7a,0x1a,0x8a,0x1a,0x02,0x63,0x14,0x01,0x79,0x10,0x01,0x6b,0x10,0x01,0x79,0x0f,0x01,0x25,0x06,0x22,0x7e,0x0d,0x0d,0x2b,0x7e,0x00,0x00, 0x18,0x41,0x36,0x7e,0x35,0x35,0x18,0x06,0x06,0x17,0x7e,0x18,0x26,0x25,0x06,0x18,0x18,0x12,0x08,0x91,0x06,0x36,0x06,0x36,0x12,0x3b,0x91,0x30,0x13,0x12,0x91,0x1d,0x04,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x39,0x2f,0x2f,0xed,0x11,0x39,0x2f,0x11,0x39,0x39,0x01,0x2f,0xed,0x33,0x2f,0x11,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed, 0x33,0x2f,0xed,0x11,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x2b,0x5d,0x01,0x34,0x2e,0x02,0x23,0x21,0x35,0x21,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22, 0x2e,0x02,0x27,0x33,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xa5,0x3b,0x70,0xa3,0x69,0xfe,0xac,0x01,0x4e,0x5e,0x93,0x60,0x30,0x26,0x45,0x60,0x3a,0x34,0x61,0x4a,0x2c,0xa6,0x4b,0x79,0x9c,0x51,0x51,0x9a,0x79,0x49,0x9a,0x90,0x48,0x84,0x62,0x38,0x55,0x8f,0xba,0x64,0x5c,0xb0,0x8a,0x55,0x02,0xa6,0x30,0x57,0x7c,0x4b,0x41,0x7a, 0x5f,0x39,0x01,0x87,0x46,0x69,0x47,0x23,0x8b,0x21,0x42,0x63,0x42,0x3d,0x5c,0x3d,0x1e,0x1b,0x36,0x50,0x34,0x58,0x84,0x58,0x2c,0x2d,0x57,0x7f,0x53,0x8e,0xb6,0x28,0x04,0x05,0x34,0x5a,0x7b,0x48,0x67,0xa0,0x6e,0x39,0x27,0x54,0x86,0x60,0x34,0x50,0x37,0x1c,0x24,0x47,0x67,0x00,0x00,0x01,0xff,0xf6,0xff,0xe8,0x05,0x1c,0x05,0x9a, 0x00,0x0f,0x00,0x54,0x40,0x38,0x29,0x0c,0x39,0x0c,0x49,0x0c,0x99,0x0c,0x04,0x97,0x0a,0x01,0x25,0x0a,0x35,0x0a,0x45,0x0a,0x03,0x46,0x03,0x56,0x03,0x02,0xd7,0x03,0x01,0x58,0x03,0x01,0x56,0x01,0x01,0x0f,0x7e,0x10,0x0e,0x01,0x0e,0x0e,0x11,0x08,0x7e,0x06,0x04,0x0e,0x0e,0x02,0x05,0x91,0x07,0x03,0x0b,0x91,0x02,0x13,0x00,0x3f, 0xed,0x3f,0xed,0x12,0x39,0x2f,0x01,0x2f,0xce,0xed,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x20,0x11,0x11,0x23,0x35,0x21,0x11,0x10,0x21,0x20,0x11,0x35,0x33,0x05,0x1c,0xfd,0xec,0xfd,0xe9,0xfb,0x01,0xa3,0x01,0x6e,0x01,0x6d,0xa8,0x02,0x44,0xfd,0xa4,0x02,0x45,0x02,0xd5,0x98,0xfc, 0x9e,0xfe,0x47,0x01,0xaa,0xab,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0xf6,0x05,0xba,0x00,0x23,0x00,0xa4,0x40,0x69,0x97,0x22,0x01,0x98,0x1e,0x01,0x99,0x19,0x01,0x38,0x19,0x48,0x19,0x02,0x9b,0x18,0x01,0x94,0x14,0x01,0x85,0x09,0x01,0x76,0x09,0x01,0x27,0x09,0x01,0x87,0x08,0x01,0x84,0x02,0x01,0x55,0x02,0x01,0x47,0x02,0x01,0x01, 0x20,0x21,0x23,0x21,0x00,0x21,0x7e,0x22,0x23,0x14,0x22,0x22,0x23,0x00,0x9f,0x20,0x01,0x8c,0x20,0x01,0x71,0x01,0x01,0x64,0x01,0x01,0x20,0x01,0x21,0x23,0x23,0x11,0x7e,0x10,0x10,0x20,0x10,0x02,0x10,0x10,0x1b,0x25,0x22,0x21,0x21,0x06,0x7e,0x0f,0x1b,0x1f,0x1b,0x02,0x1b,0x00,0x11,0x00,0x11,0x22,0x04,0x0b,0x91,0x16,0x13,0x00, 0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x12,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x33,0x87,0x04,0x10,0x2b,0x87,0x7d,0xc4,0x10,0xc4,0xc4,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x25,0x0e,0x03,0x15,0x14,0x1e,0x02, 0x33,0x32,0x3e,0x02,0x35,0x33,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x25,0x37,0x01,0x04,0xb8,0xfe,0x92,0x88,0xd4,0x93,0x4d,0x37,0x6a,0x9b,0x64,0x63,0x98,0x67,0x36,0xb0,0x54,0x99,0xd7,0x84,0x86,0xdb,0x9b,0x54,0x43,0x7e,0xb6,0x73,0xfe,0x8b,0x27,0x03,0xe5,0x04,0x14,0x66,0x15,0x6b,0x99,0xbd,0x69,0x61, 0xa3,0x76,0x42,0x3f,0x70,0x9d,0x5d,0x7d,0xd3,0x9a,0x56,0x4f,0x96,0xd7,0x88,0x6c,0xcf,0xae,0x84,0x22,0x6c,0x93,0xfe,0xed,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0x25,0x05,0xb2,0x00,0x19,0x00,0x3f,0x40,0x28,0x3b,0x12,0x4b,0x12,0x02,0x86,0x0a,0x96,0x0a,0x02,0x95,0x09,0x01,0x86,0x09,0x01,0x25,0x09,0x01,0x99,0x05,0x01,0x2a,0x05, 0x01,0x19,0x7e,0x01,0x01,0x1b,0x0c,0x7e,0x0e,0x07,0x91,0x14,0x04,0x01,0x0d,0x12,0x00,0x3f,0xc4,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x05,0x25,0xa8,0x39,0x69, 0x93,0x5a,0x5d,0x98,0x6c,0x3b,0xa8,0x4e,0x91,0xd0,0x83,0x88,0xd9,0x97,0x51,0x03,0x71,0x6a,0xa0,0x6b,0x35,0x37,0x6e,0xa6,0x6e,0xfc,0x9e,0x03,0x6d,0x91,0xda,0x91,0x49,0x4b,0x97,0xe3,0x97,0x00,0x00,0x01,0x00,0x5e,0x00,0x00,0x04,0xf6,0x05,0xb2,0x00,0x23,0x00,0x9a,0x40,0x63,0x46,0x1e,0x56,0x1e,0x96,0x1e,0x03,0x93,0x19,0x01, 0x45,0x18,0x01,0x9c,0x14,0x01,0x38,0x14,0x01,0x86,0x0d,0x01,0x89,0x09,0x01,0x3a,0x09,0x01,0x01,0x20,0x21,0x23,0x21,0x00,0x21,0x7e,0x22,0x23,0x14,0x22,0x22,0x23,0x99,0x22,0x01,0x22,0x21,0x21,0x81,0x20,0x91,0x20,0x02,0x34,0x20,0x74,0x20,0x02,0x20,0x23,0x1b,0x7e,0x6d,0x01,0x01,0x01,0x23,0x10,0x06,0x20,0x06,0x30,0x06,0x03, 0x06,0x06,0x11,0x25,0x00,0x23,0x23,0x10,0x7e,0x0f,0x11,0x1f,0x11,0x02,0x11,0x00,0x10,0x00,0x10,0x22,0x12,0x0b,0x91,0x16,0x04,0x00,0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0x5d,0x12,0x39,0x5d,0xed,0x11,0x39,0x5d,0x5d,0x32,0x2f,0x33,0x5d,0x87,0x04,0x10,0x2b,0x87,0x7d,0xc4, 0x10,0xc4,0xc4,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x05,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x05,0x07,0x01,0x9c,0x01,0x6e,0x88,0xd4,0x93,0x4d,0x37,0x6a,0x9b,0x64,0x63,0x98,0x67,0x36,0xb0,0x54,0x99,0xd7,0x84,0x86, 0xdb,0x9b,0x54,0x43,0x7e,0xb6,0x73,0x01,0x75,0x27,0xfc,0x1b,0x01,0xa6,0x66,0x15,0x65,0x91,0xb8,0x69,0x61,0x9f,0x71,0x3e,0x3f,0x70,0x9d,0x5d,0x7d,0xd3,0x9a,0x56,0x4b,0x91,0xd3,0x88,0x6c,0xc9,0xa7,0x7e,0x22,0x6c,0x93,0x01,0x13,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x05,0x89,0x05,0xb2,0x00,0x1c,0x00,0x58,0x40,0x38,0x7a,0x19, 0x01,0x68,0x19,0x01,0x1a,0x19,0x01,0x96,0x11,0x01,0x85,0x11,0x01,0x27,0x11,0x01,0x25,0x10,0x01,0x2a,0x0c,0x01,0x8b,0x0b,0x9b,0x0b,0x02,0x29,0x0b,0x01,0x16,0x03,0x01,0x13,0x7e,0x15,0x00,0x06,0x7e,0x08,0x1b,0x7e,0x00,0x08,0x08,0x01,0x00,0x15,0x12,0x1b,0x01,0x91,0x0e,0x04,0x00,0x3f,0xed,0x32,0x3f,0xce,0x11,0x39,0x2f,0x01, 0x2f,0xed,0xde,0xed,0x10,0xde,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x11,0x0e,0x03,0x15,0x15,0x23,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x11,0x02,0xaf,0x52,0x8e,0x69,0x3c,0xa8,0x5b,0xa8,0xed,0x92,0x92,0xee,0xa9,0x5c,0xa8,0x3c,0x6a,0x90,0x54, 0x01,0x59,0x03,0xbc,0x0b,0x47,0x74,0x9f,0x62,0x74,0x7f,0x91,0xe0,0x99,0x4f,0x52,0x9e,0xe9,0x97,0xfc,0xbe,0x03,0x5d,0x5f,0x9a,0x71,0x45,0x0a,0xfc,0x43,0x00,0x02,0x00,0x64,0xff,0x38,0x05,0x44,0x05,0xb2,0x00,0x28,0x00,0x3a,0x00,0xb7,0x40,0x79,0x95,0x37,0x01,0x47,0x37,0x01,0x93,0x36,0x01,0x94,0x33,0x01,0x55,0x32,0x95,0x32, 0x02,0x45,0x2d,0x01,0x36,0x2d,0x01,0x2b,0x2b,0x8b,0x2b,0x02,0x68,0x2a,0x78,0x2a,0x02,0x94,0x27,0x01,0x94,0x24,0x01,0x36,0x24,0x01,0x89,0x1e,0x01,0x8a,0x1d,0x01,0x8a,0x1b,0x01,0x5a,0x19,0x01,0x80,0x28,0x90,0x28,0x02,0x61,0x28,0x71,0x28,0x02,0x50,0x28,0x01,0x04,0x28,0x01,0x28,0x0c,0x39,0x7e,0x16,0x4f,0x10,0x01,0x3b,0x10, 0x01,0x29,0x10,0x01,0x10,0x0e,0x16,0x05,0x7e,0x06,0x06,0x26,0x7e,0x29,0x16,0x29,0x16,0x29,0x20,0x3c,0x0c,0x7e,0x0e,0x0e,0x2f,0x7e,0x20,0x39,0x10,0x2c,0x91,0x23,0x04,0x28,0x10,0x91,0x0c,0x06,0x0e,0x0c,0x12,0x00,0x3f,0xdd,0xc4,0x10,0xfd,0xc4,0x3f,0xed,0x11,0x39,0x01,0x2f,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x39,0x2f,0x2f, 0x10,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x5d,0x5d,0x5d,0x10,0xed,0x11,0x39,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e,0x02,0x23,0x21,0x15,0x23,0x11,0x21,0x36,0x37,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35, 0x34,0x00,0x33,0x20,0x00,0x11,0x10,0x05,0x01,0x34,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x36,0x04,0x0a,0x55,0x78,0x4b,0x22,0xb0,0x12,0x2a,0x43,0x30,0xfd,0x29,0xaa,0x01,0x93,0x50,0x2f,0x35,0x41,0x1d,0x14,0x2c,0x45,0x30,0x43,0x88,0x6e,0x45,0x01,0x18,0xea,0x01,0x08,0x01,0x34,0xfe,0x26,0x01,0x2a,0xcf, 0xbd,0xa4,0xae,0x2d,0x4d,0x64,0x37,0x3d,0x63,0x44,0x25,0xc0,0x98,0x37,0x60,0x80,0x49,0x2b,0x49,0x36,0x1e,0xc8,0x01,0x60,0x1d,0x1b,0x1e,0x3b,0x38,0x17,0x20,0x34,0x2c,0x27,0x13,0x1a,0x48,0x66,0x8a,0x5c,0xc0,0x01,0x12,0xfe,0xb3,0xfe,0xe3,0xfe,0x42,0xf2,0x02,0xa1,0xd6,0x01,0x0c,0xc3,0x78,0x33,0x5b,0x4e,0x3d,0x15,0x18,0x39, 0x47,0x56,0x33,0xae,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0xc6,0x05,0xb2,0x00,0x11,0x00,0x6a,0x40,0x46,0xd9,0x0a,0xf9,0x0a,0x02,0xa8,0x0a,0x01,0x46,0x0a,0x01,0x09,0x08,0x01,0x59,0x08,0x01,0x4a,0x08,0x01,0x97,0x03,0x01,0x25,0x03,0x35,0x03,0x02,0xb7,0x01,0x01,0x29,0x01,0x39,0x01,0x02,0x70,0x0e,0x01,0x0e,0x0c,0x0f,0x7e,0x30, 0x11,0x70,0x11,0x02,0x11,0x11,0x13,0x04,0x7e,0xb0,0x06,0x01,0x06,0x0d,0x91,0x0f,0x0f,0x06,0x02,0x91,0x09,0x03,0x11,0x11,0x06,0x12,0x00,0x3f,0x33,0x2f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xfd,0x32,0xcd,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x01,0x10,0x21,0x20, 0x11,0x11,0x23,0x11,0x10,0x21,0x20,0x11,0x15,0x33,0x15,0x23,0x11,0x23,0x04,0x2d,0xfe,0x99,0xfe,0x8c,0xa8,0x02,0x0a,0x02,0x21,0xf1,0xf1,0xa8,0x03,0x71,0x01,0xaa,0xfe,0x47,0xfc,0x9e,0x03,0x6d,0x02,0x45,0xfd,0xa4,0x3d,0x98,0xfd,0x7f,0x00,0x01,0x00,0xaa,0xff,0xe8,0x05,0x25,0x05,0x9a,0x00,0x19,0x00,0x3f,0x40,0x28,0x99,0x14, 0x01,0x2a,0x14,0x01,0x95,0x10,0x01,0x86,0x10,0x01,0x25,0x10,0x01,0x87,0x0f,0x97,0x0f,0x02,0x3b,0x07,0x4b,0x07,0x02,0x19,0x7e,0x17,0x17,0x1b,0x0c,0x7e,0x0a,0x18,0x0c,0x03,0x12,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xc4,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23, 0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x05,0x25,0x51,0x97,0xd9,0x88,0x83,0xd0,0x91,0x4e,0xa8,0x3b,0x6c,0x98,0x5d,0x5a,0x93,0x69,0x39,0xa8,0x02,0x44,0x97,0xe3,0x97,0x4b,0x49,0x91,0xda,0x91,0x03,0x6d,0xfc,0x9e,0x6e,0xa6,0x6e,0x37,0x35,0x6b,0x9f,0x6b,0x03,0x71,0x00,0x00,0x01, 0x00,0x5e,0x00,0x00,0x05,0x7a,0x05,0x9a,0x00,0x11,0x00,0x57,0x40,0x36,0x9e,0x10,0x01,0x4b,0x10,0x01,0x93,0x06,0x01,0x84,0x06,0x01,0x35,0x03,0x01,0x26,0x03,0x01,0x0a,0x08,0x7e,0x0c,0x06,0x06,0x13,0x01,0x7e,0x11,0x0b,0x4a,0x0d,0x5a,0x0d,0x02,0x3b,0x0d,0x01,0x2d,0x0d,0x01,0x1b,0x0d,0x01,0x0d,0x04,0x91,0x0f,0x09,0x91,0x0c, 0x12,0x01,0x07,0x03,0x00,0x3f,0xce,0x3f,0xed,0xde,0xed,0x33,0x5d,0x5d,0x5d,0x5d,0x01,0x2f,0x2f,0xed,0x12,0x39,0x2f,0xc4,0xfd,0xce,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x11,0x10,0x21,0x20,0x11,0x11,0x33,0x11,0x33,0x15,0x21,0x11,0x06,0x23,0x20,0x11,0x5e,0xa8,0x01,0x6d,0x01,0x6e,0xa8,0xf1,0xfe,0x67,0x84, 0xeb,0xfd,0xec,0x04,0x5e,0xfe,0xf1,0xfe,0x56,0x01,0xb9,0x02,0x3c,0xfa,0xfe,0x98,0x01,0x93,0x85,0x02,0x5c,0x00,0x00,0x01,0x00,0x64,0xff,0xe8,0x04,0xb5,0x05,0xb2,0x00,0x3a,0x00,0xba,0x40,0x7a,0x75,0x2e,0x01,0x56,0x2e,0x66,0x2e,0x02,0x5b,0x2a,0x01,0x86,0x24,0x96,0x24,0x02,0x75,0x24,0x01,0x66,0x24,0x01,0x75,0x23,0x01,0x67, 0x23,0x01,0x89,0x1e,0x99,0x1e,0x02,0x89,0x1a,0x01,0x4a,0x1a,0x01,0x7a,0x15,0x01,0x69,0x14,0x01,0x5a,0x11,0x01,0x33,0x0e,0x01,0x88,0x08,0x01,0x08,0x10,0x0d,0x10,0x48,0x49,0x07,0x01,0x73,0x03,0x01,0x65,0x03,0x01,0x65,0x02,0x75,0x02,0x02,0x26,0x7e,0x27,0x27,0x12,0x36,0x31,0x00,0x7e,0x17,0x1c,0x60,0x12,0x01,0x12,0x12,0x3c, 0x31,0x7e,0x1c,0x0b,0x7e,0x0a,0x0a,0x60,0x1c,0x01,0x1c,0x27,0x27,0x36,0x2c,0x36,0x10,0x21,0x0b,0x0b,0x17,0x10,0x17,0x05,0x2c,0x91,0x21,0x04,0x10,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x2f,0x01,0x2f,0x5d,0x33,0x2f,0xed,0x10,0xed,0x12,0x39,0x2f,0x5d,0x12,0x39, 0xed,0x11,0x39,0x11,0x33,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x2b,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x33,0x14,0x1e,0x02,0x33,0x20,0x11,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e, 0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x04,0xb5,0x5a,0x97,0xc6,0x6c,0x67,0xc8,0x9e,0x61,0xb1,0x45,0x6e,0x88,0x44,0x01,0x71,0x33,0x59,0x7a,0x48,0x6d,0xbf,0x8e,0x53,0x3f,0x7a,0xb1,0x72,0x5a,0xae,0x89,0x55,0xb0,0x29,0x4f,0x75,0x4b,0x48,0x6f,0x4c,0x27,0x38,0x62,0x81,0x48,0x6c,0xb9,0x87,0x4c,0x01,0x85, 0x75,0x9e,0x60,0x2a,0x2f,0x67,0xa3,0x74,0x4e,0x6a,0x41,0x1d,0x01,0x06,0x49,0x5e,0x3a,0x22,0x0d,0x14,0x3b,0x60,0x8e,0x68,0x55,0x8b,0x63,0x35,0x2b,0x5f,0x99,0x6f,0x38,0x5c,0x42,0x24,0x20,0x3b,0x52,0x33,0x43,0x5b,0x3c,0x25,0x0c,0x13,0x37,0x5f,0x92,0x00,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0x25,0x05,0xb2,0x00,0x0d,0x00,0x4f, 0x40,0x33,0x46,0x0c,0x01,0x33,0x0c,0x01,0x4b,0x0a,0x01,0x3d,0x0a,0x01,0x94,0x05,0x01,0x85,0x05,0x01,0x26,0x05,0x01,0x17,0x05,0x01,0x89,0x03,0x99,0x03,0x02,0x18,0x03,0x28,0x03,0x02,0x0d,0x7e,0x01,0x01,0x0f,0x06,0x7e,0x08,0x00,0x00,0x07,0x04,0x91,0x0b,0x04,0x07,0x12,0x00,0x3f,0x3f,0xed,0x11,0x39,0x2f,0x01,0x2f,0xed,0x12, 0x39,0x2f,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x35,0x10,0x21,0x20,0x11,0x11,0x23,0x11,0x10,0x21,0x20,0x11,0x05,0x25,0xa8,0xfe,0x6b,0xfe,0x6a,0xa8,0x02,0x3f,0x02,0x3c,0x02,0xc6,0xab,0x01,0xaa,0xfe,0x47,0xfc,0x9e,0x03,0x6d,0x02,0x45,0xfd,0xa4,0x00,0x02,0x00,0x90,0xff,0xe8,0x04,0xdf, 0x05,0xb2,0x00,0x2f,0x00,0x43,0x00,0x9f,0x40,0x67,0x59,0x2d,0x01,0x48,0x29,0x01,0x26,0x24,0x01,0x79,0x1e,0x01,0x68,0x1e,0x01,0x59,0x1e,0x01,0x5a,0x1d,0x01,0x76,0x18,0x01,0x67,0x18,0x01,0x56,0x18,0x01,0x66,0x14,0x76,0x14,0x02,0x64,0x0c,0x74,0x0c,0x84,0x0c,0x03,0x66,0x0b,0x76,0x0b,0x02,0x6a,0x07,0x01,0x7b,0x06,0x8b,0x06, 0x02,0x6c,0x06,0x01,0x01,0x10,0x04,0x0e,0x7e,0x30,0x30,0x16,0x7e,0x50,0x2b,0x01,0x2b,0x2b,0x04,0x45,0x21,0x7e,0x20,0x20,0x3a,0x7e,0x04,0x2f,0x2f,0x04,0x11,0x10,0x2e,0x3f,0x3f,0x01,0x91,0x21,0x2e,0x2e,0x35,0x26,0x91,0x1b,0x13,0x35,0x91,0x09,0x04,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xce,0xed,0x32,0x2f,0x11,0x39,0x39, 0x01,0x2f,0x33,0x2f,0x10,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x5d,0xed,0x33,0x2f,0xed,0x11,0x39,0x39,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x10,0x05,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x27,0x33,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x21,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x3e,0x03,0xcc,0xbf,0x43,0x45,0x51,0x83,0xa6,0x56,0x55,0xa4,0x82,0x50,0xfe,0xf0,0x49,0x7b,0x5a,0x33,0x5d,0x99,0xc7,0x6a,0x6c,0xc6,0x98,0x5c,0x02,0xa8,0x35,0x64,0x8e,0x5a,0x48,0x89, 0x6c,0x41,0xd1,0xdc,0xfe,0x42,0x03,0x2a,0x30,0x50,0x6a,0x39,0x3f,0x6d,0x4f,0x2d,0x2a,0x4d,0x6c,0x42,0x42,0x6c,0x4e,0x2a,0x03,0x29,0x32,0x93,0x64,0x5b,0x85,0x56,0x2a,0x28,0x57,0x87,0x5a,0xfe,0xed,0x51,0x04,0x05,0x31,0x57,0x7b,0x4e,0x6d,0xa1,0x6a,0x34,0x34,0x6a,0xa1,0x6d,0x43,0x6c,0x4b,0x28,0x20,0x43,0x68,0x48,0x8c,0x8d, 0x01,0x95,0x3a,0x5b,0x3e,0x21,0x23,0x3f,0x5b,0x37,0x40,0x61,0x41,0x22,0x01,0x03,0x23,0x41,0x5f,0x00,0x00,0x01,0x00,0xaa,0x00,0x00,0x05,0xb2,0x05,0x9a,0x00,0x1a,0x00,0x57,0x40,0x34,0x9a,0x08,0x01,0x79,0x08,0x89,0x08,0x02,0x98,0x07,0x01,0x9a,0x03,0x01,0x3d,0x03,0x4d,0x03,0x02,0x2b,0x03,0x01,0x00,0x19,0x7e,0x01,0x01,0x0c, 0x1c,0x0f,0x0a,0x7e,0x0c,0x1a,0x91,0x01,0x26,0x0f,0x01,0x0f,0x14,0x91,0x05,0x01,0x05,0x01,0x05,0x0b,0x0e,0x03,0x0b,0x12,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x32,0x5d,0x10,0xed,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0xfd,0xcd,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x35,0x34,0x26,0x23,0x22, 0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x33,0x05,0xb2,0xfe,0x7b,0xb7,0xb6,0x57,0x88,0x5e,0x31,0xa8,0xa8,0x21,0x49,0x58,0x6b,0x42,0x78,0xbb,0x84,0x4d,0x0b,0xe2,0x01,0xe6,0x47,0xd5,0xe9,0x41,0x79,0xaf,0x6e,0xfd,0xec,0x05,0x9a,0xfe,0x45,0x21,0x3c,0x2c,0x1a,0x44,0x84,0xc0,0x7c,0x00,0x03, 0x00,0x5e,0x00,0x00,0x05,0xf8,0x05,0x9a,0x00,0x14,0x00,0x1d,0x00,0x26,0x00,0x87,0x40,0x5a,0x29,0x22,0x01,0x29,0x1e,0x01,0x26,0x19,0x01,0x26,0x15,0x01,0x68,0x12,0x78,0x12,0x02,0x68,0x0e,0x78,0x0e,0x02,0x67,0x07,0x77,0x07,0x02,0x67,0x04,0x77,0x04,0x02,0x17,0x7d,0x0f,0x10,0x01,0x10,0x10,0x0b,0x20,0x7d,0x90,0x06,0x01,0x00, 0x06,0xc0,0x06,0x02,0x06,0x06,0x25,0x02,0x09,0x7e,0x1b,0x14,0x10,0x0b,0xc0,0x0b,0xd0,0x0b,0xf0,0x0b,0x04,0x0b,0x0b,0x27,0x28,0x1b,0x25,0x91,0x0c,0x09,0x40,0x12,0x16,0x48,0x09,0x0b,0x12,0x24,0x1c,0x91,0x02,0x14,0x00,0x03,0x00,0x3f,0xdd,0x32,0xed,0x32,0x3f,0xdd,0x2b,0x32,0xed,0x32,0x11,0x12,0x01,0x39,0x2f,0x5d,0x33,0x33, 0xed,0x32,0x32,0x32,0x2f,0x5d,0x71,0xed,0x11,0x33,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x33,0x15,0x04,0x17,0x16,0x15,0x14,0x00,0x21,0x15,0x23,0x35,0x20,0x27,0x26,0x35,0x34,0x37,0x36,0x25,0x01,0x06,0x15,0x14,0x17,0x16,0x33,0x11,0x06,0x01,0x36,0x35,0x34,0x27,0x26,0x27,0x11,0x32,0x02,0xd7, 0xa8,0x01,0x0d,0xb6,0xb6,0xfe,0x94,0xfe,0xf3,0xa8,0xfe,0xf2,0xb5,0xb6,0xb6,0xb5,0x01,0x0e,0xfe,0xab,0x74,0x74,0x73,0xe2,0xe2,0x02,0xdf,0x74,0x74,0x74,0xe1,0xe1,0x05,0x9a,0x8c,0x01,0xa3,0xa3,0xfb,0xfd,0xfe,0xb9,0x88,0x88,0xa3,0xa4,0xfd,0xfb,0xa3,0xa3,0x01,0xfe,0xe6,0x7f,0xab,0xa9,0x80,0x7f,0x03,0x52,0x01,0xfd,0x2e,0x80, 0xa9,0xab,0x7f,0x7f,0x01,0xfc,0xae,0x00,0x00,0x02,0x00,0x14,0x00,0x00,0x04,0xe1,0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0xbe,0x40,0x87,0x39,0x20,0x49,0x20,0x59,0x20,0x99,0x20,0x04,0xe4,0x1e,0x01,0xa6,0x1e,0xb6,0x1e,0x02,0x94,0x1e,0x01,0x36,0x1e,0x46,0x1e,0x56,0x1e,0x03,0xe7,0x1a,0x01,0xa6,0x1a,0x01,0x94,0x1a,0x01,0x35,0x1a, 0x45,0x1a,0x55,0x1a,0x03,0x99,0x18,0x01,0x3a,0x18,0x4a,0x18,0x5a,0x18,0x03,0x06,0x10,0x01,0x5b,0x0c,0x01,0x49,0x0c,0x01,0xe8,0x0c,0x01,0xaa,0x0c,0xba,0x0c,0x02,0x56,0x0a,0x01,0xe7,0x0a,0x01,0x14,0x01,0x7e,0x1c,0x7d,0x04,0x07,0x04,0x15,0x15,0x0e,0x7e,0x16,0x10,0x16,0x01,0x00,0x16,0x10,0x16,0x20,0x16,0x03,0x04,0x16,0x04, 0x16,0x23,0x06,0x19,0x91,0x0b,0x26,0x1f,0x91,0x59,0x13,0x69,0x13,0x02,0x13,0x0f,0x11,0x01,0xbf,0x11,0xcf,0x11,0xdf,0x11,0x03,0x11,0x07,0x15,0x91,0x04,0x01,0x03,0x12,0x00,0x3f,0xdd,0x32,0xfd,0x32,0xde,0x5d,0x71,0x32,0x5d,0xed,0x3f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x71,0x10,0xed,0x32,0x2f,0x11,0x33,0x10,0xed, 0xed,0x32,0x31,0x30,0x5d,0x71,0x5d,0x5d,0x71,0x71,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x21,0x15,0x23,0x35,0x23,0x35,0x33,0x11,0x34,0x00,0x33,0x32,0x00,0x15,0x14,0x02,0x23,0x22,0x27,0x15,0x21,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xe1,0xfc,0xb8,0xa8,0xdd,0xdd,0x01, 0x0b,0xe7,0xee,0x01,0x10,0xf8,0xee,0xda,0x88,0x03,0x48,0xa8,0x9f,0xab,0xa6,0xb0,0xac,0xaa,0xab,0x9f,0x98,0x98,0x98,0x98,0x02,0x8a,0xdf,0x01,0x19,0xfe,0xdf,0xe7,0xe8,0xfe,0xe8,0x77,0xf1,0x02,0x80,0xa8,0xd0,0xd3,0xa1,0xa6,0xda,0xd3,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x17,0x00,0x82,0x40,0x61, 0x1a,0x17,0x01,0xc8,0x13,0x01,0x0a,0x13,0x1a,0x13,0x02,0xc6,0x11,0x01,0x05,0x11,0x15,0x11,0x02,0x85,0x0d,0xc5,0x0d,0x02,0x04,0x0d,0x14,0x0d,0x02,0xc9,0x0b,0x01,0x56,0x0b,0x66,0x0b,0x96,0x0b,0x03,0xd7,0x07,0x01,0x55,0x07,0x65,0x07,0x95,0x07,0x03,0xc6,0x05,0x01,0x59,0x05,0x69,0x05,0x99,0x05,0x03,0xc6,0x01,0x01,0x5a,0x01, 0x6a,0x01,0x9a,0x01,0x03,0x09,0x7d,0x00,0x15,0x10,0x15,0x30,0x15,0x03,0x15,0x15,0x19,0x0f,0x7d,0x0f,0x03,0x1f,0x03,0x02,0x03,0x0c,0x91,0x06,0x04,0x12,0x91,0x00,0x13,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d, 0x05,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x02,0xfe,0xfe,0xcf,0xfe,0x91,0x01,0x76,0x01,0x42,0x01,0x29,0x01,0x6b,0xfe,0x8c,0xfe,0xd4,0xe2,0xfe,0xe6,0x01,0x13,0xdd,0xec,0x01,0x10,0xfe,0xf8,0x18,0x01,0x92,0x01,0x42,0x01,0x5a,0x01,0x9c,0xfe,0x70, 0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0x05,0x32,0xfe,0xba,0xfe,0xf7,0xfe,0xf7,0xfe,0xbd,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0x00,0x03,0x00,0x86,0xff,0xe8,0x05,0x45,0x05,0x9a,0x00,0x1f,0x00,0x2a,0x00,0x35,0x00,0x82,0x40,0x54,0x3a,0x28,0x4a,0x28,0x02,0x29,0x28,0x01,0x7c,0x23,0x01,0x69,0x23,0x01,0x4a,0x23,0x01,0x39,0x23,0x01, 0x95,0x1d,0x01,0x99,0x14,0x01,0x45,0x0e,0x95,0x0e,0x02,0x24,0x0e,0x34,0x0e,0x02,0x05,0x0e,0x15,0x0e,0x02,0x96,0x0d,0x01,0x55,0x03,0x01,0x57,0x02,0x01,0x16,0x7e,0x2b,0x11,0x00,0x7e,0x20,0x25,0x1b,0x7e,0x11,0x0a,0x7e,0x0b,0x30,0x11,0x0b,0x0b,0x26,0x11,0x11,0x25,0x05,0x31,0x91,0x1b,0x30,0x1a,0x03,0x10,0x26,0x91,0x05,0x13, 0x00,0x3f,0xed,0x32,0x3f,0x39,0x39,0xed,0x11,0x39,0x39,0x11,0x12,0x39,0x2f,0x01,0x2f,0xc4,0xde,0xed,0x10,0xfd,0xc4,0xdc,0xed,0x10,0xdc,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x33,0x14,0x1e,0x02,0x17,0x11,0x2e,0x03,0x35,0x34,0x36, 0x33,0x33,0x11,0x1e,0x03,0x07,0x34,0x2e,0x02,0x27,0x11,0x3e,0x03,0x01,0x14,0x1e,0x02,0x17,0x11,0x22,0x0e,0x02,0x05,0x45,0x59,0x9f,0xdb,0x82,0x88,0xe3,0xa4,0x5b,0xb1,0x36,0x61,0x84,0x4e,0x6d,0x9c,0x63,0x2f,0xd0,0xcb,0xa8,0x80,0xbf,0x7f,0x3f,0xb0,0x29,0x53,0x7d,0x54,0x4b,0x7b,0x57,0x30,0xfd,0x20,0x29,0x43,0x54,0x2b,0x40, 0x5a,0x38,0x19,0x01,0xe9,0x86,0xc2,0x7d,0x3c,0x44,0x86,0xc6,0x81,0x4d,0x82,0x63,0x3d,0x06,0x02,0xde,0x1a,0x3e,0x4b,0x5a,0x35,0x7a,0x8c,0xfe,0x3f,0x1e,0x61,0x7f,0x9b,0x57,0x3f,0x64,0x50,0x40,0x1b,0xfd,0x4f,0x09,0x33,0x57,0x7c,0x02,0xff,0x21,0x30,0x23,0x1a,0x0a,0x01,0x04,0x10,0x1c,0x28,0x00,0x00,0x01,0x00,0x00,0x04,0x90, 0x00,0xca,0x06,0x1c,0x00,0x0d,0x00,0x50,0x40,0x15,0x0c,0x18,0x22,0x25,0x48,0x0c,0x18,0x09,0x13,0x48,0x08,0x18,0x22,0x25,0x48,0x08,0x18,0x09,0x13,0x48,0x05,0xb8,0xff,0xe8,0xb3,0x1d,0x21,0x48,0x01,0xb8,0xff,0xf0,0x40,0x17,0x1d,0x21,0x48,0x00,0x06,0x03,0xc4,0x10,0x0a,0x20,0x0a,0x30,0x0a,0x03,0x0a,0x00,0xc5,0x40,0x0d,0xc0, 0x06,0xc5,0x07,0x00,0x2f,0xed,0x1a,0xde,0x1a,0xed,0x01,0x2f,0x5d,0xfd,0xce,0x32,0x31,0x30,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x13,0x22,0x06,0x15,0x14,0x16,0x33,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0xca,0x30,0x40,0x40,0x30,0x54,0x76,0x76,0x54,0x05,0xcb,0x41,0x34,0x34,0x41,0x51,0x6c,0x5a,0x5a,0x6c,0x00,0x01,0x00,0x00,0x04,0x8a, 0x00,0xe1,0x06,0x03,0x00,0x0e,0x00,0x25,0x40,0x0b,0x01,0x18,0x09,0x0d,0x48,0x00,0x03,0xfb,0x09,0x01,0x01,0xb8,0xff,0xc0,0xb7,0x09,0x0d,0x48,0x01,0x03,0x0c,0xaf,0x06,0x2f,0xe1,0x39,0xc4,0x2b,0x00,0x3f,0xfd,0xc4,0x31,0x30,0x2b,0x11,0x35,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x5e,0x14,0x34,0x3e, 0x3a,0x30,0x35,0x42,0x71,0x04,0x8a,0x49,0x05,0x62,0x02,0x38,0x2a,0x2b,0x3a,0x49,0x38,0x60,0x93,0x00,0x00,0x01,0x00,0x00,0x04,0xc2,0x01,0x35,0x06,0x0a,0x00,0x03,0x00,0x22,0x40,0x11,0x78,0x03,0x88,0x03,0x98,0x03,0x03,0x03,0x40,0x00,0x80,0x01,0x40,0x02,0x03,0x80,0x02,0x00,0x2f,0x1a,0xcd,0x01,0x2f,0x1a,0xcd,0x1a,0xdd,0x1a, 0xcd,0x31,0x30,0x5d,0x01,0x03,0x23,0x13,0x01,0x35,0xb6,0x7f,0x8f,0x06,0x0a,0xfe,0xb8,0x01,0x48,0x00,0x00,0x01,0x00,0x00,0x04,0x3e,0x01,0x92,0x06,0x03,0x00,0x1d,0x00,0x13,0xb6,0x03,0x1b,0x1b,0x0d,0x13,0x00,0x0f,0x00,0x2f,0xcc,0x01,0x2f,0xcd,0x33,0x2f,0xcd,0x30,0x31,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x0e,0x03,0x15, 0x14,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x35,0x34,0x27,0x01,0x86,0x04,0x08,0x1a,0x2d,0x3c,0x22,0x1a,0x2c,0x21,0x12,0x08,0x71,0x04,0x07,0x59,0x48,0x18,0x2d,0x23,0x15,0x08,0x06,0x03,0x0f,0x30,0x13,0x23,0x38,0x2e,0x25,0x10,0x0c,0x19,0x1d,0x24,0x16,0x17,0x22,0x0f,0x2f,0x14,0x45,0x5b,0x1d,0x0a,0x19,0x1f,0x25, 0x16,0x17,0x22,0x00,0x00,0x01,0x00,0x00,0x04,0xc2,0x01,0x35,0x06,0x0a,0x00,0x03,0x00,0x31,0xb7,0x77,0x03,0x87,0x03,0x97,0x03,0x03,0x03,0xb8,0xff,0xf8,0x40,0x12,0x18,0x1c,0x48,0x01,0x40,0x00,0x80,0x03,0x40,0x50,0x02,0x60,0x02,0x02,0x02,0x03,0x80,0x01,0x00,0x2f,0x1a,0xcd,0x01,0x2f,0x5d,0x1a,0xcd,0x1a,0xdd,0x1a,0xcd,0x31, 0x30,0x2b,0x5d,0x01,0x23,0x03,0x33,0x01,0x35,0x7f,0xb6,0xa8,0x04,0xc2,0x01,0x48,0x00,0x01,0x00,0x00,0x04,0x76,0x02,0x29,0x06,0x1c,0x00,0x2d,0x00,0xa0,0xb5,0x2a,0x08,0x11,0x14,0x48,0x26,0xb8,0xff,0xf8,0x40,0x4f,0x11,0x14,0x48,0x2a,0x1c,0x01,0x1c,0x10,0x11,0x14,0x48,0x06,0x12,0x16,0x12,0x02,0x19,0x07,0x11,0x01,0x2a,0x09, 0x0d,0x01,0x08,0x0c,0x01,0x39,0x0c,0x10,0x19,0x1f,0x48,0x07,0x03,0x17,0x03,0x27,0x03,0x03,0x3e,0x00,0x7f,0x2d,0x8f,0x2d,0x02,0x2d,0x2d,0x16,0x0a,0x9f,0x23,0xaf,0x23,0x02,0x23,0x40,0x09,0x0c,0x48,0x23,0x16,0x10,0x17,0x20,0x17,0x30,0x17,0x03,0x17,0x00,0x00,0x0f,0xc0,0x05,0x01,0x05,0x28,0xb8,0xff,0xc0,0x40,0x12,0x15,0x1a, 0x48,0x28,0x17,0xaf,0x0f,0xbf,0x0f,0xcf,0x0f,0x03,0x0f,0xc0,0x1e,0x01,0x1e,0x17,0xb8,0x01,0x3a,0x00,0x3f,0xdc,0x71,0xcd,0x71,0x10,0xd4,0x2b,0xcd,0x71,0x11,0x39,0x2f,0x01,0x2f,0x5d,0xcd,0xdc,0x2b,0x71,0xcd,0x11,0x39,0x2f,0x71,0xcd,0x31,0x30,0x5e,0x5d,0x2b,0x5e,0x5d,0x5d,0x5e,0x5d,0x5e,0x5d,0x2b,0x5d,0x2b,0x2b,0x01,0x14, 0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x15,0x23,0x34,0x3e,0x04,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x01,0x37,0x07,0x10,0x1b,0x14,0x15,0x1f,0x14,0x09,0x16,0x24,0x30,0x19,0x32,0x4b,0x35,0x23,0x13,0x08,0x5b,0x09,0x1a,0x2e,0x4a,0x69,0x47,0x2e,0x51,0x3c,0x23,0x18, 0x2d,0x40,0x27,0x2a,0x3c,0x28,0x13,0x05,0x4f,0x0e,0x1e,0x19,0x10,0x0e,0x18,0x1f,0x10,0x1a,0x2b,0x1e,0x11,0x20,0x36,0x45,0x4a,0x49,0x1f,0x20,0x57,0x5e,0x5c,0x48,0x2d,0x1e,0x36,0x4a,0x2c,0x23,0x3f,0x2e,0x1b,0x1b,0x2f,0x3d,0x21,0x00,0x00,0x01,0x00,0x00,0x04,0xb7,0x02,0xce,0x06,0x1c,0x00,0x06,0x00,0x2a,0x40,0x16,0xa5,0x01, 0xb5,0x01,0xc5,0x01,0x03,0x96,0x01,0x01,0x01,0x06,0x04,0x00,0x00,0x02,0x04,0x00,0x06,0x05,0x01,0x04,0x00,0x2f,0xdd,0x32,0xcd,0x32,0x01,0x2f,0xcd,0x39,0x2f,0x12,0x39,0x39,0x5d,0x5d,0x31,0x30,0x01,0x07,0x21,0x15,0x21,0x35,0x01,0x01,0x60,0xc9,0x02,0x37,0xfd,0x32,0x01,0x11,0x05,0xd1,0xd5,0x45,0x45,0x01,0x20,0x00,0x00,0x01, 0x00,0x90,0xff,0xe8,0x06,0x3e,0x04,0x00,0x00,0x1f,0x00,0x91,0x40,0x63,0x9c,0x1e,0x01,0x09,0x1e,0x19,0x1e,0x29,0x1e,0x03,0x57,0x1c,0x01,0x98,0x1b,0x01,0xc8,0x1a,0x01,0x9c,0x1a,0x01,0x07,0x0e,0x17,0x0e,0x02,0xf7,0x0e,0x01,0x36,0x0e,0x01,0x66,0x0c,0xe6,0x0c,0xf6,0x0c,0x03,0x55,0x0c,0x01,0x27,0x0c,0x37,0x0c,0x02,0x66,0x0c, 0x76,0x0c,0x86,0x0c,0x03,0x36,0x06,0x01,0x56,0x04,0x01,0x66,0x04,0x76,0x04,0x86,0x04,0x03,0x01,0x84,0x1f,0x08,0x15,0x15,0x12,0x84,0x10,0x1b,0x0a,0x84,0x08,0x08,0x20,0x21,0x16,0x0d,0x0d,0x1b,0x05,0x95,0x18,0x1d,0x16,0x14,0x0f,0x11,0x09,0x00,0x0f,0x00,0x3f,0x32,0x32,0x3f,0x3f,0x33,0xed,0x32,0x32,0x11,0x33,0x11,0x12,0x01, 0x39,0x2f,0xed,0x33,0xdc,0xed,0x33,0x2f,0x10,0xdc,0xed,0x31,0x30,0x5d,0x71,0x5d,0x5d,0x71,0x71,0x71,0x5d,0x5d,0x71,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x20,0x11,0x90,0xa4,0x69, 0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0xfe,0xae,0x04,0x00,0xfd,0xb4,0xaa,0x98,0xc0,0x86,0x02,0x48,0xfd,0xa0,0xfe,0xd2,0xb5,0x91,0x02,0x48,0xfc,0x00,0xa2,0xba,0x75,0x5f,0xd4,0x01,0xa1,0x00,0x01,0x00,0xa6,0xfe,0x29,0x04,0x2a,0x04,0x18,0x00,0x16,0x00,0x5a,0x40,0x3a,0x75,0x15, 0x01,0x05,0x14,0x15,0x14,0x25,0x14,0x75,0x14,0x85,0x14,0x95,0x14,0x06,0xe8,0x06,0xf8,0x06,0x02,0xc7,0x06,0xd7,0x06,0x02,0x69,0x03,0x01,0x09,0x09,0x18,0x16,0x84,0x01,0x01,0x18,0x0f,0x0b,0x07,0x84,0x0d,0x10,0x04,0x95,0x13,0x01,0x01,0x13,0x10,0x0e,0x0f,0x0d,0x1b,0x09,0x95,0x0b,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0x39,0x2f, 0x10,0xed,0x32,0x01,0x2f,0xed,0x32,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0x02,0xe0,0xfd,0x20,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0x01,0x30, 0x01,0x18,0x01,0x46,0xb9,0x8d,0xfe,0x50,0x98,0xfe,0x29,0x05,0xd7,0xaa,0xc2,0xd9,0xcd,0x00,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0xf2,0x04,0x18,0x00,0x14,0x00,0x21,0x00,0x72,0x40,0x4d,0xc9,0x21,0xd9,0x21,0x02,0x26,0x20,0x36,0x20,0x02,0xc9,0x1e,0xd9,0x1e,0x02,0x64,0x1e,0x01,0x45,0x1e,0x55,0x1e,0x02,0x44,0x1a,0x54,0x1a,0x02, 0x68,0x0d,0x01,0xa7,0x0c,0x01,0xca,0x09,0xda,0x09,0x02,0x02,0x00,0x13,0x84,0x16,0x12,0x20,0x04,0x01,0x04,0x04,0x23,0x1c,0x83,0x0f,0x0b,0x1f,0x0b,0x02,0x0b,0x12,0x0f,0x10,0x19,0x95,0x0e,0x10,0x05,0x1f,0x95,0x08,0x16,0x04,0x1b,0x00,0x95,0x02,0x15,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x01,0x2f,0x5d,0xed, 0x12,0x39,0x2f,0x5d,0x33,0x33,0xfd,0xce,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x15,0x23,0x11,0x23,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xf2,0xe2,0xa4,0x04,0x6b,0xf3,0xc1,0xe9,0x01, 0x00,0xd8,0xd2,0x5e,0x04,0xa4,0xa4,0xa5,0x7f,0x94,0xac,0xa6,0x83,0x90,0xab,0x98,0x98,0xfe,0x29,0x02,0x87,0xc8,0x01,0x13,0xed,0xff,0x01,0x31,0xa6,0x8e,0xfc,0x98,0x01,0x35,0x95,0x7e,0xae,0xdb,0xc7,0xb1,0xc9,0xc5,0x00,0x01,0x00,0xa6,0xfe,0x29,0x04,0xc3,0x04,0x18,0x00,0x16,0x00,0x5d,0x40,0x0b,0x28,0x11,0x01,0x76,0x11,0x86, 0x11,0x96,0x11,0x03,0x10,0xb8,0xff,0xe0,0x40,0x2f,0x10,0x14,0x48,0x05,0x10,0x15,0x10,0x25,0x10,0x03,0x86,0x06,0x96,0x06,0x02,0x28,0x03,0x01,0x68,0x03,0x01,0x14,0x00,0x12,0x84,0x01,0x01,0x18,0x0b,0x07,0x84,0x09,0x14,0x95,0x16,0x15,0x0c,0x04,0x95,0x0f,0x10,0x0a,0x0f,0x09,0x15,0x01,0x1b,0x00,0x3f,0x3f,0x3f,0x3f,0xed,0x32, 0x3f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xfd,0x32,0xce,0x31,0x30,0x5d,0x71,0x71,0x5d,0x2b,0x5d,0x71,0x01,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x33,0x15,0x23,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0xcb,0xcb,0xfe,0x29,0x04,0x1f,0x01, 0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd9,0xcd,0xfe,0x26,0x98,0x00,0x01,0x00,0xa6,0xff,0xe8,0x04,0x2a,0x05,0xec,0x00,0x16,0x00,0x60,0x40,0x3e,0x7a,0x11,0x8a,0x11,0x02,0x10,0x18,0x10,0x14,0x48,0x09,0x10,0x19,0x10,0x29,0x10,0x03,0xc9,0x06,0xd9,0x06,0x02,0x06,0x10,0x1f,0x22,0x48,0x36,0x06,0x01,0x65,0x03,0x01,0x00, 0x00,0x18,0x09,0x84,0x0b,0x07,0x07,0x18,0x15,0x01,0x84,0x12,0x08,0x08,0x0f,0x00,0x95,0x15,0x0f,0x13,0x00,0x0c,0x04,0x95,0x0f,0x16,0x0b,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x11,0x39,0x2f,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x11,0x39,0x2f,0x31,0x30,0x5d,0x5d,0x2b,0x5d,0x5d,0x2b,0x5d,0x01,0x21,0x11,0x10, 0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x21,0x04,0x2a,0xfd,0x20,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0xa4,0x02,0xe0,0x03,0x68,0xfe,0x50,0xfe,0xba,0xb9,0x8d,0x01,0x18,0xfd,0x30,0xaa,0xc2,0xd9,0xcd,0x04,0x5e,0xfe,0x14,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0xec, 0x04,0x18,0x00,0x12,0x00,0x1f,0x00,0x67,0x40,0x46,0xc9,0x1f,0xd9,0x1f,0x02,0x26,0x1e,0x36,0x1e,0x02,0xc9,0x1c,0xd9,0x1c,0x02,0x45,0x1c,0x55,0x1c,0x02,0x44,0x18,0x54,0x18,0x02,0xa7,0x07,0x01,0xca,0x04,0xda,0x04,0x02,0x10,0x0e,0x84,0x14,0x0d,0x00,0x12,0x10,0x12,0x20,0x12,0x03,0x12,0x12,0x21,0x1a,0x83,0x1f,0x06,0x01,0x06, 0x10,0x95,0x12,0x1b,0x0d,0x0f,0x0c,0x17,0x95,0x09,0x10,0x00,0x1d,0x95,0x03,0x16,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x3f,0xed,0x01,0x2f,0x5d,0xed,0x12,0x39,0x2f,0x5d,0x33,0x33,0xfd,0xce,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x00,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x33, 0x15,0x21,0x11,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0x6c,0x04,0x6b,0xf3,0xc1,0xe9,0x01,0x00,0xd8,0xd2,0x5e,0x04,0xa4,0xdc,0xfe,0x80,0xa5,0x7f,0x94,0xac,0xa6,0x83,0x90,0xab,0xb0,0xc8,0x01,0x13,0xed,0xff,0x01,0x31,0xa6,0x8e,0xfa,0xc1,0x98,0x03,0xa4,0x95,0x7e,0xae,0xdb,0xc7,0xb1,0xc9,0xc5,0x00, 0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x2a,0x05,0xec,0x00,0x09,0x00,0x26,0x40,0x13,0x09,0x06,0x09,0x06,0x0b,0x04,0x07,0x84,0x01,0x06,0x95,0x04,0x0f,0x02,0x00,0x09,0x95,0x01,0x15,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x03,0xf8, 0xfc,0xae,0xa4,0x02,0xe0,0xfd,0x20,0x02,0xae,0x05,0xec,0xfe,0x14,0x98,0xfd,0x30,0x00,0x01,0x00,0xa6,0xfe,0x29,0x04,0x2a,0x04,0x18,0x00,0x14,0x00,0x5c,0x40,0x0b,0x28,0x13,0x01,0x76,0x13,0x86,0x13,0x96,0x13,0x03,0x12,0xb8,0xff,0xe0,0x40,0x2f,0x10,0x14,0x48,0x05,0x12,0x15,0x12,0x25,0x12,0x03,0x86,0x06,0x96,0x06,0x02,0xe8, 0x05,0x01,0x28,0x03,0x01,0x69,0x03,0x01,0x09,0x14,0x84,0x01,0x01,0x16,0x0d,0x07,0x84,0x0b,0x0e,0x04,0x95,0x11,0x10,0x0c,0x0f,0x09,0x95,0x0b,0x1b,0x01,0x15,0x00,0x3f,0x3f,0xed,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xfd,0xc6,0x31,0x30,0x5d,0x71,0x5d,0x71,0x5d,0x2b,0x5d,0x71,0x21,0x23,0x11,0x10,0x23,0x22, 0x06,0x15,0x11,0x21,0x15,0x21,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0x02,0xe0,0xfc,0x7c,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0x02,0x48,0x01,0x46,0xb9,0x8d,0xfc,0x79,0x98,0x05,0xd7,0xaa,0xc2,0xd9,0xcd,0x00,0x02,0x00,0xa6,0xfe,0x29,0x05,0x2b,0x04,0x18,0x00,0x0c,0x00,0x38,0x00,0x8c,0x40,0x5b, 0x98,0x35,0x01,0x97,0x23,0x01,0x66,0x23,0x76,0x23,0x86,0x23,0x03,0x65,0x22,0x01,0x89,0x1e,0x01,0x96,0x15,0x01,0x87,0x15,0x01,0x5a,0x10,0x01,0x49,0x10,0x01,0x9a,0x0a,0x01,0x89,0x0a,0x01,0x78,0x0a,0x01,0x69,0x0a,0x01,0x97,0x07,0x01,0x66,0x03,0x76,0x03,0x86,0x03,0x03,0x28,0x27,0x25,0x84,0x0d,0x01,0x01,0x19,0x3a,0x05,0x84, 0x33,0x1b,0x17,0x84,0x19,0x01,0x28,0x95,0x25,0x0d,0x0d,0x12,0x08,0x95,0x2e,0x16,0x1c,0x1d,0x1d,0x12,0x95,0x20,0x10,0x1a,0x0f,0x18,0x1b,0x00,0x3f,0x3f,0x3f,0xed,0x33,0x11,0x33,0x3f,0xed,0x11,0x39,0x2f,0xc4,0xfd,0xc4,0x01,0x2f,0xfd,0xc4,0xde,0xed,0x11,0x12,0x39,0x2f,0xc4,0xfd,0xcd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x11,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x15,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x03,0xe9,0x80,0x58,0x67, 0x4f,0x47,0x2e,0x41,0x28,0x12,0x03,0x2e,0x4e,0x69,0x3e,0x57,0x8b,0x62,0x35,0xa4,0xa4,0x04,0x40,0xd4,0x8a,0x5a,0x99,0x71,0x40,0x01,0x9a,0x9a,0x2c,0x56,0x80,0x54,0x45,0x74,0x54,0x2f,0x36,0x60,0x85,0x4f,0x01,0x5c,0x9e,0x6a,0x61,0x54,0x61,0x27,0x40,0x51,0x01,0x60,0x3a,0x5d,0x42,0x23,0x41,0x6b,0x88,0x47,0xfc,0x16,0x05,0xd7, 0xb4,0x60,0x6c,0x38,0x67,0x90,0x57,0x98,0x9e,0x52,0x88,0x63,0x37,0x32,0x58,0x77,0x46,0x52,0x84,0x5c,0x31,0x00,0x00,0x02,0x00,0x5e,0xff,0xe8,0x04,0xca,0x05,0xec,0x00,0x16,0x00,0x23,0x00,0x55,0x40,0x36,0x68,0x0f,0x01,0x4a,0x0f,0x5a,0x0f,0x02,0x48,0x0e,0x58,0x0e,0x02,0x68,0x09,0x01,0x5a,0x09,0x01,0x4d,0x09,0x01,0x66,0x05, 0x01,0x55,0x05,0x01,0x43,0x05,0x01,0x01,0x00,0x15,0x84,0x12,0x17,0x17,0x25,0x1b,0x83,0x0c,0x01,0x17,0x95,0x12,0x15,0x0f,0x14,0x00,0x1e,0x95,0x07,0x16,0x00,0x3f,0xed,0x3f,0x3f,0xc4,0xfd,0xc4,0x01,0x2f,0xed,0x12,0x39,0x2f,0xc4,0xfd,0xcd,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x11,0x14,0x0e, 0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x21,0x11,0x33,0x11,0x33,0x05,0x21,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x04,0xca,0xce,0x39,0x6f,0xa3,0x6b,0x7b,0xb8,0x79,0x3c,0x40,0x7b,0xb4,0x74,0x01,0x13,0xa8,0xce,0xfe,0x8a,0xfe,0xff,0xa7,0xa1,0x05,0x05,0xa1,0x8e,0x48,0x6b,0x45,0x22,0x03,0x76,0xfe,0x8d, 0x69,0xc3,0x96,0x59,0x52,0x92,0xc8,0x75,0x70,0xba,0x84,0x49,0x01,0xec,0xfe,0x14,0x8a,0xba,0xb9,0xc8,0xc9,0x46,0x72,0x92,0x4b,0x00,0x00,0x01,0x00,0xa6,0xfe,0x29,0x03,0xf8,0x05,0xec,0x00,0x11,0x00,0x4e,0xb3,0x37,0x10,0x01,0x10,0xb8,0xff,0xd0,0x40,0x2c,0x11,0x14,0x48,0x71,0x10,0x01,0x06,0x10,0x16,0x10,0x26,0x10,0x03,0x86, 0x06,0x96,0x06,0x02,0x28,0x03,0x01,0x68,0x03,0x01,0x11,0x84,0x01,0x01,0x13,0x0b,0x07,0x84,0x09,0x0c,0x04,0x95,0x0f,0x10,0x0a,0x00,0x08,0x1b,0x01,0x15,0x00,0x3f,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x71,0x71,0x5d,0x5d,0x2b,0x71,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23, 0x11,0x33,0x11,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xa4,0xee,0x78,0xa4,0xa4,0xa4,0x04,0x76,0xda,0x01,0x5a,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfb,0xe5,0x07,0xc3,0xfd,0x6a,0xc2,0xfe,0x5f,0x00,0x01,0x00,0xa6,0xfe,0x29,0x02,0x76,0x04,0x00,0x00,0x05,0x00,0x1a,0x40,0x0c,0x01,0x01,0x07,0x05,0x84,0x03,0x04,0x0f,0x01,0x95,0x03,0x1b, 0x00,0x3f,0xed,0x3f,0x01,0x2f,0xed,0x11,0x33,0x2f,0x31,0x30,0x01,0x21,0x15,0x21,0x11,0x33,0x01,0x4a,0x01,0x2c,0xfe,0x30,0xa4,0xfe,0xc1,0x98,0x05,0xd7,0x00,0x01,0x00,0xa6,0xfe,0x29,0x06,0x0b,0x05,0xec,0x00,0x35,0x00,0x49,0x40,0x29,0x95,0x2c,0x01,0x87,0x2c,0x01,0x28,0x84,0x0d,0x35,0x84,0x01,0x33,0x0d,0x33,0x0d,0x33,0x1a, 0x37,0x1c,0x18,0x84,0x1a,0x34,0x0f,0x1e,0x13,0x95,0x23,0x10,0x1c,0x00,0x19,0x1b,0x2e,0x95,0x03,0x08,0x16,0x00,0x15,0x00,0x3f,0x3f,0x33,0xed,0x3f,0x3f,0x3f,0xed,0x33,0x3f,0x01,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc4,0xed,0x10,0xed,0x31,0x30,0x5d,0x5d,0x21,0x23,0x35,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35, 0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x06,0x0b,0xa4,0x04,0x1a,0x38,0x44,0x51,0x32,0x61,0x80,0x4b,0x1f,0x0d,0x26,0x43,0x37,0x42,0x63,0x42,0x21,0xa4,0xa4,0x04,0x1e,0x41,0x4c,0x5b,0x36,0x54,0x6d, 0x3f,0x18,0x0d,0x2d,0x54,0x47,0x3e,0x5a,0x3b,0x1d,0xa4,0xa2,0x2f,0x45,0x2f,0x17,0x43,0x7c,0xb0,0x6d,0x62,0x50,0x84,0x5f,0x35,0x43,0x6b,0x84,0x40,0xfc,0x0d,0x07,0xc3,0xfd,0x6a,0x30,0x49,0x31,0x18,0x41,0x77,0xa9,0x68,0x71,0x51,0x86,0x60,0x35,0x43,0x69,0x80,0x3c,0x02,0x26,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0xb0,0x06,0x02, 0x00,0x15,0x00,0x25,0x00,0xc7,0x40,0x64,0x96,0x1a,0x01,0x96,0x16,0x01,0x48,0x0a,0x58,0x0a,0x02,0x49,0x06,0x59,0x06,0x02,0x5a,0x05,0x01,0x49,0x05,0x01,0x56,0x03,0x01,0x45,0x03,0x01,0x56,0x02,0x01,0x47,0x02,0x01,0x79,0x0c,0x99,0x0c,0x02,0x4c,0x0c,0x5c,0x0c,0x02,0x38,0x0c,0x01,0x0c,0x23,0x0d,0x20,0xb5,0x11,0xc5,0x11,0x02, 0x87,0x11,0x01,0x62,0x11,0x01,0x47,0x11,0x57,0x11,0x02,0x46,0x14,0x56,0x14,0x02,0x11,0x14,0x10,0x12,0x12,0x00,0x83,0x10,0x20,0x20,0x20,0x30,0x20,0x03,0x20,0x20,0x08,0x27,0xe9,0x0f,0x01,0x0f,0x10,0x0d,0x12,0x48,0x0f,0x10,0xb8,0xff,0xc0,0x40,0x21,0x0e,0x12,0x48,0x10,0x36,0x0e,0x01,0x0e,0x0d,0x0d,0x18,0x83,0x20,0x08,0x01, 0x08,0x14,0x23,0x95,0x0f,0x10,0x0d,0x03,0x0e,0x0c,0x11,0x0f,0x0e,0x00,0x1c,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x3f,0xc5,0x12,0x17,0x39,0xfd,0xc4,0x01,0x2f,0x5d,0xed,0x33,0x2f,0x33,0x5d,0xcd,0x2b,0x32,0x2b,0x5d,0x11,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x5d,0x5d,0x11,0x12,0x39,0x39,0x5d,0x5d, 0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x01,0x37,0x17,0x07,0x01,0x21,0x15,0x23,0x16,0x25,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x37,0x36,0x35,0x26,0x27,0x27,0x23,0x22,0x04,0x50,0x85,0x8b,0xee,0xe7,0x87,0x84,0x89,0x78,0xce,0xfe,0x55, 0x97,0x88,0x43,0x01,0xda,0x01,0x76,0xd9,0x78,0xfd,0x14,0x5b,0x54,0x5c,0xa6,0xab,0x54,0x4b,0x01,0x8c,0x2c,0x5b,0xd6,0x02,0x04,0xf1,0x93,0x98,0x94,0x8f,0xe9,0xfb,0x88,0x78,0x0f,0x01,0x21,0xe3,0x5a,0x65,0xfe,0xbd,0x8a,0x96,0x2c,0x69,0xa9,0xab,0x6a,0x73,0x74,0x66,0xb2,0xe6,0x73,0x1f,0x00,0x01,0x00,0x90,0xfe,0x29,0x03,0xe2, 0x05,0xec,0x00,0x11,0x00,0x37,0x40,0x21,0x76,0x0b,0x01,0x67,0x0b,0x01,0x8b,0x06,0x9b,0x06,0x02,0x28,0x06,0x01,0x11,0x84,0x03,0x01,0x0f,0x09,0x84,0x07,0x11,0x0f,0x09,0x00,0x0c,0x95,0x02,0x05,0x16,0x00,0x1b,0x00,0x3f,0x3f,0x33,0xed,0x3f,0x3f,0x01,0x2f,0xed,0x2f,0xc4,0x33,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x23,0x11, 0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xe2,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0xa4,0xfe,0x29,0x02,0x79,0xba,0x01,0xb4,0x04,0x50,0xfb,0xca,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x11,0x00,0x98,0x40,0x2c,0x75,0x10, 0x01,0x92,0x10,0x01,0x82,0x10,0x01,0x6a,0x03,0x01,0x75,0x10,0x01,0x01,0x15,0x09,0x15,0x0c,0x04,0x95,0x0f,0x10,0x0a,0x00,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x1e,0x0b, 0x06,0x4d,0x01,0x01,0x13,0x0c,0x08,0x06,0x0d,0x06,0x4d,0x08,0x06,0x0c,0x06,0x4d,0x08,0x06,0x0b,0x06,0x4d,0x08,0x84,0x09,0x02,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x13,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b, 0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xa4,0xee,0x78,0xa4,0xa4,0xa4,0x04,0x76,0xda,0x01,0x5a,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfd,0xbc,0x05,0xec,0xfd,0x6a,0xc2, 0xfe,0x5f,0x00,0x02,0x00,0x60,0xff,0xe8,0x03,0xb2,0x05,0xc6,0x00,0x14,0x00,0x2f,0x00,0x93,0x40,0x5d,0x99,0x27,0x01,0x46,0x24,0x01,0x37,0x1d,0x01,0x9a,0x12,0x01,0x85,0x08,0x01,0x78,0x15,0x88,0x15,0x02,0x75,0x07,0x01,0x66,0x07,0x01,0x84,0x1a,0x01,0x00,0x1a,0x05,0x91,0x19,0x01,0x19,0x2f,0x2f,0x2a,0x0f,0x99,0x17,0x01,0x17, 0x90,0x18,0x01,0x18,0x16,0x15,0x15,0x05,0x83,0x0f,0x2a,0x01,0x2a,0x21,0x1f,0x84,0x0f,0x0f,0x01,0x0f,0x6c,0x00,0x7c,0x00,0x02,0x4a,0x00,0x5a,0x00,0x02,0x00,0x2f,0x19,0x15,0x18,0x04,0x16,0x1a,0x1a,0x16,0x0a,0x95,0x23,0x25,0x16,0x20,0x15,0x16,0x00,0x00,0x3f,0x3f,0x3f,0x33,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0x33,0x5d,0x5d, 0x01,0x2f,0x5d,0xed,0xc4,0x2f,0x5d,0xed,0x33,0x2f,0x33,0xcd,0x5d,0x32,0x5d,0x11,0x12,0x39,0x2f,0xcd,0x5d,0x11,0x39,0x39,0x5d,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x34,0x2e,0x02,0x01,0x37,0x17,0x07,0x05,0x07,0x1e,0x03,0x15,0x11,0x23, 0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x01,0xf0,0x48,0x5c,0x35,0x14,0x25,0x41,0x56,0x32,0x47,0x6b,0x47,0x24,0x2c,0x4d,0x69,0xfe,0x4e,0x6e,0x8f,0x37,0x01,0x89,0x71,0x49,0x7f,0x5d,0x35,0xa4,0x04,0x62,0xc6,0x54,0x8d,0x67,0x3a,0x29,0x5b,0x91,0x67,0x03,0x73,0x44,0x80,0x78,0x73,0x36,0x47,0x6a,0x47,0x24, 0x33,0x5a,0x78,0x45,0x28,0x56,0x79,0x5a,0x45,0x01,0x9e,0xd6,0x3c,0x63,0xda,0x75,0x29,0x5a,0x72,0x8e,0x5b,0xfe,0x06,0xa2,0xba,0x32,0x64,0x95,0x63,0x5a,0xaa,0xaa,0xad,0x5d,0x00,0x01,0x00,0xa6,0xfe,0x29,0x04,0xd4,0x04,0x18,0x00,0x14,0x00,0x58,0x40,0x0b,0x28,0x10,0x01,0x76,0x10,0x86,0x10,0x96,0x10,0x03,0x0f,0xb8,0xff,0xe0, 0x40,0x2c,0x10,0x14,0x48,0x05,0x0f,0x15,0x0f,0x25,0x0f,0x03,0x86,0x05,0x96,0x05,0x02,0x28,0x02,0x01,0x68,0x02,0x01,0x14,0x12,0x84,0x01,0x01,0x16,0x0a,0x06,0x84,0x09,0x0c,0x03,0x95,0x0e,0x10,0x0a,0x0f,0x08,0x15,0x12,0x95,0x00,0x1b,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xfd,0xcd,0x31, 0x30,0x5d,0x71,0x71,0x5d,0x2b,0x5d,0x71,0x01,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x33,0x15,0x03,0x54,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0xdc,0xfe,0x29,0x04,0x1f,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd9,0xcd,0xfc,0x4f,0x98,0x00,0x00,0x02, 0x00,0x60,0xff,0xe8,0x03,0x89,0x06,0x02,0x00,0x20,0x00,0x31,0x00,0x79,0x40,0x4c,0x49,0x2d,0x59,0x2d,0x02,0x76,0x24,0x86,0x24,0x96,0x24,0x03,0x67,0x24,0x01,0x75,0x12,0x01,0x66,0x12,0x01,0x86,0x0d,0x01,0x77,0x0d,0x01,0x49,0x03,0x59,0x03,0x99,0x03,0x03,0x2f,0x10,0x21,0x1f,0x01,0x1c,0x09,0x09,0x13,0x84,0x15,0x2b,0x2b,0x33, 0x21,0x84,0x1c,0x00,0x00,0x0f,0x1c,0x01,0x1c,0x26,0x95,0x17,0x19,0x16,0x14,0x15,0x09,0x0b,0x95,0x08,0x06,0x01,0x1f,0x2f,0x95,0x10,0x01,0x10,0x00,0x3f,0xc4,0xfd,0xc4,0x3f,0x33,0xed,0x32,0x3f,0x3f,0x33,0xed,0x01,0x2f,0x5d,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xc4,0xed,0x32,0x2f,0x12,0x39,0x39,0x12,0x39,0x39,0x31,0x30,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x3e,0x03,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x07,0x33,0x20,0x11,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x23,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x10,0x21,0x23,0x06,0x06,0x60,0x5a,0x21,0x77,0xa0,0xc0,0x6b,0x43,0x29,0x34,0x3e,0x50, 0x8a,0x71,0x55,0x19,0x5e,0x01,0xcd,0xa4,0x04,0x6a,0xd1,0x99,0xad,0x17,0x1d,0x34,0xa8,0x1c,0x33,0x48,0x2d,0x3f,0x68,0x4a,0x28,0xfe,0xc9,0x78,0x1b,0x13,0x04,0x18,0x62,0xb1,0x87,0x50,0x0a,0x8d,0x0d,0x3c,0x63,0x7e,0x43,0xfe,0x1e,0xfd,0xca,0xa0,0xb8,0xde,0xe0,0x8d,0xf3,0x68,0xfe,0x24,0x53,0x78,0x4f,0x26,0x30,0x52,0x6e,0x3e, 0x85,0x01,0x69,0x61,0xec,0x00,0x00,0x01,0x00,0x90,0xff,0xe8,0x04,0xaf,0x05,0xec,0x00,0x13,0x00,0x42,0x40,0x28,0x66,0x0b,0x76,0x0b,0x02,0x57,0x0b,0x01,0x8b,0x06,0x9b,0x06,0x02,0x28,0x06,0x01,0x11,0x13,0x84,0x03,0x01,0x0f,0x0f,0x15,0x09,0x84,0x07,0x12,0x95,0x10,0x00,0x09,0x0f,0x0c,0x95,0x02,0x05,0x16,0x00,0x15,0x00,0x3f, 0x3f,0x33,0xed,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xc4,0x32,0xfd,0xcd,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x21,0x15,0x23,0x03,0xe2,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x01,0x71,0xcd,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd, 0xb6,0xfe,0xbc,0xb1,0x8f,0x04,0x3a,0x98,0x00,0x01,0xff,0x70,0xfe,0x29,0x01,0x80,0x04,0x00,0x00,0x0a,0x00,0x16,0x40,0x0a,0x0a,0x84,0x05,0x09,0x09,0x0f,0x06,0x95,0x03,0x1c,0x00,0x3f,0xed,0x3f,0x01,0x2f,0xce,0xed,0x31,0x30,0x25,0x14,0x06,0x23,0x23,0x35,0x33,0x32,0x11,0x11,0x33,0x01,0x80,0xcb,0xb5,0x90,0x8c,0xe0,0xa4,0x09, 0xe8,0xf8,0x98,0x01,0x3b,0x04,0x04,0x00,0x00,0x01,0xff,0xf6,0xff,0xe8,0x04,0x0b,0x05,0xec,0x00,0x13,0x00,0x3e,0x40,0x25,0x9a,0x10,0x01,0x8b,0x10,0x01,0x29,0x10,0x01,0x76,0x03,0x01,0x67,0x03,0x01,0x13,0x01,0x84,0x11,0x0d,0x0b,0x09,0x84,0x07,0x0c,0x04,0x95,0x0f,0x16,0x0a,0x15,0x09,0x0f,0x12,0x95,0x01,0x00,0x00,0x3f,0xed, 0x3f,0x3f,0x3f,0xed,0x33,0x01,0x2f,0xed,0xc4,0x32,0x2f,0xed,0xce,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x03,0x21,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x23,0x0a,0x01,0x66,0xf8,0x78,0x9b,0xa4,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xc3,0x05,0xec,0xfb,0xca,0xfe,0xbc,0xb1,0x8f,0x02,0x4e, 0xfc,0x00,0xa2,0xba,0x01,0xb4,0x03,0xb8,0x00,0x01,0x00,0x60,0xfe,0x29,0x03,0xc6,0x04,0x18,0x00,0x2f,0x00,0x71,0x40,0x49,0x66,0x2d,0x76,0x2d,0x02,0x79,0x2b,0x01,0x48,0x22,0x58,0x22,0x02,0x9a,0x03,0x01,0x89,0x03,0x01,0x99,0x02,0x01,0x88,0x02,0x01,0x93,0x0f,0x01,0x64,0x0f,0x74,0x0f,0x84,0x0f,0x03,0x0f,0x13,0x1a,0x1a,0x0a, 0x84,0x9c,0x25,0x01,0x8b,0x25,0x01,0x6c,0x25,0x01,0x25,0x20,0x29,0x29,0x31,0x13,0x84,0x20,0x2f,0x84,0x00,0x00,0x20,0x19,0x95,0x1b,0x1b,0x00,0x00,0x2c,0x95,0x05,0x10,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x01,0x2f,0x33,0x2f,0xed,0x10,0xed,0x12,0x39,0x2f,0x12,0x39,0x5d,0x5d,0x5d,0xed,0x32,0x2f,0x11,0x39,0x5d,0x5d,0x31,0x30, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x06,0x15,0x14,0x1e,0x02,0x33,0x21,0x15,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x06,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x60,0x44,0x76,0x9e,0x5b,0x5b,0x9e,0x76,0x44,0x3d,0x63,0x80,0x84,0x80,0x63,0x3d,0x1a,0x33,0x49,0x30,0x01,0xfe,0xfd, 0xf1,0x51,0x7f,0x58,0x2f,0x3d,0x63,0x80,0x84,0x80,0x63,0x3d,0x8c,0x85,0x85,0x8c,0x02,0x89,0x5c,0x94,0x67,0x38,0x38,0x67,0x94,0x5c,0x5c,0x8e,0x6e,0x57,0x4b,0x46,0x4d,0x5b,0x3b,0x24,0x3d,0x2e,0x1a,0x94,0x30,0x57,0x77,0x48,0x4e,0x77,0x5d,0x4d,0x48,0x4a,0x5c,0x72,0x4b,0x7e,0x86,0x86,0x7e,0x00,0x00,0x01,0x00,0xa6,0x00,0x00, 0x03,0xf8,0x04,0x18,0x00,0x12,0x00,0x98,0x40,0x2c,0x75,0x11,0x01,0x92,0x10,0x01,0x82,0x10,0x01,0x6a,0x03,0x01,0x75,0x10,0x01,0x01,0x15,0x09,0x15,0x0a,0x0f,0x0c,0x04,0x95,0x0f,0x10,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x01,0xb8,0xff,0xf6,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff, 0xf8,0xb3,0x0c,0x06,0x4d,0x01,0xb8,0xff,0xf8,0x40,0x1e,0x0b,0x06,0x4d,0x01,0x01,0x14,0x0c,0x08,0x06,0x0d,0x06,0x4d,0x08,0x06,0x0c,0x06,0x4d,0x08,0x06,0x0b,0x06,0x4d,0x08,0x84,0x09,0x02,0x0d,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb3,0x0c,0x06,0x4d,0x09,0xb8,0xff,0xfe,0xb6,0x0b,0x06,0x4d,0x09,0x2f,0x14,0x01,0x5d,0x2f,0x2b,0x2b, 0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0xed,0x32,0x3f,0x3f,0x3f,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2, 0x02,0x48,0x01,0x46,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd9,0xcd,0x00,0x01,0x00,0x60,0xfe,0x29,0x02,0xec,0x04,0x1c,0x00,0x29,0x00,0x6a,0x40,0x41,0xb7,0x29,0x01,0xa6,0x29,0x01,0x88,0x25,0x01,0x9a,0x1f,0x01,0x89,0x1f,0x01,0x99,0x1e,0x01,0x8a,0x1e,0x01,0x65,0x0a,0x01,0x47,0x09,0x01,0x67,0x08,0x01,0x67,0x01,0x01,0x27, 0x28,0x28,0x29,0x95,0x29,0x01,0x29,0x11,0x11,0x03,0x84,0x26,0x23,0x23,0x2b,0x0e,0x84,0x16,0x23,0x03,0x11,0x29,0x28,0x95,0x26,0x27,0x10,0x11,0x95,0x12,0x1b,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x12,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x2f,0x32,0x5d,0x11,0x33,0x2f,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x07,0x06,0x06,0x15,0x14,0x33,0x21,0x15,0x21,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x03,0x37,0x36,0x36,0x35,0x34,0x27,0x01,0x25,0x17,0x07,0x02,0x64,0x11,0x13,0x34,0x3b,0x31,0x46,0x3a,0x38,0x22,0x0b,0x12,0x4e,0x01,0xad,0xfe,0x53,0x73,0x6c,0x06, 0x0d,0x15,0x0f,0x1b,0x4c,0x56,0x58,0x27,0x14,0x10,0x0c,0xfe,0x9c,0x01,0x07,0x5f,0x8d,0x01,0xa4,0x19,0x37,0x23,0x29,0x61,0x3b,0x30,0x48,0x41,0x41,0x29,0x0e,0x2b,0x0e,0x45,0x94,0x68,0x70,0x0c,0x24,0x28,0x29,0x13,0x22,0x54,0x59,0x58,0x27,0x13,0x26,0x10,0x19,0x12,0x02,0x08,0xbd,0x84,0x66,0x00,0x00,0x01,0x00,0x90,0xfe,0x29, 0x06,0x3e,0x04,0x00,0x00,0x1f,0x00,0x5b,0x40,0x38,0x9c,0x1e,0x01,0x85,0x0c,0x01,0x66,0x0c,0x76,0x0c,0x02,0x86,0x03,0x01,0x77,0x03,0x01,0x66,0x03,0x01,0x02,0x84,0x1f,0x08,0x16,0x14,0x12,0x84,0x10,0x1b,0x0b,0x84,0x08,0x05,0x95,0x1d,0x9d,0x1b,0x01,0x48,0x1b,0x58,0x1b,0x02,0x1b,0x15,0x0d,0x95,0x18,0x16,0x13,0x1b,0x11,0x01, 0x0a,0x0f,0x00,0x3f,0xc4,0xc4,0x3f,0x3f,0xed,0x33,0x33,0x5d,0x5d,0xd4,0xed,0x01,0x2f,0xed,0x33,0xdc,0xed,0xc4,0x33,0x10,0xdc,0xed,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x11,0x23,0x06,0x23,0x22,0x26,0x27,0x06, 0x23,0x20,0x11,0x90,0xa4,0x69,0x7c,0x69,0x93,0xa4,0xe9,0x6c,0x8c,0xa4,0xa4,0x04,0x6d,0xd1,0x69,0x9c,0x1d,0x72,0xe2,0xfe,0xae,0x04,0x00,0xfd,0xb4,0xaa,0x98,0xc0,0x86,0x02,0x48,0xfd,0xa0,0xfe,0xd2,0xb5,0x91,0x02,0x48,0xfa,0x29,0x02,0x79,0xba,0x75,0x5f,0xd4,0x01,0xa1,0x00,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0x04,0x04,0x18, 0x00,0x2d,0x00,0x44,0x00,0x86,0x40,0x57,0x66,0x40,0x01,0x67,0x3e,0x01,0x94,0x39,0x01,0x76,0x39,0x86,0x39,0x02,0x69,0x36,0x01,0x5a,0x29,0x01,0x49,0x29,0x01,0x67,0x17,0x01,0x93,0x16,0x01,0x86,0x16,0x01,0x75,0x16,0x01,0x66,0x16,0x01,0x95,0x15,0x01,0x85,0x14,0x01,0x77,0x0f,0x01,0x75,0x0e,0x01,0x89,0x02,0x99,0x02,0x02,0x1f, 0x1f,0x11,0x84,0x33,0x2e,0x42,0x84,0x00,0x00,0x07,0x33,0x33,0x26,0x46,0x3b,0x84,0x07,0x07,0x1b,0x84,0x26,0x2e,0x38,0x1f,0x95,0x21,0x1b,0x38,0x95,0x0c,0x10,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x01,0x2f,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0x12,0x39,0x2f,0xed,0x32,0x10,0xed,0x32,0x2f,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x3e,0x03,0x17,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x04,0x15,0x14,0x06, 0x01,0x5c,0x22,0x32,0x3c,0x32,0x22,0x43,0x78,0xa6,0x64,0x64,0xa8,0x78,0x43,0x4d,0x7d,0xa0,0xa6,0xa0,0x3e,0x10,0x15,0x2f,0x33,0x02,0xb1,0xfd,0x4f,0x39,0x5a,0x3f,0x21,0x28,0x23,0x3c,0x46,0x25,0x0a,0x6e,0x43,0x90,0x78,0x4d,0x2a,0x4d,0x6b,0x41,0x96,0x8f,0x1e,0x2e,0x34,0x2e,0x1e,0x0b,0x01,0x01,0x29,0x45,0x40,0x40,0x48,0x55, 0x35,0x58,0x81,0x55,0x29,0x39,0x65,0x8d,0x54,0x54,0x9b,0x8f,0x87,0x7f,0x7a,0x3b,0x0f,0x2d,0x0e,0x23,0x36,0x94,0x23,0x40,0x5b,0x38,0x2d,0x51,0x20,0x35,0x54,0x4b,0x48,0x43,0x3a,0x70,0x77,0x84,0x4e,0x3b,0x60,0x44,0x25,0x68,0x6a,0x23,0x41,0x3e,0x3d,0x41,0x45,0x27,0x2a,0x44,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x87,0x04,0x18, 0x00,0x17,0x00,0x55,0x40,0x31,0x86,0x10,0x96,0x10,0x02,0x75,0x10,0x01,0x6a,0x03,0x01,0x59,0x03,0x01,0x06,0x14,0x01,0x14,0x00,0x15,0x15,0x12,0x84,0x02,0x00,0x00,0x07,0x02,0x02,0x09,0x19,0x0d,0x0b,0x07,0x84,0x09,0x00,0x14,0x95,0x09,0x17,0x15,0x0c,0x04,0x95,0x0f,0x10,0x0a,0x0f,0x00,0x3f,0x3f,0xed,0x33,0x3f,0xc4,0xed,0x39, 0x01,0x2f,0xfd,0xc4,0x33,0x11,0x12,0x39,0x2f,0x12,0x39,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x25,0x24,0x11,0x10,0x25,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x21,0x15,0x21,0x02,0x5b,0x01,0x17,0xfe,0xfe,0x85,0xa1,0xa4,0xa4,0x04,0x74,0xe6,0x9e,0xd0, 0xc0,0x01,0x31,0xfd,0xd4,0x47,0x95,0x01,0x63,0x01,0x3e,0x11,0xb9,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xea,0xf0,0xf7,0xbb,0x8c,0x00,0x00,0x01,0x00,0x90,0xff,0xe8,0x03,0xe2,0x04,0x00,0x00,0x11,0x00,0xa5,0x40,0x3c,0x79,0x06,0x01,0x9b,0x06,0x01,0x8b,0x06,0x01,0x66,0x0b,0x01,0x56,0x0b,0x01,0x79,0x06,0x01,0x0d,0x10,0x0b,0x0c, 0x00,0x4c,0x38,0x03,0x01,0x01,0x15,0x03,0x0c,0x95,0x05,0x16,0x10,0x0f,0x08,0x0f,0x01,0x00,0x06,0x0d,0x06,0x4d,0x00,0x06,0x0c,0x06,0x4d,0x00,0x06,0x0b,0x06,0x4d,0x00,0x84,0x7f,0x0f,0x01,0x0f,0xb8,0xff,0xfa,0xb3,0x0d,0x06,0x4d,0x0f,0xb8,0xff,0xfc,0xb3,0x0c,0x06,0x4d,0x0f,0xb8,0xff,0xfc,0x40,0x2a,0x0b,0x06,0x4d,0x0f,0x0f, 0x13,0x0a,0x06,0x0d,0x06,0x4d,0x0a,0x06,0x0c,0x06,0x4d,0x0a,0x06,0x0b,0x06,0x4d,0x0a,0x84,0x07,0x0a,0x0d,0x06,0x4d,0x07,0x06,0x0c,0x06,0x4d,0x07,0x02,0x0b,0x06,0x4d,0x07,0x2f,0x13,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x33,0x00,0x3f,0x3f,0x3f,0xed,0x32, 0x3f,0x5d,0x31,0x30,0x2b,0x01,0x5d,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xe2,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0xa4,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0x00,0x01,0x00,0x90,0xfe,0x29, 0x04,0xbe,0x05,0xec,0x00,0x13,0x00,0x42,0x40,0x28,0x66,0x0b,0x76,0x0b,0x02,0x57,0x0b,0x01,0x8b,0x06,0x9b,0x06,0x02,0x28,0x06,0x01,0x00,0x12,0x84,0x03,0x01,0x0f,0x0f,0x15,0x09,0x84,0x07,0x11,0x00,0x09,0x0f,0x0c,0x95,0x02,0x05,0x16,0x13,0x95,0x01,0x1b,0x00,0x3f,0xed,0x3f,0x33,0xed,0x3f,0x3f,0x01,0x2f,0xed,0x12,0x39,0x2f, 0xc4,0x33,0xfd,0xcd,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x11,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x33,0x04,0xbe,0xfe,0x80,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0xa4,0xdc,0xfe,0x29,0x02,0x79,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x04,0x3a,0xf8,0xd5, 0x00,0x01,0x00,0x8f,0xff,0xe8,0x06,0x17,0x04,0x18,0x00,0x26,0x00,0x53,0x40,0x33,0x94,0x24,0x01,0x85,0x16,0x01,0x66,0x16,0x76,0x16,0x02,0x9c,0x11,0x01,0x79,0x03,0x89,0x03,0x02,0x68,0x03,0x01,0x14,0x84,0x12,0x1c,0x1e,0x09,0x84,0x1c,0x00,0x84,0x02,0x0b,0x1c,0x20,0x04,0x95,0x23,0x10,0x14,0x1d,0x0f,0x17,0x95,0x0d,0x10,0x16, 0x01,0x0a,0x15,0x00,0x3f,0xc4,0x3f,0x33,0xed,0x3f,0xc4,0x3f,0xed,0x33,0x01,0x2f,0xc4,0xdc,0xed,0x10,0xfd,0xc4,0x10,0xdc,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x33, 0x36,0x36,0x33,0x32,0x16,0x15,0x06,0x17,0xa4,0xd0,0x39,0x5e,0x42,0x25,0xa4,0x04,0x33,0x8b,0x60,0xfe,0xb0,0xa3,0xda,0x36,0x5a,0x41,0x24,0xa4,0x04,0x3a,0x9c,0x5c,0x96,0xa6,0x02,0x48,0x01,0x46,0x33,0x56,0x71,0x3e,0xfd,0xaa,0xa2,0x5e,0x5c,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0x34,0x58,0x74,0x40,0x02,0x4e,0xaa,0x61,0x61, 0xd8,0xce,0x00,0x01,0x00,0xa6,0xfe,0x29,0x03,0xf8,0x04,0x18,0x00,0x12,0x00,0x53,0x40,0x0b,0x28,0x11,0x01,0x76,0x11,0x86,0x11,0x96,0x11,0x03,0x10,0xb8,0xff,0xe0,0x40,0x29,0x10,0x14,0x48,0x05,0x10,0x15,0x10,0x25,0x10,0x03,0x86,0x06,0x96,0x06,0x02,0x28,0x03,0x01,0x69,0x03,0x01,0x12,0x84,0x01,0x01,0x14,0x0b,0x07,0x84,0x09, 0x0c,0x04,0x95,0x0f,0x10,0x0a,0x0f,0x09,0x1b,0x01,0x15,0x00,0x3f,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x5d,0x71,0x71,0x5d,0x2b,0x5d,0x71,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0xa4,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74, 0xdc,0xa8,0xb2,0x02,0x48,0x01,0x46,0xb9,0x8d,0xfb,0xe1,0x05,0xd7,0xaa,0xc2,0xd9,0xcd,0x00,0x00,0x02,0x00,0x60,0xfe,0x1e,0x04,0x10,0x04,0x18,0x00,0x28,0x00,0x3d,0x00,0x70,0x40,0x47,0x55,0x31,0x01,0x46,0x31,0x01,0x45,0x2b,0x01,0x5a,0x21,0x01,0x7a,0x1b,0x01,0x69,0x1b,0x01,0x38,0x12,0x01,0x74,0x0e,0x01,0x9a,0x08,0x01,0x89, 0x08,0x01,0x8a,0x07,0x01,0x54,0x02,0x01,0x45,0x02,0x01,0x27,0x15,0x00,0x84,0x38,0x38,0x1e,0x3f,0x0b,0x83,0x0a,0x0a,0x2e,0x83,0x1e,0x28,0x0f,0x29,0x95,0x25,0x23,0x10,0x33,0x95,0x17,0x0b,0x19,0x16,0x10,0x95,0x03,0x1c,0x00,0x3f,0xed,0x3f,0xce,0x33,0xed,0x3f,0x33,0xed,0x3f,0x01,0x2f,0xed,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f, 0xed,0xc4,0xc4,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x10,0x00,0x23,0x22,0x2e,0x04,0x35,0x33,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x33,0x35,0x33,0x05,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02, 0x35,0x35,0x34,0x2e,0x02,0x04,0x10,0xfe,0xf7,0xf5,0x20,0x59,0x60,0x5f,0x4b,0x2f,0xa8,0x35,0x4f,0x5d,0x27,0x51,0x81,0x5a,0x30,0x04,0x75,0xeb,0x6a,0x9f,0x6a,0x35,0x38,0x73,0xb1,0x79,0xcf,0x64,0x04,0xa4,0xfe,0x3c,0x58,0x7b,0x4e,0x23,0x24,0x4a,0x71,0x4e,0x48,0x73,0x51,0x2b,0x2c,0x4e,0x69,0x52,0xfe,0xe6,0xfe,0xe6,0x0d,0x20, 0x35,0x52,0x70,0x4a,0x3f,0x57,0x35,0x17,0x32,0x65,0x96,0x65,0x70,0xc4,0x50,0x89,0xb7,0x67,0x74,0xcf,0x9b,0x5b,0xa6,0x8e,0x72,0x44,0x74,0x98,0x54,0x4a,0x88,0x68,0x3e,0x38,0x5f,0x7f,0x47,0x97,0x3c,0x6b,0x51,0x30,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0x02,0x04,0x00,0x00,0x05,0x00,0x1a,0x40,0x0c,0x01,0x01,0x07,0x00,0x84,0x03, 0x05,0x0f,0x00,0x95,0x03,0x15,0x00,0x3f,0xed,0x3f,0x01,0x2f,0xed,0x12,0x39,0x2f,0x31,0x30,0x25,0x21,0x15,0x21,0x11,0x33,0x01,0x4a,0x01,0xb8,0xfd,0xa4,0xa4,0x98,0x98,0x04,0x00,0x00,0x00,0x01,0x00,0x8f,0xfe,0x29,0x06,0x17,0x05,0xec,0x00,0x26,0x00,0x55,0x40,0x35,0x94,0x24,0x01,0x85,0x16,0x01,0x66,0x16,0x76,0x16,0x02,0x9c, 0x11,0x01,0x79,0x03,0x89,0x03,0x02,0x68,0x03,0x01,0x14,0x84,0x12,0x1c,0x1e,0x09,0x84,0x1c,0x00,0x84,0x02,0x0b,0x1c,0x20,0x04,0x95,0x23,0x10,0x1d,0x00,0x14,0x0f,0x17,0x95,0x0d,0x10,0x16,0x0a,0x1b,0x01,0x15,0x00,0x3f,0x3f,0x3f,0x33,0xed,0x3f,0x3f,0x3f,0xed,0x33,0x01,0x2f,0xc4,0xdc,0xed,0x10,0xfd,0xc4,0x10,0xdc,0xed,0x31, 0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x23,0x06,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x06,0x17,0xa4,0xd0,0x39,0x5e,0x42,0x25,0xa4,0x04,0x33,0x8b,0x60,0xfe,0xb0,0xa3,0xda,0x36,0x5a,0x41, 0x24,0xa4,0x04,0x3a,0x9c,0x5c,0x96,0xa6,0x02,0x48,0x01,0x46,0x33,0x56,0x71,0x3e,0xfb,0xd3,0x02,0x79,0x5e,0x5c,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0x34,0x58,0x74,0x40,0x04,0x3a,0xfd,0x6a,0x61,0x61,0xd8,0xce,0x00,0x02,0x00,0x00,0xfe,0x29,0x04,0x54,0x04,0x18,0x00,0x18,0x00,0x25,0x00,0x62,0x40,0x3b,0x4a,0x21,0x5a,0x21, 0x02,0x43,0x1f,0x53,0x1f,0x02,0x66,0x09,0x76,0x09,0x02,0x12,0x12,0x0a,0x83,0x20,0x20,0x17,0x27,0x05,0x03,0x1a,0x14,0x0f,0x11,0x84,0x01,0x00,0x17,0x11,0x01,0x95,0x17,0x00,0x14,0x10,0x14,0x20,0x14,0x03,0x14,0x16,0x1b,0x1d,0x95,0x0f,0x0d,0x16,0x23,0x95,0x04,0x07,0x10,0x02,0x0f,0x00,0x3f,0x3f,0x33,0xed,0x3f,0x33,0xed,0x3f, 0xdd,0x5d,0xc4,0xfd,0xc4,0x01,0x2f,0xcd,0xc4,0xfd,0x32,0xc4,0xc4,0xc4,0x32,0x11,0x12,0x39,0x2f,0xed,0x32,0x2f,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x15,0x33,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x27,0x23,0x11,0x21,0x15,0x21,0x15,0x23,0x35,0x23,0x01,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23, 0x22,0x06,0xa6,0xa4,0x04,0x79,0xe9,0xc6,0xde,0xfa,0xd9,0xc7,0x6c,0x04,0x03,0x0a,0xfc,0xf6,0xa4,0xa6,0x01,0x4a,0xa5,0x7f,0x95,0xa9,0x9e,0x87,0x8f,0xae,0xa7,0x04,0xa7,0xb4,0xcc,0xfe,0xed,0xe7,0xfe,0xff,0xfe,0xcb,0xac,0xfe,0xc5,0x98,0x98,0x98,0x03,0x70,0x8f,0x7f,0xb1,0xe4,0xcb,0xab,0xc2,0xc7,0x00,0x02,0x00,0x60,0xff,0xe8, 0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x17,0x00,0x85,0x40,0x1f,0x19,0x40,0x0b,0x02,0x4d,0x12,0x95,0x00,0x16,0x0c,0x95,0x06,0x10,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x83,0x15,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x15,0xb8,0xff,0xf0,0x40,0x0b,0x0c,0x06,0x4d,0x20,0x15,0x30,0x15,0x90, 0x15,0x03,0x15,0xb8,0xff,0xde,0x40,0x2a,0x0b,0x06,0x4d,0x15,0x15,0x19,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x0a,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x83,0x03,0x10,0x0d,0x06,0x4d,0x03,0x0c,0x0c,0x06,0x4d,0x03,0x19,0x0b,0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d, 0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x01,0x2b,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x52,0xe3,0xfe,0xf1,0x01,0x1a,0xf0,0xe5,0x01,0x01,0xfe,0xeb,0xdd,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab,0x18,0x01,0x1f,0xed, 0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x03,0xa6,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0x00,0x03,0x00,0x60,0xfe,0x29,0x05,0x1f,0x05,0xec,0x00,0x0a,0x00,0x2f,0x00,0x38,0x00,0x93,0x40,0x5e,0x45,0x2d,0x01,0x46,0x2c,0x01,0x95,0x27,0x01,0x76,0x27,0x01,0x99,0x1c,0x01,0x96,0x16,0x01,0x34,0x16,0x01,0x25,0x16,0x01, 0x14,0x16,0x01,0x05,0x16,0x01,0x96,0x15,0x01,0x49,0x10,0x01,0x4c,0x0f,0x01,0x5b,0x08,0x01,0x3a,0x08,0x01,0x29,0x08,0x01,0x39,0x03,0x49,0x03,0x69,0x03,0x03,0x1e,0x83,0x30,0x19,0x2a,0x83,0x00,0x2f,0x05,0x25,0x84,0x19,0x12,0x83,0x13,0x35,0x0d,0x19,0x13,0x13,0x06,0x19,0x19,0x05,0x0d,0x36,0x95,0x25,0x35,0x24,0x00,0x18,0x06, 0x95,0x2f,0x0d,0x13,0x0b,0x1b,0x00,0x3f,0x3f,0x33,0xed,0x32,0x3f,0x39,0x39,0xed,0x11,0x39,0x39,0x11,0x12,0x39,0x2f,0x01,0x2f,0xc4,0xc4,0xde,0xed,0x10,0xfd,0xc4,0xc4,0xdc,0xed,0x10,0xdc,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x34,0x2e,0x02,0x27,0x11,0x3e, 0x03,0x01,0x23,0x11,0x2e,0x03,0x35,0x33,0x14,0x1e,0x02,0x17,0x11,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x01,0x14,0x1e,0x02,0x17,0x11,0x22,0x06,0x04,0x6f,0x29,0x53,0x7d,0x54,0x4c,0x7b,0x57,0x2f,0xfe,0xb3,0xa8,0x71,0xc5,0x91,0x53,0xb1,0x38,0x62,0x84,0x4b,0x6d,0x9c,0x63,0x2f,0x37, 0x69,0x99,0x62,0xa8,0x80,0xbf,0x7f,0x3f,0x4e,0x89,0xba,0x6c,0xfe,0x6d,0x29,0x43,0x54,0x2b,0x7c,0x6f,0x01,0xe9,0x3f,0x64,0x50,0x40,0x1b,0xfd,0x4f,0x0b,0x32,0x55,0x7c,0xfc,0x95,0x01,0xc2,0x07,0x49,0x84,0xbd,0x7d,0x50,0x83,0x60,0x3a,0x08,0x02,0xde,0x1e,0x47,0x56,0x67,0x3c,0x46,0x6f,0x4e,0x29,0xfd,0xea,0x1e,0x61,0x7c,0x9b, 0x57,0x7e,0xb7,0x7b,0x42,0x0a,0x04,0xd7,0x30,0x3b,0x2e,0x22,0x0d,0x01,0x56,0x4f,0x00,0x01,0x00,0x90,0xff,0xe8,0x05,0x5e,0x05,0xec,0x00,0x13,0x00,0x42,0x40,0x27,0x76,0x0b,0x01,0x67,0x0b,0x01,0x8b,0x06,0x9b,0x06,0x02,0x28,0x06,0x01,0x11,0x84,0x03,0x01,0x0f,0x13,0x0f,0x13,0x15,0x09,0x84,0x07,0x11,0x0f,0x09,0x00,0x0c,0x95, 0x02,0x05,0x16,0x12,0x95,0x01,0x15,0x00,0x3f,0xed,0x3f,0x33,0xed,0x3f,0x3f,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0xc4,0x33,0xed,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x21,0x21,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x21,0x05,0x5e,0xfd,0xe0,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78, 0x9b,0xa4,0x01,0x7c,0xa2,0xba,0x01,0xb4,0x04,0x50,0xfb,0xca,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0xfc,0x98,0x00,0x02,0x00,0x70,0xff,0xea,0x01,0x50,0x04,0x16,0x00,0x0b,0x00,0x17,0x00,0x36,0x40,0x12,0x00,0xb0,0x06,0x10,0x12,0xb0,0x0c,0x13,0x09,0x03,0x15,0xaf,0x1f,0x0f,0x2f,0x0f,0x02,0x0f,0xb8,0xff,0xec,0xb3,0x0c,0x06,0x4d,0x0f, 0xb8,0xff,0xec,0xb6,0x0b,0x06,0x4d,0x0f,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x71,0xe1,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xdf,0x2e,0x41,0x41,0x2e,0x2f,0x42,0x42,0x2f,0x2e,0x41,0x41,0x2e,0x2f, 0x42,0x42,0x03,0x38,0x42,0x2e,0x2e,0x40,0x40,0x2e,0x2e,0x42,0xfc,0xb2,0x42,0x2e,0x2e,0x43,0x43,0x2e,0x2e,0x42,0x00,0x01,0x00,0x2a,0x00,0x00,0x02,0x19,0x00,0xc8,0x00,0x09,0x00,0x35,0x40,0x1f,0x07,0x08,0x08,0x0b,0x73,0x03,0x83,0x03,0x02,0x55,0x03,0x65,0x03,0x02,0x46,0x03,0x01,0x27,0x03,0x37,0x03,0x02,0x03,0x02,0x02,0x03, 0x07,0x05,0x08,0x00,0x15,0x00,0x3f,0x32,0xdd,0x32,0xce,0x32,0x01,0x2f,0x33,0x71,0x71,0x71,0x71,0x12,0x39,0x2f,0x33,0x31,0x30,0x21,0x22,0x27,0x37,0x16,0x33,0x32,0x37,0x17,0x06,0x01,0x19,0xa6,0x49,0x59,0x27,0x70,0x66,0x7b,0x1e,0x84,0x86,0x42,0x59,0x20,0x63,0x2c,0x00,0x01,0x00,0x90,0xff,0xe8,0x08,0x69,0x05,0xec,0x00,0x23, 0x00,0x79,0x40,0x4b,0x9b,0x20,0x01,0x85,0x13,0x01,0x76,0x13,0x01,0x67,0x13,0x01,0x85,0x0b,0x01,0x66,0x0b,0x76,0x0b,0x02,0x57,0x0b,0x01,0x9b,0x06,0x01,0x03,0x01,0x23,0x84,0x0f,0x12,0x84,0x21,0x1d,0x1b,0x19,0x84,0x17,0x80,0x0f,0x01,0x4f,0x21,0x01,0x0f,0x21,0x17,0x17,0x21,0x0f,0x03,0x25,0x09,0x84,0x07,0x23,0x95,0x10,0x00, 0x18,0x09,0x0f,0x1c,0x14,0x95,0x1f,0x0c,0x95,0x02,0x05,0x16,0x1a,0x00,0x15,0x00,0x3f,0xc4,0x3f,0x33,0xed,0xd4,0xed,0x33,0x3f,0xc4,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x5d,0x10,0xed,0xc4,0x32,0x10,0xed,0x10,0xed,0xc4,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x35,0x23,0x06, 0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x21,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x21,0x03,0xe2,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x02,0x7c,0xf8,0x78,0x9b,0xa4,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xfe,0xcb,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd, 0xb6,0xfe,0xbc,0xb1,0x8f,0x04,0x3a,0xfb,0xca,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0xfc,0x00,0xa2,0xba,0x01,0xb4,0x03,0xb8,0x00,0x00,0x01,0x00,0x90,0xff,0xe8,0x08,0x9b,0x05,0xec,0x00,0x28,0x00,0x8c,0x40,0x58,0x85,0x20,0x01,0x66,0x20,0x76,0x20,0x02,0x57,0x20,0x01,0x9b,0x1b,0x01,0x9a,0x10,0x01,0x85,0x03,0x01,0x66,0x03,0x76,0x03, 0x02,0x18,0x16,0x15,0x84,0x24,0x27,0x01,0x84,0x12,0x0d,0x0b,0x07,0x28,0x28,0x09,0x84,0x07,0x20,0x24,0x80,0x24,0x02,0x3f,0x12,0x01,0x10,0x07,0x70,0x07,0x02,0x24,0x12,0x07,0x07,0x12,0x24,0x03,0x2a,0x1e,0x84,0x1c,0x08,0x00,0x95,0x1e,0x27,0x0f,0x14,0x95,0x25,0x00,0x0c,0x04,0x95,0x0f,0x21,0x95,0x17,0x1a,0x16,0x0b,0x15,0x0f, 0x00,0x3f,0xc4,0x3f,0x33,0xed,0xd4,0xed,0x33,0x3f,0xed,0x3f,0xc4,0xfd,0xce,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x5d,0x5d,0x10,0xed,0x32,0x2f,0x10,0xc4,0x32,0x10,0xfd,0xc4,0x10,0xed,0xc4,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23, 0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x21,0x11,0x21,0x08,0x9b,0xfd,0x20,0xee,0x7b,0xa1,0xa4,0xa4,0x04,0x74,0xdc,0xa8,0xb2,0xfe,0xcb,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x02,0x7d,0x02,0xe0,0x03,0x68,0xfe,0x50,0xfe,0xba,0xb9, 0x8d,0x01,0x18,0xfd,0x30,0xaa,0xc2,0xd9,0xcd,0x03,0xc6,0xfa,0xac,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x04,0x3a,0xfe,0x14,0x00,0x00,0x01,0x00,0x90,0xfe,0x29,0x08,0x69,0x05,0xec,0x00,0x23,0x00,0x81,0x40,0x52,0x92,0x22,0x01,0x85,0x17,0x01,0x66,0x17,0x76,0x17,0x02,0x57,0x17,0x01,0x9b,0x12,0x01,0x8a, 0x03,0x01,0x79,0x03,0x01,0x68,0x03,0x01,0x0f,0x0d,0x0b,0x84,0x1b,0x1f,0x1d,0x07,0x84,0x09,0x23,0x84,0x02,0x20,0x1b,0x80,0x1b,0x02,0x7f,0x09,0x01,0x10,0x02,0x01,0x1b,0x09,0x02,0x02,0x09,0x1b,0x03,0x25,0x15,0x84,0x13,0x1e,0x04,0x95,0x21,0x10,0x0a,0x95,0x1c,0x00,0x15,0x0f,0x18,0x95,0x0e,0x11,0x16,0x01,0x0c,0x15,0x08,0x1b, 0x00,0x3f,0x3f,0xc4,0x3f,0x33,0xed,0x3f,0x3f,0xed,0x3f,0xed,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x5d,0x5d,0x10,0xed,0x10,0xfd,0xc4,0x33,0x10,0xed,0xc4,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x21,0x11,0x23,0x35,0x23,0x06,0x23,0x20, 0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x21,0x11,0x33,0x36,0x33,0x20,0x11,0x08,0x69,0xa4,0xee,0x78,0xa4,0xa4,0xfe,0xcb,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x02,0x7d,0x04,0x76,0xda,0x01,0x5a,0x02,0x4e,0x01,0x40,0xb9,0x91,0xfb,0xe5,0x07,0x2b,0xfa,0xac,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe, 0xbc,0xb1,0x8f,0x04,0x3a,0xfd,0x6a,0xc2,0xfe,0x5f,0x00,0x01,0x00,0x90,0xfe,0x29,0x08,0x69,0x05,0xec,0x00,0x25,0x00,0x81,0x40,0x51,0x85,0x21,0x01,0x66,0x21,0x76,0x21,0x02,0x57,0x21,0x01,0x9c,0x1c,0x01,0x9b,0x10,0x01,0x75,0x03,0x85,0x03,0x02,0x66,0x03,0x01,0x16,0x14,0x84,0x19,0x17,0x25,0x02,0x84,0x11,0x0d,0x0b,0x09,0x84, 0x07,0x80,0x25,0x01,0x4f,0x11,0x01,0xc0,0x07,0x01,0x25,0x11,0x07,0x07,0x11,0x25,0x03,0x27,0x1f,0x84,0x1d,0x08,0x1f,0x0f,0x15,0x95,0x17,0x1b,0x22,0x95,0x18,0x1b,0x0c,0x04,0x95,0x0f,0x16,0x0a,0x15,0x12,0x95,0x00,0x00,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x33,0xd4,0x32,0xed,0x3f,0xed,0x3f,0xc4,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f, 0x2f,0x2f,0x5d,0x5d,0x5d,0x10,0xed,0xc4,0x33,0x10,0xed,0x10,0xc4,0x33,0xfd,0xcd,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x01,0x21,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x21,0x11,0x33,0x15,0x21,0x11,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x03, 0x3e,0x02,0x7c,0xf8,0x78,0x9b,0xa4,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xfe,0xcb,0xa5,0xfe,0xb7,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x05,0xec,0xfb,0xca,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0xfc,0x00,0xa2,0xba,0x01,0xb4,0x03,0xb8,0xf9,0x6d,0x98,0x02,0x79,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x00,0x00,0x01, 0x00,0x90,0xfe,0x29,0x0a,0xc2,0x05,0xec,0x00,0x31,0x00,0x90,0x40,0x59,0x85,0x2b,0x01,0x76,0x2b,0x01,0x67,0x2b,0x01,0x83,0x1d,0x01,0x66,0x1d,0x76,0x1d,0x02,0x57,0x1d,0x01,0x9b,0x18,0x01,0x9a,0x09,0x01,0x88,0x09,0x01,0x9b,0x06,0x01,0x15,0x13,0x11,0x84,0x21,0x25,0x23,0x0d,0x84,0x0f,0x29,0x84,0x07,0x03,0x01,0x31,0x84,0x2f, 0x21,0x0f,0x07,0x2f,0x2f,0x07,0x0f,0x21,0x04,0x33,0x1b,0x84,0x19,0x24,0x0a,0x95,0x27,0x10,0x10,0x95,0x22,0x00,0x30,0x1b,0x0f,0x2c,0x95,0x02,0x05,0x1e,0x95,0x14,0x17,0x16,0x01,0x12,0x15,0x0e,0x1b,0x00,0x3f,0x3f,0xc4,0x3f,0x33,0xed,0xd4,0x32,0xed,0x3f,0xc4,0x3f,0xed,0x3f,0xed,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f, 0x2f,0x2f,0x10,0xed,0xc4,0x32,0x10,0xed,0x10,0xfd,0xc4,0x33,0x10,0xed,0xc4,0x32,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x35,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x21,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35,0x11,0x21, 0x11,0x33,0x36,0x33,0x20,0x11,0x15,0x10,0x33,0x32,0x36,0x35,0x11,0x33,0x0a,0xc2,0xa4,0x04,0x66,0xc7,0xfe,0xab,0xc1,0x78,0xa4,0xa4,0xfe,0xcb,0xa4,0x04,0x66,0xd6,0xfe,0x92,0xa3,0xf8,0x78,0x9b,0x02,0x7d,0x04,0x76,0xda,0x01,0x2c,0xdf,0x69,0x9b,0xa4,0xa2,0xba,0x01,0xb4,0xb2,0x01,0x40,0xb9,0x91,0xfb,0xe5,0x07,0x2b,0xfa,0xac, 0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0xb1,0x8f,0x04,0x3a,0xfd,0x6a,0xc2,0xfe,0x5f,0xc1,0xfe,0xbc,0xb1,0x8f,0x02,0x4e,0x00,0x01,0x00,0x83,0x00,0x00,0x04,0x0a,0x05,0x9a,0x00,0x2b,0x00,0x5a,0x40,0x30,0x0f,0x09,0x1c,0x1b,0x11,0x0e,0x7e,0x01,0x2a,0x14,0x01,0x08,0x09,0x1b,0x01,0x01,0x1b,0x09,0x03,0x2d,0x24,0x00, 0x08,0x14,0x23,0x92,0x24,0x11,0x2b,0x92,0x0e,0x00,0x00,0x00,0x24,0x10,0x24,0x02,0x24,0x24,0x08,0x1c,0x12,0x0b,0x07,0x92,0x08,0x03,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x5d,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x01,0x2f,0x33,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x32,0x10,0xed,0x32,0x11,0x33,0x11,0x33, 0x31,0x30,0x13,0x21,0x2e,0x03,0x23,0x23,0x35,0x21,0x15,0x21,0x16,0x16,0x17,0x21,0x15,0x21,0x06,0x06,0x07,0x15,0x1e,0x03,0x17,0x13,0x23,0x03,0x2e,0x03,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x37,0x21,0x83,0x01,0xe5,0x08,0x25,0x43,0x63,0x44,0xce,0x03,0x87,0xfe,0xb8,0x1d,0x25,0x06,0x01,0x00,0xfe,0xfb,0x15,0x9b,0x77,0x22,0x38, 0x34,0x33,0x1d,0xff,0xbe,0xe4,0x21,0x3b,0x43,0x51,0x36,0x70,0xcd,0x33,0x5c,0x49,0x33,0x0b,0xfe,0x1d,0x04,0x53,0x2a,0x45,0x31,0x1b,0x8c,0x8c,0x25,0x5d,0x39,0x8c,0x78,0xa9,0x20,0x04,0x10,0x2a,0x37,0x48,0x2e,0xfe,0x65,0x01,0x7e,0x37,0x54,0x38,0x1c,0x89,0x21,0x3b,0x53,0x32,0x00,0x02,0x00,0x37,0x00,0x00,0x04,0x1a,0x05,0x9a, 0x00,0x07,0x00,0x0b,0x00,0x3b,0x40,0x1f,0x0b,0x00,0x02,0x7e,0x08,0x05,0x00,0x0d,0x05,0x0c,0x03,0x03,0x0d,0x0c,0x01,0x05,0x91,0x00,0x06,0x10,0x06,0x02,0x06,0x06,0x03,0x08,0x91,0x09,0x03,0x03,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x32,0x11,0x12,0x01,0x39,0x2f,0x12,0x39,0x12,0x39,0x11,0x33,0xed,0x11,0x33,0x31, 0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x25,0x35,0x21,0x15,0x04,0x1a,0xfe,0x62,0xa8,0xfe,0x63,0x03,0xe3,0xfc,0x1d,0x03,0xe3,0x03,0xdc,0xfc,0x24,0x03,0xdc,0x98,0x8e,0x98,0x98,0xff,0xff,0x00,0x90,0x00,0x00,0x01,0x66,0x05,0xd9,0x02,0x06,0x00,0x4c,0x00,0x00,0x00,0x02,0x00,0x5c,0xff,0xe7,0x03,0xf4,0x04,0x19,0x00,0x0d, 0x00,0x18,0x00,0x22,0xbc,0x00,0x00,0x01,0x86,0x00,0x0e,0x00,0x13,0x01,0x86,0x40,0x09,0x08,0x10,0x9a,0x0b,0x10,0x16,0x9a,0x05,0x18,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x02,0x35,0x10,0x12,0x33,0x32,0x12,0x03,0x10,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xf4, 0x3d,0x77,0xaf,0x72,0xd9,0xea,0xf4,0xeb,0xe0,0xd9,0xac,0xfe,0xe9,0x8f,0x9c,0x91,0x90,0x8c,0x95,0x02,0x04,0x83,0xc9,0x8a,0x47,0x01,0x06,0xff,0x01,0x14,0x01,0x19,0xfe,0xf0,0xfe,0xf5,0x01,0x93,0xcb,0xd0,0xbf,0xc8,0xcd,0x00,0x00,0x01,0x00,0x79,0x00,0x00,0x02,0x71,0x04,0x1e,0x00,0x0e,0x00,0x24,0xbc,0x00,0x00,0x01,0x86,0x00, 0x01,0x00,0x08,0x01,0x81,0x40,0x09,0x02,0x0d,0x07,0x07,0x01,0x0d,0x10,0x01,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x0e,0x03,0x07,0x35,0x3e,0x03,0x37,0x33,0x02,0x71,0xac,0x13,0x49,0x5b,0x65,0x30,0x36,0x79,0x75,0x68,0x26,0x46,0x03,0x3b,0x13,0x31,0x30,0x2a,0x0c,0xa6,0x0f, 0x33,0x3f,0x45,0x21,0x00,0x01,0x00,0x99,0x00,0x00,0x03,0xd3,0x04,0x1b,0x00,0x26,0x00,0x34,0xb9,0x00,0x1b,0x01,0x86,0xb5,0x12,0x0a,0x0a,0x00,0x25,0x24,0xb8,0x01,0x86,0xb6,0x00,0x03,0x0a,0x12,0x03,0x24,0x0d,0xb8,0x01,0x7f,0xb5,0x16,0x10,0x24,0x99,0x00,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0xed,0x2f,0x12, 0x39,0x2f,0x39,0xed,0x31,0x30,0x33,0x35,0x34,0x3e,0x06,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x06,0x15,0x21,0x15,0x99,0x32,0x53,0x69,0x6e,0x69,0x53,0x32,0x7a,0x67,0x27,0x55,0x57,0x54,0x25,0x48,0xb5,0x67,0x5b,0x8a,0x5e,0x30,0x33,0x52,0x6a,0x6f,0x6a,0x52,0x33,0x02,0x93, 0x58,0x48,0x6d,0x56,0x44,0x3b,0x3a,0x40,0x4e,0x33,0x55,0x5d,0x12,0x20,0x2c,0x1a,0x9d,0x36,0x31,0x2b,0x4f,0x70,0x45,0x40,0x67,0x55,0x46,0x3e,0x39,0x3b,0x3f,0x26,0x93,0x00,0x00,0x01,0x00,0x7b,0xfe,0x50,0x03,0xb8,0x04,0x1b,0x00,0x2a,0x00,0x43,0x40,0x1b,0x16,0x89,0x1b,0x13,0x25,0x03,0x08,0x23,0x23,0x08,0x00,0x89,0x0f,0x0f, 0x2c,0x08,0x25,0x12,0x9a,0x08,0x05,0x1b,0x1e,0x13,0x13,0x05,0x18,0xb8,0x01,0x7f,0xb4,0x1e,0x10,0x0a,0x9a,0x05,0x00,0x2f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0xed,0x39,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x05,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02, 0x35,0x10,0x21,0x23,0x35,0x33,0x20,0x11,0x34,0x21,0x22,0x06,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x10,0x05,0x15,0x1e,0x03,0x03,0xb8,0x4a,0x85,0xb9,0x6f,0xcb,0x7b,0x91,0xbb,0x4a,0x7a,0x56,0x2f,0xfe,0x71,0x77,0x71,0x01,0x62,0xfe,0xf2,0x4b,0x90,0x42,0x88,0xbe,0x5b,0x92,0x68,0x38,0xfe,0xe1,0x4b,0x7c,0x59,0x32,0x02,0x60, 0x9f,0x71,0x3e,0x4e,0xb0,0x73,0x27,0x48,0x66,0x40,0x01,0x18,0x8b,0x01,0x09,0xf3,0x33,0x33,0xa0,0x52,0x32,0x5b,0x7e,0x4b,0xfe,0xe6,0x53,0x04,0x07,0x37,0x59,0x78,0x00,0x02,0x00,0x32,0xfe,0x68,0x04,0x2e,0x04,0x02,0x00,0x0e,0x00,0x15,0x00,0x31,0xb2,0x10,0x0e,0x05,0xb8,0x01,0x85,0x40,0x12,0x0f,0x09,0x06,0x06,0x17,0x09,0x11, 0x07,0x0e,0x10,0x09,0x01,0x10,0x9a,0x04,0x07,0x18,0x06,0x00,0x2f,0x3f,0x33,0xed,0x32,0x32,0x3f,0x12,0x39,0x01,0x2f,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x33,0x31,0x30,0x01,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x35,0x3e,0x03,0x37,0x01,0x21,0x11,0x0e,0x03,0x03,0x76,0xb8,0xb8,0xa2,0xfd,0x5e,0x5e,0xc0,0xaf,0x95,0x33,0xfe, 0x24,0x01,0xe9,0x46,0x83,0x7b,0x72,0x04,0x02,0xfc,0x83,0x85,0xfe,0x68,0x01,0x98,0x7d,0x64,0xe3,0xea,0xe9,0x6b,0xfc,0x83,0x02,0x89,0x75,0xbc,0x9b,0x82,0x00,0x01,0x00,0xa4,0xfe,0x4d,0x03,0xc9,0x04,0x00,0x00,0x23,0x00,0x35,0xb9,0x00,0x1c,0x01,0x85,0xb3,0x17,0x17,0x08,0x00,0xb8,0x01,0x86,0xb2,0x0f,0x08,0x12,0xb8,0x01,0x7f, 0xb7,0x1f,0x1f,0x0a,0x1b,0x99,0x18,0x0f,0x0a,0xb9,0x01,0x7f,0x00,0x05,0x00,0x2f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x13,0x21,0x15,0x21,0x03,0x36,0x36,0x33,0x32,0x1e, 0x02,0x03,0xc9,0x48,0x85,0xbc,0x73,0xc8,0x61,0x92,0x99,0x4e,0x7d,0x58,0x2f,0xbc,0xb3,0x1d,0x40,0x40,0x3d,0x19,0x31,0x02,0x97,0xfd,0xf7,0x1d,0x20,0x48,0x1c,0x72,0xb4,0x7d,0x41,0x1c,0x69,0xaa,0x7a,0x42,0x3c,0xae,0x5e,0x2e,0x52,0x74,0x45,0x8c,0x9f,0x02,0x03,0x04,0x03,0x02,0xcf,0x94,0xfe,0x5b,0x02,0x03,0x3c,0x6f,0xa1,0x00, 0x00,0x02,0x00,0x6f,0xff,0xe7,0x03,0xfe,0x05,0xb2,0x00,0x20,0x00,0x34,0x00,0x36,0xb3,0x12,0x2b,0x19,0x00,0xbb,0x01,0x86,0x00,0x21,0x00,0x19,0x01,0x86,0x40,0x0c,0x0a,0x26,0x9a,0x19,0x1c,0x1c,0x30,0x14,0x9a,0x0f,0x06,0x30,0xb8,0x01,0x7f,0xb1,0x05,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x2f, 0xed,0x11,0x39,0x39,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xfe,0x44,0x78,0xa6,0x61,0x6c,0xab,0x77,0x3e,0x53,0x99,0xd8, 0x85,0x94,0x5a,0x6f,0x7b,0x60,0x9a,0x6e,0x3b,0x04,0x63,0xe4,0x5e,0x97,0x6b,0x3a,0xa8,0x26,0x47,0x68,0x42,0x3d,0x68,0x4c,0x2b,0x2a,0x4c,0x69,0x40,0x3e,0x66,0x48,0x28,0x01,0xc7,0x69,0xb0,0x80,0x47,0x5a,0xa9,0xf4,0x99,0xbb,0x01,0x31,0xd9,0x76,0x29,0x9b,0x39,0x56,0x9d,0xde,0x88,0xb3,0x40,0x75,0xa2,0x78,0x4b,0x78,0x54,0x2d, 0x2e,0x4f,0x69,0x3b,0x4a,0x81,0x60,0x37,0x2f,0x54,0x75,0x00,0x00,0x01,0x00,0x45,0xfe,0x66,0x03,0xd5,0x04,0x00,0x00,0x12,0x00,0x22,0xb9,0x00,0x07,0x01,0x86,0x40,0x0c,0x0f,0x08,0x08,0x00,0x10,0x00,0x00,0x10,0x99,0x11,0x0f,0x08,0x00,0x2f,0x3f,0xed,0x39,0x01,0x2f,0x2f,0x12,0x39,0x2f,0x39,0xed,0x31,0x30,0x01,0x0e,0x03,0x02, 0x02,0x07,0x23,0x36,0x12,0x12,0x3e,0x02,0x37,0x21,0x35,0x21,0x03,0xd5,0x21,0x5d,0x68,0x6c,0x5e,0x47,0x10,0xb0,0x12,0x4b,0x5f,0x6a,0x64,0x53,0x19,0xfd,0x31,0x03,0x90,0x03,0xa1,0x39,0xaa,0xd4,0xf4,0xfe,0xfc,0xfe,0xf5,0x81,0x80,0x01,0x0b,0x01,0x01,0xee,0xc8,0x99,0x2b,0x94,0x00,0x03,0x00,0x5a,0xff,0xe9,0x03,0xfc,0x05,0xb2, 0x00,0x23,0x00,0x37,0x00,0x4b,0x00,0x47,0x40,0x25,0x38,0x89,0x08,0x42,0x8a,0x12,0x05,0x15,0x12,0x08,0x12,0x08,0x12,0x00,0x1a,0x89,0x2e,0x2e,0x4d,0x24,0x89,0x00,0x05,0x15,0x33,0x9a,0x3d,0x3d,0x0d,0x29,0x99,0x1f,0x18,0x47,0x9a,0x0d,0x06,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f, 0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x37,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x13,0x14,0x1e,0x02, 0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x5a,0x24,0x43,0x63,0x3f,0x5d,0x6e,0x3d,0x6c,0x94,0x56,0x57,0x94,0x6c,0x3c,0x6e,0x5b,0x3e,0x62,0x43,0x24,0x44,0x7b,0xab,0x67,0x66,0xaa,0x7c,0x45,0xb2,0x29,0x4b,0x6b,0x41,0x3f,0x6a,0x4d,0x2b,0x29,0x4c,0x6a,0x42,0x3e,0x69,0x4d,0x2c,0x33,0x25,0x41,0x56,0x31,0x31, 0x57,0x40,0x26,0x25,0x40,0x57,0x32,0x35,0x57,0x3f,0x22,0x01,0x90,0x39,0x73,0x64,0x52,0x18,0x34,0xa3,0x63,0x4f,0x86,0x62,0x37,0x38,0x62,0x86,0x4e,0x63,0xa3,0x34,0x18,0x52,0x64,0x73,0x39,0x5e,0x9c,0x6f,0x3e,0x3e,0x6f,0x9c,0x6c,0x43,0x6c,0x4c,0x29,0x2a,0x4c,0x6c,0x42,0x3c,0x69,0x50,0x2e,0x2b,0x4d,0x6b,0x02,0x59,0x33,0x57, 0x41,0x25,0x26,0x41,0x57,0x32,0x34,0x58,0x40,0x25,0x26,0x41,0x58,0x00,0x00,0x02,0x00,0x5e,0xfe,0x4e,0x03,0xec,0x04,0x19,0x00,0x20,0x00,0x34,0x00,0x33,0x40,0x16,0x21,0x00,0x89,0x08,0x17,0x10,0x10,0x36,0x2b,0x89,0x17,0x30,0x99,0x0f,0x12,0x12,0x05,0x26,0x9a,0x1c,0x10,0x0a,0xb9,0x01,0x7f,0x00,0x05,0x00,0x2f,0xed,0x3f,0xed, 0x11,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x31,0x30,0x01,0x14,0x02,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xec, 0x4e,0x96,0xd8,0x8a,0x8e,0x6c,0x77,0x87,0x61,0x99,0x6a,0x38,0x04,0x5c,0xe4,0x5c,0x9a,0x70,0x3e,0x45,0x7b,0xa9,0x64,0x6c,0xa7,0x72,0x3c,0xb1,0x2b,0x4c,0x69,0x3e,0x3b,0x66,0x4b,0x2b,0x29,0x4c,0x6b,0x41,0x39,0x65,0x4b,0x2b,0x01,0x8a,0xc5,0xfe,0xcd,0xd5,0x6f,0x32,0x9d,0x43,0x50,0x99,0xe0,0x91,0xb9,0x41,0x77,0xa4,0x63,0x6a, 0xb0,0x7f,0x46,0x57,0xa7,0xf4,0x0a,0x53,0x88,0x61,0x35,0x2f,0x55,0x75,0x45,0x4c,0x78,0x53,0x2c,0x2b,0x49,0x63,0xff,0xff,0x00,0x5c,0xff,0xe7,0x03,0xf4,0x04,0x19,0x02,0x06,0x0c,0xb9,0x00,0x00,0x00,0x01,0x00,0xe8,0x00,0x00,0x02,0xe0,0x04,0x1e,0x00,0x0e,0x00,0x24,0xbc,0x00,0x00,0x01,0x86,0x00,0x01,0x00,0x08,0x01,0x81,0x40, 0x09,0x02,0x0d,0x07,0x07,0x01,0x0d,0x10,0x01,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x0e,0x03,0x07,0x35,0x3e,0x03,0x37,0x33,0x02,0xe0,0xac,0x13,0x49,0x5b,0x65,0x30,0x36,0x79,0x75,0x68,0x26,0x46,0x03,0x3b,0x13,0x31,0x30,0x2a,0x0c,0xa6,0x0f,0x33,0x3f,0x45,0x21,0xff,0xff, 0x00,0x99,0x00,0x00,0x03,0xd3,0x04,0x1b,0x02,0x06,0x0c,0xbb,0x00,0x00,0xff,0xff,0x00,0x7b,0xfe,0x50,0x03,0xb8,0x04,0x1b,0x02,0x06,0x0c,0xbc,0x00,0x00,0xff,0xff,0x00,0x32,0xfe,0x68,0x04,0x2e,0x04,0x02,0x00,0x06,0x0c,0xbd,0x00,0x00,0xff,0xff,0x00,0xa4,0xfe,0x4d,0x03,0xc9,0x04,0x00,0x02,0x06,0x0c,0xbe,0x00,0x00,0xff,0xff, 0x00,0x6f,0xff,0xe7,0x03,0xfe,0x05,0xb2,0x02,0x06,0x0c,0xbf,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x66,0x03,0xf0,0x04,0x00,0x00,0x06,0x0c,0xc0,0x1b,0x00,0xff,0xff,0x00,0x5a,0xff,0xe9,0x03,0xfc,0x05,0xb2,0x02,0x06,0x0c,0xc1,0x00,0x00,0xff,0xff,0x00,0x5e,0xfe,0x4e,0x03,0xec,0x04,0x19,0x02,0x06,0x0c,0xc2,0x00,0x00,0x00,0x02, 0x00,0x56,0xff,0xe7,0x03,0xfc,0x05,0xb2,0x00,0x10,0x00,0x18,0x00,0x20,0x40,0x10,0x00,0x89,0x11,0x11,0x1a,0x15,0x89,0x0a,0x13,0x9a,0x0f,0x07,0x17,0x9a,0x05,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x02,0x06,0x06,0x23,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x20,0x03, 0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x03,0xfc,0x41,0x7b,0xb3,0x72,0x6c,0xa9,0x74,0x3c,0x3f,0x7a,0xb5,0x75,0x01,0xc3,0xa8,0xfe,0xdd,0xfe,0xcd,0x01,0x2d,0x01,0x29,0x02,0xd3,0xb4,0xfe,0xea,0xbf,0x63,0x5f,0xb6,0x01,0x09,0xab,0xbc,0x01,0x20,0xc3,0x63,0xfd,0x11,0x02,0x64,0xfd,0x91,0xfd,0xbb,0x00,0x00,0x01,0x00,0x53,0x00,0x00, 0x02,0x43,0x05,0xba,0x00,0x0e,0x00,0x28,0x40,0x13,0x0e,0x8a,0x00,0x06,0x00,0x06,0x00,0x0f,0x10,0x07,0x99,0x01,0x0c,0x06,0x06,0x0c,0x07,0x00,0x18,0x00,0x3f,0x3f,0x39,0x2f,0x12,0x39,0xed,0x11,0x12,0x01,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x21,0x11,0x0e,0x03,0x07,0x35,0x3e,0x03,0x37,0x33,0x11,0x01,0x9f,0x13,0x49,0x5b, 0x65,0x30,0x36,0x79,0x75,0x68,0x26,0x3e,0x04,0xd7,0x13,0x31,0x30,0x2a,0x0c,0xa6,0x0f,0x33,0x3f,0x45,0x21,0xfa,0x46,0x00,0x00,0x01,0x00,0x6d,0x00,0x00,0x03,0xe2,0x05,0xb2,0x00,0x2a,0x00,0x2e,0x40,0x17,0x1e,0x13,0x89,0x0a,0x21,0x00,0x00,0x2c,0x1d,0x89,0x21,0x00,0x0e,0x1d,0x99,0x20,0x18,0x0a,0x0a,0x05,0x9a,0x0e,0x07,0x00, 0x3f,0xed,0x32,0x2f,0x3f,0xed,0x11,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x32,0x31,0x30,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x03,0x15,0x21,0x15,0x21,0x35,0x34,0x3e,0x02,0x37,0x3e,0x03,0x03,0x04,0x29,0x47,0x60,0x38,0x30,0x5c,0x57,0x51, 0x23,0x45,0xab,0x7b,0x58,0x96,0x6e,0x3f,0x27,0x4f,0x78,0x51,0x65,0x83,0x4d,0x1f,0x02,0xca,0xfc,0x8b,0x28,0x5c,0x95,0x6c,0x4e,0x69,0x40,0x1b,0x04,0x22,0x42,0x62,0x41,0x20,0x1a,0x2e,0x40,0x27,0xb0,0x43,0x47,0x33,0x62,0x90,0x5d,0x55,0x8a,0x7a,0x70,0x3a,0x48,0x66,0x59,0x59,0x3a,0x93,0x47,0x5c,0x8c,0x7e,0x7e,0x4f,0x38,0x66, 0x66,0x69,0x00,0x01,0x00,0x7b,0xff,0xe7,0x03,0xb9,0x05,0xb2,0x00,0x29,0x00,0x55,0x40,0x32,0x16,0x89,0x1a,0x13,0x24,0x03,0x08,0x22,0x22,0x08,0x00,0x89,0x0f,0x0f,0x2b,0x08,0x39,0x1a,0x01,0x2f,0x1a,0x01,0x1a,0x1a,0x18,0x9a,0x1d,0x24,0x12,0x9a,0x13,0x13,0x1d,0x07,0x36,0x08,0x01,0x00,0x08,0x10,0x08,0x20,0x08,0x03,0x08,0x08, 0x0a,0x9a,0x05,0x19,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x5d,0x3f,0x39,0x2f,0xed,0x39,0x10,0xed,0x32,0x2f,0x5d,0x5d,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x10,0x21,0x23,0x35,0x33,0x20,0x11,0x34,0x21,0x22,0x07,0x35,0x36, 0x33,0x32,0x1e,0x02,0x15,0x10,0x05,0x15,0x1e,0x03,0x03,0xb9,0x49,0x85,0xba,0x70,0xcd,0x79,0x91,0xbb,0x4b,0x79,0x57,0x2f,0xfe,0x70,0x77,0x71,0x01,0x62,0xfe,0xf2,0x98,0x85,0x89,0xbd,0x5a,0x92,0x68,0x39,0xfe,0xe2,0x49,0x7c,0x5a,0x33,0x01,0x96,0x61,0x9f,0x71,0x3e,0x4e,0xb0,0x72,0x26,0x48,0x66,0x40,0x01,0x19,0x8b,0x01,0x08, 0xf4,0x66,0x9f,0x52,0x32,0x5a,0x7e,0x4c,0xfe,0xe5,0x51,0x04,0x08,0x37,0x58,0x77,0x00,0x02,0x00,0x32,0x00,0x00,0x04,0x56,0x05,0x9a,0x00,0x0e,0x00,0x15,0x00,0x2e,0x40,0x16,0x10,0x0e,0x04,0x8a,0x07,0x07,0x17,0x0f,0x09,0x04,0x08,0x99,0x09,0x01,0x0f,0x0f,0x06,0x11,0x0e,0x06,0x06,0x18,0x00,0x3f,0x3f,0x33,0x12,0x39,0x2f,0x33, 0x33,0xed,0x32,0x01,0x2f,0x33,0x12,0x39,0x2f,0xed,0x33,0x33,0x31,0x30,0x01,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x35,0x3e,0x03,0x37,0x01,0x21,0x11,0x0e,0x03,0x03,0x76,0xe0,0xe0,0xa2,0xfd,0x5e,0x5e,0xc0,0xaf,0x95,0x33,0xfe,0x24,0x01,0xe9,0x4b,0x86,0x79,0x6e,0x05,0x9a,0xfc,0x4d,0x96,0xfe,0xaf,0x01,0x51,0x8e,0x6a,0xf1, 0xf8,0xf7,0x71,0xfc,0x4d,0x02,0xbe,0x83,0xce,0xa8,0x88,0x00,0x00,0x01,0x00,0xa4,0xff,0xe7,0x03,0xc9,0x05,0x9a,0x00,0x23,0x00,0x3d,0x40,0x21,0x1c,0x8a,0x1a,0x17,0x17,0x08,0x00,0x89,0x0f,0x0f,0x25,0x08,0x12,0x9a,0x1f,0x1f,0x0a,0x1b,0x99,0x18,0x06,0x32,0x08,0x01,0x20,0x08,0x01,0x08,0x08,0x0a,0x9a,0x05,0x19,0x00,0x3f,0xed, 0x32,0x2f,0x5d,0x5d,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x39,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x13,0x21,0x15,0x21,0x03,0x36,0x36,0x33,0x32,0x1e,0x02,0x03,0xc9,0x48,0x85,0xbc,0x73,0xc8,0x61,0x92, 0x99,0x4e,0x7d,0x58,0x2f,0xbc,0xb3,0x1d,0x40,0x40,0x3d,0x19,0x31,0x02,0x97,0xfd,0xf7,0x1d,0x20,0x48,0x1c,0x72,0xb4,0x7d,0x41,0x01,0xb6,0x69,0xaa,0x7a,0x42,0x3c,0xae,0x5e,0x2e,0x52,0x74,0x45,0x8c,0x9f,0x02,0x03,0x04,0x03,0x02,0xcf,0x94,0xfe,0x5b,0x02,0x03,0x3c,0x6f,0xa1,0x00,0x02,0x00,0x6f,0xff,0xe7,0x03,0xfe,0x05,0xb2, 0x00,0x20,0x00,0x34,0x00,0x37,0x40,0x1c,0x12,0x0a,0x00,0x89,0x21,0x21,0x36,0x2b,0x19,0x89,0x0a,0x26,0x9a,0x1a,0x1c,0x1c,0x30,0x0f,0x12,0x12,0x14,0x9a,0x0f,0x07,0x30,0x9a,0x05,0x19,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x11,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x14,0x0e, 0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xfe,0x44,0x78,0xa6,0x61,0x6c,0xab,0x77,0x3e,0x53,0x99,0xd8,0x85,0x94,0x5a,0x6f,0x7b,0x60,0x9a,0x6e,0x3b, 0x04,0x63,0xe4,0x5e,0x97,0x6b,0x3a,0xa8,0x26,0x47,0x68,0x42,0x3d,0x68,0x4c,0x2b,0x2a,0x4c,0x69,0x40,0x3e,0x66,0x48,0x28,0x01,0xc7,0x69,0xb0,0x80,0x47,0x5a,0xa9,0xf4,0x99,0xbb,0x01,0x31,0xd9,0x76,0x29,0x9b,0x39,0x56,0x9d,0xde,0x88,0xb3,0x40,0x75,0xa2,0x78,0x4b,0x78,0x54,0x2d,0x2e,0x4f,0x69,0x3b,0x4a,0x81,0x60,0x37,0x2f, 0x54,0x75,0x00,0x01,0x00,0x45,0x00,0x00,0x03,0xd5,0x05,0x9a,0x00,0x12,0x00,0x24,0x40,0x11,0x07,0x89,0x0f,0x00,0x08,0x00,0x08,0x00,0x14,0x10,0x00,0x10,0x99,0x11,0x06,0x08,0x18,0x00,0x3f,0x3f,0xed,0x32,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x31,0x30,0x01,0x0e,0x03,0x02,0x02,0x07,0x23,0x36,0x12,0x12,0x3e,0x02, 0x37,0x21,0x35,0x21,0x03,0xd5,0x21,0x5d,0x68,0x6c,0x5e,0x47,0x10,0xb0,0x12,0x4b,0x5f,0x6a,0x64,0x53,0x19,0xfd,0x31,0x03,0x90,0x05,0x3b,0x39,0xaa,0xd4,0xf4,0xfe,0xfc,0xfe,0xf5,0x81,0x80,0x01,0x0b,0x01,0x01,0xee,0xc8,0x99,0x2b,0x94,0x00,0x03,0x00,0x5a,0xff,0xe9,0x03,0xfc,0x05,0xb2,0x00,0x23,0x00,0x37,0x00,0x4b,0x00,0x47, 0x40,0x25,0x38,0x89,0x08,0x42,0x8a,0x12,0x05,0x15,0x12,0x08,0x12,0x08,0x12,0x00,0x1a,0x89,0x2e,0x2e,0x4d,0x24,0x89,0x00,0x15,0x05,0x33,0x9a,0x3d,0x3d,0x0d,0x29,0x99,0x1f,0x19,0x47,0x9a,0x0d,0x07,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xed,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39, 0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x37,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02, 0x23,0x22,0x0e,0x02,0x5a,0x24,0x43,0x63,0x3f,0x5d,0x6e,0x3d,0x6c,0x94,0x56,0x57,0x94,0x6c,0x3c,0x6e,0x5b,0x3e,0x62,0x43,0x24,0x44,0x7b,0xab,0x67,0x66,0xaa,0x7c,0x45,0xb2,0x29,0x4b,0x6b,0x41,0x3f,0x6a,0x4d,0x2b,0x29,0x4c,0x6a,0x42,0x3e,0x69,0x4d,0x2c,0x33,0x25,0x41,0x56,0x31,0x31,0x57,0x40,0x26,0x25,0x40,0x57,0x32,0x35, 0x57,0x3f,0x22,0x01,0x90,0x39,0x73,0x64,0x52,0x18,0x34,0xa3,0x63,0x4f,0x86,0x62,0x37,0x38,0x62,0x86,0x4e,0x63,0xa3,0x34,0x18,0x52,0x64,0x73,0x39,0x5e,0x9c,0x6f,0x3e,0x3e,0x6f,0x9c,0x6c,0x43,0x6c,0x4c,0x29,0x2a,0x4c,0x6c,0x42,0x3c,0x69,0x50,0x2e,0x2b,0x4d,0x6b,0x02,0x59,0x33,0x57,0x41,0x25,0x26,0x41,0x57,0x32,0x34,0x58, 0x40,0x25,0x26,0x41,0x58,0x00,0x00,0x02,0x00,0x5e,0xff,0xe7,0x03,0xec,0x05,0xb2,0x00,0x20,0x00,0x34,0x00,0x35,0x40,0x1b,0x21,0x00,0x89,0x08,0x17,0x10,0x10,0x36,0x2b,0x89,0x17,0x30,0x99,0x0f,0x12,0x12,0x05,0x26,0x9a,0x1c,0x07,0x08,0x08,0x0a,0x9a,0x05,0x19,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x11,0x39,0x2f,0x39,0xed,0x01, 0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x31,0x30,0x01,0x14,0x02,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xec,0x4e,0x96,0xd8,0x8a,0x8e,0x6c, 0x77,0x87,0x61,0x99,0x6a,0x38,0x04,0x5c,0xe4,0x5c,0x9a,0x70,0x3e,0x45,0x7b,0xa9,0x64,0x6c,0xa7,0x72,0x3c,0xb1,0x2b,0x4c,0x69,0x3e,0x3b,0x66,0x4b,0x2b,0x29,0x4c,0x6b,0x41,0x39,0x65,0x4b,0x2b,0x03,0x23,0xc5,0xfe,0xcd,0xd5,0x6f,0x32,0x9d,0x43,0x50,0x99,0xe0,0x91,0xb9,0x41,0x77,0xa4,0x63,0x6a,0xb0,0x7f,0x46,0x57,0xa7,0xf4, 0x0a,0x53,0x88,0x61,0x35,0x2f,0x55,0x75,0x45,0x4c,0x78,0x53,0x2c,0x2b,0x49,0x63,0x00,0x02,0x00,0x56,0xff,0xe8,0x03,0xfc,0x05,0xb2,0x00,0x0a,0x00,0x12,0x00,0x88,0x40,0x1a,0x0f,0x9a,0x00,0x19,0x0b,0x9a,0x06,0x07,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x89,0x11,0xb8,0xff,0xf0,0xb3, 0x0d,0x06,0x4d,0x11,0xb8,0xff,0xe0,0xb6,0x0c,0x06,0x4d,0x30,0x11,0x01,0x11,0xb8,0xff,0xe0,0x40,0x1d,0x0b,0x06,0x4d,0x20,0x11,0x40,0x11,0x02,0x11,0x11,0x14,0x0d,0x08,0x0d,0x06,0x4d,0x0d,0x08,0x0c,0x06,0x4d,0x0d,0x08,0x0b,0x06,0x4d,0x0d,0x89,0x03,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xd8,0xb3,0x0d,0x06,0x4d, 0x03,0xb8,0xff,0xe0,0xb6,0x0b,0x06,0x4d,0x2f,0x03,0x01,0x03,0x2f,0x5d,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x5d,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x05,0x22,0x02,0x11,0x10,0x12,0x33,0x20,0x11,0x10,0x02,0x03,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x02,0x1a,0xd5,0xef,0xf9, 0xeb,0x01,0xc2,0xfe,0xcd,0xfe,0xcd,0x01,0x2d,0x01,0x29,0x18,0x01,0x6e,0x01,0x5a,0x01,0x7c,0x01,0x86,0xfd,0x21,0xfe,0x94,0xfe,0x81,0x05,0x3f,0xfd,0x91,0xfd,0xba,0x02,0x50,0x02,0x65,0x00,0x01,0x00,0xa8,0x00,0x00,0x03,0xdb,0x05,0xba,0x00,0x09,0x00,0x7e,0xb5,0x26,0x06,0x36,0x06,0x02,0x06,0xb8,0xff,0xf8,0x40,0x2d,0x0d,0x06, 0x4d,0x04,0x08,0x0d,0x06,0x4d,0x06,0x04,0x07,0x05,0x08,0x02,0x99,0x01,0x18,0x05,0x07,0x07,0x01,0x05,0x01,0x00,0x01,0x00,0x01,0x08,0x08,0x0d,0x06,0x4d,0x08,0x08,0x0c,0x06,0x4d,0x08,0x08,0x0b,0x06,0x4d,0x08,0x8a,0x03,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xd0,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff,0xd6,0xb3,0x0b, 0x06,0x4d,0x03,0xb8,0xff,0xf0,0xb6,0x0b,0x01,0x4d,0x03,0x03,0x0b,0x0a,0x11,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x33,0x2f,0x2f,0x11,0x33,0x2f,0x00,0x3f,0x33,0x3f,0xed,0x32,0x2f,0x12,0x39,0x39,0x2b,0x2b,0x31,0x30,0x5d,0x21,0x21,0x35,0x21,0x11,0x05,0x35,0x25,0x11,0x21,0x03,0xdb,0xfc,0xd5,0x01,0x44, 0xfe,0xb4,0x01,0xf0,0x01,0x43,0x90,0x04,0x5a,0x63,0x9c,0x97,0xfa,0xd6,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0xcd,0x05,0xb2,0x00,0x17,0x00,0xa3,0xb3,0x78,0x08,0x01,0x15,0xb8,0xff,0xe8,0x40,0x36,0x0c,0x00,0x4d,0x11,0x06,0x0e,0x02,0x15,0x99,0x01,0x18,0x0b,0x0b,0x09,0x9a,0x0e,0x07,0x0b,0x00,0x10,0x0c,0x06,0x4d,0x00,0x18,0x0b, 0x0d,0x01,0x4c,0x00,0x00,0x11,0x08,0x0d,0x06,0x4d,0x11,0x08,0x0c,0x06,0x4d,0x11,0x08,0x0b,0x06,0x4d,0x11,0x8a,0x20,0x06,0x30,0x06,0x02,0x06,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf0,0xb6,0x0b,0x06,0x4d,0x06,0x06,0x19,0x0b,0xb8,0xff,0xf8,0x40,0x0c,0x0d,0x06,0x4d,0x0b, 0x16,0x20,0x0b,0x0c,0x01,0x4c,0x16,0x01,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x01,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x01,0x2f,0x2b,0x2b,0x33,0x2b,0x33,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x32,0x2f,0x2b,0x2b,0x2f,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x32,0x12,0x39,0x39,0x31,0x30,0x01,0x2b,0x5d,0x21, 0x21,0x35,0x01,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x07,0x01,0x15,0x21,0x03,0xc0,0xfc,0xa0,0x01,0xa2,0xa0,0x89,0x8e,0x83,0xc0,0xb0,0xa8,0xdf,0xc0,0xdc,0x98,0xc5,0xfe,0xb5,0x02,0x9b,0x92,0x01,0xa3,0xa0,0xd5,0x79,0x7c,0x88,0xa4,0xac,0x83,0xd0,0xaf,0x8a,0xfe,0xf9,0xc3,0xfe,0xb9, 0x04,0x00,0x00,0x01,0x00,0x83,0xff,0xe8,0x03,0xc0,0x05,0xb2,0x00,0x21,0x00,0xe5,0x40,0x3a,0x76,0x1c,0x01,0x74,0x16,0x01,0x7a,0x00,0x01,0x12,0x11,0x00,0x01,0x19,0x09,0x9a,0x0a,0x0a,0x14,0x34,0x01,0x01,0x00,0x01,0x10,0x01,0x20,0x01,0x03,0x01,0x01,0x03,0x9a,0x20,0x19,0x3b,0x11,0x01,0x2f,0x11,0x01,0x11,0x11,0x0f,0x9a,0x14, 0x07,0x19,0x09,0x10,0x0c,0x06,0x4d,0x09,0x70,0x11,0x01,0x11,0xb8,0xff,0xf0,0x40,0x3f,0x0d,0x06,0x4d,0x11,0x17,0x06,0x0c,0x06,0x4d,0x17,0x06,0x0b,0x06,0x4d,0x17,0x89,0x0d,0x10,0x0d,0x06,0x4d,0x0d,0x10,0x0c,0x06,0x4d,0x0d,0x14,0x0b,0x06,0x4d,0x0d,0x09,0x11,0x0d,0x03,0x00,0x1d,0x08,0x0d,0x06,0x4d,0x1d,0x08,0x0c,0x06,0x4d, 0x1d,0x08,0x0b,0x06,0x4d,0x1d,0x89,0x7f,0x06,0x01,0x06,0x08,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf8,0xb6,0x0b,0x06,0x4d,0x06,0x06,0x23,0x00,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xd8,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xd8,0xb3,0x0b,0x06,0x4d,0x00,0x2f,0x2b,0x2b,0x2b,0x11, 0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x12,0x17,0x39,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2f,0x2b,0x5d,0x2f,0x2b,0x39,0x00,0x3f,0xed,0x32,0x2f,0x5d,0x5d,0x3f,0xed,0x32,0x2f,0x5d,0x5d,0x11,0x39,0x2f,0xed,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x5d,0x5d,0x5d,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35, 0x33,0x20,0x11,0x34,0x21,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x10,0x05,0x15,0x16,0x16,0x15,0x14,0x04,0x23,0x22,0x83,0x93,0xb9,0x96,0xb3,0xfe,0x71,0x77,0x71,0x01,0x63,0xfe,0xf1,0x97,0x86,0x8a,0xbc,0xb5,0xd9,0xfe,0xe0,0x9b,0xb7,0xfe,0xeb,0xe3,0xcc,0x35,0xb1,0x74,0x96,0x7f,0x01,0x19,0x8b,0x01,0x08,0xf4,0x67,0xa0,0x52, 0xc0,0x96,0xfe,0xe5,0x51,0x04,0x0f,0xbb,0x8c,0xc1,0xed,0x00,0x00,0x02,0x00,0x0e,0x00,0x00,0x04,0x0a,0x05,0x9a,0x00,0x0a,0x00,0x12,0x00,0x8a,0x40,0x16,0x39,0x07,0x79,0x07,0x02,0x76,0x06,0x01,0x09,0x00,0x00,0x02,0x06,0x0b,0x0d,0x06,0x4c,0x02,0x8a,0x0b,0x07,0x03,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xd6,0xb4, 0x0b,0x0c,0x06,0x4c,0x03,0xb8,0xff,0xe0,0xb3,0x0d,0x01,0x4d,0x03,0xb8,0xff,0xf0,0x40,0x09,0x0b,0x0c,0x01,0x4c,0x03,0x03,0x14,0x12,0x05,0xb8,0xff,0xf8,0x40,0x15,0x0c,0x0d,0x06,0x4c,0x2f,0x05,0x3f,0x05,0x4f,0x05,0x03,0x05,0x01,0x05,0x9a,0x09,0x06,0x12,0x12,0x03,0x0f,0xb8,0xff,0xf0,0xb7,0x0c,0x00,0x4d,0x0f,0x07,0x06,0x03, 0x18,0x00,0x3f,0x3f,0x33,0x2b,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x01,0x2f,0x5d,0x2b,0x32,0x11,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0x33,0x33,0xe9,0x2b,0x32,0x2f,0x32,0x31,0x30,0x00,0x5d,0x01,0x5d,0x01,0x23,0x11,0x23,0x11,0x21,0x35,0x01,0x33,0x11,0x33,0x21,0x11,0x34,0x37,0x23,0x06,0x07,0x01,0x04,0x0a,0xb8,0xa2,0xfd,0x5e,0x02, 0x7e,0xc6,0xb8,0xfe,0xa6,0x04,0x04,0x0e,0x29,0xfe,0x47,0x01,0x7d,0xfe,0x83,0x01,0x7d,0x6b,0x03,0xb2,0xfc,0x68,0x02,0x6c,0x42,0x52,0x24,0x4a,0xfd,0x6e,0x00,0x01,0x00,0xa4,0xff,0xe8,0x03,0xc8,0x05,0x9a,0x00,0x19,0x00,0xb1,0x40,0x32,0x7a,0x00,0x01,0x00,0x01,0x0b,0x09,0x9a,0x12,0x12,0x0c,0x20,0x01,0x30,0x01,0x02,0x01,0x01, 0x03,0x9a,0x18,0x19,0x0f,0x99,0x0c,0x06,0x0e,0x00,0x0e,0x15,0x08,0x0d,0x06,0x4d,0x15,0x08,0x0c,0x06,0x4d,0x15,0x08,0x0b,0x06,0x4d,0x15,0x89,0x7f,0x06,0x01,0x06,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf0,0xb6,0x0b,0x06,0x4d,0x06,0x06,0x1b,0x00,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xe0,0x40,0x14, 0x0c,0x06,0x4d,0x00,0x10,0x06,0x0c,0x06,0x4d,0x10,0x0e,0x0b,0x06,0x4d,0x10,0x8b,0x70,0x0b,0x01,0x0b,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x0b,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x0b,0xb8,0xff,0xf8,0x40,0x09,0x0b,0x06,0x4d,0x0b,0x20,0x0d,0x01,0x4d,0x0b,0x2f,0x2b,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x33,0x2b,0x2b,0x12,0x39, 0x2f,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x32,0x2f,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x5d,0x11,0x39,0x2f,0xed,0x32,0x11,0x33,0x31,0x30,0x5d,0x37,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x11,0x21,0x15,0x21,0x11,0x36,0x33,0x32,0x16,0x15,0x14,0x04,0x23,0x22,0xa4,0x93,0x98,0x98,0xba,0xbe,0xb1,0x3c,0xa5, 0x02,0xb6,0xfd,0xe5,0x42,0x38,0xe6,0xfc,0xfe,0xf1,0xec,0xc7,0x23,0xae,0x5f,0xac,0x8e,0x8d,0x9e,0x0c,0x02,0xcf,0x94,0xfe,0x5c,0x04,0xe7,0xc9,0xd0,0xfe,0x00,0x02,0x00,0x6e,0xff,0xe8,0x03,0xfe,0x05,0xb2,0x00,0x16,0x00,0x22,0x00,0xae,0x40,0x3b,0x7a,0x14,0x01,0x76,0x0a,0x01,0x29,0x14,0x39,0x14,0x02,0x06,0x0f,0x15,0x17,0x9a, 0x09,0x09,0x15,0x1d,0x9a,0x0f,0x19,0x01,0x01,0x03,0x9a,0x15,0x07,0x01,0x40,0x0c,0x00,0x4d,0x01,0x01,0x0c,0x08,0x0d,0x06,0x4d,0x0c,0x08,0x0c,0x06,0x4d,0x0c,0x08,0x0b,0x06,0x4d,0x0c,0x89,0x20,0x20,0x30,0x20,0x02,0x20,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x20,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x20,0xb8,0xff,0xe4,0x40,0x19, 0x0b,0x06,0x4d,0x20,0x20,0x24,0x1a,0x06,0x08,0x0d,0x06,0x4d,0x06,0x08,0x0c,0x06,0x4d,0x06,0x08,0x0b,0x06,0x4d,0x06,0x89,0x12,0xb8,0xff,0xd4,0xb3,0x0d,0x06,0x4d,0x12,0xb8,0xff,0xd6,0xb3,0x0c,0x06,0x4d,0x12,0xb8,0xff,0xd8,0xb3,0x0b,0x06,0x4d,0x12,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x32,0x12,0x39,0x2f,0x2b,0x2b,0x2b, 0x5d,0xe9,0x2b,0x2b,0x2b,0x32,0x2f,0x2b,0x00,0x3f,0xed,0x32,0x2f,0x3f,0xed,0x11,0x39,0x2f,0xed,0x11,0x12,0x39,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x01,0x15,0x26,0x23,0x22,0x02,0x11,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x23,0x22,0x02,0x11,0x10,0x00,0x21,0x32,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03, 0xa6,0x6f,0x7b,0xbf,0xe5,0x04,0x64,0xe4,0xbc,0xde,0xfe,0xc4,0xd8,0xf6,0x01,0x42,0x01,0x08,0x96,0xfe,0xf2,0x7f,0x9e,0x9d,0x82,0x7c,0x98,0x92,0x05,0x89,0x9b,0x39,0xfe,0xac,0xfe,0xe3,0xcb,0xf1,0xca,0xd3,0xfe,0xf5,0x01,0x58,0x01,0x37,0x01,0x79,0x01,0xc2,0xfd,0x44,0xac,0x75,0x93,0xd0,0xb5,0x8b,0x98,0xac,0x00,0x01,0x00,0x56, 0x00,0x00,0x03,0xf2,0x05,0x9a,0x00,0x06,0x00,0xbc,0x40,0x0b,0x73,0x01,0x01,0x02,0x18,0x00,0x04,0x99,0x05,0x06,0x03,0xb8,0xff,0xd8,0x40,0x0b,0x0b,0x0d,0x01,0x4c,0x01,0x28,0x0b,0x0d,0x01,0x4c,0x03,0xb8,0xff,0xf4,0x40,0x09,0x0d,0x06,0x4d,0x01,0x0c,0x0d,0x06,0x4d,0x03,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x06,0x4d,0x01,0x10,0x0c, 0x06,0x4d,0x03,0xb8,0xff,0xf0,0x40,0x14,0x0b,0x06,0x4d,0x01,0x10,0x0b,0x06,0x4d,0x01,0x03,0x00,0x02,0x02,0x04,0x20,0x00,0x30,0x00,0x02,0x00,0xb8,0xff,0xe8,0xb3,0x0d,0x06,0x4d,0x00,0xb8,0xff,0xf0,0xb3,0x0c,0x06,0x4d,0x00,0xb8,0xff,0xf0,0x40,0x0d,0x0b,0x06,0x4d,0x00,0x20,0x0b,0x0c,0x01,0x4c,0x00,0x00,0x08,0x04,0xb8,0xff, 0xe0,0xb3,0x0d,0x06,0x4d,0x04,0xb8,0xff,0xe0,0xb3,0x0c,0x06,0x4d,0x04,0xb8,0xff,0xe0,0x40,0x0e,0x0b,0x06,0x4d,0x04,0x40,0x0b,0x01,0x4d,0x04,0x40,0x0b,0x00,0x4d,0x04,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x2b,0x5d,0x12,0x39,0x2f,0x12,0x39,0x39,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x3f,0xed, 0x39,0x3f,0x31,0x30,0x01,0x5d,0x01,0x01,0x23,0x01,0x21,0x35,0x21,0x03,0xf2,0xfd,0xc8,0xaa,0x02,0x19,0xfd,0x2d,0x03,0x9c,0x05,0x66,0xfa,0x9a,0x05,0x06,0x94,0x00,0x00,0x03,0x00,0x64,0xff,0xe8,0x03,0xee,0x05,0xb2,0x00,0x15,0x00,0x1f,0x00,0x29,0x00,0xfa,0x40,0x26,0x7b,0x13,0x01,0x7b,0x0f,0x01,0x74,0x08,0x01,0x74,0x04,0x01, 0x76,0x07,0x01,0x29,0x08,0x0b,0x00,0x4d,0x35,0x1f,0x01,0x36,0x0a,0x01,0x36,0x1d,0x01,0x76,0x1e,0x01,0x20,0x08,0x0d,0x06,0x4d,0x1e,0xb8,0xff,0xf8,0x40,0x38,0x0d,0x06,0x4d,0x20,0x00,0x0b,0x03,0x1e,0x1e,0x06,0x25,0x9a,0x11,0x19,0x19,0x9a,0x06,0x07,0x00,0x0b,0x1e,0x20,0x04,0x03,0x16,0x89,0x09,0x18,0x0d,0x01,0x4d,0x09,0x09, 0x0e,0x08,0x0d,0x06,0x4d,0x0e,0x08,0x0c,0x06,0x4d,0x0e,0x08,0x0b,0x06,0x4d,0x0e,0x89,0x20,0x28,0x30,0x28,0x02,0x28,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x28,0xb8,0xff,0xe8,0xb3,0x0c,0x06,0x4d,0x28,0xb8,0xff,0xe8,0x40,0x0a,0x0b,0x06,0x4d,0x28,0x28,0x2b,0x14,0x1c,0x89,0x03,0xb8,0xff,0xf8,0xb3,0x0c,0x06,0x4d,0x03,0xb8,0xff, 0xf8,0x40,0x17,0x0b,0x06,0x4d,0x03,0x03,0x22,0x08,0x0d,0x06,0x4d,0x22,0x08,0x0c,0x06,0x4d,0x22,0x08,0x0b,0x06,0x4d,0x22,0x89,0x14,0xb8,0xff,0xd8,0xb3,0x0d,0x06,0x4d,0x14,0xb8,0xff,0xd8,0xb3,0x0c,0x06,0x4d,0x14,0xb8,0xff,0xd8,0xb3,0x0b,0x06,0x4d,0x14,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x39,0x2f,0x2b,0x2b,0xe9,0x11, 0x12,0x39,0x2f,0x2b,0x2b,0x2b,0x5d,0xe9,0x2b,0x2b,0x2b,0x39,0x2f,0x2b,0xe9,0x12,0x17,0x39,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x11,0x17,0x33,0x2b,0x2b,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x2b,0x01,0x5d,0x00,0x5d,0x5d,0x5d,0x5d,0x01,0x35,0x24,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x05,0x15,0x04,0x11,0x14,0x04,0x23,0x22,0x26, 0x35,0x10,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x07,0x04,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x01,0x9a,0xfe,0xfe,0xec,0xba,0xa8,0xd8,0xfe,0xf6,0x01,0x3a,0xff,0x00,0xe4,0xb8,0xee,0x02,0xb2,0x7c,0x6b,0x64,0x8b,0xe9,0xed,0xf8,0xfe,0xee,0x9f,0x82,0x7c,0x9d,0x02,0xf0,0x04,0x78,0xe4,0x9b,0xc7,0xba,0x92,0xee, 0x84,0x04,0x70,0xfe,0xec,0xb2,0xd2,0xd0,0xa6,0x01,0x14,0x01,0xe0,0x63,0x72,0x77,0x5c,0xbb,0x5f,0x62,0xfa,0x6d,0xcf,0x6b,0x89,0x87,0x67,0xd8,0x00,0x02,0x00,0x5e,0xff,0xe8,0x03,0xec,0x05,0xb2,0x00,0x17,0x00,0x23,0x00,0xc1,0x40,0x29,0x79,0x14,0x01,0x74,0x15,0x01,0x76,0x04,0x01,0x2d,0x04,0x3d,0x04,0x02,0x29,0x14,0x39,0x14, 0x02,0x08,0x10,0x0a,0x9a,0x1e,0x1e,0x10,0x70,0x01,0x01,0x01,0x01,0x03,0x9a,0x16,0x19,0x18,0x9a,0x10,0x07,0x21,0x00,0xb8,0xff,0xea,0x40,0x17,0x0c,0x06,0x4d,0x00,0x13,0x08,0x0d,0x06,0x4d,0x13,0x08,0x0c,0x06,0x4d,0x13,0x08,0x0b,0x06,0x4d,0x21,0x13,0x89,0x06,0xb8,0xff,0xf8,0xb3,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf0,0xb3,0x0c, 0x06,0x4d,0x06,0xb8,0xff,0xe8,0x40,0x1e,0x0b,0x06,0x4d,0x20,0x06,0x30,0x06,0x02,0x06,0x06,0x25,0x00,0x1b,0x08,0x0d,0x06,0x4d,0x1b,0x08,0x0c,0x06,0x4d,0x1b,0x08,0x0b,0x06,0x4d,0x1b,0x89,0x0d,0xb8,0xff,0xd8,0xb3,0x0d,0x06,0x4d,0x0d,0xb8,0xff,0xd8,0xb3,0x0c,0x06,0x4d,0x0d,0xb8,0xff,0xd8,0xb3,0x0b,0x06,0x4d,0x0d,0x2f,0x2b, 0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x33,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xe9,0x33,0x2b,0x2b,0x2b,0x2f,0x2b,0x2f,0x00,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x5d,0x11,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x5d,0x5d,0x5d,0x5d,0x00,0x5d,0x37,0x35,0x16,0x33,0x32,0x12,0x11,0x06,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x00,0x33,0x32,0x12, 0x11,0x10,0x00,0x21,0x22,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0xac,0x78,0x86,0xc3,0xd9,0x02,0x02,0x5c,0xe4,0xb8,0xec,0x01,0x03,0xca,0xd4,0xed,0xfe,0xcc,0xfe,0xee,0x90,0x01,0x06,0x77,0x9f,0x9c,0x85,0x74,0xa1,0xa0,0x18,0x9e,0x44,0x01,0x3a,0x01,0x21,0x01,0x01,0xb9,0xfa,0xc5,0xd2,0x01,0x0d,0xfe,0xb1, 0xfe,0xc0,0xfe,0x73,0xfe,0x52,0x05,0x3f,0xb3,0x8a,0x97,0xad,0x9e,0x72,0xa3,0xce,0x00,0x02,0x00,0x48,0xff,0xec,0x02,0xa5,0x03,0x66,0x00,0x0a,0x00,0x12,0x00,0x20,0x40,0x10,0x08,0xcc,0x11,0x11,0x14,0x0d,0xcc,0x03,0x0b,0xe7,0x06,0x2b,0x0f,0xe7,0x00,0x2d,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30, 0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x20,0x11,0x14,0x06,0x03,0x22,0x11,0x10,0x33,0x32,0x11,0x10,0x01,0x6d,0x8b,0x9a,0xa1,0x99,0x01,0x23,0xa3,0x87,0xa9,0xa6,0xa4,0x14,0xdb,0xd1,0xe5,0xe9,0xfe,0x47,0xdb,0xe6,0x03,0x03,0xfe,0xaf,0xfe,0xc6,0x01,0x40,0x01,0x4b,0x00,0xff,0xff,0x00,0x50,0x00,0x01,0x01,0xc2,0x03,0x69,0x01,0x07, 0x00,0xf0,0x00,0x00,0xfd,0xb9,0x00,0x07,0xb2,0x00,0x00,0x2c,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x68,0x00,0x01,0x02,0x92,0x03,0x67,0x03,0x07,0x00,0xf1,0x00,0x00,0xfd,0xb9,0x00,0x07,0xb2,0x00,0x01,0x2c,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x81,0xff,0xec,0x02,0x8e,0x03,0x67,0x03,0x07,0x00,0xf2,0x00,0x00,0xfd,0xb9,0x00,0x07, 0xb2,0x00,0x1f,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x2f,0x00,0x01,0x02,0xaa,0x03,0x53,0x01,0x07,0x02,0x38,0x00,0x00,0xfd,0xb9,0x00,0x09,0xb3,0x01,0x00,0x03,0x2c,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x7b,0xff,0xec,0x02,0x8a,0x03,0x57,0x03,0x07,0x02,0x39,0x00,0x00,0xfd,0xb9,0x00,0x07,0xb2,0x00,0x23,0x2d,0x00,0x3f, 0x35,0x00,0x00,0x02,0x00,0x49,0xff,0xec,0x02,0xa6,0x03,0x66,0x00,0x26,0x00,0x36,0x00,0x2f,0x40,0x18,0x01,0x15,0xcd,0x34,0x34,0x38,0x2c,0x0c,0xcc,0x1f,0x27,0xe7,0x0c,0x10,0x10,0x31,0x06,0xe6,0x24,0x2b,0x31,0xe6,0x1a,0x2d,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x32,0x31, 0x30,0x01,0x15,0x2e,0x03,0x23,0x22,0x06,0x07,0x06,0x06,0x15,0x33,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x63,0x0e,0x28,0x2b,0x2c,0x12,0x39,0x55,0x21,0x1f,0x2d,0x04,0x1d,0x6e,0x4e, 0x3c,0x5f,0x42,0x23,0x2d,0x4f,0x6b,0x3d,0x3f,0x72,0x56,0x32,0x38,0x65,0x8c,0x54,0x2b,0x52,0xc1,0x22,0x3c,0x2c,0x1a,0x15,0x29,0x3a,0x25,0x4b,0x55,0x4d,0x03,0x43,0x81,0x09,0x10,0x0c,0x07,0x24,0x24,0x22,0x7f,0x61,0x32,0x41,0x27,0x47,0x63,0x3d,0x3d,0x68,0x4d,0x2b,0x31,0x63,0x98,0x68,0x75,0xb5,0x7c,0x40,0x12,0xfe,0x59,0x15, 0x28,0x38,0x24,0x22,0x41,0x32,0x1e,0x5b,0x49,0x4e,0x5a,0x00,0xff,0xff,0x00,0x4d,0x00,0x01,0x02,0xa0,0x03,0x5d,0x03,0x07,0x02,0x3a,0x00,0x00,0xfd,0xb9,0x00,0x07,0xb2,0x00,0x00,0x2c,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x41,0xff,0xed,0x02,0xad,0x03,0x67,0x03,0x07,0x02,0x3b,0x00,0x00,0xfd,0xb9,0x00,0x0b,0xb4,0x02,0x01,0x00, 0x1f,0x2d,0x00,0x3f,0x35,0x35,0x35,0x00,0x00,0x02,0x00,0x49,0xff,0xeb,0x02,0xa6,0x03,0x66,0x00,0x27,0x00,0x39,0x00,0x31,0x40,0x19,0x2d,0xcc,0x23,0x10,0x35,0x1a,0xcd,0x06,0x05,0x05,0x10,0x3b,0x30,0xe7,0x0b,0x0b,0x28,0x00,0xe6,0x1f,0x2d,0x28,0xe6,0x15,0x2b,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x11,0x12,0x01,0x39, 0x2f,0x10,0xed,0x33,0x2f,0x33,0xed,0x31,0x30,0x25,0x32,0x3e,0x02,0x35,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x1e,0x03,0x13,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x01,0x34,0x42,0x5e,0x3c,0x1b,0x04,0x0d,0x2b, 0x37,0x42,0x24,0x3c,0x61,0x46,0x26,0x2a,0x4d,0x6c,0x41,0x40,0x71,0x56,0x32,0x30,0x5d,0x8a,0x5b,0x30,0x61,0x26,0x13,0x2e,0x30,0x30,0x52,0x21,0x39,0x2a,0x18,0x52,0x45,0x20,0x3d,0x2f,0x1d,0x19,0x2c,0x3c,0x62,0x33,0x5c,0x7e,0x4b,0x1c,0x2f,0x21,0x13,0x26,0x47,0x63,0x3c,0x3f,0x6a,0x4c,0x2a,0x33,0x65,0x96,0x64,0x69,0xb4,0x82, 0x4a,0x17,0x16,0x7f,0x0b,0x13,0x0f,0x08,0x02,0x8e,0x17,0x2c,0x3e,0x28,0x4c,0x56,0x16,0x26,0x33,0x1d,0x2a,0x47,0x32,0x1c,0x00,0x02,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x33,0x00,0x07,0x00,0x15,0x00,0x27,0x40,0x12,0x15,0x08,0x15,0x08,0x00,0x05,0x00,0x03,0x39,0x15,0x15,0x05,0x0f,0x06,0x35,0x01,0x05,0x33,0x00,0x3f,0x33,0x3f, 0x33,0x12,0x39,0x2f,0xed,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x33,0x13,0x03,0x2e,0x03,0x27,0x23,0x0e,0x03,0x07,0x03,0x04,0x04,0xb3,0x71,0xfe,0x3d,0x6a,0xb3,0x01,0xae,0xa4,0x5e,0x98,0x02,0x07,0x08,0x07,0x01,0x03,0x02,0x06,0x07,0x07,0x03,0x92,0x01,0x1a,0xfe,0xe6,0x04,0x33, 0xfd,0x73,0x01,0x9a,0x05,0x17,0x1d,0x1c,0x0b,0x0c,0x1d,0x1d,0x18,0x07,0xfe,0x6b,0x00,0x03,0x00,0xb0,0x00,0x00,0x03,0xa1,0x04,0x33,0x00,0x15,0x00,0x1e,0x00,0x27,0x00,0x3c,0x40,0x21,0x10,0x24,0x0d,0x38,0x16,0x16,0x06,0x00,0x38,0x1f,0x1b,0x24,0x37,0x06,0x10,0x23,0x3a,0x2f,0x1b,0x3f,0x1b,0x02,0x1b,0x1b,0x06,0x1a,0x3a,0x07, 0x35,0x24,0x3a,0x06,0x33,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x5d,0xed,0x39,0x01,0x2f,0xed,0x32,0x2f,0xed,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x21,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x03,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x13,0x34,0x26,0x23,0x23,0x11,0x33, 0x32,0x36,0x03,0xa1,0x3b,0x67,0x8e,0x52,0xfe,0x91,0x01,0x67,0x4c,0x7c,0x57,0x2f,0x6c,0x61,0x3d,0x63,0x44,0x25,0xe7,0x71,0x72,0x83,0x71,0x73,0x82,0x3c,0x8f,0x90,0x83,0xa0,0x7b,0x87,0x01,0x35,0x45,0x72,0x51,0x2d,0x04,0x33,0x23,0x41,0x5b,0x37,0x5b,0x86,0x1e,0x03,0x06,0x2a,0x44,0x5b,0x01,0xb9,0x4e,0x3a,0xfe,0xc3,0x5a,0xfe, 0x6c,0x60,0x55,0xfe,0x9b,0x54,0x00,0x01,0x00,0x58,0xff,0xed,0x03,0xbb,0x04,0x45,0x00,0x1d,0x00,0x1b,0x40,0x0d,0x16,0x38,0x07,0x0f,0x00,0x11,0x39,0x0c,0x36,0x1b,0x39,0x02,0x34,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0x33,0x2f,0xed,0x31,0x30,0x25,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22, 0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x03,0xbb,0x83,0xc5,0x7d,0xc8,0x8c,0x4a,0x54,0x9b,0xd8,0x84,0xa9,0x6f,0x7a,0x96,0x63,0x9e,0x6d,0x3a,0x36,0x66,0x94,0x5e,0xad,0x7d,0x2c,0x3f,0x4d,0x8c,0xc6,0x79,0x80,0xd4,0x98,0x54,0x2c,0x9e,0x40,0x3d,0x70,0x9e,0x62,0x5d,0x96,0x6a,0x39,0x48,0x00,0x00,0x02,0x00,0xb0,0x00,0x00, 0x04,0x54,0x04,0x33,0x00,0x0a,0x00,0x17,0x00,0x1c,0x40,0x0e,0x00,0x38,0x0b,0x12,0x37,0x06,0x11,0x39,0x07,0x35,0x12,0x39,0x06,0x33,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x21,0x11,0x21,0x20,0x00,0x03,0x34,0x2e,0x02,0x23,0x23,0x11,0x33,0x32,0x3e,0x02,0x04,0x54,0x5d,0xa9,0xef, 0x92,0xfe,0xe3,0x01,0x2b,0x01,0x3c,0x01,0x3d,0xab,0x3c,0x76,0xae,0x72,0x83,0x7a,0x6e,0xb0,0x7b,0x42,0x02,0x27,0x7d,0xcb,0x90,0x4f,0x04,0x33,0xfe,0xfb,0xfe,0xf6,0x67,0x92,0x5c,0x2a,0xfc,0xed,0x30,0x64,0x98,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0x27,0x04,0x33,0x00,0x0b,0x00,0x3c,0x40,0x22,0x06,0x0a,0x37,0x01,0x08,0x04, 0x08,0x04,0x00,0x01,0x00,0x09,0x39,0x0f,0x06,0x01,0x2f,0x06,0x3f,0x06,0xff,0x06,0x03,0x06,0x06,0x01,0x05,0x39,0x02,0x35,0x0a,0x39,0x01,0x33,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x5d,0x71,0xed,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21, 0x03,0x27,0xfd,0x89,0x02,0x5b,0xfe,0x49,0x01,0x95,0xfe,0x6b,0x01,0xd3,0x04,0x33,0x8b,0xfe,0xc0,0x8b,0xfe,0xae,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0x0b,0x04,0x33,0x00,0x09,0x00,0x29,0x40,0x14,0x02,0x06,0x37,0x07,0x04,0x04,0x00,0x07,0x00,0x05,0x39,0x02,0x02,0x07,0x01,0x39,0x08,0x35,0x07,0x33,0x00,0x3f,0x3f,0xed,0x12,0x39, 0x2f,0xed,0x01,0x2f,0x2f,0x12,0x39,0x2f,0x10,0xed,0x32,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x03,0x0b,0xfe,0x49,0x01,0x95,0xfe,0x6b,0xa4,0x02,0x5b,0x03,0xa8,0xfe,0xb1,0x8a,0xfe,0x31,0x04,0x33,0x00,0x00,0x01,0x00,0x58,0xff,0xed,0x04,0x20,0x04,0x45,0x00,0x22,0x00,0x2f,0x40,0x18,0x20,0x20,0x07,0x1e, 0x0f,0x00,0x37,0x1e,0x16,0x38,0x07,0x20,0x39,0x21,0x21,0x02,0x11,0x39,0x0c,0x36,0x1b,0x39,0x02,0x34,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0x31,0x30,0x25,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02, 0x33,0x32,0x36,0x37,0x11,0x21,0x35,0x21,0x04,0x20,0xb3,0xdc,0x7f,0xd2,0x96,0x52,0x5c,0xa4,0xe3,0x87,0xc0,0x86,0x8e,0xbd,0x60,0xa3,0x75,0x42,0x39,0x6b,0x98,0x60,0x42,0x6d,0x30,0xfe,0xfe,0x01,0xa4,0x4a,0x5d,0x4f,0x8e,0xc8,0x79,0x7b,0xd1,0x98,0x56,0x39,0xa4,0x53,0x3f,0x71,0x9b,0x5b,0x5e,0x99,0x6c,0x3a,0x16,0x16,0x01,0x0b, 0x8b,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x04,0x39,0x04,0x33,0x00,0x0b,0x00,0x27,0x40,0x13,0x08,0x04,0x37,0x05,0x09,0x00,0x37,0x01,0x03,0x39,0x08,0x08,0x05,0x0a,0x06,0x35,0x01,0x05,0x33,0x00,0x3f,0x33,0x3f,0x33,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x33,0x2f,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11, 0x21,0x11,0x33,0x04,0x39,0xa5,0xfd,0xc0,0xa4,0xa4,0x02,0x40,0xa5,0x01,0xf3,0xfe,0x0d,0x04,0x33,0xfe,0x4b,0x01,0xb5,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x01,0x54,0x04,0x33,0x00,0x03,0x00,0x10,0xb6,0x00,0x37,0x01,0x02,0x35,0x01,0x33,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x54,0xa4,0xa4,0x04,0x33, 0x00,0x01,0x00,0x11,0xff,0xed,0x01,0xe5,0x04,0x33,0x00,0x11,0x00,0x16,0x40,0x0a,0x00,0x37,0x0f,0x07,0x10,0x35,0x0a,0x39,0x05,0x34,0x00,0x3f,0xed,0x3f,0x01,0x2f,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x01,0xe5,0x33,0x5d,0x83,0x4f,0x46,0x2c,0x2c,0x48,0x2f,0x46, 0x2f,0x18,0xa4,0x01,0x81,0x65,0x98,0x65,0x32,0x13,0x9a,0x1d,0x1b,0x3d,0x63,0x48,0x02,0xb3,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0xec,0x04,0x33,0x00,0x12,0x00,0x33,0x40,0x18,0x10,0x11,0x11,0x00,0x12,0x0b,0x07,0x37,0x08,0x01,0x00,0x00,0x14,0x12,0x06,0x0b,0x0b,0x08,0x10,0x09,0x35,0x01,0x08,0x33,0x00,0x3f,0x33,0x3f,0x33,0x12, 0x39,0x11,0x33,0x33,0x11,0x01,0x33,0x2f,0x33,0x2f,0xed,0x32,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x21,0x23,0x01,0x26,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x03,0xec,0xcc,0xfe,0x60,0x09,0x19,0x06,0x04,0xa4,0xa4,0x04,0x05,0x19,0x0a,0x01,0x91,0xb8,0xfe,0x33,0x01,0xdd,0x0b,0x20,0x0a,0xfd, 0xee,0x04,0x33,0xfe,0x07,0x08,0x1e,0x0b,0x01,0xc8,0xfd,0xfc,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0x2e,0x04,0x33,0x00,0x05,0x00,0x16,0x40,0x0a,0x04,0x37,0x01,0x00,0x02,0x35,0x04,0x39,0x01,0x33,0x00,0x3f,0xed,0x3f,0x01,0x2f,0x2f,0xed,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x03,0x2e,0xfd,0x82,0xa4,0x01,0xda,0x04,0x33,0xfc, 0x58,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x05,0x62,0x04,0x33,0x00,0x21,0x00,0x20,0x40,0x0f,0x17,0x10,0x14,0x37,0x15,0x20,0x06,0x05,0x00,0x37,0x01,0x16,0x35,0x15,0x33,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x33,0x33,0x33,0x2f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x34,0x36,0x37,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x26,0x26,0x27, 0x23,0x16,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x05,0x62,0x9e,0x02,0x06,0x04,0x0a,0x14,0x11,0xfe,0x9d,0x58,0xfe,0x98,0x12,0x15,0x09,0x03,0x03,0x03,0x99,0xda,0x01,0x45,0x15,0x1b,0x06,0x06,0x0b,0x1e,0x11,0x01,0x46,0xd7,0x02,0xbe,0x2b,0x61,0x3e,0x24,0x3a,0x26,0xfc,0xfc,0x03,0x04, 0x26,0x38,0x26,0x20,0x62,0x49,0xfd,0x43,0x04,0x33,0xfd,0x3e,0x2a,0x4a,0x17,0x1d,0x4d,0x24,0x02,0xbf,0x00,0x01,0x00,0xb0,0x00,0x00,0x04,0x7a,0x04,0x33,0x00,0x18,0x00,0x1a,0x40,0x0c,0x01,0x00,0x37,0x16,0x0c,0x09,0x37,0x0a,0x0b,0x35,0x01,0x33,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x32,0x2f,0xed,0x33,0x31,0x30,0x21,0x23,0x01,0x26, 0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x1e,0x03,0x17,0x33,0x26,0x26,0x35,0x11,0x33,0x04,0x7a,0xae,0xfd,0xcc,0x1f,0x29,0x08,0x05,0x06,0x99,0xb9,0x02,0x35,0x12,0x19,0x11,0x09,0x03,0x03,0x04,0x04,0x99,0x02,0xf7,0x2a,0x41,0x13,0x23,0x71,0xfd,0x1f,0x04,0x33,0xfd,0x04,0x19,0x23,0x18,0x10,0x05,0x17,0x4e,0x39,0x02, 0xc7,0x00,0x00,0x02,0x00,0x58,0xff,0xed,0x04,0x95,0x04,0x45,0x00,0x13,0x00,0x23,0x00,0x1c,0x40,0x0e,0x00,0x38,0x14,0x1c,0x38,0x0a,0x17,0x39,0x0f,0x36,0x21,0x39,0x05,0x34,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34, 0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x04,0x95,0x52,0x91,0xc9,0x77,0x78,0xc6,0x8e,0x4e,0x4b,0x8f,0xd0,0x85,0x7a,0xc3,0x88,0x49,0xab,0xb7,0xb7,0x57,0x8c,0x62,0x34,0x31,0x5f,0x88,0x57,0xb8,0xc0,0x02,0x27,0x86,0xd4,0x93,0x4d,0x4f,0x90,0xc8,0x79,0x7c,0xd0,0x97,0x55,0x55,0x93,0xc6,0x80,0xc8,0xdc,0x3c, 0x6e,0x9b,0x5e,0x5e,0x9a,0x6d,0x3c,0xda,0x00,0x02,0x00,0xb0,0x00,0x00,0x03,0x92,0x04,0x33,0x00,0x0e,0x00,0x17,0x00,0x24,0x40,0x12,0x00,0x38,0x0f,0x14,0x07,0x37,0x08,0x06,0x3a,0x14,0x14,0x08,0x13,0x3a,0x09,0x35,0x08,0x33,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02, 0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x1e,0x02,0x07,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x03,0x92,0x3f,0x73,0xa3,0x63,0x86,0xa4,0x01,0x4b,0x61,0x98,0x68,0x36,0xab,0x86,0x87,0x86,0x76,0x89,0x94,0x02,0xee,0x4d,0x82,0x5e,0x34,0xfe,0x73,0x04,0x33,0x2c,0x54,0x79,0x52,0x6b,0x5a,0xfe,0x65,0x69,0x00,0x02,0x00,0x58,0xff,0x65, 0x04,0xc5,0x04,0x45,0x00,0x18,0x00,0x28,0x00,0x24,0x40,0x12,0x00,0x38,0x19,0x21,0x38,0x0f,0x08,0x05,0x0a,0x1c,0x39,0x14,0x36,0x26,0x39,0x0a,0x34,0x07,0x00,0x2f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x06,0x07,0x05,0x23,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02, 0x33,0x32,0x1e,0x02,0x07,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x04,0x95,0x52,0x49,0x22,0x28,0x01,0x15,0xf8,0xb2,0x4f,0x5a,0x78,0xc6,0x8e,0x4e,0x4b,0x8f,0xd0,0x85,0x7a,0xc3,0x88,0x49,0xab,0xb7,0xb7,0x57,0x8c,0x62,0x34,0x31,0x5f,0x88,0x57,0xb8,0xc0,0x02,0x27,0x86,0xd4,0x4a,0x22,0x1b,0xe1,0x9e, 0x16,0x4f,0x90,0xc8,0x79,0x7c,0xd0,0x97,0x55,0x55,0x93,0xc6,0x80,0xc8,0xdc,0x3c,0x6e,0x9b,0x5e,0x5e,0x9a,0x6d,0x3c,0xda,0x00,0x02,0x00,0xb0,0x00,0x00,0x03,0xdf,0x04,0x33,0x00,0x19,0x00,0x24,0x00,0x2e,0x40,0x17,0x16,0x09,0x00,0x11,0x38,0x1a,0x1f,0x09,0x37,0x0a,0x16,0x08,0x3a,0x1f,0x1f,0x0a,0x1e,0x3a,0x0b,0x35,0x01,0x0a, 0x33,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0xed,0x32,0x2f,0xfd,0xc6,0x12,0x39,0x31,0x30,0x21,0x23,0x03,0x2e,0x03,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x16,0x17,0x03,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x3e,0x02,0x03,0xdf,0xc0,0xbe,0x13,0x24,0x29,0x2f,0x1d,0x61, 0xa4,0x01,0x6d,0x56,0x8a,0x61,0x34,0x26,0x46,0x62,0x3c,0x3c,0x3f,0x1c,0x77,0x76,0xa6,0xa0,0x37,0x59,0x40,0x23,0x01,0x47,0x20,0x2b,0x19,0x0a,0xfe,0x4b,0x04,0x33,0x27,0x4a,0x69,0x43,0x3a,0x63,0x4c,0x35,0x0d,0x03,0x1a,0x65,0x01,0xa1,0x57,0x4c,0xfe,0x8e,0x1e,0x37,0x4c,0x00,0x00,0x01,0x00,0x68,0xff,0xed,0x03,0x08,0x04,0x45, 0x00,0x37,0x00,0x26,0x40,0x13,0x2e,0x37,0x0a,0x1f,0x27,0x00,0x37,0x15,0x15,0x2d,0x05,0x29,0x39,0x24,0x36,0x10,0x39,0x05,0x34,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0xc4,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x35,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x2e, 0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x03,0x08,0x38,0x67,0x94,0x5d,0x20,0x4e,0x4c,0x41,0x12,0x1a,0x46,0x4d,0x4f,0x24,0x39,0x53,0x36,0x19,0x14,0x35,0x5d,0x4a,0x47,0x66,0x42,0x1f,0x39,0x66,0x8d,0x53,0xa0,0x4a,0x5f,0x93,0x32,0x4f,0x38,0x1d,0x0e,0x2f,0x56, 0x48,0x4f,0x6f,0x46,0x20,0x01,0x1b,0x44,0x70,0x4f,0x2b,0x0b,0x11,0x16,0x0c,0xac,0x15,0x24,0x1a,0x0e,0x16,0x28,0x38,0x22,0x1f,0x32,0x30,0x36,0x25,0x23,0x46,0x4c,0x58,0x35,0x40,0x68,0x49,0x28,0x26,0xa5,0x42,0x15,0x26,0x33,0x1e,0x1d,0x2f,0x31,0x36,0x22,0x26,0x47,0x4c,0x54,0x00,0x01,0x00,0x19,0x00,0x00,0x03,0x6c,0x04,0x33, 0x00,0x07,0x00,0x1e,0x40,0x0e,0x02,0x37,0x03,0x03,0x00,0x05,0x00,0x01,0x05,0x39,0x06,0x35,0x03,0x33,0x00,0x3f,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x03,0x6c,0xfe,0xa9,0xa4,0xfe,0xa8,0x03,0x53,0x03,0xa8,0xfc,0x58,0x03,0xa8,0x8b,0x00,0x01,0x00,0x9c,0xff,0xed, 0x04,0x26,0x04,0x33,0x00,0x15,0x00,0x1b,0x40,0x0d,0x00,0x37,0x13,0x09,0x37,0x06,0x14,0x07,0x35,0x0e,0x39,0x03,0x34,0x00,0x3f,0xed,0x3f,0x33,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x04,0x26,0xed,0xe2,0xd9,0xe2,0xa5,0x22,0x48, 0x6f,0x4d,0x4a,0x6b,0x45,0x20,0xa5,0x01,0xb3,0xe3,0xe3,0xdb,0xda,0x02,0x91,0xfd,0x80,0x51,0x77,0x4e,0x25,0x24,0x4d,0x76,0x51,0x02,0x83,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x15,0x04,0x33,0x00,0x0f,0x00,0x0f,0xb5,0x03,0x00,0x03,0x35,0x02,0x33,0x00,0x3f,0x3f,0x01,0x2f,0x2f,0x31,0x30,0x01,0x01,0x23,0x01,0x33,0x01,0x1e, 0x03,0x17,0x33,0x36,0x36,0x37,0x01,0x04,0x15,0xfe,0x43,0xa3,0xfe,0x4b,0xb9,0x01,0x0c,0x10,0x17,0x0f,0x0a,0x02,0x03,0x04,0x20,0x22,0x01,0x12,0x04,0x33,0xfb,0xcd,0x04,0x33,0xfd,0x40,0x2a,0x40,0x32,0x24,0x0e,0x17,0x61,0x57,0x02,0xbf,0x00,0x01,0x00,0x05,0x00,0x00,0x06,0x64,0x04,0x33,0x00,0x26,0x00,0x0f,0xb5,0x1a,0x0a,0x1a, 0x35,0x19,0x33,0x00,0x3f,0x3f,0x01,0x2f,0x2f,0x31,0x30,0x01,0x13,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x13,0x33,0x01,0x23,0x03,0x2e,0x03,0x27,0x0e,0x03,0x07,0x03,0x23,0x01,0x33,0x13,0x1e,0x03,0x17,0x33,0x36,0x36,0x37,0x13,0x03,0x81,0xdf,0x1d,0x1a,0x04,0x03,0x05,0x1c,0x20,0xd4,0xb1,0xfe,0x8c,0xa3,0xdf,0x07,0x10,0x10,0x0f, 0x04,0x06,0x10,0x11,0x10,0x07,0xda,0xa3,0xfe,0x8c,0xb0,0xd7,0x10,0x16,0x0e,0x09,0x02,0x03,0x04,0x1a,0x1d,0xde,0x04,0x33,0xfd,0x5e,0x5a,0x71,0x17,0x1c,0x71,0x62,0x02,0x95,0xfb,0xcd,0x02,0xa4,0x15,0x37,0x3e,0x3e,0x1c,0x1f,0x43,0x40,0x39,0x14,0xfd,0x67,0x04,0x33,0xfd,0x6b,0x31,0x4d,0x3a,0x29,0x0e,0x17,0x71,0x5a,0x02,0xa2, 0x00,0x01,0x00,0x1e,0x00,0x00,0x03,0xe4,0x04,0x33,0x00,0x19,0x00,0x0f,0xb5,0x0b,0x00,0x0d,0x35,0x0b,0x33,0x00,0x3f,0x3f,0x01,0x2f,0x2f,0x31,0x30,0x21,0x23,0x01,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x23,0x01,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x13,0x33,0x01,0x03,0xe4,0xc3,0xfe,0xfa,0x06,0x0e,0x08,0x03, 0x04,0x0e,0x0b,0xfe,0xc3,0x01,0x7c,0xfe,0xa2,0xc5,0xe6,0x0d,0x15,0x09,0x03,0x0d,0x17,0x0a,0xe3,0xb8,0xfe,0x9a,0x01,0x8e,0x0a,0x1a,0x12,0x09,0x1b,0x12,0xfe,0x72,0x02,0x28,0x02,0x0b,0xfe,0x91,0x14,0x25,0x12,0x19,0x27,0x0e,0x01,0x6c,0xfd,0xdf,0x00,0x01,0x00,0x14,0x00,0x00,0x03,0xa7,0x04,0x33,0x00,0x0f,0x00,0x1d,0x40,0x0d, 0x0a,0x02,0x37,0x03,0x03,0x06,0x05,0x0f,0x00,0x05,0x35,0x03,0x33,0x00,0x3f,0x3f,0x01,0x2f,0x32,0x2f,0x33,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x01,0x11,0x23,0x11,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x13,0x03,0xa7,0xfe,0x83,0xa3,0xfe,0x8d,0xb4,0xf3,0x06,0x0f,0x08,0x02,0x05,0x10,0x0b,0xff,0x04,0x33,0xfd,0x5a, 0xfe,0x73,0x01,0x8a,0x02,0xa9,0xfe,0x25,0x0c,0x21,0x15,0x0d,0x21,0x14,0x01,0xdb,0x00,0x01,0x00,0x29,0x00,0x00,0x03,0xb3,0x04,0x33,0x00,0x09,0x00,0x26,0x40,0x12,0x07,0x07,0x00,0x01,0x04,0x06,0x03,0x00,0x00,0x07,0x39,0x08,0x35,0x05,0x01,0x39,0x04,0x33,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x01,0x2f,0x33,0x33,0x2f,0x33,0x12, 0x39,0x2f,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x35,0x01,0x21,0x35,0x21,0x03,0xb3,0xfd,0x73,0x02,0x7c,0xfc,0x87,0x02,0x8b,0xfd,0xad,0x03,0x52,0x04,0x02,0xfc,0x89,0x8b,0x37,0x03,0x71,0x8b,0x00,0x00,0x02,0xff,0xf8,0x00,0x00,0x05,0x56,0x04,0x33,0x00,0x0f,0x00,0x13,0x00,0x59,0x40,0x33,0x0a,0x0e,0x37,0x01,0x11,0x01,0x10,0x01, 0x0c,0x08,0x08,0x0c,0x01,0x10,0x04,0x00,0x05,0x00,0x09,0x13,0x39,0x06,0x03,0x39,0x10,0x0d,0x39,0x0a,0x0f,0x0a,0x01,0x2f,0x0a,0x3f,0x0a,0xff,0x0a,0x03,0x10,0x0a,0x10,0x0a,0x01,0x06,0x35,0x05,0x33,0x0e,0x39,0x01,0x33,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x71,0x10,0xed,0x10,0xed,0x10,0xed,0x32,0x01,0x2f, 0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x11,0x21,0x03,0x23,0x01,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x01,0x21,0x11,0x23,0x05,0x56,0xfd,0x89,0xfe,0x6f,0x9b,0xbb,0x02,0x46,0x02,0xfc,0xfe,0x49,0x01,0x95,0xfe,0x6b,0x01,0xd3,0xfc,0x3c,0x01,0x4d,0x49,0x01,0x28,0xfe,0xd8, 0x04,0x33,0x8b,0xfe,0xc0,0x8b,0xfe,0xae,0x01,0x28,0x01,0xf6,0x00,0x02,0x00,0x58,0xff,0xed,0x05,0xe8,0x04,0x45,0x00,0x1e,0x00,0x2e,0x00,0x51,0x40,0x2f,0x19,0x1d,0x37,0x1f,0x1b,0x1f,0x1b,0x00,0x28,0x38,0x0b,0x17,0x00,0x18,0x20,0x39,0x15,0x1c,0x39,0x0f,0x19,0x01,0x2f,0x19,0x3f,0x19,0xff,0x19,0x03,0x19,0x19,0x01,0x15,0x35, 0x23,0x39,0x10,0x36,0x2d,0x39,0x06,0x34,0x1d,0x1f,0x39,0x01,0x33,0x00,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x5d,0x71,0xed,0x10,0xed,0x32,0x01,0x2f,0x33,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x32,0x31,0x30,0x21,0x21,0x22,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x23,0x21, 0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x25,0x11,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x05,0xe8,0xfd,0xab,0x06,0x3a,0x50,0x57,0x23,0x80,0xcf,0x93,0x4f,0x52,0x99,0xd8,0x86,0x25,0x58,0x49,0x2f,0x03,0x02,0x3b,0xfe,0x47,0x01,0x97,0xfe,0x69,0x01,0xd3,0xfd,0x89,0x40,0x6a,0x2b,0x5b,0x96,0x6c,0x3c,0x3b, 0x6b,0x95,0x59,0x5a,0x06,0x07,0x06,0x4f,0x8f,0xc8,0x7a,0x82,0xd2,0x94,0x50,0x06,0x06,0x06,0x8b,0xfe,0xc0,0x8b,0xfe,0xae,0x06,0x03,0x14,0x0b,0x0b,0x3f,0x70,0x9a,0x5a,0x5b,0x98,0x6e,0x3e,0x00,0x00,0x01,0x00,0x38,0x00,0x00,0x03,0x2e,0x04,0x33,0x00,0x0d,0x00,0x34,0x40,0x19,0x08,0x0c,0x37,0x01,0x0a,0x0a,0x00,0x05,0x03,0x01, 0x00,0x02,0x08,0x09,0x03,0x09,0x03,0x09,0x01,0x06,0x35,0x0c,0x39,0x01,0x33,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x01,0x2f,0x2f,0xc6,0x33,0x12,0x39,0x2f,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x11,0x07,0x35,0x37,0x11,0x33,0x11,0x25,0x15,0x05,0x11,0x21,0x03,0x2e,0xfd,0x82,0x78,0x78,0xa4,0x01,0x01,0xfe, 0xff,0x01,0xda,0x01,0x95,0x44,0x8a,0x43,0x02,0x15,0xfe,0x48,0x8f,0x8b,0x8d,0xfe,0x99,0x00,0x00,0x03,0x00,0x41,0xff,0xda,0x04,0xa9,0x04,0x65,0x00,0x1b,0x00,0x26,0x00,0x32,0x00,0x28,0x40,0x14,0x1f,0x30,0x2c,0x00,0x38,0x1c,0x2c,0x38,0x0e,0x2f,0x1e,0x22,0x27,0x39,0x13,0x36,0x22,0x39,0x05,0x34,0x00,0x3f,0xed,0x3f,0xed,0x11, 0x39,0x39,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x07,0x27,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x37,0x17,0x07,0x16,0x16,0x07,0x34,0x27,0x01,0x16,0x16,0x33,0x32,0x3e,0x02,0x01,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x01,0x26,0x26,0x04,0xa9,0x4d,0x90,0xce, 0x82,0x6f,0xb6,0x45,0x83,0x4e,0x86,0x36,0x39,0x4d,0x92,0xd4,0x86,0x61,0xa4,0x42,0x7b,0x4f,0x7a,0x3f,0x42,0xab,0x44,0xfd,0xc4,0x30,0x80,0x4e,0x5c,0x8f,0x63,0x34,0xfe,0x88,0x57,0x8f,0x66,0x37,0x1d,0x1b,0x02,0x34,0x2d,0x74,0x02,0x27,0x82,0xd2,0x95,0x51,0x3c,0x39,0x88,0x49,0x8c,0x45,0xb0,0x69,0x81,0xd1,0x95,0x51,0x32,0x2f, 0x81,0x4b,0x7f,0x47,0xbd,0x80,0xa8,0x68,0xfd,0xac,0x2d,0x2f,0x38,0x6a,0x9b,0x02,0x07,0x3c,0x6e,0x9b,0x5e,0x46,0x78,0x31,0x02,0x4e,0x21,0x23,0x00,0x02,0x00,0xb0,0x00,0x00,0x03,0x92,0x04,0x33,0x00,0x10,0x00,0x19,0x00,0x2e,0x40,0x17,0x00,0x38,0x11,0x16,0x0b,0x07,0x37,0x08,0x06,0x3a,0x16,0x15,0x3a,0x0b,0x16,0x0b,0x16,0x0b, 0x08,0x09,0x35,0x08,0x33,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x32,0x32,0x2f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x23,0x15,0x23,0x11,0x33,0x15,0x33,0x32,0x1e,0x02,0x07,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x03,0x92,0x3f,0x73,0xa3,0x63,0x86,0xa4,0xa4,0xa7,0x61,0x98,0x68,0x36, 0xab,0x86,0x87,0x86,0x76,0x89,0x94,0x02,0x2c,0x4d,0x82,0x5e,0x34,0xcb,0x04,0x33,0xc2,0x2c,0x54,0x79,0x52,0x6b,0x5a,0xfe,0x65,0x69,0x00,0x02,0x00,0x2d,0x00,0x00,0x04,0x54,0x04,0x33,0x00,0x0e,0x00,0x1f,0x00,0x35,0x40,0x1b,0x18,0x18,0x06,0x00,0x38,0x0f,0x16,0x1a,0x37,0x0a,0x08,0x06,0x19,0x08,0x39,0x16,0x09,0x09,0x06,0x15, 0x39,0x0b,0x35,0x1a,0x39,0x06,0x33,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xc6,0x33,0xed,0x32,0x2f,0xed,0x12,0x39,0x2f,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x21,0x11,0x23,0x35,0x33,0x11,0x21,0x20,0x00,0x03,0x34,0x2e,0x02,0x23,0x23,0x11,0x33,0x15,0x23,0x11,0x33,0x32,0x3e,0x02,0x04,0x54,0x5d,0xa9, 0xef,0x92,0xfe,0xe3,0x83,0x83,0x01,0x2b,0x01,0x3c,0x01,0x3d,0xab,0x3c,0x76,0xae,0x72,0x83,0xfb,0xfb,0x7a,0x6e,0xb0,0x7b,0x42,0x02,0x27,0x7d,0xcb,0x90,0x4f,0x01,0xe1,0x89,0x01,0xc9,0xfe,0xfb,0xfe,0xf6,0x67,0x92,0x5c,0x2a,0xfe,0xc7,0x89,0xfe,0xaf,0x30,0x64,0x98,0x00,0x01,0x00,0xa6,0xff,0xee,0x03,0xe8,0x04,0x45,0x00,0x39, 0x00,0x3f,0x40,0x21,0x27,0x38,0x14,0x30,0x38,0x09,0x01,0x0f,0x1c,0x14,0x09,0x14,0x09,0x3b,0x1b,0x37,0x1c,0x2a,0x0e,0x3b,0x0f,0x0f,0x22,0x04,0x39,0x35,0x34,0x17,0x39,0x22,0x36,0x1c,0x33,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31, 0x30,0x25,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x35,0x3e,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x01,0x9a,0x26,0x73,0x43,0x28,0x48,0x36,0x1f,0x2a,0x57,0x84,0x5a,0x39,0x5c, 0x41,0x23,0x5a,0x58,0x65,0x74,0xa4,0x42,0x6c,0x8c,0x4a,0x4e,0x7f,0x5a,0x31,0x68,0x77,0x56,0x7b,0x4f,0x25,0x31,0x5e,0x88,0x56,0x2c,0x43,0x35,0x2a,0x0a,0x97,0x12,0x1a,0x13,0x2a,0x42,0x30,0x2f,0x4f,0x3b,0x25,0x05,0x71,0x06,0x1c,0x2f,0x41,0x2a,0x45,0x43,0x71,0x7d,0xfd,0x32,0x02,0xe3,0x68,0x88,0x51,0x21,0x24,0x43,0x61,0x3c, 0x5a,0x80,0x1e,0x04,0x0d,0x31,0x48,0x62,0x3f,0x45,0x70,0x4f,0x2c,0x05,0x07,0x0a,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x06,0x28,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0x43,0x00,0x96,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x06,0x28,0x02,0x26, 0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x0e,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x06,0x2c,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0x8c,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00, 0x00,0x00,0x04,0x04,0x05,0xd0,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0x9f,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0xa5,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x06,0x00,0x8f,0x62,0x1e,0x00,0x0c,0xb5,0x03,0x02,0x0f,0x17,0x01,0x17,0x00, 0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0x67,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0xdc,0x00,0xdf,0xff,0x4b,0x00,0x09,0xb3,0x03,0x02,0x27,0x35,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x58,0xfe,0x56,0x03,0xbb,0x04,0x45,0x02,0x26,0x0c,0xed,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x97,0x00,0x06, 0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x06,0x28,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x06,0x00,0x43,0x79,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x06,0x28,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xec,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d, 0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x06,0x2c,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x06,0x00,0xd7,0x6c,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x05,0xa5,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x06,0x00,0x8f,0x53,0x1e,0x00,0x0c, 0xb5,0x02,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xfc,0x00,0x00,0x01,0x81,0x06,0x28,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0x43,0xaa,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x87,0x00,0x00,0x02,0x0c,0x06,0x28,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06, 0x00,0x8e,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xe9,0x00,0x00,0x02,0x1d,0x06,0x2c,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0xd7,0x8d,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xe0,0x00,0x00,0x02,0x27,0x05,0xa5,0x02,0x26,0x0c,0xf3, 0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x63,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x7a,0x05,0xd0,0x02,0x26,0x0c,0xf8,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x32,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x23,0x01,0x23,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58, 0xff,0xed,0x04,0x95,0x06,0x28,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x14,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x06,0x28,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x68,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24, 0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x06,0x2c,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x00,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x05,0xd0,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0xd8,0x01,0x13,0x00,0x1e, 0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x05,0xa5,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xd6,0x00,0x1e,0x00,0x0c,0xb5,0x03,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x06,0x28,0x02,0x26,0x0c,0xff, 0x00,0x00,0x01,0x07,0x00,0x43,0x01,0x07,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x06,0x28,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x62,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9c,0xff,0xed, 0x04,0x26,0x06,0x2c,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0xd7,0x00,0xeb,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x05,0xa5,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0x8f,0x00,0xc1,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x16,0x01,0x16,0x00, 0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x06,0x28,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xf1,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x10,0x01,0x10,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0x4d,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0xc6,0x00,0x1e, 0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0xdc,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xc9,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfe,0x70,0x04,0x04,0x04,0x33,0x02,0x26,0x0c,0xeb,0x00,0x00, 0x00,0x07,0x00,0xdf,0x02,0xab,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xed,0x03,0xbb,0x06,0x28,0x02,0x26,0x0c,0xed,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x71,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1e,0x01,0x1e,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x03,0xbb,0x06,0x2a,0x02,0x26,0x0c,0xed,0x00,0x00,0x01,0x07,0x00,0xe0, 0x00,0xf1,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1e,0x01,0x1e,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x20,0x05,0xa3,0x02,0x26,0x0c,0xf1,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0xba,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x23,0x01,0x23,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x54,0x06,0x2a,0x02,0x26, 0x0c,0xee,0x00,0x00,0x01,0x07,0x00,0xe0,0x00,0xc9,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x18,0x01,0x18,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x2d,0x00,0x00,0x04,0x54,0x04,0x33,0x02,0x06,0x0d,0x0a,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x05,0x4d,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x07,0x00,0xd9,0x00,0x9c,0x00,0x1e, 0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x05,0xdc,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xac,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x05,0xa3,0x02,0x26,0x0c,0xef,0x00,0x00, 0x01,0x07,0x00,0xdb,0x01,0x15,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0xfe,0x70,0x03,0x27,0x04,0x33,0x02,0x26,0x0c,0xef,0x00,0x00,0x00,0x07,0x00,0xdf,0x01,0xbe,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x06,0x2a,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x06,0x00,0xe0, 0x66,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x20,0x05,0xdc,0x02,0x26,0x0c,0xf1,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x52,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x23,0x01,0x23,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xfe,0x85,0x04,0x20,0x04,0x45,0x02,0x26,0x0c,0xf1, 0x00,0x00,0x00,0x07,0x01,0x9c,0x00,0xf8,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xed,0x03,0xbb,0x05,0xa3,0x02,0x26,0x0c,0xed,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0xb0,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1e,0x01,0x1e,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x39,0x06,0x2c,0x02,0x26,0x0c,0xf2,0x00,0x00,0x01,0x07, 0x00,0xd7,0x00,0xfe,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0c,0x01,0x0c,0x00,0x11,0x5d,0x35,0x00,0x02,0x00,0x2d,0x00,0x00,0x04,0xbc,0x04,0x33,0x00,0x13,0x00,0x17,0x00,0x4a,0x40,0x0e,0x17,0x0c,0x04,0x37,0x05,0x14,0x0d,0x00,0x37,0x01,0x03,0x39,0x17,0x17,0xb8,0xff,0xc0,0x40,0x16,0x09,0x0c,0x48,0x16,0x13,0x06,0x39,0x09,0x10, 0x0c,0x09,0x17,0x09,0x17,0x09,0x05,0x0e,0x0a,0x35,0x01,0x05,0x33,0x00,0x3f,0x33,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x2b,0x10,0xed,0x01,0x2f,0xed,0x33,0x33,0x2f,0xed,0x32,0x32,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x15,0x23, 0x07,0x35,0x21,0x15,0x04,0x39,0xa5,0xfd,0xc0,0xa4,0x83,0x83,0xa4,0x02,0x40,0xa5,0x83,0x83,0xa5,0xfd,0xc0,0x01,0xf3,0xfe,0x0d,0x03,0x2b,0x89,0x7f,0x7f,0x7f,0x7f,0x89,0xad,0xad,0xad,0xff,0xff,0xff,0xc3,0x00,0x00,0x02,0x44,0x05,0xd0,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0xd8,0xa0,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05, 0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x04,0x00,0x00,0x02,0x00,0x05,0x4d,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0xd9,0xc6,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xf1,0x00,0x00,0x02,0x16,0x05,0xdc,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0xda,0xcc,0x1e,0x00,0x0a, 0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x3f,0xfe,0x70,0x01,0x54,0x04,0x33,0x02,0x26,0x0c,0xf3,0x00,0x00,0x00,0x06,0x00,0xdf,0x01,0x00,0xff,0xff,0x00,0xa0,0x00,0x00,0x01,0x65,0x05,0xa3,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0xdb,0x34,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0xb0,0xff,0xed,0x03,0xe9,0x04,0x33,0x00,0x26,0x0c,0xf3,0x00,0x00,0x00,0x07,0x0c,0xf4,0x02,0x04,0x00,0x00,0xff,0xff,0x00,0x11,0xff,0xed,0x02,0xac,0x06,0x2c,0x02,0x26,0x0c,0xf4,0x00,0x00,0x01,0x06,0x00,0xd7,0x1c,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x13,0x01,0x13,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0, 0xfe,0x85,0x03,0xec,0x04,0x33,0x02,0x26,0x0c,0xf5,0x00,0x00,0x00,0x07,0x01,0x9c,0x00,0xa8,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x2e,0x06,0x28,0x02,0x26,0x0c,0xf6,0x00,0x00,0x01,0x06,0x00,0x8e,0x52,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x06,0x01,0x06,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0xfe,0x85,0x03,0x2e,0x04,0x33, 0x02,0x26,0x0c,0xf6,0x00,0x00,0x00,0x06,0x01,0x9c,0x6b,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x2e,0x04,0x33,0x02,0x26,0x0c,0xf6,0x00,0x00,0x00,0x07,0x01,0x9c,0x01,0x13,0x04,0xaa,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x2e,0x04,0x33,0x02,0x26,0x0c,0xf6,0x00,0x00,0x00,0x07,0x00,0xdb,0x01,0x8a,0xfd,0x56,0xff,0xff,0x00,0xb0, 0x00,0x00,0x04,0x7a,0x06,0x28,0x02,0x26,0x0c,0xf8,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x9e,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1a,0x01,0x1a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0xfe,0x85,0x04,0x7a,0x04,0x33,0x02,0x26,0x0c,0xf8,0x00,0x00,0x00,0x07,0x01,0x9c,0x01,0x0c,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x7a, 0x06,0x2a,0x02,0x26,0x0c,0xf8,0x00,0x00,0x01,0x07,0x00,0xe0,0x01,0x16,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1a,0x01,0x1a,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0xb0,0xfe,0x59,0x04,0x88,0x04,0x33,0x00,0x26,0x00,0x32,0x40,0x18,0x26,0x37,0x25,0x0f,0x25,0x08,0x08,0x25,0x1a,0x17,0x37,0x18,0x20,0x13,0x17,0x25,0x19,0x35,0x0f,0x00, 0x17,0x0a,0x39,0x05,0x00,0x2f,0xed,0x2f,0x33,0x33,0x3f,0x33,0x12,0x39,0x39,0x01,0x2f,0xed,0x32,0x2f,0x33,0x2f,0x11,0x33,0x10,0xed,0x31,0x30,0x05,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x01,0x26,0x26,0x27,0x23,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x1e,0x03,0x17,0x33,0x26,0x26,0x35,0x11,0x33,0x04, 0x88,0x33,0x5e,0x83,0x4f,0x46,0x2c,0x2c,0x48,0x2f,0x46,0x2f,0x18,0xfd,0xbc,0x20,0x28,0x08,0x05,0x06,0xa0,0xc0,0x02,0x35,0x12,0x19,0x11,0x09,0x03,0x03,0x04,0x04,0xa0,0x13,0x65,0x98,0x65,0x32,0x13,0x9a,0x1d,0x1b,0x42,0x6e,0x52,0x02,0xf1,0x29,0x42,0x13,0x23,0x71,0xfd,0x1f,0x04,0x33,0xfd,0x21,0x19,0x23,0x18,0x10,0x05,0x17, 0x4e,0x39,0x02,0xaa,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x05,0x4d,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x3a,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x05,0xdc,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x3f,0x00,0x1e, 0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x06,0x1e,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0xde,0x01,0x7d,0x00,0x1e,0x00,0x0c,0xb5,0x03,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0xdf,0x06,0x28,0x02,0x26,0x0c,0xfc, 0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x03,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x25,0x01,0x25,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0xfe,0x85,0x03,0xdf,0x04,0x33,0x02,0x26,0x0c,0xfc,0x00,0x00,0x00,0x07,0x01,0x9c,0x00,0xa0,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0xdf,0x06,0x2a,0x02,0x26,0x0c,0xfc,0x00,0x00,0x01,0x07, 0x00,0xe0,0x00,0x83,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x25,0x01,0x25,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x68,0xff,0xed,0x03,0x08,0x06,0x28,0x02,0x26,0x0c,0xfd,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xc9,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x3a,0x01,0x3a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x68,0xff,0xed,0x03,0x08,0x06,0x2c, 0x02,0x26,0x0c,0xfd,0x00,0x00,0x01,0x06,0x00,0xd7,0x4e,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x3a,0x01,0x3a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x68,0xfe,0x50,0x03,0x08,0x04,0x45,0x02,0x26,0x0c,0xfd,0x00,0x00,0x00,0x07,0x00,0xdd,0x00,0xdc,0x00,0x00,0xff,0xff,0x00,0x68,0xff,0xed,0x03,0x08,0x06,0x2a,0x02,0x26,0x0c,0xfd,0x00,0x00, 0x01,0x06,0x00,0xe0,0x4f,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x3a,0x01,0x3a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x19,0xfe,0x50,0x03,0x6c,0x04,0x33,0x02,0x26,0x0c,0xfe,0x00,0x00,0x00,0x07,0x00,0xdd,0x01,0x15,0x00,0x00,0xff,0xff,0x00,0x19,0xfe,0x85,0x03,0x6c,0x04,0x33,0x02,0x26,0x0c,0xfe,0x00,0x00,0x00,0x06,0x01,0x9c,0x2d,0x00, 0xff,0xff,0x00,0x19,0x00,0x00,0x03,0x6c,0x06,0x2a,0x02,0x26,0x0c,0xfe,0x00,0x00,0x01,0x06,0x00,0xe0,0x43,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x08,0x01,0x08,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0x19,0x00,0x00,0x03,0x6c,0x04,0x33,0x00,0x0f,0x00,0x3d,0x40,0x1f,0x02,0x06,0x37,0x07,0x0b,0x07,0x0a,0x07,0x03,0x03,0x07,0x0a,0x03,0x00, 0x0d,0x00,0x01,0x0d,0x39,0x0e,0x05,0x09,0x39,0x02,0x0a,0x0a,0x07,0x0e,0x35,0x07,0x33,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x01,0x21,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x03,0x6c,0xfe, 0xa9,0x01,0x0e,0xfe,0xf2,0xa4,0xfe,0xf1,0x01,0x0f,0xfe,0xa8,0x03,0x53,0x03,0xa8,0xfe,0xb6,0x89,0xfe,0x2b,0x01,0xd5,0x89,0x01,0x4a,0x8b,0x00,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x05,0xd0,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0xd8,0x00,0xfe,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35, 0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x05,0x4d,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0xd9,0x01,0x25,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x05,0xdc,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x2a,0x00,0x1e,0x00,0x0a,0xb4,0x01, 0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x06,0x3a,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07,0x00,0xdc,0x01,0x41,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x9c,0xff,0xed,0x04,0x26,0x06,0x1e,0x02,0x26,0x0c,0xff,0x00,0x00,0x01,0x07, 0x00,0xde,0x01,0x51,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x16,0x01,0x16,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x9c,0xfe,0x70,0x04,0x26,0x04,0x33,0x02,0x26,0x0c,0xff,0x00,0x00,0x00,0x07,0x00,0xdf,0x01,0xaa,0x00,0x00,0xff,0xff,0x00,0x05,0x00,0x00,0x06,0x64,0x06,0x2c,0x02,0x26,0x0d,0x01,0x00,0x00,0x01,0x07,0x00,0xd7, 0x01,0xbe,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x27,0x01,0x27,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x05,0x00,0x00,0x06,0x64,0x06,0x28,0x02,0x26,0x0d,0x01,0x00,0x00,0x01,0x07,0x00,0x43,0x01,0xa6,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x27,0x01,0x27,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x05,0x00,0x00,0x06,0x64,0x06,0x28,0x02,0x26, 0x0d,0x01,0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x5e,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x27,0x01,0x27,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x05,0x00,0x00,0x06,0x64,0x05,0xa5,0x02,0x26,0x0d,0x01,0x00,0x00,0x01,0x07,0x00,0x8f,0x01,0x94,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x27,0x01,0x27,0x00,0x11,0x5d,0x35,0x35,0xff,0xff, 0x00,0x14,0x00,0x00,0x03,0xa7,0x06,0x2c,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x06,0x00,0xd7,0x67,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x10,0x01,0x10,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x05,0xa5,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x06,0x00,0x8f,0x3d,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x10,0x01,0x10,0x00, 0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x06,0x28,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x06,0x00,0x43,0x71,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x10,0x01,0x10,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x29,0x00,0x00,0x03,0xb3,0x06,0x28,0x02,0x26,0x0d,0x04,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x21,0x00,0x1e,0x00,0x0a, 0xb4,0x01,0x0f,0x0b,0x01,0x0b,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x29,0x00,0x00,0x03,0xb3,0x05,0xa3,0x02,0x26,0x0d,0x04,0x00,0x00,0x01,0x07,0x00,0xdb,0x01,0x3d,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x13,0x01,0x13,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x29,0x00,0x00,0x03,0xb3,0x06,0x2a,0x02,0x26,0x0d,0x04,0x00,0x00,0x01,0x07, 0x00,0xe0,0x00,0x8d,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0a,0x01,0x0a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x06,0xe3,0x02,0x26,0x0c,0xeb,0x00,0x00,0x00,0x27,0x00,0xdc,0x00,0xdf,0xff,0x4b,0x01,0x07,0x00,0x8e,0x01,0x14,0x00,0xd9,0x00,0x2a,0x40,0x1b,0x04,0xe0,0x2f,0x01,0x90,0x2f,0x01,0x90,0x2f,0x01, 0x80,0x2f,0x01,0x70,0x2f,0x01,0x70,0x2f,0x01,0x60,0x2f,0x01,0x2f,0x03,0x02,0x27,0x35,0x00,0x3f,0x35,0x35,0x11,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x35,0xff,0xff,0xff,0xf8,0x00,0x00,0x05,0x56,0x06,0x28,0x02,0x26,0x0d,0x05,0x00,0x00,0x01,0x07,0x00,0x8e,0x02,0x7b,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x16,0x01,0x16,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0x41,0xff,0xda,0x04,0xa9,0x06,0x28,0x02,0x26,0x0d,0x08,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x69,0x00,0x1e,0x00,0x0a,0xb4,0x03,0x0f,0x35,0x01,0x35,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x33,0x02,0x06,0x0c,0xeb,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0xa1,0x04,0x33, 0x02,0x06,0x0c,0xec,0x00,0x00,0x00,0x01,0x00,0x9c,0x00,0x00,0x03,0x06,0x04,0x33,0x00,0x05,0x00,0x18,0x40,0x0b,0x00,0x07,0x02,0x37,0x03,0x01,0x39,0x04,0x35,0x03,0x33,0x00,0x3f,0x3f,0xed,0x01,0x2f,0xed,0x11,0x33,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x03,0x06,0xfe,0x3a,0xa4,0x02,0x6a,0x03,0xa6,0xfc,0x5a,0x04,0x33,0x00, 0x00,0x02,0x00,0x2a,0x00,0x00,0x04,0x20,0x04,0x33,0x00,0x05,0x00,0x0e,0x00,0x23,0x40,0x10,0x0e,0x02,0x06,0x05,0x02,0x05,0x0f,0x10,0x09,0x01,0x03,0x35,0x0e,0x39,0x01,0x33,0x00,0x3f,0xed,0x3f,0x12,0x39,0x11,0x12,0x01,0x39,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x21,0x21,0x35,0x01,0x33,0x01,0x27,0x01,0x26,0x27,0x23,0x06,0x06, 0x07,0x01,0x04,0x20,0xfc,0x0a,0x01,0xa7,0xa4,0x01,0xab,0xcb,0xfe,0xed,0x1c,0x04,0x03,0x03,0x10,0x0e,0xfe,0xf3,0x39,0x03,0xfa,0xfc,0x06,0x51,0x02,0x9a,0x44,0x26,0x12,0x35,0x23,0xfd,0x66,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x04,0x33,0x02,0x06,0x0c,0xef,0x00,0x00,0xff,0xff,0x00,0x29,0x00,0x00,0x03,0xb3,0x04,0x33, 0x02,0x06,0x0d,0x04,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x39,0x04,0x33,0x02,0x06,0x0c,0xf2,0x00,0x00,0x00,0x03,0x00,0x58,0xff,0xed,0x04,0x95,0x04,0x45,0x00,0x03,0x00,0x17,0x00,0x27,0x00,0x2f,0x40,0x18,0x02,0x01,0x20,0x04,0x38,0x18,0x18,0x29,0x20,0x38,0x0e,0x00,0x39,0x01,0x01,0x25,0x1b,0x39,0x13,0x36,0x25,0x39, 0x09,0x34,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x12,0x39,0x39,0x31,0x30,0x01,0x35,0x21,0x15,0x25,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x01,0xac,0x01,0x95,0x01,0x54,0x52, 0x91,0xc9,0x77,0x78,0xc6,0x8e,0x4e,0x4b,0x8f,0xd0,0x85,0x7a,0xc3,0x88,0x49,0xab,0xb7,0xb7,0x57,0x8c,0x62,0x34,0x31,0x5f,0x88,0x57,0xb8,0xc0,0x01,0xdd,0x8b,0x8b,0x4a,0x86,0xd4,0x93,0x4d,0x4f,0x90,0xc8,0x79,0x7c,0xd0,0x97,0x55,0x55,0x93,0xc6,0x80,0xc8,0xdc,0x3c,0x6e,0x9b,0x5e,0x5e,0x9a,0x6d,0x3c,0xda,0xff,0xff,0x00,0xb0, 0x00,0x00,0x01,0x54,0x04,0x33,0x02,0x06,0x0c,0xf3,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0xec,0x04,0x33,0x02,0x06,0x0c,0xf5,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x15,0x04,0x33,0x00,0x0d,0x00,0x22,0x40,0x0f,0x04,0x03,0x0d,0x00,0x03,0x00,0x0f,0x0e,0x04,0x08,0x01,0x0d,0x33,0x01,0x35,0x00,0x3f,0x3f,0x12,0x39, 0x39,0x11,0x12,0x01,0x39,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x31,0x01,0x33,0x01,0x23,0x01,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x01,0xbd,0xa3,0x01,0xb5,0xb9,0xfe,0xf4,0x20,0x1e,0x04,0x03,0x04,0x20,0x22,0xfe,0xee,0x04,0x33,0xfb,0xcd,0x02,0xc0,0x53,0x5f,0x1c,0x17,0x61,0x57,0xfd,0x41,0x00,0xff,0xff,0x00,0xb0,0x00,0x00, 0x05,0x62,0x04,0x33,0x02,0x06,0x0c,0xf7,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x7a,0x04,0x33,0x02,0x06,0x0c,0xf8,0x00,0x00,0x00,0x03,0x00,0x49,0x00,0x00,0x03,0x4c,0x04,0x33,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x30,0x40,0x19,0x02,0x03,0x06,0x07,0x04,0x0b,0x0a,0x0b,0x0a,0x0b,0x0c,0x0d,0x05,0x39,0x06,0x06,0x02,0x0a, 0x39,0x09,0x33,0x01,0x39,0x02,0x35,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xed,0x11,0x12,0x01,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x21,0x35,0x21,0x13,0x21,0x35,0x21,0x03,0x36,0xfd,0x29,0x02,0xd7,0x73,0xfe,0x0f,0x01,0xf1,0x89,0xfc,0xfd,0x03,0x03,0x03,0xa3,0x90,0xfd,0xa7,0x8c,0xfd,0x9a, 0x91,0x00,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x04,0x45,0x02,0x06,0x0c,0xf9,0x00,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x04,0x37,0x04,0x33,0x00,0x07,0x00,0x1b,0x40,0x0d,0x04,0x37,0x05,0x00,0x37,0x01,0x03,0x39,0x06,0x35,0x01,0x05,0x33,0x00,0x3f,0x33,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x21,0x11, 0x23,0x11,0x21,0x04,0x37,0xa5,0xfd,0xc2,0xa4,0x03,0x87,0x03,0xa6,0xfc,0x5a,0x04,0x33,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x92,0x04,0x33,0x02,0x06,0x0c,0xfa,0x00,0x00,0x00,0x01,0x00,0x30,0x00,0x00,0x03,0x63,0x04,0x33,0x00,0x0b,0x00,0x34,0x40,0x1a,0x08,0x04,0x03,0x07,0x09,0x0b,0x04,0x09,0x0b,0x0b,0x09,0x04,0x03,0x0d, 0x0a,0x02,0x04,0x08,0x39,0x05,0x35,0x02,0x0a,0x39,0x01,0x33,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x32,0x11,0x33,0x31,0x30,0x21,0x21,0x35,0x01,0x01,0x35,0x21,0x15,0x21,0x01,0x01,0x21,0x03,0x63,0xfc,0xcd,0x01,0x82,0xfe,0xa1,0x02,0xdc,0xfe,0x0d,0x01,0x27,0xfe,0xb0, 0x02,0x50,0x44,0x01,0xe5,0x01,0xbd,0x4d,0x8c,0xfe,0x87,0xfe,0x59,0x00,0xff,0xff,0x00,0x19,0x00,0x00,0x03,0x6c,0x04,0x33,0x02,0x06,0x0c,0xfe,0x00,0x00,0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x04,0x33,0x02,0x06,0x0d,0x03,0x00,0x00,0x00,0x03,0x00,0x50,0xff,0xf5,0x04,0xb1,0x04,0x3d,0x00,0x1d,0x00,0x2a,0x00,0x37,0x00,0x46, 0x40,0x23,0x1f,0x12,0x01,0x37,0x37,0x0f,0x02,0x02,0x09,0x18,0x37,0x25,0x32,0x37,0x09,0x1f,0x37,0x3a,0x04,0x00,0x04,0x1e,0x2c,0x3a,0x0f,0x12,0x0f,0x04,0x0f,0x04,0x0f,0x02,0x10,0x36,0x02,0x00,0x2f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0x33, 0x33,0xed,0x32,0x32,0x31,0x30,0x25,0x15,0x23,0x35,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x33,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x03,0x11,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x02,0xcd,0x99,0x18,0x66,0xaa,0x79,0x43,0x43,0x7a, 0xaa,0x67,0x16,0x99,0x17,0x69,0xaa,0x78,0x42,0x44,0x79,0xa9,0x65,0x19,0x17,0x46,0x70,0x4e,0x29,0x2a,0x4f,0x70,0x46,0xae,0x14,0x45,0x71,0x4f,0x2b,0x29,0x4e,0x70,0x47,0x8b,0x96,0x96,0x3e,0x71,0x9c,0x5f,0x5d,0x97,0x6a,0x3a,0x70,0x70,0x3b,0x6b,0x97,0x5b,0x5f,0x9c,0x71,0x3e,0x02,0xc4,0xfd,0xc1,0x27,0x4b,0x6c,0x46,0x41,0x69, 0x49,0x28,0xfd,0xc1,0x02,0x3f,0x27,0x49,0x6a,0x42,0x46,0x6c,0x4a,0x27,0xff,0xff,0x00,0x1e,0x00,0x00,0x03,0xe4,0x04,0x33,0x02,0x06,0x0d,0x02,0x00,0x00,0x00,0x01,0x00,0x7d,0x00,0x00,0x04,0xc3,0x04,0x33,0x00,0x1b,0x00,0x34,0x40,0x1a,0x0d,0x00,0x37,0x0e,0x1b,0x1b,0x06,0x15,0x37,0x14,0x07,0x37,0x06,0x01,0x19,0x39,0x0c,0x10, 0x10,0x0e,0x1b,0x06,0x14,0x35,0x0e,0x33,0x00,0x3f,0x3f,0x33,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x11,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0x23,0x11,0x23,0x11,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x11,0x02,0xec,0x19,0x97, 0x88,0x9f,0xe1,0xdd,0x19,0x99,0x19,0xd7,0xe6,0x9e,0x88,0x97,0x19,0x04,0x33,0xfd,0x60,0x8a,0x89,0x01,0x8d,0xfe,0x73,0xc6,0xd4,0xfe,0xf4,0x01,0x0c,0xd1,0xc9,0x01,0x8d,0xfe,0x73,0x89,0x8a,0x02,0xa0,0x00,0x00,0x01,0x00,0x58,0x00,0x00,0x04,0xb8,0x04,0x45,0x00,0x2b,0x00,0x2a,0xbc,0x00,0x0f,0x01,0x50,0x00,0x1b,0x00,0x25,0x01, 0x50,0x40,0x0d,0x05,0x0a,0x39,0x20,0x36,0x2a,0x12,0x03,0x15,0x39,0x01,0x14,0x33,0x00,0x3f,0x33,0xed,0x32,0x32,0x32,0x3f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x21,0x21,0x35,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x15,0x21,0x35,0x21,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15, 0x14,0x0e,0x02,0x07,0x21,0x04,0xb8,0xfe,0x51,0x80,0x86,0x36,0x64,0x90,0x5a,0x5c,0x92,0x66,0x37,0x87,0x81,0xfe,0x50,0x01,0x0d,0x48,0x67,0x40,0x1e,0x51,0x93,0xcd,0x7d,0x7f,0xd0,0x93,0x50,0x1e,0x41,0x65,0x48,0x01,0x0c,0x8a,0x5d,0xd4,0x89,0x59,0x8c,0x62,0x33,0x33,0x62,0x8c,0x58,0x89,0xd5,0x5d,0x8a,0x8b,0x2c,0x62,0x6f,0x81, 0x4c,0x75,0xb8,0x80,0x43,0x42,0x7f,0xb9,0x76,0x4b,0x81,0x70,0x61,0x2d,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x06,0x28,0x02,0x26,0x0c,0xeb,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x1c,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x06,0x28,0x02,0x26,0x0c,0xef, 0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xe8,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x39,0x06,0x28,0x02,0x26,0x0c,0xf2,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x6f,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x0c,0x01,0x0c,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x87,0x00,0x00, 0x02,0x0c,0x06,0x28,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x06,0x00,0x8e,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x06,0x28,0x02,0x26,0x0c,0xf9,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x65,0x00,0x1e,0x00,0x0a,0xb4,0x02,0x0f,0x24,0x01,0x24,0x00,0x11,0x5d,0x35, 0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x06,0x28,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x07,0x00,0x8e,0x00,0xf5,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x10,0x01,0x10,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0x00,0x00,0x04,0xb8,0x06,0x28,0x02,0x26,0x0d,0x80,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x6d,0x00,0x1e,0x00,0x0a,0xb4,0x01, 0x0f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xe0,0x00,0x00,0x02,0x27,0x05,0xa5,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x63,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x14,0x00,0x00,0x03,0xa7,0x05,0xa5,0x02,0x26,0x0d,0x03,0x00,0x00,0x01,0x06, 0x00,0x8f,0x3d,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x10,0x01,0x10,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27,0x05,0x8a,0x02,0x26,0x0c,0xef,0x00,0x00,0x01,0x06,0x00,0x8f,0x45,0x03,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x0d,0x01,0x0d,0x00,0x11,0x5d,0x35,0x35,0x00,0x01,0x00,0x22,0xff,0xf2,0x04,0x3f,0x04,0x33, 0x00,0x1d,0x00,0x3e,0x40,0x20,0x13,0x0b,0x37,0x0c,0x19,0x37,0x06,0x01,0x11,0x06,0x0c,0x06,0x0c,0x06,0x1f,0x0e,0x0a,0x39,0x13,0x13,0x0f,0x03,0x3a,0x1c,0x34,0x12,0x0e,0x39,0x0f,0x35,0x0c,0x33,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x32, 0x31,0x30,0x25,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x02,0x7c,0x32,0x49,0x4a,0x58,0x7e,0x72,0xba,0xa3,0xfe,0xd6,0x03,0x3a,0xfe,0x93,0xca,0x59,0x90,0x66,0x37,0xa4,0x97,0x4c,0x04,0x8c,0x19,0x5f,0x52,0x60,0x68,0xfe,0x10, 0x03,0xa9,0x8a,0x8a,0xfe,0xce,0x2c,0x56,0x7c,0x51,0x94,0xa2,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x1a,0x06,0x28,0x00,0x26,0x0d,0x6b,0x14,0x00,0x01,0x07,0x00,0x8e,0x00,0xd6,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x06,0x01,0x06,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0x58,0xff,0xee,0x03,0xca,0x04,0x45,0x00,0x1c,0x00,0x2e,0x40,0x17, 0x0f,0x16,0x07,0x1c,0x1c,0x1e,0x14,0x17,0x38,0x07,0x17,0x39,0x14,0x14,0x1a,0x11,0x39,0x0c,0x36,0x1a,0x39,0x02,0x34,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x12,0x39,0x33,0x31,0x30,0x25,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21, 0x15,0x21,0x16,0x16,0x33,0x32,0x37,0x03,0xca,0x83,0xc3,0x7d,0xcd,0x92,0x50,0x56,0x9a,0xd4,0x7f,0xb0,0x7f,0x86,0xaa,0xb1,0xcf,0x15,0x01,0xf7,0xfe,0x08,0x0e,0xc8,0xb4,0xb9,0x83,0x2d,0x3f,0x48,0x89,0xc7,0x7f,0x8a,0xd6,0x93,0x4d,0x2c,0x9e,0x40,0xa9,0xb6,0x89,0xa5,0xb7,0x48,0xff,0xff,0x00,0x68,0xff,0xed,0x03,0x08,0x04,0x45, 0x02,0x06,0x0c,0xfd,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x01,0x54,0x04,0x33,0x02,0x06,0x0c,0xf3,0x00,0x00,0xff,0xff,0xff,0xe0,0x00,0x00,0x02,0x27,0x05,0xa5,0x02,0x26,0x0c,0xf3,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x63,0x00,0x1e,0x00,0x0c,0xb5,0x02,0x01,0x0f,0x05,0x01,0x05,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x11, 0xff,0xed,0x01,0xe5,0x04,0x33,0x02,0x06,0x0c,0xf4,0x00,0x00,0x00,0x02,0x00,0x0d,0xff,0xef,0x06,0x32,0x04,0x33,0x00,0x26,0x00,0x2f,0x00,0x44,0xb6,0x02,0x19,0x1b,0x28,0x37,0x00,0x21,0xb8,0x01,0x50,0x40,0x1b,0x2c,0x19,0x00,0x2c,0x2c,0x00,0x19,0x03,0x31,0x0f,0x27,0x39,0x1b,0x1b,0x28,0x02,0x39,0x19,0x35,0x11,0x39,0x0c,0x34, 0x28,0x39,0x00,0x33,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x11,0x33,0x31,0x30,0x21,0x11,0x21,0x0e,0x03,0x07,0x0e,0x03,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x37,0x36,0x12,0x37,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23, 0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x03,0x37,0xfe,0xe5,0x0e,0x1a,0x16,0x14,0x08,0x0f,0x26,0x45,0x6f,0x5a,0x42,0x30,0x2b,0x33,0x2c,0x38,0x27,0x1e,0x12,0x19,0x34,0x1d,0x02,0x4a,0xe2,0x58,0x8b,0x60,0x33,0x36,0x65,0x8f,0x58,0xd6,0xc4,0x70,0x7a,0x74,0x76,0x03,0xa9,0x66,0xa5,0x87,0x6a,0x2a,0x4e,0x92,0x70,0x44,0x0f, 0x8f,0x16,0x28,0x51,0x7a,0x52,0x70,0x01,0x39,0xce,0xfe,0x44,0x2b,0x50,0x73,0x48,0x4a,0x77,0x53,0x2d,0x01,0xed,0xfe,0x9d,0x52,0x5d,0x60,0x54,0x00,0x02,0x00,0xb0,0x00,0x00,0x06,0x46,0x04,0x33,0x00,0x08,0x00,0x1f,0x00,0x49,0xb6,0x1f,0x01,0x37,0x14,0x1c,0x14,0x0e,0xb8,0x01,0x50,0x40,0x1c,0x05,0x14,0x05,0x14,0x05,0x21,0x1b, 0x17,0x37,0x18,0x16,0x39,0x1b,0x00,0x39,0x1f,0x1b,0x1f,0x1b,0x1f,0x1d,0x19,0x35,0x01,0x39,0x17,0x14,0x33,0x00,0x3f,0x33,0xed,0x3f,0x33,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x01,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x21,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x03,0xf3,0xbf,0x70,0x7a,0x6f,0x76,0x1e,0x58,0x8a,0x5e,0x31,0x36,0x65,0x8f,0x58,0xfe,0x8c,0xfe,0x03,0xa3,0xa3,0x01,0xfd,0xa3,0x01,0xed,0xfe,0x9d,0x52,0x5d,0x60,0x54,0x8a,0x2b,0x50,0x73,0x48,0x4a,0x77,0x53,0x2d,0x01,0xec,0xfe, 0x14,0x04,0x33,0xfe,0x43,0x01,0xbd,0xfe,0x44,0x00,0x00,0x01,0x00,0x22,0x00,0x00,0x04,0x64,0x04,0x33,0x00,0x12,0x00,0x34,0x40,0x1a,0x0f,0x07,0x37,0x08,0x00,0x37,0x01,0x08,0x01,0x08,0x01,0x14,0x0a,0x06,0x39,0x0f,0x0f,0x08,0x0e,0x0a,0x39,0x0b,0x35,0x01,0x08,0x33,0x00,0x3f,0x33,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f, 0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x33,0x20,0x11,0x04,0x64,0xa4,0x6f,0x65,0xfc,0xa3,0xfe,0xd5,0x03,0x3a,0xfe,0x94,0xfd,0x01,0x77,0x01,0x24,0x66,0x5f,0xfe,0x17,0x03,0xa9,0x8a,0x8a,0xfe,0xc7,0xfe,0xb4,0x00,0xff,0xff, 0x00,0xb0,0x00,0x00,0x03,0xec,0x06,0x28,0x02,0x26,0x0c,0xf5,0x00,0x00,0x01,0x07,0x00,0x8e,0x01,0x42,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x13,0x01,0x13,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x36,0xff,0xed,0x03,0xf4,0x05,0xdc,0x02,0x26,0x0d,0xab,0x00,0x00,0x01,0x07,0x00,0xda,0x00,0xea,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1c, 0x01,0x1c,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0xb0,0xfe,0xe0,0x04,0x2f,0x04,0x33,0x00,0x0b,0x00,0x2e,0x40,0x17,0x01,0x37,0x04,0x00,0x37,0x09,0x04,0x09,0x04,0x09,0x0d,0x08,0x37,0x05,0x0a,0x06,0x35,0x08,0x39,0x01,0x05,0x33,0x03,0x00,0x2f,0x3f,0x33,0xed,0x3f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed, 0x31,0x30,0x21,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x04,0x2f,0xfe,0x8b,0x98,0xfe,0x8e,0xa3,0x02,0x38,0xa4,0xfe,0xe0,0x01,0x20,0x04,0x33,0xfc,0x57,0x03,0xa9,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x33,0x02,0x06,0x0c,0xeb,0x00,0x00,0x00,0x02,0x00,0xb0,0x00,0x00,0x03,0x9c,0x04,0x33,0x00,0x10, 0x00,0x1b,0x00,0x2f,0x40,0x18,0x03,0x12,0x0b,0x38,0x16,0x16,0x1d,0x05,0x12,0x37,0x00,0x11,0x39,0x05,0x05,0x12,0x04,0x39,0x01,0x35,0x12,0x39,0x00,0x33,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x33,0x11,0x21,0x15,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e, 0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0xb0,0x02,0x7c,0xfe,0x27,0xca,0x58,0x8e,0x64,0x35,0x38,0x67,0x92,0x59,0xbf,0xac,0x7d,0x75,0x1b,0x3b,0x5c,0x40,0x04,0x33,0x8a,0xfe,0xce,0x2b,0x51,0x73,0x47,0x4a,0x77,0x53,0x2d,0x01,0xed,0xfe,0x9d,0x50,0x5f,0x30,0x45,0x2b,0x14,0x00,0xff,0xff,0x00,0xb0,0x00,0x00, 0x03,0xa1,0x04,0x33,0x02,0x06,0x0c,0xec,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x1a,0x04,0x33,0x00,0x06,0x0d,0x6b,0x14,0x00,0x00,0x02,0x00,0x12,0xfe,0xdf,0x04,0x6c,0x04,0x33,0x00,0x0f,0x00,0x18,0x00,0x44,0x40,0x23,0x0f,0x37,0x02,0x0e,0x37,0x10,0x12,0x37,0x0c,0x18,0x07,0x0c,0x07,0x10,0x06,0x02,0x10,0x02,0x10,0x1a, 0x03,0x37,0x06,0x12,0x39,0x0c,0x35,0x01,0x04,0x0e,0x07,0x18,0x39,0x03,0x33,0x00,0x3f,0xed,0x32,0x32,0x2f,0x33,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x36,0x36,0x37,0x12,0x37,0x21,0x11,0x33,0x21,0x11, 0x21,0x06,0x06,0x07,0x06,0x06,0x07,0x04,0x6c,0x98,0xfc,0xd7,0x99,0x5d,0x3c,0x64,0x2a,0x55,0x0a,0x02,0x34,0xa0,0xfe,0xbd,0xfe,0xfd,0x07,0x2d,0x27,0x27,0x56,0x30,0xfe,0xdf,0x01,0x21,0xfe,0xdf,0x01,0xab,0x61,0xdf,0x81,0x01,0x02,0xe6,0xfc,0x57,0x03,0x1f,0x58,0xcb,0x75,0x76,0xc2,0x4f,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x27, 0x04,0x33,0x02,0x06,0x0c,0xef,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x05,0xe7,0x04,0x33,0x00,0x1d,0x00,0x17,0x40,0x0a,0x06,0x37,0x07,0x07,0x1f,0x1e,0x15,0x35,0x07,0x33,0x00,0x3f,0x3f,0x11,0x12,0x01,0x39,0x2f,0xed,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x01,0x16, 0x17,0x33,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x05,0xe7,0xc9,0xfe,0x47,0x15,0x0a,0x04,0x9c,0x04,0x0b,0x13,0xfe,0x46,0xca,0x01,0xff,0xfe,0x25,0xb9,0x01,0xa7,0x13,0x0b,0x04,0x9c,0x04,0x0a,0x15,0x01,0xa6,0xb8,0xfe,0x26,0x01,0xec,0x14,0x11,0xfd,0xef,0x02,0x11,0x10,0x15,0xfe,0x14,0x02,0x2e,0x02,0x05,0xfe,0x2f,0x15, 0x10,0x01,0xf6,0xfe,0x0a,0x10,0x15,0x01,0xd1,0xfd,0xfb,0x00,0x00,0x01,0x00,0x50,0xff,0xee,0x03,0x3d,0x04,0x45,0x00,0x2f,0x00,0x39,0x40,0x1e,0x10,0x38,0x17,0x0c,0x23,0x03,0x00,0x20,0x20,0x00,0x29,0x38,0x08,0x08,0x31,0x00,0x24,0x0b,0x3a,0x0c,0x0c,0x1b,0x03,0x3b,0x2e,0x34,0x15,0x3b,0x1b,0x36,0x00,0x3f,0xed,0x3f,0xed,0x11, 0x39,0x2f,0xed,0x39,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x37,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x50,0x88,0xa9, 0x3d,0x65,0x46,0x27,0xfe,0xd9,0x76,0x6c,0x7e,0x89,0x1e,0x38,0x50,0x33,0x8e,0x89,0x42,0x96,0x56,0x54,0x88,0x60,0x34,0x75,0x71,0x3d,0x64,0x47,0x27,0x3d,0x72,0xa2,0x65,0xca,0x2d,0x96,0x5c,0x1b,0x33,0x48,0x2d,0xc2,0x80,0x60,0x58,0x25,0x3e,0x2c,0x18,0x55,0x8d,0x22,0x20,0x26,0x46,0x61,0x3b,0x69,0x83,0x1c,0x03,0x06,0x2b,0x44, 0x59,0x34,0x4a,0x77,0x54,0x2d,0x00,0x01,0x00,0xb0,0x00,0x00,0x04,0x7a,0x04,0x33,0x00,0x18,0x00,0x1e,0x40,0x0e,0x0e,0x37,0x0c,0x0f,0x0f,0x1a,0x17,0x01,0x37,0x00,0x17,0x33,0x01,0x35,0x00,0x3f,0x3f,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x13,0x33,0x11,0x14,0x06,0x07,0x33,0x3e,0x03,0x37,0x01,0x33,0x11,0x23, 0x11,0x34,0x37,0x23,0x06,0x06,0x07,0x01,0x23,0xb0,0x99,0x04,0x04,0x03,0x03,0x09,0x11,0x19,0x12,0x02,0x35,0xb9,0x99,0x06,0x05,0x08,0x29,0x1f,0xfd,0xcc,0xae,0x04,0x33,0xfd,0x39,0x39,0x4e,0x17,0x05,0x10,0x18,0x23,0x19,0x02,0xfc,0xfb,0xcd,0x02,0xe1,0x71,0x23,0x13,0x41,0x2a,0xfd,0x09,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x7a, 0x05,0xdc,0x02,0x26,0x0d,0xa0,0x00,0x00,0x01,0x07,0x00,0xda,0x01,0x65,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1c,0x01,0x1c,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0xec,0x04,0x33,0x02,0x06,0x0c,0xf5,0x00,0x00,0x00,0x01,0x00,0x0d,0xff,0xef,0x03,0xda,0x04,0x33,0x00,0x1b,0x00,0x2b,0x40,0x16,0x03,0x37,0x1a,0x00, 0x37,0x01,0x1a,0x01,0x1a,0x01,0x1d,0x10,0x03,0x39,0x1a,0x35,0x12,0x39,0x0d,0x34,0x01,0x33,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x21,0x23,0x11,0x21,0x0e,0x03,0x07,0x0e,0x03,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x37,0x36,0x12,0x37,0x21,0x03,0xda,0xa3,0xfe, 0xe5,0x0e,0x1a,0x16,0x14,0x08,0x0f,0x26,0x45,0x6f,0x5a,0x42,0x30,0x2b,0x33,0x2c,0x38,0x27,0x1e,0x12,0x19,0x34,0x1d,0x02,0x4a,0x03,0xa9,0x66,0xa5,0x87,0x6a,0x2a,0x4e,0x92,0x70,0x44,0x0f,0x8f,0x16,0x28,0x51,0x7a,0x52,0x70,0x01,0x39,0xce,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x05,0x62,0x04,0x33,0x02,0x06,0x0c,0xf7,0x00,0x00, 0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x39,0x04,0x33,0x02,0x06,0x0c,0xf2,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x95,0x04,0x45,0x02,0x06,0x0c,0xf9,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x04,0x37,0x04,0x33,0x02,0x06,0x0d,0x78,0x00,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x03,0x92,0x04,0x33,0x02,0x06,0x0c,0xfa,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0xed,0x03,0xbb,0x04,0x45,0x02,0x06,0x0c,0xed,0x00,0x00,0xff,0xff,0x00,0x19,0x00,0x00,0x03,0x6c,0x04,0x33,0x02,0x06,0x0c,0xfe,0x00,0x00,0x00,0x01,0x00,0x36,0xff,0xed,0x03,0xf4,0x04,0x33,0x00,0x18,0x00,0x23,0x40,0x10,0x18,0x00,0x00,0x1a,0x12,0x11,0x10,0x16,0x06,0x18,0x11,0x35,0x0b,0x39,0x06,0x34, 0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39,0x01,0x2f,0x33,0x11,0x33,0x2f,0x33,0x31,0x30,0x01,0x01,0x0e,0x03,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x37,0x01,0x33,0x01,0x16,0x16,0x17,0x33,0x01,0x03,0xf4,0xfe,0x91,0x2c,0x56,0x61,0x72,0x48,0x57,0x3d,0x45,0x4c,0x1f,0x3a,0x39,0x3b,0x21,0xfe,0x63,0xb6,0x01,0x18,0x08,0x11, 0x06,0x01,0x01,0x23,0x04,0x33,0xfd,0x12,0x5a,0x82,0x54,0x28,0x17,0x98,0x26,0x0e,0x29,0x49,0x3c,0x03,0x01,0xfd,0xdc,0x0e,0x26,0x12,0x02,0x6a,0xff,0xff,0x00,0x50,0xff,0xf5,0x04,0xb1,0x04,0x3d,0x02,0x06,0x0d,0x7d,0x00,0x00,0xff,0xff,0x00,0x1e,0x00,0x00,0x03,0xe4,0x04,0x33,0x02,0x06,0x0d,0x02,0x00,0x00,0x00,0x01,0x00,0xb0, 0xfe,0xdf,0x04,0xce,0x04,0x33,0x00,0x0b,0x00,0x2a,0x40,0x15,0x02,0x37,0x0b,0x0b,0x09,0x37,0x08,0x08,0x0d,0x05,0x37,0x04,0x08,0x04,0x35,0x0a,0x06,0x39,0x03,0x33,0x01,0x00,0x2f,0x3f,0xed,0x32,0x3f,0x33,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x32,0x2f,0xed,0x31,0x30,0x01,0x23,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33, 0x04,0xce,0x99,0xfc,0x7b,0xa3,0x02,0x38,0xa4,0x9f,0xfe,0xdf,0x01,0x21,0x04,0x33,0xfc,0x57,0x03,0xa9,0xfc,0x57,0x00,0x01,0x00,0x7d,0x00,0x00,0x03,0xb0,0x04,0x33,0x00,0x15,0x00,0x2b,0x40,0x15,0x15,0x37,0x02,0x14,0x14,0x17,0x0c,0x37,0x0b,0x10,0x39,0x02,0x0b,0x05,0x05,0x01,0x14,0x0b,0x35,0x01,0x33,0x00,0x3f,0x3f,0x33,0x12, 0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x21,0x23,0x11,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x37,0x11,0x33,0x03,0xb0,0xa3,0x56,0xa7,0x60,0x47,0x72,0x4f,0x2b,0xa3,0x54,0x60,0x4b,0x99,0x55,0xa3,0x01,0xd8,0x28,0x33,0x26,0x4b,0x6f,0x49,0x01,0x8d,0xfe, 0x90,0x64,0x5b,0x28,0x26,0x01,0xe1,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x05,0xc3,0x04,0x33,0x00,0x0b,0x00,0x2e,0x40,0x17,0x07,0x37,0x06,0x0b,0x37,0x0a,0x06,0x0a,0x06,0x0a,0x0d,0x03,0x37,0x02,0x0a,0x06,0x02,0x35,0x08,0x04,0x39,0x01,0x33,0x00,0x3f,0xed,0x32,0x3f,0x33,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed, 0x10,0xed,0x31,0x30,0x21,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x05,0xc3,0xfa,0xed,0xa3,0x01,0x95,0xa3,0x01,0x95,0xa3,0x04,0x33,0xfc,0x57,0x03,0xa9,0xfc,0x57,0x03,0xa9,0x00,0x00,0x01,0x00,0xb0,0xfe,0xdf,0x06,0x61,0x04,0x33,0x00,0x0f,0x00,0x39,0x40,0x1d,0x05,0x37,0x04,0x0e,0x37,0x0b,0x0b,0x09,0x37,0x08, 0x04,0x08,0x04,0x08,0x11,0x01,0x37,0x00,0x0a,0x06,0x02,0x39,0x0f,0x33,0x0d,0x08,0x04,0x00,0x35,0x00,0x3f,0x32,0x32,0x2f,0x3f,0xed,0x32,0x32,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x32,0x2f,0xed,0x10,0xed,0x31,0x30,0x13,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x11,0x23,0x11,0x21,0xb0,0xa3,0x01, 0x95,0xa3,0x01,0x95,0xa3,0x9e,0x99,0xfa,0xe8,0x04,0x33,0xfc,0x57,0x03,0xa9,0xfc,0x57,0x03,0xa9,0xfc,0x57,0xfe,0x55,0x01,0x21,0x00,0x00,0x02,0x00,0x22,0x00,0x00,0x04,0x3b,0x04,0x33,0x00,0x10,0x00,0x19,0x00,0x33,0x40,0x1a,0x05,0x12,0x37,0x00,0x0b,0x38,0x16,0x00,0x16,0x00,0x16,0x1b,0x02,0x11,0x3a,0x05,0x05,0x12,0x02,0x39, 0x03,0x35,0x12,0x3a,0x00,0x33,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x31,0x30,0x21,0x11,0x21,0x35,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x01,0x4d,0xfe,0xd5,0x01,0xce,0xca,0x58,0x8f,0x64,0x36, 0x39,0x68,0x92,0x59,0xbf,0xac,0x75,0x7f,0x7b,0x79,0x03,0xa9,0x8a,0xfe,0x44,0x2b,0x51,0x73,0x47,0x4a,0x77,0x53,0x2d,0x01,0xf1,0xfe,0x95,0x54,0x5f,0x61,0x57,0x00,0x00,0x03,0x00,0xb0,0x00,0x00,0x04,0xf1,0x04,0x33,0x00,0x0e,0x00,0x17,0x00,0x1b,0x00,0x35,0x40,0x1b,0x09,0x38,0x14,0x18,0x37,0x19,0x14,0x19,0x14,0x19,0x1d,0x03, 0x10,0x37,0x00,0x0f,0x3a,0x03,0x03,0x1a,0x01,0x35,0x10,0x3a,0x19,0x00,0x33,0x00,0x3f,0x32,0xed,0x3f,0x33,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x33,0x11,0x33,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x01,0x23,0x11, 0x33,0xb0,0xa3,0xca,0x58,0x8f,0x64,0x36,0x39,0x68,0x92,0x59,0xbf,0xac,0x75,0x7f,0x7b,0x79,0x02,0xf2,0xa4,0xa4,0x04,0x33,0xfe,0x44,0x2b,0x51,0x73,0x47,0x4a,0x77,0x53,0x2d,0x01,0xf1,0xfe,0x95,0x54,0x5f,0x61,0x57,0xfe,0x0f,0x04,0x33,0x00,0x02,0x00,0xb0,0x00,0x00,0x03,0x9e,0x04,0x33,0x00,0x0e,0x00,0x17,0x00,0x26,0x40,0x13, 0x09,0x38,0x14,0x14,0x19,0x03,0x10,0x37,0x00,0x0f,0x3a,0x03,0x03,0x01,0x35,0x10,0x3a,0x00,0x33,0x00,0x3f,0xed,0x3f,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x33,0x11,0x33,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0xb0,0xa3,0xca,0x58,0x8f,0x64, 0x36,0x39,0x68,0x92,0x59,0xbf,0xac,0x75,0x7f,0x7b,0x79,0x04,0x33,0xfe,0x44,0x2b,0x51,0x73,0x47,0x4a,0x77,0x53,0x2d,0x01,0xf1,0xfe,0x95,0x54,0x5f,0x61,0x57,0x00,0x00,0x01,0x00,0x54,0xff,0xee,0x03,0xc6,0x04,0x45,0x00,0x1c,0x00,0x2e,0x40,0x17,0x15,0x38,0x08,0x06,0x00,0x05,0x05,0x1e,0x0d,0x00,0x06,0x39,0x07,0x07,0x10,0x02, 0x39,0x1a,0x34,0x0b,0x39,0x10,0x36,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x33,0xed,0x31,0x30,0x37,0x16,0x33,0x32,0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x27,0x54,0x82,0xba,0xb4,0xc8,0x0e,0xfe,0x08,0x01, 0xf7,0x15,0xcf,0xb1,0xaa,0x86,0x7f,0xb0,0x86,0xd7,0x96,0x50,0x50,0x92,0xcd,0x7d,0xc4,0x82,0xbf,0x48,0xb7,0xa5,0x89,0xb6,0xa9,0x40,0x9e,0x2c,0x4d,0x94,0xd6,0x89,0x7f,0xc7,0x89,0x48,0x3f,0x00,0x00,0x02,0x00,0xb0,0xff,0xed,0x06,0x88,0x04,0x45,0x00,0x1a,0x00,0x2a,0x00,0x43,0xb9,0x00,0x23,0x01,0x50,0x40,0x20,0x0a,0x11,0x0a, 0x00,0x38,0x1b,0x0a,0x1b,0x0a,0x1b,0x2c,0x10,0x0c,0x37,0x0d,0x0b,0x3a,0x10,0x10,0x28,0x1e,0x39,0x16,0x36,0x0e,0x35,0x0d,0x33,0x28,0x39,0x05,0x34,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x07,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x06,0x88,0x52,0x91,0xc9,0x77,0x74,0xc1,0x8d,0x52,0x05,0xf9,0xa3,0xa3,0xfe,0x0e,0x57,0x8c,0xc0,0x78,0x7a,0xc3,0x88,0x49,0xab,0xb7,0xb7,0x57,0x8c,0x62,0x34,0x31,0x5f,0x88,0x57, 0xb8,0xc0,0x02,0x27,0x86,0xd4,0x93,0x4d,0x4b,0x87,0xbd,0x72,0xfe,0x12,0x04,0x33,0xfe,0x3d,0x68,0xac,0x7c,0x45,0x55,0x93,0xc6,0x80,0xc8,0xdc,0x3c,0x6e,0x9b,0x5e,0x5e,0x9a,0x6d,0x3c,0xda,0x00,0x00,0x02,0x00,0x12,0x00,0x00,0x03,0x39,0x04,0x33,0x00,0x1c,0x00,0x27,0x00,0x3d,0xb9,0x00,0x22,0x01,0x50,0x40,0x1b,0x16,0x1d,0x00, 0x37,0x01,0x10,0x01,0x16,0x01,0x16,0x01,0x29,0x09,0x0a,0x10,0x03,0x3a,0x27,0x27,0x09,0x1e,0x3a,0x1c,0x35,0x01,0x09,0x33,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x33,0x10,0xed,0x31,0x30,0x21,0x23,0x11,0x23,0x22,0x0e,0x02,0x07,0x03,0x23,0x13,0x3e,0x03, 0x37,0x35,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x21,0x03,0x11,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x03,0x39,0xa4,0x9c,0x16,0x26,0x24,0x24,0x14,0x97,0xb8,0xb7,0x08,0x1b,0x23,0x2b,0x18,0x3b,0x5d,0x40,0x22,0x39,0x66,0x8f,0x56,0x01,0x5d,0xa3,0xb0,0x6d,0x77,0x20,0x3b,0x52,0x33,0x01,0xb5,0x08,0x1b,0x32,0x2a,0xfe,0xca,0x01, 0x63,0x10,0x26,0x24,0x1e,0x09,0x03,0x0c,0x32,0x49,0x5d,0x36,0x46,0x71,0x50,0x2b,0xfe,0x08,0x01,0x72,0x5e,0x58,0x2c,0x45,0x31,0x1a,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0x1a,0x04,0xf9,0x00,0x07,0x00,0x1f,0x40,0x0f,0x00,0x37,0x05,0x05,0x09,0x02,0x37,0x03,0x06,0x01,0x39,0x04,0x35,0x03,0x33,0x00,0x3f,0x3f,0xed,0xce,0x01,0x2f, 0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x33,0x03,0x1a,0xfe,0x39,0xa3,0x01,0xda,0x90,0x03,0xa9,0xfc,0x57,0x04,0x33,0xc6,0x00,0x01,0x00,0x35,0x00,0x00,0x03,0xff,0x06,0x04,0x00,0x1d,0x00,0x37,0x40,0x1c,0x1c,0x04,0x84,0x09,0x05,0x05,0x01,0x07,0x13,0x00,0x84,0x01,0x13,0x13,0x08,0x16,0x95,0x0f, 0x01,0x03,0x07,0x95,0x1c,0x08,0x0f,0x01,0x05,0x15,0x00,0x3f,0x33,0x3f,0x33,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0x01,0x2f,0xfd,0xc4,0x2f,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x21,0x03, 0xff,0xa4,0xfe,0x2c,0xa4,0xae,0xae,0x40,0x81,0xc2,0x81,0x48,0x7e,0x23,0x2e,0x7f,0x49,0x53,0x7f,0x56,0x2b,0x02,0x78,0x03,0x75,0xfc,0x8b,0x03,0x75,0x8b,0x15,0x5e,0xb3,0x8a,0x54,0x09,0x09,0x94,0x0e,0x0d,0x37,0x61,0x85,0x4f,0x0d,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x04,0x01,0x06,0x04,0x00,0x1d,0x00,0x33,0x40,0x1a,0x0b,0x0f, 0x84,0x14,0x10,0x0d,0x10,0x0d,0x01,0x12,0x00,0x84,0x01,0x05,0x95,0x1a,0x01,0x0e,0x12,0x95,0x0b,0x13,0x0f,0x01,0x10,0x15,0x00,0x3f,0x33,0x3f,0x33,0xed,0x32,0x3f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11, 0x23,0x35,0x33,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x04,0x01,0xa2,0x17,0x56,0x2c,0x53,0x79,0x4e,0x25,0xf1,0xf1,0xa4,0xae,0xae,0x3a,0x79,0xbc,0x81,0x3e,0x96,0x5a,0x05,0x6e,0x04,0x07,0x37,0x61,0x85,0x4f,0x0d,0x8b,0xfc,0x8b,0x03,0x75,0x8b,0x15,0x5e,0xb3,0x8a,0x54,0x0b,0x0d,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x05,0x19, 0x06,0x02,0x00,0x2c,0x00,0x59,0x40,0x2f,0x11,0x28,0x84,0x29,0x00,0x29,0x20,0x24,0x84,0x12,0x0a,0x25,0x29,0x25,0x22,0x22,0x25,0x29,0x03,0x1a,0x2b,0x1a,0x27,0x23,0x2b,0x95,0x2c,0x0a,0x1b,0x0a,0x1b,0x06,0x20,0x11,0x2c,0x0f,0x25,0x29,0x15,0x1d,0x95,0x18,0x01,0x0d,0x95,0x06,0x00,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x3f,0x33, 0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x32,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc4,0x33,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x13,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x21,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x15,0x33,0x15, 0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0xe3,0x2f,0x5e,0x8d,0x5f,0x35,0x5b,0x1a,0x1e,0x53,0x30,0x6d,0x71,0x01,0xd5,0x30,0x57,0x78,0x47,0x4b,0x2c,0x30,0x3d,0xac,0xf0,0xf0,0xa4,0xfe,0x2b,0xa4,0xae,0x04,0x00,0x15,0x5e,0xa9,0x80,0x4a,0x09,0x09,0x94,0x0e,0x0d,0xb0,0x9e,0x0d,0xa6,0x4e,0x80,0x5b,0x33,0x12,0x94,0x1b, 0xd9,0x9e,0x8b,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x03,0x75,0x8b,0x00,0x01,0x00,0x35,0x00,0x00,0x06,0x78,0x06,0x04,0x00,0x33,0x00,0x62,0x40,0x36,0x1e,0x08,0x84,0x09,0x0d,0x09,0x32,0x04,0x84,0x1f,0x17,0x05,0x09,0x05,0x09,0x05,0x01,0x0b,0x29,0x00,0x84,0x01,0x2c,0x95,0x25,0x01,0xb0,0x29,0xc0,0x29,0xe0,0x29,0x03,0x17,0x29,0x17, 0x29,0x0c,0x1a,0x95,0x13,0x00,0x07,0x03,0x0b,0x95,0x32,0x1e,0x0c,0x0f,0x05,0x01,0x09,0x15,0x00,0x3f,0x33,0x33,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x3f,0xed,0x01,0x2f,0xfd,0xc4,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc4,0x33,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x21, 0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x21,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x21,0x06,0x78,0xa4,0xfe,0x2c,0xa4,0xfe,0x2b,0xa4,0xae,0xae,0x2f,0x5e,0x8d,0x5f,0x35,0x5b,0x1a,0x1e, 0x53,0x30,0x6d,0x71,0x01,0xd5,0x40,0x81,0xc2,0x81,0x48,0x7e,0x23,0x2e,0x7f,0x49,0x53,0x7f,0x56,0x2b,0x02,0x78,0x03,0x75,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x03,0x75,0x8b,0x15,0x5e,0xa9,0x80,0x4a,0x09,0x09,0x94,0x0e,0x0d,0xb0,0x9e,0x0d,0x15,0x5e,0xb3,0x8a,0x54,0x09,0x09,0x94,0x0e,0x0d,0x37,0x61,0x85,0x4f,0x0d,0x00,0x00,0x01, 0x00,0x35,0x00,0x00,0x06,0x78,0x06,0x04,0x00,0x33,0x00,0x58,0x40,0x2f,0x29,0x13,0x84,0x14,0x18,0x14,0x0b,0x0f,0x84,0x2a,0x22,0x10,0x14,0x10,0x0d,0x0d,0x10,0x14,0x03,0x01,0x16,0x00,0x84,0x01,0x05,0x95,0x30,0x01,0x22,0x22,0x17,0x25,0x95,0x1e,0x00,0x12,0x0e,0x16,0x95,0x29,0x0b,0x17,0x0f,0x10,0x01,0x14,0x15,0x00,0x3f,0x33, 0x33,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0xed,0x12,0x39,0x2f,0x3f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc4,0x33,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x3e,0x02, 0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x21,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x06,0x78,0xa2,0x17,0x56,0x2c,0x53,0x79,0x4e,0x25,0xf1,0xf1,0xa4,0xfe,0x2d,0xa4,0xae,0xae,0x2f,0x5e,0x8d,0x5f,0x35,0x5b,0x1a,0x1e,0x53,0x30,0x6d,0x71,0x01,0xd3,0x3a,0x79,0xbc,0x81,0x3e,0x96,0x5a,0x05,0x6e,0x04,0x07, 0x37,0x61,0x85,0x4f,0x0d,0x8b,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x03,0x75,0x8b,0x15,0x5e,0xa9,0x80,0x4a,0x09,0x09,0x94,0x0e,0x0d,0xb0,0x9e,0x0d,0x15,0x5e,0xb3,0x8a,0x54,0x0b,0x0d,0x00,0x00,0x03,0x00,0x57,0xff,0xef,0x05,0x31,0x04,0x45,0x00,0x43,0x00,0x57,0x00,0x67,0x00,0x6d,0x40,0x3e,0x38,0x05,0x0f,0x33,0x37,0x2c,0x29,0x49, 0x2c,0x53,0x24,0x4e,0x12,0x03,0x17,0x21,0x37,0x58,0x60,0x37,0x17,0x40,0x2c,0x58,0x17,0x17,0x58,0x2c,0x40,0x04,0x69,0x53,0x37,0x0f,0x12,0x4e,0x49,0x05,0x04,0x00,0x5d,0x3b,0x1c,0x2f,0x2f,0x44,0x65,0x24,0x29,0x38,0x04,0x3d,0x1c,0x36,0x44,0x39,0x0a,0x34,0x3d,0x39,0x00,0x34,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x17,0x39,0x12, 0x39,0x2f,0x10,0xed,0x11,0x17,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x17,0x39,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x05,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07, 0x1e,0x03,0x17,0x36,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x25,0x32,0x3e,0x02,0x37,0x2e,0x03,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x13,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x14,0x1e,0x02,0x17,0x36,0x36,0x04,0xb2,0x2f,0x4a,0x41,0x3b,0x1f,0x23,0x56,0x6a, 0x7e,0x4b,0x5c,0x97,0x6c,0x3c,0x8b,0x85,0x19,0x30,0x26,0x17,0x30,0x53,0x71,0x41,0x40,0x6c,0x4d,0x2b,0x65,0x65,0x34,0x56,0x4a,0x3f,0x1e,0x33,0x35,0x08,0x07,0xa1,0x08,0x06,0x14,0x2a,0x40,0x2c,0x1d,0x2d,0x2d,0x33,0x21,0x18,0x34,0x1b,0x1e,0x41,0xfd,0x20,0x3a,0x63,0x52,0x44,0x1c,0x2a,0x4f,0x56,0x63,0x3d,0x2d,0x4e,0x39,0x20, 0x26,0x42,0x59,0xde,0x19,0x28,0x31,0x18,0x44,0x51,0x01,0x14,0x21,0x2a,0x17,0x5a,0x50,0x11,0x12,0x23,0x33,0x20,0x1b,0x31,0x26,0x16,0x2a,0x51,0x76,0x4b,0x73,0xa1,0x34,0x10,0x2b,0x36,0x43,0x28,0x3c,0x5b,0x3f,0x20,0x20,0x3c,0x54,0x34,0x5a,0x77,0x2a,0x14,0x3b,0x48,0x53,0x2b,0x55,0xcb,0x70,0x1d,0x32,0x19,0x19,0x2c,0x1e,0x40, 0x86,0x83,0x7e,0x37,0x20,0x2b,0x1a,0x0b,0x0c,0x09,0x85,0x0e,0x0b,0x8b,0x10,0x1d,0x27,0x18,0x3e,0x63,0x4d,0x3a,0x16,0x11,0x29,0x39,0x4a,0x32,0x2f,0x46,0x2e,0x18,0x02,0xd7,0x1f,0x2e,0x1e,0x0e,0x45,0x3b,0x1a,0x2f,0x28,0x20,0x0b,0x1c,0x4e,0x00,0xff,0xff,0x00,0x58,0xff,0xed,0x03,0xbb,0x06,0x2c,0x02,0x26,0x0c,0xed,0x00,0x00, 0x01,0x07,0x00,0xd7,0x00,0xf1,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x1e,0x01,0x1e,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x58,0xff,0xed,0x04,0x20,0x06,0x2c,0x02,0x26,0x0c,0xf1,0x00,0x00,0x01,0x07,0x00,0xd7,0x01,0x1e,0x00,0x1e,0x00,0x0a,0xb4,0x01,0x0f,0x23,0x01,0x23,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x68,0xfe,0x85,0x03,0x08, 0x04,0x45,0x02,0x26,0x0c,0xfd,0x00,0x00,0x00,0x06,0x01,0x9c,0x25,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x2f,0x05,0x9a,0x02,0x06,0x00,0x25,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0x29,0x05,0x9a,0x02,0x06,0x00,0x33,0x00,0x00,0xff,0xff,0x00,0x52,0x00,0x00,0x03,0xbf,0x05,0x9a,0x01,0x0f,0x00,0x33,0x04,0x7b,0x05,0x9a, 0xc0,0x00,0x00,0x09,0xb3,0x01,0x00,0x03,0x12,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x3e,0x05,0x9a,0x02,0x06,0x00,0x27,0x00,0x00,0xff,0xff,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x02,0x06,0x00,0x37,0x00,0x00,0xff,0xff,0x00,0x27,0x00,0x00,0x04,0x0a,0x05,0x9a,0x01,0x47,0x00,0x37,0xff,0xfe,0x05,0x9a, 0x40,0x00,0xc0,0x00,0x00,0x07,0xb2,0x00,0x07,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0xec,0x05,0xb2,0x02,0x06,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x02,0x06,0x00,0x2e,0x00,0x00,0xff,0xff,0x00,0x02,0x00,0x00,0x03,0xe8,0x05,0x9a,0x01,0x0f,0x00,0x2e,0x04,0xa4,0x05,0x9a, 0xc0,0x00,0x00,0x07,0xb2,0x00,0x08,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x14,0xff,0xe8,0x02,0x2b,0x05,0x9a,0x02,0x06,0x00,0x2d,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x02,0x06,0x00,0x26,0x00,0x00,0xff,0xff,0x00,0x68,0xff,0xe8,0x04,0x96,0x05,0xb2,0x01,0x0f,0x00,0x26,0x04,0xf4,0x05,0x9a,0xc0,0x00, 0x00,0x07,0xb2,0x00,0x08,0x13,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x21,0x00,0x00,0x04,0x64,0x05,0x9a,0x02,0x06,0x00,0x3d,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0x94,0x05,0x9a,0x02,0x06,0x00,0x29,0x00,0x00,0xff,0xff,0x00,0x54,0x00,0x00,0x03,0x2c,0x05,0x9a,0x01,0x0f,0x00,0x29,0x03,0xe8,0x05,0x9a,0xc0,0x00,0x00,0x07, 0xb2,0x00,0x08,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x06,0x72,0x05,0x9a,0x02,0x06,0x00,0x30,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x05,0x9a,0x02,0x06,0x00,0x31,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x06,0x00,0x2f,0x00,0x00,0xff,0xff,0x00,0x79,0xff,0xe8,0x03,0xde, 0x05,0xb2,0x02,0x06,0x00,0x36,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xc0,0x05,0x9a,0x02,0x06,0x00,0x35,0x00,0x00,0xff,0xff,0x00,0x09,0x00,0x00,0x04,0x0d,0x05,0x9a,0x01,0x0f,0x00,0x35,0x04,0xc9,0x05,0x9a,0xc0,0x00,0x00,0x09,0xb3,0x01,0x00,0x0b,0x12,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0xe6, 0x05,0x9a,0x01,0x0f,0x00,0x39,0x04,0xf8,0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x03,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0xe6,0x05,0x9a,0x02,0x06,0x00,0x39,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x04,0xf2,0x05,0x9a,0x02,0x06,0x00,0x2b,0x00,0x00,0xff,0xff,0x00,0x91,0xff,0xe8,0x05,0x1f,0x05,0xb2, 0x01,0x0f,0x00,0x2a,0x05,0x7d,0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x08,0x13,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0xb0,0x00,0x00,0x02,0xc7,0x05,0xb2,0x01,0x0f,0x00,0x2d,0x02,0xdb,0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x0b,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x60,0x05,0x9a,0x02,0x06,0x00,0x3a, 0x00,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x02,0x06,0x00,0x3b,0x00,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x04,0x60,0x05,0x9a,0x02,0x06,0x00,0x3c,0x00,0x00,0xff,0xff,0x00,0x67,0x00,0x00,0x03,0xda,0x05,0x9a,0x01,0x0f,0x00,0x25,0x04,0x96,0x05,0x9a,0xc0,0x00,0x00,0x0b,0xb4,0x02,0x01,0x00,0x01,0x12,0x00,0x3f, 0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0x9a,0x02,0x06,0x00,0x24,0x00,0x00,0xff,0xff,0x00,0x17,0x00,0x00,0x05,0x13,0x05,0x9a,0x01,0x0f,0x00,0x24,0x05,0x29,0x05,0x9a,0xc0,0x00,0x00,0x09,0xb3,0x01,0x00,0x06,0x12,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xb4,0x05,0x9a,0x02,0x06, 0x00,0x28,0x00,0x00,0xff,0xff,0x00,0x58,0x00,0x00,0x03,0x50,0x05,0x9a,0x01,0x0f,0x00,0x28,0x04,0x0c,0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x03,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x01,0x64,0x05,0x9a,0x02,0x06,0x00,0x2c,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x02,0x06,0x00,0x32, 0x00,0x00,0xff,0xff,0x00,0xaa,0xff,0xe8,0x04,0xd5,0x05,0x9a,0x02,0x06,0x00,0x38,0x00,0x00,0xff,0xff,0x00,0xaa,0x00,0x00,0x04,0xd5,0x05,0xb2,0x01,0x0f,0x00,0x38,0x05,0x7f,0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x05,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x20,0x00,0x00,0x03,0x08,0x05,0x9a,0x01,0x0f,0x00,0x2f,0x03,0xc4, 0x05,0x9a,0xc0,0x00,0x00,0x07,0xb2,0x00,0x03,0x12,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x5e,0x00,0x00,0x04,0xe0,0x05,0x9a,0x01,0x0f,0x00,0x27,0x05,0x9c,0x05,0x9a,0xc0,0x00,0x00,0x09,0xb3,0x01,0x00,0x01,0x12,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x70,0xff,0xea,0x01,0x50,0x00,0xcb,0x02,0x06,0x00,0x11,0x00,0x00,0xff,0xff, 0x00,0x27,0xfe,0xf8,0x01,0x3c,0x00,0xe4,0x02,0x06,0x00,0x0f,0x00,0x00,0xff,0xff,0x00,0x70,0xff,0xea,0x03,0x0c,0x00,0xcb,0x00,0x26,0x00,0x11,0x00,0x00,0x00,0x07,0x00,0x11,0x01,0xbc,0x00,0x00,0xff,0xff,0x00,0x70,0xfe,0xf8,0x02,0xf8,0x00,0xe4,0x00,0x26,0x00,0x11,0x00,0x00,0x00,0x07,0x00,0x0f,0x01,0xbc,0x00,0x00,0xff,0xff, 0x00,0x27,0xfe,0xf8,0x01,0x52,0x04,0x16,0x02,0x06,0x00,0x1e,0x00,0x00,0xff,0xff,0x00,0x70,0xff,0xea,0x01,0x50,0x04,0x16,0x02,0x06,0x00,0x1d,0x00,0x00,0xff,0xff,0x00,0x90,0xff,0xea,0x04,0x83,0x02,0x7b,0x00,0x26,0x00,0x10,0x00,0x00,0x00,0x07,0x00,0x11,0x03,0x33,0x00,0x00,0xff,0xff,0x00,0x90,0x01,0xc8,0x02,0xb2,0x03,0xf4, 0x02,0x27,0x00,0x10,0x00,0x00,0x01,0x79,0x00,0x06,0x00,0x10,0x00,0xce,0x00,0x01,0x00,0x30,0x00,0x00,0x01,0xf0,0x05,0x9a,0x00,0x0b,0x00,0x61,0x40,0x40,0x02,0x0a,0x92,0x0b,0x03,0x03,0x07,0x92,0x40,0x06,0x01,0x04,0x0e,0x03,0x07,0x08,0x42,0x0a,0x07,0x40,0x03,0x06,0x0d,0x06,0x4d,0x03,0x06,0x0c,0x06,0x4d,0x03,0x06,0x0b,0x06, 0x4d,0x03,0x7e,0x08,0x08,0x04,0x0d,0x06,0x4d,0x08,0x02,0x0c,0x06,0x4d,0x08,0x02,0x0b,0x06,0x4d,0x08,0x40,0x0d,0x01,0x4d,0x0c,0x0d,0x08,0x7e,0xff,0x30,0x2b,0x01,0x2b,0x2b,0x2b,0x2b,0x10,0xe1,0x2b,0x2b,0x2b,0x1a,0x18,0xcd,0x32,0x2b,0x01,0x10,0xe1,0x32,0x00,0x18,0x2f,0x1a,0xed,0x32,0x3f,0xed,0x32,0x31,0x30,0x01,0x15,0x23, 0x11,0x33,0x15,0x21,0x35,0x33,0x11,0x23,0x35,0x01,0xf0,0x8c,0x8c,0xfe,0x40,0x8c,0x8c,0x05,0x9a,0x90,0xfb,0x86,0x90,0x90,0x04,0x7a,0x90,0x00,0x00,0x02,0x00,0x5e,0xfe,0x7c,0x05,0xcc,0x05,0xb2,0x00,0x28,0x00,0x38,0x00,0x96,0x40,0x29,0x78,0x12,0x01,0x14,0x00,0x29,0x91,0x0b,0x04,0x31,0x91,0x00,0x19,0xee,0x24,0x1e,0x1e,0x75, 0x14,0x01,0x14,0x00,0x07,0x0f,0x06,0x0d,0x06,0x4d,0x0f,0x06,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x7d,0x35,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x35,0xb8,0xff,0xea,0xb3,0x0c,0x06,0x4d,0x35,0xb8,0xff,0xea,0x40,0x2f,0x0b,0x06,0x4d,0x20,0x35,0x30,0x35,0x02,0x35,0x35,0x3a,0x2d,0x06,0x0d,0x06,0x4d,0x2d,0x06,0x0c,0x06, 0x4d,0x2d,0x06,0x0b,0x06,0x4d,0x2d,0x7d,0x07,0x10,0x0d,0x06,0x4d,0x07,0x10,0x0c,0x06,0x4d,0x07,0x10,0x0b,0x06,0x4d,0x07,0x2f,0x3a,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe1,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x5d,0x2b,0x2b,0x2b,0xf1,0x2b,0x2b,0x2b,0x11,0x39,0x39,0x5d,0xc2,0x2f,0x00,0x2f,0xed,0x2f,0xed,0x3f,0xed,0x12,0x39,0x31,0x30, 0x01,0x5d,0x05,0x22,0x2e,0x02,0x27,0x26,0x11,0x10,0x37,0x36,0x21,0x20,0x17,0x16,0x11,0x14,0x0e,0x02,0x07,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x03,0x22,0x07,0x06,0x11,0x10,0x17,0x16,0x33,0x32,0x37,0x36,0x11,0x10,0x27,0x26,0x02,0xf4,0x40,0x84,0x7c,0x71,0x2e,0xb7,0xba,0xbc,0x01,0x46,0x01, 0x24,0xb6,0xb6,0x3d,0x7c,0xbc,0x80,0x34,0x5b,0x5b,0x62,0x3b,0x10,0x26,0x27,0x24,0x0f,0x10,0x28,0x29,0x28,0x11,0x60,0x99,0x85,0x7c,0x2e,0xe2,0x8d,0x8d,0x89,0x8a,0xdd,0xec,0x88,0x88,0x84,0x84,0x18,0x19,0x33,0x4b,0x32,0xc8,0x01,0x43,0x01,0x5b,0xcd,0xce,0xc8,0xc8,0xfe,0xbd,0x88,0xf1,0xc2,0x87,0x1d,0x38,0x56,0x3b,0x1e,0x03, 0x07,0x09,0x06,0xa2,0x05,0x07,0x05,0x03,0x39,0x63,0x84,0x05,0x7e,0xa3,0xa3,0xfe,0xf7,0xfe,0xf8,0xa3,0xa1,0x9a,0x9a,0x01,0x15,0x01,0x1d,0x9a,0x9b,0x00,0x00,0x03,0x00,0x77,0xff,0xe7,0x05,0x91,0x05,0xb2,0x00,0x29,0x00,0x37,0x00,0x46,0x00,0x69,0x40,0x3c,0x02,0x38,0x3b,0x0b,0x04,0x12,0x04,0x24,0x27,0x1f,0x1c,0x36,0x24,0x05, 0x12,0x01,0x45,0x95,0x04,0x13,0x2f,0x96,0x12,0x04,0x27,0x02,0x25,0x09,0x1f,0x38,0x24,0x40,0x0b,0x36,0x3b,0x1c,0x04,0x17,0x0d,0x25,0xef,0x24,0x17,0x84,0x2a,0x34,0x84,0x0d,0x0d,0x2a,0x24,0x03,0x09,0x01,0x00,0x00,0x48,0x40,0x83,0x09,0x2f,0xe1,0x12,0x39,0x2f,0x33,0x12,0x17,0x39,0x2f,0xe1,0x2f,0xe1,0x2f,0xe1,0x11,0x12,0x17, 0x39,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x39,0x00,0x3f,0xed,0x3f,0xed,0x2f,0x11,0x17,0x39,0x2f,0x11,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x27,0x06,0x21,0x22,0x2e,0x02,0x35,0x34,0x25,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x16,0x16,0x17,0x3e,0x03,0x37,0x33,0x02,0x07,0x16,0x16,0x01,0x34,0x2e, 0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x17,0x36,0x13,0x26,0x26,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x05,0x91,0xe5,0x9a,0xc2,0xfe,0xed,0x67,0xa7,0x77,0x41,0x01,0x47,0x9b,0x38,0x65,0x8a,0x52,0x4d,0x7e,0x5a,0x31,0x21,0x4c,0x7c,0x5b,0x67,0xbb,0x55,0x17,0x29,0x20,0x12,0x01,0x97,0x01,0xab,0x14,0x87,0xfe,0x34,0x1c,0x30, 0x41,0x25,0x32,0x50,0x39,0x1e,0x8d,0xfe,0x62,0x46,0xcc,0x87,0x45,0x60,0x3c,0x1b,0x2c,0x4d,0x68,0x3d,0xdc,0x9e,0xb7,0x39,0x66,0x8e,0x56,0xfd,0xa7,0xc7,0x8b,0x49,0x7c,0x5a,0x33,0x2d,0x50,0x6e,0x40,0x42,0x6b,0x5f,0x56,0x2d,0x6d,0xbe,0x54,0x21,0x5c,0x67,0x6a,0x2f,0xfe,0xf2,0xd8,0x14,0x87,0x04,0x04,0x27,0x43,0x30,0x1c,0x1e, 0x37,0x4c,0x2e,0x6d,0x9d,0x7a,0xfd,0x30,0x48,0xd3,0x8f,0x23,0x45,0x4b,0x54,0x32,0x3a,0x5e,0x42,0x24,0x00,0x02,0x00,0xb4,0xff,0xee,0x01,0x91,0x05,0x9a,0x00,0x03,0x00,0x17,0x00,0x1e,0x40,0x0f,0x03,0x03,0x02,0x13,0xb0,0x09,0x13,0x01,0x02,0x00,0x7d,0x03,0x04,0xaf,0x0e,0x2f,0xe1,0xd4,0xe1,0x39,0x39,0x00,0x3f,0xfd,0xc6,0x3f, 0x31,0x30,0x01,0x03,0x23,0x03,0x13,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x01,0x77,0x14,0x72,0x14,0xb4,0x11,0x1e,0x28,0x17,0x17,0x29,0x1e,0x11,0x12,0x1e,0x28,0x17,0x16,0x28,0x1e,0x12,0x05,0x9a,0xfb,0xf9,0x04,0x07,0xfa,0xc2,0x16,0x28,0x1e,0x12,0x11,0x1e,0x28,0x17,0x17,0x28,0x1e,0x12, 0x12,0x1e,0x29,0x00,0x00,0x01,0x00,0x5c,0xfe,0xed,0x01,0x4e,0x00,0xcf,0x00,0x14,0x00,0x17,0x40,0x0a,0x14,0x0c,0xb2,0x15,0x03,0x0f,0x00,0x0f,0xaf,0x09,0x2f,0xe1,0xc6,0x12,0x39,0x00,0x10,0xf4,0xc4,0x31,0x30,0x17,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x5c,0x37,0x4c, 0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0xd8,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x02,0x00,0x5e,0xfe,0xed,0x01,0x52,0x04,0x17,0x00,0x13,0x00,0x28,0x00,0x22,0x40,0x11,0x05,0xb0,0x0f,0x10,0x28,0x20,0xb2,0x29,0x00,0xaf,0x0a,0x17,0x23,0x14, 0x23,0xaf,0x1d,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xe1,0x00,0x10,0xf4,0xc4,0x3f,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x03,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x01,0x52,0x12,0x1e,0x29,0x18,0x17,0x28,0x1e,0x11, 0x11,0x1e,0x28,0x17,0x16,0x29,0x20,0x12,0xf4,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x03,0xa8,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x28,0x1e,0x12,0x11,0x1e,0x29,0xfb,0x69,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x02,0x00,0x83, 0xff,0xee,0x03,0x31,0x05,0xb2,0x00,0x20,0x00,0x34,0x00,0x32,0x40,0x0b,0x19,0x17,0x95,0x1c,0x04,0x09,0x30,0xb0,0x26,0x13,0x08,0xb8,0x01,0x03,0x40,0x0c,0x09,0x21,0xaf,0x2b,0x2b,0x19,0x00,0x84,0x12,0x12,0x36,0x19,0x2f,0x12,0x39,0x2f,0xe1,0x11,0x39,0x2f,0xe1,0xd4,0xe1,0x00,0x3f,0xfd,0xc6,0x3f,0xfd,0xc6,0x31,0x30,0x01,0x14, 0x07,0x0e,0x03,0x15,0x15,0x23,0x35,0x34,0x3e,0x02,0x37,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x03,0x31,0xcf,0x31,0x44,0x2a,0x12,0x70,0x0f,0x25,0x3d,0x2d,0x57,0x59,0x21,0x3d,0x55,0x34,0xa9,0x7c,0x99,0xa5, 0x53,0x88,0x60,0x35,0xfe,0xc1,0x11,0x1e,0x28,0x18,0x17,0x29,0x1e,0x11,0x12,0x1e,0x28,0x17,0x17,0x28,0x1e,0x12,0x04,0x5a,0xce,0xaf,0x2a,0x41,0x39,0x3a,0x22,0x4a,0x4e,0x31,0x52,0x4a,0x48,0x29,0x4e,0x8f,0x50,0x31,0x51,0x39,0x20,0x85,0xb0,0x60,0x32,0x5a,0x7f,0xfb,0xb5,0x16,0x28,0x1e,0x12,0x11,0x1e,0x28,0x17,0x17,0x28,0x1e, 0x12,0x12,0x1e,0x28,0x00,0x02,0x00,0x6f,0x03,0xd0,0x02,0x9c,0x05,0xb2,0x00,0x14,0x00,0x29,0x00,0x32,0x40,0x18,0x21,0x0c,0x29,0x14,0x04,0x18,0x1e,0x24,0x03,0x09,0x0f,0x15,0x15,0x1e,0xaf,0x24,0x24,0x2b,0x11,0x00,0x00,0x09,0xaf,0x0f,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x00, 0x3f,0x33,0xc4,0x32,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x05,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x01,0x61,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x01,0x6b, 0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x05,0x77,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x02,0x00,0x68,0x03,0xd0,0x02,0x95,0x05,0xb2, 0x00,0x14,0x00,0x29,0x00,0x2c,0x40,0x15,0x14,0x29,0x0c,0x21,0x04,0x03,0x0f,0x09,0x18,0x24,0x1e,0x00,0x0f,0xaf,0x09,0x09,0x2b,0x15,0x24,0xaf,0x1e,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xe1,0xc6,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x3f,0x33,0xc4,0x32,0x31,0x30,0x01,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x14,0x0e,0x02,0x07,0x25,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x01,0xa3,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0xfe,0x95,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x04,0x0b,0x2d,0x5f,0x2a,0x18, 0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x01,0x00,0x6f,0x03,0xd0,0x01,0x61,0x05,0xb2,0x00,0x14,0x00,0x19,0x40,0x0b,0x0c,0x14,0x04,0x03,0x09,0x0f,0x00,0x00,0x09,0xaf,0x0f,0x2f,0xf1,0xc2, 0x2f,0x11,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x01,0x61,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x05,0x77,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44, 0x1e,0x00,0x00,0x01,0x00,0x74,0x03,0xd0,0x01,0x66,0x05,0xb2,0x00,0x14,0x00,0x15,0x40,0x09,0x14,0x0c,0x04,0x03,0x0f,0x00,0x0f,0xaf,0x09,0x2f,0xe1,0xc6,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x74,0x37,0x4c,0x14,0x1a,0x28,0x1a, 0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x04,0x0b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x01,0x00,0x62,0xfe,0xed,0x01,0x4e,0x00,0xcf,0x00,0x16,0x00,0x17,0x40,0x0a,0x16,0x0e,0xb2,0x17,0x05,0x11,0x00,0x11,0xaf,0x0b,0x2f,0xe1,0xc6,0x12,0x39,0x00,0x10,0xf4,0xc4,0x31, 0x30,0x17,0x3e,0x03,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x62,0x1b,0x31,0x24,0x15,0x19,0x1d,0x28,0x1a,0x2f,0x30,0x3b,0x45,0x20,0x35,0x46,0x27,0xde,0x16,0x31,0x31,0x2f,0x15,0x19,0x13,0x0d,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x02,0x00,0x68, 0xfe,0xed,0x02,0x95,0x00,0xcf,0x00,0x14,0x00,0x29,0x00,0x2a,0x40,0x14,0x14,0x0c,0x29,0x21,0xb2,0x2a,0x18,0x24,0x1e,0x03,0x0f,0xaf,0x09,0x09,0x09,0x2b,0x15,0x24,0xaf,0x1e,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0x2f,0xe1,0x39,0x11,0x12,0x39,0x00,0x10,0xf4,0xc4,0x33,0x32,0x31,0x30,0x05,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x25,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x01,0xa3,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0xfe,0x95,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0xd8,0x2d, 0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0xff,0xff,0x00,0x60,0xff,0xe8,0x05,0x76,0x05,0xf6,0x00,0x26,0x00,0x47,0x00,0x00,0x01,0x07,0x0e,0x10,0x03,0x70,0x06,0x63,0x00,0x14,0x40,0x0b, 0x02,0x27,0x9d,0x27,0x27,0x10,0x10,0x25,0x02,0x2a,0x01,0x00,0x3f,0x35,0x01,0x2b,0x11,0x35,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0xa4,0x02,0x26,0x00,0x2f,0x00,0x00,0x01,0x07,0x0e,0x10,0x01,0x54,0x06,0x11,0x00,0x16,0xb1,0x01,0x15,0xb8,0xff,0xb6,0xb7,0x15,0x15,0x05,0x05,0x25,0x01,0x12,0x04,0x00,0x3f,0x35,0x01,0x2b, 0x11,0x35,0xff,0xff,0x00,0xa6,0x00,0x00,0x02,0x8b,0x05,0xf6,0x00,0x26,0x00,0x4f,0x00,0x00,0x01,0x07,0x0e,0x10,0x00,0x85,0x06,0x63,0x00,0x14,0x40,0x0b,0x01,0x0d,0x78,0x0d,0x0d,0x03,0x03,0x25,0x01,0x10,0x01,0x00,0x3f,0x35,0x01,0x2b,0x11,0x35,0xff,0xff,0xff,0xe4,0x00,0x00,0x04,0x4a,0x05,0xb2,0x00,0x26,0x00,0x51,0x52,0x00, 0x01,0x07,0x0d,0xfc,0xff,0x70,0x00,0x00,0x00,0x16,0xb1,0x01,0x1f,0xb8,0xff,0x62,0xb7,0x1f,0x1f,0x0a,0x0a,0x25,0x01,0x1f,0x04,0x00,0x3f,0x35,0x01,0x2b,0x11,0x35,0xff,0xff,0x00,0x5e,0xfe,0x05,0x04,0xec,0x05,0xb2,0x02,0x26,0x00,0x2a,0x00,0x00,0x00,0x07,0x0e,0x10,0x01,0x65,0x00,0x00,0xff,0xff,0x00,0x60,0xfe,0x1e,0x04,0x10, 0x06,0x3c,0x02,0x26,0x00,0x4a,0x00,0x00,0x01,0x0f,0x0e,0x10,0x03,0xe5,0x04,0x41,0xc0,0x00,0x00,0x15,0x40,0x0c,0x02,0x32,0x11,0x26,0x02,0x35,0x0b,0x35,0x2f,0x10,0x18,0x25,0x01,0x2b,0x11,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0x00,0xbc,0xfe,0x05,0x04,0xa2,0x05,0x9a,0x02,0x26,0x00,0x2e,0x00,0x00,0x00,0x07,0x0e,0x10,0x00,0xd6, 0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x05,0x03,0xf8,0x05,0xec,0x02,0x26,0x00,0x4e,0x00,0x00,0x00,0x07,0x0e,0x10,0x00,0x87,0x00,0x00,0xff,0xff,0x00,0xbc,0xfe,0x05,0x05,0x40,0x05,0x9a,0x02,0x26,0x00,0x31,0x00,0x00,0x00,0x07,0x0e,0x10,0x01,0x45,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x05,0x03,0xf8,0x04,0x18,0x02,0x26,0x00,0x51, 0x00,0x00,0x00,0x07,0x0e,0x10,0x00,0xc5,0x00,0x00,0xff,0xff,0x00,0xbc,0xfe,0x05,0x04,0xc0,0x05,0x9a,0x02,0x26,0x00,0x35,0x00,0x00,0x00,0x07,0x0e,0x10,0x00,0xf9,0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x05,0x02,0xbc,0x04,0x12,0x02,0x26,0x00,0x55,0x00,0x00,0x00,0x06,0x0e,0x10,0xed,0x00,0xff,0xff,0x00,0x2b,0xff,0xea,0x03,0x7f, 0x05,0xf6,0x00,0x26,0x00,0x57,0x00,0x00,0x01,0x07,0x0e,0x10,0x01,0x79,0x06,0x63,0x00,0x16,0xb1,0x01,0x1e,0xb8,0x01,0x37,0xb7,0x1e,0x1e,0x0a,0x0a,0x25,0x01,0x21,0x01,0x00,0x3f,0x35,0x01,0x2b,0x11,0x35,0xff,0xff,0x00,0x79,0xfe,0x05,0x03,0xde,0x05,0xb2,0x02,0x26,0x00,0x36,0x00,0x00,0x00,0x06,0x0e,0x10,0x7f,0x00,0xff,0xff, 0x00,0x68,0xfe,0x05,0x03,0x0f,0x04,0x18,0x02,0x26,0x00,0x56,0x00,0x00,0x00,0x06,0x0e,0x10,0x14,0x00,0xff,0xff,0x00,0x5e,0xfe,0xed,0x01,0x52,0x04,0x17,0x02,0x06,0x0d,0xf7,0x00,0x00,0x00,0x01,0x00,0x74,0x03,0xd0,0x01,0x66,0x05,0xb2,0x00,0x14,0x00,0x19,0x40,0x0b,0x00,0x08,0x04,0x11,0x0b,0x05,0x14,0x14,0x0b,0xaf,0x05,0x2f, 0xf1,0xc2,0x2f,0x11,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x01,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x36,0x27,0x46,0x35,0x20,0x44,0x38,0x33,0x30,0x1a,0x28,0x1a,0x14,0x4c,0x37,0x03,0xd0,0x1e,0x44,0x4f,0x5d,0x37,0x4e,0x4f,0x39,0x26,0x22,0x26,0x11,0x0c,0x15,0x18,0x2a, 0x5f,0x2d,0x00,0x01,0x01,0x3d,0xfe,0x05,0x02,0x06,0xff,0x93,0x00,0x12,0x00,0x12,0xb6,0x12,0x0c,0x03,0x0f,0x00,0x0f,0x09,0x2f,0xc1,0xc4,0x12,0x39,0x00,0x2f,0xc4,0x31,0x30,0x01,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x01,0x50,0x31,0x21,0x12,0x17,0x24,0x18,0x2b,0x2e,0x33, 0x3d,0x45,0x46,0xfe,0x3a,0x28,0x41,0x17,0x16,0x12,0x0b,0x10,0x22,0x1e,0x22,0x34,0x48,0x45,0x4e,0x7c,0x37,0x00,0xff,0xff,0x00,0x29,0xfe,0x05,0x04,0x0c,0x05,0x9a,0x02,0x26,0x00,0x37,0x00,0x00,0x00,0x06,0x0e,0x10,0x7a,0x00,0xff,0xff,0x00,0x2b,0xfe,0x05,0x02,0x81,0x05,0x2f,0x02,0x26,0x00,0x57,0x00,0x00,0x00,0x06,0x0e,0x10, 0xe5,0x00,0x00,0x02,0xff,0xba,0xff,0xab,0x05,0x1f,0x06,0xee,0x00,0x0a,0x00,0x3d,0x00,0x60,0x40,0x25,0x3b,0x36,0x14,0x0f,0x36,0x0f,0x36,0x0f,0x3f,0x25,0x31,0x28,0x11,0x38,0x38,0x2d,0x1f,0x19,0x0d,0x33,0x0d,0x00,0x01,0x01,0x02,0x0a,0x2d,0x0d,0x26,0x0a,0x0a,0x26,0x0d,0x2d,0x04,0x04,0x05,0xb8,0x04,0xff,0x40,0x09,0x2f,0x08, 0x01,0x08,0x09,0x2f,0x04,0x01,0x04,0x00,0x2f,0x5d,0x33,0x2f,0x5d,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xcd,0x32,0x11,0x33,0x11,0x33,0x10,0xcd,0x32,0x11,0x33,0x11,0x33,0x01,0x2f,0xcd,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x10,0xcd,0x31,0x30,0x01,0x07,0x27,0x01,0x07,0x01,0x23,0x35,0x21,0x01,0x01,0x03,0x16,0x33, 0x32,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x07,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x16,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x05,0x1f,0x2a,0xa9,0xfe,0x6d,0x54,0xfe,0x0d,0xb8,0x01,0x00,0x01,0xce,0x01,0x61,0x93,0x17, 0x12,0x4e,0x11,0x64,0x12,0x15,0x28,0x3a,0x26,0x17,0x32,0x1c,0x11,0x36,0x16,0x14,0x10,0x01,0x06,0x07,0x64,0x08,0x10,0x1a,0x12,0x67,0x0a,0x10,0x07,0x12,0x0e,0x23,0x23,0x11,0x63,0x10,0x06,0x03,0x2c,0x65,0x4b,0xfc,0xa0,0x07,0x06,0xa7,0x9c,0xf9,0xc5,0x03,0x08,0x02,0x1c,0x05,0x50,0x29,0x24,0x2f,0x2f,0x24,0x40,0x31,0x1c,0x0d, 0x10,0x0f,0x0d,0x03,0x01,0x32,0x6b,0x4a,0x7a,0x77,0x47,0x78,0x74,0x7a,0x49,0x2a,0x4a,0x24,0x05,0x2c,0x25,0x25,0x27,0x26,0x2e,0x12,0x24,0x00,0x00,0x02,0xff,0xba,0xff,0xab,0x05,0x1f,0x06,0xee,0x00,0x0a,0x00,0x3a,0x00,0x57,0xb3,0x09,0x10,0x10,0x35,0xb8,0x05,0x0d,0xb6,0x2a,0x20,0x20,0x2a,0x30,0x2f,0x1b,0xb8,0x04,0xfd,0x40, 0x11,0x15,0x00,0x01,0x01,0x02,0x0a,0x25,0x0b,0x2f,0x03,0x08,0x15,0x0a,0x15,0x0a,0x04,0x05,0xb8,0x04,0xff,0x40,0x09,0x2f,0x08,0x01,0x08,0x09,0x2f,0x04,0x01,0x04,0x00,0x2f,0x5d,0x33,0x2f,0x5d,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x10,0xcd,0x32,0x11,0x33,0x10,0xed,0x10,0xcd,0x01,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f, 0x39,0x31,0x30,0x01,0x07,0x27,0x01,0x07,0x01,0x23,0x35,0x21,0x01,0x01,0x03,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x05,0x1f,0x2a,0xa9,0xfe,0x6d,0x54,0xfe,0x0d,0xb8,0x01,0x00,0x01, 0xce,0x01,0x61,0xbf,0x38,0x3f,0x20,0x07,0x12,0x1e,0x25,0x12,0x24,0x33,0x1e,0x41,0x42,0x23,0x45,0x36,0x22,0x09,0x1b,0x2f,0x26,0x24,0x2d,0x19,0x0a,0x15,0x36,0x5d,0x48,0x33,0x3b,0x1e,0x08,0x11,0x26,0x3f,0x2e,0x03,0x2c,0x65,0x4b,0xfc,0xa0,0x07,0x06,0xa7,0x9c,0xf9,0xc5,0x03,0x08,0x01,0xa7,0x34,0x4a,0x32,0x1c,0x06,0x0d,0x0f, 0x08,0x03,0x07,0x08,0x67,0x14,0x0d,0x1c,0x2f,0x22,0x0f,0x2c,0x36,0x3f,0x23,0x10,0x21,0x21,0x21,0x11,0x19,0x33,0x31,0x2f,0x16,0x6c,0x0c,0x16,0x14,0x11,0x06,0x0a,0x14,0x18,0x20,0x17,0x00,0x02,0xff,0xba,0xff,0xab,0x05,0x1f,0x06,0xee,0x00,0x0a,0x00,0x30,0x00,0x4f,0xb1,0x09,0x1d,0xbb,0x05,0x0b,0x00,0x1e,0x00,0x14,0x04,0xfd, 0x40,0x14,0x27,0x0b,0x0b,0x27,0x00,0x01,0x01,0x02,0x0a,0x2c,0x08,0x0f,0x1d,0x0a,0x0a,0x1d,0x0f,0x03,0x04,0x05,0xb8,0x04,0xff,0x40,0x09,0x2f,0x08,0x01,0x08,0x09,0x2f,0x04,0x01,0x04,0x00,0x2f,0x5d,0x33,0x2f,0x5d,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xcd,0x32,0x11,0x33,0x2f,0x33,0x2f,0x10,0xed,0x01,0x2f,0xed, 0x39,0x31,0x30,0x01,0x07,0x27,0x01,0x07,0x01,0x23,0x35,0x21,0x01,0x01,0x13,0x06,0x06,0x07,0x23,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x05,0x1f,0x2a,0xa9,0xfe,0x6d,0x54,0xfe,0x0d,0xb8,0x01,0x00,0x01,0xce,0x01,0x61,0x23, 0x22,0x34,0x10,0x76,0x07,0x16,0x1c,0x24,0x14,0x13,0x11,0x0a,0x0b,0x0a,0x64,0x0c,0x0f,0x0c,0x4a,0x34,0x21,0x39,0x2e,0x22,0x0a,0x02,0x0d,0x1a,0x11,0x03,0x2c,0x65,0x4b,0xfc,0xa0,0x07,0x06,0xa7,0x9c,0xf9,0xc5,0x03,0x08,0x02,0xb5,0x35,0x8b,0x47,0x1b,0x37,0x2b,0x1c,0x17,0x12,0x0f,0x2b,0x4f,0x78,0x5b,0x7a,0x77,0x5e,0x82,0x5a, 0x39,0x15,0x36,0x3e,0x16,0x25,0x31,0x19,0x25,0x3b,0x1f,0x00,0x00,0x02,0x00,0x1e,0xfe,0xa9,0x06,0xd2,0x03,0x61,0x00,0x3b,0x00,0x4d,0x00,0x5d,0xb4,0x38,0x25,0x16,0x10,0x06,0xb8,0x05,0x0a,0xb4,0x25,0x49,0x49,0x25,0x41,0xb8,0x05,0x0a,0xb7,0x2d,0x25,0x2d,0x25,0x2d,0x4f,0x13,0x19,0xb8,0x05,0x0a,0xb3,0x10,0x25,0x05,0x28,0xb8, 0x04,0xfb,0xb5,0x38,0x2f,0x46,0x01,0x46,0x3c,0xb8,0x04,0xfb,0xb4,0x2f,0x32,0x01,0x32,0x1e,0xb9,0x04,0xfb,0x00,0x0b,0x00,0x2f,0xed,0x2f,0x5d,0xed,0x2f,0x5d,0x33,0xed,0x32,0x39,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x2f,0x10,0xed,0x11,0x39,0x11,0x39,0x31,0x30,0x01,0x0e,0x03,0x07,0x15,0x14,0x0e, 0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05,0x35,0x25,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x37,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x25,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x2e,0x03,0x06,0xd2,0x0f,0x2c,0x39,0x43,0x25, 0x49,0x99,0xed,0xa3,0xa1,0xdb,0x87,0x3b,0x09,0x08,0xfe,0xc7,0x01,0xeb,0x13,0x13,0x2b,0x64,0xa5,0x7a,0x62,0x8f,0x64,0x3e,0x24,0x0e,0x02,0x2d,0x57,0x28,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x23,0x30,0x0c,0x33,0x5a,0x23,0xfd,0xf3,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x25,0x4d,0x27,0x07,0x27,0x36,0x43, 0x01,0x7c,0x0d,0x20,0x23,0x25,0x11,0x04,0x95,0xdc,0x91,0x47,0x41,0x7c,0xb7,0x77,0x31,0x6b,0x3a,0x3a,0x72,0x61,0x64,0xa8,0x48,0x5f,0x84,0x54,0x26,0x1a,0x30,0x42,0x50,0x5b,0x30,0x0e,0x0f,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x38,0x91,0x52,0x1c,0x3b,0x1a,0xa6,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0e,0x0d, 0x3a,0x7a,0x63,0x40,0x00,0x04,0x00,0x7c,0x00,0x00,0x05,0x61,0x05,0x58,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x5e,0xb4,0x0d,0x0e,0x0e,0x00,0x09,0xbb,0x05,0x0c,0x00,0x08,0x00,0x05,0x05,0x0c,0x40,0x0c,0x04,0x0c,0x0f,0x0f,0x04,0x00,0x08,0x04,0x08,0x04,0x11,0x01,0xb8,0x05,0x0c,0xb5,0x00,0x2f,0x0d,0x01,0x0d,0x0c,0xbb, 0x04,0xe6,0x00,0x0a,0x00,0x06,0x04,0xfe,0xb5,0x08,0x2f,0x05,0x01,0x05,0x02,0xb9,0x04,0xfe,0x00,0x01,0x00,0x2f,0xed,0x2f,0x5d,0x33,0xed,0x32,0x3f,0x2f,0x5d,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x39,0x11,0x33,0x31,0x30,0x13,0x33,0x15,0x23,0x01,0x33,0x15,0x23,0x25,0x33, 0x15,0x23,0x05,0x01,0x33,0x01,0xc0,0xf7,0xf7,0x02,0x36,0xf7,0xf7,0x01,0x74,0xf7,0xf7,0xfc,0x12,0x03,0x0d,0x8f,0xfc,0xf3,0x04,0xfd,0xf7,0xfd,0x4c,0xf7,0xf7,0xf7,0x5b,0x05,0x58,0xfa,0xa8,0x00,0x00,0x05,0x00,0x7c,0x00,0x00,0x06,0xd5,0x05,0x58,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x6d,0xb4,0x01,0x02,0x02, 0x04,0x11,0xbe,0x05,0x0c,0x00,0x10,0x00,0x0d,0x05,0x0c,0x00,0x0c,0x00,0x09,0x05,0x0c,0x40,0x0f,0x08,0x00,0x03,0x03,0x08,0x04,0x10,0x0c,0x08,0x08,0x0c,0x10,0x03,0x15,0x05,0xb8,0x05,0x0c,0xb3,0x04,0x12,0x0e,0x0a,0xb8,0x04,0xfe,0xb6,0x10,0x0c,0x2f,0x09,0x01,0x09,0x06,0xb8,0x04,0xfe,0xb5,0x05,0x2f,0x01,0x01,0x01,0x00,0xb8, 0x04,0xe6,0x00,0x3f,0x2f,0x5d,0x2f,0xed,0x2f,0x5d,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x39,0x11,0x33,0x31,0x30,0x33,0x01,0x33,0x01,0x03,0x33,0x15,0x23,0x01,0x33,0x15,0x23,0x25,0x33,0x15,0x23,0x25,0x33,0x15,0x23,0x7c,0x03,0x0d, 0x8f,0xfc,0xf3,0x4b,0xf7,0xf7,0x02,0x36,0xf7,0xf7,0x01,0x74,0xf7,0xf7,0x01,0x74,0xf7,0xf7,0x05,0x58,0xfa,0xa8,0x04,0xfd,0xf7,0xfd,0x4c,0xf7,0xf7,0xf7,0xf7,0xf7,0x00,0x01,0x00,0x76,0xfe,0xf8,0x01,0x8b,0x00,0xe4,0x00,0x03,0x00,0x10,0xb7,0x2f,0x01,0x01,0x01,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0x5d,0x31,0x30,0x25,0x13, 0x23,0x03,0x01,0x16,0x75,0x75,0xa0,0xe4,0xfe,0x14,0x01,0xec,0x00,0x02,0xff,0xc8,0x06,0x1d,0x02,0x29,0x08,0xde,0x00,0x2b,0x00,0x2f,0x00,0x2c,0xbc,0x00,0x2f,0x05,0x0d,0x00,0x2c,0x00,0x13,0x05,0x0d,0x40,0x09,0x16,0x26,0x09,0x2d,0x14,0x0e,0x1e,0x2c,0x29,0xb9,0x05,0x01,0x00,0x04,0x00,0x2f,0xfd,0xce,0xde,0xcd,0x2f,0x2f,0x01, 0x2f,0xcd,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x37,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x07,0x06,0x06,0x23,0x22,0x22,0x06,0x22,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x11,0x33,0x11,0x02,0x29,0x52,0xab,0x43,0x46,0x6c,0x49,0x26,0x25,0x35, 0x3b,0x16,0x1d,0x10,0x0d,0x0d,0x58,0x10,0x1d,0x26,0x15,0x06,0x0c,0x06,0x03,0x0e,0x0f,0x0e,0x04,0x18,0x26,0x60,0x69,0x63,0x9b,0x7f,0x58,0x06,0x8f,0x61,0x08,0x09,0x0c,0x1e,0x33,0x28,0x29,0x35,0x1f,0x0d,0x08,0x07,0x17,0x16,0x01,0x76,0xfe,0x7e,0x26,0x34,0x21,0x11,0x03,0x01,0x01,0x01,0x0f,0x12,0x19,0x10,0x09,0x48,0x02,0x0d, 0xfd,0xf3,0x00,0x02,0x00,0x43,0x06,0x1f,0x01,0x6c,0x08,0xbb,0x00,0x16,0x00,0x1a,0x00,0x23,0xb2,0x17,0x17,0x0e,0xbb,0x05,0x0d,0x00,0x07,0x00,0x19,0x04,0xfd,0xb2,0x18,0x0a,0x02,0xb9,0x04,0xfd,0x00,0x13,0x00,0x2f,0xfd,0xd6,0xd6,0xed,0x01,0x2f,0xed,0x33,0x2f,0x31,0x30,0x13,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33, 0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x13,0x23,0x35,0x33,0x43,0x36,0x28,0x21,0x2c,0x1a,0x0b,0x1d,0x13,0x5a,0x17,0x18,0x1f,0x38,0x4b,0x2b,0x17,0x2b,0x1a,0xda,0x57,0x57,0x06,0x90,0x11,0x17,0x28,0x38,0x20,0x3f,0x74,0x37,0x39,0x7f,0x34,0x3c,0x5b,0x3e,0x20,0x09,0x0a,0x02,0x33,0x56,0x00,0x01,0x00,0x37,0x06,0x7c, 0x01,0xcf,0x06,0xca,0x00,0x03,0x00,0x0c,0xba,0x00,0x02,0x05,0x00,0x00,0x01,0x00,0x2f,0xed,0x31,0x30,0x13,0x21,0x15,0x21,0x37,0x01,0x98,0xfe,0x68,0x06,0xca,0x4e,0x00,0x02,0x00,0x0d,0x06,0x5c,0x01,0xb5,0x07,0xe2,0x00,0x23,0x00,0x2f,0x00,0x36,0xb2,0x16,0x09,0x13,0xb8,0x05,0x0e,0xb4,0x24,0x19,0x19,0x24,0x2a,0xb8,0x05,0x0e, 0x40,0x0c,0x09,0x16,0x19,0x19,0x20,0x0e,0x27,0x2d,0x03,0x03,0x20,0x1a,0x00,0x2f,0x2e,0xc9,0x2f,0x32,0xd4,0xcd,0x11,0x33,0x2f,0x39,0x01,0x2f,0xed,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x31,0x30,0x13,0x16,0x16,0x33,0x32,0x32,0x37,0x35,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26, 0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0x1e,0x21,0x41,0x26,0x01,0x09,0x06,0x2d,0x1b,0x2b,0x38,0x1d,0x1c,0x34,0x28,0x19,0x3f,0x33,0x05,0x19,0x06,0x2f,0x14,0x23,0x10,0x15,0x2b,0x11,0x28,0x48,0x23,0x01,0x5d,0x2d,0x1b,0x1d,0x30,0x1f,0x17,0x2a,0x35,0x06,0xea,0x08, 0x08,0x01,0x02,0x3c,0x3b,0x22,0x35,0x24,0x13,0x12,0x24,0x36,0x24,0x3b,0x4f,0x17,0x05,0x16,0x05,0x35,0x0f,0x1f,0x0f,0x05,0x03,0x08,0x07,0xb0,0x23,0x22,0x22,0x20,0x1a,0x36,0x19,0x0e,0x32,0x00,0x00,0x01,0x00,0x37,0xff,0x23,0x01,0xcf,0xff,0x71,0x00,0x03,0x00,0x0c,0xba,0x00,0x02,0x05,0x00,0x00,0x01,0x00,0x2f,0xed,0x31,0x30, 0x17,0x21,0x15,0x21,0x37,0x01,0x98,0xfe,0x68,0x8f,0x4e,0x00,0xff,0xff,0x00,0x70,0xfe,0xf8,0x01,0x8b,0x03,0x11,0x02,0x26,0x0e,0x19,0x00,0x00,0x00,0x07,0x00,0x11,0x00,0x00,0x02,0x46,0xff,0xff,0x00,0x9a,0xfe,0x63,0x05,0x91,0x04,0x15,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0f,0x5b,0x02,0x01,0x00,0x64,0xff,0xff,0x00,0x9a, 0xfe,0x0e,0x06,0xae,0x02,0x13,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x0f,0x5b,0x02,0x01,0x00,0x0f,0xff,0xff,0xff,0xba,0xff,0x05,0x01,0xf2,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x5b,0x00,0x1a,0x01,0x06,0xff,0xff,0xff,0xba,0xff,0x05,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x5b, 0x00,0x1a,0x01,0x06,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x3e,0x02,0x26,0x0e,0x5e,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0xe4,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0x3e,0x02,0x26,0x09,0x3b,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0x72,0xfd,0x55, 0x00,0x0a,0xb4,0x01,0x2f,0x36,0x01,0x36,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab,0xff,0xff,0x00,0xab, 0xff,0xea,0x07,0x59,0x04,0xb2,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x05,0xca,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x53, 0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xca,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x9c,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0xfe,0xab,0x00,0x01,0xff,0xba,0xff,0xf2,0x04,0xad,0x03,0x0f,0x00,0x35, 0x00,0x41,0xb1,0x0d,0x24,0xb8,0x05,0x0b,0xb4,0x30,0x30,0x37,0x15,0x2a,0xb8,0x05,0x03,0x40,0x09,0x30,0x24,0x24,0x21,0x0c,0x20,0x04,0x00,0x12,0xb8,0x04,0xff,0xb5,0x2f,0x19,0x01,0x19,0x29,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x5d,0xed,0x12,0x17,0x39,0x11,0x33,0x3f,0x01,0x2f,0x12,0x39,0x2f,0xed, 0x39,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x06,0x07,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x23,0x23,0x23,0x3b,0x7b,0xe0,0xcf,0xbf,0x5a,0x39,0x60,0x68,0x7c,0x57,0x4e,0x7e,0x33, 0x37,0x84,0x4e,0x50,0x7c,0x6a,0x61,0x69,0x7a,0x4e,0x20,0x20,0x50,0x31,0x01,0x14,0x35,0x5e,0x4a,0x14,0x62,0x7d,0x4a,0x1e,0x02,0x48,0xab,0xc8,0xe3,0x80,0x0e,0x34,0x20,0x20,0x33,0x37,0x59,0x70,0x39,0x05,0x1b,0x35,0x2b,0x1b,0x14,0x10,0x9d,0x12,0x17,0x1d,0x2b,0x32,0x2c,0x1e,0x01,0xc8,0x08,0x29,0x1d,0x2b,0x3b,0x25,0x10,0xa7, 0x29,0x46,0x5d,0x35,0x2b,0x5b,0x4b,0x30,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x04,0x61,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x56,0x03,0xb1,0x00,0x01,0x00,0x52,0xff,0xea,0x04,0x02,0x03,0xba,0x00,0x24,0x00,0x29,0xb1,0x1b,0x0f,0xb8,0x05,0x0a,0xb5,0x06,0x1c,0x21,0x14,0x14,0x03,0xbd,0x04,0xfb,0x00,0x0b, 0x00,0x21,0x05,0x03,0x00,0x15,0x05,0x03,0x00,0x3f,0x3f,0xc4,0xed,0x32,0x2f,0x11,0x39,0x01,0x2f,0xed,0x39,0x31,0x30,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x12,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x52,0x61,0xa6,0x39,0x92,0x7f,0x1c,0x31,0x40,0x24, 0xa6,0x38,0x4d,0x1d,0x07,0x18,0x2d,0x46,0x36,0x16,0x21,0x3f,0x38,0x2d,0x0f,0x05,0x1a,0x51,0x64,0x75,0x3e,0x3a,0x9a,0x4b,0xa9,0x0b,0x0b,0x47,0x4e,0x2e,0x92,0xb0,0xc3,0x5f,0xa7,0xfe,0xe3,0x80,0x20,0x4d,0x43,0x2d,0xa7,0x10,0x23,0x39,0x29,0x2d,0x3c,0x25,0x0f,0x0c,0x0a,0x00,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x05,0x5d, 0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x1d,0x04,0xad,0x00,0x01,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x03,0x0f,0x00,0x58,0x00,0x83,0xb1,0x13,0x08,0xb8,0x05,0x0a,0xb2,0x05,0x1e,0x54,0xb8,0x05,0x0a,0xb3,0x51,0x27,0x27,0x49,0xb8,0x05,0x0a,0x40,0x0a,0x42,0x05,0x51,0x42,0x42,0x51,0x05,0x03,0x5a,0x38,0xb8,0x05,0x0a, 0x40,0x0e,0x31,0x2f,0x53,0x01,0x53,0x2f,0x46,0x01,0x46,0x2f,0x35,0x01,0x35,0x3d,0xb8,0x04,0xfb,0xb6,0x1f,0x2c,0x2f,0x2c,0x02,0x2c,0x4c,0xba,0x04,0xfb,0x00,0x23,0x05,0x03,0xb6,0x26,0x12,0x1d,0x03,0x06,0x0d,0x00,0xba,0x04,0xfb,0x00,0x18,0x05,0x03,0xb3,0x2f,0x06,0x01,0x06,0x00,0x2f,0x5d,0x3f,0xed,0x32,0x12,0x17,0x39,0x3f, 0xed,0x2f,0x5d,0xed,0x2f,0x5d,0x2f,0x5d,0x2f,0x5d,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x2f,0x10,0xed,0x39,0x10,0xed,0x39,0x31,0x30,0x25,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x07, 0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x07,0x57,0x26,0x40,0x2e,0x19,0x9c,0x0c,0x27,0x49,0x3e,0x16,0x5d,0x70,0x1f,0x06,0x17,0x3a,0x42,0x47,0x24,0x2c, 0x4f,0x42,0x34,0x12,0x04,0x19,0x3f,0x44,0x46,0x1f,0x42,0x52,0x19,0x05,0x03,0x3d,0x80,0xcc,0x91,0x8a,0xb9,0x70,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x93,0x5d,0x2b,0x12,0x10,0x9b,0x08,0x0c,0x05,0x06,0x58,0x5e,0x22,0x3f,0x30,0x1d,0x9c,0x0b,0x27,0x48,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x8f,0x43,0x62, 0x41,0x1f,0xa7,0x36,0x39,0x21,0x2a,0x1a,0x0a,0x0d,0x1c,0x2f,0x23,0x23,0x2f,0x1d,0x0c,0x26,0x20,0x01,0x84,0xd3,0x93,0x4e,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x53,0xbb,0x78,0x3f,0x70,0x38,0x42,0x3f,0x10,0x2a,0x48,0x38,0x01,0x0b,0xc6,0x43,0x60,0x3e,0x1e,0x00,0x00,0x01, 0xff,0xba,0xff,0xf2,0x06,0xae,0x03,0x0f,0x00,0x4d,0x00,0x68,0xb5,0x27,0x39,0x1e,0x46,0x13,0x08,0xbe,0x05,0x0a,0x00,0x05,0x00,0x49,0x05,0x0a,0x00,0x46,0x00,0x3c,0x05,0x0a,0x40,0x17,0x39,0x48,0x2f,0x3a,0x01,0x3a,0x26,0x1d,0x06,0x13,0x18,0x12,0x12,0x06,0x18,0x41,0x34,0x34,0x33,0x33,0x0d,0x0d,0x00,0xb8,0x04,0xfb,0xb3,0x2c, 0x23,0x0e,0x18,0xb8,0x05,0x03,0xb3,0x2f,0x06,0x01,0x06,0x00,0x2f,0x5d,0x3f,0x33,0x33,0x33,0xed,0x32,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x39,0x2f,0x5d,0x33,0x01,0x2f,0xed,0xd4,0xed,0xd4,0xed,0x39,0x12,0x39,0x11,0x39,0x31,0x30,0x25,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33, 0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x04,0xab,0x26,0x40,0x2e,0x19,0x9c,0x0c,0x27,0x49,0x3e, 0x16,0x5d,0x70,0x1f,0x06,0x17,0x3a,0x42,0x47,0x24,0x2c,0x4f,0x42,0x34,0x12,0x04,0x1a,0x42,0x47,0x48,0x21,0x64,0x77,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0x0b,0x24,0x44,0x39,0x24,0x43,0x33,0x1f,0x9c,0x0b,0x27,0x48,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x8f,0x43,0x62, 0x41,0x1f,0xa7,0x36,0x39,0x21,0x2a,0x1a,0x0a,0x0d,0x1c,0x2f,0x23,0x23,0x2f,0x1d,0x0c,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0x0b,0xc9,0x41,0x5f,0x3e,0x1e,0x10,0x2a,0x48,0x38,0x01,0x0b,0xc6,0x43,0x60,0x3e,0x1e,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x05,0x1f,0x02,0x26,0x0e,0x31, 0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0x50,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x05,0x1f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xa4,0x03,0x57,0x00,0x02,0x00,0x9b,0xfd,0xff,0x0a,0xb0,0x03,0x3c,0x00,0x4b,0x00,0x5f,0x00,0x7b,0xbf,0x00,0x26,0x05,0x0a,0x00,0x1f,0x00,0x5d,0x05,0x0a,0x00,0x2b,0x00, 0x37,0x05,0x0a,0x40,0x0a,0x51,0x2b,0x51,0x1f,0x51,0x1f,0x51,0x0e,0x3d,0x15,0xb8,0x05,0x0a,0x40,0x0a,0x0e,0x5d,0x5d,0x4c,0x4c,0x3c,0x3c,0x42,0x04,0x2b,0xbd,0x04,0xfb,0x00,0x3d,0x00,0x47,0x05,0x03,0x00,0x56,0x04,0xfb,0x40,0x0d,0x2f,0x32,0x01,0x32,0x2f,0x23,0x01,0x23,0x2f,0x12,0x01,0x12,0x1a,0xb8,0x04,0xfb,0xb5,0x1f,0x09, 0x2f,0x09,0x02,0x09,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0x2f,0x5d,0x2f,0x5d,0xed,0x3f,0x33,0xed,0x39,0x39,0x32,0x2f,0x33,0x11,0x33,0x2f,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x26,0x26,0x27,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15, 0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x17,0x3e,0x05,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x25,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x04,0xf8,0x1f,0x28,0x12,0x05,0x03,0x3d,0x81, 0xcd,0x94,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x93,0x5d,0x2b,0x12,0x17,0x9a,0x0b,0x0d,0x08,0x03,0x11,0x21,0x36,0x28,0x18,0x4c,0x67,0x81,0x9a,0xb4,0x65,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x46,0x38,0x16,0x5e,0x74,0x1f,0x06,0x26,0x70,0x89,0x9d,0x54,0xa1,0xe7,0x9d,0x5e,0x02,0x99,0x6b, 0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x85,0x75,0x65,0x52,0x3f,0x15,0x5c,0xee,0x03,0x09,0x1d,0x15,0x01,0x84,0xd3,0x93,0x4e,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x53,0xc5,0x6e,0x3f,0x72,0x3a,0x17,0x2b,0x22,0x15,0x02,0x41,0x96,0x95,0x8b,0x6a,0x40,0x49,0x7d,0xa4,0x5b, 0x3a,0x54,0x36,0x1a,0xa7,0x3a,0x45,0x31,0x36,0x1a,0x06,0x01,0x03,0x08,0x9d,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0x2a,0x49,0x63,0x71,0x7a,0x3c,0x02,0x01,0x00,0x00,0x02,0xff,0xba,0xff,0xea,0x08,0x04,0x03,0x3c,0x00,0x42,0x00,0x54,0x00,0x64,0xbc,0x00,0x52,0x05,0x0a,0x00,0x27,0x00,0x33,0x05,0x0a,0xb7,0x48,0x27,0x48,0x27, 0x48,0x1b,0x39,0x22,0xbd,0x05,0x0a,0x00,0x1b,0x00,0x39,0x05,0x03,0x00,0x4d,0x04,0xfb,0x40,0x13,0x2f,0x2e,0x01,0x2e,0x2f,0x1e,0x01,0x1e,0x52,0x52,0x43,0x43,0x38,0x38,0x27,0x27,0x3e,0x09,0x15,0xbc,0x04,0xfb,0x00,0x0e,0x05,0x03,0x00,0x00,0x05,0x03,0x00,0x3f,0x3f,0xed,0x39,0x39,0x32,0x2f,0x33,0x2f,0x33,0x11,0x33,0x2f,0x2f, 0x5d,0x2f,0x5d,0xed,0x3f,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x22,0x24,0x26,0x26,0x27,0x26,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x17,0x3e,0x05,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03, 0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x27,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x16,0x16,0x04,0xe7,0xb3,0xff,0x00,0xaf,0x69,0x1b,0x23,0x2e,0x14,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x27,0x42,0x30,0x1c,0x0f,0x0d,0x9a,0x0b,0x0d,0x08,0x03,0x11,0x21,0x36,0x28,0x18,0x4c, 0x67,0x81,0x9a,0xb4,0x65,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26,0x70,0x89,0x9d,0x3e,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x6e,0xbc,0x97,0x6e,0x1f,0x5c,0xee,0x16,0x01,0x06,0x0d,0x0c,0x0f,0x31,0x23,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x18,0x27,0x33,0x1b,0x30,0x6e,0x3d,0x3f, 0x72,0x3a,0x17,0x2b,0x22,0x15,0x02,0x41,0x96,0x95,0x8b,0x6a,0x40,0x49,0x7d,0xa4,0x5b,0x3a,0x54,0x36,0x1a,0xa7,0x3a,0x45,0x31,0x36,0x1a,0x06,0xa9,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0x5c,0x92,0xb5,0x5a,0x02,0x01,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x0a,0xb0,0x04,0xb2,0x02,0x26,0x0e,0x35,0x00,0x00,0x00,0x07,0x0f,0x50, 0x05,0xca,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xea,0x08,0x04,0x04,0xb2,0x02,0x26,0x0e,0x36,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x1e,0x04,0x02,0x00,0x02,0x00,0x19,0xff,0xea,0x06,0xae,0x05,0xec,0x00,0x29,0x00,0x3d,0x00,0x4c,0xb9,0x00,0x05,0x05,0x0a,0xb4,0x2f,0x2f,0x0b,0x3b,0x24,0xb8,0x05,0x0a,0x40,0x11,0x21,0x0b,0x25,0x1b, 0x15,0x23,0x15,0x15,0x0b,0x3b,0x3b,0x2a,0x2a,0x1e,0x1e,0x10,0x0a,0xbd,0x04,0xfb,0x00,0x0b,0x05,0x03,0x00,0x34,0x04,0xfb,0x00,0x00,0x00,0x2f,0xed,0x3f,0xed,0x39,0x32,0x2f,0x33,0x11,0x33,0x2f,0x11,0x33,0x2f,0x2f,0x12,0x39,0x39,0x01,0x2f,0x2f,0xed,0x39,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33, 0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x24,0x26,0x26,0x27,0x27,0x16,0x16,0x17,0x36,0x36,0x37,0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x04,0x28,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26,0x70,0x89,0x9d,0x54, 0xb7,0xfe,0xf5,0xc6,0x92,0x3e,0x20,0x2d,0x91,0x58,0x08,0x13,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x27,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5c,0xe9,0x03,0x58,0x4e,0x84,0xae,0x61,0x3a,0x54,0x36,0x1a,0xa7,0x3a,0x45,0x31,0x36,0x1a,0x06,0x03,0x06,0x09,0x06,0xa7,0x06,0x07,0x01,0x16,0x2e, 0x1a,0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0x00,0x02,0xff,0xba,0xff,0xed,0x05,0xf5,0x05,0xec,0x00,0x24,0x00,0x38,0x00,0x43,0xb9,0x00,0x05,0x05,0x0a,0xb4,0x2a,0x2a,0x3a,0x36,0x1f,0xb8,0x05,0x0a,0x40,0x09,0x1c,0x20,0x0c,0x1e, 0x36,0x36,0x25,0x25,0x18,0xb8,0x04,0xff,0xb3,0x11,0x0c,0x0c,0x11,0xbb,0x05,0x03,0x00,0x2f,0x04,0xfb,0x00,0x00,0x00,0x2f,0xed,0x3f,0x33,0x2f,0x10,0xed,0x32,0x11,0x33,0x2f,0x2f,0x12,0x39,0x01,0x2f,0xed,0x39,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x23,0x23,0x22,0x26,0x35, 0x34,0x36,0x33,0x21,0x36,0x36,0x37,0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x04,0x28,0x79,0xae,0x70,0x36,0x2d,0x51,0x71,0x88,0x9a,0x52,0x72,0xc7,0xc6,0xd2,0x7c,0x45,0x23,0x23,0x23,0x23,0x01,0x2e,0x08,0x14,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x27,0x6b,0xa2, 0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x83,0x75,0x63,0x52,0x3e,0x15,0x5b,0xeb,0x03,0x58,0x4f,0x88,0xb5,0x66,0x5d,0x80,0x54,0x2e,0x16,0x04,0x02,0x01,0x02,0x34,0x20,0x20,0x33,0x17,0x2f,0x1a,0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2c,0x4e,0x68,0x77,0x81,0x3f,0x02,0x01, 0x00,0x02,0xff,0xba,0xff,0xed,0x06,0xae,0x05,0xec,0x00,0x2d,0x00,0x41,0x00,0x50,0xb9,0x00,0x05,0x05,0x0a,0xb4,0x33,0x33,0x0b,0x3f,0x28,0xb8,0x05,0x0a,0xb6,0x25,0x0b,0x29,0x15,0x27,0x1a,0x15,0xb8,0x05,0x03,0x40,0x0a,0x3f,0x3f,0x2e,0x2e,0x22,0x22,0x21,0x21,0x10,0x0a,0xbd,0x04,0xff,0x00,0x0b,0x05,0x03,0x00,0x38,0x04,0xfb, 0x00,0x00,0x00,0x2f,0xed,0x3f,0xed,0x39,0x32,0x2f,0x33,0x2f,0x33,0x11,0x33,0x2f,0x3f,0x33,0x2f,0x12,0x39,0x01,0x2f,0x2f,0xed,0x39,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x36,0x36,0x37, 0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x04,0x28,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26,0x6f,0x89,0x9d,0x54,0x72,0xc7,0xc6,0xd2,0x7c,0x45,0x23,0x23,0x23,0x23,0x01,0x2e,0x08,0x14,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4, 0x27,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5b,0xeb,0x03,0x58,0x4e,0x84,0xae,0x61,0x3a,0x54,0x36,0x1a,0xa7,0x3c,0x43,0x30,0x35,0x1a,0x05,0x02,0x01,0x02,0x34,0x20,0x20,0x33,0x17,0x2f,0x1a,0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25, 0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0xff,0xff,0x00,0x19,0xff,0xea,0x06,0xae,0x05,0xec,0x02,0x26,0x0e,0x39,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xe5,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xed,0x05,0xf5,0x05,0xec,0x02,0x26,0x0e,0x3a,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xe5,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xed,0x06,0xae, 0x05,0xec,0x02,0x26,0x0e,0x3b,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xe5,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xa2,0x06,0xb3,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x0f,0x51,0x03,0x90,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x06,0xb3,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x51,0x03,0x90,0x06,0x03, 0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0xb3,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x39,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0xb3,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0xa2,0x06,0x02,0x02,0x26,0x09,0x46,0x00,0x00, 0x00,0x07,0x0f,0x54,0x02,0xad,0xfd,0xce,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x06,0x02,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x03,0x4b,0x06,0x02,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xab,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02, 0x06,0x02,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xab,0xfd,0xce,0xff,0xff,0x00,0x9a,0xff,0x55,0x05,0x91,0x05,0xdc,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0a,0x6e,0x02,0x01,0xfe,0x00,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x04,0x2c,0x02,0x26,0x08,0xf7,0x00,0x00,0x01,0x07,0x0a,0x6e,0x02,0x01,0xfc,0x50, 0x00,0x0a,0xb4,0x01,0x2f,0x4b,0x01,0x4b,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xc4,0x05,0x5a,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0a,0x6e,0x00,0x9c,0xfd,0x7e,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xc4,0x05,0x5a,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0a,0x6e, 0x00,0x9c,0xfd,0x7e,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0x9a,0xff,0x55,0x05,0x91,0x04,0xf9,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x8f,0x04,0x49,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x03,0xb9,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0xdc,0x03,0x09,0xff,0xff,0xff,0xba, 0xfe,0xa6,0x02,0x9a,0x04,0xb2,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x9a, 0xff,0x55,0x05,0x91,0x06,0x11,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x8f,0x04,0x49,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x04,0xd1,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0xdc,0x03,0x09,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x9a,0x05,0xca,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51, 0x00,0x4a,0xfe,0xab,0x00,0x07,0x0f,0x53,0x00,0x9c,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0xca,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x00,0x07,0x0f,0x53,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x08,0x04,0x05,0x24,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x50, 0x04,0xd7,0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x06,0x03,0x04,0x79,0x02,0x26,0x0e,0x70,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xd4,0x03,0xc9,0x00,0x02,0x00,0xab,0xff,0xea,0x06,0xae,0x05,0xec,0x00,0x2e,0x00,0x4f,0x00,0x66,0xb1,0x1e,0x13,0xbe,0x05,0x0a,0x00,0x10,0x00,0x4a,0x05,0x0b,0x00,0x31,0x00,0x42,0x05,0x0b,0x40,0x0a, 0x39,0x10,0x31,0x39,0x39,0x31,0x10,0x03,0x51,0x03,0xbe,0x05,0x0a,0x00,0x2b,0x00,0x3e,0x04,0xfd,0x00,0x3f,0x00,0x2f,0x04,0xfd,0xb5,0x4f,0x1e,0x23,0x18,0x18,0x0b,0xbc,0x04,0xfb,0x00,0x23,0x05,0x03,0x00,0x19,0x05,0x03,0xb4,0x11,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0x3f,0x3f,0xed,0x32,0x2f,0x11,0x39,0x2f,0xfd,0xd4,0xed, 0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x39,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x25,0x36,0x35,0x34,0x26,0x27, 0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x01,0x62,0x09,0x11,0x1f,0x2f,0x1a,0x4e,0x7b,0xb1,0x7d,0x6d,0xa2,0x6c,0x36,0x9c,0x0c,0x27,0x49,0x3e,0x16,0x64,0x75,0x20,0x04,0x26,0x6f,0x87,0x9b,0x53,0x76,0xc2,0x9b,0x78,0x2c,0x3f,0x30,0x12,0x0b,0x01,0xe4,0xc5,0x1f, 0x15,0x10,0x21,0x1b,0x11,0x2e,0x4f,0x69,0x3b,0x5e,0x54,0x21,0x17,0x0f,0x20,0x1a,0x10,0x25,0x4c,0x74,0x4f,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x63,0x23,0x13,0x1a,0x10,0x07,0x0a,0x29,0x53,0x48,0x04,0x8b,0xfb,0xac,0x43,0x60,0x3e,0x1e,0xa7,0x3a,0x40,0x2f,0x34,0x1a,0x05,0x06,0x16,0x2c,0x26,0x37,0x98,0x58,0x3d,0x70,0x33,0x57,0x0b, 0x47,0x12,0x16,0x0b,0x08,0x14,0x1b,0x27,0x1b,0x26,0x3e,0x2f,0x1f,0x08,0x5d,0x0c,0x2d,0x21,0x14,0x18,0x0b,0x08,0x12,0x1a,0x23,0x19,0x1f,0x3e,0x33,0x23,0x04,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x02,0x00,0x2c,0x00,0x2e,0x40,0x11,0x11,0x15,0x12,0x03,0x00,0x14,0x2f,0x13,0x01,0x13,0x27,0x27,0x26,0x26,0x21,0x21, 0x06,0xbb,0x04,0xfb,0x00,0x22,0x00,0x00,0x05,0x03,0x00,0x3f,0x32,0xed,0x32,0x11,0x33,0x2f,0x33,0x2f,0x2f,0x5d,0xcd,0x12,0x17,0x39,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x35,0x01,0x15,0x01,0x1e,0x03,0x17,0x1e,0x05,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23, 0x23,0x23,0x23,0x01,0x28,0x61,0x80,0x4c,0x1e,0x58,0xa4,0xe7,0x90,0x03,0x4b,0xfd,0x66,0xad,0xdd,0x85,0x40,0x10,0x03,0x0b,0x14,0x21,0x34,0x49,0x32,0x16,0x59,0x8d,0x2c,0x05,0x17,0x47,0x68,0x8d,0x5d,0x0e,0x34,0x20,0x20,0x33,0x16,0x2a,0x3f,0x29,0x4c,0x8c,0x86,0x85,0x46,0x76,0x02,0x22,0xb0,0xfe,0x5f,0x52,0x92,0x8b,0x8a,0x4a, 0x0f,0x2b,0x30,0x2e,0x26,0x17,0xa7,0x4a,0x55,0x22,0x3a,0x2b,0x18,0x00,0x00,0x02,0x00,0x39,0xfd,0xff,0x04,0xad,0x02,0xb9,0x00,0x2f,0x00,0x41,0x00,0x54,0xb9,0x00,0x3d,0x01,0x52,0xb5,0x1f,0x1f,0x16,0x1a,0x06,0x2b,0xbb,0x05,0x0a,0x00,0x35,0x00,0x11,0x05,0x0a,0xb4,0x1a,0x0e,0x05,0x09,0x3a,0xb8,0x04,0xfb,0x40,0x09,0x2f,0x26, 0x01,0x26,0x2f,0x16,0x01,0x16,0x09,0xb8,0x05,0x03,0xb3,0x1f,0x30,0x30,0x00,0xba,0x04,0xfb,0x00,0x01,0x05,0x03,0x00,0x3f,0xed,0x32,0x11,0x33,0x3f,0x2f,0x5d,0x2f,0x5d,0xed,0x12,0x39,0x39,0x01,0x2f,0xed,0x2f,0xed,0x39,0x11,0x39,0x39,0x10,0xed,0x31,0x30,0x25,0x15,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x23, 0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x05,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x1e,0x03,0x04,0xad,0x16,0x51,0x68,0x21,0x04,0x26,0x6c,0x4f,0x31,0x65,0x60,0x57,0x24,0x4e,0x43,0x09,0x11,0x17,0x0e,0xa6,0x19,0x1d,0x24,0x42, 0x5d,0x3a,0x17,0x3d,0x45,0x49,0x44,0x3b,0x15,0x44,0x6e,0x53,0x34,0x0b,0x06,0x0f,0x26,0x45,0xfe,0x55,0x21,0x35,0x27,0x15,0x1e,0x33,0x45,0x27,0x4b,0x6d,0x29,0x21,0x44,0x44,0x43,0x99,0xa7,0x3a,0x36,0x36,0x3b,0x13,0x17,0x13,0x63,0x5b,0x26,0x5d,0x63,0x61,0x2a,0x67,0xbd,0x45,0x48,0x79,0x5b,0x39,0x09,0x71,0xa2,0x6f,0x42,0x24, 0x0b,0x41,0x67,0x80,0x3f,0x26,0x43,0x33,0x1d,0x01,0x0c,0x1c,0x30,0x23,0x25,0x59,0x4e,0x34,0xa4,0xad,0x05,0x0e,0x0e,0x09,0x00,0x02,0xff,0xba,0xff,0xf2,0x04,0xad,0x02,0xaf,0x00,0x30,0x00,0x40,0x00,0x32,0xb2,0x31,0x08,0x3c,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x24,0x01,0x24,0x34,0x30,0x30,0x0d,0x05,0x17,0xb8,0x04,0xfb,0xb4,0x10, 0x08,0x08,0x00,0x10,0xb8,0x05,0x03,0x00,0x3f,0x33,0x33,0x2f,0x10,0xed,0x39,0x39,0x32,0x2f,0x33,0x2f,0x5d,0xed,0x12,0x39,0x31,0x30,0x05,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x3e,0x05,0x33,0x32,0x1e,0x04,0x17,0x1e,0x03,0x33, 0x25,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x04,0xad,0x16,0x5b,0x6f,0x1e,0x05,0x2d,0x87,0x61,0x34,0x61,0x57,0x4b,0x1e,0x35,0x99,0x5f,0x13,0x23,0x23,0x23,0x23,0x1a,0x3f,0x57,0x3a,0x23,0x0b,0x0d,0x21,0x2b,0x38,0x48,0x5c,0x39,0x4f,0x72,0x50,0x33,0x1c,0x0c,0x02,0x04,0x0d,0x25,0x46,0x3d,0xfc,0xd4, 0x2b,0x8e,0x56,0x5e,0x69,0x1a,0x35,0x52,0x37,0x30,0x4f,0x3e,0x2f,0x0e,0x40,0x41,0x39,0x48,0x18,0x28,0x35,0x1e,0x50,0x43,0x34,0x20,0x20,0x33,0x2e,0x41,0x48,0x1b,0x1f,0x49,0x48,0x42,0x34,0x1e,0x2e,0x48,0x56,0x51,0x40,0x0e,0x21,0x3e,0x30,0x1d,0x6d,0x35,0x36,0x44,0x45,0x21,0x51,0x45,0x2f,0x26,0x45,0x5f,0xff,0xff,0x00,0x9b, 0xfd,0xff,0x05,0x58,0x03,0x5c,0x02,0x26,0x0e,0xcf,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x9f,0x02,0xac,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0x00,0x03,0xff,0xba,0xff,0xf2,0x04,0x87,0x04,0x53,0x00,0x2d,0x00,0x3f,0x00,0x50,0x00,0x63,0xb3,0x12, 0x1f,0x17,0x24,0xb8,0x05,0x0a,0xb2,0x4b,0x46,0x43,0xb8,0x05,0x0b,0xb6,0x31,0x4b,0x31,0x4b,0x31,0x52,0x3b,0xbf,0x05,0x0a,0x00,0x17,0x00,0x49,0x04,0xfc,0x00,0x29,0x05,0x03,0x00,0x36,0x04,0xfc,0x40,0x10,0x1c,0x00,0x46,0x40,0x1c,0x04,0x05,0x1e,0x2f,0x1f,0x01,0x1f,0x2e,0x0f,0x0f,0x0c,0xba,0x04,0xfb,0x00,0x05,0x05,0x03,0x00, 0x3f,0xed,0x32,0x11,0x33,0x2f,0x5d,0xcd,0x12,0x17,0x39,0x10,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x25,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x33,0x32,0x37,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x37,0x27,0x35,0x16,0x04,0x16,0x16, 0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x36,0x35,0x34,0x2e,0x02,0x27,0x02,0x3b,0x26,0x61,0x6c,0x73,0x37,0x9e,0x23,0x23,0x23,0x23,0x3a,0x72,0x3a,0x84,0x38,0x01,0x4a,0x60,0x38,0x15,0x25,0x43,0x5c, 0x38,0x01,0x53,0xca,0x01,0x32,0xcd,0x68,0x17,0x2f,0x46,0x2e,0x1e,0x5a,0x6b,0x76,0x51,0x33,0x21,0x1c,0x2b,0x34,0x18,0x1c,0x3a,0x2f,0x1e,0x11,0x31,0x58,0x01,0x0a,0x09,0x08,0x2a,0x2d,0x43,0x9a,0x4b,0x1d,0x29,0x45,0x5b,0x31,0x4c,0x1d,0x23,0x14,0x06,0x34,0x20,0x20,0x33,0x02,0x03,0x04,0x1e,0x44,0x4d,0x55,0x2f,0x37,0x79,0x6c, 0x52,0x11,0x06,0x36,0xc7,0x71,0xf6,0xe7,0xc7,0x42,0x2f,0x5f,0x4c,0x30,0x09,0x15,0x22,0xbd,0x3f,0x7e,0x37,0x2d,0x50,0x3d,0x23,0x29,0x41,0x4f,0x26,0x19,0x36,0x3c,0x42,0x01,0x40,0x20,0x3c,0x21,0x4e,0x92,0x36,0x1a,0x20,0x06,0x2c,0x36,0x2b,0x5d,0x60,0x60,0x2e,0x00,0x00,0x03,0x00,0x53,0xff,0xf2,0x05,0x32,0x04,0x53,0x00,0x2a, 0x00,0x3c,0x00,0x4d,0x00,0x63,0xb3,0x0f,0x1c,0x14,0x21,0xb8,0x05,0x0a,0xb2,0x48,0x43,0x40,0xb8,0x05,0x0b,0xb6,0x2e,0x48,0x2e,0x48,0x2e,0x4f,0x38,0xbf,0x05,0x0a,0x00,0x14,0x00,0x46,0x04,0xfc,0x00,0x26,0x05,0x03,0x00,0x33,0x04,0xfc,0x40,0x10,0x19,0x00,0x43,0x3d,0x19,0x04,0x05,0x1b,0x2f,0x1c,0x01,0x1c,0x2b,0x0e,0x0e,0x0c, 0xba,0x04,0xfb,0x00,0x05,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x32,0x2f,0x5d,0xcd,0x12,0x17,0x39,0x10,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x25,0x0e,0x03,0x23,0x22,0x26,0x27,0x27,0x16,0x16,0x33,0x32,0x37,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x37,0x27, 0x35,0x16,0x04,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x36,0x35,0x34,0x2e,0x02,0x27,0x02,0xe6,0x23,0x59,0x63,0x69,0x33,0x55,0x80,0x23,0x20,0x52,0x9c,0x51,0x80,0x3b,0x01,0x4a,0x60,0x38, 0x15,0x25,0x43,0x5c,0x38,0x01,0x53,0xca,0x01,0x32,0xcd,0x68,0x17,0x2f,0x46,0x2e,0x1e,0x5a,0x6b,0x76,0x51,0x33,0x21,0x1c,0x2b,0x34,0x18,0x1c,0x3a,0x2f,0x1e,0x11,0x31,0x58,0x01,0x0a,0x09,0x08,0x2a,0x2d,0x43,0x9a,0x4b,0x1d,0x29,0x45,0x5b,0x31,0x4c,0x1d,0x23,0x14,0x06,0x0b,0x05,0xa7,0x0a,0x08,0x03,0x04,0x1e,0x44,0x4d,0x55, 0x2f,0x37,0x79,0x6c,0x52,0x11,0x06,0x36,0xc7,0x71,0xf6,0xe7,0xc7,0x42,0x2f,0x5f,0x4c,0x30,0x09,0x15,0x22,0xbd,0x3f,0x7e,0x37,0x2d,0x50,0x3d,0x23,0x29,0x41,0x4f,0x26,0x19,0x36,0x3c,0x42,0x01,0x40,0x20,0x3c,0x21,0x4e,0x92,0x36,0x1a,0x20,0x06,0x2c,0x36,0x2b,0x5d,0x60,0x60,0x2e,0x00,0x00,0x03,0xff,0xba,0xfd,0xff,0x04,0x02, 0x03,0x56,0x00,0x2c,0x00,0x3c,0x00,0x4c,0x00,0x59,0xb1,0x19,0x0c,0xb8,0x05,0x0a,0xb5,0x32,0x47,0x47,0x32,0x3c,0x3d,0xb8,0x05,0x0a,0x40,0x09,0x12,0x00,0x25,0x2d,0x13,0x13,0x12,0x12,0x00,0xb8,0x04,0xfb,0xb3,0x3d,0x16,0x14,0x25,0xba,0x05,0x03,0x00,0x42,0x04,0xfb,0xb6,0x1f,0x1e,0x2f,0x1e,0x02,0x1e,0x37,0xb8,0x04,0xfb,0xb3, 0x2f,0x07,0x01,0x07,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x3f,0x33,0x33,0x33,0xed,0x32,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x33,0xed,0x32,0x2f,0x33,0x2f,0x10,0xed,0x32,0x31,0x30,0x37,0x3e,0x05,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x17,0x21,0x15,0x21,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x04,0x27,0x23, 0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x07,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0xb4,0x15,0x41,0x4e,0x55,0x51,0x49,0x1b,0x2f,0x54,0x3f,0x25,0x16,0x27,0x34,0x1d,0x02,0x01,0x45,0xfe,0xc0,0x01,0x48,0x40,0x27,0x49,0x66,0x3f,0x24,0x54,0x55,0x50,0x3f, 0x29,0x04,0xab,0x23,0x23,0x23,0x23,0x01,0xd0,0x30,0x52,0x3a,0x21,0x11,0x1e,0x27,0x16,0x1a,0x47,0x47,0x3d,0x0e,0x0b,0x04,0x2e,0x45,0x52,0x27,0x22,0x2e,0x1c,0x0d,0x20,0x3d,0x58,0x38,0x99,0x85,0xcf,0x9c,0x6c,0x43,0x1e,0x45,0x6d,0x87,0x43,0x35,0x5d,0x4e,0x41,0x19,0x07,0xa7,0x06,0x2d,0x79,0x3f,0x33,0x5f,0x49,0x2d,0x14,0x2e, 0x4b,0x6f,0x96,0x61,0x34,0x20,0x20,0x33,0x33,0x53,0x69,0x36,0x28,0x55,0x45,0x2d,0x47,0x88,0xc6,0x7f,0xa7,0x58,0x7d,0x50,0x26,0x16,0x22,0x2c,0x16,0x24,0x4b,0x3c,0x26,0x00,0x00,0x02,0x00,0x00,0xfd,0xff,0x04,0x02,0x02,0xb7,0x00,0x27,0x00,0x38,0x00,0x55,0xb2,0x1f,0x1f,0x1c,0xb8,0x05,0x0a,0xb4,0x36,0x0b,0x0b,0x36,0x32,0xb8, 0x05,0x0a,0xb2,0x11,0x00,0x03,0xb8,0x04,0xfb,0xb7,0x27,0x1f,0x24,0x2f,0x24,0x02,0x24,0x2d,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x16,0x01,0x16,0x36,0x35,0x35,0x1d,0x1d,0x1c,0xbb,0x04,0xfb,0x00,0x1e,0x00,0x0b,0x05,0x03,0x00,0x3f,0x33,0xed,0x32,0x11,0x33,0x11,0x33,0x2f,0x5d,0xed,0x2f,0x5d,0x33,0xed,0x32,0x01,0x2f,0xed,0x2f,0x33, 0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x11,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x36,0x36,0x37,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x33,0x15,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x01,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x26,0x26,0x6c,0xad,0x52,0x45,0x66,0x48,0x2c,0x0c, 0x05,0x0b,0x04,0x75,0x5c,0x92,0x66,0x36,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x2d,0x35,0x07,0xbc,0xbd,0x08,0x3e,0x74,0xab,0x75,0x5b,0xac,0x64,0x02,0x8d,0x0d,0x25,0x2c,0x34,0x1c,0x1d,0x37,0x2c,0x1b,0x7c,0x87,0x65,0x04,0x0e,0xfe,0xf9,0x2c,0x23,0x21,0x39,0x4c,0x2c,0x13,0x3d,0x26,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54, 0x56,0x48,0xbf,0x6d,0xa7,0x66,0xb5,0x88,0x50,0x26,0x2e,0x02,0xe1,0x26,0x4d,0x3d,0x26,0x26,0x3c,0x4c,0x26,0x4b,0x52,0x27,0x4e,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x01,0xf2,0x03,0x0f,0x02,0x06,0x0e,0x6f,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x03,0x0f,0x02,0x06,0x09,0x3b,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6, 0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x00,0x03,0xff,0xd4,0x05,0x20,0x02,0x33,0x07,0xa1,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x60,0xb2,0x16,0x16,0x19,0xb8,0x05,0x0b,0xb5,0x12,0x15,0x15,0x12,0x12,0x03,0xb8,0x05,0x0d,0x40,0x09,0x2c,0x2f,0x2f,0x2c,0x0a,0x1f,0x23,0x23,0x26, 0xb8,0x05,0x0d,0xb5,0x1f,0x22,0x22,0x1f,0x00,0x31,0xbb,0x04,0xfd,0x00,0x32,0x00,0x35,0x04,0xfd,0xb4,0x36,0x23,0x0a,0x1c,0x29,0xb8,0x04,0xfd,0xb1,0x0d,0x06,0x00,0x2f,0x33,0xfd,0x32,0x39,0xd6,0xd6,0xfd,0xd6,0xed,0x01,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x11,0x39,0x2f,0x33,0x2f,0x10,0xed,0x32,0x11,0x33,0x2f,0x10,0xed, 0x32,0x2f,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x01,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x02,0x2f,0x02,0x02,0x63, 0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0xfe,0x36,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37, 0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0x01,0x6b,0x58,0x57,0x58,0x00,0x03,0xff,0xd8,0x06,0x60,0x02,0x2c,0x08,0x21,0x00,0x1e,0x00,0x35,0x00,0x41,0x00,0x4c,0xb4,0x14,0x39,0x04,0x32,0x11,0xbe,0x05,0x0d,0x00,0x39,0x00,0x22,0x05,0x0d,0x00,0x32,0x00,0x3f,0x05,0x0d,0xb4,0x07,0x36,0x1b,0x1e, 0x0c,0xb8,0x04,0xfd,0x40,0x0a,0x3c,0x00,0x1f,0x35,0x04,0x14,0x27,0x2d,0x2d,0x00,0xb9,0x05,0x00,0x00,0x1e,0x00,0x2f,0xed,0x32,0x2f,0xdd,0x39,0x39,0xc0,0x32,0x10,0xd4,0xed,0x11,0x39,0x39,0x01,0x2f,0xed,0x2f,0xed,0x2f,0xed,0x11,0x39,0x11,0x39,0x31,0x30,0x13,0x36,0x36,0x37,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e, 0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x26,0x27,0x06,0x06,0x07,0x13,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x01,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x88,0x2d,0x58,0x2e,0x01,0x2e,0x2b,0x1a,0x2d,0x3c,0x22,0x24,0x3d,0x2c,0x19, 0x2a,0x23,0x0e,0x18,0x0b,0x21,0x1b,0x2e,0x15,0x3e,0x84,0x3f,0x0b,0x30,0x3a,0x05,0x06,0x0d,0x06,0x1e,0x2b,0x31,0x22,0x17,0x28,0x1d,0x11,0x54,0x4c,0x01,0x17,0x22,0x27,0x2e,0x23,0x23,0x2f,0x31,0x06,0xb0,0x04,0x0e,0x13,0x05,0x1f,0x4e,0x2d,0x24,0x3b,0x2b,0x18,0x18,0x2b,0x39,0x21,0x33,0x4c,0x21,0x08,0x09,0x05,0x4a,0x0a,0x15, 0x0b,0x21,0x1d,0x05,0x01,0x86,0x17,0x41,0x2a,0x0e,0x14,0x02,0x02,0x28,0x21,0x26,0x2c,0x17,0x27,0x35,0x1e,0x4d,0x74,0x24,0xfe,0xe1,0x18,0x3a,0x21,0x22,0x29,0x27,0x20,0x26,0x3a,0x00,0x00,0x04,0xff,0xd4,0x05,0x20,0x02,0x33,0x08,0x29,0x00,0x2f,0x00,0x4e,0x00,0x65,0x00,0x71,0x00,0xaa,0x40,0x0a,0x44,0x2c,0x34,0x03,0x12,0x52, 0x52,0x16,0x16,0x19,0xb8,0x05,0x0b,0x40,0x0b,0x12,0x62,0x62,0x12,0x15,0x15,0x12,0x12,0x41,0x41,0x03,0xb8,0x05,0x0d,0x40,0x0d,0x2c,0x69,0x69,0x2c,0x2f,0x2f,0x2c,0x0a,0x26,0x1f,0x6f,0x6f,0x37,0xb8,0x05,0x0d,0xb3,0x26,0x23,0x23,0x26,0xb8,0x05,0x0d,0x40,0x09,0x1f,0x22,0x22,0x1f,0x00,0x4b,0x66,0x4e,0x3c,0xb8,0x04,0xfd,0x40, 0x0a,0x6c,0x30,0x4f,0x65,0x34,0x44,0x57,0x5d,0x5d,0x30,0xb8,0x05,0x00,0xb6,0x4e,0x2f,0x16,0x23,0x0a,0x1c,0x29,0xb8,0x04,0xfd,0xb1,0x0d,0x06,0x00,0x2f,0x33,0xfd,0x32,0x39,0xd6,0x32,0x32,0xde,0xed,0x32,0x2f,0xcd,0x39,0x39,0xc0,0x32,0x10,0xd4,0xed,0x11,0x39,0x39,0x01,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x2f,0x10,0xe4,0x33, 0x2f,0x11,0x12,0x39,0x2f,0x33,0x2f,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x32,0x11,0x33,0x2f,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x32,0x2f,0x11,0x12,0x39,0x11,0x39,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36, 0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x25,0x36,0x36,0x37,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x26,0x27,0x06,0x06,0x07,0x13,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x2e,0x02, 0x35,0x34,0x36,0x37,0x01,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02,0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0xfe,0xb9,0x2d,0x58,0x2e,0x01,0x2e,0x28,0x1c,0x2d,0x3a,0x1f, 0x1f,0x3b,0x2e,0x1c,0x28,0x23,0x0e,0x18,0x0b,0x21,0x1b,0x2e,0x15,0x3e,0x84,0x3f,0x0b,0x30,0x3a,0x05,0x06,0x0d,0x06,0x1e,0x2b,0x31,0x22,0x17,0x28,0x1d,0x11,0x54,0x4c,0x01,0x17,0x22,0x25,0x32,0x1e,0x1d,0x31,0x2e,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30, 0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0x8e,0x04,0x0e,0x13,0x05,0x1d,0x49,0x2b,0x27,0x3a,0x27,0x13,0x13,0x25,0x38,0x25,0x30,0x48,0x20,0x08,0x09,0x05,0x4a,0x0a,0x15,0x0b,0x21,0x1b,0x05,0x01,0x78,0x15,0x3d,0x26,0x0e,0x12,0x02,0x02,0x28,0x21,0x26,0x2c,0x16,0x26,0x33,0x1d,0x4b,0x70, 0x23,0xfe,0xed,0x16,0x35,0x1f,0x23,0x23,0x23,0x21,0x23,0x33,0x00,0x02,0xff,0xd4,0x05,0x20,0x02,0x33,0x08,0x04,0x00,0x2f,0x00,0x33,0x00,0x5e,0xb4,0x0a,0x31,0x23,0x23,0x30,0xbb,0x05,0x0b,0x00,0x31,0x00,0x26,0x05,0x0d,0xb5,0x22,0x22,0x31,0x16,0x16,0x19,0xb8,0x05,0x0b,0xb5,0x12,0x15,0x15,0x12,0x12,0x03,0xb8,0x05,0x0d,0x40, 0x0d,0x2c,0x2f,0x2f,0x2c,0x00,0x33,0x30,0x2f,0x16,0x23,0x0a,0x1c,0x29,0xb8,0x04,0xfd,0xb1,0x0d,0x06,0x00,0x2f,0x33,0xfd,0x32,0x39,0xd6,0x32,0x32,0xd6,0xcd,0x01,0x2f,0x2f,0x33,0x2f,0x10,0xed,0x32,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x2f,0x33,0x2f,0xed,0x10,0xed,0x32,0x2f,0x11,0x39,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x23,0x11,0x33,0x02,0x2f,0x02,0x02,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x04,0x02, 0x60,0x05,0x02,0x26,0x2d,0x2d,0x22,0x02,0x61,0x01,0x01,0x22,0x2d,0x30,0x24,0x04,0x02,0x92,0x74,0x74,0x06,0x36,0x12,0x23,0x0d,0x67,0x6d,0x1f,0x20,0x20,0x1f,0x20,0x36,0x49,0x29,0x18,0x28,0x0e,0x27,0x20,0x08,0x30,0x37,0x37,0x36,0x12,0x29,0x0e,0x0d,0x2c,0x0f,0x37,0x37,0x38,0x31,0x14,0x2c,0x0d,0x64,0x01,0x6a,0x00,0x00,0x03, 0xff,0x6c,0x05,0x26,0x02,0x03,0x08,0x58,0x00,0x18,0x00,0x3d,0x00,0x4b,0x00,0x69,0xb2,0x3a,0x11,0x37,0xb8,0x05,0x0d,0xb5,0x3e,0x09,0x09,0x3e,0x0e,0x11,0xb8,0x05,0x0d,0xb3,0x2b,0x06,0x06,0x46,0xb8,0x05,0x0d,0xb7,0x2d,0x0e,0x09,0x0a,0x25,0x22,0x1f,0x32,0xb8,0x04,0xfd,0xb3,0x41,0x3a,0x49,0x28,0xb8,0x04,0xfd,0xb4,0x1f,0x16, 0x18,0x18,0x16,0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c,0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x10,0xd6,0xfd,0x32,0x39,0xd4,0xed,0x11,0x39,0x39,0x11,0x12,0x39,0x01,0x2f,0xed,0x39,0x2f,0x39,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15, 0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x37,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x07,0x27,0x37,0x16,0x16,0x33,0x32,0x37,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36, 0x36,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x02,0x17,0x28,0x11,0x19,0x2f,0x15,0x42,0x5e,0x25,0x61,0x36,0x99,0x31,0x5b,0x34,0x10,0x0f,0x01,0x36,0x1e,0x31,0x3f,0x20,0x20,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x02,0x33,0x1f,0x0f,0x1f,0x18,0x0f,0x23,0x1a, 0x2f,0x3b,0x06,0x1e,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0x2b,0x11,0x22,0x11,0x07,0x06,0x34,0x2a,0x59,0x3b,0x8e,0x3c,0x3e,0x03,0x02,0x42,0x41,0x24,0x38,0x27,0x14,0x14,0x27,0x3a,0x27,0x3f,0x56,0x19,0x0b,0x10,0x08,0xcd,0x26,0x22,0x09,0x11,0x19,0x11,0x1b,0x38,0x1b,0x0e,0x35,0x00, 0x00,0x02,0x00,0x05,0x05,0x26,0x02,0x01,0x07,0x3b,0x00,0x18,0x00,0x1c,0x00,0x3f,0xb1,0x0e,0x06,0xb8,0x05,0x0d,0xb7,0x11,0x11,0x1d,0x1a,0x0e,0x09,0x0a,0x1a,0xb8,0x04,0xfd,0xb4,0x1b,0x16,0x18,0x18,0x16,0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c,0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f, 0x10,0xd6,0xed,0x11,0x12,0x39,0x01,0x2f,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x25,0x21,0x15,0x21,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21, 0xfe,0x92,0x01,0xfc,0xfe,0x04,0x06,0x1e,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0xb8,0x58,0x00,0x03,0xff,0xf8,0x05,0x26,0x02,0x03,0x08,0x58,0x00,0x18,0x00,0x3c,0x00,0x4a,0x00,0x65,0xb3,0x39,0x18,0x11,0x36,0xb8,0x05,0x0d,0xb5,0x3d,0x09,0x09,0x3d,0x0e,0x11,0xb8,0x05,0x0d,0xb3,0x2a, 0x06,0x06,0x45,0xb8,0x05,0x0d,0xb4,0x2c,0x0e,0x09,0x0a,0x31,0xb8,0x04,0xfd,0xb3,0x40,0x39,0x48,0x26,0xb8,0x04,0xfd,0xb4,0x1f,0x16,0x18,0x18,0x16,0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c,0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x10,0xd6,0xfd,0x32,0x39,0xd4,0xed,0x11,0x12,0x39,0x01, 0x2f,0xed,0x39,0x2f,0x39,0xed,0x39,0x2f,0x33,0x2f,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x37,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x32,0x37,0x37,0x26,0x35,0x34,0x3e,0x02, 0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x02,0x17,0x28,0x11,0x18,0x2f,0x14,0x3c,0x65,0x31,0x12,0x33,0x5a,0x39,0x01,0x0b,0x06,0x01,0x34, 0x1e,0x31,0x3e,0x21,0x20,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x02,0x33,0x1f,0x0f,0x1f,0x18,0x0f,0x23,0x1a,0x30,0x3a,0x06,0x1e,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0x2b,0x11,0x22,0x11,0x05,0x03,0x0e,0x0e,0x53,0x0d,0x0f,0x01,0x02,0x40,0x40,0x24,0x39,0x27,0x14,0x14,0x27,0x3a, 0x27,0x3f,0x56,0x19,0x0b,0x10,0x08,0xcd,0x26,0x22,0x09,0x11,0x1a,0x10,0x1a,0x3a,0x1a,0x0e,0x36,0x00,0x00,0x03,0x00,0x05,0x05,0x26,0x02,0x01,0x07,0xea,0x00,0x18,0x00,0x1c,0x00,0x20,0x00,0x41,0xb1,0x0e,0x06,0xb8,0x05,0x0d,0xb4,0x11,0x0e,0x09,0x0a,0x1a,0xbb,0x04,0xfd,0x00,0x1b,0x00,0x1e,0x04,0xfd,0xb4,0x1f,0x16,0x18,0x18, 0x16,0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c,0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x10,0xd6,0xfd,0xd6,0xed,0x11,0x12,0x39,0x01,0x2f,0xed,0x39,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01, 0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xfe,0x92,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04,0x06,0x1e,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0x01,0x67,0x58,0x57,0x58,0x00,0x00,0x03, 0x00,0x49,0x05,0x26,0x01,0xbd,0x08,0x42,0x00,0x17,0x00,0x2b,0x00,0x37,0x00,0x55,0xbc,0x00,0x1d,0x05,0x0d,0x00,0x2f,0x00,0x06,0x05,0x0d,0xb3,0x0e,0x10,0x10,0x35,0xb8,0x05,0x0d,0xb5,0x0b,0x27,0x0e,0x09,0x0a,0x18,0xbb,0x04,0xfd,0x00,0x32,0x00,0x2c,0x04,0xfd,0xb4,0x22,0x15,0x17,0x17,0x15,0xb8,0x05,0x01,0xb4,0x03,0x09,0x0c, 0x0c,0x09,0xb9,0x05,0x01,0x00,0x0a,0x00,0x2f,0xed,0x32,0x2f,0x10,0xd6,0xed,0x32,0x2f,0x10,0xd6,0xfd,0xd6,0xed,0x11,0x12,0x39,0x01,0x2f,0x33,0xed,0x39,0x2f,0x39,0xed,0x2f,0xed,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x03,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x2d,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x70,0x28,0x45,0x31,0x1c,0x1c,0x31,0x45,0x28,0x2a,0x45,0x30,0x1b,0x1b,0x31,0x44,0x2a,0x30,0x30,0x30, 0x30,0x30,0x30,0x30,0x06,0x1e,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x33,0x3a,0x21,0x37,0x28,0x16,0x06,0x01,0xbf,0x1c,0x31,0x42,0x26,0x26,0x42,0x30,0x1c,0x1c,0x30,0x42,0x26,0x26,0x42,0x31,0x1c,0xfe,0xee,0x33,0x2a,0x29,0x35,0x35,0x29,0x2a,0x33,0x00,0x00,0x03,0x00,0x05,0xfe,0x00,0x02,0x01,0x00,0xc1,0x00,0x18,0x00,0x1c, 0x00,0x20,0x00,0x3d,0xb1,0x0e,0x06,0xbe,0x05,0x0d,0x00,0x11,0x00,0x1b,0x04,0xfd,0x00,0x1a,0x00,0x1f,0x04,0xfd,0xb2,0x1e,0x0e,0x0a,0xb8,0x04,0xfd,0xb4,0x09,0x0c,0x0c,0x09,0x03,0xb8,0x04,0xfd,0xb3,0x16,0x18,0x18,0x16,0x00,0x2f,0x33,0x2f,0x10,0xfd,0xc6,0x32,0x2f,0x10,0xfd,0x39,0xd6,0xfd,0xd6,0xed,0x01,0x2f,0xed,0x39,0x31, 0x30,0x25,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xfe,0x92,0x01,0xfc,0xfe,0x04,0x01,0xfc,0xfe,0x04, 0x56,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0xfd,0x9d,0x58,0x01,0x07,0x58,0x00,0x00,0x02,0x00,0x05,0xfe,0xaf,0x02,0x01,0x00,0xc1,0x00,0x18,0x00,0x1c,0x00,0x35,0xb1,0x0e,0x06,0xbb,0x05,0x0d,0x00,0x11,0x00,0x1b,0x04,0xfd,0xb2,0x1a,0x0e,0x0a,0xb8,0x04,0xfd,0xb4,0x09,0x0c,0x0c,0x09, 0x03,0xb8,0x04,0xfd,0xb3,0x16,0x18,0x18,0x16,0x00,0x2f,0x33,0x2f,0x10,0xfd,0xc6,0x32,0x2f,0x10,0xfd,0x39,0xd6,0xed,0x01,0x2f,0xed,0x39,0x31,0x30,0x25,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0x21,0x15,0x21,0x01,0x73,0x0d,0x1d,0x10,0x2d,0x3e, 0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xfe,0x92,0x01,0xfc,0xfe,0x04,0x56,0x03,0x04,0x23,0x28,0x53,0x61,0x5b,0x05,0x1a,0x36,0x1d,0x21,0x37,0x28,0x16,0x06,0xfe,0x4c,0x58,0xff,0xff,0x00,0x4f,0xfe,0xf8,0x01,0x64,0x00,0xe4,0x00,0x06,0x00,0x0f,0x28,0x00,0x00,0x01,0x00,0xab,0xff,0xea,0x07,0x59, 0x03,0x0f,0x00,0x2e,0x00,0x3c,0xb1,0x0c,0x01,0xb8,0x05,0x0a,0xb3,0x2d,0x2d,0x30,0x20,0xb8,0x05,0x0a,0x40,0x0a,0x19,0x2f,0x2e,0x01,0x2e,0x2f,0x1d,0x01,0x1d,0x11,0xb8,0x05,0x03,0xb2,0x0c,0x28,0x06,0xba,0x04,0xfb,0x00,0x07,0x05,0x03,0x00,0x3f,0xed,0x32,0x39,0x3f,0x2f,0x5d,0x2f,0x5d,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39, 0x31,0x30,0x01,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x11,0x06,0x9f,0x0c,0x27,0x49,0x3e,0x16,0x61,0x70,0x20,0x04,0x2c,0x80,0x9d,0xb4,0x60,0x88,0xe1,0xb5,0x88,0x30,0x40, 0x30,0x12,0x0b,0x9a,0x09,0x11,0x1f,0x2f,0x1d,0x5c,0x92,0xd1,0x93,0x80,0xc0,0x7f,0x3f,0x03,0x0f,0xfe,0x89,0x43,0x60,0x3e,0x1e,0xa7,0x3a,0x40,0x2f,0x35,0x19,0x05,0x04,0x15,0x2c,0x29,0x37,0x98,0x58,0x3d,0x70,0x33,0x2b,0x65,0x36,0x3c,0x63,0x23,0x15,0x1b,0x0f,0x05,0x0a,0x29,0x53,0x48,0x01,0xae,0x00,0x01,0xff,0xba,0xff,0xf2, 0x01,0xf2,0x03,0x0f,0x00,0x16,0x00,0x1e,0xbe,0x00,0x08,0x05,0x0a,0x00,0x05,0x00,0x00,0x04,0xfb,0x00,0x0f,0x05,0x03,0xb3,0x2f,0x07,0x01,0x07,0x00,0x2f,0x5d,0x3f,0xed,0x01,0x2f,0xed,0x31,0x30,0x37,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x99,0x2e,0x47,0x30,0x18,0x9c,0x1c, 0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x3d,0x4b,0x6e,0x4c,0x31,0x1a,0x0a,0x34,0x20,0x20,0x33,0x00,0x00,0x02,0x00,0x9b,0xfd,0xff,0x06,0x03,0x02,0xb7,0x00,0x30,0x00,0x41,0x00,0x65,0xb2,0x13,0x13,0x10,0xb8,0x05,0x0a,0xb4,0x3f,0x30,0x30,0x3f,0x3b,0xb8,0x05,0x0a,0xb6,0x05, 0x3f,0x05,0x3f,0x05,0x43,0x24,0xb8,0x05,0x0a,0xb5,0x1d,0x2f,0x21,0x01,0x21,0x29,0xb8,0x04,0xfb,0x40,0x0a,0x1f,0x18,0x2f,0x18,0x02,0x18,0x3f,0x3e,0x3e,0x10,0xbd,0x04,0xfb,0x00,0x00,0x00,0x12,0x05,0x03,0x00,0x36,0x04,0xfb,0xb3,0x2f,0x0a,0x01,0x0a,0x00,0x2f,0x5d,0xed,0x3f,0x33,0xed,0x32,0x11,0x33,0x2f,0x5d,0xed,0x2f,0x5d, 0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x33,0x15,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x37,0x03,0x2e,0x03,0x23,0x22, 0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x26,0x26,0x04,0x36,0x5c,0x91,0x66,0x36,0x30,0x55,0x73,0x44,0x48,0x78,0x36,0x2d,0x34,0x07,0xbc,0xbb,0x0b,0x54,0x99,0xe0,0x97,0xa1,0xdb,0x87,0x3b,0x0f,0x0e,0x97,0x0b,0x0c,0x2b,0x64,0xa5,0x7a,0x60,0x8d,0x63,0x3e,0x24,0x10,0x03,0x1d,0x0d,0x25,0x2c,0x34,0x1c,0x1d,0x37,0x2c,0x1a,0x7c,0x86, 0x65,0x04,0x0e,0x0e,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x48,0xc0,0x6d,0xa7,0x7f,0xbc,0x7b,0x3d,0x41,0x7c,0xb7,0x77,0x3f,0x8c,0x4e,0x4b,0x7d,0x36,0x5f,0x84,0x54,0x26,0x19,0x2d,0x3e,0x49,0x52,0x2b,0x01,0x42,0x26,0x4d,0x3d,0x26,0x26,0x3c,0x4c,0x26,0x4b,0x52,0x27,0x4e,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49, 0x03,0x62,0x02,0x06,0x09,0x3c,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x03,0x62,0x02,0x06,0x09,0x3d,0x00,0x00,0xff,0xff,0x00,0x49,0x04,0x7c,0x01,0xa2,0x05,0xe9,0x00,0x07,0x09,0x7e,0x00,0x00,0xfe,0x00,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x3e,0x02,0x26,0x0e,0x5e,0x00,0x00,0x01,0x07,0x09,0x7e,0x02,0x01, 0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xe7,0xfd,0xff,0x04,0x02,0x05,0x63,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x09,0x7e,0x02,0x01,0xfd,0x55,0x01,0x07,0x09,0x30,0x00,0x28,0xfd,0x55,0x00,0x0e,0xb6,0x04,0x03,0x02,0x2f,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff, 0xff,0xba,0xff,0xf2,0x03,0xa3,0x05,0x3e,0x00,0x26,0x0e,0x6f,0x00,0x00,0x01,0x07,0x09,0x7e,0x02,0x01,0xfd,0x55,0x00,0x0a,0xb4,0x01,0x2f,0x2d,0x01,0x2d,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x05,0x3e,0x00,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x09,0x7e,0x02,0x01,0xfd,0x55,0x01,0x07,0x09,0x21,0x02,0xac, 0x00,0x00,0x00,0x0a,0xb4,0x01,0x2f,0x36,0x01,0x36,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x05,0xb9,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x57,0x02,0xad,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x06,0x32,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0x72,0x03,0xd0,0xff,0xff, 0x00,0xab,0xff,0xea,0x07,0x59,0x05,0xca,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x52,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xca,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07, 0x0f,0x52,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0xab,0xfe,0xee,0x07,0x59,0x04,0xb2,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x27,0x0f,0x5b,0x02,0xad,0x00,0xef,0x00,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0xff,0xff, 0xff,0xba,0xff,0x05,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x5b,0x00,0x1a,0x01,0x06,0x00,0x07,0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x05,0xca,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xca, 0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff, 0x00,0xab,0xff,0xea,0x07,0x59,0x05,0xca,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x56,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xca,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07, 0x0f,0x56,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x56,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0x16,0x02,0x26,0x0e,0x2d,0x00,0x00,0x01,0x07,0x09,0x7e,0x01,0x56,0xfd,0x2d,0x00,0x0a,0xb4,0x01,0x2f,0x4c,0x01,0x4c,0x00,0x11, 0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0x79,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0x03,0xb1,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0xfe,0xab,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d, 0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x56,0xfd,0xce,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0x79,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0x03,0xb1,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x56,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9, 0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x07,0x0f,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x1d,0x04,0xad,0xff,0xff,0x00,0x52,0xfe,0xf4,0x04,0x02,0x03,0xba,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x5b,0x00,0xab, 0x00,0xf5,0xff,0xff,0x00,0x52,0xfe,0xa6,0x04,0x02,0x03,0xba,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0x52,0xfe,0xa6,0x04,0x02,0x07,0x0f,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x27,0x0f,0x57,0x01,0x1d,0x04,0xad,0x00,0x07,0x0f,0x50,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0x52,0xff,0xea, 0x04,0x02,0x05,0x5d,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x1d,0x04,0xad,0xff,0xff,0x00,0x52,0xfe,0xa6,0x04,0x02,0x03,0xba,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x06,0x75,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x1d, 0x04,0xad,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x06,0x75,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x1d,0x04,0xad,0xff,0xff,0x00,0x52,0xff,0xea,0x04,0x02,0x06,0x75,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0x1d,0x04,0xad,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x04,0x07,0x02,0x26,0x0e,0x31, 0x00,0x00,0x00,0x27,0x0f,0x50,0x05,0x50,0x03,0x57,0x00,0x07,0x0f,0x50,0x05,0x50,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x06,0xae,0x04,0x07,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0xa4,0x03,0x57,0x00,0x07,0x0f,0x50,0x02,0xa4,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x09,0x5a,0x03,0x0f,0x02,0x26,0x0e,0x31, 0x00,0x00,0x00,0x07,0x0f,0x54,0x05,0x50,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x06,0xae,0x03,0x0f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xa4,0xfd,0xce,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x09,0x5a,0x05,0x1f,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x27,0x0f,0x54,0x05,0x50,0xfd,0xce,0x00,0x07,0x0f,0x53,0x05,0x46, 0x03,0x57,0xff,0xff,0xff,0xba,0xfd,0xc9,0x06,0xae,0x05,0x1f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x27,0x0f,0x54,0x02,0xa4,0xfd,0xce,0x00,0x07,0x0f,0x53,0x02,0xa4,0x03,0x57,0xff,0xff,0x00,0x9b,0xfd,0xff,0x0a,0xb0,0x03,0x3c,0x02,0x26,0x0e,0x35,0x00,0x00,0x00,0x07,0x0f,0x51,0x06,0x3c,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6, 0x08,0x04,0x03,0x3c,0x02,0x26,0x0e,0x36,0x00,0x00,0x00,0x07,0x0f,0x51,0x03,0x86,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x0a,0xb0,0x05,0xca,0x02,0x26,0x0e,0x35,0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0xca,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xea,0x08,0x04,0x05,0xca,0x02,0x26,0x0e,0x36,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x1e, 0x04,0x02,0xff,0xff,0x00,0x19,0xff,0xea,0x06,0xae,0x05,0xec,0x02,0x26,0x0e,0x39,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xe5,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xed,0x05,0xf5,0x05,0xec,0x02,0x26,0x0e,0x3a,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xe5,0x04,0x02,0xff,0xff,0xff,0xba,0xff,0xed,0x06,0xae,0x05,0xec,0x02,0x26,0x0e,0x3b, 0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xe5,0x04,0x02,0x00,0x02,0x00,0xab,0xff,0xea,0x08,0x04,0x03,0x62,0x00,0x41,0x00,0x55,0x00,0x5c,0xb1,0x10,0x0d,0xbb,0x05,0x0a,0x00,0x42,0x00,0x4e,0x05,0x0a,0xb6,0x00,0x42,0x00,0x42,0x00,0x57,0x2f,0xb8,0x05,0x0a,0xb5,0x28,0x2f,0x2c,0x01,0x2c,0x1f,0xb8,0x05,0x03,0x40,0x09,0x53,0x1a,0x05, 0x14,0x3c,0x3c,0x39,0x39,0x13,0xbc,0x04,0xfb,0x00,0x14,0x05,0x03,0x00,0x49,0x04,0xfb,0xb3,0x2f,0x05,0x01,0x05,0x00,0x2f,0x5d,0xed,0x3f,0xed,0x32,0x11,0x33,0x2f,0x11,0x12,0x39,0x39,0x3f,0x2f,0x5d,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x31,0x30,0x01,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03, 0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x05,0x33,0x32,0x36,0x37,0x37,0x2e,0x03,0x05,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x04,0xb0,0x30,0x55,0x74,0x44, 0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x38,0x72,0x43,0x16,0x2c,0x60,0x5f,0x5b,0x27,0x33,0x77,0x82,0x8a,0x45,0xb9,0x86,0xd6,0xaa,0x7f,0x2e,0x3f,0x30,0x12,0x0b,0x9a,0x09,0x11,0x20,0x2e,0x17,0x39,0x4f,0x6d,0x96,0xc7,0x82,0x5b,0x8e,0x3b,0x02,0x4a,0x60,0x38,0x15,0x01,0xfe,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b, 0x1b,0x19,0x41,0x73,0x5a,0x23,0x1b,0x01,0xd1,0x40,0x8d,0x77,0x4d,0x53,0x56,0x21,0x4a,0x53,0x5a,0x30,0x42,0x63,0x27,0x09,0x03,0xa7,0x07,0x0e,0x16,0x0f,0x18,0x1a,0x0d,0x03,0x05,0x15,0x2d,0x27,0x36,0x99,0x58,0x3d,0x70,0x33,0x2b,0x65,0x36,0x3c,0x66,0x20,0x10,0x17,0x0f,0x08,0x05,0x01,0x02,0x03,0x06,0x1e,0x44,0x4d,0x55,0x35, 0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x1f,0x3e,0x43,0x4a,0x2b,0x18,0x4d,0x00,0xff,0xff,0x00,0xab,0xfe,0xa6,0x08,0x04,0x03,0x62,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x50,0x05,0x10,0xfe,0xab,0xff,0xff,0x00,0xab,0xfe,0xa6,0x08,0x04,0x05,0x24,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x27,0x0f,0x50,0x04,0xd7, 0x04,0x74,0x00,0x07,0x0f,0x50,0x05,0x10,0xfe,0xab,0xff,0xff,0x00,0xab,0xff,0xea,0x08,0x04,0x06,0x3c,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x53,0x04,0xd7,0x04,0x74,0xff,0xff,0x00,0xab,0xfd,0xc9,0x08,0x04,0x03,0x62,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x54,0x05,0x10,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea, 0x08,0x04,0x06,0x3c,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x56,0x04,0xd7,0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x06,0x03,0x04,0x79,0x02,0x26,0x0e,0x70,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0xd4,0x03,0xc9,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x05,0x24,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5, 0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x05,0x24,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x06,0x03,0x05,0x91,0x02,0x26,0x0e,0x70,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xd4,0x03,0xc9,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x06,0x3c,0x02,0x26,0x09,0x3c, 0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x3c,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x04,0x74,0x00,0x01,0x00,0xab,0xff,0xea,0x07,0x59,0x06,0x02,0x00,0x43,0x00,0x49,0xb4,0x13,0x05,0x05,0x1b,0x37,0xb8,0x05,0x0a,0x40,0x0c,0x30,0x1b,0x2f,0x34,0x01, 0x34,0x0a,0x0e,0x0b,0x03,0x0c,0x28,0xb8,0x05,0x03,0xb5,0x3f,0x20,0x20,0x1f,0x1f,0x1a,0xba,0x04,0xfb,0x00,0x1b,0x05,0x03,0xb4,0x0d,0x2f,0x0c,0x01,0x0c,0x00,0x2f,0x5d,0x33,0x3f,0xed,0x32,0x2f,0x33,0x2f,0x33,0x3f,0x12,0x17,0x39,0x2f,0x5d,0x01,0x2f,0x2f,0xed,0x12,0x39,0x10,0xcd,0x31,0x30,0x25,0x3e,0x03,0x35,0x34,0x2e,0x02, 0x27,0x35,0x01,0x15,0x01,0x1e,0x03,0x17,0x1e,0x05,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x05,0x4b,0x25,0x32,0x1c,0x0c,0x58,0xa4,0xe7,0x90,0x03,0x4b,0xfd,0x66,0xad,0xdd,0x85,0x40, 0x10,0x03,0x0b,0x14,0x21,0x34,0x49,0x32,0x16,0x59,0x8d,0x2c,0x05,0x22,0x53,0x44,0x27,0x5d,0x74,0x90,0x5a,0x76,0xc2,0x9b,0x78,0x2c,0x3f,0x30,0x12,0x0b,0x9a,0x09,0x11,0x1f,0x2f,0x1a,0x4f,0x7b,0xb1,0x7c,0x4f,0x80,0x66,0x4f,0xad,0x0a,0x1d,0x26,0x2d,0x1a,0x4c,0x8c,0x86,0x85,0x46,0x76,0x02,0x22,0xb0,0xfe,0x5f,0x52,0x92,0x8b, 0x8a,0x4a,0x0f,0x2b,0x30,0x2e,0x26,0x17,0xa7,0x4a,0x55,0x2d,0x3d,0x15,0x0c,0x10,0x09,0x03,0x06,0x16,0x2c,0x26,0x37,0x98,0x58,0x3d,0x70,0x33,0x2b,0x65,0x36,0x3c,0x63,0x23,0x13,0x1a,0x10,0x07,0x02,0x05,0x0a,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x02,0x02,0x06,0x0e,0x56,0x00,0x00,0x00,0x01,0x00,0x19,0xff,0xea, 0x08,0xaf,0x04,0x19,0x00,0x48,0x00,0x52,0xb9,0x00,0x25,0x05,0x0a,0xb2,0x1a,0x3b,0x30,0xb8,0x05,0x0a,0xb4,0x11,0x0e,0x0e,0x11,0x14,0xb8,0x04,0xfb,0xb7,0x2b,0x2b,0x1f,0x3b,0x41,0x35,0x35,0x07,0x41,0x09,0x04,0xfb,0x00,0x41,0x05,0x03,0x00,0x32,0x04,0xfb,0x00,0x36,0x05,0x03,0x00,0x20,0x04,0xfb,0xb3,0x2f,0x1f,0x01,0x1f,0x00, 0x2f,0x5d,0xed,0x3f,0xed,0x3f,0xed,0x32,0x2f,0x11,0x39,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x39,0x2f,0xed,0x31,0x30,0x37,0x1e,0x05,0x33,0x32,0x3e,0x04,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x22,0x2e,0x02,0x35,0x34,0x36,0x36,0x24,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x21,0x32,0x1e,0x02,0x15,0x14, 0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x07,0x06,0x04,0x21,0x22,0x2e,0x04,0x27,0x19,0x25,0x83,0xaa,0xc7,0xd4,0xd8,0x65,0x72,0xbb,0x9d,0x83,0x72,0x68,0x33,0x03,0x03,0x5d,0x55,0xfb,0xd3,0x56,0x88,0x5e,0x32,0x6b,0xc7,0x01,0x1f,0xb4,0x7f,0xe3,0xac,0x65,0x19,0x4b,0x88,0x70,0x03,0xba,0x46,0x76,0x54,0x2f, 0x0b,0x20,0x3e,0x1f,0x07,0x39,0x4b,0x1a,0x04,0x0c,0x21,0x14,0x76,0xfe,0x25,0xfe,0xa9,0x47,0xb1,0xc0,0xc2,0xae,0x8f,0x2d,0xa9,0x05,0x07,0x06,0x03,0x02,0x01,0x01,0x02,0x02,0x05,0x06,0x04,0x0b,0x12,0x0b,0x43,0x55,0x07,0x1f,0x40,0x39,0x52,0xa9,0x92,0x6f,0x19,0xa6,0x10,0x43,0x56,0x61,0x2e,0x12,0x14,0x0a,0x02,0x2e,0x4d,0x66, 0x38,0x23,0x2c,0x05,0x03,0xa7,0x2c,0x29,0x16,0x21,0x0e,0x0a,0x0e,0x01,0x02,0x03,0x06,0x07,0x05,0x00,0x00,0x01,0xff,0xba,0xff,0xea,0x08,0x04,0x04,0x19,0x00,0x4d,0x00,0x61,0xb1,0x3f,0x34,0xb8,0x05,0x0a,0x40,0x09,0x15,0x12,0x12,0x24,0x15,0x15,0x1e,0x3a,0x29,0xbb,0x05,0x0a,0x00,0x1e,0x00,0x18,0x04,0xfb,0xb3,0x2f,0x2f,0x23, 0x47,0xbc,0x05,0x03,0x00,0x3a,0x05,0x03,0x00,0x24,0x04,0xfb,0x40,0x0c,0x2f,0x23,0x01,0x23,0x3f,0x00,0x39,0x36,0x36,0x0d,0x0d,0x07,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x2f,0x33,0x2f,0x33,0x11,0x39,0x2f,0x5d,0xed,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x2f,0x39,0x33,0x2f,0x10,0xed, 0x39,0x31,0x30,0x17,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x16,0x04,0x33,0x32,0x3e,0x02,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x22,0x2e,0x02,0x35,0x34,0x36,0x36,0x24,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x21,0x32,0x1e,0x02,0x15,0x14,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x07, 0x0e,0x02,0x04,0x23,0x22,0x2e,0x04,0x32,0x32,0x23,0x23,0x23,0x23,0x3b,0x1e,0xa2,0xef,0x01,0x2e,0xab,0x9d,0xf6,0xc3,0x99,0x40,0x03,0x03,0x5d,0x55,0xfb,0xd3,0x56,0x88,0x5e,0x32,0x6b,0xc7,0x01,0x1f,0xb4,0x7f,0xe3,0xac,0x65,0x19,0x4b,0x88,0x70,0x03,0xba,0x46,0x76,0x54,0x2f,0x0b,0x20,0x3e,0x1f,0x07,0x39,0x4c,0x19,0x04,0x0b, 0x22,0x14,0x34,0xb6,0xec,0xfe,0xe9,0x96,0x50,0xb3,0xb2,0xa8,0x8b,0x66,0x0e,0x34,0x20,0x20,0x33,0x03,0x03,0x02,0x03,0x05,0x07,0x05,0x0b,0x12,0x0b,0x43,0x55,0x07,0x1f,0x40,0x39,0x52,0xa9,0x92,0x6f,0x19,0xa6,0x10,0x43,0x56,0x61,0x2e,0x12,0x14,0x0a,0x02,0x2e,0x4d,0x66,0x38,0x23,0x2c,0x05,0x03,0xa7,0x2d,0x28,0x15,0x22,0x0e, 0x05,0x08,0x07,0x04,0x01,0x02,0x02,0x02,0x01,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x06,0x02,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x5b,0x04,0xa6,0x05,0xb0,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x02,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x5b,0x01,0x4f,0x05,0xb0,0xff,0xff,0x00,0xab,0xff,0xea, 0x06,0xae,0x06,0xb3,0x02,0x26,0x0e,0x55,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x73,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0xb3,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xae,0x07,0xcb,0x02,0x26,0x0e,0x55,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0x73, 0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x07,0xcb,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0x39,0x06,0x03,0xff,0xff,0x00,0xab,0xfd,0xc9,0x06,0xae,0x05,0xec,0x02,0x26,0x0e,0x55,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0x74,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02,0x06,0x02,0x02,0x26,0x0e,0x56, 0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xab,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x07,0x38,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x07,0x38,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59, 0x07,0x38,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x27,0x0f,0x5b,0x04,0xa6,0x05,0xb0,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x07,0x38,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x27,0x0f,0x5b,0x01,0x4f,0x05,0xb0,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x07,0xc3, 0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00,0x01,0x07,0x0f,0x51,0x03,0x90,0x07,0x13,0x00,0x0c,0xb5,0x03,0x02,0x20,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x07,0xc3,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x26,0x0f,0x59,0x00,0x00,0x01,0x07,0x0f,0x51,0x00,0x39, 0x07,0x13,0x00,0x0c,0xb5,0x03,0x02,0x20,0x37,0x01,0x37,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x07,0x38,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x07,0x38,0x02,0x26,0x0e,0x56,0x00,0x00, 0x00,0x26,0x0f,0x59,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0xfe,0xab,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x07,0x38,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x27,0x0f,0x52,0x02,0xad,0xfd,0xce,0x00,0x07,0x0f,0x59,0x03,0x57,0x00,0x00,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x02,0x07,0x38,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x27, 0x0f,0x52,0x00,0xab,0xfd,0xce,0x00,0x06,0x0f,0x59,0x00,0x00,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x08,0xbd,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x27,0x0f,0x59,0x03,0x57,0x00,0x00,0x01,0x07,0x0f,0x53,0x03,0x57,0x06,0xf5,0x00,0x13,0x40,0x0a,0x04,0x03,0x02,0x20,0x4f,0x01,0x20,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x5d,0x35,0x35, 0x35,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x08,0xbd,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x26,0x0f,0x59,0x00,0x00,0x01,0x07,0x0f,0x53,0x00,0x00,0x06,0xf5,0x00,0x13,0x40,0x0a,0x04,0x03,0x02,0x20,0x3c,0x01,0x20,0x3c,0x01,0x3c,0x00,0x11,0x5d,0x5d,0x35,0x35,0x35,0x00,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x70,0x08,0x0e, 0x02,0x26,0x09,0x59,0x00,0x00,0x00,0x07,0x0a,0x6d,0x03,0x48,0x00,0x32,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x58,0x07,0x67,0x02,0x26,0x09,0x59,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x48,0x06,0xb7,0xff,0xff,0x00,0x9b,0xfe,0xac,0x05,0x58,0x08,0x7f,0x02,0x26,0x09,0x59,0x00,0x00,0x01,0x07,0x0f,0x53,0x03,0x48,0x06,0xb7,0x00,0x0e, 0xb6,0x01,0x03,0x02,0x20,0x34,0x01,0x34,0x00,0x11,0x5d,0x35,0x35,0x35,0x00,0x04,0x00,0x9b,0xfd,0xc4,0x05,0x58,0x05,0xec,0x00,0x28,0x00,0x2c,0x00,0x30,0x00,0x34,0x00,0x72,0xb1,0x0e,0x01,0xbb,0x05,0x0a,0x00,0x27,0x00,0x2a,0x05,0x0c,0xb2,0x29,0x29,0x2d,0xbb,0x05,0x0c,0x00,0x2e,0x00,0x31,0x05,0x0c,0x40,0x0a,0x32,0x27,0x2e, 0x32,0x32,0x2e,0x27,0x03,0x36,0x1d,0xbb,0x05,0x0a,0x00,0x16,0x00,0x29,0x04,0xfb,0xb2,0x2c,0x31,0x2d,0xb8,0x04,0xfb,0x40,0x0c,0x33,0x2f,0x30,0x01,0x30,0x1a,0x0d,0x00,0x11,0x11,0x22,0x06,0xbb,0x04,0xfb,0x00,0x07,0x05,0x03,0x00,0x00,0x00,0x2f,0x3f,0xed,0x32,0x33,0x2f,0x12,0x39,0x2f,0x2f,0x5d,0x33,0xfd,0x32,0xd6,0xed,0x01, 0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x39,0x31,0x30,0x01,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x01,0x23,0x35,0x33,0x37,0x23,0x35,0x33, 0x05,0x23,0x35,0x33,0x04,0x9e,0x0c,0x27,0x49,0x3e,0x1a,0x23,0x4c,0x48,0x3e,0x14,0x03,0x41,0xda,0xa3,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x98,0x0b,0x0b,0x24,0x4e,0x7d,0x59,0x67,0x93,0x5d,0x2b,0xfe,0xfc,0xc9,0xc9,0xab,0xc9,0xc9,0xfe,0xaa,0xc9,0xc9,0x05,0xec,0xfb,0xb0,0x43,0x61,0x40,0x1f,0xa7,0x10,0x27,0x44,0x35,0x56,0x5a,0x45, 0x7f,0xb7,0x72,0x3f,0x83,0x4b,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x2e,0x67,0xa7,0x79,0x03,0x9c,0xf7,0xd8,0xbd,0x5b,0xbd,0xbd,0xbd,0x00,0x03,0x00,0x9b,0xfd,0xf6,0x05,0x58,0x04,0xb6,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x6e,0xb1,0x11,0x03,0xb8,0x05,0x0a,0xb2,0x2c,0x34,0x30,0xb8,0x05,0x0c,0x40,0x09,0x31,0x35,0x31,0x2c,0x31, 0x2c,0x31,0x39,0x22,0xbb,0x05,0x0a,0x00,0x1b,0x00,0x34,0x04,0xfb,0xb4,0x2f,0x37,0x01,0x37,0x30,0xb8,0x04,0xfb,0x40,0x09,0x2f,0x33,0x01,0x33,0x2f,0x2f,0x01,0x2f,0x16,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x27,0x01,0x27,0x2f,0x1f,0x01,0x1f,0x11,0x09,0xba,0x04,0xfb,0x00,0x0a,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d,0x2f,0x5d,0xed, 0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x39,0x31,0x30,0x01,0x16,0x16,0x15,0x15,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35, 0x34,0x26,0x27,0x27,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x04,0x84,0x11,0x11,0x0b,0x26,0x46,0x3b,0x19,0x1b,0x3b,0x3a,0x34,0x14,0x04,0x1b,0x56,0x79,0x9e,0x63,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x94,0x5e,0x2b,0x11,0x10,0xe4,0xc9,0xc9,0xc9,0xc9,0x03,0x17,0x5d,0xac,0x51,0x21,0x47,0x62,0x3e, 0x1c,0xa7,0x09,0x16,0x28,0x1e,0x3d,0x60,0x42,0x23,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x45,0x9d,0x64,0xe2,0xbd,0xf9,0x40,0xbd,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c,0x04,0x02,0x00,0x07,0x0f,0x50, 0x00,0x83,0xfe,0xab,0x00,0x01,0x00,0x9b,0xfd,0xff,0x05,0x58,0x01,0xc1,0x00,0x2a,0x00,0x4a,0xb2,0x0b,0x00,0x0c,0xb8,0x05,0x0a,0xb5,0x2a,0x27,0x27,0x2c,0x1a,0x1d,0xb8,0x05,0x0a,0x40,0x0b,0x19,0x16,0x2f,0x2a,0x01,0x2a,0x2f,0x1a,0x01,0x1a,0x22,0xb8,0x04,0xfb,0xb7,0x1f,0x11,0x2f,0x11,0x02,0x11,0x0c,0x06,0xba,0x04,0xfb,0x00, 0x07,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d,0xed,0x2f,0x5d,0x2f,0x5d,0x01,0x2f,0x33,0xed,0x32,0x12,0x39,0x2f,0x33,0xe1,0x32,0x32,0x31,0x30,0x01,0x16,0x16,0x17,0x16,0x16,0x33,0x15,0x23,0x22,0x26,0x27,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34, 0x26,0x27,0x04,0x84,0x08,0x09,0x06,0x09,0x55,0x5f,0x16,0x3f,0x4a,0x17,0x05,0x03,0x3c,0x82,0xcf,0x95,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x94,0x5e,0x2b,0x11,0x10,0x01,0xc1,0x2d,0x54,0x2a,0x3f,0x3e,0xa7,0x26,0x20,0x01,0x84,0xd3,0x93,0x4e,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39, 0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x45,0x9d,0x64,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x58,0x05,0x0e,0x02,0x26,0x0e,0xcf,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x9f,0x02,0xac,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x9e,0x06,0x32,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0x72,0x03,0xd0,0xff,0xff,0xff,0xba, 0xff,0xf2,0x02,0xac,0x06,0x32,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x57,0x00,0x72,0x03,0xd0,0x00,0x03,0x00,0x9b,0xfe,0x55,0x05,0x58,0x04,0xb6,0x00,0x3c,0x00,0x40,0x00,0x4c,0x00,0x7e,0xb1,0x11,0x03,0xb8,0x05,0x0a,0xb2,0x39,0x14,0x17,0xb8,0x05,0x0e,0xb2,0x44,0x23,0x21,0xb8,0x05,0x0e,0xb5,0x4a,0x44,0x4a,0x44,0x4a, 0x3d,0xb8,0x05,0x0c,0xb6,0x3e,0x39,0x3e,0x39,0x3e,0x4e,0x2f,0xbb,0x05,0x0a,0x00,0x28,0x00,0x40,0x01,0x57,0xb5,0x3d,0x2f,0x3c,0x01,0x3c,0x1c,0xb8,0x05,0x00,0xb3,0x41,0x14,0x23,0x47,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x34,0x01,0x34,0x2f,0x2c,0x01,0x2c,0x11,0x09,0xba,0x04,0xfb,0x00,0x0a,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d, 0x2f,0x5d,0xfd,0x39,0x39,0xd6,0xed,0x2f,0x5d,0xd6,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x39,0x10,0xed,0x39,0x31,0x30,0x01,0x16,0x16,0x15,0x15,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e, 0x02,0x35,0x34,0x37,0x2e,0x03,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x27,0x23,0x35,0x33,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x84,0x11,0x11,0x0b,0x26,0x46,0x3b,0x19,0x1b,0x3b,0x39,0x35,0x14,0x04,0x2b,0xa3,0x80,0x14,0x17,0x1a,0x2b,0x3a, 0x20,0x23,0x3b,0x2b,0x19,0x21,0x6e,0x95,0x5b,0x27,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x94,0x5e,0x2b,0x11,0x10,0xe4,0xc9,0xc9,0x63,0x23,0x31,0x31,0x23,0x25,0x32,0x32,0x03,0x17,0x5e,0xab,0x51,0x21,0x47,0x62,0x3e,0x1c,0xa7,0x09,0x16,0x28,0x1e,0x60,0x7d,0x18,0x15,0x38,0x21,0x20,0x3a,0x2c,0x19,0x19,0x2c,0x39, 0x21,0x3b,0x2a,0x0b,0x4d,0x7e,0xab,0x68,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x45,0x9d,0x64,0xe2,0xbd,0xf9,0xea,0x31,0x23,0x25,0x32,0x32,0x25,0x23,0x31,0x00,0xff,0xff,0xff,0xba,0xff,0x05,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x5b,0x00,0x1a,0x01,0x06,0x00,0x07, 0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x58,0x04,0x74,0x02,0x26,0x0e,0xcf,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x9f,0x02,0xac,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x87,0x04,0x53, 0x02,0x06,0x0e,0x5b,0x00,0x00,0xff,0xff,0xff,0xba,0xfd,0xff,0x04,0x02,0x03,0x56,0x02,0x06,0x0e,0x5d,0x00,0x00,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0xad,0x04,0x61,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x27,0x0f,0x54,0x01,0x56,0xfd,0xce,0x00,0x07,0x0f,0x50,0x01,0x56,0x03,0xb1,0xff,0xff,0x00,0x57,0xff,0xaf,0x04,0x02,0x04,0x11, 0x02,0x26,0x09,0x72,0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0xab,0xfc,0x28,0xff,0xff,0x00,0x57,0xff,0xaf,0x04,0x02,0x03,0x5c,0x02,0x26,0x09,0x72,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xab,0x02,0xac,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x02,0xb7,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x06,0x0f,0x5b,0x66,0x60,0x00,0x02,0x00,0x00, 0xfd,0xfe,0x04,0x02,0x03,0x1c,0x00,0x2c,0x00,0x41,0x00,0x6a,0xb2,0x12,0x2b,0x37,0xb8,0x05,0x0a,0xb2,0x13,0x20,0x2b,0xb8,0x05,0x0a,0xb4,0x18,0x3f,0x3f,0x18,0x12,0xb8,0x04,0xfd,0xb6,0x2f,0x15,0x01,0x15,0x15,0x0d,0x1b,0xb8,0x04,0xfb,0xb6,0x2f,0x3c,0x3f,0x3c,0x02,0x3c,0x32,0xb8,0x04,0xfb,0xb5,0x2f,0x25,0x01,0x25,0x0a,0x0d, 0xb8,0x04,0xfb,0x40,0x09,0x09,0x1f,0x06,0x2f,0x06,0x02,0x06,0x18,0x2b,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x39,0x2f,0x5d,0x33,0xed,0x32,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x11,0x39,0x2f,0x5d,0xed,0x01,0x2f,0x33,0x2f,0x10,0xed,0x2f,0x33,0xed,0x12,0x39,0x31,0x30,0x05,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x35,0x16, 0x16,0x33,0x32,0x3e,0x02,0x37,0x21,0x35,0x21,0x36,0x36,0x37,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x15,0x33,0x25,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x26,0x26,0x04,0x02,0xc3,0x0d,0x3f,0x72,0xab,0x79,0x58,0xad,0x58,0x67,0xab,0x45,0x3e,0x60,0x48,0x33, 0x11,0xfe,0x2a,0x01,0xf4,0x08,0x07,0x01,0x30,0x56,0x2a,0x42,0x7b,0x5e,0x39,0x30,0x55,0x75,0x45,0x42,0x7f,0x63,0x3d,0xb7,0xfe,0x96,0x0f,0x2a,0x32,0x35,0x1a,0x1c,0x37,0x2c,0x1b,0x20,0x3a,0x4e,0x2f,0x1b,0x4b,0x2a,0x02,0x09,0x0e,0x62,0xb5,0x8a,0x53,0x2c,0x2a,0xa6,0x2b,0x25,0x1b,0x31,0x43,0x28,0x6d,0x2b,0x58,0x2d,0x16,0x11, 0x29,0x4f,0x72,0x48,0x41,0x8e,0x77,0x4d,0x4f,0x9e,0xee,0x9f,0x09,0xef,0x33,0x55,0x3d,0x22,0x26,0x3d,0x4a,0x24,0x26,0x3c,0x29,0x16,0x0c,0x14,0x1d,0x33,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x31,0x02,0x26,0x0e,0x5e,0x00,0x00,0x01,0x07,0x0a,0x6d,0x00,0xe5,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x3a,0x01,0x3a,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x63,0x02,0x26,0x0e,0x5e,0x00,0x00,0x01,0x07,0x09,0x30,0x00,0xe4,0xfd,0x55,0x00,0x0c,0xb5,0x03,0x02,0x2f,0x3a,0x01,0x3a,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x59,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x07,0x09,0x73,0x00,0xe5,0xfd,0x55, 0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x05,0x31,0x02,0x26,0x0e,0x5e,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0xe5,0xfd,0x55,0x00,0x0a,0xb4,0x02,0x2f,0x3a,0x01,0x3a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x04,0x79,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0xd5,0x03,0xc9,0xff,0xff,0x00,0x00, 0xfd,0xff,0x04,0x02,0x05,0x91,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x07,0x0f,0x53,0x00,0xd5,0x03,0xc9,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xc4,0x05,0x5a,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0a,0x6d, 0x00,0x9c,0xfd,0x7e,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0x00,0xfd,0xff,0x04,0x02,0x04,0x79,0x02,0x26,0x0e,0x5e,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x03,0xc9,0xff,0xff,0xff,0xba,0xfd,0xc9,0x01,0xf2,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba, 0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x52,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x81,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0f,0x54, 0x00,0x83,0xfd,0xce,0x00,0x01,0x00,0x81,0x06,0xa6,0x01,0x86,0x07,0xab,0x00,0x13,0x00,0x19,0xbc,0x00,0x0a,0x05,0x0c,0x00,0x00,0x00,0x05,0x04,0xfe,0xb3,0x2f,0x0f,0x01,0x0f,0x00,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x13,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x81,0x13,0x23,0x2f,0x1d, 0x1c,0x31,0x22,0x14,0x14,0x22,0x31,0x1c,0x1d,0x2f,0x23,0x13,0x07,0x28,0x1c,0x31,0x22,0x14,0x14,0x22,0x31,0x1c,0x1d,0x2f,0x23,0x13,0x13,0x23,0x2f,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x05,0x1f,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x27,0x0f,0x53,0x05,0x50,0x03,0x57,0x00,0x07,0x0f,0x50,0x05,0x50,0xfe,0xab,0xff,0xff, 0xff,0xba,0xfe,0xa6,0x06,0xae,0x05,0x1f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x27,0x0f,0x53,0x02,0xa4,0x03,0x57,0x00,0x07,0x0f,0x50,0x02,0xa4,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x0a,0xb0,0x04,0xb2,0x00,0x26,0x0e,0x35,0x00,0x00,0x00,0x27,0x0f,0x50,0x05,0xca,0x04,0x02,0x00,0x07,0x0f,0x50,0x06,0x3c,0xfe,0xab,0xff,0xff, 0xff,0xba,0xfe,0xa6,0x08,0x04,0x04,0xb2,0x02,0x26,0x0e,0x36,0x00,0x00,0x00,0x27,0x0f,0x50,0x03,0x1e,0x04,0x02,0x00,0x07,0x0f,0x50,0x03,0x90,0xfe,0xab,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x55,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x03,0x0f, 0x00,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x55,0x00,0x83,0xfe,0xab,0x00,0x07,0x09,0x21,0x02,0xac,0x00,0x00,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x05,0xca,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x27,0x0f,0x53,0x02,0xad,0x04,0x02,0x00,0x07,0x0f,0x50,0x02,0xad,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0xca, 0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x53,0x00,0x9c,0x04,0x02,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07, 0x0f,0x53,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x04,0xb2,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x27,0x0f,0x53,0x02,0xad,0xfd,0xce,0x00,0x07,0x0f,0x51,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x53,0x00,0x83,0xfd,0xce,0x00,0x07, 0x0f,0x51,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x04,0xb2,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x27,0x0f,0x51,0x02,0xad,0xfe,0xab,0x00,0x07,0x0f,0x50,0x02,0xad,0x04,0x02,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x83,0xfe,0xab,0x00,0x07, 0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0xab,0xfe,0x13,0x07,0x59,0x03,0x0f,0x02,0x26,0x0e,0x6e,0x00,0x00,0x01,0x07,0x0a,0x6e,0x02,0xad,0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x35,0x01,0x35,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0x13,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0x83, 0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x26,0x01,0x26,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x05,0x5a,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0xad,0xfd,0x7e,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x05,0x5a,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0a,0x6d,0x00,0x9c,0xfd,0x7e,0xff,0xff, 0xff,0xba,0xff,0xf2,0x04,0xad,0x04,0x61,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x56,0x03,0xb1,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x56,0xfd,0xce,0xff,0xff,0x00,0x52,0xfd,0xc9,0x04,0x02,0x07,0x0f,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x27, 0x0f,0x57,0x01,0x1d,0x04,0xad,0x00,0x07,0x0f,0x52,0x00,0xab,0xfd,0xce,0xff,0xff,0x00,0x52,0xfe,0x13,0x04,0x02,0x03,0xba,0x02,0x26,0x0e,0x2f,0x00,0x00,0x01,0x07,0x0a,0x6e,0x00,0xab,0xf7,0x97,0x00,0x0a,0xb4,0x01,0x2f,0x2b,0x01,0x2b,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x02,0x5e,0x02,0x26,0x0b,0x0c, 0x00,0x00,0x00,0x07,0x0f,0x5c,0x00,0xc0,0xfc,0xfa,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x05,0x1f,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x07,0x0f,0x56,0x05,0x50,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x05,0x1f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x07,0x0f,0x56,0x02,0xa4,0x03,0x57,0xff,0xff,0x00,0xab,0xfe,0xa6, 0x08,0x04,0x03,0x62,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x51,0x05,0x10,0xfe,0xab,0xff,0xff,0x00,0xab,0xfd,0xc9,0x08,0x04,0x03,0x62,0x02,0x26,0x0e,0xa5,0x00,0x00,0x00,0x07,0x0f,0x53,0x05,0x10,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x06,0xb3,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x50,0x03,0x90, 0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x07,0xcb,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x53,0x03,0x90,0x06,0x03,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x06,0x02,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0xad,0xfd,0xce,0xff,0xff,0x00,0x39,0xfd,0xff,0x04,0xad,0x04,0x79,0x02,0x26,0x0e,0x57, 0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0x03,0xc9,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad,0x04,0x79,0x02,0x26,0x0e,0x58,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0x03,0xc9,0xff,0xff,0x00,0x39,0xfd,0xff,0x04,0xad,0x02,0xb9,0x02,0x26,0x0e,0x57,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6, 0x04,0xad,0x02,0xaf,0x02,0x26,0x0e,0x58,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x8f,0xfe,0xab,0x00,0x04,0x00,0x9b,0xfd,0xf6,0x05,0x58,0x04,0xb6,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x82,0xb1,0x11,0x03,0xbb,0x05,0x0a,0x00,0x2c,0x00,0x31,0x05,0x0c,0xb2,0x30,0x30,0x38,0xbe,0x05,0x0c,0x00,0x39,0x00,0x34,0x05,0x0c,0x00, 0x35,0x00,0x22,0x05,0x0a,0x40,0x0e,0x1b,0x2c,0x39,0x35,0x1b,0x1b,0x35,0x39,0x2c,0x04,0x3d,0x3c,0x38,0x34,0xb8,0x04,0xfb,0xb5,0x3a,0x2f,0x37,0x01,0x37,0x33,0xb8,0x01,0x57,0xb5,0x30,0x2f,0x2f,0x01,0x2f,0x16,0xb8,0x04,0xfb,0x40,0x0a,0x2f,0x27,0x01,0x27,0x2f,0x1f,0x01,0x1f,0x11,0x09,0xba,0x04,0xfb,0x00,0x0a,0x05,0x03,0x00, 0x3f,0xed,0x39,0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xd6,0xed,0x2f,0x5d,0x33,0xed,0x32,0x11,0x12,0x01,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x39,0x31,0x30,0x01,0x16,0x16,0x15,0x15,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34, 0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x27,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x84,0x11,0x11,0x0b,0x26,0x46,0x3b,0x19,0x1b,0x3b,0x3a,0x34,0x14,0x04,0x1b,0x56,0x79,0x9e,0x63,0x88,0xb7,0x6f,0x2f,0x0f,0x0e,0x97,0x0b,0x0c,0x24,0x4f,0x7e,0x5a,0x69,0x94, 0x5e,0x2b,0x11,0x10,0xe4,0xc9,0xc9,0xab,0xc9,0xc9,0x01,0x56,0xc9,0xc9,0x03,0x17,0x5d,0xac,0x51,0x21,0x47,0x62,0x3e,0x1c,0xa7,0x09,0x16,0x28,0x1e,0x3d,0x60,0x42,0x23,0x45,0x7f,0xb7,0x72,0x40,0x89,0x4e,0x4b,0x7f,0x39,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x45,0x9d,0x64,0xe2,0xbd,0xf9,0x40,0xbd,0xbd,0xbd,0x00,0xff,0xff, 0xff,0xba,0xfe,0xa6,0x02,0xac,0x04,0xb2,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x00,0x07,0x0f,0x50,0x00,0x9c,0x04,0x02,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x58,0x06,0x64,0x02,0x26,0x0e,0xcf,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x9f,0x02,0xac,0x00,0x07,0x0f,0x57,0x01,0x9f,0x04,0x02,0xff,0xff, 0xff,0xba,0xff,0xf2,0x02,0xac,0x07,0xba,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c,0x04,0x02,0x01,0x07,0x0f,0x57,0x00,0x72,0x05,0x58,0x00,0x0a,0xb4,0x01,0x20,0x21,0x01,0x21,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x58,0x05,0x63,0x02,0x26,0x0e,0xcf,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0x9f, 0x02,0xac,0x01,0x07,0x0a,0x6d,0x01,0x9f,0xfd,0x87,0x00,0x0a,0xb4,0x01,0x20,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0xc4,0x06,0xb9,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9c,0x04,0x02,0x01,0x07,0x0a,0x6d,0x00,0x9c,0xfe,0xdd,0x00,0x14,0x40,0x0a,0x02,0x2f,0x25,0x01,0x25,0x01, 0x20,0x21,0x01,0x21,0x00,0x11,0x5d,0x35,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x05,0x1f,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x07,0x0f,0x52,0x05,0x50,0x03,0x57,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x05,0x1f,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x07,0x0f,0x52,0x02,0xa4,0x03,0x57,0x00,0x03,0x00,0x7e, 0xfd,0xfe,0x04,0x2d,0x03,0x54,0x00,0x24,0x00,0x3e,0x00,0x4c,0x00,0x6a,0xb4,0x24,0x02,0x1b,0x1b,0x34,0xb8,0x05,0x0e,0xb2,0x44,0x4c,0x2b,0xb8,0x05,0x0d,0xb7,0x28,0x44,0x28,0x44,0x28,0x4e,0x10,0x21,0xbb,0x05,0x0a,0x00,0x02,0x00,0x39,0x04,0xfd,0xb6,0x3f,0x28,0x28,0x25,0x25,0x3f,0x47,0xb8,0x04,0xfd,0x40,0x0f,0x2a,0x2f,0x2f, 0x01,0x2f,0x1c,0x07,0x1b,0x03,0x14,0x2f,0x24,0x01,0x24,0x0d,0xb9,0x04,0xff,0x00,0x14,0x00,0x2f,0xed,0x2f,0x5d,0x12,0x17,0x39,0x2f,0x5d,0xc6,0xfd,0xc6,0x32,0x2f,0x32,0x2f,0x10,0xed,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x32,0x2f,0x11,0x39,0x31,0x30,0x01,0x26,0x35,0x34,0x3e,0x02,0x37,0x35, 0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x03,0x16,0x16,0x17,0x11,0x33,0x11,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x25,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x01,0x2b,0xad,0x53,0xa8,0xfe, 0xac,0x30,0x4c,0x52,0x63,0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54,0x5c,0x6d,0x48,0x20,0xc5,0xfe,0xe2,0xb8,0x58,0x5d,0x58,0x07,0x17,0x3f,0x29,0x59,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x01,0x4f,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0xfd,0xfe, 0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35,0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x01,0x1e,0x02,0x03,0x02,0x01,0xf7,0xfe,0xa5,0x01,0x3e,0x46,0x24,0x3d,0x50,0x2c,0x40,0x46,0x21,0x06,0x01,0x03,0x04,0x03,0x5e,0x02,0x0e,0x1c,0x1a,0x3b,0x38,0x1f, 0x33,0x43,0x24,0x00,0x00,0x04,0x00,0x7e,0xfd,0xfe,0x05,0x58,0x03,0x54,0x00,0x24,0x00,0x3e,0x00,0x4c,0x00,0x5a,0x00,0x7e,0xb2,0x1b,0x1b,0x34,0xb8,0x05,0x0e,0xb5,0x44,0x58,0x58,0x44,0x4c,0x2b,0xb8,0x05,0x0d,0x40,0x0b,0x28,0x44,0x28,0x44,0x28,0x5c,0x24,0x02,0x4d,0x10,0x21,0xbf,0x05,0x0a,0x00,0x02,0x00,0x50,0x04,0xfb,0x00, 0x52,0x05,0x03,0x00,0x39,0x04,0xfd,0xb6,0x3f,0x28,0x28,0x25,0x25,0x3f,0x47,0xb8,0x04,0xfd,0x40,0x10,0x2a,0x2f,0x2f,0x01,0x2f,0x1b,0x07,0x1c,0x4d,0x04,0x14,0x2f,0x24,0x01,0x24,0x0d,0xb9,0x04,0xff,0x00,0x14,0x00,0x2f,0xed,0x2f,0x5d,0x12,0x17,0x39,0x2f,0x5d,0xc6,0xfd,0xc6,0x32,0x2f,0x32,0x2f,0x10,0xed,0x3f,0xed,0x01,0x2f, 0xed,0x39,0x2f,0x12,0x39,0x11,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x11,0x33,0x2f,0x10,0xed,0x32,0x2f,0x31,0x30,0x01,0x26,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x03,0x16,0x16,0x17,0x11,0x33,0x11,0x17,0x36,0x36,0x33, 0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x25,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x01,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x36,0x36,0x01,0x2b,0xad,0x53,0xa8,0xfe,0xac,0x30,0x4c,0x52,0x63,0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54,0x5c,0x6d,0x48,0x20,0xc5, 0xfe,0xe2,0xb8,0x58,0x5d,0x58,0x06,0x17,0x3f,0x29,0x59,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x01,0x4f,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0x01,0xba,0x06,0x74,0x68,0x1f,0x37,0x4f,0x77,0x52,0x2c,0x04,0x1f,0x3f,0xfd,0xfe,0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35, 0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x01,0x1e,0x02,0x03,0x02,0x01,0xf7,0xfe,0xa5,0x01,0x3e,0x46,0x24,0x3d,0x50,0x2c,0x40,0x46,0x21,0x06,0x01,0x03,0x04,0x03,0x5e,0x02,0x0e,0x1c,0x1a,0x3b,0x38,0x1f,0x33,0x43,0x24,0x02,0x43,0x68,0x55, 0xa7,0x30,0x56,0x74,0x44,0x0b,0x13,0x00,0xff,0xff,0xff,0xba,0xfe,0x03,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x56,0xfe,0x03,0xff,0xff,0xff,0xba,0xfe,0x03,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x56,0xfe,0x03,0x00,0x05,0x00,0x7e,0xfd,0xfa,0x04,0x2d, 0x03,0x54,0x00,0x24,0x00,0x3e,0x00,0x4c,0x00,0x50,0x00,0x54,0x00,0x9d,0xb9,0x00,0x52,0x05,0x0a,0xb7,0x51,0x51,0x44,0x24,0x02,0x1b,0x1b,0x34,0xbb,0x05,0x0e,0x00,0x44,0x00,0x2b,0x05,0x0d,0xb4,0x2c,0x4c,0x28,0x28,0x4d,0xb8,0x05,0x0a,0xb7,0x4e,0x44,0x4e,0x44,0x4e,0x56,0x10,0x21,0xb8,0x05,0x0a,0xb4,0x02,0x2c,0x2a,0x52,0x4d, 0xb8,0x05,0x02,0xb2,0x53,0x50,0x39,0xb8,0x04,0xfd,0x40,0x0a,0x3f,0x28,0x28,0x25,0x25,0x2f,0x3f,0x01,0x3f,0x47,0xb8,0x04,0xfd,0x40,0x10,0x2f,0x2f,0x3f,0x2f,0x02,0x2f,0x2f,0x2a,0x01,0x2a,0x1c,0x07,0x1b,0x03,0x00,0x0d,0xb8,0x04,0xff,0xb4,0x14,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0xed,0x12,0x17,0x39,0x2f,0x5d,0x2f,0x5d, 0xfd,0xc6,0x5d,0x32,0x2f,0x32,0x2f,0x10,0xfd,0xd6,0x32,0xed,0x32,0x11,0x39,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0x39,0x39,0xed,0x10,0xed,0x32,0x2f,0x11,0x39,0x11,0x39,0x2f,0xed,0x31,0x30,0x01,0x26,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04, 0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x03,0x16,0x16,0x17,0x11,0x33,0x15,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x25,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x2b,0xad,0x53,0xa8,0xfe,0xac,0x30,0x4c,0x52,0x63, 0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54,0x5c,0x6d,0x48,0x20,0xc5,0xfe,0xe2,0xb8,0x58,0x5d,0x58,0x07,0x17,0x3f,0x29,0x59,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x01,0x4f,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0x21,0xb9,0xb9,0x01,0x42,0xb9,0xb9, 0xfd,0xfe,0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35,0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x01,0x82,0x02,0x03,0x02,0x01,0x93,0xf7,0x01,0x3e,0x46,0x24,0x3d,0x50,0x2c,0x40,0x46,0x21,0x06,0x01,0x03,0x04,0x03,0x5e,0x02,0x0e,0x1c,0x1a,0x3b,0x38, 0x1f,0x33,0x43,0x24,0xfe,0x83,0xb5,0xb5,0xb5,0x00,0x00,0x06,0x00,0x7e,0xfd,0xfa,0x05,0x58,0x03,0x54,0x00,0x24,0x00,0x3e,0x00,0x4c,0x00,0x5a,0x00,0x5e,0x00,0x62,0x00,0xb1,0xb2,0x24,0x02,0x4d,0xb8,0x05,0x0b,0xb3,0x58,0x58,0x44,0x60,0xb8,0x05,0x0a,0xb3,0x34,0x5f,0x5f,0x34,0xbb,0x05,0x0e,0x00,0x44,0x00,0x2b,0x05,0x0d,0xb4, 0x2c,0x4c,0x28,0x28,0x5b,0xb8,0x05,0x0a,0xb7,0x5c,0x44,0x5c,0x44,0x5c,0x64,0x10,0x21,0xb8,0x05,0x0a,0xb2,0x02,0x5f,0x5b,0xb8,0x04,0xfb,0x40,0x0a,0x61,0x2f,0x5e,0x01,0x5e,0x51,0x50,0x50,0x2f,0x39,0xb8,0x04,0xfd,0x40,0x0a,0x3f,0x28,0x28,0x25,0x25,0x2f,0x3f,0x01,0x3f,0x47,0xb8,0x04,0xfd,0xb3,0x2c,0x52,0x2a,0x2f,0xba,0x04, 0xfb,0x00,0x52,0x05,0x03,0xb6,0x4d,0x1c,0x07,0x1b,0x04,0x00,0x0d,0xb8,0x04,0xff,0xb4,0x14,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x2f,0xed,0x12,0x17,0x39,0x3f,0xf4,0xc6,0x12,0x39,0xfd,0xc6,0x5d,0x32,0x2f,0x32,0x2f,0x10,0xed,0x11,0x33,0x11,0x33,0x2f,0x5d,0x33,0xed,0x32,0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed, 0x39,0x2f,0x39,0x39,0xed,0x10,0xed,0x32,0x2f,0x10,0xe4,0x12,0x39,0x2f,0xed,0x11,0x39,0x31,0x30,0x01,0x26,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x03,0x16,0x16,0x17,0x11,0x33,0x15,0x17,0x36,0x36,0x33,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x25,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x01,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x36,0x36,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x2b,0xad,0x53,0xa8,0xfe,0xac,0x30,0x4c,0x52,0x63,0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54, 0x5c,0x6d,0x48,0x20,0xc5,0xfe,0xe2,0xb8,0x58,0x5d,0x58,0x33,0x17,0x3f,0x29,0x59,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x01,0x4f,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0x01,0xe7,0x06,0x74,0x68,0x1f,0x37,0x4f,0x77,0x52,0x2c,0x04,0x1f,0x3f,0xfe,0x86,0xb9,0xb9, 0x01,0x42,0xb9,0xb9,0xfd,0xfe,0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35,0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x01,0x82,0x02,0x03,0x02,0x01,0x93,0xf7,0x01,0x3e,0x46,0x24,0x3d,0x50,0x2c,0x40,0x46,0x21,0x06,0x01,0x03,0x04,0x03,0x5e,0x02,0x0e, 0x1c,0x1a,0x3b,0x38,0x1f,0x33,0x43,0x24,0x01,0xdf,0x68,0x55,0xa7,0x30,0x56,0x74,0x44,0x0b,0x13,0xfc,0xac,0xb5,0xb5,0xb5,0x00,0x04,0xff,0xba,0xfd,0xfa,0x04,0x68,0x02,0xdb,0x00,0x42,0x00,0x50,0x00,0x54,0x00,0x58,0x00,0x92,0xb1,0x0d,0x30,0xb8,0x05,0x0e,0xb2,0x48,0x48,0x55,0xb8,0x05,0x0a,0xb2,0x56,0x50,0x27,0xb8,0x05,0x0d, 0xb2,0x3f,0x3f,0x51,0xb8,0x05,0x0a,0x40,0x09,0x52,0x56,0x52,0x56,0x52,0x5a,0x15,0x55,0x51,0xb8,0x04,0xfb,0x40,0x09,0x57,0x54,0x43,0x3e,0x3e,0x43,0x3b,0x3b,0x35,0xb8,0x04,0xfd,0xb4,0x2f,0x43,0x01,0x43,0x4b,0xb8,0x04,0xfd,0x40,0x0b,0x27,0x2f,0x2b,0x01,0x2b,0x20,0x0c,0x21,0x03,0x00,0x12,0xb8,0x04,0xff,0xb7,0x2f,0x19,0x01, 0x19,0x26,0x3f,0x3f,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x39,0x11,0x33,0x2f,0x5d,0xed,0x12,0x17,0x39,0x2f,0x5d,0x33,0xfd,0xd6,0x5d,0xed,0x33,0x2f,0x11,0x33,0x2f,0x10,0xd4,0x32,0xed,0x32,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0xed,0x32,0x10,0xed,0x39,0x2f,0xed,0x39,0x31,0x30,0x15,0x22, 0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x0e,0x03,0x07,0x15,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x27,0x16,0x16,0x17,0x35,0x06,0x06,0x23,0x05,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e, 0x02,0x07,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x23,0x23,0x23,0x23,0x3b,0x7b,0xda,0xc7,0xb9,0x5a,0x3a,0x59,0x60,0x76,0x57,0x4e,0x7e,0x33,0x37,0x84,0x4e,0x50,0x79,0x66,0x5c,0x65,0x76,0x4e,0x20,0x2c,0x75,0x95,0xb4,0x6a,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x0d,0x17,0x3e, 0x2a,0x51,0xb4,0x64,0x02,0x46,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0x21,0xaf,0xaf,0x01,0x38,0xaf,0xaf,0x0e,0x34,0x20,0x20,0x33,0x31,0x4f,0x64,0x32,0x05,0x18,0x30,0x25,0x18,0x14,0x10,0x9d,0x12,0x17,0x1b,0x28,0x2f,0x29,0x1c,0x01,0xbb,0x09,0x41,0x57,0x5f,0x27,0x7a,0x01,0x3d,0x42,0x22,0x39,0x4b,0x29,0x3a, 0x40,0x1e,0x05,0x01,0x03,0x04,0x03,0x62,0x02,0x03,0x02,0xe6,0x17,0x1c,0xb5,0x02,0x0c,0x18,0x17,0x33,0x30,0x1b,0x2c,0x3a,0x1f,0xfe,0xbd,0xab,0xab,0xab,0x00,0x04,0xff,0xba,0xfd,0xfa,0x04,0xad,0x02,0xdb,0x00,0x4f,0x00,0x5d,0x00,0x61,0x00,0x65,0x00,0xa7,0xb1,0x0d,0x3d,0xb8,0x05,0x0e,0xb6,0x55,0x55,0x62,0x63,0x30,0x30,0x24, 0xba,0x05,0x0b,0x00,0x62,0x05,0x0a,0xb2,0x63,0x5d,0x34,0xb8,0x05,0x0d,0xb2,0x4c,0x4c,0x5e,0xb8,0x05,0x0a,0x40,0x09,0x5f,0x63,0x5f,0x63,0x5f,0x67,0x66,0x62,0x5e,0xb8,0x04,0xfb,0xb2,0x64,0x61,0x42,0xb8,0x04,0xfd,0x40,0x0a,0x50,0x4b,0x4b,0x48,0x48,0x2f,0x50,0x01,0x50,0x58,0xb8,0x04,0xfd,0xb5,0x34,0x2f,0x38,0x01,0x38,0x2a, 0xb8,0x05,0x03,0xb7,0x30,0x24,0x21,0x0c,0x20,0x05,0x00,0x12,0xb8,0x04,0xff,0x40,0x09,0x2f,0x19,0x01,0x19,0x33,0x4c,0x4c,0x29,0x06,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x39,0x11,0x33,0x2f,0x5d,0xed,0x12,0x17,0x39,0x3f,0x2f,0x5d,0x33,0xfd,0xc6,0x5d,0x32,0x2f,0x32,0x2f,0x10,0xfd,0xd6,0x32,0xed,0x32,0x11, 0x12,0x01,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0xed,0x32,0x10,0xfd,0xe4,0x33,0x2f,0x11,0x12,0x39,0x2f,0xed,0x39,0x31,0x30,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x06,0x07,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02, 0x27,0x06,0x06,0x07,0x15,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x27,0x16,0x16,0x17,0x35,0x06,0x06,0x23,0x05,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x23,0x23,0x23,0x23,0x3b,0x7b,0xda,0xc7,0xb9,0x5a,0x3a,0x59,0x60,0x76,0x57, 0x4e,0x7e,0x33,0x37,0x84,0x4e,0x4f,0x7a,0x66,0x5c,0x64,0x77,0x4e,0x20,0x1d,0x46,0x2a,0x03,0x14,0x35,0x5c,0x4a,0x14,0x62,0x7c,0x49,0x1e,0x04,0x48,0xad,0x67,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x0d,0x17,0x3e,0x2a,0x51,0xb4,0x64,0x02,0x46,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23, 0x3f,0x35,0x2a,0x0f,0x21,0xaf,0xaf,0x01,0x38,0xaf,0xaf,0x0e,0x34,0x20,0x20,0x33,0x31,0x4f,0x64,0x32,0x05,0x18,0x2f,0x26,0x18,0x14,0x10,0x9d,0x12,0x17,0x1b,0x28,0x2f,0x29,0x1c,0x01,0xbb,0x06,0x22,0x17,0x27,0x36,0x23,0x10,0xa7,0x29,0x45,0x59,0x31,0x2a,0x5a,0x25,0x7a,0x01,0x3c,0x43,0x22,0x39,0x4b,0x29,0x3a,0x40,0x1e,0x05, 0x01,0x03,0x04,0x03,0x62,0x02,0x03,0x02,0xe5,0x17,0x1b,0xb5,0x02,0x0c,0x18,0x17,0x33,0x30,0x1b,0x2c,0x3a,0x1f,0xfe,0xbd,0xab,0xab,0xab,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x07,0x0d,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x27,0x0f,0x51,0x05,0x46,0x03,0x57,0x01,0x07,0x0f,0x57,0x05,0x46,0x04,0xab,0x00,0x0c,0xb5,0x02, 0x01,0x20,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x07,0x0d,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x27,0x0f,0x51,0x05,0x46,0x03,0x57,0x01,0x07,0x0f,0x57,0x05,0x46,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x5b,0x01,0x5b,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4, 0x07,0x0d,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x27,0x0f,0x51,0x02,0xa4,0x03,0x57,0x01,0x07,0x0f,0x57,0x02,0xa4,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x45,0x01,0x45,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x07,0x0d,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x27,0x0f,0x51,0x02,0xa4,0x03,0x57,0x01,0x07, 0x0f,0x57,0x02,0xa4,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x4f,0x01,0x4f,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0xc6,0x07,0x0d,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x9a,0x03,0x57,0x01,0x07,0x0f,0x57,0x00,0x9a,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x1d,0x01,0x1d,0x00,0x11,0x5d, 0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x07,0x0d,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x9a,0x03,0x57,0x01,0x07,0x0f,0x57,0x00,0x9a,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x26,0x01,0x26,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0x41,0x06,0x8c,0x02,0x26,0x09,0x13,0x00,0x00, 0x00,0x07,0x0f,0x57,0x01,0x56,0x04,0x2a,0xff,0xff,0x00,0x7e,0xfd,0xff,0x04,0xad,0x06,0x8c,0x02,0x26,0x08,0xd1,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x56,0x04,0x2a,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x7c,0x06,0x13,0x02,0x26,0x08,0xd0,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x56,0x03,0xb1,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xad, 0x06,0x13,0x02,0x26,0x0e,0x2d,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x56,0x03,0xb1,0xff,0xff,0x00,0x17,0x00,0x00,0x01,0xf2,0x07,0x6e,0x00,0x27,0x09,0x0d,0x00,0xab,0x00,0x00,0x00,0x06,0x0f,0x5e,0x00,0x00,0xff,0xff,0x00,0x17,0xff,0xf2,0x02,0xac,0x07,0x6e,0x00,0x27,0x08,0xc7,0x00,0xab,0x00,0x00,0x00,0x06,0x0f,0x5e,0x00,0x00, 0xff,0xff,0x00,0x16,0x00,0x00,0x01,0xfa,0x07,0x6e,0x00,0x27,0x09,0x0d,0x00,0xab,0x00,0x00,0x00,0x06,0x0f,0x5f,0x00,0x00,0xff,0xff,0x00,0x16,0xff,0xf2,0x02,0xac,0x07,0x6e,0x00,0x27,0x08,0xc7,0x00,0xab,0x00,0x00,0x00,0x06,0x0f,0x5f,0x00,0x00,0xff,0xff,0x00,0x9a,0xff,0x55,0x05,0x91,0x05,0x8a,0x02,0x26,0x09,0x2a,0x00,0x00, 0x01,0x07,0x0f,0x5e,0x00,0xab,0xfe,0x1c,0x00,0x0a,0xb4,0x01,0x2f,0x36,0x01,0x36,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae,0x04,0xdf,0x02,0x26,0x08,0xf7,0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xa1,0xfd,0x71,0x00,0x0e,0xb7,0x01,0x2f,0x45,0x01,0x2f,0x45,0x01,0x45,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0xff,0xba, 0xfe,0xa6,0x02,0x4c,0x05,0xf6,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x01,0x07,0x0f,0x5e,0x00,0xd5,0xfe,0x88,0x00,0x0a,0xb4,0x03,0x2f,0x1f,0x01,0x1f,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0xf6,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab, 0x01,0x07,0x0f,0x5e,0x00,0xd5,0xfe,0x88,0x00,0x0a,0xb4,0x03,0x2f,0x28,0x01,0x28,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x55,0x05,0x91,0x05,0x8a,0x02,0x26,0x09,0x2a,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xab,0xfe,0x1c,0x00,0x0a,0xb4,0x01,0x2f,0x59,0x01,0x59,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x06,0xae, 0x04,0xdf,0x02,0x26,0x08,0xf7,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xa1,0xfd,0x71,0x00,0x0e,0xb7,0x01,0x2f,0x68,0x01,0x2f,0x68,0x01,0x68,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x96,0x05,0xf6,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x01,0x07,0x0f,0x5f,0x00,0x9c,0xfe,0x88, 0x00,0x0a,0xb4,0x03,0x2f,0x42,0x01,0x42,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0xf6,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x51,0x00,0x4a,0xfe,0xab,0x01,0x07,0x0f,0x5f,0x00,0x9c,0xfe,0x88,0x00,0x0a,0xb4,0x03,0x2f,0x42,0x01,0x42,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xfd,0x78,0x05,0x91, 0x04,0xaa,0x02,0x27,0x09,0x2a,0x00,0x00,0x00,0x95,0x01,0x07,0x0f,0x60,0x02,0x01,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x42,0x01,0x42,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xfd,0x78,0x06,0xae,0x02,0xbd,0x02,0x26,0x0f,0x61,0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0xc8,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x43,0x01,0x43,0x00,0x11, 0x5d,0x35,0xff,0xff,0xff,0xba,0xfd,0x78,0x02,0x75,0x03,0x0f,0x02,0x26,0x0e,0x6f,0x00,0x00,0x01,0x07,0x0f,0x60,0x00,0x9c,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x33,0x01,0x33,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfd,0x78,0x02,0xac,0x03,0x0f,0x02,0x26,0x09,0x3b,0x00,0x00,0x01,0x07,0x0f,0x60,0x00,0x9c,0xf8,0x34,0x00,0x0a, 0xb4,0x01,0x2f,0x42,0x01,0x42,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x17,0xfd,0xff,0x03,0xf4,0x04,0xc3,0x00,0x27,0x09,0x29,0x00,0xab,0x00,0x00,0x00,0x07,0x0f,0x5e,0x00,0x00,0xfd,0x55,0xff,0xff,0x00,0x17,0xfd,0xff,0x04,0xad,0x04,0xc3,0x00,0x27,0x0e,0x5e,0x00,0xab,0x00,0x00,0x00,0x07,0x0f,0x5e,0x00,0x00,0xfd,0x55,0xff,0xff, 0x00,0x16,0xfd,0xff,0x03,0xf4,0x04,0xc3,0x00,0x27,0x09,0x29,0x00,0xab,0x00,0x00,0x00,0x07,0x0f,0x5f,0x00,0x00,0xfd,0x55,0xff,0xff,0x00,0x16,0xfd,0xff,0x04,0xad,0x04,0xc3,0x00,0x27,0x0e,0x5e,0x00,0xab,0x00,0x00,0x00,0x07,0x0f,0x5f,0x00,0x00,0xfd,0x55,0xff,0xff,0x00,0x72,0xff,0xea,0x06,0xe5,0x05,0x6e,0x02,0x26,0x09,0x65, 0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xab,0xfe,0x00,0x00,0x0e,0xb7,0x01,0x2f,0x2c,0x01,0x2f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26,0x09,0x66,0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xab,0xfb,0xff,0x00,0x0a,0xb4,0x01,0x2f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff, 0x00,0x72,0xff,0xea,0x06,0xe5,0x05,0x6e,0x02,0x26,0x09,0x65,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xab,0xfe,0x00,0x00,0x0e,0xb7,0x01,0x2f,0x2c,0x01,0x2f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26,0x09,0x66,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xab,0xfb,0xff,0x00,0x0a, 0xb4,0x01,0x2f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0x00,0x02,0x00,0x7e,0xfd,0xfe,0x04,0x2c,0x03,0x54,0x00,0x24,0x00,0x4a,0x00,0x65,0xb9,0x00,0x3e,0x05,0x0b,0xb5,0x31,0x31,0x38,0x24,0x02,0x37,0xb8,0x05,0x0d,0xb4,0x38,0x38,0x4c,0x10,0x21,0xb8,0x05,0x0a,0x40,0x09,0x02,0x2f,0x37,0x01,0x37,0x47,0x25,0x28,0x2e,0xb8,0x04,0xfd, 0x40,0x13,0x41,0x4a,0x4a,0x41,0x41,0x2f,0x25,0x01,0x25,0x1c,0x07,0x1b,0x03,0x14,0x2f,0x24,0x01,0x24,0x0d,0xb9,0x04,0xff,0x00,0x14,0x00,0x2f,0xed,0x2f,0x5d,0x12,0x17,0x39,0x2f,0x5d,0x33,0x2f,0x33,0x2f,0x10,0xfd,0xc4,0x11,0x39,0x2f,0x5d,0x01,0x2f,0xed,0x39,0x12,0x39,0x2f,0xed,0x11,0x39,0x11,0x39,0x2f,0xed,0x31,0x30,0x01, 0x26,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x06,0x06,0x07,0x23,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x01, 0x2b,0xad,0x53,0xa8,0xfe,0xac,0x30,0x4c,0x52,0x63,0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54,0x5c,0x6d,0x48,0x20,0xc5,0xfe,0xe2,0xb8,0x58,0x5d,0x58,0x01,0xd3,0x1e,0x2e,0x0f,0x69,0x06,0x14,0x19,0x20,0x12,0x11,0x0f,0x09,0x0a,0x09,0x59,0x0b,0x0d,0x0b,0x42,0x2e,0x1e,0x33,0x29,0x1e,0x09,0x02,0x0b,0x17,0x10,0xfd, 0xfe,0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35,0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x02,0xd6,0x30,0x7c,0x3f,0x18,0x31,0x27,0x19,0x15,0x10,0x0d,0x27,0x46,0x6b,0x51,0x6d,0x6a,0x54,0x74,0x50,0x33,0x13,0x30,0x37,0x14,0x21,0x2b,0x17,0x21,0x35, 0x1c,0x00,0x00,0x03,0x00,0x7e,0xfd,0xfe,0x05,0x58,0x03,0x54,0x00,0x24,0x00,0x32,0x00,0x58,0x00,0x81,0xb5,0x24,0x55,0x33,0x03,0x02,0x25,0xbb,0x05,0x0b,0x00,0x30,0x00,0x4c,0x05,0x0b,0xb2,0x3f,0x3f,0x45,0xb8,0x05,0x0d,0xb7,0x46,0x30,0x46,0x30,0x46,0x5a,0x10,0x21,0xb8,0x05,0x0a,0x40,0x09,0x02,0x2f,0x45,0x01,0x45,0x55,0x33, 0x36,0x3c,0xb8,0x04,0xfd,0x40,0x0a,0x4f,0x58,0x58,0x4f,0x4f,0x2f,0x33,0x01,0x33,0x28,0xba,0x04,0xfb,0x00,0x2a,0x05,0x03,0x40,0x0a,0x1c,0x07,0x1b,0x03,0x14,0x2f,0x24,0x01,0x24,0x0d,0xb9,0x04,0xff,0x00,0x14,0x00,0x2f,0xed,0x2f,0x5d,0x12,0x17,0x39,0x3f,0xed,0x2f,0x5d,0x33,0x2f,0x33,0x2f,0x10,0xfd,0xc4,0x11,0x39,0x2f,0x5d, 0x01,0x2f,0xed,0x39,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x2f,0xed,0x10,0xed,0x11,0x17,0x39,0x31,0x30,0x01,0x26,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x04,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x36, 0x36,0x07,0x06,0x06,0x07,0x23,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x01,0x2b,0xad,0x53,0xa8,0xfe,0xac,0x30,0x4c,0x52,0x63,0x46,0x4f,0x7d,0x35,0x36,0x86,0x4b,0x49,0x6f,0x5d,0x54,0x5c,0x6d,0x48,0x20,0xc5,0xfe,0xe2,0xb8, 0x58,0x5d,0x58,0x02,0x89,0x06,0x74,0x68,0x1f,0x37,0x4f,0x77,0x52,0x2c,0x04,0x1f,0x3f,0x96,0x1e,0x2e,0x0f,0x69,0x06,0x14,0x19,0x20,0x12,0x11,0x0f,0x09,0x0a,0x09,0x59,0x0b,0x0d,0x0b,0x42,0x2e,0x1e,0x33,0x29,0x1e,0x09,0x02,0x0b,0x17,0x10,0xfd,0xfe,0xef,0xd9,0x68,0xbe,0xa6,0x8b,0x35,0x08,0x0f,0x20,0x19,0x10,0x14,0x10,0x9d, 0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xbb,0x34,0x75,0x88,0x9f,0x5e,0x64,0xe7,0x8a,0x03,0x58,0x68,0x55,0xa7,0x30,0x56,0x74,0x44,0x0b,0x13,0x7a,0x30,0x7c,0x3f,0x18,0x31,0x27,0x19,0x15,0x10,0x0d,0x27,0x46,0x6b,0x51,0x6d,0x6a,0x54,0x74,0x50,0x33,0x13,0x30,0x37,0x14,0x21,0x2b,0x17,0x21,0x35,0x1c,0x00,0xff,0xff,0xff,0xba, 0xfd,0x78,0x04,0x7c,0x03,0x0f,0x02,0x26,0x08,0xd0,0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0x56,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x2c,0x01,0x2c,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfd,0x78,0x04,0xad,0x03,0x0f,0x02,0x26,0x0e,0x2d,0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0x56,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x52,0x01,0x52, 0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x05,0x50,0x02,0x26,0x09,0x19,0x00,0x00,0x01,0x07,0x0f,0x60,0x05,0x49,0xfd,0xdd,0x00,0x0a,0xb4,0x01,0x2f,0x6a,0x01,0x6a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x05,0x50,0x02,0x26,0x0e,0x31,0x00,0x00,0x01,0x07,0x0f,0x60,0x05,0x49,0xfd,0xdd, 0x00,0x0a,0xb4,0x01,0x2f,0x75,0x01,0x75,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4,0x05,0x50,0x02,0x26,0x08,0xd4,0x00,0x00,0x01,0x07,0x0f,0x60,0x02,0x9d,0xfd,0xdd,0x00,0x0a,0xb4,0x01,0x2f,0x5f,0x01,0x5f,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x05,0x50,0x02,0x26,0x0e,0x32,0x00,0x00, 0x01,0x07,0x0f,0x60,0x02,0x9d,0xfd,0xdd,0x00,0x0a,0xb4,0x01,0x2f,0x6a,0x01,0x6a,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9b,0xfd,0xff,0x08,0xa0,0x04,0xb8,0x02,0x26,0x09,0x19,0x00,0x00,0x00,0x07,0x0a,0x6e,0x05,0x46,0xfc,0xdc,0xff,0xff,0x00,0x9b,0xfd,0xff,0x09,0x5a,0x04,0xb8,0x02,0x26,0x0e,0x31,0x00,0x00,0x00,0x07,0x0a,0x6e, 0x05,0x46,0xfc,0xdc,0xff,0xff,0xff,0xba,0xff,0xf2,0x05,0xf4,0x04,0xb8,0x02,0x26,0x08,0xd4,0x00,0x00,0x00,0x07,0x0a,0x6e,0x02,0xa4,0xfc,0xdc,0xff,0xff,0xff,0xba,0xff,0xf2,0x06,0xae,0x04,0xb8,0x02,0x26,0x0e,0x32,0x00,0x00,0x00,0x07,0x0a,0x6e,0x02,0xa4,0xfc,0xdc,0xff,0xff,0x00,0xab,0xff,0xea,0x05,0xf4,0x06,0xb3,0x02,0x26, 0x09,0x24,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0x73,0x06,0x03,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xae,0x06,0xb3,0x02,0x26,0x0e,0x55,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0x73,0x06,0x03,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x4b,0x06,0xb3,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x39,0x06,0x03,0xff,0xff,0xff,0xba, 0xff,0xf2,0x04,0x02,0x06,0xb3,0x02,0x26,0x0e,0x56,0x00,0x00,0x00,0x07,0x0f,0x51,0x00,0x39,0x06,0x03,0x00,0x01,0x00,0xa4,0xff,0xfb,0x01,0x5d,0x00,0xb0,0x00,0x03,0x00,0x19,0xbc,0x00,0x00,0x05,0x0a,0x00,0x01,0x00,0x02,0x04,0xfb,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x05,0x23,0x35,0x33,0x01, 0x5d,0xb9,0xb9,0x05,0xb5,0x00,0x00,0x02,0x00,0x03,0xff,0xfb,0x01,0xfe,0x00,0xb0,0x00,0x03,0x00,0x07,0x00,0x29,0xb9,0x00,0x00,0x05,0x0a,0xb3,0x01,0x01,0x08,0x04,0xb8,0x05,0x0a,0xb2,0x05,0x06,0x02,0xb8,0x05,0x02,0xb4,0x05,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0xed,0x32,0x01,0x2f,0xed,0x11,0x33,0x2f,0xed,0x31,0x30,0x17, 0x23,0x35,0x33,0x05,0x23,0x35,0x33,0xbc,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x05,0xb5,0xb5,0xb5,0x00,0x02,0x00,0xa4,0xff,0xfb,0x01,0x5d,0x01,0xc8,0x00,0x03,0x00,0x07,0x00,0x25,0xb1,0x04,0x00,0xb8,0x05,0x0a,0xb2,0x05,0x01,0x07,0xbb,0x05,0x02,0x00,0x04,0x00,0x02,0x05,0x02,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xfd,0xd6,0xed, 0x01,0x2f,0x33,0xed,0x32,0x31,0x30,0x05,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x5d,0xb9,0xb9,0xb9,0xb9,0x05,0xb5,0x63,0xb5,0x00,0x00,0x03,0x00,0x03,0xff,0xfb,0x01,0xfe,0x01,0xc8,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x41,0xbf,0x00,0x04,0x05,0x0a,0x00,0x05,0x00,0x08,0x05,0x0a,0x00,0x09,0x00,0x00,0x05,0x0a,0xb3,0x01,0x01, 0x0c,0x08,0xb8,0x05,0x02,0xb6,0x0b,0x0b,0x00,0x07,0x06,0x06,0x02,0xb8,0x05,0x02,0xb4,0x05,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0xed,0x32,0x11,0x33,0x11,0x33,0x2f,0xed,0x11,0x01,0x33,0x2f,0xed,0xd4,0xed,0xd6,0xed,0x31,0x30,0x17,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0xbc,0xb9,0xb9,0x01,0x42,0xb9,0xb9, 0xa1,0xb9,0xb9,0x05,0xb5,0xb5,0xb5,0x63,0xb5,0x00,0x00,0x03,0x00,0x03,0xff,0xfb,0x01,0xfe,0x01,0xc8,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x37,0xbf,0x00,0x04,0x05,0x0a,0x00,0x05,0x00,0x08,0x05,0x0a,0x00,0x09,0x00,0x00,0x05,0x0a,0xb2,0x01,0x04,0x00,0xb8,0x05,0x02,0xb3,0x06,0x03,0x03,0x0a,0xb8,0x05,0x02,0xb3,0x2f,0x08,0x01, 0x08,0x00,0x2f,0x5d,0xed,0x33,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0xd6,0xed,0xd4,0xed,0x31,0x30,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0xbc,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x01,0x13,0xb5,0xb5,0xb5,0xfe,0x33,0xb5,0x00,0x00,0x03,0xff,0x62,0xff,0xfb,0x02,0x9f,0x00,0xb0,0x00,0x03,0x00,0x07, 0x00,0x0b,0x00,0x35,0xbf,0x00,0x08,0x05,0x0a,0x00,0x09,0x00,0x04,0x05,0x0a,0x00,0x05,0x00,0x00,0x05,0x0a,0xb5,0x01,0x01,0x0c,0x0a,0x06,0x02,0xb8,0x05,0x02,0xb5,0x09,0x05,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0x32,0xed,0x32,0x32,0x11,0x01,0x33,0x2f,0xed,0xd4,0xed,0xd4,0xed,0x31,0x30,0x17,0x23,0x35,0x33,0x05,0x23,0x35, 0x33,0x05,0x23,0x35,0x33,0x1b,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x05,0xb5,0xb5,0xb5,0xb5,0xb5,0x00,0x04,0x00,0x03,0xff,0xfb,0x01,0xfe,0x01,0xc8,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x3f,0xb1,0x08,0x00,0xb8,0x05,0x0a,0xb5,0x09,0x01,0x01,0x10,0x0c,0x04,0xb8,0x05,0x0a,0xb3,0x0d,0x05,0x0d,0x08,0xb8, 0x05,0x02,0xb4,0x0e,0x0b,0x0b,0x06,0x02,0xb8,0x05,0x02,0xb4,0x05,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0x32,0xed,0x32,0x33,0x2f,0x33,0xed,0x32,0x01,0x2f,0x33,0xed,0x32,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x17,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x25,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0xbc,0xb9,0xb9,0x01,0x42,0xb9,0xb9, 0xfe,0xbe,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x05,0xb5,0xb5,0xb5,0x63,0xb5,0xb5,0xb5,0x00,0x02,0xff,0xc6,0x00,0x00,0x02,0x2c,0x02,0x62,0x00,0x19,0x00,0x27,0x00,0x44,0xb2,0x27,0x27,0x06,0xb8,0x05,0x0d,0xb3,0x03,0x03,0x28,0x0f,0xb8,0x05,0x0e,0xb4,0x1f,0x06,0x14,0x05,0x0a,0xb8,0x05,0x01,0xb7,0x22,0x00,0x27,0x1a,0x1a,0x03,0x03, 0x00,0xb8,0x05,0x01,0xb4,0x2f,0x14,0x01,0x14,0x02,0x00,0x3f,0x5d,0xed,0x32,0x2f,0x33,0x11,0x33,0x10,0xd4,0xfd,0xc6,0x12,0x39,0x01,0x2f,0xed,0x11,0x33,0x2f,0xed,0x32,0x2f,0x31,0x30,0x27,0x16,0x16,0x17,0x11,0x33,0x11,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x25,0x32,0x3e,0x02,0x35, 0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x3a,0x17,0x3f,0x29,0x59,0x03,0x26,0x67,0x48,0x30,0x45,0x2c,0x15,0x27,0x45,0x5c,0x36,0x47,0x6c,0x53,0x3d,0x18,0x01,0x4f,0x35,0x47,0x2a,0x12,0x41,0x2e,0x23,0x3f,0x35,0x2a,0x0f,0x72,0x02,0x03,0x02,0x01,0xf7,0xfe,0xa5,0x01,0x3e,0x46,0x24,0x3d,0x50,0x2c,0x40,0x46,0x21,0x06,0x01,0x03,0x04, 0x03,0x5e,0x02,0x0e,0x1c,0x1a,0x3b,0x38,0x1f,0x33,0x43,0x24,0x00,0x02,0xff,0x97,0x06,0x7d,0x01,0xf0,0x07,0xe8,0x00,0x1b,0x00,0x29,0x00,0x2b,0xbf,0x00,0x0e,0x05,0x0d,0x00,0x21,0x00,0x09,0x04,0xfd,0x00,0x24,0x00,0x1c,0x04,0xfd,0xb3,0x13,0x27,0x13,0x03,0xb8,0x04,0xfd,0xb1,0x18,0x13,0x00,0x2f,0xdc,0xed,0x11,0x39,0x10,0xfd, 0xd6,0xed,0x01,0x2f,0xed,0x31,0x30,0x03,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x07,0x25,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x69,0x2f,0x4d,0x27,0x0c,0x15,0x0b,0x24,0x77,0x4d,0x27,0x3c,0x29,0x16,0x21,0x39,0x4b,0x2a,0x20, 0x3e,0x3a,0x38,0x19,0x16,0x39,0x23,0x01,0x57,0x1c,0x2b,0x1e,0x10,0x2c,0x1f,0x27,0x4e,0x20,0x1a,0x37,0x06,0xcd,0x20,0x21,0x02,0x03,0x70,0x6f,0x1b,0x2d,0x3a,0x20,0x29,0x49,0x37,0x20,0x10,0x14,0x10,0x13,0x1b,0x56,0x13,0x1e,0x25,0x13,0x22,0x27,0x46,0x53,0x0a,0x0f,0x00,0x01,0x00,0x00,0x04,0x82,0x03,0x4b,0x07,0x38,0x00,0x03, 0x00,0x11,0xb6,0x03,0x01,0x00,0x2f,0x02,0x01,0x02,0x00,0x2f,0x5d,0xcd,0x01,0x2f,0xcd,0x31,0x30,0x11,0x35,0x01,0x15,0x03,0x4b,0x04,0x82,0x94,0x02,0x22,0x94,0x00,0x00,0x01,0x00,0x89,0xfe,0x0a,0x01,0x93,0xff,0xfa,0x00,0x1c,0x00,0x17,0xb9,0x00,0x03,0x05,0x0b,0xb2,0x17,0x1c,0x12,0xb9,0x04,0xfe,0x00,0x08,0x00,0x2f,0xfd,0xc4, 0x01,0x2f,0xed,0x31,0x30,0x05,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x01,0x5d,0x36,0x3a,0x06,0x0c,0x19,0x0e,0x1b,0x29,0x1b,0x0e,0x0f,0x1d,0x2c,0x1d,0x27,0x39,0x24,0x11,0x14,0x2a,0x44,0x30,0x46,0x17,0x57,0x33,0x17,0x16,0x03,0x05,0x14,0x20, 0x29,0x16,0x16,0x2b,0x21,0x15,0x22,0x3a,0x4c,0x2b,0x2c,0x54,0x49,0x3e,0x16,0x00,0x00,0x02,0x00,0x60,0xfd,0xff,0x01,0xa1,0xff,0x40,0x00,0x0b,0x00,0x17,0x00,0x2d,0xbf,0x00,0x03,0x05,0x0e,0x00,0x0f,0x00,0x15,0x05,0x0e,0x00,0x09,0x00,0x06,0x05,0x00,0xb4,0x2f,0x0c,0x01,0x0c,0x12,0xb8,0x05,0x00,0xb3,0x2f,0x00,0x01,0x00,0x00, 0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x05,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x02,0x41,0x5e,0x5e,0x41,0x45,0x5d,0x5d,0x45,0x23,0x31,0x31,0x23,0x25,0x32,0x32,0xc0,0x5d,0x45,0x41,0x5e,0x5e,0x41,0x45,0x5d,0xf6, 0x31,0x23,0x25,0x32,0x32,0x25,0x23,0x31,0x00,0x01,0x00,0x1e,0x04,0x20,0x02,0x8e,0x04,0x8d,0x00,0x03,0x00,0x10,0xb9,0x00,0x00,0x04,0xfd,0xb3,0x2f,0x03,0x01,0x03,0x00,0x2f,0x5d,0xed,0x31,0x30,0x01,0x21,0x35,0x21,0x02,0x8e,0xfd,0x90,0x02,0x70,0x04,0x20,0x6d,0x00,0x00,0x02,0x00,0x3c,0xfd,0xff,0x01,0xc5,0xff,0x67,0x00,0x03, 0x00,0x07,0x00,0x21,0xbc,0x00,0x04,0x05,0x0b,0x00,0x05,0x00,0x00,0x05,0x0b,0xb2,0x01,0x04,0x00,0xb8,0x04,0xfe,0xb1,0x06,0x03,0x00,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x13,0x23,0x11,0x33,0x01,0x23,0x11,0x33,0xb5,0x79,0x79,0x01,0x10,0x79,0x79,0xfd,0xff,0x01,0x68,0xfe,0x98,0x01,0x68,0x00,0x01,0x00,0x17, 0x05,0x44,0x01,0x77,0x07,0x6e,0x00,0x0f,0x00,0x17,0xb9,0x00,0x09,0x05,0x0d,0xb2,0x0a,0x09,0x01,0xb9,0x05,0x01,0x00,0x02,0x00,0x2f,0xed,0x2f,0x01,0x2f,0xed,0x31,0x30,0x13,0x21,0x15,0x23,0x1e,0x03,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x17,0x01,0x60,0xee,0x09,0x0d,0x09,0x04,0x59,0x08,0x0f,0x16,0x07,0x6e,0x66,0x2c,0x4e,0x50, 0x58,0x35,0x6d,0x6a,0x3f,0x6b,0x68,0x6d,0x00,0x01,0x00,0x16,0x05,0x44,0x01,0xfa,0x07,0x6e,0x00,0x33,0x00,0x44,0xb9,0x00,0x31,0x05,0x0d,0xb2,0x2c,0x18,0x1c,0xb8,0x05,0x0d,0xb3,0x07,0x2e,0x1d,0x0a,0xb8,0x05,0x0d,0x40,0x0b,0x04,0x1c,0x18,0x02,0x0f,0x24,0x2f,0x2f,0x07,0x29,0x02,0xb8,0x05,0x01,0xb3,0x0f,0x15,0x15,0x0f,0x00, 0x2f,0x33,0x2f,0x10,0xfd,0x32,0xc6,0x32,0x11,0x33,0x11,0x12,0x39,0x2f,0x01,0x2f,0xed,0x2f,0x39,0x39,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x33,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x07,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x16,0x17, 0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x01,0x36,0x13,0x12,0x45,0x08,0x07,0x59,0x10,0x12,0x24,0x34,0x22,0x14,0x2d,0x19,0x0f,0x30,0x14,0x11,0x0f,0x01,0x06,0x06,0x59,0x07,0x0f,0x17,0x10,0x5c,0x09,0x0e,0x06,0x0f,0x0e,0x1f,0x1f,0x0f,0x58,0x0f,0x06,0x06,0xe6,0x04,0x47,0x12,0x24,0x0f,0x29,0x2b,0x20,0x39, 0x2c,0x19,0x0c,0x0e,0x0d,0x0c,0x03,0x01,0x2d,0x5f,0x42,0x6d,0x6a,0x3f,0x6b,0x68,0x6d,0x41,0x26,0x42,0x20,0x04,0x27,0x21,0x23,0x21,0x23,0x28,0x10,0x20,0x00,0x01,0x00,0x30,0x05,0x44,0x01,0xd9,0x07,0x73,0x00,0x25,0x00,0x2b,0xb9,0x00,0x19,0x05,0x0b,0xb2,0x0c,0x0c,0x12,0xb8,0x05,0x0d,0xb6,0x13,0x13,0x22,0x03,0x25,0x25,0x1c, 0xb8,0x05,0x01,0xb1,0x03,0x09,0x00,0x2f,0xc4,0xed,0x32,0x2f,0x12,0x39,0x2f,0x01,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x06,0x06,0x07,0x23,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x01,0xd9,0x1e,0x2e,0x0f,0x69,0x06,0x14, 0x19,0x20,0x12,0x11,0x0f,0x09,0x0a,0x09,0x59,0x0b,0x0d,0x0b,0x42,0x2e,0x1e,0x33,0x29,0x1e,0x09,0x02,0x0b,0x17,0x10,0x07,0x6e,0x30,0x7c,0x3f,0x18,0x31,0x27,0x19,0x15,0x10,0x0d,0x27,0x46,0x6b,0x51,0x6d,0x6a,0x54,0x74,0x50,0x33,0x13,0x30,0x37,0x14,0x21,0x2b,0x17,0x21,0x35,0x1c,0x00,0x00,0x01,0x00,0x9a,0xff,0xd2,0x06,0xae, 0x02,0xbd,0x00,0x42,0x00,0x4c,0xb9,0x00,0x14,0x05,0x0a,0xb2,0x2f,0x2f,0x0f,0xb8,0x05,0x0a,0xb3,0x34,0x34,0x44,0x27,0xbb,0x05,0x0a,0x00,0x20,0x00,0x0c,0x04,0xff,0xb4,0x2f,0x39,0x01,0x39,0x1b,0xb8,0x04,0xfb,0x40,0x09,0x2f,0x2c,0x01,0x2c,0x2f,0x24,0x01,0x24,0x00,0xba,0x04,0xfb,0x00,0x01,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d, 0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x25,0x15,0x23,0x22,0x2e,0x04,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x35,0x34,0x3e,0x02, 0x33,0x32,0x16,0x17,0x1e,0x05,0x06,0xae,0x16,0x41,0x63,0x4d,0x3a,0x2f,0x27,0x14,0x1a,0x2b,0x1d,0x1c,0x1f,0x12,0x15,0x12,0x29,0x48,0x60,0x6e,0x76,0x39,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x21,0x5a,0xa1,0x81,0xa0,0x91,0x10,0x13,0x10,0x21,0x3a,0x4e,0x2c,0x3d,0x65,0x2a,0x12,0x1e,0x21,0x29,0x3a,0x50,0x99,0xa7,0x22, 0x3a,0x4c,0x53,0x55,0x25,0x33,0x2e,0x24,0x17,0x11,0x27,0x2d,0x36,0x20,0x2e,0x4a,0x39,0x28,0x1b,0x0c,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6f,0x3e,0x4a,0x7c,0x5c,0x33,0x41,0x38,0x14,0x29,0x2b,0x31,0x1d,0x27,0x45,0x33,0x1e,0x41,0x4d,0x20,0x49,0x47,0x41,0x32,0x1d,0x00,0xff,0xff,0xff,0xa2,0x00,0x26,0x02,0xd4,0x06,0xbf, 0x02,0x26,0x0f,0x65,0x00,0x00,0x01,0x06,0x09,0x37,0x00,0x8f,0x00,0x0a,0xb4,0x01,0x2f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x49,0x00,0x26,0x02,0xd4,0x07,0x78,0x02,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x7e,0x00,0x8f,0xff,0xff,0x00,0x72,0xfd,0xfe,0x02,0xd4,0x05,0x58,0x02,0x26,0x0f,0x65,0x00,0x00,0x00,0x06, 0x09,0x7f,0x72,0x00,0x00,0x01,0x00,0x72,0x00,0x26,0x02,0xd4,0x05,0x58,0x00,0x03,0x00,0x0c,0xb4,0x02,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xcd,0x31,0x30,0x25,0x01,0x33,0x01,0x02,0x32,0xfe,0x40,0xa6,0x01,0xbc,0x26,0x05,0x32,0xfa,0xce,0xff,0xff,0xff,0x97,0x00,0x26,0x02,0xd4,0x07,0x77,0x02,0x26,0x0f,0x65,0x00,0x00,0x00,0x06, 0x0f,0x58,0x00,0x8f,0xff,0xff,0xff,0xc2,0x00,0x26,0x02,0xd4,0x07,0x77,0x02,0x26,0x0f,0x65,0x00,0x00,0x01,0x07,0x09,0x77,0x00,0x00,0x08,0x0c,0x00,0x0a,0xb4,0x01,0x20,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x34,0xfd,0xfe,0x02,0xd4,0x05,0x58,0x02,0x26,0x0f,0x65,0x00,0x00,0x00,0x06,0x09,0x77,0x72,0x00,0xff,0xff, 0x00,0x3a,0x00,0x26,0x02,0xf8,0x05,0xe9,0x02,0x26,0x0f,0x65,0xc8,0x00,0x00,0x07,0x09,0x7e,0x01,0x56,0xfe,0x00,0xff,0xff,0x00,0x17,0x00,0x26,0x03,0x7f,0x06,0xf6,0x00,0x27,0x0f,0x65,0x00,0xab,0x00,0x00,0x01,0x06,0x0f,0x5e,0x00,0x88,0x00,0x0a,0xb4,0x01,0x2f,0x04,0x01,0x04,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x16,0x00,0x26, 0x03,0x7f,0x06,0xf6,0x00,0x27,0x0f,0x65,0x00,0xab,0x00,0x00,0x01,0x06,0x0f,0x5f,0x00,0x88,0x00,0x0a,0xb4,0x01,0x2f,0x17,0x01,0x17,0x00,0x11,0x5d,0x35,0x00,0x01,0xff,0xc8,0xff,0xf2,0x05,0x49,0x03,0x0f,0x00,0x37,0x00,0x4b,0xb9,0x00,0x1a,0x05,0x0a,0xb2,0x17,0x23,0x0d,0xbb,0x05,0x0a,0x00,0x0a,0x00,0x00,0x05,0x0a,0xb3,0x30, 0x30,0x30,0x33,0xb8,0x04,0xff,0xb6,0x2f,0x34,0x01,0x34,0x23,0x12,0x05,0xbc,0x04,0xfb,0x00,0x28,0x05,0x03,0x00,0x1f,0x05,0x03,0xb4,0x18,0x2f,0x0b,0x01,0x0b,0x00,0x2f,0x5d,0xc6,0x3f,0x3f,0xed,0x32,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x01,0x2f,0xed,0xd4,0xed,0x39,0xd4,0xed,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35, 0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x04,0x35,0x35,0x26,0x26,0x23,0x37,0x32,0x16,0x17,0x01,0x47,0x0b,0x24,0x44,0x39,0x24,0x43,0x33,0x1f,0x9c,0x0b,0x27,0x48,0x3e,0x26,0x40,0x2e,0x19,0x9c,0x39,0x5d,0x77,0x3f,0x5b,0x84,0x24, 0x04,0x1a,0x42,0x47,0x48,0x21,0x46,0x65,0x47,0x2c,0x18,0x09,0x3a,0x70,0x39,0x17,0x57,0xb6,0x5b,0x01,0x95,0x41,0x5f,0x3e,0x1e,0x10,0x2a,0x48,0x38,0x01,0x0b,0xc6,0x43,0x60,0x3e,0x1e,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x37,0x6c,0x85,0x4a,0x19,0x36,0x45,0x23,0x2f,0x1d,0x0c,0x21,0x37,0x48,0x4e,0x50,0x23,0x13,0x05,0x03,0x9c, 0x09,0x08,0x00,0x01,0xff,0xc8,0xff,0xf2,0x06,0x03,0x03,0x0f,0x00,0x44,0x00,0x5c,0xb1,0x35,0x2a,0xb8,0x05,0x0a,0xb2,0x27,0x40,0x1d,0x41,0x09,0x05,0x0a,0x00,0x1a,0x00,0x10,0x05,0x0a,0x00,0x08,0x00,0x3a,0x05,0x03,0x00,0x30,0x05,0x03,0xb7,0x28,0x2f,0x1b,0x01,0x1b,0x08,0x08,0x0b,0xb8,0x04,0xff,0x40,0x0b,0x2f,0x0c,0x01,0x0c, 0x40,0x35,0x00,0x2f,0x22,0x22,0x15,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x32,0x11,0x33,0x11,0x39,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x2f,0x5d,0xc6,0x3f,0x3f,0x01,0x2f,0xed,0xd4,0xed,0x39,0xd4,0xed,0x39,0x31,0x30,0x05,0x22,0x2e,0x04,0x35,0x35,0x26,0x26,0x23,0x37,0x32,0x16,0x17,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e, 0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x01,0xea,0x46,0x65,0x47,0x2c,0x18,0x09,0x3a,0x70,0x39,0x17,0x57,0xb6,0x5b,0x0b,0x24,0x44,0x39,0x24,0x43,0x33,0x1f,0x9c,0x0b,0x27,0x48,0x3e, 0x26,0x40,0x2e,0x19,0x9c,0x0c,0x27,0x49,0x3e,0x16,0x5d,0x70,0x1f,0x06,0x17,0x3a,0x42,0x47,0x24,0x2c,0x4f,0x42,0x34,0x12,0x04,0x1a,0x42,0x47,0x48,0x0e,0x21,0x37,0x48,0x4e,0x50,0x23,0x13,0x05,0x03,0x9c,0x09,0x08,0x64,0x41,0x5f,0x3e,0x1e,0x10,0x2a,0x48,0x38,0x01,0x0b,0xc6,0x43,0x60,0x3e,0x1e,0x0f,0x2a,0x48,0x39,0x01,0xbc, 0xfe,0x8f,0x43,0x62,0x41,0x1f,0xa7,0x36,0x39,0x21,0x2a,0x1a,0x0a,0x0d,0x1c,0x2f,0x23,0x23,0x2f,0x1d,0x0c,0x00,0xff,0xff,0xff,0xc8,0xff,0xf2,0x05,0x49,0x05,0x1f,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xff,0xf2,0x06,0x03,0x05,0x1f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x07, 0x0f,0x53,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x05,0x49,0x04,0x07,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0xf9,0x03,0x57,0x00,0x07,0x0f,0x50,0x01,0xf9,0xfe,0xab,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x06,0x03,0x04,0x07,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x27,0x0f,0x50,0x01,0xf9,0x03,0x57,0x00,0x07, 0x0f,0x50,0x01,0xf9,0xfe,0xab,0xff,0xff,0xff,0xc8,0xfd,0xc9,0x05,0x49,0x03,0x0f,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0xf9,0xfd,0xce,0xff,0xff,0xff,0xc8,0xfd,0xc9,0x06,0x03,0x03,0x0f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0xf9,0xfd,0xce,0xff,0xff,0xff,0xc8,0xfd,0xc9,0x05,0x49,0x05,0x1f, 0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x27,0x0f,0x54,0x01,0xf9,0xfd,0xce,0x00,0x07,0x0f,0x53,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xfd,0xc9,0x06,0x03,0x05,0x1f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x27,0x0f,0x53,0x01,0xf9,0x03,0x57,0x00,0x07,0x0f,0x54,0x01,0xf9,0xfd,0xce,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x05,0x49,0x05,0x1f, 0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x27,0x0f,0x53,0x01,0xf9,0x03,0x57,0x00,0x07,0x0f,0x50,0x01,0xf9,0xfe,0xab,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x06,0x03,0x05,0x1f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x27,0x0f,0x53,0x01,0xf9,0x03,0x57,0x00,0x07,0x0f,0x50,0x01,0xf9,0xfe,0xab,0xff,0xff,0xff,0xc8,0xff,0xf2,0x05,0x49,0x05,0x1f, 0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xff,0xf2,0x06,0x03,0x05,0x1f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xff,0xf2,0x05,0x49,0x05,0x1f,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0xf9,0x03,0x57,0xff,0xff, 0xff,0xc8,0xff,0xf2,0x06,0x03,0x05,0x1f,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0xf9,0x03,0x57,0xff,0xff,0xff,0xc8,0xff,0xf2,0x05,0x49,0x07,0x0d,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x27,0x0f,0x51,0x01,0xf9,0x03,0x57,0x01,0x07,0x0f,0x57,0x01,0xf9,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x3d,0x01,0x3d,0x00, 0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xc8,0xff,0xf2,0x06,0x03,0x07,0x0d,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x27,0x0f,0x57,0x01,0xf9,0x04,0xab,0x01,0x07,0x0f,0x51,0x01,0xf9,0x03,0x57,0x00,0x0c,0xb5,0x04,0x03,0x20,0x72,0x01,0x72,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0xff,0xc8,0xff,0xf2,0x05,0x49,0x05,0x50,0x02,0x26,0x0f,0x6c, 0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0xf2,0xfd,0xdd,0x00,0x0a,0xb4,0x01,0x2f,0x54,0x01,0x54,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xc8,0xff,0xf2,0x06,0x03,0x05,0x50,0x02,0x26,0x0f,0x6d,0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0xf2,0xfd,0xdd,0x00,0x0a,0xb4,0x01,0x2f,0x54,0x01,0x54,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xc8,0xff,0xf2, 0x05,0x49,0x04,0xb8,0x02,0x26,0x0f,0x6c,0x00,0x00,0x00,0x07,0x0a,0x6e,0x01,0xf9,0xfc,0xdc,0xff,0xff,0xff,0xc8,0xff,0xf2,0x06,0x03,0x04,0xb8,0x02,0x26,0x0f,0x6d,0x00,0x00,0x00,0x07,0x0a,0x6e,0x01,0xf9,0xfc,0xdc,0x00,0x02,0xff,0xc8,0xff,0xea,0x06,0xa0,0x03,0x3c,0x00,0x30,0x00,0x42,0x00,0x44,0xb9,0x00,0x0c,0x05,0x0a,0xb7, 0x36,0x36,0x44,0x40,0x00,0x20,0x20,0x23,0xb8,0x04,0xff,0x40,0x09,0x2f,0x24,0x01,0x24,0x40,0x40,0x31,0x31,0x00,0xbc,0x04,0xfb,0x00,0x13,0x05,0x03,0x00,0x3b,0x04,0xfb,0xb3,0x2f,0x07,0x01,0x07,0x00,0x2f,0x5d,0xed,0x3f,0xed,0x32,0x11,0x33,0x2f,0x2f,0x5d,0xed,0x32,0x2f,0x01,0x2f,0xcd,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x3e, 0x05,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x24,0x26,0x26,0x27,0x2e,0x03,0x27,0x26,0x26,0x27,0x26,0x26,0x23,0x37,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x16,0x16,0x01,0xd4,0x18,0x4c,0x67,0x81,0x9a,0xb3,0x66,0x79,0xae,0x70,0x36,0x2d,0x52,0x71, 0x88,0x9a,0x52,0xb3,0xff,0x00,0xaf,0x68,0x1c,0x2e,0x3b,0x24,0x13,0x07,0x05,0x04,0x04,0x3c,0x68,0x36,0x17,0x42,0xae,0x5b,0x06,0x09,0x07,0x06,0x04,0x03,0x0d,0x1e,0x33,0x02,0xa7,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x6e,0xbc,0x97,0x6e,0x1f,0x5c,0xee,0x9b,0x41,0x96,0x95,0x8b,0x6a,0x40,0x4b,0x80,0xab,0x60,0x5d,0x80,0x55, 0x2f,0x16,0x05,0x01,0x06,0x0d,0x0c,0x14,0x35,0x3f,0x47,0x27,0x1a,0x31,0x1c,0x03,0x04,0x9c,0x06,0x07,0x21,0x3a,0x37,0x37,0x1e,0x1a,0x2c,0x20,0x13,0x0a,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0x5c,0x92,0xb5,0x5a,0x02,0x01,0x00,0x02,0xff,0xc8,0xff,0xea,0x07,0x59,0x03,0x3c,0x00,0x39,0x00,0x4b,0x00,0x50,0xb9,0x00,0x05,0x05, 0x0a,0x40,0x09,0x47,0x47,0x0b,0x3f,0x33,0x0b,0x22,0x22,0x25,0xb8,0x04,0xff,0xb4,0x2f,0x26,0x01,0x26,0x15,0xb8,0x05,0x03,0xb6,0x42,0x3f,0x3f,0x33,0x33,0x10,0x0a,0xbc,0x04,0xfb,0x00,0x0b,0x05,0x03,0x00,0x3a,0x04,0xfb,0xb3,0x2f,0x00,0x01,0x00,0x00,0x2f,0x5d,0xed,0x3f,0xed,0x39,0x32,0x2f,0x33,0x2f,0x33,0x3f,0x2f,0x5d,0xed, 0x32,0x2f,0x01,0x2f,0x2f,0xcd,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x24,0x26,0x26,0x27,0x2e,0x03,0x27,0x26,0x26,0x27,0x26,0x26,0x23,0x37,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03,0x17,0x3e,0x05,0x17,0x22,0x0e,0x02,0x07,0x16,0x16,0x33,0x32, 0x3e,0x02,0x35,0x34,0x2e,0x02,0x04,0xd3,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26,0x70,0x89,0x9d,0x54,0xb3,0xff,0x00,0xaf,0x68,0x1c,0x2e,0x3b,0x24,0x13,0x07,0x05,0x04,0x04,0x3c,0x68,0x36,0x17,0x42,0xae,0x5b,0x06,0x09,0x07,0x06,0x04,0x03,0x0d,0x1e,0x33,0x29,0x18,0x4c,0x67,0x81,0x9a, 0xb3,0x4c,0x6e,0xbc,0x97,0x6e,0x1f,0x5c,0xee,0x9d,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x03,0x3c,0x49,0x7d,0xa4,0x5b,0x3a,0x54,0x36,0x1a,0xa7,0x3a,0x45,0x31,0x36,0x1a,0x06,0x01,0x06,0x0d,0x0c,0x14,0x35,0x3f,0x47,0x27,0x1a,0x31,0x1c,0x03,0x04,0x9c,0x06,0x07,0x21,0x3a,0x37,0x37,0x1e,0x1a,0x2c,0x20,0x13,0x02,0x41,0x96,0x95, 0x8b,0x6a,0x40,0xa9,0x5c,0x92,0xb5,0x5a,0x02,0x01,0x0a,0x27,0x4f,0x45,0x56,0x78,0x4b,0x22,0xff,0xff,0xff,0xc8,0xff,0xea,0x06,0xa0,0x04,0xb2,0x02,0x26,0x0f,0x82,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x73,0x04,0x02,0xff,0xff,0xff,0xc8,0xff,0xea,0x07,0x59,0x04,0xb2,0x02,0x26,0x0f,0x83,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x73, 0x04,0x02,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x06,0xa0,0x03,0x3c,0x02,0x26,0x0f,0x82,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xdb,0xfe,0xab,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x07,0x59,0x03,0x3c,0x02,0x26,0x0f,0x83,0x00,0x00,0x00,0x07,0x0f,0x51,0x02,0xdb,0xfe,0xab,0xff,0xff,0xff,0xc8,0xff,0xea,0x06,0xa0,0x05,0xca,0x02,0x26,0x0f,0x82, 0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0x73,0x04,0x02,0xff,0xff,0xff,0xc8,0xff,0xea,0x07,0x59,0x05,0xca,0x02,0x26,0x0f,0x83,0x00,0x00,0x00,0x07,0x0f,0x53,0x02,0x73,0x04,0x02,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x06,0xa0,0x04,0xb2,0x02,0x26,0x0f,0x82,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0x73,0x04,0x02,0x00,0x07,0x0f,0x50,0x02,0xe5, 0xfe,0xab,0xff,0xff,0xff,0xc8,0xfe,0xa6,0x07,0x59,0x04,0xb2,0x02,0x26,0x0f,0x83,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0x73,0x04,0x02,0x00,0x07,0x0f,0x50,0x02,0xe5,0xfe,0xab,0x00,0x01,0xfd,0xa6,0xff,0xea,0x01,0x47,0x05,0xec,0x00,0x15,0x00,0x1a,0xbf,0x00,0x0b,0x05,0x0a,0x00,0x08,0x00,0x03,0x04,0xfb,0x00,0x12,0x05,0x03,0x00, 0x0a,0x00,0x2f,0x3f,0xed,0x01,0x2f,0xed,0x31,0x30,0x25,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x22,0x26,0x27,0xfd,0xa6,0x7f,0xe1,0x6d,0x4f,0x75,0x4e,0x26,0x9c,0x23,0x3f,0x5a,0x6e,0x81,0x46,0x61,0xcb,0x64,0xa8,0x0f,0x09,0x06,0x25,0x4f,0x49,0x04,0x99,0xfb,0x60,0x56,0x77,0x4f,0x2c,0x15,0x05, 0x0a,0x0e,0x00,0x01,0xfd,0xa6,0xff,0xea,0x02,0x01,0x05,0xec,0x00,0x1e,0x00,0x29,0xb1,0x16,0x0b,0xb8,0x05,0x0a,0xb5,0x08,0x16,0x1b,0x10,0x10,0x03,0xbd,0x04,0xfb,0x00,0x1b,0x05,0x03,0x00,0x11,0x05,0x03,0x00,0x0a,0x00,0x2f,0x3f,0x3f,0xed,0x32,0x2f,0x11,0x39,0x01,0x2f,0xed,0x39,0x31,0x30,0x25,0x16,0x16,0x33,0x32,0x3e,0x02, 0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0xfd,0xa6,0x7f,0xe1,0x6d,0x4f,0x75,0x4e,0x26,0x9c,0x0f,0x2a,0x48,0x39,0x16,0x5a,0x6d,0x1e,0x04,0x1d,0x56,0x6d,0x82,0x4a,0x61,0xcb,0x64,0xa8,0x0f,0x09,0x06,0x25,0x4f,0x49,0x04,0x99,0xfb,0xac,0x47,0x62,0x3c,0x1a,0xa7,0x3b, 0x3c,0x2d,0x33,0x19,0x06,0x0a,0x0e,0x00,0xff,0xff,0xfd,0xa6,0xff,0xea,0x02,0x1a,0x08,0x0e,0x02,0x26,0x0f,0x8c,0x00,0x00,0x00,0x06,0x0a,0x6d,0xf2,0x32,0xff,0xff,0xfd,0xa6,0xff,0xea,0x02,0x1a,0x08,0x0e,0x02,0x26,0x0f,0x8d,0x00,0x00,0x00,0x06,0x0a,0x6d,0xf2,0x32,0xff,0xff,0xfd,0xa6,0xff,0xea,0x01,0x4f,0x07,0x67,0x02,0x26, 0x0f,0x8c,0x00,0x00,0x00,0x07,0x0f,0x50,0xff,0xf2,0x06,0xb7,0xff,0xff,0xfd,0xa6,0xff,0xea,0x02,0x01,0x07,0x67,0x02,0x26,0x0f,0x8d,0x00,0x00,0x00,0x07,0x0f,0x50,0xff,0xf2,0x06,0xb7,0xff,0xff,0xfd,0xa6,0xff,0xea,0x01,0xf0,0x08,0x7f,0x02,0x26,0x0f,0x8c,0x00,0x00,0x01,0x07,0x0f,0x53,0xff,0xf2,0x06,0xb7,0x00,0x0e,0xb6,0x03, 0x02,0x01,0x20,0x18,0x01,0x18,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0xfd,0xa6,0xff,0xea,0x02,0x01,0x08,0x7f,0x02,0x26,0x0f,0x8d,0x00,0x00,0x01,0x07,0x0f,0x53,0xff,0xf2,0x06,0xb7,0x00,0x0e,0xb6,0x03,0x02,0x01,0x20,0x29,0x01,0x29,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0xfd,0xa6,0xfd,0xc9,0x01,0xf0,0x05,0xec,0x02,0x26, 0x0f,0x8c,0x00,0x00,0x00,0x07,0x0f,0x54,0xff,0xf2,0xfd,0xce,0xff,0xff,0xfd,0xa6,0xfd,0xc9,0x02,0x01,0x05,0xec,0x02,0x26,0x0f,0x8d,0x00,0x00,0x00,0x07,0x0f,0x54,0xff,0xf2,0xfd,0xce,0xff,0xff,0xfd,0xa6,0xff,0xea,0x01,0xfb,0x05,0xec,0x02,0x26,0x0f,0x8c,0x00,0x00,0x00,0x07,0x0f,0x5c,0xff,0x6d,0x00,0x00,0xff,0xff,0xfd,0xa6, 0xff,0xea,0x02,0x01,0x05,0xec,0x02,0x26,0x0f,0x8d,0x00,0x00,0x00,0x07,0x0f,0x5c,0xff,0x6d,0x00,0x00,0x00,0x01,0x00,0x39,0xfd,0xff,0x03,0x72,0x02,0x0a,0x00,0x22,0x00,0x2c,0xbc,0x00,0x0b,0x05,0x0a,0x00,0x1b,0x00,0x16,0x04,0xfb,0x40,0x09,0x1f,0x10,0x2f,0x10,0x02,0x10,0x08,0x08,0x06,0xb8,0x04,0xff,0xb3,0x2f,0x00,0x01,0x00, 0x00,0x2f,0x5d,0xed,0x32,0x2f,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x01,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x3e,0x03,0x03,0x35,0x1d,0x20,0x28,0x2c,0x3c,0x30,0x11,0x14,0x44,0x79,0xa7,0x62,0x33,0x6c,0x39,0x7c,0x59, 0x55,0x74,0x45,0x1e,0x2d,0x20,0x2a,0x5b,0x57,0x4e,0x02,0x0a,0x2f,0x1d,0x1e,0x32,0x03,0x52,0x9c,0x46,0x8a,0xd4,0x90,0x4a,0x16,0x17,0xa5,0x27,0x3d,0x6c,0x92,0x56,0x76,0xda,0x67,0x06,0x09,0x06,0x03,0x00,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x04,0x07,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x0c,0x03,0x57, 0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x05,0xb9,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x57,0x01,0x0c,0x03,0x57,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x04,0xaf,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0a,0x6d,0x01,0x0c,0xfc,0xd3,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x02,0x0a,0x02,0x26,0x0f,0x98,0x00,0x00, 0x00,0x07,0x0f,0x5b,0x01,0xc9,0x00,0x00,0xff,0xff,0x00,0x39,0xfd,0xfb,0x03,0x88,0x02,0x0a,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x50,0x02,0x2b,0xfe,0x00,0xff,0xff,0x00,0x39,0xfd,0xe1,0x04,0x6a,0x02,0x0a,0x02,0x26,0x0f,0x98,0x00,0x00,0x01,0x07,0x0a,0x6d,0x02,0x42,0xf7,0x65,0x00,0x0a,0xb4,0x01,0x2f,0x27,0x01,0x27, 0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x39,0xfd,0xfb,0x03,0x88,0x04,0x07,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0x2b,0xfe,0x00,0x00,0x07,0x0f,0x50,0x01,0x0c,0x03,0x57,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x04,0x07,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0x0c,0x03,0x57,0xff,0xff,0x00,0x39, 0xfd,0xff,0x03,0x72,0x05,0x1f,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x56,0x01,0x0c,0x03,0x57,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x04,0xaf,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0a,0x6e,0x01,0x0c,0xfc,0xd3,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x87,0x02,0x0a,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x5c, 0x00,0xf9,0xfc,0x4f,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x05,0x1f,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x52,0x01,0x0c,0x03,0x57,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x04,0xbc,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x09,0x7e,0x01,0x0c,0xfc,0xd3,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x07,0x0d,0x02,0x26, 0x0f,0x98,0x00,0x00,0x00,0x27,0x0f,0x51,0x01,0x0c,0x03,0x57,0x01,0x07,0x0f,0x57,0x01,0x0c,0x04,0xab,0x00,0x0c,0xb5,0x02,0x01,0x20,0x24,0x01,0x24,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x82,0xff,0x02,0x05,0x74,0x04,0x21,0x02,0x26,0x0f,0xab,0x00,0x00,0x01,0x07,0x09,0x7e,0x00,0x39,0xfc,0x38,0x00,0x0a,0xb4,0x01,0x2f,0x4d, 0x01,0x4d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x04,0x2c,0x02,0x26,0x0f,0xab,0x00,0x00,0x01,0x07,0x0a,0x6e,0x02,0x01,0xfc,0x50,0x00,0x0a,0xb4,0x01,0x2f,0x3d,0x01,0x3d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x03,0xb9,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x07,0x0f,0x51,0x01,0xdc, 0x03,0x09,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x04,0xd1,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0xdc,0x03,0x09,0x00,0x01,0x00,0x9a,0xff,0x02,0x05,0x74,0x02,0x0a,0x00,0x36,0x00,0x41,0xb9,0x00,0x0a,0x05,0x0a,0xb2,0x25,0x25,0x05,0xb8,0x05,0x0a,0xb3,0x2c,0x2c,0x38,0x1d,0xbb,0x05,0x0a,0x00,0x16,0x00,0x00, 0x04,0xff,0xb4,0x2f,0x31,0x01,0x31,0x11,0xb8,0x04,0xfb,0xb7,0x2f,0x22,0x01,0x22,0x2f,0x1a,0x01,0x1a,0x00,0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06, 0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x20,0x3b,0x43,0x21,0x08,0x22,0x29,0x22,0x2e,0x51,0x6e,0x7d,0x88,0x43,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x20,0x5b,0xa2,0x83,0xbc,0xb9,0x10,0x18,0x1b,0x18,0x10,0x29,0x54,0x81,0x58,0x1d,0x20,0x28,0x01, 0x6e,0x13,0x1b,0x1e,0x0b,0x22,0x2a,0x2c,0x3b,0x33,0x39,0x5a,0x43,0x2f,0x1d,0x0d,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6e,0x40,0x4a,0x7c,0x5b,0x33,0x48,0x3d,0x13,0x1d,0x1b,0x1e,0x26,0x33,0x23,0x37,0x5b,0x40,0x23,0x2f,0x1d,0x1e,0x32,0x00,0xff,0xff,0x00,0x9a,0xfd,0xd3,0x05,0x74,0x02,0x0a,0x02,0x26,0x0f,0xab,0x00,0x00, 0x00,0x07,0x0f,0x51,0x02,0x01,0xfd,0xd8,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0xdd,0x05,0x3e,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x07,0x09,0x7e,0x04,0x3b,0xfd,0x55,0x00,0x01,0x00,0x1e,0xff,0x02,0x06,0x1f,0x02,0x0a,0x00,0x38,0x00,0x58,0xb9,0x00,0x1d,0x05,0x0a,0xb5,0x2d,0x2d,0x16,0x0b,0x05,0x32,0xb8,0x05,0x0a,0xb3,0x16,0x16, 0x3a,0x0e,0xb8,0x05,0x0a,0x40,0x0d,0x05,0x08,0x08,0x05,0x09,0x0a,0x0a,0x0b,0x0b,0x22,0x08,0x08,0x28,0xb8,0x04,0xff,0xb4,0x2f,0x22,0x01,0x22,0x00,0xb8,0x04,0xfb,0xb3,0x2f,0x13,0x01,0x13,0x00,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x32,0x2f,0x11,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x11,0x39, 0x11,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05,0x35,0x25,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x03,0x5c,0x98,0xcc,0x7d,0x35,0x04,0x04,0xfe,0xd0,0x01,0xe3, 0x0e,0x12,0x24,0x5d,0xa2,0x7e,0xbc,0xb9,0x10,0x18,0x1b,0x18,0x10,0x29,0x54,0x81,0x58,0x1d,0x20,0x28,0x2c,0x3b,0x43,0x21,0x08,0x22,0x29,0x22,0x2e,0x51,0x6e,0x7d,0x88,0xfe,0x4b,0x81,0xad,0x63,0x1f,0x49,0x23,0x39,0x72,0x5f,0x49,0x79,0x3f,0x4d,0x7d,0x5a,0x31,0x48,0x3d,0x13,0x1d,0x1b,0x1e,0x26,0x33,0x23,0x37,0x5b,0x40,0x23, 0x2f,0x1d,0x1e,0x32,0x13,0x1b,0x1e,0x0b,0x22,0x2a,0x2c,0x3b,0x33,0x39,0x5a,0x43,0x2f,0x1d,0x0d,0x00,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x04,0x2c,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x07,0x0a,0x6d,0x02,0x01,0xfc,0x50,0xff,0xff,0x00,0x9a,0xfd,0xc4,0x05,0x74,0x02,0xbd,0x02,0x26,0x0f,0xb4,0x00,0x00,0x00,0x07,0x0f,0x54, 0x01,0xc8,0xfd,0xc9,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x04,0xdf,0x02,0x26,0x0f,0xab,0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xa1,0xfd,0x71,0x00,0x0e,0xb7,0x01,0x2f,0x37,0x01,0x2f,0x37,0x01,0x37,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x04,0xdf,0x02,0x26,0x0f,0xab,0x00,0x00,0x01,0x07,0x0f,0x5f, 0x00,0xa1,0xfd,0x71,0x00,0x0e,0xb7,0x01,0x2f,0x37,0x01,0x2f,0x37,0x01,0x37,0x00,0x11,0x5d,0x5d,0x35,0xff,0xff,0x00,0x9a,0xfd,0x78,0x05,0x74,0x02,0xbd,0x02,0x26,0x0f,0xb4,0x00,0x00,0x01,0x07,0x0f,0x60,0x01,0xc8,0xf8,0x34,0x00,0x0a,0xb4,0x01,0x2f,0x37,0x01,0x37,0x00,0x11,0x5d,0x35,0x00,0x01,0x00,0x9a,0xff,0xd2,0x05,0x74, 0x02,0xbd,0x00,0x32,0x00,0x41,0xb9,0x00,0x0a,0x05,0x0a,0xb2,0x25,0x25,0x05,0xb8,0x05,0x0a,0xb3,0x2a,0x2a,0x34,0x1d,0xbb,0x05,0x0a,0x00,0x16,0x00,0x00,0x04,0xff,0xb4,0x2f,0x2d,0x01,0x2d,0x11,0xb8,0x04,0xfb,0xb7,0x2f,0x22,0x01,0x22,0x2f,0x1a,0x01,0x1a,0x00,0x2f,0x5d,0x2f,0x5d,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x12,0x39, 0x2f,0xed,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x20,0x38,0x40,0x1f,0x07,0x0c,0x0f,0x0d,0x29,0x47,0x60,0x70,0x7b, 0x3e,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x20,0x5b,0xa2,0x83,0xa9,0x96,0x0e,0x12,0x0e,0xae,0xa1,0x1d,0x20,0x28,0x01,0x6e,0x0a,0x10,0x12,0x07,0x0c,0x15,0x19,0x20,0x17,0x2d,0x48,0x37,0x27,0x19,0x0c,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6e,0x40,0x4a,0x7c,0x5b,0x33,0x30,0x29,0x0e,0x1a,0x1c,0x21,0x17,0x59,0x61, 0x2f,0x1d,0x1e,0x32,0x00,0x01,0x00,0x72,0xfe,0x28,0x06,0xe5,0x00,0x99,0x00,0x25,0x00,0x23,0xbc,0x00,0x06,0x05,0x0a,0x00,0x1d,0x00,0x0b,0x04,0xfb,0xb4,0x2f,0x16,0x01,0x16,0x24,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x01,0x2f,0xed,0x31,0x30,0x05,0x21,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32, 0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x04,0x35,0x34,0x3e,0x04,0x33,0x21,0x04,0xad,0xfd,0xf2,0x43,0x8e,0x75,0x4b,0x45,0x93,0xe5,0xa1,0x7b,0xf4,0xe5,0xcf,0x56,0x72,0xf9,0xf0,0xda,0x54,0x93,0xe1,0xa6,0x70,0x43,0x1d,0x3d,0x63,0x7c,0x7d,0x72,0x27,0x02,0x09,0x0e,0x04,0x19,0x37,0x32,0x2e,0x3c,0x23,0x0e,0x07,0x0c,0x10, 0x09,0xa5,0x0c,0x12,0x0c,0x06,0x12,0x24,0x35,0x45,0x55,0x32,0x4a,0x69,0x45,0x28,0x15,0x05,0x00,0x01,0x00,0x72,0xfe,0x28,0x06,0xe5,0x00,0x99,0x00,0x25,0x00,0x23,0xbc,0x00,0x06,0x05,0x0a,0x00,0x1d,0x00,0x0b,0x04,0xfb,0xb4,0x2f,0x16,0x01,0x16,0x24,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0xed,0x01,0x2f, 0xed,0x31,0x30,0x05,0x21,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x04,0x35,0x34,0x3e,0x04,0x33,0x21,0x06,0xae,0xfb,0xf1,0x43,0x8e,0x75,0x4b,0x45,0x93,0xe5,0xa1,0x7b,0xf4,0xe5,0xcf,0x56,0x72,0xf9,0xf0,0xda,0x54,0x93,0xe1,0xa6,0x70,0x43,0x1d,0x3d,0x63,0x7c,0x7d,0x72,0x27, 0x04,0x0a,0x0e,0x04,0x19,0x37,0x32,0x2e,0x3c,0x23,0x0e,0x07,0x0c,0x10,0x09,0xa5,0x0c,0x12,0x0c,0x06,0x12,0x24,0x35,0x45,0x55,0x32,0x4a,0x69,0x45,0x28,0x15,0x05,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x3d,0x02,0x26,0x0f,0xb5,0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0xab,0xfb,0x54,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5, 0x03,0x3d,0x02,0x26,0x0f,0xb6,0x00,0x00,0x00,0x07,0x09,0x7e,0x00,0xab,0xfb,0x54,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26,0x0f,0xb5,0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xab,0xfb,0xff,0x00,0x0a,0xb4,0x01,0x2f,0x26,0x01,0x26,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26, 0x0f,0xb6,0x00,0x00,0x01,0x07,0x0f,0x5e,0x00,0xab,0xfb,0xff,0x00,0x0a,0xb4,0x01,0x2f,0x26,0x01,0x26,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x72,0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26,0x0f,0xb5,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xab,0xfb,0xff,0x00,0x0a,0xb4,0x01,0x2f,0x37,0x01,0x37,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x72, 0xfe,0x28,0x06,0xe5,0x03,0x6d,0x02,0x26,0x0f,0xb6,0x00,0x00,0x01,0x07,0x0f,0x5f,0x00,0xab,0xfb,0xff,0x00,0x0a,0xb4,0x01,0x2f,0x37,0x01,0x37,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x05,0x74,0x02,0x0a,0x02,0x06,0x0f,0xab,0x00,0x00,0xff,0xff,0x00,0x9a,0xfd,0xc4,0x05,0x74,0x02,0xbd,0x02,0x26,0x0f,0xb4,0x00,0x00, 0x00,0x07,0x0f,0x52,0x01,0xc8,0xfd,0xc9,0xff,0xff,0x00,0x9a,0xfe,0x0e,0x05,0x74,0x02,0x0a,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x07,0x0f,0x5b,0x02,0x01,0x00,0x0f,0x00,0x01,0xff,0xf1,0xff,0xf2,0x01,0x47,0x05,0x7e,0x00,0x0d,0x00,0x1a,0xbf,0x00,0x08,0x05,0x0a,0x00,0x05,0x00,0x00,0x04,0xfb,0x00,0x0d,0x05,0x03,0x00,0x07,0x00, 0x2f,0x3f,0xed,0x01,0x2f,0xed,0x31,0x30,0x27,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x09,0x25,0x42,0x31,0x1c,0x9c,0x3c,0x61,0x7b,0x3e,0x99,0x16,0x2d,0x46,0x31,0x04,0x2b,0xfb,0xce,0x65,0x86,0x4f,0x20,0x00,0x00,0x01,0xff,0xea,0xff,0xf2,0x02,0x24,0x04,0xe8,0x00,0x1c,0x00,0x22,0xb9,0x00,0x00,0x05,0x0a,0xb5, 0x1a,0x10,0x0d,0x1c,0x15,0x05,0xbb,0x04,0xfb,0x00,0x14,0x00,0x0d,0x05,0x03,0x00,0x3f,0x33,0xed,0x32,0x2f,0x12,0x39,0x01,0x2f,0xed,0x31,0x30,0x01,0x14,0x1e,0x02,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x37,0x32,0x3e,0x02,0x35,0x11,0x33,0x01,0x47,0x0c,0x26,0x46,0x39,0x16,0x16,0x06,0x0d, 0x13,0x0c,0x68,0x75,0x1c,0x04,0x31,0x91,0x49,0x0a,0x1c,0x41,0x36,0x24,0x9c,0x01,0x8c,0x3b,0x5a,0x3e,0x20,0x31,0x1f,0x10,0x1f,0x19,0x0f,0x40,0x3b,0x3f,0x3c,0xa7,0x13,0x2c,0x47,0x34,0x03,0x95,0x00,0x02,0x00,0xa1,0xff,0xf2,0x04,0x25,0x03,0xd7,0x00,0x21,0x00,0x2f,0x00,0x48,0xb9,0x00,0x15,0x05,0x0a,0xb5,0x12,0x05,0x2a,0x2a, 0x31,0x22,0xbb,0x05,0x0a,0x00,0x0d,0x00,0x2b,0x04,0xfc,0xb2,0x12,0x14,0x2a,0xb8,0x04,0xfc,0x40,0x0a,0x15,0x14,0x05,0x05,0x00,0x2f,0x14,0x01,0x14,0x1a,0xba,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0x5d,0x12,0x39,0x2f,0x12,0x39,0xed,0x10,0xdd,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0x33,0xed,0x31,0x30,0x05,0x22, 0x2e,0x02,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x01,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x11,0x0e,0x03,0x03,0xec,0x38,0x64,0x50,0x3a,0x0e,0x2b,0x62,0x2a,0x45,0x7f,0x62,0x3a,0x58,0x92,0xbc,0x65,0x9c,0x0e,0x26,0x44,0x36,0x17,0x18,0x07, 0x0e,0x16,0xfd,0x3d,0x23,0x3c,0x4e,0x2a,0x27,0x55,0x22,0x4d,0x87,0x66,0x3b,0x0e,0x19,0x35,0x52,0x3a,0x11,0x0c,0x20,0x45,0x6c,0x4d,0x5e,0x92,0x68,0x42,0x0f,0x61,0xfd,0xb5,0x3d,0x5b,0x3d,0x1e,0x31,0x1e,0x10,0x20,0x19,0x0f,0x01,0xea,0x26,0x35,0x21,0x0e,0x0a,0x0b,0x01,0x76,0x0e,0x2f,0x41,0x52,0xff,0xff,0x00,0x39,0xfd,0xff, 0x03,0x72,0x05,0x1f,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07,0x0f,0x53,0x01,0x0c,0x03,0x57,0x00,0x01,0x00,0x64,0x00,0x00,0x04,0x77,0x05,0xb2,0x00,0x23,0x00,0x65,0x40,0x38,0x82,0x16,0x01,0x76,0x0a,0x01,0x63,0x09,0x01,0x6a,0x07,0x7a,0x07,0x02,0x1a,0x1d,0x1f,0x18,0x1b,0x7e,0x01,0x00,0x03,0x22,0x05,0x01,0x01,0x25,0x0e,0x0c, 0x7e,0x0f,0x11,0x0e,0x0f,0x1f,0x22,0x91,0x01,0x1c,0x02,0x05,0x18,0x91,0x1b,0x02,0x0f,0x02,0x0f,0x02,0x20,0x12,0x08,0x91,0x15,0x04,0x00,0x3f,0xed,0x3f,0x39,0x39,0x2f,0x2f,0x10,0xc4,0xfd,0xc4,0x10,0xdd,0xc4,0xfd,0xc4,0x11,0x33,0x01,0x2f,0x33,0xed,0x32,0x12,0x39,0x2f,0xc4,0xc4,0xde,0xc4,0x10,0xfd,0xc4,0xc4,0xde,0xc4,0x31, 0x30,0x5d,0x5d,0x5d,0x5d,0x01,0x33,0x35,0x23,0x35,0x33,0x35,0x10,0x21,0x22,0x07,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x37,0x36,0x33,0x20,0x11,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x02,0x52,0xbe,0xbe,0xbe,0xff,0x00,0x8a,0x44,0x36,0x22,0x96,0x34,0x66,0x71,0xd5,0x01,0xa8,0xbf,0xbf,0xbf,0xbf,0xa8, 0xbe,0x02,0x33,0x6e,0x84,0xbb,0x01,0x48,0x6c,0x56,0x83,0x64,0x4e,0x46,0x6a,0x8e,0xc9,0x7c,0x8a,0xfe,0x34,0xc1,0x84,0x6e,0x84,0xfe,0x51,0x01,0xaf,0x00,0x00,0x01,0x00,0x65,0xff,0xe8,0x04,0xb6,0x05,0xb2,0x00,0x31,0x00,0xed,0x40,0xa0,0x6a,0x31,0x7a,0x31,0x8a,0x31,0x03,0x7a,0x30,0x01,0x68,0x30,0x01,0x08,0x2c,0x01,0x8c,0x2b, 0x01,0x6b,0x2b,0x7b,0x2b,0x02,0x56,0x24,0x01,0x56,0x23,0x01,0x37,0x23,0x01,0x57,0x20,0x01,0x88,0x19,0x01,0x49,0x19,0x01,0x8b,0x18,0x01,0x4a,0x18,0x01,0x86,0x17,0x01,0x77,0x17,0x01,0x83,0x16,0x93,0x16,0x02,0x61,0x16,0x71,0x16,0x02,0x07,0x16,0x01,0x85,0x13,0x95,0x13,0x02,0x76,0x13,0x01,0x07,0x13,0x01,0x95,0x12,0x01,0x86, 0x12,0x01,0x65,0x12,0x75,0x12,0x02,0x76,0x01,0x01,0x65,0x01,0x01,0x28,0x2a,0x7d,0x27,0x25,0x25,0x08,0x1b,0x1f,0x17,0x7d,0x04,0x00,0x00,0x08,0x01,0x08,0x08,0x33,0x1f,0x7d,0x00,0x0e,0x0c,0x7d,0x0f,0x11,0x11,0x0f,0x00,0x01,0x00,0x00,0x28,0x10,0x28,0x02,0x28,0x28,0x1b,0x21,0x0f,0x0f,0x04,0x0a,0x25,0x04,0x01,0x04,0x15,0x21, 0x91,0x3a,0x1b,0x01,0x29,0x1b,0x01,0x1b,0x2e,0x13,0x0a,0x91,0x15,0x04,0x00,0x3f,0xed,0x3f,0x39,0x5d,0x5d,0xed,0x11,0x39,0x5d,0x11,0x12,0x39,0x2f,0x11,0x12,0x39,0x2f,0x5d,0x01,0x2f,0x5d,0x33,0x2f,0x33,0xed,0x32,0x10,0xed,0x12,0x39,0x2f,0x5d,0x12,0x39,0xed,0x11,0x39,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30,0x00,0x5d,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x34,0x37,0x36,0x37,0x36,0x37,0x36,0x35,0x34,0x21,0x20,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x37,0x36,0x33,0x20,0x11,0x14,0x07,0x06,0x07,0x06,0x07,0x06,0x15,0x10,0x21,0x32,0x37,0x36,0x35,0x34, 0x27,0x33,0x16,0x15,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x65,0xa9,0x73,0xee,0xaa,0x48,0x80,0xfe,0xb8,0xfe,0xbe,0x08,0xae,0x0a,0xa1,0x84,0xcb,0x01,0xfa,0xaf,0x70,0xf5,0xa5,0x49,0x7a,0x01,0x71,0x9c,0x62,0x81,0x12,0xb4,0x0f,0xb3,0x93,0xe8,0xec,0x8c,0xab,0x01,0x85,0xcc,0x6b,0x48,0x2b,0x1e,0x26,0x42,0x85,0xe0,0xd2,0x2b,0x45, 0x4b,0x25,0xbd,0x5f,0x4e,0xfe,0x88,0xcc,0x68,0x43,0x2e,0x1f,0x28,0x44,0x85,0xfe,0xfa,0x32,0x42,0x8e,0x42,0x43,0x40,0x43,0xd9,0x6b,0x57,0x56,0x6a,0x00,0x00,0x01,0x00,0x21,0x00,0x00,0x04,0x64,0x05,0x9a,0x00,0x09,0x00,0x95,0x40,0x0d,0x7c,0x06,0x01,0x74,0x01,0x01,0x01,0x20,0x0b,0x0d,0x01,0x4c,0x06,0xb8,0xff,0xe0,0x40,0x29, 0x0b,0x0d,0x01,0x4c,0x15,0x00,0x25,0x00,0x02,0x03,0x00,0x01,0xe3,0x00,0xf3,0x00,0x02,0x1a,0x05,0x2a,0x05,0x02,0x0c,0x05,0x01,0xec,0x05,0xfc,0x05,0x02,0x05,0x01,0x91,0x04,0x12,0x00,0x07,0x91,0x08,0x03,0x06,0xb8,0xff,0xf8,0x40,0x09,0x0d,0x06,0x4d,0x01,0x08,0x0d,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x09,0x0c,0x06,0x4d,0x01, 0x0c,0x0c,0x06,0x4d,0x06,0xb8,0xff,0xf4,0x40,0x14,0x0b,0x06,0x4d,0x01,0x0c,0x0b,0x06,0x4d,0x03,0x07,0x07,0x01,0x06,0x03,0x04,0x04,0x00,0x00,0x0b,0x04,0x2f,0x12,0x39,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2b,0x2b,0x2b,0x2b,0x2b,0x2b,0x00,0x3f,0xed,0x39,0x3f,0xed,0x39,0x31,0x30,0x5d,0x71,0x71,0x5d,0x71,0x71,0x01,0x2b,0x2b,0x5d, 0x5d,0x01,0x01,0x21,0x15,0x21,0x35,0x01,0x21,0x35,0x21,0x04,0x64,0xfc,0xb8,0x03,0x34,0xfb,0xd1,0x03,0x41,0xfd,0x02,0x04,0x00,0x05,0x72,0xfb,0x26,0x98,0x2f,0x04,0xd3,0x98,0x00,0x01,0x00,0x5f,0xff,0xe8,0x03,0xf0,0x06,0x02,0x00,0x2f,0x00,0xc5,0x40,0x82,0x7a,0x2f,0x01,0x79,0x2e,0x01,0x08,0x2e,0x18,0x2e,0x02,0x86,0x27,0x01, 0x24,0x27,0x01,0x26,0x26,0x46,0x26,0x02,0x85,0x23,0x01,0x56,0x23,0x01,0x79,0x21,0x01,0x79,0x1e,0x01,0x87,0x1a,0x97,0x1a,0x02,0x96,0x19,0x01,0x85,0x19,0x01,0x07,0x19,0x01,0x95,0x15,0x01,0x06,0x15,0x86,0x15,0x02,0x86,0x14,0x01,0x79,0x12,0x01,0x3b,0x12,0x01,0x38,0x11,0x01,0x9a,0x0e,0x01,0x65,0x0b,0x01,0x57,0x0b,0x01,0x57, 0x07,0x67,0x07,0x02,0x25,0x22,0x28,0x83,0x10,0x0d,0x0d,0x13,0x31,0x1b,0x84,0x1c,0x22,0x83,0x13,0x05,0x84,0x00,0x00,0x13,0x03,0x02,0x02,0x09,0x10,0x98,0x10,0x01,0x6a,0x10,0x01,0x10,0x20,0x2c,0x1b,0x1b,0x25,0x20,0x25,0x17,0x09,0x95,0x2c,0x16,0x20,0x95,0x17,0x01,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x11,0x12,0x39,0x2f,0x11, 0x12,0x39,0x5d,0x5d,0x11,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x2f,0xed,0x10,0xed,0x2f,0xed,0x11,0x12,0x39,0x2f,0x39,0xed,0x11,0x39,0x31,0x30,0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x13,0x34,0x37,0x17,0x06,0x15,0x14,0x17,0x16,0x33,0x32, 0x37,0x36,0x35,0x34,0x27,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x16,0x15,0x23,0x34,0x27,0x26,0x23,0x20,0x15,0x14,0x17,0x16,0x17,0x16,0x15,0x14,0x07,0x06,0x23,0x22,0x27,0x26,0x5f,0x28,0x9a,0x1c,0x55,0x4e,0x68,0x88,0x55,0x5b,0xbc,0xae,0xae,0xbc,0x7c,0x77,0xba,0xab,0x73,0x7f,0xa6,0x4b,0x44,0x68,0xfe,0xfb,0xbc, 0xae,0xae,0xbc,0x8e,0x85,0xcf,0xaa,0x7d,0x88,0x01,0x5c,0x5e,0x51,0x37,0x33,0x49,0x68,0x42,0x3c,0x4c,0x50,0x95,0xaa,0x57,0x4b,0x4b,0x72,0xe5,0xae,0x63,0x60,0x57,0x61,0xa8,0x68,0x39,0x34,0xfb,0x8a,0x58,0x4e,0x4d,0x76,0xd7,0xdc,0x7b,0x73,0x61,0x6a,0x00,0x00,0x02,0x00,0x0a,0xff,0xe8,0x04,0x52,0x04,0x54,0x00,0x35,0x00,0x49, 0x00,0x8c,0x40,0x5b,0x49,0x47,0x59,0x47,0x69,0x47,0x03,0x65,0x43,0x01,0x46,0x43,0x56,0x43,0x02,0x64,0x3d,0x01,0x9c,0x09,0x01,0x7a,0x08,0x01,0x8f,0x0a,0x9f,0x0a,0x02,0x7e,0x0a,0x01,0x6f,0x0a,0x01,0x87,0x3b,0x01,0x92,0x2c,0x01,0x81,0x2c,0x01,0x63,0x2c,0x73,0x2c,0x02,0x2c,0x1b,0x3b,0x0a,0x04,0x05,0x24,0x24,0x31,0x83,0x30, 0x36,0x01,0x36,0x36,0x4b,0x40,0x83,0x05,0x12,0x12,0x05,0x13,0x18,0x95,0x12,0x0a,0x0d,0x0d,0x3b,0x2c,0x24,0x29,0x95,0x23,0x1b,0x1e,0x10,0x45,0x95,0x00,0x16,0x00,0x3f,0xed,0x3f,0x33,0x33,0xed,0x32,0x32,0x32,0x32,0x2f,0x33,0x33,0xed,0x32,0x01,0x2f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0x5d,0xed,0x32,0x2f,0x11,0x17,0x39,0x5d, 0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x31,0x30,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x23,0x22,0x06,0x07,0x06,0x07,0x35,0x36,0x37,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x17,0x16,0x17,0x15,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x13, 0x34,0x2e,0x02,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x02,0x4c,0x6c,0xad,0x7b,0x42,0x22,0x4f,0x81,0x5f,0x30,0x69,0x3b,0x33,0x55,0x1f,0x24,0x1e,0x1b,0x22,0x1d,0x51,0x33,0x89,0xda,0x57,0x34,0x72,0x40,0x30,0x4b,0x1a,0x1f,0x16,0x1a,0x21,0x1c,0x4e,0x30,0x0c,0x16,0x0b,0x39,0x50,0x32,0x17,0x42,0x7b,0xad,0xc2, 0x1d,0x3d,0x5d,0x3f,0x59,0x86,0x5a,0x2d,0x26,0x4b,0x72,0x4b,0x4b,0x72,0x4b,0x26,0x18,0x40,0x7a,0xae,0x6e,0x33,0x84,0x89,0x81,0x30,0x0d,0x0e,0x09,0x05,0x06,0x07,0x97,0x03,0x04,0x02,0x05,0x31,0x2a,0x0b,0x0b,0x03,0x02,0x03,0x02,0x92,0x05,0x04,0x03,0x06,0x01,0x01,0x35,0x77,0x77,0x72,0x30,0x6e,0xae,0x7a,0x40,0x01,0xd6,0x32, 0x70,0x6e,0x66,0x29,0x1e,0x61,0x72,0x78,0x36,0x4c,0x7b,0x56,0x2f,0x2f,0x56,0x7b,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x17,0x00,0x83,0x40,0x1f,0x19,0x40,0x0b,0x02,0x4d,0x12,0x95,0x00,0x16,0x0c,0x95,0x06,0x10,0x09,0x06,0x0d,0x06,0x4d,0x09,0x06,0x0c,0x06,0x4d,0x09,0x06,0x0b,0x06,0x4d,0x09,0x83, 0x15,0xb8,0xff,0xf0,0xb3,0x0d,0x06,0x4d,0x15,0xb8,0xff,0xf0,0x40,0x09,0x0c,0x06,0x4d,0x20,0x15,0x30,0x15,0x02,0x15,0xb8,0xff,0xde,0x40,0x2a,0x0b,0x06,0x4d,0x15,0x15,0x19,0x0f,0x08,0x0d,0x06,0x4d,0x0f,0x0a,0x0c,0x06,0x4d,0x0f,0x06,0x0b,0x06,0x4d,0x0f,0x83,0x03,0x10,0x0d,0x06,0x4d,0x03,0x0c,0x0c,0x06,0x4d,0x03,0x19,0x0b, 0x06,0x4d,0x03,0x2f,0x19,0x01,0x5d,0x2f,0x2b,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x12,0x39,0x2f,0x2b,0x5d,0x2b,0x2b,0xe9,0x2b,0x2b,0x2b,0x00,0x3f,0xed,0x3f,0xed,0x31,0x30,0x01,0x2b,0x05,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x52,0xe3,0xfe,0xf1, 0x01,0x1a,0xf0,0xe5,0x01,0x01,0xfe,0xeb,0xdd,0x9e,0xb8,0xba,0x9c,0x9f,0xab,0xab,0x18,0x01,0x1f,0xed,0x01,0x02,0x01,0x22,0xfe,0xe6,0xfa,0xf5,0xfe,0xd9,0x03,0xa6,0xd7,0xbd,0xb6,0xd2,0xce,0xbe,0xc0,0xd0,0x00,0x01,0xff,0xe6,0xfe,0x1e,0x04,0x10,0x04,0x18,0x00,0x3f,0x00,0x91,0x40,0x58,0x75,0x35,0x85,0x35,0x02,0x09,0x2d,0x01, 0x05,0x28,0x15,0x28,0x02,0x6a,0x1d,0x01,0x99,0x0a,0x01,0x99,0x05,0x01,0x00,0x02,0x83,0x3f,0x3d,0x3d,0x17,0x30,0x2f,0x33,0x2a,0x83,0x11,0x12,0x0c,0x17,0x17,0x41,0x33,0x83,0x0c,0x1f,0x84,0x20,0x20,0x0c,0x3f,0x00,0x00,0x30,0x38,0x09,0x2f,0x49,0x2f,0x59,0x2f,0x03,0x7a,0x30,0x01,0x28,0x30,0x01,0x2f,0x30,0x07,0x20,0x20,0x12, 0x1a,0x95,0x16,0x12,0x01,0x35,0x11,0x01,0x12,0x11,0x25,0x10,0x38,0x95,0x07,0x1c,0x00,0x3f,0xed,0x3f,0x39,0x39,0x5d,0x5d,0xed,0x11,0x39,0x2f,0x11,0x39,0x39,0x5d,0x5d,0x5d,0x11,0x12,0x39,0x2f,0x33,0x01,0x2f,0x33,0x2f,0xed,0x10,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0xed,0x11,0x39,0x39,0x11,0x33,0x2f,0x33,0xed,0x32,0x31,0x30, 0x00,0x5d,0x5d,0x5d,0x5d,0x5d,0x5d,0x25,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x25,0x3e,0x03,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x23,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x05,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x03,0x70,0x0d,0x53,0x8c, 0xb9,0x66,0x51,0x94,0x71,0x43,0x25,0x45,0x64,0x3f,0x01,0x7d,0x43,0x5c,0x3a,0x1a,0x6c,0x6d,0x32,0x5c,0x4e,0x3a,0x0f,0xa6,0x12,0x5b,0x80,0x9d,0x54,0x4b,0x87,0x65,0x3c,0x27,0x46,0x63,0x3d,0xfe,0x85,0x80,0x79,0x28,0x45,0x5e,0x36,0x3d,0x75,0x5b,0x37,0x09,0x41,0x2a,0x30,0x66,0xa9,0x78,0x42,0x32,0x5b,0x83,0x51,0x45,0x80,0x6d, 0x56,0x1a,0x9b,0x1b,0x3e,0x49,0x54,0x31,0x4d,0x5d,0x1b,0x36,0x50,0x34,0x56,0x84,0x59,0x2d,0x23,0x49,0x6e,0x4b,0x43,0x7a,0x68,0x54,0x1e,0x96,0x33,0x9c,0x70,0x35,0x53,0x39,0x1e,0x2c,0x4e,0x6c,0x41,0x20,0x1b,0x00,0x00,0x01,0x00,0x2d,0x00,0x00,0x04,0x55,0x04,0x00,0x00,0x09,0x00,0x41,0x40,0x22,0x06,0x01,0x00,0x01,0x84,0x05, 0x06,0x14,0x05,0x05,0x06,0x09,0x00,0x00,0x02,0x03,0x03,0x05,0x0b,0x08,0x07,0x07,0x04,0x05,0x06,0x95,0x00,0x08,0x0f,0x05,0x01,0x95,0x03,0x15,0x00,0x3f,0xed,0x33,0x3f,0x33,0xed,0x01,0x2f,0x33,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0x33,0x33,0x2f,0x33,0x87,0x10,0x2b,0x87,0x7d,0xc4,0x31,0x30,0x01,0x01,0x21,0x07,0x21,0x37,0x01, 0x21,0x37,0x21,0x04,0x4b,0xfd,0x04,0x02,0x44,0x1d,0xfc,0xb7,0x0a,0x02,0xfb,0xfd,0xef,0x1e,0x03,0x16,0x03,0xd1,0xfc,0xbb,0x8c,0x33,0x03,0x41,0x8c,0x00,0x00,0x02,0x00,0x72,0xff,0xe8,0x03,0xde,0x05,0xb2,0x00,0x0d,0x00,0x18,0x00,0x20,0x40,0x10,0x0a,0x89,0x11,0x11,0x1a,0x16,0x89,0x04,0x13,0x9a,0x07,0x07,0x0e,0x9a,0x00,0x19, 0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x26,0x02,0x35,0x10,0x12,0x33,0x32,0x12,0x11,0x14,0x02,0x06,0x27,0x32,0x12,0x11,0x10,0x21,0x22,0x02,0x11,0x10,0x12,0x02,0x22,0x80,0xc6,0x6a,0xef,0xda,0xcb,0xd8,0x6e,0xc9,0x84,0x82,0x91,0xfe,0xff,0x8b,0x90,0x8e,0x18,0xb6,0x01,0x4d,0xdd,0x01, 0x64,0x01,0x86,0xfe,0x89,0xfe,0x9e,0xe4,0xfe,0xa9,0xb6,0x8a,0x01,0x3b,0x01,0x36,0x02,0x45,0xfe,0xd9,0xfe,0xd8,0xfe,0xdd,0xfe,0xbc,0x00,0x01,0x00,0xa1,0x00,0x00,0x03,0xb2,0x05,0x9a,0x00,0x1f,0x00,0x29,0x40,0x0f,0x18,0x08,0x01,0x8a,0x0b,0x10,0x00,0x14,0x1d,0x1d,0x09,0x14,0x06,0x01,0x0e,0xb8,0x01,0x81,0xb1,0x09,0x18,0x00, 0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x12,0x39,0x01,0x2f,0xcd,0xfd,0xcd,0xc4,0x31,0x30,0x01,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x11,0x34,0x36,0x33,0x33,0x32,0x17,0x13,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x02,0x75,0xf4,0x1d,0x1f,0x1f,0x1d,0xfd,0x74,0x1f,0x1d,0x1d,0x1f,0xf4,0x29, 0x33,0x7f,0x24,0x0f,0xce,0x05,0x42,0x23,0x24,0x0f,0x04,0xe3,0xfb,0xc1,0x30,0x20,0x20,0x34,0x34,0x20,0x20,0x30,0x04,0xa5,0x2f,0x22,0x1c,0xfe,0x70,0x0c,0x0b,0x20,0x2f,0x1d,0x00,0x01,0x00,0xc2,0xff,0xe8,0x03,0x8a,0x05,0xb2,0x00,0x1b,0x00,0x27,0x40,0x13,0x00,0x8a,0x14,0x14,0x1d,0x13,0x05,0x8a,0x0b,0x04,0x9b,0x13,0x13,0x08, 0x18,0x0f,0x07,0x08,0x19,0x00,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x21,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x21,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x03,0x8a,0x1c,0x1d,0xfe,0x15,0x30,0x20,0x22,0x32,0x31,0x23,0x20, 0x30,0x01,0x80,0x31,0x23,0x20,0x30,0x03,0x54,0x22,0x32,0xfd,0x21,0x1e,0x1b,0x1c,0x1d,0x05,0x58,0x1d,0x1c,0x1b,0x1e,0xfe,0x2b,0x01,0xd5,0x1d,0x1c,0x1b,0x1e,0x00,0x00,0x01,0x01,0x1f,0x00,0x00,0x03,0x34,0x05,0xb2,0x00,0x19,0x00,0x26,0x40,0x0c,0x0f,0x07,0x01,0x8a,0x13,0x0a,0x0c,0x9b,0x11,0x11,0x17,0x09,0xb8,0x01,0x81,0xb3, 0x05,0x18,0x17,0x07,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0xed,0xcd,0x32,0x31,0x30,0x01,0x11,0x14,0x06,0x23,0x21,0x22,0x35,0x34,0x33,0x21,0x11,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x11,0x34,0x36,0x33,0x32,0x16,0x03,0x34,0x2c,0x1a,0xfe,0x77,0x46,0x46,0x01,0x2b,0xfe,0xcb,0x1f,0x1d,0x1d,0x1f,0x01,0x35, 0x30,0x20,0x22,0x32,0x05,0x79,0xfa,0xd9,0x1c,0x36,0x51,0x53,0x01,0x99,0x30,0x20,0x20,0x34,0x02,0x98,0x1e,0x1b,0x1c,0x00,0x00,0x01,0x00,0xf7,0x00,0x00,0x03,0x55,0x05,0xb2,0x00,0x1a,0x00,0x2b,0x40,0x0f,0x09,0x01,0x8a,0x14,0x14,0x1c,0x05,0x8a,0x0f,0x04,0x9b,0x13,0x13,0x18,0x05,0xb8,0x01,0x81,0xb3,0x0c,0x18,0x18,0x07,0x00, 0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xfd,0xc4,0x31,0x30,0x01,0x11,0x14,0x23,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x23,0x21,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x21,0x11,0x34,0x36,0x33,0x32,0x16,0x03,0x55,0x32,0xfe,0x78,0x01,0x74,0x1e,0x28,0x46,0xfe,0x2e,0x1e,0x28,0x1d,0x1f,0x01,0x7e,0x31,0x23, 0x20,0x30,0x05,0x79,0xfd,0x7a,0x54,0xfe,0x05,0x2a,0x23,0x57,0x39,0x30,0x02,0x86,0x20,0x34,0x02,0x36,0x1d,0x1c,0x1b,0x00,0x00,0x01,0x01,0x08,0xff,0xe8,0x03,0x47,0x05,0xb2,0x00,0x16,0x00,0x1e,0x40,0x0e,0x06,0x01,0x0a,0x8a,0x10,0x09,0x9b,0x01,0x01,0x0d,0x14,0x07,0x0d,0x19,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0xfd, 0x32,0xc6,0x31,0x30,0x01,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x01,0xac,0x01,0x55,0x1e,0x28,0x28,0x1e,0xfe,0xab,0x30,0x20,0x22,0x32,0x31,0x23,0x20,0x30,0x05,0x79,0xfd,0xb3,0x2a,0x28,0x2b,0x27,0xfd,0x99,0x1e,0x1b,0x1c,0x1d,0x05,0x58,0x1d,0x1c,0x1b, 0x00,0x01,0x00,0xe1,0xff,0xe9,0x03,0x73,0x05,0xb2,0x00,0x17,0x00,0x23,0x40,0x11,0x01,0x8a,0x07,0x07,0x19,0x14,0x8a,0x0b,0x09,0x9b,0x14,0x14,0x10,0x04,0x19,0x10,0x07,0x00,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x22,0x26,0x35,0x11,0x34, 0x36,0x33,0x32,0x16,0x15,0x11,0x21,0x32,0x16,0x03,0x73,0x31,0x23,0x20,0x30,0xfe,0x66,0x22,0x32,0x30,0x20,0x22,0x32,0x01,0xb2,0x1d,0x1f,0x02,0xef,0xfd,0x33,0x1c,0x1d,0x1b,0x1e,0x02,0x7d,0x1c,0x1d,0x02,0xa1,0x1e,0x1b,0x1c,0x1d,0xfd,0xca,0x34,0x00,0x01,0x00,0xa1,0x00,0x00,0x03,0xaf,0x05,0xb2,0x00,0x16,0x00,0x21,0x40,0x0f, 0x0d,0x11,0x11,0x18,0x0c,0x8a,0x04,0x0c,0x0f,0x0f,0x01,0x08,0x07,0x01,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x33,0x31,0x30,0x21,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x01,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x01,0x06,0x01,0x68,0x73,0x25,0x2f,0x31,0x23,0x20,0x30,0x01, 0xd6,0x0d,0x20,0x24,0x43,0x06,0xfd,0xec,0x0e,0x1b,0x1b,0x05,0x43,0x1d,0x1c,0x1b,0x1e,0xfb,0x59,0x03,0x42,0x19,0x35,0x1f,0x0b,0x0c,0xfc,0x57,0x19,0x00,0x00,0x02,0x00,0xa9,0x00,0x00,0x03,0xa7,0x05,0xb2,0x00,0x14,0x00,0x17,0x00,0x26,0x40,0x12,0x15,0x03,0x03,0x19,0x00,0x17,0x8a,0x0d,0x16,0x9b,0x17,0x00,0x00,0x0a,0x11,0x07, 0x0a,0x18,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x01,0x21,0x32,0x15,0x14,0x06,0x07,0x01,0x06,0x23,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x01,0x21,0x11,0x01,0x4d,0x02,0x1d,0x3d,0x16,0x16,0xfe,0x22,0x0e,0x1f,0x73,0x25,0x2f,0x31,0x23,0x20,0x30,0x01,0x83, 0xfe,0x7d,0x04,0x2a,0x3a,0x26,0x3a,0x27,0xfc,0xb0,0x19,0x1b,0x1b,0x05,0x43,0x1d,0x1c,0x1b,0x1e,0xfe,0x0d,0xfd,0x4d,0x00,0x00,0x02,0x00,0xbc,0xff,0xe8,0x03,0x94,0x05,0xb2,0x00,0x13,0x00,0x1f,0x00,0x33,0x40,0x1a,0x04,0x8a,0x09,0x00,0x8b,0x14,0x09,0x14,0x09,0x14,0x21,0x1a,0x8b,0x0e,0x1d,0x9b,0x03,0x0b,0x0b,0x11,0x07,0x19, 0x17,0x9b,0x11,0x07,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0x94,0x9a,0x80,0x32, 0x20,0x20,0x32,0x82,0x98,0xca,0xa6,0xa6,0xc2,0x9a,0x6b,0x61,0x65,0x73,0x71,0x67,0x5c,0x70,0x04,0x6f,0x78,0xab,0x17,0xfc,0xec,0x1e,0x1b,0x1b,0x1e,0x03,0x15,0x19,0xaa,0x76,0x94,0xaf,0xad,0x8d,0x4f,0x57,0x57,0x4f,0x56,0x60,0x64,0x00,0x00,0x02,0x00,0x76,0x00,0xf7,0x03,0xb0,0x04,0x66,0x00,0x0b,0x00,0x1b,0x00,0x1f,0x40,0x0f, 0x10,0x8a,0x09,0x09,0x1d,0x03,0x8a,0x18,0x06,0x99,0x14,0x00,0x99,0x0c,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x02,0x14,0x6e,0x8f,0x93,0x6a,0x6a, 0x91,0x8d,0x6e,0x71,0xbe,0x6d,0x6f,0xbf,0x6e,0x6e,0xbf,0x71,0x6e,0xbe,0x03,0xcc,0xa2,0x7a,0x77,0xa8,0xa7,0x78,0x78,0xa4,0x9a,0x73,0xcc,0x78,0x76,0xcd,0x75,0x76,0xcc,0x76,0x76,0xcd,0x74,0x00,0x00,0x01,0x00,0x8a,0xfe,0xe6,0x03,0x37,0x05,0x9c,0x00,0x29,0x00,0x49,0x40,0x26,0x0a,0x8a,0x20,0x11,0x8a,0x17,0x0e,0x29,0x14,0x1c, 0x29,0x14,0x20,0x17,0x17,0x20,0x14,0x29,0x1c,0x05,0x2b,0x26,0x8a,0x02,0x0e,0x1c,0x29,0x1c,0x13,0x00,0x00,0x06,0x14,0x13,0x23,0x99,0x06,0x06,0x00,0x3f,0xed,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x26,0x35, 0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x07,0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x01,0x6f,0xe5,0x50,0x94,0x55,0x5b,0x98,0x57,0x48,0x86,0x9c,0xf0,0xa4,0x56,0x87,0x1c,0x1c,0x2a,0x6e,0xb5,0x75,0x9d,0xad,0x4f,0x55,0x49, 0x45,0x59,0x50,0x47,0x02,0xf7,0x8f,0xd7,0x5b,0x92,0x52,0x58,0xa4,0x68,0x5f,0xb8,0xc0,0xa7,0xd2,0xd2,0x5e,0x6a,0x68,0x52,0x27,0x3b,0x23,0x2c,0x4b,0x75,0xa9,0x67,0x9d,0xd7,0xab,0x5b,0x63,0x6c,0x60,0x49,0x42,0x7d,0x2c,0x00,0x00,0x01,0x00,0x6d,0xfe,0xdb,0x03,0xbe,0x05,0x9c,0x00,0x21,0x00,0x3c,0x40,0x1d,0x00,0x21,0x1d,0x1a, 0x8a,0x0e,0x02,0x0e,0x06,0x06,0x13,0x14,0x0b,0x0e,0x09,0x09,0x11,0x0b,0x9a,0x02,0x1d,0x1d,0x00,0x11,0x9b,0x16,0x06,0x21,0x00,0x00,0x2f,0x32,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x11,0x39,0x2f,0x01,0x2f,0x33,0xc4,0x32,0x39,0x2f,0x12,0x39,0x10,0xed,0x32,0x2f,0x33,0x31,0x30,0x01,0x02,0x03,0x2e,0x02,0x35,0x34,0x36,0x33,0x32, 0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x07,0x07,0x16,0x12,0x17,0x03,0x39,0xee,0x9a,0x46,0x74,0x42,0x4a,0x3c,0x7c,0x50,0x85,0x8d,0xc3,0x9a,0x88,0x96,0x31,0xb1,0xa4,0x8f,0xea,0x83,0xca,0xb0,0x01,0x72,0x9e,0x66,0xfe,0xdb,0x01,0x56,0x01,0x6c,0x02,0x47,0x72,0x3b,0x3b,0x4a, 0xd2,0x2a,0xb4,0x7d,0x9c,0xc8,0x49,0x94,0x4c,0x85,0xe9,0x86,0xa9,0xfe,0xfa,0x3e,0x03,0xed,0xfe,0xf6,0x89,0x00,0x00,0x01,0x00,0x76,0xfe,0xde,0x03,0xa2,0x05,0x88,0x00,0x2f,0x00,0x60,0x40,0x19,0x00,0x2f,0x2b,0x28,0x8a,0x0f,0x0c,0x24,0x0f,0x2f,0x0f,0x2f,0x0f,0x31,0x03,0x18,0x14,0x06,0x14,0x06,0x1c,0x22,0x8a,0x18,0x0c,0xb8, 0x01,0x7e,0x40,0x15,0x2b,0x03,0x2b,0x24,0x13,0x9b,0x14,0x2b,0x09,0x14,0x14,0x09,0x2b,0x03,0x00,0x1c,0x9b,0x1d,0x06,0x2f,0x00,0x00,0x2f,0x32,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x39,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0xc6,0x39,0x39,0x2f,0x2f,0x12,0x39,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x32,0x10,0xed,0x32, 0x11,0x33,0x31,0x30,0x01,0x26,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x32,0x16,0x16,0x15,0x14,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x17,0x02,0xf6,0x5a,0x71,0x4b,0x81,0x9d,0x4c,0x39,0x3a,0x83,0x3a, 0x5f,0x61,0x95,0x88,0xfe,0xc3,0x7a,0x8c,0x86,0x82,0xfe,0xd2,0x01,0x29,0x89,0xc3,0x65,0x84,0x62,0x74,0x98,0x7c,0x27,0x93,0x33,0xfe,0xde,0x8b,0x93,0x51,0x05,0x6b,0x51,0x38,0x48,0x57,0x52,0x19,0x85,0x5f,0x7b,0x83,0x97,0x66,0x5c,0x5a,0x5f,0x96,0x53,0x98,0x64,0x9d,0x61,0x06,0x2b,0xc0,0x70,0x84,0xcc,0x24,0x04,0x29,0xb9,0x4c, 0x00,0x02,0x00,0x6c,0xff,0xf3,0x04,0x48,0x05,0x88,0x00,0x25,0x00,0x31,0x00,0x50,0xb6,0x26,0x8b,0x10,0x09,0x8b,0x2c,0x02,0xb8,0x01,0x85,0x40,0x22,0x24,0x2f,0x20,0x13,0x03,0x10,0x06,0x2c,0x24,0x10,0x2c,0x24,0x24,0x2c,0x10,0x03,0x33,0x1c,0x8a,0x17,0x06,0x13,0x20,0x13,0x2f,0x03,0x0d,0x25,0x19,0x06,0x29,0x99,0x0d,0x19,0x00, 0x3f,0xed,0x3f,0x33,0x12,0x17,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x17,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x16,0x17, 0x3e,0x02,0x35,0x27,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x04,0x41,0x07,0x4d,0x8b,0xa5,0x7e,0x69,0x56,0x98,0x59,0x9c,0xc4,0x65,0x80,0xae,0x89,0x4d,0x0a,0xa6,0x0e,0x41,0x77,0x96,0x92,0x77,0x42,0x04,0xfd,0xfe,0x64,0x57,0x52,0x6e,0x55,0x67,0x68,0x57,0x05,0x88,0x25,0x2e,0x66,0xba,0xb3,0x99,0x74,0xc1, 0x63,0x5d,0x91,0x50,0xb3,0x8f,0x5f,0xb9,0x79,0x94,0xa5,0xae,0x61,0x41,0x39,0x3e,0x32,0x51,0x92,0x8e,0x80,0x84,0x9a,0xa4,0x5b,0x44,0xfb,0xa6,0x4b,0x5a,0x63,0x4c,0x42,0x8f,0x5c,0x63,0x92,0x00,0x00,0x01,0x00,0x97,0xfe,0xdb,0x05,0x22,0x05,0x88,0x00,0x25,0x00,0x49,0x40,0x24,0x25,0x00,0x1a,0x09,0x13,0x0b,0x11,0x00,0x0b,0x11, 0x11,0x0b,0x00,0x03,0x22,0x17,0x16,0x27,0x03,0x8a,0x22,0x13,0x1a,0x1a,0x1e,0x9b,0x09,0x06,0x0e,0x06,0x0e,0x17,0x25,0x06,0x16,0x17,0x00,0x2f,0x33,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x33,0xed,0x32,0x11,0x33,0x01,0x2f,0xed,0x10,0xc6,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x39,0x32,0x11,0x33,0x31,0x30,0x01,0x06,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x12,0x12,0x17,0x07,0x26,0x02,0x27,0x35,0x06,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x37,0x01,0x8d,0x2e,0x24,0x8f,0x7f,0x35,0x66,0x24,0x42,0x48,0x3e,0x48,0x5f,0x3a,0x54,0xb1,0x64,0x80,0x62,0xc9,0x25,0x37,0x8c,0x3f,0x82,0xc8,0x6f,0x2b, 0x23,0x05,0x88,0xb2,0xe2,0x63,0xc9,0xd5,0x30,0x2c,0x60,0x6b,0x4b,0x5f,0x7b,0x5c,0x5f,0x5b,0xfe,0xf9,0xfe,0x91,0x85,0x5d,0x86,0x01,0xcd,0x90,0x01,0x2f,0x35,0x91,0x01,0x04,0x9c,0x6f,0x01,0x11,0x7c,0x00,0x00,0x01,0x00,0x90,0xfe,0xde,0x04,0xce,0x05,0x88,0x00,0x36,0x00,0x63,0x40,0x33,0x04,0x8a,0x19,0x16,0x15,0x22,0x1f,0x13, 0x0b,0x11,0x1f,0x0b,0x11,0x15,0x15,0x11,0x0b,0x1f,0x04,0x26,0x38,0x2d,0x2d,0x36,0x32,0x8a,0x26,0x0e,0x01,0x13,0x19,0x19,0x09,0x07,0x99,0x1b,0x22,0x01,0x9b,0x35,0x1b,0x35,0x1b,0x35,0x16,0x2e,0x9b,0x2b,0x06,0x15,0x16,0x00,0x2f,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x32,0x33,0x11,0x33,0x11,0x39, 0x01,0x2f,0xfd,0xc6,0x39,0x2f,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x11,0x33,0x32,0xed,0x31,0x30,0x01,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x07,0x26,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35, 0x34,0x3e,0x02,0x33,0x33,0x15,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x21,0x03,0x61,0xed,0x73,0x7c,0x9d,0x7c,0x45,0x37,0x2a,0x3c,0x39,0x52,0x73,0x45,0x57,0x92,0x7d,0x3f,0x7c,0x2f,0x60,0x5a,0x80,0xd5,0x77,0x3c,0x4b,0x63,0x75,0x3b,0x64,0xa9,0x85,0xe0,0xca,0x7e,0x7e,0x43,0x96,0x7d,0x01,0x1a,0x02,0xe0,0x75,0x6d,0x7e,0xa2, 0x13,0x56,0x4a,0x3f,0x49,0x8f,0x5a,0x57,0x35,0xad,0xbd,0x5c,0x44,0xd4,0x6d,0x1c,0x75,0xce,0x7d,0x51,0x87,0x3c,0x06,0x26,0xa8,0x6f,0x4d,0x6c,0x47,0x2a,0x96,0x22,0x4a,0x3f,0x5e,0x72,0x00,0x01,0x00,0x76,0xff,0xf8,0x04,0xca,0x05,0x88,0x00,0x29,0x00,0x4d,0xbc,0x00,0x24,0x01,0x85,0x00,0x06,0x00,0x0d,0x01,0x85,0x40,0x0a,0x1d, 0x06,0x29,0x1d,0x1d,0x29,0x06,0x03,0x2b,0x16,0xb8,0x01,0x85,0x40,0x0f,0x15,0x00,0x9b,0x29,0x21,0x9b,0x09,0x29,0x09,0x29,0x09,0x11,0x15,0x06,0x1a,0xb8,0x01,0x80,0xb1,0x11,0x18,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01, 0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x06,0x23,0x22,0x00,0x02,0x11,0x33,0x10,0x12,0x12,0x33,0x32,0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x37,0x03,0xd4,0x16,0x1d,0x78,0xaf,0x5e,0xa8,0x84,0x72,0xb0,0x60,0x7d,0xe2,0x8f,0xcd,0xfe,0xea,0x83,0x9f,0x69,0xcd,0x93, 0x95,0xb9,0x3e,0x6b,0x3e,0x3f,0x4c,0x43,0x75,0x46,0x1a,0x01,0xd4,0x05,0x62,0xae,0x67,0x89,0xb1,0x8b,0xfc,0x9c,0xb6,0xfe,0xe8,0x97,0x01,0x43,0x02,0x95,0x01,0xb8,0xfe,0x5a,0xfd,0xc3,0xfe,0xeb,0x01,0x05,0xce,0x6f,0xb1,0x64,0x59,0x4c,0x48,0x66,0x36,0x02,0x00,0x01,0x00,0x80,0xff,0xa1,0x04,0x3e,0x05,0x96,0x00,0x16,0x00,0x2f, 0x40,0x16,0x16,0x00,0x0a,0x0b,0x00,0x0b,0x00,0x0b,0x18,0x04,0x8b,0x12,0x0b,0x0a,0x0a,0x0e,0x00,0x16,0x06,0x07,0x99,0x0e,0x00,0x2f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x00,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x04,0x23,0x22,0x26, 0x26,0x35,0x34,0x12,0x00,0x13,0x03,0x97,0xfd,0xef,0x52,0x19,0x95,0x73,0x6c,0xb9,0x6d,0x89,0x81,0xfe,0xfd,0x95,0x75,0xc1,0x6f,0x82,0x01,0x23,0xe9,0x05,0x39,0xfd,0x2c,0xc9,0x3c,0x3b,0x6c,0x83,0x89,0xb4,0x57,0xc7,0xb4,0x64,0xb4,0x72,0x72,0x01,0x05,0x01,0xb2,0x01,0x42,0x00,0x00,0x01,0x00,0x76,0xfe,0xe6,0x04,0x23,0x05,0x9c, 0x00,0x27,0x00,0x42,0x40,0x21,0x27,0x00,0x24,0x8a,0x02,0x12,0x13,0x10,0x89,0x16,0x00,0x1d,0x13,0x16,0x02,0x16,0x02,0x16,0x29,0x08,0x8a,0x1d,0x00,0x9a,0x27,0x27,0x12,0x05,0x9b,0x20,0x06,0x13,0x12,0x00,0x2f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x12,0x39,0x10,0xed,0x11,0x33, 0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x17,0x1e,0x02,0x15,0x14,0x07,0x27,0x36,0x35,0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x01,0xf1,0xc5,0x6f,0x59,0x60,0x77,0x38,0x86,0xcc,0xd0,0x7a,0x38,0x56,0x87,0x36,0x29,0x54,0xb4,0xec, 0xa0,0x49,0xcf,0xa2,0x6b,0xaa,0x5f,0x99,0x90,0x03,0x32,0x54,0xa6,0x60,0x76,0x84,0x63,0x40,0x7e,0xa8,0xd8,0xdd,0x99,0x74,0x37,0x6b,0x6b,0x52,0x4e,0x34,0x22,0x4f,0x69,0xbf,0xfa,0xd2,0xb0,0x5a,0xa5,0xce,0x61,0xad,0x67,0x82,0xc5,0x36,0x00,0x02,0x00,0x96,0x00,0x93,0x04,0x9f,0x04,0xc9,0x00,0x0e,0x00,0x1e,0x00,0x1f,0x40,0x0f, 0x1b,0x8a,0x00,0x00,0x20,0x08,0x8a,0x13,0x0b,0x9b,0x0f,0x04,0x9b,0x17,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x36,0x01,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x06,0x03,0xff,0x55,0x9d, 0x66,0x6c,0xa8,0x5e,0xba,0x96,0x67,0xaf,0x64,0xfe,0x79,0x8c,0xdd,0x79,0x8c,0xfa,0x96,0x8e,0xe2,0x7d,0x93,0xff,0x02,0xc0,0x64,0xa4,0x5d,0x66,0xb7,0x6c,0x9b,0xcb,0x68,0xb6,0xfe,0x3f,0x8a,0xf4,0x8e,0x98,0xff,0x93,0x87,0xed,0x90,0x99,0xfe,0xfb,0x94,0x00,0x00,0x01,0x00,0x64,0xff,0xe7,0x03,0x88,0x05,0xb1,0x00,0x25,0x00,0x35, 0x40,0x1a,0x06,0x8a,0x14,0x25,0x0d,0x12,0x22,0x14,0x0d,0x22,0x14,0x14,0x22,0x0d,0x03,0x27,0x1c,0x25,0x1f,0x10,0x10,0x0a,0x1f,0x07,0x0a,0x19,0x00,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x10,0xed,0x31,0x30,0x01,0x16,0x16,0x17,0x16,0x16,0x15,0x14,0x02,0x06,0x23, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x35,0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x01,0x32,0x12,0x5d,0x74,0xc3,0xb0,0x76,0xb2,0x6a,0x5f,0x73,0xa2,0x73,0x35,0x40,0x3b,0x3f,0x75,0x8e,0x9d,0x6a,0x3c,0x59,0x3d,0x37,0x47,0x22,0x23,0x04,0xd3,0x20,0x56,0x59,0x98,0xfe,0x81,0x7a, 0xfe,0xfa,0x86,0x5a,0x4b,0x57,0x74,0x10,0x4d,0x54,0x3d,0x77,0x7c,0x74,0x7f,0x6e,0x6a,0x35,0x44,0x55,0x3f,0x36,0x25,0x2d,0x11,0x00,0x00,0x01,0x00,0x78,0xff,0xa7,0x05,0x09,0x05,0xb1,0x00,0x2d,0x00,0x43,0x40,0x13,0x03,0x00,0x89,0x0c,0x15,0x27,0x23,0x1d,0x07,0x15,0x23,0x23,0x15,0x07,0x03,0x2f,0x1d,0x03,0x0d,0xb8,0x01,0x81, 0x40,0x0b,0x19,0x27,0x27,0x20,0x0c,0x0c,0x08,0x20,0x07,0x07,0x08,0x00,0x2f,0x33,0x3f,0x12,0x39,0x2f,0x12,0x39,0x11,0x33,0xed,0x39,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xc4,0xed,0x32,0x31,0x30,0x01,0x14,0x06,0x07,0x15,0x16,0x04,0x17,0x07,0x26,0x24,0x24,0x27,0x37,0x16,0x17,0x16,0x33,0x32,0x36,0x36, 0x35,0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x1e,0x05,0x04,0x47,0xcc,0xcf,0xc8,0x01,0x3c,0x59,0x68,0x4d,0xfe,0x8e,0xfe,0x5e,0xc8,0x10,0x31,0x85,0x3c,0x36,0x7e,0xf5,0x7c,0x41,0x75,0xa9,0x97,0x82,0x46,0x56,0x42,0x36,0x46,0x22,0x23,0x01,0x34,0x8a,0x94,0x8f,0x71,0x46,0x03,0x4b, 0x7e,0xc8,0x3f,0x06,0x4b,0xe2,0x83,0x69,0x71,0xfa,0x9c,0x12,0xa5,0x03,0x19,0x06,0x4b,0x74,0x49,0x36,0x48,0x31,0x24,0x20,0x3c,0x57,0x41,0x44,0x5b,0x42,0x2f,0x1d,0x38,0x12,0x06,0x07,0x14,0x24,0x37,0x52,0x72,0x00,0x00,0x01,0x00,0x82,0x00,0x93,0x05,0x8b,0x05,0x36,0x00,0x23,0x00,0x38,0x40,0x14,0x1a,0x8a,0x07,0x0a,0x0d,0x13, 0x0d,0x07,0x07,0x0d,0x13,0x03,0x25,0x00,0x22,0x0a,0x10,0x10,0x16,0x03,0xb8,0x01,0x80,0xb4,0x1e,0x22,0x00,0x16,0x06,0x00,0x3f,0xc6,0x32,0xd4,0xed,0x12,0x39,0x2f,0x39,0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x31,0x30,0x13,0x12,0x00,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x27,0x07,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x22,0x24,0x02,0x03,0x37,0xfb,0x96,0x01,0x40,0xce,0x64,0x97,0x53,0x98,0x83,0x09,0x30,0x8d,0x5b,0x61,0x83,0xc7,0xa8,0x95,0xe1,0x79,0x7a,0xdf,0x8e,0xb4,0xfe,0xce,0xf2,0x4a,0x73,0x05,0x36,0xfd,0xd2,0xfe,0x25,0x6c,0xc0,0x70,0x9e,0xe3,0x18,0x0e,0x3c, 0x4a,0x5b,0x83,0x93,0x6a,0x80,0x9c,0x91,0xfe,0xfe,0x9f,0xa0,0xfe,0xf5,0x99,0xf7,0x01,0xf5,0x01,0x5e,0x59,0x00,0x00,0x03,0x00,0x8c,0x00,0x4c,0x04,0x91,0x05,0xb1,0x00,0x1d,0x00,0x2b,0x00,0x38,0x00,0x46,0x40,0x26,0x2c,0x8a,0x12,0x1a,0x8a,0x33,0x03,0x8b,0x1e,0x0e,0x12,0x33,0x1d,0x1e,0x12,0x33,0x1e,0x1e,0x33,0x12,0x03,0x3a, 0x26,0x8a,0x0b,0x22,0x1d,0x0e,0x30,0x04,0x16,0x29,0x99,0x07,0x36,0x9b,0x16,0x07,0x00,0x3f,0xed,0x2f,0xed,0x12,0x17,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26, 0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x13,0x34,0x26,0x26,0x27,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x14,0x16,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0x7e,0x95,0x7e,0x8a,0xee,0x8f,0x8e,0xed,0x83,0x8f,0xa7,0x87,0x7a,0x7f,0xe0,0x80,0x82,0xd2,0x77,0x6e,0x7f,0x77,0x46,0x80,0x9b, 0x9d,0x84,0x47,0xd8,0xa0,0x94,0xbd,0xfd,0x6c,0x3f,0x76,0x9f,0x9c,0x7a,0xb7,0x89,0x84,0xa6,0x03,0x32,0x3f,0xa8,0x77,0x75,0xb3,0x60,0x62,0xb1,0x75,0x7e,0xaa,0x37,0x06,0x34,0x91,0x65,0x62,0x98,0x54,0x51,0x94,0x64,0x6b,0x92,0x33,0xfe,0x98,0x44,0x63,0x4a,0x31,0x28,0x44,0x61,0x47,0x71,0x91,0x85,0x03,0x0b,0x37,0x50,0x3d,0x2f, 0x2c,0x71,0x54,0x4c,0x62,0x5e,0x00,0x02,0x00,0x96,0x00,0x01,0x05,0x82,0x05,0xb1,0x00,0x1f,0x00,0x32,0x00,0x5a,0x40,0x18,0x02,0x8a,0x30,0x2b,0x25,0x0f,0x89,0x28,0x09,0x14,0x00,0x30,0x28,0x28,0x30,0x00,0x14,0x09,0x05,0x34,0x20,0x8a,0x1a,0x13,0xb8,0x01,0x7e,0x40,0x10,0x09,0x2b,0x05,0x12,0x30,0x08,0x1e,0x12,0x08,0x12,0x08, 0x16,0x00,0x1e,0x07,0x25,0xb8,0x01,0x80,0xb1,0x16,0x18,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x39,0x32,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x33,0x33,0x10,0xed,0x31,0x30,0x01,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x15,0x07,0x0e,0x02,0x15,0x14, 0x16,0x33,0x17,0x15,0x06,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x00,0x37,0x17,0x01,0x14,0x16,0x16,0x33,0x37,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x35,0x37,0x06,0x02,0x03,0xbf,0x2f,0x84,0x5f,0x18,0x2e,0x34,0x95,0x70,0xcb,0x8f,0x48,0x7a,0x50,0x79,0xd2,0xd1,0xb0,0xfe,0xdb,0xa5,0xa5,0x01,0x2d,0xc2,0x95,0xfd,0x75,0x78, 0xde,0x95,0x43,0x42,0x5a,0x83,0x97,0x70,0x82,0x02,0xd9,0xe3,0x05,0x5e,0x5c,0x47,0x5d,0x86,0x0d,0x1f,0x4b,0x06,0x49,0x7d,0x78,0x77,0x40,0x4c,0x80,0x80,0x06,0x6b,0x95,0x01,0x01,0x95,0x91,0x01,0x4c,0x01,0x35,0x73,0x4d,0xfc,0xcc,0x76,0xb8,0x63,0x03,0x36,0xa2,0x4d,0x62,0xc2,0x6e,0x2a,0xaa,0x71,0x15,0x15,0xac,0xfe,0xac,0x00, 0x00,0x01,0x00,0x64,0xff,0xe5,0x06,0x29,0x05,0xb1,0x00,0x2d,0x00,0x5a,0xb9,0x00,0x0a,0x01,0x85,0x40,0x12,0x19,0x06,0x1b,0x01,0x8a,0x21,0x1b,0x21,0x19,0x21,0x28,0x28,0x21,0x19,0x03,0x2f,0x11,0x02,0xb8,0x01,0x80,0x40,0x12,0x11,0x12,0x1b,0x1e,0x22,0x06,0x12,0x1e,0x06,0x12,0x12,0x06,0x1e,0x03,0x0e,0x2b,0x07,0x15,0xb8,0x01, 0x80,0xb1,0x0e,0x19,0x00,0x3f,0xed,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x11,0x33,0xed,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x01,0x11,0x14,0x33,0x32,0x36,0x37,0x33,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x20,0x00,0x03,0x37,0x33,0x12,0x21,0x32,0x36, 0x36,0x35,0x34,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x03,0x92,0x23,0x68,0xbd,0x68,0x0e,0x66,0x73,0x87,0xff,0xae,0xfe,0xae,0xfe,0x39,0x78,0x77,0x06,0xfa,0x02,0x1c,0x7a,0xb6,0x62,0x34,0x47,0xc2,0x66,0x74,0x85,0x06,0x1a,0x1d,0x2a,0x46,0x58,0x41,0x56,0x63,0x04,0x89, 0xfe,0xd2,0x73,0x93,0xa4,0x59,0xfe,0xf7,0x98,0xa6,0xfe,0xf9,0x93,0x02,0x35,0x02,0x51,0x64,0xfb,0xb5,0x6f,0xc6,0x7b,0x7a,0x6a,0x60,0x6e,0x8f,0x78,0x01,0x72,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x00,0x02,0x00,0x87,0xff,0xe8,0x04,0xa0,0x05,0xb1,0x00,0x21,0x00,0x30,0x00,0x43,0x40,0x0a,0x24,0x14,0x8a,0x21,0x1b,0x21,0x1b,0x21, 0x32,0x2e,0xb8,0x01,0x82,0xb4,0x05,0x05,0x2e,0x24,0x22,0xb8,0x01,0x80,0x40,0x0d,0x00,0x0d,0x15,0x1e,0x02,0x02,0x0d,0x1e,0x19,0x2a,0x9b,0x0d,0x07,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0xed,0x32,0x32,0x39,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x31,0x30,0x01,0x06,0x23,0x22,0x24,0x27,0x26, 0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x03,0x15,0x11,0x17,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x01,0x32,0x37,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x06,0x15,0x17,0x16,0x03,0x4e,0x63,0x96,0x5c,0xfe,0xe1,0x1b,0x19,0x1f,0x62,0x9a,0xc7,0x73,0x1f,0x58,0x59,0x3e,0x27,0x01,0x06,0x1a,0x1d,0x2a,0x46,0x58, 0x41,0x57,0x62,0xfe,0xfb,0xa2,0x63,0x29,0x37,0x3a,0x11,0x61,0xae,0x65,0x07,0x8c,0x02,0x74,0x1d,0x2a,0x13,0x1c,0x5b,0x2a,0x65,0xfc,0xb7,0x64,0x35,0x62,0x84,0xb2,0x74,0xfd,0xb2,0x4c,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x8a,0x01,0xe2,0x27,0x57,0x75,0xa0,0x63,0x2c,0x87,0xe9,0x83,0x0a,0x25,0x00,0x00,0x02,0x00,0x78,0xff,0xe8, 0x06,0x08,0x05,0xb1,0x00,0x31,0x00,0x41,0x00,0x6e,0xb3,0x1f,0x8a,0x18,0x26,0xb8,0x01,0x86,0x40,0x2d,0x3e,0x12,0x24,0x1a,0x3e,0x18,0x1a,0x3e,0x3e,0x1a,0x18,0x03,0x43,0x0e,0x35,0x8a,0x07,0x31,0x1a,0x1c,0x3e,0x34,0x32,0x9b,0x10,0x23,0x9b,0x15,0x12,0x0e,0x02,0x0a,0x1c,0x0e,0x15,0x2b,0x1c,0x10,0x15,0x15,0x10,0x1c,0x03,0x0a, 0x3a,0xb8,0x01,0x80,0xb3,0x2b,0x19,0x0a,0x07,0x00,0x3f,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x32,0x32,0x11,0x33,0x01,0x2f,0xc4,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x27,0x27,0x06,0x23,0x22,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x36,0x35,0x34,0x27,0x35,0x37,0x33,0x16,0x15,0x14,0x06,0x23,0x22,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x03,0x35,0x25,0x22,0x07,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x36,0x35,0x27,0x26,0x26,0x01,0x26,0x01,0x06,0x1a,0x1d,0x2a,0x46,0x58,0x41, 0x56,0x63,0x78,0xa1,0x90,0x80,0x26,0x52,0x54,0x58,0x4c,0x0b,0x82,0x06,0x28,0xad,0x90,0x30,0x1b,0x0e,0x62,0x99,0xc7,0x71,0x1f,0x58,0x59,0x3e,0x27,0x01,0xca,0x9b,0x8b,0x29,0x37,0x3a,0x11,0x61,0xab,0x65,0x07,0x3b,0x6f,0x04,0x71,0x52,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x8a,0xfe,0xa4,0x36,0x3c,0x18,0x12,0x3a,0x3b,0x1d,0x1f, 0x06,0x62,0x4f,0x52,0x81,0x9b,0x06,0x19,0x2a,0x64,0xff,0xb6,0x63,0x35,0x62,0x84,0xb2,0x74,0x97,0x40,0x57,0x75,0xa0,0x63,0x2c,0x85,0xeb,0x83,0x0a,0x20,0x1e,0x00,0x00,0x01,0x00,0x96,0xff,0xe7,0x05,0x3b,0x05,0xb1,0x00,0x3c,0x00,0x67,0xb9,0x00,0x1a,0x01,0x83,0xb6,0x39,0x0d,0x39,0x0d,0x39,0x07,0x35,0xb8,0x01,0x85,0x40,0x24, 0x1d,0x2d,0x2a,0x24,0x2a,0x1d,0x1d,0x2a,0x24,0x03,0x3e,0x07,0x89,0x14,0x00,0x9b,0x18,0x31,0x21,0x07,0x10,0x0a,0x21,0x2d,0x18,0x27,0x0a,0x18,0x0a,0x18,0x10,0x27,0x07,0x10,0x19,0x1a,0xb8,0x01,0x81,0xb1,0x39,0x19,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x01, 0x2f,0xec,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x01,0x22,0x06,0x06,0x15,0x14,0x17,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x20,0x13,0x36,0x36,0x35,0x34,0x26,0x26,0x27,0x24,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x07,0x07,0x14,0x16,0x17,0x04,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x2e,0x02,0x02,0x26,0x41,0x6f,0x42,0x0c,0x0b,0x0f,0x4e,0x2d,0x41,0x5d,0x5f,0x4b,0x4d,0x90,0x56,0x6d,0xb2,0x6d,0x01,0x6e,0x4c,0x56,0x6a,0x55,0xac,0xff,0xfe,0xe1,0xe2,0x4f,0x44,0x39,0x48,0x22,0x23,0x01,0x94,0xa2,0x01,0x37,0xeb,0x7a,0x87,0xd5,0x85, 0x23,0x4e,0x72,0x02,0x1f,0x45,0x7a,0x41,0x28,0x25,0x02,0x2a,0x36,0x66,0x44,0x47,0x58,0x57,0x95,0x59,0x6a,0xc4,0x63,0xfd,0xec,0x23,0xa6,0x5f,0x42,0x6e,0x61,0x5f,0x69,0xcd,0x8a,0x54,0x5c,0x3e,0x37,0x25,0x2d,0x11,0x06,0x3f,0x6c,0x39,0x6e,0x8c,0xaf,0x6d,0x81,0xf5,0x7c,0xe5,0xe2,0x71,0x00,0x02,0x00,0x98,0x00,0xe6,0x03,0xee, 0x04,0x23,0x00,0x0b,0x00,0x17,0x00,0x2a,0xb9,0x00,0x00,0x01,0x85,0xb3,0x0c,0x0c,0x19,0x12,0xbe,0x01,0x85,0x00,0x06,0x00,0x15,0x01,0x7e,0x00,0x03,0x00,0x0f,0x01,0x7e,0xb1,0x09,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x34, 0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xee,0xf8,0xb3,0xb3,0xf8,0xf0,0xbb,0xbb,0xf0,0xa0,0x93,0x78,0x77,0x94,0x97,0x74,0x73,0x98,0x02,0x83,0xae,0xef,0xef,0xae,0xbb,0xe5,0xe5,0xbb,0x71,0xab,0xad,0x6f,0x77,0xa5,0xa8,0x00,0x02,0x01,0x00,0xff,0xba,0x03,0x6f,0x05,0x1a,0x00,0x15,0x00,0x1e,0x00,0x36,0x40,0x09, 0x16,0x12,0x8a,0x02,0x00,0x02,0x00,0x20,0x1b,0xb8,0x01,0x85,0x40,0x0b,0x0a,0x1d,0x99,0x05,0x05,0x00,0x19,0x9b,0x0d,0x06,0x15,0xb8,0x01,0x80,0xb1,0x00,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x33,0x31,0x30,0x05,0x24,0x11,0x35,0x12,0x35,0x06,0x23,0x22,0x26,0x35,0x34, 0x36,0x33,0x32,0x16,0x15,0x10,0x03,0x15,0x14,0x17,0x01,0x35,0x34,0x23,0x22,0x15,0x14,0x33,0x32,0x03,0x6f,0xfe,0xeb,0x0a,0x25,0x25,0x7e,0x9c,0x9f,0x7c,0x7a,0x72,0x0a,0x72,0xfe,0xfa,0x4e,0x7b,0x78,0x21,0x46,0x24,0x01,0x11,0x0c,0x01,0x1e,0xe4,0x08,0x9b,0x7d,0x74,0x99,0xb2,0xe0,0xfe,0xf0,0xfe,0x83,0x07,0x8e,0x0d,0x03,0x44, 0x25,0xb8,0x6d,0x7c,0x00,0x01,0x00,0x5d,0xff,0xbe,0x04,0x26,0x04,0xee,0x00,0x20,0x00,0x4d,0xb2,0x1e,0x05,0x1c,0xb8,0x01,0x85,0x40,0x1d,0x10,0x0d,0x10,0x01,0x00,0x09,0x10,0x00,0x00,0x10,0x09,0x03,0x22,0x16,0x0d,0x05,0x1e,0x1e,0x07,0x0b,0x07,0x0b,0x07,0x01,0x13,0x9b,0x19,0x06,0x00,0xb8,0x01,0x80,0xb1,0x01,0x19,0x00,0x3f, 0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x11,0x33,0x33,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xed,0x32,0x32,0x31,0x30,0x25,0x07,0x26,0x27,0x26,0x27,0x06,0x23,0x22,0x35,0x34,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x36,0x33,0x32,0x00,0x15,0x10,0x05,0x16,0x16, 0x04,0x26,0x28,0x79,0x5b,0x19,0xa2,0x6c,0x6f,0xd9,0xe9,0x79,0x6b,0x6b,0x80,0xc3,0xa3,0xbc,0x8f,0x65,0x72,0xbe,0x80,0xe5,0x01,0x21,0xfe,0xf6,0x65,0x6d,0x58,0x9a,0x11,0x43,0x12,0x98,0x24,0x91,0x8e,0x45,0x38,0xc5,0x73,0xa4,0xc8,0x77,0x7c,0x57,0x44,0xfe,0xda,0xe6,0xfe,0xd1,0xad,0x63,0x3e,0x00,0x00,0x01,0x00,0x6b,0xff,0x7b, 0x04,0x19,0x05,0x04,0x00,0x2a,0x00,0x68,0xb6,0x05,0x04,0x04,0x2c,0x29,0x00,0x26,0xb8,0x01,0x85,0x40,0x19,0x1b,0x08,0x02,0x02,0x16,0x1b,0x0d,0x16,0x0d,0x16,0x22,0x13,0x1b,0x02,0x09,0x29,0x29,0x17,0x0f,0x0f,0x11,0x16,0x9b,0x17,0x11,0xb8,0x01,0x81,0x40,0x0b,0x09,0x17,0x09,0x17,0x09,0x05,0x1f,0x9b,0x24,0x06,0x04,0xb9,0x01, 0x80,0x00,0x05,0x00,0x2f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x39,0x2f,0x11,0x39,0x11,0x12,0x39,0x01,0x2f,0x33,0xc4,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x32,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x01,0x14,0x05,0x16,0x17,0x07,0x26,0x26,0x27,0x07,0x22,0x27,0x26,0x35,0x34,0x33, 0x32,0x17,0x24,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x27,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x20,0x11,0x14,0x06,0x07,0x16,0x04,0x19,0xfe,0xdb,0x41,0x7d,0x29,0x72,0x96,0x62,0x4c,0x8c,0x41,0x77,0xaa,0x6d,0xb3,0x01,0x20,0xfe,0xca,0xcd,0xeb,0x7c,0x94,0x82,0x49,0xa0,0xa8,0xbb,0x38,0xd6,0xc5,0x02,0x0b,0x57,0x3c, 0x9b,0x01,0x8f,0xe9,0x41,0x2e,0x22,0x9a,0x1f,0x51,0x61,0x01,0x12,0x22,0x65,0x78,0x6e,0x14,0x8d,0xcb,0xa1,0x5a,0x53,0x7c,0x29,0x17,0x47,0x97,0x50,0xfe,0xa4,0x46,0x9b,0x24,0x77,0x00,0x00,0x02,0x00,0x94,0xff,0xba,0x03,0xf0,0x05,0x1e,0x00,0x1c,0x00,0x29,0x00,0x53,0xb3,0x00,0x89,0x1c,0x06,0xbb,0x01,0x85,0x00,0x1d,0x00,0x24, 0x01,0x85,0x40,0x1e,0x0e,0x02,0x1c,0x12,0x21,0x18,0x03,0x1d,0x0e,0x1c,0x1d,0x0e,0x0e,0x1d,0x1c,0x03,0x2b,0x15,0x89,0x14,0x18,0x02,0x12,0x21,0x04,0x0a,0x1c,0x14,0x06,0x27,0xb8,0x01,0x80,0xb1,0x0a,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x17,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x17,0x39,0x11,0x39,0x10, 0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x02,0x01,0x1e,0x02,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x00,0x03,0x33,0x16,0x16,0x17,0x3e,0x02,0x37,0x03,0x34,0x27,0x26,0x27,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xf0,0x30,0xfe,0xef,0x81,0x3d,0x1f,0x5c,0x9b,0x53,0x54,0x9a,0x5c,0x1f,0x3e,0x80, 0xfe,0xeb,0x2c,0xaa,0x22,0x76,0x6f,0x57,0x55,0x3d,0x18,0x5a,0x38,0x11,0x5e,0x72,0x3b,0x67,0x43,0x43,0x67,0x05,0x1e,0xfe,0x81,0xfe,0xdc,0x95,0x64,0x63,0x30,0x51,0x8f,0x55,0x55,0x8f,0x51,0x30,0x63,0x65,0x94,0x01,0x28,0x01,0x7b,0xb6,0xfa,0x76,0x5a,0x8d,0xba,0x85,0xfb,0xd1,0x3b,0x50,0x18,0x6c,0x84,0x50,0x3b,0x38,0x5e,0x5c, 0x00,0x01,0x00,0x59,0xff,0xf6,0x04,0x2b,0x04,0xe1,0x00,0x1a,0x00,0x48,0xb9,0x00,0x10,0x01,0x85,0xb2,0x0a,0x18,0x00,0xb8,0x01,0x85,0x40,0x0d,0x01,0x0a,0x01,0x0a,0x01,0x1c,0x12,0x89,0x0d,0x07,0x18,0x12,0x15,0xb8,0x01,0x80,0x40,0x0b,0x02,0x07,0x0d,0x04,0x04,0x01,0x19,0x0d,0x06,0x01,0x18,0x00,0x3f,0x3f,0x33,0x12,0x39,0x2f, 0x12,0x39,0x39,0xed,0x32,0x32,0x01,0x2f,0xc6,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x10,0xed,0x31,0x30,0x05,0x23,0x11,0x06,0x23,0x22,0x24,0x27,0x37,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16,0x33,0x32,0x36,0x37,0x11,0x33,0x04,0x2b,0xa0,0x7b,0xe0,0xa7,0xfe,0xf9,0x29,0x4f,0x39,0x41,0x23,0xaa,0x5a, 0x65,0x1f,0x9f,0x56,0x57,0xd7,0x2d,0xa0,0x0a,0x01,0x53,0x2a,0x8e,0x7e,0x69,0x66,0x92,0x50,0xde,0x27,0xac,0xa9,0xcd,0x98,0x31,0x37,0x22,0x16,0x02,0xea,0x00,0x01,0x00,0x7d,0xff,0xf6,0x04,0x06,0x06,0x30,0x00,0x2d,0x00,0x68,0xb9,0x00,0x17,0x01,0x85,0x40,0x10,0x0c,0x13,0x0e,0x13,0x1a,0x1a,0x13,0x0e,0x03,0x05,0x2f,0x25,0x25, 0x00,0x20,0x28,0xb8,0x01,0x85,0x40,0x1c,0x09,0x07,0x05,0x14,0x9b,0x11,0x0c,0x00,0x2d,0x07,0x26,0x9b,0x23,0x1a,0x1b,0x2d,0x23,0x1b,0x1b,0x23,0x2d,0x03,0x02,0x1d,0x9b,0x0c,0x06,0x2b,0xb8,0x01,0x80,0xb1,0x02,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x39,0x11,0x33,0x10,0xdd,0xed,0x01, 0x2f,0x33,0x33,0xfd,0x32,0xc4,0x39,0x2f,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0xed,0x31,0x30,0x25,0x06,0x23,0x22,0x24,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x17,0x15,0x27,0x22,0x06,0x15,0x14,0x17,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x20,0x15,0x14,0x16,0x33, 0x32,0x37,0x04,0x06,0xb9,0xc0,0xe9,0xfe,0xd9,0xa0,0x9c,0xde,0xc2,0x1c,0x98,0x7a,0x69,0x69,0x50,0x22,0x68,0x88,0x23,0x75,0x7a,0xc1,0xa2,0xba,0x84,0xec,0xcb,0xfe,0x9d,0xe0,0x91,0xa3,0xa5,0x39,0x43,0xc4,0xaf,0xa5,0x5c,0x5d,0xb1,0x98,0xb4,0x10,0x32,0x45,0x6a,0x7b,0x04,0xa7,0x03,0x1c,0x21,0x47,0x27,0x23,0x9c,0x1a,0x5f,0x61, 0x52,0x6d,0xaf,0xa1,0x61,0x72,0x3b,0x00,0x00,0x01,0x00,0xbf,0xff,0xf0,0x03,0xc4,0x05,0x25,0x00,0x17,0x00,0x40,0xb4,0x03,0x04,0x10,0x0f,0x00,0xb8,0x01,0x85,0x40,0x09,0x07,0x0f,0x07,0x04,0x07,0x04,0x07,0x19,0x0d,0xb8,0x01,0x85,0x40,0x0c,0x12,0x0f,0x10,0x10,0x15,0x04,0x03,0x19,0x0a,0x9b,0x15,0x06,0x00,0x3f,0xed,0x3f,0x33, 0x12,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x14,0x00,0x05,0x27,0x36,0x00,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x03,0xc4,0xfe,0xba,0xff,0x00,0x70,0xe0,0x01,0x37,0x98,0x69,0x52,0x74,0x40,0x8c,0x53,0xc4, 0xa1,0xb1,0xef,0x03,0x92,0xc2,0xfe,0x08,0xe8,0x71,0xcb,0x01,0xc9,0x9d,0x61,0x92,0x6b,0x46,0x52,0x6b,0x4e,0x75,0x96,0x8f,0xc2,0xe8,0x00,0x01,0x00,0x2b,0xff,0xf6,0x04,0x59,0x05,0x29,0x00,0x18,0x00,0x3c,0xb6,0x10,0x00,0x10,0x00,0x1a,0x0e,0x13,0xb8,0x01,0x85,0x40,0x09,0x09,0x05,0x00,0x18,0x18,0x10,0x02,0x0c,0x0f,0xb8,0x01, 0x80,0xb3,0x07,0x10,0x06,0x16,0xb8,0x01,0x80,0xb1,0x02,0x18,0x00,0x3f,0xed,0x3f,0x33,0xfd,0xc4,0x11,0x12,0x39,0x2f,0x33,0x01,0x2f,0xc4,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x25,0x06,0x23,0x22,0x00,0x11,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x21,0x15,0x21,0x16,0x15,0x10,0x12,0x33,0x32,0x37,0x04,0x59,0x9b, 0xa6,0xfb,0xfe,0xcd,0x07,0xb8,0x83,0x40,0x5c,0x26,0x02,0xbd,0xfd,0x59,0x03,0xdd,0xb2,0x65,0x79,0x65,0x6f,0x01,0xd2,0x01,0x80,0x52,0x47,0x09,0x89,0x3f,0x77,0xa8,0x9f,0x2f,0x6b,0xfe,0xc9,0xfe,0x85,0x4d,0x00,0x01,0x00,0x2b,0xff,0xf6,0x04,0x59,0x05,0xda,0x00,0x25,0x00,0x4a,0xb9,0x00,0x19,0x01,0x85,0x40,0x0e,0x0f,0x1d,0x11, 0x1d,0x15,0x00,0x00,0x15,0x1d,0x11,0x04,0x27,0x0e,0x20,0xb8,0x01,0x85,0xb7,0x09,0x05,0x17,0x9b,0x14,0x1c,0x0c,0x0e,0xb8,0x01,0x80,0xb3,0x07,0x1e,0x06,0x23,0xb8,0x01,0x80,0xb1,0x02,0x18,0x00,0x3f,0xed,0x3f,0x33,0xfd,0xcd,0x33,0xd4,0xed,0x01,0x2f,0xc4,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x12,0x39,0xed,0x31,0x30, 0x25,0x06,0x23,0x22,0x00,0x11,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x21,0x26,0x35,0x34,0x36,0x33,0x15,0x22,0x07,0x06,0x15,0x14,0x16,0x33,0x15,0x21,0x16,0x15,0x10,0x12,0x33,0x32,0x37,0x04,0x59,0x9b,0xa6,0xfb,0xfe,0xcd,0x07,0xb8,0x83,0x40,0x5c,0x26,0x01,0xb5,0x11,0x8e,0xb1,0x44,0x17,0x45,0x46,0x34,0xfd,0x59,0x03, 0xdd,0xb2,0x65,0x79,0x65,0x6f,0x01,0xd2,0x01,0x80,0x52,0x47,0x09,0x89,0x3f,0x77,0xa8,0x2c,0x37,0x7f,0x77,0xa0,0x06,0x11,0x3f,0x2c,0x37,0x9f,0x2f,0x6b,0xfe,0xc9,0xfe,0x85,0x4d,0x00,0x00,0x02,0x00,0x76,0x01,0x13,0x03,0xc8,0x04,0xa4,0x00,0x0b,0x00,0x19,0x00,0x27,0xb9,0x00,0x10,0x01,0x85,0xb3,0x09,0x09,0x1b,0x03,0xbb,0x01, 0x85,0x00,0x17,0x00,0x06,0x01,0x80,0xb4,0x13,0x00,0x9b,0x0c,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x02,0x20,0x73,0x99,0x9d,0x6f,0x70,0x9a,0x97,0x73,0x75, 0xc3,0x70,0xed,0xbb,0x72,0xc6,0x72,0xe9,0x04,0x09,0xab,0x81,0x7f,0xb0,0xb0,0x7f,0x80,0xac,0x9b,0x76,0xd3,0x7f,0xc8,0xfe,0xff,0x7a,0xd3,0x7c,0xce,0xfa,0x00,0x02,0x00,0x2d,0xff,0xe8,0x03,0x89,0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0x3c,0x40,0x0b,0x18,0x0d,0x8a,0x0e,0x0f,0x15,0x0f,0x15,0x0f,0x23,0x1f,0xbb,0x01,0x85,0x00,0x06, 0x00,0x16,0x01,0x80,0xb3,0x03,0x03,0x09,0x0d,0xb8,0x01,0x80,0xb5,0x12,0x19,0x1c,0x9b,0x09,0x07,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x33,0x31,0x30,0x01,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35, 0x03,0x32,0x37,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x0c,0x02,0x50,0x4e,0x8c,0xb3,0xb2,0x87,0x92,0xb8,0x90,0x49,0x3f,0x83,0x35,0x42,0x44,0xa4,0x58,0x4c,0x55,0x49,0x47,0x5c,0x5b,0x03,0x39,0x02,0x15,0xb7,0x98,0x8c,0xb1,0xc9,0x9f,0xfc,0x38,0x67,0xac,0x28,0x2d,0x55,0x4b,0x03,0x3e,0x23,0x66,0x5e,0x6a,0x5e,0x49, 0x4c,0x5e,0x00,0x01,0x00,0x7c,0xff,0xe8,0x04,0x43,0x05,0xb2,0x00,0x26,0x00,0x55,0xb9,0x00,0x00,0x01,0x85,0x40,0x24,0x09,0x0a,0x1b,0x0a,0x1b,0x0a,0x28,0x18,0x03,0x8b,0x21,0x13,0x10,0x0a,0x09,0x03,0x21,0x20,0x18,0x10,0x16,0x09,0x10,0x16,0x20,0x20,0x16,0x10,0x09,0x04,0x0c,0x1e,0x9b,0x23,0x07,0x07,0xb8,0x01,0x80,0xb1,0x0c, 0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x32,0x11,0x33,0x01,0x2f,0xcd,0xc4,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x17,0x16,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x36, 0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x03,0x84,0xca,0xac,0x25,0x22,0x64,0x51,0x73,0x8c,0x3a,0x96,0x9f,0x90,0xb4,0x30,0x28,0x7d,0x79,0x68,0x47,0x94,0x38,0x6e,0x81,0xbe,0x9f,0x62,0x33,0x1a,0x38,0x60,0xa7,0xed,0x7e,0x03,0xce,0xa3,0xf2,0x26,0x90,0x82,0x7e,0x47,0x9e,0x44,0xbc,0xc0,0xa3,0x05,0x4e,0x53, 0x45,0x5d,0x9d,0x20,0x9c,0x6b,0x90,0xae,0x08,0x95,0x0e,0x7a,0xdb,0x00,0x00,0x01,0x00,0x0f,0xff,0xe8,0x04,0x52,0x05,0xb2,0x00,0x2b,0x00,0x5b,0xb9,0x00,0x02,0x01,0x85,0x40,0x0d,0x00,0x1d,0x10,0x10,0x2d,0x1d,0x23,0x17,0x23,0x17,0x0a,0x09,0x29,0xb8,0x01,0x85,0x40,0x17,0x1d,0x09,0x0a,0x00,0x13,0x17,0x9b,0x18,0x23,0x22,0x0a, 0x18,0x22,0x22,0x18,0x0a,0x03,0x06,0x20,0x9b,0x25,0x07,0x0d,0xb8,0x01,0x80,0xb1,0x06,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x39,0x11,0x33,0x01,0x2f,0xed,0xc4,0x32,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x2f,0x12,0x39,0xed,0x31,0x30,0x01,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x24, 0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x07,0x03,0x80,0xd2,0x7b,0xdd,0x89,0xb9,0xfe,0xd6,0x7f,0x7a,0x5e,0xf8,0x8d,0x97,0xb1,0x70,0x5e,0x36,0x40,0x58,0x4d,0x13,0x29,0x5d,0x6f,0x8e,0x96,0x78, 0x4d,0x3f,0x23,0x4d,0x57,0x88,0xc7,0x68,0x7f,0x02,0xf7,0x8d,0xe4,0x7d,0xbc,0x65,0xb6,0xc0,0x5f,0x94,0xa6,0x8e,0x7e,0x56,0x90,0x2f,0x10,0x0b,0x97,0x07,0x89,0x6a,0x6f,0x86,0x12,0x97,0x16,0x6a,0xbd,0x74,0xb0,0x6e,0x00,0x02,0x00,0x0a,0xff,0xe8,0x04,0xc4,0x05,0xbc,0x00,0x10,0x00,0x1b,0x00,0x57,0xbc,0x00,0x16,0x01,0x85,0x00, 0x0d,0x00,0x07,0x01,0x85,0x40,0x1c,0x11,0x02,0x03,0x14,0x01,0x0f,0x03,0x0d,0x04,0x11,0x03,0x0d,0x11,0x03,0x03,0x11,0x0d,0x03,0x1d,0x00,0x10,0x01,0x0f,0x04,0x14,0x04,0x00,0x19,0xb8,0x01,0x80,0xb7,0x0a,0x19,0x03,0x10,0x10,0x02,0x00,0x07,0x00,0x3f,0x32,0x32,0x11,0x33,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0x33,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x17,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x01,0x01,0x17,0x01,0x16,0x12,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x10,0x37,0x01,0x01,0x34,0x26,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x70,0x01,0xf5,0x01,0xed,0x72,0xfe,0x16,0x76,0x71,0xbd,0x9b,0x9f,0xbd,0xe6,0xfe,0x17,0x03,0x19, 0x55,0x64,0xbf,0x67,0x50,0x54,0x6d,0x05,0xbc,0xfe,0x3a,0x01,0xc6,0x75,0xfe,0x3b,0x81,0xfe,0xff,0x92,0xae,0xd8,0xe0,0xb0,0x01,0x1a,0xf6,0x01,0xbc,0xfc,0x35,0x5a,0xd5,0x6e,0xcb,0xd8,0x67,0x89,0x8a,0x00,0x00,0x01,0x00,0x16,0xff,0xe8,0x05,0x11,0x05,0xb2,0x00,0x22,0x00,0x4b,0x40,0x12,0x01,0x02,0x20,0x00,0x8a,0x08,0x02,0x08, 0x02,0x08,0x24,0x1b,0x8a,0x15,0x0e,0x21,0x06,0x1e,0xb8,0x01,0x80,0x40,0x0d,0x15,0x09,0x14,0x0b,0x14,0x0b,0x14,0x05,0x12,0x9b,0x17,0x07,0x00,0xb8,0x01,0x80,0xb1,0x05,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x32,0xed,0x3f,0x01,0x2f,0xc4,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x11,0x33,0x31, 0x30,0x25,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x16,0x33,0x32,0x37,0x11,0x33,0x04,0x38,0x90,0x49,0x3f,0x83,0x35,0x42,0x44,0x6e,0x8b,0xda,0xe8,0x2c,0x2f,0x2d,0x1c,0x1f,0x28,0x41,0x76,0x88,0x8e,0x7c,0x97,0x76,0xa4,0x82, 0x67,0xac,0x28,0x2d,0x55,0x4b,0xfb,0x35,0xed,0xdb,0x01,0xa2,0x29,0x36,0x05,0x96,0x0a,0x91,0x7f,0xfe,0x5e,0x87,0x90,0x66,0x03,0x4b,0x00,0x01,0x00,0x41,0xff,0xe8,0x04,0x85,0x05,0xbb,0x00,0x36,0x00,0x70,0xbf,0x00,0x0a,0x01,0x85,0x00,0x15,0x00,0x2a,0x01,0x85,0x00,0x27,0x00,0x04,0x01,0x85,0x40,0x11,0x1b,0x1d,0x27,0x1b,0x15, 0x00,0x0f,0x27,0x1b,0x1b,0x27,0x0f,0x00,0x15,0x05,0x38,0x30,0xb8,0x01,0x85,0x40,0x16,0x20,0x0f,0x10,0x07,0x17,0x17,0x1d,0x12,0x00,0x9b,0x2d,0x22,0x10,0x0d,0x22,0x27,0x36,0x36,0x0d,0x27,0x07,0x12,0xb8,0x01,0x80,0xb1,0x0d,0x19,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x11,0x33,0xed,0x12,0x39,0x39,0x11,0x33, 0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x2e,0x02,0x35,0x34,0x37,0x35,0x24,0x35,0x10,0x21,0x32,0x36,0x35,0x34,0x27,0x17, 0x16,0x15,0x14,0x06,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x03,0x30,0xb9,0x5f,0x66,0x81,0xb5,0xdb,0xc2,0xa2,0x89,0x86,0x60,0x2f,0x57,0x5b,0x3f,0x53,0xfa,0xb6,0xc1,0x62,0x44,0xfe,0xe9,0x01,0x9a,0x43,0x56,0x06,0x9d,0x04,0xac,0x82,0x87,0x7b,0x89,0x6c,0x2b,0x2d,0xed,0x03,0x1a,0x1c,0x0e,0x59,0x48,0x3d,0x3d,0x05, 0x07,0x79,0x75,0x6d,0x86,0x28,0x8b,0x1b,0x38,0x27,0x50,0x06,0x05,0x3d,0x7b,0x62,0x66,0x4a,0x02,0x45,0xdb,0x01,0x25,0x25,0x22,0x17,0x12,0x33,0x12,0x1e,0x49,0x5f,0x47,0x47,0x43,0x50,0x03,0x23,0x00,0x02,0x00,0x36,0xff,0xe8,0x04,0xaf,0x05,0xb2,0x00,0x1d,0x00,0x29,0x00,0x53,0xb1,0x21,0x16,0xbb,0x01,0x85,0x00,0x07,0x00,0x27, 0x01,0x85,0x40,0x0d,0x0f,0x07,0x0f,0x07,0x0f,0x2b,0x00,0x8b,0x1d,0x1d,0x00,0x21,0x1e,0xb8,0x01,0x80,0x40,0x09,0x0c,0x09,0x0c,0x00,0x0c,0x00,0x0c,0x12,0x03,0xb8,0x01,0x80,0xb5,0x1a,0x19,0x24,0x9b,0x12,0x07,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x32,0x11,0x33,0x01,0x2f,0xed,0x12,0x39,0x39, 0x2f,0x2f,0x10,0xed,0x10,0xed,0x33,0x31,0x30,0x13,0x12,0x12,0x33,0x32,0x36,0x12,0x35,0x34,0x27,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x22,0x00,0x03,0x25,0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xd1,0x2c,0xcf,0xb5,0x76,0xb8,0x62,0x04,0x02,0x7d,0x9b,0xa1,0xc9, 0xc0,0xa2,0x89,0xce,0x6d,0x89,0xfd,0xa2,0xf8,0xfe,0xde,0x37,0x02,0xb4,0x42,0x89,0x3d,0x21,0x83,0x52,0x5e,0x77,0x6d,0x03,0x23,0xfe,0x94,0xfe,0xcc,0x92,0x01,0x00,0x97,0x3d,0x3a,0x6a,0xdb,0xb0,0xa5,0xc9,0xbf,0xfe,0x9b,0xed,0xc9,0xfe,0xc0,0xb0,0x01,0x70,0x01,0xa2,0x5a,0x47,0x44,0x91,0xa7,0x73,0x5f,0x6c,0x85,0x00,0x00,0x01, 0x00,0x80,0xff,0xe8,0x04,0x3e,0x05,0xbc,0x00,0x14,0x00,0x33,0x40,0x14,0x14,0x00,0x09,0x0a,0x00,0x0a,0x00,0x0a,0x16,0x04,0x8b,0x10,0x0a,0x09,0x09,0x0d,0x00,0x14,0x07,0x07,0xb8,0x01,0x80,0xb1,0x0d,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x01, 0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x13,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x37,0x01,0x03,0x7c,0xfe,0x6e,0x6f,0x5e,0x90,0x74,0xe9,0xab,0x89,0x7c,0xfd,0xa0,0xbb,0xea,0x6c,0x71,0x01,0x96,0x05,0x5f,0xfd,0xdf,0x97,0xd8,0x5a,0x6a,0x88,0x01,0x3b,0x57,0xd3,0xac,0xe3,0xaf,0x7c,0x01,0x07,0x98,0x02,0x27,0x00,0x02, 0x00,0x7d,0xff,0xe8,0x04,0x96,0x05,0xb5,0x00,0x03,0x00,0x18,0x00,0x58,0x40,0x13,0x03,0x00,0x15,0x16,0x01,0x02,0x0b,0x0c,0x00,0x16,0x02,0x0c,0x0c,0x02,0x16,0x00,0x04,0x1a,0x04,0xb8,0x01,0x85,0x40,0x13,0x12,0x0c,0x0b,0x00,0x03,0x02,0x01,0x0b,0x03,0x01,0x01,0x03,0x0b,0x03,0x0e,0x16,0x15,0x07,0x08,0xb8,0x01,0x80,0xb1,0x0e, 0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x01,0x17,0x01,0x25,0x14,0x16,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x37,0x17,0x06,0x02,0x02, 0x1d,0x01,0xb1,0x71,0xfe,0x52,0xfe,0x8a,0x72,0xc8,0x78,0x61,0xa7,0x51,0x70,0xce,0xf5,0xae,0xfe,0xef,0x97,0xdc,0xca,0x70,0xad,0xcb,0x02,0x68,0x01,0x8c,0x73,0xfe,0x75,0x9a,0x99,0xf0,0x84,0x49,0x43,0x73,0xb4,0xab,0x01,0x3c,0xcc,0xe6,0x01,0x97,0x9d,0x75,0x84,0xfe,0x90,0x00,0x00,0x02,0x00,0x82,0x00,0xd7,0x04,0x4f,0x04,0x89, 0x00,0x0f,0x00,0x1c,0x00,0x22,0x40,0x09,0x08,0x89,0x10,0x10,0x1e,0x16,0x89,0x00,0x19,0xb8,0x01,0x80,0xb4,0x0c,0x13,0x9b,0x04,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x13,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14, 0x16,0x33,0x32,0x36,0x36,0x82,0x81,0xe3,0x83,0x81,0xe3,0x82,0x84,0xe2,0x80,0x81,0xe3,0x83,0x03,0x26,0xb9,0x86,0x84,0xbc,0xbb,0x85,0x55,0x94,0x56,0x02,0xb0,0x7d,0xda,0x82,0x80,0xdc,0x7d,0x7e,0xdc,0x7f,0x80,0xdc,0x7d,0x84,0xbc,0xbc,0x84,0x82,0xbd,0x54,0x96,0x00,0x00,0x02,0x00,0x82,0xff,0xe2,0x03,0x7f,0x05,0x7d,0x00,0x15, 0x00,0x21,0x00,0x3b,0x40,0x0e,0x08,0x8a,0x13,0x12,0x16,0x12,0x16,0x12,0x23,0x0e,0x1c,0x89,0x00,0x1f,0xb8,0x01,0x80,0x40,0x0d,0x0e,0x04,0x0c,0x0c,0x13,0x19,0x9b,0x04,0x06,0x12,0x9a,0x13,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x31,0x30,0x13, 0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x27,0x1e,0x02,0x17,0x07,0x24,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x82,0x69,0xb2,0x67,0x65,0xb1,0x65,0x64,0xb2,0x65,0x68,0x47,0x1b,0x8c,0xe0,0x84,0x56,0xfe,0xcc,0xfe,0xac,0x02,0x58,0x7d,0x59,0x55,0x7f,0x7e,0x56,0x59,0x7d,0x03, 0xe5,0x6c,0xbe,0x6e,0x69,0xb1,0x62,0x64,0xae,0x68,0x33,0x72,0xe3,0xc1,0x3c,0x86,0x92,0x02,0x27,0x01,0x66,0x5c,0x84,0x8b,0x63,0x58,0x7c,0x87,0x00,0x02,0x00,0x96,0xff,0xe2,0x03,0x93,0x05,0x7d,0x00,0x17,0x00,0x23,0x00,0x3d,0x40,0x0f,0x03,0x04,0x0a,0x00,0x89,0x1e,0x04,0x1e,0x04,0x1e,0x25,0x18,0x89,0x10,0x1b,0xb8,0x01,0x80, 0x40,0x0d,0x0a,0x14,0x0c,0x0c,0x03,0x21,0x9b,0x14,0x06,0x04,0x9a,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x11,0x33,0x31,0x30,0x01,0x10,0x00,0x05,0x27,0x36,0x36,0x37,0x15,0x36,0x37,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16, 0x16,0x05,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0x93,0xfe,0xaa,0xfe,0xcf,0x55,0x68,0xbc,0x44,0x74,0x2e,0x49,0x67,0x65,0xb1,0x65,0x67,0xb0,0x64,0x66,0xb3,0x69,0xfd,0xaa,0x7d,0x57,0x57,0x7d,0x7d,0x57,0x58,0x7c,0x03,0xe5,0xfe,0xb7,0xfd,0xd7,0x91,0x86,0x31,0x90,0x4f,0x01,0x91,0xb2,0x33,0x67,0xaf,0x64, 0x64,0xb1,0x67,0x6e,0xbe,0x50,0x5d,0x85,0x7d,0x57,0x62,0x8c,0x83,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x05,0x4c,0x05,0x7d,0x00,0x33,0x00,0x57,0x40,0x1a,0x11,0x10,0x14,0x89,0x0d,0x22,0x32,0x8a,0x33,0x29,0x8a,0x2a,0x10,0x0d,0x33,0x2a,0x2a,0x33,0x0d,0x10,0x04,0x35,0x07,0x89,0x1b,0x0a,0xb8,0x01,0x81,0x40,0x11,0x10,0x22,0x11, 0x17,0x11,0x17,0x11,0x1f,0x2a,0x33,0x18,0x2e,0x04,0x9b,0x25,0x1f,0x06,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x33,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36, 0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x02,0xaf,0x31,0x4f,0x27,0x5c,0x82,0x4c,0x36,0x17,0x1c,0x2e,0x27,0x33,0x52,0x77,0x80,0x5a,0x50,0x8b,0x4f,0x61,0xb4,0x74,0x4f, 0x86,0x1d,0x2a,0x7f,0x4e,0xa1,0xb7,0xa4,0x69,0x46,0x4a,0x5c,0xa4,0x03,0xe7,0x3f,0x76,0x45,0xc8,0x91,0x6d,0x9d,0x26,0x19,0x16,0x2e,0x11,0x8d,0x04,0x87,0x57,0x5f,0x88,0x77,0xc7,0x74,0x8f,0xe5,0x81,0x53,0x40,0x48,0x4b,0xc0,0xa2,0xfb,0xe5,0x04,0x1b,0x4f,0x77,0x8d,0x6d,0xfc,0x19,0x00,0x00,0x02,0x00,0x64,0xff,0xe5,0x05,0x0b, 0x05,0xa9,0x00,0x17,0x00,0x23,0x00,0x53,0x40,0x29,0x1e,0x89,0x00,0x10,0x89,0x18,0x0b,0x8b,0x0a,0x08,0x1b,0x03,0x03,0x00,0x0d,0x18,0x0a,0x00,0x18,0x0a,0x0a,0x18,0x00,0x03,0x25,0x06,0x89,0x05,0x0b,0x05,0x05,0x08,0x03,0x0d,0x1b,0x04,0x14,0x0a,0x06,0x07,0x21,0xb8,0x01,0x80,0xb1,0x14,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x17, 0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x17,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x37,0x26,0x03,0x37,0x12,0x05,0x36,0x13,0x17,0x02,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x25,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01, 0x27,0x95,0x84,0xee,0xee,0xa6,0xa6,0x01,0x1e,0xc3,0xe1,0x99,0xd6,0xde,0x85,0x93,0x72,0xc3,0x6f,0x6f,0xc1,0x74,0x02,0xa0,0x8c,0x70,0x73,0x8a,0x94,0x69,0x67,0x95,0x01,0x60,0x87,0xfa,0x57,0x94,0x01,0x9b,0x42,0xfe,0xa2,0xb0,0x6d,0x01,0x87,0x43,0xfe,0x8d,0xa2,0x64,0xf1,0x74,0x6e,0xb5,0x66,0x65,0xb1,0x72,0x5f,0xc7,0x3f,0x38, 0xcf,0x6b,0x5c,0x84,0x8b,0x00,0x00,0x03,0x00,0x64,0xff,0xe5,0x05,0x23,0x05,0x7d,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x6e,0x40,0x39,0x37,0x89,0x0a,0x1d,0x89,0x25,0x12,0x89,0x31,0x19,0x18,0x3a,0x28,0x03,0x08,0x04,0x0a,0x25,0x15,0x1b,0x31,0x18,0x0a,0x25,0x31,0x18,0x18,0x31,0x25,0x0a,0x04,0x3e,0x06,0x05,0x2b,0x89,0x00,0x18, 0x05,0x08,0x3a,0x15,0x03,0x28,0x1b,0x06,0x06,0x19,0x06,0x19,0x06,0x21,0x34,0x9b,0x0e,0x06,0x2e,0xb8,0x01,0x80,0xb1,0x21,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x32,0x33,0x01,0x2f,0xed,0xc6,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x39,0x11,0x12,0x17,0x39,0x11,0x33,0x10,0xed, 0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x37,0x26,0x03,0x37,0x16,0x17,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x27,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x25,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x13,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16, 0x17,0x36,0x36,0x01,0x0b,0x7d,0x6e,0xc8,0xca,0x86,0x80,0x8c,0x49,0x63,0xaa,0x61,0x5c,0xa4,0x60,0x89,0x5f,0x73,0xba,0x63,0x88,0x60,0x82,0x48,0x66,0xb0,0x64,0x65,0xb0,0x67,0x02,0x50,0x50,0x43,0x7d,0x97,0x7c,0x57,0x56,0x7e,0x79,0x6d,0x4c,0x52,0x74,0x4f,0x45,0x6a,0x81,0x01,0x47,0x57,0xb0,0x47,0x59,0x01,0x24,0x65,0xe0,0x56, 0x62,0x78,0x5d,0xa5,0x60,0x64,0xab,0x60,0x5d,0xb5,0x3b,0x2b,0xa3,0x89,0x65,0xaa,0x5c,0x7e,0x62,0x55,0x98,0x59,0x60,0xa4,0x42,0x54,0x9f,0x32,0x29,0x95,0x4b,0x53,0x74,0x62,0x03,0x2c,0x56,0x7d,0x74,0x52,0x3f,0x8a,0x3d,0x38,0x89,0x00,0x00,0x01,0x00,0x64,0x00,0x00,0x04,0xe2,0x05,0x7d,0x00,0x2f,0x00,0x57,0x40,0x16,0x12,0x89, 0x1f,0x2c,0x89,0x05,0x1f,0x05,0x1f,0x05,0x24,0x31,0x19,0x18,0x18,0x00,0x0c,0x89,0x24,0x18,0x19,0x1c,0xb8,0x01,0x80,0x40,0x0f,0x15,0x0c,0x28,0x1f,0x15,0x19,0x15,0x19,0x15,0x00,0x09,0x9b,0x28,0x06,0x01,0xb8,0x01,0x81,0xb1,0x00,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x12,0x39,0x10,0xed,0x11,0x33, 0x01,0x2f,0xed,0xc4,0x39,0x2f,0x33,0x11,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x33,0x35,0x33,0x20,0x00,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15, 0x10,0x00,0x21,0x64,0xcc,0x01,0x42,0x01,0xc7,0x56,0x94,0x56,0x57,0x7e,0x37,0x2e,0x43,0x4b,0xc1,0x86,0x61,0xc1,0x42,0x86,0x36,0x75,0x33,0x44,0x5c,0x76,0x3a,0x42,0x66,0xaf,0x66,0x81,0xe4,0x84,0xfd,0xd4,0xfe,0x7a,0xa7,0x01,0x9f,0x01,0x27,0x63,0xad,0x64,0x54,0x3c,0x17,0x39,0x1a,0x26,0x6b,0x3a,0x77,0xa7,0x77,0x76,0x55,0x50, 0x57,0x46,0x2f,0x3e,0x3d,0x1f,0x6e,0x3d,0x4f,0x8b,0x50,0x90,0xf5,0x8b,0xfe,0x94,0xfd,0xff,0x00,0x02,0x00,0x64,0xff,0xe5,0x04,0xed,0x05,0x7d,0x00,0x27,0x00,0x33,0x00,0x50,0x40,0x13,0x24,0x89,0x05,0x15,0x89,0x2e,0x05,0x2e,0x00,0x00,0x2e,0x05,0x03,0x35,0x28,0x0d,0x8a,0x1c,0x2b,0xb8,0x01,0x80,0x40,0x10,0x18,0x31,0x9b,0x12, 0x0f,0x12,0x18,0x12,0x18,0x12,0x00,0x09,0x9b,0x20,0x06,0x01,0xb8,0x01,0x80,0xb1,0x00,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x17,0x35,0x33,0x20,0x00,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15, 0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x10,0x00,0x21,0x13,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x64,0x95,0x01,0x5e,0x01,0xef,0x73,0xcc,0x72,0x69,0xb8,0x6b,0x09,0x27,0x7d,0x4a,0x77,0xa0,0xa0,0x70,0x6e,0xc4,0x71,0x99,0x01,0x06, 0x92,0x9f,0x01,0x17,0xa2,0xfd,0xab,0xfe,0x61,0x79,0x11,0x53,0x31,0x2e,0x3b,0x46,0x2a,0x30,0x50,0x1b,0x9c,0x01,0xad,0x01,0x32,0x66,0xb3,0x68,0x5e,0xa2,0x5e,0x18,0x26,0x43,0x54,0x9a,0x69,0x6b,0x98,0x75,0xc9,0x6f,0x86,0xec,0x88,0x92,0xfd,0x8e,0xfe,0x8b,0xfd,0xfa,0x02,0xcb,0x1b,0x24,0x40,0x28,0x26,0x36,0x4c,0x00,0x00,0x01, 0x00,0xb4,0x00,0x00,0x04,0x5a,0x05,0x42,0x00,0x05,0x00,0x16,0x40,0x0a,0x01,0x04,0x89,0x05,0x05,0x18,0x03,0x9b,0x00,0x06,0x00,0x3f,0xed,0x3f,0x01,0x2f,0xfd,0xc4,0x31,0x30,0x13,0x21,0x15,0x21,0x11,0x23,0xb4,0x03,0xa6,0xfd,0x02,0xa8,0x05,0x42,0x99,0xfb,0x57,0x00,0x00,0x01,0x00,0x82,0xff,0xe2,0x03,0xf2,0x05,0x62,0x00,0x16, 0x00,0x3b,0x40,0x1d,0x04,0x03,0x0c,0x08,0x89,0x13,0x12,0x0c,0x00,0x05,0x12,0x05,0x12,0x18,0x0f,0x89,0x00,0x0c,0x05,0x0b,0x0b,0x03,0x12,0x99,0x13,0x19,0x06,0x03,0x06,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x11,0x33,0xed,0x11,0x33,0x33,0x31,0x30,0x13,0x34,0x12, 0x37,0x33,0x01,0x11,0x33,0x11,0x14,0x06,0x23,0x01,0x06,0x06,0x15,0x14,0x00,0x17,0x07,0x26,0x24,0x02,0x82,0xb1,0x9b,0x1b,0x01,0x62,0xa7,0x1e,0x13,0xfe,0x14,0x56,0x54,0x01,0x19,0xec,0x43,0xac,0xfe,0xe0,0x9f,0x02,0xe5,0xac,0x01,0x58,0x79,0xfe,0x8f,0x01,0x71,0xfd,0x5b,0x0b,0x13,0x01,0xf5,0x51,0xde,0x80,0xcd,0xfe,0xb1,0x51, 0x96,0x3b,0xf3,0x01,0x35,0x00,0x00,0x02,0x00,0x77,0xff,0xe8,0x04,0x41,0x05,0x48,0x00,0x0b,0x00,0x17,0x00,0x20,0x40,0x10,0x00,0x89,0x0c,0x0c,0x19,0x12,0x89,0x06,0x09,0x99,0x0f,0x06,0x15,0x99,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33, 0x32,0x12,0x03,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x04,0x41,0xfb,0xeb,0xea,0xfa,0xfa,0xea,0xeb,0xfb,0xab,0x9a,0xa1,0xa1,0x98,0x97,0xa2,0xa2,0x99,0x02,0x97,0xfe,0xa8,0xfe,0xa9,0x01,0x57,0x01,0x58,0x01,0x59,0x01,0x58,0xfe,0xa8,0xfe,0xa7,0x01,0x17,0x01,0x06,0xfe,0xf7,0xfe,0xec,0xfe,0xeb,0xfe,0xfc,0x01, 0x02,0x00,0x00,0x03,0x00,0x50,0x00,0x00,0x05,0x94,0x05,0x31,0x00,0x1d,0x00,0x21,0x00,0x2d,0x00,0x57,0x40,0x30,0x21,0x89,0x14,0x19,0x0a,0x89,0x2d,0x1e,0x2d,0x00,0x89,0x07,0x14,0x2d,0x03,0x07,0x17,0x17,0x07,0x03,0x2d,0x14,0x05,0x2f,0x26,0x89,0x11,0x09,0x23,0x9b,0x14,0x19,0x21,0x21,0x0d,0x18,0x20,0x9b,0x15,0x06,0x2a,0x99, 0x0d,0x18,0x04,0x99,0x03,0x18,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x35,0x32,0x36,0x35,0x10,0x21,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37, 0x11,0x21,0x15,0x21,0x11,0x33,0x32,0x16,0x16,0x01,0x11,0x21,0x11,0x05,0x21,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x35,0x05,0x94,0xdd,0xae,0x68,0x78,0xfe,0xc6,0xd0,0xd0,0x6e,0xce,0x83,0x8d,0x7d,0x03,0x58,0xfe,0xfd,0x39,0x72,0xc5,0x75,0xfd,0x73,0xfe,0xfb,0x01,0x05,0xfe,0xc8,0x61,0x6f,0x56,0x85,0x3b,0x79,0x79,0x01, 0xc0,0xc9,0xf5,0x02,0x95,0x92,0x89,0x01,0x04,0xd5,0xff,0xe0,0x88,0xe7,0x71,0x86,0xb7,0x13,0x02,0x01,0x94,0xfe,0xab,0x65,0xb8,0x01,0x1d,0x01,0x55,0xfe,0xab,0x94,0x72,0x62,0x49,0x9c,0x66,0xad,0xbe,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x05,0xf0,0x05,0x31,0x00,0x2e,0x00,0x3a,0x00,0x62,0xb4,0x23,0x89,0x0d,0x13,0x16,0xb8,0x01, 0x84,0x40,0x0f,0x2f,0x2a,0x89,0x04,0x00,0x0d,0x2f,0x04,0x04,0x2f,0x0d,0x00,0x04,0x3c,0x35,0xbe,0x01,0x84,0x00,0x1c,0x00,0x32,0x01,0x7e,0x00,0x13,0x00,0x38,0x01,0x7e,0x40,0x12,0x19,0x08,0x27,0x27,0x19,0x13,0x19,0x13,0x19,0x01,0x10,0x9b,0x20,0x06,0x2d,0x99,0x01,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11, 0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x21,0x21,0x22,0x26,0x35,0x34,0x3e,0x06,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x15,0x14,0x06,0x06,0x07,0x06,0x06,0x15, 0x14,0x16,0x33,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0xf0,0xfb,0xe3,0xc7,0xa3,0x45,0x70,0x90,0x96,0x90,0x70,0x45,0xb7,0x9b,0x4d,0x6f,0x33,0x84,0x7d,0x98,0x6d,0x69,0x8b,0x89,0xda,0x88,0xe2,0x01,0x16,0x83,0xf2,0xad,0x8d,0x70,0x56,0x82,0x04,0x04,0xfb,0xcf,0x46,0x2d,0x2f,0x44,0x43,0x30,0x2f, 0x44,0x60,0x6e,0x4a,0x61,0x42,0x2e,0x2d,0x36,0x52,0x7a,0x5a,0x90,0xa5,0x30,0x2f,0x04,0x80,0x7c,0x61,0x8a,0x97,0x6a,0x7d,0xe0,0x76,0xf2,0xc9,0x8a,0xd0,0x79,0x2e,0x25,0x3f,0x2c,0x2e,0x23,0x02,0xbf,0x31,0x47,0x48,0x30,0x33,0x45,0x45,0x00,0x01,0x00,0x8c,0x00,0x00,0x05,0xd1,0x05,0x31,0x00,0x20,0x00,0x51,0x40,0x2b,0x16,0x0c, 0x89,0x0d,0x1f,0x1c,0x89,0x05,0x14,0x00,0x05,0x0d,0x01,0x05,0x05,0x01,0x0d,0x03,0x22,0x10,0x89,0x11,0x02,0x1f,0x99,0x01,0x08,0x9b,0x16,0x01,0x19,0x19,0x12,0x01,0x18,0x15,0x0f,0x9b,0x12,0x06,0x0d,0x11,0x18,0x00,0x3f,0x33,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f, 0x2f,0x2f,0x11,0x39,0x39,0x10,0xed,0x32,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x35,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x15,0x23,0x11,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x21,0x05,0xd1,0xfd,0xf0,0x61,0x84,0x7b,0x6b,0x47,0x54,0x3d,0xa8,0xfe,0xf4,0xa8,0x02,0xce,0x72, 0x3e,0x64,0x45,0xa8,0xd7,0x45,0x38,0x01,0x00,0x95,0x0d,0xbe,0x7a,0x81,0x9b,0x1e,0x32,0xfd,0x5a,0x04,0x9d,0xfb,0x63,0x05,0x31,0x94,0xfe,0xb5,0x20,0x19,0xe8,0xaf,0x5e,0xbf,0x43,0x00,0x00,0x03,0x00,0x50,0x00,0x00,0x05,0xa3,0x05,0x31,0x00,0x14,0x00,0x18,0x00,0x24,0x00,0x50,0x40,0x2b,0x18,0x89,0x0c,0x11,0x02,0x89,0x24,0x15, 0x24,0x00,0x89,0x12,0x0c,0x24,0x0f,0x12,0x12,0x0f,0x24,0x0c,0x04,0x26,0x1e,0x89,0x09,0x01,0x1a,0x9b,0x11,0x0c,0x18,0x18,0x05,0x10,0x17,0x9b,0x13,0x0d,0x06,0x21,0x99,0x05,0x18,0x00,0x3f,0xed,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10, 0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x21,0x15,0x10,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x21,0x15,0x23,0x11,0x21,0x11,0x33,0x01,0x11,0x21,0x11,0x05,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x05,0xa3,0xfe,0x20,0xe0,0xda,0x7f,0xc8,0x72,0x92,0x7e,0x02,0xd0,0x6d,0x01,0x38,0xa8,0xfd,0x78,0xfe,0xed, 0x01,0x13,0xa9,0x95,0x9b,0x46,0x9c,0x86,0x79,0x84,0x02,0xb4,0x90,0xfe,0xf4,0xfe,0xe8,0x70,0xd5,0x92,0x81,0xb4,0x1f,0x02,0x06,0x94,0xfe,0xab,0x01,0xe9,0xfe,0x17,0x01,0x55,0xfe,0xab,0x94,0x28,0x5d,0x5c,0x93,0xab,0xe8,0xcc,0x00,0x01,0x00,0x8c,0xfd,0xb9,0x07,0x18,0x07,0x21,0x00,0x34,0x00,0x62,0x40,0x35,0x19,0x89,0x1a,0x1f, 0x15,0x89,0x16,0x24,0x8a,0x0f,0x34,0x8a,0x00,0x1d,0x16,0x0f,0x1a,0x16,0x0f,0x00,0x00,0x0f,0x16,0x1a,0x04,0x36,0x08,0x89,0x2c,0x1e,0x18,0x9b,0x1b,0x04,0x9b,0x30,0x1b,0x12,0x9b,0x1f,0x21,0x00,0x21,0x00,0x1a,0x1b,0x06,0x0c,0x99,0x28,0x16,0x1a,0x18,0x00,0x3f,0x33,0xd4,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x39,0xed,0x10,0xd4, 0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x02,0x02,0x24,0x23,0x22,0x04,0x02,0x11,0x10,0x12,0x04,0x33,0x20,0x00,0x11,0x34,0x26,0x23,0x22,0x07,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x21,0x15,0x23,0x11,0x36,0x33,0x32,0x16, 0x15,0x14,0x02,0x04,0x23,0x20,0x00,0x02,0x11,0x10,0x12,0x00,0x21,0x32,0x04,0x12,0x13,0x06,0x76,0x07,0xa4,0xfe,0xde,0xba,0xd3,0xfe,0xc7,0xad,0x9d,0x01,0x1e,0xc8,0x01,0x0b,0x01,0x2e,0x5d,0x4f,0x70,0x37,0xa8,0xee,0xa8,0x02,0xb0,0x72,0x53,0x55,0xa1,0xae,0xb5,0xfe,0xb2,0xd6,0xfe,0xff,0xfe,0x93,0xc3,0xd3,0x01,0x8c,0x01,0x10, 0xe3,0x01,0x63,0xcb,0x0c,0x03,0x1d,0x01,0x03,0x01,0x91,0xdc,0xf7,0xfe,0x22,0xfe,0xbc,0xfe,0xb2,0xfe,0x1c,0xf5,0x01,0x6b,0x01,0x4f,0x72,0x8c,0x51,0xfe,0x4c,0x04,0x9d,0xfb,0x63,0x05,0x31,0x94,0xfd,0xaa,0x51,0xe9,0xdd,0xed,0xfe,0x96,0xc2,0x01,0x18,0x02,0x22,0x01,0x81,0x01,0x71,0x02,0x22,0x01,0x1a,0xfe,0xfe,0x2c,0xfe,0xce, 0x00,0x03,0x00,0x50,0x00,0x00,0x07,0x45,0x05,0x31,0x00,0x2e,0x00,0x3a,0x00,0x3e,0x00,0x7a,0x40,0x44,0x3e,0x89,0x2d,0x03,0x23,0x89,0x3a,0x3b,0x3a,0x06,0x1d,0x89,0x1e,0x10,0x0d,0x89,0x17,0x2d,0x3a,0x1e,0x01,0x13,0x17,0x12,0x12,0x17,0x13,0x01,0x1e,0x3a,0x2d,0x07,0x40,0x34,0x89,0x2a,0x14,0x10,0x99,0x13,0x19,0x9b,0x06,0x13, 0x0a,0x0a,0x2e,0x13,0x18,0x22,0x30,0x9b,0x03,0x2d,0x3e,0x3e,0x26,0x02,0x3d,0x9b,0x2e,0x06,0x37,0x99,0x26,0x18,0x1e,0x18,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x32, 0x10,0xed,0x39,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x15,0x23,0x11,0x16,0x16,0x17,0x3e,0x02,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x33,0x15,0x21,0x35,0x36,0x36,0x35,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x27,0x15,0x10,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x01,0x23,0x22,0x06,0x06,0x15, 0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x11,0x21,0x11,0x04,0x30,0x6d,0x52,0x75,0x32,0x23,0x50,0x53,0x48,0x94,0xaf,0x3a,0x30,0xa2,0xfe,0xc3,0x28,0x33,0xa1,0x59,0x64,0xa8,0x49,0x51,0xe0,0xda,0x7f,0xc8,0x72,0x92,0x7e,0x01,0xbb,0xa9,0x95,0x9b,0x46,0x9c,0x86,0x79,0x84,0xfe,0xed,0x05,0x31,0x94,0xfe,0xa9,0x0a,0x43,0x40,0x42,0x4d, 0x23,0xd1,0xab,0x64,0xbb,0x3b,0x95,0x93,0x39,0xb3,0x58,0x01,0x00,0x9f,0x95,0xfe,0x5d,0x01,0x94,0x82,0x7e,0x18,0x88,0xfe,0xf4,0xfe,0xe8,0x70,0xd5,0x92,0x81,0xb4,0x1f,0x02,0x06,0xfd,0x83,0x28,0x5d,0x5c,0x93,0xab,0xe8,0xcc,0xff,0x01,0x55,0xfe,0xab,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x05,0x5f,0x05,0x31,0x00,0x1a,0x00,0x26, 0x00,0x41,0x40,0x23,0x0f,0x89,0x1b,0x02,0x89,0x03,0x1b,0x03,0x00,0x00,0x03,0x1b,0x03,0x28,0x09,0x21,0x89,0x15,0x1e,0x9b,0x09,0x0c,0x0c,0x12,0x01,0x05,0x9b,0x19,0x06,0x24,0x99,0x12,0x18,0x03,0x18,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x32,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10, 0xed,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x23,0x22,0x06,0x02,0x07,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x11,0x34,0x12,0x24,0x33,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x05,0x5f,0xab,0xa8,0xed,0x99,0xf7,0x90,0x08,0x2c,0x88,0x44,0x96,0xb7,0xbe,0x91,0xcb,0xd2,0xbd,0x01,0x47,0xc3, 0x02,0x48,0xfd,0x32,0x63,0x45,0x47,0x77,0x2a,0x0a,0x79,0x6b,0x44,0x5e,0x04,0x9d,0xfb,0x63,0x04,0x9d,0x8d,0xfe,0xfc,0xa8,0x2b,0x33,0xbf,0x9c,0x9e,0xc8,0x01,0x21,0x01,0x1e,0xd0,0x01,0x5e,0xc3,0xfc,0x27,0x54,0x82,0x3c,0x30,0x8d,0xa0,0x74,0x00,0x00,0x03,0x00,0x32,0xff,0x00,0x06,0xe6,0x05,0x31,0x00,0x2a,0x00,0x34,0x00,0x40, 0x00,0x78,0x40,0x2c,0x29,0x01,0x89,0x02,0x28,0x89,0x11,0x04,0x89,0x2b,0x14,0x17,0x89,0x35,0x3b,0x8a,0x1e,0x0f,0x11,0x2b,0x02,0x11,0x2b,0x35,0x1e,0x1e,0x35,0x2b,0x11,0x02,0x05,0x42,0x2f,0x89,0x0b,0x2a,0x06,0x04,0x2c,0x9b,0x0e,0x28,0x0e,0x3e,0xb8,0x01,0x80,0x40,0x13,0x1a,0x14,0x1a,0x22,0x0e,0x1a,0x0e,0x1a,0x07,0x38,0x9b, 0x22,0x06,0x32,0x99,0x07,0x19,0x02,0x18,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x3f,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x10,0xed,0x10,0xed,0x33,0x31,0x30,0x01,0x11,0x23,0x11,0x23,0x06, 0x00,0x21,0x22,0x24,0x26,0x35,0x34,0x36,0x33,0x21,0x36,0x35,0x34,0x02,0x27,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x07,0x33,0x11,0x01,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x24,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x06,0xe6,0xa8,0xfb,0x59, 0xfe,0x6c,0xfe,0xef,0x8d,0xfe,0xfd,0x83,0xba,0x9a,0x03,0x3c,0x07,0x80,0x78,0x25,0x1b,0xbf,0x92,0x5f,0x97,0x56,0x66,0xc1,0x84,0xb7,0x01,0x0d,0x92,0x06,0xcf,0xfe,0x58,0xfc,0xcb,0x36,0x43,0xd2,0xc5,0xaf,0x01,0x06,0xc9,0x67,0x44,0x44,0x66,0x60,0x4a,0x4b,0x60,0x05,0x31,0xf9,0xf9,0x01,0xdc,0xf9,0xfe,0xf3,0x6e,0xb8,0x75,0x74, 0x8c,0x60,0x31,0xb9,0x01,0x09,0x46,0x25,0x52,0x36,0xa2,0xc1,0x55,0x9f,0x70,0x6d,0xa9,0x5f,0xad,0xfe,0xb1,0xee,0x30,0x48,0x03,0x96,0xfb,0xd5,0x4b,0x35,0x74,0x7d,0xb6,0x03,0x30,0x53,0x7f,0x7d,0x55,0x52,0x6c,0x6e,0x00,0x04,0x00,0x50,0xff,0xe4,0x07,0x4d,0x05,0x31,0x00,0x30,0x00,0x3c,0x00,0x40,0x00,0x4c,0x00,0x91,0x40,0x50, 0x40,0x89,0x20,0x13,0x15,0x08,0x41,0x26,0x03,0x03,0x23,0x23,0x03,0x25,0x15,0x89,0x3c,0x3d,0x3c,0x44,0x8a,0x11,0x0b,0x8a,0x49,0x30,0x00,0x2d,0x8a,0x03,0x00,0x49,0x03,0x20,0x3c,0x11,0x49,0x03,0x03,0x49,0x11,0x3c,0x20,0x05,0x4e,0x36,0x89,0x1d,0x14,0x32,0x9b,0x25,0x20,0x40,0x40,0x19,0x23,0x3f,0x9b,0x21,0x06,0x9b,0x08,0x41, 0x29,0x29,0x0e,0x21,0x06,0x39,0x99,0x19,0x18,0x47,0x99,0x0e,0x18,0x00,0x30,0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x39,0x39,0xed,0x10,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33, 0x10,0xed,0x32,0x11,0x39,0x2f,0x12,0x17,0x39,0x12,0x39,0x10,0xed,0x31,0x30,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x23,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x21,0x15,0x23,0x11,0x33,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x07, 0x01,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x11,0x23,0x11,0x05,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x26,0x06,0x43,0x2d,0x3b,0x87,0x73,0x4d,0x42,0x69,0x78,0x88,0x79,0x80,0x9b,0x31,0x9b,0x4b,0xa2,0x87,0x7f,0xc8,0x72,0x72,0x6c,0x02,0xbc,0x6d,0xea,0x3f,0xa8,0x61,0x72,0xc0,0x6c,0x47,0x3d, 0xfc,0x0c,0x63,0x95,0x9b,0x46,0x9c,0x86,0x65,0x52,0xff,0x02,0xf9,0x25,0x20,0x44,0x30,0x62,0x2a,0x46,0x2c,0x43,0xff,0x70,0xca,0xca,0x47,0x35,0xdf,0x8e,0xb4,0xd5,0xe1,0xc0,0x8d,0x86,0x90,0xd0,0xe5,0x6f,0x70,0xd5,0x92,0x86,0xa4,0x2a,0x02,0x06,0x94,0xfe,0xab,0x57,0x65,0x83,0xeb,0x99,0xa0,0xfe,0xda,0x53,0x02,0xd0,0x28,0x5d, 0x5c,0x93,0xab,0xc1,0xf3,0xff,0x01,0x55,0xfe,0xab,0x98,0x33,0x7c,0x65,0x74,0x93,0xf1,0x47,0x80,0x5a,0x00,0x02,0x00,0x72,0xff,0xe5,0x05,0x5b,0x04,0xc9,0x00,0x0f,0x00,0x1f,0x00,0x23,0x40,0x0d,0x0c,0x8b,0x1c,0x1c,0x21,0x14,0x8b,0x04,0x10,0x9b,0x08,0x06,0x18,0xb8,0x01,0x80,0xb1,0x00,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f, 0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x03,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x02,0xe6,0xa6,0xfe,0xdc,0xaa,0xa9,0x01,0x25,0xa6,0xa8,0x01,0x24,0xa9,0xa9,0xfe,0xdb,0xa7,0x7f,0xda,0x80,0x7f,0xda,0x80,0x7f, 0xda,0x80,0x80,0xd9,0x1b,0xa6,0x01,0x21,0xab,0xa9,0x01,0x22,0xa7,0xa7,0xfe,0xdd,0xa8,0xa8,0xfe,0xdd,0xa7,0x04,0x5b,0x7f,0xdf,0x81,0x80,0xdd,0x7e,0x7d,0xdd,0x81,0x81,0xe0,0x7e,0x00,0x00,0x01,0x00,0x74,0xff,0xe6,0x06,0x74,0x04,0xc9,0x00,0x1b,0x00,0x3e,0xb4,0x07,0x06,0x15,0x16,0x12,0xb8,0x01,0x85,0x40,0x0a,0x18,0x06,0x16, 0x18,0x18,0x16,0x06,0x03,0x1d,0x04,0xb8,0x01,0x85,0x40,0x0b,0x0a,0x00,0x9b,0x0e,0x06,0x16,0x06,0x06,0x15,0x07,0x19,0x00,0x3f,0x33,0x33,0x11,0x33,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x22,0x04,0x06,0x15,0x10,0x05,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32, 0x04,0x12,0x15,0x14,0x02,0x07,0x27,0x24,0x11,0x34,0x26,0x24,0x03,0x74,0xaa,0xfe,0xe8,0xa0,0x01,0x32,0x62,0xaf,0xbf,0xc1,0x01,0x61,0xde,0xe0,0x01,0x60,0xc0,0xbf,0xb0,0x61,0x01,0x31,0xa0,0xfe,0xea,0x04,0x33,0x89,0xef,0x88,0xfe,0xef,0xc2,0x7a,0x6a,0x01,0x37,0xac,0xb7,0x01,0x32,0xad,0xaf,0xfe,0xcf,0xb6,0xac,0xfe,0xc8,0x69, 0x7a,0xc2,0x01,0x11,0x88,0xef,0x89,0x00,0x00,0x02,0x00,0x60,0x00,0x00,0x06,0x3d,0x04,0xdc,0x00,0x1e,0x00,0x2a,0x00,0x45,0xb9,0x00,0x19,0x01,0x85,0x40,0x12,0x05,0x08,0x0a,0x8b,0x1f,0x25,0x8b,0x11,0x05,0x1f,0x11,0x11,0x1f,0x05,0x03,0x2c,0x00,0x28,0xb8,0x01,0x80,0x40,0x0c,0x08,0x0e,0x0e,0x15,0x00,0x99,0x1e,0x18,0x22,0x9b, 0x15,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x37,0x21,0x32,0x36,0x36,0x35,0x34,0x26,0x27,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x21,0x01,0x34,0x26,0x27, 0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x60,0x03,0x61,0x87,0xe4,0x72,0xb2,0x8d,0x2c,0x4e,0x81,0x4b,0x72,0x9c,0x66,0xb0,0x5f,0x99,0x01,0x21,0xab,0x9b,0xfe,0xcd,0xae,0xfc,0x9f,0x03,0x91,0x31,0x2f,0x40,0x57,0x4b,0x32,0x33,0x47,0x97,0x7d,0xd7,0x8e,0x95,0xf7,0x31,0x44,0x45,0x42,0x81,0x4b,0x9f,0x73,0x55,0x88,0x4e,0xac,0xfe, 0xe0,0xa5,0xb1,0xfe,0xee,0xa8,0x03,0xb1,0x28,0x4e,0x1f,0x0b,0x57,0x33,0x33,0x47,0x47,0x00,0x00,0x01,0x00,0x58,0xff,0xe7,0x03,0xcf,0x04,0xc9,0x00,0x28,0x00,0x53,0x40,0x2c,0x23,0x8b,0x17,0x00,0x8b,0x0e,0x26,0x0e,0x12,0x17,0x0e,0x0e,0x17,0x12,0x03,0x2a,0x1c,0x1d,0x07,0x06,0x06,0x07,0x26,0x12,0x9b,0x13,0x1d,0x1c,0x07,0x13, 0x1c,0x1c,0x13,0x07,0x03,0x1f,0x0a,0x99,0x04,0x19,0x1a,0x9b,0x1f,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x39,0x11,0x33,0x01,0x2f,0x33,0xc6,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x06,0x23,0x22,0x27,0x37,0x16,0x16,0x33,0x32,0x36, 0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x03,0xcf,0x75,0xca,0x7b,0xd9,0xe4,0x5a,0x65,0xab,0x53,0x51,0x81,0x4b,0x96,0x77,0xb6,0xb6,0x77,0x83,0x98,0x7d,0x7f,0x95,0x5c,0xa8,0xe6,0x72,0xba,0x68,0x49,0x50,0x4e,0x5e,0x01,0x54, 0x60,0xab,0x62,0xc6,0x7b,0x5b,0x50,0x39,0x64,0x3a,0x60,0x74,0x8d,0x6b,0x58,0x50,0x6d,0x74,0x64,0xa4,0x58,0x9a,0x5a,0x5f,0x84,0x2d,0x2a,0x98,0x00,0x02,0x00,0x73,0xff,0xe8,0x05,0x9f,0x04,0xec,0x00,0x0b,0x00,0x32,0x00,0x66,0x40,0x36,0x16,0x8b,0x0f,0x13,0x12,0x1d,0x8b,0x03,0x08,0x8b,0x23,0x2a,0x2b,0x1a,0x12,0x25,0x03,0x23, 0x0f,0x12,0x03,0x23,0x2b,0x2b,0x23,0x03,0x12,0x0f,0x05,0x34,0x2e,0x8b,0x28,0x2b,0x2a,0x06,0x9b,0x0c,0x1a,0x26,0x0c,0x20,0x2a,0x0c,0x2a,0x0c,0x13,0x00,0x9a,0x20,0x19,0x12,0x13,0x06,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f, 0x2f,0x11,0x12,0x39,0x11,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x25,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x13,0x24,0x36,0x37,0x26,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x24,0x11,0x34,0x37,0x17,0x06,0x06, 0x15,0x14,0x16,0x16,0x17,0x02,0xfe,0x33,0x47,0x47,0x33,0x35,0x45,0x48,0x30,0x01,0x17,0xee,0x05,0x05,0x58,0x51,0x3e,0x7e,0x8b,0x6c,0xca,0xb8,0x27,0x39,0x9d,0x76,0x77,0x9b,0x37,0x27,0xfe,0x29,0x8a,0x5c,0x31,0x1d,0x5c,0xbf,0xb0,0x72,0x44,0x38,0x29,0x4d,0x0e,0x0f,0x4d,0x28,0x39,0x43,0x01,0xa6,0x3b,0xb0,0x7e,0x4f,0x77,0x31, 0x74,0x3c,0xc2,0x6d,0x74,0xaf,0x7d,0x33,0x1e,0x62,0x40,0x6f,0x97,0x98,0x6e,0x37,0x67,0x21,0x67,0x01,0x46,0xa9,0x71,0x66,0x2f,0x59,0x2c,0x4d,0x79,0x54,0x20,0x00,0x00,0x02,0x00,0x5d,0xff,0xc0,0x06,0x59,0x04,0xcd,0x00,0x33,0x00,0x3e,0x00,0x7f,0xb9,0x00,0x1a,0x01,0x84,0x40,0x0a,0x19,0x0a,0x8b,0x34,0x13,0x20,0x3a,0x8b,0x04, 0x00,0xb8,0x01,0x84,0x40,0x14,0x2c,0x02,0x0d,0x20,0x03,0x34,0x2c,0x04,0x2f,0x19,0x34,0x04,0x2f,0x2f,0x04,0x34,0x19,0x04,0x40,0x28,0xb8,0x01,0x84,0x40,0x0c,0x29,0x00,0x2c,0x28,0x2f,0x9b,0x30,0x06,0x29,0x28,0x19,0x3c,0xb8,0x01,0x81,0x40,0x0f,0x02,0x0d,0x25,0x19,0x25,0x19,0x07,0x16,0x99,0x1d,0x19,0x37,0x9b,0x07,0x06,0x00, 0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x39,0x39,0xed,0x3f,0x33,0x3f,0xed,0x12,0x39,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x17,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x1e,0x02,0x17, 0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x27,0x2e,0x03,0x23,0x22,0x00,0x03,0x27,0x36,0x12,0x37,0x26,0x26,0x27,0x37,0x1e,0x02,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x36,0x02,0xbd,0x38,0x3a,0x51,0xa3,0x85,0x80,0xa1,0x6e,0x69,0x30,0x3f,0x2b,0x17,0x0b,0x11,0x05,0x24,0x20,0x29,0x31, 0x0e,0x8b,0x13,0x83,0x63,0x5e,0x79,0x13,0x1d,0x2d,0x40,0x49,0x33,0xe0,0xfe,0xc2,0x66,0x8f,0x3d,0xf0,0xa3,0x2d,0xc1,0x7c,0x21,0x55,0xba,0x9b,0x02,0x01,0x57,0x37,0x38,0x53,0x5e,0x51,0x6a,0x02,0xc8,0x0f,0x06,0x59,0x6d,0x7f,0xa4,0x9e,0x75,0x5e,0x91,0x27,0x25,0x65,0x82,0x82,0x43,0x44,0x16,0x1f,0x5a,0x61,0x18,0x96,0xa0,0x7f, 0x79,0xb5,0x7a,0x4d,0x21,0xfe,0xd0,0xfe,0xc7,0x25,0xdd,0x01,0x4f,0x55,0x9a,0xe7,0x32,0x88,0x14,0x90,0xdb,0x5f,0x38,0x54,0x55,0x41,0x64,0x3f,0x07,0x62,0x00,0x01,0x00,0x73,0x00,0x00,0x05,0xa9,0x04,0xbe,0x00,0x1e,0x00,0x38,0x40,0x1d,0x02,0x00,0x0a,0x13,0x1a,0x1a,0x13,0x0a,0x03,0x20,0x0e,0x17,0x8a,0x04,0x00,0x02,0x14,0x9b, 0x11,0x11,0x08,0x19,0x99,0x1c,0x18,0x0b,0x9b,0x08,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0x33,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x31,0x30,0x13,0x34,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x14,0x21,0x21,0x15, 0x21,0x22,0x26,0x73,0xa7,0xa7,0x5c,0xa0,0x5f,0x97,0x7f,0x66,0x6a,0x97,0x7b,0x01,0xd2,0xfe,0x2e,0x7b,0x97,0x01,0x04,0x03,0x8f,0xfc,0x56,0xbc,0xd0,0x01,0x42,0xbd,0x6b,0x6b,0xbe,0x50,0x8c,0x4f,0x92,0x59,0x54,0x5a,0x6f,0x97,0x77,0x61,0xb0,0x97,0xa8,0x00,0x00,0x01,0x00,0x70,0xff,0xe5,0x04,0x44,0x04,0xc9,0x00,0x2e,0x00,0x54, 0xb3,0x04,0x8a,0x03,0x22,0xb8,0x01,0x85,0x40,0x0d,0x14,0x1a,0x8b,0x1b,0x03,0x14,0x1b,0x1b,0x14,0x03,0x03,0x30,0x2c,0xb8,0x01,0x85,0x40,0x11,0x0b,0x2c,0x07,0x03,0x14,0x1b,0x1e,0x03,0x1b,0x03,0x1b,0x07,0x17,0x9b,0x1e,0x06,0x00,0xb8,0x01,0x80,0xb1,0x07,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39, 0x11,0x12,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x25,0x32,0x36,0x37,0x33,0x06,0x04,0x23,0x22,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x0e,0x03,0x07,0x0e,0x02,0x15,0x14,0x16,0x02,0x56, 0x95,0xa1,0x16,0xa2,0x18,0xfe,0xff,0xd5,0x8b,0xdf,0x7c,0x2e,0x5c,0x9a,0x95,0x8b,0x6f,0x3b,0xa5,0x6e,0x75,0x97,0x0d,0x9b,0xf9,0xbb,0x7b,0xc6,0x72,0x24,0x3d,0x59,0x6f,0x81,0x94,0x71,0x3e,0xad,0x7d,0x7c,0x7b,0xbd,0xd2,0x56,0x9e,0x6b,0x49,0x71,0x54,0x42,0x22,0x20,0x32,0x44,0x32,0x4c,0x6a,0x74,0x68,0xa1,0xd0,0x59,0x9b,0x53, 0x40,0x5f,0x48,0x33,0x27,0x1e,0x21,0x35,0x4d,0x38,0x5f,0x6c,0x00,0x01,0x00,0x74,0xff,0xe7,0x06,0x8b,0x04,0xc9,0x00,0x20,0x00,0x42,0xb1,0x03,0x06,0xb8,0x01,0x85,0x40,0x0c,0x1d,0x12,0x20,0x1d,0x01,0x01,0x1d,0x20,0x12,0x04,0x22,0x15,0xb8,0x01,0x85,0xb5,0x0e,0x12,0x11,0x11,0x00,0x19,0xb8,0x01,0x81,0xb6,0x0a,0x19,0x20,0x03, 0x9b,0x00,0x06,0x00,0x3f,0xed,0x39,0x3f,0xed,0x12,0x39,0x2f,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x31,0x30,0x01,0x21,0x15,0x21,0x16,0x16,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34,0x36,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x02,0x27,0x03,0x21,0x03, 0x6a,0xfd,0xd4,0x7c,0x81,0xa4,0xfe,0xd4,0xa4,0xa4,0xfe,0xd3,0xa3,0x7c,0x6e,0x5b,0x4d,0x58,0x7c,0xdb,0x7d,0x7c,0xdc,0x7c,0xdb,0xc0,0x04,0xc9,0x8b,0x5d,0xfb,0x91,0xa9,0xfe,0xe8,0xad,0xad,0x01,0x19,0xa8,0x92,0xfb,0x5a,0x6e,0x40,0xc9,0x70,0x7d,0xd3,0x7b,0x7b,0xd4,0x7c,0xae,0x01,0x02,0x3b,0x00,0x00,0x01,0x00,0x73,0x00,0x00, 0x05,0xa9,0x04,0xbe,0x00,0x1e,0x00,0x38,0x40,0x1d,0x1d,0x1b,0x16,0x0e,0x04,0x04,0x0e,0x16,0x03,0x20,0x08,0x12,0x8a,0x00,0x1b,0x1d,0x0f,0x9b,0x0c,0x0c,0x03,0x14,0x99,0x17,0x18,0x06,0x9b,0x03,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0x33,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x31,0x30, 0x13,0x34,0x36,0x33,0x21,0x15,0x21,0x20,0x15,0x14,0x16,0x16,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x23,0x22,0x26,0x26,0x35,0x34,0x37,0x26,0x73,0xcf,0xbd,0x03,0xaa,0xfc,0x71,0xfe,0xfc,0x43,0x7a,0x55,0x01,0xd2,0xfe,0x2e,0x7b,0x97,0xd0,0x7f,0x97,0x60,0xa0,0x5b,0xa7,0xa7,0x03,0x7b,0x99,0xaa,0x98,0xb0,0x3c, 0x64,0x38,0x96,0x70,0x59,0xa8,0x97,0x50,0x8b,0x50,0xbd,0x6b,0x6b,0x00,0x00,0x02,0x00,0x82,0x00,0x00,0x05,0x05,0x04,0xac,0x00,0x0f,0x00,0x1f,0x00,0x23,0x40,0x0d,0x00,0x8a,0x10,0x10,0x21,0x18,0x8a,0x08,0x14,0x9b,0x0c,0x06,0x1c,0xb8,0x01,0x81,0xb1,0x04,0x18,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31, 0x30,0x01,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x07,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x05,0x05,0x9b,0xfe,0xf4,0x9b,0x9c,0xfe,0xf6,0x9b,0x9a,0x01,0x0d,0x9a,0x9a,0x01,0x0c,0x9c,0xa5,0x6c,0xc0,0x71,0x70,0xc1,0x6c,0x6e,0xbe,0x71,0x70,0xbf,0x6e, 0x02,0x55,0xa2,0xfe,0xea,0x9d,0x9f,0x01,0x14,0xa2,0xa1,0x01,0x16,0xa0,0xa0,0xfe,0xe9,0xa0,0x73,0xc9,0x76,0x76,0xca,0x72,0x74,0xc9,0x74,0x73,0xca,0x00,0x00,0x01,0x00,0x82,0xff,0xfd,0x05,0x1b,0x04,0xac,0x00,0x1d,0x00,0x37,0x40,0x1c,0x13,0x12,0x03,0x04,0x00,0x8a,0x07,0x12,0x04,0x07,0x07,0x04,0x12,0x03,0x1f,0x0f,0x8a,0x16, 0x0b,0x9b,0x1a,0x06,0x04,0x12,0x12,0x03,0x13,0x18,0x00,0x3f,0x33,0x33,0x11,0x33,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x14,0x02,0x07,0x27,0x36,0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04, 0x12,0x05,0x1b,0xc2,0x8b,0x4a,0x68,0x8a,0x75,0xc4,0x6f,0x70,0xc5,0x72,0x8e,0x63,0x49,0x8d,0xc0,0xa0,0x01,0x10,0x9c,0x9d,0x01,0x11,0x9f,0x02,0x55,0xb8,0xfe,0xa6,0x46,0x93,0x37,0x01,0x08,0x86,0x72,0xcb,0x75,0x77,0xc9,0x72,0x8b,0xfe,0xf9,0x34,0x92,0x47,0x01,0x59,0xb8,0xa0,0x01,0x18,0x9f,0xa1,0xfe,0xe8,0x00,0x01,0x00,0x64, 0x00,0x00,0x04,0x54,0x04,0xac,0x00,0x25,0x00,0x44,0x40,0x0f,0x17,0x18,0x00,0x8a,0x0b,0x18,0x0b,0x18,0x0b,0x27,0x12,0x89,0x05,0x1e,0x15,0xb8,0x01,0x81,0x40,0x0c,0x18,0x17,0x1a,0x17,0x1a,0x17,0x05,0x0f,0x9b,0x22,0x06,0x06,0xb8,0x01,0x81,0xb1,0x05,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xed,0x01, 0x2f,0xc4,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x14,0x02,0x04,0x23,0x21,0x35,0x21,0x32,0x37,0x24,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x04,0x54,0x9c,0xfe,0xef,0x9f,0xfe,0x5c,0x01,0xa4,0x3c,0x4d, 0x01,0x1e,0x73,0xc4,0x70,0x54,0x80,0x7d,0x57,0x5c,0x3f,0x75,0x62,0xae,0x64,0xb0,0x66,0x66,0xb0,0x64,0xa8,0x01,0x0d,0x97,0x02,0x55,0x9d,0xfe,0xea,0xa2,0xa4,0x1b,0x64,0x01,0x32,0x72,0xca,0x76,0x7c,0x59,0x55,0x7f,0x44,0x72,0x77,0x66,0xae,0x65,0x64,0xb1,0x65,0x9b,0xfe,0xec,0x00,0x02,0x00,0x82,0xff,0xdd,0x04,0xa3,0x04,0xac, 0x00,0x32,0x00,0x3c,0x00,0x7a,0x40,0x21,0x1e,0x1f,0x1f,0x13,0x1a,0x8a,0x25,0x2c,0x8a,0x13,0x03,0x11,0x35,0x03,0x25,0x2e,0x13,0x00,0x25,0x13,0x00,0x00,0x13,0x25,0x03,0x3e,0x3a,0x8a,0x0a,0x38,0x9b,0x0e,0x1c,0xb8,0x01,0x81,0x40,0x12,0x22,0x1f,0x1e,0x11,0x35,0x2e,0x03,0x04,0x06,0x0e,0x22,0x1e,0x1e,0x22,0x0e,0x03,0x28,0x33, 0xb8,0x01,0x81,0xb2,0x06,0x18,0x30,0xb8,0x01,0x81,0xb5,0x00,0x19,0x17,0x9b,0x28,0x06,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x17,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x17,0x39,0x10,0xed,0x10,0xed,0x11,0x39,0x2f,0x33,0x31,0x30, 0x05,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x32,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x07,0x16,0x33,0x32,0x37,0x05,0x32,0x37,0x26,0x26,0x23,0x22,0x15,0x14,0x16,0x04,0xa3,0x54, 0x6c,0x6b,0x58,0xb2,0x92,0x57,0xa4,0x5f,0x57,0x99,0x5d,0x73,0xee,0x48,0x3b,0x65,0xae,0x66,0x2d,0x3a,0x65,0x36,0x2f,0x56,0x20,0x6b,0x32,0x70,0x97,0x97,0x6a,0x8d,0xff,0x9c,0x70,0x46,0x38,0x0c,0x26,0xfd,0x55,0xc5,0x55,0x3c,0xad,0x51,0xa6,0x6d,0x23,0x33,0x61,0x45,0x2c,0x4e,0x81,0x46,0x53,0x7c,0x42,0x6f,0x55,0x53,0xbe,0x6e, 0xbd,0x69,0x30,0x27,0x58,0x41,0x68,0x35,0x47,0x8e,0x6d,0x66,0x96,0x9e,0xfe,0xf1,0x96,0xe1,0x9a,0x51,0x09,0x02,0x4f,0x43,0x4b,0x64,0x36,0x43,0x00,0x03,0x00,0x6e,0xff,0xf3,0x05,0x8a,0x04,0xc1,0x00,0x26,0x00,0x30,0x00,0x3c,0x00,0x72,0x40,0x39,0x37,0x8a,0x11,0x26,0x26,0x22,0x1b,0x8a,0x27,0x0b,0x8a,0x31,0x05,0x8a,0x22,0x2f, 0x15,0x11,0x13,0x1d,0x27,0x08,0x31,0x22,0x11,0x27,0x31,0x22,0x22,0x31,0x27,0x11,0x04,0x3e,0x2c,0x8b,0x15,0x26,0x9b,0x00,0x06,0x34,0x9b,0x13,0x08,0x0e,0x1d,0x2f,0x18,0x1f,0x1f,0x0e,0x29,0x9b,0x18,0x06,0x3a,0xb8,0x01,0x81,0xb1,0x0e,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0x12,0x39,0x39,0xed,0x3f,0xed, 0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x39,0x2f,0x10,0xed,0x31,0x30,0x01,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x24,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x36,0x36, 0x35,0x34,0x26,0x26,0x27,0x05,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xfe,0x51,0x90,0x6c,0x3f,0xca,0xb8,0x25,0x37,0xbb,0x8f,0x8d,0xbd,0x48,0xfe,0x56,0x92,0x69,0x67,0x95,0xc1,0x82,0xf3,0xf0,0xdd,0x3a,0x5e,0x74,0xfd,0xe6,0x33,0x24,0x25,0x3f,0x33,0x88, 0x02,0x00,0x60,0x46,0x45,0x61,0x5d,0x49,0x4b,0x5b,0x04,0xc1,0x0c,0x1f,0x44,0x78,0x64,0x87,0xce,0x46,0x23,0x63,0x38,0x88,0xa2,0xa7,0x83,0x6f,0x45,0x9b,0x01,0x45,0x69,0x92,0x95,0x67,0xa8,0x49,0x61,0x24,0x3f,0xa0,0x63,0x3a,0x42,0x1f,0x06,0x61,0x27,0x37,0x39,0x25,0x5c,0x3c,0x2d,0xfd,0xc2,0x39,0x51,0x4e,0x3c,0x35,0x45,0x45, 0x00,0x03,0x00,0x82,0xff,0xdc,0x05,0xd8,0x04,0xac,0x00,0x35,0x00,0x3e,0x00,0x47,0x00,0x99,0x40,0x4a,0x00,0x8b,0x36,0x04,0x8b,0x0b,0x3b,0x8b,0x30,0x22,0x21,0x21,0x1e,0x18,0x18,0x3f,0x08,0x08,0x0b,0x2c,0x0f,0x8a,0x3f,0x1e,0x8b,0x25,0x02,0x36,0x2e,0x0d,0x3d,0x03,0x0b,0x30,0x36,0x0b,0x30,0x3f,0x25,0x25,0x3f,0x30,0x0b,0x36, 0x05,0x49,0x42,0x8b,0x15,0x3f,0x0f,0x9b,0x18,0x3d,0x2e,0x33,0x02,0x0d,0x2c,0x2c,0x07,0x39,0x9b,0x33,0x06,0x21,0x22,0x22,0x12,0x1b,0x9b,0x28,0x06,0x45,0xb8,0x01,0x80,0xb2,0x12,0x18,0x08,0xb8,0x01,0x80,0xb1,0x07,0x19,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0x3f,0xed,0x12,0x39,0x2f,0x39,0x39,0x12,0x39,0x39, 0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x17,0x39,0x11,0x39,0x10,0xed,0x10,0xed,0x32,0x11,0x39,0x2f,0x11,0x33,0x11,0x12,0x39,0x2f,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x07,0x16,0x15,0x14,0x06,0x07,0x27,0x32,0x36,0x35,0x34,0x27,0x06,0x07,0x06,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x25,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x17,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x15,0x14,0x17,0x36,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0xd8,0xaa,0x74,0x89,0xaa,0x4b,0x62,0x7f,0x84,0x6b,0xf7,0x1b, 0xc7,0xa8,0x73,0xa0,0xea,0x01,0x1f,0x08,0x89,0x57,0x35,0x47,0x25,0x30,0x5a,0x3e,0x59,0xa3,0x76,0x68,0xae,0x67,0x06,0x7f,0x43,0x50,0xa5,0x7a,0x80,0xa0,0x9d,0x4e,0x35,0x83,0x72,0x94,0xfd,0x42,0xc5,0x99,0x49,0x2d,0x4d,0x7e,0x03,0x78,0xdd,0x63,0x78,0x8b,0x99,0x9a,0x26,0xa0,0x67,0x49,0x5c,0x6e,0x19,0x0f,0xe1,0xed,0x9e,0x73, 0xa2,0x9e,0x18,0xac,0xfa,0x4c,0x3c,0x1d,0x3a,0x27,0x82,0x20,0x93,0x4d,0x78,0xad,0x93,0xfe,0xfa,0xa0,0x08,0x0a,0x6a,0x89,0x84,0xb0,0xb0,0x73,0x38,0x4e,0x97,0x5c,0x69,0x3e,0xfe,0xd3,0x10,0x56,0x56,0x2b,0x42,0xa5,0x00,0x02,0x00,0x64,0x00,0x00,0x05,0x43,0x04,0xac,0x00,0x1d,0x00,0x28,0x00,0x64,0xb9,0x00,0x11,0x01,0x85,0x40, 0x12,0x1e,0x23,0x8b,0x17,0x0c,0x8b,0x07,0x00,0x1e,0x17,0x07,0x07,0x17,0x1e,0x00,0x04,0x2a,0x19,0xb8,0x01,0x85,0x40,0x09,0x09,0x05,0x17,0x23,0x23,0x21,0x9b,0x0e,0x26,0xb8,0x01,0x81,0x40,0x0d,0x0c,0x07,0x0e,0x14,0x14,0x01,0x0e,0x06,0x09,0x9b,0x0a,0x06,0x1c,0xb8,0x01,0x81,0xb1,0x01,0x18,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12, 0x39,0x2f,0x12,0x39,0x39,0xed,0x10,0xed,0x32,0x11,0x33,0x01,0x2f,0xc6,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x21,0x21,0x22,0x24,0x26,0x35,0x34,0x37,0x26,0x23,0x37,0x20,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x33,0x21,0x01,0x34,0x26,0x23, 0x22,0x07,0x16,0x16,0x33,0x32,0x36,0x05,0x43,0xfe,0x06,0xa4,0xfe,0xed,0x9d,0x9d,0x73,0xbb,0x0f,0x01,0x20,0x98,0x7c,0xa2,0x86,0xac,0xad,0x85,0x7e,0xa1,0x4c,0x4a,0xfc,0xb9,0x01,0xfa,0xfe,0x98,0x54,0x3e,0x7b,0x59,0x3a,0x59,0x41,0x3f,0x53,0x84,0xeb,0x8d,0xc7,0x7d,0xc7,0xa5,0xfe,0xe6,0x2b,0xa0,0x7a,0x7b,0xa7,0x85,0xa0,0x4a, 0x6c,0x93,0xb9,0x01,0xf5,0x36,0x49,0x1d,0x79,0x5c,0x40,0x00,0x00,0x01,0x00,0x6e,0x00,0x00,0x04,0x9e,0x04,0xc1,0x00,0x27,0x00,0x42,0x40,0x1a,0x11,0x8a,0x16,0x1c,0x8a,0x0b,0x16,0x0b,0x27,0x27,0x0b,0x16,0x03,0x29,0x23,0x8a,0x05,0x1e,0x09,0x13,0x09,0x01,0x14,0x14,0x19,0x26,0xb8,0x01,0x81,0xb5,0x01,0x18,0x0e,0x9b,0x19,0x06, 0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x21,0x21,0x22,0x26,0x26,0x35,0x34,0x37,0x36,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x06,0x07,0x06,0x15, 0x14,0x16,0x33,0x21,0x04,0x9e,0xfd,0x4d,0x66,0xb1,0x66,0x8d,0x27,0xd9,0x84,0x4b,0x3f,0x37,0x4a,0x1b,0x8e,0x31,0xab,0x7c,0x84,0xa8,0x8b,0x3e,0x84,0x3f,0x84,0x7c,0x5c,0x02,0xb3,0x62,0xab,0x64,0xb5,0x66,0x1e,0x61,0x3a,0x49,0x3f,0x50,0x45,0x2f,0x30,0x1c,0x52,0x41,0x62,0x74,0x9f,0xae,0x8d,0x9d,0x46,0x1f,0x34,0x1e,0x40,0x70, 0x5b,0x83,0x00,0x02,0x00,0x82,0x00,0x00,0x05,0x43,0x04,0xc1,0x00,0x26,0x00,0x31,0x00,0x59,0xb3,0x24,0x24,0x22,0x13,0xb8,0x01,0x84,0x40,0x24,0x27,0x01,0x04,0x8a,0x22,0x27,0x22,0x00,0x00,0x22,0x27,0x03,0x33,0x2d,0x1a,0x8a,0x0c,0x2f,0x99,0x16,0x24,0x01,0x9b,0x25,0x18,0x25,0x16,0x25,0x16,0x25,0x08,0x2a,0x9b,0x10,0x06,0x1e, 0xb8,0x01,0x81,0xb1,0x08,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x39,0x10,0xed,0x01,0x2f,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x10,0xed,0x11,0x39,0x2f,0x31,0x30,0x01,0x23,0x16,0x16,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x15,0x14, 0x06,0x23,0x22,0x27,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x10,0x27,0x35,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x33,0x32,0x36,0x05,0x43,0xd6,0x62,0x4d,0x9f,0xfe,0xf0,0x9d,0xa4,0xfe,0xf0,0x9a,0x5a,0x91,0x5d,0x64,0x90,0x90,0x64,0x5c,0x3f,0x08,0x70,0xc3,0x76,0x6e,0xc5,0x75,0xec,0x01,0xb7,0xfc,0xeb,0x3f, 0x25,0x2e,0x41,0x0b,0x3f,0x3b,0x2b,0x39,0x04,0x07,0x6a,0xc1,0x87,0x9f,0xfe,0xed,0xa3,0xa5,0x01,0x22,0xaf,0xa0,0x01,0x21,0x8a,0xa4,0x72,0x6f,0xa6,0x3c,0x23,0x40,0x80,0xd5,0x76,0x74,0xc6,0x70,0x01,0x15,0xa7,0xa1,0xff,0x00,0x29,0x49,0x58,0x53,0x4b,0x4f,0x00,0x02,0x00,0x82,0x00,0x00,0x04,0x44,0x04,0xac,0x00,0x26,0x00,0x31, 0x00,0x70,0x40,0x3c,0x17,0x18,0x0b,0x8b,0x31,0x10,0x89,0x1d,0x1f,0x06,0x2c,0x03,0x31,0x1d,0x00,0x18,0x31,0x1d,0x1d,0x31,0x18,0x00,0x04,0x33,0x04,0x8a,0x21,0x18,0x17,0x2f,0x99,0x0e,0x29,0x9b,0x08,0x06,0x2c,0x1f,0x10,0x04,0x0e,0x08,0xc0,0x0e,0xf0,0x0e,0x02,0x17,0x0e,0x08,0x08,0x0e,0x17,0x03,0x1a,0x01,0x9b,0x25,0x06,0x15, 0xb8,0x01,0x81,0xb1,0x1a,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x11,0x12,0x17,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x17,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x21,0x22,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x23,0x22,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x21,0x01,0x34,0x23,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x04,0x44,0xfd,0x93,0x48,0x68,0x35,0x73,0xa4,0x80,0x92,0x92,0x68,0x9c,0x74,0x08,0x7d,0x63,0x5c,0x37,0x74,0x6a,0x9d,0xab,0xdb,0x25,0x70,0x5b, 0x9e,0x5c,0x02,0x6d,0xfe,0xa4,0x5e,0x29,0x7f,0x17,0x20,0x6e,0x27,0x27,0x41,0x04,0x07,0x68,0x48,0x5e,0x32,0x63,0x6f,0x62,0x5d,0x7b,0x45,0x1b,0x16,0x6a,0x87,0x25,0x73,0x56,0xe3,0xb2,0x4e,0x53,0x7c,0xa5,0x5a,0x9f,0x5c,0xfd,0xa9,0x41,0x28,0x15,0x1a,0x2b,0x29,0x00,0x00,0x02,0x00,0x5d,0xff,0xe8,0x03,0xe9,0x03,0x7c,0x00,0x0b, 0x00,0x1b,0x00,0x23,0x40,0x0d,0x18,0x89,0x03,0x03,0x1d,0x09,0x89,0x10,0x06,0x9b,0x14,0x06,0x00,0xb8,0x01,0x80,0xb1,0x0c,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15, 0x14,0x06,0x06,0x02,0x23,0x7f,0xa0,0xa0,0x7f,0x7f,0xa0,0xa0,0x7f,0x7e,0xd0,0x78,0x78,0xd1,0x7d,0x7e,0xd0,0x78,0x78,0xd0,0x81,0xa9,0x88,0x88,0xa9,0xa9,0x88,0x88,0xa9,0x99,0x76,0xd3,0x81,0x81,0xd3,0x76,0x76,0xd3,0x81,0x81,0xd3,0x76,0x00,0x02,0x00,0x00,0xfe,0x63,0x06,0xd4,0x05,0xb3,0x00,0x18,0x00,0x21,0x00,0x37,0x40,0x1e, 0x21,0x8a,0x11,0x00,0x8a,0x19,0x11,0x09,0x19,0x19,0x09,0x11,0x03,0x23,0x04,0x89,0x0d,0x1d,0x9b,0x15,0x07,0x07,0x99,0x0a,0x18,0x21,0x10,0x99,0x01,0x18,0x00,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x21,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21, 0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x11,0x10,0x12,0x21,0x20,0x00,0x11,0x03,0x11,0x10,0x26,0x23,0x22,0x06,0x11,0x11,0x06,0xd4,0xfa,0x99,0x67,0x5f,0x60,0x66,0x01,0x55,0xfe,0xb6,0xc2,0xb6,0xc4,0xb4,0x01,0x57,0xff,0x01,0x03,0x01,0x02,0x01,0x01,0xa4,0xb1,0xae,0xb0,0xae,0x3f,0x46,0x4a,0x3b,0x93,0x86,0x90,0x8f,0x8b,0x02,0x9d, 0x01,0x44,0x01,0x3f,0xfe,0xc5,0xfe,0xb8,0xfd,0x63,0x02,0x8e,0x01,0x05,0xf4,0xf8,0xfe,0xff,0xfd,0x72,0x00,0x01,0x00,0x64,0xff,0xe6,0x07,0x12,0x05,0xb3,0x00,0x1e,0x00,0x3d,0x40,0x21,0x10,0x0f,0x1e,0x89,0x02,0x1b,0x89,0x06,0x0f,0x02,0x06,0x00,0x00,0x06,0x02,0x0f,0x04,0x20,0x0c,0x89,0x13,0x03,0x1e,0x99,0x02,0x18,0x09,0x9b, 0x17,0x07,0x0f,0x10,0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x33,0x31,0x30,0x25,0x15,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x07,0x07,0x12, 0xfc,0xd6,0x67,0x56,0xf8,0xd5,0xd5,0xf8,0x66,0x83,0x98,0x80,0x78,0xa4,0x01,0x27,0xb4,0xae,0x01,0x1c,0x9f,0x56,0x4a,0x93,0x93,0x62,0xa7,0x01,0x15,0x96,0x01,0x19,0x01,0x4d,0xfe,0xb2,0xfe,0xe8,0xae,0xfe,0xdd,0xc6,0x37,0xb9,0x01,0x64,0xbb,0xdc,0x01,0x5b,0xbe,0xbe,0xfe,0xa7,0xde,0x8d,0xfe,0xd6,0x74,0x00,0x00,0x01,0x00,0x64, 0xff,0xe6,0x07,0x1b,0x05,0xb3,0x00,0x2d,0x00,0x50,0x40,0x2b,0x19,0x18,0x22,0x0d,0x8a,0x0e,0x2d,0x2a,0x8a,0x06,0x01,0x06,0x18,0x0e,0x02,0x06,0x06,0x02,0x0e,0x18,0x04,0x2f,0x15,0x8a,0x1c,0x22,0x19,0x09,0x12,0x9b,0x26,0x1f,0x07,0x18,0x19,0x19,0x0e,0x18,0x03,0x2d,0x99,0x02,0x18,0x00,0x3f,0xed,0x39,0x3f,0x3f,0x33,0x3f,0x33, 0xed,0x32,0x12,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x39,0x10,0xed,0x32,0x10,0xed,0x39,0x11,0x33,0x31,0x30,0x25,0x15,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x10,0x12,0x33,0x32,0x16,0x17,0x33,0x36,0x36, 0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x07,0x07,0x1b,0xfd,0x59,0x53,0x52,0x6c,0x79,0x71,0x61,0xa4,0x61,0x71,0x7b,0x6a,0x66,0x5d,0x9b,0x5f,0x6c,0xc5,0xbe,0x6e,0x96,0x21,0x08,0x20,0x96,0x6f,0x76,0xad,0x60,0x4b,0x30,0x93,0x93,0x51,0x74,0x01,0x4b,0xf6,0x01,0x12,0x01,0x00,0xc7,0xeb,0xfc,0x9a,0x03,0x66,0xea,0xc8,0xfb,0xfe,0xe9, 0xf9,0xfe,0x87,0x77,0x37,0x7f,0x01,0xa8,0xe2,0x01,0x56,0x01,0x6e,0x74,0x6b,0x6a,0x75,0xa3,0xfe,0xc0,0xe1,0x99,0xfe,0x93,0x56,0x00,0x00,0x02,0x00,0x61,0xff,0xe6,0x06,0x81,0x07,0xc8,0x00,0x30,0x00,0x3c,0x00,0x6d,0x40,0x38,0x14,0x13,0x37,0x89,0x07,0x00,0x89,0x31,0x26,0x26,0x10,0x2b,0x89,0x20,0x1d,0x34,0x0a,0x03,0x07,0x31, 0x2e,0x20,0x13,0x07,0x31,0x20,0x20,0x31,0x07,0x13,0x04,0x3e,0x10,0x89,0x17,0x1d,0x2e,0x0a,0x34,0x04,0x04,0x26,0x25,0x25,0x1b,0x23,0x9b,0x28,0x0c,0x9b,0x1b,0x07,0x13,0x14,0x19,0x3a,0xb8,0x01,0x80,0xb1,0x04,0x19,0x00,0x3f,0xed,0x3f,0x33,0x3f,0xed,0xd4,0xed,0x12,0x39,0x2f,0x33,0x11,0x17,0x39,0x01,0x2f,0xed,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x2f,0x11,0x39,0x11,0x12,0x17,0x39,0x10,0xed,0x12,0x39,0x2f,0x10,0xed,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x14,0x02,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x37,0x26,0x23,0x22,0x04,0x02,0x15,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x12,0x07,0x34,0x26,0x27,0x06,0x02,0x15,0x14,0x16,0x33,0x32,0x12,0x06,0x31,0x79,0xd9,0x88,0xac,0xd5,0xd6,0xd3,0x80,0xaf,0xac,0xfe,0xf0,0x8c,0x6e,0x6e,0x95,0x71,0x7d,0xb3,0x01,0x60,0xde,0xfd,0xba,0x77,0x5b,0x79,0x7a,0x9b,0x9f,0x1d,0xac,0xbb,0xb2,0xd7,0x7f,0x94,0x5e,0x65,0xa7,0x55,0x4b, 0xbb,0xb2,0x7c,0x69,0x80,0xa8,0x02,0x8e,0xb7,0xfe,0xc0,0xb1,0x01,0x1c,0xdd,0xdb,0x01,0x6c,0x9e,0x54,0x9d,0xfe,0xec,0xb7,0xb6,0xfe,0xc4,0x9e,0x3a,0xa6,0x01,0x7d,0xaa,0xe3,0x01,0x57,0xc6,0x8c,0x5b,0x97,0x51,0x62,0x6e,0x3b,0x8a,0x3f,0xba,0x95,0x6f,0xcf,0x72,0x6b,0xfe,0xde,0xba,0x94,0xfc,0x55,0x8d,0xfe,0xc6,0xc1,0xa3,0xbe, 0x01,0x24,0x00,0x01,0x00,0x61,0xfd,0xfe,0x07,0x0f,0x07,0x61,0x00,0x43,0x00,0x71,0x40,0x38,0x1f,0x8a,0x24,0x22,0x21,0x2a,0x8a,0x19,0x30,0x8a,0x11,0x00,0x01,0x41,0x8a,0x03,0x2c,0x11,0x01,0x24,0x21,0x14,0x19,0x11,0x01,0x03,0x03,0x01,0x11,0x19,0x14,0x21,0x24,0x07,0x45,0x0a,0x8a,0x39,0x01,0x00,0x19,0x06,0x9b,0x3d,0x27,0x2c, 0x14,0x9b,0x15,0x15,0x22,0x1c,0x9b,0x27,0x07,0x0e,0xb8,0x01,0x80,0xb3,0x34,0x21,0x22,0x19,0x00,0x3f,0x33,0xd4,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x10,0xd4,0xed,0x3f,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x31, 0x30,0x05,0x27,0x12,0x11,0x10,0x00,0x21,0x22,0x00,0x02,0x11,0x10,0x12,0x04,0x33,0x32,0x12,0x35,0x10,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x11,0x10,0x13,0x07,0x02,0x11,0x10,0x00,0x33,0x32,0x16,0x15,0x10,0x07,0x15,0x16,0x16,0x15,0x14,0x02,0x06,0x23,0x22,0x24,0x02,0x02,0x35,0x10,0x12,0x00,0x21,0x32, 0x04,0x12,0x11,0x14,0x02,0x06,0x7d,0x9e,0x8b,0xfe,0xaf,0xfe,0xd1,0xd4,0xfe,0xa5,0xb6,0x9c,0x01,0x0e,0xb4,0xbf,0xd4,0xf8,0x72,0x65,0x63,0x6d,0x73,0x7a,0xa8,0xa0,0x8b,0x99,0x96,0x01,0x03,0xed,0xb9,0xd3,0xae,0x67,0x7d,0x96,0xff,0xa8,0xa9,0xfe,0xea,0xc9,0x74,0xde,0x01,0xaa,0x01,0x0a,0xef,0x01,0x6b,0xc2,0x4c,0x19,0x37,0x01, 0x9f,0x01,0x92,0x01,0xa6,0x01,0xd3,0xfe,0xfe,0xfe,0x32,0xfe,0xcd,0xfe,0xd1,0xfe,0x00,0xff,0x01,0x24,0xfd,0x01,0x7d,0x96,0x9b,0x85,0xa2,0x8d,0xfe,0xe7,0xfe,0xbd,0xfe,0xb1,0xfe,0xae,0x37,0x01,0x75,0x01,0x5f,0x01,0x69,0x01,0x90,0xf0,0xca,0xfe,0xf8,0x67,0x06,0x1e,0xfc,0xb4,0xc0,0xfe,0xb0,0xa8,0xb1,0x01,0x4d,0x01,0xd0,0xe9, 0x01,0x60,0x02,0x19,0x01,0x33,0xfd,0xfe,0x2f,0xfe,0xc6,0xd7,0xfe,0x31,0x00,0x01,0x00,0x64,0xfd,0xfe,0x06,0xf4,0x05,0xb3,0x00,0x3e,0x00,0x6a,0x40,0x0b,0x00,0x3e,0x0a,0x33,0x8a,0x34,0x11,0x2a,0x8a,0x2b,0x17,0xb8,0x01,0x85,0x40,0x24,0x23,0x3e,0x34,0x1d,0x2b,0x23,0x23,0x2b,0x1d,0x34,0x3e,0x05,0x40,0x3c,0x8a,0x03,0x12,0x0b, 0x0b,0x34,0x2f,0x26,0x38,0x9b,0x15,0x0e,0x07,0x07,0x3e,0x00,0x19,0x1d,0x1e,0x1e,0x34,0x20,0xb8,0x01,0x80,0xb3,0x1b,0x2b,0x34,0x18,0x00,0x3f,0x33,0xd4,0xed,0x12,0x39,0x2f,0x33,0x3f,0x33,0x3f,0x33,0x33,0xed,0x32,0x32,0x12,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x10, 0xed,0x39,0x11,0x33,0x31,0x30,0x17,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x20,0x11,0x10,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x12,0x11,0x10,0x02,0x23,0x22,0x06,0x11,0x11,0x23,0x11,0x10,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x26,0x23,0x22, 0x06,0x02,0x15,0x10,0x17,0xee,0x41,0x49,0x51,0x92,0x64,0x56,0x7e,0x2a,0x05,0x24,0x86,0x5a,0x5b,0x6f,0x31,0x06,0x26,0x7f,0x60,0x01,0x3c,0x7f,0xe3,0x99,0x8c,0x6f,0x7e,0x77,0xb3,0xad,0x59,0x4e,0x5e,0x51,0xa3,0x4e,0x5b,0x63,0x54,0xa3,0x49,0x55,0x32,0x52,0x2f,0x7d,0x1a,0x85,0x01,0x91,0xdc,0xe8,0x01,0x4b,0xa8,0x56,0x6b,0x5f, 0x62,0x52,0x73,0x64,0x61,0xfc,0xcf,0xfe,0xaa,0xfd,0xe8,0xfe,0xea,0x2d,0xac,0x40,0x01,0xe2,0x01,0xf7,0x01,0x51,0x01,0x57,0xda,0xfe,0xfe,0xfc,0xc4,0x03,0x3c,0x01,0x05,0xd7,0xe9,0xf1,0xfc,0xc2,0x03,0x3e,0x01,0x0b,0xcf,0x8b,0xfe,0xf9,0xb5,0xfe,0x46,0xfa,0x00,0x02,0x00,0x46,0xff,0xe6,0x05,0x17,0x05,0xb3,0x00,0x0b,0x00,0x30, 0x00,0x47,0x40,0x1d,0x2a,0x89,0x13,0x17,0x1b,0x89,0x00,0x13,0x00,0x30,0x30,0x00,0x13,0x03,0x32,0x06,0x8a,0x22,0x09,0x99,0x30,0x0c,0x18,0x1f,0x0c,0x1f,0x0c,0x26,0x0f,0xb8,0x01,0x80,0xb5,0x2e,0x19,0x03,0x9b,0x26,0x07,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x39,0x11,0x33,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f, 0x2f,0x2f,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x16,0x04,0x33,0x32,0x36,0x12,0x35,0x34,0x02,0x26,0x27,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x20,0x27,0x02,0x8f,0x6e,0x5e,0x5e,0x7a, 0x6e,0x5d,0x63,0x76,0xfd,0xb9,0x68,0x01,0x05,0x92,0xa8,0xfd,0x84,0x86,0xe3,0x82,0x03,0x55,0x62,0x62,0xb1,0x6f,0xa9,0xc8,0x86,0xed,0x9a,0xcb,0x01,0x41,0xb8,0xb6,0xfe,0xb1,0xcb,0xfe,0xbf,0xbe,0x04,0x1e,0x69,0x80,0x82,0x64,0x66,0x7c,0x78,0xfd,0x84,0x5c,0x60,0x95,0x01,0x0f,0xb0,0x9f,0x01,0x12,0xa3,0x07,0x08,0x1c,0x9b,0x60, 0x65,0xa5,0x5d,0xc6,0xa3,0x7f,0xbd,0x66,0xb4,0xfe,0xa9,0xd3,0xdc,0xfe,0xab,0xbe,0x94,0x00,0x00,0x01,0x00,0x64,0xfd,0xfe,0x06,0xea,0x05,0xb3,0x00,0x2d,0x00,0x57,0x40,0x2a,0x2c,0x01,0x8a,0x0e,0x28,0x89,0x13,0x1d,0x1c,0x0e,0x13,0x0f,0x07,0x1c,0x1c,0x07,0x0f,0x13,0x0e,0x05,0x2f,0x19,0x89,0x20,0x2d,0x06,0x16,0x9b,0x24,0x07, 0x1c,0x1d,0x19,0x10,0x2b,0x99,0x0f,0x07,0x08,0x08,0x0f,0x0b,0xb8,0x01,0x80,0xb2,0x04,0x0f,0x18,0x00,0x3f,0xd4,0xed,0x12,0x39,0x11,0x33,0x10,0xed,0x39,0x3f,0x33,0x3f,0xed,0x3f,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x10,0xed,0x33,0x31,0x30,0x01,0x11,0x10,0x00,0x21,0x22,0x26,0x27,0x35, 0x17,0x16,0x33,0x32,0x36,0x35,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x07,0x21,0x11,0x06,0xea,0xfe,0xcd,0xfe,0xe6,0x46,0x76,0x55,0x4a,0x69,0x70,0xbb,0xdc,0xfd,0xa2,0x67,0x56,0xf8,0xd5,0xd5,0xf8,0x66,0x83,0x98,0x80,0x78, 0xa4,0x01,0x27,0xb4,0xae,0x01,0x1c,0x9f,0x56,0x4a,0x01,0x9a,0x05,0x99,0xfa,0xb4,0xfe,0xe3,0xfe,0xce,0x13,0x14,0xac,0x18,0x22,0xc6,0xa3,0x62,0xa7,0x01,0x15,0x96,0x01,0x19,0x01,0x4d,0xfe,0xb2,0xfe,0xe8,0xae,0xfe,0xdd,0xc6,0x37,0xb9,0x01,0x64,0xbb,0xdc,0x01,0x5b,0xbe,0xbe,0xfe,0xa7,0xde,0x8d,0xfe,0xd6,0x74,0x05,0x06,0x00, 0x00,0x02,0x00,0x61,0xff,0xe6,0x07,0x02,0x07,0xc8,0x00,0x3f,0x00,0x4a,0x00,0x84,0x40,0x45,0x1b,0x1a,0x26,0x10,0x8a,0x11,0x46,0x8a,0x07,0x00,0x8a,0x40,0x35,0x35,0x17,0x3a,0x8a,0x2e,0x2b,0x43,0x0a,0x03,0x07,0x40,0x3d,0x2e,0x1a,0x11,0x07,0x40,0x2e,0x2e,0x40,0x07,0x11,0x1a,0x05,0x4c,0x17,0x8a,0x1e,0x0c,0x14,0x9b,0x22,0x2b, 0x26,0x43,0x0a,0x3d,0x26,0x04,0x04,0x35,0x34,0x34,0x22,0x31,0x9b,0x37,0x29,0x22,0x07,0x1a,0x1b,0x19,0x11,0x18,0x48,0xb8,0x01,0x80,0xb1,0x04,0x19,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x3f,0x33,0xd4,0xed,0x12,0x39,0x2f,0x33,0x11,0x17,0x39,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x39, 0x11,0x12,0x17,0x39,0x10,0xed,0x12,0x39,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x39,0x11,0x33,0x31,0x30,0x01,0x14,0x02,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x37,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x17, 0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x12,0x07,0x34,0x26,0x27,0x06,0x02,0x15,0x10,0x33,0x32,0x12,0x06,0xc2,0x64,0xac,0x6c,0x88,0xad,0xb0,0xad,0x57,0x59,0x88,0x91,0xa2,0xea,0x8c,0x88,0x65,0x58,0x9a,0x5c,0x6b,0x6e,0xc5,0x81,0x75,0xab,0x20,0x07,0x2b,0xc0,0x7d,0x90, 0x85,0x3d,0x49,0x60,0x63,0x3b,0x64,0x3f,0x17,0x89,0x97,0x8e,0xad,0x67,0x75,0x48,0x54,0xa4,0x2b,0x30,0x8f,0x7f,0x9a,0x61,0x6e,0x02,0x8e,0xbb,0xfe,0xc2,0xaf,0x01,0x18,0xe1,0xdd,0x01,0x6f,0xa0,0x4f,0xf6,0xe6,0xfc,0xc2,0x03,0x3e,0x01,0xdc,0xfe,0xe3,0xfe,0xd4,0xb4,0xfe,0x8c,0x8c,0x37,0x98,0x01,0x9f,0xbb,0xe4,0x01,0x4a,0xad, 0x90,0x81,0x83,0x8e,0x87,0x3a,0xa8,0x5c,0x63,0x6d,0x1d,0x1e,0x8a,0x3f,0xb8,0x97,0x6f,0xd0,0x70,0x6d,0xfe,0xdd,0xb8,0xb7,0xd9,0x4b,0x84,0xfe,0xd5,0xcf,0xfe,0x9f,0x01,0x13,0x00,0x02,0x00,0x82,0xff,0xf4,0x05,0x2b,0x03,0xf1,0x00,0x0b,0x00,0x1b,0x00,0x20,0x40,0x10,0x18,0x89,0x03,0x03,0x1d,0x09,0x89,0x10,0x06,0x9b,0x14,0x06, 0x00,0x99,0x0c,0x18,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x22,0x24,0x26,0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x14,0x06,0x04,0x02,0xd5,0xc7,0xdf,0xdf,0xc7,0xc5,0xdd,0xdd,0xc5,0xaa,0xfe,0xee,0x97,0x95,0x01,0x13,0xab, 0xae,0x01,0x14,0x94,0x97,0xfe,0xee,0x87,0xc2,0xa9,0xab,0xc1,0xc3,0xa9,0xa9,0xc2,0x93,0x7f,0xe9,0x96,0x97,0xea,0x7e,0x7f,0xe9,0x97,0x96,0xe8,0x80,0x00,0x00,0x02,0x00,0x82,0xff,0xf4,0x05,0xa3,0x03,0xf1,0x00,0x2b,0x00,0x37,0x00,0x5f,0xbc,0x00,0x2c,0x01,0x82,0x00,0x00,0x00,0x06,0x01,0x82,0x40,0x18,0x32,0x14,0x89,0x1b,0x28, 0x32,0x00,0x32,0x17,0x1b,0x1b,0x17,0x32,0x00,0x04,0x39,0x22,0x89,0x0c,0x18,0x99,0x17,0x18,0x2f,0xb8,0x01,0x7d,0x40,0x11,0x28,0x35,0x9b,0x03,0x28,0x03,0x28,0x03,0x09,0x1f,0x9b,0x10,0x06,0x26,0x99,0x09,0x18,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f, 0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x14,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x04,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x27,0x26,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35, 0x34,0x26,0x23,0x22,0x06,0x02,0x28,0x74,0x5a,0x5d,0x77,0xe8,0xc2,0xb7,0xe7,0xa0,0x01,0x2c,0xc4,0xbf,0x01,0x2c,0xa6,0xcb,0xc2,0x6d,0x6f,0x7a,0xdc,0x8a,0xd9,0xfe,0xf9,0x3f,0x73,0x43,0x82,0x41,0x03,0x55,0x6a,0x6c,0x3a,0x2a,0x27,0x3a,0x39,0x28,0x2b,0x39,0x01,0xb7,0x58,0x78,0x7b,0x63,0xc5,0xf0,0x01,0x05,0xd6,0x9f,0xf9,0x8a, 0x88,0xfa,0x9d,0xc0,0xf6,0x27,0x95,0x1d,0xa8,0x83,0x74,0xb5,0x63,0xd9,0xb6,0x62,0x91,0x51,0x58,0x06,0x06,0x72,0x58,0x29,0x39,0x37,0x2b,0x29,0x39,0x39,0x00,0x02,0x00,0xb4,0x00,0x00,0x05,0x90,0x05,0xe6,0x00,0x3e,0x00,0x4a,0x00,0x71,0xb9,0x00,0x2d,0x01,0x83,0x40,0x2f,0x00,0x42,0x8c,0x30,0x39,0x8c,0x48,0x27,0x26,0x06,0x0e, 0x89,0x1f,0x06,0x48,0x1f,0x00,0x30,0x48,0x1f,0x1f,0x48,0x30,0x00,0x04,0x4c,0x18,0x89,0x15,0x16,0x06,0x45,0x3f,0x30,0x3c,0x36,0x06,0x27,0x3c,0x36,0x27,0x27,0x36,0x3c,0x03,0x03,0x1b,0xb8,0x01,0x80,0xb7,0x12,0x18,0x23,0x2a,0x9b,0x0a,0x03,0x06,0x00,0x3f,0x33,0xed,0x32,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x39,0x11, 0x12,0x39,0x33,0x32,0x3f,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x11, 0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x25,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x22,0x76,0x72,0x41,0x5d,0x15,0x07,0x0d,0x6e,0x4a,0x7e,0x89,0xb7,0xa0,0xfd,0xd2,0xa1,0xb6,0xad,0x66,0x5b, 0x02,0x00,0x5b,0x64,0x36,0x33,0x2e,0x3f,0x03,0x91,0x02,0x3e,0x2d,0x31,0x31,0x27,0x1e,0x05,0x04,0x55,0x44,0x44,0x57,0x64,0x5d,0x96,0xa9,0x01,0x67,0x1f,0x2e,0x2d,0x20,0x1e,0x2d,0x2e,0x02,0x98,0xb3,0xa9,0x48,0x45,0x3f,0x4e,0xaf,0x99,0xfe,0x9e,0x9b,0xaf,0xb0,0x9a,0x04,0x9c,0xfb,0x6f,0x5b,0x60,0x60,0x5b,0x01,0x5e,0x55,0x5a, 0x4c,0x3e,0x3e,0x4c,0x58,0x72,0x4f,0x73,0x10,0x05,0x05,0x18,0x42,0x58,0x59,0x41,0x4f,0x56,0xb1,0x3e,0x2b,0x20,0x20,0x2a,0x2a,0x20,0x20,0x2b,0x00,0x02,0x00,0x82,0xff,0xf4,0x05,0x73,0x03,0xf3,0x00,0x2d,0x00,0x39,0x00,0x71,0xbc,0x00,0x31,0x01,0x82,0x00,0x25,0x00,0x2b,0x01,0x82,0x40,0x30,0x37,0x1c,0x1b,0x09,0x0f,0x89,0x15, 0x09,0x37,0x12,0x25,0x37,0x12,0x15,0x15,0x12,0x37,0x25,0x04,0x3b,0x22,0x89,0x03,0x13,0x99,0x12,0x18,0x18,0x1f,0x9b,0x06,0x2e,0x9b,0x25,0x00,0x28,0x09,0x1c,0x06,0x28,0x1c,0x28,0x1c,0x00,0x0c,0x06,0x06,0x34,0xb8,0x01,0x7d,0xb1,0x00,0x18,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0xed, 0x10,0xed,0x32,0x3f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x22,0x02,0x35,0x34,0x12,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x12,0x15,0x14,0x02,0x07,0x35,0x36,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15, 0x14,0x17,0x37,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x2f,0xc3,0xea,0xc8,0xa4,0x5f,0x8d,0x24,0x1e,0x91,0x63,0xa2,0xc1,0xc4,0xa5,0xb8,0x78,0x58,0x4e,0x53,0xab,0x58,0x4f,0x56,0x77,0x37,0x07,0x06,0x6f,0x58,0x5b,0x76,0x7a,0x55,0x29,0x39,0x39,0x29,0x2a,0x37, 0x38,0x0c,0x01,0x1d,0xeb,0xdf,0x01,0x18,0x72,0x74,0x6b,0x7b,0xfe,0xea,0xdf,0xce,0xfe,0xe9,0x24,0x96,0x3c,0x01,0x37,0x92,0xd0,0x9c,0x91,0x91,0x9c,0xce,0x96,0xb0,0x74,0x02,0x54,0x68,0x74,0x58,0x5d,0x79,0x01,0x38,0x02,0x39,0x29,0x2a,0x38,0x38,0x2a,0x28,0x3c,0x00,0x00,0x02,0x00,0x82,0xff,0xed,0x05,0x4b,0x05,0x82,0x00,0x3b, 0x00,0x47,0x00,0x84,0xb9,0x00,0x06,0x01,0x82,0xb4,0x3f,0x28,0x89,0x27,0x45,0xbb,0x01,0x82,0x00,0x0c,0x00,0x0e,0x01,0x83,0x40,0x16,0x00,0x39,0x0c,0x00,0x14,0x3f,0x27,0x0c,0x00,0x00,0x0c,0x27,0x3f,0x14,0x05,0x49,0x32,0x89,0x1e,0x17,0x11,0x3c,0xb8,0x01,0x7d,0x40,0x1a,0x09,0x42,0x9b,0x03,0x22,0x2d,0x11,0x1b,0x0c,0x09,0x2d, 0x03,0x27,0x09,0x03,0x09,0x03,0x1b,0x27,0x06,0x39,0x35,0x99,0x1b,0x18,0x13,0xb8,0x01,0x80,0xb1,0x14,0x19,0x00,0x3f,0xed,0x3f,0xed,0x32,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed, 0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x17,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x24,0x37,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37, 0x26,0x26,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0xcb,0xb7,0x96,0x70,0x81,0x78,0x58,0x56,0x71,0x08,0x1f,0x9b,0x81,0x8c,0x58,0x39,0xb1,0x54,0x41,0xab,0xa5,0x33,0xda,0xed,0x93,0x01,0x20,0xf9,0xaf,0xa5,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c,0x98,0x81,0x29,0x75,0x3c,0x38,0x39,0x57,0x01,0x6f, 0x27,0x3b,0x38,0x2a,0x27,0x3b,0x3c,0x01,0xae,0x89,0xa6,0x74,0x62,0x5a,0x74,0x6a,0x59,0x23,0x38,0x5e,0x7b,0x10,0x0e,0x23,0x9a,0x19,0x24,0x18,0x16,0xeb,0xcc,0xa3,0xef,0xa4,0x3b,0x28,0x77,0x57,0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71,0x93,0x5f,0x85,0xa0,0x13,0x0b,0x05,0x1e,0x8e,0x45,0x39,0x2b,0x29,0x3a,0x39,0x2a, 0x2a,0x3a,0x00,0x03,0x00,0x82,0xff,0xed,0x05,0x4b,0x05,0x82,0x00,0x43,0x00,0x4f,0x00,0x5b,0x00,0xaa,0xbf,0x00,0x29,0x01,0x83,0x00,0x1b,0x00,0x4d,0x01,0x82,0x00,0x27,0x00,0x21,0x01,0x82,0x40,0x12,0x47,0x18,0x27,0x1b,0x27,0x47,0x2f,0x2f,0x47,0x27,0x1b,0x04,0x11,0x5d,0x07,0x89,0x06,0x00,0xb8,0x01,0x82,0x40,0x18,0x56,0x50, 0x8c,0x3e,0x3c,0x56,0x3e,0x06,0x56,0x3e,0x3e,0x56,0x06,0x03,0x5d,0x11,0x89,0x39,0x0c,0x01,0x4b,0x9b,0x1e,0x44,0xb8,0x01,0x7d,0x40,0x1a,0x24,0x32,0x2c,0x3c,0x53,0x01,0x03,0x41,0x27,0x1e,0x2c,0x24,0x1e,0x24,0x1e,0x24,0x36,0x59,0x41,0x06,0x18,0x14,0x99,0x36,0x18,0x2e,0xb8,0x01,0x80,0xb3,0x2f,0x19,0x06,0x06,0x00,0x3f,0x3f, 0xed,0x3f,0xed,0x32,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x12,0x39,0x11,0x17,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x07, 0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x17,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16, 0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0x5d,0x08,0x9e,0x8f,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c,0x98,0x81,0x29,0x75,0x3c,0x38,0x39,0x57,0xb7,0x96,0x70,0x81,0x78,0x58,0x56,0x71,0x08,0x1f,0x9b,0x81,0x8c,0x58,0x39,0xb1,0x54,0x41, 0xab,0xa5,0x33,0xda,0xed,0xb0,0xc5,0x3d,0x74,0x59,0x64,0x72,0xdd,0x27,0x3b,0x38,0x2a,0x27,0x3b,0x3c,0xfe,0x0f,0x3c,0x28,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x04,0x3d,0x10,0x29,0x72,0x52,0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71,0x93,0x5f,0x85,0xa0,0x13,0x0b,0x05,0x1e,0x8e,0x4f,0x89,0xa6,0x74,0x62,0x5a,0x74,0x6a,0x59, 0x23,0x38,0x5e,0x7b,0x10,0x0e,0x23,0x9a,0x19,0x24,0x18,0x16,0xeb,0xcc,0xb9,0x01,0x03,0x58,0x3c,0x5c,0x5a,0x75,0x81,0xfc,0xf7,0x39,0x2b,0x29,0x3a,0x39,0x2a,0x2a,0x3a,0x02,0xbc,0x28,0x3b,0x3c,0x27,0x29,0x3b,0x3b,0x00,0x02,0x00,0x50,0xff,0xf4,0x04,0xa7,0x05,0x6a,0x00,0x28,0x00,0x34,0x00,0x63,0x40,0x09,0x18,0x89,0x05,0x25, 0x8c,0x2f,0x12,0x0b,0x29,0xb8,0x01,0x83,0x40,0x14,0x1f,0x00,0x0b,0x2f,0x1f,0x05,0x2f,0x1f,0x1f,0x2f,0x05,0x03,0x36,0x0f,0x89,0x0e,0x32,0x9b,0x22,0x2c,0xb8,0x01,0x7d,0x40,0x12,0x00,0x12,0x0b,0x22,0x00,0x22,0x00,0x15,0x02,0x99,0x1c,0x18,0x08,0x9b,0x15,0x06,0x0e,0x06,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f, 0x39,0x39,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x25,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x26,0x02,0x27,0x33,0x16,0x16,0x17,0x36,0x36,0x33,0x32,0x04,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0xb5,0x47,0x8b,0xa9,0xc6,0xae,0x9b,0x47,0xa9,0x46,0x30,0xae,0x49,0xd5,0x2c,0x49,0x25,0x30,0x91,0x3b,0xe7,0x01,0x05,0x7e,0xeb,0x98,0xca,0xfe,0xfa,0x7a,0x6a,0x58,0x75,0x75,0x5b,0x60,0x3b,0x28,0x28,0x3b,0x3b,0x28,0x2a,0x39,0xb9, 0x34,0xc2,0xb1,0xa2,0xb0,0x26,0x1f,0xa1,0x01,0x70,0x54,0x44,0xd5,0xa6,0x16,0x1a,0xfc,0xe7,0x98,0xec,0x80,0xd7,0xaa,0x6d,0x7c,0x74,0x5c,0x57,0x76,0xce,0x2a,0x39,0x3c,0x27,0x29,0x3b,0x3a,0x00,0x00,0x02,0x00,0x82,0xff,0xf4,0x06,0x80,0x05,0xe6,0x00,0x3b,0x00,0x47,0x00,0x7b,0x40,0x0c,0x17,0x89,0x14,0x26,0x25,0x06,0x06,0x2c, 0x0d,0x89,0x1e,0x35,0xb8,0x01,0x82,0x40,0x21,0x45,0x3f,0x8c,0x2f,0x1c,0x1e,0x45,0x14,0x1e,0x45,0x2f,0x2f,0x45,0x1e,0x14,0x04,0x49,0x2c,0x89,0x00,0x3c,0x9b,0x2e,0x38,0x32,0x06,0x26,0x32,0x26,0x32,0x26,0x03,0x42,0xb8,0x01,0x7d,0xb2,0x38,0x18,0x10,0xb8,0x01,0x80,0x40,0x0a,0x1c,0x18,0x15,0x06,0x21,0x29,0x9b,0x0a,0x03,0x06, 0x00,0x3f,0x33,0xed,0x32,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x12,0x39,0x11,0x33,0x33,0x10,0xed,0x31,0x30,0x13,0x34,0x12,0x33,0x32,0x16,0x17,0x3e,0x02,0x33,0x32,0x12,0x15,0x14,0x06, 0x07,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x06,0x23,0x21,0x36,0x11,0x34,0x26,0x23,0x22,0x06,0x06,0x15,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x37,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x05,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x82,0xac,0xa3,0x53,0x8a,0x23,0x0d,0x48, 0x66,0x36,0xa0,0xac,0x25,0x15,0x46,0x56,0x62,0xae,0x58,0xa4,0x66,0xfe,0xe2,0x5d,0x52,0x4d,0x2d,0x49,0x29,0xa7,0x01,0x53,0x47,0x51,0x58,0x37,0x07,0x06,0x70,0x58,0x5c,0x74,0x7b,0x64,0x80,0xc5,0x6a,0x01,0xbf,0x2a,0x3a,0x3a,0x2a,0x29,0x39,0x3a,0x01,0xfc,0xf8,0x01,0x00,0x75,0x66,0x37,0x65,0x3f,0xfe,0xfe,0xf4,0x64,0xce,0x31, 0x5f,0x5b,0x04,0x91,0xfb,0x64,0x5d,0x97,0x56,0xc8,0x01,0x36,0xa7,0xbd,0x45,0x8c,0x64,0x9f,0x96,0xb8,0xae,0xbb,0x69,0x02,0x57,0x65,0x75,0x57,0x5f,0x77,0x82,0xec,0x36,0x02,0x39,0x29,0x2a,0x38,0x3b,0x27,0x27,0x3d,0x00,0x02,0x00,0x82,0xff,0xf6,0x05,0x9c,0x05,0x82,0x00,0x40,0x00,0x4c,0x00,0x7e,0xb9,0x00,0x0b,0x01,0x82,0x40, 0x1b,0x47,0x27,0x89,0x26,0x41,0x8c,0x05,0x1a,0x33,0x00,0x47,0x26,0x33,0x05,0x1d,0x47,0x26,0x05,0x05,0x26,0x47,0x03,0x4e,0x31,0x89,0x1d,0x44,0xb8,0x01,0x7d,0x40,0x1a,0x02,0x15,0x9b,0x36,0x4a,0x9b,0x08,0x21,0x2c,0x00,0x02,0x36,0x2c,0x08,0x26,0x02,0x36,0x08,0x08,0x36,0x02,0x03,0x0e,0x26,0x06,0x33,0xb8,0x01,0x81,0xb5,0x1a, 0x18,0x3d,0x99,0x0e,0x18,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36, 0x33,0x32,0x16,0x15,0x14,0x02,0x23,0x22,0x26,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x06,0x07,0x07,0x26,0x26,0x35,0x34,0x36,0x24,0x37,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26, 0x23,0x22,0x06,0x04,0xfc,0x16,0x1b,0x57,0x78,0x77,0x56,0x5c,0x77,0x9e,0x80,0x2f,0x57,0x56,0x45,0x3e,0x3e,0x1b,0x1e,0x25,0x18,0x10,0x02,0xda,0xfd,0x93,0x01,0x20,0xf9,0xaf,0xa5,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c,0xb4,0x16,0x6f,0x5d,0x26,0x49,0x49,0x52,0x46,0x4b,0x1c,0x2e,0x49,0x0d,0x9a,0x3b,0x29,0x27,0x3b,0x3a, 0x28,0x27,0x3d,0x01,0x18,0x05,0x76,0x59,0x5a,0x75,0x7c,0x65,0xd1,0xfe,0xf7,0x27,0x46,0x4d,0x44,0x2e,0x33,0x57,0x84,0x1b,0x02,0xf1,0xc7,0xa3,0xef,0xa4,0x3b,0x28,0x77,0x57,0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71,0x93,0x5f,0xca,0x39,0x8b,0x7f,0x22,0x39,0x54,0x4c,0x34,0x49,0x3d,0xd0,0x29,0x3b,0x39,0x2b,0x29,0x39, 0x3a,0x00,0x00,0x02,0x00,0x82,0xff,0xf4,0x06,0x1b,0x04,0xfe,0x00,0x37,0x00,0x43,0x00,0x7a,0x40,0x0a,0x06,0x20,0x2a,0x13,0x89,0x12,0x21,0x89,0x22,0x32,0xbb,0x01,0x82,0x00,0x41,0x00,0x3b,0x01,0x82,0x40,0x19,0x2c,0x12,0x22,0x41,0x2c,0x2c,0x41,0x22,0x12,0x04,0x45,0x2a,0x89,0x00,0x38,0x9b,0x06,0x20,0x03,0x2c,0x35,0x2f,0x2f, 0x03,0x3e,0xb8,0x01,0x7d,0x40,0x15,0x35,0x18,0x1d,0x9b,0x09,0x17,0x9b,0x0f,0x09,0x0f,0x09,0x0f,0x12,0x22,0x18,0x12,0x06,0x26,0x9b,0x03,0x06,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x39,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10, 0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x12,0x39,0x39,0x31,0x30,0x13,0x34,0x12,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x02,0x06,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x01,0x23,0x03,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14, 0x06,0x23,0x22,0x02,0x25,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x82,0xd9,0xc5,0x57,0x9d,0x2b,0x1e,0x51,0x38,0x1a,0x3f,0x4b,0x35,0x37,0x15,0x31,0x37,0xa8,0x54,0x79,0x43,0x23,0x55,0x51,0x1d,0x2e,0x11,0x1d,0x2d,0x0b,0x01,0x13,0xc1,0xe5,0x3e,0x6d,0x3f,0x4a,0x67,0x31,0x3c,0x08,0x6f,0x58,0x5b,0x76,0x7a,0x65, 0xc7,0xe6,0x01,0xbd,0x2a,0x39,0x3a,0x29,0x2a,0x37,0x38,0x01,0xdb,0xfa,0x01,0x1c,0x6a,0x57,0x94,0x7a,0x26,0x48,0x35,0x26,0xe1,0xa8,0x88,0xfe,0xe5,0x8f,0x32,0x51,0x1d,0x28,0x88,0x7f,0xfd,0x73,0x02,0x46,0xa1,0x7a,0x63,0xb5,0x6a,0x9d,0x76,0x5c,0x6e,0x74,0x58,0x5d,0x79,0x01,0x06,0x32,0x02,0x3b,0x27,0x2a,0x38,0x38,0x2a,0x28, 0x3c,0x00,0x00,0x02,0x00,0x78,0xff,0xf2,0x05,0x3f,0x04,0xa3,0x00,0x0f,0x00,0x1e,0x00,0x20,0x40,0x10,0x04,0x89,0x13,0x13,0x20,0x1b,0x89,0x0c,0x00,0x99,0x17,0x06,0x10,0x99,0x08,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34, 0x12,0x24,0x13,0x32,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x02,0xe2,0xaa,0x01,0x18,0x9b,0x9e,0xfe,0xe6,0xaf,0xa9,0xfe,0xe7,0x9e,0xa0,0x01,0x1e,0xa2,0xcb,0xf2,0x6d,0xc7,0x7f,0x82,0xcd,0x71,0x71,0xc9,0x04,0xa3,0x9a,0xfe,0xed,0xad,0xad,0xfe,0xec,0x96,0x9c,0x01,0x14,0xa7,0xa9,0x01,0x15,0x9c,0xfb, 0xe5,0xf9,0xc8,0x80,0xd0,0x74,0x76,0xd0,0x80,0x7d,0xcf,0x73,0x00,0x02,0x00,0x78,0xff,0xf7,0x05,0x3b,0x04,0xa3,0x00,0x2a,0x00,0x36,0x00,0x61,0xb5,0x29,0x89,0x04,0x00,0x01,0x19,0xbb,0x01,0x82,0x00,0x2e,0x00,0x33,0x01,0x82,0x40,0x12,0x13,0x11,0x2e,0x13,0x04,0x01,0x2e,0x13,0x13,0x2e,0x01,0x04,0x04,0x38,0x0c,0x89,0x21,0x0f, 0xb8,0x01,0x7f,0x40,0x11,0x2b,0x11,0x31,0x11,0x16,0x1d,0x16,0x1d,0x16,0x00,0x25,0x99,0x08,0x06,0x01,0x00,0x18,0x00,0x3f,0x32,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x32,0x11,0x33,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x05,0x27,0x36, 0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x10,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0xf3,0x75,0x80,0x94,0x70,0xc9,0x81,0x85,0xc7,0x6e,0x85, 0x6e,0x2d,0x15,0x38,0x69,0x48,0x48,0x6b,0x5b,0xa4,0x6f,0x75,0xbc,0x68,0xa0,0x01,0x11,0xaf,0xa5,0x01,0x15,0xa9,0xfd,0x93,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x09,0x70,0x69,0x01,0x19,0x97,0x65,0xb9,0x6f,0x6a,0xbc,0x71,0x9a,0xb4,0x0b,0x34,0x4d,0x4b,0x69,0x6b,0x49,0x4e,0x81,0x49,0x73,0xd6,0x8e,0x97,0x01,0x07,0x92,0x8e,0xfe, 0xfa,0x8f,0xfe,0x90,0x65,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x02,0x00,0x78,0xff,0xf2,0x04,0x52,0x06,0x66,0x00,0x25,0x00,0x31,0x00,0x5a,0xbf,0x00,0x2f,0x01,0x82,0x00,0x03,0x00,0x17,0x01,0x84,0x00,0x16,0x00,0x09,0x01,0x82,0x40,0x22,0x29,0x00,0x16,0x29,0x03,0x16,0x29,0x29,0x16,0x03,0x03,0x33,0x20,0x89,0x11, 0x13,0x1b,0x2c,0x06,0x31,0x00,0x1b,0x16,0x00,0x06,0x06,0x0d,0x17,0x16,0x07,0x24,0x99,0x0d,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x39,0x12,0x39,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x25,0x26,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x10,0x01,0x36,0x12,0x37,0x17,0x0e,0x02,0x07,0x0e,0x03,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x39,0x26,0x26,0x65,0x4b,0x50,0x65,0x6c,0xc8,0x7e,0xa2,0xfb,0x8b,0x01,0x82,0x94,0xca,0x3a,0x92,0x2e,0x5c,0x75,0x8d,0x69, 0x8f,0x57,0x27,0x69,0xba,0x6a,0x61,0x90,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0xa1,0x26,0x3e,0x2d,0x50,0x62,0x68,0x4a,0x58,0x93,0x55,0x7f,0xe8,0x93,0x01,0x2b,0x01,0x35,0x77,0x01,0x06,0x9d,0x36,0x7b,0xa7,0x89,0x77,0x5a,0x91,0x7b,0x71,0x51,0x5c,0xa0,0x62,0x6b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x03,0x00,0x50, 0xff,0xf2,0x05,0x71,0x06,0xac,0x00,0x45,0x00,0x50,0x00,0x5c,0x00,0x88,0x40,0x23,0x4e,0x89,0x27,0x54,0x22,0x07,0x89,0x3f,0x24,0x46,0x16,0x2f,0x04,0x27,0x2d,0x89,0x48,0x0f,0x89,0x35,0x22,0x3f,0x27,0x3f,0x48,0x35,0x45,0x45,0x35,0x48,0x3f,0x27,0x05,0x5e,0x5a,0xb8,0x01,0x82,0x40,0x1e,0x1c,0x0a,0x3b,0x45,0x3b,0x00,0x00,0x2a, 0x04,0x9b,0x42,0x2a,0x57,0x9b,0x24,0x2f,0x22,0x16,0x04,0x19,0x46,0x2a,0x1f,0x1f,0x19,0x4c,0x9b,0x2a,0x06,0x51,0xb8,0x01,0x7d,0xb5,0x19,0x19,0x32,0x99,0x13,0x19,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x17,0x39,0xed,0x10,0xd4,0xed,0x12,0x39,0x2f,0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x11,0x17,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x01,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x02,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x37,0x26,0x02,0x35,0x34,0x36,0x33,0x32,0x16, 0x15,0x14,0x07,0x16,0x16,0x33,0x32,0x12,0x35,0x34,0x2e,0x03,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x04,0x17,0x01,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x90,0xec,0x71,0x4f,0x26,0x1d,0x2a,0x44,0x67,0xe9,0xc2,0x6f,0x35,0x64,0xb5,0x71,0x62,0xcb, 0x6a,0x47,0x9f,0x69,0x49,0x68,0x69,0x48,0x36,0x57,0x16,0x27,0x1c,0x54,0x7a,0x7f,0x62,0x76,0x86,0x56,0x5d,0xa3,0x39,0x6d,0x81,0x1f,0x3c,0x59,0x73,0xb3,0x78,0x6a,0x3e,0x8b,0x66,0x56,0x01,0x2a,0x96,0xfd,0x51,0x27,0x2e,0x24,0x17,0x20,0x39,0xf9,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x05,0x66,0x71,0x2d,0x12,0x2d,0x1e,0x1d,0x2e, 0x28,0x59,0x74,0x93,0xcf,0x8f,0xc0,0xfe,0xc6,0xae,0x81,0x6f,0x78,0x78,0x69,0x49,0x4b,0x69,0x3b,0x30,0x32,0x4c,0x74,0x01,0x4f,0x72,0x72,0x97,0xd8,0xd4,0x9c,0xe5,0x73,0x81,0x01,0x1d,0xfc,0x65,0x92,0x6c,0x4c,0x3c,0x40,0x2b,0x43,0x57,0x3a,0x5f,0x82,0x68,0x53,0xfc,0x2e,0x69,0x77,0x81,0x93,0x39,0x3e,0x4c,0xe4,0xfd,0xf9,0x27, 0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x03,0x00,0x78,0xff,0xf2,0x05,0x25,0x06,0x3d,0x00,0x3d,0x00,0x47,0x00,0x53,0x00,0x8b,0xbc,0x00,0x0d,0x01,0x84,0x00,0x43,0x00,0x3b,0x01,0x82,0x40,0x44,0x4b,0x25,0x89,0x22,0x51,0x03,0x03,0x3e,0x08,0x03,0x43,0x06,0x8a,0x34,0x13,0x32,0x22,0x34,0x43,0x4b,0x22,0x34,0x34,0x22,0x4b, 0x43,0x04,0x55,0x2d,0x89,0x19,0x46,0x0a,0x53,0x00,0x4d,0x38,0x1d,0x29,0x08,0x32,0x3e,0x13,0x04,0x10,0x0a,0x03,0x00,0x29,0x38,0x23,0x0a,0x00,0x38,0x38,0x00,0x0a,0x03,0x10,0x23,0x06,0x30,0x99,0x15,0x19,0x40,0x10,0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x11,0x12,0x17,0x39, 0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x17,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34, 0x36,0x36,0x37,0x24,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x05,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x42,0x32,0x64,0x16,0x2b,0x3a,0x19,0x74, 0x65,0x73,0x8f,0x86,0x6d,0x50,0x7a,0x5a,0xe5,0x6f,0x80,0x85,0x3d,0x5c,0xbc,0xa9,0x01,0x42,0x85,0x4b,0x1e,0xa8,0xb4,0xcc,0xfe,0xf4,0x87,0x98,0x44,0x4c,0x4a,0x41,0xc6,0x32,0x7a,0xcb,0x70,0x48,0x6b,0x6c,0xf8,0x5d,0x42,0x26,0x3e,0x42,0x2f,0x3d,0x5e,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x02,0x0e,0x4c,0x3a,0x16,0x70,0x42,0x4f, 0x34,0x3c,0x70,0x56,0x5d,0x70,0x34,0x55,0x89,0x73,0xfa,0xd7,0xa5,0xe0,0x8c,0x2c,0x54,0x2f,0x34,0x41,0x2f,0xa3,0xb0,0x86,0xa0,0x34,0x45,0x23,0x6d,0xa7,0xa2,0xb9,0xd4,0x75,0x5e,0x74,0x71,0xc4,0x70,0x6b,0x49,0x49,0x69,0xfe,0xb6,0x50,0x2c,0x1f,0x20,0x27,0x01,0x7b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x04,0x00,0x78, 0xff,0xf2,0x05,0x25,0x06,0x3d,0x00,0x47,0x00,0x51,0x00,0x5c,0x00,0x68,0x00,0xba,0xb9,0x00,0x59,0x01,0x82,0xb6,0x3a,0x38,0x03,0x42,0x03,0x3a,0x40,0xb8,0x01,0x82,0x40,0x13,0x54,0x00,0x8a,0x45,0x3a,0x54,0x45,0x45,0x54,0x3a,0x03,0x33,0x6a,0x20,0x8a,0x10,0x66,0x1d,0x17,0xbb,0x01,0x82,0x00,0x60,0x00,0x27,0x01,0x84,0x40,0x41, 0x4d,0x1d,0x48,0x22,0x2d,0x0e,0x05,0x60,0x10,0x60,0x4d,0x4d,0x60,0x10,0x03,0x6a,0x09,0x89,0x33,0x50,0x24,0x68,0x1a,0x62,0x14,0x06,0x38,0x03,0x42,0x56,0x3d,0x22,0x0e,0x48,0x2d,0x04,0x2a,0x24,0x1d,0x1a,0x42,0x52,0x38,0x03,0x14,0x3d,0x24,0x1a,0x14,0x3d,0x3d,0x14,0x1a,0x24,0x04,0x2a,0x47,0x06,0x0c,0x99,0x2f,0x19,0x4a,0x2a, 0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x17,0x39,0x11,0x39,0x11,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x17,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10, 0xed,0x10,0xed,0x11,0x17,0x39,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x06,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36, 0x36,0x25,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36,0x36,0x35,0x35,0x33,0x01,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x03,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x05,0x12,0xd0,0xa8,0x23,0x72,0x80,0xc7,0x9c,0x4c,0x4a,0x41,0xc6, 0x32,0x7a,0xcb,0x70,0x48,0x6b,0x6c,0x47,0x32,0x64,0x16,0x2b,0x3a,0x19,0x74,0x65,0x73,0x8f,0x86,0x6d,0x50,0x7a,0x5a,0xe5,0x6f,0x80,0x85,0x3d,0x68,0xe7,0x01,0x20,0x0f,0x4c,0x66,0x4d,0x4a,0x67,0x0b,0x2b,0x3f,0xa5,0xfe,0x7f,0x5d,0x42,0x26,0x3e,0x42,0x2f,0x3d,0x7d,0x35,0x2a,0x17,0x1c,0x25,0x31,0xf7,0x1a,0x27,0x27,0x1a,0x1a, 0x26,0x26,0x05,0xd5,0x99,0xbe,0x23,0x3c,0x31,0x4a,0xd9,0xb6,0xb9,0xd4,0x75,0x5e,0x74,0x71,0xc4,0x70,0x6b,0x49,0x49,0x69,0x4c,0x3a,0x16,0x70,0x42,0x4f,0x34,0x3c,0x70,0x56,0x5d,0x70,0x34,0x55,0x89,0x73,0xfa,0xd7,0xa6,0xc8,0x9e,0x6b,0x08,0x35,0x5c,0x49,0x6b,0x71,0x47,0x18,0x1d,0x1c,0x6b,0x4b,0x5e,0xfa,0x87,0x50,0x2c,0x1f, 0x20,0x27,0x03,0xf6,0x21,0x29,0x1c,0x29,0x27,0x1e,0x18,0x30,0xfd,0x83,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x03,0x00,0x78,0xff,0xf2,0x06,0x58,0x06,0xac,0x00,0x4d,0x00,0x58,0x00,0x64,0x00,0xad,0x40,0x0c,0x2a,0x29,0x38,0x89,0x1c,0x0c,0x3e,0x4e,0x16,0x04,0x0e,0x14,0xb8,0x01,0x84,0xb4,0x51,0x31,0x89,0x24,0x57,0xbb, 0x01,0x84,0x00,0x0e,0x00,0x4b,0x01,0x82,0x40,0x26,0x5c,0x62,0x03,0x03,0x5c,0x44,0x29,0x1c,0x51,0x24,0x0e,0x5c,0x5c,0x0e,0x24,0x51,0x1c,0x29,0x06,0x66,0x06,0x89,0x44,0x21,0x34,0x29,0x34,0x2a,0x2a,0x5f,0x2e,0x9b,0x27,0x5f,0x54,0x9b,0x11,0x59,0xb8,0x01,0x7d,0x40,0x11,0x00,0x4e,0x16,0x0c,0x3e,0x04,0x40,0x11,0x03,0x00,0x5f, 0x11,0x00,0x11,0x00,0x40,0x48,0xb8,0x01,0x7d,0xb7,0x5f,0x06,0x18,0x0a,0x99,0x3c,0x40,0x19,0x00,0x3f,0x33,0xed,0x32,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x17,0x39,0x10,0xed,0x10,0xed,0x10,0xd4,0xed,0x12,0x39,0x2f,0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11, 0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x17,0x39,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x05,0x07,0x27, 0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x32,0x36,0x57,0x15,0x2e,0x40, 0x54,0x94,0x54,0x5b,0x40,0x63,0x79,0x5a,0x5b,0x6f,0x5d,0x39,0x62,0x50,0x93,0x59,0x35,0x74,0xd1,0xa0,0x70,0x6f,0x92,0x5d,0xa7,0x01,0x70,0x46,0x8f,0xa7,0x5a,0x3f,0x1d,0x28,0x48,0x5f,0xfb,0xed,0x69,0x84,0xe1,0x82,0x9d,0x6d,0x71,0x98,0x87,0xe1,0x7e,0x76,0xcc,0x78,0x48,0x6b,0x6c,0xf0,0x14,0x25,0x21,0x1a,0x1a,0x25,0xf4,0x1a, 0x27,0x27,0x1a,0x1a,0x26,0x26,0x03,0x50,0x3b,0x30,0x43,0xe3,0x6e,0x71,0xc0,0x6e,0x37,0x6f,0x87,0x62,0x7f,0x7f,0x62,0x87,0x6d,0x39,0x88,0xe6,0x80,0xa4,0xa7,0x7b,0x70,0x38,0x27,0x7e,0x4e,0x58,0x7d,0xbb,0x8b,0x43,0x4f,0x1e,0x2e,0x1d,0x20,0x2f,0x24,0x5d,0xb8,0xfe,0xfe,0xcb,0xaf,0xfe,0xd5,0xaa,0x6a,0x6a,0x94,0x01,0x04,0x9f, 0xa1,0x01,0x3a,0xb2,0x6b,0x49,0x49,0x69,0xfd,0xd9,0x14,0x57,0x17,0x2f,0x35,0x32,0x2a,0x4b,0x02,0x5b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x03,0x00,0x64,0xfd,0xeb,0x05,0x98,0x04,0xa5,0x00,0x2d,0x00,0x37,0x00,0x43,0x00,0x85,0xb3,0x3b,0x1e,0x21,0x40,0xb8,0x01,0x82,0xb2,0x19,0x0f,0x00,0xb8,0x01,0x83,0x40,0x14,0x2e, 0x23,0x2e,0x11,0x89,0x21,0x06,0x89,0x07,0x19,0x2e,0x21,0x07,0x07,0x21,0x2e,0x19,0x04,0x45,0x33,0xb8,0x01,0x83,0x40,0x11,0x28,0x3f,0x9b,0x35,0x25,0x1e,0x16,0x1c,0x23,0x0f,0x25,0x1c,0x25,0x1c,0x25,0x0c,0x38,0xb8,0x01,0x7d,0x40,0x0f,0x07,0x16,0x19,0x30,0x2b,0x2e,0x00,0x00,0x0c,0x2b,0x2b,0x02,0x99,0x0c,0x06,0x00,0x3f,0xed, 0x39,0x2f,0x12,0x39,0x11,0x33,0x11,0x33,0x3f,0xc6,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x39,0x11,0x12,0x39,0x11,0x33,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x01,0x24,0x33,0x32,0x12,0x15,0x11,0x23,0x11,0x34,0x26,0x26,0x23, 0x22,0x06,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0xfc,0x01,0x16,0xc4,0xd3,0xef,0xa8,0x4d,0x82, 0x4b,0x4c,0xee,0x5f,0x39,0x39,0x57,0x74,0x44,0x49,0x68,0x69,0x48,0x3b,0x32,0x17,0x1a,0x22,0x48,0x41,0x57,0x66,0x70,0x4a,0x48,0x5f,0x44,0x29,0x3d,0x1b,0x24,0x26,0x19,0x2c,0x17,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x0f,0x96,0xfe,0xeb,0xf3,0xfb,0x4e,0x04,0xb2,0x66,0xab,0x61,0x4b,0x36,0xa7,0xba,0x55,0xea,0xa3,0x59,0x69, 0x49,0x4b,0x69,0x27,0x34,0x8f,0x37,0xac,0x73,0x22,0x69,0x52,0x4c,0x70,0x3c,0x92,0x5a,0x2a,0x1b,0x1b,0x30,0xfc,0xca,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x04,0x00,0x70,0xfe,0xa4,0x05,0x65,0x04,0xa5,0x00,0x4a,0x00,0x5d,0x00,0x67,0x00,0x73,0x00,0xa6,0xb3,0x0a,0x56,0x14,0x0c,0xb8,0x01,0x82,0x40,0x09,0x5e,0x24, 0x06,0x89,0x5a,0x62,0x8c,0x14,0x3d,0xb8,0x01,0x82,0x40,0x1e,0x6b,0x71,0x37,0x34,0x89,0x44,0x37,0x6b,0x44,0x5e,0x5a,0x14,0x6b,0x44,0x44,0x6b,0x14,0x5a,0x5e,0x05,0x75,0x4b,0x89,0x1d,0x2b,0x9b,0x00,0x00,0x03,0x48,0xb8,0x01,0x80,0xb4,0x31,0x54,0x0a,0x14,0x68,0xb8,0x01,0x7d,0x40,0x1b,0x40,0x5a,0x21,0x6e,0x9b,0x3a,0x56,0x60, 0x14,0x03,0x1a,0x21,0x37,0x3a,0x40,0x3a,0x40,0x3a,0x1a,0x28,0x31,0x06,0x4e,0x99,0x1a,0x19,0x65,0xb8,0x01,0x7d,0xb1,0x0f,0x19,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x12,0x17,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x32,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed,0x33,0x10,0xed,0x11,0x39,0x39,0x31,0x30,0x01,0x36,0x36,0x33,0x32,0x16,0x11,0x10,0x02,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x06,0x07,0x07,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x25,0x36,0x36,0x35,0x34, 0x26,0x26,0x23,0x22,0x07,0x06,0x07,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x01,0x14,0x16,0x33,0x32,0x36,0x37,0x36,0x24,0x33,0x32,0x17,0x36,0x36,0x35,0x35,0x01,0x06,0x06,0x05,0x34,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x36, 0x01,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0xfa,0x1d,0xd2,0x3c,0xa8,0x98,0x19,0x38,0x34,0x5e,0x6b,0x48,0x49,0x6a,0x15,0x5b,0x45,0xbc,0x86,0x8c,0x3e,0x63,0x6e,0xae,0xbf,0x02,0x0d,0x7d,0x54,0x1c,0x3c,0x40,0x56,0xa3,0x22,0x0f,0x14,0x39,0x4a,0x5a,0x36,0x58,0x60,0x39,0x2c,0x0d,0x62,0x3f,0x48,0x6b,0x6c, 0x47,0x74,0xcf,0x7a,0x5c,0xa6,0x66,0x44,0x9c,0xfe,0x62,0x21,0x16,0x1c,0x60,0x60,0x82,0x01,0x21,0x42,0x21,0x2c,0x26,0x31,0xfd,0x99,0xae,0x87,0x03,0xb6,0x47,0x3c,0x26,0x1c,0x1c,0x25,0xfd,0x5f,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x3f,0x1b,0x49,0xee,0xff,0x00,0xfe,0xff,0xfe,0xf8,0x88,0x1b,0x35,0x7e,0x46,0x6c,0x6c,0x51, 0x20,0x26,0x16,0x1e,0x57,0x41,0x2f,0x6a,0x67,0x56,0x95,0x53,0xe5,0x36,0x7a,0x72,0x7d,0x8f,0x3f,0x5a,0x13,0x05,0x03,0x24,0x2a,0x21,0x78,0x7b,0x3a,0x70,0x1b,0x44,0x50,0x6b,0x49,0x49,0x69,0x70,0xc2,0x71,0x71,0xaf,0x5f,0x38,0xfb,0x11,0x1d,0x1f,0x25,0x2e,0x3e,0x68,0x06,0x19,0x7f,0x49,0x42,0xfe,0xf0,0x4d,0x5b,0x46,0x35,0x20, 0x24,0x31,0x19,0x29,0x26,0x02,0xb8,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x02,0x00,0x78,0xff,0xf2,0x06,0xb5,0x04,0xa1,0x00,0x33,0x00,0x3f,0x00,0x64,0x40,0x09,0x02,0x89,0x31,0x00,0x33,0x27,0x89,0x0d,0x1a,0xb8,0x01,0x82,0x40,0x1b,0x37,0x3d,0x14,0x14,0x37,0x21,0x31,0x33,0x0d,0x37,0x37,0x0d,0x33,0x31,0x04,0x41, 0x12,0x89,0x21,0x3a,0x9b,0x14,0x1d,0x17,0x17,0x0f,0x34,0xb8,0x01,0x7d,0x40,0x0c,0x1d,0x19,0x33,0x00,0x24,0x99,0x0f,0x06,0x2e,0x99,0x06,0x19,0x00,0x3f,0xed,0x3f,0xed,0xc4,0x32,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x10,0xed,0x11,0x33, 0x10,0xed,0x31,0x30,0x01,0x12,0x11,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x37,0x36,0x35,0x10,0x21,0x22,0x06,0x15,0x10,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x10,0x03,0x01,0x32,0x36,0x35,0x34,0x26,0x23,0x22, 0x06,0x15,0x14,0x16,0x06,0x13,0xa2,0x70,0xcd,0x84,0x78,0xca,0x6a,0x03,0x0c,0xfe,0xe9,0x88,0x97,0x5e,0x17,0x50,0x30,0x48,0x6b,0x6c,0x47,0x6e,0xba,0x76,0xf3,0xcf,0xcf,0xf6,0x06,0x07,0x91,0x83,0x78,0x8d,0x9c,0xfc,0xa9,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x9f,0xfe,0x8d,0xfe,0xdf,0x9f,0xf6,0x84,0x5f,0xb4,0x7a,0x56,0xcd, 0x22,0x01,0x47,0xc6,0xb2,0xfe,0xf2,0x83,0x27,0x2f,0x6b,0x49,0x49,0x69,0xb0,0x01,0x49,0xa5,0xf4,0x01,0x1d,0xfd,0xdc,0x30,0x6b,0x6c,0x33,0x7a,0x8c,0xbb,0xc8,0x01,0x1a,0x01,0x42,0xfb,0xfe,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x02,0x00,0x78,0x01,0xb4,0x03,0xde,0x05,0x9a,0x00,0x0c,0x00,0x1c,0x00,0x1f,0x40,0x0f, 0x11,0x89,0x09,0x09,0x1e,0x03,0x89,0x19,0x06,0x99,0x15,0x00,0x9b,0x0d,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x02,0x2c,0x79,0x93,0x8d,0x7f, 0x80,0x8a,0x42,0x78,0x50,0x74,0xcb,0x73,0x6d,0xc8,0x7d,0x75,0xcb,0x74,0x6f,0xca,0x05,0x09,0xc9,0x9a,0xa5,0xbc,0xbb,0xa6,0x62,0xa6,0x5b,0x91,0x86,0xe6,0x89,0x92,0xe3,0x7c,0x80,0xe4,0x8d,0x8c,0xe6,0x83,0x00,0x01,0x00,0x64,0xff,0x83,0x03,0x98,0x05,0x9a,0x00,0x1d,0x00,0x38,0x40,0x1c,0x19,0x89,0x0e,0x0d,0x1d,0x00,0x03,0x0d, 0x00,0x00,0x0d,0x03,0x03,0x1f,0x09,0x89,0x11,0x0d,0x0a,0x0e,0x0e,0x15,0x00,0x1d,0x06,0x9b,0x15,0x06,0x00,0x3f,0xed,0x2f,0x33,0x12,0x39,0x2f,0x39,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0xed,0x31,0x30,0x17,0x36,0x00,0x35,0x34,0x02,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35, 0x34,0x36,0x24,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x00,0x07,0xe9,0xfa,0x01,0x0b,0x5d,0x3d,0x35,0xb1,0x60,0x42,0x39,0x9b,0x39,0x51,0xa5,0x01,0x14,0x6f,0x4b,0x78,0x49,0x85,0xfe,0xf0,0xb0,0x19,0xe7,0x01,0xb7,0xba,0x97,0x01,0x33,0x35,0x39,0x18,0x4b,0xb0,0x43,0x4d,0x51,0xe6,0x5f,0x3a,0x78,0x5a,0x88,0xfe,0xed,0x90,0x9b,0xfe, 0xae,0xfe,0x9b,0x9a,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0x00,0x05,0x9a,0x00,0x23,0x00,0x38,0x40,0x1b,0x00,0x23,0x23,0x25,0x0c,0x20,0x0f,0x08,0x08,0x16,0x1c,0x89,0x0f,0x05,0x9b,0x20,0x0a,0x15,0x0a,0x15,0x00,0x12,0x9b,0x19,0x06,0x23,0x00,0x00,0x2f,0x32,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x39,0xed,0x01,0x2f,0xed,0xc4,0x39, 0x2f,0x12,0x39,0x39,0x11,0x39,0x2f,0x33,0x31,0x30,0x05,0x26,0x02,0x26,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x12,0x13,0x03,0x67,0x21,0x4d,0x63,0x85,0x57,0x74,0x5b,0x1b,0x6d,0xb8,0x41,0x41,0x5d,0x79,0x77,0x6a, 0x53,0xf2,0x6d,0x42,0xa3,0xe7,0x6b,0xba,0xd0,0x38,0x61,0x64,0x62,0x88,0x1c,0x7d,0xf0,0x01,0x05,0xa0,0x59,0x36,0x8c,0x3b,0x18,0x54,0xc7,0x48,0x59,0x63,0x90,0x73,0x85,0x90,0x7f,0x98,0x8b,0x5d,0x9f,0x89,0x5d,0x5f,0xfe,0x91,0xfe,0xff,0x00,0x01,0x00,0x78,0xff,0x83,0x03,0xd3,0x05,0x9a,0x00,0x31,0x00,0x64,0x40,0x33,0x1f,0x1e, 0x1e,0x33,0x07,0x18,0x89,0x2b,0x28,0x04,0x00,0x16,0x2b,0x07,0x0e,0x00,0x2b,0x2b,0x00,0x0e,0x03,0x24,0x14,0x89,0x07,0x2e,0x9b,0x02,0x16,0x02,0x21,0x9b,0x26,0x0d,0x11,0x02,0x28,0x1c,0x26,0x1f,0x02,0x26,0x02,0x26,0x11,0x1e,0x1f,0x0a,0x9b,0x11,0x06,0x00,0x3f,0xed,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x11, 0x12,0x39,0x10,0xed,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0xc4,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39,0x39,0x10,0xed,0x11,0x12,0x39,0x2f,0x33,0x31,0x30,0x01,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x17,0x07, 0x02,0x21,0x22,0x07,0x27,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x01,0x0a,0x8c,0x8f,0x33,0x2e,0x59,0x4a,0x5c,0x69,0x4e,0xec,0x60,0x3c,0x8b,0xee,0x71,0x9c,0xbf,0xb1,0x8e,0x2d,0x63,0x53,0x88,0x5b,0x8d,0xa8,0xfe,0xa1,0x37,0x36,0x37,0x5f,0x69,0x85,0x6c,0x59,0x7c,0x78,0x73,0x43,0x81,0x23,0x03,0x68, 0x36,0x08,0x41,0x67,0x32,0x4b,0x4e,0x7f,0x5b,0x7b,0x77,0x79,0x99,0x84,0x8b,0x92,0x52,0x93,0x59,0x78,0x75,0x37,0x69,0xc4,0x4e,0x01,0x68,0x14,0x81,0x23,0x28,0x2c,0x97,0x46,0x53,0x5e,0x18,0x11,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0x81,0x05,0x9a,0x00,0x22,0x00,0x33,0x40,0x1a,0x1c,0x89,0x04,0x0e,0x02,0x0e,0x20,0x20,0x0e,0x02, 0x03,0x24,0x09,0x89,0x14,0x21,0x9b,0x20,0x20,0x0f,0x04,0x9b,0x18,0x06,0x0e,0x0f,0x00,0x2f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0xed,0x31,0x30,0x01,0x20,0x11,0x34,0x37,0x22,0x0e,0x02,0x15,0x14,0x12,0x12,0x04,0x17,0x07,0x26,0x00,0x00,0x02,0x35,0x34,0x36,0x24,0x33,0x32, 0x17,0x06,0x15,0x14,0x16,0x33,0x37,0x07,0x06,0x04,0x29,0xfe,0x53,0x0e,0x2e,0xa9,0x76,0x1b,0x86,0xfb,0x01,0x1c,0x77,0x30,0x97,0xfe,0xb0,0xfe,0xe9,0x90,0x57,0x01,0x32,0x83,0x8e,0x27,0x13,0x8a,0x91,0x40,0x10,0x2a,0x02,0xa8,0x01,0xc3,0x57,0x50,0x1c,0x23,0x2a,0x45,0x92,0xfe,0xa9,0xfe,0xad,0xf2,0x2b,0x88,0x32,0x01,0x13,0x01, 0x80,0x01,0x7e,0xac,0x6f,0x61,0x58,0x29,0x9f,0x3f,0xb0,0x9e,0x05,0x9d,0x05,0x00,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0xff,0x05,0xae,0x00,0x16,0x00,0x3a,0x40,0x1c,0x04,0x03,0x00,0x89,0x16,0x07,0x14,0x16,0x03,0x16,0x03,0x16,0x18,0x0e,0x8a,0x0d,0x12,0x99,0x07,0x0e,0x09,0x09,0x04,0x00,0x0e,0x07,0x03,0x04,0x00,0x2f,0x33,0x3f, 0x33,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x12,0x12,0x17,0x07,0x26,0x02,0x03,0x06,0x23,0x22,0x26,0x02,0x03,0x37,0x17,0x12,0x16,0x33,0x32,0x37,0x02,0x03,0x03,0x36,0x19,0xee,0xc2,0x4c,0x98,0xe5,0x46,0xa6,0x81,0x73,0x93,0x48,0x03,0xa5,0x08, 0x09,0x69,0x6d,0x3c,0x91,0x3c,0x0b,0x05,0xae,0xfd,0xd5,0xfd,0x09,0x8f,0x7a,0x62,0x01,0x9b,0x01,0x24,0x56,0x9e,0x01,0x57,0x01,0x57,0x14,0x9d,0xfe,0xbf,0xf1,0x4e,0x01,0x2c,0x01,0x41,0x00,0x01,0x00,0x78,0xff,0xf6,0x05,0x17,0x05,0x9a,0x00,0x2c,0x00,0x3f,0x40,0x20,0x17,0x16,0x16,0x1c,0x24,0x89,0x08,0x1c,0x89,0x10,0x08,0x10, 0x08,0x10,0x2e,0x00,0x8a,0x2c,0x1c,0x08,0x28,0x00,0x00,0x13,0x04,0x99,0x28,0x18,0x19,0x9b,0x13,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x39,0x2f,0x33,0x31,0x30,0x01,0x12,0x12,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x2e,0x02, 0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x02,0x03,0x01,0x1c,0x0d,0x94,0xef,0x9d,0x39,0x8f,0x5c,0x61,0x61,0x70,0x7f,0x73,0x40,0xdb,0xaf,0x53,0xa0,0x5b,0x4e,0x9a,0x65,0x67,0x7a,0x5f,0x63,0x99,0x7d,0x57,0x35,0x8c,0xee,0x74,0xbe,0xfe,0xe1, 0xb5,0x1f,0x04,0x66,0xfe,0xd1,0xfe,0x33,0xe3,0x5a,0x91,0x52,0x42,0x6d,0x31,0x38,0x3f,0x62,0x7a,0x4e,0x95,0xc0,0x45,0x42,0x73,0x69,0x6c,0x5a,0x3c,0x6a,0x34,0x51,0x4b,0x54,0x68,0x41,0x70,0xdb,0x8f,0xf0,0x01,0xf1,0x01,0x75,0x00,0x01,0x00,0x64,0xff,0xf6,0x05,0x65,0x05,0xae,0x00,0x26,0x00,0x46,0x40,0x12,0x00,0x8b,0x26,0x1b, 0x89,0x0c,0x1f,0x0c,0x07,0x26,0x0c,0x07,0x07,0x0c,0x26,0x03,0x28,0x12,0xb8,0x01,0x84,0x40,0x10,0x13,0x13,0x07,0x12,0x12,0x04,0x0f,0x9b,0x17,0x06,0x21,0x99,0x04,0x18,0x00,0x07,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x39,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x31,0x30, 0x01,0x0a,0x02,0x23,0x22,0x26,0x27,0x36,0x37,0x36,0x12,0x35,0x34,0x26,0x23,0x22,0x02,0x03,0x27,0x12,0x12,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x02,0x07,0x16,0x33,0x32,0x36,0x12,0x12,0x13,0x05,0x65,0x07,0x72,0xf7,0xd9,0x71,0x98,0x45,0x0a,0x19,0x89,0x6d,0x67,0x6b,0x79,0x90,0x1b,0x8d,0x1c,0x68,0xb7,0x93,0x6f,0x9c,0x54, 0x3e,0x73,0x3a,0x34,0x2c,0x83,0xa4,0x61,0x31,0x0a,0x05,0xae,0xfd,0xac,0xfd,0xa6,0xfe,0xf6,0x29,0x2a,0x18,0x2c,0xef,0x01,0x4f,0x8a,0x92,0x81,0xfe,0xe8,0xfe,0xbd,0x2f,0x01,0x1b,0x01,0x19,0x89,0x65,0xb1,0x68,0x69,0xfe,0xf8,0xfe,0xe9,0x5c,0x10,0x77,0x01,0x01,0x01,0xc4,0x01,0xd7,0x00,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0x5a, 0x05,0xae,0x00,0x15,0x00,0x2f,0x40,0x15,0x0c,0x0d,0x00,0x15,0x0f,0x08,0x0d,0x15,0x0d,0x15,0x17,0x08,0x0f,0x08,0x07,0x07,0x0d,0x0c,0x07,0x15,0x00,0x00,0x2f,0x32,0x3f,0x33,0x39,0x2f,0x33,0x33,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x05,0x26,0x02,0x26,0x26,0x23,0x22,0x07,0x27,0x3e,0x02, 0x37,0x17,0x04,0x07,0x36,0x33,0x32,0x04,0x12,0x17,0x03,0xc1,0x12,0x80,0xa2,0xb4,0x5b,0x83,0x60,0x23,0x2b,0x9f,0xda,0x63,0x6a,0xfe,0xeb,0x87,0x38,0x3e,0x89,0x01,0x1b,0xda,0x19,0x7d,0x81,0x01,0x4c,0xf6,0x85,0x39,0x7e,0x67,0xef,0xf2,0x56,0x64,0xff,0xf6,0x07,0xfe,0xfe,0x43,0xdb,0x00,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0x2a, 0x05,0x9a,0x00,0x25,0x00,0x3e,0x40,0x20,0x00,0x25,0x0e,0x89,0x16,0x09,0x89,0x1c,0x25,0x16,0x1c,0x11,0x11,0x1c,0x16,0x25,0x04,0x27,0x23,0x89,0x02,0x11,0x0e,0x06,0x12,0x12,0x00,0x1c,0x9b,0x06,0x06,0x00,0x00,0x2f,0x3f,0xec,0x12,0x39,0x2f,0x12,0x39,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed, 0x11,0x33,0x31,0x30,0x17,0x26,0x35,0x10,0x12,0x00,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x2e,0x02,0x35,0x34,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x02,0x15,0x14,0x17,0xa3,0x2b,0xce,0x01,0x45,0xbc,0x66,0x6c,0x73,0x4b,0x28,0x85,0x72,0x21,0x7a,0xaa,0x5c,0x36,0x3d,0x3a,0x39,0x1e,0x2b, 0x88,0xeb,0x91,0x2e,0x7d,0x95,0xc0,0x01,0x31,0x02,0x4d,0x01,0x44,0x4d,0x45,0x88,0x6b,0x46,0x33,0x1a,0x41,0x54,0x0f,0x91,0x12,0x54,0x74,0x3d,0x28,0x56,0x3b,0x38,0x5c,0x2d,0x19,0x12,0xfe,0xda,0xfd,0xf6,0xfc,0xc5,0x78,0x00,0x00,0x02,0x00,0x80,0xff,0xf1,0x04,0x01,0x03,0x6e,0x00,0x0f,0x00,0x1b,0x00,0x21,0x40,0x0c,0x00,0x8b, 0x10,0x10,0x1d,0x16,0x8b,0x08,0x13,0x9b,0x0c,0x19,0xb9,0x01,0x7f,0x00,0x04,0x00,0x2f,0xed,0x2f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x01,0x78,0xd2,0x78,0x78,0xd0, 0x77,0x79,0xd0,0x76,0x79,0xd0,0x79,0x97,0xaf,0x7c,0x7c,0xab,0xad,0x7a,0x7e,0xad,0x01,0xaf,0x76,0xce,0x7a,0x79,0xd0,0x75,0x7a,0xd1,0x74,0x75,0xd0,0x7a,0x80,0xb0,0xae,0x82,0x81,0xae,0xb4,0x00,0x00,0x01,0x00,0x7f,0xff,0xf1,0x03,0xda,0x03,0x6e,0x00,0x1b,0x00,0x34,0x40,0x12,0x1b,0x0f,0x0f,0x00,0x0e,0x07,0x8b,0x15,0x00,0x1b, 0x0e,0x0f,0x1b,0x0f,0x1b,0x0f,0x03,0x12,0xb8,0x01,0x7f,0xb3,0x0b,0x18,0x9b,0x03,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0xc4,0x32,0x32,0x11,0x33,0x31,0x30,0x13,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26, 0x23,0x22,0x06,0x07,0x80,0x3d,0xe0,0x84,0x79,0xcb,0x75,0x7c,0xd1,0x76,0x85,0xda,0x39,0x89,0x26,0x88,0x59,0x84,0xb0,0xac,0x7e,0x5c,0x93,0x24,0x02,0x68,0x7a,0x8c,0x7a,0xd0,0x75,0x73,0xd1,0x7a,0x91,0x7b,0x37,0x54,0x60,0xab,0x7c,0x7f,0xb9,0x65,0x58,0x00,0x00,0x01,0x00,0x3a,0xfd,0xfe,0x03,0xc2,0x03,0x64,0x00,0x12,0x00,0x24, 0x40,0x0d,0x00,0x8b,0x10,0x10,0x14,0x09,0x8b,0x08,0x08,0x08,0x04,0x11,0x0d,0xb9,0x01,0x7f,0x00,0x04,0x00,0x2f,0xed,0x2f,0x12,0x39,0x2f,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x33,0x14,0x16,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xc2,0x70,0xc5,0x85,0x92,0xcf,0x6d,0x98, 0x4d,0x8d,0x5c,0x88,0x9b,0x97,0x0d,0x91,0xef,0x75,0x6f,0xc7,0x82,0x52,0x8a,0x4d,0xc8,0xb1,0x03,0x5e,0x00,0x01,0x00,0x7f,0xfd,0xfe,0x03,0xda,0x03,0x6e,0x00,0x1f,0x00,0x47,0x40,0x1b,0x00,0xa8,0x1f,0x1f,0x21,0x1e,0x0a,0x10,0x04,0x04,0x11,0x03,0x18,0x8b,0x0a,0x11,0x10,0x03,0x1e,0x04,0x1c,0x10,0x04,0x10,0x04,0x14,0x07,0xb8, 0x01,0x7f,0xb4,0x1c,0x0d,0x9b,0x14,0x00,0x00,0x2f,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x32,0x11,0x33,0x01,0x2f,0xed,0xc4,0x32,0x32,0x11,0x33,0x11,0x39,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x01,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16, 0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x27,0x01,0x03,0x0f,0xfd,0xcb,0x2d,0x2e,0x89,0x26,0x88,0x59,0x83,0xb1,0xab,0x7f,0x5c,0x93,0x24,0x86,0x3d,0xe0,0x84,0x79,0xcc,0x74,0x7c,0xd1,0x76,0x05,0x05,0x01,0xc2,0xfd,0xfe,0x02,0x7d,0x32,0x54,0x38,0x54,0x60,0xa8,0x7e,0x80,0xb4,0x65,0x58,0x46,0x7a,0x8c,0x78,0xcd,0x75,0x73,0xd1,0x7a, 0x01,0xfe,0x07,0x00,0x00,0x01,0x00,0x80,0xfd,0xfe,0x03,0xdb,0x03,0x6e,0x00,0x1f,0x00,0x45,0x40,0x1d,0x0f,0x1b,0x1b,0x0e,0x01,0x1c,0x1c,0x07,0x21,0x1f,0x89,0x00,0x15,0x8b,0x07,0x1c,0x1b,0x0e,0x0f,0x01,0x1b,0x0f,0x1b,0x0f,0x03,0x12,0x9b,0x0b,0x18,0xb8,0x01,0x7f,0xb1,0x03,0x00,0x00,0x2f,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39, 0x2f,0x2f,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0xed,0xd4,0xed,0x11,0x12,0x39,0x2f,0x39,0x33,0x33,0x11,0x33,0x31,0x30,0x13,0x01,0x07,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x07,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x07,0x01,0x9f,0x01,0xb5,0x0b,0x06,0x75,0xd2,0x7c,0x74, 0xcb,0x7a,0x84,0xdd,0x40,0x86,0x25,0x93,0x5b,0x7f,0xab,0xb2,0x82,0x59,0x88,0x26,0x89,0x2a,0x32,0xfd,0xe0,0xfd,0xfe,0x01,0xf9,0x01,0x7a,0xd0,0x74,0x74,0xcd,0x79,0x8b,0x7b,0x46,0x58,0x65,0xb3,0x81,0x7e,0xa8,0x60,0x54,0x38,0x50,0x36,0xfd,0x83,0x00,0x02,0x00,0x80,0xfd,0xfe,0x04,0x08,0x03,0x6e,0x00,0x27,0x00,0x33,0x00,0x5c, 0xb4,0x14,0x8b,0x24,0x02,0x05,0xbb,0x01,0x83,0x00,0x2e,0x00,0x28,0x01,0x83,0x40,0x0d,0x0b,0x24,0x2e,0x0b,0x0b,0x2e,0x24,0x03,0x35,0x1d,0x8b,0x1c,0x31,0xbb,0x01,0x7e,0x00,0x02,0x00,0x2b,0x01,0x7e,0x40,0x0a,0x08,0x02,0x08,0x1c,0x1c,0x08,0x02,0x03,0x0f,0x21,0xb8,0x01,0x7f,0xb3,0x18,0x00,0x9b,0x0f,0x00,0x2f,0xed,0x2f,0xed, 0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x10,0xed,0x31,0x30,0x01,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x33,0x14,0x16,0x16,0x33,0x32,0x36, 0x35,0x11,0x34,0x26,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x4d,0x7a,0x52,0x55,0x73,0x82,0x61,0x5f,0x83,0x75,0xd3,0x81,0x86,0xc5,0x70,0x70,0xc6,0x85,0x91,0xcf,0x6d,0x98,0x4d,0x8d,0x5b,0x89,0x9b,0x99,0xfe,0x2b,0x3c,0x28,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x02,0xdf,0x4e,0x0a,0x81,0x56,0x5b,0x87,0x84, 0x5d,0x7b,0xce,0x76,0x76,0xee,0x91,0xfe,0x7a,0x90,0xef,0x76,0x6e,0xc8,0x82,0x56,0x86,0x4d,0xc8,0xb1,0x01,0x6a,0xb0,0xbf,0xfe,0xd2,0x28,0x3b,0x3c,0x27,0x29,0x3b,0x3b,0x00,0x00,0x02,0x00,0x80,0xff,0xf1,0x04,0x08,0x05,0xe9,0x00,0x2f,0x00,0x3b,0x00,0x6f,0xb9,0x00,0x30,0x01,0x83,0xb7,0x00,0x0b,0x8b,0x28,0x1a,0x8b,0x1b,0x06, 0xb8,0x01,0x83,0x40,0x11,0x36,0x08,0x36,0x00,0x28,0x1b,0x36,0x36,0x1b,0x28,0x00,0x04,0x3d,0x23,0x8b,0x12,0x33,0xb8,0x01,0x7e,0x40,0x18,0x2d,0x08,0x2d,0x39,0x9b,0x03,0x2d,0x03,0x2f,0x1b,0x01,0x1b,0x30,0x2d,0x01,0x1b,0x03,0x2d,0x03,0x0e,0x1f,0x9b,0x17,0x25,0xb9,0x01,0x7f,0x00,0x0e,0x00,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39, 0x5d,0x2f,0x5d,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x12,0x15,0x23,0x34,0x26,0x26, 0x23,0x22,0x06,0x15,0x11,0x10,0x21,0x32,0x36,0x35,0x34,0x26,0x27,0x07,0x23,0x22,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x0f,0x86,0x5c,0x5e,0x85,0x38,0x2a,0x35,0xfb,0xc6,0x8a,0xc6,0x6a,0x73,0xc5,0x82,0xd9,0xf5,0x98,0x4d,0x8d,0x5c,0x88,0x9b,0x01,0x23,0x94,0x96,0x3a,0x25,0x0a,0x0b,0x5e,0x83, 0x7f,0x3c,0x27,0x29,0x3b,0x3b,0x29,0x28,0x3b,0x02,0x7c,0x60,0x84,0x85,0x5e,0x52,0x43,0x1d,0x49,0x37,0x9f,0xbb,0x6a,0xd7,0x8c,0x02,0x54,0x8a,0xdf,0x6e,0xfe,0xf0,0xdb,0x60,0xa0,0x5c,0xbd,0xb2,0xfd,0xe6,0xfe,0xaf,0x61,0x5b,0x23,0x2d,0x10,0x01,0x83,0x60,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x3c,0x00,0x00,0x01,0x00,0x80,0xfe,0x05, 0x04,0x30,0x03,0x6e,0x00,0x32,0x00,0x43,0xb9,0x00,0x00,0x01,0x84,0x40,0x0c,0x32,0x23,0x8b,0x10,0x32,0x10,0x32,0x10,0x34,0x19,0x18,0x2a,0xb8,0x01,0x84,0x40,0x0b,0x08,0x18,0x19,0x32,0x19,0x32,0x04,0x13,0x9b,0x1f,0x2d,0xb9,0x01,0x7f,0x00,0x04,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x33,0x01,0x2f,0xed,0xc6,0x32, 0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x0e,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x04,0x30,0x07,0x40,0x6d, 0x4b,0x50,0x68,0x3a,0x1d,0x35,0x45,0x44,0x34,0x1c,0xaf,0x7c,0x7c,0xab,0x2d,0x7b,0x4a,0x79,0xd0,0x76,0x7a,0xd1,0x77,0x1e,0x32,0x50,0x58,0x35,0x2c,0x28,0x13,0x1d,0x1d,0x15,0x15,0xf9,0x48,0x74,0x46,0x32,0x5d,0x3b,0x3d,0x62,0x6e,0x6b,0x69,0x6c,0x69,0x34,0x7f,0xa7,0xae,0x82,0x58,0x4a,0x52,0x72,0x82,0x7a,0xd1,0x74,0x72,0xca, 0x79,0x34,0x75,0x68,0x7e,0x88,0x88,0x37,0x2a,0x2c,0x09,0x19,0x23,0x48,0x00,0x02,0x00,0x80,0xff,0xf0,0x04,0x01,0x03,0x6e,0x00,0x1d,0x00,0x24,0x00,0x47,0xb5,0x1a,0x8b,0x03,0x1d,0x00,0x0c,0xb8,0x01,0x83,0x40,0x0f,0x1e,0x03,0x00,0x1e,0x1e,0x00,0x03,0x03,0x26,0x21,0x8b,0x12,0x00,0x1d,0x21,0xb8,0x01,0x7d,0xb6,0x09,0x09,0x0f, 0x06,0x9b,0x16,0x23,0xb9,0x01,0x80,0x00,0x0f,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x2f,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x07,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15, 0x14,0x06,0x07,0x25,0x34,0x26,0x27,0x16,0x17,0x36,0x02,0xa5,0x53,0x72,0xaf,0x7c,0x64,0xa0,0x1a,0x7c,0x9d,0x6e,0x51,0x77,0x84,0x79,0xd1,0x75,0x79,0xd0,0x79,0x9d,0x76,0xfe,0xc5,0x57,0x42,0x0a,0x74,0x1b,0x6f,0x1d,0xb5,0x6e,0x80,0xb0,0x76,0x5e,0x09,0x9b,0x6f,0x4d,0x9d,0x1d,0x45,0xf8,0x92,0x72,0xc6,0x76,0x75,0xd0,0x7a,0x92, 0xfe,0x2f,0xfd,0x45,0x66,0x04,0x91,0x7a,0x2e,0x00,0x00,0x02,0x00,0x80,0xfd,0xfe,0x04,0x08,0x03,0x6e,0x00,0x30,0x00,0x3c,0x00,0x72,0x40,0x09,0x05,0x29,0x16,0x8b,0x15,0x26,0x8b,0x08,0x2b,0xbb,0x01,0x83,0x00,0x37,0x00,0x31,0x01,0x83,0x40,0x10,0x00,0x29,0x15,0x08,0x37,0x00,0x00,0x37,0x08,0x15,0x04,0x3e,0x0e,0x8b,0x1e,0x34, 0xb8,0x01,0x7e,0x40,0x19,0x2e,0x3a,0x9b,0x03,0x29,0x03,0x20,0x15,0x30,0x15,0x40,0x15,0x03,0x15,0x2e,0x03,0x03,0x2e,0x15,0x03,0x1a,0x0b,0x9b,0x23,0x11,0xb9,0x01,0x7f,0x00,0x1a,0x00,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x11,0x33,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x39, 0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x33,0x31,0x30,0x25,0x34,0x36,0x33,0x33,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x20,0x11,0x11,0x14,0x16,0x33,0x32,0x36,0x36,0x35,0x33,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x37,0x14,0x16, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x0f,0x83,0x5e,0x0b,0x0a,0x25,0x3a,0x97,0x93,0xfe,0xdd,0x98,0x8b,0x5b,0x93,0x48,0x98,0x6e,0xcf,0x91,0x83,0xc4,0x73,0x6a,0xc7,0x89,0xc6,0xfb,0x35,0x2a,0x38,0x82,0x61,0x5c,0x86,0x7f,0x3b,0x28,0x29,0x3b,0x3c,0x28,0x28,0x3b,0xe3,0x5e,0x83,0x01,0x10,0x2d,0x23,0x5c,0x60,0xfe, 0xaf,0xfe,0x6e,0xb1,0xbe,0x4c,0x83,0x5a,0x82,0xc7,0x6f,0x6e,0xe0,0x89,0x01,0xcc,0x8c,0xd8,0x69,0xbc,0x9e,0x37,0x49,0x1d,0x43,0x52,0x5c,0x87,0x84,0x5e,0x29,0x3b,0x3b,0x29,0x28,0x3b,0x3c,0x00,0x00,0x02,0x00,0x80,0xff,0xf1,0x04,0x08,0x05,0xe9,0x00,0x0f,0x00,0x1a,0x00,0x23,0x40,0x0d,0x00,0x8b,0x1a,0x1a,0x1c,0x16,0x8b,0x07, 0x12,0x9b,0x0c,0x07,0x18,0xb8,0x01,0x7f,0xb1,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x02,0x23,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x07,0x10,0x21,0x22,0x06,0x15,0x11,0x10,0x21,0x20,0x11,0x04,0x08,0xf6,0xd8,0x8a,0xc6,0x6a,0x74,0xc7,0x83,0xdb,0xef, 0x97,0xfe,0xc9,0x88,0x9b,0x01,0x23,0x01,0x37,0x01,0xc8,0xd6,0xfe,0xff,0x6a,0xd7,0x8c,0x02,0x54,0x85,0xe3,0x6f,0xf2,0xdc,0x0d,0x01,0x4c,0xbd,0xb2,0xfd,0xe6,0xfe,0xaf,0x01,0x6f,0x00,0x00,0x01,0x00,0x66,0xff,0xe7,0x03,0xa8,0x05,0xe8,0x00,0x09,0x00,0x2d,0x40,0x15,0x03,0x8b,0x07,0x05,0x07,0x05,0x0b,0x00,0x05,0x04,0x00,0x09, 0x04,0x09,0x04,0x09,0x01,0x07,0x18,0x01,0x06,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x13,0x25,0x33,0x11,0x25,0x17,0x05,0x23,0x11,0x05,0x66,0x01,0xd1,0x1c,0x01,0x2b,0x2a,0xfe,0x30,0x1c,0xfe,0xd4,0x05,0x16,0xd2,0xfa,0xcb,0x86,0x80,0xd2,0x05,0x35,0x83, 0x00,0x01,0x00,0x80,0x00,0x00,0x03,0xd2,0x05,0xe9,0x00,0x22,0x00,0x32,0xb7,0x08,0x8b,0x1b,0x1b,0x24,0x22,0x03,0x11,0xb8,0x01,0x84,0x40,0x0e,0x00,0x12,0x03,0x00,0x00,0x01,0x12,0x18,0x1e,0x9b,0x05,0x05,0x01,0x06,0x00,0x3f,0x33,0x2f,0xed,0x3f,0x12,0x39,0x2f,0x39,0x01,0x2f,0x33,0xed,0x32,0x32,0x12,0x39,0x2f,0xed,0x31,0x30, 0x13,0x11,0x33,0x15,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x36,0x36,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x15,0x80,0x97,0x73,0x87,0xca,0xf7,0x51,0x92,0xaa,0x80,0x66,0x37,0x94,0x43,0x77,0x9d,0x91,0x7d,0x42,0xaa,0x80,0x4e,0x83,0x29,0x04,0x12,0x01,0xd1,0x45,0x4b,0xed, 0xbd,0x57,0x9f,0x9d,0x85,0x65,0x66,0x5d,0x2e,0xd1,0xe0,0x42,0x7b,0x7d,0x7b,0x71,0x81,0x7a,0x3e,0x7b,0xa0,0x4e,0x3c,0xbe,0x00,0x01,0x00,0x66,0x00,0x00,0x04,0x34,0x05,0xe3,0x00,0x12,0x00,0x2c,0xb6,0x0a,0x8b,0x0b,0x0b,0x14,0x03,0x12,0xbb,0x01,0x85,0x00,0x00,0x00,0x0f,0x01,0x7f,0xb7,0x03,0x05,0x05,0x01,0x06,0x0b,0x00,0x18, 0x00,0x3f,0x32,0x3f,0x39,0x2f,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x33,0x01,0x33,0x03,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x07,0x03,0x66,0x01,0xeb,0xa7,0xd1,0x28,0x2c,0x7d,0xcb,0x71,0x97,0xac,0x7e,0x44,0x3f,0xe9,0x05,0xe3,0xfd,0x83,0x08,0x6a,0xbd,0x70,0xfe,0x29,0x01, 0xa7,0x7f,0xb9,0x1e,0xfd,0x3f,0x00,0x01,0x00,0x66,0xff,0xe7,0x04,0x8b,0x05,0xe3,0x00,0x09,0x00,0x37,0x40,0x09,0x03,0x8b,0x07,0x05,0x07,0x05,0x07,0x0b,0x09,0xb8,0x01,0x85,0x40,0x0f,0x00,0x05,0x08,0x01,0x03,0x07,0x04,0x04,0x01,0x07,0x18,0x01,0x06,0x00,0x18,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x33,0x01, 0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x33,0x01,0x33,0x11,0x25,0x17,0x05,0x23,0x11,0x01,0x66,0x02,0x1d,0xb3,0x01,0x2c,0x29,0xfe,0x30,0x1c,0xfe,0x68,0x05,0xe3,0xfa,0xcf,0x87,0x80,0xd2,0x04,0x7a,0xfb,0x9f,0x00,0x02,0x00,0x80,0xff,0xf1,0x04,0x59,0x05,0xe3,0x00,0x11,0x00,0x1d,0x00,0x35,0x40,0x16,0x00,0x04, 0x8b,0x0f,0x1c,0x02,0x1c,0x02,0x1f,0x15,0x8b,0x0b,0x03,0x12,0x9b,0x00,0x0e,0x0e,0x08,0x10,0x06,0x18,0xb8,0x01,0x7f,0xb1,0x08,0x19,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x33,0x15,0x23,0x11,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33, 0x21,0x11,0x33,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x36,0x35,0x11,0x03,0xdf,0x7a,0x7a,0x67,0xbb,0x7a,0xd0,0xf3,0xf1,0xc9,0x01,0x0e,0x97,0xfe,0x62,0x8d,0x9d,0xa6,0x8e,0x40,0x78,0x45,0x03,0x6e,0x8f,0xfe,0xa0,0x7c,0xb3,0x5f,0xee,0xd0,0xcb,0xf4,0x02,0x75,0xfc,0xfc,0xa4,0x94,0x8a,0x9d,0x3a,0x64,0x3f,0x01,0x82,0x00, 0x00,0x02,0x00,0x80,0x00,0x00,0x04,0x59,0x05,0xe9,0x00,0x11,0x00,0x1d,0x00,0x36,0x40,0x1b,0x10,0x02,0x8b,0x03,0x1d,0x03,0x00,0x03,0x00,0x03,0x1f,0x19,0x8b,0x08,0x10,0x1c,0x99,0x01,0x05,0x05,0x03,0x16,0x9b,0x0b,0x07,0x03,0x18,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11, 0x33,0x10,0xed,0x32,0x31,0x30,0x01,0x23,0x11,0x23,0x11,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x33,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x04,0x59,0x7a,0x97,0xfe,0xf2,0xca,0xf0,0xf3,0xd0,0x79,0xbc,0x67,0x7a,0xfe,0xef,0x46,0x77,0x40,0x8e,0xa6,0x9d,0x8d,0x01,0x07,0x02,0x6c,0xfd, 0x94,0x02,0x6c,0xf4,0xcb,0xcf,0xef,0x5f,0xb3,0x7c,0xfe,0xa1,0x01,0x81,0x3f,0x65,0x39,0x9c,0x8a,0x96,0xa2,0x00,0x00,0x01,0x00,0x67,0x00,0x00,0x03,0x41,0x05,0xe3,0x00,0x07,0x00,0x2a,0x40,0x0d,0x02,0x89,0x05,0x03,0x01,0x05,0x05,0x01,0x03,0x03,0x09,0x00,0x02,0xb8,0x01,0x7f,0xb5,0x05,0x18,0x07,0x9b,0x00,0x06,0x00,0x3f,0xed, 0x3f,0xed,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x31,0x30,0x13,0x21,0x01,0x21,0x15,0x21,0x01,0x21,0x67,0x02,0xa8,0xfe,0x4f,0x01,0xe3,0xfd,0x50,0x01,0xaa,0xfe,0x2c,0x05,0xe3,0xfa,0xac,0x8f,0x05,0x54,0x00,0x02,0x00,0x80,0xff,0xf1,0x04,0x01,0x05,0xfe,0x00,0x28,0x00,0x34,0x00,0x59,0x40,0x29,0x1a,0x1b,0x00,0x27, 0x03,0x09,0x8b,0x29,0x24,0x29,0x14,0x11,0x1b,0x06,0x29,0x1b,0x27,0x29,0x29,0x27,0x1b,0x03,0x36,0x1e,0x2f,0x8b,0x17,0x11,0x27,0x1b,0x1b,0x00,0x1a,0x14,0x06,0x0d,0x2c,0x9b,0x21,0x06,0x32,0xb8,0x01,0x7f,0xb1,0x0d,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0xc4,0x32,0x32,0x11,0x33,0x01,0x2f,0x33,0xed,0x32,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x37,0x13,0x34,0x26,0x23, 0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0x5b,0x4c,0x5a,0x6e,0x60,0x5f,0x6f,0x78,0xd2,0x78,0x78,0xd0,0x77,0x6a,0x63,0x5e,0x6f,0x5d,0x4d,0x63,0x36,0x3f,0xad,0x7a,0x7e,0xad,0x40,0x39,0x66,0x13,0xaf,0x7c,0x7c,0xab,0xad,0x7a,0x7e,0xad,0x05,0xfb,0x3c,0xb3,0x6d,0x6f,0xca,0x3e,0x3d,0xc7,0x75,0x76,0xce,0x7a,0x79,0xd0,0x75, 0x72,0xc7,0x40,0x3d,0xc8,0x72,0x6e,0xb4,0x3d,0x6a,0x2a,0x7e,0x4d,0x81,0xae,0xb4,0x7b,0x4b,0x80,0x2b,0x66,0xfb,0xb4,0x80,0xb0,0xae,0x82,0x81,0xae,0xb4,0x00,0x02,0x00,0x80,0xff,0xdc,0x04,0x01,0x05,0xe9,0x00,0x27,0x00,0x33,0x00,0x5a,0x40,0x2e,0x0d,0x0c,0x27,0x00,0x1e,0x24,0x8b,0x03,0x28,0x03,0x13,0x10,0x0c,0x21,0x03,0x0c, 0x00,0x03,0x03,0x00,0x0c,0x03,0x35,0x2e,0x09,0x8b,0x16,0x10,0x31,0x99,0x13,0x21,0x1a,0x06,0x06,0x0d,0x2b,0x9b,0x1a,0x07,0x00,0x0c,0x0c,0x27,0x0d,0x19,0x00,0x3f,0x33,0x33,0x11,0x33,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0xed,0x01,0x2f,0x33,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0x11,0x33,0x10, 0xed,0x32,0x11,0x33,0x11,0x33,0x31,0x30,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x07,0x13,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x02,0xf1,0x39,0x40, 0xae,0x7d,0x7a,0xad,0x3f,0x36,0x63,0x4d,0x5d,0x6f,0x5e,0x61,0x6c,0x78,0xd0,0x77,0x78,0xd2,0x78,0x6f,0x5f,0x61,0x6d,0x5b,0x4d,0x11,0xae,0x7d,0x7a,0xad,0xa9,0x7e,0x7e,0xad,0x46,0x2a,0x80,0x4b,0x7c,0xb3,0xae,0x81,0x4d,0x7e,0x29,0x6b,0x3d,0xb4,0x6e,0x71,0xc9,0x3d,0x3e,0xca,0x71,0x76,0xd0,0x78,0x7a,0xce,0x76,0x75,0xc6,0x3e, 0x3f,0xc9,0x6f,0x6d,0xb3,0x3e,0x04,0x4e,0x7c,0xb3,0xae,0x81,0x81,0xae,0xb1,0x00,0x00,0x02,0x00,0xa0,0xff,0xec,0x04,0x14,0x05,0xa3,0x00,0x0b,0x00,0x17,0x00,0x26,0xb9,0x00,0x00,0x01,0x85,0x40,0x0b,0x0c,0x0c,0x19,0x12,0x8a,0x06,0x0f,0x9b,0x09,0x06,0x15,0xb8,0x01,0x7f,0xb1,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed, 0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x03,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x04,0x14,0xd6,0xe5,0xe0,0xd9,0xda,0xdf,0xe0,0xdb,0xa0,0x8c,0x8f,0x8a,0x8d,0x88,0x8f,0x92,0x89,0x02,0xc8,0xfe,0x7a,0xfe,0xaa,0x01,0x58,0x01,0x84,0x01,0x78,0x01,0x63,0xfe, 0xa0,0xfe,0x85,0x01,0x3c,0x01,0x13,0xfe,0xe1,0xfe,0xd0,0xfe,0xc9,0xfe,0xe7,0x01,0x11,0x00,0x00,0x01,0x00,0x8c,0xff,0xec,0x04,0x4d,0x05,0xa3,0x00,0x2c,0x00,0x56,0xb9,0x00,0x16,0x01,0x85,0x40,0x0e,0x2b,0x09,0x03,0x23,0x09,0x03,0x1d,0x1d,0x03,0x09,0x23,0x04,0x2e,0x28,0xbb,0x01,0x85,0x00,0x0f,0x00,0x2b,0x01,0x7f,0x40,0x15, 0x0c,0x1c,0x1d,0x00,0x0c,0x06,0x0c,0x1d,0x1d,0x0c,0x06,0x03,0x13,0x1f,0x99,0x1a,0x19,0x25,0x9b,0x13,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0xed,0x31,0x30,0x01,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x00,0x11,0x14,0x02,0x04,0x23,0x22,0x27,0x27,0x16,0x33,0x32,0x36,0x12,0x35,0x10,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x02,0x38,0x29,0x30,0x4c,0x34,0x3e,0x4c,0x94,0x6f,0x9e,0xbc,0x77,0xd6,0x84,0xeb,0x01,0x05,0xaf,0xfe,0xcf,0xc4,0x48,0x50,0x1b,0x5f,0x68,0x93,0xdc, 0x81,0xfe,0xa4,0x88,0x9d,0x68,0x54,0x3a,0x02,0xf2,0x0b,0x42,0x27,0x32,0x4e,0x5a,0x3f,0x68,0x95,0xd9,0xb3,0x7b,0xd3,0x79,0xfe,0xa1,0xfe,0xb6,0xe2,0xfe,0x95,0xc1,0x0a,0xa5,0x19,0x92,0x01,0x1e,0xb6,0x02,0x2f,0xbd,0x90,0x66,0x88,0x00,0x00,0x02,0x00,0x64,0xff,0xec,0x05,0x7f,0x06,0x3b,0x00,0x4c,0x00,0x55,0x00,0x85,0xb5,0x31, 0x1a,0x1a,0x13,0x21,0x4d,0xbe,0x01,0x85,0x00,0x2b,0x00,0x25,0x01,0x84,0x00,0x52,0x00,0x38,0x01,0x85,0x40,0x0b,0x13,0x2b,0x52,0x13,0x13,0x52,0x2b,0x03,0x57,0x4c,0x04,0xb8,0x01,0x85,0xb4,0x48,0x40,0x9b,0x0b,0x50,0xb8,0x01,0x7e,0x40,0x13,0x28,0x55,0x9b,0x21,0x1a,0x9b,0x31,0x0b,0x28,0x21,0x31,0x31,0x21,0x28,0x0b,0x04,0x2f, 0x10,0x07,0xb8,0x01,0x7f,0x40,0x0b,0x3b,0x45,0x19,0x16,0x1d,0x9b,0x4c,0x00,0x34,0x2f,0x06,0x00,0x3f,0x33,0xc4,0x32,0xed,0x32,0x3f,0x33,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0xc6,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x32,0x11,0x39,0x11, 0x33,0x31,0x30,0x13,0x16,0x16,0x15,0x11,0x14,0x33,0x32,0x36,0x37,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x11,0x34,0x23,0x22,0x06,0x07,0x07,0x27,0x26,0x23,0x22,0x06,0x15,0x15,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x2e,0x02, 0x23,0x22,0x0e,0x02,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x27,0x01,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x94,0x66,0x65,0x57,0x24,0x47,0x3e,0x6c,0x68,0x30,0x5f,0x5a,0x53,0x24,0x20,0x2c,0x62,0x22,0x5a,0x2f,0x23,0x2c,0x5c,0x52,0x26,0x2e,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0x65,0x6d,0x92,0x6a,0x2d,0x83,0x41,0x69,0x76,0x85, 0x59,0x34,0x56,0x54,0x59,0x37,0x36,0x5e,0x5b,0x5f,0x37,0x78,0x77,0x26,0x35,0x02,0x1d,0x22,0x1c,0x37,0x4d,0x28,0x06,0x3b,0x13,0x72,0x6e,0xfb,0xa2,0x72,0x11,0x17,0x28,0x19,0x1e,0x19,0x38,0x20,0x03,0xbd,0x8a,0x46,0x38,0x2a,0x33,0x74,0x55,0x56,0xbd,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59,0x4e,0x01,0xfd,0xa8,0x9b,0x82,0x3a,0x48, 0x9b,0x8b,0xfc,0x21,0x45,0x6d,0x19,0x1e,0x19,0x19,0x1e,0x19,0x67,0x6d,0x04,0x44,0x5b,0x43,0x0f,0xfc,0xd9,0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x00,0x02,0x00,0xa0,0xff,0xec,0x06,0x1e,0x05,0xa3,0x00,0x28,0x00,0x31,0x00,0x5e,0xb9,0x00,0x15,0x01,0x84,0xb2,0x2e,0x22,0x08,0xbb,0x01,0x85,0x00,0x09,0x00,0x28,0x01,0x85,0x40,0x0b, 0x00,0x2e,0x09,0x00,0x00,0x09,0x2e,0x03,0x33,0x11,0x29,0xb8,0x01,0x85,0x40,0x0f,0x1b,0x31,0x9b,0x22,0x1f,0x11,0x11,0x18,0x04,0x0d,0x9b,0x24,0x1f,0x06,0x2c,0xb8,0x01,0x7e,0xb4,0x18,0x19,0x00,0x09,0x18,0x00,0x3f,0x33,0x3f,0xed,0x3f,0x33,0xed,0x32,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f, 0x2f,0x10,0xed,0x10,0xed,0x39,0x10,0xed,0x31,0x30,0x21,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x32,0x16,0x15,0x11,0x25,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x05,0x7e,0x82,0x62,0x69, 0x82,0xa0,0x82,0x69,0x63,0x81,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0xd4,0xb0,0x64,0xa2,0x35,0x6c,0xcf,0xaf,0xd5,0xfb,0x22,0x22,0x1c,0x37,0x4d,0x28,0x04,0x1e,0x70,0x89,0x8a,0x6f,0xfb,0xe2,0x04,0x1e,0x6f,0x8a,0x8a,0x6f,0xfd,0xc0,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59,0x4e,0x03,0x89,0xb5,0xd2,0x44,0x42,0x86,0xd1,0xb6,0xfb,0xe4, 0xba,0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x00,0x01,0x00,0xa0,0xff,0xec,0x04,0xc4,0x06,0x27,0x00,0x3d,0x00,0x6f,0x40,0x12,0x08,0x89,0x32,0x38,0x8b,0x03,0x2f,0x00,0x32,0x00,0x03,0x03,0x00,0x32,0x03,0x28,0x0b,0x1f,0xb8,0x01,0x85,0xb6,0x1c,0x0b,0x1c,0x0b,0x1c,0x3f,0x28,0xb8,0x01,0x85,0x40,0x14,0x15,0x23,0x19,0x19,0x1d,0x35, 0x0e,0x2f,0x2f,0x12,0x03,0x35,0x3b,0x3b,0x12,0x06,0x9b,0x35,0x06,0x2b,0xb8,0x01,0x7f,0xb4,0x12,0x19,0x0b,0x0c,0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x11,0x33,0x10,0xc4,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10, 0xed,0x10,0xed,0x31,0x30,0x01,0x34,0x36,0x33,0x26,0x26,0x23,0x22,0x15,0x14,0x16,0x17,0x07,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x11,0x10,0x00,0x25,0x36,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x06,0x07,0x0e,0x02,0x15,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23, 0x22,0x26,0x03,0x9f,0x51,0x37,0x08,0x57,0x44,0xb6,0xe7,0xf1,0x1a,0xc0,0x64,0x55,0x77,0x78,0x3c,0x95,0xb3,0x01,0x00,0x01,0x1e,0xa9,0x97,0xa0,0x5a,0xac,0xa3,0xa4,0xb7,0x5a,0x6a,0x64,0x2e,0x77,0x7d,0x2d,0x93,0xa6,0xb8,0x9f,0x96,0xb3,0x58,0x44,0x39,0x50,0x02,0x26,0x39,0x4f,0x3b,0x44,0xdc,0x90,0xdd,0x56,0xa0,0x21,0x11,0x12, 0xc2,0x9f,0x01,0x0f,0x01,0x05,0x01,0x2e,0x4e,0x2d,0x61,0x41,0x7b,0x73,0x56,0x81,0x58,0x2b,0x2c,0x82,0xc7,0x8b,0xd6,0x83,0x89,0x0f,0x0f,0x01,0x3d,0xd9,0x93,0xb1,0xc8,0xcb,0xa7,0x4c,0x5e,0x4f,0x00,0x02,0x00,0xa0,0xff,0xec,0x04,0xf8,0x06,0x3b,0x00,0x4e,0x00,0x5a,0x00,0xa2,0xb9,0x00,0x4f,0x01,0x84,0xb4,0x3e,0x46,0x3c,0x3e, 0x44,0xbb,0x01,0x84,0x00,0x55,0x00,0x04,0x01,0x85,0x40,0x1f,0x4a,0x2a,0x89,0x15,0x1b,0x8b,0x24,0x13,0x21,0x15,0x21,0x24,0x24,0x21,0x15,0x03,0x0c,0x2d,0x3e,0x55,0x4a,0x2d,0x00,0x00,0x2d,0x4a,0x55,0x3e,0x05,0x5c,0x0c,0xb8,0x01,0x85,0x40,0x1e,0x37,0x00,0x4e,0x41,0x30,0x13,0x27,0x9b,0x18,0x46,0x3c,0x08,0x13,0x34,0x24,0x1e, 0x08,0x52,0x18,0x41,0x1e,0x18,0x1e,0x18,0x34,0x58,0x9b,0x41,0x06,0x0f,0xb8,0x01,0x7f,0xb4,0x34,0x19,0x2d,0x2e,0x19,0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x39,0x11,0x39,0x12,0x39,0x11,0x33,0x33,0x10,0xed,0x11,0x33,0x10,0xc4,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f, 0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x15,0x14,0x06,0x06,0x23,0x06,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x24,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x26,0x26,0x23, 0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x3e,0x02,0x35,0x35,0x34,0x36,0x37,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x04,0xf8,0x37,0x23,0x7d,0xf5,0x8f,0xae,0xaf,0x6a,0x64,0x2e,0x77,0x7d, 0x2d,0xfe,0xc7,0xc5,0x92,0x96,0xb3,0x58,0x44,0x39,0x50,0x51,0x37,0x08,0x57,0x44,0x53,0x63,0xf9,0xdf,0x1a,0xc0,0x64,0x55,0x77,0x78,0x3c,0x95,0xb3,0x43,0x8b,0x72,0x61,0x7a,0x62,0x5f,0x84,0x1b,0x41,0x62,0x38,0x67,0x64,0xfd,0x3f,0x30,0x23,0x24,0x31,0x31,0x24,0x23,0x30,0x05,0xb1,0x10,0x45,0x58,0x53,0x56,0x80,0x47,0x1d,0xbe, 0xaf,0x86,0x83,0x89,0x0f,0x0f,0x01,0x7c,0xf5,0x8b,0xb8,0xcb,0xa7,0x4c,0x5e,0x4f,0x3a,0x39,0x4f,0x3b,0x44,0x60,0x53,0x7a,0xc7,0x3d,0xa0,0x21,0x11,0x12,0xc2,0x9f,0xbf,0x7f,0xa2,0x7d,0x2a,0x43,0x70,0x5f,0x83,0x86,0x5b,0x34,0x33,0x01,0x2e,0x4b,0x25,0x88,0x6f,0x71,0x13,0xfe,0x57,0x23,0x30,0x30,0x23,0x24,0x31,0x31,0x00,0x01, 0x00,0x7b,0xff,0xec,0x04,0x61,0x06,0x3b,0x00,0x3a,0x00,0x76,0xb9,0x00,0x24,0x01,0x85,0xb4,0x0b,0x32,0x89,0x00,0x1e,0xb8,0x01,0x85,0x40,0x11,0x17,0x12,0x13,0x0b,0x00,0x39,0x17,0x13,0x13,0x17,0x39,0x00,0x0b,0x05,0x3c,0x1a,0x05,0xb8,0x01,0x85,0xb3,0x2b,0x13,0x12,0x02,0xb8,0x01,0x7f,0x40,0x0d,0x2e,0x00,0x2e,0x35,0x12,0x2e, 0x35,0x35,0x2e,0x12,0x03,0x20,0x08,0xb8,0x01,0x7f,0x40,0x0a,0x27,0x19,0x1a,0x1b,0x17,0x1e,0x0f,0x9b,0x20,0x06,0x00,0x3f,0xed,0x39,0x39,0xc4,0x32,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0xc6,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x10,0xed,0x10,0xed, 0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x12,0x11,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x37,0x36,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x17,0x36,0x33,0x32,0x00,0x11,0x15,0x10,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x02,0x4c,0x16, 0x3a,0x54,0x68,0x9c,0x89,0xb3,0xa9,0xac,0xa5,0x6d,0xba,0x2e,0x65,0x11,0x0c,0x04,0x2f,0x2d,0x2f,0x60,0x6c,0x02,0x70,0x74,0xfc,0x01,0x09,0xff,0xf1,0x84,0xd6,0x77,0xbc,0x9e,0x49,0x77,0x43,0x4c,0x3e,0x35,0x4b,0x30,0x02,0x9d,0x16,0x88,0x66,0x90,0xbd,0x01,0x08,0x01,0x13,0x9e,0xef,0xed,0x63,0x4e,0x72,0x26,0x1b,0x15,0x19,0x2a, 0x3e,0x0c,0x8a,0x13,0x72,0x4b,0x38,0xfe,0xc8,0xfe,0xd0,0xba,0xfe,0xbd,0xfe,0xae,0x79,0xd3,0x7b,0xb3,0xd9,0x44,0x76,0x43,0x3f,0x5a,0x4f,0x31,0x27,0x42,0x00,0x02,0x00,0xa0,0xff,0xec,0x05,0x85,0x06,0x3b,0x00,0x37,0x00,0x40,0x00,0x76,0xb9,0x00,0x1c,0x01,0x84,0xb5,0x3d,0x28,0x11,0x11,0x38,0x2e,0xbb,0x01,0x85,0x00,0x0a,0x00, 0x04,0x01,0x85,0x40,0x0d,0x33,0x3d,0x0a,0x37,0x33,0x33,0x37,0x0a,0x3d,0x04,0x42,0x18,0x38,0xb8,0x01,0x85,0x40,0x15,0x22,0x40,0x9b,0x18,0x11,0x9b,0x28,0x18,0x28,0x18,0x28,0x1f,0x0e,0x14,0x9b,0x37,0x00,0x2a,0x26,0x06,0x3b,0xb8,0x01,0x7e,0xb2,0x1f,0x19,0x30,0xb8,0x01,0x7f,0xb1,0x07,0x19,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33, 0xc6,0x32,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x12,0x39,0x11,0x33,0x10,0xed,0x31,0x30,0x01,0x16,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x26,0x23,0x22,0x06,0x15,0x11,0x1e,0x02,0x15, 0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x27,0x01,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x04,0xba,0x66,0x65,0x85,0x72,0x72,0x7f,0x28,0x30,0x23,0x63,0x52,0x2b,0x5a,0x54,0x26,0x2e,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0x65,0x6d,0x91, 0x6a,0x6c,0x84,0x6a,0x76,0x54,0x27,0x2d,0x29,0x31,0xfc,0xb5,0x22,0x1c,0x37,0x4d,0x28,0x06,0x3b,0x15,0x6e,0x65,0xfb,0x6d,0x64,0x70,0x69,0x5d,0x03,0xdb,0x46,0x44,0x49,0x5f,0x33,0x74,0x55,0x56,0xfd,0x73,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59,0x4e,0x03,0xcd,0xa8,0x9b,0x82,0x82,0x9d,0x89,0xfc,0x67,0x6c,0x39,0x39,0x04,0x2c,0x57, 0x3c,0x08,0xfb,0x09,0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x01,0x00,0xa0,0xff,0xec,0x04,0x8e,0x06,0x27,0x00,0x45,0x00,0x6d,0xb9,0x00,0x00,0x01,0x85,0xb5,0x43,0x33,0x13,0x13,0x0c,0x2e,0xb8,0x01,0x85,0x40,0x0f,0x1a,0x1f,0x89,0x28,0x43,0x1a,0x22,0x28,0x28,0x22,0x1a,0x43,0x04,0x47,0x0c,0xbb,0x01,0x85,0x00,0x39,0x00,0x13,0x01, 0x81,0x40,0x09,0x33,0x1f,0x25,0x33,0x25,0x33,0x2b,0x17,0x0f,0xb8,0x01,0x7f,0x40,0x0b,0x31,0x36,0x19,0x05,0x3f,0x3f,0x44,0x1d,0x9b,0x2b,0x06,0x00,0x3f,0xed,0xc4,0x39,0x11,0x33,0x3f,0x33,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x39,0x10,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x12,0x39,0x11, 0x33,0x10,0xed,0x31,0x30,0x01,0x14,0x0e,0x02,0x07,0x0e,0x04,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x17,0x16,0x16,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x3e,0x02,0x37, 0x3e,0x02,0x35,0x35,0x33,0x04,0x8e,0x2e,0x54,0x92,0x9a,0x7e,0x72,0x56,0x3a,0x20,0x3b,0x36,0x22,0x5a,0x2f,0x23,0x2c,0x2f,0x54,0x2b,0x41,0x39,0x52,0x3c,0x16,0x1a,0x27,0x25,0x48,0x34,0x3a,0x4b,0x7e,0x6d,0x8a,0x9e,0x8e,0x6a,0x92,0x6a,0x2d,0x84,0x40,0x6c,0x82,0x38,0x73,0xc5,0xc1,0x72,0x71,0x3a,0xa0,0x05,0xb4,0x4a,0x72,0x55, 0x44,0x26,0x20,0x36,0x4e,0x73,0xa1,0x6f,0xfe,0xf0,0x44,0x46,0x46,0x38,0x2a,0x32,0x3b,0x39,0x01,0x9f,0x98,0x75,0x90,0x07,0x0a,0x39,0x23,0x2b,0x45,0x4c,0x3a,0x60,0x80,0xe4,0xbc,0xb9,0xf9,0x82,0x3b,0x47,0xa1,0x85,0x01,0x2c,0x8b,0xcd,0x8f,0x6c,0x39,0x23,0x3d,0x52,0x30,0x7b,0x00,0x01,0x00,0xe9,0xff,0xec,0x04,0xac,0x06,0x3b, 0x00,0x43,0x00,0x85,0xb9,0x00,0x2f,0x01,0x85,0xb5,0x1b,0x40,0x04,0x8a,0x05,0x0b,0xb8,0x01,0x85,0x40,0x15,0x3b,0x05,0x23,0x38,0x29,0x3b,0x00,0x1b,0x10,0x23,0x29,0x3b,0x3b,0x29,0x23,0x10,0x1b,0x00,0x06,0x45,0x15,0xb8,0x01,0x85,0x40,0x20,0x36,0x00,0x43,0x3e,0x1e,0x9b,0x2c,0x38,0x12,0x9b,0x0f,0x20,0x26,0x2c,0x40,0x05,0x3e, 0x26,0x2c,0x0f,0x05,0x05,0x0f,0x2c,0x26,0x04,0x33,0x08,0x9b,0x3e,0x06,0x18,0xb8,0x01,0x7f,0xb1,0x33,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0xed,0x39,0x10,0xed,0x10,0xc4,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x39, 0x10,0xed,0x10,0xed,0x39,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x15,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x21,0x07,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x35, 0x10,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x34,0x36,0x37,0x04,0xac,0x37,0x23,0xa2,0x22,0x8e,0x61,0x6a,0x85,0x35,0x63,0x46,0x01,0x3c,0x10,0xed,0x8f,0xb5,0xb8,0x8c,0x91,0xa8,0x41,0x30,0x16,0x1a,0x27,0x25,0x48,0x34,0x3a,0x4b,0x7e,0x6d,0x7e,0x8d,0x78,0xda,0x87,0xdf,0xfe,0xfb,0xdc,0x57,0x5e,0xe0,0xb6,0xa3,0x69,0x67, 0x64,0x05,0xb1,0x10,0x45,0x58,0xa4,0x56,0x61,0x70,0x5b,0x35,0x58,0x32,0x8c,0xb2,0x91,0x8f,0xb7,0x7d,0x6d,0x49,0x5e,0x07,0x0a,0x39,0x23,0x2b,0x45,0x4c,0x3a,0x60,0x80,0xa7,0x99,0x6c,0xa2,0x58,0xf1,0xcd,0x01,0x2d,0x69,0x26,0x8b,0x5b,0x9b,0xbc,0x5b,0x6f,0x71,0x13,0x00,0x02,0x00,0x84,0x00,0x45,0x03,0x96,0x05,0xa3,0x00,0x0e, 0x00,0x1d,0x00,0x1f,0x40,0x0f,0x0f,0x89,0x00,0x00,0x1f,0x07,0x89,0x17,0x0b,0x9a,0x13,0x03,0x9b,0x1b,0x06,0x00,0x3f,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x12,0x37,0x14,0x02,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32, 0x12,0x02,0xef,0x60,0x4c,0x4e,0x7c,0x4e,0x33,0x55,0x2f,0x4f,0x77,0x47,0xa7,0x75,0xc9,0x87,0x67,0x95,0x51,0x7a,0xd7,0x7c,0x98,0xad,0x03,0x81,0xb6,0xe2,0xb0,0xfe,0xa8,0xb8,0x72,0xb7,0x62,0xa8,0x01,0x5f,0xa0,0xf3,0xfe,0x7f,0xbc,0x8f,0x01,0x1e,0xba,0xd5,0x01,0x5e,0xc4,0xfe,0xd5,0x00,0x00,0x01,0x00,0x69,0xfe,0xf1,0x03,0x48, 0x05,0xa3,0x00,0x2e,0x00,0x3d,0x40,0x0f,0x00,0x89,0x15,0x1c,0x89,0x28,0x15,0x21,0x28,0x28,0x21,0x15,0x03,0x30,0x0e,0xb8,0x01,0x83,0x40,0x0e,0x09,0x0c,0x24,0x0c,0x24,0x05,0x18,0x9b,0x2c,0x06,0x11,0x99,0x05,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10, 0xed,0x31,0x30,0x01,0x14,0x02,0x02,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x16,0x16,0x33,0x32,0x12,0x12,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x16,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x10,0x12,0x36,0x33,0x32,0x12,0x03,0x48,0x5d,0x88,0xa7,0x50,0x3b,0x7b,0x4d,0x4d,0x11,0x1f,0x06,0x0b, 0x51,0x2d,0x46,0x93,0x53,0x3c,0x36,0x42,0x75,0x4d,0x27,0x10,0x09,0x5f,0x1d,0x11,0x38,0x22,0x74,0xcc,0x7a,0x7f,0x8b,0x03,0x60,0xec,0xfe,0x42,0xfe,0xdd,0xa2,0x4f,0x7b,0x3a,0x12,0x3a,0x20,0x3b,0x61,0x01,0x52,0x01,0xf7,0xcb,0xb6,0xca,0xc0,0xfe,0xa8,0x90,0x72,0x8f,0x29,0x17,0x15,0x1a,0x44,0x68,0x96,0x5a,0x01,0x0e,0x01,0x9e, 0xe2,0xfe,0xd5,0x00,0x00,0x01,0x00,0x84,0x00,0x8a,0x04,0x64,0x05,0xa3,0x00,0x3f,0x00,0x4e,0xb5,0x0c,0x32,0x08,0x32,0x0f,0x00,0xb8,0x01,0x83,0x40,0x21,0x3b,0x2f,0x89,0x15,0x3b,0x15,0x0f,0x20,0x20,0x0f,0x15,0x3b,0x04,0x41,0x1c,0x89,0x27,0x32,0x08,0x0c,0x05,0x08,0x3d,0x3d,0x08,0x05,0x0c,0x04,0x23,0x17,0x9b,0x2c,0x06,0x00, 0x3f,0xed,0xc4,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x11,0x33,0x31,0x30,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x01,0x36,0x36,0x35,0x34,0x23,0x22,0x06,0x06,0x02,0x15,0x14,0x17,0x16,0x15, 0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x12,0x12,0x36,0x33,0x32,0x16,0x15,0x14,0x03,0x03,0x36,0x33,0x32,0x16,0x33,0x32,0x36,0x37,0x36,0x36,0x33,0x32,0x16,0x04,0x64,0x0f,0x6e,0x65,0x44,0x1f,0x3a,0x1f,0x2b,0x35,0x0a,0x09,0x15,0x3e,0x0b,0x01,0x1a,0x29,0x31,0x68,0x41,0xb8,0x9e,0x55,0x30,0x09,0x5f,0x1c,0x13,0x31,0x21,0x6f, 0xcc,0xf4,0x72,0x78,0x89,0xa9,0xc5,0x0d,0x14,0x18,0x2c,0x1b,0x17,0x62,0x21,0x0b,0x0d,0x0b,0x23,0x4c,0x02,0x21,0x11,0x2d,0xd7,0x60,0x12,0x22,0x07,0x40,0x10,0x16,0x16,0x02,0x32,0x52,0xaa,0x28,0xb2,0x9b,0xf7,0xfe,0xeb,0x89,0x5b,0x7d,0x18,0x11,0x17,0x47,0x5b,0x8b,0x3f,0xbf,0x01,0x6d,0x01,0x23,0xa5,0xa4,0x86,0x71,0xfe,0xbb, 0xfe,0x84,0x04,0x09,0x8d,0x51,0x1c,0x17,0x23,0x00,0x00,0x01,0x00,0x84,0x01,0x73,0x04,0x1b,0x05,0xa3,0x00,0x54,0x00,0x4c,0x40,0x28,0x47,0x89,0x14,0x41,0x4b,0x0c,0x14,0x34,0x23,0x0c,0x14,0x00,0x00,0x14,0x0c,0x23,0x34,0x05,0x56,0x2f,0x89,0x3a,0x16,0x2b,0x9b,0x3e,0x41,0x3e,0x51,0x1f,0x51,0x1f,0x04,0x37,0x4b,0x03,0x0a,0x43, 0x3e,0x06,0x00,0x3f,0x33,0xc4,0x17,0x32,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x39,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x06,0x23,0x22,0x26,0x23,0x22,0x07,0x07,0x22,0x35,0x35,0x34,0x37,0x37,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07, 0x0e,0x02,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x07,0x16,0x33,0x32,0x36,0x37,0x36,0x33,0x32,0x16,0x04,0x0e,0x62,0x7f,0x2a,0x11,0x2d,0x28,0x23,0x23, 0x10,0x36,0x43,0x20,0x9b,0x2a,0x3b,0x19,0x15,0x16,0x2b,0x31,0x38,0x24,0x23,0x30,0x27,0x1b,0x11,0x2f,0x2b,0x25,0x48,0x29,0x23,0x38,0x58,0x35,0x0d,0x11,0x0d,0x6b,0x1e,0x12,0x36,0x5f,0xa8,0x72,0x29,0x68,0x16,0x5e,0x61,0x36,0x53,0x2f,0x54,0x50,0x8d,0x18,0x1c,0x20,0x4f,0x1c,0x0d,0x15,0x11,0x32,0x02,0x62,0x22,0x71,0x51,0x07, 0x0f,0x03,0x24,0x0d,0x0e,0x71,0x39,0x01,0x23,0x4d,0xc1,0x35,0x26,0x31,0x32,0x61,0x90,0x5d,0x5c,0x66,0x2e,0x1d,0x11,0x14,0x6d,0x5e,0xb5,0x62,0x26,0x26,0x82,0xfe,0xf1,0x90,0x4b,0x5c,0x3c,0x29,0x16,0x14,0x41,0xc6,0x49,0xe7,0x01,0x75,0xb7,0x32,0x23,0x55,0x32,0x57,0x33,0x4a,0xf1,0x94,0xfe,0x0b,0x3e,0x32,0x18,0x24,0x00,0x01, 0x00,0x84,0xff,0xc3,0x03,0x45,0x05,0xa7,0x00,0x26,0x00,0x2d,0x40,0x17,0x10,0x12,0x04,0x89,0x1f,0x25,0x12,0x1f,0x1f,0x12,0x25,0x03,0x28,0x18,0x8a,0x0b,0x1b,0x9a,0x08,0x10,0x06,0x00,0x07,0x00,0x3f,0x3f,0xd4,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x32,0x16,0x16,0x15,0x10,0x02, 0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x37,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x12,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x36,0x02,0xa9,0x20,0x4c,0x30,0x69,0xba,0x83,0x8c,0x8f,0x8d,0x81,0x1a,0x15,0x0e,0x57,0x2c,0x75,0x5d,0x43,0x3b,0x4a,0x6e,0x40,0x28,0x2e,0x08,0x54,0x05,0xa7,0x9c,0xed, 0x6b,0xfe,0xef,0xfe,0x1c,0xfb,0xee,0xe8,0xd0,0x01,0x65,0x8e,0x1c,0x36,0x0c,0x14,0x3a,0xa0,0xfe,0xed,0x98,0x94,0xbb,0xde,0x01,0xa1,0xca,0x94,0xb9,0x49,0x0c,0x13,0x11,0x4a,0x00,0x01,0x00,0x84,0x01,0x46,0x03,0x79,0x05,0xa7,0x00,0x33,0x00,0x49,0xb9,0x00,0x31,0x01,0x83,0xb4,0x07,0x2f,0x89,0x28,0x0a,0xb8,0x01,0x84,0x40,0x1b, 0x21,0x00,0x07,0x28,0x21,0x21,0x28,0x07,0x00,0x04,0x35,0x19,0x8b,0x13,0x0a,0x16,0x2b,0x04,0x16,0x04,0x16,0x0f,0x2b,0x07,0x1d,0x99,0x0f,0x00,0x2f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x27, 0x27,0x26,0x27,0x27,0x06,0x02,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x07,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x36,0x37,0x36,0x35,0x34,0x27,0x27,0x34,0x36,0x33,0x32,0x16,0x16,0x17,0x17,0x13,0x17,0x16,0x03,0x79,0x3b,0x29,0x19,0x2e,0x19,0x1a,0x18,0x0a,0x05,0x06,0x29,0x35,0x5a,0x49,0x57,0x65,0x2d, 0x1e,0x37,0x27,0x1d,0x04,0x2a,0x2b,0x30,0x38,0x0d,0x06,0x0b,0x1d,0x14,0x16,0x04,0x3e,0x17,0x1b,0x17,0x14,0x0b,0x04,0x64,0x3c,0x24,0x01,0xdd,0x17,0x23,0x7b,0x8b,0x8a,0x77,0x80,0x2b,0x7f,0xfe,0x64,0xa3,0x51,0x71,0xe0,0xf8,0x21,0x1b,0x15,0x14,0xed,0x72,0x68,0xa7,0xd6,0x5a,0xa9,0x3a,0x3c,0x40,0x10,0x45,0x11,0x11,0x1f,0x18, 0x47,0x45,0x18,0xfe,0x6e,0xd2,0x7f,0x00,0x00,0x01,0x00,0x84,0xff,0xc3,0x03,0xdd,0x05,0xa3,0x00,0x40,0x00,0x49,0xb7,0x06,0x89,0x22,0x00,0x3b,0x8b,0x36,0x27,0xb8,0x01,0x82,0x40,0x1c,0x2e,0x22,0x15,0x36,0x2e,0x2e,0x36,0x15,0x22,0x04,0x42,0x1c,0x89,0x0d,0x24,0x00,0x00,0x2b,0x2b,0x39,0x1f,0x9a,0x09,0x39,0x06,0x19,0x12,0x06, 0x00,0x3f,0x33,0x3f,0xd4,0xed,0x12,0x39,0x2f,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x10,0xed,0x31,0x30,0x01,0x36,0x36,0x33,0x32,0x16,0x15,0x10,0x02,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x06,0x02,0x15,0x10,0x12,0x33,0x32, 0x36,0x35,0x34,0x23,0x22,0x06,0x06,0x07,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x35,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x15,0x14,0x07,0x06,0x15,0x14,0x02,0x7d,0x14,0x2a,0x16,0x78,0x94,0xc8,0xbe,0x88,0xd5,0x76,0x60,0xad,0xd8,0x60,0x37,0x26,0x10,0x2a,0x2f,0xb7,0xdc,0xa1,0x8a,0x70,0x72,0x7c,0x17,0x2e,0x20,0x01, 0x01,0x17,0x22,0x1f,0x17,0x0e,0x0d,0x08,0x08,0x1d,0x30,0x4f,0x0b,0x0b,0x03,0x2a,0x06,0x0d,0xb3,0x93,0xfe,0xee,0xfe,0xde,0xb1,0x01,0x49,0xd2,0x9a,0x01,0x1e,0xdb,0x81,0x13,0x1a,0x31,0x1d,0x12,0x07,0x1a,0xfe,0xa4,0xff,0xfe,0xee,0xfe,0xc6,0xb9,0xc6,0xf6,0x31,0x49,0x19,0x1c,0x1d,0x15,0x22,0x33,0x5d,0x5c,0x35,0x26,0x44,0x44, 0x24,0x29,0x28,0x3e,0x1e,0x46,0x47,0x2e,0x23,0x00,0x00,0x01,0x00,0x84,0xff,0xf6,0x03,0xe8,0x05,0xa3,0x00,0x3e,0x00,0x4a,0x40,0x29,0x00,0x89,0x2c,0x23,0x89,0x0a,0x27,0x89,0x06,0x2c,0x0a,0x06,0x16,0x16,0x06,0x0a,0x2c,0x04,0x40,0x37,0x10,0x89,0x1d,0x34,0x34,0x20,0x30,0x9b,0x3b,0x06,0x0d,0x9b,0x20,0x06,0x16,0x19,0x18,0x29, 0x9a,0x03,0x18,0x00,0x3f,0xed,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x01,0x2f,0xed,0xc4,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x10,0x02,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x02,0x35, 0x34,0x12,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0x10,0x33,0x32,0x12,0x11,0x34,0x02,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x03,0xe8,0x91,0x9e,0x6b,0x60,0x0d,0x0c,0x34,0x3c,0x3c,0x30,0x34,0x35,0x08,0x1a,0x59,0x19,0x2b,0x53,0x42,0x9b,0x89,0x78,0x90,0x0c,0x0c,0x41,0x34,0x34,0x5b, 0xa1,0x60,0x23,0x46,0x47,0x20,0x09,0x20,0x14,0xab,0x62,0x95,0xeb,0x83,0x02,0xa5,0xfe,0x97,0xfe,0xba,0xb8,0xb6,0x33,0x95,0x94,0x30,0x7c,0x71,0xb2,0xb6,0x85,0xdd,0x6d,0x0f,0x1b,0x0f,0x15,0x4f,0xab,0x01,0x50,0x71,0xea,0x01,0x09,0xbd,0x9b,0x31,0x94,0x89,0x39,0xfe,0xf8,0x01,0x20,0x01,0x07,0xa6,0x01,0x23,0xa8,0x16,0x17,0x21, 0x2f,0x1e,0x18,0x31,0xc4,0xfe,0x9f,0x00,0x00,0x01,0x00,0x70,0x00,0x45,0x03,0x6c,0x05,0xa7,0x00,0x31,0x00,0x41,0xb9,0x00,0x1c,0x01,0x85,0x40,0x10,0x17,0x05,0x89,0x27,0x17,0x27,0x00,0x00,0x27,0x17,0x03,0x33,0x22,0x8b,0x14,0x22,0xb8,0x01,0x81,0xb5,0x11,0x2f,0x11,0x2f,0x19,0x27,0xb8,0x01,0x80,0xb2,0x0a,0x19,0x07,0x00,0x3f, 0xd4,0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xec,0x10,0xed,0x31,0x30,0x01,0x14,0x07,0x06,0x06,0x07,0x0e,0x02,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x13,0x01,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x01,0x37,0x37,0x32,0x17,0x17,0x32,0x37, 0x3e,0x04,0x17,0x32,0x16,0x03,0x6c,0x2e,0x24,0x56,0x16,0x1b,0x17,0x20,0x0f,0x26,0x47,0x47,0x23,0x24,0x3f,0x3f,0x20,0x1d,0x27,0x67,0x01,0x43,0x09,0x44,0x23,0x31,0x12,0x14,0x26,0x57,0xfe,0xef,0x39,0x34,0x0e,0x65,0x20,0x11,0x21,0x0e,0x1f,0x0e,0x54,0x20,0x17,0x1f,0x4e,0x02,0xc6,0x14,0x4c,0x4b,0xd1,0x55,0x69,0x2a,0x1d,0x0f, 0x0e,0x0e,0x0f,0x25,0x26,0x30,0x01,0x24,0x03,0xa9,0x1a,0x1a,0x13,0x0e,0x34,0x2f,0x5b,0xe2,0xfd,0x1f,0x07,0x04,0x10,0x03,0x68,0x2d,0x60,0x25,0xd5,0x34,0x03,0x27,0x00,0x01,0x00,0x84,0xff,0xc3,0x03,0x33,0x05,0xa7,0x00,0x37,0x00,0x3f,0x40,0x21,0x00,0x1f,0x2d,0x89,0x0e,0x33,0x89,0x08,0x1f,0x0e,0x08,0x08,0x0e,0x1f,0x03,0x39, 0x14,0x89,0x27,0x36,0x9a,0x02,0x1c,0x02,0x1c,0x2a,0x17,0x9a,0x23,0x11,0x9b,0x2a,0x07,0x00,0x3f,0xed,0xd4,0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x14,0x06,0x23,0x27,0x26,0x23,0x22,0x35,0x34,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x02, 0x11,0x10,0x12,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x02,0x35,0x10,0x12,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x03,0x07,0x25,0x0d,0x22,0x5d,0x3d,0x3b,0x21,0x33,0x40,0x16,0x3c,0x30,0x72,0x79,0x73,0x66,0x4c,0x31,0x35,0x09,0x10,0x16,0x42,0x5d,0x89,0x4e, 0x72,0xa8,0x5b,0xe6,0xd5,0x6e,0x86,0x2e,0x55,0x0e,0x13,0x24,0x33,0x21,0x01,0x94,0x13,0x4e,0x04,0x12,0x3b,0x18,0x54,0x81,0xdb,0x97,0x48,0x72,0x80,0xfe,0x9f,0xfe,0xc4,0xfe,0xf4,0xfe,0xda,0x3c,0x40,0x0b,0x3a,0x19,0x21,0x61,0x3d,0xa4,0x01,0x3b,0xde,0x01,0x85,0x01,0xa2,0xd1,0xab,0x4c,0xc0,0xe1,0x23,0x29,0x0e,0x10,0x0f,0x0b, 0x08,0x00,0x00,0x02,0x00,0x60,0xff,0xe7,0x04,0xa2,0x04,0x19,0x00,0x0b,0x00,0x17,0x00,0x23,0x40,0x0d,0x09,0x89,0x15,0x15,0x19,0x0f,0x89,0x03,0x0c,0x9b,0x06,0x06,0x12,0xb8,0x01,0x7f,0xb1,0x00,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x00,0x35,0x10,0x00,0x21,0x32,0x00,0x15,0x14, 0x00,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x81,0xf5,0xfe,0xd4,0x01,0x2c,0x01,0x01,0xf8,0x01,0x1d,0xfe,0xdf,0xfa,0xb3,0xcc,0xd0,0xaf,0xb5,0xbe,0xbe,0x19,0x01,0x21,0xec,0x01,0x02,0x01,0x23,0xfe,0xe7,0xfc,0xfb,0xfe,0xde,0x03,0xa6,0xd9,0xba,0xb5,0xd2,0xcb,0xc0,0xc1,0xce,0x00,0x00,0x01,0x00,0x50, 0xff,0xe7,0x03,0x44,0x04,0x19,0x00,0x15,0x00,0x28,0x40,0x0b,0x0a,0x00,0x05,0x89,0x10,0x0b,0x15,0x0b,0x15,0x02,0x0d,0xb8,0x01,0x7f,0xb5,0x08,0x19,0x13,0x9b,0x02,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x01,0x2f,0xed,0xc4,0x32,0x31,0x30,0x13,0x36,0x33,0x32,0x12,0x15,0x10,0x00,0x23,0x22,0x27,0x35,0x16,0x33, 0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x56,0x72,0x9e,0xdf,0xff,0xfe,0xf8,0xf2,0x8e,0x6c,0x69,0x8f,0xa9,0xad,0xa1,0x9d,0x96,0x74,0x03,0xd3,0x46,0xfe,0xe5,0xf6,0xfe,0xfc,0xfe,0xe3,0x38,0xa2,0x4e,0xd0,0xc7,0xbe,0xc5,0x56,0x00,0x02,0x00,0x2d,0xfd,0x6d,0x03,0xe5,0x04,0x19,0x00,0x1c,0x00,0x27,0x00,0x50,0xb9,0x00,0x0d,0x01, 0x83,0x40,0x0b,0x25,0x19,0x8a,0x0b,0x25,0x0b,0x25,0x0b,0x29,0x03,0x20,0xb8,0x01,0x83,0xb3,0x13,0x03,0x04,0x22,0xb8,0x01,0x7d,0x40,0x11,0x10,0x0d,0x10,0x16,0x04,0x10,0x04,0x10,0x00,0x1d,0x9b,0x16,0x06,0x06,0x9a,0x00,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x33,0x01,0x2f,0xed, 0xc4,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x36,0x35,0x11,0x34,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x10,0x00,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0xb0,0x7b,0xb8,0x50,0xa8,0xdf,0x77,0xb4,0x63,0x1d,0x0c, 0x73,0x60,0x64,0x71,0x80,0x86,0xb6,0xb8,0xfe,0xd1,0x68,0x2f,0x33,0x60,0x2b,0x33,0x31,0xfd,0x6d,0x23,0x28,0xaa,0x6c,0x79,0xe6,0x9d,0x02,0x25,0xb3,0x65,0x59,0x65,0x70,0x61,0x6d,0x6a,0xe8,0xdd,0xfd,0x9e,0xfe,0xce,0xfe,0xad,0x06,0x3d,0x35,0x31,0x5f,0x34,0x2d,0x30,0x34,0x00,0x00,0x01,0x00,0x50,0xfd,0x6d,0x03,0xd7,0x04,0x19, 0x00,0x25,0x00,0x40,0x40,0x18,0x1c,0x27,0x13,0x0a,0x25,0x10,0x89,0x05,0x19,0x99,0x1e,0x19,0x0b,0x0a,0x15,0x00,0x13,0x0a,0x00,0x0a,0x00,0x0d,0x25,0x02,0xb8,0x01,0x7f,0xb5,0x13,0x18,0x08,0x9b,0x0d,0x06,0x00,0x3f,0xed,0x3f,0xed,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x3f,0xed,0x01,0x2f,0xed,0xc4,0x32,0x39, 0x10,0xc6,0x31,0x30,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x10,0x00,0x21,0x23,0x27,0x17,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x04,0x27,0x50,0x78,0xa2,0xc0,0xc6,0xb9,0xb2,0xad,0x82,0x7d,0xb2,0xf7,0x01,0x1a,0xfe,0xdd,0xfe,0xf1,0x1a,0x19,0x53,0xb6,0xe0,0x44,0x43, 0x36,0x36,0x59,0x49,0x94,0x8f,0x87,0x78,0x66,0x27,0xc1,0x4e,0xd0,0xc7,0xbe,0xc5,0x56,0x9c,0x46,0xfe,0xe4,0xf5,0xfe,0xfc,0xfe,0xe3,0x02,0x5d,0xd2,0xb8,0x1b,0x90,0x20,0x52,0x80,0x9c,0x94,0x7b,0x1e,0x00,0x00,0x01,0x00,0x60,0xfd,0x6d,0x03,0xe5,0x04,0x19,0x00,0x21,0x00,0x46,0x40,0x1d,0x1f,0x0a,0x0e,0x89,0x0f,0x12,0x0f,0x0a, 0x0f,0x0a,0x0f,0x23,0x03,0x89,0x17,0x1e,0x1f,0x12,0x09,0x1f,0x09,0x1f,0x14,0x00,0x9b,0x1b,0x06,0x0a,0x06,0xb8,0x01,0x7f,0xb3,0x14,0x18,0x0f,0x18,0x00,0x3f,0x3f,0xed,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x22,0x06,0x15, 0x14,0x16,0x33,0x32,0x24,0x37,0x15,0x03,0x06,0x02,0x07,0x23,0x36,0x12,0x01,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x02,0x75,0xb0,0xbf,0x9e,0x9b,0x57,0x01,0x09,0x46,0xcd,0xa7,0xaf,0x26,0xbb,0x3e,0xea,0x01,0x24,0x6d,0x8b,0xd4,0xfe,0xff,0x84,0xf5,0x98,0x73,0xbf,0x3c,0x41,0xcd,0x03,0x8f, 0xa9,0x9c,0x93,0x98,0x3e,0x24,0x9c,0xfe,0xf7,0xd5,0xfe,0xe1,0x7b,0xa9,0x01,0x5d,0x01,0x50,0x30,0xed,0xce,0x87,0xd2,0x72,0x26,0x20,0x9c,0x29,0x2f,0x00,0x00,0x01,0x00,0x60,0xfd,0x6d,0x05,0xb0,0x04,0x19,0x00,0x32,0x00,0x59,0xb9,0x00,0x0a,0x01,0x84,0x40,0x21,0x05,0x18,0x17,0x2b,0x2b,0x1f,0x00,0x8a,0x0f,0x22,0x05,0x0f,0x0f, 0x05,0x22,0x03,0x34,0x1f,0x89,0x24,0x21,0x22,0x2b,0x18,0x07,0x22,0x18,0x18,0x22,0x07,0x03,0x28,0x0d,0xb8,0x01,0x7f,0xb7,0x02,0x19,0x14,0x1b,0x9b,0x2e,0x28,0x06,0x00,0x3f,0x33,0xed,0x32,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x12,0x39,0x11,0x33, 0x33,0x10,0xed,0x31,0x30,0x01,0x10,0x23,0x22,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x10,0x17,0x15,0x24,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x05,0xb0,0xfa,0x6c,0x79,0x14,0x83,0x0e, 0x2e,0x26,0x5e,0x29,0x5c,0x52,0x60,0x6f,0x0e,0x9e,0x0e,0x6d,0x60,0x51,0x5c,0x2a,0xbf,0xfe,0x99,0x4e,0xa8,0x89,0x78,0x8a,0x29,0x29,0x8b,0x77,0x88,0xa5,0x4e,0xfe,0x81,0xfe,0xec,0x75,0x64,0x50,0x24,0x2f,0x2d,0x30,0x32,0x8b,0x03,0x79,0xb0,0x91,0x4c,0x75,0x8b,0x8a,0x76,0x4b,0x90,0xb0,0xfe,0xa5,0x24,0x9c,0x48,0x01,0xd3,0xca, 0xdb,0x72,0x60,0x75,0x74,0x61,0x70,0xda,0xcf,0x00,0x00,0x01,0x00,0x77,0xff,0xe7,0x04,0x35,0x07,0x62,0x00,0x31,0x00,0x50,0x40,0x26,0x19,0x8b,0x0d,0x1f,0x89,0x06,0x0d,0x06,0x13,0x2c,0x2c,0x13,0x06,0x0d,0x04,0x33,0x31,0x8a,0x26,0x12,0x06,0x19,0x22,0x13,0x13,0x22,0x2b,0x2c,0x2c,0x10,0x2e,0x9b,0x29,0x16,0x9b,0x10,0x06,0x03, 0xb8,0x01,0x7f,0xb1,0x22,0x19,0x00,0x3f,0xed,0x3f,0xed,0xd4,0xed,0x12,0x39,0x2f,0x33,0x11,0x39,0x2f,0x12,0x39,0x39,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x10,0x12,0x33,0x32,0x36,0x35,0x34,0x27,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15, 0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x20,0x00,0x11,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x02,0x11,0x01,0x1b,0xb1,0xc5,0x7a,0x84,0x7c,0x77,0x4b,0x32,0x1b,0x96,0x8b,0x73,0x54,0x29,0x60,0x3e,0x41,0x46,0x57,0x75,0x66,0x65,0xd8,0xcc,0xfe,0xed,0xfe,0xf9,0x01,0x3b,0x01,0x2f,0xb6,0x98,0xa5,0xa7,0xe7,0xe1, 0x02,0xe9,0xfe,0xb3,0xfe,0xd7,0x57,0x51,0x5b,0x4a,0x46,0x3b,0x45,0x4f,0x33,0x7f,0x92,0x2b,0x90,0x13,0x20,0x4c,0x39,0x33,0x55,0x43,0x3b,0x89,0x56,0xa0,0xa0,0x01,0x72,0x01,0x90,0x01,0x40,0x01,0x97,0x01,0xa2,0x4e,0xaa,0x6d,0xfe,0x9d,0xfe,0x86,0x00,0x01,0x00,0x60,0xfd,0x6d,0x06,0xec,0x04,0x19,0x00,0x32,0x00,0x5e,0x40,0x09, 0x08,0x07,0x1b,0x1b,0x0f,0x23,0x8a,0x32,0x2b,0xb8,0x01,0x83,0x40,0x21,0x2a,0x12,0x32,0x2a,0x2a,0x32,0x12,0x03,0x34,0x0f,0x89,0x14,0x04,0x0b,0x9b,0x18,0x11,0x12,0x1b,0x08,0x18,0x2a,0x12,0x08,0x08,0x12,0x2a,0x03,0x30,0x1e,0x18,0x06,0x25,0xb8,0x01,0x7f,0xb1,0x30,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f, 0x11,0x12,0x39,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x12,0x39,0x11,0x33,0x33,0x31,0x30,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x10,0x17,0x15,0x24,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x11, 0x14,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x23,0x22,0x11,0x05,0x0c,0x29,0x5c,0x52,0x60,0x6f,0x0e,0x9e,0x0e,0x6d,0x60,0x51,0x5c,0x2a,0xbf,0xfe,0x99,0x4e,0xa8,0x89,0x78,0x8a,0x29,0x29,0x8b,0x77,0x88,0xa5,0x4e,0x5e,0x27,0x2d,0x0e,0x83,0x15,0x79,0x6d,0xfa,0x02,0x00,0xb0,0x91,0x4c,0x75,0x8b,0x8a,0x76,0x4b, 0x90,0xb0,0xfe,0xa5,0x24,0x9c,0x48,0x01,0xd3,0xca,0xdb,0x72,0x60,0x75,0x74,0x61,0x70,0xda,0xcf,0xfc,0x85,0x89,0x32,0x30,0x2d,0x2f,0x26,0x3e,0x70,0x79,0x01,0x14,0x00,0x01,0x00,0x0a,0x00,0x00,0x04,0x3f,0x04,0x00,0x00,0x0e,0x00,0x2a,0x40,0x14,0x0b,0x89,0x08,0x07,0x00,0x00,0x04,0x0c,0x0c,0x10,0x03,0x89,0x04,0x00,0x04,0x07, 0x06,0x0c,0x04,0x18,0x00,0x3f,0x33,0x3f,0x12,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x12,0x39,0x11,0x33,0x33,0xed,0x31,0x30,0x01,0x06,0x02,0x07,0x23,0x36,0x12,0x37,0x33,0x16,0x12,0x17,0x23,0x26,0x02,0x02,0x25,0x2b,0xc5,0x6e,0xbd,0x9a,0xf7,0x36,0xa8,0x3b,0xf2,0x99,0xbc,0x71,0xc3,0x03,0x31,0xbc,0xfe,0x3c,0xb1,0xe1,0x02,0x2e, 0xf1,0xfe,0xfd,0xe1,0xe3,0xb6,0x01,0xc4,0x00,0x01,0x00,0x60,0xfd,0x6d,0x04,0x25,0x04,0x19,0x00,0x24,0x00,0x4d,0xb9,0x00,0x0e,0x01,0x85,0x40,0x12,0x09,0x05,0x89,0x14,0x09,0x14,0x20,0x20,0x14,0x09,0x03,0x26,0x1a,0x89,0x00,0x20,0x1f,0x11,0xb8,0x01,0x7e,0x40,0x11,0x07,0x1f,0x07,0x0b,0x0b,0x07,0x1f,0x03,0x02,0x1d,0x9a,0x22, 0x19,0x17,0x9b,0x02,0x06,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x10,0x21,0x32,0x16,0x15,0x10,0x21,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x11,0x10,0x12, 0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x00,0x60,0x02,0x11,0xd1,0xe3,0xfe,0xcd,0xfa,0x08,0xa0,0x08,0x2b,0x35,0x48,0x3d,0x8b,0x81,0xb3,0xb6,0xf8,0xe9,0x8f,0x86,0x7e,0x9f,0xfe,0xc4,0xfe,0xbb,0x01,0x29,0x02,0xf0,0xea,0xdb,0xfe,0x62,0xdd,0x30,0x12,0x18,0x27,0x2f,0x30,0x8e,0x8b,0x9b,0xa2,0xfe,0xd6,0xfe,0xbc,0xfe,0x74,0xfe,0x65, 0x52,0xa0,0x3d,0x01,0xe3,0x00,0x00,0x01,0x00,0x60,0xff,0xe7,0x04,0x7b,0x05,0xfa,0x00,0x22,0x00,0x4b,0xb1,0x03,0x0e,0xb8,0x01,0x84,0x40,0x19,0x0f,0x0a,0x89,0x05,0x0f,0x1b,0x05,0x05,0x1b,0x0f,0x03,0x24,0x15,0x89,0x20,0x1b,0x1a,0x03,0x0f,0x1a,0x0f,0x1a,0x0f,0x00,0x18,0xb8,0x01,0x7f,0xb6,0x1d,0x19,0x12,0x9b,0x07,0x00,0x06, 0x00,0x3f,0xc6,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x31,0x30,0x01,0x32,0x16,0x17,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x06,0x07,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x00,0x11, 0x34,0x12,0x02,0x29,0x68,0xa6,0x29,0x75,0x3f,0xb0,0x35,0x2f,0x54,0x75,0x8d,0x6e,0x5d,0x8d,0x98,0xad,0xa9,0x82,0x76,0x6c,0x8e,0xf2,0xfe,0xf8,0xf2,0x04,0x19,0x5f,0x56,0xa4,0xfc,0x8b,0x6b,0x6a,0x8e,0x65,0xa9,0x9a,0x97,0x5b,0x6f,0xce,0xb5,0xc7,0xd0,0x4e,0xa2,0x38,0x01,0x1a,0x01,0x07,0xfc,0x01,0x15,0x00,0x00,0x03,0x00,0x82, 0xff,0xe8,0x05,0x70,0x06,0xd0,0x00,0x1a,0x00,0x26,0x00,0x33,0x00,0x5c,0xbc,0x00,0x1b,0x01,0x85,0x00,0x27,0x00,0x00,0x01,0x85,0xb2,0x1a,0x05,0x14,0xb8,0x01,0x85,0x40,0x0f,0x13,0x2e,0x8a,0x21,0x27,0x1a,0x13,0x21,0x21,0x13,0x1a,0x27,0x04,0x35,0x0c,0xb8,0x01,0x85,0x40,0x12,0x0b,0x16,0x10,0x99,0x05,0x1a,0x13,0x0b,0x02,0x09, 0x2b,0x9b,0x24,0x06,0x31,0x99,0x1e,0x19,0x00,0x3f,0xed,0x3f,0xed,0xde,0x32,0xcd,0x32,0x32,0x39,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x02,0x21,0x22,0x26,0x27,0x0e,0x02,0x23,0x20,0x03,0x33,0x14,0x16,0x16,0x33,0x32,0x36,0x35,0x33,0x12,0x33, 0x32,0x36,0x36,0x35,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x03,0x34,0x26,0x26,0x23,0x22,0x00,0x15,0x14,0x00,0x33,0x32,0x00,0x05,0x70,0x01,0xfe,0x9f,0x59,0x9d,0x1f,0x0f,0x53,0x76,0x3c,0xfe,0x9e,0x01,0xa1,0x1f,0x5a,0x49,0x63,0x62,0xa1,0x02,0xc0,0x47,0x5a,0x21,0x99,0xfe,0x94,0xfe,0xfd,0xfe,0xfd,0xfe, 0x94,0x01,0x6d,0x01,0x02,0x01,0x01,0x01,0x6e,0xa1,0x7e,0xd5,0x7b,0xbc,0xfe,0xef,0x01,0x0c,0xc1,0xc5,0x01,0x09,0x06,0xd0,0xfe,0x51,0x57,0x4e,0x2c,0x4e,0x2b,0x01,0xaf,0x62,0x7a,0x42,0x86,0x98,0xfe,0xe2,0x3e,0x75,0x6b,0xfb,0x87,0xfe,0xfd,0xfe,0x94,0x01,0x6e,0x01,0x01,0x01,0x01,0x01,0x6e,0xfe,0x94,0xfe,0xfd,0x80,0xdb,0x83, 0xfe,0xe3,0xc1,0xbe,0xfe,0xe0,0x01,0x23,0x00,0x01,0x00,0xf0,0x00,0x00,0x01,0x91,0x06,0xd0,0x00,0x03,0x00,0x12,0xb9,0x00,0x00,0x01,0x85,0xb3,0x01,0x02,0x01,0x18,0x00,0x3f,0xcd,0x01,0x2f,0xed,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x91,0xa1,0xa1,0x06,0xd0,0x00,0x04,0x00,0x64,0xff,0xe8,0x06,0x29,0x06,0xe8,0x00,0x20,0x00,0x2c, 0x00,0x38,0x00,0x45,0x00,0x81,0xb9,0x00,0x14,0x01,0x84,0xb4,0x39,0x21,0x89,0x27,0x18,0xbb,0x01,0x85,0x00,0x09,0x00,0x3f,0x01,0x84,0x40,0x37,0x0e,0x00,0x39,0x27,0x09,0x0e,0x0e,0x09,0x27,0x39,0x00,0x05,0x47,0x2d,0x89,0x33,0x3c,0x9b,0x11,0x43,0x00,0x20,0x06,0x9b,0x1a,0x24,0x30,0x2a,0x36,0x17,0x0a,0x18,0x20,0x1a,0x0a,0x36, 0x43,0x20,0x1a,0x30,0x36,0x36,0x30,0x1a,0x20,0x04,0x09,0x43,0x06,0x09,0x18,0x1e,0x99,0x02,0x19,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x11,0x33,0x11,0x33,0x11,0x33,0x10,0xed,0x11,0x33,0x10,0xd4,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10, 0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x25,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x23,0x11,0x26,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x14,0x06,0x07,0x11,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16, 0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x36,0x06,0x29,0x73,0x9d,0x78,0x9b,0x86,0x4c,0x9d,0x5e,0xa2,0x72,0x50,0x49,0xcb,0x90,0x90,0xca,0x01,0x8f,0x7b,0x79,0x91,0x6f,0x9e,0x85,0x4d,0x6b,0x4b,0xfd,0x93,0x3d,0x2d,0x2d,0x3e,0x3e,0x2d,0x2c,0x3e,0xfd,0xd0,0x3e,0x2d,0x2b,0x40,0x40,0x2b,0x2d,0x3e,0x01,0x77, 0x76,0x54,0x50,0x7a,0x3a,0x3d,0x53,0x54,0x76,0x69,0x81,0x6d,0x5a,0xaf,0x04,0x3a,0x1d,0x5d,0x62,0x77,0x90,0xcb,0xcc,0x8f,0x78,0xbb,0x20,0xfc,0xa4,0x61,0x6b,0x5b,0x5b,0x01,0xe4,0x2d,0x3d,0x3e,0x2c,0x2d,0x3e,0x3e,0x2d,0x2c,0x3e,0x3d,0x2d,0x2e,0x3d,0x3e,0x02,0xa8,0x56,0x74,0x71,0x59,0x53,0x3d,0x3a,0x72,0x00,0x02,0x00,0x64, 0x00,0x00,0x04,0xfa,0x06,0xe8,0x00,0x29,0x00,0x35,0x00,0x6f,0xb1,0x16,0x22,0xbb,0x01,0x84,0x00,0x2a,0x00,0x04,0x01,0x85,0xb2,0x05,0x25,0x00,0xb8,0x01,0x84,0x40,0x0f,0x0b,0x12,0x27,0x0b,0x2a,0x05,0x0e,0x0b,0x0b,0x0e,0x05,0x2a,0x04,0x37,0x30,0xb8,0x01,0x84,0x40,0x1b,0x1c,0x33,0x99,0x19,0x2d,0x9b,0x1f,0x22,0x07,0x03,0x9b, 0x06,0x27,0x0e,0x9b,0x0f,0x06,0x0f,0x06,0x0f,0x05,0x16,0x9b,0x22,0x06,0x05,0x18,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xed,0x33,0x10,0xdd,0xed,0xd4,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x39,0x33,0x10,0xed,0x32,0x10,0xed,0x10,0xed,0x32,0x31,0x30,0x01,0x10,0x21,0x23,0x11, 0x23,0x11,0x21,0x32,0x36,0x35,0x34,0x26,0x26,0x23,0x35,0x20,0x36,0x35,0x34,0x26,0x23,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x20,0x15,0x14,0x07,0x15,0x16,0x01,0x34,0x26,0x27,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xfa,0xfe,0x8f,0x5f,0xa1,0x01,0x00,0x79,0x67,0x43,0xa7,0xa1,0x01,0x02, 0x89,0x71,0x6f,0x76,0x19,0xbb,0x80,0x8c,0xcf,0xcb,0x90,0x7c,0xbf,0x19,0x76,0x01,0x71,0xc5,0xc5,0xfd,0x8f,0x76,0x54,0x51,0x79,0x6f,0x5b,0x56,0x74,0x03,0x16,0xfe,0xf9,0xfd,0xf1,0x02,0xa0,0x40,0x4a,0x34,0x3b,0x12,0x91,0x42,0x4d,0x4c,0x2f,0x75,0xa0,0xc7,0x95,0x90,0xcb,0x9c,0x75,0xf8,0xb6,0x32,0x07,0x35,0x01,0xd2,0x55,0x74, 0x01,0x71,0x59,0x51,0x79,0x76,0x00,0x01,0x00,0xb4,0x00,0x00,0x05,0x0a,0x06,0xd0,0x00,0x12,0x00,0x5c,0xb1,0x11,0x04,0xb8,0x01,0x85,0xb5,0x05,0x0e,0x05,0x0b,0x0a,0x00,0xb8,0x01,0x85,0x40,0x0a,0x01,0x05,0x0a,0x01,0x01,0x0a,0x05,0x03,0x14,0x0d,0xb8,0x01,0x85,0x40,0x16,0x07,0x03,0x07,0x9b,0x11,0x0d,0x0a,0x0b,0x0d,0x0f,0x0b, 0x0b,0x0f,0x0d,0x03,0x0c,0x01,0x05,0x18,0x08,0x0c,0x07,0x00,0x3f,0xcd,0x3f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0xed,0x32,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x01,0x07,0x01,0x11,0x21,0x11, 0x33,0x11,0x21,0x05,0x0a,0xa1,0xfe,0xc7,0xa1,0xfe,0x25,0xa3,0x01,0xa5,0x72,0xfe,0xcb,0x01,0x3a,0xa1,0x01,0xda,0x02,0x48,0xfd,0xb8,0x02,0x48,0x04,0x88,0xfe,0x58,0x72,0x01,0x39,0xfc,0xea,0x01,0x22,0xfe,0xde,0x00,0x00,0x01,0x00,0xb4,0xff,0xe9,0x04,0xc6,0x06,0xd0,0x00,0x1b,0x00,0x4b,0xb9,0x00,0x00,0x01,0x84,0x40,0x0d,0x12, 0x11,0x07,0x04,0x11,0x11,0x04,0x07,0x03,0x1d,0x14,0x10,0x0d,0xb8,0x01,0x85,0x40,0x13,0x0e,0x0a,0x9b,0x11,0x12,0x14,0x18,0x12,0x18,0x12,0x0e,0x0f,0x13,0x07,0x0e,0x18,0x04,0x03,0x19,0x00,0x3f,0x33,0x3f,0x3f,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x39,0x11,0x33,0xed,0x01,0x2f,0xed,0x32,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33, 0xed,0x31,0x30,0x01,0x14,0x06,0x07,0x27,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x00,0x07,0x23,0x11,0x33,0x01,0x07,0x01,0x11,0x36,0x37,0x36,0x33,0x32,0x16,0x16,0x04,0xc6,0xd5,0x96,0x37,0x7c,0x95,0x86,0x70,0xd8,0xfe,0xef,0x01,0xa1,0xa3,0x01,0xa6,0x72,0xfe,0xca,0x51,0x87,0x7f,0x93,0x71,0xb5,0x61,0x01,0xa6,0x9a,0xf6,0x2d,0x7b, 0x21,0xb4,0x6d,0x62,0x74,0xfe,0x82,0xfe,0x06,0xd0,0xfe,0x58,0x72,0x01,0x39,0xfb,0xf9,0x89,0x47,0x47,0x51,0x9e,0x00,0x02,0x00,0x64,0xff,0xe8,0x03,0xfa,0x06,0xd0,0x00,0x1a,0x00,0x26,0x00,0x5e,0xb9,0x00,0x00,0x01,0x84,0x40,0x13,0x1b,0x21,0x1b,0x21,0x1b,0x05,0x28,0x07,0x0a,0x14,0x11,0x04,0x08,0x12,0x12,0x08,0x0e,0x08,0x16, 0xb8,0x01,0x85,0x40,0x18,0x05,0x1e,0x9b,0x18,0x14,0x08,0x9b,0x09,0x11,0x09,0x16,0x18,0x09,0x18,0x09,0x03,0x0c,0x99,0x0f,0x06,0x24,0x99,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x39,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x01,0x2f,0xed,0xc6,0xc4,0x11,0x39,0x2f,0x12,0x17,0x39,0x11,0x12,0x39,0x39,0x2f,0x2f, 0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x20,0x11,0x10,0x13,0x21,0x35,0x21,0x36,0x37,0x21,0x15,0x21,0x06,0x07,0x21,0x15,0x21,0x02,0x11,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xfa,0xcc,0x8f,0xfe,0x6e,0x7d,0xfe,0xda,0x01,0x61,0x47,0x7a,0x01,0x74,0xfe,0xf2,0x47,0x2f,0x01,0x2f, 0xfe,0x94,0x8b,0x69,0x88,0x8f,0xcc,0x91,0x72,0x58,0x59,0x72,0x70,0x5b,0x5a,0x70,0x01,0x44,0x90,0xcc,0x02,0x57,0x01,0x2d,0x01,0x53,0x92,0xa2,0xdd,0x92,0x83,0x6a,0x92,0xfe,0xa1,0xfe,0xde,0x60,0xcc,0x8e,0x50,0x79,0x78,0x51,0x50,0x7b,0x7a,0x00,0x00,0x02,0x00,0x00,0xff,0xe8,0x05,0x9d,0x06,0xe8,0x00,0x1f,0x00,0x2b,0x00,0x5a, 0xb5,0x0a,0x8a,0x16,0x08,0x16,0x0d,0xb8,0x01,0x84,0xb7,0x26,0x16,0x26,0x16,0x26,0x2d,0x00,0x20,0xb8,0x01,0x84,0x40,0x1b,0x13,0x0a,0x16,0x16,0x1f,0x29,0x29,0x10,0x1f,0x19,0x9b,0x06,0x08,0x06,0x08,0x06,0x1f,0x1d,0x9b,0x02,0x17,0x1f,0x07,0x23,0x99,0x10,0x19,0x00,0x3f,0xed,0x3f,0x33,0xdd,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10, 0xed,0x11,0x12,0x39,0x2f,0x12,0x39,0x11,0x33,0x01,0x2f,0xed,0xc6,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x31,0x30,0x11,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x33,0x11,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x11,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x01,0x14,0x16,0x33,0x32,0x36, 0x35,0x34,0x26,0x23,0x22,0x06,0x73,0x9d,0x76,0x9d,0x83,0x4e,0x9e,0x5d,0xa3,0x75,0x96,0xca,0x92,0x8f,0xcc,0x98,0x72,0x77,0x93,0x70,0x9d,0x85,0x4c,0x69,0x4e,0x03,0x26,0x77,0x53,0x54,0x77,0x78,0x53,0x53,0x77,0x06,0x67,0x81,0x6d,0x5b,0xb0,0xfb,0xc5,0x1c,0xc0,0x76,0x90,0xcb,0xca,0x91,0x77,0xc0,0x1b,0x03,0x5d,0x62,0x6c,0x5b, 0x5b,0xfb,0x47,0x53,0x77,0x76,0x54,0x54,0x76,0x77,0x00,0x04,0x00,0x82,0xff,0xe8,0x04,0x4e,0x06,0x83,0x00,0x0b,0x00,0x17,0x00,0x2d,0x00,0x39,0x00,0x6f,0x40,0x0a,0x34,0x8a,0x1e,0x0c,0x89,0x12,0x00,0x89,0x06,0x18,0xb8,0x01,0x85,0x40,0x11,0x2e,0x20,0x12,0x2c,0x06,0x2e,0x1e,0x12,0x06,0x2e,0x2e,0x06,0x12,0x1e,0x04,0x22,0x2a, 0xbb,0x01,0x85,0x00,0x29,0x00,0x23,0x01,0x85,0x40,0x11,0x22,0x31,0x9b,0x2c,0x20,0x26,0x26,0x1b,0x22,0x09,0x15,0x03,0x0f,0x29,0x22,0x06,0x37,0xb8,0x01,0x80,0xb1,0x1b,0x19,0x00,0x3f,0xed,0x3f,0x33,0xde,0x32,0xcd,0x32,0x11,0x12,0x39,0x2f,0x39,0x39,0xed,0x01,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12, 0x39,0x11,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x37,0x26,0x03,0x33,0x16,0x16,0x33,0x32,0x36,0x37,0x33,0x02,0x07,0x16,0x03,0x34,0x26,0x23,0x22, 0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x13,0x3d,0x2d,0x2e,0x3d,0x3e,0x2d,0x2c,0x3e,0xfd,0x7f,0x3d,0x2d,0x2e,0x3d,0x3e,0x2d,0x2c,0x3e,0x02,0xbc,0xfe,0xe6,0xcc,0xcc,0xfe,0xe6,0xda,0xd9,0x01,0xa2,0x01,0xbd,0x86,0x87,0xbd,0x01,0xa1,0x02,0xd8,0xda,0xa1,0xbf,0x86,0x86,0xbe,0xbf,0x85,0x86,0xbf,0x06,0x18,0x2b,0x40,0x40,0x2b, 0x2d,0x3e,0x3e,0x2d,0x2b,0x40,0x40,0x2b,0x2d,0x3e,0x3e,0xfb,0x8c,0xc7,0xfe,0xde,0x01,0x20,0xc9,0x01,0x02,0x95,0x93,0x01,0x00,0x7e,0xc5,0xc7,0x7c,0xfe,0xff,0x92,0x95,0xfe,0xfe,0x7f,0xc7,0xc6,0x80,0x83,0xc5,0xc7,0x00,0x03,0x00,0x64,0xff,0xe9,0x05,0xdd,0x06,0xe8,0x00,0x28,0x00,0x35,0x00,0x41,0x00,0x82,0xb9,0x00,0x30,0x01, 0x84,0x40,0x11,0x23,0x0d,0x0d,0x3b,0x06,0x89,0x36,0x04,0x08,0x8b,0x12,0x1d,0x12,0x20,0x03,0x23,0x00,0xb8,0x01,0x84,0x40,0x0c,0x29,0x23,0x36,0x12,0x29,0x29,0x12,0x36,0x23,0x04,0x43,0x3b,0xb8,0x01,0x85,0xb5,0x17,0x2d,0x9b,0x26,0x33,0x3f,0xb8,0x01,0x81,0x40,0x14,0x14,0x38,0x9b,0x1b,0x20,0x03,0x1d,0x36,0x06,0x12,0x06,0x1b, 0x14,0x1b,0x14,0x1b,0x0c,0x33,0x06,0x0d,0xb8,0x01,0x80,0xb1,0x0c,0x19,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x10,0xed,0x10,0xed,0x10,0xd4,0xed,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x39,0x39,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x12,0x39,0x2f,0x10,0xed,0x31,0x30,0x01,0x14, 0x06,0x07,0x15,0x14,0x07,0x16,0x15,0x14,0x06,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x27,0x06,0x21,0x22,0x24,0x27,0x34,0x37,0x36,0x33,0x20,0x17,0x36,0x35,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x32,0x16,0x07,0x34,0x27,0x26,0x23,0x22,0x06,0x07,0x14,0x16,0x33,0x32,0x36,0x01,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x20,0x37, 0x05,0xdd,0x92,0x81,0x2f,0x2f,0x79,0xf2,0x98,0xb0,0xc2,0x07,0xb5,0xfe,0xc7,0xcb,0xfe,0xec,0x01,0x8b,0x8a,0xcb,0x01,0x38,0xb6,0x07,0x01,0x7c,0x96,0xca,0x91,0x90,0xcc,0x92,0x3b,0x3a,0x55,0x55,0x74,0x01,0x71,0x59,0x56,0x74,0xfe,0x9f,0x8c,0xfe,0xe6,0x87,0xb8,0x57,0x93,0x55,0x01,0x1b,0x8b,0x05,0x8d,0x76,0xc2,0x1d,0x18,0x86, 0x74,0x72,0x88,0x9d,0xeb,0x9e,0x1d,0xa1,0x2b,0xd7,0xa0,0x28,0x29,0xc4,0xd8,0x95,0x97,0x6a,0x6c,0xc3,0x28,0x28,0x18,0x1d,0xbf,0x79,0x90,0xca,0x01,0xcc,0x8f,0x57,0x38,0x3b,0x76,0x54,0x51,0x79,0x76,0xfd,0xef,0xc2,0x74,0x50,0x32,0x5e,0x33,0xc1,0x00,0x02,0x00,0x67,0xff,0xe7,0x04,0x72,0x05,0xb2,0x00,0x0f,0x00,0x1d,0x00,0x2b, 0xb9,0x00,0x0c,0x01,0x86,0xb3,0x1b,0x1b,0x1f,0x14,0xbb,0x01,0x86,0x00,0x04,0x00,0x10,0x01,0x80,0xb2,0x08,0x07,0x17,0xb8,0x01,0x80,0xb1,0x00,0x19,0x00,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x26,0x26,0x35,0x10,0x12,0x24,0x33,0x32,0x16,0x16,0x15,0x10,0x02,0x04,0x13,0x22,0x06,0x02,0x15, 0x14,0x16,0x33,0x32,0x36,0x12,0x35,0x34,0x26,0x01,0xe2,0x78,0xab,0x58,0xae,0x01,0x28,0xc1,0x69,0xaa,0x61,0xab,0xfe,0xde,0x4a,0x87,0xd4,0x86,0x75,0x70,0x81,0xd2,0x85,0x71,0x19,0x75,0xd1,0x86,0x01,0x19,0x01,0xe9,0xfd,0x6a,0xc3,0x7e,0xfe,0xcf,0xfe,0x0a,0xf9,0x05,0x2d,0xd0,0xfe,0x65,0xd5,0xa5,0xaa,0xcf,0x01,0x9b,0xd0,0xa4, 0xb1,0x00,0x00,0x01,0x00,0x84,0xff,0xe7,0x04,0x18,0x05,0xb5,0x00,0x23,0x00,0x40,0xb9,0x00,0x18,0x01,0x86,0xb2,0x0d,0x13,0x1f,0xb8,0x01,0x86,0x40,0x0d,0x06,0x0d,0x06,0x0d,0x06,0x25,0x00,0x00,0x13,0x00,0x13,0x10,0x03,0xb8,0x01,0x80,0xb2,0x21,0x19,0x16,0xb8,0x01,0x80,0xb1,0x10,0x07,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39, 0x2f,0x2f,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xfd,0xc6,0x10,0xed,0x31,0x30,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x27,0x26,0x23,0x22,0x15,0x14,0x16,0x17,0x1e,0x02,0x15,0x10,0x21,0x22,0x27,0x84,0x3b,0xbe,0x50,0x9c,0x97,0x33,0x4d,0x46,0x3a,0x1f,0xc2,0xbd,0x5d, 0x5b,0x2e,0x35,0x48,0xe4,0x34,0x54,0x49,0x30,0x1d,0xfe,0x26,0xcd,0x7b,0xb2,0x13,0x1a,0x83,0x9b,0x3a,0x7c,0x6b,0x61,0x70,0x78,0x3f,0xb2,0xb7,0x10,0x9e,0x08,0x08,0xb2,0x40,0x88,0x7b,0x6c,0x62,0x69,0x3c,0xfe,0x38,0x1d,0x00,0x00,0x01,0x00,0x67,0xff,0xe7,0x04,0x8e,0x05,0xb2,0x00,0x27,0x00,0x61,0xb9,0x00,0x19,0x01,0x86,0xb4, 0x0b,0x12,0x89,0x13,0x00,0xb8,0x01,0x85,0x40,0x0e,0x27,0x09,0x1d,0x0b,0x1d,0x13,0x27,0x27,0x13,0x1d,0x0b,0x04,0x29,0x21,0xb8,0x01,0x86,0xb2,0x06,0x09,0x1c,0xb8,0x01,0x80,0x40,0x09,0x1d,0x27,0x13,0x13,0x27,0x1d,0x03,0x03,0x16,0xb8,0x01,0x80,0xb2,0x0f,0x07,0x24,0xb8,0x01,0x80,0xb1,0x03,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12, 0x17,0x39,0x2f,0x2f,0x2f,0xed,0x39,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x02,0x00,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33, 0x32,0x12,0x13,0x04,0x8e,0x5d,0xfe,0xc9,0xde,0xcc,0xe9,0x92,0x7a,0xaa,0x64,0xc0,0x84,0xa0,0xe2,0x1d,0xac,0x18,0x7e,0x65,0x73,0x86,0x97,0x8a,0x28,0x9b,0xc0,0x97,0x7c,0xa0,0xec,0x3f,0x02,0xcf,0xfe,0x7f,0xfe,0x99,0xe4,0xca,0x85,0xd5,0x2a,0x6c,0xc4,0x6b,0xa4,0x5a,0xae,0x91,0x4b,0x56,0x6d,0x57,0x70,0x74,0x9e,0xa7,0x8f,0x7e, 0x95,0x01,0x4f,0x01,0x26,0x00,0x00,0x01,0x00,0x3f,0xff,0xe7,0x04,0x9f,0x05,0x9d,0x00,0x2c,0x00,0x5e,0xb6,0x0e,0x8a,0x1e,0x09,0x8a,0x23,0x15,0xb8,0x01,0x85,0x40,0x0d,0x14,0x1e,0x23,0x14,0x14,0x23,0x1e,0x03,0x2a,0x2e,0x03,0x01,0x29,0xb8,0x01,0x85,0x40,0x0f,0x2c,0x2a,0x2a,0x18,0x25,0x99,0x06,0x04,0x06,0x14,0x06,0x14,0x06, 0x00,0x10,0xb8,0x01,0x80,0xb6,0x1b,0x19,0x03,0x2c,0x99,0x00,0x06,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x10,0xed,0x3f,0x01,0x2f,0xc6,0xfd,0xc4,0x33,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x21,0x07,0x21,0x03,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x06, 0x15,0x14,0x33,0x32,0x36,0x37,0x37,0x33,0x07,0x0e,0x03,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x36,0x35,0x34,0x23,0x22,0x06,0x07,0x03,0x23,0x01,0x23,0xb1,0x03,0x9f,0x20,0xfd,0xc3,0x4d,0x6c,0x69,0x77,0x90,0x04,0x3d,0x21,0x52,0x2b,0x33,0x17,0x16,0xa2,0x17,0x0f,0x21,0x3e,0x68,0x57,0x70,0x6f,0x26,0x36,0x06,0x84,0x51,0x7f,0x19, 0x91,0xa1,0x01,0x12,0xc0,0x05,0x9d,0x91,0xfe,0x96,0x36,0x84,0x6e,0x10,0x26,0xfe,0xf3,0x79,0x44,0x61,0x44,0x68,0x62,0x6d,0x44,0x75,0x56,0x30,0x69,0x72,0x3a,0xab,0xf1,0x1b,0x1b,0x79,0x51,0x48,0xfd,0x52,0x05,0x0c,0x00,0x02,0x00,0x6b,0xff,0xe7,0x04,0x21,0x05,0xb0,0x00,0x14,0x00,0x21,0x00,0x4f,0xb2,0x10,0x0f,0x03,0xb8,0x01, 0x86,0x40,0x21,0x1e,0x14,0x00,0x01,0x12,0x15,0x0e,0x04,0x1e,0x0f,0x1e,0x00,0x00,0x1e,0x0f,0x03,0x23,0x19,0x89,0x09,0x00,0x0f,0x0f,0x15,0x01,0x0e,0x12,0x04,0x06,0x14,0x10,0x07,0x1b,0xb8,0x01,0x80,0xb1,0x06,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x17,0x39,0x33,0x11,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x17, 0x39,0x11,0x33,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x01,0x00,0x15,0x14,0x04,0x21,0x22,0x26,0x35,0x34,0x36,0x36,0x37,0x37,0x27,0x37,0x16,0x17,0x36,0x37,0x01,0x0e,0x02,0x15,0x14,0x21,0x32,0x36,0x35,0x34,0x02,0x27,0x04,0x20,0xff,0x00,0x01,0x01,0xfe,0xf8,0xfe,0xf2,0xcb,0xd5,0x51,0x92,0xa5,0x5f,0xaa,0x98,0x3e,0x53,0x78,0x5c, 0xfe,0xfc,0x5d,0xc5,0x69,0x01,0x0b,0xa0,0xb9,0x7d,0x56,0x05,0x4f,0xfe,0xff,0xfe,0x52,0xeb,0xec,0xe2,0xb4,0xb0,0x66,0xc6,0xcb,0xad,0x64,0xfd,0x60,0x53,0x80,0x7a,0x58,0xfe,0x16,0x4b,0xf3,0xd3,0x47,0xe8,0x9a,0x8a,0x54,0x01,0x3f,0x88,0x00,0x02,0x00,0x5c,0xff,0xe7,0x04,0x61,0x05,0xb5,0x00,0x26,0x00,0x32,0x00,0x63,0x41,0x0b, 0x00,0x30,0x01,0x86,0x00,0x21,0x00,0x04,0x01,0x84,0x00,0x1f,0x00,0x00,0x01,0x86,0x00,0x2a,0x00,0x12,0x01,0x85,0x40,0x0c,0x11,0x21,0x1f,0x2a,0x11,0x11,0x2a,0x1f,0x21,0x04,0x34,0x0b,0xb8,0x01,0x86,0x40,0x0a,0x18,0x27,0x1f,0x04,0x11,0x04,0x11,0x04,0x15,0x2d,0xb8,0x01,0x80,0xb2,0x24,0x07,0x0e,0xb8,0x01,0x80,0xb1,0x15,0x19, 0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x01,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x14,0x06,0x06,0x07,0x06,0x06,0x07,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x12,0x37,0x17,0x02,0x00,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x37,0x36,0x36,0x37, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x03,0x8f,0x51,0xa4,0x63,0x0b,0x37,0x52,0x49,0x38,0x1e,0x7b,0x7b,0x8f,0xf7,0x3f,0xa2,0x58,0xfe,0xc1,0xd5,0xc6,0xd3,0x1f,0x39,0x4c,0x51,0x45,0x0e,0x3d,0xa0,0x77,0x7f,0x92,0xfe,0x9d,0x5c,0x5f,0x3e,0x2f,0x2b,0x40,0x18,0x04,0xab, 0x4b,0x78,0x54,0x0d,0x2d,0x5e,0x5c,0x50,0x56,0x59,0x30,0x72,0x7a,0x01,0x10,0xd8,0x27,0xfe,0xdc,0xfe,0xc5,0xcb,0xbc,0x3e,0x65,0x5c,0x54,0x58,0x72,0x39,0x74,0x6b,0x77,0x9b,0x93,0xfe,0x0f,0x47,0x31,0x2b,0x41,0x43,0x30,0x35,0x48,0x00,0x00,0x01,0x00,0xd6,0xff,0xe7,0x04,0x48,0x05,0x9a,0x00,0x1e,0x00,0x3d,0xb9,0x00,0x1a,0x01, 0x85,0x40,0x0c,0x19,0x05,0x19,0x01,0x19,0x01,0x19,0x20,0x12,0x8a,0x0b,0x15,0xb8,0x01,0x80,0x40,0x0c,0x05,0x0e,0x08,0x08,0x00,0x19,0x0e,0x06,0x01,0x9a,0x00,0x19,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x31,0x30,0x05,0x27,0x36,0x36,0x37,0x37,0x06, 0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x13,0x33,0x03,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x13,0x33,0x03,0x0e,0x02,0x01,0x7d,0x10,0x98,0xae,0x2b,0x34,0x29,0x97,0x57,0x81,0xa4,0x08,0x5d,0xa1,0x5a,0x06,0x5d,0x45,0x55,0x9d,0x2d,0x6a,0xa1,0xbd,0x2e,0x81,0xca,0x19,0x87,0x0c,0xa9,0xc3,0xf1,0x1a,0x22,0x87,0x67,0x2b,0x20,0x01, 0xc6,0xfe,0x4d,0x1d,0x19,0x35,0x43,0x32,0x2a,0x02,0x05,0xfc,0x7e,0xd5,0xdf,0x77,0x00,0x01,0x00,0x59,0xff,0xe7,0x04,0x5f,0x05,0xb5,0x00,0x19,0x00,0x41,0xb2,0x0c,0x0d,0x12,0xb8,0x01,0x86,0x40,0x11,0x07,0x0d,0x07,0x0d,0x07,0x1b,0x00,0x89,0x19,0x0d,0x0c,0x19,0x0c,0x19,0x0c,0x0f,0x02,0xb8,0x01,0x80,0xb2,0x16,0x19,0x0a,0xb8, 0x01,0x80,0xb1,0x0f,0x07,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x16,0x33,0x32,0x36,0x36,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x21,0x32,0x16,0x15,0x10,0x02,0x04,0x23,0x22,0x26,0x27,0x01,0x0d,0x2e,0x9a,0x69,0xaf,0x7f, 0x4c,0x75,0x71,0x9e,0x75,0x89,0xa9,0x01,0x04,0xb1,0xcb,0xae,0xfe,0xd6,0xc0,0x8c,0xc8,0x1a,0x01,0x34,0xaf,0x7f,0xe7,0x01,0x44,0x99,0xa1,0xae,0x96,0x5a,0xda,0xf9,0xd4,0xfe,0xe8,0xfe,0x14,0xfd,0xb4,0x98,0x00,0x01,0x00,0x7b,0xff,0xe7,0x04,0x7f,0x05,0xb2,0x00,0x1a,0x00,0x3f,0x40,0x0b,0x0d,0x0c,0x1a,0x89,0x00,0x0c,0x00,0x0c, 0x00,0x1c,0x07,0xb8,0x01,0x86,0xb7,0x13,0x0d,0x0c,0x00,0x0c,0x00,0x10,0x02,0xb8,0x01,0x80,0xb2,0x17,0x07,0x0a,0xb8,0x01,0x80,0xb1,0x10,0x19,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x33,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x06,0x02,0x15,0x14,0x16,0x33, 0x32,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x10,0x12,0x24,0x33,0x32,0x16,0x17,0x03,0xcc,0x30,0x98,0x69,0xad,0x80,0x4c,0x75,0x70,0x9e,0x75,0x88,0x57,0xd3,0x82,0xaf,0xcc,0xae,0x01,0x28,0xc1,0x8d,0xc7,0x19,0x04,0x65,0xaf,0x7c,0xe7,0xfe,0xbd,0x9a,0xa5,0xaa,0x96,0x5a,0x70,0x6a,0xf9,0xd3,0x01,0x19,0x01,0xe9,0xfd,0xb6,0x96, 0x00,0x01,0x00,0x8b,0xff,0xe7,0x04,0x9b,0x05,0x9d,0x00,0x15,0x00,0x29,0xb9,0x00,0x08,0x01,0x85,0xb4,0x07,0x07,0x17,0x13,0x00,0xb8,0x01,0x86,0xb4,0x0f,0x07,0x12,0x06,0x03,0xb8,0x01,0x80,0xb1,0x0c,0x19,0x00,0x3f,0xed,0x3f,0x33,0x01,0x2f,0xed,0x32,0x12,0x39,0x2f,0xed,0x31,0x30,0x01,0x14,0x16,0x33,0x32,0x36,0x37,0x13,0x33, 0x03,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x13,0x33,0x03,0x06,0x01,0x32,0x68,0x6d,0x75,0x88,0x22,0xd3,0xa2,0xd8,0x32,0xe2,0xbf,0xa7,0xbe,0x31,0xb1,0xa2,0xaf,0x2e,0x01,0x45,0x67,0x59,0x97,0x99,0x03,0xe7,0xfc,0x0a,0xef,0xd0,0xa3,0x8f,0x6c,0xd2,0x03,0x46,0xfc,0xca,0xcf,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x05,0x9a, 0x02,0x06,0x0d,0xf2,0x00,0x00,0xff,0xff,0xff,0xd0,0xfe,0x9d,0x02,0x51,0x05,0x9a,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xad,0xf9,0xeb,0x00,0x0b,0xb6,0x01,0x00,0x16,0x0c,0x0b,0x05,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xf9,0x00,0x00,0x02,0x29,0x07,0x18,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x04,0x2a, 0xfe,0xb9,0x01,0x84,0x00,0x13,0x40,0x0b,0x01,0x00,0x12,0x0c,0x0b,0x05,0x25,0x01,0x12,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0x86,0x00,0x00,0x01,0xf0,0x07,0x5e,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x04,0x6e,0x00,0xa9,0x01,0x5e,0x00,0x1a,0xb1,0x02,0x01,0xb8,0xff,0x78,0x40,0x0a,0x12,0x0c,0x0b,0x05, 0x25,0x02,0x01,0x11,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x05,0x9a,0x02,0x06,0x0d,0xf2,0x00,0x00,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xfe,0x07,0x66,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0x8e,0xff,0xf2,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xe8,0x40,0x09,0x0d, 0x0d,0x0b,0x05,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xfd,0x00,0x00,0x02,0x31,0x07,0x6b,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xd7,0xff,0xa1,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x10,0x05,0x26,0x01,0x00,0x10,0x0c,0x0b,0x00,0x25,0x01,0x2b,0x35,0x00,0x2b,0x35,0x00,0xff,0xff,0xff,0xbe, 0x00,0x00,0x03,0x58,0x05,0xa1,0x00,0x27,0x0d,0xf2,0x01,0x68,0x00,0x00,0x01,0x07,0x04,0x36,0xfe,0x74,0xff,0x9b,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x40,0x40,0x09,0x0d,0x19,0x0b,0x05,0x25,0x02,0x01,0x1b,0x03,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xbd,0x00,0x00,0x03,0x6e,0x05,0xa1,0x00,0x27,0x0d,0xf2, 0x01,0x7e,0x00,0x00,0x01,0x07,0x04,0x37,0xfe,0x7b,0xff,0x9b,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x31,0x40,0x09,0x0d,0x19,0x0b,0x05,0x25,0x02,0x01,0x1c,0x03,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xc1,0x00,0x00,0x03,0x67,0x05,0xa1,0x00,0x27,0x0d,0xf2,0x01,0x77,0x00,0x00,0x01,0x07,0x04,0x43,0xfe,0x7d, 0xff,0x9b,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x3a,0x40,0x09,0x0f,0x19,0x0b,0x05,0x25,0x02,0x01,0x1b,0x03,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xbe,0x00,0x00,0x03,0x6e,0x05,0xb3,0x00,0x27,0x0d,0xf2,0x01,0x7e,0x00,0x00,0x01,0x07,0x04,0x38,0xfe,0x8b,0xff,0x30,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x41, 0x40,0x09,0x12,0x0c,0x0b,0x05,0x25,0x02,0x01,0x15,0x04,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x03,0x88,0x05,0xa1,0x00,0x27,0x0d,0xf2,0x01,0x98,0x00,0x00,0x01,0x07,0x04,0x44,0xfe,0x88,0xff,0x9b,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x25,0x40,0x09,0x0f,0x19,0x0b,0x05,0x25,0x02,0x01,0x1c, 0x03,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xbe,0x00,0x00,0x03,0x6e,0x05,0xb3,0x00,0x27,0x0d,0xf2,0x01,0x7e,0x00,0x00,0x01,0x07,0x04,0x45,0xfe,0x8b,0xff,0x30,0x00,0x19,0xb1,0x02,0x01,0xb8,0xfe,0x41,0x40,0x09,0x12,0x0c,0x0b,0x05,0x25,0x02,0x01,0x15,0x04,0x00,0x3f,0x35,0x35,0x01,0x2b,0x35,0x35,0x00, 0xff,0xff,0xff,0xbf,0x00,0x00,0x02,0x48,0x05,0xa1,0x00,0x26,0x0d,0xf2,0x58,0x00,0x01,0x07,0x04,0x61,0xfd,0xdd,0xff,0x7e,0x00,0x14,0xb9,0x00,0x01,0xfe,0xb9,0xb7,0x10,0x0c,0x0b,0x05,0x25,0x01,0x13,0x04,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xbe,0x00,0x00,0x02,0x4a,0x05,0xa1,0x00,0x26,0x0d,0xf2,0x5a,0x00,0x01,0x07, 0x04,0x27,0xfd,0xda,0xff,0x7e,0x00,0x14,0xb9,0x00,0x01,0xfe,0xb5,0xb7,0x0d,0x18,0x0b,0x05,0x25,0x01,0x15,0x04,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xfe,0x00,0x00,0x02,0x22,0x07,0x0a,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x04,0x66,0x01,0x10,0x01,0x4c,0x00,0x13,0x40,0x0b,0x01,0x00,0x12,0x0c,0x0b,0x05,0x25,0x01, 0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xf2,0x00,0x00,0x02,0x39,0x06,0xe3,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x75,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x05,0x1b,0x15,0x0b,0x05,0x25,0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xf2, 0x00,0x00,0x02,0x39,0x06,0xe3,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0x8f,0xff,0x75,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x05,0x1b,0x15,0x0b,0x05,0x25,0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0xff,0xf2,0x00,0x00,0x02,0x39,0x06,0xe3,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07, 0x00,0x8f,0xff,0x75,0x01,0x5c,0x00,0x17,0x40,0x0d,0x02,0x01,0x05,0x1b,0x15,0x0b,0x05,0x25,0x02,0x01,0x18,0x05,0x26,0x00,0x2b,0x35,0x35,0x01,0x2b,0x35,0x35,0x00,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x05,0x9a,0x02,0x06,0x0d,0xf2,0x00,0x00,0xff,0xff,0x00,0x30,0xfe,0x70,0x01,0xf0,0x05,0x9a,0x02,0x26,0x0d,0xf2,0x00,0x00, 0x01,0x06,0x00,0xdf,0x12,0x00,0x00,0x0b,0xb6,0x01,0x00,0x1a,0x0c,0x0b,0x05,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x05,0x9a,0x02,0x06,0x0d,0xf2,0x00,0x00,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x07,0x83,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x02,0x50,0xff,0xf0,0x01,0x5c,0x00,0x13,0x40,0x0b, 0x01,0x00,0x16,0x15,0x0b,0x05,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x30,0xff,0xe8,0x04,0x4c,0x05,0x9a,0x00,0x26,0x0d,0xf2,0x00,0x00,0x00,0x07,0x00,0x2d,0x02,0x21,0x00,0x00,0xff,0xff,0xff,0xd1,0x00,0x00,0x02,0x52,0x07,0x0c,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xd8,0xff,0xae, 0x01,0x5a,0x00,0x13,0x40,0x0b,0x01,0x00,0x16,0x0c,0x0b,0x05,0x25,0x01,0x16,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x30,0xfe,0xc6,0x01,0xf0,0x05,0x9a,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x06,0x02,0x45,0xbc,0x00,0x00,0x0b,0xb6,0x01,0x00,0x0f,0x15,0x0b,0x05,0x25,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x1c, 0x00,0x00,0x01,0xf0,0x07,0x66,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0x43,0xff,0xca,0x01,0x5c,0x00,0x16,0xb9,0x00,0x01,0xff,0xc5,0x40,0x09,0x0e,0x0c,0x0b,0x05,0x25,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xc7,0x00,0x00,0x02,0x4a,0x05,0x9b,0x00,0x26,0x0d,0xf2,0x5a,0x00,0x01,0x07,0x04,0x60, 0xfd,0xf6,0xff,0x9b,0x00,0x14,0xb9,0x00,0x01,0xfe,0xd0,0xb7,0x0e,0x0c,0x0b,0x05,0x25,0x01,0x0f,0x03,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xc7,0x00,0x00,0x02,0x4a,0x05,0x9b,0x00,0x26,0x0d,0xf2,0x5a,0x00,0x01,0x07,0x01,0x9f,0xfe,0xf9,0xff,0x9a,0x00,0x14,0xb9,0x00,0x01,0xfe,0xcf,0xb7,0x0e,0x0c,0x0b,0x05,0x25,0x01, 0x0f,0x03,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0xff,0xf3,0x00,0x00,0x02,0x3a,0x07,0xd1,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x02,0xd5,0xff,0x76,0x00,0x00,0x00,0x1b,0x40,0x0f,0x03,0x02,0x01,0x06,0x1f,0x19,0x0b,0x05,0x25,0x03,0x02,0x01,0x1c,0x05,0x26,0x00,0x2b,0x35,0x35,0x35,0x01,0x2b,0x35,0x35,0x35,0x00,0xff,0xff, 0xff,0xf8,0x00,0x00,0x02,0x2a,0x07,0x62,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xe0,0xff,0x92,0x01,0x56,0x00,0x13,0x40,0x0b,0x01,0x00,0x0f,0x0c,0x0b,0x05,0x25,0x01,0x0e,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x12,0x00,0x00,0x02,0x0e,0x06,0x79,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x04,0x64, 0x01,0x10,0x01,0x4a,0x00,0x13,0x40,0x0b,0x01,0x00,0x0e,0x0f,0x0b,0x05,0x25,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xaf,0x00,0x00,0x02,0x2c,0x05,0x9b,0x00,0x26,0x0d,0xf2,0x3c,0x00,0x01,0x07,0x04,0x55,0xfd,0xde,0xff,0x9b,0x00,0x14,0xb9,0x00,0x01,0xfe,0xd6,0xb7,0x0e,0x0c,0x0b,0x05,0x25,0x01, 0x0f,0x03,0x00,0x3f,0x35,0x01,0x2b,0x35,0xff,0xff,0x00,0x30,0x00,0x00,0x01,0xf0,0x06,0xe2,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xdb,0x00,0x42,0x01,0x5d,0x00,0x13,0x40,0x0b,0x01,0x00,0x0f,0x15,0x0b,0x05,0x25,0x01,0x0c,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0x00,0x14,0x00,0x00,0x02,0x10,0x06,0x79, 0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xd9,0xff,0xd6,0x01,0x4a,0x00,0x13,0x40,0x0b,0x01,0x00,0x0e,0x0f,0x0b,0x05,0x25,0x01,0x0d,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x02,0x24,0x07,0x1a,0x02,0x26,0x0d,0xf2,0x00,0x00,0x01,0x07,0x00,0xda,0xff,0xda,0x01,0x5c,0x00,0x13,0x40,0x0b, 0x01,0x00,0x12,0x0c,0x0b,0x05,0x25,0x01,0x0f,0x05,0x26,0x00,0x2b,0x35,0x01,0x2b,0x35,0x00,0x00,0x14,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x09,0x00,0x15,0x00,0x4b,0x00,0x55,0x00,0x5b,0x00,0x61,0x00,0x67,0x00,0x6d,0x00,0x71,0x00,0x75,0x00,0x79,0x00,0x7d,0x00,0x81,0x00,0x85,0x00,0x89,0x00,0x8d,0x00,0x91,0x00,0x95, 0x00,0x99,0x00,0x9d,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x11,0x33,0x21,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e, 0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x05,0x21,0x35,0x33,0x11,0x07,0x35,0x37,0x11,0x33,0x01,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35, 0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x03,0x20,0x97,0x8b,0x8b,0x61,0xf8,0x02,0x1a,0x94,0x6e,0x92,0x68,0x5a,0x07,0x01,0x02,0x02,0x07,0x5a,0xfd,0x35,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d, 0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40,0x02,0xe0,0xfe,0xf0,0x59,0x5b,0xba,0x58,0xfb,0xbb,0xeb,0x96,0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56, 0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0x04,0x7b,0x6a,0x4e,0xa7,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0xd4,0x18,0x13,0x15,0x18,0x01,0x2a,0xfc,0x44,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08, 0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x04,0x4b,0x01,0x0b,0x13,0x4c,0x26,0xfe,0x96,0x03,0x8b,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c, 0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0x00,0x14,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x09,0x00,0x15,0x00,0x4b,0x00,0x61,0x00,0x67,0x00,0x6d,0x00,0x73,0x00,0x79,0x00,0x7d,0x00,0x81,0x00,0x85,0x00,0x89,0x00,0x8d,0x00,0x91,0x00,0x95,0x00,0x99, 0x00,0x9d,0x00,0xa1,0x00,0xa5,0x00,0xa9,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x11,0x33,0x21,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14, 0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x25,0x15,0x33,0x15,0x21,0x35,0x37,0x36,0x36,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x01,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35, 0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x03,0x20,0x97,0x8b,0x8b,0x61,0xf8,0x02,0x1a,0x94,0x6e,0x92,0x68,0x5a,0x07,0x01,0x02,0x02,0x07,0x5a,0xfd,0x35, 0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40,0x02,0x2f,0xae,0xfe,0xe5,0x7c,0x25,0x1e,0x40,0x37,0x33,0x38,0x47,0x42,0x4a,0x5b,0xfc,0x14,0xeb,0x96,0x04, 0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0x04,0x7b,0x6a,0x4e,0xa7,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0xd4,0x18,0x13,0x15,0x18, 0x01,0x2a,0xfc,0x44,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x4d,0x02,0x4f,0x4a,0x76,0x24,0x30,0x1b,0x3b,0x2c,0x53,0x25,0x43,0x38,0x4b, 0x51,0x03,0x37,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0x00,0x00,0x14,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0, 0x00,0x09,0x00,0x15,0x00,0x4b,0x00,0x6e,0x00,0x74,0x00,0x7a,0x00,0x80,0x00,0x86,0x00,0x8a,0x00,0x8e,0x00,0x92,0x00,0x96,0x00,0x9a,0x00,0x9e,0x00,0xa2,0x00,0xa6,0x00,0xaa,0x00,0xae,0x00,0xb2,0x00,0xb6,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x11,0x33,0x21,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13, 0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x25,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35, 0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x01,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01, 0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x03,0x20,0x97,0x8b,0x8b,0x61,0xf8,0x02,0x1a,0x94,0x6e,0x92,0x68,0x5a,0x07,0x01,0x02,0x02,0x07,0x5a,0xfd,0x35,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34, 0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40,0x01,0xd9,0x2b,0x3a,0x24,0x28,0x32,0x2b,0x27,0x24,0x54,0x41,0x2b,0x29,0x2d,0x3d,0x42,0x49,0x55,0x2d,0x35,0x58,0x4e,0x42,0xfc,0x98,0xeb,0x96,0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56, 0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0x04,0x7b,0x6a,0x4e,0xa7,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0xd4,0x18,0x13,0x15,0x18,0x01,0x2a,0xfc,0x45,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a, 0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x0a,0x52,0x1f,0x1f,0x1c,0x1d,0x1f,0x48,0x38,0x35,0x1c,0x4d,0x17,0x3b,0x30,0x54,0x15,0x02,0x06,0x37,0x27,0x3d,0x46,0x03,0xdd,0xec, 0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0x00,0x00,0x13,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x0b,0x00,0x41, 0x00,0x5d,0x00,0x63,0x00,0x69,0x00,0x6f,0x00,0x75,0x00,0x79,0x00,0x7d,0x00,0x81,0x00,0x85,0x00,0x89,0x00,0x8d,0x00,0x91,0x00,0x95,0x00,0x99,0x00,0x9d,0x00,0xa1,0x00,0xa5,0x00,0x00,0x01,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x13,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35, 0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x13,0x23,0x11,0x34,0x37,0x23,0x06,0x07,0x03,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x15,0x23,0x11,0x33,0x17,0x16,0x17,0x33,0x36,0x37,0x37,0x33,0x25,0x35,0x33,0x15,0x23,0x15,0x25,0x35, 0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33, 0x03,0x82,0x94,0x6e,0x92,0x68,0x5a,0x07,0x01,0x02,0x02,0x07,0x5a,0xe5,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40,0x7b,0x60,0x04,0x02,0x08,0x06,0x65, 0x4f,0x67,0x04,0x09,0x03,0x04,0x57,0x8e,0x58,0x0a,0x05,0x02,0x08,0x09,0x58,0x8a,0xfc,0x28,0xeb,0x96,0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55, 0x05,0x6b,0x56,0x56,0x02,0xac,0xfe,0x52,0x01,0xae,0xfe,0xd4,0x18,0x13,0x15,0x18,0x01,0x2a,0xfe,0x63,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d, 0x0c,0x02,0x19,0x01,0x01,0x2a,0x32,0x27,0x12,0xfe,0xdc,0x01,0x21,0x0c,0x30,0x3f,0x30,0xee,0x01,0xae,0xff,0x1f,0x1e,0x23,0x1b,0xfe,0x0a,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03, 0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0x00,0x00,0x03,0x00,0x93,0xff,0x43,0x03,0x75,0x05,0xb8,0x00,0x1e,0x00,0x25,0x00,0x2a,0x00,0x5b,0xb1,0x16,0x1c,0xb8,0x01,0x84,0x40,0x0d,0x29,0x19,0x13,0x00,0x00,0x1f,0x10,0x09,0x03,0x03,0x0d,0x29,0x23,0xb8,0x01,0x84,0x40,0x0b,0x06,0x0d,0x1f,0x19,0x13,0x09, 0x26,0x0a,0x03,0x20,0x18,0xb8,0x01,0x7e,0xb6,0x10,0x7f,0x13,0x01,0x13,0x27,0x09,0xb8,0x01,0x7e,0xb1,0x00,0x03,0x00,0x2f,0x33,0xed,0x32,0x2f,0x71,0x33,0xed,0x32,0x11,0x39,0x39,0x11,0x12,0x39,0x39,0x01,0x2f,0x33,0xed,0x2f,0x12,0x39,0x2f,0x33,0x33,0x33,0x33,0x11,0x33,0x33,0x10,0xed,0x32,0x31,0x30,0x25,0x15,0x23,0x35,0x22, 0x27,0x35,0x16,0x16,0x33,0x11,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x15,0x26,0x27,0x11,0x16,0x16,0x15,0x14,0x06,0x03,0x11,0x06,0x06,0x15,0x14,0x16,0x13,0x11,0x36,0x35,0x34,0x02,0x2e,0x5e,0xc1,0x79,0x35,0xb6,0x4f,0xc7,0x76,0xb3,0x8a,0x5e,0xb2,0x44,0x5d,0x99,0xbd,0x8a,0xad,0xf8,0x4c,0x59,0x48,0xbb,0xaf, 0x07,0xc4,0xbd,0x4e,0x9e,0x2f,0x3e,0x01,0xd0,0x60,0xa2,0x6e,0x84,0xbf,0x13,0xa3,0x9f,0x06,0x2d,0x9a,0x48,0x06,0xfe,0x21,0x59,0xa8,0x6b,0x80,0xaf,0x02,0xce,0x01,0xa6,0x0f,0x68,0x4b,0x4d,0x64,0xfe,0xff,0xfe,0x66,0x26,0x97,0x7d,0x00,0x00,0x05,0x00,0x48,0xff,0xec,0x05,0xaa,0x05,0x27,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x27, 0x00,0x33,0x00,0x6f,0xb5,0x18,0x1a,0x18,0x1a,0x03,0x25,0xbe,0x01,0x83,0x00,0x31,0x00,0x09,0x01,0x83,0x00,0x15,0x00,0x2b,0x01,0x83,0xb7,0x1f,0x15,0x1f,0x15,0x1f,0x03,0x31,0x0f,0xbb,0x01,0x83,0x00,0x03,0x00,0x12,0x01,0x7d,0xb5,0x70,0x00,0x01,0x00,0x00,0x0c,0xb8,0x01,0x7d,0xb6,0x06,0x06,0x7f,0x1b,0x01,0x1b,0x28,0xb8,0x01, 0x7d,0xb2,0x22,0x22,0x2e,0xb8,0x01,0x7d,0xb2,0x1c,0x1c,0x1a,0x00,0x2f,0x33,0x2f,0xed,0x33,0x2f,0xed,0x2f,0x71,0x33,0x2f,0xed,0x33,0x2f,0x71,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x2f,0x2f,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03, 0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x25,0x01,0x23,0x01,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x6e,0x86,0xa0,0xa9,0x8f,0x8b,0x99,0xab,0x7e,0x56,0x64,0x62,0x54,0x55,0x60,0x5f,0x03,0x07,0xfc,0xbe,0x81,0x03,0x40,0x23, 0x86,0xa0,0xab,0x8d,0x8a,0x9a,0xac,0x7e,0x57,0x62,0x62,0x54,0x55,0x60,0x5f,0x02,0x88,0xb0,0x94,0xa1,0xba,0xac,0x9c,0x9c,0xbb,0x02,0x3b,0x7f,0x70,0x6d,0x7b,0x7f,0x71,0x6d,0x7a,0x50,0xfa,0xe4,0x05,0x1c,0xfa,0xd9,0xb2,0x92,0xa2,0xbb,0xae,0x9c,0x9b,0xbc,0x02,0x3b,0x7f,0x70,0x6c,0x7a,0x7f,0x70,0x6e,0x78,0x00,0x03,0x00,0x6c, 0xff,0xeb,0x05,0xa8,0x05,0x29,0x00,0x43,0x00,0x57,0x00,0x67,0x00,0x7e,0xb1,0x41,0x33,0xbb,0x01,0x84,0x00,0x2c,0x00,0x60,0x01,0x84,0xb6,0x17,0x12,0x4e,0x24,0x03,0x17,0x21,0xb8,0x01,0x84,0xb3,0x58,0x29,0x05,0x38,0xb8,0x01,0x85,0x40,0x0b,0x49,0x17,0x58,0x49,0x49,0x58,0x17,0x03,0x0f,0x2c,0x53,0xb8,0x01,0x84,0xb3,0x0f,0x24, 0x12,0x4e,0xb8,0x01,0x7e,0x40,0x0c,0x29,0x49,0x38,0x05,0x04,0x0a,0x65,0x2f,0x65,0x2f,0x44,0x5d,0xb8,0x01,0x7e,0xb2,0x1c,0x3d,0x44,0xb8,0x01,0x7e,0xb1,0x00,0x0a,0x00,0x2f,0x33,0xed,0x32,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0xed,0x39,0x39,0x01,0x2f,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x39,0x39, 0x10,0xed,0x11,0x17,0x39,0x10,0xed,0x10,0xfd,0xc4,0x31,0x30,0x05,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x17,0x36,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x14,0x0e,0x02,0x07,0x1e,0x03,0x33,0x32,0x36,0x37, 0x15,0x06,0x06,0x25,0x32,0x3e,0x02,0x37,0x2e,0x03,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x01,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x14,0x1e,0x02,0x17,0x36,0x36,0x05,0x1d,0x33,0x4f,0x43,0x3f,0x22,0x25,0x5f,0x74,0x89,0x51,0x62,0xa3,0x74,0x40,0x9d,0x91,0x1c,0x36,0x2b,0x1a,0x34,0x5a,0x7c,0x47,0x47,0x75,0x54,0x2f,0x7c,0x7c,0x3e, 0x66,0x56,0x4a,0x24,0x4a,0x4a,0x08,0x07,0x90,0x07,0x03,0x02,0x23,0x3a,0x4d,0x2a,0x1f,0x35,0x35,0x39,0x25,0x1b,0x38,0x1e,0x21,0x47,0xfc,0xe5,0x45,0x74,0x62,0x4f,0x21,0x37,0x5e,0x5f,0x6b,0x47,0x39,0x60,0x46,0x28,0x2d,0x4f,0x69,0x01,0x20,0x22,0x34,0x3f,0x1f,0x59,0x6a,0x01,0x17,0x29,0x36,0x1f,0x72,0x71,0x15,0x1c,0x34,0x4a, 0x2f,0x27,0x48,0x38,0x22,0x31,0x5f,0x8c,0x5a,0x8b,0xc5,0x3e,0x14,0x35,0x44,0x53,0x31,0x47,0x6f,0x4c,0x27,0x27,0x48,0x66,0x3e,0x6d,0x90,0x33,0x18,0x47,0x57,0x64,0x35,0x66,0xf7,0x87,0x22,0x3d,0x1e,0x1e,0x36,0x25,0x52,0xa7,0x9d,0x8d,0x3b,0x2b,0x41,0x2b,0x15,0x0e,0x0b,0x89,0x0d,0x0d,0x81,0x1e,0x32,0x42,0x24,0x56,0x7a,0x59, 0x40,0x1b,0x17,0x37,0x4b,0x64,0x43,0x3e,0x5e,0x3e,0x20,0x03,0x9d,0x2d,0x40,0x29,0x13,0x60,0x52,0x25,0x42,0x38,0x2b,0x10,0x28,0x6a,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0x8f,0x05,0x29,0x00,0x1b,0x00,0x4d,0xb1,0x14,0x18,0xb8,0x01,0x84,0x40,0x0c,0x08,0x04,0x16,0x0f,0x00,0x00,0x0f,0x16,0x04,0x04,0x1d,0x1a,0xb8,0x01,0x86,0xb3, 0x06,0x01,0x17,0x06,0xb8,0x01,0x7e,0xb4,0x14,0x07,0x07,0x1a,0x11,0xb8,0x01,0x7e,0xb2,0x0c,0x02,0x1a,0xb9,0x01,0x7e,0x00,0x01,0x00,0x2f,0xed,0x32,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xc4,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x21,0x35,0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x34, 0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x15,0x21,0x15,0x21,0x15,0x14,0x07,0x21,0x03,0x8f,0xfc,0xd1,0xc6,0xb3,0xb3,0xc5,0x9d,0x6a,0x57,0x5b,0x64,0xd0,0x01,0x0c,0xfe,0xf4,0xaf,0x02,0x84,0x7a,0x3f,0xdd,0xa9,0x80,0xe6,0xab,0xd9,0x25,0x8d,0x34,0xfe,0xea,0xd6,0x80,0x8d,0xdb,0x58,0x00,0x02,0x00,0x77,0xff,0xc4,0x02,0xdb, 0x05,0x47,0x00,0x26,0x00,0x30,0x00,0x5c,0xb2,0x1c,0x00,0x25,0xbb,0x01,0x84,0x00,0x2e,0x00,0x20,0x01,0x84,0xb2,0x07,0x16,0x02,0xb8,0x01,0x84,0x40,0x09,0x0d,0x16,0x0d,0x16,0x0d,0x12,0x2e,0x14,0x29,0xb8,0x01,0x84,0x40,0x0c,0x12,0x00,0x2c,0x14,0x27,0x20,0x27,0x2c,0x0d,0x04,0x05,0x1e,0xbc,0x01,0x7e,0x00,0x19,0x00,0x0a,0x01, 0x7e,0x00,0x05,0x00,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0xfd,0xc5,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xc4,0xed,0x10,0xfd,0xcd,0xc4,0x31,0x30,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17, 0x15,0x26,0x23,0x22,0x15,0x14,0x16,0x17,0x16,0x15,0x14,0x01,0x06,0x15,0x14,0x16,0x17,0x36,0x35,0x34,0x26,0x02,0x54,0x52,0xb6,0x8c,0x77,0x61,0x75,0x6d,0x4c,0x53,0x40,0x83,0xd3,0x85,0x60,0xa9,0x8b,0x76,0x50,0x5b,0x6f,0x98,0x49,0x94,0xca,0xfe,0x8e,0x5c,0x66,0x80,0x50,0x5f,0x01,0x79,0x43,0x66,0x77,0x95,0x33,0x8f,0x43,0x48, 0x36,0x30,0x42,0x46,0x6e,0xb1,0x94,0x49,0x4b,0x7f,0x73,0x95,0x27,0x8f,0x38,0x83,0x31,0x52,0x47,0x61,0xa8,0x9a,0x01,0x5b,0x2e,0x62,0x41,0x63,0x39,0x3d,0x5f,0x41,0x5b,0x00,0x00,0x01,0x00,0x3e,0x00,0x00,0x03,0xb0,0x05,0x13,0x00,0x1b,0x00,0x72,0xb3,0x10,0x0c,0x05,0x09,0xbb,0x01,0x84,0x00,0x0a,0x00,0x01,0x01,0x82,0x40,0x15, 0x18,0x03,0x07,0x0c,0x12,0x0a,0x0e,0x18,0x07,0x07,0x18,0x0e,0x0a,0x12,0x0c,0x06,0x00,0x13,0x00,0x08,0x0c,0xb8,0x01,0x7e,0xb4,0x0d,0x05,0x0d,0x04,0x10,0xb8,0x01,0x7e,0x40,0x13,0x11,0x01,0x18,0x11,0x0f,0x11,0x1f,0x11,0x02,0x0d,0x11,0x0d,0x11,0x0a,0x13,0x7f,0x00,0x01,0x00,0x00,0x2f,0x71,0x32,0x2f,0x39,0x39,0x2f,0x2f,0x5d, 0x11,0x39,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x10,0xed,0x32,0x11,0x33,0x31,0x30,0x01,0x01,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x01,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x03,0xb0, 0xfe,0xbe,0x01,0x02,0xfe,0xd1,0x01,0x2f,0xfe,0xd1,0x94,0xfe,0xc8,0x01,0x38,0xfe,0xc8,0x01,0x08,0xfe,0xc1,0xae,0xe2,0x19,0x12,0x03,0x0c,0x21,0xe4,0x05,0x13,0xfd,0xae,0x7e,0xbc,0x7e,0xfe,0xf7,0x01,0x09,0x7e,0xbc,0x7e,0x02,0x52,0xfe,0x2f,0x35,0x30,0x26,0x44,0x01,0xcc,0x00,0x00,0x01,0x00,0x96,0xfe,0x99,0x03,0xb5,0x03,0xa0, 0x00,0x18,0x00,0x29,0xb1,0x0e,0x0a,0xbb,0x01,0x84,0x00,0x0b,0x00,0x17,0x01,0x84,0xb5,0x14,0x03,0x15,0x0d,0x0b,0x11,0xb8,0x01,0x7e,0xb1,0x06,0x01,0x00,0x2f,0x2f,0xed,0x2f,0x2f,0x33,0x01,0x2f,0x33,0xed,0x2f,0xed,0x32,0x31,0x30,0x21,0x23,0x26,0x35,0x23,0x06,0x23,0x22,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x14,0x16,0x33,0x32, 0x36,0x35,0x11,0x33,0x11,0x14,0x03,0xb5,0x9a,0x14,0x05,0x4c,0xb1,0x97,0x40,0x04,0x94,0x94,0x7d,0x65,0x6d,0x89,0x96,0x41,0x57,0xad,0x70,0xfe,0x3e,0x05,0x07,0xfd,0xc9,0x73,0x88,0x9b,0x84,0x02,0x13,0xfd,0x50,0xaa,0x00,0x01,0x00,0x2e,0xfe,0x57,0x04,0x48,0x05,0x13,0x00,0x0b,0x00,0x32,0xb1,0x08,0x0a,0xbb,0x01,0x86,0x00,0x01, 0x00,0x09,0x01,0x86,0x40,0x10,0x03,0x03,0x00,0x04,0x01,0x07,0x00,0x08,0x9a,0x7f,0x05,0x01,0x05,0x0a,0x9a,0x01,0x00,0x2f,0xed,0x2f,0x71,0xed,0x01,0x2f,0x33,0x2f,0x33,0x12,0x39,0x2f,0xed,0x10,0xed,0x32,0x31,0x30,0x01,0x21,0x35,0x01,0x01,0x35,0x21,0x15,0x21,0x01,0x01,0x21,0x04,0x48,0xfb,0xe6,0x02,0x65,0xfd,0xbd,0x03,0xd4, 0xfd,0x0b,0x02,0x1a,0xfd,0xca,0x03,0x35,0xfe,0x57,0x47,0x03,0x20,0x03,0x04,0x51,0x8b,0xfd,0x39,0xfd,0x21,0x00,0x00,0x01,0x00,0x5c,0xff,0xea,0x03,0x97,0x05,0x29,0x00,0x25,0x00,0x58,0xb4,0x14,0x25,0x25,0x27,0x1d,0xb8,0x01,0x85,0xb2,0x09,0x21,0x05,0xb8,0x01,0x7e,0xb4,0x06,0x1e,0x06,0x1c,0x0c,0xb8,0x01,0x7e,0x40,0x13,0x0d, 0x19,0x0d,0x0f,0x06,0x1f,0x06,0x02,0x3f,0x0d,0x4f,0x0d,0x02,0x06,0x0d,0x06,0x0d,0x23,0x16,0xbc,0x01,0x7e,0x00,0x11,0x00,0x23,0x01,0x7e,0x00,0x02,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x2f,0x39,0x31,0x30,0x25,0x06,0x23,0x20, 0x03,0x23,0x35,0x33,0x26,0x35,0x34,0x37,0x23,0x35,0x33,0x36,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x06,0x17,0x21,0x15,0x21,0x12,0x33,0x32,0x37,0x03,0x97,0x79,0x87,0xfe,0x7d,0x4a,0x6e,0x62,0x03,0x05,0x64,0x77,0x2e,0x01,0x01,0xb7,0x7c,0x62,0x68,0x80,0x72,0xb0,0x24,0x01,0xc3,0xfe,0x2a,0x08,0x07, 0x01,0xd7,0xfe,0x37,0x41,0xfc,0x77,0x80,0x2d,0x43,0x01,0xcb,0x7f,0x1c,0x29,0x2c,0x36,0x7f,0xd9,0xf6,0x33,0x93,0x47,0xb6,0x9a,0x7f,0x5a,0x4d,0x7f,0xfe,0xb4,0x4f,0x00,0x03,0x00,0x73,0x00,0x00,0x06,0x30,0x05,0x27,0x00,0x09,0x00,0x0d,0x00,0x24,0x00,0x70,0xb1,0x0e,0x1f,0xbe,0x01,0x83,0x00,0x14,0x00,0x08,0x01,0x82,0x00,0x03, 0x00,0x23,0x01,0x84,0x40,0x11,0x19,0x0f,0x03,0x00,0x0f,0x0f,0x00,0x03,0x03,0x05,0x0a,0x14,0x0c,0x01,0x05,0x08,0x02,0xbb,0x01,0x7d,0x00,0x01,0x00,0x17,0x01,0x7d,0xb7,0x1c,0x01,0x1c,0x01,0x1c,0x0d,0x10,0x23,0xb8,0x01,0x7d,0x40,0x0a,0x0f,0x04,0x99,0x07,0x07,0x7f,0x0d,0x01,0x0d,0x0c,0x00,0x2f,0x2f,0x71,0x33,0x2f,0xed,0x2f, 0xed,0x32,0x11,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x01,0x2f,0x33,0xc4,0x2f,0xc4,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc4,0xed,0x10,0xed,0x10,0xfd,0xc4,0x31,0x30,0x01,0x21,0x35,0x33,0x11,0x07,0x35,0x25,0x11,0x33,0x01,0x01,0x23,0x01,0x01,0x21,0x35,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32, 0x16,0x15,0x14,0x07,0x07,0x15,0x21,0x02,0x43,0xfe,0x37,0xa8,0xaf,0x01,0x25,0xab,0x02,0xab,0xfc,0xf7,0x83,0x03,0x0a,0x01,0xc4,0xfe,0x0a,0xd9,0x5e,0x33,0x45,0x38,0x6b,0x59,0x4d,0x88,0x6b,0x7d,0xb9,0x95,0x01,0x5e,0x02,0x11,0x66,0x02,0x1a,0x32,0x71,0x57,0xfd,0x50,0x02,0x9c,0xfa,0xed,0x05,0x13,0xfa,0xee,0x67,0xd6,0x5c,0x63, 0x32,0x35,0x42,0x5d,0x87,0x45,0x77,0x62,0x8b,0xb1,0x8d,0x04,0x00,0x04,0x00,0x73,0x00,0x00,0x06,0x0a,0x05,0x27,0x00,0x09,0x00,0x0d,0x00,0x18,0x00,0x20,0x00,0x7d,0xb5,0x17,0x10,0x0e,0xa8,0x11,0x08,0xbb,0x01,0x82,0x00,0x03,0x00,0x1d,0x01,0x83,0x40,0x18,0x13,0x03,0x00,0x13,0x13,0x00,0x03,0x03,0x05,0x1e,0x1a,0x19,0x0a,0x11, 0x0c,0x01,0x05,0x04,0x99,0x07,0x07,0x0d,0x0f,0x13,0xb8,0x01,0x7d,0xb5,0x1d,0x17,0x14,0x1d,0x08,0x02,0xb8,0x01,0x7d,0x40,0x11,0x01,0x19,0x15,0x1d,0x01,0x15,0x15,0x01,0x1d,0x03,0x0c,0x7f,0x0d,0x01,0x0d,0x11,0x0c,0x00,0x2f,0x33,0x2f,0x71,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x33,0x10,0xed,0x32, 0x11,0x33,0x2f,0xed,0x01,0x2f,0x33,0xc4,0x2f,0xc4,0x33,0x33,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xf4,0xc6,0x32,0x31,0x30,0x01,0x21,0x35,0x33,0x11,0x07,0x35,0x25,0x11,0x33,0x01,0x01,0x23,0x01,0x01,0x23,0x15,0x23,0x35,0x21,0x35,0x01,0x33,0x11,0x33,0x03,0x23,0x06,0x07,0x03,0x33,0x11,0x34,0x02,0x43, 0xfe,0x37,0xa8,0xaf,0x01,0x25,0xab,0x02,0xab,0xfc,0xf7,0x83,0x03,0x0a,0x01,0x9e,0x64,0x78,0xfe,0x9c,0x01,0x4f,0x8d,0x64,0xd8,0x04,0x0a,0x18,0xc6,0xe8,0x02,0x11,0x66,0x02,0x1a,0x32,0x71,0x57,0xfd,0x50,0x02,0x9c,0xfa,0xed,0x05,0x13,0xfb,0xa6,0xb9,0xb9,0x53,0x01,0xf6,0xfe,0x1a,0x01,0x74,0x1c,0x26,0xfe,0xce,0x01,0x24,0x1d, 0x00,0x04,0x00,0x75,0x00,0x00,0x06,0x45,0x05,0x25,0x00,0x20,0x00,0x24,0x00,0x2f,0x00,0x37,0x00,0x9a,0xb5,0x2e,0x27,0x25,0xa8,0x28,0x17,0xbe,0x01,0x82,0x00,0x0d,0x00,0x1c,0x01,0x83,0x00,0x06,0x00,0x34,0x01,0x83,0x40,0x0f,0x2a,0x0d,0x06,0x2a,0x2a,0x06,0x0d,0x03,0x09,0x35,0x30,0x21,0x28,0x23,0x1a,0xb8,0x01,0x86,0xb4,0x11, 0x00,0x09,0x26,0x2a,0xb8,0x01,0x7d,0xb5,0x34,0x2e,0x2b,0x34,0x19,0x09,0xb8,0x01,0x7d,0xb3,0x0a,0x0a,0x14,0x03,0xb8,0x01,0x7d,0x40,0x0d,0x1f,0x30,0x2c,0x34,0x1f,0x2c,0x2c,0x1f,0x34,0x03,0x23,0x24,0x0f,0xb8,0x01,0x7d,0xb7,0x14,0x14,0x7f,0x24,0x01,0x24,0x28,0x23,0x00,0x2f,0x33,0x2f,0x71,0x33,0x2f,0xed,0x11,0x12,0x17,0x39, 0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x11,0x39,0x2f,0xed,0x39,0x11,0x33,0x33,0x10,0xed,0x32,0x01,0x2f,0xc4,0xc6,0xed,0xc4,0x2f,0xc4,0x33,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x10,0xf4,0xc6,0x32,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07, 0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x01,0x01,0x23,0x01,0x01,0x23,0x15,0x23,0x35,0x21,0x35,0x01,0x33,0x11,0x33,0x03,0x23,0x06,0x07,0x03,0x33,0x11,0x34,0x75,0x5d,0x67,0x49,0x53,0xc6,0x4c,0x48,0xb3,0x83,0x55,0x53,0x4f,0x72,0x66,0x7a,0x84,0xa1,0x9a,0x81,0x7c,0x04,0x74,0xfc,0xf7,0x82, 0x03,0x0a,0x01,0x98,0x64,0x78,0xfe,0x9c,0x01,0x4f,0x8d,0x64,0xd8,0x04,0x0b,0x17,0xc6,0xe8,0x02,0x2e,0x81,0x45,0x44,0x3a,0x80,0x6a,0x7a,0x6c,0x3f,0x7e,0x2e,0x6b,0x57,0x89,0x31,0x04,0x26,0x91,0x6a,0x86,0x03,0x15,0xfa,0xed,0x05,0x13,0xfb,0xa6,0xb9,0xb9,0x53,0x01,0xf6,0xfe,0x1a,0x01,0x74,0x1c,0x26,0xfe,0xce,0x01,0x24,0x1d, 0x00,0x01,0x00,0x19,0x00,0x00,0x03,0x3e,0x05,0x13,0x00,0x11,0x00,0x4b,0x40,0x09,0x00,0x0e,0x00,0x0e,0x03,0x09,0x10,0x0c,0x02,0xb8,0x01,0x85,0xb4,0x07,0x05,0x03,0x01,0x05,0xb8,0x01,0x7f,0x40,0x12,0x06,0x10,0x06,0x0f,0x9a,0x0c,0x06,0x0c,0x06,0x0c,0x03,0x0b,0x9a,0x7f,0x08,0x01,0x08,0x03,0x00,0x2f,0x2f,0x71,0xed,0x12,0x39, 0x39,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xc6,0x33,0xed,0x32,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x25,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x15,0x33,0x02,0x20,0xdd,0x99,0x91,0x91,0x02,0x94,0xfe,0x05,0x01,0xd5,0xfe,0x2b,0xdd,0xfc,0xfc,0xfc,0x8d,0x03,0x8a, 0x8a,0xfe,0x3f,0x89,0xb6,0x00,0x00,0x04,0x00,0xaa,0xff,0xea,0x07,0xd0,0x05,0x13,0x00,0x09,0x00,0x10,0x00,0x25,0x00,0x45,0x00,0x9b,0xb1,0x36,0x41,0xbb,0x01,0x84,0x00,0x2b,0x00,0x06,0x01,0x85,0xb2,0x0e,0x1d,0x21,0xb8,0x01,0x84,0xb5,0x1a,0x18,0x16,0x1f,0x11,0x3b,0xb8,0x01,0x84,0x40,0x0f,0x26,0x30,0x0e,0x16,0x11,0x30,0x30, 0x11,0x16,0x0e,0x04,0x02,0x2b,0x0b,0x01,0xb8,0x01,0x85,0x40,0x0e,0x02,0x2b,0x3b,0x44,0x33,0x44,0x13,0x0b,0x9a,0x00,0x33,0x38,0x20,0x18,0xb8,0x01,0x7e,0x40,0x0d,0x19,0x1d,0x19,0x00,0x19,0x1c,0x1c,0x19,0x00,0x03,0x03,0x29,0x23,0xb8,0x01,0x7e,0x40,0x09,0x13,0x0a,0x9a,0x7f,0x03,0x01,0x03,0x02,0x18,0x00,0x3f,0x2f,0x71,0xed, 0x2f,0xed,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x32,0x33,0x10,0xed,0x11,0x33,0x11,0x12,0x39,0x39,0x01,0x2f,0xed,0x32,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xc4,0xed,0x11,0x33,0x10,0xc6,0x33,0xed,0x32,0x10,0xed,0x10,0xfd,0xc4,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x20,0x11,0x14,0x06,0x23,0x03, 0x11,0x33,0x20,0x11,0x10,0x21,0x01,0x06,0x23,0x22,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x33,0x15,0x23,0x11,0x14,0x33,0x32,0x37,0x17,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x01,0x43,0x99,0x01,0x1b,0x01, 0xa3,0xf0,0xd5,0x60,0x55,0x01,0x30,0xfe,0xe3,0x03,0xd3,0x34,0x57,0x76,0x6a,0x8d,0x8d,0x94,0xd7,0xd7,0x77,0x36,0x2a,0x3e,0x6d,0x7c,0x93,0x3a,0xdf,0x61,0xa6,0x85,0x75,0x47,0x57,0x67,0x42,0x4f,0x62,0x55,0x7f,0x44,0x9f,0x8c,0x92,0x01,0xeb,0xfe,0x15,0x05,0x13,0xfe,0x7c,0xbe,0xe6,0x02,0x9e,0xfd,0xec,0x01,0x13,0x01,0x01,0xfb, 0x80,0x1d,0x81,0x8f,0x01,0xa4,0x7d,0xe3,0x31,0xfe,0xec,0x7d,0xfe,0x76,0xad,0x1f,0x66,0x9f,0x5a,0x68,0x24,0x48,0x54,0x38,0x69,0x6e,0x83,0x2a,0x91,0x3e,0x39,0x2e,0x33,0x28,0x23,0x39,0x66,0x43,0x71,0x82,0x00,0x01,0x00,0x60,0x00,0x00,0x03,0x8f,0x05,0x29,0x00,0x23,0x00,0x81,0xb5,0x10,0x0c,0x07,0x22,0x1e,0x01,0xb8,0x01,0x84, 0x40,0x0e,0x12,0x0e,0x0a,0x20,0x00,0x0a,0x00,0x19,0x19,0x00,0x0a,0x03,0x05,0x04,0xb8,0x01,0x86,0xb3,0x07,0x05,0x01,0x0c,0xb8,0x01,0x7e,0xb4,0x0d,0x22,0x0d,0x21,0x10,0xb8,0x01,0x7e,0x40,0x16,0x11,0x1e,0x11,0x30,0x0d,0x40,0x0d,0x02,0x2f,0x11,0x01,0x00,0x11,0x10,0x11,0x02,0x0d,0x11,0x0d,0x11,0x04,0x1b,0xb8,0x01,0x7e,0xb2, 0x16,0x08,0x04,0xb9,0x01,0x7e,0x00,0x07,0x00,0x2f,0xed,0x32,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x5d,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x33,0xed,0x32,0x32,0x10,0xc4,0x32,0x31,0x30,0x01,0x21,0x15,0x14,0x07,0x21,0x15,0x21,0x35, 0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x11,0x15,0x21,0x15,0x21,0x15,0x21,0x02,0xc6,0xfe,0xf4,0xaf,0x02,0x84,0xfc,0xd1,0xc6,0xb3,0xb3,0xb3,0xb3,0xc5,0x9d,0x6b,0x56,0x5a,0x65,0xd0,0x01,0x0c,0xfe,0xf4,0x01,0x0c,0x01,0xba,0x08,0xdc,0x57,0x7f,0x7a,0x41,0xdb,0x24, 0x7f,0x7b,0x80,0x71,0xab,0xd9,0x25,0x8d,0x34,0xfe,0xea,0x61,0x80,0x7b,0x00,0x05,0x00,0x73,0xff,0xee,0x06,0x35,0x05,0x27,0x00,0x09,0x00,0x0d,0x00,0x21,0x00,0x2a,0x00,0x34,0x00,0x9a,0xbc,0x00,0x24,0x01,0x83,0x00,0x20,0x00,0x29,0x01,0x83,0x40,0x0a,0x1a,0x0e,0x18,0x1a,0x20,0x1a,0x20,0x1a,0x16,0x10,0xbb,0x01,0x83,0x00,0x33, 0x00,0x2d,0x01,0x83,0x40,0x0b,0x16,0x0c,0x16,0x0a,0x0a,0x16,0x0c,0x03,0x03,0x33,0x08,0xb8,0x01,0x82,0xb7,0x03,0x04,0x99,0x07,0x07,0x0d,0x08,0x02,0xb8,0x01,0x7d,0xb7,0x01,0x18,0x0e,0x2b,0x22,0x2b,0x13,0x26,0xb8,0x01,0x7d,0x40,0x0e,0x1d,0x22,0x30,0x1d,0x01,0x1d,0x01,0x1d,0x0c,0x7f,0x0d,0x01,0x0d,0x30,0xb8,0x01,0x7d,0xb3, 0x13,0x13,0x0c,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x39,0x11,0x12,0x39,0x39,0x10,0xed,0x32,0x11,0x33,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x21, 0x35,0x33,0x11,0x07,0x35,0x25,0x11,0x33,0x01,0x01,0x23,0x01,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x14,0x17,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x02,0x43,0xfe,0x37,0xa8,0xaf,0x01,0x25,0xab,0x02,0xab,0xfc,0xf7, 0x83,0x03,0x0a,0x01,0x35,0x94,0x94,0x87,0x72,0x97,0x93,0x77,0x8b,0x76,0x6a,0x84,0xf8,0x7b,0x79,0x36,0x46,0x74,0x90,0x55,0x42,0x41,0x53,0x02,0x11,0x66,0x02,0x1a,0x32,0x71,0x57,0xfd,0x50,0x02,0x9c,0xfa,0xed,0x05,0x13,0xfc,0x83,0x41,0x8b,0x66,0x76,0x75,0x60,0x8a,0x49,0x43,0x72,0x5b,0x6e,0x69,0x55,0x79,0x10,0x34,0x4a,0x5d, 0x33,0x28,0x4d,0xa0,0x30,0x69,0x2e,0x3e,0x3d,0x2c,0x67,0x00,0x00,0x05,0x00,0x75,0xff,0xee,0x06,0x76,0x05,0x25,0x00,0x20,0x00,0x24,0x00,0x38,0x00,0x41,0x00,0x4b,0x00,0xc3,0xbc,0x00,0x3b,0x01,0x83,0x00,0x37,0x00,0x40,0x01,0x83,0x40,0x0a,0x31,0x25,0x2f,0x31,0x37,0x31,0x37,0x31,0x2d,0x27,0xbb,0x01,0x83,0x00,0x4a,0x00,0x0d, 0x01,0x82,0x40,0x09,0x11,0x09,0x1a,0x03,0x00,0x17,0x17,0x00,0x1c,0xbb,0x01,0x83,0x00,0x06,0x00,0x44,0x01,0x83,0x40,0x0f,0x2d,0x23,0x06,0x2d,0x21,0x21,0x2d,0x06,0x23,0x04,0x00,0x4a,0x00,0x19,0x09,0xb8,0x01,0x7d,0xb3,0x0a,0x0a,0x14,0x03,0xb8,0x01,0x7d,0xb7,0x1f,0x2f,0x25,0x42,0x39,0x42,0x2a,0x3d,0xb8,0x01,0x7d,0x40,0x0b, 0x34,0x39,0x34,0x47,0x1f,0x34,0x1f,0x34,0x23,0x24,0x0f,0xb8,0x01,0x7d,0xb6,0x14,0x14,0x7f,0x24,0x01,0x24,0x47,0xb8,0x01,0x7d,0xb3,0x2a,0x2a,0x23,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x33,0x2f,0xed,0x11,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x39,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x39,0x2f,0xed,0x39, 0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x10,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15, 0x16,0x15,0x14,0x06,0x23,0x22,0x01,0x01,0x23,0x01,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x14,0x17,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x75,0x5d,0x67,0x49,0x53,0xc6,0x4c,0x48,0xb3,0x83,0x55,0x53,0x4f,0x72,0x66, 0x7a,0x84,0xa1,0x9a,0x81,0x7c,0x04,0x75,0xfc,0xf7,0x83,0x03,0x0b,0x01,0x35,0x93,0x94,0x87,0x71,0x98,0x93,0x77,0x8b,0x77,0x6a,0x83,0xf8,0x7b,0x79,0x36,0x46,0x74,0x90,0x55,0x43,0x40,0x53,0x02,0x2e,0x81,0x45,0x44,0x3a,0x80,0x6a,0x7a,0x6c,0x3f,0x7e,0x2e,0x6b,0x57,0x89,0x31,0x04,0x26,0x91,0x6a,0x86,0x03,0x15,0xfa,0xed,0x05, 0x13,0xfc,0x83,0x41,0x8b,0x66,0x76,0x75,0x60,0x8a,0x49,0x43,0x72,0x5b,0x6e,0x69,0x55,0x79,0x10,0x34,0x4a,0x5d,0x33,0x28,0x4d,0xa0,0x30,0x69,0x2e,0x3e,0x3d,0x2c,0x67,0x00,0x00,0x05,0x00,0x82,0xff,0xee,0x06,0x78,0x05,0x17,0x00,0x15,0x00,0x19,0x00,0x2d,0x00,0x36,0x00,0x40,0x00,0xb6,0xbc,0x00,0x30,0x01,0x83,0x00,0x2c,0x00, 0x35,0x01,0x83,0x40,0x0a,0x26,0x1a,0x24,0x26,0x2c,0x26,0x2c,0x26,0x22,0x1c,0xb8,0x01,0x83,0xb2,0x3f,0x0c,0x11,0xbb,0x01,0x83,0x00,0x06,0x00,0x39,0x01,0x83,0x40,0x0d,0x22,0x18,0x06,0x22,0x16,0x16,0x22,0x06,0x18,0x04,0x09,0x3f,0x0e,0xb8,0x01,0x82,0xb2,0x00,0x09,0x08,0xb8,0x01,0x7d,0xb3,0x0e,0x0e,0x0a,0x03,0xb8,0x01,0x7d, 0xb7,0x14,0x1a,0x24,0x37,0x2e,0x37,0x1f,0x32,0xb8,0x01,0x7d,0x40,0x0b,0x29,0x2e,0x29,0x3c,0x14,0x29,0x14,0x29,0x1f,0x19,0x0d,0xb8,0x01,0x7d,0xb6,0x0a,0x0a,0x7f,0x19,0x01,0x19,0x3c,0xb8,0x01,0x7d,0xb3,0x1f,0x1f,0x18,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x33,0x2f,0xed,0x11,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10, 0xed,0x11,0x39,0x11,0x12,0x39,0x39,0x10,0xed,0x11,0x39,0x2f,0xed,0x01,0x2f,0xc4,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xfd,0xc4,0x10,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39,0x10,0xed,0x10,0xed,0x31,0x30,0x13,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x07,0x11,0x21,0x15,0x21,0x15,0x36,0x16,0x15, 0x14,0x06,0x23,0x22,0x01,0x01,0x23,0x01,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x14,0x17,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x82,0x67,0x4e,0x4d,0x5b,0xb9,0x8c,0x01,0x9e,0xfe,0xd6,0xa5,0xa9,0x9e,0x89,0x70,0x04, 0x6c,0xfc,0xf7,0x83,0x03,0x0b,0x01,0x34,0x94,0x94,0x87,0x72,0x97,0x93,0x77,0x8b,0x76,0x6a,0x84,0xf8,0x7b,0x79,0x36,0x46,0x74,0x90,0x55,0x42,0x41,0x53,0x02,0x25,0x84,0x3f,0x51,0x40,0x8a,0x08,0x01,0x9a,0x71,0xb5,0x0c,0x89,0x74,0x72,0x90,0x03,0x15,0xfa,0xed,0x05,0x13,0xfc,0x83,0x41,0x8b,0x66,0x76,0x75,0x60,0x8a,0x49,0x43, 0x72,0x5b,0x6e,0x69,0x55,0x79,0x10,0x34,0x4a,0x5d,0x33,0x28,0x4d,0xa0,0x30,0x69,0x2e,0x3e,0x3d,0x2c,0x67,0x00,0x00,0x05,0x00,0x93,0xff,0xee,0x05,0xfe,0x05,0x1c,0x00,0x06,0x00,0x0a,0x00,0x1e,0x00,0x27,0x00,0x31,0x00,0x9a,0xbc,0x00,0x21,0x01,0x83,0x00,0x1d,0x00,0x26,0x01,0x83,0x40,0x0a,0x17,0x0b,0x15,0x17,0x1d,0x17,0x1d, 0x17,0x13,0x0d,0xbe,0x01,0x83,0x00,0x30,0x00,0x06,0x01,0x85,0x00,0x02,0x00,0x2a,0x01,0x83,0x40,0x0f,0x13,0x01,0x09,0x02,0x13,0x07,0x07,0x13,0x02,0x09,0x01,0x05,0x30,0x03,0x03,0xb8,0x01,0x7d,0x40,0x0a,0x04,0x04,0x0a,0x0b,0x15,0x1f,0x28,0x28,0x10,0x23,0xb8,0x01,0x7d,0x40,0x0e,0x1a,0x1f,0x2d,0x1a,0x01,0x1a,0x01,0x1a,0x10, 0x7f,0x0a,0x01,0x0a,0x2d,0xb8,0x01,0x7d,0xb3,0x10,0x10,0x09,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x10,0xed,0x11,0x39,0x11,0x12,0x39,0x39,0x11,0x33,0x2f,0xed,0x01,0x2f,0x2f,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x11,0x39,0x39,0x2f,0x2f,0x12,0x39,0x39, 0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x23,0x01,0x21,0x35,0x21,0x15,0x25,0x01,0x23,0x01,0x01,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36,0x35,0x34,0x23,0x22,0x06,0x15,0x14,0x17,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x01,0x73,0x84,0x01,0x23,0xfe,0x81,0x02, 0x1b,0x02,0x09,0xfc,0xf6,0x82,0x03,0x0a,0x01,0x35,0x94,0x95,0x87,0x71,0x97,0x92,0x76,0x8a,0x77,0x6a,0x83,0xf8,0x7b,0x78,0x36,0x46,0x74,0x90,0x55,0x42,0x40,0x54,0x02,0x11,0x02,0xa0,0x6b,0x30,0x27,0xfa,0xed,0x05,0x13,0xfc,0x83,0x41,0x8b,0x66,0x76,0x75,0x60,0x8a,0x49,0x43,0x72,0x5b,0x6e,0x69,0x55,0x79,0x10,0x34,0x4a,0x5d, 0x33,0x28,0x4d,0xa0,0x30,0x69,0x2e,0x3e,0x3d,0x2c,0x67,0x00,0x00,0x01,0x00,0x69,0x00,0x00,0x04,0x1e,0x05,0x2b,0x00,0x27,0x00,0x61,0xb1,0x22,0x26,0xb8,0x01,0x84,0x40,0x0a,0x1d,0x01,0x10,0x24,0x24,0x10,0x01,0x03,0x00,0x18,0xb8,0x01,0x84,0xb3,0x07,0x20,0x00,0x02,0xbe,0x01,0x7e,0x00,0x1d,0x00,0x25,0x01,0x7e,0x00,0x22,0x00, 0x21,0x01,0x7e,0x40,0x0a,0x1e,0x1d,0x22,0x1e,0x1e,0x22,0x1d,0x03,0x26,0x13,0xbc,0x01,0x7e,0x00,0x0c,0x00,0x26,0x01,0x7e,0x00,0x01,0x00,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x01,0x2f,0x33,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x21,0x11,0x2e,0x03, 0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x04,0x1e,0xfd,0xed,0x61,0x9b,0x6c,0x3a,0x42,0x7d,0xb3,0x70,0x3e,0x71,0x2f,0x34,0x74,0x3b,0x4d,0x7a,0x52,0x2c,0x21,0x42,0x64,0x43,0x01,0xfe,0xfe,0x95,0x01,0x51,0xfe,0xaf, 0x01,0x80,0x01,0x5a,0x03,0x4c,0x80,0xa7,0x5f,0x6f,0xbb,0x87,0x4b,0x17,0x17,0x9b,0x24,0x22,0x39,0x63,0x85,0x4b,0x45,0x75,0x59,0x39,0x0a,0x01,0xba,0x7f,0xfe,0xf0,0x7f,0xfe,0xed,0x00,0x00,0x03,0x00,0x6b,0xff,0xbc,0x03,0xb5,0x05,0xa7,0x00,0x2e,0x00,0x36,0x00,0x40,0x00,0x34,0x40,0x09,0x3b,0x32,0x3f,0x03,0x28,0x15,0x15,0x42, 0x2f,0xb8,0x01,0x85,0xb6,0x28,0x3e,0x31,0x32,0x03,0x37,0x10,0xbc,0x01,0x7e,0x00,0x1b,0x00,0x37,0x01,0x7e,0x00,0x01,0x00,0x2f,0xed,0x2f,0xed,0x11,0x17,0x39,0x01,0x2f,0xed,0x12,0x39,0x2f,0x12,0x17,0x39,0x31,0x30,0x01,0x07,0x32,0x16,0x17,0x37,0x33,0x07,0x16,0x16,0x17,0x15,0x26,0x27,0x01,0x16,0x33,0x32,0x3e,0x02,0x37,0x15, 0x0e,0x03,0x23,0x22,0x27,0x07,0x23,0x37,0x26,0x27,0x07,0x23,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x37,0x01,0x14,0x17,0x13,0x0e,0x03,0x01,0x22,0x06,0x07,0x01,0x16,0x16,0x17,0x01,0x26,0x02,0xe9,0x27,0x17,0x2b,0x14,0x27,0x68,0x2c,0x0e,0x1d,0x0f,0x36,0x2b,0xfe,0xc3,0x3c,0x4b,0x2a,0x47,0x42,0x41,0x23,0x22,0x43,0x48,0x4f, 0x2f,0x52,0x48,0x15,0x67,0x20,0x26,0x23,0x2f,0x66,0x46,0x45,0x4c,0x4a,0x84,0xb4,0x6b,0x29,0xfe,0x89,0x2f,0xf2,0x41,0x6b,0x4c,0x29,0x01,0xb2,0x09,0x10,0x08,0xfe,0xe2,0x0f,0x21,0x13,0x01,0x32,0x1a,0x05,0xa7,0x7e,0x02,0x02,0x82,0x93,0x04,0x09,0x04,0x96,0x19,0x0e,0xfb,0xee,0x19,0x09,0x12,0x1b,0x13,0x88,0x10,0x17,0x11,0x08, 0x16,0x44,0x69,0x16,0x1b,0x9a,0xe8,0x55,0xe8,0x90,0x8c,0xea,0xb3,0x73,0x13,0x87,0xfc,0xd3,0x96,0x74,0x03,0x1e,0x1a,0x63,0x8a,0xab,0x01,0xce,0x01,0x01,0xfc,0x52,0x14,0x21,0x10,0x03,0xf2,0x03,0x00,0x01,0x00,0x6b,0xff,0xea,0x03,0xb5,0x05,0x29,0x00,0x3e,0x00,0x45,0xb1,0x37,0x07,0xb8,0x01,0x83,0xb3,0x34,0x34,0x00,0x2f,0xb8, 0x01,0x85,0xb4,0x1a,0x25,0x10,0x00,0x02,0xb8,0x01,0x7e,0x40,0x09,0x35,0x37,0x34,0x07,0x04,0x3b,0x3b,0x0a,0x2a,0xbc,0x01,0x7e,0x00,0x1f,0x00,0x0a,0x01,0x7e,0x00,0x15,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0x17,0x39,0xed,0x01,0x2f,0x33,0x33,0x2f,0xed,0x12,0x39,0x2f,0xed,0x32,0x31,0x30,0x01,0x26,0x23,0x22,0x07,0x06,0x15, 0x11,0x16,0x32,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x03,0xb5,0x23,0x41,0x56,0x39,0x39,0x04,0x0b,0x06,0x2a,0x47,0x42,0x41,0x23,0x22,0x43, 0x48,0x4f,0x2f,0x77,0xc7,0x90,0x51,0x5b,0xa1,0xd9,0x7e,0x28,0x40,0x3a,0x38,0x1d,0x23,0x3c,0x3a,0x3c,0x24,0x5f,0x9e,0x74,0x41,0x24,0x41,0x5c,0x39,0x85,0x03,0x1d,0x74,0x49,0x1a,0x27,0x0e,0x02,0xd1,0x1b,0x50,0x50,0x8c,0xfe,0xaa,0x01,0x09,0x12,0x1b,0x13,0x88,0x10,0x17,0x11,0x08,0x5d,0xa8,0xef,0x93,0x9c,0x01,0x00,0xb7,0x65, 0x05,0x09,0x0e,0x0a,0x96,0x11,0x16,0x0f,0x07,0x52,0x94,0xce,0x7c,0x59,0x9e,0x7f,0x5e,0x1b,0x02,0xcd,0xab,0x58,0x62,0x07,0x05,0x00,0x00,0x01,0x00,0x96,0xff,0x28,0x05,0xbc,0x04,0x93,0x00,0x2e,0x00,0x62,0xb1,0x23,0x1f,0xb8,0x01,0x84,0xb2,0x20,0x2b,0x11,0xb8,0x01,0x84,0x40,0x0d,0x16,0x15,0x20,0x12,0x00,0x01,0x12,0x01,0x12, 0x01,0x06,0x20,0x05,0xb8,0x01,0x84,0xb2,0x06,0x0f,0x19,0xb8,0x01,0x7e,0x40,0x12,0x26,0x13,0x16,0x10,0x2b,0x04,0x26,0x20,0x2e,0x2e,0x2d,0x01,0x26,0x15,0x15,0x12,0x06,0x20,0x00,0x2f,0x33,0x33,0x33,0x2f,0x2f,0x33,0x33,0x33,0x2f,0x11,0x12,0x17,0x39,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x11, 0x12,0x39,0x33,0xed,0x39,0x10,0xed,0x32,0x31,0x30,0x01,0x07,0x33,0x20,0x11,0x11,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x22,0x07,0x03,0x11,0x23,0x35,0x03,0x23,0x01,0x35,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x17,0x36,0x37,0x13,0x05,0x00,0x7a,0x03,0x01,0x33,0x95,0x0f,0x2e,0x51, 0x41,0x07,0x0b,0x07,0xcc,0x94,0xde,0x8b,0x01,0x69,0xd3,0x39,0x56,0x37,0x1b,0x95,0x95,0x04,0x63,0xbd,0x2d,0x54,0x46,0x33,0x0c,0x39,0x56,0x90,0x04,0x93,0xde,0xfe,0x87,0xfd,0xc4,0x02,0x15,0x3f,0x6b,0x4e,0x2b,0x01,0xfe,0x8f,0xfe,0x3a,0xb9,0xfe,0x6f,0x02,0x8d,0x72,0x01,0x11,0x33,0x54,0x6a,0x36,0xfd,0xef,0x03,0xa0,0x93,0xa8, 0x1b,0x32,0x47,0x2c,0x69,0x2f,0x01,0x06,0x00,0x05,0x00,0x20,0x00,0x00,0x04,0x91,0x05,0x13,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x29,0x00,0x31,0x00,0xa2,0x40,0x0f,0x2f,0x22,0x21,0x12,0x04,0x11,0x14,0x11,0x28,0x0e,0x09,0x09,0x0c,0x08,0x10,0xb8,0x01,0x83,0x40,0x0d,0x29,0x1c,0x1f,0x04,0x04,0x03,0x1d,0x05,0x28,0x03,0x2e,0x20, 0x14,0xb8,0x01,0x84,0x40,0x0b,0x15,0x17,0x00,0x00,0x19,0x01,0x15,0x29,0x13,0x0f,0x17,0xb8,0x01,0x7e,0x40,0x09,0x18,0x20,0x1c,0x0c,0x18,0x23,0x1f,0x0b,0x1b,0xb8,0x01,0x7e,0x40,0x1c,0x00,0x2e,0x08,0x04,0x00,0x0f,0x00,0x1f,0x00,0x3f,0x00,0x4f,0x00,0x04,0x18,0x00,0x18,0x00,0x02,0x25,0x15,0x11,0x2b,0x06,0x7f,0x02,0x01,0x02, 0x00,0x2f,0x71,0xc4,0x33,0x2f,0xc4,0x33,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x33,0x33,0x10,0xed,0x32,0x32,0x32,0x11,0x33,0x33,0x33,0x10,0xed,0x32,0x32,0x32,0x01,0x2f,0x33,0x33,0x33,0x2f,0x33,0x10,0xed,0x32,0x32,0x32,0x2f,0x33,0x33,0x12,0x17,0x39,0xed,0x32,0x32,0x32,0x2f,0x33,0x11,0x33,0x11,0x12,0x17,0x39,0x31,0x30, 0x13,0x33,0x11,0x33,0x13,0x21,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x11,0x23,0x03,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x05,0x33,0x27,0x23,0x01,0x33,0x26,0x35,0x35,0x23,0x01,0x23,0x16,0x15,0x15,0x33,0x27,0x26,0x20,0x8a,0xb8,0xdb,0x01,0x3e,0x88,0x8e,0x8e,0x8e,0x8e,0xaf,0xed,0xfe, 0xcc,0x89,0x8a,0x8a,0x8a,0x02,0x99,0xc2,0xff,0xfe,0xb7,0xf6,0x3e,0xb8,0x02,0x4b,0x03,0x06,0x85,0xfe,0x3b,0x04,0x06,0x79,0x57,0x19,0x03,0x55,0x01,0xbe,0xfe,0x42,0x01,0xbe,0xfe,0x42,0x7f,0x7c,0x7e,0xfe,0x24,0x01,0xdc,0xfe,0x24,0x01,0xdc,0x7e,0x7c,0x7c,0x7c,0x7c,0x7c,0xfd,0xf2,0x2d,0x91,0x56,0x02,0x79,0x2a,0x86,0x50,0xb0, 0x32,0x00,0x00,0x03,0x00,0xaa,0xff,0xea,0x05,0xdb,0x05,0x13,0x00,0x16,0x00,0x21,0x00,0x54,0x00,0x79,0xb1,0x3a,0x4c,0xb8,0x01,0x84,0xb3,0x27,0x13,0x07,0x0e,0xbb,0x01,0x85,0x00,0x1e,0x00,0x42,0x01,0x84,0x40,0x0c,0x31,0x22,0x00,0x31,0x1e,0x31,0x1e,0x31,0x07,0x27,0x18,0x06,0xb8,0x01,0x85,0x40,0x09,0x07,0x13,0x18,0x9a,0x05, 0x27,0x42,0x51,0x3d,0xb8,0x01,0x7e,0x40,0x0d,0x36,0x05,0x36,0x05,0x36,0x07,0x17,0x9a,0x7f,0x08,0x01,0x08,0x25,0xb8,0x01,0x7e,0xb4,0x51,0x51,0x01,0x07,0x18,0x00,0x3f,0x33,0x33,0x2f,0xed,0x2f,0x71,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x12,0x39,0x39,0x10,0xed,0x39,0x01,0x2f,0xed,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11, 0x33,0x33,0x10,0xed,0x10,0xed,0x11,0x39,0x10,0xed,0x32,0x31,0x30,0x21,0x23,0x03,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x16,0x17,0x01,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x01,0x16,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17, 0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x03,0xa3,0xb5,0xa0,0x47,0x80,0x44,0x99,0x01,0x3f,0x55,0x90,0x67,0x3a,0x25,0x47,0x67,0x43,0x49,0x3c,0xfe,0x65,0x84,0x39,0x61,0x46,0x28,0x81,0x80,0x01,0xee,0x38,0x75,0x3d,0xa0,0x1a,0x2d,0x3a,0x1f,0x43,0x57,0x36, 0x16,0x2a,0x4f,0x71,0x48,0x33,0x69,0x28,0x2e,0x64,0x37,0x20,0x38,0x27,0x16,0x14,0x27,0x37,0x20,0x3c,0x5b,0x3c,0x1e,0x1f,0x4a,0x77,0x58,0x3f,0x77,0x31,0x01,0x87,0xa2,0xfd,0xd7,0x05,0x13,0x2a,0x57,0x82,0x57,0x44,0x76,0x5d,0x41,0x0f,0x03,0x1b,0x7f,0x02,0xd4,0xfe,0x29,0x23,0x40,0x5d,0x3a,0x69,0x74,0xfc,0x32,0x26,0x2d,0x64, 0x1c,0x28,0x1c,0x16,0x0b,0x15,0x30,0x3b,0x46,0x2a,0x31,0x53,0x3f,0x25,0x13,0x10,0x94,0x1d,0x1c,0x0d,0x19,0x25,0x16,0x1e,0x26,0x1b,0x14,0x0a,0x14,0x2b,0x38,0x49,0x31,0x2d,0x55,0x43,0x29,0x1b,0x18,0x00,0x00,0x07,0x00,0x12,0x00,0x00,0x05,0x53,0x05,0x13,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x33,0x00,0x3b,0x00,0x43, 0x00,0x6a,0xb4,0x3b,0x33,0x05,0x01,0x09,0xb8,0x01,0x7e,0x40,0x0b,0x0a,0x28,0x24,0x20,0x1e,0x0a,0x2b,0x27,0x23,0x1d,0x0d,0xb8,0x01,0x7e,0x40,0x23,0x0e,0x40,0x1a,0x16,0x12,0x0e,0x0f,0x0e,0x1f,0x0e,0x3f,0x0e,0x4f,0x0e,0x04,0x0a,0x0e,0x0a,0x0e,0x07,0x3c,0x18,0x14,0x10,0x10,0x7f,0x14,0x01,0x14,0x37,0x36,0x2e,0x2e,0x03,0x07, 0x00,0x2f,0x33,0x33,0x11,0x33,0x33,0x2f,0x71,0x33,0x2f,0x11,0x33,0x33,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x33,0x33,0x33,0x10,0xed,0x32,0x32,0x32,0x32,0x11,0x33,0x33,0x33,0x33,0x10,0xed,0x32,0x32,0x32,0x32,0x31,0x30,0x01,0x23,0x03,0x23,0x03,0x23,0x03,0x23,0x03,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x03,0x33,0x13,0x33, 0x13,0x33,0x13,0x33,0x13,0x33,0x03,0x33,0x15,0x23,0x07,0x33,0x21,0x33,0x37,0x23,0x05,0x33,0x37,0x23,0x07,0x33,0x27,0x23,0x03,0x16,0x17,0x33,0x36,0x37,0x37,0x23,0x05,0x16,0x17,0x33,0x36,0x37,0x37,0x23,0x03,0x23,0x06,0x07,0x07,0x33,0x27,0x26,0x05,0x53,0xf4,0x5a,0x93,0x59,0xd2,0x59,0x92,0x5d,0xed,0xd3,0x17,0xbc,0xa2,0x56, 0x82,0x51,0xf4,0x55,0x78,0x50,0xe9,0x4f,0x80,0x54,0xad,0xc5,0x17,0xdb,0xfc,0x0e,0x95,0x18,0xc4,0x02,0x27,0x8f,0x16,0xbc,0xf9,0xa1,0x16,0x74,0xe0,0x0c,0x02,0x04,0x03,0x0f,0x22,0x67,0x02,0x33,0x0a,0x04,0x02,0x03,0x0d,0x20,0x62,0xd4,0x02,0x04,0x0c,0x12,0x43,0x11,0x0c,0x01,0xde,0xfe,0x22,0x01,0xde,0xfe,0x22,0x01,0xde,0x7f, 0x7b,0x80,0x01,0xbb,0xfe,0x45,0x01,0xbb,0xfe,0x45,0x01,0xbb,0xfe,0x45,0x80,0x7b,0x7b,0x7b,0x7b,0x7b,0x7b,0xfe,0x57,0x3f,0x44,0x30,0x53,0xaf,0xb7,0x33,0x46,0x2f,0x4e,0xb3,0x02,0x5c,0x43,0x40,0x5f,0x5d,0x3d,0x00,0x00,0x03,0x00,0x57,0xfe,0xf3,0x04,0x29,0x05,0x5d,0x00,0x1c,0x00,0x31,0x00,0x35,0x00,0x64,0xb4,0x14,0x14,0x01, 0x33,0x28,0xb8,0x01,0x84,0xb4,0x0a,0x32,0x1b,0x19,0x00,0xb8,0x01,0x84,0xb4,0x1d,0x16,0x12,0x01,0x33,0xbb,0x01,0x7d,0x00,0x34,0x00,0x23,0x01,0x7e,0xb2,0x0f,0x1c,0x14,0xb8,0x01,0x7e,0x40,0x0c,0x15,0x19,0x15,0x02,0x12,0x0f,0x15,0x0f,0x15,0x05,0x18,0x2d,0xb8,0x01,0x7e,0xb3,0x05,0x18,0x01,0x18,0x00,0x3f,0x3f,0xed,0x2f,0x12, 0x39,0x39,0x2f,0x2f,0x39,0x39,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x2f,0xed,0x01,0x2f,0x33,0x33,0x33,0xfd,0x32,0xc6,0xc6,0x2f,0xed,0xc4,0x12,0x39,0x2f,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x33,0x11,0x21,0x35,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x03,0x35,0x34,0x2e,0x02, 0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x13,0x21,0x35,0x21,0x03,0xae,0x94,0x04,0x67,0xd8,0x62,0x91,0x5f,0x2e,0x35,0x6a,0xa0,0x6a,0xbc,0x5a,0x04,0xfe,0xd4,0x01,0x2c,0x94,0x7b,0x7b,0x94,0x28,0x46,0x60,0x39,0x4e,0x6f,0x46,0x21,0x20,0x43,0x68,0x49,0x40,0x68,0x4a,0x26,0x70,0xfc,0xfe,0x03,0x02,0x9e,0xb4, 0x4b,0x7d,0xa9,0x5f,0x67,0xb8,0x8b,0x51,0x96,0x01,0x22,0x79,0xa3,0xa3,0x79,0xfd,0x62,0x89,0x38,0x62,0x49,0x29,0x3c,0x68,0x87,0x4c,0x44,0x7e,0x60,0x38,0x34,0x57,0x72,0xfd,0x8f,0x6c,0x00,0x01,0x00,0x26,0x00,0x00,0x03,0x9d,0x05,0x13,0x00,0x19,0x00,0x42,0xb6,0x18,0x19,0x16,0x03,0x00,0x0f,0x07,0xb8,0x01,0x85,0xb7,0x0c,0x0a, 0x08,0x15,0x00,0x19,0x06,0x0a,0xb8,0x01,0x7e,0x40,0x0d,0x16,0x10,0x0f,0x0b,0x0b,0x01,0x14,0x7f,0x0e,0x01,0x0e,0x08,0x01,0x00,0x2f,0x33,0x2f,0x71,0x33,0x12,0x39,0x2f,0x33,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x33,0x2f,0xc6,0x33,0xed,0x32,0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x01,0x26,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x35, 0x33,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x21,0x15,0x21,0x03,0x9d,0xc6,0xfe,0x92,0x0f,0x0d,0x07,0x03,0x99,0x84,0x84,0x99,0x03,0x07,0x14,0x08,0x01,0x6f,0xb0,0xfe,0x61,0x01,0x4e,0xfe,0xb9,0x02,0x1c,0x18,0x18,0x0d,0xfd,0xa7,0x02,0x5f,0x80,0x02,0x34,0xfd,0xca,0x0d,0x1e,0x0b,0x02,0x00,0xfd,0xcc,0x80,0x00,0x01, 0x00,0x25,0x00,0x00,0x03,0x1a,0x05,0x13,0x00,0x17,0x00,0x5e,0xb9,0x00,0x06,0x01,0x84,0x40,0x2c,0x07,0x15,0x11,0x9a,0x12,0x02,0x0b,0x03,0x0a,0x0a,0x09,0x0f,0x16,0x0e,0x17,0x0e,0x0d,0x08,0x05,0x09,0x04,0x04,0x03,0x0c,0x01,0x0d,0x00,0x00,0x17,0x09,0x0d,0x03,0x17,0x17,0x03,0x0d,0x09,0x04,0x07,0x7f,0x12,0x01,0x12,0x07,0x00, 0x2f,0x2f,0x71,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x10,0xed,0x32,0x01,0x2f,0xed,0x31,0x30,0x01,0x07,0x15,0x37,0x15,0x07,0x11,0x23,0x11,0x07,0x35,0x37,0x35,0x07,0x35,0x37,0x11,0x21,0x35,0x21,0x15,0x21, 0x11,0x37,0x02,0xbf,0xd4,0xd4,0xd4,0x98,0xd9,0xd9,0xd9,0xd9,0xfe,0xd2,0x02,0xf5,0xfe,0xd1,0xd4,0x03,0x5c,0x79,0xb9,0x79,0x81,0x78,0xfe,0x56,0x01,0x53,0x7a,0x80,0x7a,0xb9,0x7a,0x81,0x7a,0x01,0x7c,0x8a,0x8a,0xfe,0xdb,0x78,0x00,0x05,0x00,0x28,0xfe,0xbf,0x08,0x0c,0x05,0xdb,0x00,0x3a,0x00,0x53,0x00,0x6a,0x00,0x7e,0x00,0x8e, 0x00,0x98,0x40,0x09,0x8c,0x3e,0x0c,0x1e,0x4f,0x36,0x2f,0x24,0x00,0xb8,0x01,0x85,0x40,0x11,0x4a,0x68,0x54,0x6b,0x2a,0x1e,0x24,0x4a,0x6b,0x6b,0x4a,0x24,0x1e,0x2a,0x05,0x14,0x5e,0xbb,0x01,0x83,0x00,0x75,0x00,0x84,0x01,0x82,0x40,0x29,0x14,0x6a,0x24,0x4f,0x4f,0x36,0x0c,0x8c,0x07,0x7f,0x7f,0x3e,0x1e,0x43,0x19,0x68,0x63,0x7a, 0x59,0x19,0x59,0x29,0x29,0x59,0x19,0x03,0x0f,0x36,0x32,0x32,0x2f,0x36,0x43,0x89,0x89,0x0f,0x70,0x63,0x63,0x07,0x0f,0x00,0x2f,0x33,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x2f,0x33,0x33,0x2f,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x12,0x39,0x11,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0x11,0x33,0x11,0x33,0x2f,0x01,0x2f, 0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x11,0x33,0x33,0x33,0x11,0x33,0x33,0x33,0x31,0x30,0x01,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x36,0x36,0x37,0x36,0x36,0x37,0x0e,0x03,0x07,0x27,0x3e,0x03,0x37,0x36, 0x36,0x37,0x17,0x06,0x06,0x07,0x1e,0x03,0x05,0x06,0x02,0x07,0x1e,0x03,0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x02,0x27,0x0e,0x03,0x01,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x03,0x23,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x05,0x22,0x0e,0x02,0x15, 0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x26,0x26,0x05,0xe7,0x20,0x45,0x6d,0x9a,0xca,0x7f,0x35,0x5d,0x4f,0x45,0x1f,0x3c,0x86,0x4d,0x2a,0x43,0x2f,0x1a,0x20,0x34,0x44,0x24,0x23,0x3d,0x38,0x34,0x1a,0x30,0x50,0x23,0x21,0x55,0x37,0x52,0x8c,0x7d,0x72,0x37,0x2f,0x3f,0x90,0xa1,0xb0,0x5e,0x3d,0x91,0x58,0x32,0x40,0x62,0x28,0x7d,0xbc, 0x7d,0x3e,0xfd,0x1c,0x2d,0x69,0x40,0x1b,0x39,0x42,0x48,0x2a,0x5f,0x98,0x76,0x55,0x37,0x1b,0x36,0x67,0x99,0x63,0x18,0x2d,0x29,0x29,0x02,0xa9,0x0e,0x29,0x4a,0x74,0x58,0x38,0x5c,0x43,0x26,0x28,0x4d,0x6f,0x48,0x1e,0x39,0x31,0x27,0x0b,0x7d,0x94,0x01,0x43,0x10,0x21,0x34,0x23,0x28,0x3e,0x2a,0x16,0x12,0x21,0x31,0x1d,0x30,0x43, 0x28,0x12,0xfa,0x8c,0x13,0x23,0x1b,0x11,0x11,0x19,0x22,0x10,0x34,0x59,0x28,0x2d,0x53,0x02,0xee,0x50,0xae,0xa7,0x95,0x71,0x42,0x12,0x1f,0x29,0x15,0x39,0x36,0x19,0x2e,0x41,0x27,0x2b,0x43,0x2d,0x17,0x0e,0x1a,0x21,0x13,0x56,0xf4,0x9b,0x99,0xe1,0x55,0x0a,0x30,0x42,0x4f,0x29,0x48,0x33,0x5f,0x4a,0x2f,0x02,0x42,0x5c,0x22,0x3b, 0x1c,0x43,0x2b,0x0e,0x56,0x8c,0xc0,0xa1,0xb1,0xfe,0xff,0x57,0x13,0x21,0x19,0x0e,0x39,0x61,0x81,0x8d,0x92,0x43,0x6c,0xa9,0x79,0x46,0x09,0x29,0x67,0x7b,0x94,0xfd,0xf1,0x31,0x69,0x57,0x39,0x21,0x41,0x5e,0x3d,0x41,0x73,0x56,0x31,0x0f,0x1c,0x28,0x18,0xfe,0x55,0x02,0x40,0x1d,0x38,0x2b,0x1a,0x22,0x39,0x49,0x27,0x25,0x3c,0x2c, 0x17,0x2c,0x40,0x4b,0x13,0x0c,0x17,0x21,0x14,0x16,0x23,0x17,0x0d,0x31,0x30,0x23,0x31,0x00,0x00,0x02,0x00,0x2b,0xfe,0x7a,0x03,0x18,0x05,0x54,0x00,0x3c,0x00,0x4e,0x00,0x5e,0xb9,0x00,0x02,0x01,0x82,0xb2,0x3b,0x28,0x47,0xb8,0x01,0x83,0xb3,0x0c,0x4a,0x35,0x1b,0xbb,0x01,0x82,0x00,0x07,0x00,0x16,0x01,0x82,0x40,0x1a,0x3d,0x3b, 0x0c,0x07,0x3d,0x3d,0x07,0x0c,0x3b,0x04,0x00,0x20,0x8a,0x30,0x00,0x25,0x4a,0x1b,0x07,0x35,0x01,0x02,0x3b,0x07,0x00,0x42,0xb8,0x01,0x7d,0xb2,0x11,0x3a,0x00,0x00,0x2f,0x32,0x2f,0xed,0x12,0x17,0x39,0x2f,0x01,0x2f,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0xcd,0x32,0x10,0xfd,0xc4,0x10,0xed,0x31,0x30, 0x33,0x13,0x13,0x36,0x37,0x36,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x35,0x26,0x36,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x27,0x06,0x06,0x07,0x06,0x07,0x03,0x07,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x3e,0x03, 0x2b,0xe7,0x44,0x10,0x11,0x0f,0x25,0x14,0x23,0x43,0x34,0x20,0x1d,0x35,0x4c,0x30,0x2b,0x40,0x2b,0x15,0x0f,0x1a,0x22,0x14,0x2a,0x59,0x49,0x2d,0x38,0x64,0x88,0x4f,0x0a,0x0a,0x01,0x08,0x0b,0x21,0x49,0x3d,0x28,0x15,0x25,0x30,0x1b,0x20,0x40,0x1a,0x1d,0x1c,0x5a,0x59,0x01,0xa2,0x0d,0x17,0x1e,0x13,0x0f,0x1e,0x17,0x0d,0x3b,0x2d, 0x0d,0x16,0x11,0x0a,0x01,0xf0,0xfe,0xfe,0x32,0x3a,0x32,0x82,0x4a,0x44,0x80,0x7e,0x7d,0x41,0x39,0x5d,0x42,0x24,0x1f,0x3a,0x53,0x32,0x1f,0x5f,0x79,0x8a,0x4b,0x4c,0x9d,0xaa,0xbb,0x69,0x48,0x88,0x69,0x40,0x0b,0x08,0x06,0x0e,0x03,0x08,0x36,0x51,0x6d,0x40,0x4e,0x90,0x85,0x7b,0x3a,0x72,0xd1,0x52,0x60,0x55,0x01,0x31,0xdf,0x04, 0x6c,0x2b,0x3b,0x24,0x10,0x12,0x25,0x3b,0x2a,0x5e,0xad,0x57,0x36,0x66,0x5d,0x4e,0x00,0x04,0x00,0x22,0x00,0x00,0x04,0x20,0x05,0x13,0x00,0x1f,0x00,0x27,0x00,0x2d,0x00,0x33,0x00,0x7f,0xb3,0x30,0x2b,0x2d,0x0c,0xb8,0x01,0x85,0xb6,0x20,0x00,0x1c,0x2d,0x2f,0x24,0x19,0xb8,0x01,0x85,0x40,0x09,0x1e,0x02,0x1a,0x18,0x9a,0x2d,0x2c, 0x12,0x1c,0xb8,0x01,0x7e,0xb6,0x1d,0x24,0x0f,0x1d,0x23,0x0a,0x00,0xb8,0x01,0x7e,0x40,0x21,0x01,0x2f,0x07,0x01,0x50,0x2d,0x01,0x50,0x1d,0x01,0x1d,0x40,0x09,0x0d,0x48,0x20,0x01,0x01,0x2d,0x1d,0x01,0x01,0x1d,0x2d,0x03,0x03,0x1a,0x2e,0x9a,0x7f,0x03,0x01,0x03,0x00,0x2f,0x71,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x2b, 0x5d,0x5d,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x10,0xed,0x01,0x2f,0x33,0x33,0xed,0x32,0x32,0x32,0xc6,0x32,0x2f,0xed,0x12,0x39,0x39,0x31,0x30,0x13,0x35,0x33,0x35,0x21,0x32,0x16,0x17,0x33,0x15,0x23,0x16,0x15,0x14,0x06,0x07,0x33,0x15,0x23,0x0e,0x03,0x23,0x23,0x11,0x23,0x11,0x23,0x35,0x33, 0x35,0x05,0x34,0x27,0x21,0x15,0x21,0x36,0x36,0x01,0x32,0x36,0x37,0x21,0x15,0x11,0x15,0x21,0x26,0x26,0x23,0x22,0x88,0x01,0x59,0x91,0xc7,0x2a,0x9b,0x82,0x03,0x03,0x02,0x84,0xa5,0x19,0x50,0x69,0x7f,0x49,0x9e,0x99,0x88,0x88,0x02,0x57,0x03,0xfe,0x45,0x01,0xba,0x01,0x03,0xfe,0xd8,0x5d,0x7b,0x22,0xfe,0x70,0x01,0x94,0x20,0x73, 0x5b,0x03,0x9d,0x80,0xf6,0x7e,0x78,0x80,0x18,0x1a,0x13,0x24,0x12,0x7f,0x3c,0x5f,0x42,0x23,0xfe,0x5d,0x02,0xa3,0x7f,0x7b,0x39,0x1e,0x1b,0x7b,0x0f,0x21,0xfe,0xda,0x3f,0x38,0x77,0x02,0x5d,0x6c,0x33,0x39,0x00,0x03,0x00,0x4c,0xff,0x43,0x03,0x93,0x05,0xb8,0x00,0x1c,0x00,0x27,0x00,0x2e,0x00,0x65,0x40,0x1a,0x1c,0x2e,0x2d,0x17, 0x16,0x0f,0x06,0x0e,0x00,0x00,0x02,0x22,0x23,0x0c,0x04,0x0d,0x01,0x0d,0x13,0x0e,0x01,0x0e,0x01,0x0e,0x07,0x19,0xbe,0x01,0x84,0x00,0x2b,0x00,0x1d,0x01,0x84,0x00,0x07,0x00,0x2d,0x01,0x7e,0xb4,0x17,0x17,0x0f,0x22,0x28,0xb8,0x01,0x7e,0xb4,0x02,0x1b,0x18,0x23,0x16,0xb8,0x01,0x7e,0xb1,0x0c,0x0f,0x00,0x2f,0x33,0xed,0x32,0x3f, 0x33,0xed,0x32,0x11,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x39,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0x31,0x30,0x05,0x23,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x37,0x33,0x07,0x16,0x16,0x17,0x15,0x26,0x26,0x27,0x03,0x21,0x11,0x06,0x23,0x23,0x01,0x14,0x1e,0x02,0x17,0x13,0x0e, 0x03,0x01,0x32,0x36,0x37,0x11,0x23,0x03,0x02,0x04,0x63,0x11,0x5b,0x87,0x58,0x2c,0x3d,0x76,0xaf,0x73,0x10,0x63,0x10,0x4a,0x80,0x34,0x37,0x87,0x4b,0x29,0x01,0x43,0xa8,0xcb,0x0b,0xfe,0xcf,0x19,0x33,0x53,0x3b,0x59,0x4e,0x73,0x4d,0x25,0x01,0x46,0x3c,0x72,0x2c,0xc0,0x24,0xbd,0xcc,0x13,0x64,0x9e,0xd3,0x81,0x96,0xee,0xaa,0x5f, 0x07,0xac,0xac,0x05,0x21,0x1d,0xa0,0x2b,0x30,0x06,0xfe,0x1c,0xfd,0xce,0x6f,0x02,0x7e,0x65,0xa6,0x7d,0x53,0x13,0x03,0xf4,0x09,0x51,0x87,0xb6,0xfd,0x93,0x1e,0x1f,0x01,0x63,0xfe,0x60,0x00,0x03,0x00,0x0b,0x00,0x00,0x03,0xdd,0x05,0x13,0x00,0x17,0x00,0x1b,0x00,0x23,0x00,0x45,0xb6,0x1c,0x1d,0x1d,0x15,0x0a,0x06,0x0e,0xb8,0x01, 0x7e,0xb6,0x0f,0x18,0x03,0x0f,0x1b,0x02,0x12,0xb8,0x01,0x7e,0x40,0x0f,0x13,0x20,0x17,0x13,0x0f,0x13,0x0f,0x13,0x08,0x7f,0x15,0x01,0x15,0x0c,0x08,0x00,0x2f,0x33,0x2f,0x71,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x15,0x23,0x17,0x33, 0x15,0x23,0x13,0x23,0x03,0x21,0x03,0x23,0x13,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x13,0x33,0x13,0x01,0x21,0x27,0x21,0x13,0x23,0x06,0x07,0x03,0x33,0x03,0x26,0x03,0xc8,0xba,0x34,0x86,0x5f,0x74,0xa8,0x6b,0xfe,0x52,0x68,0xa9,0x73,0x5d,0x85,0x33,0xb8,0xe0,0xa4,0x9d,0xa4,0xfe,0x5a,0x01,0x65,0x2f,0xfe,0xf8,0x84,0x02,0x08,0x0a, 0x4b,0xbe,0x4d,0x09,0x03,0x0e,0x80,0xa2,0x80,0xfe,0x94,0x01,0x6c,0xfe,0x94,0x01,0x6c,0x80,0xa2,0x80,0x02,0x05,0xfd,0xfb,0xfe,0xde,0xa2,0x01,0xde,0x37,0x1f,0xfe,0xf8,0x01,0x08,0x1b,0x00,0x01,0x00,0x5f,0xff,0xea,0x03,0x85,0x05,0x29,0x00,0x47,0x00,0x5c,0xb3,0x3c,0x21,0x16,0x44,0xbb,0x01,0x85,0x00,0x35,0x00,0x0e,0x01,0x85, 0xb2,0x21,0x09,0x26,0xb8,0x01,0x7d,0xb4,0x27,0x06,0x27,0x01,0x2f,0xb8,0x01,0x7d,0x40,0x1b,0x30,0x46,0x30,0x20,0x27,0x01,0x0f,0x27,0x1f,0x27,0x02,0x3f,0x30,0x4f,0x30,0x02,0x27,0x30,0x27,0x30,0x11,0x3a,0x9a,0x3f,0x11,0x9a,0x1c,0x00,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x5d,0x11,0x33,0x10,0xed,0x32,0x11, 0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x32,0x11,0x39,0x31,0x30,0x01,0x23,0x07,0x06,0x07,0x06,0x07,0x21,0x15,0x21,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x36,0x37,0x23,0x35,0x33,0x36,0x37,0x36,0x37,0x36,0x37,0x21,0x35,0x21,0x36,0x37,0x36,0x35, 0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x33,0x03,0x85,0x65,0x04,0x2b,0x3b,0x2f,0x35,0x01,0x33,0xfe,0x15,0x21,0x1a,0x29,0x2e,0x8a,0x8d,0x28,0x60,0x60,0x56,0x1f,0x1a,0x54,0x5e,0x5b,0x1f,0x5c,0xa7,0x80,0x4b,0x1b,0x11,0x17,0x4c,0xb4,0x14,0x15,0x3f,0x45,0x2a,0x24,0xfe,0x51,0x02,0x44,0x17, 0x0d,0x13,0x31,0x4e,0x63,0x32,0xb4,0x73,0x57,0xc1,0x54,0xa2,0x7f,0x4e,0x18,0x23,0x02,0xf3,0x04,0x2b,0x23,0x1c,0x1c,0x61,0x14,0x15,0x1f,0x4e,0x35,0x62,0x68,0x10,0x1e,0x2c,0x1b,0xb3,0x12,0x1c,0x13,0x0a,0x25,0x54,0x85,0x60,0x48,0x39,0x21,0x1e,0x61,0x0e,0x0c,0x26,0x23,0x15,0x12,0x61,0x16,0x1b,0x25,0x32,0x35,0x4a,0x2f,0x15, 0x4f,0xab,0x2e,0x2a,0x55,0x83,0x59,0x46,0x34,0x00,0x00,0x02,0x00,0x4e,0xff,0x43,0x03,0x88,0x05,0xb8,0x00,0x18,0x00,0x21,0x00,0x38,0xb2,0x16,0x10,0x03,0xb8,0x01,0x82,0xb5,0x1f,0x0d,0x04,0x04,0x00,0x1b,0xb8,0x01,0x84,0x40,0x0d,0x09,0x13,0x00,0x20,0x15,0x9a,0x0d,0x10,0x1f,0x16,0x9a,0x05,0x02,0x00,0x2f,0x33,0xed,0x32,0x2f, 0x33,0xed,0x32,0x01,0x2f,0x33,0x2f,0xed,0x12,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x31,0x30,0x25,0x06,0x07,0x15,0x23,0x35,0x26,0x27,0x26,0x11,0x10,0x37,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x15,0x26,0x27,0x11,0x36,0x37,0x01,0x06,0x15,0x14,0x17,0x16,0x17,0x11,0x06,0x03,0x88,0x68,0x97,0x5f,0xd0,0x80,0x8c,0x9e,0x81,0xbd,0x5f, 0x9c,0x63,0x71,0x8e,0x94,0x6b,0xfd,0xd1,0x73,0x6c,0x56,0x82,0x7d,0x36,0x41,0x09,0xa9,0xa9,0x0f,0xa2,0xb2,0x01,0x22,0x01,0x38,0xc0,0x9d,0x1c,0x96,0x8f,0x01,0x35,0xa2,0x4d,0x01,0xfb,0xd4,0x06,0x51,0x03,0x40,0x96,0xfa,0xed,0x8e,0x70,0x17,0x04,0x1c,0x1c,0x00,0x05,0x00,0xaa,0xff,0x43,0x03,0x8c,0x05,0xb8,0x00,0x17,0x00,0x1e, 0x00,0x22,0x00,0x26,0x00,0x2d,0x00,0x76,0xb6,0x0c,0x10,0x1d,0x1d,0x2c,0x05,0x15,0xb8,0x01,0x82,0xb4,0x16,0x25,0x02,0x16,0x09,0xb8,0x01,0x85,0x40,0x0a,0x29,0x16,0x21,0x29,0x29,0x21,0x16,0x03,0x00,0x10,0xb8,0x01,0x85,0xb2,0x1a,0x24,0x20,0xb8,0x01,0x85,0x40,0x1c,0xa0,0x00,0xb0,0x00,0x02,0x00,0x0d,0x1c,0x1f,0x9a,0x2c,0x24, 0x24,0x01,0x1d,0x20,0x9a,0x17,0x14,0x04,0x2b,0x23,0x9a,0x05,0x7f,0x01,0x01,0x01,0x00,0x2f,0x71,0x33,0xed,0x32,0x2f,0x2f,0x33,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x39,0x01,0x2f,0x5d,0xed,0x32,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x32,0x11,0x12,0x39,0x31,0x30,0x33,0x11, 0x21,0x35,0x33,0x15,0x16,0x17,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x07,0x06,0x07,0x15,0x23,0x35,0x37,0x36,0x35,0x34,0x27,0x11,0x36,0x01,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0x13,0x36,0x35,0x34,0x27,0x11,0x36,0xaa,0x01,0x1d,0x5e,0x85,0x53,0x5c,0x78,0x69,0x7d,0x97,0x6f,0x63,0x95,0x5e,0xe5,0x40,0xc7,0x53,0xfe, 0xcb,0x84,0x84,0x84,0xb3,0x40,0x95,0x32,0x05,0x13,0xa5,0xa6,0x08,0x49,0x53,0x84,0x6e,0xa4,0x22,0x04,0x0f,0xa8,0x86,0xa6,0x68,0x5e,0x08,0xbe,0xbd,0xc9,0x40,0x6e,0xc4,0x1d,0xfe,0x34,0x0a,0x01,0xc7,0xfe,0x2d,0x01,0xd3,0x02,0x2c,0xfe,0x5d,0x01,0xa3,0xfe,0x99,0x3d,0x6d,0x9b,0x1c,0xfe,0x6f,0x0e,0x00,0x05,0x00,0x8c,0xfe,0x2f, 0x0a,0x0a,0x05,0x5d,0x00,0x1d,0x00,0x37,0x00,0x52,0x00,0x56,0x00,0x5a,0x00,0x95,0xbc,0x00,0x10,0x05,0x0a,0x00,0x0d,0x00,0x33,0x05,0x0a,0x40,0x09,0x30,0x30,0x53,0x89,0x54,0x57,0x89,0x58,0x24,0xb8,0x05,0x0a,0x40,0x0e,0x21,0x0d,0x54,0x58,0x21,0x52,0x52,0x21,0x58,0x54,0x0d,0x05,0x1a,0x4a,0xb8,0x05,0x0a,0xb2,0x3f,0x00,0x03, 0xb8,0x05,0x0a,0x40,0x0a,0x1a,0x1d,0x44,0x22,0x22,0x44,0x1d,0x03,0x0f,0x3a,0xb8,0x04,0xfb,0xb4,0x2f,0x4f,0x01,0x4f,0x1e,0xb8,0x04,0xfb,0xb6,0x2f,0x29,0x01,0x29,0x59,0x55,0x08,0xb8,0x04,0xfb,0x40,0x0b,0x58,0x54,0x2f,0x15,0x01,0x15,0x31,0x2f,0x0f,0x01,0x0f,0x00,0x2f,0x5d,0x33,0x2f,0x5d,0x33,0x33,0xed,0x32,0x32,0x2f,0x5d, 0xed,0x2f,0x5d,0xed,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x01,0x2f,0xfd,0xc6,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x33,0x10,0xed,0x10,0xed,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05, 0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x04,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x01,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x25,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x2f,0x0a,0x0a,0x20,0x47,0x71,0x51,0x5d,0x85,0x55,0x27,0x8d,0x33, 0x75,0xc0,0x8e,0x7a,0xa5,0x63,0x2b,0x0c,0x0d,0x05,0xf7,0x55,0x52,0x8d,0x31,0x56,0x73,0x40,0x3e,0x5b,0x41,0x29,0x18,0x09,0x8e,0x08,0x20,0x3e,0x01,0x45,0x71,0x50,0x4d,0x69,0x3f,0x1b,0x11,0x1c,0x25,0x14,0x92,0x17,0x24,0x1a,0x0d,0x3d,0x6e,0x97,0x59,0x2e,0x62,0x34,0xfe,0x72,0xa8,0xa8,0x01,0x23,0xa7,0xa7,0x01,0x7e,0x41,0x6e, 0x32,0x56,0x78,0x49,0x21,0x2c,0x64,0xa2,0x75,0x04,0x51,0xfb,0x9d,0x82,0xce,0x90,0x4e,0x3e,0x74,0xa5,0x68,0x39,0x76,0x44,0xfb,0x5f,0x65,0x01,0x7e,0xfe,0x7c,0x61,0x83,0x4f,0x22,0x1e,0x34,0x44,0x4f,0x55,0x2a,0x04,0x0d,0xfc,0x29,0x3a,0x60,0x43,0x26,0xfe,0x6a,0x23,0x37,0x62,0x85,0x4d,0x44,0x81,0x7b,0x77,0x39,0x3b,0x81,0x81, 0x7e,0x38,0x7d,0xc0,0x83,0x43,0x14,0x15,0x6e,0xa4,0xa4,0xa4,0x00,0x03,0x00,0x6e,0xff,0xee,0x06,0x34,0x05,0x27,0x00,0x09,0x00,0x0d,0x00,0x2e,0x00,0x82,0xb9,0x00,0x1b,0x01,0x82,0x40,0x09,0x27,0x18,0x1f,0x03,0x0f,0x25,0x25,0x0f,0x2a,0xb8,0x01,0x83,0x40,0x0b,0x14,0x0a,0x0f,0x0c,0x0c,0x0f,0x0a,0x03,0x03,0x14,0x08,0xb8,0x01, 0x82,0xb7,0x03,0x04,0x99,0x07,0x07,0x0d,0x08,0x02,0xb8,0x01,0x7d,0xb2,0x01,0x27,0x17,0xb8,0x01,0x7d,0xb3,0x18,0x18,0x11,0x1d,0xb8,0x01,0x7d,0x40,0x0b,0x22,0x01,0x22,0x01,0x22,0x0c,0x7f,0x0d,0x01,0x0d,0x11,0xb8,0x01,0x7d,0xb3,0x2d,0x2d,0x0c,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x12, 0x39,0x2f,0xed,0x39,0x10,0xed,0x32,0x11,0x33,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x01,0x21,0x35,0x33,0x11,0x07,0x35,0x25,0x11,0x33,0x01,0x01,0x23,0x01,0x03,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07, 0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x3d,0xfe,0x38,0xa7,0xae,0x01,0x24,0xab,0x02,0xef,0xfc,0xf6,0x82,0x03,0x0a,0x51,0x5d,0x67,0x49,0x53,0xc6,0x4d,0x49,0xb2,0x82,0x55,0x54,0x4f,0x72,0x67,0x79,0x83,0xa0,0x9a,0x80,0x7d,0x02,0x11,0x66,0x02,0x1a,0x32,0x71,0x57,0xfd,0x50,0x02,0x9c, 0xfa,0xed,0x05,0x13,0xfb,0x0b,0x81,0x45,0x44,0x3a,0x7f,0x6b,0x7a,0x6b,0x3e,0x7e,0x2e,0x6c,0x57,0x88,0x31,0x04,0x26,0x91,0x6a,0x86,0x00,0x03,0x00,0x80,0xff,0xee,0x06,0x32,0x05,0x25,0x00,0x16,0x00,0x1a,0x00,0x3b,0x00,0x9c,0xb9,0x00,0x28,0x01,0x82,0x40,0x09,0x2c,0x24,0x35,0x03,0x1b,0x32,0x32,0x1b,0x37,0xbb,0x01,0x83,0x00, 0x21,0x00,0x11,0x01,0x83,0x40,0x13,0x06,0x0b,0x01,0x19,0x00,0x06,0x1b,0x19,0x06,0x1b,0x17,0x17,0x1b,0x06,0x19,0x04,0x01,0x21,0x15,0xbb,0x01,0x84,0x00,0x01,0x00,0x09,0x01,0x7d,0xb4,0x0e,0x0e,0x1a,0x34,0x24,0xb8,0x01,0x7d,0xb3,0x25,0x25,0x1e,0x2a,0xb8,0x01,0x7d,0xb2,0x2f,0x02,0x15,0xb8,0x01,0x7d,0x40,0x0b,0x01,0x2f,0x01, 0x2f,0x01,0x19,0x7f,0x1a,0x01,0x1a,0x1e,0xb8,0x01,0x7d,0xb3,0x3a,0x3a,0x19,0x18,0x00,0x3f,0x33,0x2f,0xed,0x2f,0x71,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x32,0x10,0xed,0x12,0x39,0x2f,0xed,0x39,0x11,0x33,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x11, 0x39,0x2f,0x12,0x17,0x39,0xed,0x31,0x30,0x01,0x21,0x35,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x07,0x15,0x21,0x01,0x01,0x23,0x01,0x03,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x15,0x16,0x15, 0x14,0x06,0x23,0x22,0x02,0x76,0xfe,0x0a,0xd9,0x5e,0x33,0x45,0x38,0x6b,0x59,0x4d,0x88,0x6b,0x7d,0xb9,0x95,0x01,0x5e,0x02,0xb4,0xfc,0xf7,0x83,0x03,0x0a,0x51,0x5d,0x67,0x49,0x53,0xc6,0x4c,0x48,0xb3,0x83,0x55,0x53,0x4e,0x73,0x66,0x79,0x83,0xa0,0x9a,0x80,0x7c,0x02,0x11,0x67,0xd6,0x5d,0x62,0x32,0x35,0x42,0x5d,0x87,0x45,0x77, 0x62,0x8b,0xb0,0x8e,0x03,0x02,0x93,0xfa,0xed,0x05,0x13,0xfb,0x0b,0x81,0x45,0x44,0x3a,0x7f,0x6b,0x7a,0x6b,0x3e,0x7e,0x2e,0x6c,0x57,0x88,0x31,0x04,0x26,0x91,0x6a,0x86,0x00,0x00,0x02,0x00,0xb2,0x04,0x37,0x02,0xbc,0x06,0x1f,0x00,0x03,0x00,0x07,0x00,0x1f,0xbc,0x00,0x05,0x01,0x85,0x00,0x06,0x00,0x01,0x01,0x85,0xb5,0x02,0x06, 0x02,0x02,0x07,0x00,0x00,0x2f,0x32,0x32,0x2f,0x33,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x01,0x51,0x9f,0x02,0x0a,0x9f,0x06,0x1f,0xfe,0x18,0x01,0xe8,0xfe,0x18,0x01,0xe8,0x00,0x00,0x01,0x00,0xb2,0x04,0x37,0x01,0x51,0x06,0x1f,0x00,0x03,0x00,0x13,0xb9,0x00,0x01,0x01,0x85,0xb3,0x02,0x02, 0x02,0x00,0x00,0x2f,0x32,0x2f,0x01,0x2f,0xed,0x31,0x30,0x01,0x11,0x23,0x11,0x01,0x51,0x9f,0x06,0x1f,0xfe,0x18,0x01,0xe8,0x00,0x01,0x00,0x53,0x03,0x1d,0x03,0x55,0x06,0x1f,0x00,0x0e,0x00,0x0f,0xb4,0x0c,0x0b,0x03,0x03,0x0c,0x00,0x2f,0x33,0x2f,0x01,0x2f,0xcd,0x31,0x30,0x01,0x05,0x13,0x07,0x03,0x03,0x27,0x13,0x25,0x37,0x05, 0x03,0x33,0x03,0x25,0x03,0x55,0xfe,0xd4,0xd0,0x79,0xaa,0xad,0x78,0xd0,0xfe,0xd2,0x31,0x01,0x1f,0x1a,0x97,0x19,0x01,0x20,0x04,0xb7,0x3e,0xfe,0xf7,0x53,0x01,0x21,0xfe,0xdf,0x53,0x01,0x09,0x3e,0x88,0x6c,0x01,0x4c,0xfe,0xb4,0x6c,0x00,0x00,0x01,0x00,0x2b,0xfe,0xdf,0x01,0x59,0x00,0xf9,0x00,0x03,0x00,0x0f,0xb4,0x02,0x00,0x02, 0x02,0x00,0x00,0x2f,0x32,0x2f,0x01,0x2f,0x2f,0x31,0x30,0x25,0x03,0x23,0x13,0x01,0x59,0xae,0x80,0x80,0xf9,0xfd,0xe6,0x02,0x1a,0x00,0x00,0x01,0x00,0xa6,0x02,0x49,0x03,0x1e,0x02,0xde,0x00,0x03,0x00,0x0e,0xb4,0x01,0x00,0x01,0x99,0x02,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0x1e,0xfd,0x88,0x02,0x78, 0x02,0x49,0x95,0x00,0x00,0x01,0x00,0x7a,0xff,0xe8,0x01,0x6f,0x00,0xde,0x00,0x0b,0x00,0x0d,0xb3,0x09,0x03,0x06,0x00,0x00,0x2f,0x32,0x01,0x2f,0xcd,0x31,0x30,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xf4,0x33,0x47,0x47,0x33,0x33,0x48,0x48,0x18,0x48,0x32,0x33,0x49,0x49,0x33,0x32,0x48,0x00,0x02,0x00,0x7a, 0xff,0xe8,0x01,0x6f,0x04,0x77,0x00,0x0b,0x00,0x17,0x00,0x15,0xb7,0x15,0x09,0x0f,0x03,0x12,0x0c,0x00,0x06,0x00,0x2f,0x33,0x2f,0x33,0x01,0x2f,0x33,0xcd,0x32,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xf4,0x33,0x47,0x47,0x33,0x33,0x48, 0x48,0x33,0x33,0x47,0x47,0x33,0x33,0x48,0x48,0x03,0x85,0x48,0x32,0x32,0x46,0x46,0x32,0x32,0x48,0xfc,0x63,0x48,0x32,0x33,0x49,0x49,0x33,0x32,0x48,0x00,0x00,0x02,0x00,0x2b,0xfe,0xdf,0x01,0x71,0x04,0x77,0x00,0x0b,0x00,0x0f,0x00,0x1a,0x40,0x0a,0x0c,0x0c,0x0e,0x09,0x03,0x0e,0x0e,0x0f,0x00,0x06,0x00,0x2f,0x33,0x2f,0x33,0x2f, 0x01,0x2f,0xcd,0x2f,0x39,0x2f,0x31,0x30,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x03,0x23,0x13,0xf7,0x33,0x47,0x47,0x33,0x32,0x48,0x48,0x30,0xae,0x80,0x80,0x03,0x85,0x48,0x32,0x32,0x46,0x46,0x32,0x32,0x48,0xfd,0x74,0xfd,0xe6,0x02,0x1a,0x00,0x01,0x00,0x00,0xfe,0xa9,0x03,0xd7,0xff,0x32,0x00,0x03, 0x00,0x0e,0xb4,0x01,0x00,0x01,0x9a,0x02,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x01,0x21,0x35,0x21,0x03,0xd7,0xfc,0x29,0x03,0xd7,0xfe,0xa9,0x89,0x00,0x00,0x02,0x00,0x6a,0x00,0xe7,0x04,0x48,0x03,0xf9,0x00,0x05,0x00,0x0b,0x00,0x09,0xb1,0x05,0x0b,0x00,0x19,0x2f,0x33,0x31,0x30,0x25,0x23,0x01,0x01,0x33,0x01,0x03,0x23,0x01, 0x01,0x33,0x01,0x04,0x46,0xc3,0xfe,0xa7,0x01,0x59,0xc5,0xfe,0x9d,0x61,0xc0,0xfe,0xa6,0x01,0x5a,0xc0,0xfe,0xa2,0xe7,0x01,0x85,0x01,0x8d,0xfe,0x73,0xfe,0x7b,0x01,0x85,0x01,0x8d,0xfe,0x73,0x00,0x00,0x02,0x00,0x68,0x00,0xe7,0x04,0x48,0x03,0xf9,0x00,0x05,0x00,0x0b,0x00,0x09,0xb1,0x03,0x09,0x00,0x19,0x2f,0x33,0x31,0x30,0x01, 0x01,0x23,0x01,0x01,0x33,0x03,0x01,0x23,0x01,0x01,0x33,0x04,0x48,0xfe,0xa4,0xbf,0x01,0x5d,0xfe,0xa3,0xbf,0x66,0xfe,0xa7,0xc5,0x01,0x64,0xfe,0x9c,0xc5,0x02,0x6e,0xfe,0x79,0x01,0x87,0x01,0x8b,0xfe,0x75,0xfe,0x79,0x01,0x87,0x01,0x8b,0x00,0x01,0x00,0x00,0x02,0x29,0x04,0x5f,0x02,0xb6,0x00,0x03,0x00,0x11,0xb2,0x01,0x00,0x01, 0xb9,0x01,0x7f,0x00,0x02,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30,0x01,0x21,0x35,0x21,0x04,0x5f,0xfb,0xa1,0x04,0x5f,0x02,0x29,0x8d,0x00,0x02,0x00,0x6f,0x03,0xd0,0x02,0x9c,0x05,0xb2,0x00,0x14,0x00,0x29,0x00,0x32,0x40,0x18,0x21,0x0c,0x29,0x14,0x04,0x18,0x1e,0x24,0x03,0x09,0x0f,0x15,0x15,0x1e,0xaf,0x24,0x24,0x2b,0x11,0x00, 0x00,0x09,0xaf,0x0f,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x00,0x3f,0x33,0xc4,0x32,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x05,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35, 0x34,0x3e,0x02,0x37,0x01,0x61,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x01,0x6b,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x05,0x77,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11, 0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x02,0x00,0x68,0x03,0xd0,0x02,0x95,0x05,0xb2,0x00,0x14,0x00,0x29,0x00,0x2c,0x40,0x15,0x14,0x29,0x0c,0x21,0x04,0x03,0x0f,0x09,0x18,0x24,0x1e,0x00,0x0f,0xaf,0x09,0x09,0x2b,0x15,0x24,0xaf,0x1e,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0xe1,0xc6,0x11,0x12,0x39,0x11,0x12, 0x39,0x00,0x3f,0x33,0xc4,0x32,0x31,0x30,0x01,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x25,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x01,0xa3,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27, 0xfe,0x95,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x04,0x0b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x01,0x00,0x6f,0x03,0xd0,0x01,0x61, 0x05,0xb2,0x00,0x14,0x00,0x19,0x40,0x0b,0x0c,0x14,0x04,0x03,0x09,0x0f,0x00,0x00,0x09,0xaf,0x0f,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x3e,0x02,0x37,0x01,0x61,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20, 0x35,0x46,0x27,0x05,0x77,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x01,0x00,0x74,0x03,0xd0,0x01,0x66,0x05,0xb2,0x00,0x14,0x00,0x15,0x40,0x09,0x14,0x0c,0x04,0x03,0x0f,0x00,0x0f,0xaf,0x09,0x2f,0xe1,0xc6,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x13,0x36,0x36,0x35,0x34, 0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x74,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0x04,0x0b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x01,0x00,0x62,0xfe,0xed,0x01,0x4e,0x00,0xcf,0x00,0x16,0x00,0x17, 0x40,0x0a,0x16,0x0e,0xb2,0x17,0x05,0x11,0x00,0x11,0xaf,0x0b,0x2f,0xe1,0xc6,0x12,0x39,0x00,0x10,0xf4,0xc4,0x31,0x30,0x17,0x3e,0x03,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x62,0x1b,0x31,0x24,0x15,0x19,0x1d,0x28,0x1a,0x2f,0x30,0x3b,0x45,0x20,0x35,0x46,0x27,0xde,0x16,0x31,0x31, 0x2f,0x15,0x19,0x13,0x0d,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x00,0x02,0x00,0x68,0xfe,0xed,0x02,0x95,0x00,0xcf,0x00,0x14,0x00,0x29,0x00,0x2a,0x40,0x14,0x14,0x0c,0x29,0x21,0xb2,0x2a,0x18,0x24,0x1e,0x03,0x0f,0xaf,0x09,0x09,0x09,0x2b,0x15,0x24,0xaf,0x1e,0x2f,0xe1,0xc6,0x12,0x39,0x2f,0x2f,0xe1, 0x39,0x11,0x12,0x39,0x00,0x10,0xf4,0xc4,0x33,0x32,0x31,0x30,0x05,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x25,0x36,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x07,0x01,0xa3,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44, 0x20,0x35,0x46,0x27,0xfe,0x95,0x37,0x4c,0x14,0x1a,0x28,0x1a,0x30,0x33,0x38,0x44,0x20,0x35,0x46,0x27,0xd8,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x3b,0x2d,0x5f,0x2a,0x18,0x15,0x0c,0x11,0x26,0x22,0x26,0x39,0x4f,0x4e,0x37,0x5d,0x4f,0x44,0x1e,0x00,0x01,0x00,0x74,0x03,0xd0, 0x01,0x66,0x05,0xb2,0x00,0x14,0x00,0x19,0x40,0x0b,0x00,0x08,0x04,0x11,0x0b,0x05,0x14,0x14,0x0b,0xaf,0x05,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x00,0x3f,0xc4,0x31,0x30,0x01,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x36,0x27,0x46,0x35,0x20,0x44,0x38,0x33,0x30,0x1a,0x28, 0x1a,0x14,0x4c,0x37,0x03,0xd0,0x1e,0x44,0x4f,0x5d,0x37,0x4e,0x4f,0x39,0x26,0x22,0x26,0x11,0x0c,0x15,0x18,0x2a,0x5f,0x2d,0x00,0x02,0x00,0x90,0x03,0xd0,0x02,0xbd,0x05,0xb2,0x00,0x14,0x00,0x29,0x00,0x2d,0x40,0x15,0x26,0x1a,0x20,0x29,0x29,0x20,0xaf,0x1a,0x11,0x0b,0x05,0x14,0x14,0x0b,0xaf,0x05,0x15,0x00,0x1d,0x08,0x04,0x00, 0x3f,0x33,0xc4,0x32,0x01,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xf1,0xc2,0x2f,0x11,0x12,0x39,0x31,0x30,0x01,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x05,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x52,0x27,0x46,0x35, 0x20,0x44,0x38,0x33,0x30,0x1a,0x28,0x1a,0x14,0x4c,0x37,0x01,0x0b,0x27,0x46,0x35,0x20,0x44,0x38,0x33,0x30,0x1a,0x28,0x1a,0x14,0x4c,0x37,0x03,0xd0,0x1e,0x44,0x4f,0x5d,0x37,0x4e,0x4f,0x39,0x26,0x22,0x26,0x11,0x0c,0x15,0x18,0x2a,0x5f,0x2d,0x3b,0x1e,0x44,0x4f,0x5d,0x37,0x4e,0x4f,0x39,0x26,0x22,0x26,0x11,0x0c,0x15,0x18,0x2a, 0x5f,0x2d,0x00,0x03,0x00,0x8d,0xff,0xe7,0x06,0x57,0x05,0xb1,0x00,0x15,0x00,0x31,0x00,0x4d,0x00,0x40,0x40,0x1d,0x10,0x0b,0x00,0x05,0x00,0x05,0x00,0x40,0x32,0x16,0x24,0x40,0x0b,0x0b,0x0d,0x15,0x02,0x13,0x0d,0x08,0x13,0x08,0x13,0x08,0x1d,0x39,0x2b,0x47,0x1d,0x00,0x2f,0xc9,0x2f,0xc9,0x11,0x39,0x39,0x2f,0x2f,0x10,0xc9,0x10, 0xc9,0xc6,0x10,0xc2,0x2f,0x01,0x2f,0xc9,0x2f,0xc9,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xc9,0x31,0x30,0x01,0x06,0x23,0x22,0x24,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x25,0x34,0x3e,0x04,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x04,0x37,0x14,0x1e,0x04,0x33,0x32, 0x3e,0x04,0x35,0x34,0x2e,0x04,0x23,0x22,0x0e,0x04,0x04,0x80,0x69,0x8f,0xc0,0xfe,0xfc,0x01,0x0a,0xd5,0x79,0x60,0x56,0x8f,0x8d,0xb7,0xbb,0x90,0x84,0x5e,0xfc,0x0d,0x35,0x60,0x88,0xa4,0xbe,0x66,0x66,0xbe,0xa4,0x88,0x60,0x35,0x35,0x60,0x88,0xa4,0xbe,0x66,0x66,0xbe,0xa4,0x88,0x60,0x35,0x7f,0x2c,0x50,0x70,0x88,0x9d,0x55,0x54, 0x9d,0x88,0x70,0x50,0x2c,0x2c,0x50,0x70,0x88,0x9d,0x54,0x55,0x9d,0x88,0x70,0x50,0x2c,0x01,0x49,0x45,0xfa,0xbc,0xda,0x01,0x04,0x35,0x96,0x48,0xb4,0x98,0x94,0xb2,0x4e,0xfb,0x66,0xbe,0xa4,0x88,0x60,0x35,0x35,0x60,0x88,0xa4,0xbe,0x66,0x66,0xbe,0xa4,0x88,0x60,0x35,0x35,0x60,0x88,0xa4,0xbe,0x5f,0x55,0x9c,0x88,0x70,0x50,0x2c, 0x2c,0x50,0x70,0x88,0x9c,0x55,0x55,0x9d,0x88,0x70,0x50,0x2c,0x2c,0x50,0x70,0x88,0x9d,0x00,0xff,0xff,0x00,0x70,0x00,0xb2,0x01,0x50,0x04,0xde,0x02,0x07,0x00,0x1d,0x00,0x00,0x00,0xc8,0x00,0x17,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x05,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b, 0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x5b,0x00,0x6b,0x00,0x73,0x00,0x7c,0x00,0xb2,0x00,0xbc,0x00,0xc3,0x01,0x65,0x40,0xc6,0x3b,0x1b,0x38,0x18,0x37,0x2f,0x14,0x34,0x2c,0x23,0x1f,0x20,0x1c,0x0c,0x64,0x65,0x79,0x97,0x97,0xab,0x7d,0x8e,0x03,0x11,0x4d,0x50,0x51,0xa1,0x8e,0xab,0x86,0x48, 0x57,0x59,0x57,0xbe,0xb4,0xb5,0x6d,0x75,0x5c,0xb9,0xc1,0x61,0x71,0x68,0x79,0x06,0x12,0x11,0x51,0x8e,0x86,0x57,0xb5,0x5c,0xc1,0x71,0x79,0x12,0x12,0x79,0x71,0xc1,0x5c,0xb5,0x57,0x86,0x8e,0x51,0x11,0x0b,0x14,0x30,0x3c,0x40,0x05,0x04,0x0f,0x00,0x31,0x3d,0x41,0x04,0x0c,0x09,0x24,0x28,0x44,0x04,0x17,0x25,0x29,0x45,0x0a,0x04, 0x14,0x2a,0x42,0x29,0x41,0x46,0x3e,0x01,0x45,0x3d,0x3d,0x0f,0x26,0x32,0x32,0x0f,0x25,0x31,0x31,0x0f,0x97,0x97,0x9c,0x7e,0x81,0x5a,0x52,0x51,0x51,0x49,0x15,0x0d,0xb0,0x81,0xb3,0xbe,0xbd,0xb6,0x9c,0x93,0x5c,0x75,0x49,0x57,0x74,0x6d,0x6c,0x5d,0x4d,0x52,0x0a,0x00,0x0d,0xb5,0x81,0xbe,0xb6,0x93,0x75,0x57,0x6d,0x5d,0x52,0x00, 0x00,0x52,0x5d,0x6d,0x57,0x75,0x93,0xb6,0xbe,0x81,0xb5,0x0d,0x0c,0x01,0x19,0x1d,0x2d,0x13,0x04,0x0f,0x12,0x18,0x1c,0x2c,0x04,0x0c,0x20,0x34,0x38,0x06,0x04,0x04,0x07,0x21,0x35,0x39,0x04,0x01,0x00,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9,0x17,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f, 0x2f,0x2f,0x11,0x33,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x11,0x33,0x10,0xc0,0x2f,0x10,0xc4,0x10,0xc6,0x10,0xc2,0x2f,0x10,0xc0,0x2f,0x32,0x10,0xc0,0x2f,0x32,0x10,0xc0,0x2f,0x32,0x10,0xc6,0x32,0xc6,0x32,0xc6,0x32,0x01,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9, 0x17,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x32,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x32,0x11,0x33,0x10,0xc4,0x10,0xc0,0x2f,0x10,0xc5,0x32,0x10,0xc4,0x32,0xc4,0x32,0xc4,0x32,0x10,0xc4,0x32,0xc4,0x32,0xc4, 0x32,0x31,0x30,0x13,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01, 0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x05,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x15,0x23,0x11,0x33,0x13,0x16,0x17,0x33,0x26,0x35,0x35,0x33,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x03,0x15,0x33,0x32,0x36,0x35,0x34,0x23,0x07,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23, 0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x25,0x15,0x23,0x11,0x33,0x32,0x15,0x14,0x06,0x23,0x27,0x15,0x33,0x32,0x35,0x34,0x23,0xbc,0xeb,0x96, 0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0xfd,0x02,0x61,0xb2,0x0f,0x06,0x01,0x02,0x5c,0x69,0xab,0x0b,0x0a,0x01,0x02,0x5b, 0x98,0x9d,0x48,0x4d,0x2f,0x25,0x2e,0x37,0x55,0x49,0x44,0x2a,0x1e,0x23,0x47,0x24,0x34,0x22,0x26,0x25,0x22,0xfd,0x7c,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22, 0x24,0x40,0x02,0x1f,0x61,0x98,0xa2,0x5d,0x4e,0x2e,0x26,0x4d,0x4d,0x04,0xd4,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff, 0xd1,0x2c,0x01,0x0e,0x18,0x0c,0x17,0x2f,0xec,0x01,0xae,0xfe,0xfa,0x12,0x11,0x0f,0x2c,0xee,0xfe,0x52,0x01,0xae,0x35,0x30,0x23,0x34,0x0a,0x01,0x06,0x38,0x29,0x3b,0x45,0x01,0x67,0x66,0x1d,0x19,0x30,0xae,0x72,0x1f,0x1b,0x1a,0x1e,0xfd,0x3a,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30, 0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x8f,0x94,0x01,0xae,0x89,0x41,0x50,0xd0,0x86,0x43,0x43,0x00,0x00,0x15,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x05,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23, 0x00,0x27,0x00,0x2b,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x7d,0x00,0x87,0x00,0x8e,0x00,0x98,0x00,0xb4,0x01,0x57,0x40,0xbf,0x3b,0x1b,0x38,0x18,0x14,0x23,0x1f,0x20,0x1c,0x0c,0xa8,0x2f,0x2f,0x37,0x62,0x62,0x76,0x34,0x2c,0xa4,0x8f,0x8f,0x96,0x48,0x59,0x93,0x03,0x11,0x97,0x90,0x6c,0x59, 0x96,0x92,0x76,0x51,0x37,0xa4,0x89,0x7f,0x80,0x84,0x8c,0x06,0x12,0x11,0x90,0x59,0x92,0x51,0xa4,0x80,0x8c,0x12,0x99,0x99,0x12,0x8c,0x80,0xa4,0x51,0x92,0x59,0x90,0x11,0x0a,0x14,0x30,0x3c,0x40,0x05,0x04,0x0f,0x00,0x31,0x3d,0x41,0x04,0x0c,0x09,0x24,0x28,0x44,0x04,0x17,0x25,0x29,0x45,0x0a,0x04,0x14,0x2a,0x42,0x29,0x41,0x46, 0x3e,0x01,0x45,0x3d,0x3d,0x0f,0x26,0x32,0x32,0x0f,0x25,0x31,0x31,0x0f,0x62,0x62,0x67,0x49,0x4c,0xb4,0xa4,0xac,0x15,0x0d,0x7b,0x4c,0x7e,0x89,0x88,0x81,0x67,0x5e,0xa3,0x9b,0x90,0x97,0xb1,0xb0,0xa9,0xa8,0x04,0x97,0x9e,0x9f,0xac,0x93,0x94,0x0a,0x00,0x0d,0x80,0x4c,0x89,0x81,0x5e,0x97,0xac,0x94,0x00,0x00,0x94,0xac,0x97,0x5e, 0x81,0x89,0x4c,0x80,0x0d,0x0a,0x01,0x19,0x1d,0x2d,0x13,0x04,0x0f,0x12,0x18,0x1c,0x2c,0x04,0x0c,0x20,0x34,0x38,0x06,0x04,0x04,0x07,0x21,0x35,0x39,0x04,0x01,0x00,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9,0x17,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xc9,0x10,0xc9,0x32, 0x11,0x17,0x33,0x10,0xc9,0x32,0x32,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x11,0x33,0x10,0xc4,0x32,0x10,0xc6,0x10,0xc2,0x2f,0x10,0xc0,0x2f,0x32,0x10,0xc0,0x2f,0x32,0x10,0xc0,0x2f,0x32,0x10,0xc6,0x32,0xc6,0x32,0xc6,0x32,0x01,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9,0x17,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f, 0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xc9,0x10,0xc9,0x32,0x10,0xca,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x11,0x33,0xc4,0x10,0xc4,0x10,0xc0,0x2f,0x10,0xc4,0x32,0x10,0xc0,0x2f,0x10,0xc0,0x2f,0x32,0x10,0xc4,0x32,0xc4,0x32,0x10,0xc4,0x32,0xc4,0x32,0x31,0x30,0x13,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23, 0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x01,0x35,0x16, 0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x25,0x15,0x23,0x11,0x33,0x32,0x15,0x14,0x06,0x23,0x27,0x15,0x33,0x32,0x35,0x34,0x23,0x25,0x21,0x35,0x13,0x23,0x35, 0x21,0x15,0x03,0x33,0x01,0x03,0x23,0x03,0x26,0x27,0x23,0x06,0x07,0x03,0x23,0x03,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x17,0x33,0x36,0x37,0x13,0xbc,0xeb,0x96,0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1, 0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0xfb,0xac,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13,0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40, 0x02,0x1f,0x61,0x98,0xa2,0x5d,0x4e,0x2e,0x26,0x4d,0x4d,0xfe,0x82,0xfe,0xa5,0xdd,0xcd,0x01,0x4a,0xd8,0xd9,0x02,0xb6,0x71,0x6c,0x47,0x06,0x01,0x01,0x03,0x05,0x49,0x70,0x71,0x6a,0x3c,0x04,0x02,0x02,0x01,0x07,0x4e,0x68,0x47,0x04,0x03,0x01,0x01,0x05,0x3b,0x04,0xd4,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56, 0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0xfd,0xc7,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11,0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c, 0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x8f,0x94,0x01,0xae,0x89,0x41,0x50,0xd0,0x86,0x43,0x43,0xba,0x38,0x01,0x27,0x4f,0x36,0xfe,0xd6,0x01,0x60,0xfe,0x52,0x01,0x14,0x15,0x1b,0x1d,0x13,0xfe,0xec,0x01,0xae,0xfe,0xe2,0x13,0x1f,0x17,0x1c,0x01,0x1d,0xfe,0xdf, 0x10,0x1e,0x18,0x18,0x01,0x1f,0x00,0x16,0x00,0xbc,0x00,0x00,0x06,0x7c,0x05,0xc0,0x00,0x35,0x00,0x3b,0x00,0x41,0x00,0x47,0x00,0x4d,0x00,0x51,0x00,0x55,0x00,0x59,0x00,0x5d,0x00,0x61,0x00,0x65,0x00,0x69,0x00,0x6d,0x00,0x71,0x00,0x75,0x00,0x79,0x00,0x7d,0x00,0x91,0x00,0xa5,0x00,0xb5,0x00,0xbd,0x00,0xc6,0x01,0x62,0x40,0xc3, 0x71,0x51,0x6e,0x4e,0x6d,0x65,0x4a,0x6a,0x62,0x59,0x56,0x52,0x42,0x1a,0x1a,0x2e,0x00,0x11,0xae,0xaf,0xc3,0x39,0x47,0x83,0x86,0x87,0xb7,0xbf,0xa6,0xab,0xbb,0xb2,0xc3,0x7e,0x8d,0x8f,0x8d,0x97,0x9a,0x9b,0x24,0x11,0x2e,0x09,0x92,0xa1,0xa3,0xa1,0x3c,0x48,0x47,0x87,0xa6,0xbb,0xc3,0x8d,0x9b,0x11,0x09,0xa1,0x48,0x48,0xa1,0x09, 0x11,0x9b,0x8d,0xc3,0xbb,0xa6,0x87,0x47,0x0b,0x4a,0x66,0x72,0x76,0x3b,0x04,0x45,0x36,0x67,0x73,0x77,0x04,0x42,0x3f,0x5a,0x5e,0x7a,0x04,0x4d,0x5b,0x5f,0x7b,0x40,0x04,0x4a,0x60,0x78,0x5f,0x77,0x7c,0x74,0x37,0x5b,0x67,0x67,0x45,0x01,0xbf,0xa4,0x90,0x88,0x9b,0x87,0x87,0x7f,0x1a,0x7b,0x73,0x73,0xb6,0x5c,0xae,0xaf,0x03,0x68, 0xb7,0x4b,0x43,0x33,0xa6,0xbf,0x04,0xbf,0xbe,0xb7,0x1f,0xb6,0xa7,0x16,0xa7,0x93,0x7f,0x8d,0xa1,0x8d,0x97,0x83,0x88,0x9c,0x88,0x40,0x36,0x43,0xbf,0xb7,0xa7,0x8d,0x88,0x36,0x36,0x88,0x8d,0xa7,0xb7,0xbf,0x43,0x07,0x37,0x4f,0x53,0x63,0x49,0x04,0x45,0x48,0x4e,0x52,0x62,0x04,0x42,0x56,0x6a,0x6e,0x3c,0x04,0x3a,0x3d,0x57,0x6b, 0x6f,0x04,0x37,0x00,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9,0x17,0x32,0x11,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x32,0x10,0xc9,0x11,0x33,0x10,0xc9,0x32,0x11,0x33,0x10,0xc4,0x17,0x32,0x10,0xc0,0x2f,0x32,0x32,0x10,0xc0,0x2f, 0x32,0x10,0xc4,0x32,0x10,0xc4,0x10,0xc0,0x2f,0x32,0x10,0xc6,0x32,0xc6,0x32,0xc6,0x32,0x01,0x2f,0x17,0x33,0xc9,0x17,0x32,0x2f,0x17,0x33,0xc9,0x17,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x10,0xc9,0x10, 0xc9,0x10,0xc9,0x32,0x10,0xc9,0x32,0x11,0x33,0x10,0xc5,0x32,0x10,0xc4,0x10,0xc0,0x2f,0x10,0xc4,0x32,0xc4,0xc4,0x32,0x10,0xc4,0x32,0xc4,0x32,0xc4,0x32,0x31,0x30,0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14, 0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x01,0x35,0x33,0x15,0x23,0x15,0x25,0x35,0x33,0x15,0x23,0x35,0x01,0x35,0x33,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23,0x35,0x33, 0x01,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x05,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x15,0x23,0x11,0x33,0x13,0x16,0x17,0x33,0x26,0x35,0x35,0x33,0x01,0x23,0x03,0x26,0x27,0x23,0x16,0x15,0x15,0x23,0x11,0x33,0x13,0x16,0x17,0x33,0x26,0x35,0x35,0x33,0x01,0x11,0x33,0x32, 0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x03,0x15,0x33,0x32,0x36,0x35,0x34,0x23,0x07,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x04,0x10,0x1a,0x3d,0x20,0x12,0x1b,0x12,0x09,0x0e,0x19,0x22,0x14,0x32,0x32,0x1b,0x2f,0x3d,0x22,0x22,0x34,0x16,0x0b,0x1a,0x1b,0x1a,0x0c,0x11,0x1b,0x13,0x0a,0x0c,0x15,0x1e,0x13, 0x19,0x29,0x1e,0x0f,0x1b,0x2f,0x3e,0x22,0x24,0x40,0xfc,0x95,0xeb,0x96,0x04,0x7f,0xec,0x56,0xfa,0x96,0x55,0x96,0x03,0xe9,0x96,0x56,0xfd,0xe6,0xd2,0xfc,0xce,0xd3,0xd3,0xd3,0x03,0xa7,0x56,0x56,0x56,0x56,0xfc,0xb7,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0x5e,0xd2,0xfb,0xdd,0x55,0x55,0x55,0x55,0x05,0x6b,0x56,0x56,0xfc,0xe4, 0x61,0xb2,0x0f,0x06,0x01,0x02,0x5c,0x69,0xab,0x0b,0x0a,0x01,0x02,0x5b,0x02,0x01,0x61,0xb2,0x0f,0x06,0x01,0x02,0x5c,0x69,0xab,0x0b,0x0a,0x01,0x02,0x5b,0xfc,0xc7,0x9d,0x48,0x4d,0x2f,0x25,0x2e,0x37,0x55,0x49,0x44,0x2a,0x1e,0x23,0x47,0x24,0x34,0x22,0x26,0x25,0x22,0x01,0x0e,0x60,0x16,0x16,0x07,0x0c,0x0f,0x0a,0x0c,0x14,0x11, 0x10,0x08,0x15,0x3c,0x2b,0x22,0x30,0x1f,0x0f,0x08,0x09,0x59,0x07,0x0c,0x07,0x04,0x07,0x0b,0x10,0x0a,0x0b,0x11,0x0f,0x0f,0x07,0x0b,0x19,0x1e,0x27,0x1b,0x24,0x30,0x1f,0x0d,0x0c,0x03,0xd2,0xec,0x55,0x97,0x97,0x55,0xec,0x97,0xfa,0x95,0xeb,0x95,0x56,0x56,0x95,0xeb,0x56,0x56,0x56,0x56,0x05,0x6b,0x55,0x55,0xfb,0xdd,0xd2,0x01, 0x8c,0xd2,0xfb,0x88,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xfd,0xff,0xd1,0x2c,0x01,0x0e,0x18,0x0c,0x17,0x2f,0xec,0x01,0xae,0xfe,0xfa,0x12,0x11,0x0f,0x2c,0xee,0xfe,0x52,0x01,0x0e,0x18,0x0c,0x17,0x2f,0xec,0x01,0xae,0xfe,0xfa,0x12,0x11,0x0f,0x2c,0xee,0xfc,0x34,0x01,0xae,0x35,0x30, 0x23,0x34,0x0a,0x01,0x06,0x38,0x29,0x3b,0x45,0x01,0x67,0x66,0x1d,0x19,0x30,0xae,0x72,0x1f,0x1b,0x1a,0x1e,0x00,0xff,0xff,0x00,0xab,0xff,0xf2,0x04,0x15,0x05,0xec,0x00,0x26,0x08,0xc7,0x00,0x00,0x00,0x27,0x0e,0x6f,0x02,0x01,0x00,0x00,0x01,0x07,0x09,0x7e,0x02,0x73,0xfd,0x56,0x00,0x0a,0xb4,0x02,0x2f,0x3c,0x01,0x3c,0x00,0x11, 0x5d,0x35,0xff,0xff,0x00,0xab,0xff,0xf2,0x04,0xad,0x05,0xec,0x00,0x26,0x08,0xc7,0x00,0x00,0x00,0x27,0x09,0x3b,0x02,0x01,0x00,0x00,0x01,0x07,0x09,0x7e,0x02,0x73,0xfd,0x56,0x00,0x0a,0xb4,0x02,0x2f,0x3c,0x01,0x3c,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xa1,0xff,0xf2,0x06,0x16,0x05,0x3f,0x00,0x26,0x08,0xf3,0x00,0x00,0x00,0x27, 0x0e,0x6f,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x03,0x2f,0x57,0x01,0x57,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0xa1,0xff,0xf2,0x06,0xae,0x05,0x3f,0x00,0x26,0x08,0xf3,0x00,0x00,0x00,0x27,0x09,0x3b,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x03,0x2f,0x60, 0x01,0x60,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0x16,0x05,0x3f,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x0e,0x6f,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x03,0x2f,0x59,0x01,0x59,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0xae,0x05,0x3f,0x00,0x26,0x0e,0x5e, 0x00,0x00,0x00,0x27,0x09,0x3b,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x03,0x2f,0x59,0x01,0x59,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0x16,0x05,0x64,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x09,0x30,0x00,0xe4,0xfd,0x56,0x00,0x27,0x0e,0x6f,0x04,0x02,0x00,0x00,0x01,0x07, 0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0e,0xb6,0x05,0x02,0x03,0x2f,0x59,0x01,0x59,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0xae,0x05,0x64,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x09,0x30,0x00,0xe4,0xfd,0x56,0x00,0x27,0x09,0x3b,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0e, 0xb6,0x05,0x02,0x03,0x2f,0x59,0x01,0x59,0x00,0x11,0x5d,0x35,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0x16,0x05,0x3f,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x0a,0x6d,0x00,0xe5,0xfd,0x56,0x00,0x27,0x0e,0x6f,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0c,0xb5,0x04,0x02,0x2f,0x3e,0x01,0x3e,0x00, 0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0xae,0x05,0x3f,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x0a,0x6d,0x00,0xe5,0xfd,0x56,0x00,0x27,0x09,0x3b,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0c,0xb5,0x04,0x02,0x2f,0x3e,0x01,0x3e,0x00,0x11,0x5d,0x35,0x35,0xff,0xff,0x00,0x00,0xfd,0xff, 0x06,0x16,0x05,0x5a,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27,0x09,0x73,0x00,0xe5,0xfd,0x56,0x00,0x27,0x0e,0x6f,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x04,0x2f,0x5d,0x01,0x5d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x00,0xfd,0xff,0x06,0xae,0x05,0x5a,0x00,0x26,0x0e,0x5e,0x00,0x00,0x00,0x27, 0x09,0x73,0x00,0xe5,0xfd,0x56,0x00,0x27,0x09,0x3b,0x04,0x02,0x00,0x00,0x01,0x07,0x09,0x7e,0x04,0x74,0xfd,0x56,0x00,0x0a,0xb4,0x04,0x2f,0x5d,0x01,0x5d,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xfd,0xc5,0x08,0xc2,0x05,0x3f,0x00,0x26,0x0f,0x61,0x00,0x00,0x00,0x27,0x0f,0x52,0x01,0xc8,0xfd,0xca,0x00,0x27,0x0e,0x6f,0x06,0xae, 0x00,0x00,0x01,0x07,0x09,0x7e,0x07,0x20,0xfd,0x56,0x00,0x0a,0xb4,0x04,0x2f,0x6c,0x01,0x6c,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xfd,0xc5,0x09,0x5a,0x05,0x3f,0x00,0x26,0x0f,0x61,0x00,0x00,0x00,0x27,0x0f,0x52,0x01,0xc8,0xfd,0xca,0x00,0x27,0x09,0x3b,0x06,0xae,0x00,0x00,0x01,0x07,0x09,0x7e,0x07,0x20,0xfd,0x56,0x00,0x0a, 0xb4,0x04,0x2f,0x6c,0x01,0x6c,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xfd,0xca,0x04,0xc0,0x05,0x3f,0x00,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x52,0x00,0x83,0xfd,0xcf,0x00,0x27,0x0e,0x6f,0x02,0xac,0x00,0x00,0x01,0x07,0x09,0x7e,0x03,0x1e,0xfd,0x56,0x00,0x0a,0xb4,0x04,0x2f,0x55,0x01,0x55,0x00,0x11,0x5d,0x35,0xff,0xff, 0x00,0x9a,0xff,0x02,0x08,0xc2,0x05,0x3f,0x00,0x26,0x08,0xf7,0x00,0x00,0x00,0x27,0x0e,0x6f,0x06,0xae,0x00,0x00,0x01,0x07,0x09,0x7e,0x07,0x20,0xfd,0x56,0x00,0x0a,0xb4,0x02,0x2f,0x72,0x01,0x72,0x00,0x11,0x5d,0x35,0xff,0xff,0x00,0x9a,0xff,0x02,0x09,0x5a,0x05,0x3f,0x00,0x26,0x08,0xf7,0x00,0x00,0x00,0x27,0x09,0x3b,0x06,0xae, 0x00,0x00,0x01,0x07,0x09,0x7e,0x07,0x20,0xfd,0x56,0x00,0x0a,0xb4,0x02,0x2f,0x72,0x01,0x72,0x00,0x11,0x5d,0x35,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0xc0,0x05,0x3f,0x00,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0e,0x6f,0x02,0xac,0x00,0x00,0x01,0x07,0x09,0x7e,0x03,0x1e,0xfd,0x56,0x00,0x0a,0xb4,0x02,0x2f,0x4d,0x01,0x4d,0x00,0x11, 0x5d,0x35,0x00,0x02,0xff,0x0e,0x04,0x88,0x00,0xf3,0x07,0x90,0x00,0x19,0x00,0x25,0x00,0x2b,0x40,0x0d,0x0d,0x0d,0x00,0x1a,0x14,0x14,0x20,0x06,0x1d,0x14,0x17,0x17,0x0c,0xbb,0x01,0x36,0x00,0x23,0x00,0x03,0x01,0x3a,0x00,0x3f,0xc9,0x3f,0x39,0x2f,0x39,0xc9,0x01,0x2f,0xd9,0xc0,0x2f,0x2f,0xd9,0xc0,0x2f,0x31,0x30,0x13,0x14,0x06, 0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x37,0x36,0x37,0x15,0x06,0x07,0x07,0x0e,0x02,0x07,0x33,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x07,0x15,0x14,0x16,0x33,0x32,0x36,0xf3,0x83,0x6c,0x74,0x82,0x2d,0x68,0x80,0x71,0x1e,0x0e,0x34,0x58,0x46,0x42,0x26,0x06,0x02,0x3c,0x6f,0x69,0x79,0x54,0x58,0x48,0x68,0x34,0x59,0x4a,0x45, 0x54,0x05,0x8c,0x77,0x8d,0xa3,0xa0,0x78,0xaa,0x67,0x15,0x13,0x14,0x4d,0x0e,0x09,0x0e,0x0c,0x2f,0x68,0x49,0x57,0x8c,0x7a,0x59,0x67,0x62,0x3f,0x5c,0x79,0x68,0x00,0x00,0x03,0xff,0x36,0x04,0x96,0x00,0xcb,0x06,0x96,0x00,0x0c,0x00,0x13,0x00,0x1a,0x00,0x31,0x40,0x10,0x0b,0x09,0x0d,0x0d,0x04,0x00,0x14,0x11,0x18,0x04,0x17,0x11, 0x11,0x18,0x10,0x05,0xbb,0x01,0x38,0x00,0x18,0x00,0x04,0x01,0x3a,0x00,0x3f,0xc9,0x3f,0xc9,0x12,0x39,0x2f,0xc9,0x01,0x2f,0xc9,0x32,0x2f,0xc9,0x12,0x39,0x2f,0xc9,0xc4,0x31,0x30,0x13,0x14,0x06,0x23,0x23,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x27,0x34,0x23,0x23,0x15,0x33,0x32,0x17,0x34,0x23,0x23,0x15,0x33,0x32,0xcb,0x61, 0x47,0xed,0xdf,0x4c,0x57,0x62,0x75,0x65,0x59,0x85,0x7b,0x63,0x13,0x6f,0x82,0x8e,0x63,0x05,0x29,0x40,0x53,0x02,0x00,0x42,0x3b,0x64,0x15,0x0f,0x7c,0x43,0x90,0x94,0x4e,0x9e,0x00,0x01,0xff,0x72,0x04,0x96,0x00,0x8f,0x06,0x96,0x00,0x05,0x00,0x17,0xb4,0x04,0x01,0x02,0x00,0x03,0xba,0x01,0x38,0x00,0x02,0x01,0x3a,0x00,0x3f,0x3f, 0xc9,0x01,0x2f,0xc9,0x2f,0x31,0x30,0x03,0x11,0x23,0x11,0x21,0x15,0x3c,0x52,0x01,0x1d,0x06,0x50,0xfe,0x46,0x02,0x00,0x46,0x00,0x02,0xfe,0xfc,0x03,0xdb,0x01,0x05,0x06,0x96,0x00,0x0c,0x00,0x11,0x00,0x2f,0x40,0x0b,0x0a,0x11,0x11,0x00,0x10,0x03,0x04,0x0c,0x00,0x0e,0x08,0xb8,0x01,0x38,0xb5,0x10,0x0a,0x05,0x04,0x00,0x02,0xb8, 0x01,0x3a,0x00,0x3f,0xce,0x32,0xc9,0x32,0x32,0x3f,0xc9,0x01,0x2f,0xc9,0x2f,0xc9,0xc8,0x12,0x39,0x2f,0xc9,0x31,0x30,0x13,0x35,0x21,0x15,0x23,0x11,0x33,0x36,0x13,0x21,0x11,0x33,0x11,0x03,0x23,0x06,0x07,0x33,0xbf,0xfe,0x83,0x46,0x2e,0x81,0x04,0x01,0x0a,0x4c,0x9e,0x72,0x0d,0x67,0xe6,0x03,0xdb,0xbb,0xbb,0x01,0x01,0xba,0x01, 0x00,0xfe,0x46,0xfe,0xff,0x02,0x75,0xd5,0x9f,0x00,0x00,0x01,0xfe,0x84,0x04,0x96,0x01,0x7d,0x06,0x96,0x00,0x15,0x00,0x2f,0x40,0x12,0x10,0x03,0x04,0x0d,0x04,0x0a,0x09,0x04,0x13,0x13,0x04,0x09,0x0a,0x04,0x08,0x15,0x08,0x0b,0xba,0x01,0x38,0x00,0x00,0x01,0x3a,0x00,0x3f,0x3f,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f, 0x11,0x33,0x10,0xc9,0x32,0x31,0x30,0x01,0x27,0x23,0x15,0x23,0x35,0x23,0x07,0x23,0x13,0x27,0x33,0x17,0x33,0x35,0x33,0x15,0x33,0x37,0x33,0x07,0x13,0x01,0x0e,0xe5,0x02,0x4e,0x02,0xe4,0x6f,0xfe,0xee,0x68,0xdb,0x02,0x4e,0x02,0xdb,0x6a,0xf0,0xff,0x04,0x96,0xfd,0xfd,0xfd,0xfd,0x01,0x08,0xf8,0xf0,0xf0,0xf0,0xf0,0xf8,0xfe,0xf8, 0x00,0x01,0xff,0x46,0x04,0x88,0x00,0xbb,0x06,0xa1,0x00,0x21,0x00,0x37,0x40,0x13,0x1e,0x1f,0x0d,0x1b,0x11,0x11,0x0a,0x16,0x05,0x0d,0x00,0x0a,0x1f,0x0d,0x0e,0x0e,0x08,0x14,0x19,0xbb,0x01,0x39,0x00,0x08,0x00,0x03,0x01,0x3b,0x00,0x3f,0xc9,0x3f,0xc9,0x12,0x39,0x2f,0xc9,0x39,0x01,0x2f,0xc9,0x2f,0xc4,0x32,0x12,0x39,0x2f,0xc9, 0x10,0xc9,0x32,0x31,0x30,0x13,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0xbb,0x70,0x64,0x6b,0x36,0x3f,0x5d,0x88,0x95,0x32,0x30,0x82,0x37,0x39,0x4b,0x4a,0x57,0x45,0xbb,0x3a,0x30,0x38,0x46,0x05,0x21, 0x47,0x52,0x1b,0x51,0x26,0x56,0x55,0x46,0x51,0x1f,0x2c,0x25,0x4c,0x1f,0x89,0x2e,0x41,0x09,0x02,0x05,0x42,0x00,0x00,0x01,0xff,0x2c,0x04,0x96,0x00,0xd5,0x06,0x96,0x00,0x0c,0x00,0x29,0x40,0x0c,0x0a,0x0a,0x04,0x0c,0x07,0x03,0x0b,0x04,0x02,0x07,0x09,0x06,0xbb,0x01,0x38,0x00,0x04,0x00,0x00,0x01,0x3a,0x00,0x3f,0x32,0x3f,0x33, 0x39,0x39,0x01,0x2f,0xc8,0xc9,0x32,0x2f,0x12,0x39,0x2f,0x31,0x30,0x13,0x27,0x23,0x15,0x23,0x11,0x33,0x15,0x33,0x37,0x33,0x07,0x01,0x62,0xe2,0x02,0x52,0x52,0x02,0xd7,0x6c,0xee,0x01,0x00,0x04,0x96,0xf6,0xf6,0x02,0x00,0xeb,0xeb,0xf7,0xfe,0xf7,0x00,0x01,0xff,0x20,0x04,0x8f,0x00,0xe1,0x06,0x96,0x00,0x0e,0x00,0x1c,0xb4,0x07, 0x0e,0x00,0x02,0x0c,0xb8,0x01,0x38,0xb2,0x0a,0x05,0x00,0xb8,0x01,0x3a,0x00,0x3f,0xd4,0xc9,0x3f,0xc9,0x01,0x2f,0xc9,0x2f,0x31,0x30,0x13,0x11,0x23,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x11,0x8f,0x77,0x12,0x61,0x59,0x1a,0x12,0x0d,0x19,0x70,0x1e,0x01,0x0d,0x04,0x96,0x01,0xbb,0xe9,0xd9,0x07,0x47,0x09,0x01, 0xc2,0xfe,0x00,0x00,0x00,0x01,0xfe,0xec,0x04,0x96,0x01,0x15,0x06,0x96,0x00,0x10,0x00,0x17,0xb4,0x07,0x08,0x10,0x00,0x09,0xba,0x01,0x38,0x00,0x08,0x01,0x3a,0x00,0x3f,0x3f,0x01,0x2f,0xc9,0x2f,0xc9,0x31,0x30,0x13,0x11,0x07,0x03,0x23,0x03,0x27,0x11,0x23,0x11,0x33,0x13,0x17,0x37,0x13,0x33,0x11,0xc4,0x0f,0x93,0x49,0x84,0x22, 0x47,0x69,0x87,0x25,0x24,0x83,0x6d,0x04,0x96,0x01,0xa6,0x2d,0xfe,0x87,0x01,0x48,0x5e,0xfe,0x5a,0x02,0x00,0xfe,0xb2,0x65,0x63,0x01,0x50,0xfe,0x00,0x00,0x00,0x01,0xff,0x2c,0x04,0x96,0x00,0xd5,0x06,0x96,0x00,0x0b,0x00,0x27,0x40,0x0b,0x07,0x03,0x04,0x0b,0x08,0x00,0x02,0x07,0x07,0x09,0x06,0xbb,0x01,0x38,0x00,0x04,0x00,0x00, 0x01,0x3a,0x00,0x3f,0x32,0x3f,0x33,0x39,0x2f,0xc9,0x01,0x2f,0x33,0xc9,0x2f,0xc9,0x32,0x31,0x30,0x13,0x35,0x21,0x15,0x23,0x11,0x33,0x15,0x21,0x35,0x33,0x11,0x83,0xfe,0xfb,0x52,0x52,0x01,0x05,0x52,0x04,0x96,0xe8,0xe8,0x02,0x00,0xd2,0xd2,0xfe,0x00,0x00,0x00,0x02,0xff,0x04,0x04,0x89,0x00,0xfc,0x06,0xa2,0x00,0x0b,0x00,0x15, 0x00,0x1c,0xb5,0x09,0x14,0x0f,0x03,0x0c,0x06,0xbb,0x01,0x39,0x00,0x12,0x00,0x00,0x01,0x3b,0x00,0x3f,0xc9,0x3f,0xc9,0x01,0x2f,0xc9,0x2f,0xc9,0x31,0x30,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x02,0x71,0x89,0x8d,0x79,0x71,0x81,0x8a,0x6e,0x4f,0x5d,0x5b, 0x51,0xa4,0x04,0x89,0x91,0x76,0x82,0x90,0x8e,0x7c,0x7c,0x93,0x01,0xd3,0x6a,0x5e,0x5b,0x6a,0xc7,0xc6,0x00,0x01,0xff,0x2c,0x04,0x96,0x00,0xd5,0x06,0x96,0x00,0x07,0x00,0x1c,0xb5,0x03,0x04,0x07,0x00,0x02,0x05,0xbb,0x01,0x38,0x00,0x04,0x00,0x00,0x01,0x3a,0x00,0x3f,0x32,0x3f,0xc9,0x01,0x2f,0xc9,0x2f,0xc9,0x31,0x30,0x13,0x11, 0x21,0x11,0x23,0x11,0x21,0x11,0x83,0xfe,0xfb,0x52,0x01,0xa9,0x04,0x96,0x01,0xba,0xfe,0x46,0x02,0x00,0xfe,0x00,0x00,0x02,0xff,0x15,0x03,0xa9,0x00,0xec,0x06,0xa2,0x00,0x10,0x00,0x1d,0x00,0x2e,0x40,0x0c,0x0b,0x17,0x11,0x05,0x01,0x02,0x00,0x05,0x08,0x14,0x01,0x0e,0xbd,0x01,0x3b,0x00,0x1a,0x00,0x08,0x01,0x39,0x00,0x03,0x01, 0x38,0x00,0x3f,0x3f,0xc9,0x3f,0xce,0xc9,0x12,0x39,0x39,0x01,0x2f,0xc9,0x32,0x32,0x2f,0xc9,0x31,0x30,0x03,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x99,0x52,0x52,0x02,0x3c,0x75,0x64,0x6e,0x7d,0x6c,0x65,0x35,0x02,0x52, 0x40,0x46,0x59,0x4e,0x44,0x47,0x58,0x04,0xdf,0xfe,0xca,0x02,0xed,0x5a,0x66,0x8a,0x73,0x82,0x9a,0x56,0x83,0x3b,0x59,0x6c,0x6d,0x52,0x64,0x62,0x48,0x00,0x00,0x01,0xff,0x40,0x04,0x89,0x00,0xc1,0x06,0xa2,0x00,0x15,0x00,0x1c,0xb5,0x05,0x10,0x0b,0x00,0x02,0x13,0xbb,0x01,0x39,0x00,0x08,0x00,0x0d,0x01,0x3b,0x00,0x3f,0xc9,0x3f, 0xc9,0x01,0x2f,0x33,0x2f,0xc9,0x31,0x30,0x13,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0xc1,0x38,0x41,0x4f,0x65,0x5d,0x51,0x43,0x3c,0x3d,0x51,0x6b,0x88,0x93,0x77,0x46,0x31,0x06,0x35,0x27,0x72,0x58,0x58,0x6b,0x2d,0x4e,0x25,0x8c,0x74,0x7d,0x9c,0x19,0x00,0x01, 0xff,0x3e,0x04,0x96,0x00,0xc3,0x06,0x96,0x00,0x07,0x00,0x1d,0xb7,0x01,0x02,0x02,0x06,0x04,0x00,0x04,0x05,0xba,0x01,0x38,0x00,0x02,0x01,0x3a,0x00,0x3f,0x3f,0xc9,0x32,0x01,0x2f,0x2f,0x39,0x2f,0xc9,0x31,0x30,0x13,0x11,0x23,0x11,0x23,0x35,0x21,0x15,0x2a,0x52,0x9a,0x01,0x85,0x06,0x50,0xfe,0x46,0x01,0xba,0x46,0x46,0x00,0x01, 0xff,0x23,0x04,0x96,0x00,0xdd,0x06,0x96,0x00,0x10,0x00,0x1d,0xb7,0x01,0x09,0x09,0x0a,0x08,0x02,0x00,0x03,0xba,0x01,0x3a,0x00,0x00,0x01,0x38,0x00,0x3f,0x3f,0x01,0x2f,0x32,0x2f,0x33,0x39,0x2f,0xc9,0x31,0x30,0x13,0x03,0x17,0x23,0x27,0x23,0x06,0x07,0x23,0x37,0x03,0x33,0x16,0x17,0x33,0x37,0x37,0xdd,0xac,0xaa,0x60,0x7b,0x02, 0x12,0x6b,0x5e,0xae,0xa8,0x60,0x6b,0x0e,0x02,0x1a,0x65,0x06,0x96,0xfe,0xfe,0xfe,0xcc,0x20,0xac,0xfc,0x01,0x04,0xbd,0x1b,0x31,0xa7,0x00,0x01,0xff,0x06,0x03,0xdb,0x00,0xfb,0x06,0x96,0x00,0x0b,0x00,0x29,0x40,0x0a,0x09,0x06,0x06,0x00,0x05,0x02,0x0b,0x00,0x07,0x04,0xb8,0x01,0x38,0xb3,0x09,0x05,0x00,0x02,0xb8,0x01,0x3a,0x00, 0x3f,0xce,0xc9,0x32,0x3f,0x33,0x01,0x2f,0xc9,0x2f,0xc9,0x12,0x39,0x2f,0xc9,0x31,0x30,0x13,0x35,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x11,0xb4,0xfe,0x52,0x52,0x01,0x05,0x52,0x4c,0x03,0xdb,0xbb,0x02,0x00,0xfe,0x45,0x01,0xbb,0xfe,0x45,0xff,0x00,0x00,0x01,0xff,0x2f,0x04,0x96,0x00,0xd2,0x06,0x96,0x00,0x0f,0x00,0x24, 0x40,0x0b,0x08,0x05,0x0f,0x0c,0x00,0x03,0x01,0x0a,0x0a,0x0d,0x07,0xba,0x01,0x38,0x00,0x00,0x01,0x3a,0x00,0x3f,0x3f,0x33,0x39,0x2f,0xcd,0xc9,0x01,0x2f,0x33,0xc9,0x2f,0xc9,0x31,0x30,0x13,0x35,0x06,0x23,0x22,0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x37,0x35,0x33,0x11,0x81,0x57,0x4f,0xac,0x52,0x61,0x49,0x56,0x51,0x04,0x96,0xce, 0x31,0xb6,0xad,0xa9,0x71,0x2b,0xeb,0xfe,0x04,0x00,0x00,0x01,0xfe,0xba,0x04,0x96,0x01,0x47,0x06,0x96,0x00,0x0b,0x00,0x29,0x40,0x0b,0x07,0x04,0x04,0x00,0x0b,0x08,0x03,0x00,0x09,0x05,0x02,0xb8,0x01,0x38,0xb2,0x07,0x03,0x00,0xb8,0x01,0x3a,0x00,0x3f,0xc9,0x32,0x3f,0x33,0x33,0x01,0x2f,0xc9,0x2f,0xc9,0x12,0x39,0x2f,0xc9,0x31, 0x30,0x01,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0xfe,0xba,0x52,0xcc,0x52,0xcb,0x52,0x04,0x96,0x02,0x00,0xfe,0x46,0x01,0xba,0xfe,0x46,0x01,0xba,0xfe,0x00,0x00,0x01,0xfe,0x93,0x03,0xdb,0x01,0x6d,0x06,0x96,0x00,0x0f,0x00,0x37,0x40,0x10,0x09,0x06,0x0d,0x0a,0x06,0x0a,0x06,0x0a,0x00,0x05,0x02,0x0f,0x00,0x0b, 0x07,0x04,0xb8,0x01,0x38,0xb4,0x0d,0x09,0x05,0x00,0x02,0xb8,0x01,0x3a,0x00,0x3f,0xce,0xc9,0x32,0x32,0x3f,0x33,0x33,0x01,0x2f,0xc9,0x2f,0xc9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x31,0x30,0x01,0x35,0x21,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x01,0x25,0xfd,0x6e,0x52,0xcb,0x52,0xcc,0x52, 0x4d,0x03,0xdb,0xbb,0x02,0x00,0xfe,0x45,0x01,0xbb,0xfe,0x45,0x01,0xbb,0xfe,0x45,0xff,0x00,0x00,0x03,0xff,0x04,0x04,0x89,0x00,0xfc,0x06,0xa1,0x00,0x0b,0x00,0x1b,0x00,0x28,0x00,0x40,0x40,0x19,0x27,0x09,0x19,0x1f,0x13,0x03,0x19,0x13,0x1f,0x0c,0x27,0x10,0x21,0x25,0x1f,0x27,0x21,0x21,0x27,0x1f,0x25,0x04,0x16,0x1c,0x06,0xbb, 0x01,0x39,0x00,0x16,0x00,0x00,0x01,0x3b,0x00,0x3f,0xc9,0x3f,0xc9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x32,0x01,0x2f,0xc9,0x32,0x2f,0xc9,0x33,0x31,0x30,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x22,0x27,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x37,0x06,0x06, 0x03,0x22,0x06,0x07,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x26,0x02,0x73,0x87,0x8c,0x79,0x73,0x80,0x89,0x29,0x16,0x36,0x32,0x15,0x0d,0x29,0x27,0x08,0x5c,0x45,0x48,0x51,0x0a,0x1d,0x30,0x55,0x49,0x59,0x08,0x48,0x19,0x13,0x39,0x3b,0x0c,0x0e,0x4a,0x10,0x04,0x89,0x8f,0x78,0x80,0x91,0x8c,0x7d,0x7c,0x91,0xcc,0x1b,0x1a,0x10, 0x0c,0x4b,0x57,0x4e,0x55,0x0b,0x0f,0x01,0x05,0x55,0x4d,0x18,0x19,0x1b,0x1d,0xa1,0x00,0x01,0xfe,0x94,0x04,0x88,0x01,0x6c,0x06,0x96,0x00,0x17,0x00,0x30,0x40,0x0d,0x01,0x02,0x0d,0x02,0x0d,0x02,0x12,0x16,0x07,0x12,0x00,0x04,0x15,0xbd,0x01,0x38,0x00,0x0a,0x00,0x0f,0x01,0x3b,0x00,0x02,0x01,0x3a,0x00,0x3f,0x3f,0xc9,0x3f,0xc9, 0x32,0x01,0x2f,0xc9,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc9,0x31,0x30,0x13,0x11,0x23,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x15,0xd3,0x52,0xe0,0x56,0x64,0x58,0x4b,0x44,0x3a,0x39,0x48,0x6d,0x86,0x8d,0x7c,0x01,0xcf,0x06,0x50,0xfe,0x46,0x01,0xba,0x65,0x59,0x55, 0x6e,0x2d,0x4e,0x26,0x8c,0x75,0x7d,0x90,0x46,0x00,0x00,0x02,0xff,0x36,0x04,0x89,0x00,0xcb,0x06,0xa2,0x00,0x14,0x00,0x1e,0x00,0x3a,0x40,0x12,0x0f,0x0f,0x19,0x08,0x1e,0x0b,0x00,0x01,0x15,0x0f,0x12,0x0b,0x0b,0x1b,0x02,0x05,0x0d,0x12,0xbd,0x01,0x39,0x00,0x1b,0x00,0x05,0x01,0x3b,0x00,0x01,0x01,0x3a,0x00,0x3f,0x3f,0xc9,0x3f, 0xc9,0x12,0x39,0x12,0x39,0x2f,0x12,0x39,0xc9,0x01,0x2f,0xc9,0x33,0x33,0x2f,0xd9,0xc0,0x2f,0x31,0x30,0x13,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x15,0x07,0x07,0x06,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0xcb,0x52,0x02,0x35,0x68,0x4e,0x56,0xa4,0x9f,0x6a,0x5c,0x4a,0x40, 0x6e,0xb4,0x52,0x7c,0x42,0x31,0x64,0x3a,0x51,0x04,0x96,0x50,0x5d,0x52,0x43,0x8d,0x18,0x18,0x81,0x3e,0x54,0x30,0xbe,0x4a,0x13,0x0a,0x2a,0x2e,0x56,0x54,0x40,0x00,0x00,0x02,0xff,0x21,0x04,0x89,0x00,0xdf,0x06,0xa2,0x00,0x11,0x00,0x17,0x00,0x2d,0x40,0x0e,0x06,0x06,0x00,0x12,0x17,0x01,0x0b,0x01,0x05,0x17,0x17,0x03,0x14,0x0e, 0xbb,0x01,0x39,0x00,0x03,0x00,0x08,0x01,0x3b,0x00,0x3f,0xc9,0x3f,0xc9,0x12,0x39,0x2f,0x39,0xc9,0x01,0x2f,0xc9,0x32,0x2f,0xd9,0xc2,0x2f,0x31,0x30,0x13,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x27,0x26,0x23,0x22,0x06,0x07,0xdf,0xfe,0x98,0x04,0xa1,0x56,0x4a,0x41,0x71,0x6d,0x7c, 0x86,0x65,0x64,0x6f,0x53,0x02,0x7e,0x3a,0x52,0x09,0x05,0x81,0xb2,0x39,0x4e,0x31,0x8b,0x80,0x76,0x98,0x80,0x76,0x1a,0x96,0x51,0x45,0x00,0x01,0xff,0x27,0x04,0x96,0x00,0xda,0x06,0x96,0x00,0x19,0x00,0x4c,0x40,0x1f,0x04,0x08,0x01,0x17,0x17,0x14,0x0d,0x19,0x19,0x13,0x14,0x06,0x06,0x0c,0x0d,0x10,0x17,0x08,0x17,0x07,0x19,0x00, 0x04,0x00,0x17,0x00,0x17,0x00,0x02,0x14,0x0d,0xba,0x01,0x3a,0x00,0x02,0x01,0x38,0x00,0x3f,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x01,0x2f,0xd9,0xc0,0x2f,0x2f,0xd9,0xc0,0x2f,0x11,0x12,0x39,0x2f,0x33,0xc9,0x32,0x31,0x30,0x03,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x16,0x16,0x15, 0x15,0x23,0x35,0x34,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x37,0x35,0x23,0xae,0x86,0x52,0x85,0x85,0x57,0x59,0x52,0x85,0x8a,0x52,0xb1,0x86,0x06,0x3a,0x5c,0x5c,0x43,0x4c,0x0a,0x78,0x6a,0x29,0x32,0xa1,0xa1,0x32,0x2c,0xd8,0x12,0x4b,0x00,0x00,0x02,0xff,0x18,0x04,0x88,0x00,0xe8,0x07,0x8c,0x00,0x12,0x00,0x1c,0x00,0x3b,0x40,0x1a, 0x10,0x08,0x0c,0x19,0x00,0x16,0x08,0x19,0x16,0x16,0x19,0x08,0x03,0x06,0x0f,0x1b,0x09,0x06,0x19,0x0c,0x09,0x0c,0x09,0x0f,0x13,0x03,0xb8,0x01,0x3b,0x00,0x3f,0xc9,0x2f,0x39,0x39,0x2f,0x2f,0xc9,0x01,0x2f,0xc6,0xc9,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc9,0x11,0x33,0x10,0xc9,0x31,0x30,0x13,0x14,0x06,0x23,0x22,0x26,0x35, 0x34,0x37,0x03,0x33,0x16,0x17,0x37,0x13,0x33,0x03,0x16,0x16,0x07,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x15,0x14,0x5d,0x44,0x34,0x35,0x47,0x47,0x98,0x5f,0x59,0x0e,0x09,0xa5,0x5c,0xda,0x23,0x2c,0x7a,0x19,0x10,0x0f,0x1d,0x26,0x04,0xf8,0x30,0x40,0x3d,0x36,0x37,0x89,0x01,0x20,0xb6,0x23,0x16,0x01,0x74,0xfe,0x30,0x3e,0x5e,0x52, 0x21,0x0e,0x10,0x2d,0x3a,0x4f,0x28,0x2f,0x00,0x02,0xfe,0xf7,0x04,0x96,0x01,0x0a,0x07,0x8c,0x00,0x12,0x00,0x19,0x00,0x3b,0x40,0x19,0x0f,0x0b,0x17,0x08,0x04,0x04,0x06,0x0d,0x00,0x13,0x06,0x16,0x0f,0x0e,0x06,0x07,0x0b,0x07,0x0f,0x07,0x0f,0x07,0x09,0x17,0x04,0xb8,0x01,0x3a,0x00,0x3f,0xc9,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x33, 0x10,0xc9,0x32,0x10,0xc9,0x01,0x2f,0x2f,0xc9,0xc4,0x12,0x39,0x2f,0x33,0xc9,0x32,0x32,0x31,0x30,0x01,0x14,0x06,0x23,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x32,0x16,0x07,0x34,0x23,0x23,0x15,0x33,0x32,0x01,0x0a,0x5c,0x48,0xe3,0x8c,0x8c,0x52,0x9c,0x9c,0x89,0x4f,0x5d,0x54,0x68,0x79,0x7a,0x67,0x05, 0x36,0x47,0x59,0x02,0x59,0x43,0x5a,0x5a,0x43,0xfe,0xe2,0x51,0x4a,0x55,0xaf,0x00,0x00,0x02,0xfe,0xa2,0x04,0x8a,0x01,0x5e,0x06,0xa2,0x00,0x12,0x00,0x1a,0x00,0x3b,0x40,0x10,0x15,0x0a,0x03,0x03,0x06,0x10,0x19,0x09,0x05,0x06,0x04,0x09,0x09,0x17,0x13,0x0d,0xbf,0x01,0x39,0x00,0x07,0x01,0x38,0x00,0x06,0x01,0x3a,0x00,0x17,0x00, 0x00,0x01,0x3b,0x00,0x3f,0xc9,0x3f,0x3f,0x3f,0xc9,0x12,0x39,0x2f,0xc9,0x01,0x2f,0xc9,0x32,0x2f,0xc9,0x12,0x39,0x2f,0x33,0xc9,0x31,0x30,0x13,0x22,0x26,0x27,0x23,0x15,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x15,0x14,0x33,0x32,0x35,0x34,0x6c,0x6a,0x79,0x04,0x91,0x52,0x52,0x92,0x0d,0x7c, 0x69,0x70,0x76,0x81,0x6c,0x99,0x9b,0x97,0x04,0x8a,0x7f,0x75,0xe8,0x02,0x00,0xd2,0x66,0x78,0x8e,0x7c,0x7f,0x8f,0x01,0xd3,0xc8,0xc6,0xc7,0xc7,0x00,0x02,0xfe,0xc2,0x04,0x8a,0x01,0x3f,0x06,0xa2,0x00,0x1b,0x00,0x26,0x00,0x5e,0x40,0x1d,0x0f,0x0b,0x0c,0x15,0x15,0x1c,0x09,0x07,0x07,0x00,0x0c,0x22,0x1b,0x11,0x00,0x15,0x15,0x13, 0x18,0x0a,0x0f,0x23,0x11,0x0f,0x11,0x0f,0x11,0x1f,0x18,0xbd,0x01,0x39,0x00,0x0d,0x01,0x38,0x00,0x00,0x00,0x0c,0x01,0x3a,0xb4,0x01,0x02,0x02,0x1f,0x04,0xb8,0x01,0x3b,0x00,0x3f,0xd9,0xc0,0x2f,0x32,0x3f,0x33,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x10,0xd9,0xc2,0x2f,0x01,0x2f,0x33,0xc9,0x33,0x2f,0x12,0x39, 0x2f,0xcd,0xd9,0xc0,0x2f,0x10,0xc9,0x32,0x31,0x30,0x13,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x23,0x15,0x23,0x11,0x33,0x15,0x21,0x37,0x34,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x15,0x11,0x25,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x07,0x06,0x06,0xed,0x02,0x32,0x6b,0x4c,0x57,0x1c,0xb3,0x52,0x52,0x01,0x38,0xa1,0x69,0x5b, 0x4c,0x47,0x67,0xb4,0xfe,0xc0,0x3a,0x28,0x3f,0x4d,0x7c,0x42,0x30,0x04,0x96,0x50,0x5c,0x51,0x43,0x3c,0x24,0xe8,0x02,0x00,0xd2,0x16,0x83,0x3f,0x54,0x30,0xbf,0xfe,0xb3,0x8e,0x2a,0x2b,0x57,0x3c,0x37,0x12,0x0a,0x2b,0x00,0x02,0xff,0x07,0x04,0x96,0x00,0xfa,0x06,0x96,0x00,0x08,0x00,0x14,0x00,0x47,0x40,0x1b,0x00,0x00,0x0d,0x07, 0x0e,0x04,0x03,0x0b,0x08,0x10,0x0e,0x08,0x08,0x0e,0x10,0x03,0x09,0x12,0x09,0x0b,0x10,0x10,0x08,0x0a,0x03,0x04,0x13,0xb8,0x01,0x38,0xb2,0x12,0x0e,0x0a,0xb8,0x01,0x3a,0x00,0x3f,0x33,0x33,0x3f,0xc9,0x32,0x12,0x39,0x39,0x11,0x33,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc9,0xc6,0x32,0x10,0xc4,0xd9,0xc0,0x2f,0x31, 0x30,0x13,0x27,0x26,0x27,0x23,0x06,0x06,0x07,0x17,0x17,0x23,0x27,0x07,0x15,0x23,0x35,0x27,0x07,0x23,0x13,0x33,0x3a,0x26,0x0e,0x04,0x02,0x02,0x08,0x2f,0x3d,0xf6,0x58,0x4c,0x30,0x4b,0x32,0x4e,0x54,0xd6,0x51,0x05,0xa3,0x69,0x22,0x25,0x14,0x23,0x75,0x46,0xcb,0xc6,0x3b,0x8b,0x8b,0x3c,0xc7,0x02,0x00,0x00,0x00,0x02,0xfe,0xee, 0x04,0x96,0x01,0x12,0x06,0x96,0x00,0x12,0x00,0x17,0x00,0x51,0x40,0x20,0x12,0x12,0x0e,0x13,0x03,0x04,0x0f,0x16,0x0c,0x04,0x16,0x16,0x04,0x0c,0x03,0x0d,0x13,0x14,0x09,0x0d,0x0f,0x0c,0x02,0x05,0x16,0x0c,0x16,0x0c,0x16,0x00,0x14,0x0d,0xb8,0x01,0x38,0xb2,0x09,0x04,0x00,0xb8,0x01,0x3a,0x00,0x3f,0x32,0x32,0x3f,0xc9,0x12,0x39, 0x39,0x2f,0x2f,0x10,0xc9,0x32,0x11,0x33,0x01,0x2f,0xc6,0xc9,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x10,0xd9,0xc2,0x2f,0x31,0x30,0x13,0x26,0x27,0x15,0x23,0x35,0x06,0x06,0x07,0x23,0x36,0x36,0x37,0x27,0x21,0x07,0x16,0x16,0x17,0x03,0x23,0x17,0x17,0x37,0xbb,0x12,0x80,0x4e,0x44,0x47,0x0b,0x57,0x15,0x5c,0x57, 0x9f,0x01,0xda,0xa4,0x53,0x5b,0x17,0xa8,0xc9,0x5b,0x07,0x04,0x04,0x96,0xb3,0x26,0xd9,0xda,0x15,0x68,0x5d,0x7e,0x7c,0x1b,0xeb,0xec,0x1b,0x7a,0x7f,0x01,0xbc,0x91,0x0f,0x08,0x00,0x02,0xfe,0xb2,0x04,0x96,0x01,0x4f,0x06,0x96,0x00,0x17,0x00,0x1c,0x00,0x69,0x40,0x2d,0x17,0x17,0x13,0x18,0x19,0x12,0x03,0x04,0x14,0x1b,0x12,0x0a, 0x11,0x04,0x1b,0x1b,0x04,0x11,0x0a,0x12,0x05,0x0d,0x18,0x10,0x0c,0x08,0x08,0x0c,0x0d,0x02,0x05,0x1b,0x0b,0x10,0x14,0x1b,0x10,0x10,0x1b,0x14,0x03,0x00,0x19,0x0e,0x12,0xb8,0x01,0x38,0xb3,0x0d,0x08,0x04,0x00,0xb8,0x01,0x3a,0x00,0x3f,0x32,0x32,0x32,0x3f,0xc4,0xc9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x32,0x01, 0x2f,0xd9,0xc2,0x2f,0x11,0x33,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xc9,0x10,0xc9,0x10,0xc9,0x10,0xd9,0xc2,0x2f,0x31,0x30,0x13,0x26,0x27,0x15,0x23,0x35,0x06,0x07,0x23,0x36,0x37,0x23,0x15,0x23,0x11,0x33,0x15,0x33,0x27,0x21,0x07,0x16,0x16,0x17,0x03,0x23,0x17,0x17,0x37,0xf8,0x11,0x82,0x4e,0x86,0x0f,0x57,0x1e, 0x72,0xb7,0x52,0x52,0xdf,0x8f,0x01,0xda,0xa4,0x54,0x5a,0x17,0xa8,0xc9,0x5a,0x07,0x09,0x04,0x96,0xb0,0x29,0xd9,0xda,0x29,0xb1,0xb7,0x35,0xec,0x02,0x00,0xd4,0xd4,0xec,0x1c,0x76,0x82,0x01,0xbc,0x91,0x0f,0x0f,0x00,0x00,0x01,0x00,0x21,0xfe,0x99,0x04,0x7b,0x05,0x9a,0x00,0x25,0x00,0x3f,0x40,0x21,0x06,0x1a,0x0a,0x0a,0x1a,0x06, 0x03,0x00,0x03,0x09,0x0e,0x7f,0x05,0x00,0x09,0x06,0x91,0x07,0x03,0x1d,0x92,0x16,0x16,0x03,0x23,0x92,0x1a,0x11,0x04,0x0a,0x91,0x03,0x12,0x00,0x3f,0xed,0x39,0xd4,0x32,0xed,0x12,0x39,0x2f,0xed,0x3f,0xed,0x39,0x01,0x2f,0xc4,0xfd,0xc4,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x31,0x30,0x05,0x34,0x23,0x21,0x35,0x01,0x21,0x35,0x21, 0x15,0x01,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x03,0xe8,0xa4,0xfc,0xdd,0x03,0x41,0xfd,0x02,0x04,0x00,0xfc,0xb8,0x02,0x2a,0x94,0xa1,0x8b,0x73,0x45,0x8b,0x50,0x5d,0x4e,0x40,0x41,0x8c,0x87,0x78,0x4a,0x79,0x3f,0x30,0x64,0x32, 0x37,0x45,0x79,0x79,0x2f,0x04,0xd3,0x98,0x28,0xfb,0x26,0x87,0x7f,0x6f,0x8a,0x2e,0x24,0x29,0x43,0x33,0x73,0x85,0x29,0x19,0x13,0x26,0x3e,0x00,0x00,0x01,0x00,0x21,0xfe,0xa9,0x03,0x9e,0x04,0x00,0x00,0x22,0x00,0x40,0x40,0x22,0x18,0x06,0x0a,0x05,0x05,0x0a,0x06,0x18,0x04,0x00,0x03,0x09,0x0d,0xed,0x00,0x09,0x06,0x95,0x07,0x0f, 0x1b,0x96,0x14,0x14,0x03,0x20,0x96,0x18,0x10,0x04,0x0a,0x95,0x03,0x15,0x00,0x3f,0xed,0x39,0xd4,0x32,0xed,0x12,0x39,0x2f,0xed,0x3f,0xed,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x31,0x30,0x05,0x34,0x23,0x21,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x20,0x15,0x14,0x06,0x23,0x22,0x27,0x26,0x23,0x22, 0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x17,0x16,0x33,0x32,0x36,0x03,0x11,0x99,0xfd,0xa9,0x02,0x5e,0xfd,0xdb,0x03,0x16,0xfd,0xa2,0x01,0x7b,0x01,0x11,0x7a,0x67,0x65,0x9b,0x52,0x46,0x39,0x39,0x81,0x78,0x6e,0x44,0x82,0x4b,0x50,0x2e,0x36,0x34,0x72,0x72,0x33,0x03,0x41,0x8c,0x2f,0xfc,0xbb,0xf5,0x6a,0x84,0x4c,0x28,0x40,0x30, 0x6f,0x7e,0x2c,0x22,0x26,0x3e,0x00,0x01,0x00,0x21,0xfe,0x99,0x04,0x7b,0x05,0x9a,0x00,0x2d,0x00,0x5a,0x40,0x30,0x2d,0x1b,0x03,0x1b,0x0b,0x2c,0x07,0x07,0x2c,0x0b,0x1b,0x03,0x05,0x27,0x2a,0x09,0x06,0x0f,0x7f,0x02,0x27,0x1e,0x92,0x17,0x17,0x2a,0x24,0x92,0x1b,0x12,0x2b,0x0b,0x91,0x2a,0x0a,0x2d,0x92,0x07,0x00,0x00,0x04,0x2a, 0x12,0x06,0x03,0x91,0x04,0x03,0x00,0x3f,0xed,0x39,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x39,0xd4,0x32,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xc4,0xfd,0xc4,0xc4,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x31,0x30,0x13,0x21,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x21,0x01,0x21,0x32,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x27,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x17,0x17,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x21,0x35,0x01,0x21,0xa2,0x01,0x85,0x01,0x3b,0xfd,0x02,0x04,0x00,0xfe,0x78,0x01,0x38,0xfe,0x72,0xfe,0x96,0x02,0x2a,0xa2,0x93,0x8b,0x72,0x42,0x7d,0x61,0x61,0x4a,0x40,0x42,0x8c,0x87,0x79,0x5c,0x69,0x3e, 0x30,0x63,0x32,0x37,0x44,0xa4,0xfc,0xdd,0x01,0xae,0xfe,0xd3,0x03,0x2e,0x01,0xd4,0x98,0x28,0xfd,0xbc,0x80,0xfd,0xea,0x7e,0x88,0x6f,0x8a,0x27,0x2b,0x29,0x43,0x33,0x73,0x85,0x2a,0x18,0x13,0x26,0x3e,0x2e,0x79,0x2f,0x02,0x7f,0x00,0x01,0x00,0x21,0xfe,0xa9,0x03,0x9e,0x04,0x00,0x00,0x2c,0x00,0x5a,0x40,0x31,0x1b,0x03,0x2c,0x0b, 0x2b,0x07,0x02,0x02,0x07,0x2b,0x0b,0x2c,0x03,0x1b,0x07,0x26,0x29,0x09,0x06,0x0f,0xed,0x26,0x1e,0x96,0x17,0x17,0x29,0x23,0x96,0x1b,0x12,0x2a,0x0b,0x95,0x29,0x0a,0x2c,0x96,0x07,0x00,0x00,0x04,0x29,0x15,0x06,0x03,0x95,0x04,0x0f,0x00,0x3f,0xed,0x39,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x39,0xd4,0x32,0xed,0x12,0x39, 0x2f,0xed,0x01,0x2f,0xfd,0xc4,0xc4,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x31,0x30,0x13,0x21,0x13,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x21,0x03,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x23,0x21,0x35,0x01, 0x23,0x7d,0x01,0x31,0xd1,0xfd,0xdb,0x03,0x16,0xfe,0xec,0x01,0x04,0xfe,0xa4,0xf2,0x01,0x7f,0x80,0x8d,0x7c,0x6b,0x40,0x97,0x2f,0x4c,0x45,0x36,0x37,0x81,0x76,0x6a,0x41,0x7d,0x4f,0x54,0x2f,0x39,0x36,0x76,0xfd,0x86,0x01,0x33,0xd7,0x02,0x54,0x01,0x20,0x8c,0x2f,0xfe,0x83,0x7a,0xfe,0xb2,0x7f,0x76,0x69,0x85,0x33,0x19,0x28,0x40, 0x30,0x70,0x7d,0x2b,0x23,0x26,0x3e,0x2a,0x72,0x33,0x01,0xa7,0x00,0x01,0x00,0x77,0xff,0xe8,0x03,0xdc,0x05,0xb2,0x00,0x27,0x00,0x29,0x40,0x16,0x00,0x1a,0x7d,0x0d,0x22,0x7d,0x13,0x06,0x13,0x0d,0x22,0x27,0x04,0x03,0x10,0x91,0x17,0x04,0x24,0x91,0x03,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0xc4,0xed,0x2f,0xfd, 0xc4,0x31,0x30,0x25,0x06,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x04,0x15,0x14,0x06,0x06,0x07,0x0e,0x02,0x15,0x14,0x21,0x32,0x36,0x37,0x03,0xdc,0x3f,0xcb,0x5d,0xf1,0xfe,0xf3,0xae,0xce,0x8f,0x74,0x34,0x9b,0x96,0x5e,0x8e,0x5a,0x4f,0x88,0x5e,0xef,0x01, 0x03,0x43,0x92,0x8f,0x9d,0x7a,0x38,0x01,0x34,0x63,0xe0,0x3e,0x3a,0x26,0x2c,0xb6,0xa9,0x91,0xd8,0x66,0x48,0x55,0x5d,0x44,0x5a,0x6c,0x24,0x34,0xbd,0x1e,0x15,0xbd,0xad,0x5d,0x8e,0x7a,0x49,0x50,0x5e,0x65,0x44,0xc4,0x4a,0x37,0x00,0x01,0x00,0x70,0xff,0xe8,0x03,0x17,0x04,0x18,0x00,0x22,0x00,0x29,0x40,0x16,0x00,0x16,0x83,0x0b, 0x1d,0x83,0x10,0x05,0x10,0x0b,0x1d,0x22,0x04,0x02,0x0e,0x95,0x13,0x10,0x1f,0x95,0x02,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0xc4,0xed,0x2f,0xfd,0xc4,0x31,0x30,0x25,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x0e,0x02,0x15, 0x14,0x33,0x32,0x36,0x37,0x03,0x17,0x70,0xa2,0xc6,0xcf,0x87,0x9e,0x82,0x56,0x6a,0x60,0x91,0x73,0x68,0x86,0xb5,0xd3,0x75,0x9e,0x6c,0x53,0x2b,0xd8,0x52,0x99,0x3c,0x25,0x3d,0x88,0x85,0x71,0x9c,0x3e,0x34,0x55,0x3c,0x40,0x49,0x4a,0xa6,0x2e,0x91,0x7e,0x72,0x91,0x40,0x2c,0x36,0x41,0x2b,0x86,0x35,0x2e,0x00,0x00,0x01,0x00,0xbc, 0xff,0xf0,0x02,0xc8,0x05,0x9a,0x00,0x11,0x00,0x1f,0x40,0x0f,0x09,0x7e,0x06,0x00,0x7f,0x0f,0x10,0x10,0x03,0x07,0x03,0x0c,0x91,0x03,0x13,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x01,0x2f,0xed,0x2f,0xed,0x31,0x30,0x25,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x02,0xc8,0x8b,0x79,0x7d, 0x8b,0xa8,0x3c,0x2d,0x2c,0x37,0x98,0xfa,0x7d,0x8d,0x9a,0x93,0x04,0x7d,0xfb,0x82,0x54,0x45,0x3b,0x3d,0x2b,0x00,0x00,0x01,0x00,0xa6,0xff,0xf0,0x02,0xa5,0x04,0x00,0x00,0x11,0x00,0x22,0xb3,0x09,0x84,0x06,0x00,0xb8,0x01,0x2e,0x40,0x0a,0x0f,0x10,0x10,0x03,0x07,0x0f,0x0c,0xec,0x03,0x16,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x01, 0x2f,0xed,0x2f,0xed,0x31,0x30,0x25,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x02,0xa5,0x85,0x78,0x7b,0x87,0xa3,0x38,0x31,0x2a,0x34,0x95,0xf1,0x76,0x8b,0x98,0x8b,0x02,0xed,0xfd,0x12,0x4a,0x48,0x38,0x3b,0x28,0x00,0x01,0x00,0xaa,0x00,0x00,0x04,0xd5,0x05,0x9a,0x00,0x19,0x00,0x4d, 0x40,0x29,0x12,0x16,0x7e,0x0f,0x0b,0x0b,0x07,0x00,0x0d,0x06,0x7e,0x07,0x14,0x19,0x7e,0x00,0x16,0x03,0x91,0x0b,0x15,0x0d,0x92,0x0e,0x12,0x0e,0x00,0x0b,0x10,0x0b,0x02,0x0b,0x0e,0x0b,0x0e,0x07,0x10,0x03,0x00,0x07,0x12,0x00,0x3f,0x33,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x33,0x01,0x2f,0xfd, 0xc4,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x2f,0x33,0xed,0x32,0x31,0x30,0x21,0x11,0x10,0x21,0x20,0x11,0x11,0x23,0x11,0x10,0x12,0x37,0x35,0x21,0x35,0x21,0x35,0x33,0x15,0x21,0x15,0x21,0x15,0x04,0x11,0x11,0x04,0x2d,0xfe,0x99,0xfe,0x8c,0xa8,0xe0,0xe2,0xfe,0xba,0x01,0x46,0xa8,0x01,0x46,0xfe,0xba,0x01,0xc1,0x01,0x7c,0x01,0xaa,0xfe, 0x47,0xfe,0x93,0x01,0x78,0x01,0x08,0x01,0x28,0x11,0x99,0x8a,0xbe,0xbe,0x8a,0x9b,0x2e,0xfd,0xd8,0xfe,0x9f,0x00,0x00,0x01,0x00,0x7d,0x00,0x00,0x03,0xe4,0x04,0x00,0x00,0x19,0x00,0x47,0x40,0x24,0x14,0x19,0x0d,0x07,0x12,0x16,0x84,0x0f,0x0b,0x0b,0x00,0x07,0x84,0x08,0x19,0x84,0x00,0x15,0x0d,0x96,0x12,0x0e,0x0e,0x08,0x10,0x03, 0x96,0x16,0x0b,0x0b,0x08,0x10,0x0f,0x00,0x08,0x15,0x00,0x3f,0x33,0x3f,0x12,0x39,0x2f,0x33,0xed,0x11,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xc4,0x10,0xc4,0x31,0x30,0x21,0x35,0x10,0x21,0x22,0x06,0x15,0x15,0x23,0x35,0x10,0x25,0x35,0x21,0x35,0x21,0x35,0x33,0x15,0x21,0x15, 0x21,0x15,0x04,0x11,0x15,0x03,0x40,0xfe,0xf5,0x8b,0x89,0xa4,0x01,0x62,0xfe,0xf5,0x01,0x0b,0xa4,0x01,0x0b,0xfe,0xf5,0x01,0x61,0x6b,0x01,0x3c,0xa1,0xa7,0x5f,0x58,0x01,0xac,0x28,0x96,0x86,0xb8,0xb8,0x86,0x97,0x2c,0xfe,0x54,0x53,0x00,0x00,0x02,0x00,0x48,0xff,0xe7,0x05,0x73,0x05,0x9a,0x00,0x16,0x00,0x35,0x00,0x55,0x40,0x18, 0x2b,0x1d,0x7e,0x07,0x10,0x23,0x28,0x23,0x28,0x23,0x04,0x17,0x0f,0x13,0x7d,0x17,0x2e,0x7d,0x08,0x04,0x20,0x25,0x1a,0x2b,0xb8,0x01,0x05,0x40,0x10,0x07,0x10,0x0c,0x07,0x25,0x07,0x25,0x07,0x00,0x0e,0x08,0x03,0x32,0x92,0x00,0x13,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x11,0x33,0x01, 0x2f,0xc4,0xed,0x2f,0xfd,0xc4,0x11,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0xc4,0xfd,0xcd,0x31,0x30,0x05,0x22,0x24,0x26,0x35,0x34,0x36,0x37,0x01,0x33,0x01,0x17,0x33,0x37,0x01,0x33,0x01,0x16,0x16,0x15,0x14,0x06,0x04,0x01,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x06, 0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x02,0xe9,0xca,0xfe,0xcb,0xa2,0xfe,0xed,0xfe,0x69,0xdc,0x01,0x34,0x36,0x06,0x31,0x01,0x2b,0xca,0xfe,0x88,0xe1,0xfc,0xa4,0xfe,0xd6,0x01,0x1c,0xd1,0xb0,0x46,0x36,0x2a,0x33,0x38,0x43,0x4f,0x4e,0x69,0x7a,0x32,0x39,0xb2,0xdb,0x73,0xf1,0x92,0x8f,0xd8,0x6a,0x19,0x6e,0xc8,0x86,0xad, 0xe5,0x26,0x02,0x3f,0xfe,0x20,0x5e,0x56,0x01,0xe8,0xfd,0xc3,0x26,0xdc,0xa4,0x8d,0xd3,0x70,0x01,0xca,0x88,0xa3,0x0c,0x60,0x71,0x2b,0x21,0x2f,0x1f,0x89,0x1d,0x64,0x59,0x48,0x7f,0x4e,0x14,0xa6,0x82,0x61,0x8f,0x54,0x52,0x95,0x00,0x02,0x00,0x19,0xff,0xe7,0x03,0xb6,0x05,0xed,0x00,0x14,0x00,0x20,0x00,0x3b,0x40,0x1e,0x0e,0x1e, 0x09,0x15,0x84,0x07,0x12,0x00,0x84,0x1b,0x07,0x1b,0x07,0x1b,0x0a,0x11,0x0a,0x0e,0x12,0x1e,0x03,0x0a,0x0a,0x04,0x10,0x00,0x18,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x17,0x39,0x01,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0xc5,0x10,0xfd,0xc5,0xc6,0x32,0x31,0x30,0x25,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34, 0x13,0x01,0x33,0x13,0x16,0x17,0x37,0x01,0x33,0x01,0x16,0x16,0x05,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x02,0xa2,0x3c,0x6e,0x45,0x71,0x87,0x8d,0xfe,0xd1,0xbe,0x92,0x20,0x1c,0x13,0x01,0x46,0xb8,0xfe,0x4e,0x4f,0x4f,0xfe,0xba,0x2c,0x27,0x26,0x2c,0x32,0x27,0x28,0x24,0xc6,0x3b,0x68,0x3c,0x7e,0x67,0x79,0x01, 0x07,0x02,0x40,0xfe,0xd5,0x42,0x45,0x2d,0x02,0xe6,0xfc,0x62,0x87,0xb5,0x43,0x2b,0x32,0x32,0x2b,0x23,0x85,0x47,0x59,0x6e,0x00,0x01,0x00,0x5e,0xff,0xe8,0x08,0xaa,0x05,0xb2,0x00,0x32,0x00,0x49,0x40,0x28,0x1e,0x02,0x1e,0x02,0x17,0x09,0x7d,0x30,0x24,0x7d,0x17,0x00,0x21,0x91,0x1b,0x10,0xee,0x02,0x1e,0x1e,0x1b,0x0f,0x2a,0x1f, 0x2a,0x2f,0x2a,0x03,0x2a,0x2a,0x13,0x05,0x1b,0x04,0x2d,0x27,0x91,0x0d,0x13,0x13,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0x12,0x39,0x2f,0x5d,0x12,0x39,0x11,0x33,0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x01,0x22,0x07,0x35,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x22,0x26,0x27, 0x06,0x06,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x36,0x37,0x16,0x16,0x33,0x32,0x00,0x11,0x10,0x00,0x06,0x14,0xa8,0x66,0x71,0x9b,0xc5,0x01,0x2e,0xa5,0xa4,0xfe,0xd0,0xc6,0x5e,0xd2,0x5b,0x5a,0xd6,0x5d,0xc5,0xfe,0xcf,0xa4,0xa2,0x01,0x2e,0xc8,0xa1,0x6b, 0x2e,0x8f,0x51,0xdc,0xfe,0xf6,0x01,0x0c,0xf2,0x6f,0xc9,0x3f,0x42,0xc2,0x75,0xef,0x01,0x0f,0xfe,0xf8,0x05,0x1a,0x45,0xb2,0x2b,0xb9,0xfe,0xaa,0xdf,0xd9,0xfe,0xb3,0xb6,0x2c,0x2a,0x29,0x2d,0xb6,0x01,0x4c,0xd8,0xda,0x01,0x57,0xbf,0x2b,0xb2,0x20,0x25,0xfe,0xbc,0xfe,0xf0,0xfe,0xee,0xfe,0xcb,0x35,0x2b,0x2b,0x35,0x01,0x31,0x01, 0x16,0x01,0x11,0x01,0x43,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x06,0xc6,0x04,0x18,0x00,0x2b,0x00,0x47,0x40,0x26,0x0c,0x20,0x0c,0x20,0x06,0x27,0x83,0x1b,0x11,0x83,0x06,0x1e,0x0e,0xec,0x09,0x00,0xec,0x20,0x0c,0x0c,0x09,0x16,0x40,0x09,0x0c,0x48,0x16,0x16,0x02,0x23,0x09,0x10,0x18,0x14,0x95,0x2a,0x02,0x16,0x00,0x3f,0x33,0xed, 0x32,0x3f,0x33,0x12,0x39,0x2f,0x2b,0x12,0x39,0x11,0x33,0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x25,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x00,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32, 0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x03,0x96,0x93,0xaf,0x98,0xe4,0x78,0x01,0x0a,0xdc,0x80,0x67,0x69,0x82,0x93,0xa7,0xc1,0xa7,0xa5,0x7f,0x80,0xa2,0xa9,0xbf,0xa5,0x93,0x83,0x69,0x6a,0x7e,0x90,0xdd,0x77,0xfe,0xf3,0xe6,0xae,0x42,0x5a,0x84,0xf3,0x9b,0xf6,0x01,0x28,0x30,0xaa,0x49,0xd2,0xb9,0xb9,0xcf,0x63,0x63,0xd0,0xb8,0xb8, 0xd3,0x49,0xaa,0x30,0x87,0xf7,0xa0,0xef,0xfe,0xdd,0x00,0x02,0xff,0xf3,0x00,0x00,0x04,0x5a,0x05,0xb2,0x00,0x14,0x00,0x1d,0x00,0x2d,0x40,0x17,0x00,0x1a,0x7e,0x08,0x08,0x0e,0x04,0x7d,0x15,0x0e,0x19,0x91,0x00,0x00,0x08,0x0c,0x92,0x11,0x04,0x1a,0x91,0x08,0x12,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0x2f,0xed, 0x12,0x39,0x2f,0xed,0x32,0x31,0x30,0x01,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x01,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x01,0x86,0x01,0x1d,0xcb,0xec,0xf5,0xda,0xfe,0x53,0x4a,0x51,0x26,0x2a,0x2f,0x3e,0x8e,0x98,0x02,0x23,0xa1,0x9d,0xe5,0xe7,0x9a,0xa2,0x03, 0x3a,0xd0,0xbe,0xc5,0xe7,0x04,0x05,0x9f,0x83,0x15,0x8e,0x12,0xce,0xbf,0xfd,0x7d,0x86,0x7a,0xfd,0xf6,0x8c,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x04,0x19,0x04,0x18,0x00,0x06,0x00,0x1b,0x00,0x2d,0x40,0x17,0x13,0x04,0x84,0x1b,0x1b,0x00,0x0c,0x17,0x83,0x00,0x03,0x95,0x13,0x13,0x0f,0x04,0x95,0x1b,0x15,0x0a,0x95,0x0f,0x10,0x00, 0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x2f,0xed,0x32,0x31,0x30,0x01,0x34,0x23,0x23,0x11,0x33,0x32,0x01,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x15,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x03,0x71,0xce,0xf4,0xf6,0xcc,0xfd,0x9a,0x3b,0x4a,0x30,0x24,0x39,0x37,0x83,0x8a,0x01, 0x14,0x9b,0xbb,0xb5,0x91,0xfe,0x38,0x01,0x40,0xaa,0xfe,0xa2,0x02,0x5b,0x50,0x57,0x0f,0x88,0x11,0x99,0x91,0x77,0xa5,0x92,0x92,0xae,0x00,0x03,0x00,0x33,0x00,0x00,0x06,0xa2,0x05,0x9a,0x00,0x03,0x00,0x10,0x00,0x18,0x00,0x40,0x40,0x22,0x0d,0x15,0x7e,0x08,0x04,0x7d,0x11,0x08,0x11,0x08,0x11,0x00,0x0a,0x03,0x7e,0x00,0x14,0x91, 0x0d,0x0d,0x08,0x0b,0x01,0x03,0x00,0x12,0x0a,0x91,0x0b,0x03,0x15,0x91,0x08,0x12,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0x11,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x32,0x31,0x30,0x21,0x11,0x33,0x11,0x01,0x14,0x06,0x23,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x32,0x16,0x07,0x10,0x21, 0x23,0x11,0x33,0x32,0x36,0x05,0xfa,0xa8,0xfe,0xb1,0xf5,0xda,0xfe,0x53,0xfe,0x5c,0x02,0x4c,0x01,0x1e,0xcb,0xeb,0xb1,0xfe,0xc3,0xe6,0xe7,0x97,0xa5,0x05,0x9a,0xfa,0x66,0x01,0xac,0xc4,0xe8,0x05,0x02,0x98,0xfd,0xa0,0xd3,0xc5,0x01,0x00,0xfd,0xf6,0x89,0x00,0x00,0x03,0x00,0x1c,0x00,0x00,0x05,0xae,0x04,0x00,0x00,0x03,0x00,0x10, 0x00,0x18,0x00,0x40,0x40,0x22,0x0d,0x16,0x84,0x08,0x04,0x83,0x11,0x08,0x11,0x08,0x11,0x00,0x0a,0x03,0x84,0x00,0x15,0x95,0x0d,0x0d,0x08,0x0b,0x01,0x0f,0x00,0x15,0x0a,0x95,0x0b,0x0f,0x16,0x95,0x08,0x15,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0x11,0x12,0x39,0x2f,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10, 0xed,0x32,0x31,0x30,0x21,0x11,0x33,0x11,0x01,0x14,0x06,0x23,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x32,0x16,0x07,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x05,0x0c,0xa2,0xfe,0xae,0xb6,0x92,0xfe,0x3a,0xfe,0xce,0x01,0xd6,0x01,0x14,0xa0,0xb6,0xa8,0x67,0x6c,0xef,0xef,0xd3,0x04,0x00,0xfc,0x00,0x01,0x40,0x93,0xad,0x03,0x73,0x8d,0xfe, 0x77,0xa6,0x93,0x57,0x55,0xfe,0xa2,0x00,0x00,0x02,0x00,0xbb,0x00,0x00,0x06,0x5d,0x05,0x9a,0x00,0x16,0x00,0x1f,0x00,0x4b,0x40,0x27,0x07,0x0b,0x1c,0x7e,0x04,0x13,0x09,0x13,0x09,0x17,0x03,0x16,0x7e,0x00,0x0f,0x7d,0x17,0x0a,0x15,0x91,0x07,0x03,0x03,0x13,0x01,0x1b,0x91,0x0b,0x0b,0x13,0x05,0x01,0x03,0x00,0x12,0x1c,0x91,0x13, 0x12,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x11,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x33,0xed,0x32,0x32,0x31,0x30,0x33,0x11,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x21,0x11,0x01,0x34,0x26,0x23,0x23,0x11, 0x33,0x32,0x36,0xbb,0xa8,0x01,0x7e,0xa8,0x01,0x67,0xfe,0x99,0x01,0x1a,0xce,0xec,0xfb,0xd7,0xfe,0x56,0xfe,0x82,0x04,0x49,0x9c,0xa5,0xe2,0xe3,0x9c,0xa4,0x05,0x9a,0x95,0x95,0x95,0x98,0xfe,0xcd,0xd2,0xbc,0xc9,0xe3,0x04,0x6d,0xfb,0x93,0x01,0xa2,0x80,0x80,0xfd,0xf6,0x89,0x00,0x00,0x02,0x00,0xa6,0x00,0x00,0x05,0xaa,0x05,0xec, 0x00,0x16,0x00,0x1e,0x00,0x4b,0x40,0x27,0x09,0x17,0x07,0x0b,0x1c,0x84,0x04,0x13,0x13,0x17,0x03,0x16,0x84,0x00,0x0f,0x83,0x17,0x0a,0x15,0x95,0x07,0x03,0x03,0x13,0x01,0x1b,0x95,0x0b,0x0b,0x13,0x05,0x01,0x00,0x00,0x15,0x1c,0x95,0x13,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x12,0x39,0x2f,0xed,0x11,0x12,0x39,0x2f,0x33,0xed,0x32, 0x01,0x2f,0xed,0x2f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x32,0x10,0xc4,0x31,0x30,0x33,0x11,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x21,0x11,0x21,0x11,0x01,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0xa6,0xa4,0x01,0x52,0xa4,0x01,0x1e,0xfe,0xe2,0x01,0x14,0xa2,0xb4,0xb6,0x91,0xfe, 0x39,0xfe,0xae,0x03,0xb8,0x63,0x70,0xef,0xef,0xd3,0x05,0xec,0xc3,0xc3,0xc3,0x8d,0xfd,0xdb,0xa7,0x90,0x91,0xaf,0x04,0x9c,0xfb,0x64,0x01,0x3e,0x55,0x57,0xfe,0xa2,0x00,0x02,0x00,0x60,0xff,0xe8,0x07,0x6a,0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0x36,0x40,0x1d,0x07,0x7e,0x1c,0x1c,0x0c,0x16,0x7d,0x00,0x0b,0x7e,0x08,0x0c,0x0e,0x91, 0x07,0x07,0x0c,0x09,0x03,0x0c,0x12,0x1f,0x91,0x04,0x04,0x19,0x91,0x12,0x13,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x13,0x34,0x12,0x24,0x33,0x20,0x00,0x13,0x21,0x11,0x33,0x11,0x23,0x11,0x21,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x37,0x10,0x12,0x33, 0x32,0x12,0x11,0x10,0x00,0x23,0x22,0x02,0x60,0x9a,0x01,0x21,0xbf,0x01,0x1b,0x01,0x5b,0x1f,0x01,0x53,0xa8,0xa8,0xfe,0xb2,0xa5,0xfe,0xdb,0xb7,0xcd,0xfe,0xd7,0x9d,0xb0,0xfe,0xe5,0xdf,0xf2,0xfe,0xfd,0xe1,0xe0,0xf0,0x02,0xdf,0xd7,0x01,0x49,0xb3,0xfe,0xae,0xfe,0xd5,0x02,0x65,0xfa,0x66,0x02,0x9e,0xc6,0xfe,0xbb,0xab,0xb7,0x01, 0x59,0xd0,0xfe,0xe9,0xfe,0xce,0x01,0x3b,0x01,0x17,0x01,0x13,0x01,0x36,0xfe,0xcd,0x00,0x02,0x00,0x63,0xff,0xe8,0x05,0xdb,0x04,0x18,0x00,0x13,0x00,0x1b,0x00,0x38,0x40,0x1e,0x06,0x0d,0x84,0x18,0x18,0x0b,0x14,0x83,0x00,0x0a,0x84,0x07,0x0b,0x0d,0x95,0x06,0x06,0x0b,0x08,0x0f,0x0b,0x15,0x1a,0x95,0x03,0x10,0x16,0x95,0x11,0x16, 0x00,0x3f,0xed,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0x33,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x32,0x31,0x30,0x13,0x34,0x12,0x33,0x32,0x16,0x17,0x21,0x11,0x33,0x11,0x23,0x11,0x21,0x0e,0x02,0x23,0x22,0x00,0x37,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x63,0xf0,0xdc,0xca,0xff,0x1b,0x01,0x24,0xa4,0xa4,0xfe,0xde,0x05, 0x6f,0xcb,0x8f,0xe2,0xfe,0xfe,0xa7,0x01,0x2f,0x01,0x36,0xfe,0xce,0xfe,0xcd,0x02,0x04,0xff,0x01,0x15,0xe9,0xd3,0x01,0xa4,0xfc,0x00,0x01,0xd1,0x94,0xde,0x77,0x01,0x24,0xf2,0xfe,0x74,0x01,0x8c,0x01,0x90,0x00,0x02,0x00,0xbc,0x00,0x00,0x07,0x50,0x05,0x9a,0x00,0x0f,0x00,0x17,0x00,0x48,0xb9,0x00,0x14,0x01,0x04,0x40,0x22,0x05, 0x04,0x05,0x15,0x15,0x05,0x04,0x03,0x08,0x0f,0x0b,0x07,0x7e,0x08,0x02,0x91,0x14,0x06,0x91,0x0b,0x14,0x0b,0x14,0x0b,0x08,0x11,0x0d,0x03,0x09,0x03,0x04,0x00,0x08,0x12,0x00,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xed,0x32,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x31,0x30, 0x21,0x03,0x21,0x03,0x23,0x13,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x13,0x33,0x01,0x01,0x23,0x06,0x07,0x03,0x21,0x03,0x26,0x06,0x96,0x98,0xfd,0xa0,0x8f,0xbb,0xfb,0xfe,0x15,0xa8,0xa8,0x02,0x25,0xf1,0xae,0x02,0x28,0xfd,0x80,0x04,0x09,0x0e,0xdf,0x01,0xf1,0xe1,0x0b,0x01,0x92,0xfe,0x6e,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b, 0x02,0x75,0xfa,0x66,0x04,0xec,0x37,0x29,0xfd,0x9d,0x02,0x63,0x1f,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x05,0xa1,0x04,0x18,0x00,0x1c,0x00,0x27,0x00,0x5d,0x40,0x31,0x0f,0x0b,0x84,0x0c,0x16,0x1d,0x83,0x09,0x07,0x07,0x00,0x0c,0x23,0x1c,0x84,0x11,0x00,0x13,0x95,0x19,0x10,0x01,0x02,0x0a,0x95,0x0f,0x24,0x96,0x11,0x02,0x0c,0x0f, 0x16,0x11,0x0d,0x0f,0x11,0x0f,0x11,0x0c,0x0d,0x0f,0x00,0x0c,0x15,0x20,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x33,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x11,0x33,0x3f,0xed,0x01,0x2f,0x33,0xed,0x33,0x2f,0x12,0x39,0x2f,0xcd,0xfd,0xc4,0x10,0xed,0x32,0x31,0x30,0x21,0x35,0x23,0x06,0x23, 0x22,0x26,0x35,0x34,0x37,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x25,0x10,0x23,0x22,0x06,0x07,0x35,0x36,0x33,0x20,0x11,0x11,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x07,0x06,0x06,0x04,0xfd,0x04,0x67,0xd4,0x97,0xaf,0x38,0xfe,0x9a,0xa4,0xa4,0x02,0x71,0x01,0x42,0xd3,0x60,0xa0,0x4e,0x93,0xc9,0x01,0x69,0xfd,0x7f,0x6b,0x59,0x7a, 0x9f,0xef,0x88,0x66,0xa0,0xb8,0x9f,0x89,0x74,0x4d,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x2d,0x01,0x05,0x3d,0x41,0xa8,0x60,0xfe,0x82,0xfd,0x66,0x01,0x1c,0x4c,0x5e,0xab,0x83,0x66,0x21,0x14,0x56,0x00,0x00,0x03,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x11,0x00,0x2f,0x40,0x18,0x07,0x0d,0x0e,0x04,0x04,0x0e, 0x0d,0x07,0x04,0x00,0x03,0x00,0x06,0x92,0x0d,0x0d,0x00,0x09,0x01,0x03,0x07,0x92,0x00,0x12,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x31,0x30,0x33,0x01,0x33,0x01,0x27,0x03,0x21,0x03,0x01,0x23,0x06,0x06,0x07,0x03,0x21,0x03,0x26,0x26,0x16,0x02,0x26,0xae,0x02,0x28,0xf1, 0xae,0xfe,0x3a,0xa8,0x01,0x8d,0x04,0x08,0x08,0x08,0x97,0x01,0x62,0x99,0x08,0x06,0x05,0x9a,0xfa,0x66,0x91,0x01,0xd2,0xfe,0x2e,0x04,0x5b,0x23,0x2b,0x14,0xfe,0x62,0x01,0xa0,0x17,0x2c,0x00,0x03,0x00,0x0a,0x00,0x00,0x03,0xc7,0x04,0x00,0x00,0x03,0x00,0x07,0x00,0x0f,0x00,0x2f,0x40,0x18,0x04,0x0b,0x0c,0x05,0x05,0x0c,0x0b,0x04, 0x04,0x00,0x01,0x00,0x07,0x96,0x0b,0x0b,0x01,0x08,0x02,0x0f,0x04,0x96,0x01,0x15,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x31,0x30,0x21,0x21,0x01,0x33,0x01,0x21,0x03,0x21,0x13,0x06,0x07,0x07,0x33,0x27,0x26,0x27,0x03,0xc7,0xfc,0x43,0x01,0x98,0xa1,0xfe,0xa0,0x02,0x05, 0x71,0xfe,0xe3,0x8c,0x05,0x1a,0x43,0xcb,0x40,0x14,0x10,0x04,0x00,0xfc,0x7b,0x01,0x44,0x01,0xb8,0x44,0x47,0xb9,0xb5,0x34,0x5b,0x00,0x00,0x04,0x00,0x29,0x00,0x00,0x05,0xaa,0x05,0x9a,0x00,0x14,0x00,0x1b,0x00,0x1f,0x00,0x24,0x00,0x69,0x40,0x38,0x16,0x14,0x1c,0x0b,0x7e,0x0c,0x24,0x0c,0x15,0x02,0x7e,0x19,0x00,0x23,0x14,0x0c, 0x19,0x1d,0x01,0x01,0x1d,0x19,0x0c,0x14,0x23,0x00,0x07,0x06,0x11,0x06,0x0a,0x0e,0x92,0x23,0x1c,0x23,0x1f,0x20,0x92,0x14,0x19,0x02,0x14,0x23,0x14,0x23,0x14,0x00,0x0c,0x07,0x11,0x12,0x16,0x91,0x00,0x03,0x00,0x3f,0xed,0x3f,0x33,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f, 0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xfd,0xcd,0x11,0x33,0x10,0xed,0x32,0x10,0xcd,0x31,0x30,0x13,0x21,0x01,0x16,0x16,0x12,0x17,0x23,0x26,0x27,0x21,0x11,0x23,0x11,0x21,0x06,0x07,0x23,0x12,0x00,0x37,0x01,0x21,0x13,0x16,0x17,0x36,0x36,0x13,0x21,0x26,0x27,0x27,0x06,0x06,0x07,0x21,0xa5,0x04,0x9f,0xfe, 0x52,0x9e,0xcb,0x7e,0x2d,0xbf,0x10,0x31,0xfe,0x98,0xa8,0xfe,0x8c,0x2c,0x10,0xc1,0x2f,0x01,0x01,0xe9,0x01,0xe5,0xfd,0x9f,0xf8,0x23,0x11,0x11,0x0e,0x31,0x01,0x25,0x6e,0xb7,0xa8,0x68,0x8b,0x3e,0x01,0x31,0x05,0x9a,0xfd,0x60,0x36,0xb2,0xfe,0xea,0xfc,0xb1,0x6b,0xfe,0xe4,0x01,0x1c,0x6d,0xaf,0x01,0x4a,0x01,0x6c,0x46,0x02,0x06, 0xfe,0x6a,0x37,0x39,0x33,0x1a,0xfe,0x58,0x9c,0x33,0x02,0x1f,0x5b,0x57,0x00,0x04,0x00,0x1e,0x00,0x00,0x04,0x66,0x04,0x00,0x00,0x15,0x00,0x1c,0x00,0x21,0x00,0x26,0x00,0x6d,0x40,0x0c,0x20,0x17,0x0e,0x22,0x04,0xef,0x05,0x21,0x05,0x23,0x16,0x11,0xb8,0x01,0x2e,0x40,0x2a,0x1a,0x0f,0x0e,0x05,0x1a,0x10,0x10,0x1a,0x05,0x0e,0x0f, 0x05,0x0a,0x15,0x0a,0x03,0x07,0x96,0x20,0x22,0x20,0x26,0x1d,0x96,0x0e,0x11,0x1a,0x0e,0x0f,0x20,0x0e,0x20,0x0e,0x0a,0x17,0x95,0x0f,0x0f,0x05,0x00,0x0a,0x15,0x00,0x3f,0x33,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x32,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f, 0x2f,0x10,0xfd,0xcd,0xcd,0x11,0x33,0x10,0xed,0x32,0x10,0xcd,0xcd,0x31,0x30,0x21,0x26,0x27,0x23,0x15,0x23,0x35,0x21,0x06,0x07,0x23,0x3e,0x02,0x37,0x01,0x21,0x01,0x1e,0x02,0x17,0x01,0x21,0x17,0x16,0x17,0x36,0x36,0x07,0x06,0x06,0x07,0x3b,0x02,0x26,0x26,0x27,0x03,0xb8,0x0a,0x21,0xf9,0x9c,0xff,0x00,0x1a,0x11,0xaf,0x24,0x60, 0x98,0x74,0xfe,0xc2,0x03,0xb5,0xfe,0xb8,0x73,0x9b,0x5e,0x1d,0xfe,0xb0,0xfe,0x6f,0x9f,0x1c,0x08,0x03,0x0a,0x5d,0x3a,0x5a,0x2d,0xc1,0x9c,0xb9,0x35,0x4c,0x38,0x74,0x4e,0xc2,0xc2,0x40,0x82,0xbe,0xc9,0x81,0x23,0x01,0xd5,0xfe,0x29,0x24,0x8a,0xcd,0xae,0x03,0x79,0xff,0x2b,0x17,0x08,0x11,0x9d,0x12,0x37,0x35,0x3a,0x30,0x12,0x00, 0x00,0x03,0x00,0xbc,0x00,0x00,0x07,0x50,0x05,0x9a,0x00,0x0b,0x00,0x0f,0x00,0x17,0x00,0x49,0x40,0x27,0x08,0x04,0x7e,0x05,0x14,0x0e,0x7e,0x0f,0x02,0x01,0x02,0x15,0x0c,0x0c,0x15,0x02,0x01,0x04,0x00,0x05,0x00,0x0e,0x03,0x91,0x14,0x08,0x08,0x01,0x11,0x0a,0x03,0x06,0x03,0x05,0x12,0x0f,0x92,0x01,0x12,0x00,0x3f,0xed,0x3f,0x3f, 0x3f,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x10,0xc5,0xfd,0xcd,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x13,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x13,0x33,0x01,0x03,0x21,0x03,0x01,0x23,0x06,0x07,0x03,0x21,0x03,0x26,0x07,0x50,0xfb,0x04,0xfb,0xfe,0x15,0xa8,0xa8,0x02,0x25,0xf1,0xae, 0x01,0x37,0xbe,0xfe,0x5a,0xb8,0x01,0x8d,0x04,0x09,0x0e,0x83,0x01,0x38,0x84,0x09,0x02,0x8e,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfa,0xf7,0x01,0xfd,0xfe,0x03,0x04,0x5b,0x37,0x29,0xfe,0x99,0x01,0x67,0x1b,0x00,0x00,0x03,0x00,0xa6,0x00,0x00,0x05,0xd0,0x04,0x00,0x00,0x0b,0x00,0x0f,0x00,0x17,0x00,0x4d,0x40,0x2a,0x08,0x04, 0x84,0x05,0x01,0x02,0x0c,0x13,0x14,0x0d,0x0d,0x14,0x13,0x0c,0x02,0x01,0x06,0x00,0x05,0x00,0x0f,0x96,0x13,0x03,0x95,0x08,0x13,0x08,0x13,0x08,0x01,0x10,0x0a,0x0f,0x06,0x0f,0x05,0x15,0x0c,0x96,0x01,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f, 0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x32,0x31,0x30,0x21,0x21,0x13,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x13,0x33,0x01,0x21,0x03,0x21,0x13,0x06,0x07,0x07,0x33,0x26,0x26,0x27,0x05,0xd0,0xfc,0x43,0xba,0xfe,0x7d,0xa4,0xa4,0x01,0xba,0xa7,0xa1,0xfe,0xa0,0x02,0x05,0x71,0xfe,0xe3,0x8c,0x06,0x18,0x44,0xcb,0x2c,0x2c,0x0c,0x01,0xd1,0xfe, 0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4,0xfc,0x7b,0x01,0x44,0x01,0xb8,0x47,0x44,0xb9,0x7b,0x7c,0x4d,0x00,0x00,0x01,0x00,0x1e,0xfe,0x29,0x05,0xfe,0x05,0x9a,0x00,0x1a,0x00,0x2f,0x40,0x17,0x1a,0x7e,0x02,0x00,0x00,0x0b,0x14,0x0b,0x19,0x18,0x01,0x02,0x02,0x12,0x15,0x12,0x12,0x03,0x0e,0x91,0x00,0x08,0x13,0x00,0x3f,0xc6,0xed,0x3f, 0x3f,0x12,0x39,0x11,0x33,0x33,0x33,0x01,0x2f,0x2f,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x01,0x11,0x23,0x06,0x07,0x03,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x01,0x33,0x01,0x23,0x01,0x26,0x27,0x23,0x11,0x03,0x4d,0x05,0x0e,0x1a,0xe0,0x2c,0x8c,0x6d,0x6b,0x85,0x0d,0xa1,0x0d,0x51,0x2c,0x3c,0x1f,0x01,0xb4, 0x9a,0x02,0x0c,0xc0,0xfe,0xe4,0x1d,0x0a,0x05,0xfe,0x29,0x05,0xc9,0x60,0x47,0xfd,0xa3,0x89,0x7e,0x7b,0x80,0x64,0x4b,0x51,0x04,0x80,0xfa,0x66,0x03,0x44,0x5c,0x52,0xfa,0x37,0x00,0x01,0x00,0x05,0xfe,0x29,0x04,0xd0,0x04,0x00,0x00,0x1a,0x00,0x30,0x40,0x18,0x1a,0xef,0x02,0x00,0x00,0x0a,0x14,0x0a,0x19,0x18,0x01,0x02,0x02,0x12, 0x15,0x15,0x12,0x0f,0x0e,0x95,0x08,0x16,0x00,0x1b,0x00,0x3f,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x11,0x33,0x33,0x33,0x01,0x2f,0x2f,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x01,0x11,0x23,0x06,0x07,0x03,0x06,0x06,0x23,0x22,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x37,0x01,0x33,0x01,0x23,0x03,0x26,0x27,0x23,0x11,0x02,0xa3,0x05,0x0f,0x12, 0x81,0x2f,0x78,0x5c,0xd5,0x1f,0x9d,0x05,0x29,0x29,0x27,0x39,0x22,0x01,0x2a,0x9d,0x01,0x8e,0xaa,0xbd,0x1a,0x0b,0x05,0xfe,0x29,0x04,0x86,0x54,0x36,0xfe,0xaf,0x85,0x68,0xeb,0x30,0x2d,0x43,0x56,0x02,0xf2,0xfc,0x00,0x02,0x16,0x58,0x41,0xfb,0x7a,0x00,0x01,0x00,0x3e,0xfe,0x7f,0x05,0x34,0x05,0x9a,0x00,0x0b,0x00,0x2a,0x40,0x15, 0x05,0x7e,0x02,0x02,0x06,0x0b,0x7f,0x00,0x09,0x7e,0x06,0x00,0x0a,0x07,0x03,0x03,0x05,0x01,0x91,0x0a,0x12,0x00,0x3f,0xed,0x32,0x3f,0x33,0x10,0xcd,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x31,0x30,0x13,0x11,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x3e,0xc0,0xa8,0x02,0xe6,0xa8,0xfb,0xa5,0xfe,0x7f,0x02,0x19, 0x05,0x02,0xfa,0xfe,0x05,0x02,0xfa,0x66,0xfe,0x7f,0x00,0x01,0x00,0x3e,0xfe,0x8b,0x04,0x27,0x04,0x00,0x00,0x0b,0x00,0x2a,0x40,0x15,0x05,0x84,0x02,0x02,0x06,0x0b,0xed,0x00,0x09,0x84,0x06,0x00,0x0a,0x07,0x03,0x0f,0x05,0x01,0x95,0x0a,0x15,0x00,0x3f,0xed,0x32,0x3f,0x33,0x10,0xcd,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed, 0x31,0x30,0x13,0x11,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x3e,0x97,0xa4,0x02,0x0a,0xa4,0xfc,0xa4,0xfe,0x8b,0x02,0x00,0x03,0x75,0xfc,0x8b,0x03,0x75,0xfc,0x00,0xfe,0x8b,0x00,0x02,0x00,0x0f,0xfe,0x7f,0x06,0xc6,0x05,0x9a,0x00,0x0f,0x00,0x15,0x00,0x3d,0x40,0x1f,0x14,0x07,0x01,0x7e,0x15,0x03,0x7f,0x04,0x15,0x04, 0x15,0x04,0x0e,0x07,0x7f,0x08,0x0e,0x04,0x08,0x06,0x00,0x11,0xee,0x0d,0x03,0x01,0x14,0x09,0x91,0x06,0x12,0x00,0x3f,0xed,0x32,0x32,0x3f,0xed,0x32,0x10,0xcd,0x32,0x01,0x2f,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xc4,0x31,0x30,0x01,0x11,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x12,0x12,0x13,0x21, 0x15,0x21,0x21,0x06,0x02,0x07,0x21,0x04,0x87,0xc1,0x9b,0xfb,0xfd,0x9b,0x6f,0x92,0xc8,0x0c,0x04,0xe2,0xfd,0x19,0xfe,0x94,0x0e,0xb9,0x78,0x02,0xab,0x04,0xfe,0xfb,0x9a,0xfd,0xe7,0x01,0x81,0xfe,0x7f,0x02,0x19,0x01,0x0d,0x02,0xba,0x01,0x3b,0x9c,0xe5,0xfd,0x66,0xe7,0x00,0x02,0x00,0x12,0xfe,0x8b,0x05,0x20,0x04,0x00,0x00,0x0f, 0x00,0x15,0x00,0x3d,0x40,0x1f,0x14,0x07,0x01,0x84,0x15,0x03,0xed,0x04,0x15,0x04,0x15,0x04,0x0e,0x07,0xed,0x08,0x0e,0x04,0x08,0x06,0x00,0x11,0x95,0x0d,0x0f,0x01,0x14,0x09,0x95,0x06,0x15,0x00,0x3f,0xed,0x32,0x32,0x3f,0xed,0x32,0x10,0xcd,0x32,0x01,0x2f,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xc4,0x31, 0x30,0x01,0x11,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x36,0x12,0x35,0x21,0x15,0x21,0x23,0x06,0x02,0x07,0x21,0x03,0x8b,0x98,0x8b,0xfd,0x06,0x8c,0x5b,0x7d,0x8d,0x03,0xa9,0xfd,0xc7,0xe3,0x0a,0x79,0x66,0x01,0xcc,0x03,0x74,0xfd,0x17,0xfe,0x00,0x01,0x75,0xfe,0x8b,0x02,0x00,0xb0,0x01,0xc9,0xfc,0x8c,0xc5,0xfe,0x7d,0xa1, 0x00,0x01,0x00,0x10,0xff,0xe9,0x06,0xe3,0x05,0x9a,0x00,0x17,0x00,0x24,0x40,0x12,0x17,0x7e,0x00,0x00,0x0a,0x14,0x0a,0x16,0x02,0xee,0x13,0x03,0x0e,0x91,0x08,0x13,0x00,0x12,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x11,0x21,0x07,0x06,0x02,0x02,0x06,0x23,0x22,0x27,0x35,0x16,0x16, 0x33,0x32,0x36,0x12,0x12,0x13,0x21,0x15,0x21,0x11,0x03,0xfc,0xfe,0x71,0x20,0x1e,0x46,0x57,0x8e,0x6b,0x4d,0x3c,0x12,0x47,0x18,0x44,0x4f,0x4b,0x55,0x2e,0x05,0x01,0xfd,0xc1,0x04,0xfe,0xf9,0xe7,0xfe,0x48,0xfe,0xfa,0x77,0x15,0x9e,0x0b,0x12,0x6e,0x01,0x26,0x02,0x1c,0x01,0x6b,0x9c,0xfb,0x02,0x00,0x00,0x01,0x00,0x10,0xff,0xf2, 0x05,0x26,0x04,0x00,0x00,0x11,0x00,0x24,0x40,0x12,0x11,0x84,0x00,0x00,0x07,0x0e,0x07,0x10,0x02,0x95,0x0d,0x0f,0x0a,0x95,0x05,0x16,0x00,0x15,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x11,0x23,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x12,0x13,0x21,0x15,0x21,0x11,0x02,0xee, 0xee,0x28,0xc1,0xaf,0x38,0x20,0x1f,0x2d,0x6d,0x8b,0x23,0x03,0xaf,0xfe,0x6b,0x03,0x74,0xfe,0x21,0xfe,0x5d,0x0e,0x8d,0x12,0x01,0xbf,0x01,0xc6,0x8c,0xfc,0x8c,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x08,0xb1,0x05,0x9a,0x00,0x1f,0x00,0x3f,0x40,0x1f,0x07,0x06,0x03,0x01,0x7e,0x02,0x02,0x14,0x1e,0x10,0x13,0x7e,0x14,0x00,0xee,0x1d, 0x1d,0x15,0x0f,0x07,0x06,0x10,0x19,0x10,0x14,0x15,0x03,0x0c,0x02,0x14,0x12,0x00,0x3f,0x33,0x33,0x3f,0x12,0x39,0x39,0x11,0x33,0x33,0x33,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0x32,0x2f,0x12,0x39,0x2f,0xed,0x33,0x33,0x33,0x31,0x30,0x01,0x11,0x23,0x11,0x34,0x36,0x37,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x23,0x16,0x15, 0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x36,0x36,0x01,0x21,0x15,0x06,0x72,0xa7,0x02,0x0c,0x04,0x0d,0x10,0x0e,0xfe,0x16,0x52,0xfe,0x17,0x13,0x17,0x05,0x08,0xa2,0xde,0x01,0xb8,0x31,0x11,0x06,0x29,0x1a,0x01,0xc4,0x03,0x10,0x04,0xfe,0xfb,0x02,0x03,0xc2,0x20,0x39,0xbe,0x2e,0x3f,0x1e,0xfb,0xb2,0x04,0x46,0x2d,0x66,0x6a,0xaf, 0xfc,0x40,0x05,0x9a,0xfc,0x18,0x70,0x3c,0x70,0x3c,0x03,0xe8,0x9c,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x06,0x8d,0x04,0x00,0x00,0x17,0x00,0x34,0x40,0x1a,0x17,0x84,0x00,0x00,0x0a,0x14,0x09,0xed,0x0a,0x16,0x95,0x13,0x13,0x0b,0x01,0x08,0x0f,0x08,0x0a,0x0b,0x0f,0x00,0x0a,0x15,0x05,0x15,0x00,0x3f,0x3f,0x33,0x3f,0x12,0x39,0x39, 0x11,0x33,0x11,0x33,0x10,0xed,0x01,0x2f,0xed,0x2f,0x12,0x39,0x2f,0xed,0x31,0x30,0x21,0x11,0x06,0x06,0x01,0x23,0x01,0x26,0x27,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x36,0x37,0x01,0x21,0x15,0x21,0x11,0x04,0x56,0x10,0x26,0xfe,0xf2,0x93,0xfe,0xf8,0x2d,0x17,0x8d,0xd1,0x01,0x0e,0x3e,0x0a,0x04,0x0f,0x26,0x01,0x18,0x02,0x6f, 0xfe,0x6b,0x03,0x4c,0x2f,0x6a,0xfd,0x4d,0x02,0x90,0x74,0x48,0xfc,0xb4,0x04,0x00,0xfd,0x64,0x9a,0x2f,0x39,0x5d,0x02,0xcf,0x8c,0xfc,0x8c,0x00,0x00,0x03,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x28,0x40,0x14,0x15,0x7d,0x09,0x21,0x1b,0x7d,0x03,0x0f,0x00,0x06,0x06,0x0c,0x18,0x91,0x12,0x04, 0x1e,0x91,0x0c,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0x01,0x2f,0xc4,0xed,0x2f,0xc6,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x03,0x02,0x30,0x41,0x42,0x31, 0x30,0x42,0x41,0x37,0xfe,0xd0,0xfe,0x90,0x01,0x75,0x01,0x43,0x01,0x23,0x01,0x71,0xfe,0x89,0xfe,0xd7,0xe1,0xfe,0xe5,0x01,0x0f,0xe1,0xef,0x01,0x0d,0xfe,0xf5,0x02,0x70,0x3c,0x30,0x2b,0x3e,0x39,0x30,0x2e,0x3e,0xfd,0x78,0x01,0x90,0x01,0x44,0x01,0x5a,0x01,0x9c,0xfe,0x75,0xfe,0xb8,0xfe,0x9d,0xfe,0x6c,0x05,0x32,0xfe,0xbb,0xfe, 0xf6,0xfe,0xfb,0xfe,0xb9,0x01,0x36,0x01,0x13,0x01,0x20,0x01,0x32,0x00,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x18,0x00,0x24,0x00,0x28,0x40,0x14,0x15,0x83,0x09,0x22,0x1c,0x83,0x03,0x0f,0x00,0x06,0x06,0x0c,0x19,0x95,0x12,0x10,0x1f,0x95,0x0c,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0x01, 0x2f,0xc4,0xed,0x2f,0xc6,0xed,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x12,0x17,0x14,0x06,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x58,0x29,0x38,0x3a,0x27,0x2a,0x37,0x35,0x32,0xe7,0xfe,0xf5,0x01,0x1c,0xee,0xe6,0xfe,0x02, 0x83,0xe1,0x8e,0x9e,0xb8,0xb6,0xa0,0xa0,0xaa,0xac,0x01,0xaa,0x38,0x2a,0x2d,0x32,0x37,0x28,0x27,0x3b,0xfe,0x3e,0x01,0x23,0xe9,0x01,0x04,0x01,0x20,0xfe,0xe6,0xfa,0xaa,0xf1,0x81,0x03,0xa6,0xd7,0xbd,0xb2,0xd6,0xd0,0xbc,0xc2,0xce,0x00,0x00,0x04,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f, 0x00,0x32,0x40,0x19,0x2d,0x27,0x15,0x7d,0x21,0x1b,0x7d,0x09,0x03,0x0f,0x24,0x00,0x00,0x2a,0x06,0x06,0x0c,0x18,0x91,0x12,0x04,0x1e,0x91,0x0c,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0x33,0x11,0x33,0x01,0x2f,0xc4,0xc4,0xed,0x2f,0xed,0xc4,0xc6,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x13,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x01,0x22,0x00,0x11,0x10,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x34,0x2c,0x3d,0x3e,0x2d,0x30,0x3a,0x3c,0x9a,0xfe,0xd0,0xfe,0x90,0x01,0x75,0x01,0x43,0x01,0x23,0x01,0x71,0xfe,0x89,0xfe,0xd7,0xe1,0xfe, 0xe5,0x01,0x0f,0xe1,0xef,0x01,0x0d,0xfe,0xf5,0x1e,0x2c,0x3d,0x3e,0x2d,0x30,0x3a,0x3c,0x02,0x70,0x3c,0x30,0x2e,0x3b,0x3e,0x2b,0x2d,0x3f,0xfd,0x78,0x01,0x90,0x01,0x44,0x01,0x5a,0x01,0x9c,0xfe,0x75,0xfe,0xb8,0xfe,0x9d,0xfe,0x6c,0x05,0x32,0xfe,0xbb,0xfe,0xf6,0xfe,0xfb,0xfe,0xb9,0x01,0x36,0x01,0x13,0x01,0x20,0x01,0x32,0xfd, 0x56,0x3c,0x30,0x2e,0x3b,0x3e,0x2b,0x2d,0x3f,0x00,0x00,0x04,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x0b,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x32,0x40,0x19,0x2e,0x28,0x15,0x83,0x09,0x22,0x1c,0x83,0x03,0x0f,0x25,0x00,0x00,0x2b,0x06,0x06,0x0c,0x19,0x95,0x12,0x10,0x1f,0x95,0x0c,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39, 0x2f,0x33,0x33,0x11,0x33,0x01,0x2f,0xc4,0xed,0x2f,0xc4,0xed,0xc4,0xc6,0x31,0x30,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x22,0x00,0x35,0x10,0x00,0x33,0x32,0x12,0x17,0x14,0x06,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14, 0x06,0x01,0xc9,0x28,0x34,0x37,0x25,0x25,0x38,0x37,0x63,0xe7,0xfe,0xf5,0x01,0x1c,0xee,0xe6,0xfe,0x02,0x83,0xe1,0x8e,0x9e,0xb8,0xb6,0xa0,0xa0,0xaa,0xac,0x16,0x28,0x34,0x37,0x25,0x25,0x38,0x37,0x01,0xaf,0x37,0x26,0x2b,0x30,0x31,0x2a,0x28,0x35,0xfe,0x39,0x01,0x23,0xe9,0x01,0x04,0x01,0x20,0xfe,0xe6,0xfa,0xaa,0xf1,0x81,0x03, 0xa6,0xd7,0xbd,0xb2,0xd6,0xd0,0xbc,0xc2,0xce,0xfe,0x21,0x37,0x26,0x2b,0x30,0x31,0x2a,0x28,0x35,0x00,0x00,0x05,0x00,0x5e,0xff,0xe8,0x09,0x58,0x05,0xb2,0x00,0x1d,0x00,0x2b,0x00,0x37,0x00,0x43,0x00,0x4f,0x00,0x3f,0x40,0x20,0x21,0x7d,0x35,0x35,0x0c,0x4d,0x47,0x1a,0x7d,0x28,0x41,0x3b,0x2f,0x7d,0x0c,0x44,0x38,0x38,0x4a,0x3e, 0x3e,0x09,0x1e,0x2c,0x91,0x0f,0x04,0x25,0x32,0x91,0x09,0x13,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0x11,0x33,0x01,0x2f,0xed,0xc4,0xc4,0x2f,0xed,0xc4,0xc6,0x12,0x39,0x2f,0xed,0x31,0x30,0x05,0x22,0x26,0x26,0x27,0x23,0x06,0x07,0x06,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x04,0x17,0x33,0x3e,0x02,0x33, 0x20,0x00,0x11,0x10,0x07,0x06,0x01,0x22,0x02,0x11,0x14,0x12,0x16,0x33,0x32,0x12,0x11,0x34,0x02,0x26,0x21,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x35,0x10,0x02,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0xe8,0x7b,0xc7,0x98,0x2f,0x08,0x27, 0x36,0x9e,0xfe,0xe7,0xfe,0xea,0xfe,0xb1,0x01,0x55,0x01,0x26,0xb8,0x01,0x0a,0x3e,0x08,0x24,0x9d,0xd9,0x83,0x01,0x0e,0x01,0x4c,0xaa,0xa8,0xfe,0xed,0xca,0xf6,0x69,0xc2,0x8a,0xcd,0xf3,0x67,0xc5,0xfb,0x52,0xc8,0xf8,0xf4,0xc1,0xdb,0xe5,0xef,0xcd,0x2d,0x3c,0x40,0x2a,0x2b,0x40,0x3d,0x03,0xf6,0x2b,0x3e,0x3f,0x2b,0x2b,0x40,0x3c, 0x18,0x4e,0x9d,0x7b,0x68,0x3d,0xc1,0x01,0x91,0x01,0x44,0x01,0x59,0x01,0x9c,0xbb,0xa6,0x66,0xa8,0x53,0xfe,0x70,0xfe,0xbd,0xfe,0x9f,0xca,0xcc,0x05,0x32,0xfe,0xb7,0xfe,0xfc,0xac,0xfe,0xf5,0x97,0x01,0x2e,0x01,0x1b,0xbb,0x01,0x0a,0x8d,0xfe,0xba,0xfe,0xf7,0xfe,0xf3,0xfe,0xc1,0x01,0x41,0xfe,0x01,0x2f,0x01,0x2d,0xfd,0x56,0x3f, 0x2d,0x30,0x39,0x39,0x30,0x2e,0x3e,0x3b,0x31,0x30,0x39,0x39,0x30,0x2e,0x3e,0x00,0x00,0x05,0x00,0x60,0xff,0xe8,0x06,0xdc,0x04,0x18,0x00,0x1b,0x00,0x28,0x00,0x34,0x00,0x40,0x00,0x4c,0x00,0x4b,0x40,0x28,0x3e,0x83,0x38,0x20,0x83,0x32,0x4a,0x83,0x44,0x38,0x32,0x44,0x44,0x32,0x38,0x03,0x0c,0x19,0x83,0x26,0x2c,0x83,0x0c,0x41, 0x35,0x35,0x47,0x3b,0x3b,0x08,0x1c,0x29,0x95,0x0f,0x10,0x23,0x2f,0x95,0x08,0x16,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0x33,0x11,0x33,0x01,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x22,0x26,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x10,0x00, 0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x12,0x17,0x14,0x02,0x03,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x0e, 0x57,0x89,0x6d,0x25,0x04,0x2a,0xbe,0x8c,0x86,0xc6,0x78,0x01,0x08,0xd1,0x84,0xbd,0x29,0x04,0x32,0xc4,0x86,0xca,0xee,0x01,0xfb,0xc9,0x5f,0x86,0x41,0x99,0x8d,0x88,0x94,0x94,0xfc,0x8e,0x85,0xa1,0x9d,0x89,0x84,0x98,0x95,0x8c,0x24,0x34,0x32,0x26,0x23,0x35,0x32,0x02,0xc4,0x25,0x33,0x32,0x26,0x23,0x35,0x32,0x18,0x32,0x66,0x57, 0x71,0x7e,0x7a,0xea,0xa8,0x01,0x0b,0x01,0x19,0x7e,0x70,0x75,0x79,0xfe,0xe2,0xf6,0xf5,0xfe,0xd9,0x03,0xa6,0x6b,0xad,0x78,0xb2,0xda,0xce,0xbe,0xc2,0xce,0xd3,0xc1,0xb5,0xd3,0xc8,0xc9,0xbb,0xd0,0xfe,0x1c,0x38,0x2a,0x2a,0x35,0x33,0x2c,0x29,0x39,0x39,0x29,0x2a,0x35,0x33,0x2c,0x29,0x39,0x00,0x0f,0x00,0x7e,0xff,0xe7,0x05,0xd7, 0x05,0xb3,0x00,0x2a,0x00,0x36,0x00,0x42,0x00,0x4e,0x00,0x5a,0x00,0x66,0x00,0x72,0x00,0x7e,0x00,0x8a,0x00,0x96,0x00,0xa2,0x00,0xae,0x00,0xba,0x00,0xc6,0x00,0xd2,0x01,0x3c,0xb1,0xbe,0x82,0xb8,0x01,0x04,0x40,0x0f,0x0f,0x09,0x07,0x11,0x07,0x58,0x7f,0x52,0x34,0x64,0x7f,0x5e,0x2e,0x5e,0xa6,0xb8,0x01,0x04,0xb4,0xa0,0x16,0x02, 0xca,0x8e,0xb8,0x01,0x04,0x40,0x0d,0x88,0xc4,0x88,0x4c,0x7f,0x46,0x40,0x7c,0x7f,0x76,0x3a,0x76,0xb2,0xb8,0x01,0x04,0xb4,0xac,0x1d,0x26,0x1b,0x28,0xb8,0x01,0x04,0x40,0x1d,0x94,0xd0,0x94,0x70,0x7f,0x6a,0x07,0x52,0x5e,0xa0,0x88,0x46,0x76,0xac,0x94,0x6a,0x6a,0x94,0xac,0x76,0x46,0x88,0xa0,0x5e,0x52,0x07,0x0a,0x0c,0x21,0xbb, 0x01,0x04,0x00,0xb8,0x00,0x9a,0x01,0x04,0xb2,0x0c,0xc7,0xbb,0xb8,0x01,0x05,0x40,0x0c,0x14,0x73,0x5b,0xee,0x61,0x79,0x61,0x8b,0x7f,0x26,0x25,0x09,0xb8,0x01,0x05,0x40,0x0f,0x9d,0xb5,0x9d,0x67,0x43,0x4f,0xee,0x55,0x6d,0x49,0x55,0xcd,0xc1,0xaf,0x97,0xb8,0x01,0x05,0x40,0x2a,0x0f,0x1e,0x1d,0x0f,0x37,0x2b,0xee,0x31,0x3d,0x31, 0x80,0x55,0x01,0x02,0x61,0x7f,0x9d,0xa9,0x55,0xa3,0xc1,0x0f,0x31,0x16,0x16,0x31,0x0f,0xc1,0xa3,0x55,0xa9,0x9d,0x7f,0x61,0x02,0x0b,0x04,0x18,0x14,0x04,0x91,0x85,0xb8,0x01,0x05,0xb2,0x00,0x04,0x13,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x5d,0x11,0x33,0x10, 0xed,0x32,0x11,0x33,0x33,0x10,0xed,0x32,0x11,0x33,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x10,0xed,0x32,0x32,0x11,0x33,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x32,0x01,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xed,0x11,0x33,0x10,0xfd,0x32,0xcd,0x32,0x10,0xed,0x11,0x33, 0x10,0xed,0x32,0x10,0xed,0x11,0x33,0x10,0xfd,0x32,0xcd,0x32,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0x11,0x33,0x10,0xcd,0x32,0xed,0x32,0x31,0x30,0x05,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x37,0x32,0x16,0x15, 0x14,0x06,0x07,0x23,0x27,0x16,0x15,0x14,0x06,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03,0xe2,0x8f,0x45,0x45,0x8b,0x78,0x94,0x27,0x65,0x76,0x74,0x66,0x26,0x91, 0x7e,0x8a,0x43,0x47,0x8f,0x7a,0x88,0x23,0x1c,0x6f,0x89,0x80,0x6e,0x13,0x14,0x24,0x89,0xfd,0xdc,0x1d,0x2c,0x2b,0x1e,0x1f,0x2d,0x2b,0x01,0x83,0x1d,0x2c,0x2c,0x1d,0x1e,0x2e,0x2b,0xd5,0x1d,0x2c,0x2c,0x1d,0x1d,0x2f,0x2c,0xfe,0x3c,0x1d,0x2d,0x2d,0x1d,0x1e,0x2e,0x2c,0x94,0x1d,0x2c,0x2d,0x1c,0x1e,0x2e,0x2b,0x02,0x73,0x1d,0x2c, 0x2c,0x1d,0x20,0x2b,0x2b,0xfe,0xf0,0x1d,0x2c,0x2b,0x1e,0x1e,0x2e,0x2b,0xfe,0x3b,0x46,0x54,0x56,0x48,0x4b,0x4f,0x4f,0x01,0x55,0x47,0x54,0x57,0x48,0x49,0x51,0x50,0xfd,0x5a,0x47,0x54,0x56,0x49,0x48,0x51,0x50,0x01,0x57,0x47,0x54,0x55,0x4a,0x48,0x51,0x51,0x01,0x58,0x46,0x55,0x56,0x48,0x49,0x51,0x4e,0xfd,0x1d,0x46,0x54,0x56, 0x48,0x49,0x51,0x50,0x01,0x56,0x47,0x54,0x56,0x49,0x49,0x51,0x50,0x19,0x65,0x65,0x9e,0x84,0x60,0x44,0x0f,0x99,0x76,0x77,0x9b,0x11,0x41,0x5d,0x86,0xa1,0x66,0x66,0x9e,0x8a,0x5c,0x41,0x02,0x9f,0x87,0x80,0x98,0x07,0x01,0x44,0x60,0x83,0x9e,0x04,0x5f,0x2a,0x25,0x22,0x2b,0x28,0x25,0x22,0x2d,0x2b,0x24,0x24,0x29,0x28,0x25,0x22, 0x2d,0xfe,0x3e,0x2a,0x26,0x24,0x29,0x27,0x26,0x22,0x2e,0x2b,0x25,0x22,0x2b,0x28,0x25,0x23,0x2d,0xfe,0x3f,0x2b,0x24,0x25,0x28,0x28,0x25,0x22,0x2d,0x01,0xc1,0x2c,0x24,0x23,0x2a,0x2a,0x23,0x23,0x2d,0xfe,0x3f,0x2b,0x24,0x22,0x2b,0x27,0x26,0x22,0x2d,0x01,0x09,0x69,0x59,0x5a,0x65,0x66,0x5a,0x5a,0x67,0x6a,0x59,0x59,0x65,0x64, 0x5c,0x5c,0x65,0x01,0xc2,0x6a,0x58,0x58,0x67,0x64,0x5b,0x5d,0x65,0x69,0x59,0x5a,0x65,0x63,0x5c,0x5f,0x63,0x6a,0x58,0x5a,0x65,0x64,0x5c,0x59,0x68,0x01,0xc2,0x69,0x5a,0x5a,0x65,0x64,0x5c,0x5b,0x67,0x6a,0x59,0x5a,0x65,0x64,0x5c,0x5c,0x66,0x00,0x00,0x01,0xfe,0xc2,0x04,0xd3,0x01,0x3e,0x05,0x87,0x00,0x0f,0x00,0x1a,0x40,0x0a, 0x0b,0x0c,0x03,0x04,0x00,0x40,0x07,0x80,0x0c,0x04,0x00,0x2f,0x33,0x1a,0xdd,0x1a,0xc9,0x01,0x2f,0xc9,0x2f,0xc9,0x31,0x30,0x03,0x22,0x15,0x15,0x23,0x35,0x34,0x33,0x21,0x32,0x15,0x15,0x23,0x35,0x34,0x23,0x70,0x42,0x8c,0x7a,0x01,0x88,0x7a,0x8b,0x42,0x05,0x20,0x31,0x1c,0x2e,0x86,0x88,0x2c,0x1c,0x31,0x00,0x00,0x08,0x00,0x6f, 0xfe,0xb6,0x07,0x72,0x05,0xf8,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x3b,0x00,0x47,0x00,0x53,0x00,0x5f,0x00,0x39,0x40,0x1b,0x35,0x59,0x5b,0x37,0x5b,0x29,0x4d,0x4f,0x2b,0x4f,0x1d,0x41,0x43,0x1f,0x43,0x5b,0x4f,0x43,0x43,0x4f,0x5b,0x03,0x07,0x11,0x13,0x05,0x07,0x00,0x2f,0xce,0x2f,0xce,0x12,0x17,0x39,0x2f,0x2f,0x2f, 0x11,0x33,0x10,0xce,0x32,0x11,0x33,0x10,0xce,0x32,0x11,0x33,0x10,0xce,0x32,0x31,0x30,0x01,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x03,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x01,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x13,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37, 0x33,0x01,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x01,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x01,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x13,0x17,0x23,0x27,0x07,0x23,0x37,0x27,0x33,0x17,0x37,0x33,0x04,0x1d,0x7e,0x60,0x4a,0x4b,0x5f,0x7e,0x88,0x60,0x54,0x53,0x60,0x87,0x7e, 0x60,0x4a,0x4b,0x5f,0x7e,0x88,0x60,0x54,0x53,0x60,0x01,0xa4,0x7d,0x5f,0x4b,0x4a,0x60,0x7f,0x88,0x60,0x53,0x54,0x60,0x1c,0x7e,0x60,0x4a,0x4b,0x5f,0x7e,0x88,0x60,0x54,0x53,0x60,0xfe,0xdf,0x7d,0x5f,0x4b,0x4a,0x60,0x7f,0x88,0x60,0x53,0x54,0x60,0xfb,0x1c,0x7d,0x5f,0x4b,0x4a,0x60,0x7f,0x88,0x60,0x53,0x54,0x60,0xfe,0xd4,0x7e, 0x60,0x4a,0x4b,0x5f,0x7e,0x88,0x60,0x54,0x53,0x60,0x27,0x7d,0x5f,0x4b,0x4a,0x60,0x7f,0x88,0x60,0x53,0x54,0x60,0x05,0x30,0xba,0x7c,0x7c,0xba,0xc8,0x89,0x89,0xf9,0x78,0xba,0x7b,0x7b,0xba,0xc7,0x88,0x88,0x04,0x63,0xba,0x7c,0x7c,0xba,0xc8,0x89,0x89,0xfc,0xee,0xb9,0x7b,0x7b,0xb9,0xc8,0x88,0x88,0xfc,0xed,0xba,0x7c,0x7c,0xba, 0xc8,0x89,0x89,0x03,0xcd,0xba,0x7c,0x7c,0xba,0xc8,0x89,0x89,0xfc,0xee,0xb9,0x7b,0x7b,0xb9,0xc8,0x88,0x88,0xfc,0xed,0xba,0x7c,0x7c,0xba,0xc8,0x89,0x89,0x00,0x02,0x01,0x13,0xfe,0x52,0x06,0xce,0x06,0x5b,0x00,0x07,0x00,0x0f,0x00,0x40,0xb1,0x05,0x0b,0xb8,0x01,0x04,0xb3,0x06,0x08,0x01,0x0f,0xb8,0x01,0x04,0x40,0x0c,0x02,0x0c, 0x0d,0x09,0x02,0x06,0x09,0x06,0x09,0x06,0x07,0x0b,0xbc,0x01,0x05,0x00,0x08,0x00,0x04,0x01,0x05,0x00,0x07,0x00,0x2f,0xed,0x2f,0xed,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x01,0x2f,0x33,0xed,0x32,0x2f,0x33,0xed,0x32,0x31,0x30,0x01,0x11,0x23,0x11,0x21,0x11,0x23,0x19,0x02,0x33,0x11,0x21,0x11,0x33,0x11,0x06,0xce,0x60, 0xfb,0x09,0x64,0x64,0x04,0xf7,0x60,0x06,0x5b,0xfe,0x26,0x01,0x80,0xfe,0x80,0x01,0xda,0xf7,0xf7,0x01,0xda,0xfe,0x80,0x01,0x80,0xfe,0x26,0x00,0x00,0x0a,0x00,0x26,0xfe,0x52,0x07,0xbb,0x06,0x5b,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x2f,0x00,0xae,0xb3,0x28,0x10,0x14, 0x2f,0xb8,0x01,0x04,0xb3,0x2c,0x0b,0x07,0x0f,0xb8,0x01,0x04,0xb4,0x0c,0x04,0x00,0x0c,0x1b,0xb8,0x01,0x04,0x40,0x1f,0x18,0x25,0x1d,0x21,0x14,0x2c,0x02,0x0c,0x09,0x18,0x21,0x21,0x18,0x09,0x0c,0x02,0x2c,0x14,0x07,0x11,0x24,0x20,0x1c,0x29,0x15,0x11,0x19,0x0d,0x2d,0x22,0x16,0xb8,0x01,0x05,0xb4,0x15,0x21,0x15,0x26,0x2a,0xb8, 0x01,0x05,0xb4,0x29,0x25,0x29,0x1e,0x12,0xb8,0x01,0x05,0x40,0x12,0x11,0x1d,0x11,0x2d,0x15,0x29,0x11,0x11,0x29,0x15,0x2d,0x04,0x03,0x18,0x0c,0x2c,0x0a,0x02,0xb8,0x01,0x05,0xb1,0x07,0x03,0x00,0x2f,0x33,0xed,0x32,0x2f,0x33,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x11,0x33, 0x10,0xed,0x32,0x11,0x33,0x33,0x01,0x2f,0x33,0x33,0x2f,0x33,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0x10,0xed,0x11,0x33,0x33,0x31,0x30,0x01,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x03,0x11,0x33,0x11,0x01,0x21,0x35,0x21,0x11,0x21, 0x35,0x21,0x01,0x11,0x33,0x11,0x01,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x05,0x21,0x35,0x21,0x13,0x11,0x33,0x11,0x03,0xbd,0xc0,0xc0,0x64,0xb6,0xb6,0x64,0x64,0xfd,0xd5,0xfe,0x30,0x01,0xd0,0xfe,0x30,0x01,0xd0,0x03,0x61,0x64,0x02,0x00,0xfe,0x30,0x01,0xd0,0xfe,0x30,0x01,0xd0,0xfe,0x30,0x01,0xd0,0xfa,0x3b, 0xfe,0x30,0x01,0xd0,0x2d,0x64,0x04,0x8b,0xb6,0x64,0xb6,0xb6,0x64,0xb6,0xf9,0xc7,0x01,0xd0,0xfe,0x30,0x05,0x6c,0x64,0xfc,0x68,0x64,0xfd,0x64,0x01,0xd0,0xfe,0x30,0x05,0x6c,0x64,0xfc,0x68,0x64,0x01,0x36,0x64,0x64,0x64,0xfb,0xca,0x01,0xd0,0xfe,0x30,0x00,0x00,0x02,0x00,0x7d,0x02,0xaf,0x03,0x54,0x05,0xeb,0x00,0x0b,0x00,0x17, 0x00,0x64,0xb2,0x16,0x0c,0x17,0xb8,0x01,0x00,0xb5,0x00,0x14,0x0e,0x12,0x10,0x06,0xb8,0x01,0x00,0x40,0x23,0x11,0x00,0x0e,0x11,0x11,0x0e,0x00,0x03,0x01,0x07,0x05,0x0b,0x01,0x0f,0x0c,0x0b,0x08,0x0b,0x13,0x16,0x01,0x04,0x01,0x0e,0x09,0x0b,0x14,0x01,0x0b,0x01,0x0b,0x01,0x03,0x09,0x03,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f, 0x11,0x39,0x11,0x12,0x39,0x11,0x33,0x10,0xc9,0x32,0x11,0x33,0x10,0xc9,0x32,0x01,0x2f,0x33,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xfd,0xc5,0x32,0x11,0x33,0x10,0xed,0xc5,0x32,0x31,0x30,0x13,0x27,0x33,0x37,0x17,0x33,0x07,0x17,0x23,0x07,0x27,0x23,0x37,0x33,0x17,0x37,0x33,0x27,0x37,0x23,0x27,0x07,0x23,0x17,0xfa,0x7d, 0xf9,0x73,0x74,0xf7,0x7c,0x7c,0xf8,0x73,0x73,0xf7,0x69,0xb1,0x50,0x50,0xb0,0x58,0x58,0xb0,0x50,0x51,0xb0,0x58,0x04,0x4e,0xd5,0xc8,0xc8,0xd6,0xd6,0xc8,0xc8,0x3d,0x8b,0x8b,0x99,0x99,0x8b,0x8b,0x99,0x00,0x00,0x01,0xfe,0x9c,0x04,0xc2,0x01,0x64,0x05,0xf2,0x00,0x0d,0x00,0x13,0xb6,0x0a,0x04,0x0a,0x04,0x80,0x00,0x07,0x00,0x2f, 0xc9,0x1a,0xcd,0x32,0x01,0x2f,0x2f,0x31,0x30,0x03,0x32,0x36,0x37,0x33,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16,0x33,0x01,0x4e,0x6c,0x09,0xa2,0x0f,0xc2,0x97,0x9c,0xbb,0x09,0xa2,0x12,0xae,0x05,0x36,0x67,0x55,0x8c,0xa4,0xa5,0x8b,0xbc,0x00,0x01,0xff,0x33,0x04,0x80,0x00,0xce,0x05,0xbe,0x00,0x12,0x00,0x26,0x40,0x10,0x01,0x01, 0x06,0x11,0x00,0x00,0x09,0x06,0x0c,0x40,0x03,0x03,0x10,0x08,0x80,0x00,0x00,0x2f,0x1a,0xcc,0x32,0x39,0x2f,0x1a,0xc9,0x01,0x2f,0xd9,0xc0,0x2f,0x2f,0x12,0x39,0x2f,0x31,0x30,0x13,0x37,0x06,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x33,0x03,0x0e,0x1b,0x41,0x35,0x39,0x47,0x76,0x1c,0x1f,0x1d,0x27, 0x15,0x18,0x79,0x46,0x04,0x80,0x77,0x1f,0x46,0x48,0x58,0x3c,0x26,0x21,0x0e,0x09,0x6c,0xfe,0xc2,0x00,0x00,0x01,0x00,0xfc,0x04,0xc2,0x03,0xc4,0x05,0xf2,0x00,0x0d,0x00,0x11,0xb5,0x0a,0x04,0x00,0x07,0x0a,0x04,0x00,0x2f,0x33,0x2f,0xc9,0x01,0x2f,0x2f,0x31,0x30,0x01,0x32,0x36,0x37,0x33,0x06,0x06,0x23,0x22,0x26,0x27,0x33,0x16, 0x33,0x02,0x5f,0x4e,0x6c,0x09,0xa2,0x0f,0xc2,0x97,0x9c,0xbb,0x09,0xa2,0x12,0xae,0x05,0x36,0x67,0x55,0x8c,0xa4,0xa5,0x8b,0xbc,0x00,0x00,0x01,0x01,0x33,0x04,0x80,0x02,0xce,0x05,0xbe,0x00,0x12,0x00,0x26,0x40,0x10,0x01,0x01,0x06,0x11,0x00,0x00,0x09,0x06,0x0c,0x40,0x03,0x03,0x10,0x08,0x80,0x00,0x00,0x2f,0x1a,0xcc,0x32,0x39, 0x2f,0x1a,0xc9,0x01,0x2f,0xd9,0xc0,0x2f,0x2f,0x12,0x39,0x2f,0x31,0x30,0x01,0x37,0x06,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x33,0x03,0x02,0x0f,0x1a,0x41,0x35,0x39,0x47,0x76,0x1c,0x1f,0x1e,0x26,0x15,0x18,0x79,0x46,0x04,0x80,0x77,0x1f,0x46,0x48,0x58,0x3c,0x26,0x21,0x0e,0x09,0x6c,0xfe,0xc2, 0x00,0x02,0x00,0x0f,0xfe,0x7f,0x05,0x48,0x06,0xa2,0x00,0x10,0x00,0x16,0x00,0x42,0x40,0x22,0x15,0x03,0x0c,0x7f,0x09,0x0e,0x7e,0x16,0x09,0x16,0x09,0x16,0x00,0x03,0x7f,0x04,0x10,0x7f,0x00,0x0a,0x0c,0x00,0x04,0x02,0x12,0x91,0x0c,0x03,0x0e,0x15,0x05,0x91,0x02,0x12,0x00,0x3f,0xed,0x32,0x32,0x3f,0xed,0x10,0xcd,0x32,0x10,0xcd, 0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x10,0xc4,0x31,0x30,0x01,0x11,0x21,0x11,0x23,0x11,0x33,0x12,0x12,0x11,0x35,0x33,0x11,0x21,0x11,0x33,0x11,0x01,0x21,0x06,0x02,0x07,0x21,0x04,0xad,0xfb,0xfd,0x9b,0x6f,0xa4,0xc2,0x90,0x02,0x13,0xc1,0xfe,0x97,0xfe,0x94,0x11,0xb6,0x78,0x02,0xab,0xfe,0x7f, 0x01,0x81,0xfe,0x7f,0x02,0x19,0x01,0x31,0x02,0xdb,0x01,0x11,0xed,0xfe,0xf8,0xfa,0xfe,0xfd,0xe7,0x06,0x83,0xf6,0xfd,0x7c,0xf0,0x00,0x00,0x02,0x00,0x12,0xfe,0x8b,0x04,0x23,0x05,0x0e,0x00,0x10,0x00,0x15,0x00,0x40,0x40,0x21,0x14,0x0c,0xed,0x09,0x0e,0x84,0x15,0x09,0x15,0x09,0x15,0x00,0x03,0xed,0x04,0x10,0xed,0x00,0x0a,0x0c, 0x00,0x04,0x02,0x12,0x95,0x0c,0x0f,0x0e,0x14,0x05,0x95,0x02,0x15,0x00,0x3f,0xed,0x32,0x32,0x3f,0xed,0x10,0xcd,0x32,0x10,0xcd,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0xc4,0x31,0x30,0x01,0x11,0x21,0x11,0x23,0x11,0x33,0x36,0x12,0x11,0x35,0x33,0x11,0x21,0x11,0x33,0x11,0x01,0x23,0x02,0x03,0x21, 0x03,0x98,0xfd,0x06,0x8c,0x5c,0x88,0x81,0x90,0x01,0x84,0x98,0xfe,0xc4,0xe3,0x20,0xc9,0x01,0xcc,0xfe,0x8b,0x01,0x75,0xfe,0x8b,0x02,0x00,0xcf,0x01,0xad,0x01,0x15,0xf2,0xfe,0xf2,0xfc,0x8b,0xfe,0x00,0x04,0xea,0xfe,0x4d,0xfe,0xc9,0x00,0x00,0x01,0x00,0x79,0xfe,0x29,0x03,0xde,0x05,0xb2,0x00,0x22,0x00,0x28,0x40,0x15,0x22,0x16, 0x7d,0x0b,0x11,0x1d,0x7d,0x05,0x11,0x16,0x05,0x00,0x04,0x0e,0x02,0x91,0x20,0x13,0x91,0x0e,0x04,0x00,0x3f,0xed,0x2f,0xed,0x12,0x17,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0xed,0xc4,0x31,0x30,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x26,0x26,0x35,0x34,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x02, 0x15,0x14,0x04,0x23,0x22,0x27,0x79,0xb7,0xca,0x93,0xa1,0x87,0xc8,0xbf,0xa5,0x01,0x0f,0xe3,0xa5,0x90,0x9e,0xa8,0x88,0xa9,0xa3,0x95,0x98,0x9b,0x48,0xfe,0xf6,0xf4,0xcc,0x9b,0xbf,0x81,0xa4,0x94,0x7d,0xbf,0x8b,0x83,0xff,0x9e,0xd4,0xff,0x33,0xbd,0x58,0xa9,0x89,0x7f,0xd0,0x5e,0x61,0xa0,0xb7,0x76,0xe7,0xfd,0x52,0x00,0x00,0x01, 0x00,0x67,0xfe,0x29,0x03,0x0f,0x04,0x18,0x00,0x23,0x00,0x29,0x40,0x16,0x23,0x18,0x83,0x0c,0x13,0x1e,0x83,0x06,0x13,0x18,0x06,0x00,0x04,0x10,0x03,0x95,0x21,0x1b,0x15,0x95,0x10,0x10,0x00,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0xed,0xc4,0x31,0x30,0x17,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x26, 0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x67,0x3d,0x9b,0x50,0x64,0x74,0x6d,0x7d,0x8e,0x85,0x61,0xb3,0x74,0x8e,0x60,0x72,0x88,0x63,0x71,0x62,0x76,0xa0,0x85,0xda,0xbb,0x9b,0x77,0xea,0x2e,0x35,0x7c,0x74,0x5d,0x93,0x4b,0x53,0xd5,0x8d,0x70, 0xb3,0x62,0x2e,0xa6,0x4a,0x81,0x72,0x63,0x90,0x48,0x63,0xc3,0x83,0xb5,0xd9,0x3d,0x00,0x01,0x00,0x60,0xff,0xe8,0x08,0x9a,0x05,0xb2,0x00,0x34,0x00,0x72,0x40,0x3e,0x28,0x7d,0x1d,0x2b,0x08,0x7d,0x06,0x15,0x2f,0x03,0x7e,0x04,0x2c,0x04,0x22,0x18,0x1d,0x15,0x04,0x33,0x32,0x32,0x33,0x04,0x15,0x1d,0x18,0x22,0x07,0x0e,0x34,0x0e, 0x33,0x2f,0x02,0x2f,0x02,0x06,0x18,0x92,0x2b,0x0f,0x04,0x22,0x2d,0x19,0x19,0x04,0x31,0x2d,0x03,0x20,0x92,0x25,0x04,0x12,0x92,0x0c,0x13,0x00,0x04,0x12,0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0x33,0xed,0x32,0x32,0x33,0x11,0x12,0x39,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f, 0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xcd,0xed,0xc4,0x10,0xed,0x31,0x30,0x21,0x01,0x23,0x11,0x23,0x11,0x21,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x21,0x11,0x33,0x11, 0x33,0x01,0x33,0x01,0x01,0x07,0xb0,0xfd,0xd7,0x2b,0xa8,0xfe,0x9d,0x91,0x7c,0xed,0xa2,0xf6,0x81,0x55,0xc7,0x61,0x9e,0xb4,0xfe,0x8b,0x95,0x89,0x9f,0xaf,0x94,0x7c,0xb9,0xa5,0xa3,0xc9,0xcc,0xea,0x54,0x45,0x01,0x9d,0xa8,0x2b,0x02,0x17,0xd1,0xfd,0xa1,0x02,0x8a,0x02,0xa0,0xfd,0x60,0x02,0xa0,0x5f,0xab,0x80,0xc3,0x6b,0x54,0xb6, 0x40,0x3b,0x96,0x7f,0x01,0x14,0x8b,0x8c,0x7c,0x6f,0x7f,0x71,0xaa,0x58,0xbf,0xa1,0x64,0x9a,0x29,0x02,0x6f,0xfd,0x91,0x02,0x6f,0xfd,0x59,0xfd,0x0d,0x00,0x00,0x01,0x00,0x50,0xff,0xe7,0x07,0x39,0x04,0x19,0x00,0x31,0x00,0x6f,0x40,0x3c,0x30,0x1d,0x84,0x13,0x20,0x00,0x84,0x0b,0x24,0x2d,0x84,0x2e,0x21,0x2e,0x0e,0x13,0x0b,0x2e, 0x28,0x27,0x27,0x28,0x2e,0x0b,0x13,0x0e,0x06,0x05,0x29,0x18,0x05,0x28,0x2c,0x24,0x24,0x2c,0x30,0x0e,0x95,0x20,0x06,0x2e,0x18,0x0f,0x0f,0x22,0x2a,0x2e,0x15,0x26,0x22,0x0f,0x16,0x95,0x1b,0x10,0x09,0x95,0x03,0x16,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x3f,0x33,0x12,0x39,0x2f,0x39,0x12,0x39,0x33,0xed,0x32,0x32,0x33,0x11,0x12, 0x39,0x01,0x2f,0x33,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xed,0xcd,0x10,0xfd,0xc4,0x31,0x30,0x01,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x16,0x33,0x20,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x14,0x06,0x07,0x21,0x11,0x33,0x11, 0x33,0x01,0x33,0x01,0x01,0x23,0x01,0x23,0x11,0x23,0x11,0x21,0x16,0x03,0x3b,0xe0,0xc8,0xde,0x65,0x3a,0xab,0x54,0x01,0x0f,0xfe,0xd7,0x65,0x60,0x84,0x81,0x76,0x6a,0x95,0x96,0xa1,0x97,0x01,0x76,0x35,0x2c,0x01,0x36,0xa4,0x2a,0x01,0x88,0xd7,0xfe,0x29,0x01,0xfc,0xe6,0xfe,0x62,0x2a,0xa4,0xfe,0xf6,0x5e,0x01,0x19,0x8c,0xa6,0x36, 0xa1,0x23,0x28,0xac,0xaa,0x8b,0x4f,0x53,0x46,0x51,0x4b,0x99,0x3e,0xfe,0xed,0x3f,0x53,0x20,0x01,0xac,0xfe,0x54,0x01,0xac,0xfe,0x16,0xfd,0xea,0x01,0xc9,0xfe,0x37,0x01,0xc9,0x40,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x06,0xc6,0x05,0x9a,0x00,0x20,0x00,0x38,0x40,0x1c,0x19,0x7e,0x16,0x14,0x14,0x00,0x0f,0x7e,0x0c,0x20,0x7e,0x1d, 0x00,0x1b,0x11,0x91,0x03,0x01,0x05,0x0d,0x09,0x09,0x1e,0x17,0x0d,0x03,0x00,0x12,0x00,0x3f,0x3f,0x33,0x33,0x39,0x2f,0x12,0x39,0x39,0x33,0xed,0x32,0x01,0x2f,0x33,0xed,0x2f,0xed,0x12,0x39,0x2f,0x33,0xed,0x31,0x30,0x21,0x11,0x06,0x23,0x22,0x27,0x0e,0x02,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x37,0x26,0x35, 0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x11,0x06,0x1e,0xc3,0xa9,0xc3,0x5b,0x68,0x79,0x7c,0x41,0x9f,0xb1,0xa8,0xc9,0x4d,0xba,0x4d,0x09,0xa8,0xc9,0x96,0xb5,0xa8,0x02,0x85,0x79,0x95,0x3f,0x36,0x20,0xc1,0xad,0x02,0x20,0xfd,0xf2,0xec,0x42,0x32,0x2f,0x3c,0x02,0x1b,0xfd,0xed,0xe7,0x6e,0x02,0x8c,0xfa,0x66,0x00,0x00,0x01, 0x00,0x98,0x00,0x00,0x06,0x3b,0x04,0x00,0x00,0x20,0x00,0x3c,0x40,0x1e,0x19,0xef,0x14,0x16,0x14,0x16,0x14,0x00,0x0f,0x84,0x0c,0x20,0x84,0x1d,0x00,0x1b,0x11,0xec,0x04,0x01,0x07,0x0d,0x0a,0x0a,0x1e,0x17,0x0d,0x0f,0x00,0x15,0x00,0x3f,0x3f,0x33,0x33,0x39,0x2f,0x12,0x39,0x39,0x33,0xed,0x32,0x01,0x2f,0x33,0xed,0x2f,0xed,0x12, 0x39,0x39,0x2f,0x2f,0x10,0xed,0x31,0x30,0x21,0x11,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x14,0x33,0x32,0x36,0x37,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x37,0x11,0x33,0x11,0x05,0x98,0x46,0x9a,0x5a,0x60,0x8d,0x22,0x90,0x98,0x49,0xfe,0xba,0xa4,0xb4,0x59,0x98,0x43,0x0c,0xa3,0xb5,0x8b,0x9d, 0xa3,0x01,0x9c,0x27,0x3b,0x43,0x3c,0x4f,0x30,0x01,0x6c,0x01,0x5a,0xfe,0xaf,0xe2,0x38,0x24,0x32,0x4b,0x01,0x5a,0xfe,0xae,0xe1,0x56,0x01,0xdd,0xfc,0x00,0x00,0x02,0x00,0x0f,0xfe,0x38,0x05,0xda,0x05,0x9a,0x00,0x29,0x00,0x2f,0x00,0x4c,0x40,0x27,0x2e,0x13,0x7f,0x14,0x08,0x1b,0x7e,0x29,0x2f,0x1e,0x7f,0x0e,0x2f,0x0e,0x2f,0x0e, 0x05,0x14,0x21,0x24,0x7f,0x05,0x2b,0x91,0x19,0x03,0x21,0x09,0x08,0x08,0x03,0x27,0x2e,0x1b,0x15,0x91,0x14,0x12,0x12,0x00,0x3f,0xcd,0xed,0x32,0x32,0xc4,0x32,0x39,0x2f,0x33,0x33,0x3f,0xed,0x01,0x2f,0xfd,0xcd,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xc4,0xfd,0xc4,0x10,0xfd,0xc4,0x31,0x30,0x01,0x16,0x16,0x33,0x32,0x35, 0x34,0x23,0x23,0x35,0x17,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x23,0x11,0x33,0x12,0x12,0x13,0x21,0x11,0x33,0x32,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x03,0x21,0x06,0x02,0x07,0x21,0x04,0x2a,0x24,0x60,0x1e,0x7d,0x89,0x47,0x20,0x20,0x3b,0x42,0x3c,0x40,0xfb,0xf0,0x9b,0x6f,0x92,0xc7,0x0d,0x02, 0xa3,0x47,0xf9,0x36,0x28,0x32,0x3f,0x85,0x77,0x68,0x4b,0x4c,0xfe,0x94,0x0f,0xb1,0x7f,0x02,0xab,0xfe,0xc7,0x0e,0x12,0x43,0x3a,0x69,0x01,0x21,0x1b,0x1f,0x19,0xfe,0x7f,0x02,0x19,0x01,0x0a,0x02,0xc6,0x01,0x32,0xfa,0xec,0xa6,0x33,0x41,0x0b,0x0c,0x45,0x34,0x4e,0x56,0x1a,0x06,0xb0,0xef,0xfd,0x83,0xfe,0x00,0x00,0x02,0x00,0x12, 0xfe,0x38,0x04,0xcb,0x04,0x00,0x00,0x2a,0x00,0x30,0x00,0x54,0x40,0x0a,0x2f,0x13,0xed,0x14,0x08,0x1c,0x84,0x2a,0x30,0x1f,0xb8,0x01,0x2e,0x40,0x09,0x0e,0x30,0x0e,0x30,0x0e,0x05,0x14,0x22,0x25,0xb8,0x01,0x2e,0x40,0x12,0x05,0x2c,0x95,0x1a,0x0f,0x22,0x09,0x08,0x08,0x03,0x28,0x2f,0x1c,0x15,0x95,0x14,0x12,0x15,0x00,0x3f,0xcd, 0xed,0x32,0x32,0xc4,0x32,0x39,0x2f,0x33,0x33,0x3f,0xed,0x01,0x2f,0xfd,0xcd,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xc4,0xfd,0xc4,0x10,0xfd,0xc4,0x31,0x30,0x01,0x16,0x16,0x33,0x32,0x35,0x34,0x23,0x23,0x35,0x17,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x23,0x11,0x33,0x36,0x12,0x35,0x35,0x21,0x11,0x33,0x32,0x15, 0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x03,0x23,0x06,0x02,0x07,0x21,0x03,0x1b,0x17,0x6d,0x1e,0x7d,0x89,0x47,0x20,0x20,0x3a,0x43,0x3c,0x36,0xfc,0xe9,0x8c,0x5b,0x80,0x8a,0x02,0x14,0x34,0xf9,0x36,0x28,0x30,0x41,0x87,0x75,0x68,0x4b,0x35,0xe3,0x0a,0x73,0x6d,0x01,0xcd,0xfe,0xc7,0x0a,0x16,0x43,0x3a,0x69,0x01, 0x20,0x1c,0x1f,0x19,0xfe,0x8b,0x02,0x00,0xb6,0x01,0xc8,0xea,0x0d,0xfc,0x87,0xa7,0x34,0x40,0x0b,0x0c,0x45,0x34,0x4e,0x56,0x1a,0x05,0x23,0xbc,0xfe,0x80,0xae,0x00,0x00,0x01,0x00,0x29,0xfe,0x66,0x05,0x3d,0x05,0x9a,0x00,0x1e,0x00,0x39,0x40,0x1d,0x13,0x0b,0xad,0x0c,0x1e,0x1e,0x05,0x0e,0x18,0x7d,0x11,0x05,0x0a,0x91,0x13,0x13, 0x0c,0x12,0x0e,0x91,0x0f,0x03,0x00,0x0c,0x02,0x91,0x1c,0x0c,0x12,0x00,0x3f,0xd4,0xed,0x11,0x39,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f,0xc4,0xed,0x2f,0x12,0x39,0x2f,0x33,0xe4,0x32,0x31,0x30,0x05,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x33,0x32,0x04,0x12,0x15, 0x14,0x02,0x06,0x23,0x22,0x27,0x01,0xc8,0xa2,0x9c,0xba,0xcd,0x76,0xda,0x8d,0x42,0xa8,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x4a,0xc1,0x01,0x26,0x9e,0x89,0xff,0xab,0xaa,0x98,0x96,0x6c,0xde,0xcc,0x94,0xe8,0x7e,0xfd,0x5e,0x05,0x02,0x98,0x98,0xfe,0x38,0xa2,0xfe,0xd6,0xc0,0xab,0xfe,0xf5,0x92,0x4c,0x00,0x00,0x01,0x00,0x1e,0xfe,0x66, 0x04,0x56,0x04,0x00,0x00,0x1d,0x00,0x39,0x40,0x1d,0x12,0x0a,0x84,0x1d,0x0b,0x0b,0x05,0x0d,0x16,0x83,0x10,0x05,0x09,0x95,0x12,0x12,0x0b,0x11,0x0d,0x95,0x0e,0x0f,0x00,0x0b,0x02,0x95,0x1a,0x0b,0x15,0x00,0x3f,0xd4,0xed,0x11,0x39,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x01,0x2f,0xc4,0xed,0x2f,0x12,0x39,0x2f,0xc4,0xed,0x32,0x31, 0x30,0x05,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x33,0x32,0x00,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x27,0x01,0x52,0x79,0x87,0xa5,0xb7,0xd9,0xbf,0x20,0xa4,0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0x42,0xf7,0x01,0x27,0x81,0xeb,0x9a,0x4c,0x6c,0x46,0xc0,0x4e,0xb9,0xab,0xb9,0xd7,0xfe, 0x1a,0x03,0x74,0x8c,0x8c,0xff,0x00,0xfe,0xde,0xfa,0x8e,0xe5,0x7f,0x16,0x24,0x00,0x00,0x01,0x00,0x29,0xff,0xe8,0x04,0x0c,0x05,0x9a,0x00,0x11,0x00,0x23,0x40,0x11,0x0c,0x7e,0x05,0x00,0x05,0x00,0x09,0x07,0x0b,0x07,0x91,0x08,0x03,0x0f,0x92,0x02,0x13,0x00,0x3f,0xed,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0xed,0x31, 0x30,0x25,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x03,0x83,0x3c,0x57,0x95,0x95,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x52,0x56,0x44,0x29,0x01,0x19,0xa3,0xac,0x03,0xcb,0x98,0x98,0xfc,0x53,0x78,0x66,0x1d,0x00,0x01,0x00,0x1e,0xff,0xe8,0x03,0x29,0x04,0x00,0x00,0x10,0x00,0x23,0x40,0x11, 0x0b,0x84,0x04,0x00,0x04,0x00,0x08,0x06,0x0a,0x06,0x95,0x07,0x0f,0x0e,0x95,0x02,0x16,0x00,0x3f,0xed,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x25,0x06,0x23,0x20,0x11,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x03,0x0c,0x34,0x58,0xfe,0xd2,0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0x55,0x53, 0x45,0x29,0x01,0x19,0x01,0x50,0x02,0x3c,0x8c,0x8c,0xfd,0xdd,0x78,0x67,0x1d,0x00,0x00,0x01,0x00,0xae,0xfe,0x29,0x05,0xbd,0x05,0x9a,0x00,0x26,0x00,0x40,0x40,0x12,0x26,0x17,0x7e,0x14,0x14,0x0c,0x13,0x03,0x7f,0x10,0x21,0x1a,0x7f,0x0c,0x15,0x11,0x03,0x24,0xb8,0x01,0x05,0xb3,0x00,0x00,0x10,0x07,0xb8,0x01,0x05,0xb5,0x1e,0x17, 0x13,0x91,0x10,0x12,0x00,0x3f,0xed,0x32,0xd4,0xed,0x12,0x39,0x2f,0xed,0x3f,0x33,0x01,0x2f,0xed,0x2f,0x33,0xed,0x32,0x12,0x39,0x2f,0xed,0xc4,0x31,0x30,0x05,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x21,0x32,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x16,0x16,0x15,0x14,0x04,0x21,0x21,0x22,0x26,0x35, 0x34,0x36,0x33,0x21,0x15,0x01,0xd0,0x45,0x4e,0x88,0x8b,0x0f,0x01,0x32,0x93,0xb4,0x51,0x74,0x68,0xfc,0x6f,0xa8,0x02,0xe6,0xa8,0x63,0x68,0xff,0x00,0xfe,0xf0,0xfe,0x9a,0xd3,0xc6,0x8b,0x93,0x02,0x5a,0xd8,0x23,0x21,0x30,0x24,0x2c,0x51,0x4e,0x51,0x54,0x05,0x9a,0xfa,0xfe,0x05,0x02,0xfa,0xf8,0x22,0x92,0x69,0xab,0xa1,0x56,0x63, 0x4e,0x5d,0x65,0x00,0x00,0x01,0x00,0x8f,0xfe,0x29,0x04,0xc6,0x04,0x00,0x00,0x24,0x00,0x44,0x40,0x10,0x11,0x84,0x0e,0x24,0x15,0x84,0x12,0x0e,0x12,0x0e,0x12,0x0a,0x03,0xed,0x1f,0x18,0xb8,0x01,0x2e,0x40,0x10,0x0a,0x22,0x00,0x00,0x0e,0x06,0x1c,0x1b,0x13,0x0f,0x0f,0x15,0x11,0x95,0x0e,0x15,0x00,0x3f,0xed,0x32,0x3f,0x33,0x3f, 0xcd,0x12,0x39,0x2f,0xcd,0x01,0x2f,0xed,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0xc4,0x10,0xed,0x31,0x30,0x05,0x22,0x06,0x15,0x14,0x16,0x33,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x16,0x16,0x15,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x15,0x01,0x9a,0x3c,0x44,0x78, 0x6c,0xc3,0xc3,0xaf,0x72,0x60,0xfd,0x45,0xa4,0x02,0x0a,0xa4,0x61,0x6d,0xfb,0xfb,0xed,0xaa,0xaa,0x87,0x77,0x01,0xab,0xd8,0x23,0x20,0x32,0x26,0x01,0x66,0x67,0x4c,0x59,0x04,0x00,0xfc,0x8b,0x03,0x75,0xfc,0x7b,0x1d,0x91,0x62,0x9e,0xa4,0x5c,0x62,0x4d,0x57,0x63,0x00,0x00,0x01,0x00,0x29,0xfe,0x9b,0x04,0x0c,0x05,0x9a,0x00,0x13, 0x00,0x31,0x40,0x19,0x00,0x7e,0x0a,0x05,0x13,0x7e,0x0c,0x0a,0x0c,0x0a,0x0c,0x10,0x0e,0x12,0x0e,0x91,0x0f,0x03,0x02,0x92,0x07,0x0b,0x92,0x00,0x12,0x00,0x3f,0xed,0xd4,0xed,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x39,0x39,0x2f,0x2f,0x10,0xfd,0xc4,0x10,0xed,0x31,0x30,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x35,0x33, 0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x01,0xcf,0x0a,0xa5,0x4c,0x32,0x38,0x52,0x9f,0xac,0x9f,0xfe,0x63,0x03,0xe3,0xfe,0x62,0xdb,0x20,0x92,0x18,0xc5,0xba,0x76,0x04,0x72,0x98,0x98,0xfa,0xfe,0x00,0x00,0x01,0x00,0x1e,0xfe,0x9b,0x03,0x29,0x04,0x00,0x00,0x13,0x00,0x2d,0x40,0x17,0x05,0x13,0x84,0x0c,0x0c,0x0a,0x10,0x0e,0x00,0x84, 0x0a,0x12,0x0e,0x95,0x0f,0x0f,0x02,0x95,0x07,0x0b,0xec,0x00,0x15,0x00,0x3f,0xed,0xd4,0xed,0x3f,0xed,0x32,0x01,0x2f,0xed,0xc6,0x2f,0x12,0x39,0x2f,0xfd,0xc4,0x31,0x30,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x35,0x33,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x01,0x53,0x0a,0xa4,0x44,0x2e,0x3d,0x45,0x9c,0xa6,0xa3, 0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0xdb,0x20,0x93,0x17,0xc7,0xb8,0x76,0x02,0xe4,0x8c,0x8c,0xfc,0x8c,0x00,0x00,0x01,0x00,0x29,0x00,0x00,0x05,0xc5,0x05,0x9a,0x00,0x14,0x00,0x37,0x40,0x1c,0x0d,0x7e,0x06,0x0b,0x06,0x0b,0x00,0x08,0x14,0x7e,0x11,0x00,0x12,0x03,0x0c,0x08,0x91,0x09,0x0f,0x91,0x01,0x09,0x03,0x03,0x09,0x03,0x00,0x12, 0x00,0x3f,0x3f,0x39,0x2f,0x12,0x39,0xed,0x10,0xed,0x32,0x3f,0x01,0x2f,0x33,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x21,0x11,0x06,0x23,0x22,0x26,0x35,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x21,0x32,0x37,0x11,0x33,0x11,0x05,0x1d,0xf2,0xcb,0xc3,0xd7,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x01,0x04,0xc4,0xe7,0xa8,0x02, 0x85,0x79,0xc3,0xb0,0x01,0x85,0x96,0x98,0xfe,0x85,0xe7,0x6e,0x02,0x8c,0xfa,0x66,0x00,0x01,0x00,0x1e,0x00,0x00,0x04,0xae,0x04,0x00,0x00,0x13,0x00,0x37,0x40,0x1c,0x0c,0x84,0x05,0x0a,0x05,0x0a,0x00,0x07,0x13,0x84,0x10,0x00,0x11,0x0f,0x0b,0x07,0x95,0x08,0x0e,0xec,0x01,0x08,0x03,0x03,0x08,0x0f,0x00,0x15,0x00,0x3f,0x3f,0x39, 0x2f,0x12,0x39,0xed,0x10,0xed,0x32,0x3f,0x01,0x2f,0x33,0xed,0x2f,0x12,0x39,0x39,0x2f,0x2f,0xed,0x31,0x30,0x21,0x11,0x06,0x23,0x20,0x11,0x35,0x21,0x35,0x21,0x15,0x21,0x15,0x14,0x33,0x32,0x37,0x11,0x33,0x11,0x04,0x0b,0xba,0x9c,0xfe,0x9d,0xfe,0xcc,0x03,0x0b,0xfe,0xcd,0xca,0x9a,0xb1,0xa3,0x01,0x9c,0x62,0x01,0x6c,0xce,0x8c, 0x8c,0xc6,0xe1,0x56,0x01,0xdd,0xfc,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x04,0x81,0x05,0xb4,0x00,0x19,0x00,0x2c,0x40,0x16,0x0b,0x18,0x7e,0x19,0x11,0x7e,0x05,0x12,0x15,0x91,0x0b,0x19,0x0d,0x0d,0x02,0x12,0x19,0x12,0x07,0x91,0x02,0x04,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0xed,0x01,0x2f,0xc4,0xed,0x2f,0xed,0x32, 0x31,0x30,0x13,0x10,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x15,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x07,0x11,0x23,0xa6,0x01,0xf2,0x63,0x61,0x5c,0x63,0xae,0xa1,0xea,0xc0,0xbf,0xca,0xa8,0xf5,0xb6,0xe0,0xa8,0x03,0xb4,0x02,0x00,0x17,0x9a,0x1d,0xba,0xca,0x88,0x7a,0xc5,0xaf,0xfd,0xe6,0x02,0x12,0xe8, 0x6e,0xfd,0x74,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x06,0x02,0x00,0x1d,0x00,0x29,0x40,0x15,0x0d,0x1c,0x84,0x1d,0x06,0x13,0x84,0x14,0x0d,0x10,0x14,0x1d,0x15,0x17,0x95,0x10,0x10,0x09,0x95,0x03,0x01,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x12,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0xed,0x32,0x31,0x30,0x13,0x34,0x12,0x33,0x32, 0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x36,0x33,0x20,0x11,0x11,0x23,0x11,0x10,0x23,0x22,0x06,0x06,0x15,0x11,0x23,0xa6,0xf2,0xe5,0x86,0x82,0x3e,0x8c,0x3d,0xa4,0x90,0x04,0x75,0xdb,0x01,0x5a,0xa4,0xee,0x4d,0x83,0x4c,0xa4,0x03,0xe9,0xfc,0x01,0x1d,0x37,0x98,0x20,0x24,0xc3,0xc8,0x96,0xc2,0xfe,0x5f,0xfd,0x89,0x02, 0x4e,0x01,0x40,0x53,0x97,0x60,0xfd,0xbc,0x00,0x01,0x00,0xbc,0xfe,0x29,0x07,0xa5,0x05,0x9a,0x00,0x2a,0x00,0x54,0x40,0x1d,0x03,0x7f,0x25,0x17,0x7e,0x14,0x2a,0x1b,0x7e,0x18,0x25,0x14,0x18,0x18,0x14,0x25,0x03,0x0c,0x13,0x7e,0x10,0x1e,0x7f,0x0c,0x19,0x15,0x11,0x03,0x28,0xb8,0x01,0x05,0xb3,0x00,0x00,0x10,0x07,0xb8,0x01,0x05, 0xb6,0x22,0x1b,0x17,0x13,0x91,0x10,0x12,0x00,0x3f,0xed,0x32,0x32,0xd4,0xed,0x12,0x39,0x2f,0xed,0x3f,0x33,0x33,0x01,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0xc4,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x21,0x32,0x36,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x33,0x11,0x21,0x11, 0x33,0x11,0x21,0x11,0x33,0x11,0x16,0x16,0x15,0x14,0x04,0x21,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x15,0x03,0x47,0x45,0x4e,0x88,0x8b,0x0f,0x01,0xa3,0x93,0xb4,0x51,0x75,0x68,0xfa,0x88,0xa8,0x02,0x13,0xa8,0x02,0x12,0xa8,0x62,0x6a,0xff,0x00,0xfe,0xf0,0xfe,0x28,0xd2,0xc6,0x8b,0x93,0x02,0xcb,0xd8,0x23,0x21,0x30,0x24,0x2b, 0x53,0x4d,0x51,0x54,0x05,0x9a,0xfa,0xfe,0x05,0x02,0xfa,0xfe,0x05,0x02,0xfa,0xf8,0x22,0x91,0x6a,0xaa,0xa2,0x56,0x63,0x4e,0x5d,0x65,0x00,0x01,0x00,0xa6,0xfe,0x29,0x06,0x8f,0x04,0x00,0x00,0x28,0x00,0x51,0x40,0x16,0x03,0xed,0x23,0x15,0x84,0x12,0x28,0x19,0x84,0x16,0x23,0x12,0x16,0x16,0x12,0x23,0x03,0x0a,0x11,0x84,0x0e,0x1c, 0xb8,0x01,0x2e,0x40,0x12,0x0a,0x26,0x00,0x00,0x0e,0x06,0x20,0x1b,0x17,0x13,0x0f,0x0f,0x19,0x15,0x11,0x95,0x0e,0x15,0x00,0x3f,0xed,0x32,0x32,0x3f,0x33,0x33,0x3f,0xcd,0x12,0x39,0x2f,0xcd,0x01,0x2f,0xed,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0xc4,0x10,0xed,0x10,0xed,0x31,0x30,0x05,0x22,0x06,0x15,0x14,0x16,0x33, 0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x16,0x16,0x15,0x14,0x06,0x23,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x15,0x02,0x85,0x3c,0x44,0x78,0x6c,0x01,0xa1,0xc3,0xaf,0x72,0x60,0xfb,0x7c,0xa4,0x01,0x97,0xa4,0x01,0x98,0xa4,0x61,0x6d,0xfb,0xfb,0xfe,0x35,0xaa,0xaa,0x87, 0x77,0x02,0x89,0xd8,0x23,0x20,0x32,0x26,0x01,0x66,0x67,0x4c,0x59,0x04,0x00,0xfc,0x8b,0x03,0x75,0xfc,0x8b,0x03,0x75,0xfc,0x7b,0x1d,0x91,0x62,0x9e,0xa4,0x5c,0x62,0x4d,0x57,0x63,0x00,0x00,0x01,0x00,0x2b,0xff,0xea,0x04,0x1b,0x05,0x2f,0x00,0x1c,0x00,0x47,0x40,0x24,0x0f,0x07,0x84,0x08,0x0c,0x08,0x13,0x17,0x84,0x04,0x10,0x04, 0x08,0x04,0x08,0x04,0x00,0x0a,0x15,0x00,0x12,0x0e,0x16,0x06,0x0a,0x95,0x13,0x0f,0x0b,0x0f,0x08,0x15,0x1a,0x95,0x02,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x33,0xed,0x32,0x32,0xc4,0x32,0x01,0x2f,0x33,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x31,0x30,0x25,0x06,0x23,0x20,0x11,0x11,0x23, 0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x33,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x04,0x1b,0x3a,0x5f,0xfe,0xf3,0xf6,0xa4,0xb0,0xb0,0xa4,0xf6,0xa4,0x01,0x01,0xfe,0xff,0x46,0x51,0x3f,0x2c,0x0a,0x20,0x01,0x2c,0x02,0x5e,0xfc,0x8c,0x03,0x74,0x8c,0xfa,0x35,0xfe,0xd1,0xfa,0x35,0xfe,0xd1,0x8b,0xfd, 0xbe,0x67,0x58,0x22,0x00,0x04,0x00,0x32,0x00,0x00,0x04,0x37,0x05,0xb2,0x00,0x3f,0x00,0x48,0x00,0x51,0x00,0x5a,0x00,0xb2,0xb1,0x4f,0x2b,0xb8,0x01,0x04,0xb2,0x09,0x2c,0x35,0xb8,0x01,0x04,0xb2,0x58,0x46,0x26,0xb8,0x01,0x04,0xb4,0x51,0x15,0x27,0x3e,0x21,0xb8,0x01,0x04,0x40,0x0e,0x22,0x48,0x22,0x2c,0x58,0x27,0x22,0x22,0x27, 0x58,0x2c,0x04,0x00,0x55,0xb8,0x01,0x04,0x40,0x40,0x30,0x10,0x1d,0x7d,0x00,0x58,0x3e,0x4f,0x48,0x51,0x05,0x52,0x46,0x25,0x52,0x33,0x42,0x3b,0x3b,0x33,0x4b,0x37,0x37,0x1d,0x00,0x39,0x35,0x2d,0x2a,0x20,0x23,0x28,0x09,0x25,0x10,0x15,0x09,0x03,0x33,0x25,0x40,0x09,0x11,0x48,0x0f,0x33,0x1f,0x33,0x2f,0x33,0x03,0x25,0x33,0x25, 0x33,0x0d,0x27,0x22,0x2c,0x12,0x12,0x91,0x0d,0x04,0x00,0x3f,0xed,0x3f,0x33,0x33,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x2b,0x11,0x17,0x39,0x12,0x17,0x39,0x33,0x2f,0xc9,0x11,0x33,0x2f,0xc9,0x10,0xc9,0x10,0xc9,0x11,0x17,0x39,0x01,0x2f,0xfd,0xc4,0x2f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x10,0xc4,0x33, 0xed,0x32,0x10,0xed,0x10,0xc4,0xed,0x32,0x31,0x30,0x01,0x34,0x2e,0x02,0x27,0x2e,0x02,0x35,0x34,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x17,0x1e,0x02,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x06,0x23,0x15,0x23,0x35,0x26,0x27,0x15,0x23,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x33,0x32, 0x17,0x36,0x33,0x32,0x15,0x15,0x36,0x27,0x34,0x23,0x22,0x06,0x15,0x15,0x32,0x37,0x25,0x34,0x23,0x22,0x06,0x15,0x15,0x16,0x17,0x25,0x22,0x06,0x15,0x14,0x16,0x17,0x35,0x34,0x03,0x87,0x33,0x5a,0x7b,0x47,0x9e,0x83,0x43,0x82,0xe5,0x8b,0xd3,0x62,0x7f,0xc7,0x8d,0xa4,0x2f,0x66,0xa2,0xaa,0x88,0x4a,0x90,0x84,0x60,0x42,0x61,0x60, 0x64,0x40,0x60,0x3f,0x4b,0x3c,0x33,0x5b,0x17,0x2f,0x5a,0x59,0x1e,0x2f,0x5c,0x85,0x64,0xc4,0x4e,0x24,0x31,0x69,0x3a,0xfe,0xfd,0x4e,0x26,0x30,0x39,0x6b,0xfe,0xde,0x13,0x0f,0x22,0x1e,0x01,0x5e,0x3a,0x56,0x48,0x40,0x24,0x50,0x6f,0x84,0x56,0x74,0xae,0x5d,0x33,0xbd,0x58,0x76,0x62,0x3a,0x56,0x4c,0x50,0x55,0x71,0x8a,0x57,0x7d, 0x8b,0x1b,0x4c,0x3e,0x06,0x38,0x3a,0x05,0x0d,0x4c,0x68,0x1a,0x6d,0x49,0x33,0x3d,0x54,0x53,0x53,0x53,0xaa,0x53,0x36,0x0c,0x6b,0x3e,0x30,0x6b,0x0c,0x65,0x68,0x3d,0x34,0x55,0x0c,0x05,0xe8,0x26,0x15,0x23,0x46,0x11,0x6e,0x47,0x00,0x01,0x00,0xe7,0x00,0x50,0x04,0xf6,0x04,0x5c,0x00,0x09,0x00,0x0d,0xb3,0x06,0x00,0x09,0x03,0x00, 0x2f,0xc4,0x01,0x2f,0xc4,0x31,0x30,0x37,0x01,0x23,0x27,0x05,0x17,0x13,0x27,0x35,0x01,0xe7,0x03,0x46,0xa8,0x68,0x01,0xcc,0x05,0x08,0x69,0xfc,0xb9,0xae,0x03,0x46,0x68,0x08,0x04,0xfe,0x33,0x69,0xac,0xfc,0xb8,0x00,0x00,0x01,0x00,0xe7,0x00,0x50,0x04,0xf6,0x04,0x5c,0x00,0x09,0x00,0x0d,0xb3,0x00,0x06,0x09,0x03,0x00,0x2f,0xc4, 0x01,0x2f,0xc4,0x31,0x30,0x01,0x01,0x37,0x17,0x25,0x27,0x03,0x17,0x07,0x01,0x04,0xf6,0xfc,0xb8,0xaa,0x69,0xfe,0x33,0x04,0x09,0x69,0x02,0x03,0x4a,0x03,0xfe,0xfc,0xb8,0x02,0x68,0x08,0x04,0x01,0xcd,0x68,0xaf,0x03,0x4a,0x00,0x00,0x02,0x00,0x00,0xff,0xb8,0x06,0x78,0x06,0x2e,0x00,0x09,0x00,0x13,0x00,0x2e,0x40,0x16,0x06,0x10, 0x06,0x10,0x00,0x0a,0x0a,0x15,0x30,0x00,0x01,0x00,0x03,0x0d,0x03,0x0d,0x09,0x3f,0x13,0x01,0x13,0x09,0x00,0x2f,0x2f,0x5d,0x12,0x39,0x39,0x2f,0x2f,0x01,0x2f,0x5d,0x11,0x33,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x35,0x01,0x21,0x37,0x21,0x17,0x11,0x07,0x11,0x09,0x02,0x21,0x07,0x21,0x27,0x11,0x37,0x11,0x01,0x01,0xee,0xfe, 0x91,0xb3,0x01,0xfe,0x02,0xb3,0xfe,0x11,0x05,0xe8,0xfe,0x12,0x01,0x6f,0xb3,0xfe,0x02,0x02,0xb3,0x01,0xef,0x48,0x01,0xee,0xb3,0x02,0xfe,0x02,0xb3,0x01,0x73,0xfe,0x0f,0x05,0xe6,0xfe,0x12,0xb3,0x02,0x01,0xfe,0xb3,0xfe,0x8d,0x01,0xf1,0x00,0x03,0x00,0x83,0xff,0xee,0x03,0x31,0x05,0xb2,0x00,0x13,0x00,0x1b,0x00,0x2f,0x00,0x3a, 0x40,0x1d,0x1b,0x08,0x08,0x09,0x09,0x1c,0xaf,0x26,0x26,0x0c,0x00,0x84,0x17,0x17,0x31,0x0c,0x1b,0x0f,0x09,0x2b,0xb0,0x21,0x15,0x0c,0x0a,0x1a,0x95,0x0f,0x00,0x00,0x3f,0xfd,0x32,0xcc,0x3f,0xfd,0xce,0x11,0x39,0x01,0x2f,0x12,0x39,0x2f,0xed,0x11,0x39,0x2f,0xed,0x33,0x2f,0x33,0x11,0x33,0x31,0x30,0x01,0x14,0x07,0x0e,0x03,0x15, 0x07,0x23,0x03,0x06,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x01,0x36,0x36,0x35,0x34,0x26,0x27,0x03,0x13,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x03,0x31,0xcf,0x1e,0x38,0x2b,0x1a,0x03,0x87,0x10,0x5e,0x4c,0x99,0xa5,0x53,0x88,0x60,0x35,0xfe,0xae,0x57,0x59,0x65,0x55,0x0a,0x27,0x11,0x1e,0x28, 0x18,0x17,0x29,0x1e,0x11,0x12,0x1e,0x28,0x17,0x16,0x29,0x1e,0x12,0x04,0x5a,0xce,0xaf,0x1a,0x33,0x32,0x32,0x19,0x7f,0x03,0x80,0x20,0x52,0xb0,0x60,0x32,0x5a,0x7f,0xfe,0x78,0x4e,0x8f,0x50,0x58,0x73,0x0d,0xfd,0xe8,0xfd,0x50,0x16,0x28,0x1e,0x12,0x11,0x1e,0x28,0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x29,0x00,0xff,0xff,0x00,0xac, 0xfe,0x1e,0x03,0x00,0x06,0x1e,0x00,0x26,0x00,0x5f,0x00,0x00,0x00,0x07,0x00,0x5f,0x01,0xc0,0x00,0x00,0x00,0x02,0x00,0x5e,0x00,0x78,0x05,0x1c,0x05,0x23,0x00,0x23,0x00,0x45,0x00,0x15,0xb7,0x24,0x14,0x32,0x05,0x41,0x19,0x2b,0x0d,0x00,0x2f,0x33,0x2f,0x33,0x01,0x2f,0x33,0x2f,0x33,0x31,0x30,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e, 0x04,0x07,0x23,0x2e,0x05,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x33,0x3e,0x03,0x01,0x14,0x1e,0x04,0x17,0x3e,0x05,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x2e,0x03,0x23,0x22,0x0e,0x02,0x03,0xea,0x3b,0x6f,0x55,0x33,0x40,0x68,0x83,0x86,0x7d,0x2d,0x09,0x2d,0x7c,0x86,0x83,0x68,0x40,0x33,0x55,0x6f,0x3b,0x39,0x5b, 0x49,0x37,0x14,0x09,0x14,0x38,0x49,0x5b,0xfd,0x2b,0x34,0x54,0x69,0x6c,0x63,0x23,0x23,0x62,0x6b,0x68,0x53,0x34,0x1c,0x30,0x42,0x26,0x3a,0x5b,0x49,0x39,0x16,0x17,0x38,0x49,0x5c,0x39,0x26,0x42,0x30,0x1c,0x05,0x23,0x2b,0x57,0x84,0x5a,0x64,0xad,0x98,0x85,0x79,0x6f,0x35,0x35,0x6f,0x79,0x85,0x98,0xad,0x64,0x5a,0x84,0x57,0x2b, 0x1e,0x33,0x41,0x22,0x22,0x41,0x33,0x1e,0xfe,0xa0,0x50,0x8e,0x7e,0x6f,0x63,0x57,0x26,0x26,0x57,0x63,0x6f,0x7e,0x8e,0x50,0x3d,0x58,0x38,0x1a,0x2e,0x4b,0x5e,0x2f,0x2f,0x5e,0x4b,0x2e,0x1a,0x38,0x58,0x00,0x00,0x02,0x00,0x30,0x00,0x00,0x03,0x43,0x05,0x9a,0x00,0x1b,0x00,0x1f,0x00,0x21,0x40,0x0e,0x1c,0x00,0x0f,0x12,0x1d,0x0b, 0x01,0x0e,0x1e,0x1c,0x03,0x11,0x03,0x03,0x00,0x3f,0x2f,0x12,0x39,0x39,0x01,0x2f,0x33,0xcd,0x33,0x2f,0xcd,0x32,0x32,0x31,0x30,0x01,0x25,0x11,0x33,0x15,0x37,0x15,0x07,0x11,0x37,0x15,0x07,0x11,0x23,0x35,0x05,0x11,0x23,0x35,0x07,0x35,0x37,0x11,0x07,0x35,0x37,0x11,0x33,0x11,0x25,0x11,0x05,0x01,0x37,0x01,0x05,0x67,0xa0,0xa0, 0xa0,0xa0,0x67,0xfe,0xfb,0x67,0xa0,0xa0,0xa0,0xa0,0x67,0x01,0x05,0xfe,0xfb,0x03,0xff,0x8b,0x01,0x10,0xd9,0x55,0x98,0x55,0xfe,0x42,0x55,0x98,0x55,0xfe,0xda,0xef,0x8b,0xfe,0xef,0xda,0x55,0x98,0x55,0x01,0xbe,0x55,0x98,0x55,0x01,0x0e,0xfc,0xd3,0x8b,0x01,0xbe,0x8b,0x00,0x09,0x00,0xe6,0xff,0xb8,0x07,0x19,0x05,0xe7,0x00,0x1e, 0x00,0x2c,0x00,0x3a,0x00,0x48,0x00,0x56,0x00,0x64,0x00,0x72,0x00,0x7f,0x00,0x8c,0x00,0x1e,0x40,0x13,0x30,0x49,0x23,0x36,0x57,0x41,0x86,0x50,0x79,0x6e,0x2b,0x5d,0x80,0x68,0x0e,0x3b,0x0f,0x73,0x00,0x00,0x2f,0x32,0x2f,0x33,0x17,0x39,0x31,0x30,0x05,0x22,0x27,0x2e,0x02,0x27,0x26,0x35,0x34,0x37,0x36,0x36,0x37,0x36,0x33,0x32, 0x17,0x16,0x16,0x17,0x16,0x15,0x14,0x06,0x07,0x0e,0x02,0x07,0x06,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x07,0x36,0x33,0x32,0x16,0x17,0x36,0x03,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x01,0x22,0x06,0x15,0x14,0x16,0x17,0x26,0x35,0x34,0x36,0x36,0x37,0x26,0x05,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32, 0x37,0x26,0x26,0x35,0x34,0x03,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x37,0x06,0x23,0x22,0x26,0x13,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x27,0x06,0x06,0x23,0x22,0x01,0x32,0x36,0x35,0x34,0x26,0x27,0x16,0x15,0x14,0x06,0x07,0x16,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x03,0xff,0xa4,0x76,0x69, 0xb5,0x6e,0x05,0x6e,0x6e,0x08,0xe8,0xa1,0x76,0xa4,0xa2,0x79,0xa0,0xe6,0x0a,0x6f,0x3a,0x34,0x07,0x6d,0xb6,0x69,0x77,0x02,0x11,0x54,0x96,0x56,0x63,0xa4,0x24,0x5a,0x64,0x87,0xde,0x2d,0x1b,0x84,0x23,0xa4,0x62,0x53,0x95,0x58,0x1c,0x2a,0xe1,0x86,0x66,0xfe,0x27,0x83,0xbd,0x6f,0x5e,0x2d,0x51,0x88,0x48,0x3e,0xfe,0x44,0x5b,0x71, 0x53,0x93,0x59,0x46,0x3b,0x81,0xa0,0xf1,0x1b,0x54,0x92,0x59,0x61,0xa7,0x22,0x5a,0x63,0x88,0xde,0x3c,0x24,0x9d,0x5c,0x5c,0x9b,0x56,0x1b,0x2c,0xdf,0x87,0x60,0x01,0xd3,0x82,0xbd,0x6b,0x60,0x2c,0x9d,0x86,0x40,0x01,0xbb,0x5a,0x74,0xb9,0x86,0x43,0x3e,0x7f,0xa0,0x48,0x6c,0x05,0x6c,0xb8,0x67,0x76,0xa5,0xa4,0x78,0xa0,0xe8,0x08, 0x6c,0x6d,0x08,0xe7,0x9f,0x7b,0xa4,0x4f,0x92,0x39,0x6a,0xb4,0x6c,0x06,0x6b,0x03,0x16,0x54,0x95,0x58,0x70,0x5d,0x2d,0x9f,0x84,0x40,0x01,0xbd,0x5c,0x6f,0x55,0x95,0x54,0x47,0x3c,0x82,0xa0,0x01,0x0c,0xbb,0x85,0x61,0xa5,0x24,0x58,0x67,0x60,0xa7,0x75,0x13,0x1c,0x81,0x23,0xa6,0x61,0x54,0x94,0x58,0x1b,0x2a,0xe1,0x85,0x66,0xfe, 0xaa,0x3c,0x46,0x53,0x95,0x57,0x6f,0x5d,0x2d,0xa1,0xfe,0x86,0x5b,0x71,0x56,0x94,0x55,0x45,0x3e,0x83,0xa0,0xfe,0xf5,0xbe,0x80,0x61,0xa2,0x28,0x58,0x66,0x87,0xda,0x2e,0x1c,0x80,0x23,0xa2,0x65,0x82,0xbf,0x1b,0x2b,0xdd,0x86,0x6f,0x00,0x00,0x09,0x00,0xe6,0xff,0xb8,0x07,0x19,0x05,0xe7,0x00,0x1e,0x00,0x2c,0x00,0x3a,0x00,0x48, 0x00,0x56,0x00,0x64,0x00,0x72,0x00,0x80,0x00,0x8e,0x00,0x21,0x40,0x15,0x38,0x49,0x2f,0x29,0x32,0x57,0x43,0x88,0x50,0x7a,0x21,0x6a,0x5f,0x81,0x70,0x0f,0x07,0x73,0x16,0x3b,0x07,0x00,0x2f,0x33,0x2f,0x33,0x12,0x17,0x39,0x31,0x30,0x13,0x34,0x37,0x36,0x36,0x37,0x36,0x33,0x32,0x17,0x1e,0x02,0x17,0x16,0x15,0x14,0x07,0x06,0x06, 0x07,0x06,0x23,0x22,0x27,0x2e,0x02,0x27,0x26,0x26,0x37,0x14,0x17,0x36,0x36,0x33,0x32,0x17,0x26,0x26,0x23,0x22,0x06,0x06,0x13,0x36,0x33,0x32,0x16,0x17,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x25,0x22,0x07,0x1e,0x02,0x15,0x14,0x07,0x36,0x36,0x35,0x34,0x26,0x17,0x16,0x15,0x14,0x06,0x07,0x16,0x33,0x32,0x36,0x36,0x35,0x34, 0x26,0x13,0x06,0x06,0x23,0x22,0x27,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x03,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x05,0x32,0x37,0x26,0x26,0x35,0x34,0x37,0x06,0x06,0x15,0x14,0x16,0x16,0x25,0x26,0x35,0x34,0x36,0x37,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0xe6,0x6f,0x08,0xe6,0xa2,0x79,0xa2, 0xa4,0x76,0x68,0xb6,0x6e,0x05,0x6e,0x6e,0x08,0xe6,0xa3,0x76,0xa4,0xa2,0x77,0x68,0xb6,0x70,0x05,0x34,0x3a,0x67,0x1b,0x2d,0xde,0x87,0x64,0x5a,0x23,0xa6,0x62,0x57,0x95,0x54,0x84,0x56,0x66,0x86,0xe1,0x2a,0x1c,0x57,0x94,0x55,0x62,0xa4,0x02,0x0c,0x43,0x3e,0x49,0x87,0x51,0x2d,0x5e,0x6f,0xbe,0xf7,0x2d,0xa0,0x81,0x3b,0x46,0x57, 0x94,0x54,0x71,0xc3,0x2b,0xde,0x88,0x63,0x5a,0x23,0xa6,0x61,0x5a,0x92,0x53,0x82,0x5d,0x60,0x88,0xdf,0x2b,0x1b,0x56,0x9a,0x5d,0x5b,0x9d,0xfd,0xf5,0x43,0x40,0x84,0x9f,0x2c,0x5f,0x6c,0x57,0x95,0xfe,0xdb,0x2d,0xa0,0x7f,0x3e,0x43,0x55,0x93,0x57,0x74,0x02,0xcd,0xa4,0x7b,0x9c,0xe9,0x09,0x6d,0x6c,0x05,0x6e,0xb5,0x68,0x78,0xa4, 0xa5,0x76,0xa0,0xe8,0x08,0x6c,0x6b,0x05,0x6c,0xb6,0x69,0x39,0x92,0x50,0x42,0x40,0x85,0x9e,0x2d,0x5c,0x71,0x58,0x95,0x01,0x27,0x2c,0xa0,0x82,0x3c,0x47,0x54,0x94,0x56,0x70,0xdd,0x1c,0x14,0x75,0xa6,0x60,0x67,0x58,0x24,0xa6,0x60,0x85,0xbb,0x81,0x59,0x66,0x85,0xe1,0x2a,0x1b,0x57,0x93,0x56,0x61,0xa6,0xfe,0x74,0x81,0xa1,0x2d, 0x5f,0x6d,0x58,0x96,0x51,0x46,0xfe,0x41,0x2d,0xa0,0x83,0x3e,0x45,0x55,0x94,0x56,0x70,0xdc,0x1c,0x2d,0xda,0x88,0x66,0x58,0x27,0xa3,0x61,0x54,0x94,0x56,0x80,0x53,0x6f,0x86,0xdd,0x2b,0x1b,0x55,0x97,0x55,0x64,0xa4,0xff,0xff,0x00,0x37,0xfe,0x70,0x01,0x4b,0x04,0x00,0x02,0x26,0x00,0xd6,0x00,0x00,0x01,0x06,0x00,0xdf,0xf9,0x00, 0x00,0x0b,0xb6,0x01,0x00,0x12,0x04,0x02,0x03,0x25,0x01,0x2b,0x35,0x00,0x00,0x02,0xfd,0x33,0x00,0x00,0x02,0xcd,0x05,0x9a,0x00,0x03,0x00,0x07,0x00,0x00,0x01,0x21,0x11,0x21,0x37,0x21,0x11,0x21,0xfd,0x33,0x05,0x9a,0xfa,0x66,0x7c,0x04,0xa2,0xfb,0x5e,0x05,0x9a,0xfa,0x66,0x7c,0x04,0xa2,0x00,0x04,0x00,0x00,0xfe,0xb9,0x07,0xd1, 0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x23,0x00,0x27,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x07,0x23,0x07,0x33,0x07,0x23,0x03,0x23,0x13,0x23,0x03,0x23,0x13,0x23,0x37,0x33,0x37,0x23,0x37,0x33,0x13,0x33,0x03,0x33,0x13,0x33,0x03,0x07,0x23,0x07,0x33,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfd,0xf6,0x19,0xd1, 0x32,0xe1,0x1a,0xdc,0x42,0x8d,0x41,0xc8,0x3f,0x8c,0x3f,0xd2,0x14,0xd4,0x31,0xde,0x17,0xde,0x3d,0x8d,0x3d,0xc9,0x3f,0x8a,0x3d,0xa2,0xc9,0x35,0xcb,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfd,0x0f,0x6e,0xf0,0x6b,0xfe,0xd9,0x01,0x27,0xfe,0xd9,0x01,0x27,0x6b,0xf0,0x6e,0x01,0x29,0xfe,0xd7,0x01,0x29,0xfe,0xd7,0x6e, 0xf0,0x00,0x00,0x03,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x16,0x00,0x1a,0x00,0x1e,0x00,0x00,0x01,0x11,0x23,0x11,0x06,0x06,0x07,0x06,0x06,0x07,0x35,0x36,0x36,0x37,0x36,0x36,0x37,0x36,0x36,0x37,0x36,0x36,0x37,0x01,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x04,0x62,0xae,0x16,0x31,0x1a,0x1c,0x3e,0x25,0x19,0x29,0x14,0x14, 0x28,0x14,0x13,0x27,0x13,0x15,0x29,0x15,0xfc,0x7a,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0x04,0xb2,0xfb,0xfd,0x03,0x3f,0x0f,0x1c,0x0b,0x0b,0x13,0x09,0x8b,0x07,0x0e,0x07,0x08,0x11,0x08,0x0a,0x14,0x0b,0x0b,0x1a,0x0b,0x01,0x41,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0x00,0x03,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03, 0x00,0x07,0x00,0x27,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x21,0x35,0x01,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x07,0x21,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfd,0x4a,0xfd,0x6f,0x01,0x3d,0x31,0x45,0x2c,0x13,0x10,0x28,0x42,0x32,0x49, 0x82,0x43,0x80,0xa9,0x45,0x73,0x53,0x2e,0x1f,0x3d,0x5b,0x3b,0xed,0x01,0xd6,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfa,0x20,0x84,0x01,0x23,0x2d,0x4a,0x46,0x4c,0x2f,0x15,0x38,0x33,0x23,0x3a,0x39,0x97,0x5c,0x2e,0x4e,0x65,0x37,0x3b,0x65,0x60,0x5f,0x34,0xd1,0x00,0x00,0x03,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89, 0x00,0x03,0x00,0x07,0x00,0x3e,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x94, 0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfa,0xd6,0x3a,0x95,0x48,0x21,0x4c,0x41,0x2b,0x29,0x49,0x63,0x3a,0x5d,0x58,0x34,0x57,0x3f,0x23,0x21,0x33,0x3c,0x1c,0x3b,0x82,0x35,0x36,0x81,0x49,0x3f,0x77,0x5c,0x37,0x73,0x64,0x31,0x5c,0x47,0x2a,0x3f,0x6c,0x8f,0x4f,0x50,0x92,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfa,0x4a, 0x9a,0x29,0x28,0x0e,0x25,0x40,0x31,0x31,0x45,0x2b,0x14,0x80,0x12,0x29,0x40,0x2e,0x2b,0x37,0x1f,0x0c,0x24,0x24,0x8e,0x1d,0x1d,0x1d,0x3c,0x5c,0x3f,0x64,0x80,0x17,0x05,0x26,0x3f,0x55,0x33,0x4a,0x70,0x4c,0x27,0x1b,0x00,0x04,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x12,0x00,0x15,0x00,0x00,0x13,0x11, 0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x23,0x11,0x23,0x11,0x21,0x35,0x01,0x33,0x11,0x33,0x21,0x11,0x01,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfd,0x83,0x88,0xae,0xfe,0x21,0x01,0xc4,0xc9,0x88,0xfe,0xca,0xfe,0xd7,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfb,0x2a,0xfe,0xfb,0x01,0x05,0x7f,0x02,0x79,0xfd,0x99,0x01, 0xac,0xfe,0x54,0x00,0x00,0x03,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x2c,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x11,0x21,0x15,0x21,0x11,0x3e,0x02,0x32,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x94,0x06, 0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfa,0xd7,0x7b,0x7e,0x36,0x5c,0x43,0x26,0x2d,0x4b,0x64,0x37,0x33,0x88,0x02,0x41,0xfe,0x6c,0x0e,0x0c,0x09,0x0a,0x0c,0x4f,0x92,0x6e,0x42,0x47,0x75,0x98,0x52,0xa5,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfa,0x3f,0x97,0x42,0x18,0x30,0x47,0x2f,0x30,0x43,0x2c,0x14,0x09,0x02,0x16,0x86, 0xfe,0xf8,0x01,0x01,0x01,0x21,0x48,0x73,0x52,0x56,0x7a,0x4f,0x25,0x00,0x00,0x04,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x2d,0x00,0x41,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x26,0x23,0x22,0x0e,0x02,0x15,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02, 0x35,0x34,0x3e,0x04,0x33,0x32,0x17,0x01,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfd,0x31,0x5a,0x61,0x56,0x77,0x4a,0x22,0x03,0x12,0x30,0x3d,0x48,0x29,0x47,0x75,0x54,0x2e,0x31,0x5a,0x82,0x51,0x66,0x8e,0x57,0x27,0x19,0x32,0x4d,0x68,0x84,0x51,0x76, 0x48,0xfe,0xe2,0x26,0x4a,0x3b,0x25,0x1b,0x36,0x4e,0x33,0x30,0x47,0x2f,0x18,0x21,0x36,0x45,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfd,0x7c,0x2c,0x46,0x70,0x90,0x49,0x1f,0x34,0x27,0x16,0x2f,0x53,0x72,0x42,0x4c,0x80,0x5c,0x33,0x50,0x81,0xa2,0x52,0x45,0x8c,0x82,0x71,0x55,0x30,0x20,0xfe,0x24,0x1c,0x34,0x4a,0x2e, 0x29,0x49,0x39,0x21,0x24,0x3a,0x49,0x26,0x34,0x4b,0x31,0x17,0x00,0x03,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x0e,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x01,0x23,0x01,0x21,0x35,0x21,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfd,0xae,0xfe,0x1a,0xad,0x01,0xb4,0xfd,0x9a,0x03,0x45, 0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfe,0x05,0xfc,0x23,0x03,0x78,0x8b,0x00,0x00,0x05,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x2b,0x00,0x3f,0x00,0x53,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x13,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x13,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfc,0x03,0x3b,0x70,0x56,0x34,0x5a,0x5e,0x34,0x53,0x3b,0x1f,0x3a, 0x62,0x7e,0x44,0x44,0x7e,0x62,0x3a,0x1f,0x3b,0x53,0x34,0x5e,0x5a,0x34,0x56,0x70,0x3b,0x1e,0x37,0x28,0x18,0x13,0x26,0x37,0x25,0x25,0x38,0x25,0x13,0x18,0x28,0x37,0x1e,0x28,0x44,0x32,0x1d,0x1a,0x30,0x46,0x2b,0x2c,0x45,0x30,0x1a,0x1d,0x32,0x44,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfe,0x2b,0x21,0x40,0x5e,0x3d, 0x50,0x86,0x23,0x17,0x3a,0x47,0x54,0x31,0x43,0x64,0x42,0x20,0x20,0x42,0x64,0x43,0x31,0x54,0x47,0x3a,0x17,0x23,0x86,0x50,0x3d,0x5e,0x40,0x21,0xfe,0x4a,0x0a,0x24,0x31,0x3c,0x21,0x13,0x2a,0x24,0x18,0x18,0x24,0x2a,0x13,0x21,0x3c,0x31,0x24,0xfe,0x11,0x19,0x2a,0x37,0x1e,0x24,0x39,0x30,0x2a,0x15,0x15,0x2a,0x30,0x39,0x24,0x1e, 0x37,0x2a,0x19,0x00,0x00,0x04,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x03,0x00,0x07,0x00,0x2d,0x00,0x41,0x00,0x00,0x13,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x01,0x16,0x33,0x32,0x3e,0x02,0x35,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x27,0x01,0x32,0x3e, 0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x94,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0xfa,0xdb,0x5a,0x61,0x55,0x78,0x4a,0x22,0x03,0x12,0x30,0x3d,0x48,0x29,0x47,0x75,0x54,0x2e,0x31,0x5a,0x82,0x51,0x66,0x8e,0x57,0x27,0x19,0x32,0x4d,0x68,0x84,0x51,0x76,0x48,0x01,0x1e,0x26,0x4a,0x3b,0x25,0x1b,0x36,0x4e, 0x33,0x30,0x47,0x2f,0x18,0x21,0x36,0x45,0x05,0xf3,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xfa,0xc2,0x2c,0x46,0x70,0x8f,0x4a,0x1f,0x34,0x27,0x16,0x2f,0x53,0x72,0x42,0x4c,0x80,0x5c,0x33,0x50,0x81,0xa2,0x52,0x45,0x8c,0x82,0x71,0x55,0x30,0x20,0x01,0xdc,0x1c,0x34,0x4a,0x2e,0x28,0x4a,0x39,0x21,0x24,0x3a,0x49,0x26,0x34,0x4b, 0x31,0x17,0x00,0x04,0x00,0x00,0xfe,0xb9,0x07,0xd1,0x06,0x89,0x00,0x10,0x00,0x1a,0x00,0x1e,0x00,0x22,0x00,0x00,0x25,0x22,0x26,0x27,0x26,0x35,0x34,0x36,0x37,0x36,0x33,0x20,0x11,0x14,0x06,0x07,0x06,0x03,0x22,0x11,0x14,0x16,0x33,0x32,0x11,0x34,0x26,0x01,0x11,0x21,0x11,0x13,0x21,0x11,0x21,0x03,0xd1,0x55,0x7f,0x30,0x5d,0x2f, 0x32,0x62,0xb5,0x01,0x5c,0x2f,0x32,0x63,0xa0,0xc1,0x5f,0x5e,0xb9,0x58,0xfc,0x57,0x06,0xa7,0x96,0xf8,0x2f,0x07,0xd1,0x9e,0x40,0x40,0x7f,0xf5,0x87,0xc8,0x46,0x89,0xfd,0xfa,0x80,0xc2,0x44,0x86,0x03,0x8e,0xfe,0x6d,0xbd,0xbc,0x01,0x7f,0xc9,0xc4,0x01,0xc7,0xf9,0x5c,0x06,0xa4,0xf8,0xc6,0x07,0xd0,0xff,0xff,0x00,0x90,0x01,0xfa, 0x02,0xb2,0x02,0x7b,0x02,0x06,0x00,0x10,0x00,0x00,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0x9b,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26, 0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23, 0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x1e,0x05,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x08, 0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20, 0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x01, 0xeb,0x13,0x1e,0x19,0x13,0x0c,0x07,0x7d,0x0e,0x1c,0x2b,0x1e,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d, 0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x05,0xc4,0x4e,0x8b,0x81,0x7f,0x88,0x94,0x57,0xfe,0xd1,0x01, 0x29,0x76,0xcc,0xc7,0xcf,0x7a,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0x9b,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34, 0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06, 0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x13,0x21,0x15,0x21,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x08,0xca,0x68, 0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e, 0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0xd5,0x02,0x84, 0xfe,0x1b,0x14,0x1e,0x14,0x0b,0x7d,0x0e,0x1c,0x2b,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13, 0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x05,0xc4,0x85,0x5b,0xa1,0xa7,0xb6,0x6e,0xfe,0xd1,0x01,0x29,0x76,0xcc, 0xc7,0xcf,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0xc4,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26, 0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06, 0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x13,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16, 0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x27,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0, 0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27, 0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0xd3,0x11,0x1d,0x0c,0x11,0x1e,0x0e,0x21,0x30,0x1e,0x0e,0x1d,0x7d,0x1d,0x19,0x18,0x29,0x13,0x21,0x2f,0x1f,0x0d,0x1c,0x7d,0x1d,0x1e,0x3c,0x56,0x38,0x24,0x52,0x30,0x39, 0x4f,0x21,0x23,0x09,0x0d,0x09,0x05,0x7d,0x0e,0x1c,0x2b,0x1e,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d, 0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x05,0xc4,0x49,0x80,0x3d,0x04,0x03,0x16,0x26,0x33,0x1d,0x43, 0x3e,0x47,0x45,0x41,0x33,0x07,0x06,0x16,0x26,0x33,0x1d,0x43,0x3e,0x47,0x45,0x31,0x56,0x3f,0x24,0x13,0x16,0x28,0x07,0x36,0x6d,0x74,0x7f,0x48,0xfe,0xd1,0x01,0x29,0x76,0xcc,0xc7,0xcf,0x7a,0x00,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b, 0x00,0xbd,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14, 0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27, 0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x0e,0x05,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0, 0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f, 0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x02,0x63,0x43,0x5f,0x40,0x24,0x14,0x05,0x22,0x39,0x46, 0x24,0x3c,0x61,0x2f,0x65,0x72,0x39,0x6f,0x59,0x38,0x16,0x35,0x59,0x43,0x40,0x56,0x32,0x15,0x23,0x57,0x92,0x6e,0x5c,0x6c,0x37,0x10,0x19,0x42,0x73,0x5b,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16, 0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20, 0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x03,0xbf,0x3f,0x65,0x53,0x40,0x2f,0x21,0x09,0x22,0x2a,0x18,0x08,0x10,0x0c,0x84,0x24,0x18,0x33,0x51,0x38,0x21,0x54,0x65,0x76,0x42,0x1e,0x36,0x37,0x3b,0x21,0x2b,0x5b,0x59,0x54,0x25,0x8d,0x1c,0x38,0x33,0x29,0x0c,0x14,0x20,0x2b,0x39,0x2d,0x00,0x00,0x0a,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16, 0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0xa1,0x00,0xb5,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17, 0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21, 0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x17,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34, 0x2e,0x02,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39, 0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20, 0x20,0x2f,0x01,0xe9,0x39,0x7c,0x66,0x43,0x31,0x5b,0x84,0x52,0x51,0x7c,0x55,0x2b,0x1f,0x34,0x45,0x4b,0x4c,0x20,0x20,0x49,0x3f,0x29,0x21,0x3a,0x4c,0x2b,0x3b,0x55,0x37,0x1a,0x2f,0x45,0x4e,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e, 0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20, 0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x05,0x24,0x44,0x84,0xc1,0x7d,0x4d,0x7f,0x5b,0x31,0x2d,0x51,0x73,0x48,0x54,0x92,0x7a,0x60,0x42,0x23,0x81,0x3c,0x6a,0x96,0x59,0x34,0x4a,0x2e,0x15,0x1b,0x32,0x46,0x2c,0x5f,0x98,0x68,0x38,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f, 0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0xa1,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14, 0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01, 0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x2e,0x07,0x27,0x27,0x21,0x35,0x21,0x17,0x1e,0x05,0x17,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68, 0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c, 0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x02,0xb1,0x13,0x1e,0x16,0x11,0x0b,0x09,0x06,0x04,0x03,0x02,0xfe,0x15,0x02,0x64,0x04,0x04,0x06,0x0a,0x10,0x1b,0x27,0x1b, 0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb, 0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x01,0x49,0x52,0x84,0x72,0x63,0x61,0x62,0x71,0x83,0x51,0x43,0x85,0x9e,0x70,0xac,0x93,0x84,0x91,0xab,0x6e,0x00,0x00,0x09, 0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0x9d,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33, 0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10, 0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x13,0x16,0x12,0x17,0x33,0x36,0x12,0x37,0x33,0x02,0x02,0x03,0x23,0x26,0x0a,0x02,0x27,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e, 0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05, 0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0xce,0x50,0x8c,0x3e,0x05,0x41,0x8a, 0x50,0x7e,0x66,0xad,0x4d,0x77,0x29,0x54,0x57,0x5c,0x31,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d, 0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x05,0xba,0xd9,0xfe,0x34,0xf8,0xf8,0x01,0xcc,0xd9,0xfe,0xe6,0xfd, 0xc7,0xfe,0xd8,0x9b,0x01,0x27,0x01,0x1d,0x01,0x14,0x88,0x00,0x00,0x09,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0x9d,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34, 0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27, 0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x26,0x02,0x27,0x23,0x06,0x02,0x07,0x23,0x36, 0x1a,0x02,0x37,0x33,0x12,0x12,0x13,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6, 0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27,0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e, 0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x03,0x06,0x51,0x8b,0x3e,0x05,0x41,0x8a,0x50,0x7f,0x34,0x5d,0x57,0x52,0x27,0x77,0x51,0xad,0x62,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e, 0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80,0x20,0x2e,0x2e,0x20,0x21, 0x2e,0x2f,0x01,0x49,0xda,0x01,0xcc,0xf7,0xf8,0xfe,0x34,0xd9,0x8e,0x01,0x1a,0x01,0x1e,0x01,0x21,0x94,0xfe,0xcb,0xfd,0xc9,0xfe,0xf1,0x00,0x0a,0x00,0x32,0xfe,0x7f,0x08,0xca,0x07,0x16,0x00,0x33,0x00,0x3f,0x00,0x44,0x00,0x50,0x00,0x6e,0x00,0x7a,0x00,0x7f,0x00,0x8b,0x00,0xaa,0x00,0xbf,0x00,0x00,0x01,0x14,0x07,0x06,0x07,0x16, 0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x21,0x20,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x27,0x26,0x35,0x34,0x37,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x21,0x20,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x26,0x23,0x22,0x07,0x07, 0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x34,0x27,0x26,0x27,0x06,0x23,0x22,0x27,0x21,0x06,0x23,0x22,0x27,0x06,0x07,0x06,0x15,0x10,0x01,0x36,0x33,0x32,0x17,0x21,0x36,0x33,0x32,0x17,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x27,0x21,0x16,0x33,0x32,0x25,0x34,0x26,0x23,0x22,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x23,0x2e,0x03,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03,0x03,0x2e,0x03,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x08,0xca,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0xfe,0xed,0xfe,0xef,0xf0,0x21,0x28, 0x37,0x4e,0x03,0xb3,0x64,0x68,0x68,0x64,0xb3,0x03,0x4e,0x37,0x28,0x21,0xf0,0x01,0x13,0x01,0x11,0xf0,0x21,0x28,0x37,0x4e,0x03,0xb3,0x64,0x68,0xfe,0x4e,0x2e,0x20,0x20,0x2f,0x2e,0x21,0x20,0x2e,0xd6,0xd4,0xef,0xf1,0xd4,0x39,0x2f,0x20,0x20,0x2e,0x2e,0x20,0x21,0x2e,0x05,0xdb,0x5c,0x58,0x9f,0x1d,0x23,0x38,0x27,0xfc,0x28,0x27, 0x38,0x23,0x1d,0x9f,0x58,0x5c,0x01,0x53,0x1d,0x23,0x38,0x27,0x03,0xd8,0x27,0x38,0x23,0x1d,0x01,0x53,0xfe,0xbc,0x2e,0x20,0x21,0x2e,0x2f,0x20,0x20,0x2e,0xd6,0xfc,0x78,0xd4,0xf1,0xef,0xfd,0x13,0x2e,0x21,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x03,0x51,0x80,0x20,0x2c,0x1c,0x11,0x07,0x64,0x60,0x40,0x71,0x54,0x32,0x29,0x4d,0x70,0x48, 0x46,0x71,0x30,0x1a,0x1e,0x12,0x09,0x05,0x06,0x10,0x1e,0x32,0xe3,0x03,0x06,0x08,0x0c,0x08,0x1c,0x58,0x38,0x23,0x3c,0x2c,0x19,0x20,0x38,0x4d,0x2e,0x26,0x53,0x02,0xcb,0xf6,0xdc,0xd6,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f,0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd6,0xdc,0xf6,0xf6,0xdc,0xd5,0x9a,0x0e,0x0f,0x37,0x4d,0x16,0x7f,0x7f, 0x16,0x4d,0x37,0x0f,0x0e,0x9a,0xd5,0xdc,0x02,0x67,0x21,0x2e,0x2f,0x20,0x20,0x2e,0x2e,0x33,0x6d,0x6d,0x13,0x20,0x2f,0x2e,0x21,0x20,0x2e,0x2e,0xfc,0xc2,0xdb,0xc6,0xbe,0x8b,0x10,0x29,0x29,0x10,0x8b,0xbe,0xc6,0xdb,0xfe,0x3f,0xfe,0xd8,0x10,0x29,0x29,0x10,0x01,0x28,0xfe,0x64,0x20,0x2e,0x2e,0x20,0x20,0x2f,0x2e,0x0e,0x6d,0x80, 0x20,0x2e,0x2e,0x20,0x21,0x2e,0x2f,0x01,0x49,0x4e,0x97,0x8d,0x83,0x39,0x2f,0x2a,0x4d,0x72,0x48,0x40,0x7b,0x60,0x3b,0x40,0x4c,0x28,0x50,0x57,0x62,0x3b,0x41,0x91,0xa2,0xb5,0x02,0x43,0x22,0x34,0x2d,0x28,0x15,0x46,0x4e,0x1e,0x34,0x46,0x27,0x2c,0x45,0x30,0x19,0x13,0x00,0x01,0x00,0x53,0x00,0x00,0x04,0x2d,0x05,0x9a,0x00,0x1d, 0x00,0x70,0x40,0x25,0x1b,0x00,0x1a,0x01,0x1a,0x03,0x18,0x02,0x0f,0x19,0x1f,0x19,0x02,0x19,0x40,0x0f,0x12,0x48,0x19,0x19,0x15,0x17,0x04,0x16,0x05,0x16,0x14,0x07,0x15,0x06,0x06,0x00,0x05,0x10,0x05,0x02,0x05,0xb8,0xff,0xc0,0x40,0x1a,0x0f,0x12,0x48,0x05,0x05,0x02,0x01,0x60,0x15,0x70,0x15,0x02,0x0d,0x15,0x01,0x01,0x15,0x0d, 0x03,0x13,0x1c,0x03,0x08,0x91,0x13,0x12,0x00,0x3f,0xed,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x11,0x33,0x33,0x2f,0x2b,0x5d,0x33,0x11,0x12,0x39,0x39,0x32,0x11,0x12,0x39,0x39,0x11,0x33,0x2f,0x2b,0x5d,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0x31,0x30,0x01,0x25,0x15,0x05,0x15,0x25,0x15,0x05,0x11,0x33,0x32,0x37,0x36,0x37, 0x33,0x06,0x07,0x06,0x23,0x23,0x11,0x07,0x35,0x37,0x35,0x07,0x35,0x37,0x11,0x33,0x01,0xea,0x01,0x58,0xfe,0xa8,0x01,0x58,0xfe,0xa8,0x23,0xa3,0x68,0x66,0x0b,0xa4,0x14,0x93,0x90,0xee,0xc6,0xef,0xef,0xef,0xef,0xa8,0x04,0x1d,0x89,0x99,0x89,0x83,0x89,0x99,0x88,0xfe,0x2e,0x69,0x69,0xb9,0xfe,0x92,0x92,0x02,0x26,0x5e,0x98,0x5f, 0x83,0x5f,0x98,0x5f,0x01,0xc0,0x00,0x02,0x00,0xbb,0x00,0xf7,0x03,0xf5,0x04,0x66,0x00,0x0b,0x00,0x1b,0x00,0x00,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x02,0x59,0x6e,0x8f,0x93,0x6a,0x6a,0x91,0x8d,0x6e,0x71,0xbe,0x6d,0x6f, 0xbf,0x6e,0x6e,0xbf,0x71,0x6e,0xbe,0x03,0xcc,0xa2,0x7a,0x77,0xa8,0xa7,0x78,0x78,0xa4,0x9a,0x73,0xcc,0x78,0x76,0xcd,0x75,0x76,0xcc,0x76,0x76,0xcd,0x74,0x00,0x01,0x01,0x01,0xfe,0xe6,0x03,0xae,0x05,0x9c,0x00,0x29,0x00,0x00,0x01,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x07, 0x27,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x01,0xe6,0xe5,0x50,0x94,0x55,0x5b,0x98,0x57,0x48,0x86,0x9c,0xf0,0xa4,0x56,0x87,0x1c,0x1c,0x2a,0x6e,0xb5,0x75,0x9d,0xad,0x4f,0x55,0x49,0x45,0x59,0x50,0x47,0x02,0xf7,0x8f,0xd7,0x5b,0x92,0x52,0x58,0xa4,0x68,0x5f,0xb8,0xc0, 0xa7,0xd2,0xd2,0x5e,0x6a,0x68,0x52,0x27,0x3b,0x23,0x2c,0x4b,0x75,0xa9,0x67,0x9d,0xd7,0xab,0x5b,0x63,0x6c,0x60,0x49,0x42,0x7d,0x2c,0x00,0x01,0x00,0xaf,0xfe,0xdb,0x04,0x00,0x05,0x9c,0x00,0x21,0x00,0x00,0x01,0x02,0x03,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16, 0x16,0x15,0x14,0x02,0x07,0x07,0x16,0x12,0x17,0x03,0x7b,0xee,0x9a,0x46,0x74,0x42,0x4a,0x3c,0x7c,0x50,0x85,0x8d,0xc3,0x9a,0x88,0x96,0x31,0xb1,0xa4,0x8f,0xea,0x83,0xca,0xb0,0x01,0x72,0x9e,0x66,0xfe,0xdb,0x01,0x56,0x01,0x6c,0x02,0x47,0x72,0x3b,0x3b,0x4a,0xd2,0x2a,0xb4,0x7d,0x9c,0xc8,0x49,0x94,0x4c,0x85,0xe9,0x86,0xa9,0xfe, 0xfa,0x3e,0x03,0xed,0xfe,0xf6,0x89,0x00,0x00,0x01,0x00,0xc2,0xfe,0xde,0x03,0xee,0x05,0x88,0x00,0x2f,0x00,0x00,0x01,0x26,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x32,0x16,0x16,0x15,0x14,0x07,0x15,0x16,0x16,0x15,0x14, 0x06,0x07,0x15,0x16,0x16,0x17,0x03,0x42,0x5a,0x71,0x4b,0x81,0x9d,0x4c,0x39,0x3a,0x83,0x3a,0x5f,0x61,0x95,0x88,0xfe,0xc3,0x7a,0x8c,0x86,0x82,0xfe,0xd2,0x01,0x29,0x89,0xc3,0x65,0x84,0x62,0x74,0x98,0x7c,0x27,0x93,0x33,0xfe,0xde,0x8b,0x93,0x51,0x05,0x6b,0x51,0x38,0x48,0x57,0x52,0x19,0x85,0x5f,0x7b,0x83,0x97,0x66,0x5c,0x5a, 0x5f,0x96,0x53,0x98,0x64,0x9d,0x61,0x06,0x2b,0xc0,0x70,0x84,0xcc,0x24,0x04,0x29,0xb9,0x4c,0x00,0x02,0x00,0x6a,0xff,0xf3,0x04,0x46,0x05,0x88,0x00,0x25,0x00,0x31,0x00,0x00,0x01,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16, 0x16,0x17,0x3e,0x02,0x35,0x27,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x04,0x3f,0x07,0x4d,0x8b,0xa5,0x7e,0x69,0x56,0x98,0x59,0x9c,0xc4,0x65,0x80,0xae,0x89,0x4d,0x0a,0xa6,0x0e,0x41,0x77,0x96,0x92,0x77,0x42,0x04,0xfd,0xfe,0x64,0x57,0x52,0x6e,0x55,0x67,0x68,0x57,0x05,0x88,0x25,0x2e,0x66,0xba,0xb3,0x99, 0x74,0xc1,0x63,0x5d,0x91,0x50,0xb3,0x8f,0x5f,0xb9,0x79,0x94,0xa5,0xae,0x61,0x41,0x39,0x3e,0x32,0x51,0x92,0x8e,0x80,0x84,0x9a,0xa4,0x5b,0x44,0xfb,0xa6,0x4b,0x5a,0x63,0x4c,0x42,0x8f,0x5c,0x63,0x92,0x00,0x00,0x01,0x00,0x64,0xfe,0xdb,0x04,0xef,0x05,0x88,0x00,0x25,0x00,0x00,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x12,0x12,0x17,0x07,0x26,0x02,0x27,0x35,0x06,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x37,0x01,0x5a,0x2e,0x24,0x8f,0x7f,0x35,0x66,0x24,0x42,0x48,0x3e,0x48,0x5f,0x3a,0x54,0xb1,0x64,0x80,0x62,0xc9,0x25,0x37,0x8c,0x3f,0x82,0xc8,0x6f,0x2b,0x23,0x05,0x88,0xb2,0xe2,0x63,0xc9, 0xd5,0x30,0x2c,0x60,0x6b,0x4b,0x5f,0x7b,0x5c,0x5f,0x5b,0xfe,0xf9,0xfe,0x91,0x85,0x5d,0x86,0x01,0xcd,0x90,0x01,0x2f,0x35,0x91,0x01,0x04,0x9c,0x6f,0x01,0x11,0x7c,0x00,0x01,0x00,0x39,0xfe,0xde,0x04,0x77,0x05,0x88,0x00,0x36,0x00,0x00,0x01,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x07,0x16,0x17,0x07,0x26,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x15,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x21,0x03,0x0a,0xed,0x73,0x7c,0x9d,0x7c,0x45,0x37,0x2a,0x3c,0x39,0x52,0x73,0x45,0x57,0x92,0x7d,0x3f,0x7c,0x2f,0x60,0x5a,0x80,0xd5,0x77,0x3c,0x4b, 0x63,0x75,0x3b,0x64,0xa9,0x85,0xe0,0xca,0x7e,0x7e,0x43,0x96,0x7d,0x01,0x1a,0x02,0xe0,0x75,0x6d,0x7e,0xa2,0x13,0x56,0x4a,0x3f,0x49,0x8f,0x5a,0x57,0x35,0xad,0xbd,0x5c,0x44,0xd4,0x6d,0x1c,0x75,0xce,0x7d,0x51,0x87,0x3c,0x06,0x26,0xa8,0x6f,0x4d,0x6c,0x47,0x2a,0x96,0x22,0x4a,0x3f,0x5e,0x72,0x00,0x00,0x01,0x00,0x2e,0xff,0xf8, 0x04,0x82,0x05,0x88,0x00,0x29,0x00,0x00,0x01,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x06,0x23,0x22,0x00,0x02,0x11,0x33,0x10,0x12,0x12,0x33,0x32,0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x37,0x03,0x8c,0x16,0x1d,0x78,0xaf,0x5e,0xa8,0x84,0x72,0xb0,0x60,0x7d,0xe2, 0x8f,0xcd,0xfe,0xea,0x83,0x9f,0x69,0xcd,0x93,0x95,0xb9,0x3e,0x6b,0x3e,0x3f,0x4c,0x43,0x75,0x46,0x1a,0x01,0xd4,0x05,0x62,0xae,0x67,0x89,0xb1,0x8b,0xfc,0x9c,0xb6,0xfe,0xe8,0x97,0x01,0x43,0x02,0x95,0x01,0xb8,0xfe,0x5a,0xfd,0xc3,0xfe,0xeb,0x01,0x05,0xce,0x6f,0xb1,0x64,0x59,0x4c,0x48,0x66,0x36,0x02,0x00,0x00,0x01,0x00,0x79, 0xff,0xa1,0x04,0x37,0x05,0x96,0x00,0x16,0x00,0x00,0x01,0x00,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x04,0x23,0x22,0x26,0x26,0x35,0x34,0x12,0x00,0x13,0x03,0x90,0xfd,0xef,0x52,0x19,0x95,0x73,0x6c,0xb9,0x6d,0x89,0x81,0xfe,0xfd,0x95,0x75,0xc1,0x6f,0x82,0x01,0x23,0xe9,0x05,0x39,0xfd,0x2c,0xc9,0x3c,0x3b,0x6c, 0x83,0x89,0xb4,0x57,0xc7,0xb4,0x64,0xb4,0x72,0x72,0x01,0x05,0x01,0xb2,0x01,0x42,0x00,0x01,0x00,0x81,0xfe,0xe6,0x04,0x2e,0x05,0x9c,0x00,0x27,0x00,0x00,0x01,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x17,0x1e,0x02,0x15,0x14,0x07,0x27,0x36,0x35,0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x16, 0x15,0x14,0x06,0x07,0x01,0xfc,0xc5,0x6f,0x59,0x60,0x77,0x38,0x86,0xcc,0xd0,0x7a,0x38,0x56,0x87,0x36,0x29,0x54,0xb4,0xec,0xa0,0x49,0xcf,0xa2,0x6b,0xaa,0x5f,0x99,0x90,0x03,0x32,0x54,0xa6,0x60,0x76,0x84,0x63,0x40,0x7e,0xa8,0xd8,0xdd,0x99,0x74,0x37,0x6b,0x6b,0x52,0x4e,0x34,0x22,0x4f,0x69,0xbf,0xfa,0xd2,0xb0,0x5a,0xa5,0xce, 0x61,0xad,0x67,0x82,0xc5,0x36,0x00,0x02,0x00,0xfd,0x00,0x93,0x05,0x06,0x04,0xc9,0x00,0x0e,0x00,0x1e,0x00,0x00,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x36,0x01,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x06,0x04,0x66,0x55,0x9d,0x66,0x6c,0xa8,0x5e,0xba,0x96,0x67, 0xaf,0x64,0xfe,0x79,0x8c,0xdd,0x79,0x8c,0xfa,0x96,0x8e,0xe2,0x7d,0x93,0xff,0x02,0xc0,0x64,0xa4,0x5d,0x66,0xb7,0x6c,0x9b,0xcb,0x68,0xb6,0xfe,0x3f,0x8a,0xf4,0x8e,0x98,0xff,0x93,0x87,0xed,0x90,0x99,0xfe,0xfb,0x94,0x00,0x01,0x01,0x70,0xff,0xe7,0x04,0x94,0x05,0xb1,0x00,0x25,0x00,0x00,0x01,0x16,0x16,0x17,0x16,0x16,0x15,0x14, 0x02,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x35,0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x02,0x3e,0x12,0x5d,0x74,0xc3,0xb0,0x76,0xb2,0x6a,0x5f,0x73,0xa2,0x73,0x35,0x40,0x3b,0x3f,0x75,0x8e,0x9d,0x6a,0x3c,0x59,0x3d,0x37,0x47,0x22,0x23,0x04,0xd3,0x20,0x56,0x59,0x98, 0xfe,0x81,0x7a,0xfe,0xfa,0x86,0x5a,0x4b,0x57,0x74,0x10,0x4d,0x54,0x3d,0x77,0x7c,0x74,0x7f,0x6e,0x6a,0x35,0x44,0x55,0x3f,0x36,0x25,0x2d,0x11,0x00,0x01,0x00,0xb9,0xff,0xa7,0x05,0x4a,0x05,0xb1,0x00,0x2d,0x00,0x00,0x01,0x14,0x06,0x07,0x15,0x16,0x04,0x17,0x07,0x26,0x24,0x24,0x27,0x37,0x16,0x17,0x16,0x33,0x32,0x36,0x36,0x35, 0x34,0x26,0x26,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x1e,0x05,0x04,0x88,0xcc,0xcf,0xc8,0x01,0x3c,0x59,0x68,0x4d,0xfe,0x8e,0xfe,0x5e,0xc8,0x10,0x31,0x85,0x3c,0x36,0x7e,0xf5,0x7c,0x41,0x75,0xa9,0x97,0x82,0x46,0x56,0x42,0x36,0x46,0x22,0x23,0x01,0x34,0x8a,0x94,0x8f,0x71,0x46,0x03,0x4b,0x7e, 0xc8,0x3f,0x06,0x4b,0xe2,0x83,0x69,0x71,0xfa,0x9c,0x12,0xa5,0x03,0x19,0x06,0x4b,0x74,0x49,0x36,0x48,0x31,0x24,0x20,0x3c,0x57,0x41,0x44,0x5b,0x42,0x2f,0x1d,0x38,0x12,0x06,0x07,0x14,0x24,0x37,0x52,0x72,0x00,0x01,0x00,0x7d,0x00,0x93,0x05,0x86,0x05,0x36,0x00,0x23,0x00,0x00,0x13,0x12,0x00,0x33,0x32,0x36,0x36,0x35,0x34,0x26, 0x27,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x22,0x24,0x02,0x03,0x37,0xf6,0x96,0x01,0x40,0xce,0x64,0x97,0x53,0x98,0x83,0x09,0x30,0x8d,0x5b,0x61,0x83,0xc7,0xa8,0x95,0xe1,0x79,0x7a,0xdf,0x8e,0xb4,0xfe,0xce,0xf2,0x4a,0x73,0x05,0x36,0xfd,0xd2,0xfe,0x25,0x6c,0xc0, 0x70,0x9e,0xe3,0x18,0x0e,0x3c,0x4a,0x5b,0x83,0x93,0x6a,0x80,0x9c,0x91,0xfe,0xfe,0x9f,0xa0,0xfe,0xf5,0x99,0xf7,0x01,0xf5,0x01,0x5e,0x59,0x00,0x00,0x03,0x00,0xff,0x00,0x4c,0x05,0x04,0x05,0xb1,0x00,0x1d,0x00,0x2b,0x00,0x38,0x00,0x00,0x01,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26, 0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x13,0x34,0x26,0x26,0x27,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x14,0x16,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0xf1,0x95,0x7e,0x8a,0xee,0x8f,0x8e,0xed,0x83,0x8f,0xa7,0x87,0x7a,0x7f,0xe0,0x80,0x82,0xd2,0x77,0x6e,0x7f,0x77,0x46,0x80,0x9b, 0x9d,0x84,0x47,0xd8,0xa0,0x94,0xbd,0xfd,0x6c,0x3f,0x76,0x9f,0x9c,0x7a,0xb7,0x89,0x84,0xa6,0x03,0x32,0x3f,0xa8,0x77,0x75,0xb3,0x60,0x62,0xb1,0x75,0x7e,0xaa,0x37,0x06,0x34,0x91,0x65,0x62,0x98,0x54,0x51,0x94,0x64,0x6b,0x92,0x33,0xfe,0x98,0x44,0x63,0x4a,0x31,0x28,0x44,0x61,0x47,0x71,0x91,0x85,0x03,0x0b,0x37,0x50,0x3d,0x2f, 0x2c,0x71,0x54,0x4c,0x62,0x5e,0x00,0x02,0x00,0x8c,0x00,0x01,0x05,0x78,0x05,0xb1,0x00,0x1f,0x00,0x32,0x00,0x00,0x01,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x15,0x07,0x0e,0x02,0x15,0x14,0x16,0x33,0x17,0x15,0x06,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x00,0x37,0x17,0x01,0x14,0x16,0x16,0x33,0x37,0x26,0x26,0x35,0x34,0x36, 0x37,0x26,0x26,0x35,0x35,0x37,0x06,0x02,0x03,0xb5,0x2f,0x84,0x5f,0x18,0x2e,0x34,0x95,0x70,0xcb,0x8f,0x48,0x7a,0x50,0x79,0xd2,0xd1,0xb0,0xfe,0xdb,0xa5,0xa5,0x01,0x2d,0xc2,0x95,0xfd,0x75,0x78,0xde,0x95,0x43,0x42,0x5a,0x83,0x97,0x70,0x82,0x02,0xd9,0xe3,0x05,0x5e,0x5c,0x47,0x5d,0x86,0x0d,0x1f,0x4b,0x06,0x49,0x7d,0x78,0x77, 0x40,0x4c,0x80,0x80,0x06,0x6b,0x95,0x01,0x01,0x95,0x91,0x01,0x4c,0x01,0x35,0x73,0x4d,0xfc,0xcc,0x76,0xb8,0x63,0x03,0x36,0xa2,0x4d,0x62,0xc2,0x6e,0x2a,0xaa,0x71,0x15,0x15,0xac,0xfe,0xac,0x00,0x00,0x01,0x00,0x1f,0xff,0xe5,0x05,0xe4,0x05,0xb1,0x00,0x2d,0x00,0x00,0x01,0x11,0x14,0x33,0x32,0x36,0x37,0x33,0x16,0x12,0x15,0x14, 0x02,0x06,0x23,0x20,0x00,0x03,0x37,0x33,0x12,0x21,0x32,0x36,0x36,0x35,0x34,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x03,0x4d,0x23,0x68,0xbd,0x68,0x0e,0x66,0x73,0x87,0xff,0xae,0xfe,0xae,0xfe,0x39,0x78,0x77,0x06,0xfa,0x02,0x1c,0x7a,0xb6,0x62,0x34,0x47,0xc2,0x66,0x74, 0x85,0x06,0x1a,0x1d,0x2a,0x46,0x58,0x41,0x56,0x63,0x04,0x89,0xfe,0xd2,0x73,0x93,0xa4,0x59,0xfe,0xf7,0x98,0xa6,0xfe,0xf9,0x93,0x02,0x35,0x02,0x51,0x64,0xfb,0xb5,0x6f,0xc6,0x7b,0x7a,0x6a,0x60,0x6e,0x8f,0x78,0x01,0x72,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x00,0x02,0x00,0xf5,0xff,0xe8,0x05,0x0e,0x05,0xb1,0x00,0x21,0x00,0x30, 0x00,0x00,0x01,0x06,0x23,0x22,0x24,0x27,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x03,0x15,0x11,0x17,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x01,0x32,0x37,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x06,0x15,0x17,0x16,0x03,0xbc,0x63,0x96,0x5c,0xfe,0xe1,0x1b,0x19,0x1f,0x62,0x9a,0xc7,0x73,0x1f,0x58,0x59, 0x3e,0x27,0x01,0x06,0x1a,0x1d,0x2a,0x46,0x58,0x41,0x57,0x62,0xfe,0xfb,0xa2,0x63,0x29,0x37,0x3a,0x11,0x61,0xae,0x65,0x07,0x8c,0x02,0x74,0x1d,0x2a,0x13,0x1c,0x5b,0x2a,0x65,0xfc,0xb7,0x64,0x35,0x62,0x84,0xb2,0x74,0xfd,0xb2,0x4c,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x8a,0x01,0xe2,0x27,0x57,0x75,0xa0,0x63,0x2c,0x87,0xe9,0x83, 0x0a,0x25,0x00,0x02,0x00,0x3a,0xff,0xe8,0x05,0xca,0x05,0xb1,0x00,0x31,0x00,0x41,0x00,0x00,0x13,0x27,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x36,0x35,0x34,0x27,0x35,0x37,0x33,0x16,0x15,0x14,0x06,0x23,0x22,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x03, 0x35,0x25,0x22,0x07,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x36,0x35,0x27,0x26,0x26,0xe8,0x01,0x06,0x1a,0x1d,0x2a,0x46,0x58,0x41,0x56,0x63,0x78,0xa1,0x90,0x80,0x26,0x52,0x54,0x58,0x4c,0x0b,0x82,0x06,0x28,0xad,0x90,0x30,0x1b,0x0e,0x62,0x99,0xc7,0x71,0x1f,0x58,0x59,0x3e,0x27,0x01,0xca,0x9b,0x8b,0x29,0x37,0x3a,0x11,0x61,0xab, 0x65,0x07,0x3b,0x6f,0x04,0x71,0x52,0x01,0x11,0x42,0x2f,0x38,0x55,0x9e,0x8a,0xfe,0xa4,0x36,0x3c,0x18,0x12,0x3a,0x3b,0x1d,0x1f,0x06,0x62,0x4f,0x52,0x81,0x9b,0x06,0x19,0x2a,0x64,0xff,0xb6,0x63,0x35,0x62,0x84,0xb2,0x74,0x97,0x40,0x57,0x75,0xa0,0x63,0x2c,0x85,0xeb,0x83,0x0a,0x20,0x1e,0x00,0x01,0x00,0xaf,0xff,0xe7,0x05,0x54, 0x05,0xb1,0x00,0x3c,0x00,0x00,0x01,0x22,0x06,0x06,0x15,0x14,0x17,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x20,0x13,0x36,0x36,0x35,0x34,0x26,0x26,0x27,0x24,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x14,0x16,0x17,0x04,0x16,0x16,0x15,0x14,0x06,0x06,0x23, 0x2e,0x02,0x02,0x3f,0x41,0x6f,0x42,0x0c,0x0b,0x0f,0x4e,0x2d,0x41,0x5d,0x5f,0x4b,0x4d,0x90,0x56,0x6d,0xb2,0x6d,0x01,0x6e,0x4c,0x56,0x6a,0x55,0xac,0xff,0xfe,0xe1,0xe2,0x4f,0x44,0x39,0x48,0x22,0x23,0x01,0x94,0xa2,0x01,0x37,0xeb,0x7a,0x87,0xd5,0x85,0x23,0x4e,0x72,0x02,0x1f,0x45,0x7a,0x41,0x28,0x25,0x02,0x2a,0x36,0x66,0x44, 0x47,0x58,0x57,0x95,0x59,0x6a,0xc4,0x63,0xfd,0xec,0x23,0xa6,0x5f,0x42,0x6e,0x61,0x5f,0x69,0xcd,0x8a,0x54,0x5c,0x3e,0x37,0x25,0x2d,0x11,0x06,0x3f,0x6c,0x39,0x6e,0x8c,0xaf,0x6d,0x81,0xf5,0x7c,0xe5,0xe2,0x71,0x00,0x00,0x02,0x00,0xb7,0x00,0xe6,0x04,0x0d,0x04,0x23,0x00,0x0b,0x00,0x17,0x00,0x00,0x01,0x14,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x0d,0xf8,0xb3,0xb3,0xf8,0xf0,0xbb,0xbb,0xf0,0xa0,0x93,0x78,0x77,0x94,0x97,0x74,0x73,0x98,0x02,0x83,0xae,0xef,0xef,0xae,0xbb,0xe5,0xe5,0xbb,0x71,0xab,0xad,0x6f,0x77,0xa5,0xa8,0x00,0x02,0x01,0x2a,0xff,0xba,0x03,0x99,0x05,0x1a, 0x00,0x15,0x00,0x1e,0x00,0x00,0x05,0x24,0x11,0x35,0x12,0x35,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x10,0x03,0x15,0x14,0x17,0x01,0x35,0x34,0x23,0x22,0x15,0x14,0x33,0x32,0x03,0x99,0xfe,0xeb,0x0a,0x25,0x25,0x7e,0x9c,0x9f,0x7c,0x7a,0x72,0x0a,0x72,0xfe,0xfa,0x4e,0x7b,0x78,0x21,0x46,0x24,0x01,0x11,0x0c,0x01, 0x1e,0xe4,0x08,0x9b,0x7d,0x74,0x99,0xb2,0xe0,0xfe,0xf0,0xfe,0x83,0x07,0x8e,0x0d,0x03,0x44,0x25,0xb8,0x6d,0x7c,0x00,0x01,0x00,0x7d,0xff,0xbe,0x04,0x46,0x04,0xee,0x00,0x20,0x00,0x00,0x25,0x07,0x26,0x27,0x26,0x27,0x06,0x23,0x22,0x35,0x34,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x36,0x33,0x32,0x00, 0x15,0x10,0x05,0x16,0x16,0x04,0x46,0x28,0x79,0x5b,0x19,0xa2,0x6c,0x6f,0xd9,0xe9,0x79,0x6b,0x6b,0x80,0xc3,0xa3,0xbc,0x8f,0x65,0x72,0xbe,0x80,0xe5,0x01,0x21,0xfe,0xf6,0x65,0x6d,0x58,0x9a,0x11,0x43,0x12,0x98,0x24,0x91,0x8e,0x45,0x38,0xc5,0x73,0xa4,0xc8,0x77,0x7c,0x57,0x44,0xfe,0xda,0xe6,0xfe,0xd1,0xad,0x63,0x3e,0x00,0x01, 0x00,0x8b,0xff,0x7b,0x04,0x39,0x05,0x04,0x00,0x2a,0x00,0x00,0x01,0x14,0x05,0x16,0x17,0x07,0x26,0x26,0x27,0x07,0x22,0x27,0x26,0x35,0x34,0x33,0x32,0x17,0x24,0x35,0x34,0x21,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x27,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x20,0x11,0x14,0x06,0x07,0x16,0x04,0x39,0xfe,0xdb,0x41,0x7d,0x29,0x72,0x96, 0x62,0x4c,0x8c,0x41,0x77,0xaa,0x6d,0xb3,0x01,0x20,0xfe,0xca,0xcd,0xeb,0x7c,0x94,0x82,0x49,0xa0,0xa8,0xbb,0x38,0xd6,0xc5,0x02,0x0b,0x57,0x3c,0x9b,0x01,0x8f,0xe9,0x41,0x2e,0x22,0x9a,0x1f,0x51,0x61,0x01,0x12,0x22,0x65,0x78,0x6e,0x14,0x8d,0xcb,0xa1,0x5a,0x53,0x7c,0x29,0x17,0x47,0x97,0x50,0xfe,0xa4,0x46,0x9b,0x24,0x77,0x00, 0x00,0x02,0x00,0xb4,0xff,0xba,0x04,0x10,0x05,0x1e,0x00,0x1c,0x00,0x29,0x00,0x00,0x01,0x02,0x01,0x1e,0x02,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x00,0x03,0x33,0x16,0x16,0x17,0x3e,0x02,0x37,0x03,0x34,0x27,0x26,0x27,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0x10,0x30,0xfe,0xef,0x81,0x3d,0x1f, 0x5c,0x9b,0x53,0x54,0x9a,0x5c,0x1f,0x3e,0x80,0xfe,0xeb,0x2c,0xaa,0x22,0x76,0x6f,0x57,0x55,0x3d,0x18,0x5a,0x38,0x11,0x5e,0x72,0x3b,0x67,0x43,0x43,0x67,0x05,0x1e,0xfe,0x81,0xfe,0xdc,0x95,0x64,0x63,0x30,0x51,0x8f,0x55,0x55,0x8f,0x51,0x30,0x63,0x65,0x94,0x01,0x28,0x01,0x7b,0xb6,0xfa,0x76,0x5a,0x8d,0xba,0x85,0xfb,0xd1,0x3b, 0x50,0x18,0x6c,0x84,0x50,0x3b,0x38,0x5e,0x5c,0x00,0x00,0x01,0x00,0x79,0xff,0xf6,0x04,0x4b,0x04,0xe1,0x00,0x1a,0x00,0x00,0x05,0x23,0x11,0x06,0x23,0x22,0x24,0x27,0x37,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x16,0x33,0x32,0x36,0x37,0x11,0x33,0x04,0x4b,0xa0,0x7b,0xe0,0xa7,0xfe,0xf9,0x29,0x4f,0x39,0x41,0x23, 0xaa,0x5a,0x65,0x1f,0x9f,0x56,0x57,0xd7,0x2d,0xa0,0x0a,0x01,0x53,0x2a,0x8e,0x7e,0x69,0x66,0x92,0x50,0xde,0x27,0xac,0xa9,0xcd,0x98,0x31,0x37,0x22,0x16,0x02,0xea,0x00,0x01,0x00,0x9d,0xff,0xf6,0x04,0x26,0x06,0x30,0x00,0x2d,0x00,0x00,0x25,0x06,0x23,0x22,0x24,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x37,0x26,0x35,0x34,0x36,0x33, 0x17,0x15,0x27,0x22,0x06,0x15,0x14,0x17,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x20,0x15,0x14,0x16,0x33,0x32,0x37,0x04,0x26,0xb9,0xc0,0xe9,0xfe,0xd9,0xa0,0x9c,0xde,0xc2,0x1c,0x98,0x7a,0x69,0x69,0x50,0x22,0x68,0x88,0x23,0x75,0x7a,0xc1,0xa2,0xba,0x84,0xec,0xcb,0xfe,0x9d,0xe0,0x91,0xa3,0xa5,0x39, 0x43,0xc4,0xaf,0xa5,0x5c,0x5d,0xb1,0x98,0xb4,0x10,0x32,0x45,0x6a,0x7b,0x04,0xa7,0x03,0x1c,0x21,0x47,0x27,0x23,0x9c,0x1a,0x5f,0x61,0x52,0x6d,0xaf,0xa1,0x61,0x72,0x3b,0x00,0x00,0x01,0x00,0xdf,0xff,0xf0,0x03,0xe4,0x05,0x25,0x00,0x17,0x00,0x00,0x01,0x14,0x00,0x05,0x27,0x36,0x00,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17, 0x07,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x03,0xe4,0xfe,0xba,0xff,0x00,0x70,0xe0,0x01,0x37,0x98,0x69,0x52,0x74,0x40,0x8c,0x53,0xc4,0xa1,0xb1,0xef,0x03,0x92,0xc2,0xfe,0x08,0xe8,0x71,0xcb,0x01,0xc9,0x9d,0x61,0x92,0x6b,0x46,0x52,0x6b,0x4e,0x75,0x96,0x8f,0xc2,0xe8,0x00,0x01,0x00,0x4b,0xff,0xf6,0x04,0x79,0x05,0x29,0x00,0x18, 0x00,0x00,0x25,0x06,0x23,0x22,0x00,0x11,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x21,0x15,0x21,0x16,0x15,0x10,0x12,0x33,0x32,0x37,0x04,0x79,0x9b,0xa6,0xfb,0xfe,0xcd,0x07,0xb8,0x83,0x40,0x5c,0x26,0x02,0xbd,0xfd,0x59,0x03,0xdd,0xb2,0x65,0x79,0x65,0x6f,0x01,0xd2,0x01,0x80,0x52,0x47,0x09,0x89,0x3f,0x77,0xa8,0x9f,0x2f, 0x6b,0xfe,0xc9,0xfe,0x85,0x4d,0x00,0x01,0x00,0x4b,0xff,0xf6,0x04,0x79,0x05,0xda,0x00,0x25,0x00,0x00,0x25,0x06,0x23,0x22,0x00,0x11,0x34,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x21,0x26,0x35,0x34,0x36,0x33,0x15,0x22,0x07,0x06,0x15,0x14,0x16,0x33,0x15,0x21,0x16,0x15,0x10,0x12,0x33,0x32,0x37,0x04,0x79,0x9b,0xa6,0xfb,0xfe, 0xcd,0x07,0xb8,0x83,0x40,0x5c,0x26,0x01,0xb5,0x11,0x8e,0xb1,0x44,0x17,0x45,0x46,0x34,0xfd,0x59,0x03,0xdd,0xb2,0x65,0x79,0x65,0x6f,0x01,0xd2,0x01,0x80,0x52,0x47,0x09,0x89,0x3f,0x77,0xa8,0x2c,0x37,0x7f,0x77,0xa0,0x06,0x11,0x3f,0x2c,0x37,0x9f,0x2f,0x6b,0xfe,0xc9,0xfe,0x85,0x4d,0x00,0x00,0x02,0x00,0xe1,0x01,0x13,0x04,0x33, 0x04,0xa4,0x00,0x0b,0x00,0x19,0x00,0x00,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x02,0x8b,0x73,0x99,0x9d,0x6f,0x70,0x9a,0x97,0x73,0x75,0xc3,0x70,0xed,0xbb,0x72,0xc6,0x72,0xe9,0x04,0x09,0xab,0x81,0x7f,0xb0,0xb0,0x7f,0x80,0xac,0x9b, 0x76,0xd3,0x7f,0xc8,0xfe,0xff,0x7a,0xd3,0x7c,0xce,0xfa,0x00,0x00,0x02,0x00,0xdc,0xff,0xe8,0x04,0x38,0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0x00,0x01,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x03,0x32,0x37,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0xbb, 0x02,0x50,0x4e,0x8c,0xb3,0xb2,0x87,0x92,0xb8,0x90,0x49,0x3f,0x83,0x35,0x42,0x44,0xa4,0x58,0x4c,0x55,0x49,0x47,0x5c,0x5b,0x03,0x39,0x02,0x15,0xb7,0x98,0x8c,0xb1,0xc9,0x9f,0xfc,0x38,0x67,0xac,0x28,0x2d,0x55,0x4b,0x03,0x3e,0x23,0x66,0x5e,0x6a,0x5e,0x49,0x4c,0x5e,0x00,0x01,0x00,0xa6,0xff,0xe8,0x04,0x6d,0x05,0xb2,0x00,0x26, 0x00,0x00,0x01,0x14,0x06,0x07,0x17,0x16,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x03,0xae,0xca,0xac,0x25,0x22,0x64,0x51,0x73,0x8c,0x3a,0x96,0x9f,0x90,0xb4,0x30,0x28,0x7d,0x79,0x68,0x47,0x94,0x38, 0x6e,0x81,0xbe,0x9f,0x62,0x33,0x1a,0x38,0x60,0xa7,0xed,0x7e,0x03,0xce,0xa3,0xf2,0x26,0x90,0x82,0x7e,0x47,0x9e,0x44,0xbc,0xc0,0xa3,0x05,0x4e,0x53,0x45,0x5d,0x9d,0x20,0x9c,0x6b,0x90,0xae,0x08,0x95,0x0e,0x7a,0xdb,0x00,0x01,0x00,0x68,0xff,0xe8,0x04,0xab,0x05,0xb2,0x00,0x2b,0x00,0x00,0x01,0x16,0x15,0x14,0x06,0x06,0x23,0x22, 0x24,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x07,0x03,0xd9,0xd2,0x7b,0xdd,0x89,0xb9,0xfe,0xd6,0x7f,0x7a,0x5e,0xf8,0x8d,0x97,0xb1,0x70,0x5e,0x36,0x40,0x58,0x4d,0x13,0x29,0x5d,0x6f,0x8e,0x96, 0x78,0x4d,0x3f,0x23,0x4d,0x57,0x88,0xc7,0x68,0x7f,0x02,0xf7,0x8d,0xe4,0x7d,0xbc,0x65,0xb6,0xc0,0x5f,0x94,0xa6,0x8e,0x7e,0x56,0x90,0x2f,0x10,0x0b,0x97,0x07,0x89,0x6a,0x6f,0x86,0x12,0x97,0x16,0x6a,0xbd,0x74,0xb0,0x6e,0x00,0x00,0x02,0x00,0x2d,0xff,0xe8,0x04,0xe7,0x05,0xbc,0x00,0x10,0x00,0x1b,0x00,0x00,0x13,0x01,0x01,0x17, 0x01,0x16,0x12,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x10,0x37,0x01,0x01,0x34,0x26,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x93,0x01,0xf5,0x01,0xed,0x72,0xfe,0x16,0x76,0x71,0xbd,0x9b,0x9f,0xbd,0xe6,0xfe,0x17,0x03,0x19,0x55,0x64,0xbf,0x67,0x50,0x54,0x6d,0x05,0xbc,0xfe,0x3a,0x01,0xc6,0x75,0xfe,0x3b,0x81,0xfe,0xff,0x92,0xae, 0xd8,0xe0,0xb0,0x01,0x1a,0xf6,0x01,0xbc,0xfc,0x35,0x5a,0xd5,0x6e,0xcb,0xd8,0x67,0x89,0x8a,0x00,0x01,0x00,0x0c,0xff,0xe8,0x05,0x07,0x05,0xb2,0x00,0x22,0x00,0x00,0x25,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x16,0x33,0x32, 0x37,0x11,0x33,0x04,0x2e,0x90,0x49,0x3f,0x83,0x35,0x42,0x44,0x6e,0x8b,0xda,0xe8,0x2c,0x2f,0x2d,0x1c,0x1f,0x28,0x41,0x76,0x88,0x8e,0x7c,0x97,0x76,0xa4,0x82,0x67,0xac,0x28,0x2d,0x55,0x4b,0xfb,0x35,0xed,0xdb,0x01,0xa2,0x29,0x36,0x05,0x96,0x0a,0x91,0x7f,0xfe,0x5e,0x87,0x90,0x66,0x03,0x4b,0x00,0x00,0x01,0x00,0x68,0xff,0xe8, 0x04,0xac,0x05,0xbb,0x00,0x36,0x00,0x00,0x01,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x2e,0x02,0x35,0x34,0x37,0x35,0x24,0x35,0x10,0x21,0x32,0x36,0x35,0x34,0x27,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x03,0x57, 0xb9,0x5f,0x66,0x81,0xb5,0xdb,0xc2,0xa2,0x89,0x86,0x60,0x2f,0x57,0x5b,0x3f,0x53,0xfa,0xb6,0xc1,0x62,0x44,0xfe,0xe9,0x01,0x9a,0x43,0x56,0x06,0x9d,0x04,0xac,0x82,0x87,0x7b,0x89,0x6c,0x2b,0x2d,0xed,0x03,0x1a,0x1c,0x0e,0x59,0x48,0x3d,0x3d,0x05,0x07,0x79,0x75,0x6d,0x86,0x28,0x8b,0x1b,0x38,0x27,0x50,0x06,0x05,0x3d,0x7b,0x62, 0x66,0x4a,0x02,0x45,0xdb,0x01,0x25,0x25,0x22,0x17,0x12,0x33,0x12,0x1e,0x49,0x5f,0x47,0x47,0x43,0x50,0x03,0x23,0x00,0x02,0x00,0x4d,0xff,0xe8,0x04,0xc6,0x05,0xb2,0x00,0x1d,0x00,0x29,0x00,0x00,0x13,0x12,0x12,0x33,0x32,0x36,0x12,0x35,0x34,0x27,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x06, 0x23,0x22,0x00,0x03,0x25,0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xe8,0x2c,0xcf,0xb5,0x76,0xb8,0x62,0x04,0x02,0x7d,0x9b,0xa1,0xc9,0xc0,0xa2,0x89,0xce,0x6d,0x89,0xfd,0xa2,0xf8,0xfe,0xde,0x37,0x02,0xb4,0x42,0x89,0x3d,0x21,0x83,0x52,0x5e,0x77,0x6d,0x03,0x23,0xfe,0x94,0xfe,0xcc,0x92,0x01,0x00,0x97,0x3d,0x3a, 0x6a,0xdb,0xb0,0xa5,0xc9,0xbf,0xfe,0x9b,0xed,0xc9,0xfe,0xc0,0xb0,0x01,0x70,0x01,0xa2,0x5a,0x47,0x44,0x91,0xa7,0x73,0x5f,0x6c,0x85,0x00,0x01,0x00,0xab,0xff,0xe8,0x04,0x69,0x05,0xbc,0x00,0x14,0x00,0x00,0x01,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x13,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x37,0x01,0x03,0xa7,0xfe, 0x6e,0x6f,0x5e,0x90,0x74,0xe9,0xab,0x89,0x7c,0xfd,0xa0,0xbb,0xea,0x6c,0x71,0x01,0x96,0x05,0x5f,0xfd,0xdf,0x97,0xd8,0x5a,0x6a,0x88,0x01,0x3b,0x57,0xd3,0xac,0xe3,0xaf,0x7c,0x01,0x07,0x98,0x02,0x27,0x00,0x00,0x02,0x00,0x7d,0xff,0xe8,0x04,0x96,0x05,0xb5,0x00,0x03,0x00,0x18,0x00,0x00,0x01,0x01,0x17,0x01,0x25,0x14,0x16,0x16, 0x33,0x32,0x36,0x37,0x17,0x06,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x37,0x17,0x06,0x02,0x02,0x1d,0x01,0xb1,0x71,0xfe,0x52,0xfe,0x8a,0x72,0xc8,0x78,0x61,0xa7,0x51,0x70,0xce,0xf5,0xae,0xfe,0xef,0x97,0xdc,0xca,0x70,0xad,0xcb,0x02,0x68,0x01,0x8c,0x73,0xfe,0x75,0x9a,0x99,0xf0,0x84,0x49,0x43,0x73,0xb4,0xab,0x01,0x3c,0xcc,0xe6, 0x01,0x97,0x9d,0x75,0x84,0xfe,0x90,0x00,0x00,0x02,0x00,0xad,0x00,0xd7,0x04,0x7a,0x04,0x89,0x00,0x0f,0x00,0x1c,0x00,0x00,0x13,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x36,0xad,0x81,0xe3,0x83,0x81,0xe3,0x82,0x84,0xe2,0x80,0x81, 0xe3,0x83,0x03,0x26,0xb9,0x86,0x84,0xbc,0xbb,0x85,0x55,0x94,0x56,0x02,0xb0,0x7d,0xda,0x82,0x80,0xdc,0x7d,0x7e,0xdc,0x7f,0x80,0xdc,0x7d,0x84,0xbc,0xbc,0x84,0x82,0xbd,0x54,0x96,0x00,0x00,0x02,0x01,0x15,0xff,0xe2,0x04,0x12,0x05,0x7d,0x00,0x15,0x00,0x21,0x00,0x00,0x01,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06, 0x23,0x22,0x27,0x1e,0x02,0x17,0x07,0x24,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x15,0x69,0xb2,0x67,0x65,0xb1,0x65,0x64,0xb2,0x65,0x68,0x47,0x1b,0x8c,0xe0,0x84,0x56,0xfe,0xcc,0xfe,0xac,0x02,0x58,0x7d,0x59,0x55,0x7f,0x7e,0x56,0x59,0x7d,0x03,0xe5,0x6c,0xbe,0x6e,0x69,0xb1,0x62,0x64,0xae,0x68, 0x33,0x72,0xe3,0xc1,0x3c,0x86,0x92,0x02,0x27,0x01,0x66,0x5c,0x84,0x8b,0x63,0x58,0x7c,0x87,0x00,0x02,0x01,0x15,0xff,0xe2,0x04,0x12,0x05,0x7d,0x00,0x17,0x00,0x23,0x00,0x00,0x01,0x10,0x00,0x05,0x27,0x36,0x36,0x37,0x15,0x36,0x37,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x05,0x14,0x16,0x33,0x32,0x36, 0x35,0x34,0x26,0x23,0x22,0x06,0x04,0x12,0xfe,0xaa,0xfe,0xcf,0x55,0x68,0xbc,0x44,0x74,0x2e,0x49,0x67,0x65,0xb1,0x65,0x67,0xb0,0x64,0x66,0xb3,0x69,0xfd,0xaa,0x7d,0x57,0x57,0x7d,0x7d,0x57,0x58,0x7c,0x03,0xe5,0xfe,0xb7,0xfd,0xd7,0x91,0x86,0x31,0x90,0x4f,0x01,0x91,0xb2,0x33,0x67,0xaf,0x64,0x64,0xb1,0x67,0x6e,0xbe,0x50,0x5d, 0x85,0x7d,0x57,0x62,0x8c,0x83,0x00,0x01,0x00,0x2f,0x00,0x00,0x04,0xf9,0x05,0x7d,0x00,0x33,0x00,0x00,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x02,0x5c,0x31,0x4f,0x27,0x5c,0x82,0x4c,0x36,0x17,0x1c,0x2e,0x27,0x33,0x52,0x77,0x80,0x5a,0x50,0x8b,0x4f,0x61,0xb4,0x74,0x4f,0x86,0x1d,0x2a,0x7f,0x4e,0xa1,0xb7,0xa4,0x69,0x46,0x4a,0x5c,0xa4,0x03,0xe7,0x3f,0x76,0x45,0xc8,0x91,0x6d,0x9d,0x26,0x19,0x16,0x2e,0x11,0x8d,0x04,0x87,0x57, 0x5f,0x88,0x77,0xc7,0x74,0x8f,0xe5,0x81,0x53,0x40,0x48,0x4b,0xc0,0xa2,0xfb,0xe5,0x04,0x1b,0x4f,0x77,0x8d,0x6d,0xfc,0x19,0x00,0x02,0x00,0x40,0xff,0xe5,0x04,0xe7,0x05,0xa9,0x00,0x17,0x00,0x23,0x00,0x00,0x01,0x34,0x36,0x37,0x26,0x03,0x37,0x12,0x05,0x36,0x13,0x17,0x02,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26, 0x25,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x03,0x95,0x84,0xee,0xee,0xa6,0xa6,0x01,0x1e,0xc3,0xe1,0x99,0xd6,0xde,0x85,0x93,0x72,0xc3,0x6f,0x6f,0xc1,0x74,0x02,0xa0,0x8c,0x70,0x73,0x8a,0x94,0x69,0x67,0x95,0x01,0x60,0x87,0xfa,0x57,0x94,0x01,0x9b,0x42,0xfe,0xa2,0xb0,0x6d,0x01,0x87,0x43,0xfe,0x8d,0xa2, 0x64,0xf1,0x74,0x6e,0xb5,0x66,0x65,0xb1,0x72,0x5f,0xc7,0x3f,0x38,0xcf,0x6b,0x5c,0x84,0x8b,0x00,0x03,0x00,0x34,0xff,0xe5,0x04,0xf3,0x05,0x7d,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x00,0x13,0x34,0x36,0x37,0x26,0x03,0x37,0x16,0x17,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x27, 0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x25,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x13,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0xdb,0x7d,0x6e,0xc8,0xca,0x86,0x80,0x8c,0x49,0x63,0xaa,0x61,0x5c,0xa4,0x60,0x89,0x5f,0x73,0xba,0x63,0x88,0x60,0x82,0x48,0x66,0xb0,0x64,0x65,0xb0,0x67,0x02, 0x50,0x50,0x43,0x7d,0x97,0x7c,0x57,0x56,0x7e,0x79,0x6d,0x4c,0x52,0x74,0x4f,0x45,0x6a,0x81,0x01,0x47,0x57,0xb0,0x47,0x59,0x01,0x24,0x65,0xe0,0x56,0x62,0x78,0x5d,0xa5,0x60,0x64,0xab,0x60,0x5d,0xb5,0x3b,0x2b,0xa3,0x89,0x65,0xaa,0x5c,0x7e,0x62,0x55,0x98,0x59,0x60,0xa4,0x42,0x54,0x9f,0x32,0x29,0x95,0x4b,0x53,0x74,0x62,0x03, 0x2c,0x56,0x7d,0x74,0x52,0x3f,0x8a,0x3d,0x38,0x89,0x00,0x01,0x00,0x55,0x00,0x00,0x04,0xd3,0x05,0x7d,0x00,0x2f,0x00,0x00,0x33,0x35,0x33,0x20,0x00,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x26,0x26,0x35,0x34,0x36,0x36, 0x33,0x32,0x16,0x16,0x15,0x10,0x00,0x21,0x55,0xcc,0x01,0x42,0x01,0xc7,0x56,0x94,0x56,0x57,0x7e,0x37,0x2e,0x43,0x4b,0xc1,0x86,0x61,0xc1,0x42,0x86,0x36,0x75,0x33,0x44,0x5c,0x76,0x3a,0x42,0x66,0xaf,0x66,0x81,0xe4,0x84,0xfd,0xd4,0xfe,0x7a,0xa7,0x01,0x9f,0x01,0x27,0x63,0xad,0x64,0x54,0x3c,0x17,0x39,0x1a,0x26,0x6b,0x3a,0x77, 0xa7,0x77,0x76,0x55,0x50,0x57,0x46,0x2f,0x3e,0x3d,0x1f,0x6e,0x3d,0x4f,0x8b,0x50,0x90,0xf5,0x8b,0xfe,0x94,0xfd,0xff,0x00,0x00,0x02,0x00,0x4f,0xff,0xe5,0x04,0xd8,0x05,0x7d,0x00,0x27,0x00,0x33,0x00,0x00,0x17,0x35,0x33,0x20,0x00,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x10,0x00,0x21,0x13,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x4f,0x95,0x01,0x5e,0x01,0xef,0x73,0xcc,0x72,0x69,0xb8,0x6b,0x09,0x27,0x7d,0x4a,0x77,0xa0,0xa0,0x70,0x6e,0xc4,0x71,0x99,0x01,0x06,0x92,0x9f,0x01,0x17,0xa2,0xfd,0xab,0xfe,0x61,0x79, 0x11,0x53,0x31,0x2e,0x3b,0x46,0x2a,0x30,0x50,0x1b,0x9c,0x01,0xad,0x01,0x32,0x66,0xb3,0x68,0x5e,0xa2,0x5e,0x18,0x26,0x43,0x54,0x9a,0x69,0x6b,0x98,0x75,0xc9,0x6f,0x86,0xec,0x88,0x92,0xfd,0x8e,0xfe,0x8b,0xfd,0xfa,0x02,0xcb,0x1b,0x24,0x40,0x28,0x26,0x36,0x4c,0x00,0x00,0x01,0x00,0xc1,0x00,0x00,0x04,0x67,0x05,0x42,0x00,0x05, 0x00,0x00,0x13,0x21,0x15,0x21,0x11,0x23,0xc1,0x03,0xa6,0xfd,0x02,0xa8,0x05,0x42,0x99,0xfb,0x57,0x00,0x00,0x01,0x00,0xdc,0xff,0xe2,0x04,0x4c,0x05,0x62,0x00,0x16,0x00,0x00,0x13,0x34,0x12,0x37,0x33,0x01,0x11,0x33,0x11,0x14,0x06,0x23,0x01,0x06,0x06,0x15,0x14,0x00,0x17,0x07,0x26,0x24,0x02,0xdc,0xb1,0x9b,0x1b,0x01,0x62,0xa7, 0x1e,0x13,0xfe,0x14,0x56,0x54,0x01,0x19,0xec,0x43,0xac,0xfe,0xe0,0x9f,0x02,0xe5,0xac,0x01,0x58,0x79,0xfe,0x8f,0x01,0x71,0xfd,0x5b,0x0b,0x13,0x01,0xf5,0x51,0xde,0x80,0xcd,0xfe,0xb1,0x51,0x96,0x3b,0xf3,0x01,0x35,0x00,0x02,0x01,0xbd,0xff,0xe8,0x05,0x87,0x05,0x48,0x00,0x0b,0x00,0x17,0x00,0x00,0x01,0x10,0x02,0x23,0x22,0x02, 0x11,0x10,0x12,0x33,0x32,0x12,0x03,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x05,0x87,0xfb,0xeb,0xea,0xfa,0xfa,0xea,0xeb,0xfb,0xab,0x9a,0xa1,0xa1,0x98,0x97,0xa2,0xa2,0x99,0x02,0x97,0xfe,0xa8,0xfe,0xa9,0x01,0x57,0x01,0x58,0x01,0x59,0x01,0x58,0xfe,0xa8,0xfe,0xa7,0x01,0x17,0x01,0x06,0xfe,0xf7,0xfe,0xec,0xfe, 0xeb,0xfe,0xfc,0x01,0x02,0x00,0x00,0x03,0x01,0x00,0x00,0x00,0x06,0x44,0x05,0x31,0x00,0x1d,0x00,0x21,0x00,0x2d,0x00,0x00,0x01,0x14,0x06,0x07,0x35,0x32,0x36,0x35,0x10,0x21,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x21,0x15,0x21,0x11,0x33,0x32,0x16,0x16,0x01,0x11,0x21,0x11,0x05,0x21,0x22,0x06,0x15,0x14, 0x16,0x16,0x33,0x32,0x36,0x35,0x06,0x44,0xdd,0xae,0x68,0x78,0xfe,0xc6,0xd0,0xd0,0x6e,0xce,0x83,0x8d,0x7d,0x03,0x58,0xfe,0xfd,0x39,0x72,0xc5,0x75,0xfd,0x73,0xfe,0xfb,0x01,0x05,0xfe,0xc8,0x61,0x6f,0x56,0x85,0x3b,0x79,0x79,0x01,0xc0,0xc9,0xf5,0x02,0x95,0x92,0x89,0x01,0x04,0xd5,0xff,0xe0,0x88,0xe7,0x71,0x86,0xb7,0x13,0x02, 0x01,0x94,0xfe,0xab,0x65,0xb8,0x01,0x1d,0x01,0x55,0xfe,0xab,0x94,0x72,0x62,0x49,0x9c,0x66,0xad,0xbe,0x00,0x02,0x00,0xd2,0x00,0x00,0x06,0x72,0x05,0x31,0x00,0x2e,0x00,0x3a,0x00,0x00,0x21,0x21,0x22,0x26,0x35,0x34,0x3e,0x06,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33, 0x32,0x04,0x15,0x14,0x06,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x06,0x72,0xfb,0xe3,0xc7,0xa3,0x45,0x70,0x90,0x96,0x90,0x70,0x45,0xb7,0x9b,0x4d,0x6f,0x33,0x84,0x7d,0x98,0x6d,0x69,0x8b,0x89,0xda,0x88,0xe2,0x01,0x16,0x83,0xf2,0xad,0x8d,0x70,0x56,0x82,0x04, 0x04,0xfb,0xcf,0x46,0x2d,0x2f,0x44,0x43,0x30,0x2f,0x44,0x60,0x6e,0x4a,0x61,0x42,0x2e,0x2d,0x36,0x52,0x7a,0x5a,0x90,0xa5,0x30,0x2f,0x04,0x80,0x7c,0x61,0x8a,0x97,0x6a,0x7d,0xe0,0x76,0xf2,0xc9,0x8a,0xd0,0x79,0x2e,0x25,0x3f,0x2c,0x2e,0x23,0x02,0xbf,0x31,0x47,0x48,0x30,0x33,0x45,0x45,0x00,0x01,0x00,0xff,0x00,0x00,0x06,0x44, 0x05,0x31,0x00,0x20,0x00,0x00,0x21,0x21,0x35,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x15,0x23,0x11,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x21,0x06,0x44,0xfd,0xf0,0x61,0x84,0x7b,0x6b,0x47,0x54,0x3d,0xa8,0xfe,0xf4,0xa8,0x02,0xce,0x72,0x3e,0x64,0x45,0xa8,0xd7,0x45,0x38, 0x01,0x00,0x95,0x0d,0xbe,0x7a,0x81,0x9b,0x1e,0x32,0xfd,0x5a,0x04,0x9d,0xfb,0x63,0x05,0x31,0x94,0xfe,0xb5,0x20,0x19,0xe8,0xaf,0x5e,0xbf,0x43,0x00,0x03,0x00,0xf8,0x00,0x00,0x06,0x4b,0x05,0x31,0x00,0x14,0x00,0x18,0x00,0x24,0x00,0x00,0x01,0x21,0x15,0x10,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x21,0x15,0x23,0x11, 0x21,0x11,0x33,0x01,0x11,0x21,0x11,0x05,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x06,0x4b,0xfe,0x20,0xe0,0xda,0x7f,0xc8,0x72,0x92,0x7e,0x02,0xd0,0x6d,0x01,0x38,0xa8,0xfd,0x78,0xfe,0xed,0x01,0x13,0xa9,0x95,0x9b,0x46,0x9c,0x86,0x79,0x84,0x02,0xb4,0x90,0xfe,0xf4,0xfe,0xe8,0x70,0xd5,0x92,0x81,0xb4,0x1f,0x02, 0x06,0x94,0xfe,0xab,0x01,0xe9,0xfe,0x17,0x01,0x55,0xfe,0xab,0x94,0x28,0x5d,0x5c,0x93,0xab,0xe8,0xcc,0x00,0x01,0x00,0x5c,0xfd,0xb9,0x06,0xe8,0x07,0x21,0x00,0x34,0x00,0x00,0x01,0x02,0x02,0x24,0x23,0x22,0x04,0x02,0x11,0x10,0x12,0x04,0x33,0x20,0x00,0x11,0x34,0x26,0x23,0x22,0x07,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x21,0x15, 0x23,0x11,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x04,0x23,0x20,0x00,0x02,0x11,0x10,0x12,0x00,0x21,0x32,0x04,0x12,0x13,0x06,0x46,0x07,0xa4,0xfe,0xde,0xba,0xd3,0xfe,0xc7,0xad,0x9d,0x01,0x1e,0xc8,0x01,0x0b,0x01,0x2e,0x5d,0x4f,0x70,0x37,0xa8,0xee,0xa8,0x02,0xb0,0x72,0x53,0x55,0xa1,0xae,0xb5,0xfe,0xb2,0xd6,0xfe,0xff,0xfe,0x93, 0xc3,0xd3,0x01,0x8c,0x01,0x10,0xe3,0x01,0x63,0xcb,0x0c,0x03,0x1d,0x01,0x03,0x01,0x91,0xdc,0xf7,0xfe,0x22,0xfe,0xbc,0xfe,0xb2,0xfe,0x1c,0xf5,0x01,0x6b,0x01,0x4f,0x72,0x8c,0x51,0xfe,0x4c,0x04,0x9d,0xfb,0x63,0x05,0x31,0x94,0xfd,0xaa,0x51,0xe9,0xdd,0xed,0xfe,0x96,0xc2,0x01,0x18,0x02,0x22,0x01,0x81,0x01,0x71,0x02,0x22,0x01, 0x1a,0xfe,0xfe,0x2c,0xfe,0xce,0x00,0x03,0x00,0x27,0x00,0x00,0x07,0x1c,0x05,0x31,0x00,0x2e,0x00,0x3a,0x00,0x3e,0x00,0x00,0x01,0x15,0x23,0x11,0x16,0x16,0x17,0x3e,0x02,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x33,0x15,0x21,0x35,0x36,0x36,0x35,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x27,0x15,0x10,0x02,0x23,0x22,0x26, 0x26,0x35,0x34,0x36,0x37,0x11,0x01,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x11,0x21,0x11,0x04,0x07,0x6d,0x52,0x75,0x32,0x23,0x50,0x53,0x48,0x94,0xaf,0x3a,0x30,0xa2,0xfe,0xc3,0x28,0x33,0xa1,0x59,0x64,0xa8,0x49,0x51,0xe0,0xda,0x7f,0xc8,0x72,0x92,0x7e,0x01,0xbb,0xa9,0x95,0x9b,0x46,0x9c,0x86,0x79,0x84, 0xfe,0xed,0x05,0x31,0x94,0xfe,0xa9,0x0a,0x43,0x40,0x42,0x4d,0x23,0xd1,0xab,0x64,0xbb,0x3b,0x95,0x93,0x39,0xb3,0x58,0x01,0x00,0x9f,0x95,0xfe,0x5d,0x01,0x94,0x82,0x7e,0x18,0x88,0xfe,0xf4,0xfe,0xe8,0x70,0xd5,0x92,0x81,0xb4,0x1f,0x02,0x06,0xfd,0x83,0x28,0x5d,0x5c,0x93,0xab,0xe8,0xcc,0xff,0x01,0x55,0xfe,0xab,0x00,0x00,0x02, 0x01,0x1a,0x00,0x00,0x06,0x29,0x05,0x31,0x00,0x1a,0x00,0x26,0x00,0x00,0x01,0x23,0x11,0x23,0x11,0x23,0x22,0x06,0x02,0x07,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x11,0x34,0x12,0x24,0x33,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x06,0x29,0xab,0xa8,0xed,0x99,0xf7,0x90,0x08,0x2c,0x88, 0x44,0x96,0xb7,0xbe,0x91,0xcb,0xd2,0xbd,0x01,0x47,0xc3,0x02,0x48,0xfd,0x32,0x63,0x45,0x47,0x77,0x2a,0x0a,0x79,0x6b,0x44,0x5e,0x04,0x9d,0xfb,0x63,0x04,0x9d,0x8d,0xfe,0xfc,0xa8,0x2b,0x33,0xbf,0x9c,0x9e,0xc8,0x01,0x21,0x01,0x1e,0xd0,0x01,0x5e,0xc3,0xfc,0x27,0x54,0x82,0x3c,0x30,0x8d,0xa0,0x74,0x00,0x03,0x00,0x48,0xff,0x00, 0x06,0xfc,0x05,0x31,0x00,0x2a,0x00,0x34,0x00,0x40,0x00,0x00,0x01,0x11,0x23,0x11,0x23,0x06,0x00,0x21,0x22,0x24,0x26,0x35,0x34,0x36,0x33,0x21,0x36,0x35,0x34,0x02,0x27,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x07,0x33,0x11,0x01,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32, 0x24,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x06,0xfc,0xa8,0xfb,0x59,0xfe,0x6c,0xfe,0xef,0x8d,0xfe,0xfd,0x83,0xba,0x9a,0x03,0x3c,0x07,0x80,0x78,0x25,0x1b,0xbf,0x92,0x5f,0x97,0x56,0x66,0xc1,0x84,0xb7,0x01,0x0d,0x92,0x06,0xcf,0xfe,0x58,0xfc,0xcb,0x36,0x43,0xd2,0xc5,0xaf,0x01,0x06,0xc9,0x67,0x44,0x44, 0x66,0x60,0x4a,0x4b,0x60,0x05,0x31,0xf9,0xf9,0x01,0xdc,0xf9,0xfe,0xf3,0x6e,0xb8,0x75,0x74,0x8c,0x60,0x31,0xb9,0x01,0x09,0x46,0x25,0x52,0x36,0xa2,0xc1,0x55,0x9f,0x70,0x6d,0xa9,0x5f,0xad,0xfe,0xb1,0xee,0x30,0x48,0x03,0x96,0xfb,0xd5,0x4b,0x35,0x74,0x7d,0xb6,0x03,0x30,0x53,0x7f,0x7d,0x55,0x52,0x6c,0x6e,0x00,0x04,0x00,0x23, 0xff,0xe4,0x07,0x20,0x05,0x31,0x00,0x30,0x00,0x3c,0x00,0x40,0x00,0x4c,0x00,0x00,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x23,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x11,0x21,0x15,0x23,0x11,0x33,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02, 0x07,0x01,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x11,0x23,0x11,0x05,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x26,0x06,0x16,0x2d,0x3b,0x87,0x73,0x4d,0x42,0x69,0x78,0x88,0x79,0x80,0x9b,0x31,0x9b,0x4b,0xa2,0x87,0x7f,0xc8,0x72,0x72,0x6c,0x02,0xbc,0x6d,0xea,0x3f,0xa8,0x61,0x72,0xc0,0x6c,0x47, 0x3d,0xfc,0x0c,0x63,0x95,0x9b,0x46,0x9c,0x86,0x65,0x52,0xff,0x02,0xf9,0x25,0x20,0x44,0x30,0x62,0x2a,0x46,0x2c,0x43,0xff,0x70,0xca,0xca,0x47,0x35,0xdf,0x8e,0xb4,0xd5,0xe1,0xc0,0x8d,0x86,0x90,0xd0,0xe5,0x6f,0x70,0xd5,0x92,0x86,0xa4,0x2a,0x02,0x06,0x94,0xfe,0xab,0x57,0x65,0x83,0xeb,0x99,0xa0,0xfe,0xda,0x53,0x02,0xd0,0x28, 0x5d,0x5c,0x93,0xab,0xc1,0xf3,0xff,0x01,0x55,0xfe,0xab,0x98,0x33,0x7c,0x65,0x74,0x93,0xf1,0x47,0x80,0x5a,0x00,0x00,0x02,0x00,0xbf,0xff,0xe5,0x05,0xa8,0x04,0xc9,0x00,0x0f,0x00,0x1f,0x00,0x00,0x05,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x03,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32, 0x36,0x36,0x35,0x34,0x26,0x26,0x03,0x33,0xa6,0xfe,0xdc,0xaa,0xa9,0x01,0x25,0xa6,0xa8,0x01,0x24,0xa9,0xa9,0xfe,0xdb,0xa7,0x7f,0xda,0x80,0x7f,0xda,0x80,0x7f,0xda,0x80,0x80,0xd9,0x1b,0xa6,0x01,0x21,0xab,0xa9,0x01,0x22,0xa7,0xa7,0xfe,0xdd,0xa8,0xa8,0xfe,0xdd,0xa7,0x04,0x5b,0x7f,0xdf,0x81,0x80,0xdd,0x7e,0x7d,0xdd,0x81,0x81, 0xe0,0x7e,0x00,0x01,0x00,0x34,0xff,0xe6,0x06,0x34,0x04,0xc9,0x00,0x1b,0x00,0x00,0x01,0x22,0x04,0x06,0x15,0x10,0x05,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x07,0x27,0x24,0x11,0x34,0x26,0x24,0x03,0x34,0xaa,0xfe,0xe8,0xa0,0x01,0x32,0x62,0xaf,0xbf,0xc1,0x01,0x61,0xde,0xe0,0x01,0x60,0xc0,0xbf, 0xb0,0x61,0x01,0x31,0xa0,0xfe,0xea,0x04,0x33,0x89,0xef,0x88,0xfe,0xef,0xc2,0x7a,0x6a,0x01,0x37,0xac,0xb7,0x01,0x32,0xad,0xaf,0xfe,0xcf,0xb6,0xac,0xfe,0xc8,0x69,0x7a,0xc2,0x01,0x11,0x88,0xef,0x89,0x00,0x00,0x02,0x00,0x45,0x00,0x00,0x06,0x22,0x04,0xdc,0x00,0x1e,0x00,0x2a,0x00,0x00,0x37,0x21,0x32,0x36,0x36,0x35,0x34,0x26, 0x27,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x21,0x01,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x45,0x03,0x61,0x87,0xe4,0x72,0xb2,0x8d,0x2c,0x4e,0x81,0x4b,0x72,0x9c,0x66,0xb0,0x5f,0x99,0x01,0x21,0xab,0x9b,0xfe,0xcd,0xae,0xfc,0x9f,0x03,0x91, 0x31,0x2f,0x40,0x57,0x4b,0x32,0x33,0x47,0x97,0x7d,0xd7,0x8e,0x95,0xf7,0x31,0x44,0x45,0x42,0x81,0x4b,0x9f,0x73,0x55,0x88,0x4e,0xac,0xfe,0xe0,0xa5,0xb1,0xfe,0xee,0xa8,0x03,0xb1,0x28,0x4e,0x1f,0x0b,0x57,0x33,0x33,0x47,0x47,0x00,0x01,0x01,0x78,0xff,0xe7,0x04,0xef,0x04,0xc9,0x00,0x28,0x00,0x00,0x01,0x14,0x06,0x06,0x23,0x22, 0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x04,0xef,0x75,0xca,0x7b,0xd9,0xe4,0x5a,0x65,0xab,0x53,0x51,0x81,0x4b,0x96,0x77,0xb6,0xb6,0x77,0x83,0x98,0x7d,0x7f,0x95,0x5c,0xa8,0xe6,0x72,0xba, 0x68,0x49,0x50,0x4e,0x5e,0x01,0x54,0x60,0xab,0x62,0xc6,0x7b,0x5b,0x50,0x39,0x64,0x3a,0x60,0x74,0x8d,0x6b,0x58,0x50,0x6d,0x74,0x64,0xa4,0x58,0x9a,0x5a,0x5f,0x84,0x2d,0x2a,0x98,0x00,0x00,0x02,0x00,0x9e,0xff,0xe8,0x05,0xca,0x04,0xec,0x00,0x0b,0x00,0x32,0x00,0x00,0x25,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x15,0x14,0x16, 0x13,0x24,0x36,0x37,0x26,0x26,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x24,0x11,0x34,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x16,0x17,0x03,0x29,0x33,0x47,0x47,0x33,0x35,0x45,0x48,0x30,0x01,0x17,0xee,0x05,0x05,0x58,0x51,0x3e,0x7e,0x8b,0x6c,0xca,0xb8,0x27,0x39, 0x9d,0x76,0x77,0x9b,0x37,0x27,0xfe,0x29,0x8a,0x5c,0x31,0x1d,0x5c,0xbf,0xb0,0x72,0x44,0x38,0x29,0x4d,0x0e,0x0f,0x4d,0x28,0x39,0x43,0x01,0xa6,0x3b,0xb0,0x7e,0x4f,0x77,0x31,0x74,0x3c,0xc2,0x6d,0x74,0xaf,0x7d,0x33,0x1e,0x62,0x40,0x6f,0x97,0x98,0x6e,0x37,0x67,0x21,0x67,0x01,0x46,0xa9,0x71,0x66,0x2f,0x59,0x2c,0x4d,0x79,0x54, 0x20,0x00,0x00,0x02,0x00,0x36,0xff,0xc0,0x06,0x32,0x04,0xcd,0x00,0x33,0x00,0x3e,0x00,0x00,0x01,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x1e,0x02,0x17,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x27,0x2e,0x03,0x23,0x22,0x00,0x03,0x27,0x36,0x12,0x37,0x26,0x26,0x27,0x37, 0x1e,0x02,0x25,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x36,0x02,0x96,0x38,0x3a,0x51,0xa3,0x85,0x80,0xa1,0x6e,0x69,0x30,0x3f,0x2b,0x17,0x0b,0x11,0x05,0x24,0x20,0x29,0x31,0x0e,0x8b,0x13,0x83,0x63,0x5e,0x79,0x13,0x1d,0x2d,0x40,0x49,0x33,0xe0,0xfe,0xc2,0x66,0x8f,0x3d,0xf0,0xa3,0x2d,0xc1,0x7c,0x21,0x55,0xba,0x9b,0x02, 0x01,0x57,0x37,0x38,0x53,0x5e,0x51,0x6a,0x02,0xc8,0x0f,0x06,0x59,0x6d,0x7f,0xa4,0x9e,0x75,0x5e,0x91,0x27,0x25,0x65,0x82,0x82,0x43,0x44,0x16,0x1f,0x5a,0x61,0x18,0x96,0xa0,0x7f,0x79,0xb5,0x7a,0x4d,0x21,0xfe,0xd0,0xfe,0xc7,0x25,0xdd,0x01,0x4f,0x55,0x9a,0xe7,0x32,0x88,0x14,0x90,0xdb,0x5f,0x38,0x54,0x55,0x41,0x64,0x3f,0x07, 0x62,0x00,0x00,0x01,0x00,0x99,0x00,0x00,0x05,0xcf,0x04,0xbe,0x00,0x1e,0x00,0x00,0x13,0x34,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x14,0x21,0x21,0x15,0x21,0x22,0x26,0x99,0xa7,0xa7,0x5c,0xa0,0x5f,0x97,0x7f,0x66,0x6a,0x97,0x7b,0x01,0xd2,0xfe,0x2e,0x7b, 0x97,0x01,0x04,0x03,0x8f,0xfc,0x56,0xbc,0xd0,0x01,0x42,0xbd,0x6b,0x6b,0xbe,0x50,0x8c,0x4f,0x92,0x59,0x54,0x5a,0x6f,0x97,0x77,0x61,0xb0,0x97,0xa8,0x00,0x00,0x01,0x01,0x4a,0xff,0xe5,0x05,0x1e,0x04,0xc9,0x00,0x2e,0x00,0x00,0x25,0x32,0x36,0x37,0x33,0x06,0x04,0x23,0x22,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x02,0x35,0x34, 0x26,0x23,0x22,0x06,0x07,0x23,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x0e,0x03,0x07,0x0e,0x02,0x15,0x14,0x16,0x03,0x30,0x95,0xa1,0x16,0xa2,0x18,0xfe,0xff,0xd5,0x8b,0xdf,0x7c,0x2e,0x5c,0x9a,0x95,0x8b,0x6f,0x3b,0xa5,0x6e,0x75,0x97,0x0d,0x9b,0xf9,0xbb,0x7b,0xc6,0x72,0x24,0x3d,0x59,0x6f,0x81,0x94,0x71,0x3e,0xad,0x7d,0x7c, 0x7b,0xbd,0xd2,0x56,0x9e,0x6b,0x49,0x71,0x54,0x42,0x22,0x20,0x32,0x44,0x32,0x4c,0x6a,0x74,0x68,0xa1,0xd0,0x59,0x9b,0x53,0x40,0x5f,0x48,0x33,0x27,0x1e,0x21,0x35,0x4d,0x38,0x5f,0x6c,0x00,0x01,0x00,0x28,0xff,0xe7,0x06,0x3f,0x04,0xc9,0x00,0x20,0x00,0x00,0x01,0x21,0x15,0x21,0x16,0x16,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02, 0x35,0x34,0x36,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x02,0x27,0x02,0xd5,0x03,0x6a,0xfd,0xd4,0x7c,0x81,0xa4,0xfe,0xd4,0xa4,0xa4,0xfe,0xd3,0xa3,0x7c,0x6e,0x5b,0x4d,0x58,0x7c,0xdb,0x7d,0x7c,0xdc,0x7c,0xdb,0xc0,0x04,0xc9,0x8b,0x5d,0xfb,0x91,0xa9,0xfe,0xe8,0xad,0xad,0x01,0x19,0xa8,0x92,0xfb, 0x5a,0x6e,0x40,0xc9,0x70,0x7d,0xd3,0x7b,0x7b,0xd4,0x7c,0xae,0x01,0x02,0x3b,0x00,0x00,0x01,0x00,0x99,0x00,0x00,0x05,0xcf,0x04,0xbe,0x00,0x1e,0x00,0x00,0x13,0x34,0x36,0x33,0x21,0x15,0x21,0x20,0x15,0x14,0x16,0x16,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x23,0x22,0x26,0x26,0x35,0x34,0x37,0x26,0x99,0xcf,0xbd, 0x03,0xaa,0xfc,0x71,0xfe,0xfc,0x43,0x7a,0x55,0x01,0xd2,0xfe,0x2e,0x7b,0x97,0xd0,0x7f,0x97,0x60,0xa0,0x5b,0xa7,0xa7,0x03,0x7b,0x99,0xaa,0x98,0xb0,0x3c,0x64,0x38,0x96,0x70,0x59,0xa8,0x97,0x50,0x8b,0x50,0xbd,0x6b,0x6b,0x00,0x00,0x02,0x00,0xac,0x00,0x00,0x05,0x2f,0x04,0xac,0x00,0x0f,0x00,0x1f,0x00,0x00,0x01,0x14,0x02,0x04, 0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x07,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x05,0x2f,0x9b,0xfe,0xf4,0x9b,0x9c,0xfe,0xf6,0x9b,0x9a,0x01,0x0d,0x9a,0x9a,0x01,0x0c,0x9c,0xa5,0x6c,0xc0,0x71,0x70,0xc1,0x6c,0x6e,0xbe,0x71,0x70,0xbf,0x6e,0x02,0x55,0xa2,0xfe,0xea, 0x9d,0x9f,0x01,0x14,0xa2,0xa1,0x01,0x16,0xa0,0xa0,0xfe,0xe9,0xa0,0x73,0xc9,0x76,0x76,0xca,0x72,0x74,0xc9,0x74,0x73,0xca,0x00,0x01,0x00,0xa1,0xff,0xfd,0x05,0x3a,0x04,0xac,0x00,0x1d,0x00,0x00,0x01,0x14,0x02,0x07,0x27,0x36,0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24, 0x33,0x32,0x04,0x12,0x05,0x3a,0xc2,0x8b,0x4a,0x68,0x8a,0x75,0xc4,0x6f,0x70,0xc5,0x72,0x8e,0x63,0x49,0x8d,0xc0,0xa0,0x01,0x10,0x9c,0x9d,0x01,0x11,0x9f,0x02,0x55,0xb8,0xfe,0xa6,0x46,0x93,0x37,0x01,0x08,0x86,0x72,0xcb,0x75,0x77,0xc9,0x72,0x8b,0xfe,0xf9,0x34,0x92,0x47,0x01,0x59,0xb8,0xa0,0x01,0x18,0x9f,0xa1,0xfe,0xe8,0x00, 0x00,0x01,0x00,0xf6,0x00,0x00,0x04,0xe6,0x04,0xac,0x00,0x25,0x00,0x00,0x01,0x14,0x02,0x04,0x23,0x21,0x35,0x21,0x32,0x37,0x24,0x11,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x04,0xe6,0x9c,0xfe,0xef,0x9f,0xfe,0x5c,0x01,0xa4,0x3c,0x4d, 0x01,0x1e,0x73,0xc4,0x70,0x54,0x80,0x7d,0x57,0x5c,0x3f,0x75,0x62,0xae,0x64,0xb0,0x66,0x66,0xb0,0x64,0xa8,0x01,0x0d,0x97,0x02,0x55,0x9d,0xfe,0xea,0xa2,0xa4,0x1b,0x64,0x01,0x32,0x72,0xca,0x76,0x7c,0x59,0x55,0x7f,0x44,0x72,0x77,0x66,0xae,0x65,0x64,0xb1,0x65,0x9b,0xfe,0xec,0x00,0x02,0x00,0xdd,0xff,0xdd,0x04,0xfe,0x04,0xac, 0x00,0x32,0x00,0x3c,0x00,0x00,0x05,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x32,0x37,0x17,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x07,0x16,0x33,0x32,0x37,0x05,0x32,0x37,0x26,0x26,0x23,0x22, 0x15,0x14,0x16,0x04,0xfe,0x54,0x6c,0x6b,0x58,0xb2,0x92,0x57,0xa4,0x5f,0x57,0x99,0x5d,0x73,0xee,0x48,0x3b,0x65,0xae,0x66,0x2d,0x3a,0x65,0x36,0x2f,0x56,0x20,0x6b,0x32,0x70,0x97,0x97,0x6a,0x8d,0xff,0x9c,0x70,0x46,0x38,0x0c,0x26,0xfd,0x55,0xc5,0x55,0x3c,0xad,0x51,0xa6,0x6d,0x23,0x33,0x61,0x45,0x2c,0x4e,0x81,0x46,0x53,0x7c, 0x42,0x6f,0x55,0x53,0xbe,0x6e,0xbd,0x69,0x30,0x27,0x58,0x41,0x68,0x35,0x47,0x8e,0x6d,0x66,0x96,0x9e,0xfe,0xf1,0x96,0xe1,0x9a,0x51,0x09,0x02,0x4f,0x43,0x4b,0x64,0x36,0x43,0x00,0x03,0x00,0x60,0xff,0xf3,0x05,0x7c,0x04,0xc1,0x00,0x26,0x00,0x30,0x00,0x3c,0x00,0x00,0x01,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06, 0x23,0x22,0x26,0x35,0x34,0x37,0x24,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x26,0x27,0x05,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x36,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xf0,0x51,0x90,0x6c,0x3f,0xca,0xb8,0x25,0x37,0xbb,0x8f,0x8d,0xbd,0x48,0xfe,0x56, 0x92,0x69,0x67,0x95,0xc1,0x82,0xf3,0xf0,0xdd,0x3a,0x5e,0x74,0xfd,0xe6,0x33,0x24,0x25,0x3f,0x33,0x88,0x02,0x00,0x60,0x46,0x45,0x61,0x5d,0x49,0x4b,0x5b,0x04,0xc1,0x0c,0x1f,0x44,0x78,0x64,0x87,0xce,0x46,0x23,0x63,0x38,0x88,0xa2,0xa7,0x83,0x6f,0x45,0x9b,0x01,0x45,0x69,0x92,0x95,0x67,0xa8,0x49,0x61,0x24,0x3f,0xa0,0x63,0x3a, 0x42,0x1f,0x06,0x61,0x27,0x37,0x39,0x25,0x5c,0x3c,0x2d,0xfd,0xc2,0x39,0x51,0x4e,0x3c,0x35,0x45,0x45,0x00,0x03,0x00,0x43,0xff,0xdc,0x05,0x99,0x04,0xac,0x00,0x35,0x00,0x3e,0x00,0x47,0x00,0x00,0x01,0x14,0x07,0x16,0x15,0x14,0x06,0x07,0x27,0x32,0x36,0x35,0x34,0x27,0x06,0x07,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x25,0x26, 0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x17,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x15,0x14,0x17,0x36,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x99,0xaa,0x74,0x89,0xaa,0x4b,0x62,0x7f,0x84,0x6b,0xf7,0x1b,0xc7,0xa8,0x73,0xa0,0xea, 0x01,0x1f,0x08,0x89,0x57,0x35,0x47,0x25,0x30,0x5a,0x3e,0x59,0xa3,0x76,0x68,0xae,0x67,0x06,0x7f,0x43,0x50,0xa5,0x7a,0x80,0xa0,0x9d,0x4e,0x35,0x83,0x72,0x94,0xfd,0x42,0xc5,0x99,0x49,0x2d,0x4d,0x7e,0x03,0x78,0xdd,0x63,0x78,0x8b,0x99,0x9a,0x26,0xa0,0x67,0x49,0x5c,0x6e,0x19,0x0f,0xe1,0xed,0x9e,0x73,0xa2,0x9e,0x18,0xac,0xfa, 0x4c,0x3c,0x1d,0x3a,0x27,0x82,0x20,0x93,0x4d,0x78,0xad,0x93,0xfe,0xfa,0xa0,0x08,0x0a,0x6a,0x89,0x84,0xb0,0xb0,0x73,0x38,0x4e,0x97,0x5c,0x69,0x3e,0xfe,0xd3,0x10,0x56,0x56,0x2b,0x42,0xa5,0x00,0x00,0x02,0x00,0x7e,0x00,0x00,0x05,0x5d,0x04,0xac,0x00,0x1d,0x00,0x28,0x00,0x00,0x21,0x21,0x22,0x24,0x26,0x35,0x34,0x37,0x26,0x23, 0x37,0x20,0x13,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x33,0x21,0x01,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x33,0x32,0x36,0x05,0x5d,0xfe,0x06,0xa4,0xfe,0xed,0x9d,0x9d,0x73,0xbb,0x0f,0x01,0x20,0x98,0x7c,0xa2,0x86,0xac,0xad,0x85,0x7e,0xa1,0x4c,0x4a,0xfc,0xb9,0x01,0xfa,0xfe,0x98,0x54,0x3e, 0x7b,0x59,0x3a,0x59,0x41,0x3f,0x53,0x84,0xeb,0x8d,0xc7,0x7d,0xc7,0xa5,0xfe,0xe6,0x2b,0xa0,0x7a,0x7b,0xa7,0x85,0xa0,0x4a,0x6c,0x93,0xb9,0x01,0xf5,0x36,0x49,0x1d,0x79,0x5c,0x40,0x00,0x00,0x01,0x00,0xd6,0x00,0x00,0x05,0x06,0x04,0xc1,0x00,0x27,0x00,0x00,0x21,0x21,0x22,0x26,0x26,0x35,0x34,0x37,0x36,0x37,0x36,0x35,0x34,0x26, 0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x06,0x07,0x06,0x15,0x14,0x16,0x33,0x21,0x05,0x06,0xfd,0x4d,0x66,0xb1,0x66,0x8d,0x27,0xd9,0x84,0x4b,0x3f,0x37,0x4a,0x1b,0x8e,0x31,0xab,0x7c,0x84,0xa8,0x8b,0x3e,0x84,0x3f,0x84,0x7c,0x5c,0x02,0xb3,0x62,0xab,0x64,0xb5,0x66,0x1e,0x61, 0x3a,0x49,0x3f,0x50,0x45,0x2f,0x30,0x1c,0x52,0x41,0x62,0x74,0x9f,0xae,0x8d,0x9d,0x46,0x1f,0x34,0x1e,0x40,0x70,0x5b,0x83,0x00,0x02,0x00,0x8d,0x00,0x00,0x05,0x4e,0x04,0xc1,0x00,0x26,0x00,0x31,0x00,0x00,0x01,0x23,0x16,0x16,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22, 0x27,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x10,0x27,0x35,0x21,0x01,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x33,0x32,0x36,0x05,0x4e,0xd6,0x62,0x4d,0x9f,0xfe,0xf0,0x9d,0xa4,0xfe,0xf0,0x9a,0x5a,0x91,0x5d,0x64,0x90,0x90,0x64,0x5c,0x3f,0x08,0x70,0xc3,0x76,0x6e,0xc5,0x75,0xec,0x01,0xb7,0xfc,0xeb,0x3f,0x25,0x2e,0x41, 0x0b,0x3f,0x3b,0x2b,0x39,0x04,0x07,0x6a,0xc1,0x87,0x9f,0xfe,0xed,0xa3,0xa5,0x01,0x22,0xaf,0xa0,0x01,0x21,0x8a,0xa4,0x72,0x6f,0xa6,0x3c,0x23,0x40,0x80,0xd5,0x76,0x74,0xc6,0x70,0x01,0x15,0xa7,0xa1,0xff,0x00,0x29,0x49,0x58,0x53,0x4b,0x4f,0x00,0x00,0x02,0x01,0x0d,0x00,0x00,0x04,0xcf,0x04,0xac,0x00,0x26,0x00,0x31,0x00,0x00, 0x01,0x21,0x22,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x17,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x21,0x01,0x34,0x23,0x22,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x04,0xcf,0xfd,0x93,0x48,0x68,0x35,0x73,0xa4,0x80,0x92,0x92,0x68,0x9c, 0x74,0x08,0x7d,0x63,0x5c,0x37,0x74,0x6a,0x9d,0xab,0xdb,0x25,0x70,0x5b,0x9e,0x5c,0x02,0x6d,0xfe,0xa4,0x5e,0x29,0x7f,0x17,0x20,0x6e,0x27,0x27,0x41,0x04,0x07,0x68,0x48,0x5e,0x32,0x63,0x6f,0x62,0x5d,0x7b,0x45,0x1b,0x16,0x6a,0x87,0x25,0x73,0x56,0xe3,0xb2,0x4e,0x53,0x7c,0xa5,0x5a,0x9f,0x5c,0xfd,0xa9,0x41,0x28,0x15,0x1a,0x2b, 0x29,0x00,0x00,0x02,0x01,0xc8,0xff,0xe8,0x05,0x54,0x03,0x7c,0x00,0x0b,0x00,0x1b,0x00,0x00,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x8e,0x7f,0xa0,0xa0,0x7f,0x7f,0xa0,0xa0,0x7f,0x7e,0xd0,0x78,0x78,0xd1,0x7d,0x7e,0xd0, 0x78,0x78,0xd0,0x81,0xa9,0x88,0x88,0xa9,0xa9,0x88,0x88,0xa9,0x99,0x76,0xd3,0x81,0x81,0xd3,0x76,0x76,0xd3,0x81,0x81,0xd3,0x76,0x00,0x00,0x02,0x00,0x24,0xfe,0x63,0x06,0xf8,0x05,0xb3,0x00,0x18,0x00,0x21,0x00,0x00,0x21,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x11,0x10,0x12,0x21, 0x20,0x00,0x11,0x03,0x11,0x10,0x26,0x23,0x22,0x06,0x11,0x11,0x06,0xf8,0xfa,0x99,0x67,0x5f,0x60,0x66,0x01,0x55,0xfe,0xb6,0xc2,0xb6,0xc4,0xb4,0x01,0x57,0xff,0x01,0x03,0x01,0x02,0x01,0x01,0xa4,0xb1,0xae,0xb0,0xae,0x3f,0x46,0x4a,0x3b,0x93,0x86,0x90,0x8f,0x8b,0x02,0x9d,0x01,0x44,0x01,0x3f,0xfe,0xc5,0xfe,0xb8,0xfd,0x63,0x02, 0x8e,0x01,0x05,0xf4,0xf8,0xfe,0xff,0xfd,0x72,0x00,0x00,0x01,0x00,0x37,0xff,0xe6,0x06,0xe5,0x05,0xb3,0x00,0x1e,0x00,0x00,0x25,0x15,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x07,0x06,0xe5,0xfc,0xd6,0x67,0x56,0xf8,0xd5,0xd5, 0xf8,0x66,0x83,0x98,0x80,0x78,0xa4,0x01,0x27,0xb4,0xae,0x01,0x1c,0x9f,0x56,0x4a,0x93,0x93,0x62,0xa7,0x01,0x15,0x96,0x01,0x19,0x01,0x4d,0xfe,0xb2,0xfe,0xe8,0xae,0xfe,0xdd,0xc6,0x37,0xb9,0x01,0x64,0xbb,0xdc,0x01,0x5b,0xbe,0xbe,0xfe,0xa7,0xde,0x8d,0xfe,0xd6,0x74,0x00,0x01,0x00,0x32,0xff,0xe6,0x06,0xe9,0x05,0xb3,0x00,0x2d, 0x00,0x00,0x25,0x15,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x10,0x12,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x07,0x06,0xe9,0xfd,0x59,0x53,0x52,0x6c,0x79,0x71,0x61,0xa4,0x61,0x71,0x7b,0x6a,0x66, 0x5d,0x9b,0x5f,0x6c,0xc5,0xbe,0x6e,0x96,0x21,0x08,0x20,0x96,0x6f,0x76,0xad,0x60,0x4b,0x30,0x93,0x93,0x51,0x74,0x01,0x4b,0xf6,0x01,0x12,0x01,0x00,0xc7,0xeb,0xfc,0x9a,0x03,0x66,0xea,0xc8,0xfb,0xfe,0xe9,0xf9,0xfe,0x87,0x77,0x37,0x7f,0x01,0xa8,0xe2,0x01,0x56,0x01,0x6e,0x74,0x6b,0x6a,0x75,0xa3,0xfe,0xc0,0xe1,0x99,0xfe,0x93, 0x56,0x00,0x00,0x02,0x00,0x7e,0xff,0xe6,0x06,0x9e,0x07,0xc8,0x00,0x30,0x00,0x3c,0x00,0x00,0x01,0x14,0x02,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x37,0x26,0x23,0x22,0x04,0x02,0x15,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x07,0x16,0x12,0x07,0x34,0x26,0x27,0x06,0x02,0x15,0x14,0x16,0x33,0x32,0x12,0x06,0x4e,0x79,0xd9,0x88,0xac,0xd5,0xd6,0xd3,0x80,0xaf,0xac,0xfe,0xf0,0x8c,0x6e,0x6e,0x95,0x71,0x7d,0xb3,0x01,0x60,0xde,0xfd,0xba,0x77,0x5b,0x79,0x7a,0x9b,0x9f,0x1d,0xac,0xbb,0xb2,0xd7,0x7f,0x94,0x5e,0x65,0xa7,0x55,0x4b,0xbb,0xb2,0x7c,0x69,0x80, 0xa8,0x02,0x8e,0xb7,0xfe,0xc0,0xb1,0x01,0x1c,0xdd,0xdb,0x01,0x6c,0x9e,0x54,0x9d,0xfe,0xec,0xb7,0xb6,0xfe,0xc4,0x9e,0x3a,0xa6,0x01,0x7d,0xaa,0xe3,0x01,0x57,0xc6,0x8c,0x5b,0x97,0x51,0x62,0x6e,0x3b,0x8a,0x3f,0xba,0x95,0x6f,0xcf,0x72,0x6b,0xfe,0xde,0xba,0x94,0xfc,0x55,0x8d,0xfe,0xc6,0xc1,0xa3,0xbe,0x01,0x24,0x00,0x00,0x01, 0x00,0x37,0xfd,0xfe,0x06,0xe5,0x07,0x61,0x00,0x43,0x00,0x00,0x05,0x27,0x12,0x11,0x10,0x00,0x21,0x22,0x00,0x02,0x11,0x10,0x12,0x04,0x33,0x32,0x12,0x35,0x10,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x11,0x10,0x13,0x07,0x02,0x11,0x10,0x00,0x33,0x32,0x16,0x15,0x10,0x07,0x15,0x16,0x16,0x15,0x14,0x02,0x06, 0x23,0x22,0x24,0x02,0x02,0x35,0x10,0x12,0x00,0x21,0x32,0x04,0x12,0x11,0x14,0x02,0x06,0x53,0x9e,0x8b,0xfe,0xaf,0xfe,0xd1,0xd4,0xfe,0xa5,0xb6,0x9c,0x01,0x0e,0xb4,0xbf,0xd4,0xf8,0x72,0x65,0x63,0x6d,0x73,0x7a,0xa8,0xa0,0x8b,0x99,0x96,0x01,0x03,0xed,0xb9,0xd3,0xae,0x67,0x7d,0x96,0xff,0xa8,0xa9,0xfe,0xea,0xc9,0x74,0xde,0x01, 0xaa,0x01,0x0a,0xef,0x01,0x6b,0xc2,0x4c,0x19,0x37,0x01,0x9f,0x01,0x92,0x01,0xa6,0x01,0xd3,0xfe,0xfe,0xfe,0x32,0xfe,0xcd,0xfe,0xd1,0xfe,0x00,0xff,0x01,0x24,0xfd,0x01,0x7d,0x96,0x9b,0x85,0xa2,0x8d,0xfe,0xe7,0xfe,0xbd,0xfe,0xb1,0xfe,0xae,0x37,0x01,0x75,0x01,0x5f,0x01,0x69,0x01,0x90,0xf0,0xca,0xfe,0xf8,0x67,0x06,0x1e,0xfc, 0xb4,0xc0,0xfe,0xb0,0xa8,0xb1,0x01,0x4d,0x01,0xd0,0xe9,0x01,0x60,0x02,0x19,0x01,0x33,0xfd,0xfe,0x2f,0xfe,0xc6,0xd7,0xfe,0x31,0x00,0x00,0x01,0x00,0x46,0xfd,0xfe,0x06,0xd6,0x05,0xb3,0x00,0x3e,0x00,0x00,0x17,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x20,0x11, 0x10,0x02,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x12,0x11,0x10,0x02,0x23,0x22,0x06,0x11,0x11,0x23,0x11,0x10,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x26,0x23,0x22,0x06,0x02,0x15,0x10,0x17,0xd0,0x41,0x49,0x51,0x92,0x64,0x56,0x7e,0x2a,0x05,0x24,0x86,0x5a,0x5b,0x6f,0x31,0x06,0x26,0x7f,0x60,0x01,0x3c,0x7f,0xe3,0x99, 0x8c,0x6f,0x7e,0x77,0xb3,0xad,0x59,0x4e,0x5e,0x51,0xa3,0x4e,0x5b,0x63,0x54,0xa3,0x49,0x55,0x32,0x52,0x2f,0x7d,0x1a,0x85,0x01,0x91,0xdc,0xe8,0x01,0x4b,0xa8,0x56,0x6b,0x5f,0x62,0x52,0x73,0x64,0x61,0xfc,0xcf,0xfe,0xaa,0xfd,0xe8,0xfe,0xea,0x2d,0xac,0x40,0x01,0xe2,0x01,0xf7,0x01,0x51,0x01,0x57,0xda,0xfe,0xfe,0xfc,0xc4,0x03, 0x3c,0x01,0x05,0xd7,0xe9,0xf1,0xfc,0xc2,0x03,0x3e,0x01,0x0b,0xcf,0x8b,0xfe,0xf9,0xb5,0xfe,0x46,0xfa,0x00,0x02,0x01,0x25,0xff,0xe6,0x05,0xf6,0x05,0xb3,0x00,0x0b,0x00,0x30,0x00,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x16,0x04,0x33,0x32,0x36,0x12,0x35,0x34,0x02,0x26,0x27,0x07,0x16,0x16,0x15, 0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x20,0x27,0x03,0x6e,0x6e,0x5e,0x5e,0x7a,0x6e,0x5d,0x63,0x76,0xfd,0xb9,0x68,0x01,0x05,0x92,0xa8,0xfd,0x84,0x86,0xe3,0x82,0x03,0x55,0x62,0x62,0xb1,0x6f,0xa9,0xc8,0x86,0xed,0x9a,0xcb,0x01,0x41,0xb8,0xb6,0xfe,0xb1,0xcb,0xfe,0xbf, 0xbe,0x04,0x1e,0x69,0x80,0x82,0x64,0x66,0x7c,0x78,0xfd,0x84,0x5c,0x60,0x95,0x01,0x0f,0xb0,0x9f,0x01,0x12,0xa3,0x07,0x08,0x1c,0x9b,0x60,0x65,0xa5,0x5d,0xc6,0xa3,0x7f,0xbd,0x66,0xb4,0xfe,0xa9,0xd3,0xdc,0xfe,0xab,0xbe,0x94,0x00,0x01,0x00,0x4b,0xfd,0xfe,0x06,0xd1,0x05,0xb3,0x00,0x2d,0x00,0x00,0x01,0x11,0x10,0x00,0x21,0x22, 0x26,0x27,0x35,0x17,0x16,0x33,0x32,0x36,0x35,0x21,0x35,0x36,0x12,0x35,0x10,0x02,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15,0x14,0x02,0x07,0x21,0x11,0x06,0xd1,0xfe,0xcd,0xfe,0xe6,0x46,0x76,0x55,0x4a,0x69,0x70,0xbb,0xdc,0xfd,0xa2,0x67,0x56,0xf8,0xd5,0xd5,0xf8,0x66,0x83, 0x98,0x80,0x78,0xa4,0x01,0x27,0xb4,0xae,0x01,0x1c,0x9f,0x56,0x4a,0x01,0x9a,0x05,0x99,0xfa,0xb4,0xfe,0xe3,0xfe,0xce,0x13,0x14,0xac,0x18,0x22,0xc6,0xa3,0x62,0xa7,0x01,0x15,0x96,0x01,0x19,0x01,0x4d,0xfe,0xb2,0xfe,0xe8,0xae,0xfe,0xdd,0xc6,0x37,0xb9,0x01,0x64,0xbb,0xdc,0x01,0x5b,0xbe,0xbe,0xfe,0xa7,0xde,0x8d,0xfe,0xd6,0x74, 0x05,0x06,0x00,0x02,0x00,0x3d,0xff,0xe6,0x06,0xde,0x07,0xc8,0x00,0x3f,0x00,0x4a,0x00,0x00,0x01,0x14,0x02,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x37,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x02,0x11,0x14,0x12,0x17,0x07,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x17,0x36,0x36, 0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x12,0x07,0x34,0x26,0x27,0x06,0x02,0x15,0x10,0x33,0x32,0x12,0x06,0x9e,0x64,0xac,0x6c,0x88,0xad,0xb0,0xad,0x57,0x59,0x88,0x91,0xa2,0xea,0x8c,0x88,0x65,0x58,0x9a,0x5c,0x6b,0x6e,0xc5,0x81,0x75,0xab,0x20,0x07,0x2b,0xc0,0x7d,0x90,0x85,0x3d, 0x49,0x60,0x63,0x3b,0x64,0x3f,0x17,0x89,0x97,0x8e,0xad,0x67,0x75,0x48,0x54,0xa4,0x2b,0x30,0x8f,0x7f,0x9a,0x61,0x6e,0x02,0x8e,0xbb,0xfe,0xc2,0xaf,0x01,0x18,0xe1,0xdd,0x01,0x6f,0xa0,0x4f,0xf6,0xe6,0xfc,0xc2,0x03,0x3e,0x01,0xdc,0xfe,0xe3,0xfe,0xd4,0xb4,0xfe,0x8c,0x8c,0x37,0x98,0x01,0x9f,0xbb,0xe4,0x01,0x4a,0xad,0x90,0x81, 0x83,0x8e,0x87,0x3a,0xa8,0x5c,0x63,0x6d,0x1d,0x1e,0x8a,0x3f,0xb8,0x97,0x6f,0xd0,0x70,0x6d,0xfe,0xdd,0xb8,0xb7,0xd9,0x4b,0x84,0xfe,0xd5,0xcf,0xfe,0x9f,0x01,0x13,0x00,0x02,0x00,0xdf,0xff,0xf4,0x05,0x88,0x03,0xf1,0x00,0x0b,0x00,0x1b,0x00,0x00,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x22,0x24,0x26, 0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x14,0x06,0x04,0x03,0x32,0xc7,0xdf,0xdf,0xc7,0xc5,0xdd,0xdd,0xc5,0xaa,0xfe,0xee,0x97,0x95,0x01,0x13,0xab,0xae,0x01,0x14,0x94,0x97,0xfe,0xee,0x87,0xc2,0xa9,0xab,0xc1,0xc3,0xa9,0xa9,0xc2,0x93,0x7f,0xe9,0x96,0x97,0xea,0x7e,0x7f,0xe9,0x97,0x96,0xe8,0x80,0x00,0x00,0x02,0x00,0xa3, 0xff,0xf4,0x05,0xc4,0x03,0xf1,0x00,0x2b,0x00,0x37,0x00,0x00,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x35,0x34,0x36,0x24,0x33,0x32,0x04,0x16,0x15,0x14,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x04,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x27,0x26,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x22,0x06,0x02,0x49,0x74,0x5a,0x5d,0x77,0xe8,0xc2,0xb7,0xe7,0xa0,0x01,0x2c,0xc4,0xbf,0x01,0x2c,0xa6,0xcb,0xc2,0x6d,0x6f,0x7a,0xdc,0x8a,0xd9,0xfe,0xf9,0x3f,0x73,0x43,0x82,0x41,0x03,0x55,0x6a,0x6c,0x3a,0x2a,0x27,0x3a,0x39,0x28,0x2b,0x39,0x01,0xb7,0x58,0x78,0x7b,0x63,0xc5,0xf0,0x01,0x05,0xd6,0x9f,0xf9,0x8a,0x88, 0xfa,0x9d,0xc0,0xf6,0x27,0x95,0x1d,0xa8,0x83,0x74,0xb5,0x63,0xd9,0xb6,0x62,0x91,0x51,0x58,0x06,0x06,0x72,0x58,0x29,0x39,0x37,0x2b,0x29,0x39,0x39,0x00,0x00,0x02,0x00,0xc6,0x00,0x00,0x05,0xa2,0x05,0xe6,0x00,0x3e,0x00,0x4a,0x00,0x00,0x01,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23, 0x21,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x25,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x34,0x76,0x72,0x41,0x5d,0x15, 0x07,0x0d,0x6e,0x4a,0x7e,0x89,0xb7,0xa0,0xfd,0xd2,0xa1,0xb6,0xad,0x66,0x5b,0x02,0x00,0x5b,0x64,0x36,0x33,0x2e,0x3f,0x03,0x91,0x02,0x3e,0x2d,0x31,0x31,0x27,0x1e,0x05,0x04,0x55,0x44,0x44,0x57,0x64,0x5d,0x96,0xa9,0x01,0x67,0x1f,0x2e,0x2d,0x20,0x1e,0x2d,0x2e,0x02,0x98,0xb3,0xa9,0x48,0x45,0x3f,0x4e,0xaf,0x99,0xfe,0x9e,0x9b, 0xaf,0xb0,0x9a,0x04,0x9c,0xfb,0x6f,0x5b,0x60,0x60,0x5b,0x01,0x5e,0x55,0x5a,0x4c,0x3e,0x3e,0x4c,0x58,0x72,0x4f,0x73,0x10,0x05,0x05,0x18,0x42,0x58,0x59,0x41,0x4f,0x56,0xb1,0x3e,0x2b,0x20,0x20,0x2a,0x2a,0x20,0x20,0x2b,0x00,0x00,0x02,0x00,0xbb,0xff,0xf4,0x05,0xac,0x03,0xf3,0x00,0x2d,0x00,0x39,0x00,0x00,0x05,0x22,0x02,0x35, 0x34,0x12,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x12,0x15,0x14,0x02,0x07,0x35,0x36,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x37,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x68,0xc3,0xea,0xc8,0xa4,0x5f,0x8d,0x24,0x1e, 0x91,0x63,0xa2,0xc1,0xc4,0xa5,0xb8,0x78,0x58,0x4e,0x53,0xab,0x58,0x4f,0x56,0x77,0x37,0x07,0x06,0x6f,0x58,0x5b,0x76,0x7a,0x55,0x29,0x39,0x39,0x29,0x2a,0x37,0x38,0x0c,0x01,0x1d,0xeb,0xdf,0x01,0x18,0x72,0x74,0x6b,0x7b,0xfe,0xea,0xdf,0xce,0xfe,0xe9,0x24,0x96,0x3c,0x01,0x37,0x92,0xd0,0x9c,0x91,0x91,0x9c,0xce,0x96,0xb0,0x74, 0x02,0x54,0x68,0x74,0x58,0x5d,0x79,0x01,0x38,0x02,0x39,0x29,0x2a,0x38,0x38,0x2a,0x28,0x3c,0x00,0x02,0x00,0xcf,0xff,0xed,0x05,0x98,0x05,0x82,0x00,0x3b,0x00,0x47,0x00,0x00,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x17,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x24,0x37,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x26,0x26,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x18,0xb7,0x96,0x70,0x81,0x78,0x58,0x56,0x71,0x08,0x1f,0x9b,0x81,0x8c,0x58,0x39,0xb1,0x54,0x41,0xab,0xa5,0x33,0xda, 0xed,0x93,0x01,0x20,0xf9,0xaf,0xa5,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c,0x98,0x81,0x29,0x75,0x3c,0x38,0x39,0x57,0x01,0x6f,0x27,0x3b,0x38,0x2a,0x27,0x3b,0x3c,0x01,0xae,0x89,0xa6,0x74,0x62,0x5a,0x74,0x6a,0x59,0x23,0x38,0x5e,0x7b,0x10,0x0e,0x23,0x9a,0x19,0x24,0x18,0x16,0xeb,0xcc,0xa3,0xef,0xa4,0x3b,0x28,0x77,0x57, 0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71,0x93,0x5f,0x85,0xa0,0x13,0x0b,0x05,0x1e,0x8e,0x45,0x39,0x2b,0x29,0x3a,0x39,0x2a,0x2a,0x3a,0x00,0x03,0x00,0xcf,0xff,0xed,0x05,0x98,0x05,0x82,0x00,0x43,0x00,0x4f,0x00,0x5b,0x00,0x00,0x01,0x07,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x16, 0x33,0x32,0x37,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x15,0x14,0x16,0x17,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x14,0x16,0x33, 0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0xaa,0x08,0x9e,0x8f,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c,0x98,0x81,0x29,0x75,0x3c,0x38,0x39,0x57,0xb7,0x96,0x70,0x81,0x78,0x58,0x56,0x71,0x08,0x1f,0x9b,0x81,0x8c,0x58,0x39,0xb1,0x54,0x41,0xab,0xa5,0x33,0xda,0xed,0xb0,0xc5,0x3d,0x74,0x59,0x64,0x72,0xdd,0x27,0x3b,0x38, 0x2a,0x27,0x3b,0x3c,0xfe,0x0f,0x3c,0x28,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x04,0x3d,0x10,0x29,0x72,0x52,0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71,0x93,0x5f,0x85,0xa0,0x13,0x0b,0x05,0x1e,0x8e,0x4f,0x89,0xa6,0x74,0x62,0x5a,0x74,0x6a,0x59,0x23,0x38,0x5e,0x7b,0x10,0x0e,0x23,0x9a,0x19,0x24,0x18,0x16,0xeb,0xcc,0xb9,0x01, 0x03,0x58,0x3c,0x5c,0x5a,0x75,0x81,0xfc,0xf7,0x39,0x2b,0x29,0x3a,0x39,0x2a,0x2a,0x3a,0x02,0xbc,0x28,0x3b,0x3c,0x27,0x29,0x3b,0x3b,0x00,0x02,0x01,0x08,0xff,0xf4,0x05,0x5f,0x05,0x6a,0x00,0x28,0x00,0x34,0x00,0x00,0x25,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x26,0x02,0x27,0x33,0x16,0x16,0x17,0x36,0x36,0x33, 0x32,0x04,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x6d,0x47,0x8b,0xa9,0xc6,0xae,0x9b,0x47,0xa9,0x46,0x30,0xae,0x49,0xd5,0x2c,0x49,0x25,0x30,0x91,0x3b,0xe7,0x01,0x05,0x7e,0xeb,0x98,0xca,0xfe,0xfa,0x7a,0x6a,0x58, 0x75,0x75,0x5b,0x60,0x3b,0x28,0x28,0x3b,0x3b,0x28,0x2a,0x39,0xb9,0x34,0xc2,0xb1,0xa2,0xb0,0x26,0x1f,0xa1,0x01,0x70,0x54,0x44,0xd5,0xa6,0x16,0x1a,0xfc,0xe7,0x98,0xec,0x80,0xd7,0xaa,0x6d,0x7c,0x74,0x5c,0x57,0x76,0xce,0x2a,0x39,0x3c,0x27,0x29,0x3b,0x3a,0x00,0x02,0x00,0x35,0xff,0xf4,0x06,0x33,0x05,0xe6,0x00,0x3b,0x00,0x47, 0x00,0x00,0x13,0x34,0x12,0x33,0x32,0x16,0x17,0x3e,0x02,0x33,0x32,0x12,0x15,0x14,0x06,0x07,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x06,0x23,0x21,0x36,0x11,0x34,0x26,0x23,0x22,0x06,0x06,0x15,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x37,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x05,0x06,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0xac,0xa3,0x53,0x8a,0x23,0x0d,0x48,0x66,0x36,0xa0,0xac,0x25,0x15,0x46,0x56,0x62,0xae,0x58,0xa4,0x66,0xfe,0xe2,0x5d,0x52,0x4d,0x2d,0x49,0x29,0xa7,0x01,0x53,0x47,0x51,0x58,0x37,0x07,0x06,0x70,0x58,0x5c,0x74,0x7b,0x64,0x80,0xc5,0x6a,0x01,0xbf,0x2a,0x3a,0x3a,0x2a,0x29,0x39, 0x3a,0x01,0xfc,0xf8,0x01,0x00,0x75,0x66,0x37,0x65,0x3f,0xfe,0xfe,0xf4,0x64,0xce,0x31,0x5f,0x5b,0x04,0x91,0xfb,0x64,0x5d,0x97,0x56,0xc8,0x01,0x36,0xa7,0xbd,0x45,0x8c,0x64,0x9f,0x96,0xb8,0xae,0xbb,0x69,0x02,0x57,0x65,0x75,0x57,0x5f,0x77,0x82,0xec,0x36,0x02,0x39,0x29,0x2a,0x38,0x3b,0x27,0x27,0x3d,0x00,0x00,0x02,0x00,0xa7, 0xff,0xf6,0x05,0xc1,0x05,0x82,0x00,0x40,0x00,0x4c,0x00,0x00,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x23,0x22,0x26,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x06,0x07,0x07,0x26,0x26,0x35,0x34,0x36,0x24,0x37,0x36,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x07,0x0e,0x03,0x15,0x14,0x17,0x36,0x36, 0x33,0x32,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x05,0x21,0x16,0x1b,0x57,0x78,0x77,0x56,0x5c,0x77,0x9e,0x80,0x2f,0x57,0x56,0x45,0x3e,0x3e,0x1b,0x1e,0x25,0x18,0x10,0x02,0xda,0xfd,0x93,0x01,0x20,0xf9,0xaf,0xa5,0x12,0xac,0x15,0xd7,0xe9,0xcd,0xc0,0x78,0x3c, 0xb4,0x16,0x6f,0x5d,0x26,0x49,0x49,0x52,0x46,0x4b,0x1c,0x2e,0x49,0x0d,0x9a,0x3b,0x29,0x27,0x3b,0x3a,0x28,0x27,0x3d,0x01,0x18,0x05,0x76,0x59,0x5a,0x75,0x7c,0x65,0xd1,0xfe,0xf7,0x27,0x46,0x4d,0x44,0x2e,0x33,0x57,0x84,0x1b,0x02,0xf1,0xc7,0xa3,0xef,0xa4,0x3b,0x28,0x77,0x57,0x3b,0x2d,0x28,0x3d,0x94,0xb6,0x35,0x30,0x56,0x71, 0x93,0x5f,0xca,0x39,0x8b,0x7f,0x22,0x39,0x54,0x4c,0x34,0x49,0x3d,0xd0,0x29,0x3b,0x39,0x2b,0x29,0x39,0x3a,0x00,0x00,0x02,0x00,0x67,0xff,0xf4,0x06,0x00,0x04,0xfe,0x00,0x37,0x00,0x43,0x00,0x00,0x13,0x34,0x12,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x02,0x06,0x23,0x22,0x26, 0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x01,0x23,0x03,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x02,0x25,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x67,0xd9,0xc5,0x57,0x9d,0x2b,0x1e,0x51,0x38,0x1a,0x3f,0x4b,0x35,0x37,0x15,0x31,0x37,0xa8,0x54,0x79,0x43,0x23, 0x55,0x51,0x1d,0x2e,0x11,0x1d,0x2d,0x0b,0x01,0x13,0xc1,0xe5,0x3e,0x6d,0x3f,0x4a,0x67,0x31,0x3c,0x08,0x6f,0x58,0x5b,0x76,0x7a,0x65,0xc7,0xe6,0x01,0xbd,0x2a,0x39,0x3a,0x29,0x2a,0x37,0x38,0x01,0xdb,0xfa,0x01,0x1c,0x6a,0x57,0x94,0x7a,0x26,0x48,0x35,0x26,0xe1,0xa8,0x88,0xfe,0xe5,0x8f,0x32,0x51,0x1d,0x28,0x88,0x7f,0xfd,0x73, 0x02,0x46,0xa1,0x7a,0x63,0xb5,0x6a,0x9d,0x76,0x5c,0x6e,0x74,0x58,0x5d,0x79,0x01,0x06,0x32,0x02,0x3b,0x27,0x2a,0x38,0x38,0x2a,0x28,0x3c,0x00,0x00,0x02,0x00,0xd0,0xff,0xf2,0x05,0x97,0x04,0xa3,0x00,0x0f,0x00,0x1e,0x00,0x00,0x01,0x32,0x04,0x12,0x15,0x14,0x02,0x04,0x23,0x22,0x24,0x02,0x35,0x34,0x12,0x24,0x13,0x32,0x36,0x35, 0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x03,0x3a,0xaa,0x01,0x18,0x9b,0x9e,0xfe,0xe6,0xaf,0xa9,0xfe,0xe7,0x9e,0xa0,0x01,0x1e,0xa2,0xcb,0xf2,0x6d,0xc7,0x7f,0x82,0xcd,0x71,0x71,0xc9,0x04,0xa3,0x9a,0xfe,0xed,0xad,0xad,0xfe,0xec,0x96,0x9c,0x01,0x14,0xa7,0xa9,0x01,0x15,0x9c,0xfb,0xe5,0xf9,0xc8,0x80,0xd0,0x74, 0x76,0xd0,0x80,0x7d,0xcf,0x73,0x00,0x02,0x00,0xd2,0xff,0xf7,0x05,0x95,0x04,0xa3,0x00,0x2a,0x00,0x36,0x00,0x00,0x05,0x27,0x36,0x12,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x12,0x24,0x33,0x32,0x04,0x12,0x15, 0x10,0x25,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x4d,0x75,0x80,0x94,0x70,0xc9,0x81,0x85,0xc7,0x6e,0x85,0x6e,0x2d,0x15,0x38,0x69,0x48,0x48,0x6b,0x5b,0xa4,0x6f,0x75,0xbc,0x68,0xa0,0x01,0x11,0xaf,0xa5,0x01,0x15,0xa9,0xfd,0x93,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x09,0x70,0x69,0x01,0x19,0x97,0x65,0xb9, 0x6f,0x6a,0xbc,0x71,0x9a,0xb4,0x0b,0x34,0x4d,0x4b,0x69,0x6b,0x49,0x4e,0x81,0x49,0x73,0xd6,0x8e,0x97,0x01,0x07,0x92,0x8e,0xfe,0xfa,0x8f,0xfe,0x90,0x65,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x02,0x01,0x47,0xff,0xf2,0x05,0x21,0x06,0x66,0x00,0x25,0x00,0x31,0x00,0x00,0x25,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x10,0x01,0x36,0x12,0x37,0x17,0x0e,0x02,0x07,0x0e,0x03,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x08,0x26,0x26,0x65,0x4b,0x50,0x65,0x6c,0xc8,0x7e,0xa2,0xfb,0x8b,0x01,0x82,0x94,0xca,0x3a,0x92,0x2e,0x5c,0x75,0x8d,0x69,0x8f,0x57, 0x27,0x69,0xba,0x6a,0x61,0x90,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0xa1,0x26,0x3e,0x2d,0x50,0x62,0x68,0x4a,0x58,0x93,0x55,0x7f,0xe8,0x93,0x01,0x2b,0x01,0x35,0x77,0x01,0x06,0x9d,0x36,0x7b,0xa7,0x89,0x77,0x5a,0x91,0x7b,0x71,0x51,0x5c,0xa0,0x62,0x6b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x03,0x00,0xa3,0xff,0xf2, 0x05,0xc4,0x06,0xac,0x00,0x45,0x00,0x50,0x00,0x5c,0x00,0x00,0x01,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x02,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x37,0x26,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x33,0x32,0x12,0x35,0x34, 0x2e,0x03,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x04,0x17,0x01,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0xe3,0xec,0x71,0x4f,0x26,0x1d,0x2a,0x44,0x67,0xe9,0xc2,0x6f,0x35,0x64,0xb5,0x71,0x62,0xcb,0x6a,0x47,0x9f,0x69,0x49,0x68,0x69,0x48,0x36,0x57, 0x16,0x27,0x1c,0x54,0x7a,0x7f,0x62,0x76,0x86,0x56,0x5d,0xa3,0x39,0x6d,0x81,0x1f,0x3c,0x59,0x73,0xb3,0x78,0x6a,0x3e,0x8b,0x66,0x56,0x01,0x2a,0x96,0xfd,0x51,0x27,0x2e,0x24,0x17,0x20,0x39,0xf9,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x05,0x66,0x71,0x2d,0x12,0x2d,0x1e,0x1d,0x2e,0x28,0x59,0x74,0x93,0xcf,0x8f,0xc0,0xfe,0xc6,0xae, 0x81,0x6f,0x78,0x78,0x69,0x49,0x4b,0x69,0x3b,0x30,0x32,0x4c,0x74,0x01,0x4f,0x72,0x72,0x97,0xd8,0xd4,0x9c,0xe5,0x73,0x81,0x01,0x1d,0xfc,0x65,0x92,0x6c,0x4c,0x3c,0x40,0x2b,0x43,0x57,0x3a,0x5f,0x82,0x68,0x53,0xfc,0x2e,0x69,0x77,0x81,0x93,0x39,0x3e,0x4c,0xe4,0xfd,0xf9,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x03, 0x00,0xdd,0xff,0xf2,0x05,0x8a,0x06,0x3d,0x00,0x3d,0x00,0x47,0x00,0x53,0x00,0x00,0x01,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x24,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x05,0x0e,0x02,0x15,0x14,0x16,0x33,0x32, 0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0xa7,0x32,0x64,0x16,0x2b,0x3a,0x19,0x74,0x65,0x73,0x8f,0x86,0x6d,0x50,0x7a,0x5a,0xe5,0x6f,0x80,0x85,0x3d,0x5c,0xbc,0xa9,0x01,0x42,0x85,0x4b,0x1e, 0xa8,0xb4,0xcc,0xfe,0xf4,0x87,0x98,0x44,0x4c,0x4a,0x41,0xc6,0x32,0x7a,0xcb,0x70,0x48,0x6b,0x6c,0xf8,0x5d,0x42,0x26,0x3e,0x42,0x2f,0x3d,0x5e,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x02,0x0e,0x4c,0x3a,0x16,0x70,0x42,0x4f,0x34,0x3c,0x70,0x56,0x5d,0x70,0x34,0x55,0x89,0x73,0xfa,0xd7,0xa5,0xe0,0x8c,0x2c,0x54,0x2f,0x34,0x41,0x2f, 0xa3,0xb0,0x86,0xa0,0x34,0x45,0x23,0x6d,0xa7,0xa2,0xb9,0xd4,0x75,0x5e,0x74,0x71,0xc4,0x70,0x6b,0x49,0x49,0x69,0xfe,0xb6,0x50,0x2c,0x1f,0x20,0x27,0x01,0x7b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x04,0x00,0xdd,0xff,0xf2,0x05,0x8a,0x06,0x3d,0x00,0x47,0x00,0x51,0x00,0x5c,0x00,0x68,0x00,0x00,0x01,0x14,0x06,0x23, 0x06,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x17,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x25,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x36, 0x36,0x35,0x35,0x33,0x01,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x03,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x05,0x77,0xd0,0xa8,0x23,0x72,0x80,0xc7,0x9c,0x4c,0x4a,0x41,0xc6,0x32,0x7a,0xcb,0x70,0x48,0x6b,0x6c,0x47,0x32,0x64,0x16,0x2b,0x3a,0x19, 0x74,0x65,0x73,0x8f,0x86,0x6d,0x50,0x7a,0x5a,0xe5,0x6f,0x80,0x85,0x3d,0x68,0xe7,0x01,0x20,0x0f,0x4c,0x66,0x4d,0x4a,0x67,0x0b,0x2b,0x3f,0xa5,0xfe,0x7f,0x5d,0x42,0x26,0x3e,0x42,0x2f,0x3d,0x7d,0x35,0x2a,0x17,0x1c,0x25,0x31,0xf7,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x05,0xd5,0x99,0xbe,0x23,0x3c,0x31,0x4a,0xd9,0xb6,0xb9,0xd4, 0x75,0x5e,0x74,0x71,0xc4,0x70,0x6b,0x49,0x49,0x69,0x4c,0x3a,0x16,0x70,0x42,0x4f,0x34,0x3c,0x70,0x56,0x5d,0x70,0x34,0x55,0x89,0x73,0xfa,0xd7,0xa6,0xc8,0x9e,0x6b,0x08,0x35,0x5c,0x49,0x6b,0x71,0x47,0x18,0x1d,0x1c,0x6b,0x4b,0x5e,0xfa,0x87,0x50,0x2c,0x1f,0x20,0x27,0x03,0xf6,0x21,0x29,0x1c,0x29,0x27,0x1e,0x18,0x30,0xfd,0x83, 0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x03,0x00,0x44,0xff,0xf2,0x06,0x24,0x06,0xac,0x00,0x4d,0x00,0x58,0x00,0x64,0x00,0x00,0x01,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36, 0x33,0x32,0x05,0x07,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0xfe, 0x36,0x57,0x15,0x2e,0x40,0x54,0x94,0x54,0x5b,0x40,0x63,0x79,0x5a,0x5b,0x6f,0x5d,0x39,0x62,0x50,0x93,0x59,0x35,0x74,0xd1,0xa0,0x70,0x6f,0x92,0x5d,0xa7,0x01,0x70,0x46,0x8f,0xa7,0x5a,0x3f,0x1d,0x28,0x48,0x5f,0xfb,0xed,0x69,0x84,0xe1,0x82,0x9d,0x6d,0x71,0x98,0x87,0xe1,0x7e,0x76,0xcc,0x78,0x48,0x6b,0x6c,0xf0,0x14,0x25,0x21, 0x1a,0x1a,0x25,0xf4,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x03,0x50,0x3b,0x30,0x43,0xe3,0x6e,0x71,0xc0,0x6e,0x37,0x6f,0x87,0x62,0x7f,0x7f,0x62,0x87,0x6d,0x39,0x88,0xe6,0x80,0xa4,0xa7,0x7b,0x70,0x38,0x27,0x7e,0x4e,0x58,0x7d,0xbb,0x8b,0x43,0x4f,0x1e,0x2e,0x1d,0x20,0x2f,0x24,0x5d,0xb8,0xfe,0xfe,0xcb,0xaf,0xfe,0xd5,0xaa,0x6a, 0x6a,0x94,0x01,0x04,0x9f,0xa1,0x01,0x3a,0xb2,0x6b,0x49,0x49,0x69,0xfd,0xd9,0x14,0x57,0x17,0x2f,0x35,0x32,0x2a,0x4b,0x02,0x5b,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x03,0x00,0x9a,0xfd,0xeb,0x05,0xce,0x04,0xa5,0x00,0x2d,0x00,0x37,0x00,0x43,0x00,0x00,0x01,0x24,0x33,0x32,0x12,0x15,0x11,0x23,0x11,0x34,0x26,0x26, 0x23,0x22,0x06,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x32,0x01,0x16,0xc4,0xd3,0xef,0xa8,0x4d, 0x82,0x4b,0x4c,0xee,0x5f,0x39,0x39,0x57,0x74,0x44,0x49,0x68,0x69,0x48,0x3b,0x32,0x17,0x1a,0x22,0x48,0x41,0x57,0x66,0x70,0x4a,0x48,0x5f,0x44,0x29,0x3d,0x1b,0x24,0x26,0x19,0x2c,0x17,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x0f,0x96,0xfe,0xeb,0xf3,0xfb,0x4e,0x04,0xb2,0x66,0xab,0x61,0x4b,0x36,0xa7,0xba,0x55,0xea,0xa3,0x59, 0x69,0x49,0x4b,0x69,0x27,0x34,0x8f,0x37,0xac,0x73,0x22,0x69,0x52,0x4c,0x70,0x3c,0x92,0x5a,0x2a,0x1b,0x1b,0x30,0xfc,0xca,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x04,0x00,0xb9,0xfe,0xa4,0x05,0xae,0x04,0xa5,0x00,0x4a,0x00,0x5d,0x00,0x67,0x00,0x73,0x00,0x00,0x01,0x36,0x36,0x33,0x32,0x16,0x11,0x10,0x02,0x06,0x07,0x16, 0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x06,0x07,0x07,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x25,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x07,0x06,0x07,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x01,0x14,0x16, 0x33,0x32,0x36,0x37,0x36,0x24,0x33,0x32,0x17,0x36,0x36,0x35,0x35,0x01,0x06,0x06,0x05,0x34,0x27,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x43,0x1d,0xd2,0x3c,0xa8,0x98,0x19,0x38,0x34,0x5e,0x6b,0x48,0x49,0x6a,0x15,0x5b,0x45,0xbc,0x86,0x8c,0x3e,0x63,0x6e,0xae,0xbf, 0x02,0x0d,0x7d,0x54,0x1c,0x3c,0x40,0x56,0xa3,0x22,0x0f,0x14,0x39,0x4a,0x5a,0x36,0x58,0x60,0x39,0x2c,0x0d,0x62,0x3f,0x48,0x6b,0x6c,0x47,0x74,0xcf,0x7a,0x5c,0xa6,0x66,0x44,0x9c,0xfe,0x62,0x21,0x16,0x1c,0x60,0x60,0x82,0x01,0x21,0x42,0x21,0x2c,0x26,0x31,0xfd,0x99,0xae,0x87,0x03,0xb6,0x47,0x3c,0x26,0x1c,0x1c,0x25,0xfd,0x5f, 0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x3f,0x1b,0x49,0xee,0xff,0x00,0xfe,0xff,0xfe,0xf8,0x88,0x1b,0x35,0x7e,0x46,0x6c,0x6c,0x51,0x20,0x26,0x16,0x1e,0x57,0x41,0x2f,0x6a,0x67,0x56,0x95,0x53,0xe5,0x36,0x7a,0x72,0x7d,0x8f,0x3f,0x5a,0x13,0x05,0x03,0x24,0x2a,0x21,0x78,0x7b,0x3a,0x70,0x1b,0x44,0x50,0x6b,0x49,0x49,0x69,0x70, 0xc2,0x71,0x71,0xaf,0x5f,0x38,0xfb,0x11,0x1d,0x1f,0x25,0x2e,0x3e,0x68,0x06,0x19,0x7f,0x49,0x42,0xfe,0xf0,0x4d,0x5b,0x46,0x35,0x20,0x24,0x31,0x19,0x29,0x26,0x02,0xb8,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x02,0x00,0x15,0xff,0xf2,0x06,0x52,0x04,0xa1,0x00,0x33,0x00,0x3f,0x00,0x00,0x01,0x12,0x11,0x14,0x06,0x06, 0x23,0x22,0x26,0x26,0x35,0x37,0x36,0x35,0x10,0x21,0x22,0x06,0x15,0x10,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x10,0x03,0x01,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x05,0xb0,0xa2,0x70,0xcd,0x84, 0x78,0xca,0x6a,0x03,0x0c,0xfe,0xe9,0x88,0x97,0x5e,0x17,0x50,0x30,0x48,0x6b,0x6c,0x47,0x6e,0xba,0x76,0xf3,0xcf,0xcf,0xf6,0x06,0x07,0x91,0x83,0x78,0x8d,0x9c,0xfc,0xa9,0x1a,0x27,0x27,0x1a,0x1a,0x26,0x26,0x04,0x9f,0xfe,0x8d,0xfe,0xdf,0x9f,0xf6,0x84,0x5f,0xb4,0x7a,0x56,0xcd,0x22,0x01,0x47,0xc6,0xb2,0xfe,0xf2,0x83,0x27,0x2f, 0x6b,0x49,0x49,0x69,0xb0,0x01,0x49,0xa5,0xf4,0x01,0x1d,0xfd,0xdc,0x30,0x6b,0x6c,0x33,0x7a,0x8c,0xbb,0xc8,0x01,0x1a,0x01,0x42,0xfb,0xfe,0x27,0x1a,0x1b,0x27,0x26,0x1c,0x1b,0x26,0x00,0x00,0x02,0x01,0x09,0x01,0xb4,0x04,0x6f,0x05,0x9a,0x00,0x0c,0x00,0x1c,0x00,0x00,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26, 0x26,0x27,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x02,0xbd,0x79,0x93,0x8d,0x7f,0x80,0x8a,0x42,0x78,0x50,0x74,0xcb,0x73,0x6d,0xc8,0x7d,0x75,0xcb,0x74,0x6f,0xca,0x05,0x09,0xc9,0x9a,0xa5,0xbc,0xbb,0xa6,0x62,0xa6,0x5b,0x91,0x86,0xe6,0x89,0x92,0xe3,0x7c,0x80,0xe4,0x8d,0x8c,0xe6,0x83,0x00, 0x00,0x01,0x01,0x22,0xff,0x83,0x04,0x56,0x05,0x9a,0x00,0x1d,0x00,0x00,0x05,0x36,0x00,0x35,0x34,0x02,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x24,0x33,0x32,0x16,0x12,0x15,0x14,0x02,0x00,0x07,0x01,0xa7,0xfa,0x01,0x0b,0x5d,0x3d,0x35,0xb1,0x60,0x42,0x39,0x9b,0x39,0x51,0xa5,0x01,0x14,0x6f,0x4b, 0x78,0x49,0x85,0xfe,0xf0,0xb0,0x19,0xe7,0x01,0xb7,0xba,0x97,0x01,0x33,0x35,0x39,0x18,0x4b,0xb0,0x43,0x4d,0x51,0xe6,0x5f,0x3a,0x78,0x5a,0x88,0xfe,0xed,0x90,0x9b,0xfe,0xae,0xfe,0x9b,0x9a,0x00,0x00,0x01,0x00,0xf8,0xff,0x83,0x04,0x80,0x05,0x9a,0x00,0x23,0x00,0x00,0x05,0x26,0x02,0x26,0x26,0x23,0x22,0x07,0x27,0x36,0x33,0x32, 0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x16,0x12,0x13,0x03,0xe7,0x21,0x4d,0x63,0x85,0x57,0x74,0x5b,0x1b,0x6d,0xb8,0x41,0x41,0x5d,0x79,0x77,0x6a,0x53,0xf2,0x6d,0x42,0xa3,0xe7,0x6b,0xba,0xd0,0x38,0x61,0x64,0x62,0x88,0x1c,0x7d,0xf0,0x01,0x05,0xa0,0x59,0x36, 0x8c,0x3b,0x18,0x54,0xc7,0x48,0x59,0x63,0x90,0x73,0x85,0x90,0x7f,0x98,0x8b,0x5d,0x9f,0x89,0x5d,0x5f,0xfe,0x91,0xfe,0xff,0x00,0x01,0x01,0x0e,0xff,0x83,0x04,0x69,0x05,0x9a,0x00,0x31,0x00,0x00,0x01,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x15,0x14, 0x06,0x06,0x07,0x16,0x17,0x07,0x02,0x21,0x22,0x07,0x27,0x36,0x33,0x32,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x01,0xa0,0x8c,0x8f,0x33,0x2e,0x59,0x4a,0x5c,0x69,0x4e,0xec,0x60,0x3c,0x8b,0xee,0x71,0x9c,0xbf,0xb1,0x8e,0x2d,0x63,0x53,0x88,0x5b,0x8d,0xa8,0xfe,0xa1,0x37,0x36,0x37,0x5f,0x69,0x85,0x6c,0x59,0x7c,0x78, 0x73,0x43,0x81,0x23,0x03,0x68,0x36,0x08,0x41,0x67,0x32,0x4b,0x4e,0x7f,0x5b,0x7b,0x77,0x79,0x99,0x84,0x8b,0x92,0x52,0x93,0x59,0x78,0x75,0x37,0x69,0xc4,0x4e,0x01,0x68,0x14,0x81,0x23,0x28,0x2c,0x97,0x46,0x53,0x5e,0x18,0x11,0x00,0x01,0x00,0xb7,0xff,0x83,0x04,0xc0,0x05,0x9a,0x00,0x22,0x00,0x00,0x01,0x20,0x11,0x34,0x37,0x22, 0x0e,0x02,0x15,0x14,0x12,0x12,0x04,0x17,0x07,0x26,0x00,0x00,0x02,0x35,0x34,0x36,0x24,0x33,0x32,0x17,0x06,0x15,0x14,0x16,0x33,0x37,0x07,0x06,0x04,0x68,0xfe,0x53,0x0e,0x2e,0xa9,0x76,0x1b,0x86,0xfb,0x01,0x1c,0x77,0x30,0x97,0xfe,0xb0,0xfe,0xe9,0x90,0x57,0x01,0x32,0x83,0x8e,0x27,0x13,0x8a,0x91,0x40,0x10,0x2a,0x02,0xa8,0x01, 0xc3,0x57,0x50,0x1c,0x23,0x2a,0x45,0x92,0xfe,0xa9,0xfe,0xad,0xf2,0x2b,0x88,0x32,0x01,0x13,0x01,0x80,0x01,0x7e,0xac,0x6f,0x61,0x58,0x29,0x9f,0x3f,0xb0,0x9e,0x05,0x9d,0x05,0x00,0x01,0x00,0x78,0xff,0x83,0x04,0xff,0x05,0xae,0x00,0x16,0x00,0x00,0x01,0x12,0x12,0x17,0x07,0x26,0x02,0x03,0x06,0x23,0x22,0x26,0x02,0x03,0x37,0x17, 0x12,0x16,0x33,0x32,0x37,0x02,0x03,0x03,0x36,0x19,0xee,0xc2,0x4c,0x98,0xe5,0x46,0xa6,0x81,0x73,0x93,0x48,0x03,0xa5,0x08,0x09,0x69,0x6d,0x3c,0x91,0x3c,0x0b,0x05,0xae,0xfd,0xd5,0xfd,0x09,0x8f,0x7a,0x62,0x01,0x9b,0x01,0x24,0x56,0x9e,0x01,0x57,0x01,0x57,0x14,0x9d,0xfe,0xbf,0xf1,0x4e,0x01,0x2c,0x01,0x41,0x00,0x01,0x00,0x6c, 0xff,0xf6,0x05,0x0b,0x05,0x9a,0x00,0x2c,0x00,0x00,0x01,0x12,0x12,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x07,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x02,0x03,0x01,0x10,0x0d,0x94,0xef,0x9d,0x39,0x8f,0x5c,0x61,0x61,0x70, 0x7f,0x73,0x40,0xdb,0xaf,0x53,0xa0,0x5b,0x4e,0x9a,0x65,0x67,0x7a,0x5f,0x63,0x99,0x7d,0x57,0x35,0x8c,0xee,0x74,0xbe,0xfe,0xe1,0xb5,0x1f,0x04,0x66,0xfe,0xd1,0xfe,0x33,0xe3,0x5a,0x91,0x52,0x42,0x6d,0x31,0x38,0x3f,0x62,0x7a,0x4e,0x95,0xc0,0x45,0x42,0x73,0x69,0x6c,0x5a,0x3c,0x6a,0x34,0x51,0x4b,0x54,0x68,0x41,0x70,0xdb,0x8f, 0xf0,0x01,0xf1,0x01,0x75,0x00,0x00,0x01,0x00,0x3b,0xff,0xf6,0x05,0x3c,0x05,0xae,0x00,0x26,0x00,0x00,0x01,0x0a,0x02,0x23,0x22,0x26,0x27,0x36,0x37,0x36,0x12,0x35,0x34,0x26,0x23,0x22,0x02,0x03,0x27,0x12,0x12,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x02,0x02,0x07,0x16,0x33,0x32,0x36,0x12,0x12,0x13,0x05,0x3c,0x07,0x72,0xf7,0xd9, 0x71,0x98,0x45,0x0a,0x19,0x89,0x6d,0x67,0x6b,0x79,0x90,0x1b,0x8d,0x1c,0x68,0xb7,0x93,0x6f,0x9c,0x54,0x3e,0x73,0x3a,0x34,0x2c,0x83,0xa4,0x61,0x31,0x0a,0x05,0xae,0xfd,0xac,0xfd,0xa6,0xfe,0xf6,0x29,0x2a,0x18,0x2c,0xef,0x01,0x4f,0x8a,0x92,0x81,0xfe,0xe8,0xfe,0xbd,0x2f,0x01,0x1b,0x01,0x19,0x89,0x65,0xb1,0x68,0x69,0xfe,0xf8, 0xfe,0xe9,0x5c,0x10,0x77,0x01,0x01,0x01,0xc4,0x01,0xd7,0x00,0x00,0x01,0x00,0xcb,0xff,0x83,0x04,0xad,0x05,0xae,0x00,0x15,0x00,0x00,0x05,0x26,0x02,0x26,0x26,0x23,0x22,0x07,0x27,0x3e,0x02,0x37,0x17,0x04,0x07,0x36,0x33,0x32,0x04,0x12,0x17,0x04,0x14,0x12,0x80,0xa2,0xb4,0x5b,0x83,0x60,0x23,0x2b,0x9f,0xda,0x63,0x6a,0xfe,0xeb, 0x87,0x38,0x3e,0x89,0x01,0x1b,0xda,0x19,0x7d,0x81,0x01,0x4c,0xf6,0x85,0x39,0x7e,0x67,0xef,0xf2,0x56,0x64,0xff,0xf6,0x07,0xfe,0xfe,0x43,0xdb,0x00,0x01,0x00,0xe3,0xff,0x83,0x04,0x95,0x05,0x9a,0x00,0x25,0x00,0x00,0x05,0x26,0x35,0x10,0x12,0x00,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x2e,0x02,0x35, 0x34,0x36,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x02,0x15,0x14,0x17,0x01,0x0e,0x2b,0xce,0x01,0x45,0xbc,0x66,0x6c,0x73,0x4b,0x28,0x85,0x72,0x21,0x7a,0xaa,0x5c,0x36,0x3d,0x3a,0x39,0x1e,0x2b,0x88,0xeb,0x91,0x2e,0x7d,0x95,0xc0,0x01,0x31,0x02,0x4d,0x01,0x44,0x4d,0x45,0x88,0x6b,0x46,0x33,0x1a,0x41,0x54,0x0f,0x91,0x12, 0x54,0x74,0x3d,0x28,0x56,0x3b,0x38,0x5c,0x2d,0x19,0x12,0xfe,0xda,0xfd,0xf6,0xfc,0xc5,0x78,0x00,0x02,0x00,0x47,0xff,0xf1,0x03,0xc8,0x03,0x6e,0x00,0x0f,0x00,0x1b,0x00,0x00,0x01,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0xc8, 0x78,0xd2,0x78,0x78,0xd0,0x77,0x79,0xd0,0x76,0x79,0xd0,0x79,0x97,0xaf,0x7c,0x7c,0xab,0xad,0x7a,0x7e,0xad,0x01,0xaf,0x76,0xce,0x7a,0x79,0xd0,0x75,0x7a,0xd1,0x74,0x75,0xd0,0x7a,0x80,0xb0,0xae,0x82,0x81,0xae,0xb4,0x00,0x01,0x00,0x5a,0xff,0xf1,0x03,0xb5,0x03,0x6e,0x00,0x1b,0x00,0x00,0x13,0x36,0x36,0x33,0x32,0x16,0x16,0x15, 0x14,0x06,0x06,0x23,0x22,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x5b,0x3d,0xe0,0x84,0x79,0xcb,0x75,0x7c,0xd1,0x76,0x85,0xda,0x39,0x89,0x26,0x88,0x59,0x84,0xb0,0xac,0x7e,0x5c,0x93,0x24,0x02,0x68,0x7a,0x8c,0x7a,0xd0,0x75,0x73,0xd1,0x7a,0x91,0x7b,0x37,0x54,0x60,0xab,0x7c,0x7f,0xb9,0x65, 0x58,0x00,0x00,0x01,0x00,0x44,0xfd,0xfe,0x03,0xcc,0x03,0x64,0x00,0x12,0x00,0x00,0x05,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x33,0x14,0x16,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x03,0xcc,0x70,0xc5,0x85,0x92,0xcf,0x6d,0x98,0x4d,0x8d,0x5c,0x88,0x9b,0x97,0x0d,0x91,0xef,0x75,0x6f,0xc7,0x82,0x52,0x8a,0x4d,0xc8,0xb1,0x03,0x5e, 0x00,0x01,0x00,0x5a,0xfd,0xfe,0x03,0xb5,0x03,0x6e,0x00,0x1f,0x00,0x00,0x01,0x01,0x26,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x27,0x01,0x02,0xea,0xfd,0xcb,0x2d,0x2e,0x89,0x26,0x88,0x59,0x83,0xb1,0xab,0x7f,0x5c,0x93,0x24,0x86, 0x3d,0xe0,0x84,0x79,0xcc,0x74,0x7c,0xd1,0x76,0x05,0x05,0x01,0xc2,0xfd,0xfe,0x02,0x7d,0x32,0x54,0x38,0x54,0x60,0xa8,0x7e,0x80,0xb4,0x65,0x58,0x46,0x7a,0x8c,0x78,0xcd,0x75,0x73,0xd1,0x7a,0x01,0xfe,0x07,0x00,0x01,0x00,0x5a,0xfd,0xfe,0x03,0xb5,0x03,0x6e,0x00,0x1f,0x00,0x00,0x13,0x01,0x07,0x23,0x22,0x26,0x26,0x35,0x34,0x36, 0x36,0x33,0x32,0x16,0x17,0x07,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x07,0x01,0x79,0x01,0xb5,0x0b,0x06,0x75,0xd2,0x7c,0x74,0xcb,0x7a,0x84,0xdd,0x40,0x86,0x25,0x93,0x5b,0x7f,0xab,0xb2,0x82,0x59,0x88,0x26,0x89,0x2a,0x32,0xfd,0xe0,0xfd,0xfe,0x01,0xf9,0x01,0x7a,0xd0,0x74,0x74,0xcd,0x79,0x8b, 0x7b,0x46,0x58,0x65,0xb3,0x81,0x7e,0xa8,0x60,0x54,0x38,0x50,0x36,0xfd,0x83,0x00,0x00,0x02,0x00,0x44,0xfd,0xfe,0x03,0xcc,0x03,0x6e,0x00,0x27,0x00,0x33,0x00,0x00,0x01,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x33,0x14,0x16, 0x16,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x11,0x7a,0x52,0x55,0x73,0x82,0x61,0x5f,0x83,0x75,0xd3,0x81,0x86,0xc5,0x70,0x70,0xc6,0x85,0x91,0xcf,0x6d,0x98,0x4d,0x8d,0x5b,0x89,0x9b,0x99,0xfe,0x2b,0x3c,0x28,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x02,0xdf,0x4e,0x0a,0x81, 0x56,0x5b,0x87,0x84,0x5d,0x7b,0xce,0x76,0x76,0xee,0x91,0xfe,0x7a,0x90,0xef,0x76,0x6e,0xc8,0x82,0x56,0x86,0x4d,0xc8,0xb1,0x01,0x6a,0xb0,0xbf,0xfe,0xd2,0x28,0x3b,0x3c,0x27,0x29,0x3b,0x3b,0x00,0x00,0x02,0x00,0x44,0xff,0xf1,0x03,0xcc,0x05,0xe9,0x00,0x2f,0x00,0x3b,0x00,0x00,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x16, 0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x12,0x15,0x23,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x11,0x10,0x21,0x32,0x36,0x35,0x34,0x26,0x27,0x07,0x23,0x22,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0xd3,0x86,0x5c,0x5e,0x85,0x38,0x2a,0x35,0xfb,0xc6,0x8a,0xc6,0x6a, 0x73,0xc5,0x82,0xd9,0xf5,0x98,0x4d,0x8d,0x5c,0x88,0x9b,0x01,0x23,0x94,0x96,0x3a,0x25,0x0a,0x0b,0x5e,0x83,0x7f,0x3c,0x27,0x29,0x3b,0x3b,0x29,0x28,0x3b,0x02,0x7c,0x60,0x84,0x85,0x5e,0x52,0x43,0x1d,0x49,0x37,0x9f,0xbb,0x6a,0xd7,0x8c,0x02,0x54,0x8a,0xdf,0x6e,0xfe,0xf0,0xdb,0x60,0xa0,0x5c,0xbd,0xb2,0xfd,0xe6,0xfe,0xaf,0x61, 0x5b,0x23,0x2d,0x10,0x01,0x83,0x60,0x28,0x3b,0x3b,0x28,0x29,0x3b,0x3c,0x00,0x01,0x00,0x30,0xfe,0x05,0x03,0xe0,0x03,0x6e,0x00,0x32,0x00,0x00,0x05,0x0e,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x07,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06, 0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x03,0xe0,0x07,0x40,0x6d,0x4b,0x50,0x68,0x3a,0x1d,0x35,0x45,0x44,0x34,0x1c,0xaf,0x7c,0x7c,0xab,0x2d,0x7b,0x4a,0x79,0xd0,0x76,0x7a,0xd1,0x77,0x1e,0x32,0x50,0x58,0x35,0x2c,0x28,0x13,0x1d,0x1d,0x15,0x15,0xf9,0x48,0x74,0x46,0x32,0x5d,0x3b,0x3d,0x62,0x6e,0x6b,0x69, 0x6c,0x69,0x34,0x7f,0xa7,0xae,0x82,0x58,0x4a,0x52,0x72,0x82,0x7a,0xd1,0x74,0x72,0xca,0x79,0x34,0x75,0x68,0x7e,0x88,0x88,0x37,0x2a,0x2c,0x09,0x19,0x23,0x48,0x00,0x00,0x02,0x00,0x47,0xff,0xf0,0x03,0xc8,0x03,0x6e,0x00,0x1d,0x00,0x24,0x00,0x00,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x07, 0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x25,0x34,0x26,0x27,0x16,0x17,0x36,0x02,0x6c,0x53,0x72,0xaf,0x7c,0x64,0xa0,0x1a,0x7c,0x9d,0x6e,0x51,0x77,0x84,0x79,0xd1,0x75,0x79,0xd0,0x79,0x9d,0x76,0xfe,0xc5,0x57,0x42,0x0a,0x74,0x1b,0x6f,0x1d,0xb5,0x6e,0x80,0xb0,0x76,0x5e,0x09,0x9b,0x6f,0x4d,0x9d, 0x1d,0x45,0xf8,0x92,0x72,0xc6,0x76,0x75,0xd0,0x7a,0x92,0xfe,0x2f,0xfd,0x45,0x66,0x04,0x91,0x7a,0x2e,0x00,0x02,0x00,0x44,0xfd,0xfe,0x03,0xcc,0x03,0x6e,0x00,0x30,0x00,0x3c,0x00,0x00,0x25,0x34,0x36,0x33,0x33,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x20,0x11,0x11,0x14,0x16,0x33,0x32,0x36,0x36,0x35,0x33,0x14,0x06,0x06,0x23,0x22, 0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x37,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x01,0xd3,0x83,0x5e,0x0b,0x0a,0x25,0x3a,0x97,0x93,0xfe,0xdd,0x98,0x8b,0x5b,0x93,0x48,0x98,0x6e,0xcf,0x91,0x83,0xc4,0x73,0x6a,0xc7,0x89,0xc6,0xfb,0x35,0x2a, 0x38,0x82,0x61,0x5c,0x86,0x7f,0x3b,0x28,0x29,0x3b,0x3c,0x28,0x28,0x3b,0xe3,0x5e,0x83,0x01,0x10,0x2d,0x23,0x5c,0x60,0xfe,0xaf,0xfe,0x6e,0xb1,0xbe,0x4c,0x83,0x5a,0x82,0xc7,0x6f,0x6e,0xe0,0x89,0x01,0xcc,0x8c,0xd8,0x69,0xbc,0x9e,0x37,0x49,0x1d,0x43,0x52,0x5c,0x87,0x84,0x5e,0x29,0x3b,0x3b,0x29,0x28,0x3b,0x3c,0x00,0x00,0x02, 0x00,0x80,0xff,0xf1,0x04,0x08,0x05,0xe9,0x00,0x0f,0x00,0x1a,0x00,0x00,0x01,0x14,0x02,0x23,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x15,0x07,0x10,0x21,0x22,0x06,0x15,0x11,0x10,0x21,0x20,0x11,0x04,0x08,0xf6,0xd8,0x8a,0xc6,0x6a,0x74,0xc7,0x83,0xdb,0xef,0x97,0xfe,0xc9,0x88,0x9b,0x01,0x23,0x01,0x37,0x01,0xc8, 0xd6,0xfe,0xff,0x6a,0xd7,0x8c,0x02,0x54,0x85,0xe3,0x6f,0xf2,0xdc,0x0d,0x01,0x4c,0xbd,0xb2,0xfd,0xe6,0xfe,0xaf,0x01,0x6f,0x00,0x01,0x00,0xa3,0xff,0xe7,0x03,0xe5,0x05,0xe8,0x00,0x09,0x00,0x00,0x13,0x25,0x33,0x11,0x25,0x17,0x05,0x23,0x11,0x05,0xa3,0x01,0xd1,0x1c,0x01,0x2b,0x2a,0xfe,0x30,0x1c,0xfe,0xd4,0x05,0x16,0xd2,0xfa, 0xcb,0x86,0x80,0xd2,0x05,0x35,0x83,0x00,0x00,0x01,0x00,0x9b,0x00,0x00,0x03,0xed,0x05,0xe9,0x00,0x22,0x00,0x00,0x13,0x11,0x33,0x15,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x36,0x36,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x15,0x9b,0x97,0x73,0x87,0xca,0xf7,0x51,0x92,0xaa, 0x80,0x66,0x37,0x94,0x43,0x77,0x9d,0x91,0x7d,0x42,0xaa,0x80,0x4e,0x83,0x29,0x04,0x12,0x01,0xd1,0x45,0x4b,0xed,0xbd,0x57,0x9f,0x9d,0x85,0x65,0x66,0x5d,0x2e,0xd1,0xe0,0x42,0x7b,0x7d,0x7b,0x71,0x81,0x7a,0x3e,0x7b,0xa0,0x4e,0x3c,0xbe,0x00,0x01,0x00,0x5d,0x00,0x00,0x04,0x2b,0x05,0xe3,0x00,0x12,0x00,0x00,0x33,0x01,0x33,0x03, 0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x07,0x03,0x5d,0x01,0xeb,0xa7,0xd1,0x28,0x2c,0x7d,0xcb,0x71,0x97,0xac,0x7e,0x44,0x3f,0xe9,0x05,0xe3,0xfd,0x83,0x08,0x6a,0xbd,0x70,0xfe,0x29,0x01,0xa7,0x7f,0xb9,0x1e,0xfd,0x3f,0x00,0x01,0x00,0x31,0xff,0xe7,0x04,0x56,0x05,0xe3,0x00,0x09,0x00,0x00,0x33,0x01, 0x33,0x11,0x25,0x17,0x05,0x23,0x11,0x01,0x31,0x02,0x1d,0xb3,0x01,0x2c,0x29,0xfe,0x30,0x1c,0xfe,0x68,0x05,0xe3,0xfa,0xcf,0x87,0x80,0xd2,0x04,0x7a,0xfb,0x9f,0x00,0x00,0x02,0x00,0x57,0xff,0xf1,0x04,0x30,0x05,0xe3,0x00,0x11,0x00,0x1d,0x00,0x00,0x01,0x33,0x15,0x23,0x11,0x14,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21, 0x11,0x33,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x36,0x35,0x11,0x03,0xb6,0x7a,0x7a,0x67,0xbb,0x7a,0xd0,0xf3,0xf1,0xc9,0x01,0x0e,0x97,0xfe,0x62,0x8d,0x9d,0xa6,0x8e,0x40,0x78,0x45,0x03,0x6e,0x8f,0xfe,0xa0,0x7c,0xb3,0x5f,0xee,0xd0,0xcb,0xf4,0x02,0x75,0xfc,0xfc,0xa4,0x94,0x8a,0x9d,0x3a,0x64,0x3f,0x01,0x82,0x00,0x02, 0x00,0x57,0x00,0x00,0x04,0x30,0x05,0xe9,0x00,0x11,0x00,0x1d,0x00,0x00,0x01,0x23,0x11,0x23,0x11,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x33,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x04,0x30,0x7a,0x97,0xfe,0xf2,0xca,0xf0,0xf3,0xd0,0x79,0xbc,0x67,0x7a,0xfe,0xef,0x46,0x77,0x40,0x8e, 0xa6,0x9d,0x8d,0x01,0x07,0x02,0x6c,0xfd,0x94,0x02,0x6c,0xf4,0xcb,0xcf,0xef,0x5f,0xb3,0x7c,0xfe,0xa1,0x01,0x81,0x3f,0x65,0x39,0x9c,0x8a,0x96,0xa2,0x00,0x00,0x01,0x00,0xd7,0x00,0x00,0x03,0xb1,0x05,0xe3,0x00,0x07,0x00,0x00,0x13,0x21,0x01,0x21,0x15,0x21,0x01,0x21,0xd7,0x02,0xa8,0xfe,0x4f,0x01,0xe3,0xfd,0x50,0x01,0xaa,0xfe, 0x2c,0x05,0xe3,0xfa,0xac,0x8f,0x05,0x54,0x00,0x02,0x00,0x83,0xff,0xf1,0x04,0x04,0x05,0xfe,0x00,0x28,0x00,0x34,0x00,0x00,0x01,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27, 0x37,0x13,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x03,0x5e,0x4c,0x5a,0x6e,0x60,0x5f,0x6f,0x78,0xd2,0x78,0x78,0xd0,0x77,0x6a,0x63,0x5e,0x6f,0x5d,0x4d,0x63,0x36,0x3f,0xad,0x7a,0x7e,0xad,0x40,0x39,0x66,0x13,0xaf,0x7c,0x7c,0xab,0xad,0x7a,0x7e,0xad,0x05,0xfb,0x3c,0xb3,0x6d,0x6f,0xca,0x3e,0x3d,0xc7,0x75,0x76, 0xce,0x7a,0x79,0xd0,0x75,0x72,0xc7,0x40,0x3d,0xc8,0x72,0x6e,0xb4,0x3d,0x6a,0x2a,0x7e,0x4d,0x81,0xae,0xb4,0x7b,0x4b,0x80,0x2b,0x66,0xfb,0xb4,0x80,0xb0,0xae,0x82,0x81,0xae,0xb4,0x00,0x00,0x02,0x00,0x83,0xff,0xdc,0x04,0x04,0x05,0xe9,0x00,0x27,0x00,0x33,0x00,0x00,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16, 0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x07,0x13,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x02,0xf4,0x39,0x40,0xae,0x7d,0x7a,0xad,0x3f,0x36,0x63,0x4d,0x5d,0x6f,0x5e,0x61,0x6c,0x78,0xd0,0x77,0x78,0xd2,0x78,0x6f, 0x5f,0x61,0x6d,0x5b,0x4d,0x11,0xae,0x7d,0x7a,0xad,0xa9,0x7e,0x7e,0xad,0x46,0x2a,0x80,0x4b,0x7c,0xb3,0xae,0x81,0x4d,0x7e,0x29,0x6b,0x3d,0xb4,0x6e,0x71,0xc9,0x3d,0x3e,0xca,0x71,0x76,0xd0,0x78,0x7a,0xce,0x76,0x75,0xc6,0x3e,0x3f,0xc9,0x6f,0x6d,0xb3,0x3e,0x04,0x4e,0x7c,0xb3,0xae,0x81,0x81,0xae,0xb1,0x00,0x00,0x02,0x01,0x48, 0xff,0xec,0x04,0xbc,0x05,0xa3,0x00,0x0b,0x00,0x17,0x00,0x00,0x01,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x03,0x10,0x02,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x12,0x04,0xbc,0xd6,0xe5,0xe0,0xd9,0xda,0xdf,0xe0,0xdb,0xa0,0x8c,0x8f,0x8a,0x8d,0x88,0x8f,0x92,0x89,0x02,0xc8,0xfe,0x7a,0xfe,0xaa,0x01,0x58,0x01, 0x84,0x01,0x78,0x01,0x63,0xfe,0xa0,0xfe,0x85,0x01,0x3c,0x01,0x13,0xfe,0xe1,0xfe,0xd0,0xfe,0xc9,0xfe,0xe7,0x01,0x11,0x00,0x00,0x01,0x01,0x21,0xff,0xec,0x04,0xe2,0x05,0xa3,0x00,0x2c,0x00,0x00,0x01,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x00,0x11,0x14,0x02,0x04, 0x23,0x22,0x27,0x27,0x16,0x33,0x32,0x36,0x12,0x35,0x10,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x02,0xcd,0x29,0x30,0x4c,0x34,0x3e,0x4c,0x94,0x6f,0x9e,0xbc,0x77,0xd6,0x84,0xeb,0x01,0x05,0xaf,0xfe,0xcf,0xc4,0x48,0x50,0x1b,0x5f,0x68,0x93,0xdc,0x81,0xfe,0xa4,0x88,0x9d,0x68,0x54,0x3a,0x02,0xf2,0x0b,0x42,0x27,0x32,0x4e,0x5a, 0x3f,0x68,0x95,0xd9,0xb3,0x7b,0xd3,0x79,0xfe,0xa1,0xfe,0xb6,0xe2,0xfe,0x95,0xc1,0x0a,0xa5,0x19,0x92,0x01,0x1e,0xb6,0x02,0x2f,0xbd,0x90,0x66,0x88,0x00,0x00,0x02,0x00,0x74,0xff,0xec,0x05,0x8f,0x06,0x3b,0x00,0x4c,0x00,0x55,0x00,0x00,0x13,0x16,0x16,0x15,0x11,0x14,0x33,0x32,0x36,0x37,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36, 0x35,0x11,0x34,0x23,0x22,0x06,0x07,0x07,0x27,0x26,0x23,0x22,0x06,0x15,0x15,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x27,0x01,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x27, 0xa4,0x66,0x65,0x57,0x24,0x47,0x3e,0x6c,0x68,0x30,0x5f,0x5a,0x53,0x24,0x20,0x2c,0x62,0x22,0x5a,0x2f,0x23,0x2c,0x5c,0x52,0x26,0x2e,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0x65,0x6d,0x92,0x6a,0x2d,0x83,0x41,0x69,0x76,0x85,0x59,0x34,0x56,0x54,0x59,0x37,0x36,0x5e,0x5b,0x5f,0x37,0x78,0x77,0x26,0x35,0x02,0x1d,0x22,0x1c,0x37,0x4d, 0x28,0x06,0x3b,0x13,0x72,0x6e,0xfb,0xa2,0x72,0x11,0x17,0x28,0x19,0x1e,0x19,0x38,0x20,0x03,0xbd,0x8a,0x46,0x38,0x2a,0x33,0x74,0x55,0x56,0xbd,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59,0x4e,0x01,0xfd,0xa8,0x9b,0x82,0x3a,0x48,0x9b,0x8b,0xfc,0x21,0x45,0x6d,0x19,0x1e,0x19,0x19,0x1e,0x19,0x67,0x6d,0x04,0x44,0x5b,0x43,0x0f,0xfc,0xd9, 0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x02,0x00,0x43,0xff,0xec,0x05,0xc1,0x05,0xa3,0x00,0x28,0x00,0x31,0x00,0x00,0x21,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x32,0x16,0x15,0x11,0x25,0x14, 0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x05,0x21,0x82,0x62,0x69,0x82,0xa0,0x82,0x69,0x63,0x81,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0xd4,0xb0,0x64,0xa2,0x35,0x6c,0xcf,0xaf,0xd5,0xfb,0x22,0x22,0x1c,0x37,0x4d,0x28,0x04,0x1e,0x70,0x89,0x8a,0x6f,0xfb,0xe2,0x04,0x1e,0x6f,0x8a,0x8a,0x6f,0xfd,0xc0,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59, 0x4e,0x03,0x89,0xb5,0xd2,0x44,0x42,0x86,0xd1,0xb6,0xfb,0xe4,0xba,0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x00,0x01,0x00,0xf0,0xff,0xec,0x05,0x14,0x06,0x27,0x00,0x3d,0x00,0x00,0x01,0x34,0x36,0x33,0x26,0x26,0x23,0x22,0x15,0x14,0x16,0x17,0x07,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x11,0x10,0x00,0x25,0x36,0x36,0x35,0x35, 0x33,0x15,0x14,0x06,0x06,0x07,0x0e,0x02,0x15,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x03,0xef,0x51,0x37,0x08,0x57,0x44,0xb6,0xe7,0xf1,0x1a,0xc0,0x64,0x55,0x77,0x78,0x3c,0x95,0xb3,0x01,0x00,0x01,0x1e,0xa9,0x97,0xa0,0x5a,0xac,0xa3,0xa4,0xb7,0x5a,0x6a, 0x64,0x2e,0x77,0x7d,0x2d,0x93,0xa6,0xb8,0x9f,0x96,0xb3,0x58,0x44,0x39,0x50,0x02,0x26,0x39,0x4f,0x3b,0x44,0xdc,0x90,0xdd,0x56,0xa0,0x21,0x11,0x12,0xc2,0x9f,0x01,0x0f,0x01,0x05,0x01,0x2e,0x4e,0x2d,0x61,0x41,0x7b,0x73,0x56,0x81,0x58,0x2b,0x2c,0x82,0xc7,0x8b,0xd6,0x83,0x89,0x0f,0x0f,0x01,0x3d,0xd9,0x93,0xb1,0xc8,0xcb,0xa7, 0x4c,0x5e,0x4f,0x00,0x00,0x02,0x00,0xd6,0xff,0xec,0x05,0x2e,0x06,0x3b,0x00,0x4e,0x00,0x5a,0x00,0x00,0x01,0x06,0x06,0x15,0x15,0x14,0x06,0x06,0x23,0x06,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x37,0x24,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x26,0x26,0x23,0x22,0x06,0x15,0x14, 0x16,0x17,0x07,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x36,0x37,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x3e,0x02,0x35,0x35,0x34,0x36,0x37,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x05,0x2e,0x37,0x23,0x7d,0xf5,0x8f,0xae,0xaf,0x6a,0x64,0x2e,0x77,0x7d,0x2d,0xfe,0xc7,0xc5, 0x92,0x96,0xb3,0x58,0x44,0x39,0x50,0x51,0x37,0x08,0x57,0x44,0x53,0x63,0xf9,0xdf,0x1a,0xc0,0x64,0x55,0x77,0x78,0x3c,0x95,0xb3,0x43,0x8b,0x72,0x61,0x7a,0x62,0x5f,0x84,0x1b,0x41,0x62,0x38,0x67,0x64,0xfd,0x3f,0x30,0x23,0x24,0x31,0x31,0x24,0x23,0x30,0x05,0xb1,0x10,0x45,0x58,0x53,0x56,0x80,0x47,0x1d,0xbe,0xaf,0x86,0x83,0x89, 0x0f,0x0f,0x01,0x7c,0xf5,0x8b,0xb8,0xcb,0xa7,0x4c,0x5e,0x4f,0x3a,0x39,0x4f,0x3b,0x44,0x60,0x53,0x7a,0xc7,0x3d,0xa0,0x21,0x11,0x12,0xc2,0x9f,0xbf,0x7f,0xa2,0x7d,0x2a,0x43,0x70,0x5f,0x83,0x86,0x5b,0x34,0x33,0x01,0x2e,0x4b,0x25,0x88,0x6f,0x71,0x13,0xfe,0x57,0x23,0x30,0x30,0x23,0x24,0x31,0x31,0x00,0x01,0x01,0x0f,0xff,0xec, 0x04,0xf5,0x06,0x3b,0x00,0x3a,0x00,0x00,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x12,0x11,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x37,0x36,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x16,0x17,0x36,0x33,0x32,0x00,0x11,0x15,0x10,0x02,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x02,0xe0,0x16,0x3a,0x54,0x68,0x9c,0x89,0xb3,0xa9,0xac,0xa5,0x6d,0xba,0x2e,0x65,0x11,0x0c,0x04,0x2f,0x2d,0x2f,0x60,0x6c,0x02,0x70,0x74,0xfc,0x01,0x09,0xff,0xf1,0x84,0xd6,0x77,0xbc,0x9e,0x49,0x77,0x43,0x4c,0x3e,0x35,0x4b,0x30,0x02,0x9d,0x16,0x88,0x66,0x90,0xbd,0x01,0x08,0x01,0x13,0x9e,0xef,0xed,0x63,0x4e, 0x72,0x26,0x1b,0x15,0x19,0x2a,0x3e,0x0c,0x8a,0x13,0x72,0x4b,0x38,0xfe,0xc8,0xfe,0xd0,0xba,0xfe,0xbd,0xfe,0xae,0x79,0xd3,0x7b,0xb3,0xd9,0x44,0x76,0x43,0x3f,0x5a,0x4f,0x31,0x27,0x42,0x00,0x02,0x00,0x8f,0xff,0xec,0x05,0x74,0x06,0x3b,0x00,0x37,0x00,0x40,0x00,0x00,0x01,0x16,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x11, 0x34,0x26,0x23,0x22,0x06,0x07,0x27,0x26,0x23,0x22,0x06,0x15,0x11,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x27,0x01,0x14,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x04,0xa9,0x66,0x65,0x85,0x72,0x72,0x7f,0x28,0x30,0x23,0x63, 0x52,0x2b,0x5a,0x54,0x26,0x2e,0x48,0x74,0x45,0x75,0x5b,0x62,0x6f,0x65,0x6d,0x91,0x6a,0x6c,0x84,0x6a,0x76,0x54,0x27,0x2d,0x29,0x31,0xfc,0xb5,0x22,0x1c,0x37,0x4d,0x28,0x06,0x3b,0x15,0x6e,0x65,0xfb,0x6d,0x64,0x70,0x69,0x5d,0x03,0xdb,0x46,0x44,0x49,0x5f,0x33,0x74,0x55,0x56,0xfd,0x73,0x10,0x5f,0x83,0x3b,0x58,0x6d,0x59,0x4e, 0x03,0xcd,0xa8,0x9b,0x82,0x82,0x9d,0x89,0xfc,0x67,0x6c,0x39,0x39,0x04,0x2c,0x57,0x3c,0x08,0xfb,0x09,0x24,0x28,0x52,0x25,0x63,0x0b,0x00,0x01,0x01,0x0b,0xff,0xec,0x04,0xf9,0x06,0x27,0x00,0x45,0x00,0x00,0x01,0x14,0x0e,0x02,0x07,0x0e,0x04,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x17,0x16,0x16,0x17,0x32,0x36,0x35,0x34, 0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x3e,0x02,0x37,0x3e,0x02,0x35,0x35,0x33,0x04,0xf9,0x2e,0x54,0x92,0x9a,0x7e,0x72,0x56,0x3a,0x20,0x3b,0x36,0x22,0x5a,0x2f,0x23,0x2c,0x2f,0x54,0x2b,0x41,0x39,0x52, 0x3c,0x16,0x1a,0x27,0x25,0x48,0x34,0x3a,0x4b,0x7e,0x6d,0x8a,0x9e,0x8e,0x6a,0x92,0x6a,0x2d,0x84,0x40,0x6c,0x82,0x38,0x73,0xc5,0xc1,0x72,0x71,0x3a,0xa0,0x05,0xb4,0x4a,0x72,0x55,0x44,0x26,0x20,0x36,0x4e,0x73,0xa1,0x6f,0xfe,0xf0,0x44,0x46,0x46,0x38,0x2a,0x32,0x3b,0x39,0x01,0x9f,0x98,0x75,0x90,0x07,0x0a,0x39,0x23,0x2b,0x45, 0x4c,0x3a,0x60,0x80,0xe4,0xbc,0xb9,0xf9,0x82,0x3b,0x47,0xa1,0x85,0x01,0x2c,0x8b,0xcd,0x8f,0x6c,0x39,0x23,0x3d,0x52,0x30,0x7b,0x00,0x00,0x01,0x01,0x20,0xff,0xec,0x04,0xe3,0x06,0x3b,0x00,0x43,0x00,0x00,0x01,0x06,0x06,0x15,0x15,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x21,0x07,0x23,0x22,0x06,0x15,0x14,0x16, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x24,0x35,0x10,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x34,0x36,0x37,0x04,0xe3,0x37,0x23,0xa2,0x22,0x8e,0x61,0x6a,0x85,0x35,0x63,0x46,0x01,0x3c,0x10,0xed,0x8f,0xb5,0xb8, 0x8c,0x91,0xa8,0x41,0x30,0x16,0x1a,0x27,0x25,0x48,0x34,0x3a,0x4b,0x7e,0x6d,0x7e,0x8d,0x78,0xda,0x87,0xdf,0xfe,0xfb,0xdc,0x57,0x5e,0xe0,0xb6,0xa3,0x69,0x67,0x64,0x05,0xb1,0x10,0x45,0x58,0xa4,0x56,0x61,0x70,0x5b,0x35,0x58,0x32,0x8c,0xb2,0x91,0x8f,0xb7,0x7d,0x6d,0x49,0x5e,0x07,0x0a,0x39,0x23,0x2b,0x45,0x4c,0x3a,0x60,0x80, 0xa7,0x99,0x6c,0xa2,0x58,0xf1,0xcd,0x01,0x2d,0x69,0x26,0x8b,0x5b,0x9b,0xbc,0x5b,0x6f,0x71,0x13,0x00,0x00,0x02,0x00,0x9d,0x00,0x45,0x03,0xaf,0x05,0xa3,0x00,0x0e,0x00,0x1d,0x00,0x00,0x01,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x12,0x37,0x14,0x02,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x33, 0x32,0x12,0x03,0x08,0x60,0x4c,0x4e,0x7c,0x4e,0x33,0x55,0x2f,0x4f,0x77,0x47,0xa7,0x75,0xc9,0x87,0x67,0x95,0x51,0x7a,0xd7,0x7c,0x98,0xad,0x03,0x81,0xb6,0xe2,0xb0,0xfe,0xa8,0xb8,0x72,0xb7,0x62,0xa8,0x01,0x5f,0xa0,0xf3,0xfe,0x7f,0xbc,0x8f,0x01,0x1e,0xba,0xd5,0x01,0x5e,0xc4,0xfe,0xd5,0x00,0x01,0x00,0xb6,0xfe,0xf1,0x03,0x95, 0x05,0xa3,0x00,0x2e,0x00,0x00,0x01,0x14,0x02,0x02,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x16,0x16,0x33,0x32,0x12,0x12,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x16,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x10,0x12,0x36,0x33,0x32,0x12,0x03,0x95,0x5d,0x88,0xa7,0x50,0x3b,0x7b,0x4d,0x4d,0x11, 0x1f,0x06,0x0b,0x51,0x2d,0x46,0x93,0x53,0x3c,0x36,0x42,0x75,0x4d,0x27,0x10,0x09,0x5f,0x1d,0x11,0x38,0x22,0x74,0xcc,0x7a,0x7f,0x8b,0x03,0x60,0xec,0xfe,0x42,0xfe,0xdd,0xa2,0x4f,0x7b,0x3a,0x12,0x3a,0x20,0x3b,0x61,0x01,0x52,0x01,0xf7,0xcb,0xb6,0xca,0xc0,0xfe,0xa8,0x90,0x72,0x8f,0x29,0x17,0x15,0x1a,0x44,0x68,0x96,0x5a,0x01, 0x0e,0x01,0x9e,0xe2,0xfe,0xd5,0x00,0x01,0x00,0x36,0x00,0x8a,0x04,0x16,0x05,0xa3,0x00,0x3f,0x00,0x00,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x01,0x36,0x36,0x35,0x34,0x23,0x22,0x06,0x06,0x02,0x15,0x14,0x17,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x12,0x12,0x36,0x33, 0x32,0x16,0x15,0x14,0x03,0x03,0x36,0x33,0x32,0x16,0x33,0x32,0x36,0x37,0x36,0x36,0x33,0x32,0x16,0x04,0x16,0x0f,0x6e,0x65,0x44,0x1f,0x3a,0x1f,0x2b,0x35,0x0a,0x09,0x15,0x3e,0x0b,0x01,0x1a,0x29,0x31,0x68,0x41,0xb8,0x9e,0x55,0x30,0x09,0x5f,0x1c,0x13,0x31,0x21,0x6f,0xcc,0xf4,0x72,0x78,0x89,0xa9,0xc5,0x0d,0x14,0x18,0x2c,0x1b, 0x17,0x62,0x21,0x0b,0x0d,0x0b,0x23,0x4c,0x02,0x21,0x11,0x2d,0xd7,0x60,0x12,0x22,0x07,0x40,0x10,0x16,0x16,0x02,0x32,0x52,0xaa,0x28,0xb2,0x9b,0xf7,0xfe,0xeb,0x89,0x5b,0x7d,0x18,0x11,0x17,0x47,0x5b,0x8b,0x3f,0xbf,0x01,0x6d,0x01,0x23,0xa5,0xa4,0x86,0x71,0xfe,0xbb,0xfe,0x84,0x04,0x09,0x8d,0x51,0x1c,0x17,0x23,0x00,0x00,0x01, 0x00,0x5a,0x01,0x73,0x03,0xf1,0x05,0xa3,0x00,0x54,0x00,0x00,0x01,0x14,0x06,0x06,0x23,0x22,0x26,0x23,0x22,0x07,0x07,0x22,0x35,0x35,0x34,0x37,0x37,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x0e,0x02,0x23,0x22,0x26,0x35,0x34,0x37,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x02,0x15,0x14,0x1e,0x02,0x15,0x14,0x06, 0x23,0x22,0x26,0x35,0x34,0x12,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x07,0x16,0x33,0x32,0x36,0x37,0x36,0x33,0x32,0x16,0x03,0xe4,0x62,0x7f,0x2a,0x11,0x2d,0x28,0x23,0x23,0x10,0x36,0x43,0x20,0x9b,0x2a,0x3b,0x19,0x15,0x16,0x2b,0x31,0x38,0x24,0x23,0x30,0x27,0x1b,0x11,0x2f,0x2b,0x25,0x48,0x29, 0x23,0x38,0x58,0x35,0x0d,0x11,0x0d,0x6b,0x1e,0x12,0x36,0x5f,0xa8,0x72,0x29,0x68,0x16,0x5e,0x61,0x36,0x53,0x2f,0x54,0x50,0x8d,0x18,0x1c,0x20,0x4f,0x1c,0x0d,0x15,0x11,0x32,0x02,0x62,0x22,0x71,0x51,0x07,0x0f,0x03,0x24,0x0d,0x0e,0x71,0x39,0x01,0x23,0x4d,0xc1,0x35,0x26,0x31,0x32,0x61,0x90,0x5d,0x5c,0x66,0x2e,0x1d,0x11,0x14, 0x6d,0x5e,0xb5,0x62,0x26,0x26,0x82,0xfe,0xf1,0x90,0x4b,0x5c,0x3c,0x29,0x16,0x14,0x41,0xc6,0x49,0xe7,0x01,0x75,0xb7,0x32,0x23,0x55,0x32,0x57,0x33,0x4a,0xf1,0x94,0xfe,0x0b,0x3e,0x32,0x18,0x24,0x00,0x01,0x00,0xc5,0xff,0xc3,0x03,0x86,0x05,0xa7,0x00,0x26,0x00,0x00,0x01,0x32,0x16,0x16,0x15,0x10,0x02,0x06,0x23,0x22,0x26,0x35, 0x34,0x12,0x37,0x36,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x12,0x35,0x34,0x26,0x27,0x26,0x35,0x34,0x36,0x02,0xea,0x20,0x4c,0x30,0x69,0xba,0x83,0x8c,0x8f,0x8d,0x81,0x1a,0x15,0x0e,0x57,0x2c,0x75,0x5d,0x43,0x3b,0x4a,0x6e,0x40,0x28,0x2e,0x08,0x54,0x05,0xa7,0x9c,0xed,0x6b,0xfe,0xef,0xfe,0x1c, 0xfb,0xee,0xe8,0xd0,0x01,0x65,0x8e,0x1c,0x36,0x0c,0x14,0x3a,0xa0,0xfe,0xed,0x98,0x94,0xbb,0xde,0x01,0xa1,0xca,0x94,0xb9,0x49,0x0c,0x13,0x11,0x4a,0x00,0x00,0x01,0x00,0xab,0x01,0x46,0x03,0xa0,0x05,0xa7,0x00,0x33,0x00,0x00,0x01,0x14,0x06,0x23,0x22,0x26,0x27,0x27,0x26,0x27,0x27,0x06,0x02,0x06,0x06,0x23,0x22,0x26,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x15,0x07,0x14,0x16,0x33,0x32,0x36,0x37,0x37,0x36,0x37,0x36,0x35,0x34,0x27,0x27,0x34,0x36,0x33,0x32,0x16,0x16,0x17,0x17,0x13,0x17,0x16,0x03,0xa0,0x3b,0x29,0x19,0x2e,0x19,0x1a,0x18,0x0a,0x05,0x06,0x29,0x35,0x5a,0x49,0x57,0x65,0x2d,0x1e,0x37,0x27,0x1d,0x04,0x2a,0x2b,0x30,0x38,0x0d,0x06,0x0b,0x1d, 0x14,0x16,0x04,0x3e,0x17,0x1b,0x17,0x14,0x0b,0x04,0x64,0x3c,0x24,0x01,0xdd,0x17,0x23,0x7b,0x8b,0x8a,0x77,0x80,0x2b,0x7f,0xfe,0x64,0xa3,0x51,0x71,0xe0,0xf8,0x21,0x1b,0x15,0x14,0xed,0x72,0x68,0xa7,0xd6,0x5a,0xa9,0x3a,0x3c,0x40,0x10,0x45,0x11,0x11,0x1f,0x18,0x47,0x45,0x18,0xfe,0x6e,0xd2,0x7f,0x00,0x01,0x00,0x79,0xff,0xc3, 0x03,0xd2,0x05,0xa3,0x00,0x40,0x00,0x00,0x01,0x36,0x36,0x33,0x32,0x16,0x15,0x10,0x02,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x06,0x02,0x15,0x10,0x12,0x33,0x32,0x36,0x35,0x34,0x23,0x22,0x06,0x06,0x07,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x35,0x34,0x27,0x26,0x35,0x34, 0x36,0x33,0x32,0x15,0x14,0x07,0x06,0x15,0x14,0x02,0x72,0x14,0x2a,0x16,0x78,0x94,0xc8,0xbe,0x88,0xd5,0x76,0x60,0xad,0xd8,0x60,0x37,0x26,0x10,0x2a,0x2f,0xb7,0xdc,0xa1,0x8a,0x70,0x72,0x7c,0x17,0x2e,0x20,0x01,0x01,0x17,0x22,0x1f,0x17,0x0e,0x0d,0x08,0x08,0x1d,0x30,0x4f,0x0b,0x0b,0x03,0x2a,0x06,0x0d,0xb3,0x93,0xfe,0xee,0xfe, 0xde,0xb1,0x01,0x49,0xd2,0x9a,0x01,0x1e,0xdb,0x81,0x13,0x1a,0x31,0x1d,0x12,0x07,0x1a,0xfe,0xa4,0xff,0xfe,0xee,0xfe,0xc6,0xb9,0xc6,0xf6,0x31,0x49,0x19,0x1c,0x1d,0x15,0x22,0x33,0x5d,0x5c,0x35,0x26,0x44,0x44,0x24,0x29,0x28,0x3e,0x1e,0x46,0x47,0x2e,0x23,0x00,0x01,0x00,0x74,0xff,0xf6,0x03,0xd8,0x05,0xa3,0x00,0x3e,0x00,0x00, 0x01,0x10,0x02,0x23,0x22,0x26,0x35,0x34,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x02,0x35,0x34,0x12,0x33,0x32,0x16,0x15,0x14,0x07,0x06,0x15,0x10,0x33,0x32,0x12,0x11,0x34,0x02,0x26,0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x12,0x03, 0xd8,0x91,0x9e,0x6b,0x60,0x0d,0x0c,0x34,0x3c,0x3c,0x30,0x34,0x35,0x08,0x1a,0x59,0x19,0x2b,0x53,0x42,0x9b,0x89,0x78,0x90,0x0c,0x0c,0x41,0x34,0x34,0x5b,0xa1,0x60,0x23,0x46,0x47,0x20,0x09,0x20,0x14,0xab,0x62,0x95,0xeb,0x83,0x02,0xa5,0xfe,0x97,0xfe,0xba,0xb8,0xb6,0x33,0x95,0x94,0x30,0x7c,0x71,0xb2,0xb6,0x85,0xdd,0x6d,0x0f, 0x1b,0x0f,0x15,0x4f,0xab,0x01,0x50,0x71,0xea,0x01,0x09,0xbd,0x9b,0x31,0x94,0x89,0x39,0xfe,0xf8,0x01,0x20,0x01,0x07,0xa6,0x01,0x23,0xa8,0x16,0x17,0x21,0x2f,0x1e,0x18,0x31,0xc4,0xfe,0x9f,0x00,0x00,0x01,0x00,0xa8,0x00,0x45,0x03,0xa4,0x05,0xa7,0x00,0x31,0x00,0x00,0x01,0x14,0x07,0x06,0x06,0x07,0x0e,0x02,0x23,0x22,0x27,0x26, 0x23,0x22,0x07,0x06,0x23,0x22,0x26,0x35,0x34,0x13,0x01,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x01,0x37,0x37,0x32,0x17,0x17,0x32,0x37,0x3e,0x04,0x17,0x32,0x16,0x03,0xa4,0x2e,0x24,0x56,0x16,0x1b,0x17,0x20,0x0f,0x26,0x47,0x47,0x23,0x24,0x3f,0x3f,0x20,0x1d,0x27,0x67,0x01,0x43,0x09,0x44,0x23,0x31,0x12,0x14,0x26, 0x57,0xfe,0xef,0x39,0x34,0x0e,0x65,0x20,0x11,0x21,0x0e,0x1f,0x0e,0x54,0x20,0x17,0x1f,0x4e,0x02,0xc6,0x14,0x4c,0x4b,0xd1,0x55,0x69,0x2a,0x1d,0x0f,0x0e,0x0e,0x0f,0x25,0x26,0x30,0x01,0x24,0x03,0xa9,0x1a,0x1a,0x13,0x0e,0x34,0x2f,0x5b,0xe2,0xfd,0x1f,0x07,0x04,0x10,0x03,0x68,0x2d,0x60,0x25,0xd5,0x34,0x03,0x27,0x00,0x00,0x01, 0x00,0xce,0xff,0xc3,0x03,0x7d,0x05,0xa7,0x00,0x37,0x00,0x00,0x01,0x14,0x06,0x23,0x27,0x26,0x23,0x22,0x35,0x34,0x37,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x02,0x11,0x10,0x12,0x33,0x32,0x37,0x37,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x02,0x35,0x10,0x12,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x06,0x15,0x14, 0x16,0x17,0x16,0x03,0x51,0x25,0x0d,0x22,0x5d,0x3d,0x3b,0x21,0x33,0x40,0x16,0x3c,0x30,0x72,0x79,0x73,0x66,0x4c,0x31,0x35,0x09,0x10,0x16,0x42,0x5d,0x89,0x4e,0x72,0xa8,0x5b,0xe6,0xd5,0x6e,0x86,0x2e,0x55,0x0e,0x13,0x24,0x33,0x21,0x01,0x94,0x13,0x4e,0x04,0x12,0x3b,0x18,0x54,0x81,0xdb,0x97,0x48,0x72,0x80,0xfe,0x9f,0xfe,0xc4, 0xfe,0xf4,0xfe,0xda,0x3c,0x40,0x0b,0x3a,0x19,0x21,0x61,0x3d,0xa4,0x01,0x3b,0xde,0x01,0x85,0x01,0xa2,0xd1,0xab,0x4c,0xc0,0xe1,0x23,0x29,0x0e,0x10,0x0f,0x0b,0x08,0x00,0x02,0x00,0xc3,0xff,0xe7,0x05,0x05,0x04,0x19,0x00,0x0b,0x00,0x17,0x00,0x00,0x05,0x22,0x00,0x35,0x10,0x00,0x21,0x32,0x00,0x15,0x14,0x00,0x03,0x22,0x06,0x15, 0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0xe4,0xf5,0xfe,0xd4,0x01,0x2c,0x01,0x01,0xf8,0x01,0x1d,0xfe,0xdf,0xfa,0xb3,0xcc,0xd0,0xaf,0xb5,0xbe,0xbe,0x19,0x01,0x21,0xec,0x01,0x02,0x01,0x23,0xfe,0xe7,0xfc,0xfb,0xfe,0xde,0x03,0xa6,0xd9,0xba,0xb5,0xd2,0xcb,0xc0,0xc1,0xce,0x00,0x01,0x01,0x6a,0xff,0xe7,0x04,0x5e,0x04,0x19, 0x00,0x15,0x00,0x00,0x01,0x36,0x33,0x32,0x12,0x15,0x10,0x00,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x01,0x70,0x72,0x9e,0xdf,0xff,0xfe,0xf8,0xf2,0x8e,0x6c,0x69,0x8f,0xa9,0xad,0xa1,0x9d,0x96,0x74,0x03,0xd3,0x46,0xfe,0xe5,0xf6,0xfe,0xfc,0xfe,0xe3,0x38,0xa2,0x4e,0xd0,0xc7,0xbe,0xc5,0x56,0x00, 0x00,0x02,0x01,0x08,0xfd,0x6d,0x04,0xc0,0x04,0x19,0x00,0x1c,0x00,0x27,0x00,0x00,0x01,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x36,0x35,0x11,0x34,0x27,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x10,0x00,0x03,0x22,0x06,0x15,0x14,0x33,0x32,0x36,0x35,0x34,0x26,0x02,0x8b,0x7b,0xb8,0x50,0xa8,0xdf,0x77, 0xb4,0x63,0x1d,0x0c,0x73,0x60,0x64,0x71,0x80,0x86,0xb6,0xb8,0xfe,0xd1,0x68,0x2f,0x33,0x60,0x2b,0x33,0x31,0xfd,0x6d,0x23,0x28,0xaa,0x6c,0x79,0xe6,0x9d,0x02,0x25,0xb3,0x65,0x59,0x65,0x70,0x61,0x6d,0x6a,0xe8,0xdd,0xfd,0x9e,0xfe,0xce,0xfe,0xad,0x06,0x3d,0x35,0x31,0x5f,0x34,0x2d,0x30,0x34,0x00,0x00,0x01,0x01,0x20,0xfd,0x6d, 0x04,0xa7,0x04,0x19,0x00,0x25,0x00,0x00,0x25,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x10,0x00,0x21,0x23,0x27,0x17,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x04,0x27,0x01,0x20,0x78,0xa2,0xc0,0xc6,0xb9,0xb2,0xad,0x82,0x7d,0xb2,0xf7,0x01,0x1a,0xfe,0xdd,0xfe,0xf1,0x1a,0x19, 0x53,0xb6,0xe0,0x44,0x43,0x36,0x36,0x59,0x49,0x94,0x8f,0x87,0x78,0x66,0x27,0xc1,0x4e,0xd0,0xc7,0xbe,0xc5,0x56,0x9c,0x46,0xfe,0xe4,0xf5,0xfe,0xfc,0xfe,0xe3,0x02,0x5d,0xd2,0xb8,0x1b,0x90,0x20,0x52,0x80,0x9c,0x94,0x7b,0x1e,0x00,0x01,0x01,0x21,0xfd,0x6d,0x04,0xa6,0x04,0x19,0x00,0x21,0x00,0x00,0x01,0x22,0x06,0x15,0x14,0x16, 0x33,0x32,0x24,0x37,0x15,0x03,0x06,0x02,0x07,0x23,0x36,0x12,0x01,0x06,0x23,0x22,0x24,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x03,0x36,0xb0,0xbf,0x9e,0x9b,0x57,0x01,0x09,0x46,0xcd,0xa7,0xaf,0x26,0xbb,0x3e,0xea,0x01,0x24,0x6d,0x8b,0xd4,0xfe,0xff,0x84,0xf5,0x98,0x73,0xbf,0x3c,0x41,0xcd,0x03,0x8f,0xa9,0x9c, 0x93,0x98,0x3e,0x24,0x9c,0xfe,0xf7,0xd5,0xfe,0xe1,0x7b,0xa9,0x01,0x5d,0x01,0x50,0x30,0xed,0xce,0x87,0xd2,0x72,0x26,0x20,0x9c,0x29,0x2f,0x00,0x00,0x01,0x00,0x3c,0xfd,0x6d,0x05,0x8c,0x04,0x19,0x00,0x32,0x00,0x00,0x01,0x10,0x23,0x22,0x26,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x35,0x11,0x34,0x26,0x26,0x23,0x22, 0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x10,0x17,0x15,0x24,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x05,0x8c,0xfa,0x6c,0x79,0x14,0x83,0x0e,0x2e,0x26,0x5e,0x29,0x5c,0x52,0x60,0x6f,0x0e,0x9e,0x0e,0x6d,0x60,0x51,0x5c,0x2a,0xbf,0xfe,0x99,0x4e,0xa8,0x89,0x78,0x8a,0x29,0x29,0x8b, 0x77,0x88,0xa5,0x4e,0xfe,0x81,0xfe,0xec,0x75,0x64,0x50,0x24,0x2f,0x2d,0x30,0x32,0x8b,0x03,0x79,0xb0,0x91,0x4c,0x75,0x8b,0x8a,0x76,0x4b,0x90,0xb0,0xfe,0xa5,0x24,0x9c,0x48,0x01,0xd3,0xca,0xdb,0x72,0x60,0x75,0x74,0x61,0x70,0xda,0xcf,0x00,0x01,0x01,0x05,0xff,0xe7,0x04,0xc3,0x07,0x62,0x00,0x31,0x00,0x00,0x01,0x10,0x12,0x33, 0x32,0x36,0x35,0x34,0x27,0x2e,0x03,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x20,0x00,0x11,0x11,0x10,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x02,0x11,0x01,0xa9,0xb1,0xc5,0x7a,0x84,0x7c,0x77,0x4b,0x32,0x1b,0x96,0x8b,0x73,0x54,0x29,0x60,0x3e,0x41,0x46, 0x57,0x75,0x66,0x65,0xd8,0xcc,0xfe,0xed,0xfe,0xf9,0x01,0x3b,0x01,0x2f,0xb6,0x98,0xa5,0xa7,0xe7,0xe1,0x02,0xe9,0xfe,0xb3,0xfe,0xd7,0x57,0x51,0x5b,0x4a,0x46,0x3b,0x45,0x4f,0x33,0x7f,0x92,0x2b,0x90,0x13,0x20,0x4c,0x39,0x33,0x55,0x43,0x3b,0x89,0x56,0xa0,0xa0,0x01,0x72,0x01,0x90,0x01,0x40,0x01,0x97,0x01,0xa2,0x4e,0xaa,0x6d, 0xfe,0x9d,0xfe,0x86,0x00,0x01,0x00,0x50,0xfd,0x6d,0x06,0xdc,0x04,0x19,0x00,0x32,0x00,0x00,0x01,0x34,0x26,0x26,0x23,0x22,0x06,0x07,0x23,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x10,0x17,0x15,0x24,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x11,0x14,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x15, 0x14,0x06,0x23,0x22,0x11,0x04,0xfc,0x29,0x5c,0x52,0x60,0x6f,0x0e,0x9e,0x0e,0x6d,0x60,0x51,0x5c,0x2a,0xbf,0xfe,0x99,0x4e,0xa8,0x89,0x78,0x8a,0x29,0x29,0x8b,0x77,0x88,0xa5,0x4e,0x5e,0x27,0x2d,0x0e,0x83,0x15,0x79,0x6d,0xfa,0x02,0x00,0xb0,0x91,0x4c,0x75,0x8b,0x8a,0x76,0x4b,0x90,0xb0,0xfe,0xa5,0x24,0x9c,0x48,0x01,0xd3,0xca, 0xdb,0x72,0x60,0x75,0x74,0x61,0x70,0xda,0xcf,0xfc,0x85,0x89,0x32,0x30,0x2d,0x2f,0x26,0x3e,0x70,0x79,0x01,0x14,0x00,0x01,0x00,0xc9,0x00,0x00,0x04,0xfe,0x04,0x00,0x00,0x0e,0x00,0x00,0x01,0x06,0x02,0x07,0x23,0x36,0x12,0x37,0x33,0x16,0x12,0x17,0x23,0x26,0x02,0x02,0xe4,0x2b,0xc5,0x6e,0xbd,0x9a,0xf7,0x36,0xa8,0x3b,0xf2,0x99, 0xbc,0x71,0xc3,0x03,0x31,0xbc,0xfe,0x3c,0xb1,0xe1,0x02,0x2e,0xf1,0xfe,0xfd,0xe1,0xe3,0xb6,0x01,0xc4,0x00,0x01,0x01,0x01,0xfd,0x6d,0x04,0xc6,0x04,0x19,0x00,0x24,0x00,0x00,0x01,0x10,0x21,0x32,0x16,0x15,0x10,0x21,0x22,0x35,0x34,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x02,0x11,0x10,0x12,0x33, 0x32,0x37,0x15,0x06,0x23,0x20,0x00,0x01,0x01,0x02,0x11,0xd1,0xe3,0xfe,0xcd,0xfa,0x08,0xa0,0x08,0x2b,0x35,0x48,0x3d,0x8b,0x81,0xb3,0xb6,0xf8,0xe9,0x8f,0x86,0x7e,0x9f,0xfe,0xc4,0xfe,0xbb,0x01,0x29,0x02,0xf0,0xea,0xdb,0xfe,0x62,0xdd,0x30,0x12,0x18,0x27,0x2f,0x30,0x8e,0x8b,0x9b,0xa2,0xfe,0xd6,0xfe,0xbc,0xfe,0x74,0xfe,0x65, 0x52,0xa0,0x3d,0x01,0xe3,0x00,0x00,0x01,0x00,0xd6,0xff,0xe7,0x04,0xf1,0x05,0xfa,0x00,0x22,0x00,0x00,0x01,0x32,0x16,0x17,0x36,0x35,0x34,0x27,0x33,0x16,0x15,0x14,0x06,0x06,0x07,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x00,0x11,0x34,0x12,0x02,0x9f,0x68,0xa6,0x29,0x75,0x3f,0xb0,0x35, 0x2f,0x54,0x75,0x8d,0x6e,0x5d,0x8d,0x98,0xad,0xa9,0x82,0x76,0x6c,0x8e,0xf2,0xfe,0xf8,0xf2,0x04,0x19,0x5f,0x56,0xa4,0xfc,0x8b,0x6b,0x6a,0x8e,0x65,0xa9,0x9a,0x97,0x5b,0x6f,0xce,0xb5,0xc7,0xd0,0x4e,0xa2,0x38,0x01,0x1a,0x01,0x07,0xfc,0x01,0x15,0x00,0x03,0x00,0x8b,0xff,0xe8,0x05,0x79,0x06,0xd0,0x00,0x1a,0x00,0x26,0x00,0x33, 0x00,0x00,0x01,0x02,0x21,0x22,0x26,0x27,0x0e,0x02,0x23,0x20,0x03,0x33,0x14,0x16,0x16,0x33,0x32,0x36,0x35,0x33,0x12,0x33,0x32,0x36,0x36,0x35,0x13,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x03,0x34,0x26,0x26,0x23,0x22,0x00,0x15,0x14,0x00,0x33,0x32,0x00,0x05,0x79,0x01,0xfe,0x9f,0x59,0x9d,0x1f,0x0f,0x53,0x76, 0x3c,0xfe,0x9e,0x01,0xa1,0x1f,0x5a,0x49,0x63,0x62,0xa1,0x02,0xc0,0x47,0x5a,0x21,0x99,0xfe,0x94,0xfe,0xfd,0xfe,0xfd,0xfe,0x94,0x01,0x6d,0x01,0x02,0x01,0x01,0x01,0x6e,0xa1,0x7e,0xd5,0x7b,0xbc,0xfe,0xef,0x01,0x0c,0xc1,0xc5,0x01,0x09,0x06,0xd0,0xfe,0x51,0x57,0x4e,0x2c,0x4e,0x2b,0x01,0xaf,0x62,0x7a,0x42,0x86,0x98,0xfe,0xe2, 0x3e,0x75,0x6b,0xfb,0x87,0xfe,0xfd,0xfe,0x94,0x01,0x6e,0x01,0x01,0x01,0x01,0x01,0x6e,0xfe,0x94,0xfe,0xfd,0x80,0xdb,0x83,0xfe,0xe3,0xc1,0xbe,0xfe,0xe0,0x01,0x23,0x00,0x01,0x02,0xb1,0x00,0x00,0x03,0x52,0x06,0xd0,0x00,0x03,0x00,0x00,0x21,0x23,0x11,0x33,0x03,0x52,0xa1,0xa1,0x06,0xd0,0x00,0x04,0x00,0x1f,0xff,0xe8,0x05,0xe4, 0x06,0xe8,0x00,0x20,0x00,0x2c,0x00,0x38,0x00,0x45,0x00,0x00,0x25,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x23,0x11,0x26,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x14,0x06,0x07,0x11,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x16,0x33,0x32,0x36,0x05,0xe4,0x73,0x9d,0x78,0x9b,0x86,0x4c,0x9d,0x5e,0xa2,0x72,0x50,0x49,0xcb,0x90,0x90,0xca,0x01,0x8f,0x7b,0x79,0x91,0x6f,0x9e,0x85,0x4d,0x6b,0x4b,0xfd,0x93,0x3d,0x2d,0x2d,0x3e,0x3e,0x2d,0x2c,0x3e,0xfd,0xd0,0x3e,0x2d,0x2b,0x40,0x40, 0x2b,0x2d,0x3e,0x01,0x77,0x76,0x54,0x50,0x7a,0x3a,0x3d,0x53,0x54,0x76,0x69,0x81,0x6d,0x5a,0xaf,0x04,0x3a,0x1d,0x5d,0x62,0x77,0x90,0xcb,0xcc,0x8f,0x78,0xbb,0x20,0xfc,0xa4,0x61,0x6b,0x5b,0x5b,0x01,0xe4,0x2d,0x3d,0x3e,0x2c,0x2d,0x3e,0x3e,0x2d,0x2c,0x3e,0x3d,0x2d,0x2e,0x3d,0x3e,0x02,0xa8,0x56,0x74,0x71,0x59,0x53,0x3d,0x3a, 0x72,0x00,0x00,0x02,0x00,0xb7,0x00,0x00,0x05,0x4d,0x06,0xe8,0x00,0x29,0x00,0x35,0x00,0x00,0x01,0x10,0x21,0x23,0x11,0x23,0x11,0x21,0x32,0x36,0x35,0x34,0x26,0x26,0x23,0x35,0x20,0x36,0x35,0x34,0x26,0x23,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x20,0x15,0x14,0x07,0x15,0x16,0x01,0x34,0x26,0x27, 0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x4d,0xfe,0x8f,0x5f,0xa1,0x01,0x00,0x79,0x67,0x43,0xa7,0xa1,0x01,0x02,0x89,0x71,0x6f,0x76,0x19,0xbb,0x80,0x8c,0xcf,0xcb,0x90,0x7c,0xbf,0x19,0x76,0x01,0x71,0xc5,0xc5,0xfd,0x8f,0x76,0x54,0x51,0x79,0x6f,0x5b,0x56,0x74,0x03,0x16,0xfe,0xf9,0xfd,0xf1,0x02,0xa0,0x40,0x4a,0x34,0x3b, 0x12,0x91,0x42,0x4d,0x4c,0x2f,0x75,0xa0,0xc7,0x95,0x90,0xcb,0x9c,0x75,0xf8,0xb6,0x32,0x07,0x35,0x01,0xd2,0x55,0x74,0x01,0x71,0x59,0x51,0x79,0x76,0x00,0x00,0x01,0x00,0xd7,0x00,0x00,0x05,0x2d,0x06,0xd0,0x00,0x12,0x00,0x00,0x21,0x23,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x33,0x01,0x07,0x01,0x11,0x21,0x11,0x33,0x11,0x21,0x05, 0x2d,0xa1,0xfe,0xc7,0xa1,0xfe,0x25,0xa3,0x01,0xa5,0x72,0xfe,0xcb,0x01,0x3a,0xa1,0x01,0xda,0x02,0x48,0xfd,0xb8,0x02,0x48,0x04,0x88,0xfe,0x58,0x72,0x01,0x39,0xfc,0xea,0x01,0x22,0xfe,0xde,0x00,0x00,0x01,0x00,0xf9,0xff,0xe9,0x05,0x0b,0x06,0xd0,0x00,0x1b,0x00,0x00,0x01,0x14,0x06,0x07,0x27,0x36,0x36,0x35,0x34,0x26,0x23,0x22, 0x00,0x07,0x23,0x11,0x33,0x01,0x07,0x01,0x11,0x36,0x37,0x36,0x33,0x32,0x16,0x16,0x05,0x0b,0xd5,0x96,0x37,0x7c,0x95,0x86,0x70,0xd8,0xfe,0xef,0x01,0xa1,0xa3,0x01,0xa6,0x72,0xfe,0xca,0x51,0x87,0x7f,0x93,0x71,0xb5,0x61,0x01,0xa6,0x9a,0xf6,0x2d,0x7b,0x21,0xb4,0x6d,0x62,0x74,0xfe,0x82,0xfe,0x06,0xd0,0xfe,0x58,0x72,0x01,0x39, 0xfb,0xf9,0x89,0x47,0x47,0x51,0x9e,0x00,0x00,0x02,0x01,0x37,0xff,0xe8,0x04,0xcd,0x06,0xd0,0x00,0x1a,0x00,0x26,0x00,0x00,0x01,0x14,0x06,0x23,0x20,0x11,0x10,0x13,0x21,0x35,0x21,0x36,0x37,0x21,0x15,0x21,0x06,0x07,0x21,0x15,0x21,0x02,0x11,0x36,0x33,0x32,0x16,0x07,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04, 0xcd,0xcc,0x8f,0xfe,0x6e,0x7d,0xfe,0xda,0x01,0x61,0x47,0x7a,0x01,0x74,0xfe,0xf2,0x47,0x2f,0x01,0x2f,0xfe,0x94,0x8b,0x69,0x88,0x8f,0xcc,0x91,0x72,0x58,0x59,0x72,0x70,0x5b,0x5a,0x70,0x01,0x44,0x90,0xcc,0x02,0x57,0x01,0x2d,0x01,0x53,0x92,0xa2,0xdd,0x92,0x83,0x6a,0x92,0xfe,0xa1,0xfe,0xde,0x60,0xcc,0x8e,0x50,0x79,0x78,0x51, 0x50,0x7b,0x7a,0x00,0x00,0x02,0x00,0x33,0xff,0xe8,0x05,0xd0,0x06,0xe8,0x00,0x1f,0x00,0x2b,0x00,0x00,0x13,0x36,0x33,0x32,0x17,0x16,0x33,0x32,0x37,0x33,0x11,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x11,0x06,0x23,0x22,0x27,0x26,0x23,0x22,0x07,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06, 0x33,0x73,0x9d,0x76,0x9d,0x83,0x4e,0x9e,0x5d,0xa3,0x75,0x96,0xca,0x92,0x8f,0xcc,0x98,0x72,0x77,0x93,0x70,0x9d,0x85,0x4c,0x69,0x4e,0x03,0x26,0x77,0x53,0x54,0x77,0x78,0x53,0x53,0x77,0x06,0x67,0x81,0x6d,0x5b,0xb0,0xfb,0xc5,0x1c,0xc0,0x76,0x90,0xcb,0xca,0x91,0x77,0xc0,0x1b,0x03,0x5d,0x62,0x6c,0x5b,0x5b,0xfb,0x47,0x53,0x77, 0x76,0x54,0x54,0x76,0x77,0x00,0x00,0x04,0x01,0x1c,0xff,0xe8,0x04,0xe8,0x06,0x83,0x00,0x0b,0x00,0x17,0x00,0x2d,0x00,0x39,0x00,0x00,0x01,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x05,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x01,0x14,0x00,0x23,0x22,0x00,0x35,0x10,0x37,0x26,0x03,0x33,0x16,0x16, 0x33,0x32,0x36,0x37,0x33,0x02,0x07,0x16,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xad,0x3d,0x2d,0x2e,0x3d,0x3e,0x2d,0x2c,0x3e,0xfd,0x7f,0x3d,0x2d,0x2e,0x3d,0x3e,0x2d,0x2c,0x3e,0x02,0xbc,0xfe,0xe6,0xcc,0xcc,0xfe,0xe6,0xda,0xd9,0x01,0xa2,0x01,0xbd,0x86,0x87,0xbd,0x01,0xa1,0x02,0xd8,0xda,0xa1,0xbf, 0x86,0x86,0xbe,0xbf,0x85,0x86,0xbf,0x06,0x18,0x2b,0x40,0x40,0x2b,0x2d,0x3e,0x3e,0x2d,0x2b,0x40,0x40,0x2b,0x2d,0x3e,0x3e,0xfb,0x8c,0xc7,0xfe,0xde,0x01,0x20,0xc9,0x01,0x02,0x95,0x93,0x01,0x00,0x7e,0xc5,0xc7,0x7c,0xfe,0xff,0x92,0x95,0xfe,0xfe,0x7f,0xc7,0xc6,0x80,0x83,0xc5,0xc7,0x00,0x00,0x03,0x00,0x45,0xff,0xe9,0x05,0xbe, 0x06,0xe8,0x00,0x28,0x00,0x35,0x00,0x41,0x00,0x00,0x01,0x14,0x06,0x07,0x15,0x14,0x07,0x16,0x15,0x14,0x06,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x27,0x06,0x21,0x22,0x24,0x27,0x34,0x37,0x36,0x33,0x20,0x17,0x36,0x35,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x32,0x16,0x07,0x34,0x27,0x26,0x23,0x22,0x06,0x07,0x14,0x16,0x33,0x32,0x36, 0x01,0x26,0x21,0x22,0x06,0x15,0x14,0x16,0x16,0x33,0x20,0x37,0x05,0xbe,0x92,0x81,0x2f,0x2f,0x79,0xf2,0x98,0xb0,0xc2,0x07,0xb5,0xfe,0xc7,0xcb,0xfe,0xec,0x01,0x8b,0x8a,0xcb,0x01,0x38,0xb6,0x07,0x01,0x7c,0x96,0xca,0x91,0x90,0xcc,0x92,0x3b,0x3a,0x55,0x55,0x74,0x01,0x71,0x59,0x56,0x74,0xfe,0x9f,0x8c,0xfe,0xe6,0x87,0xb8,0x57, 0x93,0x55,0x01,0x1b,0x8b,0x05,0x8d,0x76,0xc2,0x1d,0x18,0x86,0x74,0x72,0x88,0x9d,0xeb,0x9e,0x1d,0xa1,0x2b,0xd7,0xa0,0x28,0x29,0xc4,0xd8,0x95,0x97,0x6a,0x6c,0xc3,0x28,0x28,0x18,0x1d,0xbf,0x79,0x90,0xca,0x01,0xcc,0x8f,0x57,0x38,0x3b,0x76,0x54,0x51,0x79,0x76,0xfd,0xef,0xc2,0x74,0x50,0x32,0x5e,0x33,0xc1,0xff,0xff,0x00,0x00, 0xfd,0xff,0x03,0xbd,0xff,0xbb,0x02,0x26,0x0b,0x59,0x00,0x00,0x00,0x27,0x0b,0x5f,0x02,0x6d,0x00,0x00,0x00,0x07,0x0b,0x53,0x03,0x04,0x00,0x00,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x97,0xff,0xbb,0x02,0x26,0x0b,0x5a,0x00,0x00,0x00,0x67,0x0b,0x5f,0x02,0x47,0x00,0x00,0xc0,0x01,0x40,0x00,0x00,0x07,0x0b,0x53,0x02,0xde,0x00,0x00, 0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x97,0xff,0xbb,0x02,0x26,0x0b,0x5b,0x00,0x00,0x00,0x67,0x0b,0x5f,0x02,0x47,0x00,0x00,0xc0,0x01,0x40,0x00,0x00,0x07,0x0b,0x53,0x02,0xde,0x00,0x00,0xff,0xff,0xff,0x9c,0x05,0x77,0x00,0x67,0x06,0x40,0x02,0x06,0x0b,0x66,0x00,0x00,0xff,0xff,0xfe,0xe6,0x05,0x77,0x01,0x1b,0x06,0x40,0x02,0x27, 0x0b,0x66,0xff,0x4a,0x00,0x00,0x00,0x07,0x0b,0x66,0x00,0xb4,0x00,0x00,0xff,0xff,0xff,0x9c,0xfe,0x8d,0x00,0x67,0xff,0x56,0x02,0x06,0x0b,0x67,0x00,0x00,0xff,0xff,0x00,0x31,0x00,0x00,0x03,0x17,0x05,0xd5,0x02,0x26,0x0b,0x6a,0x00,0x00,0x00,0x07,0x0b,0x61,0x01,0x9f,0x00,0x00,0xff,0xff,0x00,0x20,0x00,0x00,0x03,0xab,0x05,0xd5, 0x02,0x26,0x0b,0x6b,0x00,0x00,0x00,0x07,0x0b,0x61,0x01,0xea,0x00,0x00,0xff,0xff,0x00,0xb8,0x00,0x00,0x04,0xc0,0x05,0xd5,0x02,0x26,0x0b,0x6c,0x00,0x00,0x00,0x07,0x0b,0x61,0x02,0xad,0x00,0x00,0xff,0xff,0x00,0x34,0xff,0xed,0x05,0x23,0x05,0xd5,0x02,0x26,0x0b,0x82,0x00,0x00,0x00,0x07,0x0b,0x61,0x02,0xf3,0x00,0x00,0x00,0x02, 0x00,0x6d,0xff,0xe8,0x01,0xcc,0x05,0xb2,0x00,0x0d,0x00,0x1b,0x00,0x4d,0x40,0x2e,0x11,0x03,0x7e,0x18,0x0a,0x0a,0x1d,0x1b,0x14,0x0d,0x06,0x15,0x91,0x14,0x0d,0x91,0x00,0x2f,0x14,0x01,0x20,0x00,0x50,0x00,0x80,0x00,0xb0,0x00,0xd0,0x00,0xe0,0x00,0x06,0x14,0x00,0x14,0x00,0x06,0x1b,0x91,0x0e,0x04,0x07,0x91,0x06,0x13,0x00,0x3f, 0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x10,0xed,0x10,0xed,0x01,0x2f,0x33,0x33,0x33,0x12,0x39,0x2f,0x33,0xe9,0x32,0x31,0x30,0x13,0x32,0x16,0x15,0x14,0x06,0x23,0x35,0x36,0x36,0x35,0x34,0x26,0x27,0x11,0x32,0x16,0x15,0x14,0x06,0x23,0x35,0x36,0x36,0x35,0x34,0x26,0x27,0x6d,0x91,0xce,0xce,0x91,0x52,0x65,0x65,0x52, 0x91,0xce,0xce,0x91,0x52,0x65,0x65,0x52,0x02,0xa6,0xce,0x91,0x91,0xce,0x98,0x06,0x6e,0x53,0x53,0x6e,0x06,0x03,0xa4,0xce,0x91,0x91,0xce,0x98,0x06,0x6e,0x53,0x53,0x6e,0x06,0x00,0x02,0x00,0x5a,0x01,0x80,0x01,0x52,0x05,0xb2,0x00,0x0d,0x00,0x1b,0x00,0x30,0x40,0x18,0x11,0x03,0xed,0x18,0x0a,0x0a,0x1d,0x1b,0x14,0x0d,0x06,0x07, 0x96,0x06,0x0d,0x96,0x00,0x15,0x96,0x14,0x1b,0x96,0x0e,0x04,0x00,0x3f,0xed,0xd6,0xed,0xd6,0xed,0xd6,0xed,0x01,0x2f,0x33,0x33,0x33,0x12,0x39,0x2f,0x33,0xe9,0x32,0x31,0x30,0x13,0x16,0x16,0x15,0x14,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x26,0x27,0x11,0x16,0x16,0x15,0x14,0x06,0x07,0x35,0x36,0x36,0x35,0x34,0x26,0x27,0x5a,0x68, 0x90,0x90,0x68,0x36,0x3a,0x3a,0x36,0x68,0x90,0x90,0x68,0x36,0x3a,0x3a,0x36,0x03,0x70,0x02,0x91,0x65,0x65,0x91,0x02,0x82,0x05,0x3b,0x36,0x36,0x3b,0x05,0x02,0xc4,0x02,0x91,0x65,0x65,0x91,0x02,0x82,0x05,0x3b,0x36,0x36,0x3b,0x05,0x00,0x00,0x01,0x00,0x5b,0x02,0xac,0x01,0xde,0x05,0xb2,0x00,0x0d,0x00,0x1e,0x40,0x0e,0x00,0x07, 0x07,0x0f,0x03,0x7e,0x0a,0x06,0x91,0x07,0x00,0x91,0x0d,0x04,0x00,0x3f,0xed,0xd6,0xed,0x01,0x2f,0xe9,0x12,0x39,0x11,0x33,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x01,0xde,0x60,0x7b,0x7b,0x60,0xa7,0xdc,0xdc,0xa7,0x05,0x1a,0x06,0x85,0x60,0x60,0x85,0x06,0x98,0xdc,0xa7,0xa7,0xdc,0x00, 0x00,0x01,0x00,0x4e,0x03,0x90,0x01,0x5e,0x05,0xb2,0x00,0x0d,0x00,0x1e,0x40,0x0e,0x00,0x07,0x07,0x0f,0x03,0xed,0x0a,0x06,0x96,0x07,0x00,0x96,0x0d,0x04,0x00,0x3f,0xed,0xd6,0xed,0x01,0x2f,0xe9,0x12,0x39,0x2f,0x33,0x31,0x30,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x15,0x26,0x26,0x35,0x34,0x36,0x37,0x01,0x5e,0x3f,0x49,0x49,0x3f, 0x77,0x99,0x95,0x7b,0x05,0x30,0x05,0x4b,0x3f,0x3f,0x4b,0x05,0x82,0x02,0x98,0x77,0x75,0x98,0x04,0x00,0x00,0x01,0x00,0xbc,0xfe,0x5a,0x04,0xf2,0x05,0x9a,0x00,0x15,0x00,0x3b,0x40,0x1f,0x13,0x00,0x7e,0x0b,0x06,0x0b,0x06,0x0b,0x17,0x12,0x0e,0x7e,0x0f,0x0d,0x91,0x40,0x12,0x10,0x0f,0x12,0x91,0x2b,0x30,0x14,0x10,0x03,0x08,0x91, 0x03,0x0f,0x12,0x00,0x3f,0xd4,0xed,0x3f,0x33,0x2b,0x00,0x18,0x2f,0x1a,0xed,0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x33,0x31,0x30,0x25,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x04,0xf2,0xb5,0xb7,0x4c,0x3d,0x4f,0x3e,0x5f,0x61,0xfd,0x1a,0xa8, 0xa8,0x02,0xe6,0xa8,0x3f,0xf8,0xed,0x1f,0xa5,0x2c,0x86,0x89,0x02,0x8d,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x02,0x75,0x00,0x01,0x00,0xa6,0xfe,0x5a,0x03,0xf8,0x05,0xec,0x00,0x1a,0x00,0x2f,0x40,0x18,0x00,0x84,0x0a,0x06,0x0a,0x06,0x0a,0x1c,0x15,0x11,0x84,0x12,0x15,0x0d,0x95,0x18,0x0f,0x13,0x00,0x08,0xec,0x03,0x12,0x15,0x00,0x3f, 0xd4,0xed,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x21,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x20,0x11,0x03,0xf8,0xb7,0xaf,0x4d,0x3d,0x4f,0x3f,0xbe,0xee,0x77,0xa5,0xa4,0xa4,0x04,0x77,0xd9,0x01, 0x5a,0xd4,0xd2,0x1f,0xa5,0x2c,0x01,0x0e,0x02,0x4e,0x01,0x40,0xb8,0x92,0xfd,0xbc,0x05,0xec,0xfd,0x6a,0xc2,0xfe,0x5f,0x00,0x00,0x01,0x00,0x29,0xfe,0x21,0x05,0x83,0x05,0x9a,0x00,0x21,0x00,0x5c,0x40,0x31,0x1f,0x17,0x7e,0x13,0x0a,0x18,0x03,0x7d,0x10,0x15,0x21,0x1a,0x18,0x1d,0x10,0x21,0x21,0x10,0x1d,0x18,0x1a,0x05,0x22,0x23, 0x00,0x14,0x21,0x15,0x91,0x1f,0x12,0x92,0x00,0x00,0x06,0x1f,0x1f,0x18,0x1e,0x1a,0x91,0x1b,0x03,0x0a,0x0d,0x92,0x06,0x18,0x12,0x00,0x3f,0xd4,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x12,0x39,0x2f,0xed,0x10,0xed,0x32,0x01,0x2f,0x33,0x11,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xe9,0x10,0xc6,0xc4,0xe9,0x32, 0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x04,0x23,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x23,0x35,0x01,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x21,0x15,0x03,0xea,0xbf,0xda,0xfe,0xdf,0xea,0x76,0xaa,0x56,0x63,0xb7,0x63,0x96,0xbc,0xfe,0xa1,0x8c,0x01,0x8a,0xfd,0xfe,0xa8,0xfe,0x63,0x03,0xe3,0xfe, 0x62,0x03,0x02,0x01,0x73,0x04,0xd8,0xb6,0xce,0xf2,0x26,0x2e,0xb6,0x44,0x37,0xa0,0x87,0x01,0x1e,0x07,0x02,0x3f,0xfc,0xc5,0x05,0x02,0x98,0x98,0xfe,0xd1,0x28,0x00,0x00,0x01,0x00,0x2b,0xfe,0x21,0x04,0xe4,0x05,0x2f,0x00,0x29,0x00,0x57,0x40,0x2e,0x00,0x12,0x03,0x83,0x0e,0x14,0x29,0x12,0x0e,0x29,0x29,0x0e,0x12,0x03,0x2b,0x27, 0x15,0x84,0x24,0x22,0x09,0x20,0x29,0x15,0x21,0x95,0x23,0x11,0x96,0x00,0x00,0x06,0x27,0x26,0x23,0x0f,0x1b,0x19,0x95,0x1e,0x15,0x09,0x0b,0x95,0x06,0x1b,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x33,0x33,0x12,0x39,0x2f,0xed,0x10,0xed,0x32,0x32,0x01,0x2f,0xc4,0x33,0x33,0xe9,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10, 0xe9,0x11,0x33,0x31,0x30,0x01,0x16,0x16,0x15,0x14,0x00,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x11,0x11,0x23,0x35,0x33,0x35,0x37,0x11,0x21,0x15,0x03,0x20,0xd2,0xf2,0xfe,0xb5,0xf0,0xb6,0x9a,0xa6,0xb0,0xab,0xe2,0xdb,0xd1,0x52,0x01, 0x80,0xfd,0xc1,0x46,0x51,0x3f,0x2c,0x3b,0x5e,0xfe,0xf3,0xb0,0xb0,0xa4,0x03,0x2a,0x01,0xae,0x1c,0xe9,0xb3,0xce,0xfe,0xf9,0x51,0xa2,0x68,0xb2,0x94,0x9b,0xa0,0x33,0x02,0x14,0xfd,0xbf,0x67,0x58,0x22,0x8c,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xfa,0x35,0xfe,0xd1,0x33,0x00,0x00,0x01,0x00,0x66,0xff,0xe9,0x04,0x0b,0x05,0xb2,0x00,0x24, 0x00,0x4b,0x40,0x17,0x24,0x1a,0x18,0x01,0x20,0x0e,0x1a,0x01,0x0e,0x0e,0x01,0x1a,0x03,0x26,0x09,0x7d,0x15,0x20,0x23,0x91,0x1c,0x00,0x05,0xb8,0x01,0x05,0x40,0x0e,0x19,0x1a,0x24,0x1b,0x19,0x04,0x12,0x1c,0x04,0x0e,0x0c,0x91,0x12,0x13,0x00,0x3f,0xed,0x32,0x3f,0x12,0x17,0x39,0x10,0xed,0x33,0x10,0xed,0x32,0x01,0x2f,0xe9,0x12, 0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x15,0x26,0x26,0x27,0x27,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x06,0x23,0x20,0x24,0x35,0x34,0x24,0x37,0x35,0x01,0x35,0x01,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x07,0x03,0x3c,0x0c,0x25,0x13,0x26,0x1f,0xd2,0xca,0xd4,0xac,0xb9,0xbb,0x5c, 0xb3,0x65,0xfe,0xfd,0xfe,0xd2,0x01,0x17,0xf4,0xfe,0x49,0x01,0xb7,0x93,0x9c,0x4f,0x53,0xbf,0x58,0xf8,0x03,0x40,0x8c,0x03,0x03,0x01,0x02,0x99,0x9b,0x7e,0x8c,0x5c,0xa6,0x29,0x23,0xdc,0xc3,0xc6,0xd8,0x02,0x04,0x01,0x23,0x2e,0x01,0x35,0x24,0x22,0xaa,0x30,0x28,0xab,0x00,0x01,0x00,0x26,0xfe,0x1d,0x03,0xc5,0x04,0x00,0x00,0x25, 0x00,0x4a,0x40,0x26,0x25,0x1b,0x19,0x00,0x1b,0x00,0x1b,0x00,0x16,0x21,0x10,0x10,0x27,0x09,0x84,0x16,0x21,0x24,0x95,0x1d,0x06,0x96,0x00,0x1c,0x25,0x1b,0x03,0x1d,0x19,0x19,0x13,0x1d,0x10,0x0f,0x0c,0x95,0x13,0x1c,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x12,0x17,0x39,0x33,0xed,0x10,0xed,0x32,0x01,0x2f,0xe9,0x12,0x39,0x2f, 0xc4,0x11,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x15,0x26,0x26,0x27,0x27,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x24,0x35,0x34,0x24,0x37,0x35,0x01,0x35,0x01,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x07,0x02,0xf6,0x0c,0x25,0x13,0x26,0x1f,0xc3,0xde,0xe3,0xa2,0x5e,0xb8,0x5e, 0x67,0xaa,0x63,0xf9,0xfe,0xce,0x01,0x1e,0xee,0xfe,0x56,0x01,0x8f,0x9a,0xaa,0x4e,0x53,0xbf,0x58,0xf0,0x01,0x8e,0x8c,0x03,0x03,0x01,0x02,0xa9,0x97,0x83,0xa0,0x34,0x2e,0x9c,0x2d,0x24,0xe3,0xca,0xc5,0xe3,0x02,0x05,0x01,0x23,0x2e,0x01,0x36,0x24,0x22,0x9b,0x30,0x28,0xbe,0x00,0x00,0x02,0x00,0x51,0xff,0xe6,0x03,0x95,0x05,0x9a, 0x00,0x12,0x00,0x1e,0x00,0x35,0x40,0x1a,0x13,0x12,0x01,0x7e,0x0f,0x08,0x0f,0x08,0x0f,0x20,0x1e,0x10,0x11,0x10,0x91,0x17,0x12,0x1e,0x1e,0x04,0x12,0x03,0x0b,0x91,0x04,0x12,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x01,0x2f,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x33,0x33,0x31,0x30,0x01,0x11,0x14,0x06,0x23, 0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x21,0x35,0x01,0x13,0x11,0x34,0x36,0x37,0x23,0x06,0x07,0x07,0x06,0x07,0x01,0x03,0x95,0xa4,0xbc,0x23,0x65,0x21,0x1f,0x61,0x29,0x60,0x58,0xfd,0x64,0x02,0x95,0x07,0x07,0x03,0x04,0x07,0x09,0x11,0x09,0x08,0xfe,0x47,0x05,0x9a,0xfb,0xdc,0xde,0xb2,0x0f,0x10,0xa5,0x11,0x1b, 0x58,0x80,0x0f,0x81,0x03,0xb4,0xfc,0x61,0x02,0x4d,0x18,0x54,0x1a,0x0f,0x10,0x1d,0x0f,0x0c,0xfd,0x84,0x00,0x02,0x00,0x21,0xfe,0x1e,0x03,0x50,0x04,0x00,0x00,0x12,0x00,0x1d,0x00,0x30,0x40,0x18,0x13,0x11,0x00,0x84,0x0e,0x07,0x0e,0x07,0x0e,0x1f,0x1d,0x10,0x17,0x11,0x0f,0x10,0x1d,0x96,0x0f,0x15,0x0a,0x95,0x03,0x1c,0x00,0x3f, 0xed,0x3f,0xed,0x32,0x3f,0x33,0x01,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x33,0x33,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x21,0x35,0x01,0x33,0x03,0x11,0x34,0x36,0x37,0x23,0x06,0x06,0x07,0x07,0x01,0x03,0x50,0xae,0xa5,0x29,0x57,0x29,0x2b,0x51,0x2a,0x5a,0x58,0xfd,0x75, 0x02,0x85,0xaa,0xa4,0x02,0x05,0x03,0x03,0x0a,0x06,0x14,0xfe,0x46,0x3f,0xca,0xd9,0x0c,0x14,0x99,0x1b,0x12,0x7e,0x9b,0x3d,0x6f,0x03,0x91,0xfc,0x84,0x02,0x54,0x1e,0x32,0x15,0x07,0x14,0x0a,0x22,0xfd,0x8e,0x00,0x03,0x00,0x51,0xff,0xe6,0x04,0xa1,0x05,0x9a,0x00,0x16,0x00,0x22,0x00,0x26,0x00,0x54,0x40,0x2c,0x26,0x23,0x24,0x25, 0x01,0x04,0x7e,0x13,0x17,0x16,0x13,0x23,0x03,0x25,0x13,0x0c,0x0c,0x13,0x25,0x03,0x23,0x05,0x28,0x22,0x14,0x25,0x12,0x26,0x04,0x14,0x91,0x15,0x01,0x1b,0x16,0x22,0x22,0x08,0x16,0x03,0x0f,0x91,0x08,0x13,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0x33,0x33,0xfd,0x32,0xcc,0x3f,0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f, 0x2f,0x2f,0x11,0x33,0x33,0x10,0xe9,0x32,0x11,0x33,0x11,0x33,0x31,0x30,0x01,0x11,0x33,0x15,0x23,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x21,0x35,0x01,0x13,0x11,0x34,0x36,0x37,0x23,0x06,0x07,0x07,0x06,0x07,0x01,0x05,0x03,0x23,0x13,0x03,0x95,0xf1,0xf1,0xa6,0xba,0x23,0x65,0x21,0x1f,0x61, 0x29,0x60,0x58,0xfd,0x64,0x02,0x95,0x07,0x07,0x03,0x04,0x07,0x09,0x11,0x09,0x08,0xfe,0x47,0x03,0x99,0xa6,0x7b,0x75,0x05,0x9a,0xfc,0x61,0x96,0x0e,0xc7,0xaa,0x0f,0x10,0xa5,0x11,0x1b,0x58,0x80,0x0f,0x81,0x03,0xb4,0xfc,0x61,0x02,0x4d,0x18,0x54,0x1a,0x0f,0x10,0x1d,0x0f,0x0c,0xfd,0x84,0xf8,0xfe,0xfc,0x01,0x04,0x00,0x00,0x03, 0x00,0x21,0xfe,0x1e,0x04,0x72,0x04,0x00,0x00,0x16,0x00,0x21,0x00,0x25,0x00,0x4b,0x40,0x26,0x23,0x24,0x25,0x22,0x07,0x24,0x14,0x22,0x22,0x14,0x24,0x07,0x04,0x27,0x21,0x10,0x13,0x16,0x84,0x17,0x11,0x0e,0x1b,0x11,0x0f,0x24,0x24,0x03,0x13,0x10,0x21,0x25,0x16,0x0f,0x15,0x0a,0x03,0x1c,0x00,0x3f,0xcd,0x3f,0x33,0xcc,0xcd,0x32, 0x32,0x12,0x39,0x2f,0x3f,0x33,0x01,0x2f,0x33,0x33,0xe9,0x32,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x05,0x14,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x21,0x35,0x01,0x33,0x11,0x21,0x15,0x21,0x27,0x11,0x34,0x36,0x37,0x23,0x06,0x06,0x07,0x07,0x01,0x05,0x03,0x23, 0x13,0x03,0x50,0xae,0xa5,0x29,0x57,0x29,0x2b,0x51,0x2a,0x5a,0x58,0xfd,0x75,0x02,0x85,0xaa,0x01,0x05,0xfe,0xfb,0xa4,0x02,0x05,0x03,0x03,0x0a,0x06,0x14,0xfe,0x46,0x03,0xa3,0xa6,0x7b,0x75,0x3f,0xca,0xd9,0x0c,0x14,0x99,0x1b,0x12,0x7e,0x9b,0x3d,0x6f,0x03,0x91,0xfc,0x84,0x84,0x84,0x02,0x54,0x1e,0x32,0x15,0x07,0x14,0x0a,0x22, 0xfd,0x8e,0xdc,0xfe,0xfc,0x01,0x04,0x00,0x00,0x01,0x00,0xb0,0x00,0x00,0x03,0x0b,0x04,0x33,0x00,0x09,0x00,0x26,0x40,0x12,0x03,0x00,0x00,0x0b,0x02,0x05,0x84,0x07,0x05,0x95,0x02,0x02,0x07,0x01,0x95,0x08,0x07,0x15,0x00,0x3f,0xdd,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xe9,0x32,0x12,0x39,0x2f,0xc6,0x31,0x30,0x01,0x21,0x11,0x21, 0x15,0x21,0x11,0x23,0x11,0x21,0x03,0x0b,0xfe,0x49,0x01,0x95,0xfe,0x6b,0xa4,0x02,0x5b,0x03,0xa8,0xfe,0xb1,0x8a,0xfe,0x31,0x04,0x33,0x00,0x01,0x00,0x68,0xff,0xed,0x03,0x08,0x04,0x45,0x00,0x21,0x00,0x34,0x40,0x1b,0x1b,0x84,0x06,0x11,0x06,0x11,0x21,0x23,0x16,0x84,0x0b,0x21,0x11,0x13,0x95,0x16,0x0b,0x1b,0x06,0x04,0x0e,0x1e, 0x00,0x03,0x95,0x1e,0x16,0x00,0x3f,0xfd,0xc6,0x10,0xd4,0x17,0x39,0xfd,0xc6,0x01,0x2f,0xd4,0xe9,0x11,0x12,0x39,0x39,0x2f,0x2f,0xe9,0x31,0x30,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x24,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x04,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x6b,0x33, 0xa3,0x4a,0x73,0x68,0x71,0xfe,0xef,0x7c,0xd7,0xa8,0xa0,0x4a,0x5f,0x93,0x61,0x75,0x77,0x01,0x01,0x87,0xd7,0xb9,0x43,0xa8,0x22,0xd7,0x29,0x38,0x54,0x44,0x46,0x57,0x87,0x91,0x69,0x7e,0x9b,0x26,0xa5,0x42,0x4e,0x3e,0x4d,0x59,0x7b,0x8d,0x67,0x88,0xa6,0x28,0x16,0x00,0x00,0x03,0x00,0x16,0x00,0x00,0x08,0xf1,0x05,0x9a,0x00,0x17, 0x00,0x21,0x00,0x2b,0x00,0x3f,0x40,0x1f,0x17,0x0c,0x1c,0x03,0x05,0x26,0x13,0x00,0x00,0x05,0x13,0x13,0x2d,0x05,0x26,0x1c,0x16,0x03,0x91,0x2b,0x21,0x21,0x04,0x1c,0x11,0x06,0x03,0x14,0x01,0x04,0x12,0x00,0x3f,0x33,0x33,0x3f,0x33,0xcd,0x12,0x39,0x2f,0x33,0xed,0x32,0x11,0x33,0x01,0x2f,0x11,0x33,0x2f,0x12,0x39,0x2f,0x12,0x39, 0x12,0x17,0x39,0x31,0x30,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x33,0x01,0x17,0x16,0x16,0x17,0x33,0x34,0x36,0x37,0x01,0x33,0x01,0x23,0x03,0x21,0x03,0x01,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x21,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x05,0x12,0xba,0x98,0xfd,0xa0,0x8f,0xbb,0x02,0x26,0xae,0x01,0x6f,0x16,0x06, 0x0b,0x02,0x04,0x15,0x09,0x01,0x77,0xae,0x02,0x28,0xba,0x98,0xfd,0xa0,0x60,0xfe,0xaa,0xe1,0x06,0x0e,0x02,0x04,0x02,0x0d,0x08,0xdf,0x05,0xd0,0xe1,0x06,0x0e,0x02,0x04,0x02,0x0d,0x08,0xdf,0x01,0x92,0xfe,0x6e,0x05,0x9a,0xfc,0x47,0x3b,0x12,0x23,0x0d,0x0d,0x40,0x16,0x03,0xd3,0xfa,0x66,0x01,0x92,0xfe,0xf2,0x01,0xa5,0x02,0x63, 0x10,0x3a,0x16,0x14,0x36,0x15,0xfd,0x9c,0x02,0x63,0x10,0x3a,0x16,0x14,0x36,0x15,0xfd,0x9c,0x00,0x03,0x00,0x5a,0xff,0xe8,0x05,0xfc,0x04,0x18,0x00,0x2d,0x00,0x38,0x00,0x43,0x00,0x5d,0x40,0x30,0x09,0x09,0x00,0x32,0xef,0x39,0x23,0x19,0x39,0x2e,0x11,0x84,0x12,0x04,0x12,0x39,0x12,0x39,0x12,0x45,0x3d,0x83,0x27,0x20,0x09,0x27, 0x27,0x06,0x25,0x95,0x2a,0x2e,0x39,0x96,0x04,0x23,0x23,0x0d,0x2a,0x0f,0x35,0x40,0x95,0x16,0x1d,0x16,0x12,0x15,0x00,0x3f,0x3f,0x33,0xed,0x32,0x3f,0x33,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x32,0x11,0x33,0x01,0x2f,0xc4,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xe9,0x33,0x11,0x33,0x33,0x10,0xf9,0x32,0xc0,0x2f,0x31, 0x30,0x01,0x36,0x36,0x37,0x25,0x10,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x15,0x05,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x25,0x07,0x06,0x06,0x15,0x14, 0x16,0x33,0x32,0x36,0x35,0x03,0x7b,0x1f,0x5b,0x30,0x01,0x33,0xcd,0x3f,0x8f,0x1f,0x3d,0x87,0x52,0x9f,0xa9,0xa4,0x04,0x6a,0xd1,0x78,0x91,0x26,0x04,0x32,0xa9,0x6b,0x94,0xb2,0x01,0x52,0x01,0x33,0xd3,0xba,0x94,0x97,0xc5,0xb9,0xa8,0x01,0xdd,0xf7,0x82,0x64,0x73,0x51,0x78,0xa1,0xfd,0x87,0xf7,0x82,0x64,0x6d,0x57,0x7a,0x9f,0x02, 0x2d,0x12,0x18,0x07,0x2b,0x01,0x05,0x49,0x35,0x9e,0x39,0x31,0xbe,0xc0,0xfd,0x66,0xa0,0xb8,0x5b,0x61,0x5a,0x62,0xa1,0x87,0x01,0x1f,0x2f,0x2b,0x01,0x05,0x7e,0xa8,0x60,0xc3,0xbb,0x94,0x22,0x12,0x5f,0x57,0x4d,0x5d,0xae,0x80,0x66,0x22,0x12,0x5f,0x57,0x50,0x5a,0xae,0x80,0x00,0x00,0x03,0x00,0x16,0xff,0xe8,0x08,0xdb,0x05,0xb2, 0x00,0x15,0x00,0x21,0x00,0x2b,0x00,0x3b,0x40,0x1f,0x0d,0x7d,0x26,0x06,0x1b,0x1b,0x00,0x2d,0x21,0x7f,0x07,0x00,0x14,0x91,0x06,0x2b,0x2b,0x01,0x15,0x12,0x18,0x91,0x10,0x13,0x1e,0x91,0x0a,0x04,0x26,0x01,0x03,0x00,0x3f,0xcd,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x39,0xed,0x01,0x2f,0x2f,0xe9,0x11,0x12,0x39,0x2f,0x39,0x39, 0xe9,0x31,0x30,0x33,0x01,0x33,0x13,0x16,0x17,0x17,0x33,0x36,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x24,0x27,0x21,0x03,0x00,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x11,0x07,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x16,0x02,0x26,0xae,0x9f,0x0b,0x08,0x0c,0x04,0x21,0x01,0x60,0x01,0x1a,0x01,0x28,0x01, 0x6c,0xfe,0x8c,0xfe,0xc8,0xeb,0xfe,0xbd,0x42,0xfd,0xa1,0x8f,0x03,0x6e,0x01,0x12,0xde,0xec,0x01,0x10,0xfe,0xf8,0xe8,0xe2,0xfe,0xe6,0xb6,0xe1,0x05,0x0c,0x05,0x04,0x05,0x0b,0x07,0xdf,0x05,0x9a,0xfe,0x62,0x1d,0x19,0x2c,0xdf,0x01,0x39,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0xed,0xbd,0xfe,0x6e,0x01,0xc1,0xfe,0xbe,0x01,0x34, 0x01,0x15,0x01,0x1c,0x01,0x36,0xfe,0xb9,0xfe,0xf8,0xa2,0x02,0x63,0x0f,0x30,0x21,0x1f,0x30,0x11,0xfd,0x9d,0x00,0x00,0x03,0x00,0x5a,0xff,0xe8,0x06,0xb6,0x04,0x18,0x00,0x20,0x00,0x2c,0x00,0x37,0x00,0x52,0x40,0x2c,0x00,0x14,0x2c,0x84,0x30,0x0a,0x30,0x1b,0x83,0x26,0x30,0x26,0x30,0x26,0x39,0x34,0x83,0x0e,0x07,0x23,0x95,0x1e, 0x16,0x29,0x95,0x18,0x10,0x0e,0x0c,0x95,0x11,0x30,0x96,0x14,0x11,0x00,0x0a,0x0a,0x11,0x10,0x37,0x95,0x04,0x16,0x00,0x3f,0xed,0x3f,0x39,0x2f,0x39,0x12,0x39,0xed,0x10,0xed,0x32,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xc4,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x11,0x33,0x10,0xe9,0x39,0x39,0x31,0x30,0x25,0x23,0x06,0x06,0x23,0x22, 0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x12,0x15,0x14,0x00,0x23,0x22,0x26,0x36,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x00,0x36,0x35,0x35,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x03,0x27,0x02,0x45,0xc8,0x78,0x92,0xb4,0x01,0x52,0x01,0x33,0xd3,0xba, 0x94,0x97,0xc5,0x8d,0x98,0x18,0x04,0x44,0xd3,0x6a,0xe0,0xfa,0xfe,0xf2,0xe4,0x83,0xe0,0x22,0xb4,0x99,0x9c,0xa2,0xa2,0x9c,0x9c,0xb1,0xfe,0xc2,0x9a,0xf7,0x8f,0x57,0x6e,0x56,0xcd,0x73,0x72,0xa2,0x86,0x01,0x1f,0x2f,0x2b,0x01,0x05,0x7e,0xa8,0x60,0x64,0x4b,0x61,0x4e,0xfe,0xe4,0xf8,0xf3,0xfe,0xd7,0x75,0xed,0xd8,0xcf,0xbd,0xbe, 0xd2,0xe1,0xa1,0xfe,0x66,0xa9,0x8f,0x5c,0x22,0x15,0x5e,0x55,0x4b,0x5f,0x00,0x02,0x00,0x16,0xff,0xe8,0x07,0x3a,0x05,0x9a,0x00,0x13,0x00,0x1d,0x00,0x30,0x40,0x18,0x02,0x7e,0x18,0x08,0x0c,0x01,0x01,0x1f,0x0c,0x0a,0x91,0x1d,0x1d,0x0b,0x18,0x01,0x0d,0x03,0x0b,0x12,0x12,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0x3f,0x33,0xcd,0x12, 0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x2f,0x12,0x39,0x39,0xe9,0x31,0x30,0x01,0x11,0x33,0x11,0x10,0x21,0x22,0x26,0x27,0x03,0x21,0x03,0x23,0x01,0x33,0x01,0x16,0x16,0x33,0x20,0x01,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x06,0x92,0xa8,0xfd,0xdf,0x34,0x59,0x34,0x98,0xfd,0xa0,0x8f,0xbb,0x02,0x26,0xae,0x01,0xf5,0x12,0x29, 0x11,0x01,0x67,0xfc,0xf7,0xe1,0x05,0x0c,0x05,0x04,0x05,0x0b,0x07,0xdf,0x02,0x29,0x03,0x71,0xfc,0xaa,0xfd,0xa4,0x0a,0x0e,0x01,0x92,0xfe,0x6e,0x05,0x9a,0xfa,0xea,0x03,0x02,0x01,0xaa,0x02,0x63,0x0f,0x30,0x21,0x1f,0x30,0x11,0xfd,0x9d,0x00,0x02,0x00,0x5a,0xff,0xe8,0x06,0x1e,0x04,0x18,0x00,0x26,0x00,0x31,0x00,0x50,0x40,0x2b, 0x1d,0x84,0x2a,0x12,0x08,0x2a,0x02,0x00,0x84,0x24,0x2a,0x24,0x2a,0x24,0x33,0x2e,0x83,0x18,0x0f,0x25,0x0f,0x18,0x16,0x95,0x1b,0x2a,0x96,0x12,0x12,0x1b,0x0f,0x08,0x31,0x95,0x0c,0x16,0x02,0x21,0x95,0x05,0x16,0x01,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x39,0x2f,0xed,0x10,0xed,0x32,0x3f,0x01,0x2f,0xc4,0xe1,0x12, 0x39,0x39,0x2f,0x2f,0x10,0xe9,0x33,0x11,0x33,0x33,0x10,0xe9,0x31,0x30,0x21,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x00,0x36,0x35,0x35,0x07,0x06,0x06,0x15,0x14,0x16,0x33, 0x06,0x1e,0x9f,0x04,0x63,0xd0,0x75,0x98,0x2f,0x03,0x3f,0xc0,0x6a,0x99,0xad,0x01,0x52,0x01,0x33,0x6b,0x68,0xba,0x94,0x97,0xc5,0x01,0x69,0x7b,0x74,0x74,0x94,0xa4,0xfc,0x27,0x9a,0xf7,0x8f,0x57,0x6e,0x56,0xa2,0xba,0x57,0x65,0x5d,0x5f,0xa1,0x87,0x01,0x1f,0x2f,0x2b,0x11,0x75,0x7f,0x7e,0xa8,0x60,0xfe,0x82,0xf4,0x92,0xa2,0xb2, 0x8e,0x02,0x4e,0xfc,0x72,0xa9,0x8f,0x5c,0x22,0x15,0x5e,0x55,0x4b,0x5f,0x00,0x02,0x00,0x16,0x00,0x00,0x07,0x24,0x05,0x9a,0x00,0x10,0x00,0x1a,0x00,0x32,0x40,0x18,0x15,0x05,0x00,0x0a,0x0b,0x0b,0x1c,0x0c,0x06,0x00,0x0f,0x91,0x1a,0x1a,0x01,0x10,0x05,0x0d,0x12,0x0a,0x03,0x15,0x01,0x03,0x00,0x3f,0xcd,0x3f,0x3f,0x33,0x33,0x12, 0x39,0x2f,0xed,0x01,0x2f,0x2f,0x33,0x11,0x33,0x2f,0x33,0x12,0x39,0x39,0x31,0x30,0x33,0x01,0x33,0x01,0x16,0x17,0x33,0x34,0x36,0x37,0x01,0x33,0x01,0x23,0x03,0x21,0x03,0x01,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x16,0x02,0x26,0xae,0x01,0xb5,0x14,0x0b,0x04,0x10,0x08,0x01,0x95,0xb5,0xfd,0xed,0xb9,0x98,0xfd,0xa0,0x8f, 0x02,0xb8,0xe1,0x05,0x0c,0x05,0x04,0x05,0x0b,0x07,0xdf,0x05,0x9a,0xfb,0x8f,0x36,0x49,0x18,0x51,0x16,0x04,0x71,0xfa,0x66,0x01,0x92,0xfe,0x6e,0x02,0x29,0x02,0x63,0x0f,0x30,0x21,0x1f,0x30,0x11,0xfd,0x9d,0x00,0x02,0x00,0x5a,0xff,0xe8,0x05,0x3a,0x04,0x18,0x00,0x1b,0x00,0x26,0x00,0x45,0x40,0x24,0x0c,0x04,0x84,0x17,0x0e,0x1f, 0x1f,0x14,0x0a,0x0b,0x0b,0x28,0x23,0x83,0x1b,0x14,0x1f,0x96,0x05,0x17,0x17,0x02,0x0e,0x26,0x95,0x11,0x16,0x0c,0x15,0x0a,0x0f,0x1b,0x19,0x95,0x02,0x10,0x00,0x3f,0xed,0x32,0x3f,0x3f,0x3f,0xed,0x32,0x11,0x39,0x2f,0x39,0xed,0x01,0x2f,0xc4,0xe9,0x11,0x33,0x2f,0x33,0x12,0x39,0x2f,0x33,0x33,0xe9,0x32,0x31,0x30,0x13,0x36,0x33, 0x20,0x11,0x11,0x33,0x36,0x36,0x37,0x13,0x33,0x01,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x00,0x36,0x35,0x35,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0xbe,0x97,0xc5,0x01,0x69,0x04,0x03,0x16,0x11,0xdc,0xad,0xfe,0x4a,0xa5,0x04,0x6a,0xd1,0x99,0xad,0x01,0x52,0x01,0x33,0xd3,0xba,0x94,0x01,0x87, 0x9a,0xf7,0x8f,0x57,0x6e,0x56,0x03,0xb8,0x60,0xfe,0x82,0xfe,0x87,0x24,0x51,0x2a,0x02,0x40,0xfc,0x00,0xa0,0xb8,0xa1,0x87,0x01,0x1f,0x2f,0x2b,0x01,0x05,0x7e,0xfd,0x62,0xa9,0x8f,0x5c,0x22,0x15,0x5e,0x55,0x4b,0x5f,0x00,0x03,0x00,0x16,0x00,0x00,0x07,0x24,0x05,0x9a,0x00,0x0f,0x00,0x19,0x00,0x22,0x00,0x3b,0x40,0x1c,0x00,0x1d, 0x10,0x1d,0x05,0x0d,0x0a,0x0b,0x0b,0x24,0x05,0x22,0x0f,0x03,0x91,0x0c,0x08,0x1c,0x14,0x14,0x04,0x10,0x0a,0x06,0x03,0x01,0x04,0x12,0x00,0x3f,0x33,0x3f,0x33,0xcd,0x12,0x39,0x2f,0x39,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0x11,0x33,0x2f,0x33,0xc6,0x12,0x39,0x39,0x11,0x33,0x31,0x30,0x21,0x23,0x03,0x21,0x03,0x23,0x01,0x33,0x01, 0x21,0x13,0x33,0x03,0x33,0x15,0x21,0x01,0x06,0x06,0x07,0x03,0x21,0x03,0x26,0x26,0x27,0x01,0x16,0x17,0x33,0x34,0x36,0x37,0x13,0x21,0x05,0x11,0xb9,0xe5,0xfe,0x3a,0xdc,0xbb,0x02,0x26,0xae,0x01,0x02,0x01,0x94,0xef,0xb5,0xf9,0xcd,0xfe,0xfb,0xfc,0x9b,0x05,0x0b,0x07,0x93,0x01,0x57,0x93,0x05,0x0c,0x05,0x02,0x0d,0x14,0x0b,0x04, 0x10,0x08,0x70,0xfe,0xdc,0x02,0x64,0xfd,0x9c,0x05,0x9a,0xfd,0x61,0x02,0x9f,0xfd,0x61,0x97,0x02,0x88,0x1f,0x30,0x11,0xfe,0x6f,0x01,0x91,0x0f,0x30,0x21,0xfc,0x3d,0x36,0x49,0x18,0x51,0x16,0x01,0x3b,0x00,0x00,0x03,0x00,0x5a,0xff,0xe8,0x05,0x3a,0x04,0x18,0x00,0x1d,0x00,0x24,0x00,0x2f,0x00,0x4d,0x40,0x28,0x1a,0x17,0x18,0x18, 0x31,0x1d,0x15,0x1f,0x84,0x0a,0x01,0x2f,0x28,0x83,0x0f,0x07,0x17,0x0f,0x0f,0x0d,0x95,0x12,0x1f,0x1c,0x2f,0x96,0x19,0x15,0x20,0x0a,0x0a,0x12,0x10,0x01,0x2b,0x95,0x04,0x16,0x00,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x39,0x2f,0x39,0x33,0x33,0xed,0x32,0x32,0x10,0xed,0x32,0x3f,0x01,0x2f,0xc4,0xe9,0x2f,0x33,0x33,0xe9,0x32,0x32, 0x11,0x33,0x2f,0x33,0xc6,0x31,0x30,0x21,0x35,0x23,0x06,0x23,0x22,0x26,0x35,0x34,0x24,0x21,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x11,0x15,0x33,0x13,0x33,0x03,0x33,0x15,0x23,0x03,0x13,0x23,0x15,0x33,0x36,0x36,0x37,0x27,0x20,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x02,0xdf,0x04,0x6a,0xd1,0x99,0xad,0x01,0x29, 0x01,0x5c,0x69,0x6a,0xba,0x94,0x97,0xc5,0x01,0x69,0x7e,0x8c,0xad,0x9f,0x77,0xaf,0xdf,0x4b,0x4c,0x04,0x05,0x20,0x11,0xf3,0xfe,0xf6,0xbe,0x6e,0x56,0x7f,0x9a,0xa0,0xb8,0xa1,0x87,0xbe,0xbf,0x83,0x7e,0x7e,0xa8,0x60,0xfe,0x82,0x0d,0x01,0x73,0xfe,0x8d,0x83,0xfd,0xf6,0x02,0x0a,0xf1,0x2e,0x64,0x2e,0x31,0x76,0x78,0x4b,0x5f,0xa9, 0x8f,0x60,0x00,0x02,0x00,0x16,0xfe,0x1e,0x07,0x24,0x05,0x9a,0x00,0x1c,0x00,0x26,0x00,0x42,0x40,0x22,0x21,0x00,0x0c,0x05,0x19,0x03,0x0b,0x13,0x13,0x00,0x0a,0x0b,0x0b,0x28,0x00,0x1b,0x91,0x05,0x1c,0x26,0x26,0x01,0x19,0x1c,0x12,0x15,0x91,0x0f,0x1c,0x0a,0x03,0x21,0x01,0x03,0x00,0x3f,0xcd,0x3f,0x3f,0xed,0x3f,0x33,0x12,0x39, 0x2f,0x12,0x39,0xed,0x01,0x2f,0x11,0x33,0x2f,0x33,0x12,0x39,0x2f,0x12,0x17,0x39,0x12,0x39,0x31,0x30,0x33,0x01,0x33,0x01,0x16,0x17,0x33,0x34,0x36,0x37,0x01,0x33,0x01,0x06,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x37,0x37,0x03,0x21,0x03,0x01,0x03,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x16,0x02,0x26,0xae,0x01, 0xb5,0x14,0x0b,0x04,0x10,0x08,0x01,0x95,0xb5,0xfd,0xe5,0x5f,0xb6,0x8c,0x1e,0x30,0x1d,0x31,0x30,0x3a,0x60,0x22,0x48,0xa2,0xfd,0xa0,0x8f,0x02,0xb8,0xe1,0x05,0x0c,0x05,0x04,0x05,0x0b,0x07,0xdf,0x05,0x9a,0xfb,0x8f,0x36,0x49,0x18,0x51,0x16,0x04,0x71,0xfa,0x53,0xfd,0xd2,0x05,0x08,0x9d,0x12,0x56,0x50,0xa4,0x01,0x92,0xfe,0x6e, 0x02,0x29,0x02,0x63,0x0f,0x30,0x21,0x1f,0x30,0x11,0xfd,0x9d,0x00,0x02,0x00,0x5a,0xfe,0x1e,0x05,0x3a,0x04,0x18,0x00,0x25,0x00,0x30,0x00,0x56,0x40,0x2d,0x28,0x13,0x84,0x25,0x0a,0x1b,0x25,0x1a,0x20,0x25,0x20,0x25,0x07,0x19,0x1a,0x1a,0x32,0x2d,0x83,0x07,0x0e,0x0e,0x07,0x22,0x95,0x1d,0x1c,0x19,0x0f,0x0e,0x0c,0x95,0x11,0x29, 0x96,0x14,0x0a,0x0a,0x11,0x10,0x00,0x30,0x95,0x04,0x16,0x00,0x3f,0xed,0x32,0x3f,0x39,0x2f,0x39,0xed,0x10,0xed,0x32,0x3f,0x3f,0xed,0x01,0x2f,0x33,0x2f,0x10,0xe9,0x11,0x33,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x32,0x10,0xe9,0x33,0x31,0x30,0x25,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x10,0x25,0x25,0x10,0x23,0x22, 0x07,0x35,0x36,0x33,0x20,0x11,0x11,0x33,0x36,0x36,0x37,0x13,0x33,0x01,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x37,0x26,0x36,0x35,0x35,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x02,0xe4,0x04,0x36,0xa1,0x69,0x99,0xad,0x01,0x52,0x01,0x33,0xd3,0xba,0x94,0x97,0xc5,0x01,0x69,0x04,0x03,0x18,0x10,0xdb,0xad,0xfe,0x0a,0x7e,0xe4, 0x41,0x2a,0x34,0x2d,0x7f,0x3d,0x50,0x9f,0x9a,0xf7,0x8f,0x57,0x6e,0x56,0xa8,0x5d,0x63,0xa1,0x87,0x01,0x1f,0x2f,0x2b,0x01,0x05,0x7e,0xa8,0x60,0xfe,0x82,0xfe,0x8c,0x24,0x51,0x2a,0x02,0x3b,0xfb,0x5c,0xfe,0xc2,0x0d,0x93,0x12,0x94,0xc2,0x70,0xa9,0x8f,0x5c,0x22,0x15,0x5e,0x55,0x4b,0x5f,0x00,0x02,0x00,0x68,0xff,0xe8,0x04,0x96, 0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0x37,0x40,0x1c,0x1b,0xc0,0x21,0x10,0x7d,0x05,0x21,0x05,0x21,0x05,0x23,0x0a,0x15,0x1e,0xc1,0x18,0x18,0x0d,0x00,0x02,0x91,0x13,0x13,0x0a,0x08,0x91,0x0d,0x04,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x11,0x39,0x2f,0xed,0x01,0x2f,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x31,0x30,0x37, 0x16,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x27,0x00,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x68,0x9d,0xd9,0xea,0x01,0x1e,0xfe,0xcc,0xf6,0xb9,0x9b,0x87,0xcb,0x01,0x3e,0x01,0x9e,0xfe,0x8f,0xfe,0xcf,0xed,0x9f,0x01,0x27,0x3a,0x29,0x2a,0x38,0x38,0x2a, 0x29,0x3a,0xdf,0x60,0x01,0x38,0x01,0x05,0x01,0x14,0x01,0x4a,0x56,0xb3,0x3b,0xfe,0x58,0xfe,0xa8,0xfe,0xbf,0xfe,0x77,0x54,0x02,0xc2,0x37,0x36,0x2a,0x2a,0x39,0x3b,0x28,0x00,0x00,0x02,0x00,0x50,0xff,0xe8,0x03,0x52,0x04,0x18,0x00,0x15,0x00,0x21,0x00,0x37,0x40,0x1c,0x1b,0xc0,0x21,0x10,0x83,0x05,0x21,0x05,0x21,0x05,0x23,0x0a, 0x15,0x1e,0xc1,0x18,0x18,0x0d,0x00,0x02,0x95,0x13,0x16,0x0a,0x08,0x95,0x0d,0x10,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x11,0x39,0x2f,0xed,0x01,0x2f,0xc6,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x31,0x30,0x37,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x27,0x12, 0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x52,0x77,0x85,0x9e,0xbe,0xca,0x9c,0x81,0x73,0x69,0x85,0xf1,0x01,0x23,0xfe,0xf3,0xdb,0xa1,0x77,0xa1,0x3a,0x29,0x2a,0x38,0x38,0x2a,0x29,0x3a,0xcb,0x59,0xd0,0xb4,0xb6,0xe2,0x50,0xa8,0x32,0xfe,0xcd,0xfd,0xe4,0xfe,0xe4,0x47,0x01,0xfd,0x37,0x36,0x2a,0x2a,0x39,0x3b,0x28, 0x00,0x01,0x00,0x12,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x19,0x00,0x46,0x40,0x23,0x17,0x18,0x00,0x19,0x10,0x10,0x07,0x01,0x00,0x00,0x1b,0x12,0x0e,0x06,0x7e,0x0b,0x09,0x07,0x11,0x09,0x92,0x0e,0x04,0x19,0x12,0x03,0x0a,0x0a,0x07,0x17,0x0c,0x03,0x01,0x07,0x12,0x00,0x3f,0x33,0x3f,0x33,0x12,0x39,0x2f,0x17,0x39,0x33,0xed,0x32, 0x01,0x2f,0xc6,0x33,0xe1,0x32,0x32,0x11,0x33,0x2f,0x33,0x12,0x39,0x2f,0x39,0x10,0xc6,0x32,0x31,0x30,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x04,0xa2,0xea,0xfd,0xd6,0x1e,0x08,0x04,0xa8,0xaa,0xaa,0xa8,0xe8,0xe8,0x04,0x07,0x13,0x0c, 0x02,0x18,0xd1,0xfd,0x99,0x02,0x90,0x24,0x0e,0xfd,0x3e,0x04,0x9c,0x85,0x79,0x79,0x85,0xfe,0x5c,0x0b,0x18,0x0e,0x02,0x71,0xfd,0x50,0x00,0x01,0x00,0x27,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x14,0x00,0x43,0x40,0x22,0x09,0x09,0x0d,0x0e,0x11,0x0e,0x10,0x10,0x16,0x0f,0x0b,0x07,0x14,0x84,0x04,0x02,0x00,0x0d,0x0f,0x0a,0x02,0x96, 0x07,0x12,0x0f,0x0b,0x03,0x03,0x03,0x05,0x00,0x11,0x00,0x15,0x00,0x3f,0x32,0x3f,0x39,0x2f,0x17,0x39,0x33,0xed,0x32,0x3f,0x01,0x2f,0xc6,0x33,0xe1,0x32,0x32,0x32,0x11,0x33,0x11,0x33,0x33,0x2f,0x33,0x39,0x2f,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x01,0x33,0x01,0x01,0x23,0x01,0x23,0x11, 0xa6,0x7f,0x7f,0xa4,0x01,0x54,0xfe,0xac,0x04,0x01,0xae,0xd7,0xfe,0x25,0x02,0x00,0xe6,0xfe,0x3c,0x04,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfd,0x79,0x01,0xd5,0xfe,0x12,0xfd,0xee,0x01,0xec,0xfe,0x14,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x19,0x00,0x41,0x40,0x21,0x0a,0x0c,0x13,0x0c,0x13,0x0c,0x08,0x09,0x09,0x10, 0x0f,0x0f,0x1b,0x03,0x19,0x7e,0x00,0x13,0x12,0x0d,0x0c,0x0c,0x03,0x0a,0x17,0x12,0x05,0x08,0x01,0x03,0x10,0x00,0x12,0x00,0x3f,0x32,0x3f,0x33,0x17,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0xe1,0x32,0x11,0x33,0x2f,0x33,0x33,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x12,0x39,0x31,0x30,0x33,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01, 0x17,0x01,0x15,0x07,0x01,0x23,0x01,0x07,0x35,0x37,0x27,0x26,0x27,0x23,0x11,0xbc,0xa8,0x04,0x07,0x13,0x0c,0x02,0x18,0xd1,0xfd,0x99,0xa5,0x01,0x08,0xa8,0x01,0x8d,0xea,0xfe,0xec,0xcc,0x6e,0xb8,0x1e,0x08,0x04,0x05,0x9a,0xfd,0x5e,0x0b,0x18,0x0e,0x02,0x71,0xfd,0x50,0xbc,0x01,0x21,0xd5,0xb8,0xfe,0x3e,0x01,0x46,0xe1,0xd7,0x79, 0xdb,0x24,0x0e,0xfd,0x3e,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x14,0x00,0x40,0x40,0x21,0x02,0x13,0x84,0x14,0x0e,0x08,0x0e,0x08,0x05,0x14,0x04,0x05,0x05,0x0c,0x0b,0x0f,0x0e,0x09,0x08,0x08,0x02,0x06,0x11,0x0e,0x05,0x04,0x0c,0x14,0x15,0x04,0x0f,0x00,0x00,0x00,0x3f,0x3f,0x3f,0x33,0x12,0x17,0x39,0x11, 0x33,0x11,0x33,0x01,0x2f,0x33,0x33,0x2f,0x33,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x32,0x31,0x30,0x13,0x33,0x11,0x33,0x01,0x33,0x01,0x17,0x37,0x15,0x07,0x01,0x23,0x27,0x07,0x35,0x37,0x27,0x23,0x11,0x23,0xa6,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0x67,0xe6,0x88,0x01,0x3b,0xe6,0xc4,0x99,0x3e,0xa5,0x04,0xa4,0x05,0xec,0xfc, 0x3f,0x01,0xd5,0xfe,0x12,0x6b,0xee,0xc2,0x8d,0xfe,0xba,0xd4,0x9e,0xc2,0x40,0xb4,0xfe,0x14,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x21,0x00,0x54,0x40,0x2b,0x12,0x14,0x1b,0x14,0x1b,0x14,0x10,0x11,0x11,0x18,0x17,0x17,0x23,0x0b,0x07,0x21,0x7e,0x04,0x02,0x00,0x0a,0x02,0x92,0x07,0x03,0x15,0x14,0x1b,0x1a,0x1a, 0x1f,0x12,0x0b,0x14,0x05,0x03,0x03,0x10,0x05,0x03,0x18,0x00,0x12,0x00,0x3f,0x32,0x3f,0x33,0x39,0x2f,0x17,0x39,0x11,0x33,0x11,0x33,0x11,0x33,0xed,0x32,0x01,0x2f,0xc6,0x33,0xe1,0x32,0x32,0x11,0x33,0x2f,0x33,0x33,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x12,0x39,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11, 0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x17,0x01,0x15,0x07,0x01,0x23,0x01,0x07,0x35,0x37,0x27,0x26,0x27,0x23,0x11,0xbc,0xaa,0xaa,0xa8,0xe8,0xe8,0x04,0x07,0x13,0x0c,0x02,0x18,0xd1,0xfd,0x99,0xa5,0x01,0x08,0xa8,0x01,0x8d,0xea,0xfe,0xec,0xcc,0x6e,0xb8,0x1e,0x08,0x04,0x04,0x9c,0x85,0x79,0x79,0x85,0xfe,0x5c,0x0b,0x18,0x0e,0x02, 0x71,0xfd,0x50,0xbc,0x01,0x21,0xd5,0xb8,0xfe,0x3e,0x01,0x46,0xe1,0xd7,0x79,0xdb,0x24,0x0e,0xfd,0x3e,0x00,0x01,0x00,0x27,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x1c,0x00,0x59,0x40,0x2e,0x0d,0x0f,0x16,0x0f,0x16,0x0f,0x0b,0x0c,0x0c,0x13,0x12,0x12,0x1e,0x09,0x05,0x1a,0x84,0x02,0x00,0x1b,0x10,0x0f,0x16,0x15,0x15,0x18,0x0d,0x09, 0x0f,0x05,0x0b,0x1b,0x08,0x00,0x96,0x05,0x01,0x01,0x03,0x13,0x1b,0x15,0x0b,0x0f,0x03,0x00,0x00,0x3f,0x3f,0x3f,0x33,0x12,0x39,0x2f,0x33,0xed,0x32,0x11,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0x01,0x2f,0xc6,0x33,0xe1,0x32,0x32,0x11,0x33,0x2f,0x33,0x33,0x2f,0x33,0x39,0x39,0x2f,0x2f,0x12,0x39,0x31,0x30,0x13,0x35,0x33,0x35,0x33, 0x15,0x21,0x15,0x21,0x11,0x33,0x01,0x33,0x01,0x17,0x37,0x15,0x07,0x01,0x23,0x27,0x07,0x35,0x37,0x27,0x23,0x11,0x23,0x11,0x27,0x7f,0xa4,0x01,0x54,0xfe,0xac,0x04,0x01,0xae,0xd7,0xfe,0x25,0x67,0xe6,0x88,0x01,0x3b,0xe6,0xc4,0x99,0x3e,0xa5,0x04,0xa4,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfd,0x79,0x01,0xd5,0xfe,0x12,0x6b,0xee,0xc2, 0x8d,0xfe,0xba,0xd4,0x9e,0xc2,0x40,0xb4,0xfe,0x14,0x04,0xb2,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0x3b,0x05,0x9a,0x00,0x09,0x00,0x2a,0x40,0x16,0x01,0x7e,0x04,0x02,0x04,0x02,0x0b,0x08,0x7e,0x06,0x06,0x05,0x09,0x00,0x04,0x04,0x07,0x03,0x01,0x91,0x04,0x12,0x00,0x3f,0xed,0x3f,0x12,0x17,0x39,0x01,0x2f,0xe1,0x12,0x39,0x39,0x2f, 0x2f,0xe1,0x31,0x30,0x01,0x11,0x21,0x15,0x21,0x11,0x07,0x11,0x33,0x11,0x01,0xfc,0x02,0x3f,0xfd,0x18,0x97,0xa9,0x03,0x18,0xfd,0x80,0x98,0x02,0xa8,0x2f,0x03,0x21,0xfd,0x4d,0x00,0x01,0x00,0xa6,0x00,0x00,0x01,0xdc,0x05,0xed,0x00,0x07,0x00,0x2b,0x40,0x16,0x06,0x84,0x04,0x00,0x84,0x02,0x04,0x02,0x04,0x02,0x08,0x09,0x04,0x03, 0x07,0x00,0x04,0x02,0x05,0x00,0x02,0x15,0x00,0x3f,0x3f,0x12,0x17,0x39,0x11,0x12,0x01,0x39,0x39,0x2f,0x2f,0x10,0xe1,0x10,0xe1,0x31,0x30,0x01,0x11,0x23,0x11,0x07,0x11,0x33,0x11,0x01,0xdc,0xa4,0x92,0xa4,0x03,0x43,0xfc,0xbd,0x02,0xd5,0x2e,0x03,0x46,0xfd,0x26,0x00,0x00,0x01,0x00,0x12,0x00,0x00,0x03,0xa4,0x05,0x9a,0x00,0x0d, 0x00,0x2d,0x40,0x16,0x09,0x0c,0x09,0x0c,0x0f,0x0b,0x7e,0x02,0x00,0x0a,0x02,0x92,0x07,0x03,0x03,0x00,0x05,0x03,0x0b,0x91,0x00,0x12,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xc6,0xe1,0x12,0x39,0x39,0x2f,0x2f,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x21,0x15,0xbc,0xaa,0xaa, 0xa8,0xe8,0xe8,0x02,0x40,0x04,0x9c,0x85,0x79,0x79,0x85,0xfb,0xfc,0x98,0x00,0x01,0x00,0x1e,0x00,0x00,0x01,0xd2,0x05,0xec,0x00,0x0b,0x00,0x2c,0x40,0x15,0x09,0x09,0x07,0x0a,0x84,0x04,0x02,0x00,0x00,0x0c,0x0d,0x0a,0x02,0x96,0x07,0x03,0x03,0x05,0x00,0x00,0x15,0x00,0x3f,0x3f,0x39,0x2f,0x33,0xed,0x32,0x11,0x12,0x01,0x39,0x2f, 0xc6,0x33,0xf1,0x32,0xc1,0x2f,0x31,0x30,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0xa6,0x88,0x88,0xa4,0x88,0x88,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfb,0x4e,0x00,0x03,0x00,0x00,0xff,0xe8,0x06,0x08,0x05,0xb2,0x00,0x11,0x00,0x18,0x00,0x1f,0x00,0x3f,0x40,0x20,0x0a,0x0a,0x08,0x0b,0x7d,0x12,0x1f,0x1f,0x21,0x18, 0x19,0x7d,0x02,0x00,0x11,0x19,0x0b,0x11,0x91,0x18,0x08,0x02,0x02,0x05,0x1c,0x91,0x0e,0x13,0x15,0x91,0x05,0x04,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcd,0x33,0xe1,0x32,0x12,0x39,0x2f,0x33,0xf1,0x32,0xc1,0x2f,0x31,0x30,0x11,0x35,0x33,0x12,0x00,0x21,0x20,0x00,0x13,0x33,0x15,0x23,0x02, 0x00,0x21,0x20,0x00,0x03,0x25,0x26,0x02,0x23,0x22,0x00,0x07,0x15,0x16,0x00,0x33,0x32,0x00,0x37,0x61,0x14,0x01,0x7a,0x01,0x27,0x01,0x1e,0x01,0x5d,0x17,0x60,0x62,0x16,0xfe,0x91,0xfe,0xdd,0xfe,0xdc,0xfe,0x9a,0x14,0x04,0x97,0x15,0xfe,0xda,0xd3,0xfe,0xee,0x14,0x14,0x01,0x0f,0xca,0xdf,0x01,0x05,0x15,0x02,0x7e,0x9b,0x01,0x2c, 0x01,0x6d,0xfe,0x9e,0xfe,0xc9,0x9b,0xfe,0xd0,0xfe,0x9a,0x01,0x69,0x01,0x2d,0x9b,0xf9,0x01,0x08,0xfe,0xea,0xeb,0x9b,0xe6,0xfe,0xe7,0x01,0x09,0xf6,0x00,0x00,0x03,0x00,0x00,0xff,0xe8,0x04,0xb0,0x04,0x18,0x00,0x11,0x00,0x18,0x00,0x1f,0x00,0x3b,0x40,0x1e,0x08,0x08,0x07,0x0a,0x83,0x19,0x18,0x1f,0x12,0x83,0x01,0x00,0x10,0x12, 0x0a,0x11,0x95,0x1f,0x07,0x00,0x00,0x04,0x15,0x95,0x0d,0x16,0x1c,0x95,0x04,0x10,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0x33,0xed,0x32,0x32,0x01,0x2f,0xcd,0x33,0xe1,0x32,0x2f,0x33,0xf1,0x32,0xc1,0x2f,0x31,0x30,0x11,0x33,0x36,0x24,0x33,0x32,0x16,0x17,0x33,0x15,0x23,0x06,0x00,0x23,0x22,0x00,0x27,0x23,0x21,0x16,0x16, 0x33,0x32,0x36,0x37,0x27,0x26,0x26,0x23,0x22,0x06,0x07,0x66,0x1e,0x01,0x10,0xd6,0xce,0xfd,0x16,0x65,0x62,0x10,0xfe,0xf2,0xde,0xdc,0xfe,0xf9,0x0e,0x61,0x01,0x0a,0x0c,0xb1,0x97,0x96,0xa5,0x0d,0x04,0x15,0xa3,0x8c,0x87,0xb0,0x19,0x02,0x5b,0xd0,0xed,0xec,0xd1,0x8b,0xe1,0xfe,0xf9,0x01,0x04,0xe4,0xa4,0xba,0xb2,0xac,0x8c,0x95, 0x9d,0xa0,0x92,0x00,0x00,0x03,0x00,0x5e,0xff,0xe8,0x06,0xcb,0x05,0xb2,0x00,0x15,0x00,0x21,0x00,0x2c,0x00,0x44,0x40,0x25,0x00,0x2b,0x22,0x03,0x11,0x0b,0x7d,0x1b,0x06,0x7f,0x25,0x1b,0x25,0x1b,0x25,0x2e,0x21,0x7d,0x11,0x1e,0x91,0x14,0x04,0x22,0x92,0x09,0x09,0x03,0x18,0x91,0x0e,0x13,0x00,0x28,0x92,0x03,0x04,0x00,0x3f,0xed, 0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x3f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x11,0x17,0x39,0x31,0x30,0x01,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x17,0x15,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x15,0x25,0x36,0x36,0x35, 0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x04,0xda,0x26,0x7c,0x55,0x73,0x87,0xa0,0x83,0x02,0xfe,0x8e,0xfe,0xc6,0xfe,0xd0,0xfe,0x90,0x01,0x78,0x01,0x40,0x01,0x14,0xfc,0xe4,0x01,0x11,0xdf,0xef,0x01,0x0d,0xfe,0xfd,0xed,0xe8,0xfe,0xec,0x04,0x89,0x47,0x59,0x39,0x37,0x31,0x4e,0x19,0x4c,0x05,0x04,0x52,0x5c,0x9d,0x84,0x95,0xcd,0x11, 0x1f,0x20,0xfe,0xa8,0xfe,0x61,0x01,0x97,0x01,0x3d,0x01,0x59,0x01,0x9d,0xfc,0x1a,0xfe,0xb3,0x01,0x40,0x01,0x09,0x01,0x17,0x01,0x3b,0xfe,0xac,0xfb,0xd3,0x13,0x7e,0x57,0x4f,0x56,0x4a,0x42,0x71,0x00,0x03,0x00,0x60,0xff,0xe8,0x05,0x4b,0x04,0x18,0x00,0x13,0x00,0x1f,0x00,0x2a,0x00,0x45,0xb7,0x20,0x29,0x04,0x03,0x0d,0x84,0x19, 0x0a,0xb8,0x01,0x03,0x40,0x1b,0x23,0x19,0x23,0x19,0x23,0x2c,0x1f,0x83,0x13,0x20,0x96,0x0d,0x0d,0x07,0x16,0x95,0x10,0x16,0x04,0x26,0x96,0x07,0x0f,0x1c,0x95,0x02,0x10,0x00,0x3f,0xed,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x17,0x39,0x31,0x30,0x12,0x00,0x33, 0x32,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x06,0x00,0x23,0x22,0x00,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x25,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x60,0x01,0x1b,0xef,0xc4,0x7a,0x22,0x61,0x3c,0x6a,0x7a,0x8e,0x6f,0x16,0xfe,0xef,0xd5,0xe3,0xfe,0xf1,0xa8,0xba,0x9c,0xa1, 0xa9,0xa8,0xa2,0x9f,0xb7,0x03,0x45,0x39,0x40,0x34,0x31,0x23,0x33,0x14,0x4a,0x02,0xef,0x01,0x29,0x68,0x2f,0x39,0x8d,0x79,0x79,0xb8,0x15,0xe0,0xfe,0xfc,0x01,0x24,0xe8,0xa9,0xd9,0xcf,0xbd,0xbf,0xd1,0xe1,0xb3,0x4c,0x19,0x67,0x45,0x40,0x55,0x29,0x1f,0x70,0x00,0x03,0x00,0x5e,0xff,0xe8,0x0a,0x47,0x05,0xb2,0x00,0x19,0x00,0x25, 0x00,0x31,0x00,0x3f,0x40,0x22,0x00,0x0d,0x25,0x7d,0x2b,0x2b,0x07,0x13,0x7d,0x1f,0x1f,0x33,0x31,0x7d,0x07,0x1c,0x91,0x16,0x13,0x22,0x91,0x10,0x04,0x0d,0x00,0x04,0x2e,0x91,0x0a,0x04,0x28,0x91,0x04,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x39, 0x39,0x31,0x30,0x01,0x0e,0x02,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x32,0x04,0x17,0x36,0x24,0x33,0x20,0x00,0x11,0x10,0x00,0x21,0x22,0x26,0x26,0x36,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x11,0x00,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x11,0x05,0x50,0x1e,0xb0,0xef,0x95,0xfe,0xcf,0xfe,0x91,0x01,0x77, 0x01,0x41,0xd1,0x01,0x2c,0x43,0x42,0x01,0x39,0xe2,0x01,0x28,0x01,0x6c,0xfe,0x8c,0xfe,0xc8,0x93,0xec,0xae,0x3d,0x01,0x12,0xde,0xec,0x01,0x10,0xfe,0xf8,0xe8,0xe2,0xfe,0xe6,0xfb,0x63,0x01,0x12,0xde,0xec,0x01,0x10,0xfe,0xf8,0xe8,0xe2,0xfe,0xe6,0x01,0x4a,0x54,0xb2,0x5c,0x01,0x91,0x01,0x43,0x01,0x5b,0x01,0x9b,0xc5,0x9e,0x9a, 0xc9,0xfe,0x70,0xfe,0xbd,0xfe,0xa1,0xfe,0x68,0x5d,0xb1,0xcb,0xfe,0xbe,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0xfe,0xb9,0xfe,0xf8,0xfe,0xf6,0xfe,0xbe,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0xfe,0xb9,0xfe,0xf8,0x00,0x03,0x00,0x60,0xff,0xe8,0x07,0x98,0x04,0x18,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x3f,0x40,0x22,0x00,0x0c, 0x23,0x83,0x29,0x29,0x06,0x12,0x83,0x1d,0x1d,0x31,0x2f,0x83,0x06,0x1a,0x95,0x15,0x16,0x20,0x95,0x0f,0x10,0x0c,0x00,0x03,0x2c,0x95,0x09,0x10,0x26,0x95,0x03,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0xed,0x3f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x39,0x39,0x31,0x30,0x25,0x06,0x06,0x23,0x22, 0x00,0x35,0x10,0x00,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x00,0x15,0x14,0x00,0x23,0x22,0x26,0x36,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x04,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x03,0xf9,0x2d,0xdb,0x9f,0xe4,0xfe,0xf2,0x01,0x19,0xf1,0x92,0xd7,0x2e,0x27,0xe6,0xa4,0xe6,0x01,0x00,0xfe, 0xeb,0xe9,0x98,0xde,0x2c,0xbb,0x9b,0xa1,0xa9,0xa8,0xa2,0xa0,0xb6,0xfc,0xb8,0xba,0x9c,0xa1,0xa9,0xa8,0xa2,0xa0,0xb6,0xc9,0x60,0x81,0x01,0x1f,0xed,0x01,0x01,0x01,0x23,0x75,0x6b,0x5b,0x85,0xfe,0xe5,0xf9,0xf5,0xfe,0xd9,0x81,0xd9,0xd0,0xcf,0xbd,0xbf,0xd1,0xda,0xbb,0xb5,0xd2,0xcf,0xbd,0xbf,0xd1,0xda,0xba,0x00,0x02,0x00,0x19, 0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x12,0x00,0x1a,0x00,0x47,0x40,0x24,0x0f,0x7d,0x18,0x18,0x06,0x1c,0x14,0x05,0x03,0x03,0x01,0x05,0x7e,0x0a,0x08,0x06,0x00,0x91,0x14,0x04,0x08,0x92,0x09,0x01,0x09,0x14,0x09,0x14,0x09,0x06,0x13,0x91,0x0b,0x03,0x06,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32, 0x10,0xed,0x01,0x2f,0xc6,0x33,0xf9,0x32,0xc2,0x2f,0x11,0x33,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30,0x01,0x15,0x21,0x15,0x21,0x15,0x23,0x35,0x23,0x35,0x33,0x11,0x21,0x32,0x04,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0x01,0x0d,0xfe,0xf3,0xa8,0xa3,0xa3,0x01,0x8a,0xe1,0x01,0x02,0xfe,0xe8,0xf0,0xbd, 0xb0,0xaf,0xb6,0xfe,0xb0,0x02,0x1e,0x9d,0x85,0xfc,0xfc,0x85,0x04,0x19,0xe2,0xca,0xcb,0xfe,0xfb,0x02,0xe4,0xfd,0xb4,0x9e,0x92,0x01,0x1c,0x00,0x00,0x02,0x00,0x1e,0xfe,0x29,0x04,0x54,0x04,0x18,0x00,0x19,0x00,0x26,0x00,0x49,0x40,0x27,0x0d,0x83,0x20,0x20,0x19,0x28,0x16,0x16,0x14,0x06,0x18,0x84,0x03,0x01,0x19,0x00,0x16,0x96, 0x03,0x15,0x15,0x10,0x19,0x1b,0x12,0x1d,0x95,0x2f,0x10,0x01,0x10,0x16,0x06,0x23,0x95,0x0a,0x10,0x04,0x0f,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x5d,0xed,0x32,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xc6,0x33,0xf9,0x32,0x32,0xc2,0x2f,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30,0x13,0x23,0x35,0x33,0x11,0x33,0x15,0x33,0x36,0x36,0x33, 0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x27,0x23,0x11,0x21,0x15,0x21,0x15,0x23,0x13,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0xa6,0x88,0x88,0xa4,0x04,0x3f,0xaf,0x74,0xc4,0xe0,0xfa,0xd9,0xc7,0x6c,0x04,0x01,0x4b,0xfe,0xb5,0xa4,0xa4,0xa4,0x80,0x94,0xaa,0x9e,0x87,0x8d,0xb0,0xfe,0xdd,0x86,0x04,0x9d,0xb4,0x68, 0x64,0xfe,0xee,0xe8,0xfe,0xfe,0xfe,0xcc,0xac,0xfe,0xcf,0x86,0xb4,0x03,0x79,0x80,0xb0,0xe3,0xcc,0xab,0xc2,0xc5,0x98,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x05,0x31,0x05,0x9a,0x00,0x18,0x00,0x20,0x00,0x39,0x40,0x1d,0x15,0x7d,0x1e,0x1e,0x02,0x22,0x07,0x7e,0x0c,0x1a,0x01,0x7e,0x10,0x02,0x03,0x00,0x91,0x10,0x1a,0x09,0x1a,0x09, 0x02,0x19,0x91,0x11,0x03,0x02,0x12,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x33,0xed,0x32,0x01,0x2f,0x33,0xe9,0x32,0xd4,0xe9,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30,0x01,0x11,0x23,0x11,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35, 0x10,0x21,0x02,0x6c,0xa8,0x5c,0x51,0x59,0x14,0x9e,0x16,0xca,0x9a,0x42,0x01,0x8a,0xe5,0xfe,0xfe,0xe8,0xf0,0xbd,0xb0,0xaf,0xb6,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x02,0x1e,0x5c,0x4e,0x36,0x34,0x36,0x44,0x89,0xa9,0x02,0xe4,0xe3,0xc9,0xcb,0xfe,0xfb,0x02,0xe4,0xfd,0xb4,0x9e,0x92,0x01,0x1c,0x00,0x02,0x00,0x05,0xfe,0x29,0x05,0x46, 0x04,0x18,0x00,0x1d,0x00,0x28,0x00,0x39,0x40,0x1e,0x09,0x83,0x22,0x14,0x83,0x1a,0x1e,0x02,0x0e,0x84,0x00,0x0f,0x17,0x17,0x0d,0x0f,0x1b,0x00,0x1e,0x95,0x10,0x0d,0x15,0x03,0x25,0x95,0x06,0x10,0x01,0x0f,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x33,0xed,0x32,0x3f,0x12,0x39,0x2f,0x01,0x2f,0x33,0xe9,0x32,0x32,0xd4,0xed,0x2f,0xe9,0x31, 0x30,0x25,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x00,0x21,0x23,0x11,0x23,0x11,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x3b,0x02,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x98,0xa4,0x04,0x79,0xe9,0xc4,0xe0,0xfe,0xdd,0xfe,0xf1,0xd8,0xa4,0x39,0x64,0x6c,0x1c,0x94,0x07,0x0b,0xb1,0x99, 0xed,0xe4,0xc6,0xb8,0x9e,0x87,0x8d,0xb0,0x8a,0x03,0x76,0xb4,0xcc,0xfe,0xee,0xe8,0xff,0x00,0xfe,0xe2,0xfe,0x29,0x01,0xd7,0x52,0x52,0x32,0x3a,0x0e,0x4b,0x1d,0x89,0x9b,0xd1,0xc6,0xab,0xc2,0xc5,0x98,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x06,0x27,0x05,0xb2,0x00,0x23,0x00,0x2b,0x00,0x41,0x40,0x22,0x20,0x7d,0x29,0x29,0x02,0x2d, 0x15,0x7e,0x0e,0x08,0x08,0x2c,0x25,0x01,0x7e,0x1b,0x02,0x03,0x00,0x91,0x1b,0x25,0x25,0x01,0x24,0x91,0x1c,0x03,0x0b,0x91,0x12,0x04,0x01,0x12,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0x33,0xe9,0x32,0x12,0x39,0x2f,0xc6,0xe9,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30,0x01,0x11,0x23,0x11,0x23,0x22,0x26, 0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x16,0x16,0x33,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x03,0x62,0xa8,0x27,0xcd,0xb4,0x41,0x4e,0x20,0x3a,0x1f,0x28,0x42,0x28,0x7f,0x9f,0x27,0x5b,0x55,0x29,0x01,0x8a,0xe5,0xfe,0xfe,0xe8,0xf0, 0xbd,0xb0,0xaf,0xb6,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x02,0x1e,0xb0,0xca,0xd3,0x4e,0x5b,0x0c,0x0a,0x9e,0x0b,0x0b,0x9c,0x7c,0xc4,0x83,0x6b,0x31,0x02,0xe3,0xe3,0xc9,0xcb,0xfe,0xfb,0x02,0xe4,0xfd,0xb4,0x9e,0x92,0x01,0x1c,0x00,0x00,0x02,0x00,0x05,0xfe,0x29,0x06,0x85,0x04,0x96,0x00,0x28,0x00,0x33,0x00,0x44,0x40,0x24,0x23,0x83, 0x2d,0x2d,0x00,0x35,0x15,0x84,0x0c,0x05,0x05,0x34,0x29,0x1d,0x28,0x84,0x1a,0x00,0x1d,0x30,0x95,0x20,0x10,0x09,0x95,0x11,0x1b,0x0f,0x29,0x1a,0x95,0x27,0x01,0x15,0x00,0x1b,0x00,0x3f,0x3f,0x33,0xed,0x32,0x3f,0xd4,0xed,0x3f,0xed,0x32,0x01,0x2f,0x33,0xe9,0x32,0x32,0x12,0x39,0x2f,0xc6,0xe9,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30, 0x01,0x11,0x23,0x22,0x26,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x37,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x16,0x16,0x33,0x33,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x00,0x21,0x23,0x11,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x02,0xd7,0x49,0xcd,0xb4,0x3e,0x43,0x23,0x41,0x23,0x28,0x1e, 0x31,0x20,0x83,0x92,0x29,0x5d,0x55,0x4b,0xa4,0x04,0x79,0xe9,0xc4,0xe0,0xfe,0xdd,0xfe,0xf1,0xd8,0xe4,0xc6,0xb8,0x9e,0x87,0x8d,0xb0,0xfe,0x29,0x01,0xd7,0xb0,0xca,0x01,0xf3,0x4f,0x50,0x10,0x10,0x94,0x09,0x07,0x06,0x95,0x83,0xfe,0x2b,0x81,0x6c,0x32,0x03,0x76,0xb4,0xcc,0xfe,0xee,0xe8,0xff,0x00,0xfe,0xe2,0xfe,0x29,0x02,0x61, 0xd1,0xc6,0xab,0xc2,0xc5,0x98,0x00,0x02,0x00,0x5e,0xfe,0xd0,0x06,0x25,0x05,0xb2,0x00,0x18,0x00,0x24,0x00,0x4f,0x40,0x2a,0x02,0x7d,0x1e,0x0b,0x0a,0x07,0x10,0x05,0x1e,0x0e,0x1e,0x07,0x07,0x1e,0x0e,0x03,0x26,0x24,0x7d,0x15,0x21,0x91,0x18,0x04,0x0c,0x0f,0x09,0x06,0x04,0x0b,0x0b,0x0d,0x08,0x07,0x1b,0x91,0x0e,0x0d,0x10,0x05, 0x12,0x13,0x00,0x3f,0x33,0x33,0xc6,0x32,0xfd,0xc0,0x32,0x11,0x39,0x2f,0x17,0x39,0x3f,0xed,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x39,0x10,0xc6,0x32,0x10,0xe9,0x31,0x30,0x00,0x00,0x11,0x14,0x02,0x07,0x17,0x25,0x15,0x07,0x17,0x21,0x27,0x05,0x35,0x37,0x27,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x00,0x00, 0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x11,0x04,0x3e,0x01,0x6c,0xa1,0x77,0x44,0x01,0x05,0x8d,0xd7,0xfe,0xcf,0x46,0xff,0x00,0x8a,0x52,0x6b,0x7d,0xfe,0xcf,0xfe,0x91,0x01,0x77,0x01,0x41,0xfd,0xf8,0x01,0x12,0xde,0xec,0x01,0x10,0xfe,0xf8,0xe8,0xe2,0xfe,0xe6,0x05,0xb2,0xfe,0x70,0xfe,0xbd,0xeb,0xfe,0xbd,0x51,0x31,0xa6, 0xa3,0x59,0x9a,0x34,0xa3,0xa3,0x58,0x3e,0x21,0x01,0x91,0x01,0x43,0x01,0x5b,0x01,0x9b,0xfc,0x11,0xfe,0xbc,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0xfe,0xb9,0xfe,0xf8,0x00,0x00,0x02,0x00,0x60,0xfe,0x29,0x04,0x98,0x04,0x18,0x00,0x18,0x00,0x25,0x00,0x4f,0x40,0x2b,0x14,0x17,0x84,0x00,0x25,0x10,0x04,0x00,0x02,0x00,0x16,0x16, 0x00,0x02,0x03,0x27,0x1f,0x83,0x0b,0x12,0x0f,0x10,0x1c,0x95,0x0e,0x10,0x06,0x22,0x95,0x08,0x17,0x02,0x96,0x14,0x03,0x03,0x2f,0x08,0x01,0x08,0x16,0x00,0x1b,0x00,0x3f,0x3f,0x5d,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x3f,0xed,0x32,0x3f,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x33,0x33,0x10,0xe9,0x32,0x31, 0x30,0x01,0x35,0x21,0x35,0x21,0x11,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x33,0x15,0x23,0x15,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x03,0x6c,0xfe,0xb5,0x01,0x4b,0x04,0x6b,0xf3,0xc2,0xe8,0xff,0xd9,0xd2,0x5e,0x04,0xa4,0x88,0x88,0xa4,0xa7,0x7d,0x94,0xac,0xa4, 0x85,0x90,0xab,0xfe,0x29,0xb4,0x86,0x01,0x4d,0xc8,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x8e,0xfb,0x63,0x86,0xb4,0x04,0x39,0x7f,0xad,0xdc,0xc6,0xb0,0xca,0xc6,0x95,0x00,0x02,0x00,0x5e,0xfe,0x3c,0x07,0xa9,0x05,0xb2,0x00,0x23,0x00,0x2f,0x00,0x5a,0x40,0x31,0x00,0x01,0x0e,0x7d,0x29,0x1d,0x7e,0x16,0x03,0x11,0x29,0x01,0x29,0x19, 0x22,0x16,0x16,0x22,0x19,0x29,0x01,0x05,0x31,0x2f,0x7d,0x08,0x19,0x92,0x11,0x12,0x03,0x03,0x1a,0x1a,0x05,0x2c,0x91,0x0b,0x04,0x21,0x02,0x05,0x23,0x23,0x01,0x26,0x91,0x05,0x13,0x00,0x3f,0xed,0xc6,0x39,0x2f,0x12,0x39,0x39,0x3f,0xed,0x12,0x39,0x2f,0x17,0x39,0xed,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x12, 0x39,0x39,0x10,0xe9,0x10,0xe9,0x11,0x33,0x31,0x30,0x01,0x23,0x01,0x27,0x06,0x23,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x14,0x02,0x07,0x17,0x01,0x36,0x36,0x35,0x34,0x26,0x23,0x37,0x32,0x16,0x15,0x14,0x06,0x07,0x01,0x17,0x21,0x00,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x11,0x04,0x43,0xaf,0x01,0x00,0xae, 0x6b,0x7d,0xfe,0xcf,0xfe,0x91,0x01,0x77,0x01,0x41,0x01,0x28,0x01,0x6c,0x8f,0x89,0x6e,0x01,0x38,0x64,0x6c,0x6d,0x85,0x01,0xc6,0xcc,0x59,0x8a,0xfe,0xaa,0xb5,0xfe,0xe7,0xfc,0x02,0x01,0x11,0xdf,0xec,0x01,0x10,0xfe,0xf8,0xe8,0xe2,0xfe,0xe6,0xfe,0x3c,0x01,0x4b,0x82,0x21,0x01,0x91,0x01,0x43,0x01,0x5b,0x01,0x9b,0xfe,0x70,0xfe, 0xbd,0xce,0xfe,0xac,0x5d,0x4f,0x01,0x93,0x81,0xb7,0x32,0x4c,0x4c,0x91,0x90,0x8e,0x3d,0xb4,0xb0,0xfe,0x49,0x82,0x02,0x83,0xfe,0xbd,0x01,0x34,0x01,0x15,0x01,0x1c,0x01,0x36,0xfe,0xb9,0xfe,0xf8,0x00,0x02,0x00,0x60,0xfe,0x29,0x06,0x12,0x04,0x18,0x00,0x25,0x00,0x32,0x00,0x56,0x40,0x2e,0x00,0x01,0x32,0x23,0x84,0x24,0x10,0x02, 0x24,0x1d,0xef,0x16,0x01,0x09,0x24,0x19,0x16,0x16,0x19,0x24,0x03,0x34,0x2c,0x83,0x09,0x25,0x01,0x01,0x06,0x24,0x1b,0x19,0x95,0x1a,0x10,0x0e,0x29,0x95,0x0c,0x10,0x12,0x03,0x2f,0x95,0x06,0x16,0x00,0x3f,0xed,0x32,0x32,0x3f,0xed,0x32,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x39,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39, 0x10,0xed,0x11,0x33,0x33,0x10,0xe9,0x33,0x11,0x33,0x31,0x30,0x01,0x23,0x01,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x37,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x01,0x11,0x23,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x02, 0xcd,0xa5,0x01,0x44,0x04,0x6b,0xf3,0xc2,0xe8,0xff,0xd9,0xd2,0x5e,0x04,0xa4,0x9b,0x64,0x6c,0x71,0x81,0x01,0xc4,0xc4,0x52,0x43,0x4e,0xfe,0xe1,0xa4,0xa7,0x7d,0x94,0xac,0xa4,0x85,0x90,0xab,0xfe,0x4e,0x01,0x9f,0xc3,0xc8,0x01,0x13,0xed,0xfe,0x01,0x32,0xa6,0x8e,0xfc,0xbe,0xc7,0x81,0xb7,0x32,0x4f,0x50,0x8a,0x90,0x8e,0x40,0xa4, 0x58,0x65,0xfe,0x92,0xfe,0x3e,0xf0,0x03,0x49,0x7f,0xad,0xdc,0xc6,0xb0,0xca,0xc6,0x95,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x04,0x13,0x05,0xb3,0x00,0x16,0x00,0x3d,0x40,0x1f,0x14,0x01,0x11,0x7d,0x04,0x16,0x15,0x01,0x04,0x15,0x15,0x04,0x01,0x03,0x18,0x0a,0x7e,0x0b,0x14,0x01,0x0a,0x01,0x0a,0x01,0x0e,0x16,0x12,0x07,0x91,0x0e, 0x04,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xcd,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x11,0x33,0x31,0x30,0x01,0x35,0x24,0x24,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x24,0x33,0x32,0x04,0x15,0x14,0x00,0x07,0x01,0x23,0x01,0x3c,0x01,0x0c,0x01,0x0a,0xa1,0x84,0x8f,0xb1,0x24,0xab, 0x24,0x01,0x1a,0xd4,0xd0,0x01,0x02,0xfe,0xeb,0xca,0x01,0xf0,0xd3,0x02,0x4c,0x3e,0x27,0xc6,0x94,0x7b,0x95,0x9b,0x8f,0xd2,0xf0,0xe7,0xc1,0xa8,0xfe,0xf9,0x2c,0xfd,0xd0,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x03,0x0b,0x04,0x18,0x00,0x16,0x00,0x3e,0x40,0x20,0x0b,0x0a,0x06,0x83,0x10,0x09,0x0c,0x0a,0x10,0x0c,0x0c,0x10,0x0a,0x03, 0x18,0x16,0x84,0x00,0x0c,0x09,0x96,0x0d,0x00,0x0d,0x00,0x03,0x0b,0x15,0x13,0x95,0x03,0x10,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0xed,0x32,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xe9,0x11,0x33,0x31,0x30,0x13,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x01,0x23,0x01,0x35,0x36,0x36,0x35,0x34, 0x26,0x23,0x22,0x06,0x07,0x0f,0x29,0xbb,0xa1,0x94,0xbe,0xab,0x93,0x01,0x63,0xd6,0xfe,0xaa,0x9d,0xc2,0x5e,0x4e,0x58,0x66,0x1f,0x02,0xcf,0xa1,0xa8,0xae,0x89,0x71,0xae,0x32,0xfe,0x70,0x01,0x9e,0x40,0x16,0x8c,0x61,0x4c,0x61,0x56,0x69,0x00,0x01,0x00,0x3d,0x00,0x00,0x04,0x53,0x05,0xb0,0x00,0x1e,0x00,0x4c,0x40,0x26,0x10,0x7e, 0x04,0x1a,0x1a,0x18,0x1c,0x7e,0x1d,0x15,0x1d,0x04,0x1d,0x04,0x1d,0x20,0x14,0x09,0x00,0x1b,0x1e,0x91,0x15,0x18,0x01,0x15,0x16,0x15,0x16,0x15,0x0d,0x1d,0x12,0x09,0x07,0x92,0x0d,0x04,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x01,0x2f,0xc4,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10, 0xf9,0x32,0xc2,0x2f,0x10,0xe9,0x31,0x30,0x13,0x35,0x12,0x12,0x35,0x34,0x26,0x23,0x22,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x06,0x07,0x21,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x3d,0xfe,0xa8,0x4e,0x3e,0x76,0x5f,0x3d,0x77,0x3d,0x80,0x95,0x5a,0x91,0xaf,0x01,0xf1,0xa8,0xcc,0xcc,0xa8,0x01,0x47,0x96,0x01, 0x05,0x01,0x29,0x7c,0x43,0x55,0x76,0xa4,0x39,0x2a,0x9e,0x8b,0x64,0xc5,0xc3,0xbe,0x01,0xfb,0xfe,0x05,0x96,0xfe,0xb9,0x01,0x47,0x00,0x00,0x01,0x00,0x0f,0xfe,0xe7,0x03,0xe0,0x04,0x18,0x00,0x1e,0x00,0x48,0x40,0x24,0x1b,0x84,0x0e,0x04,0x04,0x03,0x07,0x84,0x08,0x00,0x08,0x0e,0x08,0x0e,0x08,0x20,0x1e,0x14,0x0a,0x14,0x11,0x95, 0x18,0x01,0x01,0x09,0x18,0x10,0x0b,0x03,0x00,0x96,0x08,0x06,0x09,0x15,0x00,0x3f,0x33,0xcd,0xed,0x32,0x32,0x3f,0x12,0x39,0x2f,0x10,0xed,0x32,0x01,0x2f,0xc4,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xf9,0x32,0xc0,0x2f,0x10,0xe9,0x31,0x30,0x25,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x37,0x36,0x12,0x35,0x34, 0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x02,0x07,0x02,0x9d,0xa4,0x9f,0x9f,0xa4,0xfd,0x72,0x02,0xc9,0xca,0x46,0x42,0x36,0x6b,0x30,0x39,0x79,0x39,0x7d,0x91,0xb1,0xd6,0x84,0x01,0xe3,0xfe,0x1d,0x84,0xfe,0xe7,0x01,0x19,0x77,0xc4,0x01,0x44,0x7f,0x42,0x4e,0x36,0x36,0x93,0x34,0x2f,0x98,0x7b,0x7a,0xfe, 0xd1,0xd8,0x00,0x01,0x00,0x12,0x00,0x00,0x04,0xe6,0x05,0x9a,0x00,0x14,0x00,0x3a,0x40,0x1d,0x14,0x00,0x05,0x06,0x00,0x06,0x00,0x06,0x0f,0x10,0x10,0x16,0x03,0x02,0x04,0x07,0x01,0x13,0x0b,0x05,0x14,0x14,0x02,0x12,0x12,0x0f,0x05,0x02,0x03,0x00,0x3f,0x33,0x33,0x3f,0x12,0x39,0x2f,0x17,0x39,0x01,0x2f,0x32,0x11,0x33,0x2f,0x33, 0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x31,0x30,0x37,0x13,0x01,0x33,0x13,0x13,0x33,0x01,0x17,0x16,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x23,0x03,0x03,0xb0,0xb1,0xfe,0xb1,0xbb,0xed,0xf3,0x93,0xfe,0xc2,0x58,0x0a,0x0e,0x05,0x04,0x07,0x1a,0x01,0x95,0xb5,0xfd,0xed,0xb9,0x6f,0x68,0x0f,0x01,0xee,0x03,0x9d,0xfd,0x5a,0x02, 0xa6,0xfc,0x8a,0xfb,0x1c,0x3f,0x24,0x3c,0x45,0x04,0x6f,0xfa,0x66,0x01,0x31,0xfe,0xde,0x00,0x00,0x01,0xff,0xe8,0xff,0x37,0x03,0xcb,0x04,0xd1,0x00,0x14,0x00,0x42,0x40,0x24,0x10,0x0f,0x06,0x03,0x01,0x13,0x04,0x07,0x12,0x05,0x05,0x02,0x0f,0x05,0x02,0x02,0x05,0x0f,0x03,0x16,0x14,0x00,0x04,0x07,0x01,0x0a,0x04,0x03,0x14,0x12, 0x15,0x06,0x0f,0x0f,0x03,0x0f,0x00,0x3f,0x3f,0xce,0x3f,0xce,0x12,0x17,0x39,0x01,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x17,0x39,0x33,0x32,0x11,0x33,0x30,0x31,0x07,0x01,0x03,0x33,0x13,0x13,0x33,0x01,0x17,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x23,0x03,0x03,0x18,0x01,0x09,0xe3,0xb4,0x88,0xff,0x87,0xfe, 0xb7,0x3f,0x1d,0x07,0x04,0x05,0x10,0x0b,0x01,0x10,0xad,0xfe,0x68,0xa1,0x62,0xc3,0xc9,0x02,0x71,0x02,0x58,0xfe,0x79,0x02,0x58,0xfc,0xfb,0xb4,0x53,0x3c,0x26,0x46,0x1f,0x02,0xec,0xfc,0x00,0x01,0x01,0xfe,0x36,0x00,0x00,0x01,0x00,0x1a,0xfe,0x1e,0x07,0x60,0x05,0x9a,0x00,0x2c,0x00,0x4e,0x40,0x27,0x18,0x17,0x1d,0x23,0x22,0x13, 0x0f,0x01,0x27,0x1d,0x19,0x13,0x27,0x00,0x09,0x09,0x19,0x2c,0x00,0x00,0x2e,0x1a,0x19,0x1d,0x27,0x13,0x03,0x18,0x2c,0x22,0x19,0x03,0x0f,0x18,0x12,0x0b,0x91,0x05,0x1c,0x00,0x3f,0xed,0x3f,0x33,0x3f,0x33,0x33,0x12,0x17,0x39,0x01,0x2f,0x33,0x11,0x33,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x39,0x12,0x39,0x11,0x33,0x33,0x11,0x33, 0x33,0x11,0x33,0x33,0x31,0x30,0x01,0x01,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x37,0x37,0x01,0x26,0x26,0x27,0x23,0x06,0x07,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x07,0x60,0xfe,0x74,0x3c,0x75,0x9c,0x63,0x1d,0x31,0x1d,0x30,0x31,0x3b, 0x67,0x1f,0x3c,0xfe,0xc8,0x0a,0x0b,0x02,0x04,0x06,0x14,0xfe,0xd7,0xc3,0xfe,0x5c,0xb9,0x01,0x31,0x13,0x05,0x05,0x02,0x10,0x0d,0x01,0x3d,0xa1,0x01,0x37,0x09,0x09,0x03,0x03,0x04,0x0a,0x0a,0x01,0x24,0x05,0x9a,0xfa,0x88,0xd5,0xca,0x65,0x05,0x08,0x9d,0x12,0x56,0x52,0xa2,0x04,0x18,0x22,0x48,0x28,0x47,0x49,0xfb,0xe6,0x05,0x9a, 0xfb,0xb4,0x45,0x4b,0x1a,0x48,0x2e,0x04,0x4c,0xfb,0xb0,0x20,0x4a,0x20,0x21,0x43,0x26,0x04,0x50,0x00,0x00,0x01,0x00,0x18,0xfe,0x1e,0x05,0xb0,0x04,0x00,0x00,0x2c,0x00,0x4b,0x40,0x25,0x18,0x17,0x1f,0x23,0x22,0x13,0x0f,0x27,0x1f,0x19,0x13,0x27,0x00,0x09,0x09,0x19,0x2c,0x00,0x00,0x2e,0x1a,0x19,0x27,0x1e,0x13,0x03,0x18,0x2c, 0x22,0x19,0x0f,0x0b,0x95,0x05,0x0f,0x18,0x15,0x00,0x3f,0x33,0xd4,0xed,0x3f,0x33,0x33,0x12,0x17,0x39,0x01,0x2f,0x33,0x11,0x33,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x39,0x12,0x39,0x11,0x33,0x11,0x33,0x33,0x11,0x33,0x33,0x31,0x30,0x01,0x01,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x37,0x37,0x03,0x26,0x26,0x27, 0x23,0x06,0x07,0x03,0x23,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x36,0x37,0x13,0x33,0x13,0x16,0x16,0x17,0x33,0x34,0x36,0x37,0x13,0x05,0xb0,0xfe,0xb4,0x39,0x59,0x88,0x6a,0x1c,0x34,0x1b,0x34,0x2d,0x51,0x66,0x23,0x2d,0xdd,0x06,0x08,0x02,0x04,0x03,0x12,0xe5,0xa4,0xfe,0xca,0xac,0xd4,0x05,0x07,0x02,0x08,0x03,0x0f,0xec,0x96,0xd5, 0x05,0x06,0x02,0x06,0x06,0x08,0xd6,0x04,0x00,0xfb,0xb6,0xba,0x90,0x4e,0x05,0x08,0x93,0x12,0x5b,0x6f,0x8a,0x02,0xdd,0x15,0x30,0x1a,0x24,0x39,0xfd,0x21,0x04,0x00,0xfc,0xfe,0x11,0x2e,0x1d,0x2d,0x31,0x03,0x00,0xfc,0xfc,0x13,0x2d,0x1c,0x13,0x2f,0x1a,0x03,0x04,0x00,0x00,0x01,0x00,0x55,0xfe,0x21,0x04,0x93,0x05,0xc2,0x00,0x2c, 0x00,0x53,0x40,0x19,0x0c,0x20,0x20,0x26,0x00,0x00,0x26,0x22,0x0b,0x0b,0x0f,0x7d,0x1c,0x1c,0x2e,0x16,0x06,0x7d,0x26,0x0b,0x22,0x91,0x09,0x21,0x1f,0xb8,0x01,0x05,0x40,0x0e,0x0c,0x09,0x0c,0x09,0x0c,0x12,0x03,0x91,0x29,0x16,0x19,0x91,0x12,0x1c,0x00,0x3f,0xed,0x32,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x10,0xed, 0x32,0x01,0x2f,0xe9,0xc4,0x12,0x39,0x2f,0xf9,0xc0,0x2f,0x32,0x11,0x39,0x2f,0x12,0x39,0x11,0x33,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x01,0x32,0x04,0x15,0x14,0x04,0x21,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32, 0x16,0x17,0x02,0x7e,0x1f,0x63,0x27,0x59,0x78,0x8e,0x84,0x01,0xf9,0xfe,0xad,0xd3,0x01,0x04,0xfe,0xc0,0xfe,0xfb,0x57,0xae,0x57,0x59,0xb1,0x58,0xb9,0xd8,0xc2,0xf0,0x68,0x01,0x4c,0xfe,0xd8,0xec,0xd9,0x9b,0x32,0x5b,0x29,0x05,0x00,0x10,0x1d,0x74,0x5b,0x74,0x7d,0x56,0xfe,0x65,0xe0,0xbe,0xcc,0xf1,0x20,0x2a,0xa2,0x32,0x22,0x9c, 0x8e,0x91,0x8e,0x37,0x01,0x9c,0xc9,0xc0,0x95,0xcf,0x0b,0x0c,0x00,0x01,0x00,0x3e,0xfe,0x21,0x04,0x0c,0x04,0xdd,0x00,0x2c,0x00,0x53,0x40,0x19,0x0c,0x20,0x20,0x26,0x00,0x00,0x26,0x22,0x0b,0x0b,0x0f,0x83,0x1c,0x1c,0x2e,0x16,0x06,0x83,0x26,0x0b,0x22,0x95,0x09,0x21,0x1f,0xb8,0x01,0x05,0x40,0x0e,0x0c,0x09,0x0c,0x09,0x0c,0x12, 0x03,0x96,0x29,0x16,0x19,0x95,0x12,0x1c,0x00,0x3f,0xed,0x32,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x10,0xed,0x32,0x01,0x2f,0xed,0xc4,0x12,0x39,0x2f,0xf9,0xc0,0x2f,0x32,0x11,0x39,0x2f,0x12,0x39,0x11,0x33,0x31,0x30,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x01,0x16,0x16,0x15,0x14,0x04,0x23, 0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x01,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x02,0x00,0x26,0x4b,0x27,0x39,0x4a,0x5d,0x5e,0x01,0xec,0xfe,0xbe,0xd4,0xee,0xfe,0xc6,0xf1,0x53,0xa6,0x53,0x55,0xa8,0x54,0xab,0xd3,0xe0,0xcf,0x4f,0x01,0x42,0xfe,0xf9,0x9e,0xc5,0xa8,0x77,0x29, 0x51,0x29,0x04,0x33,0x14,0x10,0x46,0x39,0x4a,0x4e,0x53,0xfe,0x7e,0x11,0xd6,0xb6,0xc6,0xe7,0x1f,0x28,0xa2,0x34,0x2a,0x9c,0x8b,0x91,0x96,0x35,0x01,0x85,0xa0,0x84,0x70,0x95,0x0b,0x11,0x00,0x02,0x00,0x12,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x14,0x00,0x1c,0x00,0x56,0x40,0x16,0x11,0x7d,0x1a,0x16,0x0d,0x01,0x0b,0x0b,0x09,0x01, 0x7e,0x06,0x04,0x02,0x00,0x91,0x16,0x15,0x91,0x0d,0x0c,0x04,0xb8,0x01,0x05,0xb6,0x05,0x09,0x05,0x20,0x16,0x01,0x05,0xb8,0xff,0xc0,0x40,0x0c,0x09,0x0e,0x48,0x16,0x05,0x16,0x05,0x02,0x07,0x03,0x02,0x12,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x2b,0x5d,0x11,0x33,0x10,0xfd,0x32,0xdc,0xed,0x10,0xed,0x01,0x2f,0xc6,0x33,0xf9, 0x32,0xc0,0x2f,0x11,0x33,0x33,0x2f,0xe9,0x31,0x30,0x01,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0xa8,0xaa,0xaa,0xa8,0xd4,0xd4,0xe2,0xe8,0xfb,0xfe,0xe5,0xf0,0xba,0xb0,0xae,0xb7,0xfe,0xb0,0x01,0x3e,0xfe,0xc2,0x04, 0xee,0x67,0x45,0x45,0x67,0x36,0xe0,0xcc,0xcb,0xfe,0xfd,0x02,0xe3,0xfd,0xb4,0x9b,0x92,0x01,0x1f,0x00,0x00,0x02,0x00,0x27,0xfe,0x29,0x04,0x54,0x05,0xec,0x00,0x18,0x00,0x25,0x00,0x4f,0x40,0x2c,0x10,0x83,0x1f,0x08,0x1f,0x08,0x1f,0x27,0x0a,0x06,0x17,0x84,0x03,0x01,0x18,0x17,0x1b,0x15,0x1c,0x95,0x13,0x16,0x0a,0x22,0x95,0x0d, 0x09,0x01,0x96,0x06,0x02,0x02,0x04,0x00,0x0d,0x10,0x0d,0x20,0x0d,0x03,0x0d,0x10,0x04,0x00,0x00,0x3f,0x3f,0x5d,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x3f,0xed,0x32,0x3f,0x01,0x2f,0xc6,0x33,0xe9,0x32,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x13,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x15,0x21,0x11,0x33,0x36, 0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x27,0x23,0x11,0x23,0x13,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0xa6,0x7f,0x7f,0xa4,0x01,0x54,0xfe,0xac,0x04,0x79,0xe9,0xc4,0xe0,0xfa,0xd9,0xc7,0x6c,0x04,0xa4,0xa4,0xa4,0x80,0x94,0xaa,0x9e,0x87,0x8d,0xb0,0x04,0xb2,0x86,0xb4,0xb4,0x86,0xfe,0x9a,0xcc,0xfe,0xee, 0xe8,0xfe,0xfe,0xfe,0xcc,0xac,0xfd,0x95,0x03,0x79,0x80,0xb0,0xe3,0xcc,0xab,0xc2,0xc5,0x98,0x00,0x02,0x00,0x12,0x00,0x00,0x04,0x29,0x05,0x9a,0x00,0x14,0x00,0x1c,0x00,0x44,0x40,0x23,0x11,0x7d,0x1a,0x1a,0x06,0x1e,0x16,0x05,0x03,0x03,0x01,0x05,0x7e,0x0a,0x08,0x06,0x15,0x91,0x0d,0x0d,0x06,0x0b,0x03,0x16,0x91,0x00,0x01,0x0f, 0x09,0x01,0x09,0x04,0x08,0x06,0x12,0x00,0x3f,0xde,0x32,0xdd,0x5d,0x32,0xdc,0xed,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0xc6,0x33,0xf9,0x32,0xc2,0x2f,0x11,0x33,0x11,0x12,0x39,0x2f,0xe9,0x31,0x30,0x01,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x11,0x33,0x15,0x33,0x32,0x16,0x15,0x14,0x00,0x23,0x03,0x11,0x33,0x32,0x36, 0x35,0x10,0x21,0x01,0x64,0xd4,0xd4,0xa8,0xaa,0xaa,0xa8,0xe2,0xe8,0xfb,0xfe,0xe5,0xf0,0xba,0xb0,0xae,0xb7,0xfe,0xb0,0x01,0x3e,0x55,0x67,0x82,0x82,0x67,0x04,0xb1,0xe2,0xe0,0xcc,0xcb,0xfe,0xfd,0x02,0xe3,0xfd,0xb4,0x9b,0x92,0x01,0x1f,0x00,0x02,0x00,0x27,0xfe,0x29,0x04,0x54,0x05,0xec,0x00,0x18,0x00,0x25,0x00,0x4b,0x40,0x28, 0x0c,0x1f,0x1f,0x18,0x27,0x19,0x17,0x15,0x15,0x13,0x06,0x17,0x03,0x01,0x18,0x17,0x1b,0x11,0x1c,0x95,0x0f,0x00,0x16,0x96,0x03,0x13,0x1f,0x0f,0x2f,0x0f,0x02,0x0f,0x16,0x06,0x22,0x95,0x09,0x10,0x04,0x00,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x5d,0xde,0x32,0xed,0x32,0x10,0xed,0x32,0x3f,0x01,0x2f,0xc6,0x33,0xd1,0x32,0x32,0xc2,0x2f, 0x11,0x33,0x11,0x12,0x39,0x2f,0xc1,0x31,0x30,0x17,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x12,0x15,0x10,0x02,0x23,0x22,0x27,0x23,0x11,0x21,0x15,0x21,0x15,0x23,0x13,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0xa6,0x7f,0x7f,0xa4,0x04,0x79,0xe9,0xc4,0xe0,0xfa,0xd9,0xc7,0x6c,0x04,0x01,0x54,0xfe, 0xac,0xa4,0xa4,0xa4,0x80,0x94,0xaa,0x9e,0x87,0x8d,0xb0,0xf8,0x86,0x06,0x5e,0xfd,0x60,0xcc,0xfe,0xee,0xe8,0xfe,0xfe,0xfe,0xcc,0xac,0xfe,0xfa,0x86,0xdf,0x03,0x79,0x80,0xb0,0xe3,0xcc,0xab,0xc2,0xc5,0x98,0x00,0x01,0x00,0xbc,0xfe,0x29,0x03,0xc7,0x05,0x9a,0x00,0x0b,0x00,0x23,0x40,0x10,0x09,0x0a,0x0a,0x0d,0x04,0x00,0x7e,0x01, 0x04,0x0b,0x01,0x09,0x02,0x03,0x01,0x1b,0x00,0x3f,0x3f,0x33,0x12,0x39,0x39,0x01,0x2f,0xe9,0x32,0x11,0x33,0x2f,0x33,0x31,0x30,0x01,0x23,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x01,0x64,0xa8,0xa8,0x04,0x03,0x0e,0x0d,0x01,0x8c,0xb5,0xfd,0x9d,0xfe,0x29,0x07,0x71,0xfb,0xcb,0x12,0x31,0x1e,0x03,0xd4,0xfa,0x66,0x00, 0x00,0x01,0x00,0xa6,0xfe,0x29,0x03,0x28,0x04,0x00,0x00,0x0b,0x00,0x21,0x40,0x0f,0x08,0x09,0x09,0x0d,0x03,0x0a,0x84,0x00,0x0a,0x03,0x08,0x01,0x0f,0x00,0x1b,0x00,0x3f,0x3f,0x33,0x39,0x39,0x01,0x2f,0xe9,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x13,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x13,0x33,0x01,0x11,0xa6,0xa4,0x04,0x0a,0x2b, 0x14,0xe4,0xad,0xfe,0x22,0xfe,0x29,0x05,0xd7,0xfd,0x34,0x33,0x68,0x2f,0x02,0x02,0xfc,0x00,0xfe,0x29,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x5d,0x05,0xb2,0x00,0x29,0x00,0x41,0x40,0x22,0x1c,0x7d,0x0f,0x23,0x7d,0x06,0x1f,0x0f,0x0a,0x0f,0x06,0x06,0x0f,0x0a,0x03,0x2b,0x15,0x29,0x1f,0x0a,0x91,0x0b,0x0b,0x19,0x00,0x03,0x91,0x26, 0x13,0x15,0x12,0x91,0x19,0x04,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0xc4,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xe9,0x10,0xe9,0x31,0x30,0x37,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15, 0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x60,0x4b,0xa1,0x4b,0x80,0x99,0x9b,0x93,0x71,0x5a,0x7f,0x95,0x67,0x62,0x45,0x99,0x41,0x4b,0x93,0x4b,0xa9,0xc3,0x6d,0x6a,0x7c,0x8c,0xf8,0xcc,0x4e,0x9d,0x4e,0xd7,0x32,0x26,0x95,0x82,0x80,0x85,0x98,0x97,0x84,0x64,0x69,0x2d,0x30,0xa2,0x2b,0x27,0xc1,0xa0,0x7d, 0xa9,0x2d,0x08,0x16,0xbe,0x8c,0xc4,0xea,0x21,0x2c,0x00,0x01,0x00,0x1e,0xfe,0x23,0x02,0xe7,0x04,0x18,0x00,0x29,0x00,0x41,0x40,0x22,0x1c,0x84,0x0f,0x23,0x84,0x06,0x20,0x0f,0x0a,0x0f,0x06,0x06,0x0f,0x0a,0x03,0x2b,0x15,0x00,0x1f,0x0a,0x95,0x0b,0x0b,0x19,0x00,0x03,0x95,0x26,0x1c,0x15,0x12,0x95,0x19,0x10,0x00,0x3f,0xed,0x32, 0x3f,0xed,0x32,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0xc6,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xe9,0x10,0xe9,0x31,0x30,0x13,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x00,0x23, 0x22,0x26,0x27,0x21,0x23,0x6c,0x2b,0x97,0xd0,0x9c,0xba,0x46,0x52,0x78,0xa1,0x71,0x65,0x47,0x8f,0x47,0x48,0x94,0x48,0xaf,0xc6,0x72,0x51,0x80,0x73,0xfe,0xcf,0xdb,0x2a,0x66,0x2a,0xfe,0xcc,0x0f,0x11,0xc5,0x96,0x8b,0x85,0x89,0xa2,0x78,0x65,0x70,0x29,0x2b,0x98,0x25,0x20,0xb8,0xa6,0x5d,0xc0,0x2a,0x05,0x2c,0xbb,0x80,0xcd,0xfe, 0xe9,0x08,0x09,0x00,0x00,0x02,0x00,0x14,0xff,0xe8,0x03,0xba,0x05,0xb0,0x00,0x19,0x00,0x24,0x00,0x41,0x40,0x21,0x24,0x0e,0x7e,0x00,0x03,0x00,0x0a,0x7d,0x1d,0x00,0x1d,0x00,0x1d,0x26,0x01,0x15,0x15,0x17,0x91,0x12,0x0e,0x00,0x91,0x24,0x02,0x02,0x07,0x12,0x13,0x20,0x91,0x07,0x04,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed, 0x32,0x10,0xed,0x32,0x01,0x2f,0xc6,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x11,0x33,0x10,0xe9,0x32,0x31,0x30,0x01,0x21,0x35,0x21,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x01,0x83,0xfe,0xe2,0x01,0x1e, 0x95,0x86,0x7d,0x9f,0xb9,0x86,0x50,0xd1,0xbc,0x54,0x36,0x36,0x56,0xe3,0xf9,0x49,0x45,0x31,0x36,0x41,0x37,0x03,0x70,0x97,0x81,0x8c,0x9c,0x99,0x7c,0x80,0xab,0xfe,0x92,0xf8,0xfe,0xde,0x18,0xa6,0x27,0x01,0x81,0x02,0x07,0x53,0x41,0x36,0x4a,0x50,0x43,0x81,0x00,0x02,0xff,0x76,0xfe,0x1e,0x03,0x15,0x06,0x02,0x00,0x19,0x00,0x24, 0x00,0x41,0x40,0x21,0x24,0x0e,0x84,0x00,0x03,0x00,0x0a,0x83,0x1d,0x00,0x1d,0x00,0x1d,0x26,0x01,0x15,0x15,0x17,0x95,0x12,0x0e,0x00,0x95,0x24,0x02,0x02,0x07,0x12,0x1c,0x20,0x95,0x07,0x00,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x33,0xed,0x32,0x10,0xed,0x32,0x01,0x2f,0xc6,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x11,0x33,0x10,0xe9, 0x32,0x31,0x30,0x13,0x23,0x35,0x37,0x35,0x34,0x36,0x37,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x14,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0xe2,0xd8,0xd8,0x91,0x8a,0x7d,0x9b,0xae,0x83,0x5e,0xcc,0xbc,0x45,0x43,0x49,0x43,0xe0,0xf9,0x43,0x4f,0x3d,0x33,0x3c,0x3b, 0x03,0xc6,0x8c,0x01,0x87,0x89,0x9e,0x01,0x98,0x7a,0x82,0xa8,0xfc,0x65,0xfd,0xfe,0xf0,0x20,0x99,0x2d,0x01,0x66,0x04,0x42,0x57,0x47,0x3d,0x4b,0x54,0x4a,0x88,0x00,0x00,0x01,0x00,0x38,0xff,0xe8,0x03,0xca,0x05,0xb2,0x00,0x25,0x00,0x37,0x40,0x1c,0x15,0x7d,0x22,0x08,0x22,0x08,0x22,0x27,0x1c,0x02,0x7e,0x0f,0x1c,0x1f,0x91,0x18, 0x08,0x05,0x91,0x0c,0x0c,0x12,0x18,0x13,0x25,0x91,0x12,0x04,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x32,0x10,0xed,0x32,0x01,0x2f,0xe9,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x00,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x33,0x32,0x12,0x11,0x10,0x00,0x21,0x22,0x26, 0x27,0x35,0x16,0x16,0x33,0x32,0x12,0x11,0x10,0x26,0x23,0x01,0x7c,0x9b,0x8b,0x7c,0x3a,0x6e,0x36,0x35,0x6d,0x3d,0xc1,0xee,0xf8,0xcd,0xde,0xef,0xfe,0xc0,0xfe,0xe7,0x3c,0x77,0x3c,0x39,0x81,0x39,0xcf,0xd6,0x8f,0x90,0x05,0x1c,0xae,0x8d,0x90,0xaf,0x28,0x2b,0xa2,0x23,0x24,0xfc,0xc7,0xd7,0x01,0x0c,0xfe,0x9f,0xfe,0xbe,0xfe,0x87, 0xfe,0x52,0x18,0x16,0xa5,0x1d,0x20,0x01,0x4c,0x01,0x45,0x01,0x10,0xfd,0x00,0x01,0x00,0x43,0xfe,0x4e,0x03,0xce,0x04,0x18,0x00,0x25,0x00,0x34,0x40,0x1a,0x15,0x83,0x22,0x08,0x22,0x08,0x22,0x27,0x1c,0x02,0x84,0x0f,0x08,0x05,0x95,0x0c,0x0c,0x12,0x1c,0x1f,0x95,0x18,0x25,0x95,0x12,0x0f,0x00,0x3f,0xed,0x2f,0xed,0x32,0x11,0x39, 0x2f,0xed,0x32,0x01,0x2f,0xe9,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x00,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x12,0x33,0x32,0x12,0x11,0x10,0x00,0x21,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x12,0x11,0x10,0x02,0x23,0x01,0x83,0x9c,0x8e,0x7b,0x39,0x6d,0x37,0x36,0x71, 0x37,0xc0,0xec,0xf5,0xcd,0xdd,0xec,0xfe,0xc8,0xfe,0xe2,0x3c,0x76,0x3c,0x39,0x82,0x38,0xd4,0xd5,0x91,0x92,0x03,0x8e,0xb6,0x8e,0x96,0xb2,0x24,0x2b,0x98,0x23,0x1e,0xfb,0xc5,0xd6,0x01,0x0a,0xfe,0xa2,0xfe,0xbb,0xfe,0x8a,0xfe,0x4f,0x16,0x14,0x9d,0x1d,0x20,0x01,0x55,0x01,0x49,0x01,0x18,0x01,0x00,0x00,0x01,0x00,0x28,0x02,0x89, 0x02,0x39,0x05,0xaa,0x00,0x24,0x00,0x44,0xb3,0x00,0x00,0x05,0x0b,0xb8,0x01,0x04,0xb3,0x18,0x18,0x26,0x1e,0xb8,0x01,0x04,0xb3,0x12,0x05,0x12,0x15,0xb8,0x01,0x05,0xb2,0x0e,0x24,0x21,0xb8,0x01,0x05,0xb4,0x02,0x02,0x08,0x0e,0x1b,0xb8,0x01,0x05,0xb1,0x08,0x04,0x00,0x3f,0xed,0x2f,0x12,0x39,0x2f,0xed,0x32,0x10,0xed,0x32,0x01, 0x2f,0xc4,0xe9,0x12,0x39,0x2f,0xed,0x12,0x39,0x2f,0x31,0x30,0x01,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x01,0x7a,0x2b,0x32,0x77,0x7e,0x8f,0x71,0x83,0x8e,0xa9,0x9c,0x29,0x4b,0x26, 0x28,0x4b,0x28,0x5f,0x62,0x49,0x45,0x3a,0x47,0x38,0x3f,0x18,0x31,0x13,0x03,0xbb,0x11,0x83,0x72,0x74,0x97,0xbf,0xad,0xc5,0xf0,0x0f,0x0e,0x78,0x14,0x11,0xa3,0xa1,0x86,0x77,0x55,0x42,0x3f,0x52,0x0c,0x0e,0x00,0x02,0x00,0x60,0xff,0x43,0x05,0x60,0x05,0xec,0x00,0x1a,0x00,0x27,0x00,0x4e,0x40,0x2a,0x27,0x19,0x84,0x15,0x09,0x06, 0x07,0x00,0x01,0x09,0x07,0x01,0x03,0x03,0x01,0x07,0x09,0x04,0x29,0x21,0x83,0x10,0x17,0x00,0x15,0x1e,0x95,0x13,0x10,0x0a,0x24,0x95,0x07,0x0d,0x16,0x02,0x00,0x19,0x95,0x05,0x09,0x15,0x00,0x3f,0x33,0xfd,0xc6,0x33,0x3f,0xc6,0xed,0x32,0x3f,0xed,0x32,0x3f,0x01,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33, 0x11,0x33,0xe9,0x33,0x31,0x30,0x01,0x33,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x35,0x23,0x06,0x23,0x22,0x02,0x35,0x34,0x12,0x33,0x32,0x17,0x33,0x11,0x33,0x11,0x33,0x03,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x04,0xbc,0x8e,0x59,0x6f,0xb1,0x59,0x8e,0x59,0xb5,0x04,0x72,0xee,0xc0,0xe8,0xff,0xd6,0xd3, 0x60,0x04,0xa4,0x53,0xf7,0xa6,0x7c,0x97,0xab,0xa3,0x8d,0x88,0xac,0x01,0x44,0xba,0x8a,0xbd,0xbd,0xae,0xc6,0x01,0x11,0xef,0xfc,0x01,0x34,0xa6,0x02,0x7a,0xfa,0x9e,0x01,0xdc,0x7e,0xaa,0xdd,0xc1,0xb1,0xcd,0xc6,0x97,0x00,0x01,0x00,0xa6,0xff,0x43,0x02,0x9a,0x05,0xec,0x00,0x0d,0x00,0x30,0x40,0x17,0x0b,0x0c,0x05,0x06,0x0c,0x06, 0x00,0x08,0x08,0x0f,0x03,0x84,0x00,0x01,0x00,0x07,0x05,0x03,0x95,0x0c,0x0a,0x00,0x15,0x00,0x3f,0x32,0xc6,0xfd,0xc6,0x33,0x3f,0x01,0x2f,0xe9,0x12,0x39,0x2f,0x12,0x39,0x39,0x11,0x33,0x11,0x33,0x31,0x30,0x33,0x11,0x33,0x11,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0xa6,0xa4,0x53,0x57,0x8e,0x57,0x6f,0xb1,0x59,0x8e, 0x59,0x05,0xec,0xfa,0x9e,0xba,0xba,0x8a,0xbd,0xbd,0x00,0x01,0x00,0xa6,0xff,0x43,0x07,0xa4,0x04,0x18,0x00,0x29,0x00,0x5d,0x40,0x32,0x1d,0x19,0x84,0x1a,0x23,0x11,0x84,0x12,0x28,0x84,0x09,0x06,0x07,0x00,0x01,0x12,0x09,0x07,0x01,0x03,0x03,0x01,0x07,0x09,0x12,0x05,0x04,0x1a,0x04,0x23,0x1d,0x0d,0x15,0x95,0x25,0x20,0x10,0x1b, 0x0f,0x12,0x19,0x15,0x02,0x00,0x28,0x95,0x07,0x05,0x09,0x15,0x00,0x3f,0x33,0xc6,0xfd,0xc6,0x33,0x3f,0x33,0x3f,0x3f,0x33,0xed,0x32,0x32,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0x10,0xe9,0x10,0xe9,0x39,0x10,0xe9,0x32,0x31,0x30,0x01,0x33,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x11, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x17,0x36,0x33,0x20,0x11,0x11,0x33,0x06,0xfe,0x8e,0x57,0x6f,0xb1,0x59,0x8e,0x59,0xb5,0x68,0x7d,0x69,0x93,0xa4,0xe9,0x6a,0x8e,0xa4,0xa4,0x04,0x6d,0xd1,0x68,0x9e,0x1c,0x72,0xe2,0x01,0x52,0x53,0x01,0x44, 0xba,0x8a,0xbd,0xbd,0x02,0x4c,0xa7,0x9b,0xbe,0x88,0xfd,0xb8,0x02,0x60,0x01,0x2e,0xb3,0x93,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x76,0x5e,0xd4,0xfe,0x5f,0xfe,0x13,0x00,0x00,0x01,0x00,0xa6,0xff,0x43,0x05,0x48,0x04,0x18,0x00,0x1c,0x00,0x45,0x40,0x25,0x14,0x10,0x84,0x11,0x1b,0x84,0x06,0x07,0x00,0x01,0x09,0x07,0x01,0x03,0x03,0x01, 0x07,0x09,0x04,0x04,0x11,0x04,0x15,0x0c,0x95,0x17,0x10,0x12,0x0f,0x11,0x15,0x00,0x1b,0x95,0x07,0x09,0x15,0x00,0x3f,0xc6,0xfd,0xc6,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x11,0x33,0x11,0x33,0xed,0x10,0xe9,0x32,0x31,0x30,0x01,0x33,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x11,0x10,0x23, 0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x33,0x04,0xa5,0x8e,0x5a,0x6f,0xb1,0x59,0x8e,0x59,0xb5,0xee,0x7a,0xa2,0xa4,0xa4,0x04,0x74,0xdc,0xa9,0xb1,0x53,0x01,0x46,0xbc,0x8a,0xbd,0xbd,0x02,0x48,0x01,0x46,0xb8,0x8e,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd8,0xce,0xfe,0x18,0x00,0x00,0x01,0x00,0xa6, 0x00,0x00,0x02,0xbc,0x04,0x91,0x00,0x17,0x00,0x3a,0x40,0x1e,0x09,0x0a,0x00,0x01,0x0a,0x01,0x06,0x06,0x01,0x0a,0x03,0x19,0x12,0x0f,0x84,0x10,0x11,0x0f,0x10,0x15,0x14,0x0b,0x09,0x08,0xec,0x17,0x00,0x96,0x02,0x10,0x00,0x3f,0xed,0x33,0xfd,0xcd,0x33,0x33,0x3f,0x3f,0x01,0x2f,0xe9,0x32,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33, 0x11,0x33,0x31,0x30,0x01,0x33,0x07,0x16,0x16,0x17,0x15,0x26,0x27,0x07,0x23,0x37,0x06,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x37,0x02,0x26,0x7a,0x23,0x14,0x1e,0x0d,0x26,0x42,0x3a,0x7a,0x31,0x3a,0x4d,0xa4,0xa4,0x04,0x1a,0x5b,0x3b,0x04,0x91,0x80,0x02,0x06,0x05,0xaa,0x1d,0x03,0xd7,0xb7,0x26,0xa8,0x82,0xfd,0xf6, 0x04,0x00,0xd3,0x4f,0x6c,0x18,0x00,0x02,0x00,0xa6,0xff,0x43,0x04,0xa2,0x04,0x01,0x00,0x1e,0x00,0x27,0x00,0x53,0x40,0x2c,0x0f,0x06,0x0c,0x83,0x1c,0x1d,0x16,0x17,0x17,0x14,0x1d,0x00,0x04,0x19,0x24,0x19,0x24,0x19,0x07,0x1a,0x20,0x06,0x84,0x07,0x0f,0x20,0x96,0x05,0x05,0x06,0x1f,0x96,0x08,0x0f,0x06,0x15,0x18,0x16,0x14,0x95, 0x1d,0x1b,0x00,0x15,0x00,0x3f,0x32,0xc6,0xfd,0xc6,0x33,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x01,0x2f,0xe9,0x32,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x12,0x17,0x39,0x11,0x33,0x11,0x33,0xed,0x11,0x39,0x31,0x30,0x21,0x03,0x26,0x26,0x23,0x23,0x11,0x23,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x17,0x17,0x33,0x37, 0x33,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x01,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x02,0xe5,0x98,0x2e,0x40,0x4e,0x47,0xa4,0x01,0x36,0xce,0xb2,0x90,0x67,0x1f,0x3b,0x2a,0x69,0x53,0x4f,0x8e,0x4f,0x6f,0xb1,0x59,0x8e,0x59,0xfd,0xe7,0x78,0x72,0x80,0x67,0x73,0x01,0x1b,0x54,0x34,0xfe,0x5d,0x04,0x01,0x8b,0x94,0x5f,0x97,0x0c, 0x03,0x09,0x3d,0x4d,0xc0,0xa7,0xa7,0x8a,0xbd,0xbd,0x03,0x7e,0xfe,0xab,0x5f,0x5a,0x4f,0x4d,0x00,0x02,0x00,0x2b,0xff,0xea,0x05,0x12,0x05,0xb1,0x00,0x21,0x00,0x2c,0x00,0x4d,0x40,0x28,0x1c,0xef,0x25,0x09,0x25,0x09,0x25,0x2e,0x14,0x03,0x84,0x11,0x0f,0x0d,0x2c,0x21,0x84,0x15,0x00,0x28,0x96,0x19,0x20,0x02,0x0e,0x95,0x11,0x2c, 0x14,0x11,0x13,0x13,0x11,0x0f,0x06,0x95,0x0b,0x16,0x00,0x15,0x00,0x3f,0x3f,0xed,0x3f,0x33,0x2f,0x11,0x33,0x33,0x10,0xed,0x32,0x32,0xd4,0xed,0x01,0x2f,0x33,0xe9,0x32,0x2f,0xc6,0x33,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x21,0x11,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x11,0x11,0x23,0x35, 0x33,0x35,0x37,0x11,0x21,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x02,0xf2,0xfe,0x8d,0x46,0x51,0x3f,0x2c,0x3b,0x5e,0xfe,0xf3,0xb0,0xb0,0xa4,0x01,0x73,0x8c,0x8a,0x83,0x87,0xa7,0xa0,0x35,0x36,0x4f,0x5d,0x37,0x39,0x39,0x37,0x03,0x74,0xfd,0xbf,0x67, 0x58,0x22,0x8c,0x20,0x01,0x2c,0x02,0x5e,0x8c,0xfa,0x35,0xfe,0xd1,0x6e,0xa9,0x9a,0x96,0x82,0x8d,0x98,0xfc,0x8c,0x04,0x00,0x4b,0x4f,0x49,0x48,0x52,0x6e,0x6b,0x00,0x00,0x02,0xff,0xec,0x00,0x00,0x03,0x5b,0x05,0xb2,0x00,0x22,0x00,0x2e,0x00,0x4c,0x40,0x28,0x1f,0x10,0x22,0x0d,0x7e,0x26,0x03,0x23,0x00,0x26,0x13,0x7e,0x1c,0x26, 0x1c,0x26,0x1c,0x30,0x22,0x00,0x2c,0x7e,0x18,0x07,0x1f,0x03,0x10,0x23,0x04,0x22,0x22,0x0a,0x18,0x91,0x16,0x12,0x29,0x91,0x0a,0x03,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x17,0x39,0x01,0x2f,0xc6,0xe9,0xc6,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x11,0x12,0x39,0x39,0x10,0xe9,0x11,0x39,0x39,0x31,0x30,0x13,0x36,0x12,0x37, 0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x21,0x35,0x21,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x07,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x95,0x4d,0x8d,0x3c,0x10,0x93,0x4c,0x98,0x6f,0x73,0x88,0x31,0x22,0x84,0x6c,0xe5,0xc4,0xfe,0x3a,0x01,0xd1, 0x69,0x89,0x42,0x48,0x3d,0x87,0x4b,0xcf,0x15,0x18,0x2c,0x29,0x29,0x31,0x49,0x01,0x3a,0x80,0x01,0x04,0x80,0x0e,0x82,0x97,0x4f,0x6b,0x93,0x92,0x79,0x4b,0xa5,0x59,0x84,0xd8,0x73,0xba,0xd5,0x97,0x89,0x6d,0x54,0x9e,0x4e,0x7e,0xed,0x7b,0x02,0xf5,0x38,0x5d,0x38,0x36,0x3b,0x3c,0x29,0x39,0x69,0x00,0x00,0x02,0x00,0x0f,0xff,0xe8, 0x05,0xaa,0x05,0x9a,0x00,0x0e,0x00,0x1a,0x00,0x28,0x40,0x14,0x05,0x7d,0x0e,0x0b,0x14,0x14,0x1c,0x1a,0x7d,0x00,0x0b,0x11,0x91,0x08,0x13,0x17,0x0e,0x91,0x01,0x03,0x00,0x3f,0xed,0x32,0x3f,0xed,0x01,0x2f,0xc6,0xe9,0x12,0x39,0x2f,0x12,0x39,0xe9,0x31,0x30,0x13,0x35,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x11,0x34,0x12, 0x37,0x02,0x00,0x33,0x32,0x00,0x11,0x10,0x00,0x23,0x22,0x00,0x15,0x0f,0x03,0x07,0x01,0x25,0x01,0x6f,0xfe,0x8c,0xfe,0xc8,0xfe,0xd4,0xfe,0x8c,0x99,0x74,0x5d,0x01,0x11,0xdf,0xe9,0x01,0x13,0xfe,0xfc,0xec,0xe1,0xfe,0xe5,0x05,0x02,0x98,0xfe,0x6d,0xfe,0xcc,0xfe,0xb0,0xfe,0x65,0x01,0x8d,0x01,0x3b,0xe1,0x01,0x2a,0x47,0xfc,0xc1, 0xfe,0xbc,0x01,0x34,0x01,0x09,0x01,0x10,0x01,0x36,0xfe,0xb9,0xfc,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x18,0x05,0xe9,0x00,0x13,0x00,0x1e,0x00,0x2f,0x40,0x18,0x09,0x0c,0x10,0x83,0x19,0x19,0x20,0x0d,0x0c,0x1e,0x83,0x02,0x08,0x05,0x16,0x95,0x13,0x16,0x0d,0x00,0x1b,0x95,0x05,0x10,0x00,0x3f,0xed,0x3f,0x3f,0xed,0x12,0x39, 0x01,0x2f,0xe9,0xc4,0x32,0x12,0x39,0x2f,0xed,0x12,0x39,0x31,0x30,0x04,0x02,0x35,0x34,0x00,0x33,0x32,0x16,0x17,0x37,0x26,0x00,0x27,0x33,0x04,0x00,0x11,0x14,0x00,0x23,0x00,0x16,0x33,0x32,0x36,0x35,0x10,0x21,0x22,0x06,0x15,0x01,0x5c,0xfc,0x01,0x09,0xde,0x33,0x5e,0x1f,0x03,0x4f,0xfe,0xea,0xbc,0xfa,0x01,0x20,0x01,0x25,0xfe, 0xfa,0xd4,0xfe,0xca,0xa9,0x91,0x8a,0xa4,0xfe,0xd6,0x96,0xa8,0x18,0x01,0x1c,0xf6,0xf0,0x01,0x2e,0x1e,0x1d,0x02,0x77,0x01,0x06,0x8d,0xdb,0xfe,0x07,0xfe,0xf1,0xef,0xfe,0xd1,0x01,0x61,0xd7,0xdf,0xad,0x01,0x90,0xdc,0xb8,0x00,0x00,0x01,0x00,0xbc,0xfe,0x29,0x02,0xf4,0x05,0xac,0x00,0x15,0x00,0x2b,0x40,0x16,0x07,0x00,0x00,0x17, 0x0d,0x06,0x09,0x83,0x0b,0x0e,0x02,0xf4,0x12,0x01,0x0c,0x00,0x0a,0x1b,0x06,0xec,0x09,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x32,0x32,0x11,0x39,0x2f,0x33,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x02,0xf4,0x2f,0x57,0x78, 0x92,0x01,0x77,0xfe,0x89,0xa8,0xa8,0x04,0x26,0x9b,0x61,0x23,0x34,0x13,0x04,0xea,0x21,0xd1,0xc8,0xfd,0x25,0x97,0xfe,0x29,0x07,0x71,0xd3,0x6b,0x7a,0x07,0x07,0x00,0x00,0x01,0x00,0xa6,0xfe,0x29,0x02,0xbc,0x04,0x12,0x00,0x14,0x00,0x2b,0x40,0x16,0x07,0x00,0x00,0x16,0x0d,0x06,0x09,0x84,0x0b,0x0e,0x02,0xec,0x12,0x10,0x0c,0x0f, 0x0a,0x1b,0x06,0x95,0x09,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x32,0x32,0x11,0x39,0x2f,0x33,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x11,0x21,0x15,0x21,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x02,0xbc,0x2c,0x50,0x6a,0x8c,0x01,0x56,0xfe,0xaa,0xa4,0xa4,0x04,0x25,0x8f,0x58,0x3e,0x24, 0x03,0x5a,0x21,0xc5,0xac,0xfe,0x80,0x8a,0xfe,0x29,0x05,0xd7,0xd3,0x6e,0x77,0x0e,0x00,0x02,0x00,0x5a,0xff,0xe8,0x04,0x49,0x05,0x9a,0x00,0x1a,0x00,0x2b,0x00,0x4d,0x40,0x28,0x07,0x7d,0x18,0x0b,0x7d,0x1d,0x00,0x04,0x15,0x25,0x1d,0x18,0x1d,0x04,0x04,0x1d,0x18,0x03,0x2d,0x28,0x7d,0x01,0x12,0x18,0x07,0x25,0x07,0x02,0x15,0x15, 0x02,0x2b,0x91,0x0f,0x13,0x04,0x00,0x91,0x02,0x03,0x00,0x3f,0xed,0x32,0x3f,0xed,0x11,0x39,0x2f,0x12,0x39,0xcd,0x11,0x33,0x01,0x2f,0xc4,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x39,0x11,0x33,0x10,0xe9,0x10,0xe9,0x31,0x30,0x01,0x21,0x35,0x21,0x15,0x06,0x06,0x15,0x14,0x04,0x16,0x15,0x15,0x06,0x04,0x23,0x22,0x24,0x35, 0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x12,0x36,0x35,0x34,0x26,0x2f,0x02,0x26,0x26,0x27,0x06,0x06,0x15,0x14,0x16,0x33,0x02,0x82,0xfe,0x27,0x03,0x4b,0x95,0xeb,0x01,0x31,0xa4,0x06,0xfe,0xe8,0xe5,0xdb,0xfe,0xef,0xc0,0xda,0x19,0x17,0x69,0xb6,0xb6,0x55,0x39,0x4b,0x3c,0x0e,0x19,0x0e,0xbe,0x87,0xa9,0x96,0x05,0x04,0x96,0x85, 0x1a,0x90,0x52,0x52,0xce,0xcb,0x81,0x07,0xd0,0xee,0xed,0xc3,0x9d,0xee,0x61,0x21,0x53,0x23,0x46,0x7f,0xfb,0x9f,0xa1,0x8c,0x40,0x76,0x2d,0x3a,0x2d,0x0a,0x14,0x0c,0x5a,0xae,0x76,0x88,0x9b,0x00,0x00,0x02,0x00,0x59,0x00,0x00,0x04,0x48,0x05,0xb2,0x00,0x1d,0x00,0x2d,0x00,0x45,0x40,0x24,0x1b,0x7d,0x07,0x15,0x7d,0x2a,0x00,0x0f, 0x07,0x2a,0x01,0x01,0x2a,0x07,0x03,0x2f,0x20,0x7d,0x04,0x0f,0x27,0x1b,0x07,0x07,0x18,0x18,0x03,0x2d,0x91,0x12,0x04,0x04,0x00,0x91,0x03,0x12,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0x39,0x11,0x33,0xcd,0x01,0x2f,0xc4,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x10,0xe9,0x10,0xe9,0x31,0x30,0x25,0x21,0x15,0x21,0x35, 0x36,0x24,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x35,0x36,0x24,0x33,0x32,0x04,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x02,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x17,0x36,0x36,0x35,0x34,0x26,0x23,0x02,0x20,0x01,0xd9,0xfc,0xb5,0x7b,0x01,0x05,0x45,0x47,0x46,0x8f,0x74,0x06,0x01,0x17,0xe6,0xdb,0x01,0x11,0xc9,0xd1, 0x19,0x17,0x69,0xb6,0xb6,0x60,0x9a,0x1c,0x0d,0x19,0x0e,0xbe,0x87,0xa9,0x96,0x96,0x96,0x85,0x12,0x93,0x57,0x2a,0x53,0x33,0x32,0x6a,0xb5,0x65,0x0d,0xcf,0xef,0xed,0xc3,0xa1,0xf0,0x5b,0x21,0x53,0x23,0x46,0x7f,0x04,0x61,0xa1,0x8c,0x41,0x85,0x6f,0x15,0x0a,0x14,0x0c,0x5a,0xae,0x76,0x88,0x9b,0x00,0x00,0x02,0x00,0x60,0xfe,0x39, 0x04,0x3f,0x04,0x18,0x00,0x19,0x00,0x27,0x00,0x48,0x40,0x25,0x21,0x14,0x1c,0x17,0x84,0x07,0x11,0x83,0x24,0x00,0x0b,0x07,0x01,0x24,0x07,0x24,0x07,0x24,0x29,0x1c,0x83,0x04,0x0b,0x21,0x96,0x14,0x14,0x02,0x27,0x95,0x0e,0x10,0x04,0x00,0x95,0x02,0x1b,0x00,0x3f,0xed,0x32,0x3f,0xed,0x12,0x39,0x2f,0xed,0x01,0x2f,0xc4,0xe9,0x12, 0x39,0x39,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0x10,0xe9,0x10,0xe9,0x11,0x39,0x39,0x31,0x30,0x01,0x21,0x15,0x21,0x35,0x36,0x36,0x35,0x34,0x24,0x26,0x35,0x34,0x24,0x33,0x32,0x04,0x15,0x14,0x02,0x07,0x16,0x16,0x15,0x14,0x06,0x02,0x06,0x15,0x14,0x16,0x1f,0x02,0x36,0x36,0x35,0x34,0x26,0x23,0x02,0x08,0x01,0xc0,0xfc,0xd3,0xd5, 0xb0,0xfe,0xc2,0x82,0x01,0x1a,0xef,0xca,0x01,0x0c,0xd8,0xc6,0x14,0x11,0x6a,0x96,0xbe,0x5c,0x60,0x6a,0x1b,0xa7,0xa7,0xaa,0x8a,0xfe,0xc5,0x8c,0x47,0x61,0x97,0x4e,0x5b,0xd6,0xd0,0x86,0xd5,0xf6,0xef,0xc9,0xb2,0xfe,0xf7,0x5c,0x21,0x41,0x21,0x4d,0x8e,0x04,0xa2,0xa7,0x95,0x68,0x7f,0x4d,0x54,0x18,0x52,0xc8,0x95,0x8c,0xa1,0x00, 0x00,0x01,0x00,0x20,0x00,0x00,0x03,0x08,0x05,0x9a,0x00,0x05,0x00,0x1a,0x40,0x0c,0x02,0x7e,0x03,0x03,0x07,0x05,0x03,0x12,0x05,0x91,0x00,0x03,0x00,0x3f,0xed,0x3f,0x01,0x2f,0x12,0x39,0x2f,0xe9,0x31,0x30,0x13,0x21,0x11,0x23,0x11,0x21,0x20,0x02,0xe8,0xa8,0xfd,0xc0,0x05,0x9a,0xfa,0x66,0x05,0x02,0x00,0x01,0x00,0xa6,0x00,0x00, 0x01,0x4a,0x05,0xec,0x00,0x03,0x00,0x17,0x40,0x0a,0x00,0x84,0x01,0x01,0x04,0x05,0x02,0x00,0x01,0x15,0x00,0x3f,0x3f,0x11,0x12,0x01,0x39,0x2f,0xe9,0x31,0x30,0x21,0x23,0x11,0x33,0x01,0x4a,0xa4,0xa4,0x05,0xec,0x00,0x00,0x01,0x00,0xbc,0xfe,0x29,0x05,0xfc,0x05,0xb2,0x00,0x1e,0x00,0x2e,0x40,0x18,0x00,0x7e,0x0d,0x06,0x0d,0x06, 0x20,0x17,0x14,0x7e,0x15,0x19,0x10,0x91,0x1b,0x04,0x17,0x03,0x14,0x1b,0x03,0x91,0x0a,0x13,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0xe9,0x31,0x30,0x01,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x10,0x21,0x22,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x33, 0x12,0x21,0x32,0x12,0x11,0x05,0x27,0x34,0x31,0x20,0x36,0x1a,0x18,0x44,0x1f,0x7e,0x84,0xfe,0x9f,0xc1,0xf9,0xa8,0xa8,0x06,0x9d,0x01,0x3f,0xe8,0xf9,0x01,0x21,0x5b,0x48,0x0e,0x0e,0x9e,0x0b,0x09,0x91,0x7f,0x02,0x3d,0x01,0xe5,0xfe,0xe5,0xd4,0xfa,0xfe,0x07,0x71,0xfe,0xfa,0x01,0x1e,0xfe,0xcd,0xfe,0xe3,0x00,0x00,0x01,0x00,0xa6, 0xfe,0x29,0x04,0xb0,0x04,0x18,0x00,0x1e,0x00,0x2e,0x40,0x18,0x00,0x84,0x0d,0x06,0x0d,0x06,0x20,0x18,0x14,0x84,0x15,0x18,0x10,0x95,0x1b,0x10,0x17,0x0f,0x14,0x1b,0x03,0x95,0x0a,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0xe9,0x31,0x30,0x01,0x14,0x16,0x33,0x32,0x36,0x37,0x15, 0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0xf8,0x2c,0x2c,0x16,0x34,0x16,0x17,0x39,0x19,0x73,0x80,0xee,0x7a,0xa2,0xa4,0xa4,0x04,0x74,0xdc,0xa9,0xb1,0x01,0x14,0x5e,0x45,0x0a,0x0e,0x8d,0x0b,0x09,0x8d,0x83,0x01,0x50,0x01,0x46,0xb8,0x8e,0xfb,0xe1, 0x05,0xd7,0xaa,0xc2,0xd8,0xce,0x00,0x01,0x00,0xbc,0xfe,0x29,0x02,0xf4,0x05,0xb2,0x00,0x11,0x00,0x21,0x40,0x10,0x0c,0x0c,0x13,0x04,0x00,0x83,0x01,0x04,0x0e,0xf4,0x08,0x01,0x03,0x00,0x00,0x1b,0x00,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe1,0x32,0x11,0x39,0x2f,0x31,0x30,0x01,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16, 0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x01,0x64,0xa8,0xa8,0x04,0x26,0x9b,0x61,0x23,0x34,0x13,0x2f,0x57,0x78,0x92,0xfe,0x29,0x07,0x71,0xcd,0x6b,0x7a,0x07,0x07,0xb4,0x21,0xd1,0xc8,0x00,0x00,0x01,0x00,0xa6,0xfe,0x29,0x02,0xbc,0x04,0x12,0x00,0x10,0x00,0x21,0x40,0x10,0x00,0x00,0x12,0x0b,0x06,0x84,0x07,0x0a,0x02,0xec,0x0e,0x10, 0x09,0x0f,0x06,0x1b,0x00,0x3f,0x3f,0x3f,0xed,0x32,0x01,0x2f,0xe1,0x32,0x11,0x39,0x2f,0x31,0x30,0x01,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x02,0xbc,0x2c,0x50,0x6a,0x8c,0xa4,0xa4,0x04,0x25,0x8f,0x58,0x3e,0x24,0x03,0x5a,0x21,0xc5,0xac,0xfc,0x1f,0x05,0xd7,0xd3,0x6e,0x77,0x0e,0x00, 0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0xb9,0x05,0x9b,0x00,0x1e,0x00,0x2f,0x40,0x17,0x1d,0x19,0x12,0x08,0x12,0x08,0x20,0x1e,0x0c,0x7d,0x19,0x13,0x12,0x12,0x0f,0x91,0x16,0x13,0x09,0x1d,0x91,0x00,0x03,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x2f,0x33,0x01,0x2f,0xe1,0xc4,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x31,0x30,0x13,0x33,0x32, 0x37,0x21,0x32,0x17,0x33,0x15,0x21,0x22,0x00,0x15,0x14,0x00,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x20,0x00,0x11,0x34,0x12,0x36,0x37,0x21,0x6b,0xe6,0x64,0x4f,0x01,0xc6,0x32,0x3a,0x83,0xfe,0x88,0xe7,0xfe,0xb4,0x01,0x20,0xe9,0x57,0xa6,0x78,0x50,0xc0,0x6a,0xfe,0xc4,0xfe,0x88,0x84,0xad,0x35,0xfe,0xa7,0x05,0x9a,0x01,0x01, 0x97,0xfe,0xa4,0xeb,0xfa,0xfe,0xbd,0x28,0x38,0xa3,0x2a,0x2a,0x01,0x88,0x01,0x42,0x91,0x01,0x18,0x96,0x12,0x00,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x98,0x04,0x00,0x00,0x17,0x00,0x2d,0x40,0x16,0x16,0x13,0x0c,0x02,0x0c,0x02,0x19,0x17,0x06,0x83,0x13,0x0c,0x0c,0x09,0x95,0x10,0x16,0x03,0x16,0x95,0x00,0x0f,0x00,0x3f,0xed,0x32, 0x3f,0xed,0x32,0x2f,0x01,0x2f,0xe9,0xc6,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x31,0x30,0x13,0x21,0x15,0x21,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x00,0x35,0x34,0x36,0x37,0x23,0x60,0x03,0x38,0xfe,0xe3,0x9c,0xbf,0xbd,0x93,0x44,0x7f,0x44,0x45,0x82,0x44,0xdd,0xfe,0xe7,0x72,0x5a,0xe2,0x04,0x00, 0x89,0xda,0xaf,0xa1,0xdc,0x2b,0x30,0x9c,0x29,0x1f,0x01,0x16,0xdf,0x95,0xcc,0x39,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xf2,0x05,0x9a,0x00,0x09,0x00,0x25,0x40,0x12,0x08,0x7e,0x01,0x07,0x07,0x0b,0x04,0x7e,0x03,0x02,0x91,0x05,0x05,0x07,0x03,0x03,0x00,0x12,0x00,0x3f,0x3f,0x33,0x39,0x2f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x2f,0x33, 0xe9,0x31,0x30,0x21,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x04,0x4a,0xfc,0x72,0xa8,0x02,0xe6,0xa8,0x02,0x8e,0x03,0x0c,0xfd,0x8b,0x02,0x75,0xfa,0x66,0x00,0x00,0x02,0xff,0xe5,0xfe,0x1e,0x03,0x30,0x05,0xec,0x00,0x22,0x00,0x2c,0x00,0x55,0x40,0x2c,0x00,0x08,0x84,0x12,0x23,0x20,0x12,0x0c,0x04,0x12,0x04,0x12,0x04,0x2e, 0x28,0xef,0x1a,0x07,0x17,0x96,0x04,0x03,0x2b,0x00,0x2b,0x25,0x96,0x1d,0x20,0x1d,0x20,0x2b,0x01,0x2b,0x1d,0x2b,0x1d,0x0f,0x21,0x00,0x0a,0x95,0x0f,0x1c,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x10,0xed,0x11,0x33,0x10,0xc4,0x32,0xed,0x32,0x01,0x2f,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xc6,0x11,0x33,0x33, 0x10,0xe9,0x32,0x31,0x30,0x01,0x36,0x36,0x37,0x15,0x06,0x06,0x07,0x11,0x14,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x35,0x11,0x07,0x22,0x07,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x11,0x33,0x03,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x02,0x16,0x3c,0x75,0x3c,0x3c,0x75,0x3c,0xac,0x3c,0x32,0x29,0x4d,0x8e, 0xba,0x15,0x0c,0x0d,0x2e,0x8d,0xa4,0x85,0x6a,0x25,0x53,0x26,0xa4,0xa4,0x04,0x8f,0x2a,0x39,0x4d,0x61,0x25,0x03,0x8b,0x1a,0x49,0x34,0xa6,0x2a,0x3f,0x17,0xfc,0x8d,0xdf,0x1a,0x93,0x13,0xc0,0xa1,0x03,0x51,0x02,0x01,0x01,0x81,0x73,0x65,0x7b,0x16,0x22,0x01,0x84,0xfd,0x6a,0xc4,0x30,0x2a,0x3a,0x36,0x00,0x01,0x00,0xbc,0xfe,0x7f, 0x06,0x00,0x05,0x9a,0x00,0x1a,0x00,0x38,0x40,0x1c,0x12,0x0c,0x7e,0x0b,0x0e,0x7f,0x10,0x0b,0x10,0x0b,0x10,0x1c,0x02,0x1a,0x7e,0x00,0x15,0x06,0x01,0x1a,0x10,0x0d,0x91,0x12,0x12,0x0b,0x01,0x03,0x00,0x3f,0x33,0x3f,0xed,0xce,0x33,0x12,0x39,0x39,0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x33,0x31,0x30, 0x33,0x11,0x33,0x01,0x16,0x16,0x17,0x33,0x26,0x26,0x35,0x11,0x33,0x11,0x33,0x11,0x23,0x11,0x23,0x01,0x26,0x27,0x23,0x16,0x16,0x15,0x11,0xbc,0xda,0x02,0xce,0x17,0x1c,0x07,0x04,0x05,0x05,0xa8,0xc0,0x9b,0xf3,0xfd,0x1e,0x1b,0x13,0x06,0x04,0x04,0x05,0x9a,0xfb,0x9b,0x23,0x30,0x0d,0x1f,0x68,0x4c,0x03,0xf2,0xfa,0xfe,0xfd,0xe7, 0x01,0x81,0x04,0x77,0x2a,0x30,0x17,0x61,0x4d,0xfb,0xf4,0x00,0x00,0x01,0x00,0xa6,0xfe,0x8b,0x04,0x8f,0x04,0x18,0x00,0x16,0x00,0x35,0x40,0x1b,0x13,0x84,0x01,0x15,0xed,0x16,0x01,0x16,0x01,0x16,0x18,0x0b,0x08,0x84,0x09,0x0c,0x04,0x0f,0x10,0x0a,0x0f,0x08,0x15,0x16,0x13,0x01,0x15,0x00,0x3f,0xcd,0xce,0x3f,0x3f,0x3f,0xcd,0x32, 0x01,0x2f,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x31,0x30,0x21,0x23,0x11,0x10,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x33,0x11,0x23,0x04,0x02,0xae,0xee,0x7a,0xa2,0xa4,0xa4,0x04,0x74,0xdc,0xa9,0xb1,0x97,0x8d,0x02,0x48,0x01,0x46,0xb8,0x8e,0xfd,0xb8,0x04,0x00,0xaa, 0xc2,0xd8,0xce,0xfe,0x19,0xfe,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x00,0x1b,0x00,0x3e,0x40,0x1f,0x15,0x06,0x06,0x1d,0x1a,0x01,0x7d,0x0f,0x0d,0x0c,0x14,0x15,0x15,0x17,0x91,0x12,0x01,0x0c,0x91,0x1a,0x0f,0x0f,0x12,0x04,0x07,0x06,0x06,0x04,0x91,0x09,0x13,0x00,0x3f,0xed,0x32,0x2f,0x33,0x3f,0x39,0x2f, 0x33,0xed,0x32,0x10,0xed,0x32,0x2f,0x33,0x01,0x2f,0xcd,0x33,0xe9,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x01,0x21,0x16,0x00,0x33,0x32,0x37,0x15,0x06,0x23,0x20,0x00,0x03,0x23,0x35,0x33,0x12,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x07,0x21,0x02,0xa2,0xfe,0x6e,0x10,0x01,0x18,0xde,0xd8,0x9e,0x9f,0xed,0xfe,0xdc,0xfe,0x93, 0x10,0x5f,0x62,0x1d,0x01,0x91,0x01,0x2a,0xcb,0x87,0x9b,0xb9,0xe3,0xfe,0xd6,0x19,0x01,0x90,0x02,0x7d,0xe7,0xfe,0xe9,0x60,0xa3,0x54,0x01,0x6b,0x01,0x2a,0x9b,0x01,0x25,0x01,0x75,0x3b,0xb3,0x56,0xfe,0xe8,0xea,0x00,0x00,0x01,0x00,0x00,0xff,0xe8,0x03,0x62,0x04,0x18,0x00,0x1b,0x00,0x32,0x40,0x19,0x07,0x14,0x14,0x1d,0x0c,0x0f, 0x83,0x01,0x00,0x1a,0x0f,0x1a,0x95,0x0c,0x00,0x00,0x04,0x12,0x95,0x17,0x16,0x09,0x95,0x04,0x10,0x00,0x3f,0xed,0x3f,0xed,0x11,0x39,0x2f,0x33,0xed,0x32,0x01,0x2f,0xcd,0x33,0xe9,0x32,0x12,0x39,0x2f,0x33,0x31,0x30,0x11,0x33,0x36,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x33,0x32,0x37,0x15, 0x06,0x23,0x22,0x00,0x27,0x23,0x68,0x1f,0x01,0x15,0xd8,0x85,0x69,0x73,0x81,0x89,0xbc,0x19,0x01,0x36,0xfe,0xc3,0x09,0xbc,0x96,0x85,0x77,0x77,0xa1,0xd5,0xfe,0xf5,0x08,0x60,0x02,0x5c,0xc6,0xf6,0x32,0xa8,0x50,0xac,0x86,0x8b,0xa5,0xba,0x59,0x9c,0x47,0x01,0x0d,0xdc,0x00,0x01,0x00,0x01,0xff,0xe8,0x05,0x1a,0x05,0xb2,0x00,0x1f, 0x00,0x78,0x40,0x2b,0x19,0x19,0x00,0x00,0x0b,0x7e,0x06,0x08,0x06,0x08,0x06,0x21,0x1e,0x01,0x7e,0x13,0x10,0x19,0x19,0x1b,0x91,0x16,0x10,0x01,0x11,0x00,0x00,0x1f,0x08,0x91,0x13,0x1e,0x12,0x1f,0x12,0x11,0x1f,0x16,0x11,0xc0,0x09,0x01,0x09,0xb8,0xff,0xc0,0xb3,0x0f,0x13,0x48,0x09,0xb8,0xff,0xc0,0x40,0x0d,0x0a,0x0d,0x48,0x09, 0x09,0x16,0x04,0x0b,0x06,0x04,0x91,0x0d,0x13,0x00,0x3f,0xed,0x32,0x32,0x3f,0x39,0x2f,0x2b,0x2b,0x5d,0x39,0x12,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0xed,0x11,0x33,0x11,0x12,0x39,0x39,0x10,0xed,0x32,0x2f,0x01,0x2f,0x33,0xe9,0x32,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x32,0x2f,0x32,0x2f,0x31,0x30,0x01,0x01,0x16,0x00,0x33,0x32, 0x37,0x11,0x21,0x35,0x21,0x11,0x06,0x21,0x20,0x00,0x03,0x07,0x35,0x37,0x12,0x00,0x21,0x32,0x17,0x15,0x26,0x23,0x22,0x00,0x07,0x01,0x05,0x1a,0xfb,0xf6,0x13,0x01,0x19,0xe5,0xa9,0x7a,0xfe,0xc6,0x01,0xe2,0xd9,0xfe,0xf9,0xfe,0xe7,0xfe,0x92,0x20,0x64,0x5d,0x0b,0x01,0xa2,0x01,0x3b,0xeb,0x9e,0xaf,0xed,0xe2,0xfe,0xd5,0x14,0x04, 0x08,0x03,0xe0,0xfe,0x9c,0xed,0xfe,0xf0,0x43,0x01,0x92,0x98,0xfd,0x76,0x7a,0x01,0x4c,0x01,0x0d,0x22,0x9a,0x20,0x01,0x41,0x01,0x98,0x4c,0xba,0x6e,0xfe,0xdc,0xe0,0x01,0x64,0x00,0x03,0x00,0x00,0xfe,0x1e,0x04,0x81,0x04,0x18,0x00,0x21,0x00,0x29,0x00,0x31,0x00,0x60,0x40,0x34,0x22,0x2a,0x84,0x0d,0x0b,0x00,0x0e,0x1b,0x1b,0x19, 0x1d,0x84,0x2b,0x29,0x16,0x04,0x00,0x02,0x95,0x1f,0x1b,0x17,0x0f,0x15,0x2e,0x95,0x1c,0x29,0x22,0x0b,0x04,0x0c,0x1b,0x1b,0x19,0x2a,0x0e,0x03,0x0d,0x1a,0x0d,0x0c,0x1a,0x0c,0x08,0x13,0x10,0x05,0x25,0x95,0x08,0x16,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0xed,0x32,0x3f, 0x3f,0xed,0x32,0x01,0x2f,0x33,0x33,0x33,0xf9,0x32,0xc2,0x2f,0x2f,0xc4,0x33,0xcd,0xe9,0x32,0x31,0x30,0x17,0x16,0x33,0x20,0x11,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x07,0x35,0x37,0x26,0x35,0x10,0x12,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x37,0x15,0x07,0x11,0x10,0x21,0x22,0x27,0x13,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x05,0x25, 0x26,0x26,0x23,0x22,0x06,0x15,0xa8,0xac,0x9e,0x01,0x7a,0x04,0x75,0xeb,0x96,0xd0,0x29,0x79,0x62,0x02,0xfa,0xdb,0xcf,0x64,0x04,0xa4,0x71,0x71,0xfd,0xe4,0xbe,0x8e,0x72,0x1e,0x91,0x6c,0x8a,0xad,0xfd,0x9c,0x02,0x5c,0x16,0x97,0x6b,0x99,0xab,0xf6,0x60,0x01,0x92,0x70,0xc4,0xa8,0x8e,0x29,0x8e,0x21,0x0e,0x1e,0x01,0x14,0x01,0x34, 0xa6,0x8e,0xfe,0xe9,0x27,0x8e,0x27,0xfd,0xf7,0xfd,0xcc,0x48,0x02,0xf0,0x67,0x7d,0xc4,0x99,0x53,0x45,0xd1,0x5c,0x84,0xdf,0xc5,0x00,0x00,0x02,0x00,0x12,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x17,0x00,0x1d,0x00,0x57,0x40,0x2f,0x0b,0x10,0x0d,0x09,0x0a,0x0a,0x11,0x10,0x10,0x1f,0x13,0x04,0x19,0x7e,0x17,0x01,0x15,0x0f,0x12,0x13, 0x16,0x04,0x17,0x0e,0x0e,0x0c,0x1a,0x19,0x01,0x04,0x00,0x0d,0x00,0x17,0x17,0x18,0x0b,0x04,0x0d,0x05,0x02,0x11,0x15,0x12,0x09,0x02,0x03,0x00,0x3f,0x33,0x3f,0x33,0x12,0x17,0x39,0x11,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0x01,0x2f,0x33,0xc6,0xed,0x32,0x32,0x11,0x33,0x2f,0x33,0x33,0x2f,0x33,0x33,0x11,0x39,0x31, 0x30,0x13,0x37,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x17,0x25,0x15,0x05,0x01,0x23,0x01,0x07,0x11,0x23,0x11,0x07,0x01,0x15,0x37,0x27,0x26,0x27,0x12,0xaa,0xa8,0x04,0x07,0x13,0x0c,0x02,0x18,0xd1,0xfd,0x99,0x81,0x01,0xfb,0xfe,0x6a,0x01,0xac,0xea,0xfe,0x97,0xeb,0xa8,0xaa,0x01,0x52,0x89,0x5f,0x1e,0x08,0x01,0x7c, 0x3a,0x03,0xe4,0xfd,0x5e,0x0b,0x18,0x0e,0x02,0x71,0xfd,0x50,0x93,0xaf,0x96,0x8c,0xfe,0x1c,0x01,0xab,0x51,0xfe,0xa6,0x01,0x20,0x3a,0x01,0xdc,0xd2,0x2f,0x71,0x24,0x0e,0x00,0x00,0x02,0x00,0x26,0x00,0x00,0x03,0xf8,0x05,0xec,0x00,0x14,0x00,0x18,0x00,0x54,0x40,0x2e,0x12,0x11,0x15,0x0e,0x06,0x84,0x0b,0x09,0x07,0x14,0x10,0x11, 0x11,0x03,0x02,0x01,0x04,0x05,0x08,0x04,0x09,0x00,0x00,0x13,0x16,0x15,0x0b,0x04,0x0a,0x14,0x0a,0x09,0x09,0x17,0x12,0x0e,0x14,0x05,0x07,0x10,0x0f,0x0c,0x00,0x03,0x07,0x15,0x00,0x3f,0x33,0x3f,0x3f,0x12,0x17,0x39,0x11,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0x01,0x2f,0x33,0x33,0x2f,0x33,0x33,0x2f,0xce,0x33,0xe9, 0x32,0x32,0x11,0x39,0x31,0x30,0x01,0x05,0x01,0x23,0x01,0x07,0x15,0x23,0x35,0x07,0x35,0x37,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x17,0x25,0x05,0x37,0x27,0x23,0x03,0xea,0xfe,0xc2,0x01,0x4c,0xe6,0xfe,0xf7,0xbf,0xa4,0x80,0x80,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0x4d,0x01,0xa5,0xfd,0x60,0x5c,0x58,0x04,0x01,0xc5,0x6d,0xfe,0xa8, 0x01,0x20,0x42,0xde,0xa6,0x2c,0x8e,0x2c,0x04,0xb8,0xfc,0x3f,0x01,0xd5,0xfe,0x12,0x50,0x91,0xe7,0x20,0x60,0x00,0x00,0x03,0x00,0x12,0x00,0x00,0x05,0xea,0x05,0x9a,0x00,0x13,0x00,0x1c,0x00,0x26,0x00,0x58,0x40,0x31,0x0c,0x08,0x0a,0x0a,0x08,0x7e,0x25,0x07,0x07,0x28,0x18,0x04,0x11,0x7e,0x02,0x00,0x12,0x0c,0x25,0x26,0x0f,0x10, 0x13,0x06,0x00,0x0b,0x0b,0x06,0x09,0x01,0x0a,0x01,0x00,0x20,0x00,0x02,0x18,0x19,0x05,0x0a,0x14,0x08,0x03,0x0e,0x12,0x12,0x07,0x03,0x03,0x00,0x3f,0x33,0x3f,0x33,0x12,0x17,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x33,0x11,0x12,0x17,0x39,0x01,0x2f,0xce,0x33,0xe9,0x32,0x32,0x12,0x39,0x2f,0x33,0xf9,0xca,0x2f,0x11,0x33,0x31,0x30, 0x13,0x35,0x37,0x11,0x33,0x01,0x25,0x11,0x33,0x11,0x37,0x15,0x07,0x11,0x23,0x01,0x05,0x11,0x23,0x11,0x13,0x16,0x16,0x15,0x11,0x25,0x03,0x26,0x27,0x01,0x16,0x16,0x17,0x33,0x26,0x26,0x35,0x11,0x05,0x12,0xaa,0xda,0x01,0x90,0x01,0x72,0xa8,0xaa,0xaa,0xce,0xfe,0x6a,0xfe,0x88,0xa8,0xa0,0x04,0x04,0x01,0x26,0xfa,0x1b,0x13,0x03, 0x02,0x17,0x1c,0x07,0x04,0x05,0x05,0xfe,0xde,0x01,0x82,0x9a,0x3a,0x03,0x44,0xfd,0x8e,0x7e,0x01,0xf4,0xfe,0x45,0x3a,0x9a,0x3a,0xfc,0xbb,0x02,0x75,0x80,0xfe,0x0b,0x01,0xbc,0x03,0x15,0x17,0x61,0x4d,0xfe,0x83,0x64,0x01,0x84,0x2a,0x30,0xfc,0x64,0x23,0x30,0x0d,0x1f,0x68,0x4c,0x01,0x64,0x63,0x00,0x00,0x02,0x00,0x19,0x00,0x00, 0x04,0x86,0x04,0x18,0x00,0x15,0x00,0x1c,0x00,0x55,0x40,0x2e,0x17,0x0d,0x06,0x84,0x0b,0x09,0x07,0x14,0x02,0x00,0x00,0x02,0x84,0x18,0x03,0x0f,0x1a,0x95,0x01,0x04,0x05,0x03,0x09,0x00,0x00,0x14,0x18,0x17,0x0b,0x04,0x0a,0x15,0x0a,0x09,0x09,0x08,0x15,0x03,0x06,0x11,0x10,0x0d,0x0f,0x03,0x06,0x15,0x00,0x3f,0x33,0x3f,0x3f,0x12, 0x17,0x39,0x11,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0xed,0x32,0x01,0x2f,0x33,0xf9,0xca,0x2f,0x11,0x33,0x2f,0xce,0x33,0xe9,0x32,0x32,0x31,0x30,0x01,0x07,0x11,0x23,0x11,0x05,0x11,0x23,0x11,0x07,0x35,0x37,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x17,0x37,0x05,0x15,0x25,0x26,0x23,0x22,0x06,0x04,0x86,0x8e,0xa4, 0xfd,0xf6,0xa4,0x8d,0x8d,0xa4,0x04,0x74,0xdc,0x93,0xad,0x14,0x94,0xfc,0xc4,0x02,0x05,0x1d,0xcc,0x7a,0xa2,0x02,0x78,0x30,0xfd,0xb8,0x02,0x10,0xb4,0xfe,0xa4,0x01,0x23,0x30,0x8e,0x30,0x02,0x4f,0xaa,0xc2,0xa6,0x9e,0x32,0xbe,0x5e,0xb2,0xf2,0xb8,0x00,0x03,0x00,0x12,0x00,0x00,0x04,0xc0,0x05,0x9a,0x00,0x1d,0x00,0x24,0x00,0x2a, 0x00,0x65,0x40,0x35,0x0f,0x22,0x1c,0x15,0x14,0x09,0x09,0x14,0x14,0x2c,0x07,0x0c,0x27,0x23,0x26,0x1e,0x1b,0x7e,0x02,0x00,0x1c,0x0a,0x23,0x24,0x1d,0x04,0x00,0x09,0x09,0x07,0x27,0x26,0x02,0x04,0x01,0x08,0x01,0x00,0x0f,0x1e,0x91,0x08,0x00,0x1a,0x1a,0x03,0x15,0x1b,0x12,0x25,0x91,0x03,0x03,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39, 0x2f,0x39,0x39,0xed,0x39,0x11,0x33,0x11,0x12,0x17,0x39,0x33,0x11,0x12,0x17,0x39,0x01,0x2f,0xc6,0x33,0xe9,0x32,0x32,0x2f,0x33,0xc1,0x32,0x11,0x33,0x2f,0x33,0x2f,0x11,0x33,0x12,0x39,0x39,0x31,0x30,0x13,0x35,0x37,0x11,0x21,0x32,0x16,0x17,0x37,0x15,0x07,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x17,0x01,0x23,0x03,0x26,0x26, 0x23,0x23,0x11,0x23,0x11,0x17,0x33,0x32,0x36,0x35,0x35,0x05,0x11,0x11,0x25,0x26,0x26,0x23,0x12,0xaa,0x01,0xac,0x84,0xcd,0x35,0xbc,0x91,0x03,0xa7,0x97,0x2f,0x4d,0x59,0x01,0x0d,0xc8,0xf0,0x47,0x7b,0x58,0x8a,0xa8,0xa8,0xe4,0x81,0xa3,0xfd,0xf8,0x01,0xdb,0x23,0x7b,0x57,0x02,0xf4,0x9a,0x3a,0x01,0xd2,0x5d,0x5f,0x40,0x9a,0x31, 0x1b,0x1c,0x90,0xcb,0x27,0x04,0x15,0x44,0x8e,0xfe,0x51,0x01,0x92,0x79,0x57,0xfd,0x9e,0x03,0x2e,0x34,0x97,0x7d,0x0a,0xb1,0x01,0x9b,0xfe,0xff,0xa1,0x2f,0x31,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0xbc,0x04,0x12,0x00,0x17,0x00,0x48,0x40,0x23,0x17,0x11,0x11,0x19,0x16,0x09,0x02,0x84,0x07,0x05,0x03,0x11,0x11,0x0b,0x13,0x0e, 0x10,0x04,0x01,0x05,0x00,0x00,0x07,0x16,0x06,0x17,0x06,0x05,0x17,0x05,0x03,0x08,0x0f,0x03,0x15,0x00,0x3f,0x3f,0x12,0x39,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0x3f,0xcd,0x32,0x32,0x2f,0x01,0x2f,0xc6,0x33,0xe9,0x32,0x32,0x11,0x39,0x2f,0x33,0x31,0x30,0x01,0x05,0x11,0x23,0x11,0x07,0x35,0x37,0x11,0x33, 0x15,0x33,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x25,0x02,0xa4,0xfe,0xa6,0xa4,0x83,0x83,0xa4,0x04,0x25,0x8f,0x58,0x3e,0x24,0x2c,0x50,0x69,0x8d,0x01,0x5a,0x02,0x20,0xa1,0xfe,0x81,0x01,0x33,0x3c,0x92,0x3c,0x02,0x3b,0xd3,0x6e,0x77,0x0e,0xaa,0x21,0xc5,0xa5,0xa1,0x00,0x00,0x01,0x00,0x45,0xff,0xe8,0x04,0x06, 0x05,0xb2,0x00,0x2a,0x00,0x5b,0x40,0x31,0x0f,0x7d,0x00,0x04,0x15,0x15,0x19,0x7d,0x26,0x04,0x26,0x0a,0x0a,0x26,0x04,0x03,0x2c,0x20,0x1f,0x20,0x29,0x16,0x2a,0x15,0x15,0x01,0x13,0x00,0x14,0x00,0x2a,0x26,0x19,0x2a,0x14,0x04,0x0f,0x06,0x07,0x23,0x91,0x1c,0x13,0x09,0x0a,0x0c,0x91,0x07,0x04,0x00,0x3f,0xed,0xcd,0x32,0x3f,0xed, 0x12,0x17,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0xc4,0x32,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xf9,0xc2,0x2f,0x10,0xc6,0xe9,0x31,0x30,0x13,0x25,0x26,0x26,0x35,0x34,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x17,0x25,0x15,0x05,0x16,0x16,0x15,0x14,0x04,0x23,0x22,0x26, 0x27,0x35,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x05,0x45,0x01,0x2b,0x86,0x6f,0x01,0x1b,0xd7,0xd3,0x62,0x7f,0xc7,0x8a,0xa7,0x54,0x8e,0x3f,0x01,0xba,0xfe,0xf0,0x7b,0x6d,0xfe,0xf2,0xf0,0x52,0xe2,0x33,0x40,0xe2,0x5f,0x9c,0x98,0x62,0xaf,0xfe,0x28,0x02,0x6f,0x66,0x4d,0xa4,0x6d,0xae,0xd1,0x33,0xbd,0x58,0x74,0x64,0x4d, 0x68,0x4d,0x1f,0x97,0x96,0x5d,0x4f,0xa8,0x64,0xba,0xc8,0x2f,0x23,0xc6,0x39,0x48,0x72,0x6d,0x4a,0x79,0x59,0xa1,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x2b,0x04,0x18,0x00,0x27,0x00,0x63,0x40,0x35,0x26,0x01,0x04,0x22,0x83,0x13,0x17,0x04,0x83,0x0e,0x27,0x1d,0x14,0x11,0x0e,0x17,0x0e,0x1d,0x1d,0x0e,0x17,0x03,0x29,0x09,0x1d,0x1f, 0x95,0x11,0x01,0x12,0x00,0x00,0x14,0x26,0x13,0x27,0x13,0x12,0x0e,0x04,0x12,0x27,0x17,0x22,0x06,0x07,0x1a,0x10,0x0a,0x0c,0x95,0x07,0x16,0x00,0x3f,0xfd,0xc6,0x3f,0x12,0x17,0x39,0x11,0x33,0x11,0x12,0x39,0x39,0x33,0x11,0x12,0x39,0x39,0xfd,0xc6,0x01,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x39,0x10,0xc6,0x10,0xe9,0x10, 0xc6,0xe9,0x11,0x39,0x39,0x31,0x30,0x01,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x26,0x27,0x05,0x35,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x25,0x03,0x2b,0x9e,0x3f,0x43,0xe2,0xb3,0x9f,0x73,0x85,0xa2,0xd8,0x41,0x68,0xfe,0xa2,0xa7, 0x53,0x4a,0xe2,0xa6,0x86,0x68,0x71,0x93,0x5b,0x6f,0x41,0x39,0x51,0x01,0x4e,0x02,0x2a,0x37,0x27,0x6a,0x50,0x89,0xa1,0x3d,0xb0,0x63,0x90,0x33,0x4d,0x2a,0x78,0x8e,0x39,0x2d,0x74,0x54,0x84,0xa4,0x2e,0xa6,0x4a,0x50,0x40,0x3b,0x45,0x18,0x21,0x73,0x00,0x01,0xff,0xac,0x00,0x00,0x05,0x44,0x05,0x9a,0x00,0x17,0x00,0x39,0x40,0x1e, 0x17,0x7e,0x14,0x00,0x00,0x04,0x19,0x09,0x7e,0x0e,0x13,0x03,0x7e,0x04,0x15,0x03,0x02,0x91,0x13,0x0b,0x0b,0x04,0x06,0x91,0x11,0x03,0x04,0x12,0x00,0x12,0x00,0x3f,0x3f,0x3f,0xed,0x12,0x39,0x2f,0x2f,0xed,0x3f,0x01,0x2f,0xed,0x32,0xd4,0xe9,0x11,0x12,0x39,0x2f,0x33,0xe9,0x31,0x30,0x21,0x11,0x21,0x11,0x23,0x11,0x23,0x22,0x06, 0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x36,0x33,0x33,0x11,0x21,0x11,0x33,0x11,0x04,0x9c,0xfd,0x1a,0xa8,0x18,0x51,0x59,0x14,0x9e,0x16,0xc8,0x9a,0xa8,0x02,0xe6,0xa8,0x02,0x8e,0xfd,0x72,0x05,0x02,0x5c,0x4e,0x36,0x34,0x36,0x44,0x88,0xaa,0xfd,0x8b,0x02,0x75,0xfa,0x66,0x00,0x02,0x00,0x19,0x02,0x9a,0x03,0x4b,0x05,0x9a,0x00,0x13, 0x00,0x17,0x00,0x5d,0xb3,0x0a,0x0a,0x08,0x0c,0xb8,0x01,0x0c,0xb7,0x14,0x05,0x0d,0x0d,0x19,0x17,0x04,0x10,0xb8,0x01,0x0c,0xb3,0x13,0x01,0x11,0x0f,0xb8,0x01,0x0e,0x40,0x0a,0x30,0x17,0x40,0x17,0x02,0x17,0x17,0x00,0x0d,0x11,0xb8,0x01,0x0a,0xb2,0x16,0x0b,0x13,0xb8,0x01,0x0e,0xb4,0x08,0x04,0x00,0x06,0x02,0xb8,0x01,0x06,0x00, 0x3f,0x33,0xde,0x32,0x32,0xed,0x32,0x32,0x3f,0x33,0x12,0x39,0x2f,0x5d,0xed,0x01,0x2f,0x33,0xce,0xe1,0x32,0x32,0x12,0x39,0x2f,0x33,0x33,0xf1,0x32,0xca,0x2f,0x31,0x30,0x13,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x23,0x05,0x35,0x21,0x15,0x19,0x62,0x83,0x01,0x68,0x84,0x61, 0x61,0x84,0xfe,0x98,0x83,0x62,0x02,0x4d,0xfe,0x98,0x05,0x2b,0x6f,0x6f,0x6f,0x6f,0x70,0xfd,0xdf,0x01,0x4e,0xfe,0xb2,0x02,0x21,0x63,0x63,0x63,0x00,0x03,0x00,0x3e,0x02,0x89,0x03,0xf6,0x04,0xcf,0x00,0x1f,0x00,0x2b,0x00,0x30,0x00,0x7a,0xb3,0x15,0x02,0x30,0x0b,0xb8,0x01,0x0c,0xb2,0x22,0x0f,0x0a,0xb8,0x01,0x0c,0xb6,0x2c,0x22, 0x2c,0x22,0x2c,0x32,0x28,0xb8,0x01,0x0c,0xb2,0x1c,0x02,0x25,0xbb,0x01,0x0d,0x00,0x1f,0x00,0x0b,0x01,0x0d,0x40,0x0e,0x0c,0x30,0x1c,0x30,0x2c,0x30,0x03,0x30,0x0f,0x30,0x0f,0x1f,0x0d,0x2e,0x41,0x0d,0x01,0x0d,0x00,0x06,0x00,0x1f,0x01,0x09,0x00,0x15,0x00,0x2b,0x01,0x0d,0x00,0x19,0x00,0x0d,0x01,0x0d,0x00,0x12,0x00,0x19,0x01, 0x0b,0x00,0x3f,0xd4,0xed,0x10,0xed,0x32,0x3f,0xd4,0xed,0x11,0x12,0x39,0x39,0x2f,0x2f,0x5d,0xed,0x10,0xed,0x32,0x01,0x2f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xfd,0xc6,0x10,0xed,0x32,0x39,0x39,0x31,0x30,0x00,0x16,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x21,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x27,0x23,0x06, 0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x12,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x25,0x26,0x23,0x22,0x07,0x01,0x9f,0x71,0x2b,0x04,0x23,0x6a,0x37,0x71,0x82,0xfe,0x87,0x0b,0x99,0x5b,0x4f,0x48,0x78,0x3b,0x6c,0x29,0x04,0x26,0x71,0x48,0x7f,0x9b,0xa0,0x86,0x43,0x57,0x57,0x49,0x49,0x57,0x58,0x48,0x02,0x1d, 0x02,0x78,0x78,0x0c,0x04,0xcf,0x2c,0x3c,0x36,0x32,0x92,0x7b,0x43,0x8f,0x35,0x6f,0x2d,0x2a,0x3c,0x30,0x36,0x9d,0x80,0x85,0xa4,0xfe,0x25,0x61,0x57,0x58,0x60,0x61,0x57,0x57,0x61,0xee,0x8a,0x8a,0x00,0x01,0x00,0x90,0xff,0xe8,0x06,0x3e,0x04,0x00,0x00,0x1f,0x00,0x3b,0x40,0x1f,0x1b,0x0b,0x84,0x08,0x08,0x1f,0x14,0x12,0x84,0x11, 0x11,0x21,0x02,0x84,0x1f,0x1b,0x05,0x95,0x1d,0x16,0x15,0x0d,0x95,0x18,0x16,0x14,0x15,0x11,0x01,0x09,0x0f,0x00,0x3f,0x33,0x33,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xed,0x33,0x12,0x39,0x2f,0xe9,0x33,0x31,0x30,0x13,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x10,0x33,0x32,0x36,0x35, 0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x26,0x27,0x06,0x23,0x20,0x11,0x90,0xa4,0x67,0x7e,0x68,0x94,0xa4,0xe9,0x6c,0x8c,0xa4,0xa4,0x04,0x6e,0xd0,0x6b,0x9a,0x1d,0x72,0xe2,0xfe,0xae,0x04,0x00,0xfd,0xb4,0xa8,0x9a,0xc1,0x85,0x02,0x48,0xfd,0xa0,0xfe,0xd2,0xb4,0x92,0x02,0x48,0xfc,0x00,0xa2,0xba,0x75,0x5f,0xd4,0x01,0xa1, 0x00,0x01,0x00,0x54,0x00,0x00,0x03,0x2c,0x05,0x9a,0x00,0x09,0x00,0x29,0x40,0x14,0x02,0x7e,0x03,0x06,0x03,0x06,0x03,0x0b,0x09,0x04,0x91,0x07,0x07,0x00,0x03,0x12,0x08,0x91,0x00,0x03,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x01,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x31,0x30,0x13,0x21,0x11,0x23,0x11,0x21,0x35,0x21,0x11, 0x21,0x54,0x02,0xd8,0xa8,0xfd,0xfa,0x02,0x06,0xfd,0xd0,0x05,0x9a,0xfa,0x66,0x02,0x7b,0x97,0x01,0xf0,0x00,0x02,0x00,0x52,0x00,0x00,0x03,0xbf,0x05,0x9a,0x00,0x0a,0x00,0x12,0x00,0x28,0x40,0x14,0x11,0x08,0x7e,0x09,0x09,0x14,0x0d,0x7d,0x03,0x0a,0x91,0x11,0x11,0x06,0x09,0x12,0x12,0x91,0x06,0x03,0x00,0x3f,0xed,0x3f,0x12,0x39, 0x2f,0xed,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x33,0x31,0x30,0x01,0x22,0x00,0x35,0x34,0x36,0x33,0x21,0x11,0x23,0x11,0x03,0x20,0x11,0x14,0x16,0x33,0x33,0x11,0x02,0x5a,0xf0,0xfe,0xe8,0xff,0xe4,0x01,0x8a,0xa8,0xc5,0xfe,0xb0,0xb6,0xaf,0xb0,0x02,0x1e,0x01,0x05,0xcb,0xcd,0xdf,0xfa,0x66,0x02,0x1e,0x02,0xe4,0xfe,0xe4,0x92,0x9e, 0x02,0x4c,0x00,0x01,0x00,0xbd,0x00,0x00,0x06,0x73,0x05,0x9a,0x00,0x1e,0x00,0x30,0x40,0x18,0x15,0x13,0x7e,0x05,0x00,0x0d,0x12,0x12,0x20,0x1d,0x01,0x7e,0x00,0x0d,0x06,0x18,0x03,0x15,0x1d,0x12,0x12,0x09,0x00,0x03,0x00,0x3f,0x32,0x32,0x3f,0x33,0x17,0x39,0x01,0x2f,0xe9,0x32,0x12,0x39,0x2f,0x39,0x12,0x39,0xe9,0x33,0x31,0x30, 0x13,0x33,0x11,0x14,0x06,0x07,0x33,0x36,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x26,0x26,0x35,0x11,0x33,0x11,0x23,0x01,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x23,0xbd,0xa7,0x07,0x07,0x04,0x18,0x13,0x01,0xea,0x52,0x01,0xe9,0x14,0x17,0x04,0x04,0x04,0xa2,0xde,0xfe,0x48,0x33,0x0f,0x06,0x16,0x22,0x0d,0xfe,0x3f,0xd2,0x05,0x9a,0xfc, 0x3e,0x39,0x8b,0x53,0x63,0x28,0x04,0x4e,0xfb,0xba,0x2e,0x65,0x2b,0x8b,0x63,0x03,0xc0,0xfa,0x66,0x03,0xe8,0x74,0x38,0x3c,0x57,0x1d,0xfc,0x1c,0x00,0x01,0x00,0xbc,0xfe,0x29,0x01,0x64,0x05,0x9a,0x00,0x03,0x00,0x17,0x40,0x0a,0x00,0x7e,0x01,0x01,0x04,0x05,0x02,0x03,0x01,0x1b,0x00,0x3f,0x3f,0x11,0x12,0x01,0x39,0x2f,0xe9,0x31, 0x30,0x01,0x23,0x11,0x33,0x01,0x64,0xa8,0xa8,0xfe,0x29,0x07,0x71,0x00,0x00,0x01,0x00,0x1a,0x00,0x00,0x09,0x12,0x05,0x9a,0x00,0x27,0x00,0x48,0x40,0x25,0x0c,0x0b,0x04,0x00,0x0f,0x15,0x14,0x24,0x1f,0x1e,0x18,0x18,0x24,0x0f,0x04,0x04,0x0a,0x1d,0x1d,0x29,0x27,0x10,0x0a,0x0f,0x18,0x04,0x23,0x04,0x09,0x1c,0x14,0x0b,0x03,0x1f, 0x00,0x09,0x12,0x00,0x3f,0x33,0x33,0x3f,0x33,0x33,0x12,0x17,0x39,0x01,0x2f,0x2f,0x33,0x11,0x33,0x2f,0x12,0x17,0x39,0x11,0x33,0x33,0x11,0x33,0x33,0x11,0x33,0x11,0x33,0x33,0x31,0x30,0x21,0x01,0x27,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x16,0x17,0x33,0x36,0x37, 0x01,0x33,0x01,0x23,0x01,0x26,0x26,0x27,0x23,0x06,0x07,0x01,0x03,0x70,0xfe,0xcc,0x13,0x0a,0x03,0x04,0x03,0x12,0x0a,0xfe,0xd7,0xb6,0x01,0xb2,0xb9,0x01,0x31,0x13,0x05,0x05,0x02,0x10,0x0d,0x01,0x3d,0xa1,0x01,0x30,0x10,0x08,0x04,0x04,0x17,0x01,0x25,0xb6,0xfe,0x6b,0xc5,0xfe,0xd9,0x0a,0x0b,0x02,0x04,0x06,0x14,0xfe,0xd7,0x04, 0x1a,0x46,0x23,0x25,0x25,0x46,0x23,0xfb,0xe6,0x05,0x9a,0xfb,0xb4,0x45,0x4b,0x1a,0x48,0x2e,0x04,0x4c,0xfb,0xac,0x39,0x4d,0x34,0x56,0x04,0x50,0xfa,0x66,0x04,0x18,0x22,0x48,0x28,0x47,0x49,0xfb,0xe6,0x00,0xff,0xff,0x00,0x50,0x00,0x00,0x06,0xd7,0x05,0xb0,0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00, 0x01,0x07,0x02,0x3a,0x04,0x37,0xfd,0xb9,0x00,0x07,0xb2,0x02,0x11,0x2c,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x50,0xff,0xeb,0x06,0xd4,0x05,0xb0,0x00,0x27,0x0c,0xea,0x04,0x2e,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x06,0x00,0xf0,0x00,0x00,0x00,0x09,0xb3,0x01,0x00,0x1f,0x2d,0x00,0x3f,0x35,0x35,0x00,0xff,0xff, 0x00,0x4a,0xff,0xec,0x09,0x19,0x05,0xb0,0x00,0x26,0x00,0xf0,0xfa,0x00,0x00,0x27,0x00,0xf0,0x04,0x00,0xfd,0xb9,0x00,0x27,0x0c,0xe1,0x06,0x74,0x00,0x00,0x01,0x07,0x00,0xbc,0x02,0xbf,0x00,0x00,0x00,0x0e,0xb6,0x03,0x02,0x1a,0x2d,0x01,0x0d,0x2c,0x00,0x3f,0x35,0x3f,0x35,0x35,0xff,0xff,0x00,0x50,0xff,0xec,0x06,0xa3,0x05,0xb0, 0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x02,0x39,0x04,0x19,0xfd,0xb9,0x01,0x07,0x00,0xbc,0x02,0xbf,0x00,0x00,0x00,0x07,0xb2,0x01,0x30,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x8d,0xff,0xec,0x06,0xe5,0x05,0xae,0x00,0x26,0x00,0xf1,0x25,0x00,0x00,0x27,0x00,0xbc,0x03,0x01,0x00,0x00,0x01,0x07,0x02,0x39,0x04,0x5b,0xfd,0xb9, 0x00,0x07,0xb2,0x02,0x47,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x81,0xff,0xec,0x06,0xe5,0x05,0xae,0x00,0x26,0x00,0xf2,0x00,0x00,0x00,0x27,0x00,0xbc,0x03,0x01,0x00,0x00,0x01,0x07,0x02,0x39,0x04,0x5b,0xfd,0xb9,0x00,0x07,0xb2,0x02,0x48,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x2f,0xff,0xec,0x06,0xa3,0x05,0x9a,0x00,0x26, 0x02,0x38,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x07,0x02,0x39,0x04,0x19,0xfd,0xb9,0x00,0x07,0xb2,0x03,0x39,0x2d,0x00,0x3f,0x35,0x00,0xff,0xff,0x00,0x50,0xff,0xec,0x06,0xb3,0x05,0xb0,0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xbf,0x00,0x00,0x01,0x07,0x0c,0xe7,0x04,0x0d,0x00,0x00,0x00,0x09, 0xb3,0x03,0x02,0x2b,0x2d,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x7b,0xff,0xec,0x06,0xed,0x05,0x9e,0x00,0x26,0x02,0x39,0x00,0x00,0x00,0x27,0x00,0xbc,0x02,0xf9,0x00,0x00,0x01,0x07,0x0c,0xe7,0x04,0x47,0x00,0x00,0x00,0x09,0xb3,0x03,0x02,0x43,0x2d,0x00,0x3f,0x35,0x35,0x00,0xff,0xff,0x00,0x50,0x00,0x00,0x05,0x71,0x05,0xb0, 0x00,0x26,0x00,0xf0,0x00,0x00,0x00,0x07,0x00,0xbc,0x02,0xbf,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x03,0xa4,0x05,0x9a,0x02,0x06,0x00,0x2f,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x04,0x8c,0x05,0xb2,0x02,0x06,0x00,0x26,0x00,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x3e,0x05,0x9a,0x02,0x06,0x00,0x27,0x00,0x00,0xff,0xff, 0x00,0xbc,0x00,0x00,0x06,0x72,0x05,0x9a,0x02,0x06,0x00,0x30,0x00,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x05,0x12,0x05,0xd9,0x00,0x26,0x00,0x5b,0x00,0x00,0x00,0x07,0x00,0x4c,0x03,0xac,0x00,0x00,0xff,0xff,0x00,0x1a,0x00,0x00,0x07,0x02,0x05,0xd9,0x00,0x26,0x00,0x5b,0x00,0x00,0x00,0x27,0x00,0x4c,0x03,0xac,0x00,0x00,0x00,0x07, 0x00,0x4c,0x05,0x9c,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x01,0x4a,0x05,0xec,0x02,0x06,0x00,0x4f,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0x62,0x04,0x18,0x02,0x06,0x00,0x46,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x04,0x10,0x05,0xec,0x02,0x06,0x00,0x47,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x06,0x54,0x04,0x18, 0x02,0x06,0x00,0x50,0x00,0x00,0x00,0x03,0x00,0x5e,0x00,0x00,0x07,0xde,0x05,0x9a,0x00,0x0f,0x00,0x19,0x00,0x23,0x00,0x2d,0x40,0x17,0x11,0x7e,0x22,0x22,0x05,0x0a,0x7d,0x17,0x17,0x25,0x1c,0x7d,0x05,0x10,0x23,0x91,0x07,0x03,0x11,0x22,0x91,0x00,0x12,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x12, 0x39,0x2f,0xe9,0x31,0x30,0x21,0x22,0x24,0x26,0x02,0x35,0x10,0x21,0x21,0x20,0x11,0x14,0x02,0x06,0x04,0x23,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x10,0x21,0x21,0x20,0x11,0x14,0x1e,0x02,0x33,0x33,0x11,0x03,0x64,0xaa,0xfe,0xe4,0xce,0x72,0x02,0xf6,0x01,0x94,0x02,0xf6,0x72,0xce,0xfe,0xe4,0xaa,0x66,0x68,0x8b,0xdd,0x9a,0x52,0xfd, 0xb6,0xfe,0x74,0xfd,0xb6,0x52,0x9a,0xdd,0x8b,0x68,0x65,0xbf,0x01,0x10,0xab,0x02,0xbb,0xfd,0x45,0xab,0xfe,0xf0,0xbf,0x65,0x05,0x02,0xfb,0x96,0x4c,0x93,0xd8,0x8c,0x02,0x27,0xfd,0xd9,0x8c,0xd8,0x93,0x4c,0x04,0x6a,0x00,0x03,0x00,0xbc,0x00,0x00,0x05,0x3e,0x05,0x9a,0x00,0x09,0x00,0x20,0x00,0x2b,0x00,0x41,0x40,0x22,0x11,0x7e, 0x24,0x24,0x00,0x04,0x7d,0x1e,0x1e,0x2d,0x2b,0x0b,0x18,0x7e,0x00,0x2a,0x92,0x0b,0x2b,0x92,0x17,0x0b,0x17,0x0b,0x17,0x00,0x0a,0x91,0x01,0x03,0x18,0x91,0x00,0x12,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x01,0x2f,0xe9,0x32,0x32,0x12,0x39,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x31,0x30,0x33,0x11,0x21, 0x20,0x11,0x14,0x02,0x06,0x04,0x23,0x03,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x33,0x32,0x3e,0x02,0x35,0x10,0x21,0x03,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0xbc,0x01,0x8c,0x02,0xf6,0x72,0xce,0xfe,0xe4,0xaa,0xd4,0x5a,0x65,0xa1,0x6f,0x3b,0x3a,0x6f,0xa0,0x65,0x5c,0xd6,0x8b,0xdd,0x9a,0x52,0xfd, 0xb6,0x83,0x78,0x89,0x24,0x44,0x60,0x3c,0x5a,0x05,0x9a,0xfd,0x45,0xab,0xfe,0xf0,0xbf,0x65,0x05,0x02,0x9d,0x30,0x61,0x95,0x65,0x65,0x9d,0x6b,0x38,0x9d,0x4c,0x93,0xd8,0x8c,0x02,0x27,0xfc,0xba,0x8b,0x93,0x49,0x64,0x3d,0x1a,0xfd,0xde,0x00,0x05,0x00,0x5e,0x00,0x00,0x07,0xde,0x05,0x9a,0x00,0x0f,0x00,0x26,0x00,0x3d,0x00,0x48, 0x00,0x53,0x00,0x6b,0x40,0x39,0x45,0x7e,0x20,0x53,0x30,0x3d,0x7e,0x19,0x3e,0x26,0x19,0x36,0x7e,0x4c,0x20,0x19,0x4c,0x4c,0x19,0x20,0x03,0x05,0x0a,0x7d,0x2c,0x2c,0x55,0x13,0x7d,0x05,0x52,0x3f,0x92,0x26,0x30,0x26,0x53,0x3e,0x92,0x1a,0x3c,0x1a,0x26,0x1a,0x26,0x1a,0x00,0x2f,0x10,0x91,0x07,0x03,0x3d,0x19,0x91,0x00,0x12,0x00, 0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x01,0x2f,0xe9,0x12,0x39,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xe9,0x11,0x33,0x33,0x10,0xe9,0x32,0x32,0x10,0xe9,0x31,0x30,0x21,0x22,0x24,0x26,0x02,0x35,0x10,0x21,0x21,0x20,0x11,0x14,0x02,0x06,0x04,0x23,0x01, 0x23,0x20,0x11,0x14,0x1e,0x02,0x33,0x33,0x35,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x01,0x32,0x3e,0x02,0x35,0x10,0x21,0x23,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x03,0x11,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x21,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x03,0x64,0xaa,0xfe,0xe4, 0xce,0x72,0x02,0xf6,0x01,0x94,0x02,0xf6,0x72,0xce,0xfe,0xe4,0xaa,0xfe,0xf2,0x72,0xfd,0xb6,0x52,0x9a,0xdd,0x8b,0x68,0x5c,0x65,0xa0,0x6f,0x3a,0x3b,0x6f,0xa1,0x65,0x5a,0x01,0x10,0x8b,0xdd,0x9a,0x52,0xfd,0xb6,0x72,0x5a,0x65,0xa1,0x6f,0x3b,0x3a,0x6f,0xa0,0x65,0x5c,0xa8,0x5a,0x3c,0x60,0x44,0x24,0x89,0x78,0x01,0x62,0x78,0x89, 0x24,0x44,0x60,0x3c,0x5a,0x65,0xbf,0x01,0x10,0xab,0x02,0xbb,0xfd,0x45,0xab,0xfe,0xf0,0xbf,0x65,0x05,0x02,0xfd,0xd9,0x8c,0xd8,0x93,0x4c,0x9d,0x38,0x6b,0x9d,0x65,0x65,0x95,0x61,0x30,0xfc,0x33,0x4c,0x93,0xd8,0x8c,0x02,0x27,0x9d,0x30,0x61,0x95,0x65,0x65,0x9d,0x6b,0x38,0x9d,0x01,0x24,0x02,0x22,0x1a,0x3d,0x64,0x49,0x93,0x8b, 0x8b,0x93,0x49,0x64,0x3d,0x1a,0xfd,0xde,0x00,0x01,0x00,0x68,0xff,0xe8,0x04,0x96,0x05,0xb2,0x00,0x19,0x00,0x2f,0x40,0x18,0x06,0x7d,0x13,0x13,0x1b,0x0d,0x19,0x0c,0x2f,0x0d,0x01,0x0d,0x0d,0x0f,0x91,0x0a,0x13,0x00,0x19,0x19,0x17,0x91,0x02,0x04,0x00,0x3f,0xed,0x32,0x2f,0x33,0x3f,0xed,0x32,0x2f,0x5d,0x33,0x01,0x2f,0x33,0x12, 0x39,0x2f,0xe9,0x31,0x30,0x13,0x36,0x33,0x20,0x17,0x16,0x11,0x10,0x07,0x06,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x36,0x11,0x10,0x27,0x26,0x23,0x22,0x07,0x68,0x9f,0xed,0x01,0x31,0xb9,0xb8,0xcf,0xcf,0xfe,0xc2,0xcb,0x87,0x9b,0xb9,0xf6,0x9b,0x99,0x8f,0x90,0xe9,0xd9,0x9d,0x05,0x5e,0x54,0xc5,0xc4,0xfe,0xbf,0xfe,0xa7,0xd3, 0xd4,0x3b,0xb3,0x56,0xa5,0xa5,0x01,0x14,0x01,0x05,0x9d,0x9b,0x60,0x00,0x00,0x01,0x00,0x5e,0xfe,0x7f,0x04,0x8c,0x05,0xb2,0x00,0x20,0x00,0x38,0x40,0x1e,0x1c,0x7f,0x1f,0x0d,0x1f,0x0d,0x22,0x14,0x7d,0x05,0x0c,0x30,0x0d,0x01,0x0d,0x0d,0x0f,0x91,0x0a,0x04,0x20,0x1c,0x01,0x1c,0x1c,0x19,0x91,0x1e,0x00,0x13,0x00,0x3f,0xce,0xed, 0x32,0x2f,0x5d,0x3f,0xed,0x32,0x2f,0x5d,0x33,0x01,0x2f,0xe9,0x12,0x39,0x39,0x2f,0x2f,0xe9,0x31,0x30,0x05,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x24,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x11,0x23,0x11,0x06,0x03,0x00,0xa1,0xfb,0xac,0x5a,0x6b,0xc2,0x01,0x0d,0xa2,0xcb,0x87, 0x9b,0xb9,0x87,0xcf,0x8c,0x48,0x47,0x87,0xc0,0x7a,0x6b,0xba,0x51,0x9b,0x6e,0x18,0x70,0xc2,0x01,0x04,0x94,0xa6,0x01,0x1a,0xcd,0x73,0x3b,0xb3,0x56,0x61,0xa6,0xdc,0x7b,0x7a,0xd1,0x9a,0x58,0x2f,0x32,0xfd,0x9f,0x01,0x83,0x1a,0x00,0x01,0x01,0x05,0xff,0xcc,0x05,0x57,0x05,0xc6,0x00,0x08,0x00,0x24,0x40,0x0f,0x03,0x08,0x01,0x07, 0x07,0x0a,0x05,0x07,0x00,0x06,0x06,0x03,0x01,0x05,0x03,0x00,0x2f,0xdd,0xc4,0x12,0x39,0x11,0x33,0x2f,0x01,0x2f,0x12,0x39,0x2f,0x39,0xc9,0x39,0x31,0x30,0x01,0x01,0x11,0x01,0x01,0x11,0x01,0x11,0x21,0x03,0xb1,0x01,0xa6,0xfd,0xd7,0xfd,0xd7,0x01,0xa8,0x01,0x04,0x01,0x66,0x01,0x70,0xfe,0xd7,0xfe,0x1f,0x01,0xe1,0x01,0x29,0xfe, 0x90,0x04,0x60,0x00,0x00,0x04,0x00,0xbc,0x00,0x00,0x05,0x3e,0x05,0x9a,0x00,0x09,0x00,0x20,0x00,0x36,0x00,0x3f,0x00,0x65,0x40,0x18,0x2f,0x7f,0x3a,0x11,0x7e,0x26,0x3a,0x26,0x3a,0x26,0x00,0x04,0x7d,0x1e,0x1e,0x41,0x3f,0x36,0x2b,0x0b,0x18,0x7e,0x00,0x3e,0xb8,0x01,0x05,0xb4,0x2b,0x2a,0x92,0x0b,0x3f,0xb8,0x01,0x05,0x40,0x14, 0x35,0x36,0x92,0x17,0x40,0x0b,0x01,0x0b,0x17,0x0b,0x17,0x00,0x0a,0x91,0x01,0x03,0x18,0x91,0x00,0x12,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xfd,0xd6,0xed,0x10,0xfd,0xd6,0xed,0x01,0x2f,0xe9,0x32,0x32,0x32,0x32,0x12,0x39,0x2f,0xe9,0x12,0x39,0x39,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x31,0x30,0x33,0x11,0x21, 0x20,0x11,0x14,0x02,0x06,0x04,0x23,0x03,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x33,0x32,0x3e,0x02,0x35,0x10,0x21,0x03,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0xbc,0x01,0x8c,0x02,0xf6,0x72,0xce,0xfe, 0xe4,0xaa,0xd4,0x8c,0x7d,0xc6,0x89,0x48,0x48,0x89,0xc5,0x7c,0x8e,0xd6,0x8b,0xdd,0x9a,0x52,0xfd,0xb6,0x54,0x61,0x8b,0x5a,0x2a,0xb1,0xbf,0x8c,0x3c,0x9f,0xa8,0x30,0x56,0x77,0x48,0x3e,0x3c,0x5b,0x57,0x56,0x5c,0x3c,0x05,0x9a,0xfd,0x45,0xab,0xfe,0xf0,0xbf,0x65,0x05,0x02,0x53,0x35,0x71,0xb2,0x7c,0x73,0xb5,0x7e,0x42,0x5b,0x4c, 0x93,0xd8,0x8c,0x02,0x27,0xfc,0x6e,0x3a,0x64,0x83,0x4a,0xa8,0xaf,0x4b,0x7c,0x90,0x50,0x6e,0x44,0x1e,0x4b,0xba,0x52,0x5f,0x55,0x48,0xfe,0xb2,0x00,0x07,0x00,0x5e,0x00,0x00,0x08,0xba,0x05,0x9a,0x00,0x0f,0x00,0x26,0x00,0x3d,0x00,0x53,0x00,0x69,0x00,0x72,0x00,0x7b,0x00,0x95,0x40,0x2c,0x4e,0x7e,0x2c,0x78,0x7f,0x45,0x72,0x69, 0x5e,0x19,0x26,0x7e,0x3c,0x73,0x49,0x3e,0x32,0x3c,0x62,0x7f,0x6d,0x1f,0x7e,0x59,0x2c,0x45,0x3c,0x6d,0x59,0x59,0x6d,0x3c,0x45,0x2c,0x05,0x05,0x0a,0x7d,0x15,0x36,0x7d,0x05,0x71,0x74,0xb8,0x01,0x05,0x40,0x13,0x5e,0x49,0x5d,0x4a,0x92,0x19,0x20,0x32,0x30,0x32,0x02,0x32,0x18,0x33,0x91,0x07,0x03,0x72,0x73,0xb8,0x01,0x05,0x40, 0x0f,0x68,0x3f,0x69,0x3e,0x92,0x25,0x2f,0x3d,0x01,0x3d,0x26,0x3c,0x91,0x00,0x12,0x00,0x3f,0xfd,0x32,0xd6,0x5d,0x32,0xfd,0x32,0xd6,0x32,0xed,0x32,0x3f,0xfd,0x32,0xd6,0x5d,0x32,0xfd,0x32,0xd6,0x32,0xed,0x32,0x01,0x2f,0xe9,0x2f,0xe9,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x2f,0x2f,0x10,0xe9,0x10,0xe9,0x11,0x33,0x33,0x33,0x33,0x10, 0xe9,0x32,0x32,0x32,0x32,0x10,0xe9,0x10,0xe9,0x31,0x30,0x21,0x22,0x24,0x26,0x02,0x35,0x10,0x21,0x21,0x20,0x11,0x14,0x02,0x06,0x04,0x23,0x37,0x32,0x3e,0x02,0x35,0x10,0x21,0x23,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x25,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x23,0x20,0x11,0x14,0x1e,0x02, 0x33,0x33,0x3d,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x33,0x33,0x35,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x21,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x15,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x03,0x64,0xaa,0xfe, 0xe4,0xce,0x72,0x02,0xf6,0x02,0x70,0x02,0xf6,0x72,0xce,0xfe,0xe4,0xaa,0x02,0x8b,0xdd,0x9a,0x52,0xfd,0xb6,0xe0,0x8c,0x7d,0xc6,0x89,0x48,0x48,0x89,0xc5,0x7c,0x8e,0xfe,0xca,0x7d,0xc4,0x89,0x48,0x48,0x89,0xc6,0x7d,0x8c,0xe0,0xfd,0xb6,0x52,0x9a,0xdd,0x8b,0xd6,0x3e,0x48,0x77,0x56,0x30,0xa8,0x9f,0x3c,0x8c,0xbf,0xb1,0x2a,0x5a, 0x8b,0x61,0x01,0xc0,0x61,0x8b,0x5a,0x2a,0xb1,0xbf,0x8c,0x3c,0x9f,0xa8,0x30,0x56,0x77,0x48,0x3e,0x3c,0x5b,0x57,0x56,0x5c,0x3c,0xa8,0x3c,0x5c,0x56,0x56,0x5c,0x65,0xbf,0x01,0x10,0xab,0x02,0xbb,0xfd,0x45,0xab,0xfe,0xf0,0xbf,0x65,0x98,0x4c,0x93,0xd8,0x8c,0x02,0x27,0x53,0x35,0x71,0xb2,0x7c,0x73,0xb5,0x7e,0x42,0x5b,0x5b,0x42, 0x7e,0xb5,0x73,0x7c,0xb2,0x71,0x35,0x53,0xfd,0xd9,0x8c,0xd8,0x93,0x4c,0x5b,0x7d,0x4b,0x1e,0x44,0x6e,0x50,0x90,0x7c,0x4b,0xaf,0xa8,0x4a,0x83,0x64,0x3a,0x3a,0x64,0x83,0x4a,0xa8,0xaf,0x4b,0x7c,0x90,0x50,0x6e,0x44,0x1e,0x4b,0xba,0x52,0x5f,0x55,0x48,0xfe,0xb2,0x01,0x4e,0x48,0x55,0x5f,0x52,0x00,0xff,0xff,0x00,0x48,0xff,0xec, 0x06,0xd9,0x05,0xae,0x00,0x27,0x00,0xbc,0x03,0x03,0x00,0x00,0x00,0x27,0x00,0xf2,0x04,0x4b,0xfd,0xb9,0x01,0x06,0x08,0x8d,0x00,0x00,0x00,0x07,0xb2,0x01,0x23,0x2d,0x00,0x3f,0x35,0x00,0x00,0x01,0x00,0x00,0x01,0x46,0x04,0x27,0x01,0xb6,0x00,0x03,0x00,0x0e,0xb4,0x01,0x00,0x01,0x52,0x02,0x00,0x2f,0xed,0x01,0x2f,0x2f,0x31,0x30, 0x01,0x21,0x35,0x21,0x04,0x27,0xfb,0xd9,0x04,0x27,0x01,0x46,0x70,0x00,0x00,0x02,0x00,0xab,0xfe,0x0a,0x07,0x59,0x03,0x0f,0x00,0x2e,0x00,0x35,0x00,0x00,0x01,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03, 0x33,0x32,0x3e,0x02,0x35,0x11,0x01,0x03,0x33,0x17,0x37,0x33,0x03,0x06,0x9f,0x0c,0x27,0x49,0x3e,0x16,0x61,0x70,0x20,0x04,0x2c,0x80,0x9d,0xb4,0x60,0x88,0xe1,0xb5,0x88,0x30,0x40,0x30,0x12,0x0b,0x9a,0x09,0x11,0x1f,0x2f,0x1d,0x5c,0x92,0xd1,0x93,0x80,0xc0,0x7f,0x3f,0xfd,0x6c,0xec,0x7d,0xab,0xa8,0x79,0xe6,0x03,0x0f,0xfe,0x89, 0x43,0x60,0x3e,0x1e,0xa7,0x3a,0x40,0x2f,0x35,0x19,0x05,0x04,0x15,0x2c,0x29,0x37,0x98,0x58,0x3d,0x70,0x33,0x2b,0x65,0x36,0x3c,0x63,0x23,0x15,0x1b,0x0f,0x05,0x0a,0x29,0x53,0x48,0x01,0xae,0xfa,0xfb,0x01,0x60,0xff,0xff,0xfe,0xa0,0x00,0x00,0x02,0xff,0xba,0xfe,0x0a,0x02,0xac,0x03,0x0f,0x00,0x1f,0x00,0x26,0x00,0x00,0x01,0x14, 0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x03,0x03,0x33,0x17,0x37,0x33,0x03,0x01,0xf2,0x0c,0x27,0x4a,0x3d,0x16,0x64,0x78,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0xa9,0xec,0x7d,0xab, 0xa8,0x79,0xe6,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0xbc,0xfa,0xfb,0x01,0x60,0xff,0xff,0xfe,0xa0,0x00,0x02,0x00,0xab,0xfe,0x0a,0x06,0x9f,0x03,0x0f,0x00,0x25,0x00,0x2c,0x00,0x00,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35, 0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x01,0x03,0x33,0x17,0x37,0x33,0x03,0x01,0x62,0x09,0x11,0x1e,0x30,0x1d,0x5c,0x91,0xd2,0x93,0x80,0xc0,0x7f,0x3f,0x9c,0x33,0x5d,0x81,0x9a,0xaf,0x5d,0x86,0xde,0xb3,0x87,0x30,0x3f,0x30,0x12,0x0b,0x02,0xa7,0xec,0x7d,0xab,0xa8,0x79,0xe6,0x02, 0x5f,0x2b,0x65,0x36,0x3c,0x63,0x23,0x15,0x1b,0x0f,0x05,0x0a,0x29,0x53,0x48,0x01,0xae,0xfe,0x4b,0x5a,0x7c,0x52,0x2d,0x16,0x05,0x03,0x15,0x2d,0x29,0x37,0x98,0x58,0x3d,0x70,0x33,0xfb,0xab,0x01,0x60,0xff,0xff,0xfe,0xa0,0x00,0x00,0x02,0xff,0xba,0xfe,0x0a,0x02,0xa6,0x03,0x0f,0x00,0x16,0x00,0x1d,0x00,0x00,0x37,0x32,0x3e,0x02, 0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x01,0x03,0x33,0x17,0x37,0x33,0x03,0x99,0x2e,0x47,0x30,0x18,0x9c,0x1c,0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x01,0x49,0xec,0x7d,0xab,0xa8,0x79,0xe6,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x3d,0x4b,0x6e,0x4c,0x31,0x1a,0x0a,0x34,0x20, 0x20,0x33,0xfd,0x71,0x01,0x60,0xff,0xff,0xfe,0xa0,0x00,0x04,0x00,0x7e,0xfd,0xff,0x04,0x41,0x04,0xb2,0x00,0x31,0x00,0x35,0x00,0x39,0x00,0x3d,0x00,0x00,0x01,0x06,0x04,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36, 0x36,0x33,0x32,0x1e,0x04,0x17,0x01,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x0c,0xd8,0xfe,0xde,0xaf,0x49,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31,0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe, 0xf9,0xb9,0xb9,0xfe,0xe9,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x02,0x01,0x39,0x7e,0x8a,0x98,0x52,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19,0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfd,0x0e,0xb5,0x03,0x7e,0xb5,0xb5,0xb5,0x00,0x04, 0x00,0x7e,0xfd,0xff,0x04,0xad,0x04,0xb2,0x00,0x40,0x00,0x44,0x00,0x48,0x00,0x4c,0x00,0x00,0x01,0x06,0x06,0x07,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33, 0x32,0x1e,0x04,0x17,0x01,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x0c,0x22,0x40,0x1e,0x05,0x26,0x46,0x69,0x47,0x18,0x63,0x8f,0x5f,0x31,0x05,0x8d,0xc0,0x75,0x32,0x2e,0x64,0x9d,0x70,0x61,0xc3,0x64,0x6d,0xbd,0x63,0x98,0xd7,0x88,0x3f,0x19,0x3d,0x64,0x97,0xcd,0x87,0x32,0x4d,0x51,0x63,0x49,0x4b,0x80,0x31, 0x37,0x85,0x4e,0x48,0x6d,0x5d,0x53,0x5d,0x6d,0x48,0xfe,0xd4,0xb9,0xb9,0xf2,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x02,0x01,0x09,0x12,0x09,0x60,0x7e,0x49,0x1d,0xa7,0x3f,0x75,0xa6,0x67,0x33,0x6e,0x77,0x80,0x45,0x42,0x74,0x56,0x31,0x26,0x23,0x9a,0x26,0x23,0x48,0x7b,0xa3,0x5c,0x38,0x75,0x76,0x74,0x6d,0x63,0x2a,0x08,0x10,0x20,0x19, 0x0f,0x15,0x0f,0x9d,0x12,0x17,0x16,0x21,0x27,0x22,0x17,0x01,0xfc,0xe6,0xb5,0x03,0xa6,0xb5,0xb5,0xb5,0x00,0x04,0xff,0xba,0xfe,0xa6,0x04,0x7c,0x04,0xb2,0x00,0x28,0x00,0x2c,0x00,0x30,0x00,0x34,0x00,0x00,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32, 0x1e,0x04,0x17,0x07,0x0e,0x05,0x23,0x01,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x23,0x23,0x23,0x23,0x3b,0x7b,0xe0,0xcf,0xbf,0x5a,0x39,0x60,0x68,0x7c,0x57,0x4e,0x7e,0x33,0x37,0x84,0x4e,0x50,0x7c,0x6a,0x61,0x69,0x7a,0x4e,0x20,0x2b,0x73,0x92,0xb1,0xd0,0xf1,0x88,0x02,0x81,0xb9,0xb9,0xc3,0xb9,0xb9,0x01,0x42, 0xb9,0xb9,0x0e,0x34,0x20,0x20,0x33,0x37,0x59,0x70,0x39,0x05,0x1b,0x35,0x2b,0x1b,0x14,0x10,0x9d,0x12,0x17,0x1d,0x2b,0x32,0x2c,0x1e,0x01,0xc8,0x0a,0x42,0x59,0x62,0x53,0x36,0xfe,0xb4,0xb5,0x04,0xa2,0xb5,0xb5,0xb5,0x00,0x04,0xff,0xba,0xfe,0xa6,0x04,0xad,0x04,0xb2,0x00,0x35,0x00,0x39,0x00,0x3d,0x00,0x41,0x00,0x00,0x15,0x22, 0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x06,0x07,0x1e,0x03,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x01,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x23,0x23,0x23,0x23,0x3b,0x7b,0xe0,0xcf,0xbf,0x5a,0x39, 0x60,0x68,0x7c,0x57,0x4e,0x7e,0x33,0x37,0x84,0x4e,0x50,0x7c,0x6a,0x61,0x69,0x7a,0x4e,0x20,0x20,0x50,0x31,0x01,0x14,0x35,0x5e,0x4a,0x14,0x62,0x7d,0x4a,0x1e,0x02,0x48,0xab,0xc8,0xe3,0x80,0x02,0x81,0xb9,0xb9,0xc3,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x0e,0x34,0x20,0x20,0x33,0x37,0x59,0x70,0x39,0x05,0x1b,0x35,0x2b,0x1b,0x14,0x10, 0x9d,0x12,0x17,0x1d,0x2b,0x32,0x2c,0x1e,0x01,0xc8,0x08,0x29,0x1d,0x2b,0x3b,0x25,0x10,0xa7,0x29,0x46,0x5d,0x35,0x2b,0x5b,0x4b,0x30,0xfe,0xb4,0xb5,0x04,0xa2,0xb5,0xb5,0xb5,0x00,0x04,0x00,0x19,0xff,0xea,0x05,0xf5,0x05,0xec,0x00,0x20,0x00,0x34,0x00,0x38,0x00,0x3c,0x00,0x00,0x01,0x33,0x11,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x04,0x23,0x22,0x24,0x26,0x26,0x27,0x27,0x16,0x16,0x17,0x36,0x36,0x37,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x55,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x5a,0x79,0xae,0x70,0x36,0x2d,0x52,0x71,0x88,0x9a,0x52,0xb7,0xfe,0xf5,0xc6,0x92, 0x3e,0x20,0x2d,0x91,0x58,0x08,0x13,0x0b,0x02,0x52,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5c,0xe9,0x97,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x05,0xec,0xfc,0x1d,0x01,0x43,0x7a,0x5d,0x36,0x4f,0x88,0xb5,0x66,0x5d,0x80,0x55,0x2f,0x16,0x05,0x03,0x06,0x09,0x06,0xa7,0x06,0x07,0x01,0x16,0x2e,0x1a, 0x66,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0x03,0x6a,0xb5,0xb5,0xb5,0x00,0x04,0xff,0xba,0xff,0xed,0x05,0xf5,0x05,0xec,0x00,0x24,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x00,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x36, 0x36,0x37,0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x28,0x79,0xae,0x70,0x36,0x2d,0x51,0x71,0x88,0x9a,0x52,0x72,0xc7,0xc6,0xd2,0x7c,0x45,0x23,0x23,0x23,0x23,0x01,0x2e,0x08,0x14,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4, 0x27,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x83,0x75,0x63,0x52,0x3e,0x15,0x5b,0xeb,0x96,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x03,0x58,0x4f,0x88,0xb5,0x66,0x5d,0x80,0x54,0x2e,0x16,0x04,0x02,0x01,0x02,0x34,0x20,0x20,0x33,0x17,0x2f,0x1a,0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82, 0x52,0x25,0x2c,0x4e,0x68,0x77,0x81,0x3f,0x02,0x01,0x03,0x6a,0xb5,0xb5,0xb5,0x00,0x00,0x04,0xff,0xba,0xff,0xed,0x06,0xae,0x05,0xec,0x00,0x2d,0x00,0x41,0x00,0x45,0x00,0x49,0x00,0x00,0x01,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33, 0x21,0x36,0x36,0x37,0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x28,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26,0x6f,0x89,0x9d,0x54,0x72,0xc7,0xc6,0xd2,0x7c,0x45,0x23,0x23,0x23, 0x23,0x01,0x2e,0x08,0x14,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x27,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5b,0xeb,0x96,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x03,0x58,0x4e,0x84,0xae,0x61,0x3a,0x54,0x36,0x1a,0xa7,0x3c,0x43,0x30,0x35,0x1a,0x05,0x02,0x01,0x02,0x34,0x20,0x20,0x33,0x17,0x2f,0x1a, 0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0x03,0x6a,0xb5,0xb5,0xb5,0x00,0x04,0x00,0x19,0xff,0xea,0x06,0xae,0x05,0xec,0x00,0x29,0x00,0x3d,0x00,0x41,0x00,0x45,0x00,0x00,0x01,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26, 0x27,0x23,0x0e,0x03,0x23,0x22,0x24,0x26,0x26,0x27,0x27,0x16,0x16,0x17,0x36,0x36,0x37,0x11,0x33,0x11,0x17,0x3e,0x03,0x03,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x04,0x07,0x16,0x16,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x28,0x78,0xac,0x70,0x37,0x02,0x01,0x11,0x29,0x47,0x37,0x16,0x5e,0x74,0x1f,0x06,0x26, 0x70,0x89,0x9d,0x54,0xb7,0xfe,0xf5,0xc6,0x92,0x3e,0x20,0x2d,0x91,0x58,0x08,0x13,0x0b,0x9e,0x03,0x2e,0x77,0x8f,0xa4,0x27,0x6b,0xa2,0x6d,0x37,0x32,0x58,0x79,0x47,0x49,0x84,0x74,0x63,0x52,0x3e,0x15,0x5c,0xe9,0x97,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x03,0x58,0x4e,0x84,0xae,0x61,0x3a,0x54,0x36,0x1a,0xa7,0x3a,0x45,0x31,0x36,0x1a, 0x06,0x03,0x06,0x09,0x06,0xa7,0x06,0x07,0x01,0x16,0x2e,0x1a,0x04,0xf3,0xfc,0x1d,0x01,0x43,0x7a,0x5c,0x37,0xfd,0x3b,0x0a,0x27,0x4f,0x45,0x5e,0x82,0x52,0x25,0x2d,0x4d,0x68,0x77,0x81,0x3f,0x02,0x01,0x03,0x6a,0xb5,0xb5,0xb5,0x00,0x06,0x00,0xab,0xfe,0xa6,0x07,0x4b,0x06,0x3c,0x00,0x36,0x00,0x4a,0x00,0x4e,0x00,0x52,0x00,0x56, 0x00,0x5a,0x00,0x00,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x05,0x33,0x32,0x36,0x37,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x05,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0x23,0x35, 0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x01,0x62,0x09,0x11,0x20,0x2e,0x17,0x39,0x4f,0x6d,0x96,0xc7,0x82,0x5b,0x8e,0x3b,0x02,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x3a,0x64,0x89,0x9d,0xac,0x55,0xb9,0x86,0xd6,0xaa,0x7f,0x2e,0x3f,0x30,0x12,0x0b,0x05,0xe6,0x0f, 0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2c,0x1a,0x18,0x42,0x73,0x5a,0x21,0x1d,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0xfe,0x0f,0xb9,0xb9,0x02,0x5f,0x2b,0x65,0x36,0x3c,0x66,0x20,0x10,0x17,0x0f,0x08,0x05,0x01,0x02,0x03,0x06,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x57,0x21,0x4a,0x53,0x5a,0x30,0x60, 0x84,0x57,0x30,0x17,0x05,0x05,0x15,0x2d,0x27,0x36,0x99,0x58,0x3d,0x70,0x33,0xf2,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3e,0x44,0x49,0x2a,0x18,0x4d,0x03,0x3e,0xb5,0xb5,0xb5,0x63,0xb5,0xf8,0x6a,0xb5,0x00,0x00,0x06,0xff,0xba,0xfe,0xa6,0x03,0x49,0x06,0x3c,0x00,0x24,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x44, 0x00,0x48,0x00,0x00,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x13,0x23,0x35,0x33, 0x01,0xa5,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x14,0x26,0x1d,0x12,0x39,0x61,0x81,0x91,0x97,0x47,0xbf,0x23,0x23,0x23,0x23,0xc8,0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x37,0x2c,0x1b,0x19,0x41,0x73,0x5a,0x21,0x1d,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x39,0xb9,0xb9, 0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x58,0x21,0x4a,0x52,0x5a,0x30,0x60,0x83,0x55,0x2e,0x15,0x04,0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3f,0x42,0x4a,0x2a,0x18,0x4d,0x03,0x3e,0xb5,0xb5,0xb5,0x63,0xb5,0xf8,0x6a,0xb5,0x00,0x00,0x06,0xff,0xba,0xfe,0xa6, 0x04,0x02,0x06,0x3c,0x00,0x2f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x53,0x00,0x00,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22, 0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x13,0x23,0x35,0x33,0x01,0xa5,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x38,0x72,0x43,0x16,0x2c,0x60,0x5f,0x5c,0x27,0x32,0x70,0x75,0x74,0x34,0xbf,0x23,0x23,0x23,0x23,0xc8, 0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19,0x43,0x74,0x5b,0x21,0x19,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x39,0xb9,0xb9,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x53,0x56,0x21,0x4a,0x53,0x5a,0x30,0x42,0x64,0x26,0x09,0x03,0xa7,0x07,0x0e,0x16,0x0f,0x16,0x17, 0x0b,0x02,0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3e,0x44,0x4a,0x2b,0x18,0x4f,0x03,0x3e,0xb5,0xb5,0xb5,0x63,0xb5,0xf8,0x6a,0xb5,0x00,0x06,0x00,0xab,0xfe,0xa6,0x08,0x04,0x06,0x3c,0x00,0x41,0x00,0x55,0x00,0x59,0x00,0x5d,0x00,0x61,0x00,0x65,0x00,0x00,0x01,0x34,0x3e,0x02, 0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x05,0x33,0x32,0x36,0x37,0x37,0x2e,0x03,0x05,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36, 0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x04,0xb0,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x38,0x72,0x43,0x16,0x2c,0x60,0x5f,0x5b,0x27,0x33,0x77,0x82,0x8a,0x45,0xb9,0x86,0xd6,0xaa,0x7f,0x2e,0x3f,0x30,0x12,0x0b,0x9a,0x09,0x11,0x20,0x2e,0x17,0x39,0x4f,0x6d, 0x96,0xc7,0x82,0x5b,0x8e,0x3b,0x02,0x4a,0x60,0x38,0x15,0x01,0xfe,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19,0x41,0x73,0x5a,0x23,0x1b,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0xfe,0x0f,0xb9,0xb9,0x01,0xd1,0x40,0x8d,0x77,0x4d,0x53,0x56,0x21,0x4a,0x53,0x5a,0x30,0x42,0x63,0x27,0x09,0x03,0xa7,0x07, 0x0e,0x16,0x0f,0x18,0x1a,0x0d,0x03,0x05,0x15,0x2d,0x27,0x36,0x99,0x58,0x3d,0x70,0x33,0x2b,0x65,0x36,0x3c,0x66,0x20,0x10,0x17,0x0f,0x08,0x05,0x01,0x02,0x03,0x06,0x1e,0x44,0x4d,0x55,0x35,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x1f,0x3e,0x43,0x4a,0x2b,0x18,0x4d,0x03,0x3e,0xb5,0xb5,0xb5,0x63,0xb5,0xf8,0x6a,0xb5, 0x00,0x05,0x00,0x9b,0xfc,0xb6,0x05,0x4b,0x04,0x79,0x00,0x30,0x00,0x44,0x00,0x48,0x00,0x4c,0x00,0x50,0x00,0x00,0x25,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x35,0x2e,0x05, 0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x04,0xad,0x50,0x5c,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x1b,0x28,0x1b,0x0e,0x4a,0x98,0xed,0xa3,0xa1,0xdb,0x87,0x3b,0x0f,0x0e,0x97,0x0b,0x0c,0x2b,0x64,0xa5,0x7a,0x67,0x93,0x64,0x3b,0x21, 0x0b,0x01,0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0xf8,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xfe,0x6a,0xb9,0xb9,0x17,0x25,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x2a,0x68,0x75,0x7f,0x40,0x95,0xdc,0x91,0x47,0x41,0x7c,0xb7,0x77,0x3f,0x8c,0x4e,0x4b,0x7d,0x36,0x5f,0x84,0x54,0x26, 0x1d,0x32,0x46,0x51,0x5b,0xd0,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0x03,0x1f,0xb5,0xb5,0xb5,0xf8,0x3d,0xb5,0x00,0x00,0x05,0xff,0xba,0xfe,0xa6,0x03,0x49,0x05,0x24,0x00,0x24,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x44,0x00,0x00,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e, 0x03,0x15,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x01,0xa5,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x14,0x26,0x1d,0x12,0x39,0x61,0x81, 0x91,0x97,0x47,0xbf,0x23,0x23,0x23,0x23,0xc8,0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x37,0x2c,0x1b,0x19,0x41,0x73,0x5a,0x21,0x1d,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x68,0xb9,0xb9,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x58,0x21,0x4a,0x52,0x5a,0x30,0x60,0x83,0x55,0x2e,0x15,0x04, 0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3f,0x42,0x4a,0x2a,0x18,0x4d,0x03,0x3e,0xb5,0xb5,0xb5,0xf9,0x82,0xb5,0x00,0x05,0xff,0xba,0xfe,0xa6,0x04,0x02,0x05,0x24,0x00,0x2f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x00,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16, 0x17,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x01,0xa5,0x4a,0x60,0x38,0x15,0x30, 0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x38,0x72,0x43,0x16,0x2c,0x60,0x5f,0x5c,0x27,0x32,0x70,0x75,0x74,0x34,0xbf,0x23,0x23,0x23,0x23,0xc8,0x30,0x75,0x36,0x01,0x09,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19,0x43,0x74,0x5b,0x21,0x19,0xfe,0xe5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x68,0xb9,0xb9, 0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x53,0x56,0x21,0x4a,0x53,0x5a,0x30,0x42,0x64,0x26,0x09,0x03,0xa7,0x07,0x0e,0x16,0x0f,0x16,0x17,0x0b,0x02,0x34,0x20,0x20,0x33,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3e,0x44,0x4a,0x2b,0x18,0x4f,0x03,0x3e,0xb5,0xb5,0xb5,0xf9,0x82,0xb5,0x00, 0x00,0x05,0x00,0x9b,0xfc,0xb6,0x06,0x03,0x04,0x79,0x00,0x30,0x00,0x41,0x00,0x45,0x00,0x49,0x00,0x4d,0x00,0x00,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x33,0x15,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x37,0x03,0x2e, 0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x26,0x26,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x04,0x36,0x5c,0x91,0x66,0x36,0x30,0x55,0x73,0x44,0x48,0x78,0x36,0x2d,0x34,0x07,0xbc,0xbb,0x0b,0x54,0x99,0xe0,0x97,0xa1,0xdb,0x87,0x3b,0x0f,0x0e,0x97,0x0b,0x0c,0x2b,0x64,0xa5,0x7a,0x60,0x8d,0x63,0x3e, 0x24,0x10,0x03,0x1d,0x0d,0x25,0x2c,0x34,0x1c,0x1d,0x37,0x2c,0x1a,0x7c,0x86,0x65,0x04,0x0e,0xfe,0xf5,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xfe,0x6a,0xb9,0xb9,0x0e,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x48,0xc0,0x6d,0xa7,0x7f,0xbc,0x7b,0x3d,0x41,0x7c,0xb7,0x77,0x3f,0x8c,0x4e,0x4b,0x7d,0x36,0x5f,0x84,0x54,0x26,0x19, 0x2d,0x3e,0x49,0x52,0x2b,0x01,0x42,0x26,0x4d,0x3d,0x26,0x26,0x3c,0x4c,0x26,0x4b,0x52,0x27,0x4e,0x02,0xb6,0xb5,0xb5,0xb5,0xf8,0x3d,0xb5,0x00,0x00,0x01,0x00,0x9b,0xfe,0xac,0x05,0x51,0x05,0xec,0x00,0x2d,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15, 0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x33,0x05,0x51,0xb3,0xb3,0xb3,0x38,0x81,0xd4,0x9d,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x98,0x0b,0x0b,0x23,0x4f,0x7d,0x59,0x67,0x93,0x5d,0x2b,0xfe,0xdf,0x01,0x21,0xfe,0xdf,0x01,0x21,0x9c,0xb3,0x04,0x5c,0x83,0x6d,0xfd,0xa8,0x8f,0xe4, 0x9f,0x56,0x45,0x7f,0xb7,0x72,0x3f,0x83,0x4b,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x02,0x44,0x6d,0x83,0x6d,0x01,0x23,0xfe,0xdd,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x02,0xa5,0x05,0xec,0x00,0x26,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32, 0x3e,0x02,0x35,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x33,0x02,0xa5,0xb3,0xb3,0xb3,0x1c,0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x99,0x2e,0x47,0x30,0x18,0xfe,0xdf,0x01,0x21,0xfe,0xdf,0x01,0x21,0x9c,0xb3,0x04,0x5c,0x83,0x6d,0xfd,0xe0,0x4b,0x6e,0x4c,0x31,0x1a,0x0a,0x34,0x20,0x20,0x33,0x0f,0x2a, 0x48,0x39,0x02,0x19,0x6d,0x83,0x6d,0x01,0x23,0xfe,0xdd,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x02,0xac,0x05,0xec,0x00,0x2f,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x21,0x35,0x21,0x35,0x21, 0x35,0x21,0x11,0x33,0x11,0x33,0x02,0xa5,0xb3,0xb3,0xb3,0x0c,0x27,0x4a,0x3d,0x16,0x61,0x74,0x1d,0x04,0x1b,0x43,0x48,0x49,0x22,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0xfe,0xdf,0x01,0x21,0xfe,0xdf,0x01,0x21,0x9c,0xb3,0x04,0x5c,0x83,0x6d,0xfe,0x2c,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20, 0x20,0x33,0x12,0x2c,0x47,0x35,0x02,0x19,0x6d,0x83,0x6d,0x01,0x23,0xfe,0xdd,0x00,0x00,0x01,0x00,0x9b,0xfe,0xac,0x05,0x58,0x05,0xec,0x00,0x38,0x00,0x00,0x01,0x23,0x15,0x33,0x15,0x23,0x11,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02, 0x33,0x32,0x3e,0x02,0x35,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x33,0x05,0x51,0xb3,0xb3,0xb3,0x0c,0x27,0x4a,0x3d,0x13,0x49,0x59,0x1c,0x04,0x11,0x4c,0x7f,0xb7,0x7c,0x87,0xb6,0x6d,0x2f,0x0d,0x0e,0x98,0x0b,0x0b,0x23,0x4f,0x7d,0x59,0x67,0x93,0x5d,0x2b,0xfe,0xdf,0x01,0x21,0xfe,0xdf,0x01,0x21,0x9c,0xb3,0x04, 0x5c,0x83,0x6d,0xfe,0x30,0x43,0x61,0x40,0x1f,0xa7,0x28,0x26,0x5f,0x95,0x69,0x37,0x45,0x7f,0xb7,0x72,0x3f,0x83,0x4b,0x48,0x7a,0x37,0x5f,0x84,0x51,0x24,0x31,0x6e,0xb3,0x81,0x02,0x44,0x6d,0x83,0x6d,0x01,0x23,0xfe,0xdd,0x00,0x00,0x05,0x00,0x39,0xfd,0xff,0x03,0xf4,0x05,0x91,0x00,0x26,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x44, 0x00,0x00,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x05,0x13,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x1e,0x03,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x02,0xac,0x4c,0x79,0x55,0x2e, 0x23,0x47,0x69,0x45,0x31,0x66,0x61,0x59,0x24,0x4e,0x43,0x09,0x11,0x17,0x0e,0xa6,0x19,0x1d,0x24,0x42,0x5d,0x3a,0x17,0x3d,0x45,0x49,0x44,0x3b,0x2e,0x21,0x35,0x27,0x15,0x1e,0x33,0x45,0x27,0x4b,0x6d,0x29,0x21,0x44,0x44,0x43,0x54,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x02,0xb9,0x53,0x7d,0x91,0x3e,0x3b,0x6c,0x52,0x30, 0x13,0x17,0x13,0x63,0x5b,0x26,0x5d,0x63,0x61,0x2a,0x67,0xbd,0x45,0x48,0x79,0x5b,0x39,0x09,0x71,0xa2,0x6f,0x43,0x23,0x0b,0xfd,0xdf,0x0c,0x1c,0x30,0x23,0x25,0x59,0x4e,0x34,0xa4,0xad,0x05,0x0f,0x0d,0x09,0x03,0x2c,0xb5,0xb5,0xb5,0x63,0xb5,0x00,0x00,0x05,0xff,0xba,0xff,0xf2,0x03,0xf4,0x05,0x91,0x00,0x23,0x00,0x33,0x00,0x37, 0x00,0x3b,0x00,0x3f,0x00,0x00,0x15,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x01,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x23,0x23, 0x23,0x23,0x1a,0x3f,0x57,0x3b,0x22,0x0b,0x14,0x37,0x54,0x79,0x56,0x61,0x8b,0x58,0x2a,0x2b,0x56,0x81,0x57,0x36,0x63,0x58,0x4b,0x1f,0x35,0x9a,0x5e,0x01,0x6e,0x2a,0x8f,0x55,0x5e,0x6a,0x1a,0x35,0x52,0x38,0x32,0x4e,0x3f,0x2d,0xb0,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x0e,0x34,0x20,0x20,0x33,0x2e,0x41,0x48,0x1a,0x2f, 0x72,0x62,0x42,0x4d,0x74,0x86,0x3a,0x3b,0x72,0x59,0x36,0x17,0x28,0x35,0x1f,0x50,0x43,0x01,0x13,0x34,0x37,0x44,0x46,0x21,0x50,0x45,0x2f,0x28,0x47,0x5f,0x02,0x89,0xb5,0xb5,0xb5,0x63,0xb5,0x00,0x00,0x05,0xff,0xba,0xff,0xf2,0x04,0xad,0x05,0x91,0x00,0x30,0x00,0x40,0x00,0x44,0x00,0x48,0x00,0x4c,0x00,0x00,0x05,0x23,0x22,0x26, 0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x37,0x3e,0x05,0x33,0x32,0x1e,0x04,0x17,0x1e,0x03,0x33,0x25,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x04,0xad,0x16,0x5b, 0x6f,0x1e,0x05,0x2d,0x87,0x61,0x34,0x61,0x57,0x4b,0x1e,0x35,0x99,0x5f,0x13,0x23,0x23,0x23,0x23,0x1a,0x3f,0x57,0x3a,0x23,0x0b,0x0d,0x21,0x2b,0x38,0x48,0x5c,0x39,0x4f,0x72,0x50,0x33,0x1c,0x0c,0x02,0x04,0x0d,0x25,0x46,0x3d,0xfc,0xd4,0x2b,0x8e,0x56,0x5e,0x69,0x1a,0x35,0x52,0x37,0x30,0x4f,0x3e,0x2f,0xaf,0xb9,0xb9,0x01,0x42, 0xb9,0xb9,0xa1,0xb9,0xb9,0x0e,0x40,0x41,0x39,0x48,0x18,0x28,0x35,0x1e,0x50,0x43,0x34,0x20,0x20,0x33,0x2e,0x41,0x48,0x1b,0x1f,0x49,0x48,0x42,0x34,0x1e,0x2e,0x48,0x56,0x51,0x40,0x0e,0x21,0x3e,0x30,0x1d,0x6d,0x35,0x36,0x44,0x45,0x21,0x51,0x45,0x2f,0x26,0x45,0x5f,0x02,0x85,0xb5,0xb5,0xb5,0x63,0xb5,0x00,0x00,0x05,0x00,0x39, 0xfd,0xff,0x04,0xad,0x05,0x91,0x00,0x2f,0x00,0x41,0x00,0x45,0x00,0x49,0x00,0x4d,0x00,0x00,0x25,0x15,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x3e,0x05,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x05,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02, 0x23,0x22,0x06,0x07,0x1e,0x03,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x27,0x23,0x35,0x33,0x04,0xad,0x16,0x51,0x68,0x21,0x04,0x26,0x6c,0x4f,0x31,0x65,0x60,0x57,0x24,0x4e,0x43,0x09,0x11,0x17,0x0e,0xa6,0x19,0x1d,0x24,0x42,0x5d,0x3a,0x17,0x3d,0x45,0x49,0x44,0x3b,0x15,0x44,0x6e,0x53,0x34,0x0b,0x06,0x0f,0x26,0x45,0xfe,0x55, 0x21,0x35,0x27,0x15,0x1e,0x33,0x45,0x27,0x4b,0x6d,0x29,0x21,0x44,0x44,0x43,0x54,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xa1,0xb9,0xb9,0x99,0xa7,0x3a,0x36,0x36,0x3b,0x13,0x17,0x13,0x63,0x5b,0x26,0x5d,0x63,0x61,0x2a,0x67,0xbd,0x45,0x48,0x79,0x5b,0x39,0x09,0x71,0xa2,0x6f,0x42,0x24,0x0b,0x41,0x67,0x80,0x3f,0x26,0x43,0x33,0x1d,0x01, 0x0c,0x1c,0x30,0x23,0x25,0x59,0x4e,0x34,0xa4,0xad,0x05,0x0e,0x0e,0x09,0x03,0x2c,0xb5,0xb5,0xb5,0x63,0xb5,0x00,0x00,0x04,0x00,0x82,0xfe,0x10,0x05,0x91,0x04,0xcc,0x00,0x35,0x00,0x4e,0x00,0x52,0x00,0x56,0x00,0x00,0x05,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e, 0x04,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x04,0x15,0x14,0x0e,0x04,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x02,0x9c,0x94,0xc5,0x77,0x32,0x23,0x1d,0x97,0x17,0x23,0x21,0x52,0x8e,0x6d, 0x6d,0xbd,0x8d,0x51,0x33,0x4b,0x59,0x4b,0x33,0x54,0x96,0xd1,0x7e,0x64,0x9c,0x6c,0x38,0x33,0x4d,0x5a,0x4d,0x33,0x27,0x4e,0x73,0x98,0xbc,0xfe,0xa1,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xc2,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xab,0x4e,0x85,0xb1,0x63,0x5b,0xba,0x5b,0x58, 0xaf,0x55,0x47,0x7b,0x5c,0x34,0x2e,0x4b,0x5e,0x30,0x26,0x33,0x2c,0x2e,0x40,0x5c,0x45,0x55,0x7f,0x5b,0x3b,0x12,0xa2,0x0d,0x23,0x31,0x41,0x2a,0x29,0x39,0x2f,0x2c,0x3a,0x4f,0x3a,0x31,0x6a,0x68,0x5e,0x47,0x2a,0x05,0x0c,0x03,0x04,0x25,0x2b,0x58,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0xf9,0x4a,0xb5,0xb5,0xb5, 0x00,0x04,0xff,0xba,0xfe,0xa6,0x02,0x48,0x05,0x3e,0x00,0x16,0x00,0x1a,0x00,0x1e,0x00,0x37,0x00,0x00,0x37,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26, 0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x99,0x2e,0x47,0x30,0x18,0x9c,0x1c,0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x01,0x06,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x63,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x3d,0x4b,0x6e,0x4c, 0x31,0x1a,0x0a,0x34,0x20,0x20,0x33,0xfe,0x0d,0xb5,0xb5,0xb5,0x05,0x78,0x03,0x04,0x25,0x2b,0x58,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0x00,0x04,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0x3e,0x00,0x1f,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x00,0x01,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23, 0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x03,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0xf2,0x0c,0x27,0x4a,0x3d,0x16,0x64,0x78,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23, 0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0x0d,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55,0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xdf,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0xbc,0x01,0xc4,0x03,0x04,0x25, 0x2b,0x58,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0xf9,0x6e,0xb5,0xb5,0xb5,0x00,0x04,0x00,0x82,0xfd,0xc0,0x06,0xae,0x04,0x68,0x00,0x44,0x00,0x5d,0x00,0x61,0x00,0x65,0x00,0x00,0x25,0x15,0x23,0x22,0x2e,0x04,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34, 0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x05,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x33,0x33,0x15,0x21,0x35,0x33,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x13,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x06,0xae,0x16,0x43,0x67, 0x4e,0x3b,0x2d,0x25,0x12,0x17,0x2b,0x18,0x1d,0x27,0x20,0x26,0x20,0x2d,0x4e,0x68,0x77,0x80,0x3e,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x21,0x5a,0xa1,0x81,0x54,0x81,0x59,0x2d,0x20,0x26,0x20,0x26,0x41,0x57,0x30,0x31,0x60,0x27,0x11,0x1e,0x21,0x2a,0x3b,0x52,0xfb,0x36,0x0d,0x1d,0x10,0x2d,0x3e,0x8e,0x46,0xfe,0xa7,0x55, 0x01,0x17,0x16,0x1c,0x33,0x47,0x2b,0x1f,0x21,0xc2,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x99,0xa7,0x21,0x35,0x45,0x47,0x44,0x1b,0x23,0x1c,0x22,0x24,0x21,0x2c,0x2f,0x3e,0x34,0x3a,0x5c,0x47,0x31,0x20,0x0e,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6f,0x3e,0x4a,0x7c,0x5c,0x33,0x16,0x27,0x35,0x20,0x1c,0x2b,0x30,0x41,0x32,0x35,0x57, 0x3e,0x22,0x2c,0x3a,0x1a,0x3d,0x3d,0x3a,0x2c,0x1a,0x03,0x64,0x03,0x04,0x25,0x2b,0x58,0x61,0x5b,0x05,0x1a,0x3a,0x1d,0x22,0x39,0x2a,0x17,0x06,0xf9,0x5e,0xb5,0xb5,0xb5,0x00,0x00,0x04,0x00,0x9a,0xfe,0x10,0x05,0x91,0x04,0x78,0x00,0x35,0x00,0x39,0x00,0x3d,0x00,0x41,0x00,0x00,0x05,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06, 0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x04,0x15,0x14,0x0e,0x04,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x02,0x9c,0x94,0xc5,0x77,0x32,0x23,0x1d,0x97,0x17,0x23,0x21,0x52,0x8e,0x6d,0x6d,0xbd,0x8d,0x51,0x33,0x4b,0x59,0x4b, 0x33,0x54,0x96,0xd1,0x7e,0x64,0x9c,0x6c,0x38,0x33,0x4d,0x5a,0x4d,0x33,0x27,0x4e,0x73,0x98,0xbc,0x9d,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xfe,0xb2,0xb9,0xb9,0xab,0x4e,0x85,0xb1,0x63,0x5b,0xba,0x5b,0x58,0xaf,0x55,0x47,0x7b,0x5c,0x34,0x2e,0x4b,0x5e,0x30,0x26,0x33,0x2c,0x2e,0x40,0x5c,0x45,0x55,0x7f,0x5b,0x3b,0x12,0xa2,0x0d,0x23, 0x31,0x41,0x2a,0x29,0x39,0x2f,0x2c,0x3a,0x4f,0x3a,0x31,0x6a,0x68,0x5e,0x47,0x2a,0xfe,0xbb,0xb5,0xb5,0xb5,0x04,0xfe,0xb5,0x00,0x04,0xff,0xba,0xfe,0xa6,0x02,0x48,0x04,0xb2,0x00,0x16,0x00,0x1a,0x00,0x1e,0x00,0x22,0x00,0x00,0x37,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x0e,0x04,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x01, 0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x99,0x2e,0x47,0x30,0x18,0x9c,0x1c,0x31,0x43,0x4f,0x57,0x2d,0x8f,0x23,0x23,0x23,0x23,0x01,0x06,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x4f,0xb9,0xb9,0x99,0x0f,0x2a,0x48,0x39,0x01,0xbc,0xfe,0x3d,0x4b,0x6e,0x4c,0x31,0x1a,0x0a,0x34,0x20,0x20,0x33,0xfe,0x0d,0xb5,0xb5,0xb5,0x04, 0xa2,0xb5,0x00,0x04,0xff,0xba,0xfe,0xa6,0x02,0xac,0x04,0xb2,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x00,0x01,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x23,0x35,0x33,0x01,0xf2, 0x0c,0x27,0x4a,0x3d,0x16,0x64,0x78,0x1e,0x04,0x1a,0x41,0x46,0x47,0x21,0x8f,0x23,0x23,0x23,0x23,0x99,0x1d,0x43,0x38,0x25,0x9c,0xec,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x4f,0xb9,0xb9,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x3f,0x3c,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0xbc,0xfb,0x97,0xb5,0xb5,0xb5,0x04, 0xa2,0xb5,0x00,0x04,0x00,0x9a,0xfd,0xc0,0x06,0xae,0x03,0xba,0x00,0x44,0x00,0x48,0x00,0x4c,0x00,0x50,0x00,0x00,0x25,0x15,0x23,0x22,0x2e,0x04,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e, 0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x05,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x06,0xae,0x16,0x43,0x67,0x4e,0x3b,0x2d,0x25,0x12,0x17,0x2b,0x18,0x1d,0x27,0x20,0x26,0x20,0x2d,0x4e,0x68,0x77,0x80,0x3e,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x21,0x5a,0xa1,0x81,0x54,0x81,0x59,0x2d, 0x20,0x26,0x20,0x26,0x41,0x57,0x30,0x31,0x60,0x27,0x11,0x1e,0x21,0x2a,0x3b,0x52,0xfb,0xf8,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xfe,0x9b,0xb9,0xb9,0x99,0xa7,0x21,0x35,0x45,0x47,0x44,0x1b,0x23,0x1c,0x22,0x24,0x21,0x2c,0x2f,0x3e,0x34,0x3a,0x5c,0x47,0x31,0x20,0x0e,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6f,0x3e,0x4a,0x7c,0x5c, 0x33,0x16,0x27,0x35,0x20,0x1c,0x2b,0x30,0x41,0x32,0x35,0x57,0x3e,0x22,0x2c,0x3a,0x1a,0x3d,0x3d,0x3a,0x2c,0x1a,0xfd,0x27,0xb5,0xb5,0xb5,0x04,0x90,0xb5,0x00,0x02,0xff,0xa6,0xfd,0xff,0x03,0x5a,0x02,0x5e,0x00,0x28,0x00,0x38,0x00,0x00,0x01,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e, 0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x03,0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x02,0x31,0x1a,0x28,0x1c,0x0f,0x0f,0x0d,0x3c,0x6c,0x30,0x8b,0x3f,0x51,0x23,0x56,0x5f,0x64,0x30,0x45,0x6f,0x4f,0x2a,0x2e,0x4e,0x67,0x39,0x4e,0x9a,0x4b,0x07,0x05,0x13,0x1f, 0x29,0x16,0xbc,0x46,0x78,0x2a,0x37,0x7c,0x47,0x26,0x31,0x1d,0x0b,0x0f,0x23,0x37,0x02,0x5e,0x41,0x8e,0x8f,0x8b,0x3e,0x3e,0x6d,0x31,0x2b,0x72,0x4a,0x57,0x61,0x44,0x36,0x4a,0x2e,0x15,0x22,0x40,0x5d,0x3b,0x3d,0x5b,0x3a,0x1d,0x1d,0x20,0x31,0x41,0x1e,0x4b,0x8e,0x88,0x83,0x3f,0xfc,0x49,0x33,0x39,0x18,0x19,0x0d,0x16,0x1d,0x10, 0x10,0x1c,0x15,0x0c,0x00,0x02,0xff,0xa6,0xfd,0xff,0x03,0x5a,0x02,0x5e,0x00,0x30,0x00,0x40,0x00,0x00,0x01,0x16,0x16,0x17,0x1e,0x03,0x33,0x15,0x23,0x22,0x26,0x27,0x14,0x06,0x07,0x16,0x16,0x17,0x07,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x2e,0x02,0x27,0x03,0x32, 0x36,0x37,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x02,0x31,0x1e,0x2b,0x0f,0x06,0x1c,0x31,0x49,0x32,0x16,0x3f,0x4a,0x1a,0x0f,0x0d,0x3c,0x6c,0x30,0x8b,0x3f,0x51,0x23,0x56,0x5f,0x64,0x30,0x45,0x6f,0x4f,0x2a,0x2e,0x4e,0x67,0x39,0x4e,0x9a,0x4b,0x07,0x05,0x13,0x1f,0x29,0x16,0xbc,0x46,0x78,0x2a,0x37,0x7c,0x47,0x26, 0x31,0x1d,0x0b,0x0f,0x23,0x37,0x02,0x5e,0x4c,0xa5,0x53,0x21,0x31,0x20,0x0f,0xa7,0x24,0x21,0x3e,0x6d,0x31,0x2b,0x72,0x4a,0x57,0x61,0x44,0x36,0x4a,0x2e,0x15,0x22,0x40,0x5d,0x3b,0x3d,0x5b,0x3a,0x1d,0x1d,0x20,0x31,0x41,0x1e,0x4b,0x8e,0x88,0x83,0x3f,0xfc,0x49,0x33,0x39,0x18,0x19,0x0d,0x16,0x1d,0x10,0x10,0x1c,0x15,0x0c,0x00, 0x00,0x03,0x00,0x00,0xfd,0xff,0x03,0x49,0x02,0xb7,0x00,0x22,0x00,0x36,0x00,0x3a,0x00,0x00,0x11,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x2e,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x01, 0x23,0x35,0x33,0x6c,0xad,0x52,0x64,0x7b,0x45,0x1a,0x02,0x53,0x59,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x36,0x36,0x34,0x72,0xb6,0x82,0x5b,0xac,0x64,0x02,0xa9,0x01,0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0xfe,0x93,0xb9,0xb9,0xfe,0xf9,0x2c,0x23,0x42,0x68,0x82,0x41, 0x25,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x55,0xed,0x84,0x74,0xd3,0xa2,0x60,0x26,0x2e,0x02,0x66,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0xfe,0x8c,0xb5,0x00,0x03,0x00,0x00,0xfd,0xff,0x04,0x02,0x02,0xb7,0x00,0x27,0x00,0x38,0x00,0x3c,0x00,0x00,0x11,0x16,0x16,0x33,0x32,0x3e, 0x02,0x37,0x36,0x36,0x37,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x33,0x15,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x01,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x26,0x26,0x01,0x23,0x35,0x33,0x6c,0xad,0x52,0x45,0x66,0x48,0x2c,0x0c,0x05,0x0b,0x04,0x75,0x5c,0x92,0x66,0x36,0x30, 0x55,0x74,0x44,0x48,0x77,0x36,0x2d,0x35,0x07,0xbc,0xbd,0x08,0x3e,0x74,0xab,0x75,0x5b,0xac,0x64,0x02,0x8d,0x0d,0x25,0x2c,0x34,0x1c,0x1d,0x37,0x2c,0x1b,0x7c,0x87,0x65,0x04,0x0e,0xfe,0x7f,0xb9,0xb9,0xfe,0xf9,0x2c,0x23,0x21,0x39,0x4c,0x2c,0x13,0x3d,0x26,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x56,0x48,0xbf,0x6d,0xa7, 0x66,0xb5,0x88,0x50,0x26,0x2e,0x02,0xe1,0x26,0x4d,0x3d,0x26,0x26,0x3c,0x4c,0x26,0x4b,0x52,0x27,0x4e,0xfe,0x23,0xb5,0x00,0x00,0x04,0x00,0x02,0xfe,0x8d,0x03,0xfe,0x03,0x62,0x00,0x3d,0x00,0x51,0x00,0x55,0x00,0x59,0x00,0x00,0x25,0x16,0x16,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23, 0x22,0x0e,0x02,0x15,0x15,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x27,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x03,0x15,0x1d,0x47,0x26,0x19,0x23,0x23,0x23, 0x23,0x22,0x17,0x3f,0x4a,0x51,0x27,0x32,0x5e,0x4d,0x35,0x07,0x10,0x29,0x49,0x39,0x21,0x83,0x03,0x01,0x41,0x67,0x7f,0x3e,0x10,0x22,0x0a,0x02,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x82,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19,0x43,0x74,0x5b,0x21,0x19,0x87,0xb9,0xb9, 0x01,0x42,0xb9,0xb9,0xa5,0x05,0x07,0x33,0x20,0x20,0x34,0x07,0x0e,0x16,0x0f,0x16,0x17,0x0b,0x02,0x25,0x4f,0x7b,0x56,0x20,0x16,0x1e,0x05,0x7d,0xb1,0x71,0x34,0x01,0x01,0x07,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x57,0x21,0x4a,0x53,0x5a,0x30,0x42,0x64,0xa2,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20, 0x3e,0x44,0x4a,0x2b,0x18,0x4f,0xfd,0x75,0xb5,0xb5,0xb5,0x00,0x00,0x04,0x00,0x02,0xfe,0x8d,0x04,0x1c,0x03,0x62,0x00,0x37,0x00,0x4b,0x00,0x4f,0x00,0x53,0x00,0x00,0x25,0x15,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x37,0x2e,0x03,0x35,0x34, 0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x06,0x07,0x16,0x16,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x04,0x1c,0x30,0x2c,0x60,0x5f,0x5c,0x27,0x32,0x5e,0x4d,0x35,0x07,0x10,0x29,0x49,0x39,0x21,0x83,0x03,0x01,0x41,0x67,0x7f,0x3e,0x0e,0x25, 0x09,0x02,0x4a,0x60,0x38,0x15,0x30,0x55,0x74,0x44,0x48,0x78,0x36,0x15,0x25,0x1d,0x11,0x1b,0x19,0x39,0x8b,0xfe,0xd3,0x0f,0x1c,0x26,0x2d,0x32,0x1a,0x1d,0x38,0x2b,0x1b,0x19,0x43,0x74,0x5b,0x21,0x19,0x87,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x99,0xa7,0x07,0x0e,0x16,0x0f,0x16,0x17,0x0b,0x02,0x25,0x4f,0x7b,0x56,0x20,0x16,0x1e,0x05, 0x7d,0xb1,0x71,0x34,0x01,0x01,0x07,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x52,0x57,0x21,0x4a,0x53,0x5a,0x30,0x42,0x64,0x26,0x09,0x03,0xd4,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3e,0x44,0x4a,0x2b,0x18,0x4f,0xfd,0x75,0xb5,0xb5,0xb5,0x00,0x00,0x01,0x00,0x00,0x06,0x40,0x02,0x35,0x07,0xaa,0x00,0x1b, 0x00,0x00,0x13,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x0c,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0x06,0x40,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b,0x20,0x23, 0x3d,0x2d,0x19,0x1e,0x20,0x13,0x0d,0x00,0x00,0x02,0x00,0x00,0x06,0x76,0x02,0x33,0x08,0x14,0x00,0x2a,0x00,0x37,0x00,0x00,0x01,0x06,0x07,0x06,0x07,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x37,0x1e,0x03,0x33,0x32,0x37,0x36,0x37,0x26,0x27,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x36,0x37,0x27,0x34,0x26, 0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x36,0x02,0x33,0x25,0x29,0x0b,0x11,0x22,0x72,0x54,0x21,0x44,0x3e,0x31,0x0d,0x44,0x07,0x1a,0x27,0x34,0x22,0x2d,0x26,0x12,0x10,0x10,0x10,0x1c,0x2c,0x1b,0x18,0x29,0x38,0x21,0x1f,0x38,0x2a,0x19,0x04,0x0f,0x0e,0x6e,0x2a,0x1b,0x1c,0x28,0x29,0x15,0x24,0x1c,0x0b,0x07,0x07,0x0c,0x09, 0x14,0x12,0x25,0x31,0x13,0x22,0x31,0x1e,0x35,0x0e,0x22,0x1e,0x14,0x0b,0x05,0x07,0x02,0x05,0x09,0x24,0x38,0x27,0x23,0x3a,0x29,0x17,0x14,0x29,0x3d,0x29,0x14,0x15,0x06,0x07,0x19,0x2a,0x21,0x24,0x1f,0x1f,0x24,0x02,0x1a,0x00,0x00,0x01,0x00,0x00,0xfe,0x89,0x02,0x35,0xff,0xf3,0x00,0x1b,0x00,0x00,0x13,0x26,0x35,0x34,0x3e,0x02, 0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x0c,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0xfe,0x89,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x13,0x0d,0x00, 0x00,0x02,0x00,0x00,0x06,0x40,0x02,0x7b,0x08,0x72,0x00,0x1b,0x00,0x37,0x00,0x00,0x13,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x27,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22, 0x06,0x15,0x14,0x17,0x52,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0x9f,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0x06,0x40,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e, 0x20,0x13,0x0d,0x9d,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x13,0x0d,0x00,0x00,0x04,0x00,0x00,0x06,0x76,0x02,0xdd,0x08,0xfa,0x00,0x28,0x00,0x51,0x00,0x5e,0x00,0x6c,0x00,0x00,0x01,0x06,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x37,0x1e,0x03,0x33,0x32,0x37,0x2e,0x03, 0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x36,0x36,0x37,0x01,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x07,0x2e,0x03,0x23,0x22,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x06,0x06,0x07,0x17,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x07,0x06,0x05,0x34,0x26,0x23,0x22, 0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x36,0x02,0xdd,0x26,0x28,0x0f,0x2e,0x40,0x53,0x34,0x21,0x44,0x3e,0x31,0x0d,0x44,0x07,0x1a,0x27,0x34,0x22,0x43,0x31,0x19,0x2f,0x24,0x16,0x18,0x29,0x38,0x21,0x1f,0x38,0x2a,0x19,0x04,0x08,0x0e,0x07,0xfd,0x35,0x25,0x29,0x0f,0x2e,0x40,0x52,0x35,0x21,0x44,0x3e,0x30,0x0e,0x44,0x08,0x19, 0x27,0x34,0x22,0x44,0x31,0x19,0x2f,0x25,0x16,0x18,0x29,0x38,0x21,0x1f,0x38,0x2a,0x19,0x04,0x08,0x0e,0x07,0x6e,0x2a,0x1b,0x1c,0x28,0x29,0x15,0x24,0x1c,0x0b,0x01,0xdd,0x2a,0x1b,0x1c,0x28,0x29,0x15,0x12,0x20,0x0e,0x0b,0x07,0x07,0x0c,0x09,0x1a,0x2d,0x21,0x14,0x13,0x22,0x31,0x1e,0x35,0x0e,0x22,0x1e,0x14,0x17,0x03,0x15,0x24, 0x34,0x23,0x23,0x3a,0x29,0x17,0x14,0x29,0x3d,0x29,0x16,0x13,0x03,0x06,0x04,0x01,0x14,0x0c,0x09,0x19,0x2e,0x21,0x14,0x13,0x22,0x31,0x1e,0x35,0x0d,0x22,0x1e,0x15,0x18,0x03,0x15,0x24,0x34,0x22,0x23,0x3a,0x29,0x17,0x14,0x29,0x3d,0x29,0x15,0x13,0x02,0x07,0x03,0x19,0x2a,0x21,0x24,0x1f,0x1f,0x24,0x03,0x1b,0xb1,0x2a,0x21,0x24, 0x1f,0x1f,0x24,0x01,0x01,0x1b,0x00,0x02,0x00,0x00,0xfd,0xc1,0x02,0x7b,0xff,0xf3,0x00,0x1b,0x00,0x37,0x00,0x00,0x13,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x27,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x15, 0x14,0x0e,0x02,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x52,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0x9f,0x0c,0x19,0x2e,0x41,0x29,0xd6,0x1f,0x33,0x09,0x59,0x0c,0x19,0x2e,0x42,0x28,0xd6,0x1f,0x33,0x09,0xfd,0xc1,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b, 0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x13,0x0d,0x9d,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x12,0x0e,0x2b,0x1b,0x20,0x23,0x3d,0x2d,0x19,0x1e,0x20,0x13,0x0d,0x00,0x00,0x01,0x00,0x64,0x06,0x76,0x01,0x1d,0x07,0x2b,0x00,0x03,0x00,0x00,0x01,0x23,0x35,0x33,0x01,0x1d,0xb9,0xb9,0x06,0x76,0xb5,0x00,0x00,0x02,0x00,0x64,0x06,0x76, 0x02,0x5f,0x07,0x2b,0x00,0x03,0x00,0x07,0x00,0x00,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x1d,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0x06,0x76,0xb5,0xb5,0xb5,0x00,0x00,0x02,0x00,0x00,0x06,0x41,0x02,0x3f,0x07,0xda,0x00,0x1c,0x00,0x2b,0x00,0x00,0x01,0x26,0x27,0x06,0x07,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16, 0x17,0x16,0x17,0x36,0x37,0x17,0x06,0x07,0x06,0x07,0x16,0x17,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x01,0xa4,0x09,0x0b,0x1a,0x1e,0x36,0x43,0x28,0x50,0x3f,0x28,0x5a,0x51,0x3b,0x6c,0x2b,0x27,0x1e,0x37,0x2a,0x1c,0x1a,0x21,0x0e,0x10,0x0b,0x07,0xb5,0x1e,0x4a,0x28,0x0f,0x20,0x1b,0x11,0x47,0x3d, 0x4c,0x3f,0x11,0x06,0x41,0x23,0x20,0x04,0x04,0x06,0x0d,0x27,0x48,0x3a,0x51,0x5d,0x3e,0x36,0x30,0x3f,0x0f,0x10,0x64,0x07,0x0b,0x04,0x05,0x23,0x26,0xcf,0x2a,0x30,0x07,0x12,0x1e,0x17,0x29,0x27,0x0a,0x20,0x00,0x01,0x00,0x64,0xfe,0xa6,0x01,0x1d,0xff,0x5b,0x00,0x03,0x00,0x00,0x01,0x23,0x35,0x33,0x01,0x1d,0xb9,0xb9,0xfe,0xa6, 0xb5,0x00,0x00,0x02,0x00,0x64,0xfe,0xa6,0x02,0x5f,0xff,0x5b,0x00,0x03,0x00,0x07,0x00,0x00,0x01,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x1d,0xb9,0xb9,0x01,0x42,0xb9,0xb9,0xfe,0xa6,0xb5,0xb5,0xb5,0x00,0x00,0x02,0x00,0x00,0xfd,0xd1,0x02,0x3f,0xff,0x6a,0x00,0x1c,0x00,0x2b,0x00,0x00,0x01,0x26,0x27,0x06,0x07,0x06,0x23,0x22, 0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x16,0x17,0x36,0x37,0x17,0x06,0x07,0x06,0x07,0x16,0x17,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x37,0x26,0x01,0xa4,0x09,0x0b,0x1b,0x1d,0x36,0x43,0x28,0x50,0x3f,0x28,0x5a,0x51,0x3b,0x6c,0x2b,0x27,0x1e,0x37,0x2a,0x1c,0x1a,0x21,0x0e,0x10,0x0b,0x07,0xb5,0x1e, 0x4a,0x28,0x0f,0x20,0x1b,0x11,0x47,0x3d,0x4c,0x40,0x11,0xfd,0xd1,0x23,0x21,0x05,0x03,0x07,0x0d,0x27,0x48,0x3a,0x51,0x5d,0x3e,0x36,0x30,0x3f,0x0f,0x10,0x64,0x07,0x0a,0x05,0x04,0x24,0x26,0xd0,0x29,0x30,0x07,0x12,0x1e,0x17,0x29,0x27,0x0a,0x20,0x00,0x02,0x00,0x00,0x06,0x76,0x02,0xae,0x08,0x74,0x00,0x03,0x00,0x07,0x00,0x00, 0x11,0x25,0x17,0x05,0x13,0x25,0x17,0x05,0x02,0x22,0x1e,0xfd,0xde,0x50,0x02,0x22,0x1e,0xfd,0xde,0x06,0xde,0x9c,0x68,0x9c,0x01,0x62,0x9c,0x68,0x9c,0x00,0x00,0x04,0xff,0xbf,0x06,0x55,0x03,0xd2,0x08,0x0e,0x00,0x21,0x00,0x2f,0x00,0x51,0x00,0x5f,0x00,0x00,0x01,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x37,0x16,0x16,0x33,0x32, 0x36,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x05,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x37,0x16,0x16,0x33,0x32,0x36,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37, 0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x01,0x3c,0x17,0x28,0x11,0x18,0x30,0x15,0x72,0x5e,0x12,0x33,0x5a,0x39,0x01,0x0b,0x07,0x34,0x1e,0x32,0x3f,0x20,0x1f,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x04,0x33,0x1f,0x10,0x1f,0x19,0x0f,0x23,0x1a,0x30,0x3c,0x01,0xcf,0x17,0x28,0x11,0x18,0x30,0x15,0x72,0x5e, 0x12,0x33,0x5a,0x39,0x01,0x0b,0x07,0x34,0x1e,0x32,0x3f,0x20,0x1f,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x04,0x33,0x1f,0x10,0x1f,0x19,0x0f,0x23,0x1a,0x30,0x3c,0x06,0x55,0x11,0x22,0x11,0x05,0x03,0x1c,0x53,0x0d,0x0f,0x01,0x02,0x43,0x44,0x26,0x3c,0x29,0x15,0x14,0x29,0x3d,0x29,0x42,0x5a,0x1a,0x0b,0x10,0x08,0xd6,0x29,0x25, 0x09,0x13,0x1c,0x12,0x1d,0x3d,0x1d,0x10,0x39,0xe9,0x11,0x22,0x11,0x05,0x03,0x1c,0x53,0x0d,0x0f,0x01,0x02,0x43,0x44,0x26,0x3c,0x29,0x15,0x14,0x29,0x3d,0x29,0x42,0x5a,0x1a,0x0b,0x10,0x08,0xd6,0x29,0x25,0x09,0x13,0x1c,0x12,0x1d,0x3d,0x1d,0x10,0x39,0x00,0x00,0x02,0x00,0x00,0xfd,0x6c,0x02,0xae,0xff,0x6a,0x00,0x03,0x00,0x07, 0x00,0x00,0x11,0x25,0x17,0x05,0x13,0x25,0x17,0x05,0x02,0x22,0x1e,0xfd,0xde,0x50,0x02,0x22,0x1e,0xfd,0xde,0xfd,0xd4,0x9c,0x68,0x9c,0x01,0x62,0x9c,0x68,0x9c,0x00,0x00,0x02,0x00,0x00,0x06,0x76,0x01,0xc8,0x08,0xdd,0x00,0x23,0x00,0x35,0x00,0x00,0x11,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34, 0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x3c,0x5c,0x2b,0x34,0x41,0x25,0x0e,0x15,0x2d,0x17,0x24,0x42,0x33,0x1e,0x1a,0x2e,0x3f,0x24,0x26,0x45,0x1d,0x1d,0x1d,0x1e,0x3f,0x63,0x45,0x31,0x5c,0x36,0x01,0x6a,0x01,0x11, 0x1d,0x25,0x15,0x0f,0x1c,0x17,0x0e,0x12,0x1d,0x27,0x15,0x13,0x28,0x07,0x01,0x18,0x12,0x1e,0x31,0x3d,0x20,0x08,0x0a,0x16,0x2a,0x3d,0x28,0x22,0x47,0x39,0x25,0x2b,0x2e,0x2d,0x70,0x47,0x3e,0x6c,0x51,0x2f,0x10,0x19,0x01,0x3d,0x14,0x38,0x33,0x24,0x0f,0x1a,0x24,0x14,0x13,0x1f,0x15,0x0c,0x06,0x00,0x00,0x03,0x00,0x0a,0x06,0x7b, 0x02,0x06,0x08,0x1c,0x00,0x11,0x00,0x18,0x00,0x1f,0x00,0x00,0x13,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x33,0x15,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x32,0x36,0x37,0x23,0x16,0x16,0x13,0x22,0x06,0x07,0x33,0x26,0x26,0x0a,0x5c,0x0a,0x50,0x42,0x42,0x52,0x0b,0x65,0x64,0x08,0x50,0x48,0x45,0x51,0x08,0x5a,0xfb,0x2a,0x22, 0x04,0xa3,0x04,0x25,0x2a,0x27,0x26,0x05,0xa0,0x05,0x23,0x07,0x7e,0x50,0x4e,0x4e,0x50,0x58,0x55,0x56,0x56,0x55,0x60,0x2b,0x35,0x35,0x2b,0x01,0x0b,0x25,0x2e,0x2d,0x26,0x00,0x00,0x02,0x00,0x05,0x06,0x7c,0x02,0x01,0x07,0xdf,0x00,0x03,0x00,0x07,0x00,0x00,0x13,0x21,0x15,0x21,0x25,0x23,0x35,0x33,0x05,0x01,0xfc,0xfe,0x04,0x01, 0x5b,0xb9,0xb9,0x06,0xd4,0x58,0xae,0xb5,0x00,0x02,0x00,0x05,0xfe,0x07,0x02,0x01,0xff,0x6a,0x00,0x03,0x00,0x07,0x00,0x00,0x17,0x21,0x15,0x21,0x01,0x23,0x35,0x33,0x05,0x01,0xfc,0xfe,0x04,0x01,0x5b,0xb9,0xb9,0x96,0x58,0xfe,0xf5,0xb5,0x00,0x01,0x00,0x00,0x06,0x62,0x01,0x49,0x08,0x48,0x00,0x06,0x00,0x00,0x11,0x25,0x15,0x07, 0x17,0x15,0x25,0x01,0x49,0xe7,0xe7,0xfe,0xb7,0x07,0x8e,0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x00,0x01,0x00,0x00,0x06,0x62,0x01,0x49,0x08,0x48,0x00,0x06,0x00,0x00,0x01,0x05,0x35,0x37,0x27,0x35,0x05,0x01,0x49,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x07,0x1c,0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x00,0x01,0x00,0x00,0xfd,0x84,0x01,0x49, 0xff,0x6a,0x00,0x06,0x00,0x00,0x11,0x25,0x15,0x07,0x17,0x15,0x25,0x01,0x49,0xe7,0xe7,0xfe,0xb7,0xfe,0xb0,0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x00,0x01,0x00,0x00,0xfd,0x84,0x01,0x49,0xff,0x6a,0x00,0x06,0x00,0x00,0x01,0x05,0x35,0x37,0x27,0x35,0x05,0x01,0x49,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0xfe,0x3e,0xba,0x7d,0x76,0x76,0x7d, 0xba,0x00,0x00,0x02,0x00,0x00,0x06,0x62,0x02,0xd9,0x08,0x48,0x00,0x06,0x00,0x0d,0x00,0x00,0x01,0x05,0x35,0x37,0x27,0x35,0x0d,0x02,0x35,0x37,0x27,0x35,0x05,0x01,0x49,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x01,0x90,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x07,0x1c,0xba,0x7d,0x76,0x76,0x7d,0xba,0x72,0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x03, 0x00,0x64,0x06,0x62,0x04,0x41,0x08,0x48,0x00,0x03,0x00,0x0a,0x00,0x11,0x00,0x00,0x01,0x23,0x35,0x33,0x05,0x05,0x35,0x37,0x27,0x35,0x0d,0x02,0x35,0x37,0x27,0x35,0x05,0x01,0x1d,0xb9,0xb9,0x01,0x94,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x01,0x90,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x06,0xf8,0xb5,0x91,0xba,0x7d,0x76,0x76,0x7d,0xba,0x72, 0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x02,0x00,0x64,0x06,0x62,0x02,0xb1,0x08,0x48,0x00,0x03,0x00,0x0a,0x00,0x00,0x01,0x23,0x35,0x33,0x05,0x05,0x35,0x37,0x27,0x35,0x05,0x01,0x1d,0xb9,0xb9,0x01,0x94,0xfe,0xb7,0xe7,0xe7,0x01,0x49,0x06,0xf8,0xb5,0x91,0xba,0x7d,0x76,0x76,0x7d,0xba,0x00,0x00,0x03,0x00,0x00,0x06,0x55,0x02,0x84, 0x08,0x0e,0x00,0x21,0x00,0x2f,0x00,0x33,0x00,0x00,0x01,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x37,0x16,0x16,0x33,0x32,0x32,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x17,0x37,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x36,0x36,0x25,0x23,0x35,0x33,0x01,0xf6,0x17,0x28,0x11, 0x18,0x30,0x15,0x72,0x5e,0x12,0x33,0x5a,0x39,0x01,0x0c,0x08,0x36,0x1e,0x32,0x3f,0x20,0x1f,0x3c,0x2e,0x1c,0x48,0x39,0x0b,0x14,0x09,0x04,0x33,0x1f,0x10,0x1f,0x19,0x0f,0x23,0x1a,0x30,0x3c,0xfe,0x8a,0xb9,0xb9,0x06,0x55,0x11,0x22,0x11,0x05,0x03,0x1c,0x53,0x0d,0x0f,0x02,0x45,0x43,0x26,0x3c,0x29,0x15,0x14,0x29,0x3d,0x29,0x42, 0x5a,0x1a,0x0b,0x10,0x08,0xd6,0x29,0x25,0x09,0x13,0x1c,0x12,0x1d,0x3d,0x1d,0x10,0x39,0x11,0xb5,0x00,0x00,0x01,0x00,0x73,0xff,0xf2,0x0b,0xf8,0x02,0x3e,0x00,0x45,0x00,0x2c,0xb1,0x40,0x37,0xb8,0x04,0xfb,0xb5,0x0e,0x45,0x45,0x3c,0x3c,0x30,0xb8,0x04,0xfb,0xb4,0x15,0x05,0x0e,0x28,0x1f,0xb9,0x04,0xfb,0x00,0x21,0x00,0x2f,0xfd, 0x32,0xde,0x32,0xdc,0xed,0x32,0x2f,0x33,0x2f,0x10,0xed,0x32,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x33,0x15,0x21,0x22,0x26,0x27,0x27,0x37,0x21,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x04,0x33,0x32,0x3e,0x02,0x35,0x33,0x14, 0x16,0x33,0x32,0x3e,0x02,0x35,0x0b,0xf8,0x16,0x2d,0x44,0x2e,0x2d,0x4a,0x17,0x07,0x12,0x24,0x26,0x28,0x16,0x29,0x39,0x2c,0x25,0x2b,0x36,0x26,0x20,0x24,0x14,0x05,0x0b,0x17,0x21,0x17,0x8c,0xf8,0x84,0x55,0xb2,0x51,0x1c,0x05,0x07,0xa7,0x17,0x15,0x1a,0x38,0x56,0x3c,0x2a,0x3d,0x30,0x28,0x29,0x2f,0x20,0x20,0x2d,0x1c,0x0d,0x6e, 0x26,0x33,0x13,0x18,0x0e,0x06,0x02,0x3d,0x45,0x6f,0x4e,0x2a,0x27,0x2a,0x1a,0x20,0x11,0x06,0x14,0x1e,0x24,0x1e,0x14,0x11,0x1a,0x20,0x10,0x15,0x30,0x2e,0x27,0x0b,0xa7,0x0e,0x0f,0x85,0x05,0x25,0x5c,0x23,0x30,0x5a,0x47,0x2b,0x17,0x22,0x27,0x22,0x17,0x20,0x30,0x37,0x17,0x54,0x4a,0x1f,0x30,0x37,0x18,0x00,0x00,0x01,0x00,0xbc, 0x00,0x00,0x03,0xfa,0x05,0x9a,0x00,0x07,0x00,0x00,0x01,0x15,0x21,0x11,0x23,0x11,0x33,0x11,0x03,0xfa,0xfd,0x6a,0xa8,0xa8,0x03,0x25,0x97,0xfd,0x72,0x05,0x9a,0xfd,0x8b,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0x04,0x04,0x00,0x00,0x07,0x00,0x00,0x01,0x15,0x21,0x11,0x23,0x11,0x33,0x11,0x03,0x04,0xfe,0x46,0xa4,0xa4,0x02,0x5c, 0x8b,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x00,0x00,0x01,0x00,0x50,0x00,0x00,0x04,0x33,0x05,0x9a,0x00,0x0b,0x00,0x00,0x01,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x04,0x33,0xa8,0xf6,0xa8,0xf5,0xa8,0x05,0x9a,0xfe,0x1e,0x01,0x4a,0xfa,0xfe,0x05,0x02,0xfe,0xb6,0x01,0xe2,0x00,0x00,0x01,0x00,0x50,0x00,0x00,0x03,0xe8, 0x05,0x3f,0x00,0x0b,0x00,0x00,0x01,0x11,0x23,0x35,0x23,0x11,0x23,0x11,0x23,0x15,0x23,0x11,0x03,0xe8,0x9e,0xdc,0xa4,0xdc,0x9e,0x05,0x3f,0xfe,0x8e,0xe6,0xfb,0x4d,0x04,0xb3,0xe6,0x01,0x72,0x00,0xff,0xff,0x00,0xbc,0x00,0x00,0x05,0x40,0x05,0x9a,0x02,0x06,0x01,0xef,0x00,0x00,0xff,0xff,0x00,0xa6,0x00,0x00,0x04,0x00,0x04,0x00, 0x02,0x06,0x02,0x0f,0x00,0x00,0x00,0x01,0x00,0xbc,0xfe,0x8c,0x04,0x98,0x05,0x9a,0x00,0x12,0x00,0x00,0x25,0x01,0x27,0x01,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x37,0x01,0x33,0x01,0x04,0x98,0xfe,0x30,0x63,0x01,0x49,0xfd,0xe0,0x1f,0x07,0x04,0xa8,0xa8,0x04,0x0e,0x18,0x02,0x18,0xd1,0xfd,0x99,0x05,0xfe,0x87, 0x74,0x01,0x0b,0x02,0x85,0x25,0x0d,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x16,0x1b,0x02,0x71,0xfd,0x50,0x00,0x00,0x01,0x00,0x10,0xff,0xe9,0x06,0xe4,0x05,0x9a,0x00,0x28,0x00,0x00,0x21,0x23,0x01,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x01,0x23,0x03,0x06,0x06,0x07,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x36,0x12,0x13, 0x21,0x01,0x16,0x16,0x17,0x33,0x36,0x37,0x01,0x33,0x01,0x06,0xe4,0xcd,0xfe,0xb6,0x10,0x11,0x04,0x05,0x11,0x0c,0xfe,0xac,0xce,0x01,0xe0,0xfe,0xa4,0x7a,0x6d,0x10,0x2d,0x14,0x52,0xc5,0x4f,0x3a,0x34,0x3d,0x3e,0x36,0x37,0x71,0x45,0x01,0x76,0x01,0x25,0x0e,0x1a,0x0b,0x04,0x1f,0x19,0x01,0x31,0xc1,0xfe,0x3d,0x02,0x25,0x1b,0x2c, 0x0b,0x24,0x18,0xfd,0xdb,0x02,0xd1,0x02,0x31,0xfd,0x02,0x71,0xa3,0x36,0xd1,0x15,0x9e,0x1d,0x4a,0x4a,0x02,0x6e,0x02,0x19,0xfe,0x08,0x19,0x32,0x19,0x41,0x27,0x01,0xf4,0xfd,0x39,0x00,0x00,0x01,0x00,0x10,0xff,0xf2,0x05,0x40,0x04,0x00,0x00,0x21,0x00,0x00,0x09,0x02,0x23,0x03,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x23,0x01,0x03, 0x23,0x02,0x07,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x13,0x16,0x16,0x17,0x33,0x01,0x05,0x40,0xfe,0xa8,0x01,0x52,0xbf,0xc9,0x14,0x19,0x04,0x02,0x18,0x15,0xcd,0xbd,0x01,0x5d,0xf5,0x30,0x29,0x64,0x63,0xa8,0x31,0x27,0x22,0x2a,0xdc,0x3f,0x01,0x1f,0xc6,0x0b,0x15,0x0b,0x04,0x01,0x00,0x04,0x00,0xfd,0xfa,0xfe,0x06, 0x01,0x4c,0x1f,0x2f,0x05,0x26,0x23,0xfe,0xb4,0x01,0xf6,0x01,0x7f,0xfe,0x0f,0xc9,0xc9,0x0e,0x8d,0x12,0x03,0x85,0xfe,0xa2,0x14,0x28,0x14,0x01,0xae,0x00,0x00,0x02,0x00,0xbc,0x00,0x00,0x05,0xe0,0x05,0x9a,0x00,0x11,0x00,0x19,0x00,0x00,0x01,0x11,0x23,0x11,0x21,0x32,0x17,0x16,0x17,0x13,0x33,0x01,0x01,0x23,0x01,0x06,0x06,0x23, 0x03,0x11,0x33,0x32,0x36,0x35,0x10,0x21,0x01,0x64,0xa8,0x01,0x8a,0xe7,0x7d,0x73,0x0b,0xf1,0xc1,0xfe,0x3d,0x01,0xc9,0xcd,0xfe,0x63,0x42,0xab,0x68,0xbd,0xb0,0xaf,0xb6,0xfe,0xb0,0x02,0x1e,0xfd,0xe2,0x05,0x9a,0x70,0x66,0xb5,0x01,0x8b,0xfd,0x39,0xfd,0x2d,0x02,0x80,0x32,0x30,0x02,0xe4,0xfd,0xb4,0x9e,0x92,0x01,0x1c,0x00,0x02, 0x00,0xa6,0xfe,0x29,0x05,0xea,0x04,0x18,0x00,0x1a,0x00,0x2f,0x00,0x00,0x09,0x02,0x23,0x03,0x0e,0x03,0x23,0x22,0x27,0x23,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x17,0x13,0x01,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x05,0xea,0xfe,0xa8,0x01,0x52,0xbf,0xe2,0x13,0x4e, 0x72,0x95,0x5a,0xc7,0x6c,0x04,0xa4,0xa4,0x04,0x79,0xe9,0x58,0x8f,0x6a,0x42,0x0b,0xe7,0xfc,0x15,0x2b,0x4e,0x6b,0x40,0x4b,0x76,0x52,0x2b,0x29,0x4c,0x6d,0x43,0x47,0x75,0x53,0x2e,0x04,0x00,0xfd,0xfa,0xfe,0x06,0x01,0x74,0x5b,0x93,0x67,0x37,0xac,0xfd,0x95,0x05,0xd7,0xb4,0xcc,0x3a,0x6b,0x99,0x5e,0x01,0x84,0xfe,0x31,0x8f,0x3f, 0x6f,0x52,0x30,0x3b,0x70,0x9f,0x65,0x55,0x87,0x5f,0x32,0x35,0x5e,0x80,0x00,0x02,0x00,0x3d,0x00,0x00,0x06,0x4d,0x05,0x9a,0x00,0x24,0x00,0x2f,0x00,0x00,0x21,0x21,0x11,0x23,0x22,0x0e,0x02,0x07,0x03,0x23,0x13,0x3e,0x03,0x37,0x35,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x01,0x11,0x23, 0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x06,0x4d,0xfd,0x08,0xd1,0x1e,0x34,0x31,0x2f,0x19,0xb4,0xc8,0xda,0x0a,0x21,0x2b,0x33,0x1d,0x47,0x70,0x4e,0x29,0x44,0x7a,0xaa,0x66,0x03,0xd0,0xfd,0xd0,0x02,0x06,0xfd,0xfa,0x02,0x50,0xfd,0x08,0xe9,0x8f,0x9c,0x2a,0x4d,0x6d,0x43,0x02,0x62,0x0b,0x25,0x47,0x3b,0xfe,0x50,0x01,0xdf,0x16,0x34, 0x30,0x29,0x0b,0x04,0x10,0x43,0x60,0x7b,0x47,0x5c,0x95,0x6a,0x39,0x98,0xfe,0x23,0x97,0xfe,0x0a,0x02,0x62,0x02,0x08,0x85,0x7b,0x3d,0x62,0x44,0x25,0x00,0x00,0x03,0x00,0x3e,0xff,0xe8,0x06,0x3a,0x04,0x18,0x00,0x28,0x00,0x31,0x00,0x38,0x00,0x00,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x27,0x23,0x22, 0x07,0x03,0x23,0x13,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x21,0x15,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x07,0x11,0x23,0x22,0x15,0x14,0x33,0x06,0x3a,0xfd,0x2d,0x04,0xaf,0x9b,0xac,0x92,0x88,0xdd,0x63,0xa1,0x77,0x48,0x0a,0x8c,0x63,0x51,0x85,0xbe,0xac,0x3d,0x54,0x79,0x7d,0x33, 0x61,0x8b,0x58,0x01,0x66,0x3e,0x9b,0x5a,0x65,0x9d,0x6b,0x38,0xa8,0x01,0x86,0x79,0x3a,0x64,0x4e,0x33,0x0a,0xab,0xc2,0xcf,0xc9,0x01,0xd7,0xac,0xb9,0x72,0x9a,0x62,0x3c,0x72,0xa7,0x6b,0xa0,0xfe,0xf8,0x01,0x3c,0x6f,0x22,0x10,0x8f,0x6d,0x44,0x6d,0x4d,0x29,0x62,0x3a,0x40,0x43,0x7f,0xb6,0x73,0x35,0x8f,0x9d,0x2c,0x4f,0x6f,0x42, 0x31,0x01,0x43,0x9d,0xa6,0x00,0x00,0x01,0x00,0xbc,0x00,0x00,0x04,0xa2,0x05,0x9a,0x00,0x19,0x00,0x00,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x27,0x37,0x17,0x37,0x33,0x01,0x17,0x07,0x27,0x03,0x04,0xa2,0xea,0xfd,0xd6,0x1e,0x08,0x04,0xa8,0xa8,0x04,0x07,0x13,0x0c,0x01,0x04,0x7f,0x6a, 0x79,0xb0,0xd1,0xfe,0xe6,0x92,0x6e,0x8b,0xe6,0x02,0x90,0x24,0x0e,0xfd,0x3e,0x05,0x9a,0xfd,0x5e,0x0b,0x18,0x0e,0x01,0x30,0x8d,0x69,0x82,0xcd,0xfe,0xc5,0x9c,0x71,0x99,0xfe,0xff,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf8,0x04,0x00,0x00,0x14,0x00,0x00,0x01,0x37,0x33,0x07,0x17,0x07,0x27,0x07,0x01,0x23,0x01,0x23,0x11,0x23, 0x11,0x33,0x11,0x33,0x37,0x27,0x37,0x02,0x84,0x78,0xd7,0xed,0x66,0x61,0x5e,0x95,0x02,0x00,0xe6,0xfe,0x3c,0x04,0xa4,0xa4,0x04,0xdf,0x57,0x5f,0x03,0x7d,0x83,0xf6,0x77,0x54,0x6e,0x9b,0xfd,0xee,0x01,0xec,0xfe,0x14,0x04,0x00,0xfe,0x2b,0xf3,0x66,0x55,0x00,0x00,0x01,0x00,0x10,0xfe,0x66,0x07,0x73,0x05,0x9a,0x00,0x2e,0x00,0x00, 0x01,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x23,0x11,0x21,0x03,0x06,0x06,0x07,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x36,0x12,0x13,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x03,0xfe,0xa3,0x9b,0xbe,0xc9,0x42,0x7a,0xb0,0x6d,0x46,0xa8,0xfe,0x72,0x6d,0x10,0x2d,0x14,0x52,0xc5, 0x4f,0x3a,0x34,0x3d,0x3e,0x36,0x37,0x71,0x45,0x02,0xc2,0x4a,0x93,0xee,0xa8,0x5c,0x4b,0x90,0xd2,0x86,0xae,0xfe,0xb2,0xb8,0x6c,0xde,0xcc,0x69,0xb9,0x89,0x4f,0xfd,0x5e,0x05,0x02,0xfd,0x02,0x71,0xa3,0x36,0xd1,0x15,0x9e,0x1d,0x4a,0x4a,0x02,0x6e,0x02,0x19,0xfd,0xa0,0x5f,0xac,0xf0,0x91,0x7d,0xd6,0x9c,0x59,0x00,0x01,0x00,0x10, 0xfe,0x66,0x05,0xf1,0x04,0x00,0x00,0x2c,0x00,0x00,0x01,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x23,0x11,0x23,0x06,0x02,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x13,0x21,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x02,0xed,0x75,0x8b,0x54,0x81,0x59,0x2e,0x39,0x6a,0x97,0x5e,0x20, 0xa3,0xee,0x15,0x46,0x65,0x85,0x53,0x31,0x27,0x22,0x2a,0xdc,0x3f,0x02,0x1a,0x42,0x7b,0xc8,0x8e,0x4d,0x49,0x87,0xbf,0x77,0x9a,0xfe,0xa0,0xa0,0x4e,0x30,0x5b,0x85,0x54,0x5d,0x94,0x67,0x38,0xfe,0x1a,0x03,0x75,0xfb,0xfe,0xa9,0xd4,0x5d,0x0e,0x8d,0x12,0x03,0x85,0xfe,0x74,0x4c,0x8d,0xc8,0x7b,0x6b,0xb6,0x85,0x4c,0x00,0x00,0x01, 0x00,0xbc,0xfe,0x66,0x07,0xc1,0x05,0x9a,0x00,0x25,0x00,0x00,0x01,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x04,0x4c,0xa3,0x9b,0xbe,0xc9,0x42,0x7a,0xb0,0x6d,0x46,0xa8,0xfd,0x1a,0xa8,0xa8,0x02, 0xe6,0xa8,0x4a,0x93,0xee,0xa8,0x5c,0x4b,0x90,0xd2,0x86,0xae,0xfe,0xb2,0xb8,0x6c,0xde,0xcc,0x69,0xb9,0x89,0x4f,0xfd,0x5e,0x02,0xa3,0xfd,0x5d,0x05,0x9a,0xfd,0xa0,0x02,0x60,0xfd,0xa0,0x5f,0xac,0xf0,0x91,0x7d,0xd6,0x9c,0x59,0x00,0x01,0x00,0xa6,0xfe,0x66,0x06,0x58,0x04,0x00,0x00,0x27,0x00,0x00,0x01,0x35,0x16,0x33,0x32,0x3e, 0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x03,0x54,0x75,0x8b,0x54,0x81,0x59,0x2e,0x39,0x6a,0x97,0x5e,0x20,0xa4,0xfd,0xf6,0xa4,0xa4,0x02,0x0a,0xa4,0x42,0x7b,0xc8,0x8e,0x4d,0x49,0x87,0xbf,0x77,0x9a,0xfe,0xa0,0xa0, 0x4e,0x30,0x5b,0x85,0x54,0x5d,0x94,0x67,0x38,0xfe,0x1a,0x01,0xd1,0xfe,0x2f,0x04,0x00,0xfe,0x5c,0x01,0xa4,0xfe,0x74,0x4c,0x8d,0xc8,0x7b,0x6b,0xb6,0x85,0x4c,0x00,0x00,0x01,0x00,0xa6,0xfe,0x7f,0x05,0x41,0x05,0x9a,0x00,0x16,0x00,0x00,0x13,0x33,0x11,0x36,0x33,0x32,0x1e,0x02,0x15,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x34,0x23, 0x22,0x07,0x11,0x23,0xa6,0xa8,0xe5,0xc5,0x5e,0x92,0x65,0x34,0xc0,0x9b,0xcd,0xf6,0xb1,0xe4,0xa8,0x05,0x9a,0xfd,0x7b,0x79,0x32,0x5f,0x8a,0x58,0xfe,0x7d,0xfd,0xe7,0x01,0x81,0x02,0x13,0xe7,0x6e,0xfd,0x74,0x00,0x01,0x00,0x98,0xfe,0x8b,0x04,0x76,0x04,0x00,0x00,0x13,0x00,0x00,0x01,0x23,0x11,0x23,0x11,0x34,0x23,0x22,0x07,0x11, 0x23,0x11,0x33,0x11,0x36,0x33,0x20,0x11,0x15,0x33,0x04,0x76,0x8d,0xae,0xc2,0x94,0xaa,0xa3,0xa3,0xb5,0x97,0x01,0x58,0x97,0xfe,0x8b,0x01,0x75,0x01,0x52,0xe1,0x56,0xfe,0x23,0x04,0x00,0xfe,0x64,0x62,0xfe,0x94,0xcf,0x00,0x01,0x00,0x35,0x00,0x00,0x02,0xa0,0x06,0x02,0x00,0x1a,0x00,0x00,0x01,0x07,0x11,0x23,0x11,0x07,0x35,0x37, 0x35,0x23,0x35,0x33,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x11,0x37,0x02,0x77,0xf0,0xa3,0xaf,0xaf,0xaf,0xaf,0x32,0x58,0x76,0x45,0x4b,0x2c,0x30,0x3d,0xac,0xf0,0x02,0xec,0x92,0xfd,0xa6,0x01,0xf8,0x6a,0xa5,0x68,0xd9,0x8c,0xa6,0x51,0x81,0x5a,0x30,0x12,0x94,0x1b,0xd9,0xfe,0x5f,0x8f,0x00,0x01,0x00,0x35, 0x00,0x00,0x02,0xa0,0x06,0x02,0x00,0x18,0x00,0x00,0x01,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x3e,0x03,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x02,0x77,0xf0,0xa3,0xaf,0xaf,0xaf,0xba,0x0d,0x3b,0x52,0x67,0x39,0x4b,0x2c,0x30,0x3d,0x7b,0x23,0x05,0x09,0x8c,0xfb,0x83,0x03,0x74,0x8c,0x7d,0x8c,0x3a,0x5d, 0x40,0x22,0x12,0x94,0x1b,0x6e,0x00,0x02,0x00,0x5c,0xff,0xe7,0x04,0x53,0x05,0xfe,0x00,0x27,0x00,0x38,0x00,0x00,0x01,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x03,0x04,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e, 0x02,0x35,0x34,0x2e,0x02,0x03,0xe7,0xa9,0xab,0x32,0x51,0x3a,0x20,0x19,0x36,0x55,0x3c,0x72,0xa7,0x6e,0x36,0x4a,0x88,0xc0,0x77,0x6d,0xb5,0x83,0x49,0xd3,0xcc,0xee,0x36,0x65,0x91,0x5a,0xa6,0xbf,0xfe,0x92,0x2f,0x57,0x7a,0x4b,0x4f,0x7f,0x59,0x30,0x22,0x4a,0x75,0x05,0xbe,0xb7,0x65,0x12,0x21,0x2f,0x1d,0x18,0x31,0x36,0x3e,0x24, 0x45,0x7c,0x81,0x8f,0x5a,0x75,0xbb,0x83,0x47,0x46,0x7f,0xb1,0x6c,0x9c,0x01,0x01,0x58,0x93,0xa3,0x40,0x63,0x44,0x23,0xfd,0x75,0x95,0xfe,0xec,0x4f,0x7e,0x59,0x30,0x32,0x5d,0x82,0x50,0x3b,0x68,0x63,0x62,0x00,0x02,0x00,0xbc,0x00,0x00,0x05,0x0c,0x05,0x9a,0x00,0x05,0x00,0x09,0x00,0x00,0x21,0x21,0x11,0x33,0x11,0x21,0x05,0x23, 0x11,0x33,0x05,0x0c,0xfd,0x18,0xa8,0x02,0x40,0xfc,0x58,0xa8,0xa8,0x05,0x9a,0xfa,0xfe,0x98,0x05,0x9a,0x00,0x01,0x00,0x1e,0x00,0x00,0x03,0x26,0x05,0xec,0x00,0x13,0x00,0x00,0x01,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x03,0x26,0x88,0xa4,0xb0,0xa4,0x88,0x88,0xa4,0xb0, 0xa4,0x88,0x04,0xb2,0xfb,0x4e,0x04,0xb2,0xfb,0x4e,0x04,0xb2,0x86,0xb4,0xb4,0xb4,0xb4,0x00,0x00,0x01,0x00,0x81,0xff,0xe9,0x04,0x4b,0x05,0xee,0x00,0x25,0x00,0x00,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x37,0x17,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27, 0x03,0x8d,0x5a,0x64,0x43,0x7d,0xb1,0x6e,0x77,0xb7,0x7d,0x40,0x3b,0x62,0x7d,0x42,0x80,0x3e,0x6c,0x50,0x2e,0x2a,0x51,0x75,0x4b,0x43,0x6d,0x4e,0x2b,0x38,0x33,0x03,0x9b,0x43,0xda,0x8d,0x75,0xbf,0x89,0x4b,0x56,0xa4,0xf0,0x9b,0x92,0x01,0x11,0xea,0xb9,0x3a,0x6b,0x40,0x9e,0xc2,0xe8,0x8b,0x6c,0xb7,0x84,0x4b,0x36,0x5e,0x82,0x4c, 0x60,0x96,0x32,0x00,0x00,0x01,0x00,0x77,0xff,0xe8,0x03,0xaa,0x05,0xf1,0x00,0x25,0x00,0x00,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x36,0x36,0x37,0x17,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x02,0xf1,0x58,0x61,0x33,0x61,0x8c,0x5a,0x6c,0xa5,0x6f,0x39,0x3b,0x61, 0x7c,0x42,0x78,0x3e,0x6c,0x50,0x2e,0x25,0x47,0x66,0x41,0x31,0x4d,0x34,0x1c,0x38,0x33,0x03,0x96,0x42,0xd8,0x8c,0x75,0xbf,0x89,0x4b,0x56,0xa5,0xf0,0x9b,0x93,0x01,0x13,0xeb,0xb9,0x39,0x65,0x40,0x9f,0xc4,0xec,0x8d,0x6e,0xbb,0x88,0x4d,0x37,0x62,0x86,0x4e,0x61,0x98,0x33,0x00,0x00,0x02,0x00,0x06,0xff,0xe7,0x04,0x96,0x05,0x9a, 0x00,0x1a,0x00,0x29,0x00,0x00,0x01,0x01,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x01,0x33,0x01,0x16,0x16,0x17,0x33,0x01,0x01,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x26,0x04,0x96,0xfe,0x45,0x3c,0x70,0x71,0x76,0x41,0x3b,0x5f,0x43,0x24,0x42,0x6e,0x8d,0x4b,0x30,0x2f,0xfe,0x4f,0xbf, 0x01,0x58,0x05,0x12,0x0e,0x05,0x01,0x65,0xfd,0x96,0x2e,0x4a,0x35,0x1d,0x3a,0x35,0x18,0x35,0x3c,0x42,0x24,0x43,0x05,0x9a,0xfc,0x17,0x87,0xb0,0x69,0x2a,0x26,0x44,0x5e,0x37,0x48,0x6f,0x4b,0x26,0x06,0x03,0x92,0xfd,0x02,0x0a,0x2e,0x25,0x03,0x5b,0xfb,0xea,0x15,0x26,0x35,0x20,0x3b,0x3c,0x19,0x38,0x5c,0x44,0x16,0x00,0x00,0x02, 0xff,0xbd,0xfe,0x1e,0x03,0xd5,0x04,0x00,0x00,0x19,0x00,0x29,0x00,0x00,0x01,0x01,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x01,0x33,0x01,0x17,0x33,0x36,0x36,0x37,0x01,0x01,0x22,0x0e,0x02,0x15,0x14,0x33,0x32,0x3e,0x02,0x37,0x37,0x26,0x22,0x03,0xd5,0xfe,0x29,0x7e,0xe4,0x32,0x52,0x3b,0x20,0x43,0x6f, 0x8f,0x4b,0x14,0x25,0x13,0xfe,0x79,0xb6,0x01,0x15,0x15,0x06,0x02,0x0a,0x08,0x01,0x23,0xfe,0x08,0x2e,0x4c,0x36,0x1e,0x49,0x12,0x2a,0x2b,0x28,0x0f,0x22,0x0e,0x1e,0x04,0x00,0xfb,0x5c,0xfe,0xc2,0x1b,0x36,0x51,0x36,0x48,0x6f,0x4a,0x26,0x02,0x02,0x03,0xe7,0xfc,0xec,0x4e,0x0c,0x26,0x1a,0x03,0x16,0xfb,0x93,0x15,0x25,0x35,0x20, 0x58,0x12,0x25,0x38,0x25,0x51,0x02,0x00,0x00,0x02,0x00,0xbc,0xff,0xe8,0x05,0x8c,0x05,0xb2,0x00,0x18,0x00,0x2d,0x00,0x00,0x01,0x3e,0x03,0x33,0x32,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x15,0x23,0x11,0x33,0x11,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x01,0x64, 0x27,0x70,0x7c,0x7e,0x35,0x85,0xe0,0xa2,0x5b,0x67,0xb0,0xea,0x82,0x42,0x7c,0x6c,0x5a,0x21,0xa8,0xa8,0x16,0x65,0x7c,0x84,0x35,0x5d,0xa5,0x7d,0x49,0x40,0x76,0xa5,0x66,0x33,0x82,0x7d,0x69,0x1c,0x04,0xab,0x4a,0x65,0x3d,0x1b,0x6a,0xc3,0xfe,0xeb,0xab,0xa9,0xfe,0xf1,0xbf,0x66,0x22,0x3b,0x4d,0x2b,0xbd,0x05,0x9a,0xfc,0x6d,0x6e, 0x96,0x5c,0x28,0x4e,0x96,0xd9,0x8c,0x8a,0xdc,0x9a,0x52,0x27,0x5c,0x98,0x70,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x06,0x40,0x04,0x18,0x00,0x31,0x00,0x3a,0x00,0x00,0x01,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x17,0x0e,0x03,0x23,0x22,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e, 0x02,0x33,0x32,0x1e,0x02,0x15,0x15,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x01,0x0a,0x04,0xaf,0x9b,0x3c,0x79,0x6b,0x52,0x15,0x6a,0x03,0x18,0x2d,0x45,0x30,0x28,0x46,0x3b,0x32,0x15,0x4a,0x1e,0x4d,0x56,0x5c,0x2d,0x54,0x7a,0x1b,0x29,0x67,0x75,0x7d,0x3f,0x75,0xb7,0x7e,0x42,0x49,0x7f,0xad,0x63,0x65,0x9d,0x6b,0x38,0xa8,0x01, 0x86,0x79,0x3a,0x64,0x4e,0x33,0x0a,0x01,0xd7,0xac,0xb9,0x12,0x39,0x6a,0x57,0x1b,0x1f,0x43,0x37,0x24,0x23,0x3d,0x51,0x2e,0x23,0x57,0x7f,0x54,0x29,0x67,0x62,0x45,0x5c,0x38,0x17,0x47,0x89,0xc6,0x7e,0x77,0xc7,0x8f,0x4f,0x43,0x7f,0xb6,0x73,0x56,0x8b,0x8f,0x9d,0x2c,0x4f,0x6f,0x42,0x00,0x00,0x01,0x00,0x78,0xff,0xee,0x02,0x8e, 0x05,0xfe,0x00,0x25,0x00,0x00,0x37,0x16,0x33,0x32,0x37,0x36,0x36,0x35,0x11,0x34,0x26,0x27,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x35,0x33,0x11,0x23,0x35,0x23,0x0e,0x03,0x23,0x22,0x27,0x78,0x2b,0x51,0x69,0x47,0x22,0x24,0x24,0x22,0x47,0x69,0x51,0x2b,0x24,0x3e,0x2d,0x51,0x46,0x36,0x12,0x04,0xa4,0xa4, 0x04,0x12,0x36,0x46,0x51,0x2d,0x3e,0x24,0xa6,0x21,0x63,0x30,0x81,0x53,0x02,0x14,0x52,0x82,0x30,0x63,0x21,0xaa,0x0e,0x1f,0x3b,0x55,0x36,0xd3,0xfa,0x14,0xd3,0x36,0x55,0x3b,0x1f,0x0e,0x00,0x03,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18,0x00,0x13,0x00,0x2f,0x00,0x3e,0x00,0x00,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x02,0x03,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x36,0x36,0x35,0x34,0x26,0x03,0x22,0x0e,0x02,0x15,0x14,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x02,0x52,0x71,0xb8,0x82,0x47,0x49,0x88,0xc1,0x78,0x73,0xb4,0x7d,0x42,0x48,0x84,0xbd,0x69,0x4e,0x7f, 0x59,0x30,0x4d,0x46,0x06,0x1f,0x38,0x4d,0x2d,0x2c,0x4a,0x36,0x1f,0x07,0x3e,0x40,0xaa,0x9f,0x18,0x29,0x1e,0x11,0x70,0x19,0x2b,0x1f,0x11,0x41,0x18,0x4b,0x8a,0xc1,0x76,0x81,0xcb,0x8d,0x4b,0x49,0x8a,0xc5,0x7c,0x79,0xc7,0x8e,0x4e,0x03,0xa6,0x37,0x69,0x96,0x5e,0x73,0xab,0x31,0x18,0x1b,0x2d,0x49,0x34,0x1c,0x1d,0x33,0x46,0x2a, 0x1c,0x16,0x31,0xa7,0x74,0xc1,0xcf,0xfd,0xc5,0x11,0x1f,0x29,0x18,0x70,0x11,0x1e,0x29,0x18,0x31,0x40,0x00,0x01,0x00,0x49,0x00,0x00,0x02,0xc0,0x04,0x33,0x00,0x0b,0x00,0x00,0x37,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x49,0x01,0xd3,0xfe,0x6b,0x01,0x95,0xfe,0x49,0x02,0x5b,0xfd,0x89,0x8b,0x01,0x52,0x8b,0x01, 0x40,0x8b,0xfb,0xcd,0x00,0x02,0x00,0x06,0xfd,0xe3,0x01,0x4a,0x02,0x13,0x00,0x0d,0x00,0x19,0x00,0x00,0x05,0x14,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x35,0x11,0x33,0x27,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x40,0x74,0x6e,0x15,0x2c,0x17,0x3a,0x20,0x6a,0x76,0x3f,0x1d,0x2a,0x2a,0x1d,0x1e,0x2b, 0x2b,0xf7,0x8f,0x97,0x0b,0x0a,0x72,0x25,0xb5,0x02,0x19,0x76,0x28,0x1e,0x1d,0x27,0x27,0x1d,0x1d,0x29,0x00,0x01,0x00,0x1c,0x02,0x9a,0x02,0xdb,0x05,0xa3,0x00,0x08,0x00,0x00,0x01,0x01,0x23,0x01,0x33,0x13,0x17,0x37,0x13,0x02,0xdb,0xfe,0xd7,0x79,0xfe,0xe3,0x83,0xcf,0x0a,0x0a,0xd9,0x05,0xa3,0xfc,0xf7,0x03,0x09,0xfd,0xb7,0x2f, 0x2e,0x02,0x4a,0x00,0x00,0x01,0x00,0x79,0xfe,0x92,0x03,0xde,0x05,0xb2,0x00,0x49,0x00,0x00,0x01,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x26,0x27,0x26,0x26,0x27,0x35,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03, 0x15,0x14,0x0e,0x02,0x07,0x16,0x16,0x17,0x1e,0x03,0x33,0x32,0x36,0x37,0x03,0xab,0x23,0x5b,0x38,0x32,0x5f,0x53,0x42,0x15,0x41,0x8c,0x23,0x3d,0x14,0x22,0x5f,0x69,0x6a,0x2d,0x9c,0x98,0x27,0x53,0x7e,0x57,0x4b,0x82,0x60,0x37,0x56,0x8c,0xb3,0x5d,0xd3,0x62,0x7f,0xc7,0x38,0x6d,0x56,0x36,0x29,0x50,0x73,0x4b,0x4d,0x8a,0x68,0x3d, 0x4d,0x83,0xac,0x5f,0x13,0x1d,0x0b,0x0f,0x2c,0x33,0x38,0x1a,0x2c,0x56,0x2b,0xfe,0xb9,0x14,0x13,0x15,0x2b,0x40,0x2b,0x83,0x4a,0x0a,0x18,0x0e,0xc6,0x1e,0x30,0x21,0x12,0x71,0x6d,0x37,0x4f,0x45,0x45,0x2d,0x27,0x4d,0x5e,0x77,0x50,0x62,0x90,0x5f,0x2e,0x33,0xbd,0x58,0x17,0x34,0x52,0x3b,0x37,0x50,0x42,0x3e,0x25,0x26,0x54,0x66, 0x7d,0x4f,0x64,0x8e,0x5d,0x2e,0x04,0x11,0x28,0x17,0x1d,0x2c,0x1d,0x0f,0x14,0x15,0x00,0x01,0x00,0x21,0xfe,0x8b,0x04,0x64,0x05,0x9a,0x00,0x1c,0x00,0x00,0x01,0x01,0x1e,0x03,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x27,0x2e,0x03,0x23,0x23,0x35,0x01,0x21,0x35,0x21,0x04,0x64,0xfc,0xbd,0x3a,0x6d,0x60,0x54,0x23, 0x4e,0x75,0x32,0x29,0x43,0x28,0x40,0x69,0xaa,0xaa,0x2b,0x51,0x54,0x59,0x33,0xae,0x03,0x41,0xfd,0x02,0x04,0x00,0x05,0x72,0xfb,0x2e,0x0c,0x30,0x3e,0x48,0x24,0x51,0x50,0x14,0x15,0x91,0x26,0xba,0x2e,0x47,0x2e,0x18,0x2f,0x04,0xd3,0x98,0x00,0x01,0x00,0x70,0xff,0xea,0x01,0x50,0x01,0xcf,0x00,0x17,0x00,0x00,0x17,0x22,0x2e,0x02, 0x35,0x34,0x3e,0x02,0x37,0x17,0x0e,0x03,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0xdf,0x17,0x28,0x1e,0x12,0x1b,0x24,0x26,0x0b,0x66,0x0b,0x16,0x13,0x10,0x06,0x24,0x30,0x12,0x1f,0x29,0x16,0x12,0x1e,0x29,0x17,0x20,0x67,0x6e,0x63,0x1d,0x13,0x19,0x3c,0x41,0x41,0x1e,0x0a,0x3d,0x26,0x17,0x29,0x1e,0x12,0x00,0x01,0x00,0x70,0x00,0xf8, 0x01,0x50,0x01,0xd9,0x00,0x13,0x00,0x00,0x37,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0xdf,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0xf8,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x01,0x00,0x27,0xff,0xd4, 0x01,0x3c,0x01,0xc0,0x00,0x03,0x00,0x00,0x01,0x03,0x23,0x13,0x01,0x3c,0xa0,0x75,0x75,0x01,0xc0,0xfe,0x14,0x01,0xec,0x00,0x00,0x02,0x00,0x6f,0xff,0xea,0x01,0x9a,0x05,0x08,0x00,0x13,0x00,0x17,0x00,0x00,0x37,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x03,0x13,0x33,0x03,0xdf,0x17,0x29,0x1e, 0x12,0x12,0x1e,0x29,0x17,0x17,0x29,0x1e,0x12,0x12,0x1e,0x29,0x43,0xa0,0x75,0x75,0xc8,0x12,0x1e,0x29,0x17,0x18,0x28,0x1d,0x11,0x11,0x1e,0x28,0x17,0x17,0x29,0x1e,0x12,0x02,0x54,0x01,0xec,0xfe,0x14,0x00,0x00,0x01,0x00,0x30,0x00,0xe5,0x01,0xda,0x05,0x99,0x00,0x09,0x00,0x00,0x25,0x23,0x03,0x05,0x35,0x05,0x03,0x33,0x03,0x33, 0x01,0xaa,0x4c,0x28,0xfe,0xfa,0x01,0x2e,0x28,0x9c,0x28,0x30,0xe5,0x02,0xb6,0x1e,0x96,0x14,0x01,0x9a,0xfe,0x66,0x00,0x01,0x01,0x2e,0x00,0xe5,0x02,0xd8,0x05,0x99,0x00,0x09,0x00,0x00,0x01,0x33,0x03,0x33,0x03,0x25,0x15,0x25,0x03,0x23,0x01,0x2e,0x30,0x28,0x9c,0x28,0x01,0x2e,0xfe,0xfa,0x28,0x4c,0x03,0xff,0x01,0x9a,0xfe,0x66, 0x14,0x96,0x1e,0xfd,0x4a,0x00,0x00,0x01,0x00,0x30,0x00,0xe5,0x02,0xd8,0x05,0x99,0x00,0x0b,0x00,0x00,0x01,0x25,0x13,0x23,0x13,0x05,0x35,0x05,0x13,0x33,0x13,0x25,0x02,0xd8,0xfe,0xd2,0x28,0x9c,0x28,0xfe,0xd2,0x01,0x06,0x28,0x4c,0x28,0x01,0x06,0x02,0x6b,0x14,0xfe,0x66,0x01,0x9a,0x14,0x96,0x1e,0x02,0xb6,0xfd,0x4a,0x1e,0x00, 0x00,0x02,0x00,0x83,0x01,0x31,0x03,0x27,0x05,0xd3,0x00,0x1f,0x00,0x2d,0x00,0x00,0x01,0x26,0x26,0x27,0x26,0x35,0x34,0x37,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x14,0x1e,0x02,0x17,0x16,0x15,0x14,0x06,0x07,0x01,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x35,0x34,0x2e,0x02,0x02,0x1e,0x18,0x5d,0x3d,0xe9, 0x93,0x6a,0x31,0x5a,0x7d,0x4c,0x84,0x57,0x65,0x7a,0xa8,0x0d,0x32,0x61,0x54,0xdf,0x3d,0x39,0xfe,0xdd,0x65,0x1a,0x3c,0x61,0x47,0x58,0x18,0x38,0x5d,0x01,0x31,0x13,0x3c,0x20,0x7a,0xc3,0xa3,0x51,0x52,0x8d,0x40,0x6b,0x4d,0x2b,0x2b,0x9e,0x3e,0x90,0x1c,0x2f,0x32,0x3a,0x28,0x6a,0xbb,0x4c,0x7b,0x35,0x01,0xd1,0x33,0x6c,0x25,0x3d, 0x39,0x39,0x20,0x43,0x69,0x24,0x3b,0x36,0x35,0x00,0x00,0x01,0x00,0x00,0x01,0xfa,0x0b,0xf2,0x02,0x7b,0x00,0x03,0x00,0x00,0x01,0x21,0x35,0x21,0x0b,0xf2,0xf4,0x0e,0x0b,0xf2,0x01,0xfa,0x81,0x00,0x00,0x01,0x00,0x00,0x01,0xfa,0x0f,0xfe,0x02,0x7b,0x00,0x03,0x00,0x00,0x01,0x21,0x35,0x21,0x0f,0xfe,0xf0,0x02,0x0f,0xfe,0x01,0xfa, 0x81,0x00,0x00,0x01,0x00,0x25,0x06,0x12,0x02,0x7d,0x09,0x46,0x00,0x1f,0x00,0x00,0x01,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x1e,0x03,0x33,0x32,0x36,0x37,0x02,0x7d,0x5c,0x85,0x55,0x8a,0x62,0x36,0x3a,0x67,0x8f,0x56,0x74,0x5e,0x6b,0x68,0x6b,0x8d,0x0e,0x01, 0x54,0xfe,0xac,0x06,0x2a,0x42,0x58,0x35,0x39,0x6d,0x34,0x06,0x44,0x32,0x3a,0x68,0x92,0x58,0x60,0x9c,0x6f,0x3d,0x25,0x7c,0x38,0x83,0x7b,0x69,0x39,0x5d,0x42,0x23,0x1f,0x21,0x00,0x01,0x00,0x5b,0x06,0x20,0x02,0xe6,0x09,0x3a,0x00,0x09,0x00,0x00,0x01,0x23,0x11,0x01,0x23,0x11,0x33,0x11,0x01,0x33,0x02,0xe6,0x78,0xfe,0x76,0x89, 0x78,0x01,0x87,0x8c,0x06,0x20,0x02,0x64,0xfd,0x9c,0x03,0x1a,0xfd,0x9e,0x02,0x62,0x00,0x03,0xff,0xda,0x06,0x1f,0x01,0x31,0x09,0x2f,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x00,0x13,0x23,0x11,0x33,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xc2,0x76, 0x76,0x2c,0x1b,0x28,0x27,0x1b,0x1d,0x27,0x26,0xeb,0x1d,0x29,0x28,0x1c,0x1c,0x29,0x28,0x06,0x1f,0x02,0x3e,0x51,0x24,0x1c,0x1c,0x25,0x25,0x1c,0x1b,0x25,0x26,0x1a,0x1c,0x25,0x25,0x1c,0x1b,0x25,0x00,0x01,0xff,0xf7,0x05,0x1c,0x02,0x26,0x08,0x5d,0x00,0x14,0x00,0x00,0x01,0x01,0x06,0x06,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32, 0x36,0x37,0x37,0x26,0x02,0x27,0x33,0x13,0x13,0x02,0x26,0xfe,0xfc,0x22,0x68,0x41,0x12,0x24,0x12,0x2b,0x17,0x1b,0x2e,0x0e,0x2a,0x35,0x70,0x36,0x80,0x97,0x9e,0x08,0x5d,0xfd,0x72,0x55,0x5e,0x05,0x06,0x68,0x0f,0x25,0x23,0x65,0x89,0x01,0x1e,0x89,0xfe,0x53,0x01,0xad,0x00,0x02,0x00,0x0c,0x06,0x1f,0x02,0xe6,0x09,0x39,0x00,0x0e, 0x00,0x16,0x00,0x00,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x23,0xea,0xde,0x01,0x55,0x84,0x79,0x88,0x25,0x45,0x62,0x3d,0x7c,0x71,0x48,0x50,0x98,0x06,0x1f,0x02,0xb0,0x6a,0xfe,0xb9,0x74,0x6e,0x37,0x59,0x3f,0x22,0x01,0x6b,0xfe,0xff,0x44,0x3e,0x7f,0x00,0x03, 0x00,0x5b,0x06,0x1f,0x03,0x0c,0x09,0x39,0x00,0x03,0x00,0x10,0x00,0x18,0x00,0x00,0x01,0x23,0x11,0x33,0x01,0x11,0x33,0x11,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x23,0x03,0x0c,0x77,0x77,0xfd,0x4f,0x78,0x83,0x7a,0x88,0x25,0x45,0x62,0x3d,0x7c,0x71,0x48,0x50,0x98,0x06,0x1f,0x03,0x1a,0xfc, 0xe6,0x03,0x1a,0xfe,0xb9,0x75,0x6d,0x37,0x59,0x3f,0x22,0x01,0x6b,0xfe,0xff,0x43,0x3f,0x7f,0x00,0x02,0x00,0x5a,0x06,0x1f,0x02,0x57,0x09,0x39,0x00,0x0c,0x00,0x14,0x00,0x00,0x13,0x11,0x33,0x11,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x23,0x5a,0x78,0x83,0x7a,0x88,0x25,0x45,0x62,0x3d,0x7c, 0x71,0x48,0x50,0x98,0x06,0x1f,0x03,0x1a,0xfe,0xb9,0x75,0x6d,0x37,0x59,0x3f,0x22,0x01,0x6b,0xfe,0xff,0x43,0x3f,0x7f,0x00,0x00,0x01,0x00,0x1e,0x06,0x1f,0x03,0xd5,0x09,0x39,0x00,0x2d,0x00,0x00,0x01,0x2e,0x05,0x27,0x33,0x1e,0x03,0x17,0x13,0x2e,0x03,0x27,0x33,0x1e,0x03,0x17,0x3e,0x05,0x37,0x33,0x0e,0x05,0x07,0x23,0x26,0x26, 0x27,0x03,0x01,0x19,0x2b,0x41,0x31,0x24,0x1c,0x14,0x0a,0x79,0x0c,0x20,0x2b,0x38,0x26,0x6b,0x0c,0x12,0x0f,0x0d,0x06,0x78,0x0d,0x1f,0x2b,0x39,0x26,0x1a,0x2a,0x23,0x1c,0x18,0x14,0x09,0x78,0x09,0x15,0x1b,0x24,0x32,0x40,0x2b,0x6b,0x2a,0x3f,0x18,0x68,0x06,0x1f,0x53,0x89,0x7b,0x73,0x7a,0x86,0x50,0x6c,0xa7,0x90,0x89,0x4f,0x01, 0x11,0x28,0x52,0x59,0x60,0x37,0x6e,0xa6,0x91,0x89,0x51,0x36,0x5f,0x5d,0x5f,0x6a,0x7a,0x4a,0x51,0x86,0x7a,0x74,0x7a,0x89,0x52,0x51,0x83,0x3c,0xfe,0xf0,0x00,0x01,0x00,0x5c,0x06,0x12,0x03,0xfb,0x09,0x46,0x00,0x27,0x00,0x00,0x01,0x06,0x23,0x22,0x2e,0x02,0x27,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x3e,0x03,0x33,0x32,0x16,0x17, 0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x15,0x21,0x1e,0x03,0x33,0x32,0x36,0x37,0x03,0xfb,0x5e,0x84,0x50,0x84,0x61,0x3a,0x06,0xcf,0x79,0x79,0xd1,0x09,0x40,0x66,0x86,0x4e,0x3b,0x68,0x2f,0x6d,0x66,0x6c,0x8d,0x0d,0x01,0x53,0xfe,0xac,0x06,0x2a,0x42,0x58,0x35,0x39,0x6d,0x35,0x06,0x44,0x32,0x33,0x5e,0x83,0x50,0xfe,0xa9,0x03,0x1a, 0xfe,0xa6,0x52,0x85,0x5d,0x33,0x13,0x12,0x7c,0x38,0x83,0x7b,0x69,0x39,0x5d,0x42,0x23,0x1f,0x21,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x79,0x07,0x71,0x00,0x03,0x00,0x17,0x00,0x00,0x21,0x23,0x11,0x33,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x02,0x79,0x94,0x94,0xfe,0x5a,0x17,0x28, 0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x07,0x58,0xc8,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x79,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x21,0x23,0x11,0x33,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x02,0x02,0x79,0x94,0x94,0xfe,0x5a,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x07,0x58,0xfd,0xa3,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x79,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x21,0x23, 0x11,0x33,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x02,0x79,0x94,0x94,0xfe,0x5a,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x07,0x58,0xfb,0xe1,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x02,0x00,0x64, 0x00,0x00,0x02,0x79,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x21,0x23,0x11,0x33,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x02,0x79,0x94,0x94,0xfe,0x5a,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x07,0x58,0xfa,0x1f,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f, 0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x02,0x00,0x64,0xff,0xf1,0x02,0x79,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x21,0x23,0x11,0x33,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x02,0x79,0x94,0x94,0xfe,0x5a,0x17,0x28,0x1e,0x12,0x12,0x1e,0x28,0x17,0x17,0x29,0x1f,0x12, 0x12,0x1f,0x29,0x07,0x58,0xf8,0x99,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x02,0x00,0x96,0x00,0x00,0x02,0xab,0x07,0x71,0x00,0x03,0x00,0x17,0x00,0x00,0x13,0x33,0x11,0x23,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x96,0x94,0x94,0x01, 0xa6,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x28,0x07,0x58,0xf8,0xa8,0x06,0x90,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x02,0x00,0x96,0x00,0x00,0x02,0xab,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x13,0x33,0x11,0x23,0x01,0x22,0x2e,0x02,0x35,0x34, 0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x96,0x94,0x94,0x01,0xa6,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x28,0x07,0x58,0xf8,0xa8,0x04,0xfb,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x02,0x00,0x96,0x00,0x00,0x02,0xab,0x07,0x58,0x00,0x03, 0x00,0x17,0x00,0x00,0x13,0x33,0x11,0x23,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x96,0x94,0x94,0x01,0xa6,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x28,0x07,0x58,0xf8,0xa8,0x03,0x39,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29, 0x1e,0x12,0x00,0x02,0x00,0x96,0x00,0x00,0x02,0xab,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x13,0x33,0x11,0x23,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x96,0x94,0x94,0x01,0xa6,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x28,0x07,0x58,0xf8,0xa8,0x01,0x77, 0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x02,0x00,0x96,0xff,0xf1,0x02,0xab,0x07,0x58,0x00,0x03,0x00,0x17,0x00,0x00,0x13,0x33,0x11,0x23,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x96,0x94,0x94,0x01,0xa6,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29, 0x17,0x16,0x29,0x1e,0x12,0x12,0x1e,0x28,0x07,0x58,0xf8,0xa8,0x0f,0x12,0x1e,0x29,0x17,0x17,0x29,0x1f,0x12,0x12,0x1f,0x29,0x17,0x17,0x29,0x1e,0x12,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0x5f,0x07,0x58,0x00,0x05,0x00,0x00,0x01,0x21,0x11,0x23,0x11,0x21,0x03,0x5f,0xfd,0xcb,0x94,0x02,0xc9,0x06,0xd4,0xf9,0x2c,0x07,0x58,0x00, 0x00,0x01,0x00,0x96,0x00,0x00,0x03,0x5f,0x07,0x58,0x00,0x07,0x00,0x00,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x03,0x5f,0xfd,0xcb,0x94,0x94,0x02,0x35,0x05,0x1f,0xfa,0xe1,0x07,0x58,0xfe,0x4b,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0x5f,0x07,0x58,0x00,0x07,0x00,0x00,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x03,0x5f,0xfd,0xcb, 0x94,0x94,0x02,0x35,0x03,0x6a,0xfc,0x96,0x07,0x58,0xfc,0x96,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0x5f,0x07,0x58,0x00,0x07,0x00,0x00,0x01,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x03,0x5f,0xfd,0xcb,0x94,0x94,0x02,0x35,0x01,0xb5,0xfe,0x4b,0x07,0x58,0xfa,0xe1,0x00,0x01,0x00,0x96,0x00,0x00,0x03,0x5f,0x07,0x58,0x00,0x05,0x00,0x00, 0x13,0x33,0x11,0x21,0x15,0x21,0x96,0x94,0x02,0x35,0xfd,0x37,0x07,0x58,0xf9,0x2c,0x84,0x00,0x00,0x04,0x00,0xb4,0xfe,0x31,0x09,0xec,0x07,0x69,0x00,0x0e,0x00,0x26,0x00,0x3a,0x00,0x46,0x00,0x5f,0xb9,0x00,0x0e,0x01,0x43,0xb2,0x07,0x0d,0x36,0xbb,0x01,0x43,0x00,0x20,0x00,0x16,0x01,0x43,0x40,0x0c,0x2c,0x0d,0x20,0x2c,0x2c,0x20, 0x0d,0x03,0x3b,0x41,0x3b,0x44,0xbc,0x01,0x42,0x00,0x3e,0x01,0x41,0x00,0x27,0x01,0x44,0xb2,0x1b,0x07,0x31,0xb8,0x01,0x44,0x40,0x0c,0x0f,0x19,0x0e,0x18,0x04,0x0c,0x01,0x0c,0x06,0x07,0x00,0x07,0x00,0x3f,0xde,0xce,0x33,0x5d,0x3f,0x3f,0xe6,0x3f,0xe6,0x3f,0x3f,0x01,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xe6,0x10,0xe6, 0x10,0xcd,0xe6,0x30,0x31,0x01,0x23,0x0e,0x03,0x07,0x15,0x3e,0x03,0x37,0x11,0x33,0x05,0x32,0x3e,0x04,0x35,0x34,0x02,0x26,0x26,0x23,0x22,0x06,0x06,0x02,0x15,0x14,0x1e,0x04,0x13,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x01,0x10,0x00,0x21,0x20,0x00,0x11,0x10,0x00,0x21,0x20,0x00,0x04,0x2f, 0x7a,0x26,0x68,0x75,0x79,0x36,0x30,0x65,0x5b,0x49,0x13,0xe0,0x02,0x8f,0x64,0x8f,0x62,0x3b,0x20,0x0a,0x2c,0x61,0x9d,0x70,0x75,0xa8,0x6c,0x33,0x0f,0x24,0x3c,0x5c,0x7e,0x6a,0x3a,0x4a,0x2b,0x10,0x11,0x2c,0x4d,0x3b,0x3c,0x4e,0x2d,0x12,0x12,0x2f,0x50,0xfa,0x1d,0x02,0xb7,0x01,0xe5,0x01,0xe5,0x02,0xb7,0xfd,0x49,0xfe,0x1b,0xfe, 0x1b,0xfd,0x49,0x05,0xba,0x21,0x45,0x3f,0x33,0x0f,0xce,0x0c,0x2a,0x30,0x31,0x13,0xfb,0x51,0x18,0x45,0x73,0x98,0xa6,0xa9,0x4c,0xb8,0x01,0x13,0xb8,0x5c,0x62,0xc2,0xfe,0xe0,0xbe,0x58,0xae,0x9f,0x87,0x64,0x38,0x05,0x0d,0x46,0x8d,0xd3,0x8d,0x87,0xcc,0x87,0x44,0x42,0x85,0xc8,0x85,0x8f,0xd7,0x8f,0x48,0xfd,0xd8,0x01,0xe5,0x02, 0xb7,0xfd,0x49,0xfe,0x1b,0xfe,0x1b,0xfd,0x49,0x02,0xb7,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x04,0x08,0x05,0x9a,0x00,0x1a,0x00,0x27,0x00,0x5c,0x40,0x35,0x76,0x15,0x01,0x59,0x22,0x69,0x22,0x89,0x22,0x03,0x22,0x15,0x29,0x05,0x01,0x1c,0x09,0x0d,0x0b,0x06,0x0f,0x07,0x03,0x02,0x0a,0x02,0x0b,0x1a,0x1d,0x0e,0x1d,0x2f,0x02,0x6f, 0x02,0x7f,0x02,0xbf,0x02,0x04,0x2f,0x1d,0x01,0x02,0x1d,0x02,0x1d,0x05,0x27,0x0f,0x06,0x05,0x18,0x00,0x3f,0x3f,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x11,0x33,0x10,0xcd,0x32,0x11,0x33,0x10,0xcd,0x32,0x01,0x2f,0x33,0x33,0xce,0x32,0xcd,0x32,0x32,0x10,0xde,0xcd,0x5d,0x5d,0x30,0x31,0x01,0x15,0x21,0x15,0x21,0x11,0x23,0x11, 0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x01,0x5b,0x01,0x82,0xfe,0x7e,0xa4,0x77,0x77,0x77,0x77,0x01,0x84,0x5c,0xa7,0x7f,0x4b,0x43,0x80,0xb8,0x76,0xbc,0xa7,0x57,0x85,0x5b,0x2e,0x2a,0x54,0x7e,0x54,0x02,0x7f,0xcf,0x8b,0xfe, 0xdb,0x01,0x25,0x8b,0xcf,0x8b,0x02,0x90,0x2f,0x60,0x92,0x63,0x66,0x98,0x66,0x33,0x02,0x90,0xfd,0xfb,0x1b,0x3d,0x64,0x48,0x47,0x62,0x3d,0x1b,0x00,0x01,0x00,0x32,0x00,0x00,0x05,0xe6,0x05,0x9a,0x00,0x27,0x00,0x57,0x40,0x35,0x67,0x25,0x01,0x00,0x12,0x25,0x13,0x13,0x1e,0x0a,0x0f,0x07,0x3f,0x07,0x02,0x07,0x29,0x1b,0x5f,0x1e, 0x6f,0x1e,0x8f,0x1e,0xaf,0x1e,0x04,0x1e,0x78,0x11,0x88,0x11,0x02,0x11,0x5b,0x14,0x01,0x3a,0x14,0x4a,0x14,0x02,0x14,0x00,0x25,0x25,0x13,0x27,0x06,0x1c,0x09,0x13,0x18,0x00,0x3f,0x33,0x33,0x3f,0x12,0x39,0x2f,0x33,0xcd,0x5d,0x5d,0x32,0x5d,0x01,0x2f,0x5d,0xcd,0x10,0xde,0x5d,0xcd,0x12,0x39,0x2f,0x33,0xcd,0x32,0x00,0x5d,0x30, 0x31,0x01,0x1e,0x04,0x12,0x15,0x15,0x23,0x35,0x34,0x2e,0x04,0x27,0x11,0x23,0x11,0x0e,0x05,0x15,0x15,0x23,0x35,0x34,0x12,0x3e,0x03,0x37,0x11,0x33,0x03,0x5e,0x55,0xa3,0x90,0x78,0x57,0x31,0xa4,0x27,0x45,0x5d,0x6c,0x75,0x3a,0xa4,0x39,0x73,0x6c,0x5e,0x46,0x28,0xa4,0x32,0x58,0x7a,0x90,0xa1,0x53,0xa4,0x04,0x6d,0x09,0x39,0x65, 0x95,0xcd,0xfe,0xf9,0xa5,0xb8,0xbf,0x91,0xe3,0xac,0x79,0x51,0x2c,0x09,0xfc,0x22,0x03,0xe0,0x08,0x2a,0x4f,0x7a,0xad,0xe5,0x94,0xbf,0xb8,0xa8,0x01,0x0b,0xce,0x95,0x63,0x35,0x08,0x01,0x2c,0x00,0x00,0x16,0x00,0x26,0x00,0x00,0x07,0x15,0x05,0xc0,0x00,0x05,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23, 0x00,0x27,0x00,0x2d,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x57,0x00,0x5c,0x00,0x62,0x00,0x7c,0x00,0x00,0x13,0x35,0x33,0x15,0x23,0x15,0x03,0x35,0x33,0x15,0x33,0x15,0x33,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x13,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x01,0x23, 0x35,0x33,0x35,0x23,0x35,0x33,0x25,0x35,0x33,0x15,0x23,0x35,0x03,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0x23,0x35,0x33,0x01,0x23,0x27,0x23,0x07,0x23,0x13,0x33,0x13,0x27,0x27,0x15,0x07,0x05,0x21,0x11,0x33,0x11, 0x33,0x05,0x23,0x11,0x34,0x34,0x37,0x03,0x23,0x03,0x15,0x11,0x23,0x11,0x33,0x13,0x16,0x16,0x17,0x36,0x37,0x3e,0x03,0x37,0x33,0x26,0xeb,0x96,0x55,0x55,0x96,0x5b,0xd3,0xd3,0xd3,0x5e,0xd1,0xfd,0x0d,0x55,0x55,0x02,0x22,0xd1,0xfd,0x0d,0x55,0x55,0x55,0x55,0x05,0xae,0xec,0x56,0x96,0x96,0x56,0xfd,0xe6,0xd2,0x01,0x48,0x56,0x56, 0x56,0x56,0xfc,0xb7,0xd1,0xd1,0xd1,0x5e,0xd2,0x01,0x48,0x56,0x56,0xfb,0x91,0x50,0x35,0xc6,0x32,0x50,0xc2,0x48,0x28,0x4d,0x01,0x4b,0x02,0x7d,0xfe,0xed,0x4a,0xc9,0x02,0x4a,0x4b,0x01,0xa9,0x28,0xaa,0x48,0x5b,0x9a,0x08,0x04,0x05,0x0a,0x08,0x12,0x28,0x29,0x28,0x12,0x58,0x04,0xd4,0xec,0x55,0x97,0xfb,0x2c,0xeb,0x95,0x56,0x56, 0x56,0x05,0x6b,0x55,0x55,0xfa,0x95,0x56,0x56,0x01,0x48,0xd2,0x03,0x51,0x55,0x55,0xfd,0x0c,0xd1,0x5e,0xd2,0xf3,0x55,0xec,0x97,0xfa,0x95,0x56,0x95,0xeb,0x56,0x56,0x01,0x48,0xd2,0x01,0x8c,0xd2,0xfb,0x88,0x56,0x56,0x05,0x6b,0x55,0x55,0x55,0x55,0xfd,0x0c,0xd1,0xfe,0xb6,0x8c,0x8c,0x01,0xfb,0xfe,0xce,0xcf,0x02,0x02,0xcf,0xc9, 0x01,0xfb,0xfe,0x42,0x3d,0x01,0x53,0x09,0x14,0x0b,0xfe,0x85,0x01,0x7b,0x29,0xfe,0xae,0x01,0xfb,0xfe,0xa2,0x12,0x0f,0x09,0x1b,0x10,0x28,0x59,0x5c,0x59,0x27,0x00,0x00,0x01,0x00,0xbc,0xfe,0x96,0x06,0x72,0x05,0x9a,0x00,0x26,0x00,0x1f,0x40,0x10,0x0e,0x16,0x21,0x03,0x1c,0x1d,0x03,0x08,0x03,0x03,0x1c,0x12,0x12,0x12,0x00,0x03, 0x00,0x3f,0x3f,0x3f,0x33,0x2f,0x33,0x3f,0x12,0x17,0x39,0x30,0x31,0x01,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x34,0x36,0x37,0x23,0x06,0x07,0x01,0x23,0x01,0x26,0x27,0x23,0x16,0x16,0x15,0x11,0x23,0x11,0x33,0x01,0x16,0x17,0x33,0x36,0x36,0x37,0x01,0x06,0x72,0xfe,0xaf,0x3f,0x39,0x32,0x3e,0xb2,0x07,0x07,0x04, 0x18,0x13,0xfe,0x16,0x52,0xfe,0x17,0x14,0x17,0x04,0x04,0x04,0xa2,0xde,0x01,0xb8,0x33,0x0f,0x06,0x16,0x22,0x0d,0x01,0xc1,0x05,0x9a,0xfa,0x9b,0xfe,0x61,0x14,0xa0,0x1d,0x01,0x08,0x03,0x8d,0x39,0x8b,0x53,0x63,0x28,0xfb,0xb2,0x04,0x46,0x2e,0x65,0x2b,0x8c,0x62,0xfc,0x40,0x05,0x9a,0xfc,0x18,0x74,0x38,0x3c,0x57,0x1d,0x03,0xe4, 0x00,0x02,0x00,0x16,0x00,0x00,0x05,0x12,0x05,0x9a,0x00,0x07,0x00,0x11,0x00,0x1a,0x40,0x0c,0x11,0x0d,0x06,0x02,0x02,0x01,0x06,0x12,0x04,0x03,0x01,0x03,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0x33,0x30,0x31,0x13,0x33,0x13,0x21,0x13,0x33,0x01,0x23,0x03,0x13,0x16,0x16,0x17,0x33,0x36,0x36,0x37,0x13,0x16,0xba,0x98,0x02, 0x60,0x8f,0xbb,0xfd,0xda,0xae,0x9f,0xe1,0x05,0x0c,0x05,0x04,0x05,0x0b,0x07,0xdf,0x05,0x9a,0xfe,0x6e,0x01,0x92,0xfa,0x66,0x03,0x71,0xfd,0x9d,0x0f,0x30,0x21,0x1f,0x30,0x11,0x02,0x63,0xff,0xff,0x00,0x60,0xfe,0x96,0x03,0x62,0x04,0x18,0x02,0x26,0x00,0x46,0x00,0x00,0x00,0x07,0x08,0x5d,0x02,0x89,0x00,0x00,0xff,0xff,0x00,0xa6, 0xfe,0x96,0x04,0x91,0x05,0xec,0x02,0x26,0x00,0x4b,0x00,0x00,0x00,0x07,0x08,0x5d,0x03,0xba,0x00,0x00,0x00,0x03,0x00,0x6e,0x00,0x00,0x05,0x5b,0x05,0x9a,0x00,0x2a,0x00,0x32,0x00,0x3c,0x00,0x29,0x40,0x15,0x1f,0x35,0x91,0x2b,0x13,0x91,0x01,0x01,0x2b,0x0a,0x2b,0x0a,0x00,0x3c,0x91,0x14,0x03,0x2c,0x91,0x00,0x12,0x00,0x3f,0xed, 0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x33,0x2f,0xed,0x10,0xed,0x39,0x30,0x31,0x21,0x11,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x23,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x11,0x33,0x32,0x3e, 0x02,0x35,0x34,0x21,0x01,0xe8,0x47,0x28,0x3b,0x27,0x13,0x06,0x05,0x98,0x09,0x28,0x4b,0x6a,0x41,0x5c,0x01,0x98,0x5d,0x95,0x69,0x39,0x22,0x40,0x5c,0x3a,0x48,0x75,0x54,0x2e,0x47,0x7c,0xab,0x63,0xfa,0xe4,0x95,0xa2,0xfe,0xa6,0xc1,0xac,0x45,0x6e,0x4c,0x29,0xfe,0xed,0x02,0x9c,0x17,0x25,0x31,0x1a,0x0f,0x2c,0x13,0x30,0x29,0x47, 0x67,0x44,0x20,0x02,0x68,0x30,0x57,0x78,0x49,0x3d,0x6b,0x58,0x41,0x13,0x04,0x08,0x38,0x5a,0x7a,0x4a,0x5c,0x98,0x6c,0x3c,0x02,0x9c,0xfd,0xfc,0x8b,0x7b,0xfe,0x02,0x66,0xfe,0x31,0x22,0x41,0x5f,0x3c,0xd1,0x00,0x02,0x00,0x75,0xfe,0xab,0x05,0x80,0x05,0xec,0x00,0x30,0x00,0x43,0x00,0x24,0x40,0x14,0x12,0x0f,0x21,0x03,0x15,0x23, 0x15,0x2d,0x96,0x05,0x36,0x95,0x1f,0x15,0x40,0x95,0x15,0x10,0x11,0x00,0x00,0x3f,0x3f,0xed,0x3f,0xed,0xdc,0xed,0x3f,0x12,0x17,0x39,0x30,0x31,0x05,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x11,0x33,0x11,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x27,0x23,0x15,0x23,0x11,0x0e,0x03,0x15,0x14, 0x16,0x33,0x32,0x36,0x37,0x03,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x03,0x4d,0x10,0x3c,0x4c,0x54,0x27,0x7d,0xac,0x6c,0x30,0x2b,0x57,0x83,0x58,0xa4,0x46,0x9f,0x5b,0x66,0xa9,0x78,0x43,0x40,0x79,0xad,0x6d,0xcc,0x67,0x04,0xa4,0x2f,0x44,0x2c,0x16,0x8d,0x98,0x3f,0x77,0x27,0xa9,0x2b,0x4e, 0x6b,0x40,0x4b,0x76,0x52,0x2b,0x22,0x50,0x83,0x61,0x4e,0x85,0x39,0xf7,0x12,0x22,0x1a,0x10,0x44,0x79,0xa9,0x65,0x4c,0xc0,0xc9,0xc3,0x4e,0x02,0x90,0xfd,0xe0,0x23,0x29,0x48,0x85,0xbb,0x72,0x7f,0xd1,0x94,0x52,0xac,0x94,0x02,0x9c,0x41,0x91,0x92,0x89,0x39,0xa8,0xae,0x1d,0x19,0x02,0x4c,0x3f,0x6f,0x52,0x30,0x3b,0x70,0x9f,0x65, 0x46,0x83,0x66,0x3d,0x2b,0x25,0x00,0x01,0xff,0x9a,0xfe,0x96,0x03,0x94,0x05,0x9a,0x00,0x15,0x00,0x20,0x40,0x10,0x14,0x91,0x01,0x01,0x09,0x91,0x06,0x06,0x02,0x11,0x91,0x0c,0x04,0x91,0x02,0x03,0x00,0x3f,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x33,0x2f,0xed,0x30,0x31,0x03,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x10, 0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x23,0x1f,0xdb,0x02,0xd8,0xfd,0xd0,0x01,0x20,0xfe,0xe0,0xfe,0xae,0x3f,0x39,0x32,0x3e,0xb2,0xdb,0x03,0x12,0x02,0x88,0x98,0xfe,0x10,0x97,0xfd,0xba,0xfe,0x61,0x14,0xa0,0x1d,0x01,0x08,0x02,0x46,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x02,0xa0,0x06,0x02,0x00,0x1d,0x00,0x33,0xb6,0x05, 0x95,0x08,0x08,0x02,0x95,0x1d,0xb8,0xff,0xc0,0x40,0x14,0x09,0x0c,0x48,0x1d,0x1d,0x03,0x1c,0x95,0x19,0x0f,0x16,0x95,0x11,0x00,0x09,0x95,0x0c,0x0f,0x03,0x15,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x2b,0xed,0x33,0x2f,0xed,0x30,0x31,0x01,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x34, 0x37,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x15,0x02,0x77,0xf0,0xa3,0xaf,0xaf,0xaf,0xaf,0x5d,0x5d,0x8b,0x4b,0x2c,0x30,0x3d,0xac,0xf0,0xf0,0x03,0x06,0x8c,0xfd,0x86,0x02,0x7a,0x8c,0x6e,0x8c,0xa6,0xa1,0x5d,0x5e,0x12,0x94,0x1b,0xd9,0x9e,0x8c,0x6e,0x00,0x02,0x00,0x5e,0xff,0xe8,0x04,0x8e,0x05,0xb2, 0x00,0x21,0x00,0x3d,0x00,0x26,0x40,0x14,0x0f,0x36,0x92,0x35,0x35,0x00,0x21,0x03,0x1f,0x2d,0x91,0x1a,0x04,0x02,0x22,0x92,0x05,0x13,0x00,0x12,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x21,0x23,0x35,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x35,0x34,0x3e, 0x02,0x33,0x32,0x1e,0x02,0x17,0x35,0x33,0x01,0x32,0x3e,0x02,0x37,0x11,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x15,0x22,0x06,0x15,0x14,0x1e,0x02,0x04,0x8e,0xa8,0x4e,0xd4,0x83,0x6c,0xb1,0x80,0x46,0x2d,0x54,0x77,0x4a,0x44,0x66,0x44,0x22,0x43,0x79,0xab,0x68,0x3b,0x70,0x64,0x56,0x22,0xa8,0xfd,0xbe,0x4d,0x7b,0x63, 0x4e,0x21,0x21,0x54,0x63,0x72,0x3f,0x47,0x69,0x46,0x23,0xae,0x9d,0xc2,0xbc,0x30,0x55,0x73,0x8c,0x4b,0x59,0x3f,0x72,0x9e,0x5f,0x45,0x77,0x5a,0x3a,0x08,0x04,0x12,0x38,0x4f,0x6a,0x44,0x54,0x8b,0x63,0x37,0x14,0x23,0x31,0x1d,0x6d,0xfa,0xdd,0x27,0x40,0x52,0x2c,0x02,0xf3,0x2d,0x4b,0x36,0x1d,0x23,0x40,0x59,0x35,0x7e,0x80,0x8b, 0x8a,0x8a,0x3e,0x66,0x49,0x28,0x00,0x02,0x00,0x60,0xff,0xe8,0x03,0x97,0x04,0x19,0x00,0x1f,0x00,0x3d,0x00,0x26,0x40,0x14,0x0f,0x36,0x96,0x34,0x34,0x01,0x1f,0x0f,0x1d,0x2b,0x95,0x18,0x10,0x02,0x20,0x95,0x05,0x16,0x01,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x21,0x23,0x35,0x06, 0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x35,0x33,0x01,0x32,0x3e,0x02,0x37,0x11,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x03,0x97,0xa4,0x3c,0x8d,0x5f,0x4f,0x85,0x61,0x36,0x24,0x42,0x5d,0x39,0x64, 0x6f,0x36,0x5d,0x7c,0x47,0x2e,0x52,0x45,0x39,0x16,0xa4,0xfe,0x54,0x24,0x4a,0x45,0x3e,0x17,0x16,0x38,0x41,0x48,0x25,0x37,0x4d,0x31,0x16,0x6d,0x7b,0x06,0x0b,0x4a,0x67,0x3f,0x1c,0x78,0x5d,0x34,0x41,0x2b,0x4f,0x71,0x46,0x34,0x57,0x41,0x28,0x05,0x05,0x15,0x6c,0x5a,0x45,0x6d,0x4c,0x29,0x12,0x1c,0x23,0x12,0x4a,0xfc,0x71,0x10, 0x1e,0x2e,0x1e,0x02,0x28,0x1b,0x2d,0x21,0x12,0x19,0x2b,0x3c,0x22,0x51,0x4c,0x81,0x17,0x2c,0x42,0x2a,0x57,0x57,0x00,0x02,0x00,0x5e,0xff,0xe8,0x05,0x14,0x05,0xb2,0x00,0x1e,0x00,0x39,0x00,0x1c,0x40,0x0e,0x0a,0x28,0x92,0x27,0x27,0x00,0x1f,0x91,0x15,0x04,0x30,0x92,0x00,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39, 0x30,0x31,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x06,0x03,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x15,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x02,0x6a,0x7b,0xc3,0x87,0x47,0x2d,0x54,0x77,0x4a,0x44,0x66,0x44, 0x22,0x44,0x80,0xb8,0x74,0x94,0xf3,0xae,0x5f,0x62,0xb3,0xfb,0x90,0x50,0x72,0x4b,0x23,0xae,0x9d,0xc2,0xbc,0x31,0x58,0x7a,0x4a,0x75,0xc0,0x87,0x4a,0x46,0x81,0xb7,0x18,0x3f,0x72,0x9e,0x5f,0x45,0x77,0x5a,0x3a,0x08,0x04,0x12,0x38,0x4f,0x6a,0x44,0x54,0x8b,0x63,0x37,0x6a,0xbf,0xfe,0xf6,0xa0,0xaa,0xfe,0xe9,0xc8,0x6e,0x05,0x32, 0x23,0x40,0x59,0x35,0x7e,0x80,0x8b,0x8a,0x8a,0x3e,0x66,0x49,0x28,0x52,0x99,0xdc,0x8a,0x8f,0xde,0x97,0x4e,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x10,0x04,0x19,0x00,0x1c,0x00,0x3b,0x00,0x1e,0x40,0x0f,0x00,0x1c,0x1d,0x96,0x3b,0x3b,0x08,0x26,0x95,0x12,0x16,0x30,0x95,0x08,0x10,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed, 0x39,0x39,0x30,0x31,0x01,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x17,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x33,0x01,0x5c,0x64,0x6f,0x38,0x68,0x96,0x5d,0x6f,0xb8, 0x84,0x49,0x49,0x87,0xc0,0x78,0x63,0x9d,0x6d,0x3b,0x24,0x42,0x5d,0x39,0xbe,0x0b,0x4a,0x67,0x3f,0x1c,0x80,0x89,0x54,0x82,0x58,0x2e,0x24,0x50,0x82,0x5e,0x37,0x56,0x3c,0x1f,0x18,0x36,0x59,0x41,0x06,0x02,0x17,0x15,0x6c,0x5a,0x45,0x6d,0x4c,0x29,0x43,0x85,0xc8,0x85,0x71,0xc5,0x92,0x54,0x2b,0x4f,0x71,0x46,0x34,0x57,0x41,0x28, 0x05,0x44,0x17,0x2c,0x42,0x2a,0x57,0x57,0x3b,0x6a,0x92,0x56,0x52,0x92,0x6d,0x3f,0x19,0x2b,0x3c,0x22,0x29,0x3b,0x26,0x13,0x00,0x01,0x00,0x5e,0xff,0xe8,0x04,0x8e,0x05,0x9a,0x00,0x2b,0x00,0x21,0x40,0x11,0x0f,0x1c,0x92,0x1b,0x1b,0x00,0x2b,0x03,0x15,0x03,0x02,0x24,0x92,0x05,0x13,0x00,0x12,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f, 0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x21,0x23,0x35,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x15,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x11,0x33,0x04,0x8e,0xa8,0x4e,0xd4,0x83,0x6c,0xb1,0x80,0x46,0x2d,0x54,0x77,0x4a,0x7d,0x8a,0xa8,0x31, 0x58,0x7b,0x4a,0xc2,0xbc,0x30,0x55,0x73,0x43,0x4d,0x7b,0x63,0x4e,0x21,0xa8,0x8c,0x4b,0x59,0x3f,0x72,0x9e,0x5f,0x45,0x77,0x5a,0x3a,0x08,0x04,0x22,0x87,0x74,0x01,0x8b,0xfe,0x76,0x39,0x56,0x39,0x1d,0x8b,0x8a,0x8a,0x3e,0x66,0x49,0x28,0x27,0x40,0x52,0x2c,0x04,0x3e,0x00,0x01,0x00,0x60,0xff,0xe8,0x03,0x97,0x04,0x00,0x00,0x2b, 0x00,0x21,0x40,0x11,0x0f,0x1b,0x96,0x1a,0x1a,0x00,0x2b,0x0f,0x15,0x0f,0x02,0x24,0x92,0x05,0x16,0x00,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x21,0x23,0x35,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x0e, 0x02,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x37,0x11,0x33,0x03,0x97,0xa4,0x3c,0x8d,0x5f,0x4f,0x85,0x61,0x36,0x24,0x42,0x5d,0x39,0x64,0x6f,0xa4,0x6d,0x7a,0x06,0x0b,0x4a,0x67,0x3f,0x1c,0x78,0x70,0x24,0x4a,0x45,0x3e,0x17,0xa4,0x5d,0x34,0x41,0x2b,0x4f,0x71,0x46,0x34,0x57,0x41,0x28,0x05,0x05,0x15,0x6c,0x5a,0x01,0x0e,0xfe,0xec, 0x51,0x4c,0x81,0x17,0x2c,0x42,0x2a,0x57,0x57,0x10,0x1e,0x2e,0x1e,0x03,0x15,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x03,0xe2,0x05,0xb2,0x02,0x06,0x01,0xee,0x00,0x00,0x00,0x02,0x00,0x5e,0xfe,0x1e,0x05,0x2c,0x05,0xb2,0x00,0x1f,0x00,0x36,0x00,0x25,0x40,0x14,0x19,0x91,0x16,0x2f,0x14,0x01,0x14,0x11,0x03,0x0f,0x1d,0x00,0x20,0x91, 0x0a,0x04,0x2a,0x91,0x00,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x3f,0x2f,0x5d,0x33,0xed,0x30,0x31,0x05,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x35,0x33,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x35,0x06,0x06,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04, 0x35,0x11,0x34,0x2e,0x02,0x02,0xb9,0x86,0xde,0x9f,0x58,0x5c,0xa9,0xf0,0x94,0x4e,0x80,0x66,0x4d,0x1c,0xa8,0xfd,0x6b,0xf4,0xb6,0xdf,0xc9,0xf2,0xfd,0x40,0xe1,0x80,0x6c,0xad,0x7a,0x42,0x42,0x79,0xa9,0x66,0x33,0x67,0x5f,0x53,0x3d,0x23,0x3b,0x6e,0x9a,0x18,0x6a,0xbf,0x01,0x0a,0xa1,0xac,0x01,0x18,0xc6,0x6c,0x21,0x39,0x4b,0x2a, 0xb7,0xfa,0xf0,0xfd,0x94,0x4f,0xb2,0x69,0xdf,0xdd,0x64,0x6d,0x81,0x05,0x32,0x56,0x9c,0xd9,0x84,0x84,0xd9,0x9a,0x55,0x13,0x2c,0x48,0x6a,0x90,0x5d,0x01,0x0d,0x6c,0xa2,0x6c,0x36,0x00,0x00,0x02,0x00,0x28,0x00,0x00,0x04,0x9d,0x05,0x9a,0x00,0x20,0x00,0x2c,0x00,0x32,0x40,0x1c,0x1e,0x07,0x92,0x2b,0x17,0x2b,0x23,0x92,0x11,0x8f, 0x11,0xef,0x11,0x02,0x61,0x11,0x01,0x2b,0x11,0x2b,0x11,0x01,0x15,0x03,0x1f,0x91,0x01,0x12,0x00,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x5d,0x10,0xed,0x11,0x33,0x10,0xed,0x32,0x30,0x31,0x21,0x21,0x11,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x11,0x33,0x11,0x36,0x36,0x37,0x15,0x06,0x06, 0x07,0x11,0x21,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x04,0x9d,0xfd,0x18,0x0b,0x10,0x13,0x19,0x15,0x46,0x71,0x4f,0x2b,0x23,0x3f,0x58,0x35,0x25,0x53,0x26,0xa8,0x3c,0x75,0x3c,0x3c,0x75,0x3c,0x02,0x40,0xfd,0x18,0x04,0x8f,0x2a,0x39,0x12,0x29,0x43,0x30,0x25,0x02,0x22,0x01,0x01,0x01,0x01,0x21,0x3e,0x5b,0x3a, 0x31,0x53,0x3b,0x21,0x16,0x22,0x01,0xe0,0xfd,0x43,0x1a,0x49,0x34,0xa6,0x2a,0x3f,0x17,0xfe,0x4a,0x02,0x10,0xc4,0x30,0x2a,0x1d,0x2a,0x1c,0x0d,0x00,0x01,0x00,0x02,0x00,0x00,0x03,0xe8,0x05,0x9a,0x00,0x10,0x00,0x19,0x40,0x0d,0x0e,0x12,0x04,0x10,0x0a,0x03,0x06,0x09,0x12,0x06,0x03,0x01,0x03,0x00,0x3f,0x3f,0x3f,0x12,0x17,0x39, 0x3f,0x30,0x31,0x13,0x33,0x01,0x16,0x17,0x33,0x11,0x33,0x11,0x23,0x11,0x23,0x06,0x07,0x01,0x23,0x01,0x02,0xea,0x02,0x2a,0x1f,0x07,0x04,0xa8,0xa8,0x04,0x0e,0x18,0xfd,0xe8,0xd1,0x02,0x67,0x05,0x9a,0xfd,0x70,0x25,0x0d,0x02,0xc2,0xfa,0x66,0x02,0xa2,0x16,0x1b,0xfd,0x8f,0x02,0xb0,0x00,0x00,0x01,0x00,0x29,0x00,0x00,0x04,0x0c, 0x05,0x9a,0x00,0x07,0x00,0x0f,0xb6,0x05,0x03,0x06,0x02,0x91,0x00,0x12,0x00,0x3f,0xed,0x32,0x3f,0x30,0x31,0x21,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x04,0x0c,0xfc,0x1d,0x01,0x9d,0xa8,0x01,0x9e,0x98,0x05,0x02,0xfa,0xfe,0x00,0x00,0x01,0x00,0x32,0x02,0x79,0x05,0xcc,0x03,0x21,0x00,0x03,0x00,0x08,0xb1,0x01,0x03,0x00,0x2f,0xcd, 0x30,0x31,0x01,0x15,0x21,0x35,0x05,0xcc,0xfa,0x66,0x03,0x21,0xa8,0xa8,0x00,0x03,0xff,0xf9,0xff,0xe8,0x04,0xc5,0x04,0x18,0x00,0x27,0x00,0x30,0x00,0x39,0x00,0x30,0x40,0x19,0x1c,0x0f,0x20,0x0c,0x35,0x1d,0x0f,0x19,0x14,0x04,0x2d,0x2d,0x07,0x28,0x95,0x14,0x10,0x31,0xec,0x07,0x16,0x25,0xec,0x02,0x16,0x00,0x3f,0xed,0x3f,0xed, 0x3f,0xed,0x12,0x39,0x2f,0x39,0x12,0x39,0x33,0x33,0xcd,0x32,0x32,0x3f,0x30,0x31,0x25,0x06,0x23,0x22,0x03,0x23,0x02,0x21,0x22,0x2e,0x02,0x27,0x23,0x35,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x33,0x13,0x33,0x03,0x33,0x15,0x23,0x1e,0x03,0x33,0x32,0x37,0x01,0x22,0x0e,0x02,0x07,0x21,0x26,0x26,0x03,0x32,0x36,0x37,0x21,0x1e, 0x03,0x04,0xc5,0x33,0x2c,0x9a,0x36,0x04,0x95,0xfe,0xf7,0x5a,0x94,0x6b,0x3d,0x04,0x61,0x67,0x0c,0x4d,0x79,0xa3,0x63,0x3f,0x72,0x60,0x4c,0x1a,0x04,0x55,0xac,0xab,0xa0,0xaa,0x10,0x20,0x26,0x2c,0x1c,0x16,0x12,0xfd,0x74,0x3f,0x67,0x4e,0x33,0x0a,0x02,0x53,0x2a,0x92,0x95,0x66,0xa8,0x3a,0xfd,0xb1,0x05,0x29,0x43,0x5d,0x05,0x0d, 0x01,0x25,0xfe,0xcb,0x48,0x7f,0xae,0x66,0x81,0x68,0xac,0x7c,0x44,0x26,0x4a,0x6a,0x44,0x01,0x06,0xfe,0x44,0x81,0x59,0x75,0x46,0x1d,0x05,0x02,0xf9,0x32,0x59,0x79,0x48,0xa2,0xaa,0xfc,0xe8,0xa6,0xa5,0x47,0x79,0x58,0x33,0x00,0x00,0x03,0x00,0x5a,0xff,0xe8,0x06,0x58,0x04,0x18,0x00,0x29,0x00,0x38,0x00,0x41,0x00,0x43,0x40,0x24, 0x23,0x25,0x95,0x20,0x10,0x18,0x16,0x95,0x1b,0x39,0x95,0x28,0x2a,0x95,0x14,0x08,0x0c,0x28,0x1d,0x14,0x1b,0x28,0x14,0x28,0x14,0x0c,0x1b,0x10,0x33,0x95,0x0c,0x16,0x3e,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x10,0xed,0x32,0x3f,0xed,0x32,0x30, 0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x15,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x10,0x25,0x25,0x10,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x05,0x07,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x37,0x1e,0x03,0x33,0x32,0x36,0x37,0x06,0x58,0x38, 0x6b,0x9d,0x65,0x80,0xcc,0x3e,0x04,0x91,0xf2,0x4d,0x79,0x55,0x2d,0x01,0x7f,0x01,0x06,0xd7,0xaf,0x9b,0x94,0xc8,0xdb,0x48,0x3c,0xb8,0x7b,0xdd,0x88,0x92,0xac,0x9b,0xaf,0x04,0x02,0xd3,0xfc,0x87,0xcb,0x8b,0x89,0x1b,0x33,0x49,0x2d,0x3b,0x67,0x4d,0x2c,0xa8,0x0a,0x33,0x4e,0x64,0x3a,0x79,0x86,0x01,0x01,0xd3,0x73,0xb6,0x7f,0x43, 0x7e,0x6e,0x07,0xe5,0x2a,0x4d,0x6d,0x44,0x01,0x2c,0x18,0x10,0x01,0x2a,0x7a,0xa4,0x60,0xb1,0x56,0x5b,0x62,0x9a,0x72,0xb9,0xac,0x50,0x0c,0x08,0x52,0x5f,0x24,0x3c,0x2b,0x17,0x2d,0x50,0x6c,0x3f,0x04,0x43,0x6e,0x4f,0x2c,0x9d,0x8f,0x00,0x00,0x02,0x00,0x64,0xff,0xd8,0x03,0x40,0x04,0x12,0x00,0x20,0x00,0x2a,0x00,0x22,0x40,0x0f, 0x1f,0x1e,0x14,0x21,0x1e,0x21,0x1e,0x21,0x01,0x25,0x0d,0x20,0x19,0x01,0x15,0x00,0x3f,0xcd,0x33,0x2f,0xcd,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x30,0x31,0x05,0x37,0x2e,0x03,0x35,0x11,0x34,0x3e,0x02,0x37,0x25,0x33,0x13,0x16,0x15,0x14,0x07,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x17,0x01,0x03,0x25,0x36,0x35, 0x27,0x0e,0x03,0x15,0x01,0xac,0x09,0x62,0x82,0x4d,0x20,0x07,0x10,0x1c,0x14,0x01,0x7c,0x31,0xd9,0x0f,0x1a,0xfe,0x35,0x2f,0x45,0x50,0x21,0x21,0x31,0x2d,0x2f,0x1e,0x2d,0xfe,0xaf,0x92,0x01,0x0b,0x11,0xa7,0x19,0x2b,0x1f,0x12,0x0d,0x1a,0x1e,0x4b,0x5b,0x6c,0x40,0x01,0x18,0x23,0x2d,0x20,0x17,0x0c,0xea,0xfe,0xd6,0x1a,0x09,0x0f, 0x10,0xfe,0xef,0x30,0x44,0x2d,0x15,0x07,0x13,0x21,0x19,0x2d,0xfe,0xd2,0x02,0x09,0x9a,0x0b,0x07,0xf1,0x10,0x1a,0x23,0x35,0x2c,0x00,0x00,0x02,0x00,0x13,0xff,0xe8,0x04,0x23,0x04,0x18,0x00,0x20,0x00,0x29,0x00,0x36,0x40,0x1e,0x11,0x0b,0xff,0x06,0x01,0x06,0x03,0x14,0x03,0x01,0x95,0x29,0xe0,0x03,0xf0,0x03,0x02,0x03,0x29,0x03, 0x29,0x0e,0x24,0x95,0x1b,0x10,0x09,0x95,0x0e,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x11,0x33,0x10,0xdd,0x5d,0xce,0x33,0x30,0x31,0x01,0x21,0x14,0x17,0x21,0x15,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x27,0x23,0x35,0x33,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x27, 0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x03,0xdd,0xfd,0x2d,0x06,0x03,0x13,0xfd,0x15,0x29,0x92,0x65,0xac,0x92,0x88,0xdd,0xa1,0xdb,0x31,0x71,0x53,0x06,0x49,0x7f,0xad,0x63,0x65,0x9d,0x6b,0x38,0xa8,0x01,0x86,0x79,0x3a,0x64,0x4e,0x33,0x0a,0x01,0xd7,0x26,0x21,0x81,0x4d,0x50,0x72,0x9a,0x62,0x98,0x8f,0x81,0x33,0x39,0x77,0xc7,0x8f, 0x4f,0x43,0x7f,0xb6,0x73,0x35,0x8f,0x9d,0x2c,0x4f,0x6f,0x42,0x00,0x02,0x00,0x29,0xff,0xe8,0x04,0xc4,0x04,0x18,0x00,0x26,0x00,0x2f,0x00,0x27,0x40,0x14,0x0f,0x95,0x1b,0x1b,0x01,0x95,0x2f,0x13,0x2f,0x13,0x2f,0x09,0x2a,0x95,0x21,0x10,0x04,0x95,0x09,0x16,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x2f, 0xed,0x30,0x31,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x27,0x23,0x22,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x3e,0x02,0x33,0x33,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x04,0xc4,0xfd,0x2d,0x04,0xaf,0x9b,0xac,0x92,0x88,0xdd,0x75,0xab,0x72,0x3a,0x04,0x0e,0x8a,0x29, 0x89,0x27,0x25,0x44,0x60,0x3b,0x22,0x0e,0x4c,0x77,0x9f,0x60,0x6f,0xa0,0x66,0x30,0xa8,0x01,0x86,0x79,0x41,0x66,0x4b,0x2e,0x09,0x01,0xd7,0xac,0xb9,0x72,0x9a,0x62,0x4e,0x87,0xb4,0x66,0x77,0x4a,0x47,0x49,0x56,0x38,0x5a,0x40,0x22,0x5b,0x9f,0x77,0x45,0x50,0x88,0xb2,0x61,0x35,0x8f,0x9d,0x34,0x54,0x6c,0x38,0xff,0xff,0x00,0x35, 0x00,0x00,0x02,0xa0,0x06,0x02,0x02,0x06,0x00,0x49,0x00,0x00,0x00,0x03,0x00,0x60,0xfe,0x11,0x04,0x35,0x04,0x18,0x00,0x2d,0x00,0x42,0x00,0x4e,0x00,0x45,0x40,0x2b,0x24,0x15,0x18,0x27,0x0f,0x33,0x95,0x22,0x10,0x24,0x12,0x01,0x02,0x46,0x2a,0x12,0x04,0x05,0x49,0x96,0x2f,0x0f,0x01,0x0f,0x3d,0x95,0xef,0x18,0x01,0x18,0x40,0x09, 0x0f,0x48,0x18,0x15,0x43,0x96,0x05,0x1b,0x2d,0x00,0x1b,0x00,0x3f,0x32,0x3f,0xed,0x3f,0x2b,0x5d,0xed,0xde,0x5d,0xed,0x12,0x17,0x39,0x5d,0x3f,0xed,0x3f,0x12,0x39,0x39,0x30,0x31,0x01,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x35,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e, 0x02,0x33,0x32,0x17,0x33,0x35,0x33,0x11,0x14,0x07,0x16,0x16,0x17,0x03,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x01,0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0xaa,0x1c,0x2b,0x49,0xbc,0x63,0x3a,0x69,0x50,0x2f,0x34,0x56,0x71,0x3e,0x51,0x9e,0x45,0x26,0x04,0x75,0xeb, 0x5f,0x9d,0x6f,0x3d,0x41,0x79,0xae,0x6d,0xcf,0x64,0x04,0xa4,0x4a,0x26,0x38,0x11,0xc9,0x2c,0x4e,0x69,0x3d,0x4b,0x78,0x54,0x2d,0x2a,0x4f,0x6f,0x45,0x45,0x72,0x53,0x2d,0xfe,0x95,0x4d,0x78,0x2d,0x30,0x6e,0x3e,0x4d,0x51,0x48,0xfe,0x11,0x42,0x36,0x3b,0x30,0x1c,0x35,0x4b,0x2f,0x31,0x4b,0x33,0x1b,0x29,0x27,0x5b,0x7e,0x70,0xc4, 0x47,0x83,0xba,0x73,0x82,0xd2,0x95,0x50,0xa6,0x8e,0xfc,0x52,0xd0,0x83,0x29,0x60,0x39,0x04,0x29,0x3c,0x6b,0x51,0x30,0x38,0x6c,0x9c,0x64,0x54,0x8b,0x63,0x36,0x35,0x5d,0x80,0x4b,0xfc,0xd1,0x2a,0x26,0x1f,0x22,0x27,0x1d,0x23,0x2a,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0xb7,0x05,0xec,0x00,0x2b,0x00,0x2b,0x40,0x15,0x21,0x20, 0x11,0x03,0x03,0x1a,0x27,0x0a,0x0b,0x20,0x27,0x0b,0x0b,0x27,0x20,0x03,0x16,0x2a,0x00,0x16,0x15,0x00,0x3f,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xcd,0x33,0x2f,0xcd,0x11,0x33,0x30,0x31,0x01,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x11,0x23,0x11,0x26,0x26, 0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x11,0x33,0x01,0xae,0x0f,0x1d,0x0e,0x1b,0x25,0x17,0x09,0x57,0x27,0x58,0x47,0x6f,0x68,0x0e,0x18,0x0c,0xa4,0x0f,0x20,0x11,0x32,0x29,0x2d,0x2a,0x26,0x4d,0x53,0x6a,0x68,0x1a,0x1e,0xa4,0x03,0x1f,0x06,0x08,0x10,0x1c,0x27,0x17,0x5b,0x19,0x52,0x17, 0x63,0x4c,0x5f,0x70,0x04,0x03,0xfd,0x4d,0x02,0xff,0x05,0x07,0x3c,0x2e,0x34,0x32,0x0e,0x51,0x0e,0x62,0x55,0x5f,0x70,0x08,0x02,0x84,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0xa4,0x05,0xec,0x00,0x26,0x00,0x4f,0x6e,0x00,0x00,0x27,0x00,0xd8,0x00,0x00,0xfe,0x71,0x00,0x07,0x00,0xd8,0x00,0x00,0xfd,0x3b,0x00,0x03,0xff,0xf6,0x00,0x00, 0x01,0xfa,0x05,0xec,0x00,0x15,0x00,0x1b,0x00,0x22,0x00,0x29,0x40,0x13,0x20,0x15,0x15,0x18,0x02,0x1f,0x0d,0x0d,0x19,0x0a,0x02,0x0a,0x02,0x0a,0x01,0x0b,0x00,0x01,0x15,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x2f,0x33,0x11,0x33,0x33,0x2f,0x33,0x30,0x31,0x21,0x23,0x11,0x2e,0x03,0x35,0x34,0x36,0x37,0x11,0x33, 0x11,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x27,0x14,0x17,0x35,0x06,0x06,0x05,0x34,0x26,0x27,0x15,0x36,0x36,0x01,0x4a,0xa4,0x27,0x41,0x2e,0x1a,0x60,0x50,0xa4,0x50,0x60,0x1a,0x2f,0x41,0x26,0xe4,0x40,0x1d,0x23,0x01,0x1e,0x20,0x1a,0x1a,0x20,0x02,0x1c,0x0a,0x2a,0x3a,0x4a,0x2c,0x5b,0x7a,0x17,0x02,0x00,0xfe,0x01,0x16,0x7a,0x55, 0x2a,0x4a,0x3c,0x2d,0x0c,0xe6,0x5f,0x1e,0xf5,0x13,0x3f,0x26,0x23,0x3c,0x13,0xe3,0x13,0x3b,0x00,0x02,0x00,0xa6,0xff,0xe8,0x06,0xb4,0x04,0x18,0x00,0x3a,0x00,0x47,0x00,0x36,0x40,0x1e,0x36,0x1a,0x95,0x38,0x03,0x96,0x01,0x01,0x3b,0x96,0x13,0x13,0x20,0x38,0x10,0x2e,0x24,0x95,0x31,0x10,0x2d,0x0f,0x2a,0x15,0x20,0x15,0x43,0x95, 0x09,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0xed,0x33,0x2f,0xed,0x10,0xed,0x32,0x30,0x31,0x01,0x33,0x15,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33, 0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x17,0x36,0x33,0x20,0x11,0x03,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x06,0x54,0x60,0x60,0x28,0x49,0x67,0x3f,0x37,0x5c,0x42,0x24,0x2a,0x4a,0x66,0x3c,0x56,0x19,0x37,0x57,0x3e,0x35,0x5c,0x44,0x27,0xa4,0xe9,0x35,0x5b,0x42,0x26,0xa4,0xa4,0x04,0x6d,0xd1,0x34,0x5d,0x4b,0x38, 0x0e,0x72,0xe2,0x01,0x52,0xeb,0x24,0x36,0x23,0x11,0x36,0x36,0x36,0x33,0x01,0xd8,0x6f,0x63,0x46,0x6b,0x48,0x25,0x27,0x45,0x5e,0x37,0x3c,0x59,0x3c,0x1e,0x74,0x54,0x7a,0x4f,0x25,0x34,0x5a,0x76,0x42,0xfd,0xb8,0x02,0x60,0x01,0x2e,0x30,0x56,0x78,0x48,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x1f,0x38,0x4e,0x2f,0xd4,0xfe,0x5f,0xfe,0xf2, 0x16,0x24,0x2f,0x19,0x35,0x3f,0x50,0x43,0x63,0x00,0x00,0x02,0x00,0xa6,0xff,0xe8,0x04,0x58,0x04,0x18,0x00,0x26,0x00,0x33,0x00,0x2b,0x40,0x17,0x20,0x17,0x95,0x23,0x03,0x96,0x00,0x00,0x27,0x96,0x13,0x13,0x1c,0x23,0x10,0x1f,0x0f,0x1c,0x15,0x2f,0x95,0x09,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x33,0x2f,0xed, 0x10,0xed,0x32,0x30,0x31,0x01,0x33,0x15,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x10,0x23,0x22,0x07,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x03,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x03,0xf8,0x60,0x60,0x28,0x49,0x67,0x3f,0x37,0x5c,0x42, 0x24,0x2a,0x4a,0x66,0x3c,0x56,0xee,0x7b,0x51,0x50,0xa4,0xa4,0x04,0x74,0xdc,0xa9,0xb1,0xeb,0x24,0x36,0x23,0x11,0x36,0x36,0x36,0x33,0x01,0xd8,0x6f,0x63,0x46,0x6b,0x48,0x25,0x27,0x45,0x5e,0x37,0x3c,0x59,0x3c,0x1e,0x70,0x01,0x46,0x5d,0x5c,0x8d,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd8,0xce,0xfe,0xf7,0x16,0x24,0x2f,0x19,0x35,0x3f, 0x50,0x43,0x63,0x00,0x00,0x02,0x00,0xa6,0xfe,0x11,0x04,0x1c,0x04,0x18,0x00,0x2e,0x00,0x3a,0x00,0x3f,0x40,0x28,0x17,0x95,0x24,0x10,0x20,0x0f,0x24,0x12,0x01,0x02,0x32,0x2b,0x12,0x04,0x05,0x35,0x96,0x2f,0x0f,0x5f,0x0f,0x6f,0x0f,0xef,0x0f,0x04,0x06,0x0f,0x01,0x0f,0x0f,0x1d,0x15,0x2e,0x00,0x00,0x2f,0x96,0x05,0x1b,0x00,0x3f, 0xed,0x33,0x2f,0x33,0x3f,0x33,0x2f,0x5d,0x5d,0xed,0x12,0x17,0x39,0x5d,0x3f,0x3f,0xed,0x30,0x31,0x01,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x35,0x11,0x10,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x16,0x16,0x17,0x25, 0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x91,0x1c,0x2a,0x4a,0xbb,0x64,0x3a,0x69,0x50,0x2f,0x34,0x56,0x71,0x3e,0x51,0x9e,0x46,0x26,0xee,0x3d,0x68,0x4c,0x2b,0xa4,0xa4,0x04,0x74,0xdc,0xa9,0xb1,0x27,0x23,0x26,0x37,0x11,0xfd,0xca,0x44,0x83,0x2d,0x30,0x6e,0x3e,0x4d,0x51,0x47,0xfe,0x11,0x42,0x36,0x3b,0x30, 0x1c,0x35,0x4b,0x2f,0x31,0x4b,0x33,0x1b,0x29,0x27,0x5a,0x7f,0x02,0x0c,0x01,0x46,0x31,0x57,0x78,0x46,0xfd,0xb8,0x04,0x00,0xaa,0xc2,0xd8,0xce,0xfd,0xca,0x61,0x9e,0x3f,0x28,0x60,0x39,0x63,0x29,0x26,0x1f,0x23,0x27,0x1d,0x23,0x2a,0x00,0x00,0x02,0x00,0x64,0xff,0xd8,0x03,0xc9,0x04,0x12,0x00,0x1e,0x00,0x30,0x00,0x0d,0xb4,0x30, 0x1e,0x25,0x10,0x16,0x00,0x3f,0xcd,0x2f,0xcd,0x30,0x31,0x01,0x07,0x1e,0x03,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x07,0x23,0x26,0x26,0x27,0x35,0x3e,0x03,0x35,0x11,0x34,0x26,0x27,0x25,0x05,0x11,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x26,0x26,0x27,0x03,0x02,0x20,0x03,0x23,0x36,0x40,0x20,0x16,0x15,0x19,0x38, 0x5c,0x42,0xbd,0x43,0x04,0xbe,0xb4,0x10,0x13,0x0b,0x04,0x05,0x05,0x02,0x54,0xfe,0xa6,0x2d,0x52,0x42,0x2d,0x06,0x0e,0x26,0x22,0x18,0x29,0x28,0x30,0x56,0x13,0x03,0xd9,0x0e,0x05,0x3b,0x55,0x67,0x32,0x23,0x41,0x2a,0x28,0x4e,0x58,0x69,0x42,0xbe,0x14,0x50,0x2d,0x3e,0x05,0x11,0x20,0x31,0x26,0x01,0x57,0x33,0x53,0x22,0xdf,0xd4, 0xfd,0xb8,0x15,0x1e,0x15,0x0a,0x2b,0x47,0x5a,0x2f,0x3a,0x6d,0x3f,0x4a,0x74,0x2a,0x00,0x03,0x00,0x54,0xff,0xb4,0x03,0xc9,0x04,0x40,0x00,0x22,0x00,0x31,0x00,0x37,0x00,0x16,0x40,0x09,0x37,0x00,0x20,0x13,0x12,0x12,0x23,0x0e,0x16,0x00,0x3f,0xcd,0x33,0x2f,0x33,0x2f,0x33,0x33,0x30,0x31,0x01,0x07,0x16,0x16,0x17,0x16,0x16,0x15, 0x14,0x0e,0x02,0x07,0x07,0x23,0x26,0x26,0x27,0x07,0x23,0x37,0x27,0x35,0x3e,0x03,0x35,0x11,0x34,0x26,0x27,0x25,0x17,0x37,0x03,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x27,0x01,0x1e,0x03,0x03,0x11,0x13,0x26,0x26,0x27,0x03,0x9e,0x83,0x1b,0x46,0x22,0x16,0x15,0x19,0x38,0x5c,0x42,0xbd,0x43,0x03,0x60,0x5b,0x50,0x78,0x62,0x52,0x10, 0x13,0x0b,0x04,0x05,0x05,0x02,0x54,0x14,0x31,0xab,0x0e,0x26,0x22,0x18,0x29,0x28,0x06,0xfe,0xff,0x2b,0x4f,0x3f,0x2b,0xee,0xcb,0x1b,0x2d,0x0b,0x04,0x40,0xd3,0x2d,0x6d,0x36,0x23,0x41,0x2a,0x28,0x4e,0x58,0x69,0x42,0xbe,0x0e,0x31,0x1e,0x81,0x9f,0x16,0x3e,0x05,0x11,0x20,0x31,0x26,0x01,0x57,0x33,0x53,0x22,0xdf,0x22,0x50,0xfc, 0x64,0x2b,0x47,0x5a,0x2f,0x3a,0x6d,0x3f,0x09,0xfe,0x63,0x14,0x1c,0x14,0x09,0x02,0x9a,0xfe,0x64,0x01,0x48,0x27,0x42,0x1a,0x00,0x02,0x00,0x80,0xff,0xb4,0x04,0x50,0x04,0x40,0x00,0x23,0x00,0x2b,0x00,0x2b,0x40,0x15,0x0c,0x22,0x0e,0x23,0x23,0x1f,0x12,0x1b,0x12,0x1b,0x09,0x18,0x95,0x1f,0x10,0x0e,0x0e,0x24,0x95,0x09,0x16,0x00, 0x3f,0xed,0x33,0x2f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x2f,0x12,0x39,0x39,0x30,0x31,0x01,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x07,0x23,0x37,0x26,0x27,0x33,0x16,0x16,0x17,0x01,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x17,0x37,0x01,0x32,0x36,0x35,0x34,0x27,0x01,0x16,0x04,0x25, 0x66,0x47,0x4a,0x48,0x84,0xbd,0x75,0x38,0x64,0x2d,0x36,0x78,0x53,0x7a,0x34,0xb3,0x0e,0x28,0x17,0x01,0x9c,0x4d,0x71,0x6b,0x9b,0x29,0xaf,0x34,0xfd,0xb9,0x4b,0x81,0x36,0x40,0xfe,0xb2,0xa0,0xaa,0x42,0xfe,0x72,0x3c,0x04,0x40,0xa5,0x45,0xce,0x84,0x79,0xc7,0x8e,0x4e,0x12,0x11,0x57,0x87,0x54,0x98,0x1f,0x34,0x15,0x02,0x99,0x36, 0x65,0x5e,0x9f,0xae,0x20,0x1f,0x67,0xfc,0x32,0xcd,0xbf,0xa8,0x65,0xfd,0x7f,0x18,0x00,0x03,0x00,0x60,0xff,0xe8,0x07,0x1f,0x04,0x18,0x00,0x22,0x00,0x32,0x00,0x3b,0x00,0x2c,0x40,0x18,0x1e,0x95,0x19,0x10,0x33,0x95,0x16,0x14,0x08,0x21,0x21,0x0a,0x23,0x95,0x14,0x10,0x2d,0x95,0x0a,0x16,0x38,0x95,0x05,0x16,0x00,0x3f,0xed,0x3f, 0xed,0x3f,0xed,0x12,0x39,0x2f,0x39,0x12,0x39,0xed,0x3f,0xed,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x20,0x17,0x36,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x06,0x07,0x21,0x01,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x01,0x1e,0x03,0x33, 0x32,0x36,0x37,0x07,0x1f,0x38,0x6b,0x9d,0x65,0x80,0xca,0x3c,0x83,0xfe,0xe1,0x72,0xb9,0x81,0x46,0x4a,0x89,0xc1,0x78,0x01,0x17,0x6f,0x39,0xc2,0x86,0xdd,0x88,0x92,0xac,0x9b,0xaf,0x04,0x02,0xd3,0xfb,0x3f,0x4e,0x7f,0x59,0x30,0x30,0x58,0x7e,0x4e,0xa0,0xac,0xac,0x01,0x52,0x0a,0x33,0x4e,0x64,0x3a,0x79,0x86,0x01,0x01,0xd3,0x73, 0xb6,0x7f,0x43,0x7e,0x6e,0xec,0x4b,0x89,0xc0,0x76,0x81,0xcc,0x8e,0x4b,0xd4,0x67,0x6d,0x62,0x9a,0x72,0xb9,0xac,0x01,0x65,0x38,0x69,0x98,0x5f,0x5a,0x8f,0x65,0x36,0xcc,0xbe,0xc3,0xcf,0xfe,0x10,0x43,0x6e,0x4f,0x2c,0x9d,0x8f,0x00,0x04,0x00,0x60,0xff,0xb4,0x07,0x21,0x04,0x40,0x00,0x2d,0x00,0x36,0x00,0x41,0x00,0x4a,0x00,0x41, 0x40,0x24,0x2e,0x95,0x29,0x2c,0x3f,0x34,0x0b,0x04,0x0c,0x2d,0x2d,0x29,0x10,0x42,0x95,0x10,0x13,0x26,0x24,0x19,0x19,0x13,0x1f,0x95,0x24,0x10,0x45,0x95,0x13,0x16,0x0c,0x0c,0x37,0x95,0x09,0x16,0x00,0x3f,0xed,0x33,0x2f,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0xed,0x3f,0x33,0x2f,0x12,0x17,0x39,0x10,0xed,0x30, 0x31,0x01,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x27,0x07,0x23,0x37,0x26,0x27,0x23,0x06,0x21,0x22,0x2e,0x02,0x35,0x35,0x21,0x2e,0x03,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x17,0x33,0x36,0x21,0x32,0x16,0x17,0x37,0x05,0x22,0x06,0x15,0x14,0x16,0x17,0x01,0x26,0x03,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x01,0x16,0x01,0x16, 0x16,0x33,0x32,0x3e,0x02,0x37,0x06,0xf5,0x69,0x48,0x4d,0x4a,0x89,0xc2,0x77,0x6a,0x55,0x33,0x78,0x52,0x4d,0x2d,0x04,0x76,0xfe,0xf5,0x63,0x9a,0x6a,0x37,0x02,0xd5,0x02,0x2f,0x56,0x7a,0x4d,0xaf,0x90,0x89,0xdc,0x01,0x0d,0x71,0x04,0x82,0x01,0x1e,0x4d,0x85,0x38,0x43,0xfe,0xa9,0xa0,0xac,0x3c,0x39,0x01,0x9c,0x52,0x75,0x4f,0x7f, 0x59,0x2f,0x24,0x22,0xfe,0x72,0x39,0xfc,0x2a,0x02,0x85,0x75,0x3d,0x67,0x50,0x33,0x08,0x04,0x40,0xaa,0x45,0xc7,0x7c,0x81,0xcc,0x8e,0x4b,0x1f,0x53,0x84,0x38,0x63,0xeb,0x45,0x7f,0xb5,0x70,0x58,0x55,0x85,0x5c,0x2f,0x72,0x9a,0x62,0xed,0xed,0x23,0x21,0x6c,0xb2,0xcc,0xbe,0x72,0xa5,0x33,0x02,0x9a,0x3a,0xfc,0xe4,0x39,0x69,0x97, 0x5f,0x4e,0x7f,0x31,0xfd,0x7f,0x15,0x01,0x2c,0x8f,0x9d,0x2e,0x51,0x6e,0x3f,0x00,0x00,0x04,0x00,0x60,0xff,0xe8,0x07,0x21,0x04,0x18,0x00,0x24,0x00,0x2d,0x00,0x36,0x00,0x3f,0x00,0x3b,0x40,0x20,0x3a,0x95,0x1f,0x16,0x37,0x95,0x01,0x2b,0x95,0x31,0x1c,0x1a,0x01,0x0d,0x31,0x01,0x31,0x01,0x31,0x10,0x25,0x95,0x1a,0x16,0x2e,0x95, 0x10,0x10,0x06,0x95,0x0b,0x10,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x39,0x11,0x12,0x39,0x10,0xed,0x10,0xed,0x3f,0xed,0x30,0x31,0x13,0x21,0x2e,0x03,0x23,0x22,0x07,0x35,0x36,0x33,0x20,0x17,0x33,0x36,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x20,0x27,0x23,0x06,0x21,0x22,0x2e,0x02,0x35,0x01, 0x32,0x3e,0x02,0x37,0x21,0x16,0x16,0x13,0x22,0x06,0x07,0x21,0x2e,0x03,0x01,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x60,0x02,0xd5,0x02,0x2f,0x56,0x7a,0x4d,0xaf,0x90,0x89,0xdc,0x01,0x0d,0x71,0x04,0x82,0x01,0x1e,0x73,0xb8,0x81,0x46,0x4a,0x89,0xc2,0x77,0xfe,0xda,0x6c,0x04,0x76,0xfe,0xf5,0x63,0x9a,0x6a,0x37,0x04,0xc3,0x49,0x77, 0x58,0x35,0x07,0xfd,0x63,0x0b,0xab,0x95,0x8c,0xa7,0x14,0x02,0x95,0x0a,0x38,0x55,0x72,0xfb,0x9e,0x02,0x85,0x75,0x3d,0x67,0x50,0x33,0x08,0x02,0x29,0x55,0x85,0x5c,0x2f,0x72,0x9a,0x62,0xed,0xed,0x4c,0x89,0xc0,0x75,0x81,0xcc,0x8e,0x4b,0xeb,0xeb,0x45,0x7f,0xb5,0x70,0xfe,0xa1,0x30,0x5b,0x82,0x52,0xab,0xb4,0x03,0x1c,0x9d,0x95, 0x47,0x72,0x4f,0x2a,0xfe,0x10,0x8f,0x9d,0x2e,0x51,0x6e,0x3f,0x00,0x02,0x00,0x60,0xff,0xe8,0x07,0x98,0x04,0x18,0x00,0x32,0x00,0x42,0x00,0x1f,0x40,0x11,0x33,0x95,0x29,0x10,0x17,0x95,0x10,0x10,0x21,0x95,0x06,0x16,0x03,0x3d,0x95,0x00,0x16,0x00,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x30,0x31,0x05,0x22,0x26,0x27,0x06, 0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x07,0x26,0x22,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x05,0x9a,0x8d,0xd5,0x3f,0x42,0xd6,0x8f,0x71,0xb8,0x82, 0x47,0x49,0x88,0xc1,0x78,0x0d,0x18,0x0c,0x19,0x09,0x12,0x09,0x4e,0x7f,0x59,0x30,0x30,0x5a,0x7e,0x4e,0xa0,0xaa,0x4a,0x89,0xc0,0x77,0x73,0xb4,0x7d,0x42,0x48,0x84,0xbd,0x69,0x4e,0x7f,0x59,0x30,0x30,0x5a,0x7e,0x4e,0xa0,0xaa,0xaa,0x18,0x71,0x66,0x66,0x71,0x4b,0x8a,0xc1,0x76,0x81,0xcb,0x8d,0x4b,0x01,0x01,0x89,0x01,0x37,0x69, 0x96,0x5e,0x5a,0x91,0x66,0x37,0xcd,0xbf,0x7e,0xc8,0x8b,0x49,0x49,0x8a,0xc5,0x7c,0x79,0xc7,0x8e,0x4e,0x03,0xa6,0x37,0x69,0x96,0x5e,0x5a,0x91,0x66,0x37,0xcd,0xbf,0xc1,0xcf,0x00,0x03,0x00,0x60,0xff,0xb4,0x07,0x98,0x04,0x40,0x00,0x3c,0x00,0x47,0x00,0x4f,0x00,0x30,0x40,0x1b,0x03,0x45,0x4d,0x32,0x04,0x05,0x33,0x33,0x3d,0x95, 0x2f,0x10,0x1d,0x95,0x16,0x10,0x09,0x27,0x95,0x0c,0x16,0x05,0x05,0x48,0x95,0x00,0x16,0x00,0x3f,0xed,0x33,0x2f,0x3f,0xed,0x32,0x3f,0xed,0x3f,0xed,0x33,0x2f,0x12,0x17,0x39,0x30,0x31,0x05,0x22,0x26,0x27,0x07,0x23,0x37,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x07,0x26,0x22,0x23, 0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x37,0x33,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x03,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x01,0x26,0x03,0x32,0x36,0x35,0x34,0x27,0x01,0x16,0x05,0x9a,0x38,0x64,0x2d,0x36,0x78,0x54,0x26,0x3f,0x19,0x42,0xd6,0x8f,0x71,0xb8,0x82,0x47,0x49, 0x88,0xc1,0x78,0x0d,0x18,0x0c,0x19,0x09,0x12,0x09,0x4e,0x7f,0x59,0x30,0x30,0x5a,0x7e,0x4e,0xa0,0xaa,0x4a,0x89,0xc0,0x77,0x4b,0x81,0x36,0x40,0x79,0x66,0x47,0x4a,0x48,0x84,0xbd,0x69,0x4e,0x7f,0x59,0x30,0x3f,0x3a,0x01,0x9b,0x4d,0x71,0xa0,0xaa,0x42,0xfe,0x72,0x3c,0x18,0x13,0x11,0x58,0x87,0x1a,0x42,0x28,0x66,0x71,0x4b,0x8a, 0xc1,0x76,0x81,0xcb,0x8d,0x4b,0x01,0x01,0x89,0x01,0x37,0x69,0x96,0x5e,0x5a,0x91,0x66,0x37,0xcd,0xbf,0x7e,0xc8,0x8b,0x49,0x20,0x1f,0x67,0xa5,0x45,0xce,0x84,0x79,0xc7,0x8e,0x4e,0x03,0xa6,0x37,0x69,0x96,0x5e,0x69,0x9f,0x33,0x02,0x99,0x36,0xfc,0xe4,0xcd,0xbf,0xa8,0x65,0xfd,0x7f,0x18,0x00,0x01,0x00,0x7d,0x00,0x00,0x03,0xe4, 0x04,0x00,0x00,0x11,0x00,0x19,0x40,0x0c,0x0b,0x03,0x96,0x0e,0x0e,0x07,0x0c,0x0f,0x07,0x15,0x00,0x15,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x33,0x30,0x31,0x21,0x35,0x10,0x21,0x22,0x06,0x15,0x15,0x23,0x35,0x10,0x25,0x11,0x33,0x11,0x04,0x11,0x15,0x03,0x40,0xfe,0xf5,0x8c,0x88,0xa4,0x01,0x62,0xa4,0x01,0x61,0x6b,0x01,0x3c, 0xa0,0xa8,0x5f,0x58,0x01,0xab,0x29,0x01,0xd4,0xfe,0x2b,0x2c,0xfe,0x54,0x53,0x00,0x00,0x02,0x00,0xb0,0xfe,0x8d,0x04,0x24,0x04,0x33,0x00,0x2a,0x00,0x35,0x00,0x1d,0x40,0x0e,0x0a,0x27,0x3a,0x30,0x30,0x28,0x2f,0x3a,0x2a,0x16,0x3a,0x1d,0x28,0x08,0x00,0x3f,0xdc,0xed,0x2f,0xed,0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x01,0x32,0x1e, 0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x15,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x2e,0x02,0x23,0x23,0x11,0x23,0x11,0x01,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x3e,0x02,0x02,0x1d,0x56,0x8a,0x61,0x34,0x26,0x46,0x62,0x3c,0x3c,0x55,0x37,0x19,0x09,0x1b,0x30,0x28,0x11,0x20, 0x0e,0x11,0x22,0x13,0x96,0x83,0x27,0x40,0x51,0x29,0x90,0xa4,0x02,0x37,0x77,0x76,0xa6,0xa0,0x37,0x59,0x40,0x23,0x04,0x33,0x27,0x4a,0x69,0x43,0x3b,0x62,0x4c,0x35,0x0d,0x03,0x14,0x2e,0x3e,0x4f,0x33,0xe8,0x3b,0x58,0x3a,0x1e,0x05,0x05,0x88,0x04,0x04,0xb8,0xb9,0xff,0x25,0x43,0x33,0x1d,0xfe,0x4b,0x04,0x33,0xfe,0xd7,0x57,0x4c, 0xfe,0x8e,0x1e,0x37,0x4c,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x01,0xef,0x04,0x00,0x00,0x0d,0x00,0x11,0xb7,0x09,0x00,0x0d,0x0f,0x07,0x0f,0x05,0x15,0x00,0x3f,0x3f,0x3f,0x33,0x32,0x30,0x31,0x01,0x06,0x07,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x37,0x01,0xef,0x35,0x2a,0x46,0xa4,0xa4,0x04,0x18,0x51,0x35,0x03,0x6a, 0x18,0x3a,0x62,0xac,0xfd,0xf6,0x04,0x00,0xd3,0x49,0x68,0x1a,0x00,0x01,0x00,0xa6,0x00,0x00,0x03,0xf2,0x04,0x12,0x00,0x1e,0x00,0x1b,0x40,0x0e,0x14,0x07,0x0a,0xec,0x1a,0x10,0x13,0x0f,0x10,0x15,0x05,0xec,0x00,0x10,0x00,0x3f,0xed,0x3f,0x3f,0x3f,0xed,0x32,0x32,0x30,0x31,0x01,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x26,0x26,0x23, 0x22,0x06,0x07,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x3e,0x03,0x33,0x32,0x16,0x17,0x36,0x03,0x90,0x3e,0x24,0x2c,0x50,0x65,0x45,0x2a,0x50,0x20,0x35,0x4a,0x23,0x46,0xa4,0xa4,0x04,0x12,0x36,0x46,0x51,0x2d,0x32,0x49,0x1a,0x47,0x04,0x12,0x0e,0xaa,0x21,0x5b,0x37,0x24,0x31,0x32,0x62,0xac,0xfd,0xf6,0x04,0x00,0xd3,0x36,0x55, 0x3b,0x1f,0x20,0x1d,0x3d,0x00,0x00,0x02,0x00,0x1c,0xff,0xe8,0x03,0x9e,0x04,0x12,0x00,0x26,0x00,0x33,0x00,0x28,0x40,0x15,0x02,0xec,0x24,0x10,0x0a,0x96,0x07,0x07,0x27,0x96,0x1e,0x1c,0x1b,0x1b,0x10,0x1c,0x0f,0x2f,0x95,0x10,0x16,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x2f,0xed,0x3f,0xed,0x30,0x31,0x01,0x26, 0x23,0x22,0x07,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x33,0x15,0x33,0x3e,0x03,0x33,0x32,0x17,0x01,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x03,0x9e,0x2c,0x50,0x6a,0x46,0x46,0x60,0x60,0x28,0x49,0x67,0x3f,0x37,0x5c,0x42,0x24,0x2a,0x4a,0x66, 0x3c,0x56,0xa4,0x04,0x12,0x36,0x46,0x51,0x2d,0x3e,0x24,0xfd,0xa3,0x24,0x36,0x23,0x11,0x36,0x36,0x36,0x33,0x03,0x5a,0x21,0x63,0x62,0xac,0x32,0x6f,0x63,0x46,0x6b,0x48,0x25,0x27,0x45,0x5e,0x37,0x3c,0x59,0x3c,0x1e,0x02,0x28,0xd3,0x36,0x55,0x3b,0x1f,0x0e,0xfd,0x65,0x16,0x24,0x2f,0x19,0x35,0x3f,0x50,0x43,0x63,0x00,0x00,0x02, 0x00,0x1c,0xff,0xe8,0x04,0xd4,0x04,0x12,0x00,0x32,0x00,0x3f,0x00,0x30,0x40,0x1a,0x07,0x0a,0xec,0x2e,0x10,0x14,0x96,0x11,0x11,0x33,0x96,0x28,0x27,0x25,0x25,0x1a,0x27,0x0f,0x3b,0x95,0x1a,0x16,0x05,0xec,0x00,0x10,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x33,0x2f,0xed,0x3f,0xed,0x32,0x30,0x31,0x01,0x32, 0x17,0x15,0x26,0x23,0x22,0x07,0x26,0x26,0x23,0x22,0x06,0x07,0x06,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x33,0x15,0x33,0x3e,0x03,0x33,0x32,0x16,0x17,0x36,0x01,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x04,0x72,0x3e,0x24,0x2c,0x50,0x65,0x45, 0x2a,0x50,0x20,0x35,0x4a,0x23,0x23,0x23,0x60,0x60,0x28,0x49,0x67,0x3f,0x37,0x5c,0x42,0x24,0x2a,0x4a,0x66,0x3c,0x56,0xa4,0x04,0x12,0x36,0x46,0x51,0x2d,0x32,0x49,0x1a,0x47,0xfd,0x29,0x24,0x36,0x23,0x11,0x36,0x36,0x36,0x33,0x04,0x12,0x0e,0xaa,0x21,0x5b,0x37,0x24,0x31,0x32,0x32,0x90,0x56,0x28,0x6f,0x63,0x46,0x6b,0x48,0x25, 0x27,0x45,0x5e,0x37,0x3c,0x59,0x3c,0x1e,0x02,0x28,0xd3,0x36,0x55,0x3b,0x1f,0x20,0x1d,0x3d,0xfd,0x57,0x16,0x24,0x2f,0x19,0x35,0x3f,0x50,0x43,0x63,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x03,0x14,0x04,0x00,0x00,0x15,0x00,0x1d,0x40,0x0e,0x05,0x96,0x0f,0x0a,0x0f,0x0a,0x0f,0x01,0x14,0x0f,0x0c,0x0f,0x01,0x15,0x00,0x3f,0x3f,0x3f, 0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x30,0x31,0x21,0x23,0x11,0x06,0x06,0x23,0x22,0x26,0x27,0x15,0x23,0x11,0x33,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x33,0x03,0x14,0xa4,0x2d,0x70,0x46,0x4a,0x6e,0x2b,0x6e,0x83,0x27,0x64,0x41,0x25,0x4a,0x3f,0x2e,0x09,0xa4,0x03,0x64,0x1a,0x1f,0x1f,0x1c,0xd4,0x01,0x6e,0x38,0x24,0x10,0x1a,0x21, 0x11,0x00,0x00,0x02,0x00,0x3c,0xff,0xe9,0x05,0x06,0x04,0x00,0x00,0x20,0x00,0x2c,0x00,0x29,0x40,0x16,0x21,0x96,0x1c,0x09,0x96,0x13,0x0d,0x1c,0x13,0x13,0x1c,0x0d,0x03,0x00,0x18,0x0f,0x10,0x0f,0x27,0x96,0x00,0x16,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x10,0xed,0x10,0xed,0x30,0x31,0x05,0x22,0x2e,0x02,0x35, 0x11,0x06,0x06,0x23,0x22,0x26,0x27,0x15,0x23,0x11,0x33,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x33,0x11,0x36,0x33,0x20,0x11,0x14,0x06,0x03,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x03,0xb0,0x48,0x76,0x54,0x2e,0x2d,0x70,0x46,0x4a,0x6e,0x2b,0x6e,0x83,0x27,0x64,0x41,0x25,0x4a,0x3f,0x2e,0x09,0xa4,0x49,0x6b,0x01, 0x3e,0xb2,0x94,0x5d,0x4f,0x4e,0x5b,0x5a,0x4c,0x4b,0x17,0x27,0x4b,0x70,0x4a,0x02,0x4f,0x1a,0x1f,0x1f,0x1c,0xd4,0x01,0x6e,0x38,0x24,0x10,0x1a,0x21,0x11,0xfe,0x73,0x24,0xfe,0xac,0xaa,0xb0,0x02,0x52,0x81,0x83,0x79,0x79,0x7a,0x7d,0x80,0x7f,0x00,0xff,0xff,0xff,0x92,0xfe,0x1e,0x02,0x68,0x06,0x02,0x02,0x06,0x05,0x88,0x00,0x00, 0x00,0x01,0x00,0x90,0xff,0xe8,0x03,0xe2,0x04,0x00,0x00,0x12,0x00,0x19,0x40,0x0c,0x11,0x11,0x01,0x09,0x0f,0x02,0x0c,0x95,0x05,0x16,0x01,0x15,0x00,0x3f,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x30,0x31,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x33,0x32,0x37,0x36,0x35,0x11,0x33,0x03,0xe2,0xa4,0x04,0x66,0xd6, 0xfe,0x92,0xa3,0xf8,0x79,0x4c,0x4e,0xa4,0xa2,0xba,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0x58,0x58,0x90,0x01,0x03,0x00,0x00,0x02,0x00,0x21,0xff,0xe8,0x04,0xa4,0x04,0x00,0x00,0x15,0x00,0x1f,0x00,0x28,0x40,0x13,0x0a,0x01,0x18,0x10,0x14,0x0d,0x10,0x12,0x10,0x12,0x10,0x07,0x0f,0x0f,0x04,0x1b,0x95,0x07,0x15,0x00,0x3f,0xed, 0x32,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x10,0xcd,0x32,0x32,0x30,0x31,0x01,0x23,0x11,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x21,0x35,0x33,0x15,0x33,0x05,0x35,0x21,0x15,0x10,0x33,0x32,0x3e,0x02,0x04,0xa4,0x98,0xa4,0x04,0x66,0xd5,0xfe,0x8f,0x97,0x97,0xa4,0x02,0x0c,0xa4,0x98,0xfe, 0xc4,0xfd,0xf4,0xfa,0x3c,0x65,0x48,0x29,0x01,0xdb,0xfe,0x25,0xa2,0xba,0x01,0xb4,0x3f,0x8b,0x01,0x9a,0xfe,0x66,0x50,0x50,0xb4,0x29,0x25,0xfe,0xbc,0x2f,0x54,0x76,0x00,0x02,0x00,0xa6,0xff,0xe8,0x06,0x54,0x04,0x12,0x00,0x27,0x00,0x3b,0x00,0x29,0x40,0x16,0x0e,0x0e,0x25,0x28,0x32,0x10,0x07,0x95,0x25,0x16,0x23,0x1b,0x11,0x95, 0x1e,0x16,0x1a,0x15,0x17,0x0f,0x01,0x0f,0x00,0x3f,0x3f,0x3f,0x3f,0xed,0x32,0x32,0x3f,0xed,0x3f,0xcd,0x12,0x39,0x2f,0x30,0x31,0x13,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x10,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x27,0x06,0x23,0x20,0x11,0x01,0x22,0x2e, 0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0xa6,0xa4,0x19,0x36,0x57,0x3f,0x34,0x5c,0x45,0x27,0xa4,0xe9,0x36,0x5b,0x42,0x25,0xa4,0xa4,0x04,0x6e,0xd0,0x35,0x5d,0x4b,0x37,0x0e,0x72,0xe2,0xfe,0xae,0x02,0xd7,0x16,0x27,0x1c,0x11,0x11,0x1c,0x27,0x16,0x16,0x28,0x1d,0x11,0x11,0x1d,0x28,0x04,0x00,0xfd,0xb4, 0x55,0x7a,0x4e,0x25,0x35,0x59,0x76,0x42,0x8d,0xa5,0xfe,0xd2,0x30,0x57,0x77,0x48,0x02,0x48,0xfc,0x00,0xa2,0xba,0x1f,0x38,0x4e,0x2f,0xd4,0x01,0xa1,0x01,0xb4,0x10,0x1c,0x27,0x17,0x17,0x27,0x1d,0x10,0x10,0x1d,0x27,0x17,0x16,0x27,0x1c,0x11,0x00,0x00,0x02,0x00,0xa6,0xff,0xee,0x06,0x54,0x04,0x18,0x00,0x27,0x00,0x3b,0x00,0x2b, 0x40,0x17,0x28,0x32,0x16,0x07,0x95,0x25,0x10,0x11,0x95,0x1e,0x10,0x23,0x1b,0x19,0x0e,0x0e,0x18,0x19,0x0f,0x18,0x15,0x01,0x15,0x00,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0x12,0x39,0x39,0x3f,0xed,0x3f,0xed,0x3f,0xcd,0x30,0x31,0x21,0x23,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x10,0x23,0x22,0x0e,0x02,0x15,0x11, 0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x1e,0x02,0x17,0x36,0x33,0x20,0x11,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x06,0x54,0xa4,0x19,0x36,0x57,0x3f,0x35,0x5b,0x45,0x27,0xa4,0xe9,0x36,0x5b,0x42,0x25,0xa4,0xa4,0x04,0x6d,0xd1,0x34,0x5e,0x4b,0x37,0x0e,0x72,0xe2,0x01,0x52,0xfd,0x29, 0x16,0x27,0x1c,0x11,0x11,0x1c,0x27,0x16,0x17,0x27,0x1d,0x11,0x11,0x1d,0x27,0x02,0x4c,0x55,0x7a,0x4e,0x25,0x35,0x59,0x76,0x42,0x8d,0xa5,0x01,0x2e,0x30,0x57,0x77,0x48,0xfd,0xb8,0x04,0x00,0xa2,0xba,0x1f,0x38,0x4e,0x2f,0xd4,0xfe,0x5f,0xfe,0x4c,0x10,0x1c,0x27,0x17,0x17,0x27,0x1d,0x10,0x10,0x1d,0x27,0x17,0x16,0x27,0x1c,0x11, 0x00,0x01,0x00,0x0e,0xff,0xe8,0x04,0x46,0x04,0x31,0x00,0x21,0x00,0x1c,0x40,0x0e,0x0d,0x95,0x13,0x13,0x02,0x01,0x20,0x0f,0x1b,0x95,0x05,0x16,0x01,0x15,0x00,0x3f,0x3f,0xed,0x3f,0x12,0x39,0x33,0x2f,0xed,0x30,0x31,0x21,0x23,0x35,0x23,0x06,0x23,0x20,0x11,0x11,0x34,0x2e,0x02,0x23,0x22,0x06,0x07,0x35,0x36,0x33,0x32,0x1e,0x02, 0x15,0x11,0x10,0x33,0x32,0x37,0x36,0x35,0x11,0x33,0x04,0x46,0xa4,0x04,0x66,0xd6,0xfe,0x92,0x0a,0x1c,0x35,0x2a,0x1e,0x2a,0x19,0x2a,0x4c,0x48,0x68,0x43,0x20,0xf8,0x79,0x4c,0x4e,0xa4,0xa2,0xba,0x01,0xb4,0x01,0x2b,0x38,0x54,0x37,0x1c,0x0d,0x0e,0x94,0x12,0x34,0x5e,0x82,0x4e,0xfe,0xe7,0xfe,0xbc,0x58,0x58,0x90,0x02,0x4e,0x00, 0xff,0xff,0x00,0x0c,0xfe,0x21,0x04,0x46,0x04,0x18,0x02,0x06,0x01,0xd3,0x00,0x00,0x00,0x02,0x00,0x0c,0xfe,0x21,0x04,0xbc,0x04,0x18,0x00,0x28,0x00,0x3c,0x00,0x28,0x40,0x15,0x38,0x18,0x0a,0x1b,0x07,0x04,0x19,0x1f,0x1f,0x08,0x19,0x0f,0x0d,0xec,0x12,0x10,0x2e,0x00,0x00,0x08,0x1b,0x00,0x3f,0x33,0x2f,0x32,0x3f,0xed,0x3f,0x12, 0x39,0x2f,0x12,0x17,0x39,0x33,0x30,0x31,0x01,0x22,0x26,0x27,0x26,0x26,0x27,0x03,0x01,0x23,0x01,0x03,0x26,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x1e,0x02,0x17,0x13,0x01,0x33,0x01,0x13,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x27,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x03,0xea, 0x3e,0x5c,0x1c,0x1c,0x35,0x1f,0xa0,0xfe,0xa1,0xb9,0x01,0xc6,0xae,0x42,0x48,0x2e,0x2a,0x21,0x4a,0x2b,0x44,0x39,0x32,0x1a,0x8c,0x01,0x11,0xb9,0xfe,0x89,0xdc,0x1c,0x4c,0x2d,0x2c,0x4a,0x36,0x1f,0x21,0x39,0x4d,0x8c,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0xfe,0x21,0x38,0x30,0x30,0x6c, 0x43,0x01,0x56,0xfd,0x6f,0x03,0x38,0x01,0x89,0x94,0x0e,0x9a,0x0a,0x15,0x32,0x51,0x3c,0xfe,0xb6,0x02,0x06,0xfd,0x58,0xfe,0x18,0x1a,0x1b,0x1d,0x33,0x46,0x2a,0x2a,0x48,0x34,0x1e,0xc6,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x00,0x00,0x01,0x00,0x0c,0xfe,0x21,0x04,0x46,0x04,0x18,0x00,0x21, 0x00,0x20,0x40,0x12,0x02,0xec,0x1f,0x1c,0x08,0x16,0x05,0x19,0x04,0x07,0x18,0x1b,0x13,0xec,0x0e,0x10,0x07,0x0f,0x00,0x3f,0x3f,0xed,0x3f,0x12,0x17,0x39,0x3f,0xed,0x30,0x31,0x13,0x16,0x33,0x32,0x37,0x13,0x01,0x33,0x01,0x13,0x3e,0x03,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x07,0x03,0x01,0x23,0x01,0x03,0x0e,0x03,0x23,0x22,0x27, 0x0c,0x27,0x27,0x48,0x44,0xec,0xfe,0x89,0xb9,0x01,0x11,0x8c,0x1a,0x32,0x39,0x44,0x2b,0x4a,0x21,0x2a,0x2e,0x48,0x42,0xae,0x01,0xc6,0xb9,0xfe,0xa1,0x9f,0x26,0x44,0x45,0x4b,0x2d,0x31,0x2b,0xfe,0xc6,0x10,0x96,0x02,0x0c,0x02,0xa8,0xfd,0xfa,0x01,0x4a,0x3d,0x52,0x31,0x14,0x0a,0x9a,0x0e,0x94,0xfe,0x77,0xfc,0xc8,0x02,0x91,0xfe, 0x95,0x57,0x75,0x48,0x1e,0x09,0x00,0x02,0x00,0x1a,0xff,0xd3,0x04,0x2c,0x04,0x00,0x00,0x27,0x00,0x3b,0x00,0x26,0x40,0x16,0x21,0x0f,0x37,0x25,0x01,0x1f,0x18,0x04,0x05,0x40,0x0b,0x0e,0x48,0x05,0x05,0x1d,0x15,0x2d,0x0f,0x16,0x00,0x0f,0x00,0x3f,0x3f,0x33,0x3f,0x39,0x2f,0x2b,0x17,0x39,0x33,0x3f,0x30,0x31,0x01,0x01,0x17,0x36, 0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x27,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x03,0x23,0x01,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x01,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x03,0x92,0xfe,0xa8,0x88,0x1c,0x51,0x32,0x2c,0x4a,0x36,0x1f,0x21,0x39,0x4d, 0x2b,0x34,0x46,0x34,0x2c,0x19,0x63,0x09,0x17,0x0d,0x04,0x02,0x18,0x15,0xcd,0xbd,0x01,0x5d,0xfe,0xb2,0xbf,0xc6,0x0b,0x15,0x0b,0x04,0x01,0x00,0x1b,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x04,0x00,0xfd,0xfa,0xe2,0x1e,0x21,0x1d,0x33,0x46,0x2a,0x2a,0x48,0x34,0x1e,0x1b,0x32,0x49,0x2e, 0xb5,0x11,0x26,0x17,0x05,0x26,0x23,0xfe,0xb4,0x01,0xf6,0x02,0x0a,0xfe,0xa2,0x14,0x28,0x14,0x01,0xae,0xfc,0x99,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x00,0x00,0x01,0xff,0x1f,0xfe,0x57,0x03,0x92,0x04,0x00,0x00,0x15,0x00,0x1a,0x40,0x0e,0x06,0x0d,0x01,0x13,0x04,0x03,0x15,0x0f,0x0f,0x0f, 0x0b,0x1b,0x03,0x15,0x00,0x3f,0x3f,0x3f,0x3f,0x12,0x17,0x39,0x30,0x31,0x09,0x02,0x23,0x03,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x01,0x03,0x92,0xfe,0xa8,0x01,0x52,0xbf,0xc9,0x14,0x19,0x04,0x02,0x18,0x15,0xfe,0x38,0xbd,0x02,0x58,0xfe,0xb2,0xbf,0xc6,0x0b,0x15,0x0b,0x04,0x01,0x00, 0x04,0x00,0xfd,0xfa,0xfe,0x06,0x01,0x4c,0x1f,0x2f,0x05,0x26,0x23,0xfd,0x0b,0x03,0x9f,0x02,0x0a,0xfe,0xa2,0x14,0x28,0x14,0x01,0xae,0x00,0x02,0xff,0x1f,0xfe,0x57,0x04,0x2c,0x04,0x00,0x00,0x27,0x00,0x3b,0x00,0x2a,0x40,0x18,0x37,0x18,0x1f,0x01,0x25,0x04,0x27,0x2f,0x05,0x3f,0x05,0x02,0x05,0x05,0x0f,0x27,0x0f,0x21,0x0f,0x1d, 0x1b,0x2d,0x0f,0x16,0x00,0x3f,0x33,0x3f,0x3f,0x3f,0x12,0x39,0x2f,0x5d,0x12,0x17,0x39,0x33,0x30,0x31,0x01,0x01,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x27,0x26,0x26,0x27,0x23,0x06,0x06,0x07,0x01,0x23,0x01,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x01,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e, 0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x03,0x92,0xfe,0xa8,0x88,0x1c,0x51,0x32,0x2c,0x4a,0x36,0x1f,0x21,0x39,0x4d,0x2b,0x29,0x3f,0x36,0x2e,0x16,0x74,0x09,0x17,0x0d,0x04,0x02,0x18,0x15,0xfe,0x38,0xbd,0x02,0x58,0xfe,0xb2,0xbf,0xc6,0x0b,0x15,0x0b,0x04,0x01,0x00,0x1b,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d, 0x26,0x15,0x15,0x26,0x1d,0x10,0x04,0x00,0xfd,0xfa,0xe2,0x1e,0x21,0x1d,0x33,0x46,0x2a,0x2a,0x48,0x34,0x1e,0x15,0x29,0x3e,0x29,0xd4,0x11,0x26,0x17,0x05,0x26,0x23,0xfd,0x0b,0x03,0x9f,0x02,0x0a,0xfe,0xa2,0x14,0x28,0x14,0x01,0xae,0xfc,0x99,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x15,0x15,0x26,0x1d,0x10,0x10,0x1d,0x26,0x00,0x01, 0xfe,0xc8,0xfe,0x21,0x03,0x7a,0x04,0x00,0x00,0x23,0x00,0x1d,0x40,0x10,0x02,0xec,0x21,0x1c,0x0e,0x12,0x08,0x17,0x04,0x10,0x14,0x15,0x10,0x0f,0x0a,0x0f,0x00,0x3f,0x3f,0x3f,0x12,0x17,0x39,0x3f,0xed,0x30,0x31,0x01,0x16,0x33,0x32,0x3e,0x02,0x37,0x01,0x01,0x33,0x13,0x16,0x16,0x17,0x33,0x01,0x33,0x01,0x01,0x23,0x03,0x26,0x27, 0x23,0x06,0x06,0x07,0x01,0x0e,0x03,0x23,0x22,0x27,0xfe,0xc8,0x27,0x27,0x14,0x1d,0x1f,0x2a,0x21,0x01,0xae,0xfe,0xb2,0xbf,0xc6,0x0b,0x15,0x0b,0x04,0x01,0x00,0xb5,0xfe,0xa8,0x01,0x52,0xbf,0xc9,0x14,0x19,0x04,0x02,0x18,0x15,0xfe,0xab,0x2b,0x41,0x3c,0x41,0x2a,0x31,0x2b,0xfe,0xc6,0x10,0x0a,0x21,0x3f,0x34,0x02,0xa2,0x02,0x0a, 0xfe,0xa2,0x14,0x28,0x14,0x01,0xae,0xfd,0xfa,0xfe,0x06,0x01,0x4c,0x1f,0x2f,0x05,0x26,0x23,0xfd,0xdc,0x45,0x64,0x40,0x1e,0x09,0x00,0x00,0x01,0x00,0x0e,0xfe,0x1e,0x03,0x40,0x04,0x00,0x00,0x14,0x00,0x18,0x40,0x0b,0x0f,0x0b,0x14,0x14,0x03,0x0d,0x0f,0x08,0x95,0x03,0x1c,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x39,0x39,0x30,0x31, 0x01,0x01,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x37,0x37,0x01,0x33,0x01,0x17,0x33,0x36,0x36,0x37,0x13,0x03,0x40,0xfe,0xbe,0x7e,0xe4,0x41,0x2a,0x34,0x2d,0x7d,0x3d,0x52,0xfe,0x70,0xb6,0x01,0x15,0x15,0x06,0x02,0x0a,0x08,0x99,0x02,0x89,0xfc,0xd3,0xfe,0xc2,0x0d,0x93,0x12,0x94,0xc2,0x03,0xfe,0xfc,0xec,0x4e,0x0c,0x26,0x1a, 0x01,0x9f,0x00,0x02,0x00,0x25,0x03,0x50,0x02,0x4a,0x05,0xbe,0x00,0x10,0x00,0x21,0x00,0x14,0xb7,0x11,0x16,0x14,0x1c,0x0b,0x10,0x0d,0x05,0x00,0x2f,0xcd,0xcc,0x32,0xde,0xcd,0xcc,0x32,0x30,0x31,0x01,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x33,0x16,0x33,0x32,0x36,0x37,0x11,0x26,0x26,0x23,0x22,0x07,0x23,0x3e,0x03,0x33,0x32,0x1e, 0x02,0x17,0x02,0x4a,0x05,0x2e,0x4a,0x61,0x39,0x3a,0x61,0x47,0x2a,0x02,0x64,0x0c,0xa0,0x45,0x60,0x0a,0x0a,0x60,0x45,0xa0,0x0c,0x64,0x02,0x2a,0x47,0x61,0x3a,0x37,0x62,0x4a,0x2f,0x05,0x05,0xbe,0x38,0x5c,0x43,0x25,0x24,0x42,0x5d,0x39,0x9b,0x53,0x48,0xfd,0x92,0x48,0x53,0x9b,0x39,0x5d,0x42,0x24,0x25,0x42,0x5d,0x38,0x00,0x01, 0x00,0x64,0x01,0xbc,0x02,0x4e,0x05,0xc4,0x00,0x21,0x00,0x14,0xb7,0x12,0x1f,0x1f,0x19,0x1a,0x0a,0x05,0x19,0x00,0x2f,0xdc,0xcd,0x2f,0x12,0x39,0x2f,0xcd,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x11,0x34,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x15,0x02, 0x4e,0x1f,0x3a,0x56,0x36,0x2b,0x24,0x2b,0x26,0x13,0x25,0x1b,0x11,0x6d,0x1d,0x2e,0x21,0x12,0x80,0x80,0x02,0x3a,0x7a,0xb4,0x02,0xa0,0x3e,0x57,0x36,0x19,0x10,0x5f,0x16,0x06,0x1a,0x32,0x2c,0x01,0x3a,0x97,0x16,0x28,0x36,0x1f,0xfe,0xc9,0x03,0x2a,0xfe,0xa4,0x67,0xe7,0x00,0x01,0x00,0x00,0x02,0x9a,0x01,0xf4,0x05,0xc4,0x00,0x28, 0x00,0x29,0x40,0x13,0x1c,0x1d,0x0e,0x02,0x02,0x16,0x23,0x07,0x08,0x1d,0x23,0x08,0x08,0x23,0x1d,0x03,0x12,0x27,0x12,0x00,0x2f,0x2f,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xcd,0x33,0x2f,0xcd,0x11,0x33,0x30,0x31,0x01,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x37,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x11,0x23,0x11,0x26, 0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x07,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x11,0x33,0x01,0x3c,0x12,0x11,0x24,0x1b,0x3f,0x1e,0x42,0x35,0x50,0x4b,0x10,0x0d,0x80,0x0a,0x14,0x0b,0x21,0x1b,0x21,0x1e,0x1e,0x39,0x3f,0x4d,0x4c,0x09,0x11,0x09,0x80,0x04,0x6b,0x05,0x27,0x20,0x3d,0x11,0x43,0x11,0x48,0x38,0x45,0x52, 0x03,0xfe,0x81,0x01,0xb9,0x03,0x04,0x29,0x1f,0x23,0x23,0x0a,0x41,0x0b,0x48,0x3e,0x45,0x52,0x03,0x02,0x01,0x20,0x00,0x01,0x00,0x00,0x02,0x95,0x01,0xbf,0x05,0xc0,0x00,0x2f,0x00,0x23,0x40,0x0f,0x03,0x2d,0x2d,0x0a,0x10,0x10,0x28,0x22,0x22,0x15,0x1b,0x1b,0x07,0x1e,0x07,0x00,0x2f,0x2f,0x12,0x39,0x2f,0xcd,0x33,0x2f,0xcd,0x32, 0x2f,0xcd,0x33,0x2f,0xcd,0x30,0x31,0x01,0x06,0x06,0x23,0x22,0x27,0x11,0x23,0x11,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x35,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x17,0x35,0x33,0x11,0x16,0x33,0x32,0x37,0x33,0x06,0x06,0x23,0x22,0x27,0x15,0x16,0x33,0x32,0x37,0x01,0xbf,0x02,0x40,0x38,0x11,0x10,0x86,0x14, 0x0d,0x41,0x02,0x3a,0x02,0x40,0x3b,0x11,0x10,0x14,0x0d,0x41,0x02,0x3a,0x02,0x40,0x3b,0x11,0x10,0x86,0x0d,0x11,0x3e,0x02,0x3d,0x02,0x40,0x38,0x11,0x10,0x0d,0x11,0x3e,0x02,0x04,0x3d,0x47,0x59,0x03,0xfe,0xf5,0x01,0x45,0x06,0x50,0x49,0x57,0x04,0x76,0x06,0x50,0x49,0x57,0x04,0xcc,0xfe,0xf7,0x04,0x52,0x47,0x59,0x03,0x79,0x04, 0x52,0x00,0x00,0x01,0x00,0x00,0x02,0x8d,0x02,0x80,0x04,0xfc,0x00,0x25,0x00,0x19,0x40,0x0a,0x0c,0x13,0x13,0x02,0x01,0x25,0x1e,0x06,0x06,0x01,0x00,0x2f,0x33,0x2f,0xcd,0x2f,0x12,0x39,0x33,0x2f,0xcd,0x30,0x31,0x01,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02, 0x15,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x02,0x80,0x7f,0x02,0x1d,0x4f,0x3d,0xd3,0x1c,0x30,0x11,0x18,0x0e,0x0c,0x2e,0x16,0x29,0x42,0x2d,0x18,0x05,0x14,0x29,0x23,0x24,0x3a,0x29,0x15,0x7f,0x02,0x9a,0x5c,0x35,0x34,0xf7,0xa0,0x40,0x3f,0x07,0x08,0x5e,0x05,0x05,0x1e,0x35,0x4a,0x2c,0x8c,0x2e,0x45,0x2e,0x17, 0x1e,0x33,0x41,0x24,0x01,0x3b,0x00,0x02,0x00,0x60,0xff,0xe8,0x04,0x0e,0x04,0x18,0x00,0x14,0x00,0x29,0x00,0x1b,0x40,0x0e,0x00,0x1b,0x95,0x13,0x10,0x06,0x25,0x95,0x09,0x16,0x04,0x15,0x03,0x0f,0x00,0x3f,0x3f,0x3f,0xed,0x32,0x3f,0xed,0x32,0x30,0x31,0x01,0x33,0x35,0x33,0x11,0x23,0x35,0x23,0x06,0x23,0x22,0x2e,0x02,0x35,0x34, 0x3e,0x02,0x33,0x32,0x13,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0x66,0x04,0xa4,0xa4,0x04,0x7a,0xe8,0x63,0x9c,0x6c,0x39,0x40,0x79,0xad,0x6d,0xcc,0x6b,0x2c,0x4e,0x6b,0x3f,0x4a,0x76,0x52,0x2c,0x29,0x4c,0x6c,0x44,0x48,0x75,0x53,0x2d,0x03,0x6c,0x94,0xfc,0x00,0xb4,0xcc,0x48,0x84, 0xbb,0x73,0x7f,0xd0,0x95,0x52,0xfd,0xb7,0x8f,0x3e,0x6f,0x53,0x30,0x3b,0x6f,0xa0,0x65,0x55,0x87,0x5f,0x32,0x36,0x5e,0x7f,0xff,0xff,0x00,0x58,0x00,0x00,0x04,0xb8,0x04,0x45,0x02,0x06,0x0d,0x80,0x00,0x00,0xff,0xff,0x00,0xcf,0x03,0xca,0x01,0x88,0x04,0x7f,0x00,0x07,0x0f,0x50,0x00,0x2b,0x03,0xcf,0xff,0xff,0x00,0xcf,0xfe,0xe8, 0x01,0x88,0xff,0x9d,0x00,0x07,0x0f,0x50,0x00,0x2b,0xfe,0xed,0xff,0xff,0x00,0x2e,0x03,0xca,0x02,0x29,0x04,0x7f,0x00,0x07,0x0f,0x51,0x00,0x2b,0x03,0xcf,0xff,0xff,0x00,0x2e,0xfe,0xe8,0x02,0x29,0xff,0x9d,0x00,0x07,0x0f,0x51,0x00,0x2b,0xfe,0xed,0xff,0xff,0x00,0x2e,0x03,0xca,0x02,0x29,0x05,0x97,0x00,0x07,0x0f,0x53,0x00,0x2b, 0x03,0xcf,0xff,0xff,0x00,0x2e,0xfd,0xd0,0x02,0x29,0xff,0x9d,0x00,0x07,0x0f,0x53,0x00,0x2b,0xfd,0xd5,0xff,0xff,0x00,0x2e,0x03,0xca,0x02,0x29,0x05,0x97,0x00,0x07,0x0f,0x54,0x00,0x2b,0x03,0xcf,0xff,0xff,0x00,0x2e,0xfd,0xd0,0x02,0x29,0xff,0x9d,0x00,0x07,0x0f,0x54,0x00,0x2b,0xfd,0xd5,0xff,0xff,0x00,0x2e,0x03,0xca,0x02,0x29, 0x05,0x97,0x00,0x07,0x0f,0x56,0x00,0x2b,0x03,0xcf,0xff,0xff,0x00,0x2e,0xfd,0xd0,0x02,0x29,0xff,0x9d,0x00,0x07,0x0f,0x56,0x00,0x2b,0xfd,0xd5,0xff,0xff,0x00,0x67,0xfe,0x36,0x01,0xf0,0xff,0x9e,0x00,0x06,0x0f,0x5d,0x2b,0x37,0xff,0xff,0x00,0xcf,0x03,0xca,0x01,0x88,0x05,0x97,0x00,0x07,0x0f,0x52,0x00,0x2b,0x03,0xcf,0xff,0xff, 0x00,0xcf,0xfd,0xd0,0x01,0x88,0xff,0x9d,0x00,0x07,0x0f,0x52,0x00,0x2b,0xfd,0xd5,0xff,0xff,0x00,0x8b,0xfe,0x63,0x01,0xcc,0xff,0xa4,0x00,0x06,0x0f,0x5b,0x2b,0x64,0xff,0xff,0x00,0x0c,0x03,0xca,0x02,0x72,0x06,0x2c,0x00,0x07,0x0f,0x57,0x00,0x46,0x03,0xca,0xff,0xff,0x00,0x0c,0xfe,0x17,0x02,0x72,0x00,0x79,0x00,0x07,0x0f,0x57, 0x00,0x46,0xfe,0x17,0xff,0xff,0xff,0xd4,0x03,0xc3,0x02,0x33,0x06,0xa7,0x02,0x07,0x0e,0x65,0x00,0x00,0xfe,0xa3,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x51,0x05,0x95,0x00,0x27,0x0a,0x65,0x00,0x1e,0xfe,0xa3,0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x51,0x06,0xa0,0x00,0x27,0x0a,0x66,0x00,0x1e,0xfe,0xa3, 0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x51,0x05,0x9f,0x00,0x27,0x0a,0x67,0x00,0x1e,0xfe,0xa3,0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0x00,0x05,0xff,0xf2,0x02,0x01,0x07,0x8d,0x02,0x26,0x08,0xc7,0x00,0x00,0x00,0x06,0x09,0x2c,0x00,0x00,0xff,0xff,0x00,0x05,0x00,0x00,0x02,0x01,0x07,0x8d,0x02,0x26, 0x09,0x0d,0x00,0x00,0x00,0x06,0x09,0x2c,0x00,0x00,0x00,0x02,0x00,0x52,0xfe,0x9c,0x0c,0xb6,0x03,0xba,0x00,0x7a,0x00,0x8a,0x00,0x68,0xb1,0x72,0x03,0xbd,0x04,0xfb,0x00,0x77,0x05,0x03,0x00,0x15,0x00,0x6a,0x04,0xfb,0xb6,0x6b,0x6b,0x59,0x1f,0x5e,0x37,0x34,0xb8,0x04,0xfb,0xb6,0x7b,0x55,0x59,0x33,0x33,0x2c,0x3c,0x41,0x09,0x04, 0xfb,0x00,0x59,0x05,0x03,0x00,0x7e,0x04,0xfb,0x00,0x50,0x05,0x03,0x00,0x86,0x04,0xfb,0xb5,0x2f,0x46,0x01,0x46,0x46,0x25,0xb8,0x04,0xff,0xb3,0x2c,0x0e,0x0e,0x2c,0x00,0x2f,0x33,0x2f,0x10,0xed,0x33,0x2f,0x5d,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x39,0xed,0x32,0x32,0x39,0x11,0x33,0x2f,0xed,0x32,0x3f,0xed,0x32, 0x30,0x31,0x37,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x00,0x17,0x1e,0x03,0x17,0x26,0x26,0x35,0x34,0x3e,0x04,0x37,0x35,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x04,0x17,0x07,0x06,0x06,0x07,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23, 0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x0e,0x05,0x15,0x14,0x1e,0x02,0x17,0x07,0x2e,0x05,0x27,0x0e,0x03,0x23,0x22,0x26,0x27,0x01,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x52,0x61,0xa6,0x39,0x4f,0x6c,0x42,0x1d,0x3b,0x60,0x7b,0x40,0xb9,0x01,0x05,0x2d,0x1f,0x5e,0x76,0x8a,0x4b, 0x06,0x09,0x31,0x5a,0x80,0x9f,0xb9,0x67,0x39,0x60,0x68,0x7d,0x56,0x4e,0x7e,0x33,0x37,0x84,0x4e,0x50,0x7c,0x6a,0x61,0x69,0x7a,0x4e,0x20,0x20,0x50,0x31,0x01,0x13,0x30,0x55,0x44,0x3f,0x56,0x3a,0x22,0x0b,0x14,0x37,0x54,0x79,0x56,0x61,0x8b,0x58,0x2a,0x2b,0x56,0x81,0x57,0x36,0x63,0x58,0x4b,0x1f,0x32,0x88,0x55,0x31,0x43,0x6e, 0x50,0x30,0x05,0x30,0x6f,0x70,0x66,0x50,0x2f,0x24,0x4b,0x73,0x50,0x2f,0x50,0xad,0xad,0xa5,0x91,0x77,0x28,0x1c,0x53,0x67,0x76,0x3f,0x3a,0x9a,0x4b,0x09,0xd1,0x2a,0x8f,0x55,0x5e,0x6a,0x1a,0x35,0x52,0x38,0x32,0x4e,0x3e,0x2e,0xa9,0x0b,0x0b,0x15,0x2c,0x44,0x2f,0x49,0x9c,0x9f,0xa1,0x4e,0xfe,0xdc,0xf9,0x5a,0x97,0x7b,0x61,0x23, 0x1e,0x39,0x12,0x38,0x57,0x47,0x3e,0x3d,0x42,0x29,0x05,0x1b,0x36,0x2a,0x1b,0x14,0x10,0x9d,0x12,0x17,0x1d,0x2b,0x32,0x2c,0x1e,0x01,0xc8,0x08,0x29,0x1d,0x2a,0x3a,0x26,0x11,0x2e,0x41,0x48,0x1a,0x2f,0x72,0x62,0x42,0x4d,0x74,0x86,0x3a,0x3b,0x72,0x59,0x36,0x17,0x28,0x35,0x1f,0x4b,0x48,0x29,0x4d,0x6e,0x45,0x0c,0x24,0x2a,0x31, 0x34,0x38,0x1b,0x25,0x43,0x35,0x22,0x04,0xaa,0x08,0x2a,0x41,0x55,0x67,0x77,0x42,0x2c,0x3b,0x24,0x0f,0x0c,0x0a,0x01,0x05,0x34,0x37,0x44,0x46,0x21,0x50,0x45,0x2f,0x28,0x47,0x5f,0x00,0x00,0x12,0x00,0x32,0xff,0x17,0x07,0xc3,0x06,0x5d,0x01,0x37,0x01,0x67,0x01,0x8a,0x01,0xb5,0x01,0xb9,0x01,0xc7,0x01,0xec,0x02,0x11,0x02,0x21, 0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x48,0x02,0x4c,0x02,0x50,0x02,0x54,0x02,0x58,0x02,0x5c,0x00,0x00,0x01,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17, 0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x15,0x14,0x16,0x33,0x33,0x35,0x33,0x15,0x21, 0x32,0x3e,0x02,0x35,0x11,0x23,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x33,0x14,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x16,0x17, 0x33,0x11,0x33,0x11,0x36,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x2e,0x02,0x27,0x23,0x06,0x06,0x23,0x23,0x11,0x14,0x1e,0x02,0x33,0x33,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17, 0x36,0x36,0x37,0x15,0x0e,0x03,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x21,0x11,0x14,0x1e,0x02,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x16,0x17,0x32,0x3e,0x02,0x35,0x35,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06, 0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x01,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x27,0x15,0x14,0x0e,0x02,0x23, 0x22,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x21,0x35,0x21,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x17,0x32,0x36,0x35,0x35,0x01,0x33,0x11,0x23,0x25,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x01,0x06,0x06,0x15,0x14,0x33,0x32,0x35,0x35,0x33,0x15,0x14, 0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x34,0x37,0x05,0x06,0x06,0x15,0x14,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x34,0x37,0x01,0x34, 0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x1e,0x03,0x03,0x14,0x16,0x33,0x32,0x36,0x37,0x35,0x06,0x06,0x13,0x14,0x16,0x33,0x32,0x36,0x37,0x35,0x06,0x06,0x01,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x01,0x21,0x15,0x21,0x25,0x33,0x15,0x23,0x03,0x23,0x35,0x33, 0x07,0x23,0x35,0x33,0x05,0xf4,0x19,0x27,0x32,0x18,0x23,0x37,0x0e,0x11,0x39,0x17,0x1d,0x38,0x10,0x17,0x39,0x17,0x68,0x2f,0x35,0x0b,0x15,0x31,0x14,0x97,0x18,0x28,0x0d,0x10,0x24,0x19,0x13,0x27,0x11,0x0f,0x1b,0x0a,0x19,0x14,0x0e,0x0b,0x47,0x0a,0x0a,0x2e,0x2b,0x0d,0x24,0x26,0x23,0x0c,0x18,0x27,0x1e,0x13,0x05,0x01,0x05,0x0e, 0x19,0x15,0x8d,0x09,0x15,0x11,0x0c,0xdb,0x1d,0x27,0x0d,0x14,0x30,0x17,0x26,0x3c,0x0c,0x10,0x20,0x0b,0x19,0x2f,0x24,0x15,0x1e,0x33,0x41,0x23,0x42,0x15,0x21,0x13,0x26,0x43,0x13,0x23,0xd2,0x41,0x01,0xee,0x09,0x15,0x11,0x0c,0x0c,0x26,0x2e,0x0a,0x15,0x31,0x14,0x27,0x2f,0x22,0x1b,0x12,0x13,0x24,0x21,0x29,0x21,0x8b,0x94,0x75, 0x6a,0x01,0x02,0x3c,0x03,0x20,0x30,0x3a,0x1a,0x73,0x6d,0x24,0x2a,0x24,0x42,0x3c,0x1f,0x2a,0x22,0x24,0x1a,0x09,0x14,0x11,0x0b,0x41,0x18,0x22,0x0a,0x41,0x1a,0x21,0x05,0x05,0x42,0x04,0x04,0x03,0x04,0x3c,0x10,0x36,0x3d,0x3e,0x19,0x2c,0x3c,0x25,0x10,0x21,0x39,0x4d,0x2d,0x4b,0x1a,0x36,0x30,0x28,0x0d,0x01,0x0f,0x2d,0x16,0x0e, 0x07,0x11,0x1d,0x15,0xb7,0x2e,0x1b,0x15,0x2c,0x42,0x2c,0x0e,0x2d,0x12,0x11,0x25,0x14,0x17,0x26,0x1d,0x10,0x24,0x35,0x2f,0x4e,0x33,0x2d,0x4e,0x4a,0x48,0x27,0x8c,0x2f,0x35,0x0b,0x15,0x31,0x14,0xfe,0x16,0x07,0x11,0x1d,0x15,0x6b,0x0b,0x18,0x13,0x0d,0x43,0x1d,0x26,0x0c,0x17,0x12,0x0c,0x40,0x21,0x2a,0x0e,0x1a,0x13,0x0b,0xfc, 0x2c,0x13,0x23,0x17,0x22,0x42,0x16,0x24,0x2d,0x16,0x20,0x2a,0x0e,0x14,0x30,0x17,0x26,0x3c,0x0c,0x10,0x20,0x0b,0x19,0x2f,0x24,0x15,0x1e,0x33,0x41,0x23,0x42,0x15,0x21,0x13,0x26,0x43,0x04,0x1d,0x2a,0x43,0x20,0x27,0x31,0x1b,0x0a,0x01,0x21,0x22,0x1a,0x30,0x25,0x16,0x13,0x21,0x2d,0x1b,0x1d,0x2e,0x14,0x16,0x15,0x14,0x2d,0x48, 0x33,0x23,0x43,0x27,0xe6,0x12,0x1c,0x23,0x12,0x34,0x16,0x0d,0x27,0x11,0x14,0x29,0x0b,0x11,0x28,0x11,0xfe,0xa3,0x01,0x60,0x11,0x1f,0x30,0x15,0x1b,0x11,0x1e,0x2d,0x18,0x1d,0x15,0x1e,0xfd,0xf8,0x42,0x42,0x04,0x15,0x4d,0x3c,0x11,0x19,0x1c,0x0c,0x17,0x2d,0x28,0x21,0x0b,0xfa,0xe9,0x02,0x01,0x18,0x14,0x2d,0x09,0x0c,0x0e,0x09, 0x01,0x2c,0x01,0x26,0x1e,0x18,0x16,0x17,0x16,0x22,0x1d,0x02,0x02,0x68,0x02,0x01,0x18,0x14,0x2d,0x09,0x0c,0x0e,0x09,0x01,0x2c,0x01,0x26,0x1e,0x18,0x16,0x17,0x16,0x22,0x1d,0x02,0x03,0x7c,0x0d,0x16,0x1c,0x0f,0x0c,0x16,0x11,0x0b,0x31,0x20,0x0f,0x1e,0xfa,0x73,0x14,0x19,0x09,0x11,0x15,0x0c,0x2d,0x1b,0x17,0x1d,0x12,0x0a,0xf3, 0x29,0x1b,0x0c,0x18,0x0c,0x32,0x42,0x05,0x29,0x1b,0x0c,0x18,0x0c,0x32,0x42,0x03,0x5d,0x01,0x0d,0xfe,0xf3,0x01,0x0d,0xfe,0xf3,0x02,0x36,0x01,0x0d,0xfe,0xf3,0xfd,0x85,0xd1,0xd1,0xe2,0x4c,0x4c,0x83,0x4b,0x4b,0x01,0x23,0xa2,0x29,0x31,0x1b,0x09,0x12,0x0f,0x14,0x0d,0x11,0x14,0x16,0x0f,0x18,0x0d,0x15,0x10,0x13,0x0e,0x10,0x11, 0x07,0x05,0x04,0x05,0x1f,0x1c,0x1a,0x41,0x22,0x26,0x3c,0x18,0x33,0x42,0x08,0x3c,0x46,0x24,0x09,0x18,0x26,0x2f,0x16,0x0c,0x14,0x0f,0x09,0x05,0x0d,0x16,0x11,0x01,0x48,0x14,0x11,0x11,0x14,0x23,0x26,0x05,0x03,0x0c,0x19,0x28,0x1d,0x21,0x31,0x22,0x16,0x06,0x2b,0xd1,0x27,0x26,0x19,0x20,0x01,0x07,0xf3,0x26,0x27,0x7c,0x7c,0x05, 0x0d,0x16,0x11,0x01,0x83,0x02,0x17,0x0c,0x15,0x10,0x2b,0x34,0x2b,0x1d,0x1a,0x10,0x26,0x2b,0x30,0x1a,0x4f,0x4b,0x4d,0x55,0x0e,0x17,0x0e,0x13,0x15,0x09,0x20,0x25,0x12,0x05,0x29,0x30,0x11,0x22,0x26,0x2c,0x1c,0x39,0x48,0x2b,0x33,0x2b,0x05,0x0e,0x15,0x11,0x02,0x0c,0xfe,0x0b,0x1a,0x30,0x05,0x01,0xb8,0xfe,0x48,0x02,0x17,0x14, 0x11,0x29,0x17,0x17,0x2b,0x15,0x21,0x03,0x38,0x59,0x3e,0x21,0x1c,0x2f,0x40,0x24,0x33,0x39,0x1b,0x06,0x02,0x09,0x14,0x12,0x14,0x1d,0xfe,0x94,0x0f,0x1c,0x17,0x0e,0x27,0x3b,0x19,0x1d,0x35,0x27,0x17,0x03,0x03,0x46,0x03,0x04,0x05,0x11,0x1f,0x19,0x17,0x37,0x21,0x09,0x1f,0x19,0x4e,0x14,0x1a,0x10,0x06,0x18,0x0d,0x15,0x10,0xfe, 0xcf,0x0f,0x1c,0x17,0x0e,0x04,0x0d,0x16,0x12,0x63,0x4b,0x2c,0x25,0x04,0x0c,0x17,0x12,0x63,0x49,0x2c,0x26,0x01,0x04,0x0c,0x17,0x12,0x9f,0x03,0x42,0x26,0x27,0x1a,0x1f,0x01,0x6d,0xfe,0x90,0x25,0x30,0x1d,0x0c,0x13,0x12,0x11,0x14,0x23,0x26,0x05,0x03,0x0c,0x19,0x28,0x1d,0x21,0x31,0x22,0x16,0x06,0x2b,0xd1,0x27,0x26,0x19,0x20, 0x01,0x39,0xfa,0x39,0x11,0x0e,0x1a,0x28,0x33,0x1a,0x0f,0x10,0x1f,0x2d,0x1d,0x19,0x37,0x2f,0x1e,0x21,0x21,0x22,0x5c,0x34,0x2d,0x53,0x3f,0x26,0x0f,0x12,0x56,0x6d,0x1b,0x21,0x12,0x06,0x16,0x0e,0x08,0x0b,0x0e,0x0f,0x0a,0x30,0x0f,0x17,0x43,0x32,0x1d,0x1a,0x0e,0x18,0x43,0x31,0x1d,0x1a,0x01,0x0e,0x18,0x6b,0x06,0x70,0xfd,0x3c, 0x95,0x1b,0x24,0x20,0x29,0x18,0x0a,0x1c,0x2f,0x3e,0x21,0x02,0x02,0x0a,0x14,0x02,0x20,0x22,0x1e,0x1e,0x11,0x11,0x10,0x11,0x08,0x0d,0x0a,0x07,0x0b,0x08,0x26,0x2a,0x12,0x12,0x30,0x20,0x03,0x0f,0x08,0x69,0x0a,0x14,0x02,0x20,0x22,0x1e,0x1e,0x11,0x11,0x10,0x11,0x08,0x0d,0x0a,0x07,0x0b,0x08,0x26,0x2a,0x12,0x12,0x30,0x20,0x03, 0x0f,0x08,0xfa,0xc0,0x0f,0x2d,0x2a,0x1e,0x0f,0x17,0x1e,0x0f,0x1d,0x21,0x05,0x20,0x0f,0x14,0x0c,0x1d,0x18,0x11,0x68,0x04,0x05,0x03,0x01,0x02,0x33,0x17,0x13,0x02,0x04,0x74,0x0b,0x28,0x01,0xe7,0x17,0x13,0x02,0x04,0x74,0x0b,0x28,0xfc,0xd6,0x25,0x01,0x6f,0x25,0x03,0x3f,0x25,0x51,0x25,0xfb,0x58,0x4c,0x4c,0x4c,0x00,0x00,0x05, 0x00,0x32,0xff,0xba,0x06,0xc7,0x06,0x22,0x00,0xa9,0x00,0xb9,0x00,0xc7,0x00,0xcb,0x00,0xcf,0x00,0x00,0x25,0x22,0x26,0x27,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x35,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x35,0x23,0x22,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x35,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x27,0x26, 0x26,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x11,0x14,0x16,0x33,0x32,0x37,0x26,0x02,0x27,0x35,0x33,0x16,0x12,0x17,0x33,0x11,0x33,0x11,0x14,0x07,0x16,0x16,0x17,0x3e,0x03,0x35,0x11,0x33,0x11,0x14,0x16,0x17,0x16,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x32,0x3e,0x02, 0x37,0x26,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x17,0x17,0x36,0x36,0x37,0x26,0x26,0x27,0x26,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x17,0x16,0x17,0x36,0x36,0x37,0x17,0x07,0x06,0x06,0x07,0x16,0x16,0x17,0x37,0x15,0x0e,0x05,0x25,0x26,0x26,0x27,0x0e,0x03,0x07,0x16,0x16,0x33,0x32,0x3e,0x02,0x01,0x0e,0x03,0x15,0x14,0x16,0x33,0x32, 0x3e,0x02,0x35,0x01,0x23,0x35,0x33,0x07,0x23,0x35,0x33,0x04,0xc2,0x2d,0x39,0x10,0x09,0x0a,0x3b,0x5d,0x7e,0x4c,0x6b,0xc5,0xab,0x8a,0x2e,0x33,0x93,0xae,0xc0,0x60,0x3e,0x70,0x56,0x32,0x14,0x2d,0x39,0x16,0x14,0x37,0x3d,0x42,0x20,0x2d,0x5e,0x58,0x4d,0x1c,0x34,0x69,0x29,0x25,0x40,0x22,0x10,0x10,0x05,0x10,0x07,0x0f,0x08,0x32, 0x43,0x2c,0x4d,0x39,0x20,0x17,0x48,0x2a,0x21,0x33,0x23,0x13,0x34,0x51,0x61,0x2d,0x4c,0x3e,0x46,0x3a,0x24,0x39,0x96,0x61,0x5c,0x41,0x81,0x3e,0x08,0x48,0x25,0x0e,0x1b,0x0d,0x13,0x22,0x18,0x0e,0x47,0x08,0x0b,0x0a,0x25,0x14,0x16,0x47,0x16,0x19,0x3d,0x42,0x44,0x21,0x22,0x41,0x22,0x23,0x27,0x2a,0x62,0x35,0x22,0x13,0x1f,0x0c, 0x15,0x3e,0x2a,0x2b,0x56,0x2f,0x1c,0x21,0x2a,0x57,0x33,0x63,0x5d,0x14,0x2d,0x14,0x03,0x19,0x17,0x3d,0x22,0x15,0x27,0x15,0x59,0x1e,0x51,0x5d,0x63,0x5f,0x56,0x01,0x3d,0x0f,0x2b,0x20,0x2f,0x60,0x5b,0x51,0x20,0x0f,0x2e,0x1d,0x29,0x5e,0x5c,0x56,0xfb,0x47,0x22,0x43,0x35,0x21,0x24,0x1f,0x10,0x2a,0x25,0x19,0x04,0xb9,0x3f,0x3f, 0xad,0x3f,0x3f,0x47,0x28,0x26,0x1f,0x18,0x38,0x30,0x20,0x31,0x4e,0x61,0x30,0x61,0x37,0x67,0x50,0x30,0x18,0x29,0x36,0x1e,0x1c,0x24,0x2f,0x25,0x34,0x21,0x0f,0x11,0x1d,0x24,0x13,0x54,0x1e,0x2d,0x0b,0x0a,0x06,0x03,0x02,0x39,0x19,0x33,0x19,0x19,0x15,0x28,0x39,0x23,0x17,0x20,0x18,0x29,0x34,0x1c,0x34,0x44,0x29,0x13,0x03,0x25, 0xfe,0xec,0x32,0x36,0x15,0xab,0x01,0x4c,0x9f,0x05,0x6b,0xfe,0xea,0xb4,0x03,0x86,0xfc,0x77,0x4c,0x31,0x2b,0x5c,0x30,0x08,0x1f,0x27,0x2c,0x15,0x04,0x7b,0xfb,0xb5,0x20,0x38,0x1a,0x17,0x20,0x04,0xa7,0xfb,0x59,0x0d,0x16,0x1c,0x10,0x0a,0x08,0x52,0x13,0x11,0x0c,0x0a,0x11,0x08,0x11,0x21,0x10,0x10,0x0e,0x52,0x0e,0x10,0x1e,0x43, 0x0b,0x1a,0x0b,0x5a,0x0f,0x0e,0x24,0x13,0x0c,0x1a,0x10,0x32,0x54,0x16,0x33,0x34,0x31,0x25,0x17,0xda,0x0e,0x1b,0x0f,0x18,0x2d,0x23,0x16,0x01,0x1c,0x24,0x18,0x27,0x30,0x01,0xe0,0x03,0x0b,0x19,0x2b,0x22,0x1e,0x29,0x06,0x0d,0x14,0x0e,0xfd,0x9c,0x40,0x85,0x40,0x00,0x00,0x20,0x00,0x32,0xfe,0x62,0x08,0x31,0x06,0xaf,0x00,0x69, 0x00,0xcf,0x01,0x2d,0x01,0x5d,0x01,0x61,0x01,0x86,0x01,0x8a,0x01,0x96,0x01,0xa5,0x01,0xb4,0x01,0xbe,0x01,0xc2,0x01,0xc6,0x01,0xca,0x01,0xf0,0x01,0xf4,0x02,0x1a,0x02,0x1e,0x02,0x2a,0x02,0x36,0x02,0x42,0x02,0x4e,0x02,0x52,0x02,0x56,0x02,0x5a,0x02,0x5e,0x02,0x62,0x02,0x66,0x02,0x6a,0x02,0x6e,0x02,0x93,0x02,0xb8,0x00,0x00, 0x01,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x33,0x32,0x3e,0x02, 0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x16,0x17,0x32,0x3e,0x02,0x35,0x35,0x01,0x06,0x06,0x07,0x0e,0x03,0x23,0x23,0x22,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36, 0x37,0x36,0x36,0x35,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x1e,0x03,0x33,0x33,0x32,0x3e,0x02,0x37,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x17,0x03,0x06,0x06,0x07,0x0e,0x03,0x23,0x23, 0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x17,0x1e,0x03,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x33,0x32,0x3e,0x02,0x37,0x27,0x26,0x26,0x23,0x22,0x06, 0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x17,0x1e,0x03,0x33,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x25,0x33,0x11,0x23,0x01,0x06,0x06,0x15, 0x14,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x34,0x37,0x01,0x23,0x35,0x33,0x13,0x22,0x06,0x07,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x01,0x1e,0x03,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x01,0x32,0x36,0x35, 0x34,0x2e,0x02,0x23,0x22,0x07,0x1e,0x03,0x25,0x14,0x16,0x33,0x32,0x36,0x37,0x35,0x06,0x06,0x01,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x13,0x23,0x35,0x33,0x01,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x27,0x0e,0x03,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x16, 0x33,0x01,0x33,0x11,0x23,0x03,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x27,0x0e,0x03,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x16,0x33,0x01,0x33,0x11,0x23,0x01,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22, 0x06,0x15,0x14,0x16,0x01,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x01,0x33,0x15,0x23,0x25,0x33,0x15,0x23,0x03,0x33,0x15,0x23,0x01,0x33,0x15,0x23,0x05,0x33,0x15,0x23,0x03,0x33,0x15,0x23,0x05,0x06,0x06,0x15, 0x14,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x23,0x22,0x26,0x35,0x34,0x34,0x37,0x13,0x06,0x06,0x15,0x14,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x35,0x33,0x14,0x16,0x15,0x14,0x06,0x23,0x22,0x27,0x06,0x23, 0x22,0x26,0x35,0x34,0x34,0x37,0x08,0x31,0x19,0x27,0x32,0x18,0x23,0x37,0x0e,0x11,0x39,0x17,0x1d,0x38,0x10,0x17,0x39,0x17,0x20,0x33,0x0f,0x15,0x31,0x14,0x30,0x18,0x28,0x0d,0x10,0x24,0x19,0x13,0x27,0x11,0x0f,0x1b,0x0a,0x19,0x14,0x0e,0x0b,0x47,0x0a,0x0a,0x2e,0x2b,0x0d,0x24,0x26,0x23,0x0c,0x18,0x27,0x1e,0x13,0x05,0x01,0x05, 0x0e,0x19,0x15,0x26,0x09,0x15,0x11,0x0c,0x41,0x1d,0x23,0x0b,0x18,0x13,0x0d,0x43,0x1d,0x26,0x0c,0x17,0x12,0x0c,0x40,0x21,0x2a,0x0e,0x1a,0x13,0x0b,0xfd,0x03,0x1a,0x32,0x17,0x16,0x32,0x39,0x3f,0x23,0x24,0x44,0x1c,0x13,0x2c,0x20,0x21,0x3a,0x18,0x12,0x2d,0x19,0x18,0x11,0x15,0x09,0x05,0x58,0x65,0x2f,0x41,0x28,0x12,0x03,0x02, 0x02,0x03,0x42,0x05,0x05,0x31,0x3b,0x23,0x32,0x1f,0x0e,0x07,0x06,0x42,0x08,0x02,0x1c,0x1d,0x10,0x16,0x11,0x0b,0x04,0x0d,0x1a,0x20,0x29,0x1c,0x29,0x34,0x1c,0x0b,0x01,0x08,0x12,0x20,0x1b,0x1c,0x18,0x2f,0x34,0x3b,0x23,0x16,0x23,0x23,0x23,0x16,0x18,0x2f,0x17,0x14,0x33,0x1b,0x22,0x3c,0x3c,0x3f,0x23,0x4f,0x0e,0x31,0x2a,0x16, 0x2e,0x37,0x42,0x2a,0x38,0x20,0x2a,0x0e,0x15,0x31,0x14,0x27,0x17,0x28,0x0d,0x10,0x24,0x1a,0x13,0x26,0x11,0x0f,0x1b,0x0a,0x19,0x15,0x0f,0x0b,0x47,0x0a,0x0a,0x2e,0x2b,0x0d,0x24,0x26,0x23,0x0b,0x19,0x27,0x1e,0x13,0x05,0x01,0x05,0x0e,0x18,0x15,0x1d,0x09,0x15,0x11,0x0c,0x40,0x14,0x23,0x4b,0x19,0x2e,0x33,0x3b,0x26,0x19,0x19, 0x38,0x2c,0x18,0x2e,0x17,0x14,0x32,0x1c,0x2a,0x39,0x1a,0x0d,0x19,0x1e,0x24,0x17,0xfd,0x23,0x13,0x23,0x17,0x22,0x42,0x16,0x24,0x2d,0x16,0x20,0x2a,0x0e,0x14,0x30,0x17,0x26,0x3c,0x0c,0x10,0x20,0x0b,0x19,0x2f,0x24,0x15,0x1e,0x33,0x41,0x23,0x42,0x15,0x21,0x13,0x26,0x43,0x01,0x20,0x42,0x42,0xfe,0x7f,0x02,0x01,0x18,0x14,0x2d, 0x09,0x0c,0x0e,0x09,0x01,0x2c,0x01,0x26,0x1e,0x18,0x16,0x17,0x16,0x22,0x1d,0x02,0x01,0x40,0x33,0x33,0x32,0x1e,0x27,0x0c,0x1e,0x38,0x3e,0x08,0x10,0x19,0xfe,0x84,0x17,0x1c,0x12,0x0a,0x06,0x15,0x19,0x09,0x11,0x16,0x0c,0x2c,0x03,0x0f,0x14,0x19,0x09,0x11,0x15,0x0c,0x2d,0x1b,0x17,0x1d,0x12,0x0a,0xfb,0xfb,0x29,0x1b,0x0c,0x18, 0x0c,0x32,0x42,0x07,0xb1,0x4b,0x4b,0xf9,0x00,0x4b,0x4b,0xac,0x2d,0x2d,0x04,0xac,0x1e,0x1d,0x42,0x16,0x24,0x2e,0x18,0x3e,0x20,0x15,0x03,0x1a,0x2a,0x38,0x21,0x23,0x2e,0x31,0x1f,0x36,0x2c,0x1a,0x10,0x42,0x0e,0x0f,0x05,0x04,0x20,0x26,0x01,0x10,0x41,0x41,0xdf,0x1e,0x1d,0x42,0x16,0x24,0x2e,0x18,0x3e,0x20,0x15,0x03,0x1a,0x2a, 0x38,0x21,0x23,0x2e,0x31,0x1f,0x36,0x2c,0x1a,0x10,0x42,0x0e,0x0f,0x05,0x04,0x20,0x26,0x01,0x10,0x41,0x41,0xfe,0x50,0x20,0x2c,0x2c,0x20,0x20,0x2c,0x2c,0x20,0x11,0x15,0x15,0x11,0x10,0x15,0x15,0xfe,0xd8,0x1f,0x2c,0x2c,0x1f,0x21,0x2c,0x2c,0x21,0x10,0x15,0x15,0x10,0x11,0x15,0x15,0xfe,0x51,0x4b,0x4b,0x83,0x4c,0x4c,0x02,0x10, 0xd1,0xd1,0xfe,0xd8,0xc7,0xc7,0x60,0xc7,0xc7,0x01,0x86,0xd1,0xd1,0xfb,0x5c,0xc7,0xc7,0x75,0xbd,0xbd,0x05,0x44,0x02,0x01,0x18,0x14,0x2d,0x09,0x0c,0x0e,0x09,0x01,0x2c,0x01,0x26,0x1e,0x18,0x16,0x17,0x16,0x22,0x1d,0x02,0x2c,0x02,0x01,0x18,0x14,0x2d,0x09,0x0c,0x0e,0x09,0x01,0x2c,0x01,0x26,0x1e,0x18,0x16,0x17,0x16,0x22,0x1d, 0x02,0x04,0xf0,0xa2,0x29,0x31,0x1b,0x09,0x12,0x0f,0x14,0x0d,0x11,0x14,0x16,0x0f,0x14,0x11,0x15,0x10,0x13,0x0e,0x10,0x11,0x07,0x05,0x04,0x05,0x1f,0x1c,0x1a,0x41,0x22,0x26,0x3c,0x18,0x33,0x42,0x08,0x3c,0x46,0x24,0x09,0x18,0x26,0x2f,0x16,0x0c,0x14,0x0f,0x09,0x05,0x0d,0x16,0x11,0x63,0x4c,0x2a,0x26,0x04,0x0d,0x16,0x12,0x63, 0x4b,0x2c,0x25,0x04,0x0c,0x17,0x12,0x9f,0x85,0x2c,0x26,0x01,0x04,0x0c,0x17,0x12,0x9f,0xfc,0xfb,0x07,0x20,0x0e,0x0e,0x1f,0x1a,0x10,0x27,0x14,0x13,0x1c,0x14,0x14,0x1c,0x08,0x07,0x59,0x63,0x19,0x2e,0x42,0x29,0x0f,0x1b,0x0e,0x0e,0x16,0x0c,0x21,0x2f,0x11,0x3f,0x31,0x10,0x24,0x3b,0x2b,0x17,0x3d,0x24,0x41,0x11,0x14,0x0b,0x11, 0x13,0x09,0x1b,0x2e,0x23,0x14,0x22,0x2d,0x2c,0x0a,0x09,0x12,0x0f,0x09,0x0f,0x1a,0x25,0x17,0x0b,0x11,0x0c,0x06,0x08,0x06,0x46,0x06,0x08,0x15,0x19,0x15,0x01,0xfd,0x54,0x04,0x19,0x1d,0x0f,0x1d,0x17,0x0e,0x14,0x11,0x15,0x10,0x13,0x0e,0x10,0x11,0x07,0x05,0x04,0x05,0x1f,0x1c,0x1a,0x41,0x22,0x26,0x3c,0x18,0x33,0x42,0x08,0x3c, 0x46,0x24,0x09,0x18,0x26,0x2f,0x16,0x0c,0x14,0x0f,0x09,0x05,0x0d,0x16,0x11,0x9f,0x89,0x2a,0x25,0x0d,0x19,0x26,0x19,0x0c,0x0d,0x15,0x08,0x06,0x45,0x06,0x08,0x15,0x0d,0x06,0x0c,0x09,0x06,0x04,0x83,0x26,0x27,0x1a,0x1f,0x01,0x6d,0xfe,0x90,0x25,0x30,0x1d,0x0c,0x13,0x12,0x11,0x14,0x23,0x26,0x05,0x03,0x0c,0x19,0x28,0x1d,0x21, 0x31,0x22,0x16,0x06,0x2b,0xd1,0x27,0x26,0x19,0x20,0x01,0x39,0x5a,0xfd,0xf1,0x02,0x46,0x0a,0x14,0x02,0x20,0x22,0x1e,0x1e,0x11,0x11,0x10,0x11,0x08,0x0d,0x0a,0x07,0x0b,0x08,0x26,0x2a,0x12,0x12,0x30,0x20,0x03,0x0f,0x08,0xfc,0x7e,0xdb,0xfe,0xa4,0x2c,0x25,0x20,0x29,0x0a,0x19,0x16,0x0f,0xfd,0x41,0x04,0x05,0x03,0x01,0x0f,0x14, 0x0c,0x1c,0x19,0x11,0x04,0x56,0x0f,0x14,0x0c,0x1d,0x18,0x11,0x68,0x04,0x05,0x03,0x01,0x6a,0x17,0x13,0x02,0x04,0x74,0x0b,0x28,0xfe,0xb5,0x4c,0xfe,0xb0,0x4d,0x03,0xa2,0x71,0xfb,0x17,0x14,0x25,0x01,0x9c,0xfe,0x61,0x29,0x32,0x1b,0x09,0x10,0x2e,0x3e,0x27,0x11,0x12,0x45,0x10,0x35,0x38,0x31,0x5b,0x2b,0x1f,0x2c,0x1b,0x16,0x12, 0x01,0xd0,0xfd,0xe7,0xfd,0xd0,0x14,0x25,0x01,0xa7,0xfe,0x56,0x29,0x31,0x1b,0x09,0x10,0x2e,0x41,0x2a,0x13,0x12,0x44,0x10,0x3d,0x39,0x30,0x5b,0x2c,0x1f,0x2d,0x1b,0x16,0x12,0x01,0xdb,0xfd,0xdd,0x06,0xa1,0x2d,0x20,0x20,0x2c,0x2c,0x20,0x20,0x2d,0x71,0x14,0x10,0x10,0x15,0x15,0x10,0x10,0x14,0xfd,0xfb,0x2d,0x21,0x20,0x2c,0x2c, 0x20,0x21,0x2d,0x72,0x14,0x10,0x10,0x16,0x16,0x10,0x10,0x14,0xfb,0xca,0x4c,0x4c,0x4c,0x04,0x61,0x25,0x8e,0x29,0xfb,0x6f,0x29,0x02,0x00,0x25,0x21,0x2a,0x03,0x7d,0x2a,0xbb,0x0a,0x14,0x02,0x20,0x22,0x1e,0x1e,0x11,0x11,0x10,0x11,0x08,0x0d,0x0a,0x07,0x0b,0x08,0x26,0x2a,0x12,0x12,0x30,0x20,0x03,0x0f,0x08,0xfd,0x87,0x0a,0x14, 0x02,0x20,0x22,0x1e,0x1e,0x11,0x11,0x10,0x11,0x08,0x0d,0x0a,0x07,0x0b,0x08,0x26,0x2a,0x12,0x12,0x30,0x20,0x03,0x0f,0x08,0xff,0xff,0x00,0x29,0x03,0xcb,0x02,0x25,0x04,0xdc,0x00,0x07,0x09,0x2c,0x00,0x24,0xfd,0x4f,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x4e,0x04,0xdc,0x00,0x27,0x09,0x2c,0x00,0x24,0xfd,0x4f,0x00,0x06,0x14,0x02, 0x00,0x00,0xff,0xff,0x00,0x05,0x03,0x9a,0x02,0x9c,0x05,0x53,0x00,0x07,0x09,0x2d,0x00,0xd2,0xfd,0x45,0x00,0x01,0x00,0x9a,0xff,0xf2,0x03,0x2a,0x02,0xdd,0x00,0x13,0x00,0x10,0xb1,0x0a,0x12,0xba,0x04,0xfb,0x00,0x01,0x05,0x03,0x00,0x3f,0xed,0x2f,0x30,0x31,0x05,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14, 0x1e,0x02,0x33,0x33,0x03,0x2a,0x79,0x9c,0xce,0x7b,0x32,0x12,0x11,0x9a,0x0e,0x12,0x21,0x5a,0xa1,0x81,0x56,0x0e,0x50,0x87,0xb2,0x63,0x3f,0x7b,0x45,0x40,0x6f,0x3e,0x4a,0x7c,0x5c,0x33,0xff,0xff,0x00,0x05,0xfe,0x60,0x02,0x01,0xff,0x71,0x00,0x06,0x09,0x2e,0x00,0x00,0xff,0xff,0x00,0x15,0x03,0xcb,0x02,0x11,0x04,0x23,0x00,0x07, 0x09,0x2f,0x00,0x10,0xfd,0x4f,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x4e,0x04,0x23,0x02,0x26,0x14,0x02,0x00,0x00,0x00,0x07,0x09,0x2f,0x00,0x10,0xfd,0x4f,0xff,0xff,0x00,0x21,0x03,0x90,0x02,0x2c,0x05,0x49,0x00,0x07,0x09,0x30,0x00,0x62,0xfd,0x3b,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x4e,0x05,0x49,0x00,0x27,0x09,0x30,0x00,0x62, 0xfd,0x3b,0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0x00,0x29,0xff,0x19,0x02,0x25,0xff,0x71,0x00,0x06,0x09,0x31,0x24,0x00,0xff,0xff,0xff,0xba,0xff,0x19,0x02,0x4e,0x00,0x99,0x00,0x26,0x09,0x31,0x24,0x00,0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0xff,0xf8,0x03,0xc5,0x02,0x57,0x04,0xef,0x00,0x07,0x09,0x32,0x00,0x24,0xfd,0x4f, 0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x57,0x04,0xef,0x00,0x27,0x09,0x32,0x00,0x24,0xfd,0x4f,0x00,0x06,0x14,0x02,0x00,0x00,0xff,0xff,0x00,0x69,0x03,0xbb,0x01,0xe5,0x05,0x2e,0x00,0x07,0x09,0x33,0x00,0x24,0xfd,0x45,0xff,0xff,0xff,0xba,0xff,0xf2,0x02,0x4e,0x05,0x2e,0x00,0x27,0x09,0x33,0x00,0x24,0xfd,0x45,0x00,0x06,0x14,0x02, 0x00,0x00,0x00,0x01,0xff,0xba,0xff,0xf2,0x02,0x4e,0x00,0x99,0x00,0x08,0x00,0x0e,0xbb,0x00,0x08,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x30,0x31,0x05,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x02,0x4e,0xfd,0xb2,0x23,0x23,0x23,0x23,0x02,0x4e,0x0e,0x34,0x20,0x20,0x33,0x00,0x01,0xff,0xe7,0x06,0x19,0x05,0x0f,0x07,0x5f, 0x00,0x1a,0x00,0x16,0xbc,0x00,0x12,0x04,0xfb,0x00,0x07,0x00,0x19,0x04,0xfb,0xb1,0x0c,0x02,0x00,0x2f,0x33,0xed,0xdc,0xed,0x30,0x31,0x01,0x07,0x21,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x23,0x3e,0x03,0x33,0x32,0x1e,0x04,0x33,0x21,0x05,0x0f,0x5a,0xfd,0xf4,0x4a,0x7d,0x66,0x4d,0x19,0x10,0x27,0x2e,0x34,0x1d,0x79,0x28,0x57, 0x5a,0x59,0x2a,0x18,0x39,0x3f,0x44,0x49,0x4c,0x27,0x02,0x3c,0x06,0xb6,0x9d,0x32,0x3d,0x32,0x08,0x1f,0x3c,0x34,0x55,0x78,0x4c,0x23,0x18,0x23,0x29,0x23,0x18,0x00,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x04,0x76,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0xad,0xfe,0xab,0x00,0x07,0x09,0x7e,0x02,0xb6,0xfc,0x8d, 0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x14,0x05,0x3e,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x83,0xfe,0xab,0x00,0x07,0x09,0x7e,0x00,0x72,0xfd,0x55,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0x3e,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x83,0xfe,0xab,0x00,0x07,0x09,0x7e,0x00,0x72,0xfd,0x55, 0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x04,0x76,0x02,0x26,0x0e,0x6e,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0xad,0xfe,0xab,0x00,0x07,0x09,0x7e,0x02,0xb6,0xfc,0x8d,0xff,0xff,0x00,0xc4,0xfd,0xe4,0x01,0x42,0xff,0x6c,0x00,0x07,0x09,0x73,0x00,0x00,0xf7,0x68,0xff,0xff,0x00,0x52,0xfd,0xc9,0x03,0x4a,0x03,0xba,0x02,0x26,0x09,0x15, 0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xc9,0xfd,0xce,0xff,0xff,0x00,0x52,0xfd,0xc9,0x04,0x02,0x03,0xba,0x02,0x26,0x0e,0x2f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0xc9,0xfd,0xce,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x09,0xf7,0x03,0x3c,0x02,0x26,0x09,0x1b,0x00,0x00,0x00,0x07,0x0f,0x54,0x06,0x46,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9, 0x07,0x4b,0x03,0x3c,0x02,0x26,0x08,0xd6,0x00,0x00,0x00,0x07,0x0f,0x54,0x03,0x9c,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x08,0x04,0x03,0x3c,0x02,0x26,0x0e,0x36,0x00,0x00,0x00,0x07,0x0f,0x54,0x03,0x9c,0xfd,0xce,0xff,0xff,0x00,0x9b,0xfd,0xc9,0x0a,0xb0,0x03,0x3c,0x02,0x26,0x0e,0x35,0x00,0x00,0x00,0x07,0x0f,0x54,0x06,0x46, 0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0xb9,0x06,0x02,0x02,0x26,0x09,0x46,0x00,0x00,0x00,0x07,0x14,0x18,0x06,0xe0,0xff,0x38,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x5d,0x06,0x02,0x02,0x26,0x08,0xed,0x00,0x00,0x00,0x07,0x14,0x18,0x03,0x84,0xff,0x38,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x06,0x02,0x02,0x26,0x0e,0x56, 0x00,0x00,0x00,0x07,0x14,0x18,0x03,0x84,0xff,0x38,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x06,0x02,0x02,0x26,0x0e,0xb1,0x00,0x00,0x00,0x07,0x14,0x18,0x06,0xe0,0xff,0x38,0x00,0x02,0x00,0xab,0xfe,0x0c,0x03,0x49,0x02,0xb7,0x00,0x15,0x00,0x29,0x00,0x18,0xb1,0x11,0x1d,0xbd,0x04,0xfb,0x00,0x0a,0x00,0x27,0x04,0xfb,0x00,0x00, 0x05,0x03,0x00,0x3f,0xed,0x2f,0xed,0x2f,0x30,0x31,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x11,0x23,0x11,0x06,0x06,0x37,0x2e,0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x01,0xff,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x36,0x36,0x9c,0x2a,0x58,0x7e,0x01, 0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0x0e,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x55,0xf0,0x92,0xfd,0xd5,0x02,0x09,0x11,0x12,0xc7,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0x00,0x02,0x00,0xab,0xfe,0x0c,0x04,0x02,0x02,0xb7,0x00,0x18, 0x00,0x2c,0x00,0x23,0xb1,0x14,0x11,0x41,0x0a,0x04,0xfb,0x00,0x13,0x05,0x03,0x00,0x20,0x04,0xfb,0x00,0x0a,0x00,0x2a,0x04,0xfb,0x00,0x00,0x05,0x03,0x00,0x3f,0xed,0x2f,0xed,0x3f,0xed,0x2f,0x30,0x31,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x17,0x33,0x15,0x23,0x11,0x23,0x11,0x06,0x06,0x37,0x2e, 0x05,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x01,0xff,0x42,0x7b,0x5e,0x39,0x30,0x55,0x74,0x44,0x48,0x77,0x36,0x2d,0x33,0x08,0xbd,0xb9,0x9c,0x2a,0x58,0x7e,0x01,0x10,0x1b,0x24,0x2d,0x32,0x1b,0x1d,0x37,0x2c,0x1b,0x22,0x39,0x4a,0x28,0x27,0x4e,0x0e,0x29,0x4f,0x72,0x4a,0x40,0x8d,0x77,0x4d,0x54,0x55,0x47,0xbc, 0x72,0xa7,0xfe,0x1a,0x02,0x09,0x11,0x12,0xc7,0x19,0x45,0x4b,0x49,0x3b,0x24,0x26,0x3c,0x4c,0x26,0x25,0x3b,0x28,0x16,0x0d,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0xc3,0x05,0xca,0x02,0x26,0x09,0x17,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9a,0x03,0x57,0x00,0x07,0x0a,0x6e,0x00,0x9b,0xfd,0xee,0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57, 0x05,0xca,0x02,0x26,0x0b,0x0c,0x00,0x00,0x00,0x27,0x0f,0x50,0x00,0x9a,0x03,0x57,0x00,0x07,0x0a,0x6e,0x00,0x9b,0xfd,0xee,0x00,0x01,0x00,0x8c,0x06,0x56,0x01,0xc8,0x08,0x05,0x00,0x18,0x00,0x0c,0xb3,0x08,0x0e,0x00,0x18,0x00,0x2f,0xcd,0xdc,0xcd,0x30,0x31,0x13,0x3e,0x03,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x33,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x8c,0x2a,0x49,0x35,0x1f,0x3e,0x2d,0x10,0x1d,0x0d,0x21,0x1f,0x37,0x52,0x36,0x1b,0x2d,0x53,0x75,0x47,0x06,0xa9,0x0a,0x17,0x23,0x33,0x26,0x29,0x2a,0x04,0x03,0x6d,0x06,0x1c,0x2e,0x3e,0x22,0x3e,0x57,0x3c,0x26,0x0e,0x00,0x00,0x01,0xfe,0x45,0x04,0x3a,0xff,0xd9,0x05,0xc0,0x00,0x03,0x00,0x0c, 0xb3,0x03,0x02,0x01,0x00,0x00,0x2f,0x32,0xcd,0x32,0x30,0x31,0x01,0x35,0x01,0x15,0xfe,0x45,0x01,0x94,0x04,0x3a,0x85,0x01,0x01,0x8f,0xff,0xff,0x00,0x14,0xff,0xe8,0x02,0x2b,0x05,0x9a,0x02,0x06,0x00,0x2d,0x00,0x00,0xff,0xff,0x00,0xbc,0xfe,0x80,0x05,0xbb,0x05,0x9a,0x00,0x26,0x01,0xb5,0x00,0x00,0x00,0x07,0x0a,0xbd,0x03,0x5b, 0x00,0x00,0xff,0xff,0x00,0xa6,0xfe,0x8a,0x04,0x91,0x04,0x00,0x00,0x26,0x02,0x16,0x00,0x00,0x00,0x07,0x0a,0xbe,0x02,0x44,0x00,0x00,0x00,0x01,0xff,0x98,0xfe,0x96,0x04,0xf2,0x05,0x9a,0x00,0x13,0x00,0x1d,0x40,0x0e,0x10,0x91,0x0b,0x0b,0x06,0x07,0x91,0x01,0x01,0x06,0x12,0x03,0x00,0x03,0x00,0x3f,0x32,0x3f,0x39,0x2f,0xed,0x11, 0x33,0x2f,0xed,0x30,0x31,0x01,0x11,0x21,0x11,0x33,0x11,0x23,0x11,0x21,0x11,0x10,0x21,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x01,0x64,0x02,0xe6,0xa8,0xa8,0xfd,0x1a,0xfe,0xbc,0x4c,0x3c,0x36,0x44,0xaa,0x05,0x9a,0xfd,0x8b,0x02,0x75,0xfa,0x66,0x02,0x8e,0xfd,0x9d,0xfe,0x6b,0x1a,0x94,0x17,0x01,0x08,0x05,0x65,0x00,0x00,0x01, 0xff,0x5c,0xfe,0x1e,0x03,0xf8,0x04,0x00,0x00,0x16,0x00,0x1f,0x40,0x0f,0x16,0x95,0x10,0x10,0x0e,0x14,0x0a,0x95,0x05,0x05,0x14,0x15,0x11,0x0e,0x0f,0x00,0x3f,0x33,0x3f,0x33,0x2f,0xed,0x11,0x12,0x39,0x2f,0xed,0x30,0x31,0x05,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x11,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x23,0x11, 0x21,0x01,0x4a,0x31,0x5d,0x87,0x57,0x4b,0x37,0x3d,0x45,0xc8,0xa4,0x02,0x0a,0xa4,0xa4,0xfd,0xf6,0x04,0x73,0xb2,0x7a,0x3f,0x1a,0x99,0x27,0x01,0x3e,0x04,0x18,0xfe,0x5c,0x01,0xa4,0xfc,0x00,0x01,0xd1,0x00,0x00,0x02,0x00,0x0f,0xfe,0x7f,0x0a,0x06,0x05,0x9a,0x00,0x25,0x00,0x2e,0x00,0x32,0x40,0x1b,0x08,0x91,0x04,0x25,0x1e,0x03, 0x1a,0x1a,0x07,0x23,0x1c,0x03,0x27,0x91,0x19,0x03,0x12,0x0a,0x26,0x91,0x10,0x0c,0x0e,0x12,0x01,0x07,0x12,0x00,0x3f,0x33,0x3f,0xcd,0x32,0xed,0x32,0x32,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x17,0x39,0xed,0x30,0x31,0x21,0x23,0x01,0x26,0x27,0x23,0x11,0x23,0x11,0x21,0x11,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x36,0x12, 0x37,0x12,0x13,0x21,0x11,0x21,0x11,0x33,0x11,0x33,0x36,0x36,0x37,0x01,0x33,0x01,0x01,0x11,0x21,0x06,0x02,0x07,0x06,0x02,0x07,0x0a,0x06,0xea,0xfd,0xd6,0x1e,0x08,0x04,0xa8,0xfe,0x67,0xc1,0x9b,0xfb,0xfd,0x9b,0x6f,0x48,0x79,0x33,0x65,0x0d,0x02,0xa3,0x01,0x99,0xa8,0x04,0x07,0x13,0x0c,0x02,0x18,0xd1,0xfd,0x99,0xfc,0x6b,0xfe, 0x94,0x08,0x36,0x30,0x30,0x67,0x3a,0x02,0x90,0x24,0x0e,0xfd,0x3e,0x02,0x8e,0xfe,0x0a,0xfd,0xe7,0x01,0x81,0xfe,0x7f,0x02,0x19,0x84,0x01,0x31,0xb1,0x01,0x61,0x01,0x3b,0xfd,0x8b,0x02,0x75,0xfd,0x5e,0x0b,0x18,0x0e,0x02,0x71,0xfd,0x50,0xfd,0xae,0x04,0x6a,0x7d,0xfe,0xe2,0xa7,0xa7,0xfe,0xee,0x6f,0x00,0x02,0x00,0x12,0xfe,0x8b, 0x08,0x44,0x04,0x00,0x00,0x1d,0x00,0x22,0x00,0x32,0x40,0x1b,0x07,0x95,0x02,0x1d,0x19,0x03,0x15,0x15,0x05,0x1b,0x17,0x0f,0x1f,0x95,0x14,0x0f,0x10,0x08,0x1e,0x95,0x0e,0x0a,0x0c,0x15,0x01,0x05,0x15,0x00,0x3f,0x33,0x3f,0xcd,0x32,0xed,0x32,0x32,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x17,0x39,0xed,0x30,0x31,0x21,0x23,0x01,0x23, 0x11,0x23,0x11,0x21,0x11,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x33,0x00,0x13,0x21,0x11,0x21,0x11,0x33,0x11,0x33,0x01,0x33,0x01,0x01,0x11,0x23,0x02,0x03,0x08,0x44,0xe6,0xfe,0x3c,0x04,0xa4,0xfe,0x99,0x98,0x8b,0xfd,0x06,0x8c,0x5b,0x01,0x05,0x05,0x02,0x14,0x01,0x67,0xa4,0x04,0x01,0xae,0xd7,0xfe,0x25,0xfc,0xa3,0xe3,0x1b, 0xce,0x01,0xec,0xfe,0x14,0x01,0xd1,0xfe,0xba,0xfe,0x00,0x01,0x75,0xfe,0x8b,0x02,0x00,0x01,0x79,0x01,0xfc,0xfe,0x5c,0x01,0xa4,0xfe,0x2b,0x01,0xd5,0xfe,0x12,0xfe,0x79,0x02,0xea,0xfe,0x62,0xfe,0xb4,0x00,0x00,0x03,0x00,0x0f,0xfe,0x7f,0x05,0x48,0x05,0x9a,0x00,0x13,0x00,0x1a,0x00,0x1f,0x00,0x29,0x40,0x14,0x09,0x14,0x91,0x11, 0x1e,0x13,0x1b,0x1b,0x04,0x0e,0x13,0x03,0x08,0x00,0x18,0x91,0x06,0x02,0x04,0x12,0x00,0x3f,0xcd,0x32,0xed,0x32,0x32,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x33,0xed,0x32,0x30,0x31,0x25,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x01,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x17,0x01,0x33,0x01,0x22,0x27,0x01,0x21,0x11,0x06,0x27,0x32, 0x37,0x11,0x01,0x04,0x81,0xc7,0x9b,0xfb,0xfd,0x9b,0x01,0x40,0x53,0x56,0xa8,0x63,0x02,0x28,0xa8,0xfd,0xae,0x30,0x2b,0xfe,0xe2,0x03,0x23,0xe5,0xb0,0xb1,0xe4,0xfe,0x66,0x98,0xfd,0xe7,0x01,0x81,0xfe,0x7f,0x02,0x1a,0x01,0xa4,0x2d,0xa2,0x73,0x02,0x1b,0xfd,0xed,0x93,0x36,0x02,0xdc,0xfc,0x72,0x06,0xfe,0x86,0x01,0xed,0x79,0x94, 0x6e,0x01,0xb1,0xfd,0xe1,0x00,0x00,0x03,0x00,0x12,0xfe,0x8b,0x04,0x23,0x04,0x00,0x00,0x12,0x00,0x19,0x00,0x1f,0x00,0x2b,0x40,0x15,0x09,0x13,0xec,0x18,0x10,0x1d,0x0d,0x1a,0x1a,0x04,0x11,0x0d,0x0f,0x08,0x01,0x16,0x95,0x06,0x02,0x04,0x15,0x00,0x3f,0xcd,0x32,0xed,0x32,0x32,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x33,0x33,0xed, 0x32,0x30,0x31,0x25,0x33,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x37,0x26,0x35,0x11,0x33,0x11,0x14,0x17,0x01,0x33,0x01,0x22,0x27,0x07,0x21,0x11,0x06,0x27,0x32,0x37,0x11,0x01,0x16,0x03,0xdf,0x44,0x8b,0xfd,0x06,0x8c,0xe8,0x62,0xa4,0x30,0x01,0xd0,0xa3,0xfe,0x11,0x52,0x3f,0xb2,0x02,0x8f,0xb5,0x89,0x94,0xaa,0xfe,0x98,0x13,0x8b, 0xfe,0x00,0x01,0x75,0xfe,0x8b,0x02,0x00,0xfe,0x59,0xc4,0x01,0x5a,0xfe,0xae,0x6f,0x39,0x01,0xfa,0xfd,0x3a,0x15,0xc4,0x01,0x11,0x62,0x93,0x56,0x01,0x3a,0xfe,0x73,0x03,0x00,0xff,0xff,0x00,0x10,0xfe,0x80,0x05,0x60,0x05,0x9a,0x00,0x26,0x01,0xf2,0x00,0x00,0x00,0x07,0x0a,0xbd,0x03,0x00,0x00,0x00,0xff,0xff,0x00,0x10,0xfe,0x8a, 0x04,0x29,0x04,0x00,0x00,0x26,0x02,0x12,0x00,0x00,0x00,0x07,0x0a,0xbe,0x01,0xdc,0x00,0x00,0xff,0xff,0x00,0x5e,0xff,0xe8,0x0a,0x47,0x05,0xb2,0x02,0x06,0x12,0x8f,0x00,0x00,0xff,0xff,0x00,0x60,0xff,0xe8,0x07,0x98,0x04,0x18,0x02,0x06,0x12,0x90,0x00,0x00,0x00,0x05,0x00,0x5e,0xff,0xe8,0x05,0xaa,0x05,0xb2,0x00,0x13,0x00,0x1a, 0x00,0x21,0x00,0x28,0x00,0x2f,0x00,0x22,0x40,0x11,0x15,0x2a,0x91,0x23,0x21,0x21,0x00,0x24,0x20,0x91,0x0a,0x03,0x14,0x2b,0x91,0x00,0x12,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x30,0x31,0x05,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x24,0x33,0x32,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x06,0x27,0x11, 0x21,0x1e,0x03,0x01,0x2e,0x03,0x27,0x11,0x21,0x21,0x11,0x0e,0x03,0x01,0x21,0x11,0x3e,0x03,0x02,0xfe,0x98,0xf8,0xb0,0x60,0x61,0xb4,0x01,0x02,0xa1,0x94,0xf3,0xae,0x5f,0x61,0xb3,0xfc,0xdf,0xfe,0x57,0x09,0x45,0x6f,0x94,0x02,0x93,0x08,0x40,0x6b,0x92,0x5a,0xfd,0xbb,0x01,0xa9,0x59,0x93,0x6e,0x45,0x03,0xda,0xfe,0x61,0x5b,0x91, 0x6a,0x40,0x18,0x6a,0xbf,0x01,0x0a,0xa1,0xac,0x01,0x18,0xc6,0x6c,0x6a,0xbf,0xfe,0xf6,0xa0,0xaf,0xfe,0xe7,0xc5,0x6a,0x9b,0x01,0xfa,0x6b,0xb0,0x82,0x51,0x02,0x89,0x6e,0xb2,0x82,0x4f,0x0c,0xfe,0x03,0x01,0xfc,0x0d,0x53,0x84,0xaf,0xfe,0xfc,0xfe,0x08,0x0d,0x50,0x80,0xaf,0x00,0x00,0x05,0x00,0x60,0xff,0xe8,0x04,0x50,0x04,0x18, 0x00,0x13,0x00,0x17,0x00,0x1e,0x00,0x22,0x00,0x27,0x00,0x22,0x40,0x11,0x19,0x15,0x95,0x24,0x22,0x22,0x00,0x25,0x21,0x95,0x0a,0x0f,0x18,0x16,0x95,0x00,0x15,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x12,0x39,0x2f,0x33,0xed,0x32,0x30,0x31,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x13,0x21, 0x11,0x36,0x05,0x11,0x21,0x1e,0x03,0x01,0x02,0x27,0x11,0x21,0x21,0x11,0x06,0x06,0x02,0x52,0x72,0xb8,0x82,0x46,0x49,0x88,0xc1,0x78,0x73,0xb4,0x7d,0x42,0x48,0x84,0xbd,0xdf,0xfe,0xfe,0xef,0xfe,0x7d,0xfe,0xfa,0x06,0x26,0x40,0x5c,0x01,0xd0,0x24,0xda,0xfe,0x6a,0x01,0x02,0x69,0x85,0x18,0x4c,0x8a,0xc1,0x75,0x81,0xcb,0x8d,0x4b, 0x49,0x8a,0xc5,0x7c,0x79,0xc7,0x8e,0x4e,0x01,0xe9,0xfe,0xa6,0x25,0x23,0x01,0x58,0x42,0x72,0x5a,0x3d,0x01,0xd6,0x01,0x0a,0x22,0xfe,0xd4,0x01,0x2a,0x15,0x98,0x00,0xff,0xff,0x00,0x0c,0x06,0x1f,0x02,0xe6,0x09,0x39,0x02,0x06,0x13,0x7b,0x00,0x00,0xff,0xff,0x00,0x5a,0x06,0x1f,0x02,0x57,0x09,0x39,0x02,0x06,0x13,0x7d,0x00,0x00, 0x00,0x03,0x00,0x28,0xff,0xe8,0x04,0xca,0x05,0x88,0x00,0x4a,0x00,0x68,0x00,0x79,0x00,0x54,0x40,0x16,0x3a,0x37,0x99,0x40,0x32,0x27,0x2e,0x03,0x5a,0x4f,0x2b,0x00,0x4a,0x4a,0x2b,0x9a,0x55,0x55,0x22,0x9a,0x5e,0x07,0xb8,0x01,0x7f,0xb2,0x6f,0x6f,0x4b,0xb8,0x01,0x7f,0x40,0x0a,0x18,0x5e,0x18,0x5e,0x18,0x11,0x3b,0x40,0x19,0x75, 0xb9,0x01,0x7d,0x00,0x11,0x00,0x2f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x2f,0xed,0x10,0xed,0x33,0x2f,0xed,0x32,0x2f,0x33,0x10,0xcd,0x32,0x17,0x39,0x10,0xed,0x32,0x30,0x31,0x13,0x3e,0x03,0x37,0x11,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x15,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e, 0x02,0x23,0x22,0x2e,0x02,0x27,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x07,0x1e,0x03,0x33,0x32,0x36,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x07,0x01,0x11,0x36,0x36,0x37,0x17,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x17,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x01,0x14,0x1e,0x02, 0x33,0x33,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x7c,0x09,0x2b,0x3c,0x48,0x26,0x23,0x56,0x6b,0x3a,0x14,0x25,0x41,0x59,0x35,0x3e,0x56,0x36,0x18,0x01,0x6f,0x49,0x7f,0x5e,0x37,0x1a,0x3a,0x5d,0x43,0x12,0x26,0x25,0x20,0x0c,0x07,0x18,0x3b,0x26,0x20,0x3e,0x17,0x07,0x0e,0x28,0x19,0x07,0x27,0x3f,0x58,0x39,0x5b,0x8b,0x34,0x1c, 0x47,0x4c,0x4d,0x22,0x5b,0x91,0x69,0x40,0x09,0x24,0x44,0x3c,0x30,0x0e,0x01,0x82,0x21,0x2e,0x07,0x3b,0x05,0x0f,0x1b,0x15,0x15,0x2a,0x22,0x15,0x3b,0x30,0x2b,0x10,0x26,0x22,0x17,0x24,0x3d,0x51,0x2e,0xfd,0x4e,0x0d,0x21,0x38,0x2c,0x0c,0x03,0x0e,0x1e,0x1b,0x17,0x20,0x14,0x09,0x01,0x97,0x01,0x09,0x0f,0x15,0x0e,0x01,0x9d,0x37, 0x50,0x59,0x21,0x43,0x68,0x47,0x25,0x2c,0x46,0x56,0x2b,0x98,0x2a,0x4f,0x72,0x49,0x3e,0x78,0x5e,0x3b,0x06,0x11,0x1b,0x15,0x26,0x21,0x20,0x27,0x0b,0x14,0x0a,0x54,0x6c,0x40,0x19,0x35,0x30,0xb1,0x13,0x1c,0x13,0x09,0x2b,0x5d,0x92,0x67,0x08,0x0e,0x0a,0x07,0x02,0x02,0x30,0xfe,0xb3,0x17,0x37,0x20,0x11,0x14,0x2d,0x27,0x19,0x1c, 0x2c,0x33,0x17,0x11,0x39,0x48,0x14,0x2d,0x46,0x32,0x2e,0x45,0x2e,0x17,0x01,0x1b,0x21,0x35,0x25,0x13,0x7a,0x1b,0x3a,0x30,0x1f,0x17,0x27,0x34,0x00,0x01,0xff,0x38,0x06,0x19,0x05,0x0f,0x06,0xc0,0x00,0x04,0x00,0x0c,0xba,0x00,0x02,0x04,0xfb,0x00,0x00,0x00,0x2f,0xed,0x30,0x31,0x01,0x21,0x35,0x21,0x15,0x04,0xb5,0xfa,0x83,0x05, 0xd7,0x06,0x19,0xa7,0x0a,0x00,0x00,0x01,0x00,0x50,0x00,0x00,0x05,0x26,0x06,0x50,0x00,0x3b,0x00,0x2e,0x40,0x12,0x3a,0x31,0x00,0x30,0x17,0x0b,0x11,0x9a,0x36,0x15,0x06,0x0d,0x0d,0x23,0x36,0x07,0x26,0x21,0xb8,0x01,0x7f,0xb1,0x23,0x18,0x00,0x3f,0xed,0x32,0x3f,0x12,0x39,0x2f,0x33,0x33,0x10,0xed,0x32,0x32,0x39,0x39,0xcc,0x32, 0x30,0x31,0x01,0x1e,0x03,0x17,0x23,0x2e,0x03,0x27,0x11,0x23,0x11,0x26,0x26,0x23,0x22,0x06,0x07,0x11,0x23,0x11,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x21,0x15,0x21,0x35,0x21,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x15,0x36,0x36,0x33,0x32,0x16,0x17,0x35,0x33,0x03,0x6d,0x67,0xa0,0x6f,0x3e,0x05,0xa5,0x05,0x23,0x42,0x65, 0x45,0x72,0x0e,0x1e,0x0f,0x12,0x21,0x10,0x72,0x47,0x67,0x43,0x20,0x45,0x83,0xbd,0x78,0x01,0xd7,0xfb,0xb4,0x01,0x12,0x4a,0x78,0x54,0x2e,0x40,0x74,0xa4,0x63,0x72,0x11,0x23,0x12,0x0e,0x1c,0x0e,0x72,0x05,0x9c,0x1b,0x76,0xa6,0xcd,0x73,0x5c,0x9d,0x7d,0x59,0x18,0xfe,0x19,0x01,0xff,0x01,0x02,0x02,0x02,0xfe,0x02,0x01,0xe1,0x1d, 0x69,0x8e,0xae,0x62,0x78,0xd9,0xa4,0x61,0x8c,0x8c,0x22,0x7c,0xa1,0xbb,0x62,0x7c,0xde,0xb3,0x81,0x20,0xba,0xa2,0x02,0x02,0x02,0x01,0xa1,0x00,0x00,0x03,0x00,0xbc,0xff,0x2f,0x03,0xea,0x06,0x50,0x00,0x28,0x00,0x33,0x00,0x3e,0x00,0x38,0x40,0x0b,0x12,0x2a,0x99,0x35,0x35,0x27,0x26,0x06,0x00,0x00,0x34,0xb8,0x01,0x80,0xb7,0x08, 0x02,0x27,0x06,0x1d,0x24,0x24,0x2b,0xb8,0x01,0x80,0xb3,0x22,0x1b,0x26,0x18,0x00,0x3f,0x33,0x33,0xed,0x33,0x2f,0x33,0x3f,0x33,0x33,0xed,0x33,0x2f,0x33,0x11,0x12,0x39,0x2f,0xed,0x39,0x30,0x31,0x01,0x33,0x15,0x33,0x32,0x17,0x35,0x33,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x15,0x14,0x06,0x07,0x15,0x23,0x35, 0x06,0x22,0x23,0x23,0x15,0x23,0x35,0x23,0x11,0x33,0x13,0x23,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x27,0x03,0x11,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x01,0x7f,0x68,0x0f,0x23,0x24,0x68,0x3a,0x62,0x48,0x29,0x24,0x42,0x5b,0x37,0x48,0x71,0x4e,0x29,0xa9,0x9c,0x68,0x11,0x22,0x12,0x11,0x68,0xc3,0xc3,0x77,0x92,0x94,0x48,0x77, 0x54,0x2f,0xdc,0xfa,0x92,0x81,0x8b,0x17,0x3c,0x68,0x51,0x06,0x50,0xb6,0x03,0xb9,0xc7,0x0c,0x30,0x4b,0x69,0x47,0x3d,0x6c,0x58,0x41,0x12,0x04,0x09,0x3c,0x5c,0x78,0x45,0xac,0xc2,0x1f,0xe0,0xd3,0x02,0xd1,0xd1,0x05,0x9a,0xfd,0x02,0xfd,0xfc,0x1a,0x3d,0x64,0x4b,0xd9,0x1f,0x02,0x6c,0xfe,0x31,0x82,0x7c,0x2b,0x4c,0x39,0x21,0x00, 0x00,0x01,0x00,0x66,0xfe,0xef,0x02,0x50,0x02,0x19,0x00,0x13,0x00,0x12,0xb6,0x04,0x11,0x11,0x0b,0x0c,0x01,0x0b,0x00,0x2f,0x33,0x2f,0x12,0x39,0x2f,0x33,0x30,0x31,0x01,0x23,0x11,0x34,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x11,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0x7f,0x6d,0x1d,0x2e,0x21,0x12,0x80,0x80,0x02,0x3a,0x7a, 0xb4,0xfe,0xef,0x01,0x33,0x97,0x16,0x28,0x36,0x1f,0xfe,0xc9,0x03,0x2a,0xfe,0xa4,0x67,0xe7,0xff,0xff,0x00,0x66,0xfe,0xef,0x02,0x56,0x02,0x19,0x02,0x07,0x07,0xb1,0x00,0x00,0xfc,0x55,0x00,0x01,0x00,0x66,0xfe,0xef,0x00,0xe6,0x02,0x19,0x00,0x03,0x00,0x08,0xb1,0x03,0x00,0x00,0x2f,0x2f,0x30,0x31,0x13,0x23,0x11,0x33,0xe6,0x80, 0x80,0xfe,0xef,0x03,0x2a,0x00,0xff,0xff,0x00,0x66,0xfe,0xef,0x03,0x9a,0x01,0x24,0x02,0x07,0x07,0xb2,0x00,0x00,0xfc,0x55,0x00,0x01,0x00,0x66,0xfe,0xef,0x02,0x50,0x01,0x24,0x00,0x13,0x00,0x14,0xb7,0x04,0x11,0x11,0x0e,0x0b,0x0c,0x01,0x0b,0x00,0x2f,0x33,0x2f,0x12,0x39,0x33,0x2f,0x33,0x30,0x31,0x01,0x23,0x11,0x34,0x23,0x22, 0x0e,0x02,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x33,0x32,0x15,0x02,0x50,0x7f,0x6d,0x1d,0x2e,0x21,0x12,0x80,0x80,0x02,0x3a,0x7a,0xb4,0xfe,0xef,0x01,0x33,0x97,0x16,0x28,0x36,0x1f,0xfe,0xc9,0x02,0x24,0x56,0x67,0xe7,0x00,0xff,0xff,0x00,0x66,0xfd,0xf9,0x02,0x89,0x01,0x24,0x02,0x07,0x07,0xb8,0x00,0x00,0xfc,0x55,0x00,0x01, 0x00,0x3c,0xfe,0xdc,0x01,0xcd,0x01,0x26,0x00,0x2e,0x00,0x12,0xb6,0x06,0x1f,0x15,0x03,0x2c,0x1c,0x15,0x00,0x2f,0x33,0x2f,0x33,0x12,0x39,0x39,0x30,0x31,0x17,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x15, 0x14,0x0e,0x02,0x23,0x22,0x27,0x3c,0x28,0x59,0x2f,0x33,0x32,0x10,0x1d,0x27,0x16,0x2c,0x40,0x2a,0x14,0x22,0x3b,0x51,0x30,0x2a,0x4e,0x20,0x23,0x4d,0x2d,0x2a,0x34,0x39,0x33,0x27,0x3f,0x2c,0x17,0x27,0x42,0x55,0x2e,0x60,0x45,0x96,0x16,0x15,0x1d,0x21,0x13,0x1a,0x14,0x10,0x09,0x10,0x21,0x27,0x30,0x21,0x28,0x3e,0x2a,0x16,0x0f, 0x0e,0x6d,0x0f,0x14,0x1a,0x1d,0x20,0x26,0x13,0x0f,0x1f,0x28,0x32,0x21,0x2b,0x40,0x2a,0x15,0x25,0x00,0xff,0xff,0x00,0x0a,0xfe,0xe3,0x01,0x68,0x01,0xb7,0x02,0x07,0x07,0xb9,0x00,0x00,0xfc,0x55,0x00,0x03,0x00,0x1e,0x04,0xdb,0x03,0x93,0x0a,0x63,0x00,0x1d,0x00,0x26,0x00,0x31,0x00,0x27,0x40,0x11,0x1f,0x1d,0x1d,0x27,0x04,0x1e, 0x13,0x13,0x28,0x0e,0x04,0x0e,0x04,0x0e,0x02,0x10,0x02,0x00,0x2f,0x2f,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x33,0x2f,0x33,0x11,0x33,0x33,0x2f,0x33,0x30,0x31,0x01,0x11,0x23,0x11,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x11,0x33,0x11,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x03,0x11,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x02,0x14,0x77,0x12,0x52,0x87,0x60,0x34,0x36,0x61,0x88,0x53,0x0d,0x77,0x0a,0x54,0x8a,0x62,0x35,0x34,0x5f,0x86,0x52,0x14,0x0a,0x73,0x7f,0x7c,0x71,0x86,0x0d,0x70,0x7f,0x20,0x3e,0x5a,0x3b,0x06,0x29,0xfe,0xb2,0x01,0x4e,0x38,0x65,0x8d,0x55,0x5a,0x93,0x69,0x3a,0x01, 0x2b,0xfe,0xd5,0x3a,0x69,0x93,0x5a,0x54,0x8d,0x66,0x38,0x02,0xa4,0xfd,0xc6,0x95,0x84,0x89,0x98,0xfd,0xc6,0x02,0x3a,0x97,0x8a,0x41,0x67,0x4a,0x27,0x00,0x00,0x01,0x00,0x6e,0xff,0x35,0x02,0x7f,0x01,0x12,0x00,0x15,0x00,0x0e,0xb4,0x07,0x09,0x09,0x00,0x14,0x00,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x25,0x23,0x22,0x06,0x15,0x14, 0x16,0x33,0x33,0x15,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x21,0x02,0x7f,0xf3,0x4c,0x4c,0x50,0x48,0xf3,0xfe,0xf8,0x3d,0x62,0x45,0x25,0x23,0x42,0x60,0x3c,0x01,0x10,0x9d,0x3c,0x40,0x3f,0x36,0x77,0x20,0x3d,0x58,0x37,0x37,0x59,0x3f,0x22,0x00,0x02,0x00,0x6e,0xfe,0x48,0x02,0x7f,0x01,0x12,0x00,0x15,0x00,0x19,0x00,0x14, 0xb7,0x16,0x19,0x19,0x07,0x09,0x09,0x00,0x14,0x00,0x2f,0x33,0x33,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x25,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x21,0x11,0x21,0x35,0x21,0x02,0x7f,0xf3,0x4c,0x4c,0x50,0x48,0xf3,0xfe,0xf8,0x3d,0x62,0x45,0x25,0x23,0x42,0x60,0x3c,0x01,0x10, 0xfe,0x0a,0x01,0xf6,0x9d,0x3c,0x40,0x3f,0x36,0x77,0x20,0x3d,0x58,0x37,0x37,0x59,0x3f,0x22,0xfd,0x36,0x75,0x00,0x00,0x01,0x00,0x6e,0x05,0x32,0x02,0x7f,0x07,0x0f,0x00,0x15,0x00,0x0e,0xb4,0x07,0x09,0x09,0x00,0x14,0x00,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x01,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x21,0x22,0x2e,0x02, 0x35,0x34,0x3e,0x02,0x33,0x21,0x02,0x7f,0xf3,0x4c,0x4c,0x50,0x48,0xf3,0xfe,0xf8,0x3d,0x62,0x45,0x25,0x23,0x42,0x60,0x3c,0x01,0x10,0x06,0x9a,0x3c,0x40,0x3f,0x36,0x77,0x20,0x3d,0x58,0x37,0x37,0x59,0x3f,0x22,0x00,0x00,0x02,0x00,0x6e,0x04,0x45,0x02,0x7f,0x07,0x0f,0x00,0x15,0x00,0x19,0x00,0x14,0xb7,0x16,0x19,0x19,0x07,0x09, 0x09,0x00,0x14,0x00,0x2f,0x33,0x33,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x01,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x21,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x21,0x11,0x21,0x35,0x21,0x02,0x7f,0xf3,0x4c,0x4c,0x50,0x48,0xf3,0xfe,0xf8,0x3d,0x62,0x45,0x25,0x23,0x42,0x60,0x3c,0x01,0x10,0xfe,0x0a,0x01,0xf6,0x06,0x9a, 0x3c,0x40,0x3f,0x36,0x77,0x20,0x3d,0x58,0x37,0x37,0x59,0x3f,0x22,0xfd,0x36,0x75,0x00,0x01,0x00,0x6e,0x05,0x32,0x02,0x7f,0x07,0x0f,0x00,0x15,0x00,0x0e,0xb4,0x0d,0x0c,0x0c,0x14,0x00,0x00,0x2f,0x32,0x32,0x2f,0x33,0x30,0x31,0x13,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x21,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23, 0x6e,0x01,0x10,0x3c,0x60,0x42,0x23,0x25,0x45,0x62,0x3d,0xfe,0xf8,0xf3,0x48,0x50,0x4c,0x4c,0xf3,0x07,0x0f,0x22,0x3f,0x59,0x37,0x37,0x58,0x3d,0x20,0x77,0x36,0x3f,0x40,0x3c,0x00,0x02,0x00,0x6e,0x04,0x45,0x02,0x7f,0x07,0x0f,0x00,0x15,0x00,0x19,0x00,0x14,0xb7,0x19,0x16,0x16,0x0d,0x0c,0x0c,0x14,0x00,0x00,0x2f,0x32,0x32,0x2f, 0x33,0x33,0x2f,0x33,0x30,0x31,0x13,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x21,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x21,0x15,0x21,0x6e,0x01,0x10,0x3c,0x60,0x42,0x23,0x25,0x45,0x62,0x3d,0xfe,0xf8,0xf3,0x48,0x50,0x4c,0x4c,0xf3,0x01,0xf6,0xfe,0x0a,0x07,0x0f,0x22,0x3f,0x59,0x37,0x37,0x58,0x3d,0x20,0x77, 0x36,0x3f,0x40,0x3c,0xfe,0x20,0x75,0x00,0x00,0x01,0x00,0x6e,0xff,0x35,0x02,0x7f,0x01,0x12,0x00,0x15,0x00,0x0e,0xb4,0x0d,0x0c,0x0c,0x14,0x00,0x00,0x2f,0x32,0x32,0x2f,0x33,0x30,0x31,0x13,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x21,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x6e,0x01,0x10,0x3c,0x60,0x42,0x23,0x25, 0x45,0x62,0x3d,0xfe,0xf8,0xf3,0x48,0x50,0x4c,0x4c,0xf3,0x01,0x12,0x22,0x3f,0x59,0x37,0x37,0x58,0x3d,0x20,0x77,0x36,0x3f,0x40,0x3c,0x00,0x02,0x00,0x6e,0xfe,0x48,0x02,0x7f,0x01,0x12,0x00,0x15,0x00,0x19,0x00,0x14,0xb7,0x19,0x16,0x16,0x0d,0x0c,0x0c,0x14,0x00,0x00,0x2f,0x32,0x32,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x13,0x21, 0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x21,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x21,0x15,0x21,0x6e,0x01,0x10,0x3c,0x60,0x42,0x23,0x25,0x45,0x62,0x3d,0xfe,0xf8,0xf3,0x48,0x50,0x4c,0x4c,0xf3,0x01,0xf6,0xfe,0x0a,0x01,0x12,0x22,0x3f,0x59,0x37,0x37,0x58,0x3d,0x20,0x77,0x36,0x3f,0x40,0x3c,0xfe,0x20,0x75,0x00, 0xff,0xff,0x00,0x70,0x01,0xfe,0x01,0x50,0x02,0xdf,0x02,0x02,0x00,0xc3,0x00,0x00,0x00,0x01,0x00,0x29,0x00,0x00,0x04,0x0c,0x05,0x9a,0x00,0x0b,0x00,0x15,0x40,0x0a,0x09,0x04,0x91,0x06,0x03,0x0a,0x03,0x91,0x01,0x12,0x00,0x3f,0xed,0x32,0x3f,0xed,0x32,0x30,0x31,0x21,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x21,0x04, 0x0c,0xfc,0x1d,0x01,0x9d,0xfe,0x63,0x03,0xe3,0xfe,0x62,0x01,0x9e,0x98,0x04,0x6a,0x98,0x98,0xfb,0x96,0x00,0x02,0x00,0x20,0xff,0xde,0x02,0xd9,0x05,0xa4,0x00,0x1d,0x00,0x29,0x00,0x2a,0x40,0x19,0x07,0x21,0x00,0x16,0x04,0xb9,0x24,0xc9,0x24,0x02,0x24,0x14,0x14,0x0a,0x19,0x03,0xb6,0x1e,0xc6,0x1e,0x02,0x1e,0x04,0x0a,0x12,0x00, 0x3f,0x33,0x33,0x5d,0x3f,0x12,0x39,0x2f,0x33,0x5d,0x17,0x39,0x30,0x31,0x25,0x16,0x16,0x17,0x07,0x26,0x26,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x17,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x05,0x32,0x36,0x37,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x83,0x1c,0x2d,0x0d,0x91,0x09,0x18,0x0d,0x38, 0x86,0x4a,0x35,0x59,0x40,0x24,0x29,0x46,0x5f,0x35,0x77,0x66,0x12,0xa8,0x17,0xfe,0x7c,0x2c,0x4d,0x20,0x22,0x47,0x28,0x33,0x33,0x36,0xd6,0x29,0x63,0x37,0x35,0x1b,0x3d,0x17,0x33,0x29,0x1d,0x36,0x4d,0x30,0x32,0x50,0x37,0x1d,0x43,0x4e,0x6d,0x03,0x95,0xfc,0x68,0x52,0x9e,0x91,0x1b,0x20,0x1b,0x1d,0x20,0x19,0x1e,0x1c,0xff,0xff, 0x00,0x1a,0x00,0x00,0x04,0x9a,0x05,0x9a,0x02,0x02,0x00,0x3b,0x00,0x00,0x00,0x03,0x00,0xbc,0xfe,0x29,0x04,0x2f,0x05,0x9a,0x00,0x19,0x00,0x21,0x00,0x2b,0x00,0x22,0x40,0x11,0x0b,0x1a,0x91,0x23,0x23,0x00,0x1b,0x91,0x17,0x19,0x19,0x17,0x12,0x22,0x91,0x00,0x03,0x00,0x3f,0xed,0x3f,0x33,0x2f,0x10,0xed,0x12,0x39,0x2f,0xed,0x39, 0x30,0x31,0x13,0x21,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x23,0x11,0x23,0x13,0x11,0x33,0x32,0x36,0x35,0x34,0x21,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x21,0xbc,0x01,0x98,0x5d,0x95,0x69,0x39,0x22,0x40,0x5c,0x3a,0x48,0x75,0x54,0x2e,0x47,0x7c,0xab,0x63,0xfa,0xa8,0xa8,0xe4,0x95, 0xa2,0xfe,0xa6,0xc1,0xac,0x45,0x6e,0x4c,0x29,0xfe,0xed,0x05,0x9a,0x30,0x57,0x78,0x49,0x3d,0x6b,0x58,0x41,0x13,0x04,0x08,0x38,0x5a,0x7a,0x4a,0x5c,0x98,0x6c,0x3c,0xfe,0x29,0x04,0x73,0xfd,0xfc,0x8b,0x7b,0xfe,0x02,0x66,0xfe,0x31,0x22,0x41,0x5f,0x3c,0xd1,0xff,0xff,0x00,0xa7,0xfe,0x1f,0x04,0x15,0x05,0xfc,0x02,0x02,0x01,0xc4, 0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0xe8,0x07,0x58,0x05,0x9a,0x00,0x44,0x00,0x20,0x40,0x10,0x38,0x91,0x21,0x12,0x1c,0x17,0x3f,0x3f,0x0a,0x00,0x91,0x17,0x12,0x2e,0x0a,0x03,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x3f,0xed,0x30,0x31,0x25,0x32,0x12,0x11,0x34,0x2e,0x04,0x27,0x33,0x1e,0x05,0x15,0x14,0x02,0x06,0x06, 0x23,0x22,0x2e,0x02,0x27,0x0e,0x03,0x23,0x22,0x26,0x26,0x02,0x35,0x34,0x3e,0x04,0x37,0x33,0x0e,0x05,0x15,0x10,0x12,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x05,0x5d,0xa0,0xab,0x18,0x28,0x35,0x3a,0x3b,0x1b,0xb5,0x18,0x38,0x39,0x35,0x29,0x19,0x46,0x85,0xc0,0x79,0x4a,0x72,0x5a,0x47,0x1e,0x1f,0x47,0x5a,0x72, 0x49,0x7a,0xbf,0x85,0x46,0x19,0x29,0x35,0x39,0x38,0x18,0xb5,0x1b,0x3b,0x3a,0x35,0x28,0x18,0xaa,0xa1,0x5c,0x76,0x44,0x1a,0xa8,0x18,0x42,0x77,0x7f,0x01,0x0a,0x01,0x15,0x45,0x96,0x96,0x8f,0x7b,0x63,0x1e,0x1c,0x58,0x73,0x88,0x98,0xa4,0x54,0xa7,0xfe,0xff,0xb0,0x5b,0x16,0x2b,0x3f,0x29,0x29,0x3f,0x2b,0x16,0x5b,0xb0,0x01,0x01, 0xa7,0x54,0xa4,0x98,0x88,0x73,0x58,0x1c,0x1e,0x63,0x7b,0x8f,0x96,0x96,0x45,0xfe,0xeb,0xfe,0xf6,0x32,0x62,0x93,0x62,0x01,0xc7,0xfe,0x4d,0x66,0x9b,0x68,0x34,0x00,0xff,0xff,0x00,0x77,0xff,0xea,0x06,0x00,0x04,0x01,0x02,0x02,0x01,0xd5,0x00,0x01,0x00,0x02,0x00,0xa6,0x00,0x00,0x06,0x14,0x04,0x00,0x00,0x11,0x00,0x18,0x00,0x1e, 0x40,0x0f,0x12,0x95,0x04,0x04,0x00,0x11,0x95,0x02,0x0f,0x13,0x95,0x0f,0x0f,0x00,0x15,0x00,0x3f,0x32,0x2f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x30,0x31,0x21,0x23,0x11,0x21,0x11,0x21,0x32,0x1e,0x02,0x15,0x14,0x07,0x06,0x23,0x21,0x11,0x21,0x01,0x11,0x33,0x32,0x35,0x34,0x23,0x01,0x4a,0xa4,0x03,0x04,0x01,0x14,0x51,0x7f,0x58, 0x2e,0x5c,0x5c,0x8f,0xfe,0x39,0xfe,0x44,0x02,0x60,0xf6,0xcc,0xce,0x04,0x00,0xfe,0x6a,0x28,0x4e,0x71,0x49,0x93,0x54,0x53,0x03,0x74,0xfe,0x69,0xfe,0xaf,0xae,0xa3,0x00,0x02,0x00,0xa6,0xff,0xe8,0x05,0xfe,0x04,0x18,0x00,0x1f,0x00,0x28,0x00,0x27,0x40,0x15,0x23,0x95,0x1a,0x0f,0x01,0x95,0x28,0x28,0x0f,0x95,0x14,0x14,0x11,0x12, 0x0f,0x11,0x15,0x04,0x95,0x09,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x12,0x39,0x2f,0xed,0x33,0x2f,0xed,0x3f,0xed,0x30,0x31,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x27,0x21,0x11,0x23,0x11,0x33,0x11,0x21,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x05,0xfe,0xfd,0x2d,0x04, 0xaf,0x9b,0xac,0x92,0x88,0xdd,0x68,0xa8,0x78,0x44,0x04,0xfe,0xc8,0xa4,0xa4,0x01,0x3e,0x0f,0x52,0x7b,0x9c,0x59,0x65,0x9d,0x6b,0x38,0xa8,0x01,0x86,0x79,0x3a,0x64,0x4e,0x33,0x0a,0x01,0xd7,0xac,0xb9,0x72,0x9a,0x62,0x42,0x7f,0xb8,0x76,0xfe,0x29,0x04,0x00,0xfe,0x62,0x62,0xa2,0x73,0x3f,0x43,0x7f,0xb6,0x73,0x35,0x8f,0x9d,0x2c, 0x4f,0x6f,0x42,0x00,0x00,0x02,0x00,0x60,0xff,0xe8,0x06,0x37,0x04,0x18,0x00,0x2e,0x00,0x37,0x00,0x2e,0x40,0x19,0x32,0x95,0x29,0x0f,0x01,0x95,0x0c,0x0f,0x26,0x23,0x37,0x37,0x0f,0x1e,0x95,0x23,0x0f,0x14,0x95,0x0f,0x15,0x04,0x95,0x09,0x15,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x12,0x39,0x12,0x39,0xed,0x3f,0xed, 0x30,0x31,0x01,0x21,0x16,0x16,0x33,0x32,0x37,0x15,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x07,0x35,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x07,0x06,0x37,0xfd,0x2d,0x04,0xaf,0x9b,0xac,0x92,0x88, 0xdd,0x88,0xc8,0x3a,0x45,0xdd,0x91,0x85,0x69,0x73,0x81,0x4e,0x84,0x5f,0x35,0x31,0x5b,0x81,0x4f,0x85,0x77,0x77,0xa1,0x89,0xd0,0x3f,0x40,0xc7,0x79,0x65,0x9d,0x6b,0x38,0xa8,0x01,0x86,0x79,0x3a,0x64,0x4e,0x33,0x0a,0x01,0xd7,0xac,0xb9,0x72,0x9a,0x62,0x6d,0x69,0x66,0x70,0x32,0xa8,0x50,0x3b,0x6c,0x96,0x5b,0x5a,0x8f,0x65,0x36, 0x59,0x9c,0x47,0x73,0x65,0x66,0x72,0x43,0x7f,0xb6,0x73,0x35,0x8f,0x9d,0x2c,0x4f,0x6f,0x42,0x00,0x02,0x00,0x90,0xff,0xe8,0x07,0x2a,0x04,0x18,0x00,0x23,0x00,0x33,0x00,0x22,0x40,0x12,0x24,0x95,0x1a,0x0f,0x17,0x03,0x08,0x15,0x0b,0x0f,0x0f,0x95,0x08,0x15,0x2e,0x95,0x00,0x15,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x12,0x39,0x39, 0x3f,0xed,0x30,0x31,0x05,0x22,0x26,0x27,0x0e,0x03,0x23,0x20,0x11,0x11,0x33,0x11,0x10,0x21,0x32,0x3e,0x02,0x35,0x11,0x33,0x15,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x05,0x2c,0x81,0xc6,0x40,0x17,0x3d,0x58,0x77,0x4f,0xfe,0x5d,0xa3,0x01,0x00, 0x48,0x66,0x40,0x1d,0xa4,0x42,0xb2,0x6e,0x73,0xb4,0x7d,0x42,0x48,0x84,0xbd,0x69,0x4e,0x7f,0x59,0x30,0x30,0x5a,0x7e,0x4e,0xa0,0xaa,0xaa,0x18,0x5e,0x57,0x23,0x41,0x33,0x1e,0x01,0xb4,0x02,0x64,0xfd,0xb6,0xfe,0xbc,0x2f,0x55,0x75,0x47,0x02,0x4e,0x62,0x3c,0x3e,0x49,0x8a,0xc5,0x7c,0x79,0xc7,0x8e,0x4e,0x03,0xa6,0x37,0x69,0x96, 0x5e,0x5a,0x91,0x66,0x37,0xcd,0xbf,0xc1,0xcf,0x00,0x00,0x01,0x00,0x35,0xff,0xea,0x04,0xce,0x06,0x02,0x00,0x26,0x00,0x26,0x40,0x14,0x1c,0x0b,0x16,0x95,0x11,0x00,0x20,0x06,0x09,0x95,0x1d,0x19,0x0b,0x0f,0x07,0x15,0x24,0x95,0x02,0x15,0x00,0x3f,0xed,0x3f,0x3f,0x33,0x33,0xed,0x32,0x32,0x3f,0xed,0x12,0x39,0x30,0x31,0x25,0x06, 0x23,0x20,0x11,0x11,0x21,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x37,0x36,0x33,0x32,0x17,0x15,0x26,0x23,0x22,0x15,0x15,0x21,0x35,0x37,0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x04,0xce,0x3b,0x5e,0xfe,0xf3,0xfe,0x5f,0xa3,0xaf,0xaf,0x5d,0x5d,0x8b,0x4b,0x2c,0x30,0x3d,0xac,0x01,0xa1,0xa4,0x01,0x02,0xfe,0xfe,0x46, 0x51,0x3f,0x2c,0x0a,0x20,0x01,0x2c,0x02,0x5e,0xfc,0x8c,0x03,0x74,0x8c,0xa6,0xa1,0x5d,0x5e,0x12,0x94,0x1b,0xd9,0x9e,0xfa,0x35,0xfe,0xd1,0x8c,0xfd,0xbf,0x67,0x58,0x22,0x00,0x00,0x01,0x00,0x68,0xff,0xe8,0x05,0x47,0x05,0x2f,0x00,0x3d,0x00,0x25,0x40,0x14,0x37,0x95,0x34,0x0f,0x0b,0x21,0x1a,0x33,0x05,0x95,0x31,0x0f,0x1f,0x95, 0x1a,0x15,0x3b,0x95,0x02,0x15,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x33,0x12,0x39,0x39,0x3f,0xed,0x30,0x31,0x25,0x06,0x23,0x20,0x11,0x11,0x21,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x27,0x35,0x16,0x33,0x32,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x21,0x35,0x37, 0x11,0x21,0x15,0x21,0x11,0x14,0x16,0x33,0x32,0x37,0x05,0x47,0x3b,0x5e,0xfe,0xf3,0xfe,0x3b,0x2e,0x4a,0x35,0x1d,0x1d,0x38,0x50,0x33,0x44,0x6c,0x4c,0x29,0x43,0x70,0x93,0x4f,0x9f,0x73,0x85,0xa2,0xd8,0x25,0x3f,0x55,0x31,0x44,0x67,0x45,0x23,0x3d,0x63,0x7e,0x40,0x01,0xd9,0xa4,0x01,0x02,0xfe,0xfe,0x46,0x51,0x3f,0x2c,0x0a,0x20, 0x01,0x2c,0x02,0x5e,0x0d,0x1c,0x2d,0x20,0x28,0x36,0x2a,0x22,0x14,0x1a,0x37,0x45,0x5b,0x3d,0x4c,0x70,0x4a,0x24,0x3d,0xb0,0x63,0x90,0x27,0x38,0x2d,0x25,0x13,0x1b,0x37,0x45,0x58,0x3b,0x48,0x67,0x42,0x1f,0xfa,0x35,0xfe,0xd1,0x8c,0xfd,0xbf,0x67,0x58,0x22,0x00,0x01,0x00,0x50,0x00,0x00,0x04,0xad,0x04,0xda,0x00,0x0b,0x00,0x0b, 0xb3,0x05,0x06,0x00,0x18,0x00,0x3f,0x2f,0x39,0x30,0x31,0x21,0x26,0x02,0x27,0x00,0x25,0x37,0x04,0x13,0x16,0x12,0x17,0x04,0x74,0x58,0xde,0x8d,0xfe,0xeb,0xfe,0xb4,0xe6,0x01,0x1d,0xe7,0x75,0xb8,0x46,0xcd,0x01,0x5b,0x97,0x01,0x2a,0x85,0x6c,0xd4,0xfe,0xbe,0xa3,0xfe,0xa0,0xc1,0x00,0x01,0x00,0x50,0xff,0xfa,0x02,0xd5,0x04,0xdd, 0x00,0x42,0x00,0x26,0x40,0x11,0x2a,0x29,0x29,0x10,0x11,0x36,0x3e,0x11,0x3e,0x11,0x3e,0x05,0x18,0x20,0x33,0x05,0x18,0x00,0x3f,0x33,0x2f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x11,0x33,0x33,0x2f,0x33,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x23,0x35,0x21,0x36,0x36,0x35,0x34,0x26,0x23, 0x22,0x07,0x26,0x26,0x35,0x34,0x36,0x37,0x36,0x1e,0x02,0x15,0x14,0x06,0x15,0x33,0x15,0x23,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x02,0xd5,0x2d,0x51,0x70,0x43,0x17,0x4c,0x4b,0x36,0x1b,0x28,0x30,0x14,0xf7,0x01,0x0e,0x09,0x0d,0x4a,0x40,0x1d,0x27,0x08,0x11,0x0d,0x10, 0x47,0x69,0x45,0x21,0x04,0xe1,0xf3,0x2b,0x39,0x21,0x0d,0x39,0x42,0x3c,0x57,0x1d,0x27,0x20,0x11,0x1b,0x22,0x12,0x1d,0x2d,0x1f,0x10,0x01,0x02,0x2f,0x5e,0x4c,0x2f,0x26,0x46,0x62,0x3c,0x36,0x7a,0x80,0x82,0x3e,0x4e,0x11,0x39,0x28,0x4e,0x55,0x0b,0x08,0x1f,0x1a,0x11,0x26,0x17,0x02,0x3b,0x5e,0x72,0x36,0x17,0x2e,0x15,0x4e,0x7a, 0x9f,0x6a,0x44,0x1d,0x5d,0x65,0x47,0x36,0x12,0x31,0x19,0x13,0x25,0x1b,0x11,0x19,0x27,0x31,0x00,0x03,0x00,0x3c,0xfd,0xec,0x06,0xe7,0x05,0x65,0x00,0x3b,0x00,0x4f,0x00,0x63,0x00,0x43,0x40,0x0e,0x2e,0x15,0x9b,0x18,0x55,0x9b,0x4b,0x18,0x4b,0x18,0x4b,0x06,0x21,0x1f,0xb8,0x01,0x80,0x40,0x0c,0x27,0x5f,0x9b,0x41,0x41,0x06,0x39, 0x99,0x02,0x02,0x35,0x0b,0xb8,0x01,0x80,0xb2,0x09,0x06,0x18,0x00,0x3f,0x33,0xed,0x33,0x33,0x2f,0xed,0x11,0x33,0x2f,0xed,0x2f,0xed,0x33,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x30,0x31,0x01,0x06,0x23,0x22,0x27,0x26,0x27,0x26,0x27,0x37,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x20,0x35, 0x34,0x2e,0x02,0x23,0x22,0x07,0x27,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x16,0x15,0x14,0x0e,0x02,0x07,0x16,0x17,0x16,0x33,0x32,0x37,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x07,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x03,0xcf,0x67,0x59, 0xb2,0x7f,0x56,0x2f,0xbf,0x5e,0x8c,0x50,0xa6,0x34,0x5a,0x43,0x26,0x2d,0x51,0x70,0x43,0x8b,0x8b,0x01,0x35,0x27,0x44,0x5c,0x34,0x9c,0x5d,0x89,0x18,0x4f,0x65,0x76,0x40,0x59,0x96,0x6c,0x3c,0xa6,0xa3,0x33,0x5c,0x7f,0x4b,0x0c,0x4f,0x63,0x61,0x42,0x2c,0x03,0x61,0x3f,0x6c,0x8f,0x51,0x50,0x8f,0x6c,0x3f,0x3f,0x6c,0x8f,0x50,0x50, 0x90,0x6c,0x3f,0xa1,0x25,0x40,0x55,0x30,0x30,0x55,0x40,0x25,0x25,0x40,0x55,0x30,0x30,0x55,0x40,0x25,0xfe,0x20,0x34,0xcd,0x8a,0xc5,0x1f,0xa4,0x4d,0x77,0x1e,0x38,0x4c,0x2f,0x38,0x5b,0x40,0x22,0xa0,0xdc,0x31,0x53,0x3d,0x23,0x77,0x50,0x2d,0x49,0x33,0x1c,0x38,0x66,0x8e,0x56,0xc3,0x6a,0x63,0xe1,0x4a,0x7f,0x60,0x3d,0x09,0x60, 0x81,0xa5,0x26,0x02,0xdb,0x50,0x8f,0x6c,0x3f,0x3f,0x6c,0x8f,0x50,0x51,0x90,0x6c,0x3f,0x3f,0x6c,0x90,0x51,0x30,0x55,0x41,0x25,0x25,0x41,0x55,0x30,0x30,0x55,0x40,0x25,0x25,0x40,0x55,0x00,0x02,0x00,0x54,0xfe,0x9b,0x08,0x76,0x08,0xe0,0x00,0x72,0x00,0x82,0x00,0x53,0xb9,0x00,0x39,0x01,0x81,0xb4,0x4b,0x4b,0x43,0x48,0x42,0xb8, 0x01,0x81,0x40,0x18,0x45,0x11,0x63,0x79,0x23,0x04,0x16,0x7e,0x1e,0x1e,0x01,0x76,0x16,0x16,0x69,0x71,0x01,0x01,0x45,0x45,0x43,0x0c,0x69,0x2d,0xb8,0x01,0x81,0xb4,0x55,0x55,0x40,0x43,0x18,0x00,0x3f,0x33,0x33,0x2f,0xed,0x2f,0x33,0x12,0x39,0x2f,0x33,0x2f,0x33,0x12,0x39,0x2f,0x33,0x11,0x33,0x2f,0x33,0x12,0x17,0x39,0x10,0xed, 0x32,0x12,0x39,0x2f,0xed,0x30,0x31,0x01,0x21,0x35,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x07,0x3e,0x03,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x0e,0x02,0x02,0x15,0x14,0x12,0x04,0x04,0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x21,0x11,0x23,0x11,0x21, 0x15,0x23,0x11,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x02,0x06,0x04,0x23,0x22,0x24,0x24,0x26,0x26,0x02,0x35,0x34,0x3e,0x04,0x37,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x21,0x25,0x34,0x26,0x23,0x22,0x06,0x07,0x1e,0x03,0x33,0x32,0x3e,0x02,0x06,0xe5,0xfe,0x0b,0x1d,0x2f,0x20,0x11,0x28,0x4b,0x6b,0x42,0x3a, 0x60,0x47,0x2a,0x04,0x08,0x1a,0x20,0x20,0x0e,0x76,0x82,0x23,0x3f,0x56,0x34,0x38,0x56,0x40,0x2a,0x0d,0x46,0x93,0x78,0x4c,0x90,0x01,0x05,0x01,0x6d,0xde,0x5f,0xaf,0x96,0x7b,0x57,0x30,0x18,0x2d,0x40,0x29,0x1d,0x36,0x29,0x19,0xd8,0xfe,0xd7,0xd8,0x03,0xcd,0xf4,0x40,0x7f,0x50,0x81,0x5a,0x31,0x66,0xd9,0xfe,0xad,0xec,0xb2,0xfe, 0xc6,0xfe,0xf8,0xd2,0x91,0x4d,0x30,0x54,0x71,0x82,0x8d,0x45,0x44,0x75,0x9d,0x58,0x60,0xa4,0x77,0x44,0x23,0x23,0x01,0x21,0xfd,0x25,0x2b,0x2e,0x26,0x3b,0x11,0x02,0x16,0x22,0x2a,0x17,0x10,0x1d,0x16,0x0d,0x05,0xa8,0x7f,0x12,0x39,0x44,0x47,0x20,0x48,0x75,0x53,0x2e,0x29,0x46,0x61,0x37,0x04,0x08,0x08,0x05,0x78,0x6e,0x32,0x52, 0x3b,0x20,0x27,0x40,0x52,0x2c,0x2d,0x8f,0xd4,0xfe,0xe1,0xbd,0xda,0xfe,0xa0,0xfa,0x87,0x08,0x1f,0x3f,0x6e,0xa6,0x77,0x47,0x78,0x57,0x31,0x21,0x36,0x42,0x21,0xfe,0x1c,0x04,0x78,0xfb,0x88,0x05,0x28,0xb0,0xfe,0x99,0x3e,0x46,0x7c,0xad,0x67,0xb3,0xfe,0xee,0xba,0x5f,0x4b,0x8d,0xca,0xfe,0x01,0x2c,0xa9,0x8e,0xf6,0xd0,0xaa,0x87, 0x64,0x21,0x17,0x58,0x9d,0x75,0x45,0x45,0x78,0xa5,0x60,0x3c,0x7a,0x3b,0x56,0x36,0x30,0x15,0x0e,0x1e,0x37,0x2a,0x1a,0x0f,0x18,0x1f,0x00,0x01,0x00,0x74,0x00,0xfd,0x03,0x47,0x05,0x5a,0x00,0x5c,0x00,0x2b,0x40,0x14,0x37,0x53,0x59,0x22,0x1c,0x12,0x2d,0x03,0x53,0x03,0x12,0x12,0x03,0x53,0x03,0x0a,0x4d,0x40,0x21,0x0a,0x00,0x2f, 0x33,0x2f,0x33,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x12,0x39,0x11,0x33,0x32,0x32,0x11,0x33,0x30,0x31,0x01,0x06,0x06,0x07,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x11,0x26,0x26,0x27,0x22,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16, 0x17,0x35,0x34,0x26,0x23,0x22,0x06,0x23,0x22,0x2e,0x02,0x27,0x13,0x33,0x17,0x16,0x33,0x32,0x37,0x17,0x07,0x22,0x2e,0x02,0x23,0x22,0x06,0x07,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x15,0x36,0x36,0x37,0x03,0x47,0x2e,0x82,0x53,0x0d,0x15,0x1a,0x0c,0x42,0x24,0x50,0x43,0x2c,0x3b,0x2e,0x06,0x1b,0x1b,0x15,0x18,0x1c,0x18,0x0b,0x15, 0x20,0x15,0x2e,0x55,0x31,0x36,0x3c,0x10,0x1c,0x26,0x17,0x27,0x3b,0x07,0x0e,0x28,0x1e,0x2a,0x25,0x0f,0x17,0x09,0x0b,0x10,0x10,0x12,0x0c,0xfc,0x1c,0x9f,0x06,0x12,0x0f,0x0c,0x1d,0x75,0x08,0x1e,0x2b,0x38,0x22,0x1a,0x28,0x11,0x0e,0x19,0x0b,0x27,0x3f,0x2d,0x18,0x34,0x66,0x33,0x03,0x8b,0x54,0x4f,0x0e,0xfe,0x69,0x0f,0x1a,0x13, 0x0a,0x38,0x5b,0x75,0x3d,0x3f,0x47,0x06,0x18,0x33,0x2d,0x27,0x27,0x14,0x08,0x07,0x0c,0x25,0x23,0x19,0x01,0x69,0x04,0x0b,0x12,0x3f,0x2a,0x16,0x26,0x1d,0x10,0x2b,0x23,0x09,0x0d,0x0c,0x34,0x35,0x28,0x03,0x0e,0x1b,0x27,0x18,0x01,0x0c,0x6c,0x06,0x09,0x2a,0x78,0x1a,0x20,0x1a,0x2a,0x1b,0x02,0x03,0x17,0x25,0x31,0x1a,0x93,0x05, 0x2c,0x3b,0x00,0x01,0xff,0xf8,0xff,0xec,0x09,0x3b,0x05,0xcd,0x00,0xa4,0x00,0x00,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x37,0x3e,0x03,0x37,0x17,0x0e,0x05,0x07,0x0e,0x05,0x07,0x3e,0x05,0x37,0x3e,0x03,0x37,0x3e,0x03,0x37,0x17, 0x0e,0x05,0x07,0x0e,0x05,0x15,0x14,0x33,0x32,0x3e,0x02,0x37,0x17,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x37,0x3e,0x05,0x37,0x0e,0x03,0x07,0x0e,0x03,0x07,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x36,0x12,0x37,0x3e,0x05,0x37,0x0e,0x05,0x07,0x0e,0x05,0x01,0x0a,0x3f,0x65,0x48,0x26,0x1c,0x31,0x44,0x29,0x22, 0x2c,0x1a,0x0b,0x14,0x2c,0x43,0x2f,0x1a,0x11,0x13,0x2e,0x4b,0x38,0x4b,0x87,0x7e,0x77,0x76,0x78,0x41,0x61,0xc1,0xb0,0x96,0x36,0x21,0x09,0x32,0x40,0x47,0x3f,0x2e,0x07,0x07,0x24,0x30,0x36,0x31,0x26,0x07,0x20,0x4b,0x51,0x55,0x55,0x52,0x27,0x2d,0x4a,0x43,0x40,0x23,0x39,0x70,0x64,0x55,0x1f,0x22,0x17,0x3d,0x44,0x48,0x46,0x40, 0x19,0x15,0x38,0x3c,0x3b,0x2f,0x1d,0x10,0x1b,0x51,0x5b,0x5e,0x29,0x19,0x27,0x5f,0x62,0x5f,0x28,0x23,0x38,0x27,0x15,0x24,0x3b,0x48,0x48,0x3f,0x15,0x1a,0x4d,0x55,0x58,0x4b,0x37,0x0a,0x1a,0x70,0x9d,0xc4,0x6d,0x3e,0x6b,0x5d,0x51,0x24,0x1f,0x38,0x34,0x2f,0x15,0x22,0x27,0x14,0x05,0x19,0x49,0x84,0x6c,0x18,0x3e,0x42,0x41,0x36, 0x28,0x08,0x2c,0x6c,0x74,0x79,0x71,0x67,0x28,0x37,0x6d,0x71,0x78,0x85,0x96,0x14,0x27,0x48,0x63,0x3c,0x2b,0x4c,0x38,0x20,0x14,0x21,0x28,0x14,0x18,0x2d,0x26,0x1c,0x06,0x03,0x16,0x12,0x09,0x30,0x31,0x26,0x3a,0x65,0x8b,0xa0,0xaf,0x58,0x84,0xef,0xc3,0x90,0x26,0x15,0x15,0x6e,0x91,0xa1,0x8e,0x69,0x10,0x10,0x59,0x79,0x8e,0x8f, 0x83,0x30,0x20,0x66,0x7c,0x8a,0x8a,0x82,0x35,0x3d,0x64,0x55,0x4b,0x25,0x3d,0x69,0x54,0x3e,0x12,0x21,0x21,0x65,0x78,0x85,0x85,0x7d,0x33,0x2a,0x79,0x8a,0x90,0x81,0x67,0x1c,0x1d,0x38,0x59,0x6e,0x35,0x15,0x36,0x72,0x5e,0x3d,0x1a,0x3c,0x64,0x4a,0x31,0x7c,0x86,0x87,0x78,0x60,0x1c,0x23,0x5f,0x67,0x67,0x56,0x3e,0x0b,0x12,0x56, 0x97,0xde,0x99,0x59,0xa6,0x98,0x85,0x36,0x2e,0x4f,0x3b,0x21,0x2f,0x45,0x4d,0x1e,0x21,0x7b,0xbc,0x01,0x01,0xa7,0x26,0x5c,0x5e,0x5b,0x4c,0x36,0x0b,0x21,0x6b,0x82,0x91,0x90,0x86,0x36,0x49,0xa1,0x9b,0x8d,0x6b,0x3f,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0x2d,0x04,0x2a,0x02,0x26,0x09,0x1f,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0xc9, 0xfe,0xf4,0xff,0xff,0x00,0xab,0xfe,0xa6,0x05,0xf4,0x05,0xec,0x00,0x27,0x0f,0x50,0x02,0x59,0xfe,0xab,0x00,0x06,0x09,0x24,0x00,0x00,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0x9f,0x04,0x12,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x27,0x0f,0x50,0x02,0xad,0xfe,0xab,0x00,0x07,0x0a,0x19,0x02,0xc0,0xfb,0xb4,0xff,0xff,0x00,0xab,0xfd,0xc9, 0x06,0x9f,0x04,0x12,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x27,0x0f,0x54,0x02,0xad,0xfd,0xce,0x00,0x07,0x0a,0x19,0x02,0xc0,0xfb,0xb4,0xff,0xff,0x00,0xab,0xff,0xea,0x06,0x9f,0x04,0x39,0x02,0x26,0x09,0x3e,0x00,0x00,0x00,0x07,0x14,0x7c,0x03,0xc6,0xfb,0xaa,0xff,0xff,0x00,0x00,0xfd,0xff,0x02,0x9e,0x05,0x5f,0x02,0x26,0x09,0x17, 0x00,0x00,0x00,0x07,0x0a,0x1f,0x00,0xa5,0xfc,0xd3,0xff,0xff,0x00,0x9a,0xfd,0xfb,0x05,0x91,0x05,0xe2,0x02,0x26,0x09,0x2a,0x00,0x00,0x00,0x27,0x0f,0x51,0x02,0x01,0xfe,0x00,0x00,0x07,0x0a,0x1f,0x01,0xc4,0xfd,0x56,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x4b,0x03,0x62,0x02,0x06,0x09,0xc8,0x00,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff, 0x05,0x4b,0x02,0xb7,0x02,0x06,0x09,0x7c,0x00,0x00,0xff,0xff,0x00,0x9b,0xfd,0xff,0x04,0xa6,0x01,0xc1,0x02,0x06,0x09,0x5f,0x00,0x00,0x00,0x04,0x00,0x00,0x06,0x71,0x04,0xb4,0x09,0x9a,0x00,0x28,0x00,0x2c,0x00,0x6e,0x00,0x7c,0x00,0x00,0x01,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23, 0x22,0x26,0x27,0x35,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x17,0x16,0x16,0x33,0x13,0x33,0x11,0x23,0x25,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26, 0x27,0x35,0x34,0x36,0x37,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x16,0x16,0x33,0x27,0x34,0x26,0x23,0x22,0x06,0x07,0x16,0x16,0x17,0x3e,0x03,0x03,0x75,0x1d,0x1d,0x5c,0x1a,0x2b,0x38,0x1d,0x19,0x0b,0x13,0x08,0x08,0x6a,0x4d,0x15,0x2b,0x17,0x17,0x2f,0x10,0x1d,0x27,0x18,0x0a,0x1f,0x11,0x61,0x0c,0x12,0x05,0x04, 0x1d,0x1d,0xee,0x5c,0x5c,0xfd,0x6b,0x1d,0x1d,0x5c,0x1a,0x2b,0x38,0x1d,0x1b,0x45,0x78,0x33,0x31,0x26,0x10,0x23,0x38,0x27,0x26,0x53,0x26,0x2b,0x4d,0x28,0x3f,0x5b,0x39,0x1b,0x0a,0x1a,0x2e,0x23,0x19,0x30,0x11,0x08,0x05,0x12,0x2d,0x32,0x35,0x1a,0x19,0x38,0x2d,0x1e,0x09,0x19,0x2c,0x24,0x25,0x50,0x2d,0x8d,0x26,0x21,0x18,0x32, 0x17,0x11,0x27,0x14,0x1c,0x24,0x15,0x07,0x07,0x95,0x16,0x23,0x01,0xcc,0xfe,0x31,0x31,0x3c,0x20,0x0a,0x07,0x03,0x66,0x67,0x08,0x0b,0x5f,0x07,0x09,0x15,0x26,0x34,0x1f,0x39,0x73,0x30,0x1d,0x42,0x20,0x14,0x15,0x02,0x05,0xfd,0x9a,0x61,0x16,0x23,0xb7,0xba,0x31,0x3c,0x20,0x0a,0x36,0x2e,0x16,0x30,0x1a,0x16,0x27,0x1e,0x11,0x0f, 0x0d,0x5a,0x14,0x09,0x1e,0x35,0x45,0x27,0x15,0x2b,0x2a,0x29,0x15,0x1c,0x45,0x1d,0x46,0x05,0x09,0x01,0x03,0x07,0x07,0x04,0x07,0x13,0x25,0x1e,0x0e,0x26,0x2a,0x2b,0x14,0x17,0x1a,0xbb,0x0b,0x08,0x04,0x03,0x1a,0x2e,0x14,0x0d,0x18,0x15,0x11,0x00,0x00,0x02,0xff,0x2b,0x06,0x1f,0x02,0xdf,0x08,0x40,0x00,0x36,0x00,0x48,0x00,0x21, 0x40,0x0e,0x00,0x37,0x37,0x23,0x31,0x05,0x0f,0x0f,0x1a,0x3f,0x05,0x05,0x29,0x1a,0x00,0x2f,0x33,0x33,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x39,0x33,0x11,0x33,0x30,0x31,0x01,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15, 0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x17,0x16,0x16,0x33,0x17,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x32,0x32,0x16,0x32,0x01,0x35,0x0d,0x2f,0x43,0x57,0x36,0x28,0x3c,0x27,0x13,0x20,0x46,0x71,0x51,0x17,0x3e,0x3b,0x30,0x0a,0x02,0x02,0x1a,0x36,0x56,0x3e,0x3f,0x54,0x32,0x15,0x06,0x07,0x56, 0x05,0x05,0x3a,0x45,0x28,0x38,0x23,0x10,0x07,0x07,0x58,0x0a,0x02,0x1b,0x13,0xd3,0x2e,0x3b,0x23,0x0e,0x34,0x25,0x1f,0x34,0x29,0x1e,0x09,0x08,0x1c,0x1d,0x1b,0x07,0x2f,0x27,0x5f,0x53,0x38,0x22,0x3a,0x50,0x2d,0x3a,0x40,0x1e,0x06,0x01,0x06,0x0c,0x0a,0x30,0x4a,0x33,0x1a,0x1b,0x32,0x48,0x2d,0x1a,0x37,0x1d,0x1b,0x29,0x16,0x42, 0x34,0x12,0x28,0x41,0x2f,0x21,0x43,0x2f,0x5d,0x14,0x1c,0x03,0x02,0x0e,0x1b,0x1a,0x39,0x33,0x1f,0x33,0x3f,0x1f,0x01,0x00,0x00,0x01,0x00,0x00,0x06,0x1e,0x01,0xba,0x08,0xdd,0x00,0x35,0x00,0x19,0x40,0x0a,0x19,0x00,0x30,0x30,0x11,0x2a,0x21,0x21,0x0a,0x11,0x00,0x2f,0x33,0x33,0x2f,0x33,0x12,0x39,0x2f,0x33,0x33,0x30,0x31,0x01, 0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x32,0x16,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x3e,0x03,0x37,0x01,0x62,0x47,0x61,0x3d,0x1b,0x12,0x26,0x3d,0x2b,0x2d,0x65,0x26,0x2f,0x5c,0x2e,0x45,0x61, 0x3e,0x1d,0x23,0x30,0x1c,0x1a,0x1c,0x35,0x4d,0x30,0x06,0x16,0x1a,0x16,0x06,0x0b,0x2b,0x11,0x34,0x43,0x11,0x0e,0x10,0x2f,0x34,0x37,0x1a,0x07,0xaa,0x10,0x28,0x2f,0x33,0x1b,0x18,0x2b,0x20,0x13,0x16,0x0e,0x63,0x10,0x12,0x21,0x38,0x4c,0x2a,0x2a,0x56,0x2a,0x1f,0x49,0x23,0x24,0x44,0x34,0x1f,0x02,0x03,0x03,0x64,0x02,0x03,0x25, 0x32,0x1a,0x2d,0x0f,0x0a,0x13,0x13,0x10,0x07,0x00,0x00,0x04,0x00,0x00,0x06,0x71,0x01,0xf5,0x09,0x3e,0x00,0x2a,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x27,0x40,0x11,0x40,0x3e,0x3e,0x3b,0x39,0x39,0x2b,0x00,0x19,0x0f,0x0f,0x22,0x33,0x19,0x19,0x08,0x22,0x00,0x2f,0x33,0x33,0x2f,0x33,0x12,0x39,0x2f,0x12,0x39,0x33,0x32,0x2f,0x33, 0x33,0x2f,0x33,0x30,0x31,0x13,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x05,0x32,0x36,0x37,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x65, 0x03,0x05,0x0f,0x23,0x3a,0x2c,0x31,0x3c,0x23,0x0e,0x03,0x18,0x1a,0x1d,0x36,0x29,0x19,0x15,0x26,0x33,0x1e,0x21,0x33,0x19,0x16,0x17,0x7d,0x88,0x43,0x5c,0x38,0x19,0x05,0x05,0x01,0x61,0x0b,0x15,0x0b,0x02,0x0b,0x11,0x16,0x0b,0x10,0x1d,0x27,0x2f,0x73,0x73,0xc8,0x73,0x73,0x07,0xa4,0x1a,0x2c,0x13,0x21,0x2c,0x1b,0x0c,0x0f,0x1b, 0x25,0x15,0x07,0x12,0x23,0x33,0x21,0x1b,0x3d,0x33,0x21,0x25,0x25,0x21,0x65,0x33,0x7e,0x77,0x1b,0x34,0x4e,0x32,0x17,0x32,0x1c,0x10,0x01,0x05,0x0e,0x25,0x21,0x17,0x2b,0x19,0x15,0x18,0x01,0x38,0x71,0x71,0x71,0x00,0x00,0x03,0x00,0x32,0x05,0xd1,0x01,0xd4,0x08,0x8c,0x00,0x1c,0x00,0x20,0x00,0x24,0x00,0x1d,0x40,0x0c,0x23,0x22, 0x22,0x1f,0x1d,0x1d,0x11,0x08,0x1c,0x1c,0x16,0x08,0x00,0x2f,0x33,0x33,0x2f,0x12,0x39,0x33,0x2f,0x33,0x32,0x2f,0x33,0x30,0x31,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x23,0x35,0x33,0x03,0x21,0x15,0x21,0x01,0xc7,0x07,0x06, 0x16,0x35,0x56,0x40,0x37,0x4a,0x2d,0x13,0x06,0x05,0x58,0x09,0x30,0x3c,0x46,0x3c,0x07,0x06,0x31,0x73,0x73,0xdd,0x01,0x52,0xfe,0xae,0x07,0xe3,0x23,0x43,0x1f,0x37,0x58,0x3d,0x21,0x1a,0x32,0x46,0x2c,0x18,0x35,0x1e,0x3b,0x29,0x36,0x29,0x40,0x4f,0x1a,0x3d,0x26,0x38,0x71,0xfd,0x9d,0x58,0xff,0xff,0x00,0x32,0xfc,0xd5,0x01,0xd4, 0xff,0x90,0x02,0x03,0x14,0x61,0x00,0x00,0xf7,0x04,0x00,0x0b,0xfc,0xe6,0x07,0x1d,0x02,0xe0,0x0a,0x0e,0x00,0x64,0x00,0x68,0x00,0x6c,0x00,0x70,0x00,0x74,0x00,0x78,0x00,0x7c,0x00,0x80,0x00,0x84,0x00,0x88,0x00,0x8c,0x00,0x00,0x03,0x14,0x16,0x33,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x32,0x3e,0x02,0x35, 0x35,0x33,0x15,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x23,0x22,0x26,0x26,0x34,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17, 0x16,0x16,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x01,0x33,0x11,0x23,0x01,0x33,0x15,0x23,0x07,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x25,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x25,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0xf6,0x14,0x26,0x50,0x09,0x14,0x12,0x0c,0x5c,0x13,0x26,0x36,0x09,0x15, 0x11,0x0c,0x5c,0x11,0x21,0x3e,0x1d,0x1d,0x5c,0x1a,0x2b,0x38,0x1d,0x3b,0x23,0x32,0x11,0x17,0x35,0x19,0x4c,0x19,0x2c,0x0d,0x17,0x39,0x19,0x6a,0x17,0x2d,0x0d,0x17,0x35,0x1a,0x0e,0x17,0x27,0x22,0x1d,0x0e,0x16,0x2b,0x17,0x1c,0x28,0x50,0x02,0x01,0x01,0x1d,0x2d,0x39,0x1b,0x12,0x26,0x24,0x20,0x0d,0x17,0x2a,0x17,0x0e,0x09,0x15, 0x11,0x0c,0x5c,0x03,0x7a,0x5c,0x5c,0xfc,0xdd,0x3f,0x3f,0x9e,0x65,0x65,0x02,0x2e,0x65,0x65,0xfc,0x7b,0x65,0x65,0x03,0xcc,0x64,0x64,0xfc,0xc0,0x64,0x64,0x01,0x12,0x64,0x64,0x45,0x64,0x64,0x02,0x2e,0x64,0x64,0x07,0xe9,0x2c,0x28,0x06,0x0d,0x16,0x11,0x01,0xcb,0xfe,0x4f,0x2c,0x28,0x06,0x0d,0x16,0x11,0xb7,0x9d,0x2a,0x2a,0x16, 0x23,0x01,0xcc,0xfe,0x31,0x31,0x3c,0x20,0x0a,0x15,0x12,0x16,0x11,0x16,0x11,0x16,0x11,0x18,0x0f,0x16,0x11,0x0c,0x13,0x18,0x0c,0x12,0x1d,0x33,0x3d,0x19,0x0a,0x0c,0x0b,0x02,0x36,0x4b,0x30,0x15,0x0d,0x13,0x18,0x0a,0x12,0x1d,0x06,0x0d,0x16,0x11,0xb7,0x01,0x14,0xfd,0x9a,0x02,0xda,0xc4,0x8f,0x62,0x62,0x62,0xeb,0x62,0xaf,0x62, 0xfe,0x8d,0x62,0xaf,0x62,0xea,0x62,0x62,0x62,0x00,0x00,0x07,0xfb,0x6b,0x06,0xaa,0x03,0xb0,0x09,0x9a,0x00,0x84,0x00,0x94,0x00,0x98,0x00,0xa4,0x00,0xa8,0x00,0xac,0x00,0xb0,0x00,0x00,0x01,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x33,0x16,0x16,0x17,0x1e,0x03,0x17,0x33,0x32,0x3e,0x02,0x37,0x27,0x26,0x26,0x23,0x22, 0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x16,0x17,0x1e,0x03,0x17,0x07,0x07,0x16,0x16,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x17,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x06,0x06, 0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x0e,0x03,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x03,0x1e,0x03,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x27,0x01,0x33,0x11,0x23,0x25,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x06,0x06,0x13,0x23,0x35,0x33, 0x17,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0xfc,0xb3,0x26,0x47,0x16,0x32,0x29,0x0c,0x13,0x1a,0x0e,0x5f,0x17,0x20,0x0b,0x02,0x08,0x0e,0x15,0x0f,0x09,0x2a,0x4f,0x49,0x45,0x20,0x0b,0x1d,0x3f,0x32,0x1e,0x3d,0x13,0x17,0x3c,0x1f,0x32,0x45,0x1e,0x0d,0x1d,0x22,0x2b,0x1c,0x10,0x3d,0x02,0x22,0x2c,0x1d,0x09,0x15,0x11,0x0c,0x5c,0x03, 0x0b,0x15,0x11,0x16,0x22,0x5c,0x13,0x26,0x17,0x1d,0x5d,0x10,0x21,0x0d,0x1d,0x1d,0x5c,0x1a,0x2b,0x38,0x1d,0x19,0x1c,0x27,0x0e,0x14,0x34,0x1a,0x22,0x35,0x12,0x17,0x37,0x19,0x24,0x32,0x0f,0x16,0x38,0x18,0x38,0x2d,0x42,0x08,0x1c,0x41,0x4b,0x54,0x2f,0x0f,0x1b,0x2b,0x0c,0x1a,0x4e,0x2e,0x17,0x41,0x1d,0xe7,0x35,0x49,0x2d,0x13, 0x51,0x49,0x47,0x4b,0x35,0x21,0x1f,0x07,0xb2,0x5c,0x5c,0xf8,0x73,0x21,0x17,0x20,0x1c,0x18,0x21,0x1a,0x21,0x20,0x65,0x65,0x8c,0x64,0x64,0x02,0xe0,0x64,0x64,0x07,0x9e,0x05,0x06,0x14,0x16,0x12,0x3e,0x4b,0x52,0x24,0x45,0x79,0x31,0x0a,0x19,0x17,0x0f,0x01,0x12,0x1e,0x27,0x14,0x05,0x10,0x18,0x08,0x05,0x58,0x08,0x0b,0x19,0x10, 0x06,0x0d,0x0b,0x09,0x02,0x59,0x27,0x14,0x10,0x06,0x0d,0x16,0x11,0x71,0x58,0x15,0x20,0x14,0x0a,0x17,0x23,0x71,0x57,0x2c,0x28,0x17,0x23,0xb8,0x9b,0x2b,0x2a,0x02,0x16,0x23,0x01,0xcc,0xfe,0x31,0x31,0x3c,0x20,0x0a,0x13,0x0f,0x13,0x0f,0x10,0x17,0x16,0x11,0x14,0x12,0x14,0x12,0x30,0x2a,0x10,0x20,0x1a,0x10,0x1c,0x11,0x1b,0x15, 0x08,0x04,0x01,0x96,0x21,0x43,0x45,0x47,0x25,0x42,0x51,0x49,0x3e,0x40,0x63,0x1f,0x1a,0x01,0x0c,0xfd,0x9a,0x8a,0x1a,0x17,0x1a,0x16,0x1f,0x3c,0x23,0x16,0x42,0x01,0x2a,0x62,0x62,0x62,0xfd,0x3b,0x62,0x00,0x00,0x06,0xfb,0x9b,0x07,0x31,0x03,0x92,0x09,0x9a,0x00,0x7e,0x00,0x82,0x00,0x92,0x00,0xa1,0x00,0xa5,0x00,0xa9,0x00,0x00, 0x01,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x23,0x26,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x0e,0x03,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x37, 0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x17,0x16,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x16,0x16,0x17,0x01,0x33,0x11,0x23,0x25,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23, 0x22,0x0e,0x02,0x25,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x03,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0x01,0x7a,0x17,0x1d,0x5d,0x03,0x0c,0x16,0x13,0x10,0x1d,0x1d,0x5c,0x1a,0x2b,0x38,0x1d,0x19,0x20,0x2c,0x0f,0x14,0x34,0x1a,0x1b,0x24,0x2d,0x11,0x11,0x2e,0x35,0x3b,0x1e,0x48,0x66,0x45,0x2a,0x0b,0x0c,0x11, 0x07,0x17,0x37,0x19,0x19,0x11,0x1c,0x1a,0x19,0x0f,0x2a,0x67,0x36,0x48,0x68,0x89,0x27,0x1d,0x15,0x0b,0x05,0x5a,0x04,0x09,0x0a,0x0e,0x0c,0x22,0x33,0x48,0x31,0x13,0x26,0x21,0x18,0x04,0x22,0x10,0x15,0x26,0x33,0x1e,0x24,0x39,0x27,0x15,0x0c,0x39,0x17,0x21,0x09,0x05,0x5c,0x0e,0x02,0x0e,0x10,0x0f,0x37,0x4e,0x65,0x3d,0x33,0x4a, 0x30,0x17,0x01,0x0e,0x17,0x01,0xe2,0x5c,0x5c,0xfc,0x5a,0x21,0x52,0x35,0x26,0x39,0x27,0x14,0x40,0x32,0x25,0x41,0x34,0x29,0xfe,0x59,0x0a,0x12,0x17,0x0d,0x11,0x1c,0x08,0x16,0x25,0x1e,0x0c,0x11,0x64,0x64,0x04,0x24,0x64,0x64,0x07,0x95,0x17,0x23,0xb8,0x9b,0x17,0x20,0x16,0x0a,0x16,0x23,0x01,0xcc,0xfe,0x31,0x31,0x3c,0x20,0x0a, 0x01,0x11,0x10,0x13,0x0f,0x0f,0x18,0x0e,0x11,0x09,0x02,0x01,0x03,0x05,0x05,0x05,0x0f,0x08,0x16,0x11,0x03,0x06,0x08,0x06,0x13,0x07,0x0f,0x20,0x17,0x43,0x25,0x1b,0x34,0x14,0x11,0x34,0x13,0x14,0x23,0x09,0x08,0x0a,0x04,0x01,0x01,0x02,0x02,0x01,0x16,0x31,0x20,0x1b,0x3d,0x33,0x21,0x2c,0x40,0x49,0x1d,0x29,0x1c,0x19,0x0f,0x11, 0x3a,0x17,0x68,0x0b,0x11,0x04,0x28,0x5c,0x4e,0x34,0x1f,0x35,0x46,0x27,0x20,0x25,0x01,0x02,0x04,0xfd,0x9a,0x61,0x01,0x01,0x03,0x0c,0x19,0x16,0x3a,0x31,0x1d,0x2f,0x3c,0x24,0x0f,0x27,0x23,0x18,0x2b,0x19,0x09,0x14,0x15,0x19,0x0f,0x0d,0x01,0x42,0x62,0x8d,0x62,0x00,0x00,0x05,0xfc,0x00,0x07,0x1d,0x02,0x8d,0x09,0xb2,0x00,0x7e, 0x00,0x82,0x00,0x86,0x00,0x8a,0x00,0x8e,0x00,0x00,0x01,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x35,0x25,0x15,0x07,0x1e,0x03,0x17,0x1e,0x03,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22, 0x26,0x27,0x06,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x23,0x22,0x26,0x26,0x34,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x16,0x16,0x33,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x05,0x23,0x35, 0x33,0x25,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0xfe,0x24,0x14,0x26,0xd5,0x43,0x30,0x23,0x40,0x5a,0x36,0x01,0x5e,0xea,0x42,0x50,0x2e,0x15,0x07,0x01,0x07,0x10,0x1d,0x19,0x13,0x09,0x15,0x11,0x0c,0x5c,0x03,0x0b,0x15,0x11,0x16,0x22,0x5c,0x13,0x26,0x17,0x1d,0x5d,0x0f,0x22,0x38,0x29,0x22,0x35,0x12,0x17,0x37, 0x19,0x24,0x32,0x0f,0x16,0x38,0x18,0x38,0x0a,0x16,0x16,0x12,0x05,0x17,0x50,0x42,0xdd,0x23,0x32,0x11,0x17,0x35,0x1a,0x10,0x2c,0x41,0x1c,0x16,0x2b,0x17,0x1c,0x28,0x50,0x02,0x01,0x01,0x1d,0x2d,0x39,0x1b,0x12,0x26,0x24,0x20,0x0d,0x17,0x2a,0x17,0x0e,0x09,0x15,0x11,0x0c,0x5c,0xfe,0x62,0x65,0x65,0x01,0x57,0x65,0x65,0x8c,0x64, 0x64,0xfe,0xa9,0x64,0x64,0x07,0xe9,0x2c,0x28,0x1a,0x18,0x1b,0x35,0x34,0x34,0x1b,0x3d,0xdb,0x61,0x94,0x20,0x38,0x36,0x36,0x1e,0x07,0x18,0x16,0x11,0x06,0x0d,0x16,0x11,0x71,0x58,0x15,0x20,0x14,0x0a,0x17,0x23,0x71,0x57,0x2c,0x28,0x17,0x23,0xb8,0x9b,0x33,0x46,0x2b,0x14,0x10,0x17,0x16,0x11,0x14,0x12,0x14,0x12,0x0b,0x10,0x12, 0x07,0x17,0x1d,0x15,0x12,0x16,0x11,0x2a,0x19,0x12,0x1d,0x33,0x3d,0x19,0x0a,0x0c,0x0b,0x02,0x36,0x4b,0x30,0x15,0x0d,0x13,0x18,0x0a,0x12,0x1d,0x06,0x0d,0x16,0x11,0xb7,0x54,0x62,0x27,0x62,0x62,0x62,0xeb,0x62,0x00,0x00,0x06,0xfd,0x71,0x07,0x31,0x01,0x80,0x09,0x5c,0x00,0x43,0x00,0x52,0x00,0x61,0x00,0x65,0x00,0x69,0x00,0x6d, 0x00,0x00,0x03,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x33,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x22,0x26,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x26,0x26,0x17,0x34, 0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x25,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x03,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0x05,0x23,0x35,0x33,0xfc,0x15,0x26,0x33,0x1e,0x24,0x39,0x27,0x15,0x0c,0x74,0x1f,0x16,0x15,0x26,0x32,0x1e,0x24,0x38,0x28,0x15,0x33,0x4f,0x60,0x2c,0x4b,0x1a,0x2f, 0x14,0x2a,0x67,0x36,0x48,0x68,0x89,0x27,0x1d,0x15,0x0b,0x05,0x5a,0x04,0x09,0x0a,0x0e,0x0c,0x22,0x33,0x48,0x31,0x13,0x26,0x21,0x18,0x04,0x22,0x10,0xc8,0x0a,0x12,0x17,0x0d,0x11,0x1c,0x08,0x16,0x25,0x1e,0x0c,0x01,0x58,0x0b,0x12,0x17,0x0c,0x11,0x1c,0x08,0x16,0x25,0x1e,0x0c,0x58,0x65,0x65,0x8c,0x64,0x64,0xfe,0x63,0x64,0x64, 0x08,0x00,0x1b,0x3d,0x33,0x21,0x2c,0x40,0x49,0x1d,0x29,0x1c,0x16,0x35,0x20,0x1b,0x3d,0x33,0x21,0x2c,0x40,0x49,0x1d,0x3e,0x44,0x1f,0x05,0x0f,0x08,0x13,0x07,0x0f,0x20,0x17,0x43,0x25,0x1b,0x34,0x14,0x11,0x34,0x13,0x14,0x23,0x09,0x08,0x0a,0x04,0x01,0x01,0x02,0x02,0x01,0x16,0x31,0x08,0x0f,0x27,0x23,0x18,0x2b,0x19,0x09,0x14, 0x15,0x19,0x0f,0x0d,0x20,0x0f,0x27,0x23,0x18,0x2b,0x19,0x09,0x14,0x15,0x18,0x0f,0x0f,0x01,0x3f,0x62,0x62,0x62,0x62,0x62,0x00,0x0a,0xfd,0x0e,0x06,0x71,0x02,0x8c,0x09,0x5c,0x00,0x4b,0x00,0x6d,0x00,0x7c,0x00,0x8b,0x00,0x8f,0x00,0x93,0x00,0x97,0x00,0x9b,0x00,0x9f,0x00,0xaf,0x00,0x00,0x01,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02, 0x15,0x14,0x07,0x33,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x0e,0x03,0x23,0x23,0x22,0x26,0x27,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x23,0x22,0x26,0x26,0x34,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x16,0x16,0x33,0x32,0x36,0x37,0x26,0x26,0x05,0x16,0x16,0x33,0x32, 0x3e,0x02,0x37,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x25,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x17,0x36,0x03,0x23,0x35,0x33,0x01,0x23,0x35,0x33,0x25,0x23,0x35,0x33,0x05,0x23, 0x35,0x33,0x01,0x23,0x35,0x33,0x05,0x32,0x36,0x37,0x2e,0x03,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0xfe,0xa0,0x15,0x26,0x33,0x1e,0x24,0x39,0x27,0x15,0x0c,0x74,0x1f,0x16,0x15,0x26,0x32,0x1e,0x24,0x38,0x28,0x15,0x33,0x4f,0x60,0x2c,0x4b,0x19,0x30,0x14,0x15,0x30,0x2f,0x2c,0x12,0x27,0x30,0x42,0x1d,0x16,0x2b,0x17,0x1c,0x28,0x50, 0x02,0x01,0x01,0x1d,0x2d,0x39,0x1b,0x12,0x26,0x24,0x20,0x0d,0x19,0x2f,0x1e,0x14,0x1e,0x05,0x22,0x10,0x02,0x89,0x2a,0x51,0x1d,0x1e,0x27,0x19,0x0c,0x02,0x16,0x1c,0x1d,0x35,0x2a,0x19,0x16,0x25,0x33,0x1e,0x2d,0x3b,0x23,0x0f,0x16,0x30,0x4e,0x37,0x26,0x4b,0x27,0xfe,0x3f,0x0a,0x12,0x17,0x0d,0x11,0x1c,0x08,0x16,0x25,0x1e,0x0c, 0x01,0x58,0x0b,0x12,0x17,0x0c,0x11,0x1c,0x08,0x16,0x25,0x1e,0x0c,0x58,0x65,0x65,0xfd,0x2c,0x65,0x65,0x01,0xc3,0x64,0x64,0x01,0x9d,0x64,0x64,0xfd,0x2c,0x64,0x64,0x03,0xe3,0x0b,0x15,0x0a,0x02,0x0b,0x11,0x14,0x0c,0x08,0x10,0x0d,0x08,0x27,0x08,0x00,0x1b,0x3d,0x33,0x21,0x2c,0x40,0x49,0x1d,0x29,0x1c,0x16,0x35,0x20,0x1b,0x3d, 0x33,0x21,0x2c,0x40,0x49,0x1d,0x3e,0x44,0x1f,0x05,0x0f,0x08,0x08,0x0a,0x04,0x01,0x2a,0x19,0x12,0x1d,0x33,0x3d,0x19,0x0a,0x0c,0x0b,0x02,0x36,0x4b,0x30,0x15,0x0d,0x13,0x18,0x0a,0x14,0x1c,0x03,0x02,0x16,0x31,0xe9,0x11,0x13,0x12,0x1d,0x25,0x14,0x07,0x12,0x23,0x33,0x21,0x1b,0x3d,0x33,0x21,0x38,0x51,0x59,0x21,0x30,0x59,0x43, 0x29,0x09,0x13,0x01,0x4b,0x0f,0x27,0x23,0x18,0x2b,0x19,0x09,0x14,0x15,0x19,0x0f,0x0d,0x20,0x0f,0x27,0x23,0x18,0x2b,0x19,0x09,0x14,0x15,0x18,0x0f,0x0f,0x01,0x3f,0x62,0xfe,0xd6,0x62,0x66,0x62,0x62,0x62,0xfe,0xd6,0x62,0xff,0x02,0x05,0x0e,0x25,0x21,0x16,0x0c,0x14,0x17,0x0c,0x16,0x18,0x00,0x02,0x00,0x00,0x06,0x71,0x02,0xf4, 0x08,0x06,0x00,0x1b,0x00,0x2e,0x00,0x14,0xb7,0x21,0x18,0x18,0x05,0x2a,0x10,0x10,0x05,0x00,0x2f,0x33,0x2f,0x33,0x11,0x33,0x11,0x33,0x30,0x31,0x01,0x0e,0x03,0x23,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x33,0x32,0x36,0x37,0x25,0x14,0x1e,0x02,0x33,0x33,0x36,0x36,0x35,0x34,0x2e,0x02,0x23, 0x22,0x0e,0x02,0x02,0xf4,0x11,0x3c,0x4e,0x5d,0x31,0xef,0x3f,0x54,0x33,0x16,0x11,0x2b,0x48,0x38,0x2b,0x43,0x2c,0x17,0x13,0x81,0x59,0x93,0x2d,0xfd,0x66,0x0f,0x21,0x34,0x24,0x15,0x0f,0x0d,0x10,0x1a,0x20,0x10,0x1d,0x25,0x15,0x08,0x06,0x98,0x08,0x0f,0x0a,0x06,0x26,0x3c,0x49,0x23,0x21,0x47,0x3a,0x25,0x1f,0x36,0x4a,0x2b,0x32, 0x33,0x13,0x10,0x41,0x13,0x24,0x1c,0x11,0x1d,0x31,0x15,0x19,0x26,0x1a,0x0d,0x12,0x1c,0x25,0x00,0x02,0xff,0xfe,0x06,0x71,0x03,0x28,0x07,0xeb,0x00,0x29,0x00,0x39,0x00,0x21,0x40,0x0e,0x0f,0x2d,0x2d,0x20,0x08,0x14,0x1c,0x1c,0x26,0x35,0x14,0x14,0x03,0x26,0x00,0x2f,0x33,0x33,0x2f,0x33,0x11,0x33,0x2f,0x12,0x39,0x39,0x33,0x11, 0x33,0x30,0x31,0x03,0x16,0x16,0x33,0x32,0x3e,0x02,0x37,0x33,0x15,0x14,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x16,0x15,0x14,0x0e,0x02,0x23,0x23,0x22,0x26,0x27,0x23,0x0e,0x03,0x23,0x22,0x22,0x27,0x25,0x32,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x02,0x0f,0x1b,0x0d,0x37,0x4b,0x2e,0x16,0x03,0x5b,0x04,0x0c, 0x18,0x15,0x0d,0x30,0x44,0x57,0x35,0x42,0x43,0x1d,0x41,0x67,0x4a,0x5d,0x4c,0x52,0x06,0x04,0x0b,0x22,0x35,0x4c,0x35,0x0a,0x13,0x0b,0x01,0xe4,0x08,0x16,0x0c,0x16,0x3f,0x3a,0x2a,0x23,0x1d,0x1f,0x34,0x29,0x1e,0x06,0xda,0x01,0x02,0x11,0x1f,0x2e,0x1e,0x14,0x1a,0x26,0x1a,0x0d,0x01,0x29,0x61,0x53,0x37,0x4c,0x46,0x28,0x51,0x42, 0x2a,0x3e,0x34,0x19,0x2b,0x1f,0x12,0x01,0x66,0x01,0x08,0x18,0x2f,0x27,0x17,0x24,0x1f,0x33,0x3f,0x00,0x00,0x02,0x00,0xdc,0x01,0x03,0x03,0xa8,0x04,0x9a,0x00,0x1e,0x00,0x39,0x00,0x1a,0xb1,0x03,0x1b,0xb8,0x04,0xfb,0xb3,0x36,0x1f,0x22,0x2c,0xb9,0x04,0xfb,0x00,0x0f,0x00,0x2f,0xed,0x2f,0xce,0x33,0xed,0x32,0x30,0x31,0x01,0x06, 0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x33,0x32,0x1e,0x04,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x37,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x02,0x3f,0x20,0x4d,0x2e,0x25,0x47,0x39,0x23,0x24,0x3b,0x4c,0x51,0x4e,0x20,0x1e,0x4d,0x4e,0x4b,0x3b, 0x23,0x26,0x3c,0x4b,0x25,0x2d,0x4a,0x1b,0x28,0x2d,0x30,0x13,0x24,0x1c,0x10,0x35,0x4b,0x52,0x1d,0x1d,0x4e,0x48,0x32,0x0f,0x1a,0x25,0x15,0x28,0x31,0x02,0x01,0x68,0x38,0x2d,0x1c,0x46,0x78,0x5c,0x5a,0xa0,0x87,0x6c,0x4c,0x28,0x27,0x4a,0x69,0x83,0x9c,0x57,0x60,0x7e,0x4b,0x1e,0x2d,0x38,0xaf,0x3a,0x49,0x0f,0x28,0x45,0x37,0x62, 0xa9,0x7b,0x46,0x47,0x7b,0xa6,0x5e,0x35,0x46,0x2c,0x12,0x44,0x3f,0x00,0xff,0xff,0xfe,0xd4,0xfe,0x53,0x00,0xdf,0x00,0x0c,0x02,0x07,0x0a,0x51,0xff,0x15,0xf7,0xe0,0xff,0xff,0x00,0x65,0xfd,0xff,0x04,0xad,0x03,0x95,0x02,0x26,0x08,0xe4,0x00,0x00,0x00,0x47,0x0f,0x54,0x01,0x91,0xfe,0xe7,0x2d,0x51,0x2d,0x42,0xff,0xff,0xff,0xba, 0xfd,0xc9,0x04,0xad,0x03,0x5e,0x02,0x26,0x08,0xe3,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x7f,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x04,0x3c,0x03,0x8a,0x02,0x26,0x08,0xe2,0x00,0x00,0x00,0x07,0x0f,0x54,0x01,0x31,0xfd,0xce,0xff,0xff,0x00,0xab,0xfe,0xa6,0x06,0xae,0x05,0xec,0x00,0x27,0x0f,0x50,0x02,0x59,0xfe,0xab,0x00,0x06, 0x0e,0x55,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x06,0x02,0x00,0x27,0x0f,0x50,0x00,0xf6,0xfe,0xab,0x00,0x06,0x0e,0x56,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x4b,0x06,0x02,0x00,0x27,0x0f,0x50,0x00,0x98,0xfe,0xab,0x00,0x06,0x08,0xed,0x00,0x00,0xff,0xff,0x00,0xab,0xfe,0xa6,0x07,0x59,0x04,0x12,0x00,0x27, 0x0f,0x50,0x02,0xad,0xfe,0xab,0x00,0x27,0x0a,0x19,0x02,0xc0,0xfb,0xb4,0x00,0x06,0x0e,0x6e,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac,0x05,0x3e,0x00,0x27,0x0f,0x50,0x00,0xa1,0xfe,0xab,0x00,0x26,0x09,0x3b,0x00,0x00,0x00,0x07,0x0a,0x19,0x00,0x65,0xfc,0xe0,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x8d,0x05,0x3e,0x00,0x27, 0x0a,0x19,0x00,0x65,0xfc,0xe0,0x00,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0x83,0xfe,0xab,0xff,0xff,0x00,0xab,0xfd,0xc9,0x07,0x59,0x04,0x12,0x00,0x27,0x0a,0x19,0x02,0xc0,0xfb,0xb4,0x00,0x26,0x0e,0x6e,0x00,0x00,0x00,0x07,0x0f,0x54,0x02,0xad,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0xac,0x05,0x3e,0x02,0x26, 0x09,0x3b,0x00,0x00,0x00,0x27,0x0a,0x19,0x00,0x65,0xfc,0xe0,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff,0xff,0xba,0xfd,0xc9,0x02,0x8d,0x05,0x3e,0x00,0x27,0x0a,0x19,0x00,0x65,0xfc,0xe0,0x00,0x26,0x0e,0x6f,0x00,0x00,0x00,0x07,0x0f,0x54,0x00,0x83,0xfd,0xce,0xff,0xff,0x00,0xab,0xff,0xea,0x07,0x59,0x04,0x39,0x02,0x26, 0x0e,0x6e,0x00,0x00,0x00,0x07,0x14,0x7c,0x03,0xc6,0xfb,0xaa,0x00,0x04,0xff,0xba,0xff,0xf2,0x03,0xf1,0x05,0x17,0x00,0x21,0x00,0x45,0x00,0x49,0x00,0x4d,0x00,0x25,0x40,0x0c,0x4b,0x47,0x4a,0x49,0x34,0x22,0x3a,0x2d,0x2d,0x20,0x05,0x19,0xb8,0x04,0xfb,0xb1,0x06,0x12,0x00,0x2f,0x33,0xed,0x32,0x2f,0x33,0x2f,0xcd,0xde,0x32,0xde, 0x32,0xcd,0x32,0x30,0x31,0x01,0x14,0x1e,0x02,0x33,0x15,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x3e,0x02,0x35,0x11,0x33,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36, 0x37,0x37,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x03,0x48,0x07,0x20,0x44,0x3e,0x16,0x32,0x4a,0x37,0x27,0x0f,0x04,0x1a,0x41,0x46,0x47,0x21,0xfe,0x1b,0x23,0x23,0x23,0x23,0x01,0xef,0x1d,0x43,0x38,0x25,0x9c,0xfd,0x2d,0x06,0x09,0x0e,0x16,0x0c,0x1b,0x2b,0x43,0x35,0x39,0x4f,0x31,0x16,0x5e,0x2f,0x54,0x73,0x45,0x3d,0x4f,0x38,0x2a, 0x17,0x1e,0x17,0x0a,0x07,0x97,0x73,0x47,0x72,0x01,0x98,0x43,0x60,0x3e,0x1e,0xa7,0x10,0x1f,0x2e,0x1e,0x23,0x2f,0x1d,0x0c,0x34,0x20,0x20,0x33,0x12,0x2c,0x47,0x35,0x01,0xbc,0x01,0x5b,0x1a,0x3c,0x21,0x24,0x31,0x15,0x0d,0x11,0x09,0x03,0x06,0x19,0x31,0x2c,0xb4,0xb8,0x53,0x5a,0x2a,0x07,0x02,0x0d,0x1b,0x19,0x22,0x50,0x36,0x25, 0x42,0x1f,0x3d,0x70,0x70,0x70,0x70,0x00,0x00,0x04,0xff,0xba,0xff,0xf2,0x03,0x48,0x05,0x17,0x00,0x14,0x00,0x38,0x00,0x3c,0x00,0x40,0x00,0x21,0x40,0x0b,0x3e,0x3a,0x3d,0x3c,0x27,0x15,0x2d,0x20,0x20,0x14,0x0d,0xb9,0x04,0xfb,0x00,0x06,0x00,0x2f,0xed,0x2f,0x33,0x2f,0xcd,0xde,0x32,0xde,0x32,0xcd,0x32,0x30,0x31,0x01,0x11,0x14, 0x0e,0x02,0x23,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x3e,0x02,0x35,0x11,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x03,0x48,0x3d,0x63,0x80,0x43,0xfe,0x1b,0x23, 0x23,0x23,0x23,0x01,0xef,0x2e,0x47,0x30,0x18,0xfd,0xc9,0x06,0x09,0x0e,0x16,0x0c,0x1b,0x2b,0x43,0x35,0x39,0x4f,0x31,0x16,0x5e,0x2f,0x54,0x73,0x45,0x3d,0x4f,0x38,0x2a,0x17,0x1e,0x17,0x0a,0x07,0x97,0x73,0x47,0x72,0x03,0x0f,0xfe,0x3d,0x71,0x88,0x49,0x18,0x34,0x20,0x20,0x33,0x0f,0x2a,0x48,0x39,0x01,0xbc,0x01,0x5b,0x1a,0x3c, 0x21,0x24,0x31,0x15,0x0d,0x11,0x09,0x03,0x06,0x19,0x31,0x2c,0xb4,0xb8,0x53,0x5a,0x2a,0x07,0x02,0x0d,0x1b,0x19,0x22,0x50,0x36,0x25,0x42,0x1f,0x3d,0x70,0x70,0x70,0x70,0x00,0x00,0x03,0xfe,0x84,0x06,0x71,0x01,0x76,0x08,0x8f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x1d,0x40,0x0c,0x24,0x27,0x27,0x29,0x2b,0x2b,0x00,0x18,0x11,0x11, 0x0b,0x18,0x00,0x2f,0x33,0x33,0x2f,0x12,0x39,0x33,0x2f,0x33,0x33,0x2f,0x33,0x30,0x31,0x01,0x06,0x06,0x15,0x14,0x16,0x17,0x1e,0x03,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x25,0x23,0x35,0x33,0x17,0x23,0x35,0x33,0xfe,0xed,0x06,0x09,0x12,0x1a,0x10,0x22, 0x37,0x56,0x44,0x49,0x66,0x3f,0x1d,0x5e,0x38,0x65,0x8a,0x52,0x49,0x60,0x43,0x32,0x1b,0x24,0x1c,0x0a,0x07,0x01,0x46,0x73,0x73,0xb9,0x72,0x72,0x07,0xe2,0x1a,0x3c,0x21,0x24,0x31,0x15,0x0d,0x11,0x09,0x03,0x06,0x19,0x32,0x2b,0xef,0xf3,0x53,0x5a,0x2a,0x07,0x02,0x0d,0x1b,0x19,0x22,0x50,0x36,0x25,0x42,0x1f,0x3d,0x70,0x70,0x70, 0xff,0xff,0x00,0x00,0xfd,0xff,0x03,0x57,0x05,0x5f,0x00,0x27,0x0a,0x1f,0x00,0xa5,0xfc,0xd3,0x00,0x06,0x0b,0x0c,0x00,0x00,0xff,0xff,0x00,0x9a,0xfd,0xd3,0x06,0xae,0x04,0x24,0x02,0x26,0x08,0xf7,0x00,0x00,0x00,0x27,0x0f,0x51,0x02,0x01,0xfd,0xd8,0x00,0x07,0x0a,0x1f,0x01,0xde,0xfb,0x98,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0xac, 0x05,0xb4,0x02,0x26,0x09,0x3b,0x00,0x00,0x00,0x27,0x0a,0x1f,0x00,0xa0,0xfd,0x28,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x02,0x74,0x05,0xb4,0x02,0x26,0x0e,0x6f,0x00,0x00,0x00,0x27,0x0a,0x1f,0x00,0xa0,0xfd,0x28,0x00,0x07,0x0f,0x51,0x00,0x4a,0xfe,0xab,0xff,0xff,0x00,0xab,0xff,0xea,0x08,0x04, 0x03,0x62,0x02,0x06,0x0e,0xa5,0x00,0x00,0xff,0xff,0xff,0xba,0xfe,0xa6,0x04,0x02,0x03,0x62,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x0e,0xfe,0xab,0xff,0xff,0xff,0xba,0xfe,0xa6,0x03,0x49,0x03,0x62,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x50,0x01,0x0e,0xfe,0xab,0xff,0xff,0x00,0x9b,0xfd,0xff,0x06,0x03, 0x02,0xb7,0x02,0x02,0x0e,0x70,0x00,0x00,0xff,0xff,0xff,0xba,0xff,0xf2,0x04,0x02,0x05,0x24,0x02,0x26,0x09,0x3d,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0xff,0xba,0xff,0xf2,0x03,0x49,0x05,0x24,0x02,0x26,0x09,0x3c,0x00,0x00,0x00,0x07,0x0f,0x50,0x00,0xd5,0x04,0x74,0xff,0xff,0x00,0x9b,0xfd,0xff,0x05,0x58, 0x01,0xc1,0x02,0x02,0x0e,0xcf,0x00,0x00,0x00,0x01,0x00,0xab,0x01,0xe1,0x01,0xac,0x02,0xe2,0x00,0x13,0x00,0x08,0xb1,0x0a,0x00,0x00,0x2f,0xcd,0x30,0x31,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0x2d,0x17,0x2e,0x25,0x18,0x18,0x25,0x2e,0x17,0x16,0x2d,0x25,0x17,0x17,0x25,0x2d,0x01, 0xe1,0x17,0x25,0x2d,0x16,0x16,0x2f,0x25,0x18,0x18,0x25,0x2f,0x16,0x16,0x2d,0x25,0x17,0x00,0x00,0x01,0x00,0xd4,0x01,0x18,0x01,0x84,0x03,0xe5,0x00,0x0d,0x00,0x08,0xb1,0x06,0x00,0x00,0x2f,0x2f,0x30,0x31,0x01,0x1e,0x03,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0x01,0x43,0x11,0x18,0x10,0x08,0x6b,0x07,0x10,0x1b,0x13,0x03,0xe5, 0x45,0x74,0x70,0x74,0x45,0xeb,0xe7,0x3b,0x6c,0x71,0x7f,0x4f,0x00,0x01,0x00,0x66,0x01,0x18,0x02,0x01,0x03,0xe5,0x00,0x0f,0x00,0x0a,0xb2,0x01,0x0e,0x07,0x00,0x2f,0x2f,0xcd,0x30,0x31,0x01,0x21,0x1e,0x03,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0x21,0x02,0x01,0xfe,0xf2,0x08,0x0d,0x09,0x05,0x6b,0x07,0x10,0x1b,0x13,0x01,0x9b, 0x03,0x5d,0x2b,0x51,0x53,0x59,0x32,0xeb,0xe7,0x3b,0x6c,0x71,0x7f,0x4f,0x00,0x01,0x00,0x1f,0x01,0x18,0x02,0x39,0x03,0xe5,0x00,0x37,0x00,0x14,0xb7,0x30,0x2b,0x25,0x06,0x16,0x1c,0x00,0x0d,0x00,0x2f,0x33,0x33,0xdc,0x32,0xcd,0x32,0x2f,0x30,0x31,0x13,0x16,0x16,0x17,0x16,0x32,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16, 0x15,0x14,0x06,0x07,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x23,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0x8e,0x0c,0x12,0x07,0x04,0x09,0x04,0x28,0x1f,0x12,0x0b,0x6b,0x0d,0x0d,0x04,0x02,0x08,0x0e,0x07,0x28,0x1f,0x12,0x0b,0x6b,0x0d,0x0d, 0x18,0x2b,0x3c,0x23,0x18,0x33,0x1d,0x13,0x2f,0x18,0x10,0x05,0x05,0x6b,0x07,0x10,0x1b,0x13,0x03,0xe5,0x30,0x51,0x27,0x01,0x25,0x1b,0x19,0x38,0x18,0x20,0x37,0x1b,0x0e,0x19,0x0d,0x02,0x01,0x25,0x1b,0x19,0x38,0x18,0x21,0x35,0x1d,0x29,0x3f,0x2d,0x17,0x0b,0x0f,0x0d,0x0c,0x2d,0x5e,0x39,0xeb,0xe7,0x3b,0x6c,0x71,0x7f,0x4f,0x00, 0x00,0x01,0x00,0x7f,0x01,0x0b,0x01,0xd8,0x03,0xfa,0x00,0x2e,0x00,0x0c,0xb3,0x14,0x13,0x2e,0x00,0x00,0x2f,0xcd,0x2f,0xcd,0x30,0x31,0x01,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37, 0x01,0xd8,0x23,0x3f,0x21,0x27,0x4d,0x3d,0x25,0x3b,0x46,0x43,0x38,0x1b,0x3e,0x66,0x4b,0x39,0x44,0x23,0x0b,0x21,0x35,0x44,0x24,0x3f,0x4a,0x25,0x0a,0x16,0x1f,0x25,0x0f,0x14,0x20,0x1e,0x20,0x13,0x01,0x20,0x0b,0x0a,0x10,0x23,0x37,0x28,0x2f,0x6c,0x44,0x20,0x42,0x33,0x22,0x41,0x3a,0x35,0x17,0x8d,0x11,0x1b,0x14,0x0e,0x04,0x0a, 0x1b,0x1c,0x1d,0x0d,0x1d,0x35,0x4b,0x32,0x1d,0x07,0x0e,0x0f,0x07,0x02,0x01,0x04,0x06,0x05,0x00,0x02,0x00,0x4f,0x01,0x60,0x02,0x08,0x03,0x99,0x00,0x13,0x00,0x27,0x00,0x0c,0xb3,0x14,0x0a,0x1e,0x00,0x00,0x2f,0xcd,0x2f,0xcd,0x30,0x31,0x01,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x03,0x22, 0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x01,0x26,0x30,0x4f,0x39,0x1f,0x2c,0x42,0x4b,0x20,0x22,0x4f,0x43,0x2c,0x22,0x3c,0x53,0x30,0x11,0x26,0x20,0x16,0x12,0x1e,0x28,0x16,0x23,0x2d,0x1b,0x0a,0x18,0x24,0x29,0x01,0x60,0x1b,0x36,0x4f,0x35,0x54,0x84,0x5b,0x31,0x2b,0x54,0x7e,0x54,0x39,0x56,0x3b, 0x1e,0x01,0xb3,0x1f,0x38,0x4d,0x2e,0x1b,0x22,0x14,0x07,0x0f,0x19,0x1f,0x10,0x30,0x4e,0x37,0x1e,0x00,0x00,0x01,0x00,0x35,0x01,0x18,0x02,0x22,0x03,0xe5,0x00,0x12,0x00,0x0a,0xb2,0x12,0x07,0x0a,0x00,0x2f,0xcd,0x2f,0x30,0x31,0x01,0x2e,0x05,0x27,0x21,0x35,0x21,0x17,0x1e,0x05,0x17,0x01,0xb2,0x10,0x16,0x10,0x09,0x06,0x04,0x02, 0xfe,0xce,0x01,0x99,0x03,0x02,0x04,0x07,0x0a,0x11,0x18,0x11,0x01,0x18,0x43,0x66,0x56,0x4d,0x55,0x63,0x41,0x88,0x63,0x46,0x6c,0x5b,0x53,0x5b,0x6a,0x45,0x00,0x01,0x00,0x1b,0x01,0x12,0x02,0x3c,0x03,0xe5,0x00,0x13,0x00,0x0c,0xb3,0x03,0x10,0x00,0x0a,0x00,0x2f,0x33,0x2f,0x33,0x30,0x31,0x01,0x36,0x36,0x37,0x33,0x0e,0x03,0x07, 0x23,0x2e,0x03,0x27,0x33,0x16,0x16,0x17,0x01,0x2d,0x22,0x4e,0x2d,0x72,0x23,0x3d,0x38,0x32,0x19,0x5c,0x1a,0x34,0x38,0x3b,0x21,0x72,0x2d,0x4e,0x22,0x01,0xe5,0x87,0xfc,0x7d,0x60,0xb6,0xb1,0xb1,0x5b,0x60,0xb4,0xb1,0xb1,0x5d,0x7d,0xfb,0x88,0x00,0x00,0x01,0x00,0x1b,0x01,0x18,0x02,0x3c,0x03,0xea,0x00,0x13,0x00,0x0c,0xb3,0x13, 0x09,0x10,0x03,0x00,0x2f,0x33,0x2f,0x33,0x30,0x31,0x01,0x06,0x06,0x07,0x23,0x3e,0x03,0x37,0x33,0x1e,0x03,0x17,0x23,0x26,0x26,0x27,0x01,0x2a,0x22,0x4e,0x2d,0x72,0x23,0x3d,0x37,0x33,0x19,0x5c,0x1a,0x34,0x38,0x3b,0x21,0x72,0x2d,0x4e,0x22,0x03,0x18,0x88,0xfb,0x7d,0x60,0xb5,0xb1,0xb1,0x5b,0x5f,0xb4,0xb1,0xb1,0x5d,0x7d,0xfa, 0x89,0x00,0x00,0x02,0x00,0x35,0x01,0x18,0x02,0x23,0x03,0xeb,0x00,0x1c,0x00,0x2d,0x00,0x0e,0xb4,0x1c,0x05,0x28,0x20,0x0f,0x00,0x2f,0xdd,0xde,0xcd,0x2f,0x30,0x31,0x01,0x26,0x26,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03,0x17,0x03,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14, 0x16,0x33,0x32,0x36,0x37,0x26,0x26,0x01,0xb2,0x28,0x20,0x08,0x38,0x36,0x27,0x45,0x35,0x1e,0x1c,0x33,0x47,0x2c,0x2a,0x47,0x1f,0x10,0x13,0x0c,0x07,0x04,0x03,0x0a,0x15,0x23,0x1d,0xdd,0x0e,0x2d,0x1f,0x13,0x1e,0x14,0x0b,0x38,0x29,0x14,0x2e,0x18,0x03,0x07,0x01,0x18,0x5b,0xa5,0x40,0x16,0x19,0x31,0x4a,0x32,0x2f,0x53,0x3d,0x24, 0x28,0x2e,0x1a,0x30,0x36,0x3e,0x26,0x26,0x53,0x63,0x75,0x48,0x02,0x04,0x22,0x28,0x10,0x19,0x20,0x0f,0x26,0x25,0x08,0x07,0x1a,0x1f,0x00,0x01,0x00,0x53,0x01,0x18,0x02,0x05,0x03,0xf1,0x00,0x2b,0x00,0x10,0xb5,0x24,0x1c,0x15,0x0b,0x00,0x05,0x00,0x2f,0x33,0xdd,0xde,0xcd,0x2f,0x30,0x31,0x13,0x17,0x17,0x36,0x36,0x33,0x32,0x16, 0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x06,0x23,0x22,0x26,0x27,0x07,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x27,0xc2,0x12,0x03,0x1a,0x58,0x3f,0x0c,0x23,0x16,0x22,0x25,0x1d,0x38,0x2b,0x1b,0x14,0x1f,0x27,0x14,0x2d,0x58,0x27,0x1f,0x5b,0x30,0x18,0x2e,0x14,0x02,0x02,0x02, 0x6b,0x07,0x10,0x1b,0x13,0x03,0xe5,0x52,0x01,0x2a,0x35,0x03,0x05,0x85,0x08,0x0a,0x13,0x1c,0x12,0x11,0x17,0x0f,0x07,0x1e,0x18,0x8a,0x14,0x1d,0x09,0x0b,0x01,0x1b,0x33,0x20,0xeb,0xe7,0x3b,0x6c,0x71,0x7f,0x4f,0x00,0x00,0x02,0x00,0x32,0x01,0x07,0x02,0x25,0x03,0xed,0x00,0x1a,0x00,0x35,0x00,0x12,0xb6,0x28,0x25,0x2c,0x03,0x17, 0x1b,0x0d,0x00,0x2f,0xcd,0x2f,0x33,0xdd,0x32,0xcc,0x30,0x31,0x01,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x33,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x01,0x29,0x14,0x34,0x1e,0x1a, 0x33,0x2a,0x1a,0x32,0x4c,0x58,0x27,0x26,0x57,0x49,0x30,0x1c,0x2c,0x36,0x1a,0x1d,0x32,0x12,0x04,0x15,0x32,0x2b,0x1c,0x08,0x0d,0x13,0x0b,0x17,0x18,0x02,0x5b,0x17,0x1b,0x0a,0x12,0x0e,0x08,0x1e,0x2d,0x34,0x01,0x4e,0x28,0x1f,0x17,0x3b,0x64,0x4e,0x6c,0xb1,0x7f,0x46,0x44,0x7b,0xae,0x69,0x50,0x69,0x3e,0x19,0x1f,0x28,0x02,0x1f, 0x35,0x5d,0x7f,0x4b,0x26,0x32,0x1d,0x0c,0x31,0x39,0x34,0x35,0x09,0x1b,0x31,0x27,0x4e,0x81,0x5d,0x34,0x00,0x01,0x00,0x59,0x01,0x03,0x01,0xff,0x03,0xec,0x00,0x27,0x00,0x19,0x40,0x0a,0x20,0x19,0x00,0x23,0x1f,0x1f,0x24,0x23,0x0f,0x08,0x00,0x2f,0xcd,0x2f,0x33,0x39,0x2f,0x12,0x39,0x33,0x33,0x30,0x31,0x01,0x26,0x26,0x35,0x34, 0x3e,0x02,0x33,0x32,0x16,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x36,0x36,0x37,0x15,0x06,0x06,0x07,0x27,0x36,0x36,0x37,0x01,0x18,0x48,0x46,0x24,0x3f,0x56,0x32,0x10,0x25,0x1a,0x1b,0x2a,0x12,0x18,0x2b,0x21,0x14,0x12,0x1c,0x25,0x14,0x12,0x1f,0x0f,0x14,0x2e,0x21,0x6a,0xc3,0x5a,0x1f, 0x28,0x62,0x36,0x02,0x70,0x13,0x59,0x45,0x31,0x4c,0x33,0x1b,0x03,0x04,0x88,0x04,0x04,0x07,0x12,0x1f,0x17,0x16,0x1e,0x13,0x09,0x06,0x05,0x0b,0x1a,0x10,0x9b,0x2e,0xb4,0x86,0x9c,0x3c,0x65,0x2d,0x00,0x01,0x00,0x2b,0x01,0x18,0x02,0x2d,0x03,0xec,0x00,0x28,0x00,0x0e,0xb4,0x09,0x0f,0x04,0x23,0x19,0x00,0x2f,0x2f,0x33,0xdd,0xcc, 0x30,0x31,0x01,0x36,0x36,0x37,0x33,0x0e,0x03,0x07,0x23,0x2e,0x03,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x16,0x16,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x01,0x6c,0x0e,0x1e,0x13,0x82,0x1e,0x2b,0x21,0x18,0x0a,0x5b,0x09,0x19,0x20,0x27,0x16,0x17,0x13,0x09,0x03,0x08,0x08,0x6b,0x0b,0x0d,0x0b, 0x4c,0x3e,0x22,0x38,0x2c,0x22,0x0c,0x03,0x71,0x21,0x37,0x1c,0x2a,0x48,0x45,0x45,0x26,0x22,0x3c,0x2b,0x19,0x17,0x12,0x11,0x2c,0x14,0x2d,0x7c,0x58,0xd2,0xce,0x60,0x7a,0x51,0x36,0x1b,0x45,0x45,0x15,0x23,0x2c,0x17,0x00,0x01,0x00,0x4d,0x01,0x12,0x02,0x0a,0x03,0xe5,0x00,0x0e,0x00,0x0c,0xb3,0x09,0x05,0x07,0x00,0x00,0x2f,0x2f, 0xcd,0x32,0x30,0x31,0x01,0x0e,0x03,0x07,0x21,0x15,0x21,0x35,0x3e,0x03,0x37,0x01,0x5d,0x06,0x15,0x1e,0x26,0x18,0x01,0x24,0xfe,0x43,0x25,0x39,0x29,0x19,0x06,0x03,0xe5,0x79,0xb1,0x87,0x69,0x31,0x88,0x47,0x43,0x7f,0x94,0xb9,0x7d,0x00,0x00,0x06,0x00,0xa1,0xff,0xf2,0x0b,0x4d,0x08,0x36,0x00,0x64,0x00,0x78,0x00,0x86,0x00,0xb4, 0x00,0xb8,0x00,0xbc,0x00,0x54,0x40,0x0b,0xb8,0xb6,0xa0,0x87,0x94,0x9a,0x8d,0xa6,0xad,0x4d,0x34,0xb8,0x04,0xfb,0x40,0x0f,0x3e,0x82,0x40,0x7e,0x82,0x7e,0x82,0x40,0x40,0x5a,0x4d,0x76,0x53,0x46,0x61,0xb8,0x04,0xfb,0xb5,0x2c,0x25,0x1a,0xbc,0xba,0x6c,0xb9,0x04,0xfb,0x00,0x0a,0x00,0x2f,0xed,0xde,0xcd,0x2f,0x33,0x33,0xed,0x32, 0x32,0x32,0x2f,0x33,0x33,0x2f,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0xed,0x10,0xde,0x32,0xdd,0x32,0xdc,0x32,0x32,0xde,0xcd,0x30,0x31,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x07,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x27, 0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x25,0x14,0x1e,0x02,0x33, 0x32,0x36,0x37,0x11,0x0e,0x03,0x01,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x34,0x27,0x33,0x06,0x14,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x33,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x25,0x23,0x11,0x33,0x01,0x23,0x35,0x33,0x09,0xa8,0x4a,0x61,0x38, 0x16,0x31,0x55,0x75,0x44,0x48,0x79,0x36,0x14,0x26,0x1d,0x11,0x39,0x61,0x82,0x90,0x98,0x47,0x8d,0x3b,0x5c,0x46,0x34,0x13,0x04,0x19,0x40,0x49,0x4f,0x28,0x68,0x75,0x1c,0x04,0x31,0x91,0x49,0x38,0x64,0x50,0x3a,0x0e,0x2b,0x62,0x2a,0x45,0x7f,0x62,0x3a,0x58,0x92,0xbc,0x65,0x9c,0x0e,0x26,0x44,0x36,0x1c,0x41,0x36,0x24,0x9c,0x0c, 0x26,0x46,0x39,0x25,0x42,0x31,0x1c,0x9c,0x20,0x3c,0x57,0x38,0x96,0x30,0x75,0x36,0x01,0x0a,0x10,0x1b,0x27,0x2d,0x32,0x1a,0x1d,0x38,0x2c,0x1c,0x19,0x43,0x73,0x5a,0x21,0x1e,0xf6,0x87,0x23,0x3c,0x4e,0x2a,0x27,0x55,0x22,0x4d,0x87,0x66,0x3b,0x02,0xf8,0x03,0x01,0x26,0x2d,0x2d,0x22,0x01,0x5f,0x01,0x22,0x2d,0x30,0x24,0x03,0x5f, 0x01,0x01,0x63,0x52,0x26,0x44,0x14,0x06,0x15,0x49,0x27,0x2d,0x3d,0x26,0x11,0x03,0x01,0x6b,0x74,0x74,0x04,0xfb,0xb9,0xb9,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x53,0x57,0x21,0x4a,0x52,0x5a,0x30,0x60,0x82,0x53,0x2d,0x15,0x06,0x02,0x11,0x20,0x2e,0x1c,0x23,0x2f,0x1d,0x0c,0x40,0x3b,0x3f,0x3c,0x19,0x35,0x52,0x3a, 0x11,0x0c,0x20,0x45,0x6c,0x4d,0x5e,0x92,0x68,0x42,0x0f,0x61,0xfd,0xb5,0x3d,0x5b,0x3d,0x1e,0x13,0x2c,0x47,0x34,0x03,0x95,0xfc,0xa4,0x3b,0x5a,0x3e,0x20,0x16,0x2d,0x46,0x31,0x04,0x2b,0xfc,0x0d,0x45,0x5c,0x39,0x18,0x01,0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3f,0x43,0x49,0x2a,0x18,0x4d,0xab,0x26, 0x35,0x21,0x0e,0x0a,0x0b,0x01,0x76,0x0e,0x2f,0x41,0x52,0x04,0x80,0x1c,0x18,0x09,0x33,0x3f,0x3d,0x3c,0x0d,0x1c,0x0d,0x0e,0x1c,0x0b,0x3d,0x3d,0x3e,0x37,0x1f,0x1b,0x0c,0x18,0x08,0x6d,0x76,0x1f,0x20,0x20,0x1f,0x22,0x3a,0x4e,0x2c,0x21,0x18,0x53,0x01,0x56,0xfc,0x39,0xb5,0x00,0x00,0x04,0x00,0xa1,0xff,0xf2,0x0b,0x4d,0x05,0x7e, 0x00,0x64,0x00,0x78,0x00,0x86,0x00,0x8a,0x00,0x3b,0xb9,0x00,0x34,0x04,0xfb,0x40,0x0d,0x82,0x3e,0x40,0x7e,0x7e,0x40,0x40,0x5a,0x4d,0x76,0x53,0x46,0x60,0xb8,0x04,0xfb,0xb5,0x2c,0x25,0x19,0x8a,0x88,0x6c,0xb9,0x04,0xfb,0x00,0x0a,0x00,0x2f,0xed,0xde,0xcd,0x2f,0x33,0x33,0xed,0x32,0x32,0x32,0x2f,0x33,0x33,0x2f,0x39,0x2f,0x12, 0x39,0x39,0xed,0x30,0x31,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x15,0x14,0x0e,0x04,0x07,0x23,0x22,0x2e,0x02,0x27,0x23,0x0e,0x03,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0x23,0x22,0x2e,0x02,0x27,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x35,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02, 0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x33,0x11,0x14,0x1e,0x02,0x33,0x33,0x32,0x16,0x17,0x25,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x36,0x36,0x25,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x11,0x0e,0x03,0x01,0x23,0x35,0x33,0x09,0xa8,0x4a,0x61,0x38,0x16,0x31,0x55,0x75,0x44,0x48, 0x79,0x36,0x14,0x26,0x1d,0x11,0x39,0x61,0x82,0x90,0x98,0x47,0x8d,0x3b,0x5c,0x46,0x34,0x13,0x04,0x19,0x40,0x49,0x4f,0x28,0x68,0x75,0x1c,0x04,0x31,0x91,0x49,0x38,0x64,0x50,0x3a,0x0e,0x2b,0x62,0x2a,0x45,0x7f,0x62,0x3a,0x58,0x92,0xbc,0x65,0x9c,0x0e,0x26,0x44,0x36,0x1c,0x41,0x36,0x24,0x9c,0x0c,0x26,0x46,0x39,0x25,0x42,0x31, 0x1c,0x9c,0x20,0x3c,0x57,0x38,0x96,0x30,0x75,0x36,0x01,0x0a,0x10,0x1b,0x27,0x2d,0x32,0x1a,0x1d,0x38,0x2c,0x1c,0x19,0x43,0x73,0x5a,0x21,0x1e,0xf6,0x87,0x23,0x3c,0x4e,0x2a,0x27,0x55,0x22,0x4d,0x87,0x66,0x3b,0x08,0xfe,0xb9,0xb9,0x9e,0x1e,0x44,0x4d,0x55,0x2f,0x40,0x8d,0x77,0x4d,0x53,0x57,0x21,0x4a,0x52,0x5a,0x30,0x60,0x82, 0x53,0x2d,0x15,0x06,0x02,0x11,0x20,0x2e,0x1c,0x23,0x2f,0x1d,0x0c,0x40,0x3b,0x3f,0x3c,0x19,0x35,0x52,0x3a,0x11,0x0c,0x20,0x45,0x6c,0x4d,0x5e,0x92,0x68,0x42,0x0f,0x61,0xfd,0xb5,0x3d,0x5b,0x3d,0x1e,0x13,0x2c,0x47,0x34,0x03,0x95,0xfc,0xa4,0x3b,0x5a,0x3e,0x20,0x16,0x2d,0x46,0x31,0x04,0x2b,0xfc,0x0d,0x45,0x5c,0x39,0x18,0x01, 0x01,0xd6,0x1d,0x47,0x49,0x45,0x36,0x20,0x26,0x3c,0x4c,0x26,0x20,0x3f,0x43,0x49,0x2a,0x18,0x4d,0xab,0x26,0x35,0x21,0x0e,0x0a,0x0b,0x01,0x76,0x0e,0x2f,0x41,0x52,0x02,0x62,0xb5,0x00,0x00,0x01,0x00,0x73,0xff,0xf2,0x08,0xfe,0x00,0xc1,0x00,0x0e,0x00,0x0c,0xba,0x00,0x0e,0x04,0xfb,0x00,0x01,0x00,0x2f,0xed,0x30,0x31,0x05,0x21, 0x22,0x2e,0x02,0x27,0x27,0x37,0x1e,0x03,0x33,0x21,0x08,0xfe,0xf9,0xb1,0x4b,0x99,0x8f,0x7d,0x2e,0x1e,0x05,0x36,0x8d,0x9f,0xa9,0x50,0x06,0x2b,0x0e,0x07,0x0f,0x15,0x0e,0x91,0x05,0x0a,0x0f,0x0a,0x05,0x00,0x00,0x01,0x00,0x00,0xff,0xf2,0x05,0x2f,0x00,0x99,0x00,0x07,0x00,0x0c,0xba,0x00,0x00,0x04,0xfb,0x00,0x06,0x00,0x2f,0xed, 0x30,0x31,0x35,0x21,0x17,0x07,0x06,0x06,0x23,0x21,0x05,0x2a,0x05,0x1a,0x56,0xb9,0x6e,0xfc,0x68,0x99,0x05,0x84,0x0d,0x11,0x00,0x01,0x00,0x00,0xff,0xf2,0x05,0x2f,0x00,0x99,0x00,0x07,0x00,0x0c,0xba,0x00,0x00,0x04,0xfb,0x00,0x06,0x00,0x2f,0xed,0x30,0x31,0x35,0x21,0x17,0x07,0x06,0x06,0x23,0x21,0x05,0x2a,0x05,0x1a,0x56,0xb9, 0x6e,0xfc,0x68,0x99,0x05,0x84,0x0d,0x11,0xff,0xff,0x00,0x73,0xff,0xf2,0x08,0xfe,0x00,0xc1,0x02,0x06,0x14,0x99,0x00,0x00,0xff,0xff,0x00,0x73,0xff,0xf2,0x08,0xfe,0x00,0xc1,0x02,0x06,0x14,0x99,0x00,0x00,0x00,0x01,0x00,0xf2,0x02,0x84,0x02,0x5a,0x03,0xed,0x00,0x13,0x00,0x08,0xb1,0x0a,0x00,0x00,0x2f,0xcd,0x30,0x31,0x01,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x01,0xa8,0x20,0x40,0x35,0x21,0x21,0x35,0x40,0x20,0x1f,0x40,0x33,0x20,0x20,0x33,0x40,0x02,0x84,0x20,0x34,0x3f,0x20,0x1f,0x41,0x34,0x22,0x21,0x35,0x41,0x1f,0x20,0x3f,0x34,0x20,0x00,0x00,0x01,0x01,0x2f,0x01,0x4a,0x02,0x1d,0x05,0x7d,0x00,0x0d,0x00,0x08, 0xb1,0x06,0x00,0x00,0x2f,0x2f,0x30,0x31,0x01,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x01,0xb7,0x19,0x27,0x19,0x0d,0x84,0x0c,0x19,0x29,0x1c,0x05,0x7d,0x6c,0xb4,0xb1,0xbc,0x73,0xfe,0xcd,0x01,0x2d,0x67,0xb5,0xb5,0xc1,0x74,0x00,0x01,0x00,0x76,0x01,0x4a,0x02,0xd6,0x05,0x7d,0x00,0x0f,0x00,0x0a,0xb2,0x01,0x0f,0x08, 0x00,0x2f,0x2f,0xcd,0x30,0x31,0x01,0x15,0x21,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0x02,0xd6,0xfe,0x4a,0x10,0x19,0x12,0x09,0x84,0x0c,0x19,0x29,0x1c,0x05,0x7d,0x97,0x4f,0x9b,0xa0,0xa9,0x5d,0xfe,0xf4,0x01,0x06,0x75,0xc5,0xbc,0xc3,0x74,0x00,0x00,0x01,0x00,0x25,0x01,0x4a,0x03,0x28,0x05,0x7d,0x00,0x3c,0x00,0x14, 0xb7,0x35,0x2c,0x26,0x06,0x15,0x1d,0x00,0x0f,0x00,0x2f,0x33,0x33,0xdc,0x32,0xcd,0x32,0x2f,0x30,0x31,0x13,0x16,0x16,0x17,0x16,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x15,0x14,0x07,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x06,0x06,0x23,0x22,0x26, 0x27,0x1e,0x03,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0xac,0x11,0x1b,0x0b,0x0c,0x17,0x0b,0x1f,0x2c,0x1b,0x0c,0x12,0x0f,0x84,0x1f,0x12,0x24,0x1e,0x1f,0x2c,0x1b,0x0c,0x12,0x0f,0x84,0x0e,0x10,0x1d,0x39,0x54,0x37,0x23,0x4c,0x2d,0x1b,0x42,0x25,0x0c,0x19,0x0d,0x06,0x0a,0x07,0x04,0x83,0x10,0x1c,0x27,0x17,0x05,0x7d,0x45,0x79, 0x3a,0x03,0x02,0x13,0x21,0x2b,0x19,0x21,0x44,0x20,0x4b,0x45,0x36,0x2d,0x0a,0x13,0x21,0x2b,0x19,0x21,0x44,0x20,0x21,0x52,0x27,0x2c,0x51,0x3e,0x24,0x11,0x16,0x14,0x12,0x02,0x02,0x28,0x53,0x62,0x77,0x4c,0xfe,0xe1,0x01,0x1a,0x6c,0xcb,0xc4,0xbf,0x5f,0x00,0x00,0x01,0x00,0xab,0x01,0x38,0x02,0xa1,0x05,0x97,0x00,0x2f,0x00,0x0c, 0xb3,0x25,0x24,0x0a,0x10,0x00,0x2f,0xcd,0x2f,0xcd,0x30,0x31,0x01,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x37,0x15,0x0e,0x03,0x15,0x14,0x1e,0x02,0x17,0x02,0x3f,0x5f,0x6c,0x36,0x0e,0x25,0x36,0x3d,0x18,0x39,0x58,0x30,0x62,0x65, 0x37,0x6d,0x56,0x35,0x15,0x30,0x50,0x3c,0x39,0x4d,0x2e,0x14,0x24,0x55,0x8e,0x6b,0x56,0x66,0x34,0x0f,0x20,0x43,0x6a,0x4b,0x03,0x91,0x55,0x7b,0x56,0x33,0x0c,0x1c,0x22,0x12,0x06,0x0c,0x0d,0x96,0x21,0x17,0x31,0x4e,0x38,0x20,0x4d,0x5b,0x68,0x3a,0x1b,0x31,0x34,0x39,0x22,0x2d,0x58,0x55,0x4f,0x23,0x9f,0x1a,0x31,0x29,0x21,0x0a, 0x11,0x22,0x28,0x33,0x22,0x00,0x00,0x02,0x00,0x62,0x01,0xbc,0x02,0xeb,0x04,0xf3,0x00,0x13,0x00,0x27,0x00,0x0c,0xb3,0x1e,0x0a,0x14,0x00,0x00,0x2f,0xcd,0x2f,0xcd,0x30,0x31,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x17,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34, 0x2e,0x02,0x01,0xa1,0x35,0x74,0x62,0x3f,0x2f,0x57,0x7c,0x4c,0x4a,0x75,0x51,0x2b,0x40,0x60,0x6f,0x2e,0x1c,0x41,0x37,0x25,0x1e,0x33,0x43,0x26,0x36,0x4c,0x30,0x15,0x29,0x3d,0x46,0x04,0xf3,0x40,0x7c,0xb8,0x78,0x4d,0x7a,0x56,0x2e,0x29,0x4e,0x70,0x47,0x78,0xc1,0x87,0x49,0x94,0x35,0x5e,0x84,0x4f,0x2e,0x3f,0x26,0x11,0x18,0x2c, 0x3c,0x23,0x54,0x85,0x5d,0x31,0x00,0x01,0x00,0x42,0x01,0x4a,0x03,0x0a,0x05,0x7d,0x00,0x13,0x00,0x0a,0xb2,0x13,0x08,0x0a,0x00,0x2f,0xcd,0x2f,0x30,0x31,0x01,0x2e,0x05,0x27,0x27,0x21,0x35,0x21,0x17,0x1e,0x05,0x17,0x02,0x80,0x17,0x21,0x17,0x0e,0x0a,0x06,0x03,0x03,0xfe,0x35,0x02,0x4a,0x05,0x03,0x07,0x0a,0x0f,0x19,0x23,0x1a, 0x01,0x4a,0x60,0x96,0x7e,0x70,0x79,0x8a,0x59,0x5c,0x97,0x94,0x68,0xa1,0x89,0x7d,0x88,0xa1,0x67,0x00,0x00,0x01,0x00,0x1c,0x01,0x47,0x03,0x30,0x05,0x7d,0x00,0x13,0x00,0x0c,0xb3,0x03,0x0e,0x07,0x00,0x00,0x2f,0x32,0x2f,0x33,0x30,0x31,0x13,0x16,0x12,0x17,0x33,0x36,0x12,0x37,0x33,0x06,0x0a,0x02,0x07,0x23,0x26,0x0a,0x02,0x27, 0xa5,0x49,0x7d,0x39,0x04,0x3a,0x7d,0x49,0x88,0x32,0x59,0x53,0x4c,0x24,0x78,0x27,0x4e,0x53,0x57,0x2f,0x05,0x7d,0xc7,0xfe,0x64,0xdf,0xdf,0x01,0x9d,0xc6,0x89,0xfe,0xf5,0xfe,0xf5,0xfe,0xf3,0x8a,0x91,0x01,0x12,0x01,0x0b,0x01,0x05,0x83,0x00,0x01,0x00,0x1d,0x01,0x4a,0x03,0x30,0x05,0x80,0x00,0x13,0x00,0x0c,0xb3,0x03,0x0d,0x00, 0x07,0x00,0x2f,0x33,0x2f,0x33,0x30,0x31,0x01,0x26,0x02,0x27,0x23,0x06,0x02,0x07,0x23,0x36,0x1a,0x02,0x37,0x33,0x16,0x1a,0x02,0x17,0x02,0xa8,0x4a,0x7d,0x38,0x05,0x39,0x7e,0x48,0x88,0x31,0x59,0x52,0x4d,0x25,0x78,0x26,0x4e,0x53,0x57,0x2f,0x01,0x4a,0xc7,0x01,0x9b,0xe0,0xe0,0xfe,0x64,0xc6,0x88,0x01,0x0b,0x01,0x0b,0x01,0x0e, 0x8a,0x90,0xfe,0xed,0xfe,0xf6,0xfe,0xfa,0x83,0x00,0x00,0x02,0x00,0x3c,0x01,0x4a,0x03,0x10,0x05,0x87,0x00,0x1e,0x00,0x33,0x00,0x10,0xb5,0x07,0x31,0x31,0x1e,0x27,0x11,0x00,0x2f,0xcd,0x2f,0x39,0x2f,0xcd,0x30,0x31,0x01,0x2e,0x03,0x27,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x1e,0x03,0x17,0x1e,0x03, 0x17,0x01,0x2e,0x03,0x27,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x02,0x88,0x1f,0x28,0x1b,0x10,0x06,0x5d,0x55,0x3b,0x6a,0x4f,0x2e,0x27,0x4a,0x6a,0x43,0x41,0x6a,0x2d,0x18,0x1d,0x11,0x09,0x05,0x05,0x0f,0x1e,0x31,0x27,0xfe,0xf3,0x03,0x05,0x07,0x09,0x07,0x19,0x4d,0x33,0x1f,0x35,0x26,0x15,0x1c,0x30, 0x42,0x27,0x22,0x4a,0x01,0x4a,0x47,0x8a,0x81,0x77,0x34,0x29,0x26,0x4a,0x6c,0x46,0x3f,0x76,0x5b,0x37,0x3b,0x47,0x26,0x4b,0x51,0x5c,0x38,0x3b,0x85,0x97,0xab,0x63,0x02,0x86,0x1b,0x2b,0x25,0x21,0x11,0x3d,0x44,0x1b,0x2d,0x3b,0x20,0x25,0x3a,0x27,0x14,0x10,0x00,0x01,0x00,0x69,0x01,0x4a,0x02,0xe4,0x05,0x92,0x00,0x31,0x00,0x12, 0xb6,0x22,0x17,0x17,0x2a,0x0d,0x00,0x07,0x00,0x2f,0x33,0xcd,0x2f,0x39,0x2f,0xcd,0x30,0x31,0x13,0x17,0x33,0x3e,0x03,0x33,0x32,0x16,0x17,0x15,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x37,0x15,0x0e,0x03,0x23,0x22,0x26,0x27,0x07,0x16,0x16,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x27,0xf0,0x21,0x04,0x0d, 0x32,0x46,0x59,0x35,0x16,0x36,0x1d,0x33,0x36,0x30,0x58,0x42,0x28,0x1e,0x31,0x3c,0x1e,0x24,0x48,0x43,0x3d,0x19,0x12,0x37,0x45,0x4d,0x27,0x2a,0x53,0x1d,0x03,0x0a,0x07,0x83,0x0b,0x19,0x28,0x1e,0x05,0x7d,0x92,0x21,0x3d,0x2e,0x1b,0x05,0x08,0x95,0x0c,0x12,0x22,0x30,0x1d,0x1a,0x25,0x18,0x0b,0x0e,0x17,0x1e,0x10,0x9a,0x0e,0x1c, 0x16,0x0f,0x14,0x17,0x02,0x48,0xac,0x53,0xfe,0xe5,0x01,0x16,0x6a,0xba,0xba,0xc8,0x77,0x00,0x00,0x02,0x00,0x3c,0x01,0x36,0x03,0x10,0x05,0x81,0x00,0x1e,0x00,0x3c,0x00,0x12,0xb6,0x3c,0x3a,0x24,0x03,0x1b,0x30,0x0f,0x00,0x2f,0xcd,0x2f,0x33,0xdd,0x32,0xcc,0x30,0x31,0x01,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x04,0x33, 0x32,0x1e,0x04,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x37,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x01,0xa3,0x20,0x4c,0x2e,0x25,0x49,0x3b,0x24,0x22,0x38,0x4b,0x52,0x53,0x26,0x25,0x51,0x4f,0x48,0x37,0x20,0x27,0x3d,0x4d,0x26,0x2c,0x49,0x1c,0x36,0x0a, 0x15,0x21,0x16,0x23,0x25,0x10,0x02,0x16,0x25,0x30,0x35,0x35,0x18,0x23,0x50,0x44,0x2c,0x0e,0x18,0x21,0x13,0x50,0x06,0x01,0xa3,0x3c,0x31,0x22,0x55,0x91,0x70,0x6b,0xbe,0xa1,0x80,0x59,0x30,0x2e,0x57,0x7d,0x9c,0xba,0x68,0x74,0x98,0x5a,0x25,0x31,0x3c,0xcb,0x1f,0x37,0x29,0x18,0x33,0x47,0x48,0x15,0x53,0x96,0x81,0x68,0x49,0x28, 0x59,0x9a,0xd2,0x78,0x41,0x57,0x34,0x16,0x9c,0x00,0x00,0x01,0x00,0x6f,0x01,0x3a,0x02,0xdd,0x05,0x86,0x00,0x25,0x00,0x1b,0x40,0x0c,0x20,0x00,0x07,0x03,0x03,0x25,0x25,0x03,0x16,0x10,0x04,0x03,0x00,0x2f,0x33,0x2f,0xcd,0x11,0x39,0x2f,0x12,0x17,0x39,0x30,0x31,0x01,0x06,0x00,0x07,0x27,0x36,0x36,0x37,0x27,0x26,0x26,0x35,0x34, 0x3e,0x02,0x33,0x32,0x17,0x15,0x26,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x37,0x36,0x36,0x37,0x02,0xdd,0xa7,0xfe,0xde,0x83,0x22,0x43,0xa6,0x5e,0x01,0x6e,0x76,0x30,0x57,0x79,0x4a,0x2d,0x3e,0x1d,0x3b,0x1a,0x27,0x46,0x33,0x1e,0x19,0x2c,0x3b,0x21,0x34,0x35,0x1d,0x3c,0x24,0x03,0x78,0x4e,0xfe,0xe3,0xd3,0xaf, 0x6d,0xbe,0x4c,0x03,0x16,0x88,0x69,0x42,0x69,0x4a,0x27,0x09,0x99,0x05,0x05,0x0f,0x22,0x37,0x28,0x25,0x36,0x24,0x11,0x13,0x11,0x22,0x12,0x00,0x00,0x01,0x00,0x41,0x01,0x4a,0x03,0x0b,0x05,0x88,0x00,0x29,0x00,0x0e,0xb4,0x04,0x09,0x29,0x20,0x16,0x00,0x2f,0x2f,0x33,0xdd,0xce,0x30,0x31,0x01,0x06,0x06,0x07,0x23,0x2e,0x03,0x23, 0x22,0x0e,0x02,0x15,0x14,0x1e,0x04,0x15,0x11,0x23,0x11,0x34,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x17,0x33,0x36,0x36,0x37,0x03,0x0b,0x42,0x54,0x1c,0x7a,0x0d,0x29,0x35,0x40,0x25,0x15,0x1a,0x0f,0x06,0x08,0x0c,0x0d,0x0c,0x08,0x83,0x13,0x16,0x13,0x67,0x5e,0x34,0x56,0x44,0x30,0x0e,0x04,0x14,0x30,0x1d,0x05,0x7d,0x61, 0xc2,0x71,0x36,0x60,0x46,0x29,0x0b,0x13,0x19,0x0d,0x11,0x2b,0x3b,0x52,0x73,0x99,0x65,0xfe,0xda,0x01,0x10,0x93,0xd0,0x8e,0x5b,0x1e,0x5b,0x69,0x29,0x3f,0x4e,0x25,0x3c,0x65,0x2f,0x00,0x00,0x01,0x00,0x6b,0x01,0x47,0x02,0xe1,0x05,0x7d,0x00,0x12,0x00,0x0c,0xb3,0x00,0x0f,0x11,0x08,0x00,0x2f,0x2f,0xcd,0x32,0x30,0x31,0x13,0x3e, 0x05,0x37,0x33,0x0e,0x05,0x07,0x21,0x15,0x21,0x6b,0x25,0x3f,0x33,0x28,0x1e,0x13,0x05,0x83,0x06,0x12,0x19,0x21,0x27,0x2f,0x1a,0x01,0xc0,0xfd,0x8a,0x01,0x8b,0x45,0x83,0x89,0x98,0xb2,0xd5,0x82,0x82,0xd1,0xaa,0x8a,0x77,0x6b,0x36,0x97,0xff,0xff,0x00,0x39,0xfd,0xff,0x03,0x72,0x05,0x5f,0x02,0x26,0x0f,0x98,0x00,0x00,0x00,0x07, 0x0a,0x1f,0x01,0x09,0xfc,0xd3,0xff,0xff,0x00,0x9a,0xfd,0xd3,0x05,0x74,0x04,0x24,0x02,0x26,0x0f,0xab,0x00,0x00,0x00,0x27,0x0a,0x1f,0x02,0x00,0xfb,0x98,0x00,0x07,0x0f,0x51,0x02,0x01,0xfd,0xd8,0x00,0x01,0x00,0x55,0xff,0xe8,0x04,0x79,0x05,0x9a,0x00,0x2d,0x00,0x14,0x40,0x09,0x0e,0x0e,0x05,0x24,0x03,0x16,0x91,0x05,0x13,0x00, 0x3f,0xed,0x3f,0x12,0x39,0x2f,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x27,0x2e,0x03,0x27,0x33,0x1e,0x03,0x17,0x1e,0x03,0x04,0x79,0x4e,0x8f,0xc7,0x78,0x78,0xc1,0x87,0x48,0x0c,0x10,0xb4,0x0e,0x12,0x2c,0x58,0x83,0x58,0xb1, 0xb4,0x1e,0x35,0x49,0x2b,0x2f,0x57,0x44,0x2c,0x04,0xa8,0x03,0x22,0x38,0x4c,0x2e,0x2b,0x57,0x45,0x2b,0x01,0xdc,0x7b,0xbb,0x7e,0x40,0x43,0x75,0x9e,0x5b,0x27,0x52,0x2a,0x21,0x50,0x33,0x3e,0x67,0x4b,0x29,0xa9,0xae,0x40,0x6f,0x62,0x56,0x28,0x2c,0x67,0x85,0xab,0x72,0x60,0x89,0x69,0x57,0x2e,0x2c,0x60,0x74,0x8e,0x00,0x00,0x02, 0x00,0x78,0xff,0xe8,0x04,0xae,0x05,0x9a,0x00,0x2f,0x00,0x41,0x00,0x1c,0x40,0x0e,0x3d,0x91,0x26,0x13,0x12,0x00,0x10,0x03,0x03,0x1c,0x35,0x91,0x00,0x10,0x00,0x3f,0xed,0x39,0x39,0x3f,0x12,0x39,0x3f,0xed,0x30,0x31,0x01,0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x2e,0x06,0x35,0x35,0x33,0x15,0x14,0x1e,0x04,0x15,0x14,0x06,0x07,0x1e, 0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x01,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x02,0x9f,0x0e,0x1b,0x0e,0x01,0x01,0x20,0x35,0x44,0x46,0x44,0x35,0x20,0xa4,0x38,0x55,0x62,0x55,0x38,0x04,0x02,0x4d,0x74,0x4d,0x26,0x4f,0x90,0xc9,0x7a,0x7a,0xc5,0x8a,0x4b,0x43,0x88, 0xcf,0x01,0xec,0x33,0x5b,0x80,0x4c,0xb8,0xc4,0x32,0x5f,0x89,0x58,0x58,0x85,0x5a,0x2d,0x04,0x17,0x01,0x01,0x05,0x0a,0x05,0x18,0x1e,0x16,0x11,0x17,0x20,0x34,0x4b,0x36,0x28,0x28,0x1f,0x23,0x1d,0x1d,0x33,0x4f,0x40,0x0b,0x27,0x0f,0x1c,0x60,0x80,0x9c,0x57,0x7e,0xc8,0x8c,0x4a,0x4b,0x8a,0xc1,0x76,0x72,0xc8,0x94,0x55,0xfd,0xe7, 0x60,0x91,0x60,0x31,0xcb,0xbb,0x59,0x8d,0x61,0x34,0x34,0x62,0x8f,0x00,0x00,0x02,0x00,0x78,0xff,0xe8,0x04,0xae,0x05,0xae,0x00,0x2f,0x00,0x41,0x00,0x21,0x40,0x11,0x3d,0x91,0x26,0x13,0x10,0x10,0x00,0x0b,0x91,0x16,0x04,0x03,0x1e,0x35,0x91,0x00,0x10,0x00,0x3f,0xed,0x39,0x39,0x3f,0xed,0x12,0x39,0x2f,0x3f,0xed,0x30,0x31,0x01, 0x32,0x16,0x17,0x36,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x01,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x02,0x9f,0x26,0x46,0x21,0x07,0x08,0x1a,0x2f, 0x40,0x27,0x2f,0x47,0x2f,0x17,0xaf,0x35,0x60,0x86,0x50,0x51,0x82,0x5b,0x32,0x14,0x0c,0x73,0x70,0x4f,0x90,0xc9,0x7a,0x7a,0xc5,0x8a,0x4b,0x43,0x88,0xcf,0x01,0xec,0x33,0x5b,0x80,0x4c,0xb8,0xc4,0x32,0x5f,0x89,0x58,0x58,0x85,0x5a,0x2d,0x04,0x17,0x07,0x07,0x17,0x35,0x22,0x29,0x3d,0x28,0x13,0x17,0x27,0x36,0x1f,0x43,0x6e,0x4e, 0x2a,0x2a,0x50,0x71,0x46,0x39,0x58,0x1f,0x45,0xed,0x97,0x7e,0xc8,0x8c,0x4a,0x4b,0x8a,0xc1,0x76,0x72,0xc8,0x94,0x55,0xfd,0xe7,0x60,0x91,0x60,0x31,0xcb,0xbb,0x59,0x8d,0x61,0x34,0x34,0x62,0x8f,0x00,0x02,0x00,0x82,0xff,0xe0,0x06,0xac,0x05,0xaf,0x00,0x42,0x00,0x52,0x00,0x34,0x40,0x1b,0x1f,0x2e,0x2a,0x92,0x33,0x50,0x91,0x0a, 0x33,0x0a,0x33,0x0a,0x25,0x15,0x91,0x3d,0x04,0x24,0x25,0x13,0x12,0x40,0x40,0x48,0x91,0x00,0x04,0x00,0x3f,0xed,0x39,0x11,0x33,0x3f,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x10,0xed,0x39,0x39,0x30,0x31,0x01,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x26,0x26,0x23,0x22,0x0e,0x02, 0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x17,0x07,0x2e,0x03,0x23,0x22,0x06,0x07,0x35,0x3e,0x03,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x04,0xdf,0x6a,0xab,0x78,0x40,0x40,0x78,0xab,0x6a,0x6a,0xb1,0x7f,0x47,0x29,0x26,0x38,0x6d,0x31, 0x4e,0x79,0x53,0x2b,0x59,0x94,0xc0,0x67,0x57,0xa4,0x9b,0x91,0x45,0x5d,0x44,0xbb,0xd2,0xda,0x63,0x78,0xc1,0x3c,0x1b,0x46,0x4d,0x50,0x25,0x52,0x89,0x62,0x36,0x48,0x85,0xbb,0x73,0x55,0x9a,0x47,0x3e,0x97,0x01,0x74,0x21,0x46,0x6c,0x4a,0x4b,0x72,0x4d,0x27,0x9b,0x96,0x95,0x88,0x05,0xaf,0x42,0x7d,0xb6,0x75,0x75,0xb6,0x7d,0x40, 0x41,0x7e,0xb6,0x75,0x56,0x90,0x39,0x22,0x11,0x38,0x67,0x93,0x5a,0x82,0xb6,0x7f,0x54,0x20,0x1b,0x35,0x3e,0x4a,0x2f,0x7b,0x33,0x5b,0x45,0x28,0x23,0x1b,0x9c,0x0a,0x11,0x0d,0x08,0x02,0x22,0x68,0x8a,0xab,0x66,0x7e,0xca,0x8c,0x4b,0x25,0x37,0x2d,0x2f,0xfe,0x16,0x52,0x7e,0x57,0x2d,0x32,0x5a,0x7c,0x4a,0xa5,0xaf,0xad,0x00,0x01, 0x00,0x64,0xff,0xe8,0x04,0x87,0x05,0xb2,0x00,0x31,0x00,0x1b,0x40,0x0d,0x26,0x0e,0x26,0x0e,0x05,0x21,0x91,0x2c,0x04,0x16,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11, 0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x04,0x87,0x4a,0x8b,0xca,0x80,0x75,0xbf,0x87,0x49,0x0f,0x10,0xb6,0x0f,0x16,0x2d,0x5a,0x86,0x59,0x57,0x85,0x5a,0x2f,0x2d,0x51,0x72,0x44,0x42,0x6c,0x4b,0x29,0xb0,0x48,0x7e,0xaa,0x62,0x62,0xae,0x81,0x4b,0x01,0xda,0x71,0xb7,0x83,0x47,0x44, 0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20,0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a,0x82,0x53,0x02,0x27,0x44,0x68,0x47,0x25,0x1b,0x34,0x50,0x34,0x58,0x88,0x5b,0x2f,0x35,0x66,0x96,0x61,0x00,0x00,0x01,0x00,0x6e,0xff,0xe8,0x04,0x93,0x05,0xb2,0x00,0x41,0x00,0x22,0x40,0x11,0x3d,0x1f,0x2d,0x22,0x91,0x0d,0x1f,0x1f,0x05,0x2a,0x91,0x33, 0x04,0x15,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xce,0xfd,0xce,0x12,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x3e,0x02, 0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x04,0x93,0x5a,0x94,0xbf,0x66,0x75,0xc3,0x8c,0x4e,0x1e,0xb7,0x12,0x13,0x34,0x5f,0x83,0x4e,0x64,0x88,0x52,0x23,0x2a,0x56,0x83,0x59,0xd4,0xce,0x52,0x6b,0x3f,0x1a,0x7f,0x82,0x79,0x8c,0xb0,0x40,0x75,0xa5,0x65,0x5c,0x9b,0x71,0x3f,0x21,0x3f,0x5d,0x3c,0x43,0x76,0x59,0x33, 0x01,0xb2,0x75,0xad,0x71,0x37,0x3f,0x72,0x9f,0x60,0x4d,0x57,0x22,0x5a,0x27,0x44,0x69,0x48,0x26,0x35,0x57,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x24,0x3f,0x53,0x2f,0x60,0x6b,0x68,0x6b,0x5c,0x88,0x5a,0x2c,0x31,0x5c,0x81,0x50,0x3b,0x66,0x4e,0x34,0x09,0x08,0x3c,0x61,0x83,0x00,0x00,0x03,0x00,0x28,0xff,0xe8,0x05,0xfe,0x05,0xb2, 0x00,0x27,0x00,0x37,0x00,0x45,0x00,0x24,0x40,0x13,0x1e,0x3b,0x91,0x23,0x10,0x0b,0x33,0x91,0x10,0x10,0x05,0x2b,0x91,0x1a,0x04,0x43,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x3f,0xed,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02, 0x33,0x32,0x16,0x15,0x15,0x3e,0x03,0x33,0x32,0x1e,0x02,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x01,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x05,0xfe,0x45,0x84,0xc0,0x7a,0x6f,0xb7,0x82,0x47,0x0d,0x28,0x2e,0x34,0x19,0x41,0x70,0x53,0x30,0x2f,0x56,0x79,0x49,0x9e,0xa1,0x21, 0x53,0x5d,0x63,0x31,0x6e,0xb5,0x81,0x47,0xfc,0x0e,0x58,0x45,0x45,0x58,0x18,0x2a,0x39,0x21,0x21,0x3a,0x2a,0x19,0x03,0x40,0xa8,0x9d,0x4f,0x80,0x5a,0x30,0xaa,0xaf,0xa5,0xa0,0x02,0x16,0x84,0xcf,0x90,0x4b,0x4a,0x8c,0xc9,0x7f,0x01,0x70,0x0d,0x16,0x0f,0x09,0x2a,0x51,0x73,0x4a,0x4a,0x76,0x53,0x2c,0x9b,0x9c,0xf7,0x29,0x38,0x22, 0x0f,0x42,0x82,0xbf,0x01,0xe2,0x54,0x52,0x52,0x54,0x2c,0x3e,0x28,0x12,0x12,0x28,0x3e,0xfd,0xc7,0xbf,0xb1,0x2d,0x5b,0x8c,0x60,0xc4,0xca,0xcb,0x00,0x02,0x00,0x82,0xff,0xe8,0x07,0x4c,0x05,0xb2,0x00,0x28,0x00,0x36,0x00,0x20,0x40,0x11,0x10,0x23,0x23,0x0e,0x91,0x26,0x04,0x2c,0x91,0x21,0x04,0x34,0x91,0x17,0x13,0x06,0x12,0x00, 0x3f,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x39,0x11,0x33,0x30,0x31,0x01,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x10,0x02,0x23,0x22,0x07,0x16,0x11,0x14,0x02,0x06,0x06,0x23,0x22,0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x36,0x33,0x32,0x17,0x36,0x36,0x33,0x32,0x00,0x01,0x10,0x02,0x23,0x22,0x02,0x11,0x14,0x1e,0x02,0x33,0x32,0x12,0x07, 0x4c,0x1e,0x31,0x3e,0x20,0xc9,0x2b,0x49,0x34,0x1e,0xae,0xb4,0x91,0x58,0x61,0x4a,0x8b,0xca,0x7f,0x73,0xc3,0x8d,0x4f,0x4c,0x8e,0xce,0x82,0xc6,0x7d,0x44,0xac,0x67,0xf9,0x01,0x0d,0xfc,0xb6,0xae,0xb4,0xb2,0xbc,0x32,0x5e,0x88,0x56,0xac,0xb6,0x02,0xc0,0x80,0xd2,0xab,0x8a,0x39,0x3a,0x9c,0xb8,0xcd,0x6b,0x01,0x2a,0x01,0x2c,0x60, 0xb7,0xfe,0xc7,0xba,0xfe,0xea,0xb8,0x5c,0x53,0xaf,0x01,0x12,0xc0,0xc0,0x01,0x1c,0xbd,0x5d,0x75,0x3c,0x39,0xfe,0x89,0xfe,0x8b,0x01,0x2a,0x01,0x2b,0xfe,0xd4,0xfe,0xd3,0x97,0xda,0x8e,0x44,0x01,0x1f,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x04,0xb2,0x05,0xb2,0x00,0x24,0x00,0x0f,0xb6,0x0b,0x1a,0x12,0x12,0x91,0x00,0x04,0x00,0x3f, 0xed,0x3f,0x33,0x30,0x31,0x01,0x32,0x16,0x16,0x12,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x10,0x21,0x22,0x02,0x11,0x14,0x1e,0x02,0x17,0x23,0x2e,0x03,0x35,0x34,0x12,0x36,0x36,0x02,0xa7,0x7c,0xc3,0x86,0x46,0x1e,0x31,0x3e,0x20,0xc9,0x2b,0x49,0x34,0x1e,0xfe,0x9c,0xb4,0xb8,0x1e,0x34,0x49,0x2b,0xc9,0x20,0x3e,0x31,0x1e, 0x4b,0x8e,0xcb,0x05,0xb2,0x5e,0xbc,0xfe,0xe5,0xbd,0x80,0xd2,0xab,0x8a,0x39,0x3a,0x9c,0xb6,0xc9,0x67,0x02,0x60,0xfe,0xd4,0xfe,0xd6,0x6b,0xcd,0xb8,0x9c,0x3a,0x39,0x8a,0xab,0xd2,0x80,0xbd,0x01,0x1b,0xbc,0x5e,0x00,0x00,0x01,0x00,0x6e,0xff,0xe8,0x04,0x93,0x05,0xb2,0x00,0x3a,0x00,0x1e,0x40,0x0f,0x36,0x23,0x91,0x0e,0x20,0x20, 0x05,0x2b,0x91,0x2c,0x04,0x16,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0xce,0xed,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x23,0x35,0x32,0x1e,0x02, 0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x04,0x93,0x5a,0x94,0xbf,0x66,0x75,0xc3,0x8c,0x4e,0x0e,0x0f,0xb8,0x12,0x14,0x36,0x60,0x83,0x4c,0x64,0x88,0x52,0x23,0x2a,0x56,0x83,0x59,0xd4,0xce,0x52,0x6b,0x3f,0x1a,0x7b,0x83,0x63,0x9f,0x70,0x3c,0x21,0x40,0x5e,0x3d,0x45,0x78,0x58,0x33,0x01,0xb2,0x75,0xad,0x71,0x37,0x3f,0x72,0x9f,0x60, 0x26,0x52,0x2c,0x26,0x4f,0x2e,0x44,0x69,0x48,0x26,0x35,0x57,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x24,0x3f,0x53,0x2f,0x60,0x6b,0x97,0x31,0x5c,0x81,0x50,0x3b,0x65,0x4e,0x34,0x0a,0x09,0x3c,0x61,0x82,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x08,0x12,0x05,0xb3,0x00,0x5c,0x00,0x3d,0x40,0x21,0x48,0x3e,0x0e,0x0a,0x07,0x91,0x57,0x0b, 0x57,0x3e,0x2e,0x57,0x57,0x2e,0x3e,0x03,0x00,0x39,0x91,0x24,0x04,0x21,0x1b,0x42,0x91,0x1e,0x04,0x4d,0x91,0x18,0x04,0x00,0x12,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x32,0x32,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x33,0x10,0xed,0x32,0x39,0x11,0x33,0x30,0x31,0x21,0x2e,0x05,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x37,0x2e,0x03, 0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x16,0x04,0x04,0x16, 0x17,0x05,0xf6,0x0c,0x50,0x7a,0x9e,0xb3,0xc4,0x63,0x7e,0xf0,0x68,0x3c,0x93,0x55,0x66,0x8e,0x58,0x28,0x2b,0x59,0x88,0x5c,0x6d,0x9a,0x2f,0x27,0x9a,0x67,0x65,0x9d,0x26,0x32,0x93,0x66,0x54,0x8b,0x62,0x36,0x11,0x1b,0x20,0x10,0xc4,0x1c,0x2a,0x1c,0x0e,0x20,0x36,0x48,0x29,0x73,0x64,0xa8,0x63,0x73,0x39,0x4f,0x31,0x15,0xa8,0x64, 0x73,0x2c,0x49,0x35,0x1d,0x43,0x6f,0x8e,0x4b,0xc7,0x01,0x59,0x01,0x0b,0xb0,0x1f,0x1c,0x38,0x31,0x2a,0x1e,0x11,0x1f,0x22,0x9c,0x11,0x16,0x05,0x33,0x85,0x9c,0xb0,0x5f,0x62,0xb2,0x87,0x50,0x5b,0x65,0x65,0x5b,0x61,0x5f,0x66,0x5a,0x3e,0x7c,0xbb,0x7c,0x42,0x73,0x61,0x50,0x20,0x26,0x5b,0x64,0x6b,0x35,0x62,0x85,0x52,0x23,0xac, 0xae,0x88,0x88,0xae,0xac,0x2b,0x57,0x81,0x57,0x88,0x88,0xae,0xac,0x26,0x53,0x84,0x5f,0x77,0xb9,0x8e,0x67,0x23,0x0f,0x39,0x5c,0x80,0x55,0x00,0x00,0x02,0x00,0x82,0xff,0xe8,0x04,0x74,0x05,0xb2,0x00,0x2a,0x00,0x3a,0x00,0x1e,0x40,0x0f,0x14,0x36,0x91,0x1f,0x0f,0x0f,0x05,0x1a,0x91,0x25,0x04,0x2e,0x91,0x05,0x13,0x00,0x3f,0xed, 0x3f,0xed,0x12,0x39,0x2f,0xce,0xed,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x04,0x74,0x47,0x82,0xb7, 0x6f,0x7a,0xc0,0x84,0x45,0x47,0x81,0xb5,0x6e,0x31,0x62,0x5c,0x50,0x20,0x2e,0x52,0x72,0x44,0x42,0x6f,0x4f,0x2c,0xb0,0x4b,0x81,0xae,0x62,0x62,0xae,0x82,0x4c,0xfc,0xbe,0xa2,0xa5,0xaf,0xa4,0x2f,0x57,0x7e,0x4f,0x4e,0x7a,0x54,0x2b,0x01,0xfc,0x7f,0xc6,0x88,0x47,0x48,0x8c,0xcc,0x84,0x7d,0xbc,0x7e,0x3f,0x0f,0x23,0x38,0x29,0x92, 0x45,0x69,0x47,0x25,0x1b,0x34,0x50,0x34,0x58,0x88,0x5b,0x2f,0x32,0x63,0x92,0x61,0xfd,0xdc,0xc7,0xc1,0xc0,0xc4,0x60,0x89,0x58,0x29,0x28,0x57,0x87,0x00,0x00,0x02,0x00,0xa0,0xff,0xe8,0x04,0x92,0x05,0xb2,0x00,0x30,0x00,0x40,0x00,0x2b,0x40,0x16,0x21,0x2b,0x91,0x18,0x26,0x91,0x1d,0x1d,0x18,0x00,0x36,0x91,0x05,0x05,0x0f,0x20, 0x18,0x04,0x3e,0x91,0x0f,0x13,0x00,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0xed,0x39,0x11,0x33,0x2f,0xed,0x10,0xed,0x32,0x30,0x31,0x01,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x37,0x15,0x0e,0x03,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15, 0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x01,0x42,0x21,0x53,0x5d,0x63,0x31,0x6e,0xb5,0x81,0x47,0x45,0x84,0xc0,0x7a,0x6f,0xb7,0x82,0x47,0xa3,0xac,0x2b,0x63,0x5f,0x55,0x1e,0x2a,0x74,0x38,0x17,0x36,0x38,0x36,0x18,0x2e,0x62,0x5e,0x56,0x22,0x2e,0x41,0x28,0x13,0x02,0xa6,0x2d,0x56,0x7c,0x4e,0x4f, 0x80,0x5a,0x30,0xaa,0xaf,0xa5,0xa8,0x03,0x84,0x29,0x38,0x22,0x0f,0x42,0x82,0xbf,0x7d,0x84,0xcf,0x90,0x4b,0x4a,0x8c,0xc9,0x7f,0x02,0x5a,0xa9,0xa9,0x16,0x1a,0x16,0x21,0x23,0xaa,0x0c,0x12,0x0c,0x06,0x16,0x1a,0x16,0x10,0x28,0x42,0x33,0xfd,0xa1,0x60,0x8b,0x5a,0x2b,0x2d,0x5b,0x8c,0x60,0xc4,0xca,0xcb,0x00,0x00,0x01,0x00,0x82, 0x00,0x00,0x06,0xf8,0x05,0xb4,0x00,0x3e,0x00,0x20,0x40,0x10,0x2a,0x25,0x0c,0x0c,0x2f,0x1c,0x3a,0x12,0x05,0x91,0x2f,0x04,0x12,0x91,0x25,0x04,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x33,0x12,0x39,0x2f,0x12,0x39,0x30,0x31,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e, 0x02,0x17,0x23,0x2e,0x03,0x35,0x10,0x12,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x16,0x16,0x12,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x06,0x48,0x21,0x46,0x6c,0x4a,0x3a,0x67,0x4e,0x2d,0xa4,0x2d,0x4e,0x67,0x3a,0x4a,0x6c,0x46,0x21,0x1e,0x34,0x49,0x2b,0xc9,0x20,0x3e,0x31,0x1e,0xee,0xe2,0x36,0x6e,0x62,0x4f,0x16,0x13, 0x4f,0x68,0x78,0x3d,0x69,0xa5,0x72,0x3c,0x1e,0x31,0x3e,0x20,0xc9,0x2b,0x49,0x34,0x1e,0x02,0xbc,0x91,0xe2,0x9c,0x52,0x46,0x86,0xc4,0x7e,0x6e,0x6e,0x7e,0xc4,0x86,0x46,0x4e,0x98,0xde,0x91,0x73,0xd0,0xb5,0x96,0x3a,0x39,0x8a,0xac,0xd2,0x80,0x01,0x77,0x01,0x7c,0x23,0x4a,0x76,0x52,0x52,0x75,0x4b,0x23,0x61,0xbf,0xfe,0xe3,0xbb, 0x81,0xd0,0xa9,0x89,0x39,0x3a,0x96,0xb2,0xcb,0x00,0x00,0x01,0x00,0x6e,0xff,0xe8,0x04,0x93,0x05,0x9a,0x00,0x43,0x00,0x1f,0x40,0x0f,0x3b,0x01,0x0f,0x36,0x91,0x21,0x33,0x33,0x01,0x29,0x91,0x19,0x13,0x01,0x03,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xce,0xed,0x39,0x11,0x39,0x30,0x31,0x01,0x33,0x1e,0x07,0x15,0x14,0x0e,0x02,0x07, 0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x06,0x01,0x12,0xbe,0x04,0x3a,0x5a,0x71,0x75,0x6f,0x57,0x35,0x24,0x41,0x5d,0x39,0x43,0x76,0x59,0x33,0x5a,0x94,0xbf,0x66,0x75,0xc3, 0x8c,0x4e,0x1e,0xb7,0x12,0x13,0x34,0x5f,0x83,0x4e,0x64,0x88,0x52,0x23,0x2a,0x56,0x83,0x59,0xd4,0xce,0x4f,0x6d,0x44,0x1e,0x36,0x58,0x71,0x78,0x74,0x5e,0x3e,0x05,0x9a,0x23,0x2a,0x1b,0x11,0x16,0x21,0x38,0x56,0x41,0x2e,0x50,0x40,0x2c,0x09,0x08,0x3c,0x61,0x83,0x4e,0x75,0xad,0x71,0x37,0x3f,0x72,0x9f,0x60,0x4d,0x57,0x22,0x5a, 0x27,0x44,0x69,0x48,0x26,0x35,0x57,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x1e,0x2e,0x38,0x1a,0x28,0x2f,0x1c,0x12,0x15,0x20,0x39,0x5a,0x00,0x01,0x00,0x64,0xff,0xe8,0x04,0xc3,0x05,0xb2,0x00,0x42,0x00,0x35,0x40,0x1e,0x3e,0x1a,0x92,0x00,0x0e,0x00,0x0e,0x00,0x20,0xb0,0x30,0xc0,0x30,0xd0,0x30,0x03,0x30,0x13,0x91,0x08,0x08,0x21, 0x38,0x91,0x27,0x13,0x21,0x04,0x20,0x03,0x00,0x3f,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0xce,0x5d,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x30,0x31,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x33,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x37,0x32,0x3e,0x02,0x37,0x33,0x07,0x11,0x14,0x0e,0x02,0x23, 0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x0e,0x03,0x02,0xf1,0x14,0x13,0x2a,0x53,0x7c,0x52,0x3f,0x81,0x68,0x41,0xaa,0x20,0x33,0x3f,0x1f,0x52,0x5d,0x2a,0x31,0x37,0x5e,0x9c,0x86,0x76,0x37,0x4c,0x01,0x4a,0x8b,0xca,0x80,0x75,0xc1,0x8b,0x4c,0x0f,0x10,0xb6,0x0f,0x16, 0x30,0x5e,0x88,0x59,0x57,0x85,0x5a,0x2f,0x18,0x44,0x4e,0x55,0x04,0x7c,0x23,0x4a,0x25,0x39,0x6a,0x52,0x31,0x21,0x4b,0x78,0x58,0x2f,0x3f,0x27,0x11,0x4d,0x51,0x2b,0x43,0x1c,0x83,0x10,0x27,0x43,0x33,0x02,0xfc,0x2a,0x71,0xb7,0x83,0x47,0x44,0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20,0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a,0x82,0x53, 0x02,0xe8,0x0e,0x18,0x14,0x0c,0x00,0x01,0x00,0x82,0x00,0x00,0x05,0xd0,0x05,0x9a,0x00,0x54,0x00,0x44,0x40,0x14,0x17,0x45,0x91,0x1e,0x3e,0x1b,0x1b,0x38,0x91,0x23,0x80,0x23,0x90,0x23,0xa0,0x23,0xe0,0x23,0x04,0x23,0xb8,0xff,0xc0,0x40,0x11,0x09,0x0d,0x48,0x3e,0x23,0x3e,0x23,0x0d,0x4f,0x2d,0x12,0x12,0x91,0x07,0x07,0x0d,0x03, 0x00,0x3f,0x33,0x2f,0xed,0x3f,0x33,0x12,0x39,0x39,0x2f,0x2f,0x2b,0x5d,0x10,0xed,0x33,0x2f,0x12,0x39,0xed,0x39,0x30,0x31,0x13,0x34,0x3e,0x04,0x37,0x3e,0x03,0x37,0x33,0x0e,0x03,0x07,0x0e,0x03,0x07,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x34,0x2e,0x02, 0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x23,0x2e,0x03,0x82,0x3f,0x6a,0x8d,0x9b,0xa0,0x49,0x55,0x6c,0x42,0x24,0x0d,0xb5,0x10,0x49,0x77,0xa8,0x6f,0x4d,0x8b,0x72,0x58,0x1a,0x05,0x22,0x4f,0x28,0x6a,0x88,0x1b,0x0e,0x3d,0x51,0x5f,0x2f,0x54,0x8b,0x63,0x37,0x1d,0x2f, 0x3c,0x1f,0xc2,0x23,0x45,0x36,0x21,0x22,0x39,0x4b,0x29,0x3b,0x53,0x33,0x17,0xa2,0x14,0x32,0x54,0x40,0x2f,0x4f,0x39,0x20,0x23,0x37,0x44,0x21,0xc2,0x1f,0x3c,0x2f,0x1d,0x02,0x26,0xab,0xf2,0xa4,0x62,0x38,0x18,0x09,0x0a,0x13,0x1a,0x25,0x1c,0x42,0x58,0x3c,0x27,0x10,0x0b,0x11,0x20,0x3b,0x34,0x1d,0x1a,0x7c,0x85,0x45,0x61,0x3d, 0x1d,0x3e,0x7d,0xbb,0x7c,0x66,0xa3,0x85,0x6b,0x2d,0x29,0x6b,0x88,0xa6,0x64,0x62,0x85,0x52,0x23,0x37,0x60,0x83,0x4c,0x30,0x30,0x4d,0x83,0x60,0x36,0x29,0x56,0x83,0x5a,0x64,0xa6,0x88,0x6b,0x29,0x2d,0x6d,0x87,0xa2,0x00,0x01,0x00,0xa0,0xff,0xe8,0x04,0xac,0x05,0x9a,0x00,0x27,0x00,0x18,0x40,0x0b,0x23,0x15,0x1f,0x1f,0x05,0x0c, 0x03,0x10,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x39,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x04,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x04,0xac,0x46,0x83,0xbb,0x75,0x80,0xc6,0x87,0x46,0xa2,0xb2,0xad,0x58,0x85, 0x58,0x2c,0x13,0x1e,0x21,0x1e,0x13,0x15,0x1b,0xb1,0x15,0x22,0x29,0x31,0x29,0x01,0x98,0x5a,0x9d,0x75,0x44,0x47,0x83,0xb7,0x71,0x03,0xc0,0xfc,0x42,0xa6,0xb8,0x2a,0x4b,0x68,0x3d,0x3a,0x5e,0x4e,0x43,0x40,0x40,0x24,0x22,0x4c,0x2d,0x20,0x46,0x32,0x2c,0x5a,0x6c,0x86,0x00,0x02,0x00,0x6e,0xff,0xe8,0x05,0xba,0x05,0xb2,0x00,0x5a, 0x00,0x66,0x00,0x3e,0xb6,0x3d,0x2d,0x64,0x54,0x64,0x01,0x64,0xb8,0xff,0xe0,0x40,0x1a,0x10,0x15,0x48,0x64,0x9f,0x13,0x01,0x13,0x13,0x35,0x1e,0x1b,0x92,0x23,0x23,0x49,0x55,0x0f,0x05,0x91,0x49,0x13,0x5e,0x92,0x35,0x04,0x00,0x3f,0xed,0x3f,0xed,0x3f,0x12,0x39,0x2f,0xed,0x33,0x12,0x39,0x2f,0x5d,0x33,0x2b,0x5d,0x12,0x39,0x39, 0x30,0x31,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x04,0x35,0x34,0x2e,0x04,0x27,0x0e,0x03,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x16,0x16,0x17,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x1e,0x05,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x04,0x35,0x34,0x3e, 0x02,0x37,0x33,0x0e,0x03,0x01,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x36,0x36,0x01,0x1d,0x57,0x8e,0xb4,0x5d,0x3a,0x78,0x70,0x62,0x49,0x2a,0x20,0x38,0x4a,0x56,0x5b,0x2d,0x19,0x2b,0x21,0x13,0x31,0x36,0x1d,0x38,0x11,0x23,0x39,0x18,0x52,0x92,0x38,0x5c,0x41,0x24,0x17,0x26,0x33,0x1c,0x3a,0x48,0x28,0x46,0x5c,0x35,0x31, 0x5a,0x46,0x2a,0x43,0x30,0x30,0x66,0x61,0x56,0x40,0x26,0x71,0xbc,0xf6,0x84,0x52,0xa4,0x97,0x81,0x60,0x37,0x21,0x3a,0x4f,0x2d,0xd7,0x35,0x5c,0x46,0x28,0x02,0xbf,0x33,0x2a,0x31,0x31,0x36,0x2d,0x27,0x35,0x02,0x1c,0x6e,0x9c,0x64,0x2f,0x11,0x25,0x3b,0x54,0x70,0x47,0x3c,0x5f,0x4c,0x3d,0x34,0x2e,0x17,0x15,0x27,0x25,0x24,0x12, 0x26,0x32,0x1a,0x16,0x11,0x2d,0x16,0x6d,0x22,0x3b,0x52,0x30,0x27,0x44,0x3b,0x34,0x17,0x2a,0x70,0x51,0x31,0x52,0x3b,0x21,0x21,0x3b,0x52,0x31,0x3c,0x67,0x2d,0x17,0x32,0x3d,0x4b,0x5f,0x77,0x4a,0x93,0xd2,0x86,0x3f,0x1c,0x39,0x59,0x7a,0x9c,0x61,0x46,0x89,0x7f,0x74,0x31,0x2f,0x6f,0x7b,0x86,0x02,0x72,0x23,0x2d,0x2f,0x21,0x2c, 0x41,0x1c,0x20,0x42,0x00,0x01,0x00,0x0a,0xff,0xe8,0x06,0x23,0x05,0xb8,0x00,0x54,0x00,0x30,0x40,0x19,0x10,0x91,0x0d,0x1e,0x07,0x07,0x19,0x4e,0x35,0x4e,0x35,0x4e,0x21,0x3d,0x91,0x2c,0x13,0x48,0x91,0x21,0x04,0x00,0x91,0x19,0x04,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x12,0x39,0x2f,0x39,0x39,0xed, 0x30,0x31,0x01,0x22,0x0e,0x04,0x23,0x22,0x2e,0x02,0x35,0x33,0x14,0x16,0x33,0x32,0x3e,0x06,0x33,0x32,0x1e,0x02,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x15, 0x23,0x35,0x34,0x2e,0x02,0x02,0x76,0x32,0x39,0x27,0x22,0x36,0x58,0x49,0x32,0x53,0x3b,0x21,0x97,0x30,0x1d,0x1e,0x2b,0x20,0x1c,0x20,0x29,0x3b,0x51,0x39,0x38,0x5a,0x42,0x2b,0x08,0x1d,0x9b,0x74,0x54,0x88,0x60,0x33,0x4a,0x8b,0xca,0x80,0x75,0xbf,0x87,0x49,0x0f,0x10,0xb6,0x0f,0x16,0x2d,0x5a,0x86,0x59,0x57,0x85,0x5a,0x2f,0x20, 0x36,0x48,0x29,0x3b,0x52,0x33,0x17,0xa8,0x13,0x2d,0x49,0x05,0x21,0x2f,0x45,0x51,0x45,0x2e,0x23,0x3f,0x55,0x32,0x2a,0x2a,0x1b,0x2c,0x39,0x3a,0x39,0x2c,0x1b,0x26,0x44,0x5f,0x38,0x80,0x7f,0x3e,0x7d,0xbb,0x7c,0xfe,0x16,0x71,0xb7,0x83,0x47,0x44,0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20,0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a,0x82, 0x53,0x01,0xe1,0x64,0x89,0x52,0x24,0x37,0x60,0x83,0x4c,0x30,0x30,0x49,0x82,0x63,0x39,0x00,0x00,0x02,0x00,0x55,0xff,0xe8,0x06,0xd5,0x05,0xb2,0x00,0x56,0x00,0x66,0x00,0x31,0x40,0x1a,0x64,0x91,0x04,0x2b,0x47,0x19,0x91,0x16,0x2b,0x16,0x2b,0x16,0x3d,0x0c,0x91,0x52,0x13,0x38,0x21,0x91,0x3d,0x04,0x5c,0x91,0x35,0x04,0x00,0x3f, 0xed,0x3f,0xed,0x39,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x39,0x10,0xce,0xed,0x30,0x31,0x01,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x07,0x06,0x06,0x07,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e, 0x02,0x33,0x32,0x16,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x13,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0x02,0x59,0x03,0x02,0xb0,0x03,0x02,0x3f,0x6c,0x92,0x53,0x69,0x96,0x60,0x2d,0x25,0x4f,0x79,0x54,0x5e,0x58,0x51,0x6c, 0x41,0x1b,0x82,0x82,0x61,0xaf,0x53,0x1d,0x3a,0x6c,0x9b,0x62,0x61,0xa1,0x73,0x40,0x42,0x75,0xa0,0x5e,0x64,0x9d,0x36,0x37,0x6e,0x6f,0x6f,0x39,0x5d,0x9c,0x71,0x40,0x20,0x3e,0x5a,0x3a,0x3a,0x69,0x4f,0x2e,0x62,0xa2,0xce,0x6c,0x81,0xd4,0x97,0x52,0xa4,0x1c,0x3b,0x5c,0x40,0x41,0x61,0x42,0x21,0x83,0x82,0x80,0x73,0x01,0x8e,0x0f, 0x1f,0x11,0x11,0x1e,0x0f,0x44,0x66,0x44,0x22,0x35,0x56,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x24,0x3f,0x53,0x2f,0x5f,0x6d,0x01,0x02,0x30,0x3d,0x54,0x69,0x6c,0xa6,0x71,0x3b,0x3c,0x72,0xa7,0x6b,0x6a,0xa6,0x72,0x3c,0x3e,0x3c,0x26,0x31,0x1c,0x0a,0x31,0x5c,0x81,0x50,0x3b,0x65,0x4e,0x33,0x09,0x04,0x07,0x3b,0x61,0x83,0x4e,0x75, 0xad,0x71,0x37,0x3c,0x6e,0x9c,0x02,0xc1,0x47,0x6f,0x4c,0x27,0x2c,0x4e,0x6c,0x41,0x90,0x99,0x98,0x00,0x00,0x01,0x00,0x5a,0xff,0xe8,0x04,0x7d,0x05,0x9a,0x00,0x31,0x00,0x23,0x40,0x11,0x24,0x0a,0x24,0x0a,0x1b,0x13,0x05,0x91,0x10,0x10,0x15,0x2c,0x91,0x1b,0x13,0x15,0x03,0x00,0x3f,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x12,0x39, 0x39,0x2f,0x2f,0x30,0x31,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x11,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x03,0xd5,0x2e,0x52,0x72,0x44,0x42,0x6f,0x4f,0x2c,0xa6,0x48,0x7e,0xaa,0x62,0x59, 0x9c,0x41,0xa8,0x4a,0x8b,0xca,0x80,0x75,0xbf,0x87,0x49,0x0f,0x10,0xb6,0x0f,0x16,0x2d,0x5a,0x86,0x59,0x57,0x85,0x5a,0x2f,0x02,0xed,0x43,0x68,0x47,0x24,0x1b,0x34,0x50,0x34,0x58,0x88,0x5b,0x2f,0x28,0x29,0x01,0x51,0xfc,0x40,0x71,0xb7,0x83,0x47,0x44,0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20,0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a, 0x82,0x53,0x00,0x01,0x00,0x82,0x00,0x00,0x05,0xb6,0x05,0xb3,0x00,0x4d,0x00,0x33,0x40,0x1b,0x08,0x05,0x92,0x4a,0x09,0x0c,0x19,0x37,0x1c,0x0c,0x26,0x37,0x37,0x26,0x0c,0x03,0x00,0x31,0x91,0x1c,0x04,0x3e,0x91,0x16,0x04,0x00,0x12,0x00,0x3f,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x11,0x12,0x39,0x11,0x33,0x33,0xed, 0x32,0x30,0x31,0x21,0x2e,0x03,0x27,0x22,0x06,0x07,0x35,0x36,0x36,0x37,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x04,0x17,0x16,0x16, 0x17,0x04,0x49,0x19,0x65,0x8a,0xa7,0x6e,0x46,0xbb,0x59,0x41,0x98,0x51,0x68,0x90,0x5a,0x28,0x2b,0x59,0x88,0x5c,0x6d,0x92,0x2f,0x27,0x99,0x67,0x54,0x8b,0x62,0x36,0x11,0x1b,0x20,0x10,0xc4,0x1c,0x2a,0x1c,0x0e,0x20,0x36,0x49,0x2a,0x39,0x4f,0x30,0x15,0xa8,0x16,0x31,0x4f,0x39,0x2c,0x49,0x35,0x1d,0x2b,0x4a,0x62,0x6d,0x74,0x36, 0xb8,0xf1,0x2f,0x2e,0x4f,0x3a,0x23,0x04,0x1e,0x23,0x9c,0x15,0x19,0x02,0x2d,0x83,0x9e,0xb3,0x5e,0x62,0xb2,0x87,0x50,0x5b,0x65,0x65,0x5b,0x3e,0x7c,0xbb,0x7c,0x42,0x73,0x61,0x50,0x20,0x26,0x5b,0x64,0x6b,0x35,0x62,0x85,0x52,0x23,0x2b,0x57,0x81,0x57,0x88,0x88,0x57,0x81,0x57,0x2b,0x26,0x53,0x84,0x5f,0x5a,0x98,0x7e,0x65,0x4f, 0x39,0x13,0x2d,0xa7,0x7d,0x00,0x00,0x01,0x00,0x6e,0xff,0xe8,0x04,0x91,0x05,0x9a,0x00,0x3d,0x00,0x1d,0x40,0x0e,0x00,0x1a,0x91,0x30,0x05,0x05,0x21,0x38,0x91,0x27,0x13,0x10,0x21,0x03,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xce,0xed,0x39,0x30,0x31,0x01,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x37,0x33,0x0e,0x03, 0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x35,0x33,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x03,0xe9,0x20,0x54,0x5e,0x63,0x30,0x5a,0xa8,0x80,0x4d,0x08,0x0d,0x13,0x0b,0xb6,0x0d,0x15,0x0f,0x08,0x39,0x57,0x68,0x30,0x49,0x7f,0x5e,0x36,0xa8, 0x4a,0x8b,0xca,0x80,0x75,0xbf,0x87,0x49,0x0f,0x10,0xb6,0x0f,0x16,0x2d,0x5a,0x86,0x59,0x57,0x85,0x5a,0x2f,0x03,0x5f,0x2a,0x3a,0x26,0x11,0x34,0x6d,0xaa,0x77,0x21,0x49,0x48,0x45,0x1d,0x1a,0x45,0x4b,0x4c,0x22,0x5f,0x74,0x3f,0x15,0x33,0x57,0x75,0x42,0xfe,0xfc,0x40,0x71,0xb7,0x83,0x47,0x44,0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20, 0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a,0x82,0x53,0x00,0x02,0x00,0x32,0xff,0xe8,0x04,0xf3,0x05,0xb3,0x00,0x13,0x00,0x57,0x00,0x32,0x40,0x1c,0x38,0x33,0x2b,0x20,0x0f,0x91,0x57,0x48,0x00,0x52,0x10,0x52,0x02,0x52,0x52,0x3d,0x05,0x91,0x48,0x13,0x19,0x92,0x3d,0x04,0x26,0x92,0x33,0x04,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12, 0x39,0x2f,0x5d,0x12,0x39,0xed,0xce,0x32,0x11,0x39,0x30,0x31,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x01,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x15,0x14,0x17,0x23,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32, 0x1e,0x02,0x15,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x01,0xb1,0x39,0x5d,0x75,0x3c,0x3c,0x79,0x61,0x3d,0x39,0x5e,0x7a,0x42,0x42,0x76,0x5a,0x35,0x02,0x9a,0x18,0x2d,0x44,0x2b,0x36,0x48,0x2c,0x13,0x9e,0x1c,0x33,0x46,0x2a,0x4e,0x4f,0x15,0xb5,0x0e,0x32,0x5a,0x7b,0x49,0x2a,0x4e, 0x45,0x38,0x13,0x11,0x36,0x43,0x4d,0x29,0x5a,0x87,0x5b,0x2d,0x52,0x89,0xb3,0x61,0x69,0xbc,0x8c,0x52,0x59,0x8e,0xae,0x56,0x31,0x62,0x5b,0x51,0x20,0x01,0xde,0x56,0x83,0x59,0x2e,0x2d,0x58,0x82,0x55,0x55,0x83,0x59,0x2e,0x2b,0x56,0x83,0x01,0xc8,0x50,0x71,0x48,0x22,0x1e,0x33,0x45,0x27,0x2b,0x2b,0x2d,0x46,0x30,0x1a,0x62,0x54, 0x30,0x42,0x36,0x32,0x52,0x7b,0x53,0x2a,0x0f,0x23,0x38,0x29,0x28,0x38,0x24,0x10,0x32,0x6d,0xac,0x7a,0xfd,0xec,0x72,0xb9,0x81,0x46,0x46,0x84,0xbc,0x76,0x78,0xb8,0x7d,0x3f,0x11,0x24,0x37,0x27,0x00,0x02,0x00,0xa0,0x00,0x00,0x04,0x94,0x05,0xb1,0x00,0x0d,0x00,0x3f,0x00,0x22,0x40,0x11,0x06,0x91,0x3a,0x3a,0x3b,0x23,0x91,0x0e, 0x0e,0x2a,0x00,0x92,0x30,0x04,0x19,0x2a,0x12,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x2f,0xed,0x39,0x33,0x2f,0xed,0x30,0x31,0x01,0x22,0x0e,0x02,0x15,0x15,0x3e,0x03,0x35,0x34,0x26,0x13,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x23,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x11,0x23,0x11,0x34,0x3e,0x02,0x33,0x32, 0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x15,0x3e,0x03,0x01,0xde,0x23,0x39,0x28,0x16,0x4e,0x6e,0x45,0x1f,0x3f,0x9a,0x63,0xab,0x7f,0x48,0x11,0x1b,0x20,0x10,0xc4,0x1c,0x2a,0x1c,0x0e,0x37,0x56,0x6b,0x33,0x48,0x87,0x69,0x3f,0xa2,0x33,0x57,0x73,0x41,0x44,0x6f,0x50,0x2b,0x2e,0x6b,0xb0,0x81,0x21,0x5b,0x66,0x6b,0x05,0x21,0x18,0x2a, 0x3c,0x24,0x83,0x0a,0x25,0x31,0x3b,0x20,0x30,0x3a,0xfe,0x36,0x35,0x71,0xb0,0x7b,0x42,0x73,0x61,0x50,0x20,0x26,0x5b,0x64,0x6b,0x35,0x5f,0x7b,0x47,0x1c,0x30,0x57,0x7d,0x4c,0xfe,0x8e,0x04,0x74,0x4c,0x77,0x50,0x2a,0x20,0x3f,0x5b,0x3b,0x34,0x66,0x5a,0x48,0x16,0xc5,0x2d,0x43,0x2c,0x16,0x00,0x01,0x00,0x82,0xff,0xe8,0x05,0x1d, 0x05,0x9a,0x00,0x42,0x00,0x20,0x40,0x10,0x14,0x3d,0x91,0x00,0x07,0x3c,0x3c,0x1e,0x28,0x03,0x31,0x91,0x1e,0x13,0x07,0x03,0x00,0x3f,0x3f,0xed,0x3f,0x12,0x39,0x2f,0x12,0x39,0xed,0x39,0x30,0x31,0x01,0x34,0x2e,0x04,0x35,0x33,0x14,0x1e,0x04,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x26,0x02,0x35, 0x34,0x3e,0x02,0x37,0x33,0x06,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x04,0x28,0x3a,0x57,0x65,0x57,0x3a,0xb1,0x39,0x55,0x64,0x55,0x39,0x24,0x41,0x5c,0x37,0x45,0x77,0x56,0x31,0x5f,0x9f,0xd2,0x73,0x87,0xdd,0x9e,0x56,0x1f,0x34,0x42,0x23,0xc7,0x6d,0x68,0x3c,0x72, 0xa4,0x68,0x69,0x97,0x60,0x2d,0x2c,0x58,0x85,0x59,0x7f,0x79,0x46,0x6a,0x48,0x25,0x04,0x1a,0x31,0x32,0x20,0x1c,0x35,0x5c,0x50,0x2c,0x2d,0x1d,0x1c,0x36,0x5e,0x51,0x30,0x54,0x42,0x2d,0x08,0x09,0x3c,0x61,0x82,0x4e,0x75,0xad,0x71,0x37,0x5e,0xbc,0x01,0x1b,0xbd,0x7b,0xd3,0xaf,0x8d,0x36,0x94,0xfe,0xa4,0xd6,0x94,0xe0,0x96,0x4b, 0x35,0x56,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x20,0x32,0x3e,0x00,0x02,0x00,0x6e,0xff,0xe8,0x04,0x60,0x05,0x9a,0x00,0x16,0x00,0x24,0x00,0x16,0x40,0x0b,0x15,0x03,0x22,0x91,0x14,0x0f,0x10,0x1a,0x91,0x05,0x13,0x00,0x3f,0xed,0x3f,0x33,0xed,0x3f,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32, 0x1e,0x02,0x17,0x11,0x33,0x01,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x04,0x60,0x47,0x82,0xb7,0x6f,0x7a,0xc0,0x84,0x45,0x47,0x81,0xb5,0x6e,0x31,0x63,0x5b,0x51,0x1f,0xa8,0xfc,0xbe,0xa2,0xa5,0xae,0xa5,0x2f,0x57,0x7e,0x4f,0x9d,0xaa,0x02,0x06,0x7f,0xc9,0x8c,0x4a,0x4b,0x90,0xcf,0x84,0x7d,0xc0,0x82,0x43, 0x10,0x24,0x39,0x28,0x02,0x17,0xfc,0x76,0xc7,0xcb,0xcb,0xc3,0x60,0x8c,0x5d,0x2d,0xb3,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x04,0xff,0x05,0xb3,0x00,0x41,0x00,0x56,0x00,0x33,0x40,0x1c,0x3f,0x53,0x91,0x17,0x12,0x30,0x00,0x00,0x00,0x10,0x00,0x02,0x23,0x00,0x23,0x00,0x09,0x29,0x92,0x1c,0x04,0x36,0x92,0x12,0x04,0x47,0x09,0x12, 0x00,0x3f,0x33,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xce,0x11,0x39,0xed,0x39,0x30,0x31,0x01,0x32,0x1e,0x02,0x15,0x14,0x07,0x01,0x23,0x01,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x07,0x23,0x36,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x15,0x23,0x35, 0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x17,0x17,0x36,0x36,0x13,0x1e,0x03,0x17,0x33,0x3e,0x03,0x37,0x37,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x02,0xa4,0x58,0x8c,0x62,0x33,0x2d,0xfe,0xfe,0x8e,0xfe,0x17,0x11,0x16,0x32,0x5a,0x7e,0x4b,0x29,0x4d,0x43,0x36,0x11,0x13,0x38,0x45,0x4e,0x2a,0x49,0x7c,0x5a,0x33,0x0e, 0xb7,0x15,0x4f,0x4e,0x2a,0x46,0x33,0x1c,0x9e,0x13,0x2c,0x48,0x36,0x22,0x3b,0x2b,0x19,0x0c,0x0c,0x39,0x4e,0xa7,0x33,0x05,0x10,0x10,0x0d,0x03,0x02,0x03,0x0e,0x11,0x11,0x05,0x72,0x18,0x67,0x72,0x4b,0x7e,0x37,0x03,0xd5,0x28,0x4c,0x6d,0x45,0x59,0x5a,0xfe,0x04,0x03,0xca,0x23,0x5b,0x32,0x51,0x76,0x4d,0x25,0x10,0x24,0x38,0x28, 0x29,0x38,0x23,0x0f,0x2a,0x53,0x7b,0x52,0x32,0x36,0x42,0x30,0x54,0x62,0x1a,0x30,0x46,0x2d,0x2b,0x2b,0x27,0x45,0x33,0x1e,0x18,0x2e,0x43,0x2b,0x1d,0x36,0x17,0x72,0x1d,0x20,0xfd,0x79,0x0b,0x20,0x25,0x25,0x0f,0x0f,0x25,0x25,0x21,0x0b,0xe1,0x2e,0x3a,0x53,0x53,0x1c,0x19,0x00,0x00,0x02,0x00,0x32,0xff,0xe8,0x05,0x26,0x05,0x9a, 0x00,0x41,0x00,0x53,0x00,0x3f,0x40,0x25,0x02,0x41,0x09,0x4f,0x2d,0x10,0x06,0x05,0x0d,0x0d,0x4c,0x91,0x1f,0x32,0x05,0x05,0x42,0x91,0x3c,0x6f,0x32,0x7f,0x32,0xdf,0x32,0x03,0x32,0x3c,0x32,0x3c,0x01,0x27,0x91,0x16,0x13,0x01,0x03,0x00,0x3f,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x33,0x2f,0x10,0xce,0xed,0x33,0x2f, 0x12,0x17,0x39,0x30,0x31,0x01,0x33,0x11,0x36,0x36,0x37,0x15,0x06,0x06,0x07,0x16,0x16,0x17,0x15,0x26,0x26,0x27,0x11,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x11,0x0e,0x03,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x17,0x25,0x22, 0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x37,0x2e,0x03,0x03,0xad,0xa8,0x33,0x66,0x38,0x39,0x69,0x30,0x30,0x69,0x39,0x38,0x66,0x33,0x4a,0x8b,0xca,0x80,0x7e,0xc1,0x82,0x43,0x0f,0x10,0xb6,0x0f,0x16,0x2b,0x58,0x87,0x5c,0x57,0x85,0x5a,0x2f,0x2d,0x5a,0x5f,0x66,0x37,0x43,0x70,0x52,0x2e,0x2e,0x52,0x70,0x43,0x37,0x66,0x5f, 0x5a,0x2d,0xfe,0x88,0x17,0x32,0x2a,0x1b,0x1b,0x2a,0x32,0x17,0x66,0xbf,0x55,0x2a,0x5b,0x5f,0x63,0x05,0x9a,0xfe,0xac,0x2a,0x4d,0x21,0xa0,0x1d,0x46,0x26,0x26,0x45,0x1d,0xa0,0x20,0x4e,0x29,0xfe,0xb6,0x71,0xb7,0x83,0x47,0x44,0x75,0x9d,0x5a,0x27,0x53,0x2a,0x20,0x53,0x30,0x3d,0x68,0x4b,0x2b,0x2f,0x5a,0x82,0x53,0x01,0x53,0x22, 0x3b,0x2c,0x19,0x2b,0x4f,0x6d,0x42,0x42,0x6d,0x4e,0x2b,0x19,0x2c,0x3b,0x22,0x0f,0x0f,0x23,0x39,0x2a,0x2a,0x3a,0x23,0x0f,0x55,0x40,0x20,0x37,0x28,0x17,0x00,0x02,0x00,0xa0,0xff,0xe8,0x04,0x92,0x05,0x9a,0x00,0x16,0x00,0x24,0x00,0x16,0x40,0x0b,0x22,0x91,0x11,0x13,0x1a,0x91,0x02,0x07,0x10,0x01,0x03,0x00,0x3f,0x3f,0x33,0xed, 0x3f,0xed,0x30,0x31,0x13,0x33,0x11,0x3e,0x03,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x25,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x16,0x33,0x32,0x36,0xa0,0xa8,0x1f,0x51,0x5b,0x63,0x31,0x6e,0xb5,0x81,0x47,0x45,0x84,0xc0,0x7a,0x6f,0xb7,0x82,0x47,0x03,0x42,0xaa,0x9d,0x4f,0x7e,0x57,0x2f,0xa5,0xae, 0xa5,0xa2,0x05,0x9a,0xfd,0xe9,0x28,0x39,0x24,0x10,0x43,0x82,0xc0,0x7d,0x84,0xcf,0x90,0x4b,0x4a,0x8c,0xc9,0x7f,0x0a,0xbf,0xb3,0x2d,0x5d,0x8c,0x60,0xc3,0xcb,0xcb,0x00,0x01,0x00,0x50,0xff,0xe8,0x05,0xea,0x05,0xb2,0x00,0x5b,0x00,0x34,0x40,0x1d,0x14,0x4f,0x21,0x4f,0x21,0x4f,0x29,0x48,0x91,0x57,0x13,0x5b,0x44,0x15,0x2d,0x04, 0x08,0x34,0x91,0x3b,0x04,0x19,0x92,0x29,0x04,0x0e,0x92,0x08,0x13,0x00,0x3f,0xed,0x3f,0xed,0x3f,0xed,0x12,0x17,0x39,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x12,0x39,0x30,0x31,0x01,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x35,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x01,0x01,0x26,0x26,0x27,0x22,0x06,0x06,0x15,0x14, 0x16,0x17,0x23,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x16,0x17,0x01,0x01,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x35,0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x06,0x07,0x01,0x01,0x16,0x16,0x37,0x36,0x36,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x27,0x01,0x01,0xd9,0x19,0x1d,0x24,0x49, 0x6e,0x4a,0x20,0x48,0x1f,0x3c,0x4b,0x39,0x39,0x3b,0x3d,0x01,0xc9,0xfe,0xb5,0x0f,0x21,0x12,0x09,0x1a,0x16,0x1c,0x17,0xa4,0x11,0x15,0x25,0x3d,0x4e,0x2a,0x48,0x6a,0x2a,0x01,0x32,0x01,0xc4,0x23,0x1b,0x29,0x1e,0x35,0x51,0x2c,0x2b,0x66,0x28,0x3d,0x5a,0x3b,0x1d,0x3e,0x3e,0xfe,0x21,0x01,0x40,0x0f,0x1f,0x15,0x20,0x18,0x1c,0x17, 0xae,0x11,0x15,0x26,0x3f,0x50,0x2a,0x48,0x6f,0x2a,0xfe,0xd9,0x01,0x7c,0x24,0x54,0x28,0x2f,0x58,0x44,0x29,0x0d,0x0f,0xb5,0x47,0x3f,0x2e,0x30,0x61,0x26,0x01,0x45,0x02,0x1e,0x18,0x0f,0x01,0x08,0x1f,0x1d,0x26,0x5b,0x2c,0x2b,0x50,0x2c,0x37,0x52,0x37,0x1b,0x3f,0x45,0xfe,0x10,0x01,0x42,0x19,0x34,0x14,0x1a,0x22,0x1e,0x17,0xa4, 0x11,0x15,0x22,0x3a,0x4f,0x2d,0x3c,0x6d,0x2c,0xfe,0xad,0xfd,0xfa,0x18,0x12,0x01,0x04,0x24,0x1d,0x26,0x55,0x2c,0x2b,0x50,0x2c,0x37,0x54,0x38,0x1d,0x3f,0x45,0x01,0xe3,0x00,0x00,0x01,0x00,0x50,0xff,0xe8,0x04,0x46,0x05,0x9a,0x00,0x52,0x00,0x2e,0x40,0x19,0x31,0x16,0x91,0x13,0x39,0x0d,0x91,0x0a,0x5f,0x0a,0x01,0x13,0x4b,0x0a, 0x0a,0x4b,0x13,0x03,0x22,0x00,0x91,0x43,0x13,0x22,0x03,0x00,0x3f,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x10,0xed,0x39,0x10,0xed,0x39,0x30,0x31,0x25,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x2e,0x06,0x35,0x33,0x14,0x1e,0x06,0x15,0x14, 0x0e,0x02,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x02,0x58,0x4a,0x76,0x52,0x2b,0x21,0x3b,0x51,0x2f,0x5e,0x5e,0x67,0x75,0x6b,0x71,0x5e,0x5e,0x73,0x69,0x2a,0x46,0x58,0x5d,0x58,0x46,0x2a,0xb1,0x2a,0x46,0x58,0x5d,0x58,0x46, 0x2a,0x17,0x31,0x4c,0x35,0x65,0x63,0x1a,0x32,0x4b,0x31,0x35,0x4c,0x30,0x17,0x3f,0x7c,0xbb,0x7b,0x6f,0xbd,0x8a,0x4e,0x1e,0xb7,0x12,0x13,0x33,0x5c,0x7e,0x7e,0x13,0x2a,0x41,0x2e,0x21,0x36,0x25,0x15,0x96,0x3b,0x3d,0x3f,0x31,0x96,0x3d,0x3b,0x1e,0x24,0x16,0x0e,0x13,0x1d,0x33,0x4f,0x3b,0x1b,0x22,0x18,0x11,0x14,0x1d,0x2e,0x44, 0x32,0x27,0x49,0x3c,0x29,0x07,0x14,0x5c,0x4d,0x26,0x41,0x32,0x21,0x06,0x09,0x2e,0x3f,0x4d,0x28,0x47,0x71,0x50,0x2b,0x3f,0x72,0x9f,0x60,0x4d,0x57,0x22,0x5a,0x27,0x44,0x69,0x48,0x26,0x00,0x01,0x00,0x82,0xff,0xe8,0x04,0xcc,0x05,0x9a,0x00,0x57,0x00,0x2c,0x40,0x17,0x20,0x4c,0x91,0x49,0x18,0x55,0x91,0x52,0x5f,0x49,0x01,0x49, 0x52,0x49,0x52,0x09,0x3f,0x91,0x2a,0x13,0x35,0x09,0x03,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x10,0xed,0x39,0x10,0xed,0x39,0x30,0x31,0x01,0x34,0x2e,0x06,0x35,0x33,0x14,0x1e,0x06,0x15,0x14,0x0e,0x02,0x07,0x16,0x16,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x26,0x26,0x02,0x35,0x34, 0x3e,0x02,0x37,0x33,0x0e,0x03,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x04,0x1b,0x1f,0x33,0x41,0x45,0x41,0x33,0x1f,0xb1,0x1f,0x33,0x41,0x45,0x41,0x33,0x1f,0x17,0x31,0x4c,0x35,0x65,0x63,0x1a,0x32,0x4b,0x31,0x35,0x4c,0x30,0x17, 0x3f,0x7c,0xbb,0x7b,0x87,0xdd,0x9e,0x56,0x1e,0x33,0x43,0x24,0xc9,0x38,0x50,0x33,0x17,0x3b,0x70,0xa2,0x68,0x47,0x73,0x50,0x2b,0x21,0x3b,0x51,0x2f,0x5e,0x5e,0x67,0x75,0x6b,0x71,0x5e,0x5e,0x73,0x69,0x04,0x47,0x1e,0x25,0x18,0x11,0x14,0x1e,0x32,0x4b,0x38,0x1b,0x22,0x18,0x11,0x14,0x1d,0x2e,0x44,0x32,0x27,0x49,0x3c,0x29,0x07, 0x14,0x5c,0x4d,0x26,0x41,0x32,0x21,0x06,0x09,0x2e,0x3f,0x4d,0x28,0x47,0x71,0x50,0x2b,0x5e,0xbc,0x01,0x1b,0xbd,0x7c,0xd2,0xaf,0x8d,0x36,0x4a,0xa0,0xb0,0xc1,0x6b,0x94,0xe0,0x96,0x4b,0x13,0x29,0x41,0x2e,0x21,0x36,0x25,0x15,0x96,0x3b,0x3d,0x3f,0x31,0x96,0x3d,0x00,0x00,0x02,0x00,0x64,0xff,0xe8,0x05,0xe4,0x05,0xb2,0x00,0x29, 0x00,0x3b,0x00,0x26,0x40,0x14,0x2f,0x91,0x1f,0x04,0x37,0xee,0x08,0x08,0x10,0x15,0x91,0x0f,0x0a,0x13,0x00,0x27,0x91,0x01,0x06,0x13,0x00,0x3f,0x33,0xed,0x32,0x3f,0x33,0xed,0x32,0x39,0x10,0xed,0x3f,0xed,0x30,0x31,0x25,0x15,0x0e,0x03,0x23,0x22,0x27,0x06,0x23,0x22,0x2e,0x02,0x27,0x35,0x1e,0x03,0x17,0x2e,0x03,0x35,0x34,0x12, 0x36,0x36,0x33,0x32,0x1e,0x02,0x15,0x14,0x02,0x07,0x36,0x36,0x03,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x12,0x17,0x3e,0x03,0x05,0xe4,0x35,0x64,0x6d,0x7c,0x4c,0x82,0x72,0x6b,0x74,0x56,0x83,0x6f,0x63,0x34,0x2f,0x5a,0x5f,0x67,0x3c,0x5c,0x83,0x56,0x28,0x5d,0xaf,0xfa,0x9e,0x92,0xec,0xa7,0x5b,0xb9,0xba,0x72,0xc9,0x78, 0x40,0x7b,0xb1,0x70,0x6e,0xb4,0x80,0x46,0xf7,0xe9,0x75,0xb4,0x7b,0x40,0xd8,0xb0,0x10,0x18,0x10,0x08,0x15,0x15,0x08,0x10,0x18,0x10,0xb5,0x12,0x1e,0x17,0x10,0x03,0x2d,0x82,0xa0,0xbc,0x68,0xa6,0x01,0x04,0xb4,0x5e,0x5d,0xae,0xf8,0x9c,0xe2,0xfe,0xab,0x5d,0x04,0x2f,0x02,0x54,0x85,0xc8,0x85,0x42,0x49,0x8b,0xc8,0x7e,0xf3,0xfe, 0xc7,0x38,0x1b,0x6c,0x9d,0xcb,0x00,0x01,0x00,0x64,0xff,0xe8,0x04,0x89,0x05,0xbb,0x00,0x34,0x00,0x26,0x40,0x13,0x0c,0x0a,0x91,0x1b,0x2d,0x1b,0x2d,0x15,0x00,0x91,0x25,0x13,0x10,0x91,0x15,0x15,0x18,0x13,0x04,0x00,0x3f,0x33,0x33,0x2f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0xed,0x39,0x30,0x31,0x25,0x32,0x3e,0x02,0x35,0x34, 0x2e,0x02,0x23,0x23,0x35,0x01,0x23,0x06,0x23,0x22,0x27,0x37,0x16,0x33,0x32,0x36,0x37,0x15,0x01,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x02,0x78,0x64,0x8a,0x54,0x25,0x2c,0x58,0x85,0x59,0xc5,0x01,0x64,0x03,0x77,0x76,0xaa,0xb7,0x2b,0x8d,0xce,0x67,0xff,0x81, 0xfe,0x76,0x03,0x8b,0xb9,0x6d,0x2d,0x5a,0x94,0xbf,0x66,0x75,0xc3,0x8c,0x4e,0x1e,0xb7,0x12,0x13,0x34,0x5f,0x83,0x7f,0x35,0x56,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x4b,0x01,0xdb,0x18,0x41,0x97,0x40,0x21,0x20,0x3f,0xfd,0xf0,0x02,0x07,0x53,0x7c,0x97,0x4b,0x75,0xad,0x71,0x37,0x3f,0x72,0x9f,0x60,0x4d,0x57,0x22,0x5a,0x27,0x44,0x69, 0x48,0x25,0x00,0x01,0x00,0x64,0xff,0xe8,0x04,0x89,0x05,0x9a,0x00,0x44,0x00,0x2e,0x40,0x1a,0x3d,0x91,0x08,0x0f,0x36,0x91,0x33,0x00,0x33,0x10,0x33,0x02,0x08,0x33,0x21,0x21,0x33,0x08,0x03,0x00,0x29,0x91,0x19,0x13,0x00,0x03,0x00,0x3f,0x3f,0xed,0x12,0x17,0x39,0x2f,0x2f,0x2f,0x5d,0x10,0xed,0x39,0x10,0xed,0x30,0x31,0x01,0x33, 0x06,0x15,0x14,0x1e,0x02,0x33,0x21,0x15,0x14,0x0e,0x02,0x07,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x37,0x33,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23,0x23,0x35,0x33,0x32,0x3e,0x02,0x35,0x35,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x01,0x17,0xaf,0x09,0x1f,0x3d,0x5a,0x3b, 0x01,0x91,0x24,0x41,0x5d,0x39,0x43,0x76,0x59,0x33,0x5a,0x94,0xbf,0x66,0x75,0xc3,0x8c,0x4e,0x1e,0xb7,0x12,0x13,0x34,0x5f,0x83,0x4e,0x64,0x88,0x52,0x23,0x2a,0x56,0x83,0x59,0x70,0x6a,0x4f,0x6d,0x45,0x1f,0xfe,0x58,0x93,0x69,0x3b,0x06,0x05,0x9a,0x24,0x1b,0x23,0x29,0x15,0x05,0xda,0x2e,0x50,0x40,0x2c,0x09,0x08,0x3c,0x61,0x83, 0x4e,0x75,0xad,0x71,0x37,0x3f,0x72,0x9f,0x60,0x4d,0x57,0x22,0x5a,0x27,0x44,0x69,0x48,0x26,0x35,0x57,0x6e,0x39,0x3e,0x6a,0x4e,0x2d,0x97,0x1e,0x2e,0x38,0x1a,0x55,0x17,0x35,0x57,0x41,0x14,0x2c,0x00,0x03,0x00,0x6e,0xff,0xe8,0x04,0x29,0x05,0xb2,0x00,0x29,0x00,0x38,0x00,0x47,0x00,0x35,0x40,0x1c,0x24,0x2a,0x91,0x13,0x27,0x13, 0x01,0x39,0x91,0x12,0x28,0x12,0x2f,0x13,0x01,0x13,0x12,0x13,0x12,0x07,0x2e,0x91,0x1e,0x04,0x44,0x91,0x07,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x5d,0x11,0x33,0x10,0xed,0x32,0x11,0x33,0x10,0xed,0x32,0x30,0x31,0x01,0x23,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x23,0x22, 0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x15,0x33,0x15,0x23,0x15,0x33,0x01,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x13,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x04,0x29,0xad,0x35,0x63,0x8e,0x5a,0x54,0x91,0x6c,0x3d,0x3e,0x6f,0x9a,0x5c,0xc9,0xc9,0x5c,0x9a,0x6f,0x3e, 0x3d,0x6a,0x92,0x55,0x5a,0x8e,0x63,0x35,0xad,0xad,0xad,0xfe,0xb1,0x73,0x6b,0x2f,0x53,0x3e,0x24,0x25,0x42,0x5c,0x36,0xc9,0xc9,0x36,0x5c,0x42,0x25,0x24,0x3e,0x53,0x2f,0x68,0x76,0x01,0xe6,0x94,0x5a,0x88,0x5b,0x2d,0x29,0x52,0x7a,0x52,0x51,0x7c,0x55,0x2b,0xa2,0x2b,0x55,0x7c,0x51,0x52,0x7a,0x52,0x29,0x2e,0x5a,0x88,0x5a,0x94, 0x96,0xa2,0x01,0x38,0x94,0x69,0x6c,0x13,0x2a,0x44,0x31,0x2e,0x44,0x2e,0x17,0xfe,0x32,0x17,0x2e,0x45,0x2d,0x31,0x44,0x2a,0x13,0x6b,0x6a,0x00,0x00,0x03,0x00,0x6e,0xff,0xf1,0x05,0xd9,0x05,0xa7,0x00,0x1d,0x00,0x2a,0x00,0x37,0x00,0x2d,0x40,0x17,0x37,0x91,0x04,0x04,0x20,0x91,0x1d,0x2d,0x92,0x0e,0x0e,0x2a,0x92,0x13,0x1d,0x13, 0x1d,0x13,0x01,0x10,0x03,0x01,0x12,0x00,0x3f,0x3f,0x12,0x39,0x39,0x2f,0x2f,0x10,0xed,0x33,0x2f,0xed,0x10,0xed,0x33,0x2f,0xed,0x30,0x31,0x25,0x15,0x23,0x35,0x23,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x33,0x35,0x33,0x15,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x23,0x03,0x11,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x23, 0x03,0x11,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x03,0x78,0xa8,0x2b,0x7c,0xd0,0x97,0x54,0x54,0x97,0xd1,0x7d,0x29,0xa8,0x2a,0x7d,0xd0,0x96,0x54,0x55,0x97,0xcf,0x7a,0x2c,0x2c,0x5a,0x91,0x64,0x36,0x37,0x65,0x91,0x5a,0xd2,0x29,0x59,0x91,0x67,0x38,0x35,0x64,0x92,0x5c,0xba,0xc9,0xc9,0x54,0x96,0xd1,0x7d,0x7b,0xc9,0x8f, 0x4d,0x95,0x95,0x4f,0x8f,0xc8,0x7a,0x7e,0xd1,0x96,0x53,0x03,0xca,0xfc,0xcc,0x39,0x6b,0x9a,0x62,0x5b,0x95,0x6a,0x3a,0xfc,0xcc,0x03,0x34,0x39,0x69,0x96,0x5d,0x62,0x9b,0x6a,0x38,0x00,0x00,0x01,0x00,0x76,0xff,0xe8,0x04,0xc1,0x05,0xb2,0x00,0x3a,0x00,0x1b,0x40,0x0d,0x29,0x0a,0x1a,0x31,0x2b,0x91,0x36,0x13,0x15,0x0f,0x91,0x1a, 0x04,0x00,0x3f,0xed,0xcd,0x3f,0xed,0xcd,0x12,0x39,0x39,0x30,0x31,0x13,0x34,0x3e,0x02,0x37,0x3e,0x03,0x35,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x23,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x07,0x0e,0x03,0x15,0x10,0x21,0x32,0x3e,0x02,0x35,0x33,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x76,0x4c,0x86,0xb8,0x6c, 0x49,0x81,0x62,0x39,0x28,0x4c,0x70,0x49,0x4c,0x76,0x50,0x29,0xaa,0x54,0x88,0xae,0x59,0x71,0xb0,0x79,0x3f,0x4c,0x85,0xb6,0x6a,0x46,0x82,0x65,0x3d,0x01,0x74,0x44,0x89,0x6f,0x46,0xab,0x60,0x9d,0xc7,0x67,0x6b,0xc5,0x96,0x5a,0x01,0x85,0x6f,0x92,0x5f,0x37,0x13,0x0c,0x25,0x3c,0x5b,0x43,0x33,0x52,0x3b,0x20,0x24,0x42,0x5c,0x38, 0x6f,0x99,0x5f,0x2b,0x35,0x63,0x8b,0x55,0x66,0x8d,0x60,0x3a,0x14,0x0d,0x24,0x3e,0x5e,0x47,0xfe,0xfa,0x1d,0x41,0x6a,0x4e,0x74,0xa3,0x67,0x2f,0x2a,0x60,0x9e,0x00,0x00,0x01,0x00,0xa0,0xff,0xe8,0x04,0xc3,0x05,0x9a,0x00,0x3d,0x00,0x1d,0x40,0x0e,0x3d,0x23,0x91,0x0e,0x38,0x38,0x16,0x2d,0x1d,0x03,0x05,0x91,0x16,0x13,0x00,0x3f, 0xed,0x3f,0x33,0x12,0x39,0x2f,0xce,0xed,0x39,0x30,0x31,0x01,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x11,0x33,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x27,0x33,0x1e,0x03,0x15,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x27,0x01,0x48, 0x2f,0x5a,0x85,0x57,0x58,0x86,0x5a,0x2e,0x16,0x0f,0xb6,0x10,0x0f,0x4a,0x87,0xbe,0x75,0x80,0xca,0x8b,0x4a,0xa8,0x36,0x5e,0x7f,0x49,0x30,0x68,0x57,0x39,0x08,0x0f,0x15,0x0d,0xb6,0x0b,0x13,0x0d,0x08,0x4d,0x80,0xa8,0x5a,0x30,0x63,0x5e,0x54,0x20,0x01,0xdc,0x53,0x82,0x5a,0x2f,0x2b,0x4b,0x68,0x3d,0x30,0x53,0x20,0x2a,0x53,0x27, 0x5a,0x9d,0x75,0x44,0x47,0x83,0xb7,0x71,0x03,0xc0,0xfe,0x42,0x75,0x57,0x33,0x19,0x44,0x78,0x5f,0x22,0x48,0x47,0x40,0x1a,0x1d,0x45,0x48,0x49,0x21,0x77,0xaa,0x6d,0x34,0x11,0x26,0x3a,0x2a,0x00,0x00,0x02,0x00,0x78,0xff,0xe8,0x04,0xae,0x05,0xae,0x00,0x2f,0x00,0x3f,0x00,0x26,0x40,0x15,0x1e,0x03,0x35,0x91,0x11,0x00,0x40,0x09, 0x0d,0x48,0x00,0x00,0x16,0x3d,0x91,0x26,0x04,0x0b,0x91,0x16,0x13,0x00,0x3f,0xed,0x3f,0xed,0x12,0x39,0x2f,0x2b,0xce,0xed,0x39,0x39,0x30,0x31,0x01,0x22,0x26,0x27,0x06,0x06,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x33,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e, 0x02,0x15,0x14,0x0e,0x02,0x01,0x14,0x1e,0x02,0x33,0x32,0x36,0x35,0x34,0x2e,0x02,0x23,0x22,0x06,0x02,0x87,0x26,0x46,0x21,0x07,0x08,0x1a,0x2f,0x40,0x27,0x2f,0x47,0x2f,0x17,0xaf,0x35,0x60,0x86,0x50,0x51,0x82,0x5b,0x32,0x14,0x0c,0x73,0x70,0x4f,0x90,0xc9,0x7a,0x7a,0xc5,0x8a,0x4b,0x43,0x88,0xcf,0xfe,0x14,0x33,0x5b,0x7f,0x4d, 0xb8,0xc4,0x32,0x5f,0x89,0x58,0xb0,0xb4,0x01,0x7f,0x07,0x07,0x17,0x35,0x22,0x29,0x3d,0x28,0x13,0x17,0x27,0x36,0x1f,0x43,0x6e,0x4e,0x2a,0x2a,0x50,0x70,0x47,0x39,0x58,0x1f,0x45,0xed,0x97,0x7e,0xc8,0x8c,0x4a,0x4b,0x8a,0xc1,0x76,0x72,0xc8,0x94,0x55,0x02,0x19,0x60,0x91,0x60,0x31,0xcb,0xbb,0x59,0x8d,0x61,0x34,0xca,0x00,0x01, 0x00,0x82,0xff,0xd5,0x05,0x14,0x05,0xb2,0x00,0x24,0x00,0x22,0x40,0x10,0x03,0x22,0x00,0x24,0x12,0x24,0x12,0x24,0x01,0x18,0x91,0x0d,0x04,0x02,0x01,0x13,0x00,0x3f,0x33,0x3f,0xed,0x12,0x39,0x39,0x2f,0x2f,0x11,0x33,0x39,0x39,0x30,0x31,0x25,0x01,0x35,0x25,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e, 0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x33,0x25,0x04,0xd6,0xfc,0x21,0x01,0x73,0x71,0xb5,0x7e,0x44,0x59,0x9d,0xd8,0x7f,0x83,0xd6,0x99,0x53,0xaa,0x36,0x68,0x9a,0x63,0x65,0x9c,0x6b,0x37,0x4d,0x94,0xd5,0x89,0x01,0x01,0x6a,0xe5,0xfe,0xf0,0x9d,0x6b,0x20,0x75,0xa2,0xcd,0x78,0x84,0xdd,0x9f,0x59,0x50,0x96,0xd5,0x85, 0x5d,0x9d,0x70,0x3f,0x48,0x7e,0xaa,0x61,0x68,0xb8,0x92,0x65,0x15,0x65,0x00,0x01,0x00,0x62,0xff,0xe8,0x04,0xad,0x05,0xb2,0x00,0x3a,0x00,0x1b,0x40,0x0d,0x31,0x12,0x05,0x2c,0x91,0x26,0x21,0x04,0x10,0x91,0x0a,0x05,0x13,0x00,0x3f,0xcd,0xed,0x3f,0xcd,0xed,0x12,0x39,0x39,0x30,0x31,0x01,0x14,0x0e,0x02,0x23,0x22,0x2e,0x02,0x35, 0x33,0x14,0x1e,0x02,0x33,0x20,0x11,0x34,0x2e,0x02,0x27,0x2e,0x03,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x23,0x34,0x2e,0x02,0x23,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x17,0x1e,0x03,0x04,0xad,0x5a,0x96,0xc5,0x6b,0x67,0xc7,0x9d,0x60,0xab,0x46,0x6f,0x89,0x44,0x01,0x74,0x3d,0x65,0x82,0x46,0x6a,0xb6,0x85,0x4c,0x42,0x7b, 0xaf,0x6d,0x59,0xad,0x89,0x54,0xaa,0x29,0x50,0x76,0x4c,0x49,0x70,0x4d,0x27,0x39,0x61,0x82,0x49,0x6c,0xb8,0x86,0x4c,0x01,0x85,0x75,0x9e,0x60,0x2a,0x2f,0x67,0xa3,0x74,0x4e,0x6a,0x41,0x1d,0x01,0x06,0x47,0x5e,0x3e,0x24,0x0d,0x14,0x3a,0x60,0x8d,0x66,0x53,0x8b,0x63,0x37,0x2b,0x5f,0x99,0x6f,0x38,0x5c,0x42,0x24,0x20,0x3b,0x52, 0x33,0x43,0x5b,0x3c,0x25,0x0c,0x13,0x37,0x5f,0x92,0x00,0x02,0x00,0x64,0xff,0xe8,0x05,0xe4,0x05,0xb2,0x00,0x29,0x00,0x3b,0x00,0x26,0x40,0x14,0x2f,0x91,0x1e,0x13,0x0f,0x14,0x91,0x0e,0x09,0x04,0x37,0xee,0x07,0x07,0x29,0x26,0x91,0x00,0x05,0x04,0x00,0x3f,0x33,0xed,0x32,0x39,0x10,0xed,0x3f,0x33,0xed,0x32,0x3f,0xed,0x30,0x31, 0x13,0x3e,0x03,0x33,0x32,0x17,0x36,0x33,0x32,0x1e,0x02,0x17,0x15,0x2e,0x03,0x27,0x1e,0x03,0x15,0x14,0x02,0x06,0x06,0x23,0x22,0x2e,0x02,0x35,0x34,0x12,0x37,0x06,0x06,0x07,0x13,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x02,0x27,0x0e,0x03,0x64,0x34,0x65,0x6d,0x7c,0x4c,0x82,0x72,0x6a,0x75,0x55,0x84,0x6f,0x62,0x35,0x2f, 0x5a,0x5f,0x67,0x3c,0x5b,0x84,0x56,0x28,0x5d,0xaf,0xfb,0x9d,0x92,0xec,0xa7,0x5b,0xb9,0xba,0x72,0xc9,0x66,0xde,0x40,0x7b,0xb0,0x71,0x6e,0xb4,0x80,0x46,0xf7,0xe9,0x75,0xb4,0x7b,0x40,0x05,0x72,0x10,0x18,0x10,0x08,0x15,0x15,0x08,0x10,0x18,0x10,0xb5,0x12,0x1e,0x17,0x10,0x03,0x2d,0x82,0xa0,0xbc,0x68,0xa6,0xfe,0xfc,0xb4,0x5e, 0x5d,0xae,0xf8,0x9c,0xe2,0x01,0x55,0x5d,0x04,0x2f,0x26,0xfd,0xd2,0x86,0xc7,0x85,0x42,0x49,0x8b,0xc8,0x7e,0xf3,0x01,0x39,0x38,0x1b,0x6c,0x9d,0xcb,0x00,0x00,0x02,0x00,0x78,0xff,0xe8,0x05,0xbe,0x05,0xb2,0x00,0x13,0x00,0x27,0x00,0x10,0xb7,0x14,0x91,0x0a,0x04,0x1e,0x91,0x00,0x13,0x00,0x3f,0xed,0x3f,0xed,0x30,0x31,0x05,0x22, 0x26,0x26,0x02,0x35,0x34,0x12,0x36,0x24,0x33,0x32,0x16,0x16,0x12,0x15,0x14,0x02,0x06,0x06,0x03,0x22,0x0e,0x02,0x15,0x14,0x1e,0x02,0x33,0x32,0x3e,0x02,0x35,0x34,0x2e,0x02,0x03,0x15,0x98,0xf6,0xb0,0x5f,0x60,0xb4,0x01,0x01,0xa0,0x94,0xf2,0xac,0x5f,0x61,0xb2,0xfb,0x8f,0x72,0xbc,0x87,0x4a,0x48,0x83,0xb8,0x70,0x76,0xbd,0x85, 0x47,0x44,0x81,0xb9,0x18,0x6a,0xc0,0x01,0x0a,0xa0,0xac,0x01,0x18,0xc6,0x6c,0x6a,0xbe,0xfe,0xf5,0xa0,0xaf,0xfe,0xe7,0xc5,0x6a,0x05,0x32,0x56,0x9c,0xd9,0x84,0x83,0xd9,0x9b,0x55,0x4f,0x96,0xda,0x8a,0x8d,0xdd,0x98,0x50,0x00,0x00,0x03,0x00,0xbe,0x02,0x27,0x03,0x98,0x06,0x8f,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x1a,0x40,0x09, 0x0b,0x09,0x09,0x02,0x05,0x07,0x07,0x00,0x02,0xb8,0x01,0x4a,0x00,0x3f,0xcd,0x33,0x2f,0xcd,0x11,0x33,0x2f,0xcd,0x30,0x31,0x01,0x23,0x11,0x33,0x01,0x23,0x11,0x33,0x05,0x23,0x11,0x33,0x01,0x67,0xa9,0xa9,0x02,0x31,0xa9,0xa9,0xfe,0xe8,0xa9,0xa9,0x02,0x27,0x02,0xa6,0xfd,0x5a,0x02,0xa6,0x67,0x02,0x29,0x00,0x00,0x00,0x00,0x01, 0x00,0x00,0xc2,0x66,0x00,0x01,0x20,0x64,0xc0,0x00,0x00,0x0d,0x02,0x58,0x00,0x05,0x00,0x55,0xff,0xcd,0x00,0x05,0x00,0x56,0xff,0xbe,0x00,0x05,0x00,0xe4,0xff,0xbe,0x00,0x05,0x00,0xfb,0xff,0xbe,0x00,0x05,0x01,0x1b,0xff,0xcd,0x00,0x05,0x01,0x1d,0xff,0xcd,0x00,0x05,0x01,0x1f,0xff,0xbe,0x00,0x05,0x01,0x73,0xff,0xcd,0x00,0x05, 0x01,0x75,0xff,0xbe,0x00,0x05,0x01,0xd5,0xff,0x6f,0x00,0x05,0x02,0x2b,0xff,0xbc,0x00,0x05,0x02,0x3e,0xff,0xbe,0x00,0x0a,0x00,0x55,0xff,0xcd,0x00,0x0a,0x00,0x56,0xff,0xbe,0x00,0x0a,0x00,0xe4,0xff,0xbe,0x00,0x0a,0x00,0xfb,0xff,0xbe,0x00,0x0a,0x01,0x1b,0xff,0xcd,0x00,0x0a,0x01,0x1d,0xff,0xcd,0x00,0x0a,0x01,0x1f,0xff,0xbe, 0x00,0x0a,0x01,0x73,0xff,0xcd,0x00,0x0a,0x01,0x75,0xff,0xbe,0x00,0x0a,0x01,0xd5,0xff,0x6f,0x00,0x0a,0x02,0x2b,0xff,0xbc,0x00,0x0a,0x02,0x3e,0xff,0xbe,0x00,0x0b,0x00,0x4d,0x00,0xe9,0x00,0x0b,0x01,0x64,0x00,0xe9,0x00,0x0d,0x00,0x24,0xff,0x5a,0x00,0x0d,0x00,0x2d,0xff,0x66,0x00,0x0d,0x00,0x46,0xff,0x9a,0x00,0x0d,0x00,0x47, 0xff,0x9a,0x00,0x0d,0x00,0x48,0xff,0x9a,0x00,0x0d,0x00,0x4a,0xff,0x9a,0x00,0x0d,0x00,0x52,0xff,0x9a,0x00,0x0d,0x00,0x54,0xff,0x9a,0x00,0x0d,0x00,0xa9,0xff,0x58,0x00,0x0d,0x00,0xf8,0xff,0x9a,0x00,0x0d,0x00,0xfd,0xff,0x9a,0x00,0x0d,0x00,0xff,0xff,0x9a,0x00,0x0d,0x01,0x00,0xff,0x9a,0x00,0x0d,0x01,0x03,0xff,0x5a,0x00,0x0d, 0x01,0x05,0xff,0x5a,0x00,0x0d,0x01,0x08,0xff,0x9a,0x00,0x0d,0x01,0x0b,0xff,0x9a,0x00,0x0d,0x01,0x45,0xff,0x5a,0x00,0x0d,0x01,0x48,0xff,0x9a,0x00,0x0d,0x01,0x52,0xff,0x9a,0x00,0x0d,0x01,0x54,0xff,0x9a,0x00,0x0d,0x01,0x56,0xff,0x9a,0x00,0x0d,0x01,0x63,0xff,0x66,0x00,0x0d,0x01,0x85,0xff,0x5a,0x00,0x0d,0x01,0x87,0xff,0x5a, 0x00,0x0d,0x01,0xa9,0xff,0x58,0x00,0x0d,0x01,0xb0,0xff,0x58,0x00,0x0d,0x01,0xe7,0xff,0x58,0x00,0x0d,0x02,0x0c,0xff,0x98,0x00,0x0d,0x02,0x15,0xff,0x98,0x00,0x0d,0x02,0x18,0xff,0x98,0x00,0x0d,0x02,0x1b,0xff,0x98,0x00,0x0d,0x02,0x27,0xff,0x98,0x00,0x0d,0x02,0x2a,0xff,0x98,0x00,0x0f,0x00,0xb4,0xff,0x31,0x00,0x0f,0x00,0xb5, 0xff,0x31,0x00,0x0f,0x00,0xb6,0xff,0x31,0x00,0x0f,0x00,0xb7,0xff,0x31,0x00,0x10,0x01,0x33,0xff,0xdb,0x00,0x10,0x01,0xd3,0xff,0xe7,0x00,0x10,0x02,0x37,0xff,0xdb,0x00,0x11,0x00,0xb4,0xff,0x31,0x00,0x11,0x00,0xb5,0xff,0x3d,0x00,0x11,0x00,0xb6,0xff,0x31,0x00,0x11,0x00,0xb7,0xff,0x3d,0x00,0x1e,0x02,0x37,0xff,0xdb,0x00,0x22, 0x01,0xcb,0xff,0xe7,0x00,0x22,0x02,0x37,0xff,0xdb,0x00,0x24,0x00,0x0d,0xff,0x7f,0x00,0x24,0x00,0x0f,0x00,0x44,0x00,0x24,0x00,0x1e,0x00,0x44,0x00,0x24,0x00,0x26,0xff,0xe5,0x00,0x24,0x00,0x2a,0xff,0xe5,0x00,0x24,0x00,0x2d,0x00,0x5e,0x00,0x24,0x00,0x32,0xff,0xe5,0x00,0x24,0x00,0x37,0xff,0x6d,0x00,0x24,0x00,0x38,0xff,0xe5, 0x00,0x24,0x00,0x39,0xff,0x8b,0x00,0x24,0x00,0x3a,0xff,0xb6,0x00,0x24,0x00,0x3c,0xff,0x64,0x00,0x24,0x00,0x3d,0x00,0x3b,0x00,0x24,0x00,0x57,0xff,0xe5,0x00,0x24,0x00,0x59,0xff,0xd5,0x00,0x24,0x00,0x5a,0xff,0xe5,0x00,0x24,0x00,0x5c,0xff,0xdb,0x00,0x24,0x00,0x8d,0xff,0x9a,0x00,0x24,0x00,0xb4,0xff,0x66,0x00,0x24,0x00,0xb5, 0xff,0x3f,0x00,0x24,0x00,0xb6,0xff,0x66,0x00,0x24,0x00,0xb7,0xff,0x3f,0x00,0x24,0x00,0xba,0xff,0xc1,0x00,0x24,0x00,0xbb,0xff,0x64,0x00,0x24,0x00,0xe5,0x00,0x3b,0x00,0x24,0x00,0xea,0xff,0x64,0x00,0x24,0x00,0xeb,0xff,0xdb,0x00,0x24,0x00,0xf7,0xff,0xe5,0x00,0x24,0x00,0xfc,0xff,0xe5,0x00,0x24,0x00,0xfe,0xff,0xe5,0x00,0x24, 0x01,0x18,0xff,0xe5,0x00,0x24,0x01,0x20,0xff,0x6d,0x00,0x24,0x01,0x21,0xff,0xe5,0x00,0x24,0x01,0x22,0xff,0x6d,0x00,0x24,0x01,0x23,0xff,0xe5,0x00,0x24,0x01,0x24,0xff,0xe5,0x00,0x24,0x01,0x26,0xff,0xe5,0x00,0x24,0x01,0x28,0x00,0x3b,0x00,0x24,0x01,0x2a,0x00,0x3b,0x00,0x24,0x01,0x47,0xff,0xe5,0x00,0x24,0x01,0x51,0xff,0xe5, 0x00,0x24,0x01,0x53,0xff,0xe5,0x00,0x24,0x01,0x55,0xff,0xe5,0x00,0x24,0x01,0x63,0x00,0x5e,0x00,0x24,0x01,0x6e,0xff,0xe5,0x00,0x24,0x01,0x70,0xff,0xe5,0x00,0x24,0x01,0x76,0xff,0x6d,0x00,0x24,0x01,0x77,0xff,0xe5,0x00,0x24,0x01,0x78,0xff,0xe5,0x00,0x24,0x01,0x7a,0xff,0xe5,0x00,0x24,0x01,0x7c,0xff,0xe5,0x00,0x24,0x01,0x7e, 0xff,0xe5,0x00,0x24,0x01,0x80,0xff,0xb6,0x00,0x24,0x01,0x81,0xff,0xe5,0x00,0x24,0x01,0x82,0xff,0x64,0x00,0x24,0x01,0x83,0xff,0xdb,0x00,0x24,0x01,0x89,0xff,0xe5,0x00,0x24,0x01,0x8c,0xff,0xb6,0x00,0x24,0x01,0x8d,0xff,0xe5,0x00,0x24,0x01,0x8e,0xff,0xb6,0x00,0x24,0x01,0x8f,0xff,0xe5,0x00,0x24,0x01,0x90,0xff,0xb6,0x00,0x24, 0x01,0x91,0xff,0xe5,0x00,0x24,0x01,0x92,0xff,0x64,0x00,0x24,0x01,0x93,0xff,0xdb,0x00,0x25,0x00,0x37,0xff,0xa4,0x00,0x25,0x00,0x3c,0xff,0xbe,0x00,0x25,0x00,0xbb,0xff,0xbe,0x00,0x25,0x00,0xc4,0xff,0xb2,0x00,0x25,0x00,0xc5,0xff,0xb2,0x00,0x25,0x00,0xea,0xff,0xbe,0x00,0x25,0x01,0x20,0xff,0xa4,0x00,0x25,0x01,0x22,0xff,0xa4, 0x00,0x25,0x01,0x76,0xff,0xa4,0x00,0x25,0x01,0x82,0xff,0xbe,0x00,0x25,0x01,0x92,0xff,0xbe,0x00,0x26,0x00,0x22,0x00,0x02,0x00,0x26,0x00,0x26,0xff,0xc9,0x00,0x26,0x00,0x2a,0xff,0xc9,0x00,0x26,0x00,0x32,0xff,0xe5,0x00,0x26,0x00,0x34,0xff,0xc9,0x00,0x26,0x00,0x64,0xff,0xc9,0x00,0x26,0x00,0x67,0xff,0xc9,0x00,0x26,0x00,0x77, 0x00,0x1d,0x00,0x26,0x00,0x92,0xff,0xc9,0x00,0x26,0x00,0xaa,0xff,0xcf,0x00,0x26,0x00,0xaf,0xff,0xc9,0x00,0x26,0x00,0xb0,0xff,0xc9,0x00,0x26,0x00,0xbe,0xff,0xcf,0x00,0x26,0x00,0xd0,0xff,0xc9,0x00,0x26,0x00,0xd1,0xff,0xc9,0x00,0x26,0x00,0xd2,0xff,0xc9,0x00,0x26,0x00,0xf7,0xff,0xc9,0x00,0x26,0x00,0xfc,0xff,0xc9,0x00,0x26, 0x00,0xfe,0xff,0xc9,0x00,0x26,0x01,0x18,0xff,0xe5,0x00,0x26,0x01,0x47,0xff,0xc9,0x00,0x26,0x01,0x51,0xff,0xc9,0x00,0x26,0x01,0x53,0xff,0xc9,0x00,0x26,0x01,0x55,0xff,0xc9,0x00,0x26,0x01,0x5c,0x00,0x1d,0x00,0x26,0x01,0x5e,0x00,0x1d,0x00,0x26,0x01,0x60,0x00,0x1d,0x00,0x26,0x01,0x6e,0xff,0xe5,0x00,0x26,0x01,0x70,0xff,0xe5, 0x00,0x26,0x01,0x89,0xff,0xe5,0x00,0x27,0x00,0x0f,0xff,0x7f,0x00,0x27,0x00,0x11,0xff,0x7f,0x00,0x27,0x00,0x24,0xff,0xdf,0x00,0x27,0x00,0x37,0xff,0xa4,0x00,0x27,0x00,0x3b,0xff,0xcb,0x00,0x27,0x00,0x3d,0xff,0xcf,0x00,0x27,0x00,0x62,0xff,0xdf,0x00,0x27,0x00,0x63,0xff,0xdf,0x00,0x27,0x00,0x91,0xff,0xb6,0x00,0x27,0x00,0xac, 0xff,0x7f,0x00,0x27,0x00,0xad,0xff,0xdf,0x00,0x27,0x00,0xae,0xff,0xdf,0x00,0x27,0x00,0xbb,0xff,0xf6,0x00,0x27,0x00,0xc4,0xff,0x8b,0x00,0x27,0x00,0xc5,0xff,0x8b,0x00,0x27,0x00,0xc7,0xff,0xdf,0x00,0x27,0x00,0xc9,0xff,0xdf,0x00,0x27,0x00,0xe5,0xff,0xcf,0x00,0x27,0x01,0x03,0xff,0xdf,0x00,0x27,0x01,0x05,0xff,0xdf,0x00,0x27, 0x01,0x20,0xff,0xa4,0x00,0x27,0x01,0x22,0xff,0xa4,0x00,0x27,0x01,0x28,0xff,0xcf,0x00,0x27,0x01,0x2a,0xff,0xcf,0x00,0x27,0x01,0x45,0xff,0xdf,0x00,0x27,0x01,0x76,0xff,0xa4,0x00,0x27,0x01,0x85,0xff,0xdf,0x00,0x27,0x01,0x87,0xff,0xdf,0x00,0x28,0x00,0x24,0x00,0x0a,0x00,0x28,0x00,0x2d,0x00,0x44,0x00,0x28,0x00,0x37,0x00,0x04, 0x00,0x28,0x00,0x3a,0x00,0x1d,0x00,0x28,0x00,0x3b,0x00,0x08,0x00,0x28,0x00,0x62,0x00,0x0a,0x00,0x28,0x00,0x63,0x00,0x0a,0x00,0x28,0x00,0x77,0x00,0x12,0x00,0x28,0x00,0xad,0x00,0x0a,0x00,0x28,0x00,0xae,0x00,0x0a,0x00,0x28,0x00,0xc7,0x00,0x0a,0x00,0x28,0x00,0xc9,0x00,0x0a,0x00,0x28,0x01,0x03,0x00,0x0a,0x00,0x28,0x01,0x05, 0x00,0x0a,0x00,0x28,0x01,0x20,0x00,0x04,0x00,0x28,0x01,0x22,0x00,0x04,0x00,0x28,0x01,0x45,0x00,0x0a,0x00,0x28,0x01,0x5c,0x00,0x12,0x00,0x28,0x01,0x5e,0x00,0x12,0x00,0x28,0x01,0x60,0x00,0x12,0x00,0x28,0x01,0x63,0x00,0x44,0x00,0x28,0x01,0x76,0x00,0x04,0x00,0x28,0x01,0x80,0x00,0x1d,0x00,0x28,0x01,0x85,0x00,0x0a,0x00,0x28, 0x01,0x87,0x00,0x0a,0x00,0x28,0x01,0x8c,0x00,0x1d,0x00,0x28,0x01,0x8e,0x00,0x1d,0x00,0x28,0x01,0x90,0x00,0x1d,0x00,0x29,0x00,0x0f,0xff,0x66,0x00,0x29,0x00,0x11,0xff,0x66,0x00,0x29,0x00,0x24,0xff,0x7b,0x00,0x29,0x00,0x2d,0xff,0xbe,0x00,0x29,0x00,0x36,0xff,0xe5,0x00,0x29,0x00,0x37,0x00,0x0e,0x00,0x29,0x00,0x44,0xff,0xb4, 0x00,0x29,0x00,0x49,0x00,0x0a,0x00,0x29,0x00,0x62,0xff,0x7b,0x00,0x29,0x00,0x63,0xff,0x7b,0x00,0x29,0x00,0x77,0x00,0x27,0x00,0x29,0x00,0x91,0xff,0x4c,0x00,0x29,0x00,0xac,0xff,0x66,0x00,0x29,0x00,0xad,0xff,0x7b,0x00,0x29,0x00,0xae,0xff,0x7b,0x00,0x29,0x00,0xc4,0xff,0x4a,0x00,0x29,0x00,0xc5,0xff,0x4a,0x00,0x29,0x00,0xc7, 0xff,0x7b,0x00,0x29,0x00,0xc9,0xff,0x7b,0x00,0x29,0x00,0xe3,0xff,0xe5,0x00,0x29,0x00,0xfa,0xff,0xe5,0x00,0x29,0x01,0x03,0xff,0x7b,0x00,0x29,0x01,0x05,0xff,0x7b,0x00,0x29,0x01,0x06,0xff,0xb4,0x00,0x29,0x01,0x1e,0xff,0xe5,0x00,0x29,0x01,0x20,0x00,0x0e,0x00,0x29,0x01,0x22,0x00,0x0e,0x00,0x29,0x01,0x45,0xff,0x7b,0x00,0x29, 0x01,0x5c,0x00,0x27,0x00,0x29,0x01,0x5e,0x00,0x27,0x00,0x29,0x01,0x60,0x00,0x27,0x00,0x29,0x01,0x63,0xff,0xbe,0x00,0x29,0x01,0x74,0xff,0xe5,0x00,0x29,0x01,0x76,0x00,0x0e,0x00,0x29,0x01,0x85,0xff,0x7b,0x00,0x29,0x01,0x87,0xff,0x7b,0x00,0x29,0x01,0x88,0xff,0xb4,0x00,0x29,0x02,0x3d,0xff,0xe5,0x00,0x2a,0x00,0x37,0xff,0xcf, 0x00,0x2a,0x00,0x39,0xff,0xe5,0x00,0x2a,0x00,0x5c,0xff,0xe5,0x00,0x2a,0x00,0xba,0xff,0xe5,0x00,0x2a,0x00,0xeb,0xff,0xe5,0x00,0x2a,0x01,0x20,0xff,0xcf,0x00,0x2a,0x01,0x22,0xff,0xcf,0x00,0x2a,0x01,0x76,0xff,0xcf,0x00,0x2a,0x01,0x83,0xff,0xe5,0x00,0x2a,0x01,0x93,0xff,0xe5,0x00,0x2d,0x00,0x0f,0xff,0x9a,0x00,0x2d,0x00,0x11, 0xff,0x9a,0x00,0x2d,0x00,0x24,0xff,0xdb,0x00,0x2d,0x00,0x2d,0xff,0xbe,0x00,0x2d,0x00,0x44,0xff,0xe5,0x00,0x2d,0x00,0x62,0xff,0xdb,0x00,0x2d,0x00,0x63,0xff,0xdb,0x00,0x2d,0x00,0x69,0xff,0xe5,0x00,0x2d,0x00,0x6a,0xff,0xe5,0x00,0x2d,0x00,0x6b,0xff,0xe5,0x00,0x2d,0x00,0x6c,0xff,0xe5,0x00,0x2d,0x00,0x6d,0xff,0xe5,0x00,0x2d, 0x00,0x6e,0xff,0xe5,0x00,0x2d,0x00,0x91,0xff,0x98,0x00,0x2d,0x00,0xa0,0xff,0xe5,0x00,0x2d,0x00,0xac,0xff,0x9a,0x00,0x2d,0x00,0xad,0xff,0xdb,0x00,0x2d,0x00,0xae,0xff,0xdb,0x00,0x2d,0x00,0xc4,0xff,0x66,0x00,0x2d,0x00,0xc5,0xff,0x9a,0x00,0x2d,0x00,0xc7,0xff,0xdb,0x00,0x2d,0x00,0xc9,0xff,0xdb,0x00,0x2d,0x01,0x03,0xff,0xdb, 0x00,0x2d,0x01,0x04,0xff,0xe5,0x00,0x2d,0x01,0x05,0xff,0xdb,0x00,0x2d,0x01,0x06,0xff,0xe5,0x00,0x2d,0x01,0x45,0xff,0xdb,0x00,0x2d,0x01,0x46,0xff,0xe5,0x00,0x2d,0x01,0x63,0xff,0xbe,0x00,0x2d,0x01,0x85,0xff,0xdb,0x00,0x2d,0x01,0x86,0xff,0xe5,0x00,0x2d,0x01,0x87,0xff,0xdb,0x00,0x2d,0x01,0x88,0xff,0xe5,0x00,0x2e,0x00,0x0f, 0x00,0x27,0x00,0x2e,0x00,0x1e,0x00,0x27,0x00,0x2e,0x00,0x26,0xff,0xa6,0x00,0x2e,0x00,0x2a,0xff,0xa6,0x00,0x2e,0x00,0x2d,0x00,0x5a,0x00,0x2e,0x00,0x32,0xff,0xa6,0x00,0x2e,0x00,0x34,0xff,0xa6,0x00,0x2e,0x00,0x3b,0x00,0x25,0x00,0x2e,0x00,0x3d,0x00,0x27,0x00,0x2e,0x00,0x46,0xff,0xe5,0x00,0x2e,0x00,0x47,0xff,0xe5,0x00,0x2e, 0x00,0x48,0xff,0xe5,0x00,0x2e,0x00,0x4a,0xff,0xe5,0x00,0x2e,0x00,0x52,0xff,0xe5,0x00,0x2e,0x00,0x54,0xff,0xe5,0x00,0x2e,0x00,0x57,0xff,0xd1,0x00,0x2e,0x00,0x59,0xff,0xb6,0x00,0x2e,0x00,0x5a,0xff,0xcb,0x00,0x2e,0x00,0x5c,0xff,0xa4,0x00,0x2e,0x00,0x64,0xff,0x9a,0x00,0x2e,0x00,0x67,0xff,0xa6,0x00,0x2e,0x00,0x6f,0xff,0xe5, 0x00,0x2e,0x00,0x70,0xff,0xe5,0x00,0x2e,0x00,0x71,0xff,0xe5,0x00,0x2e,0x00,0x72,0xff,0xe5,0x00,0x2e,0x00,0x73,0xff,0xe5,0x00,0x2e,0x00,0x74,0xff,0xcf,0x00,0x2e,0x00,0x77,0x00,0x27,0x00,0x2e,0x00,0x79,0xff,0xe5,0x00,0x2e,0x00,0x7a,0xff,0xe5,0x00,0x2e,0x00,0x7b,0xff,0xe5,0x00,0x2e,0x00,0x7c,0xff,0xe5,0x00,0x2e,0x00,0x7d, 0xff,0xe5,0x00,0x2e,0x00,0x92,0xff,0xa6,0x00,0x2e,0x00,0xaf,0xff,0xa6,0x00,0x2e,0x00,0xb0,0xff,0xa6,0x00,0x2e,0x00,0xb1,0xff,0xe5,0x00,0x2e,0x00,0xba,0xff,0xa4,0x00,0x2e,0x00,0xc4,0x00,0x44,0x00,0x2e,0x00,0xc5,0x00,0x44,0x00,0x2e,0x00,0xd0,0xff,0xa6,0x00,0x2e,0x00,0xd1,0xff,0xa6,0x00,0x2e,0x00,0xd2,0xff,0xa6,0x00,0x2e, 0x00,0xe5,0x00,0x27,0x00,0x2e,0x00,0xeb,0xff,0xa4,0x00,0x2e,0x00,0xf7,0xff,0xa6,0x00,0x2e,0x00,0xf8,0xff,0xe5,0x00,0x2e,0x00,0xfc,0xff,0xa6,0x00,0x2e,0x00,0xfd,0xff,0xe5,0x00,0x2e,0x00,0xfe,0xff,0xa6,0x00,0x2e,0x00,0xff,0xff,0xe5,0x00,0x2e,0x01,0x00,0xff,0xe5,0x00,0x2e,0x01,0x08,0xff,0xe5,0x00,0x2e,0x01,0x0b,0xff,0xe5, 0x00,0x2e,0x01,0x0d,0xff,0xe5,0x00,0x2e,0x01,0x18,0xff,0xa6,0x00,0x2e,0x01,0x19,0xff,0xe5,0x00,0x2e,0x01,0x21,0xff,0xd1,0x00,0x2e,0x01,0x23,0xff,0xd1,0x00,0x2e,0x01,0x28,0x00,0x27,0x00,0x2e,0x01,0x2a,0x00,0x27,0x00,0x2e,0x01,0x47,0xff,0xa6,0x00,0x2e,0x01,0x48,0xff,0xe5,0x00,0x2e,0x01,0x4c,0xff,0xe5,0x00,0x2e,0x01,0x4e, 0xff,0xe5,0x00,0x2e,0x01,0x50,0xff,0xe5,0x00,0x2e,0x01,0x51,0xff,0xa6,0x00,0x2e,0x01,0x52,0xff,0xe5,0x00,0x2e,0x01,0x53,0xff,0xa6,0x00,0x2e,0x01,0x54,0xff,0xe5,0x00,0x2e,0x01,0x55,0xff,0xa6,0x00,0x2e,0x01,0x56,0xff,0xe5,0x00,0x2e,0x01,0x5c,0x00,0x27,0x00,0x2e,0x01,0x5e,0x00,0x27,0x00,0x2e,0x01,0x60,0x00,0x27,0x00,0x2e, 0x01,0x63,0x00,0x5a,0x00,0x2e,0x01,0x6e,0xff,0xa6,0x00,0x2e,0x01,0x6f,0xff,0xe5,0x00,0x2e,0x01,0x70,0xff,0xa6,0x00,0x2e,0x01,0x71,0xff,0xe5,0x00,0x2e,0x01,0x77,0xff,0xd1,0x00,0x2e,0x01,0x81,0xff,0xcb,0x00,0x2e,0x01,0x83,0xff,0xa4,0x00,0x2e,0x01,0x89,0xff,0xa6,0x00,0x2e,0x01,0x8a,0xff,0xe5,0x00,0x2e,0x01,0x8d,0xff,0xcb, 0x00,0x2e,0x01,0x8f,0xff,0xcb,0x00,0x2e,0x01,0x91,0xff,0xcb,0x00,0x2e,0x01,0x93,0xff,0xa4,0x00,0x2f,0x00,0x0d,0xff,0x31,0x00,0x2f,0x00,0x22,0xff,0x9a,0x00,0x2f,0x00,0x24,0x00,0x3b,0x00,0x2f,0x00,0x26,0xff,0xbe,0x00,0x2f,0x00,0x2a,0xff,0xbe,0x00,0x2f,0x00,0x2d,0x00,0x64,0x00,0x2f,0x00,0x32,0xff,0xba,0x00,0x2f,0x00,0x34, 0xff,0xba,0x00,0x2f,0x00,0x37,0xff,0x8f,0x00,0x2f,0x00,0x38,0xff,0xe3,0x00,0x2f,0x00,0x39,0xff,0x8b,0x00,0x2f,0x00,0x3a,0xff,0xcf,0x00,0x2f,0x00,0x3c,0xff,0x7f,0x00,0x2f,0x00,0x3d,0x00,0x3b,0x00,0x2f,0x00,0x57,0xff,0xe5,0x00,0x2f,0x00,0x59,0xff,0x9a,0x00,0x2f,0x00,0x5a,0xff,0xbe,0x00,0x2f,0x00,0x5c,0xff,0xb4,0x00,0x2f, 0x00,0x64,0xff,0xbe,0x00,0x2f,0x00,0x67,0xff,0xba,0x00,0x2f,0x00,0x68,0xff,0xe3,0x00,0x2f,0x00,0x8d,0xff,0x9a,0x00,0x2f,0x00,0x92,0xff,0xba,0x00,0x2f,0x00,0xaf,0xff,0xba,0x00,0x2f,0x00,0xb0,0xff,0xba,0x00,0x2f,0x00,0xb4,0xff,0x73,0x00,0x2f,0x00,0xb5,0xff,0x8b,0x00,0x2f,0x00,0xb6,0xff,0x73,0x00,0x2f,0x00,0xb7,0xff,0x7f, 0x00,0x2f,0x00,0xba,0xff,0xb4,0x00,0x2f,0x00,0xbb,0xff,0x9a,0x00,0x2f,0x00,0xc4,0x00,0x44,0x00,0x2f,0x00,0xc5,0x00,0x44,0x00,0x2f,0x00,0xd0,0xff,0xba,0x00,0x2f,0x00,0xd1,0xff,0xba,0x00,0x2f,0x00,0xd2,0xff,0xba,0x00,0x2f,0x00,0xd3,0xff,0xe3,0x00,0x2f,0x00,0xd4,0xff,0xe3,0x00,0x2f,0x00,0xd5,0xff,0xe3,0x00,0x2f,0x00,0xe5, 0x00,0x3b,0x00,0x2f,0x00,0xea,0xff,0x7f,0x00,0x2f,0x00,0xeb,0xff,0xb4,0x00,0x2f,0x00,0xf7,0xff,0xbe,0x00,0x2f,0x00,0xfc,0xff,0xbe,0x00,0x2f,0x00,0xfe,0xff,0xbe,0x00,0x2f,0x01,0x03,0x00,0x3b,0x00,0x2f,0x01,0x05,0x00,0x3b,0x00,0x2f,0x01,0x18,0xff,0xba,0x00,0x2f,0x01,0x20,0xff,0x8f,0x00,0x2f,0x01,0x21,0xff,0xe5,0x00,0x2f, 0x01,0x22,0xff,0x8f,0x00,0x2f,0x01,0x23,0xff,0xe5,0x00,0x2f,0x01,0x24,0xff,0xe3,0x00,0x2f,0x01,0x26,0xff,0xe3,0x00,0x2f,0x01,0x28,0x00,0x3b,0x00,0x2f,0x01,0x2a,0x00,0x3b,0x00,0x2f,0x01,0x45,0x00,0x3b,0x00,0x2f,0x01,0x47,0xff,0xbe,0x00,0x2f,0x01,0x51,0xff,0xbe,0x00,0x2f,0x01,0x53,0xff,0xbe,0x00,0x2f,0x01,0x55,0xff,0xbe, 0x00,0x2f,0x01,0x63,0x00,0x64,0x00,0x2f,0x01,0x6e,0xff,0xba,0x00,0x2f,0x01,0x70,0xff,0xba,0x00,0x2f,0x01,0x76,0xff,0x8f,0x00,0x2f,0x01,0x77,0xff,0xe5,0x00,0x2f,0x01,0x78,0xff,0xe3,0x00,0x2f,0x01,0x7a,0xff,0xe3,0x00,0x2f,0x01,0x7c,0xff,0xe3,0x00,0x2f,0x01,0x7e,0xff,0xe3,0x00,0x2f,0x01,0x80,0xff,0xcf,0x00,0x2f,0x01,0x81, 0xff,0xbe,0x00,0x2f,0x01,0x82,0xff,0x7f,0x00,0x2f,0x01,0x83,0xff,0xb4,0x00,0x2f,0x01,0x85,0x00,0x3b,0x00,0x2f,0x01,0x87,0x00,0x3b,0x00,0x2f,0x01,0x89,0xff,0xba,0x00,0x2f,0x01,0x8c,0xff,0xcf,0x00,0x2f,0x01,0x8d,0xff,0xbe,0x00,0x2f,0x01,0x8e,0xff,0xcf,0x00,0x2f,0x01,0x8f,0xff,0xbe,0x00,0x2f,0x01,0x90,0xff,0xcf,0x00,0x2f, 0x01,0x91,0xff,0xbe,0x00,0x2f,0x01,0x92,0xff,0x7f,0x00,0x2f,0x01,0x93,0xff,0xb4,0x00,0x32,0x00,0x0f,0xff,0xa4,0x00,0x32,0x00,0x11,0xff,0xa4,0x00,0x32,0x00,0x24,0xff,0xe5,0x00,0x32,0x00,0x2d,0xff,0xf6,0x00,0x32,0x00,0x37,0xff,0xa4,0x00,0x32,0x00,0x3b,0xff,0xdb,0x00,0x32,0x00,0x3c,0xff,0xe7,0x00,0x32,0x00,0x3d,0xff,0xcf, 0x00,0x32,0x00,0x62,0xff,0xe5,0x00,0x32,0x00,0x63,0xff,0xe5,0x00,0x32,0x00,0xac,0xff,0xa4,0x00,0x32,0x00,0xad,0xff,0xe5,0x00,0x32,0x00,0xae,0xff,0xe5,0x00,0x32,0x00,0xbb,0xff,0xf6,0x00,0x32,0x00,0xc4,0xff,0x4c,0x00,0x32,0x00,0xc5,0xff,0x98,0x00,0x32,0x00,0xc7,0xff,0xe5,0x00,0x32,0x00,0xc9,0xff,0xe5,0x00,0x32,0x00,0xe5, 0xff,0xcf,0x00,0x32,0x00,0xea,0xff,0xe7,0x00,0x32,0x01,0x03,0xff,0xe5,0x00,0x32,0x01,0x05,0xff,0xe5,0x00,0x32,0x01,0x20,0xff,0xa4,0x00,0x32,0x01,0x22,0xff,0xa4,0x00,0x32,0x01,0x28,0xff,0xcf,0x00,0x32,0x01,0x2a,0xff,0xcf,0x00,0x32,0x01,0x45,0xff,0xe5,0x00,0x32,0x01,0x63,0xff,0xf6,0x00,0x32,0x01,0x76,0xff,0xa4,0x00,0x32, 0x01,0x82,0xff,0xe7,0x00,0x32,0x01,0x85,0xff,0xe5,0x00,0x32,0x01,0x87,0xff,0xe5,0x00,0x32,0x01,0x92,0xff,0xe7,0x00,0x33,0x00,0x0f,0xfe,0xba,0x00,0x33,0x00,0x11,0xfe,0xba,0x00,0x33,0x00,0x24,0xff,0x62,0x00,0x33,0x00,0x2a,0xff,0xf6,0x00,0x33,0x00,0x2d,0xff,0x7f,0x00,0x33,0x00,0x3a,0x00,0x27,0x00,0x33,0x00,0x3b,0xff,0xc3, 0x00,0x33,0x00,0x44,0xff,0xbe,0x00,0x33,0x00,0x46,0xff,0xb4,0x00,0x33,0x00,0x47,0xff,0xb4,0x00,0x33,0x00,0x48,0xff,0xb4,0x00,0x33,0x00,0x4a,0xff,0xb4,0x00,0x33,0x00,0x52,0xff,0xb4,0x00,0x33,0x00,0x54,0xff,0xb6,0x00,0x33,0x00,0x62,0xff,0x62,0x00,0x33,0x00,0x63,0xff,0x62,0x00,0x33,0x00,0x69,0xff,0xbe,0x00,0x33,0x00,0x6a, 0xff,0xbe,0x00,0x33,0x00,0x6b,0xff,0xbe,0x00,0x33,0x00,0x6c,0xff,0xbe,0x00,0x33,0x00,0x6d,0xff,0xbe,0x00,0x33,0x00,0x6e,0xff,0xbe,0x00,0x33,0x00,0x6f,0xff,0xb4,0x00,0x33,0x00,0x70,0xff,0xb4,0x00,0x33,0x00,0x71,0xff,0xb4,0x00,0x33,0x00,0x72,0xff,0xb4,0x00,0x33,0x00,0x73,0xff,0xb4,0x00,0x33,0x00,0x79,0xff,0xb4,0x00,0x33, 0x00,0x7a,0xff,0xb4,0x00,0x33,0x00,0x7b,0xff,0xb4,0x00,0x33,0x00,0x7c,0xff,0xb4,0x00,0x33,0x00,0x7d,0xff,0xb4,0x00,0x33,0x00,0x91,0xfe,0xe9,0x00,0x33,0x00,0xa0,0xff,0xbe,0x00,0x33,0x00,0xac,0xfe,0xba,0x00,0x33,0x00,0xad,0xff,0x62,0x00,0x33,0x00,0xae,0xff,0x62,0x00,0x33,0x00,0xb1,0xff,0xb4,0x00,0x33,0x00,0xc4,0xfe,0xba, 0x00,0x33,0x00,0xc5,0xfe,0xae,0x00,0x33,0x00,0xc7,0xff,0x62,0x00,0x33,0x00,0xc9,0xff,0x62,0x00,0x33,0x00,0xf7,0xff,0xf6,0x00,0x33,0x00,0xf8,0xff,0xb4,0x00,0x33,0x00,0xfd,0xff,0xb4,0x00,0x33,0x00,0xff,0xff,0xb4,0x00,0x33,0x01,0x00,0xff,0xb4,0x00,0x33,0x01,0x03,0xff,0x62,0x00,0x33,0x01,0x04,0xff,0xbe,0x00,0x33,0x01,0x05, 0xff,0x62,0x00,0x33,0x01,0x06,0xff,0xbe,0x00,0x33,0x01,0x08,0xff,0xb4,0x00,0x33,0x01,0x0b,0xff,0xb4,0x00,0x33,0x01,0x0d,0xff,0xb4,0x00,0x33,0x01,0x19,0xff,0xb4,0x00,0x33,0x01,0x45,0xff,0x62,0x00,0x33,0x01,0x46,0xff,0xbe,0x00,0x33,0x01,0x48,0xff,0xb4,0x00,0x33,0x01,0x4c,0xff,0xb4,0x00,0x33,0x01,0x4e,0xff,0xb4,0x00,0x33, 0x01,0x50,0xff,0xb4,0x00,0x33,0x01,0x51,0xff,0xf6,0x00,0x33,0x01,0x52,0xff,0xb4,0x00,0x33,0x01,0x53,0xff,0xf6,0x00,0x33,0x01,0x54,0xff,0xb4,0x00,0x33,0x01,0x55,0xff,0xf6,0x00,0x33,0x01,0x56,0xff,0xb4,0x00,0x33,0x01,0x63,0xff,0x7f,0x00,0x33,0x01,0x6f,0xff,0xb4,0x00,0x33,0x01,0x71,0xff,0xb4,0x00,0x33,0x01,0x80,0x00,0x27, 0x00,0x33,0x01,0x85,0xff,0x62,0x00,0x33,0x01,0x86,0xff,0xbe,0x00,0x33,0x01,0x87,0xff,0x62,0x00,0x33,0x01,0x88,0xff,0xbe,0x00,0x33,0x01,0x8a,0xff,0xb4,0x00,0x33,0x01,0x8c,0x00,0x27,0x00,0x33,0x01,0x8e,0x00,0x27,0x00,0x33,0x01,0x90,0x00,0x27,0x00,0x34,0x00,0x0f,0xff,0xa4,0x00,0x34,0x00,0x11,0xff,0x7f,0x00,0x34,0x00,0x24, 0xff,0xe5,0x00,0x34,0x00,0x37,0xff,0xa4,0x00,0x34,0x00,0x3b,0xff,0xdb,0x00,0x34,0x00,0x3c,0xff,0xf6,0x00,0x34,0x00,0x3d,0xff,0xcf,0x00,0x34,0x00,0x62,0xff,0xe5,0x00,0x34,0x00,0x63,0xff,0xe5,0x00,0x34,0x00,0xac,0xff,0x7f,0x00,0x34,0x00,0xad,0xff,0xe5,0x00,0x34,0x00,0xae,0xff,0xe5,0x00,0x34,0x00,0xbb,0xff,0xf6,0x00,0x34, 0x00,0xc4,0xff,0x98,0x00,0x34,0x00,0xc5,0xff,0x98,0x00,0x34,0x00,0xc7,0xff,0xe5,0x00,0x34,0x00,0xc9,0xff,0xe5,0x00,0x34,0x00,0xe5,0xff,0xcf,0x00,0x34,0x00,0xea,0xff,0xf6,0x00,0x34,0x01,0x03,0xff,0xe5,0x00,0x34,0x01,0x05,0xff,0xe5,0x00,0x34,0x01,0x20,0xff,0xa4,0x00,0x34,0x01,0x22,0xff,0xa4,0x00,0x34,0x01,0x28,0xff,0xcf, 0x00,0x34,0x01,0x2a,0xff,0xcf,0x00,0x34,0x01,0x45,0xff,0xe5,0x00,0x34,0x01,0x76,0xff,0xa4,0x00,0x34,0x01,0x82,0xff,0xf6,0x00,0x34,0x01,0x85,0xff,0xe5,0x00,0x34,0x01,0x87,0xff,0xe5,0x00,0x34,0x01,0x92,0xff,0xf6,0x00,0x35,0x00,0x1e,0x00,0x52,0x00,0x35,0x00,0x26,0xff,0xe3,0x00,0x35,0x00,0x2a,0xff,0xe3,0x00,0x35,0x00,0x2d, 0x00,0x39,0x00,0x35,0x00,0x32,0xff,0xec,0x00,0x35,0x00,0x34,0xff,0xec,0x00,0x35,0x00,0x37,0xff,0xcb,0x00,0x35,0x00,0x3c,0xff,0xd9,0x00,0x35,0x00,0x46,0xff,0xcb,0x00,0x35,0x00,0x47,0xff,0xcb,0x00,0x35,0x00,0x48,0xff,0xc7,0x00,0x35,0x00,0x4a,0xff,0xc7,0x00,0x35,0x00,0x52,0xff,0xc5,0x00,0x35,0x00,0x54,0xff,0xcb,0x00,0x35, 0x00,0x64,0xff,0xe5,0x00,0x35,0x00,0x67,0xff,0xec,0x00,0x35,0x00,0x6f,0xff,0xbe,0x00,0x35,0x00,0x70,0xff,0xbe,0x00,0x35,0x00,0x71,0xff,0xbe,0x00,0x35,0x00,0x72,0xff,0xbe,0x00,0x35,0x00,0x73,0xff,0xbe,0x00,0x35,0x00,0x79,0xff,0xc5,0x00,0x35,0x00,0x7a,0xff,0xc5,0x00,0x35,0x00,0x7b,0xff,0xc5,0x00,0x35,0x00,0x7c,0xff,0xc5, 0x00,0x35,0x00,0x7d,0xff,0xc5,0x00,0x35,0x00,0x92,0xff,0xec,0x00,0x35,0x00,0xaf,0xff,0xec,0x00,0x35,0x00,0xb0,0xff,0xec,0x00,0x35,0x00,0xb1,0xff,0xc5,0x00,0x35,0x00,0xbb,0xff,0xe5,0x00,0x35,0x00,0xd0,0xff,0xec,0x00,0x35,0x00,0xd1,0xff,0xec,0x00,0x35,0x00,0xd2,0xff,0xec,0x00,0x35,0x00,0xea,0xff,0xd9,0x00,0x35,0x00,0xf7, 0xff,0xe3,0x00,0x35,0x00,0xf8,0xff,0xc7,0x00,0x35,0x00,0xfc,0xff,0xe3,0x00,0x35,0x00,0xfd,0xff,0xcb,0x00,0x35,0x00,0xfe,0xff,0xe3,0x00,0x35,0x00,0xff,0xff,0xcb,0x00,0x35,0x01,0x00,0xff,0xcb,0x00,0x35,0x01,0x08,0xff,0xcb,0x00,0x35,0x01,0x0b,0xff,0xc7,0x00,0x35,0x01,0x0d,0xff,0xbe,0x00,0x35,0x01,0x18,0xff,0xec,0x00,0x35, 0x01,0x19,0xff,0xc5,0x00,0x35,0x01,0x20,0xff,0xcb,0x00,0x35,0x01,0x22,0xff,0xcb,0x00,0x35,0x01,0x47,0xff,0xe3,0x00,0x35,0x01,0x48,0xff,0xcb,0x00,0x35,0x01,0x4c,0xff,0xbe,0x00,0x35,0x01,0x4e,0xff,0xbe,0x00,0x35,0x01,0x50,0xff,0xbe,0x00,0x35,0x01,0x51,0xff,0xe3,0x00,0x35,0x01,0x52,0xff,0xc7,0x00,0x35,0x01,0x53,0xff,0xe3, 0x00,0x35,0x01,0x54,0xff,0xc7,0x00,0x35,0x01,0x55,0xff,0xe3,0x00,0x35,0x01,0x56,0xff,0xc7,0x00,0x35,0x01,0x63,0x00,0x39,0x00,0x35,0x01,0x6e,0xff,0xec,0x00,0x35,0x01,0x6f,0xff,0xc5,0x00,0x35,0x01,0x70,0xff,0xec,0x00,0x35,0x01,0x71,0xff,0xc5,0x00,0x35,0x01,0x76,0xff,0xcb,0x00,0x35,0x01,0x82,0xff,0xd9,0x00,0x35,0x01,0x89, 0xff,0xec,0x00,0x35,0x01,0x8a,0xff,0xc5,0x00,0x35,0x01,0x92,0xff,0xd9,0x00,0x36,0x00,0x57,0xff,0xbe,0x00,0x36,0x00,0x59,0xff,0xcf,0x00,0x36,0x00,0x5a,0xff,0xe5,0x00,0x36,0x00,0x5c,0xff,0xd1,0x00,0x36,0x00,0xba,0xff,0xbe,0x00,0x36,0x00,0xc4,0xff,0xb2,0x00,0x36,0x00,0xc5,0xff,0xb2,0x00,0x36,0x00,0xeb,0xff,0xd1,0x00,0x36, 0x01,0x21,0xff,0xbe,0x00,0x36,0x01,0x23,0xff,0xbe,0x00,0x36,0x01,0x77,0xff,0xbe,0x00,0x36,0x01,0x81,0xff,0xe5,0x00,0x36,0x01,0x83,0xff,0xd1,0x00,0x36,0x01,0x8d,0xff,0xe5,0x00,0x36,0x01,0x8f,0xff,0xe5,0x00,0x36,0x01,0x91,0xff,0xe5,0x00,0x36,0x01,0x93,0xff,0xd1,0x00,0x37,0x00,0x0f,0xff,0x7f,0x00,0x37,0x00,0x11,0xff,0x4c, 0x00,0x37,0x00,0x1d,0xff,0xe9,0x00,0x37,0x00,0x1e,0xff,0xe9,0x00,0x37,0x00,0x24,0xff,0x66,0x00,0x37,0x00,0x26,0xff,0xa4,0x00,0x37,0x00,0x2a,0xff,0xa4,0x00,0x37,0x00,0x2d,0xff,0x8f,0x00,0x37,0x00,0x32,0xff,0xa4,0x00,0x37,0x00,0x34,0xff,0xa4,0x00,0x37,0x00,0x37,0x00,0x27,0x00,0x37,0x00,0x39,0x00,0x2b,0x00,0x37,0x00,0x3a, 0x00,0x27,0x00,0x37,0x00,0x3b,0xff,0xfa,0x00,0x37,0x00,0x3c,0x00,0x1d,0x00,0x37,0x00,0x44,0xff,0x27,0x00,0x37,0x00,0x46,0xff,0x2d,0x00,0x37,0x00,0x47,0xff,0x2d,0x00,0x37,0x00,0x48,0xff,0x2d,0x00,0x37,0x00,0x49,0xff,0xa0,0x00,0x37,0x00,0x4a,0xff,0x2d,0x00,0x37,0x00,0x50,0xff,0x4e,0x00,0x37,0x00,0x51,0xff,0x4e,0x00,0x37, 0x00,0x52,0xff,0x2d,0x00,0x37,0x00,0x53,0xff,0x4e,0x00,0x37,0x00,0x54,0xff,0x2d,0x00,0x37,0x00,0x55,0xff,0x4e,0x00,0x37,0x00,0x56,0xff,0x66,0x00,0x37,0x00,0x58,0xff,0x4e,0x00,0x37,0x00,0x59,0xff,0x9a,0x00,0x37,0x00,0x5a,0xff,0x8f,0x00,0x37,0x00,0x5b,0xff,0x4c,0x00,0x37,0x00,0x5c,0xff,0x8f,0x00,0x37,0x00,0x5d,0xff,0x7f, 0x00,0x37,0x00,0x62,0xff,0x66,0x00,0x37,0x00,0x63,0xff,0x66,0x00,0x37,0x00,0x64,0xff,0xa4,0x00,0x37,0x00,0x67,0xff,0xa4,0x00,0x37,0x00,0x69,0xff,0x27,0x00,0x37,0x00,0x6a,0xff,0x27,0x00,0x37,0x00,0x6b,0xff,0x27,0x00,0x37,0x00,0x6c,0xff,0x27,0x00,0x37,0x00,0x6d,0xff,0x3f,0x00,0x37,0x00,0x6e,0xff,0x27,0x00,0x37,0x00,0x6f, 0xff,0x1b,0x00,0x37,0x00,0x70,0xff,0x2d,0x00,0x37,0x00,0x71,0xff,0x2d,0x00,0x37,0x00,0x72,0xff,0x2d,0x00,0x37,0x00,0x73,0xff,0x2d,0x00,0x37,0x00,0x74,0xff,0xe9,0x00,0x37,0x00,0x76,0x00,0x31,0x00,0x37,0x00,0x77,0x00,0x6f,0x00,0x37,0x00,0x78,0xff,0x4e,0x00,0x37,0x00,0x79,0xff,0x2d,0x00,0x37,0x00,0x7a,0xff,0x2d,0x00,0x37, 0x00,0x7b,0xff,0x2d,0x00,0x37,0x00,0x7c,0xff,0x2d,0x00,0x37,0x00,0x7d,0xff,0x2d,0x00,0x37,0x00,0x7e,0xff,0x4e,0x00,0x37,0x00,0x7f,0xff,0x4e,0x00,0x37,0x00,0x80,0xff,0x4e,0x00,0x37,0x00,0x81,0xff,0x4e,0x00,0x37,0x00,0x8d,0x00,0x52,0x00,0x37,0x00,0x91,0xff,0x0c,0x00,0x37,0x00,0x92,0xff,0xa4,0x00,0x37,0x00,0xa0,0xff,0x27, 0x00,0x37,0x00,0xaa,0xff,0x9a,0x00,0x37,0x00,0xab,0xff,0xcf,0x00,0x37,0x00,0xac,0xff,0x4c,0x00,0x37,0x00,0xad,0xff,0x66,0x00,0x37,0x00,0xae,0xff,0x66,0x00,0x37,0x00,0xaf,0xff,0xa4,0x00,0x37,0x00,0xb0,0xff,0xa4,0x00,0x37,0x00,0xb1,0xff,0x2d,0x00,0x37,0x00,0xb5,0x00,0x27,0x00,0x37,0x00,0xb7,0x00,0x27,0x00,0x37,0x00,0xba, 0xff,0x8f,0x00,0x37,0x00,0xbe,0xff,0x9a,0x00,0x37,0x00,0xbf,0xff,0xcf,0x00,0x37,0x00,0xc4,0xff,0x17,0x00,0x37,0x00,0xc5,0xff,0x17,0x00,0x37,0x00,0xc7,0xff,0x66,0x00,0x37,0x00,0xc9,0xff,0x66,0x00,0x37,0x00,0xd0,0xff,0xa4,0x00,0x37,0x00,0xd1,0xff,0xa4,0x00,0x37,0x00,0xd2,0xff,0xa4,0x00,0x37,0x00,0xe4,0xff,0x66,0x00,0x37, 0x00,0xe6,0xff,0x7f,0x00,0x37,0x00,0xea,0x00,0x1d,0x00,0x37,0x00,0xeb,0xff,0x8f,0x00,0x37,0x00,0xf7,0xff,0xa4,0x00,0x37,0x00,0xf8,0xff,0x2d,0x00,0x37,0x00,0xfb,0xff,0x66,0x00,0x37,0x00,0xfc,0xff,0xa4,0x00,0x37,0x00,0xfd,0xff,0x2d,0x00,0x37,0x00,0xfe,0xff,0xa4,0x00,0x37,0x00,0xff,0xff,0x2d,0x00,0x37,0x01,0x00,0xff,0x2d, 0x00,0x37,0x01,0x03,0xff,0x66,0x00,0x37,0x01,0x04,0xff,0x27,0x00,0x37,0x01,0x05,0xff,0x66,0x00,0x37,0x01,0x06,0xff,0x27,0x00,0x37,0x01,0x08,0xff,0x2d,0x00,0x37,0x01,0x0b,0xff,0x2d,0x00,0x37,0x01,0x0d,0xff,0x2d,0x00,0x37,0x01,0x15,0xff,0x4e,0x00,0x37,0x01,0x17,0xff,0x4e,0x00,0x37,0x01,0x18,0xff,0xa4,0x00,0x37,0x01,0x19, 0xff,0x2d,0x00,0x37,0x01,0x1b,0xff,0x4e,0x00,0x37,0x01,0x1d,0xff,0x4e,0x00,0x37,0x01,0x1f,0xff,0x66,0x00,0x37,0x01,0x20,0x00,0x27,0x00,0x37,0x01,0x22,0x00,0x27,0x00,0x37,0x01,0x25,0xff,0x4e,0x00,0x37,0x01,0x27,0xff,0x4e,0x00,0x37,0x01,0x29,0xff,0x7f,0x00,0x37,0x01,0x2b,0xff,0x7f,0x00,0x37,0x01,0x45,0xff,0x66,0x00,0x37, 0x01,0x46,0xff,0x27,0x00,0x37,0x01,0x47,0xff,0xa4,0x00,0x37,0x01,0x48,0xff,0x2d,0x00,0x37,0x01,0x4c,0xff,0x2d,0x00,0x37,0x01,0x4e,0xff,0x2d,0x00,0x37,0x01,0x50,0xff,0x2d,0x00,0x37,0x01,0x51,0xff,0xa4,0x00,0x37,0x01,0x52,0xff,0x2d,0x00,0x37,0x01,0x53,0xff,0xa4,0x00,0x37,0x01,0x54,0xff,0x2d,0x00,0x37,0x01,0x55,0xff,0xa4, 0x00,0x37,0x01,0x56,0xff,0x2d,0x00,0x37,0x01,0x5c,0x00,0x6f,0x00,0x37,0x01,0x5e,0x00,0x6f,0x00,0x37,0x01,0x60,0x00,0x6f,0x00,0x37,0x01,0x63,0xff,0x8f,0x00,0x37,0x01,0x6d,0xff,0x4e,0x00,0x37,0x01,0x6e,0xff,0xa4,0x00,0x37,0x01,0x6f,0xff,0x2d,0x00,0x37,0x01,0x70,0xff,0xa4,0x00,0x37,0x01,0x71,0xff,0x2d,0x00,0x37,0x01,0x73, 0xff,0x4e,0x00,0x37,0x01,0x75,0xff,0x66,0x00,0x37,0x01,0x76,0x00,0x27,0x00,0x37,0x01,0x79,0xff,0x4e,0x00,0x37,0x01,0x7b,0xff,0x4e,0x00,0x37,0x01,0x7d,0xff,0x4e,0x00,0x37,0x01,0x7f,0xff,0x4e,0x00,0x37,0x01,0x80,0x00,0x27,0x00,0x37,0x01,0x81,0xff,0x8f,0x00,0x37,0x01,0x82,0x00,0x1d,0x00,0x37,0x01,0x83,0xff,0x8f,0x00,0x37, 0x01,0x85,0xff,0x66,0x00,0x37,0x01,0x86,0xff,0x27,0x00,0x37,0x01,0x87,0xff,0x66,0x00,0x37,0x01,0x88,0xff,0x27,0x00,0x37,0x01,0x89,0xff,0xa4,0x00,0x37,0x01,0x8a,0xff,0x2d,0x00,0x37,0x01,0x8c,0x00,0x27,0x00,0x37,0x01,0x8d,0xff,0x8f,0x00,0x37,0x01,0x8e,0x00,0x27,0x00,0x37,0x01,0x8f,0xff,0x8f,0x00,0x37,0x01,0x90,0x00,0x27, 0x00,0x37,0x01,0x91,0xff,0x8f,0x00,0x37,0x01,0x92,0x00,0x1d,0x00,0x37,0x01,0x93,0xff,0x8f,0x00,0x37,0x02,0x3e,0xff,0x66,0x00,0x38,0x00,0x24,0xff,0xd7,0x00,0x38,0x00,0x91,0xff,0x8b,0x00,0x38,0x00,0xc4,0xff,0xa6,0x00,0x38,0x00,0xc5,0xff,0xa6,0x00,0x38,0x01,0x03,0xff,0xd7,0x00,0x38,0x01,0x05,0xff,0xd7,0x00,0x38,0x01,0x45, 0xff,0xd7,0x00,0x38,0x01,0x85,0xff,0xd7,0x00,0x38,0x01,0x87,0xff,0xd7,0x00,0x39,0x00,0x0f,0xff,0x33,0x00,0x39,0x00,0x11,0xff,0x1b,0x00,0x39,0x00,0x24,0xff,0x8b,0x00,0x39,0x00,0x26,0xff,0xd5,0x00,0x39,0x00,0x2a,0xff,0xd5,0x00,0x39,0x00,0x2d,0xff,0xba,0x00,0x39,0x00,0x32,0xff,0xf4,0x00,0x39,0x00,0x34,0xff,0xd5,0x00,0x39, 0x00,0x36,0xff,0xe5,0x00,0x39,0x00,0x37,0x00,0x27,0x00,0x39,0x00,0x44,0xff,0x6d,0x00,0x39,0x00,0x46,0xff,0x7f,0x00,0x39,0x00,0x47,0xff,0x7f,0x00,0x39,0x00,0x48,0xff,0x7f,0x00,0x39,0x00,0x4a,0xff,0x7f,0x00,0x39,0x00,0x50,0xff,0xb4,0x00,0x39,0x00,0x51,0xff,0xb4,0x00,0x39,0x00,0x52,0xff,0x7f,0x00,0x39,0x00,0x53,0xff,0xb4, 0x00,0x39,0x00,0x54,0xff,0x7f,0x00,0x39,0x00,0x55,0xff,0xb4,0x00,0x39,0x00,0x56,0xff,0xbe,0x00,0x39,0x00,0x58,0xff,0xb4,0x00,0x39,0x00,0x62,0xff,0x8b,0x00,0x39,0x00,0x63,0xff,0x8b,0x00,0x39,0x00,0x64,0xff,0xe1,0x00,0x39,0x00,0x67,0xff,0xf4,0x00,0x39,0x00,0x69,0xff,0x6d,0x00,0x39,0x00,0x6a,0xff,0x6d,0x00,0x39,0x00,0x6b, 0xff,0x6d,0x00,0x39,0x00,0x6c,0xff,0x6d,0x00,0x39,0x00,0x6d,0xff,0x6d,0x00,0x39,0x00,0x6e,0xff,0x6d,0x00,0x39,0x00,0x6f,0xff,0x7f,0x00,0x39,0x00,0x70,0xff,0x7f,0x00,0x39,0x00,0x71,0xff,0x7f,0x00,0x39,0x00,0x72,0xff,0x7f,0x00,0x39,0x00,0x73,0xff,0x7f,0x00,0x39,0x00,0x76,0x00,0x1d,0x00,0x39,0x00,0x77,0x00,0x5a,0x00,0x39, 0x00,0x78,0xff,0xb4,0x00,0x39,0x00,0x79,0xff,0x7f,0x00,0x39,0x00,0x7a,0xff,0x7f,0x00,0x39,0x00,0x7b,0xff,0x7f,0x00,0x39,0x00,0x7c,0xff,0x7f,0x00,0x39,0x00,0x7d,0xff,0x7f,0x00,0x39,0x00,0x7e,0xff,0xb4,0x00,0x39,0x00,0x7f,0xff,0xb4,0x00,0x39,0x00,0x80,0xff,0xb4,0x00,0x39,0x00,0x81,0xff,0xb4,0x00,0x39,0x00,0x8d,0x00,0x52, 0x00,0x39,0x00,0x91,0xff,0x44,0x00,0x39,0x00,0x92,0xff,0xf4,0x00,0x39,0x00,0xa0,0xff,0x6d,0x00,0x39,0x00,0xa2,0xff,0x75,0x00,0x39,0x00,0xaa,0xff,0xcf,0x00,0x39,0x00,0xac,0xff,0x1b,0x00,0x39,0x00,0xad,0xff,0x8b,0x00,0x39,0x00,0xae,0xff,0x8b,0x00,0x39,0x00,0xaf,0xff,0xf4,0x00,0x39,0x00,0xb0,0xff,0xf4,0x00,0x39,0x00,0xb1, 0xff,0x7f,0x00,0x39,0x00,0xbe,0xff,0xcf,0x00,0x39,0x00,0xc4,0xff,0x73,0x00,0x39,0x00,0xc5,0xff,0x7f,0x00,0x39,0x00,0xc7,0xff,0x8b,0x00,0x39,0x00,0xc9,0xff,0x8b,0x00,0x39,0x00,0xd0,0xff,0xf4,0x00,0x39,0x00,0xd1,0xff,0xf4,0x00,0x39,0x00,0xd2,0xff,0xf4,0x00,0x39,0x00,0xe3,0xff,0xe5,0x00,0x39,0x00,0xe4,0xff,0xbe,0x00,0x39, 0x00,0xf7,0xff,0xd5,0x00,0x39,0x00,0xf8,0xff,0x7f,0x00,0x39,0x00,0xfa,0xff,0xe5,0x00,0x39,0x00,0xfb,0xff,0xbe,0x00,0x39,0x00,0xfc,0xff,0xd5,0x00,0x39,0x00,0xfd,0xff,0x7f,0x00,0x39,0x00,0xfe,0xff,0xd5,0x00,0x39,0x00,0xff,0xff,0x7f,0x00,0x39,0x01,0x00,0xff,0x7f,0x00,0x39,0x01,0x03,0xff,0x8b,0x00,0x39,0x01,0x04,0xff,0x6d, 0x00,0x39,0x01,0x05,0xff,0x8b,0x00,0x39,0x01,0x06,0xff,0x6d,0x00,0x39,0x01,0x08,0xff,0x7f,0x00,0x39,0x01,0x0b,0xff,0x7f,0x00,0x39,0x01,0x0d,0xff,0x7f,0x00,0x39,0x01,0x15,0xff,0xb4,0x00,0x39,0x01,0x17,0xff,0xb4,0x00,0x39,0x01,0x18,0xff,0xf4,0x00,0x39,0x01,0x19,0xff,0x7f,0x00,0x39,0x01,0x1b,0xff,0xb4,0x00,0x39,0x01,0x1d, 0xff,0xb4,0x00,0x39,0x01,0x1e,0xff,0xe5,0x00,0x39,0x01,0x1f,0xff,0xbe,0x00,0x39,0x01,0x20,0x00,0x27,0x00,0x39,0x01,0x22,0x00,0x27,0x00,0x39,0x01,0x25,0xff,0xb4,0x00,0x39,0x01,0x27,0xff,0xb4,0x00,0x39,0x01,0x45,0xff,0x8b,0x00,0x39,0x01,0x46,0xff,0x6d,0x00,0x39,0x01,0x47,0xff,0xd5,0x00,0x39,0x01,0x48,0xff,0x7f,0x00,0x39, 0x01,0x4c,0xff,0x7f,0x00,0x39,0x01,0x4e,0xff,0x7f,0x00,0x39,0x01,0x50,0xff,0x7f,0x00,0x39,0x01,0x51,0xff,0xd5,0x00,0x39,0x01,0x52,0xff,0x7f,0x00,0x39,0x01,0x53,0xff,0xd5,0x00,0x39,0x01,0x54,0xff,0x7f,0x00,0x39,0x01,0x55,0xff,0xd5,0x00,0x39,0x01,0x56,0xff,0x7f,0x00,0x39,0x01,0x5c,0x00,0x5a,0x00,0x39,0x01,0x5e,0x00,0x5a, 0x00,0x39,0x01,0x60,0x00,0x5a,0x00,0x39,0x01,0x63,0xff,0xba,0x00,0x39,0x01,0x6d,0xff,0xb4,0x00,0x39,0x01,0x6e,0xff,0xf4,0x00,0x39,0x01,0x6f,0xff,0x7f,0x00,0x39,0x01,0x70,0xff,0xf4,0x00,0x39,0x01,0x71,0xff,0x7f,0x00,0x39,0x01,0x73,0xff,0xb4,0x00,0x39,0x01,0x74,0xff,0xe5,0x00,0x39,0x01,0x75,0xff,0xbe,0x00,0x39,0x01,0x76, 0x00,0x27,0x00,0x39,0x01,0x79,0xff,0xb4,0x00,0x39,0x01,0x7b,0xff,0xb4,0x00,0x39,0x01,0x7d,0xff,0xb4,0x00,0x39,0x01,0x7f,0xff,0xb4,0x00,0x39,0x01,0x85,0xff,0x8b,0x00,0x39,0x01,0x86,0xff,0x6d,0x00,0x39,0x01,0x87,0xff,0x8b,0x00,0x39,0x01,0x88,0xff,0x6d,0x00,0x39,0x01,0x89,0xff,0xf4,0x00,0x39,0x01,0x8a,0xff,0x7f,0x00,0x39, 0x02,0x3d,0xff,0xe5,0x00,0x39,0x02,0x3e,0xff,0xbe,0x00,0x3a,0x00,0x0f,0xff,0x8b,0x00,0x3a,0x00,0x11,0xff,0x7f,0x00,0x3a,0x00,0x24,0xff,0xb6,0x00,0x3a,0x00,0x37,0x00,0x27,0x00,0x3a,0x00,0x44,0xff,0xb4,0x00,0x3a,0x00,0x46,0xff,0xcf,0x00,0x3a,0x00,0x47,0xff,0xcf,0x00,0x3a,0x00,0x48,0xff,0xcf,0x00,0x3a,0x00,0x4a,0xff,0xcf, 0x00,0x3a,0x00,0x52,0xff,0xcf,0x00,0x3a,0x00,0x54,0xff,0xcf,0x00,0x3a,0x00,0x62,0xff,0xb6,0x00,0x3a,0x00,0x63,0xff,0xb6,0x00,0x3a,0x00,0x69,0xff,0xb4,0x00,0x3a,0x00,0x6a,0xff,0xb4,0x00,0x3a,0x00,0x6b,0xff,0xb4,0x00,0x3a,0x00,0x6c,0xff,0xb4,0x00,0x3a,0x00,0x6d,0xff,0xb4,0x00,0x3a,0x00,0x6e,0xff,0xb4,0x00,0x3a,0x00,0x6f, 0xff,0xcf,0x00,0x3a,0x00,0x70,0xff,0xcf,0x00,0x3a,0x00,0x71,0xff,0xcf,0x00,0x3a,0x00,0x72,0xff,0xcf,0x00,0x3a,0x00,0x73,0xff,0xcf,0x00,0x3a,0x00,0x76,0x00,0x31,0x00,0x3a,0x00,0x77,0x00,0x64,0x00,0x3a,0x00,0x79,0xff,0xcf,0x00,0x3a,0x00,0x7a,0xff,0xcf,0x00,0x3a,0x00,0x7b,0xff,0xcf,0x00,0x3a,0x00,0x7c,0xff,0xcf,0x00,0x3a, 0x00,0x7d,0xff,0xcf,0x00,0x3a,0x00,0x91,0xff,0x9a,0x00,0x3a,0x00,0xa0,0xff,0xb4,0x00,0x3a,0x00,0xa2,0xff,0xa4,0x00,0x3a,0x00,0xaa,0xff,0xcf,0x00,0x3a,0x00,0xab,0x00,0x27,0x00,0x3a,0x00,0xac,0xff,0x7f,0x00,0x3a,0x00,0xad,0xff,0xb6,0x00,0x3a,0x00,0xae,0xff,0xb6,0x00,0x3a,0x00,0xb1,0xff,0xcf,0x00,0x3a,0x00,0xbe,0xff,0xcf, 0x00,0x3a,0x00,0xbf,0x00,0x27,0x00,0x3a,0x00,0xc4,0xff,0x7f,0x00,0x3a,0x00,0xc5,0xff,0x8b,0x00,0x3a,0x00,0xc7,0xff,0xb6,0x00,0x3a,0x00,0xc9,0xff,0xb6,0x00,0x3a,0x00,0xf8,0xff,0xcf,0x00,0x3a,0x00,0xfd,0xff,0xcf,0x00,0x3a,0x00,0xff,0xff,0xcf,0x00,0x3a,0x01,0x00,0xff,0xcf,0x00,0x3a,0x01,0x03,0xff,0xb6,0x00,0x3a,0x01,0x04, 0xff,0xb4,0x00,0x3a,0x01,0x05,0xff,0xb6,0x00,0x3a,0x01,0x06,0xff,0xb4,0x00,0x3a,0x01,0x08,0xff,0xcf,0x00,0x3a,0x01,0x0b,0xff,0xcf,0x00,0x3a,0x01,0x0d,0xff,0xcf,0x00,0x3a,0x01,0x19,0xff,0xcf,0x00,0x3a,0x01,0x20,0x00,0x27,0x00,0x3a,0x01,0x22,0x00,0x27,0x00,0x3a,0x01,0x45,0xff,0xb6,0x00,0x3a,0x01,0x46,0xff,0xb4,0x00,0x3a, 0x01,0x48,0xff,0xcf,0x00,0x3a,0x01,0x4c,0xff,0xcf,0x00,0x3a,0x01,0x4e,0xff,0xcf,0x00,0x3a,0x01,0x50,0xff,0xcf,0x00,0x3a,0x01,0x52,0xff,0xcf,0x00,0x3a,0x01,0x54,0xff,0xcf,0x00,0x3a,0x01,0x56,0xff,0xcf,0x00,0x3a,0x01,0x5c,0x00,0x64,0x00,0x3a,0x01,0x5e,0x00,0x64,0x00,0x3a,0x01,0x60,0x00,0x64,0x00,0x3a,0x01,0x6f,0xff,0xcf, 0x00,0x3a,0x01,0x71,0xff,0xcf,0x00,0x3a,0x01,0x76,0x00,0x27,0x00,0x3a,0x01,0x85,0xff,0xb6,0x00,0x3a,0x01,0x86,0xff,0xb4,0x00,0x3a,0x01,0x87,0xff,0xb6,0x00,0x3a,0x01,0x88,0xff,0xb4,0x00,0x3a,0x01,0x8a,0xff,0xcf,0x00,0x3b,0x00,0x0f,0x00,0x44,0x00,0x3b,0x00,0x11,0x00,0x39,0x00,0x3b,0x00,0x1e,0x00,0x52,0x00,0x3b,0x00,0x26, 0xff,0xe9,0x00,0x3b,0x00,0x2a,0xff,0xe9,0x00,0x3b,0x00,0x2d,0x00,0x60,0x00,0x3b,0x00,0x32,0xff,0xe9,0x00,0x3b,0x00,0x34,0xff,0xe9,0x00,0x3b,0x00,0x37,0x00,0x21,0x00,0x3b,0x00,0x64,0xff,0xe9,0x00,0x3b,0x00,0x67,0xff,0xe9,0x00,0x3b,0x00,0x77,0x00,0x52,0x00,0x3b,0x00,0x92,0xff,0xe9,0x00,0x3b,0x00,0xac,0x00,0x39,0x00,0x3b, 0x00,0xaf,0xff,0xe9,0x00,0x3b,0x00,0xb0,0xff,0xe9,0x00,0x3b,0x00,0xc4,0x00,0x44,0x00,0x3b,0x00,0xc5,0x00,0x52,0x00,0x3b,0x00,0xd0,0xff,0xe9,0x00,0x3b,0x00,0xd1,0xff,0xe9,0x00,0x3b,0x00,0xd2,0xff,0xe9,0x00,0x3b,0x00,0xf7,0xff,0xe9,0x00,0x3b,0x00,0xfc,0xff,0xe9,0x00,0x3b,0x00,0xfe,0xff,0xe9,0x00,0x3b,0x01,0x18,0xff,0xe9, 0x00,0x3b,0x01,0x20,0x00,0x21,0x00,0x3b,0x01,0x22,0x00,0x21,0x00,0x3b,0x01,0x47,0xff,0xe9,0x00,0x3b,0x01,0x51,0xff,0xe9,0x00,0x3b,0x01,0x53,0xff,0xe9,0x00,0x3b,0x01,0x55,0xff,0xe9,0x00,0x3b,0x01,0x5c,0x00,0x52,0x00,0x3b,0x01,0x5e,0x00,0x52,0x00,0x3b,0x01,0x60,0x00,0x52,0x00,0x3b,0x01,0x63,0x00,0x60,0x00,0x3b,0x01,0x6e, 0xff,0xe9,0x00,0x3b,0x01,0x70,0xff,0xe9,0x00,0x3b,0x01,0x76,0x00,0x21,0x00,0x3b,0x01,0x89,0xff,0xe9,0x00,0x3c,0x00,0x0f,0xff,0x50,0x00,0x3c,0x00,0x11,0xff,0x3d,0x00,0x3c,0x00,0x24,0xff,0x62,0x00,0x3c,0x00,0x26,0xff,0xd3,0x00,0x3c,0x00,0x2a,0xff,0xd3,0x00,0x3c,0x00,0x2d,0xff,0xbe,0x00,0x3c,0x00,0x32,0xff,0xd3,0x00,0x3c, 0x00,0x34,0xff,0xd3,0x00,0x3c,0x00,0x36,0xff,0xe5,0x00,0x3c,0x00,0x37,0x00,0x27,0x00,0x3c,0x00,0x44,0xff,0x39,0x00,0x3c,0x00,0x46,0xff,0x4c,0x00,0x3c,0x00,0x47,0xff,0x4c,0x00,0x3c,0x00,0x48,0xff,0x4c,0x00,0x3c,0x00,0x49,0xff,0xe5,0x00,0x3c,0x00,0x4a,0xff,0x4c,0x00,0x3c,0x00,0x50,0xff,0x73,0x00,0x3c,0x00,0x51,0xff,0x73, 0x00,0x3c,0x00,0x52,0xff,0x4c,0x00,0x3c,0x00,0x53,0xff,0x73,0x00,0x3c,0x00,0x54,0xff,0x4c,0x00,0x3c,0x00,0x55,0xff,0x73,0x00,0x3c,0x00,0x56,0xff,0x7b,0x00,0x3c,0x00,0x58,0xff,0x73,0x00,0x3c,0x00,0x62,0xff,0x62,0x00,0x3c,0x00,0x63,0xff,0x62,0x00,0x3c,0x00,0x64,0xff,0xcd,0x00,0x3c,0x00,0x67,0xff,0xd3,0x00,0x3c,0x00,0x69, 0xff,0x39,0x00,0x3c,0x00,0x6a,0xff,0x39,0x00,0x3c,0x00,0x6b,0xff,0x39,0x00,0x3c,0x00,0x6c,0xff,0x7f,0x00,0x3c,0x00,0x6d,0xff,0x66,0x00,0x3c,0x00,0x6e,0xff,0x39,0x00,0x3c,0x00,0x6f,0xff,0x4c,0x00,0x3c,0x00,0x70,0xff,0x4c,0x00,0x3c,0x00,0x71,0xff,0x4c,0x00,0x3c,0x00,0x72,0xff,0x4c,0x00,0x3c,0x00,0x73,0xff,0x4c,0x00,0x3c, 0x00,0x77,0x00,0x5a,0x00,0x3c,0x00,0x78,0xff,0x73,0x00,0x3c,0x00,0x79,0xff,0x4c,0x00,0x3c,0x00,0x7a,0xff,0x4c,0x00,0x3c,0x00,0x7b,0xff,0x4c,0x00,0x3c,0x00,0x7c,0xff,0x4c,0x00,0x3c,0x00,0x7d,0xff,0x4c,0x00,0x3c,0x00,0x7e,0xff,0x73,0x00,0x3c,0x00,0x7f,0xff,0x73,0x00,0x3c,0x00,0x80,0xff,0x73,0x00,0x3c,0x00,0x81,0xff,0x73, 0x00,0x3c,0x00,0x91,0xff,0x3f,0x00,0x3c,0x00,0x92,0xff,0xd3,0x00,0x3c,0x00,0xa0,0xff,0x39,0x00,0x3c,0x00,0xa2,0xff,0x1b,0x00,0x3c,0x00,0xaa,0xff,0xcf,0x00,0x3c,0x00,0xac,0xff,0x3d,0x00,0x3c,0x00,0xad,0xff,0x62,0x00,0x3c,0x00,0xae,0xff,0x62,0x00,0x3c,0x00,0xaf,0xff,0xd3,0x00,0x3c,0x00,0xb0,0xff,0xd3,0x00,0x3c,0x00,0xb1, 0xff,0x4c,0x00,0x3c,0x00,0xbe,0xff,0x9a,0x00,0x3c,0x00,0xc4,0xff,0x08,0x00,0x3c,0x00,0xc5,0xff,0x08,0x00,0x3c,0x00,0xc7,0xff,0x62,0x00,0x3c,0x00,0xc9,0xff,0x62,0x00,0x3c,0x00,0xd0,0xff,0xd3,0x00,0x3c,0x00,0xd1,0xff,0xd3,0x00,0x3c,0x00,0xd2,0xff,0xd3,0x00,0x3c,0x00,0xe3,0xff,0xe5,0x00,0x3c,0x00,0xe4,0xff,0x7b,0x00,0x3c, 0x00,0xf7,0xff,0xd3,0x00,0x3c,0x00,0xf8,0xff,0x4c,0x00,0x3c,0x00,0xfa,0xff,0xe5,0x00,0x3c,0x00,0xfb,0xff,0x7b,0x00,0x3c,0x00,0xfc,0xff,0xd3,0x00,0x3c,0x00,0xfd,0xff,0x4c,0x00,0x3c,0x00,0xfe,0xff,0xd3,0x00,0x3c,0x00,0xff,0xff,0x4c,0x00,0x3c,0x01,0x00,0xff,0x4c,0x00,0x3c,0x01,0x03,0xff,0x62,0x00,0x3c,0x01,0x04,0xff,0x7f, 0x00,0x3c,0x01,0x05,0xff,0x62,0x00,0x3c,0x01,0x06,0xff,0x39,0x00,0x3c,0x01,0x08,0xff,0x4c,0x00,0x3c,0x01,0x0b,0xff,0x4c,0x00,0x3c,0x01,0x0d,0xff,0x4c,0x00,0x3c,0x01,0x15,0xff,0x73,0x00,0x3c,0x01,0x17,0xff,0x73,0x00,0x3c,0x01,0x18,0xff,0xd3,0x00,0x3c,0x01,0x19,0xff,0x4c,0x00,0x3c,0x01,0x1b,0xff,0x73,0x00,0x3c,0x01,0x1d, 0xff,0x73,0x00,0x3c,0x01,0x1e,0xff,0xe5,0x00,0x3c,0x01,0x1f,0xff,0x7b,0x00,0x3c,0x01,0x20,0x00,0x27,0x00,0x3c,0x01,0x22,0x00,0x27,0x00,0x3c,0x01,0x25,0xff,0x73,0x00,0x3c,0x01,0x27,0xff,0x73,0x00,0x3c,0x01,0x45,0xff,0x62,0x00,0x3c,0x01,0x46,0xff,0x7f,0x00,0x3c,0x01,0x47,0xff,0xd3,0x00,0x3c,0x01,0x48,0xff,0x4c,0x00,0x3c, 0x01,0x4c,0xff,0x4c,0x00,0x3c,0x01,0x4e,0xff,0x4c,0x00,0x3c,0x01,0x50,0xff,0x4c,0x00,0x3c,0x01,0x51,0xff,0xd3,0x00,0x3c,0x01,0x52,0xff,0x4c,0x00,0x3c,0x01,0x53,0xff,0xd3,0x00,0x3c,0x01,0x54,0xff,0x4c,0x00,0x3c,0x01,0x55,0xff,0xd3,0x00,0x3c,0x01,0x56,0xff,0x4c,0x00,0x3c,0x01,0x5c,0x00,0x5a,0x00,0x3c,0x01,0x5e,0x00,0x5a, 0x00,0x3c,0x01,0x60,0x00,0x5a,0x00,0x3c,0x01,0x63,0xff,0xbe,0x00,0x3c,0x01,0x6d,0xff,0x73,0x00,0x3c,0x01,0x6e,0xff,0xd3,0x00,0x3c,0x01,0x6f,0xff,0x4c,0x00,0x3c,0x01,0x70,0xff,0xd3,0x00,0x3c,0x01,0x71,0xff,0x4c,0x00,0x3c,0x01,0x73,0xff,0x73,0x00,0x3c,0x01,0x74,0xff,0xe5,0x00,0x3c,0x01,0x75,0xff,0x7b,0x00,0x3c,0x01,0x76, 0x00,0x27,0x00,0x3c,0x01,0x79,0xff,0x73,0x00,0x3c,0x01,0x7b,0xff,0x73,0x00,0x3c,0x01,0x7d,0xff,0x73,0x00,0x3c,0x01,0x7f,0xff,0x73,0x00,0x3c,0x01,0x85,0xff,0x62,0x00,0x3c,0x01,0x86,0xff,0x7f,0x00,0x3c,0x01,0x87,0xff,0x62,0x00,0x3c,0x01,0x88,0xff,0x39,0x00,0x3c,0x01,0x89,0xff,0xd3,0x00,0x3c,0x01,0x8a,0xff,0x4c,0x00,0x3c, 0x02,0x3d,0xff,0xe5,0x00,0x3c,0x02,0x3e,0xff,0x7b,0x00,0x3d,0x00,0x2d,0x00,0x52,0x00,0x3d,0x00,0x37,0x00,0x27,0x00,0x3d,0x00,0x5c,0xff,0xcb,0x00,0x3d,0x00,0x77,0x00,0x46,0x00,0x3d,0x00,0xab,0x00,0x27,0x00,0x3d,0x00,0xba,0xff,0xbe,0x00,0x3d,0x00,0xbf,0x00,0x52,0x00,0x3d,0x00,0xeb,0xff,0xcb,0x00,0x3d,0x01,0x20,0x00,0x27, 0x00,0x3d,0x01,0x22,0x00,0x27,0x00,0x3d,0x01,0x5c,0x00,0x46,0x00,0x3d,0x01,0x5e,0x00,0x46,0x00,0x3d,0x01,0x60,0x00,0x46,0x00,0x3d,0x01,0x63,0x00,0x52,0x00,0x3d,0x01,0x76,0x00,0x27,0x00,0x3d,0x01,0x83,0xff,0xcb,0x00,0x3d,0x01,0x93,0xff,0xcb,0x00,0x3e,0x00,0x4d,0x00,0xe9,0x00,0x3e,0x01,0x64,0x00,0xe9,0x00,0x45,0x00,0x44, 0xff,0xe5,0x00,0x45,0x00,0x49,0xff,0xf6,0x00,0x45,0x00,0x5b,0xff,0xe7,0x00,0x45,0x00,0x69,0xff,0xe5,0x00,0x45,0x00,0x6a,0xff,0xe5,0x00,0x45,0x00,0x6b,0xff,0xe5,0x00,0x45,0x00,0x6c,0xff,0xe5,0x00,0x45,0x00,0x6d,0xff,0xe5,0x00,0x45,0x00,0x6e,0xff,0xe5,0x00,0x45,0x00,0xa0,0xff,0xe5,0x00,0x45,0x00,0xc0,0xff,0xf6,0x00,0x45, 0x00,0xc1,0xff,0xf6,0x00,0x45,0x01,0x04,0xff,0xe5,0x00,0x45,0x01,0x06,0xff,0xe5,0x00,0x45,0x01,0x46,0xff,0xe5,0x00,0x45,0x01,0x86,0xff,0xe5,0x00,0x45,0x01,0x88,0xff,0xe5,0x00,0x46,0x00,0x2d,0x00,0x46,0x00,0x46,0x00,0x37,0xff,0x9a,0x00,0x46,0x00,0x3c,0xff,0xb4,0x00,0x46,0x00,0xea,0xff,0xb4,0x00,0x46,0x01,0x20,0xff,0x9a, 0x00,0x46,0x01,0x22,0xff,0x9a,0x00,0x46,0x01,0x63,0x00,0x46,0x00,0x46,0x01,0x76,0xff,0x9a,0x00,0x46,0x01,0x82,0xff,0xb4,0x00,0x46,0x01,0x92,0xff,0xb4,0x00,0x48,0x00,0x05,0xff,0x98,0x00,0x48,0x00,0x0a,0xff,0x98,0x00,0x49,0x00,0x0c,0x00,0x8d,0x00,0x49,0x00,0x0f,0xff,0x7f,0x00,0x49,0x00,0x10,0xff,0x9a,0x00,0x49,0x00,0x11, 0xff,0x7f,0x00,0x49,0x00,0x1d,0x00,0x52,0x00,0x49,0x00,0x1e,0x00,0x52,0x00,0x49,0x00,0x22,0x00,0x42,0x00,0x49,0x00,0x40,0x00,0x8d,0x00,0x49,0x00,0x45,0x00,0x12,0x00,0x49,0x00,0x4b,0x00,0x12,0x00,0x49,0x00,0x57,0x00,0x25,0x00,0x49,0x00,0x59,0x00,0x27,0x00,0x49,0x00,0x5a,0x00,0x27,0x00,0x49,0x00,0x5b,0x00,0x12,0x00,0x49, 0x00,0x5c,0x00,0x21,0x00,0x49,0x00,0x60,0x00,0x52,0x00,0x49,0x00,0x75,0x00,0x2d,0x00,0x49,0x00,0x76,0x00,0x12,0x00,0x49,0x00,0x77,0x00,0x79,0x00,0x49,0x00,0x8d,0x00,0x93,0x00,0x49,0x00,0xab,0x00,0x27,0x00,0x49,0x00,0xac,0xff,0x7f,0x00,0x49,0x00,0xb4,0x00,0x5e,0x00,0x49,0x00,0xb5,0x00,0x52,0x00,0x49,0x00,0xb6,0x00,0x5e, 0x00,0x49,0x00,0xb7,0x00,0x52,0x00,0x49,0x00,0xbf,0x00,0x27,0x00,0x49,0x00,0xc4,0xff,0xb0,0x00,0x49,0x00,0xc5,0xff,0xb0,0x00,0x49,0x00,0xeb,0x00,0x21,0x00,0x49,0x00,0xed,0x00,0x12,0x00,0x49,0x01,0x21,0x00,0x25,0x00,0x49,0x01,0x23,0x00,0x25,0x00,0x49,0x01,0x58,0x00,0x12,0x00,0x49,0x01,0x5a,0x00,0x12,0x00,0x49,0x01,0x5c, 0x00,0x79,0x00,0x49,0x01,0x5e,0x00,0x79,0x00,0x49,0x01,0x60,0x00,0x79,0x00,0x49,0x01,0x77,0x00,0x25,0x00,0x49,0x01,0x81,0x00,0x27,0x00,0x49,0x01,0x83,0x00,0x21,0x00,0x49,0x01,0x8d,0x00,0x27,0x00,0x49,0x01,0x8f,0x00,0x27,0x00,0x49,0x01,0x91,0x00,0x27,0x00,0x49,0x01,0x93,0x00,0x21,0x00,0x4a,0x00,0x4d,0x00,0x2f,0x00,0x4a, 0x01,0x64,0x00,0x2f,0x00,0x4d,0x00,0x4d,0x00,0x23,0x00,0x4d,0x01,0x64,0x00,0x23,0x00,0x4e,0x00,0x0f,0x00,0x52,0x00,0x4e,0x00,0x10,0xff,0x75,0x00,0x4e,0x00,0x11,0x00,0x52,0x00,0x4e,0x00,0x1d,0x00,0x52,0x00,0x4e,0x00,0x1e,0x00,0x52,0x00,0x4e,0x00,0x46,0xff,0xd7,0x00,0x4e,0x00,0x47,0xff,0xe5,0x00,0x4e,0x00,0x48,0xff,0xd7, 0x00,0x4e,0x00,0x4a,0xff,0xd7,0x00,0x4e,0x00,0x52,0xff,0xd7,0x00,0x4e,0x00,0x54,0xff,0xe5,0x00,0x4e,0x00,0x57,0xff,0xf0,0x00,0x4e,0x00,0x6f,0xff,0xe5,0x00,0x4e,0x00,0x70,0xff,0xd7,0x00,0x4e,0x00,0x71,0xff,0xd7,0x00,0x4e,0x00,0x72,0xff,0xd7,0x00,0x4e,0x00,0x73,0xff,0xd7,0x00,0x4e,0x00,0x79,0xff,0xd7,0x00,0x4e,0x00,0x7a, 0xff,0xd7,0x00,0x4e,0x00,0x7b,0xff,0xd7,0x00,0x4e,0x00,0x7c,0xff,0xd7,0x00,0x4e,0x00,0x7d,0xff,0xd7,0x00,0x4e,0x00,0xac,0x00,0x52,0x00,0x4e,0x00,0xb1,0xff,0xd7,0x00,0x4e,0x00,0xf8,0xff,0xd7,0x00,0x4e,0x00,0xfd,0xff,0xd7,0x00,0x4e,0x00,0xff,0xff,0xd7,0x00,0x4e,0x01,0x00,0xff,0xe5,0x00,0x4e,0x01,0x08,0xff,0xe5,0x00,0x4e, 0x01,0x0b,0xff,0xd7,0x00,0x4e,0x01,0x0d,0xff,0xd7,0x00,0x4e,0x01,0x19,0xff,0xd7,0x00,0x4e,0x01,0x21,0xff,0xf0,0x00,0x4e,0x01,0x23,0xff,0xf0,0x00,0x4e,0x01,0x48,0xff,0xd7,0x00,0x4e,0x01,0x4c,0xff,0xd7,0x00,0x4e,0x01,0x4e,0xff,0xd7,0x00,0x4e,0x01,0x50,0xff,0xd7,0x00,0x4e,0x01,0x52,0xff,0xd7,0x00,0x4e,0x01,0x54,0xff,0xd7, 0x00,0x4e,0x01,0x56,0xff,0xd7,0x00,0x4e,0x01,0x6f,0xff,0xd7,0x00,0x4e,0x01,0x71,0xff,0xd7,0x00,0x4e,0x01,0x77,0xff,0xf0,0x00,0x4e,0x01,0x8a,0xff,0xd7,0x00,0x51,0x00,0x05,0xff,0x98,0x00,0x51,0x00,0x0a,0xff,0x98,0x00,0x52,0x00,0x05,0xff,0x6f,0x00,0x52,0x00,0x0a,0xff,0x6f,0x00,0x52,0x00,0x44,0xff,0xe5,0x00,0x52,0x00,0x49, 0xff,0xdb,0x00,0x52,0x00,0x5b,0xff,0xe7,0x00,0x52,0x00,0x69,0xff,0xe5,0x00,0x52,0x00,0x6a,0xff,0xe5,0x00,0x52,0x00,0x6b,0xff,0xe5,0x00,0x52,0x00,0x6c,0xff,0xe5,0x00,0x52,0x00,0x6d,0xff,0xe5,0x00,0x52,0x00,0x6e,0xff,0xe5,0x00,0x52,0x00,0xa0,0xff,0xe5,0x00,0x52,0x00,0xb4,0xff,0xb2,0x00,0x52,0x00,0xb5,0xff,0x7d,0x00,0x52, 0x00,0xb6,0xff,0xbe,0x00,0x52,0x00,0xb7,0xff,0x7d,0x00,0x52,0x00,0xc0,0xff,0xe7,0x00,0x52,0x00,0xc1,0xff,0xe7,0x00,0x52,0x01,0x04,0xff,0xe5,0x00,0x52,0x01,0x06,0xff,0xe5,0x00,0x52,0x01,0x46,0xff,0xe5,0x00,0x52,0x01,0x86,0xff,0xe5,0x00,0x52,0x01,0x88,0xff,0xe5,0x00,0x53,0x00,0x44,0xff,0xe5,0x00,0x53,0x00,0x49,0xff,0xdb, 0x00,0x53,0x00,0x5b,0xff,0xe7,0x00,0x53,0x00,0x69,0xff,0xe5,0x00,0x53,0x00,0x6a,0xff,0xe5,0x00,0x53,0x00,0x6b,0xff,0xe5,0x00,0x53,0x00,0x6c,0xff,0xe5,0x00,0x53,0x00,0x6d,0xff,0xe5,0x00,0x53,0x00,0x6e,0xff,0xe5,0x00,0x53,0x00,0xa0,0xff,0xe5,0x00,0x53,0x00,0xb4,0xff,0xcb,0x00,0x53,0x00,0xb5,0xff,0x89,0x00,0x53,0x00,0xb6, 0xff,0x89,0x00,0x53,0x00,0xb7,0xff,0x89,0x00,0x53,0x00,0xc0,0xff,0xe7,0x00,0x53,0x00,0xc1,0xff,0xe7,0x00,0x53,0x01,0x04,0xff,0xe5,0x00,0x53,0x01,0x06,0xff,0xe5,0x00,0x53,0x01,0x46,0xff,0xe5,0x00,0x53,0x01,0x86,0xff,0xe5,0x00,0x53,0x01,0x88,0xff,0xe5,0x00,0x54,0x00,0x4d,0x00,0x66,0x00,0x54,0x01,0x64,0x00,0x66,0x00,0x55, 0x00,0x0f,0xff,0x62,0x00,0x55,0x00,0x10,0xff,0x7f,0x00,0x55,0x00,0x11,0xff,0x56,0x00,0x55,0x00,0x1d,0x00,0x52,0x00,0x55,0x00,0x1e,0x00,0x52,0x00,0x55,0x00,0x46,0xff,0xe5,0x00,0x55,0x00,0x47,0xff,0xe5,0x00,0x55,0x00,0x48,0xff,0xe5,0x00,0x55,0x00,0x49,0x00,0x27,0x00,0x55,0x00,0x4a,0xff,0xe5,0x00,0x55,0x00,0x50,0xff,0xfc, 0x00,0x55,0x00,0x51,0xff,0xfc,0x00,0x55,0x00,0x52,0xff,0xe5,0x00,0x55,0x00,0x54,0xff,0xe5,0x00,0x55,0x00,0x56,0x00,0x0e,0x00,0x55,0x00,0x57,0x00,0x3b,0x00,0x55,0x00,0x59,0x00,0x52,0x00,0x55,0x00,0x5a,0x00,0x52,0x00,0x55,0x00,0x5b,0x00,0x3b,0x00,0x55,0x00,0x5c,0x00,0x52,0x00,0x55,0x00,0x5d,0x00,0x27,0x00,0x55,0x00,0x6f, 0xff,0xe5,0x00,0x55,0x00,0x70,0xff,0xe5,0x00,0x55,0x00,0x71,0xff,0xe5,0x00,0x55,0x00,0x72,0xff,0xe5,0x00,0x55,0x00,0x73,0xff,0xe5,0x00,0x55,0x00,0x79,0xff,0xe5,0x00,0x55,0x00,0x7a,0xff,0xe5,0x00,0x55,0x00,0x7b,0xff,0xe5,0x00,0x55,0x00,0x7c,0xff,0xe5,0x00,0x55,0x00,0x7d,0xff,0xe5,0x00,0x55,0x00,0xac,0xff,0x56,0x00,0x55, 0x00,0xb1,0xff,0xe5,0x00,0x55,0x00,0xb4,0x00,0xa4,0x00,0x55,0x00,0xb5,0x00,0x79,0x00,0x55,0x00,0xb6,0x00,0xa4,0x00,0x55,0x00,0xb7,0x00,0x79,0x00,0x55,0x00,0xc4,0xff,0x62,0x00,0x55,0x00,0xc5,0xff,0x62,0x00,0x55,0x00,0xe4,0x00,0x0e,0x00,0x55,0x00,0xe6,0x00,0x27,0x00,0x55,0x00,0xeb,0x00,0x52,0x00,0x55,0x00,0xf8,0xff,0xe5, 0x00,0x55,0x00,0xfb,0x00,0x0e,0x00,0x55,0x00,0xfd,0xff,0xe5,0x00,0x55,0x00,0xff,0xff,0xe5,0x00,0x55,0x01,0x00,0xff,0xe5,0x00,0x55,0x01,0x08,0xff,0xe5,0x00,0x55,0x01,0x0b,0xff,0xe5,0x00,0x55,0x01,0x0d,0xff,0xe5,0x00,0x55,0x01,0x19,0xff,0xe5,0x00,0x55,0x01,0x1f,0x00,0x0e,0x00,0x55,0x01,0x21,0x00,0x3b,0x00,0x55,0x01,0x23, 0x00,0x3b,0x00,0x55,0x01,0x29,0x00,0x27,0x00,0x55,0x01,0x2b,0x00,0x27,0x00,0x55,0x01,0x48,0xff,0xe5,0x00,0x55,0x01,0x4c,0xff,0xe5,0x00,0x55,0x01,0x4e,0xff,0xe5,0x00,0x55,0x01,0x50,0xff,0xe5,0x00,0x55,0x01,0x52,0xff,0xe5,0x00,0x55,0x01,0x54,0xff,0xe5,0x00,0x55,0x01,0x56,0xff,0xe5,0x00,0x55,0x01,0x6d,0xff,0xfc,0x00,0x55, 0x01,0x6f,0xff,0xe5,0x00,0x55,0x01,0x71,0xff,0xe5,0x00,0x55,0x01,0x75,0x00,0x0e,0x00,0x55,0x01,0x77,0x00,0x3b,0x00,0x55,0x01,0x81,0x00,0x52,0x00,0x55,0x01,0x83,0x00,0x52,0x00,0x55,0x01,0x8a,0xff,0xe5,0x00,0x55,0x01,0x8d,0x00,0x52,0x00,0x55,0x01,0x8f,0x00,0x52,0x00,0x55,0x01,0x91,0x00,0x52,0x00,0x55,0x01,0x93,0x00,0x52, 0x00,0x55,0x02,0x3e,0x00,0x0e,0x00,0x57,0x00,0x10,0xff,0x8f,0x00,0x57,0x00,0x22,0xff,0xcb,0x00,0x57,0x00,0x46,0xff,0xe5,0x00,0x57,0x00,0x47,0xff,0xe5,0x00,0x57,0x00,0x48,0xff,0xf0,0x00,0x57,0x00,0x4a,0xff,0xf0,0x00,0x57,0x00,0x52,0xff,0xf0,0x00,0x57,0x00,0x54,0xff,0xf0,0x00,0x57,0x00,0x5b,0x00,0x1d,0x00,0x57,0x00,0x6f, 0xff,0xe5,0x00,0x57,0x00,0x70,0xff,0xf0,0x00,0x57,0x00,0x71,0xff,0xf0,0x00,0x57,0x00,0x72,0xff,0xf0,0x00,0x57,0x00,0x73,0xff,0xf0,0x00,0x57,0x00,0x79,0xff,0xf0,0x00,0x57,0x00,0x7a,0xff,0xf0,0x00,0x57,0x00,0x7b,0xff,0xf0,0x00,0x57,0x00,0x7c,0xff,0xf0,0x00,0x57,0x00,0x7d,0xff,0xf0,0x00,0x57,0x00,0xab,0x00,0x27,0x00,0x57, 0x00,0xb1,0xff,0xf0,0x00,0x57,0x00,0xbf,0x00,0x27,0x00,0x57,0x00,0xf8,0xff,0xf0,0x00,0x57,0x00,0xfd,0xff,0xe5,0x00,0x57,0x00,0xff,0xff,0xe5,0x00,0x57,0x01,0x00,0xff,0xe5,0x00,0x57,0x01,0x08,0xff,0xe5,0x00,0x57,0x01,0x0b,0xff,0xf0,0x00,0x57,0x01,0x0d,0xff,0xf0,0x00,0x57,0x01,0x19,0xff,0xf0,0x00,0x57,0x01,0x48,0xff,0xe5, 0x00,0x57,0x01,0x4c,0xff,0xf0,0x00,0x57,0x01,0x4e,0xff,0xf0,0x00,0x57,0x01,0x50,0xff,0xf0,0x00,0x57,0x01,0x52,0xff,0xf0,0x00,0x57,0x01,0x54,0xff,0xf0,0x00,0x57,0x01,0x56,0xff,0xf0,0x00,0x57,0x01,0x6f,0xff,0xf0,0x00,0x57,0x01,0x71,0xff,0xf0,0x00,0x57,0x01,0x8a,0xff,0xf0,0x00,0x58,0x00,0x05,0xff,0xbe,0x00,0x58,0x00,0x0a, 0xff,0xbe,0x00,0x59,0x00,0x0f,0xff,0x8b,0x00,0x59,0x00,0x11,0xff,0x7f,0x00,0x59,0x00,0x44,0xff,0xdb,0x00,0x59,0x00,0x46,0xff,0xf4,0x00,0x59,0x00,0x47,0xff,0xf0,0x00,0x59,0x00,0x48,0xff,0xf4,0x00,0x59,0x00,0x4a,0xff,0xf4,0x00,0x59,0x00,0x52,0xff,0xf4,0x00,0x59,0x00,0x54,0xff,0xf0,0x00,0x59,0x00,0x69,0xff,0xdb,0x00,0x59, 0x00,0x6a,0xff,0xdb,0x00,0x59,0x00,0x6b,0xff,0xdb,0x00,0x59,0x00,0x6c,0xff,0xdb,0x00,0x59,0x00,0x6d,0xff,0xdb,0x00,0x59,0x00,0x6e,0xff,0xdb,0x00,0x59,0x00,0x6f,0xff,0xf4,0x00,0x59,0x00,0x70,0xff,0xf4,0x00,0x59,0x00,0x71,0xff,0xf4,0x00,0x59,0x00,0x72,0xff,0xf4,0x00,0x59,0x00,0x73,0xff,0xf4,0x00,0x59,0x00,0x79,0xff,0xf4, 0x00,0x59,0x00,0x7a,0xff,0xf4,0x00,0x59,0x00,0x7b,0xff,0xf4,0x00,0x59,0x00,0x7c,0xff,0xf4,0x00,0x59,0x00,0x7d,0xff,0xf4,0x00,0x59,0x00,0xa0,0xff,0xdb,0x00,0x59,0x00,0xac,0xff,0x7f,0x00,0x59,0x00,0xb1,0xff,0xf4,0x00,0x59,0x00,0xc4,0xff,0x8b,0x00,0x59,0x00,0xc5,0xff,0x7f,0x00,0x59,0x00,0xf8,0xff,0xf4,0x00,0x59,0x00,0xfd, 0xff,0xf4,0x00,0x59,0x00,0xff,0xff,0xf4,0x00,0x59,0x01,0x00,0xff,0xf0,0x00,0x59,0x01,0x04,0xff,0xdb,0x00,0x59,0x01,0x06,0xff,0xdb,0x00,0x59,0x01,0x08,0xff,0xf0,0x00,0x59,0x01,0x0b,0xff,0xf4,0x00,0x59,0x01,0x0d,0xff,0xf4,0x00,0x59,0x01,0x19,0xff,0xf4,0x00,0x59,0x01,0x46,0xff,0xdb,0x00,0x59,0x01,0x48,0xff,0xf4,0x00,0x59, 0x01,0x4c,0xff,0xf4,0x00,0x59,0x01,0x4e,0xff,0xf4,0x00,0x59,0x01,0x50,0xff,0xf4,0x00,0x59,0x01,0x52,0xff,0xf4,0x00,0x59,0x01,0x54,0xff,0xf4,0x00,0x59,0x01,0x56,0xff,0xf4,0x00,0x59,0x01,0x6f,0xff,0xf4,0x00,0x59,0x01,0x71,0xff,0xf4,0x00,0x59,0x01,0x86,0xff,0xdb,0x00,0x59,0x01,0x88,0xff,0xdb,0x00,0x59,0x01,0x8a,0xff,0xf4, 0x00,0x5a,0x00,0x0f,0xff,0xa6,0x00,0x5a,0x00,0x11,0xff,0x9a,0x00,0x5a,0x00,0x46,0xff,0xfa,0x00,0x5a,0x00,0x47,0xff,0xf6,0x00,0x5a,0x00,0x48,0xff,0xf6,0x00,0x5a,0x00,0x4a,0xff,0xfa,0x00,0x5a,0x00,0x52,0xff,0xfa,0x00,0x5a,0x00,0x54,0xff,0xf6,0x00,0x5a,0x00,0x6f,0xff,0xfa,0x00,0x5a,0x00,0x70,0xff,0xf6,0x00,0x5a,0x00,0x71, 0xff,0xf6,0x00,0x5a,0x00,0x72,0xff,0xf6,0x00,0x5a,0x00,0x73,0xff,0xf6,0x00,0x5a,0x00,0x79,0xff,0xfa,0x00,0x5a,0x00,0x7a,0xff,0xfa,0x00,0x5a,0x00,0x7b,0xff,0xfa,0x00,0x5a,0x00,0x7c,0xff,0xfa,0x00,0x5a,0x00,0x7d,0xff,0xfa,0x00,0x5a,0x00,0xac,0xff,0x9a,0x00,0x5a,0x00,0xb1,0xff,0xfa,0x00,0x5a,0x00,0xc4,0xff,0xb4,0x00,0x5a, 0x00,0xc5,0xff,0xb4,0x00,0x5a,0x00,0xf8,0xff,0xfa,0x00,0x5a,0x00,0xfd,0xff,0xfa,0x00,0x5a,0x00,0xff,0xff,0xfa,0x00,0x5a,0x01,0x00,0xff,0xf6,0x00,0x5a,0x01,0x08,0xff,0xf6,0x00,0x5a,0x01,0x0b,0xff,0xf6,0x00,0x5a,0x01,0x0d,0xff,0xf6,0x00,0x5a,0x01,0x19,0xff,0xfa,0x00,0x5a,0x01,0x48,0xff,0xfa,0x00,0x5a,0x01,0x4c,0xff,0xf6, 0x00,0x5a,0x01,0x4e,0xff,0xf6,0x00,0x5a,0x01,0x50,0xff,0xf6,0x00,0x5a,0x01,0x52,0xff,0xfa,0x00,0x5a,0x01,0x54,0xff,0xfa,0x00,0x5a,0x01,0x56,0xff,0xfa,0x00,0x5a,0x01,0x6f,0xff,0xfa,0x00,0x5a,0x01,0x71,0xff,0xfa,0x00,0x5a,0x01,0x8a,0xff,0xfa,0x00,0x5b,0x00,0x46,0xff,0xf0,0x00,0x5b,0x00,0x47,0xff,0xf0,0x00,0x5b,0x00,0x48, 0xff,0xf0,0x00,0x5b,0x00,0x4a,0xff,0xf0,0x00,0x5b,0x00,0x52,0xff,0xf0,0x00,0x5b,0x00,0x54,0xff,0xf0,0x00,0x5b,0x00,0x6f,0xff,0xf0,0x00,0x5b,0x00,0x70,0xff,0xf0,0x00,0x5b,0x00,0x71,0xff,0xf0,0x00,0x5b,0x00,0x72,0xff,0xf0,0x00,0x5b,0x00,0x73,0xff,0xf0,0x00,0x5b,0x00,0x79,0xff,0xf0,0x00,0x5b,0x00,0x7a,0xff,0xf0,0x00,0x5b, 0x00,0x7b,0xff,0xf0,0x00,0x5b,0x00,0x7c,0xff,0xf0,0x00,0x5b,0x00,0x7d,0xff,0xf0,0x00,0x5b,0x00,0xb1,0xff,0xf0,0x00,0x5b,0x00,0xf8,0xff,0xf0,0x00,0x5b,0x00,0xfd,0xff,0xf0,0x00,0x5b,0x00,0xff,0xff,0xf0,0x00,0x5b,0x01,0x00,0xff,0xf0,0x00,0x5b,0x01,0x08,0xff,0xf0,0x00,0x5b,0x01,0x0b,0xff,0xf0,0x00,0x5b,0x01,0x0d,0xff,0xf0, 0x00,0x5b,0x01,0x19,0xff,0xf0,0x00,0x5b,0x01,0x48,0xff,0xf0,0x00,0x5b,0x01,0x4c,0xff,0xf0,0x00,0x5b,0x01,0x4e,0xff,0xf0,0x00,0x5b,0x01,0x50,0xff,0xf0,0x00,0x5b,0x01,0x52,0xff,0xf0,0x00,0x5b,0x01,0x54,0xff,0xf0,0x00,0x5b,0x01,0x56,0xff,0xf0,0x00,0x5b,0x01,0x6f,0xff,0xf0,0x00,0x5b,0x01,0x71,0xff,0xf0,0x00,0x5b,0x01,0x8a, 0xff,0xf0,0x00,0x5c,0x00,0x05,0x00,0x1d,0x00,0x5c,0x00,0x0a,0x00,0x1d,0x00,0x5c,0x00,0x0f,0xff,0x9a,0x00,0x5c,0x00,0x11,0xff,0x81,0x00,0x5c,0x00,0x22,0xff,0xb4,0x00,0x5c,0x00,0x46,0xff,0xf6,0x00,0x5c,0x00,0x47,0xff,0xf6,0x00,0x5c,0x00,0x48,0xff,0xf6,0x00,0x5c,0x00,0x49,0x00,0x04,0x00,0x5c,0x00,0x4a,0xff,0xf6,0x00,0x5c, 0x00,0x52,0xff,0xf6,0x00,0x5c,0x00,0x54,0xff,0xf6,0x00,0x5c,0x00,0x57,0x00,0x06,0x00,0x5c,0x00,0x6f,0xff,0xf6,0x00,0x5c,0x00,0x70,0xff,0xf6,0x00,0x5c,0x00,0x71,0xff,0xf6,0x00,0x5c,0x00,0x72,0xff,0xf6,0x00,0x5c,0x00,0x73,0xff,0xf6,0x00,0x5c,0x00,0x79,0xff,0xf6,0x00,0x5c,0x00,0x7a,0xff,0xf6,0x00,0x5c,0x00,0x7b,0xff,0xf6, 0x00,0x5c,0x00,0x7c,0xff,0xf6,0x00,0x5c,0x00,0x7d,0xff,0xf6,0x00,0x5c,0x00,0xac,0xff,0x81,0x00,0x5c,0x00,0xb1,0xff,0xf6,0x00,0x5c,0x00,0xbf,0x00,0x0c,0x00,0x5c,0x00,0xc4,0xff,0x8d,0x00,0x5c,0x00,0xc5,0xff,0x8d,0x00,0x5c,0x00,0xf8,0xff,0xf6,0x00,0x5c,0x00,0xfd,0xff,0xf6,0x00,0x5c,0x00,0xff,0xff,0xf6,0x00,0x5c,0x01,0x00, 0xff,0xf6,0x00,0x5c,0x01,0x08,0xff,0xf6,0x00,0x5c,0x01,0x0b,0xff,0xf6,0x00,0x5c,0x01,0x0d,0xff,0xf6,0x00,0x5c,0x01,0x19,0xff,0xf6,0x00,0x5c,0x01,0x21,0x00,0x06,0x00,0x5c,0x01,0x23,0x00,0x06,0x00,0x5c,0x01,0x48,0xff,0xf6,0x00,0x5c,0x01,0x4c,0xff,0xf6,0x00,0x5c,0x01,0x4e,0xff,0xf6,0x00,0x5c,0x01,0x50,0xff,0xf6,0x00,0x5c, 0x01,0x52,0xff,0xf6,0x00,0x5c,0x01,0x54,0xff,0xf6,0x00,0x5c,0x01,0x56,0xff,0xf6,0x00,0x5c,0x01,0x6f,0xff,0xf6,0x00,0x5c,0x01,0x71,0xff,0xf6,0x00,0x5c,0x01,0x77,0x00,0x06,0x00,0x5c,0x01,0x8a,0xff,0xf6,0x00,0x5e,0x00,0x4d,0x00,0xcb,0x00,0x5e,0x01,0x64,0x00,0xcb,0x00,0x62,0x00,0x2d,0x00,0x5e,0x00,0x62,0x00,0x37,0xff,0x6d, 0x00,0x62,0x00,0x39,0xff,0x8b,0x00,0x62,0x00,0x3a,0xff,0xb0,0x00,0x62,0x00,0x3c,0xff,0x64,0x00,0x62,0x00,0xea,0xff,0x64,0x00,0x62,0x01,0x20,0xff,0x6d,0x00,0x62,0x01,0x22,0xff,0x6d,0x00,0x62,0x01,0x63,0x00,0x5e,0x00,0x62,0x01,0x76,0xff,0x6d,0x00,0x62,0x01,0x80,0xff,0xb0,0x00,0x62,0x01,0x82,0xff,0x64,0x00,0x62,0x01,0x8c, 0xff,0xb0,0x00,0x62,0x01,0x8e,0xff,0xb0,0x00,0x62,0x01,0x90,0xff,0xb0,0x00,0x62,0x01,0x92,0xff,0x64,0x00,0x63,0x00,0x2d,0x00,0x5e,0x00,0x63,0x00,0x37,0xff,0x6d,0x00,0x63,0x00,0x39,0xff,0x8b,0x00,0x63,0x00,0x3a,0xff,0xb6,0x00,0x63,0x00,0x3c,0xff,0x64,0x00,0x63,0x00,0xea,0xff,0x64,0x00,0x63,0x01,0x20,0xff,0x6d,0x00,0x63, 0x01,0x22,0xff,0x6d,0x00,0x63,0x01,0x63,0x00,0x5e,0x00,0x63,0x01,0x76,0xff,0x6d,0x00,0x63,0x01,0x80,0xff,0xb6,0x00,0x63,0x01,0x82,0xff,0x64,0x00,0x63,0x01,0x8c,0xff,0xb6,0x00,0x63,0x01,0x8e,0xff,0xb6,0x00,0x63,0x01,0x90,0xff,0xb6,0x00,0x63,0x01,0x92,0xff,0x64,0x00,0x64,0x00,0x26,0xff,0xc9,0x00,0x64,0x00,0x2a,0xff,0xc9, 0x00,0x64,0x00,0x32,0xff,0xc9,0x00,0x64,0x00,0x34,0xff,0xc9,0x00,0x64,0x00,0xf7,0xff,0xc9,0x00,0x64,0x00,0xfc,0xff,0xc9,0x00,0x64,0x00,0xfe,0xff,0xc9,0x00,0x64,0x01,0x18,0xff,0xc9,0x00,0x64,0x01,0x47,0xff,0xc9,0x00,0x64,0x01,0x51,0xff,0xc9,0x00,0x64,0x01,0x53,0xff,0xc9,0x00,0x64,0x01,0x55,0xff,0xc9,0x00,0x64,0x01,0x6e, 0xff,0xc9,0x00,0x64,0x01,0x70,0xff,0xc9,0x00,0x64,0x01,0x89,0xff,0xc9,0x00,0x65,0x00,0x2d,0x00,0x3d,0x00,0x65,0x01,0x63,0x00,0x3d,0x00,0x67,0x00,0x24,0xff,0xe5,0x00,0x67,0x00,0x37,0xff,0xa4,0x00,0x67,0x00,0x3b,0xff,0xdb,0x00,0x67,0x00,0x3d,0xff,0xcf,0x00,0x67,0x00,0xe5,0xff,0xcf,0x00,0x67,0x01,0x03,0xff,0xe5,0x00,0x67, 0x01,0x05,0xff,0xe5,0x00,0x67,0x01,0x20,0xff,0xa4,0x00,0x67,0x01,0x22,0xff,0xa4,0x00,0x67,0x01,0x28,0xff,0xcf,0x00,0x67,0x01,0x2a,0xff,0xcf,0x00,0x67,0x01,0x45,0xff,0xe5,0x00,0x67,0x01,0x76,0xff,0xa4,0x00,0x67,0x01,0x85,0xff,0xe5,0x00,0x67,0x01,0x87,0xff,0xe5,0x00,0x79,0x00,0x44,0xff,0xe5,0x00,0x79,0x00,0x49,0xff,0xe7, 0x00,0x79,0x00,0x5b,0xff,0xe5,0x00,0x79,0x00,0xc0,0xff,0xe7,0x00,0x79,0x00,0xc1,0xff,0xe7,0x00,0x79,0x01,0x06,0xff,0xe5,0x00,0x79,0x01,0x88,0xff,0xe5,0x00,0x7a,0x00,0x44,0xff,0xe5,0x00,0x7a,0x00,0x49,0xff,0xe7,0x00,0x7a,0x00,0x5b,0xff,0xe5,0x00,0x7a,0x00,0xc0,0xff,0xe7,0x00,0x7a,0x00,0xc1,0xff,0xe7,0x00,0x7a,0x01,0x06, 0xff,0xe5,0x00,0x7a,0x01,0x88,0xff,0xe5,0x00,0x7b,0x00,0x44,0xff,0xe5,0x00,0x7b,0x00,0x49,0xff,0xe7,0x00,0x7b,0x00,0x5b,0xff,0xe5,0x00,0x7b,0x00,0xc0,0xff,0xe7,0x00,0x7b,0x00,0xc1,0xff,0xe7,0x00,0x7b,0x01,0x06,0xff,0xe5,0x00,0x7b,0x01,0x88,0xff,0xe5,0x00,0x7c,0x00,0x44,0xff,0xe5,0x00,0x7c,0x00,0x49,0xff,0xe7,0x00,0x7c, 0x00,0x5b,0xff,0xe5,0x00,0x7c,0x00,0xc0,0xff,0xe7,0x00,0x7c,0x00,0xc1,0xff,0xe7,0x00,0x7c,0x01,0x06,0xff,0xe5,0x00,0x7c,0x01,0x88,0xff,0xe5,0x00,0x7d,0x00,0x44,0xff,0xe5,0x00,0x7d,0x00,0x49,0xff,0xe7,0x00,0x7d,0x00,0x5b,0xff,0xe5,0x00,0x7d,0x00,0xc0,0xff,0xe7,0x00,0x7d,0x00,0xc1,0xff,0xe7,0x00,0x7d,0x01,0x06,0xff,0xe5, 0x00,0x7d,0x01,0x88,0xff,0xe5,0x00,0x91,0x00,0x2d,0x00,0x0e,0x00,0x91,0x01,0x63,0x00,0x0e,0x00,0x92,0x00,0x24,0xff,0xe5,0x00,0x92,0x00,0x37,0xff,0xa4,0x00,0x92,0x00,0x3b,0xff,0xdb,0x00,0x92,0x00,0x3d,0xff,0xcf,0x00,0x92,0x00,0xe5,0xff,0xcf,0x00,0x92,0x01,0x03,0xff,0xe5,0x00,0x92,0x01,0x05,0xff,0xe5,0x00,0x92,0x01,0x20, 0xff,0xa4,0x00,0x92,0x01,0x22,0xff,0xa4,0x00,0x92,0x01,0x28,0xff,0xcf,0x00,0x92,0x01,0x2a,0xff,0xcf,0x00,0x92,0x01,0x45,0xff,0xe5,0x00,0x92,0x01,0x76,0xff,0xa4,0x00,0x92,0x01,0x85,0xff,0xe5,0x00,0x92,0x01,0x87,0xff,0xe5,0x00,0xa1,0x00,0x44,0xff,0xe5,0x00,0xa1,0x00,0x49,0xff,0xe7,0x00,0xa1,0x00,0x5b,0xff,0xe5,0x00,0xa1, 0x00,0xc0,0xff,0xe7,0x00,0xa1,0x00,0xc1,0xff,0xe7,0x00,0xa1,0x01,0x06,0xff,0xe5,0x00,0xa1,0x01,0x88,0xff,0xe5,0x00,0xa2,0x00,0x3c,0xff,0x9a,0x00,0xa2,0x00,0x4d,0x00,0xbc,0x00,0xa2,0x00,0xea,0xff,0x9a,0x00,0xa2,0x01,0x64,0x00,0xbc,0x00,0xa2,0x01,0x82,0xff,0x9a,0x00,0xa2,0x01,0x92,0xff,0x9a,0x00,0xa4,0x00,0x4d,0x00,0xa0, 0x00,0xa4,0x01,0x33,0xff,0xdb,0x00,0xa4,0x01,0x64,0x00,0xa0,0x00,0xa4,0x02,0x37,0xff,0xdb,0x00,0xa9,0x00,0x0d,0xff,0x7f,0x00,0xa9,0x00,0x8d,0xff,0x98,0x00,0xa9,0x00,0xb4,0xff,0x66,0x00,0xa9,0x00,0xb5,0xff,0x3d,0x00,0xa9,0x00,0xb6,0xff,0x66,0x00,0xa9,0x00,0xb7,0xff,0x3d,0x00,0xa9,0x01,0x2d,0xff,0xd5,0x00,0xa9,0x01,0x2e, 0xff,0xd5,0x00,0xa9,0x01,0x33,0xff,0xa4,0x00,0xa9,0x01,0xb4,0xff,0xd5,0x00,0xa9,0x01,0xb7,0x00,0x3d,0x00,0xa9,0x01,0xb8,0xff,0x66,0x00,0xa9,0x01,0xb9,0xff,0x66,0x00,0xa9,0x01,0xba,0x00,0x3d,0x00,0xa9,0x01,0xbb,0xff,0x79,0x00,0xa9,0x01,0xbc,0x00,0x12,0x00,0xa9,0x01,0xbe,0xff,0x66,0x00,0xa9,0x01,0xc3,0xff,0xf6,0x00,0xa9, 0x01,0xc5,0xff,0xb6,0x00,0xa9,0x01,0xc8,0xff,0xf4,0x00,0xa9,0x01,0xcb,0x00,0x3d,0x00,0xa9,0x01,0xcd,0xff,0xdb,0x00,0xa9,0x01,0xd2,0xff,0xf6,0x00,0xa9,0x01,0xd3,0xff,0xc1,0x00,0xa9,0x01,0xd4,0xff,0xf6,0x00,0xa9,0x01,0xd7,0xff,0xf6,0x00,0xa9,0x01,0xd9,0xff,0xf6,0x00,0xaa,0x00,0x2d,0x00,0x52,0x00,0xaa,0x00,0x37,0xff,0xcf, 0x00,0xaa,0x00,0x3a,0x00,0x52,0x00,0xaa,0x00,0x3d,0x00,0x52,0x00,0xaa,0x00,0x5c,0x00,0x0c,0x00,0xaa,0x00,0xe5,0x00,0x52,0x00,0xaa,0x00,0xeb,0x00,0x0c,0x00,0xaa,0x01,0x20,0xff,0xcf,0x00,0xaa,0x01,0x22,0xff,0xcf,0x00,0xaa,0x01,0x28,0x00,0x52,0x00,0xaa,0x01,0x2a,0x00,0x52,0x00,0xaa,0x01,0x63,0x00,0x52,0x00,0xaa,0x01,0x76, 0xff,0xcf,0x00,0xaa,0x01,0x80,0x00,0x52,0x00,0xaa,0x01,0x83,0x00,0x0c,0x00,0xaa,0x01,0x8c,0x00,0x52,0x00,0xaa,0x01,0x8e,0x00,0x52,0x00,0xaa,0x01,0x90,0x00,0x52,0x00,0xaa,0x01,0x93,0x00,0x0c,0x00,0xaa,0x01,0xac,0x00,0x52,0x00,0xaa,0x01,0xb8,0xff,0xcd,0x00,0xaa,0x01,0xdc,0xff,0xcd,0x00,0xaa,0x01,0xe1,0x00,0x52,0x00,0xaa, 0x01,0xe3,0xff,0xcd,0x00,0xaa,0x01,0xeb,0x00,0x52,0x00,0xaa,0x01,0xf2,0x00,0x52,0x00,0xaa,0x01,0xf9,0xff,0xcd,0x00,0xaa,0x02,0x01,0xff,0xcd,0x00,0xaa,0x02,0x1a,0x00,0x0e,0x00,0xaa,0x02,0x31,0x00,0x0e,0x00,0xab,0x00,0x37,0xff,0xcf,0x00,0xab,0x00,0x39,0xff,0xcf,0x00,0xab,0x00,0x3a,0xff,0xcf,0x00,0xab,0x00,0x3c,0xff,0x9a, 0x00,0xab,0x00,0xea,0xff,0x9a,0x00,0xab,0x01,0x20,0xff,0xcf,0x00,0xab,0x01,0x22,0xff,0xcf,0x00,0xab,0x01,0x76,0xff,0xcf,0x00,0xab,0x01,0x80,0xff,0xcf,0x00,0xab,0x01,0x82,0xff,0x9a,0x00,0xab,0x01,0x8c,0xff,0xcf,0x00,0xab,0x01,0x8e,0xff,0xcf,0x00,0xab,0x01,0x90,0xff,0xcf,0x00,0xab,0x01,0x92,0xff,0x9a,0x00,0xab,0x01,0xb8, 0xff,0xcd,0x00,0xab,0x01,0xb9,0xff,0x98,0x00,0xab,0x01,0xdc,0xff,0xcd,0x00,0xab,0x01,0xe3,0xff,0xcd,0x00,0xab,0x01,0xf9,0xff,0xcd,0x00,0xab,0x02,0x01,0xff,0xcd,0x00,0xac,0x00,0xb4,0xff,0x31,0x00,0xac,0x00,0xb5,0xff,0x3d,0x00,0xac,0x00,0xb6,0xff,0x31,0x00,0xac,0x00,0xb7,0xff,0x3d,0x00,0xad,0x00,0x2d,0x00,0x5e,0x00,0xad, 0x00,0x37,0xff,0x6d,0x00,0xad,0x00,0x39,0xff,0x8b,0x00,0xad,0x00,0x3a,0xff,0xb6,0x00,0xad,0x00,0x3c,0xff,0x64,0x00,0xad,0x00,0xea,0xff,0x64,0x00,0xad,0x01,0x20,0xff,0x6d,0x00,0xad,0x01,0x22,0xff,0x6d,0x00,0xad,0x01,0x63,0x00,0x5e,0x00,0xad,0x01,0x76,0xff,0x6d,0x00,0xad,0x01,0x80,0xff,0xb6,0x00,0xad,0x01,0x82,0xff,0x64, 0x00,0xad,0x01,0x8c,0xff,0xb6,0x00,0xad,0x01,0x8e,0xff,0xb6,0x00,0xad,0x01,0x90,0xff,0xb6,0x00,0xad,0x01,0x92,0xff,0x64,0x00,0xae,0x00,0x2d,0x00,0x5e,0x00,0xae,0x00,0x37,0xff,0x6d,0x00,0xae,0x00,0x39,0xff,0x8b,0x00,0xae,0x00,0x3a,0xff,0xb6,0x00,0xae,0x00,0x3c,0xff,0x64,0x00,0xae,0x00,0xea,0xff,0x64,0x00,0xae,0x01,0x20, 0xff,0x6d,0x00,0xae,0x01,0x22,0xff,0x6d,0x00,0xae,0x01,0x63,0x00,0x5e,0x00,0xae,0x01,0x76,0xff,0x6d,0x00,0xae,0x01,0x80,0xff,0xb6,0x00,0xae,0x01,0x82,0xff,0x64,0x00,0xae,0x01,0x8c,0xff,0xb6,0x00,0xae,0x01,0x8e,0xff,0xb6,0x00,0xae,0x01,0x90,0xff,0xb6,0x00,0xae,0x01,0x92,0xff,0x64,0x00,0xaf,0x00,0x24,0xff,0xe5,0x00,0xaf, 0x00,0x37,0xff,0xa4,0x00,0xaf,0x00,0x3b,0xff,0xdb,0x00,0xaf,0x00,0x3d,0xff,0xcf,0x00,0xaf,0x00,0xe5,0xff,0xcf,0x00,0xaf,0x01,0x03,0xff,0xe5,0x00,0xaf,0x01,0x05,0xff,0xe5,0x00,0xaf,0x01,0x20,0xff,0xa4,0x00,0xaf,0x01,0x22,0xff,0xa4,0x00,0xaf,0x01,0x28,0xff,0xcf,0x00,0xaf,0x01,0x2a,0xff,0xcf,0x00,0xaf,0x01,0x45,0xff,0xe5, 0x00,0xaf,0x01,0x76,0xff,0xa4,0x00,0xaf,0x01,0x85,0xff,0xe5,0x00,0xaf,0x01,0x87,0xff,0xe5,0x00,0xb0,0x00,0x24,0x00,0x1d,0x00,0xb0,0x00,0x2d,0x00,0x44,0x00,0xb0,0x00,0x37,0x00,0x04,0x00,0xb0,0x00,0x3b,0x00,0x08,0x00,0xb0,0x01,0x03,0x00,0x1d,0x00,0xb0,0x01,0x05,0x00,0x1d,0x00,0xb0,0x01,0x20,0x00,0x04,0x00,0xb0,0x01,0x22, 0x00,0x04,0x00,0xb0,0x01,0x45,0x00,0x1d,0x00,0xb0,0x01,0x63,0x00,0x44,0x00,0xb0,0x01,0x76,0x00,0x04,0x00,0xb0,0x01,0x85,0x00,0x1d,0x00,0xb0,0x01,0x87,0x00,0x1d,0x00,0xb4,0x00,0x0f,0xff,0x98,0x00,0xb4,0x00,0x11,0xff,0x98,0x00,0xb4,0x00,0x24,0xff,0x25,0x00,0xb4,0x00,0x2d,0xff,0x62,0x00,0xb4,0x00,0x37,0x00,0x52,0x00,0xb4, 0x00,0x46,0xff,0x7f,0x00,0xb4,0x00,0x47,0xff,0x7f,0x00,0xb4,0x00,0x48,0xff,0x7f,0x00,0xb4,0x00,0x4a,0xff,0x73,0x00,0xb4,0x00,0x56,0xff,0xb2,0x00,0xb4,0x00,0x91,0xfe,0x87,0x00,0xb4,0x00,0xac,0xff,0x98,0x00,0xb4,0x00,0xe4,0xff,0xb2,0x00,0xb4,0x00,0xf8,0xff,0x73,0x00,0xb4,0x00,0xfb,0xff,0xb2,0x00,0xb4,0x00,0xfd,0xff,0x7f, 0x00,0xb4,0x00,0xff,0xff,0x7f,0x00,0xb4,0x01,0x00,0xff,0x7f,0x00,0xb4,0x01,0x03,0xff,0x25,0x00,0xb4,0x01,0x05,0xff,0x25,0x00,0xb4,0x01,0x08,0xff,0x7f,0x00,0xb4,0x01,0x0b,0xff,0x7f,0x00,0xb4,0x01,0x1f,0xff,0xb2,0x00,0xb4,0x01,0x20,0x00,0x52,0x00,0xb4,0x01,0x22,0x00,0x52,0x00,0xb4,0x01,0x45,0xff,0x25,0x00,0xb4,0x01,0x48, 0xff,0x7f,0x00,0xb4,0x01,0x52,0xff,0x73,0x00,0xb4,0x01,0x54,0xff,0x73,0x00,0xb4,0x01,0x56,0xff,0x73,0x00,0xb4,0x01,0x63,0xff,0x62,0x00,0xb4,0x01,0x75,0xff,0xb2,0x00,0xb4,0x01,0x76,0x00,0x52,0x00,0xb4,0x01,0x85,0xff,0x25,0x00,0xb4,0x01,0x87,0xff,0x25,0x00,0xb4,0x01,0xb8,0x00,0x52,0x00,0xb4,0x01,0xdc,0x00,0x52,0x00,0xb4, 0x01,0xe1,0xff,0x6f,0x00,0xb4,0x01,0xe3,0x00,0x52,0x00,0xb4,0x01,0xe7,0xff,0x23,0x00,0xb4,0x01,0xeb,0xff,0x6f,0x00,0xb4,0x01,0xf2,0xff,0x6f,0x00,0xb4,0x01,0xf9,0x00,0x52,0x00,0xb4,0x02,0x01,0x00,0x52,0x00,0xb4,0x02,0x0c,0xff,0x7f,0x00,0xb4,0x02,0x15,0xff,0x7f,0x00,0xb4,0x02,0x18,0xff,0x7f,0x00,0xb4,0x02,0x1b,0xff,0x7f, 0x00,0xb4,0x02,0x27,0xff,0x7f,0x00,0xb4,0x02,0x2a,0xff,0x7f,0x00,0xb4,0x02,0x2b,0xff,0xb0,0x00,0xb4,0x02,0x3e,0xff,0xb2,0x00,0xb5,0x00,0x0f,0xff,0x9a,0x00,0xb5,0x00,0x11,0xff,0x9a,0x00,0xb5,0x00,0x24,0xff,0x66,0x00,0xb5,0x00,0x37,0x00,0x52,0x00,0xb5,0x00,0x46,0xff,0xdd,0x00,0xb5,0x00,0x47,0xff,0x62,0x00,0xb5,0x00,0x48, 0xff,0x62,0x00,0xb5,0x00,0x4a,0xff,0x62,0x00,0xb5,0x00,0x52,0xff,0x62,0x00,0xb5,0x00,0x56,0xff,0x7f,0x00,0xb5,0x00,0x91,0xff,0x0a,0x00,0xb5,0x00,0xac,0xff,0x9a,0x00,0xb5,0x00,0xe4,0xff,0x7f,0x00,0xb5,0x00,0xf8,0xff,0x62,0x00,0xb5,0x00,0xfb,0xff,0x7f,0x00,0xb5,0x00,0xfd,0xff,0xdd,0x00,0xb5,0x00,0xff,0xff,0xdd,0x00,0xb5, 0x01,0x00,0xff,0x62,0x00,0xb5,0x01,0x03,0xff,0x66,0x00,0xb5,0x01,0x05,0xff,0x66,0x00,0xb5,0x01,0x08,0xff,0x62,0x00,0xb5,0x01,0x0b,0xff,0x62,0x00,0xb5,0x01,0x1f,0xff,0x7f,0x00,0xb5,0x01,0x20,0x00,0x52,0x00,0xb5,0x01,0x22,0x00,0x52,0x00,0xb5,0x01,0x45,0xff,0x66,0x00,0xb5,0x01,0x48,0xff,0xdd,0x00,0xb5,0x01,0x52,0xff,0x62, 0x00,0xb5,0x01,0x54,0xff,0x62,0x00,0xb5,0x01,0x56,0xff,0x62,0x00,0xb5,0x01,0x75,0xff,0x7f,0x00,0xb5,0x01,0x76,0x00,0x52,0x00,0xb5,0x01,0x85,0xff,0x66,0x00,0xb5,0x01,0x87,0xff,0x66,0x00,0xb5,0x01,0xdc,0x00,0x52,0x00,0xb5,0x01,0xe3,0x00,0x52,0x00,0xb5,0x01,0xe7,0xff,0x66,0x00,0xb5,0x01,0xf9,0x00,0x52,0x00,0xb5,0x02,0x01, 0x00,0x52,0x00,0xb5,0x02,0x0c,0xff,0x62,0x00,0xb5,0x02,0x15,0xff,0x62,0x00,0xb5,0x02,0x18,0xff,0x62,0x00,0xb5,0x02,0x1b,0xff,0x62,0x00,0xb5,0x02,0x27,0xff,0x62,0x00,0xb5,0x02,0x2a,0xff,0x62,0x00,0xb5,0x02,0x2b,0xff,0x7f,0x00,0xb5,0x02,0x3e,0xff,0x7f,0x00,0xb6,0x00,0x24,0xff,0x25,0x00,0xb6,0x00,0x26,0xff,0xbe,0x00,0xb6, 0x00,0x2d,0xff,0x6f,0x00,0xb6,0x00,0x37,0x00,0x52,0x00,0xb6,0x00,0x46,0xff,0x7f,0x00,0xb6,0x00,0x47,0xff,0x62,0x00,0xb6,0x00,0x48,0xff,0x7f,0x00,0xb6,0x00,0x4a,0xff,0x7f,0x00,0xb6,0x00,0x52,0xff,0x7f,0x00,0xb6,0x00,0x56,0xff,0xb2,0x00,0xb6,0x00,0x91,0xff,0x0a,0x00,0xb6,0x00,0xb6,0xff,0x54,0x00,0xb6,0x00,0xe4,0xff,0xb2, 0x00,0xb6,0x00,0xf8,0xff,0x7f,0x00,0xb6,0x00,0xfb,0xff,0xb2,0x00,0xb6,0x00,0xfc,0xff,0xbe,0x00,0xb6,0x00,0xfd,0xff,0x7f,0x00,0xb6,0x00,0xfe,0xff,0xbe,0x00,0xb6,0x00,0xff,0xff,0x7f,0x00,0xb6,0x01,0x00,0xff,0x62,0x00,0xb6,0x01,0x03,0xff,0x25,0x00,0xb6,0x01,0x05,0xff,0x25,0x00,0xb6,0x01,0x08,0xff,0x62,0x00,0xb6,0x01,0x0b, 0xff,0x7f,0x00,0xb6,0x01,0x1f,0xff,0xb2,0x00,0xb6,0x01,0x20,0x00,0x52,0x00,0xb6,0x01,0x22,0x00,0x52,0x00,0xb6,0x01,0x45,0xff,0x25,0x00,0xb6,0x01,0x47,0xff,0xbe,0x00,0xb6,0x01,0x48,0xff,0x7f,0x00,0xb6,0x01,0x52,0xff,0x7f,0x00,0xb6,0x01,0x54,0xff,0x7f,0x00,0xb6,0x01,0x56,0xff,0x7f,0x00,0xb6,0x01,0x63,0xff,0x6f,0x00,0xb6, 0x01,0x75,0xff,0xb2,0x00,0xb6,0x01,0x76,0x00,0x52,0x00,0xb6,0x01,0x85,0xff,0x25,0x00,0xb6,0x01,0x87,0xff,0x25,0x00,0xb6,0x01,0xdc,0x00,0x52,0x00,0xb6,0x01,0xde,0xff,0xbc,0x00,0xb6,0x01,0xe1,0xff,0x6f,0x00,0xb6,0x01,0xe3,0x00,0x52,0x00,0xb6,0x01,0xe7,0xff,0x23,0x00,0xb6,0x01,0xeb,0xff,0x6f,0x00,0xb6,0x01,0xf2,0xff,0x6f, 0x00,0xb6,0x01,0xf5,0xff,0xbc,0x00,0xb6,0x01,0xf8,0xff,0xbc,0x00,0xb6,0x01,0xf9,0x00,0x52,0x00,0xb6,0x01,0xfb,0xff,0xbc,0x00,0xb6,0x02,0x01,0x00,0x52,0x00,0xb6,0x02,0x0c,0xff,0x7f,0x00,0xb6,0x02,0x15,0xff,0x7f,0x00,0xb6,0x02,0x18,0xff,0x7f,0x00,0xb6,0x02,0x1b,0xff,0x7f,0x00,0xb6,0x02,0x27,0xff,0x7f,0x00,0xb6,0x02,0x2a, 0xff,0x7f,0x00,0xb6,0x02,0x2b,0xff,0xb0,0x00,0xb6,0x02,0x3e,0xff,0xb2,0x00,0xb7,0x00,0x0f,0xff,0x9a,0x00,0xb7,0x00,0x11,0xff,0x9a,0x00,0xb7,0x00,0x24,0xff,0x5a,0x00,0xb7,0x00,0x2d,0xff,0x62,0x00,0xb7,0x00,0x37,0x00,0x52,0x00,0xb7,0x00,0x44,0xff,0x98,0x00,0xb7,0x00,0x46,0xff,0x3d,0x00,0xb7,0x00,0x47,0xff,0x62,0x00,0xb7, 0x00,0x48,0xff,0x62,0x00,0xb7,0x00,0x4a,0xff,0x62,0x00,0xb7,0x00,0x52,0xff,0x62,0x00,0xb7,0x00,0x54,0xff,0x6f,0x00,0xb7,0x00,0x56,0xff,0x8b,0x00,0xb7,0x00,0x91,0xff,0x08,0x00,0xb7,0x00,0xac,0xff,0x9a,0x00,0xb7,0x00,0xb7,0xff,0x54,0x00,0xb7,0x00,0xc4,0xff,0x98,0x00,0xb7,0x00,0xe4,0xff,0x8b,0x00,0xb7,0x00,0xf8,0xff,0x62, 0x00,0xb7,0x00,0xfb,0xff,0x8b,0x00,0xb7,0x00,0xfd,0xff,0x3d,0x00,0xb7,0x00,0xff,0xff,0x3d,0x00,0xb7,0x01,0x00,0xff,0x62,0x00,0xb7,0x01,0x03,0xff,0x5a,0x00,0xb7,0x01,0x05,0xff,0x5a,0x00,0xb7,0x01,0x06,0xff,0x98,0x00,0xb7,0x01,0x08,0xff,0x62,0x00,0xb7,0x01,0x0b,0xff,0x62,0x00,0xb7,0x01,0x1f,0xff,0x8b,0x00,0xb7,0x01,0x20, 0x00,0x52,0x00,0xb7,0x01,0x22,0x00,0x52,0x00,0xb7,0x01,0x45,0xff,0x5a,0x00,0xb7,0x01,0x48,0xff,0x3d,0x00,0xb7,0x01,0x52,0xff,0x62,0x00,0xb7,0x01,0x54,0xff,0x62,0x00,0xb7,0x01,0x56,0xff,0x62,0x00,0xb7,0x01,0x63,0xff,0x62,0x00,0xb7,0x01,0x75,0xff,0x8b,0x00,0xb7,0x01,0x76,0x00,0x52,0x00,0xb7,0x01,0x85,0xff,0x5a,0x00,0xb7, 0x01,0x87,0xff,0x5a,0x00,0xb7,0x01,0x88,0xff,0x98,0x00,0xb7,0x01,0xdc,0x00,0x52,0x00,0xb7,0x01,0xe1,0xff,0x62,0x00,0xb7,0x01,0xe3,0x00,0x52,0x00,0xb7,0x01,0xe7,0xff,0x5a,0x00,0xb7,0x01,0xeb,0xff,0x62,0x00,0xb7,0x01,0xf2,0xff,0x62,0x00,0xb7,0x01,0xf9,0x00,0x52,0x00,0xb7,0x02,0x01,0x00,0x52,0x00,0xb7,0x02,0x07,0xff,0x96, 0x00,0xb7,0x02,0x0c,0xff,0x62,0x00,0xb7,0x02,0x15,0xff,0x62,0x00,0xb7,0x02,0x18,0xff,0x62,0x00,0xb7,0x02,0x1b,0xff,0x62,0x00,0xb7,0x02,0x27,0xff,0x62,0x00,0xb7,0x02,0x2a,0xff,0x62,0x00,0xb7,0x02,0x2b,0xff,0x8b,0x00,0xb7,0x02,0x3e,0xff,0x8b,0x00,0xba,0x00,0x46,0xff,0xf6,0x00,0xba,0x00,0x47,0xff,0xf6,0x00,0xba,0x00,0x48, 0xff,0xf6,0x00,0xba,0x00,0x4a,0xff,0xf6,0x00,0xba,0x00,0x52,0xff,0xf6,0x00,0xba,0x00,0x54,0xff,0xf6,0x00,0xba,0x00,0xf8,0xff,0xf6,0x00,0xba,0x00,0xfd,0xff,0xf6,0x00,0xba,0x00,0xff,0xff,0xf6,0x00,0xba,0x01,0x00,0xff,0xf6,0x00,0xba,0x01,0x08,0xff,0xf6,0x00,0xba,0x01,0x0b,0xff,0xf6,0x00,0xba,0x01,0x48,0xff,0xf6,0x00,0xba, 0x01,0x52,0xff,0xf6,0x00,0xba,0x01,0x54,0xff,0xf6,0x00,0xba,0x01,0x56,0xff,0xf6,0x00,0xbb,0x00,0x24,0xff,0x62,0x00,0xbb,0x00,0x26,0xff,0xe1,0x00,0xbb,0x00,0x2a,0xff,0xe1,0x00,0xbb,0x00,0x32,0xff,0xe1,0x00,0xbb,0x00,0x34,0xff,0xcd,0x00,0xbb,0x00,0x36,0xff,0xe5,0x00,0xbb,0x00,0xe3,0xff,0xe5,0x00,0xbb,0x00,0xf7,0xff,0xe1, 0x00,0xbb,0x00,0xfa,0xff,0xe5,0x00,0xbb,0x00,0xfc,0xff,0xe1,0x00,0xbb,0x00,0xfe,0xff,0xe1,0x00,0xbb,0x01,0x03,0xff,0x62,0x00,0xbb,0x01,0x05,0xff,0x62,0x00,0xbb,0x01,0x18,0xff,0xe1,0x00,0xbb,0x01,0x1e,0xff,0xe5,0x00,0xbb,0x01,0x45,0xff,0x62,0x00,0xbb,0x01,0x47,0xff,0xe1,0x00,0xbb,0x01,0x51,0xff,0xe1,0x00,0xbb,0x01,0x53, 0xff,0xe1,0x00,0xbb,0x01,0x55,0xff,0xe1,0x00,0xbb,0x01,0x6e,0xff,0xe1,0x00,0xbb,0x01,0x70,0xff,0xe1,0x00,0xbb,0x01,0x74,0xff,0xe5,0x00,0xbb,0x01,0x85,0xff,0x62,0x00,0xbb,0x01,0x87,0xff,0x62,0x00,0xbb,0x01,0x89,0xff,0xe1,0x00,0xbb,0x02,0x3d,0xff,0xe5,0x00,0xbe,0x00,0x2d,0x00,0x52,0x00,0xbe,0x00,0x37,0xff,0xcf,0x00,0xbe, 0x00,0x3a,0x00,0x27,0x00,0xbe,0x00,0x3d,0x00,0x52,0x00,0xbe,0x00,0x5c,0x00,0x0c,0x00,0xbe,0x00,0xe5,0x00,0x52,0x00,0xbe,0x00,0xeb,0x00,0x0c,0x00,0xbe,0x01,0x20,0xff,0xcf,0x00,0xbe,0x01,0x22,0xff,0xcf,0x00,0xbe,0x01,0x28,0x00,0x52,0x00,0xbe,0x01,0x2a,0x00,0x52,0x00,0xbe,0x01,0x63,0x00,0x52,0x00,0xbe,0x01,0x76,0xff,0xcf, 0x00,0xbe,0x01,0x80,0x00,0x27,0x00,0xbe,0x01,0x83,0x00,0x0c,0x00,0xbe,0x01,0x8c,0x00,0x27,0x00,0xbe,0x01,0x8e,0x00,0x27,0x00,0xbe,0x01,0x90,0x00,0x27,0x00,0xbe,0x01,0x93,0x00,0x0c,0x00,0xbe,0x01,0xdc,0xff,0xcd,0x00,0xbe,0x01,0xe1,0x00,0x52,0x00,0xbe,0x01,0xe3,0xff,0xcd,0x00,0xbe,0x01,0xeb,0x00,0x52,0x00,0xbe,0x01,0xf2, 0x00,0x52,0x00,0xbe,0x01,0xf9,0xff,0xcd,0x00,0xbe,0x02,0x01,0xff,0xcd,0x00,0xbe,0x02,0x1a,0x00,0x0e,0x00,0xbe,0x02,0x31,0x00,0x0e,0x00,0xbf,0x00,0x37,0xff,0x9a,0x00,0xbf,0x00,0x39,0xff,0xcf,0x00,0xbf,0x00,0x3a,0xff,0xcf,0x00,0xbf,0x00,0x3c,0xff,0x9a,0x00,0xbf,0x00,0xea,0xff,0x9a,0x00,0xbf,0x01,0x20,0xff,0x9a,0x00,0xbf, 0x01,0x22,0xff,0x9a,0x00,0xbf,0x01,0x76,0xff,0x9a,0x00,0xbf,0x01,0x80,0xff,0xcf,0x00,0xbf,0x01,0x82,0xff,0x9a,0x00,0xbf,0x01,0x8c,0xff,0xcf,0x00,0xbf,0x01,0x8e,0xff,0xcf,0x00,0xbf,0x01,0x90,0xff,0xcf,0x00,0xbf,0x01,0x92,0xff,0x9a,0x00,0xbf,0x01,0xdc,0xff,0x98,0x00,0xbf,0x01,0xe3,0xff,0x98,0x00,0xbf,0x01,0xf9,0xff,0x98, 0x00,0xbf,0x02,0x01,0xff,0x98,0x00,0xc4,0x00,0x2a,0xff,0xb2,0x00,0xc4,0x00,0x2d,0x00,0x6d,0x00,0xc4,0x00,0x32,0xff,0xa6,0x00,0xc4,0x00,0x37,0xff,0x31,0x00,0xc4,0x00,0x38,0xff,0xf6,0x00,0xc4,0x00,0x39,0xff,0x73,0x00,0xc4,0x00,0x3a,0xff,0x7f,0x00,0xc4,0x00,0x3b,0x00,0x39,0x00,0xc4,0x00,0x3c,0xff,0x08,0x00,0xc4,0x00,0x52, 0x00,0x19,0x00,0xc4,0x00,0x59,0xff,0x8b,0x00,0xc4,0x00,0x5a,0xff,0x7f,0x00,0xc4,0x00,0xea,0xff,0x08,0x00,0xc4,0x00,0xf7,0xff,0xb2,0x00,0xc4,0x01,0x18,0xff,0xa6,0x00,0xc4,0x01,0x20,0xff,0x31,0x00,0xc4,0x01,0x22,0xff,0x31,0x00,0xc4,0x01,0x24,0xff,0xf6,0x00,0xc4,0x01,0x26,0xff,0xf6,0x00,0xc4,0x01,0x51,0xff,0xb2,0x00,0xc4, 0x01,0x53,0xff,0xb2,0x00,0xc4,0x01,0x55,0xff,0xb2,0x00,0xc4,0x01,0x63,0x00,0x6d,0x00,0xc4,0x01,0x6e,0xff,0xa6,0x00,0xc4,0x01,0x70,0xff,0xa6,0x00,0xc4,0x01,0x76,0xff,0x31,0x00,0xc4,0x01,0x78,0xff,0xf6,0x00,0xc4,0x01,0x7a,0xff,0xf6,0x00,0xc4,0x01,0x7c,0xff,0xf6,0x00,0xc4,0x01,0x7e,0xff,0xf6,0x00,0xc4,0x01,0x80,0xff,0x7f, 0x00,0xc4,0x01,0x81,0xff,0x7f,0x00,0xc4,0x01,0x82,0xff,0x08,0x00,0xc4,0x01,0x89,0xff,0xa6,0x00,0xc4,0x01,0x8c,0xff,0x7f,0x00,0xc4,0x01,0x8d,0xff,0x7f,0x00,0xc4,0x01,0x8e,0xff,0x7f,0x00,0xc4,0x01,0x8f,0xff,0x7f,0x00,0xc4,0x01,0x90,0xff,0x7f,0x00,0xc4,0x01,0x91,0xff,0x7f,0x00,0xc4,0x01,0x92,0xff,0x08,0x00,0xc4,0x01,0xdc, 0xff,0x31,0x00,0xc4,0x01,0xde,0xff,0xa4,0x00,0xc4,0x01,0xe1,0x00,0x6f,0x00,0xc4,0x01,0xe3,0xff,0x31,0x00,0xc4,0x01,0xeb,0x00,0x6f,0x00,0xc4,0x01,0xf2,0x00,0x6f,0x00,0xc4,0x01,0xf5,0xff,0xa4,0x00,0xc4,0x01,0xf8,0xff,0xa4,0x00,0xc4,0x01,0xf9,0xff,0x31,0x00,0xc4,0x01,0xfb,0xff,0xa4,0x00,0xc4,0x01,0xfc,0x00,0x39,0x00,0xc4, 0x02,0x01,0xff,0x31,0x00,0xc4,0x02,0x08,0x00,0x1b,0x00,0xc4,0x02,0x0c,0x00,0x1b,0x00,0xc4,0x02,0x15,0x00,0x1b,0x00,0xc4,0x02,0x18,0x00,0x1b,0x00,0xc4,0x02,0x1b,0x00,0x1b,0x00,0xc4,0x02,0x27,0x00,0x1b,0x00,0xc4,0x02,0x2a,0x00,0x1b,0x00,0xc5,0x00,0x2a,0xff,0xa6,0x00,0xc5,0x00,0x2d,0x00,0x6d,0x00,0xc5,0x00,0x32,0xff,0xb2, 0x00,0xc5,0x00,0x37,0xff,0x31,0x00,0xc5,0x00,0x38,0xff,0xf6,0x00,0xc5,0x00,0x39,0xff,0x7f,0x00,0xc5,0x00,0x3a,0xff,0x8b,0x00,0xc5,0x00,0x3b,0x00,0x27,0x00,0xc5,0x00,0x3c,0xff,0x3d,0x00,0xc5,0x00,0x59,0xff,0x8b,0x00,0xc5,0x00,0x5a,0xff,0x7f,0x00,0xc5,0x00,0xea,0xff,0x3d,0x00,0xc5,0x00,0xf7,0xff,0xa6,0x00,0xc5,0x01,0x18, 0xff,0xb2,0x00,0xc5,0x01,0x20,0xff,0x31,0x00,0xc5,0x01,0x22,0xff,0x31,0x00,0xc5,0x01,0x24,0xff,0xf6,0x00,0xc5,0x01,0x26,0xff,0xf6,0x00,0xc5,0x01,0x51,0xff,0xa6,0x00,0xc5,0x01,0x53,0xff,0xa6,0x00,0xc5,0x01,0x55,0xff,0xa6,0x00,0xc5,0x01,0x63,0x00,0x6d,0x00,0xc5,0x01,0x6e,0xff,0xb2,0x00,0xc5,0x01,0x70,0xff,0xb2,0x00,0xc5, 0x01,0x76,0xff,0x31,0x00,0xc5,0x01,0x78,0xff,0xf6,0x00,0xc5,0x01,0x7a,0xff,0xf6,0x00,0xc5,0x01,0x7c,0xff,0xf6,0x00,0xc5,0x01,0x7e,0xff,0xf6,0x00,0xc5,0x01,0x80,0xff,0x8b,0x00,0xc5,0x01,0x81,0xff,0x7f,0x00,0xc5,0x01,0x82,0xff,0x3d,0x00,0xc5,0x01,0x89,0xff,0xb2,0x00,0xc5,0x01,0x8c,0xff,0x8b,0x00,0xc5,0x01,0x8d,0xff,0x7f, 0x00,0xc5,0x01,0x8e,0xff,0x8b,0x00,0xc5,0x01,0x8f,0xff,0x7f,0x00,0xc5,0x01,0x90,0xff,0x8b,0x00,0xc5,0x01,0x91,0xff,0x7f,0x00,0xc5,0x01,0x92,0xff,0x3d,0x00,0xc5,0x01,0xdc,0xff,0x31,0x00,0xc5,0x01,0xde,0xff,0xb0,0x00,0xc5,0x01,0xe1,0x00,0x6f,0x00,0xc5,0x01,0xe3,0xff,0x31,0x00,0xc5,0x01,0xeb,0x00,0x6f,0x00,0xc5,0x01,0xf2, 0x00,0x6f,0x00,0xc5,0x01,0xf5,0xff,0xb0,0x00,0xc5,0x01,0xf8,0xff,0xb0,0x00,0xc5,0x01,0xf9,0xff,0x31,0x00,0xc5,0x01,0xfb,0xff,0xb0,0x00,0xc5,0x01,0xfc,0x00,0x29,0x00,0xc5,0x02,0x01,0xff,0x31,0x00,0xc7,0x00,0x2d,0x00,0x5e,0x00,0xc7,0x00,0x37,0xff,0x6d,0x00,0xc7,0x00,0x39,0xff,0x8b,0x00,0xc7,0x00,0x3a,0xff,0xb6,0x00,0xc7, 0x00,0x3c,0xff,0x64,0x00,0xc7,0x00,0xea,0xff,0x64,0x00,0xc7,0x01,0x20,0xff,0x6d,0x00,0xc7,0x01,0x22,0xff,0x6d,0x00,0xc7,0x01,0x63,0x00,0x5e,0x00,0xc7,0x01,0x76,0xff,0x6d,0x00,0xc7,0x01,0x80,0xff,0xb6,0x00,0xc7,0x01,0x82,0xff,0x64,0x00,0xc7,0x01,0x8c,0xff,0xb6,0x00,0xc7,0x01,0x8e,0xff,0xb6,0x00,0xc7,0x01,0x90,0xff,0xb6, 0x00,0xc7,0x01,0x92,0xff,0x64,0x00,0xc8,0x00,0x2d,0x00,0x3d,0x00,0xc8,0x01,0x63,0x00,0x3d,0x00,0xc9,0x00,0x2d,0x00,0x5e,0x00,0xc9,0x00,0x37,0xff,0x6d,0x00,0xc9,0x00,0x39,0xff,0x8b,0x00,0xc9,0x00,0x3a,0xff,0xb6,0x00,0xc9,0x00,0x3c,0xff,0x64,0x00,0xc9,0x00,0xea,0xff,0x64,0x00,0xc9,0x01,0x20,0xff,0x6d,0x00,0xc9,0x01,0x22, 0xff,0x6d,0x00,0xc9,0x01,0x63,0x00,0x5e,0x00,0xc9,0x01,0x76,0xff,0x6d,0x00,0xc9,0x01,0x80,0xff,0xb6,0x00,0xc9,0x01,0x82,0xff,0x64,0x00,0xc9,0x01,0x8c,0xff,0xb6,0x00,0xc9,0x01,0x8e,0xff,0xb6,0x00,0xc9,0x01,0x90,0xff,0xb6,0x00,0xc9,0x01,0x92,0xff,0x64,0x00,0xca,0x00,0x2d,0x00,0x3d,0x00,0xca,0x01,0x63,0x00,0x3d,0x00,0xcb, 0x00,0x2d,0x00,0x3d,0x00,0xcb,0x01,0x63,0x00,0x3d,0x00,0xd0,0x00,0x24,0xff,0xe5,0x00,0xd0,0x00,0x37,0xff,0xa4,0x00,0xd0,0x00,0x3b,0xff,0xdb,0x00,0xd0,0x00,0x3d,0xff,0xcf,0x00,0xd0,0x00,0xe5,0xff,0xcf,0x00,0xd0,0x01,0x03,0xff,0xe5,0x00,0xd0,0x01,0x05,0xff,0xe5,0x00,0xd0,0x01,0x20,0xff,0xa4,0x00,0xd0,0x01,0x22,0xff,0xa4, 0x00,0xd0,0x01,0x28,0xff,0xcf,0x00,0xd0,0x01,0x2a,0xff,0xcf,0x00,0xd0,0x01,0x45,0xff,0xe5,0x00,0xd0,0x01,0x76,0xff,0xa4,0x00,0xd0,0x01,0x85,0xff,0xe5,0x00,0xd0,0x01,0x87,0xff,0xe5,0x00,0xd1,0x00,0x24,0xff,0xe5,0x00,0xd1,0x00,0x37,0xff,0xa4,0x00,0xd1,0x00,0x3b,0xff,0xdb,0x00,0xd1,0x00,0x3d,0xff,0xcf,0x00,0xd1,0x00,0xe5, 0xff,0xcf,0x00,0xd1,0x01,0x03,0xff,0xe5,0x00,0xd1,0x01,0x05,0xff,0xe5,0x00,0xd1,0x01,0x20,0xff,0xa4,0x00,0xd1,0x01,0x22,0xff,0xa4,0x00,0xd1,0x01,0x28,0xff,0xcf,0x00,0xd1,0x01,0x2a,0xff,0xcf,0x00,0xd1,0x01,0x45,0xff,0xe5,0x00,0xd1,0x01,0x76,0xff,0xa4,0x00,0xd1,0x01,0x85,0xff,0xe5,0x00,0xd1,0x01,0x87,0xff,0xe5,0x00,0xd2, 0x00,0x24,0xff,0xe5,0x00,0xd2,0x00,0x37,0xff,0xa4,0x00,0xd2,0x00,0x3b,0xff,0xdb,0x00,0xd2,0x00,0x3d,0xff,0xcf,0x00,0xd2,0x00,0xe5,0xff,0xcf,0x00,0xd2,0x01,0x03,0xff,0xe5,0x00,0xd2,0x01,0x05,0xff,0xe5,0x00,0xd2,0x01,0x20,0xff,0xa4,0x00,0xd2,0x01,0x22,0xff,0xa4,0x00,0xd2,0x01,0x28,0xff,0xcf,0x00,0xd2,0x01,0x2a,0xff,0xcf, 0x00,0xd2,0x01,0x45,0xff,0xe5,0x00,0xd2,0x01,0x76,0xff,0xa4,0x00,0xd2,0x01,0x85,0xff,0xe5,0x00,0xd2,0x01,0x87,0xff,0xe5,0x00,0xe1,0x00,0x0d,0xff,0x31,0x00,0xe1,0x00,0x22,0xff,0x9a,0x00,0xe1,0x00,0x24,0x00,0x3b,0x00,0xe1,0x00,0x26,0xff,0xbe,0x00,0xe1,0x00,0x2a,0xff,0xbe,0x00,0xe1,0x00,0x2d,0x00,0x64,0x00,0xe1,0x00,0x32, 0xff,0xba,0x00,0xe1,0x00,0x34,0xff,0xba,0x00,0xe1,0x00,0x37,0xff,0x8f,0x00,0xe1,0x00,0x38,0xff,0xe3,0x00,0xe1,0x00,0x39,0xff,0x8b,0x00,0xe1,0x00,0x3a,0xff,0xcf,0x00,0xe1,0x00,0x3c,0xff,0x7f,0x00,0xe1,0x00,0x3d,0x00,0x3b,0x00,0xe1,0x00,0x57,0xff,0xe5,0x00,0xe1,0x00,0x59,0xff,0x9a,0x00,0xe1,0x00,0x5a,0xff,0xbe,0x00,0xe1, 0x00,0x5c,0xff,0xb4,0x00,0xe1,0x00,0x64,0xff,0xbe,0x00,0xe1,0x00,0x67,0xff,0xba,0x00,0xe1,0x00,0x68,0xff,0xe3,0x00,0xe1,0x00,0x8d,0xff,0x9a,0x00,0xe1,0x00,0x92,0xff,0xba,0x00,0xe1,0x00,0xaf,0xff,0xba,0x00,0xe1,0x00,0xb0,0xff,0xba,0x00,0xe1,0x00,0xb4,0xff,0x73,0x00,0xe1,0x00,0xb5,0xff,0x8b,0x00,0xe1,0x00,0xb6,0xff,0x73, 0x00,0xe1,0x00,0xb7,0xff,0x7f,0x00,0xe1,0x00,0xba,0xff,0xb4,0x00,0xe1,0x00,0xbb,0xff,0x9a,0x00,0xe1,0x00,0xc4,0x00,0x44,0x00,0xe1,0x00,0xc5,0x00,0x44,0x00,0xe1,0x00,0xd0,0xff,0xba,0x00,0xe1,0x00,0xd1,0xff,0xba,0x00,0xe1,0x00,0xd2,0xff,0xba,0x00,0xe1,0x00,0xd3,0xff,0xe3,0x00,0xe1,0x00,0xd4,0xff,0xe3,0x00,0xe1,0x00,0xd5, 0xff,0xe3,0x00,0xe1,0x00,0xe5,0x00,0x3b,0x00,0xe1,0x00,0xea,0xff,0x7f,0x00,0xe1,0x00,0xeb,0xff,0xb4,0x00,0xe1,0x00,0xf7,0xff,0xbe,0x00,0xe1,0x00,0xfc,0xff,0xbe,0x00,0xe1,0x00,0xfe,0xff,0xbe,0x00,0xe1,0x01,0x03,0x00,0x3b,0x00,0xe1,0x01,0x05,0x00,0x3b,0x00,0xe1,0x01,0x18,0xff,0xba,0x00,0xe1,0x01,0x20,0xff,0x8f,0x00,0xe1, 0x01,0x21,0xff,0xe5,0x00,0xe1,0x01,0x22,0xff,0x8f,0x00,0xe1,0x01,0x23,0xff,0xe5,0x00,0xe1,0x01,0x24,0xff,0xe3,0x00,0xe1,0x01,0x26,0xff,0xe3,0x00,0xe1,0x01,0x28,0x00,0x3b,0x00,0xe1,0x01,0x2a,0x00,0x3b,0x00,0xe1,0x01,0x45,0x00,0x3b,0x00,0xe1,0x01,0x47,0xff,0xbe,0x00,0xe1,0x01,0x51,0xff,0xbe,0x00,0xe1,0x01,0x53,0xff,0xbe, 0x00,0xe1,0x01,0x55,0xff,0xbe,0x00,0xe1,0x01,0x63,0x00,0x64,0x00,0xe1,0x01,0x6e,0xff,0xba,0x00,0xe1,0x01,0x70,0xff,0xba,0x00,0xe1,0x01,0x76,0xff,0x8f,0x00,0xe1,0x01,0x77,0xff,0xe5,0x00,0xe1,0x01,0x78,0xff,0xe3,0x00,0xe1,0x01,0x7a,0xff,0xe3,0x00,0xe1,0x01,0x7c,0xff,0xe3,0x00,0xe1,0x01,0x7e,0xff,0xe3,0x00,0xe1,0x01,0x80, 0xff,0xcf,0x00,0xe1,0x01,0x81,0xff,0xbe,0x00,0xe1,0x01,0x82,0xff,0x7f,0x00,0xe1,0x01,0x83,0xff,0xb4,0x00,0xe1,0x01,0x85,0x00,0x3b,0x00,0xe1,0x01,0x87,0x00,0x3b,0x00,0xe1,0x01,0x89,0xff,0xba,0x00,0xe1,0x01,0x8c,0xff,0xcf,0x00,0xe1,0x01,0x8d,0xff,0xbe,0x00,0xe1,0x01,0x8e,0xff,0xcf,0x00,0xe1,0x01,0x8f,0xff,0xbe,0x00,0xe1, 0x01,0x90,0xff,0xcf,0x00,0xe1,0x01,0x91,0xff,0xbe,0x00,0xe1,0x01,0x92,0xff,0x7f,0x00,0xe1,0x01,0x93,0xff,0xb4,0x00,0xe3,0x00,0x57,0xff,0xbe,0x00,0xe3,0x00,0x59,0xff,0xcf,0x00,0xe3,0x00,0x5a,0xff,0xe5,0x00,0xe3,0x00,0x5c,0xff,0xd1,0x00,0xe3,0x00,0xba,0xff,0xbe,0x00,0xe3,0x00,0xc4,0xff,0xb2,0x00,0xe3,0x00,0xc5,0xff,0xb2, 0x00,0xe3,0x00,0xeb,0xff,0xd1,0x00,0xe3,0x01,0x21,0xff,0xbe,0x00,0xe3,0x01,0x23,0xff,0xbe,0x00,0xe3,0x01,0x77,0xff,0xbe,0x00,0xe3,0x01,0x81,0xff,0xe5,0x00,0xe3,0x01,0x83,0xff,0xd1,0x00,0xe3,0x01,0x8d,0xff,0xe5,0x00,0xe3,0x01,0x8f,0xff,0xe5,0x00,0xe3,0x01,0x91,0xff,0xe5,0x00,0xe3,0x01,0x93,0xff,0xd1,0x00,0xe5,0x00,0x2d, 0x00,0x52,0x00,0xe5,0x00,0x37,0x00,0x27,0x00,0xe5,0x00,0x5c,0xff,0xcb,0x00,0xe5,0x00,0x77,0x00,0x46,0x00,0xe5,0x00,0xab,0x00,0x27,0x00,0xe5,0x00,0xba,0xff,0xbe,0x00,0xe5,0x00,0xbf,0x00,0x52,0x00,0xe5,0x00,0xeb,0xff,0xcb,0x00,0xe5,0x01,0x20,0x00,0x27,0x00,0xe5,0x01,0x22,0x00,0x27,0x00,0xe5,0x01,0x5c,0x00,0x46,0x00,0xe5, 0x01,0x5e,0x00,0x46,0x00,0xe5,0x01,0x60,0x00,0x46,0x00,0xe5,0x01,0x63,0x00,0x52,0x00,0xe5,0x01,0x76,0x00,0x27,0x00,0xe5,0x01,0x83,0xff,0xcb,0x00,0xe5,0x01,0x93,0xff,0xcb,0x00,0xe8,0x00,0x0f,0xff,0x7f,0x00,0xe8,0x00,0x11,0xff,0x7f,0x00,0xe8,0x00,0x24,0xff,0xdf,0x00,0xe8,0x00,0x37,0xff,0xa4,0x00,0xe8,0x00,0x3b,0xff,0xcb, 0x00,0xe8,0x00,0x3d,0xff,0xcf,0x00,0xe8,0x00,0x62,0xff,0xdf,0x00,0xe8,0x00,0x63,0xff,0xdf,0x00,0xe8,0x00,0x91,0xff,0xb6,0x00,0xe8,0x00,0xac,0xff,0x7f,0x00,0xe8,0x00,0xad,0xff,0xdf,0x00,0xe8,0x00,0xae,0xff,0xdf,0x00,0xe8,0x00,0xbb,0xff,0xf6,0x00,0xe8,0x00,0xc4,0xff,0x8b,0x00,0xe8,0x00,0xc5,0xff,0x8b,0x00,0xe8,0x00,0xc7, 0xff,0xdf,0x00,0xe8,0x00,0xc9,0xff,0xdf,0x00,0xe8,0x00,0xe5,0xff,0xcf,0x00,0xe8,0x01,0x03,0xff,0xdf,0x00,0xe8,0x01,0x05,0xff,0xdf,0x00,0xe8,0x01,0x20,0xff,0xa4,0x00,0xe8,0x01,0x22,0xff,0xa4,0x00,0xe8,0x01,0x28,0xff,0xcf,0x00,0xe8,0x01,0x2a,0xff,0xcf,0x00,0xe8,0x01,0x45,0xff,0xdf,0x00,0xe8,0x01,0x76,0xff,0xa4,0x00,0xe8, 0x01,0x85,0xff,0xdf,0x00,0xe8,0x01,0x87,0xff,0xdf,0x00,0xea,0x00,0x0f,0xff,0x50,0x00,0xea,0x00,0x11,0xff,0x3d,0x00,0xea,0x00,0x24,0xff,0x62,0x00,0xea,0x00,0x26,0xff,0xd3,0x00,0xea,0x00,0x2a,0xff,0xd3,0x00,0xea,0x00,0x2d,0xff,0xbe,0x00,0xea,0x00,0x32,0xff,0xd3,0x00,0xea,0x00,0x34,0xff,0xd3,0x00,0xea,0x00,0x36,0xff,0xe5, 0x00,0xea,0x00,0x37,0x00,0x27,0x00,0xea,0x00,0x44,0xff,0x39,0x00,0xea,0x00,0x46,0xff,0x4c,0x00,0xea,0x00,0x47,0xff,0x4c,0x00,0xea,0x00,0x48,0xff,0x4c,0x00,0xea,0x00,0x49,0xff,0xe5,0x00,0xea,0x00,0x4a,0xff,0x4c,0x00,0xea,0x00,0x50,0xff,0x73,0x00,0xea,0x00,0x51,0xff,0x73,0x00,0xea,0x00,0x52,0xff,0x4c,0x00,0xea,0x00,0x53, 0xff,0x73,0x00,0xea,0x00,0x54,0xff,0x4c,0x00,0xea,0x00,0x55,0xff,0x73,0x00,0xea,0x00,0x56,0xff,0x7b,0x00,0xea,0x00,0x58,0xff,0x73,0x00,0xea,0x00,0x62,0xff,0x62,0x00,0xea,0x00,0x63,0xff,0x62,0x00,0xea,0x00,0x64,0xff,0xcd,0x00,0xea,0x00,0x67,0xff,0xd3,0x00,0xea,0x00,0x69,0xff,0x39,0x00,0xea,0x00,0x6a,0xff,0x39,0x00,0xea, 0x00,0x6b,0xff,0x39,0x00,0xea,0x00,0x6c,0xff,0x7f,0x00,0xea,0x00,0x6d,0xff,0x66,0x00,0xea,0x00,0x6e,0xff,0x39,0x00,0xea,0x00,0x6f,0xff,0x4c,0x00,0xea,0x00,0x70,0xff,0x4c,0x00,0xea,0x00,0x71,0xff,0x4c,0x00,0xea,0x00,0x72,0xff,0x4c,0x00,0xea,0x00,0x73,0xff,0x4c,0x00,0xea,0x00,0x77,0x00,0x5a,0x00,0xea,0x00,0x78,0xff,0x73, 0x00,0xea,0x00,0x79,0xff,0x4c,0x00,0xea,0x00,0x7a,0xff,0x4c,0x00,0xea,0x00,0x7b,0xff,0x4c,0x00,0xea,0x00,0x7c,0xff,0x4c,0x00,0xea,0x00,0x7d,0xff,0x4c,0x00,0xea,0x00,0x7e,0xff,0x73,0x00,0xea,0x00,0x7f,0xff,0x73,0x00,0xea,0x00,0x80,0xff,0x73,0x00,0xea,0x00,0x81,0xff,0x73,0x00,0xea,0x00,0x91,0xff,0x3f,0x00,0xea,0x00,0x92, 0xff,0xd3,0x00,0xea,0x00,0xa0,0xff,0x39,0x00,0xea,0x00,0xa2,0xff,0x1b,0x00,0xea,0x00,0xaa,0xff,0xcf,0x00,0xea,0x00,0xac,0xff,0x3d,0x00,0xea,0x00,0xad,0xff,0x62,0x00,0xea,0x00,0xae,0xff,0x62,0x00,0xea,0x00,0xaf,0xff,0xd3,0x00,0xea,0x00,0xb0,0xff,0xd3,0x00,0xea,0x00,0xb1,0xff,0x4c,0x00,0xea,0x00,0xbe,0xff,0x9a,0x00,0xea, 0x00,0xc4,0xff,0x08,0x00,0xea,0x00,0xc5,0xff,0x08,0x00,0xea,0x00,0xc7,0xff,0x62,0x00,0xea,0x00,0xc9,0xff,0x62,0x00,0xea,0x00,0xd0,0xff,0xd3,0x00,0xea,0x00,0xd1,0xff,0xd3,0x00,0xea,0x00,0xd2,0xff,0xd3,0x00,0xea,0x00,0xe3,0xff,0xe5,0x00,0xea,0x00,0xe4,0xff,0x7b,0x00,0xea,0x00,0xf7,0xff,0xd3,0x00,0xea,0x00,0xf8,0xff,0x4c, 0x00,0xea,0x00,0xfa,0xff,0xe5,0x00,0xea,0x00,0xfb,0xff,0x7b,0x00,0xea,0x00,0xfc,0xff,0xd3,0x00,0xea,0x00,0xfd,0xff,0x4c,0x00,0xea,0x00,0xfe,0xff,0xd3,0x00,0xea,0x00,0xff,0xff,0x4c,0x00,0xea,0x01,0x00,0xff,0x4c,0x00,0xea,0x01,0x03,0xff,0x62,0x00,0xea,0x01,0x04,0xff,0x7f,0x00,0xea,0x01,0x05,0xff,0x62,0x00,0xea,0x01,0x06, 0xff,0x39,0x00,0xea,0x01,0x08,0xff,0x4c,0x00,0xea,0x01,0x0b,0xff,0x4c,0x00,0xea,0x01,0x0d,0xff,0x4c,0x00,0xea,0x01,0x15,0xff,0x73,0x00,0xea,0x01,0x17,0xff,0x73,0x00,0xea,0x01,0x18,0xff,0xd3,0x00,0xea,0x01,0x19,0xff,0x4c,0x00,0xea,0x01,0x1b,0xff,0x73,0x00,0xea,0x01,0x1d,0xff,0x73,0x00,0xea,0x01,0x1e,0xff,0xe5,0x00,0xea, 0x01,0x1f,0xff,0x7b,0x00,0xea,0x01,0x20,0x00,0x27,0x00,0xea,0x01,0x22,0x00,0x27,0x00,0xea,0x01,0x25,0xff,0x73,0x00,0xea,0x01,0x27,0xff,0x73,0x00,0xea,0x01,0x45,0xff,0x62,0x00,0xea,0x01,0x46,0xff,0x7f,0x00,0xea,0x01,0x47,0xff,0xd3,0x00,0xea,0x01,0x48,0xff,0x4c,0x00,0xea,0x01,0x4c,0xff,0x4c,0x00,0xea,0x01,0x4e,0xff,0x4c, 0x00,0xea,0x01,0x50,0xff,0x4c,0x00,0xea,0x01,0x51,0xff,0xd3,0x00,0xea,0x01,0x52,0xff,0x4c,0x00,0xea,0x01,0x53,0xff,0xd3,0x00,0xea,0x01,0x54,0xff,0x4c,0x00,0xea,0x01,0x55,0xff,0xd3,0x00,0xea,0x01,0x56,0xff,0x4c,0x00,0xea,0x01,0x5c,0x00,0x5a,0x00,0xea,0x01,0x5e,0x00,0x5a,0x00,0xea,0x01,0x60,0x00,0x5a,0x00,0xea,0x01,0x63, 0xff,0xbe,0x00,0xea,0x01,0x6d,0xff,0x73,0x00,0xea,0x01,0x6e,0xff,0xd3,0x00,0xea,0x01,0x6f,0xff,0x4c,0x00,0xea,0x01,0x70,0xff,0xd3,0x00,0xea,0x01,0x71,0xff,0x4c,0x00,0xea,0x01,0x73,0xff,0x73,0x00,0xea,0x01,0x74,0xff,0xe5,0x00,0xea,0x01,0x75,0xff,0x7b,0x00,0xea,0x01,0x76,0x00,0x27,0x00,0xea,0x01,0x79,0xff,0x73,0x00,0xea, 0x01,0x7b,0xff,0x73,0x00,0xea,0x01,0x7d,0xff,0x73,0x00,0xea,0x01,0x7f,0xff,0x73,0x00,0xea,0x01,0x85,0xff,0x62,0x00,0xea,0x01,0x86,0xff,0x7f,0x00,0xea,0x01,0x87,0xff,0x62,0x00,0xea,0x01,0x88,0xff,0x39,0x00,0xea,0x01,0x89,0xff,0xd3,0x00,0xea,0x01,0x8a,0xff,0x4c,0x00,0xea,0x02,0x3d,0xff,0xe5,0x00,0xea,0x02,0x3e,0xff,0x7b, 0x00,0xeb,0x00,0x05,0x00,0x1d,0x00,0xeb,0x00,0x0a,0x00,0x1d,0x00,0xeb,0x00,0x0f,0xff,0x9a,0x00,0xeb,0x00,0x11,0xff,0x81,0x00,0xeb,0x00,0x22,0xff,0xb4,0x00,0xeb,0x00,0x46,0xff,0xf6,0x00,0xeb,0x00,0x47,0xff,0xf6,0x00,0xeb,0x00,0x48,0xff,0xf6,0x00,0xeb,0x00,0x49,0x00,0x04,0x00,0xeb,0x00,0x4a,0xff,0xf6,0x00,0xeb,0x00,0x52, 0xff,0xf6,0x00,0xeb,0x00,0x54,0xff,0xf6,0x00,0xeb,0x00,0x57,0x00,0x06,0x00,0xeb,0x00,0x6f,0xff,0xf6,0x00,0xeb,0x00,0x70,0xff,0xf6,0x00,0xeb,0x00,0x71,0xff,0xf6,0x00,0xeb,0x00,0x72,0xff,0xf6,0x00,0xeb,0x00,0x73,0xff,0xf6,0x00,0xeb,0x00,0x79,0xff,0xf6,0x00,0xeb,0x00,0x7a,0xff,0xf6,0x00,0xeb,0x00,0x7b,0xff,0xf6,0x00,0xeb, 0x00,0x7c,0xff,0xf6,0x00,0xeb,0x00,0x7d,0xff,0xf6,0x00,0xeb,0x00,0xac,0xff,0x81,0x00,0xeb,0x00,0xb1,0xff,0xf6,0x00,0xeb,0x00,0xbf,0x00,0x0c,0x00,0xeb,0x00,0xc4,0xff,0x8d,0x00,0xeb,0x00,0xc5,0xff,0x8d,0x00,0xeb,0x00,0xf8,0xff,0xf6,0x00,0xeb,0x00,0xfd,0xff,0xf6,0x00,0xeb,0x00,0xff,0xff,0xf6,0x00,0xeb,0x01,0x00,0xff,0xf6, 0x00,0xeb,0x01,0x08,0xff,0xf6,0x00,0xeb,0x01,0x0b,0xff,0xf6,0x00,0xeb,0x01,0x0d,0xff,0xf6,0x00,0xeb,0x01,0x19,0xff,0xf6,0x00,0xeb,0x01,0x21,0x00,0x06,0x00,0xeb,0x01,0x23,0x00,0x06,0x00,0xeb,0x01,0x48,0xff,0xf6,0x00,0xeb,0x01,0x4c,0xff,0xf6,0x00,0xeb,0x01,0x4e,0xff,0xf6,0x00,0xeb,0x01,0x50,0xff,0xf6,0x00,0xeb,0x01,0x52, 0xff,0xf6,0x00,0xeb,0x01,0x54,0xff,0xf6,0x00,0xeb,0x01,0x56,0xff,0xf6,0x00,0xeb,0x01,0x6f,0xff,0xf6,0x00,0xeb,0x01,0x71,0xff,0xf6,0x00,0xeb,0x01,0x77,0x00,0x06,0x00,0xeb,0x01,0x8a,0xff,0xf6,0x00,0xec,0x00,0x0f,0xfe,0xba,0x00,0xec,0x00,0x11,0xfe,0xba,0x00,0xec,0x00,0x24,0xff,0x62,0x00,0xec,0x00,0x2a,0xff,0xf6,0x00,0xec, 0x00,0x2d,0xff,0x7f,0x00,0xec,0x00,0x3a,0x00,0x27,0x00,0xec,0x00,0x3b,0xff,0xc3,0x00,0xec,0x00,0x44,0xff,0xbe,0x00,0xec,0x00,0x46,0xff,0xb4,0x00,0xec,0x00,0x47,0xff,0xb4,0x00,0xec,0x00,0x48,0xff,0xb4,0x00,0xec,0x00,0x4a,0xff,0xb4,0x00,0xec,0x00,0x52,0xff,0xb4,0x00,0xec,0x00,0x54,0xff,0xb6,0x00,0xec,0x00,0x62,0xff,0x62, 0x00,0xec,0x00,0x63,0xff,0x62,0x00,0xec,0x00,0x69,0xff,0xbe,0x00,0xec,0x00,0x6a,0xff,0xbe,0x00,0xec,0x00,0x6b,0xff,0xbe,0x00,0xec,0x00,0x6c,0xff,0xbe,0x00,0xec,0x00,0x6d,0xff,0xbe,0x00,0xec,0x00,0x6e,0xff,0xbe,0x00,0xec,0x00,0x6f,0xff,0xb4,0x00,0xec,0x00,0x70,0xff,0xb4,0x00,0xec,0x00,0x71,0xff,0xb4,0x00,0xec,0x00,0x72, 0xff,0xb4,0x00,0xec,0x00,0x73,0xff,0xb4,0x00,0xec,0x00,0x79,0xff,0xb4,0x00,0xec,0x00,0x7a,0xff,0xb4,0x00,0xec,0x00,0x7b,0xff,0xb4,0x00,0xec,0x00,0x7c,0xff,0xb4,0x00,0xec,0x00,0x7d,0xff,0xb4,0x00,0xec,0x00,0x91,0xfe,0xe9,0x00,0xec,0x00,0xa0,0xff,0xbe,0x00,0xec,0x00,0xac,0xfe,0xba,0x00,0xec,0x00,0xad,0xff,0x62,0x00,0xec, 0x00,0xae,0xff,0x62,0x00,0xec,0x00,0xb1,0xff,0xb4,0x00,0xec,0x00,0xc4,0xfe,0xba,0x00,0xec,0x00,0xc5,0xfe,0xae,0x00,0xec,0x00,0xc7,0xff,0x62,0x00,0xec,0x00,0xc9,0xff,0x62,0x00,0xec,0x00,0xf7,0xff,0xf6,0x00,0xec,0x00,0xf8,0xff,0xb4,0x00,0xec,0x00,0xfd,0xff,0xb4,0x00,0xec,0x00,0xff,0xff,0xb4,0x00,0xec,0x01,0x00,0xff,0xb4, 0x00,0xec,0x01,0x03,0xff,0x62,0x00,0xec,0x01,0x04,0xff,0xbe,0x00,0xec,0x01,0x05,0xff,0x62,0x00,0xec,0x01,0x06,0xff,0xbe,0x00,0xec,0x01,0x08,0xff,0xb4,0x00,0xec,0x01,0x0b,0xff,0xb4,0x00,0xec,0x01,0x0d,0xff,0xb4,0x00,0xec,0x01,0x19,0xff,0xb4,0x00,0xec,0x01,0x45,0xff,0x62,0x00,0xec,0x01,0x46,0xff,0xbe,0x00,0xec,0x01,0x48, 0xff,0xb4,0x00,0xec,0x01,0x4c,0xff,0xb4,0x00,0xec,0x01,0x4e,0xff,0xb4,0x00,0xec,0x01,0x50,0xff,0xb4,0x00,0xec,0x01,0x51,0xff,0xf6,0x00,0xec,0x01,0x52,0xff,0xb4,0x00,0xec,0x01,0x53,0xff,0xf6,0x00,0xec,0x01,0x54,0xff,0xb4,0x00,0xec,0x01,0x55,0xff,0xf6,0x00,0xec,0x01,0x56,0xff,0xb4,0x00,0xec,0x01,0x63,0xff,0x7f,0x00,0xec, 0x01,0x6f,0xff,0xb4,0x00,0xec,0x01,0x71,0xff,0xb4,0x00,0xec,0x01,0x80,0x00,0x27,0x00,0xec,0x01,0x85,0xff,0x62,0x00,0xec,0x01,0x86,0xff,0xbe,0x00,0xec,0x01,0x87,0xff,0x62,0x00,0xec,0x01,0x88,0xff,0xbe,0x00,0xec,0x01,0x8a,0xff,0xb4,0x00,0xec,0x01,0x8c,0x00,0x27,0x00,0xec,0x01,0x8e,0x00,0x27,0x00,0xec,0x01,0x90,0x00,0x27, 0x00,0xed,0x00,0x44,0xff,0xe5,0x00,0xed,0x00,0x49,0xff,0xf6,0x00,0xed,0x00,0x5b,0xff,0xe7,0x00,0xed,0x00,0x69,0xff,0xe5,0x00,0xed,0x00,0x6a,0xff,0xe5,0x00,0xed,0x00,0x6b,0xff,0xe5,0x00,0xed,0x00,0x6c,0xff,0xe5,0x00,0xed,0x00,0x6d,0xff,0xe5,0x00,0xed,0x00,0x6e,0xff,0xe5,0x00,0xed,0x00,0xa0,0xff,0xe5,0x00,0xed,0x00,0xc0, 0xff,0xf6,0x00,0xed,0x00,0xc1,0xff,0xf6,0x00,0xed,0x01,0x04,0xff,0xe5,0x00,0xed,0x01,0x06,0xff,0xe5,0x00,0xed,0x01,0x46,0xff,0xe5,0x00,0xed,0x01,0x86,0xff,0xe5,0x00,0xed,0x01,0x88,0xff,0xe5,0x00,0xf7,0x00,0x37,0xff,0xcf,0x00,0xf7,0x00,0x39,0xff,0xe5,0x00,0xf7,0x00,0x5c,0xff,0xe5,0x00,0xf7,0x00,0xba,0xff,0xe5,0x00,0xf7, 0x00,0xeb,0xff,0xe5,0x00,0xf7,0x01,0x20,0xff,0xcf,0x00,0xf7,0x01,0x22,0xff,0xcf,0x00,0xf7,0x01,0x76,0xff,0xcf,0x00,0xf7,0x01,0x83,0xff,0xe5,0x00,0xf7,0x01,0x93,0xff,0xe5,0x00,0xf8,0x00,0x4d,0x00,0x2f,0x00,0xf8,0x01,0x64,0x00,0x2f,0x00,0xfa,0x00,0x57,0xff,0xbe,0x00,0xfa,0x00,0x59,0xff,0xcf,0x00,0xfa,0x00,0x5a,0xff,0xe5, 0x00,0xfa,0x00,0x5c,0xff,0xd1,0x00,0xfa,0x00,0xba,0xff,0xbe,0x00,0xfa,0x00,0xc4,0xff,0xb2,0x00,0xfa,0x00,0xc5,0xff,0xb2,0x00,0xfa,0x00,0xeb,0xff,0xd1,0x00,0xfa,0x01,0x21,0xff,0xbe,0x00,0xfa,0x01,0x23,0xff,0xbe,0x00,0xfa,0x01,0x77,0xff,0xbe,0x00,0xfa,0x01,0x81,0xff,0xe5,0x00,0xfa,0x01,0x83,0xff,0xd1,0x00,0xfa,0x01,0x8d, 0xff,0xe5,0x00,0xfa,0x01,0x8f,0xff,0xe5,0x00,0xfa,0x01,0x91,0xff,0xe5,0x00,0xfa,0x01,0x93,0xff,0xd1,0x00,0xfc,0x00,0x26,0xff,0xc9,0x00,0xfc,0x00,0x2a,0xff,0xc9,0x00,0xfc,0x00,0x32,0xff,0xe5,0x00,0xfc,0x00,0x34,0xff,0xc9,0x00,0xfc,0x00,0x64,0xff,0xc9,0x00,0xfc,0x00,0x67,0xff,0xc9,0x00,0xfc,0x00,0x77,0x00,0x1d,0x00,0xfc, 0x00,0x92,0xff,0xc9,0x00,0xfc,0x00,0xaa,0xff,0xcf,0x00,0xfc,0x00,0xaf,0xff,0xc9,0x00,0xfc,0x00,0xb0,0xff,0xc9,0x00,0xfc,0x00,0xbe,0xff,0xcf,0x00,0xfc,0x00,0xd0,0xff,0xc9,0x00,0xfc,0x00,0xd1,0xff,0xc9,0x00,0xfc,0x00,0xd2,0xff,0xc9,0x00,0xfc,0x00,0xf7,0xff,0xc9,0x00,0xfc,0x00,0xfc,0xff,0xc9,0x00,0xfc,0x00,0xfe,0xff,0xc9, 0x00,0xfc,0x01,0x18,0xff,0xe5,0x00,0xfc,0x01,0x47,0xff,0xc9,0x00,0xfc,0x01,0x51,0xff,0xc9,0x00,0xfc,0x01,0x53,0xff,0xc9,0x00,0xfc,0x01,0x55,0xff,0xc9,0x00,0xfc,0x01,0x5c,0x00,0x1d,0x00,0xfc,0x01,0x5e,0x00,0x1d,0x00,0xfc,0x01,0x60,0x00,0x1d,0x00,0xfc,0x01,0x6e,0xff,0xe5,0x00,0xfc,0x01,0x70,0xff,0xe5,0x00,0xfc,0x01,0x89, 0xff,0xe5,0x00,0xfd,0x00,0x2d,0x00,0x46,0x00,0xfd,0x00,0x37,0xff,0x9a,0x00,0xfd,0x00,0x3c,0xff,0xb4,0x00,0xfd,0x00,0xea,0xff,0xb4,0x00,0xfd,0x01,0x20,0xff,0x9a,0x00,0xfd,0x01,0x22,0xff,0x9a,0x00,0xfd,0x01,0x63,0x00,0x46,0x00,0xfd,0x01,0x76,0xff,0x9a,0x00,0xfd,0x01,0x82,0xff,0xb4,0x00,0xfd,0x01,0x92,0xff,0xb4,0x00,0xfe, 0x00,0x26,0xff,0xc9,0x00,0xfe,0x00,0x2a,0xff,0xc9,0x00,0xfe,0x00,0x32,0xff,0xe5,0x00,0xfe,0x00,0x34,0xff,0xc9,0x00,0xfe,0x00,0x64,0xff,0xc9,0x00,0xfe,0x00,0x67,0xff,0xc9,0x00,0xfe,0x00,0x77,0x00,0x1d,0x00,0xfe,0x00,0x92,0xff,0xc9,0x00,0xfe,0x00,0xaa,0xff,0xcf,0x00,0xfe,0x00,0xaf,0xff,0xc9,0x00,0xfe,0x00,0xb0,0xff,0xc9, 0x00,0xfe,0x00,0xbe,0xff,0xcf,0x00,0xfe,0x00,0xd0,0xff,0xc9,0x00,0xfe,0x00,0xd1,0xff,0xc9,0x00,0xfe,0x00,0xd2,0xff,0xc9,0x00,0xfe,0x00,0xf7,0xff,0xc9,0x00,0xfe,0x00,0xfc,0xff,0xc9,0x00,0xfe,0x00,0xfe,0xff,0xc9,0x00,0xfe,0x01,0x18,0xff,0xe5,0x00,0xfe,0x01,0x47,0xff,0xc9,0x00,0xfe,0x01,0x51,0xff,0xc9,0x00,0xfe,0x01,0x53, 0xff,0xc9,0x00,0xfe,0x01,0x55,0xff,0xc9,0x00,0xfe,0x01,0x5c,0x00,0x1d,0x00,0xfe,0x01,0x5e,0x00,0x1d,0x00,0xfe,0x01,0x60,0x00,0x1d,0x00,0xfe,0x01,0x6e,0xff,0xe5,0x00,0xfe,0x01,0x70,0xff,0xe5,0x00,0xfe,0x01,0x89,0xff,0xe5,0x00,0xff,0x00,0x2d,0x00,0x46,0x00,0xff,0x00,0x37,0xff,0x9a,0x00,0xff,0x00,0x3c,0xff,0xb4,0x00,0xff, 0x00,0xea,0xff,0xb4,0x00,0xff,0x01,0x20,0xff,0x9a,0x00,0xff,0x01,0x22,0xff,0x9a,0x00,0xff,0x01,0x63,0x00,0x46,0x00,0xff,0x01,0x76,0xff,0x9a,0x00,0xff,0x01,0x82,0xff,0xb4,0x00,0xff,0x01,0x92,0xff,0xb4,0x01,0x03,0x00,0x0d,0xff,0x7f,0x01,0x03,0x00,0x0f,0x00,0x44,0x01,0x03,0x00,0x1e,0x00,0x44,0x01,0x03,0x00,0x26,0xff,0xe5, 0x01,0x03,0x00,0x2a,0xff,0xe5,0x01,0x03,0x00,0x2d,0x00,0x5e,0x01,0x03,0x00,0x32,0xff,0xe5,0x01,0x03,0x00,0x37,0xff,0x6d,0x01,0x03,0x00,0x38,0xff,0xe5,0x01,0x03,0x00,0x39,0xff,0x8b,0x01,0x03,0x00,0x3a,0xff,0xb6,0x01,0x03,0x00,0x3c,0xff,0x64,0x01,0x03,0x00,0x3d,0x00,0x3b,0x01,0x03,0x00,0x57,0xff,0xe5,0x01,0x03,0x00,0x59, 0xff,0xd5,0x01,0x03,0x00,0x5a,0xff,0xe5,0x01,0x03,0x00,0x5c,0xff,0xdb,0x01,0x03,0x00,0x8d,0xff,0x9a,0x01,0x03,0x00,0xb4,0xff,0x66,0x01,0x03,0x00,0xb5,0xff,0x3f,0x01,0x03,0x00,0xb6,0xff,0x66,0x01,0x03,0x00,0xb7,0xff,0x3f,0x01,0x03,0x00,0xba,0xff,0xc1,0x01,0x03,0x00,0xbb,0xff,0x64,0x01,0x03,0x00,0xe5,0x00,0x3b,0x01,0x03, 0x00,0xea,0xff,0x64,0x01,0x03,0x00,0xeb,0xff,0xdb,0x01,0x03,0x00,0xf7,0xff,0xe5,0x01,0x03,0x00,0xfc,0xff,0xe5,0x01,0x03,0x00,0xfe,0xff,0xe5,0x01,0x03,0x01,0x18,0xff,0xe5,0x01,0x03,0x01,0x20,0xff,0x6d,0x01,0x03,0x01,0x21,0xff,0xe5,0x01,0x03,0x01,0x22,0xff,0x6d,0x01,0x03,0x01,0x23,0xff,0xe5,0x01,0x03,0x01,0x24,0xff,0xe5, 0x01,0x03,0x01,0x26,0xff,0xe5,0x01,0x03,0x01,0x28,0x00,0x3b,0x01,0x03,0x01,0x2a,0x00,0x3b,0x01,0x03,0x01,0x47,0xff,0xe5,0x01,0x03,0x01,0x51,0xff,0xe5,0x01,0x03,0x01,0x53,0xff,0xe5,0x01,0x03,0x01,0x55,0xff,0xe5,0x01,0x03,0x01,0x63,0x00,0x5e,0x01,0x03,0x01,0x6e,0xff,0xe5,0x01,0x03,0x01,0x70,0xff,0xe5,0x01,0x03,0x01,0x76, 0xff,0x6d,0x01,0x03,0x01,0x77,0xff,0xe5,0x01,0x03,0x01,0x78,0xff,0xe5,0x01,0x03,0x01,0x7a,0xff,0xe5,0x01,0x03,0x01,0x7c,0xff,0xe5,0x01,0x03,0x01,0x7e,0xff,0xe5,0x01,0x03,0x01,0x80,0xff,0xb6,0x01,0x03,0x01,0x81,0xff,0xe5,0x01,0x03,0x01,0x82,0xff,0x64,0x01,0x03,0x01,0x83,0xff,0xdb,0x01,0x03,0x01,0x89,0xff,0xe5,0x01,0x03, 0x01,0x8c,0xff,0xb6,0x01,0x03,0x01,0x8d,0xff,0xe5,0x01,0x03,0x01,0x8e,0xff,0xb6,0x01,0x03,0x01,0x8f,0xff,0xe5,0x01,0x03,0x01,0x90,0xff,0xb6,0x01,0x03,0x01,0x91,0xff,0xe5,0x01,0x03,0x01,0x92,0xff,0x64,0x01,0x03,0x01,0x93,0xff,0xdb,0x01,0x05,0x00,0x0d,0xff,0x7f,0x01,0x05,0x00,0x0f,0x00,0x44,0x01,0x05,0x00,0x1e,0x00,0x44, 0x01,0x05,0x00,0x26,0xff,0xe5,0x01,0x05,0x00,0x2a,0xff,0xe5,0x01,0x05,0x00,0x2d,0x00,0x5e,0x01,0x05,0x00,0x32,0xff,0xe5,0x01,0x05,0x00,0x37,0xff,0x6d,0x01,0x05,0x00,0x38,0xff,0xe5,0x01,0x05,0x00,0x39,0xff,0x8b,0x01,0x05,0x00,0x3a,0xff,0xb6,0x01,0x05,0x00,0x3c,0xff,0x64,0x01,0x05,0x00,0x3d,0x00,0x3b,0x01,0x05,0x00,0x57, 0xff,0xe5,0x01,0x05,0x00,0x59,0xff,0xd5,0x01,0x05,0x00,0x5a,0xff,0xe5,0x01,0x05,0x00,0x5c,0xff,0xdb,0x01,0x05,0x00,0x8d,0xff,0x9a,0x01,0x05,0x00,0xb4,0xff,0x66,0x01,0x05,0x00,0xb5,0xff,0x3f,0x01,0x05,0x00,0xb6,0xff,0x66,0x01,0x05,0x00,0xb7,0xff,0x3f,0x01,0x05,0x00,0xba,0xff,0xc1,0x01,0x05,0x00,0xbb,0xff,0x64,0x01,0x05, 0x00,0xe5,0x00,0x3b,0x01,0x05,0x00,0xea,0xff,0x64,0x01,0x05,0x00,0xeb,0xff,0xdb,0x01,0x05,0x00,0xf7,0xff,0xe5,0x01,0x05,0x00,0xfc,0xff,0xe5,0x01,0x05,0x00,0xfe,0xff,0xe5,0x01,0x05,0x01,0x18,0xff,0xe5,0x01,0x05,0x01,0x20,0xff,0x6d,0x01,0x05,0x01,0x21,0xff,0xe5,0x01,0x05,0x01,0x22,0xff,0x6d,0x01,0x05,0x01,0x23,0xff,0xe5, 0x01,0x05,0x01,0x24,0xff,0xe5,0x01,0x05,0x01,0x26,0xff,0xe5,0x01,0x05,0x01,0x28,0x00,0x3b,0x01,0x05,0x01,0x2a,0x00,0x3b,0x01,0x05,0x01,0x47,0xff,0xe5,0x01,0x05,0x01,0x51,0xff,0xe5,0x01,0x05,0x01,0x53,0xff,0xe5,0x01,0x05,0x01,0x55,0xff,0xe5,0x01,0x05,0x01,0x63,0x00,0x5e,0x01,0x05,0x01,0x6e,0xff,0xe5,0x01,0x05,0x01,0x70, 0xff,0xe5,0x01,0x05,0x01,0x76,0xff,0x6d,0x01,0x05,0x01,0x77,0xff,0xe5,0x01,0x05,0x01,0x78,0xff,0xe5,0x01,0x05,0x01,0x7a,0xff,0xe5,0x01,0x05,0x01,0x7c,0xff,0xe5,0x01,0x05,0x01,0x7e,0xff,0xe5,0x01,0x05,0x01,0x80,0xff,0xb6,0x01,0x05,0x01,0x81,0xff,0xe5,0x01,0x05,0x01,0x82,0xff,0x64,0x01,0x05,0x01,0x83,0xff,0xdb,0x01,0x05, 0x01,0x89,0xff,0xe5,0x01,0x05,0x01,0x8c,0xff,0xb6,0x01,0x05,0x01,0x8d,0xff,0xe5,0x01,0x05,0x01,0x8e,0xff,0xb6,0x01,0x05,0x01,0x8f,0xff,0xe5,0x01,0x05,0x01,0x90,0xff,0xb6,0x01,0x05,0x01,0x91,0xff,0xe5,0x01,0x05,0x01,0x92,0xff,0x64,0x01,0x05,0x01,0x93,0xff,0xdb,0x01,0x07,0x00,0x0f,0xff,0x7f,0x01,0x07,0x00,0x11,0xff,0x7f, 0x01,0x07,0x00,0x24,0xff,0xdf,0x01,0x07,0x00,0x37,0xff,0xa4,0x01,0x07,0x00,0x3b,0xff,0xcb,0x01,0x07,0x00,0x3d,0xff,0xcf,0x01,0x07,0x00,0x62,0xff,0xdf,0x01,0x07,0x00,0x63,0xff,0xdf,0x01,0x07,0x00,0x91,0xff,0xb6,0x01,0x07,0x00,0xac,0xff,0x7f,0x01,0x07,0x00,0xad,0xff,0xdf,0x01,0x07,0x00,0xae,0xff,0xdf,0x01,0x07,0x00,0xbb, 0xff,0xf6,0x01,0x07,0x00,0xc4,0xff,0x8b,0x01,0x07,0x00,0xc5,0xff,0x8b,0x01,0x07,0x00,0xc7,0xff,0xdf,0x01,0x07,0x00,0xc9,0xff,0xdf,0x01,0x07,0x00,0xe5,0xff,0xcf,0x01,0x07,0x01,0x03,0xff,0xdf,0x01,0x07,0x01,0x05,0xff,0xdf,0x01,0x07,0x01,0x20,0xff,0xa4,0x01,0x07,0x01,0x22,0xff,0xa4,0x01,0x07,0x01,0x28,0xff,0xcf,0x01,0x07, 0x01,0x2a,0xff,0xcf,0x01,0x07,0x01,0x45,0xff,0xdf,0x01,0x07,0x01,0x76,0xff,0xa4,0x01,0x07,0x01,0x85,0xff,0xdf,0x01,0x07,0x01,0x87,0xff,0xdf,0x01,0x0a,0x00,0x24,0x00,0x0a,0x01,0x0a,0x00,0x2d,0x00,0x44,0x01,0x0a,0x00,0x37,0x00,0x04,0x01,0x0a,0x00,0x3a,0x00,0x1d,0x01,0x0a,0x00,0x3b,0x00,0x08,0x01,0x0a,0x00,0x62,0x00,0x0a, 0x01,0x0a,0x00,0x63,0x00,0x0a,0x01,0x0a,0x00,0x77,0x00,0x12,0x01,0x0a,0x00,0xad,0x00,0x0a,0x01,0x0a,0x00,0xae,0x00,0x0a,0x01,0x0a,0x00,0xc7,0x00,0x0a,0x01,0x0a,0x00,0xc9,0x00,0x0a,0x01,0x0a,0x01,0x03,0x00,0x0a,0x01,0x0a,0x01,0x05,0x00,0x0a,0x01,0x0a,0x01,0x20,0x00,0x04,0x01,0x0a,0x01,0x22,0x00,0x04,0x01,0x0a,0x01,0x45, 0x00,0x0a,0x01,0x0a,0x01,0x5c,0x00,0x12,0x01,0x0a,0x01,0x5e,0x00,0x12,0x01,0x0a,0x01,0x60,0x00,0x12,0x01,0x0a,0x01,0x63,0x00,0x44,0x01,0x0a,0x01,0x76,0x00,0x04,0x01,0x0a,0x01,0x80,0x00,0x1d,0x01,0x0a,0x01,0x85,0x00,0x0a,0x01,0x0a,0x01,0x87,0x00,0x0a,0x01,0x0a,0x01,0x8c,0x00,0x1d,0x01,0x0a,0x01,0x8e,0x00,0x1d,0x01,0x0a, 0x01,0x90,0x00,0x1d,0x01,0x0b,0x00,0x05,0xff,0x98,0x01,0x0b,0x00,0x0a,0xff,0x98,0x01,0x0c,0x00,0x24,0x00,0x0a,0x01,0x0c,0x00,0x2d,0x00,0x44,0x01,0x0c,0x00,0x37,0x00,0x04,0x01,0x0c,0x00,0x3a,0x00,0x1d,0x01,0x0c,0x00,0x3b,0x00,0x08,0x01,0x0c,0x00,0x62,0x00,0x0a,0x01,0x0c,0x00,0x63,0x00,0x0a,0x01,0x0c,0x00,0x77,0x00,0x12, 0x01,0x0c,0x00,0xad,0x00,0x0a,0x01,0x0c,0x00,0xae,0x00,0x0a,0x01,0x0c,0x00,0xc7,0x00,0x0a,0x01,0x0c,0x00,0xc9,0x00,0x0a,0x01,0x0c,0x01,0x03,0x00,0x0a,0x01,0x0c,0x01,0x05,0x00,0x0a,0x01,0x0c,0x01,0x20,0x00,0x04,0x01,0x0c,0x01,0x22,0x00,0x04,0x01,0x0c,0x01,0x45,0x00,0x0a,0x01,0x0c,0x01,0x5c,0x00,0x12,0x01,0x0c,0x01,0x5e, 0x00,0x12,0x01,0x0c,0x01,0x60,0x00,0x12,0x01,0x0c,0x01,0x63,0x00,0x44,0x01,0x0c,0x01,0x76,0x00,0x04,0x01,0x0c,0x01,0x80,0x00,0x1d,0x01,0x0c,0x01,0x85,0x00,0x0a,0x01,0x0c,0x01,0x87,0x00,0x0a,0x01,0x0c,0x01,0x8c,0x00,0x1d,0x01,0x0c,0x01,0x8e,0x00,0x1d,0x01,0x0c,0x01,0x90,0x00,0x1d,0x01,0x0d,0x00,0x05,0xff,0x98,0x01,0x0d, 0x00,0x0a,0xff,0x98,0x01,0x0e,0x00,0x0d,0xff,0x31,0x01,0x0e,0x00,0x22,0xff,0x9a,0x01,0x0e,0x00,0x24,0x00,0x3b,0x01,0x0e,0x00,0x26,0xff,0xbe,0x01,0x0e,0x00,0x2a,0xff,0xbe,0x01,0x0e,0x00,0x2d,0x00,0x64,0x01,0x0e,0x00,0x32,0xff,0xba,0x01,0x0e,0x00,0x34,0xff,0xba,0x01,0x0e,0x00,0x37,0xff,0x8f,0x01,0x0e,0x00,0x38,0xff,0xe3, 0x01,0x0e,0x00,0x39,0xff,0x8b,0x01,0x0e,0x00,0x3a,0xff,0xcf,0x01,0x0e,0x00,0x3c,0xff,0x7f,0x01,0x0e,0x00,0x3d,0x00,0x3b,0x01,0x0e,0x00,0x57,0xff,0xe5,0x01,0x0e,0x00,0x59,0xff,0x9a,0x01,0x0e,0x00,0x5a,0xff,0xbe,0x01,0x0e,0x00,0x5c,0xff,0xb4,0x01,0x0e,0x00,0x64,0xff,0xbe,0x01,0x0e,0x00,0x67,0xff,0xba,0x01,0x0e,0x00,0x68, 0xff,0xe3,0x01,0x0e,0x00,0x8d,0xff,0x9a,0x01,0x0e,0x00,0x92,0xff,0xba,0x01,0x0e,0x00,0xaf,0xff,0xba,0x01,0x0e,0x00,0xb0,0xff,0xba,0x01,0x0e,0x00,0xb4,0xff,0x73,0x01,0x0e,0x00,0xb5,0xff,0x8b,0x01,0x0e,0x00,0xb6,0xff,0x73,0x01,0x0e,0x00,0xb7,0xff,0x7f,0x01,0x0e,0x00,0xba,0xff,0xb4,0x01,0x0e,0x00,0xbb,0xff,0x9a,0x01,0x0e, 0x00,0xc4,0x00,0x44,0x01,0x0e,0x00,0xc5,0x00,0x44,0x01,0x0e,0x00,0xd0,0xff,0xba,0x01,0x0e,0x00,0xd1,0xff,0xba,0x01,0x0e,0x00,0xd2,0xff,0xba,0x01,0x0e,0x00,0xd3,0xff,0xe3,0x01,0x0e,0x00,0xd4,0xff,0xe3,0x01,0x0e,0x00,0xd5,0xff,0xe3,0x01,0x0e,0x00,0xe5,0x00,0x3b,0x01,0x0e,0x00,0xea,0xff,0x7f,0x01,0x0e,0x00,0xeb,0xff,0xb4, 0x01,0x0e,0x00,0xf7,0xff,0xbe,0x01,0x0e,0x00,0xfc,0xff,0xbe,0x01,0x0e,0x00,0xfe,0xff,0xbe,0x01,0x0e,0x01,0x03,0x00,0x3b,0x01,0x0e,0x01,0x05,0x00,0x3b,0x01,0x0e,0x01,0x18,0xff,0xba,0x01,0x0e,0x01,0x20,0xff,0x8f,0x01,0x0e,0x01,0x21,0xff,0xe5,0x01,0x0e,0x01,0x22,0xff,0x8f,0x01,0x0e,0x01,0x23,0xff,0xe5,0x01,0x0e,0x01,0x24, 0xff,0xe3,0x01,0x0e,0x01,0x26,0xff,0xe3,0x01,0x0e,0x01,0x28,0x00,0x3b,0x01,0x0e,0x01,0x2a,0x00,0x3b,0x01,0x0e,0x01,0x45,0x00,0x3b,0x01,0x0e,0x01,0x47,0xff,0xbe,0x01,0x0e,0x01,0x51,0xff,0xbe,0x01,0x0e,0x01,0x53,0xff,0xbe,0x01,0x0e,0x01,0x55,0xff,0xbe,0x01,0x0e,0x01,0x63,0x00,0x64,0x01,0x0e,0x01,0x6e,0xff,0xba,0x01,0x0e, 0x01,0x70,0xff,0xba,0x01,0x0e,0x01,0x76,0xff,0x8f,0x01,0x0e,0x01,0x77,0xff,0xe5,0x01,0x0e,0x01,0x78,0xff,0xe3,0x01,0x0e,0x01,0x7a,0xff,0xe3,0x01,0x0e,0x01,0x7c,0xff,0xe3,0x01,0x0e,0x01,0x7e,0xff,0xe3,0x01,0x0e,0x01,0x80,0xff,0xcf,0x01,0x0e,0x01,0x81,0xff,0xbe,0x01,0x0e,0x01,0x82,0xff,0x7f,0x01,0x0e,0x01,0x83,0xff,0xb4, 0x01,0x0e,0x01,0x85,0x00,0x3b,0x01,0x0e,0x01,0x87,0x00,0x3b,0x01,0x0e,0x01,0x89,0xff,0xba,0x01,0x0e,0x01,0x8c,0xff,0xcf,0x01,0x0e,0x01,0x8d,0xff,0xbe,0x01,0x0e,0x01,0x8e,0xff,0xcf,0x01,0x0e,0x01,0x8f,0xff,0xbe,0x01,0x0e,0x01,0x90,0xff,0xcf,0x01,0x0e,0x01,0x91,0xff,0xbe,0x01,0x0e,0x01,0x92,0xff,0x7f,0x01,0x0e,0x01,0x93, 0xff,0xb4,0x01,0x10,0x00,0x0d,0xff,0x31,0x01,0x10,0x00,0x22,0xff,0x9a,0x01,0x10,0x00,0x24,0x00,0x3b,0x01,0x10,0x00,0x26,0xff,0xbe,0x01,0x10,0x00,0x2a,0xff,0xbe,0x01,0x10,0x00,0x2d,0x00,0x64,0x01,0x10,0x00,0x32,0xff,0xba,0x01,0x10,0x00,0x34,0xff,0xba,0x01,0x10,0x00,0x37,0xff,0x8f,0x01,0x10,0x00,0x38,0xff,0xe3,0x01,0x10, 0x00,0x39,0xff,0x8b,0x01,0x10,0x00,0x3a,0xff,0xcf,0x01,0x10,0x00,0x3c,0xff,0x7f,0x01,0x10,0x00,0x3d,0x00,0x3b,0x01,0x10,0x00,0x57,0xff,0xe5,0x01,0x10,0x00,0x59,0xff,0x9a,0x01,0x10,0x00,0x5a,0xff,0xbe,0x01,0x10,0x00,0x5c,0xff,0xb4,0x01,0x10,0x00,0x64,0xff,0xbe,0x01,0x10,0x00,0x67,0xff,0xba,0x01,0x10,0x00,0x68,0xff,0xe3, 0x01,0x10,0x00,0x8d,0xff,0x9a,0x01,0x10,0x00,0x92,0xff,0xba,0x01,0x10,0x00,0xaf,0xff,0xba,0x01,0x10,0x00,0xb0,0xff,0xba,0x01,0x10,0x00,0xb4,0xff,0x73,0x01,0x10,0x00,0xb5,0xff,0x8b,0x01,0x10,0x00,0xb6,0xff,0x73,0x01,0x10,0x00,0xb7,0xff,0x7f,0x01,0x10,0x00,0xba,0xff,0xb4,0x01,0x10,0x00,0xbb,0xff,0x9a,0x01,0x10,0x00,0xc4, 0x00,0x44,0x01,0x10,0x00,0xc5,0x00,0x44,0x01,0x10,0x00,0xd0,0xff,0xba,0x01,0x10,0x00,0xd1,0xff,0xba,0x01,0x10,0x00,0xd2,0xff,0xba,0x01,0x10,0x00,0xd3,0xff,0xe3,0x01,0x10,0x00,0xd4,0xff,0xe3,0x01,0x10,0x00,0xd5,0xff,0xe3,0x01,0x10,0x00,0xe5,0x00,0x3b,0x01,0x10,0x00,0xea,0xff,0x7f,0x01,0x10,0x00,0xeb,0xff,0xb4,0x01,0x10, 0x00,0xf7,0xff,0xbe,0x01,0x10,0x00,0xfc,0xff,0xbe,0x01,0x10,0x00,0xfe,0xff,0xbe,0x01,0x10,0x01,0x03,0x00,0x3b,0x01,0x10,0x01,0x05,0x00,0x3b,0x01,0x10,0x01,0x20,0xff,0x8f,0x01,0x10,0x01,0x21,0xff,0xe5,0x01,0x10,0x01,0x22,0xff,0x8f,0x01,0x10,0x01,0x23,0xff,0xe5,0x01,0x10,0x01,0x24,0xff,0xe3,0x01,0x10,0x01,0x26,0xff,0xe3, 0x01,0x10,0x01,0x28,0x00,0x3b,0x01,0x10,0x01,0x2a,0x00,0x3b,0x01,0x10,0x01,0x45,0x00,0x3b,0x01,0x10,0x01,0x47,0xff,0xbe,0x01,0x10,0x01,0x51,0xff,0xbe,0x01,0x10,0x01,0x53,0xff,0xbe,0x01,0x10,0x01,0x55,0xff,0xbe,0x01,0x10,0x01,0x63,0x00,0x64,0x01,0x10,0x01,0x6e,0xff,0xba,0x01,0x10,0x01,0x70,0xff,0xba,0x01,0x10,0x01,0x76, 0xff,0x8f,0x01,0x10,0x01,0x77,0xff,0xe5,0x01,0x10,0x01,0x78,0xff,0xe3,0x01,0x10,0x01,0x7a,0xff,0xe3,0x01,0x10,0x01,0x7c,0xff,0xe3,0x01,0x10,0x01,0x7e,0xff,0xe3,0x01,0x10,0x01,0x80,0xff,0xcf,0x01,0x10,0x01,0x81,0xff,0xbe,0x01,0x10,0x01,0x82,0xff,0x7f,0x01,0x10,0x01,0x83,0xff,0xb4,0x01,0x10,0x01,0x85,0x00,0x3b,0x01,0x10, 0x01,0x87,0x00,0x3b,0x01,0x10,0x01,0x89,0xff,0xba,0x01,0x10,0x01,0x8c,0xff,0xcf,0x01,0x10,0x01,0x8d,0xff,0xbe,0x01,0x10,0x01,0x8e,0xff,0xcf,0x01,0x10,0x01,0x8f,0xff,0xbe,0x01,0x10,0x01,0x90,0xff,0xcf,0x01,0x10,0x01,0x91,0xff,0xbe,0x01,0x10,0x01,0x92,0xff,0x7f,0x01,0x10,0x01,0x93,0xff,0xb4,0x01,0x12,0x00,0x0d,0xff,0x31, 0x01,0x12,0x00,0x22,0xff,0x9a,0x01,0x12,0x00,0x24,0x00,0x3b,0x01,0x12,0x00,0x26,0xff,0xbe,0x01,0x12,0x00,0x2a,0xff,0xbe,0x01,0x12,0x00,0x2d,0x00,0x64,0x01,0x12,0x00,0x32,0xff,0xba,0x01,0x12,0x00,0x34,0xff,0xba,0x01,0x12,0x00,0x37,0xff,0x8f,0x01,0x12,0x00,0x38,0xff,0xe3,0x01,0x12,0x00,0x39,0xff,0x8b,0x01,0x12,0x00,0x3a, 0xff,0xcf,0x01,0x12,0x00,0x3c,0xff,0x7f,0x01,0x12,0x00,0x3d,0x00,0x3b,0x01,0x12,0x00,0x57,0xff,0xe5,0x01,0x12,0x00,0x59,0xff,0x9a,0x01,0x12,0x00,0x5a,0xff,0xbe,0x01,0x12,0x00,0x5c,0xff,0xb4,0x01,0x12,0x00,0x64,0xff,0xbe,0x01,0x12,0x00,0x67,0xff,0xba,0x01,0x12,0x00,0x68,0xff,0xe3,0x01,0x12,0x00,0x8d,0xff,0x9a,0x01,0x12, 0x00,0x92,0xff,0xba,0x01,0x12,0x00,0xaf,0xff,0xba,0x01,0x12,0x00,0xb0,0xff,0xba,0x01,0x12,0x00,0xb4,0xff,0x73,0x01,0x12,0x00,0xb5,0xff,0x8b,0x01,0x12,0x00,0xb6,0xff,0x73,0x01,0x12,0x00,0xb7,0xff,0x7f,0x01,0x12,0x00,0xba,0xff,0xb4,0x01,0x12,0x00,0xbb,0xff,0x9a,0x01,0x12,0x00,0xc4,0x00,0x44,0x01,0x12,0x00,0xc5,0x00,0x44, 0x01,0x12,0x00,0xd0,0xff,0xba,0x01,0x12,0x00,0xd1,0xff,0xba,0x01,0x12,0x00,0xd2,0xff,0xba,0x01,0x12,0x00,0xd3,0xff,0xe3,0x01,0x12,0x00,0xd4,0xff,0xe3,0x01,0x12,0x00,0xd5,0xff,0xe3,0x01,0x12,0x00,0xe5,0x00,0x3b,0x01,0x12,0x00,0xea,0xff,0x7f,0x01,0x12,0x00,0xeb,0xff,0xb4,0x01,0x12,0x00,0xf7,0xff,0xbe,0x01,0x12,0x00,0xfc, 0xff,0xbe,0x01,0x12,0x00,0xfe,0xff,0xbe,0x01,0x12,0x01,0x03,0x00,0x3b,0x01,0x12,0x01,0x05,0x00,0x3b,0x01,0x12,0x01,0x18,0xff,0xba,0x01,0x12,0x01,0x20,0xff,0x8f,0x01,0x12,0x01,0x21,0xff,0xe5,0x01,0x12,0x01,0x22,0xff,0x8f,0x01,0x12,0x01,0x23,0xff,0xe5,0x01,0x12,0x01,0x24,0xff,0xe3,0x01,0x12,0x01,0x26,0xff,0xe3,0x01,0x12, 0x01,0x28,0x00,0x3b,0x01,0x12,0x01,0x2a,0x00,0x3b,0x01,0x12,0x01,0x45,0x00,0x3b,0x01,0x12,0x01,0x47,0xff,0xbe,0x01,0x12,0x01,0x51,0xff,0xbe,0x01,0x12,0x01,0x53,0xff,0xbe,0x01,0x12,0x01,0x55,0xff,0xbe,0x01,0x12,0x01,0x63,0x00,0x64,0x01,0x12,0x01,0x6e,0xff,0xba,0x01,0x12,0x01,0x70,0xff,0xba,0x01,0x12,0x01,0x76,0xff,0x8f, 0x01,0x12,0x01,0x77,0xff,0xe5,0x01,0x12,0x01,0x78,0xff,0xe3,0x01,0x12,0x01,0x7a,0xff,0xe3,0x01,0x12,0x01,0x7c,0xff,0xe3,0x01,0x12,0x01,0x7e,0xff,0xe3,0x01,0x12,0x01,0x80,0xff,0xcf,0x01,0x12,0x01,0x81,0xff,0xbe,0x01,0x12,0x01,0x82,0xff,0x7f,0x01,0x12,0x01,0x83,0xff,0xb4,0x01,0x12,0x01,0x85,0x00,0x3b,0x01,0x12,0x01,0x87, 0x00,0x3b,0x01,0x12,0x01,0x89,0xff,0xba,0x01,0x12,0x01,0x8c,0xff,0xcf,0x01,0x12,0x01,0x8d,0xff,0xbe,0x01,0x12,0x01,0x8e,0xff,0xcf,0x01,0x12,0x01,0x8f,0xff,0xbe,0x01,0x12,0x01,0x90,0xff,0xcf,0x01,0x12,0x01,0x91,0xff,0xbe,0x01,0x12,0x01,0x92,0xff,0x7f,0x01,0x12,0x01,0x93,0xff,0xb4,0x01,0x15,0x00,0x05,0xff,0x98,0x01,0x15, 0x00,0x0a,0xff,0x98,0x01,0x17,0x00,0x05,0xff,0x98,0x01,0x17,0x00,0x0a,0xff,0x98,0x01,0x18,0x00,0x0f,0xff,0xa4,0x01,0x18,0x00,0x11,0xff,0xa4,0x01,0x18,0x00,0x24,0xff,0xe5,0x01,0x18,0x00,0x2d,0xff,0xf6,0x01,0x18,0x00,0x37,0xff,0xa4,0x01,0x18,0x00,0x3b,0xff,0xdb,0x01,0x18,0x00,0x3c,0xff,0xe7,0x01,0x18,0x00,0x3d,0xff,0xcf, 0x01,0x18,0x00,0x62,0xff,0xe5,0x01,0x18,0x00,0x63,0xff,0xe5,0x01,0x18,0x00,0xac,0xff,0xa4,0x01,0x18,0x00,0xad,0xff,0xe5,0x01,0x18,0x00,0xae,0xff,0xe5,0x01,0x18,0x00,0xbb,0xff,0xf6,0x01,0x18,0x00,0xc4,0xff,0x4c,0x01,0x18,0x00,0xc5,0xff,0x98,0x01,0x18,0x00,0xc7,0xff,0xe5,0x01,0x18,0x00,0xc9,0xff,0xe5,0x01,0x18,0x00,0xe5, 0xff,0xcf,0x01,0x18,0x00,0xea,0xff,0xe7,0x01,0x18,0x01,0x03,0xff,0xe5,0x01,0x18,0x01,0x05,0xff,0xe5,0x01,0x18,0x01,0x20,0xff,0xa4,0x01,0x18,0x01,0x22,0xff,0xa4,0x01,0x18,0x01,0x28,0xff,0xcf,0x01,0x18,0x01,0x2a,0xff,0xcf,0x01,0x18,0x01,0x45,0xff,0xe5,0x01,0x18,0x01,0x63,0xff,0xf6,0x01,0x18,0x01,0x76,0xff,0xa4,0x01,0x18, 0x01,0x82,0xff,0xe7,0x01,0x18,0x01,0x85,0xff,0xe5,0x01,0x18,0x01,0x87,0xff,0xe5,0x01,0x18,0x01,0x92,0xff,0xe7,0x01,0x19,0x00,0x05,0xff,0x6f,0x01,0x19,0x00,0x0a,0xff,0x6f,0x01,0x19,0x00,0x44,0xff,0xe5,0x01,0x19,0x00,0x49,0xff,0xdb,0x01,0x19,0x00,0x5b,0xff,0xe7,0x01,0x19,0x00,0x69,0xff,0xe5,0x01,0x19,0x00,0x6a,0xff,0xe5, 0x01,0x19,0x00,0x6b,0xff,0xe5,0x01,0x19,0x00,0x6c,0xff,0xe5,0x01,0x19,0x00,0x6d,0xff,0xe5,0x01,0x19,0x00,0x6e,0xff,0xe5,0x01,0x19,0x00,0xa0,0xff,0xe5,0x01,0x19,0x00,0xb4,0xff,0xb2,0x01,0x19,0x00,0xb5,0xff,0x7d,0x01,0x19,0x00,0xb6,0xff,0xbe,0x01,0x19,0x00,0xb7,0xff,0x7d,0x01,0x19,0x00,0xc0,0xff,0xe7,0x01,0x19,0x00,0xc1, 0xff,0xe7,0x01,0x19,0x01,0x04,0xff,0xe5,0x01,0x19,0x01,0x06,0xff,0xe5,0x01,0x19,0x01,0x46,0xff,0xe5,0x01,0x19,0x01,0x86,0xff,0xe5,0x01,0x19,0x01,0x88,0xff,0xe5,0x01,0x1a,0x00,0x1e,0x00,0x52,0x01,0x1a,0x00,0x26,0xff,0xe3,0x01,0x1a,0x00,0x2a,0xff,0xe3,0x01,0x1a,0x00,0x2d,0x00,0x39,0x01,0x1a,0x00,0x32,0xff,0xec,0x01,0x1a, 0x00,0x34,0xff,0xec,0x01,0x1a,0x00,0x37,0xff,0xcb,0x01,0x1a,0x00,0x3c,0xff,0xd9,0x01,0x1a,0x00,0x46,0xff,0xcb,0x01,0x1a,0x00,0x47,0xff,0xcb,0x01,0x1a,0x00,0x48,0xff,0xc7,0x01,0x1a,0x00,0x4a,0xff,0xc7,0x01,0x1a,0x00,0x52,0xff,0xc5,0x01,0x1a,0x00,0x54,0xff,0xcb,0x01,0x1a,0x00,0x64,0xff,0xe5,0x01,0x1a,0x00,0x67,0xff,0xec, 0x01,0x1a,0x00,0x6f,0xff,0xbe,0x01,0x1a,0x00,0x70,0xff,0xbe,0x01,0x1a,0x00,0x71,0xff,0xbe,0x01,0x1a,0x00,0x72,0xff,0xbe,0x01,0x1a,0x00,0x73,0xff,0xbe,0x01,0x1a,0x00,0x79,0xff,0xc5,0x01,0x1a,0x00,0x7a,0xff,0xc5,0x01,0x1a,0x00,0x7b,0xff,0xc5,0x01,0x1a,0x00,0x7c,0xff,0xc5,0x01,0x1a,0x00,0x7d,0xff,0xc5,0x01,0x1a,0x00,0x92, 0xff,0xec,0x01,0x1a,0x00,0xaf,0xff,0xec,0x01,0x1a,0x00,0xb0,0xff,0xec,0x01,0x1a,0x00,0xb1,0xff,0xc5,0x01,0x1a,0x00,0xbb,0xff,0xe5,0x01,0x1a,0x00,0xd0,0xff,0xec,0x01,0x1a,0x00,0xd1,0xff,0xec,0x01,0x1a,0x00,0xd2,0xff,0xec,0x01,0x1a,0x00,0xea,0xff,0xd9,0x01,0x1a,0x00,0xf7,0xff,0xe3,0x01,0x1a,0x00,0xf8,0xff,0xc7,0x01,0x1a, 0x00,0xfc,0xff,0xe3,0x01,0x1a,0x00,0xfd,0xff,0xcb,0x01,0x1a,0x00,0xfe,0xff,0xe3,0x01,0x1a,0x00,0xff,0xff,0xcb,0x01,0x1a,0x01,0x00,0xff,0xcb,0x01,0x1a,0x01,0x08,0xff,0xcb,0x01,0x1a,0x01,0x0b,0xff,0xc7,0x01,0x1a,0x01,0x0d,0xff,0xbe,0x01,0x1a,0x01,0x18,0xff,0xec,0x01,0x1a,0x01,0x19,0xff,0xc5,0x01,0x1a,0x01,0x20,0xff,0xcb, 0x01,0x1a,0x01,0x22,0xff,0xcb,0x01,0x1a,0x01,0x47,0xff,0xe3,0x01,0x1a,0x01,0x48,0xff,0xcb,0x01,0x1a,0x01,0x4c,0xff,0xbe,0x01,0x1a,0x01,0x4e,0xff,0xbe,0x01,0x1a,0x01,0x50,0xff,0xbe,0x01,0x1a,0x01,0x51,0xff,0xe3,0x01,0x1a,0x01,0x52,0xff,0xc7,0x01,0x1a,0x01,0x53,0xff,0xe3,0x01,0x1a,0x01,0x54,0xff,0xc7,0x01,0x1a,0x01,0x55, 0xff,0xe3,0x01,0x1a,0x01,0x56,0xff,0xc7,0x01,0x1a,0x01,0x63,0x00,0x39,0x01,0x1a,0x01,0x6e,0xff,0xec,0x01,0x1a,0x01,0x6f,0xff,0xc5,0x01,0x1a,0x01,0x70,0xff,0xec,0x01,0x1a,0x01,0x71,0xff,0xc5,0x01,0x1a,0x01,0x76,0xff,0xcb,0x01,0x1a,0x01,0x82,0xff,0xd9,0x01,0x1a,0x01,0x89,0xff,0xec,0x01,0x1a,0x01,0x8a,0xff,0xc5,0x01,0x1a, 0x01,0x92,0xff,0xd9,0x01,0x1b,0x00,0x0f,0xff,0x62,0x01,0x1b,0x00,0x10,0xff,0x7f,0x01,0x1b,0x00,0x11,0xff,0x56,0x01,0x1b,0x00,0x1d,0x00,0x52,0x01,0x1b,0x00,0x1e,0x00,0x52,0x01,0x1b,0x00,0x46,0xff,0xe5,0x01,0x1b,0x00,0x47,0xff,0xe5,0x01,0x1b,0x00,0x48,0xff,0xe5,0x01,0x1b,0x00,0x49,0x00,0x27,0x01,0x1b,0x00,0x4a,0xff,0xe5, 0x01,0x1b,0x00,0x50,0xff,0xfc,0x01,0x1b,0x00,0x51,0xff,0xfc,0x01,0x1b,0x00,0x52,0xff,0xe5,0x01,0x1b,0x00,0x54,0xff,0xe5,0x01,0x1b,0x00,0x56,0x00,0x0e,0x01,0x1b,0x00,0x57,0x00,0x3b,0x01,0x1b,0x00,0x59,0x00,0x52,0x01,0x1b,0x00,0x5a,0x00,0x52,0x01,0x1b,0x00,0x5b,0x00,0x3b,0x01,0x1b,0x00,0x5c,0x00,0x52,0x01,0x1b,0x00,0x5d, 0x00,0x27,0x01,0x1b,0x00,0x6f,0xff,0xe5,0x01,0x1b,0x00,0x70,0xff,0xe5,0x01,0x1b,0x00,0x71,0xff,0xe5,0x01,0x1b,0x00,0x72,0xff,0xe5,0x01,0x1b,0x00,0x73,0xff,0xe5,0x01,0x1b,0x00,0x79,0xff,0xe5,0x01,0x1b,0x00,0x7a,0xff,0xe5,0x01,0x1b,0x00,0x7b,0xff,0xe5,0x01,0x1b,0x00,0x7c,0xff,0xe5,0x01,0x1b,0x00,0x7d,0xff,0xe5,0x01,0x1b, 0x00,0xac,0xff,0x56,0x01,0x1b,0x00,0xb1,0xff,0xe5,0x01,0x1b,0x00,0xb4,0x00,0xa4,0x01,0x1b,0x00,0xb5,0x00,0x79,0x01,0x1b,0x00,0xb6,0x00,0xa4,0x01,0x1b,0x00,0xb7,0x00,0x79,0x01,0x1b,0x00,0xc4,0xff,0x62,0x01,0x1b,0x00,0xc5,0xff,0x62,0x01,0x1b,0x00,0xe4,0x00,0x0e,0x01,0x1b,0x00,0xe6,0x00,0x27,0x01,0x1b,0x00,0xeb,0x00,0x52, 0x01,0x1b,0x00,0xf8,0xff,0xe5,0x01,0x1b,0x00,0xfb,0x00,0x0e,0x01,0x1b,0x00,0xfd,0xff,0xe5,0x01,0x1b,0x00,0xff,0xff,0xe5,0x01,0x1b,0x01,0x00,0xff,0xe5,0x01,0x1b,0x01,0x08,0xff,0xe5,0x01,0x1b,0x01,0x0b,0xff,0xe5,0x01,0x1b,0x01,0x0d,0xff,0xe5,0x01,0x1b,0x01,0x19,0xff,0xe5,0x01,0x1b,0x01,0x1f,0x00,0x0e,0x01,0x1b,0x01,0x21, 0x00,0x3b,0x01,0x1b,0x01,0x23,0x00,0x3b,0x01,0x1b,0x01,0x29,0x00,0x27,0x01,0x1b,0x01,0x2b,0x00,0x27,0x01,0x1b,0x01,0x48,0xff,0xe5,0x01,0x1b,0x01,0x4c,0xff,0xe5,0x01,0x1b,0x01,0x4e,0xff,0xe5,0x01,0x1b,0x01,0x50,0xff,0xe5,0x01,0x1b,0x01,0x52,0xff,0xe5,0x01,0x1b,0x01,0x54,0xff,0xe5,0x01,0x1b,0x01,0x56,0xff,0xe5,0x01,0x1b, 0x01,0x6d,0xff,0xfc,0x01,0x1b,0x01,0x6f,0xff,0xe5,0x01,0x1b,0x01,0x71,0xff,0xe5,0x01,0x1b,0x01,0x75,0x00,0x0e,0x01,0x1b,0x01,0x77,0x00,0x3b,0x01,0x1b,0x01,0x81,0x00,0x52,0x01,0x1b,0x01,0x83,0x00,0x52,0x01,0x1b,0x01,0x8a,0xff,0xe5,0x01,0x1b,0x01,0x8d,0x00,0x52,0x01,0x1b,0x01,0x8f,0x00,0x52,0x01,0x1b,0x01,0x91,0x00,0x52, 0x01,0x1b,0x01,0x93,0x00,0x52,0x01,0x1b,0x02,0x3e,0x00,0x0e,0x01,0x1c,0x00,0x1e,0x00,0x52,0x01,0x1c,0x00,0x26,0xff,0xe3,0x01,0x1c,0x00,0x2a,0xff,0xe3,0x01,0x1c,0x00,0x2d,0x00,0x39,0x01,0x1c,0x00,0x32,0xff,0xec,0x01,0x1c,0x00,0x34,0xff,0xec,0x01,0x1c,0x00,0x37,0xff,0xcb,0x01,0x1c,0x00,0x3c,0xff,0xd9,0x01,0x1c,0x00,0x46, 0xff,0xcb,0x01,0x1c,0x00,0x47,0xff,0xcb,0x01,0x1c,0x00,0x48,0xff,0xc7,0x01,0x1c,0x00,0x4a,0xff,0xc7,0x01,0x1c,0x00,0x52,0xff,0xc5,0x01,0x1c,0x00,0x54,0xff,0xcb,0x01,0x1c,0x00,0x64,0xff,0xe5,0x01,0x1c,0x00,0x67,0xff,0xec,0x01,0x1c,0x00,0x6f,0xff,0xbe,0x01,0x1c,0x00,0x70,0xff,0xbe,0x01,0x1c,0x00,0x71,0xff,0xbe,0x01,0x1c, 0x00,0x72,0xff,0xbe,0x01,0x1c,0x00,0x73,0xff,0xbe,0x01,0x1c,0x00,0x79,0xff,0xc5,0x01,0x1c,0x00,0x7a,0xff,0xc5,0x01,0x1c,0x00,0x7b,0xff,0xc5,0x01,0x1c,0x00,0x7c,0xff,0xc5,0x01,0x1c,0x00,0x7d,0xff,0xc5,0x01,0x1c,0x00,0x92,0xff,0xec,0x01,0x1c,0x00,0xaf,0xff,0xec,0x01,0x1c,0x00,0xb0,0xff,0xec,0x01,0x1c,0x00,0xb1,0xff,0xc5, 0x01,0x1c,0x00,0xbb,0xff,0xe5,0x01,0x1c,0x00,0xd0,0xff,0xec,0x01,0x1c,0x00,0xd1,0xff,0xec,0x01,0x1c,0x00,0xd2,0xff,0xec,0x01,0x1c,0x00,0xea,0xff,0xd9,0x01,0x1c,0x00,0xf7,0xff,0xe3,0x01,0x1c,0x00,0xf8,0xff,0xc7,0x01,0x1c,0x00,0xfc,0xff,0xe3,0x01,0x1c,0x00,0xfd,0xff,0xcb,0x01,0x1c,0x00,0xfe,0xff,0xe3,0x01,0x1c,0x00,0xff, 0xff,0xcb,0x01,0x1c,0x01,0x00,0xff,0xcb,0x01,0x1c,0x01,0x08,0xff,0xcb,0x01,0x1c,0x01,0x0b,0xff,0xc7,0x01,0x1c,0x01,0x0d,0xff,0xbe,0x01,0x1c,0x01,0x18,0xff,0xec,0x01,0x1c,0x01,0x19,0xff,0xc5,0x01,0x1c,0x01,0x20,0xff,0xcb,0x01,0x1c,0x01,0x22,0xff,0xcb,0x01,0x1c,0x01,0x47,0xff,0xe3,0x01,0x1c,0x01,0x48,0xff,0xcb,0x01,0x1c, 0x01,0x4c,0xff,0xbe,0x01,0x1c,0x01,0x4e,0xff,0xbe,0x01,0x1c,0x01,0x50,0xff,0xbe,0x01,0x1c,0x01,0x51,0xff,0xe3,0x01,0x1c,0x01,0x52,0xff,0xc7,0x01,0x1c,0x01,0x53,0xff,0xe3,0x01,0x1c,0x01,0x54,0xff,0xc7,0x01,0x1c,0x01,0x55,0xff,0xe3,0x01,0x1c,0x01,0x56,0xff,0xc7,0x01,0x1c,0x01,0x63,0x00,0x39,0x01,0x1c,0x01,0x6e,0xff,0xec, 0x01,0x1c,0x01,0x6f,0xff,0xc5,0x01,0x1c,0x01,0x70,0xff,0xec,0x01,0x1c,0x01,0x71,0xff,0xc5,0x01,0x1c,0x01,0x76,0xff,0xcb,0x01,0x1c,0x01,0x82,0xff,0xd9,0x01,0x1c,0x01,0x89,0xff,0xec,0x01,0x1c,0x01,0x8a,0xff,0xc5,0x01,0x1c,0x01,0x92,0xff,0xd9,0x01,0x1d,0x00,0x0f,0xff,0x62,0x01,0x1d,0x00,0x10,0xff,0x7f,0x01,0x1d,0x00,0x11, 0xff,0x56,0x01,0x1d,0x00,0x1d,0x00,0x52,0x01,0x1d,0x00,0x1e,0x00,0x52,0x01,0x1d,0x00,0x46,0xff,0xe5,0x01,0x1d,0x00,0x47,0xff,0xe5,0x01,0x1d,0x00,0x48,0xff,0xe5,0x01,0x1d,0x00,0x49,0x00,0x27,0x01,0x1d,0x00,0x4a,0xff,0xe5,0x01,0x1d,0x00,0x50,0xff,0xfc,0x01,0x1d,0x00,0x51,0xff,0xfc,0x01,0x1d,0x00,0x52,0xff,0xe5,0x01,0x1d, 0x00,0x54,0xff,0xe5,0x01,0x1d,0x00,0x56,0x00,0x0e,0x01,0x1d,0x00,0x57,0x00,0x3b,0x01,0x1d,0x00,0x59,0x00,0x52,0x01,0x1d,0x00,0x5a,0x00,0x52,0x01,0x1d,0x00,0x5b,0x00,0x3b,0x01,0x1d,0x00,0x5c,0x00,0x52,0x01,0x1d,0x00,0x5d,0x00,0x27,0x01,0x1d,0x00,0x6f,0xff,0xe5,0x01,0x1d,0x00,0x70,0xff,0xe5,0x01,0x1d,0x00,0x71,0xff,0xe5, 0x01,0x1d,0x00,0x72,0xff,0xe5,0x01,0x1d,0x00,0x73,0xff,0xe5,0x01,0x1d,0x00,0x79,0xff,0xe5,0x01,0x1d,0x00,0x7a,0xff,0xe5,0x01,0x1d,0x00,0x7b,0xff,0xe5,0x01,0x1d,0x00,0x7c,0xff,0xe5,0x01,0x1d,0x00,0x7d,0xff,0xe5,0x01,0x1d,0x00,0xac,0xff,0x56,0x01,0x1d,0x00,0xb1,0xff,0xe5,0x01,0x1d,0x00,0xb4,0x00,0xa4,0x01,0x1d,0x00,0xb5, 0x00,0x79,0x01,0x1d,0x00,0xb6,0x00,0xa4,0x01,0x1d,0x00,0xb7,0x00,0x79,0x01,0x1d,0x00,0xc4,0xff,0x62,0x01,0x1d,0x00,0xc5,0xff,0x62,0x01,0x1d,0x00,0xe4,0x00,0x0e,0x01,0x1d,0x00,0xe6,0x00,0x27,0x01,0x1d,0x00,0xeb,0x00,0x52,0x01,0x1d,0x00,0xf8,0xff,0xe5,0x01,0x1d,0x00,0xfb,0x00,0x0e,0x01,0x1d,0x00,0xfd,0xff,0xe5,0x01,0x1d, 0x00,0xff,0xff,0xe5,0x01,0x1d,0x01,0x00,0xff,0xe5,0x01,0x1d,0x01,0x08,0xff,0xe5,0x01,0x1d,0x01,0x0b,0xff,0xe5,0x01,0x1d,0x01,0x0d,0xff,0xe5,0x01,0x1d,0x01,0x19,0xff,0xe5,0x01,0x1d,0x01,0x1f,0x00,0x0e,0x01,0x1d,0x01,0x21,0x00,0x3b,0x01,0x1d,0x01,0x23,0x00,0x3b,0x01,0x1d,0x01,0x29,0x00,0x27,0x01,0x1d,0x01,0x2b,0x00,0x27, 0x01,0x1d,0x01,0x48,0xff,0xe5,0x01,0x1d,0x01,0x4c,0xff,0xe5,0x01,0x1d,0x01,0x4e,0xff,0xe5,0x01,0x1d,0x01,0x50,0xff,0xe5,0x01,0x1d,0x01,0x52,0xff,0xe5,0x01,0x1d,0x01,0x54,0xff,0xe5,0x01,0x1d,0x01,0x56,0xff,0xe5,0x01,0x1d,0x01,0x6d,0xff,0xfc,0x01,0x1d,0x01,0x6f,0xff,0xe5,0x01,0x1d,0x01,0x71,0xff,0xe5,0x01,0x1d,0x01,0x75, 0x00,0x0e,0x01,0x1d,0x01,0x77,0x00,0x3b,0x01,0x1d,0x01,0x81,0x00,0x52,0x01,0x1d,0x01,0x83,0x00,0x52,0x01,0x1d,0x01,0x8a,0xff,0xe5,0x01,0x1d,0x01,0x8d,0x00,0x52,0x01,0x1d,0x01,0x8f,0x00,0x52,0x01,0x1d,0x01,0x91,0x00,0x52,0x01,0x1d,0x01,0x93,0x00,0x52,0x01,0x1d,0x02,0x3e,0x00,0x0e,0x01,0x1e,0x00,0x57,0xff,0xbe,0x01,0x1e, 0x00,0x59,0xff,0xcf,0x01,0x1e,0x00,0x5a,0xff,0xe5,0x01,0x1e,0x00,0x5c,0xff,0xd1,0x01,0x1e,0x00,0xba,0xff,0xbe,0x01,0x1e,0x00,0xc4,0xff,0xb2,0x01,0x1e,0x00,0xc5,0xff,0xb2,0x01,0x1e,0x00,0xeb,0xff,0xd1,0x01,0x1e,0x01,0x21,0xff,0xbe,0x01,0x1e,0x01,0x23,0xff,0xbe,0x01,0x1e,0x01,0x77,0xff,0xbe,0x01,0x1e,0x01,0x81,0xff,0xe5, 0x01,0x1e,0x01,0x83,0xff,0xd1,0x01,0x1e,0x01,0x8d,0xff,0xe5,0x01,0x1e,0x01,0x8f,0xff,0xe5,0x01,0x1e,0x01,0x91,0xff,0xe5,0x01,0x1e,0x01,0x93,0xff,0xd1,0x01,0x20,0x00,0x0f,0xff,0x7f,0x01,0x20,0x00,0x11,0xff,0x4c,0x01,0x20,0x00,0x1d,0xff,0xe9,0x01,0x20,0x00,0x1e,0xff,0xe9,0x01,0x20,0x00,0x24,0xff,0x66,0x01,0x20,0x00,0x26, 0xff,0xa4,0x01,0x20,0x00,0x2a,0xff,0xa4,0x01,0x20,0x00,0x2d,0xff,0x8f,0x01,0x20,0x00,0x32,0xff,0xa4,0x01,0x20,0x00,0x34,0xff,0xa4,0x01,0x20,0x00,0x37,0x00,0x27,0x01,0x20,0x00,0x39,0x00,0x2b,0x01,0x20,0x00,0x3a,0x00,0x27,0x01,0x20,0x00,0x3b,0xff,0xfa,0x01,0x20,0x00,0x3c,0x00,0x1d,0x01,0x20,0x00,0x44,0xff,0x27,0x01,0x20, 0x00,0x46,0xff,0x2d,0x01,0x20,0x00,0x47,0xff,0x2d,0x01,0x20,0x00,0x48,0xff,0x2d,0x01,0x20,0x00,0x49,0xff,0xa0,0x01,0x20,0x00,0x4a,0xff,0x2d,0x01,0x20,0x00,0x50,0xff,0x4e,0x01,0x20,0x00,0x51,0xff,0x4e,0x01,0x20,0x00,0x52,0xff,0x2d,0x01,0x20,0x00,0x53,0xff,0x4e,0x01,0x20,0x00,0x54,0xff,0x2d,0x01,0x20,0x00,0x55,0xff,0x4e, 0x01,0x20,0x00,0x56,0xff,0x66,0x01,0x20,0x00,0x58,0xff,0x4e,0x01,0x20,0x00,0x59,0xff,0x9a,0x01,0x20,0x00,0x5a,0xff,0x8f,0x01,0x20,0x00,0x5b,0xff,0x4c,0x01,0x20,0x00,0x5c,0xff,0x8f,0x01,0x20,0x00,0x5d,0xff,0x7f,0x01,0x20,0x00,0x62,0xff,0x66,0x01,0x20,0x00,0x63,0xff,0x66,0x01,0x20,0x00,0x64,0xff,0xa4,0x01,0x20,0x00,0x67, 0xff,0xa4,0x01,0x20,0x00,0x69,0xff,0x27,0x01,0x20,0x00,0x6a,0xff,0x27,0x01,0x20,0x00,0x6b,0xff,0x27,0x01,0x20,0x00,0x6c,0xff,0x27,0x01,0x20,0x00,0x6d,0xff,0x3f,0x01,0x20,0x00,0x6e,0xff,0x27,0x01,0x20,0x00,0x6f,0xff,0x1b,0x01,0x20,0x00,0x70,0xff,0x2d,0x01,0x20,0x00,0x71,0xff,0x2d,0x01,0x20,0x00,0x72,0xff,0x2d,0x01,0x20, 0x00,0x73,0xff,0x2d,0x01,0x20,0x00,0x74,0xff,0xe9,0x01,0x20,0x00,0x76,0x00,0x31,0x01,0x20,0x00,0x77,0x00,0x6f,0x01,0x20,0x00,0x78,0xff,0x4e,0x01,0x20,0x00,0x79,0xff,0x2d,0x01,0x20,0x00,0x7a,0xff,0x2d,0x01,0x20,0x00,0x7b,0xff,0x2d,0x01,0x20,0x00,0x7c,0xff,0x2d,0x01,0x20,0x00,0x7d,0xff,0x2d,0x01,0x20,0x00,0x7e,0xff,0x4e, 0x01,0x20,0x00,0x7f,0xff,0x4e,0x01,0x20,0x00,0x80,0xff,0x4e,0x01,0x20,0x00,0x81,0xff,0x4e,0x01,0x20,0x00,0x8d,0x00,0x52,0x01,0x20,0x00,0x91,0xff,0x0c,0x01,0x20,0x00,0x92,0xff,0xa4,0x01,0x20,0x00,0xa0,0xff,0x27,0x01,0x20,0x00,0xaa,0xff,0x9a,0x01,0x20,0x00,0xab,0xff,0xcf,0x01,0x20,0x00,0xac,0xff,0x4c,0x01,0x20,0x00,0xad, 0xff,0x66,0x01,0x20,0x00,0xae,0xff,0x66,0x01,0x20,0x00,0xaf,0xff,0xa4,0x01,0x20,0x00,0xb0,0xff,0xa4,0x01,0x20,0x00,0xb1,0xff,0x2d,0x01,0x20,0x00,0xb5,0x00,0x27,0x01,0x20,0x00,0xb7,0x00,0x27,0x01,0x20,0x00,0xba,0xff,0x8f,0x01,0x20,0x00,0xbe,0xff,0x9a,0x01,0x20,0x00,0xbf,0xff,0xcf,0x01,0x20,0x00,0xc4,0xff,0x17,0x01,0x20, 0x00,0xc5,0xff,0x17,0x01,0x20,0x00,0xc7,0xff,0x66,0x01,0x20,0x00,0xc9,0xff,0x66,0x01,0x20,0x00,0xd0,0xff,0xa4,0x01,0x20,0x00,0xd1,0xff,0xa4,0x01,0x20,0x00,0xd2,0xff,0xa4,0x01,0x20,0x00,0xe4,0xff,0x66,0x01,0x20,0x00,0xe6,0xff,0x7f,0x01,0x20,0x00,0xea,0x00,0x1d,0x01,0x20,0x00,0xeb,0xff,0x8f,0x01,0x20,0x00,0xf7,0xff,0xa4, 0x01,0x20,0x00,0xf8,0xff,0x2d,0x01,0x20,0x00,0xfb,0xff,0x66,0x01,0x20,0x00,0xfc,0xff,0xa4,0x01,0x20,0x00,0xfd,0xff,0x2d,0x01,0x20,0x00,0xfe,0xff,0xa4,0x01,0x20,0x00,0xff,0xff,0x2d,0x01,0x20,0x01,0x00,0xff,0x2d,0x01,0x20,0x01,0x03,0xff,0x66,0x01,0x20,0x01,0x04,0xff,0x27,0x01,0x20,0x01,0x05,0xff,0x66,0x01,0x20,0x01,0x06, 0xff,0x27,0x01,0x20,0x01,0x08,0xff,0x2d,0x01,0x20,0x01,0x0b,0xff,0x2d,0x01,0x20,0x01,0x0d,0xff,0x2d,0x01,0x20,0x01,0x15,0xff,0x4e,0x01,0x20,0x01,0x17,0xff,0x4e,0x01,0x20,0x01,0x18,0xff,0xa4,0x01,0x20,0x01,0x19,0xff,0x2d,0x01,0x20,0x01,0x1b,0xff,0x4e,0x01,0x20,0x01,0x1d,0xff,0x4e,0x01,0x20,0x01,0x1f,0xff,0x66,0x01,0x20, 0x01,0x20,0x00,0x27,0x01,0x20,0x01,0x22,0x00,0x27,0x01,0x20,0x01,0x25,0xff,0x4e,0x01,0x20,0x01,0x27,0xff,0x4e,0x01,0x20,0x01,0x29,0xff,0x7f,0x01,0x20,0x01,0x2b,0xff,0x7f,0x01,0x20,0x01,0x45,0xff,0x66,0x01,0x20,0x01,0x46,0xff,0x27,0x01,0x20,0x01,0x47,0xff,0xa4,0x01,0x20,0x01,0x48,0xff,0x2d,0x01,0x20,0x01,0x4c,0xff,0x2d, 0x01,0x20,0x01,0x4e,0xff,0x2d,0x01,0x20,0x01,0x50,0xff,0x2d,0x01,0x20,0x01,0x51,0xff,0xa4,0x01,0x20,0x01,0x52,0xff,0x2d,0x01,0x20,0x01,0x53,0xff,0xa4,0x01,0x20,0x01,0x54,0xff,0x2d,0x01,0x20,0x01,0x55,0xff,0xa4,0x01,0x20,0x01,0x56,0xff,0x2d,0x01,0x20,0x01,0x5c,0x00,0x6f,0x01,0x20,0x01,0x5e,0x00,0x6f,0x01,0x20,0x01,0x60, 0x00,0x6f,0x01,0x20,0x01,0x63,0xff,0x8f,0x01,0x20,0x01,0x6d,0xff,0x4e,0x01,0x20,0x01,0x6e,0xff,0xa4,0x01,0x20,0x01,0x6f,0xff,0x2d,0x01,0x20,0x01,0x70,0xff,0xa4,0x01,0x20,0x01,0x71,0xff,0x2d,0x01,0x20,0x01,0x73,0xff,0x4e,0x01,0x20,0x01,0x75,0xff,0x66,0x01,0x20,0x01,0x76,0x00,0x27,0x01,0x20,0x01,0x79,0xff,0x4e,0x01,0x20, 0x01,0x7b,0xff,0x4e,0x01,0x20,0x01,0x7d,0xff,0x4e,0x01,0x20,0x01,0x7f,0xff,0x4e,0x01,0x20,0x01,0x80,0x00,0x27,0x01,0x20,0x01,0x81,0xff,0x8f,0x01,0x20,0x01,0x82,0x00,0x1d,0x01,0x20,0x01,0x83,0xff,0x8f,0x01,0x20,0x01,0x85,0xff,0x66,0x01,0x20,0x01,0x86,0xff,0x27,0x01,0x20,0x01,0x87,0xff,0x66,0x01,0x20,0x01,0x88,0xff,0x27, 0x01,0x20,0x01,0x89,0xff,0xa4,0x01,0x20,0x01,0x8a,0xff,0x2d,0x01,0x20,0x01,0x8c,0x00,0x27,0x01,0x20,0x01,0x8d,0xff,0x8f,0x01,0x20,0x01,0x8e,0x00,0x27,0x01,0x20,0x01,0x8f,0xff,0x8f,0x01,0x20,0x01,0x90,0x00,0x27,0x01,0x20,0x01,0x91,0xff,0x8f,0x01,0x20,0x01,0x92,0x00,0x1d,0x01,0x20,0x01,0x93,0xff,0x8f,0x01,0x20,0x02,0x3e, 0xff,0x66,0x01,0x21,0x00,0x10,0xff,0x8f,0x01,0x21,0x00,0x22,0xff,0xcb,0x01,0x21,0x00,0x46,0xff,0xe5,0x01,0x21,0x00,0x47,0xff,0xe5,0x01,0x21,0x00,0x48,0xff,0xf0,0x01,0x21,0x00,0x4a,0xff,0xf0,0x01,0x21,0x00,0x52,0xff,0xf0,0x01,0x21,0x00,0x54,0xff,0xf0,0x01,0x21,0x00,0x5b,0x00,0x1d,0x01,0x21,0x00,0x6f,0xff,0xe5,0x01,0x21, 0x00,0x70,0xff,0xf0,0x01,0x21,0x00,0x71,0xff,0xf0,0x01,0x21,0x00,0x72,0xff,0xf0,0x01,0x21,0x00,0x73,0xff,0xf0,0x01,0x21,0x00,0x79,0xff,0xf0,0x01,0x21,0x00,0x7a,0xff,0xf0,0x01,0x21,0x00,0x7b,0xff,0xf0,0x01,0x21,0x00,0x7c,0xff,0xf0,0x01,0x21,0x00,0x7d,0xff,0xf0,0x01,0x21,0x00,0xab,0x00,0x27,0x01,0x21,0x00,0xb1,0xff,0xf0, 0x01,0x21,0x00,0xbf,0x00,0x27,0x01,0x21,0x00,0xf8,0xff,0xf0,0x01,0x21,0x00,0xfd,0xff,0xe5,0x01,0x21,0x00,0xff,0xff,0xe5,0x01,0x21,0x01,0x00,0xff,0xe5,0x01,0x21,0x01,0x08,0xff,0xe5,0x01,0x21,0x01,0x0b,0xff,0xf0,0x01,0x21,0x01,0x0d,0xff,0xf0,0x01,0x21,0x01,0x19,0xff,0xf0,0x01,0x21,0x01,0x48,0xff,0xe5,0x01,0x21,0x01,0x4c, 0xff,0xf0,0x01,0x21,0x01,0x4e,0xff,0xf0,0x01,0x21,0x01,0x50,0xff,0xf0,0x01,0x21,0x01,0x52,0xff,0xf0,0x01,0x21,0x01,0x54,0xff,0xf0,0x01,0x21,0x01,0x56,0xff,0xf0,0x01,0x21,0x01,0x6f,0xff,0xf0,0x01,0x21,0x01,0x71,0xff,0xf0,0x01,0x21,0x01,0x8a,0xff,0xf0,0x01,0x22,0x00,0x0f,0xff,0x7f,0x01,0x22,0x00,0x11,0xff,0x4c,0x01,0x22, 0x00,0x1d,0xff,0xe9,0x01,0x22,0x00,0x1e,0xff,0xe9,0x01,0x22,0x00,0x24,0xff,0x66,0x01,0x22,0x00,0x26,0xff,0xa4,0x01,0x22,0x00,0x2a,0xff,0xa4,0x01,0x22,0x00,0x2d,0xff,0x8f,0x01,0x22,0x00,0x32,0xff,0xa4,0x01,0x22,0x00,0x34,0xff,0xa4,0x01,0x22,0x00,0x37,0x00,0x27,0x01,0x22,0x00,0x39,0x00,0x2b,0x01,0x22,0x00,0x3a,0x00,0x27, 0x01,0x22,0x00,0x3b,0xff,0xfa,0x01,0x22,0x00,0x3c,0x00,0x1d,0x01,0x22,0x00,0x44,0xff,0x27,0x01,0x22,0x00,0x46,0xff,0x2d,0x01,0x22,0x00,0x47,0xff,0x2d,0x01,0x22,0x00,0x48,0xff,0x2d,0x01,0x22,0x00,0x49,0xff,0xa0,0x01,0x22,0x00,0x4a,0xff,0x2d,0x01,0x22,0x00,0x50,0xff,0x4e,0x01,0x22,0x00,0x51,0xff,0x4e,0x01,0x22,0x00,0x52, 0xff,0x2d,0x01,0x22,0x00,0x53,0xff,0x4e,0x01,0x22,0x00,0x54,0xff,0x2d,0x01,0x22,0x00,0x55,0xff,0x4e,0x01,0x22,0x00,0x56,0xff,0x66,0x01,0x22,0x00,0x58,0xff,0x4e,0x01,0x22,0x00,0x59,0xff,0x9a,0x01,0x22,0x00,0x5a,0xff,0x8f,0x01,0x22,0x00,0x5b,0xff,0x4c,0x01,0x22,0x00,0x5c,0xff,0x8f,0x01,0x22,0x00,0x5d,0xff,0x7f,0x01,0x22, 0x00,0x62,0xff,0x66,0x01,0x22,0x00,0x63,0xff,0x66,0x01,0x22,0x00,0x64,0xff,0xa4,0x01,0x22,0x00,0x67,0xff,0xa4,0x01,0x22,0x00,0x69,0xff,0x27,0x01,0x22,0x00,0x6a,0xff,0x27,0x01,0x22,0x00,0x6b,0xff,0x27,0x01,0x22,0x00,0x6c,0xff,0x27,0x01,0x22,0x00,0x6d,0xff,0x3f,0x01,0x22,0x00,0x6e,0xff,0x27,0x01,0x22,0x00,0x6f,0xff,0x1b, 0x01,0x22,0x00,0x70,0xff,0x2d,0x01,0x22,0x00,0x71,0xff,0x2d,0x01,0x22,0x00,0x72,0xff,0x2d,0x01,0x22,0x00,0x73,0xff,0x2d,0x01,0x22,0x00,0x74,0xff,0xe9,0x01,0x22,0x00,0x76,0x00,0x31,0x01,0x22,0x00,0x77,0x00,0x6f,0x01,0x22,0x00,0x78,0xff,0x4e,0x01,0x22,0x00,0x79,0xff,0x2d,0x01,0x22,0x00,0x7a,0xff,0x2d,0x01,0x22,0x00,0x7b, 0xff,0x2d,0x01,0x22,0x00,0x7c,0xff,0x2d,0x01,0x22,0x00,0x7d,0xff,0x2d,0x01,0x22,0x00,0x7e,0xff,0x4e,0x01,0x22,0x00,0x7f,0xff,0x4e,0x01,0x22,0x00,0x80,0xff,0x4e,0x01,0x22,0x00,0x81,0xff,0x4e,0x01,0x22,0x00,0x8d,0x00,0x52,0x01,0x22,0x00,0x91,0xff,0x0c,0x01,0x22,0x00,0x92,0xff,0xa4,0x01,0x22,0x00,0xa0,0xff,0x27,0x01,0x22, 0x00,0xaa,0xff,0x9a,0x01,0x22,0x00,0xab,0xff,0xcf,0x01,0x22,0x00,0xac,0xff,0x4c,0x01,0x22,0x00,0xad,0xff,0x66,0x01,0x22,0x00,0xae,0xff,0x66,0x01,0x22,0x00,0xaf,0xff,0xa4,0x01,0x22,0x00,0xb0,0xff,0xa4,0x01,0x22,0x00,0xb1,0xff,0x2d,0x01,0x22,0x00,0xb5,0x00,0x27,0x01,0x22,0x00,0xb7,0x00,0x27,0x01,0x22,0x00,0xba,0xff,0x8f, 0x01,0x22,0x00,0xbe,0xff,0x9a,0x01,0x22,0x00,0xbf,0xff,0xcf,0x01,0x22,0x00,0xc4,0xff,0x17,0x01,0x22,0x00,0xc5,0xff,0x17,0x01,0x22,0x00,0xc7,0xff,0x66,0x01,0x22,0x00,0xc9,0xff,0x66,0x01,0x22,0x00,0xd0,0xff,0xa4,0x01,0x22,0x00,0xd1,0xff,0xa4,0x01,0x22,0x00,0xd2,0xff,0xa4,0x01,0x22,0x00,0xe4,0xff,0x66,0x01,0x22,0x00,0xe6, 0xff,0x7f,0x01,0x22,0x00,0xea,0x00,0x1d,0x01,0x22,0x00,0xeb,0xff,0x8f,0x01,0x22,0x00,0xf7,0xff,0xa4,0x01,0x22,0x00,0xf8,0xff,0x2d,0x01,0x22,0x00,0xfb,0xff,0x66,0x01,0x22,0x00,0xfc,0xff,0xa4,0x01,0x22,0x00,0xfd,0xff,0x2d,0x01,0x22,0x00,0xfe,0xff,0xa4,0x01,0x22,0x00,0xff,0xff,0x2d,0x01,0x22,0x01,0x00,0xff,0x2d,0x01,0x22, 0x01,0x03,0xff,0x66,0x01,0x22,0x01,0x04,0xff,0x27,0x01,0x22,0x01,0x05,0xff,0x66,0x01,0x22,0x01,0x06,0xff,0x27,0x01,0x22,0x01,0x08,0xff,0x2d,0x01,0x22,0x01,0x0b,0xff,0x2d,0x01,0x22,0x01,0x0d,0xff,0x2d,0x01,0x22,0x01,0x15,0xff,0x4e,0x01,0x22,0x01,0x17,0xff,0x4e,0x01,0x22,0x01,0x18,0xff,0xa4,0x01,0x22,0x01,0x19,0xff,0x2d, 0x01,0x22,0x01,0x1b,0xff,0x4e,0x01,0x22,0x01,0x1d,0xff,0x4e,0x01,0x22,0x01,0x1f,0xff,0x66,0x01,0x22,0x01,0x20,0x00,0x27,0x01,0x22,0x01,0x22,0x00,0x27,0x01,0x22,0x01,0x25,0xff,0x4e,0x01,0x22,0x01,0x27,0xff,0x4e,0x01,0x22,0x01,0x29,0xff,0x7f,0x01,0x22,0x01,0x2b,0xff,0x7f,0x01,0x22,0x01,0x45,0xff,0x66,0x01,0x22,0x01,0x46, 0xff,0x27,0x01,0x22,0x01,0x47,0xff,0xa4,0x01,0x22,0x01,0x48,0xff,0x2d,0x01,0x22,0x01,0x4c,0xff,0x2d,0x01,0x22,0x01,0x4e,0xff,0x2d,0x01,0x22,0x01,0x50,0xff,0x2d,0x01,0x22,0x01,0x51,0xff,0xa4,0x01,0x22,0x01,0x52,0xff,0x2d,0x01,0x22,0x01,0x53,0xff,0xa4,0x01,0x22,0x01,0x54,0xff,0x2d,0x01,0x22,0x01,0x55,0xff,0xa4,0x01,0x22, 0x01,0x56,0xff,0x2d,0x01,0x22,0x01,0x5c,0x00,0x6f,0x01,0x22,0x01,0x5e,0x00,0x6f,0x01,0x22,0x01,0x60,0x00,0x6f,0x01,0x22,0x01,0x63,0xff,0x8f,0x01,0x22,0x01,0x6d,0xff,0x4e,0x01,0x22,0x01,0x6e,0xff,0xa4,0x01,0x22,0x01,0x6f,0xff,0x2d,0x01,0x22,0x01,0x70,0xff,0xa4,0x01,0x22,0x01,0x71,0xff,0x2d,0x01,0x22,0x01,0x73,0xff,0x4e, 0x01,0x22,0x01,0x75,0xff,0x66,0x01,0x22,0x01,0x76,0x00,0x27,0x01,0x22,0x01,0x79,0xff,0x4e,0x01,0x22,0x01,0x7b,0xff,0x4e,0x01,0x22,0x01,0x7d,0xff,0x4e,0x01,0x22,0x01,0x7f,0xff,0x4e,0x01,0x22,0x01,0x80,0x00,0x27,0x01,0x22,0x01,0x81,0xff,0x8f,0x01,0x22,0x01,0x82,0x00,0x1d,0x01,0x22,0x01,0x83,0xff,0x8f,0x01,0x22,0x01,0x85, 0xff,0x66,0x01,0x22,0x01,0x86,0xff,0x27,0x01,0x22,0x01,0x87,0xff,0x66,0x01,0x22,0x01,0x88,0xff,0x27,0x01,0x22,0x01,0x89,0xff,0xa4,0x01,0x22,0x01,0x8a,0xff,0x2d,0x01,0x22,0x01,0x8c,0x00,0x27,0x01,0x22,0x01,0x8d,0xff,0x8f,0x01,0x22,0x01,0x8e,0x00,0x27,0x01,0x22,0x01,0x8f,0xff,0x8f,0x01,0x22,0x01,0x90,0x00,0x27,0x01,0x22, 0x01,0x91,0xff,0x8f,0x01,0x22,0x01,0x92,0x00,0x1d,0x01,0x22,0x01,0x93,0xff,0x8f,0x01,0x22,0x02,0x3e,0xff,0x66,0x01,0x23,0x00,0x10,0xff,0x8f,0x01,0x23,0x00,0x22,0xff,0xcb,0x01,0x23,0x00,0x46,0xff,0xe5,0x01,0x23,0x00,0x47,0xff,0xe5,0x01,0x23,0x00,0x48,0xff,0xf0,0x01,0x23,0x00,0x4a,0xff,0xf0,0x01,0x23,0x00,0x52,0xff,0xf0, 0x01,0x23,0x00,0x54,0xff,0xf0,0x01,0x23,0x00,0x5b,0x00,0x1d,0x01,0x23,0x00,0x6f,0xff,0xe5,0x01,0x23,0x00,0x70,0xff,0xf0,0x01,0x23,0x00,0x71,0xff,0xf0,0x01,0x23,0x00,0x72,0xff,0xf0,0x01,0x23,0x00,0x73,0xff,0xf0,0x01,0x23,0x00,0x79,0xff,0xf0,0x01,0x23,0x00,0x7a,0xff,0xf0,0x01,0x23,0x00,0x7b,0xff,0xf0,0x01,0x23,0x00,0x7c, 0xff,0xf0,0x01,0x23,0x00,0x7d,0xff,0xf0,0x01,0x23,0x00,0xab,0x00,0x27,0x01,0x23,0x00,0xb1,0xff,0xf0,0x01,0x23,0x00,0xbf,0x00,0x27,0x01,0x23,0x00,0xf8,0xff,0xf0,0x01,0x23,0x00,0xfd,0xff,0xe5,0x01,0x23,0x00,0xff,0xff,0xe5,0x01,0x23,0x01,0x00,0xff,0xe5,0x01,0x23,0x01,0x08,0xff,0xe5,0x01,0x23,0x01,0x0b,0xff,0xf0,0x01,0x23, 0x01,0x0d,0xff,0xf0,0x01,0x23,0x01,0x19,0xff,0xf0,0x01,0x23,0x01,0x48,0xff,0xe5,0x01,0x23,0x01,0x4c,0xff,0xf0,0x01,0x23,0x01,0x4e,0xff,0xf0,0x01,0x23,0x01,0x50,0xff,0xf0,0x01,0x23,0x01,0x52,0xff,0xf0,0x01,0x23,0x01,0x54,0xff,0xf0,0x01,0x23,0x01,0x56,0xff,0xf0,0x01,0x23,0x01,0x6f,0xff,0xf0,0x01,0x23,0x01,0x71,0xff,0xf0, 0x01,0x23,0x01,0x8a,0xff,0xf0,0x01,0x24,0x00,0x24,0xff,0xd7,0x01,0x24,0x00,0x91,0xff,0x8b,0x01,0x24,0x00,0xc4,0xff,0xa6,0x01,0x24,0x00,0xc5,0xff,0xa6,0x01,0x24,0x01,0x03,0xff,0xd7,0x01,0x24,0x01,0x05,0xff,0xd7,0x01,0x24,0x01,0x45,0xff,0xd7,0x01,0x24,0x01,0x85,0xff,0xd7,0x01,0x24,0x01,0x87,0xff,0xd7,0x01,0x25,0x00,0x05, 0xff,0xbe,0x01,0x25,0x00,0x0a,0xff,0xbe,0x01,0x26,0x00,0x24,0xff,0xd7,0x01,0x26,0x00,0x91,0xff,0x8b,0x01,0x26,0x00,0xc4,0xff,0xa6,0x01,0x26,0x00,0xc5,0xff,0xa6,0x01,0x26,0x01,0x03,0xff,0xd7,0x01,0x26,0x01,0x05,0xff,0xd7,0x01,0x26,0x01,0x45,0xff,0xd7,0x01,0x26,0x01,0x85,0xff,0xd7,0x01,0x26,0x01,0x87,0xff,0xd7,0x01,0x27, 0x00,0x05,0xff,0xbe,0x01,0x27,0x00,0x0a,0xff,0xbe,0x01,0x28,0x00,0x2d,0x00,0x52,0x01,0x28,0x00,0x37,0x00,0x27,0x01,0x28,0x00,0x5c,0xff,0xcb,0x01,0x28,0x00,0x77,0x00,0x46,0x01,0x28,0x00,0xab,0x00,0x27,0x01,0x28,0x00,0xba,0xff,0xbe,0x01,0x28,0x00,0xbf,0x00,0x52,0x01,0x28,0x00,0xeb,0xff,0xcb,0x01,0x28,0x01,0x20,0x00,0x27, 0x01,0x28,0x01,0x22,0x00,0x27,0x01,0x28,0x01,0x5c,0x00,0x46,0x01,0x28,0x01,0x5e,0x00,0x46,0x01,0x28,0x01,0x60,0x00,0x46,0x01,0x28,0x01,0x63,0x00,0x52,0x01,0x28,0x01,0x76,0x00,0x27,0x01,0x28,0x01,0x83,0xff,0xcb,0x01,0x28,0x01,0x93,0xff,0xcb,0x01,0x2a,0x00,0x2d,0x00,0x52,0x01,0x2a,0x00,0x37,0x00,0x27,0x01,0x2a,0x00,0x5c, 0xff,0xcb,0x01,0x2a,0x00,0x77,0x00,0x46,0x01,0x2a,0x00,0xab,0x00,0x27,0x01,0x2a,0x00,0xba,0xff,0xbe,0x01,0x2a,0x00,0xbf,0x00,0x52,0x01,0x2a,0x00,0xeb,0xff,0xcb,0x01,0x2a,0x01,0x20,0x00,0x27,0x01,0x2a,0x01,0x22,0x00,0x27,0x01,0x2a,0x01,0x5c,0x00,0x46,0x01,0x2a,0x01,0x5e,0x00,0x46,0x01,0x2a,0x01,0x60,0x00,0x46,0x01,0x2a, 0x01,0x63,0x00,0x52,0x01,0x2a,0x01,0x76,0x00,0x27,0x01,0x2a,0x01,0x83,0xff,0xcb,0x01,0x2a,0x01,0x93,0xff,0xcb,0x01,0x2c,0x00,0x04,0x00,0x44,0x01,0x2c,0x00,0x0f,0xff,0x7d,0x01,0x2c,0x00,0x11,0xff,0x4c,0x01,0x2c,0x00,0x1d,0xff,0xe9,0x01,0x2c,0x00,0x1e,0xff,0xe9,0x01,0x2c,0x00,0x8d,0x00,0x52,0x01,0x2c,0x00,0xa9,0xff,0x6d, 0x01,0x2c,0x00,0xaa,0xff,0x98,0x01,0x2c,0x00,0xab,0xff,0xcd,0x01,0x2c,0x00,0xac,0xff,0x4c,0x01,0x2c,0x00,0xb5,0x00,0x29,0x01,0x2c,0x00,0xb7,0x00,0x29,0x01,0x2c,0x00,0xbe,0xff,0x98,0x01,0x2c,0x00,0xbf,0xff,0xcd,0x01,0x2c,0x00,0xc4,0xff,0x14,0x01,0x2c,0x00,0xc5,0xff,0x14,0x01,0x2c,0x01,0x2d,0xff,0xb6,0x01,0x2c,0x01,0x2e, 0xff,0xb6,0x01,0x2c,0x01,0x2f,0xff,0x2b,0x01,0x2c,0x01,0x30,0xff,0xb0,0x01,0x2c,0x01,0x31,0xff,0x2b,0x01,0x2c,0x01,0x32,0xff,0x2b,0x01,0x2c,0x01,0x33,0xff,0x8f,0x01,0x2c,0x01,0x34,0xff,0x2b,0x01,0x2c,0x01,0xa8,0x00,0x7b,0x01,0x2c,0x01,0xa9,0xff,0x6d,0x01,0x2c,0x01,0xac,0x00,0x0a,0x01,0x2c,0x01,0xb0,0xff,0x6d,0x01,0x2c, 0x01,0xb4,0xff,0xb6,0x01,0x2c,0x01,0xb8,0x00,0x2f,0x01,0x2c,0x01,0xb9,0x00,0x1d,0x01,0x2c,0x01,0xbc,0xff,0xcf,0x01,0x2c,0x01,0xbf,0xff,0x2b,0x01,0x2c,0x01,0xc0,0xff,0x2b,0x01,0x2c,0x01,0xc1,0xff,0x4e,0x01,0x2c,0x01,0xc2,0xff,0x8f,0x01,0x2c,0x01,0xc5,0xff,0xc1,0x01,0x2c,0x01,0xc7,0xff,0x4e,0x01,0x2c,0x01,0xc9,0xff,0x4e, 0x01,0x2c,0x01,0xca,0xff,0x4e,0x01,0x2c,0x01,0xcc,0xff,0x4e,0x01,0x2c,0x01,0xce,0xff,0xb0,0x01,0x2c,0x01,0xcf,0xff,0x2b,0x01,0x2c,0x01,0xd0,0xff,0x4e,0x01,0x2c,0x01,0xd1,0xff,0x2b,0x01,0x2c,0x01,0xd2,0xff,0x4e,0x01,0x2c,0x01,0xd3,0xff,0x7f,0x01,0x2c,0x01,0xd4,0xff,0x4e,0x01,0x2c,0x01,0xd5,0xff,0x2b,0x01,0x2c,0x01,0xd6, 0x00,0x52,0x01,0x2c,0x01,0xd7,0xff,0x4e,0x01,0x2c,0x01,0xd8,0xff,0x2b,0x01,0x2c,0x01,0xd9,0xff,0x4e,0x01,0x2c,0x01,0xda,0xff,0x2b,0x01,0x2c,0x02,0x37,0xff,0x8f,0x01,0x2d,0x00,0x0f,0xff,0xa2,0x01,0x2d,0x00,0xa9,0xff,0xcf,0x01,0x2d,0x00,0xc4,0xff,0x4a,0x01,0x2d,0x00,0xc5,0xff,0x96,0x01,0x2d,0x01,0xa9,0xff,0xe5,0x01,0x2d, 0x01,0xac,0xff,0xcd,0x01,0x2d,0x01,0xb0,0xff,0xe5,0x01,0x2d,0x01,0xb7,0xff,0xe3,0x01,0x2d,0x01,0xb8,0xff,0xa4,0x01,0x2d,0x01,0xb9,0xff,0xe7,0x01,0x2d,0x01,0xba,0xff,0xdb,0x01,0x2d,0x01,0xbe,0xff,0xe7,0x01,0x2d,0x01,0xcb,0xff,0xd7,0x01,0x2e,0x00,0x0f,0xff,0xa2,0x01,0x2e,0x00,0xa9,0xff,0xcf,0x01,0x2e,0x00,0xc4,0xff,0x4a, 0x01,0x2e,0x00,0xc5,0xff,0x96,0x01,0x2e,0x01,0xa9,0xff,0xcf,0x01,0x2e,0x01,0xac,0xff,0xcd,0x01,0x2e,0x01,0xb0,0xff,0xcf,0x01,0x2e,0x01,0xb7,0xff,0xe3,0x01,0x2e,0x01,0xb8,0xff,0xa4,0x01,0x2e,0x01,0xb9,0xff,0xe7,0x01,0x2e,0x01,0xba,0xff,0xd3,0x01,0x2e,0x01,0xbe,0xff,0xe7,0x01,0x2e,0x01,0xcb,0xff,0xc3,0x01,0x2f,0x01,0x2f, 0xff,0xee,0x01,0x2f,0x01,0x30,0xff,0xee,0x01,0x2f,0x01,0x32,0xff,0xee,0x01,0x2f,0x01,0x34,0xff,0xee,0x01,0x2f,0x01,0xbf,0xff,0xee,0x01,0x2f,0x01,0xcf,0xff,0xee,0x01,0x2f,0x01,0xd1,0xff,0xee,0x01,0x2f,0x01,0xd5,0xff,0xee,0x01,0x2f,0x01,0xd8,0xff,0xee,0x01,0x30,0x00,0x05,0xff,0x6f,0x01,0x30,0x00,0x0a,0xff,0x6f,0x01,0x30, 0x00,0xb4,0xff,0xb0,0x01,0x30,0x00,0xb5,0xff,0x7b,0x01,0x30,0x00,0xb6,0xff,0xbc,0x01,0x30,0x00,0xb7,0xff,0x7b,0x01,0x30,0x01,0x33,0xff,0xdb,0x01,0x30,0x01,0xc5,0xff,0xc1,0x01,0x30,0x01,0xd3,0xff,0xaa,0x01,0x30,0x02,0x37,0xff,0xdb,0x01,0x32,0x01,0x33,0x00,0x19,0x01,0x32,0x01,0xc5,0x00,0x31,0x01,0x32,0x01,0xcd,0x00,0x39, 0x01,0x32,0x01,0xd3,0x00,0x19,0x01,0x32,0x02,0x37,0x00,0x19,0x01,0x33,0x01,0x2f,0xff,0xdb,0x01,0x33,0x01,0x30,0xff,0xdb,0x01,0x33,0x01,0x32,0xff,0xdb,0x01,0x33,0x01,0x33,0x00,0x19,0x01,0x33,0x01,0x34,0xff,0xdb,0x01,0x33,0x01,0xbf,0xff,0xdb,0x01,0x33,0x01,0xc5,0x00,0x29,0x01,0x33,0x01,0xcd,0x00,0x25,0x01,0x33,0x01,0xcf, 0xff,0xdb,0x01,0x33,0x01,0xd0,0xff,0xcf,0x01,0x33,0x01,0xd3,0x00,0x19,0x01,0x33,0x01,0xd5,0xff,0xdb,0x01,0x33,0x01,0xd8,0xff,0xdb,0x01,0x33,0x01,0xda,0xff,0xdb,0x01,0x34,0x00,0x05,0xff,0x6f,0x01,0x34,0x00,0x0a,0xff,0x6f,0x01,0x34,0x00,0xb4,0xff,0xb0,0x01,0x34,0x00,0xb5,0xff,0x7b,0x01,0x34,0x00,0xb6,0xff,0xbc,0x01,0x34, 0x00,0xb7,0xff,0x7b,0x01,0x34,0x01,0x33,0xff,0xdb,0x01,0x34,0x01,0xc5,0xff,0xdb,0x01,0x34,0x01,0xd3,0xff,0xc3,0x01,0x34,0x02,0x37,0xff,0xdb,0x01,0x3a,0x00,0x4d,0x00,0x23,0x01,0x3a,0x01,0x64,0x00,0x23,0x01,0x3b,0x00,0x05,0xff,0x98,0x01,0x3b,0x00,0x0a,0xff,0x98,0x01,0x45,0x00,0x0d,0xff,0x7f,0x01,0x45,0x00,0x0f,0x00,0x44, 0x01,0x45,0x00,0x1e,0x00,0x44,0x01,0x45,0x00,0x26,0xff,0xe5,0x01,0x45,0x00,0x2a,0xff,0xe5,0x01,0x45,0x00,0x2d,0x00,0x5e,0x01,0x45,0x00,0x32,0xff,0xe5,0x01,0x45,0x00,0x37,0xff,0x6d,0x01,0x45,0x00,0x38,0xff,0xe5,0x01,0x45,0x00,0x39,0xff,0x8b,0x01,0x45,0x00,0x3a,0xff,0xb6,0x01,0x45,0x00,0x3c,0xff,0x64,0x01,0x45,0x00,0x3d, 0x00,0x3b,0x01,0x45,0x00,0x57,0xff,0xe5,0x01,0x45,0x00,0x59,0xff,0xd5,0x01,0x45,0x00,0x5a,0xff,0xe5,0x01,0x45,0x00,0x5c,0xff,0xdb,0x01,0x45,0x00,0x8d,0xff,0x9a,0x01,0x45,0x00,0xb4,0xff,0x66,0x01,0x45,0x00,0xb5,0xff,0x3f,0x01,0x45,0x00,0xb6,0xff,0x66,0x01,0x45,0x00,0xb7,0xff,0x3f,0x01,0x45,0x00,0xba,0xff,0xc1,0x01,0x45, 0x00,0xbb,0xff,0x64,0x01,0x45,0x00,0xe5,0x00,0x3b,0x01,0x45,0x00,0xea,0xff,0x64,0x01,0x45,0x00,0xeb,0xff,0xdb,0x01,0x45,0x00,0xf7,0xff,0xe5,0x01,0x45,0x00,0xfc,0xff,0xe5,0x01,0x45,0x00,0xfe,0xff,0xe5,0x01,0x45,0x01,0x18,0xff,0xe5,0x01,0x45,0x01,0x20,0xff,0x6d,0x01,0x45,0x01,0x21,0xff,0xe5,0x01,0x45,0x01,0x22,0xff,0x6d, 0x01,0x45,0x01,0x23,0xff,0xe5,0x01,0x45,0x01,0x24,0xff,0xe5,0x01,0x45,0x01,0x26,0xff,0xe5,0x01,0x45,0x01,0x28,0x00,0x3b,0x01,0x45,0x01,0x2a,0x00,0x3b,0x01,0x45,0x01,0x47,0xff,0xe5,0x01,0x45,0x01,0x51,0xff,0xe5,0x01,0x45,0x01,0x53,0xff,0xe5,0x01,0x45,0x01,0x55,0xff,0xe5,0x01,0x45,0x01,0x63,0x00,0x5e,0x01,0x45,0x01,0x6e, 0xff,0xe5,0x01,0x45,0x01,0x70,0xff,0xe5,0x01,0x45,0x01,0x76,0xff,0x6d,0x01,0x45,0x01,0x77,0xff,0xe5,0x01,0x45,0x01,0x78,0xff,0xe5,0x01,0x45,0x01,0x7a,0xff,0xe5,0x01,0x45,0x01,0x7c,0xff,0xe5,0x01,0x45,0x01,0x7e,0xff,0xe5,0x01,0x45,0x01,0x80,0xff,0xb6,0x01,0x45,0x01,0x81,0xff,0xe5,0x01,0x45,0x01,0x82,0xff,0x64,0x01,0x45, 0x01,0x83,0xff,0xdb,0x01,0x45,0x01,0x89,0xff,0xe5,0x01,0x45,0x01,0x8c,0xff,0xb6,0x01,0x45,0x01,0x8d,0xff,0xe5,0x01,0x45,0x01,0x8e,0xff,0xb6,0x01,0x45,0x01,0x8f,0xff,0xe5,0x01,0x45,0x01,0x90,0xff,0xb6,0x01,0x45,0x01,0x91,0xff,0xe5,0x01,0x45,0x01,0x92,0xff,0x64,0x01,0x45,0x01,0x93,0xff,0xdb,0x01,0x47,0x00,0x26,0xff,0xc9, 0x01,0x47,0x00,0x2a,0xff,0xc9,0x01,0x47,0x00,0x32,0xff,0xe5,0x01,0x47,0x00,0x34,0xff,0xc9,0x01,0x47,0x00,0x64,0xff,0xc9,0x01,0x47,0x00,0x67,0xff,0xc9,0x01,0x47,0x00,0x77,0x00,0x1d,0x01,0x47,0x00,0x92,0xff,0xc9,0x01,0x47,0x00,0xaa,0xff,0xcf,0x01,0x47,0x00,0xaf,0xff,0xc9,0x01,0x47,0x00,0xb0,0xff,0xc9,0x01,0x47,0x00,0xbe, 0xff,0xcf,0x01,0x47,0x00,0xd0,0xff,0xc9,0x01,0x47,0x00,0xd1,0xff,0xc9,0x01,0x47,0x00,0xd2,0xff,0xc9,0x01,0x47,0x00,0xf7,0xff,0xc9,0x01,0x47,0x00,0xfc,0xff,0xc9,0x01,0x47,0x00,0xfe,0xff,0xc9,0x01,0x47,0x01,0x18,0xff,0xe5,0x01,0x47,0x01,0x47,0xff,0xc9,0x01,0x47,0x01,0x51,0xff,0xc9,0x01,0x47,0x01,0x53,0xff,0xc9,0x01,0x47, 0x01,0x55,0xff,0xc9,0x01,0x47,0x01,0x5c,0x00,0x1d,0x01,0x47,0x01,0x5e,0x00,0x1d,0x01,0x47,0x01,0x60,0x00,0x1d,0x01,0x47,0x01,0x6e,0xff,0xe5,0x01,0x47,0x01,0x70,0xff,0xe5,0x01,0x47,0x01,0x89,0xff,0xe5,0x01,0x48,0x00,0x2d,0x00,0x46,0x01,0x48,0x00,0x37,0xff,0x9a,0x01,0x48,0x00,0x3c,0xff,0xb4,0x01,0x48,0x00,0xea,0xff,0xb4, 0x01,0x48,0x01,0x20,0xff,0x9a,0x01,0x48,0x01,0x22,0xff,0x9a,0x01,0x48,0x01,0x63,0x00,0x46,0x01,0x48,0x01,0x76,0xff,0x9a,0x01,0x48,0x01,0x82,0xff,0xb4,0x01,0x48,0x01,0x92,0xff,0xb4,0x01,0x4b,0x00,0x24,0x00,0x0a,0x01,0x4b,0x00,0x2d,0x00,0x44,0x01,0x4b,0x00,0x37,0x00,0x04,0x01,0x4b,0x00,0x3a,0x00,0x1d,0x01,0x4b,0x00,0x3b, 0x00,0x08,0x01,0x4b,0x00,0x62,0x00,0x0a,0x01,0x4b,0x00,0x63,0x00,0x0a,0x01,0x4b,0x00,0x77,0x00,0x12,0x01,0x4b,0x00,0xad,0x00,0x0a,0x01,0x4b,0x00,0xae,0x00,0x0a,0x01,0x4b,0x00,0xc7,0x00,0x0a,0x01,0x4b,0x00,0xc9,0x00,0x0a,0x01,0x4b,0x01,0x03,0x00,0x0a,0x01,0x4b,0x01,0x05,0x00,0x0a,0x01,0x4b,0x01,0x20,0x00,0x04,0x01,0x4b, 0x01,0x22,0x00,0x04,0x01,0x4b,0x01,0x45,0x00,0x0a,0x01,0x4b,0x01,0x5c,0x00,0x12,0x01,0x4b,0x01,0x5e,0x00,0x12,0x01,0x4b,0x01,0x60,0x00,0x12,0x01,0x4b,0x01,0x63,0x00,0x44,0x01,0x4b,0x01,0x76,0x00,0x04,0x01,0x4b,0x01,0x80,0x00,0x1d,0x01,0x4b,0x01,0x85,0x00,0x0a,0x01,0x4b,0x01,0x87,0x00,0x0a,0x01,0x4b,0x01,0x8c,0x00,0x1d, 0x01,0x4b,0x01,0x8e,0x00,0x1d,0x01,0x4b,0x01,0x90,0x00,0x1d,0x01,0x4c,0x00,0x05,0xff,0x98,0x01,0x4c,0x00,0x0a,0xff,0x98,0x01,0x4d,0x00,0x24,0x00,0x0a,0x01,0x4d,0x00,0x2d,0x00,0x44,0x01,0x4d,0x00,0x37,0x00,0x04,0x01,0x4d,0x00,0x3a,0x00,0x1d,0x01,0x4d,0x00,0x3b,0x00,0x08,0x01,0x4d,0x00,0x62,0x00,0x0a,0x01,0x4d,0x00,0x63, 0x00,0x0a,0x01,0x4d,0x00,0x77,0x00,0x12,0x01,0x4d,0x00,0xad,0x00,0x0a,0x01,0x4d,0x00,0xae,0x00,0x0a,0x01,0x4d,0x00,0xc7,0x00,0x0a,0x01,0x4d,0x00,0xc9,0x00,0x0a,0x01,0x4d,0x01,0x03,0x00,0x0a,0x01,0x4d,0x01,0x05,0x00,0x0a,0x01,0x4d,0x01,0x20,0x00,0x04,0x01,0x4d,0x01,0x22,0x00,0x04,0x01,0x4d,0x01,0x45,0x00,0x0a,0x01,0x4d, 0x01,0x5c,0x00,0x12,0x01,0x4d,0x01,0x5e,0x00,0x12,0x01,0x4d,0x01,0x60,0x00,0x12,0x01,0x4d,0x01,0x63,0x00,0x44,0x01,0x4d,0x01,0x76,0x00,0x04,0x01,0x4d,0x01,0x80,0x00,0x1d,0x01,0x4d,0x01,0x85,0x00,0x0a,0x01,0x4d,0x01,0x87,0x00,0x0a,0x01,0x4d,0x01,0x8c,0x00,0x1d,0x01,0x4d,0x01,0x8e,0x00,0x1d,0x01,0x4d,0x01,0x90,0x00,0x1d, 0x01,0x4e,0x00,0x05,0xff,0x98,0x01,0x4e,0x00,0x0a,0xff,0x98,0x01,0x4f,0x00,0x24,0x00,0x0a,0x01,0x4f,0x00,0x2d,0x00,0x44,0x01,0x4f,0x00,0x37,0x00,0x04,0x01,0x4f,0x00,0x3a,0x00,0x1d,0x01,0x4f,0x00,0x3b,0x00,0x08,0x01,0x4f,0x00,0x62,0x00,0x0a,0x01,0x4f,0x00,0x63,0x00,0x0a,0x01,0x4f,0x00,0x77,0x00,0x12,0x01,0x4f,0x00,0xad, 0x00,0x0a,0x01,0x4f,0x00,0xae,0x00,0x0a,0x01,0x4f,0x00,0xc7,0x00,0x0a,0x01,0x4f,0x00,0xc9,0x00,0x0a,0x01,0x4f,0x01,0x03,0x00,0x0a,0x01,0x4f,0x01,0x05,0x00,0x0a,0x01,0x4f,0x01,0x20,0x00,0x04,0x01,0x4f,0x01,0x22,0x00,0x04,0x01,0x4f,0x01,0x45,0x00,0x0a,0x01,0x4f,0x01,0x5c,0x00,0x12,0x01,0x4f,0x01,0x5e,0x00,0x12,0x01,0x4f, 0x01,0x60,0x00,0x12,0x01,0x4f,0x01,0x63,0x00,0x44,0x01,0x4f,0x01,0x76,0x00,0x04,0x01,0x4f,0x01,0x80,0x00,0x1d,0x01,0x4f,0x01,0x85,0x00,0x0a,0x01,0x4f,0x01,0x87,0x00,0x0a,0x01,0x4f,0x01,0x8c,0x00,0x1d,0x01,0x4f,0x01,0x8e,0x00,0x1d,0x01,0x4f,0x01,0x90,0x00,0x1d,0x01,0x50,0x00,0x05,0xff,0x98,0x01,0x50,0x00,0x0a,0xff,0x98, 0x01,0x51,0x00,0x37,0xff,0xcf,0x01,0x51,0x00,0x39,0xff,0xe5,0x01,0x51,0x00,0x5c,0xff,0xe5,0x01,0x51,0x00,0xba,0xff,0xe5,0x01,0x51,0x00,0xeb,0xff,0xe5,0x01,0x51,0x01,0x20,0xff,0xcf,0x01,0x51,0x01,0x22,0xff,0xcf,0x01,0x51,0x01,0x76,0xff,0xcf,0x01,0x51,0x01,0x83,0xff,0xe5,0x01,0x51,0x01,0x93,0xff,0xe5,0x01,0x52,0x00,0x4d, 0x00,0x2f,0x01,0x52,0x01,0x64,0x00,0x2f,0x01,0x53,0x00,0x37,0xff,0xcf,0x01,0x53,0x00,0x39,0xff,0xe5,0x01,0x53,0x00,0x5c,0xff,0xe5,0x01,0x53,0x00,0xba,0xff,0xe5,0x01,0x53,0x00,0xeb,0xff,0xe5,0x01,0x53,0x01,0x20,0xff,0xcf,0x01,0x53,0x01,0x22,0xff,0xcf,0x01,0x53,0x01,0x76,0xff,0xcf,0x01,0x53,0x01,0x83,0xff,0xe5,0x01,0x53, 0x01,0x93,0xff,0xe5,0x01,0x54,0x00,0x4d,0x00,0x2f,0x01,0x54,0x01,0x64,0x00,0x2f,0x01,0x55,0x00,0x37,0xff,0xcf,0x01,0x55,0x00,0x39,0xff,0xe5,0x01,0x55,0x00,0x5c,0xff,0xe5,0x01,0x55,0x00,0xba,0xff,0xe5,0x01,0x55,0x00,0xeb,0xff,0xe5,0x01,0x55,0x01,0x20,0xff,0xcf,0x01,0x55,0x01,0x22,0xff,0xcf,0x01,0x55,0x01,0x76,0xff,0xcf, 0x01,0x55,0x01,0x83,0xff,0xe5,0x01,0x55,0x01,0x93,0xff,0xe5,0x01,0x56,0x00,0x4d,0x00,0x2f,0x01,0x56,0x01,0x64,0x00,0x2f,0x01,0x63,0x00,0x0f,0xff,0x9a,0x01,0x63,0x00,0x11,0xff,0x9a,0x01,0x63,0x00,0x24,0xff,0xdb,0x01,0x63,0x00,0x2d,0xff,0xbe,0x01,0x63,0x00,0x44,0xff,0xe5,0x01,0x63,0x00,0x62,0xff,0xdb,0x01,0x63,0x00,0x63, 0xff,0xdb,0x01,0x63,0x00,0x69,0xff,0xe5,0x01,0x63,0x00,0x6a,0xff,0xe5,0x01,0x63,0x00,0x6b,0xff,0xe5,0x01,0x63,0x00,0x6c,0xff,0xe5,0x01,0x63,0x00,0x6d,0xff,0xe5,0x01,0x63,0x00,0x6e,0xff,0xe5,0x01,0x63,0x00,0x91,0xff,0x98,0x01,0x63,0x00,0xa0,0xff,0xe5,0x01,0x63,0x00,0xac,0xff,0x9a,0x01,0x63,0x00,0xad,0xff,0xdb,0x01,0x63, 0x00,0xae,0xff,0xdb,0x01,0x63,0x00,0xc4,0xff,0x66,0x01,0x63,0x00,0xc5,0xff,0x9a,0x01,0x63,0x00,0xc7,0xff,0xdb,0x01,0x63,0x00,0xc9,0xff,0xdb,0x01,0x63,0x01,0x03,0xff,0xdb,0x01,0x63,0x01,0x04,0xff,0xe5,0x01,0x63,0x01,0x05,0xff,0xdb,0x01,0x63,0x01,0x06,0xff,0xe5,0x01,0x63,0x01,0x45,0xff,0xdb,0x01,0x63,0x01,0x46,0xff,0xe5, 0x01,0x63,0x01,0x63,0xff,0xbe,0x01,0x63,0x01,0x85,0xff,0xdb,0x01,0x63,0x01,0x86,0xff,0xe5,0x01,0x63,0x01,0x87,0xff,0xdb,0x01,0x63,0x01,0x88,0xff,0xe5,0x01,0x64,0x00,0x4d,0x00,0x23,0x01,0x64,0x01,0x64,0x00,0x23,0x01,0x65,0x00,0x0f,0x00,0x27,0x01,0x65,0x00,0x1e,0x00,0x27,0x01,0x65,0x00,0x26,0xff,0xa6,0x01,0x65,0x00,0x2a, 0xff,0xa6,0x01,0x65,0x00,0x2d,0x00,0x5a,0x01,0x65,0x00,0x32,0xff,0xa6,0x01,0x65,0x00,0x34,0xff,0xa6,0x01,0x65,0x00,0x3b,0x00,0x25,0x01,0x65,0x00,0x3d,0x00,0x27,0x01,0x65,0x00,0x46,0xff,0xe5,0x01,0x65,0x00,0x47,0xff,0xe5,0x01,0x65,0x00,0x48,0xff,0xe5,0x01,0x65,0x00,0x4a,0xff,0xe5,0x01,0x65,0x00,0x52,0xff,0xe5,0x01,0x65, 0x00,0x54,0xff,0xe5,0x01,0x65,0x00,0x57,0xff,0xd1,0x01,0x65,0x00,0x59,0xff,0xb6,0x01,0x65,0x00,0x5a,0xff,0xcb,0x01,0x65,0x00,0x5c,0xff,0xa4,0x01,0x65,0x00,0x64,0xff,0x9a,0x01,0x65,0x00,0x67,0xff,0xa6,0x01,0x65,0x00,0x6f,0xff,0xe5,0x01,0x65,0x00,0x70,0xff,0xe5,0x01,0x65,0x00,0x71,0xff,0xe5,0x01,0x65,0x00,0x72,0xff,0xe5, 0x01,0x65,0x00,0x73,0xff,0xe5,0x01,0x65,0x00,0x74,0xff,0xcf,0x01,0x65,0x00,0x77,0x00,0x27,0x01,0x65,0x00,0x79,0xff,0xe5,0x01,0x65,0x00,0x7a,0xff,0xe5,0x01,0x65,0x00,0x7b,0xff,0xe5,0x01,0x65,0x00,0x7c,0xff,0xe5,0x01,0x65,0x00,0x7d,0xff,0xe5,0x01,0x65,0x00,0x92,0xff,0xa6,0x01,0x65,0x00,0xaf,0xff,0xa6,0x01,0x65,0x00,0xb0, 0xff,0xa6,0x01,0x65,0x00,0xb1,0xff,0xe5,0x01,0x65,0x00,0xba,0xff,0xa4,0x01,0x65,0x00,0xc4,0x00,0x44,0x01,0x65,0x00,0xc5,0x00,0x44,0x01,0x65,0x00,0xd0,0xff,0xa6,0x01,0x65,0x00,0xd1,0xff,0xa6,0x01,0x65,0x00,0xd2,0xff,0xa6,0x01,0x65,0x00,0xe5,0x00,0x27,0x01,0x65,0x00,0xeb,0xff,0xa4,0x01,0x65,0x00,0xf7,0xff,0xa6,0x01,0x65, 0x00,0xf8,0xff,0xe5,0x01,0x65,0x00,0xfc,0xff,0xa6,0x01,0x65,0x00,0xfd,0xff,0xe5,0x01,0x65,0x00,0xfe,0xff,0xa6,0x01,0x65,0x00,0xff,0xff,0xe5,0x01,0x65,0x01,0x00,0xff,0xe5,0x01,0x65,0x01,0x08,0xff,0xe5,0x01,0x65,0x01,0x0b,0xff,0xe5,0x01,0x65,0x01,0x0d,0xff,0xe5,0x01,0x65,0x01,0x18,0xff,0xa6,0x01,0x65,0x01,0x19,0xff,0xe5, 0x01,0x65,0x01,0x21,0xff,0xd1,0x01,0x65,0x01,0x23,0xff,0xd1,0x01,0x65,0x01,0x28,0x00,0x27,0x01,0x65,0x01,0x2a,0x00,0x27,0x01,0x65,0x01,0x47,0xff,0xa6,0x01,0x65,0x01,0x48,0xff,0xe5,0x01,0x65,0x01,0x4c,0xff,0xe5,0x01,0x65,0x01,0x4e,0xff,0xe5,0x01,0x65,0x01,0x50,0xff,0xe5,0x01,0x65,0x01,0x51,0xff,0xa6,0x01,0x65,0x01,0x52, 0xff,0xe5,0x01,0x65,0x01,0x53,0xff,0xa6,0x01,0x65,0x01,0x54,0xff,0xe5,0x01,0x65,0x01,0x55,0xff,0xa6,0x01,0x65,0x01,0x56,0xff,0xe5,0x01,0x65,0x01,0x5c,0x00,0x27,0x01,0x65,0x01,0x5e,0x00,0x27,0x01,0x65,0x01,0x60,0x00,0x27,0x01,0x65,0x01,0x63,0x00,0x5a,0x01,0x65,0x01,0x6e,0xff,0xa6,0x01,0x65,0x01,0x6f,0xff,0xe5,0x01,0x65, 0x01,0x70,0xff,0xa6,0x01,0x65,0x01,0x71,0xff,0xe5,0x01,0x65,0x01,0x77,0xff,0xd1,0x01,0x65,0x01,0x81,0xff,0xcb,0x01,0x65,0x01,0x83,0xff,0xa4,0x01,0x65,0x01,0x89,0xff,0xa6,0x01,0x65,0x01,0x8a,0xff,0xe5,0x01,0x65,0x01,0x8d,0xff,0xcb,0x01,0x65,0x01,0x8f,0xff,0xcb,0x01,0x65,0x01,0x91,0xff,0xcb,0x01,0x65,0x01,0x93,0xff,0xa4, 0x01,0x66,0x00,0x0f,0x00,0x52,0x01,0x66,0x00,0x10,0xff,0x75,0x01,0x66,0x00,0x11,0x00,0x52,0x01,0x66,0x00,0x1d,0x00,0x52,0x01,0x66,0x00,0x1e,0x00,0x52,0x01,0x66,0x00,0x46,0xff,0xd7,0x01,0x66,0x00,0x47,0xff,0xe5,0x01,0x66,0x00,0x48,0xff,0xd7,0x01,0x66,0x00,0x4a,0xff,0xd7,0x01,0x66,0x00,0x52,0xff,0xd7,0x01,0x66,0x00,0x54, 0xff,0xe5,0x01,0x66,0x00,0x57,0xff,0xf0,0x01,0x66,0x00,0x6f,0xff,0xe5,0x01,0x66,0x00,0x70,0xff,0xd7,0x01,0x66,0x00,0x71,0xff,0xd7,0x01,0x66,0x00,0x72,0xff,0xd7,0x01,0x66,0x00,0x73,0xff,0xd7,0x01,0x66,0x00,0x79,0xff,0xd7,0x01,0x66,0x00,0x7a,0xff,0xd7,0x01,0x66,0x00,0x7b,0xff,0xd7,0x01,0x66,0x00,0x7c,0xff,0xd7,0x01,0x66, 0x00,0x7d,0xff,0xd7,0x01,0x66,0x00,0xac,0x00,0x52,0x01,0x66,0x00,0xb1,0xff,0xd7,0x01,0x66,0x00,0xf8,0xff,0xd7,0x01,0x66,0x00,0xfd,0xff,0xd7,0x01,0x66,0x00,0xff,0xff,0xd7,0x01,0x66,0x01,0x00,0xff,0xe5,0x01,0x66,0x01,0x08,0xff,0xe5,0x01,0x66,0x01,0x0b,0xff,0xd7,0x01,0x66,0x01,0x0d,0xff,0xd7,0x01,0x66,0x01,0x19,0xff,0xd7, 0x01,0x66,0x01,0x21,0xff,0xf0,0x01,0x66,0x01,0x23,0xff,0xf0,0x01,0x66,0x01,0x48,0xff,0xd7,0x01,0x66,0x01,0x4c,0xff,0xd7,0x01,0x66,0x01,0x4e,0xff,0xd7,0x01,0x66,0x01,0x50,0xff,0xd7,0x01,0x66,0x01,0x52,0xff,0xd7,0x01,0x66,0x01,0x54,0xff,0xd7,0x01,0x66,0x01,0x56,0xff,0xd7,0x01,0x66,0x01,0x6f,0xff,0xd7,0x01,0x66,0x01,0x71, 0xff,0xd7,0x01,0x66,0x01,0x77,0xff,0xf0,0x01,0x66,0x01,0x8a,0xff,0xd7,0x01,0x67,0x00,0x0f,0x00,0x52,0x01,0x67,0x00,0x10,0xff,0x75,0x01,0x67,0x00,0x11,0x00,0x52,0x01,0x67,0x00,0x1d,0x00,0x52,0x01,0x67,0x00,0x1e,0x00,0x52,0x01,0x67,0x00,0x46,0xff,0xd7,0x01,0x67,0x00,0x47,0xff,0xe5,0x01,0x67,0x00,0x48,0xff,0xd7,0x01,0x67, 0x00,0x4a,0xff,0xd7,0x01,0x67,0x00,0x52,0xff,0xd7,0x01,0x67,0x00,0x54,0xff,0xe5,0x01,0x67,0x00,0x57,0xff,0xf0,0x01,0x67,0x00,0x6f,0xff,0xe5,0x01,0x67,0x00,0x70,0xff,0xd7,0x01,0x67,0x00,0x71,0xff,0xd7,0x01,0x67,0x00,0x72,0xff,0xd7,0x01,0x67,0x00,0x73,0xff,0xd7,0x01,0x67,0x00,0x79,0xff,0xd7,0x01,0x67,0x00,0x7a,0xff,0xd7, 0x01,0x67,0x00,0x7b,0xff,0xd7,0x01,0x67,0x00,0x7c,0xff,0xd7,0x01,0x67,0x00,0x7d,0xff,0xd7,0x01,0x67,0x00,0xac,0x00,0x52,0x01,0x67,0x00,0xb1,0xff,0xd7,0x01,0x67,0x00,0xf8,0xff,0xd7,0x01,0x67,0x00,0xfd,0xff,0xd7,0x01,0x67,0x00,0xff,0xff,0xd7,0x01,0x67,0x01,0x00,0xff,0xe5,0x01,0x67,0x01,0x08,0xff,0xe5,0x01,0x67,0x01,0x0b, 0xff,0xd7,0x01,0x67,0x01,0x0d,0xff,0xd7,0x01,0x67,0x01,0x19,0xff,0xd7,0x01,0x67,0x01,0x21,0xff,0xf0,0x01,0x67,0x01,0x23,0xff,0xf0,0x01,0x67,0x01,0x48,0xff,0xd7,0x01,0x67,0x01,0x4c,0xff,0xd7,0x01,0x67,0x01,0x4e,0xff,0xd7,0x01,0x67,0x01,0x50,0xff,0xd7,0x01,0x67,0x01,0x52,0xff,0xd7,0x01,0x67,0x01,0x54,0xff,0xd7,0x01,0x67, 0x01,0x56,0xff,0xd7,0x01,0x67,0x01,0x6f,0xff,0xd7,0x01,0x67,0x01,0x71,0xff,0xd7,0x01,0x67,0x01,0x77,0xff,0xf0,0x01,0x67,0x01,0x8a,0xff,0xd7,0x01,0x68,0x00,0x0d,0xff,0x31,0x01,0x68,0x00,0x22,0xff,0x9a,0x01,0x68,0x00,0x24,0x00,0x3b,0x01,0x68,0x00,0x26,0xff,0xbe,0x01,0x68,0x00,0x2a,0xff,0xbe,0x01,0x68,0x00,0x2d,0x00,0x64, 0x01,0x68,0x00,0x32,0xff,0xba,0x01,0x68,0x00,0x34,0xff,0xba,0x01,0x68,0x00,0x37,0xff,0x8f,0x01,0x68,0x00,0x38,0xff,0xe3,0x01,0x68,0x00,0x39,0xff,0x8b,0x01,0x68,0x00,0x3a,0xff,0xcf,0x01,0x68,0x00,0x3c,0xff,0x7f,0x01,0x68,0x00,0x3d,0x00,0x3b,0x01,0x68,0x00,0x57,0xff,0xe5,0x01,0x68,0x00,0x59,0xff,0x9a,0x01,0x68,0x00,0x5a, 0xff,0xbe,0x01,0x68,0x00,0x5c,0xff,0xb4,0x01,0x68,0x00,0x64,0xff,0xbe,0x01,0x68,0x00,0x67,0xff,0xba,0x01,0x68,0x00,0x68,0xff,0xe3,0x01,0x68,0x00,0x8d,0xff,0x9a,0x01,0x68,0x00,0x92,0xff,0xba,0x01,0x68,0x00,0xaf,0xff,0xba,0x01,0x68,0x00,0xb0,0xff,0xba,0x01,0x68,0x00,0xb4,0xff,0x73,0x01,0x68,0x00,0xb5,0xff,0x8b,0x01,0x68, 0x00,0xb6,0xff,0x73,0x01,0x68,0x00,0xb7,0xff,0x7f,0x01,0x68,0x00,0xba,0xff,0xb4,0x01,0x68,0x00,0xbb,0xff,0x9a,0x01,0x68,0x00,0xc4,0x00,0x44,0x01,0x68,0x00,0xc5,0x00,0x44,0x01,0x68,0x00,0xd0,0xff,0xba,0x01,0x68,0x00,0xd1,0xff,0xba,0x01,0x68,0x00,0xd2,0xff,0xba,0x01,0x68,0x00,0xd3,0xff,0xe3,0x01,0x68,0x00,0xd4,0xff,0xe3, 0x01,0x68,0x00,0xd5,0xff,0xe3,0x01,0x68,0x00,0xe5,0x00,0x3b,0x01,0x68,0x00,0xea,0xff,0x7f,0x01,0x68,0x00,0xeb,0xff,0xb4,0x01,0x68,0x00,0xf7,0xff,0xbe,0x01,0x68,0x00,0xfc,0xff,0xbe,0x01,0x68,0x00,0xfe,0xff,0xbe,0x01,0x68,0x01,0x03,0x00,0x3b,0x01,0x68,0x01,0x05,0x00,0x3b,0x01,0x68,0x01,0x18,0xff,0xba,0x01,0x68,0x01,0x20, 0xff,0x8f,0x01,0x68,0x01,0x21,0xff,0xe5,0x01,0x68,0x01,0x22,0xff,0x8f,0x01,0x68,0x01,0x23,0xff,0xe5,0x01,0x68,0x01,0x24,0xff,0xe3,0x01,0x68,0x01,0x26,0xff,0xe3,0x01,0x68,0x01,0x28,0x00,0x3b,0x01,0x68,0x01,0x2a,0x00,0x3b,0x01,0x68,0x01,0x45,0x00,0x3b,0x01,0x68,0x01,0x47,0xff,0xbe,0x01,0x68,0x01,0x51,0xff,0xbe,0x01,0x68, 0x01,0x53,0xff,0xbe,0x01,0x68,0x01,0x55,0xff,0xbe,0x01,0x68,0x01,0x63,0x00,0x64,0x01,0x68,0x01,0x6e,0xff,0xba,0x01,0x68,0x01,0x70,0xff,0xba,0x01,0x68,0x01,0x76,0xff,0x8f,0x01,0x68,0x01,0x77,0xff,0xe5,0x01,0x68,0x01,0x78,0xff,0xe3,0x01,0x68,0x01,0x7a,0xff,0xe3,0x01,0x68,0x01,0x7c,0xff,0xe3,0x01,0x68,0x01,0x7e,0xff,0xe3, 0x01,0x68,0x01,0x80,0xff,0xcf,0x01,0x68,0x01,0x81,0xff,0xbe,0x01,0x68,0x01,0x82,0xff,0x7f,0x01,0x68,0x01,0x83,0xff,0xb4,0x01,0x68,0x01,0x85,0x00,0x3b,0x01,0x68,0x01,0x87,0x00,0x3b,0x01,0x68,0x01,0x89,0xff,0xba,0x01,0x68,0x01,0x8c,0xff,0xcf,0x01,0x68,0x01,0x8d,0xff,0xbe,0x01,0x68,0x01,0x8e,0xff,0xcf,0x01,0x68,0x01,0x8f, 0xff,0xbe,0x01,0x68,0x01,0x90,0xff,0xcf,0x01,0x68,0x01,0x91,0xff,0xbe,0x01,0x68,0x01,0x92,0xff,0x7f,0x01,0x68,0x01,0x93,0xff,0xb4,0x01,0x6c,0x00,0x0f,0xff,0x9a,0x01,0x6c,0x00,0x11,0xff,0x9a,0x01,0x6c,0x00,0x24,0xff,0xdb,0x01,0x6c,0x00,0x2d,0xff,0xbe,0x01,0x6c,0x00,0x44,0xff,0xe5,0x01,0x6c,0x00,0x62,0xff,0xdb,0x01,0x6c, 0x00,0x63,0xff,0xdb,0x01,0x6c,0x00,0x69,0xff,0xe5,0x01,0x6c,0x00,0x6a,0xff,0xe5,0x01,0x6c,0x00,0x6b,0xff,0xe5,0x01,0x6c,0x00,0x6c,0xff,0xe5,0x01,0x6c,0x00,0x6d,0xff,0xe5,0x01,0x6c,0x00,0x6e,0xff,0xe5,0x01,0x6c,0x00,0x91,0xff,0x98,0x01,0x6c,0x00,0xa0,0xff,0xe5,0x01,0x6c,0x00,0xac,0xff,0x9a,0x01,0x6c,0x00,0xad,0xff,0xdb, 0x01,0x6c,0x00,0xae,0xff,0xdb,0x01,0x6c,0x00,0xc4,0xff,0x66,0x01,0x6c,0x00,0xc5,0xff,0x9a,0x01,0x6c,0x00,0xc7,0xff,0xdb,0x01,0x6c,0x00,0xc9,0xff,0xdb,0x01,0x6c,0x01,0x03,0xff,0xdb,0x01,0x6c,0x01,0x04,0xff,0xe5,0x01,0x6c,0x01,0x05,0xff,0xdb,0x01,0x6c,0x01,0x06,0xff,0xe5,0x01,0x6c,0x01,0x45,0xff,0xdb,0x01,0x6c,0x01,0x46, 0xff,0xe5,0x01,0x6c,0x01,0x63,0xff,0xbe,0x01,0x6c,0x01,0x85,0xff,0xdb,0x01,0x6c,0x01,0x86,0xff,0xe5,0x01,0x6c,0x01,0x87,0xff,0xdb,0x01,0x6c,0x01,0x88,0xff,0xe5,0x01,0x6d,0x00,0x4d,0x00,0x23,0x01,0x6d,0x01,0x64,0x00,0x23,0x01,0x6e,0x00,0x0f,0xff,0xa4,0x01,0x6e,0x00,0x11,0xff,0xa4,0x01,0x6e,0x00,0x24,0xff,0xe5,0x01,0x6e, 0x00,0x2d,0xff,0xf6,0x01,0x6e,0x00,0x37,0xff,0xa4,0x01,0x6e,0x00,0x3b,0xff,0xdb,0x01,0x6e,0x00,0x3c,0xff,0xe7,0x01,0x6e,0x00,0x3d,0xff,0xcf,0x01,0x6e,0x00,0x62,0xff,0xe5,0x01,0x6e,0x00,0x63,0xff,0xe5,0x01,0x6e,0x00,0xac,0xff,0xa4,0x01,0x6e,0x00,0xad,0xff,0xe5,0x01,0x6e,0x00,0xae,0xff,0xe5,0x01,0x6e,0x00,0xbb,0xff,0xf6, 0x01,0x6e,0x00,0xc4,0xff,0x4c,0x01,0x6e,0x00,0xc5,0xff,0x98,0x01,0x6e,0x00,0xc7,0xff,0xe5,0x01,0x6e,0x00,0xc9,0xff,0xe5,0x01,0x6e,0x00,0xe5,0xff,0xcf,0x01,0x6e,0x00,0xea,0xff,0xe7,0x01,0x6e,0x01,0x03,0xff,0xe5,0x01,0x6e,0x01,0x05,0xff,0xe5,0x01,0x6e,0x01,0x20,0xff,0xa4,0x01,0x6e,0x01,0x22,0xff,0xa4,0x01,0x6e,0x01,0x28, 0xff,0xcf,0x01,0x6e,0x01,0x2a,0xff,0xcf,0x01,0x6e,0x01,0x45,0xff,0xe5,0x01,0x6e,0x01,0x63,0xff,0xf6,0x01,0x6e,0x01,0x76,0xff,0xa4,0x01,0x6e,0x01,0x82,0xff,0xe7,0x01,0x6e,0x01,0x85,0xff,0xe5,0x01,0x6e,0x01,0x87,0xff,0xe5,0x01,0x6e,0x01,0x92,0xff,0xe7,0x01,0x6f,0x00,0x05,0xff,0x6f,0x01,0x6f,0x00,0x0a,0xff,0x6f,0x01,0x6f, 0x00,0x44,0xff,0xe5,0x01,0x6f,0x00,0x49,0xff,0xdb,0x01,0x6f,0x00,0x5b,0xff,0xe7,0x01,0x6f,0x00,0x69,0xff,0xe5,0x01,0x6f,0x00,0x6a,0xff,0xe5,0x01,0x6f,0x00,0x6b,0xff,0xe5,0x01,0x6f,0x00,0x6c,0xff,0xe5,0x01,0x6f,0x00,0x6d,0xff,0xe5,0x01,0x6f,0x00,0x6e,0xff,0xe5,0x01,0x6f,0x00,0xa0,0xff,0xe5,0x01,0x6f,0x00,0xb4,0xff,0xb2, 0x01,0x6f,0x00,0xb5,0xff,0x7d,0x01,0x6f,0x00,0xb6,0xff,0xbe,0x01,0x6f,0x00,0xb7,0xff,0x7d,0x01,0x6f,0x00,0xc0,0xff,0xe7,0x01,0x6f,0x00,0xc1,0xff,0xe7,0x01,0x6f,0x01,0x04,0xff,0xe5,0x01,0x6f,0x01,0x06,0xff,0xe5,0x01,0x6f,0x01,0x46,0xff,0xe5,0x01,0x6f,0x01,0x86,0xff,0xe5,0x01,0x6f,0x01,0x88,0xff,0xe5,0x01,0x70,0x00,0x0f, 0xff,0xa4,0x01,0x70,0x00,0x11,0xff,0xa4,0x01,0x70,0x00,0x24,0xff,0xe5,0x01,0x70,0x00,0x2d,0xff,0xf6,0x01,0x70,0x00,0x37,0xff,0xa4,0x01,0x70,0x00,0x3b,0xff,0xdb,0x01,0x70,0x00,0x3c,0xff,0xe7,0x01,0x70,0x00,0x3d,0xff,0xcf,0x01,0x70,0x00,0x62,0xff,0xe5,0x01,0x70,0x00,0x63,0xff,0xe5,0x01,0x70,0x00,0xac,0xff,0xa4,0x01,0x70, 0x00,0xad,0xff,0xe5,0x01,0x70,0x00,0xae,0xff,0xe5,0x01,0x70,0x00,0xbb,0xff,0xf6,0x01,0x70,0x00,0xc4,0xff,0x4c,0x01,0x70,0x00,0xc5,0xff,0x98,0x01,0x70,0x00,0xc7,0xff,0xe5,0x01,0x70,0x00,0xc9,0xff,0xe5,0x01,0x70,0x00,0xe5,0xff,0xcf,0x01,0x70,0x00,0xea,0xff,0xe7,0x01,0x70,0x01,0x03,0xff,0xe5,0x01,0x70,0x01,0x05,0xff,0xe5, 0x01,0x70,0x01,0x20,0xff,0xa4,0x01,0x70,0x01,0x22,0xff,0xa4,0x01,0x70,0x01,0x28,0xff,0xcf,0x01,0x70,0x01,0x2a,0xff,0xcf,0x01,0x70,0x01,0x45,0xff,0xe5,0x01,0x70,0x01,0x63,0xff,0xf6,0x01,0x70,0x01,0x76,0xff,0xa4,0x01,0x70,0x01,0x82,0xff,0xe7,0x01,0x70,0x01,0x85,0xff,0xe5,0x01,0x70,0x01,0x87,0xff,0xe5,0x01,0x70,0x01,0x92, 0xff,0xe7,0x01,0x71,0x00,0x05,0xff,0x6f,0x01,0x71,0x00,0x0a,0xff,0x6f,0x01,0x71,0x00,0x44,0xff,0xe5,0x01,0x71,0x00,0x49,0xff,0xdb,0x01,0x71,0x00,0x5b,0xff,0xe7,0x01,0x71,0x00,0x69,0xff,0xe5,0x01,0x71,0x00,0x6a,0xff,0xe5,0x01,0x71,0x00,0x6b,0xff,0xe5,0x01,0x71,0x00,0x6c,0xff,0xe5,0x01,0x71,0x00,0x6d,0xff,0xe5,0x01,0x71, 0x00,0x6e,0xff,0xe5,0x01,0x71,0x00,0xa0,0xff,0xe5,0x01,0x71,0x00,0xb4,0xff,0xb2,0x01,0x71,0x00,0xb5,0xff,0x7d,0x01,0x71,0x00,0xb6,0xff,0xbe,0x01,0x71,0x00,0xb7,0xff,0x7d,0x01,0x71,0x00,0xc0,0xff,0xe7,0x01,0x71,0x00,0xc1,0xff,0xe7,0x01,0x71,0x01,0x04,0xff,0xe5,0x01,0x71,0x01,0x06,0xff,0xe5,0x01,0x71,0x01,0x46,0xff,0xe5, 0x01,0x71,0x01,0x86,0xff,0xe5,0x01,0x71,0x01,0x88,0xff,0xe5,0x01,0x72,0x00,0x1e,0x00,0x52,0x01,0x72,0x00,0x26,0xff,0xe3,0x01,0x72,0x00,0x2a,0xff,0xe3,0x01,0x72,0x00,0x2d,0x00,0x39,0x01,0x72,0x00,0x32,0xff,0xec,0x01,0x72,0x00,0x34,0xff,0xec,0x01,0x72,0x00,0x37,0xff,0xcb,0x01,0x72,0x00,0x3c,0xff,0xd9,0x01,0x72,0x00,0x46, 0xff,0xcb,0x01,0x72,0x00,0x47,0xff,0xcb,0x01,0x72,0x00,0x48,0xff,0xc7,0x01,0x72,0x00,0x4a,0xff,0xc7,0x01,0x72,0x00,0x52,0xff,0xc5,0x01,0x72,0x00,0x54,0xff,0xcb,0x01,0x72,0x00,0x64,0xff,0xe5,0x01,0x72,0x00,0x67,0xff,0xec,0x01,0x72,0x00,0x6f,0xff,0xbe,0x01,0x72,0x00,0x70,0xff,0xbe,0x01,0x72,0x00,0x71,0xff,0xbe,0x01,0x72, 0x00,0x72,0xff,0xbe,0x01,0x72,0x00,0x73,0xff,0xbe,0x01,0x72,0x00,0x79,0xff,0xc5,0x01,0x72,0x00,0x7a,0xff,0xc5,0x01,0x72,0x00,0x7b,0xff,0xc5,0x01,0x72,0x00,0x7c,0xff,0xc5,0x01,0x72,0x00,0x7d,0xff,0xc5,0x01,0x72,0x00,0x92,0xff,0xec,0x01,0x72,0x00,0xaf,0xff,0xec,0x01,0x72,0x00,0xb0,0xff,0xec,0x01,0x72,0x00,0xb1,0xff,0xc5, 0x01,0x72,0x00,0xbb,0xff,0xe5,0x01,0x72,0x00,0xd0,0xff,0xec,0x01,0x72,0x00,0xd1,0xff,0xec,0x01,0x72,0x00,0xd2,0xff,0xec,0x01,0x72,0x00,0xea,0xff,0xd9,0x01,0x72,0x00,0xf7,0xff,0xe3,0x01,0x72,0x00,0xf8,0xff,0xc7,0x01,0x72,0x00,0xfc,0xff,0xe3,0x01,0x72,0x00,0xfd,0xff,0xcb,0x01,0x72,0x00,0xfe,0xff,0xe3,0x01,0x72,0x00,0xff, 0xff,0xcb,0x01,0x72,0x01,0x00,0xff,0xcb,0x01,0x72,0x01,0x08,0xff,0xcb,0x01,0x72,0x01,0x0b,0xff,0xc7,0x01,0x72,0x01,0x0d,0xff,0xbe,0x01,0x72,0x01,0x18,0xff,0xec,0x01,0x72,0x01,0x19,0xff,0xc5,0x01,0x72,0x01,0x20,0xff,0xcb,0x01,0x72,0x01,0x22,0xff,0xcb,0x01,0x72,0x01,0x47,0xff,0xe3,0x01,0x72,0x01,0x48,0xff,0xcb,0x01,0x72, 0x01,0x4c,0xff,0xbe,0x01,0x72,0x01,0x4e,0xff,0xbe,0x01,0x72,0x01,0x50,0xff,0xbe,0x01,0x72,0x01,0x51,0xff,0xe3,0x01,0x72,0x01,0x52,0xff,0xc7,0x01,0x72,0x01,0x53,0xff,0xe3,0x01,0x72,0x01,0x54,0xff,0xc7,0x01,0x72,0x01,0x55,0xff,0xe3,0x01,0x72,0x01,0x56,0xff,0xc7,0x01,0x72,0x01,0x63,0x00,0x39,0x01,0x72,0x01,0x6e,0xff,0xec, 0x01,0x72,0x01,0x6f,0xff,0xc5,0x01,0x72,0x01,0x70,0xff,0xec,0x01,0x72,0x01,0x71,0xff,0xc5,0x01,0x72,0x01,0x76,0xff,0xcb,0x01,0x72,0x01,0x82,0xff,0xd9,0x01,0x72,0x01,0x89,0xff,0xec,0x01,0x72,0x01,0x8a,0xff,0xc5,0x01,0x72,0x01,0x92,0xff,0xd9,0x01,0x73,0x00,0x0f,0xff,0x62,0x01,0x73,0x00,0x10,0xff,0x7f,0x01,0x73,0x00,0x11, 0xff,0x56,0x01,0x73,0x00,0x1d,0x00,0x52,0x01,0x73,0x00,0x1e,0x00,0x52,0x01,0x73,0x00,0x46,0xff,0xe5,0x01,0x73,0x00,0x47,0xff,0xe5,0x01,0x73,0x00,0x48,0xff,0xe5,0x01,0x73,0x00,0x49,0x00,0x27,0x01,0x73,0x00,0x4a,0xff,0xe5,0x01,0x73,0x00,0x50,0xff,0xfc,0x01,0x73,0x00,0x51,0xff,0xfc,0x01,0x73,0x00,0x52,0xff,0xe5,0x01,0x73, 0x00,0x54,0xff,0xe5,0x01,0x73,0x00,0x56,0x00,0x0e,0x01,0x73,0x00,0x57,0x00,0x3b,0x01,0x73,0x00,0x59,0x00,0x52,0x01,0x73,0x00,0x5a,0x00,0x52,0x01,0x73,0x00,0x5b,0x00,0x3b,0x01,0x73,0x00,0x5c,0x00,0x52,0x01,0x73,0x00,0x5d,0x00,0x27,0x01,0x73,0x00,0x6f,0xff,0xe5,0x01,0x73,0x00,0x70,0xff,0xe5,0x01,0x73,0x00,0x71,0xff,0xe5, 0x01,0x73,0x00,0x72,0xff,0xe5,0x01,0x73,0x00,0x73,0xff,0xe5,0x01,0x73,0x00,0x79,0xff,0xe5,0x01,0x73,0x00,0x7a,0xff,0xe5,0x01,0x73,0x00,0x7b,0xff,0xe5,0x01,0x73,0x00,0x7c,0xff,0xe5,0x01,0x73,0x00,0x7d,0xff,0xe5,0x01,0x73,0x00,0xac,0xff,0x56,0x01,0x73,0x00,0xb1,0xff,0xe5,0x01,0x73,0x00,0xb4,0x00,0xa4,0x01,0x73,0x00,0xb5, 0x00,0x79,0x01,0x73,0x00,0xb6,0x00,0xa4,0x01,0x73,0x00,0xb7,0x00,0x79,0x01,0x73,0x00,0xc4,0xff,0x62,0x01,0x73,0x00,0xc5,0xff,0x62,0x01,0x73,0x00,0xe4,0x00,0x0e,0x01,0x73,0x00,0xe6,0x00,0x27,0x01,0x73,0x00,0xeb,0x00,0x52,0x01,0x73,0x00,0xf8,0xff,0xe5,0x01,0x73,0x00,0xfb,0x00,0x0e,0x01,0x73,0x00,0xfd,0xff,0xe5,0x01,0x73, 0x00,0xff,0xff,0xe5,0x01,0x73,0x01,0x00,0xff,0xe5,0x01,0x73,0x01,0x08,0xff,0xe5,0x01,0x73,0x01,0x0b,0xff,0xe5,0x01,0x73,0x01,0x0d,0xff,0xe5,0x01,0x73,0x01,0x19,0xff,0xe5,0x01,0x73,0x01,0x1f,0x00,0x0e,0x01,0x73,0x01,0x21,0x00,0x3b,0x01,0x73,0x01,0x23,0x00,0x3b,0x01,0x73,0x01,0x29,0x00,0x27,0x01,0x73,0x01,0x2b,0x00,0x27, 0x01,0x73,0x01,0x48,0xff,0xe5,0x01,0x73,0x01,0x4c,0xff,0xe5,0x01,0x73,0x01,0x4e,0xff,0xe5,0x01,0x73,0x01,0x50,0xff,0xe5,0x01,0x73,0x01,0x52,0xff,0xe5,0x01,0x73,0x01,0x54,0xff,0xe5,0x01,0x73,0x01,0x56,0xff,0xe5,0x01,0x73,0x01,0x6d,0xff,0xfc,0x01,0x73,0x01,0x6f,0xff,0xe5,0x01,0x73,0x01,0x71,0xff,0xe5,0x01,0x73,0x01,0x75, 0x00,0x0e,0x01,0x73,0x01,0x77,0x00,0x3b,0x01,0x73,0x01,0x81,0x00,0x52,0x01,0x73,0x01,0x83,0x00,0x52,0x01,0x73,0x01,0x8a,0xff,0xe5,0x01,0x73,0x01,0x8d,0x00,0x52,0x01,0x73,0x01,0x8f,0x00,0x52,0x01,0x73,0x01,0x91,0x00,0x52,0x01,0x73,0x01,0x93,0x00,0x52,0x01,0x73,0x02,0x3e,0x00,0x0e,0x01,0x74,0x00,0x57,0xff,0xbe,0x01,0x74, 0x00,0x59,0xff,0xcf,0x01,0x74,0x00,0x5a,0xff,0xe5,0x01,0x74,0x00,0x5c,0xff,0xd1,0x01,0x74,0x00,0xba,0xff,0xbe,0x01,0x74,0x00,0xc4,0xff,0xb2,0x01,0x74,0x00,0xc5,0xff,0xb2,0x01,0x74,0x00,0xeb,0xff,0xd1,0x01,0x74,0x01,0x21,0xff,0xbe,0x01,0x74,0x01,0x23,0xff,0xbe,0x01,0x74,0x01,0x77,0xff,0xbe,0x01,0x74,0x01,0x81,0xff,0xe5, 0x01,0x74,0x01,0x83,0xff,0xd1,0x01,0x74,0x01,0x8d,0xff,0xe5,0x01,0x74,0x01,0x8f,0xff,0xe5,0x01,0x74,0x01,0x91,0xff,0xe5,0x01,0x74,0x01,0x93,0xff,0xd1,0x01,0x76,0x00,0x0f,0xff,0x7f,0x01,0x76,0x00,0x11,0xff,0x4c,0x01,0x76,0x00,0x1d,0xff,0xe9,0x01,0x76,0x00,0x1e,0xff,0xe9,0x01,0x76,0x00,0x24,0xff,0x66,0x01,0x76,0x00,0x26, 0xff,0xa4,0x01,0x76,0x00,0x2a,0xff,0xa4,0x01,0x76,0x00,0x2d,0xff,0x8f,0x01,0x76,0x00,0x32,0xff,0xa4,0x01,0x76,0x00,0x34,0xff,0xa4,0x01,0x76,0x00,0x37,0x00,0x27,0x01,0x76,0x00,0x39,0x00,0x2b,0x01,0x76,0x00,0x3a,0x00,0x27,0x01,0x76,0x00,0x3b,0xff,0xfa,0x01,0x76,0x00,0x3c,0x00,0x1d,0x01,0x76,0x00,0x44,0xff,0x27,0x01,0x76, 0x00,0x46,0xff,0x2d,0x01,0x76,0x00,0x47,0xff,0x2d,0x01,0x76,0x00,0x48,0xff,0x2d,0x01,0x76,0x00,0x49,0xff,0xa0,0x01,0x76,0x00,0x4a,0xff,0x2d,0x01,0x76,0x00,0x50,0xff,0x4e,0x01,0x76,0x00,0x51,0xff,0x4e,0x01,0x76,0x00,0x52,0xff,0x2d,0x01,0x76,0x00,0x53,0xff,0x4e,0x01,0x76,0x00,0x54,0xff,0x2d,0x01,0x76,0x00,0x55,0xff,0x4e, 0x01,0x76,0x00,0x56,0xff,0x66,0x01,0x76,0x00,0x58,0xff,0x4e,0x01,0x76,0x00,0x59,0xff,0x9a,0x01,0x76,0x00,0x5a,0xff,0x8f,0x01,0x76,0x00,0x5b,0xff,0x4c,0x01,0x76,0x00,0x5c,0xff,0x8f,0x01,0x76,0x00,0x5d,0xff,0x7f,0x01,0x76,0x00,0x62,0xff,0x66,0x01,0x76,0x00,0x63,0xff,0x66,0x01,0x76,0x00,0x64,0xff,0xa4,0x01,0x76,0x00,0x67, 0xff,0xa4,0x01,0x76,0x00,0x69,0xff,0x27,0x01,0x76,0x00,0x6a,0xff,0x27,0x01,0x76,0x00,0x6b,0xff,0x27,0x01,0x76,0x00,0x6c,0xff,0x27,0x01,0x76,0x00,0x6d,0xff,0x3f,0x01,0x76,0x00,0x6e,0xff,0x27,0x01,0x76,0x00,0x6f,0xff,0x1b,0x01,0x76,0x00,0x70,0xff,0x2d,0x01,0x76,0x00,0x71,0xff,0x2d,0x01,0x76,0x00,0x72,0xff,0x2d,0x01,0x76, 0x00,0x73,0xff,0x2d,0x01,0x76,0x00,0x74,0xff,0xe9,0x01,0x76,0x00,0x76,0x00,0x31,0x01,0x76,0x00,0x77,0x00,0x6f,0x01,0x76,0x00,0x78,0xff,0x4e,0x01,0x76,0x00,0x79,0xff,0x2d,0x01,0x76,0x00,0x7a,0xff,0x2d,0x01,0x76,0x00,0x7b,0xff,0x2d,0x01,0x76,0x00,0x7c,0xff,0x2d,0x01,0x76,0x00,0x7d,0xff,0x2d,0x01,0x76,0x00,0x7e,0xff,0x4e, 0x01,0x76,0x00,0x7f,0xff,0x4e,0x01,0x76,0x00,0x80,0xff,0x4e,0x01,0x76,0x00,0x81,0xff,0x4e,0x01,0x76,0x00,0x8d,0x00,0x52,0x01,0x76,0x00,0x91,0xff,0x0c,0x01,0x76,0x00,0x92,0xff,0xa4,0x01,0x76,0x00,0xa0,0xff,0x27,0x01,0x76,0x00,0xaa,0xff,0x9a,0x01,0x76,0x00,0xab,0xff,0xcf,0x01,0x76,0x00,0xac,0xff,0x4c,0x01,0x76,0x00,0xad, 0xff,0x66,0x01,0x76,0x00,0xae,0xff,0x66,0x01,0x76,0x00,0xaf,0xff,0xa4,0x01,0x76,0x00,0xb0,0xff,0xa4,0x01,0x76,0x00,0xb1,0xff,0x2d,0x01,0x76,0x00,0xb5,0x00,0x27,0x01,0x76,0x00,0xb7,0x00,0x27,0x01,0x76,0x00,0xba,0xff,0x8f,0x01,0x76,0x00,0xbe,0xff,0x9a,0x01,0x76,0x00,0xbf,0xff,0xcf,0x01,0x76,0x00,0xc4,0xff,0x17,0x01,0x76, 0x00,0xc5,0xff,0x17,0x01,0x76,0x00,0xc7,0xff,0x66,0x01,0x76,0x00,0xc9,0xff,0x66,0x01,0x76,0x00,0xd0,0xff,0xa4,0x01,0x76,0x00,0xd1,0xff,0xa4,0x01,0x76,0x00,0xd2,0xff,0xa4,0x01,0x76,0x00,0xe4,0xff,0x66,0x01,0x76,0x00,0xe6,0xff,0x7f,0x01,0x76,0x00,0xea,0x00,0x1d,0x01,0x76,0x00,0xeb,0xff,0x8f,0x01,0x76,0x00,0xf7,0xff,0xa4, 0x01,0x76,0x00,0xf8,0xff,0x2d,0x01,0x76,0x00,0xfb,0xff,0x66,0x01,0x76,0x00,0xfc,0xff,0xa4,0x01,0x76,0x00,0xfd,0xff,0x2d,0x01,0x76,0x00,0xfe,0xff,0xa4,0x01,0x76,0x00,0xff,0xff,0x2d,0x01,0x76,0x01,0x00,0xff,0x2d,0x01,0x76,0x01,0x03,0xff,0x66,0x01,0x76,0x01,0x04,0xff,0x27,0x01,0x76,0x01,0x05,0xff,0x66,0x01,0x76,0x01,0x06, 0xff,0x27,0x01,0x76,0x01,0x08,0xff,0x2d,0x01,0x76,0x01,0x0b,0xff,0x2d,0x01,0x76,0x01,0x0d,0xff,0x2d,0x01,0x76,0x01,0x15,0xff,0x4e,0x01,0x76,0x01,0x17,0xff,0x4e,0x01,0x76,0x01,0x18,0xff,0xa4,0x01,0x76,0x01,0x19,0xff,0x2d,0x01,0x76,0x01,0x1b,0xff,0x4e,0x01,0x76,0x01,0x1d,0xff,0x4e,0x01,0x76,0x01,0x1f,0xff,0x66,0x01,0x76, 0x01,0x20,0x00,0x27,0x01,0x76,0x01,0x22,0x00,0x27,0x01,0x76,0x01,0x25,0xff,0x4e,0x01,0x76,0x01,0x27,0xff,0x4e,0x01,0x76,0x01,0x29,0xff,0x7f,0x01,0x76,0x01,0x2b,0xff,0x7f,0x01,0x76,0x01,0x45,0xff,0x66,0x01,0x76,0x01,0x46,0xff,0x27,0x01,0x76,0x01,0x47,0xff,0xa4,0x01,0x76,0x01,0x48,0xff,0x2d,0x01,0x76,0x01,0x4c,0xff,0x2d, 0x01,0x76,0x01,0x4e,0xff,0x2d,0x01,0x76,0x01,0x50,0xff,0x2d,0x01,0x76,0x01,0x51,0xff,0xa4,0x01,0x76,0x01,0x52,0xff,0x2d,0x01,0x76,0x01,0x53,0xff,0xa4,0x01,0x76,0x01,0x54,0xff,0x2d,0x01,0x76,0x01,0x55,0xff,0xa4,0x01,0x76,0x01,0x56,0xff,0x2d,0x01,0x76,0x01,0x5c,0x00,0x6f,0x01,0x76,0x01,0x5e,0x00,0x6f,0x01,0x76,0x01,0x60, 0x00,0x6f,0x01,0x76,0x01,0x63,0xff,0x8f,0x01,0x76,0x01,0x6d,0xff,0x4e,0x01,0x76,0x01,0x6e,0xff,0xa4,0x01,0x76,0x01,0x6f,0xff,0x2d,0x01,0x76,0x01,0x70,0xff,0xa4,0x01,0x76,0x01,0x71,0xff,0x2d,0x01,0x76,0x01,0x73,0xff,0x4e,0x01,0x76,0x01,0x75,0xff,0x66,0x01,0x76,0x01,0x76,0x00,0x27,0x01,0x76,0x01,0x79,0xff,0x4e,0x01,0x76, 0x01,0x7b,0xff,0x4e,0x01,0x76,0x01,0x7d,0xff,0x4e,0x01,0x76,0x01,0x7f,0xff,0x4e,0x01,0x76,0x01,0x80,0x00,0x27,0x01,0x76,0x01,0x81,0xff,0x8f,0x01,0x76,0x01,0x82,0x00,0x1d,0x01,0x76,0x01,0x83,0xff,0x8f,0x01,0x76,0x01,0x85,0xff,0x66,0x01,0x76,0x01,0x86,0xff,0x27,0x01,0x76,0x01,0x87,0xff,0x66,0x01,0x76,0x01,0x88,0xff,0x27, 0x01,0x76,0x01,0x89,0xff,0xa4,0x01,0x76,0x01,0x8a,0xff,0x2d,0x01,0x76,0x01,0x8c,0x00,0x27,0x01,0x76,0x01,0x8d,0xff,0x8f,0x01,0x76,0x01,0x8e,0x00,0x27,0x01,0x76,0x01,0x8f,0xff,0x8f,0x01,0x76,0x01,0x90,0x00,0x27,0x01,0x76,0x01,0x91,0xff,0x8f,0x01,0x76,0x01,0x92,0x00,0x1d,0x01,0x76,0x01,0x93,0xff,0x8f,0x01,0x76,0x02,0x3e, 0xff,0x66,0x01,0x77,0x00,0x10,0xff,0x8f,0x01,0x77,0x00,0x22,0xff,0xcb,0x01,0x77,0x00,0x46,0xff,0xe5,0x01,0x77,0x00,0x47,0xff,0xe5,0x01,0x77,0x00,0x48,0xff,0xf0,0x01,0x77,0x00,0x4a,0xff,0xf0,0x01,0x77,0x00,0x52,0xff,0xf0,0x01,0x77,0x00,0x54,0xff,0xf0,0x01,0x77,0x00,0x5b,0x00,0x1d,0x01,0x77,0x00,0x6f,0xff,0xe5,0x01,0x77, 0x00,0x70,0xff,0xf0,0x01,0x77,0x00,0x71,0xff,0xf0,0x01,0x77,0x00,0x72,0xff,0xf0,0x01,0x77,0x00,0x73,0xff,0xf0,0x01,0x77,0x00,0x79,0xff,0xf0,0x01,0x77,0x00,0x7a,0xff,0xf0,0x01,0x77,0x00,0x7b,0xff,0xf0,0x01,0x77,0x00,0x7c,0xff,0xf0,0x01,0x77,0x00,0x7d,0xff,0xf0,0x01,0x77,0x00,0xab,0x00,0x27,0x01,0x77,0x00,0xb1,0xff,0xf0, 0x01,0x77,0x00,0xbf,0x00,0x27,0x01,0x77,0x00,0xf8,0xff,0xf0,0x01,0x77,0x00,0xfd,0xff,0xe5,0x01,0x77,0x00,0xff,0xff,0xe5,0x01,0x77,0x01,0x00,0xff,0xe5,0x01,0x77,0x01,0x08,0xff,0xe5,0x01,0x77,0x01,0x0b,0xff,0xf0,0x01,0x77,0x01,0x0d,0xff,0xf0,0x01,0x77,0x01,0x19,0xff,0xf0,0x01,0x77,0x01,0x48,0xff,0xe5,0x01,0x77,0x01,0x4c, 0xff,0xf0,0x01,0x77,0x01,0x4e,0xff,0xf0,0x01,0x77,0x01,0x50,0xff,0xf0,0x01,0x77,0x01,0x52,0xff,0xf0,0x01,0x77,0x01,0x54,0xff,0xf0,0x01,0x77,0x01,0x56,0xff,0xf0,0x01,0x77,0x01,0x6f,0xff,0xf0,0x01,0x77,0x01,0x71,0xff,0xf0,0x01,0x77,0x01,0x8a,0xff,0xf0,0x01,0x78,0x00,0x24,0xff,0xd7,0x01,0x78,0x00,0x91,0xff,0x8b,0x01,0x78, 0x00,0xc4,0xff,0xa6,0x01,0x78,0x00,0xc5,0xff,0xa6,0x01,0x78,0x01,0x03,0xff,0xd7,0x01,0x78,0x01,0x05,0xff,0xd7,0x01,0x78,0x01,0x45,0xff,0xd7,0x01,0x78,0x01,0x85,0xff,0xd7,0x01,0x78,0x01,0x87,0xff,0xd7,0x01,0x79,0x00,0x05,0xff,0xbe,0x01,0x79,0x00,0x0a,0xff,0xbe,0x01,0x7a,0x00,0x24,0xff,0xd7,0x01,0x7a,0x00,0x91,0xff,0x8b, 0x01,0x7a,0x00,0xc4,0xff,0xa6,0x01,0x7a,0x00,0xc5,0xff,0xa6,0x01,0x7a,0x01,0x03,0xff,0xd7,0x01,0x7a,0x01,0x05,0xff,0xd7,0x01,0x7a,0x01,0x45,0xff,0xd7,0x01,0x7a,0x01,0x85,0xff,0xd7,0x01,0x7a,0x01,0x87,0xff,0xd7,0x01,0x7b,0x00,0x05,0xff,0xbe,0x01,0x7b,0x00,0x0a,0xff,0xbe,0x01,0x7c,0x00,0x24,0xff,0xd7,0x01,0x7c,0x00,0x91, 0xff,0x8b,0x01,0x7c,0x00,0xc4,0xff,0xa6,0x01,0x7c,0x00,0xc5,0xff,0xa6,0x01,0x7c,0x01,0x03,0xff,0xd7,0x01,0x7c,0x01,0x05,0xff,0xd7,0x01,0x7c,0x01,0x45,0xff,0xd7,0x01,0x7c,0x01,0x85,0xff,0xd7,0x01,0x7c,0x01,0x87,0xff,0xd7,0x01,0x7d,0x00,0x05,0xff,0xbe,0x01,0x7d,0x00,0x0a,0xff,0xbe,0x01,0x7e,0x00,0x24,0xff,0xd7,0x01,0x7e, 0x00,0x91,0xff,0x8b,0x01,0x7e,0x00,0xc4,0xff,0xa6,0x01,0x7e,0x00,0xc5,0xff,0xa6,0x01,0x7e,0x01,0x03,0xff,0xd7,0x01,0x7e,0x01,0x05,0xff,0xd7,0x01,0x7e,0x01,0x45,0xff,0xd7,0x01,0x7e,0x01,0x85,0xff,0xd7,0x01,0x7e,0x01,0x87,0xff,0xd7,0x01,0x7f,0x00,0x05,0xff,0xbe,0x01,0x7f,0x00,0x0a,0xff,0xbe,0x01,0x80,0x00,0x0f,0xff,0x8b, 0x01,0x80,0x00,0x11,0xff,0x7f,0x01,0x80,0x00,0x24,0xff,0xb6,0x01,0x80,0x00,0x37,0x00,0x27,0x01,0x80,0x00,0x44,0xff,0xb4,0x01,0x80,0x00,0x46,0xff,0xcf,0x01,0x80,0x00,0x47,0xff,0xcf,0x01,0x80,0x00,0x48,0xff,0xcf,0x01,0x80,0x00,0x4a,0xff,0xcf,0x01,0x80,0x00,0x52,0xff,0xcf,0x01,0x80,0x00,0x54,0xff,0xcf,0x01,0x80,0x00,0x62, 0xff,0xb6,0x01,0x80,0x00,0x63,0xff,0xb6,0x01,0x80,0x00,0x69,0xff,0xb4,0x01,0x80,0x00,0x6a,0xff,0xb4,0x01,0x80,0x00,0x6b,0xff,0xb4,0x01,0x80,0x00,0x6c,0xff,0xb4,0x01,0x80,0x00,0x6d,0xff,0xb4,0x01,0x80,0x00,0x6e,0xff,0xb4,0x01,0x80,0x00,0x6f,0xff,0xcf,0x01,0x80,0x00,0x70,0xff,0xcf,0x01,0x80,0x00,0x71,0xff,0xcf,0x01,0x80, 0x00,0x72,0xff,0xcf,0x01,0x80,0x00,0x73,0xff,0xcf,0x01,0x80,0x00,0x76,0x00,0x31,0x01,0x80,0x00,0x77,0x00,0x64,0x01,0x80,0x00,0x79,0xff,0xcf,0x01,0x80,0x00,0x7a,0xff,0xcf,0x01,0x80,0x00,0x7b,0xff,0xcf,0x01,0x80,0x00,0x7c,0xff,0xcf,0x01,0x80,0x00,0x7d,0xff,0xcf,0x01,0x80,0x00,0x91,0xff,0x9a,0x01,0x80,0x00,0xa0,0xff,0xb4, 0x01,0x80,0x00,0xa2,0xff,0xa4,0x01,0x80,0x00,0xaa,0xff,0xcf,0x01,0x80,0x00,0xab,0x00,0x27,0x01,0x80,0x00,0xac,0xff,0x7f,0x01,0x80,0x00,0xad,0xff,0xb6,0x01,0x80,0x00,0xae,0xff,0xb6,0x01,0x80,0x00,0xb1,0xff,0xcf,0x01,0x80,0x00,0xbe,0xff,0xcf,0x01,0x80,0x00,0xbf,0x00,0x27,0x01,0x80,0x00,0xc4,0xff,0x7f,0x01,0x80,0x00,0xc5, 0xff,0x8b,0x01,0x80,0x00,0xc7,0xff,0xb6,0x01,0x80,0x00,0xc9,0xff,0xb6,0x01,0x80,0x00,0xf8,0xff,0xcf,0x01,0x80,0x00,0xfd,0xff,0xcf,0x01,0x80,0x00,0xff,0xff,0xcf,0x01,0x80,0x01,0x00,0xff,0xcf,0x01,0x80,0x01,0x03,0xff,0xb6,0x01,0x80,0x01,0x04,0xff,0xb4,0x01,0x80,0x01,0x05,0xff,0xb6,0x01,0x80,0x01,0x06,0xff,0xb4,0x01,0x80, 0x01,0x08,0xff,0xcf,0x01,0x80,0x01,0x0b,0xff,0xcf,0x01,0x80,0x01,0x0d,0xff,0xcf,0x01,0x80,0x01,0x19,0xff,0xcf,0x01,0x80,0x01,0x20,0x00,0x27,0x01,0x80,0x01,0x22,0x00,0x27,0x01,0x80,0x01,0x45,0xff,0xb6,0x01,0x80,0x01,0x46,0xff,0xb4,0x01,0x80,0x01,0x48,0xff,0xcf,0x01,0x80,0x01,0x4c,0xff,0xcf,0x01,0x80,0x01,0x4e,0xff,0xcf, 0x01,0x80,0x01,0x50,0xff,0xcf,0x01,0x80,0x01,0x52,0xff,0xcf,0x01,0x80,0x01,0x54,0xff,0xcf,0x01,0x80,0x01,0x56,0xff,0xcf,0x01,0x80,0x01,0x5c,0x00,0x64,0x01,0x80,0x01,0x5e,0x00,0x64,0x01,0x80,0x01,0x60,0x00,0x64,0x01,0x80,0x01,0x6f,0xff,0xcf,0x01,0x80,0x01,0x71,0xff,0xcf,0x01,0x80,0x01,0x76,0x00,0x27,0x01,0x80,0x01,0x85, 0xff,0xb6,0x01,0x80,0x01,0x86,0xff,0xb4,0x01,0x80,0x01,0x87,0xff,0xb6,0x01,0x80,0x01,0x88,0xff,0xb4,0x01,0x80,0x01,0x8a,0xff,0xcf,0x01,0x81,0x00,0x0f,0xff,0xa6,0x01,0x81,0x00,0x11,0xff,0x9a,0x01,0x81,0x00,0x46,0xff,0xfa,0x01,0x81,0x00,0x47,0xff,0xf6,0x01,0x81,0x00,0x48,0xff,0xf6,0x01,0x81,0x00,0x4a,0xff,0xfa,0x01,0x81, 0x00,0x52,0xff,0xfa,0x01,0x81,0x00,0x54,0xff,0xf6,0x01,0x81,0x00,0x6f,0xff,0xfa,0x01,0x81,0x00,0x70,0xff,0xf6,0x01,0x81,0x00,0x71,0xff,0xf6,0x01,0x81,0x00,0x72,0xff,0xf6,0x01,0x81,0x00,0x73,0xff,0xf6,0x01,0x81,0x00,0x79,0xff,0xfa,0x01,0x81,0x00,0x7a,0xff,0xfa,0x01,0x81,0x00,0x7b,0xff,0xfa,0x01,0x81,0x00,0x7c,0xff,0xfa, 0x01,0x81,0x00,0x7d,0xff,0xfa,0x01,0x81,0x00,0xac,0xff,0x9a,0x01,0x81,0x00,0xb1,0xff,0xfa,0x01,0x81,0x00,0xc4,0xff,0xb4,0x01,0x81,0x00,0xc5,0xff,0xb4,0x01,0x81,0x00,0xf8,0xff,0xfa,0x01,0x81,0x00,0xfd,0xff,0xfa,0x01,0x81,0x00,0xff,0xff,0xfa,0x01,0x81,0x01,0x00,0xff,0xf6,0x01,0x81,0x01,0x08,0xff,0xf6,0x01,0x81,0x01,0x0b, 0xff,0xf6,0x01,0x81,0x01,0x0d,0xff,0xf6,0x01,0x81,0x01,0x19,0xff,0xfa,0x01,0x81,0x01,0x48,0xff,0xfa,0x01,0x81,0x01,0x4c,0xff,0xf6,0x01,0x81,0x01,0x4e,0xff,0xf6,0x01,0x81,0x01,0x50,0xff,0xf6,0x01,0x81,0x01,0x52,0xff,0xfa,0x01,0x81,0x01,0x54,0xff,0xfa,0x01,0x81,0x01,0x56,0xff,0xfa,0x01,0x81,0x01,0x6f,0xff,0xfa,0x01,0x81, 0x01,0x71,0xff,0xfa,0x01,0x81,0x01,0x8a,0xff,0xfa,0x01,0x82,0x00,0x0f,0xff,0x50,0x01,0x82,0x00,0x11,0xff,0x3d,0x01,0x82,0x00,0x24,0xff,0x62,0x01,0x82,0x00,0x26,0xff,0xd3,0x01,0x82,0x00,0x2a,0xff,0xd3,0x01,0x82,0x00,0x2d,0xff,0xbe,0x01,0x82,0x00,0x32,0xff,0xd3,0x01,0x82,0x00,0x34,0xff,0xd3,0x01,0x82,0x00,0x36,0xff,0xe5, 0x01,0x82,0x00,0x37,0x00,0x27,0x01,0x82,0x00,0x44,0xff,0x39,0x01,0x82,0x00,0x46,0xff,0x4c,0x01,0x82,0x00,0x47,0xff,0x4c,0x01,0x82,0x00,0x48,0xff,0x4c,0x01,0x82,0x00,0x49,0xff,0xe5,0x01,0x82,0x00,0x4a,0xff,0x4c,0x01,0x82,0x00,0x50,0xff,0x73,0x01,0x82,0x00,0x51,0xff,0x73,0x01,0x82,0x00,0x52,0xff,0x4c,0x01,0x82,0x00,0x53, 0xff,0x73,0x01,0x82,0x00,0x54,0xff,0x4c,0x01,0x82,0x00,0x55,0xff,0x73,0x01,0x82,0x00,0x56,0xff,0x7b,0x01,0x82,0x00,0x58,0xff,0x73,0x01,0x82,0x00,0x62,0xff,0x62,0x01,0x82,0x00,0x63,0xff,0x62,0x01,0x82,0x00,0x64,0xff,0xcd,0x01,0x82,0x00,0x67,0xff,0xd3,0x01,0x82,0x00,0x69,0xff,0x39,0x01,0x82,0x00,0x6a,0xff,0x39,0x01,0x82, 0x00,0x6b,0xff,0x39,0x01,0x82,0x00,0x6c,0xff,0x7f,0x01,0x82,0x00,0x6d,0xff,0x66,0x01,0x82,0x00,0x6e,0xff,0x39,0x01,0x82,0x00,0x6f,0xff,0x4c,0x01,0x82,0x00,0x70,0xff,0x4c,0x01,0x82,0x00,0x71,0xff,0x4c,0x01,0x82,0x00,0x72,0xff,0x4c,0x01,0x82,0x00,0x73,0xff,0x4c,0x01,0x82,0x00,0x77,0x00,0x5a,0x01,0x82,0x00,0x78,0xff,0x73, 0x01,0x82,0x00,0x79,0xff,0x4c,0x01,0x82,0x00,0x7a,0xff,0x4c,0x01,0x82,0x00,0x7b,0xff,0x4c,0x01,0x82,0x00,0x7c,0xff,0x4c,0x01,0x82,0x00,0x7d,0xff,0x4c,0x01,0x82,0x00,0x7e,0xff,0x73,0x01,0x82,0x00,0x7f,0xff,0x73,0x01,0x82,0x00,0x80,0xff,0x73,0x01,0x82,0x00,0x81,0xff,0x73,0x01,0x82,0x00,0x91,0xff,0x3f,0x01,0x82,0x00,0x92, 0xff,0xd3,0x01,0x82,0x00,0xa0,0xff,0x39,0x01,0x82,0x00,0xa2,0xff,0x1b,0x01,0x82,0x00,0xaa,0xff,0xcf,0x01,0x82,0x00,0xac,0xff,0x3d,0x01,0x82,0x00,0xad,0xff,0x62,0x01,0x82,0x00,0xae,0xff,0x62,0x01,0x82,0x00,0xaf,0xff,0xd3,0x01,0x82,0x00,0xb0,0xff,0xd3,0x01,0x82,0x00,0xb1,0xff,0x4c,0x01,0x82,0x00,0xbe,0xff,0x9a,0x01,0x82, 0x00,0xc4,0xff,0x08,0x01,0x82,0x00,0xc5,0xff,0x08,0x01,0x82,0x00,0xc7,0xff,0x62,0x01,0x82,0x00,0xc9,0xff,0x62,0x01,0x82,0x00,0xd0,0xff,0xd3,0x01,0x82,0x00,0xd1,0xff,0xd3,0x01,0x82,0x00,0xd2,0xff,0xd3,0x01,0x82,0x00,0xe3,0xff,0xe5,0x01,0x82,0x00,0xe4,0xff,0x7b,0x01,0x82,0x00,0xf7,0xff,0xd3,0x01,0x82,0x00,0xf8,0xff,0x4c, 0x01,0x82,0x00,0xfa,0xff,0xe5,0x01,0x82,0x00,0xfb,0xff,0x7b,0x01,0x82,0x00,0xfc,0xff,0xd3,0x01,0x82,0x00,0xfd,0xff,0x4c,0x01,0x82,0x00,0xfe,0xff,0xd3,0x01,0x82,0x00,0xff,0xff,0x4c,0x01,0x82,0x01,0x00,0xff,0x4c,0x01,0x82,0x01,0x03,0xff,0x62,0x01,0x82,0x01,0x04,0xff,0x7f,0x01,0x82,0x01,0x05,0xff,0x62,0x01,0x82,0x01,0x06, 0xff,0x39,0x01,0x82,0x01,0x08,0xff,0x4c,0x01,0x82,0x01,0x0b,0xff,0x4c,0x01,0x82,0x01,0x0d,0xff,0x4c,0x01,0x82,0x01,0x15,0xff,0x73,0x01,0x82,0x01,0x17,0xff,0x73,0x01,0x82,0x01,0x18,0xff,0xd3,0x01,0x82,0x01,0x19,0xff,0x4c,0x01,0x82,0x01,0x1b,0xff,0x73,0x01,0x82,0x01,0x1d,0xff,0x73,0x01,0x82,0x01,0x1e,0xff,0xe5,0x01,0x82, 0x01,0x1f,0xff,0x7b,0x01,0x82,0x01,0x20,0x00,0x27,0x01,0x82,0x01,0x22,0x00,0x27,0x01,0x82,0x01,0x25,0xff,0x73,0x01,0x82,0x01,0x27,0xff,0x73,0x01,0x82,0x01,0x45,0xff,0x62,0x01,0x82,0x01,0x46,0xff,0x7f,0x01,0x82,0x01,0x47,0xff,0xd3,0x01,0x82,0x01,0x48,0xff,0x4c,0x01,0x82,0x01,0x4c,0xff,0x4c,0x01,0x82,0x01,0x4e,0xff,0x4c, 0x01,0x82,0x01,0x50,0xff,0x4c,0x01,0x82,0x01,0x51,0xff,0xd3,0x01,0x82,0x01,0x52,0xff,0x4c,0x01,0x82,0x01,0x53,0xff,0xd3,0x01,0x82,0x01,0x54,0xff,0x4c,0x01,0x82,0x01,0x55,0xff,0xd3,0x01,0x82,0x01,0x56,0xff,0x4c,0x01,0x82,0x01,0x5c,0x00,0x5a,0x01,0x82,0x01,0x5e,0x00,0x5a,0x01,0x82,0x01,0x60,0x00,0x5a,0x01,0x82,0x01,0x63, 0xff,0xbe,0x01,0x82,0x01,0x6d,0xff,0x73,0x01,0x82,0x01,0x6e,0xff,0xd3,0x01,0x82,0x01,0x6f,0xff,0x4c,0x01,0x82,0x01,0x70,0xff,0xd3,0x01,0x82,0x01,0x71,0xff,0x4c,0x01,0x82,0x01,0x73,0xff,0x73,0x01,0x82,0x01,0x74,0xff,0xe5,0x01,0x82,0x01,0x75,0xff,0x7b,0x01,0x82,0x01,0x76,0x00,0x27,0x01,0x82,0x01,0x79,0xff,0x73,0x01,0x82, 0x01,0x7b,0xff,0x73,0x01,0x82,0x01,0x7d,0xff,0x73,0x01,0x82,0x01,0x7f,0xff,0x73,0x01,0x82,0x01,0x85,0xff,0x62,0x01,0x82,0x01,0x86,0xff,0x7f,0x01,0x82,0x01,0x87,0xff,0x62,0x01,0x82,0x01,0x88,0xff,0x39,0x01,0x82,0x01,0x89,0xff,0xd3,0x01,0x82,0x01,0x8a,0xff,0x4c,0x01,0x82,0x02,0x3d,0xff,0xe5,0x01,0x82,0x02,0x3e,0xff,0x7b, 0x01,0x83,0x00,0x05,0x00,0x1d,0x01,0x83,0x00,0x0a,0x00,0x1d,0x01,0x83,0x00,0x0f,0xff,0x9a,0x01,0x83,0x00,0x11,0xff,0x81,0x01,0x83,0x00,0x22,0xff,0xb4,0x01,0x83,0x00,0x46,0xff,0xf6,0x01,0x83,0x00,0x47,0xff,0xf6,0x01,0x83,0x00,0x48,0xff,0xf6,0x01,0x83,0x00,0x49,0x00,0x04,0x01,0x83,0x00,0x4a,0xff,0xf6,0x01,0x83,0x00,0x52, 0xff,0xf6,0x01,0x83,0x00,0x54,0xff,0xf6,0x01,0x83,0x00,0x57,0x00,0x06,0x01,0x83,0x00,0x6f,0xff,0xf6,0x01,0x83,0x00,0x70,0xff,0xf6,0x01,0x83,0x00,0x71,0xff,0xf6,0x01,0x83,0x00,0x72,0xff,0xf6,0x01,0x83,0x00,0x73,0xff,0xf6,0x01,0x83,0x00,0x79,0xff,0xf6,0x01,0x83,0x00,0x7a,0xff,0xf6,0x01,0x83,0x00,0x7b,0xff,0xf6,0x01,0x83, 0x00,0x7c,0xff,0xf6,0x01,0x83,0x00,0x7d,0xff,0xf6,0x01,0x83,0x00,0xac,0xff,0x81,0x01,0x83,0x00,0xb1,0xff,0xf6,0x01,0x83,0x00,0xbf,0x00,0x0c,0x01,0x83,0x00,0xc4,0xff,0x8d,0x01,0x83,0x00,0xc5,0xff,0x8d,0x01,0x83,0x00,0xf8,0xff,0xf6,0x01,0x83,0x00,0xfd,0xff,0xf6,0x01,0x83,0x00,0xff,0xff,0xf6,0x01,0x83,0x01,0x00,0xff,0xf6, 0x01,0x83,0x01,0x08,0xff,0xf6,0x01,0x83,0x01,0x0b,0xff,0xf6,0x01,0x83,0x01,0x0d,0xff,0xf6,0x01,0x83,0x01,0x19,0xff,0xf6,0x01,0x83,0x01,0x21,0x00,0x06,0x01,0x83,0x01,0x23,0x00,0x06,0x01,0x83,0x01,0x48,0xff,0xf6,0x01,0x83,0x01,0x4c,0xff,0xf6,0x01,0x83,0x01,0x4e,0xff,0xf6,0x01,0x83,0x01,0x50,0xff,0xf6,0x01,0x83,0x01,0x52, 0xff,0xf6,0x01,0x83,0x01,0x54,0xff,0xf6,0x01,0x83,0x01,0x56,0xff,0xf6,0x01,0x83,0x01,0x6f,0xff,0xf6,0x01,0x83,0x01,0x71,0xff,0xf6,0x01,0x83,0x01,0x77,0x00,0x06,0x01,0x83,0x01,0x8a,0xff,0xf6,0x01,0x84,0x00,0x0c,0x00,0x8d,0x01,0x84,0x00,0x0f,0xff,0x7f,0x01,0x84,0x00,0x10,0xff,0x9a,0x01,0x84,0x00,0x11,0xff,0x7f,0x01,0x84, 0x00,0x1d,0x00,0x52,0x01,0x84,0x00,0x1e,0x00,0x52,0x01,0x84,0x00,0x22,0x00,0x42,0x01,0x84,0x00,0x40,0x00,0x8d,0x01,0x84,0x00,0x45,0x00,0x12,0x01,0x84,0x00,0x4b,0x00,0x12,0x01,0x84,0x00,0x57,0x00,0x25,0x01,0x84,0x00,0x59,0x00,0x27,0x01,0x84,0x00,0x5a,0x00,0x27,0x01,0x84,0x00,0x5b,0x00,0x12,0x01,0x84,0x00,0x5c,0x00,0x21, 0x01,0x84,0x00,0x60,0x00,0x52,0x01,0x84,0x00,0x75,0x00,0x2d,0x01,0x84,0x00,0x76,0x00,0x12,0x01,0x84,0x00,0x77,0x00,0x79,0x01,0x84,0x00,0x8d,0x00,0x93,0x01,0x84,0x00,0xab,0x00,0x27,0x01,0x84,0x00,0xac,0xff,0x7f,0x01,0x84,0x00,0xb4,0x00,0x5e,0x01,0x84,0x00,0xb5,0x00,0x52,0x01,0x84,0x00,0xb6,0x00,0x5e,0x01,0x84,0x00,0xb7, 0x00,0x52,0x01,0x84,0x00,0xbf,0x00,0x27,0x01,0x84,0x00,0xc4,0xff,0xb0,0x01,0x84,0x00,0xc5,0xff,0xb0,0x01,0x84,0x00,0xeb,0x00,0x21,0x01,0x84,0x00,0xed,0x00,0x12,0x01,0x84,0x01,0x21,0x00,0x25,0x01,0x84,0x01,0x23,0x00,0x25,0x01,0x84,0x01,0x58,0x00,0x12,0x01,0x84,0x01,0x5a,0x00,0x12,0x01,0x84,0x01,0x5c,0x00,0x79,0x01,0x84, 0x01,0x5e,0x00,0x79,0x01,0x84,0x01,0x60,0x00,0x79,0x01,0x84,0x01,0x77,0x00,0x25,0x01,0x84,0x01,0x81,0x00,0x27,0x01,0x84,0x01,0x83,0x00,0x21,0x01,0x84,0x01,0x8d,0x00,0x27,0x01,0x84,0x01,0x8f,0x00,0x27,0x01,0x84,0x01,0x91,0x00,0x27,0x01,0x84,0x01,0x93,0x00,0x21,0x01,0x85,0x00,0x0d,0xff,0x7f,0x01,0x85,0x00,0x0f,0x00,0x44, 0x01,0x85,0x00,0x1e,0x00,0x44,0x01,0x85,0x00,0x26,0xff,0xe5,0x01,0x85,0x00,0x2a,0xff,0xe5,0x01,0x85,0x00,0x2d,0x00,0x5e,0x01,0x85,0x00,0x32,0xff,0xe5,0x01,0x85,0x00,0x37,0xff,0x6d,0x01,0x85,0x00,0x38,0xff,0xe5,0x01,0x85,0x00,0x39,0xff,0x8b,0x01,0x85,0x00,0x3a,0xff,0xb6,0x01,0x85,0x00,0x3c,0xff,0x64,0x01,0x85,0x00,0x3d, 0x00,0x3b,0x01,0x85,0x00,0x57,0xff,0xe5,0x01,0x85,0x00,0x59,0xff,0xd5,0x01,0x85,0x00,0x5a,0xff,0xe5,0x01,0x85,0x00,0x5c,0xff,0xdb,0x01,0x85,0x00,0x8d,0xff,0x9a,0x01,0x85,0x00,0xb4,0xff,0x66,0x01,0x85,0x00,0xb5,0xff,0x3f,0x01,0x85,0x00,0xb6,0xff,0x66,0x01,0x85,0x00,0xb7,0xff,0x3f,0x01,0x85,0x00,0xba,0xff,0xc1,0x01,0x85, 0x00,0xbb,0xff,0x64,0x01,0x85,0x00,0xe5,0x00,0x3b,0x01,0x85,0x00,0xea,0xff,0x64,0x01,0x85,0x00,0xeb,0xff,0xdb,0x01,0x85,0x00,0xf7,0xff,0xe5,0x01,0x85,0x00,0xfc,0xff,0xe5,0x01,0x85,0x00,0xfe,0xff,0xe5,0x01,0x85,0x01,0x18,0xff,0xe5,0x01,0x85,0x01,0x20,0xff,0x6d,0x01,0x85,0x01,0x21,0xff,0xe5,0x01,0x85,0x01,0x22,0xff,0x6d, 0x01,0x85,0x01,0x23,0xff,0xe5,0x01,0x85,0x01,0x24,0xff,0xe5,0x01,0x85,0x01,0x26,0xff,0xe5,0x01,0x85,0x01,0x28,0x00,0x3b,0x01,0x85,0x01,0x2a,0x00,0x3b,0x01,0x85,0x01,0x47,0xff,0xe5,0x01,0x85,0x01,0x51,0xff,0xe5,0x01,0x85,0x01,0x53,0xff,0xe5,0x01,0x85,0x01,0x55,0xff,0xe5,0x01,0x85,0x01,0x63,0x00,0x5e,0x01,0x85,0x01,0x6e, 0xff,0xe5,0x01,0x85,0x01,0x70,0xff,0xe5,0x01,0x85,0x01,0x76,0xff,0x6d,0x01,0x85,0x01,0x77,0xff,0xe5,0x01,0x85,0x01,0x78,0xff,0xe5,0x01,0x85,0x01,0x7a,0xff,0xe5,0x01,0x85,0x01,0x7c,0xff,0xe5,0x01,0x85,0x01,0x7e,0xff,0xe5,0x01,0x85,0x01,0x80,0xff,0xb6,0x01,0x85,0x01,0x81,0xff,0xe5,0x01,0x85,0x01,0x82,0xff,0x64,0x01,0x85, 0x01,0x83,0xff,0xdb,0x01,0x85,0x01,0x89,0xff,0xe5,0x01,0x85,0x01,0x8c,0xff,0xb6,0x01,0x85,0x01,0x8d,0xff,0xe5,0x01,0x85,0x01,0x8e,0xff,0xb6,0x01,0x85,0x01,0x8f,0xff,0xe5,0x01,0x85,0x01,0x90,0xff,0xb6,0x01,0x85,0x01,0x91,0xff,0xe5,0x01,0x85,0x01,0x92,0xff,0x64,0x01,0x85,0x01,0x93,0xff,0xdb,0x01,0x87,0x00,0x24,0x00,0x0a, 0x01,0x87,0x00,0x2d,0x00,0x44,0x01,0x87,0x00,0x37,0x00,0x04,0x01,0x87,0x00,0x3a,0x00,0x1d,0x01,0x87,0x00,0x3b,0x00,0x08,0x01,0x87,0x00,0x62,0x00,0x0a,0x01,0x87,0x00,0x63,0x00,0x0a,0x01,0x87,0x00,0x77,0x00,0x12,0x01,0x87,0x00,0xad,0x00,0x0a,0x01,0x87,0x00,0xae,0x00,0x0a,0x01,0x87,0x00,0xc7,0x00,0x0a,0x01,0x87,0x00,0xc9, 0x00,0x0a,0x01,0x87,0x01,0x03,0x00,0x0a,0x01,0x87,0x01,0x05,0x00,0x0a,0x01,0x87,0x01,0x20,0x00,0x04,0x01,0x87,0x01,0x22,0x00,0x04,0x01,0x87,0x01,0x45,0x00,0x0a,0x01,0x87,0x01,0x5c,0x00,0x12,0x01,0x87,0x01,0x5e,0x00,0x12,0x01,0x87,0x01,0x60,0x00,0x12,0x01,0x87,0x01,0x63,0x00,0x44,0x01,0x87,0x01,0x76,0x00,0x04,0x01,0x87, 0x01,0x80,0x00,0x1d,0x01,0x87,0x01,0x85,0x00,0x0a,0x01,0x87,0x01,0x87,0x00,0x0a,0x01,0x87,0x01,0x8c,0x00,0x1d,0x01,0x87,0x01,0x8e,0x00,0x1d,0x01,0x87,0x01,0x90,0x00,0x1d,0x01,0x88,0x00,0x05,0xff,0x98,0x01,0x88,0x00,0x0a,0xff,0x98,0x01,0x89,0x00,0x0f,0xff,0xa4,0x01,0x89,0x00,0x11,0xff,0xa4,0x01,0x89,0x00,0x24,0xff,0xe5, 0x01,0x89,0x00,0x2d,0xff,0xf6,0x01,0x89,0x00,0x37,0xff,0xa4,0x01,0x89,0x00,0x3b,0xff,0xdb,0x01,0x89,0x00,0x3c,0xff,0xe7,0x01,0x89,0x00,0x3d,0xff,0xcf,0x01,0x89,0x00,0x62,0xff,0xe5,0x01,0x89,0x00,0x63,0xff,0xe5,0x01,0x89,0x00,0xac,0xff,0xa4,0x01,0x89,0x00,0xad,0xff,0xe5,0x01,0x89,0x00,0xae,0xff,0xe5,0x01,0x89,0x00,0xbb, 0xff,0xf6,0x01,0x89,0x00,0xc4,0xff,0x4c,0x01,0x89,0x00,0xc5,0xff,0x98,0x01,0x89,0x00,0xc7,0xff,0xe5,0x01,0x89,0x00,0xc9,0xff,0xe5,0x01,0x89,0x00,0xe5,0xff,0xcf,0x01,0x89,0x00,0xea,0xff,0xe7,0x01,0x89,0x01,0x03,0xff,0xe5,0x01,0x89,0x01,0x05,0xff,0xe5,0x01,0x89,0x01,0x20,0xff,0xa4,0x01,0x89,0x01,0x22,0xff,0xa4,0x01,0x89, 0x01,0x28,0xff,0xcf,0x01,0x89,0x01,0x2a,0xff,0xcf,0x01,0x89,0x01,0x45,0xff,0xe5,0x01,0x89,0x01,0x63,0xff,0xf6,0x01,0x89,0x01,0x76,0xff,0xa4,0x01,0x89,0x01,0x82,0xff,0xe7,0x01,0x89,0x01,0x85,0xff,0xe5,0x01,0x89,0x01,0x87,0xff,0xe5,0x01,0x89,0x01,0x92,0xff,0xe7,0x01,0x8a,0x00,0x05,0xff,0x6f,0x01,0x8a,0x00,0x0a,0xff,0x6f, 0x01,0x8a,0x00,0x44,0xff,0xe5,0x01,0x8a,0x00,0x49,0xff,0xdb,0x01,0x8a,0x00,0x5b,0xff,0xe7,0x01,0x8a,0x00,0x69,0xff,0xe5,0x01,0x8a,0x00,0x6a,0xff,0xe5,0x01,0x8a,0x00,0x6b,0xff,0xe5,0x01,0x8a,0x00,0x6c,0xff,0xe5,0x01,0x8a,0x00,0x6d,0xff,0xe5,0x01,0x8a,0x00,0x6e,0xff,0xe5,0x01,0x8a,0x00,0xa0,0xff,0xe5,0x01,0x8a,0x00,0xb4, 0xff,0xb2,0x01,0x8a,0x00,0xb5,0xff,0x7d,0x01,0x8a,0x00,0xb6,0xff,0xbe,0x01,0x8a,0x00,0xb7,0xff,0x7d,0x01,0x8a,0x00,0xc0,0xff,0xe7,0x01,0x8a,0x00,0xc1,0xff,0xe7,0x01,0x8a,0x01,0x04,0xff,0xe5,0x01,0x8a,0x01,0x06,0xff,0xe5,0x01,0x8a,0x01,0x46,0xff,0xe5,0x01,0x8a,0x01,0x86,0xff,0xe5,0x01,0x8a,0x01,0x88,0xff,0xe5,0x01,0x8c, 0x00,0x0f,0xff,0x8b,0x01,0x8c,0x00,0x11,0xff,0x7f,0x01,0x8c,0x00,0x24,0xff,0xb6,0x01,0x8c,0x00,0x37,0x00,0x27,0x01,0x8c,0x00,0x44,0xff,0xb4,0x01,0x8c,0x00,0x46,0xff,0xcf,0x01,0x8c,0x00,0x47,0xff,0xcf,0x01,0x8c,0x00,0x48,0xff,0xcf,0x01,0x8c,0x00,0x4a,0xff,0xcf,0x01,0x8c,0x00,0x52,0xff,0xcf,0x01,0x8c,0x00,0x54,0xff,0xcf, 0x01,0x8c,0x00,0x62,0xff,0xb6,0x01,0x8c,0x00,0x63,0xff,0xb6,0x01,0x8c,0x00,0x69,0xff,0xb4,0x01,0x8c,0x00,0x6a,0xff,0xb4,0x01,0x8c,0x00,0x6b,0xff,0xb4,0x01,0x8c,0x00,0x6c,0xff,0xb4,0x01,0x8c,0x00,0x6d,0xff,0xb4,0x01,0x8c,0x00,0x6e,0xff,0xb4,0x01,0x8c,0x00,0x6f,0xff,0xcf,0x01,0x8c,0x00,0x70,0xff,0xcf,0x01,0x8c,0x00,0x71, 0xff,0xcf,0x01,0x8c,0x00,0x72,0xff,0xcf,0x01,0x8c,0x00,0x73,0xff,0xcf,0x01,0x8c,0x00,0x76,0x00,0x31,0x01,0x8c,0x00,0x77,0x00,0x64,0x01,0x8c,0x00,0x79,0xff,0xcf,0x01,0x8c,0x00,0x7a,0xff,0xcf,0x01,0x8c,0x00,0x7b,0xff,0xcf,0x01,0x8c,0x00,0x7c,0xff,0xcf,0x01,0x8c,0x00,0x7d,0xff,0xcf,0x01,0x8c,0x00,0x91,0xff,0x9a,0x01,0x8c, 0x00,0xa0,0xff,0xb4,0x01,0x8c,0x00,0xa2,0xff,0xa4,0x01,0x8c,0x00,0xaa,0xff,0xcf,0x01,0x8c,0x00,0xab,0x00,0x27,0x01,0x8c,0x00,0xac,0xff,0x7f,0x01,0x8c,0x00,0xad,0xff,0xb6,0x01,0x8c,0x00,0xae,0xff,0xb6,0x01,0x8c,0x00,0xb1,0xff,0xcf,0x01,0x8c,0x00,0xbe,0xff,0xcf,0x01,0x8c,0x00,0xbf,0x00,0x27,0x01,0x8c,0x00,0xc4,0xff,0x7f, 0x01,0x8c,0x00,0xc5,0xff,0x8b,0x01,0x8c,0x00,0xc7,0xff,0xb6,0x01,0x8c,0x00,0xc9,0xff,0xb6,0x01,0x8c,0x00,0xf8,0xff,0xcf,0x01,0x8c,0x00,0xfd,0xff,0xcf,0x01,0x8c,0x00,0xff,0xff,0xcf,0x01,0x8c,0x01,0x00,0xff,0xcf,0x01,0x8c,0x01,0x03,0xff,0xb6,0x01,0x8c,0x01,0x04,0xff,0xb4,0x01,0x8c,0x01,0x05,0xff,0xb6,0x01,0x8c,0x01,0x06, 0xff,0xb4,0x01,0x8c,0x01,0x08,0xff,0xcf,0x01,0x8c,0x01,0x0b,0xff,0xcf,0x01,0x8c,0x01,0x0d,0xff,0xcf,0x01,0x8c,0x01,0x19,0xff,0xcf,0x01,0x8c,0x01,0x20,0x00,0x27,0x01,0x8c,0x01,0x22,0x00,0x27,0x01,0x8c,0x01,0x45,0xff,0xb6,0x01,0x8c,0x01,0x46,0xff,0xb4,0x01,0x8c,0x01,0x48,0xff,0xcf,0x01,0x8c,0x01,0x4c,0xff,0xcf,0x01,0x8c, 0x01,0x4e,0xff,0xcf,0x01,0x8c,0x01,0x50,0xff,0xcf,0x01,0x8c,0x01,0x52,0xff,0xcf,0x01,0x8c,0x01,0x54,0xff,0xcf,0x01,0x8c,0x01,0x56,0xff,0xcf,0x01,0x8c,0x01,0x5c,0x00,0x64,0x01,0x8c,0x01,0x5e,0x00,0x64,0x01,0x8c,0x01,0x60,0x00,0x64,0x01,0x8c,0x01,0x6f,0xff,0xcf,0x01,0x8c,0x01,0x71,0xff,0xcf,0x01,0x8c,0x01,0x76,0x00,0x27, 0x01,0x8c,0x01,0x85,0xff,0xb6,0x01,0x8c,0x01,0x86,0xff,0xb4,0x01,0x8c,0x01,0x87,0xff,0xb6,0x01,0x8c,0x01,0x88,0xff,0xb4,0x01,0x8c,0x01,0x8a,0xff,0xcf,0x01,0x8d,0x00,0x0f,0xff,0xa6,0x01,0x8d,0x00,0x11,0xff,0x9a,0x01,0x8d,0x00,0x46,0xff,0xfa,0x01,0x8d,0x00,0x47,0xff,0xf6,0x01,0x8d,0x00,0x48,0xff,0xf6,0x01,0x8d,0x00,0x4a, 0xff,0xfa,0x01,0x8d,0x00,0x52,0xff,0xfa,0x01,0x8d,0x00,0x54,0xff,0xf6,0x01,0x8d,0x00,0x6f,0xff,0xfa,0x01,0x8d,0x00,0x70,0xff,0xf6,0x01,0x8d,0x00,0x71,0xff,0xf6,0x01,0x8d,0x00,0x72,0xff,0xf6,0x01,0x8d,0x00,0x73,0xff,0xf6,0x01,0x8d,0x00,0x79,0xff,0xfa,0x01,0x8d,0x00,0x7a,0xff,0xfa,0x01,0x8d,0x00,0x7b,0xff,0xfa,0x01,0x8d, 0x00,0x7c,0xff,0xfa,0x01,0x8d,0x00,0x7d,0xff,0xfa,0x01,0x8d,0x00,0xac,0xff,0x9a,0x01,0x8d,0x00,0xb1,0xff,0xfa,0x01,0x8d,0x00,0xc4,0xff,0xb4,0x01,0x8d,0x00,0xc5,0xff,0xb4,0x01,0x8d,0x00,0xf8,0xff,0xfa,0x01,0x8d,0x00,0xfd,0xff,0xfa,0x01,0x8d,0x00,0xff,0xff,0xfa,0x01,0x8d,0x01,0x00,0xff,0xf6,0x01,0x8d,0x01,0x08,0xff,0xf6, 0x01,0x8d,0x01,0x0b,0xff,0xf6,0x01,0x8d,0x01,0x0d,0xff,0xf6,0x01,0x8d,0x01,0x19,0xff,0xfa,0x01,0x8d,0x01,0x48,0xff,0xfa,0x01,0x8d,0x01,0x4c,0xff,0xf6,0x01,0x8d,0x01,0x4e,0xff,0xf6,0x01,0x8d,0x01,0x50,0xff,0xf6,0x01,0x8d,0x01,0x52,0xff,0xfa,0x01,0x8d,0x01,0x54,0xff,0xfa,0x01,0x8d,0x01,0x56,0xff,0xfa,0x01,0x8d,0x01,0x6f, 0xff,0xfa,0x01,0x8d,0x01,0x71,0xff,0xfa,0x01,0x8d,0x01,0x8a,0xff,0xfa,0x01,0x8e,0x00,0x0f,0xff,0x8b,0x01,0x8e,0x00,0x11,0xff,0x7f,0x01,0x8e,0x00,0x24,0xff,0xb6,0x01,0x8e,0x00,0x37,0x00,0x27,0x01,0x8e,0x00,0x44,0xff,0xb4,0x01,0x8e,0x00,0x46,0xff,0xcf,0x01,0x8e,0x00,0x47,0xff,0xcf,0x01,0x8e,0x00,0x48,0xff,0xcf,0x01,0x8e, 0x00,0x4a,0xff,0xcf,0x01,0x8e,0x00,0x52,0xff,0xcf,0x01,0x8e,0x00,0x54,0xff,0xcf,0x01,0x8e,0x00,0x62,0xff,0xb6,0x01,0x8e,0x00,0x63,0xff,0xb6,0x01,0x8e,0x00,0x69,0xff,0xb4,0x01,0x8e,0x00,0x6a,0xff,0xb4,0x01,0x8e,0x00,0x6b,0xff,0xb4,0x01,0x8e,0x00,0x6c,0xff,0xb4,0x01,0x8e,0x00,0x6d,0xff,0xb4,0x01,0x8e,0x00,0x6e,0xff,0xb4, 0x01,0x8e,0x00,0x6f,0xff,0xcf,0x01,0x8e,0x00,0x70,0xff,0xcf,0x01,0x8e,0x00,0x71,0xff,0xcf,0x01,0x8e,0x00,0x72,0xff,0xcf,0x01,0x8e,0x00,0x73,0xff,0xcf,0x01,0x8e,0x00,0x76,0x00,0x31,0x01,0x8e,0x00,0x77,0x00,0x64,0x01,0x8e,0x00,0x79,0xff,0xcf,0x01,0x8e,0x00,0x7a,0xff,0xcf,0x01,0x8e,0x00,0x7b,0xff,0xcf,0x01,0x8e,0x00,0x7c, 0xff,0xcf,0x01,0x8e,0x00,0x7d,0xff,0xcf,0x01,0x8e,0x00,0x91,0xff,0x9a,0x01,0x8e,0x00,0xa0,0xff,0xb4,0x01,0x8e,0x00,0xa2,0xff,0xa4,0x01,0x8e,0x00,0xaa,0xff,0xcf,0x01,0x8e,0x00,0xab,0x00,0x27,0x01,0x8e,0x00,0xac,0xff,0x7f,0x01,0x8e,0x00,0xad,0xff,0xb6,0x01,0x8e,0x00,0xae,0xff,0xb6,0x01,0x8e,0x00,0xb1,0xff,0xcf,0x01,0x8e, 0x00,0xbe,0xff,0xcf,0x01,0x8e,0x00,0xbf,0x00,0x27,0x01,0x8e,0x00,0xc4,0xff,0x7f,0x01,0x8e,0x00,0xc5,0xff,0x8b,0x01,0x8e,0x00,0xc7,0xff,0xb6,0x01,0x8e,0x00,0xc9,0xff,0xb6,0x01,0x8e,0x00,0xf8,0xff,0xcf,0x01,0x8e,0x00,0xfd,0xff,0xcf,0x01,0x8e,0x00,0xff,0xff,0xcf,0x01,0x8e,0x01,0x00,0xff,0xcf,0x01,0x8e,0x01,0x03,0xff,0xb6, 0x01,0x8e,0x01,0x04,0xff,0xb4,0x01,0x8e,0x01,0x05,0xff,0xb6,0x01,0x8e,0x01,0x06,0xff,0xb4,0x01,0x8e,0x01,0x08,0xff,0xcf,0x01,0x8e,0x01,0x0b,0xff,0xcf,0x01,0x8e,0x01,0x0d,0xff,0xcf,0x01,0x8e,0x01,0x19,0xff,0xcf,0x01,0x8e,0x01,0x20,0x00,0x27,0x01,0x8e,0x01,0x22,0x00,0x27,0x01,0x8e,0x01,0x45,0xff,0xb6,0x01,0x8e,0x01,0x46, 0xff,0xb4,0x01,0x8e,0x01,0x48,0xff,0xcf,0x01,0x8e,0x01,0x4c,0xff,0xcf,0x01,0x8e,0x01,0x4e,0xff,0xcf,0x01,0x8e,0x01,0x50,0xff,0xcf,0x01,0x8e,0x01,0x52,0xff,0xcf,0x01,0x8e,0x01,0x54,0xff,0xcf,0x01,0x8e,0x01,0x56,0xff,0xcf,0x01,0x8e,0x01,0x5c,0x00,0x64,0x01,0x8e,0x01,0x5e,0x00,0x64,0x01,0x8e,0x01,0x60,0x00,0x64,0x01,0x8e, 0x01,0x6f,0xff,0xcf,0x01,0x8e,0x01,0x71,0xff,0xcf,0x01,0x8e,0x01,0x76,0x00,0x27,0x01,0x8e,0x01,0x85,0xff,0xb6,0x01,0x8e,0x01,0x86,0xff,0xb4,0x01,0x8e,0x01,0x87,0xff,0xb6,0x01,0x8e,0x01,0x88,0xff,0xb4,0x01,0x8e,0x01,0x8a,0xff,0xcf,0x01,0x8f,0x00,0x0f,0xff,0xa6,0x01,0x8f,0x00,0x11,0xff,0x9a,0x01,0x8f,0x00,0x46,0xff,0xfa, 0x01,0x8f,0x00,0x47,0xff,0xf6,0x01,0x8f,0x00,0x48,0xff,0xf6,0x01,0x8f,0x00,0x4a,0xff,0xfa,0x01,0x8f,0x00,0x52,0xff,0xfa,0x01,0x8f,0x00,0x54,0xff,0xf6,0x01,0x8f,0x00,0x6f,0xff,0xfa,0x01,0x8f,0x00,0x70,0xff,0xf6,0x01,0x8f,0x00,0x71,0xff,0xf6,0x01,0x8f,0x00,0x72,0xff,0xf6,0x01,0x8f,0x00,0x73,0xff,0xf6,0x01,0x8f,0x00,0x79, 0xff,0xfa,0x01,0x8f,0x00,0x7a,0xff,0xfa,0x01,0x8f,0x00,0x7b,0xff,0xfa,0x01,0x8f,0x00,0x7c,0xff,0xfa,0x01,0x8f,0x00,0x7d,0xff,0xfa,0x01,0x8f,0x00,0xac,0xff,0x9a,0x01,0x8f,0x00,0xb1,0xff,0xfa,0x01,0x8f,0x00,0xc4,0xff,0xb4,0x01,0x8f,0x00,0xc5,0xff,0xb4,0x01,0x8f,0x00,0xf8,0xff,0xfa,0x01,0x8f,0x00,0xfd,0xff,0xfa,0x01,0x8f, 0x00,0xff,0xff,0xfa,0x01,0x8f,0x01,0x00,0xff,0xf6,0x01,0x8f,0x01,0x08,0xff,0xf6,0x01,0x8f,0x01,0x0b,0xff,0xf6,0x01,0x8f,0x01,0x0d,0xff,0xf6,0x01,0x8f,0x01,0x19,0xff,0xfa,0x01,0x8f,0x01,0x48,0xff,0xfa,0x01,0x8f,0x01,0x4c,0xff,0xf6,0x01,0x8f,0x01,0x4e,0xff,0xf6,0x01,0x8f,0x01,0x50,0xff,0xf6,0x01,0x8f,0x01,0x52,0xff,0xfa, 0x01,0x8f,0x01,0x54,0xff,0xfa,0x01,0x8f,0x01,0x56,0xff,0xfa,0x01,0x8f,0x01,0x6f,0xff,0xfa,0x01,0x8f,0x01,0x71,0xff,0xfa,0x01,0x8f,0x01,0x8a,0xff,0xfa,0x01,0x90,0x00,0x0f,0xff,0x8b,0x01,0x90,0x00,0x11,0xff,0x7f,0x01,0x90,0x00,0x24,0xff,0xb6,0x01,0x90,0x00,0x37,0x00,0x27,0x01,0x90,0x00,0x44,0xff,0xb4,0x01,0x90,0x00,0x46, 0xff,0xcf,0x01,0x90,0x00,0x47,0xff,0xcf,0x01,0x90,0x00,0x48,0xff,0xcf,0x01,0x90,0x00,0x4a,0xff,0xcf,0x01,0x90,0x00,0x52,0xff,0xcf,0x01,0x90,0x00,0x54,0xff,0xcf,0x01,0x90,0x00,0x62,0xff,0xb6,0x01,0x90,0x00,0x63,0xff,0xb6,0x01,0x90,0x00,0x69,0xff,0xb4,0x01,0x90,0x00,0x6a,0xff,0xb4,0x01,0x90,0x00,0x6b,0xff,0xb4,0x01,0x90, 0x00,0x6c,0xff,0xb4,0x01,0x90,0x00,0x6d,0xff,0xb4,0x01,0x90,0x00,0x6e,0xff,0xb4,0x01,0x90,0x00,0x6f,0xff,0xcf,0x01,0x90,0x00,0x70,0xff,0xcf,0x01,0x90,0x00,0x71,0xff,0xcf,0x01,0x90,0x00,0x72,0xff,0xcf,0x01,0x90,0x00,0x73,0xff,0xcf,0x01,0x90,0x00,0x76,0x00,0x31,0x01,0x90,0x00,0x77,0x00,0x64,0x01,0x90,0x00,0x79,0xff,0xcf, 0x01,0x90,0x00,0x7a,0xff,0xcf,0x01,0x90,0x00,0x7b,0xff,0xcf,0x01,0x90,0x00,0x7c,0xff,0xcf,0x01,0x90,0x00,0x7d,0xff,0xcf,0x01,0x90,0x00,0x91,0xff,0x9a,0x01,0x90,0x00,0xa0,0xff,0xb4,0x01,0x90,0x00,0xa2,0xff,0xa4,0x01,0x90,0x00,0xaa,0xff,0xcf,0x01,0x90,0x00,0xab,0x00,0x27,0x01,0x90,0x00,0xac,0xff,0x7f,0x01,0x90,0x00,0xad, 0xff,0xb6,0x01,0x90,0x00,0xae,0xff,0xb6,0x01,0x90,0x00,0xb1,0xff,0xcf,0x01,0x90,0x00,0xbe,0xff,0xcf,0x01,0x90,0x00,0xbf,0x00,0x27,0x01,0x90,0x00,0xc4,0xff,0x7f,0x01,0x90,0x00,0xc5,0xff,0x8b,0x01,0x90,0x00,0xc7,0xff,0xb6,0x01,0x90,0x00,0xc9,0xff,0xb6,0x01,0x90,0x00,0xf8,0xff,0xcf,0x01,0x90,0x00,0xfd,0xff,0xcf,0x01,0x90, 0x00,0xff,0xff,0xcf,0x01,0x90,0x01,0x00,0xff,0xcf,0x01,0x90,0x01,0x03,0xff,0xb6,0x01,0x90,0x01,0x04,0xff,0xb4,0x01,0x90,0x01,0x05,0xff,0xb6,0x01,0x90,0x01,0x06,0xff,0xb4,0x01,0x90,0x01,0x08,0xff,0xcf,0x01,0x90,0x01,0x0b,0xff,0xcf,0x01,0x90,0x01,0x0d,0xff,0xcf,0x01,0x90,0x01,0x19,0xff,0xcf,0x01,0x90,0x01,0x20,0x00,0x27, 0x01,0x90,0x01,0x22,0x00,0x27,0x01,0x90,0x01,0x45,0xff,0xb6,0x01,0x90,0x01,0x46,0xff,0xb4,0x01,0x90,0x01,0x48,0xff,0xcf,0x01,0x90,0x01,0x4c,0xff,0xcf,0x01,0x90,0x01,0x4e,0xff,0xcf,0x01,0x90,0x01,0x50,0xff,0xcf,0x01,0x90,0x01,0x52,0xff,0xcf,0x01,0x90,0x01,0x54,0xff,0xcf,0x01,0x90,0x01,0x56,0xff,0xcf,0x01,0x90,0x01,0x5c, 0x00,0x64,0x01,0x90,0x01,0x5e,0x00,0x64,0x01,0x90,0x01,0x60,0x00,0x64,0x01,0x90,0x01,0x6f,0xff,0xcf,0x01,0x90,0x01,0x71,0xff,0xcf,0x01,0x90,0x01,0x76,0x00,0x27,0x01,0x90,0x01,0x85,0xff,0xb6,0x01,0x90,0x01,0x86,0xff,0xb4,0x01,0x90,0x01,0x87,0xff,0xb6,0x01,0x90,0x01,0x88,0xff,0xb4,0x01,0x90,0x01,0x8a,0xff,0xcf,0x01,0x91, 0x00,0x0f,0xff,0xa6,0x01,0x91,0x00,0x11,0xff,0x9a,0x01,0x91,0x00,0x46,0xff,0xfa,0x01,0x91,0x00,0x47,0xff,0xf6,0x01,0x91,0x00,0x48,0xff,0xf6,0x01,0x91,0x00,0x4a,0xff,0xfa,0x01,0x91,0x00,0x52,0xff,0xfa,0x01,0x91,0x00,0x54,0xff,0xf6,0x01,0x91,0x00,0x6f,0xff,0xfa,0x01,0x91,0x00,0x70,0xff,0xf6,0x01,0x91,0x00,0x71,0xff,0xf6, 0x01,0x91,0x00,0x72,0xff,0xf6,0x01,0x91,0x00,0x73,0xff,0xf6,0x01,0x91,0x00,0x79,0xff,0xfa,0x01,0x91,0x00,0x7a,0xff,0xfa,0x01,0x91,0x00,0x7b,0xff,0xfa,0x01,0x91,0x00,0x7c,0xff,0xfa,0x01,0x91,0x00,0x7d,0xff,0xfa,0x01,0x91,0x00,0xac,0xff,0x9a,0x01,0x91,0x00,0xb1,0xff,0xfa,0x01,0x91,0x00,0xc4,0xff,0xb4,0x01,0x91,0x00,0xc5, 0xff,0xb4,0x01,0x91,0x00,0xf8,0xff,0xfa,0x01,0x91,0x00,0xfd,0xff,0xfa,0x01,0x91,0x00,0xff,0xff,0xfa,0x01,0x91,0x01,0x00,0xff,0xf6,0x01,0x91,0x01,0x08,0xff,0xf6,0x01,0x91,0x01,0x0b,0xff,0xf6,0x01,0x91,0x01,0x0d,0xff,0xf6,0x01,0x91,0x01,0x19,0xff,0xfa,0x01,0x91,0x01,0x48,0xff,0xfa,0x01,0x91,0x01,0x4c,0xff,0xf6,0x01,0x91, 0x01,0x4e,0xff,0xf6,0x01,0x91,0x01,0x50,0xff,0xf6,0x01,0x91,0x01,0x52,0xff,0xfa,0x01,0x91,0x01,0x54,0xff,0xfa,0x01,0x91,0x01,0x56,0xff,0xfa,0x01,0x91,0x01,0x6f,0xff,0xfa,0x01,0x91,0x01,0x71,0xff,0xfa,0x01,0x91,0x01,0x8a,0xff,0xfa,0x01,0x92,0x00,0x0f,0xff,0x50,0x01,0x92,0x00,0x11,0xff,0x3d,0x01,0x92,0x00,0x24,0xff,0x62, 0x01,0x92,0x00,0x26,0xff,0xd3,0x01,0x92,0x00,0x2a,0xff,0xd3,0x01,0x92,0x00,0x2d,0xff,0xbe,0x01,0x92,0x00,0x32,0xff,0xd3,0x01,0x92,0x00,0x34,0xff,0xd3,0x01,0x92,0x00,0x36,0xff,0xe5,0x01,0x92,0x00,0x37,0x00,0x27,0x01,0x92,0x00,0x44,0xff,0x39,0x01,0x92,0x00,0x46,0xff,0x4c,0x01,0x92,0x00,0x47,0xff,0x4c,0x01,0x92,0x00,0x48, 0xff,0x4c,0x01,0x92,0x00,0x49,0xff,0xe5,0x01,0x92,0x00,0x4a,0xff,0x4c,0x01,0x92,0x00,0x50,0xff,0x73,0x01,0x92,0x00,0x51,0xff,0x73,0x01,0x92,0x00,0x52,0xff,0x4c,0x01,0x92,0x00,0x53,0xff,0x73,0x01,0x92,0x00,0x54,0xff,0x4c,0x01,0x92,0x00,0x55,0xff,0x73,0x01,0x92,0x00,0x56,0xff,0x7b,0x01,0x92,0x00,0x58,0xff,0x73,0x01,0x92, 0x00,0x62,0xff,0x62,0x01,0x92,0x00,0x63,0xff,0x62,0x01,0x92,0x00,0x64,0xff,0xcd,0x01,0x92,0x00,0x67,0xff,0xd3,0x01,0x92,0x00,0x69,0xff,0x39,0x01,0x92,0x00,0x6a,0xff,0x39,0x01,0x92,0x00,0x6b,0xff,0x39,0x01,0x92,0x00,0x6c,0xff,0x7f,0x01,0x92,0x00,0x6d,0xff,0x66,0x01,0x92,0x00,0x6e,0xff,0x39,0x01,0x92,0x00,0x6f,0xff,0x4c, 0x01,0x92,0x00,0x70,0xff,0x4c,0x01,0x92,0x00,0x71,0xff,0x4c,0x01,0x92,0x00,0x72,0xff,0x4c,0x01,0x92,0x00,0x73,0xff,0x4c,0x01,0x92,0x00,0x77,0x00,0x5a,0x01,0x92,0x00,0x78,0xff,0x73,0x01,0x92,0x00,0x79,0xff,0x4c,0x01,0x92,0x00,0x7a,0xff,0x4c,0x01,0x92,0x00,0x7b,0xff,0x4c,0x01,0x92,0x00,0x7c,0xff,0x4c,0x01,0x92,0x00,0x7d, 0xff,0x4c,0x01,0x92,0x00,0x7e,0xff,0x73,0x01,0x92,0x00,0x7f,0xff,0x73,0x01,0x92,0x00,0x80,0xff,0x73,0x01,0x92,0x00,0x81,0xff,0x73,0x01,0x92,0x00,0x91,0xff,0x3f,0x01,0x92,0x00,0x92,0xff,0xd3,0x01,0x92,0x00,0xa0,0xff,0x39,0x01,0x92,0x00,0xa2,0xff,0x1b,0x01,0x92,0x00,0xaa,0xff,0xcf,0x01,0x92,0x00,0xac,0xff,0x3d,0x01,0x92, 0x00,0xad,0xff,0x62,0x01,0x92,0x00,0xae,0xff,0x62,0x01,0x92,0x00,0xaf,0xff,0xd3,0x01,0x92,0x00,0xb0,0xff,0xd3,0x01,0x92,0x00,0xb1,0xff,0x4c,0x01,0x92,0x00,0xbe,0xff,0x9a,0x01,0x92,0x00,0xc4,0xff,0x08,0x01,0x92,0x00,0xc5,0xff,0x08,0x01,0x92,0x00,0xc7,0xff,0x62,0x01,0x92,0x00,0xc9,0xff,0x62,0x01,0x92,0x00,0xd0,0xff,0xd3, 0x01,0x92,0x00,0xd1,0xff,0xd3,0x01,0x92,0x00,0xd2,0xff,0xd3,0x01,0x92,0x00,0xe3,0xff,0xe5,0x01,0x92,0x00,0xe4,0xff,0x7b,0x01,0x92,0x00,0xf7,0xff,0xd3,0x01,0x92,0x00,0xf8,0xff,0x4c,0x01,0x92,0x00,0xfa,0xff,0xe5,0x01,0x92,0x00,0xfb,0xff,0x7b,0x01,0x92,0x00,0xfc,0xff,0xd3,0x01,0x92,0x00,0xfd,0xff,0x4c,0x01,0x92,0x00,0xfe, 0xff,0xd3,0x01,0x92,0x00,0xff,0xff,0x4c,0x01,0x92,0x01,0x00,0xff,0x4c,0x01,0x92,0x01,0x03,0xff,0x62,0x01,0x92,0x01,0x04,0xff,0x7f,0x01,0x92,0x01,0x05,0xff,0x62,0x01,0x92,0x01,0x06,0xff,0x39,0x01,0x92,0x01,0x08,0xff,0x4c,0x01,0x92,0x01,0x0b,0xff,0x4c,0x01,0x92,0x01,0x0d,0xff,0x4c,0x01,0x92,0x01,0x15,0xff,0x73,0x01,0x92, 0x01,0x17,0xff,0x73,0x01,0x92,0x01,0x18,0xff,0xd3,0x01,0x92,0x01,0x19,0xff,0x4c,0x01,0x92,0x01,0x1b,0xff,0x73,0x01,0x92,0x01,0x1d,0xff,0x73,0x01,0x92,0x01,0x1e,0xff,0xe5,0x01,0x92,0x01,0x1f,0xff,0x7b,0x01,0x92,0x01,0x20,0x00,0x27,0x01,0x92,0x01,0x22,0x00,0x27,0x01,0x92,0x01,0x25,0xff,0x73,0x01,0x92,0x01,0x27,0xff,0x73, 0x01,0x92,0x01,0x45,0xff,0x62,0x01,0x92,0x01,0x46,0xff,0x7f,0x01,0x92,0x01,0x47,0xff,0xd3,0x01,0x92,0x01,0x48,0xff,0x4c,0x01,0x92,0x01,0x4c,0xff,0x4c,0x01,0x92,0x01,0x4e,0xff,0x4c,0x01,0x92,0x01,0x50,0xff,0x4c,0x01,0x92,0x01,0x51,0xff,0xd3,0x01,0x92,0x01,0x52,0xff,0x4c,0x01,0x92,0x01,0x53,0xff,0xd3,0x01,0x92,0x01,0x54, 0xff,0x4c,0x01,0x92,0x01,0x55,0xff,0xd3,0x01,0x92,0x01,0x56,0xff,0x4c,0x01,0x92,0x01,0x5c,0x00,0x5a,0x01,0x92,0x01,0x5e,0x00,0x5a,0x01,0x92,0x01,0x60,0x00,0x5a,0x01,0x92,0x01,0x63,0xff,0xbe,0x01,0x92,0x01,0x6d,0xff,0x73,0x01,0x92,0x01,0x6e,0xff,0xd3,0x01,0x92,0x01,0x6f,0xff,0x4c,0x01,0x92,0x01,0x70,0xff,0xd3,0x01,0x92, 0x01,0x71,0xff,0x4c,0x01,0x92,0x01,0x73,0xff,0x73,0x01,0x92,0x01,0x74,0xff,0xe5,0x01,0x92,0x01,0x75,0xff,0x7b,0x01,0x92,0x01,0x76,0x00,0x27,0x01,0x92,0x01,0x79,0xff,0x73,0x01,0x92,0x01,0x7b,0xff,0x73,0x01,0x92,0x01,0x7d,0xff,0x73,0x01,0x92,0x01,0x7f,0xff,0x73,0x01,0x92,0x01,0x85,0xff,0x62,0x01,0x92,0x01,0x86,0xff,0x7f, 0x01,0x92,0x01,0x87,0xff,0x62,0x01,0x92,0x01,0x88,0xff,0x39,0x01,0x92,0x01,0x89,0xff,0xd3,0x01,0x92,0x01,0x8a,0xff,0x4c,0x01,0x92,0x02,0x3d,0xff,0xe5,0x01,0x92,0x02,0x3e,0xff,0x7b,0x01,0x93,0x00,0x05,0x00,0x1d,0x01,0x93,0x00,0x0a,0x00,0x1d,0x01,0x93,0x00,0x0f,0xff,0x9a,0x01,0x93,0x00,0x11,0xff,0x81,0x01,0x93,0x00,0x22, 0xff,0xb4,0x01,0x93,0x00,0x46,0xff,0xf6,0x01,0x93,0x00,0x47,0xff,0xf6,0x01,0x93,0x00,0x48,0xff,0xf6,0x01,0x93,0x00,0x49,0x00,0x04,0x01,0x93,0x00,0x4a,0xff,0xf6,0x01,0x93,0x00,0x52,0xff,0xf6,0x01,0x93,0x00,0x54,0xff,0xf6,0x01,0x93,0x00,0x57,0x00,0x06,0x01,0x93,0x00,0x6f,0xff,0xf6,0x01,0x93,0x00,0x70,0xff,0xf6,0x01,0x93, 0x00,0x71,0xff,0xf6,0x01,0x93,0x00,0x72,0xff,0xf6,0x01,0x93,0x00,0x73,0xff,0xf6,0x01,0x93,0x00,0x79,0xff,0xf6,0x01,0x93,0x00,0x7a,0xff,0xf6,0x01,0x93,0x00,0x7b,0xff,0xf6,0x01,0x93,0x00,0x7c,0xff,0xf6,0x01,0x93,0x00,0x7d,0xff,0xf6,0x01,0x93,0x00,0xac,0xff,0x81,0x01,0x93,0x00,0xb1,0xff,0xf6,0x01,0x93,0x00,0xbf,0x00,0x0c, 0x01,0x93,0x00,0xc4,0xff,0x8d,0x01,0x93,0x00,0xc5,0xff,0x8d,0x01,0x93,0x00,0xf8,0xff,0xf6,0x01,0x93,0x00,0xfd,0xff,0xf6,0x01,0x93,0x00,0xff,0xff,0xf6,0x01,0x93,0x01,0x00,0xff,0xf6,0x01,0x93,0x01,0x08,0xff,0xf6,0x01,0x93,0x01,0x0b,0xff,0xf6,0x01,0x93,0x01,0x0d,0xff,0xf6,0x01,0x93,0x01,0x19,0xff,0xf6,0x01,0x93,0x01,0x21, 0x00,0x06,0x01,0x93,0x01,0x23,0x00,0x06,0x01,0x93,0x01,0x48,0xff,0xf6,0x01,0x93,0x01,0x4c,0xff,0xf6,0x01,0x93,0x01,0x4e,0xff,0xf6,0x01,0x93,0x01,0x50,0xff,0xf6,0x01,0x93,0x01,0x52,0xff,0xf6,0x01,0x93,0x01,0x54,0xff,0xf6,0x01,0x93,0x01,0x56,0xff,0xf6,0x01,0x93,0x01,0x6f,0xff,0xf6,0x01,0x93,0x01,0x71,0xff,0xf6,0x01,0x93, 0x01,0x77,0x00,0x06,0x01,0x93,0x01,0x8a,0xff,0xf6,0x01,0xa1,0x00,0x0d,0xff,0x7f,0x01,0xa1,0x00,0x8d,0xff,0x98,0x01,0xa1,0x00,0xb4,0xff,0x66,0x01,0xa1,0x00,0xb5,0xff,0x3d,0x01,0xa1,0x00,0xb6,0xff,0x66,0x01,0xa1,0x00,0xb7,0xff,0x3d,0x01,0xa1,0x01,0x2d,0xff,0xe5,0x01,0xa1,0x01,0x2e,0xff,0xcf,0x01,0xa1,0x01,0x33,0xff,0x8f, 0x01,0xa1,0x01,0xb4,0xff,0xe5,0x01,0xa1,0x01,0xb7,0x00,0x3d,0x01,0xa1,0x01,0xb8,0xff,0x6d,0x01,0xa1,0x01,0xb9,0xff,0x64,0x01,0xa1,0x01,0xbb,0xff,0x79,0x01,0xa1,0x01,0xbe,0xff,0x64,0x01,0xa1,0x01,0xc5,0xff,0xaa,0x01,0xa1,0x01,0xc8,0xff,0xe7,0x01,0xa1,0x01,0xd3,0xff,0xcf,0x01,0xa2,0x00,0xa9,0x00,0x0c,0x01,0xa2,0x01,0xa8, 0x00,0x0a,0x01,0xa2,0x01,0xa9,0x00,0x0c,0x01,0xa2,0x01,0xb0,0x00,0x0c,0x01,0xa2,0x01,0xb8,0x00,0x33,0x01,0xa5,0x01,0xa9,0xff,0xe5,0x01,0xa5,0x01,0xb0,0xff,0xe5,0x01,0xa5,0x01,0xb8,0xff,0xa4,0x01,0xa5,0x01,0xb9,0xff,0xe7,0x01,0xa5,0x01,0xbe,0xff,0xe7,0x01,0xa5,0x01,0xcb,0xff,0xd7,0x01,0xa6,0x00,0x04,0xff,0xd7,0x01,0xa6, 0x00,0x11,0xff,0x71,0x01,0xa6,0x00,0x1e,0xff,0x4c,0x01,0xa6,0x00,0xa2,0xff,0xd7,0x01,0xa6,0x00,0xa9,0xff,0x71,0x01,0xa6,0x00,0xac,0xff,0x71,0x01,0xa6,0x01,0x2d,0xff,0xd3,0x01,0xa6,0x01,0x2e,0xff,0xd3,0x01,0xa6,0x01,0x2f,0xff,0x4c,0x01,0xa6,0x01,0x30,0xff,0xc3,0x01,0xa6,0x01,0x31,0xff,0x9c,0x01,0xa6,0x01,0x32,0xff,0x4c, 0x01,0xa6,0x01,0x33,0xff,0xcf,0x01,0xa6,0x01,0x34,0xff,0x4c,0x01,0xa6,0x01,0xa9,0xff,0x60,0x01,0xa6,0x01,0xb0,0xff,0x60,0x01,0xa6,0x01,0xb4,0xff,0xd3,0x01,0xa6,0x01,0xb8,0x00,0x29,0x01,0xa6,0x01,0xbf,0xff,0x4c,0x01,0xa6,0x01,0xc0,0xff,0x9c,0x01,0xa6,0x01,0xc3,0xff,0x9a,0x01,0xa6,0x01,0xc6,0xff,0xc1,0x01,0xa6,0x01,0xc7, 0xff,0x71,0x01,0xa6,0x01,0xc9,0xff,0xd7,0x01,0xa6,0x01,0xca,0xff,0x71,0x01,0xa6,0x01,0xcc,0xff,0x71,0x01,0xa6,0x01,0xce,0xff,0xb0,0x01,0xa6,0x01,0xcf,0xff,0x4c,0x01,0xa6,0x01,0xd0,0xff,0x71,0x01,0xa6,0x01,0xd1,0xff,0x4c,0x01,0xa6,0x01,0xd2,0xff,0x9a,0x01,0xa6,0x01,0xd3,0xff,0xdb,0x01,0xa6,0x01,0xd4,0xff,0x9a,0x01,0xa6, 0x01,0xd5,0xff,0x4c,0x01,0xa6,0x01,0xd7,0xff,0x9a,0x01,0xa6,0x01,0xd8,0xff,0x4c,0x01,0xa6,0x01,0xd9,0xff,0x9a,0x01,0xa6,0x01,0xda,0xff,0x4c,0x01,0xa6,0x02,0x37,0xff,0xcf,0x01,0xa8,0x01,0xcb,0x00,0x6a,0x01,0xa9,0x00,0x0d,0xff,0x7f,0x01,0xa9,0x00,0x0f,0x00,0x46,0x01,0xa9,0x00,0x1e,0x00,0x46,0x01,0xa9,0x00,0x8d,0xff,0x98, 0x01,0xa9,0x00,0xa4,0xff,0xf6,0x01,0xa9,0x00,0xb4,0xff,0x66,0x01,0xa9,0x00,0xb5,0xff,0x3d,0x01,0xa9,0x00,0xb6,0xff,0x66,0x01,0xa9,0x00,0xb7,0xff,0x3d,0x01,0xa9,0x01,0x2d,0xff,0xe5,0x01,0xa9,0x01,0x2e,0xff,0xcf,0x01,0xa9,0x01,0x33,0xff,0x8f,0x01,0xa9,0x01,0xb4,0xff,0xe5,0x01,0xa9,0x01,0xb7,0x00,0x3d,0x01,0xa9,0x01,0xb8, 0xff,0x6d,0x01,0xa9,0x01,0xb9,0xff,0x64,0x01,0xa9,0x01,0xbb,0xff,0x79,0x01,0xa9,0x01,0xbe,0xff,0x64,0x01,0xa9,0x01,0xc5,0xff,0xaa,0x01,0xa9,0x01,0xc8,0xff,0xe7,0x01,0xa9,0x01,0xcb,0x00,0x3d,0x01,0xa9,0x01,0xcd,0xff,0xcf,0x01,0xa9,0x01,0xd3,0xff,0xcf,0x01,0xa9,0x01,0xd4,0xff,0xf6,0x01,0xaa,0x00,0xc4,0xff,0xb0,0x01,0xaa, 0x00,0xc5,0xff,0xb0,0x01,0xaa,0x01,0xb8,0xff,0xa4,0x01,0xaa,0x01,0xb9,0xff,0xbe,0x01,0xaa,0x01,0xbb,0xff,0xe7,0x01,0xaa,0x01,0xbe,0xff,0xbe,0x01,0xaa,0x01,0xd3,0xff,0xe7,0x01,0xab,0x00,0xa9,0x00,0x0c,0x01,0xab,0x01,0xa8,0x00,0x0a,0x01,0xab,0x01,0xa9,0x00,0x0c,0x01,0xab,0x01,0xb0,0x00,0x0c,0x01,0xab,0x01,0xb8,0x00,0x33, 0x01,0xab,0x01,0xba,0x00,0x0a,0x01,0xac,0x00,0xab,0x00,0x29,0x01,0xac,0x00,0xbf,0x00,0x52,0x01,0xac,0x01,0xa8,0x00,0x3d,0x01,0xac,0x01,0xb8,0x00,0x29,0x01,0xac,0x01,0xcb,0x00,0x25,0x01,0xaf,0x00,0x0f,0x00,0x29,0x01,0xaf,0x00,0x1e,0x00,0x29,0x01,0xaf,0x00,0xc4,0x00,0x46,0x01,0xaf,0x00,0xc5,0x00,0x46,0x01,0xaf,0x01,0x2d, 0xff,0xa6,0x01,0xaf,0x01,0x2e,0xff,0x91,0x01,0xaf,0x01,0x2f,0xff,0xe7,0x01,0xaf,0x01,0x30,0xff,0xe7,0x01,0xaf,0x01,0x32,0xff,0xe7,0x01,0xaf,0x01,0x33,0xff,0x9a,0x01,0xaf,0x01,0x34,0xff,0xe7,0x01,0xaf,0x01,0xa8,0x00,0x4a,0x01,0xaf,0x01,0xac,0x00,0x29,0x01,0xaf,0x01,0xb4,0xff,0xa6,0x01,0xaf,0x01,0xb7,0x00,0x3f,0x01,0xaf, 0x01,0xba,0x00,0x25,0x01,0xaf,0x01,0xbb,0xff,0xdb,0x01,0xaf,0x01,0xbf,0xff,0xe7,0x01,0xaf,0x01,0xc2,0xff,0xe7,0x01,0xaf,0x01,0xc3,0xff,0xe7,0x01,0xaf,0x01,0xc5,0xff,0xd1,0x01,0xaf,0x01,0xc8,0xff,0xe7,0x01,0xaf,0x01,0xc9,0xff,0xe7,0x01,0xaf,0x01,0xca,0x00,0x29,0x01,0xaf,0x01,0xcb,0x00,0x3d,0x01,0xaf,0x01,0xcc,0x00,0x29, 0x01,0xaf,0x01,0xcf,0xff,0xe7,0x01,0xaf,0x01,0xd1,0xff,0xe7,0x01,0xaf,0x01,0xd2,0xff,0xe7,0x01,0xaf,0x01,0xd4,0xff,0xe7,0x01,0xaf,0x01,0xd5,0xff,0xe7,0x01,0xaf,0x01,0xd7,0xff,0xe7,0x01,0xaf,0x01,0xd9,0xff,0xe7,0x01,0xaf,0x01,0xda,0xff,0xe7,0x01,0xb0,0x00,0x0d,0xff,0x7f,0x01,0xb0,0x00,0x8d,0xff,0x98,0x01,0xb0,0x00,0xb4, 0xff,0x66,0x01,0xb0,0x00,0xb5,0xff,0x3d,0x01,0xb0,0x00,0xb6,0xff,0x66,0x01,0xb0,0x00,0xb7,0xff,0x3d,0x01,0xb0,0x01,0x2d,0xff,0xe5,0x01,0xb0,0x01,0x2e,0xff,0xcf,0x01,0xb0,0x01,0x33,0xff,0x8f,0x01,0xb0,0x01,0xb4,0xff,0xe5,0x01,0xb0,0x01,0xb7,0x00,0x3d,0x01,0xb0,0x01,0xb8,0xff,0x6d,0x01,0xb0,0x01,0xb9,0xff,0x64,0x01,0xb0, 0x01,0xbb,0xff,0x79,0x01,0xb0,0x01,0xbe,0xff,0x64,0x01,0xb0,0x01,0xc3,0xff,0xf6,0x01,0xb0,0x01,0xc5,0xff,0xaa,0x01,0xb0,0x01,0xc8,0xff,0xe7,0x01,0xb0,0x01,0xcb,0x00,0x3d,0x01,0xb0,0x01,0xcd,0xff,0xcf,0x01,0xb0,0x01,0xd3,0xff,0xcf,0x01,0xb0,0x01,0xd4,0xff,0xf6,0x01,0xb0,0x01,0xd9,0xff,0xf6,0x01,0xb3,0x01,0xa8,0x00,0x3d, 0x01,0xb3,0x01,0xb7,0x00,0x25,0x01,0xb3,0x01,0xcb,0x00,0x3d,0x01,0xb4,0x00,0x0f,0xff,0xa2,0x01,0xb4,0x00,0xa9,0xff,0xcf,0x01,0xb4,0x00,0xc4,0xff,0x4a,0x01,0xb4,0x00,0xc5,0xff,0x96,0x01,0xb4,0x01,0xa9,0xff,0xe5,0x01,0xb4,0x01,0xac,0xff,0xcd,0x01,0xb4,0x01,0xb0,0xff,0xe5,0x01,0xb4,0x01,0xb7,0xff,0xe3,0x01,0xb4,0x01,0xb8, 0xff,0xa4,0x01,0xb4,0x01,0xb9,0xff,0xe7,0x01,0xb4,0x01,0xba,0xff,0xdb,0x01,0xb4,0x01,0xbe,0xff,0xe7,0x01,0xb4,0x01,0xcb,0xff,0xd7,0x01,0xb6,0x00,0x0f,0xfe,0xba,0x01,0xb6,0x00,0x11,0xfe,0xba,0x01,0xb6,0x00,0xa9,0xff,0x58,0x01,0xb6,0x00,0xac,0xfe,0xba,0x01,0xb6,0x00,0xc4,0xfe,0xba,0x01,0xb6,0x00,0xc5,0xfe,0xae,0x01,0xb6, 0x01,0x2f,0xff,0xb2,0x01,0xb6,0x01,0x30,0xff,0xb2,0x01,0xb6,0x01,0x32,0xff,0xb2,0x01,0xb6,0x01,0x34,0xff,0xb2,0x01,0xb6,0x01,0xa9,0xff,0x60,0x01,0xb6,0x01,0xb0,0xff,0x60,0x01,0xb6,0x01,0xba,0xff,0xc3,0x01,0xb6,0x01,0xbf,0xff,0xb2,0x01,0xb6,0x01,0xcb,0xff,0xc3,0x01,0xb6,0x01,0xcf,0xff,0xb2,0x01,0xb6,0x01,0xd0,0xff,0xa0, 0x01,0xb6,0x01,0xd1,0xff,0xc3,0x01,0xb6,0x01,0xd5,0xff,0xc3,0x01,0xb6,0x01,0xd8,0xff,0xb2,0x01,0xb7,0x00,0xa9,0x00,0x3d,0x01,0xb7,0x01,0x2d,0xff,0xe7,0x01,0xb7,0x01,0x2e,0xff,0xe7,0x01,0xb7,0x01,0x33,0xff,0xb6,0x01,0xb7,0x01,0xa9,0x00,0x3d,0x01,0xb7,0x01,0xb0,0x00,0x3d,0x01,0xb7,0x01,0xb3,0x00,0x25,0x01,0xb7,0x01,0xb4, 0xff,0xe7,0x01,0xb7,0x01,0xba,0x00,0x12,0x01,0xb7,0x01,0xcb,0x00,0x3d,0x01,0xb7,0x01,0xd3,0xff,0xdb,0x01,0xb8,0x00,0x0f,0xff,0x7d,0x01,0xb8,0x00,0x11,0xff,0x4c,0x01,0xb8,0x00,0x1d,0xff,0x7d,0x01,0xb8,0x00,0x1e,0xff,0xe9,0x01,0xb8,0x00,0x8d,0x00,0x52,0x01,0xb8,0x00,0xa9,0xff,0x6d,0x01,0xb8,0x00,0xaa,0xff,0x98,0x01,0xb8, 0x00,0xab,0xff,0xcd,0x01,0xb8,0x00,0xac,0xff,0x4c,0x01,0xb8,0x00,0xb5,0x00,0x29,0x01,0xb8,0x00,0xb7,0x00,0x29,0x01,0xb8,0x00,0xbe,0xff,0x98,0x01,0xb8,0x00,0xbf,0xff,0xcd,0x01,0xb8,0x00,0xc4,0xff,0x14,0x01,0xb8,0x00,0xc5,0xff,0x14,0x01,0xb8,0x01,0x2d,0xff,0xa4,0x01,0xb8,0x01,0x2e,0xff,0xa4,0x01,0xb8,0x01,0x2f,0xff,0x2b, 0x01,0xb8,0x01,0x30,0xff,0xb0,0x01,0xb8,0x01,0x31,0xff,0x2b,0x01,0xb8,0x01,0x32,0xff,0x2b,0x01,0xb8,0x01,0x33,0xff,0x8f,0x01,0xb8,0x01,0x34,0xff,0x2b,0x01,0xb8,0x01,0xa8,0x00,0x7b,0x01,0xb8,0x01,0xa9,0xff,0x66,0x01,0xb8,0x01,0xb0,0xff,0x66,0x01,0xb8,0x01,0xb4,0xff,0xa4,0x01,0xb8,0x01,0xb8,0x00,0x29,0x01,0xb8,0x01,0xb9, 0x00,0x1d,0x01,0xb8,0x01,0xba,0xff,0xf8,0x01,0xb8,0x01,0xbe,0x00,0x1d,0x01,0xb8,0x01,0xbf,0xff,0x2b,0x01,0xb8,0x01,0xc0,0xff,0x2b,0x01,0xb8,0x01,0xc1,0xff,0x4e,0x01,0xb8,0x01,0xc2,0xff,0x8f,0x01,0xb8,0x01,0xc3,0xff,0x4e,0x01,0xb8,0x01,0xc5,0xff,0xc1,0x01,0xb8,0x01,0xc6,0xff,0xc1,0x01,0xb8,0x01,0xc7,0xff,0x4e,0x01,0xb8, 0x01,0xc9,0xff,0x4e,0x01,0xb8,0x01,0xca,0xff,0x4e,0x01,0xb8,0x01,0xcc,0xff,0x4e,0x01,0xb8,0x01,0xce,0xff,0xb0,0x01,0xb8,0x01,0xcf,0xff,0x2b,0x01,0xb8,0x01,0xd0,0xff,0x4e,0x01,0xb8,0x01,0xd1,0xff,0x2b,0x01,0xb8,0x01,0xd2,0xff,0x4e,0x01,0xb8,0x01,0xd3,0xff,0x7f,0x01,0xb8,0x01,0xd4,0xff,0x4e,0x01,0xb8,0x01,0xd5,0xff,0x2b, 0x01,0xb8,0x01,0xd6,0x00,0x52,0x01,0xb8,0x01,0xd7,0xff,0x4e,0x01,0xb8,0x01,0xd8,0xff,0x2b,0x01,0xb8,0x01,0xd9,0xff,0x4e,0x01,0xb8,0x01,0xda,0xff,0x2b,0x01,0xb8,0x02,0x37,0xff,0x8f,0x01,0xb9,0x00,0x0f,0xff,0x50,0x01,0xb9,0x00,0x11,0xff,0x3d,0x01,0xb9,0x00,0x1e,0xff,0x4c,0x01,0xb9,0x00,0xa2,0xff,0x19,0x01,0xb9,0x00,0xa9, 0xff,0x71,0x01,0xb9,0x00,0xaa,0xff,0xcd,0x01,0xb9,0x00,0xac,0xff,0x3d,0x01,0xb9,0x00,0xbe,0xff,0x98,0x01,0xb9,0x00,0xc4,0xff,0x06,0x01,0xb9,0x00,0xc5,0xff,0x06,0x01,0xb9,0x01,0x2d,0xff,0xd3,0x01,0xb9,0x01,0x2e,0xff,0xd3,0x01,0xb9,0x01,0x2f,0xff,0x4c,0x01,0xb9,0x01,0x30,0xff,0xc3,0x01,0xb9,0x01,0x31,0xff,0x9c,0x01,0xb9, 0x01,0x32,0xff,0x4c,0x01,0xb9,0x01,0x33,0xff,0xcf,0x01,0xb9,0x01,0x34,0xff,0x4c,0x01,0xb9,0x01,0xa8,0x00,0x5c,0x01,0xb9,0x01,0xa9,0xff,0x60,0x01,0xb9,0x01,0xb0,0xff,0x60,0x01,0xb9,0x01,0xb4,0xff,0xd3,0x01,0xb9,0x01,0xb8,0x00,0x29,0x01,0xb9,0x01,0xbf,0xff,0x4c,0x01,0xb9,0x01,0xc0,0xff,0x9c,0x01,0xb9,0x01,0xc2,0xff,0x9a, 0x01,0xb9,0x01,0xc3,0xff,0x9a,0x01,0xb9,0x01,0xc6,0xff,0xc1,0x01,0xb9,0x01,0xc7,0xff,0x71,0x01,0xb9,0x01,0xc9,0xff,0x9a,0x01,0xb9,0x01,0xca,0xff,0x71,0x01,0xb9,0x01,0xcc,0xff,0x71,0x01,0xb9,0x01,0xce,0xff,0xb0,0x01,0xb9,0x01,0xcf,0xff,0x4c,0x01,0xb9,0x01,0xd0,0xff,0x71,0x01,0xb9,0x01,0xd1,0xff,0x4c,0x01,0xb9,0x01,0xd2, 0xff,0x9a,0x01,0xb9,0x01,0xd3,0xff,0xdb,0x01,0xb9,0x01,0xd4,0xff,0x9a,0x01,0xb9,0x01,0xd5,0xff,0x4c,0x01,0xb9,0x01,0xd6,0x00,0x29,0x01,0xb9,0x01,0xd7,0xff,0x9a,0x01,0xb9,0x01,0xd8,0xff,0x4c,0x01,0xb9,0x01,0xd9,0xff,0x9a,0x01,0xb9,0x01,0xda,0xff,0x4c,0x01,0xb9,0x02,0x37,0xff,0xcf,0x01,0xba,0x00,0x0f,0x00,0x46,0x01,0xba, 0x00,0x10,0xff,0xe7,0x01,0xba,0x00,0x11,0x00,0x39,0x01,0xba,0x00,0x1e,0x00,0x52,0x01,0xba,0x00,0xa9,0x00,0x3d,0x01,0xba,0x00,0xac,0x00,0x39,0x01,0xba,0x00,0xc4,0x00,0x46,0x01,0xba,0x00,0xc5,0x00,0x52,0x01,0xba,0x01,0x2d,0xff,0xe7,0x01,0xba,0x01,0x2e,0xff,0xe7,0x01,0xba,0x01,0x33,0xff,0xc3,0x01,0xba,0x01,0xa8,0x00,0x52, 0x01,0xba,0x01,0xb4,0xff,0xe7,0x01,0xba,0x01,0xb7,0x00,0x12,0x01,0xba,0x01,0xb8,0x00,0x23,0x01,0xba,0x01,0xc2,0xff,0xe7,0x01,0xba,0x01,0xc3,0xff,0xe7,0x01,0xba,0x01,0xc9,0xff,0xe7,0x01,0xba,0x01,0xd2,0xff,0xe7,0x01,0xba,0x01,0xd4,0xff,0xe7,0x01,0xba,0x01,0xd6,0x00,0x0a,0x01,0xba,0x01,0xd7,0xff,0xe7,0x01,0xba,0x01,0xd9, 0xff,0xe7,0x01,0xbb,0x00,0xa9,0xff,0x71,0x01,0xbb,0x01,0x2f,0xff,0xe7,0x01,0xbb,0x01,0x30,0xff,0xe7,0x01,0xbb,0x01,0x32,0xff,0xe7,0x01,0xbb,0x01,0x34,0xff,0xe7,0x01,0xbb,0x01,0xa9,0xff,0x6d,0x01,0xbb,0x01,0xb0,0xff,0x6d,0x01,0xbb,0x01,0xbf,0xff,0xe7,0x01,0xbb,0x01,0xcf,0xff,0xe7,0x01,0xbb,0x01,0xd1,0xff,0xe7,0x01,0xbb, 0x01,0xd5,0xff,0xe7,0x01,0xbb,0x01,0xd8,0xff,0xe7,0x01,0xbb,0x01,0xda,0xff,0xe7,0x01,0xbc,0x00,0xa9,0x00,0x12,0x01,0xbe,0x00,0x04,0xff,0xd7,0x01,0xbe,0x00,0x11,0xff,0x71,0x01,0xbe,0x00,0x1e,0xff,0x4c,0x01,0xbe,0x00,0xa2,0xff,0xd7,0x01,0xbe,0x00,0xa9,0xff,0x71,0x01,0xbe,0x00,0xac,0xff,0x71,0x01,0xbe,0x01,0x2d,0xff,0xd3, 0x01,0xbe,0x01,0x2e,0xff,0xd3,0x01,0xbe,0x01,0x2f,0xff,0x4c,0x01,0xbe,0x01,0x30,0xff,0xc3,0x01,0xbe,0x01,0x31,0xff,0x9c,0x01,0xbe,0x01,0x32,0xff,0x4c,0x01,0xbe,0x01,0x33,0xff,0xcf,0x01,0xbe,0x01,0x34,0xff,0x4c,0x01,0xbe,0x01,0xa9,0xff,0x60,0x01,0xbe,0x01,0xb0,0xff,0x60,0x01,0xbe,0x01,0xb4,0xff,0xd3,0x01,0xbe,0x01,0xb8, 0x00,0x29,0x01,0xbe,0x01,0xbf,0xff,0x4c,0x01,0xbe,0x01,0xc0,0xff,0x9c,0x01,0xbe,0x01,0xc3,0xff,0x9a,0x01,0xbe,0x01,0xc6,0xff,0xc1,0x01,0xbe,0x01,0xc7,0xff,0x71,0x01,0xbe,0x01,0xc9,0xff,0xd7,0x01,0xbe,0x01,0xca,0xff,0x71,0x01,0xbe,0x01,0xcc,0xff,0x71,0x01,0xbe,0x01,0xce,0xff,0xb0,0x01,0xbe,0x01,0xcf,0xff,0x4c,0x01,0xbe, 0x01,0xd0,0xff,0x71,0x01,0xbe,0x01,0xd1,0xff,0x4c,0x01,0xbe,0x01,0xd2,0xff,0x9a,0x01,0xbe,0x01,0xd3,0xff,0xdb,0x01,0xbe,0x01,0xd4,0xff,0x9a,0x01,0xbe,0x01,0xd5,0xff,0x4c,0x01,0xbe,0x01,0xd7,0xff,0x9a,0x01,0xbe,0x01,0xd8,0xff,0x4c,0x01,0xbe,0x01,0xd9,0xff,0x9a,0x01,0xbe,0x01,0xda,0xff,0x4c,0x01,0xbe,0x02,0x37,0xff,0xcf, 0x01,0xbf,0x00,0x1e,0xff,0xee,0x01,0xbf,0x01,0x2f,0xff,0xee,0x01,0xbf,0x01,0x30,0xff,0xee,0x01,0xbf,0x01,0x32,0xff,0xee,0x01,0xbf,0x01,0x34,0xff,0xee,0x01,0xbf,0x01,0xcf,0xff,0xee,0x01,0xbf,0x01,0xd1,0xff,0xee,0x01,0xbf,0x01,0xd5,0xff,0xee,0x01,0xc1,0x00,0x05,0xff,0x98,0x01,0xc1,0x00,0x0a,0xff,0x98,0x01,0xc2,0x01,0xcb, 0x00,0x6a,0x01,0xc3,0x00,0x05,0xff,0x6f,0x01,0xc3,0x00,0x0a,0xff,0x6f,0x01,0xc3,0x01,0xc5,0xff,0xdb,0x01,0xc3,0x01,0xcb,0xff,0xe7,0x01,0xc3,0x01,0xd3,0xff,0xe7,0x01,0xc4,0x01,0x33,0xff,0xd1,0x01,0xc4,0x01,0xd3,0xff,0xc1,0x01,0xc5,0x01,0x30,0xff,0xe5,0x01,0xc5,0x01,0x33,0x00,0x19,0x01,0xc5,0x01,0xc8,0x00,0x19,0x01,0xc5, 0x01,0xd0,0xff,0xe7,0x01,0xc5,0x02,0x37,0x00,0x19,0x01,0xc6,0x01,0x2f,0xff,0xb6,0x01,0xc6,0x01,0x30,0xff,0xb6,0x01,0xc6,0x01,0x32,0xff,0xb6,0x01,0xc6,0x01,0x33,0xff,0x81,0x01,0xc6,0x01,0x34,0xff,0xb6,0x01,0xc6,0x01,0xa8,0x00,0x3d,0x01,0xc6,0x01,0xbf,0xff,0xb6,0x01,0xc6,0x01,0xc3,0xff,0xe7,0x01,0xc6,0x01,0xc5,0xff,0xc3, 0x01,0xc6,0x01,0xcd,0xff,0x8f,0x01,0xc6,0x01,0xcf,0xff,0xb6,0x01,0xc6,0x01,0xd1,0xff,0xb6,0x01,0xc6,0x01,0xd2,0xff,0xe7,0x01,0xc6,0x01,0xd4,0xff,0xc3,0x01,0xc6,0x01,0xd5,0xff,0xb6,0x01,0xc6,0x01,0xd7,0xff,0xe7,0x01,0xc6,0x01,0xd8,0xff,0xb6,0x01,0xc6,0x01,0xd9,0xff,0xe7,0x01,0xc7,0x00,0x05,0xff,0x98,0x01,0xc7,0x00,0x0a, 0xff,0x98,0x01,0xc9,0x01,0xcb,0x00,0x6a,0x01,0xca,0x00,0x0f,0x00,0x29,0x01,0xca,0x00,0x10,0xff,0xb8,0x01,0xca,0x00,0x11,0x00,0x29,0x01,0xca,0x00,0x1d,0x00,0x52,0x01,0xca,0x00,0x1e,0x00,0x52,0x01,0xca,0x00,0xac,0x00,0x29,0x01,0xca,0x01,0x2f,0xff,0xd7,0x01,0xca,0x01,0x30,0xff,0xd7,0x01,0xca,0x01,0x32,0xff,0xd7,0x01,0xca, 0x01,0x34,0xff,0xd7,0x01,0xca,0x01,0xbf,0xff,0xd7,0x01,0xca,0x01,0xcb,0x00,0x31,0x01,0xca,0x01,0xcf,0xff,0xd7,0x01,0xca,0x01,0xd1,0xff,0xd7,0x01,0xca,0x01,0xd5,0xff,0xd7,0x01,0xca,0x01,0xd8,0xff,0xd7,0x01,0xca,0x01,0xda,0xff,0xd7,0x01,0xcb,0x01,0x33,0xff,0xb0,0x01,0xcb,0x01,0xc3,0xff,0xdb,0x01,0xcb,0x01,0xcb,0x00,0x31, 0x01,0xcb,0x01,0xcd,0xff,0xd1,0x01,0xcb,0x01,0xd2,0xff,0xdb,0x01,0xcb,0x01,0xd3,0xff,0xcf,0x01,0xcb,0x01,0xd4,0xff,0xdb,0x01,0xcb,0x01,0xd7,0xff,0xdb,0x01,0xcb,0x01,0xd9,0xff,0xdb,0x01,0xcd,0x01,0x2f,0xff,0xd7,0x01,0xcd,0x01,0x30,0xff,0xd7,0x01,0xcd,0x01,0x32,0xff,0xd7,0x01,0xcd,0x01,0x34,0xff,0xd7,0x01,0xcd,0x01,0xbf, 0xff,0xd7,0x01,0xcd,0x01,0xcb,0xff,0xb6,0x01,0xcd,0x01,0xce,0xff,0xe7,0x01,0xcd,0x01,0xcf,0xff,0xd7,0x01,0xcd,0x01,0xd0,0xff,0xdb,0x01,0xcd,0x01,0xd1,0xff,0xec,0x01,0xcd,0x01,0xd5,0xff,0xd7,0x01,0xcd,0x01,0xd8,0xff,0xd7,0x01,0xcd,0x01,0xda,0xff,0xd7,0x01,0xce,0x01,0x2f,0xff,0xd7,0x01,0xce,0x01,0x30,0xff,0xd7,0x01,0xce, 0x01,0x32,0xff,0xd7,0x01,0xce,0x01,0x34,0xff,0xd7,0x01,0xce,0x01,0xbf,0xff,0xd7,0x01,0xce,0x01,0xcf,0xff,0xd7,0x01,0xce,0x01,0xd5,0xff,0xd7,0x01,0xce,0x01,0xda,0xff,0xd7,0x01,0xcf,0x00,0x05,0xff,0x6f,0x01,0xcf,0x00,0x0a,0xff,0x6f,0x01,0xcf,0x00,0xb4,0xff,0xb0,0x01,0xcf,0x00,0xb5,0xff,0x7b,0x01,0xcf,0x00,0xb6,0xff,0xbc, 0x01,0xcf,0x00,0xb7,0xff,0x7b,0x01,0xcf,0x01,0x33,0xff,0xdb,0x01,0xcf,0x01,0xc5,0xff,0xdb,0x01,0xcf,0x01,0xd3,0xff,0xc3,0x01,0xcf,0x02,0x37,0xff,0xdb,0x01,0xd0,0x00,0x05,0xff,0x6f,0x01,0xd0,0x00,0x0a,0xff,0x6f,0x01,0xd0,0x00,0xb4,0xff,0xb0,0x01,0xd0,0x00,0xb5,0xff,0x7b,0x01,0xd0,0x00,0xb6,0xff,0xbc,0x01,0xd0,0x00,0xb7, 0xff,0x7b,0x01,0xd0,0x01,0x33,0xff,0xdb,0x01,0xd0,0x01,0xc5,0xff,0xe7,0x01,0xd0,0x01,0xd3,0xff,0xc3,0x01,0xd0,0x02,0x37,0xff,0xdb,0x01,0xd1,0x01,0x2f,0xff,0xc3,0x01,0xd1,0x01,0x30,0xff,0xc3,0x01,0xd1,0x01,0x32,0xff,0xc3,0x01,0xd1,0x01,0x34,0xff,0xc3,0x01,0xd1,0x01,0xbf,0xff,0xc3,0x01,0xd1,0x01,0xcb,0x00,0x25,0x01,0xd1, 0x01,0xcf,0xff,0xc3,0x01,0xd1,0x01,0xd8,0xff,0xc3,0x01,0xd1,0x01,0xda,0xff,0xc3,0x01,0xd2,0x00,0x05,0xff,0x6f,0x01,0xd2,0x00,0x0a,0xff,0x6f,0x01,0xd2,0x00,0xb4,0xff,0xb0,0x01,0xd2,0x00,0xb5,0xff,0x7b,0x01,0xd2,0x00,0xb6,0xff,0xbc,0x01,0xd2,0x00,0xb7,0xff,0x7b,0x01,0xd2,0x01,0x33,0xff,0xdb,0x01,0xd2,0x01,0xc5,0xff,0xdb, 0x01,0xd2,0x01,0xcb,0xff,0xe7,0x01,0xd2,0x01,0xd3,0xff,0xe7,0x01,0xd2,0x02,0x37,0xff,0xdb,0x01,0xd3,0x00,0x10,0xff,0xe7,0x01,0xd3,0x01,0x2f,0xff,0xc3,0x01,0xd3,0x01,0x30,0xff,0x9c,0x01,0xd3,0x01,0x31,0xff,0xd7,0x01,0xd3,0x01,0x32,0xff,0xc3,0x01,0xd3,0x01,0x34,0xff,0xc3,0x01,0xd3,0x01,0xbf,0xff,0xc3,0x01,0xd3,0x01,0xc0, 0xff,0xd7,0x01,0xd3,0x01,0xc3,0xff,0xe7,0x01,0xd3,0x01,0xcb,0xff,0xe7,0x01,0xd3,0x01,0xcf,0xff,0xc3,0x01,0xd3,0x01,0xd1,0xff,0xbe,0x01,0xd3,0x01,0xd2,0xff,0xe7,0x01,0xd3,0x01,0xd3,0x00,0x19,0x01,0xd3,0x01,0xd5,0xff,0xc3,0x01,0xd3,0x01,0xd7,0xff,0xe7,0x01,0xd3,0x01,0xd8,0xff,0xc3,0x01,0xd3,0x01,0xd9,0xff,0xe7,0x01,0xd3, 0x01,0xda,0xff,0xc3,0x01,0xd4,0x01,0xcb,0xff,0xe7,0x01,0xd5,0x00,0x05,0xff,0x6f,0x01,0xd5,0x00,0x0a,0xff,0x6f,0x01,0xd5,0x00,0xb4,0xff,0xb0,0x01,0xd5,0x00,0xb5,0xff,0x7b,0x01,0xd5,0x00,0xb6,0xff,0xbc,0x01,0xd5,0x00,0xb7,0xff,0x7b,0x01,0xd5,0x01,0x33,0xff,0xdb,0x01,0xd5,0x01,0xc5,0xff,0xdb,0x01,0xd5,0x01,0xd3,0xff,0xe7, 0x01,0xd5,0x02,0x37,0xff,0xdb,0x01,0xd6,0x01,0xcb,0x00,0x6a,0x01,0xd7,0x00,0x05,0xff,0x6f,0x01,0xd7,0x00,0x0a,0xff,0x6f,0x01,0xd7,0x00,0xb4,0xff,0xb0,0x01,0xd7,0x00,0xb5,0xff,0x7b,0x01,0xd7,0x00,0xb6,0xff,0xbc,0x01,0xd7,0x00,0xb7,0xff,0x7b,0x01,0xd7,0x01,0xc5,0xff,0xdb,0x01,0xd7,0x01,0xcb,0xff,0xe7,0x01,0xd7,0x01,0xd3, 0xff,0xe7,0x01,0xd8,0x00,0x05,0xff,0x6f,0x01,0xd8,0x00,0x0a,0xff,0x6f,0x01,0xd8,0x00,0xb4,0xff,0xb0,0x01,0xd8,0x00,0xb5,0xff,0x7b,0x01,0xd8,0x00,0xb6,0xff,0xbc,0x01,0xd8,0x00,0xb7,0xff,0x7b,0x01,0xd8,0x01,0xc5,0xff,0xdb,0x01,0xd8,0x01,0xd3,0xff,0xc3,0x01,0xd9,0x00,0x05,0xff,0x6f,0x01,0xd9,0x00,0x0a,0xff,0x6f,0x01,0xd9, 0x00,0xb4,0xff,0xb0,0x01,0xd9,0x00,0xb5,0xff,0x7b,0x01,0xd9,0x00,0xb6,0xff,0xbc,0x01,0xd9,0x00,0xb7,0xff,0x7b,0x01,0xd9,0x01,0xc5,0xff,0xdb,0x01,0xd9,0x01,0xcb,0xff,0xe7,0x01,0xd9,0x01,0xd3,0xff,0xe7,0x01,0xda,0x00,0x05,0xff,0x6f,0x01,0xda,0x00,0x0a,0xff,0x6f,0x01,0xda,0x00,0xb4,0xff,0xb0,0x01,0xda,0x00,0xb5,0xff,0x7b, 0x01,0xda,0x00,0xb6,0xff,0xbc,0x01,0xda,0x00,0xb7,0xff,0x7b,0x01,0xda,0x01,0xc5,0xff,0xdb,0x01,0xda,0x01,0xd3,0xff,0xe7,0x01,0xdb,0x01,0xe1,0x00,0x46,0x01,0xdb,0x01,0xe7,0x00,0x0c,0x01,0xdb,0x01,0xeb,0x00,0x46,0x01,0xdb,0x01,0xed,0x00,0x14,0x01,0xdb,0x01,0xf2,0x00,0x46,0x01,0xdb,0x01,0xfc,0x00,0x0a,0x01,0xdc,0x01,0xdc, 0xff,0x79,0x01,0xdc,0x01,0xde,0xff,0xcf,0x01,0xdc,0x01,0xe1,0x00,0x29,0x01,0xdc,0x01,0xe3,0xff,0x79,0x01,0xdc,0x01,0xe5,0xff,0xee,0x01,0xdc,0x01,0xeb,0x00,0x29,0x01,0xdc,0x01,0xf2,0x00,0x29,0x01,0xdc,0x01,0xf5,0xff,0xcf,0x01,0xdc,0x01,0xf8,0xff,0xcf,0x01,0xdc,0x01,0xf9,0xff,0x79,0x01,0xdc,0x01,0xfa,0xff,0xee,0x01,0xdc, 0x01,0xfb,0xff,0xc3,0x01,0xdc,0x01,0xfe,0xff,0x60,0x01,0xdc,0x02,0x01,0xff,0x79,0x01,0xdc,0x02,0x19,0xff,0xcf,0x01,0xdc,0x02,0x1a,0xff,0xe7,0x01,0xdc,0x02,0x31,0xff,0xe7,0x01,0xdd,0x00,0x0f,0xff,0x83,0x01,0xdd,0x00,0x11,0xff,0x83,0x01,0xdd,0x00,0xaa,0xff,0x91,0x01,0xdd,0x00,0xab,0xff,0xd7,0x01,0xdd,0x00,0xac,0xff,0x83, 0x01,0xdd,0x01,0xdc,0x00,0x29,0x01,0xdd,0x01,0xde,0xff,0xa2,0x01,0xdd,0x01,0xe1,0xff,0xa2,0x01,0xdd,0x01,0xe3,0x00,0x29,0x01,0xdd,0x01,0xe5,0x00,0x1d,0x01,0xdd,0x01,0xe7,0xff,0x71,0x01,0xdd,0x01,0xeb,0xff,0xa2,0x01,0xdd,0x01,0xf2,0xff,0xa2,0x01,0xdd,0x01,0xf5,0xff,0xcf,0x01,0xdd,0x01,0xf8,0xff,0xcf,0x01,0xdd,0x01,0xf9, 0x00,0x29,0x01,0xdd,0x01,0xfa,0x00,0x1d,0x01,0xdd,0x01,0xfb,0xff,0xa2,0x01,0xdd,0x02,0x01,0x00,0x29,0x01,0xdd,0x02,0x06,0xff,0xe7,0x01,0xdd,0x02,0x07,0xff,0x27,0x01,0xdd,0x02,0x09,0xff,0x4e,0x01,0xdd,0x02,0x0a,0xff,0x4e,0x01,0xdd,0x02,0x0b,0xff,0x9e,0x01,0xdd,0x02,0x0c,0xff,0x2b,0x01,0xdd,0x02,0x0f,0xff,0x4e,0x01,0xdd, 0x02,0x10,0xff,0x4e,0x01,0xdd,0x02,0x11,0xff,0x4e,0x01,0xdd,0x02,0x12,0xff,0x9e,0x01,0xdd,0x02,0x13,0xff,0x4e,0x01,0xdd,0x02,0x14,0xff,0x4e,0x01,0xdd,0x02,0x15,0xff,0x2b,0x01,0xdd,0x02,0x16,0xff,0x4e,0x01,0xdd,0x02,0x17,0xff,0x4e,0x01,0xdd,0x02,0x18,0xff,0x2b,0x01,0xdd,0x02,0x19,0xff,0xc3,0x01,0xdd,0x02,0x1b,0xff,0x2b, 0x01,0xdd,0x02,0x1c,0xff,0x4c,0x01,0xdd,0x02,0x1d,0xff,0x4e,0x01,0xdd,0x02,0x1e,0xff,0x4e,0x01,0xdd,0x02,0x1f,0xff,0x4e,0x01,0xdd,0x02,0x20,0xff,0x4e,0x01,0xdd,0x02,0x21,0xff,0xc3,0x01,0xdd,0x02,0x22,0xff,0x4e,0x01,0xdd,0x02,0x23,0xff,0x4e,0x01,0xdd,0x02,0x24,0xff,0x60,0x01,0xdd,0x02,0x25,0xff,0x4e,0x01,0xdd,0x02,0x26, 0xff,0x54,0x01,0xdd,0x02,0x27,0xff,0x2b,0x01,0xdd,0x02,0x29,0xff,0x4e,0x01,0xdd,0x02,0x2a,0xff,0x2b,0x01,0xdd,0x02,0x2b,0xff,0x66,0x01,0xdd,0x02,0x2c,0x00,0x6f,0x01,0xdd,0x02,0x2d,0xff,0x9e,0x01,0xdd,0x02,0x2e,0xff,0x4e,0x01,0xdd,0x02,0x32,0xff,0x4e,0x01,0xdd,0x02,0x34,0xff,0x4e,0x01,0xde,0x00,0xaa,0xff,0xcd,0x01,0xde, 0x00,0xbe,0xff,0xcd,0x01,0xde,0x01,0xde,0xff,0xc9,0x01,0xde,0x01,0xf5,0xff,0xc9,0x01,0xde,0x01,0xf8,0xff,0xc9,0x01,0xde,0x01,0xfb,0xff,0xc9,0x01,0xde,0x02,0x19,0xff,0xdb,0x01,0xde,0x02,0x21,0xff,0xdb,0x01,0xde,0x02,0x2c,0x00,0x1f,0x01,0xdf,0x00,0xc4,0xff,0xb0,0x01,0xdf,0x00,0xc5,0xff,0xb0,0x01,0xdf,0x01,0xf5,0xff,0xe7, 0x01,0xdf,0x01,0xfb,0xff,0xdb,0x01,0xdf,0x01,0xfe,0xff,0xdb,0x01,0xdf,0x02,0x1a,0xff,0xcf,0x01,0xdf,0x02,0x31,0xff,0xcf,0x01,0xe1,0x01,0xdc,0xff,0x79,0x01,0xe1,0x01,0xde,0xff,0xe7,0x01,0xe1,0x01,0xe3,0xff,0x79,0x01,0xe1,0x01,0xf5,0xff,0xe7,0x01,0xe1,0x01,0xf8,0xff,0xe7,0x01,0xe1,0x01,0xf9,0xff,0x79,0x01,0xe1,0x01,0xfb, 0xff,0xe7,0x01,0xe1,0x01,0xfe,0xff,0x62,0x01,0xe1,0x02,0x01,0xff,0x79,0x01,0xe1,0x02,0x19,0xff,0xcf,0x01,0xe1,0x02,0x21,0xff,0xcf,0x01,0xe2,0x01,0xdc,0xff,0x79,0x01,0xe2,0x01,0xde,0xff,0xe7,0x01,0xe2,0x01,0xe3,0xff,0x79,0x01,0xe2,0x01,0xf5,0xff,0xe7,0x01,0xe2,0x01,0xf8,0xff,0xe7,0x01,0xe2,0x01,0xf9,0xff,0x79,0x01,0xe2, 0x01,0xfb,0xff,0xe7,0x01,0xe2,0x01,0xfe,0xff,0x62,0x01,0xe2,0x02,0x01,0xff,0x79,0x01,0xe2,0x02,0x19,0xff,0xcf,0x01,0xe2,0x02,0x21,0xff,0xcf,0x01,0xe3,0x01,0xdc,0xff,0x79,0x01,0xe3,0x01,0xe1,0x00,0x3d,0x01,0xe3,0x01,0xe3,0xff,0x58,0x01,0xe3,0x01,0xeb,0x00,0x3d,0x01,0xe3,0x01,0xf2,0x00,0x3d,0x01,0xe3,0x01,0xfb,0xff,0xe7, 0x01,0xe3,0x01,0xfe,0xff,0x4e,0x01,0xe3,0x02,0x01,0xff,0xae,0x01,0xe4,0x00,0x0f,0x00,0x29,0x01,0xe4,0x00,0x1e,0x00,0x29,0x01,0xe4,0x00,0xc4,0x00,0x46,0x01,0xe4,0x00,0xc5,0x00,0x46,0x01,0xe4,0x01,0xde,0xff,0xa4,0x01,0xe4,0x01,0xe1,0x00,0x5c,0x01,0xe4,0x01,0xeb,0x00,0x5c,0x01,0xe4,0x01,0xed,0x00,0x62,0x01,0xe4,0x01,0xf2, 0x00,0x5c,0x01,0xe4,0x01,0xf5,0xff,0xa4,0x01,0xe4,0x01,0xf8,0xff,0xa4,0x01,0xe4,0x01,0xfb,0xff,0xa4,0x01,0xe4,0x01,0xfc,0x00,0x25,0x01,0xe4,0x01,0xfe,0xff,0xc3,0x01,0xe4,0x02,0x08,0xff,0xe5,0x01,0xe4,0x02,0x0b,0x00,0x62,0x01,0xe4,0x02,0x0c,0xff,0xe5,0x01,0xe4,0x02,0x0d,0x00,0x3d,0x01,0xe4,0x02,0x12,0x00,0x62,0x01,0xe4, 0x02,0x15,0xff,0xe5,0x01,0xe4,0x02,0x18,0xff,0xe5,0x01,0xe4,0x02,0x1a,0xff,0xa2,0x01,0xe4,0x02,0x1b,0xff,0xe5,0x01,0xe4,0x02,0x1e,0xff,0xc3,0x01,0xe4,0x02,0x27,0xff,0xe5,0x01,0xe4,0x02,0x2a,0xff,0xe5,0x01,0xe4,0x02,0x2c,0x00,0x29,0x01,0xe4,0x02,0x2d,0x00,0x62,0x01,0xe4,0x02,0x31,0xff,0xa2,0x01,0xe5,0x00,0x0f,0xff,0x3b, 0x01,0xe5,0x00,0x11,0xff,0x2b,0x01,0xe5,0x00,0xac,0xff,0x2b,0x01,0xe5,0x01,0xdc,0x00,0x29,0x01,0xe5,0x01,0xe1,0xff,0x75,0x01,0xe5,0x01,0xe3,0x00,0x29,0x01,0xe5,0x01,0xe7,0xff,0x33,0x01,0xe5,0x01,0xeb,0xff,0x75,0x01,0xe5,0x01,0xed,0x00,0x25,0x01,0xe5,0x01,0xf2,0xff,0x75,0x01,0xe5,0x01,0xf9,0x00,0x29,0x01,0xe5,0x02,0x01, 0x00,0x29,0x01,0xe5,0x02,0x07,0xff,0x79,0x01,0xe5,0x02,0x09,0xff,0xb6,0x01,0xe5,0x02,0x0a,0xff,0xb6,0x01,0xe5,0x02,0x0b,0xfe,0xfe,0x01,0xe5,0x02,0x0c,0xff,0x91,0x01,0xe5,0x02,0x0f,0xff,0xb6,0x01,0xe5,0x02,0x10,0xff,0xb6,0x01,0xe5,0x02,0x11,0xff,0xb6,0x01,0xe5,0x02,0x12,0xfe,0xfe,0x01,0xe5,0x02,0x13,0xff,0xb6,0x01,0xe5, 0x02,0x14,0xff,0xb6,0x01,0xe5,0x02,0x15,0xff,0x91,0x01,0xe5,0x02,0x16,0xff,0xb6,0x01,0xe5,0x02,0x17,0xff,0xb6,0x01,0xe5,0x02,0x18,0xff,0x91,0x01,0xe5,0x02,0x1b,0xff,0x91,0x01,0xe5,0x02,0x1c,0xff,0xb6,0x01,0xe5,0x02,0x1d,0xff,0xb6,0x01,0xe5,0x02,0x1f,0xff,0xb6,0x01,0xe5,0x02,0x20,0xff,0xb6,0x01,0xe5,0x02,0x22,0xff,0xb6, 0x01,0xe5,0x02,0x23,0xff,0xb6,0x01,0xe5,0x02,0x25,0xff,0xb6,0x01,0xe5,0x02,0x26,0xff,0xaa,0x01,0xe5,0x02,0x27,0xff,0x91,0x01,0xe5,0x02,0x29,0xff,0xb6,0x01,0xe5,0x02,0x2a,0xff,0x91,0x01,0xe5,0x02,0x2b,0xff,0xc3,0x01,0xe5,0x02,0x2c,0x00,0x6d,0x01,0xe5,0x02,0x2d,0xfe,0xfe,0x01,0xe5,0x02,0x2e,0xff,0xb6,0x01,0xe5,0x02,0x30, 0xff,0xb6,0x01,0xe5,0x02,0x32,0xff,0xb6,0x01,0xe5,0x02,0x34,0xff,0xb6,0x01,0xe7,0x00,0x0d,0xff,0x7f,0x01,0xe7,0x00,0x0f,0x00,0x46,0x01,0xe7,0x00,0x1e,0x00,0x46,0x01,0xe7,0x00,0x8d,0xff,0x98,0x01,0xe7,0x00,0xb4,0xff,0x66,0x01,0xe7,0x00,0xb5,0xff,0x3d,0x01,0xe7,0x00,0xb6,0xff,0x66,0x01,0xe7,0x00,0xb7,0xff,0x3d,0x01,0xe7, 0x01,0xdc,0xff,0x6d,0x01,0xe7,0x01,0xde,0xff,0xe5,0x01,0xe7,0x01,0xe1,0x00,0x60,0x01,0xe7,0x01,0xe3,0xff,0x6d,0x01,0xe7,0x01,0xeb,0x00,0x60,0x01,0xe7,0x01,0xed,0x00,0x3d,0x01,0xe7,0x01,0xf2,0x00,0x60,0x01,0xe7,0x01,0xf5,0xff,0xe5,0x01,0xe7,0x01,0xf8,0xff,0xe5,0x01,0xe7,0x01,0xf9,0xff,0x6d,0x01,0xe7,0x01,0xfb,0xff,0xc3, 0x01,0xe7,0x01,0xfe,0xff,0x3d,0x01,0xe7,0x02,0x01,0xff,0x6d,0x01,0xe7,0x02,0x0b,0x00,0x56,0x01,0xe7,0x02,0x0d,0x00,0x29,0x01,0xe7,0x02,0x12,0x00,0x56,0x01,0xe7,0x02,0x1a,0xff,0xd9,0x01,0xe7,0x02,0x2d,0x00,0x56,0x01,0xe7,0x02,0x31,0xff,0xd9,0x01,0xe8,0x01,0xde,0xff,0xe7,0x01,0xe8,0x01,0xf5,0xff,0xe7,0x01,0xe8,0x01,0xf8, 0xff,0xe7,0x01,0xe8,0x01,0xfb,0xff,0xe7,0x01,0xe8,0x01,0xfe,0xff,0x62,0x01,0xe8,0x02,0x19,0xff,0xcf,0x01,0xe8,0x02,0x21,0xff,0xcf,0x01,0xe9,0x00,0xc4,0xff,0xb0,0x01,0xe9,0x00,0xc5,0xff,0xb0,0x01,0xe9,0x01,0xdc,0xff,0xa2,0x01,0xe9,0x01,0xe3,0xff,0xa2,0x01,0xe9,0x01,0xf9,0xff,0xa2,0x01,0xe9,0x01,0xfe,0xff,0xd5,0x01,0xe9, 0x02,0x01,0xff,0xa2,0x01,0xea,0x00,0x0f,0xff,0x83,0x01,0xea,0x00,0x11,0xff,0x83,0x01,0xea,0x00,0xaa,0xff,0x91,0x01,0xea,0x00,0xab,0xff,0xd7,0x01,0xea,0x00,0xac,0xff,0x83,0x01,0xea,0x01,0xdc,0x00,0x29,0x01,0xea,0x01,0xde,0xff,0xa2,0x01,0xea,0x01,0xe1,0xff,0x9e,0x01,0xea,0x01,0xe3,0x00,0x29,0x01,0xea,0x01,0xe5,0x00,0x1d, 0x01,0xea,0x01,0xe7,0xff,0x71,0x01,0xea,0x01,0xeb,0xff,0xa2,0x01,0xea,0x01,0xf2,0xff,0xa2,0x01,0xea,0x01,0xf5,0xff,0xcf,0x01,0xea,0x01,0xf8,0xff,0xcf,0x01,0xea,0x01,0xf9,0x00,0x29,0x01,0xea,0x01,0xfa,0x00,0x1d,0x01,0xea,0x01,0xfb,0xff,0xa2,0x01,0xea,0x02,0x01,0x00,0x29,0x01,0xea,0x02,0x06,0xff,0xe7,0x01,0xea,0x02,0x07, 0xff,0x27,0x01,0xea,0x02,0x09,0xff,0x4e,0x01,0xea,0x02,0x0a,0xff,0x4e,0x01,0xea,0x02,0x0b,0xff,0x9e,0x01,0xea,0x02,0x0c,0xff,0x2b,0x01,0xea,0x02,0x0f,0xff,0x4e,0x01,0xea,0x02,0x10,0xff,0x4e,0x01,0xea,0x02,0x11,0xff,0x4e,0x01,0xea,0x02,0x12,0xff,0x9e,0x01,0xea,0x02,0x13,0xff,0x4e,0x01,0xea,0x02,0x14,0xff,0x4e,0x01,0xea, 0x02,0x15,0xff,0x2b,0x01,0xea,0x02,0x16,0xff,0x4e,0x01,0xea,0x02,0x17,0xff,0x4e,0x01,0xea,0x02,0x18,0xff,0x2b,0x01,0xea,0x02,0x19,0xff,0xc3,0x01,0xea,0x02,0x1b,0xff,0x2b,0x01,0xea,0x02,0x1c,0xff,0x4c,0x01,0xea,0x02,0x1d,0xff,0x4e,0x01,0xea,0x02,0x1e,0xff,0x4e,0x01,0xea,0x02,0x1f,0xff,0x4e,0x01,0xea,0x02,0x20,0xff,0x4e, 0x01,0xea,0x02,0x21,0xff,0xc3,0x01,0xea,0x02,0x22,0xff,0x4e,0x01,0xea,0x02,0x23,0xff,0x4e,0x01,0xea,0x02,0x24,0xff,0x60,0x01,0xea,0x02,0x25,0xff,0x4e,0x01,0xea,0x02,0x26,0xff,0x54,0x01,0xea,0x02,0x27,0xff,0x2b,0x01,0xea,0x02,0x29,0xff,0x4e,0x01,0xea,0x02,0x2a,0xff,0x2b,0x01,0xea,0x02,0x2b,0xff,0x66,0x01,0xea,0x02,0x2c, 0x00,0x6f,0x01,0xea,0x02,0x2d,0xff,0x9e,0x01,0xea,0x02,0x2e,0xff,0x4e,0x01,0xea,0x02,0x32,0xff,0x4e,0x01,0xea,0x02,0x34,0xff,0x4e,0x01,0xec,0x01,0xe1,0x00,0x46,0x01,0xec,0x01,0xe7,0x00,0x0c,0x01,0xec,0x01,0xeb,0x00,0x46,0x01,0xec,0x01,0xed,0x00,0x14,0x01,0xec,0x01,0xf2,0x00,0x46,0x01,0xec,0x01,0xfc,0x00,0x0a,0x01,0xec, 0x02,0x2c,0x00,0x14,0x01,0xed,0x00,0x0f,0x00,0x52,0x01,0xed,0x00,0x1e,0x00,0x52,0x01,0xed,0x00,0xc4,0x00,0x5a,0x01,0xed,0x00,0xc5,0x00,0x5a,0x01,0xed,0x01,0xde,0xff,0xcd,0x01,0xed,0x01,0xe1,0x00,0x85,0x01,0xed,0x01,0xe7,0x00,0x3d,0x01,0xed,0x01,0xeb,0x00,0x85,0x01,0xed,0x01,0xed,0x00,0x66,0x01,0xed,0x01,0xf5,0xff,0xcd, 0x01,0xed,0x01,0xf8,0xff,0xcd,0x01,0xed,0x01,0xfb,0xff,0xcd,0x01,0xed,0x01,0xfc,0x00,0x25,0x01,0xed,0x01,0xfe,0xff,0xdb,0x01,0xed,0x02,0x06,0x00,0x3d,0x01,0xed,0x02,0x0b,0x00,0x7b,0x01,0xed,0x02,0x0d,0x00,0x3d,0x01,0xed,0x02,0x12,0x00,0x7b,0x01,0xed,0x02,0x1a,0xff,0xd1,0x01,0xed,0x02,0x1c,0x00,0x48,0x01,0xed,0x02,0x1e, 0xff,0xe7,0x01,0xed,0x02,0x2c,0x00,0x52,0x01,0xed,0x02,0x2d,0x00,0x7b,0x01,0xed,0x02,0x31,0xff,0xd1,0x01,0xee,0x01,0xdc,0xff,0xe1,0x01,0xee,0x01,0xde,0xff,0xdb,0x01,0xee,0x01,0xe3,0xff,0xe1,0x01,0xee,0x01,0xf5,0xff,0xdb,0x01,0xee,0x01,0xf8,0xff,0xdb,0x01,0xee,0x01,0xf9,0xff,0xe1,0x01,0xee,0x01,0xfb,0xff,0xdb,0x01,0xee, 0x01,0xfe,0xff,0xdd,0x01,0xee,0x02,0x01,0xff,0xe1,0x01,0xf1,0x00,0x0f,0x00,0x29,0x01,0xf1,0x00,0x1e,0x00,0x29,0x01,0xf1,0x00,0xc4,0x00,0x46,0x01,0xf1,0x00,0xc5,0x00,0x46,0x01,0xf1,0x01,0xde,0xff,0xa4,0x01,0xf1,0x01,0xe1,0x00,0x5c,0x01,0xf1,0x01,0xeb,0x00,0x5c,0x01,0xf1,0x01,0xed,0x00,0x62,0x01,0xf1,0x01,0xf2,0x00,0x5c, 0x01,0xf1,0x01,0xf5,0xff,0xa4,0x01,0xf1,0x01,0xf8,0xff,0xa4,0x01,0xf1,0x01,0xfb,0xff,0xa4,0x01,0xf1,0x01,0xfc,0x00,0x25,0x01,0xf1,0x01,0xfe,0xff,0xc3,0x01,0xf1,0x02,0x06,0x00,0x3d,0x01,0xf1,0x02,0x08,0xff,0xe5,0x01,0xf1,0x02,0x0b,0x00,0x62,0x01,0xf1,0x02,0x0c,0xff,0xe5,0x01,0xf1,0x02,0x0d,0x00,0x3d,0x01,0xf1,0x02,0x12, 0x00,0x62,0x01,0xf1,0x02,0x15,0xff,0xe5,0x01,0xf1,0x02,0x18,0xff,0xe5,0x01,0xf1,0x02,0x1a,0xff,0xa2,0x01,0xf1,0x02,0x1b,0xff,0xe5,0x01,0xf1,0x02,0x1e,0xff,0xc3,0x01,0xf1,0x02,0x27,0xff,0xe5,0x01,0xf1,0x02,0x2a,0xff,0xe5,0x01,0xf1,0x02,0x2c,0x00,0x29,0x01,0xf1,0x02,0x2d,0x00,0x62,0x01,0xf1,0x02,0x31,0xff,0xa2,0x01,0xf5, 0x00,0x0f,0xff,0xa2,0x01,0xf5,0x00,0x11,0xff,0xa2,0x01,0xf5,0x00,0xac,0xff,0xa2,0x01,0xf5,0x00,0xc4,0xff,0x4a,0x01,0xf5,0x00,0xc5,0xff,0x96,0x01,0xf5,0x01,0xdc,0xff,0xa2,0x01,0xf5,0x01,0xdf,0xff,0xdb,0x01,0xf5,0x01,0xe1,0xff,0xf6,0x01,0xf5,0x01,0xe3,0xff,0xa2,0x01,0xf5,0x01,0xe5,0xff,0xe7,0x01,0xf5,0x01,0xe7,0xff,0xe5, 0x01,0xf5,0x01,0xeb,0xff,0xf6,0x01,0xf5,0x01,0xed,0xff,0xcd,0x01,0xf5,0x01,0xf2,0xff,0xf6,0x01,0xf5,0x01,0xf9,0xff,0xa2,0x01,0xf5,0x01,0xfa,0xff,0xe7,0x01,0xf5,0x01,0xfc,0xff,0xdb,0x01,0xf5,0x02,0x01,0xff,0xa2,0x01,0xf7,0x00,0x0f,0xfe,0xba,0x01,0xf7,0x00,0x11,0xfe,0xba,0x01,0xf7,0x00,0xac,0xfe,0xba,0x01,0xf7,0x00,0xc4, 0xfe,0xba,0x01,0xf7,0x00,0xc5,0xfe,0xae,0x01,0xf7,0x01,0xde,0xff,0xf6,0x01,0xf7,0x01,0xe1,0xff,0x7f,0x01,0xf7,0x01,0xe5,0xff,0xe7,0x01,0xf7,0x01,0xe7,0xff,0x60,0x01,0xf7,0x01,0xeb,0xff,0x7f,0x01,0xf7,0x01,0xed,0xff,0xcf,0x01,0xf7,0x01,0xee,0xff,0xe7,0x01,0xf7,0x01,0xf2,0xff,0x7f,0x01,0xf7,0x01,0xf5,0xff,0xf6,0x01,0xf7, 0x01,0xf8,0xff,0xf6,0x01,0xf7,0x01,0xfa,0xff,0xe7,0x01,0xf7,0x01,0xfb,0xff,0xf6,0x01,0xf7,0x01,0xfc,0xff,0xc1,0x01,0xf7,0x02,0x07,0xff,0xbc,0x01,0xf7,0x02,0x0b,0xff,0x6d,0x01,0xf7,0x02,0x0c,0xff,0xb2,0x01,0xf7,0x02,0x12,0xff,0x6d,0x01,0xf7,0x02,0x15,0xff,0xb2,0x01,0xf7,0x02,0x18,0xff,0xb2,0x01,0xf7,0x02,0x1b,0xff,0xb2, 0x01,0xf7,0x02,0x27,0xff,0xb2,0x01,0xf7,0x02,0x2a,0xff,0xb2,0x01,0xf7,0x02,0x2d,0xff,0x6d,0x01,0xf8,0x00,0xaa,0xff,0xcd,0x01,0xf8,0x00,0xbe,0xff,0xcd,0x01,0xf8,0x01,0xde,0xff,0xc9,0x01,0xf8,0x01,0xed,0x00,0x31,0x01,0xf8,0x01,0xf5,0xff,0xc9,0x01,0xf8,0x01,0xf8,0xff,0xc9,0x01,0xf8,0x01,0xfb,0xff,0xc9,0x01,0xf8,0x02,0x19, 0xff,0xdb,0x01,0xf8,0x02,0x21,0xff,0xdb,0x01,0xf8,0x02,0x2c,0x00,0x1f,0x01,0xf9,0x00,0x0f,0xff,0x7d,0x01,0xf9,0x00,0x11,0xff,0x4c,0x01,0xf9,0x00,0x1d,0xff,0xe9,0x01,0xf9,0x00,0x1e,0xff,0xe9,0x01,0xf9,0x00,0x8d,0x00,0x52,0x01,0xf9,0x00,0xaa,0xff,0x98,0x01,0xf9,0x00,0xab,0xff,0xcd,0x01,0xf9,0x00,0xac,0xff,0x4c,0x01,0xf9, 0x00,0xb5,0x00,0x29,0x01,0xf9,0x00,0xb7,0x00,0x29,0x01,0xf9,0x00,0xbe,0xff,0x98,0x01,0xf9,0x00,0xbf,0xff,0xcd,0x01,0xf9,0x00,0xc4,0xff,0x14,0x01,0xf9,0x00,0xc5,0xff,0x14,0x01,0xf9,0x01,0xdc,0x00,0x29,0x01,0xf9,0x01,0xde,0xff,0xa2,0x01,0xf9,0x01,0xe1,0xff,0x8d,0x01,0xf9,0x01,0xe3,0x00,0x29,0x01,0xf9,0x01,0xe7,0xff,0x66, 0x01,0xf9,0x01,0xeb,0xff,0x8d,0x01,0xf9,0x01,0xf2,0xff,0x8d,0x01,0xf9,0x01,0xf5,0xff,0xa2,0x01,0xf9,0x01,0xf8,0xff,0xa2,0x01,0xf9,0x01,0xf9,0x00,0x29,0x01,0xf9,0x01,0xfb,0xff,0xa2,0x01,0xf9,0x01,0xfc,0xff,0xf8,0x01,0xf9,0x02,0x01,0x00,0x29,0x01,0xf9,0x02,0x06,0xff,0xe7,0x01,0xf9,0x02,0x07,0xff,0x27,0x01,0xf9,0x02,0x09, 0xff,0x4e,0x01,0xf9,0x02,0x0a,0xff,0x4e,0x01,0xf9,0x02,0x0b,0xff,0x9e,0x01,0xf9,0x02,0x0c,0xff,0x2b,0x01,0xf9,0x02,0x0d,0xff,0xa6,0x01,0xf9,0x02,0x0f,0xff,0x4e,0x01,0xf9,0x02,0x10,0xff,0x4e,0x01,0xf9,0x02,0x11,0xff,0x4e,0x01,0xf9,0x02,0x12,0xff,0x9e,0x01,0xf9,0x02,0x13,0xff,0x4e,0x01,0xf9,0x02,0x14,0xff,0x4e,0x01,0xf9, 0x02,0x15,0xff,0x2b,0x01,0xf9,0x02,0x16,0xff,0x4e,0x01,0xf9,0x02,0x17,0xff,0x4e,0x01,0xf9,0x02,0x18,0xff,0x2b,0x01,0xf9,0x02,0x19,0xff,0xc3,0x01,0xf9,0x02,0x1a,0xff,0x8d,0x01,0xf9,0x02,0x1b,0xff,0x2b,0x01,0xf9,0x02,0x1c,0xff,0x4c,0x01,0xf9,0x02,0x1d,0xff,0x4e,0x01,0xf9,0x02,0x1e,0xff,0x4e,0x01,0xf9,0x02,0x1f,0xff,0x4e, 0x01,0xf9,0x02,0x20,0xff,0x4e,0x01,0xf9,0x02,0x21,0xff,0xc3,0x01,0xf9,0x02,0x22,0xff,0x4e,0x01,0xf9,0x02,0x23,0xff,0x4e,0x01,0xf9,0x02,0x24,0xff,0x60,0x01,0xf9,0x02,0x25,0xff,0x4e,0x01,0xf9,0x02,0x26,0xff,0x54,0x01,0xf9,0x02,0x27,0xff,0x2b,0x01,0xf9,0x02,0x29,0xff,0x4e,0x01,0xf9,0x02,0x2a,0xff,0x2b,0x01,0xf9,0x02,0x2b, 0xff,0x66,0x01,0xf9,0x02,0x2c,0x00,0x6f,0x01,0xf9,0x02,0x2d,0xff,0x9e,0x01,0xf9,0x02,0x2e,0xff,0x4e,0x01,0xf9,0x02,0x30,0xff,0x4e,0x01,0xf9,0x02,0x31,0xff,0x8d,0x01,0xf9,0x02,0x32,0xff,0x4e,0x01,0xf9,0x02,0x34,0xff,0x4e,0x01,0xfa,0x00,0x0f,0xff,0x3b,0x01,0xfa,0x00,0x11,0xff,0x2b,0x01,0xfa,0x00,0xac,0xff,0x2b,0x01,0xfa, 0x01,0xdc,0x00,0x29,0x01,0xfa,0x01,0xe1,0xff,0x75,0x01,0xfa,0x01,0xe3,0x00,0x29,0x01,0xfa,0x01,0xe7,0xff,0x33,0x01,0xfa,0x01,0xeb,0xff,0x75,0x01,0xfa,0x01,0xed,0x00,0x25,0x01,0xfa,0x01,0xf2,0xff,0x75,0x01,0xfa,0x01,0xf8,0xff,0xdb,0x01,0xfa,0x01,0xf9,0x00,0x29,0x01,0xfa,0x02,0x01,0x00,0x29,0x01,0xfa,0x02,0x07,0xff,0x79, 0x01,0xfa,0x02,0x09,0xff,0xb6,0x01,0xfa,0x02,0x0a,0xff,0xb6,0x01,0xfa,0x02,0x0b,0xfe,0xfe,0x01,0xfa,0x02,0x0c,0xff,0x91,0x01,0xfa,0x02,0x0f,0xff,0xb6,0x01,0xfa,0x02,0x10,0xff,0xb6,0x01,0xfa,0x02,0x11,0xff,0xb6,0x01,0xfa,0x02,0x12,0xfe,0xfe,0x01,0xfa,0x02,0x13,0xff,0xb6,0x01,0xfa,0x02,0x14,0xff,0xb6,0x01,0xfa,0x02,0x15, 0xff,0x91,0x01,0xfa,0x02,0x16,0xff,0xb6,0x01,0xfa,0x02,0x17,0xff,0xb6,0x01,0xfa,0x02,0x18,0xff,0x91,0x01,0xfa,0x02,0x1b,0xff,0x91,0x01,0xfa,0x02,0x1c,0xff,0xb6,0x01,0xfa,0x02,0x1d,0xff,0xb6,0x01,0xfa,0x02,0x1f,0xff,0xb6,0x01,0xfa,0x02,0x20,0xff,0xb6,0x01,0xfa,0x02,0x22,0xff,0xb6,0x01,0xfa,0x02,0x23,0xff,0xb6,0x01,0xfa, 0x02,0x25,0xff,0xb6,0x01,0xfa,0x02,0x26,0xff,0xaa,0x01,0xfa,0x02,0x27,0xff,0x91,0x01,0xfa,0x02,0x29,0xff,0xb6,0x01,0xfa,0x02,0x2a,0xff,0x91,0x01,0xfa,0x02,0x2b,0xff,0xc3,0x01,0xfa,0x02,0x2c,0x00,0x6d,0x01,0xfa,0x02,0x2d,0xfe,0xfe,0x01,0xfa,0x02,0x2e,0xff,0xb6,0x01,0xfa,0x02,0x30,0xff,0xb6,0x01,0xfa,0x02,0x32,0xff,0xb6, 0x01,0xfa,0x02,0x34,0xff,0xb6,0x01,0xfb,0x00,0x0f,0xff,0xa2,0x01,0xfb,0x00,0x11,0xff,0xa2,0x01,0xfb,0x00,0xac,0xff,0xa2,0x01,0xfb,0x00,0xc4,0xff,0x4a,0x01,0xfb,0x00,0xc5,0xff,0x96,0x01,0xfb,0x01,0xdc,0xff,0xa2,0x01,0xfb,0x01,0xdf,0xff,0xdb,0x01,0xfb,0x01,0xe1,0xff,0xf6,0x01,0xfb,0x01,0xe3,0xff,0xa2,0x01,0xfb,0x01,0xe5, 0xff,0xe7,0x01,0xfb,0x01,0xe7,0xff,0xc3,0x01,0xfb,0x01,0xeb,0xff,0xf6,0x01,0xfb,0x01,0xed,0xff,0xcd,0x01,0xfb,0x01,0xee,0xff,0xcf,0x01,0xfb,0x01,0xf2,0xff,0xf6,0x01,0xfb,0x01,0xf9,0xff,0xa2,0x01,0xfb,0x01,0xfa,0xff,0xe7,0x01,0xfb,0x01,0xfc,0xff,0xdb,0x01,0xfb,0x02,0x01,0xff,0xa2,0x01,0xfb,0x02,0x07,0xff,0xe7,0x01,0xfb, 0x02,0x0b,0xff,0x91,0x01,0xfb,0x02,0x2d,0xff,0x91,0x01,0xfc,0x00,0x0f,0x00,0x46,0x01,0xfc,0x00,0x11,0x00,0x39,0x01,0xfc,0x00,0x1e,0x00,0x52,0x01,0xfc,0x00,0xac,0x00,0x39,0x01,0xfc,0x00,0xc4,0x00,0x46,0x01,0xfc,0x00,0xc5,0x00,0x52,0x01,0xfc,0x01,0xdc,0x00,0x23,0x01,0xfc,0x01,0xde,0xff,0xdb,0x01,0xfc,0x01,0xe1,0x00,0x62, 0x01,0xfc,0x01,0xe3,0x00,0x23,0x01,0xfc,0x01,0xeb,0x00,0x62,0x01,0xfc,0x01,0xed,0x00,0x25,0x01,0xfc,0x01,0xf2,0x00,0x62,0x01,0xfc,0x01,0xf5,0xff,0xe7,0x01,0xfc,0x01,0xf8,0xff,0xdb,0x01,0xfc,0x01,0xf9,0x00,0x23,0x01,0xfc,0x01,0xfb,0xff,0xdb,0x01,0xfc,0x02,0x01,0x00,0x23,0x01,0xfc,0x02,0x2c,0x00,0x52,0x01,0xfd,0x00,0x0f, 0x00,0x29,0x01,0xfd,0x00,0xc4,0x00,0x29,0x01,0xfd,0x00,0xc5,0x00,0x29,0x01,0xfd,0x01,0xe1,0x00,0x3d,0x01,0xfd,0x01,0xeb,0x00,0x3d,0x01,0xfd,0x01,0xf2,0x00,0x3d,0x01,0xfd,0x01,0xfe,0xff,0xdb,0x01,0xfd,0x02,0x0b,0x00,0x25,0x01,0xfd,0x02,0x12,0x00,0x25,0x01,0xfd,0x02,0x2d,0x00,0x25,0x02,0x00,0x00,0x0f,0x00,0x29,0x02,0x00, 0x00,0x1e,0x00,0x29,0x02,0x00,0x00,0xc4,0x00,0x29,0x02,0x00,0x00,0xc5,0x00,0x29,0x02,0x00,0x01,0xe1,0x00,0x3d,0x02,0x00,0x01,0xeb,0x00,0x3d,0x02,0x00,0x01,0xf2,0x00,0x3d,0x02,0x00,0x01,0xfb,0xff,0xcf,0x02,0x00,0x01,0xfe,0xff,0xdb,0x02,0x00,0x02,0x0b,0x00,0x25,0x02,0x00,0x02,0x12,0x00,0x25,0x02,0x00,0x02,0x2d,0x00,0x25, 0x02,0x01,0x01,0xdc,0xff,0x79,0x02,0x01,0x01,0xde,0xff,0xe7,0x02,0x01,0x01,0xe3,0xff,0x79,0x02,0x01,0x01,0xf5,0xff,0xe7,0x02,0x01,0x01,0xf8,0xff,0xe7,0x02,0x01,0x01,0xf9,0xff,0x79,0x02,0x01,0x01,0xfb,0xff,0xe7,0x02,0x01,0x01,0xfe,0xff,0x62,0x02,0x01,0x02,0x01,0xff,0x79,0x02,0x01,0x02,0x19,0xff,0xcf,0x02,0x01,0x02,0x21, 0xff,0xcf,0x02,0x03,0x01,0xdc,0xff,0x79,0x02,0x03,0x01,0xde,0xff,0xe7,0x02,0x03,0x01,0xe3,0xff,0x79,0x02,0x03,0x01,0xf5,0xff,0xe7,0x02,0x03,0x01,0xf8,0xff,0xe7,0x02,0x03,0x01,0xf9,0xff,0x79,0x02,0x03,0x01,0xfb,0xff,0xe7,0x02,0x03,0x01,0xfe,0xff,0x62,0x02,0x03,0x02,0x01,0xff,0x79,0x02,0x03,0x02,0x19,0xff,0xcf,0x02,0x03, 0x02,0x21,0xff,0xcf,0x02,0x04,0x00,0x0f,0xff,0xa2,0x02,0x04,0x00,0x11,0xff,0xa2,0x02,0x04,0x00,0xac,0xff,0xa2,0x02,0x04,0x00,0xc4,0xff,0x4a,0x02,0x04,0x00,0xc5,0xff,0x96,0x02,0x04,0x01,0xdc,0xff,0xa2,0x02,0x04,0x01,0xdf,0xff,0xdb,0x02,0x04,0x01,0xe1,0xff,0xf6,0x02,0x04,0x01,0xe3,0xff,0xa2,0x02,0x04,0x01,0xe5,0xff,0xe7, 0x02,0x04,0x01,0xe7,0xff,0xe5,0x02,0x04,0x01,0xeb,0xff,0xf6,0x02,0x04,0x01,0xf2,0xff,0xf6,0x02,0x04,0x01,0xf9,0xff,0xa2,0x02,0x04,0x01,0xfa,0xff,0xe7,0x02,0x04,0x01,0xfc,0xff,0xdb,0x02,0x04,0x02,0x01,0xff,0xa2,0x02,0x05,0x00,0x0f,0xff,0xa2,0x02,0x05,0x00,0x11,0xff,0xa2,0x02,0x05,0x00,0xac,0xff,0xa2,0x02,0x05,0x00,0xc4, 0xff,0x4a,0x02,0x05,0x00,0xc5,0xff,0x96,0x02,0x05,0x01,0xdc,0xff,0xa2,0x02,0x05,0x01,0xdf,0xff,0xdb,0x02,0x05,0x01,0xe1,0xff,0xf6,0x02,0x05,0x01,0xe3,0xff,0xa2,0x02,0x05,0x01,0xe5,0xff,0xe7,0x02,0x05,0x01,0xe7,0xff,0xe5,0x02,0x05,0x01,0xeb,0xff,0xf6,0x02,0x05,0x01,0xf2,0xff,0xf6,0x02,0x05,0x01,0xf9,0xff,0xa2,0x02,0x05, 0x01,0xfa,0xff,0xe7,0x02,0x05,0x01,0xfc,0xff,0xdb,0x02,0x05,0x02,0x01,0xff,0xa2,0x02,0x07,0x02,0x1e,0xff,0xe7,0x02,0x08,0x02,0x0b,0xff,0xe7,0x02,0x08,0x02,0x0d,0xff,0xe1,0x02,0x08,0x02,0x19,0xff,0xdb,0x02,0x08,0x02,0x21,0xff,0xdb,0x02,0x09,0x02,0x19,0xff,0xee,0x02,0x09,0x02,0x1e,0xff,0xe7,0x02,0x09,0x02,0x21,0xff,0xee, 0x02,0x0a,0x00,0x0f,0xff,0xc3,0x02,0x0a,0x00,0x11,0xff,0xae,0x02,0x0a,0x00,0xac,0xff,0xae,0x02,0x0a,0x02,0x07,0xff,0xc3,0x02,0x0a,0x02,0x0b,0xff,0xb6,0x02,0x0a,0x02,0x0c,0xff,0xdb,0x02,0x0a,0x02,0x12,0xff,0xb6,0x02,0x0a,0x02,0x15,0xff,0xdb,0x02,0x0a,0x02,0x18,0xff,0xdb,0x02,0x0a,0x02,0x19,0x00,0x29,0x02,0x0a,0x02,0x1b, 0xff,0xdb,0x02,0x0a,0x02,0x21,0x00,0x29,0x02,0x0a,0x02,0x26,0xff,0xe7,0x02,0x0a,0x02,0x27,0xff,0xdb,0x02,0x0a,0x02,0x2a,0xff,0xdb,0x02,0x0a,0x02,0x2d,0xff,0xb6,0x02,0x0b,0x02,0x12,0x00,0x14,0x02,0x0b,0x02,0x1e,0xff,0xdb,0x02,0x0b,0x02,0x2d,0x00,0x14,0x02,0x0c,0x00,0x05,0xff,0x98,0x02,0x0c,0x00,0x0a,0xff,0x98,0x02,0x0d, 0x00,0x0f,0x00,0x52,0x02,0x0d,0x00,0x10,0xff,0x73,0x02,0x0d,0x00,0x11,0x00,0x52,0x02,0x0d,0x00,0x1d,0x00,0x52,0x02,0x0d,0x00,0x1e,0x00,0x52,0x02,0x0d,0x00,0xac,0x00,0x52,0x02,0x0d,0x02,0x0b,0x00,0x29,0x02,0x0d,0x02,0x0c,0xff,0xd7,0x02,0x0d,0x02,0x0d,0x00,0x4a,0x02,0x0d,0x02,0x12,0x00,0x52,0x02,0x0d,0x02,0x15,0xff,0xd7, 0x02,0x0d,0x02,0x18,0xff,0xd7,0x02,0x0d,0x02,0x1b,0xff,0xd7,0x02,0x0d,0x02,0x1e,0xff,0xe7,0x02,0x0d,0x02,0x27,0xff,0xd7,0x02,0x0d,0x02,0x2a,0xff,0xd7,0x02,0x0d,0x02,0x2d,0x00,0x29,0x02,0x0e,0x02,0x1e,0xff,0xd7,0x02,0x11,0x00,0x0f,0x00,0x52,0x02,0x11,0x00,0x10,0xff,0x73,0x02,0x11,0x00,0x11,0x00,0x52,0x02,0x11,0x00,0x1d, 0x00,0x52,0x02,0x11,0x00,0x1e,0x00,0x52,0x02,0x11,0x00,0xac,0x00,0x52,0x02,0x11,0x02,0x0b,0x00,0x14,0x02,0x11,0x02,0x0c,0xff,0xd7,0x02,0x11,0x02,0x0d,0x00,0x3d,0x02,0x11,0x02,0x12,0x00,0x29,0x02,0x11,0x02,0x15,0xff,0xd7,0x02,0x11,0x02,0x18,0xff,0xd7,0x02,0x11,0x02,0x1b,0xff,0xd7,0x02,0x11,0x02,0x1e,0xff,0xe7,0x02,0x11, 0x02,0x27,0xff,0xd7,0x02,0x11,0x02,0x2a,0xff,0xd7,0x02,0x11,0x02,0x2d,0x00,0x29,0x02,0x15,0x00,0x05,0xff,0x6f,0x02,0x15,0x00,0x0a,0xff,0x6f,0x02,0x15,0x00,0xb4,0xff,0xb0,0x02,0x15,0x00,0xb5,0xff,0x7b,0x02,0x15,0x00,0xb6,0xff,0xbc,0x02,0x15,0x00,0xb7,0xff,0x7b,0x02,0x15,0x02,0x07,0xff,0xe5,0x02,0x15,0x02,0x0b,0xff,0xe7, 0x02,0x15,0x02,0x0d,0xff,0xd7,0x02,0x15,0x02,0x19,0xff,0xdb,0x02,0x15,0x02,0x1c,0xff,0xe7,0x02,0x15,0x02,0x21,0xff,0xdb,0x02,0x17,0x00,0x05,0xff,0x6f,0x02,0x17,0x00,0x0a,0xff,0x6f,0x02,0x17,0x00,0xb4,0xff,0xc9,0x02,0x17,0x00,0xb5,0xff,0x87,0x02,0x17,0x00,0xb6,0xff,0x87,0x02,0x17,0x00,0xb7,0xff,0x87,0x02,0x17,0x02,0x07, 0xff,0xe5,0x02,0x17,0x02,0x0b,0xff,0xe7,0x02,0x17,0x02,0x0d,0xff,0xd7,0x02,0x17,0x02,0x19,0xff,0xdb,0x02,0x17,0x02,0x1c,0xff,0xe7,0x02,0x17,0x02,0x21,0xff,0xdb,0x02,0x19,0x00,0x0f,0xff,0xc3,0x02,0x19,0x00,0x11,0xff,0xae,0x02,0x19,0x00,0xac,0xff,0xae,0x02,0x19,0x02,0x0b,0xff,0xdb,0x02,0x19,0x02,0x0c,0xff,0xdb,0x02,0x19, 0x02,0x12,0xff,0xdb,0x02,0x19,0x02,0x15,0xff,0xdb,0x02,0x19,0x02,0x18,0xff,0xdb,0x02,0x19,0x02,0x19,0x00,0x14,0x02,0x19,0x02,0x1a,0x00,0x29,0x02,0x19,0x02,0x1b,0xff,0xdb,0x02,0x19,0x02,0x21,0x00,0x29,0x02,0x19,0x02,0x26,0xff,0xe7,0x02,0x19,0x02,0x27,0xff,0xdb,0x02,0x19,0x02,0x2a,0xff,0xdb,0x02,0x19,0x02,0x2d,0xff,0xdb, 0x02,0x19,0x02,0x31,0x00,0x29,0x02,0x1a,0x00,0x05,0x00,0x1d,0x02,0x1a,0x00,0x0a,0x00,0x1d,0x02,0x1a,0x00,0x0f,0xff,0x98,0x02,0x1a,0x00,0x11,0xff,0x7f,0x02,0x1a,0x00,0x22,0xff,0xb2,0x02,0x1a,0x00,0xac,0xff,0x7f,0x02,0x1a,0x00,0xbf,0x00,0x0e,0x02,0x1a,0x00,0xc4,0xff,0x8b,0x02,0x1a,0x00,0xc5,0xff,0x8b,0x02,0x1a,0x02,0x0b, 0xff,0x91,0x02,0x1a,0x02,0x0c,0xff,0xf6,0x02,0x1a,0x02,0x12,0xff,0x91,0x02,0x1a,0x02,0x15,0xff,0xf6,0x02,0x1a,0x02,0x18,0xff,0xf6,0x02,0x1a,0x02,0x19,0x00,0x29,0x02,0x1a,0x02,0x1b,0xff,0xf6,0x02,0x1a,0x02,0x21,0x00,0x29,0x02,0x1a,0x02,0x27,0xff,0xf6,0x02,0x1a,0x02,0x2a,0xff,0xf6,0x02,0x1a,0x02,0x2d,0xff,0x91,0x02,0x1b, 0x00,0x05,0xff,0x6f,0x02,0x1b,0x00,0x0a,0xff,0x6f,0x02,0x1b,0x00,0xb4,0xff,0xb0,0x02,0x1b,0x00,0xb5,0xff,0x7b,0x02,0x1b,0x00,0xb6,0xff,0xbc,0x02,0x1b,0x00,0xb7,0xff,0x7b,0x02,0x1b,0x02,0x07,0xff,0xe5,0x02,0x1b,0x02,0x0b,0xff,0xe7,0x02,0x1b,0x02,0x0d,0xff,0xd7,0x02,0x1b,0x02,0x19,0xff,0xdb,0x02,0x1b,0x02,0x1c,0xff,0xe7, 0x02,0x1b,0x02,0x21,0xff,0xdb,0x02,0x1c,0x02,0x0b,0x00,0x14,0x02,0x1c,0x02,0x0c,0xff,0xee,0x02,0x1c,0x02,0x12,0x00,0x29,0x02,0x1c,0x02,0x15,0xff,0xee,0x02,0x1c,0x02,0x18,0xff,0xee,0x02,0x1c,0x02,0x1b,0xff,0xee,0x02,0x1c,0x02,0x1e,0xff,0xdb,0x02,0x1c,0x02,0x27,0xff,0xee,0x02,0x1c,0x02,0x2a,0xff,0xee,0x02,0x1c,0x02,0x2d, 0x00,0x29,0x02,0x1d,0x02,0x1e,0xff,0xdb,0x02,0x20,0x02,0x1e,0xff,0xdb,0x02,0x21,0x02,0x0c,0xff,0xf4,0x02,0x21,0x02,0x15,0xff,0xf4,0x02,0x21,0x02,0x18,0xff,0xf4,0x02,0x21,0x02,0x19,0xff,0xaa,0x02,0x21,0x02,0x1a,0xff,0xb6,0x02,0x21,0x02,0x1b,0xff,0xf4,0x02,0x21,0x02,0x1e,0xff,0x85,0x02,0x21,0x02,0x21,0xff,0xaa,0x02,0x21, 0x02,0x27,0xff,0xf4,0x02,0x21,0x02,0x2a,0xff,0xf4,0x02,0x21,0x02,0x31,0xff,0xb6,0x02,0x23,0x02,0x0c,0xff,0xf4,0x02,0x23,0x02,0x15,0xff,0xf4,0x02,0x23,0x02,0x18,0xff,0xf4,0x02,0x23,0x02,0x19,0xff,0xaa,0x02,0x23,0x02,0x1a,0xff,0xb6,0x02,0x23,0x02,0x1b,0xff,0xf4,0x02,0x23,0x02,0x1e,0xff,0x85,0x02,0x23,0x02,0x21,0xff,0xaa, 0x02,0x23,0x02,0x27,0xff,0xf4,0x02,0x23,0x02,0x2a,0xff,0xf4,0x02,0x23,0x02,0x31,0xff,0xb6,0x02,0x24,0x00,0x05,0xff,0x6f,0x02,0x24,0x00,0x0a,0xff,0x6f,0x02,0x24,0x00,0xb4,0xff,0xb0,0x02,0x24,0x00,0xb5,0xff,0x7b,0x02,0x24,0x00,0xb6,0xff,0xbc,0x02,0x24,0x00,0xb7,0xff,0x7b,0x02,0x24,0x02,0x07,0xff,0xe5,0x02,0x24,0x02,0x0b, 0xff,0xe7,0x02,0x24,0x02,0x0d,0xff,0xd7,0x02,0x24,0x02,0x19,0xff,0xdb,0x02,0x24,0x02,0x1c,0xff,0xe7,0x02,0x24,0x02,0x21,0xff,0xdb,0x02,0x25,0x00,0x05,0xff,0x6f,0x02,0x25,0x00,0x0a,0xff,0x6f,0x02,0x25,0x00,0xb4,0xff,0xb0,0x02,0x25,0x00,0xb5,0xff,0x7b,0x02,0x25,0x00,0xb6,0xff,0xbc,0x02,0x25,0x00,0xb7,0xff,0x7b,0x02,0x25, 0x02,0x07,0xff,0xe5,0x02,0x25,0x02,0x0b,0xff,0xe7,0x02,0x25,0x02,0x0d,0xff,0xd7,0x02,0x25,0x02,0x19,0xff,0xdb,0x02,0x25,0x02,0x1c,0xff,0xe7,0x02,0x25,0x02,0x21,0xff,0xdb,0x02,0x27,0x00,0x05,0xff,0x98,0x02,0x27,0x00,0x0a,0xff,0x98,0x02,0x28,0x00,0x05,0xff,0x6f,0x02,0x28,0x00,0x0a,0xff,0x6f,0x02,0x28,0x00,0xb4,0xff,0xb0, 0x02,0x28,0x00,0xb5,0xff,0x7b,0x02,0x28,0x00,0xb6,0xff,0xbc,0x02,0x28,0x00,0xb7,0xff,0x7b,0x02,0x28,0x02,0x07,0xff,0xee,0x02,0x28,0x02,0x19,0xff,0xe7,0x02,0x28,0x02,0x1c,0xff,0xee,0x02,0x28,0x02,0x1e,0xff,0xe7,0x02,0x28,0x02,0x21,0xff,0xe7,0x02,0x29,0x00,0x0f,0xff,0xc3,0x02,0x29,0x00,0x11,0xff,0xae,0x02,0x29,0x00,0xac, 0xff,0xae,0x02,0x29,0x02,0x07,0xff,0xc3,0x02,0x29,0x02,0x0b,0xff,0xb6,0x02,0x29,0x02,0x0c,0xff,0xdb,0x02,0x29,0x02,0x12,0xff,0xb6,0x02,0x29,0x02,0x15,0xff,0xdb,0x02,0x29,0x02,0x18,0xff,0xdb,0x02,0x29,0x02,0x19,0x00,0x29,0x02,0x29,0x02,0x1b,0xff,0xdb,0x02,0x29,0x02,0x21,0x00,0x29,0x02,0x29,0x02,0x26,0xff,0xe7,0x02,0x29, 0x02,0x27,0xff,0xdb,0x02,0x29,0x02,0x2a,0xff,0xdb,0x02,0x29,0x02,0x2d,0xff,0xb6,0x02,0x2a,0x01,0xe4,0xff,0xe5,0x02,0x2c,0x02,0x28,0x00,0x52,0x02,0x2c,0x02,0x2f,0x00,0x52,0x02,0x2d,0x02,0x0c,0xff,0xf4,0x02,0x2d,0x02,0x15,0xff,0xf4,0x02,0x2d,0x02,0x18,0xff,0xf4,0x02,0x2d,0x02,0x19,0xff,0xaa,0x02,0x2d,0x02,0x1a,0xff,0xb6, 0x02,0x2d,0x02,0x1b,0xff,0xf4,0x02,0x2d,0x02,0x1e,0xff,0x85,0x02,0x2d,0x02,0x21,0xff,0xaa,0x02,0x2d,0x02,0x27,0xff,0xf4,0x02,0x2d,0x02,0x2a,0xff,0xf4,0x02,0x2d,0x02,0x31,0xff,0xb6,0x02,0x2e,0x02,0x0c,0xff,0xf4,0x02,0x2e,0x02,0x15,0xff,0xf4,0x02,0x2e,0x02,0x18,0xff,0xf4,0x02,0x2e,0x02,0x19,0xff,0xaa,0x02,0x2e,0x02,0x1a, 0xff,0xb6,0x02,0x2e,0x02,0x1b,0xff,0xf4,0x02,0x2e,0x02,0x1e,0xff,0x85,0x02,0x2e,0x02,0x21,0xff,0xaa,0x02,0x2e,0x02,0x27,0xff,0xf4,0x02,0x2e,0x02,0x2a,0xff,0xf4,0x02,0x2e,0x02,0x31,0xff,0xb6,0x02,0x2f,0x00,0x05,0xff,0x98,0x02,0x2f,0x00,0x0a,0xff,0x98,0x02,0x30,0x00,0x0f,0x00,0x52,0x02,0x30,0x00,0x10,0xff,0x73,0x02,0x30, 0x00,0x11,0x00,0x52,0x02,0x30,0x00,0x1d,0x00,0x52,0x02,0x30,0x00,0x1e,0x00,0x52,0x02,0x30,0x00,0xac,0x00,0x52,0x02,0x30,0x02,0x0b,0x00,0x29,0x02,0x30,0x02,0x0c,0xff,0xd7,0x02,0x30,0x02,0x12,0x00,0x3d,0x02,0x30,0x02,0x15,0xff,0xd7,0x02,0x30,0x02,0x18,0xff,0xd7,0x02,0x30,0x02,0x1b,0xff,0xd7,0x02,0x30,0x02,0x1e,0xff,0xe7, 0x02,0x30,0x02,0x27,0xff,0xd7,0x02,0x30,0x02,0x2a,0xff,0xd7,0x02,0x30,0x02,0x2d,0x00,0x3d,0x02,0x31,0x00,0x05,0x00,0x1d,0x02,0x31,0x00,0x0a,0x00,0x1d,0x02,0x31,0x00,0x0f,0xff,0x98,0x02,0x31,0x00,0x11,0xff,0x7f,0x02,0x31,0x00,0x22,0xff,0xb2,0x02,0x31,0x00,0xac,0xff,0x7f,0x02,0x31,0x00,0xbf,0x00,0x0e,0x02,0x31,0x00,0xc4, 0xff,0x8b,0x02,0x31,0x00,0xc5,0xff,0x8b,0x02,0x31,0x02,0x0b,0xff,0x91,0x02,0x31,0x02,0x0c,0xff,0xf6,0x02,0x31,0x02,0x12,0xff,0x91,0x02,0x31,0x02,0x15,0xff,0xf6,0x02,0x31,0x02,0x18,0xff,0xf6,0x02,0x31,0x02,0x19,0x00,0x29,0x02,0x31,0x02,0x1b,0xff,0xf6,0x02,0x31,0x02,0x21,0x00,0x29,0x02,0x31,0x02,0x27,0xff,0xf6,0x02,0x31, 0x02,0x2a,0xff,0xf6,0x02,0x31,0x02,0x2d,0xff,0x91,0x02,0x33,0x01,0xdc,0x00,0x29,0x02,0x33,0x01,0xde,0xff,0xa2,0x02,0x33,0x01,0xe0,0x00,0x2d,0x02,0x33,0x01,0xe1,0xff,0xa2,0x02,0x33,0x01,0xe3,0x00,0x29,0x02,0x33,0x01,0xe5,0x00,0x1d,0x02,0x33,0x01,0xe7,0xff,0x71,0x02,0x33,0x01,0xeb,0xff,0xa2,0x02,0x33,0x01,0xf2,0xff,0xa2, 0x02,0x33,0x01,0xf5,0xff,0xcf,0x02,0x33,0x01,0xf8,0xff,0xcf,0x02,0x33,0x01,0xf9,0x00,0x29,0x02,0x33,0x01,0xfa,0x00,0x1d,0x02,0x33,0x01,0xfb,0xff,0xa2,0x02,0x33,0x02,0x01,0x00,0x29,0x02,0x33,0x02,0x06,0xff,0xe7,0x02,0x33,0x02,0x07,0xff,0x27,0x02,0x33,0x02,0x09,0xff,0x4e,0x02,0x33,0x02,0x0a,0xff,0x4e,0x02,0x33,0x02,0x0b, 0xff,0x9e,0x02,0x33,0x02,0x0c,0xff,0x2b,0x02,0x33,0x02,0x0f,0xff,0x4e,0x02,0x33,0x02,0x10,0xff,0x4e,0x02,0x33,0x02,0x11,0xff,0x4e,0x02,0x33,0x02,0x12,0xff,0x9e,0x02,0x33,0x02,0x13,0xff,0x4e,0x02,0x33,0x02,0x14,0xff,0x4e,0x02,0x33,0x02,0x15,0xff,0x2b,0x02,0x33,0x02,0x16,0xff,0x4e,0x02,0x33,0x02,0x17,0xff,0x4e,0x02,0x33, 0x02,0x18,0xff,0x2b,0x02,0x33,0x02,0x19,0xff,0xc3,0x02,0x33,0x02,0x1b,0xff,0x2b,0x02,0x33,0x02,0x1c,0xff,0x4c,0x02,0x33,0x02,0x1d,0xff,0x4e,0x02,0x33,0x02,0x1e,0xff,0x4e,0x02,0x33,0x02,0x1f,0xff,0x4e,0x02,0x33,0x02,0x20,0xff,0x4e,0x02,0x33,0x02,0x21,0xff,0xc3,0x02,0x33,0x02,0x22,0xff,0x4e,0x02,0x33,0x02,0x23,0xff,0x4e, 0x02,0x33,0x02,0x24,0xff,0x60,0x02,0x33,0x02,0x25,0xff,0x4e,0x02,0x33,0x02,0x26,0xff,0x54,0x02,0x33,0x02,0x27,0xff,0x2b,0x02,0x33,0x02,0x29,0xff,0x4e,0x02,0x33,0x02,0x2a,0xff,0x2b,0x02,0x33,0x02,0x2b,0xff,0x66,0x02,0x33,0x02,0x2c,0x00,0x6f,0x02,0x33,0x02,0x2d,0xff,0x9e,0x02,0x33,0x02,0x2e,0xff,0x4e,0x02,0x33,0x02,0x32, 0xff,0x4e,0x02,0x33,0x02,0x34,0xff,0x4e,0x02,0x34,0x00,0x0f,0xff,0xc3,0x02,0x34,0x00,0x11,0xff,0xae,0x02,0x34,0x00,0xac,0xff,0xae,0x02,0x34,0x02,0x07,0xff,0xc3,0x02,0x34,0x02,0x0b,0xff,0xb6,0x02,0x34,0x02,0x0c,0xff,0xdb,0x02,0x34,0x02,0x12,0xff,0xb6,0x02,0x34,0x02,0x15,0xff,0xdb,0x02,0x34,0x02,0x18,0xff,0xdb,0x02,0x34, 0x02,0x19,0x00,0x29,0x02,0x34,0x02,0x1b,0xff,0xdb,0x02,0x34,0x02,0x21,0x00,0x29,0x02,0x34,0x02,0x26,0xff,0xe7,0x02,0x34,0x02,0x27,0xff,0xdb,0x02,0x34,0x02,0x2a,0xff,0xdb,0x02,0x34,0x02,0x2c,0x00,0x52,0x02,0x34,0x02,0x2d,0xff,0xb6,0x02,0x37,0x01,0x33,0x00,0x19,0x02,0x37,0x01,0xc5,0x00,0x29,0x02,0x37,0x02,0x37,0x00,0x19, 0x02,0x3d,0x00,0x57,0xff,0xbe,0x02,0x3d,0x00,0x59,0xff,0xcf,0x02,0x3d,0x00,0x5a,0xff,0xe5,0x02,0x3d,0x00,0x5c,0xff,0xd1,0x02,0x3d,0x00,0xba,0xff,0xbe,0x02,0x3d,0x00,0xc4,0xff,0xb2,0x02,0x3d,0x00,0xc5,0xff,0xb2,0x02,0x3d,0x00,0xeb,0xff,0xd1,0x02,0x3d,0x01,0x21,0xff,0xbe,0x02,0x3d,0x01,0x23,0xff,0xbe,0x02,0x3d,0x01,0x77, 0xff,0xbe,0x02,0x3d,0x01,0x81,0xff,0xe5,0x02,0x3d,0x01,0x83,0xff,0xd1,0x02,0x3d,0x01,0x8d,0xff,0xe5,0x02,0x3d,0x01,0x8f,0xff,0xe5,0x02,0x3d,0x01,0x91,0xff,0xe5,0x02,0x3d,0x01,0x93,0xff,0xd1,0x00,0x00,0x00,0x00,0x00,0x30,0x02,0x46,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x14,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00, 0x00,0x01,0x00,0x10,0x02,0x14,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x0e,0x02,0x24,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x20,0x02,0x32,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x10,0x02,0x14,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x18,0x02,0x52,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x06,0x00,0x0e, 0x02,0x6a,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x72,0x02,0x78,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x2a,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x56,0x02,0xea,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0d,0x0e,0x04,0x03,0x40,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0e,0x00,0x56,0x02,0xea,0x00,0x03, 0x00,0x01,0x04,0x03,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x05,0x00,0x02,0x00,0x10,0x11,0x50,0x00,0x03,0x00,0x01,0x04,0x06,0x00,0x02,0x00,0x0c,0x11,0x60,0x00,0x03,0x00,0x01,0x04,0x07,0x00,0x02,0x00,0x10,0x11,0x6c,0x00,0x03,0x00,0x01,0x04,0x08,0x00,0x02,0x00,0x10,0x11,0x7c,0x00,0x03,0x00,0x01,0x04,0x09, 0x00,0x00,0x02,0x18,0x11,0x8c,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x01,0x00,0x10,0x02,0x14,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x02,0x00,0x0e,0x02,0x24,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x03,0x00,0x20,0x02,0x32,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x04,0x00,0x10,0x02,0x14,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x05,0x00,0x18, 0x02,0x52,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x06,0x00,0x0e,0x02,0x6a,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x07,0x00,0x72,0x02,0x78,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x08,0x00,0x2a,0x00,0x0e,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0b,0x00,0x56,0x02,0xea,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0d,0x0e,0x18,0x13,0xa4,0x00,0x03, 0x00,0x01,0x04,0x09,0x00,0x0e,0x00,0x4a,0x02,0xea,0x00,0x03,0x00,0x01,0x04,0x0a,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x0b,0x00,0x02,0x00,0x10,0x21,0xbc,0x00,0x03,0x00,0x01,0x04,0x0c,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x0e,0x00,0x02,0x00,0x0c,0x21,0xcc,0x00,0x03,0x00,0x01,0x04,0x10, 0x00,0x02,0x00,0x0e,0x21,0xd8,0x00,0x03,0x00,0x01,0x04,0x13,0x00,0x02,0x00,0x12,0x21,0xe6,0x00,0x03,0x00,0x01,0x04,0x14,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x15,0x00,0x02,0x00,0x10,0x21,0xf8,0x00,0x03,0x00,0x01,0x04,0x16,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x19,0x00,0x02,0x00,0x0e, 0x22,0x08,0x00,0x03,0x00,0x01,0x04,0x1b,0x00,0x02,0x00,0x10,0x22,0x16,0x00,0x03,0x00,0x01,0x04,0x1d,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x1f,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x04,0x24,0x00,0x02,0x00,0x0e,0x22,0x26,0x00,0x03,0x00,0x01,0x04,0x2d,0x00,0x02,0x00,0x0e,0x22,0x34,0x00,0x03, 0x00,0x01,0x08,0x0a,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x08,0x16,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x0c,0x0a,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0x03,0x00,0x01,0x0c,0x0c,0x00,0x02,0x00,0x0c,0x11,0x44,0x00,0xa9,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x31,0x00,0x38,0x00,0x20,0x00,0x4d,0x00,0x69, 0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,0x00,0x43,0x00,0x6f,0x00,0x72,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x41,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x52,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x73,0x00,0x20, 0x00,0x52,0x00,0x65,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x76,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x20,0x00,0x0d,0x00,0x0d,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f, 0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0xa9,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30,0x00,0x33,0x00,0x20,0x00,0x26,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30,0x00,0x37, 0x00,0x2c,0x00,0x20,0x00,0x52,0x00,0x61,0x00,0x6c,0x00,0x70,0x00,0x68,0x00,0x20,0x00,0x48,0x00,0x61,0x00,0x6e,0x00,0x63,0x00,0x6f,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x26,0x00,0x20,0x00,0x4a,0x00,0x6f,0x00,0x68,0x00,0x6e,0x00,0x20,0x00,0x48,0x00,0x75,0x00,0x64,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x54, 0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48,0x00,0x65, 0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x75,0x00,0x72,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x75,0x00,0x6e,0x00,0x64, 0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x20,0x00,0x4c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x3b,0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x65,0x00,0x20,0x00,0x65,0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x64,0x00,0x65,0x00,0x64, 0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x74,0x00,0x61,0x00,0x69,0x00,0x6c,0x00,0x73, 0x00,0x2e,0x00,0x53,0x00,0x65,0x00,0x67,0x00,0x6f,0x00,0x65,0x00,0x20,0x00,0x55,0x00,0x49,0x00,0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72,0x00,0x53,0x00,0x65,0x00,0x67,0x00,0x6f,0x00,0x65,0x00,0x20,0x00,0x55,0x00,0x49,0x00,0x20,0x00,0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72, 0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x35,0x00,0x2e,0x00,0x36,0x00,0x32,0x00,0x53,0x00,0x65,0x00,0x67,0x00,0x6f,0x00,0x65,0x00,0x55,0x00,0x49,0x00,0x53,0x00,0x65,0x00,0x67,0x00,0x6f,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x74,0x00,0x72, 0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x6d,0x00,0x61,0x00,0x72,0x00,0x6b,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,0x00,0x67,0x00,0x72,0x00,0x6f,0x00,0x75,0x00,0x70,0x00,0x20,0x00,0x6f, 0x00,0x66,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x70,0x00,0x61,0x00,0x6e,0x00,0x69,0x00,0x65,0x00,0x73,0x00,0x2e,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x64,0x00,0x6f,0x00,0x63,0x00,0x73,0x00,0x2e,0x00,0x6d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f, 0x00,0x66,0x00,0x74,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x2f,0x00,0x74,0x00,0x79,0x00,0x70,0x00,0x6f,0x00,0x67,0x00,0x72,0x00,0x61,0x00,0x70,0x00,0x68,0x00,0x79,0x00,0x2f,0x00,0x61,0x00,0x62,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74, 0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x70,0x00,0x70,0x00,0x6c,0x00,0x69,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x2e,0x00,0x20,0x00,0x59,0x00,0x6f,0x00,0x75,0x00,0x20,0x00,0x6d,0x00,0x61,0x00,0x79,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73, 0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x63,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x64,0x00,0x69,0x00,0x73,0x00,0x70,0x00,0x6c,0x00,0x61,0x00,0x79,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x70,0x00,0x72, 0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20, 0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x6f, 0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65, 0x00,0x2c,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x77,0x00,0x68,0x00,0x69,0x00,0x63,0x00,0x68,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20, 0x00,0x77,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x20,0x00,0x59,0x00,0x6f,0x00,0x75,0x00,0x20,0x00,0x6d,0x00,0x61,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x6e,0x00,0x6c,0x00,0x79,0x00,0x20,0x00,0x28,0x00,0x69,0x00,0x29,0x00,0x20,0x00,0x65, 0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72, 0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x65,0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x64,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x63,0x00,0x74, 0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x3b,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20, 0x00,0x28,0x00,0x69,0x00,0x69,0x00,0x29,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x72,0x00,0x69,0x00,0x6c,0x00,0x79,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x6e,0x00,0x6c,0x00,0x6f,0x00,0x61,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66, 0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x70,0x00,0x75,0x00,0x74, 0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x70,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x2e,0x00,0x20,0x00,0x41, 0x00,0x6e,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x68,0x00,0x69,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x0d,0x00,0x0d,0x00,0x54,0x00,0x68,0x00,0x65, 0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x62,0x00,0x61,0x00,0x73,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65, 0x00,0x20,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x28,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x65,0x00,0x6e,0x00,0x2e,0x00,0x77,0x00,0x69,0x00,0x6b,0x00,0x69,0x00,0x70,0x00,0x65,0x00,0x64,0x00,0x69, 0x00,0x61,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,0x6b,0x00,0x69,0x00,0x2f,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x5f,0x00,0x4c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x29,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x70,0x00,0x70,0x00,0x6c,0x00,0x69,0x00,0x65,0x00,0x73, 0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f, 0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x20,0x1c,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x20,0x1d, 0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x6a,0x00,0x6f,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x6c,0x00,0x79,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x76,0x00,0x65,0x00,0x6c,0x00,0x6f,0x00,0x70,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x52,0x00,0x61,0x00,0x6c,0x00,0x70,0x00,0x68,0x00,0x20,0x00,0x48, 0x00,0x61,0x00,0x6e,0x00,0x63,0x00,0x6f,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x4a,0x00,0x6f,0x00,0x68,0x00,0x6e,0x00,0x20,0x00,0x48,0x00,0x75,0x00,0x64,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x0d,0x00,0x0d,0x00,0x50,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x73, 0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x65,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x67,0x00,0x72,0x00,0x61,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x2c,0x00,0x20,0x00,0x66,0x00,0x72,0x00,0x65,0x00,0x65,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20, 0x00,0x63,0x00,0x68,0x00,0x61,0x00,0x72,0x00,0x67,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x79,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x6f,0x00,0x62,0x00,0x74,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20, 0x00,0x61,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f, 0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x73,0x00,0x6f, 0x00,0x63,0x00,0x69,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x63,0x00,0x75,0x00,0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x66,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x28,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20, 0x20,0x1c,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x20,0x1d,0x00,0x29,0x00,0x2c,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x61, 0x00,0x6c,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x77, 0x00,0x69,0x00,0x74,0x00,0x68,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x2c,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x77,0x00,0x69, 0x00,0x74,0x00,0x68,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x73,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x75, 0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x2c,0x00,0x20,0x00,0x6d,0x00,0x6f,0x00,0x64,0x00,0x69,0x00,0x66,0x00,0x79,0x00,0x2c,0x00,0x20,0x00,0x6d,0x00,0x65,0x00,0x72,0x00,0x67,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x70,0x00,0x75,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x73,0x00,0x68, 0x00,0x2c,0x00,0x20,0x00,0x64,0x00,0x69,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x62,0x00,0x75,0x00,0x74,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x2f,0x00,0x6f,0x00,0x72, 0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x69,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63, 0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x73, 0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x77,0x00,0x68,0x00,0x6f,0x00,0x6d,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61, 0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x75,0x00,0x72,0x00,0x6e,0x00,0x69,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x6a,0x00,0x65,0x00,0x63, 0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x64,0x00,0x69,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x3a,0x00,0x0d,0x00,0x0d, 0x00,0x54,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x61,0x00,0x62,0x00,0x6f,0x00,0x76,0x00,0x65,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x74, 0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x73,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x68,0x00,0x61,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x62,0x00,0x65,0x00,0x20,0x00,0x69, 0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x61,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x69,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x73,0x00,0x74,0x00,0x61,0x00,0x6e, 0x00,0x74,0x00,0x69,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69, 0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x2e,0x00,0x0d,0x00,0x0d,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46,0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x20,0x00,0x49,0x00,0x53,0x00,0x20,0x00,0x50,0x00,0x52,0x00,0x4f, 0x00,0x56,0x00,0x49,0x00,0x44,0x00,0x45,0x00,0x44,0x00,0x20,0x00,0x27,0x00,0x41,0x00,0x53,0x00,0x20,0x00,0x49,0x00,0x53,0x00,0x27,0x00,0x2c,0x00,0x20,0x00,0x57,0x00,0x49,0x00,0x54,0x00,0x48,0x00,0x4f,0x00,0x55,0x00,0x54,0x00,0x20,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x52,0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x59,0x00,0x20, 0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x59,0x00,0x20,0x00,0x4b,0x00,0x49,0x00,0x4e,0x00,0x44,0x00,0x2c,0x00,0x20,0x00,0x45,0x00,0x58,0x00,0x50,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x49,0x00,0x4d,0x00,0x50,0x00,0x4c,0x00,0x49,0x00,0x45,0x00,0x44,0x00,0x2c, 0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x43,0x00,0x4c,0x00,0x55,0x00,0x44,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x20,0x00,0x42,0x00,0x55,0x00,0x54,0x00,0x20,0x00,0x4e,0x00,0x4f,0x00,0x54,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x45,0x00,0x44,0x00,0x20,0x00,0x54,0x00,0x4f,0x00,0x20,0x00,0x54,0x00,0x48, 0x00,0x45,0x00,0x20,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x52,0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x49,0x00,0x45,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x4d,0x00,0x45,0x00,0x52,0x00,0x43,0x00,0x48,0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x41,0x00,0x42,0x00,0x49,0x00,0x4c,0x00,0x49,0x00,0x54,0x00,0x59,0x00,0x2c, 0x00,0x20,0x00,0x46,0x00,0x49,0x00,0x54,0x00,0x4e,0x00,0x45,0x00,0x53,0x00,0x53,0x00,0x20,0x00,0x46,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x41,0x00,0x20,0x00,0x50,0x00,0x41,0x00,0x52,0x00,0x54,0x00,0x49,0x00,0x43,0x00,0x55,0x00,0x4c,0x00,0x41,0x00,0x52,0x00,0x20,0x00,0x50,0x00,0x55,0x00,0x52,0x00,0x50,0x00,0x4f,0x00,0x53, 0x00,0x45,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x44,0x00,0x20,0x00,0x4e,0x00,0x4f,0x00,0x4e,0x00,0x49,0x00,0x4e,0x00,0x46,0x00,0x52,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x45,0x00,0x4d,0x00,0x45,0x00,0x4e,0x00,0x54,0x00,0x2e,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x4e,0x00,0x4f,0x00,0x20,0x00,0x45,0x00,0x56,0x00,0x45, 0x00,0x4e,0x00,0x54,0x00,0x20,0x00,0x53,0x00,0x48,0x00,0x41,0x00,0x4c,0x00,0x4c,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x41,0x00,0x55,0x00,0x54,0x00,0x48,0x00,0x4f,0x00,0x52,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x50,0x00,0x59,0x00,0x52,0x00,0x49,0x00,0x47,0x00,0x48, 0x00,0x54,0x00,0x20,0x00,0x48,0x00,0x4f,0x00,0x4c,0x00,0x44,0x00,0x45,0x00,0x52,0x00,0x53,0x00,0x20,0x00,0x42,0x00,0x45,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x41,0x00,0x42,0x00,0x4c,0x00,0x45,0x00,0x20,0x00,0x46,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x59,0x00,0x20,0x00,0x43,0x00,0x4c,0x00,0x41,0x00,0x49, 0x00,0x4d,0x00,0x2c,0x00,0x20,0x00,0x44,0x00,0x41,0x00,0x4d,0x00,0x41,0x00,0x47,0x00,0x45,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x41,0x00,0x42,0x00,0x49,0x00,0x4c,0x00,0x49,0x00,0x54,0x00,0x59,0x00,0x2c,0x00,0x20,0x00,0x57, 0x00,0x48,0x00,0x45,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x20,0x00,0x41,0x00,0x43,0x00,0x54,0x00,0x49,0x00,0x4f,0x00,0x4e,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x4e,0x00,0x54,0x00,0x52,0x00,0x41,0x00,0x43,0x00,0x54,0x00,0x2c, 0x00,0x20,0x00,0x54,0x00,0x4f,0x00,0x52,0x00,0x54,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x57,0x00,0x49,0x00,0x53,0x00,0x45,0x00,0x2c,0x00,0x20,0x00,0x41,0x00,0x52,0x00,0x49,0x00,0x53,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x20,0x00,0x46,0x00,0x52,0x00,0x4f,0x00,0x4d, 0x00,0x2c,0x00,0x20,0x00,0x4f,0x00,0x55,0x00,0x54,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x4e,0x00,0x4e,0x00,0x45,0x00,0x43,0x00,0x54,0x00,0x49,0x00,0x4f,0x00,0x4e,0x00,0x20,0x00,0x57,0x00,0x49,0x00,0x54,0x00,0x48,0x00,0x20,0x00,0x54, 0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46,0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x55,0x00,0x53,0x00,0x45,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x20, 0x00,0x44,0x00,0x45,0x00,0x41,0x00,0x4c,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x53,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46,0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x2e,0x00,0x4e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x6c,0x00,0x6f, 0x00,0x62,0x00,0x79,0x01,0x0d,0x00,0x65,0x00,0x6a,0x00,0x6e,0x00,0xe9,0x00,0x6e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x6c,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x61,0x00,0x72,0x00,0x64,0x03,0x9a,0x03,0xb1,0x03,0xbd,0x03,0xbf,0x03,0xbd,0x03,0xb9,0x03,0xba,0x03,0xac,0x00,0xa9,0x00,0x20,0x00,0x32, 0x00,0x30,0x00,0x31,0x00,0x38,0x00,0x20,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,0x00,0x43,0x00,0x6f,0x00,0x72,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x41,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x52, 0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x73,0x00,0x20,0x00,0x52,0x00,0x65,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x76,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x20,0x00,0x0d,0x00,0x0a,0x00,0x0d,0x00,0x0a,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x54, 0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0xa9,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30, 0x00,0x33,0x00,0x20,0x00,0x26,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x30,0x00,0x37,0x00,0x2c,0x00,0x20,0x00,0x52,0x00,0x61,0x00,0x6c,0x00,0x70,0x00,0x68,0x00,0x20,0x00,0x48,0x00,0x61,0x00,0x6e,0x00,0x63,0x00,0x6f,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x26,0x00,0x20,0x00,0x4a,0x00,0x6f,0x00,0x68,0x00,0x6e,0x00,0x20,0x00,0x48, 0x00,0x75,0x00,0x64,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69,0x00,0x62, 0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x75,0x00,0x72,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74, 0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x75,0x00,0x6e,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x20,0x00,0x4c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x3b,0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x65,0x00,0x20, 0x00,0x65,0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72, 0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x74,0x00,0x61,0x00,0x69,0x00,0x6c,0x00,0x73,0x00,0x2e,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x70,0x00,0x70,0x00,0x6c,0x00,0x69,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74, 0x00,0x2e,0x00,0x20,0x00,0x59,0x00,0x6f,0x00,0x75,0x00,0x20,0x00,0x6d,0x00,0x61,0x00,0x79,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x63,0x00,0x72,0x00,0x65,0x00,0x61,0x00,0x74, 0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x64,0x00,0x69,0x00,0x73,0x00,0x70,0x00,0x6c,0x00,0x61,0x00,0x79,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x61,0x00,0x73, 0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x73,0x00,0x20, 0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66, 0x00,0x74,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x64,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x69, 0x00,0x6e,0x00,0x20,0x00,0x77,0x00,0x68,0x00,0x69,0x00,0x63,0x00,0x68,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x77,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x20, 0x00,0x59,0x00,0x6f,0x00,0x75,0x00,0x20,0x00,0x6d,0x00,0x61,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x6e,0x00,0x6c,0x00,0x79,0x00,0x20,0x00,0x28,0x00,0x69,0x00,0x29,0x00,0x20,0x00,0x65,0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74, 0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20, 0x00,0x65,0x00,0x6d,0x00,0x62,0x00,0x65,0x00,0x64,0x00,0x64,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x20, 0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x3b,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x28,0x00,0x69,0x00,0x69,0x00,0x29,0x00,0x20,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x72,0x00,0x69, 0x00,0x6c,0x00,0x79,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x6e,0x00,0x6c,0x00,0x6f,0x00,0x61,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x74, 0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x70,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x68,0x00,0x65,0x00,0x6c, 0x00,0x70,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x2e,0x00,0x20,0x00,0x41,0x00,0x6e,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x69, 0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x72,0x00,0x6f,0x00,0x68,0x00,0x69,0x00,0x62,0x00,0x69,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x2e,0x00,0x0d,0x00,0x0a,0x00,0x0d,0x00,0x0a,0x00,0x54,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x6c, 0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x62,0x00,0x61,0x00,0x73,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65, 0x00,0x20,0x00,0x28,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x65,0x00,0x6e,0x00,0x2e,0x00,0x77,0x00,0x69,0x00,0x6b,0x00,0x69,0x00,0x70,0x00,0x65,0x00,0x64,0x00,0x69,0x00,0x61,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,0x6b,0x00,0x69,0x00,0x2f,0x00,0x4d, 0x00,0x49,0x00,0x54,0x00,0x5f,0x00,0x4c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x29,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x70,0x00,0x70,0x00,0x6c,0x00,0x69,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e, 0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48, 0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x20,0x1c,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x20,0x1d,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x6a,0x00,0x6f,0x00,0x69,0x00,0x6e,0x00,0x74,0x00,0x6c,0x00,0x79,0x00,0x20, 0x00,0x64,0x00,0x65,0x00,0x76,0x00,0x65,0x00,0x6c,0x00,0x6f,0x00,0x70,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x52,0x00,0x61,0x00,0x6c,0x00,0x70,0x00,0x68,0x00,0x20,0x00,0x48,0x00,0x61,0x00,0x6e,0x00,0x63,0x00,0x6f,0x00,0x63,0x00,0x6b,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x4a, 0x00,0x6f,0x00,0x68,0x00,0x6e,0x00,0x20,0x00,0x48,0x00,0x75,0x00,0x64,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x2e,0x00,0x20,0x00,0x0d,0x00,0x0a,0x00,0x0d,0x00,0x0a,0x00,0x50,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x73,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x68,0x00,0x65, 0x00,0x72,0x00,0x65,0x00,0x62,0x00,0x79,0x00,0x20,0x00,0x67,0x00,0x72,0x00,0x61,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x2c,0x00,0x20,0x00,0x66,0x00,0x72,0x00,0x65,0x00,0x65,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x63,0x00,0x68,0x00,0x61,0x00,0x72,0x00,0x67,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x74,0x00,0x6f, 0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x79,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x6f,0x00,0x62,0x00,0x74,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20, 0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x54,0x00,0x79,0x00,0x70,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x42,0x00,0x69, 0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x48,0x00,0x65,0x00,0x62,0x00,0x72,0x00,0x65,0x00,0x77,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x61,0x00,0x73,0x00,0x73,0x00,0x6f,0x00,0x63,0x00,0x69,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x63, 0x00,0x75,0x00,0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x66,0x00,0x69,0x00,0x6c,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x28,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x20,0x1c,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f, 0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x20,0x1d,0x00,0x29,0x00,0x2c,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x64,0x00,0x65,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c, 0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x77,0x00,0x69,0x00,0x74,0x00,0x68,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x72,0x00,0x65,0x00,0x73, 0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x2c,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x77,0x00,0x69,0x00,0x74,0x00,0x68,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x6d,0x00,0x69, 0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x73,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x75,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x2c,0x00,0x20, 0x00,0x6d,0x00,0x6f,0x00,0x64,0x00,0x69,0x00,0x66,0x00,0x79,0x00,0x2c,0x00,0x20,0x00,0x6d,0x00,0x65,0x00,0x72,0x00,0x67,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x70,0x00,0x75,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x73,0x00,0x68,0x00,0x2c,0x00,0x20,0x00,0x64,0x00,0x69,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x62,0x00,0x75, 0x00,0x74,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x2f,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x73,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x69, 0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x2c, 0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d,0x00,0x69,0x00,0x74,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x77,0x00,0x68,0x00,0x6f,0x00,0x6d,0x00,0x20,0x00,0x74, 0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x66,0x00,0x75,0x00,0x72,0x00,0x6e, 0x00,0x69,0x00,0x73,0x00,0x68,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x64,0x00,0x6f,0x00,0x20,0x00,0x73,0x00,0x6f,0x00,0x2c,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x6a,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x74,0x00,0x6f,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x66, 0x00,0x6f,0x00,0x6c,0x00,0x6c,0x00,0x6f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x64,0x00,0x69,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x3a,0x00,0x0d,0x00,0x0a,0x00,0x0d,0x00,0x0a,0x00,0x54,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x61,0x00,0x62,0x00,0x6f,0x00,0x76, 0x00,0x65,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x70,0x00,0x65,0x00,0x72,0x00,0x6d, 0x00,0x69,0x00,0x73,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x73,0x00,0x68,0x00,0x61,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x62,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x6e,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x64,0x00,0x65,0x00,0x64,0x00,0x20, 0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x61,0x00,0x6c,0x00,0x6c,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x70,0x00,0x69,0x00,0x65,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x72,0x00,0x20,0x00,0x73,0x00,0x75,0x00,0x62,0x00,0x73,0x00,0x74,0x00,0x61,0x00,0x6e,0x00,0x74,0x00,0x69,0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x70,0x00,0x6f,0x00,0x72, 0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4c,0x00,0x61,0x00,0x79,0x00,0x6f,0x00,0x75,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x6f,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61, 0x00,0x72,0x00,0x65,0x00,0x2e,0x00,0x0d,0x00,0x0a,0x00,0x0d,0x00,0x0a,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46,0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x20,0x00,0x49,0x00,0x53,0x00,0x20,0x00,0x50,0x00,0x52,0x00,0x4f,0x00,0x56,0x00,0x49,0x00,0x44,0x00,0x45,0x00,0x44,0x00,0x20, 0x00,0x27,0x00,0x41,0x00,0x53,0x00,0x20,0x00,0x49,0x00,0x53,0x00,0x27,0x00,0x2c,0x00,0x20,0x00,0x57,0x00,0x49,0x00,0x54,0x00,0x48,0x00,0x4f,0x00,0x55,0x00,0x54,0x00,0x20,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x52,0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x59,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x59, 0x00,0x20,0x00,0x4b,0x00,0x49,0x00,0x4e,0x00,0x44,0x00,0x2c,0x00,0x20,0x00,0x45,0x00,0x58,0x00,0x50,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x49,0x00,0x4d,0x00,0x50,0x00,0x4c,0x00,0x49,0x00,0x45,0x00,0x44,0x00,0x2c,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x43,0x00,0x4c,0x00,0x55, 0x00,0x44,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x20,0x00,0x42,0x00,0x55,0x00,0x54,0x00,0x20,0x00,0x4e,0x00,0x4f,0x00,0x54,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x4d,0x00,0x49,0x00,0x54,0x00,0x45,0x00,0x44,0x00,0x20,0x00,0x54,0x00,0x4f,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x52, 0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x49,0x00,0x45,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x4d,0x00,0x45,0x00,0x52,0x00,0x43,0x00,0x48,0x00,0x41,0x00,0x4e,0x00,0x54,0x00,0x41,0x00,0x42,0x00,0x49,0x00,0x4c,0x00,0x49,0x00,0x54,0x00,0x59,0x00,0x2c,0x00,0x20,0x00,0x46,0x00,0x49,0x00,0x54,0x00,0x4e,0x00,0x45, 0x00,0x53,0x00,0x53,0x00,0x20,0x00,0x46,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x41,0x00,0x20,0x00,0x50,0x00,0x41,0x00,0x52,0x00,0x54,0x00,0x49,0x00,0x43,0x00,0x55,0x00,0x4c,0x00,0x41,0x00,0x52,0x00,0x20,0x00,0x50,0x00,0x55,0x00,0x52,0x00,0x50,0x00,0x4f,0x00,0x53,0x00,0x45,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x44,0x00,0x20, 0x00,0x4e,0x00,0x4f,0x00,0x4e,0x00,0x49,0x00,0x4e,0x00,0x46,0x00,0x52,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x45,0x00,0x4d,0x00,0x45,0x00,0x4e,0x00,0x54,0x00,0x2e,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x4e,0x00,0x4f,0x00,0x20,0x00,0x45,0x00,0x56,0x00,0x45,0x00,0x4e,0x00,0x54,0x00,0x20,0x00,0x53,0x00,0x48,0x00,0x41, 0x00,0x4c,0x00,0x4c,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x41,0x00,0x55,0x00,0x54,0x00,0x48,0x00,0x4f,0x00,0x52,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x50,0x00,0x59,0x00,0x52,0x00,0x49,0x00,0x47,0x00,0x48,0x00,0x54,0x00,0x20,0x00,0x48,0x00,0x4f,0x00,0x4c,0x00,0x44, 0x00,0x45,0x00,0x52,0x00,0x53,0x00,0x20,0x00,0x42,0x00,0x45,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x41,0x00,0x42,0x00,0x4c,0x00,0x45,0x00,0x20,0x00,0x46,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x59,0x00,0x20,0x00,0x43,0x00,0x4c,0x00,0x41,0x00,0x49,0x00,0x4d,0x00,0x2c,0x00,0x20,0x00,0x44,0x00,0x41,0x00,0x4d, 0x00,0x41,0x00,0x47,0x00,0x45,0x00,0x53,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x20,0x00,0x4c,0x00,0x49,0x00,0x41,0x00,0x42,0x00,0x49,0x00,0x4c,0x00,0x49,0x00,0x54,0x00,0x59,0x00,0x2c,0x00,0x20,0x00,0x57,0x00,0x48,0x00,0x45,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52, 0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x41,0x00,0x4e,0x00,0x20,0x00,0x41,0x00,0x43,0x00,0x54,0x00,0x49,0x00,0x4f,0x00,0x4e,0x00,0x20,0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x4e,0x00,0x54,0x00,0x52,0x00,0x41,0x00,0x43,0x00,0x54,0x00,0x2c,0x00,0x20,0x00,0x54,0x00,0x4f,0x00,0x52,0x00,0x54,0x00,0x20, 0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x57,0x00,0x49,0x00,0x53,0x00,0x45,0x00,0x2c,0x00,0x20,0x00,0x41,0x00,0x52,0x00,0x49,0x00,0x53,0x00,0x49,0x00,0x4e,0x00,0x47,0x00,0x20,0x00,0x46,0x00,0x52,0x00,0x4f,0x00,0x4d,0x00,0x2c,0x00,0x20,0x00,0x4f,0x00,0x55,0x00,0x54,0x00,0x20, 0x00,0x4f,0x00,0x46,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x43,0x00,0x4f,0x00,0x4e,0x00,0x4e,0x00,0x45,0x00,0x43,0x00,0x54,0x00,0x49,0x00,0x4f,0x00,0x4e,0x00,0x20,0x00,0x57,0x00,0x49,0x00,0x54,0x00,0x48,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46, 0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x55,0x00,0x53,0x00,0x45,0x00,0x20,0x00,0x4f,0x00,0x52,0x00,0x20,0x00,0x4f,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x52,0x00,0x20,0x00,0x44,0x00,0x45,0x00,0x41,0x00,0x4c,0x00,0x49,0x00,0x4e, 0x00,0x47,0x00,0x53,0x00,0x20,0x00,0x49,0x00,0x4e,0x00,0x20,0x00,0x54,0x00,0x48,0x00,0x45,0x00,0x20,0x00,0x53,0x00,0x4f,0x00,0x46,0x00,0x54,0x00,0x57,0x00,0x41,0x00,0x52,0x00,0x45,0x00,0x2e,0x00,0x0d,0x00,0x0a,0x00,0x4e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x61,0x00,0x6c,0x00,0x69,0x00,0x4e,0x00,0x6f,0x00,0x72, 0x00,0x6d,0x00,0xe1,0x00,0x6c,0x00,0x4e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x6c,0x00,0x65,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x6e,0x00,0x64,0x00,0x61,0x00,0x61,0x00,0x72,0x00,0x64,0x00,0x4e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x6c,0x00,0x6e,0x00,0x79,0x04,0x1e,0x04,0x31,0x04,0x4b,0x04,0x47,0x04,0x3d, 0x04,0x4b,0x04,0x39,0x00,0x4e,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0xe1,0x00,0x6c,0x00,0x6e,0x00,0x65,0x00,0x4e,0x00,0x61,0x00,0x76,0x00,0x61,0x00,0x64,0x00,0x6e,0x00,0x6f,0x00,0x41,0x00,0x72,0x00,0x72,0x00,0x75,0x00,0x6e,0x00,0x74,0x00,0x61,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x4e,0x00,0x77,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x08,0x00,0x0a,0x00,0x13,0x00,0x07,0xff,0xff,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x23,0x8a,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x82,0x30,0x82,0x23,0x7e, 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x82,0x23,0x6f,0x30,0x82,0x23,0x6b,0x02,0x01,0x01,0x31,0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x30,0x71,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x04,0xa0,0x63,0x30,0x61,0x30,0x2c,0x06,0x0a,0x2b,0x06,0x01, 0x04,0x01,0x82,0x37,0x02,0x01,0x1c,0xa2,0x1e,0x80,0x1c,0x00,0x3c,0x00,0x3c,0x00,0x3c,0x00,0x4f,0x00,0x62,0x00,0x73,0x00,0x6f,0x00,0x6c,0x00,0x65,0x00,0x74,0x00,0x65,0x00,0x3e,0x00,0x3e,0x00,0x3e,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20,0xd1,0x66,0x06,0x5e,0x25,0x40, 0xdd,0x89,0xdd,0x33,0x17,0x38,0x13,0xf4,0x79,0x7b,0x24,0x66,0x3e,0x9d,0x0d,0xef,0x96,0x4e,0xe9,0x40,0xb6,0xb7,0x21,0xab,0x14,0x43,0xa0,0x82,0x0d,0x81,0x30,0x82,0x05,0xff,0x30,0x82,0x03,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x13,0x33,0x00,0x00,0x01,0x03,0x5e,0x25,0x1c,0x99,0x1f,0xa3,0x1e,0xb8,0x00,0x00,0x00,0x00,0x01,0x03, 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x7e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65, 0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1f,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x64,0x65,0x20,0x53, 0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x31,0x30,0x1e,0x17,0x0d,0x31,0x38,0x30,0x37,0x31,0x32,0x32,0x30,0x30,0x38,0x34,0x38,0x5a,0x17,0x0d,0x31,0x39,0x30,0x37,0x32,0x36,0x32,0x30,0x30,0x38,0x34,0x38,0x5a,0x30,0x74,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72, 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x03,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01, 0x0a,0x02,0x82,0x01,0x01,0x00,0xd1,0x94,0x76,0x36,0xe6,0x86,0xab,0x36,0xfe,0x69,0xf9,0x46,0x7c,0x8b,0x88,0x50,0xcb,0x90,0x70,0x7f,0xb0,0x55,0xa9,0x24,0x1d,0x7e,0x39,0xe7,0x05,0x9f,0x0f,0xac,0x7b,0x97,0xb2,0xce,0x73,0x0a,0xfb,0xd4,0x9b,0x24,0x5c,0x16,0xb5,0x39,0xdd,0x1b,0x7e,0x33,0x6c,0x11,0xfc,0x3b,0x26,0xf3,0x98,0xaa, 0x5d,0x53,0x6b,0xaa,0xc3,0xec,0x13,0xb8,0xd2,0xef,0xcf,0x57,0x7f,0xcc,0x65,0xcb,0xaf,0x4d,0x2e,0x32,0xb1,0x56,0x2b,0x4e,0x34,0x07,0x89,0xfe,0x69,0x21,0xbd,0x3e,0x44,0xfb,0xde,0x12,0x9d,0x85,0xbf,0x7c,0x76,0x86,0x7d,0x72,0xb1,0x76,0x9b,0x61,0xe6,0x8a,0x64,0x4c,0x46,0xce,0xb6,0xd5,0x3a,0x8c,0x77,0x93,0x77,0x67,0x21,0x9c, 0xb6,0x5a,0x06,0x5e,0x47,0x86,0xf5,0x3c,0xd1,0x09,0xca,0x0d,0x3d,0xcd,0xb2,0xe9,0xa1,0x50,0x78,0xd1,0x84,0x88,0xe2,0x01,0x3c,0x22,0xfc,0xaf,0x96,0x08,0xcc,0x5d,0x99,0xc0,0xed,0xeb,0xa5,0x5a,0x98,0x92,0xf5,0xc8,0x40,0x4e,0x6a,0x73,0xaf,0xde,0xe3,0x74,0x7a,0xd3,0x5f,0x46,0x97,0xbc,0xe2,0x67,0x28,0x77,0x99,0xac,0xc1,0x0e, 0x31,0x16,0x8f,0x00,0x0f,0x01,0xfe,0x4b,0x5e,0x54,0x0f,0xca,0xc4,0x65,0x3f,0x0a,0xe3,0xa3,0x46,0xdb,0xf6,0x2c,0x03,0x3a,0x19,0xbe,0x68,0x05,0x16,0x9c,0xe6,0x7f,0x34,0xbf,0xa7,0x87,0x8d,0x65,0x39,0x26,0xc9,0x63,0xd4,0xef,0xc5,0xdd,0xbd,0x25,0xfe,0xfd,0x28,0xf4,0x34,0x86,0x79,0xac,0x2a,0xd5,0x5f,0x30,0x91,0x3b,0xe4,0x14, 0x6a,0xeb,0xb1,0xca,0x04,0x23,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7e,0x30,0x82,0x01,0x7a,0x30,0x1f,0x06,0x03,0x55,0x1d,0x25,0x04,0x18,0x30,0x16,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x4c,0x08,0x01,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x47, 0xbe,0xc0,0xcb,0xe1,0xa6,0x3f,0xfd,0x65,0xd6,0x38,0xf2,0x03,0x5d,0xb7,0xaf,0x77,0xf7,0x40,0xff,0x30,0x50,0x06,0x03,0x55,0x1d,0x11,0x04,0x49,0x30,0x47,0xa4,0x45,0x30,0x43,0x31,0x29,0x30,0x27,0x06,0x03,0x55,0x04,0x0b,0x13,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e, 0x73,0x20,0x50,0x75,0x65,0x72,0x74,0x6f,0x20,0x52,0x69,0x63,0x6f,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x05,0x13,0x0d,0x32,0x33,0x30,0x30,0x31,0x32,0x2b,0x34,0x33,0x37,0x39,0x36,0x35,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x48,0x6e,0x64,0xe5,0x50,0x05,0xd3,0x82,0xaa,0x17,0x37,0x37,0x22,0xb5, 0x6d,0xa8,0xca,0x75,0x02,0x95,0x30,0x54,0x06,0x03,0x55,0x1d,0x1f,0x04,0x4d,0x30,0x4b,0x30,0x49,0xa0,0x47,0xa0,0x45,0x86,0x43,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x6f,0x70,0x73,0x2f,0x63,0x72,0x6c,0x2f,0x4d,0x69,0x63, 0x43,0x6f,0x64,0x53,0x69,0x67,0x50,0x43,0x41,0x32,0x30,0x31,0x31,0x5f,0x32,0x30,0x31,0x31,0x2d,0x30,0x37,0x2d,0x30,0x38,0x2e,0x63,0x72,0x6c,0x30,0x61,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x55,0x30,0x53,0x30,0x51,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x45,0x68,0x74,0x74,0x70,0x3a,0x2f, 0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x6f,0x70,0x73,0x2f,0x63,0x65,0x72,0x74,0x73,0x2f,0x4d,0x69,0x63,0x43,0x6f,0x64,0x53,0x69,0x67,0x50,0x43,0x41,0x32,0x30,0x31,0x31,0x5f,0x32,0x30,0x31,0x31,0x2d,0x30,0x37,0x2d,0x30,0x38,0x2e,0x63,0x72,0x74,0x30, 0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x9f,0xf5,0xc9,0x53,0x0d,0x3f,0x0d,0x26,0xec,0xa2,0x44,0xd8,0x0d,0xd1,0x9f,0x63,0x96,0x06,0x4b,0x3f,0x1e,0x5c,0xc5,0x33,0xa3,0xa4,0xc3,0x6c,0xaf,0x1f,0xc0, 0x01,0xba,0xeb,0x65,0xec,0x9e,0x33,0x10,0x0f,0xa7,0xac,0x5b,0xd4,0xbd,0x90,0x61,0x17,0xe7,0x31,0xe7,0xc3,0x26,0xb4,0xac,0xf5,0x27,0xd3,0x48,0x93,0x86,0x88,0xfe,0x12,0x35,0x91,0x64,0x22,0xd1,0x6b,0x2d,0x3b,0xa8,0x2c,0x15,0x94,0x29,0xd2,0x37,0x96,0xe6,0x35,0xff,0x0c,0xce,0xc8,0x06,0x16,0x16,0x9e,0x24,0xb1,0xe2,0x39,0xf9, 0x6e,0x0e,0x78,0xd8,0x0c,0x1b,0xb6,0x29,0x60,0x27,0x76,0x34,0x24,0x9b,0xdd,0xb9,0x97,0x75,0xcb,0x01,0x3b,0xad,0x82,0x12,0x16,0x22,0x80,0x89,0x15,0x84,0xbb,0x98,0x50,0x20,0xb0,0x17,0x26,0x86,0x49,0xaf,0xce,0x7d,0x45,0x15,0x43,0x34,0x96,0xcf,0x81,0x5c,0x18,0x2c,0xd4,0x93,0xf2,0x67,0xab,0xe2,0x73,0xc8,0x3d,0xa3,0xcd,0xfc, 0x32,0x1e,0x60,0x1c,0xe9,0xb0,0x1b,0x30,0xfb,0x2c,0xbb,0x07,0x2e,0x96,0x84,0x93,0x45,0x28,0x54,0x5c,0xcd,0x96,0xfd,0xa0,0xdb,0x81,0xd8,0xb6,0x30,0xca,0x43,0xb1,0xf3,0x48,0xc0,0xb2,0x46,0x1c,0x5d,0x5e,0x76,0x2a,0x58,0x9f,0xd4,0xee,0xf2,0xf4,0xfa,0x48,0x4c,0xb5,0x61,0x8b,0xb0,0x8c,0x41,0xe9,0xaa,0xb8,0x9d,0x90,0xf4,0xff, 0x6a,0x42,0x0f,0xb9,0x3e,0xe9,0x0e,0xec,0x94,0xfc,0x8d,0x80,0xbb,0x78,0xe3,0x23,0xa7,0x78,0x5b,0xb2,0x6d,0x1f,0xf9,0x59,0xc1,0x7d,0xb6,0xd1,0x39,0xc9,0x79,0xe0,0x83,0x1c,0x60,0x0a,0xda,0x3d,0xb0,0xd1,0xed,0x36,0xbf,0x45,0x07,0xe9,0x1b,0x36,0x6e,0xe5,0x3d,0x3b,0x05,0x03,0xa7,0xd4,0xa7,0x25,0x12,0x8f,0xe6,0x76,0xa3,0x13, 0xb3,0x45,0x5a,0x43,0x31,0x82,0xda,0xd8,0x84,0xae,0xb9,0xb0,0x1f,0x75,0xf5,0xf6,0x1d,0x7d,0x51,0x11,0x37,0x27,0xe8,0xb5,0x35,0x84,0x71,0xf7,0x57,0xaa,0xae,0xfa,0x89,0x71,0xc9,0x98,0xd2,0x9e,0x5a,0x64,0x76,0xbe,0x8c,0xc3,0x7d,0x15,0x6a,0x91,0xf1,0x14,0xf4,0xf2,0xd9,0x35,0x31,0xb8,0xdb,0x72,0xfa,0xb4,0x75,0xc8,0x88,0x9b, 0x6a,0xbf,0x98,0x45,0xc7,0x66,0xb2,0xd7,0xff,0xce,0x92,0x90,0x75,0xe4,0xeb,0xe6,0x86,0xd2,0xc8,0x1b,0xdb,0x27,0xc0,0x5b,0x95,0x6f,0x49,0x6f,0x58,0x5d,0x69,0x2a,0xde,0x53,0x4b,0xf8,0xe8,0xca,0x7b,0xf6,0x6c,0x15,0xf9,0x03,0x19,0x0f,0x11,0x85,0xaa,0x4f,0x9a,0xbf,0xaa,0x57,0xdd,0x60,0xc6,0xf5,0x71,0x20,0xf4,0x51,0xa8,0x9a, 0xca,0xe9,0xd1,0xeb,0x34,0x47,0x3d,0x75,0xfa,0x22,0xec,0x55,0x3f,0x6a,0x19,0x39,0x6b,0x10,0xe9,0x5a,0x3f,0x8e,0xf4,0x23,0x78,0x30,0xb2,0xf2,0xa6,0x38,0xcb,0x35,0x8d,0xaa,0x98,0x59,0x24,0x40,0xb8,0x3a,0x67,0xa4,0x07,0x5f,0xa0,0xfe,0xd8,0x3b,0x49,0x13,0xfb,0x0c,0xe1,0xed,0x0b,0x6d,0x83,0x50,0xce,0xf0,0x7f,0x3e,0xe0,0xd9, 0x08,0xe8,0x8c,0x21,0x4a,0x41,0xc2,0xde,0xeb,0x8e,0x5b,0xee,0x03,0xc3,0x1d,0x6e,0x6e,0xe6,0x54,0x35,0x66,0x67,0x72,0x7c,0x1a,0xea,0x52,0xf6,0x22,0xc4,0x72,0x3f,0xae,0x30,0x82,0x07,0x7a,0x30,0x82,0x05,0x62,0xa0,0x03,0x02,0x01,0x02,0x02,0x0a,0x61,0x0e,0x90,0xd2,0x00,0x00,0x00,0x00,0x00,0x03,0x30,0x0d,0x06,0x09,0x2a,0x86, 0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64, 0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66, 0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x20,0x32,0x30,0x31,0x31,0x30,0x1e,0x17,0x0d,0x31,0x31,0x30,0x37,0x30,0x38,0x32,0x30,0x35,0x39,0x30,0x39,0x5a,0x17,0x0d,0x32,0x36,0x30,0x37,0x30,0x38,0x32,0x31,0x30,0x39,0x30,0x39,0x5a,0x30,0x7e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43, 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1f,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x31,0x30,0x82,0x02,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xab,0xf0,0xfa,0x72,0x10,0x1c,0x2e,0xad,0xd8,0x6e,0xaa,0x82,0x10,0x4d,0x34,0xba,0xf2,0xb6,0x58,0x21,0x9f,0x42,0x1b,0x2a,0x6b,0xe9,0x5a,0x50,0xaa,0xb8,0x06,0x38,0x1a,0x04,0x49,0xba,0x7f,0xc3,0x0c,0x1e,0xdd,0x37,0x6b, 0xc6,0x12,0xd8,0x0b,0xf0,0x38,0xc2,0x99,0x06,0xb0,0xc8,0x39,0xd5,0x01,0x14,0x31,0x42,0xd3,0x89,0x0d,0x79,0x64,0x87,0x7e,0x94,0x60,0x24,0x6c,0xaf,0x9e,0x49,0x9c,0xe9,0x68,0x5e,0xd2,0xdf,0x9b,0x53,0xb2,0x0a,0x2c,0xc3,0xaf,0xd9,0xa9,0x2b,0xae,0x7a,0x09,0xaf,0xd7,0x96,0x59,0xca,0x60,0x1a,0x05,0xe9,0x66,0x76,0xe8,0x32,0x52, 0x26,0x12,0x2f,0xe7,0xab,0x08,0x50,0xcf,0xb3,0x44,0xb7,0x5d,0xd8,0xc4,0x2e,0x03,0x75,0xab,0x68,0xf3,0xcb,0x6d,0xf3,0x3a,0x5c,0xa1,0x16,0xf4,0x46,0xba,0xe0,0x38,0x64,0xac,0x6e,0x64,0x35,0x78,0xa6,0xa0,0x63,0x0f,0x2d,0xd3,0x40,0x93,0xf8,0xe3,0xde,0x07,0x0d,0xd5,0x5c,0x79,0xa5,0x49,0x29,0xe7,0x0d,0xbe,0xa0,0x13,0x77,0xbe, 0x94,0x3d,0xef,0xfb,0xe3,0x2b,0x5a,0x10,0x1f,0x4d,0x56,0x28,0xa2,0x7a,0x72,0xe0,0x12,0x3a,0xb7,0x49,0x5e,0xd8,0xed,0xed,0x43,0x91,0x83,0xd9,0x7b,0xb2,0x7b,0x86,0x1b,0xd9,0x3e,0xb1,0x8c,0x5d,0xe8,0x89,0x4f,0x84,0x1a,0xf2,0xa1,0x2f,0x59,0xe4,0x90,0x3b,0x2d,0xae,0x33,0x58,0xc5,0xb7,0x3e,0xfe,0x32,0xd3,0xb3,0x03,0x3d,0xb1, 0xb2,0xaf,0x92,0x38,0x7e,0xd2,0x9d,0x80,0x2c,0xf5,0x4e,0x56,0x91,0x21,0x35,0x25,0xc3,0x39,0x6e,0x64,0x7f,0x53,0xba,0x9c,0x0f,0xad,0x19,0x23,0x84,0xcb,0xf4,0xba,0x03,0x86,0x8d,0xf7,0x5f,0xf0,0xd0,0x52,0xbf,0x8c,0x94,0x87,0xbc,0xc0,0x21,0x74,0x25,0x5f,0x18,0x28,0xb6,0xcc,0x27,0x28,0x38,0x25,0x98,0x39,0x4a,0x36,0xcf,0x7c, 0xb1,0x92,0xae,0x1c,0x23,0xa7,0xa9,0x66,0xec,0x61,0x1f,0x6a,0xe1,0x28,0x49,0x9d,0x5f,0x88,0xe2,0x25,0x5d,0xd3,0x21,0x4b,0x3e,0x52,0xc4,0xb5,0x57,0x3f,0x24,0x03,0xf0,0xd1,0x7a,0x5b,0x2f,0xd5,0x23,0xe3,0x70,0x5d,0x0f,0x51,0x46,0x77,0xb3,0xf8,0x00,0xe1,0xbc,0xac,0x02,0x82,0x5f,0xdb,0xc0,0x15,0xb3,0xbd,0x1b,0xd4,0x55,0x4b, 0xe7,0x39,0xa1,0x0f,0xe9,0x23,0x49,0xbc,0x18,0xb8,0x44,0x7c,0x45,0xe4,0xc1,0xc3,0x72,0x7a,0xe0,0x72,0xe7,0x24,0xdf,0xbf,0x46,0x99,0xc5,0xef,0xc2,0x1c,0x57,0xdb,0x83,0x8d,0xec,0x4d,0x49,0x30,0xa7,0xab,0x8e,0xdf,0xec,0x5b,0x9f,0xaf,0xfc,0xdd,0xb0,0x66,0xe2,0xc1,0x97,0x81,0x7b,0xed,0xd6,0xed,0x4b,0xe7,0x49,0x29,0xa7,0x13, 0x28,0xa6,0xa7,0x7d,0x67,0x80,0xe6,0x8a,0x62,0x78,0x5f,0xb2,0x2f,0x84,0xd7,0x57,0x9c,0x5c,0xbf,0x77,0x28,0x28,0xf1,0xed,0x6d,0xc3,0x28,0x8f,0x2c,0x8f,0x40,0x37,0x4f,0xc1,0xe1,0x85,0x44,0x89,0xc4,0x09,0x4c,0xc5,0xd4,0xa5,0x43,0x2f,0x74,0x95,0xf7,0x6e,0xf8,0x78,0x20,0x58,0x2c,0x13,0x5d,0x60,0x95,0x9a,0x3e,0x4f,0x33,0x84, 0xda,0xb0,0x88,0x17,0xde,0x9e,0x4e,0xf4,0x96,0xb0,0xbc,0x46,0xa0,0x6c,0x98,0xd2,0xe0,0xd6,0x88,0x8c,0x0b,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xed,0x30,0x82,0x01,0xe9,0x30,0x10,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16,0x04,0x14,0x48, 0x6e,0x64,0xe5,0x50,0x05,0xd3,0x82,0xaa,0x17,0x37,0x37,0x22,0xb5,0x6d,0xa8,0xca,0x75,0x02,0x95,0x30,0x19,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x04,0x0c,0x1e,0x0a,0x00,0x53,0x00,0x75,0x00,0x62,0x00,0x43,0x00,0x41,0x30,0x0b,0x06,0x03,0x55,0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0f,0x06,0x03,0x55, 0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x72,0x2d,0x3a,0x02,0x31,0x90,0x43,0xb9,0x14,0x05,0x4e,0xe1,0xea,0xa7,0xc7,0x31,0xd1,0x23,0x89,0x34,0x30,0x5a,0x06,0x03,0x55,0x1d,0x1f,0x04,0x53,0x30,0x51,0x30,0x4f,0xa0,0x4d,0xa0,0x4b,0x86,0x49, 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63,0x72,0x6c,0x2f,0x70,0x72,0x6f,0x64,0x75,0x63,0x74,0x73,0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74,0x32,0x30,0x31,0x31,0x5f,0x32,0x30,0x31,0x31,0x5f, 0x30,0x33,0x5f,0x32,0x32,0x2e,0x63,0x72,0x6c,0x30,0x5e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x52,0x30,0x50,0x30,0x4e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x42,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f, 0x70,0x6b,0x69,0x2f,0x63,0x65,0x72,0x74,0x73,0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74,0x32,0x30,0x31,0x31,0x5f,0x32,0x30,0x31,0x31,0x5f,0x30,0x33,0x5f,0x32,0x32,0x2e,0x63,0x72,0x74,0x30,0x81,0x9f,0x06,0x03,0x55,0x1d,0x20,0x04,0x81,0x97,0x30,0x81,0x94,0x30,0x81,0x91,0x06,0x09,0x2b,0x06,0x01,0x04, 0x01,0x82,0x37,0x2e,0x03,0x30,0x81,0x83,0x30,0x3f,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x33,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x6f,0x70,0x73,0x2f,0x64,0x6f,0x63,0x73,0x2f,0x70,0x72,0x69,0x6d,0x61, 0x72,0x79,0x63,0x70,0x73,0x2e,0x68,0x74,0x6d,0x30,0x40,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x34,0x1e,0x32,0x20,0x1d,0x00,0x4c,0x00,0x65,0x00,0x67,0x00,0x61,0x00,0x6c,0x00,0x5f,0x00,0x70,0x00,0x6f,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x79,0x00,0x5f,0x00,0x73,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x65,0x00, 0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x2e,0x20,0x1d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x67,0xf2,0x86,0xa5,0x98,0xe0,0x54,0x79,0x1a,0x2e,0xd3,0xd8,0x74,0x67,0x22,0x9b,0x0b,0x96,0x11,0xe1,0x63,0x92,0x99,0x42,0x96,0x7d,0xd2,0x79,0x0c,0x90,0xc1,0x65,0x5f, 0x2e,0x2c,0x3e,0xf8,0xc3,0x72,0xd1,0x6d,0x83,0xfe,0xbe,0x3f,0xe8,0x0a,0xca,0x3b,0xbf,0x47,0xa9,0xa3,0xf3,0x69,0xdb,0x63,0xbf,0x22,0x35,0xa5,0x97,0x5d,0x65,0x84,0x90,0x7d,0x8b,0x46,0x50,0x55,0xd8,0x0c,0x92,0x7c,0xd2,0x1a,0x4b,0x1c,0xf3,0x3c,0x42,0x8b,0x52,0xd0,0xb0,0xfd,0x6b,0xe3,0x3e,0x07,0x2e,0x29,0x9b,0xe6,0x3d,0x1b, 0xa5,0xd4,0xb5,0x1d,0x77,0x94,0x39,0xe2,0xe9,0x64,0xc9,0x44,0x3d,0x78,0x7a,0x23,0xf3,0x13,0x7d,0xa6,0x90,0x74,0x83,0x8d,0xf4,0xcb,0x26,0x02,0x46,0x2a,0xc2,0x8a,0x10,0xbb,0xa4,0xa9,0x05,0x0c,0x9b,0xed,0x68,0xfa,0x68,0x2e,0x95,0xa0,0x2a,0x3f,0x2a,0x6b,0x58,0x49,0x63,0x1f,0x09,0x69,0x6e,0x5a,0x98,0x96,0xe4,0x83,0xf4,0xc0, 0x8f,0xf3,0x46,0x2b,0xde,0xfc,0x3b,0xd0,0xbd,0x35,0xef,0x6e,0x25,0xae,0xe5,0xaf,0x27,0xed,0xd0,0xdd,0xf3,0x0e,0xaf,0x99,0x28,0x97,0x98,0x4d,0x0e,0x3d,0x0b,0xf2,0x08,0x89,0xd6,0x1f,0xc3,0x32,0x18,0xe2,0xf0,0xc5,0x2d,0xce,0x5b,0x9e,0xb4,0x49,0x39,0x0a,0xc6,0x0a,0xc2,0xc6,0xad,0xae,0xe5,0xb2,0xd9,0xdb,0x15,0x88,0x51,0x45, 0x58,0x38,0x32,0x71,0x27,0x1a,0x7f,0xb1,0xf4,0x27,0xf8,0xde,0x2c,0x3a,0x20,0x69,0x98,0xb2,0x59,0x89,0x68,0x6e,0x6f,0xa7,0xb7,0x74,0xc3,0x40,0x05,0x06,0xa6,0x01,0x2a,0x28,0x3e,0x82,0x3f,0x13,0x4d,0x66,0x0b,0xc0,0xb3,0x4d,0xf5,0xe1,0x8f,0x7f,0x1c,0x6f,0x15,0x7d,0x45,0xa7,0x76,0xe5,0x40,0x2a,0x65,0xa3,0xc3,0x5d,0x52,0x62, 0x86,0xc3,0x1d,0x63,0x36,0x97,0x86,0xdf,0xda,0xf3,0xf8,0xf2,0x16,0xa1,0x9a,0x27,0xe1,0xcd,0xa5,0x97,0xd0,0xee,0x5d,0x63,0x41,0xe3,0x5b,0x07,0x9c,0x87,0x3e,0x06,0x77,0x06,0xd1,0x06,0xb1,0x75,0x1f,0x14,0xbe,0x61,0x61,0xb5,0xf0,0xdc,0xc6,0x1b,0x04,0xbe,0xdf,0x41,0xc7,0x0e,0x28,0xee,0xde,0x65,0x2f,0xec,0x97,0xf6,0xa1,0x5c, 0x96,0xd8,0x00,0xd6,0xa1,0x46,0xbd,0x59,0xf3,0x97,0xa5,0x09,0x4b,0x48,0x10,0x99,0x80,0x1f,0xd0,0x00,0x29,0xc5,0xb1,0x9b,0xa5,0x3f,0x45,0x77,0x1e,0x35,0xc6,0xd2,0xa2,0xa2,0x9f,0x7a,0x7a,0x22,0xfa,0x48,0x95,0x1f,0xab,0xfb,0x47,0x23,0x80,0xf5,0x9e,0xf8,0xbf,0x6b,0xb7,0x4b,0x97,0xe2,0xeb,0x75,0x78,0x1a,0xec,0xea,0x37,0x99, 0x79,0x18,0x4b,0xff,0xd6,0xb3,0x23,0x68,0x75,0xe6,0xaf,0xfa,0xfc,0x8b,0xeb,0x0b,0x80,0xea,0x69,0x3b,0xaf,0xfc,0x30,0xed,0x04,0x4c,0x8e,0xdf,0xdf,0x75,0x6d,0x63,0x91,0x3d,0xd1,0x9d,0x56,0x4e,0x4f,0xbf,0x80,0x57,0x22,0xa1,0x78,0x11,0x32,0x21,0x7a,0xef,0x41,0x0a,0xb1,0x3f,0xfb,0xa8,0xcc,0xa4,0x5d,0xc1,0xa1,0x88,0x9b,0x57, 0x71,0x56,0x4e,0x48,0x45,0xc0,0x42,0xc9,0x9b,0x76,0x5b,0x0a,0x80,0x48,0x6b,0xfd,0x79,0x9f,0xc1,0xbd,0x6d,0x6d,0x6a,0xc9,0x52,0x73,0x13,0x0d,0x7a,0x50,0xcd,0x31,0x82,0x15,0x5b,0x30,0x82,0x15,0x57,0x02,0x01,0x01,0x30,0x81,0x95,0x30,0x7e,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11, 0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74, 0x69,0x6f,0x6e,0x31,0x28,0x30,0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1f,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x31,0x02,0x13,0x33,0x00,0x00,0x01,0x03,0x5e,0x25,0x1c,0x99,0x1f,0xa3,0x1e,0xb8,0x00,0x00,0x00,0x00, 0x01,0x03,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa0,0x81,0xae,0x30,0x19,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0c,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x04,0x30,0x1c,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0b,0x31,0x0e,0x30, 0x0c,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x15,0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x04,0x31,0x22,0x04,0x20,0xef,0x1c,0x60,0x9d,0x4d,0xa4,0xea,0x66,0x76,0x09,0x51,0xf4,0xba,0x29,0x24,0x71,0xc9,0x1d,0x9e,0x20,0xa1,0x48,0x83,0xb3,0x95,0xb6,0x32,0x21,0x3f,0xc2,0xe1,0x1b,0x30,0x42, 0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0c,0x31,0x34,0x30,0x32,0xa0,0x14,0x80,0x12,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0xa1,0x1a,0x80,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63, 0x6f,0x6d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x82,0x01,0x00,0x40,0xe0,0xd2,0x89,0x67,0x1e,0x8d,0xfc,0xdd,0x9c,0xd3,0x57,0x55,0xe8,0x1f,0x88,0x8d,0x5a,0xb1,0x90,0xf0,0xfa,0xb0,0x85,0xec,0xba,0xfa,0x6d,0x70,0xfa,0xab,0x25,0x02,0xe2,0x31,0xef,0xa5,0xfb,0xb2,0x85,0x7a,0xf7,0x50, 0xcf,0x79,0xff,0xf4,0x16,0x03,0x5f,0x86,0xa6,0xde,0xda,0x4a,0xfc,0x47,0xdd,0x21,0x41,0x45,0xda,0xcd,0x3b,0xe9,0xf3,0xf1,0xe6,0xd3,0xf8,0x9b,0xd8,0x83,0xcb,0x5f,0x4e,0x07,0x80,0x70,0x2a,0xc3,0x57,0x1e,0xa3,0x72,0xf3,0xe7,0xc7,0x90,0xd3,0x53,0xc7,0x44,0x76,0xd6,0xff,0xeb,0x2e,0x62,0xf4,0x1b,0xe2,0x09,0x62,0x8f,0x0a,0x08, 0x1b,0xc9,0xc5,0x1a,0xe0,0xd3,0x20,0x65,0x22,0x84,0xc1,0x58,0x73,0xa8,0x05,0x4c,0x6c,0x2a,0xee,0x5c,0x61,0x76,0x16,0x53,0x2b,0xf2,0x1a,0xb3,0xdb,0x8c,0xd7,0x39,0x03,0x3d,0x4c,0xf6,0xbd,0x67,0x20,0x8e,0x69,0xf9,0x0e,0x50,0x18,0x08,0x70,0x7d,0x33,0xfb,0xff,0x2e,0x5c,0x62,0x2d,0x6e,0xc6,0x3e,0x5e,0xf7,0x60,0x56,0x99,0xce, 0x52,0x94,0xce,0x2f,0xae,0xf8,0x50,0x19,0xe7,0x6e,0x6a,0x22,0x9b,0x27,0x70,0xfe,0xbe,0x79,0xdb,0x31,0x52,0x01,0x3f,0x4e,0xb4,0xcd,0xe8,0xf7,0x30,0xc2,0x61,0x02,0xc7,0x05,0x9b,0x0a,0x2f,0xe5,0xf5,0x0e,0x0c,0x9d,0xcb,0x2a,0xb0,0x79,0xac,0x96,0xf8,0x39,0xf0,0xb4,0xe5,0x67,0x7f,0x94,0x8a,0xac,0x77,0x9a,0xc9,0x38,0xb9,0x93, 0xed,0xf5,0x33,0xc2,0x44,0x82,0x81,0x5d,0xab,0x33,0x75,0xd2,0x6e,0x43,0xf4,0x03,0xf0,0x91,0x23,0x18,0xfb,0xa1,0x82,0x12,0xe5,0x30,0x82,0x12,0xe1,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x03,0x03,0x01,0x31,0x82,0x12,0xd1,0x30,0x82,0x12,0xcd,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x82,0x12,0xbe, 0x30,0x82,0x12,0xba,0x02,0x01,0x03,0x31,0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x30,0x82,0x01,0x51,0x06,0x0b,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x10,0x01,0x04,0xa0,0x82,0x01,0x40,0x04,0x82,0x01,0x3c,0x30,0x82,0x01,0x38,0x02,0x01,0x01,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x84, 0x59,0x0a,0x03,0x01,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20,0x4d,0xd8,0x6e,0x4d,0x11,0x8e,0x9b,0xbb,0x96,0x9d,0x1d,0x2e,0x32,0x48,0x7c,0xb0,0xde,0x56,0x6c,0xeb,0x7e,0x1c,0xe6,0x73,0xbc,0xa1,0x52,0xc7,0xa9,0xdb,0x41,0x31,0x02,0x06,0x5c,0x3d,0xd3,0x10,0xa8,0xe5,0x18, 0x13,0x32,0x30,0x31,0x39,0x30,0x31,0x32,0x34,0x31,0x38,0x34,0x30,0x33,0x36,0x2e,0x37,0x34,0x35,0x5a,0x30,0x04,0x80,0x02,0x01,0xf4,0xa0,0x81,0xd0,0xa4,0x81,0xcd,0x30,0x81,0xca,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69, 0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0b, 0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x41,0x6d,0x65,0x72,0x69,0x63,0x61,0x20,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x73,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x13,0x1d,0x54,0x68,0x61,0x6c,0x65,0x73,0x20,0x54,0x53,0x53,0x20,0x45,0x53,0x4e,0x3a,0x34,0x39,0x42,0x43,0x2d,0x45,0x33,0x37, 0x41,0x2d,0x32,0x33,0x33,0x43,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0xa0,0x82,0x0e,0x3c,0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x13, 0x33,0x00,0x00,0x00,0xee,0xf8,0xc5,0xf5,0x36,0x3b,0x81,0x1c,0x8c,0x00,0x00,0x00,0x00,0x00,0xee,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x7c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68, 0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04, 0x03,0x13,0x1d,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x30,0x1e,0x17,0x0d,0x31,0x38,0x31,0x30,0x32,0x34,0x32,0x31,0x31,0x34,0x31,0x35,0x5a,0x17,0x0d,0x32,0x30,0x30,0x31,0x31,0x30,0x32,0x31,0x31,0x34,0x31,0x35,0x5a, 0x30,0x81,0xca,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a, 0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0b,0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x41,0x6d,0x65,0x72,0x69,0x63,0x61,0x20,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x73,0x31,0x26, 0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x13,0x1d,0x54,0x68,0x61,0x6c,0x65,0x73,0x20,0x54,0x53,0x53,0x20,0x45,0x53,0x4e,0x3a,0x34,0x39,0x42,0x43,0x2d,0x45,0x33,0x37,0x41,0x2d,0x32,0x33,0x33,0x43,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d, 0x53,0x74,0x61,0x6d,0x70,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa3,0xf7,0x56,0x35,0x84,0xf3,0xdd,0x34,0xe4,0xa3,0x93,0x48,0x65,0xb2,0x92,0x69,0xb8,0xa1, 0x51,0xc2,0xfb,0x51,0x1e,0x08,0xbe,0xa5,0x84,0xaf,0xf3,0x48,0x46,0x9b,0x6c,0x0c,0xdc,0x8f,0xc3,0x82,0x4b,0x12,0x11,0xb1,0x11,0x5c,0xff,0x22,0xb3,0x3e,0xc2,0xde,0xb7,0xda,0xac,0x93,0x45,0x91,0xf4,0x8a,0xff,0x12,0x16,0x6f,0xd2,0x2d,0x4f,0xc8,0x20,0x76,0x05,0x21,0x37,0x4b,0x9f,0xd4,0xfd,0x57,0x7e,0xa9,0xf4,0x91,0x21,0xa6, 0xb9,0x8c,0x69,0xbf,0xe9,0x21,0xb8,0x98,0x0c,0x20,0xb7,0x5b,0xb4,0xc5,0xbf,0x4f,0xc3,0x6c,0x74,0x86,0x8d,0x10,0xfc,0x68,0xfe,0x8d,0x0c,0x85,0x64,0x5b,0xf0,0x23,0x2d,0xda,0x24,0x0b,0x0c,0x50,0xb4,0x8c,0x8f,0x67,0x02,0x0d,0x97,0x37,0xb4,0x1f,0x1d,0xaf,0x8b,0xcd,0xd5,0x87,0x8c,0x1e,0x70,0xd3,0xee,0xdf,0x22,0xc9,0xfe,0x54, 0xac,0x57,0xf4,0xbe,0xcd,0x55,0x12,0xfb,0x9b,0xa0,0x29,0xe1,0xcb,0x56,0x02,0x2e,0x4d,0xcb,0x72,0x2a,0xbf,0x4c,0x8c,0x14,0x9a,0x84,0x2a,0x25,0xdf,0x11,0xce,0x80,0x81,0xea,0x15,0x60,0x62,0x57,0xa2,0x0e,0x1a,0x09,0x74,0xa5,0x18,0xad,0xe9,0x9a,0x88,0x56,0x2c,0xcd,0xaf,0xd2,0x69,0x5d,0x2f,0xf1,0x88,0x1a,0x96,0x11,0x38,0x51, 0x0e,0x97,0xbd,0xdd,0x6c,0x11,0x52,0xe8,0x32,0xa5,0x95,0x17,0xa4,0x27,0x49,0xa9,0x7e,0x38,0x1a,0x84,0x1d,0xe8,0xe5,0xe7,0xcd,0x9f,0x6c,0x9c,0x2f,0x44,0x65,0x13,0x5d,0x89,0x5a,0x80,0x3d,0x3c,0x5a,0x37,0x7e,0xfd,0x5f,0xc6,0xab,0x2d,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x1b,0x30,0x82,0x01,0x17,0x30,0x1d,0x06,0x03,0x55, 0x1d,0x0e,0x04,0x16,0x04,0x14,0x26,0x77,0xcd,0x38,0x2b,0x45,0x7e,0xbd,0xd3,0x33,0x65,0x28,0xf7,0xcf,0xe3,0x68,0xf2,0x0e,0x65,0x4d,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xd5,0x63,0x3a,0x5c,0x8a,0x31,0x90,0xf3,0x43,0x7b,0x7c,0x46,0x1b,0xc5,0x33,0x68,0x5a,0x85,0x6d,0x55,0x30,0x56,0x06,0x03,0x55, 0x1d,0x1f,0x04,0x4f,0x30,0x4d,0x30,0x4b,0xa0,0x49,0xa0,0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63,0x72,0x6c,0x2f,0x70,0x72,0x6f,0x64,0x75,0x63,0x74,0x73,0x2f,0x4d,0x69,0x63,0x54,0x69,0x6d,0x53,0x74, 0x61,0x50,0x43,0x41,0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x37,0x2d,0x30,0x31,0x2e,0x63,0x72,0x6c,0x30,0x5a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4e,0x30,0x4c,0x30,0x4a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72, 0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63,0x65,0x72,0x74,0x73,0x2f,0x4d,0x69,0x63,0x54,0x69,0x6d,0x53,0x74,0x61,0x50,0x43,0x41,0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x37,0x2d,0x30,0x31,0x2e,0x63,0x72,0x74,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x02,0x30,0x00,0x30,0x13,0x06, 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x91,0x3f,0xe2,0xd1,0x15,0x1b,0x20,0x21,0x1c,0xf2,0x7b,0xbc,0xe4,0x9b,0x59,0x03,0xdf,0x8c,0x9a,0x5c,0x62,0xc4,0x1e,0xc1,0xc5,0xd3, 0x4e,0x96,0x21,0x60,0xf5,0x03,0xe5,0xcf,0x83,0x98,0x94,0x27,0x4d,0x5d,0xf8,0x1a,0x4e,0xec,0xa4,0x59,0xe3,0x23,0x87,0x2c,0x2c,0xc8,0x72,0xf8,0xc4,0x26,0xc3,0x73,0x06,0x5a,0xa7,0xff,0xed,0xfe,0xee,0xa1,0x8a,0x27,0xc5,0x65,0x68,0xc8,0xf6,0x16,0x8f,0x5a,0x4e,0x72,0xe5,0x37,0xf1,0x91,0x81,0xfc,0x18,0xe4,0x6e,0x2c,0xcd,0x94, 0x99,0xb5,0xda,0x60,0xa0,0x60,0x5f,0x76,0x3c,0x64,0x46,0x45,0xff,0x19,0x16,0x0c,0x40,0x25,0x7f,0x67,0xbb,0x2f,0x3a,0xfc,0x1f,0xbf,0x18,0x6c,0x68,0x90,0x8c,0xad,0x9a,0x23,0x6f,0xfd,0xa9,0xa6,0x3e,0x29,0xb2,0x57,0x1e,0xaa,0x83,0x8c,0xa3,0x1a,0xb5,0x95,0xe3,0xd7,0x0b,0x78,0xc9,0xa4,0xd1,0x0b,0x1c,0xbb,0xcd,0xc5,0xcf,0xe3, 0x13,0x45,0x57,0x43,0x0f,0x1f,0xc1,0x17,0x86,0x26,0x71,0x2f,0xad,0x27,0x6e,0x11,0xf3,0xa6,0xb3,0x72,0x5d,0x90,0xa3,0xdd,0xa0,0x2b,0x74,0x87,0xf7,0x77,0x26,0xd9,0x06,0x8f,0x5f,0x4d,0xfd,0x1e,0x0f,0x7b,0x0c,0x34,0xf0,0x25,0x54,0x21,0xe4,0x6e,0x4b,0x1f,0xab,0x7d,0x9d,0x9a,0x01,0x80,0x02,0xdf,0xf6,0xa9,0xa6,0x19,0xf9,0x24, 0xd2,0xa8,0x14,0x2e,0x38,0xfa,0x21,0x59,0x33,0xfe,0x9b,0x67,0xca,0x10,0x77,0x4f,0x66,0x4e,0x7c,0x97,0xb7,0x04,0x5a,0xa5,0x04,0xb3,0x56,0x39,0xb6,0x2f,0x54,0x21,0xe2,0x5c,0xc5,0x01,0xa8,0x46,0x30,0x82,0x06,0x71,0x30,0x82,0x04,0x59,0xa0,0x03,0x02,0x01,0x02,0x02,0x0a,0x61,0x09,0x81,0x2a,0x00,0x00,0x00,0x00,0x00,0x02,0x30, 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x81,0x88,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65, 0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43, 0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x20,0x32,0x30,0x31,0x30,0x30,0x1e,0x17,0x0d,0x31,0x30,0x30,0x37,0x30,0x31,0x32,0x31,0x33,0x36,0x35,0x35,0x5a,0x17,0x0d,0x32,0x35,0x30,0x37,0x30,0x31,0x32,0x31,0x34,0x36,0x35,0x35,0x5a,0x30,0x7c,0x31,0x0b,0x30,0x09,0x06, 0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73, 0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a, 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0x1d,0x0d,0xbc,0x77,0x11,0x8a,0x3a,0x20,0xec,0xfc,0x13,0x97,0xf5,0xfa,0x7f,0x69,0x94,0x6b,0x74,0x54,0x10,0xd5,0xa5,0x0a,0x00,0x82,0x85,0xfb,0xed,0x7c,0x68,0x4b,0x2c,0x5f,0xc5,0xc3,0xe5,0x61,0xc2, 0x76,0xb7,0x3e,0x66,0x2b,0x5b,0xf0,0x15,0x53,0x27,0x04,0x31,0x1f,0x41,0x1b,0x1a,0x95,0x1d,0xce,0x09,0x13,0x8e,0x7c,0x61,0x30,0x59,0xb1,0x30,0x44,0x0f,0xf1,0x60,0x88,0x84,0x54,0x43,0x0c,0xd7,0x4d,0xb8,0x38,0x08,0xb3,0x42,0xdd,0x93,0xac,0xd6,0x73,0x30,0x57,0x26,0x82,0xa3,0x45,0x0d,0xd0,0xea,0xf5,0x47,0x81,0xcd,0xbf,0x24, 0x60,0x32,0x58,0x60,0x46,0xf2,0x58,0x47,0x86,0x32,0x84,0x1e,0x74,0x61,0x67,0x91,0x5f,0x81,0x54,0xb1,0xcf,0x93,0x4c,0x92,0xc1,0xc4,0xa6,0x5d,0xd1,0x61,0x13,0x6e,0x28,0xc6,0x1a,0xf9,0x86,0x80,0xbb,0xdf,0x61,0xfc,0x46,0xc1,0x27,0x1d,0x24,0x67,0x12,0x72,0x1a,0x21,0x8a,0xaf,0x4b,0x64,0x89,0x50,0x62,0xb1,0x5d,0xfd,0x77,0x1f, 0x3d,0xf0,0x57,0x75,0xac,0xbd,0x8a,0x42,0x4d,0x40,0x51,0xd1,0x0f,0x9c,0x06,0x3e,0x67,0x7f,0xf5,0x66,0xc0,0x03,0x96,0x44,0x7e,0xef,0xd0,0x4b,0xfd,0x6e,0xe5,0x9a,0xca,0xb1,0xa8,0xf2,0x7a,0x2a,0x0a,0x31,0xf0,0xda,0x4e,0x06,0x91,0xb6,0x88,0x08,0x35,0xe8,0x78,0x1c,0xb0,0xe9,0x99,0xcd,0x3c,0xe7,0x2f,0x44,0xba,0xa7,0xf4,0xdc, 0x64,0xbd,0xa4,0x01,0xc1,0x20,0x09,0x93,0x78,0xcd,0xfc,0xbc,0xc0,0xc9,0x44,0x5d,0x5e,0x16,0x9c,0x01,0x05,0x4f,0x22,0x4d,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xe6,0x30,0x82,0x01,0xe2,0x30,0x10,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,0x16, 0x04,0x14,0xd5,0x63,0x3a,0x5c,0x8a,0x31,0x90,0xf3,0x43,0x7b,0x7c,0x46,0x1b,0xc5,0x33,0x68,0x5a,0x85,0x6d,0x55,0x30,0x19,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x04,0x0c,0x1e,0x0a,0x00,0x53,0x00,0x75,0x00,0x62,0x00,0x43,0x00,0x41,0x30,0x0b,0x06,0x03,0x55,0x1d,0x0f,0x04,0x04,0x03,0x02,0x01,0x86,0x30,0x0f, 0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xd5,0xf6,0x56,0xcb,0x8f,0xe8,0xa2,0x5c,0x62,0x68,0xd1,0x3d,0x94,0x90,0x5b,0xd7,0xce,0x9a,0x18,0xc4,0x30,0x56,0x06,0x03,0x55,0x1d,0x1f,0x04,0x4f,0x30,0x4d,0x30,0x4b,0xa0,0x49,0xa0, 0x47,0x86,0x45,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x6b,0x69,0x2f,0x63,0x72,0x6c,0x2f,0x70,0x72,0x6f,0x64,0x75,0x63,0x74,0x73,0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74,0x5f,0x32,0x30,0x31,0x30,0x2d,0x30, 0x36,0x2d,0x32,0x33,0x2e,0x63,0x72,0x6c,0x30,0x5a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4e,0x30,0x4c,0x30,0x4a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x70, 0x6b,0x69,0x2f,0x63,0x65,0x72,0x74,0x73,0x2f,0x4d,0x69,0x63,0x52,0x6f,0x6f,0x43,0x65,0x72,0x41,0x75,0x74,0x5f,0x32,0x30,0x31,0x30,0x2d,0x30,0x36,0x2d,0x32,0x33,0x2e,0x63,0x72,0x74,0x30,0x81,0xa0,0x06,0x03,0x55,0x1d,0x20,0x01,0x01,0xff,0x04,0x81,0x95,0x30,0x81,0x92,0x30,0x81,0x8f,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82, 0x37,0x2e,0x03,0x30,0x81,0x81,0x30,0x3d,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x31,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x50,0x4b,0x49,0x2f,0x64,0x6f,0x63,0x73,0x2f,0x43,0x50,0x53,0x2f,0x64,0x65,0x66,0x61,0x75,0x6c, 0x74,0x2e,0x68,0x74,0x6d,0x30,0x40,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x34,0x1e,0x32,0x20,0x1d,0x00,0x4c,0x00,0x65,0x00,0x67,0x00,0x61,0x00,0x6c,0x00,0x5f,0x00,0x50,0x00,0x6f,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x79,0x00,0x5f,0x00,0x53,0x00,0x74,0x00,0x61,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x65,0x00, 0x6e,0x00,0x74,0x00,0x2e,0x20,0x1d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0x07,0xe6,0x88,0x51,0x0d,0xe2,0xc6,0xe0,0x98,0x3f,0x81,0x71,0x03,0x3d,0x9d,0xa3,0xa1,0x21,0x6f,0xb3,0xeb,0xa6,0xcc,0xf5,0x31,0xbe,0xcf,0x05,0xe2,0xa9,0xfe,0xfa,0x57,0x6d,0x19,0x30,0xb3, 0xc2,0xc5,0x66,0xc9,0x6a,0xdf,0xf5,0xe7,0xf0,0x78,0xbd,0xc7,0xa8,0x9e,0x25,0xe3,0xf9,0xbc,0xed,0x6b,0x54,0x57,0x08,0x2b,0x51,0x82,0x44,0x12,0xfb,0xb9,0x53,0x8c,0xcc,0xf4,0x60,0x12,0x8a,0x76,0xcc,0x40,0x40,0x41,0x9b,0xdc,0x5c,0x17,0xff,0x5c,0xf9,0x5e,0x17,0x35,0x98,0x24,0x56,0x4b,0x74,0xef,0x42,0x10,0xc8,0xaf,0xbf,0x7f, 0xc6,0x7f,0xf2,0x37,0x7d,0x5a,0x3f,0x1c,0xf2,0x99,0x79,0x4a,0x91,0x52,0x00,0xaf,0x38,0x0f,0x17,0xf5,0x2f,0x79,0x81,0x65,0xd9,0xa9,0xb5,0x6b,0xe4,0xc7,0xce,0xf6,0xca,0x7a,0x00,0x6f,0x4b,0x30,0x44,0x24,0x22,0x3c,0xcf,0xed,0x03,0xa5,0x96,0x8f,0x59,0x29,0xbc,0xb6,0xfd,0x04,0xe1,0x70,0x9f,0x32,0x4a,0x27,0xfd,0x55,0xaf,0x2f, 0xfe,0xb6,0xe5,0x8e,0x33,0xbb,0x62,0x5f,0x9a,0xdb,0x57,0x40,0xe9,0xf1,0xce,0x99,0x66,0x90,0x8c,0xff,0x6a,0x62,0x7f,0xdd,0xc5,0x4a,0x0b,0x91,0x26,0xe2,0x39,0xec,0x19,0x4a,0x71,0x63,0x9d,0x7b,0x21,0x6d,0xc3,0x9c,0xa3,0xa2,0x3c,0xfa,0x7f,0x7d,0x96,0x6a,0x90,0x78,0xa6,0x6d,0xd2,0xe1,0x9c,0xf9,0x1d,0xfc,0x38,0xd8,0x94,0xf4, 0xc6,0xa5,0x0a,0x96,0x86,0xa4,0xbd,0x9e,0x1a,0xae,0x04,0x42,0x83,0xb8,0xb5,0x80,0x9b,0x22,0x38,0x20,0xb5,0x25,0xe5,0x64,0xec,0xf7,0xf4,0xbf,0x7e,0x63,0x59,0x25,0x0f,0x7a,0x2e,0x39,0x57,0x76,0xa2,0x71,0xaa,0x06,0x8a,0x0f,0x89,0x16,0xba,0x61,0xa7,0x11,0xcb,0x9a,0xd8,0x0e,0x47,0x9a,0x80,0xc5,0xd0,0xcd,0xa7,0xd0,0xef,0x7d, 0x83,0xf0,0xe1,0x3b,0x71,0x09,0xdf,0x5d,0x74,0x98,0x22,0x08,0x61,0xda,0xb0,0x50,0x1e,0x6f,0xbd,0xf1,0xe1,0x00,0xdf,0xe7,0x31,0x07,0xa4,0x93,0x3a,0xf7,0x65,0x47,0x78,0xe8,0xf8,0xa8,0x48,0xab,0xf7,0xde,0x72,0x7e,0x61,0x6b,0x6f,0x77,0xa9,0x81,0xcb,0xa7,0x09,0xac,0x39,0xbb,0xec,0xc6,0xcb,0xd8,0x82,0xb4,0x72,0xcd,0x1d,0xf4, 0xb8,0x85,0x01,0x1e,0x80,0xfb,0x1b,0x89,0x2a,0x54,0x39,0xb2,0x5b,0xda,0xc8,0x0d,0x55,0x99,0x7a,0x87,0x73,0x3b,0x08,0xe6,0x98,0x2d,0xea,0x8d,0xe0,0x33,0x2e,0x12,0x29,0xf5,0xc0,0x2f,0x54,0x27,0x21,0xf7,0xc8,0xac,0x4e,0xda,0x28,0xb8,0xb1,0xa9,0xdb,0x96,0xb2,0xa7,0x42,0xa2,0xc9,0xcf,0x19,0x41,0x4d,0xe0,0x86,0xf9,0x2a,0x9a, 0xa3,0x11,0x66,0x30,0xd3,0xbb,0x74,0x32,0x4b,0xdf,0x63,0x7b,0xf5,0x99,0x8a,0x2f,0x1b,0xc7,0x21,0xaf,0x59,0xb5,0xae,0xdc,0x44,0x3c,0x97,0x50,0x71,0xd7,0xa1,0xd2,0xc5,0x55,0xe3,0x69,0xde,0x57,0xc1,0xd1,0xde,0x30,0xc0,0xfd,0xcc,0xe6,0x4d,0xfb,0x0d,0xbf,0x5d,0x4f,0xe9,0x9d,0x1e,0x19,0x38,0x2f,0xbc,0xcf,0x58,0x05,0x2e,0xef, 0x0d,0xa0,0x50,0x35,0xda,0xef,0x09,0x27,0x1c,0xd5,0xb3,0x7e,0x35,0x1e,0x08,0xba,0xda,0x36,0xdb,0xd3,0x5f,0x8f,0xde,0x74,0x88,0x49,0x12,0xa1,0x82,0x02,0xce,0x30,0x82,0x02,0x37,0x02,0x01,0x01,0x30,0x81,0xf8,0xa1,0x81,0xd0,0xa4,0x81,0xcd,0x30,0x81,0xca,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f, 0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0b,0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x41,0x6d,0x65,0x72,0x69,0x63,0x61,0x20,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x73,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0b,0x13,0x1d,0x54,0x68,0x61,0x6c,0x65,0x73,0x20,0x54, 0x53,0x53,0x20,0x45,0x53,0x4e,0x3a,0x34,0x39,0x42,0x43,0x2d,0x45,0x33,0x37,0x41,0x2d,0x32,0x33,0x33,0x43,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x03,0x13,0x1c,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0xa2,0x23,0x0a,0x01, 0x01,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x03,0x15,0x00,0x38,0x3d,0xac,0x26,0x41,0x22,0x8f,0x3c,0xc6,0xc6,0x55,0xda,0x06,0x0a,0xf9,0x32,0x6d,0x93,0x2e,0x69,0xa0,0x81,0x83,0x30,0x81,0x80,0xa4,0x7e,0x30,0x7c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, 0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31, 0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x02,0x05,0x00,0xdf,0xf4,0x2e,0xe3,0x30,0x22,0x18, 0x0f,0x32,0x30,0x31,0x39,0x30,0x31,0x32,0x34,0x32,0x30,0x33,0x32,0x33,0x35,0x5a,0x18,0x0f,0x32,0x30,0x31,0x39,0x30,0x31,0x32,0x35,0x32,0x30,0x33,0x32,0x33,0x35,0x5a,0x30,0x77,0x30,0x3d,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x84,0x59,0x0a,0x04,0x01,0x31,0x2f,0x30,0x2d,0x30,0x0a,0x02,0x05,0x00,0xdf,0xf4,0x2e,0xe3,0x02,0x01, 0x00,0x30,0x0a,0x02,0x01,0x00,0x02,0x02,0x19,0xf6,0x02,0x01,0xff,0x30,0x07,0x02,0x01,0x00,0x02,0x02,0x11,0x74,0x30,0x0a,0x02,0x05,0x00,0xdf,0xf5,0x80,0x63,0x02,0x01,0x00,0x30,0x36,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x84,0x59,0x0a,0x04,0x02,0x31,0x28,0x30,0x26,0x30,0x0c,0x06,0x0a,0x2b,0x06,0x01,0x04,0x01,0x84,0x59,0x0a, 0x03,0x02,0xa0,0x0a,0x30,0x08,0x02,0x01,0x00,0x02,0x03,0x07,0xa1,0x20,0xa1,0x0a,0x30,0x08,0x02,0x01,0x00,0x02,0x03,0x01,0x86,0xa0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x79,0x78,0x9e,0x72,0x3a,0x6f,0xf0,0x0e,0x50,0x48,0xa6,0x78,0x90,0xb3,0x7b,0xd8,0xf9,0xd8,0xeb, 0x34,0x2d,0x2b,0x30,0xd5,0x86,0xfa,0x8c,0xc2,0x8e,0x06,0xad,0x31,0xb1,0xf1,0xfa,0x4b,0x6b,0xce,0xd8,0x44,0x4c,0xc7,0xc5,0xb0,0xa0,0x86,0x94,0x97,0x10,0x01,0x25,0xd1,0x29,0x21,0x2b,0x6c,0x1d,0x67,0x37,0xd3,0x15,0x81,0x32,0x40,0xa9,0x7f,0x2e,0x6b,0x4d,0x0d,0xcb,0xc9,0xa0,0x05,0xed,0x54,0x89,0x0a,0x8c,0x7f,0x0d,0x52,0x1a, 0x26,0xda,0x26,0x7f,0x8e,0xa4,0xc2,0x49,0xba,0x54,0x51,0xd1,0x1e,0xfc,0xf2,0x66,0xbf,0x46,0xa5,0xde,0x59,0x55,0x9a,0xbc,0xea,0xca,0xf7,0xf7,0xf9,0x7b,0x77,0x66,0x86,0x03,0xf0,0xf2,0xb8,0x53,0x28,0xa3,0x4a,0x0e,0xbe,0xf9,0x71,0x31,0x82,0x03,0x0d,0x30,0x82,0x03,0x09,0x02,0x01,0x01,0x30,0x81,0x93,0x30,0x7c,0x31,0x0b,0x30, 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72, 0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x02,0x13,0x33,0x00,0x00,0x00,0xee, 0xf8,0xc5,0xf5,0x36,0x3b,0x81,0x1c,0x8c,0x00,0x00,0x00,0x00,0x00,0xee,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa0,0x82,0x01,0x4a,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0d,0x06,0x0b,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x10,0x01,0x04,0x30,0x2f,0x06, 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x04,0x31,0x22,0x04,0x20,0xa9,0xb8,0x68,0x0f,0x5b,0x53,0xc4,0x53,0x8f,0x02,0x31,0x6a,0xa0,0x8b,0xf7,0x6b,0x41,0xea,0x53,0x11,0xcb,0xc2,0x98,0xe8,0xce,0x11,0x08,0xe6,0x0c,0xe8,0x14,0xd4,0x30,0x81,0xfa,0x06,0x0b,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x10,0x02,0x2f,0x31,0x81, 0xea,0x30,0x81,0xe7,0x30,0x81,0xe4,0x30,0x81,0xbd,0x04,0x20,0x3f,0xae,0xc6,0x22,0xb7,0x3e,0xfb,0xf8,0xb4,0xb1,0x77,0x93,0x35,0x3e,0x92,0x51,0x0a,0x9f,0x0b,0x21,0x01,0xf2,0x99,0x2b,0x12,0x0c,0xd1,0x23,0x2f,0x10,0x2e,0xc3,0x30,0x81,0x98,0x30,0x81,0x80,0xa4,0x7e,0x30,0x7c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0a,0x57,0x61,0x73,0x68,0x69,0x6e,0x67,0x74,0x6f,0x6e,0x31,0x10,0x30,0x0e,0x06,0x03,0x55,0x04,0x07,0x13,0x07,0x52,0x65,0x64,0x6d,0x6f,0x6e,0x64,0x31,0x1e,0x30,0x1c,0x06,0x03,0x55,0x04,0x0a,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43, 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x03,0x13,0x1d,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x54,0x69,0x6d,0x65,0x2d,0x53,0x74,0x61,0x6d,0x70,0x20,0x50,0x43,0x41,0x20,0x32,0x30,0x31,0x30,0x02,0x13,0x33,0x00,0x00,0x00,0xee,0xf8,0xc5,0xf5,0x36,0x3b,0x81,0x1c, 0x8c,0x00,0x00,0x00,0x00,0x00,0xee,0x30,0x22,0x04,0x20,0x14,0xc2,0x54,0x4f,0xba,0xe2,0x1c,0xdf,0x0c,0x3b,0x9d,0xfc,0xbc,0x5c,0xd8,0xb1,0x97,0xa6,0x39,0x9a,0x30,0x96,0xf8,0xa5,0xf4,0xb2,0x11,0xd6,0x59,0xc6,0x50,0xdd,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x04,0x82,0x01,0x00,0x4e,0x09, 0xa9,0x0d,0x51,0x40,0x35,0x45,0x38,0x88,0x5f,0x87,0xc6,0xaf,0x4a,0xd8,0x8c,0x36,0x34,0xd4,0x98,0x9b,0x5b,0xfb,0xc0,0xc0,0x85,0xd8,0x62,0x7e,0x9d,0x36,0x78,0x97,0xc6,0x77,0x76,0x2c,0xfb,0xf7,0x48,0x80,0x3e,0x93,0x18,0x95,0x1d,0xda,0xab,0x0a,0x0a,0xd1,0x9d,0xdb,0xcd,0xb7,0x67,0x8c,0x91,0xa8,0xdd,0x33,0x8d,0x55,0x9e,0xa0, 0x25,0xdb,0x26,0x6d,0x71,0xea,0xb6,0x99,0x10,0xce,0xa6,0x7a,0xfe,0x58,0x2e,0xb0,0x19,0xbd,0xc4,0x92,0xa4,0xa4,0x2b,0x56,0x85,0x54,0x02,0xdc,0x8d,0xe5,0x7b,0x23,0xcd,0xd7,0xee,0x49,0xcb,0x8d,0x7d,0x2f,0x80,0x9d,0x48,0x77,0xa2,0xe1,0xcc,0xb9,0x66,0x09,0xbd,0x3b,0x43,0x88,0x4d,0x7d,0xbc,0x83,0xff,0xfc,0xbf,0x27,0x4d,0x0c, 0xc7,0x06,0xbb,0x68,0x0d,0x37,0xcc,0xa0,0x0f,0xda,0xe0,0xf5,0xcc,0x8c,0xd2,0x24,0x97,0xe4,0x6c,0x02,0x83,0xb3,0xbd,0x0e,0x50,0xdd,0x2f,0x0c,0x05,0xee,0xe7,0xda,0x9b,0x11,0xc4,0x9d,0x6e,0x67,0x8c,0x29,0x9b,0x4e,0xef,0x33,0xe7,0x31,0x20,0x9e,0xdf,0x47,0xdd,0x6a,0xea,0x7b,0xac,0x08,0x0f,0x83,0x04,0x2c,0xee,0x13,0x35,0x69, 0x90,0xb4,0x8a,0xbe,0xc5,0x5e,0x5e,0x29,0x29,0x09,0xc0,0x1b,0xa7,0x68,0x47,0x29,0x21,0x91,0x3b,0xdf,0xa3,0x2f,0x81,0x42,0x88,0x50,0x90,0x72,0x29,0x4f,0x24,0xc5,0x03,0x45,0x2e,0xa2,0x6a,0x10,0xf4,0xd1,0x0b,0x23,0xbd,0xbf,0x92,0x8c,0xc8,0x74,0x6e,0x35,0xcd,0x74,0x9b,0x38,0xdf,0x13,0xd2,0x2a,0xc5,0xfa,0x30,0xab,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x02,0x1a,0x02,0x22,0x00,0x02,0x00,0x57,0x00,0x00,0x02,0x43,0x00,0x01,0x02,0x44,0x02,0x56,0x00,0x03,0x02,0x57,0x04,0x61,0x00,0x01,0x04,0x62,0x04,0xaf,0x00,0x03,0x04,0xb0,0x05,0xfc,0x00,0x01,0x05,0xfd,0x06,0x02,0x00,0x03,0x06,0x03,0x06,0x65,0x00,0x01,0x06,0x66,0x06,0x72,0x00,0x03, 0x06,0x73,0x06,0x9a,0x00,0x01,0x06,0x9b,0x06,0x9b,0x00,0x03,0x06,0x9c,0x06,0xad,0x00,0x01,0x06,0xae,0x06,0xd9,0x00,0x02,0x06,0xda,0x06,0xda,0x00,0x03,0x06,0xdb,0x07,0x38,0x00,0x02,0x07,0x39,0x07,0x3d,0x00,0x03,0x07,0x3e,0x07,0x54,0x00,0x01,0x07,0x55,0x07,0x5f,0x00,0x03,0x07,0x60,0x07,0xec,0x00,0x01,0x07,0xed,0x07,0xf0, 0x00,0x03,0x07,0xf1,0x08,0x4b,0x00,0x01,0x08,0x4c,0x08,0x4f,0x00,0x03,0x08,0x50,0x09,0x2b,0x00,0x01,0x09,0x2c,0x09,0x33,0x00,0x03,0x09,0x34,0x09,0x36,0x00,0x01,0x09,0x37,0x09,0x37,0x00,0x03,0x09,0x38,0x09,0x70,0x00,0x01,0x09,0x71,0x09,0x71,0x00,0x02,0x09,0x72,0x09,0x72,0x00,0x01,0x09,0x73,0x09,0x75,0x00,0x03,0x09,0x76, 0x09,0x76,0x00,0x01,0x09,0x77,0x09,0x77,0x00,0x03,0x09,0x78,0x09,0x7d,0x00,0x01,0x09,0x7e,0x09,0x7f,0x00,0x03,0x09,0x80,0x0a,0x0e,0x00,0x01,0x0a,0x0f,0x0a,0x13,0x00,0x03,0x0a,0x14,0x0a,0x15,0x00,0x01,0x0a,0x16,0x0a,0x1f,0x00,0x03,0x0a,0x20,0x0a,0x20,0x00,0x01,0x0a,0x21,0x0a,0x23,0x00,0x03,0x0a,0x24,0x0a,0x4a,0x00,0x01, 0x0a,0x4b,0x0a,0x53,0x00,0x03,0x0a,0x54,0x0a,0x5b,0x00,0x01,0x0a,0x5c,0x0a,0x5e,0x00,0x03,0x0a,0x5f,0x0a,0x62,0x00,0x01,0x0a,0x63,0x0a,0x64,0x00,0x02,0x0a,0x65,0x0a,0x69,0x00,0x03,0x0a,0x6a,0x0a,0x6b,0x00,0x01,0x0a,0x6c,0x0a,0x71,0x00,0x03,0x0a,0x72,0x0a,0xda,0x00,0x01,0x0a,0xdb,0x0a,0xe3,0x00,0x03,0x0a,0xe4,0x0b,0x52, 0x00,0x01,0x0b,0x53,0x0b,0x5f,0x00,0x03,0x0b,0x60,0x0b,0x60,0x00,0x01,0x0b,0x61,0x0b,0x61,0x00,0x03,0x0b,0x62,0x0b,0x62,0x00,0x01,0x0b,0x63,0x0b,0x64,0x00,0x03,0x0b,0x65,0x0b,0x65,0x00,0x01,0x0b,0x66,0x0b,0x67,0x00,0x03,0x0b,0x68,0x0b,0xb8,0x00,0x01,0x0b,0xb9,0x0b,0xb9,0x00,0x03,0x0b,0xba,0x0b,0xbe,0x00,0x01,0x0b,0xbf, 0x0b,0xde,0x00,0x03,0x0b,0xdf,0x0b,0xe0,0x00,0x01,0x0b,0xe1,0x0b,0xe1,0x00,0x03,0x0b,0xe2,0x0e,0x19,0x00,0x01,0x0e,0x1a,0x0e,0x1e,0x00,0x03,0x0e,0x1f,0x0e,0x61,0x00,0x01,0x0e,0x62,0x0e,0x6c,0x00,0x03,0x0e,0x6d,0x0e,0xea,0x00,0x01,0x0e,0xeb,0x0e,0xeb,0x00,0x03,0x0e,0xec,0x12,0x58,0x00,0x01,0x12,0x59,0x12,0x5e,0x00,0x03, 0x12,0x5f,0x13,0x29,0x00,0x01,0x13,0x2a,0x13,0x44,0x00,0x03,0x13,0x45,0x13,0xd8,0x00,0x01,0x13,0xd9,0x13,0xe9,0x00,0x03,0x13,0xea,0x13,0xee,0x00,0x01,0x13,0xef,0x13,0xf2,0x00,0x02,0x13,0xf3,0x14,0x16,0x00,0x01,0x14,0x17,0x14,0x17,0x00,0x03,0x14,0x18,0x14,0x5c,0x00,0x01,0x14,0x5d,0x14,0x6a,0x00,0x03,0x14,0x6b,0x14,0x6b, 0x00,0x01,0x14,0x6c,0x14,0x6c,0x00,0x03,0x14,0x6d,0x14,0x96,0x00,0x01,0x14,0x97,0x14,0x98,0x00,0x02,0x14,0x99,0x14,0xdf,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x33,0x02,0x44,0x02,0x44,0x00,0x02,0x02,0x45,0x02,0x45,0x00,0x04,0x02,0x46,0x02,0x47,0x00,0x02,0x04,0x62,0x04,0x73,0x00,0x02,0x04,0x75, 0x04,0x78,0x00,0x04,0x04,0x79,0x04,0x79,0x00,0x02,0x04,0x7b,0x04,0x7f,0x00,0x04,0x04,0x82,0x04,0x84,0x00,0x04,0x04,0x87,0x04,0x91,0x00,0x04,0x04,0x97,0x04,0x9a,0x00,0x04,0x04,0x9b,0x04,0x9d,0x00,0x02,0x04,0xa0,0x04,0xa2,0x00,0x02,0x04,0xa3,0x04,0xa3,0x00,0x04,0x04,0xa4,0x04,0xa4,0x00,0x02,0x04,0xa5,0x04,0xa7,0x00,0x04, 0x04,0xa8,0x04,0xaa,0x00,0x02,0x04,0xab,0x04,0xac,0x00,0x04,0x05,0xfd,0x06,0x00,0x00,0x02,0x06,0x66,0x06,0x72,0x00,0x02,0x07,0x3a,0x07,0x3d,0x00,0x03,0x07,0x55,0x07,0x57,0x00,0x02,0x07,0x58,0x07,0x5b,0x00,0x04,0x07,0x5c,0x07,0x5c,0x00,0x02,0x07,0xed,0x07,0xee,0x00,0x04,0x07,0xef,0x07,0xef,0x00,0x02,0x08,0x4c,0x08,0x4d, 0x00,0x02,0x08,0x4e,0x08,0x4e,0x00,0x04,0x08,0x4f,0x08,0x4f,0x00,0x02,0x09,0x2e,0x09,0x2e,0x00,0x01,0x09,0x31,0x09,0x31,0x00,0x01,0x09,0x77,0x09,0x77,0x00,0x01,0x09,0x7f,0x09,0x7f,0x00,0x01,0x0a,0x1a,0x0a,0x1a,0x00,0x01,0x0a,0x21,0x0a,0x21,0x00,0x01,0x0a,0x23,0x0a,0x23,0x00,0x01,0x0a,0x50,0x0a,0x50,0x00,0x01,0x0a,0x6f, 0x0a,0x6f,0x00,0x01,0x0a,0xdb,0x0a,0xe0,0x00,0x02,0x0a,0xe1,0x0a,0xe1,0x00,0x04,0x0a,0xe2,0x0a,0xe2,0x00,0x02,0x0a,0xe3,0x0a,0xe3,0x00,0x04,0x0e,0x1e,0x0e,0x1e,0x00,0x01,0x0e,0x6b,0x0e,0x6c,0x00,0x01,0x13,0x2c,0x13,0x2c,0x00,0x01,0x13,0x2f,0x13,0x2f,0x00,0x01,0x13,0x33,0x13,0x35,0x00,0x01,0x13,0x38,0x13,0x38,0x00,0x01, 0x13,0x3c,0x13,0x3c,0x00,0x01,0x13,0x3f,0x13,0x40,0x00,0x01,0x14,0x62,0x14,0x62,0x00,0x01,0x14,0x6c,0x14,0x6c,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x0a,0x01,0xee,0x04,0xce,0x00,0x15,0x61,0x72,0x61,0x62,0x00,0x80,0x62,0x6e,0x67,0x32,0x00,0xea,0x63,0x79,0x72,0x6c,0x00,0xf4,0x64,0x65,0x76,0x32,0x01,0x08,0x67,0x6a,0x72,0x32, 0x01,0x22,0x67,0x72,0x65,0x6b,0x01,0x12,0x67,0x75,0x72,0x32,0x01,0x2c,0x68,0x65,0x62,0x72,0x01,0x36,0x6b,0x68,0x6d,0x72,0x01,0x4e,0x6b,0x6e,0x64,0x32,0x01,0x44,0x6c,0x61,0x6f,0x20,0x01,0x58,0x6c,0x61,0x74,0x6e,0x01,0x62,0x6d,0x6c,0x6d,0x32,0x01,0x8a,0x6d,0x6f,0x6e,0x67,0x01,0x94,0x6d,0x79,0x6d,0x72,0x01,0x9e,0x6f,0x72, 0x79,0x32,0x01,0xb2,0x74,0x61,0x6c,0x75,0x01,0xa8,0x74,0x65,0x6c,0x32,0x01,0xc6,0x74,0x68,0x61,0x69,0x01,0xd0,0x74,0x69,0x62,0x74,0x01,0xda,0x74,0x6d,0x6c,0x32,0x01,0xbc,0x00,0x2e,0x00,0x05,0x41,0x52,0x41,0x20,0x00,0x22,0x4d,0x4c,0x59,0x20,0x00,0x3a,0x4d,0x4f,0x52,0x20,0x00,0x46,0x53,0x4e,0x44,0x20,0x00,0x52,0x55,0x52, 0x44,0x20,0x00,0x5e,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x08,0x00,0x12,0x00,0x1c,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x09,0x00,0x13,0x00,0x1d,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x0b,0x00,0x15,0x00,0x1f,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x0c,0x00,0x16,0x00,0x20, 0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x0d,0x00,0x17,0x00,0x21,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x05,0x00,0x04,0x00,0x00,0x00,0x0e,0x00,0x18,0x00,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x05, 0x00,0x01,0x00,0x0f,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x02,0x00,0x10,0x00,0x19,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, 0xff,0xff,0x00,0x00,0x00,0x0a,0x00,0x01,0x54,0x52,0x4b,0x20,0x00,0x1a,0x00,0x00,0xff,0xff,0x00,0x05,0x00,0x06,0x00,0x02,0x00,0x11,0x00,0x1a,0x00,0x23,0x00,0x00,0xff,0xff,0x00,0x04,0x00,0x07,0x00,0x03,0x00,0x1b,0x00,0x24,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00, 0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x04,0x00,0x00, 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x25,0x63,0x61,0x73,0x65,0x00,0xe0,0x63,0x61,0x73,0x65,0x00,0xe6,0x63,0x61,0x73,0x65,0x00,0xec,0x63,0x61,0x73,0x65,0x00,0xf2,0x63,0x70,0x73,0x70,0x00,0xf8,0x63,0x70,0x73,0x70,0x01,0x02,0x63,0x70,0x73,0x70,0x01,0x0c,0x63,0x70,0x73,0x70,0x01,0x16,0x6b,0x65,0x72,0x6e,0x01,0x20,0x6b,0x65, 0x72,0x6e,0x01,0x36,0x6b,0x65,0x72,0x6e,0x01,0x60,0x6b,0x65,0x72,0x6e,0x01,0x76,0x6b,0x65,0x72,0x6e,0x01,0x8c,0x6b,0x65,0x72,0x6e,0x01,0xa2,0x6b,0x65,0x72,0x6e,0x01,0xcc,0x6b,0x65,0x72,0x6e,0x01,0xd2,0x6b,0x65,0x72,0x6e,0x01,0xd8,0x6b,0x65,0x72,0x6e,0x01,0xde,0x6d,0x61,0x72,0x6b,0x01,0xe4,0x6d,0x61,0x72,0x6b,0x01,0xee, 0x6d,0x61,0x72,0x6b,0x01,0xf8,0x6d,0x61,0x72,0x6b,0x02,0x02,0x6d,0x61,0x72,0x6b,0x02,0x0c,0x6d,0x61,0x72,0x6b,0x02,0x16,0x6d,0x61,0x72,0x6b,0x02,0x20,0x6d,0x61,0x72,0x6b,0x02,0x28,0x6d,0x61,0x72,0x6b,0x02,0x6a,0x6d,0x61,0x72,0x6b,0x02,0x80,0x6d,0x6b,0x6d,0x6b,0x02,0x94,0x6d,0x6b,0x6d,0x6b,0x02,0x9c,0x6d,0x6b,0x6d,0x6b, 0x02,0xa4,0x6d,0x6b,0x6d,0x6b,0x02,0xac,0x6d,0x6b,0x6d,0x6b,0x02,0xb4,0x6d,0x6b,0x6d,0x6b,0x02,0xbc,0x6d,0x6b,0x6d,0x6b,0x02,0xc4,0x6d,0x6b,0x6d,0x6b,0x02,0xcc,0x6d,0x6b,0x6d,0x6b,0x02,0xd8,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x00, 0x00,0x03,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x00,0x00,0x03,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x00,0x00,0x03,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x00,0x00,0x03,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x00,0x00,0x13, 0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x40,0x00,0x41,0x00,0x42,0x00,0x43,0x00,0x44,0x00,0x45,0x00,0x46,0x00,0x47,0x00,0x48,0x00,0x49,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x00,0x00,0x09, 0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x39,0x00,0x3a,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x40, 0x00,0x41,0x00,0x42,0x00,0x43,0x00,0x44,0x00,0x45,0x00,0x46,0x00,0x47,0x00,0x48,0x00,0x49,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x01,0x00,0x19,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00, 0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x13,0x00,0x00,0x00,0x1f,0x00,0x1a,0x00,0x1b,0x00,0x1c,0x00,0x1d,0x00,0x1e,0x00,0x1f,0x00,0x20, 0x00,0x21,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x2b,0x00,0x2c,0x00,0x2d,0x00,0x2e,0x00,0x2f,0x00,0x30,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x00,0x00,0x09,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x07,0x00,0x08,0x00,0x09, 0x00,0x0a,0x00,0x0c,0x00,0x14,0x00,0x00,0x00,0x08,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x17, 0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x0d,0x00,0x0e,0x00,0x00,0x00,0x04,0x00,0x0d,0x00,0x0e,0x00,0x17,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x0d,0x00,0x0e,0x00,0x86,0x01,0x0e,0x01,0x28,0x01,0x42,0x01,0x52,0x01,0x62,0x01,0x72,0x01,0x82,0x01,0x92,0x01,0xa2,0x01,0xb2,0x01,0xc2,0x01,0xd2, 0x01,0xe2,0x01,0xf2,0x02,0x02,0x02,0x12,0x02,0x22,0x02,0x32,0x02,0x42,0x02,0x52,0x02,0x62,0x02,0x72,0x02,0x96,0x02,0xa6,0x02,0xb6,0x02,0xc6,0x02,0xd6,0x02,0xe6,0x02,0xf6,0x03,0x06,0x03,0x2a,0x03,0x3a,0x03,0x68,0x04,0x5e,0x05,0xb8,0x05,0xc8,0x05,0xd8,0x06,0x56,0x06,0x7a,0x06,0xee,0x07,0x1c,0x09,0x70,0x09,0x80,0x09,0x90, 0x09,0xa0,0x09,0xb0,0x09,0xc0,0x09,0xd0,0x09,0xe0,0x0a,0x04,0x0a,0x14,0x0a,0x38,0x0a,0x7a,0x0a,0xa8,0x0a,0xb8,0x0a,0xc8,0x0a,0xf6,0x0b,0x06,0x0b,0x16,0x0b,0x26,0x0b,0x36,0x0b,0x46,0x0b,0x56,0x0b,0x66,0x0b,0x76,0x0b,0x9a,0x0b,0xbe,0x0b,0xe2,0x0c,0x06,0x0c,0x2a,0x0c,0x4e,0x0c,0x72,0x0c,0x96,0x0c,0xba,0x0c,0xde,0x0c,0xee, 0x0c,0xfe,0x0d,0x0e,0x0d,0x1e,0x0d,0x2e,0x0d,0x3e,0x0d,0x4e,0x0d,0x5e,0x0d,0x6e,0x0d,0x7e,0x0d,0x8e,0x0d,0x9e,0x0d,0xae,0x0d,0xbe,0x0d,0xce,0x0d,0xde,0x0d,0xee,0x0d,0xfe,0x0e,0x0e,0x0e,0x1e,0x0e,0x2e,0x0e,0x3e,0x0e,0x4e,0x0e,0x5e,0x0e,0x6e,0x0e,0x7e,0x0e,0x8e,0x0e,0x9e,0x0e,0xae,0x0e,0xbe,0x0e,0xce,0x0e,0xde,0x0e,0xee, 0x0e,0xfe,0x0f,0x0e,0x0f,0x1e,0x0f,0x2e,0x0f,0x3e,0x0f,0x4e,0x0f,0x5e,0x0f,0x6e,0x0f,0x7e,0x0f,0x8e,0x0f,0x9e,0x0f,0xae,0x0f,0xbe,0x0f,0xce,0x0f,0xde,0x0f,0xee,0x0f,0xfe,0x10,0x0e,0x10,0x1e,0x10,0x2e,0x10,0x3e,0x10,0x4e,0x10,0x5e,0x10,0x6e,0x10,0x7e,0x10,0x8e,0x00,0x09,0x00,0x09,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01, 0x00,0x02,0x00,0x00,0x0f,0x86,0x00,0x01,0x00,0x02,0x00,0x00,0x2d,0x04,0x00,0x09,0x00,0x08,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01,0x00,0x02,0x00,0x00,0x35,0xd0,0x00,0x01,0x00,0x02,0x00,0x00,0x36,0x16,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x82,0xbe,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0x97,0x3c,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x98,0x5c,0x00,0x09,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x36,0x96,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x99,0xa2,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0x9a,0x78,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0xa8,0x76,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0xa9,0x56,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0xaa,0x32,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0xb1,0x9a,0x00,0x09,0x03,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0xb2,0x1c,0x00,0x09,0x02,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0xfe,0xcc,0x00,0x09,0x04,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x01,0x20,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x01,0x00,0x00,0x48,0x22,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x49,0xe8,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x49,0xf2,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x4a,0x08,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x01,0x02,0x92,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x02,0xa8,0x00,0x09,0x00,0x01,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x4a,0x40,0x00,0x01,0x00,0x08,0x00,0x00,0x4a,0x60,0x00,0x01,0x00,0x08,0x00,0x00,0x4a,0x78,0x00,0x09,0x00,0x01, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x05,0x00,0x01,0x12,0xb8,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x15,0x60,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x18,0xd4,0x00,0x09,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x4a,0xcc,0x00,0x09,0x00,0x01, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x1a,0x3a,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x1a,0x90,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x4e,0xa2,0x00,0x09,0x00,0x01,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x4e,0xe4, 0x00,0x01,0x00,0x08,0x00,0x00,0x4e,0xf0,0x00,0x01,0x00,0x08,0x00,0x00,0x4e,0xfc,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x1d,0x58,0x00,0x09,0x00,0x01,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x2c,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x36,0x00,0x01, 0x00,0x08,0x00,0x00,0x4f,0x42,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x50,0x00,0x09,0x00,0x01,0x00,0x18,0x00,0x36,0x00,0x3e,0x00,0x46,0x00,0x4e,0x00,0x56,0x00,0x5e,0x00,0x66,0x00,0x6e,0x00,0x76,0x00,0x7e,0x00,0x86,0x00,0x8e,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6,0x00,0xbe,0x00,0xc6,0x00,0xce,0x00,0xd6,0x00,0xde, 0x00,0xe6,0x00,0xee,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x58,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x64,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x70,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x7e,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x8a,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0x98,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0xa2,0x00,0x01,0x00,0x08, 0x00,0x00,0x4f,0xb0,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0xc0,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0xd2,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0xe0,0x00,0x01,0x00,0x08,0x00,0x00,0x4f,0xf0,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x12,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x24,0x00,0x01,0x00,0x08, 0x00,0x00,0x50,0x38,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x46,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x56,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x66,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x78,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x8a,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0x9e,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0xaa,0x00,0x01,0x00,0x08, 0x00,0x00,0x50,0xb8,0x00,0x09,0x00,0x01,0x00,0x22,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x6a,0x00,0x72,0x00,0x7a,0x00,0x82,0x00,0x8a,0x00,0x92,0x00,0x9a,0x00,0xa2,0x00,0xaa,0x00,0xb2,0x00,0xba,0x00,0xc2,0x00,0xca,0x00,0xd2,0x00,0xda,0x00,0xe2,0x00,0xea,0x00,0xf2,0x00,0xfa,0x01,0x02,0x01,0x0a,0x01,0x12,0x01,0x1a, 0x01,0x22,0x01,0x2a,0x01,0x32,0x01,0x3a,0x01,0x42,0x01,0x4a,0x01,0x52,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0xce,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0xda,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0xe8,0x00,0x01,0x00,0x08,0x00,0x00,0x50,0xf8,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x06,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x16,0x00,0x01, 0x00,0x08,0x00,0x00,0x51,0x28,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x34,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x42,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x52,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x60,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x70,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x82,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0x90,0x00,0x01, 0x00,0x08,0x00,0x00,0x51,0xa0,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0xb2,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0xc0,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0xd0,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0xe2,0x00,0x01,0x00,0x08,0x00,0x00,0x51,0xf2,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x04,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x18,0x00,0x01, 0x00,0x08,0x00,0x00,0x52,0x26,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x36,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x48,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x5a,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x6e,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x84,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0x94,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0xa6,0x00,0x01, 0x00,0x08,0x00,0x00,0x52,0xba,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0xca,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0xdc,0x00,0x01,0x00,0x08,0x00,0x00,0x52,0xf0,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x1b,0xac,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x53,0xbe,0x00,0x09, 0x00,0x01,0x00,0x0c,0x00,0x1e,0x00,0x26,0x00,0x2e,0x00,0x36,0x00,0x3e,0x00,0x46,0x00,0x4e,0x00,0x56,0x00,0x5e,0x00,0x66,0x00,0x6e,0x00,0x76,0x00,0x01,0x00,0x08,0x00,0x00,0x53,0xf0,0x00,0x01,0x00,0x08,0x00,0x00,0x53,0xfa,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x06,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x14,0x00,0x01,0x00,0x08, 0x00,0x00,0x54,0x1e,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x2a,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x38,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x42,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x4e,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x5c,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x66,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0x72,0x00,0x09,0x00,0x01, 0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0xd8,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0xe4,0x00,0x01,0x00,0x08,0x00,0x00,0x54,0xf2,0x00,0x09,0x00,0x01,0x00,0x0b,0x00,0x1c,0x00,0x24,0x00,0x2c,0x00,0x34,0x00,0x3c,0x00,0x44,0x00,0x4c,0x00,0x54,0x00,0x5c,0x00,0x64,0x00,0x6c,0x00,0x01,0x00,0x08, 0x00,0x00,0x55,0x42,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x4e,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x5c,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x6c,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x78,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x86,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0x96,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0xa2,0x00,0x01,0x00,0x08, 0x00,0x00,0x55,0xb0,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0xc0,0x00,0x01,0x00,0x08,0x00,0x00,0x55,0xcc,0x00,0x09,0x00,0x01,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x38,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x46,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x56,0x00,0x01,0x00,0x08,0x00,0x00, 0x56,0x68,0x00,0x09,0x00,0x01,0x00,0x3b,0x00,0x7c,0x00,0x84,0x00,0x8c,0x00,0x94,0x00,0x9c,0x00,0xa4,0x00,0xac,0x00,0xb4,0x00,0xbc,0x00,0xc4,0x00,0xcc,0x00,0xd4,0x00,0xdc,0x00,0xe4,0x00,0xec,0x00,0xf4,0x00,0xfc,0x01,0x04,0x01,0x0c,0x01,0x14,0x01,0x1c,0x01,0x24,0x01,0x2c,0x01,0x34,0x01,0x3c,0x01,0x44,0x01,0x4c,0x01,0x54, 0x01,0x5c,0x01,0x64,0x01,0x6c,0x01,0x74,0x01,0x7c,0x01,0x84,0x01,0x8c,0x01,0x94,0x01,0x9c,0x01,0xa4,0x01,0xac,0x01,0xb4,0x01,0xbc,0x01,0xc4,0x01,0xcc,0x01,0xd4,0x01,0xdc,0x01,0xe4,0x01,0xec,0x01,0xf4,0x01,0xfc,0x02,0x04,0x02,0x0c,0x02,0x14,0x02,0x1c,0x02,0x24,0x02,0x2c,0x02,0x34,0x02,0x3c,0x02,0x44,0x02,0x4c,0x00,0x01, 0x00,0x08,0x00,0x00,0x56,0x62,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x70,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0x90,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0xa0,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0xb2,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0xc4,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0xd8,0x00,0x01, 0x00,0x08,0x00,0x00,0x56,0xea,0x00,0x01,0x00,0x08,0x00,0x00,0x56,0xfc,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x10,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x24,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x3a,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x4a,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x5c,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x6e,0x00,0x01, 0x00,0x08,0x00,0x00,0x57,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0x94,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0xa8,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0xbe,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0xd2,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0xe6,0x00,0x01,0x00,0x08,0x00,0x00,0x57,0xfc,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x12,0x00,0x01, 0x00,0x08,0x00,0x00,0x58,0x2a,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x3a,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x4a,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x5c,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x6e,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x80,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0x92,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0xa6,0x00,0x01, 0x00,0x08,0x00,0x00,0x58,0xba,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0xd0,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0xe2,0x00,0x01,0x00,0x08,0x00,0x00,0x58,0xf4,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x32,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x46,0x00,0x01, 0x00,0x08,0x00,0x00,0x59,0x5a,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x6e,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x84,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0x96,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0xaa,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0xbe,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0xd4,0x00,0x01,0x00,0x08,0x00,0x00,0x59,0xea,0x00,0x01, 0x00,0x08,0x00,0x00,0x59,0xf8,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x18,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x28,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x3a,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x4c,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x60,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x72,0x00,0x01, 0x00,0x08,0x00,0x00,0x5a,0x84,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0x98,0x00,0x01,0x00,0x08,0x00,0x00,0x5a,0xac,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x1d,0x36,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5b,0xa4,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01, 0x00,0x08,0x00,0x00,0x5b,0xb6,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5b,0xd0,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x1e,0xda,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x1f,0x28,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01, 0x00,0x06,0x00,0x01,0x20,0x1c,0x00,0x09,0x00,0x01,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x5b,0xb6,0x00,0x01,0x00,0x08,0x00,0x00,0x5b,0xc2,0x00,0x01,0x00,0x08,0x00,0x00,0x5b,0xce,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x20,0xb0,0x00,0x09,0x00,0x01,0x00,0x03, 0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0x2c,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0x38,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0x46,0x00,0x09,0x00,0x01,0x00,0x06,0x00,0x12,0x00,0x1a,0x00,0x22,0x00,0x2a,0x00,0x32,0x00,0x3a,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0xc6,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0xd2, 0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0xde,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0xea,0x00,0x01,0x00,0x08,0x00,0x00,0x5c,0xf6,0x00,0x01,0x00,0x08,0x00,0x00,0x5d,0x02,0x00,0x09,0x00,0x01,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26,0x00,0x01,0x00,0x08,0x00,0x00,0x5d,0x5a,0x00,0x01,0x00,0x08,0x00,0x00,0x5d,0x66,0x00,0x01, 0x00,0x08,0x00,0x00,0x5d,0x72,0x00,0x01,0x00,0x08,0x00,0x00,0x5d,0x7e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5d,0xe6,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x01,0x20,0xc8,0x00,0x09,0x00,0x01,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26,0x00,0x01,0x00,0x08, 0x00,0x00,0x5e,0x46,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0x52,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0x60,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0x70,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x01,0x21,0x7a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0xa4,0x00,0x09,0x00,0x00, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0xb6,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0xca,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0xde,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5e,0xf4,0x00,0x09,0x00,0x00, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x0a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x20,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x2e,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x48,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x62, 0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x70,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0x8c,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0xa8,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0xb8,0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0xd4, 0x00,0x01,0x00,0x08,0x00,0x00,0x5f,0xf0,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x1e,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x3c,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x4e, 0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x6c,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x8a,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0x9c,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0xba,0x00,0x01,0x00,0x08,0x00,0x00,0x60,0xd8,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c, 0x00,0x01,0x00,0x08,0x00,0x00,0x60,0xea,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x0a,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x2a,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x3e,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x5e,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x7e,0x00,0x09,0x00,0x00, 0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0x92,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0xb2,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0xd2,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x08,0x00,0x00,0x61,0xe6,0x00,0x01,0x00,0x08,0x00,0x00,0x62,0x06,0x00,0x01,0x00,0x08, 0x00,0x00,0x62,0x26,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x62,0x3e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x62,0x3e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x62,0x3e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04, 0x00,0x00,0x65,0x04,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x67,0x4e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x68,0x26,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x68,0xf8,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04, 0x00,0x00,0x69,0xca,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6a,0x26,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6b,0xb0,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6c,0x88,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04, 0x00,0x00,0x6c,0xea,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6d,0xbc,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6e,0x18,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6e,0xe6,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04, 0x00,0x00,0x6f,0xbe,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x70,0x96,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x71,0x6e,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x72,0x94,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06, 0x00,0x00,0x72,0xea,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x73,0x40,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x73,0x96,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x74,0xe0,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x60,0xfc,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x02,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x06,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x08,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x0a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x0e,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x14,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x18,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x1c,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x20,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x22,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x24,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x26,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x2a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x2e,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x32,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x36,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x3a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x3e,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x42,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x46,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x4a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x4e,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x52,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x56,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x58,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x5a,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x5c,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x5e,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x60,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x62,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x64,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x66,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x68,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x61,0x6c,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x61,0x70,0x00,0x01,0x1c,0xce,0x00,0x05,0x00,0x00,0x00,0x53,0x00,0xb8,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb8,0x00,0xc0,0x09,0x64,0x14,0x30,0x00,0xb8,0x10,0x92,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x08,0x3c,0x08,0x3c,0x08,0x3c,0x08,0x3c, 0x14,0x30,0x14,0x30,0x00,0xb8,0x00,0xb8,0x14,0x30,0x14,0x30,0x15,0x52,0x14,0x30,0x14,0x30,0x08,0x3c,0x08,0x3c,0x14,0x30,0x14,0x30,0x08,0x3c,0x08,0x3c,0x08,0x3c,0x08,0x3c,0x14,0x30,0x14,0x30,0x14,0x30,0x14,0x30,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x08,0x3c,0x14,0x30,0x14,0x30,0x00,0xb8,0x00,0xb8,0x00,0xb8, 0x00,0xb8,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x00,0xb0,0x08,0x3c,0x08,0x3c,0x14,0x30,0x14,0x30,0x08,0x3c,0x08,0x3c,0x08,0x3c,0x08,0x3c,0x14,0x30,0x14,0x30,0x14,0x30,0x08,0x3c,0x14,0x30,0x14,0x30,0x14,0x30,0x14,0x30,0x14,0x30,0x14,0x30,0x14,0x30,0x00,0x01,0x09,0x08,0x01,0x56,0x01,0x56,0x00,0x01,0x09,0x08, 0x00,0xab,0x00,0xab,0x01,0x3f,0x08,0xcc,0xff,0x55,0xff,0x55,0x08,0xcd,0xff,0x55,0xff,0x55,0x08,0xd4,0xff,0x55,0xff,0x55,0x08,0xd5,0xff,0x55,0xff,0x55,0x08,0xd6,0xff,0x55,0xff,0x55,0x08,0xe1,0xff,0x55,0xff,0x55,0x08,0xe2,0xff,0x55,0xff,0x55,0x08,0xe5,0xff,0x55,0xff,0x55,0x08,0xe8,0xff,0x55,0xff,0x55,0x08,0xeb,0xff,0x55, 0xff,0x55,0x08,0xed,0xff,0x55,0xff,0x55,0x08,0xee,0xff,0x55,0xff,0x55,0x08,0xef,0xff,0x55,0xff,0x55,0x08,0xf0,0xff,0x55,0xff,0x55,0x08,0xf1,0xff,0x55,0xff,0x55,0x08,0xf4,0x00,0xab,0x00,0xab,0x08,0xf9,0xff,0x55,0xff,0x55,0x08,0xfa,0xff,0x55,0xff,0x55,0x08,0xff,0xff,0x55,0xff,0x55,0x09,0x01,0xff,0x55,0xff,0x55,0x09,0x06, 0xff,0x55,0xff,0x55,0x09,0x07,0xff,0x55,0xff,0x55,0x09,0x08,0xff,0x55,0xff,0x55,0x09,0x09,0xff,0x55,0xff,0x55,0x09,0x0a,0xff,0x55,0xff,0x55,0x09,0x0c,0xff,0x55,0xff,0x55,0x09,0x0d,0xff,0x55,0xff,0x55,0x09,0x0e,0xff,0x55,0xff,0x55,0x09,0x0f,0xff,0x55,0xff,0x55,0x09,0x10,0xff,0x55,0xff,0x55,0x09,0x11,0xff,0x55,0xff,0x55, 0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x15,0xff,0x55,0xff,0x55,0x09,0x16,0xff,0x55,0xff,0x55,0x09,0x17,0xff,0x55,0xff,0x55,0x09,0x18,0xff,0x55,0xff,0x55,0x09,0x19,0xff,0x55,0xff,0x55,0x09,0x1a,0xff,0x55,0xff,0x55,0x09,0x1b,0xff,0x55,0xff,0x55,0x09,0x1c,0xff,0x55, 0xff,0x55,0x09,0x1d,0xff,0x55,0xff,0x55,0x09,0x1e,0xff,0x55,0xff,0x55,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x22,0xff,0x55,0xff,0x55,0x09,0x24,0xff,0x55,0xff,0x55,0x09,0x26,0xff,0x55,0xff,0x55,0x09,0x28,0xff,0x55,0xff,0x55,0x09,0x29,0xff,0x55,0xff,0x55,0x09,0x2a,0xff,0x55,0xff,0x55,0x09,0x2b, 0xff,0x55,0xff,0x55,0x09,0x34,0xff,0x55,0xff,0x55,0x09,0x3c,0xff,0x55,0xff,0x55,0x09,0x3e,0xff,0x55,0xff,0x55,0x09,0x40,0xff,0x55,0xff,0x55,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab,0x09,0x45,0xff,0x55,0xff,0x55,0x09,0x46,0xff,0x55,0xff,0x55,0x09,0x47,0xff,0x55,0xff,0x55,0x09,0x48,0xff,0x55,0xff,0x55, 0x09,0x49,0xff,0x55,0xff,0x55,0x09,0x4a,0xff,0x55,0xff,0x55,0x09,0x4c,0x00,0xab,0x00,0xab,0x09,0x4e,0xff,0x55,0xff,0x55,0x09,0x5b,0xff,0x55,0xff,0x55,0x09,0x5c,0xff,0x55,0xff,0x55,0x09,0x5d,0xff,0x55,0xff,0x55,0x09,0x5e,0xff,0x55,0xff,0x55,0x09,0x60,0xff,0x55,0xff,0x55,0x09,0x63,0xff,0x55,0xff,0x55,0x09,0x64,0xff,0x55, 0xff,0x55,0x09,0x65,0xff,0x55,0xff,0x55,0x09,0x67,0xff,0x55,0xff,0x55,0x09,0x6c,0xff,0x55,0xff,0x55,0x09,0x6d,0xff,0x55,0xff,0x55,0x09,0x71,0xff,0x55,0xff,0x55,0x09,0x80,0xff,0x55,0xff,0x55,0x09,0x82,0xff,0x55,0xff,0x55,0x09,0x88,0xff,0x55,0xff,0x55,0x09,0x89,0xff,0x55,0xff,0x55,0x09,0x8a,0xff,0x55,0xff,0x55,0x09,0x8c, 0xff,0x55,0xff,0x55,0x09,0x8d,0xff,0x55,0xff,0x55,0x09,0x8e,0xff,0x55,0xff,0x55,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x90,0xff,0x55,0xff,0x55,0x09,0x92,0xff,0x55,0xff,0x55,0x09,0x93,0xff,0x55,0xff,0x55,0x09,0x94,0xff,0x55,0xff,0x55,0x09,0x95,0xff,0x55,0xff,0x55,0x09,0x96,0xff,0x55,0xff,0x55,0x09,0x97,0x00,0xab,0x00,0xab, 0x09,0x98,0x00,0xab,0x00,0xab,0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xaa,0xff,0x55,0xff,0x55,0x09,0xab,0xff,0x55,0xff,0x55,0x09,0xac,0xff,0x55,0xff,0x55,0x09,0xae,0xff,0x55,0xff,0x55,0x09,0xb2,0xff,0x55, 0xff,0x55,0x09,0xb7,0xff,0x55,0xff,0x55,0x09,0xb8,0xff,0x55,0xff,0x55,0x09,0xb9,0xff,0x55,0xff,0x55,0x09,0xba,0xff,0x55,0xff,0x55,0x09,0xbb,0xff,0x55,0xff,0x55,0x09,0xbc,0xff,0x55,0xff,0x55,0x09,0xbd,0xff,0x55,0xff,0x55,0x09,0xbe,0xff,0x55,0xff,0x55,0x09,0xbf,0xff,0x55,0xff,0x55,0x09,0xc0,0xff,0x55,0xff,0x55,0x09,0xc1, 0xff,0x55,0xff,0x55,0x09,0xc2,0xff,0x55,0xff,0x55,0x09,0xc3,0xff,0x55,0xff,0x55,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xc6,0xff,0x55,0xff,0x55,0x09,0xc8,0xff,0x55,0xff,0x55,0x09,0xc9,0xff,0x55,0xff,0x55,0x09,0xca,0xff,0x55,0xff,0x55,0x09,0xcc,0xff,0x55,0xff,0x55,0x09,0xcd,0xff,0x55,0xff,0x55,0x09,0xd2,0xff,0x55,0xff,0x55, 0x09,0xd3,0xff,0x55,0xff,0x55,0x09,0xd7,0xff,0x55,0xff,0x55,0x09,0xd8,0xff,0x55,0xff,0x55,0x09,0xd9,0xff,0x55,0xff,0x55,0x09,0xda,0xff,0x55,0xff,0x55,0x09,0xdb,0xff,0x55,0xff,0x55,0x09,0xdc,0xff,0x55,0xff,0x55,0x09,0xdd,0xff,0x55,0xff,0x55,0x09,0xde,0xff,0x55,0xff,0x55,0x09,0xdf,0xff,0x55,0xff,0x55,0x09,0xe1,0xff,0x55, 0xff,0x55,0x09,0xe2,0xff,0x55,0xff,0x55,0x09,0xe3,0xff,0x55,0xff,0x55,0x09,0xe4,0xff,0x55,0xff,0x55,0x09,0xe5,0xff,0x55,0xff,0x55,0x09,0xe7,0xff,0x55,0xff,0x55,0x09,0xe8,0xff,0x55,0xff,0x55,0x09,0xe9,0xff,0x55,0xff,0x55,0x09,0xea,0xff,0x55,0xff,0x55,0x09,0xec,0xff,0x55,0xff,0x55,0x09,0xee,0xff,0x55,0xff,0x55,0x09,0xf0, 0xff,0x55,0xff,0x55,0x09,0xf2,0x00,0xab,0x00,0xab,0x09,0xf9,0xff,0x55,0xff,0x55,0x09,0xfa,0x00,0xab,0x00,0xab,0x09,0xfe,0xff,0x55,0xff,0x55,0x09,0xff,0xff,0x55,0xff,0x55,0x0a,0x00,0xff,0x55,0xff,0x55,0x0a,0x01,0xff,0x55,0xff,0x55,0x0a,0x02,0xff,0x55,0xff,0x55,0x0a,0x03,0xff,0x55,0xff,0x55,0x0a,0x04,0xff,0x55,0xff,0x55, 0x0a,0x05,0xff,0x55,0xff,0x55,0x0a,0x07,0xff,0x55,0xff,0x55,0x0a,0x0a,0xff,0x55,0xff,0x55,0x0a,0x0b,0xff,0x55,0xff,0x55,0x0a,0x0d,0xff,0x55,0xff,0x55,0x0a,0x24,0xff,0x55,0xff,0x55,0x0a,0x25,0xff,0x55,0xff,0x55,0x0a,0x26,0xff,0x55,0xff,0x55,0x0a,0x27,0xff,0x55,0xff,0x55,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x2a,0xff,0x55, 0xff,0x55,0x0a,0x3e,0xff,0x55,0xff,0x55,0x0a,0x56,0xff,0x55,0xff,0x55,0x0a,0x58,0xff,0x55,0xff,0x55,0x0a,0x5a,0xff,0x55,0xff,0x55,0x0a,0x63,0xff,0x55,0xff,0x55,0x0a,0x72,0xff,0x55,0xff,0x55,0x0a,0x73,0x00,0xab,0x00,0xab,0x0a,0x74,0xff,0x55,0xff,0x55,0x0a,0x76,0xff,0x55,0xff,0x55,0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x78, 0xff,0x55,0xff,0x55,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7a,0xff,0x55,0xff,0x55,0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7c,0xff,0x55,0xff,0x55,0x0a,0x7d,0x00,0xab,0x00,0xab,0x0a,0x7e,0xff,0x55,0xff,0x55,0x0a,0x7f,0xff,0x55,0xff,0x55,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x86,0xff,0x55,0xff,0x55, 0x0a,0x87,0xff,0x55,0xff,0x55,0x0a,0x88,0xff,0x55,0xff,0x55,0x0a,0x89,0xff,0x55,0xff,0x55,0x0a,0x8a,0xff,0x55,0xff,0x55,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8d,0xff,0x55,0xff,0x55,0x0a,0x8f,0x00,0xab,0x00,0xab,0x0a,0x91,0xff,0x55,0xff,0x55,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0x95,0xff,0x55,0xff,0x55,0x0a,0x9d,0xff,0x55, 0xff,0x55,0x0a,0x9e,0xff,0x55,0xff,0x55,0x0a,0xa0,0xff,0x55,0xff,0x55,0x0a,0xa1,0xff,0x55,0xff,0x55,0x0a,0xa3,0xff,0x55,0xff,0x55,0x0a,0xa6,0xff,0x55,0xff,0x55,0x0a,0xa7,0xff,0x55,0xff,0x55,0x0a,0xa8,0xff,0x55,0xff,0x55,0x0a,0xa9,0xff,0x55,0xff,0x55,0x0a,0xab,0x00,0xab,0x00,0xab,0x0a,0xad,0xff,0x55,0xff,0x55,0x0a,0xaf, 0xff,0x55,0xff,0x55,0x0a,0xb2,0xff,0x55,0xff,0x55,0x0a,0xb4,0xff,0x55,0xff,0x55,0x0a,0xb5,0xff,0x55,0xff,0x55,0x0a,0xb6,0xff,0x55,0xff,0x55,0x0a,0xb7,0xff,0x55,0xff,0x55,0x0b,0x19,0xff,0x55,0xff,0x55,0x0e,0x20,0xff,0x55,0xff,0x55,0x0e,0x3a,0xff,0x55,0xff,0x55,0x0e,0x3d,0xff,0x55,0xff,0x55,0x0e,0x3f,0xff,0x55,0xff,0x55, 0x0e,0x41,0xff,0x55,0xff,0x55,0x0e,0x43,0xff,0x55,0xff,0x55,0x0e,0x47,0xff,0x55,0xff,0x55,0x0e,0x49,0x00,0xab,0x00,0xab,0x0e,0x4b,0xff,0x55,0xff,0x55,0x0e,0x4d,0x00,0xab,0x00,0xab,0x0e,0x4f,0xff,0x55,0xff,0x55,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0x5b,0xff,0x55,0xff,0x55,0x0e,0x5c,0xff,0x55,0xff,0x55,0x0e,0x5f,0xff,0x55, 0xff,0x55,0x0e,0x6f,0xff,0x55,0xff,0x55,0x0e,0x71,0xff,0x55,0xff,0x55,0x0e,0x76,0xff,0x55,0xff,0x55,0x0e,0xa3,0xff,0x55,0xff,0x55,0x0e,0xac,0xff,0x55,0xff,0x55,0x0e,0xaf,0xff,0x55,0xff,0x55,0x0e,0xd1,0xff,0x55,0xff,0x55,0x0e,0xd7,0xff,0x55,0xff,0x55,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16, 0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x1e,0xff,0x55,0xff,0x55,0x0f,0x20,0xff,0x55,0xff,0x55,0x0f,0x22,0xff,0x55,0xff,0x55,0x0f,0x24,0x00,0xab,0x00,0xab,0x0f,0x28,0xff,0x55,0xff,0x55,0x0f,0x2a,0xff,0x55,0xff,0x55,0x0f,0x2c,0xff,0x55,0xff,0x55,0x0f,0x2e,0x00,0xab,0x00,0xab,0x0f,0x30,0xff,0x55,0xff,0x55, 0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x34,0xff,0x55,0xff,0x55,0x0f,0x36,0x00,0xab,0x00,0xab,0x0f,0x38,0xff,0x55,0xff,0x55,0x0f,0x3a,0xff,0x55,0xff,0x55,0x0f,0x3c,0xff,0x55,0xff,0x55,0x0f,0x3e,0xff,0x55,0xff,0x55,0x0f,0x40,0x00,0xab,0x00,0xab,0x0f,0x44,0xff,0x55,0xff,0x55,0x0f,0x46,0xff,0x55,0xff,0x55,0x0f,0x48,0xff,0x55, 0xff,0x55,0x0f,0x4a,0xff,0x55,0xff,0x55,0x0f,0x4c,0xff,0x55,0xff,0x55,0x0f,0x4e,0xff,0x55,0xff,0x55,0x0f,0x6c,0xff,0x55,0xff,0x55,0x0f,0x6e,0xff,0x55,0xff,0x55,0x0f,0x70,0xff,0x55,0xff,0x55,0x0f,0x72,0xff,0x55,0xff,0x55,0x0f,0x74,0xff,0x55,0xff,0x55,0x0f,0x76,0xff,0x55,0xff,0x55,0x0f,0x78,0xff,0x55,0xff,0x55,0x0f,0x7a, 0xff,0x55,0xff,0x55,0x0f,0x7c,0xff,0x55,0xff,0x55,0x0f,0x7e,0xff,0x55,0xff,0x55,0x0f,0x80,0xff,0x55,0xff,0x55,0x0f,0x82,0xff,0x55,0xff,0x55,0x0f,0x84,0xff,0x55,0xff,0x55,0x0f,0x86,0xff,0x55,0xff,0x55,0x0f,0x88,0xff,0x55,0xff,0x55,0x0f,0x8a,0xff,0x55,0xff,0x55,0x0f,0x8c,0xff,0x55,0xff,0x55,0x0f,0x8e,0xff,0x55,0xff,0x55, 0x0f,0x90,0xff,0x55,0xff,0x55,0x0f,0x92,0xff,0x55,0xff,0x55,0x0f,0x94,0x00,0xab,0x00,0xab,0x0f,0x96,0xff,0x55,0xff,0x55,0x0f,0xc0,0xff,0x55,0xff,0x55,0x10,0xfe,0xff,0x55,0xff,0x55,0x11,0x00,0xff,0x55,0xff,0x55,0x11,0x02,0xff,0x55,0xff,0x55,0x11,0x04,0xff,0x55,0xff,0x55,0x11,0x06,0xff,0x55,0xff,0x55,0x11,0x08,0xff,0x55, 0xff,0x55,0x11,0x0a,0xff,0x55,0xff,0x55,0x11,0x0c,0xff,0x55,0xff,0x55,0x11,0x0d,0xff,0x55,0xff,0x55,0x11,0x0f,0xff,0x55,0xff,0x55,0x14,0x53,0x00,0xab,0x00,0xab,0x14,0x54,0xff,0x55,0xff,0x55,0x14,0x55,0xff,0x55,0xff,0x55,0x14,0x56,0xff,0x55,0xff,0x55,0x14,0x57,0xff,0x55,0xff,0x55,0x14,0x58,0xff,0x55,0xff,0x55,0x14,0x59, 0xff,0x55,0xff,0x55,0x14,0x5a,0xff,0x55,0xff,0x55,0x14,0x6f,0xff,0x55,0xff,0x55,0x14,0x72,0xff,0x55,0xff,0x55,0x14,0x75,0xff,0x55,0xff,0x55,0x14,0x78,0x00,0xab,0x00,0xab,0x14,0x7b,0xff,0x55,0xff,0x55,0x14,0x83,0xff,0x55,0xff,0x55,0x14,0x86,0xff,0x55,0xff,0x55,0x14,0x97,0xff,0x55,0xff,0x55,0x14,0x98,0xff,0x55,0xff,0x55, 0x00,0x31,0x08,0xf4,0x00,0xab,0x00,0xab,0x09,0x08,0xff,0x55,0xff,0x55,0x09,0x0e,0xff,0x55,0xff,0x55,0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab,0x09,0x4c, 0x00,0xab,0x00,0xab,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x97,0x00,0xab,0x00,0xab,0x09,0x98,0x00,0xab,0x00,0xab,0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xf2,0x00,0xab,0x00,0xab, 0x09,0xfa,0x00,0xab,0x00,0xab,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x73,0x00,0xab,0x00,0xab,0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7d,0x00,0xab,0x00,0xab,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8f,0x00,0xab, 0x00,0xab,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0xab,0x00,0xab,0x00,0xab,0x0e,0x49,0x00,0xab,0x00,0xab,0x0e,0x4d,0x00,0xab,0x00,0xab,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16,0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x24,0x00,0xab,0x00,0xab,0x0f,0x2e, 0x00,0xab,0x00,0xab,0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x36,0x00,0xab,0x00,0xab,0x0f,0x40,0x00,0xab,0x00,0xab,0x0f,0x94,0x00,0xab,0x00,0xab,0x14,0x53,0x00,0xab,0x00,0xab,0x14,0x78,0x00,0xab,0x00,0xab,0x01,0x32,0x08,0xd4,0xff,0x55,0xff,0x55,0x08,0xd5,0xff,0x55,0xff,0x55,0x08,0xd6,0xff,0x55,0xff,0x55,0x08,0xe1,0xff,0x55, 0xff,0x55,0x08,0xe2,0xff,0x55,0xff,0x55,0x08,0xe5,0xff,0x55,0xff,0x55,0x08,0xe8,0xff,0x55,0xff,0x55,0x08,0xeb,0xff,0x55,0xff,0x55,0x08,0xed,0xff,0x55,0xff,0x55,0x08,0xee,0xff,0x55,0xff,0x55,0x08,0xef,0xff,0x55,0xff,0x55,0x08,0xf0,0xff,0x55,0xff,0x55,0x08,0xf1,0xff,0x55,0xff,0x55,0x08,0xf4,0x00,0xab,0x00,0xab,0x08,0xf9, 0xff,0x55,0xff,0x55,0x08,0xfa,0xff,0x55,0xff,0x55,0x08,0xff,0xff,0x55,0xff,0x55,0x09,0x01,0xff,0x55,0xff,0x55,0x09,0x06,0xff,0x55,0xff,0x55,0x09,0x07,0xff,0x55,0xff,0x55,0x09,0x08,0xff,0x55,0xff,0x55,0x09,0x09,0xff,0x55,0xff,0x55,0x09,0x0a,0xff,0x55,0xff,0x55,0x09,0x0c,0xff,0x55,0xff,0x55,0x09,0x0d,0xff,0x55,0xff,0x55, 0x09,0x0e,0xff,0x55,0xff,0x55,0x09,0x0f,0xff,0x55,0xff,0x55,0x09,0x10,0xff,0x55,0xff,0x55,0x09,0x11,0xff,0x55,0xff,0x55,0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x15,0xff,0x55,0xff,0x55,0x09,0x16,0xff,0x55,0xff,0x55,0x09,0x17,0xff,0x55,0xff,0x55,0x09,0x18,0xff,0x55, 0xff,0x55,0x09,0x19,0xff,0x55,0xff,0x55,0x09,0x1a,0xff,0x55,0xff,0x55,0x09,0x1b,0xff,0x55,0xff,0x55,0x09,0x1c,0xff,0x55,0xff,0x55,0x09,0x1d,0xff,0x55,0xff,0x55,0x09,0x1e,0xff,0x55,0xff,0x55,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x22,0xff,0x55,0xff,0x55,0x09,0x24,0xff,0x55,0xff,0x55,0x09,0x26, 0xff,0x55,0xff,0x55,0x09,0x28,0xff,0x55,0xff,0x55,0x09,0x29,0xff,0x55,0xff,0x55,0x09,0x2a,0xff,0x55,0xff,0x55,0x09,0x2b,0xff,0x55,0xff,0x55,0x09,0x34,0xff,0x55,0xff,0x55,0x09,0x3c,0xff,0x55,0xff,0x55,0x09,0x3e,0xff,0x55,0xff,0x55,0x09,0x40,0xff,0x55,0xff,0x55,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab, 0x09,0x45,0xff,0x55,0xff,0x55,0x09,0x46,0xff,0x55,0xff,0x55,0x09,0x47,0xff,0x55,0xff,0x55,0x09,0x48,0xff,0x55,0xff,0x55,0x09,0x49,0xff,0x55,0xff,0x55,0x09,0x4a,0xff,0x55,0xff,0x55,0x09,0x4c,0x00,0xab,0x00,0xab,0x09,0x4e,0xff,0x55,0xff,0x55,0x09,0x5b,0xff,0x55,0xff,0x55,0x09,0x5d,0xff,0x55,0xff,0x55,0x09,0x5e,0xff,0x55, 0xff,0x55,0x09,0x60,0xff,0x55,0xff,0x55,0x09,0x63,0xff,0x55,0xff,0x55,0x09,0x64,0xff,0x55,0xff,0x55,0x09,0x6c,0xff,0x55,0xff,0x55,0x09,0x6d,0xff,0x55,0xff,0x55,0x09,0x71,0xff,0x55,0xff,0x55,0x09,0x80,0xff,0x55,0xff,0x55,0x09,0x82,0xff,0x55,0xff,0x55,0x09,0x88,0xff,0x55,0xff,0x55,0x09,0x89,0xff,0x55,0xff,0x55,0x09,0x8a, 0xff,0x55,0xff,0x55,0x09,0x8c,0xff,0x55,0xff,0x55,0x09,0x8d,0xff,0x55,0xff,0x55,0x09,0x8e,0xff,0x55,0xff,0x55,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x90,0xff,0x55,0xff,0x55,0x09,0x92,0xff,0x55,0xff,0x55,0x09,0x94,0xff,0x55,0xff,0x55,0x09,0x96,0xff,0x55,0xff,0x55,0x09,0x97,0x00,0xab,0x00,0xab,0x09,0x98,0x00,0xab,0x00,0xab, 0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xaa,0xff,0x55,0xff,0x55,0x09,0xab,0xff,0x55,0xff,0x55,0x09,0xac,0xff,0x55,0xff,0x55,0x09,0xae,0xff,0x55,0xff,0x55,0x09,0xb2,0xff,0x55,0xff,0x55,0x09,0xb7,0xff,0x55, 0xff,0x55,0x09,0xb8,0xff,0x55,0xff,0x55,0x09,0xb9,0xff,0x55,0xff,0x55,0x09,0xba,0xff,0x55,0xff,0x55,0x09,0xbb,0xff,0x55,0xff,0x55,0x09,0xbc,0xff,0x55,0xff,0x55,0x09,0xbd,0xff,0x55,0xff,0x55,0x09,0xbe,0xff,0x55,0xff,0x55,0x09,0xbf,0xff,0x55,0xff,0x55,0x09,0xc0,0xff,0x55,0xff,0x55,0x09,0xc1,0xff,0x55,0xff,0x55,0x09,0xc2, 0xff,0x55,0xff,0x55,0x09,0xc3,0xff,0x55,0xff,0x55,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xc6,0xff,0x55,0xff,0x55,0x09,0xc8,0xff,0x55,0xff,0x55,0x09,0xc9,0xff,0x55,0xff,0x55,0x09,0xca,0xff,0x55,0xff,0x55,0x09,0xcc,0xff,0x55,0xff,0x55,0x09,0xcd,0xff,0x55,0xff,0x55,0x09,0xd2,0xff,0x55,0xff,0x55,0x09,0xd3,0xff,0x55,0xff,0x55, 0x09,0xd7,0xff,0x55,0xff,0x55,0x09,0xd8,0xff,0x55,0xff,0x55,0x09,0xd9,0xff,0x55,0xff,0x55,0x09,0xda,0xff,0x55,0xff,0x55,0x09,0xdb,0xff,0x55,0xff,0x55,0x09,0xdc,0xff,0x55,0xff,0x55,0x09,0xdd,0xff,0x55,0xff,0x55,0x09,0xde,0xff,0x55,0xff,0x55,0x09,0xdf,0xff,0x55,0xff,0x55,0x09,0xe1,0xff,0x55,0xff,0x55,0x09,0xe2,0xff,0x55, 0xff,0x55,0x09,0xe3,0xff,0x55,0xff,0x55,0x09,0xe4,0xff,0x55,0xff,0x55,0x09,0xe5,0xff,0x55,0xff,0x55,0x09,0xe7,0xff,0x55,0xff,0x55,0x09,0xe8,0xff,0x55,0xff,0x55,0x09,0xe9,0xff,0x55,0xff,0x55,0x09,0xea,0xff,0x55,0xff,0x55,0x09,0xec,0xff,0x55,0xff,0x55,0x09,0xee,0xff,0x55,0xff,0x55,0x09,0xf0,0xff,0x55,0xff,0x55,0x09,0xf2, 0x00,0xab,0x00,0xab,0x09,0xfa,0x00,0xab,0x00,0xab,0x09,0xfe,0xff,0x55,0xff,0x55,0x09,0xff,0xff,0x55,0xff,0x55,0x0a,0x00,0xff,0x55,0xff,0x55,0x0a,0x01,0xff,0x55,0xff,0x55,0x0a,0x02,0xff,0x55,0xff,0x55,0x0a,0x03,0xff,0x55,0xff,0x55,0x0a,0x04,0xff,0x55,0xff,0x55,0x0a,0x05,0xff,0x55,0xff,0x55,0x0a,0x07,0xff,0x55,0xff,0x55, 0x0a,0x0a,0xff,0x55,0xff,0x55,0x0a,0x0b,0xff,0x55,0xff,0x55,0x0a,0x0d,0xff,0x55,0xff,0x55,0x0a,0x24,0xff,0x55,0xff,0x55,0x0a,0x25,0xff,0x55,0xff,0x55,0x0a,0x26,0xff,0x55,0xff,0x55,0x0a,0x27,0xff,0x55,0xff,0x55,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x2a,0xff,0x55,0xff,0x55,0x0a,0x3e,0xff,0x55,0xff,0x55,0x0a,0x56,0xff,0x55, 0xff,0x55,0x0a,0x58,0xff,0x55,0xff,0x55,0x0a,0x5a,0xff,0x55,0xff,0x55,0x0a,0x63,0xff,0x55,0xff,0x55,0x0a,0x72,0xff,0x55,0xff,0x55,0x0a,0x73,0x00,0xab,0x00,0xab,0x0a,0x74,0xff,0x55,0xff,0x55,0x0a,0x76,0xff,0x55,0xff,0x55,0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x78,0xff,0x55,0xff,0x55,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7a, 0xff,0x55,0xff,0x55,0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7c,0xff,0x55,0xff,0x55,0x0a,0x7d,0x00,0xab,0x00,0xab,0x0a,0x7e,0xff,0x55,0xff,0x55,0x0a,0x7f,0xff,0x55,0xff,0x55,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x86,0xff,0x55,0xff,0x55,0x0a,0x87,0xff,0x55,0xff,0x55,0x0a,0x88,0xff,0x55,0xff,0x55, 0x0a,0x89,0xff,0x55,0xff,0x55,0x0a,0x8a,0xff,0x55,0xff,0x55,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8d,0xff,0x55,0xff,0x55,0x0a,0x8f,0x00,0xab,0x00,0xab,0x0a,0x91,0xff,0x55,0xff,0x55,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0x95,0xff,0x55,0xff,0x55,0x0a,0x9d,0xff,0x55,0xff,0x55,0x0a,0x9e,0xff,0x55,0xff,0x55,0x0a,0xa0,0xff,0x55, 0xff,0x55,0x0a,0xa1,0xff,0x55,0xff,0x55,0x0a,0xa3,0xff,0x55,0xff,0x55,0x0a,0xa6,0xff,0x55,0xff,0x55,0x0a,0xa7,0xff,0x55,0xff,0x55,0x0a,0xa8,0xff,0x55,0xff,0x55,0x0a,0xa9,0xff,0x55,0xff,0x55,0x0a,0xab,0x00,0xab,0x00,0xab,0x0a,0xad,0xff,0x55,0xff,0x55,0x0a,0xaf,0xff,0x55,0xff,0x55,0x0a,0xb2,0xff,0x55,0xff,0x55,0x0a,0xb4, 0xff,0x55,0xff,0x55,0x0a,0xb5,0xff,0x55,0xff,0x55,0x0a,0xb6,0xff,0x55,0xff,0x55,0x0a,0xb7,0xff,0x55,0xff,0x55,0x0b,0x19,0xff,0x55,0xff,0x55,0x0e,0x20,0xff,0x55,0xff,0x55,0x0e,0x3a,0xff,0x55,0xff,0x55,0x0e,0x3d,0xff,0x55,0xff,0x55,0x0e,0x3f,0xff,0x55,0xff,0x55,0x0e,0x41,0xff,0x55,0xff,0x55,0x0e,0x43,0xff,0x55,0xff,0x55, 0x0e,0x47,0xff,0x55,0xff,0x55,0x0e,0x49,0x00,0xab,0x00,0xab,0x0e,0x4b,0xff,0x55,0xff,0x55,0x0e,0x4d,0x00,0xab,0x00,0xab,0x0e,0x4f,0xff,0x55,0xff,0x55,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0x5b,0xff,0x55,0xff,0x55,0x0e,0x5c,0xff,0x55,0xff,0x55,0x0e,0x5f,0xff,0x55,0xff,0x55,0x0e,0x6f,0xff,0x55,0xff,0x55,0x0e,0x71,0xff,0x55, 0xff,0x55,0x0e,0x76,0xff,0x55,0xff,0x55,0x0e,0xa3,0xff,0x55,0xff,0x55,0x0e,0xac,0xff,0x55,0xff,0x55,0x0e,0xaf,0xff,0x55,0xff,0x55,0x0e,0xd7,0xff,0x55,0xff,0x55,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16,0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x1e,0xff,0x55,0xff,0x55,0x0f,0x20, 0xff,0x55,0xff,0x55,0x0f,0x22,0xff,0x55,0xff,0x55,0x0f,0x24,0x00,0xab,0x00,0xab,0x0f,0x28,0xff,0x55,0xff,0x55,0x0f,0x2a,0xff,0x55,0xff,0x55,0x0f,0x2c,0xff,0x55,0xff,0x55,0x0f,0x2e,0x00,0xab,0x00,0xab,0x0f,0x30,0xff,0x55,0xff,0x55,0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x34,0xff,0x55,0xff,0x55,0x0f,0x36,0x00,0xab,0x00,0xab, 0x0f,0x38,0xff,0x55,0xff,0x55,0x0f,0x3a,0xff,0x55,0xff,0x55,0x0f,0x40,0x00,0xab,0x00,0xab,0x0f,0x44,0xff,0x55,0xff,0x55,0x0f,0x46,0xff,0x55,0xff,0x55,0x0f,0x48,0xff,0x55,0xff,0x55,0x0f,0x4a,0xff,0x55,0xff,0x55,0x0f,0x4c,0xff,0x55,0xff,0x55,0x0f,0x4e,0xff,0x55,0xff,0x55,0x0f,0x6c,0xff,0x55,0xff,0x55,0x0f,0x6e,0xff,0x55, 0xff,0x55,0x0f,0x70,0xff,0x55,0xff,0x55,0x0f,0x72,0xff,0x55,0xff,0x55,0x0f,0x74,0xff,0x55,0xff,0x55,0x0f,0x76,0xff,0x55,0xff,0x55,0x0f,0x78,0xff,0x55,0xff,0x55,0x0f,0x7a,0xff,0x55,0xff,0x55,0x0f,0x7c,0xff,0x55,0xff,0x55,0x0f,0x7e,0xff,0x55,0xff,0x55,0x0f,0x80,0xff,0x55,0xff,0x55,0x0f,0x82,0xff,0x55,0xff,0x55,0x0f,0x84, 0xff,0x55,0xff,0x55,0x0f,0x86,0xff,0x55,0xff,0x55,0x0f,0x88,0xff,0x55,0xff,0x55,0x0f,0x8a,0xff,0x55,0xff,0x55,0x0f,0x8c,0xff,0x55,0xff,0x55,0x0f,0x8e,0xff,0x55,0xff,0x55,0x0f,0x90,0xff,0x55,0xff,0x55,0x0f,0x92,0xff,0x55,0xff,0x55,0x0f,0x94,0x00,0xab,0x00,0xab,0x0f,0x96,0xff,0x55,0xff,0x55,0x0f,0xc0,0xff,0x55,0xff,0x55, 0x10,0xfe,0xff,0x55,0xff,0x55,0x11,0x00,0xff,0x55,0xff,0x55,0x11,0x02,0xff,0x55,0xff,0x55,0x11,0x04,0xff,0x55,0xff,0x55,0x11,0x06,0xff,0x55,0xff,0x55,0x11,0x08,0xff,0x55,0xff,0x55,0x11,0x0a,0xff,0x55,0xff,0x55,0x11,0x0c,0xff,0x55,0xff,0x55,0x11,0x0d,0xff,0x55,0xff,0x55,0x11,0x0f,0xff,0x55,0xff,0x55,0x14,0x53,0x00,0xab, 0x00,0xab,0x14,0x54,0xff,0x55,0xff,0x55,0x14,0x55,0xff,0x55,0xff,0x55,0x14,0x56,0xff,0x55,0xff,0x55,0x14,0x57,0xff,0x55,0xff,0x55,0x14,0x58,0xff,0x55,0xff,0x55,0x14,0x59,0xff,0x55,0xff,0x55,0x14,0x5a,0xff,0x55,0xff,0x55,0x14,0x6f,0xff,0x55,0xff,0x55,0x14,0x72,0xff,0x55,0xff,0x55,0x14,0x78,0x00,0xab,0x00,0xab,0x14,0x83, 0xff,0x55,0xff,0x55,0x14,0x86,0xff,0x55,0xff,0x55,0x14,0x97,0xff,0x55,0xff,0x55,0x14,0x98,0xff,0x55,0xff,0x55,0x00,0x9a,0x08,0xd6,0xff,0x55,0xff,0x55,0x08,0xe1,0xff,0x55,0xff,0x55,0x08,0xe2,0xff,0x55,0xff,0x55,0x08,0xe5,0xff,0x55,0xff,0x55,0x08,0xe8,0xff,0x55,0xff,0x55,0x08,0xeb,0xff,0x55,0xff,0x55,0x08,0xef,0xff,0x55, 0xff,0x55,0x08,0xf1,0xff,0x55,0xff,0x55,0x08,0xf4,0x00,0xab,0x00,0xab,0x09,0x07,0xff,0x55,0xff,0x55,0x09,0x0e,0xff,0x55,0xff,0x55,0x09,0x10,0xff,0x55,0xff,0x55,0x09,0x11,0xff,0x55,0xff,0x55,0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x15,0xff,0x55,0xff,0x55,0x09,0x16, 0xff,0x55,0xff,0x55,0x09,0x1b,0xff,0x55,0xff,0x55,0x09,0x1c,0xff,0x55,0xff,0x55,0x09,0x1d,0xff,0x55,0xff,0x55,0x09,0x1e,0xff,0x55,0xff,0x55,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x22,0xff,0x55,0xff,0x55,0x09,0x26,0xff,0x55,0xff,0x55,0x09,0x28,0xff,0x55,0xff,0x55,0x09,0x3c,0xff,0x55,0xff,0x55, 0x09,0x3e,0xff,0x55,0xff,0x55,0x09,0x40,0xff,0x55,0xff,0x55,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab,0x09,0x4c,0x00,0xab,0x00,0xab,0x09,0x4e,0xff,0x55,0xff,0x55,0x09,0x5b,0xff,0x55,0xff,0x55,0x09,0x5d,0xff,0x55,0xff,0x55,0x09,0x60,0xff,0x55,0xff,0x55,0x09,0x63,0xff,0x55,0xff,0x55,0x09,0x65,0xff,0x55, 0xff,0x55,0x09,0x67,0xff,0x55,0xff,0x55,0x09,0x6c,0xff,0x55,0xff,0x55,0x09,0x6d,0xff,0x55,0xff,0x55,0x09,0x8c,0xff,0x55,0xff,0x55,0x09,0x8e,0xff,0x55,0xff,0x55,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x90,0xff,0x55,0xff,0x55,0x09,0x92,0xff,0x55,0xff,0x55,0x09,0x94,0xff,0x55,0xff,0x55,0x09,0x96,0xff,0x55,0xff,0x55,0x09,0x97, 0x00,0xab,0x00,0xab,0x09,0x98,0x00,0xab,0x00,0xab,0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xaa,0xff,0x55,0xff,0x55,0x09,0xab,0xff,0x55,0xff,0x55,0x09,0xac,0xff,0x55,0xff,0x55,0x09,0xae,0xff,0x55,0xff,0x55, 0x09,0xbf,0xff,0x55,0xff,0x55,0x09,0xc0,0xff,0x55,0xff,0x55,0x09,0xc1,0xff,0x55,0xff,0x55,0x09,0xc2,0xff,0x55,0xff,0x55,0x09,0xc3,0xff,0x55,0xff,0x55,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xc6,0xff,0x55,0xff,0x55,0x09,0xc8,0xff,0x55,0xff,0x55,0x09,0xc9,0xff,0x55,0xff,0x55,0x09,0xca,0xff,0x55,0xff,0x55,0x09,0xcc,0xff,0x55, 0xff,0x55,0x09,0xcd,0xff,0x55,0xff,0x55,0x09,0xd2,0xff,0x55,0xff,0x55,0x09,0xd3,0xff,0x55,0xff,0x55,0x09,0xd7,0xff,0x55,0xff,0x55,0x09,0xd8,0xff,0x55,0xff,0x55,0x09,0xf2,0x00,0xab,0x00,0xab,0x09,0xfa,0x00,0xab,0x00,0xab,0x0a,0x26,0xff,0x55,0xff,0x55,0x0a,0x27,0xff,0x55,0xff,0x55,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x2a, 0xff,0x55,0xff,0x55,0x0a,0x58,0xff,0x55,0xff,0x55,0x0a,0x5a,0xff,0x55,0xff,0x55,0x0a,0x72,0xff,0x55,0xff,0x55,0x0a,0x73,0x00,0xab,0x00,0xab,0x0a,0x74,0xff,0x55,0xff,0x55,0x0a,0x76,0xff,0x55,0xff,0x55,0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x78,0xff,0x55,0xff,0x55,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7a,0xff,0x55,0xff,0x55, 0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7c,0xff,0x55,0xff,0x55,0x0a,0x7d,0x00,0xab,0x00,0xab,0x0a,0x7e,0xff,0x55,0xff,0x55,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x86,0xff,0x55,0xff,0x55,0x0a,0x87,0xff,0x55,0xff,0x55,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8d,0xff,0x55,0xff,0x55,0x0a,0x8f,0x00,0xab, 0x00,0xab,0x0a,0x91,0xff,0x55,0xff,0x55,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0x95,0xff,0x55,0xff,0x55,0x0a,0xa6,0xff,0x55,0xff,0x55,0x0a,0xa7,0xff,0x55,0xff,0x55,0x0a,0xa8,0xff,0x55,0xff,0x55,0x0a,0xa9,0xff,0x55,0xff,0x55,0x0a,0xab,0x00,0xab,0x00,0xab,0x0b,0x19,0xff,0x55,0xff,0x55,0x0e,0x3a,0xff,0x55,0xff,0x55,0x0e,0x3d, 0xff,0x55,0xff,0x55,0x0e,0x49,0x00,0xab,0x00,0xab,0x0e,0x4d,0x00,0xab,0x00,0xab,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0x5b,0xff,0x55,0xff,0x55,0x0e,0x5c,0xff,0x55,0xff,0x55,0x0e,0x5f,0xff,0x55,0xff,0x55,0x0e,0x6f,0xff,0x55,0xff,0x55,0x0e,0x71,0xff,0x55,0xff,0x55,0x0e,0xa3,0xff,0x55,0xff,0x55,0x0e,0xac,0xff,0x55,0xff,0x55, 0x0e,0xaf,0xff,0x55,0xff,0x55,0x0e,0xd7,0xff,0x55,0xff,0x55,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16,0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x24,0x00,0xab,0x00,0xab,0x0f,0x2e,0x00,0xab,0x00,0xab,0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x36,0x00,0xab,0x00,0xab,0x0f,0x3c,0xff,0x55, 0xff,0x55,0x0f,0x3e,0xff,0x55,0xff,0x55,0x0f,0x40,0x00,0xab,0x00,0xab,0x0f,0x82,0xff,0x55,0xff,0x55,0x0f,0x84,0xff,0x55,0xff,0x55,0x0f,0x86,0xff,0x55,0xff,0x55,0x0f,0x88,0xff,0x55,0xff,0x55,0x0f,0x8a,0xff,0x55,0xff,0x55,0x0f,0x94,0x00,0xab,0x00,0xab,0x14,0x53,0x00,0xab,0x00,0xab,0x14,0x55,0xff,0x55,0xff,0x55,0x14,0x56, 0xff,0x55,0xff,0x55,0x14,0x57,0xff,0x55,0xff,0x55,0x14,0x5a,0xff,0x55,0xff,0x55,0x14,0x6f,0xff,0x55,0xff,0x55,0x14,0x78,0x00,0xab,0x00,0xab,0x14,0x83,0xff,0x55,0xff,0x55,0x14,0x86,0xff,0x55,0xff,0x55,0x14,0x97,0xff,0x55,0xff,0x55,0x14,0x98,0xff,0x55,0xff,0x55,0x00,0x30,0x08,0xf4,0x00,0xab,0x00,0xab,0x09,0x0e,0xff,0x55, 0xff,0x55,0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab,0x09,0x4c,0x00,0xab,0x00,0xab,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x97,0x00,0xab,0x00,0xab,0x09,0x98, 0x00,0xab,0x00,0xab,0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xf2,0x00,0xab,0x00,0xab,0x09,0xfa,0x00,0xab,0x00,0xab,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x73,0x00,0xab,0x00,0xab, 0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7d,0x00,0xab,0x00,0xab,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8f,0x00,0xab,0x00,0xab,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0xab,0x00,0xab,0x00,0xab,0x0e,0x49,0x00,0xab, 0x00,0xab,0x0e,0x4d,0x00,0xab,0x00,0xab,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16,0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x24,0x00,0xab,0x00,0xab,0x0f,0x2e,0x00,0xab,0x00,0xab,0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x36,0x00,0xab,0x00,0xab,0x0f,0x40, 0x00,0xab,0x00,0xab,0x0f,0x94,0x00,0xab,0x00,0xab,0x14,0x53,0x00,0xab,0x00,0xab,0x14,0x78,0x00,0xab,0x00,0xab,0x01,0x3f,0x08,0xcc,0xff,0x55,0xff,0x55,0x08,0xcd,0xff,0x55,0xff,0x55,0x08,0xd4,0xff,0x55,0xff,0x55,0x08,0xd5,0xff,0x55,0xff,0x55,0x08,0xd6,0xff,0x55,0xff,0x55,0x08,0xe1,0xff,0x55,0xff,0x55,0x08,0xe2,0xff,0x55, 0xff,0x55,0x08,0xe5,0xff,0x55,0xff,0x55,0x08,0xe8,0xff,0x55,0xff,0x55,0x08,0xeb,0xff,0x55,0xff,0x55,0x08,0xed,0xff,0x55,0xff,0x55,0x08,0xee,0xff,0x55,0xff,0x55,0x08,0xef,0xff,0x55,0xff,0x55,0x08,0xf0,0xff,0x55,0xff,0x55,0x08,0xf1,0xff,0x55,0xff,0x55,0x08,0xf4,0x00,0xab,0x00,0xab,0x08,0xf9,0xff,0x55,0xff,0x55,0x08,0xfa, 0xff,0x55,0xff,0x55,0x08,0xff,0xff,0x55,0xff,0x55,0x09,0x01,0xff,0x55,0xff,0x55,0x09,0x06,0xff,0x55,0xff,0x55,0x09,0x07,0xff,0x55,0xff,0x55,0x09,0x08,0xff,0x55,0xff,0x55,0x09,0x09,0xff,0x55,0xff,0x55,0x09,0x0a,0xff,0x55,0xff,0x55,0x09,0x0c,0xff,0x55,0xff,0x55,0x09,0x0d,0xff,0x55,0xff,0x55,0x09,0x0f,0xff,0x55,0xff,0x55, 0x09,0x10,0xff,0x55,0xff,0x55,0x09,0x11,0xff,0x55,0xff,0x55,0x09,0x12,0x00,0xab,0x00,0xab,0x09,0x13,0x00,0xab,0x00,0xab,0x09,0x14,0x00,0xab,0x00,0xab,0x09,0x15,0xff,0x55,0xff,0x55,0x09,0x16,0xff,0x55,0xff,0x55,0x09,0x17,0xff,0x55,0xff,0x55,0x09,0x18,0xff,0x55,0xff,0x55,0x09,0x19,0xff,0x55,0xff,0x55,0x09,0x1a,0xff,0x55, 0xff,0x55,0x09,0x1b,0xff,0x55,0xff,0x55,0x09,0x1c,0xff,0x55,0xff,0x55,0x09,0x1d,0xff,0x55,0xff,0x55,0x09,0x1e,0xff,0x55,0xff,0x55,0x09,0x1f,0x00,0xab,0x00,0xab,0x09,0x20,0x00,0xab,0x00,0xab,0x09,0x22,0xff,0x55,0xff,0x55,0x09,0x24,0xff,0x55,0xff,0x55,0x09,0x26,0xff,0x55,0xff,0x55,0x09,0x28,0xff,0x55,0xff,0x55,0x09,0x29, 0xff,0x55,0xff,0x55,0x09,0x2a,0xff,0x55,0xff,0x55,0x09,0x2b,0xff,0x55,0xff,0x55,0x09,0x34,0xff,0x55,0xff,0x55,0x09,0x3c,0xff,0x55,0xff,0x55,0x09,0x3e,0xff,0x55,0xff,0x55,0x09,0x40,0xff,0x55,0xff,0x55,0x09,0x41,0x00,0xab,0x00,0xab,0x09,0x42,0x00,0xab,0x00,0xab,0x09,0x45,0xff,0x55,0xff,0x55,0x09,0x46,0xff,0x55,0xff,0x55, 0x09,0x47,0xff,0x55,0xff,0x55,0x09,0x48,0xff,0x55,0xff,0x55,0x09,0x49,0xff,0x55,0xff,0x55,0x09,0x4a,0xff,0x55,0xff,0x55,0x09,0x4c,0x00,0xab,0x00,0xab,0x09,0x4e,0xff,0x55,0xff,0x55,0x09,0x5b,0xff,0x55,0xff,0x55,0x09,0x5c,0xff,0x55,0xff,0x55,0x09,0x5d,0xff,0x55,0xff,0x55,0x09,0x5e,0xff,0x55,0xff,0x55,0x09,0x60,0xff,0x55, 0xff,0x55,0x09,0x63,0xff,0x55,0xff,0x55,0x09,0x64,0xff,0x55,0xff,0x55,0x09,0x6c,0xff,0x55,0xff,0x55,0x09,0x6d,0xff,0x55,0xff,0x55,0x09,0x71,0xff,0x55,0xff,0x55,0x09,0x80,0xff,0x55,0xff,0x55,0x09,0x82,0xff,0x55,0xff,0x55,0x09,0x88,0xff,0x55,0xff,0x55,0x09,0x89,0xff,0x55,0xff,0x55,0x09,0x8a,0xff,0x55,0xff,0x55,0x09,0x8c, 0xff,0x55,0xff,0x55,0x09,0x8d,0xff,0x55,0xff,0x55,0x09,0x8e,0xff,0x55,0xff,0x55,0x09,0x8f,0x00,0xab,0x00,0xab,0x09,0x90,0xff,0x55,0xff,0x55,0x09,0x92,0xff,0x55,0xff,0x55,0x09,0x93,0xff,0x55,0xff,0x55,0x09,0x94,0xff,0x55,0xff,0x55,0x09,0x95,0xff,0x55,0xff,0x55,0x09,0x96,0xff,0x55,0xff,0x55,0x09,0x97,0x00,0xab,0x00,0xab, 0x09,0x98,0x00,0xab,0x00,0xab,0x09,0x9b,0x00,0xab,0x00,0xab,0x09,0x9e,0x00,0xab,0x00,0xab,0x09,0xa1,0x00,0xab,0x00,0xab,0x09,0xa4,0x00,0xab,0x00,0xab,0x09,0xa7,0x00,0xab,0x00,0xab,0x09,0xaa,0xff,0x55,0xff,0x55,0x09,0xab,0xff,0x55,0xff,0x55,0x09,0xac,0xff,0x55,0xff,0x55,0x09,0xae,0xff,0x55,0xff,0x55,0x09,0xb2,0xff,0x55, 0xff,0x55,0x09,0xb3,0xff,0x55,0xff,0x55,0x09,0xb4,0xff,0x55,0xff,0x55,0x09,0xb5,0xff,0x55,0xff,0x55,0x09,0xb6,0xff,0x55,0xff,0x55,0x09,0xb7,0xff,0x55,0xff,0x55,0x09,0xb8,0xff,0x55,0xff,0x55,0x09,0xb9,0xff,0x55,0xff,0x55,0x09,0xba,0xff,0x55,0xff,0x55,0x09,0xbb,0xff,0x55,0xff,0x55,0x09,0xbc,0xff,0x55,0xff,0x55,0x09,0xbd, 0xff,0x55,0xff,0x55,0x09,0xbe,0xff,0x55,0xff,0x55,0x09,0xbf,0xff,0x55,0xff,0x55,0x09,0xc0,0xff,0x55,0xff,0x55,0x09,0xc1,0xff,0x55,0xff,0x55,0x09,0xc2,0xff,0x55,0xff,0x55,0x09,0xc3,0xff,0x55,0xff,0x55,0x09,0xc4,0x00,0xab,0x00,0xab,0x09,0xc6,0xff,0x55,0xff,0x55,0x09,0xc8,0xff,0x55,0xff,0x55,0x09,0xc9,0xff,0x55,0xff,0x55, 0x09,0xca,0xff,0x55,0xff,0x55,0x09,0xcc,0xff,0x55,0xff,0x55,0x09,0xcd,0xff,0x55,0xff,0x55,0x09,0xd2,0xff,0x55,0xff,0x55,0x09,0xd3,0xff,0x55,0xff,0x55,0x09,0xd7,0xff,0x55,0xff,0x55,0x09,0xd8,0xff,0x55,0xff,0x55,0x09,0xd9,0xff,0x55,0xff,0x55,0x09,0xda,0xff,0x55,0xff,0x55,0x09,0xdb,0xff,0x55,0xff,0x55,0x09,0xdc,0xff,0x55, 0xff,0x55,0x09,0xdd,0xff,0x55,0xff,0x55,0x09,0xde,0xff,0x55,0xff,0x55,0x09,0xdf,0xff,0x55,0xff,0x55,0x09,0xe1,0xff,0x55,0xff,0x55,0x09,0xe2,0xff,0x55,0xff,0x55,0x09,0xe3,0xff,0x55,0xff,0x55,0x09,0xe4,0xff,0x55,0xff,0x55,0x09,0xe5,0xff,0x55,0xff,0x55,0x09,0xe7,0xff,0x55,0xff,0x55,0x09,0xe8,0xff,0x55,0xff,0x55,0x09,0xe9, 0xff,0x55,0xff,0x55,0x09,0xea,0xff,0x55,0xff,0x55,0x09,0xec,0xff,0x55,0xff,0x55,0x09,0xee,0xff,0x55,0xff,0x55,0x09,0xf0,0xff,0x55,0xff,0x55,0x09,0xf2,0x00,0xab,0x00,0xab,0x09,0xf9,0xff,0x55,0xff,0x55,0x09,0xfa,0x00,0xab,0x00,0xab,0x09,0xfd,0xff,0x55,0xff,0x55,0x09,0xfe,0xff,0x55,0xff,0x55,0x09,0xff,0xff,0x55,0xff,0x55, 0x0a,0x00,0xff,0x55,0xff,0x55,0x0a,0x01,0xff,0x55,0xff,0x55,0x0a,0x02,0xff,0x55,0xff,0x55,0x0a,0x03,0xff,0x55,0xff,0x55,0x0a,0x04,0xff,0x55,0xff,0x55,0x0a,0x05,0xff,0x55,0xff,0x55,0x0a,0x07,0xff,0x55,0xff,0x55,0x0a,0x0a,0xff,0x55,0xff,0x55,0x0a,0x0b,0xff,0x55,0xff,0x55,0x0a,0x0d,0xff,0x55,0xff,0x55,0x0a,0x24,0xff,0x55, 0xff,0x55,0x0a,0x25,0xff,0x55,0xff,0x55,0x0a,0x26,0xff,0x55,0xff,0x55,0x0a,0x27,0xff,0x55,0xff,0x55,0x0a,0x28,0x00,0xab,0x00,0xab,0x0a,0x2a,0xff,0x55,0xff,0x55,0x0a,0x3e,0xff,0x55,0xff,0x55,0x0a,0x56,0xff,0x55,0xff,0x55,0x0a,0x58,0xff,0x55,0xff,0x55,0x0a,0x5a,0xff,0x55,0xff,0x55,0x0a,0x63,0xff,0x55,0xff,0x55,0x0a,0x72, 0xff,0x55,0xff,0x55,0x0a,0x73,0x00,0xab,0x00,0xab,0x0a,0x74,0xff,0x55,0xff,0x55,0x0a,0x76,0xff,0x55,0xff,0x55,0x0a,0x77,0x00,0xab,0x00,0xab,0x0a,0x78,0xff,0x55,0xff,0x55,0x0a,0x79,0x00,0xab,0x00,0xab,0x0a,0x7a,0xff,0x55,0xff,0x55,0x0a,0x7b,0x00,0xab,0x00,0xab,0x0a,0x7c,0xff,0x55,0xff,0x55,0x0a,0x7d,0x00,0xab,0x00,0xab, 0x0a,0x7e,0xff,0x55,0xff,0x55,0x0a,0x7f,0xff,0x55,0xff,0x55,0x0a,0x80,0x00,0xab,0x00,0xab,0x0a,0x83,0x00,0xab,0x00,0xab,0x0a,0x86,0xff,0x55,0xff,0x55,0x0a,0x87,0xff,0x55,0xff,0x55,0x0a,0x88,0xff,0x55,0xff,0x55,0x0a,0x89,0xff,0x55,0xff,0x55,0x0a,0x8a,0xff,0x55,0xff,0x55,0x0a,0x8b,0x00,0xab,0x00,0xab,0x0a,0x8d,0xff,0x55, 0xff,0x55,0x0a,0x8f,0x00,0xab,0x00,0xab,0x0a,0x91,0xff,0x55,0xff,0x55,0x0a,0x93,0x00,0xab,0x00,0xab,0x0a,0x95,0xff,0x55,0xff,0x55,0x0a,0x9d,0xff,0x55,0xff,0x55,0x0a,0x9e,0xff,0x55,0xff,0x55,0x0a,0xa0,0xff,0x55,0xff,0x55,0x0a,0xa1,0xff,0x55,0xff,0x55,0x0a,0xa3,0xff,0x55,0xff,0x55,0x0a,0xa6,0xff,0x55,0xff,0x55,0x0a,0xa7, 0xff,0x55,0xff,0x55,0x0a,0xa8,0xff,0x55,0xff,0x55,0x0a,0xa9,0xff,0x55,0xff,0x55,0x0a,0xab,0x00,0xab,0x00,0xab,0x0a,0xad,0xff,0x55,0xff,0x55,0x0a,0xaf,0xff,0x55,0xff,0x55,0x0a,0xb2,0xff,0x55,0xff,0x55,0x0a,0xb4,0xff,0x55,0xff,0x55,0x0a,0xb5,0xff,0x55,0xff,0x55,0x0a,0xb6,0xff,0x55,0xff,0x55,0x0a,0xb7,0xff,0x55,0xff,0x55, 0x0b,0x19,0xff,0x55,0xff,0x55,0x0e,0x20,0xff,0x55,0xff,0x55,0x0e,0x3a,0xff,0x55,0xff,0x55,0x0e,0x3d,0xff,0x55,0xff,0x55,0x0e,0x3f,0xff,0x55,0xff,0x55,0x0e,0x41,0xff,0x55,0xff,0x55,0x0e,0x43,0xff,0x55,0xff,0x55,0x0e,0x47,0xff,0x55,0xff,0x55,0x0e,0x49,0x00,0xab,0x00,0xab,0x0e,0x4b,0xff,0x55,0xff,0x55,0x0e,0x4d,0x00,0xab, 0x00,0xab,0x0e,0x4f,0xff,0x55,0xff,0x55,0x0e,0x51,0x00,0xab,0x00,0xab,0x0e,0x5b,0xff,0x55,0xff,0x55,0x0e,0x5c,0xff,0x55,0xff,0x55,0x0e,0x5f,0xff,0x55,0xff,0x55,0x0e,0x6f,0xff,0x55,0xff,0x55,0x0e,0x71,0xff,0x55,0xff,0x55,0x0e,0x76,0xff,0x55,0xff,0x55,0x0e,0xa3,0xff,0x55,0xff,0x55,0x0e,0xac,0xff,0x55,0xff,0x55,0x0e,0xaf, 0xff,0x55,0xff,0x55,0x0e,0xd1,0xff,0x55,0xff,0x55,0x0e,0xd7,0xff,0x55,0xff,0x55,0x0e,0xe7,0x00,0xab,0x00,0xab,0x0e,0xe9,0x00,0xab,0x00,0xab,0x0f,0x16,0x00,0xab,0x00,0xab,0x0f,0x1a,0x00,0xab,0x00,0xab,0x0f,0x1e,0xff,0x55,0xff,0x55,0x0f,0x20,0xff,0x55,0xff,0x55,0x0f,0x22,0xff,0x55,0xff,0x55,0x0f,0x24,0x00,0xab,0x00,0xab, 0x0f,0x28,0xff,0x55,0xff,0x55,0x0f,0x2a,0xff,0x55,0xff,0x55,0x0f,0x2c,0xff,0x55,0xff,0x55,0x0f,0x2e,0x00,0xab,0x00,0xab,0x0f,0x30,0xff,0x55,0xff,0x55,0x0f,0x32,0x00,0xab,0x00,0xab,0x0f,0x34,0xff,0x55,0xff,0x55,0x0f,0x36,0x00,0xab,0x00,0xab,0x0f,0x38,0xff,0x55,0xff,0x55,0x0f,0x3a,0xff,0x55,0xff,0x55,0x0f,0x40,0x00,0xab, 0x00,0xab,0x0f,0x44,0xff,0x55,0xff,0x55,0x0f,0x46,0xff,0x55,0xff,0x55,0x0f,0x48,0xff,0x55,0xff,0x55,0x0f,0x4a,0xff,0x55,0xff,0x55,0x0f,0x4c,0xff,0x55,0xff,0x55,0x0f,0x4e,0xff,0x55,0xff,0x55,0x0f,0x6c,0xff,0x55,0xff,0x55,0x0f,0x6e,0xff,0x55,0xff,0x55,0x0f,0x70,0xff,0x55,0xff,0x55,0x0f,0x72,0xff,0x55,0xff,0x55,0x0f,0x74, 0xff,0x55,0xff,0x55,0x0f,0x76,0xff,0x55,0xff,0x55,0x0f,0x78,0xff,0x55,0xff,0x55,0x0f,0x7a,0xff,0x55,0xff,0x55,0x0f,0x7c,0xff,0x55,0xff,0x55,0x0f,0x7e,0xff,0x55,0xff,0x55,0x0f,0x80,0xff,0x55,0xff,0x55,0x0f,0x82,0xff,0x55,0xff,0x55,0x0f,0x84,0xff,0x55,0xff,0x55,0x0f,0x86,0xff,0x55,0xff,0x55,0x0f,0x88,0xff,0x55,0xff,0x55, 0x0f,0x8a,0xff,0x55,0xff,0x55,0x0f,0x8c,0xff,0x55,0xff,0x55,0x0f,0x8e,0xff,0x55,0xff,0x55,0x0f,0x90,0xff,0x55,0xff,0x55,0x0f,0x92,0xff,0x55,0xff,0x55,0x0f,0x94,0x00,0xab,0x00,0xab,0x0f,0x96,0xff,0x55,0xff,0x55,0x0f,0xc0,0xff,0x55,0xff,0x55,0x10,0xfe,0xff,0x55,0xff,0x55,0x11,0x00,0xff,0x55,0xff,0x55,0x11,0x02,0xff,0x55, 0xff,0x55,0x11,0x04,0xff,0x55,0xff,0x55,0x11,0x06,0xff,0x55,0xff,0x55,0x11,0x08,0xff,0x55,0xff,0x55,0x11,0x0a,0xff,0x55,0xff,0x55,0x11,0x0c,0xff,0x55,0xff,0x55,0x11,0x0d,0xff,0x55,0xff,0x55,0x11,0x0f,0xff,0x55,0xff,0x55,0x14,0x53,0x00,0xab,0x00,0xab,0x14,0x54,0xff,0x55,0xff,0x55,0x14,0x55,0xff,0x55,0xff,0x55,0x14,0x56, 0xff,0x55,0xff,0x55,0x14,0x57,0xff,0x55,0xff,0x55,0x14,0x58,0xff,0x55,0xff,0x55,0x14,0x59,0xff,0x55,0xff,0x55,0x14,0x5a,0xff,0x55,0xff,0x55,0x14,0x6f,0xff,0x55,0xff,0x55,0x14,0x72,0xff,0x55,0xff,0x55,0x14,0x75,0xff,0x55,0xff,0x55,0x14,0x78,0x00,0xab,0x00,0xab,0x14,0x7b,0xff,0x55,0xff,0x55,0x14,0x83,0xff,0x55,0xff,0x55, 0x14,0x86,0xff,0x55,0xff,0x55,0x14,0x97,0xff,0x55,0xff,0x55,0x14,0x98,0xff,0x55,0xff,0x55,0x00,0x02,0x00,0x1e,0x08,0xc8,0x08,0xc9,0x00,0x00,0x08,0xff,0x09,0x01,0x00,0x02,0x09,0x04,0x09,0x04,0x00,0x05,0x09,0x08,0x09,0x09,0x00,0x06,0x09,0x17,0x09,0x18,0x00,0x08,0x09,0x45,0x09,0x45,0x00,0x0a,0x09,0x5d,0x09,0x5e,0x00,0x0b, 0x09,0x80,0x09,0x83,0x00,0x0d,0x09,0xad,0x09,0xad,0x00,0x11,0x09,0xaf,0x09,0xb1,0x00,0x12,0x09,0xb3,0x09,0xb8,0x00,0x15,0x0a,0x54,0x0a,0x57,0x00,0x1b,0x0a,0x88,0x0a,0x88,0x00,0x1f,0x0a,0xb4,0x0a,0xb5,0x00,0x20,0x0b,0x0c,0x0b,0x0f,0x00,0x22,0x0b,0x11,0x0b,0x18,0x00,0x26,0x0e,0x8f,0x0e,0x8f,0x00,0x2e,0x0e,0x93,0x0e,0x93, 0x00,0x2f,0x0e,0x95,0x0e,0x97,0x00,0x30,0x0f,0x02,0x0f,0x02,0x00,0x33,0x0f,0x22,0x0f,0x23,0x00,0x34,0x0f,0x28,0x0f,0x2b,0x00,0x36,0x0f,0x62,0x0f,0x63,0x00,0x3a,0x0f,0x66,0x0f,0x67,0x00,0x3c,0x0f,0x6a,0x0f,0x6b,0x00,0x3e,0x0f,0x98,0x0f,0xa6,0x00,0x40,0x0f,0xc3,0x0f,0xc3,0x00,0x4f,0x14,0x58,0x14,0x58,0x00,0x50,0x14,0x7d, 0x14,0x7d,0x00,0x51,0x14,0xad,0x14,0xad,0x00,0x52,0x00,0x02,0x01,0x70,0x00,0x05,0x00,0x00,0x02,0x2e,0x03,0x3a,0x00,0x08,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0xab,0x00,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x55,0xff,0x55,0xff,0x55, 0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0x00,0xab,0x00,0xab,0x00,0xab,0x00,0xab,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0x00,0x00,0x00,0x00,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0x00,0xab,0x00,0xab,0x00,0xab, 0x00,0xab,0xff,0x55,0xff,0x55,0xff,0x55,0xff,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x55,0xff,0x55,0x00,0x00,0x00,0x00,0xff,0x55,0xff,0x55,0x00,0x00,0x00,0x00,0x00,0xab,0x00,0xab,0x00,0xab,0x00,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x55,0xff,0x55,0x00,0x02,0x00,0x1f,0x08,0xc9, 0x08,0xca,0x00,0x00,0x08,0xff,0x09,0x01,0x00,0x02,0x09,0x04,0x09,0x04,0x00,0x05,0x09,0x08,0x09,0x08,0x00,0x06,0x09,0x0a,0x09,0x0b,0x00,0x07,0x09,0x29,0x09,0x29,0x00,0x09,0x09,0x45,0x09,0x45,0x00,0x0a,0x09,0x85,0x09,0x85,0x00,0x0b,0x09,0xb3,0x09,0xb8,0x00,0x0c,0x0a,0x56,0x0a,0x57,0x00,0x12,0x0a,0xb4,0x0a,0xb5,0x00,0x14, 0x0b,0x0c,0x0b,0x0f,0x00,0x16,0x0b,0x11,0x0b,0x18,0x00,0x1a,0x0e,0x24,0x0e,0x24,0x00,0x22,0x0e,0x5e,0x0e,0x5e,0x00,0x23,0x0e,0x74,0x0e,0x75,0x00,0x24,0x0e,0xdc,0x0e,0xe3,0x00,0x26,0x0e,0xe6,0x0e,0xe6,0x00,0x2e,0x0f,0x02,0x0f,0x02,0x00,0x2f,0x0f,0x22,0x0f,0x23,0x00,0x30,0x0f,0x39,0x0f,0x39,0x00,0x32,0x0f,0x3b,0x0f,0x3b, 0x00,0x33,0x0f,0x62,0x0f,0x63,0x00,0x34,0x0f,0x66,0x0f,0x67,0x00,0x36,0x0f,0x6a,0x0f,0x6b,0x00,0x38,0x0f,0x98,0x0f,0xa6,0x00,0x3a,0x0f,0xc3,0x0f,0xc3,0x00,0x49,0x11,0x02,0x11,0x09,0x00,0x4a,0x14,0x58,0x14,0x58,0x00,0x52,0x14,0x7d,0x14,0x7d,0x00,0x53,0x14,0xad,0x14,0xad,0x00,0x54,0x00,0x02,0x00,0x2c,0x08,0xc9,0x08,0xc9, 0x00,0x01,0x08,0xca,0x08,0xca,0x00,0x03,0x08,0xff,0x09,0x01,0x00,0x04,0x09,0x04,0x09,0x04,0x00,0x04,0x09,0x08,0x09,0x08,0x00,0x01,0x09,0x0a,0x09,0x0a,0x00,0x02,0x09,0x0b,0x09,0x0b,0x00,0x03,0x09,0x29,0x09,0x29,0x00,0x02,0x09,0x45,0x09,0x45,0x00,0x07,0x09,0x85,0x09,0x85,0x00,0x03,0x09,0xb3,0x09,0xb5,0x00,0x05,0x09,0xb6, 0x09,0xb6,0x00,0x06,0x09,0xb7,0x09,0xb8,0x00,0x07,0x0a,0x56,0x0a,0x57,0x00,0x07,0x0a,0xb4,0x0a,0xb5,0x00,0x07,0x0b,0x0c,0x0b,0x0c,0x00,0x05,0x0b,0x0d,0x0b,0x0d,0x00,0x06,0x0b,0x0e,0x0b,0x0f,0x00,0x07,0x0b,0x11,0x0b,0x13,0x00,0x05,0x0b,0x14,0x0b,0x14,0x00,0x06,0x0b,0x15,0x0b,0x18,0x00,0x07,0x0e,0x24,0x0e,0x24,0x00,0x02, 0x0e,0x5e,0x0e,0x5e,0x00,0x02,0x0e,0x74,0x0e,0x75,0x00,0x02,0x0e,0xdc,0x0e,0xe3,0x00,0x02,0x0e,0xe6,0x0e,0xe6,0x00,0x02,0x0f,0x02,0x0f,0x02,0x00,0x06,0x0f,0x22,0x0f,0x23,0x00,0x07,0x0f,0x39,0x0f,0x39,0x00,0x02,0x0f,0x3b,0x0f,0x3b,0x00,0x02,0x0f,0x62,0x0f,0x63,0x00,0x04,0x0f,0x66,0x0f,0x67,0x00,0x04,0x0f,0x6a,0x0f,0x6b, 0x00,0x04,0x0f,0x98,0x0f,0x99,0x00,0x05,0x0f,0x9a,0x0f,0x9b,0x00,0x07,0x0f,0x9c,0x0f,0x9f,0x00,0x05,0x0f,0xa0,0x0f,0xa2,0x00,0x07,0x0f,0xa3,0x0f,0xa3,0x00,0x05,0x0f,0xa4,0x0f,0xa6,0x00,0x07,0x0f,0xc3,0x0f,0xc3,0x00,0x07,0x11,0x02,0x11,0x09,0x00,0x02,0x14,0x58,0x14,0x58,0x00,0x07,0x14,0x7d,0x14,0x7d,0x00,0x07,0x14,0xad, 0x14,0xad,0x00,0x07,0x00,0x02,0x00,0xf0,0x08,0xcc,0x08,0xcd,0x00,0x05,0x08,0xd4,0x08,0xd5,0x00,0x01,0x08,0xd6,0x08,0xd6,0x00,0x02,0x08,0xe1,0x08,0xe2,0x00,0x02,0x08,0xe5,0x08,0xe5,0x00,0x02,0x08,0xe8,0x08,0xe8,0x00,0x02,0x08,0xeb,0x08,0xeb,0x00,0x02,0x08,0xed,0x08,0xed,0x00,0x08,0x08,0xee,0x08,0xee,0x00,0x01,0x08,0xef, 0x08,0xef,0x00,0x02,0x08,0xf0,0x08,0xf0,0x00,0x01,0x08,0xf1,0x08,0xf1,0x00,0x02,0x08,0xf4,0x08,0xf4,0x00,0x06,0x08,0xf9,0x08,0xfa,0x00,0x01,0x08,0xff,0x08,0xff,0x00,0x01,0x09,0x01,0x09,0x01,0x00,0x01,0x09,0x06,0x09,0x06,0x00,0x01,0x09,0x07,0x09,0x07,0x00,0x02,0x09,0x09,0x09,0x09,0x00,0x03,0x09,0x0a,0x09,0x0a,0x00,0x01, 0x09,0x0c,0x09,0x0d,0x00,0x01,0x09,0x0f,0x09,0x0f,0x00,0x04,0x09,0x10,0x09,0x11,0x00,0x02,0x09,0x12,0x09,0x14,0x00,0x06,0x09,0x15,0x09,0x16,0x00,0x02,0x09,0x17,0x09,0x1a,0x00,0x01,0x09,0x1b,0x09,0x1e,0x00,0x02,0x09,0x1f,0x09,0x20,0x00,0x07,0x09,0x22,0x09,0x22,0x00,0x02,0x09,0x24,0x09,0x24,0x00,0x01,0x09,0x26,0x09,0x26, 0x00,0x02,0x09,0x28,0x09,0x28,0x00,0x02,0x09,0x29,0x09,0x2b,0x00,0x01,0x09,0x34,0x09,0x34,0x00,0x01,0x09,0x3c,0x09,0x3c,0x00,0x02,0x09,0x3e,0x09,0x3e,0x00,0x02,0x09,0x40,0x09,0x40,0x00,0x02,0x09,0x41,0x09,0x42,0x00,0x06,0x09,0x45,0x09,0x45,0x00,0x01,0x09,0x46,0x09,0x49,0x00,0x08,0x09,0x4a,0x09,0x4a,0x00,0x01,0x09,0x4c, 0x09,0x4c,0x00,0x06,0x09,0x4e,0x09,0x4e,0x00,0x02,0x09,0x5b,0x09,0x5b,0x00,0x02,0x09,0x5c,0x09,0x5c,0x00,0x05,0x09,0x5d,0x09,0x5d,0x00,0x02,0x09,0x5e,0x09,0x5e,0x00,0x01,0x09,0x60,0x09,0x60,0x00,0x02,0x09,0x63,0x09,0x63,0x00,0x02,0x09,0x64,0x09,0x64,0x00,0x04,0x09,0x65,0x09,0x65,0x00,0x0a,0x09,0x67,0x09,0x67,0x00,0x0a, 0x09,0x6c,0x09,0x6d,0x00,0x02,0x09,0x71,0x09,0x71,0x00,0x01,0x09,0x80,0x09,0x80,0x00,0x03,0x09,0x82,0x09,0x82,0x00,0x03,0x09,0x88,0x09,0x8a,0x00,0x01,0x09,0x8c,0x09,0x8c,0x00,0x02,0x09,0x8d,0x09,0x8d,0x00,0x01,0x09,0x8e,0x09,0x8e,0x00,0x02,0x09,0x8f,0x09,0x8f,0x00,0x06,0x09,0x90,0x09,0x90,0x00,0x02,0x09,0x92,0x09,0x92, 0x00,0x02,0x09,0x93,0x09,0x93,0x00,0x05,0x09,0x94,0x09,0x94,0x00,0x02,0x09,0x95,0x09,0x95,0x00,0x05,0x09,0x96,0x09,0x96,0x00,0x02,0x09,0x97,0x09,0x98,0x00,0x06,0x09,0x9b,0x09,0x9b,0x00,0x06,0x09,0x9e,0x09,0x9e,0x00,0x06,0x09,0xa1,0x09,0xa1,0x00,0x06,0x09,0xa4,0x09,0xa4,0x00,0x06,0x09,0xa7,0x09,0xa7,0x00,0x06,0x09,0xaa, 0x09,0xac,0x00,0x02,0x09,0xae,0x09,0xae,0x00,0x02,0x09,0xb2,0x09,0xb2,0x00,0x01,0x09,0xb3,0x09,0xb6,0x00,0x09,0x09,0xb7,0x09,0xbe,0x00,0x01,0x09,0xbf,0x09,0xc3,0x00,0x02,0x09,0xc4,0x09,0xc4,0x00,0x07,0x09,0xc6,0x09,0xc6,0x00,0x02,0x09,0xc8,0x09,0xca,0x00,0x02,0x09,0xcc,0x09,0xcd,0x00,0x02,0x09,0xd2,0x09,0xd3,0x00,0x02, 0x09,0xd7,0x09,0xd8,0x00,0x02,0x09,0xd9,0x09,0xda,0x00,0x08,0x09,0xdb,0x09,0xdb,0x00,0x01,0x09,0xdc,0x09,0xdc,0x00,0x08,0x09,0xdd,0x09,0xdd,0x00,0x01,0x09,0xde,0x09,0xde,0x00,0x08,0x09,0xdf,0x09,0xdf,0x00,0x01,0x09,0xe1,0x09,0xe5,0x00,0x08,0x09,0xe7,0x09,0xea,0x00,0x08,0x09,0xec,0x09,0xec,0x00,0x01,0x09,0xee,0x09,0xee, 0x00,0x01,0x09,0xf0,0x09,0xf0,0x00,0x01,0x09,0xf2,0x09,0xf2,0x00,0x06,0x09,0xf9,0x09,0xf9,0x00,0x05,0x09,0xfa,0x09,0xfa,0x00,0x06,0x09,0xfd,0x09,0xfd,0x00,0x09,0x09,0xfe,0x0a,0x05,0x00,0x01,0x0a,0x07,0x0a,0x07,0x00,0x01,0x0a,0x0a,0x0a,0x0b,0x00,0x01,0x0a,0x0d,0x0a,0x0d,0x00,0x01,0x0a,0x24,0x0a,0x25,0x00,0x01,0x0a,0x26, 0x0a,0x27,0x00,0x02,0x0a,0x28,0x0a,0x28,0x00,0x07,0x0a,0x2a,0x0a,0x2a,0x00,0x02,0x0a,0x3e,0x0a,0x3e,0x00,0x08,0x0a,0x56,0x0a,0x56,0x00,0x01,0x0a,0x58,0x0a,0x58,0x00,0x02,0x0a,0x5a,0x0a,0x5a,0x00,0x02,0x0a,0x63,0x0a,0x63,0x00,0x01,0x0a,0x72,0x0a,0x72,0x00,0x02,0x0a,0x73,0x0a,0x73,0x00,0x06,0x0a,0x74,0x0a,0x74,0x00,0x02, 0x0a,0x76,0x0a,0x76,0x00,0x02,0x0a,0x77,0x0a,0x77,0x00,0x06,0x0a,0x78,0x0a,0x78,0x00,0x02,0x0a,0x79,0x0a,0x79,0x00,0x06,0x0a,0x7a,0x0a,0x7a,0x00,0x02,0x0a,0x7b,0x0a,0x7b,0x00,0x06,0x0a,0x7c,0x0a,0x7c,0x00,0x02,0x0a,0x7d,0x0a,0x7d,0x00,0x06,0x0a,0x7e,0x0a,0x7e,0x00,0x02,0x0a,0x7f,0x0a,0x7f,0x00,0x01,0x0a,0x80,0x0a,0x80, 0x00,0x06,0x0a,0x83,0x0a,0x83,0x00,0x06,0x0a,0x86,0x0a,0x87,0x00,0x02,0x0a,0x88,0x0a,0x8a,0x00,0x01,0x0a,0x8b,0x0a,0x8b,0x00,0x07,0x0a,0x8d,0x0a,0x8d,0x00,0x02,0x0a,0x8f,0x0a,0x8f,0x00,0x07,0x0a,0x91,0x0a,0x91,0x00,0x02,0x0a,0x93,0x0a,0x93,0x00,0x07,0x0a,0x95,0x0a,0x95,0x00,0x02,0x0a,0x9d,0x0a,0x9e,0x00,0x08,0x0a,0xa0, 0x0a,0xa1,0x00,0x08,0x0a,0xa3,0x0a,0xa3,0x00,0x08,0x0a,0xa6,0x0a,0xa9,0x00,0x02,0x0a,0xab,0x0a,0xab,0x00,0x06,0x0a,0xad,0x0a,0xad,0x00,0x01,0x0a,0xaf,0x0a,0xaf,0x00,0x01,0x0a,0xb2,0x0a,0xb2,0x00,0x01,0x0a,0xb4,0x0a,0xb7,0x00,0x01,0x0b,0x19,0x0b,0x19,0x00,0x02,0x0e,0x20,0x0e,0x20,0x00,0x01,0x0e,0x3a,0x0e,0x3a,0x00,0x02, 0x0e,0x3d,0x0e,0x3d,0x00,0x02,0x0e,0x3f,0x0e,0x3f,0x00,0x08,0x0e,0x41,0x0e,0x41,0x00,0x08,0x0e,0x43,0x0e,0x43,0x00,0x08,0x0e,0x47,0x0e,0x47,0x00,0x01,0x0e,0x49,0x0e,0x49,0x00,0x06,0x0e,0x4b,0x0e,0x4b,0x00,0x01,0x0e,0x4d,0x0e,0x4d,0x00,0x06,0x0e,0x4f,0x0e,0x4f,0x00,0x01,0x0e,0x51,0x0e,0x51,0x00,0x06,0x0e,0x5b,0x0e,0x5c, 0x00,0x02,0x0e,0x5f,0x0e,0x5f,0x00,0x02,0x0e,0x6f,0x0e,0x6f,0x00,0x02,0x0e,0x71,0x0e,0x71,0x00,0x02,0x0e,0x76,0x0e,0x76,0x00,0x01,0x0e,0xa3,0x0e,0xa3,0x00,0x02,0x0e,0xac,0x0e,0xac,0x00,0x02,0x0e,0xaf,0x0e,0xaf,0x00,0x02,0x0e,0xd1,0x0e,0xd1,0x00,0x05,0x0e,0xd7,0x0e,0xd7,0x00,0x02,0x0e,0xe7,0x0e,0xe7,0x00,0x06,0x0e,0xe9, 0x0e,0xe9,0x00,0x06,0x0f,0x16,0x0f,0x16,0x00,0x06,0x0f,0x1a,0x0f,0x1a,0x00,0x06,0x0f,0x1e,0x0f,0x1e,0x00,0x01,0x0f,0x20,0x0f,0x20,0x00,0x01,0x0f,0x22,0x0f,0x22,0x00,0x01,0x0f,0x24,0x0f,0x24,0x00,0x06,0x0f,0x28,0x0f,0x28,0x00,0x01,0x0f,0x2a,0x0f,0x2a,0x00,0x01,0x0f,0x2c,0x0f,0x2c,0x00,0x01,0x0f,0x2e,0x0f,0x2e,0x00,0x06, 0x0f,0x30,0x0f,0x30,0x00,0x01,0x0f,0x32,0x0f,0x32,0x00,0x06,0x0f,0x34,0x0f,0x34,0x00,0x01,0x0f,0x36,0x0f,0x36,0x00,0x06,0x0f,0x38,0x0f,0x38,0x00,0x01,0x0f,0x3a,0x0f,0x3a,0x00,0x01,0x0f,0x3c,0x0f,0x3c,0x00,0x0a,0x0f,0x3e,0x0f,0x3e,0x00,0x0a,0x0f,0x40,0x0f,0x40,0x00,0x06,0x0f,0x44,0x0f,0x44,0x00,0x01,0x0f,0x46,0x0f,0x46, 0x00,0x01,0x0f,0x48,0x0f,0x48,0x00,0x01,0x0f,0x4a,0x0f,0x4a,0x00,0x01,0x0f,0x4c,0x0f,0x4c,0x00,0x01,0x0f,0x4e,0x0f,0x4e,0x00,0x08,0x0f,0x6c,0x0f,0x6c,0x00,0x01,0x0f,0x6e,0x0f,0x6e,0x00,0x01,0x0f,0x70,0x0f,0x70,0x00,0x01,0x0f,0x72,0x0f,0x72,0x00,0x01,0x0f,0x74,0x0f,0x74,0x00,0x01,0x0f,0x76,0x0f,0x76,0x00,0x01,0x0f,0x78, 0x0f,0x78,0x00,0x01,0x0f,0x7a,0x0f,0x7a,0x00,0x01,0x0f,0x7c,0x0f,0x7c,0x00,0x01,0x0f,0x7e,0x0f,0x7e,0x00,0x01,0x0f,0x80,0x0f,0x80,0x00,0x01,0x0f,0x82,0x0f,0x82,0x00,0x02,0x0f,0x84,0x0f,0x84,0x00,0x02,0x0f,0x86,0x0f,0x86,0x00,0x02,0x0f,0x88,0x0f,0x88,0x00,0x02,0x0f,0x8a,0x0f,0x8a,0x00,0x02,0x0f,0x8c,0x0f,0x8c,0x00,0x01, 0x0f,0x8e,0x0f,0x8e,0x00,0x01,0x0f,0x90,0x0f,0x90,0x00,0x01,0x0f,0x92,0x0f,0x92,0x00,0x01,0x0f,0x94,0x0f,0x94,0x00,0x06,0x0f,0x96,0x0f,0x96,0x00,0x01,0x0f,0xc0,0x0f,0xc0,0x00,0x01,0x10,0xfe,0x10,0xfe,0x00,0x01,0x11,0x00,0x11,0x00,0x00,0x01,0x11,0x02,0x11,0x02,0x00,0x01,0x11,0x04,0x11,0x04,0x00,0x01,0x11,0x06,0x11,0x06, 0x00,0x01,0x11,0x08,0x11,0x08,0x00,0x01,0x11,0x0a,0x11,0x0a,0x00,0x01,0x11,0x0c,0x11,0x0d,0x00,0x01,0x11,0x0f,0x11,0x0f,0x00,0x01,0x14,0x53,0x14,0x53,0x00,0x07,0x14,0x54,0x14,0x54,0x00,0x01,0x14,0x55,0x14,0x57,0x00,0x02,0x14,0x58,0x14,0x59,0x00,0x01,0x14,0x5a,0x14,0x5b,0x00,0x02,0x14,0x6f,0x14,0x6f,0x00,0x02,0x14,0x72, 0x14,0x72,0x00,0x08,0x14,0x75,0x14,0x75,0x00,0x05,0x14,0x78,0x14,0x78,0x00,0x06,0x14,0x7b,0x14,0x7b,0x00,0x05,0x14,0x80,0x14,0x80,0x00,0x06,0x14,0x83,0x14,0x83,0x00,0x02,0x14,0x97,0x14,0x98,0x00,0x02,0x00,0x01,0x00,0x26,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x1a,0x00,0x20,0x00,0x20,0x00,0x1a,0x00,0x1a,0x00,0x20,0x00,0x20, 0x00,0x1a,0x00,0x01,0x08,0xdd,0xff,0x55,0x00,0x01,0x08,0xdb,0xff,0x55,0x00,0x02,0x00,0x06,0x08,0xd7,0x08,0xd7,0x00,0x00,0x08,0xd9,0x08,0xd9,0x00,0x01,0x08,0xde,0x08,0xdf,0x00,0x02,0x09,0x4f,0x09,0x4f,0x00,0x04,0x09,0x51,0x09,0x51,0x00,0x05,0x09,0x56,0x09,0x57,0x00,0x06,0x00,0x02,0x00,0x30,0x00,0x04,0x00,0x00,0x00,0x4c, 0x00,0x80,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x55,0x00,0x00,0xfe,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x55,0x00,0x00,0x00,0x00,0xff,0x55,0x00,0x00,0x00,0x02,0x00,0x04,0x08,0xd9,0x08,0xda,0x00,0x00,0x08,0xde,0x08,0xdf,0x00,0x02,0x09,0x51,0x09,0x53,0x00,0x04,0x09,0x55,0x09,0x57, 0x00,0x07,0x00,0x02,0x00,0x08,0x08,0xd9,0x08,0xda,0x00,0x01,0x08,0xde,0x08,0xde,0x00,0x01,0x08,0xdf,0x08,0xdf,0x00,0x03,0x09,0x51,0x09,0x52,0x00,0x01,0x09,0x53,0x09,0x53,0x00,0x02,0x09,0x55,0x09,0x55,0x00,0x02,0x09,0x56,0x09,0x56,0x00,0x01,0x09,0x57,0x09,0x57,0x00,0x03,0x00,0x02,0x00,0x0a,0x08,0xd7,0x08,0xd7,0x00,0x01, 0x08,0xdc,0x08,0xdc,0x00,0x01,0x08,0xde,0x08,0xde,0x00,0x02,0x08,0xdf,0x08,0xdf,0x00,0x03,0x08,0xe0,0x08,0xe0,0x00,0x02,0x09,0x4f,0x09,0x4f,0x00,0x01,0x09,0x54,0x09,0x55,0x00,0x01,0x09,0x56,0x09,0x56,0x00,0x02,0x09,0x57,0x09,0x57,0x00,0x03,0x09,0x58,0x09,0x58,0x00,0x02,0x00,0x01,0x10,0xc6,0x00,0x04,0x00,0x00,0x00,0x57, 0x00,0xb8,0x01,0xbe,0x01,0xe4,0x02,0x3e,0x02,0xa8,0x03,0x2a,0x03,0x70,0x03,0xa6,0x04,0xf0,0x06,0x16,0x06,0x9c,0x07,0x96,0x08,0x14,0x09,0x0a,0x09,0x50,0x0b,0x7a,0x0b,0xa8,0x0d,0x72,0x0e,0x88,0x0e,0xde,0x10,0x88,0x00,0xb8,0x00,0xb8,0x01,0xe4,0x06,0x16,0x0b,0x7a,0x06,0x16,0x00,0xb8,0x00,0xb8,0x06,0x16,0x06,0x16,0x0e,0xde, 0x00,0xb8,0x00,0xb8,0x06,0x16,0x06,0x16,0x06,0x16,0x0b,0x7a,0x0b,0x7a,0x0b,0x7a,0x09,0x0a,0x10,0x88,0x02,0x3e,0x0e,0xde,0x03,0x2a,0x09,0x0a,0x01,0xe4,0x01,0xe4,0x00,0xb8,0x00,0xb8,0x04,0xf0,0x06,0x16,0x08,0x14,0x08,0x14,0x09,0x0a,0x09,0x50,0x09,0x50,0x0b,0x7a,0x0b,0x7a,0x10,0x88,0x10,0x88,0x00,0xb8,0x01,0xe4,0x03,0x2a, 0x03,0x2a,0x03,0x2a,0x03,0x70,0x03,0xa6,0x04,0xf0,0x06,0x16,0x06,0x16,0x08,0x14,0x09,0x0a,0x09,0x50,0x0b,0x7a,0x0b,0x7a,0x0b,0x7a,0x0b,0x7a,0x0d,0x72,0x0e,0xde,0x00,0xb8,0x06,0x16,0x0d,0x72,0x0d,0x72,0x0d,0x72,0x0e,0xde,0x09,0x0a,0x00,0x41,0x00,0x26,0xff,0xd8,0x00,0x2a,0xff,0xd8,0x00,0x2d,0x00,0x5e,0x00,0x32,0xff,0xd8, 0x00,0x37,0xff,0x6d,0x00,0x38,0xff,0xd8,0x00,0x39,0xff,0x74,0x00,0x3a,0xff,0x74,0x00,0x3c,0xff,0x74,0x00,0x3d,0x00,0x3c,0x00,0x59,0xff,0xd8,0x00,0x5a,0xff,0xd8,0x00,0x5c,0xff,0xd8,0x00,0x64,0xff,0xd8,0x00,0x67,0xff,0xd8,0x00,0x68,0xff,0xd8,0x00,0x92,0xff,0xd8,0x00,0xaf,0xff,0xd8,0x00,0xb0,0xff,0xd8,0x00,0xba,0xff,0xd8, 0x00,0xbb,0xff,0x74,0x00,0xd0,0xff,0xd8,0x00,0xd1,0xff,0xd8,0x00,0xd2,0xff,0xd8,0x00,0xd3,0xff,0xd8,0x00,0xd4,0xff,0xd8,0x00,0xd5,0xff,0xd8,0x00,0xe5,0x00,0x3c,0x00,0xea,0xff,0x74,0x00,0xeb,0xff,0xd8,0x00,0xf7,0xff,0xd8,0x00,0xfc,0xff,0xd8,0x00,0xfe,0xff,0xd8,0x01,0x18,0xff,0xd8,0x01,0x20,0xff,0x6d,0x01,0x22,0xff,0x6d, 0x01,0x24,0xff,0xd8,0x01,0x26,0xff,0xd8,0x01,0x28,0x00,0x3c,0x01,0x2a,0x00,0x3c,0x01,0x47,0xff,0xd8,0x01,0x51,0xff,0xd8,0x01,0x53,0xff,0xd8,0x01,0x55,0xff,0xd8,0x01,0x63,0x00,0x5e,0x01,0x6e,0xff,0xd8,0x01,0x70,0xff,0xd8,0x01,0x76,0xff,0x6d,0x01,0x78,0xff,0xd8,0x01,0x7a,0xff,0xd8,0x01,0x7c,0xff,0xd8,0x01,0x7e,0xff,0xd8, 0x01,0x80,0xff,0x74,0x01,0x81,0xff,0xd8,0x01,0x82,0xff,0x74,0x01,0x83,0xff,0xd8,0x01,0x89,0xff,0xd8,0x01,0x8c,0xff,0x74,0x01,0x8d,0xff,0xd8,0x01,0x8e,0xff,0x74,0x01,0x8f,0xff,0xd8,0x01,0x90,0xff,0x74,0x01,0x91,0xff,0xd8,0x01,0x92,0xff,0x74,0x01,0x93,0xff,0xd8,0x00,0x09,0x00,0x37,0xff,0xa4,0x00,0x3c,0xff,0xbe,0x00,0xbb, 0xff,0xbe,0x00,0xea,0xff,0xbe,0x01,0x20,0xff,0xa4,0x01,0x22,0xff,0xa4,0x01,0x76,0xff,0xa4,0x01,0x82,0xff,0xbe,0x01,0x92,0xff,0xbe,0x00,0x16,0x00,0x26,0xff,0xc9,0x00,0x2a,0xff,0xc9,0x00,0x32,0xff,0xc9,0x00,0x64,0xff,0xc9,0x00,0x67,0xff,0xc9,0x00,0x92,0xff,0xc9,0x00,0xaf,0xff,0xc9,0x00,0xb0,0xff,0xc9,0x00,0xd0,0xff,0xc9, 0x00,0xd1,0xff,0xc9,0x00,0xd2,0xff,0xc9,0x00,0xf7,0xff,0xc9,0x00,0xfc,0xff,0xc9,0x00,0xfe,0xff,0xc9,0x01,0x18,0xff,0xc9,0x01,0x47,0xff,0xc9,0x01,0x51,0xff,0xc9,0x01,0x53,0xff,0xc9,0x01,0x55,0xff,0xc9,0x01,0x6e,0xff,0xc9,0x01,0x70,0xff,0xc9,0x01,0x89,0xff,0xc9,0x00,0x1a,0x00,0x24,0xff,0xce,0x00,0x37,0xff,0xa4,0x00,0x39, 0xff,0xce,0x00,0x3a,0xff,0xce,0x00,0x3b,0xff,0xc4,0x00,0x3d,0xff,0xce,0x00,0x62,0xff,0xce,0x00,0x63,0xff,0xce,0x00,0xad,0xff,0xce,0x00,0xae,0xff,0xce,0x00,0xc7,0xff,0xce,0x00,0xc9,0xff,0xce,0x00,0xe5,0xff,0xce,0x01,0x03,0xff,0xce,0x01,0x05,0xff,0xce,0x01,0x20,0xff,0xa4,0x01,0x22,0xff,0xa4,0x01,0x28,0xff,0xce,0x01,0x2a, 0xff,0xce,0x01,0x45,0xff,0xce,0x01,0x76,0xff,0xa4,0x01,0x80,0xff,0xce,0x01,0x85,0xff,0xce,0x01,0x8c,0xff,0xce,0x01,0x8e,0xff,0xce,0x01,0x90,0xff,0xce,0x00,0x20,0x00,0x24,0xff,0x88,0x00,0x2d,0xff,0xbe,0x00,0x44,0xff,0xba,0x00,0x62,0xff,0x88,0x00,0x63,0xff,0x88,0x00,0x69,0xff,0xba,0x00,0x6a,0xff,0xba,0x00,0x6b,0xff,0xba, 0x00,0x6c,0xff,0xba,0x00,0x6d,0xff,0xba,0x00,0x6e,0xff,0xba,0x00,0x75,0x00,0x32,0x00,0x76,0x00,0x32,0x00,0x77,0x00,0x32,0x00,0xa0,0xff,0xba,0x00,0xad,0xff,0x88,0x00,0xae,0xff,0x88,0x00,0xc7,0xff,0x88,0x00,0xc9,0xff,0x88,0x01,0x03,0xff,0x88,0x01,0x04,0xff,0xba,0x01,0x05,0xff,0x88,0x01,0x06,0xff,0xba,0x01,0x45,0xff,0x88, 0x01,0x46,0xff,0xba,0x01,0x5c,0x00,0x32,0x01,0x5e,0x00,0x32,0x01,0x60,0x00,0x32,0x01,0x63,0xff,0xbe,0x01,0x85,0xff,0x88,0x01,0x86,0xff,0xba,0x01,0x88,0xff,0xba,0x00,0x11,0x00,0x37,0xff,0xcf,0x00,0x39,0xff,0xd8,0x00,0x3a,0xff,0xd8,0x00,0x3b,0xff,0xd8,0x00,0x5c,0xff,0xd8,0x00,0x5d,0xff,0xd8,0x00,0xba,0xff,0xd8,0x00,0xeb, 0xff,0xd8,0x01,0x20,0xff,0xcf,0x01,0x22,0xff,0xcf,0x01,0x76,0xff,0xcf,0x01,0x80,0xff,0xd8,0x01,0x83,0xff,0xd8,0x01,0x8c,0xff,0xd8,0x01,0x8e,0xff,0xd8,0x01,0x90,0xff,0xd8,0x01,0x93,0xff,0xd8,0x00,0x0d,0x00,0x24,0xff,0xce,0x00,0x2d,0xff,0xb0,0x00,0x62,0xff,0xce,0x00,0x63,0xff,0xce,0x00,0xad,0xff,0xce,0x00,0xae,0xff,0xce, 0x00,0xc7,0xff,0xce,0x00,0xc9,0xff,0xce,0x01,0x03,0xff,0xce,0x01,0x05,0xff,0xce,0x01,0x45,0xff,0xce,0x01,0x63,0xff,0xb0,0x01,0x85,0xff,0xce,0x00,0x52,0x00,0x26,0xff,0xa6,0x00,0x2a,0xff,0xa6,0x00,0x2d,0x00,0x5a,0x00,0x32,0xff,0xa6,0x00,0x39,0x00,0x28,0x00,0x3a,0x00,0x28,0x00,0x3b,0x00,0x32,0x00,0x3c,0x00,0x28,0x00,0x3d, 0x00,0x28,0x00,0x46,0xff,0xe5,0x00,0x47,0xff,0xe5,0x00,0x48,0xff,0xe5,0x00,0x4a,0xff,0xe5,0x00,0x52,0xff,0xce,0x00,0x54,0xff,0xce,0x00,0x57,0xff,0xd1,0x00,0x59,0xff,0xba,0x00,0x5a,0xff,0xba,0x00,0x5b,0x00,0x1e,0x00,0x5c,0xff,0xa6,0x00,0x64,0xff,0xa6,0x00,0x67,0xff,0xa6,0x00,0x79,0xff,0xce,0x00,0x7a,0xff,0xce,0x00,0x7b, 0xff,0xce,0x00,0x7c,0xff,0xce,0x00,0x7d,0xff,0xce,0x00,0x92,0xff,0xa6,0x00,0xaf,0xff,0xa6,0x00,0xb0,0xff,0xa6,0x00,0xb1,0xff,0xce,0x00,0xba,0xff,0xa6,0x00,0xbb,0x00,0x28,0x00,0xd0,0xff,0xa6,0x00,0xd1,0xff,0xa6,0x00,0xd2,0xff,0xa6,0x00,0xe5,0x00,0x28,0x00,0xea,0x00,0x28,0x00,0xeb,0xff,0xa6,0x00,0xf7,0xff,0xa6,0x00,0xf8, 0xff,0xe5,0x00,0xfc,0xff,0xa6,0x00,0xfd,0xff,0xe5,0x00,0xfe,0xff,0xa6,0x00,0xff,0xff,0xe5,0x01,0x00,0xff,0xe5,0x01,0x08,0xff,0xe5,0x01,0x0b,0xff,0xe5,0x01,0x18,0xff,0xa6,0x01,0x19,0xff,0xce,0x01,0x21,0xff,0xd1,0x01,0x23,0xff,0xd1,0x01,0x28,0x00,0x28,0x01,0x2a,0x00,0x28,0x01,0x47,0xff,0xa6,0x01,0x48,0xff,0xe5,0x01,0x51, 0xff,0xa6,0x01,0x52,0xff,0xe5,0x01,0x53,0xff,0xa6,0x01,0x54,0xff,0xe5,0x01,0x55,0xff,0xa6,0x01,0x56,0xff,0xe5,0x01,0x63,0x00,0x5a,0x01,0x6e,0xff,0xa6,0x01,0x6f,0xff,0xce,0x01,0x70,0xff,0xa6,0x01,0x71,0xff,0xce,0x01,0x77,0xff,0xd1,0x01,0x80,0x00,0x28,0x01,0x81,0xff,0xba,0x01,0x82,0x00,0x28,0x01,0x83,0xff,0xa6,0x01,0x89, 0xff,0xa6,0x01,0x8a,0xff,0xce,0x01,0x8c,0x00,0x28,0x01,0x8d,0xff,0xba,0x01,0x8e,0x00,0x28,0x01,0x8f,0xff,0xba,0x01,0x90,0x00,0x28,0x01,0x91,0xff,0xba,0x01,0x92,0x00,0x28,0x01,0x93,0xff,0xa6,0x00,0x49,0x00,0x24,0x00,0x3c,0x00,0x26,0xff,0xba,0x00,0x2a,0xff,0xbe,0x00,0x2d,0x00,0x64,0x00,0x32,0xff,0xba,0x00,0x37,0xff,0x74, 0x00,0x38,0xff,0xd8,0x00,0x39,0xff,0x88,0x00,0x3a,0xff,0x88,0x00,0x3c,0xff,0x88,0x00,0x3d,0x00,0x3b,0x00,0x57,0xff,0xe5,0x00,0x59,0xff,0x9c,0x00,0x5a,0xff,0x9c,0x00,0x5c,0xff,0x9c,0x00,0x62,0x00,0x3c,0x00,0x63,0x00,0x3c,0x00,0x64,0xff,0xba,0x00,0x68,0xff,0xd8,0x00,0xad,0x00,0x3c,0x00,0xae,0x00,0x3c,0x00,0xba,0xff,0x9c, 0x00,0xbb,0xff,0x88,0x00,0xc7,0x00,0x3c,0x00,0xc9,0x00,0x3c,0x00,0xd3,0xff,0xd8,0x00,0xd4,0xff,0xd8,0x00,0xd5,0xff,0xd8,0x00,0xe5,0x00,0x3b,0x00,0xea,0xff,0x88,0x00,0xeb,0xff,0x9c,0x00,0xf7,0xff,0xbe,0x00,0xfc,0xff,0xba,0x00,0xfe,0xff,0xba,0x01,0x03,0x00,0x3c,0x01,0x05,0x00,0x3c,0x01,0x18,0xff,0xba,0x01,0x20,0xff,0x74, 0x01,0x21,0xff,0xe5,0x01,0x22,0xff,0x74,0x01,0x23,0xff,0xe5,0x01,0x24,0xff,0xd8,0x01,0x26,0xff,0xd8,0x01,0x28,0x00,0x3b,0x01,0x2a,0x00,0x3b,0x01,0x45,0x00,0x3c,0x01,0x47,0xff,0xba,0x01,0x51,0xff,0xbe,0x01,0x53,0xff,0xbe,0x01,0x55,0xff,0xbe,0x01,0x63,0x00,0x64,0x01,0x6e,0xff,0xba,0x01,0x70,0xff,0xba,0x01,0x76,0xff,0x74, 0x01,0x77,0xff,0xe5,0x01,0x78,0xff,0xd8,0x01,0x7a,0xff,0xd8,0x01,0x7c,0xff,0xd8,0x01,0x7e,0xff,0xd8,0x01,0x80,0xff,0x88,0x01,0x81,0xff,0x9c,0x01,0x82,0xff,0x88,0x01,0x83,0xff,0x9c,0x01,0x85,0x00,0x3c,0x01,0x89,0xff,0xba,0x01,0x8c,0xff,0x88,0x01,0x8d,0xff,0x9c,0x01,0x8e,0xff,0x88,0x01,0x8f,0xff,0x9c,0x01,0x90,0xff,0x88, 0x01,0x91,0xff,0x9c,0x01,0x92,0xff,0x88,0x01,0x93,0xff,0x9c,0x00,0x21,0x00,0x24,0xff,0xce,0x00,0x2d,0xff,0xf6,0x00,0x37,0xff,0xa4,0x00,0x39,0xff,0xce,0x00,0x3a,0xff,0xce,0x00,0x3b,0xff,0xce,0x00,0x3c,0xff,0xce,0x00,0x3d,0xff,0xce,0x00,0x62,0xff,0xce,0x00,0x63,0xff,0xce,0x00,0xad,0xff,0xce,0x00,0xae,0xff,0xce,0x00,0xbb, 0xff,0xce,0x00,0xc7,0xff,0xce,0x00,0xc9,0xff,0xce,0x00,0xe5,0xff,0xce,0x00,0xea,0xff,0xce,0x01,0x03,0xff,0xce,0x01,0x05,0xff,0xce,0x01,0x20,0xff,0xa4,0x01,0x22,0xff,0xa4,0x01,0x28,0xff,0xce,0x01,0x2a,0xff,0xce,0x01,0x45,0xff,0xce,0x01,0x63,0xff,0xf6,0x01,0x76,0xff,0xa4,0x01,0x80,0xff,0xce,0x01,0x82,0xff,0xce,0x01,0x85, 0xff,0xce,0x01,0x8c,0xff,0xce,0x01,0x8e,0xff,0xce,0x01,0x90,0xff,0xce,0x01,0x92,0xff,0xce,0x00,0x3e,0x00,0x24,0xff,0x74,0x00,0x2d,0xff,0x7f,0x00,0x3b,0xff,0xce,0x00,0x44,0xff,0xba,0x00,0x46,0xff,0xb4,0x00,0x47,0xff,0xb4,0x00,0x48,0xff,0xb4,0x00,0x4a,0xff,0xb4,0x00,0x52,0xff,0xb4,0x00,0x54,0xff,0xb4,0x00,0x62,0xff,0x74, 0x00,0x63,0xff,0x74,0x00,0x69,0xff,0xba,0x00,0x6a,0xff,0xba,0x00,0x6b,0xff,0xba,0x00,0x6c,0xff,0xba,0x00,0x6d,0xff,0xba,0x00,0x6e,0xff,0xba,0x00,0x6f,0xff,0xb4,0x00,0x70,0xff,0xb4,0x00,0x71,0xff,0xb4,0x00,0x72,0xff,0xb4,0x00,0x73,0xff,0xb4,0x00,0x79,0xff,0xb4,0x00,0x7a,0xff,0xb4,0x00,0x7b,0xff,0xb4,0x00,0x7c,0xff,0xb4, 0x00,0x7d,0xff,0xb4,0x00,0xa0,0xff,0xba,0x00,0xad,0xff,0x74,0x00,0xae,0xff,0x74,0x00,0xb1,0xff,0xb4,0x00,0xc7,0xff,0x74,0x00,0xc9,0xff,0x74,0x00,0xf8,0xff,0xb4,0x00,0xfd,0xff,0xb4,0x00,0xff,0xff,0xb4,0x01,0x00,0xff,0xb4,0x01,0x03,0xff,0x74,0x01,0x04,0xff,0xba,0x01,0x05,0xff,0x74,0x01,0x06,0xff,0xba,0x01,0x08,0xff,0xb4, 0x01,0x0b,0xff,0xb4,0x01,0x0d,0xff,0xb4,0x01,0x19,0xff,0xb4,0x01,0x45,0xff,0x74,0x01,0x46,0xff,0xba,0x01,0x48,0xff,0xb4,0x01,0x4c,0xff,0xb4,0x01,0x4e,0xff,0xb4,0x01,0x50,0xff,0xb4,0x01,0x52,0xff,0xb4,0x01,0x54,0xff,0xb4,0x01,0x56,0xff,0xb4,0x01,0x63,0xff,0x7f,0x01,0x6f,0xff,0xb4,0x01,0x71,0xff,0xb4,0x01,0x85,0xff,0x74, 0x01,0x86,0xff,0xba,0x01,0x88,0xff,0xba,0x01,0x8a,0xff,0xb4,0x00,0x1f,0x00,0x24,0xff,0xce,0x00,0x37,0xff,0xa4,0x00,0x39,0xff,0xce,0x00,0x3a,0xff,0xce,0x00,0x3b,0xff,0xce,0x00,0x3c,0xff,0xce,0x00,0x3d,0xff,0xce,0x00,0x62,0xff,0xce,0x00,0x63,0xff,0xce,0x00,0xad,0xff,0xce,0x00,0xae,0xff,0xce,0x00,0xbb,0xff,0xce,0x00,0xc7, 0xff,0xce,0x00,0xc9,0xff,0xce,0x00,0xe5,0xff,0xce,0x00,0xea,0xff,0xce,0x01,0x03,0xff,0xce,0x01,0x05,0xff,0xce,0x01,0x20,0xff,0xa4,0x01,0x22,0xff,0xa4,0x01,0x28,0xff,0xce,0x01,0x2a,0xff,0xce,0x01,0x45,0xff,0xce,0x01,0x76,0xff,0xa4,0x01,0x80,0xff,0xce,0x01,0x82,0xff,0xce,0x01,0x85,0xff,0xce,0x01,0x8c,0xff,0xce,0x01,0x8e, 0xff,0xce,0x01,0x90,0xff,0xce,0x01,0x92,0xff,0xce,0x00,0x3d,0x00,0x26,0xff,0xe3,0x00,0x2a,0xff,0xe3,0x00,0x2d,0x00,0x39,0x00,0x32,0xff,0xec,0x00,0x37,0xff,0xa4,0x00,0x3c,0xff,0xd9,0x00,0x46,0xff,0xc4,0x00,0x47,0xff,0xc4,0x00,0x48,0xff,0xc4,0x00,0x4a,0xff,0xc4,0x00,0x52,0xff,0xc4,0x00,0x54,0xff,0xcb,0x00,0x64,0xff,0xe3, 0x00,0x6f,0xff,0xc4,0x00,0x70,0xff,0xc4,0x00,0x71,0xff,0xc4,0x00,0x72,0xff,0xc4,0x00,0x73,0xff,0xc4,0x00,0x79,0xff,0xc4,0x00,0x7a,0xff,0xc4,0x00,0x7b,0xff,0xc4,0x00,0x7c,0xff,0xc4,0x00,0x7d,0xff,0xc4,0x00,0xb1,0xff,0xc4,0x00,0xbb,0xff,0xd9,0x00,0xea,0xff,0xd9,0x00,0xf7,0xff,0xe3,0x00,0xf8,0xff,0xc4,0x00,0xfc,0xff,0xe3, 0x00,0xfd,0xff,0xc4,0x00,0xfe,0xff,0xe3,0x00,0xff,0xff,0xc4,0x01,0x00,0xff,0xc4,0x01,0x08,0xff,0xc4,0x01,0x0b,0xff,0xc4,0x01,0x0d,0xff,0xc4,0x01,0x18,0xff,0xec,0x01,0x19,0xff,0xc4,0x01,0x20,0xff,0xa4,0x01,0x22,0xff,0xa4,0x01,0x47,0xff,0xe3,0x01,0x48,0xff,0xc4,0x01,0x4c,0xff,0xc4,0x01,0x4e,0xff,0xc4,0x01,0x50,0xff,0xc4, 0x01,0x51,0xff,0xe3,0x01,0x52,0xff,0xc4,0x01,0x53,0xff,0xe3,0x01,0x54,0xff,0xc4,0x01,0x55,0xff,0xe3,0x01,0x56,0xff,0xc4,0x01,0x63,0x00,0x39,0x01,0x6e,0xff,0xec,0x01,0x6f,0xff,0xc4,0x01,0x70,0xff,0xec,0x01,0x71,0xff,0xc4,0x01,0x76,0xff,0xa4,0x01,0x82,0xff,0xd9,0x01,0x89,0xff,0xec,0x01,0x8a,0xff,0xc4,0x01,0x92,0xff,0xd9, 0x00,0x11,0x00,0x57,0xff,0xbe,0x00,0x59,0xff,0xce,0x00,0x5a,0xff,0xe2,0x00,0x5b,0xff,0xe2,0x00,0x5c,0xff,0xc4,0x00,0x5d,0xff,0xc4,0x00,0xba,0xff,0xc4,0x00,0xeb,0xff,0xc4,0x01,0x21,0xff,0xbe,0x01,0x23,0xff,0xbe,0x01,0x77,0xff,0xbe,0x01,0x81,0xff,0xe2,0x01,0x83,0xff,0xc4,0x01,0x8d,0xff,0xe2,0x01,0x8f,0xff,0xe2,0x01,0x91, 0xff,0xe2,0x01,0x93,0xff,0xc4,0x00,0x8a,0x00,0x24,0xff,0x74,0x00,0x26,0xff,0xa1,0x00,0x2a,0xff,0xa1,0x00,0x2d,0xff,0x8f,0x00,0x32,0xff,0xa1,0x00,0x36,0xff,0xd8,0x00,0x37,0x00,0x28,0x00,0x39,0x00,0x2b,0x00,0x3a,0x00,0x2b,0x00,0x3c,0x00,0x28,0x00,0x44,0xff,0x1a,0x00,0x46,0xff,0x38,0x00,0x47,0xff,0x38,0x00,0x48,0xff,0x38, 0x00,0x49,0xff,0xa0,0x00,0x4a,0xff,0x38,0x00,0x50,0xff,0x4e,0x00,0x51,0xff,0x4e,0x00,0x52,0xff,0x38,0x00,0x53,0xff,0x4e,0x00,0x54,0xff,0x38,0x00,0x55,0xff,0x4e,0x00,0x56,0xff,0x66,0x00,0x59,0xff,0x9a,0x00,0x5a,0xff,0x8f,0x00,0x5b,0xff,0x4c,0x00,0x5c,0xff,0x8f,0x00,0x5d,0xff,0x8f,0x00,0x62,0xff,0x74,0x00,0x63,0xff,0x74, 0x00,0x64,0xff,0xa1,0x00,0x67,0xff,0xa1,0x00,0x69,0xff,0x1a,0x00,0x6a,0xff,0x1a,0x00,0x6b,0xff,0x1a,0x00,0x6c,0xff,0x38,0x00,0x6d,0xff,0x38,0x00,0x6e,0xff,0x1a,0x00,0x6f,0xff,0x38,0x00,0x70,0xff,0x38,0x00,0x71,0xff,0x38,0x00,0x72,0xff,0x38,0x00,0x73,0xff,0x38,0x00,0x75,0x00,0x1e,0x00,0x76,0x00,0x32,0x00,0x77,0x00,0x32, 0x00,0x79,0xff,0x38,0x00,0x7a,0xff,0x38,0x00,0x7b,0xff,0x38,0x00,0x7c,0xff,0x38,0x00,0x7d,0xff,0x38,0x00,0x92,0xff,0xa1,0x00,0xa0,0xff,0x1a,0x00,0xad,0xff,0x74,0x00,0xae,0xff,0x74,0x00,0xaf,0xff,0xa1,0x00,0xb0,0xff,0xa1,0x00,0xb1,0xff,0x38,0x00,0xba,0xff,0x8f,0x00,0xbb,0x00,0x28,0x00,0xc7,0xff,0x74,0x00,0xc9,0xff,0x74, 0x00,0xd0,0xff,0xa1,0x00,0xd1,0xff,0xa1,0x00,0xd2,0xff,0xa1,0x00,0xe3,0xff,0xd8,0x00,0xe4,0xff,0x66,0x00,0xea,0x00,0x28,0x00,0xeb,0xff,0x8f,0x00,0xf7,0xff,0xa1,0x00,0xf8,0xff,0x38,0x00,0xfa,0xff,0xd8,0x00,0xfb,0xff,0x66,0x00,0xfc,0xff,0xa1,0x00,0xfd,0xff,0x38,0x00,0xfe,0xff,0xa1,0x00,0xff,0xff,0x38,0x01,0x00,0xff,0x38, 0x01,0x03,0xff,0x74,0x01,0x04,0xff,0x38,0x01,0x05,0xff,0x74,0x01,0x06,0xff,0x1a,0x01,0x08,0xff,0x38,0x01,0x0b,0xff,0x38,0x01,0x0d,0xff,0x38,0x01,0x18,0xff,0xa1,0x01,0x19,0xff,0x38,0x01,0x1b,0xff,0x4e,0x01,0x1d,0xff,0x4e,0x01,0x1e,0xff,0xd8,0x01,0x1f,0xff,0x66,0x01,0x20,0x00,0x28,0x01,0x22,0x00,0x28,0x01,0x45,0xff,0x74, 0x01,0x46,0xff,0x38,0x01,0x47,0xff,0xa1,0x01,0x48,0xff,0x38,0x01,0x4c,0xff,0x38,0x01,0x4e,0xff,0x38,0x01,0x50,0xff,0x38,0x01,0x51,0xff,0xa1,0x01,0x52,0xff,0x38,0x01,0x53,0xff,0xa1,0x01,0x54,0xff,0x38,0x01,0x55,0xff,0xa1,0x01,0x56,0xff,0x38,0x01,0x5c,0x00,0x32,0x01,0x5e,0x00,0x32,0x01,0x60,0x00,0x32,0x01,0x63,0xff,0x8f, 0x01,0x6d,0xff,0x4e,0x01,0x6e,0xff,0xa1,0x01,0x6f,0xff,0x38,0x01,0x70,0xff,0xa1,0x01,0x71,0xff,0x38,0x01,0x73,0xff,0x4e,0x01,0x74,0xff,0xd8,0x01,0x75,0xff,0x66,0x01,0x76,0x00,0x28,0x01,0x80,0x00,0x2b,0x01,0x81,0xff,0x8f,0x01,0x82,0x00,0x28,0x01,0x83,0xff,0x8f,0x01,0x85,0xff,0x74,0x01,0x86,0xff,0x38,0x01,0x88,0xff,0x1a, 0x01,0x89,0xff,0xa1,0x01,0x8a,0xff,0x38,0x01,0x8c,0x00,0x2b,0x01,0x8d,0xff,0x8f,0x01,0x8e,0x00,0x2b,0x01,0x8f,0xff,0x8f,0x01,0x90,0x00,0x2b,0x01,0x91,0xff,0x8f,0x01,0x92,0x00,0x28,0x01,0x93,0xff,0x8f,0x02,0x3d,0xff,0xd8,0x02,0x3e,0xff,0x66,0x00,0x0b,0x00,0x24,0xff,0xce,0x00,0x62,0xff,0xce,0x00,0x63,0xff,0xce,0x00,0xad, 0xff,0xce,0x00,0xae,0xff,0xce,0x00,0xc7,0xff,0xce,0x00,0xc9,0xff,0xce,0x01,0x03,0xff,0xce,0x01,0x05,0xff,0xce,0x01,0x45,0xff,0xce,0x01,0x85,0xff,0xce,0x00,0x72,0x00,0x24,0xff,0x88,0x00,0x26,0xff,0xce,0x00,0x2a,0xff,0xce,0x00,0x2d,0xff,0xba,0x00,0x32,0xff,0xce,0x00,0x37,0x00,0x27,0x00,0x44,0xff,0x6a,0x00,0x46,0xff,0x7e, 0x00,0x47,0xff,0x7e,0x00,0x48,0xff,0x7e,0x00,0x4a,0xff,0x7e,0x00,0x50,0xff,0xb0,0x00,0x51,0xff,0xb0,0x00,0x52,0xff,0x7e,0x00,0x53,0xff,0xb4,0x00,0x54,0xff,0x7e,0x00,0x55,0xff,0xb4,0x00,0x56,0xff,0xbe,0x00,0x58,0xff,0xce,0x00,0x62,0xff,0x88,0x00,0x63,0xff,0x88,0x00,0x64,0xff,0xce,0x00,0x67,0xff,0xce,0x00,0x69,0xff,0x6a, 0x00,0x6a,0xff,0x6a,0x00,0x6b,0xff,0x6a,0x00,0x6c,0xff,0x6a,0x00,0x6d,0xff,0x6a,0x00,0x6e,0xff,0x6a,0x00,0x6f,0xff,0x7e,0x00,0x70,0xff,0x7e,0x00,0x71,0xff,0x7e,0x00,0x72,0xff,0x7e,0x00,0x73,0xff,0x7e,0x00,0x75,0x00,0x1e,0x00,0x76,0x00,0x1e,0x00,0x77,0x00,0x3c,0x00,0x79,0xff,0x7e,0x00,0x7a,0xff,0x7e,0x00,0x7b,0xff,0x7e, 0x00,0x7c,0xff,0x7e,0x00,0x7d,0xff,0x7e,0x00,0x92,0xff,0xce,0x00,0xa0,0xff,0x6a,0x00,0xad,0xff,0x88,0x00,0xae,0xff,0x88,0x00,0xaf,0xff,0xce,0x00,0xb0,0xff,0xce,0x00,0xb1,0xff,0x7e,0x00,0xc7,0xff,0x88,0x00,0xc9,0xff,0x88,0x00,0xd0,0xff,0xce,0x00,0xd1,0xff,0xce,0x00,0xd2,0xff,0xce,0x00,0xe4,0xff,0xbe,0x00,0xf7,0xff,0xce, 0x00,0xf8,0xff,0x7e,0x00,0xfb,0xff,0xbe,0x00,0xfc,0xff,0xce,0x00,0xfd,0xff,0x7e,0x00,0xfe,0xff,0xce,0x00,0xff,0xff,0x7e,0x01,0x00,0xff,0x7e,0x01,0x03,0xff,0x88,0x01,0x04,0xff,0x6a,0x01,0x05,0xff,0x88,0x01,0x06,0xff,0x6a,0x01,0x08,0xff,0x7e,0x01,0x0b,0xff,0x7e,0x01,0x0d,0xff,0x7e,0x01,0x18,0xff,0xce,0x01,0x19,0xff,0x7e, 0x01,0x1b,0xff,0xb4,0x01,0x1d,0xff,0xb4,0x01,0x1f,0xff,0xbe,0x01,0x20,0x00,0x27,0x01,0x22,0x00,0x27,0x01,0x25,0xff,0xce,0x01,0x27,0xff,0xce,0x01,0x45,0xff,0x88,0x01,0x46,0xff,0x6a,0x01,0x47,0xff,0xce,0x01,0x48,0xff,0x7e,0x01,0x4c,0xff,0x7e,0x01,0x4e,0xff,0x7e,0x01,0x50,0xff,0x7e,0x01,0x51,0xff,0xce,0x01,0x52,0xff,0x7e, 0x01,0x53,0xff,0xce,0x01,0x54,0xff,0x7e,0x01,0x55,0xff,0xce,0x01,0x56,0xff,0x7e,0x01,0x5c,0x00,0x3c,0x01,0x5e,0x00,0x3c,0x01,0x60,0x00,0x3c,0x01,0x63,0xff,0xba,0x01,0x6d,0xff,0xb0,0x01,0x6e,0xff,0xce,0x01,0x6f,0xff,0x7e,0x01,0x70,0xff,0xce,0x01,0x71,0xff,0x7e,0x01,0x73,0xff,0xb4,0x01,0x75,0xff,0xbe,0x01,0x76,0x00,0x27, 0x01,0x79,0xff,0xce,0x01,0x7b,0xff,0xce,0x01,0x7d,0xff,0xce,0x01,0x7f,0xff,0xce,0x01,0x85,0xff,0x88,0x01,0x86,0xff,0x6a,0x01,0x88,0xff,0x6a,0x01,0x89,0xff,0xce,0x01,0x8a,0xff,0x7e,0x02,0x3e,0xff,0xbe,0x00,0x45,0x00,0x24,0xff,0xb0,0x00,0x37,0x00,0x27,0x00,0x44,0xff,0xb0,0x00,0x46,0xff,0xb0,0x00,0x47,0xff,0xb0,0x00,0x48, 0xff,0xb0,0x00,0x4a,0xff,0xb0,0x00,0x52,0xff,0xb0,0x00,0x54,0xff,0xb0,0x00,0x62,0xff,0xb0,0x00,0x63,0xff,0xb0,0x00,0x69,0xff,0xb0,0x00,0x6a,0xff,0xb0,0x00,0x6b,0xff,0xb0,0x00,0x6c,0xff,0xb0,0x00,0x6d,0xff,0xb0,0x00,0x6e,0xff,0xb0,0x00,0x6f,0xff,0xb0,0x00,0x70,0xff,0xb0,0x00,0x71,0xff,0xb0,0x00,0x72,0xff,0xb0,0x00,0x73, 0xff,0xb0,0x00,0x75,0x00,0x1e,0x00,0x76,0x00,0x1e,0x00,0x77,0x00,0x3c,0x00,0x79,0xff,0xb0,0x00,0x7a,0xff,0xb0,0x00,0x7b,0xff,0xb0,0x00,0x7c,0xff,0xb0,0x00,0x7d,0xff,0xb0,0x00,0xa0,0xff,0xb0,0x00,0xad,0xff,0xb0,0x00,0xae,0xff,0xb0,0x00,0xb1,0xff,0xb0,0x00,0xc7,0xff,0xb0,0x00,0xc9,0xff,0xb0,0x00,0xf8,0xff,0xb0,0x00,0xfd, 0xff,0xb0,0x00,0xff,0xff,0xb0,0x01,0x00,0xff,0xb0,0x01,0x03,0xff,0xb0,0x01,0x04,0xff,0xb0,0x01,0x05,0xff,0xb0,0x01,0x06,0xff,0xb0,0x01,0x08,0xff,0xb0,0x01,0x0b,0xff,0xb0,0x01,0x0d,0xff,0xb0,0x01,0x19,0xff,0xb0,0x01,0x20,0x00,0x27,0x01,0x22,0x00,0x27,0x01,0x45,0xff,0xb0,0x01,0x46,0xff,0xb0,0x01,0x48,0xff,0xb0,0x01,0x4c, 0xff,0xb0,0x01,0x4e,0xff,0xb0,0x01,0x50,0xff,0xb0,0x01,0x52,0xff,0xb0,0x01,0x54,0xff,0xb0,0x01,0x56,0xff,0xb0,0x01,0x5c,0x00,0x3c,0x01,0x5e,0x00,0x3c,0x01,0x60,0x00,0x3c,0x01,0x6f,0xff,0xb0,0x01,0x71,0xff,0xb0,0x01,0x76,0x00,0x27,0x01,0x85,0xff,0xb0,0x01,0x86,0xff,0xb0,0x01,0x88,0xff,0xb0,0x01,0x8a,0xff,0xb0,0x00,0x15, 0x00,0x26,0xff,0xe9,0x00,0x2a,0xff,0xe9,0x00,0x2d,0x00,0x60,0x00,0x32,0xff,0xe9,0x00,0x37,0x00,0x21,0x00,0x64,0xff,0xe9,0x00,0xf7,0xff,0xe9,0x00,0xfc,0xff,0xe9,0x00,0xfe,0xff,0xe9,0x01,0x18,0xff,0xe9,0x01,0x20,0x00,0x21,0x01,0x22,0x00,0x21,0x01,0x47,0xff,0xe9,0x01,0x51,0xff,0xe9,0x01,0x53,0xff,0xe9,0x01,0x55,0xff,0xe9, 0x01,0x63,0x00,0x60,0x01,0x6e,0xff,0xe9,0x01,0x70,0xff,0xe9,0x01,0x76,0x00,0x21,0x01,0x89,0xff,0xe9,0x00,0x6a,0x00,0x24,0xff,0x60,0x00,0x26,0xff,0xb0,0x00,0x2a,0xff,0xb0,0x00,0x2d,0xff,0xbe,0x00,0x32,0xff,0xb0,0x00,0x37,0x00,0x27,0x00,0x44,0xff,0x4c,0x00,0x46,0xff,0x4c,0x00,0x47,0xff,0x4c,0x00,0x48,0xff,0x4c,0x00,0x49, 0xff,0xe5,0x00,0x4a,0xff,0x4c,0x00,0x50,0xff,0x73,0x00,0x51,0xff,0x73,0x00,0x52,0xff,0x4c,0x00,0x53,0xff,0x74,0x00,0x54,0xff,0x4c,0x00,0x55,0xff,0x73,0x00,0x56,0xff,0x7b,0x00,0x62,0xff,0x60,0x00,0x63,0xff,0x60,0x00,0x64,0xff,0xb0,0x00,0x67,0xff,0xb0,0x00,0x69,0xff,0x4c,0x00,0x6a,0xff,0x4c,0x00,0x6b,0xff,0x4c,0x00,0x6c, 0xff,0x4c,0x00,0x6d,0xff,0x4c,0x00,0x6e,0xff,0x4c,0x00,0x6f,0xff,0x4c,0x00,0x70,0xff,0x4c,0x00,0x71,0xff,0x4c,0x00,0x72,0xff,0x4c,0x00,0x73,0xff,0x4c,0x00,0x77,0x00,0x32,0x00,0x79,0xff,0x4c,0x00,0x7a,0xff,0x4c,0x00,0x7b,0xff,0x4c,0x00,0x7c,0xff,0x4c,0x00,0x7d,0xff,0x4c,0x00,0x92,0xff,0xb0,0x00,0xa0,0xff,0x4c,0x00,0xad, 0xff,0x60,0x00,0xae,0xff,0x60,0x00,0xaf,0xff,0xb0,0x00,0xb0,0xff,0xb0,0x00,0xb1,0xff,0x4c,0x00,0xc7,0xff,0x60,0x00,0xc9,0xff,0x60,0x00,0xd0,0xff,0xb0,0x00,0xd1,0xff,0xb0,0x00,0xd2,0xff,0xb0,0x00,0xe4,0xff,0x7b,0x00,0xf7,0xff,0xb0,0x00,0xf8,0xff,0x4c,0x00,0xfb,0xff,0x7b,0x00,0xfc,0xff,0xb0,0x00,0xfd,0xff,0x4c,0x00,0xfe, 0xff,0xb0,0x00,0xff,0xff,0x4c,0x01,0x00,0xff,0x4c,0x01,0x03,0xff,0x60,0x01,0x04,0xff,0x4c,0x01,0x05,0xff,0x60,0x01,0x06,0xff,0x4c,0x01,0x08,0xff,0x4c,0x01,0x0b,0xff,0x4c,0x01,0x0d,0xff,0x4c,0x01,0x18,0xff,0xb0,0x01,0x19,0xff,0x4c,0x01,0x1b,0xff,0x73,0x01,0x1d,0xff,0x73,0x01,0x1f,0xff,0x7b,0x01,0x20,0x00,0x27,0x01,0x22, 0x00,0x27,0x01,0x45,0xff,0x60,0x01,0x46,0xff,0x4c,0x01,0x47,0xff,0xb0,0x01,0x48,0xff,0x4c,0x01,0x4c,0xff,0x4c,0x01,0x4e,0xff,0x4c,0x01,0x50,0xff,0x4c,0x01,0x51,0xff,0xb0,0x01,0x52,0xff,0x4c,0x01,0x53,0xff,0xb0,0x01,0x54,0xff,0x4c,0x01,0x55,0xff,0xb0,0x01,0x56,0xff,0x4c,0x01,0x5c,0x00,0x32,0x01,0x5e,0x00,0x32,0x01,0x60, 0x00,0x32,0x01,0x63,0xff,0xbe,0x01,0x6d,0xff,0x73,0x01,0x6e,0xff,0xb0,0x01,0x6f,0xff,0x4c,0x01,0x70,0xff,0xb0,0x01,0x71,0xff,0x4c,0x01,0x73,0xff,0x73,0x01,0x75,0xff,0x7b,0x01,0x76,0x00,0x27,0x01,0x85,0xff,0x60,0x01,0x86,0xff,0x4c,0x01,0x88,0xff,0x4c,0x01,0x89,0xff,0xb0,0x01,0x8a,0xff,0x4c,0x02,0x3e,0xff,0x7b,0x00,0x0f, 0x00,0x2d,0x00,0x52,0x00,0x37,0x00,0x27,0x00,0x5c,0xff,0xcb,0x00,0x77,0x00,0x32,0x00,0xba,0xff,0xcb,0x00,0xeb,0xff,0xcb,0x01,0x20,0x00,0x27,0x01,0x22,0x00,0x27,0x01,0x5c,0x00,0x32,0x01,0x5e,0x00,0x32,0x01,0x60,0x00,0x32,0x01,0x63,0x00,0x52,0x01,0x76,0x00,0x27,0x01,0x83,0xff,0xcb,0x01,0x93,0xff,0xcb,0x00,0x02,0x00,0x3b, 0x00,0x24,0x00,0x27,0x00,0x00,0x00,0x29,0x00,0x2a,0x00,0x04,0x00,0x2d,0x00,0x2f,0x00,0x06,0x00,0x32,0x00,0x3d,0x00,0x09,0x00,0x62,0x00,0x64,0x00,0x15,0x00,0x67,0x00,0x68,0x00,0x18,0x00,0x92,0x00,0x92,0x00,0x1a,0x00,0xad,0x00,0xb0,0x00,0x1b,0x00,0xbb,0x00,0xbb,0x00,0x1f,0x00,0xc7,0x00,0xc7,0x00,0x20,0x00,0xc9,0x00,0xc9, 0x00,0x21,0x00,0xd0,0x00,0xd5,0x00,0x22,0x00,0xe3,0x00,0xe3,0x00,0x28,0x00,0xe5,0x00,0xe5,0x00,0x29,0x00,0xe8,0x00,0xe8,0x00,0x2a,0x00,0xea,0x00,0xea,0x00,0x2b,0x00,0xf7,0x00,0xf7,0x00,0x2c,0x00,0xfa,0x00,0xfa,0x00,0x2d,0x00,0xfc,0x00,0xfc,0x00,0x2e,0x00,0xfe,0x00,0xfe,0x00,0x2f,0x01,0x03,0x01,0x03,0x00,0x30,0x01,0x05, 0x01,0x05,0x00,0x31,0x01,0x0e,0x01,0x0e,0x00,0x32,0x01,0x18,0x01,0x18,0x00,0x33,0x01,0x1a,0x01,0x1a,0x00,0x34,0x01,0x1c,0x01,0x1c,0x00,0x35,0x01,0x1e,0x01,0x1e,0x00,0x36,0x01,0x20,0x01,0x20,0x00,0x37,0x01,0x22,0x01,0x22,0x00,0x38,0x01,0x24,0x01,0x24,0x00,0x39,0x01,0x26,0x01,0x26,0x00,0x3a,0x01,0x28,0x01,0x28,0x00,0x3b, 0x01,0x2a,0x01,0x2a,0x00,0x3c,0x01,0x45,0x01,0x45,0x00,0x3d,0x01,0x47,0x01,0x47,0x00,0x3e,0x01,0x51,0x01,0x51,0x00,0x3f,0x01,0x53,0x01,0x53,0x00,0x40,0x01,0x55,0x01,0x55,0x00,0x41,0x01,0x63,0x01,0x63,0x00,0x42,0x01,0x65,0x01,0x65,0x00,0x43,0x01,0x68,0x01,0x68,0x00,0x44,0x01,0x6e,0x01,0x6e,0x00,0x45,0x01,0x70,0x01,0x70, 0x00,0x46,0x01,0x72,0x01,0x72,0x00,0x47,0x01,0x74,0x01,0x74,0x00,0x48,0x01,0x76,0x01,0x76,0x00,0x49,0x01,0x78,0x01,0x78,0x00,0x4a,0x01,0x7a,0x01,0x7a,0x00,0x4b,0x01,0x7c,0x01,0x7c,0x00,0x4c,0x01,0x7e,0x01,0x7e,0x00,0x4d,0x01,0x80,0x01,0x80,0x00,0x4e,0x01,0x82,0x01,0x82,0x00,0x4f,0x01,0x85,0x01,0x85,0x00,0x50,0x01,0x89, 0x01,0x89,0x00,0x51,0x01,0x8c,0x01,0x8c,0x00,0x52,0x01,0x8e,0x01,0x8e,0x00,0x53,0x01,0x90,0x01,0x90,0x00,0x54,0x01,0x92,0x01,0x92,0x00,0x55,0x02,0x3d,0x02,0x3d,0x00,0x56,0x00,0x01,0x00,0x0a,0x00,0x05,0x00,0x24,0x00,0x48,0x00,0x02,0x00,0x4c,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x62,0x00,0x68,0x00,0x1a,0x00,0x91,0x00,0x92, 0x00,0x21,0x00,0xad,0x00,0xb0,0x00,0x23,0x00,0xbb,0x00,0xbb,0x00,0x27,0x00,0xc7,0x00,0xd5,0x00,0x28,0x00,0xe1,0x00,0xe1,0x00,0x37,0x00,0xe3,0x00,0xe3,0x00,0x38,0x00,0xe5,0x00,0xe5,0x00,0x39,0x00,0xe8,0x00,0xe8,0x00,0x3a,0x00,0xea,0x00,0xea,0x00,0x3b,0x00,0xec,0x00,0xec,0x00,0x3c,0x00,0xf7,0x00,0xf7,0x00,0x3d,0x00,0xf9, 0x00,0xfa,0x00,0x3e,0x00,0xfc,0x00,0xfc,0x00,0x40,0x00,0xfe,0x00,0xfe,0x00,0x41,0x01,0x03,0x01,0x03,0x00,0x42,0x01,0x05,0x01,0x05,0x00,0x43,0x01,0x07,0x01,0x07,0x00,0x44,0x01,0x09,0x01,0x0a,0x00,0x45,0x01,0x0c,0x01,0x0c,0x00,0x47,0x01,0x0e,0x01,0x0e,0x00,0x48,0x01,0x10,0x01,0x10,0x00,0x49,0x01,0x12,0x01,0x12,0x00,0x4a, 0x01,0x14,0x01,0x14,0x00,0x4b,0x01,0x16,0x01,0x16,0x00,0x4c,0x01,0x18,0x01,0x18,0x00,0x4d,0x01,0x1a,0x01,0x1a,0x00,0x4e,0x01,0x1c,0x01,0x1c,0x00,0x4f,0x01,0x1e,0x01,0x1e,0x00,0x50,0x01,0x20,0x01,0x20,0x00,0x51,0x01,0x22,0x01,0x22,0x00,0x52,0x01,0x24,0x01,0x24,0x00,0x53,0x01,0x26,0x01,0x26,0x00,0x54,0x01,0x28,0x01,0x28, 0x00,0x55,0x01,0x2a,0x01,0x2a,0x00,0x56,0x01,0x39,0x01,0x39,0x00,0x57,0x01,0x45,0x01,0x45,0x00,0x58,0x01,0x47,0x01,0x47,0x00,0x59,0x01,0x49,0x01,0x49,0x00,0x5a,0x01,0x4b,0x01,0x4b,0x00,0x5b,0x01,0x4d,0x01,0x4d,0x00,0x5c,0x01,0x4f,0x01,0x4f,0x00,0x5d,0x01,0x51,0x01,0x51,0x00,0x5e,0x01,0x53,0x01,0x53,0x00,0x5f,0x01,0x55, 0x01,0x55,0x00,0x60,0x01,0x57,0x01,0x57,0x00,0x61,0x01,0x59,0x01,0x59,0x00,0x62,0x01,0x5b,0x01,0x5b,0x00,0x63,0x01,0x5d,0x01,0x5d,0x00,0x64,0x01,0x5f,0x01,0x5f,0x00,0x65,0x01,0x61,0x01,0x61,0x00,0x66,0x01,0x63,0x01,0x63,0x00,0x67,0x01,0x65,0x01,0x65,0x00,0x68,0x01,0x68,0x01,0x68,0x00,0x69,0x01,0x6a,0x01,0x6a,0x00,0x6a, 0x01,0x6c,0x01,0x6c,0x00,0x6b,0x01,0x6e,0x01,0x6e,0x00,0x6c,0x01,0x70,0x01,0x70,0x00,0x6d,0x01,0x72,0x01,0x72,0x00,0x6e,0x01,0x74,0x01,0x74,0x00,0x6f,0x01,0x76,0x01,0x76,0x00,0x70,0x01,0x78,0x01,0x78,0x00,0x71,0x01,0x7a,0x01,0x7a,0x00,0x72,0x01,0x7c,0x01,0x7c,0x00,0x73,0x01,0x7e,0x01,0x7e,0x00,0x74,0x01,0x80,0x01,0x80, 0x00,0x75,0x01,0x82,0x01,0x82,0x00,0x76,0x01,0x85,0x01,0x85,0x00,0x77,0x01,0x87,0x01,0x87,0x00,0x78,0x01,0x89,0x01,0x89,0x00,0x79,0x01,0x8c,0x01,0x8c,0x00,0x7a,0x01,0x8e,0x01,0x8e,0x00,0x7b,0x01,0x90,0x01,0x90,0x00,0x7c,0x01,0x92,0x01,0x92,0x00,0x7d,0x0b,0x21,0x0b,0x21,0x00,0x7e,0x00,0x01,0x00,0x0a,0x00,0x05,0x00,0x24, 0x00,0x48,0x00,0x02,0x00,0x02,0x01,0xdb,0x02,0x06,0x00,0x00,0x02,0x33,0x02,0x33,0x00,0x2c,0x00,0x01,0x00,0x0a,0x00,0x05,0x00,0x24,0x00,0x48,0x00,0x02,0x00,0x04,0x00,0xa9,0x00,0xa9,0x00,0x00,0x01,0x2c,0x01,0x2e,0x00,0x01,0x01,0xa1,0x01,0xa7,0x00,0x04,0x01,0xa9,0x01,0xbe,0x00,0x0b,0x00,0x02,0x00,0x26,0x00,0x02,0x00,0x0f, 0x00,0x8c,0x00,0x8c,0x00,0x6e,0x00,0x8c,0x00,0x8c,0x00,0x8c,0x00,0x8c,0x01,0x96,0x01,0x96,0x00,0x6e,0x00,0x6e,0x00,0x6e,0x00,0x6e,0x00,0x6e,0x00,0x6e,0x00,0x02,0x00,0x0b,0x00,0x0b,0x00,0x0c,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x02,0x00,0x3e,0x00,0x3e,0x00,0x03,0x00,0x40,0x00,0x40,0x00,0x04,0x00,0x5e,0x00,0x5e,0x00,0x05, 0x00,0x60,0x00,0x60,0x00,0x06,0x00,0xa2,0x00,0xa2,0x00,0x07,0x00,0xa4,0x00,0xa4,0x00,0x08,0x00,0xaa,0x00,0xab,0x00,0x09,0x00,0xb2,0x00,0xb3,0x00,0x0b,0x00,0xbe,0x00,0xbf,0x00,0x0d,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4a,0x00,0x02,0x00,0x02,0x0f,0x2c,0x0f,0x2d,0x00,0x00, 0x0f,0x30,0x0f,0x31,0x00,0x02,0x00,0x01,0x00,0x01,0x09,0x73,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4b,0x00,0x01,0x00,0x02,0x0a,0x07,0x0a,0x08,0x00,0x01,0x00,0x01,0x09,0x73,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x8e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4c,0x00,0x02, 0x00,0x14,0x08,0xf5,0x08,0xf5,0x00,0x00,0x08,0xf7,0x08,0xf7,0x00,0x01,0x09,0x02,0x09,0x02,0x00,0x02,0x09,0x0c,0x09,0x0c,0x00,0x03,0x09,0x2a,0x09,0x2b,0x00,0x04,0x09,0x4a,0x09,0x4b,0x00,0x06,0x09,0x8a,0x09,0x8b,0x00,0x08,0x0a,0x05,0x0a,0x08,0x00,0x0a,0x0a,0x0b,0x0a,0x0e,0x00,0x0e,0x0e,0x20,0x0e,0x21,0x00,0x12,0x0e,0x4b, 0x0e,0x4c,0x00,0x14,0x0e,0x4f,0x0e,0x50,0x00,0x16,0x0f,0x2c,0x0f,0x2d,0x00,0x18,0x0f,0x30,0x0f,0x31,0x00,0x1a,0x0f,0x34,0x0f,0x35,0x00,0x1c,0x13,0x1c,0x13,0x1c,0x00,0x1e,0x13,0x1f,0x13,0x20,0x00,0x1f,0x13,0x23,0x13,0x23,0x00,0x21,0x14,0x59,0x14,0x59,0x00,0x22,0x14,0x7e,0x14,0x7e,0x00,0x23,0x00,0x01,0x00,0x01,0x09,0x73, 0x00,0x01,0x03,0x7e,0x00,0x05,0x00,0x00,0x00,0x2e,0x00,0x66,0x00,0xd4,0x01,0x48,0x02,0x04,0x02,0x84,0x02,0x84,0x02,0x84,0x01,0x48,0x02,0x84,0x02,0x92,0x02,0x92,0x02,0x9a,0x02,0x92,0x02,0xc6,0x03,0x76,0x02,0x84,0x02,0x84,0x01,0x48,0x01,0x48,0x00,0x66,0x01,0x48,0x02,0x84,0x01,0x48,0x01,0x48,0x02,0xc6,0x02,0xc6,0x02,0xc6, 0x02,0xc6,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x66,0x01,0x48,0x02,0x84,0x02,0x84,0x01,0x48,0x02,0x84,0x01,0x48,0x02,0xc6,0x02,0x84,0x01,0x48,0x00,0x66,0x01,0x48,0x01,0x48,0x01,0x48,0x01,0x48,0x00,0x12,0x0b,0x6b,0xff,0xec,0xff,0xec,0x0b,0x74,0xff,0xec,0xff,0xec,0x0b,0x7a,0xff,0xec,0xff,0xec,0x0b,0x7f,0xff,0xec,0xff,0xec, 0x0b,0x81,0xff,0xec,0xff,0xec,0x0b,0x8a,0xff,0xec,0xff,0xec,0x0b,0x8b,0xff,0xec,0xff,0xec,0x0b,0x8d,0xff,0xec,0xff,0xec,0x0b,0x8f,0xff,0xec,0xff,0xec,0x0b,0x92,0xff,0xec,0xff,0xec,0x0b,0x97,0xff,0xec,0xff,0xec,0x0b,0x98,0xff,0xec,0xff,0xec,0x0b,0x99,0xff,0xec,0xff,0xec,0x0b,0x9a,0xff,0xec,0xff,0xec,0x0b,0xa0,0xff,0xec, 0xff,0xec,0x0b,0xaf,0xff,0xec,0xff,0xec,0x0b,0xb1,0xff,0xec,0xff,0xec,0x0b,0xbb,0xff,0xec,0xff,0xec,0x00,0x13,0x0b,0x6b,0xff,0xec,0xff,0xec,0x0b,0x71,0xff,0xec,0xff,0xec,0x0b,0x74,0xff,0xec,0xff,0xec,0x0b,0x7a,0xff,0xec,0xff,0xec,0x0b,0x7f,0xff,0xec,0xff,0xec,0x0b,0x81,0xff,0xec,0xff,0xec,0x0b,0x8a,0xff,0xec,0xff,0xec, 0x0b,0x8b,0xff,0xec,0xff,0xec,0x0b,0x8d,0xff,0xec,0xff,0xec,0x0b,0x8f,0xff,0xec,0xff,0xec,0x0b,0x92,0xff,0xec,0xff,0xec,0x0b,0x97,0xff,0xec,0xff,0xec,0x0b,0x98,0xff,0xec,0xff,0xec,0x0b,0x99,0xff,0xec,0xff,0xec,0x0b,0x9a,0xff,0xec,0xff,0xec,0x0b,0xa0,0xff,0xec,0xff,0xec,0x0b,0xaf,0xff,0xec,0xff,0xec,0x0b,0xb1,0xff,0xec, 0xff,0xec,0x0b,0xbb,0xff,0xec,0xff,0xec,0x00,0x1f,0x0b,0x69,0xff,0xce,0xff,0xce,0x0b,0x6a,0xff,0xce,0xff,0xce,0x0b,0x6c,0xff,0xce,0xff,0xce,0x0b,0x6e,0x00,0x28,0x00,0x28,0x0b,0x6f,0xff,0xce,0xff,0xce,0x0b,0x70,0xff,0xd8,0xff,0xd8,0x0b,0x73,0xff,0xd8,0xff,0xd8,0x0b,0x75,0xff,0xce,0xff,0xce,0x0b,0x76,0xff,0xce,0xff,0xce, 0x0b,0x78,0xff,0xce,0xff,0xce,0x0b,0x79,0xff,0xd8,0xff,0xd8,0x0b,0x7b,0xff,0xce,0xff,0xce,0x0b,0x7c,0xff,0xd8,0xff,0xd8,0x0b,0x7d,0x00,0x14,0x00,0x14,0x0b,0x82,0xff,0xce,0xff,0xce,0x0b,0x90,0xff,0xce,0xff,0xce,0x0b,0x91,0xff,0xd8,0xff,0xd8,0x0b,0x93,0xff,0xce,0xff,0xce,0x0b,0x94,0xff,0xce,0xff,0xce,0x0b,0x95,0xff,0xce, 0xff,0xce,0x0b,0x9f,0xff,0xce,0xff,0xce,0x0b,0xa1,0xff,0xce,0xff,0xce,0x0b,0xa4,0xff,0xd8,0xff,0xd8,0x0b,0xa6,0xff,0xce,0xff,0xce,0x0b,0xa7,0xff,0xd8,0xff,0xd8,0x0b,0xa9,0xff,0xce,0xff,0xce,0x0b,0xab,0xff,0xd8,0xff,0xd8,0x0b,0xac,0xff,0xce,0xff,0xce,0x0b,0xad,0xff,0xd8,0xff,0xd8,0x0b,0xb0,0xff,0xce,0xff,0xce,0x0b,0xb2, 0xff,0xce,0xff,0xce,0x00,0x15,0x0b,0x6a,0xff,0xe2,0xff,0xe2,0x0b,0x6c,0xff,0xec,0xff,0xec,0x0b,0x6e,0x00,0x14,0x00,0x14,0x0b,0x6f,0xff,0xec,0xff,0xec,0x0b,0x75,0xff,0xec,0xff,0xec,0x0b,0x76,0xff,0xec,0xff,0xec,0x0b,0x78,0xff,0xec,0xff,0xec,0x0b,0x7b,0xff,0xec,0xff,0xec,0x0b,0x7d,0x00,0x14,0x00,0x14,0x0b,0x82,0xff,0xec, 0xff,0xec,0x0b,0x90,0xff,0xec,0xff,0xec,0x0b,0x93,0xff,0xec,0xff,0xec,0x0b,0x94,0xff,0xec,0xff,0xec,0x0b,0x95,0xff,0xec,0xff,0xec,0x0b,0x9f,0xff,0xe2,0xff,0xe2,0x0b,0xa1,0xff,0xec,0xff,0xec,0x0b,0xa6,0xff,0xec,0xff,0xec,0x0b,0xa9,0xff,0xec,0xff,0xec,0x0b,0xac,0xff,0xec,0xff,0xec,0x0b,0xb0,0xff,0xec,0xff,0xec,0x0b,0xb2, 0xff,0xec,0xff,0xec,0x00,0x02,0x0b,0x6a,0xff,0xe2,0xff,0xe2,0x0b,0x9f,0xff,0xe2,0xff,0xe2,0x00,0x01,0x0b,0x6e,0x00,0x14,0x00,0x14,0x00,0x07,0x0b,0x79,0xff,0xe2,0xff,0xe2,0x0b,0x7c,0xff,0xe2,0xff,0xe2,0x0b,0x91,0xff,0xe2,0xff,0xe2,0x0b,0xa4,0xff,0xe2,0xff,0xe2,0x0b,0xa7,0xff,0xe2,0xff,0xe2,0x0b,0xab,0xff,0xe2,0xff,0xe2, 0x0b,0xad,0xff,0xe2,0xff,0xe2,0x00,0x1d,0x0b,0x69,0xff,0xec,0xff,0xec,0x0b,0x6a,0xff,0xe2,0xff,0xe2,0x0b,0x6c,0xff,0xec,0xff,0xec,0x0b,0x6f,0xff,0xec,0xff,0xec,0x0b,0x70,0xff,0xec,0xff,0xec,0x0b,0x73,0xff,0xec,0xff,0xec,0x0b,0x75,0xff,0xec,0xff,0xec,0x0b,0x76,0xff,0xec,0xff,0xec,0x0b,0x78,0xff,0xec,0xff,0xec,0x0b,0x79, 0xff,0xec,0xff,0xec,0x0b,0x7b,0xff,0xec,0xff,0xec,0x0b,0x7c,0xff,0xec,0xff,0xec,0x0b,0x82,0xff,0xec,0xff,0xec,0x0b,0x90,0xff,0xec,0xff,0xec,0x0b,0x91,0xff,0xec,0xff,0xec,0x0b,0x93,0xff,0xec,0xff,0xec,0x0b,0x94,0xff,0xec,0xff,0xec,0x0b,0x95,0xff,0xec,0xff,0xec,0x0b,0x9f,0xff,0xe2,0xff,0xe2,0x0b,0xa1,0xff,0xec,0xff,0xec, 0x0b,0xa4,0xff,0xec,0xff,0xec,0x0b,0xa6,0xff,0xec,0xff,0xec,0x0b,0xa7,0xff,0xec,0xff,0xec,0x0b,0xa9,0xff,0xec,0xff,0xec,0x0b,0xab,0xff,0xec,0xff,0xec,0x0b,0xac,0xff,0xec,0xff,0xec,0x0b,0xad,0xff,0xec,0xff,0xec,0x0b,0xb0,0xff,0xec,0xff,0xec,0x0b,0xb2,0xff,0xec,0xff,0xec,0x00,0x01,0x0b,0x81,0xff,0xe2,0xff,0xe2,0x00,0x02, 0x00,0x16,0x0b,0x68,0x0b,0x68,0x00,0x00,0x0b,0x6a,0x0b,0x6b,0x00,0x01,0x0b,0x6e,0x0b,0x6e,0x00,0x03,0x0b,0x70,0x0b,0x71,0x00,0x04,0x0b,0x73,0x0b,0x74,0x00,0x06,0x0b,0x79,0x0b,0x7a,0x00,0x08,0x0b,0x7d,0x0b,0x7f,0x00,0x0a,0x0b,0x81,0x0b,0x82,0x00,0x0d,0x0b,0x84,0x0b,0x85,0x00,0x0f,0x0b,0x8a,0x0b,0x8b,0x00,0x11,0x0b,0x8e, 0x0b,0x8f,0x00,0x13,0x0b,0x91,0x0b,0x92,0x00,0x15,0x0b,0x94,0x0b,0x94,0x00,0x17,0x0b,0x97,0x0b,0x9d,0x00,0x18,0x0b,0x9f,0x0b,0xa0,0x00,0x1f,0x0b,0xa4,0x0b,0xa4,0x00,0x21,0x0b,0xa7,0x0b,0xa8,0x00,0x22,0x0b,0xab,0x0b,0xab,0x00,0x24,0x0b,0xb0,0x0b,0xb1,0x00,0x25,0x0b,0xb5,0x0b,0xb5,0x00,0x27,0x0b,0xb7,0x0b,0xb7,0x00,0x28, 0x0b,0xba,0x0b,0xbe,0x00,0x29,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x28,0x00,0x01,0x00,0x00,0x00,0x4d,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf, 0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x02,0x00,0x44,0x00,0x44,0x00,0x01,0x00,0x00,0x00,0x4e,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x28,0x00,0x02,0x00,0x30,0x00,0x5e,0x00,0x01, 0x00,0x00,0x00,0x4e,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x14,0x00,0x02,0x00,0x1c,0x00,0x50,0x00,0x01,0x00,0x00,0x00,0x4e,0x00,0x01,0x00,0x02,0x0b,0x53,0x0b,0x57,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9, 0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x5a,0x00,0x01,0x00,0x01,0x0b,0x58,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x54,0x00,0x01,0x00,0x5a,0x00,0x01,0x00,0x00,0x00,0x4f,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x02,0x00,0x4e,0x00,0x48,0x00,0x01,0x00,0x00,0x00,0x4f, 0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2e,0x00,0x03,0x00,0x3a,0x00,0x3a,0x00,0x34,0x00,0x01,0x00,0x00,0x00,0x4f,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x04,0x00,0x24,0x00,0x24,0x00,0x24,0x00,0x1e,0x00,0x01,0x00,0x00,0x00,0x4f,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x02,0x00,0x05,0x0b,0x5f, 0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xdd,0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x30,0x00,0x02,0x02,0x36,0x02,0x3c,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x1c,0x00,0x02,0x02,0x22,0x02,0x38,0x00,0x01, 0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x08,0x00,0x03,0x02,0x0e,0x02,0x2a,0x02,0x24,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xf2,0x00,0x02,0x01,0xf8,0x02,0x36,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xde,0x00,0x03,0x01,0xe4,0x02,0x00,0x02,0x22,0x00,0x01, 0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xc8,0x00,0x01,0x02,0x12,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xb6,0x00,0x03,0x01,0xd8,0x01,0xbc,0x01,0xc2,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xa0,0x00,0x04,0x01,0xc2,0x01,0xc2,0x01,0xa6,0x01,0xac,0x00,0x01, 0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x88,0x00,0x05,0x01,0xaa,0x01,0xaa,0x01,0xaa,0x01,0x8e,0x01,0x94,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x6e,0x00,0x03,0x01,0x90,0x01,0x74,0x01,0x8a,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x58,0x00,0x04,0x01,0x7a, 0x01,0x5e,0x01,0x7a,0x01,0x74,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x40,0x00,0x04,0x01,0x62,0x01,0x62,0x01,0x46,0x01,0x5c,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x28,0x00,0x05,0x01,0x4a,0x01,0x4a,0x01,0x2e,0x01,0x4a,0x01,0x44,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03, 0x00,0x00,0x00,0x01,0x01,0x0e,0x00,0x05,0x01,0x30,0x01,0x30,0x01,0x30,0x01,0x14,0x01,0x2a,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xf4,0x00,0x06,0x01,0x16,0x01,0x16,0x01,0x16,0x00,0xfa,0x01,0x16,0x01,0x10,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xd8,0x00,0x03,0x00,0xfa, 0x00,0xde,0x01,0x1c,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xc2,0x00,0x04,0x00,0xe4,0x00,0xc8,0x00,0xe4,0x01,0x06,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xaa,0x00,0x04,0x00,0xcc,0x00,0xcc,0x00,0xb0,0x00,0xee,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01, 0x00,0x92,0x00,0x05,0x00,0xb4,0x00,0xb4,0x00,0x98,0x00,0xb4,0x00,0xd6,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x78,0x00,0x05,0x00,0x9a,0x00,0x9a,0x00,0x9a,0x00,0x7e,0x00,0xbc,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x5e,0x00,0x06,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x64, 0x00,0x80,0x00,0xa2,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x02,0x00,0x64,0x00,0x8c,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2e,0x00,0x03,0x00,0x50,0x00,0x50,0x00,0x78,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x04,0x00,0x3a, 0x00,0x3a,0x00,0x3a,0x00,0x62,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x02,0x00,0x02,0x0b,0x53,0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0xb3,0x00,0x02,0x00,0x05,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf, 0x0b,0xdd,0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x01,0x00,0x01,0x0b,0xa2,0x00,0x01,0x00,0x01,0x0b,0x9d,0x00,0x03,0x00,0x00,0x00,0x01,0x03,0x3c,0x00,0x02,0x03,0x42,0x03,0x82,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x03,0x28,0x00,0x03,0x03,0xa8,0x03,0x2e,0x03,0x6e, 0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x03,0x12,0x00,0x04,0x03,0x92,0x03,0x92,0x03,0x18,0x03,0x58,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0xfa,0x00,0x03,0x03,0x00,0x03,0x9c,0x03,0xa2,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0xe4,0x00,0x04,0x03,0x64, 0x02,0xea,0x03,0x86,0x03,0x8c,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0xcc,0x00,0x05,0x03,0x4c,0x03,0x4c,0x02,0xd2,0x03,0x6e,0x03,0x74,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0xb2,0x00,0x02,0x02,0xb8,0x03,0x6a,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01, 0x02,0x9e,0x00,0x03,0x03,0x1e,0x02,0xa4,0x03,0x56,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x88,0x00,0x04,0x03,0x08,0x03,0x08,0x02,0x8e,0x03,0x40,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x70,0x00,0x03,0x02,0x76,0x03,0x12,0x03,0x2e,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03, 0x00,0x00,0x00,0x01,0x02,0x5a,0x00,0x04,0x02,0xda,0x02,0x60,0x02,0xfc,0x03,0x18,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x42,0x00,0x05,0x02,0xc2,0x02,0xc2,0x02,0x48,0x02,0xe4,0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x28,0x00,0x03,0x02,0x2e,0x02,0xca,0x02,0xec, 0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x02,0x12,0x00,0x04,0x02,0x92,0x02,0x18,0x02,0xb4,0x02,0xd6,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xfa,0x00,0x05,0x02,0x7a,0x02,0x7a,0x02,0x00,0x02,0x9c,0x02,0xbe,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xe0, 0x00,0x03,0x01,0xe6,0x02,0x60,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xca,0x00,0x04,0x02,0x4a,0x01,0xd0,0x02,0x4a,0x02,0x10,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0xb2,0x00,0x05,0x02,0x32,0x02,0x32,0x01,0xb8,0x02,0x32,0x01,0xf8,0x00,0x01,0x00,0x00,0x00,0x51, 0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x98,0x00,0x04,0x01,0x9e,0x02,0x18,0x02,0x3a,0x02,0x40,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x80,0x00,0x05,0x02,0x00,0x01,0x86,0x02,0x00,0x02,0x22,0x02,0x28,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x66,0x00,0x06,0x01,0xe6,0x01,0xe6, 0x01,0x6c,0x01,0xe6,0x02,0x08,0x02,0x0e,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x4a,0x00,0x03,0x01,0x50,0x01,0xca,0x02,0x02,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x34,0x00,0x04,0x01,0xb4,0x01,0x3a,0x01,0xb4,0x01,0xec,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00, 0x00,0x01,0x01,0x1c,0x00,0x05,0x01,0x9c,0x01,0x9c,0x01,0x22,0x01,0x9c,0x01,0xd4,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x01,0x02,0x00,0x05,0x01,0x08,0x01,0x82,0x01,0xa4,0x01,0xcc,0x01,0xd2,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xe8,0x00,0x06,0x01,0x68,0x00,0xee,0x01,0x68, 0x01,0x8a,0x01,0xb2,0x01,0xb8,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xcc,0x00,0x07,0x01,0x4c,0x01,0x4c,0x00,0xd2,0x01,0x4c,0x01,0x6e,0x01,0x96,0x01,0x9c,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xae,0x00,0x04,0x00,0xb4,0x01,0x2e,0x01,0x50,0x01,0x6c,0x00,0x01,0x00,0x00, 0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0x05,0x01,0x16,0x00,0x9c,0x01,0x16,0x01,0x38,0x01,0x54,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x7c,0x00,0x06,0x00,0xfc,0x00,0xfc,0x00,0x82,0x00,0xfc,0x01,0x1e,0x01,0x3a,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x60, 0x00,0x04,0x00,0x66,0x00,0xe0,0x01,0x02,0x01,0x24,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x48,0x00,0x05,0x00,0xc8,0x00,0x4e,0x00,0xc8,0x00,0xea,0x01,0x0c,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2e,0x00,0x06,0x00,0xae,0x00,0xae,0x00,0x34,0x00,0xae,0x00,0xd0,0x00,0xf2, 0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x03,0x00,0x01,0x00,0xe8,0x00,0x01,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x0a,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcc,0x00,0x06,0x0b,0xcf,0x0b,0xcf,0x00,0x07, 0x0b,0xd6,0x0b,0xd6,0x00,0x08,0x0b,0xd9,0x0b,0xda,0x00,0x09,0x0b,0xdd,0x0b,0xdd,0x00,0x0b,0x0b,0xe1,0x0b,0xe1,0x00,0x0c,0x12,0x5c,0x12,0x5d,0x00,0x0d,0x00,0x02,0x00,0x09,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x69,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1e,0x0b,0x97,0x0b,0x9a,0x00,0x2c,0x0b,0x9d,0x0b,0xa6,0x00,0x30, 0x0b,0xa8,0x0b,0xb2,0x00,0x3a,0x0b,0xb4,0x0b,0xb7,0x00,0x45,0x0b,0xe0,0x0b,0xe0,0x00,0x49,0x12,0x5f,0x12,0x62,0x00,0x4a,0x00,0x02,0x00,0x05,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xdd,0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x01,0x00,0x01,0x0b,0x68, 0x00,0x02,0x00,0x02,0x0b,0x53,0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x9d,0x00,0x01,0x00,0x01,0x0b,0xb3,0x00,0x01,0x00,0x01,0x0b,0xa2,0x00,0x01,0x00,0x01,0x0b,0x6d,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x01,0x00,0x01,0x0b,0x61,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x1a,0x00,0x01,0x00,0x42, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x52,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x02,0x00,0x03,0x0b,0xc0,0x0b,0xc0,0x00,0x00, 0x0b,0xd7,0x0b,0xd7,0x00,0x01,0x0b,0xdc,0x0b,0xdc,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xf0,0x00,0x01,0x00,0xf8,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xde,0x00,0x02,0x01,0x0e,0x00,0xe6,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xca,0x00,0x03,0x00,0xfa,0x00,0xfa, 0x00,0xd2,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xb4,0x00,0x01,0x01,0x06,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xa2,0x00,0x02,0x00,0xd2,0x00,0xf4,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x8e,0x00,0x03,0x00,0xbe,0x00,0xbe,0x00,0xe0,0x00,0x01, 0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x78,0x00,0x01,0x00,0xd0,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x66,0x00,0x02,0x00,0x96,0x00,0xbe,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x52,0x00,0x03,0x00,0x82,0x00,0x82,0x00,0xaa,0x00,0x01,0x00,0x00,0x00,0x53, 0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x01,0x00,0x9a,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2a,0x00,0x02,0x00,0x5a,0x00,0x88,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x16,0x00,0x03,0x00,0x46,0x00,0x46,0x00,0x74,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x01,0x00,0x02, 0x0b,0xc0,0x0b,0xd7,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x02,0x00,0x05,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xdd, 0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x01,0x00,0x01,0x0b,0x62,0x00,0x01,0x00,0x01,0x11,0x86,0x00,0x01,0x00,0x01,0x0b,0x07,0x00,0x03,0x00,0x01,0x00,0x40,0x00,0x01,0x00,0x46,0x00,0x01,0x00,0x4e,0x00,0x01,0x00,0x00,0x00,0x54,0x00,0x03,0x00,0x01,0x00,0x2c,0x00,0x01,0x00,0x32,0x00,0x02, 0x00,0x74,0x00,0x7a,0x00,0x01,0x00,0x00,0x00,0x54,0x00,0x03,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x1c,0x00,0x02,0x00,0x5e,0x00,0x64,0x00,0x01,0x00,0x00,0x00,0x54,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x01,0x00,0x02,0x0b,0xc0,0x0b,0xd7,0x00,0x02,0x00,0x09,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x69,0x0b,0x85,0x00,0x01,0x0b,0x88, 0x0b,0x95,0x00,0x1e,0x0b,0x97,0x0b,0x9a,0x00,0x2c,0x0b,0x9d,0x0b,0xa6,0x00,0x30,0x0b,0xa8,0x0b,0xb2,0x00,0x3a,0x0b,0xb4,0x0b,0xb7,0x00,0x45,0x0b,0xe0,0x0b,0xe0,0x00,0x49,0x12,0x5f,0x12,0x62,0x00,0x4a,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x02,0x00,0x02,0x0b,0x53,0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b,0x00,0x03, 0x00,0x02,0x00,0xee,0x00,0xee,0x00,0x01,0x01,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x03,0x01,0x08,0x00,0xda,0x00,0xda,0x00,0x01,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x04,0x00,0xf2,0x00,0xf2,0x00,0xc4,0x00,0xc4,0x00,0x01,0x00,0xec,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55, 0x00,0x03,0x00,0x02,0x00,0xac,0x00,0xda,0x00,0x01,0x00,0xd4,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x03,0x00,0xc6,0x00,0x98,0x00,0xc6,0x00,0x01,0x00,0xc0,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x04,0x00,0xb0,0x00,0xb0,0x00,0x82,0x00,0xb0,0x00,0x01,0x00,0xaa,0x00,0x00,0x00,0x01,0x00,0x00, 0x00,0x55,0x00,0x03,0x00,0x02,0x00,0x6a,0x00,0xc6,0x00,0x01,0x00,0x92,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x03,0x00,0x84,0x00,0x56,0x00,0xb2,0x00,0x01,0x00,0x7e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x04,0x00,0x6e,0x00,0x6e,0x00,0x40,0x00,0x9c,0x00,0x01,0x00,0x68,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x02,0x00,0x28,0x00,0x8a,0x00,0x01,0x00,0x50,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x7c,0x00,0x01,0x00,0x3c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95, 0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x01,0x0b,0xce,0x00,0x02,0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61,0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd,0x00,0x11,0x0b,0xe1,0x0b,0xe1, 0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x01,0x00,0x01,0x0b,0x62,0x00,0x01,0x00,0x01,0x11,0x86,0x00,0x01,0x00,0x01,0x0b,0x07,0x00,0x03,0x00,0x03,0x00,0x64,0x00,0x6a,0x00,0x6a,0x00,0x01,0x00,0x92,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x56,0x00,0x03,0x00,0x04,0x00,0x4e,0x00,0x54,0x00,0x82,0x00,0x54,0x00,0x01,0x00,0x7c, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x56,0x00,0x03,0x00,0x05,0x00,0x36,0x00,0x3c,0x00,0x6a,0x00,0x6a,0x00,0x3c,0x00,0x01,0x00,0x64,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x56,0x00,0x03,0x00,0x06,0x00,0x1c,0x00,0x22,0x00,0x50,0x00,0x50,0x00,0x50,0x00,0x22,0x00,0x01,0x00,0x4a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x56,0x00,0x01, 0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x01,0x0b,0xce,0x00,0x02,0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61, 0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd,0x00,0x11,0x0b,0xe1,0x0b,0xe1,0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x03,0x00,0x02,0x06,0x38,0x06,0x3e,0x00,0x01,0x06,0x66,0x00,0x01,0x06,0xa6,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x06,0x22,0x06,0xca,0x06,0x28, 0x00,0x01,0x06,0x50,0x00,0x01,0x06,0x90,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x06,0x0a,0x06,0x10,0x00,0x01,0x06,0x38,0x00,0x02,0x06,0xba,0x06,0x78,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x06,0xa2,0x05,0xf2,0x05,0xf8,0x00,0x01,0x06,0x20,0x00,0x01,0x06,0x60,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03, 0x00,0x04,0x06,0x8a,0x06,0x8a,0x05,0xda,0x05,0xe0,0x00,0x01,0x06,0x08,0x00,0x01,0x06,0x48,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x06,0x70,0x05,0xc0,0x05,0xc6,0x00,0x01,0x05,0xee,0x00,0x02,0x06,0x70,0x06,0x2e,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x06,0x56,0x06,0x56,0x05,0xa6,0x05,0xac,0x00,0x01, 0x05,0xd4,0x00,0x02,0x06,0x56,0x06,0x14,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x05,0x8a,0x06,0x32,0x05,0x90,0x00,0x01,0x05,0xb8,0x00,0x02,0x06,0x3a,0x05,0xf8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x06,0x20,0x05,0x70,0x06,0x18,0x05,0x76,0x00,0x01,0x05,0x9e,0x00,0x01,0x05,0xde,0x00,0x01,0x00,0x00, 0x00,0x57,0x00,0x03,0x00,0x05,0x06,0x06,0x06,0x06,0x05,0x56,0x05,0xfe,0x05,0x5c,0x00,0x01,0x05,0x84,0x00,0x01,0x05,0xc4,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x05,0xea,0x05,0x3a,0x05,0xe2,0x05,0x40,0x00,0x01,0x05,0x68,0x00,0x02,0x05,0xea,0x05,0xa8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x05,0x05,0xce, 0x05,0xce,0x05,0x1e,0x05,0xc6,0x05,0x24,0x00,0x01,0x05,0x4c,0x00,0x02,0x05,0xce,0x05,0x8c,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x05,0x00,0x05,0x06,0x00,0x01,0x05,0x2e,0x00,0x02,0x05,0xd2,0x05,0xd8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x04,0xe8,0x05,0x90,0x04,0xee,0x00,0x01,0x05,0x16,0x00,0x02, 0x05,0xba,0x05,0xc0,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x04,0xce,0x04,0xd4,0x00,0x01,0x04,0xfc,0x00,0x03,0x05,0x7e,0x05,0xa0,0x05,0xa6,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x05,0x64,0x04,0xb4,0x04,0xba,0x00,0x01,0x04,0xe2,0x00,0x02,0x05,0x86,0x05,0x8c,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03, 0x00,0x04,0x05,0x4a,0x05,0x4a,0x04,0x9a,0x04,0xa0,0x00,0x01,0x04,0xc8,0x00,0x02,0x05,0x6c,0x05,0x72,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x05,0x2e,0x04,0x7e,0x04,0x84,0x00,0x01,0x04,0xac,0x00,0x03,0x05,0x2e,0x05,0x50,0x05,0x56,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x05,0x12,0x05,0x12,0x04,0x62, 0x04,0x68,0x00,0x01,0x04,0x90,0x00,0x03,0x05,0x12,0x05,0x34,0x05,0x3a,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x04,0x44,0x04,0xec,0x04,0x4a,0x00,0x01,0x04,0x72,0x00,0x03,0x04,0xf4,0x05,0x16,0x05,0x1c,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x04,0xd8,0x04,0x28,0x04,0xd0,0x04,0x2e,0x00,0x01,0x04,0x56, 0x00,0x02,0x04,0xfa,0x05,0x00,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x05,0x04,0xbc,0x04,0xbc,0x04,0x0c,0x04,0xb4,0x04,0x12,0x00,0x01,0x04,0x3a,0x00,0x02,0x04,0xde,0x04,0xe4,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x04,0x9e,0x03,0xee,0x04,0x96,0x03,0xf4,0x00,0x01,0x04,0x1c,0x00,0x03,0x04,0x9e,0x04,0xc0, 0x04,0xc6,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x05,0x04,0x80,0x04,0x80,0x03,0xd0,0x04,0x78,0x03,0xd6,0x00,0x01,0x03,0xfe,0x00,0x03,0x04,0x80,0x04,0xa2,0x04,0xa8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x03,0xb0,0x03,0xb6,0x00,0x01,0x03,0xde,0x00,0x02,0x04,0x82,0x04,0x98,0x00,0x01,0x00,0x00,0x00,0x57, 0x00,0x03,0x00,0x02,0x03,0x98,0x03,0x9e,0x00,0x01,0x03,0xc6,0x00,0x02,0x04,0x6a,0x04,0x86,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0x80,0x04,0x28,0x03,0x86,0x00,0x01,0x03,0xae,0x00,0x02,0x04,0x52,0x04,0x68,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0x66,0x04,0x0e,0x03,0x6c,0x00,0x01,0x03,0x94, 0x00,0x02,0x04,0x38,0x04,0x54,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x03,0x4c,0x03,0x52,0x00,0x01,0x03,0x7a,0x00,0x03,0x03,0xfc,0x04,0x1e,0x04,0x34,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0xe2,0x03,0x32,0x03,0x38,0x00,0x01,0x03,0x60,0x00,0x02,0x04,0x04,0x04,0x1a,0x00,0x01,0x00,0x00,0x00,0x57, 0x00,0x03,0x00,0x04,0x03,0xc8,0x03,0xc8,0x03,0x18,0x03,0x1e,0x00,0x01,0x03,0x46,0x00,0x02,0x03,0xea,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0xac,0x02,0xfc,0x03,0x02,0x00,0x01,0x03,0x2a,0x00,0x03,0x03,0xac,0x03,0xce,0x03,0xe4,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x03,0x90,0x03,0x90, 0x02,0xe0,0x02,0xe6,0x00,0x01,0x03,0x0e,0x00,0x03,0x03,0x90,0x03,0xb2,0x03,0xc8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x02,0xc2,0x02,0xc8,0x00,0x01,0x02,0xf0,0x00,0x03,0x03,0x72,0x03,0x94,0x03,0xb0,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0x58,0x02,0xa8,0x02,0xae,0x00,0x01,0x02,0xd6,0x00,0x02, 0x03,0x7a,0x03,0x96,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x03,0x3e,0x03,0x3e,0x02,0x8e,0x02,0x94,0x00,0x01,0x02,0xbc,0x00,0x02,0x03,0x60,0x03,0x7c,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x03,0x22,0x02,0x72,0x02,0x78,0x00,0x01,0x02,0xa0,0x00,0x03,0x03,0x22,0x03,0x44,0x03,0x60,0x00,0x01,0x00,0x00, 0x00,0x57,0x00,0x03,0x00,0x04,0x03,0x06,0x03,0x06,0x02,0x56,0x02,0x5c,0x00,0x01,0x02,0x84,0x00,0x03,0x03,0x06,0x03,0x28,0x03,0x44,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x02,0x38,0x02,0xe0,0x02,0x3e,0x00,0x01,0x02,0x66,0x00,0x03,0x02,0xe8,0x03,0x0a,0x03,0x20,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04, 0x02,0xcc,0x02,0x1c,0x02,0xc4,0x02,0x22,0x00,0x01,0x02,0x4a,0x00,0x02,0x02,0xee,0x03,0x04,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x02,0xb0,0x02,0x00,0x02,0xa8,0x02,0x06,0x00,0x01,0x02,0x2e,0x00,0x02,0x02,0xd2,0x02,0xe8,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x02,0x94,0x01,0xe4,0x02,0x8c,0x01,0xea, 0x00,0x01,0x02,0x12,0x00,0x03,0x02,0x94,0x02,0xb6,0x02,0xcc,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x02,0x76,0x02,0x76,0x00,0x01,0x01,0xf4,0x00,0x03,0x02,0x76,0x02,0x98,0x02,0xae,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x01,0xac,0x02,0x54,0x01,0xb2,0x00,0x01,0x01,0xda,0x00,0x03,0x02,0x5c,0x02,0x7e, 0x02,0x94,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x02,0x40,0x01,0x90,0x02,0x38,0x01,0x96,0x00,0x01,0x01,0xbe,0x00,0x02,0x02,0x62,0x02,0x78,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x05,0x02,0x24,0x02,0x24,0x01,0x74,0x02,0x1c,0x01,0x7a,0x00,0x01,0x01,0xa2,0x00,0x02,0x02,0x46,0x02,0x5c,0x00,0x01,0x00,0x00, 0x00,0x57,0x00,0x03,0x00,0x04,0x02,0x06,0x01,0x56,0x01,0xfe,0x01,0x5c,0x00,0x01,0x01,0x84,0x00,0x03,0x02,0x06,0x02,0x28,0x02,0x3e,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x01,0x38,0x01,0x3e,0x00,0x01,0x01,0x66,0x00,0x01,0x02,0x2c,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x01,0x22,0x01,0xca,0x01,0x28, 0x00,0x01,0x01,0x50,0x00,0x01,0x02,0x16,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x02,0x01,0x0a,0x01,0x10,0x00,0x01,0x01,0x38,0x00,0x02,0x01,0xba,0x01,0xfe,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x01,0xa2,0x00,0xf2,0x00,0xf8,0x00,0x01,0x01,0x20,0x00,0x01,0x01,0xe6,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03, 0x00,0x04,0x01,0x8a,0x01,0x8a,0x00,0xda,0x00,0xe0,0x00,0x01,0x01,0x08,0x00,0x01,0x01,0xce,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x01,0x70,0x00,0xc0,0x00,0xc6,0x00,0x01,0x00,0xee,0x00,0x02,0x01,0x70,0x01,0xb4,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x01,0x56,0x01,0x56,0x00,0xa6,0x00,0xac,0x00,0x01, 0x00,0xd4,0x00,0x02,0x01,0x56,0x01,0x9a,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x03,0x00,0x8a,0x01,0x32,0x00,0x90,0x00,0x01,0x00,0xb8,0x00,0x02,0x01,0x3a,0x01,0x7e,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x01,0x20,0x00,0x70,0x01,0x18,0x00,0x76,0x00,0x01,0x00,0x9e,0x00,0x01,0x01,0x64,0x00,0x01,0x00,0x00, 0x00,0x57,0x00,0x03,0x00,0x05,0x01,0x06,0x01,0x06,0x00,0x56,0x00,0xfe,0x00,0x5c,0x00,0x01,0x00,0x84,0x00,0x01,0x01,0x4a,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x04,0x00,0xea,0x00,0x3a,0x00,0xe2,0x00,0x40,0x00,0x01,0x00,0x68,0x00,0x02,0x00,0xea,0x01,0x2e,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x03,0x00,0x05,0x00,0xce, 0x00,0xce,0x00,0x1e,0x00,0xc6,0x00,0x24,0x00,0x01,0x00,0x4c,0x00,0x02,0x00,0xce,0x01,0x12,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31, 0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x02,0x00,0x0a,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcc,0x00,0x06,0x0b,0xcf,0x0b,0xcf,0x00,0x07,0x0b,0xd6,0x0b,0xd6,0x00,0x08,0x0b,0xd9,0x0b,0xda,0x00,0x09,0x0b,0xdd,0x0b,0xdd,0x00,0x0b,0x0b,0xe1,0x0b,0xe1,0x00,0x0c, 0x12,0x5c,0x12,0x5d,0x00,0x0d,0x00,0x02,0x00,0x09,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x69,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1e,0x0b,0x97,0x0b,0x9a,0x00,0x2c,0x0b,0x9d,0x0b,0xa6,0x00,0x30,0x0b,0xa8,0x0b,0xb2,0x00,0x3a,0x0b,0xb4,0x0b,0xb7,0x00,0x45,0x0b,0xe0,0x0b,0xe0,0x00,0x49,0x12,0x5f,0x12,0x62,0x00,0x4a, 0x00,0x01,0x00,0x02,0x0b,0x5e,0x0b,0x61,0x00,0x02,0x00,0x05,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xdd,0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x02,0x00,0x02,0x0b,0x53,0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b, 0x00,0x01,0x00,0x01,0x0b,0xb3,0x00,0x01,0x00,0x01,0x0b,0xa2,0x00,0x01,0x00,0x01,0x0b,0x9d,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x58,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x01,0x00,0x02,0x0b,0x53,0x0b,0x57,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1a, 0x00,0x01,0x00,0x00,0x00,0x59,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x02,0x00,0x02,0x0b,0x58,0x0b,0x5b,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x04,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x02,0x00,0x02,0x0b,0x54,0x0b,0x56, 0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x3c,0x00,0x01,0x00,0x42,0x00,0x01,0x00,0x70,0x00,0x01,0x00,0x00,0x00,0x5b,0x00,0x03,0x00,0x01,0x00,0x8a,0x00,0x01,0x00,0x2e,0x00,0x01,0x00,0x5c,0x00,0x01,0x00,0x00,0x00,0x5b,0x00,0x03,0x00,0x01,0x00,0x7c,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x48,0x00,0x01, 0x00,0x00,0x00,0x5b,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f, 0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x88,0x00,0x01,0x00,0x01,0x0b,0x89,0x00,0x03,0x00,0x02,0x00,0x3e,0x00,0x6c,0x00,0x01,0x00,0x72,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x5c,0x00,0x03,0x00,0x03,0x00,0x66,0x00,0x7c,0x00,0x82,0x00,0x01,0x00,0x5e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5c,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x94,0x00,0x01,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5c,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01, 0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x53,0x00,0x01,0x00,0x02,0x0b,0xc8,0x0b,0xdb,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9, 0x00,0x0a,0x00,0x01,0x00,0x01,0x0b,0x5f,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x01,0x0b,0x57,0x00,0x03,0x00,0x02,0x00,0x78,0x00,0xa6,0x00,0x01, 0x00,0xac,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x03,0x00,0x02,0x00,0x64,0x00,0xa0,0x00,0x01,0x00,0x98,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x03,0x00,0x02,0x00,0x50,0x00,0x92,0x00,0x01,0x00,0x84,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x03,0x00,0x02,0x00,0x3c,0x00,0x84,0x00,0x01,0x00,0x70,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x03,0x00,0x02,0x00,0x28,0x00,0x76,0x00,0x01,0x00,0x5c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x68,0x00,0x01,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5d,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf, 0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x58,0x00,0x01,0x00,0x02,0x0b,0xc8,0x0b,0xdb,0x00,0x01,0x00,0x01,0x0b,0x59,0x00,0x01,0x00,0x01,0x0b,0x5a,0x00,0x01,0x00,0x01,0x0b,0x5b,0x00,0x01,0x00,0x01, 0x0b,0x5d,0x00,0x01,0x00,0x01,0x0b,0xb9,0x00,0x03,0x00,0x02,0x00,0x50,0x00,0x7e,0x00,0x01,0x00,0x84,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5e,0x00,0x03,0x00,0x02,0x00,0x3c,0x00,0x78,0x00,0x01,0x00,0x70,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5e,0x00,0x03,0x00,0x02,0x00,0x28,0x00,0x6a,0x00,0x01,0x00,0x5c,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x5e,0x00,0x03,0x00,0x02,0x00,0x5c,0x00,0x72,0x00,0x01,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5e,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05, 0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x54,0x00,0x01,0x00,0x02,0x0b,0xc8,0x0b,0xdb,0x00,0x01,0x00,0x01,0x0b,0x55,0x00,0x01,0x00,0x01,0x0b,0x56,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x00,0x01,0x00,0x01,0x0b,0x5f,0x00,0x03,0x00,0x00, 0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x4c,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x02,0x00,0x09,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcf,0x00,0x06,0x0b,0xd6,0x0b,0xd7,0x00,0x0a,0x0b,0xd9,0x0b,0xda,0x00,0x0c,0x0b,0xdd,0x0b,0xdd,0x00,0x0e,0x0b,0xe1,0x0b,0xe1, 0x00,0x0f,0x12,0x5c,0x12,0x5d,0x00,0x10,0x00,0x02,0x00,0x09,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcf,0x00,0x06,0x0b,0xd6,0x0b,0xd7,0x00,0x0a,0x0b,0xd9,0x0b,0xda,0x00,0x0c,0x0b,0xdd,0x0b,0xdd,0x00,0x0e,0x0b,0xe1,0x0b,0xe1,0x00,0x0f,0x12,0x5c,0x12,0x5d, 0x00,0x10,0x00,0x03,0x00,0x01,0x00,0x5c,0x00,0x01,0x00,0x8a,0x00,0x01,0x00,0x90,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x03,0x00,0x01,0x00,0x48,0x00,0x01,0x00,0x76,0x00,0x02,0x00,0x48,0x00,0x7c,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x03,0x00,0x01,0x00,0x32,0x00,0x01,0x00,0x60,0x00,0x03,0x00,0x32,0x00,0x32,0x00,0x66,0x00,0x01, 0x00,0x00,0x00,0x60,0x00,0x03,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x48,0x00,0x04,0x00,0x1a,0x00,0x1a,0x00,0x1a,0x00,0x4e,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x02,0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61,0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd,0x00,0x11, 0x0b,0xe1,0x0b,0xe1,0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x01,0x00,0x01,0x0b,0x57,0x00,0x01,0x00,0x01,0x0b,0x75,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x14, 0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x62,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x1e,0x00,0x01,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x63,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x01, 0x0a,0x14,0x00,0x03,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x1c,0x00,0x02,0x00,0x1c,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x64,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x02, 0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x03,0x00,0x03,0x00,0x16,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x66,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x18,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x01,0x00,0x01,0x14,0x6b,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01, 0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6a,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01, 0x00,0x14,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x6b,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x14,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x6c,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x02,0x00,0x01,0x14,0x9e, 0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x14,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x1e,0x00,0x01,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6e,0x00,0x02,0x00,0x01, 0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x1e,0x00,0x01,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6f,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x1e,0x00,0x01,0x00,0x14,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x70,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x03,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x1c,0x00,0x02,0x00,0x1c,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x71,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x16, 0x00,0x01,0x00,0x1c,0x00,0x02,0x00,0x1c,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x72,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x1c,0x00,0x02,0x00,0x1c,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x73,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x02,0x00,0x01, 0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x00,0x00,0x74,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x03,0x00,0x02,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x00, 0x00,0x75,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x02,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x03,0x00,0x03,0x00,0x16,0x00,0x16, 0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x77,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x03,0x00,0x03,0x00,0x16,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01, 0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x03,0x00,0x16,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x79,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x03,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x1e,0x00,0x03,0x00,0x1e,0x00,0x1e,0x00,0x1e,0x00,0x01,0x00,0x00, 0x00,0x7a,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x1e,0x00,0x03,0x00,0x1e,0x00,0x1e,0x00,0x1e,0x00,0x01,0x00,0x00,0x00,0x7b,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x18, 0x00,0x01,0x00,0x1e,0x00,0x03,0x00,0x1e,0x00,0x1e,0x00,0x1e,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x02,0x00,0x18,0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x7d,0x00,0x02,0x00,0x01,0x14,0x9e, 0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x03,0x00,0x02,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x02,0x00,0x18,0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x7e,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x02,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x02, 0x00,0x18,0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x7f,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x03,0x00,0x03,0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x80,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01, 0x0a,0x44,0x00,0x03,0x00,0x03,0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x81,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x03,0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x18,0x00,0x01,0x00,0x00, 0x00,0x82,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x03,0x00,0x04,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x83,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x44,0x00,0x03,0x00,0x04,0x00,0x18, 0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x84,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x47,0x00,0x03,0x00,0x04,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x22,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x85,0x00,0x02,0x00,0x01,0x14,0x9e, 0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x13,0x45,0x00,0x01,0x00,0x0a,0x00,0x03,0x00,0x64,0xff,0xce,0x00,0x01,0x00,0x01,0x09,0x73,0x00,0x01,0x00,0x0a,0x00,0x03,0x01,0x2c,0xff,0xce,0x00,0x01,0x00,0x01,0x09,0x73,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0xc8,0x00,0x01,0x00,0x01,0x09,0x73,0x00,0x01,0x00,0x0a,0x00,0x05,0xfa,0x5d, 0xfd,0xa8,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0xd4,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfb,0x89,0xfd,0xa8,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0xd4,0x00,0x02,0x00,0x01,0x14,0x88, 0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0xd4,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfc,0xb5,0xfd,0xa8,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x0c,0x00,0x07,0xfc,0xc8,0xfc,0xc7,0xfd,0xa8,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00, 0x00,0x01,0x00,0x0a,0x00,0x05,0xf8,0xe6,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf6,0xcd,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf6,0x8e,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfa,0x8d,0xfc,0xb2,0x00,0x02,0x00,0x01, 0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf8,0x74,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf8,0x35,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfb,0x0b,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac, 0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfb,0x0b,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfb,0x0b,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfe,0x59,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01, 0x00,0x0a,0x00,0x05,0xfe,0x59,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfe,0x59,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xff,0x82,0x03,0x4e,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05, 0xfd,0x69,0x03,0x4e,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfd,0x2a,0x03,0x4e,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01, 0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08, 0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0xfe,0x59,0x00,0x02,0x00,0x01,0x14,0x9e, 0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xfa,0x8d,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf8,0x74,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x05,0xf8,0x35,0xfc,0xb2,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00, 0x00,0x01,0x02,0x1c,0x02,0x32,0x00,0x03,0x00,0x0c,0x00,0x3a,0x00,0x0b,0x00,0x00,0x4f,0xd6,0x00,0x02,0x4f,0xd6,0x00,0x02,0x4f,0xd6,0x00,0x02,0x4f,0xd6,0x00,0x00,0x4f,0xd6,0x00,0x01,0x4f,0xd6,0x00,0x01,0x4f,0xd6,0x00,0x01,0x4f,0xd6,0x00,0x01,0x4f,0xd6,0x00,0x02,0x4f,0xd6,0x00,0x01,0x4f,0xd6,0x00,0x50,0x4f,0xae,0x4f,0xb4, 0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x4f,0xcc,0x4f,0xd2,0x4f,0xd8,0x4f,0xde,0x4f,0xe4,0x4f,0xea,0x4f,0xf0,0x4f,0xf6,0x4f,0xfc,0x50,0x02,0x50,0x08,0x50,0x0e,0x50,0x14,0x4f,0xde,0x50,0x1a,0x50,0x20,0x50,0x14,0x50,0x26,0x50,0x2c,0x50,0x32,0x50,0x38,0x50,0x3e,0x50,0x44,0x50,0x4a,0x50,0x50,0x4f,0xde,0x50,0x1a,0x50,0x20,0x50,0x56, 0x50,0x5c,0x50,0x62,0x50,0x68,0x50,0x6e,0x50,0x74,0x50,0x7a,0x50,0x80,0x50,0x86,0x50,0x8c,0x50,0x92,0x50,0x98,0x50,0x8c,0x50,0x92,0x50,0x98,0x50,0x9e,0x50,0xa4,0x50,0xaa,0x50,0xb0,0x50,0xb6,0x50,0xbc,0x50,0xc2,0x50,0xc8,0x50,0xce,0x50,0xd4,0x50,0xda,0x50,0xe0,0x50,0xe6,0x50,0xec,0x50,0xf2,0x50,0xf8,0x50,0xfe,0x51,0x04, 0x51,0x0a,0x51,0x10,0x51,0x16,0x51,0x1c,0x51,0x22,0x51,0x28,0x51,0x2e,0x51,0x34,0x51,0x3a,0x51,0x40,0x51,0x46,0x51,0x4c,0x51,0x52,0x51,0x58,0x51,0x5e,0x51,0x64,0x51,0x6a,0x51,0x70,0x51,0x76,0x51,0x7c,0x51,0x82,0x51,0x76,0x51,0x7c,0x51,0x82,0x51,0x76,0x51,0x7c,0x51,0x82,0x50,0x56,0x50,0x5c,0x50,0x62,0x50,0x56,0x50,0x5c, 0x50,0x62,0x50,0x7a,0x50,0x80,0x50,0x86,0x50,0x7a,0x50,0x80,0x50,0x86,0x51,0x88,0x51,0x8e,0x51,0x94,0x51,0x9a,0x51,0xa0,0x51,0xa6,0x4f,0xc0,0x4f,0xc6,0x4f,0xcc,0x4f,0xf6,0x4f,0xfc,0x50,0x02,0x50,0x08,0x50,0x0e,0x50,0x14,0x51,0xac,0x51,0xb2,0x51,0xb8,0x50,0x7a,0x50,0x80,0x50,0x86,0x50,0x8c,0x50,0x92,0x50,0x98,0x51,0x40, 0x51,0x46,0x51,0x4c,0x51,0x64,0x51,0x6a,0x51,0x70,0x51,0x52,0x51,0x58,0x51,0x5e,0x51,0x52,0x51,0x58,0x51,0x5e,0x51,0x52,0x51,0x58,0x51,0x5e,0x51,0x52,0x51,0x58,0x51,0x5e,0x4f,0xc0,0x4f,0xc6,0x4f,0xcc,0x4f,0xd2,0x4f,0xd8,0x4f,0xde,0x4f,0xe4,0x4f,0xea,0x4f,0xf0,0x4f,0xf6,0x4f,0xfc,0x50,0x02,0x50,0x08,0x50,0x0e,0x50,0x14, 0x51,0xbe,0x51,0xc4,0x51,0xca,0x51,0xd0,0x51,0xd6,0x51,0xdc,0x50,0x44,0x50,0x4a,0x50,0x50,0x51,0xbe,0x51,0xc4,0x51,0xca,0x50,0x56,0x50,0x5c,0x50,0x62,0x50,0x68,0x50,0x6e,0x50,0x74,0x50,0x7a,0x50,0x80,0x50,0x86,0x50,0x8c,0x50,0x92,0x50,0x98,0x50,0xb0,0x50,0xb6,0x50,0xbc,0x50,0xc2,0x50,0xc8,0x50,0xce,0x50,0xe6,0x50,0xec, 0x50,0xf2,0x50,0xf8,0x50,0xfe,0x51,0x04,0x51,0x1c,0x51,0x22,0x51,0x28,0x51,0x2e,0x51,0x34,0x51,0x3a,0x51,0x40,0x51,0x46,0x51,0x4c,0x51,0x52,0x51,0x58,0x51,0x5e,0x51,0x64,0x51,0x6a,0x51,0x70,0x4f,0xde,0x50,0x1a,0x50,0x20,0x4f,0xd2,0x4f,0xd8,0x4f,0xde,0x50,0x68,0x50,0x6e,0x50,0x74,0x50,0xf8,0x50,0xfe,0x51,0x04,0x51,0x9a, 0x51,0xa0,0x51,0xa6,0x4f,0xe4,0x4f,0xea,0x4f,0xf0,0x4f,0xf6,0x4f,0xfc,0x50,0x02,0x50,0x08,0x50,0x0e,0x50,0x14,0x51,0x64,0x51,0x6a,0x51,0x70,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85, 0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb8,0x00,0xc0,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x4d,0x7c,0x00,0x00,0x4d,0x7c,0x00,0x50,0x4f,0xac,0x4f,0xb2,0x4f,0xb8,0x4f,0xbe,0x4f,0xc4,0x4f,0xca,0x4f,0xd0, 0x4e,0xc2,0x4f,0xd6,0x4f,0xdc,0x4f,0xd0,0x4e,0x20,0x4f,0xe2,0x4f,0xe8,0x4f,0xee,0x4f,0xee,0x4e,0x68,0x4f,0xf4,0x4f,0xfa,0x50,0x00,0x4e,0xb0,0x50,0x06,0x4e,0xd4,0x50,0x0c,0x50,0x12,0x50,0x18,0x50,0x1e,0x50,0x24,0x50,0x2a,0x50,0x2a,0x50,0x2a,0x4e,0x20,0x4e,0x20,0x4f,0xe8,0x4f,0xe8,0x50,0x30,0x50,0x36,0x4f,0xb2,0x4f,0xc4, 0x4f,0xca,0x4f,0xe2,0x4f,0xe8,0x4f,0xee,0x50,0x18,0x50,0x24,0x50,0x1e,0x50,0x1e,0x50,0x1e,0x50,0x1e,0x4f,0xb2,0x4f,0xb8,0x4f,0xbe,0x4f,0xc4,0x4f,0xca,0x50,0x3c,0x50,0x42,0x4f,0xdc,0x50,0x3c,0x4e,0x20,0x4f,0xe2,0x4f,0xe8,0x4f,0xee,0x4f,0xf4,0x50,0x48,0x4e,0xb0,0x50,0x06,0x50,0x0c,0x50,0x12,0x50,0x18,0x50,0x1e,0x50,0x24, 0x4f,0xd0,0x4f,0xb8,0x4f,0xe2,0x50,0x06,0x50,0x36,0x4f,0xbe,0x4f,0xc4,0x4f,0xca,0x50,0x24,0x00,0x01,0x00,0x02,0x0b,0x53,0x0b,0x57,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62, 0x00,0x4c,0x00,0x01,0x00,0xb4,0x00,0xba,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4c,0x94,0x00,0x50,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a, 0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a, 0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x4f,0x6a,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06, 0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb4,0x00,0xba,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4b,0xb2,0x00,0x50,0x4e,0x8e,0x4e,0x94,0x4e,0x9a,0x4e,0xa0, 0x4e,0xa6,0x4e,0xac,0x4e,0xb2,0x4e,0xb8,0x4e,0xbe,0x4e,0xc4,0x4e,0xb2,0x4e,0xca,0x4e,0xd0,0x4e,0xd6,0x4e,0xbe,0x4e,0xdc,0x4e,0xb2,0x4e,0xe2,0x4e,0xe8,0x4e,0xee,0x4e,0xf4,0x4e,0xe8,0x4e,0xfa,0x4f,0x00,0x4e,0xdc,0x4e,0xca,0x4f,0x06,0x4f,0x0c,0x4e,0xb2,0x4e,0xb2,0x4e,0xb2,0x4e,0xca,0x4e,0xca,0x4e,0xd6,0x4e,0xd6,0x4e,0xb2, 0x4e,0xee,0x4e,0x94,0x4e,0xa6,0x4e,0xac,0x4e,0xd0,0x4e,0xd6,0x4e,0xbe,0x4e,0xca,0x4f,0x0c,0x4f,0x06,0x4f,0x12,0x4f,0x06,0x4f,0x12,0x4e,0x94,0x4e,0x9a,0x4e,0xa0,0x4e,0xa6,0x4e,0xac,0x4f,0x18,0x4e,0xf4,0x4e,0xc4,0x4f,0x18,0x4e,0xca,0x4e,0xd0,0x4e,0xd6,0x4e,0xdc,0x4e,0xe2,0x4e,0xe8,0x4e,0xf4,0x4e,0xe8,0x4f,0x00,0x4e,0xdc, 0x4e,0xca,0x4f,0x06,0x4f,0x0c,0x4f,0x1e,0x4f,0x24,0x4f,0x2a,0x4f,0x30,0x4e,0xd6,0x4f,0x36,0x4f,0x24,0x4f,0x3c,0x4f,0x42,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31, 0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x2c,0x00,0x32,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4a,0xd0,0x00,0x0c,0x4e,0x66,0x4e,0x6c,0x4e,0x72,0x4e,0x6c,0x4e,0x6c,0x4e,0x78,0x4e,0x66,0x4e,0x7e,0x4e,0x78,0x4e,0x84,0x4e,0x78,0x4e,0x54,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x09,0x0b,0x6a,0x0b,0x6a, 0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x01,0x0b,0x71,0x0b,0x71,0x00,0x03,0x0b,0x77,0x0b,0x78,0x00,0x04,0x0b,0x9f,0x0b,0x9f,0x00,0x06,0x0b,0xa2,0x0b,0xa3,0x00,0x07,0x0b,0xa5,0x0b,0xa5,0x00,0x09,0x0b,0xaa,0x0b,0xaa,0x00,0x0a,0x12,0x5f,0x12,0x5f,0x00,0x0b,0x00,0x01,0x01,0x5c,0x01,0x72,0x00,0x02,0x00,0x0c,0x00,0x1a,0x00,0x03, 0x00,0x00,0x4a,0x64,0x00,0x00,0x4a,0x64,0x00,0x01,0x4a,0x64,0x00,0x50,0x4e,0x16,0x4e,0x1c,0x4e,0x22,0x4e,0x28,0x4e,0x2e,0x4e,0x34,0x4e,0x3a,0x4e,0x40,0x4e,0x46,0x4e,0x4c,0x4e,0x52,0x4e,0x58,0x4e,0x5e,0x4e,0x64,0x4e,0x6a,0x4e,0x70,0x4e,0x76,0x4e,0x7c,0x4e,0x82,0x4e,0x88,0x4e,0x5e,0x4e,0x64,0x4e,0x8e,0x4e,0x94,0x4e,0x9a, 0x4e,0xa0,0x4e,0xa6,0x4e,0xac,0x4e,0xb2,0x4e,0x7c,0x4e,0x16,0x4e,0x58,0x4e,0x5e,0x4e,0x64,0x4e,0xb8,0x4e,0xbe,0x4e,0xc4,0x4e,0xca,0x4e,0xd0,0x4e,0xd6,0x4e,0xdc,0x4e,0xe2,0x4e,0xc4,0x4e,0xca,0x4e,0xe8,0x4e,0xee,0x4e,0xf4,0x4e,0xfa,0x4f,0x00,0x4e,0x58,0x4e,0x8e,0x4e,0x94,0x4f,0x06,0x4f,0x0c,0x4f,0x12,0x4f,0x18,0x4e,0x5e, 0x4e,0x7c,0x4e,0x5e,0x4e,0x7c,0x4e,0x5e,0x4e,0x7c,0x4e,0x8e,0x4e,0x94,0x4e,0x8e,0x4e,0x94,0x4e,0xa6,0x4e,0xac,0x4e,0xa6,0x4e,0xac,0x4e,0x5e,0x4e,0x7c,0x4e,0xd0,0x4e,0xd6,0x4e,0x22,0x4e,0x28,0x4e,0x46,0x4e,0x4c,0x4e,0x52,0x4e,0x58,0x4e,0x9a,0x4e,0xa0,0x4e,0xa6,0x4e,0xac,0x4e,0xb2,0x4e,0x7c,0x4e,0x8e,0x4e,0x94,0x4f,0x12, 0x4f,0x18,0x4f,0x06,0x4f,0x0c,0x4f,0x06,0x4f,0x0c,0x4f,0x06,0x4f,0x0c,0x4f,0x06,0x4f,0x0c,0x4f,0x1e,0x4f,0x24,0x4e,0x2e,0x4f,0x2a,0x4e,0x3a,0x4e,0x40,0x4e,0x46,0x4e,0x4c,0x4e,0x52,0x4e,0x58,0x4f,0x30,0x4f,0x36,0x4f,0x3c,0x4f,0x42,0x4e,0x82,0x4e,0x88,0x4f,0x30,0x4f,0x36,0x4e,0x8e,0x4e,0x94,0x4e,0x9a,0x4e,0xa0,0x4e,0xa6, 0x4e,0xac,0x4e,0x16,0x4e,0x58,0x4e,0xb8,0x4e,0xbe,0x4e,0xc4,0x4e,0xca,0x4e,0xdc,0x4e,0xe2,0x4e,0xc4,0x4e,0xca,0x4e,0xf4,0x4e,0xfa,0x4f,0x00,0x4e,0x58,0x4e,0x8e,0x4e,0x94,0x4f,0x06,0x4f,0x0c,0x4f,0x12,0x4f,0x18,0x4e,0x5e,0x4e,0x64,0x4e,0x2e,0x4e,0x34,0x4f,0x48,0x4e,0xa0,0x4e,0xc4,0x4e,0xca,0x4e,0xa6,0x4e,0xac,0x4e,0x3a, 0x4e,0x40,0x4e,0x46,0x4e,0x4c,0x4e,0x52,0x4e,0x58,0x4f,0x12,0x4f,0x18,0x00,0x02,0x00,0x03,0x0b,0xc0,0x0b,0xc0,0x00,0x00,0x0b,0xd7,0x0b,0xd7,0x00,0x01,0x0b,0xdc,0x0b,0xdc,0x00,0x02,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d, 0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb8,0x00,0xc0,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x48,0xca,0x00,0x00,0x48,0xca,0x00,0x50,0x4a,0x76,0x4d,0xb8,0x4d,0xbe,0x4d,0xc4,0x4d,0xbe,0x4d,0xca,0x4b,0xc6,0x4d,0xd0,0x4b,0x8a,0x4d,0xd6,0x4b,0xc6,0x4d,0xdc,0x4d,0xe2,0x4d,0xe8, 0x4d,0xee,0x4d,0xf4,0x4b,0xc6,0x4d,0xfa,0x4e,0x00,0x4b,0x1e,0x4e,0x06,0x4e,0x0c,0x4e,0x12,0x4e,0x18,0x4e,0x1e,0x4d,0xdc,0x4e,0x24,0x4e,0x2a,0x49,0x68,0x49,0x68,0x49,0x68,0x4d,0xdc,0x4d,0xdc,0x4d,0xe8,0x4d,0xe8,0x4e,0x30,0x4b,0x1e,0x4d,0xb8,0x4d,0xbe,0x4d,0xca,0x4d,0xe2,0x4d,0xe8,0x4d,0xee,0x4d,0xdc,0x4e,0x2a,0x4e,0x24, 0x4e,0x24,0x4e,0x24,0x4e,0x24,0x4d,0xb8,0x4d,0xbe,0x4d,0xc4,0x4d,0xbe,0x4d,0xca,0x4c,0x2c,0x4e,0x36,0x4d,0xd6,0x4c,0x2c,0x4d,0xdc,0x4d,0xe2,0x4d,0xe8,0x4d,0xf4,0x4d,0xfa,0x4e,0x00,0x4e,0x06,0x4e,0x0c,0x4e,0x18,0x4e,0x1e,0x4d,0xdc,0x4e,0x24,0x4e,0x2a,0x4e,0x3c,0x4e,0x42,0x4e,0x48,0x4e,0x4e,0x4e,0x54,0x4e,0x5a,0x4e,0x42, 0x4e,0x60,0x4e,0x66,0x00,0x01,0x00,0x02,0x0b,0xc0,0x0b,0xd7,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x30,0x00,0x38,0x00,0x01,0x00,0x0c,0x00,0x16, 0x00,0x02,0x00,0x00,0x47,0xe2,0x00,0x00,0x47,0xe2,0x00,0x0c,0x4d,0x84,0x4d,0x8a,0x49,0xbe,0x4d,0x8a,0x4d,0x8a,0x4d,0x90,0x4d,0x84,0x48,0xfe,0x4d,0x90,0x4d,0x96,0x4d,0x90,0x4d,0x72,0x00,0x01,0x00,0x02,0x0b,0xc0,0x0b,0xd7,0x00,0x02,0x00,0x09,0x0b,0x6a,0x0b,0x6a,0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x01,0x0b,0x71,0x0b,0x71, 0x00,0x03,0x0b,0x77,0x0b,0x78,0x00,0x04,0x0b,0x9f,0x0b,0x9f,0x00,0x06,0x0b,0xa2,0x0b,0xa3,0x00,0x07,0x0b,0xa5,0x0b,0xa5,0x00,0x09,0x0b,0xaa,0x0b,0xaa,0x00,0x0a,0x12,0x5f,0x12,0x5f,0x00,0x0b,0x00,0x01,0x00,0xb4,0x00,0xba,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x47,0x70,0x00,0x50,0x49,0x20,0x4c,0x62,0x4c,0x68, 0x4c,0x6e,0x4c,0x68,0x4c,0x74,0x4a,0x70,0x4c,0x7a,0x4a,0x34,0x4c,0x80,0x4a,0x70,0x4c,0x86,0x4c,0x8c,0x4d,0x2e,0x4c,0x98,0x4c,0x9e,0x4a,0x70,0x4c,0xa4,0x4c,0xaa,0x49,0xc8,0x4c,0xb0,0x4c,0xb6,0x4c,0xbc,0x4c,0xc2,0x4c,0xc8,0x4c,0x86,0x4c,0xce,0x4c,0xd4,0x48,0x12,0x48,0x12,0x48,0x12,0x4c,0x86,0x4c,0x86,0x4d,0x2e,0x4d,0x2e, 0x4c,0xda,0x49,0xc8,0x4c,0x62,0x4c,0x68,0x4c,0x74,0x4c,0x8c,0x4d,0x2e,0x4c,0x98,0x4c,0x86,0x4c,0xd4,0x4c,0xce,0x4c,0xce,0x4c,0xce,0x4c,0xce,0x4c,0x62,0x4c,0x68,0x4c,0x6e,0x4c,0x68,0x4c,0x74,0x4a,0xd6,0x4c,0xe0,0x4c,0x80,0x4a,0xd6,0x4c,0x86,0x4c,0x8c,0x4d,0x2e,0x4c,0x9e,0x4c,0xa4,0x4c,0xaa,0x4c,0xb0,0x4c,0xb6,0x4c,0xc2, 0x4c,0xc8,0x4c,0x86,0x4c,0xce,0x4c,0xd4,0x4d,0x34,0x4c,0xec,0x4c,0xf2,0x4c,0xf8,0x4c,0xfe,0x4d,0x04,0x4c,0xec,0x4d,0x0a,0x4d,0x10,0x00,0x01,0x00,0x01,0x0b,0xce,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7, 0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x2c,0x00,0x32,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x46,0x8e,0x00,0x0c,0x4c,0x58,0x4c,0x5e,0x4c,0x64,0x4c,0x5e,0x4c,0x5e,0x4c,0x6a,0x4c,0x58,0x4c,0x70,0x4c,0x6a,0x4c,0x76,0x4c,0x6a,0x4c,0x22,0x00,0x01,0x00,0x01,0x0b,0xce,0x00,0x02,0x00,0x09,0x0b,0x6a, 0x0b,0x6a,0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x01,0x0b,0x71,0x0b,0x71,0x00,0x03,0x0b,0x77,0x0b,0x78,0x00,0x04,0x0b,0x9f,0x0b,0x9f,0x00,0x06,0x0b,0xa2,0x0b,0xa3,0x00,0x07,0x0b,0xa5,0x0b,0xa5,0x00,0x09,0x0b,0xaa,0x0b,0xaa,0x00,0x0a,0x12,0x5f,0x12,0x5f,0x00,0x0b,0x00,0x01,0x00,0x64,0x00,0xa4,0x00,0x01,0x00,0x0c,0x00,0x4a, 0x00,0x0f,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x00,0x46,0x22,0x00,0x0c, 0x46,0x50,0x4b,0xd8,0x47,0xfa,0x4b,0xd8,0x4b,0xd8,0x4b,0xde,0x46,0x50,0x4b,0xe4,0x4b,0xde,0x4b,0xea,0x4b,0xde,0x4b,0x7e,0x00,0x02,0x00,0x0a,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcc,0x00,0x06,0x0b,0xcf,0x0b,0xcf,0x00,0x07,0x0b,0xd6,0x0b,0xd6,0x00,0x08, 0x0b,0xd9,0x0b,0xda,0x00,0x09,0x0b,0xdd,0x0b,0xdd,0x00,0x0b,0x0b,0xe1,0x0b,0xe1,0x00,0x0c,0x12,0x5c,0x12,0x5d,0x00,0x0d,0x00,0x02,0x00,0x09,0x0b,0x6a,0x0b,0x6a,0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x01,0x0b,0x71,0x0b,0x71,0x00,0x03,0x0b,0x77,0x0b,0x78,0x00,0x04,0x0b,0x9f,0x0b,0x9f,0x00,0x06,0x0b,0xa2,0x0b,0xa3,0x00,0x07, 0x0b,0xa5,0x0b,0xa5,0x00,0x09,0x0b,0xaa,0x0b,0xaa,0x00,0x0a,0x12,0x5f,0x12,0x5f,0x00,0x0b,0x00,0x01,0x00,0xb8,0x00,0xc0,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x45,0x44,0x00,0x00,0x45,0x44,0x00,0x50,0x4b,0x46,0x4b,0x4c,0x4b,0x52,0x4b,0x58,0x4b,0x5e,0x4b,0x64,0x4a,0x3e,0x4b,0x6a,0x4b,0x70,0x4b,0x76,0x4a,0x3e, 0x4a,0x8c,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x88,0x4b,0x8e,0x4b,0x94,0x47,0xaa,0x45,0x88,0x4b,0x9a,0x4b,0xa0,0x4b,0xa6,0x4b,0xac,0x45,0x9a,0x4b,0xb2,0x4b,0xb8,0x47,0xf8,0x46,0x24,0x46,0x24,0x46,0x24,0x4a,0x8c,0x4a,0x8c,0x4b,0x82,0x4b,0x82,0x48,0x04,0x46,0x8a,0x4b,0x4c,0x4b,0x5e,0x4b,0x64,0x4b,0xbe,0x4b,0x82,0x4b,0x88, 0x4b,0xb2,0x47,0xf8,0x4b,0xb8,0x4b,0xb8,0x4b,0xb8,0x4b,0xb8,0x4b,0x4c,0x4b,0x52,0x4b,0x58,0x4b,0x5e,0x4b,0x64,0x4b,0xc4,0x4b,0x0a,0x4b,0x76,0x4b,0xc4,0x4a,0x8c,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x94,0x47,0xaa,0x4b,0x9a,0x4b,0xa0,0x4b,0xac,0x45,0x9a,0x4b,0xb2,0x4b,0xb8,0x47,0xf8,0x4a,0x3e,0x4b,0x52,0x4b,0x7c,0x4b,0xa0, 0x46,0x8a,0x4b,0x58,0x4b,0x5e,0x4b,0x64,0x47,0xf8,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb8,0x00,0xc0, 0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x44,0x5c,0x00,0x00,0x44,0x5c,0x00,0x50,0x4a,0xe2,0x4a,0xe8,0x4a,0xee,0x46,0xd4,0x44,0xdc,0x4a,0xf4,0x4a,0xfa,0x49,0x92,0x4b,0x00,0x4b,0x06,0x4a,0xfa,0x4b,0x0c,0x46,0x14,0x46,0x02,0x4b,0x12,0x4b,0x12,0x4a,0xa6,0x4b,0x18,0x4b,0x1e,0x4b,0x24,0x47,0x22,0x4b,0x2a,0x4a,0xbe, 0x4b,0x30,0x4b,0x36,0x4b,0x3c,0x4b,0x42,0x4b,0x48,0x4b,0x4e,0x4b,0x4e,0x4b,0x4e,0x4b,0x0c,0x4b,0x0c,0x46,0x02,0x46,0x02,0x4b,0x54,0x4b,0x5a,0x4a,0xe8,0x44,0xdc,0x4a,0xf4,0x4b,0x60,0x46,0x02,0x4b,0x12,0x4b,0x3c,0x4b,0x48,0x4b,0x42,0x4b,0x42,0x4b,0x42,0x4b,0x42,0x4a,0xe8,0x4a,0xee,0x46,0xd4,0x44,0xdc,0x4a,0xf4,0x4b,0x66, 0x4b,0x6c,0x4b,0x06,0x4b,0x66,0x4b,0x0c,0x46,0x14,0x46,0x02,0x4b,0x12,0x4b,0x18,0x4b,0x1e,0x47,0x22,0x4b,0x2a,0x4b,0x30,0x4b,0x36,0x4b,0x3c,0x4b,0x42,0x4b,0x48,0x4a,0xfa,0x4a,0xee,0x46,0x14,0x4b,0x2a,0x4b,0x5a,0x46,0xd4,0x44,0xdc,0x4a,0xf4,0x4b,0x48,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x02,0x00,0x06,0x0a,0x43, 0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb8,0x00,0xc0,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x43,0x74,0x00,0x00,0x43,0x74,0x00,0x50,0x4a,0x8a,0x4a,0x90,0x4a,0x96, 0x49,0xb8,0x4a,0x9c,0x46,0x1c,0x4a,0xa2,0x4a,0xa8,0x4a,0xae,0x4a,0xb4,0x4a,0xa2,0x4a,0xba,0x4a,0xc0,0x46,0x04,0x46,0x16,0x46,0x16,0x4a,0xc6,0x43,0x82,0x4a,0xcc,0x4a,0xd2,0x45,0xb6,0x4a,0xd8,0x4a,0xde,0x45,0xfe,0x4a,0xe4,0x4a,0xea,0x4a,0xf0,0x4a,0xf6,0x4a,0xfc,0x4a,0xfc,0x4a,0xfc,0x4a,0xba,0x4a,0xba,0x46,0x04,0x46,0x04, 0x4b,0x02,0x4b,0x08,0x4a,0x90,0x4a,0x9c,0x46,0x1c,0x4b,0x0e,0x46,0x04,0x46,0x16,0x4a,0xea,0x4a,0xf6,0x4a,0xf0,0x4a,0xf0,0x4a,0xf0,0x4a,0xf0,0x4a,0x90,0x4a,0x96,0x49,0xb8,0x4a,0x9c,0x46,0x1c,0x4b,0x14,0x4a,0x72,0x4a,0xb4,0x4b,0x14,0x4a,0xba,0x4a,0xc0,0x46,0x04,0x46,0x16,0x43,0x82,0x4a,0xcc,0x45,0xb6,0x4a,0xd8,0x45,0xfe, 0x4a,0xe4,0x4a,0xea,0x4a,0xf0,0x4a,0xf6,0x4a,0xa2,0x4a,0x96,0x4a,0xc0,0x4a,0xd8,0x4b,0x08,0x49,0xb8,0x4a,0x9c,0x46,0x1c,0x4a,0xf6,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d, 0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xe0,0x01,0x0e,0x00,0x01,0x00,0x0c,0x00,0x3e,0x00,0x0c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c, 0x00,0x00,0x42,0x8c,0x00,0x00,0x42,0x8c,0x00,0x50,0x48,0x90,0x43,0xe6,0x4a,0x0a,0x47,0xee,0x4a,0x10,0x4a,0x16,0x4a,0x1c,0x4a,0x22,0x4a,0x28,0x4a,0x2e,0x4a,0x1c,0x43,0x80,0x4a,0x34,0x47,0x64,0x48,0xf0,0x48,0xf0,0x4a,0x3a,0x4a,0x40,0x4a,0x46,0x4a,0x4c,0x4a,0x52,0x4a,0x58,0x4a,0x5e,0x4a,0x64,0x4a,0x6a,0x4a,0x70,0x4a,0x76, 0x4a,0x7c,0x4a,0x82,0x4a,0x82,0x4a,0x82,0x43,0x80,0x43,0x80,0x47,0x64,0x47,0x64,0x4a,0x88,0x4a,0x8e,0x43,0xe6,0x4a,0x10,0x4a,0x16,0x4a,0x94,0x47,0x64,0x48,0xf0,0x4a,0x70,0x4a,0x7c,0x4a,0x76,0x4a,0x76,0x4a,0x76,0x4a,0x76,0x43,0xe6,0x4a,0x0a,0x47,0xee,0x4a,0x10,0x4a,0x16,0x47,0x82,0x4a,0x9a,0x4a,0x2e,0x47,0x82,0x43,0x80, 0x4a,0x34,0x47,0x64,0x48,0xf0,0x4a,0x40,0x4a,0x46,0x4a,0x52,0x4a,0x58,0x4a,0x64,0x4a,0x6a,0x4a,0x70,0x4a,0x76,0x4a,0x7c,0x4a,0x1c,0x4a,0x0a,0x4a,0x34,0x4a,0x58,0x4a,0x8e,0x47,0xee,0x4a,0x10,0x4a,0x16,0x4a,0x7c,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02, 0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c, 0x00,0x01,0x00,0x30,0x00,0x38,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x41,0x56,0x00,0x00,0x41,0x56,0x00,0x0c,0x49,0x92,0x49,0x98,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x49,0x9e,0x00,0x01,0x00,0x02,0x0b,0xc8,0x0b,0xdb,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f, 0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x30,0x00,0x38,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x40,0xf0,0x00,0x00,0x40,0xf0,0x00,0x0c,0x46,0x2c, 0x46,0x2c,0x49,0x3e,0x49,0x3e,0x49,0x3e,0x49,0x3e,0x49,0x3e,0x49,0x3e,0x49,0x3e,0x46,0xf2,0x49,0x3e,0x49,0x3e,0x00,0x01,0x00,0x02,0x0b,0xc8,0x0b,0xdb,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04, 0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x30,0x00,0x38,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x40,0x8a,0x00,0x00,0x40,0x8a,0x00,0x0c,0x46,0x8c,0x46,0x8c,0x47,0x1c,0x47,0x1c,0x47,0x1c,0x47,0x1c,0x47,0x1c,0x47,0x1c,0x47,0x1c,0x48,0xde,0x47,0x1c,0x47,0x1c,0x00,0x01,0x00,0x02, 0x0b,0xc8,0x0b,0xdb,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0xf8,0x01,0x32,0x00,0x01,0x00,0x0c,0x00,0x56,0x00,0x12, 0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24, 0x00,0x00,0x40,0x24,0x00,0x00,0x40,0x24,0x00,0x50,0x48,0x3e,0x48,0x44,0x40,0x28,0x48,0x4a,0x40,0x28,0x48,0x50,0x40,0x88,0x48,0x56,0x48,0x5c,0x48,0x62,0x40,0x88,0x45,0x08,0x41,0x2a,0x42,0x32,0x48,0x68,0x48,0x6e,0x40,0x88,0x42,0x38,0x48,0x74,0x48,0x7a,0x48,0x80,0x46,0x28,0x40,0x76,0x48,0x86,0x48,0x8c,0x45,0x08,0x47,0x00, 0x48,0x92,0x48,0x98,0x48,0x98,0x48,0x98,0x45,0x08,0x45,0x08,0x42,0x32,0x42,0x32,0x47,0xd8,0x48,0x7a,0x48,0x44,0x40,0x28,0x48,0x50,0x41,0x2a,0x42,0x32,0x48,0x68,0x45,0x08,0x48,0x92,0x42,0x56,0x46,0xc4,0x42,0x56,0x46,0xc4,0x48,0x44,0x40,0x28,0x48,0x4a,0x40,0x28,0x48,0x50,0x48,0x9e,0x48,0xa4,0x48,0x62,0x48,0x9e,0x45,0x08, 0x41,0x2a,0x42,0x32,0x48,0x6e,0x42,0x38,0x48,0x74,0x48,0x80,0x46,0x28,0x48,0x86,0x48,0x8c,0x45,0x08,0x47,0x00,0x48,0x92,0x48,0xaa,0x48,0xb0,0x48,0xb6,0x48,0xbc,0x46,0x52,0x48,0xc2,0x48,0xc8,0x48,0xce,0x48,0xd4,0x00,0x02,0x00,0x09,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05, 0x0b,0xcc,0x0b,0xcf,0x00,0x06,0x0b,0xd6,0x0b,0xd7,0x00,0x0a,0x0b,0xd9,0x0b,0xda,0x00,0x0c,0x0b,0xdd,0x0b,0xdd,0x00,0x0e,0x0b,0xe1,0x0b,0xe1,0x00,0x0f,0x12,0x5c,0x12,0x5d,0x00,0x10,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d, 0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb4,0x00,0xba,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x3e,0xca,0x00,0x50,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0, 0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0, 0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0,0x3f,0xc0, 0x00,0x01,0x00,0x01,0x0b,0x57,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x12,0xf4,0x13,0x46,0x00,0x03,0x00,0x0c,0x01,0xbe,0x00,0x6c,0x00,0x00,0x46,0xe8, 0x00,0x02,0x46,0xee,0x00,0x00,0x46,0xf4,0x00,0x00,0x46,0xf4,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x00,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x06,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x0c,0x00,0x00,0x47,0x0c,0x00,0x00,0x47,0x12, 0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x18,0x00,0x00,0x47,0x1e,0x00,0x00,0x47,0x24,0x00,0x01,0x47,0x2a,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x47,0x30,0x00,0x02,0x47,0x36,0x00,0x00,0x47,0x3c,0x00,0x02,0x47,0x42,0x00,0x02,0x47,0x48,0x00,0x02,0x47,0x48,0x00,0x02,0x47,0x48,0x00,0x02,0x47,0x4e, 0x00,0x02,0x3d,0xe8,0x00,0x02,0x47,0x54,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x3d,0xe8,0x00,0x02,0x47,0x54,0x00,0x02,0x3d,0xe8,0x00,0x02,0x47,0x5a,0x00,0x02,0x47,0x60,0x00,0x02,0x47,0x66,0x00,0x02,0x47,0x6c,0x00,0x02,0x3d,0xe8, 0x00,0x02,0x47,0x72,0x00,0x02,0x3d,0xe8,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x78,0x00,0x00,0x47,0x00,0x00,0x00,0x47,0x7e,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x3c,0x00,0x02,0x43,0xb2,0x00,0x00,0x46,0xfa,0x00,0x02,0x47,0x84,0x00,0x02,0x3d,0xe8,0x00,0x02,0x47,0x8a,0x00,0x00,0x46,0xfa,0x00,0x00,0x46,0xfa,0x00,0x00,0x47,0x90, 0x00,0x02,0x47,0x96,0x00,0x02,0x47,0x9c,0x00,0x00,0x47,0xa2,0x00,0x00,0x47,0xa8,0x00,0x00,0x47,0xae,0x00,0x00,0x47,0xae,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0x3c,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0x3c,0x00,0x00,0x47,0x3c,0x00,0x00,0x47,0x3c, 0x00,0x00,0x47,0xb4,0x00,0x00,0x47,0x3c,0x00,0x00,0x47,0x3c,0x00,0x00,0x47,0xba,0x00,0x00,0x47,0xc0,0x00,0x00,0x46,0xfa,0x00,0x02,0x47,0xc6,0x00,0x02,0x47,0xcc,0x00,0x02,0x47,0xcc,0x00,0x02,0x47,0xcc,0x00,0x00,0x47,0xd2,0x00,0x02,0x47,0xd8,0x00,0x02,0x47,0x5a,0x00,0x00,0x47,0xba,0x00,0x00,0x47,0xba,0x00,0x00,0x47,0xba, 0x00,0x02,0x47,0xde,0x00,0x00,0x47,0xe4,0x00,0x00,0x47,0xea,0x00,0x00,0x47,0xea,0x00,0x00,0x47,0xf0,0x00,0x00,0x47,0xf0,0x00,0x00,0x47,0xf6,0x00,0x00,0x47,0xf6,0x00,0x02,0x47,0xfc,0x00,0x00,0x48,0x02,0x00,0x02,0x48,0x08,0x02,0xde,0x46,0x5c,0x46,0x62,0x46,0x68,0x46,0x6e,0x46,0x74,0x46,0x7a,0x46,0x80,0x46,0x86,0x46,0x8c, 0x46,0x92,0x46,0x98,0x46,0x9e,0x46,0xa4,0x46,0xaa,0x46,0xb0,0x46,0xa4,0x46,0xaa,0x46,0xb0,0x46,0xb6,0x46,0xbc,0x46,0xc2,0x46,0xc8,0x46,0xce,0x46,0xd4,0x46,0xda,0x46,0xe0,0x46,0xe6,0x46,0xec,0x46,0xf2,0x46,0xf8,0x46,0xfe,0x47,0x04,0x47,0x0a,0x47,0x10,0x47,0x16,0x47,0x1c,0x47,0x22,0x47,0x28,0x47,0x2e,0x46,0xb6,0x47,0x34, 0x47,0x3a,0x47,0x40,0x47,0x46,0x47,0x4c,0x47,0x52,0x46,0x74,0x47,0x58,0x47,0x40,0x47,0x46,0x47,0x5e,0x47,0x52,0x47,0x64,0x46,0x68,0x47,0x6a,0x46,0xaa,0x47,0x70,0x47,0x76,0x47,0x7c,0x47,0x82,0x46,0x92,0x47,0x46,0x47,0x88,0x47,0x8e,0x47,0x46,0x47,0x94,0x47,0x9a,0x47,0xa0,0x47,0xa6,0x47,0xac,0x46,0x98,0x47,0xb2,0x47,0xb8, 0x47,0x04,0x47,0xbe,0x46,0xfe,0x47,0x04,0x47,0xbe,0x47,0xc4,0x47,0xca,0x47,0xd0,0x47,0xd6,0x47,0xdc,0x47,0xe2,0x47,0xe8,0x47,0xee,0x47,0xf4,0x47,0xfa,0x48,0x00,0x48,0x06,0x48,0x0c,0x47,0xca,0x47,0xf4,0x48,0x12,0x46,0x80,0x48,0x18,0x48,0x0c,0x48,0x1e,0x48,0x24,0x47,0xd6,0x47,0xdc,0x47,0x1c,0x48,0x2a,0x48,0x30,0x48,0x36, 0x48,0x3c,0x48,0x30,0x48,0x42,0x47,0xd6,0x48,0x48,0x47,0x1c,0x48,0x2a,0x48,0x4e,0x48,0x36,0x48,0x54,0x48,0x5a,0x48,0x60,0x48,0x66,0x48,0x6c,0x47,0x1c,0x48,0x72,0x48,0x6c,0x48,0x78,0x48,0x66,0x48,0x7e,0x48,0x84,0x48,0x66,0x48,0x8a,0x48,0x84,0x48,0x90,0x48,0x96,0x48,0x36,0x48,0x9c,0x48,0xa2,0x48,0xa8,0x48,0xae,0x48,0xb4, 0x48,0xba,0x47,0xe8,0x48,0xc0,0x47,0x70,0x48,0xc6,0x48,0xcc,0x48,0xd2,0x48,0xd8,0x48,0xde,0x48,0xe4,0x48,0xea,0x48,0xf0,0x48,0xf6,0x48,0xfc,0x48,0x7e,0x49,0x02,0x49,0x08,0x47,0xee,0x49,0x0e,0x49,0x14,0x49,0x1a,0x46,0x68,0x49,0x14,0x49,0x1a,0x46,0x68,0x46,0x80,0x46,0x86,0x49,0x20,0x49,0x26,0x49,0x2c,0x46,0xb0,0x49,0x32, 0x49,0x38,0x47,0x3a,0x49,0x3e,0x49,0x44,0x47,0x4c,0x49,0x4a,0x49,0x50,0x47,0x88,0x49,0x56,0x49,0x5c,0x47,0xd0,0x49,0x56,0x49,0x5c,0x47,0xd0,0x49,0x56,0x49,0x5c,0x47,0xd0,0x49,0x62,0x49,0x5c,0x49,0x68,0x49,0x6e,0x49,0x5c,0x47,0xd0,0x49,0x56,0x49,0x74,0x47,0xd0,0x47,0xe8,0x47,0xee,0x49,0x7a,0x49,0x80,0x49,0x5c,0x47,0xf4, 0x49,0x80,0x49,0x5c,0x47,0xf4,0x49,0x86,0x49,0x5c,0x49,0x8c,0x49,0x92,0x49,0x5c,0x47,0x70,0x48,0x2a,0x49,0x98,0x48,0x36,0x48,0x2a,0x49,0x9e,0x48,0x36,0x49,0xa4,0x49,0xaa,0x48,0x36,0x49,0xb0,0x49,0xaa,0x48,0x36,0x49,0xb6,0x49,0xbc,0x47,0x1c,0x49,0xc2,0x49,0xbc,0x48,0x78,0x49,0xc2,0x49,0xbc,0x48,0x78,0x49,0xc8,0x49,0xbc, 0x49,0xce,0x49,0xd4,0x49,0xbc,0x48,0x78,0x49,0xd4,0x49,0xbc,0x48,0x78,0x49,0xda,0x49,0xe0,0x47,0x70,0x49,0xda,0x49,0xe0,0x47,0x70,0x49,0x80,0x49,0xe0,0x47,0xf4,0x49,0xe6,0x49,0xe0,0x47,0xf4,0x49,0xec,0x49,0xf2,0x49,0xf8,0x49,0xfe,0x4a,0x04,0x4a,0x0a,0x47,0x40,0x49,0x44,0x47,0x4c,0x4a,0x10,0x4a,0x16,0x4a,0x1c,0x48,0x72, 0x49,0xbc,0x48,0x78,0x4a,0x22,0x4a,0x28,0x4a,0x2e,0x4a,0x34,0x49,0x1a,0x46,0x68,0x49,0x14,0x4a,0x3a,0x46,0x68,0x49,0x3e,0x49,0x44,0x47,0x4c,0x4a,0x40,0x4a,0x46,0x4a,0x4c,0x4a,0x52,0x4a,0x58,0x4a,0x5e,0x4a,0x64,0x4a,0x6a,0x49,0x02,0x4a,0x70,0x4a,0x76,0x47,0xbe,0x4a,0x34,0x49,0x1a,0x46,0x68,0x4a,0x7c,0x4a,0x82,0x4a,0x88, 0x4a,0x34,0x4a,0x8e,0x46,0x68,0x4a,0x94,0x4a,0x9a,0x4a,0x88,0x49,0x26,0x4a,0x82,0x46,0xb0,0x4a,0xa0,0x4a,0xa6,0x46,0xe6,0x4a,0xac,0x4a,0xa6,0x4a,0xb2,0x4a,0xb8,0x4a,0xbe,0x46,0xe6,0x4a,0xa0,0x4a,0xc4,0x46,0xe6,0x4a,0xca,0x49,0x50,0x47,0x4c,0x4a,0xca,0x49,0x50,0x47,0x4c,0x4a,0xca,0x49,0x50,0x47,0x4c,0x4a,0xd0,0x49,0x50, 0x47,0x88,0x4a,0xd0,0x49,0x50,0x47,0x88,0x4a,0xd0,0x49,0x50,0x47,0x88,0x4a,0xd6,0x4a,0xdc,0x48,0x36,0x47,0x10,0x47,0x16,0x47,0x1c,0x4a,0xe2,0x4a,0xe8,0x4a,0xee,0x4a,0xf4,0x4a,0xfa,0x47,0x70,0x4b,0x00,0x4b,0x06,0x48,0xa8,0x4b,0x0c,0x4b,0x12,0x47,0xbe,0x4b,0x18,0x4b,0x1e,0x49,0x0e,0x46,0x92,0x46,0x98,0x46,0x9e,0x4b,0x24, 0x4b,0x2a,0x4b,0x30,0x4b,0x36,0x4a,0x76,0x47,0xbe,0x4b,0x3c,0x4a,0x6a,0x49,0x02,0x4b,0x42,0x4b,0x48,0x4b,0x4e,0x4b,0x54,0x4b,0x5a,0x4b,0x60,0x4b,0x66,0x4b,0x6c,0x46,0xc2,0x49,0x80,0x4b,0x72,0x48,0x24,0x4b,0x78,0x4b,0x7e,0x4a,0xb2,0x47,0x6a,0x46,0xaa,0x4b,0x84,0x48,0x9c,0x48,0xa2,0x4b,0x8a,0x4b,0x90,0x4b,0x96,0x46,0x8c, 0x49,0xda,0x4b,0x1e,0x47,0xf4,0x4b,0x9c,0x4b,0x96,0x4b,0xa2,0x4b,0xa8,0x4b,0x1e,0x4b,0xae,0x47,0xfa,0x48,0x00,0x48,0x06,0x4a,0x34,0x4a,0x3a,0x46,0x68,0x49,0x56,0x49,0x5c,0x47,0xd0,0x4b,0xb4,0x46,0x62,0x4b,0xba,0x47,0xc4,0x47,0xca,0x4b,0xc0,0x4b,0xc6,0x4b,0xcc,0x4b,0xd2,0x47,0xfa,0x48,0x00,0x48,0x06,0x46,0x92,0x46,0x98, 0x46,0x9e,0x46,0xa4,0x46,0xaa,0x4b,0xd8,0x48,0x0c,0x47,0xca,0x4b,0xde,0x4a,0x7c,0x4a,0xfa,0x46,0xb0,0x49,0x80,0x49,0x5c,0x47,0xf4,0x4b,0xe4,0x4b,0xea,0x47,0x1c,0x4b,0xf0,0x4b,0xf6,0x48,0x36,0x47,0x10,0x4b,0xfc,0x47,0x1c,0x48,0x2a,0x4c,0x02,0x48,0x36,0x47,0x10,0x47,0x16,0x47,0x1c,0x48,0x2a,0x48,0x4e,0x48,0x36,0x4b,0x66, 0x4c,0x08,0x47,0x3a,0x4c,0x0e,0x49,0xbc,0x47,0x1c,0x4a,0xca,0x4c,0x08,0x4c,0x14,0x49,0xc2,0x49,0xbc,0x46,0xb0,0x4a,0xca,0x4c,0x1a,0x47,0x4c,0x49,0xc2,0x49,0xbc,0x48,0x78,0x4c,0x20,0x4c,0x26,0x46,0x68,0x4c,0x2c,0x4c,0x32,0x48,0x36,0x4c,0x20,0x4c,0x26,0x46,0x68,0x4c,0x38,0x4c,0x32,0x48,0x36,0x4c,0x3e,0x4a,0xfa,0x47,0x70, 0x4c,0x38,0x4b,0x06,0x48,0xa8,0x47,0x76,0x47,0x7c,0x4b,0x84,0x48,0xae,0x48,0xb4,0x4c,0x44,0x4a,0xf4,0x4c,0x4a,0x47,0x82,0x4c,0x50,0x4c,0x56,0x48,0xba,0x4b,0xc6,0x4c,0x5c,0x47,0x88,0x49,0xda,0x49,0xe0,0x47,0x70,0x4a,0xd0,0x4c,0x5c,0x47,0x88,0x49,0xda,0x49,0xe0,0x47,0x70,0x4c,0x62,0x4c,0x68,0x47,0xbe,0x4c,0x6e,0x4b,0x1e, 0x49,0x0e,0x4c,0x74,0x4c,0x7a,0x47,0x1c,0x4c,0x80,0x4b,0x1e,0x49,0x0e,0x4c,0x86,0x4c,0x8c,0x4c,0x92,0x4c,0x98,0x4c,0x9e,0x4c,0xa4,0x4c,0xaa,0x4c,0xb0,0x4c,0xb6,0x4c,0xbc,0x4a,0x3a,0x46,0x68,0x49,0x6e,0x49,0x5c,0x47,0xd0,0x4c,0xc2,0x4b,0x96,0x4c,0xc8,0x49,0xda,0x4b,0x1e,0x47,0xf4,0x49,0x3e,0x4c,0xce,0x47,0x4c,0x49,0xd4, 0x4b,0x1e,0x48,0x78,0x4c,0xd4,0x4a,0x9a,0x47,0xbe,0x49,0xe6,0x4c,0xda,0x47,0xf4,0x4c,0xe0,0x4a,0x9a,0x46,0xb0,0x49,0xda,0x49,0x5c,0x47,0x70,0x4c,0xe6,0x4c,0xec,0x47,0x82,0x49,0xe6,0x49,0x5c,0x47,0xf4,0x4b,0x9c,0x4c,0xf2,0x4b,0xa2,0x4b,0xa8,0x4b,0x72,0x4c,0xf8,0x49,0x32,0x4b,0x6c,0x46,0xc2,0x49,0xe6,0x4b,0x72,0x48,0x24, 0x46,0xb6,0x46,0xbc,0x4c,0xfe,0x4d,0x04,0x4d,0x0a,0x48,0x24,0x4d,0x10,0x4c,0x08,0x46,0xd4,0x4d,0x16,0x4d,0x1c,0x47,0xb2,0x4d,0x22,0x4d,0x28,0x4d,0x2e,0x4d,0x34,0x4d,0x3a,0x4d,0x40,0x4d,0x46,0x4a,0xbe,0x4a,0xee,0x4d,0x4c,0x49,0xaa,0x48,0x36,0x4d,0x52,0x4a,0xbe,0x46,0xe6,0x4d,0x58,0x49,0xaa,0x48,0x36,0x4d,0x5e,0x4a,0xc4, 0x4a,0xee,0x4d,0x64,0x49,0x9e,0x48,0x36,0x4d,0x6a,0x46,0xe0,0x4d,0x70,0x48,0x2a,0x48,0x30,0x4d,0x76,0x4d,0x7c,0x4d,0x82,0x46,0xf8,0x48,0x3c,0x4d,0x88,0x48,0x42,0x46,0xfe,0x47,0x04,0x4d,0x8e,0x47,0xd6,0x48,0x48,0x4d,0x94,0x4d,0x9a,0x4d,0xa0,0x4d,0xa6,0x47,0x10,0x47,0x16,0x4d,0xac,0x48,0x2a,0x48,0x4e,0x4d,0xb2,0x46,0xb6, 0x47,0x34,0x4c,0xfe,0x48,0x66,0x48,0x6c,0x4d,0x94,0x46,0xb6,0x47,0x34,0x4d,0xb8,0x48,0x66,0x48,0x6c,0x48,0x84,0x4d,0xbe,0x49,0x44,0x47,0x4c,0x49,0xd4,0x49,0xbc,0x48,0x78,0x4a,0xca,0x49,0x44,0x47,0x4c,0x49,0xc2,0x49,0xbc,0x48,0x78,0x47,0x52,0x47,0x64,0x4d,0xc4,0x48,0x90,0x48,0x96,0x4d,0xca,0x4a,0xf4,0x4a,0xfa,0x47,0x70, 0x4c,0x38,0x4b,0x06,0x48,0xa8,0x4d,0xd0,0x4d,0xd6,0x4d,0xdc,0x4d,0xe2,0x4d,0xe8,0x48,0xba,0x49,0x4a,0x49,0x50,0x47,0x88,0x49,0x92,0x49,0xe0,0x47,0x70,0x4d,0xee,0x49,0x50,0x47,0x88,0x49,0x92,0x49,0xe0,0x47,0x70,0x4a,0xd0,0x49,0x50,0x47,0x88,0x49,0xda,0x49,0xe0,0x47,0x70,0x46,0x92,0x47,0x46,0x4d,0xf4,0x47,0xe8,0x48,0xc0, 0x4d,0xfa,0x4e,0x00,0x4e,0x06,0x47,0xa6,0x4e,0x0c,0x4e,0x12,0x48,0xe4,0x4b,0x36,0x4a,0x76,0x47,0xbe,0x49,0x56,0x4a,0x6a,0x4e,0x18,0x4e,0x1e,0x4e,0x24,0x48,0x36,0x4e,0x2a,0x4e,0x06,0x47,0xa6,0x4e,0x30,0x4e,0x12,0x48,0xe4,0x4e,0x2a,0x4e,0x06,0x47,0xa6,0x4e,0x30,0x4e,0x12,0x48,0xe4,0x4e,0x36,0x4e,0x06,0x47,0xa6,0x4e,0x3c, 0x4e,0x12,0x48,0xe4,0x4b,0x36,0x4a,0x76,0x47,0xbe,0x4b,0x3c,0x4e,0x42,0x49,0x02,0x47,0x40,0x4e,0x48,0x47,0x4c,0x48,0x72,0x4e,0x4e,0x48,0x78,0x4e,0x54,0x4e,0x5a,0x47,0x88,0x4e,0x60,0x4e,0x66,0x47,0x70,0x4b,0xb4,0x46,0x62,0x4e,0x6c,0x4e,0x72,0x47,0xca,0x4e,0x78,0x4a,0x34,0x4a,0x8e,0x46,0x68,0x49,0x56,0x49,0x5c,0x47,0xd0, 0x47,0xb8,0x46,0xaa,0x4e,0x7e,0x48,0x66,0x47,0xca,0x4e,0x84,0x4a,0xf4,0x4a,0xfa,0x47,0x82,0x49,0x80,0x49,0x5c,0x47,0xf4,0x4c,0xe6,0x4a,0x9a,0x47,0x82,0x49,0xe6,0x4c,0xda,0x47,0xf4,0x4a,0xa0,0x4e,0x8a,0x46,0xe6,0x48,0x2a,0x4e,0x90,0x48,0x36,0x46,0xda,0x46,0xe0,0x4e,0x96,0x48,0x2a,0x48,0x30,0x4e,0x9c,0x47,0x40,0x47,0x46, 0x4e,0xa2,0x48,0x72,0x48,0x6c,0x4e,0xa8,0x4a,0xca,0x4c,0x5c,0x47,0x4c,0x49,0xc2,0x49,0xbc,0x48,0x78,0x46,0x92,0x47,0x46,0x4e,0xae,0x47,0xe8,0x48,0xc0,0x4e,0xb4,0x4a,0xd0,0x4c,0x5c,0x47,0x88,0x49,0xda,0x49,0xe0,0x47,0x70,0x47,0xb8,0x47,0x04,0x4e,0x7e,0x48,0xfc,0x48,0x7e,0x49,0x02,0x4b,0x36,0x4b,0x12,0x47,0xbe,0x4b,0x3c, 0x4e,0x42,0x49,0x02,0x4a,0x70,0x4a,0x76,0x47,0xbe,0x4a,0x64,0x4a,0x6a,0x49,0x02,0x47,0x76,0x47,0x7c,0x4e,0xba,0x48,0xae,0x48,0xb4,0x4e,0xc0,0x4e,0xc6,0x4e,0xcc,0x4e,0xd2,0x4e,0xd8,0x4e,0xde,0x4e,0xe4,0x46,0xa4,0x46,0xaa,0x4e,0xea,0x48,0x0c,0x47,0xca,0x49,0x7a,0x4b,0xb4,0x46,0x62,0x4e,0xf0,0x47,0xc4,0x47,0xca,0x4e,0xf6, 0x4e,0xfc,0x4f,0x02,0x46,0x7a,0x47,0xd6,0x47,0xdc,0x47,0xe2,0x4f,0x08,0x46,0x74,0x4f,0x0e,0x47,0xd6,0x47,0xdc,0x4f,0x14,0x47,0xb8,0x46,0x74,0x4f,0x1a,0x47,0xd6,0x47,0xdc,0x4f,0x20,0x49,0x14,0x4f,0x26,0x46,0x68,0x47,0xfa,0x48,0x00,0x48,0x06,0x4f,0x2c,0x46,0x98,0x4f,0x32,0x4f,0x38,0x48,0x00,0x4e,0xa8,0x46,0xfe,0x46,0x98, 0x4f,0x3e,0x47,0xd6,0x48,0x00,0x4f,0x44,0x46,0x92,0x46,0x98,0x4f,0x4a,0x47,0xfa,0x48,0x00,0x4f,0x50,0x4f,0x56,0x46,0x98,0x4f,0x5c,0x47,0xd6,0x48,0x00,0x48,0x84,0x47,0x10,0x46,0xaa,0x48,0x84,0x4f,0x62,0x47,0xca,0x4c,0xf8,0x4f,0x08,0x46,0xaa,0x4f,0x68,0x48,0x0c,0x47,0xca,0x4b,0xde,0x4f,0x6e,0x4a,0x82,0x4f,0x74,0x4f,0x7a, 0x4f,0x80,0x48,0x18,0x4f,0x86,0x49,0x38,0x46,0xc2,0x49,0xe6,0x4b,0x72,0x48,0x24,0x4f,0x8c,0x4f,0x92,0x46,0xd4,0x4f,0x98,0x4f,0x9e,0x47,0x1c,0x46,0xc8,0x46,0xce,0x4f,0xa4,0x4f,0xaa,0x47,0xdc,0x4f,0xb0,0x4f,0x8c,0x49,0x38,0x46,0xd4,0x4f,0xb6,0x4f,0xbc,0x47,0x94,0x46,0xc8,0x46,0xce,0x4f,0xc2,0x47,0xd6,0x47,0xdc,0x48,0x84, 0x46,0xc8,0x46,0xce,0x4f,0xc8,0x47,0xd6,0x47,0xdc,0x4f,0xce,0x46,0xda,0x46,0xe0,0x4f,0xd4,0x48,0x2a,0x48,0x30,0x4d,0x76,0x4f,0xda,0x4c,0x68,0x47,0x0a,0x4f,0xe0,0x49,0x2c,0x47,0x1c,0x47,0x8e,0x47,0x04,0x4f,0xe6,0x4f,0xec,0x48,0x48,0x4e,0xb4,0x46,0xfe,0x47,0x04,0x4f,0x3e,0x4f,0xf2,0x48,0x48,0x4f,0xf8,0x47,0x76,0x47,0x16, 0x4e,0xb4,0x48,0x2a,0x48,0x4e,0x4e,0x9c,0x4f,0xfe,0x50,0x04,0x4e,0xb4,0x50,0x0a,0x4b,0xf6,0x4e,0x9c,0x4f,0x08,0x47,0x16,0x4f,0xf8,0x48,0x2a,0x48,0x4e,0x50,0x10,0x50,0x16,0x47,0x16,0x50,0x1c,0x48,0x2a,0x48,0x4e,0x50,0x22,0x50,0x28,0x50,0x2e,0x47,0x2e,0x50,0x34,0x50,0x3a,0x48,0x60,0x50,0x40,0x50,0x46,0x47,0x2e,0x50,0x34, 0x50,0x3a,0x48,0x60,0x47,0x22,0x47,0x28,0x50,0x4c,0x48,0x54,0x48,0x5a,0x50,0x52,0x50,0x58,0x49,0x38,0x50,0x5e,0x49,0xd4,0x49,0xbc,0x46,0xb0,0x50,0x64,0x47,0x34,0x50,0x6a,0x48,0x72,0x48,0x6c,0x4e,0xa8,0x50,0x64,0x47,0x34,0x50,0x70,0x48,0x72,0x48,0x6c,0x50,0x76,0x47,0x40,0x47,0x34,0x50,0x7c,0x48,0x66,0x48,0x6c,0x48,0x84, 0x4c,0x20,0x50,0x82,0x47,0x58,0x4c,0x0e,0x4a,0x6a,0x48,0x84,0x4a,0x94,0x50,0x88,0x4a,0x88,0x50,0x8e,0x4a,0x6a,0x50,0x94,0x50,0x9a,0x50,0xa0,0x46,0xb0,0x50,0xa6,0x4c,0x32,0x48,0x36,0x47,0x52,0x47,0x64,0x50,0xac,0x48,0x90,0x48,0x96,0x4e,0x9c,0x47,0x52,0x47,0x64,0x50,0xb2,0x48,0x90,0x48,0x96,0x50,0x10,0x4c,0x74,0x4a,0x82, 0x50,0xb8,0x4c,0x2c,0x4b,0x06,0x50,0xbe,0x47,0x6a,0x46,0xaa,0x4e,0xb4,0x50,0xc4,0x48,0xa2,0x50,0xca,0x4c,0x3e,0x50,0xd0,0x47,0x70,0x4c,0x38,0x50,0xd6,0x48,0xa8,0x50,0xdc,0x50,0xd0,0x4b,0xae,0x50,0xe2,0x50,0xd6,0x48,0xa8,0x50,0xe8,0x4a,0x82,0x50,0xee,0x4c,0x2c,0x4b,0x06,0x50,0xf4,0x4c,0xe6,0x4a,0x9a,0x47,0x82,0x50,0xfa, 0x4c,0x56,0x48,0xba,0x47,0x76,0x47,0x7c,0x4e,0xb4,0x48,0xae,0x48,0xb4,0x51,0x00,0x47,0x76,0x47,0x7c,0x51,0x06,0x48,0xae,0x48,0xb4,0x51,0x0c,0x47,0x76,0x47,0x7c,0x51,0x12,0x48,0xae,0x48,0xb4,0x51,0x18,0x46,0x92,0x47,0x46,0x4e,0xae,0x51,0x1e,0x48,0xc0,0x51,0x24,0x46,0x92,0x47,0x46,0x4e,0xae,0x47,0xe8,0x48,0xc0,0x4e,0xb4, 0x4f,0x56,0x47,0x46,0x4f,0x5c,0x51,0x2a,0x48,0xc0,0x50,0x1c,0x51,0x30,0x51,0x36,0x47,0x94,0x49,0x62,0x51,0x3c,0x48,0xd2,0x47,0x8e,0x47,0x46,0x4f,0xe6,0x48,0xc6,0x48,0xcc,0x51,0x42,0x51,0x48,0x51,0x4e,0x47,0xa6,0x51,0x54,0x4e,0x12,0x48,0xe4,0x47,0x9a,0x47,0xa0,0x51,0x5a,0x48,0xd8,0x48,0xde,0x51,0x60,0x51,0x66,0x51,0x6c, 0x47,0xb2,0x51,0x72,0x51,0x78,0x48,0xf6,0x51,0x66,0x4f,0x26,0x47,0xb2,0x51,0x72,0x4e,0x42,0x48,0xf6,0x4a,0x70,0x4c,0x7a,0x47,0xbe,0x4a,0x64,0x4e,0x42,0x49,0x02,0x49,0x26,0x4b,0x12,0x46,0xb0,0x4c,0x6e,0x4b,0x1e,0x51,0x7e,0x46,0xfe,0x47,0x04,0x4e,0xa8,0x49,0x08,0x47,0xee,0x51,0x84,0x46,0xfe,0x47,0x04,0x4f,0x1a,0x48,0x90, 0x47,0xee,0x51,0x8a,0x47,0xd6,0x47,0xdc,0x4f,0x44,0x51,0x90,0x51,0x96,0x48,0xba,0x4e,0x30,0x4e,0x12,0x48,0xe4,0x4b,0x3c,0x4a,0x6a,0x49,0x02,0x49,0x56,0x51,0x9c,0x47,0xd0,0x51,0xa2,0x51,0xa8,0x51,0xae,0x4b,0x54,0x51,0xb4,0x51,0xba,0x51,0xc0,0x51,0xc6,0x51,0xcc,0x51,0xd2,0x51,0xd8,0x51,0xde,0x4b,0x54,0x51,0xe4,0x51,0xba, 0x51,0xea,0x51,0xf0,0x51,0xf6,0x4b,0x54,0x51,0xb4,0x51,0xba,0x51,0xfc,0x52,0x02,0x52,0x08,0x52,0x0e,0x52,0x14,0x52,0x1a,0x52,0x20,0x52,0x26,0x4b,0x30,0x52,0x2c,0x52,0x32,0x46,0x9e,0x52,0x38,0x52,0x3e,0x52,0x44,0x52,0x4a,0x52,0x50,0x52,0x56,0x4b,0x54,0x52,0x5c,0x51,0xba,0x52,0x62,0x52,0x68,0x52,0x6e,0x52,0x74,0x52,0x7a, 0x51,0x7e,0x52,0x80,0x52,0x86,0x48,0x78,0x52,0x8c,0x52,0x92,0x52,0x98,0x52,0x9e,0x52,0xa4,0x46,0xc2,0x52,0xaa,0x52,0xb0,0x52,0xb6,0x52,0xbc,0x52,0xc2,0x52,0xc8,0x52,0xce,0x52,0xd4,0x48,0x18,0x52,0xda,0x52,0xe0,0x4a,0xb2,0x52,0xe6,0x52,0xec,0x52,0xf2,0x52,0xf8,0x52,0xfe,0x53,0x04,0x53,0x0a,0x53,0x10,0x53,0x16,0x53,0x1c, 0x53,0x22,0x53,0x04,0x53,0x28,0x53,0x2e,0x53,0x34,0x53,0x3a,0x53,0x40,0x53,0x46,0x53,0x4c,0x53,0x52,0x53,0x58,0x53,0x5e,0x53,0x64,0x53,0x6a,0x53,0x70,0x53,0x76,0x53,0x7c,0x53,0x82,0x53,0x88,0x53,0x8e,0x53,0x94,0x53,0x9a,0x53,0xa0,0x53,0xa6,0x53,0xac,0x4b,0x60,0x53,0xb2,0x53,0xb8,0x53,0xbe,0x47,0x6a,0x46,0xaa,0x47,0x70, 0x48,0x9c,0x48,0xa2,0x48,0xa8,0x53,0xc4,0x53,0xca,0x53,0xd0,0x53,0xd6,0x53,0xdc,0x53,0xe2,0x53,0xe8,0x53,0xee,0x53,0xf4,0x53,0xfa,0x54,0x00,0x54,0x06,0x54,0x0c,0x54,0x12,0x54,0x18,0x53,0xfa,0x54,0x00,0x54,0x1e,0x54,0x24,0x54,0x2a,0x54,0x30,0x54,0x36,0x54,0x3c,0x54,0x42,0x54,0x48,0x54,0x4e,0x54,0x54,0x54,0x5a,0x54,0x60, 0x54,0x66,0x46,0xfe,0x47,0x04,0x47,0xbe,0x49,0x08,0x47,0xee,0x49,0x0e,0x47,0x76,0x47,0x04,0x51,0x12,0x46,0x80,0x46,0xce,0x54,0x6c,0x54,0x72,0x54,0x78,0x54,0x7e,0x54,0x84,0x54,0x8a,0x54,0x90,0x54,0x96,0x54,0x9c,0x54,0xa2,0x54,0xa8,0x54,0xae,0x54,0xb4,0x54,0xba,0x54,0xc0,0x54,0xc6,0x54,0xcc,0x54,0xd2,0x54,0xd8,0x54,0xde, 0x54,0xe4,0x54,0xea,0x54,0xf0,0x54,0xf6,0x54,0xfc,0x55,0x02,0x55,0x08,0x55,0x0e,0x55,0x14,0x55,0x1a,0x55,0x20,0x55,0x26,0x55,0x2c,0x55,0x32,0x55,0x38,0x55,0x3e,0x55,0x44,0x4a,0x34,0x4a,0x8e,0x46,0x68,0x55,0x4a,0x49,0x5c,0x55,0x50,0x4a,0xa0,0x4a,0xa6,0x46,0xe6,0x48,0x2a,0x55,0x56,0x48,0x36,0x4a,0xca,0x4c,0x5c,0x47,0x4c, 0x49,0xc2,0x49,0xbc,0x48,0x78,0x55,0x5c,0x4c,0x5c,0x55,0x62,0x4b,0xa8,0x49,0xe0,0x4b,0xae,0x4e,0x72,0x47,0xca,0x52,0x08,0x55,0x68,0x55,0x6e,0x55,0x74,0x55,0x7a,0x55,0x80,0x55,0x86,0x46,0xb6,0x46,0xbc,0x46,0xc2,0x48,0x0c,0x48,0x1e,0x48,0x24,0x55,0x8c,0x4c,0xf2,0x55,0x92,0x4b,0xa8,0x4b,0x72,0x4c,0xf8,0x49,0x26,0x4c,0x68, 0x46,0xb0,0x55,0x98,0x49,0x2c,0x53,0x04,0x47,0x40,0x47,0x46,0x55,0x9e,0x48,0x72,0x48,0x6c,0x55,0xa4,0x4d,0xbe,0x49,0x44,0x55,0x9e,0x49,0xd4,0x49,0xbc,0x55,0xa4,0x55,0xaa,0x4c,0x68,0x4e,0x18,0x55,0xb0,0x4b,0x1e,0x55,0xb6,0x48,0x3c,0x55,0xbc,0x48,0x42,0x55,0xc2,0x55,0xc8,0x55,0xce,0x55,0xd4,0x55,0xda,0x54,0xc6,0x55,0xe0, 0x55,0xe6,0x54,0xd8,0x4b,0x66,0x4c,0xf2,0x46,0xc2,0x49,0x80,0x4b,0x72,0x48,0x24,0x46,0x92,0x55,0xec,0x46,0x9e,0x55,0xf2,0x55,0xf8,0x55,0xfe,0x4b,0x66,0x49,0x38,0x47,0x3a,0x4c,0x0e,0x49,0xbc,0x47,0x1c,0x4a,0x34,0x56,0x04,0x46,0x68,0x49,0x56,0x49,0x5c,0x47,0xd0,0x4a,0x34,0x4a,0x3a,0x46,0x68,0x49,0x56,0x49,0x5c,0x47,0xd0, 0x4c,0xe0,0x56,0x0a,0x46,0xb0,0x49,0xda,0x49,0x5c,0x47,0xf4,0x4a,0x7c,0x4a,0x9a,0x4a,0x88,0x49,0xda,0x49,0x5c,0x47,0x70,0x4a,0xa0,0x56,0x10,0x46,0xe6,0x48,0x2a,0x56,0x16,0x48,0x36,0x4a,0xa0,0x4a,0xbe,0x46,0xe6,0x48,0x2a,0x49,0xaa,0x48,0x36,0x4b,0x90,0x49,0x44,0x47,0x4c,0x49,0x80,0x49,0xbc,0x48,0x78,0x4a,0xca,0x49,0x44, 0x47,0x4c,0x49,0xc2,0x49,0xbc,0x48,0x78,0x4a,0xf4,0x4c,0x26,0x46,0xb0,0x4b,0x00,0x4c,0x32,0x48,0x36,0x4c,0x20,0x50,0xa0,0x46,0x68,0x56,0x1c,0x4c,0x32,0x48,0x36,0x4a,0xd0,0x4c,0x5c,0x47,0x88,0x49,0xda,0x49,0xe0,0x47,0x70,0x4a,0xd0,0x49,0x50,0x47,0x88,0x4b,0xa8,0x49,0xe0,0x4b,0xae,0x56,0x22,0x56,0x28,0x56,0x2e,0x56,0x34, 0x56,0x3a,0x56,0x40,0x4d,0x10,0x4c,0x08,0x46,0xd4,0x55,0x98,0x56,0x46,0x47,0x1c,0x56,0x4c,0x56,0x52,0x56,0x58,0x56,0x5e,0x56,0x64,0x56,0x6a,0x56,0x70,0x56,0x76,0x4b,0xae,0x46,0xfe,0x47,0x04,0x56,0x7c,0x49,0x08,0x47,0xee,0x56,0x82,0x49,0x14,0x49,0x1a,0x46,0x68,0x49,0x6e,0x49,0x5c,0x47,0xd0,0x49,0x3e,0x49,0x50,0x47,0x4c, 0x49,0xd4,0x49,0xbc,0x48,0x78,0x4a,0x70,0x4f,0x92,0x47,0xbe,0x4a,0x64,0x4a,0x6a,0x49,0x02,0x56,0x88,0x56,0x8e,0x56,0x94,0x56,0x9a,0x56,0xa0,0x56,0xa6,0x56,0x9a,0x56,0xac,0x56,0xa6,0x56,0xb2,0x56,0xb8,0x56,0xbe,0x56,0xc4,0x56,0xca,0x56,0xd0,0x56,0xd6,0x56,0xca,0x56,0xdc,0x56,0xe2,0x56,0xe8,0x56,0xee,0x56,0xe2,0x56,0xf4, 0x56,0xbe,0x56,0xfa,0x4e,0xde,0x57,0x00,0x57,0x06,0x57,0x0c,0x57,0x12,0x57,0x18,0x57,0x1e,0x57,0x24,0x57,0x2a,0x57,0x1e,0x57,0x30,0x57,0x2a,0x57,0x36,0x57,0x30,0x57,0x3c,0x57,0x42,0x57,0x48,0x57,0x4e,0x57,0x54,0x57,0x5a,0x57,0x60,0x56,0xf4,0x48,0x24,0x48,0x0c,0x48,0x1e,0x48,0x24,0x57,0x66,0x57,0x6c,0x57,0x72,0x57,0x78, 0x57,0x7e,0x57,0x84,0x57,0x8a,0x57,0x90,0x57,0x96,0x57,0x9c,0x57,0xa2,0x57,0xa8,0x57,0xae,0x57,0xb4,0x47,0x1c,0x57,0xae,0x57,0xb4,0x57,0xa8,0x57,0xba,0x57,0xc0,0x57,0xc6,0x57,0xcc,0x57,0xd2,0x48,0x18,0x57,0xd8,0x57,0xde,0x57,0xe4,0x57,0xea,0x57,0xf0,0x57,0xf6,0x57,0xfc,0x58,0x02,0x58,0x08,0x58,0x0e,0x58,0x14,0x58,0x1a, 0x58,0x20,0x58,0x26,0x58,0x2c,0x58,0x32,0x58,0x38,0x4c,0x92,0x58,0x32,0x58,0x38,0x58,0x3e,0x48,0x54,0x48,0x5a,0x58,0x44,0x48,0x66,0x48,0x6c,0x48,0x84,0x48,0x66,0x48,0x6c,0x48,0x84,0x58,0x4a,0x58,0x50,0x46,0xb0,0x58,0x56,0x58,0x5c,0x48,0x78,0x58,0x62,0x58,0x68,0x58,0x6e,0x58,0x74,0x58,0x7a,0x58,0x80,0x58,0x86,0x58,0x8c, 0x58,0x92,0x58,0x98,0x58,0x9e,0x58,0xa4,0x58,0xaa,0x58,0xb0,0x58,0xa4,0x58,0x98,0x58,0x9e,0x58,0xb6,0x58,0xbc,0x48,0x96,0x50,0x22,0x58,0xbc,0x48,0x96,0x57,0x5a,0x58,0xc2,0x58,0xc8,0x58,0xce,0x58,0xd4,0x58,0xda,0x58,0xe0,0x58,0xe6,0x58,0xec,0x58,0xf2,0x58,0xe6,0x58,0xf8,0x58,0xf2,0x48,0x9c,0x48,0xa2,0x58,0xfe,0x59,0x04, 0x59,0x0a,0x59,0x10,0x59,0x16,0x59,0x1c,0x59,0x22,0x59,0x28,0x59,0x2e,0x59,0x34,0x59,0x3a,0x59,0x40,0x59,0x46,0x59,0x4c,0x59,0x52,0x59,0x58,0x48,0xae,0x48,0xb4,0x59,0x5e,0x59,0x64,0x59,0x6a,0x59,0x70,0x59,0x76,0x59,0x7c,0x59,0x82,0x59,0x88,0x59,0x8e,0x59,0x94,0x59,0x9a,0x59,0xa0,0x48,0xd2,0x59,0xa6,0x59,0xac,0x59,0xb2, 0x59,0xb8,0x59,0xbe,0x58,0xf2,0x59,0xc4,0x59,0xca,0x59,0xd0,0x49,0x08,0x47,0xee,0x59,0xd6,0x49,0x08,0x47,0xee,0x59,0xdc,0x59,0xe2,0x47,0xee,0x56,0x40,0x59,0xe2,0x47,0xee,0x56,0x40,0x59,0xe8,0x59,0xee,0x59,0xf4,0x59,0xe8,0x59,0xfa,0x5a,0x00,0x57,0xea,0x5a,0x06,0x5a,0x0c,0x5a,0x12,0x5a,0x18,0x48,0x24,0x5a,0x1e,0x5a,0x24, 0x5a,0x2a,0x58,0xe6,0x5a,0x30,0x58,0xf2,0x5a,0x36,0x5a,0x3c,0x5a,0x42,0x5a,0x48,0x5a,0x4e,0x5a,0x54,0x5a,0x5a,0x57,0xa2,0x4d,0x40,0x5a,0x60,0x5a,0x66,0x5a,0x6c,0x5a,0x72,0x5a,0x78,0x5a,0x7e,0x5a,0x84,0x5a,0x8a,0x51,0x7e,0x47,0xd6,0x5a,0x90,0x48,0x84,0x59,0xe8,0x59,0xee,0x59,0xf4,0x59,0xe8,0x59,0xfa,0x5a,0x00,0x5a,0x96, 0x5a,0x9c,0x5a,0xa2,0x5a,0x96,0x5a,0xa8,0x5a,0xae,0x5a,0x96,0x5a,0xb4,0x5a,0xba,0x5a,0xc0,0x5a,0xc6,0x5a,0xcc,0x5a,0xd2,0x5a,0xd8,0x5a,0xde,0x5a,0xe4,0x5a,0xea,0x5a,0xf0,0x5a,0xf6,0x53,0x64,0x5a,0xfc,0x5b,0x02,0x5b,0x08,0x5b,0x0e,0x5b,0x14,0x5b,0x1a,0x5b,0x20,0x5b,0x26,0x5b,0x2c,0x5b,0x32,0x5b,0x38,0x5b,0x2c,0x5b,0x32, 0x5b,0x3e,0x5b,0x44,0x48,0x42,0x5b,0x4a,0x5b,0x44,0x46,0xe6,0x5b,0x50,0x5b,0x56,0x5b,0x5c,0x5b,0x62,0x5b,0x68,0x50,0x22,0x5b,0x6e,0x5b,0x74,0x48,0x84,0x5b,0x7a,0x5b,0x80,0x5b,0x86,0x52,0x62,0x5b,0x8c,0x52,0x6e,0x52,0x62,0x5b,0x8c,0x52,0x6e,0x5b,0x92,0x5b,0x98,0x5b,0x9e,0x5b,0xa4,0x5b,0xaa,0x5b,0xb0,0x5b,0xb6,0x5b,0xbc, 0x5b,0xc2,0x5b,0xc8,0x5b,0xce,0x5b,0xd4,0x5b,0xda,0x5b,0xe0,0x5b,0xe6,0x47,0x10,0x47,0x16,0x47,0x1c,0x5b,0xec,0x5b,0xf2,0x5b,0xf8,0x48,0x9c,0x48,0xa2,0x5b,0xfe,0x49,0x08,0x47,0xee,0x5c,0x04,0x5c,0x0a,0x5c,0x10,0x48,0xd2,0x47,0xd6,0x47,0xdc,0x47,0xe2,0x47,0xfa,0x48,0x00,0x48,0x06,0x48,0x12,0x46,0x80,0x48,0x18,0x48,0x54, 0x48,0x5a,0x48,0x60,0x48,0x66,0x48,0x6c,0x47,0x1c,0x48,0x66,0x48,0x7e,0x48,0x84,0x48,0x90,0x48,0x96,0x48,0x36,0x5c,0x16,0x5c,0x1c,0x5c,0x22,0x48,0x9c,0x48,0xa2,0x48,0xa8,0x48,0xae,0x48,0xb4,0x48,0xba,0x49,0x08,0x47,0xee,0x49,0x0e,0x5c,0x28,0x5c,0x2e,0x56,0xee,0x5c,0x34,0x5c,0x3a,0x5c,0x40,0x5c,0x46,0x5c,0x4c,0x5c,0x52, 0x5c,0x58,0x5c,0x5e,0x5c,0x64,0x5c,0x6a,0x57,0xde,0x5c,0x70,0x4a,0xd6,0x5c,0x76,0x48,0x36,0x48,0x66,0x48,0x7e,0x48,0x84,0x5c,0x7c,0x5c,0x82,0x5c,0x88,0x59,0x76,0x59,0x7c,0x59,0x82,0x47,0xd6,0x47,0xdc,0x5c,0x8e,0x47,0xfa,0x48,0x00,0x5c,0x94,0x48,0x12,0x46,0x80,0x5c,0x9a,0x48,0x0c,0x48,0x1e,0x48,0x24,0x47,0xd6,0x48,0x48, 0x5c,0xa0,0x48,0x2a,0x48,0x4e,0x4d,0x76,0x48,0x54,0x48,0x5a,0x5c,0xa6,0x48,0x66,0x48,0x6c,0x5c,0xa0,0x48,0x66,0x48,0x7e,0x48,0x84,0x48,0x90,0x48,0x96,0x4d,0x76,0x48,0x9c,0x48,0xa2,0x58,0xfe,0x59,0x04,0x59,0x0a,0x59,0x10,0x48,0xc6,0x48,0xcc,0x5c,0xac,0x48,0xea,0x48,0xf0,0x5c,0xb2,0x49,0x08,0x47,0xee,0x5c,0xb8,0x47,0xc4, 0x47,0xca,0x4b,0xc0,0x48,0x66,0x48,0x8a,0x5c,0xa0,0x47,0xd6,0x5a,0x90,0x5c,0xa0,0x48,0x0c,0x47,0xca,0x4b,0xde,0x57,0x18,0x57,0x1e,0x5c,0xbe,0x57,0x2a,0x57,0x1e,0x5c,0xc4,0x48,0x0c,0x47,0xca,0x47,0xf4,0x48,0x2a,0x48,0x30,0x4d,0x76,0x5c,0xca,0x47,0xee,0x5c,0xd0,0x59,0x04,0x59,0x0a,0x59,0x10,0x47,0xe8,0x48,0xc0,0x4d,0xfa, 0x5c,0xd6,0x5c,0xdc,0x5c,0xe2,0x5c,0xe8,0x5c,0xee,0x5c,0xf4,0x5c,0xfa,0x5d,0x00,0x57,0xe4,0x46,0x6e,0x46,0x74,0x46,0x7a,0x46,0x92,0x47,0x46,0x47,0x88,0x46,0xfe,0x46,0x62,0x47,0x0a,0x46,0xa4,0x46,0xaa,0x5d,0x06,0x5d,0x0c,0x5d,0x12,0x4b,0xde,0x46,0xec,0x46,0xf2,0x46,0xf8,0x48,0x3c,0x48,0x30,0x48,0x42,0x5d,0x18,0x5d,0x1e, 0x5d,0x24,0x5d,0x2a,0x5d,0x30,0x5d,0x36,0x47,0x52,0x47,0x64,0x46,0x68,0x48,0x90,0x48,0x96,0x48,0x36,0x47,0xb8,0x47,0x04,0x47,0xbe,0x48,0xfc,0x48,0x7e,0x49,0x02,0x5d,0x3c,0x5d,0x42,0x5d,0x48,0x47,0x10,0x47,0x16,0x47,0x1c,0x5d,0x4e,0x48,0x4e,0x5d,0x54,0x47,0x10,0x47,0x16,0x47,0x1c,0x47,0x52,0x46,0x74,0x47,0x58,0x47,0x52, 0x47,0x64,0x5d,0x5a,0x5d,0x60,0x5d,0x66,0x4b,0xc0,0x5d,0x6c,0x5d,0x72,0x5d,0x78,0x48,0x66,0x5d,0x7e,0x47,0x1c,0x5d,0x84,0x5d,0x8a,0x5d,0x90,0x4a,0xd6,0x4a,0xdc,0x4d,0x76,0x00,0x02,0x00,0x0d,0x02,0x44,0x02,0x47,0x00,0x00,0x04,0x62,0x04,0x79,0x00,0x04,0x04,0x7b,0x04,0x7f,0x00,0x1c,0x04,0x82,0x04,0x84,0x00,0x21,0x04,0x87, 0x04,0x91,0x00,0x24,0x04,0x97,0x04,0x9d,0x00,0x2f,0x04,0xa0,0x04,0xac,0x00,0x36,0x05,0xfd,0x06,0x00,0x00,0x43,0x06,0x66,0x06,0x72,0x00,0x47,0x07,0x55,0x07,0x5c,0x00,0x54,0x07,0xed,0x07,0xef,0x00,0x5c,0x08,0x4c,0x08,0x4f,0x00,0x5f,0x0a,0xdb,0x0a,0xe3,0x00,0x63,0x00,0x02,0x00,0x36,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44, 0x00,0x5d,0x00,0x1a,0x00,0x62,0x00,0x81,0x00,0x34,0x00,0x89,0x00,0x89,0x00,0x54,0x00,0x91,0x00,0x92,0x00,0x55,0x00,0xa0,0x00,0xa1,0x00,0x57,0x00,0xa7,0x00,0xa7,0x00,0x59,0x00,0xad,0x00,0xb1,0x00,0x5a,0x00,0xba,0x00,0xbb,0x00,0x5f,0x00,0xc7,0x00,0xd6,0x00,0x61,0x00,0xe1,0x00,0xe6,0x00,0x71,0x00,0xe8,0x00,0xed,0x00,0x77, 0x00,0xf7,0x01,0x00,0x00,0x7d,0x01,0x03,0x01,0x2b,0x00,0x87,0x01,0x39,0x01,0x3b,0x00,0xb0,0x01,0x45,0x01,0x84,0x00,0xb3,0x01,0x8c,0x01,0x93,0x00,0xf3,0x02,0x40,0x02,0x43,0x00,0xfb,0x02,0x57,0x02,0x5a,0x00,0xff,0x02,0x6f,0x02,0x74,0x01,0x03,0x02,0x7f,0x02,0x86,0x01,0x09,0x02,0x9b,0x02,0x9e,0x01,0x11,0x02,0xa9,0x02,0xb0, 0x01,0x15,0x02,0xcd,0x02,0xce,0x01,0x1d,0x02,0xe1,0x02,0xea,0x01,0x1f,0x02,0xed,0x02,0xf6,0x01,0x29,0x02,0xfb,0x02,0xfe,0x01,0x33,0x03,0x01,0x03,0x10,0x01,0x37,0x03,0x13,0x03,0x2e,0x01,0x47,0x03,0x37,0x03,0x3e,0x01,0x63,0x03,0x41,0x03,0x5a,0x01,0x6b,0x03,0x5f,0x03,0x78,0x01,0x85,0x04,0xb0,0x04,0xe2,0x01,0x9f,0x04,0xe6, 0x04,0xe7,0x01,0xd2,0x04,0xe9,0x04,0xe9,0x01,0xd4,0x04,0xee,0x04,0xfe,0x01,0xd5,0x05,0x07,0x05,0x07,0x01,0xe6,0x05,0x0c,0x05,0x46,0x01,0xe7,0x05,0x4b,0x05,0x4c,0x02,0x22,0x05,0x4f,0x05,0x50,0x02,0x24,0x05,0x56,0x05,0xb2,0x02,0x26,0x06,0xac,0x06,0xad,0x02,0x83,0x07,0x3e,0x07,0x43,0x02,0x85,0x07,0xe1,0x07,0xe2,0x02,0x8b, 0x07,0xe4,0x07,0xeb,0x02,0x8d,0x07,0xf7,0x08,0x05,0x02,0x95,0x08,0x07,0x08,0x26,0x02,0xa4,0x0a,0x43,0x0a,0x43,0x02,0xc4,0x0a,0xbf,0x0a,0xcc,0x02,0xc5,0x0a,0xe5,0x0a,0xe5,0x02,0xd3,0x0a,0xe7,0x0a,0xed,0x02,0xd4,0x0a,0xf4,0x0a,0xf4,0x02,0xdb,0x0a,0xf7,0x0a,0xf7,0x02,0xdc,0x11,0x8c,0x11,0x8c,0x02,0xdd,0x00,0x01,0x00,0x98, 0x00,0xc0,0x00,0x02,0x00,0x0c,0x00,0x2e,0x00,0x08,0x00,0x00,0x4a,0xba,0x00,0x00,0x4a,0xc0,0x00,0x01,0x4a,0xc6,0x00,0x00,0x4a,0xcc,0x00,0x01,0x4a,0xc6,0x00,0x00,0x4a,0xc6,0x00,0x01,0x4a,0xc6,0x00,0x01,0x4a,0xc6,0x00,0x1a,0x4a,0xb0,0x4a,0xb0,0x4a,0xb6,0x4a,0xbc,0x4a,0xc2,0x4a,0xc2,0x4a,0xc8,0x4a,0xc8,0x4a,0xce,0x4a,0xce, 0x4a,0xd4,0x4a,0xda,0x4a,0xe0,0x4a,0xe6,0x4a,0xec,0x4a,0xf2,0x4a,0xf8,0x4a,0xf8,0x4a,0xfe,0x4b,0x04,0x4b,0x0a,0x4b,0x10,0x40,0xb4,0x40,0xb4,0x4b,0x16,0x4b,0x1c,0x4b,0x22,0x4b,0x22,0x4b,0x28,0x4b,0x2e,0x4b,0x34,0x4b,0x3a,0x4b,0x40,0x4b,0x40,0x4b,0x46,0x4b,0x4c,0x4b,0x52,0x4b,0x58,0x4b,0x5e,0x4b,0x5e,0x4b,0x64,0x4b,0x6a, 0x4b,0x70,0x4b,0x76,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x8e,0x4b,0x94,0x4b,0x9a,0x4b,0x22,0x4b,0x22,0x00,0x02,0x00,0x06,0x02,0x46,0x02,0x47,0x00,0x00,0x04,0x63,0x04,0x64,0x00,0x02,0x04,0x66,0x04,0x66,0x00,0x04,0x04,0x6b,0x04,0x6b,0x00,0x05,0x04,0x6e,0x04,0x6e,0x00,0x06,0x04,0x70,0x04,0x70,0x00,0x07,0x00,0x02,0x00,0x12, 0x01,0xdb,0x01,0xdb,0x00,0x00,0x01,0xe5,0x01,0xe5,0x00,0x01,0x01,0xe7,0x01,0xe7,0x00,0x02,0x01,0xec,0x01,0xec,0x00,0x03,0x01,0xef,0x01,0xf0,0x00,0x04,0x01,0xf5,0x01,0xf5,0x00,0x06,0x01,0xfa,0x01,0xfa,0x00,0x07,0x02,0x02,0x02,0x02,0x00,0x08,0x02,0x04,0x02,0x07,0x00,0x09,0x02,0x0c,0x02,0x0c,0x00,0x0d,0x02,0x0f,0x02,0x10, 0x00,0x0e,0x02,0x15,0x02,0x15,0x00,0x10,0x02,0x1a,0x02,0x1a,0x00,0x11,0x02,0x22,0x02,0x22,0x00,0x12,0x02,0x24,0x02,0x27,0x00,0x13,0x02,0x31,0x02,0x31,0x00,0x17,0x02,0xcd,0x02,0xcd,0x00,0x18,0x05,0x07,0x05,0x07,0x00,0x19,0x00,0x01,0x00,0xd8,0x00,0xde,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4a,0x92,0x00,0x62, 0x4a,0x92,0x4a,0x98,0x4a,0x9e,0x4a,0xa4,0x4a,0xaa,0x4a,0xb0,0x4a,0xb6,0x4a,0xbc,0x4a,0xc2,0x4a,0xc8,0x4a,0xce,0x4a,0xd4,0x4a,0xda,0x4a,0xe0,0x4a,0xe6,0x4a,0xec,0x4a,0xe6,0x4a,0xf2,0x4a,0xf8,0x4a,0xfe,0x4b,0x04,0x4b,0x0a,0x4b,0x10,0x42,0x52,0x4b,0x16,0x4b,0x1c,0x4b,0x22,0x4b,0x28,0x4b,0x2e,0x4b,0x34,0x4b,0x3a,0x4b,0x40, 0x4b,0x46,0x4b,0x4c,0x4b,0x52,0x4b,0x58,0x4b,0x5e,0x4b,0x64,0x4b,0x6a,0x4b,0x70,0x4b,0x76,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x8e,0x4b,0x94,0x4b,0x9a,0x4b,0xa0,0x4b,0xa6,0x4b,0xac,0x4b,0xb2,0x4b,0xb8,0x4b,0x22,0x4b,0x22,0x4b,0x22,0x4b,0x22,0x4b,0x22,0x4b,0x22,0x4b,0x3a,0x4b,0x3a,0x4b,0x3a,0x4b,0x3a,0x4b,0x52,0x4b,0x52, 0x4b,0x52,0x4b,0x52,0x4b,0x76,0x4b,0x76,0x4b,0x76,0x4b,0x76,0x4b,0x76,0x4b,0x9a,0x4b,0x9a,0x4b,0x9a,0x4b,0x9a,0x4b,0xbe,0x4b,0xc4,0x4b,0xca,0x4b,0xb2,0x4b,0xd0,0x4b,0xb2,0x4b,0xd6,0x4b,0xdc,0x4b,0xe2,0x4b,0xe8,0x4b,0xee,0x4b,0xf4,0x4b,0xfa,0x4c,0x00,0x4c,0x06,0x4c,0x0c,0x4c,0x12,0x4c,0x18,0x4b,0x76,0x4c,0x1e,0x4c,0x24, 0x4c,0x2a,0x4c,0x30,0x00,0x01,0x00,0x01,0x06,0x9b,0x00,0x02,0x00,0x16,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a,0x00,0x69,0x00,0x6e,0x00,0x34,0x00,0x70,0x00,0x77,0x00,0x3a,0x00,0x79,0x00,0x81,0x00,0x42,0x00,0xa0,0x00,0xa1,0x00,0x4b,0x00,0xb1,0x00,0xb1,0x00,0x4d,0x00,0xba,0x00,0xba,0x00,0x4e,0x00,0xd6, 0x00,0xd6,0x00,0x4f,0x00,0xeb,0x00,0xeb,0x00,0x50,0x05,0x07,0x05,0x07,0x00,0x51,0x05,0x56,0x05,0x58,0x00,0x52,0x05,0x5a,0x05,0x5a,0x00,0x55,0x05,0x5e,0x05,0x5e,0x00,0x56,0x05,0x60,0x05,0x61,0x00,0x57,0x05,0x63,0x05,0x63,0x00,0x59,0x05,0x69,0x05,0x69,0x00,0x5a,0x05,0x6d,0x05,0x6d,0x00,0x5b,0x05,0x6f,0x05,0x6f,0x00,0x5c, 0x05,0x7a,0x05,0x7b,0x00,0x5d,0x05,0x8e,0x05,0x8f,0x00,0x5f,0x05,0x91,0x05,0x91,0x00,0x61,0x00,0x01,0x00,0x9c,0x00,0xa6,0x00,0x01,0x00,0x0c,0x00,0x22,0x00,0x05,0x00,0x00,0x4a,0xd6,0x00,0x00,0x4a,0xd6,0x00,0x00,0x26,0xc4,0x00,0x00,0x4a,0xdc,0x00,0x00,0x4a,0xe2,0x00,0x3c,0x4a,0xd2,0x4a,0xd8,0x4a,0xde,0x4a,0xe4,0x4a,0xea, 0x4a,0xf0,0x4a,0xf6,0x4a,0xfc,0x4b,0x02,0x4b,0x08,0x4b,0x0e,0x4b,0x14,0x4b,0x1a,0x4b,0x20,0x4b,0x26,0x4b,0x2c,0x4b,0x32,0x4b,0x2c,0x4b,0x38,0x4b,0x3e,0x4b,0x44,0x4b,0x4a,0x4b,0x50,0x4b,0x56,0x4b,0x5c,0x4b,0x62,0x4b,0x68,0x4b,0x6e,0x4b,0x74,0x4b,0x7a,0x4b,0x80,0x4b,0x86,0x4b,0x8c,0x4b,0x92,0x4b,0x98,0x4b,0x9e,0x4b,0xa4, 0x4b,0xaa,0x4b,0xb0,0x4b,0xb6,0x4b,0xbc,0x4b,0xc2,0x4b,0xc8,0x4b,0xce,0x4b,0xd4,0x4b,0xda,0x4b,0xe0,0x4b,0xe6,0x4b,0xec,0x4b,0xf2,0x4b,0xf8,0x4b,0xfe,0x4c,0x04,0x4c,0x0a,0x4c,0x10,0x4c,0x16,0x4c,0x1c,0x4c,0x22,0x4c,0x28,0x4c,0x2e,0x00,0x02,0x00,0x01,0x04,0x92,0x04,0x96,0x00,0x00,0x00,0x02,0x00,0x0a,0x00,0x24,0x00,0x3d, 0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a,0x00,0x79,0x00,0x79,0x00,0x34,0x00,0xd0,0x00,0xd0,0x00,0x35,0x00,0xe4,0x00,0xe4,0x00,0x36,0x00,0xe6,0x00,0xe6,0x00,0x37,0x00,0xe9,0x00,0xe9,0x00,0x38,0x05,0x83,0x05,0x83,0x00,0x39,0x05,0x88,0x05,0x88,0x00,0x3a,0x05,0x97,0x05,0x97,0x00,0x3b,0x00,0x01,0x0c,0xf8,0x0d,0x0e,0x00,0x02, 0x00,0x0c,0x00,0x2a,0x00,0x07,0x00,0x00,0x4b,0x64,0x00,0x00,0x4b,0x6a,0x00,0x01,0x2f,0x68,0x00,0x00,0x4b,0x6a,0x00,0x00,0x4b,0x6a,0x00,0x01,0x4b,0x70,0x00,0x01,0x2f,0x8c,0x03,0x33,0x4b,0x58,0x4b,0x5e,0x4b,0x64,0x4b,0x6a,0x4b,0x70,0x4b,0x76,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x8e,0x4b,0x94,0x4b,0x9a,0x4b,0xa0,0x4b,0xa6, 0x4b,0xac,0x4b,0xb2,0x4b,0xb8,0x4b,0xbe,0x4b,0xc4,0x4b,0xca,0x4b,0xd0,0x4b,0xd6,0x4b,0xdc,0x4b,0xe2,0x4b,0xe8,0x4b,0xee,0x4b,0xf4,0x4b,0xfa,0x4c,0x00,0x4c,0x06,0x4c,0x0c,0x4c,0x12,0x4c,0x18,0x4c,0x1e,0x4c,0x24,0x4c,0x2a,0x4c,0x30,0x4c,0x36,0x4c,0x3c,0x4c,0x42,0x4c,0x48,0x4c,0x4e,0x4c,0x54,0x4c,0x5a,0x4c,0x60,0x4c,0x66, 0x4c,0x6c,0x4c,0x72,0x4c,0x78,0x4c,0x7e,0x4c,0x84,0x4c,0x8a,0x4c,0x90,0x4c,0x96,0x4c,0x9c,0x4c,0xa2,0x4c,0xa8,0x4c,0xae,0x4c,0xb4,0x4c,0xba,0x4c,0xc0,0x4c,0xc6,0x4c,0xcc,0x4c,0xd2,0x4c,0xb4,0x4c,0xba,0x4c,0xd8,0x4c,0xde,0x4c,0xe4,0x4c,0xea,0x4c,0xe4,0x4c,0xea,0x4c,0xd8,0x4c,0xde,0x4c,0xf0,0x4c,0xf6,0x4c,0xfc,0x4d,0x02, 0x4c,0xd8,0x4c,0xde,0x4d,0x08,0x4d,0x0e,0x4c,0x9c,0x4c,0xa2,0x4c,0xb4,0x4c,0xba,0x4d,0x14,0x4d,0x1a,0x4d,0x20,0x4d,0x26,0x4d,0x2c,0x4d,0x32,0x4d,0x38,0x4d,0x3e,0x4d,0x44,0x4d,0x4a,0x4d,0x50,0x4d,0x56,0x4d,0x5c,0x4d,0x62,0x4d,0x68,0x4d,0x6e,0x4d,0x74,0x4d,0x7a,0x4d,0x80,0x4b,0x5e,0x4d,0x80,0x4b,0x5e,0x4b,0x70,0x4b,0x76, 0x4b,0x88,0x4b,0x8e,0x4d,0x86,0x4b,0xfa,0x4d,0x8c,0x4c,0x06,0x4d,0x92,0x4c,0x4e,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x4c,0xa8,0x4c,0xae,0x4c,0xc0,0x4c,0xc6,0x4c,0xc0,0x4c,0xc6,0x4c,0xc0,0x4c,0xc6,0x4c,0xc0,0x4c,0xc6,0x4d,0x98,0x4d,0x9e, 0x4d,0xa4,0x4d,0xaa,0x4d,0xb0,0x4d,0xb6,0x4d,0xbc,0x4d,0xc2,0x4c,0xd8,0x4c,0xde,0x4d,0x08,0x4d,0x0e,0x4d,0x08,0x4d,0x0e,0x4d,0x08,0x4d,0x0e,0x4d,0x08,0x4d,0x0e,0x4d,0x08,0x4d,0x0e,0x4d,0x38,0x4d,0x3e,0x4d,0x38,0x4d,0x3e,0x4d,0x38,0x4d,0x3e,0x4d,0x38,0x4d,0x3e,0x4d,0xc8,0x4d,0xce,0x4d,0xd4,0x4d,0xda,0x4c,0x00,0x4c,0x06, 0x4d,0xe0,0x4d,0xe6,0x4d,0xec,0x4d,0xf2,0x4d,0xf8,0x4d,0xfe,0x4d,0x80,0x4b,0x5e,0x4d,0x80,0x4b,0x5e,0x4d,0x8c,0x4c,0x06,0x4e,0x04,0x4e,0x0a,0x4e,0x10,0x4e,0x16,0x4d,0x68,0x4d,0x6e,0x4c,0x78,0x4c,0x7e,0x4d,0x80,0x4b,0x5e,0x4e,0x1c,0x4b,0x8e,0x4d,0x80,0x4b,0x5e,0x4e,0x1c,0x4b,0x8e,0x4e,0x1c,0x4b,0x8e,0x4e,0x22,0x4e,0x28, 0x4e,0x2e,0x4e,0x34,0x4e,0x3a,0x4e,0x40,0x4e,0x46,0x4b,0xbe,0x4d,0x8c,0x4c,0x06,0x4d,0x8c,0x4c,0x06,0x4d,0x8c,0x4c,0x06,0x4d,0x92,0x4c,0x4e,0x4d,0x92,0x4c,0x4e,0x4d,0x92,0x4c,0x4e,0x4c,0xf0,0x4c,0xf6,0x4b,0xdc,0x4b,0xe2,0x4e,0x4c,0x4e,0x52,0x4e,0x58,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4e,0x5e,0x4c,0x8a,0x4d,0x74,0x4d,0x7a, 0x4b,0x7c,0x4b,0x82,0x4e,0x64,0x4e,0x6a,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4c,0x0c,0x4c,0x12,0x4c,0x9c,0x4c,0xa2,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x4b,0xb8,0x4b,0xbe,0x4c,0x30,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4b,0x70,0x4b,0x76,0x4c,0xa8,0x4c,0xae,0x4e,0x7c,0x4b,0x76,0x4c,0xa8,0x4c,0xae,0x4e,0x82,0x4e,0x88, 0x4b,0x58,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4b,0x58,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4e,0x8e,0x4b,0x82,0x4e,0x94,0x4e,0x9a,0x4b,0x7c,0x4b,0x82,0x4b,0x88,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0xa0,0x4b,0xe2,0x4e,0xa6,0x4e,0xac,0x4b,0xdc,0x4b,0xe2,0x4e,0xb2,0x4e,0xb8,0x4b,0xdc,0x4b,0xe2, 0x4e,0xbe,0x4e,0xc4,0x4d,0x86,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4d,0x86,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4e,0xca,0x4c,0x2a,0x4d,0x14,0x4d,0x1a,0x4e,0xca,0x4c,0x2a,0x4e,0xd0,0x4e,0xd6,0x4e,0x58,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4c,0x3c,0x4c,0x42,0x4e,0xdc,0x4e,0xe2,0x4e,0xe8,0x4c,0x42, 0x4e,0xee,0x4e,0xf4,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4e,0x5e,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x4e,0x5e,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x4e,0xfa,0x4f,0x00,0x4f,0x06,0x4f,0x0c,0x4f,0x12,0x4f,0x18,0x4b,0x58,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4e,0x7c,0x4b,0x76,0x4c,0xa8,0x4c,0xae, 0x4e,0x7c,0x4b,0x76,0x4c,0xa8,0x4c,0xae,0x4b,0x88,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x4b,0xa0,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x4f,0x1e,0x4b,0xb2,0x4f,0x24,0x4c,0xde, 0x4f,0x2a,0x4f,0x30,0x4c,0xd8,0x4c,0xde,0x4f,0x36,0x4f,0x3c,0x4f,0x42,0x4f,0x48,0x4f,0x4e,0x4f,0x54,0x4f,0x5a,0x4f,0x60,0x4f,0x66,0x4f,0x6c,0x4f,0x72,0x4f,0x78,0x4b,0xb8,0x4b,0xbe,0x4c,0xe4,0x4c,0xea,0x4f,0x7e,0x4f,0x84,0x4f,0x4e,0x4f,0x54,0x4b,0xd0,0x4b,0xd6,0x4c,0xd8,0x4c,0xde,0x4c,0xd8,0x4c,0xde,0x4b,0xdc,0x4b,0xe2, 0x4d,0x98,0x4d,0x9e,0x4b,0xf4,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4b,0xf4,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4c,0x00,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4c,0x00,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4c,0x24,0x4c,0x2a,0x4d,0x14,0x4d,0x1a,0x4e,0x58,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4c,0x3c,0x4c,0x42,0x4d,0x2c,0x4d,0x32,0x4d,0x92,0x4c,0x4e, 0x4d,0x38,0x4d,0x3e,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4c,0x60,0x4c,0x66,0x4d,0x50,0x4d,0x56,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4f,0x8a,0x4f,0x90,0x4f,0x96,0x4c,0x66,0x4d,0x50,0x4d,0x56,0x4f,0x96,0x4c,0x66,0x4d,0x50,0x4d,0x56, 0x4f,0x96,0x4c,0x66,0x4d,0x50,0x4d,0x56,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4f,0x9c,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x4f,0xb4,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x4b,0x58,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4f,0xcc,0x4f,0xd2,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96, 0x4d,0x80,0x4b,0x5e,0x4f,0xd8,0x4f,0xde,0x4d,0x80,0x4b,0x5e,0x4f,0xe4,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4f,0xe4,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4f,0xe4,0x4c,0x96,0x4d,0x80,0x4b,0x5e,0x4c,0x90,0x4c,0x96, 0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4f,0xea,0x4f,0xf0,0x4f,0xf6,0x4f,0xfc,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x50,0x02,0x50,0x08,0x50,0x0e,0x50,0x14,0x4e,0x1c,0x4b,0x8e,0x50,0x1a,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6, 0x4e,0x46,0x4b,0xbe,0x50,0x20,0x50,0x26,0x4b,0xb8,0x4b,0xbe,0x4c,0xe4,0x4c,0xea,0x4c,0x00,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4e,0x82,0x4e,0x88,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x50,0x2c,0x4d,0x0e, 0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x50,0x32,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x50,0x32,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x50,0x32,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x50,0x32,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x4f,0x9c,0x4f,0xa2,0x4f,0xa8,0x4f,0xae,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e, 0x50,0x38,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x50,0x38,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x50,0x38,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x50,0x38,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x50,0x38,0x4f,0xba,0x4f,0xc0,0x4f,0xc6,0x4c,0x78,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e, 0x4c,0x3c,0x4c,0x42,0x4d,0x2c,0x4d,0x32,0x50,0x3e,0x50,0x44,0x50,0x4a,0x50,0x50,0x4b,0x88,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4b,0x58,0x4b,0x5e,0x4c,0x90,0x4c,0x96,0x50,0x56,0x4b,0x6a,0x4c,0x9c,0x4c,0xa2,0x4b,0x64,0x4b,0x6a,0x4c,0x9c,0x4c,0xa2,0x4b,0x64,0x4b,0x6a,0x4c,0x9c,0x4c,0xa2,0x4e,0x7c,0x4b,0x76,0x4c,0xa8,0x4c,0xae, 0x4e,0x8e,0x4b,0x82,0x4c,0xb4,0x4c,0xba,0x4b,0x7c,0x4b,0x82,0x4c,0xb4,0x4c,0xba,0x4b,0x7c,0x4b,0x82,0x4c,0xb4,0x4c,0xba,0x4b,0x7c,0x4b,0x82,0x4c,0xb4,0x4c,0xba,0x4b,0x7c,0x4b,0x82,0x4c,0xb4,0x4c,0xba,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4b,0x88,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6, 0x4b,0x88,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x50,0x5c,0x4b,0x9a,0x50,0x62,0x4c,0xd2,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x4f,0x1e,0x4b,0xb2,0x4c,0xd8,0x4c,0xde,0x4b,0xac,0x4b,0xb2,0x4c,0xd8,0x4c,0xde,0x4f,0x1e,0x4b,0xb2,0x4f,0x24,0x4c,0xde,0x4b,0xac,0x4b,0xb2,0x4c,0xd8,0x4c,0xde, 0x4b,0xac,0x4b,0xb2,0x4c,0xd8,0x4c,0xde,0x50,0x68,0x50,0x6e,0x50,0x74,0x50,0x7a,0x50,0x80,0x50,0x86,0x50,0x8c,0x50,0x92,0x50,0x98,0x4b,0xd6,0x4f,0x24,0x4c,0xde,0x4b,0xd0,0x4b,0xd6,0x4c,0xd8,0x4c,0xde,0x4b,0xd0,0x4b,0xd6,0x4c,0xd8,0x4c,0xde,0x4b,0xdc,0x4b,0xe2,0x50,0x9e,0x50,0xa4,0x4e,0xa0,0x4b,0xe2,0x50,0xaa,0x50,0xb0, 0x4b,0xdc,0x4b,0xe2,0x50,0xb6,0x50,0xbc,0x4b,0xdc,0x4b,0xe2,0x4e,0xa6,0x4e,0xac,0x50,0xc2,0x4b,0xee,0x4c,0xfc,0x4d,0x02,0x50,0xc2,0x4b,0xee,0x4c,0xfc,0x4d,0x02,0x4b,0xe8,0x4b,0xee,0x4c,0xfc,0x4d,0x02,0x4d,0x86,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4b,0xf4,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4b,0xf4,0x4b,0xfa,0x4c,0xd8,0x4c,0xde, 0x4b,0xf4,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x50,0x2c,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x50,0xc8,0x4c,0x12,0x4c,0x9c,0x4c,0xa2,0x50,0xc8,0x4c,0x12,0x4c,0x9c,0x4c,0xa2,0x4e,0xca,0x4c,0x2a,0x4d,0x14,0x4d,0x1a, 0x4c,0x24,0x4c,0x2a,0x4d,0x14,0x4d,0x1a,0x4e,0xca,0x4c,0x2a,0x4d,0x14,0x4d,0x1a,0x4c,0x24,0x4c,0x2a,0x50,0xce,0x50,0xd4,0x4e,0x58,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4c,0x30,0x4c,0x36,0x4d,0x20,0x4d,0x26,0x4e,0x58,0x4c,0x36,0x50,0xda,0x4d,0x26,0x4e,0x58,0x4c,0x36,0x50,0xda,0x4d,0x26,0x4e,0x58,0x4c,0x36,0x4d,0x20,0x4d,0x26, 0x4e,0xe8,0x4c,0x42,0x4d,0x2c,0x4d,0x32,0x4c,0x3c,0x4c,0x42,0x4d,0x2c,0x4d,0x32,0x4c,0x3c,0x4c,0x42,0x50,0xe0,0x50,0xe6,0x4c,0x3c,0x4c,0x42,0x50,0xec,0x50,0xf2,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4c,0x48,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e, 0x4d,0x92,0x4c,0x4e,0x50,0xf8,0x4d,0x3e,0x50,0xfe,0x4c,0x5a,0x4d,0x44,0x4d,0x4a,0x4c,0x54,0x4c,0x5a,0x4d,0x44,0x4d,0x4a,0x4f,0x96,0x4c,0x66,0x4d,0x50,0x4d,0x56,0x4c,0x60,0x4c,0x66,0x4d,0x50,0x4d,0x56,0x51,0x04,0x4c,0x72,0x4d,0x5c,0x4d,0x62,0x51,0x04,0x4c,0x72,0x4d,0x5c,0x4d,0x62,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e, 0x4e,0x5e,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x4c,0x84,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x4c,0x84,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x4c,0xd8,0x4c,0xde,0x4d,0x2c,0x4d,0x32,0x4d,0x50,0x4d,0x56,0x4d,0x68,0x4d,0x6e,0x4c,0x90,0x4c,0x96,0x51,0x0a,0x4f,0x90,0x4c,0x9c,0x4c,0xa2,0x51,0x10,0x51,0x16,0x51,0x1c,0x51,0x22,0x4c,0x9c,0x4c,0xa2, 0x51,0x1c,0x51,0x22,0x4c,0x9c,0x4c,0xa2,0x4e,0x82,0x4e,0x88,0x51,0x28,0x51,0x2e,0x51,0x34,0x51,0x3a,0x4b,0x7c,0x4b,0x82,0x51,0x40,0x51,0x46,0x51,0x4c,0x51,0x52,0x51,0x34,0x51,0x3a,0x51,0x58,0x51,0x5e,0x51,0x64,0x51,0x6a,0x51,0x70,0x51,0x76,0x4b,0x94,0x4b,0x9a,0x51,0x7c,0x51,0x82,0x4c,0x54,0x4c,0x5a,0x51,0x88,0x51,0x8e, 0x51,0x94,0x51,0x9a,0x4d,0xbc,0x4d,0xc2,0x4b,0xd0,0x4b,0xd6,0x4c,0xd8,0x4c,0xde,0x51,0xa0,0x51,0xa6,0x51,0xac,0x51,0xb2,0x51,0xb8,0x51,0xbe,0x51,0x28,0x51,0x2e,0x4c,0xd8,0x4c,0xde,0x4c,0x00,0x4c,0x06,0x51,0xc4,0x51,0xca,0x51,0xd0,0x51,0xd6,0x51,0xdc,0x51,0xe2,0x4c,0x9c,0x4c,0xa2,0x51,0xe8,0x51,0xee,0x51,0xf4,0x51,0xfa, 0x52,0x00,0x52,0x06,0x52,0x0c,0x52,0x12,0x4e,0xbe,0x4e,0xc4,0x4d,0x2c,0x4d,0x32,0x4c,0x3c,0x4c,0x42,0x4d,0x2c,0x4d,0x32,0x4c,0x3c,0x4c,0x42,0x52,0x18,0x52,0x1e,0x52,0x24,0x52,0x2a,0x52,0x30,0x52,0x36,0x4c,0x78,0x4c,0x7e,0x4c,0x84,0x4c,0x8a,0x4d,0x74,0x4d,0x7a,0x52,0x3c,0x52,0x42,0x52,0x48,0x52,0x4e,0x52,0x54,0x52,0x5a, 0x52,0x60,0x52,0x66,0x52,0x6c,0x52,0x72,0x52,0x78,0x52,0x7e,0x52,0x84,0x52,0x8a,0x52,0x90,0x52,0x96,0x52,0x9c,0x52,0xa2,0x52,0xa8,0x52,0xae,0x52,0xb4,0x52,0xba,0x52,0xc0,0x52,0xc6,0x52,0xcc,0x52,0xd2,0x52,0xd8,0x52,0xde,0x52,0xe4,0x52,0xea,0x4d,0x80,0x4b,0x5e,0x52,0xf0,0x52,0xf6,0x52,0xfc,0x53,0x02,0x53,0x08,0x53,0x0e, 0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x50,0x4a,0x50,0x50,0x53,0x14,0x4d,0xda,0x53,0x1a,0x53,0x20,0x53,0x26,0x53,0x2c,0x53,0x32,0x53,0x38,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x50,0x98,0x4b,0xd6,0x4f,0x24,0x4c,0xde,0x4c,0x00,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06, 0x4d,0x08,0x4d,0x0e,0x53,0x3e,0x52,0x42,0x53,0x44,0x53,0x4a,0x4d,0xbc,0x4d,0xc2,0x53,0x50,0x52,0x8a,0x53,0x56,0x53,0x5c,0x53,0x62,0x53,0x68,0x4e,0x76,0x4b,0xa6,0x4c,0xb4,0x4c,0xba,0x53,0x6e,0x53,0x74,0x53,0x7a,0x53,0x80,0x4d,0x86,0x4b,0xfa,0x4c,0xd8,0x4c,0xde,0x4d,0x80,0x4b,0x5e,0x52,0xf0,0x52,0xf6,0x4d,0x80,0x4b,0x5e, 0x52,0xf0,0x52,0xf6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x1c,0x4b,0x8e,0x4c,0xc0,0x4c,0xc6,0x4e,0x46,0x4b,0xbe,0x53,0x86,0x53,0x8c,0x53,0x92,0x53,0x98,0x53,0x9e,0x53,0xa4,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4e,0xca,0x4c,0x2a,0x4d,0x14,0x4d,0x1a,0x4e,0xca,0x4c,0x2a, 0x53,0xaa,0x53,0xb0,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x92,0x4c,0x4e,0x4d,0x38,0x4d,0x3e,0x4d,0x44,0x4d,0x4a,0x53,0xb6,0x53,0xbc,0x4f,0x1e,0x4b,0xb2,0x4f,0x24,0x4c,0xde,0x53,0x7a,0x53,0x80,0x51,0x10,0x51,0x16,0x53,0xc2,0x53,0xc8,0x51,0xdc,0x51,0xe2,0x53,0xce,0x53,0xd4,0x4d,0x80,0x4b,0x5e,0x52,0xf0,0x52,0xf6, 0x4d,0x8c,0x4c,0x06,0x4d,0x08,0x4d,0x0e,0x4e,0x70,0x4c,0x7e,0x4d,0x68,0x4d,0x6e,0x4d,0xf8,0x4d,0xfe,0x4c,0xb4,0x4c,0xba,0x4c,0x9c,0x4c,0xa2,0x53,0xda,0x53,0xe0,0x53,0xe6,0x53,0xec,0x53,0xf2,0x53,0xf8,0x53,0xfe,0x54,0x04,0x53,0xfe,0x54,0x04,0x50,0x4a,0x50,0x50,0x54,0x0a,0x54,0x10,0x54,0x16,0x54,0x1c,0x54,0x22,0x54,0x28, 0x54,0x2e,0x54,0x34,0x4c,0x3c,0x4c,0x42,0x54,0x3a,0x54,0x40,0x53,0xfe,0x54,0x04,0x4c,0xb4,0x4c,0xba,0x54,0x46,0x54,0x4c,0x54,0x52,0x54,0x58,0x53,0xce,0x53,0xd4,0x4d,0x38,0x4d,0x3e,0x4c,0xd8,0x4c,0xde,0x4c,0xd8,0x4c,0xde,0x54,0x5e,0x54,0x64,0x54,0x6a,0x54,0x70,0x54,0x76,0x54,0x7c,0x54,0x82,0x54,0x88,0x54,0x22,0x54,0x28, 0x54,0x8e,0x54,0x94,0x54,0x9a,0x54,0xa0,0x4c,0xfc,0x4d,0x02,0x4c,0xfc,0x4d,0x02,0x4c,0xfc,0x4d,0x02,0x4c,0xd8,0x4c,0xde,0x54,0xa6,0x54,0xac,0x54,0xb2,0x54,0xb8,0x4d,0x08,0x4d,0x0e,0x54,0xbe,0x54,0xc4,0x54,0xca,0x54,0xd0,0x54,0xd6,0x54,0xdc,0x54,0xe2,0x4f,0x6c,0x54,0xe2,0x4f,0x6c,0x54,0xe8,0x54,0xee,0x4d,0x14,0x4d,0x1a, 0x4d,0x14,0x4d,0x1a,0x54,0xf4,0x54,0xfa,0x55,0x00,0x55,0x06,0x4c,0x90,0x4c,0x96,0x4c,0x90,0x4c,0x96,0x55,0x0c,0x55,0x12,0x55,0x18,0x55,0x1e,0x55,0x24,0x55,0x2a,0x55,0x30,0x55,0x36,0x55,0x3c,0x55,0x42,0x55,0x3c,0x55,0x42,0x4d,0x2c,0x4d,0x32,0x55,0x48,0x55,0x4e,0x51,0xe8,0x51,0xee,0x52,0x78,0x52,0x7e,0x52,0x54,0x52,0x5a, 0x4d,0x50,0x4d,0x56,0x55,0x54,0x55,0x5a,0x55,0x60,0x55,0x66,0x55,0x6c,0x55,0x72,0x55,0x78,0x55,0x7e,0x53,0x44,0x53,0x4a,0x55,0x84,0x55,0x8a,0x55,0x90,0x55,0x96,0x55,0x9c,0x55,0xa2,0x55,0xa8,0x55,0xae,0x55,0xb4,0x55,0xba,0x55,0xc0,0x55,0xc6,0x55,0xcc,0x55,0xd2,0x55,0xd8,0x55,0xde,0x4c,0x9c,0x4c,0xa2,0x4d,0x38,0x4d,0x3e, 0x55,0xe4,0x4e,0x40,0x55,0xea,0x55,0xf0,0x55,0xf6,0x55,0xfc,0x53,0xfe,0x54,0x04,0x55,0x90,0x55,0x96,0x55,0x9c,0x55,0xa2,0x56,0x02,0x56,0x08,0x56,0x0e,0x56,0x14,0x56,0x1a,0x56,0x20,0x56,0x26,0x56,0x2c,0x56,0x32,0x56,0x38,0x4c,0x00,0x4c,0x06,0x56,0x3e,0x56,0x44,0x4d,0x08,0x4d,0x0e,0x4c,0x78,0x4c,0x7e,0x56,0x4a,0x56,0x50, 0x55,0xcc,0x55,0xd2,0x4c,0xf0,0x4c,0xf6,0x54,0x5e,0x54,0x64,0x56,0x56,0x56,0x5c,0x55,0xea,0x55,0xf0,0x56,0x62,0x56,0x68,0x55,0x84,0x55,0x8a,0x52,0x78,0x52,0x7e,0x53,0x7a,0x53,0x80,0x56,0x6e,0x56,0x74,0x56,0x6e,0x56,0x74,0x4b,0x58,0x4b,0x5e,0x56,0x7a,0x56,0x80,0x56,0x86,0x56,0x8c,0x4b,0xdc,0x4b,0xe2,0x56,0x92,0x56,0x98, 0x4d,0x20,0x4d,0x26,0x4d,0x74,0x4d,0x7a,0x56,0x9e,0x56,0xa4,0x4c,0x9c,0x4c,0xa2,0x56,0xaa,0x56,0xb0,0x4c,0xcc,0x4c,0xd2,0x52,0xd8,0x52,0xde,0x56,0xb6,0x56,0xbc,0x4c,0x9c,0x4c,0xa2,0x4d,0x14,0x4d,0x1a,0x54,0xf4,0x54,0xfa,0x56,0xc2,0x56,0xc8,0x4d,0x2c,0x4d,0x32,0x4d,0x74,0x4d,0x7a,0x53,0xda,0x53,0xe0,0x56,0xce,0x56,0xd4, 0x56,0xda,0x56,0xe0,0x56,0xe6,0x56,0xec,0x56,0xf2,0x56,0xf8,0x56,0xfe,0x57,0x04,0x4c,0x48,0x4c,0x4e,0x57,0x0a,0x57,0x10,0x57,0x16,0x57,0x1c,0x4c,0x9c,0x4c,0xa2,0x4f,0xa8,0x4f,0xae,0x4c,0xcc,0x4c,0xd2,0x57,0x22,0x57,0x28,0x57,0x2e,0x57,0x34,0x57,0x3a,0x57,0x40,0x57,0x46,0x57,0x4c,0x57,0x52,0x57,0x58,0x4c,0x9c,0x4c,0xa2, 0x4d,0x14,0x4d,0x1a,0x57,0x5e,0x57,0x64,0x57,0x6a,0x57,0x70,0x57,0x76,0x57,0x7c,0x4d,0x5c,0x4d,0x62,0x4d,0x74,0x4d,0x7a,0x57,0x82,0x57,0x88,0x57,0x8e,0x57,0x94,0x53,0xfe,0x54,0x04,0x57,0x9a,0x57,0xa0,0x4c,0x0c,0x4c,0x12,0x57,0xa6,0x57,0xac,0x57,0xb2,0x57,0xb8,0x57,0xbe,0x57,0xc4,0x53,0xe6,0x53,0xec,0x55,0x18,0x55,0x1e, 0x57,0xca,0x57,0xd0,0x53,0x44,0x53,0x4a,0x57,0xd6,0x57,0xdc,0x54,0x16,0x54,0x1c,0x4d,0xec,0x4d,0xf2,0x57,0xe2,0x57,0xe8,0x57,0xee,0x57,0xf4,0x4c,0x3c,0x4c,0x42,0x4b,0x64,0x4b,0x6a,0x55,0x0c,0x55,0x12,0x4b,0xb8,0x4b,0xbe,0x57,0xfa,0x58,0x00,0x53,0x32,0x53,0x38,0x56,0x92,0x56,0x98,0x58,0x06,0x58,0x0c,0x58,0x12,0x58,0x18, 0x51,0xac,0x51,0xb2,0x58,0x1e,0x58,0x24,0x58,0x2a,0x58,0x30,0x58,0x36,0x58,0x3c,0x58,0x42,0x58,0x48,0x51,0xdc,0x51,0xe2,0x56,0x92,0x56,0x98,0x58,0x4e,0x58,0x54,0x58,0x5a,0x58,0x60,0x58,0x66,0x58,0x6c,0x58,0x72,0x58,0x78,0x4c,0xf0,0x4c,0xea,0x00,0x02,0x00,0x03,0x04,0xad,0x04,0xaf,0x00,0x00,0x07,0x5d,0x07,0x5f,0x00,0x03, 0x07,0xf0,0x07,0xf0,0x00,0x06,0x00,0x02,0x00,0x2a,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a,0x00,0x62,0x00,0x81,0x00,0x34,0x00,0x89,0x00,0x89,0x00,0x54,0x00,0x91,0x00,0x92,0x00,0x55,0x00,0xa0,0x00,0xa1,0x00,0x57,0x00,0xa7,0x00,0xa7,0x00,0x59,0x00,0xad,0x00,0xb1,0x00,0x5a,0x00,0xba,0x00,0xbb,0x00,0x5f, 0x00,0xc7,0x00,0xd6,0x00,0x61,0x00,0xe1,0x00,0xe6,0x00,0x71,0x00,0xe8,0x00,0xed,0x00,0x77,0x00,0xf7,0x01,0x00,0x00,0x7d,0x01,0x03,0x01,0x2b,0x00,0x87,0x01,0x39,0x01,0x3b,0x00,0xb0,0x01,0x45,0x01,0x84,0x00,0xb3,0x01,0x8c,0x01,0x93,0x00,0xf3,0x02,0x40,0x02,0x43,0x00,0xfb,0x02,0x57,0x02,0xb0,0x00,0xff,0x02,0xcd,0x02,0xce, 0x01,0x59,0x02,0xe1,0x03,0x78,0x01,0x5b,0x04,0xb0,0x04,0xe2,0x01,0xf3,0x04,0xe6,0x04,0xe9,0x02,0x26,0x04,0xee,0x04,0xfe,0x02,0x2a,0x05,0x07,0x05,0x07,0x02,0x3b,0x05,0x0c,0x05,0x46,0x02,0x3c,0x05,0x4b,0x05,0x4c,0x02,0x77,0x05,0x4f,0x05,0x50,0x02,0x79,0x05,0x56,0x05,0xb2,0x02,0x7b,0x06,0xac,0x06,0xad,0x02,0xd8,0x07,0x3e, 0x07,0x43,0x02,0xda,0x07,0xe1,0x07,0xe2,0x02,0xe0,0x07,0xe4,0x07,0xeb,0x02,0xe2,0x07,0xf7,0x08,0x05,0x02,0xea,0x08,0x07,0x08,0x26,0x02,0xf9,0x0a,0x43,0x0a,0x43,0x03,0x19,0x0a,0xbf,0x0a,0xcc,0x03,0x1a,0x0a,0xe5,0x0a,0xe5,0x03,0x28,0x0a,0xe7,0x0a,0xed,0x03,0x29,0x0a,0xf4,0x0a,0xf4,0x03,0x30,0x0a,0xf7,0x0a,0xf7,0x03,0x31, 0x11,0x8c,0x11,0x8c,0x03,0x32,0x00,0x01,0x00,0xa4,0x00,0xaa,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4a,0x8e,0x00,0x48,0x4a,0x8e,0x4a,0x94,0x4a,0x9a,0x4a,0xa0,0x4a,0xa6,0x4a,0xa6,0x4a,0xac,0x4a,0xb2,0x4a,0xb8,0x4a,0xbe,0x4a,0xc4,0x4a,0xca,0x4a,0xd0,0x4a,0xd6,0x4a,0xdc,0x4a,0xe2,0x4a,0xdc,0x4a,0xe8,0x4a,0xee, 0x4a,0xf4,0x4a,0xfa,0x4b,0x00,0x4b,0x06,0x3a,0xbc,0x3a,0xbc,0x3a,0xbc,0x4b,0x0c,0x4b,0x12,0x4b,0x18,0x4b,0x1e,0x4b,0x24,0x4b,0x2a,0x4b,0x30,0x4b,0x36,0x4b,0x3c,0x4b,0x42,0x4b,0x48,0x4b,0x4e,0x4b,0x54,0x4b,0x5a,0x4b,0x60,0x4b,0x66,0x4b,0x6c,0x4b,0x72,0x4b,0x78,0x4b,0x7e,0x4b,0x84,0x4b,0x8a,0x4b,0x90,0x4b,0x96,0x4b,0x9c, 0x4b,0xa2,0x4b,0x60,0x4b,0x60,0x4b,0x60,0x4b,0x84,0x4b,0x84,0x4a,0xdc,0x4a,0xdc,0x4a,0xdc,0x4a,0xfa,0x4a,0xfa,0x4a,0xfa,0x4b,0x84,0x4a,0xdc,0x4b,0x60,0x4a,0xdc,0x4b,0x60,0x4a,0xfa,0x4b,0x84,0x4a,0xfa,0x4b,0x84,0x00,0x01,0x00,0x01,0x04,0x7a,0x00,0x02,0x00,0x0b,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a, 0x00,0x79,0x00,0x7a,0x00,0x34,0x00,0x7d,0x00,0x7f,0x00,0x36,0x00,0xaf,0x00,0xaf,0x00,0x39,0x00,0xd0,0x00,0xd0,0x00,0x3a,0x00,0xd2,0x00,0xd3,0x00,0x3b,0x00,0xd5,0x00,0xd5,0x00,0x3d,0x01,0x78,0x01,0x79,0x00,0x3e,0x02,0x83,0x02,0x86,0x00,0x40,0x02,0x9b,0x02,0x9e,0x00,0x44,0x00,0x01,0x00,0x58,0x00,0x5e,0x00,0x01,0x00,0x0c, 0x00,0x12,0x00,0x01,0x00,0x00,0x1e,0xc0,0x00,0x22,0x4a,0xb8,0x4a,0xbe,0x17,0x16,0x2b,0x02,0x19,0xec,0x4a,0xc4,0x18,0x30,0x4a,0xca,0x4a,0xd0,0x4a,0xd6,0x4a,0xdc,0x17,0x70,0x4a,0xe2,0x23,0xb2,0x4a,0xe8,0x4a,0xee,0x4a,0xf4,0x4a,0xfa,0x4b,0x00,0x4b,0x06,0x4b,0x0c,0x21,0x54,0x4b,0x12,0x4b,0x18,0x4b,0x1e,0x32,0xe8,0x4b,0x06, 0x4b,0x06,0x32,0xe8,0x32,0xe8,0x19,0xec,0x4a,0xe2,0x4a,0xe2,0x4b,0x06,0x00,0x01,0x00,0x01,0x04,0x85,0x00,0x02,0x00,0x17,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x26,0x00,0x26,0x00,0x01,0x00,0x28,0x00,0x28,0x00,0x02,0x00,0x2a,0x00,0x2a,0x00,0x03,0x00,0x2c,0x00,0x2c,0x00,0x04,0x00,0x2e,0x00,0x2f,0x00,0x05,0x00,0x31,0x00,0x32, 0x00,0x07,0x00,0x35,0x00,0x38,0x00,0x09,0x00,0x44,0x00,0x44,0x00,0x0d,0x00,0x46,0x00,0x46,0x00,0x0e,0x00,0x48,0x00,0x48,0x00,0x0f,0x00,0x4a,0x00,0x4a,0x00,0x10,0x00,0x4c,0x00,0x4c,0x00,0x11,0x00,0x4e,0x00,0x4f,0x00,0x12,0x00,0x51,0x00,0x52,0x00,0x14,0x00,0x55,0x00,0x58,0x00,0x16,0x00,0x74,0x00,0x74,0x00,0x1a,0x00,0x76, 0x00,0x76,0x00,0x1b,0x00,0x7e,0x00,0x7e,0x00,0x1c,0x00,0x80,0x00,0x80,0x00,0x1d,0x00,0xcd,0x00,0xcd,0x00,0x1e,0x00,0xd3,0x00,0xd4,0x00,0x1f,0x01,0x0f,0x01,0x0f,0x00,0x21,0x00,0x01,0x06,0x78,0x06,0x7e,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x4a,0x3e,0x03,0x32,0x4a,0x3e,0x4a,0x44,0x4a,0x4a,0x4a,0x44,0x1d,0x98, 0x4a,0x50,0x4a,0x56,0x4a,0x5c,0x4a,0x50,0x4a,0x62,0x4a,0x68,0x4a,0x6e,0x4a,0x74,0x4a,0x7a,0x4a,0x80,0x4a,0x50,0x4a,0x86,0x4a,0x8c,0x4a,0x92,0x4a,0x98,0x1d,0x98,0x16,0x2a,0x4a,0x9e,0x4a,0x68,0x4a,0xa4,0x4a,0xaa,0x1b,0xfa,0x4a,0xb0,0x4a,0xb6,0x4a,0xbc,0x16,0x7e,0x19,0x24,0x4a,0xc2,0x4a,0xc8,0x4a,0x50,0x4a,0xce,0x4a,0xd4, 0x19,0x12,0x4a,0xda,0x4a,0xc8,0x16,0x7e,0x4a,0xe0,0x4a,0xe6,0x19,0x12,0x4a,0x98,0x4a,0xec,0x4a,0xf2,0x4a,0xf8,0x4a,0xfe,0x4b,0x04,0x4b,0x0a,0x16,0x7e,0x4a,0x3e,0x4a,0x3e,0x4b,0x10,0x1d,0x98,0x4b,0x16,0x4a,0x80,0x1d,0x98,0x1b,0xfa,0x1b,0xfa,0x1b,0xfa,0x1b,0xfa,0x1b,0xfa,0x1b,0xfa,0x4b,0x1c,0x16,0x7e,0x16,0x7e,0x16,0x7e, 0x16,0x7e,0x19,0x12,0x19,0x12,0x19,0x12,0x19,0x12,0x4a,0xc8,0x16,0x7e,0x16,0x7e,0x16,0x7e,0x16,0x7e,0x16,0x7e,0x4a,0xf2,0x4a,0xf2,0x4a,0xf2,0x4a,0xf2,0x17,0xe0,0x4a,0xda,0x4a,0x80,0x4b,0x22,0x16,0x7e,0x4b,0x28,0x4a,0x3e,0x4a,0x3e,0x4a,0x80,0x4b,0x2e,0x4b,0x34,0x4b,0x0a,0x4a,0xa4,0x4a,0x3e,0x1d,0x98,0x4a,0x3e,0x1d,0x98, 0x1d,0x98,0x4a,0x50,0x19,0x24,0x4a,0x50,0x4b,0x3a,0x4a,0x80,0x4a,0x80,0x4a,0x80,0x1d,0x98,0x1d,0x98,0x1d,0x98,0x19,0x12,0x4a,0x6e,0x4a,0x62,0x4a,0x92,0x4a,0x98,0x4a,0xaa,0x16,0x7e,0x4b,0x40,0x4b,0x46,0x4a,0xa4,0x4b,0x0a,0x19,0x36,0x4b,0x4c,0x4a,0x56,0x4a,0xc2,0x4a,0x50,0x4b,0x52,0x4b,0x58,0x4a,0x4a,0x4a,0xb6,0x4a,0x4a, 0x4a,0xb6,0x4a,0xbc,0x4a,0x3e,0x1b,0xfa,0x4b,0x5e,0x29,0x80,0x4a,0x44,0x4a,0xbc,0x4a,0x44,0x4b,0x64,0x4b,0x6a,0x1d,0x98,0x16,0x7e,0x4a,0x6e,0x19,0x12,0x4a,0x6e,0x19,0x12,0x4a,0x6e,0x19,0x12,0x4a,0x7a,0x4a,0xc8,0x4a,0x7a,0x4a,0xc8,0x4a,0x80,0x16,0x7e,0x4a,0x8c,0x19,0x12,0x4a,0x8c,0x19,0x12,0x4a,0x92,0x4a,0x98,0x47,0x32, 0x4b,0x70,0x4a,0x98,0x4a,0xec,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x4a,0xaa,0x16,0x7e,0x4a,0xaa,0x16,0x7e,0x4b,0x76,0x4b,0x7c,0x4b,0x82,0x4a,0x3e,0x1b,0xfa,0x4a,0x4a,0x4a,0xb6,0x4a,0x4a,0x4a,0xb6,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x4a,0x56,0x4a,0xc2,0x4a,0x56,0x4a,0xc2,0x4b,0x88,0x4a,0xc2, 0x4a,0x5c,0x4a,0xc8,0x4a,0x5c,0x4a,0xc8,0x4a,0x50,0x19,0x12,0x4a,0x50,0x19,0x12,0x4a,0x50,0x4b,0x8e,0x2c,0x50,0x4b,0x94,0x4a,0x62,0x4a,0xce,0x4a,0x68,0x1d,0xda,0x16,0x4e,0x4b,0x1c,0x4b,0x9a,0x4a,0x7a,0x4a,0xaa,0x4b,0xa0,0x4b,0xa6,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x8c,0x4b,0x8e,0x4a,0x92,0x4a,0x98,0x4a,0x98, 0x4a,0xec,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x4b,0x64,0x4b,0xac,0x4a,0x9e,0x4a,0xfe,0x4a,0xa4,0x4b,0x0a,0x19,0x12,0x4a,0x9e,0x4a,0xfe,0x4a,0x9e,0x4a,0xfe,0x4a,0x9e,0x4a,0xfe,0x4a,0xa4,0x4b,0x0a,0x4a,0x80,0x16,0x7e,0x1d,0x98,0x4a,0xf2,0x4a,0x3e,0x4b,0xb2,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa, 0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x4b,0xb2,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x4b,0xb2,0x1c,0x8a,0x4b,0xb8,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e, 0x1c,0x8a,0x4b,0xb8,0x19,0x36,0x19,0x12,0x4b,0xbe,0x4b,0xc4,0x4b,0xca,0x4b,0xd0,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4b,0xd6,0x4b,0xdc,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4b,0xe2,0x4b,0xe8,0x4b,0xee,0x4a,0xbc, 0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x4b,0xf4,0x4a,0xbc,0x4b,0xfa,0x4c,0x00,0x4a,0xa4,0x4b,0x0a,0x4a,0xa4,0x4b,0x0a,0x4c,0x06,0x4c,0x0c,0x4a,0xf2,0x16,0x2a,0x3e,0x62,0x4c,0x12,0x4a,0x3e,0x4a,0xd4,0x4a,0x44,0x4a,0xb0,0x4c,0x18,0x4c,0x1e,0x4c,0x24,0x4c,0x2a, 0x42,0xa0,0x4c,0x30,0x4a,0x44,0x4a,0xbc,0x4c,0x36,0x4a,0xaa,0x4c,0x3c,0x4c,0x42,0x4c,0x48,0x4a,0xaa,0x4c,0x4e,0x23,0x32,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x4c,0x54,0x4c,0x54,0x4c,0x5a,0x4c,0x60,0x4c,0x66,0x4c,0x12,0x19,0x36,0x19,0x24,0x4a,0x56,0x4a,0xc2,0x4a,0x5c,0x4a,0xc8,0x4a,0x5c,0x1e,0x4c,0x4a,0x5c,0x4a,0xc8, 0x4a,0x5c,0x4a,0xc8,0x4c,0x6c,0x4c,0x72,0x4c,0x78,0x4c,0x7e,0x4a,0x50,0x19,0x12,0x4a,0x68,0x4a,0xd4,0x4a,0x68,0x4c,0x84,0x4c,0x8a,0x4c,0x90,0x4a,0xf2,0x4c,0x96,0x4a,0xf2,0x4c,0x9c,0x4c,0xa2,0x29,0xc8,0x4c,0xa8,0x4c,0xae,0x4a,0x74,0x4a,0xda,0x4a,0x74,0x4a,0xda,0x4a,0x74,0x4c,0xb4,0x4a,0x7a,0x4a,0xc8,0x4a,0x7a,0x4a,0xaa, 0x4c,0xba,0x28,0xfc,0x22,0xd8,0x4c,0xc0,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x19,0x36,0x4c,0xc6,0x19,0x36,0x4c,0xc6,0x4a,0x8c,0x19,0x12,0x4a,0x8c,0x4b,0x8e,0x4a,0x8c,0x4b,0x8e,0x4c,0xcc,0x4c,0xd2,0x4a,0x92,0x4a,0x98,0x4c,0xd8,0x4c,0xde,0x4a,0x92,0x4a,0x98,0x4a,0x92,0x4a,0x98, 0x4c,0xe4,0x4c,0xea,0x4a,0x98,0x4a,0xec,0x4c,0xf0,0x4c,0xf6,0x4c,0xfc,0x4d,0x02,0x4d,0x08,0x4d,0x0e,0x4d,0x14,0x4d,0x1a,0x4d,0x20,0x4d,0x26,0x4c,0x4e,0x4c,0xa8,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x16,0x2a,0x4a,0xf8,0x4c,0x60,0x33,0x8e,0x4a,0x9e,0x4a,0xfe,0x4a,0x9e,0x4d,0x2c,0x4a,0x68,0x4b,0x04,0x4a,0x68,0x4b,0x04, 0x4a,0xa4,0x4b,0x0a,0x4a,0xaa,0x16,0x7e,0x4d,0x32,0x4d,0x38,0x4d,0x3e,0x4d,0x44,0x28,0xfc,0x4a,0xec,0x4a,0xfe,0x4b,0x0a,0x1b,0xfa,0x19,0x12,0x4a,0xb0,0x4d,0x4a,0x4d,0x50,0x4a,0xb0,0x1b,0xdc,0x4a,0xb0,0x4d,0x56,0x4a,0x4a,0x4d,0x5c,0x4a,0x44,0x1c,0x4e,0x4d,0x62,0x4d,0x68,0x4d,0x6e,0x4d,0x74,0x4d,0x7a,0x4d,0x80,0x4a,0x56, 0x29,0x02,0x4d,0x86,0x4d,0x8c,0x19,0x36,0x4a,0x68,0x4a,0xd4,0x19,0x12,0x4a,0xf2,0x4a,0x74,0x4a,0x7a,0x4d,0x92,0x4a,0x80,0x4d,0x98,0x4d,0x9e,0x4d,0xa4,0x4d,0xaa,0x4d,0xb0,0x1d,0x26,0x4d,0xb6,0x4b,0xb2,0x4d,0xbc,0x4d,0xc2,0x4a,0x98,0x4a,0xec,0x4d,0xc8,0x4d,0xce,0x4d,0xd4,0x17,0xc2,0x4b,0x0a,0x4a,0xaa,0x16,0x7e,0x4d,0xda, 0x4d,0xe0,0x17,0xe6,0x4d,0xe6,0x4d,0xec,0x4b,0x4c,0x4d,0xf2,0x4d,0xf8,0x4d,0xfe,0x4e,0x04,0x47,0xaa,0x4b,0x7c,0x4e,0x0a,0x4e,0x10,0x4e,0x16,0x4a,0x3e,0x1b,0xfa,0x4a,0x50,0x19,0x12,0x4a,0x80,0x16,0x7e,0x1d,0x98,0x4a,0xf2,0x1c,0x0c,0x4e,0x1c,0x4e,0x22,0x4a,0x56,0x4a,0xc2,0x4a,0x56,0x4a,0xc2,0x4a,0x68,0x4a,0xd4,0x4e,0x28, 0x4e,0x2e,0x4e,0x28,0x4e,0x2e,0x4d,0x6e,0x4e,0x34,0x4a,0xce,0x4d,0xf2,0x4d,0xf8,0x4d,0xfe,0x4a,0x56,0x4a,0xc2,0x4e,0x3a,0x4e,0x40,0x4b,0x16,0x4a,0xc8,0x4a,0x3e,0x1b,0xfa,0x4a,0x3e,0x1b,0xfa,0x1d,0x98,0x16,0x7e,0x1d,0x98,0x16,0x7e,0x4a,0x50,0x19,0x12,0x4a,0x50,0x19,0x12,0x4a,0x80,0x16,0x7e,0x4a,0x80,0x16,0x7e,0x4a,0x8c, 0x19,0x12,0x4a,0x8c,0x19,0x12,0x1d,0x98,0x4a,0xf2,0x1d,0x98,0x4a,0xf2,0x29,0x20,0x36,0x4c,0x4a,0x5c,0x4a,0xc8,0x4e,0x46,0x4a,0xb0,0x16,0x7e,0x1a,0xe6,0x4a,0xa4,0x4a,0x3e,0x1b,0xfa,0x4a,0x80,0x16,0x7e,0x4a,0xa4,0x4b,0x0a,0x4e,0x4c,0x4e,0x52,0x1e,0x46,0x4b,0x04,0x4e,0x58,0x1b,0x82,0x4e,0x5e,0x4a,0xbc,0x16,0x2a,0x4e,0x64, 0x15,0xfa,0x4d,0xec,0x4e,0x6a,0x4e,0x70,0x4e,0x76,0x4a,0xc2,0x4a,0xc2,0x1b,0x22,0x4e,0x7c,0x4e,0x82,0x4e,0x88,0x4a,0xc8,0x44,0x56,0x18,0xe2,0x4d,0x8c,0x4e,0x8e,0x4b,0x3a,0x4e,0x94,0x2f,0xf8,0x4e,0x9a,0x4e,0xa0,0x4e,0xa6,0x4e,0xac,0x4a,0xc8,0x4e,0xb2,0x1e,0x9a,0x16,0x7e,0x4e,0xb8,0x4d,0x2c,0x26,0xb0,0x4e,0xbe,0x4e,0xc4, 0x2a,0x4c,0x32,0xc8,0x2f,0xf8,0x19,0x9c,0x4e,0xca,0x4e,0xd0,0x1b,0xee,0x4e,0xd6,0x4e,0xdc,0x4e,0xe2,0x20,0xb0,0x4e,0xe8,0x4e,0xee,0x2f,0xe6,0x4d,0x68,0x1e,0x46,0x4e,0xf4,0x4b,0xb2,0x4e,0x22,0x4b,0xb2,0x4e,0xfa,0x4f,0x00,0x4b,0x04,0x4f,0x06,0x4f,0x0c,0x18,0xd6,0x4f,0x12,0x4f,0x18,0x4f,0x1e,0x4f,0x24,0x17,0xc2,0x1b,0x9a, 0x1a,0xe6,0x1c,0x18,0x4f,0x2a,0x4f,0x30,0x1c,0x0c,0x4f,0x36,0x18,0xd6,0x4f,0x3c,0x4f,0x42,0x4f,0x48,0x4d,0x98,0x4a,0xf2,0x4f,0x4e,0x4f,0x54,0x4f,0x5a,0x4f,0x60,0x4a,0xaa,0x1d,0xe6,0x4f,0x60,0x4a,0xce,0x19,0x12,0x4e,0x16,0x4f,0x66,0x4f,0x6c,0x44,0x6e,0x4f,0x72,0x4e,0x5e,0x4f,0x78,0x4f,0x7e,0x4a,0x3e,0x4a,0x4a,0x4a,0xb6, 0x4a,0x6e,0x4a,0x98,0x4c,0xde,0x4f,0x84,0x4d,0xec,0x4a,0xb0,0x4a,0xbc,0x19,0x24,0x4a,0xda,0x4a,0xc8,0x4a,0xe0,0x19,0x12,0x4b,0x8e,0x4a,0xa4,0x4a,0xec,0x16,0x7e,0x4f,0x8a,0x4f,0x90,0x2f,0x56,0x4f,0x96,0x4f,0x9c,0x1e,0x34,0x4a,0xe0,0x4f,0xa2,0x1e,0x46,0x4f,0xa8,0x4f,0xae,0x27,0x28,0x4a,0xc2,0x4f,0xb4,0x4f,0xba,0x4f,0xc0, 0x4f,0xc6,0x4a,0xe0,0x4f,0xba,0x25,0x72,0x4e,0xdc,0x4f,0xb4,0x4f,0xcc,0x25,0x90,0x4f,0xd2,0x4f,0xd8,0x4f,0xde,0x4f,0xe4,0x4f,0xea,0x4f,0xf0,0x1c,0x0c,0x25,0x78,0x27,0x28,0x21,0xfa,0x4f,0xf6,0x1a,0xe6,0x4f,0xfc,0x50,0x02,0x4a,0x44,0x1d,0x98,0x50,0x08,0x1d,0x98,0x16,0x7e,0x4a,0x62,0x4a,0xce,0x50,0x0e,0x50,0x14,0x4a,0x8c, 0x19,0x12,0x4a,0xa4,0x50,0x1a,0x4a,0xb6,0x4a,0x6e,0x4b,0x3a,0x4a,0x6e,0x4a,0x62,0x4a,0x8c,0x1b,0xfa,0x4a,0xec,0x4d,0xb6,0x50,0x20,0x00,0x01,0x00,0x01,0x04,0x86,0x00,0x02,0x00,0x29,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a,0x00,0x62,0x00,0x81,0x00,0x34,0x00,0x89,0x00,0x89,0x00,0x54,0x00,0x91,0x00,0x92, 0x00,0x55,0x00,0xa0,0x00,0xa1,0x00,0x57,0x00,0xa7,0x00,0xa7,0x00,0x59,0x00,0xad,0x00,0xb1,0x00,0x5a,0x00,0xba,0x00,0xbb,0x00,0x5f,0x00,0xc7,0x00,0xd6,0x00,0x61,0x00,0xe1,0x00,0xe6,0x00,0x71,0x00,0xe8,0x00,0xed,0x00,0x77,0x00,0xf7,0x01,0x00,0x00,0x7d,0x01,0x03,0x01,0x2b,0x00,0x87,0x01,0x39,0x01,0x3b,0x00,0xb0,0x01,0x45, 0x01,0x84,0x00,0xb3,0x01,0x8c,0x01,0x93,0x00,0xf3,0x02,0x40,0x02,0x43,0x00,0xfb,0x02,0x57,0x02,0xb0,0x00,0xff,0x02,0xcd,0x02,0xce,0x01,0x59,0x02,0xe1,0x03,0x78,0x01,0x5b,0x04,0xb0,0x04,0xe2,0x01,0xf3,0x04,0xe6,0x04,0xe9,0x02,0x26,0x04,0xee,0x04,0xfe,0x02,0x2a,0x05,0x07,0x05,0x07,0x02,0x3b,0x05,0x0c,0x05,0x46,0x02,0x3c, 0x05,0x4b,0x05,0x4c,0x02,0x77,0x05,0x4f,0x05,0x50,0x02,0x79,0x05,0x56,0x05,0xb2,0x02,0x7b,0x06,0xac,0x06,0xad,0x02,0xd8,0x07,0x3e,0x07,0x43,0x02,0xda,0x07,0xe1,0x07,0xe2,0x02,0xe0,0x07,0xe4,0x07,0xeb,0x02,0xe2,0x07,0xf7,0x08,0x05,0x02,0xea,0x08,0x07,0x08,0x26,0x02,0xf9,0x0a,0x43,0x0a,0x43,0x03,0x19,0x0a,0xbf,0x0a,0xcc, 0x03,0x1a,0x0a,0xe5,0x0a,0xe5,0x03,0x28,0x0a,0xe7,0x0a,0xed,0x03,0x29,0x0a,0xf4,0x0a,0xf4,0x03,0x30,0x0a,0xf7,0x0a,0xf7,0x03,0x31,0x00,0x01,0x00,0x68,0x00,0x70,0x00,0x02,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x48,0xb4,0x00,0x01,0x48,0xba,0x00,0x14,0x48,0xb6,0x48,0xb6,0x48,0xbc,0x48,0xbc,0x48,0xc2,0x48,0xc8,0x48,0xce, 0x48,0xce,0x48,0xd4,0x48,0xda,0x48,0xe0,0x48,0xe0,0x48,0xe6,0x48,0xe6,0x48,0xec,0x48,0xec,0x42,0x9e,0x42,0x9e,0x48,0xf2,0x48,0xf2,0x48,0xf8,0x48,0xe0,0x48,0xfe,0x48,0xfe,0x49,0x04,0x49,0x04,0x49,0x0a,0x49,0x0a,0x49,0x10,0x49,0x10,0x0f,0x62,0x0f,0x62,0x14,0xf0,0x14,0xf0,0x49,0x16,0x49,0x16,0x49,0x1c,0x49,0x22,0x49,0x28, 0x49,0x2e,0x00,0x01,0x00,0x02,0x04,0x80,0x04,0x81,0x00,0x02,0x00,0x05,0x00,0x45,0x00,0x47,0x00,0x00,0x00,0x49,0x00,0x4b,0x00,0x03,0x00,0x4d,0x00,0x51,0x00,0x06,0x00,0x53,0x00,0x5a,0x00,0x0b,0x00,0x5d,0x00,0x5d,0x00,0x13,0x00,0x01,0x0c,0xec,0x0c,0xf6,0x00,0x02,0x00,0x0c,0x00,0x1e,0x00,0x04,0x00,0x00,0x48,0xac,0x00,0x01, 0x48,0xb2,0x00,0x00,0x48,0xb8,0x00,0x01,0x48,0xbe,0x03,0x33,0x48,0xb2,0x48,0xb8,0x48,0xbe,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x48,0xca,0x48,0xb8,0x37,0x00,0x48,0xb8,0x48,0xd0,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x48,0xe8,0x48,0xb8,0x48,0xee,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x48,0xfa,0x48,0xb8, 0x49,0x00,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x0c,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x2a,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x36,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x54,0x48,0xb8, 0x49,0x5a,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x49,0x60,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x66,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x72,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x84,0x48,0xb8, 0x49,0x8a,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x90,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x9c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x37,0x00,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x48,0x48,0xb8, 0x49,0x48,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x54,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x78,0x48,0xb8, 0x49,0x78,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0xae,0x48,0xb8,0x49,0xb4,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0xba,0x48,0xb8,0x49,0x78,0x48,0xb8,0x38,0x44,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x06,0x48,0xb8, 0x49,0xc0,0x48,0xb8,0x49,0xc6,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x37,0x00,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x37,0x00,0x48,0xb8,0x37,0x00,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x06,0x48,0xb8, 0x49,0x24,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x24,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x49,0xcc,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0xd2,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x0c,0x48,0xb8,0x49,0x4e,0x48,0xb8, 0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0xd8,0x48,0xb8, 0x48,0xca,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x49,0xde,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x49,0xe4,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x06,0x48,0xb8, 0x49,0x78,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0xea,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x42,0x48,0xb8, 0x49,0xa8,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x49,0xf0,0x48,0xb8,0x49,0xf6,0x48,0xb8,0x49,0xfc,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8, 0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8, 0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xe8,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xee,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x06,0x48,0xb8, 0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8, 0x49,0x66,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4a,0x02,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8, 0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8, 0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8, 0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8, 0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8,0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8, 0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8,0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8,0x4a,0x08,0x48,0xb8,0x4a,0x0e,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8, 0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x35,0xa4,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x4a,0x14,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8, 0x48,0xb2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x48,0xbe,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x48,0xbe,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x48,0xbe,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0x5a,0x48,0xb8, 0x48,0xca,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xca,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xd0,0x48,0xb8,0x49,0x60,0x48,0xb8, 0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8, 0x48,0xee,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x48,0xee,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x48,0xee,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4a,0x1a,0x48,0xb8,0x49,0x72,0x48,0xb8, 0x4a,0x1a,0x48,0xb8,0x49,0x72,0x48,0xb8,0x4a,0x1a,0x48,0xb8,0x49,0x72,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8, 0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x0c,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x0c,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8, 0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8, 0x49,0x1e,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x2a,0x48,0xb8,0x49,0x90,0x48,0xb8,0x49,0x2a,0x48,0xb8,0x49,0x90,0x48,0xb8, 0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x30,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0x36,0x48,0xb8,0x49,0x9c,0x48,0xb8,0x49,0x36,0x48,0xb8,0x49,0x9c,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8, 0x49,0x66,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x49,0x48,0x48,0xb8,0x4a,0x02,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4a,0x20,0x48,0xb8,0x4a,0x26,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4a,0x2c,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4a,0x32,0x48,0xb8,0x4a,0x32,0x48,0xb8,0x4a,0x38,0x48,0xb8,0x48,0xca,0x48,0xb8, 0x4a,0x3e,0x48,0xb8,0x4a,0x44,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4a,0x4a,0x48,0xb8,0x4a,0x50,0x48,0xb8,0x4a,0x56,0x48,0xb8,0x48,0xd0,0x48,0xb8,0x4a,0x5c,0x48,0xb8,0x49,0x2a,0x48,0xb8,0x4a,0x62,0x48,0xb8,0x4a,0x68,0x48,0xb8,0x4a,0x6e,0x48,0xb8,0x48,0xee,0x48,0xb8,0x4a,0x74,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4a,0x74,0x48,0xb8, 0x4a,0x7a,0x48,0xb8,0x49,0x00,0x48,0xb8,0x39,0x1c,0x48,0xb8,0x49,0x06,0x48,0xb8,0x4a,0x80,0x48,0xb8,0x4a,0x86,0x48,0xb8,0x4a,0x8c,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4a,0x92,0x48,0xb8,0x49,0x18,0x48,0xb8,0x49,0x84,0x48,0xb8,0x4a,0x98,0x48,0xb8,0x4a,0x9e,0x48,0xb8,0x4a,0xa4,0x48,0xb8,0x4a,0xaa,0x48,0xb8,0x4a,0xa4,0x48,0xb8, 0x4a,0xaa,0x48,0xb8,0x4a,0xb0,0x48,0xb8,0x4a,0xb6,0x48,0xb8,0x4a,0xbc,0x48,0xb8,0x4a,0xc2,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x4a,0xc8,0x48,0xb8,0x4a,0xc8,0x48,0xb8,0x38,0x44,0x48,0xb8,0x4a,0xce,0x48,0xb8,0x4a,0xd4,0x48,0xb8,0x4a,0xda,0x48,0xb8,0x4a,0xe0,0x48,0xb8,0x4a,0xe6,0x48,0xb8,0x4a,0xec,0x48,0xb8, 0x4a,0xf2,0x48,0xb8,0x4a,0xf8,0x48,0xb8,0x4a,0xfe,0x48,0xb8,0x4b,0x04,0x48,0xb8,0x4b,0x0a,0x48,0xb8,0x4b,0x10,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x4b,0x16,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x49,0xb4,0x48,0xb8, 0x4b,0x1c,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x48,0xee,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x4a,0xc8,0x48,0xb8,0x4b,0x22,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4a,0xe0,0x48,0xb8,0x4a,0xe6,0x48,0xb8, 0x4a,0xec,0x48,0xb8,0x48,0xd6,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x4b,0x28,0x48,0xb8,0x4b,0x2e,0x48,0xb8,0x49,0x00,0x48,0xb8,0x49,0x66,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x4b,0x16,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x4b,0x16,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xe2,0x48,0xb8, 0x36,0x5e,0x48,0xb8,0x48,0xe2,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x39,0x1c,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x24,0x48,0xb8,0x49,0x66,0x48,0xb8,0x4b,0x34,0x48,0xb8, 0x4b,0x3a,0x48,0xb8,0x48,0xdc,0x48,0xb8,0x49,0x66,0x48,0xb8,0x4b,0x40,0x48,0xb8,0x49,0x36,0x48,0xb8,0x4b,0x46,0x48,0xb8,0x49,0x42,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x4b,0x16,0x48,0xb8,0x49,0x06,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4b,0x16,0x48,0xb8,0x37,0x36,0x48,0xb8, 0x37,0x36,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x4a,0x38,0x48,0xb8,0x4a,0x38,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x39,0x16,0x48,0xb8,0x4b,0x4c,0x48,0xb8,0x4b,0x4c,0x48,0xb8,0x4a,0x50,0x48,0xb8,0x4b,0x52,0x48,0xb8,0x36,0x52,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x4b,0x58,0x48,0xb8, 0x49,0x90,0x48,0xb8,0x4b,0x5e,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x66,0x48,0xb8,0x4b,0x64,0x48,0xb8,0x4a,0x6e,0x48,0xb8,0x4b,0x6a,0x48,0xb8,0x4b,0x70,0x48,0xb8,0x4b,0x76,0x48,0xb8,0x4a,0x02,0x48,0xb8,0x4b,0x7c,0x48,0xb8,0x49,0x72,0x48,0xb8,0x49,0x72,0x48,0xb8,0x49,0x72,0x48,0xb8,0x4b,0x82,0x48,0xb8, 0x4b,0x82,0x48,0xb8,0x49,0x78,0x48,0xb8,0x49,0x78,0x48,0xb8,0x4b,0x88,0x48,0xb8,0x4a,0x14,0x48,0xb8,0x4b,0x8e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x4b,0x94,0x48,0xb8,0x4b,0x94,0x48,0xb8,0x4b,0x9a,0x48,0xb8,0x4b,0x9a,0x48,0xb8,0x4b,0xa0,0x48,0xb8, 0x4b,0xa6,0x48,0xb8,0x4b,0xac,0x48,0xb8,0x4a,0x68,0x48,0xb8,0x4b,0xb2,0x48,0xb8,0x4a,0xa4,0x48,0xb8,0x4a,0xa4,0x48,0xb8,0x4b,0xb8,0x48,0xb8,0x4b,0xbe,0x48,0xb8,0x4b,0xc4,0x48,0xb8,0x49,0x90,0x48,0xb8,0x49,0x96,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4b,0xca,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x4b,0xd0,0x48,0xb8,0x4b,0x22,0x48,0xb8, 0x4b,0x22,0x48,0xb8,0x4b,0xd6,0x48,0xb8,0x4b,0xd6,0x48,0xb8,0x4b,0xd6,0x48,0xb8,0x4a,0x38,0x48,0xb8,0x37,0x36,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4b,0xdc,0x48,0xb8,0x4b,0x58,0x48,0xb8,0x49,0x66,0x48,0xb8,0x4a,0x02,0x48,0xb8,0x4a,0x74,0x48,0xb8,0x4b,0xe2,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x4b,0xd6,0x48,0xb8,0x4b,0xd6,0x48,0xb8, 0x4b,0xe8,0x48,0xb8,0x4b,0xee,0x48,0xb8,0x4b,0xf4,0x48,0xb8,0x4a,0x20,0x48,0xb8,0x4b,0xfa,0x48,0xb8,0x4c,0x00,0x48,0xb8,0x4c,0x06,0x48,0xb8,0x48,0xee,0x48,0xb8,0x4a,0xbc,0x48,0xb8,0x4c,0x0c,0x48,0xb8,0x4c,0x0c,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4b,0x64,0x48,0xb8,0x4c,0x12,0x48,0xb8,0x4c,0x18,0x48,0xb8,0x4c,0x1e,0x48,0xb8, 0x49,0x8a,0x48,0xb8,0x4a,0x4a,0x48,0xb8,0x4a,0x4a,0x48,0xb8,0x4c,0x24,0x48,0xb8,0x4c,0x24,0x48,0xb8,0x48,0xb2,0x48,0xb8,0x48,0xc4,0x48,0xb8,0x49,0x54,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x49,0x1e,0x48,0xb8,0x49,0x84,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x4c,0x2a,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x60,0x48,0xb8, 0x49,0x72,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x4b,0x94,0x48,0xb8,0x4c,0x30,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x49,0xa8,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x4c,0x36,0x48,0xb8,0x4c,0x3c,0x48,0xb8,0x4c,0x42,0x48,0xb8,0x4b,0x6a,0x48,0xb8,0x4c,0x48,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x4c,0x4e,0x48,0xb8, 0x4b,0xbe,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x60,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x6c,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x49,0x72,0x48,0xb8,0x49,0x66,0x48,0xb8,0x49,0x4e,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x84,0x48,0xb8,0x4c,0x54,0x48,0xb8,0x49,0x90,0x48,0xb8,0x49,0x9c,0x48,0xb8,0x49,0xa8,0x48,0xb8, 0x49,0x48,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x4c,0x5a,0x48,0xb8,0x4c,0x60,0x48,0xb8,0x4c,0x66,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4a,0x38,0x48,0xb8,0x4b,0xa6,0x48,0xb8,0x49,0x66,0x48,0xb8,0x4b,0x22,0x48,0xb8,0x4c,0x6c,0x48,0xb8,0x4c,0x72,0x48,0xb8,0x48,0xbe,0x48,0xb8,0x49,0x24,0x48,0xb8, 0x4c,0x78,0x48,0xb8,0x37,0x00,0x48,0xb8,0x38,0x6e,0x48,0xb8,0x48,0xe8,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x4c,0x7e,0x48,0xb8,0x49,0x5a,0x48,0xb8,0x49,0x12,0x48,0xb8,0x49,0x7e,0x48,0xb8,0x49,0x3c,0x48,0xb8,0x49,0xa2,0x48,0xb8,0x4c,0x84,0x48,0xb8,0x48,0xf4,0x48,0xb8,0x4c,0x8a,0x48,0xb8,0x4c,0x90,0x48,0xb8,0x49,0x0c,0x48,0xb8, 0x49,0x12,0x48,0xb8,0x49,0x48,0x48,0xb8,0x49,0x8a,0x48,0xb8,0x4c,0x96,0x48,0xb8,0x4c,0x9c,0x48,0xb8,0x36,0x5e,0x48,0xb8,0x00,0x02,0x00,0x01,0x07,0x3a,0x07,0x3d,0x00,0x00,0x00,0x02,0x00,0x2a,0x00,0x24,0x00,0x3d,0x00,0x00,0x00,0x44,0x00,0x5d,0x00,0x1a,0x00,0x62,0x00,0x81,0x00,0x34,0x00,0x89,0x00,0x89,0x00,0x54,0x00,0x91, 0x00,0x92,0x00,0x55,0x00,0xa0,0x00,0xa1,0x00,0x57,0x00,0xa7,0x00,0xa7,0x00,0x59,0x00,0xad,0x00,0xb1,0x00,0x5a,0x00,0xba,0x00,0xbb,0x00,0x5f,0x00,0xc7,0x00,0xd6,0x00,0x61,0x00,0xe1,0x00,0xe6,0x00,0x71,0x00,0xe8,0x00,0xed,0x00,0x77,0x00,0xf7,0x01,0x00,0x00,0x7d,0x01,0x03,0x01,0x2b,0x00,0x87,0x01,0x39,0x01,0x3b,0x00,0xb0, 0x01,0x45,0x01,0x84,0x00,0xb3,0x01,0x8c,0x01,0x93,0x00,0xf3,0x02,0x40,0x02,0x43,0x00,0xfb,0x02,0x57,0x02,0xb0,0x00,0xff,0x02,0xcd,0x02,0xce,0x01,0x59,0x02,0xe1,0x03,0x78,0x01,0x5b,0x04,0xb0,0x04,0xe2,0x01,0xf3,0x04,0xe6,0x04,0xe9,0x02,0x26,0x04,0xee,0x04,0xfe,0x02,0x2a,0x05,0x07,0x05,0x07,0x02,0x3b,0x05,0x0c,0x05,0x46, 0x02,0x3c,0x05,0x4b,0x05,0x4c,0x02,0x77,0x05,0x4f,0x05,0x50,0x02,0x79,0x05,0x56,0x05,0xb2,0x02,0x7b,0x06,0xac,0x06,0xad,0x02,0xd8,0x07,0x3e,0x07,0x43,0x02,0xda,0x07,0xe1,0x07,0xe2,0x02,0xe0,0x07,0xe4,0x07,0xeb,0x02,0xe2,0x07,0xf7,0x08,0x05,0x02,0xea,0x08,0x07,0x08,0x26,0x02,0xf9,0x0a,0x43,0x0a,0x43,0x03,0x19,0x0a,0xbf, 0x0a,0xcc,0x03,0x1a,0x0a,0xe5,0x0a,0xe5,0x03,0x28,0x0a,0xe7,0x0a,0xed,0x03,0x29,0x0a,0xf4,0x0a,0xf4,0x03,0x30,0x0a,0xf7,0x0a,0xf7,0x03,0x31,0x11,0x8c,0x11,0x8c,0x03,0x32,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0xe4,0x00,0x00,0x00,0x01,0x02,0x47,0x00,0x00,0x00,0x01,0x01,0xc1,0x00,0x00,0x00,0x01,0x03,0x0a,0x00,0x00, 0x00,0x01,0x02,0x6d,0x00,0x00,0x00,0x01,0x01,0xe7,0x00,0x00,0x00,0x01,0x02,0xb9,0x00,0x00,0x00,0x01,0x02,0x1c,0x00,0x00,0x00,0x01,0x01,0x96,0x00,0x00,0x00,0x01,0x02,0x30,0x00,0x00,0x00,0x01,0x01,0x93,0x00,0x00,0x00,0x01,0x01,0x0d,0x00,0x00,0x00,0x01,0x02,0xf2,0x00,0x00,0x00,0x01,0x02,0x23,0x00,0x00,0x00,0x01,0x01,0x61, 0x00,0x00,0x00,0x01,0x03,0x3d,0x00,0x00,0x00,0x01,0x02,0xa0,0x00,0x00,0x00,0x01,0x02,0x1a,0x00,0x00,0x00,0x01,0x00,0xf9,0x00,0x00,0x00,0x01,0x00,0x73,0x00,0x00,0x00,0x01,0x01,0x4b,0x00,0x00,0x00,0x01,0x00,0xcf,0x00,0x00,0x00,0x01,0x03,0x3b,0x00,0x00,0x00,0x01,0x02,0x9e,0x00,0x00,0x00,0x01,0x02,0x18,0x00,0x00,0x00,0x01, 0x03,0x3a,0x00,0x00,0x00,0x01,0x02,0x9d,0x00,0x00,0x00,0x01,0x02,0x17,0x00,0x00,0x00,0x01,0x02,0x19,0x00,0x00,0x00,0x01,0x00,0xfc,0x00,0x00,0x00,0x01,0xff,0xf5,0x00,0x00,0x00,0x01,0x02,0x48,0x00,0x00,0x00,0x01,0x01,0xab,0x00,0x00,0x00,0x01,0x01,0x39,0x00,0x00,0x00,0x01,0x02,0x4d,0x00,0x00,0x00,0x01,0x01,0xb0,0x00,0x00, 0x00,0x01,0x01,0x2a,0x00,0x00,0x00,0x01,0x03,0x42,0x00,0x00,0x00,0x01,0x02,0xa5,0x00,0x00,0x00,0x01,0x02,0x1f,0x00,0x00,0x00,0x01,0xff,0xb5,0x00,0x00,0x00,0x01,0xfe,0x98,0x00,0x00,0x00,0x01,0xfd,0x91,0x00,0x00,0x00,0x01,0x01,0xee,0x00,0x00,0x00,0x01,0x01,0x51,0x00,0x00,0x00,0x01,0x00,0xcb,0x00,0x00,0x00,0x01,0x03,0x37, 0x00,0x00,0x00,0x01,0x02,0x9a,0x00,0x00,0x00,0x01,0x02,0x14,0x00,0x00,0x00,0x01,0x02,0xe8,0x00,0x00,0x00,0x01,0x02,0x4b,0x00,0x00,0x00,0x01,0x01,0xc5,0x00,0x00,0x00,0x01,0x02,0x85,0x00,0x00,0x00,0x01,0x01,0x68,0x00,0x00,0x00,0x01,0x00,0x61,0x00,0x00,0x00,0x01,0x02,0xcf,0x00,0x00,0x00,0x01,0x02,0x32,0x00,0x00,0x00,0x01, 0x01,0xac,0x00,0x00,0x00,0x01,0x00,0xd3,0x00,0x00,0x00,0x01,0xff,0xb6,0x00,0x00,0x00,0x01,0xfe,0xaf,0x00,0x00,0x00,0x01,0x02,0x8e,0x00,0x00,0x00,0x01,0x01,0xf1,0x00,0x00,0x00,0x01,0x01,0x6b,0x00,0x00,0x00,0x01,0x03,0x89,0x00,0x00,0x00,0x01,0x03,0x6b,0x00,0x00,0x00,0x01,0x03,0x61,0x00,0x00,0x00,0x01,0x03,0xe7,0x00,0x00, 0x00,0x01,0x03,0x18,0x00,0x00,0x00,0x01,0x02,0x06,0x00,0x00,0x00,0x01,0x03,0x83,0x00,0x00,0x00,0x01,0x02,0xe6,0x00,0x00,0x00,0x01,0x02,0x60,0x00,0x00,0x00,0x01,0x03,0x7e,0x00,0x00,0x00,0x01,0x02,0xe1,0x00,0x00,0x00,0x01,0x02,0x5b,0x00,0x00,0x00,0x01,0x02,0x9b,0x00,0x00,0x00,0x01,0x01,0xfe,0x00,0x00,0x00,0x01,0x01,0x78, 0x00,0x00,0x00,0x01,0x02,0xad,0x00,0x00,0x00,0x01,0x02,0x10,0x00,0x00,0x00,0x01,0x01,0x8a,0x00,0x00,0x00,0x01,0x02,0xc5,0x00,0x00,0x00,0x01,0x02,0x28,0x00,0x00,0x00,0x01,0x01,0xa2,0x00,0x00,0x00,0x01,0x02,0x34,0x00,0x00,0x00,0x01,0x01,0x97,0x00,0x00,0x00,0x01,0x01,0x11,0x00,0x00,0x00,0x01,0x01,0xdc,0x00,0x00,0x00,0x01, 0x01,0x3f,0x00,0x00,0x00,0x01,0x00,0xb9,0x00,0x00,0x00,0x01,0x02,0x42,0x00,0x00,0x00,0x01,0x01,0x73,0x00,0x00,0x00,0x01,0x00,0xf7,0x00,0x00,0x00,0x01,0x03,0xbf,0x00,0x00,0x00,0x01,0x03,0xe5,0x00,0x00,0x00,0x01,0x03,0x9a,0x00,0x00,0x00,0x01,0x03,0x0b,0x00,0x00,0x00,0x01,0x03,0x5b,0x00,0x00,0x00,0x01,0x04,0x18,0x00,0x00, 0x00,0x01,0x02,0x71,0x00,0x00,0x00,0x01,0x04,0x16,0x00,0x00,0x00,0x01,0x04,0x15,0x00,0x00,0x00,0x01,0x03,0x41,0x00,0x00,0x00,0x01,0x03,0x28,0x00,0x00,0x00,0x01,0x04,0x1d,0x00,0x00,0x00,0x01,0x02,0xc9,0x00,0x00,0x00,0x01,0x04,0x12,0x00,0x00,0x00,0x01,0x03,0xa1,0x00,0x00,0x00,0x01,0x03,0xaa,0x00,0x00,0x00,0x01,0x03,0x69, 0x00,0x00,0x00,0x01,0x05,0x40,0x00,0x00,0x00,0x01,0x03,0xab,0x00,0x00,0x00,0x01,0x04,0x5e,0x00,0x00,0x00,0x01,0x04,0x59,0x00,0x00,0x00,0x01,0x03,0x76,0x00,0x00,0x00,0x01,0x03,0x88,0x00,0x00,0x00,0x01,0x03,0xa0,0x00,0x00,0x00,0x01,0x02,0xb7,0x00,0x00,0x00,0x01,0x02,0xf7,0x00,0x00,0x00,0x01,0x04,0x11,0x00,0x00,0x00,0x01, 0xfe,0xfd,0x00,0x00,0x00,0x01,0x00,0xe6,0xff,0x9c,0x00,0x01,0x00,0xef,0x00,0x00,0x00,0x01,0x00,0xb8,0x00,0x00,0x00,0x01,0x00,0xca,0x00,0x00,0x00,0x01,0x00,0x8a,0x00,0x00,0x00,0x01,0x01,0x1d,0x00,0x00,0x00,0x01,0x01,0x12,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0x00,0x00,0x01,0x01,0x10,0x00,0x00,0x00,0x01,0x00,0xf2,0x00,0x00, 0x00,0x01,0x00,0x97,0x00,0x00,0x00,0x01,0x00,0xb4,0x00,0x00,0x00,0x01,0xff,0xac,0x00,0x00,0x00,0x01,0x01,0x17,0x00,0x00,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x01,0x00,0xe8,0x00,0x00,0x00,0x01,0x00,0xb5,0x00,0x00,0x00,0x01,0x00,0xbe,0x00,0x00,0x00,0x01,0x00,0x66,0x00,0x00,0x00,0x01,0x00,0x98,0x00,0x00,0x00,0x01,0x00,0xc0, 0x00,0x00,0x00,0x01,0x01,0x80,0x00,0x00,0x00,0x01,0xff,0xb4,0x00,0x00,0x00,0x01,0x01,0x58,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01,0xff,0xec,0x00,0x00,0x00,0x01,0x00,0x69,0x00,0x00,0x00,0x01,0xff,0xc4,0x00,0x00,0x00,0x01,0x00,0xd2,0x00,0x00,0x00,0x01,0x01,0x18,0x00,0x00,0x00,0x01, 0x00,0xb6,0x00,0x00,0x00,0x01,0x00,0x37,0x00,0x00,0x00,0x01,0x00,0x78,0x00,0x00,0x00,0x01,0x00,0xa0,0x00,0x00,0x00,0x01,0x00,0x7c,0x00,0x00,0x00,0x01,0x00,0x7d,0x00,0x00,0x00,0x01,0x00,0xed,0x00,0xf0,0x00,0x01,0x01,0xa6,0x00,0xf0,0x00,0x01,0x00,0xe4,0x00,0xf0,0x00,0x01,0x01,0x9d,0x00,0xf0,0x00,0x01,0x00,0x8e,0x00,0xf0, 0x00,0x01,0x01,0x47,0x00,0xf0,0x00,0x01,0x00,0x3c,0x00,0xf0,0x00,0x01,0x00,0xf5,0x00,0xf0,0x00,0x01,0x00,0x60,0x00,0xf0,0x00,0x01,0x01,0x19,0x00,0xf0,0x00,0x01,0x01,0x11,0x00,0xf0,0x00,0x01,0x01,0x97,0x00,0xf0,0x00,0x01,0x00,0x84,0x00,0xf0,0x00,0x01,0x01,0x3d,0x00,0xf0,0x00,0x01,0x00,0x6c,0x00,0xf0,0x00,0x01,0x01,0x25, 0x00,0xf0,0x00,0x01,0x01,0x0e,0x00,0xf0,0x00,0x01,0x01,0x90,0x00,0xf0,0x00,0x01,0x00,0xf0,0x00,0xf0,0x00,0x01,0x01,0x72,0x00,0xf0,0x00,0x01,0x00,0x6d,0x00,0xf0,0x00,0x01,0x01,0x26,0x00,0xf0,0x00,0x01,0x00,0x8a,0x00,0xf0,0x00,0x01,0x01,0x43,0x00,0xf0,0x00,0x01,0xff,0x1e,0x00,0xf0,0x00,0x01,0xff,0xd7,0x00,0xf0,0x00,0x01, 0x01,0x04,0x00,0xf0,0x00,0x01,0x00,0x62,0x00,0xf0,0x00,0x01,0x01,0x1b,0x00,0xf0,0x00,0x01,0x00,0xdc,0x00,0xf0,0x00,0x01,0x01,0x68,0x00,0xf0,0x00,0x01,0x00,0xb3,0x00,0xf0,0x00,0x01,0x01,0x6c,0x00,0xf0,0x00,0x01,0x00,0xb2,0x00,0xf0,0x00,0x01,0x01,0x3e,0x00,0xf0,0x00,0x01,0x00,0x64,0x00,0xf0,0x00,0x01,0x01,0x1d,0x00,0xf0, 0x00,0x01,0x00,0xaa,0x00,0xf0,0x00,0x01,0x01,0x63,0x00,0xf0,0x00,0x01,0x01,0x0b,0x00,0xf0,0x00,0x01,0x00,0xbe,0x00,0xf0,0x00,0x01,0x01,0x77,0x00,0xf0,0x00,0x01,0x00,0xf2,0x00,0xf0,0x00,0x01,0x01,0xab,0x00,0xf0,0x00,0x01,0x00,0xe3,0x00,0xf0,0x00,0x01,0x01,0x9c,0x00,0xf0,0x00,0x01,0x01,0x01,0x00,0xf0,0x00,0x01,0x00,0xca, 0x00,0xf0,0x00,0x01,0x01,0x83,0x00,0xf0,0x00,0x01,0x00,0x94,0x00,0xf0,0x00,0x01,0x01,0x4d,0x00,0xf0,0x00,0x01,0xff,0x5e,0x00,0xf0,0x00,0x01,0x02,0xa8,0x00,0x00,0x00,0x01,0x01,0xeb,0x00,0x00,0x00,0x01,0x01,0xa0,0x00,0x00,0x00,0x01,0x02,0xae,0x00,0x00,0x00,0x01,0x01,0x56,0x00,0x00,0x00,0x01,0x02,0xc1,0x00,0x00,0x00,0x01, 0x01,0xb8,0x00,0x00,0x00,0x01,0x01,0xc8,0x00,0x00,0x00,0x01,0x02,0x3d,0x00,0x00,0x00,0x01,0x02,0xbf,0x00,0x00,0x00,0x01,0x02,0xbe,0x00,0x00,0x00,0x01,0x01,0x6a,0x00,0x00,0x00,0x01,0x02,0xb3,0x00,0x00,0x00,0x01,0x02,0x26,0x00,0x00,0x00,0x01,0x02,0x45,0x00,0x00,0x00,0x01,0x02,0x33,0x00,0x00,0x00,0x01,0x02,0x5e,0x00,0x00, 0x00,0x01,0x02,0xaf,0x00,0x00,0x00,0x01,0x03,0x1f,0x00,0x00,0x00,0x01,0x02,0xf4,0x00,0x00,0x00,0x01,0x02,0x29,0x00,0x00,0x00,0x01,0x01,0x7f,0x00,0x00,0x00,0x01,0x01,0x12,0x00,0xf0,0x00,0x01,0x01,0xeb,0x00,0xdc,0x00,0x01,0x01,0xc8,0x00,0xdc,0x00,0x01,0x02,0x45,0x00,0xdc,0x00,0x01,0x02,0x91,0x00,0x00,0x00,0x01,0x01,0xa0, 0x00,0xdc,0x00,0x01,0x02,0xae,0x00,0xdc,0x00,0x01,0x02,0xf4,0x00,0xdc,0x00,0x01,0x02,0x4e,0x00,0x00,0x00,0x01,0x01,0xcf,0x00,0x00,0x00,0x01,0x02,0x38,0x00,0x00,0x00,0x01,0x02,0x15,0x00,0x00,0x00,0x01,0x02,0x3b,0x00,0x00,0x00,0x01,0xff,0xa6,0x00,0x00,0x00,0x01,0x02,0x4c,0x00,0x00,0x00,0x01,0x01,0xcd,0x00,0x00,0x00,0x01, 0x02,0x0e,0x00,0x00,0x00,0x01,0x02,0x36,0x00,0x00,0x00,0x01,0x02,0x12,0x00,0x00,0x00,0x01,0x02,0x13,0x00,0x00,0x00,0x01,0x01,0x9b,0x00,0x00,0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x01,0x01,0xe0,0x00,0x00,0x00,0x01,0x01,0xe1,0x00,0x00,0x00,0x01,0x02,0xee,0x00,0x00,0x00,0x01,0x03,0x14,0x00,0x00,0x00,0x01,0x02,0xc3,0x00,0x00, 0x00,0x01,0x02,0x3a,0x00,0x00,0x00,0x01,0x03,0x10,0x00,0x00,0x00,0x01,0x03,0x47,0x00,0x00,0x00,0x01,0x02,0x24,0x00,0x00,0x00,0x01,0x03,0x45,0x00,0x00,0x00,0x01,0x03,0x44,0x00,0x00,0x00,0x01,0x02,0x52,0x00,0x00,0x00,0x01,0x02,0x57,0x00,0x00,0x00,0x01,0x03,0x4c,0x00,0x00,0x00,0x01,0x00,0x27,0x00,0x00,0x00,0x01,0x01,0xf8, 0x00,0x00,0x00,0x01,0x02,0xbb,0x00,0x00,0x00,0x01,0x02,0xd9,0x00,0x00,0x00,0x01,0x01,0x45,0x00,0x00,0x00,0x01,0x02,0x98,0x00,0x00,0x00,0x01,0x04,0x05,0x00,0x00,0x00,0x01,0x03,0x8d,0x00,0x00,0x00,0x01,0x02,0x3e,0x00,0x00,0x00,0x01,0x01,0xe6,0x00,0x00,0x00,0x01,0x03,0x7d,0x00,0x00,0x00,0x01,0x03,0xa3,0x00,0x00,0x00,0x01, 0x03,0x52,0x00,0x00,0x00,0x01,0x03,0xd6,0x00,0x00,0x00,0x01,0x02,0x2f,0x00,0x00,0x00,0x01,0x03,0xd4,0x00,0x00,0x00,0x01,0x03,0xd3,0x00,0x00,0x00,0x01,0x02,0x8b,0x00,0x00,0x00,0x01,0x03,0xdb,0x00,0x00,0x00,0x01,0x02,0x87,0x00,0x00,0x00,0x01,0x03,0xd0,0x00,0x00,0x00,0x01,0x03,0x81,0x00,0x00,0x00,0x01,0x03,0x68,0x00,0x00, 0x00,0x01,0x03,0x27,0x00,0x00,0x00,0x01,0x04,0x2b,0x00,0x00,0x00,0x01,0x04,0x30,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x17,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x00,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x01,0x03,0x5e,0x00,0x00,0x00,0x01,0x02,0xcd,0x00,0x00,0x00,0x01,0x02,0x75,0x00,0x00,0x00,0x01,0x02,0xdb, 0x00,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0x00,0x01,0x04,0x26,0x00,0x00,0x00,0x01,0x03,0xd5,0x00,0x00,0x00,0x01,0x03,0x8c,0x00,0x00,0x00,0x01,0x02,0xb2,0x00,0x00,0x00,0x01,0x03,0x36,0x00,0x00,0x00,0x01,0x04,0x57,0x00,0x00,0x00,0x01,0x04,0x56,0x00,0x00,0x00,0x01,0x02,0x9f,0x00,0x00,0x00,0x01,0x03,0x64,0x00,0x00,0x00,0x01, 0x00,0x3b,0x00,0x00,0x00,0x01,0x04,0x53,0x00,0x00,0x00,0x01,0x04,0x04,0x00,0x00,0x00,0x01,0x03,0xeb,0x00,0x00,0x00,0x01,0x01,0x59,0x00,0x00,0x00,0x01,0x05,0x1e,0x00,0x00,0x00,0x01,0x04,0x4f,0x00,0x00,0x00,0x01,0x04,0x9f,0x00,0x00,0x00,0x01,0x04,0x9a,0x00,0x00,0x00,0x01,0x03,0xb7,0x00,0x00,0x00,0x01,0x03,0xc9,0x00,0x00, 0x00,0x01,0x03,0xe1,0x00,0x00,0x00,0x01,0x03,0x50,0x00,0x00,0x00,0x01,0x02,0xf8,0x00,0x00,0x00,0x01,0x03,0x1a,0x00,0x00,0x00,0x01,0x03,0x03,0x00,0x00,0x00,0x01,0x03,0x9e,0x00,0x00,0x00,0x01,0x01,0xf7,0x00,0x00,0x00,0x01,0x02,0x7b,0x00,0x00,0x00,0x01,0x03,0x9c,0x00,0x00,0x00,0x01,0x03,0x9b,0x00,0x00,0x00,0x01,0x02,0xa9, 0x00,0x00,0x00,0x01,0xff,0xb0,0x00,0x00,0x00,0x01,0x02,0x4f,0x00,0x00,0x00,0x01,0x03,0x98,0x00,0x00,0x00,0x01,0x03,0x49,0x00,0x00,0x00,0x01,0x02,0x80,0x00,0x00,0x00,0x01,0x03,0x30,0x00,0x00,0x00,0x01,0x00,0xce,0x00,0x00,0x00,0x01,0x02,0xef,0x00,0x00,0x00,0x01,0x04,0x46,0x00,0x00,0x00,0x01,0x03,0xf8,0x00,0x00,0x00,0x01, 0x03,0xe4,0x00,0x00,0x00,0x01,0x03,0xdf,0x00,0x00,0x00,0x01,0x02,0xfc,0x00,0x00,0x00,0x01,0x03,0x0e,0x00,0x00,0x00,0x01,0x03,0x26,0x00,0x00,0x00,0x01,0x02,0x95,0x00,0x00,0x00,0x01,0x02,0xa3,0x00,0x00,0x00,0x01,0x01,0x2c,0x00,0x00,0x00,0x01,0x01,0x5e,0x00,0x00,0x00,0x01,0x01,0xc2,0x00,0x00,0x00,0x01,0x02,0xbc,0x00,0x00, 0x00,0x01,0x03,0x84,0x00,0x00,0x00,0x01,0x03,0x67,0x00,0x00,0x00,0x01,0x03,0xaf,0x00,0x00,0x00,0x01,0x02,0xa7,0x00,0x00,0x00,0x01,0x03,0xb5,0x00,0x00,0x00,0x01,0x02,0x5d,0x00,0x00,0x00,0x01,0x03,0xbe,0x00,0x00,0x00,0x01,0x03,0xc8,0x00,0x00,0x00,0x01,0x03,0xc6,0x00,0x00,0x00,0x01,0x03,0xc5,0x00,0x00,0x00,0x01,0x03,0xba, 0x00,0x00,0x00,0x01,0x03,0x78,0x00,0x00,0x00,0x01,0x03,0x2d,0x00,0x00,0x00,0x01,0x03,0x65,0x00,0x00,0x00,0x01,0x03,0xb6,0x00,0x00,0x00,0x01,0x03,0xfb,0x00,0x00,0x00,0x01,0x03,0x1e,0x00,0x00,0x00,0x01,0x02,0x5f,0x00,0x00,0x00,0x01,0x02,0x86,0x00,0x00,0x00,0x01,0x02,0x5f,0x00,0xf0,0x00,0x01,0x02,0xf2,0x00,0xd0,0x00,0x01, 0x02,0xcf,0x00,0xd0,0x00,0x01,0x03,0x4c,0x00,0xd0,0x00,0x01,0x02,0xa7,0x00,0xd0,0x00,0x01,0x02,0xf2,0x00,0xdc,0x00,0x01,0x03,0xb5,0x00,0xd0,0x00,0x01,0x03,0xfb,0x00,0xd0,0x00,0x01,0x01,0x04,0x04,0xb0,0x00,0x01,0x01,0x54,0x00,0x00,0x00,0x01,0x01,0x13,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0xb0,0x00,0x01,0x00,0x00,0x05,0x64, 0x00,0x01,0xff,0xce,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x88,0x00,0x01,0x00,0x46,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x60,0x00,0x01,0x00,0x00,0x03,0xde,0x00,0x01,0x00,0x00,0x03,0xe8,0x00,0x01,0xff,0xc4,0x03,0xe8,0x00,0x01,0xff,0xf6,0x00,0x41,0x00,0x01,0x00,0x0a,0x00,0x41,0x00,0x01,0x00,0x00,0x04,0x7e,0x00,0x01,0x00,0x0f, 0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x41,0x00,0x01,0xff,0xfb,0x00,0x32,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x01,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,0x00,0xff,0xc9,0x00,0x01,0x00,0x00,0xff,0xe2,0x00,0x01,0xff,0xf1,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x01,0x00,0x00,0x04,0xec,0x00,0x01,0x00,0x00,0xff,0xec,0x00,0x01, 0x01,0xae,0x00,0x82,0x00,0x01,0x00,0x00,0x00,0x46,0x00,0x01,0x00,0x1e,0x04,0xb0,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x01,0x01,0x93,0x04,0xb0,0x00,0x01,0x01,0xa6,0x04,0xb0,0x00,0x01,0x01,0xb2,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x6f,0x00,0x01,0x00,0x00,0x04,0xa6,0x00,0x01,0x00,0x0f,0x04,0x7e, 0x00,0x01,0x00,0x00,0x00,0x1e,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x01,0xff,0xf1,0x04,0x7e,0x00,0x01,0x00,0x00,0x00,0x64,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x01,0x00,0x00,0x04,0xc4,0x00,0x01,0x01,0xd9,0x04,0xba,0x00,0x01,0x01,0xd9,0x03,0xca,0x00,0x01,0x02,0x07,0x04,0x74,0x00,0x01,0x00,0xd9,0x00,0x82,0x00,0x01,0x01,0x53, 0x04,0x06,0x00,0x01,0x02,0x80,0x00,0x82,0x00,0x01,0x02,0x8c,0x06,0x40,0x00,0x01,0x03,0x93,0x05,0xdc,0x00,0x01,0x02,0x9e,0xff,0xf1,0x00,0x01,0x02,0x1c,0x06,0x40,0x00,0x01,0x03,0xe8,0x05,0xdc,0x00,0x01,0x02,0x1c,0xff,0xf1,0x00,0x01,0x02,0xee,0x06,0x40,0x00,0x01,0x04,0xc4,0x05,0xdc,0x00,0x01,0x02,0xee,0xff,0xe7,0x00,0x01, 0x02,0xbc,0x06,0x40,0x00,0x01,0x04,0xce,0x05,0xdc,0x00,0x01,0x02,0xbc,0xff,0xf1,0x00,0x01,0x02,0x58,0x06,0x40,0x00,0x01,0x03,0xd4,0x05,0xdc,0x00,0x01,0x02,0x58,0xff,0xf1,0x00,0x01,0x03,0x20,0x06,0x40,0x00,0x01,0x05,0x00,0x05,0xdc,0x00,0x01,0x03,0x20,0xff,0xe7,0x00,0x01,0x02,0xd0,0x06,0x40,0x00,0x01,0x05,0x28,0x05,0xdc, 0x00,0x01,0x02,0xd0,0xff,0xf1,0x00,0x01,0x01,0x09,0x06,0x40,0x00,0x01,0x02,0x08,0x05,0xdc,0x00,0x01,0x01,0x09,0xff,0xf1,0x00,0x01,0x01,0xd6,0x06,0x40,0x00,0x01,0x02,0x58,0x05,0xdc,0x00,0x01,0x01,0x7c,0xff,0xf1,0x00,0x01,0x02,0x8a,0x06,0x40,0x00,0x01,0x04,0xb0,0x05,0xdc,0x00,0x01,0x02,0x8a,0xff,0xf1,0x00,0x01,0x02,0x4e, 0x06,0x40,0x00,0x01,0x03,0x84,0x05,0xdc,0x00,0x01,0x02,0x4e,0xff,0xf1,0x00,0x01,0x03,0x93,0x06,0x40,0x00,0x01,0x06,0xa4,0x05,0xdc,0x00,0x01,0x03,0x93,0xff,0xf1,0x00,0x01,0x05,0x78,0x05,0xdc,0x00,0x01,0x03,0x20,0xff,0xf1,0x00,0x01,0x03,0x02,0x06,0x40,0x00,0x01,0x05,0x14,0x05,0xdc,0x00,0x01,0x03,0x02,0xff,0xe7,0x00,0x01, 0x02,0x62,0x06,0x40,0x00,0x01,0x02,0x62,0xff,0xf1,0x00,0x01,0x03,0x02,0xfe,0xf2,0x00,0x01,0x04,0x10,0x05,0xdc,0x00,0x01,0x02,0x3a,0x06,0x40,0x00,0x01,0x02,0x26,0xff,0xe7,0x00,0x01,0x02,0x26,0x06,0x40,0x00,0x01,0x04,0x4c,0x05,0xdc,0x00,0x01,0x02,0x26,0xff,0xf1,0x00,0x01,0x02,0xbc,0xff,0xe7,0x00,0x01,0x02,0x80,0x06,0x40, 0x00,0x01,0x02,0x80,0xff,0xf1,0x00,0x01,0x03,0xca,0x06,0x40,0x00,0x01,0x07,0x9e,0x05,0xdc,0x00,0x01,0x03,0xca,0xff,0xf1,0x00,0x01,0x02,0x6c,0x06,0x40,0x00,0x01,0x02,0x6c,0xff,0xf1,0x00,0x01,0x02,0x44,0x06,0x40,0x00,0x01,0x02,0x44,0xff,0xf1,0x00,0x01,0x02,0x08,0x05,0x14,0x00,0x01,0x03,0x84,0x04,0xb0,0x00,0x01,0x02,0x08, 0xff,0xe7,0x00,0x01,0x02,0x4e,0x06,0x72,0x00,0x01,0x03,0xca,0x05,0x78,0x00,0x01,0x02,0x6c,0xff,0xe7,0x00,0x01,0x02,0x26,0x05,0x14,0x00,0x01,0x03,0x98,0x04,0xb0,0x00,0x01,0x02,0x3a,0xff,0xe7,0x00,0x01,0x02,0x1c,0x06,0x72,0x00,0x01,0x04,0x4c,0x06,0x40,0x00,0x01,0x02,0x1c,0xff,0xe7,0x00,0x01,0x02,0x3a,0x05,0x14,0x00,0x01, 0x01,0xe0,0x06,0x72,0x00,0x01,0x01,0x36,0xff,0xf1,0x00,0x01,0x04,0x38,0x04,0xb0,0x00,0x01,0x02,0x3a,0xfe,0x2a,0x00,0x01,0x00,0xfa,0x06,0x72,0x00,0x01,0x01,0xa4,0x06,0x0e,0x00,0x01,0x00,0xfa,0xff,0xf1,0x00,0x01,0x00,0xf0,0x06,0x72,0x00,0x01,0x00,0x50,0xfe,0x2a,0x00,0x01,0x03,0x84,0x05,0x78,0x00,0x01,0x01,0x7c,0x06,0x40, 0x00,0x01,0x03,0x7a,0x05,0x14,0x00,0x01,0x06,0x40,0x04,0xb0,0x00,0x01,0x03,0x7a,0xff,0xf1,0x00,0x01,0x02,0x4e,0x05,0x14,0x00,0x01,0x03,0xe8,0x04,0xb0,0x00,0x01,0x02,0x58,0x05,0x14,0x00,0x01,0x02,0x58,0xff,0xe7,0x00,0x01,0x04,0x1a,0x04,0xb0,0x00,0x01,0x02,0x4e,0xfe,0x2a,0x00,0x01,0x04,0x42,0x04,0xb0,0x00,0x01,0x01,0xcc, 0x05,0x14,0x00,0x01,0x02,0xe4,0x04,0xb0,0x00,0x01,0x01,0xae,0x05,0x14,0x00,0x01,0x03,0x02,0x04,0xb0,0x00,0x01,0x01,0xae,0xff,0xe7,0x00,0x01,0x01,0x2c,0x05,0xdc,0x00,0x01,0x01,0xe0,0x05,0x78,0x00,0x01,0x01,0x80,0xff,0xe7,0x00,0x01,0x04,0x06,0x04,0xb0,0x00,0x01,0x01,0xf4,0x05,0x14,0x00,0x01,0x04,0x10,0x04,0xb0,0x00,0x01, 0x01,0xf4,0xff,0xf1,0x00,0x01,0x02,0xf3,0x05,0x14,0x00,0x01,0x05,0xf0,0x04,0xb0,0x00,0x01,0x02,0xf3,0xff,0xf1,0x00,0x01,0x01,0xd6,0x05,0x14,0x00,0x01,0x03,0xca,0x04,0xb0,0x00,0x01,0x01,0xd6,0xff,0xf1,0x00,0x01,0x01,0xf9,0x05,0x14,0x00,0x01,0x01,0xf9,0xfe,0x2a,0x00,0x01,0x01,0xe0,0x05,0x14,0x00,0x01,0x01,0xc2,0xff,0xf1, 0x00,0x01,0x02,0x9e,0x07,0x80,0x00,0x01,0x04,0x33,0x06,0x7c,0x00,0x01,0x02,0xee,0xfe,0x48,0x00,0x01,0x02,0x58,0x07,0xb0,0x00,0x01,0x03,0xd4,0x06,0xa4,0x00,0x01,0x03,0x20,0x07,0x80,0x00,0x01,0x05,0x78,0x06,0x7c,0x00,0x01,0x03,0x02,0x07,0x80,0x00,0x01,0x05,0x8c,0x06,0x7c,0x00,0x01,0x02,0xbc,0x07,0x80,0x00,0x01,0x05,0x64, 0x06,0x7c,0x00,0x01,0x02,0x08,0x06,0x54,0x00,0x01,0x03,0xd4,0x05,0x50,0x00,0x01,0x01,0xf4,0x06,0x04,0x00,0x01,0x01,0xf4,0xff,0xe7,0x00,0x01,0x02,0x08,0x06,0x04,0x00,0x01,0x03,0x84,0x05,0x50,0x00,0x01,0x02,0x3a,0xfe,0x48,0x00,0x01,0x02,0x3a,0x06,0x54,0x00,0x01,0x02,0x2b,0x06,0x54,0x00,0x01,0x02,0x2b,0xff,0xe7,0x00,0x01, 0x02,0x26,0x06,0x04,0x00,0x01,0x02,0x44,0x05,0x46,0x00,0x01,0x01,0xf4,0x05,0x1e,0x00,0x01,0x00,0xe6,0x06,0x72,0x00,0x01,0x02,0x44,0x05,0x1e,0x00,0x01,0x00,0xe6,0x06,0x0e,0x00,0x01,0x02,0x4e,0x06,0x04,0x00,0x01,0x04,0x38,0x05,0x50,0x00,0x01,0x02,0x58,0x06,0x54,0x00,0x01,0x02,0x53,0x06,0x54,0x00,0x01,0x02,0x53,0xff,0xe7, 0x00,0x01,0x02,0x58,0x06,0x04,0x00,0x01,0x02,0x26,0x06,0x54,0x00,0x01,0x04,0x56,0x05,0x50,0x00,0x01,0x02,0x3a,0x06,0x04,0x00,0x01,0x02,0x2d,0x06,0xa2,0x00,0x01,0x04,0x5a,0x06,0x02,0x00,0x01,0x02,0x2d,0xff,0xe7,0x00,0x01,0x03,0xe8,0x06,0x40,0x00,0x01,0x06,0xe2,0x05,0xdc,0x00,0x01,0x03,0xe8,0xff,0xf1,0x00,0x01,0x03,0x48, 0x05,0x14,0x00,0x01,0x06,0xa8,0x04,0xb0,0x00,0x01,0x03,0x48,0xff,0xe7,0x00,0x01,0x03,0x02,0x06,0x72,0x00,0x01,0x04,0x00,0x05,0x9a,0x00,0x01,0x01,0x4b,0xfe,0xd4,0x00,0x01,0x02,0x9e,0x07,0xb0,0x00,0x01,0x04,0x83,0x06,0x7c,0x00,0x01,0x04,0x74,0x06,0x40,0x00,0x01,0x07,0x72,0x05,0xdc,0x00,0x01,0x04,0x74,0xff,0xe7,0x00,0x01, 0x03,0xfc,0x05,0x14,0x00,0x01,0x07,0x6c,0x04,0xb0,0x00,0x01,0x03,0xfc,0xff,0xe7,0x00,0x01,0x01,0xf9,0x06,0x04,0x00,0x01,0x04,0x6a,0x05,0x50,0x00,0x01,0x02,0x44,0x07,0x80,0x00,0x01,0x05,0x00,0x06,0x7c,0x00,0x01,0x02,0x30,0x07,0xb0,0x00,0x01,0x04,0x24,0x06,0x7c,0x00,0x01,0x02,0x30,0xff,0xf1,0x00,0x01,0x04,0x33,0x06,0xa4, 0x00,0x01,0x02,0x30,0x07,0x80,0x00,0x01,0x04,0x4c,0x06,0x7c,0x00,0x01,0x01,0x09,0x07,0xb0,0x00,0x01,0x02,0x80,0x06,0xa4,0x00,0x01,0x01,0x1d,0x07,0xb0,0x00,0x01,0x01,0x1d,0xff,0xf1,0x00,0x01,0x01,0x09,0x07,0x80,0x00,0x01,0x02,0x80,0x06,0x7c,0x00,0x01,0x02,0x30,0x06,0x7c,0x00,0x01,0x03,0x02,0x07,0xb0,0x00,0x01,0x02,0xbc, 0x07,0xb0,0x00,0x01,0x00,0xfa,0x04,0xa0,0x00,0x01,0x01,0x7c,0x04,0x50,0x00,0x01,0x01,0x0e,0x06,0x72,0x00,0x01,0x01,0xa4,0x06,0x40,0x00,0x01,0x01,0x0e,0xff,0xf1,0x00,0x01,0x02,0x26,0x07,0xb0,0x00,0x01,0x04,0x24,0x06,0xa4,0x00,0x01,0x01,0x90,0x06,0x54,0x00,0x01,0x03,0x52,0x05,0x50,0x00,0x01,0x02,0x6c,0x07,0xb0,0x00,0x01, 0x05,0x00,0x06,0xa4,0x00,0x01,0x01,0xf4,0x06,0x54,0x00,0x01,0x03,0xe8,0x05,0x50,0x00,0x01,0x02,0x3c,0x06,0x94,0x00,0x01,0x04,0x79,0x05,0xf4,0x00,0x01,0x02,0x3c,0xff,0xe7,0x00,0x01,0x02,0x44,0x07,0xb0,0x00,0x01,0x01,0xf9,0x06,0x54,0x00,0x01,0x02,0x3d,0x06,0x3a,0x00,0x01,0x04,0x7b,0x04,0xfa,0x00,0x01,0x02,0x3d,0xff,0xf1, 0x00,0x01,0x02,0x5a,0x06,0x8c,0x00,0x01,0x04,0xb4,0x05,0x4c,0x00,0x01,0x02,0x5a,0xfe,0x2a,0x00,0x01,0x03,0x20,0x07,0xb0,0x00,0x01,0x05,0x50,0x06,0x7c,0x00,0x01,0x04,0x88,0x05,0x50,0x00,0x01,0x01,0x1d,0x07,0x08,0x00,0x01,0x02,0x21,0x06,0x42,0x00,0x01,0x02,0x26,0xfe,0x48,0x00,0x01,0x01,0xae,0xfe,0x48,0x00,0x01,0x02,0xee, 0x07,0xb0,0x00,0x01,0x05,0x14,0x06,0xa4,0x00,0x01,0x03,0x0c,0x07,0xb0,0x00,0x01,0x03,0x0c,0xff,0xe7,0x00,0x01,0x02,0x44,0x06,0x54,0x00,0x01,0x02,0x44,0xff,0xe7,0x00,0x01,0x02,0x9e,0x06,0x40,0x00,0x01,0x02,0x9e,0xfe,0xa2,0x00,0x01,0x02,0x08,0xfe,0xa2,0x00,0x01,0x02,0xa8,0x07,0xb0,0x00,0x01,0x05,0x1e,0x06,0xa4,0x00,0x01, 0x02,0xa8,0xff,0xf1,0x00,0x01,0x02,0x58,0xfe,0xa2,0x00,0x01,0x02,0x3a,0xfe,0xa2,0x00,0x01,0x02,0x4e,0x07,0xb0,0x00,0x01,0x03,0x84,0x06,0xa4,0x00,0x01,0x00,0xfa,0x08,0x02,0x00,0x01,0x01,0xf4,0x06,0xe0,0x00,0x01,0x03,0xc4,0x05,0xdc,0x00,0x01,0x02,0x75,0x06,0x40,0x00,0x01,0x05,0x78,0x06,0xa4,0x00,0x01,0x02,0x4e,0x06,0x54, 0x00,0x01,0x03,0x02,0xff,0xf1,0x00,0x01,0x05,0x8c,0x06,0xa4,0x00,0x01,0x02,0x62,0x07,0xb0,0x00,0x01,0x04,0x60,0x06,0xa4,0x00,0x01,0x01,0xcc,0x06,0x54,0x00,0x01,0x03,0x34,0x05,0x50,0x00,0x01,0x01,0xae,0x06,0x54,0x00,0x01,0x02,0x3a,0x07,0xb0,0x00,0x01,0x01,0x80,0xfe,0x48,0x00,0x01,0x04,0x9c,0x06,0xa4,0x00,0x01,0x01,0x2c, 0x06,0x0e,0x00,0x01,0x02,0x30,0x06,0x18,0x00,0x01,0x05,0x64,0x06,0xa4,0x00,0x01,0x02,0x8a,0x07,0x80,0x00,0x01,0x04,0xb0,0x06,0xa4,0x00,0x01,0x01,0xe0,0x06,0x54,0x00,0x01,0x02,0x4e,0x07,0x80,0x00,0x01,0x04,0xb0,0x06,0x7c,0x00,0x01,0x01,0xe0,0x06,0x04,0x00,0x01,0x03,0xf8,0x06,0x3a,0x00,0x01,0x04,0xac,0x06,0x3a,0x00,0x01, 0x03,0x7a,0xff,0xe7,0x00,0x01,0x03,0x0c,0x06,0x79,0x00,0x01,0x03,0xf6,0x06,0x29,0x00,0x01,0x02,0x8a,0xfe,0x2a,0x00,0x01,0x02,0xe8,0x05,0xb2,0x00,0x01,0x04,0x39,0x04,0xb0,0x00,0x01,0x02,0xe8,0xff,0xf1,0x00,0x01,0x02,0x9e,0x07,0x30,0x00,0x01,0x02,0xf8,0x07,0xb0,0x00,0x01,0x02,0xf8,0xff,0xe7,0x00,0x01,0x04,0xc4,0x06,0x7c, 0x00,0x01,0x02,0x44,0x07,0x30,0x00,0x01,0x03,0xfc,0x05,0x50,0x00,0x01,0x02,0x1c,0x07,0xb0,0x00,0x01,0x02,0x26,0x07,0x80,0x00,0x01,0x03,0xd4,0x06,0x40,0x00,0x01,0x05,0x50,0x06,0xa4,0x00,0x01,0x02,0x44,0xfe,0x2a,0x00,0x01,0x03,0x20,0xfe,0x70,0x00,0x01,0x02,0x3a,0x06,0x16,0x00,0x01,0x04,0x66,0x05,0xa0,0x00,0x01,0x02,0xd0, 0x07,0xb0,0x00,0x01,0x02,0x6c,0x07,0xb2,0x00,0x01,0x04,0x1a,0x06,0x18,0x00,0x01,0x02,0xd7,0x06,0x3a,0x00,0x01,0x05,0x5e,0x05,0xea,0x00,0x01,0x02,0xd7,0xff,0xf1,0x00,0x01,0x02,0x43,0x06,0x3c,0x00,0x01,0x04,0x37,0x05,0x4c,0x00,0x01,0x02,0x43,0xff,0xf1,0x00,0x01,0x01,0x0e,0x07,0x80,0x00,0x01,0x00,0xfa,0x06,0x0e,0x00,0x01, 0x01,0x09,0x07,0x30,0x00,0x01,0x00,0xfa,0x05,0xd2,0x00,0x01,0x01,0x0e,0x07,0xb0,0x00,0x01,0x00,0xe1,0x06,0x72,0x00,0x01,0x01,0x0e,0x06,0x40,0x00,0x01,0x01,0x0e,0xfe,0xa2,0x00,0x01,0x00,0xfa,0xfe,0xa2,0x00,0x01,0x01,0xd6,0x07,0xb0,0x00,0x01,0x02,0xd0,0x06,0xa4,0x00,0x01,0x01,0xf4,0x05,0x6e,0x00,0x01,0x02,0x8a,0xfe,0x70, 0x00,0x01,0x02,0x4e,0xfe,0x70,0x00,0x01,0x01,0xfd,0x04,0xa0,0x00,0x01,0x03,0xfa,0x04,0xa0,0x00,0x01,0x01,0xfd,0xff,0xf1,0x00,0x01,0x02,0x4e,0xfe,0x48,0x00,0x01,0x00,0xfa,0xfe,0x48,0x00,0x01,0x03,0x20,0xfe,0x2a,0x00,0x01,0x03,0x02,0x07,0x30,0x00,0x01,0x02,0x9e,0xfe,0x70,0x00,0x01,0x00,0xfa,0xfe,0x70,0x00,0x01,0x02,0x18, 0x05,0xea,0x00,0x01,0x04,0x81,0x05,0xea,0x00,0x01,0x02,0x18,0xff,0xf1,0x00,0x01,0x01,0x2c,0x05,0x7f,0x00,0x01,0x02,0xb6,0x05,0x2f,0x00,0x01,0x02,0xbc,0x07,0x30,0x00,0x01,0x02,0xbc,0xfe,0xa2,0x00,0x01,0x02,0x26,0xfe,0xa2,0x00,0x01,0x03,0xd4,0x07,0xb0,0x00,0x01,0x07,0x9e,0x06,0x7c,0x00,0x01,0x02,0xf8,0x06,0x54,0x00,0x01, 0x05,0xf0,0x05,0x50,0x00,0x01,0x02,0x08,0xfe,0x2a,0x00,0x01,0x01,0x7c,0x06,0x72,0x00,0x01,0x02,0x8e,0x06,0x52,0x00,0x01,0x03,0xca,0x07,0xb0,0x00,0x01,0x02,0xf3,0x06,0x54,0x00,0x01,0x03,0xca,0x07,0x80,0x00,0x01,0x02,0xf3,0x06,0x04,0x00,0x01,0x04,0x1a,0x05,0x50,0x00,0x01,0x06,0x1a,0x06,0x7c,0x00,0x01,0x04,0xc7,0x04,0xb0, 0x00,0x01,0x02,0xbc,0x06,0xd6,0x00,0x01,0x05,0xfa,0x06,0x7c,0x00,0x01,0x02,0x26,0x05,0x46,0x00,0x01,0x05,0x04,0x05,0x00,0x00,0x01,0x02,0xb2,0xfe,0xc0,0x00,0x01,0x02,0x12,0x05,0x14,0x00,0x01,0x02,0x12,0xfe,0xc0,0x00,0x01,0x02,0x44,0xfe,0xc0,0x00,0x01,0x02,0x4e,0xfe,0xc0,0x00,0x01,0x02,0x30,0x06,0xc2,0x00,0x01,0x01,0xf4, 0x05,0x82,0x00,0x01,0x01,0x09,0xfe,0xc0,0x00,0x01,0x00,0xfa,0xfe,0xc0,0x00,0x01,0x03,0x02,0xfe,0xc0,0x00,0x01,0x02,0x58,0xfe,0xc0,0x00,0x01,0x02,0xbc,0xfe,0xc0,0x00,0x01,0x02,0x26,0xfe,0xc0,0x00,0x01,0x02,0x26,0xfe,0x84,0x00,0x01,0x01,0x80,0xfe,0x84,0x00,0x01,0x02,0xe2,0x06,0x52,0x00,0x01,0x05,0x74,0x05,0x62,0x00,0x01, 0x02,0xe2,0xff,0xe7,0x00,0x01,0x02,0x03,0x04,0xb8,0x00,0x01,0x03,0xdf,0x03,0xc8,0x00,0x01,0x02,0x03,0xff,0xe7,0x00,0x01,0x02,0x58,0xfe,0x48,0x00,0x01,0x02,0x9e,0xfe,0x02,0x00,0x01,0x02,0x08,0xfe,0x02,0x00,0x01,0x02,0x1c,0x07,0x80,0x00,0x01,0x03,0xe8,0x06,0x7c,0x00,0x01,0x02,0x30,0x06,0x40,0x00,0x01,0x02,0x30,0xfe,0xc0, 0x00,0x01,0x02,0x6c,0xfe,0xc0,0x00,0x01,0x02,0x44,0xff,0x24,0x00,0x01,0x02,0x6c,0xff,0x24,0x00,0x01,0x05,0x1e,0x06,0x7c,0x00,0x01,0x02,0xa8,0x06,0x40,0x00,0x01,0x02,0xa8,0xfe,0xc0,0x00,0x01,0x02,0x58,0x06,0x72,0x00,0x01,0x02,0x8a,0xff,0x24,0x00,0x01,0x02,0x4e,0xff,0x24,0x00,0x01,0x02,0xbc,0xfe,0x70,0x00,0x01,0x02,0x1c, 0xfe,0x70,0x00,0x01,0x02,0xb2,0x06,0x40,0x00,0x01,0x02,0xb2,0xfe,0x2a,0x00,0x01,0x02,0x44,0x05,0x14,0x00,0x01,0x02,0x30,0xfe,0xa2,0x00,0x01,0x02,0x12,0x07,0x80,0x00,0x01,0x02,0x12,0xff,0xf1,0x00,0x01,0x01,0xe0,0x07,0x62,0x00,0x01,0x02,0xee,0x06,0xe0,0x00,0x01,0x03,0x20,0x07,0x30,0x00,0x01,0x02,0xd0,0x07,0x80,0x00,0x01, 0x05,0x28,0x06,0x7c,0x00,0x01,0x02,0x4e,0x06,0xd6,0x00,0x01,0x03,0xca,0x06,0x18,0x00,0x01,0x02,0xee,0xfe,0xc0,0x00,0x01,0x02,0x3a,0x06,0x72,0x00,0x01,0x02,0x3a,0xfe,0xc0,0x00,0x01,0x02,0x80,0x07,0xb2,0x00,0x01,0x04,0x1a,0x06,0x54,0x00,0x01,0x02,0xd0,0xfe,0x2a,0x00,0x01,0x02,0xd0,0xfe,0x84,0x00,0x01,0x02,0x4e,0xfe,0x84, 0x00,0x01,0x01,0x09,0xfe,0xa2,0x00,0x01,0x02,0x8a,0x07,0xb0,0x00,0x01,0x02,0x4e,0x07,0xb2,0x00,0x01,0x02,0x80,0xfe,0xc0,0x00,0x01,0x02,0x26,0x06,0x72,0x00,0x01,0x02,0x30,0x06,0x72,0x00,0x01,0x02,0x30,0xff,0x24,0x00,0x01,0x02,0x26,0x07,0x30,0x00,0x01,0x03,0xd4,0x06,0x7c,0x00,0x01,0x00,0xfa,0x07,0x12,0x00,0x01,0x00,0xfa, 0xff,0x24,0x00,0x01,0x02,0x2b,0x06,0x40,0x00,0x01,0x02,0x2b,0xfe,0x2a,0x00,0x01,0x00,0xfa,0xfe,0x2a,0x00,0x01,0x03,0x93,0x07,0xb0,0x00,0x01,0x06,0xa4,0x06,0xa4,0x00,0x01,0x03,0x7a,0x06,0x54,0x00,0x01,0x06,0x40,0x05,0x50,0x00,0x01,0x03,0x5c,0x07,0x80,0x00,0x01,0x06,0xa4,0x06,0x7c,0x00,0x01,0x03,0x5c,0xfe,0xc0,0x00,0x01, 0x03,0x7a,0xfe,0xc0,0x00,0x01,0x02,0xf8,0x07,0x80,0x00,0x01,0x02,0xf8,0xff,0xf1,0x00,0x01,0x02,0xf8,0x06,0x40,0x00,0x01,0x02,0xf8,0xfe,0xc0,0x00,0x01,0x02,0xf8,0xff,0x24,0x00,0x01,0x02,0x58,0xff,0x24,0x00,0x01,0x03,0x02,0xfe,0x2a,0x00,0x01,0x04,0x38,0x06,0xa4,0x00,0x01,0x04,0x38,0x06,0x7c,0x00,0x01,0x02,0x6c,0x06,0x04, 0x00,0x01,0x02,0x6c,0xfe,0x2a,0x00,0x01,0x02,0x58,0x07,0x80,0x00,0x01,0x04,0x60,0x06,0x7c,0x00,0x01,0x01,0x90,0x06,0x04,0x00,0x01,0x02,0x8a,0xfe,0xc0,0x00,0x01,0x02,0x9e,0xff,0x24,0x00,0x01,0x02,0x4e,0xff,0xe7,0x00,0x01,0x01,0xcc,0xff,0xe7,0x00,0x01,0x01,0xc2,0x05,0x14,0x00,0x01,0x01,0xc2,0xfe,0xc0,0x00,0x01,0x04,0x24, 0x07,0x1c,0x00,0x01,0x03,0x52,0x05,0xf0,0x00,0x01,0x02,0x44,0x07,0xd0,0x00,0x01,0x01,0xae,0x06,0xa4,0x00,0x01,0x02,0x62,0x07,0x80,0x00,0x01,0x02,0x62,0xfe,0xc0,0x00,0x01,0x01,0xd6,0xfe,0xc0,0x00,0x01,0x01,0x2c,0x07,0x1c,0x00,0x01,0x01,0x68,0xfe,0xc0,0x00,0x01,0x02,0x26,0xff,0x24,0x00,0x01,0x01,0x80,0xff,0x24,0x00,0x01, 0x02,0x26,0xfe,0x2a,0x00,0x01,0x01,0x68,0xfe,0x2a,0x00,0x01,0x02,0x1c,0x05,0x14,0x00,0x01,0x02,0x1c,0xfe,0xc0,0x00,0x01,0x02,0x2b,0x05,0x14,0x00,0x01,0x02,0x80,0x07,0x80,0x00,0x01,0x05,0x14,0x06,0x7c,0x00,0x01,0x04,0x60,0x05,0x50,0x00,0x01,0x01,0xf4,0xfe,0xc0,0x00,0x01,0x03,0xde,0x07,0x80,0x00,0x01,0x07,0xee,0x06,0x7c, 0x00,0x01,0x02,0xf8,0x06,0x04,0x00,0x01,0x03,0xca,0xfe,0xc0,0x00,0x01,0x02,0xf3,0xfe,0xc0,0x00,0x01,0x02,0x6c,0x07,0x80,0x00,0x01,0x04,0xce,0x06,0x7c,0x00,0x01,0x01,0xd6,0x06,0x24,0x00,0x01,0x03,0xca,0x05,0x50,0x00,0x01,0x01,0xe0,0xff,0xf1,0x00,0x01,0x01,0xe0,0xfe,0xc0,0x00,0x01,0x01,0xcc,0xff,0x24,0x00,0x01,0x01,0x54, 0x07,0x1c,0x00,0x01,0x02,0xd0,0x06,0x18,0x00,0x01,0x03,0xd4,0x05,0x82,0x00,0x01,0x01,0x8b,0x07,0xb2,0x00,0x01,0x02,0x8e,0x06,0x92,0x00,0x01,0x00,0xf7,0xff,0xf1,0x00,0x01,0x04,0x64,0x05,0x4c,0x00,0x01,0x02,0x5a,0xff,0xe7,0x00,0x01,0x02,0x74,0x06,0x3a,0x00,0x01,0x04,0x98,0x05,0x4a,0x00,0x01,0x02,0x74,0xff,0xf1,0x00,0x01, 0x02,0x49,0x06,0x3a,0x00,0x01,0x04,0x93,0x05,0x9a,0x00,0x01,0x02,0x49,0xff,0xe7,0x00,0x01,0x04,0xb4,0x05,0xec,0x00,0x01,0x02,0x4f,0x06,0x52,0x00,0x01,0x04,0x4e,0x05,0x12,0x00,0x01,0x02,0x4f,0xff,0xe7,0x00,0x01,0x02,0x12,0x06,0x52,0x00,0x01,0x04,0xa6,0x05,0x62,0x00,0x01,0x02,0x12,0xff,0xe7,0x00,0x01,0x02,0xfa,0x06,0xd6, 0x00,0x01,0x05,0x96,0x06,0x83,0x00,0x01,0x02,0xfa,0xff,0xe7,0x00,0x01,0x02,0x3c,0x05,0x46,0x00,0x01,0x04,0x5a,0x05,0x25,0x00,0x01,0x02,0xce,0x06,0x3a,0x00,0x01,0x05,0x4c,0x05,0x4a,0x00,0x01,0x03,0x2a,0x06,0x3a,0x00,0x01,0x05,0x9e,0x05,0x4a,0x00,0x01,0x03,0x2a,0xff,0xf1,0x00,0x01,0x02,0x4a,0x06,0x3a,0x00,0x01,0x04,0x44, 0x05,0xea,0x00,0x01,0x02,0x4a,0xff,0xe7,0x00,0x01,0x04,0xb4,0x06,0x3c,0x00,0x01,0x02,0x5e,0x04,0xb8,0x00,0x01,0x04,0x6c,0x03,0xc8,0x00,0x01,0x02,0x5e,0xfe,0x2a,0x00,0x01,0x01,0xe0,0x06,0x3a,0x00,0x01,0x03,0xbe,0x05,0xea,0x00,0x01,0x02,0x58,0x06,0x52,0x00,0x01,0x04,0x04,0x05,0xb2,0x00,0x01,0x02,0x44,0x06,0x3a,0x00,0x01, 0x03,0xe8,0x05,0xea,0x00,0x01,0x01,0x2c,0xfe,0x84,0x00,0x01,0x03,0x20,0x06,0xd6,0x00,0x01,0x05,0xd9,0x06,0x83,0x00,0x01,0x02,0x7c,0x06,0x3a,0x00,0x01,0x05,0x48,0x05,0xea,0x00,0x01,0x02,0x7c,0xfe,0x2a,0x00,0x01,0x03,0x7f,0x06,0x8c,0x00,0x01,0x06,0xae,0x05,0x4c,0x00,0x01,0x03,0x7f,0xff,0xe7,0x00,0x01,0x01,0x36,0x06,0x72, 0x00,0x01,0x01,0xfe,0x05,0xea,0x00,0x01,0x01,0x1d,0x06,0x3a,0x00,0x01,0x02,0x3a,0x05,0xea,0x00,0x01,0x02,0x52,0x06,0x52,0x00,0x01,0x04,0xf4,0x06,0x02,0x00,0x01,0x02,0x52,0xff,0xf1,0x00,0x01,0x01,0xfe,0x06,0xa2,0x00,0x01,0x03,0xfc,0x06,0xa2,0x00,0x01,0x01,0xfe,0xff,0xf1,0x00,0x01,0x00,0xf8,0x06,0x8c,0x00,0x01,0x01,0xa0, 0x06,0x3c,0x00,0x01,0x00,0xf8,0xff,0xf1,0x00,0x01,0x01,0xfe,0x06,0x8e,0x00,0x01,0x03,0xac,0x05,0x4e,0x00,0x01,0x03,0x91,0x06,0x3a,0x00,0x01,0x06,0xd3,0x05,0xea,0x00,0x01,0x03,0x91,0xff,0xe7,0x00,0x01,0x02,0xfe,0x06,0x3a,0x00,0x01,0x05,0xac,0x05,0xea,0x00,0x01,0x03,0x97,0xff,0xf1,0x00,0x01,0x02,0x4d,0x04,0xb8,0x00,0x01, 0x04,0x4a,0x04,0x18,0x00,0x01,0x02,0x4d,0xfe,0x70,0x00,0x01,0x03,0x04,0x06,0x52,0x00,0x01,0x05,0xb8,0x05,0x62,0x00,0x01,0x03,0x04,0xff,0xe7,0x00,0x01,0x03,0xe0,0x06,0x52,0x00,0x01,0x07,0x48,0x06,0x02,0x00,0x01,0x03,0xe0,0xff,0xe7,0x00,0x01,0x03,0x29,0x04,0xb8,0x00,0x01,0x06,0x02,0x04,0x68,0x00,0x01,0x03,0x29,0xff,0xe7, 0x00,0x01,0x02,0x67,0x06,0x3a,0x00,0x01,0x04,0x7f,0x05,0x9a,0x00,0x01,0x02,0x67,0xff,0xf1,0x00,0x01,0x02,0x5a,0x06,0xa2,0x00,0x01,0x04,0x64,0x05,0x62,0x00,0x01,0x02,0x4e,0x06,0x3a,0x00,0x01,0x04,0x4c,0x04,0xfa,0x00,0x01,0x02,0x4e,0xff,0x51,0x00,0x01,0x02,0x10,0x06,0x3a,0x00,0x01,0x03,0xd1,0x05,0xea,0x00,0x01,0x02,0x10, 0xff,0xf1,0x00,0x01,0x00,0xaa,0x06,0xa2,0x00,0x01,0x02,0x0e,0x05,0xb2,0x00,0x01,0x01,0x6b,0xfe,0x2a,0x00,0x01,0x01,0x5c,0x05,0xcf,0x00,0x01,0x02,0xb8,0x05,0x2f,0x00,0x01,0x01,0x5c,0xfe,0x84,0x00,0x01,0x02,0x19,0x06,0x3a,0x00,0x01,0x04,0x33,0x05,0xea,0x00,0x01,0x02,0x19,0xff,0xf1,0x00,0x01,0x01,0x5c,0x06,0xa2,0x00,0x01, 0x03,0x08,0x06,0x52,0x00,0x01,0x01,0x5c,0xff,0xe7,0x00,0x01,0x02,0x19,0xfe,0x84,0x00,0x01,0x03,0x05,0x06,0x3a,0x00,0x01,0x06,0x0a,0x05,0xea,0x00,0x01,0x03,0x05,0xff,0xe7,0x00,0x01,0x02,0xd9,0x06,0x52,0x00,0x01,0x05,0x12,0x06,0x02,0x00,0x01,0x02,0xd9,0xff,0xe7,0x00,0x01,0x02,0x81,0x06,0x52,0x00,0x01,0x04,0xde,0x06,0x02, 0x00,0x01,0x02,0x81,0xff,0xf1,0x00,0x01,0x02,0x7b,0x05,0x14,0x00,0x01,0x04,0xc3,0x04,0x18,0x00,0x01,0x02,0x7b,0xfe,0x2a,0x00,0x01,0x02,0xee,0xfe,0x2a,0x00,0x01,0x02,0x28,0x06,0x3a,0x00,0x01,0x03,0xb0,0x06,0x3a,0x00,0x01,0x02,0x28,0xff,0xe7,0x00,0x01,0x01,0x85,0x04,0xa0,0x00,0x01,0x02,0xba,0x04,0xa0,0x00,0x01,0x01,0x85, 0xff,0xe7,0x00,0x01,0x02,0x2f,0x04,0xb8,0x00,0x01,0x04,0x5e,0x04,0x18,0x00,0x01,0x01,0x4b,0xfe,0x2a,0x00,0x01,0x07,0xbc,0x07,0xb0,0x00,0x01,0x09,0xe8,0x06,0xa4,0x00,0x01,0x07,0xbc,0xff,0xf1,0x00,0x01,0x07,0x6c,0x06,0x54,0x00,0x01,0x09,0x1c,0x05,0x50,0x00,0x01,0x07,0x6c,0xff,0xf1,0x00,0x01,0x06,0x86,0x06,0x54,0x00,0x01, 0x08,0x33,0x05,0x50,0x00,0x01,0x06,0x86,0xff,0xf1,0x00,0x01,0x05,0xd2,0x06,0x3a,0x00,0x01,0x06,0x89,0x05,0xdc,0x00,0x01,0x05,0x7b,0xff,0xe7,0x00,0x01,0x04,0xc4,0x06,0x79,0x00,0x01,0x05,0x72,0x06,0x0e,0x00,0x01,0x04,0x6e,0xfe,0x2a,0x00,0x01,0x03,0x0c,0x06,0x8c,0x00,0x01,0x03,0xb1,0x06,0x0e,0x00,0x01,0x02,0xa8,0xfe,0x2a, 0x00,0x01,0x07,0x8f,0x06,0x3a,0x00,0x01,0x08,0x44,0x05,0xdc,0x00,0x01,0x07,0x40,0xff,0xe7,0x00,0x01,0x06,0xc2,0x06,0x79,0x00,0x01,0x07,0x6e,0x06,0x0e,0x00,0x01,0x06,0x72,0xfe,0x2a,0x00,0x01,0x05,0x78,0x06,0x79,0x00,0x01,0x06,0x27,0x06,0x0e,0x00,0x01,0x05,0x23,0xfe,0x2a,0x00,0x01,0x01,0xfe,0x06,0x54,0x00,0x01,0x01,0xfe, 0xff,0xe7,0x00,0x01,0x02,0x44,0x05,0x82,0x00,0x01,0x02,0xc6,0x07,0xb0,0x00,0x01,0x02,0xc6,0xff,0xe7,0x00,0x01,0x04,0x92,0x07,0x30,0x00,0x01,0x06,0x92,0x06,0x7c,0x00,0x01,0x04,0x92,0xff,0xf1,0x00,0x01,0x03,0x50,0x06,0x04,0x00,0x01,0x06,0x50,0x05,0x50,0x00,0x01,0x03,0x50,0xff,0xe7,0x00,0x01,0x02,0xda,0x07,0xb0,0x00,0x01, 0x02,0xda,0xff,0xe7,0x00,0x01,0x01,0xfe,0x07,0xb2,0x00,0x01,0x03,0x02,0xfe,0x70,0x00,0x01,0x02,0x58,0xfe,0x70,0x00,0x01,0x02,0x08,0x07,0xb0,0x00,0x01,0x01,0x7c,0x06,0x54,0x00,0x01,0x01,0x7c,0xfe,0x2a,0x00,0x01,0x02,0x94,0x06,0x0e,0x00,0x01,0x07,0xda,0x06,0xe0,0x00,0x01,0x09,0xe8,0x05,0xdc,0x00,0x01,0x07,0xda,0xff,0xf1, 0x00,0x01,0x07,0x6c,0x05,0xb4,0x00,0x01,0x09,0x1c,0x04,0xb0,0x00,0x01,0x06,0x86,0x05,0xb4,0x00,0x01,0x08,0x33,0x04,0xb0,0x00,0x01,0x07,0xae,0x05,0xdc,0x00,0x01,0x02,0xc1,0x06,0x52,0x00,0x01,0x05,0x83,0x05,0xb2,0x00,0x01,0x01,0x62,0xfe,0x2a,0x00,0x01,0x04,0x83,0x06,0xa4,0x00,0x01,0x04,0x4c,0x06,0xa4,0x00,0x01,0x02,0x30, 0x06,0xa4,0x00,0x01,0x01,0xf4,0x05,0x50,0x00,0x01,0x01,0xb8,0x06,0x54,0x00,0x01,0x01,0xb8,0x06,0x52,0x00,0x01,0x03,0xb8,0x05,0x62,0x00,0x01,0x01,0xb8,0xfe,0x2a,0x00,0x01,0x01,0x90,0x04,0xb8,0x00,0x01,0x03,0x20,0x03,0xc8,0x00,0x01,0x01,0x90,0xfe,0x2a,0x00,0x01,0x04,0x1a,0x06,0xa4,0x00,0x01,0x02,0xef,0x06,0x52,0x00,0x01, 0x05,0x3f,0x05,0xb2,0x00,0x01,0x02,0xef,0xfe,0x2a,0x00,0x01,0x02,0x5c,0x06,0x3a,0x00,0x01,0x04,0x68,0x05,0x9a,0x00,0x01,0x02,0x5c,0xff,0xe7,0x00,0x01,0x02,0x44,0x06,0x8c,0x00,0x01,0x04,0x39,0x05,0xec,0x00,0x01,0x02,0x48,0xff,0x24,0x00,0x01,0x01,0xcf,0xff,0x24,0x00,0x01,0x02,0x05,0x04,0xb8,0x00,0x01,0x03,0xba,0x03,0xc8, 0x00,0x01,0x02,0x05,0xff,0xe7,0x00,0x01,0x02,0x79,0x04,0xb8,0x00,0x01,0x04,0xa2,0x04,0x68,0x00,0x01,0x02,0x79,0xff,0xe7,0x00,0x01,0x04,0xa2,0x04,0x18,0x00,0x01,0x02,0x5b,0x06,0xa2,0x00,0x01,0x04,0x66,0x05,0xaa,0x00,0x01,0x02,0x5b,0xff,0xe7,0x00,0x01,0x01,0xab,0x04,0xb8,0x00,0x01,0x03,0x6a,0x03,0xc8,0x00,0x01,0x01,0xab, 0xff,0xe7,0x00,0x01,0x02,0x08,0x04,0xb8,0x00,0x01,0x02,0x08,0xff,0x51,0x00,0x01,0x02,0x5b,0x06,0x8c,0x00,0x01,0x04,0x66,0x05,0xec,0x00,0x01,0x02,0x5b,0xfe,0x2a,0x00,0x01,0x05,0x56,0x06,0x52,0x00,0x01,0x02,0x17,0x04,0xb8,0x00,0x01,0x02,0x17,0xff,0xe7,0x00,0x01,0x01,0xf5,0x04,0xb8,0x00,0x01,0x04,0x96,0x03,0xc8,0x00,0x01, 0x01,0xf5,0xff,0xe7,0x00,0x01,0x01,0xbb,0x04,0xb8,0x00,0x01,0x02,0xfe,0x03,0xc8,0x00,0x01,0x01,0xbb,0xff,0xe7,0x00,0x01,0x01,0x93,0x04,0xb8,0x00,0x01,0x01,0x93,0xff,0xe7,0x00,0x01,0x03,0xa0,0x03,0xc8,0x00,0x01,0x02,0x34,0x04,0xb8,0x00,0x01,0x04,0x18,0x03,0xc8,0x00,0x01,0x02,0x34,0xff,0xe7,0x00,0x01,0x01,0x1c,0x04,0xa0, 0x00,0x01,0x02,0x38,0x04,0x50,0x00,0x01,0x01,0x1c,0xfe,0x2a,0x00,0x01,0x02,0x5b,0x06,0x72,0x00,0x01,0x02,0x1e,0x04,0xb8,0x00,0x01,0x03,0xec,0x04,0x18,0x00,0x01,0x02,0x1e,0xff,0xe7,0x00,0x01,0x01,0xea,0x04,0xa0,0x00,0x01,0x03,0xd5,0x04,0x50,0x00,0x01,0x01,0xea,0xfe,0x2a,0x00,0x01,0x01,0xd4,0x04,0xb8,0x00,0x01,0x03,0xa8, 0x04,0x68,0x00,0x01,0x01,0xd4,0xff,0xe7,0x00,0x01,0x02,0x43,0x04,0xe2,0x00,0x01,0x04,0x37,0x04,0x50,0x00,0x01,0x02,0x43,0xfe,0x2a,0x00,0x01,0x02,0x43,0x06,0xa2,0x00,0x01,0x04,0x1a,0x05,0x78,0x00,0x01,0x01,0x0c,0x06,0x29,0x00,0x01,0x01,0xc8,0x05,0x89,0x00,0x01,0x01,0x0c,0xff,0xf1,0x00,0x01,0x00,0xe1,0x04,0xa0,0x00,0x01, 0x01,0xea,0x04,0x50,0x00,0x01,0x01,0x40,0x04,0xa0,0x00,0x01,0x02,0x90,0x04,0x50,0x00,0x01,0x01,0x40,0xff,0xf1,0x00,0x01,0x01,0x18,0x06,0x8c,0x00,0x01,0x02,0x3e,0x05,0x9c,0x00,0x01,0x01,0x18,0xff,0xf1,0x00,0x01,0x01,0x9a,0x06,0x8c,0x00,0x01,0x03,0x02,0x05,0x9c,0x00,0x01,0x01,0x9a,0xff,0xf1,0x00,0x01,0x00,0xf7,0x06,0x8c, 0x00,0x01,0x01,0xee,0x05,0x9c,0x00,0x01,0x01,0x3f,0xfe,0x2a,0x00,0x01,0x02,0xf8,0x06,0x72,0x00,0x01,0x04,0xd3,0x04,0xb0,0x00,0x01,0x02,0xf8,0xfe,0x2a,0x00,0x01,0x03,0x7a,0x04,0xa0,0x00,0x01,0x06,0x94,0x04,0x50,0x00,0x01,0x03,0x7a,0xfe,0x2a,0x00,0x01,0x02,0x11,0xff,0xf1,0x00,0x01,0x02,0x58,0x04,0xa0,0x00,0x01,0x04,0x60, 0x04,0x50,0x00,0x01,0x02,0x58,0x04,0xb8,0x00,0x01,0x04,0x60,0x03,0xc8,0x00,0x01,0x03,0x6b,0x04,0xb6,0x00,0x01,0x05,0x96,0x04,0x66,0x00,0x01,0x03,0x6b,0xff,0xe7,0x00,0x01,0x02,0xdf,0x04,0xb8,0x00,0x01,0x05,0x74,0x03,0xc8,0x00,0x01,0x02,0xdf,0xff,0xe7,0x00,0x01,0x02,0x8d,0x06,0x8c,0x00,0x01,0x04,0xca,0x05,0x4c,0x00,0x01, 0x02,0x8d,0xfe,0x2a,0x00,0x01,0x01,0xd1,0x04,0xa0,0x00,0x01,0x02,0x78,0x04,0x50,0x00,0x01,0x01,0x64,0xff,0xe7,0x00,0x01,0x01,0xd1,0x06,0x8c,0x00,0x01,0x02,0x78,0x06,0x3c,0x00,0x01,0x01,0x64,0xfe,0x2a,0x00,0x01,0x01,0xcc,0x04,0xb2,0x00,0x01,0x01,0x86,0x04,0xb8,0x00,0x01,0x02,0xfe,0x04,0x68,0x00,0x01,0x00,0xe1,0xff,0xf1, 0x00,0x01,0x01,0x18,0x04,0xb8,0x00,0x01,0x02,0x5e,0x04,0x18,0x00,0x01,0x01,0xcc,0xff,0xf1,0x00,0x01,0x01,0xef,0x04,0xa0,0x00,0x01,0x03,0xa2,0x04,0x00,0x00,0x01,0x01,0xef,0xff,0xf1,0x00,0x01,0x03,0xa2,0x04,0x50,0x00,0x01,0x01,0xae,0xfe,0xa2,0x00,0x01,0x01,0x4a,0x06,0xa2,0x00,0x01,0x02,0x9a,0x06,0x52,0x00,0x01,0x00,0xb4, 0xfe,0x2a,0x00,0x01,0x01,0x5e,0x06,0xa2,0x00,0x01,0x02,0xb0,0x06,0x52,0x00,0x01,0x00,0xc8,0xfe,0x2a,0x00,0x01,0x00,0xb4,0x06,0xa2,0x00,0x01,0x01,0xfe,0x05,0xb2,0x00,0x01,0x01,0x4a,0xff,0xe7,0x00,0x01,0x01,0x68,0x06,0xa2,0x00,0x01,0x02,0xe4,0x06,0x52,0x00,0x01,0x00,0xdc,0xfe,0x2a,0x00,0x01,0x01,0x2c,0x04,0xb6,0x00,0x01, 0x02,0x68,0x03,0xc6,0x00,0x01,0x01,0x90,0xfe,0xd4,0x00,0x01,0x01,0x80,0xfe,0x2a,0x00,0x01,0x02,0x65,0x04,0xa0,0x00,0x01,0x04,0x7b,0x04,0x50,0x00,0x01,0x02,0x65,0xff,0xe7,0x00,0x01,0x02,0x61,0x04,0xa0,0x00,0x01,0x04,0xc2,0x04,0x50,0x00,0x01,0x02,0x61,0xff,0xe7,0x00,0x01,0x02,0x3b,0x04,0xb8,0x00,0x01,0x04,0x27,0x04,0x68, 0x00,0x01,0x02,0x3b,0xff,0xe7,0x00,0x01,0x01,0xf4,0x04,0xa0,0x00,0x01,0x03,0x35,0x04,0x50,0x00,0x01,0x02,0xe4,0x04,0xa0,0x00,0x01,0x05,0x28,0x04,0x50,0x00,0x01,0x02,0xe4,0xff,0xf1,0x00,0x01,0x01,0xef,0x06,0x8c,0x00,0x01,0x03,0xdf,0x05,0x9c,0x00,0x01,0x01,0xab,0x04,0xa0,0x00,0x01,0x03,0x56,0x04,0x50,0x00,0x01,0x01,0xab, 0xff,0xf1,0x00,0x01,0x01,0xc2,0xfe,0xd4,0x00,0x01,0x02,0x0c,0xff,0x51,0x00,0x01,0x01,0x90,0x05,0x14,0x00,0x01,0x01,0x76,0x06,0xa2,0x00,0x01,0x03,0x3c,0x05,0xb2,0x00,0x01,0x01,0x2c,0xff,0xf1,0x00,0x01,0x02,0xec,0x05,0xb2,0x00,0x01,0x01,0xa4,0xff,0xf1,0x00,0x01,0x02,0x9c,0x05,0x4c,0x00,0x01,0x01,0x58,0xff,0xe7,0x00,0x01, 0x02,0x3a,0x04,0xb8,0x00,0x01,0x03,0xba,0x04,0x68,0x00,0x01,0x02,0x71,0x06,0xa4,0x00,0x01,0x04,0x74,0x05,0xdc,0x00,0x01,0x02,0x71,0xff,0xe7,0x00,0x01,0x03,0x8f,0x04,0x00,0x00,0x01,0x02,0x31,0x04,0xb8,0x00,0x01,0x04,0x12,0x03,0xc8,0x00,0x01,0x02,0x31,0xff,0xe7,0x00,0x01,0x02,0x8a,0x05,0x46,0x00,0x01,0x04,0xdc,0x04,0xe2, 0x00,0x01,0x02,0x8a,0xff,0xe7,0x00,0x01,0x02,0x43,0x04,0xa0,0x00,0x01,0x01,0x04,0x06,0x79,0x00,0x01,0x01,0x9e,0x05,0x89,0x00,0x01,0x00,0x62,0xfe,0x2a,0x00,0x01,0x01,0xfe,0x04,0xa0,0x00,0x01,0x03,0xac,0x04,0x50,0x00,0x01,0x01,0xfe,0xfe,0x2a,0x00,0x01,0x01,0xe0,0x04,0xa0,0x00,0x01,0x03,0x14,0x03,0xb0,0x00,0x01,0x05,0x56, 0x06,0x02,0x00,0x01,0x05,0xaa,0x06,0x72,0x00,0x01,0x07,0x54,0x04,0xb0,0x00,0x01,0x05,0xaa,0xff,0xf1,0x00,0x01,0x07,0x98,0x04,0xb0,0x00,0x01,0x05,0xaa,0xfe,0x2a,0x00,0x01,0x07,0x7f,0x04,0xb0,0x00,0x01,0x05,0xaa,0xff,0x51,0x00,0x01,0x03,0x6f,0x05,0x78,0x00,0x01,0x04,0x98,0x04,0xb0,0x00,0x01,0x03,0x6f,0xff,0xf1,0x00,0x01, 0x02,0xaa,0x06,0x52,0x00,0x01,0x04,0x6f,0x06,0x52,0x00,0x01,0x02,0xaa,0xfe,0x2a,0x00,0x01,0x04,0x05,0x05,0x78,0x00,0x01,0x05,0x6e,0x04,0x8f,0x00,0x01,0x04,0x05,0xff,0xe7,0x00,0x01,0x04,0x70,0x06,0x72,0x00,0x01,0x04,0x70,0xfe,0x2a,0x00,0x01,0x03,0x3f,0x06,0x72,0x00,0x01,0x04,0x54,0x04,0xb0,0x00,0x01,0x03,0x3f,0xff,0xe7, 0x00,0x01,0x02,0xee,0x06,0x72,0x00,0x01,0x04,0x8e,0x04,0xb0,0x00,0x01,0x02,0xee,0xff,0xf1,0x00,0x01,0x02,0x08,0x06,0x3a,0x00,0x01,0x04,0x44,0x05,0x9a,0x00,0x01,0x01,0xfa,0xff,0xf1,0x00,0x01,0x01,0xfa,0x06,0x3a,0x00,0x01,0x00,0xf0,0x05,0x14,0x00,0x01,0x01,0xa4,0x04,0xb0,0x00,0x01,0x01,0x09,0x05,0x14,0x00,0x01,0x02,0x1c, 0x06,0x8c,0x00,0x01,0x04,0x87,0x06,0x8c,0x00,0x01,0x02,0x1c,0xfe,0x2a,0x00,0x01,0x00,0xfa,0x06,0x8c,0x00,0x01,0x01,0x96,0x06,0x8c,0x00,0x01,0x02,0x4e,0x04,0xb8,0x00,0x01,0x03,0xec,0x04,0xb8,0x00,0x01,0x01,0x2c,0x05,0xcf,0x00,0x01,0x01,0xe5,0x05,0x7f,0x00,0x01,0x01,0x2c,0xfe,0x2a,0x00,0x01,0x04,0x6c,0x04,0x68,0x00,0x01, 0x03,0xbd,0x06,0x72,0x00,0x01,0x06,0xba,0x05,0x78,0x00,0x01,0x03,0xbd,0xff,0xe7,0x00,0x01,0x03,0xbd,0x05,0x14,0x00,0x01,0x06,0xba,0x04,0xb0,0x00,0x01,0x03,0xbd,0xfe,0x2a,0x00,0x01,0x02,0x8c,0x06,0x90,0x00,0x01,0x03,0x93,0x06,0x7c,0x00,0x01,0x02,0x9e,0xff,0xa1,0x00,0x01,0x02,0xee,0x06,0x90,0x00,0x01,0x04,0x7c,0x06,0x2c, 0x00,0x01,0x02,0xee,0xff,0x97,0x00,0x01,0x02,0x26,0x05,0xb4,0x00,0x01,0x04,0x52,0x04,0xd1,0x00,0x01,0x02,0x3a,0xff,0x97,0x00,0x01,0x02,0x26,0x06,0x90,0x00,0x01,0x04,0x9c,0x06,0x2c,0x00,0x01,0x02,0x26,0xff,0xa1,0x00,0x01,0x01,0xae,0xfe,0x8e,0x00,0x01,0x01,0xc2,0xfe,0x8e,0x00,0x01,0x02,0x0b,0x06,0x7a,0x00,0x01,0x03,0xc6, 0x06,0x02,0x00,0x01,0x01,0x9b,0x05,0x14,0x00,0x01,0x02,0xd6,0x04,0xb0,0x00,0x01,0x00,0xe6,0xff,0xf1,0x00,0x01,0x02,0x5b,0x04,0xb8,0x00,0x01,0x04,0xb6,0x04,0x18,0x00,0x01,0x01,0xd8,0x06,0x3a,0x00,0x01,0x03,0xb1,0x05,0x9a,0x00,0x01,0x01,0xd8,0xff,0xf1,0x00,0x01,0x02,0x4f,0x04,0xa0,0x00,0x01,0x04,0x9f,0x04,0x50,0x00,0x01, 0x02,0x4f,0xfe,0x2a,0x00,0x01,0x05,0x11,0x06,0xc2,0x00,0x01,0x06,0x83,0x05,0x78,0x00,0x01,0x05,0x11,0xff,0xf1,0x00,0x01,0x01,0x48,0x04,0xa0,0x00,0x01,0x01,0x48,0xff,0xf1,0x00,0x01,0x01,0xa4,0x04,0xa0,0x00,0x01,0x02,0x23,0x04,0xa0,0x00,0x01,0x03,0xf6,0x04,0x50,0x00,0x01,0x02,0x23,0xff,0xe7,0x00,0x01,0x02,0x6c,0xfe,0xa2, 0x00,0x01,0x02,0x1c,0xfe,0xa2,0x00,0x01,0x01,0x36,0xfe,0xa2,0x00,0x01,0x02,0x4e,0xfe,0xa2,0x00,0x01,0x03,0x7a,0xfe,0xa2,0x00,0x01,0x01,0xf4,0xfe,0xa2,0x00,0x01,0x01,0xd6,0xfe,0xa2,0x00,0x01,0x01,0xc2,0xfe,0xa2,0x00,0x01,0x01,0xbb,0xfe,0xa2,0x00,0x01,0x01,0x93,0xfe,0xa2,0x00,0x01,0x01,0xdd,0x05,0x14,0x00,0x01,0x01,0xdd, 0xfe,0xa2,0x00,0x01,0x01,0xc4,0x04,0xa0,0x00,0x01,0x03,0x89,0x04,0x50,0x00,0x01,0x01,0xc4,0xfe,0x2a,0x00,0x01,0x02,0x60,0x04,0xee,0x00,0x01,0x04,0x71,0x04,0x4e,0x00,0x01,0x02,0x60,0xff,0xe7,0x00,0x01,0x01,0x7a,0x05,0xd0,0x00,0x01,0x02,0xa4,0x05,0x30,0x00,0x01,0x02,0x58,0xff,0x6a,0x00,0x01,0x02,0x3a,0x05,0x8d,0x00,0x01, 0x04,0x2f,0x05,0x00,0x00,0x01,0x03,0x00,0x06,0x52,0x00,0x01,0x05,0x4d,0x06,0x02,0x00,0x01,0x03,0x00,0xff,0x06,0x00,0x01,0x02,0x5b,0x05,0x14,0x00,0x01,0x04,0x34,0x04,0x68,0x00,0x01,0x02,0x5b,0xff,0x06,0x00,0x01,0x01,0xce,0x04,0xa1,0x00,0x01,0x03,0x20,0x04,0xa1,0x00,0x01,0x01,0xce,0xff,0xf1,0x00,0x01,0x01,0x22,0x06,0x72, 0x00,0x01,0x01,0x22,0xff,0xf1,0x00,0x01,0x02,0x9e,0xfe,0x8e,0x00,0x01,0x02,0x08,0x05,0x8d,0x00,0x01,0x03,0x9a,0x05,0x00,0x00,0x01,0x01,0x2c,0x05,0xea,0x00,0x01,0x02,0x66,0x05,0xc8,0x00,0x01,0x01,0x80,0xff,0x06,0x00,0x01,0x04,0x4c,0x04,0xb0,0x00,0x01,0x02,0xcc,0x04,0xb8,0x00,0x01,0x04,0xb0,0x04,0xb0,0x00,0x01,0x02,0xcc, 0xff,0xe7,0x00,0x01,0x01,0x18,0x04,0xba,0x00,0x01,0x01,0x04,0x04,0xba,0x00,0x01,0x00,0x00,0x04,0xba,0x00,0x01,0xff,0xf6,0x04,0xb0,0x00,0x01,0x02,0x26,0x07,0x33,0x00,0x01,0x02,0x58,0x07,0x62,0x00,0x01,0x02,0x76,0x07,0xa8,0x00,0x01,0x02,0x94,0x06,0x3a,0x00,0x01,0x02,0x06,0x06,0x3a,0x00,0x01,0x02,0xff,0x06,0x3a,0x00,0x01, 0x02,0xee,0x07,0x4a,0x00,0x01,0x03,0x0c,0x07,0xa8,0x00,0x01,0x03,0x04,0x06,0x6a,0x00,0x01,0x03,0x04,0x06,0x3a,0x00,0x01,0x02,0x40,0x06,0x52,0x00,0x01,0x02,0x40,0x06,0x3a,0x00,0x01,0x03,0x22,0x06,0x3a,0x00,0x01,0x02,0x77,0x06,0x6a,0x00,0x01,0x02,0x58,0x06,0x3a,0x00,0x01,0x04,0x13,0x06,0x6a,0x00,0x01,0x03,0xd4,0x06,0x3a, 0x00,0x01,0x02,0x09,0x04,0xd0,0x00,0x01,0x02,0x08,0x04,0xd0,0x00,0x01,0x02,0x17,0x04,0xd0,0x00,0x01,0x02,0x53,0x04,0xa0,0x00,0x01,0x02,0x53,0x04,0xd0,0x00,0x01,0x02,0x3f,0x05,0xee,0x00,0x01,0x02,0x58,0x06,0x5e,0x00,0x01,0x02,0x58,0x04,0xd0,0x00,0x01,0x01,0xef,0x05,0x4a,0x00,0x01,0x01,0xef,0x04,0xd0,0x00,0x01,0x02,0xd6, 0x04,0xa0,0x00,0x01,0x02,0xd0,0x04,0xd0,0x00,0x01,0x01,0xd9,0x04,0xd0,0x00,0x01,0x03,0x40,0x04,0xd0,0x00,0x01,0x03,0x20,0x04,0xd0,0x00,0x01,0x02,0x03,0x04,0xa0,0x00,0x01,0x02,0x03,0x04,0xd0,0x00,0x01,0x02,0x17,0x05,0x9f,0x00,0x01,0x02,0x17,0x06,0x2c,0x00,0x01,0x01,0xdc,0x06,0x19,0x00,0x01,0x01,0xf4,0x06,0x5e,0x00,0x01, 0x02,0xe2,0x06,0x6a,0x00,0x01,0x02,0xe2,0x06,0x3a,0x00,0x01,0x00,0xc8,0x02,0xf8,0x00,0x01,0x03,0x0c,0x05,0x9a,0x00,0x01,0x03,0xc0,0x05,0x22,0x00,0x01,0x04,0x8e,0x05,0x82,0x00,0x01,0x04,0xaf,0x05,0x07,0x00,0x01,0x03,0x94,0x05,0x9a,0x00,0x01,0x03,0x9d,0x05,0x9a,0x00,0x01,0x04,0xcf,0x05,0x40,0x00,0x01,0x04,0xf7,0x05,0x9a, 0x00,0x01,0x01,0xe0,0x05,0x9a,0x00,0x01,0x02,0x2d,0x05,0xa0,0x00,0x01,0x04,0x2c,0x05,0x9a,0x00,0x01,0x01,0x6a,0x05,0x9a,0x00,0x01,0x06,0x6d,0x05,0x9a,0x00,0x01,0x05,0x45,0x05,0x9a,0x00,0x01,0x05,0x51,0x04,0x94,0x00,0x01,0x04,0x03,0x05,0x22,0x00,0x01,0x03,0xf7,0x05,0x22,0x00,0x01,0x03,0xad,0x05,0x82,0x00,0x01,0x04,0x01, 0x05,0x9a,0x00,0x01,0x04,0xd1,0x05,0xa0,0x00,0x01,0x04,0xd1,0x05,0x9a,0x00,0x01,0x07,0x47,0x05,0x9a,0x00,0x01,0x04,0x38,0x05,0x9a,0x00,0x01,0x04,0x4c,0x05,0x9a,0x00,0x01,0x03,0x70,0x03,0x8e,0x00,0x01,0x04,0x0f,0x03,0x92,0x00,0x01,0x03,0x5d,0x03,0xdf,0x00,0x01,0x04,0x08,0x05,0xe9,0x00,0x01,0x03,0x98,0x03,0x8e,0x00,0x01, 0x02,0xa2,0x05,0xf0,0x00,0x01,0x04,0x08,0x03,0xff,0x00,0x01,0x03,0xe2,0x03,0x35,0x00,0x01,0x01,0x4a,0x03,0xfc,0x00,0x01,0x01,0x4b,0x03,0xf8,0x00,0x01,0x03,0x82,0x04,0x02,0x00,0x01,0x01,0x40,0x05,0xe9,0x00,0x01,0x06,0x40,0x03,0xa0,0x00,0x01,0x03,0xd4,0x03,0xa0,0x00,0x01,0x03,0xfc,0x03,0x8e,0x00,0x01,0x03,0xfc,0x03,0xaf, 0x00,0x01,0x04,0x08,0x04,0x03,0x00,0x01,0x02,0xb3,0x04,0x06,0x00,0x01,0x02,0xe4,0x03,0xfc,0x00,0x01,0x02,0x74,0x03,0xfe,0x00,0x01,0x03,0xde,0x03,0xfc,0x00,0x01,0x03,0xc1,0x04,0x00,0x00,0x01,0x05,0xa0,0x04,0x00,0x00,0x01,0x03,0x66,0x04,0x00,0x00,0x01,0x03,0xc0,0x03,0xfc,0x00,0x01,0x03,0x52,0x04,0x00,0x00,0x01,0x06,0x30, 0x03,0x8e,0x00,0x01,0x04,0x3e,0x03,0x07,0x00,0x01,0x06,0xf4,0x03,0x8e,0x00,0x01,0x01,0x40,0x04,0x06,0x00,0x01,0x03,0x84,0x03,0xb8,0x00,0x01,0x03,0x6e,0x04,0x0c,0x00,0x01,0x04,0x9e,0x04,0x0c,0x00,0x01,0x03,0xd8,0x03,0xf1,0x00,0x01,0x02,0xf1,0x03,0xb8,0x00,0x01,0x03,0x42,0x03,0xe8,0x00,0x01,0x02,0xd6,0x03,0xfc,0x00,0x01, 0x02,0x80,0x03,0xfc,0x00,0x01,0x03,0xde,0x03,0xb8,0x00,0x01,0x03,0x9c,0x04,0x1a,0x00,0x01,0x01,0x61,0x03,0xfc,0x00,0x01,0x02,0x33,0x04,0x00,0x00,0x01,0x05,0x39,0x04,0x08,0x00,0x01,0x04,0x02,0x03,0xfc,0x00,0x01,0x04,0x5c,0x04,0x0f,0x00,0x01,0x02,0x56,0x03,0xfd,0x00,0x01,0x00,0x00,0x02,0x21,0x00,0x01,0x00,0x00,0x02,0x12, 0x00,0x01,0x00,0x00,0x02,0x58,0x00,0x01,0x02,0x94,0x02,0xcd,0x00,0x01,0x02,0x4b,0x02,0xcd,0x00,0x01,0x02,0xde,0x02,0xe5,0x00,0x01,0x02,0xee,0x02,0xcd,0x00,0x01,0x02,0x06,0x02,0xcd,0x00,0x01,0x01,0xf4,0x02,0xcd,0x00,0x01,0x02,0xbe,0x02,0xe5,0x00,0x01,0x02,0xd7,0x02,0xcd,0x00,0x01,0x01,0x10,0x02,0xcd,0x00,0x01,0x01,0xd1, 0x02,0xd9,0x00,0x01,0x00,0xed,0x03,0xeb,0x00,0x01,0x01,0x0e,0x02,0xcd,0x00,0x01,0x03,0xa2,0x03,0x42,0x00,0x01,0x02,0xfe,0x02,0xcd,0x00,0x01,0x03,0x04,0x02,0xe5,0x00,0x01,0x02,0x64,0x03,0xeb,0x00,0x01,0x03,0x04,0x02,0xe2,0x00,0x01,0x02,0x20,0x02,0xe5,0x00,0x01,0x02,0x18,0x02,0xcd,0x00,0x01,0x02,0xbf,0x02,0xd9,0x00,0x01, 0x02,0x7c,0x02,0xcd,0x00,0x01,0x03,0xbc,0x02,0xcd,0x00,0x01,0x02,0x5c,0x02,0xcd,0x00,0x01,0x02,0x36,0x01,0xae,0x00,0x01,0x02,0x48,0x02,0xcd,0x00,0x01,0x02,0x09,0x01,0x41,0x00,0x01,0x02,0x80,0x01,0xce,0x00,0x01,0x02,0x3d,0x02,0x18,0x00,0x01,0x02,0x44,0x02,0x1b,0x00,0x01,0x02,0x35,0x02,0x58,0x00,0x01,0x01,0x40,0x02,0x67, 0x00,0x01,0x02,0x37,0x01,0xfc,0x00,0x01,0x01,0x01,0x04,0x71,0x00,0x01,0x01,0x03,0x02,0x26,0x00,0x01,0x00,0xf8,0x01,0xef,0x00,0x01,0x00,0xfa,0x04,0x25,0x00,0x01,0x00,0xfa,0x02,0xf9,0x00,0x01,0x03,0x72,0x02,0x0c,0x00,0x01,0x02,0x4c,0x02,0x0c,0x00,0x01,0x02,0x53,0x02,0x18,0x00,0x01,0x02,0x7c,0x01,0xef,0x00,0x01,0x02,0x3d, 0x02,0x13,0x00,0x01,0x01,0x01,0x01,0xe5,0x00,0x01,0x01,0xb2,0x02,0x18,0x00,0x01,0x01,0x2c,0x02,0x1b,0x00,0x01,0x02,0x39,0x02,0x0c,0x00,0x01,0x02,0x17,0x02,0x6c,0x00,0x01,0x02,0xe4,0x02,0x00,0x00,0x01,0x01,0xd6,0x02,0x00,0x00,0x01,0x01,0xef,0x02,0x5a,0x00,0x01,0x01,0xcf,0x02,0x00,0x00,0x01,0x02,0x58,0x01,0xd7,0x00,0x01, 0x03,0x04,0x02,0xff,0x00,0x01,0x01,0xb2,0x01,0xd7,0x00,0x01,0x01,0x9d,0x01,0xd0,0x00,0x01,0x02,0x3c,0x01,0xcf,0x00,0x01,0x00,0xe5,0x02,0x0c,0x00,0x01,0x00,0xfd,0x03,0x28,0x00,0x01,0x02,0xf6,0x00,0x6f,0x00,0x01,0x00,0x00,0x05,0xc8,0x00,0x01,0x00,0x00,0x05,0xbe,0x00,0x01,0x00,0x00,0xff,0x6a,0x00,0x01,0x05,0x12,0x07,0x6c, 0x00,0x01,0x05,0x12,0xfe,0x5c,0x00,0x01,0x04,0x2f,0x07,0x6c,0x00,0x01,0x04,0x2f,0xfe,0x5c,0x00,0x01,0x04,0x8c,0x07,0x6c,0x00,0x01,0x04,0x8c,0xfe,0x5c,0x00,0x01,0x05,0x3e,0x07,0x6c,0x00,0x01,0x05,0x3e,0xfe,0x5c,0x00,0x01,0x03,0xb4,0x07,0x6c,0x00,0x01,0x03,0xb4,0xfe,0x5c,0x00,0x01,0x03,0x94,0x07,0x6c,0x00,0x01,0x03,0x94, 0xfe,0x5c,0x00,0x01,0x04,0xec,0x07,0x6c,0x00,0x01,0x04,0xec,0xfe,0x5c,0x00,0x01,0x04,0xf2,0x07,0x6c,0x00,0x01,0x04,0xf2,0xfe,0x5c,0x00,0x01,0x01,0xf0,0x07,0x6c,0x00,0x01,0x01,0xf0,0xfe,0x5c,0x00,0x01,0x02,0x2b,0x07,0x6c,0x00,0x01,0x02,0x2b,0xfe,0x5c,0x00,0x01,0x04,0xa2,0x07,0x6c,0x00,0x01,0x04,0xa2,0xfe,0x5c,0x00,0x01, 0x03,0xa4,0x07,0x6c,0x00,0x01,0x03,0xa4,0xfe,0x5c,0x00,0x01,0x06,0x72,0x07,0x6c,0x00,0x01,0x06,0x72,0xfe,0x5c,0x00,0x01,0x05,0x40,0x07,0x6c,0x00,0x01,0x05,0x40,0xfe,0x5c,0x00,0x01,0x05,0xaa,0x07,0x6c,0x00,0x01,0x05,0xaa,0xfe,0x5c,0x00,0x01,0x04,0x29,0x07,0x6c,0x00,0x01,0x04,0x29,0xfe,0x5c,0x00,0x01,0x05,0xcc,0x07,0x6c, 0x00,0x01,0x05,0xcc,0xfe,0x5c,0x00,0x01,0x04,0xc0,0x07,0x6c,0x00,0x01,0x04,0xc0,0xfe,0x5c,0x00,0x01,0x03,0xde,0x07,0x6c,0x00,0x01,0x03,0xde,0xfe,0x5c,0x00,0x01,0x04,0x0c,0x07,0x6c,0x00,0x01,0x04,0x0c,0xfe,0x5c,0x00,0x01,0x04,0xd5,0x07,0x6c,0x00,0x01,0x04,0xd5,0xfe,0x5c,0x00,0x01,0x04,0xe6,0x07,0x6c,0x00,0x01,0x04,0xe6, 0xfe,0x5c,0x00,0x01,0x07,0x60,0x07,0x6c,0x00,0x01,0x07,0x60,0xfe,0x5c,0x00,0x01,0x04,0x9a,0x07,0x6c,0x00,0x01,0x04,0x9a,0xfe,0x5c,0x00,0x01,0x04,0x60,0x07,0x6c,0x00,0x01,0x04,0x60,0xfe,0x5c,0x00,0x01,0x04,0x64,0x07,0x6c,0x00,0x01,0x04,0x64,0xfe,0x5c,0x00,0x01,0x03,0x83,0x07,0x6c,0x00,0x01,0x03,0x83,0xfe,0x5c,0x00,0x01, 0x04,0x54,0x07,0x6c,0x00,0x01,0x04,0x54,0xfe,0x5c,0x00,0x01,0x03,0x62,0x07,0x6c,0x00,0x01,0x03,0x62,0xfe,0x5c,0x00,0x01,0x04,0x10,0x07,0x6c,0x00,0x01,0x04,0x10,0xfe,0x5c,0x00,0x01,0x03,0xdd,0x07,0x6c,0x00,0x01,0x03,0xdd,0xfe,0x5c,0x00,0x01,0x02,0xa0,0x07,0x6c,0x00,0x01,0x02,0xa0,0xfe,0x5c,0x00,0x01,0x03,0xf8,0x07,0x6c, 0x00,0x01,0x03,0xf8,0xfe,0x5c,0x00,0x01,0x01,0x66,0x07,0x6c,0x00,0x01,0x01,0x66,0xfe,0x5c,0x00,0x01,0x01,0x4a,0x07,0x6c,0x00,0x01,0x01,0x4a,0xfe,0x5c,0x00,0x01,0x06,0x54,0x07,0x6c,0x00,0x01,0x06,0x54,0xfe,0x5c,0x00,0x01,0x04,0x50,0x07,0x6c,0x00,0x01,0x04,0x50,0xfe,0x5c,0x00,0x01,0x02,0xbc,0x07,0x6c,0x00,0x01,0x02,0xbc, 0xfe,0x5c,0x00,0x01,0x03,0x0f,0x07,0x6c,0x00,0x01,0x03,0x0f,0xfe,0x5c,0x00,0x01,0x02,0x81,0x07,0x6c,0x00,0x01,0x02,0x81,0xfe,0x5c,0x00,0x01,0x03,0xe2,0x07,0x6c,0x00,0x01,0x03,0xe2,0xfe,0x5c,0x00,0x01,0x03,0xcb,0x07,0x6c,0x00,0x01,0x03,0xcb,0xfe,0x5c,0x00,0x01,0x05,0xb0,0x07,0x6c,0x00,0x01,0x05,0xb0,0xfe,0x5c,0x00,0x01, 0x03,0x92,0x07,0x6c,0x00,0x01,0x03,0x92,0xfe,0x5c,0x00,0x01,0x03,0xd5,0x07,0x6c,0x00,0x01,0x03,0xd5,0xfe,0x5c,0x00,0x01,0x03,0x70,0x07,0x6c,0x00,0x01,0x03,0x70,0xfe,0x5c,0x00,0x01,0x05,0x12,0x08,0x34,0x00,0x01,0x05,0x40,0x08,0x34,0x00,0x01,0x05,0xaa,0x08,0x34,0x00,0x01,0x04,0xd5,0x08,0x34,0x00,0x01,0x01,0xdd,0x07,0x6c, 0x00,0x01,0x01,0xdd,0xfe,0x5c,0x00,0x01,0x01,0x71,0x07,0x6c,0x00,0x01,0x01,0x71,0xfe,0x5c,0x00,0x01,0x02,0x07,0x07,0x6c,0x00,0x01,0x02,0x07,0xfe,0x5c,0x00,0x01,0x02,0x10,0x07,0x6c,0x00,0x01,0x02,0x10,0xfe,0x5c,0x00,0x01,0x04,0x14,0x07,0x6c,0x00,0x01,0x04,0x14,0xfe,0x5c,0x00,0x01,0x06,0x83,0x07,0x6c,0x00,0x01,0x06,0x83, 0xfe,0x5c,0x00,0x01,0x06,0x56,0x07,0x6c,0x00,0x01,0x06,0x56,0xfe,0x5c,0x00,0x01,0x04,0x96,0x07,0x6c,0x00,0x01,0x04,0x96,0xfe,0x5c,0x00,0x01,0x03,0xb8,0x07,0x6c,0x00,0x01,0x03,0xb8,0xfe,0x5c,0x00,0x01,0x07,0x12,0x07,0x6c,0x00,0x01,0x07,0x12,0xfe,0x5c,0x00,0x01,0x07,0x21,0x07,0x6c,0x00,0x01,0x07,0x21,0xfe,0x5c,0x00,0x01, 0x03,0xb4,0x08,0x34,0x00,0x01,0x01,0xfd,0x08,0x34,0x00,0x01,0x01,0xfd,0xfe,0x5c,0x00,0x01,0x02,0x30,0x08,0x34,0x00,0x01,0x02,0x30,0xfe,0x5c,0x00,0x01,0x02,0x38,0x08,0x34,0x00,0x01,0x02,0x38,0xfe,0x5c,0x00,0x01,0x01,0xf0,0x08,0x34,0x00,0x01,0x02,0x12,0x07,0x6c,0x00,0x01,0x02,0x12,0xfe,0x5c,0x00,0x01,0x03,0xde,0x08,0x34, 0x00,0x01,0x04,0x64,0x08,0x34,0x00,0x01,0x04,0x18,0x07,0x6c,0x00,0x01,0x04,0x18,0xfe,0x5c,0x00,0x01,0x04,0x60,0x08,0x34,0x00,0x01,0x04,0xec,0x08,0x34,0x00,0x01,0x04,0x8c,0x08,0x34,0x00,0x01,0x04,0x98,0x07,0x6c,0x00,0x01,0x04,0x98,0xfe,0x5c,0x00,0x01,0x05,0x3e,0x08,0x34,0x00,0x01,0x05,0xb3,0x07,0x6c,0x00,0x01,0x05,0xb3, 0xfe,0x5c,0x00,0x01,0x03,0xa4,0x08,0x34,0x00,0x01,0x02,0x13,0x07,0x6c,0x00,0x01,0x02,0x13,0xfe,0x5c,0x00,0x01,0x02,0xc3,0x07,0x6c,0x00,0x01,0x02,0xc3,0xfe,0x5c,0x00,0x01,0x02,0x87,0x07,0x6c,0x00,0x01,0x02,0x87,0xfe,0x5c,0x00,0x01,0x04,0xc0,0x08,0x34,0x00,0x01,0x02,0xc9,0x07,0x6c,0x00,0x01,0x02,0xc9,0xfe,0x5c,0x00,0x01, 0x02,0x9a,0x07,0x6c,0x00,0x01,0x02,0x9a,0xfe,0x5c,0x00,0x01,0x04,0x0c,0x08,0x34,0x00,0x01,0x03,0xd3,0x07,0x6c,0x00,0x01,0x03,0xd3,0xfe,0x5c,0x00,0x01,0x04,0x4e,0x07,0x6c,0x00,0x01,0x04,0x4e,0xfe,0x5c,0x00,0x01,0x03,0x6c,0x07,0x6c,0x00,0x01,0x03,0x6c,0xfe,0x5c,0x00,0x01,0x04,0x4a,0x07,0x6c,0x00,0x01,0x04,0x4a,0xfe,0x5c, 0x00,0x01,0x04,0xf2,0x08,0x34,0x00,0x01,0x03,0xf8,0x08,0x34,0x00,0x01,0x05,0x92,0x07,0x6c,0x00,0x01,0x05,0x92,0xfe,0x5c,0x00,0x01,0x02,0x51,0x07,0x6c,0x00,0x01,0x02,0x51,0xfe,0x5c,0x00,0x01,0x02,0x2e,0x07,0x6c,0x00,0x01,0x02,0x2e,0xfe,0x5c,0x00,0x01,0x02,0x0f,0x07,0x6c,0x00,0x01,0x02,0x0f,0xfe,0x5c,0x00,0x01,0x01,0xeb, 0x07,0x6c,0x00,0x01,0x01,0xeb,0xfe,0x5c,0x00,0x01,0x02,0x23,0x08,0x34,0x00,0x01,0x02,0x23,0xfe,0x5c,0x00,0x01,0x02,0x00,0x07,0x6c,0x00,0x01,0x02,0x00,0xfe,0x5c,0x00,0x01,0x02,0xf2,0x07,0x6c,0x00,0x01,0x02,0xf2,0xfe,0x5c,0x00,0x01,0x02,0x62,0x07,0x6c,0x00,0x01,0x02,0x62,0xfe,0x5c,0x00,0x01,0x07,0x60,0x08,0x34,0x00,0x01, 0x06,0x3a,0x07,0x6c,0x00,0x01,0x06,0x3a,0xfe,0x5c,0x00,0x01,0x04,0xa9,0x07,0x6c,0x00,0x01,0x04,0xa9,0xfe,0x5c,0x00,0x01,0x05,0xd0,0x07,0x6c,0x00,0x01,0x05,0xd0,0xfe,0x5c,0x00,0x01,0x04,0xc7,0x07,0x6c,0x00,0x01,0x04,0xc7,0xfe,0x5c,0x00,0x01,0x04,0x52,0x07,0x6c,0x00,0x01,0x04,0x52,0xfe,0x5c,0x00,0x01,0x03,0xe9,0x07,0x6c, 0x00,0x01,0x03,0xe9,0xfe,0x5c,0x00,0x01,0x03,0x83,0x08,0x34,0x00,0x01,0x04,0x6f,0x08,0x34,0x00,0x01,0x04,0x6f,0xfe,0x5c,0x00,0x01,0x04,0x5a,0x07,0x6c,0x00,0x01,0x04,0x5a,0xfe,0x5c,0x00,0x01,0x04,0x20,0x08,0x34,0x00,0x01,0x04,0x20,0xfe,0x5c,0x00,0x01,0x04,0x32,0x07,0x6c,0x00,0x01,0x04,0x32,0xfe,0x5c,0x00,0x01,0x03,0xdd, 0x08,0x34,0x00,0x01,0x01,0xa1,0x07,0x6c,0x00,0x01,0x01,0xa1,0xfe,0x5c,0x00,0x01,0x04,0x50,0x08,0x34,0x00,0x01,0x06,0x3a,0x08,0x34,0x00,0x01,0x05,0xd0,0x08,0x34,0x00,0x01,0x05,0x66,0x07,0x6c,0x00,0x01,0x05,0x66,0xfe,0x5c,0x00,0x01,0x03,0xcf,0x07,0x6c,0x00,0x01,0x03,0xcf,0xfe,0x5c,0x00,0x01,0x04,0x2f,0x08,0x34,0x00,0x01, 0x03,0x94,0x08,0x34,0x00,0x01,0x02,0xa0,0x08,0x34,0x00,0x01,0x02,0x50,0x07,0x6c,0x00,0x01,0x02,0x50,0xfe,0x5c,0x00,0x01,0x02,0x3a,0x07,0x6c,0x00,0x01,0x02,0x3a,0xfe,0x5c,0x00,0x01,0x02,0x39,0x08,0x34,0x00,0x01,0x02,0x39,0xfe,0x5c,0x00,0x01,0x02,0x1b,0x08,0x34,0x00,0x01,0x02,0x1b,0xfe,0x5c,0x00,0x01,0x04,0xa2,0x08,0x34, 0x00,0x01,0x01,0x5b,0x07,0x6c,0x00,0x01,0x01,0x5b,0xfe,0x5c,0x00,0x01,0x01,0xf6,0x08,0x34,0x00,0x01,0x01,0xf6,0xfe,0x5c,0x00,0x01,0x01,0xf8,0x07,0x6c,0x00,0x01,0x01,0xf8,0xfe,0x5c,0x00,0x01,0x06,0x72,0x08,0x34,0x00,0x01,0x04,0x29,0x08,0x34,0x00,0x01,0x02,0xc7,0x07,0x6c,0x00,0x01,0x02,0xc7,0xfe,0x5c,0x00,0x01,0x03,0x0f, 0x08,0x34,0x00,0x01,0x02,0x95,0x07,0x6c,0x00,0x01,0x02,0x95,0xfe,0x5c,0x00,0x01,0x02,0x86,0x07,0x6c,0x00,0x01,0x02,0x86,0xfe,0x5c,0x00,0x01,0x03,0xe2,0x08,0x34,0x00,0x01,0x04,0xe6,0x08,0x34,0x00,0x01,0x04,0x9a,0x08,0x34,0x00,0x01,0x02,0x62,0x08,0x34,0x00,0x01,0x04,0x81,0x07,0x6c,0x00,0x01,0x04,0x81,0xfe,0x5c,0x00,0x01, 0x04,0x38,0x07,0x6c,0x00,0x01,0x04,0x38,0xfe,0x5c,0x00,0x01,0x05,0x42,0x07,0x6c,0x00,0x01,0x05,0x42,0xfe,0x5c,0x00,0x01,0x04,0x0e,0x07,0x6c,0x00,0x01,0x04,0x0e,0xfe,0x5c,0x00,0x01,0x05,0x90,0x07,0x6c,0x00,0x01,0x05,0x90,0xfe,0x5c,0x00,0x01,0x03,0xd7,0x07,0x6c,0x00,0x01,0x03,0xd7,0xfe,0x5c,0x00,0x01,0x04,0x5c,0x07,0x6c, 0x00,0x01,0x04,0x5c,0xfe,0x5c,0x00,0x01,0x03,0x52,0x07,0x6c,0x00,0x01,0x03,0x52,0xfe,0x5c,0x00,0x01,0x03,0xf4,0x07,0x6c,0x00,0x01,0x03,0xf4,0xfe,0x5c,0x00,0x01,0x05,0x85,0x07,0x6c,0x00,0x01,0x05,0x85,0xfe,0x5c,0x00,0x01,0x06,0x87,0x07,0x6c,0x00,0x01,0x06,0x87,0xfe,0x5c,0x00,0x01,0x02,0x25,0x07,0x6c,0x00,0x01,0x02,0x25, 0xfe,0x5c,0x00,0x01,0x01,0xdb,0x07,0x6c,0x00,0x01,0x01,0xdb,0xfe,0x5c,0x00,0x01,0x03,0xdf,0x07,0x6c,0x00,0x01,0x03,0xdf,0xfe,0x5c,0x00,0x01,0x06,0x66,0x07,0x6c,0x00,0x01,0x06,0x66,0xfe,0x5c,0x00,0x01,0x07,0x04,0x07,0x6c,0x00,0x01,0x07,0x04,0xfe,0x5c,0x00,0x01,0x05,0xac,0x07,0x6c,0x00,0x01,0x05,0xac,0xfe,0x5c,0x00,0x01, 0x04,0x7b,0x07,0x6c,0x00,0x01,0x04,0x7b,0xfe,0x5c,0x00,0x01,0x04,0x62,0x07,0x6c,0x00,0x01,0x04,0x62,0xfe,0x5c,0x00,0x01,0x03,0xc7,0x07,0x6c,0x00,0x01,0x03,0xc7,0xfe,0x5c,0x00,0x01,0x02,0xfd,0x07,0x6c,0x00,0x01,0x02,0xfd,0xfe,0x5c,0x00,0x01,0x03,0xf0,0x07,0x6c,0x00,0x01,0x03,0xf0,0xfe,0x5c,0x00,0x01,0x05,0xa8,0x07,0x6c, 0x00,0x01,0x05,0xa8,0xfe,0x5c,0x00,0x01,0x05,0x54,0x07,0x6c,0x00,0x01,0x05,0x54,0xfe,0x5c,0x00,0x01,0x04,0x7f,0x07,0x6c,0x00,0x01,0x04,0x7f,0xfe,0x5c,0x00,0x01,0x04,0x83,0x07,0x6c,0x00,0x01,0x04,0x83,0xfe,0x5c,0x00,0x01,0x04,0xd7,0x07,0x6c,0x00,0x01,0x04,0xd7,0xfe,0x5c,0x00,0x01,0x03,0xc8,0x07,0x6c,0x00,0x01,0x03,0xc8, 0xfe,0x5c,0x00,0x01,0x02,0xcd,0x07,0x6c,0x00,0x01,0x02,0xcd,0xfe,0x5c,0x00,0x01,0x02,0xe4,0x07,0x6c,0x00,0x01,0x02,0xe4,0xfe,0x5c,0x00,0x01,0x04,0x16,0x07,0x6c,0x00,0x01,0x04,0x16,0xfe,0x5c,0x00,0x01,0x09,0xbc,0x08,0x34,0x00,0x01,0x09,0xbc,0xfe,0x5c,0x00,0x01,0x08,0xef,0x07,0x6c,0x00,0x01,0x08,0xef,0xfe,0x5c,0x00,0x01, 0x08,0x05,0x07,0x6c,0x00,0x01,0x08,0x05,0xfe,0x5c,0x00,0x01,0x06,0x29,0x07,0x6c,0x00,0x01,0x06,0x29,0xfe,0x5c,0x00,0x01,0x05,0x39,0x07,0x6c,0x00,0x01,0x05,0x39,0xfe,0x5c,0x00,0x01,0x03,0x77,0x07,0x6c,0x00,0x01,0x03,0x77,0xfe,0x5c,0x00,0x01,0x07,0xe4,0x07,0x6c,0x00,0x01,0x07,0xe4,0xfe,0x5c,0x00,0x01,0x07,0x34,0x07,0x6c, 0x00,0x01,0x07,0x34,0xfe,0x5c,0x00,0x01,0x05,0xed,0x07,0x6c,0x00,0x01,0x05,0xed,0xfe,0x5c,0x00,0x01,0x03,0x7b,0x07,0x6c,0x00,0x01,0x03,0x7b,0xfe,0x5c,0x00,0x01,0x02,0x29,0x08,0x34,0x00,0x01,0x02,0x29,0xfe,0x5c,0x00,0x01,0x02,0x11,0x07,0x6c,0x00,0x01,0x02,0x11,0xfe,0x5c,0x00,0x01,0x06,0x83,0x08,0x34,0x00,0x01,0x06,0x4e, 0x07,0x6c,0x00,0x01,0x06,0x4e,0xfe,0x5c,0x00,0x01,0x05,0x7d,0x07,0x6c,0x00,0x01,0x05,0x7d,0xfe,0x5c,0x00,0x01,0x04,0xb6,0x07,0x6c,0x00,0x01,0x04,0xb6,0xfe,0x5c,0x00,0x01,0x04,0x83,0x08,0x34,0x00,0x01,0x03,0x68,0x07,0x6c,0x00,0x01,0x03,0x68,0xfe,0x5c,0x00,0x01,0x09,0xbc,0x07,0x6c,0x00,0x01,0x08,0xf0,0x07,0x6c,0x00,0x01, 0x08,0xf0,0xfe,0x5c,0x00,0x01,0x08,0x06,0x07,0x6c,0x00,0x01,0x08,0x06,0xfe,0x5c,0x00,0x01,0x07,0x79,0x07,0x6c,0x00,0x01,0x07,0x79,0xfe,0x5c,0x00,0x01,0x05,0x27,0x07,0x6c,0x00,0x01,0x05,0x27,0xfe,0x5c,0x00,0x01,0x01,0xb6,0x07,0x6c,0x00,0x01,0x01,0xb6,0xfe,0x5c,0x00,0x01,0x02,0x28,0x08,0x34,0x00,0x01,0x02,0x28,0xfe,0x5c, 0x00,0x01,0x02,0x0a,0x07,0x6c,0x00,0x01,0x02,0x0a,0xfe,0x5c,0x00,0x01,0x02,0xca,0x07,0x6c,0x00,0x01,0x02,0xca,0xfe,0x5c,0x00,0x01,0x03,0x3e,0x07,0x6c,0x00,0x01,0x03,0x3e,0xfe,0x5c,0x00,0x01,0x04,0x42,0x07,0x6c,0x00,0x01,0x04,0x42,0xfe,0x5c,0x00,0x01,0x03,0x9e,0x07,0x6c,0x00,0x01,0x03,0x9e,0xfe,0x5c,0x00,0x01,0x04,0x56, 0x07,0x6c,0x00,0x01,0x04,0x56,0xfe,0x5c,0x00,0x01,0x03,0x5a,0x07,0x6c,0x00,0x01,0x03,0x5a,0xfe,0x5c,0x00,0x01,0x03,0xa0,0x07,0x6c,0x00,0x01,0x03,0xa0,0xfe,0x5c,0x00,0x01,0x05,0x21,0x07,0x6c,0x00,0x01,0x05,0x21,0xfe,0x5c,0x00,0x01,0x05,0x16,0x07,0x6c,0x00,0x01,0x05,0x16,0xfe,0x5c,0x00,0x01,0x02,0xf4,0x07,0x6c,0x00,0x01, 0x02,0xf4,0xfe,0x5c,0x00,0x01,0x02,0xee,0x07,0x6c,0x00,0x01,0x02,0xee,0xfe,0x5c,0x00,0x01,0x04,0x35,0x07,0x6c,0x00,0x01,0x04,0x35,0xfe,0x5c,0x00,0x01,0x02,0x1c,0x07,0x6c,0x00,0x01,0x02,0x1c,0xfe,0x5c,0x00,0x01,0x03,0xcd,0x07,0x6c,0x00,0x01,0x03,0xcd,0xfe,0x5c,0x00,0x01,0x03,0xc6,0x07,0x6c,0x00,0x01,0x03,0xc6,0xfe,0x5c, 0x00,0x01,0x02,0x0e,0x07,0x6c,0x00,0x01,0x02,0x0e,0xfe,0x5c,0x00,0x01,0x02,0x2f,0x07,0x6c,0x00,0x01,0x02,0x2f,0xfe,0x5c,0x00,0x01,0x02,0x44,0x07,0x6c,0x00,0x01,0x02,0x44,0xfe,0x5c,0x00,0x01,0x02,0x52,0x07,0x6c,0x00,0x01,0x02,0x52,0xfe,0x5c,0x00,0x01,0x02,0x5a,0x07,0x6c,0x00,0x01,0x02,0x5a,0xfe,0x5c,0x00,0x01,0x04,0xb2, 0x07,0x6c,0x00,0x01,0x04,0xb2,0xfe,0x5c,0x00,0x01,0x05,0x08,0x07,0x6c,0x00,0x01,0x05,0x08,0xfe,0x5c,0x00,0x01,0x04,0x0a,0x07,0x6c,0x00,0x01,0x04,0x0a,0xfe,0x5c,0x00,0x01,0x05,0x60,0x07,0x6c,0x00,0x01,0x05,0x60,0xfe,0x5c,0x00,0x01,0x05,0x64,0x07,0x6c,0x00,0x01,0x05,0x64,0xfe,0x5c,0x00,0x01,0x04,0xba,0x07,0x6c,0x00,0x01, 0x04,0xba,0xfe,0x5c,0x00,0x01,0x02,0x23,0x07,0x6c,0x00,0x01,0x03,0x33,0x07,0x6c,0x00,0x01,0x03,0x33,0xfe,0x5c,0x00,0x01,0x02,0xa2,0x07,0x6c,0x00,0x01,0x02,0xa2,0xfe,0x5c,0x00,0x01,0x02,0x1e,0x07,0x6c,0x00,0x01,0x02,0x1e,0xfe,0x5c,0x00,0x01,0x02,0xdb,0x07,0x6c,0x00,0x01,0x02,0xdb,0xfe,0x5c,0x00,0x01,0x02,0x68,0x07,0x6c, 0x00,0x01,0x02,0x68,0xfe,0x5c,0x00,0x01,0x02,0x72,0x07,0x6c,0x00,0x01,0x02,0x72,0xfe,0x5c,0x00,0x01,0x02,0x48,0x07,0x6c,0x00,0x01,0x02,0x48,0xfe,0x5c,0x00,0x01,0x02,0x8e,0x07,0x6c,0x00,0x01,0x02,0x8e,0xfe,0x5c,0x00,0x01,0x04,0xa4,0x07,0x6c,0x00,0x01,0x04,0xa4,0xfe,0x5c,0x00,0x01,0x03,0xd1,0x07,0x6c,0x00,0x01,0x03,0xd1, 0xfe,0x5c,0x00,0x01,0x03,0x4c,0x07,0x6c,0x00,0x01,0x03,0x4c,0xfe,0x5c,0x00,0x01,0x03,0xfe,0x07,0x6c,0x00,0x01,0x03,0xfe,0xfe,0x5c,0x00,0x01,0x04,0x25,0x07,0x6c,0x00,0x01,0x04,0x25,0xfe,0x5c,0x00,0x01,0x03,0x8c,0x07,0x6c,0x00,0x01,0x03,0x8c,0xfe,0x5c,0x00,0x01,0x02,0xe8,0x07,0x6c,0x00,0x01,0x02,0xe8,0xfe,0x5c,0x00,0x01, 0x02,0xcf,0x07,0x6c,0x00,0x01,0x02,0xcf,0xfe,0x5c,0x00,0x01,0x02,0xcb,0x07,0x6c,0x00,0x01,0x02,0xcb,0xfe,0x5c,0x00,0x01,0x03,0x60,0x07,0x6c,0x00,0x01,0x03,0x60,0xfe,0x5c,0x00,0x01,0x04,0x92,0x07,0x6c,0x00,0x01,0x04,0x92,0xfe,0x5c,0x00,0x01,0x03,0x7f,0x07,0x6c,0x00,0x01,0x03,0x7f,0xfe,0x5c,0x00,0x01,0x04,0x02,0x07,0x6c, 0x00,0x01,0x04,0x02,0xfe,0x5c,0x00,0x01,0x02,0x38,0x07,0x6c,0x00,0x01,0x03,0x56,0x07,0x6c,0x00,0x01,0x03,0x56,0xfe,0x5c,0x00,0x01,0x02,0xf8,0x07,0x6c,0x00,0x01,0x02,0xf8,0xfe,0x5c,0x00,0x01,0x07,0x27,0x07,0x6c,0x00,0x01,0x07,0x27,0xfe,0x5c,0x00,0x01,0x07,0x77,0x07,0x6c,0x00,0x01,0x07,0x77,0xfe,0x5c,0x00,0x01,0x07,0xdb, 0x07,0x6c,0x00,0x01,0x07,0xdb,0xfe,0x5c,0x00,0x01,0x04,0x94,0x07,0x6c,0x00,0x01,0x04,0x94,0xfe,0x5c,0x00,0x01,0x04,0x3e,0x07,0x6c,0x00,0x01,0x04,0x3e,0xfe,0x5c,0x00,0x01,0x05,0xc8,0x07,0x6c,0x00,0x01,0x05,0xc8,0xfe,0x5c,0x00,0x01,0x03,0xc2,0x07,0x6c,0x00,0x01,0x03,0xc2,0xfe,0x5c,0x00,0x01,0x06,0x1c,0x07,0x6c,0x00,0x01, 0x06,0x1c,0xfe,0x5c,0x00,0x01,0x06,0x04,0x07,0x6c,0x00,0x01,0x06,0x04,0xfe,0x5c,0x00,0x01,0x07,0x1a,0x07,0x6c,0x00,0x01,0x07,0x1a,0xfe,0x5c,0x00,0x01,0x04,0xf0,0x07,0x6c,0x00,0x01,0x04,0xf0,0xfe,0x5c,0x00,0x01,0x04,0x0b,0x07,0x6c,0x00,0x01,0x04,0x0b,0xfe,0x5c,0x00,0x01,0x04,0xc9,0x07,0x6c,0x00,0x01,0x04,0xc9,0xfe,0x5c, 0x00,0x01,0x03,0xf6,0x07,0x6c,0x00,0x01,0x03,0xf6,0xfe,0x5c,0x00,0x01,0x04,0xff,0x07,0x6c,0x00,0x01,0x04,0xff,0xfe,0x5c,0x00,0x01,0x04,0xdc,0x07,0x6c,0x00,0x01,0x04,0xdc,0xfe,0x5c,0x00,0x01,0x03,0xac,0x07,0x6c,0x00,0x01,0x03,0xac,0xfe,0x5c,0x00,0x01,0x03,0x37,0x07,0x6c,0x00,0x01,0x03,0x37,0xfe,0x5c,0x00,0x01,0x04,0x3f, 0x07,0x6c,0x00,0x01,0x04,0x3f,0xfe,0x5c,0x00,0x01,0x06,0xae,0x07,0x6c,0x00,0x01,0x06,0xae,0xfe,0x5c,0x00,0x01,0x02,0x46,0x07,0x6c,0x00,0x01,0x02,0x46,0xfe,0x5c,0x00,0x01,0x02,0x08,0x07,0x6c,0x00,0x01,0x02,0x08,0xfe,0x5c,0x00,0x01,0x04,0x24,0x07,0x6c,0x00,0x01,0x04,0x24,0xfe,0x5c,0x00,0x01,0x04,0xae,0x07,0x6c,0x00,0x01, 0x04,0xae,0xfe,0x5c,0x00,0x01,0x05,0xfc,0x07,0x6c,0x00,0x01,0x05,0xfc,0xfe,0x5c,0x00,0x01,0x03,0xf9,0x07,0x6c,0x00,0x01,0x03,0xf9,0xfe,0x5c,0x00,0x01,0x01,0xe3,0x07,0x6c,0x00,0x01,0x01,0xe3,0xfe,0x5c,0x00,0x01,0x06,0xed,0x07,0x6c,0x00,0x01,0x06,0xed,0xfe,0x5c,0x00,0x01,0x04,0x91,0x07,0x6c,0x00,0x01,0x04,0x91,0xfe,0x5c, 0x00,0x01,0x03,0xad,0x07,0x6c,0x00,0x01,0x03,0xad,0xfe,0x5c,0x00,0x01,0x03,0x4b,0x07,0x6c,0x00,0x01,0x03,0x4b,0xfe,0x5c,0x00,0x01,0x04,0x06,0x07,0x6c,0x00,0x01,0x04,0x06,0xfe,0x5c,0x00,0x01,0x04,0x71,0x07,0x6c,0x00,0x01,0x04,0x71,0xfe,0x5c,0x00,0x01,0x04,0xfe,0x07,0x6c,0x00,0x01,0x04,0xfe,0xfe,0x5c,0x00,0x01,0x04,0x84, 0x07,0x6c,0x00,0x01,0x04,0x84,0xfe,0x5c,0x00,0x01,0x03,0x3b,0x07,0x6c,0x00,0x01,0x03,0x3b,0xfe,0x5c,0x00,0x01,0x05,0xe0,0x07,0x6c,0x00,0x01,0x05,0xe0,0xfe,0x5c,0x00,0x01,0x02,0xd1,0x07,0x6c,0x00,0x01,0x02,0xd1,0xfe,0x5c,0x00,0x01,0x04,0xd0,0x07,0x6c,0x00,0x01,0x04,0xd0,0xfe,0x5c,0x00,0x01,0x04,0xc1,0x07,0x6c,0x00,0x01, 0x04,0xc1,0xfe,0x5c,0x00,0x01,0x05,0x7f,0x07,0x6c,0x00,0x01,0x05,0x7f,0xfe,0x5c,0x00,0x01,0x05,0x07,0x07,0x6c,0x00,0x01,0x05,0x07,0xfe,0x5c,0x00,0x01,0x06,0x01,0x07,0x6c,0x00,0x01,0x06,0x01,0xfe,0x5c,0x00,0x01,0x02,0xc8,0x07,0x6c,0x00,0x01,0x02,0xc8,0xfe,0x5c,0x00,0x01,0x04,0x6c,0x07,0x6c,0x00,0x01,0x04,0x6c,0xfe,0x5c, 0x00,0x01,0x03,0x9c,0x07,0x6c,0x00,0x01,0x03,0x9c,0xfe,0x5c,0x00,0x01,0x03,0xc4,0x07,0x6c,0x00,0x01,0x03,0xc4,0xfe,0x5c,0x00,0x01,0x02,0x4a,0x07,0x6c,0x00,0x01,0x02,0x4a,0xfe,0x5c,0x00,0x01,0x04,0x19,0x07,0x6c,0x00,0x01,0x04,0x19,0xfe,0x5c,0x00,0x01,0x04,0x12,0x07,0x6c,0x00,0x01,0x04,0x12,0xfe,0x5c,0x00,0x01,0x02,0xb6, 0x07,0x6c,0x00,0x01,0x02,0xb6,0xfe,0x5c,0x00,0x01,0x04,0x8d,0x07,0x6c,0x00,0x01,0x04,0x8d,0xfe,0x5c,0x00,0x01,0x05,0x98,0x07,0x6c,0x00,0x01,0x05,0x98,0xfe,0x5c,0x00,0x01,0xff,0x9c,0x05,0x14,0x00,0x01,0x03,0x34,0x05,0x9a,0x00,0x01,0x03,0xf6,0x04,0xfa,0x00,0x01,0x04,0x81,0x05,0x79,0x00,0x01,0x04,0xb0,0x04,0xfa,0x00,0x01, 0x03,0x70,0x05,0x9a,0x00,0x01,0x04,0xd4,0x05,0x69,0x00,0x01,0x05,0x0e,0x05,0x9a,0x00,0x01,0x01,0xfe,0x05,0x9a,0x00,0x01,0x02,0x3b,0x05,0x9a,0x00,0x01,0x04,0x04,0x05,0x9a,0x00,0x01,0x01,0x42,0x05,0x9a,0x00,0x01,0x06,0xae,0x05,0x9a,0x00,0x01,0x05,0x5c,0x05,0x9a,0x00,0x01,0x04,0xd8,0x05,0x28,0x00,0x01,0x03,0xdb,0x04,0xfa, 0x00,0x01,0x04,0x29,0x04,0xfa,0x00,0x01,0x03,0xa0,0x05,0x94,0x00,0x01,0x04,0x06,0x05,0xa3,0x00,0x01,0x04,0xda,0x05,0x9f,0x00,0x01,0x04,0xa9,0x05,0x9a,0x00,0x01,0x07,0x58,0x05,0x9a,0x00,0x01,0x03,0x20,0x03,0xf1,0x00,0x01,0x04,0x14,0x03,0xb6,0x00,0x01,0x03,0x59,0x03,0xf1,0x00,0x01,0x04,0x04,0x05,0xf2,0x00,0x01,0x03,0x71, 0x03,0xcd,0x00,0x01,0x02,0x9e,0x06,0x02,0x00,0x01,0x04,0x0d,0x04,0x04,0x00,0x01,0x03,0xd5,0x03,0xaa,0x00,0x01,0x01,0x59,0x04,0x01,0x00,0x01,0x01,0x50,0x04,0x01,0x00,0x01,0x03,0xb4,0x04,0x0b,0x00,0x01,0x01,0x67,0x05,0xf2,0x00,0x01,0x06,0x44,0x03,0x78,0x00,0x01,0x03,0xe7,0x03,0x78,0x00,0x01,0x03,0xde,0x03,0x84,0x00,0x01, 0x04,0x14,0x03,0x87,0x00,0x01,0x04,0x04,0x04,0x03,0x00,0x01,0x02,0xc1,0x04,0x02,0x00,0x01,0x02,0xe0,0x03,0xf3,0x00,0x01,0x02,0x70,0x04,0x03,0x00,0x01,0x03,0xd4,0x03,0xfc,0x00,0x01,0x03,0xb3,0x04,0x00,0x00,0x01,0x05,0xa6,0x04,0x00,0x00,0x01,0x03,0x6f,0x04,0x00,0x00,0x01,0x03,0xb4,0x04,0x0c,0x00,0x01,0x03,0x34,0x04,0x00, 0x00,0x01,0x02,0x94,0xff,0xce,0x00,0x01,0x02,0xde,0xff,0xf1,0x00,0x01,0x02,0x52,0xff,0xce,0x00,0x01,0x02,0xfe,0xff,0xce,0x00,0x01,0x03,0x04,0xff,0xf1,0x00,0x01,0x02,0x64,0xff,0xce,0x00,0x01,0x02,0x20,0xff,0xf1,0x00,0x01,0x02,0xbf,0xff,0xf1,0x00,0x01,0x02,0x3a,0xff,0xf1,0x00,0x01,0x02,0x2b,0xff,0xf1,0x00,0x01,0x02,0x44, 0xfe,0x3e,0x00,0x01,0x00,0xfa,0x00,0x14,0x00,0x01,0x01,0xfd,0xff,0xce,0x00,0x01,0x00,0xfa,0x00,0x00,0x00,0x01,0x02,0x43,0xff,0xce,0x00,0x01,0x00,0xf6,0x00,0x00,0x00,0x01,0x01,0xa8,0xff,0xf1,0x00,0x01,0x01,0xbf,0x00,0x00,0x00,0x01,0x00,0x00,0xff,0xf6,0x00,0x01,0x04,0x65,0x00,0x00,0x00,0x01,0x02,0x58,0x00,0x00,0x00,0x01, 0x03,0x5c,0xff,0xf1,0x00,0x01,0x00,0xe6,0x00,0x00,0x00,0x01,0x03,0xa7,0x00,0x00,0x00,0x01,0x04,0x4c,0x00,0x00,0x00,0x01,0x00,0xc8,0x00,0x00,0x00,0x01,0x03,0xca,0x00,0x00,0x00,0x01,0x02,0xda,0x00,0x00,0x00,0x01,0x05,0xd2,0x00,0x00,0x00,0x01,0x04,0x88,0x00,0x00,0x00,0x01,0x03,0x3e,0xff,0xf1,0x00,0x01,0x03,0x70,0xff,0x4c, 0x00,0x01,0x04,0x10,0x00,0x00,0x00,0x01,0x02,0x62,0x00,0x00,0x00,0x01,0x01,0xcc,0x00,0x00,0x00,0x01,0x05,0x19,0x00,0x00,0x00,0x01,0x01,0xf4,0x00,0x00,0x00,0x01,0x03,0x8e,0x00,0x00,0x00,0x01,0x02,0xc6,0x00,0x00,0x00,0x01,0x02,0x94,0x00,0x00,0x00,0x01,0x03,0x66,0x00,0x00,0x00,0x01,0x02,0xd2,0xfe,0x70,0x00,0x01,0x03,0x5c, 0x00,0x00,0x00,0x01,0x00,0x32,0xfe,0x5c,0x00,0x01,0x03,0x16,0x00,0x00,0x00,0x01,0x05,0xaa,0x00,0x00,0x00,0x01,0x00,0xaa,0xfe,0x20,0x00,0x01,0x03,0x70,0xfe,0x20,0x00,0x01,0x01,0xb8,0xff,0xf1,0x00,0x01,0x03,0x3e,0x00,0x00,0x00,0x01,0x01,0xa4,0x00,0x00,0x00,0x01,0x03,0xde,0x00,0x00,0x00,0x01,0x02,0xd0,0x00,0x00,0x00,0x01, 0x00,0xdc,0xfe,0x48,0x00,0x01,0x02,0xf8,0xfe,0x70,0x00,0x01,0x04,0x6a,0x00,0x00,0x00,0x01,0x02,0x44,0xfe,0x70,0x00,0x01,0x05,0x80,0x00,0x27,0x00,0x01,0x00,0xf1,0xff,0x0e,0x00,0x01,0x06,0x4a,0x00,0x00,0x00,0x01,0x05,0xf0,0x00,0x00,0x00,0x01,0x00,0xdc,0x00,0x00,0x00,0x01,0x02,0xf0,0x00,0x1b,0x00,0x01,0x02,0x9a,0x00,0x09, 0x00,0x01,0x00,0xaa,0xfe,0x2a,0x00,0x01,0x02,0x3a,0xfe,0x70,0x00,0x01,0x01,0xcc,0xfe,0x70,0x00,0x01,0x04,0x4c,0xfe,0x84,0x00,0x01,0x02,0xe4,0xfe,0x84,0x00,0x01,0x02,0x76,0xfe,0x84,0x00,0x01,0x01,0xb8,0xfe,0x5c,0x00,0x01,0x02,0xeb,0x00,0x03,0x00,0x01,0x02,0x4e,0xfe,0x5c,0x00,0x01,0x03,0xb2,0x00,0x00,0x00,0x01,0x02,0x76, 0xfe,0x99,0x00,0x01,0x00,0xaa,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x84,0x00,0x01,0x01,0x18,0xfe,0x70,0x00,0x01,0x03,0xd6,0xfe,0x5c,0x00,0x01,0x02,0xa3,0xfe,0x5c,0x00,0x01,0x03,0x66,0xfe,0x84,0x00,0x01,0x03,0x20,0x00,0x00,0x00,0x01,0x03,0x2e,0x00,0x3f,0x00,0x01,0x00,0xfd,0xfe,0xee,0x00,0x01,0x00,0xdc,0xfe,0xdc,0x00,0x01, 0x02,0xed,0xfe,0xec,0x00,0x01,0x02,0x4d,0xfe,0xfb,0x00,0x01,0x02,0xdb,0xfe,0xec,0x00,0x01,0x02,0x44,0xfe,0xf2,0x00,0x01,0x02,0xf6,0xfe,0xf5,0x00,0x01,0x02,0x3b,0xfe,0xf2,0x00,0x01,0x02,0xab,0xfe,0xfb,0x00,0x01,0x02,0x99,0xfe,0xf2,0x00,0x01,0x02,0x0f,0xfe,0xe5,0x00,0x01,0x01,0x00,0xfe,0x67,0x00,0x01,0x01,0x86,0xfe,0x98, 0x00,0x01,0x01,0x18,0xfe,0x98,0x00,0x01,0x02,0x17,0xfe,0x5c,0x00,0x01,0x02,0x08,0xfe,0xd4,0x00,0x01,0x02,0x48,0xfe,0xd4,0x00,0x01,0x02,0x2a,0xff,0x24,0x00,0x01,0x02,0x63,0xff,0x24,0x00,0x01,0x02,0x26,0xfe,0x5c,0x00,0x01,0x02,0x72,0xfe,0xd4,0x00,0x01,0x02,0x60,0xff,0x24,0x00,0x01,0x02,0x3d,0xff,0x24,0x00,0x01,0x02,0x3e, 0xfe,0x92,0x00,0x01,0x02,0x9e,0xfe,0x48,0x00,0x01,0x02,0x35,0xfe,0x48,0x00,0x01,0x02,0x2a,0xfe,0xd4,0x00,0x01,0x02,0x4e,0xfe,0xd4,0x00,0x01,0x02,0x2a,0xfe,0x5c,0x00,0x01,0x02,0xe4,0xfe,0xa2,0x00,0x01,0x02,0x76,0xfe,0xa2,0x00,0x01,0x01,0x22,0xfe,0xd4,0x00,0x01,0x00,0xf0,0xfe,0xd4,0x00,0x01,0x03,0x7a,0x00,0x00,0x00,0x01, 0x04,0x3f,0x00,0x00,0x00,0x01,0x02,0x23,0xff,0x24,0x00,0x01,0x00,0xd2,0xfe,0xd4,0x00,0x01,0x00,0xc8,0xfe,0xd4,0x00,0x01,0x02,0x1c,0xff,0x24,0x00,0x01,0x02,0x17,0xfe,0x48,0x00,0x01,0x00,0xe6,0xfe,0x48,0x00,0x01,0x05,0xbe,0x00,0x00,0x00,0x01,0x02,0xf3,0xff,0x24,0x00,0x01,0x02,0x44,0xfe,0x48,0x00,0x01,0x00,0xb4,0xfe,0x20, 0x00,0x01,0x02,0x84,0xff,0x24,0x00,0x01,0x01,0x9e,0xff,0x24,0x00,0x01,0x01,0xf9,0xfe,0xd4,0x00,0x01,0x01,0x9a,0xfe,0xd4,0x00,0x01,0x02,0x2b,0xfe,0xd4,0x00,0x01,0x01,0xa9,0xfe,0xd4,0x00,0x01,0x01,0xf4,0xfe,0xd4,0x00,0x01,0x01,0x3b,0xfe,0xd4,0x00,0x01,0x01,0xf0,0xff,0x24,0x00,0x01,0x01,0x82,0xff,0x24,0x00,0x01,0x02,0x12, 0xfe,0x48,0x00,0x01,0x01,0x54,0xfe,0x48,0x00,0x01,0x02,0xb2,0xfe,0xac,0x00,0x01,0x02,0x1c,0xfe,0xac,0x00,0x01,0x02,0xb4,0xfe,0xd4,0x00,0x01,0x02,0x4b,0xfe,0xd4,0x00,0x01,0x04,0x1a,0x00,0x00,0x00,0x01,0x02,0x26,0xfe,0xd4,0x00,0x01,0x01,0xae,0xfe,0xd4,0x00,0x01,0x02,0x3a,0xff,0x24,0x00,0x01,0x01,0xc2,0xff,0x24,0x00,0x01, 0x02,0x9c,0x00,0x00,0x00,0x01,0x02,0x0d,0x00,0x00,0x00,0x01,0x01,0xd7,0xff,0xf1,0x00,0x01,0x02,0x7d,0xff,0xf1,0x00,0x01,0x03,0x54,0x00,0x00,0x00,0x01,0x03,0x74,0x00,0x00,0x00,0x01,0x02,0xe4,0xfe,0x70,0x00,0x01,0x01,0x4a,0x00,0x00,0x00,0x01,0x02,0xca,0x00,0x00,0x00,0x01,0x00,0x5c,0xfe,0xb6,0x00,0x01,0x05,0x00,0x00,0x00, 0x00,0x01,0x01,0x54,0xff,0xf1,0x00,0x01,0x03,0x52,0xfe,0x70,0x00,0x01,0x06,0x72,0x00,0x00,0x00,0x01,0x05,0x0a,0x00,0x00,0x00,0x01,0x01,0x25,0x00,0x00,0x00,0x01,0x00,0xb9,0xfe,0x2a,0x00,0x01,0x03,0x98,0xff,0x74,0x00,0x01,0x02,0x08,0x00,0x00,0x00,0x01,0x01,0xe4,0xfe,0x2a,0x00,0x01,0x01,0x78,0xfe,0xab,0x00,0x01,0x02,0xe8, 0xfe,0x9b,0x00,0x01,0x03,0x39,0xff,0xf1,0x00,0x01,0x02,0xe9,0xff,0xfa,0x00,0x01,0x02,0x58,0xfe,0x3a,0x00,0x01,0x03,0x66,0xfe,0x2f,0x00,0x01,0x01,0x90,0x00,0x00,0x00,0x01,0x01,0xae,0x00,0x00,0x00,0x01,0x08,0xde,0x00,0x00,0x00,0x01,0x08,0x20,0x00,0x00,0x00,0x01,0x07,0x30,0x00,0x00,0x00,0x01,0x04,0xce,0x00,0x00,0x00,0x01, 0x06,0x86,0x00,0x00,0x00,0x01,0x05,0xfa,0xfe,0x5c,0x00,0x01,0x04,0xb0,0xfe,0x5c,0x00,0x01,0x05,0xa2,0x00,0x00,0x00,0x01,0x05,0x14,0x00,0x00,0x00,0x01,0x02,0xda,0xfe,0x84,0x00,0x01,0x02,0x3a,0xfe,0x84,0x00,0x01,0x01,0xcc,0xfe,0x48,0x00,0x01,0x06,0x18,0x00,0x00,0x00,0x01,0x00,0xbe,0xfe,0x2a,0x00,0x01,0x04,0x88,0xfe,0x2a, 0x00,0x01,0x02,0x66,0x00,0x00,0x00,0x01,0x03,0x70,0x00,0x00,0x00,0x01,0x01,0xa5,0xff,0xf7,0x00,0x01,0x04,0x4c,0xfe,0x2a,0x00,0x01,0x02,0x22,0x00,0x00,0x00,0x01,0x01,0xb6,0x00,0x00,0x00,0x01,0x02,0xc2,0x00,0x00,0x00,0x01,0x00,0x8c,0xfe,0x75,0x00,0x01,0x01,0xd8,0xfe,0x5c,0x00,0x01,0x01,0xd4,0x00,0x00,0x00,0x01,0x03,0x47, 0xfe,0x2a,0x00,0x01,0x01,0x36,0x00,0x00,0x00,0x01,0x01,0x48,0x00,0x00,0x00,0x01,0x03,0x0c,0xfe,0x48,0x00,0x01,0x05,0xa4,0x00,0x00,0x00,0x01,0x05,0xa4,0xfe,0x2a,0x00,0x01,0x04,0xff,0xfe,0x35,0x00,0x01,0x04,0x3d,0xfe,0x2a,0x00,0x01,0x04,0x9c,0x00,0x00,0x00,0x01,0x01,0x91,0x00,0x00,0x00,0x01,0x01,0x88,0x00,0x00,0x00,0x01, 0x01,0x84,0x00,0x09,0x00,0x01,0x02,0xde,0x00,0x09,0x00,0x01,0x01,0x8d,0xfe,0xe0,0x00,0x01,0x00,0x91,0xfe,0x7e,0x00,0x01,0x00,0x8a,0xfe,0x63,0x00,0x01,0x00,0xa4,0xfe,0x5c,0x00,0x01,0x01,0x5c,0xfe,0xfb,0x00,0x01,0x02,0x76,0x00,0x00,0x00,0x01,0x01,0x6c,0x00,0x09,0x00,0x01,0x03,0x52,0xff,0x06,0x00,0x01,0x01,0xc2,0xfe,0x41, 0x00,0x01,0x01,0xc2,0xfe,0x4a,0x00,0x01,0x01,0x5b,0x00,0x00,0x00,0x01,0x01,0x47,0x00,0x00,0x00,0x01,0x02,0x7d,0xfe,0x48,0x00,0x01,0x02,0xa5,0xff,0xfa,0x00,0x01,0x00,0x43,0xfe,0x41,0x00,0x01,0x02,0xbc,0xfe,0x16,0x00,0x01,0x03,0x76,0xfe,0x2a,0x00,0x01,0x01,0x64,0x00,0x00,0x00,0x01,0x06,0x5e,0x00,0x00,0x00,0x01,0x05,0xb4, 0xfe,0x36,0x00,0x01,0x02,0x14,0xfe,0x4a,0x00,0x01,0x04,0xb0,0x00,0x00,0x00,0x01,0x04,0xb0,0xfe,0x48,0x00,0x01,0x03,0x02,0x00,0x00,0x00,0x01,0x01,0xf4,0xfe,0x5c,0x00,0x01,0x04,0x9c,0xfe,0x5c,0x00,0x01,0x03,0x84,0xfe,0x2a,0x00,0x01,0x05,0x82,0x00,0x00,0x00,0x01,0x03,0x7a,0xfe,0x20,0x00,0x01,0x02,0x1f,0xfe,0xd4,0x00,0x01, 0x02,0x9e,0xfe,0x2a,0x00,0x01,0x02,0xd0,0x01,0xf6,0x00,0x01,0x06,0x1a,0x00,0x00,0x00,0x01,0x01,0x22,0x00,0x00,0x00,0x01,0x02,0x6c,0x00,0x00,0x00,0x01,0x02,0xd0,0xfe,0xa2,0x00,0x01,0x03,0x98,0xfe,0xa2,0x00,0x01,0x02,0xee,0xfe,0xa2,0x00,0x01,0x00,0xd2,0xfe,0xa2,0x00,0x01,0x05,0xdc,0xfe,0xa2,0x00,0x01,0x03,0x84,0xfe,0xa2, 0x00,0x01,0x02,0x80,0xfe,0xa2,0x00,0x01,0x03,0xa2,0xfe,0xa2,0x00,0x01,0x04,0x2e,0xfe,0xa2,0x00,0x01,0x04,0x38,0xfe,0xa2,0x00,0x01,0x03,0xb6,0xfe,0xc0,0x00,0x01,0x03,0x52,0xfe,0xa2,0x00,0x01,0x02,0x7f,0x00,0x46,0x00,0x01,0x03,0xfc,0xfe,0xa2,0x00,0x01,0x04,0x21,0x00,0x00,0x00,0x01,0x00,0xe6,0x00,0x8c,0x00,0x01,0x04,0x42, 0x00,0x00,0x00,0x01,0x05,0xbe,0xfe,0xa2,0x00,0x01,0x04,0xba,0xfe,0xa2,0x00,0x01,0x00,0xc8,0xfe,0x48,0x00,0x01,0x03,0xa2,0x00,0x0f,0x00,0x01,0x00,0x8c,0x00,0x1e,0x00,0x01,0xff,0x6a,0x00,0x1e,0x00,0x01,0x03,0x4a,0x00,0x50,0x00,0x01,0x02,0xd5,0x00,0x1a,0x00,0x01,0x03,0xbc,0x00,0x09,0x00,0x01,0x03,0xbc,0x00,0x00,0x00,0x01, 0x01,0x40,0x00,0x00,0x00,0x01,0x03,0x3a,0xfe,0x93,0x00,0x01,0x03,0x48,0xfe,0xc0,0x00,0x01,0x03,0xa8,0x00,0x00,0x00,0x01,0x00,0x83,0xfe,0x89,0x00,0x01,0x03,0x5a,0x00,0x00,0x00,0x01,0x05,0xfc,0x00,0x00,0x00,0x01,0x03,0xa2,0x00,0x09,0x00,0x01,0x03,0x5c,0x00,0x3f,0x00,0x01,0x03,0xb3,0xfe,0x42,0x00,0x01,0x00,0xf8,0x00,0x00, 0x00,0x01,0x02,0x60,0x00,0x50,0x00,0x01,0x01,0xea,0x00,0x00,0x00,0x01,0x04,0x27,0x00,0x09,0x00,0x01,0x04,0x27,0x00,0x00,0x00,0x01,0x03,0x07,0xff,0xf7,0x00,0x01,0x03,0x07,0x00,0x00,0x00,0x01,0x02,0x58,0x06,0xea,0x00,0x01,0xff,0x6f,0x06,0xea,0x00,0x01,0x00,0xaa,0x06,0x40,0x00,0x01,0xff,0x7e,0x06,0x40,0x00,0x01,0x05,0x29, 0x08,0x34,0x00,0x01,0x00,0x00,0x08,0x34,0x00,0x01,0x04,0x96,0x08,0x34,0x00,0x01,0x04,0xf4,0x08,0x34,0x00,0x01,0x05,0x9c,0x08,0x34,0x00,0x01,0x03,0xe8,0x08,0x34,0x00,0x01,0x05,0x7d,0x08,0x34,0x00,0x01,0x05,0xae,0x08,0x34,0x00,0x01,0x02,0x21,0x08,0x34,0x00,0x01,0x02,0xdb,0x08,0x34,0x00,0x01,0x04,0xa4,0x08,0x34,0x00,0x01, 0x03,0xc4,0x08,0x34,0x00,0x01,0x07,0x2f,0x08,0x34,0x00,0x01,0x05,0xfc,0x08,0x34,0x00,0x01,0x06,0x08,0x08,0x34,0x00,0x01,0x04,0x7b,0x08,0x34,0x00,0x01,0x04,0xc9,0x08,0x34,0x00,0x01,0x04,0x40,0x08,0x34,0x00,0x01,0x04,0x31,0x08,0x34,0x00,0x01,0x05,0x7f,0x08,0x34,0x00,0x01,0x04,0xf8,0x08,0x34,0x00,0x01,0x07,0x79,0x08,0x34, 0x00,0x01,0x04,0xb8,0x08,0x34,0x00,0x01,0x04,0x6c,0x08,0x34,0x00,0x01,0x04,0x90,0x08,0x34,0x00,0x01,0x04,0x12,0x08,0x34,0x00,0x01,0x04,0xb4,0x08,0x34,0x00,0x01,0x03,0xb2,0x08,0x34,0x00,0x01,0x04,0xb6,0x08,0x34,0x00,0x01,0x02,0x81,0x08,0x34,0x00,0x01,0x04,0x87,0x08,0x34,0x00,0x01,0x03,0xfa,0x08,0x34,0x00,0x01,0x06,0xe4, 0x08,0x34,0x00,0x01,0x04,0xb0,0x08,0x34,0x00,0x01,0x02,0xc8,0x08,0x34,0x00,0x01,0x03,0x65,0x08,0x34,0x00,0x01,0x02,0xb6,0x08,0x34,0x00,0x01,0x03,0xd5,0x08,0x34,0x00,0x01,0x05,0xc8,0x08,0x34,0x00,0x01,0x03,0xac,0x08,0x34,0x00,0x01,0x03,0xdf,0x08,0x34,0x00,0x01,0x03,0x9e,0x08,0x34,0x00,0x01,0x04,0x5a,0x08,0x34,0x00,0x01, 0x06,0xe2,0x08,0x34,0x00,0x01,0x06,0xa8,0x08,0x34,0x00,0x01,0x07,0x72,0x08,0x34,0x00,0x01,0x07,0x6c,0x08,0x34,0x00,0x01,0x02,0x31,0x08,0x34,0x00,0x01,0x04,0x79,0x08,0x34,0x00,0x01,0x05,0x65,0x08,0x34,0x00,0x01,0x02,0x75,0x08,0x34,0x00,0x01,0x02,0x85,0x08,0x34,0x00,0x01,0x03,0x85,0x08,0x34,0x00,0x01,0x04,0xfc,0x08,0x34, 0x00,0x01,0x03,0xf6,0x08,0x34,0x00,0x01,0x04,0xd9,0x08,0x34,0x00,0x01,0x01,0xee,0x08,0x34,0x00,0x01,0x06,0x1a,0x08,0x34,0x00,0x01,0x04,0xc7,0x08,0x34,0x00,0x01,0x05,0xc4,0x08,0x34,0x00,0x01,0x06,0x8e,0x08,0x34,0x00,0x01,0x04,0xe8,0x08,0x34,0x00,0x01,0x04,0x93,0x08,0x34,0x00,0x01,0x04,0x9e,0x08,0x34,0x00,0x01,0x04,0xf6, 0x08,0x34,0x00,0x01,0x03,0xba,0x08,0x34,0x00,0x01,0x05,0xee,0x08,0x34,0x00,0x01,0x04,0x94,0x08,0x34,0x00,0x01,0x04,0xbc,0x08,0x34,0x00,0x01,0x04,0x0e,0x08,0x34,0x00,0x01,0x04,0x54,0x08,0x34,0x00,0x01,0x05,0x89,0x08,0x34,0x00,0x01,0x06,0xfe,0x08,0x34,0x00,0x01,0x02,0x4e,0x08,0x34,0x00,0x01,0x02,0x3a,0x08,0x34,0x00,0x01, 0x03,0xfc,0x08,0x34,0x00,0x01,0x07,0x23,0x08,0x34,0x00,0x01,0x07,0xc0,0x08,0x34,0x00,0x01,0x06,0x52,0x08,0x34,0x00,0x01,0x04,0xcf,0x08,0x34,0x00,0x01,0x04,0x9c,0x08,0x34,0x00,0x01,0x04,0x21,0x08,0x34,0x00,0x01,0x02,0x5e,0x08,0x34,0x00,0x01,0x02,0xb8,0x08,0x34,0x00,0x01,0x04,0x33,0x08,0x34,0x00,0x01,0x06,0x0a,0x08,0x34, 0x00,0x01,0x05,0xb2,0x08,0x34,0x00,0x01,0x04,0x8e,0x08,0x34,0x00,0x01,0x04,0x23,0x08,0x34,0x00,0x01,0x04,0xe2,0x08,0x34,0x00,0x01,0x03,0x0a,0x08,0x34,0x00,0x01,0x03,0x27,0x08,0x34,0x00,0x01,0x04,0x5e,0x08,0x34,0x00,0x01,0x09,0xe8,0x08,0x34,0x00,0x01,0x09,0x1c,0x08,0x34,0x00,0x01,0x08,0x33,0x08,0x34,0x00,0x01,0x06,0xd9, 0x08,0x34,0x00,0x01,0x05,0xc2,0x08,0x34,0x00,0x01,0x04,0x01,0x08,0x34,0x00,0x01,0x08,0x94,0x08,0x34,0x00,0x01,0x07,0xbe,0x08,0x34,0x00,0x01,0x06,0x77,0x08,0x34,0x00,0x01,0x04,0x0a,0x08,0x34,0x00,0x01,0x06,0xa0,0x08,0x34,0x00,0x01,0x03,0x89,0x08,0x34,0x00,0x01,0x07,0xfe,0x08,0x34,0x00,0x01,0x05,0x83,0x08,0x34,0x00,0x01, 0x04,0x08,0x08,0x34,0x00,0x01,0x03,0x70,0x08,0x34,0x00,0x01,0x05,0xdf,0x08,0x34,0x00,0x01,0x04,0x89,0x08,0x34,0x00,0x01,0x03,0x4e,0x08,0x34,0x00,0x01,0x04,0x68,0x08,0x34,0x00,0x01,0x04,0x3c,0x08,0x34,0x00,0x01,0x03,0xa8,0x08,0x34,0x00,0x01,0x02,0x18,0x08,0x34,0x00,0x01,0x02,0x90,0x08,0x34,0x00,0x01,0x02,0x3e,0x08,0x34, 0x00,0x01,0x03,0x02,0x08,0x34,0x00,0x01,0x04,0xd3,0x08,0x34,0x00,0x01,0x04,0x72,0x08,0x34,0x00,0x01,0x05,0x96,0x08,0x34,0x00,0x01,0x05,0x1a,0x08,0x34,0x00,0x01,0x02,0xae,0x08,0x34,0x00,0x01,0x03,0xa2,0x08,0x34,0x00,0x01,0x03,0x2f,0x08,0x34,0x00,0x01,0x01,0xfa,0x08,0x34,0x00,0x01,0x02,0x10,0x08,0x34,0x00,0x01,0x02,0x44, 0x08,0x34,0x00,0x01,0x04,0xcb,0x08,0x34,0x00,0x01,0x04,0xc2,0x08,0x34,0x00,0x01,0x04,0x77,0x08,0x34,0x00,0x01,0x03,0x56,0x08,0x34,0x00,0x01,0x04,0x18,0x08,0x34,0x00,0x01,0x02,0xec,0x08,0x34,0x00,0x01,0x04,0x62,0x08,0x34,0x00,0x01,0x03,0x14,0x08,0x34,0x00,0x01,0x07,0x54,0x08,0x34,0x00,0x01,0x07,0x98,0x08,0x34,0x00,0x01, 0x07,0xcf,0x08,0x34,0x00,0x01,0x03,0xcf,0x08,0x34,0x00,0x01,0x05,0xbe,0x08,0x34,0x00,0x01,0x06,0x58,0x08,0x34,0x00,0x01,0x03,0xf4,0x08,0x34,0x00,0x01,0x05,0x27,0x08,0x34,0x00,0x01,0x02,0x60,0x08,0x34,0x00,0x01,0x05,0x0e,0x08,0x34,0x00,0x01,0x07,0x7a,0x08,0x34,0x00,0x01,0x04,0x16,0x08,0x34,0x00,0x01,0x03,0xb5,0x08,0x34, 0x00,0x01,0x03,0xb1,0x08,0x34,0x00,0x01,0x04,0x9f,0x08,0x34,0x00,0x01,0x07,0x3d,0x08,0x34,0x00,0x01,0x02,0x22,0x08,0x34,0x00,0x01,0x04,0x46,0x08,0x34,0x00,0x01,0x03,0x76,0x08,0x34,0x00,0x01,0x03,0x81,0x08,0x34,0x00,0x01,0x03,0x91,0x08,0x34,0x00,0x01,0x05,0xe0,0x08,0x34,0x00,0x01,0x04,0xc1,0x08,0x34,0x00,0x01,0x02,0xf4, 0x08,0x34,0x00,0x01,0x05,0x07,0x08,0x34,0x00,0x01,0x06,0x01,0x08,0x34,0x00,0x01,0x03,0x9c,0x08,0x34,0x00,0x01,0x02,0x4a,0x08,0x34,0x00,0x01,0x04,0x19,0x08,0x34,0x00,0x01,0x04,0x8d,0x08,0x34,0x00,0x01,0x05,0x98,0x08,0x34,0x00,0x01,0x01,0x90,0x01,0xfa,0x00,0x01,0x00,0x0c,0x01,0x0e,0x00,0x40,0x00,0x00,0x2b,0xce,0x00,0x00, 0x2b,0xd4,0x00,0x00,0x2b,0xd4,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xe0,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xe6,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xec,0x00,0x00,0x2b,0xec,0x00,0x00,0x2b,0xf2,0x00,0x00,0x2b,0xda,0x00,0x00, 0x2b,0xda,0x00,0x00,0x2b,0xf8,0x00,0x00,0x2b,0xfe,0x00,0x00,0x2c,0x04,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2b,0xda,0x00,0x00,0x2c,0x10,0x00,0x00,0x2b,0xe0,0x00,0x00,0x2c,0x16,0x00,0x00,0x2b,0xda,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2b,0xda,0x00,0x00,0x2c,0x1c,0x00,0x00,0x2c,0x22,0x00,0x00, 0x2c,0x28,0x00,0x00,0x2c,0x2e,0x00,0x00,0x2c,0x2e,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2c,0x34,0x00,0x00,0x2c,0x0a,0x00,0x00,0x2c,0x0a,0x00,0x00, 0x2c,0x3a,0x00,0x00,0x2c,0x40,0x00,0x00,0x2b,0xda,0x00,0x00,0x2c,0x46,0x00,0x00,0x2c,0x3a,0x00,0x00,0x2c,0x3a,0x00,0x00,0x2c,0x3a,0x00,0x00,0x2c,0x4c,0x00,0x00,0x2c,0x52,0x00,0x00,0x2c,0x52,0x00,0x00,0x2c,0x58,0x00,0x00,0x2c,0x58,0x00,0x00,0x2c,0x5e,0x00,0x00,0x2c,0x5e,0x00,0x00,0x2c,0x64,0x00,0x40,0x2b,0x68,0x2b,0x6e, 0x2b,0x74,0x2b,0x7a,0x2b,0x80,0x2b,0x86,0x2b,0x8c,0x2b,0x92,0x2b,0x98,0x2b,0x9e,0x2b,0xa4,0x2b,0xaa,0x2b,0xb0,0x2b,0xaa,0x2b,0xaa,0x2b,0xaa,0x2b,0xb6,0x2b,0x92,0x2b,0xbc,0x2b,0xc2,0x2b,0xc2,0x2b,0xb6,0x2b,0xc8,0x2b,0xce,0x2b,0xd4,0x2b,0xda,0x2b,0xe0,0x2b,0xaa,0x2b,0xe6,0x2b,0xec,0x2b,0xf2,0x2b,0xf8,0x2b,0xfe,0x2c,0x04, 0x2c,0x0a,0x2c,0x0a,0x2c,0x10,0x2c,0x10,0x2c,0x16,0x2c,0x10,0x2c,0x10,0x2c,0x10,0x2c,0x1c,0x2c,0x1c,0x2c,0x10,0x2c,0x10,0x2c,0x22,0x2c,0x10,0x2c,0x10,0x2c,0x28,0x2c,0x2e,0x2b,0xb6,0x2c,0x2e,0x2c,0x34,0x2c,0x3a,0x2c,0x3a,0x2b,0x92,0x2c,0x40,0x2c,0x40,0x2c,0x46,0x2c,0x46,0x2c,0x4c,0x2c,0x4c,0x2c,0x52,0x00,0x02,0x00,0x11, 0x02,0x44,0x02,0x44,0x00,0x00,0x02,0x46,0x02,0x47,0x00,0x01,0x04,0x62,0x04,0x73,0x00,0x03,0x04,0x79,0x04,0x79,0x00,0x15,0x04,0x9b,0x04,0x9d,0x00,0x16,0x04,0xa0,0x04,0xa2,0x00,0x19,0x04,0xa4,0x04,0xa4,0x00,0x1c,0x04,0xa8,0x04,0xaa,0x00,0x1d,0x05,0xfd,0x06,0x00,0x00,0x20,0x06,0x66,0x06,0x72,0x00,0x24,0x07,0x55,0x07,0x57, 0x00,0x31,0x07,0x5c,0x07,0x5c,0x00,0x34,0x07,0xef,0x07,0xef,0x00,0x35,0x08,0x4c,0x08,0x4d,0x00,0x36,0x08,0x4f,0x08,0x4f,0x00,0x38,0x0a,0xdb,0x0a,0xe0,0x00,0x39,0x0a,0xe2,0x0a,0xe2,0x00,0x3f,0x00,0x02,0x00,0x11,0x02,0x44,0x02,0x44,0x00,0x00,0x02,0x46,0x02,0x47,0x00,0x01,0x04,0x62,0x04,0x73,0x00,0x03,0x04,0x79,0x04,0x79, 0x00,0x15,0x04,0x9b,0x04,0x9d,0x00,0x16,0x04,0xa0,0x04,0xa2,0x00,0x19,0x04,0xa4,0x04,0xa4,0x00,0x1c,0x04,0xa8,0x04,0xaa,0x00,0x1d,0x05,0xfd,0x06,0x00,0x00,0x20,0x06,0x66,0x06,0x72,0x00,0x24,0x07,0x55,0x07,0x57,0x00,0x31,0x07,0x5c,0x07,0x5c,0x00,0x34,0x07,0xef,0x07,0xef,0x00,0x35,0x08,0x4c,0x08,0x4d,0x00,0x36,0x08,0x4f, 0x08,0x4f,0x00,0x38,0x0a,0xdb,0x0a,0xe0,0x00,0x39,0x0a,0xe2,0x0a,0xe2,0x00,0x3f,0x00,0x01,0x01,0x12,0x01,0x6a,0x00,0x01,0x00,0x0c,0x00,0xba,0x00,0x2b,0x00,0x00,0x2a,0xf6,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x02,0x00,0x00,0x2b,0x08,0x00,0x00,0x2b,0x0e,0x00,0x00,0x2b,0x14,0x00,0x00,0x2b,0x14,0x00,0x00, 0x2b,0x14,0x00,0x00,0x2b,0x1a,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x20,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x20,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x26,0x00,0x00,0x2b,0x2c,0x00,0x00,0x2b,0x32,0x00,0x00, 0x2b,0x38,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x3e,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x44,0x00,0x00,0x2b,0x4a,0x00,0x00,0x2a,0xfc,0x00,0x00,0x2b,0x50,0x00,0x00,0x2b,0x56,0x00,0x00,0x2b,0x5c,0x00,0x00,0x2b,0x62,0x00,0x00,0x2b,0x68,0x00,0x00,0x2b,0x68,0x00,0x00,0x2b,0x68,0x00,0x00,0x2b,0x6e,0x00,0x00,0x2b,0x26,0x00,0x00, 0x2b,0x74,0x00,0x00,0x2b,0x7a,0x00,0x00,0x2b,0x80,0x00,0x2b,0x2a,0xd8,0x2a,0xde,0x2a,0xde,0x2a,0xde,0x2a,0xde,0x2a,0xe4,0x2a,0xde,0x2a,0xde,0x2a,0xe4,0x2a,0xea,0x2a,0xf0,0x2a,0xf6,0x2a,0xe4,0x2a,0xfc,0x2a,0xe4,0x2b,0x02,0x2a,0xde,0x2a,0xde,0x2b,0x08,0x2b,0x0e,0x2b,0x14,0x2b,0x1a,0x2b,0x20,0x2b,0x26,0x2a,0xe4,0x2a,0xe4, 0x2b,0x2c,0x2b,0x14,0x2b,0x32,0x2b,0x38,0x2a,0xfc,0x2a,0xde,0x2a,0xe4,0x2a,0xe4,0x2b,0x3e,0x2a,0xe4,0x2a,0xe4,0x2a,0xe4,0x2a,0xe4,0x2a,0xe4,0x2a,0xde,0x2b,0x44,0x2b,0x4a,0x00,0x02,0x00,0x0e,0x02,0x45,0x02,0x45,0x00,0x00,0x04,0x75,0x04,0x78,0x00,0x01,0x04,0x7b,0x04,0x7f,0x00,0x05,0x04,0x82,0x04,0x84,0x00,0x0a,0x04,0x87, 0x04,0x91,0x00,0x0d,0x04,0x97,0x04,0x9a,0x00,0x18,0x04,0xa3,0x04,0xa3,0x00,0x1c,0x04,0xa5,0x04,0xa7,0x00,0x1d,0x04,0xab,0x04,0xac,0x00,0x20,0x07,0x58,0x07,0x5b,0x00,0x22,0x07,0xed,0x07,0xee,0x00,0x26,0x08,0x4e,0x08,0x4e,0x00,0x28,0x0a,0xe1,0x0a,0xe1,0x00,0x29,0x0a,0xe3,0x0a,0xe3,0x00,0x2a,0x00,0x02,0x00,0x0e,0x02,0x45, 0x02,0x45,0x00,0x00,0x04,0x75,0x04,0x78,0x00,0x01,0x04,0x7b,0x04,0x7f,0x00,0x05,0x04,0x82,0x04,0x84,0x00,0x0a,0x04,0x87,0x04,0x91,0x00,0x0d,0x04,0x97,0x04,0x9a,0x00,0x18,0x04,0xa3,0x04,0xa3,0x00,0x1c,0x04,0xa5,0x04,0xa7,0x00,0x1d,0x04,0xab,0x04,0xac,0x00,0x20,0x07,0x58,0x07,0x5b,0x00,0x22,0x07,0xed,0x07,0xee,0x00,0x26, 0x08,0x4e,0x08,0x4e,0x00,0x28,0x0a,0xe1,0x0a,0xe1,0x00,0x29,0x0a,0xe3,0x0a,0xe3,0x00,0x2a,0x00,0x01,0x00,0x18,0x00,0x1e,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x27,0xb4,0x00,0x02,0x2a,0x36,0x2a,0x3c,0x00,0x01,0x00,0x01,0x04,0x64,0x00,0x01,0x00,0x02,0x02,0xcf,0x02,0xd0,0x00,0x01,0x0e,0xec,0x0f,0x62,0x00,0x02, 0x00,0x0c,0x01,0xca,0x00,0x6f,0x00,0x00,0x2a,0x22,0x00,0x00,0x2a,0x28,0x00,0x01,0x2a,0x2e,0x00,0x00,0x2a,0x34,0x00,0x00,0x2a,0x3a,0x00,0x01,0x2a,0x2e,0x00,0x00,0x2a,0x40,0x00,0x00,0x2a,0x40,0x00,0x00,0x2a,0x46,0x00,0x00,0x2a,0x22,0x00,0x00,0x2a,0x4c,0x00,0x00,0x2a,0x52,0x00,0x01,0x2a,0x58,0x00,0x00,0x2a,0x5e,0x00,0x01, 0x2a,0x64,0x00,0x00,0x2a,0x4c,0x00,0x00,0x2a,0x52,0x00,0x00,0x2a,0x6a,0x00,0x00,0x2a,0x70,0x00,0x00,0x2a,0x76,0x00,0x00,0x2a,0x7c,0x00,0x00,0x2a,0x82,0x00,0x00,0x2a,0x88,0x00,0x00,0x2a,0x8e,0x00,0x01,0x2a,0x94,0x00,0x00,0x2a,0x88,0x00,0x00,0x2a,0x9a,0x00,0x00,0x2a,0x88,0x00,0x01,0x2a,0xa0,0x00,0x00,0x2a,0xa6,0x00,0x01, 0x2a,0xac,0x00,0x00,0x2a,0xb2,0x00,0x00,0x2a,0xb8,0x00,0x00,0x2a,0xbe,0x00,0x00,0x2a,0xc4,0x00,0x00,0x2a,0xca,0x00,0x01,0x2a,0xd0,0x00,0x00,0x2a,0x3a,0x00,0x00,0x2a,0x88,0x00,0x00,0x2a,0xd6,0x00,0x00,0x2a,0xdc,0x00,0x00,0x2a,0xe2,0x00,0x00,0x2a,0xe8,0x00,0x00,0x2a,0xdc,0x00,0x00,0x2a,0xe8,0x00,0x00,0x2a,0x22,0x00,0x00, 0x2a,0x22,0x00,0x00,0x2a,0x22,0x00,0x01,0x2a,0xee,0x00,0x00,0x2a,0xf4,0x00,0x00,0x2a,0xfa,0x00,0x00,0x2b,0x00,0x00,0x00,0x2b,0x06,0x00,0x00,0x2a,0x22,0x00,0x00,0x2b,0x0c,0x00,0x01,0x2a,0x2e,0x00,0x00,0x2a,0xdc,0x00,0x00,0x2b,0x12,0x00,0x00,0x2a,0xdc,0x00,0x00,0x2a,0xdc,0x00,0x00,0x2b,0x18,0x00,0x00,0x2b,0x1e,0x00,0x00, 0x2b,0x18,0x00,0x00,0x2b,0x1e,0x00,0x00,0x2b,0x1e,0x00,0x01,0x2b,0x24,0x00,0x01,0x2b,0x24,0x00,0x00,0x2b,0x2a,0x00,0x00,0x2b,0x2a,0x00,0x01,0x2b,0x30,0x00,0x00,0x2b,0x36,0x00,0x00,0x2b,0x3c,0x00,0x01,0x2b,0x42,0x00,0x00,0x2b,0x48,0x00,0x00,0x2b,0x4e,0x00,0x00,0x2b,0x54,0x00,0x01,0x2b,0x5a,0x00,0x01,0x2b,0x60,0x00,0x01, 0x2b,0x66,0x00,0x00,0x2b,0x6c,0x00,0x00,0x2b,0x72,0x00,0x01,0x2b,0x78,0x00,0x00,0x2b,0x7e,0x00,0x00,0x2b,0x54,0x00,0x00,0x2b,0x54,0x00,0x01,0x2b,0x84,0x00,0x00,0x2b,0x48,0x00,0x00,0x2b,0x8a,0x00,0x01,0x2b,0x90,0x00,0x01,0x2b,0x90,0x00,0x00,0x2b,0x36,0x00,0x00,0x2b,0x96,0x00,0x00,0x2b,0x9c,0x00,0x00,0x2b,0x6c,0x00,0x00, 0x2b,0xa2,0x00,0x00,0x2b,0xa8,0x00,0x00,0x2b,0xae,0x00,0x00,0x2b,0xb4,0x00,0x00,0x2b,0xba,0x00,0x00,0x2b,0xc0,0x00,0x00,0x2b,0xc6,0x00,0x01,0x2b,0xcc,0x00,0x00,0x2b,0xd2,0x00,0x00,0x2b,0xd8,0x00,0x00,0x2b,0xde,0x00,0x00,0x2b,0xe4,0x00,0x00,0x2b,0xea,0x00,0x00,0x2b,0xf0,0x00,0x00,0x2b,0xf6,0x00,0x00,0x2b,0xfc,0x00,0x01, 0x2c,0x02,0x03,0x48,0x2a,0x4a,0x2a,0x50,0x2a,0x56,0x2a,0x50,0x2a,0x5c,0x2a,0x50,0x2a,0x4a,0x2a,0x62,0x2a,0x68,0x2a,0x6e,0x2a,0x74,0x2a,0x7a,0x2a,0x80,0x2a,0x7a,0x2a,0x86,0x2a,0x8c,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2a,0x9e,0x2a,0x92,0x2a,0x98,0x2a,0xa4,0x2a,0x9e,0x2a,0xaa,0x2a,0x98,0x2a,0xb0,0x2a,0xb6,0x2a,0xbc,0x2a,0xb6, 0x2a,0xc2,0x2a,0xc8,0x2a,0xc2,0x2a,0xc8,0x2a,0xce,0x2a,0xd4,0x2a,0xda,0x2a,0xd4,0x2a,0xe0,0x2a,0xe6,0x2a,0xec,0x2a,0xd4,0x2a,0xf2,0x2a,0xd4,0x2a,0xf8,0x2a,0xe6,0x2a,0xfe,0x2b,0x04,0x2a,0xfe,0x2b,0x04,0x2b,0x0a,0x2b,0x04,0x2b,0x0a,0x2b,0x04,0x2b,0x10,0x2b,0x16,0x2b,0x1c,0x2b,0x22,0x2b,0x28,0x2b,0x2e,0x2b,0x34,0x2a,0x7a, 0x2b,0x3a,0x2b,0x40,0x2b,0x46,0x2b,0x4c,0x2b,0x52,0x2b,0x58,0x2a,0x68,0x2b,0x5e,0x2b,0x64,0x2b,0x6a,0x2b,0x70,0x2b,0x58,0x2b,0x64,0x2b,0x76,0x2b,0x7c,0x2a,0x7a,0x2b,0x82,0x2b,0x88,0x2b,0x8e,0x2b,0x94,0x2a,0x5c,0x2b,0x9a,0x2a,0x56,0x2b,0x9a,0x2b,0xa0,0x2b,0xa6,0x2a,0x4a,0x2a,0x62,0x2b,0xac,0x2b,0xb2,0x2a,0x4a,0x2b,0x9a, 0x2b,0xb8,0x2b,0xbe,0x2b,0xc4,0x2b,0xca,0x2b,0xd0,0x2b,0xd6,0x2b,0xdc,0x2b,0xd6,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0xaa,0x2a,0x98,0x2b,0xe2,0x2b,0xe8,0x2b,0xee,0x2b,0xe8,0x2b,0xf4,0x2b,0xfa,0x2c,0x00,0x2b,0xfa,0x2c,0x06,0x2c,0x0c,0x2c,0x06,0x2c,0x0c,0x2c,0x12,0x2c,0x18,0x2c,0x12,0x2c,0x18,0x2c,0x1e,0x2c,0x24, 0x2c,0x1e,0x2c,0x24,0x2c,0x2a,0x2a,0xe6,0x2c,0x30,0x2a,0xe6,0x2c,0x36,0x2c,0x3c,0x2c,0x42,0x2c,0x48,0x2c,0x4e,0x2c,0x54,0x2c,0x5a,0x2c,0x60,0x2c,0x66,0x2c,0x6c,0x2c,0x72,0x2c,0x78,0x2c,0x7e,0x2c,0x84,0x2c,0x8a,0x2b,0xca,0x2c,0x90,0x2b,0xa6,0x2c,0x96,0x2c,0x9c,0x2c,0x96,0x2c,0xa2,0x2a,0x68,0x2a,0x7a,0x2c,0xa8,0x2b,0x04, 0x2c,0xa8,0x2b,0x04,0x2b,0xb8,0x2b,0xd6,0x2b,0x1c,0x2b,0x16,0x2b,0xb8,0x2c,0xae,0x2a,0x68,0x2c,0xb4,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2c,0xba,0x2c,0xc0,0x2b,0xfa,0x2c,0xc6,0x2c,0xcc,0x2b,0x10,0x2b,0x16,0x2c,0xd2,0x2c,0xcc,0x2c,0xd8,0x2b,0x16,0x2c,0x96,0x2c,0x9c,0x2b,0x64,0x2b,0x76,0x2a,0x68,0x2b,0x5e, 0x2c,0xde,0x2b,0x58,0x2c,0xe4,0x2b,0xca,0x2c,0x66,0x2c,0x6c,0x2c,0xea,0x2b,0xd6,0x2c,0xf0,0x2a,0x7a,0x2c,0xf6,0x2b,0xe8,0x2c,0xfc,0x2b,0xfa,0x2d,0x02,0x2c,0x84,0x2d,0x08,0x2b,0xca,0x2a,0x68,0x2d,0x0e,0x2d,0x14,0x2d,0x1a,0x2c,0xe4,0x2b,0xca,0x2b,0xc4,0x2b,0xca,0x2d,0x20,0x2d,0x26,0x2d,0x2c,0x2d,0x32,0x2d,0x38,0x2d,0x26, 0x2d,0x3e,0x2d,0x32,0x2d,0x44,0x2c,0x48,0x2d,0x4a,0x2b,0x04,0x2d,0x4a,0x2b,0x04,0x2d,0x50,0x2d,0x56,0x2d,0x5c,0x2c,0x54,0x2d,0x62,0x2b,0x9a,0x2d,0x62,0x2a,0x50,0x2a,0x56,0x2b,0x9a,0x2a,0x56,0x2a,0x50,0x2a,0x4a,0x2d,0x68,0x2a,0x4a,0x2d,0x68,0x2a,0x4a,0x2b,0x9a,0x2a,0x4a,0x2a,0x50,0x2d,0x6e,0x2b,0xa6,0x2d,0x74,0x2d,0x7a, 0x2d,0x80,0x2c,0x9c,0x2d,0x86,0x2b,0x76,0x2d,0x8c,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2b,0xb8,0x2d,0x92,0x2a,0x68,0x2d,0x98,0x2b,0xd0,0x2d,0x9e,0x2a,0x74,0x2d,0xa4,0x2d,0xaa,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2d,0xaa,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2b,0xb8,0x2c,0xae,0x2a,0x68,0x2d,0x98,0x2d,0xb0,0x2a,0x98,0x2d,0xb0,0x2a,0x98, 0x2d,0xb6,0x2a,0x9e,0x2d,0xbc,0x2a,0x98,0x2d,0xbc,0x2a,0x98,0x2d,0xc2,0x2a,0x9e,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2a,0x8c,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2c,0xba,0x2d,0xc8,0x2a,0x98,0x2d,0xc8,0x2a,0x98,0x2d,0xc2,0x2a,0x9e,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2c,0xba, 0x2b,0xe2,0x2d,0xce,0x2b,0xe2,0x2d,0xd4,0x2b,0xee,0x2d,0xd4,0x2b,0xee,0x2b,0xe8,0x2b,0xe2,0x2d,0xd4,0x2d,0xda,0x2b,0xe8,0x2d,0xda,0x2b,0xe8,0x2d,0xda,0x2b,0xe8,0x2d,0xe0,0x2b,0xfa,0x2b,0xf4,0x2b,0xfa,0x2b,0xf4,0x2d,0xe6,0x2b,0xf4,0x2d,0xec,0x2c,0x00,0x2d,0xe6,0x2c,0x00,0x2b,0xfa,0x2c,0xc0,0x2b,0xfa,0x2c,0x06,0x2d,0xf2, 0x2d,0xf8,0x2d,0xfe,0x2c,0x06,0x2e,0x04,0x2a,0xb0,0x2e,0x0a,0x2c,0x06,0x2e,0x04,0x2a,0xbc,0x2e,0x0a,0x2c,0x12,0x2e,0x10,0x2a,0xc2,0x2e,0x16,0x2e,0x1c,0x2c,0x18,0x2e,0x22,0x2a,0xc8,0x2e,0x28,0x2c,0x24,0x2e,0x2e,0x2a,0xe6,0x2e,0x34,0x2a,0xe6,0x2e,0x3a,0x2a,0xd4,0x2e,0x40,0x2a,0xd4,0x2c,0x42,0x2c,0x48,0x2c,0x42,0x2c,0x48, 0x2c,0xa8,0x2e,0x46,0x2c,0xa8,0x2e,0x46,0x2c,0x42,0x2c,0x48,0x2a,0xfe,0x2e,0x46,0x2a,0xfe,0x2e,0x46,0x2c,0x42,0x2c,0x48,0x2c,0xa8,0x2e,0x4c,0x2c,0xa8,0x2e,0x4c,0x2d,0x44,0x2c,0x48,0x2d,0x4a,0x2b,0x04,0x2d,0x4a,0x2b,0x04,0x2e,0x52,0x2c,0x54,0x2e,0x58,0x2c,0x54,0x2e,0x5e,0x2e,0x64,0x2e,0x6a,0x2e,0x70,0x2c,0xc6,0x2c,0xcc, 0x2b,0x10,0x2b,0x16,0x2e,0x76,0x2c,0x60,0x2e,0x7c,0x2b,0x16,0x2e,0x82,0x2c,0x60,0x2e,0x88,0x2b,0x16,0x2c,0x5a,0x2c,0xae,0x2b,0x10,0x2d,0x98,0x2c,0xd2,0x2c,0xcc,0x2c,0xd8,0x2b,0x16,0x2e,0x8e,0x2c,0xcc,0x2e,0x94,0x2b,0x16,0x2c,0xd2,0x2e,0x9a,0x2c,0xd8,0x2e,0xa0,0x2c,0xd2,0x2e,0xa6,0x2c,0xd8,0x2d,0x98,0x2e,0xac,0x2c,0xcc, 0x2e,0xb2,0x2b,0x16,0x2c,0x66,0x2c,0x6c,0x2e,0xb8,0x2b,0x22,0x2c,0x66,0x2c,0x6c,0x2e,0xbe,0x2b,0x22,0x2c,0x66,0x2c,0x6c,0x2e,0xc4,0x2b,0x22,0x2c,0x66,0x2e,0xca,0x2b,0x1c,0x2e,0xd0,0x2e,0xd6,0x2e,0xdc,0x2b,0x34,0x2a,0x6e,0x2e,0xe2,0x2c,0x84,0x2e,0xd6,0x2e,0xe8,0x2b,0x34,0x2d,0xa4,0x2e,0xee,0x2c,0x84,0x2a,0xaa,0x2a,0x98, 0x2a,0xaa,0x2a,0x98,0x2a,0xa4,0x2c,0xba,0x2c,0x90,0x2b,0xa6,0x2e,0xf4,0x2e,0xfa,0x2f,0x00,0x2b,0xa6,0x2f,0x06,0x2b,0xa6,0x2f,0x0c,0x2b,0xa6,0x2f,0x00,0x2b,0xa6,0x2f,0x12,0x2b,0xa6,0x2f,0x18,0x2b,0xa6,0x2f,0x1e,0x2f,0x24,0x2f,0x2a,0x2b,0x88,0x2f,0x30,0x2c,0x9c,0x2f,0x36,0x2b,0x76,0x2f,0x3c,0x2b,0x5e,0x2f,0x12,0x2b,0xa6, 0x2f,0x42,0x2f,0x48,0x2f,0x4e,0x2f,0x54,0x2f,0x42,0x2f,0x5a,0x2f,0x4e,0x2f,0x60,0x2c,0x06,0x2d,0xf2,0x2a,0xbc,0x2d,0xfe,0x2c,0x12,0x2e,0x10,0x2a,0xc2,0x2f,0x66,0x2c,0x30,0x2a,0xe6,0x2f,0x6c,0x2a,0xe6,0x2a,0xec,0x2f,0x72,0x2a,0xf2,0x2f,0x72,0x2c,0x72,0x2f,0x78,0x2f,0x7e,0x2c,0xcc,0x2f,0x7e,0x2c,0xcc,0x2f,0x84,0x2f,0x8a, 0x2f,0x90,0x2b,0xe8,0x2f,0x96,0x2b,0xe8,0x2d,0xe0,0x2b,0xfa,0x2d,0xe0,0x2b,0xfa,0x2f,0x9c,0x2b,0x40,0x2f,0xa2,0x2b,0x4c,0x2f,0xa8,0x2f,0xae,0x2f,0xb4,0x2f,0xba,0x2e,0xb8,0x2b,0x16,0x2e,0xbe,0x2b,0x16,0x2e,0xc4,0x2b,0x16,0x2b,0x1c,0x2e,0xd0,0x2b,0xb8,0x2f,0xc0,0x2a,0x68,0x2f,0xc6,0x2b,0xdc,0x2b,0xbe,0x2a,0x80,0x2a,0x6e, 0x2b,0xb8,0x2d,0x92,0x2a,0x68,0x2c,0xb4,0x2b,0xd0,0x2d,0x92,0x2a,0x74,0x2c,0xb4,0x2b,0xd0,0x2e,0x9a,0x2b,0x34,0x2f,0xcc,0x2b,0xb8,0x2f,0xd2,0x2a,0x68,0x2f,0xd8,0x2f,0xde,0x2b,0xd6,0x2f,0x3c,0x2a,0x7a,0x2a,0xaa,0x2a,0x98,0x2a,0xaa,0x2a,0x98,0x2a,0xa4,0x2a,0x9e,0x2a,0x92,0x2a,0x98,0x2a,0x92,0x2a,0x98,0x2a,0x86,0x2c,0xba, 0x2b,0xe2,0x2f,0xe4,0x2b,0xe2,0x2f,0xea,0x2b,0xf4,0x2b,0xfa,0x2c,0x06,0x2c,0x0c,0x2f,0xf0,0x2a,0xb6,0x2f,0xf6,0x2a,0xe6,0x2f,0xfc,0x2a,0xe6,0x2a,0xec,0x2a,0xd4,0x2a,0xf2,0x2a,0xd4,0x30,0x02,0x2a,0xe6,0x30,0x08,0x2a,0xe6,0x2e,0x3a,0x2a,0xd4,0x2e,0x40,0x2a,0xd4,0x30,0x02,0x2a,0xe6,0x30,0x08,0x2a,0xe6,0x2e,0x3a,0x2a,0xd4, 0x2e,0x40,0x2a,0xd4,0x2c,0x42,0x2c,0x48,0x2c,0xa8,0x30,0x0e,0x2c,0xa8,0x30,0x0e,0x2c,0x42,0x2c,0x48,0x2c,0xa8,0x2e,0x4c,0x2c,0xa8,0x30,0x14,0x30,0x1a,0x2c,0xcc,0x2e,0x7c,0x2b,0x16,0x2e,0x7c,0x2b,0x16,0x30,0x20,0x2c,0xcc,0x2e,0x88,0x2b,0x16,0x2e,0x88,0x2b,0x16,0x2c,0xc6,0x2c,0xae,0x2b,0x10,0x30,0x26,0x2b,0x10,0x30,0x26, 0x30,0x2c,0x2c,0x78,0x30,0x32,0x2b,0x2e,0x2c,0x72,0x30,0x38,0x2b,0x28,0x30,0x3e,0x2e,0xd6,0x30,0x44,0x2b,0x34,0x2b,0x5e,0x30,0x4a,0x2c,0x84,0x30,0x50,0x2a,0x7a,0x30,0x56,0x2c,0x84,0x30,0x5c,0x2a,0x7a,0x2c,0x66,0x2c,0x6c,0x2c,0x66,0x2c,0x6c,0x2b,0x1c,0x2b,0x22,0x2b,0x1c,0x2b,0x16,0x2c,0xc0,0x2b,0xfa,0x30,0x62,0x2b,0xfa, 0x2c,0x06,0x2c,0x0c,0x2a,0xbc,0x2a,0xb6,0x2b,0xf4,0x2b,0xfa,0x2c,0x00,0x2b,0xfa,0x2c,0xc0,0x2b,0xfa,0x2c,0xfc,0x2b,0xfa,0x2d,0xe0,0x2b,0xfa,0x2b,0xf4,0x2b,0xfa,0x2b,0xf4,0x2d,0xe6,0x2b,0xf4,0x2d,0xec,0x2c,0x00,0x2d,0xe6,0x2c,0x00,0x2b,0xfa,0x2c,0xc0,0x2b,0xfa,0x2c,0xc0,0x2b,0xfa,0x30,0x62,0x2b,0xfa,0x30,0x68,0x30,0x6e, 0x2b,0x64,0x30,0x74,0x2a,0x68,0x2d,0xa4,0x2a,0x68,0x2d,0xa4,0x2b,0xa0,0x2b,0xa6,0x2b,0x7c,0x2a,0x7a,0x2b,0xb8,0x2b,0xbe,0x2a,0x68,0x2a,0x6e,0x2b,0xd0,0x2b,0xd6,0x2a,0x74,0x2a,0x7a,0x2b,0xdc,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2a,0x86,0x2a,0x8c,0x2a,0x86,0x2a,0x9e,0x2a,0xa4,0x2a,0x9e,0x30,0x7a,0x2b,0xe8,0x30,0x80,0x2b,0xe8, 0x2c,0x06,0x2c,0x0c,0x2a,0xb0,0x2a,0xb6,0x2c,0x06,0x2c,0x0c,0x2a,0xbc,0x2a,0xb6,0x2c,0x12,0x2c,0x18,0x2a,0xc2,0x2a,0xc8,0x2c,0x12,0x2c,0x18,0x2a,0xc2,0x2a,0xc8,0x2c,0x1e,0x2c,0x24,0x2c,0x1e,0x30,0x86,0x2c,0x1e,0x30,0x86,0x2c,0x1e,0x2c,0x24,0x2c,0x1e,0x30,0x86,0x2c,0x1e,0x30,0x86,0x30,0x8c,0x2c,0x9c,0x30,0x92,0x2b,0x76, 0x2a,0x74,0x2b,0x5e,0x2a,0x74,0x2b,0x5e,0x30,0x98,0x2c,0x9c,0x30,0x9e,0x2b,0x76,0x2a,0x80,0x2b,0x5e,0x2a,0x80,0x2b,0x5e,0x2c,0x42,0x2c,0x48,0x2c,0x4e,0x2c,0x54,0x2c,0x5a,0x2c,0x60,0x2b,0x10,0x2b,0x16,0x2c,0x72,0x2c,0x78,0x2b,0x28,0x2b,0x2e,0x2c,0x7e,0x2c,0x84,0x2b,0x34,0x2a,0x7a,0x30,0xa4,0x2a,0x9e,0x30,0xaa,0x2b,0x40, 0x30,0xb0,0x30,0xb6,0x2c,0x90,0x2b,0xa6,0x2a,0x68,0x2a,0x7a,0x2a,0x68,0x2a,0x7a,0x2a,0x68,0x2b,0x5e,0x2b,0xb8,0x2b,0xd6,0x2a,0x68,0x2a,0x7a,0x2d,0x5c,0x2c,0x54,0x2c,0xa8,0x2b,0x04,0x2c,0xa8,0x2b,0x04,0x2d,0x6e,0x2b,0xa6,0x2d,0x74,0x2d,0x7a,0x30,0xbc,0x2a,0x7a,0x30,0xbc,0x2a,0x7a,0x2c,0xea,0x2b,0xd6,0x2c,0xf0,0x2a,0x7a, 0x2d,0x8c,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2b,0xb8,0x2d,0x92,0x2a,0x68,0x2d,0x98,0x2b,0xd0,0x2d,0x9e,0x2a,0x74,0x2d,0xa4,0x2d,0xaa,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2b,0xb8,0x2c,0xae,0x2a,0x68,0x2c,0xb4,0x2d,0xaa,0x2b,0xd6,0x2a,0x80,0x2a,0x7a,0x2b,0xb8,0x2c,0xae,0x2a,0x68,0x2d,0x98,0x2d,0xb6,0x2a,0x9e,0x2d,0xc2,0x2a,0x9e, 0x2a,0x86,0x2a,0x8c,0x2a,0x86,0x2c,0xba,0x2d,0xc2,0x2a,0x9e,0x2a,0x86,0x2c,0xba,0x2a,0x86,0x2c,0xba,0x30,0xc2,0x2b,0xe8,0x30,0x7a,0x2d,0xce,0x30,0x7a,0x2d,0xd4,0x30,0x80,0x2d,0xd4,0x30,0x80,0x2b,0xe8,0x30,0x7a,0x2d,0xd4,0x30,0xc8,0x2b,0xe8,0x30,0xc8,0x2b,0xe8,0x30,0xc8,0x2b,0xe8,0x2c,0x06,0x2d,0xf2,0x2d,0xf8,0x2d,0xfe, 0x2c,0x06,0x2e,0x04,0x2a,0xb0,0x2e,0x0a,0x2c,0x06,0x2e,0x04,0x2a,0xbc,0x2e,0x0a,0x2c,0x12,0x2e,0x10,0x2a,0xc2,0x2e,0x16,0x2e,0x1c,0x2c,0x18,0x2e,0x22,0x2a,0xc8,0x2e,0x28,0x2c,0x24,0x2e,0x28,0x30,0x86,0x2e,0x28,0x30,0x86,0x2c,0x42,0x2c,0x48,0x2c,0x42,0x2c,0x48,0x2c,0x42,0x2c,0x48,0x2d,0x44,0x2c,0x48,0x2c,0x42,0x2c,0x48, 0x2d,0x44,0x2c,0x48,0x2e,0x52,0x2c,0x54,0x2a,0xfe,0x2b,0x04,0x2a,0xfe,0x2b,0x04,0x2e,0x58,0x2c,0x54,0x2d,0x4a,0x2b,0x04,0x2d,0x4a,0x2b,0x04,0x30,0xce,0x2c,0xcc,0x2b,0x10,0x2b,0x16,0x2e,0x5e,0x2e,0x64,0x2e,0x6a,0x2e,0x70,0x30,0xce,0x2c,0xcc,0x2b,0x10,0x2b,0x16,0x2e,0x76,0x2c,0x60,0x2e,0x7c,0x2b,0x16,0x2e,0x82,0x2c,0x60, 0x2e,0x88,0x2b,0x16,0x2c,0x5a,0x2c,0xae,0x2b,0x10,0x2d,0x98,0x2c,0xd2,0x2c,0xcc,0x2c,0xd8,0x2b,0x16,0x30,0xd4,0x2c,0xcc,0x2c,0xd8,0x2b,0x16,0x30,0xda,0x2c,0xcc,0x2e,0x94,0x2b,0x16,0x30,0xd4,0x2e,0x9a,0x2c,0xd8,0x2e,0xa0,0x30,0xd4,0x2e,0xa6,0x2c,0xd8,0x2d,0x98,0x30,0xe0,0x2c,0xcc,0x2e,0xb2,0x2b,0x16,0x2c,0x66,0x2c,0x6c, 0x2c,0x66,0x2c,0x6c,0x2c,0x66,0x2c,0x6c,0x2c,0x66,0x2e,0xca,0x30,0xe6,0x30,0xec,0x2b,0x34,0x2a,0x6e,0x2d,0x02,0x2c,0x84,0x2e,0xe2,0x2c,0x84,0x2c,0xf0,0x2a,0x7a,0x2c,0xf0,0x2a,0x7a,0x30,0xe6,0x2e,0xe8,0x2b,0x34,0x2d,0xa4,0x2e,0xee,0x2c,0x84,0x30,0xa4,0x2a,0x9e,0x30,0xb0,0x30,0xb6,0x2a,0xa4,0x2c,0xba,0x30,0xf2,0x2d,0x56, 0x30,0xf8,0x2d,0x56,0x2c,0x90,0x2b,0xa6,0x2e,0xf4,0x2e,0xfa,0x2f,0x00,0x2b,0xa6,0x2f,0x06,0x2b,0xa6,0x2f,0x0c,0x2b,0xa6,0x2f,0x00,0x2b,0xa6,0x2f,0x12,0x2b,0xa6,0x2f,0x18,0x2b,0xa6,0x2a,0x68,0x2b,0x5e,0x2f,0x3c,0x2b,0x5e,0x2f,0x12,0x2b,0xa6,0x2a,0x68,0x2d,0x98,0x2a,0x68,0x2d,0x98,0x2a,0x68,0x2c,0xb4,0x2a,0x68,0x2c,0xb4, 0x2c,0x06,0x2d,0xf2,0x2a,0xbc,0x2d,0xfe,0x2c,0x12,0x2e,0x10,0x2a,0xc2,0x2f,0x66,0x2b,0xb8,0x2f,0xc0,0x2a,0x68,0x2a,0x6e,0x2b,0xdc,0x2b,0xbe,0x2a,0x80,0x2a,0x6e,0x2b,0xb8,0x2d,0x92,0x2a,0x68,0x2c,0xb4,0x2b,0xd0,0x2d,0x92,0x2a,0x74,0x2c,0xb4,0x2b,0xd0,0x2e,0x9a,0x2b,0x34,0x2f,0xcc,0x2b,0xb8,0x2f,0xd2,0x2a,0x68,0x2f,0xd8, 0x2f,0xde,0x2b,0xd6,0x2f,0x3c,0x2a,0x7a,0x2a,0xa4,0x2a,0x9e,0x2a,0x86,0x2c,0xba,0x30,0xfe,0x2f,0xe4,0x30,0x7a,0x2f,0xea,0x2b,0xf4,0x2b,0xfa,0x2c,0x06,0x2c,0x0c,0x2f,0xf0,0x2a,0xb6,0x2c,0x42,0x2c,0x48,0x2c,0x42,0x2c,0x48,0x31,0x04,0x2c,0xcc,0x31,0x0a,0x2c,0xcc,0x30,0xce,0x2c,0xae,0x30,0x2c,0x2c,0x78,0x30,0x32,0x2b,0x2e, 0x2c,0x72,0x30,0x38,0x2b,0x28,0x30,0x3e,0x30,0xe6,0x31,0x10,0x2b,0x34,0x2b,0x5e,0x30,0x4a,0x2c,0x84,0x30,0x50,0x2a,0x7a,0x30,0x56,0x2c,0x84,0x30,0x5c,0x2a,0x7a,0x2c,0x06,0x2c,0x0c,0x2a,0xbc,0x2a,0xb6,0x2a,0x92,0x31,0x16,0x2a,0x92,0x31,0x16,0x2a,0x86,0x31,0x1c,0x2a,0x86,0x31,0x1c,0x2a,0x92,0x31,0x22,0x2a,0x92,0x31,0x22, 0x31,0x28,0x31,0x2e,0x31,0x28,0x31,0x2e,0x2c,0x06,0x2c,0x0c,0x2c,0x06,0x2c,0x0c,0x31,0x34,0x2a,0xb6,0x31,0x34,0x2a,0xb6,0x31,0x3a,0x2b,0xfa,0x31,0x3a,0x2b,0xfa,0x31,0x40,0x2a,0x98,0x31,0x40,0x2a,0x98,0x31,0x46,0x2a,0x9e,0x31,0x46,0x2a,0x9e,0x31,0x4c,0x31,0x52,0x31,0x4c,0x31,0x58,0x31,0x4c,0x31,0x52,0x31,0x4c,0x31,0x58, 0x31,0x5e,0x2c,0x9c,0x31,0x64,0x2b,0x76,0x31,0x6a,0x2b,0x5e,0x31,0x6a,0x2b,0x5e,0x31,0x5e,0x2c,0x9c,0x31,0x64,0x2b,0x76,0x31,0x6a,0x2b,0x5e,0x31,0x6a,0x2b,0x5e,0x2f,0x42,0x31,0x70,0x31,0x76,0x31,0x70,0x2a,0x68,0x31,0x7c,0x2a,0x68,0x31,0x7c,0x31,0x82,0x31,0x88,0x31,0x82,0x31,0x88,0x31,0x8e,0x31,0x94,0x31,0x8e,0x31,0x94, 0x31,0x9a,0x2d,0x26,0x31,0xa0,0x2d,0x32,0x31,0x9a,0x2d,0x26,0x31,0xa0,0x2d,0x32,0x2a,0x92,0x31,0x16,0x2a,0x92,0x31,0x16,0x2a,0x86,0x31,0xa6,0x2a,0x86,0x31,0xa6,0x2c,0x06,0x2c,0x0c,0x2c,0x06,0x2c,0x0c,0x31,0xac,0x2a,0xb6,0x31,0xac,0x2a,0xb6,0x2c,0x06,0x2c,0x0c,0x2c,0x06,0x2c,0x0c,0x31,0xb2,0x2a,0xb6,0x31,0xb2,0x2a,0xb6, 0x2e,0x76,0x2c,0x60,0x2e,0x76,0x2c,0x60,0x2e,0x7c,0x2b,0x16,0x2e,0x7c,0x2b,0x16,0x31,0xb8,0x31,0xbe,0x31,0xc4,0x31,0xbe,0x31,0xca,0x31,0xd0,0x31,0xca,0x31,0xbe,0x31,0xd6,0x31,0xbe,0x31,0xd6,0x31,0xbe,0x31,0xca,0x31,0xd0,0x31,0xdc,0x31,0xbe,0x31,0xe2,0x31,0xbe,0x31,0xe2,0x31,0xbe,0x31,0xe8,0x2a,0xd4,0x31,0xe8,0x2a,0xd4, 0x31,0xee,0x2a,0xd4,0x31,0xee,0x2a,0xd4,0x31,0xf4,0x31,0xfa,0x31,0xf4,0x31,0xfa,0x31,0xe8,0x32,0x00,0x31,0xe8,0x32,0x00,0x31,0xee,0x32,0x00,0x31,0xee,0x32,0x00,0x31,0xee,0x31,0xfa,0x31,0xee,0x31,0xfa,0x32,0x06,0x2a,0xd4,0x32,0x06,0x2a,0xd4,0x31,0xee,0x2a,0xd4,0x31,0xee,0x2a,0xd4,0x32,0x0c,0x2a,0xd4,0x32,0x0c,0x2a,0xd4, 0x32,0x12,0x2a,0xd4,0x32,0x12,0x2a,0xd4,0x32,0x18,0x2a,0xd4,0x32,0x18,0x2a,0xd4,0x32,0x1e,0x2a,0xc8,0x32,0x1e,0x2a,0xc8,0x32,0x1e,0x2a,0xc8,0x32,0x1e,0x2a,0xc8,0x32,0x1e,0x32,0x24,0x32,0x1e,0x32,0x24,0x32,0x2a,0x2a,0xc8,0x32,0x2a,0x2a,0xc8,0x32,0x1e,0x2e,0x16,0x32,0x1e,0x2e,0x16,0x32,0x30,0x32,0x36,0x32,0x30,0x32,0x3c, 0x32,0x42,0x32,0x36,0x32,0x42,0x32,0x3c,0x32,0x48,0x32,0x36,0x32,0x48,0x32,0x3c,0x32,0x4e,0x32,0x36,0x32,0x4e,0x32,0x3c,0x32,0x30,0x32,0x54,0x32,0x30,0x32,0x5a,0x32,0x30,0x32,0x36,0x32,0x30,0x32,0x3c,0x32,0x60,0x32,0x66,0x32,0x6c,0x32,0x66,0x32,0x72,0x32,0x66,0x32,0x78,0x32,0x66,0x32,0x60,0x32,0x66,0x32,0x60,0x32,0x7e, 0x32,0x60,0x32,0x84,0x32,0x6c,0x32,0x7e,0x32,0x6c,0x32,0x66,0x32,0x8a,0x32,0x66,0x32,0x78,0x32,0x66,0x32,0x60,0x32,0x66,0x32,0x8a,0x32,0x66,0x32,0x90,0x32,0x66,0x32,0x96,0x32,0x66,0x2b,0x82,0x2b,0x88,0x32,0x9c,0x2b,0x76,0x32,0xa2,0x2b,0x76,0x32,0xa8,0x2b,0x76,0x32,0xae,0x2b,0x76,0x32,0xae,0x32,0xb4,0x2d,0x86,0x2b,0x76, 0x32,0xba,0x2b,0x88,0x2f,0x36,0x2b,0x76,0x31,0x76,0x32,0xc0,0x31,0x64,0x2b,0x76,0x31,0x64,0x2b,0x76,0x31,0x76,0x32,0xc6,0x31,0x76,0x32,0xcc,0x32,0xd2,0x2d,0x32,0x32,0xd2,0x2d,0x32,0x2d,0x3e,0x2d,0x32,0x2d,0x3e,0x2d,0x32,0x31,0xa0,0x2d,0x32,0x31,0xa0,0x2d,0x32,0x31,0xa0,0x2d,0x32,0x31,0xa0,0x2d,0x32,0x32,0xae,0x2b,0x76, 0x31,0x76,0x32,0xd8,0x32,0xae,0x32,0xde,0x32,0xe4,0x32,0xea,0x32,0xf0,0x32,0xf6,0x2b,0x52,0x2b,0x58,0x32,0x8a,0x32,0x66,0x32,0xfc,0x33,0x02,0x2a,0x68,0x33,0x08,0x32,0xfc,0x33,0x02,0x2a,0x68,0x33,0x08,0x33,0x0e,0x33,0x14,0x33,0x0e,0x33,0x14,0x33,0x1a,0x2a,0x8c,0x33,0x1a,0x2a,0x8c,0x33,0x20,0x2c,0x24,0x33,0x20,0x2c,0x24, 0x33,0x20,0x2c,0x24,0x33,0x20,0x2c,0x24,0x2c,0x42,0x33,0x26,0x33,0x2c,0x33,0x32,0x33,0x2c,0x33,0x32,0x33,0x38,0x33,0x26,0x33,0x3e,0x33,0x44,0x33,0x4a,0x33,0x32,0x33,0x4a,0x33,0x32,0x33,0x3e,0x33,0x44,0x33,0x50,0x33,0x56,0x33,0x5c,0x32,0xea,0x33,0x5c,0x2b,0x16,0x33,0x50,0x33,0x56,0x33,0x62,0x33,0x68,0x33,0x6e,0x2b,0x2e, 0x33,0x6e,0x2b,0x2e,0x33,0x62,0x33,0x68,0x33,0x74,0x33,0x7a,0x33,0x80,0x33,0x86,0x33,0x80,0x33,0x8c,0x33,0x92,0x33,0x98,0x33,0x9e,0x33,0x7a,0x33,0xa4,0x33,0x8c,0x33,0xa4,0x33,0x8c,0x33,0xaa,0x33,0x98,0x33,0xb0,0x33,0xb6,0x33,0xb0,0x33,0xb6,0x2c,0x90,0x33,0xbc,0x2c,0x90,0x33,0xbc,0x33,0xc2,0x33,0xc8,0x33,0xc2,0x33,0xc8, 0x2b,0xd0,0x33,0x02,0x33,0x80,0x33,0x8c,0x33,0x80,0x33,0x8c,0x2b,0xd0,0x33,0x02,0x30,0x7a,0x33,0xce,0x30,0x7a,0x33,0xce,0x2c,0x12,0x33,0xd4,0x2a,0xc2,0x33,0xda,0x2a,0xc2,0x33,0xda,0x2c,0x12,0x33,0xd4,0x2c,0xd2,0x2c,0xcc,0x33,0xe0,0x2b,0x16,0x33,0xe0,0x2b,0x16,0x2c,0xd2,0x2c,0xcc,0x2c,0x90,0x33,0xe6,0x2c,0x90,0x33,0xe6, 0x33,0xec,0x2b,0xfa,0x33,0xec,0x2b,0xfa,0x2c,0x2a,0x2a,0xe6,0x2c,0x5a,0x2c,0xae,0x33,0xf2,0x2b,0xbe,0x33,0xf2,0x2c,0xae,0x33,0xf2,0x2b,0xd6,0x33,0xf8,0x2b,0xfa,0x33,0xfe,0x2c,0xa2,0x2c,0x42,0x2c,0x48,0x2d,0x5c,0x2c,0x54,0x2d,0x02,0x2c,0x84,0x34,0x04,0x27,0x56,0x2a,0xe0,0x2a,0xe6,0x2a,0xda,0x34,0x0a,0x2a,0xce,0x34,0x10, 0x2c,0x5a,0x2c,0xae,0x2b,0x10,0x2e,0xa0,0x2b,0x10,0x2e,0xa0,0x33,0xf2,0x2b,0xbe,0x34,0x16,0x2a,0x6e,0x34,0x16,0x2a,0x6e,0x33,0xf2,0x2c,0xae,0x34,0x16,0x2c,0xb4,0x34,0x16,0x2c,0xb4,0x33,0xf2,0x2b,0xd6,0x34,0x1c,0x2b,0x16,0x34,0x1c,0x2b,0x16,0x33,0xf8,0x2b,0xfa,0x34,0x22,0x2b,0x6a,0x2a,0x80,0x2b,0x5e,0x2a,0x80,0x2b,0x5e, 0x2c,0x42,0x2c,0x48,0x2c,0xa8,0x2e,0x46,0x2c,0xa8,0x2e,0x46,0x2d,0x5c,0x2c,0x54,0x2a,0xfe,0x2b,0x04,0x2a,0xfe,0x2b,0x04,0x2d,0x02,0x2c,0x84,0x27,0x56,0x27,0x56,0x27,0x56,0x27,0x56,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c, 0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44, 0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x02,0x00,0x25,0x08,0xc7,0x08,0xd6,0x00,0x00,0x08,0xe1,0x08,0xe9,0x00,0x10,0x08,0xeb,0x08,0xf7,0x00,0x19,0x08,0xf9,0x08,0xf9,0x00,0x26,0x09,0x02,0x09,0x02,0x00,0x27,0x09,0x07,0x09,0x2b, 0x00,0x28,0x09,0x3b,0x09,0x4e,0x00,0x4d,0x09,0x59,0x09,0x59,0x00,0x61,0x09,0x5b,0x09,0x68,0x00,0x62,0x09,0x6c,0x09,0x6e,0x00,0x70,0x09,0x72,0x09,0x72,0x00,0x73,0x09,0x7c,0x09,0x7c,0x00,0x74,0x09,0x80,0x09,0xf8,0x00,0x75,0x09,0xfa,0x0a,0x0e,0x00,0xee,0x0a,0x24,0x0a,0x2b,0x01,0x03,0x0a,0x2d,0x0a,0x2d,0x01,0x0b,0x0a,0x3e, 0x0a,0x3f,0x01,0x0c,0x0a,0x43,0x0a,0x43,0x01,0x0e,0x0a,0x54,0x0a,0x5b,0x01,0x0f,0x0a,0x5f,0x0a,0x62,0x01,0x17,0x0a,0x72,0x0a,0xb7,0x01,0x1b,0x0b,0x0c,0x0b,0x18,0x01,0x61,0x0e,0x20,0x0e,0x3e,0x01,0x6e,0x0e,0x4b,0x0e,0x61,0x01,0x8d,0x0e,0x6e,0x0e,0x72,0x01,0xa4,0x0e,0x74,0x0e,0xd5,0x01,0xa9,0x0e,0xd7,0x0e,0xea,0x02,0x0b, 0x0e,0xec,0x0f,0x4f,0x02,0x1f,0x0f,0x62,0x0f,0xc3,0x02,0x83,0x13,0x00,0x13,0x29,0x02,0xe5,0x14,0x04,0x14,0x07,0x03,0x0f,0x14,0x09,0x14,0x16,0x03,0x13,0x14,0x53,0x14,0x5c,0x03,0x21,0x14,0x6b,0x14,0x6b,0x03,0x2b,0x14,0x6d,0x14,0x7b,0x03,0x2c,0x14,0x7d,0x14,0x87,0x03,0x3b,0x14,0xad,0x14,0xae,0x03,0x46,0x00,0x01,0x02,0x2c, 0x02,0xa2,0x00,0x02,0x00,0x0c,0x01,0xca,0x00,0x6f,0x00,0x00,0x19,0xde,0x00,0x00,0x19,0xe4,0x00,0x01,0x19,0xea,0x00,0x00,0x19,0xf0,0x00,0x00,0x19,0xf6,0x00,0x01,0x19,0xea,0x00,0x00,0x19,0xfc,0x00,0x00,0x19,0xfc,0x00,0x00,0x1a,0x02,0x00,0x00,0x19,0xde,0x00,0x00,0x1a,0x08,0x00,0x00,0x1a,0x0e,0x00,0x01,0x1a,0x14,0x00,0x00, 0x1a,0x1a,0x00,0x01,0x1a,0x20,0x00,0x00,0x1a,0x08,0x00,0x00,0x1a,0x0e,0x00,0x00,0x1a,0x26,0x00,0x00,0x1a,0x2c,0x00,0x00,0x1a,0x32,0x00,0x00,0x1a,0x38,0x00,0x00,0x1a,0x3e,0x00,0x00,0x1a,0x44,0x00,0x00,0x1a,0x4a,0x00,0x01,0x1a,0x50,0x00,0x00,0x1a,0x44,0x00,0x00,0x1a,0x56,0x00,0x00,0x1a,0x44,0x00,0x01,0x1a,0x5c,0x00,0x00, 0x1a,0x62,0x00,0x01,0x1a,0x68,0x00,0x00,0x1a,0x6e,0x00,0x00,0x1a,0x74,0x00,0x00,0x1a,0x7a,0x00,0x00,0x1a,0x80,0x00,0x00,0x1a,0x86,0x00,0x01,0x1a,0x8c,0x00,0x00,0x19,0xf6,0x00,0x00,0x1a,0x44,0x00,0x00,0x1a,0x92,0x00,0x00,0x1a,0x98,0x00,0x00,0x1a,0x9e,0x00,0x00,0x1a,0xa4,0x00,0x00,0x1a,0x98,0x00,0x00,0x1a,0xa4,0x00,0x00, 0x19,0xde,0x00,0x00,0x19,0xde,0x00,0x00,0x19,0xde,0x00,0x01,0x1a,0xaa,0x00,0x00,0x1a,0xb0,0x00,0x00,0x1a,0xb6,0x00,0x00,0x1a,0xbc,0x00,0x00,0x1a,0xc2,0x00,0x00,0x19,0xde,0x00,0x00,0x1a,0xc8,0x00,0x01,0x19,0xea,0x00,0x00,0x1a,0x98,0x00,0x00,0x1a,0xce,0x00,0x00,0x1a,0x98,0x00,0x00,0x1a,0x98,0x00,0x00,0x1a,0xd4,0x00,0x00, 0x1a,0xda,0x00,0x00,0x1a,0xd4,0x00,0x00,0x1a,0xda,0x00,0x00,0x1a,0xda,0x00,0x01,0x1a,0xe0,0x00,0x01,0x1a,0xe0,0x00,0x00,0x1a,0xe6,0x00,0x00,0x1a,0xe6,0x00,0x01,0x1a,0xec,0x00,0x00,0x1a,0xf2,0x00,0x00,0x1a,0xf8,0x00,0x01,0x1a,0xfe,0x00,0x00,0x1b,0x04,0x00,0x00,0x1b,0x0a,0x00,0x00,0x1b,0x10,0x00,0x01,0x1b,0x16,0x00,0x01, 0x1b,0x1c,0x00,0x01,0x1b,0x22,0x00,0x00,0x1b,0x28,0x00,0x00,0x1b,0x2e,0x00,0x01,0x1b,0x34,0x00,0x00,0x1b,0x3a,0x00,0x00,0x1b,0x10,0x00,0x00,0x1b,0x10,0x00,0x01,0x1b,0x40,0x00,0x00,0x1b,0x04,0x00,0x00,0x1b,0x46,0x00,0x01,0x1b,0x4c,0x00,0x01,0x1b,0x4c,0x00,0x00,0x1a,0xf2,0x00,0x00,0x1b,0x52,0x00,0x00,0x1b,0x58,0x00,0x00, 0x1b,0x28,0x00,0x00,0x1b,0x5e,0x00,0x00,0x1b,0x64,0x00,0x00,0x1b,0x6a,0x00,0x00,0x1b,0x70,0x00,0x00,0x1b,0x76,0x00,0x00,0x1b,0x7c,0x00,0x00,0x1b,0x82,0x00,0x01,0x1b,0x88,0x00,0x00,0x1b,0x8e,0x00,0x00,0x1b,0x94,0x00,0x00,0x1b,0x9a,0x00,0x00,0x1b,0xa0,0x00,0x00,0x1b,0xa6,0x00,0x00,0x1b,0xac,0x00,0x00,0x1b,0xb2,0x00,0x00, 0x1b,0xb8,0x00,0x01,0x1b,0xbe,0x00,0x05,0x00,0x0c,0x00,0x1a,0x00,0x2c,0x00,0x3e,0x00,0x50,0x00,0x03,0x23,0xd8,0x23,0xde,0x23,0xe4,0x23,0xea,0x1b,0x02,0x1b,0x08,0x00,0x04,0x23,0xe2,0x23,0xe8,0x23,0xca,0x23,0xd0,0x23,0xd6,0x23,0xdc,0x1a,0xf4,0x1a,0xfa,0x00,0x04,0x23,0xdc,0x23,0xe2,0x23,0xe8,0x23,0xee,0x23,0xf4,0x23,0xfa, 0x1b,0xf6,0x1b,0xfc,0x00,0x04,0x23,0xee,0x23,0xf4,0x23,0xa6,0x23,0xac,0x23,0xb2,0x23,0xb8,0x1a,0xd0,0x1a,0xd6,0x00,0x04,0x23,0xdc,0x23,0xe2,0x23,0xe8,0x23,0x9a,0x23,0xee,0x23,0xa6,0x1a,0xbe,0x1a,0xc4,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77, 0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38, 0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x02,0x00,0x03,0x09,0x71,0x09,0x71,0x00,0x00,0x0a,0x63,0x0a,0x64,0x00,0x01,0x14,0x97,0x14,0x98,0x00,0x03,0x00,0x01,0x02,0x20,0x02,0xd2,0x00,0x01,0x00,0x0c,0x01,0x6e, 0x00,0x58,0x00,0x00,0x17,0x26,0x00,0x00,0x17,0x2c,0x00,0x00,0x17,0x38,0x00,0x00,0x17,0x3e,0x00,0x00,0x17,0x44,0x00,0x00,0x17,0x44,0x00,0x00,0x17,0x4a,0x00,0x00,0x17,0x26,0x00,0x00,0x17,0x50,0x00,0x00,0x17,0x56,0x00,0x00,0x17,0x62,0x00,0x00,0x17,0x50,0x00,0x00,0x17,0x56,0x00,0x00,0x17,0x6e,0x00,0x00,0x17,0x74,0x00,0x00, 0x17,0x7a,0x00,0x00,0x17,0x80,0x00,0x00,0x17,0x86,0x00,0x00,0x17,0x8c,0x00,0x00,0x17,0x92,0x00,0x00,0x17,0x8c,0x00,0x00,0x17,0x9e,0x00,0x00,0x17,0x8c,0x00,0x00,0x17,0xaa,0x00,0x00,0x17,0xb6,0x00,0x00,0x17,0xbc,0x00,0x00,0x17,0xc2,0x00,0x00,0x17,0xc8,0x00,0x00,0x17,0xce,0x00,0x00,0x17,0x3e,0x00,0x00,0x17,0x8c,0x00,0x00, 0x17,0xda,0x00,0x00,0x17,0xe0,0x00,0x00,0x17,0xe6,0x00,0x00,0x17,0xec,0x00,0x00,0x17,0xe0,0x00,0x00,0x17,0xec,0x00,0x00,0x17,0x26,0x00,0x00,0x17,0x26,0x00,0x00,0x17,0x26,0x00,0x00,0x17,0xf8,0x00,0x00,0x17,0xfe,0x00,0x00,0x18,0x04,0x00,0x00,0x18,0x0a,0x00,0x00,0x17,0x26,0x00,0x00,0x18,0x10,0x00,0x00,0x17,0xe0,0x00,0x00, 0x18,0x16,0x00,0x00,0x17,0xe0,0x00,0x00,0x17,0xe0,0x00,0x00,0x18,0x1c,0x00,0x00,0x18,0x22,0x00,0x00,0x18,0x1c,0x00,0x00,0x18,0x22,0x00,0x00,0x18,0x22,0x00,0x00,0x18,0x2e,0x00,0x00,0x18,0x2e,0x00,0x00,0x18,0x3a,0x00,0x00,0x18,0x40,0x00,0x00,0x18,0x4c,0x00,0x00,0x18,0x52,0x00,0x00,0x18,0x58,0x00,0x00,0x18,0x70,0x00,0x00, 0x18,0x76,0x00,0x00,0x18,0x82,0x00,0x00,0x18,0x58,0x00,0x00,0x18,0x58,0x00,0x00,0x18,0x4c,0x00,0x00,0x18,0x8e,0x00,0x00,0x18,0x3a,0x00,0x00,0x18,0x9a,0x00,0x00,0x18,0xa0,0x00,0x00,0x18,0x70,0x00,0x00,0x18,0xa6,0x00,0x00,0x18,0xac,0x00,0x00,0x18,0xb2,0x00,0x00,0x18,0xb8,0x00,0x00,0x18,0xbe,0x00,0x00,0x18,0xc4,0x00,0x00, 0x18,0xca,0x00,0x00,0x18,0xd6,0x00,0x00,0x18,0xdc,0x00,0x00,0x18,0xe2,0x00,0x00,0x18,0xe8,0x00,0x00,0x18,0xee,0x00,0x00,0x18,0xf4,0x00,0x00,0x18,0xfa,0x00,0x00,0x19,0x00,0x00,0x58,0x21,0xe8,0x21,0xee,0x21,0xf4,0x21,0xfa,0x21,0xe8,0x22,0x00,0x22,0x06,0x22,0x0c,0x22,0x12,0x22,0x18,0x22,0x1e,0x22,0x24,0x22,0x2a,0x22,0x30, 0x22,0x36,0x22,0x3c,0x22,0x42,0x22,0x36,0x22,0x48,0x22,0x4e,0x22,0x06,0x22,0x54,0x22,0x5a,0x22,0x0c,0x22,0x60,0x22,0x66,0x22,0x6c,0x22,0x72,0x22,0x78,0x22,0x7e,0x22,0x84,0x22,0x8a,0x22,0x90,0x22,0x96,0x22,0x90,0x22,0x84,0x22,0x9c,0x22,0xa2,0x22,0x42,0x22,0x42,0x22,0xa8,0x22,0xae,0x22,0xb4,0x22,0xba,0x22,0xc0,0x22,0xc6, 0x22,0x9c,0x22,0xcc,0x22,0xcc,0x22,0x84,0x22,0xd2,0x22,0xd8,0x22,0xde,0x22,0xe4,0x22,0xea,0x22,0xf0,0x22,0xf6,0x22,0xfc,0x23,0x02,0x23,0x08,0x23,0x0e,0x23,0x14,0x23,0x1a,0x23,0x20,0x23,0x26,0x23,0x2c,0x23,0x32,0x23,0x38,0x23,0x3e,0x23,0x44,0x23,0x4a,0x23,0x50,0x23,0x56,0x23,0x5c,0x22,0xe4,0x23,0x62,0x23,0x68,0x23,0x6e, 0x23,0x74,0x23,0x7a,0x23,0x80,0x23,0x86,0x23,0x8c,0x23,0x92,0x23,0x98,0x23,0x9e,0x23,0xa4,0x23,0xaa,0x00,0x02,0x00,0x1d,0x09,0x2c,0x09,0x2d,0x00,0x00,0x09,0x2f,0x09,0x30,0x00,0x02,0x09,0x32,0x09,0x33,0x00,0x04,0x09,0x37,0x09,0x37,0x00,0x06,0x09,0x73,0x09,0x75,0x00,0x07,0x09,0x7e,0x09,0x7e,0x00,0x0a,0x0a,0x0f,0x0a,0x13, 0x00,0x0b,0x0a,0x16,0x0a,0x19,0x00,0x10,0x0a,0x1b,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x15,0x0a,0x22,0x0a,0x22,0x00,0x17,0x0a,0x4b,0x0a,0x4f,0x00,0x18,0x0a,0x51,0x0a,0x53,0x00,0x1d,0x0a,0x65,0x0a,0x69,0x00,0x20,0x0a,0x6c,0x0a,0x6e,0x00,0x25,0x0a,0x70,0x0a,0x71,0x00,0x28,0x0e,0x1a,0x0e,0x1d,0x00,0x2a,0x0e,0x62, 0x0e,0x6a,0x00,0x2e,0x13,0x2a,0x13,0x2b,0x00,0x37,0x13,0x2d,0x13,0x2e,0x00,0x39,0x13,0x30,0x13,0x32,0x00,0x3b,0x13,0x36,0x13,0x37,0x00,0x3e,0x13,0x39,0x13,0x3b,0x00,0x40,0x13,0x3d,0x13,0x3e,0x00,0x43,0x13,0x41,0x13,0x44,0x00,0x45,0x13,0xe9,0x13,0xe9,0x00,0x49,0x14,0x17,0x14,0x17,0x00,0x4a,0x14,0x5d,0x14,0x61,0x00,0x4b, 0x14,0x63,0x14,0x6a,0x00,0x50,0x00,0x02,0x00,0x1d,0x09,0x2c,0x09,0x2d,0x00,0x00,0x09,0x2f,0x09,0x30,0x00,0x02,0x09,0x32,0x09,0x33,0x00,0x04,0x09,0x37,0x09,0x37,0x00,0x06,0x09,0x73,0x09,0x75,0x00,0x07,0x09,0x7e,0x09,0x7e,0x00,0x0a,0x0a,0x0f,0x0a,0x13,0x00,0x0b,0x0a,0x16,0x0a,0x19,0x00,0x10,0x0a,0x1b,0x0a,0x1b,0x00,0x14, 0x0a,0x1e,0x0a,0x1f,0x00,0x15,0x0a,0x22,0x0a,0x22,0x00,0x17,0x0a,0x4b,0x0a,0x4f,0x00,0x18,0x0a,0x51,0x0a,0x53,0x00,0x1d,0x0a,0x65,0x0a,0x69,0x00,0x20,0x0a,0x6c,0x0a,0x6e,0x00,0x25,0x0a,0x70,0x0a,0x71,0x00,0x28,0x0e,0x1a,0x0e,0x1d,0x00,0x2a,0x0e,0x62,0x0e,0x6a,0x00,0x2e,0x13,0x2a,0x13,0x2b,0x00,0x37,0x13,0x2d,0x13,0x2e, 0x00,0x39,0x13,0x30,0x13,0x32,0x00,0x3b,0x13,0x36,0x13,0x37,0x00,0x3e,0x13,0x39,0x13,0x3b,0x00,0x40,0x13,0x3d,0x13,0x3e,0x00,0x43,0x13,0x41,0x13,0x44,0x00,0x45,0x13,0xe9,0x13,0xe9,0x00,0x49,0x14,0x17,0x14,0x17,0x00,0x4a,0x14,0x5d,0x14,0x61,0x00,0x4b,0x14,0x63,0x14,0x6a,0x00,0x50,0x00,0x01,0x00,0x9a,0x01,0x10,0x00,0x01, 0x00,0x0c,0x00,0x6a,0x00,0x17,0x00,0x00,0x13,0xae,0x00,0x00,0x13,0xae,0x00,0x00,0x13,0xd8,0x00,0x00,0x13,0xe4,0x00,0x00,0x14,0x14,0x00,0x00,0x14,0x20,0x00,0x00,0x14,0x2c,0x00,0x00,0x14,0x50,0x00,0x00,0x14,0x6e,0x00,0x00,0x13,0xae,0x00,0x00,0x14,0xa4,0x00,0x00,0x14,0xa4,0x00,0x00,0x14,0xb0,0x00,0x00,0x14,0xc2,0x00,0x00, 0x14,0xda,0x00,0x00,0x14,0xe0,0x00,0x00,0x14,0xe6,0x00,0x00,0x14,0xf8,0x00,0x00,0x15,0x04,0x00,0x00,0x15,0x10,0x00,0x00,0x15,0x10,0x00,0x00,0x15,0x4c,0x00,0x00,0x15,0x82,0x00,0x17,0x21,0x30,0x21,0x36,0x21,0x3c,0x21,0x42,0x21,0x48,0x21,0x42,0x21,0x4e,0x21,0x42,0x21,0x54,0x21,0x36,0x21,0x42,0x21,0x5a,0x21,0x60,0x21,0x66, 0x21,0x6c,0x21,0x72,0x21,0x78,0x21,0x7e,0x21,0x84,0x21,0x8a,0x21,0x8a,0x21,0x90,0x21,0x96,0x00,0x02,0x00,0x13,0x09,0x2e,0x09,0x2e,0x00,0x00,0x09,0x31,0x09,0x31,0x00,0x01,0x09,0x77,0x09,0x77,0x00,0x02,0x09,0x7f,0x09,0x7f,0x00,0x03,0x0a,0x1a,0x0a,0x1a,0x00,0x04,0x0a,0x21,0x0a,0x21,0x00,0x05,0x0a,0x23,0x0a,0x23,0x00,0x06, 0x0a,0x50,0x0a,0x50,0x00,0x07,0x0a,0x6f,0x0a,0x6f,0x00,0x08,0x0e,0x1e,0x0e,0x1e,0x00,0x09,0x0e,0x6b,0x0e,0x6c,0x00,0x0a,0x13,0x2c,0x13,0x2c,0x00,0x0c,0x13,0x2f,0x13,0x2f,0x00,0x0d,0x13,0x33,0x13,0x35,0x00,0x0e,0x13,0x38,0x13,0x38,0x00,0x11,0x13,0x3c,0x13,0x3c,0x00,0x12,0x13,0x3f,0x13,0x40,0x00,0x13,0x14,0x62,0x14,0x62, 0x00,0x15,0x14,0x6c,0x14,0x6c,0x00,0x16,0x00,0x02,0x00,0x13,0x09,0x2e,0x09,0x2e,0x00,0x00,0x09,0x31,0x09,0x31,0x00,0x01,0x09,0x77,0x09,0x77,0x00,0x02,0x09,0x7f,0x09,0x7f,0x00,0x03,0x0a,0x1a,0x0a,0x1a,0x00,0x04,0x0a,0x21,0x0a,0x21,0x00,0x05,0x0a,0x23,0x0a,0x23,0x00,0x06,0x0a,0x50,0x0a,0x50,0x00,0x07,0x0a,0x6f,0x0a,0x6f, 0x00,0x08,0x0e,0x1e,0x0e,0x1e,0x00,0x09,0x0e,0x6b,0x0e,0x6c,0x00,0x0a,0x13,0x2c,0x13,0x2c,0x00,0x0c,0x13,0x2f,0x13,0x2f,0x00,0x0d,0x13,0x33,0x13,0x35,0x00,0x0e,0x13,0x38,0x13,0x38,0x00,0x11,0x13,0x3c,0x13,0x3c,0x00,0x12,0x13,0x3f,0x13,0x40,0x00,0x13,0x14,0x62,0x14,0x62,0x00,0x15,0x14,0x6c,0x14,0x6c,0x00,0x16,0x00,0x01, 0x00,0x32,0x00,0x38,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00,0x11,0x0e,0x00,0x0f,0x20,0x6e,0x20,0x74,0x20,0x7a,0x20,0x80,0x20,0x86,0x20,0x8c,0x20,0x92,0x20,0x98,0x20,0x9e,0x20,0xa4,0x20,0xaa,0x20,0xb0,0x20,0x7a,0x20,0xb6,0x20,0xbc,0x00,0x01,0x00,0x01,0x0b,0x5e,0x00,0x02,0x00,0x07,0x0a,0x43,0x0a,0x43,0x00,0x00, 0x0b,0x6f,0x0b,0x6f,0x00,0x01,0x0b,0x75,0x0b,0x75,0x00,0x02,0x0b,0x77,0x0b,0x77,0x00,0x03,0x0b,0x7a,0x0b,0x7a,0x00,0x04,0x0b,0x7d,0x0b,0x7d,0x00,0x05,0x0b,0x8d,0x0b,0x95,0x00,0x06,0x00,0x01,0x02,0xc8,0x02,0xe4,0x00,0x04,0x00,0x0c,0x00,0x46,0x00,0x0e,0x00,0x00,0x10,0xa8,0x00,0x02,0x10,0xa8,0x00,0x02,0x10,0xa8,0x00,0x02, 0x10,0xa8,0x00,0x00,0x10,0xa8,0x00,0x01,0x10,0xa8,0x00,0x01,0x10,0xa8,0x00,0x01,0x10,0xa8,0x00,0x01,0x10,0xa8,0x00,0x02,0x10,0xa8,0x00,0x01,0x10,0xa8,0x00,0x03,0x10,0xa8,0x00,0x03,0x10,0xa8,0x00,0x03,0x10,0xa8,0x00,0x50,0x20,0x28,0x20,0x2e,0x20,0x34,0x20,0x3a,0x20,0x40,0x20,0x46,0x20,0x4c,0x20,0x52,0x20,0x58,0x20,0x5e, 0x20,0x64,0x20,0x6a,0x20,0x70,0x20,0x76,0x20,0x7c,0x20,0x82,0x20,0x88,0x20,0x8e,0x20,0x94,0x20,0x9a,0x20,0xa0,0x20,0xa6,0x20,0xac,0x20,0xb2,0x20,0xb8,0x20,0xbe,0x20,0xc4,0x20,0xca,0x20,0xd0,0x20,0xd6,0x20,0xdc,0x20,0xe2,0x20,0xe8,0x20,0xee,0x20,0xf4,0x20,0xfa,0x21,0x00,0x21,0x06,0x21,0x0c,0x21,0x12,0x20,0xb8,0x20,0xbe, 0x20,0xc4,0x20,0xca,0x21,0x18,0x21,0x1e,0x21,0x24,0x21,0x2a,0x21,0x30,0x21,0x36,0x21,0x3c,0x21,0x42,0x21,0x48,0x21,0x4e,0x21,0x54,0x21,0x5a,0x21,0x60,0x21,0x66,0x21,0x6c,0x21,0x72,0x21,0x60,0x21,0x66,0x21,0x6c,0x21,0x72,0x20,0xc4,0x21,0x78,0x21,0x7e,0x21,0x84,0x21,0x8a,0x21,0x90,0x21,0x42,0x21,0x96,0x21,0x9c,0x21,0xa2, 0x21,0xa8,0x21,0xae,0x21,0xb4,0x21,0xba,0x21,0x72,0x21,0xc0,0x21,0xc6,0x21,0xa8,0x21,0xcc,0x21,0xd2,0x21,0xd8,0x21,0xde,0x21,0xe4,0x21,0xea,0x21,0xf0,0x21,0xf6,0x21,0xfc,0x22,0x02,0x22,0x08,0x22,0x0e,0x21,0xc0,0x20,0x9a,0x22,0x14,0x22,0x1a,0x22,0x20,0x22,0x26,0x22,0x2c,0x22,0x32,0x22,0x38,0x22,0x3e,0x22,0x44,0x22,0x4a, 0x22,0x50,0x22,0x3e,0x22,0x56,0x22,0x5c,0x22,0x62,0x22,0x68,0x22,0x6e,0x22,0x74,0x22,0x7a,0x22,0x80,0x22,0x6e,0x22,0x74,0x22,0x7a,0x22,0x80,0x22,0x6e,0x22,0x74,0x22,0x7a,0x22,0x80,0x21,0x18,0x21,0x1e,0x21,0x24,0x21,0x2a,0x21,0x18,0x21,0x1e,0x21,0x24,0x21,0x2a,0x21,0x48,0x21,0x4e,0x21,0x54,0x21,0x5a,0x21,0x48,0x21,0x4e, 0x21,0x54,0x21,0x5a,0x22,0x86,0x22,0x8c,0x22,0x92,0x22,0x98,0x22,0x9e,0x22,0xa4,0x22,0xaa,0x22,0xb0,0x20,0x40,0x20,0x46,0x20,0x4c,0x20,0x52,0x20,0x88,0x20,0x8e,0x20,0x94,0x20,0x9a,0x20,0xa0,0x20,0xa6,0x20,0xac,0x20,0xb2,0x10,0x68,0x22,0xb6,0x20,0x9a,0x22,0xbc,0x21,0x48,0x21,0x4e,0x21,0x54,0x21,0x5a,0x21,0x60,0x21,0x66, 0x21,0x6c,0x21,0x72,0x22,0x2c,0x22,0x32,0x22,0xc2,0x22,0x3e,0x22,0x56,0x22,0x5c,0x22,0x62,0x22,0x68,0x22,0x44,0x22,0x4a,0x22,0x50,0x22,0x3e,0x22,0x44,0x22,0x4a,0x22,0x50,0x22,0x3e,0x22,0x44,0x22,0x4a,0x22,0x50,0x22,0x3e,0x22,0x44,0x22,0x4a,0x22,0x50,0x22,0x3e,0x20,0x40,0x20,0x46,0x20,0x4c,0x20,0x52,0x20,0x58,0x20,0x5e, 0x20,0x64,0x20,0x6a,0x20,0x70,0x20,0x76,0x20,0x7c,0x20,0x82,0x20,0x88,0x20,0x8e,0x20,0x94,0x20,0x9a,0x20,0xa0,0x20,0xa6,0x20,0xac,0x20,0xb2,0x22,0xc8,0x22,0xce,0x22,0xd4,0x22,0xda,0x22,0xe0,0x22,0xe6,0x22,0xec,0x20,0xdc,0x21,0x00,0x21,0x06,0x21,0x0c,0x21,0x12,0x22,0xc8,0x22,0xce,0x22,0xd4,0x22,0xda,0x21,0x18,0x21,0x1e, 0x21,0x24,0x21,0x2a,0x21,0x30,0x21,0x36,0x21,0x3c,0x21,0x42,0x21,0x48,0x21,0x4e,0x21,0x54,0x21,0x5a,0x21,0x60,0x21,0x66,0x21,0x6c,0x21,0x72,0x21,0x8a,0x21,0x90,0x21,0x42,0x21,0x96,0x21,0x9c,0x21,0xa2,0x21,0xa8,0x21,0xae,0x21,0xc6,0x21,0xa8,0x21,0xcc,0x21,0xd2,0x21,0xd8,0x21,0xde,0x21,0xe4,0x21,0xea,0x22,0x08,0x22,0x0e, 0x21,0xc0,0x20,0x9a,0x22,0x14,0x22,0x1a,0x22,0x20,0x22,0x26,0x22,0x2c,0x22,0x32,0x22,0x38,0x22,0x3e,0x22,0x44,0x22,0x4a,0x22,0x50,0x22,0x3e,0x22,0x56,0x22,0x5c,0x22,0x62,0x22,0x68,0x20,0xb8,0x20,0xbe,0x20,0xc4,0x20,0xca,0x20,0x58,0x20,0x5e,0x20,0x64,0x20,0x6a,0x21,0x30,0x21,0x36,0x21,0x3c,0x21,0x42,0x21,0xd8,0x21,0xde, 0x21,0xe4,0x21,0xea,0x22,0x9e,0x22,0xa4,0x22,0xaa,0x22,0xb0,0x20,0x70,0x20,0x76,0x20,0x7c,0x20,0x82,0x20,0x88,0x20,0x8e,0x20,0x94,0x20,0x9a,0x20,0xa0,0x20,0xa6,0x20,0xac,0x20,0xb2,0x22,0x56,0x22,0x5c,0x22,0x62,0x22,0x68,0x00,0x02,0x00,0x04,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9, 0x00,0x0a,0x12,0x59,0x12,0x5b,0x00,0x0b,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0xb4,0x00,0xba,0x00,0x01,0x00,0x0c,0x00,0x12,0x00,0x01,0x00,0x00, 0x0d,0x9c,0x00,0x50,0x20,0x1a,0x1d,0x5c,0x1f,0xba,0x20,0x20,0x20,0x26,0x20,0x2c,0x20,0x32,0x20,0x38,0x20,0x3e,0x20,0x44,0x20,0x32,0x20,0x4a,0x20,0x50,0x20,0x56,0x20,0x3e,0x20,0x5c,0x20,0x32,0x20,0x62,0x1e,0xd6,0x20,0x68,0x20,0x6e,0x1e,0xd6,0x20,0x74,0x20,0x7a,0x20,0x5c,0x20,0x4a,0x20,0x80,0x20,0x86,0x20,0x32,0x20,0x32, 0x20,0x32,0x20,0x4a,0x20,0x4a,0x20,0x56,0x20,0x56,0x20,0x32,0x20,0x68,0x1d,0x5c,0x20,0x26,0x20,0x2c,0x20,0x50,0x20,0x56,0x20,0x3e,0x20,0x4a,0x20,0x86,0x20,0x80,0x20,0x8c,0x20,0x80,0x20,0x8c,0x1d,0x5c,0x1f,0xba,0x20,0x20,0x20,0x26,0x20,0x2c,0x20,0x92,0x20,0x6e,0x20,0x44,0x20,0x92,0x20,0x4a,0x20,0x50,0x20,0x56,0x20,0x5c, 0x20,0x62,0x1e,0xd6,0x20,0x6e,0x1e,0xd6,0x20,0x7a,0x20,0x5c,0x20,0x4a,0x20,0x80,0x20,0x86,0x20,0x98,0x20,0x9e,0x20,0xa4,0x20,0xaa,0x20,0x56,0x20,0xb0,0x20,0x9e,0x20,0xb6,0x20,0xbc,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f, 0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x04,0xda,0x05,0x14,0x00,0x07,0x00,0x0c,0x00,0x6a,0x00,0x17,0x00,0x01,0x0c,0xba,0x00,0x00,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x06,0x0c,0xba, 0x00,0x01,0x0c,0xba,0x00,0x04,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x03,0x0c,0xba,0x00,0x02,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x00,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x05,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x01,0x0c,0xba,0x00,0x51,0x1f,0x88, 0x1f,0x8e,0x1f,0x94,0x1f,0x8e,0x1f,0x9a,0x1f,0xa0,0x1f,0xa6,0x1f,0xac,0x1f,0xb2,0x1f,0xb8,0x1f,0xb2,0x1f,0xbe,0x1f,0xc4,0x1f,0xc4,0x1f,0xca,0x1f,0xd0,0x1f,0xd6,0x1f,0xd0,0x1f,0xdc,0x1f,0xe2,0x1f,0xe2,0x1f,0xe8,0x1f,0xee,0x1f,0xf4,0x1f,0xee,0x1f,0xfa,0x20,0x00,0x20,0x06,0x20,0x0c,0x1f,0xd0,0x20,0x12,0x1f,0xd0,0x20,0x18, 0x20,0x1e,0x20,0x1e,0x20,0x24,0x20,0x2a,0x20,0x30,0x20,0x2a,0x20,0x36,0x1c,0x7c,0x20,0x3c,0x20,0x42,0x1e,0xf8,0x20,0x48,0x1e,0xf8,0x20,0x4e,0x20,0x54,0x1f,0xe2,0x20,0x5a,0x1e,0x92,0x20,0x60,0x1e,0x92,0x20,0x66,0x20,0x6c,0x20,0x24,0x1d,0x78,0x1b,0xc8,0x20,0x72,0x1b,0xc8,0x20,0x78,0x20,0x7e,0x1d,0xf6,0x1f,0x28,0x20,0x84, 0x20,0x8a,0x20,0x84,0x20,0x90,0x20,0x96,0x20,0x7e,0x20,0x42,0x1e,0xf8,0x20,0x9c,0x1e,0xf8,0x20,0x4e,0x20,0x54,0x1f,0xe2,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x1e,0xec,0x1d,0x90,0x20,0xba,0x1d,0x90,0x20,0xc0,0x20,0xc6,0x20,0xc6,0x20,0xcc,0x20,0xd2,0x20,0xd8,0x20,0xde,0x20,0xe4,0x20,0xea, 0x20,0xf0,0x20,0xf6,0x20,0xfc,0x21,0x02,0x20,0xfc,0x21,0x08,0x20,0x7e,0x1d,0xf6,0x1f,0x88,0x21,0x0e,0x21,0x14,0x21,0x0e,0x21,0x1a,0x1c,0x7c,0x21,0x20,0x20,0x42,0x1e,0xf8,0x20,0x9c,0x1e,0xf8,0x20,0x4e,0x20,0x54,0x1f,0xe2,0x21,0x26,0x21,0x2c,0x21,0x32,0x21,0x2c,0x21,0x38,0x21,0x3e,0x21,0x44,0x21,0x4a,0x21,0x50,0x21,0x56, 0x21,0x50,0x21,0x5c,0x1d,0x1e,0x21,0x62,0x21,0x68,0x21,0x6e,0x21,0x74,0x21,0x6e,0x21,0x7a,0x21,0x80,0x21,0x86,0x21,0x8c,0x1c,0x76,0x21,0x92,0x1c,0x76,0x21,0x98,0x1e,0x7a,0x21,0x9e,0x21,0x4a,0x21,0xa4,0x21,0xaa,0x21,0xa4,0x21,0xb0,0x1d,0x1e,0x21,0x62,0x21,0xb6,0x21,0xbc,0x21,0xc2,0x21,0xbc,0x21,0xc8,0x1e,0xf2,0x20,0x06, 0x21,0xce,0x21,0xd4,0x21,0xda,0x21,0xd4,0x21,0xe0,0x21,0xe6,0x21,0xec,0x21,0xf2,0x21,0xf8,0x21,0xfe,0x21,0xf8,0x22,0x04,0x1c,0x7c,0x20,0x3c,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x1f,0x34,0x22,0x0a,0x22,0x10,0x22,0x0a,0x22,0x16,0x22,0x1c,0x21,0xe6,0x1f,0x0a,0x22,0x22,0x22,0x28,0x22,0x22, 0x22,0x2e,0x21,0x20,0x1c,0x7c,0x20,0x42,0x22,0x34,0x22,0x3a,0x22,0x34,0x22,0x40,0x20,0x7e,0x1d,0xf6,0x20,0x42,0x22,0x34,0x22,0x3a,0x22,0x34,0x22,0x40,0x20,0x7e,0x1d,0xf6,0x20,0x42,0x22,0x34,0x22,0x3a,0x22,0x34,0x22,0x40,0x20,0x7e,0x1d,0xf6,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x1e,0xbc, 0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x22,0x46,0x20,0xd2,0x20,0xd8,0x20,0xde,0x20,0xe4,0x22,0x4c,0x22,0x52,0x22,0x46,0x20,0xd2,0x20,0xd8,0x20,0xde,0x20,0xe4,0x22,0x4c,0x22,0x52,0x20,0x42,0x22,0x58,0x22,0x5e,0x22,0x58,0x22,0x64,0x20,0x7e,0x1d,0xf6,0x21,0x68,0x21,0x6e,0x21,0x74,0x21,0x6e,0x21,0x7a, 0x21,0x80,0x21,0x86,0x1f,0xac,0x1f,0xb2,0x1f,0xb8,0x1f,0xb2,0x1f,0xbe,0x1f,0xc4,0x1f,0xc4,0x20,0x0c,0x1f,0xd0,0x20,0x12,0x1f,0xd0,0x20,0x18,0x20,0x1e,0x20,0x1e,0x20,0x24,0x20,0x2a,0x20,0x30,0x20,0x2a,0x20,0x36,0x1c,0x7c,0x20,0x3c,0x1e,0xec,0x1d,0x90,0x20,0xba,0x1d,0x90,0x20,0xc0,0x20,0xc6,0x20,0xc6,0x20,0xcc,0x20,0xd2, 0x20,0xd8,0x20,0xde,0x20,0xe4,0x20,0xea,0x20,0xf0,0x20,0xf6,0x20,0xfc,0x21,0x02,0x20,0xfc,0x21,0x08,0x20,0x7e,0x1d,0xf6,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x1f,0x0a,0x22,0x22,0x22,0x28,0x22,0x22,0x22,0x2e,0x21,0x20,0x1c,0x7c,0x1f,0x34,0x22,0x0a,0x22,0x6a,0x22,0x70,0x22,0x76,0x22,0x1c, 0x21,0xe6,0x22,0x7c,0x22,0x0a,0x22,0x10,0x22,0x82,0x22,0x16,0x22,0x88,0x22,0x8e,0x1f,0x34,0x22,0x0a,0x22,0x6a,0x22,0x70,0x22,0x76,0x22,0x1c,0x21,0xe6,0x22,0x7c,0x22,0x0a,0x22,0x10,0x22,0x82,0x22,0x16,0x22,0x88,0x22,0x8e,0x22,0x94,0x1f,0xb2,0x1f,0xb8,0x1f,0xb2,0x1f,0xbe,0x22,0x9a,0x22,0x9a,0x1f,0xca,0x1f,0xd0,0x1f,0xd6, 0x1f,0xd0,0x1f,0xdc,0x22,0xa0,0x1f,0xe2,0x1f,0xe8,0x1f,0xee,0x1f,0xf4,0x1f,0xee,0x1f,0xfa,0x20,0x00,0x20,0x06,0x20,0x0c,0x1f,0xd0,0x20,0x12,0x1f,0xd0,0x20,0x18,0x20,0x1e,0x20,0x1e,0x20,0x24,0x20,0x2a,0x20,0x30,0x20,0x2a,0x20,0x36,0x1c,0x7c,0x20,0x3c,0x1e,0xe6,0x1f,0x58,0x22,0xa6,0x1f,0x58,0x22,0xac,0x22,0xb2,0x22,0xb8, 0x22,0xbe,0x22,0xc4,0x21,0x32,0x22,0xc4,0x1c,0x16,0x1d,0x5a,0x21,0x44,0x1f,0x28,0x20,0x84,0x20,0x8a,0x20,0x84,0x20,0x90,0x20,0x96,0x20,0x7e,0x1e,0xe6,0x1f,0x58,0x22,0xa6,0x1f,0x58,0x22,0xac,0x22,0xb2,0x22,0xb8,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae,0x20,0xb4,0x20,0xb4,0x1e,0xec,0x1d,0x90,0x20,0xba,0x1d,0x90, 0x20,0xc0,0x20,0xc6,0x20,0xc6,0x20,0xcc,0x20,0xd2,0x20,0xd8,0x20,0xde,0x20,0xe4,0x20,0xea,0x20,0xf0,0x1f,0x88,0x21,0x0e,0x21,0x14,0x21,0x0e,0x21,0x1a,0x1c,0x7c,0x21,0x20,0x21,0x26,0x21,0x2c,0x21,0x32,0x21,0x2c,0x21,0x38,0x21,0x3e,0x21,0x44,0x21,0x4a,0x21,0x50,0x21,0x56,0x21,0x50,0x21,0x5c,0x1d,0x1e,0x21,0x62,0x21,0x8c, 0x1c,0x76,0x21,0x92,0x1c,0x76,0x21,0x98,0x1e,0x7a,0x21,0x9e,0x21,0x4a,0x21,0xa4,0x21,0xaa,0x21,0xa4,0x21,0xb0,0x1d,0x1e,0x21,0x62,0x21,0xce,0x21,0xd4,0x21,0xda,0x21,0xd4,0x21,0xe0,0x21,0xe6,0x21,0xec,0x21,0xf2,0x21,0xf8,0x21,0xfe,0x21,0xf8,0x22,0x04,0x1c,0x7c,0x20,0x3c,0x1e,0xbc,0x20,0xa2,0x20,0xa8,0x20,0xa2,0x20,0xae, 0x20,0xb4,0x20,0xb4,0x1f,0x34,0x22,0x0a,0x22,0x10,0x22,0x0a,0x22,0x16,0x22,0x1c,0x21,0xe6,0x1f,0x0a,0x22,0x22,0x22,0x28,0x22,0x22,0x22,0x2e,0x21,0x20,0x1c,0x7c,0x22,0xca,0x20,0xea,0x22,0xd0,0x22,0xd6,0x22,0xdc,0x22,0xe2,0x22,0xe8,0x22,0xee,0x22,0xf4,0x22,0xfa,0x22,0xf4,0x23,0x00,0x23,0x06,0x1e,0x98,0x23,0x0c,0x23,0x12, 0x23,0x18,0x23,0x12,0x23,0x1e,0x23,0x24,0x23,0x2a,0x23,0x30,0x23,0x36,0x23,0x3c,0x23,0x36,0x21,0xb0,0x22,0xbe,0x23,0x42,0x20,0xcc,0x23,0x48,0x23,0x4e,0x23,0x54,0x23,0x5a,0x20,0xea,0x20,0xf0,0x23,0x60,0x23,0x66,0x1b,0xc8,0x23,0x66,0x23,0x6c,0x23,0x72,0x1c,0x34,0x23,0x78,0x23,0x7e,0x23,0x84,0x23,0x7e,0x23,0x8a,0x23,0x90, 0x23,0x96,0x22,0xee,0x22,0xf4,0x22,0xfa,0x22,0xf4,0x23,0x00,0x23,0x06,0x1e,0x98,0x23,0x9c,0x23,0xa2,0x23,0xa8,0x23,0xa2,0x20,0x36,0x23,0xae,0x23,0xb4,0x1e,0xec,0x23,0xba,0x23,0xc0,0x23,0xba,0x22,0x2e,0x20,0xc6,0x1c,0x7c,0x00,0x02,0x00,0x09,0x0b,0x61,0x0b,0x61,0x00,0x00,0x0b,0xc0,0x0b,0xc3,0x00,0x01,0x0b,0xc5,0x0b,0xc7, 0x00,0x05,0x0b,0xca,0x0b,0xcf,0x00,0x08,0x0b,0xd6,0x0b,0xd7,0x00,0x0e,0x0b,0xd9,0x0b,0xda,0x00,0x10,0x0b,0xdc,0x0b,0xdd,0x00,0x12,0x0b,0xe1,0x0b,0xe1,0x00,0x14,0x12,0x5c,0x12,0x5d,0x00,0x15,0x00,0x02,0x00,0x07,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a, 0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x0b,0xdf,0x0b,0xdf,0x00,0x4c,0x12,0x5f,0x12,0x62,0x00,0x4d,0x00,0x01,0x01,0x88,0x01,0xbc,0x00,0x02,0x00,0x0c,0x00,0x46,0x00,0x0e,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00, 0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x00,0x07,0x78,0x00,0x50,0x1a,0x70,0x1a,0x7c,0x1e,0xa8,0x1e,0xae,0x1e,0xb4,0x1e,0xba,0x1e,0xc0,0x1e,0xc6,0x1d,0x88,0x1e,0xcc,0x1e,0xd2,0x1b,0x8a,0x19,0xda,0x1b,0x30,0x1c,0x1a,0x1e,0xd8,0x16,0xaa,0x1e,0xde, 0x1e,0xe4,0x1e,0xea,0x19,0xda,0x1b,0x30,0x1e,0xf0,0x1e,0xf6,0x18,0xea,0x1c,0xaa,0x1e,0xfc,0x1f,0x02,0x1b,0xf0,0x1f,0x08,0x1b,0xf0,0x1f,0x0e,0x1f,0x14,0x1f,0x1a,0x1c,0x0e,0x17,0x5e,0x1c,0x32,0x1f,0x20,0x1f,0x26,0x1f,0x2c,0x1f,0x32,0x1f,0x38,0x1f,0x3e,0x1f,0x44,0x1f,0x4a,0x1c,0x50,0x1f,0x50,0x1f,0x56,0x1c,0xda,0x1f,0x5c, 0x1f,0x62,0x1f,0x02,0x1f,0x68,0x1f,0x6e,0x1f,0x74,0x1f,0x7a,0x1d,0x16,0x1f,0x80,0x1d,0x16,0x1f,0x80,0x1d,0x16,0x1f,0x80,0x1e,0xf0,0x1e,0xf6,0x1e,0xf0,0x1e,0xf6,0x1e,0xfc,0x1f,0x02,0x1e,0xfc,0x1f,0x02,0x1d,0x3a,0x1f,0x86,0x1f,0x8c,0x1f,0x2c,0x1e,0xa8,0x1e,0xae,0x1d,0x88,0x1e,0xcc,0x1e,0xd2,0x1f,0x92,0x1f,0x98,0x1c,0xaa, 0x1e,0xfc,0x1f,0x02,0x1b,0xf0,0x1f,0x9e,0x1f,0x62,0x1f,0x02,0x1f,0x74,0x1f,0x7a,0x1f,0x68,0x1f,0x6e,0x1f,0x68,0x1f,0x6e,0x1f,0x68,0x1f,0x6e,0x1f,0x68,0x1f,0x6e,0x1e,0xa8,0x1e,0xae,0x1e,0xb4,0x1e,0xba,0x1e,0xc0,0x1e,0xc6,0x1d,0x88,0x1e,0xcc,0x1e,0xd2,0x1b,0x8a,0x1a,0x3a,0x1d,0x8e,0x18,0xf0,0x17,0x5e,0x1e,0xe4,0x1e,0xea, 0x1a,0x3a,0x1d,0x8e,0x1e,0xf0,0x1e,0xf6,0x18,0xea,0x1c,0xaa,0x1e,0xfc,0x1f,0x02,0x1b,0xf0,0x1f,0x0e,0x1c,0x0e,0x17,0x5e,0x1c,0x32,0x1f,0x20,0x1f,0x32,0x1f,0x38,0x1f,0x3e,0x1f,0x44,0x1f,0x50,0x1f,0x56,0x1c,0xda,0x1f,0x5c,0x1f,0x62,0x1f,0x02,0x1f,0x68,0x1f,0x6e,0x1f,0x74,0x1f,0x7a,0x19,0xda,0x1b,0x30,0x1e,0xb4,0x1e,0xba, 0x18,0xea,0x1c,0xaa,0x1f,0x3e,0x1f,0x44,0x1f,0x8c,0x1f,0xa4,0x1e,0xc0,0x1e,0xc6,0x1d,0x88,0x1e,0xcc,0x1e,0xd2,0x1b,0x8a,0x1f,0x74,0x1f,0x7a,0x00,0x02,0x00,0x08,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc8,0x0b,0xc9,0x00,0x04,0x0b,0xd0, 0x0b,0xd5,0x00,0x06,0x0b,0xd8,0x0b,0xd8,0x00,0x0c,0x0b,0xdb,0x0b,0xdb,0x00,0x0d,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62,0x00,0x4c,0x00,0x01,0x00,0x40,0x00,0x56,0x00,0x01, 0x00,0x0c,0x00,0x3a,0x00,0x0b,0x00,0x00,0x05,0x94,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x05,0x94,0x00,0x00,0x18,0x2a,0x00,0x00,0x18,0x2a,0x00,0x00,0x1e,0x06,0x00,0x00,0x1e,0x06,0x00,0x00,0x17,0x46,0x00,0x00,0x1e,0x06,0x00,0x02,0x1d,0xde,0x16,0x70,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b, 0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x00,0x01,0x00,0x02,0x0b,0x5f,0x0b,0x67,0x00,0x01,0x00,0xb4,0x00,0xe8,0x00,0x04,0x00,0x0c,0x00,0x42,0x00,0x0d,0x00,0x00,0x05,0x36,0x00,0x00,0x05,0x36,0x00,0x01,0x05,0x36,0x00,0x01,0x05,0x36,0x00,0x03,0x05,0x36,0x00,0x01,0x05,0x36,0x00,0x01,0x05,0x36, 0x00,0x01,0x1d,0xb4,0x00,0x01,0x05,0x36,0x00,0x02,0x05,0x36,0x00,0x01,0x1d,0xba,0x00,0x01,0x05,0x36,0x00,0x03,0x1d,0xc0,0x00,0x0e,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x17,0xa2,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x15,0xf2,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x1d,0xa2,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x1d,0xa8,0x1d,0x90,0x1d,0x96,0x1d,0x9c, 0x17,0xa2,0x1d,0x90,0x1d,0xae,0x1d,0x9c,0x1d,0xb4,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x1d,0xb4,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x19,0x22,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x19,0x22,0x1d,0x90,0x1d,0xae,0x1d,0x9c,0x1d,0xba,0x1d,0x90,0x1d,0x96,0x1d,0x9c,0x19,0x22,0x1d,0xc0,0x1d,0xae,0x1d,0xc6,0x1d,0x06,0x1d,0xc0,0x1d,0xcc,0x1d,0xc6, 0x1a,0x84,0x1d,0xc0,0x1d,0xcc,0x1d,0xc6,0x1a,0x84,0x00,0x02,0x00,0x08,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc8,0x0b,0xc9,0x00,0x04,0x0b,0xd1,0x0b,0xd5,0x00,0x06,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x0b,0xdb,0x0b,0xdb,0x00,0x0c,0x00,0x02, 0x00,0x04,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x12,0x59,0x12,0x5b,0x00,0x0b,0x00,0x01,0x00,0x78,0x00,0x8e,0x00,0x02,0x00,0x0c,0x00,0x1e,0x00,0x04,0x00,0x00,0x04,0x32,0x00,0x00,0x04,0x32,0x00,0x01,0x04,0x32,0x00,0x01,0x04,0x32,0x00,0x16,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2, 0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0xf2,0x1c,0xf8,0x1c,0x98,0x1c,0xfe,0x1c,0xf2,0x1c,0xf8,0x1d,0x04,0x1d,0x0a,0x1d,0x04,0x1d,0x10,0x1d,0x16,0x1d,0x10,0x1d,0x1c,0x1d,0x22,0x1d,0x28,0x1d,0x2e,0x1d,0x28, 0x1d,0x34,0x1d,0x3a,0x1c,0xfe,0x1d,0x40,0x1d,0x46,0x1d,0x4c,0x1d,0x52,0x1d,0x04,0x1d,0x22,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x53,0x00,0x00,0x0b,0x57,0x0b,0x58,0x00,0x01,0x0b,0x5a,0x0b,0x5a,0x00,0x03,0x00,0x02,0x00,0x09,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0x67,0x0b,0x67,0x00,0x0a,0x0b,0xb9, 0x0b,0xb9,0x00,0x0b,0x0b,0xbf,0x0b,0xbf,0x00,0x0c,0x0b,0xc4,0x0b,0xc4,0x00,0x0d,0x0b,0xc9,0x0b,0xc9,0x00,0x0e,0x0b,0xd0,0x0b,0xd5,0x00,0x0f,0x0b,0xd8,0x0b,0xd8,0x00,0x15,0x00,0x01,0x00,0x70,0x00,0x9e,0x00,0x02,0x00,0x0c,0x00,0x3e,0x00,0x0c,0x00,0x00,0x1b,0xe8,0x00,0x00,0x03,0x6a,0x00,0x00,0x16,0xf6,0x00,0x00,0x1c,0xa2, 0x00,0x00,0x1c,0xa2,0x00,0x00,0x1c,0xa2,0x00,0x00,0x1c,0xa8,0x00,0x00,0x1c,0xa8,0x00,0x00,0x1c,0xa2,0x00,0x01,0x03,0x6a,0x00,0x00,0x1c,0xae,0x00,0x00,0x1c,0xa2,0x00,0x0c,0x1c,0x82,0x1c,0x52,0x1c,0x88,0x1c,0x2e,0x1c,0x8e,0x1c,0x94,0x1c,0x8e,0x1c,0x10,0x1c,0x8e,0x1c,0x10,0x1c,0x8e,0x1c,0x9a,0x14,0x42,0x1c,0xa0,0x1c,0xa6, 0x1c,0xac,0x1c,0x8e,0x1c,0xa0,0x1c,0xb2,0x1c,0xb8,0x14,0x42,0x1c,0xbe,0x1c,0x8e,0x1c,0x9a,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b, 0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x7c,0x00,0xb6,0x00,0x01,0x00,0x0c,0x00,0x56,0x00,0x12,0x00,0x00,0x1b,0x1c, 0x00,0x00,0x1a,0x74,0x00,0x00,0x02,0x9e,0x00,0x00,0x1c,0x2a,0x00,0x00,0x17,0xf8,0x00,0x00,0x1c,0x2a,0x00,0x00,0x16,0x2a,0x00,0x00,0x1c,0x30,0x00,0x00,0x1b,0xe2,0x00,0x00,0x15,0xac,0x00,0x00,0x02,0x9e,0x00,0x00,0x02,0x9e,0x00,0x00,0x1c,0x2a,0x00,0x00,0x02,0x9e,0x00,0x00,0x1b,0xe2,0x00,0x00,0x1c,0x36,0x00,0x00,0x1b,0x1c, 0x00,0x00,0x1c,0x36,0x00,0x12,0x1b,0x6e,0x1b,0x80,0x1b,0xf2,0x1b,0x38,0x1b,0xf8,0x1b,0xc8,0x1b,0xfe,0x1c,0x04,0x1c,0x0a,0x1c,0x0a,0x1c,0x0a,0x1c,0x10,0x1b,0x6e,0x1b,0x4a,0x1b,0xc8,0x1b,0xfe,0x1b,0x80,0x1b,0xd4,0x00,0x02,0x00,0x09,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05, 0x0b,0xcc,0x0b,0xcf,0x00,0x06,0x0b,0xd6,0x0b,0xd7,0x00,0x0a,0x0b,0xd9,0x0b,0xda,0x00,0x0c,0x0b,0xdd,0x0b,0xdd,0x00,0x0e,0x0b,0xe1,0x0b,0xe1,0x00,0x0f,0x12,0x5c,0x12,0x5d,0x00,0x10,0x00,0x02,0x00,0x09,0x0b,0xc1,0x0b,0xc3,0x00,0x00,0x0b,0xc5,0x0b,0xc6,0x00,0x03,0x0b,0xca,0x0b,0xca,0x00,0x05,0x0b,0xcc,0x0b,0xcf,0x00,0x06, 0x0b,0xd6,0x0b,0xd7,0x00,0x0a,0x0b,0xd9,0x0b,0xda,0x00,0x0c,0x0b,0xdd,0x0b,0xdd,0x00,0x0e,0x0b,0xe1,0x0b,0xe1,0x00,0x0f,0x12,0x5c,0x12,0x5d,0x00,0x10,0x00,0x01,0x00,0x1a,0x00,0x22,0x00,0x01,0x00,0x0c,0x00,0x16,0x00,0x02,0x00,0x00,0x01,0xae,0x00,0x00,0x01,0xae,0x00,0x01,0x1b,0x66,0x00,0x01,0x00,0x02,0x0b,0x63,0x0b,0x64, 0x00,0x01,0x00,0x01,0x0a,0x43,0x00,0x01,0x01,0x04,0x04,0xb0,0x00,0x01,0x01,0x13,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0xb0,0x00,0x01,0x00,0x00,0x05,0x64,0x00,0x01,0xff,0xce,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x88,0x00,0x01,0x00,0x46,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x60,0x00,0x01,0x00,0x00,0x03,0xde,0x00,0x01,0x00,0x00, 0x03,0xe8,0x00,0x01,0x00,0x00,0x04,0x7e,0x00,0x01,0x00,0x00,0x04,0xec,0x00,0x01,0x00,0x00,0xff,0xec,0x00,0x01,0x00,0x1e,0x04,0xb0,0x00,0x01,0x01,0x93,0x04,0xb0,0x00,0x01,0x01,0xa6,0x04,0xb0,0x00,0x01,0x01,0xa8,0x04,0xb0,0x00,0x01,0x00,0x00,0x04,0x6f,0x00,0x01,0x00,0x00,0x04,0xa6,0x00,0x01,0x00,0x0f,0x04,0x7e,0x00,0x01, 0xff,0xf1,0x04,0x7e,0x00,0x01,0x00,0x00,0x04,0xc4,0x00,0x01,0x01,0xd9,0x04,0xba,0x00,0x01,0x01,0xd9,0x03,0xca,0x00,0x01,0x02,0x07,0x04,0x74,0x00,0x01,0x01,0x53,0x04,0x06,0x00,0x01,0x01,0x18,0x06,0x77,0x00,0x01,0x00,0xe1,0x06,0x08,0x00,0x01,0x01,0x0e,0x06,0x08,0x00,0x01,0x00,0x00,0x06,0x5e,0x00,0x01,0x00,0x00,0x05,0xdc, 0x00,0x01,0x00,0x00,0x05,0x7f,0x00,0x01,0x00,0x00,0x06,0x3c,0x00,0x01,0x00,0x00,0x06,0x0e,0x00,0x01,0x00,0x00,0x05,0xd5,0x00,0x01,0x00,0x00,0x05,0xd7,0x00,0x01,0x00,0x00,0x06,0x6c,0x00,0x01,0x00,0x00,0x06,0x50,0x00,0x01,0x00,0x00,0x06,0x5c,0x00,0x01,0x00,0x00,0x06,0xb8,0x00,0x01,0x00,0x00,0x06,0x73,0x00,0x01,0x00,0x00, 0x05,0xf0,0x00,0x01,0x00,0x00,0x06,0xb5,0x00,0x01,0x00,0x00,0x07,0x6c,0x00,0x01,0x00,0x00,0x07,0x54,0x00,0x01,0x00,0x00,0x01,0x4d,0x00,0x01,0x00,0x00,0x06,0x3a,0x00,0x01,0x00,0x00,0x06,0x40,0x00,0x01,0x00,0x00,0x06,0xc4,0x00,0x01,0x00,0x00,0x07,0xb2,0x00,0x01,0x00,0x00,0x06,0xf0,0x00,0x01,0x01,0x93,0x06,0x22,0x00,0x01, 0x01,0xa6,0x06,0x18,0x00,0x01,0x01,0xa8,0x06,0x4a,0x00,0x01,0x00,0x00,0x06,0xfe,0x00,0x01,0x00,0x00,0x07,0xda,0x00,0x01,0x00,0x00,0x07,0xe4,0x00,0x01,0x00,0x00,0x07,0x80,0x00,0x01,0x00,0x00,0x06,0xa8,0x00,0x01,0x00,0x00,0x06,0x54,0x00,0x01,0x00,0x00,0x06,0xc2,0x00,0x01,0x00,0x00,0x06,0x27,0x00,0x01,0x01,0xd9,0x06,0x5a, 0x00,0x01,0x01,0xd9,0x05,0x80,0x00,0x01,0x02,0x07,0x06,0x22,0x00,0x01,0x01,0x53,0x06,0xc9,0x00,0x01,0x01,0x54,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xf6,0x00,0x41,0x00,0x01,0x00,0x0a,0x00,0x41,0x00,0x01,0x00,0x0f,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x41,0x00,0x01,0xff,0xfb,0x00,0x32,0x00,0x01,0x00,0x00, 0x00,0x78,0x00,0x01,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,0x00,0xff,0xc9,0x00,0x01,0x00,0x00,0xff,0xe2,0x00,0x01,0xff,0xf1,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x01,0xff,0xa6,0x00,0x00,0x00,0x01,0x01,0xae,0x00,0x82,0x00,0x01,0x00,0x00,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x01, 0x00,0x00,0x00,0x1e,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x01,0x00,0x00,0x00,0x64,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x01,0x00,0xd9,0x00,0x82,0x00,0x01,0x02,0x80,0x00,0x82,0x00,0x01,0x01,0x54,0xfe,0xc0,0x00,0x01,0x00,0x00,0xfe,0x48,0x00,0x01,0x00,0x00,0xfe,0x5c,0x00,0x01,0xff,0xfb,0xff,0x4c,0x00,0x01,0x00,0x00,0xfe,0xc0, 0x00,0x01,0x00,0x00,0xfe,0x7a,0x00,0x01,0x00,0x00,0xfe,0x20,0x00,0x01,0x00,0x00,0xfe,0xb6,0x00,0x01,0x00,0x00,0xfe,0x84,0x00,0x01,0x00,0x00,0xff,0x10,0x00,0x01,0x00,0x00,0xfe,0xa2,0x00,0x01,0x00,0x00,0xff,0x56,0x00,0x01,0x00,0x00,0xfe,0xd4,0x00,0x01,0x00,0x00,0xfd,0xf8,0x00,0x01,0x00,0x00,0xfe,0x16,0x00,0x01,0x00,0x00, 0xfe,0x3e,0x00,0x01,0x01,0xa9,0xfe,0xa2,0x00,0x01,0x00,0x00,0xfe,0x0c,0x00,0x01,0x00,0xd9,0xfe,0x02,0x00,0x01,0x02,0x80,0xfe,0x02,0x00,0x01,0x03,0x16,0x06,0x0e,0x00,0x01,0x02,0x67,0x04,0xb0,0x00,0x01,0x01,0x03,0x06,0x7c,0x00,0x01,0x00,0x7e,0x06,0x73,0x00,0x01,0x01,0x03,0xff,0x71,0x00,0x01,0x01,0x03,0x06,0x5e,0x00,0x01, 0x00,0xc4,0x06,0x73,0x00,0x01,0x01,0x03,0x06,0x76,0x00,0x01,0x01,0x03,0x06,0x62,0x00,0x01,0x01,0x03,0x06,0x1d,0x00,0x01,0x00,0xef,0x06,0x71,0x00,0x01,0x00,0xb2,0xff,0x6b,0x00,0x01,0x00,0xf5,0x06,0x7c,0x00,0x01,0x01,0x03,0xff,0x6b,0x00,0x01,0x00,0xe9,0x06,0x1e,0x00,0x01,0x01,0x03,0x06,0x70,0x00,0x01,0x00,0xec,0x06,0x1f, 0x00,0x01,0x01,0x03,0x06,0x8f,0x00,0x01,0x01,0x03,0x06,0x7b,0x00,0x01,0x01,0x03,0x06,0x71,0x00,0x01,0x01,0x1f,0x06,0x65,0x00,0x01,0x00,0xec,0x00,0x05,0x00,0x01,0x01,0x0c,0x06,0x70,0x00,0x01,0x01,0x03,0xff,0xc1,0x00,0x01,0x01,0x03,0x06,0x35,0x00,0x01,0x01,0x1f,0x00,0x34,0x00,0x01,0x00,0xf9,0x06,0x55,0x00,0x01,0x00,0xeb, 0x06,0x55,0x00,0x01,0x01,0x11,0x06,0x1f,0x00,0x01,0x01,0x1c,0x06,0x1f,0x00,0x01,0x00,0xf3,0x06,0x71,0x00,0x01,0x01,0x03,0xff,0x7e,0x00,0x01,0x00,0xf9,0x06,0x7c,0x00,0x01,0x01,0x03,0x05,0x16,0x00,0x01,0x01,0x03,0x05,0x20,0x00,0x01,0x01,0x03,0x05,0x28,0x00,0x01,0x01,0x03,0xff,0x69,0x00,0x01,0x01,0x42,0x06,0x73,0x00,0x01, 0x01,0x03,0x06,0x67,0x00,0x01,0x00,0xf8,0x06,0x1d,0x00,0x01,0x00,0xd7,0x06,0x1f,0x00,0x01,0x00,0xe1,0x06,0x7a,0x00,0x01,0x01,0x03,0x06,0x60,0x00,0x01,0x01,0x03,0x05,0x26,0x00,0x01,0x00,0xfa,0x05,0x26,0x00,0x01,0x01,0x03,0x00,0xc1,0x00,0x01,0x01,0x18,0x06,0x72,0x00,0x01,0x00,0xfa,0xff,0xce,0x00,0x01,0x01,0x40,0x06,0x72, 0x00,0x01,0x01,0x7c,0x06,0x72,0x00,0x01,0x01,0x2c,0xff,0xce,0x00,0x01,0x00,0xc8,0x06,0x72,0x00,0x01,0x01,0x68,0x06,0x72,0x00,0x01,0x00,0xfa,0x06,0x72,0x00,0x01,0x00,0xbe,0xff,0x74,0x00,0x01,0x01,0x5e,0xff,0x74,0x00,0x01,0x00,0xc8,0xff,0x74,0x00,0x01,0x01,0x2c,0x06,0x72,0x00,0x01,0x01,0xe0,0x06,0x72,0x00,0x01,0x01,0x7c, 0xff,0x74,0x00,0x01,0x00,0xdc,0x06,0x72,0x00,0x01,0x01,0x04,0xff,0x74,0x00,0x01,0x00,0xa0,0x06,0x72,0x00,0x01,0x00,0x8c,0xff,0x4c,0x00,0x01,0x02,0x80,0x06,0x72,0x00,0x01,0x01,0x4a,0x06,0x72,0x00,0x01,0x01,0x03,0x03,0xb8,0x00,0x01,0x00,0xfa,0x06,0x5e,0x00,0x01,0x02,0x5a,0x06,0x71,0x00,0x01,0x01,0x05,0x06,0x1f,0x00,0x01, 0x00,0xdd,0x06,0x1e,0x00,0x01,0x00,0xfa,0x06,0x71,0x00,0x01,0x01,0x03,0x05,0xd1,0x00,0x01,0x01,0x03,0xff,0x90,0x00,0x01,0x00,0x1d,0x07,0x1d,0x00,0x01,0xff,0x8e,0x07,0x1d,0x00,0x01,0xff,0x97,0x07,0x1d,0x00,0x01,0xff,0x47,0x07,0x1d,0x00,0x01,0xff,0x79,0x07,0x1d,0x00,0x01,0xff,0xcd,0x07,0x1d,0x00,0x01,0x01,0x7a,0x06,0x71, 0x00,0x01,0x01,0x93,0x06,0x71,0x00,0x01,0xff,0xda,0x00,0x0c,0x00,0x01,0x00,0xfa,0x06,0x1e,0x00,0x01,0x00,0xfa,0xff,0x5c,0x00,0x01,0x00,0xfa,0x08,0x1b,0x00,0x01,0x00,0xfa,0x07,0x62,0x00,0x01,0x00,0xfa,0xfd,0xcc,0x00,0x01,0x00,0xfa,0x04,0x09,0x00,0x01,0x01,0x2c,0xfe,0x42,0x00,0x01,0x01,0x90,0x05,0x48,0x00,0x01,0x00,0xfa, 0xff,0x2a,0x00,0x01,0x01,0x90,0x06,0x2e,0x00,0x01,0x01,0xf4,0x04,0x09,0x00,0x01,0x02,0x26,0xfe,0x42,0x00,0x01,0x02,0x0e,0x04,0x4e,0x00,0x01,0x02,0xa4,0xfd,0xcd,0x00,0x01,0x02,0x26,0xff,0x2a,0x00,0x01,0x01,0xf4,0x04,0xf7,0x00,0x01,0x02,0x0e,0x05,0x3e,0x00,0x01,0x01,0xc2,0x04,0x3b,0x00,0x01,0x02,0x58,0xff,0x2a,0x00,0x01, 0x01,0x5e,0x04,0x89,0x00,0x01,0x01,0x2c,0x03,0xd2,0x00,0x01,0x02,0xbc,0xff,0x22,0x00,0x01,0x01,0xc2,0x04,0xb6,0x00,0x01,0x01,0xf4,0xff,0x2a,0x00,0x01,0x01,0xf4,0x04,0x8a,0x00,0x01,0x01,0xf5,0x04,0x5d,0x00,0x01,0x02,0x8b,0xfd,0xcd,0x00,0x01,0x01,0xc2,0x05,0x48,0x00,0x01,0x01,0xf4,0x05,0x16,0x00,0x01,0x01,0xf5,0x05,0x65, 0x00,0x01,0x01,0x90,0x05,0x88,0x00,0x01,0x01,0x90,0xff,0x2a,0x00,0x01,0x01,0xc2,0x05,0x88,0x00,0x01,0x00,0xfa,0x05,0x9e,0x00,0x01,0x01,0x5e,0xff,0x2a,0x00,0x01,0x01,0x5e,0x06,0x1e,0x00,0x01,0x01,0x2c,0xff,0x2a,0x00,0x01,0x01,0x4a,0x03,0xdb,0x00,0x01,0x02,0x44,0xfe,0xf8,0x00,0x01,0x01,0x5e,0x05,0x48,0x00,0x01,0x01,0x7f, 0x04,0xe9,0x00,0x01,0x02,0x79,0xff,0x2a,0x00,0x01,0x01,0xc5,0x04,0x50,0x00,0x01,0x03,0x55,0xfd,0xcd,0x00,0x01,0x01,0xff,0x04,0x9f,0x00,0x01,0x02,0x31,0xff,0x2a,0x00,0x01,0x01,0x40,0xfe,0x42,0x00,0x01,0x01,0xc6,0x03,0x3f,0x00,0x01,0x00,0x64,0xfe,0xff,0x00,0x01,0x01,0xff,0x05,0xc8,0x00,0x01,0x01,0xf8,0xfe,0x9e,0x00,0x01, 0x01,0x5e,0x05,0xd4,0x00,0x01,0x01,0xae,0x04,0xb7,0x00,0x01,0x01,0xe0,0xfe,0x9e,0x00,0x01,0x01,0x22,0x03,0x7c,0x00,0x01,0x01,0x81,0xff,0x38,0x00,0x01,0x00,0xfa,0xff,0x9c,0x00,0x01,0x01,0x90,0x05,0xa2,0x00,0x01,0x01,0x90,0xfd,0xcd,0x00,0x01,0x01,0xae,0x05,0x62,0x00,0x01,0x01,0xe0,0xfe,0xf1,0x00,0x01,0x02,0x3b,0x03,0xd7, 0x00,0x01,0x01,0x73,0xff,0x0a,0x00,0x01,0x01,0xa5,0x05,0xc1,0x00,0x01,0x02,0x09,0xff,0x22,0x00,0x01,0x02,0x3b,0x05,0x48,0x00,0x01,0x01,0xd7,0xff,0x22,0x00,0x01,0x01,0x73,0x05,0x02,0x00,0x01,0x01,0x1a,0x04,0x82,0x00,0x01,0x01,0xb0,0xff,0x22,0x00,0x01,0x01,0x1a,0x05,0xc1,0x00,0x01,0x01,0x90,0x03,0x26,0x00,0x01,0x01,0x2c, 0xfd,0xcd,0x00,0x01,0x01,0x90,0x04,0x6b,0x00,0x01,0x02,0x8f,0x03,0xd7,0x00,0x01,0x06,0x13,0xff,0x2b,0x00,0x01,0x02,0x8f,0x03,0xd2,0x00,0x01,0x06,0xdb,0xff,0x2b,0x00,0x01,0x03,0xe8,0x05,0x24,0x00,0x01,0x02,0xee,0xff,0x22,0x00,0x01,0x01,0x91,0x04,0xf2,0x00,0x01,0x01,0x91,0x05,0xf3,0x00,0x01,0x00,0x96,0x02,0x29,0x00,0x01, 0x00,0x96,0xfe,0x62,0x00,0x01,0x02,0x9f,0x04,0x2a,0x00,0x01,0x02,0x3b,0xff,0x22,0x00,0x01,0x01,0x31,0x04,0x79,0x00,0x01,0x02,0xc1,0xfd,0xcd,0x00,0x01,0x02,0x3b,0x05,0x24,0x00,0x01,0x03,0x03,0xff,0x22,0x00,0x01,0x01,0xc7,0x05,0x24,0x00,0x01,0x02,0x8f,0xfe,0x48,0x00,0x01,0x01,0x33,0x03,0x81,0x00,0x01,0x02,0x5f,0xff,0x2b, 0x00,0x01,0x02,0x5d,0x04,0x24,0x00,0x01,0x02,0x8f,0xfd,0xcd,0x00,0x01,0x01,0xa5,0x04,0x96,0x00,0x01,0x01,0xc2,0x03,0xe3,0x00,0x01,0x01,0xc6,0x04,0x15,0x00,0x01,0x01,0xf8,0xfe,0xf1,0x00,0x01,0x00,0x64,0xff,0x27,0x00,0x01,0x01,0x90,0x04,0x5c,0x00,0x01,0x01,0x41,0xff,0x27,0x00,0x01,0x01,0x72,0xfd,0x97,0x00,0x01,0x02,0x26, 0xfd,0x97,0x00,0x01,0x01,0x90,0x05,0x83,0x00,0x01,0x01,0xd7,0x04,0xa4,0x00,0x01,0x03,0x67,0xff,0x22,0x00,0x01,0x01,0xd7,0x05,0x76,0x00,0x01,0x00,0xfa,0x06,0xa2,0x00,0x01,0x01,0xff,0x06,0x7d,0x00,0x01,0x01,0xa5,0x06,0x76,0x00,0x01,0x01,0x73,0x04,0x8d,0x00,0x01,0x01,0x5e,0x06,0x96,0x00,0x01,0x00,0xe8,0x07,0x41,0x00,0x01, 0x01,0x5e,0x06,0x1d,0x00,0x01,0x02,0x5d,0x02,0xed,0x00,0x01,0x01,0xa5,0x04,0xc8,0x00,0x01,0x00,0xfa,0xfd,0xd8,0x00,0x01,0x01,0x5e,0x03,0x2d,0x00,0x01,0x01,0x90,0xfd,0xc8,0x00,0x01,0x01,0x6c,0x03,0xf1,0x00,0x01,0x02,0x66,0xff,0x22,0x00,0x01,0x01,0x6c,0x01,0x2f,0x00,0x01,0x02,0x66,0xfd,0xf6,0x00,0x01,0x01,0x6c,0x05,0xa2, 0x00,0x01,0x01,0x6c,0x03,0xa1,0x00,0x01,0x02,0x9f,0x04,0xf2,0x00,0x01,0x01,0xc2,0x06,0xa0,0x00,0x01,0x01,0x83,0x02,0xe7,0x00,0x01,0x02,0x19,0xff,0x19,0x00,0x01,0x01,0xf9,0x03,0x7f,0x00,0x01,0x00,0xfa,0x08,0x1a,0x00,0x01,0x00,0x96,0xfd,0xcc,0x00,0x01,0x01,0xc2,0x05,0xa2,0x00,0x01,0x01,0xa9,0x05,0xc7,0x00,0x01,0x01,0x77, 0xfd,0xcd,0x00,0x01,0x01,0xc6,0x04,0x8b,0x00,0x01,0x01,0xc6,0x03,0x4a,0x00,0x01,0x01,0x73,0x04,0x9e,0x00,0x01,0x01,0x73,0xff,0x27,0x00,0x01,0x01,0x5e,0xfd,0x97,0x00,0x01,0x01,0xd7,0xff,0x20,0x00,0x01,0x00,0xfa,0xfe,0xa1,0x00,0x01,0x01,0x41,0x04,0x9e,0x00,0x01,0x02,0x0e,0x05,0xf3,0x00,0x01,0x01,0xf4,0x05,0x7a,0x00,0x01, 0x02,0x0e,0x06,0x56,0x00,0x01,0x01,0xf4,0x05,0xdd,0x00,0x01,0x01,0xdc,0x06,0x56,0x00,0x01,0x01,0xb0,0xfe,0x90,0x00,0x01,0x01,0xb0,0xfe,0x42,0x00,0x01,0x01,0x1a,0x06,0xd9,0x00,0x01,0x01,0x90,0x05,0x13,0x00,0x01,0x01,0x2c,0xfd,0xc9,0x00,0x01,0x01,0x2c,0xfd,0xaf,0x00,0x01,0x06,0x13,0xfe,0x63,0x00,0x01,0x01,0xc2,0x04,0x39, 0x00,0x01,0x01,0xc2,0xff,0x3c,0x00,0x01,0x06,0x13,0xfd,0x97,0x00,0x01,0x01,0x5e,0xff,0x27,0x00,0x01,0x07,0x3f,0xfe,0x63,0x00,0x01,0x02,0x26,0xff,0x0a,0x00,0x01,0x02,0x8f,0x04,0x68,0x00,0x01,0x01,0x2c,0x04,0x68,0x00,0x01,0x03,0xe8,0x06,0x1e,0x00,0x01,0x01,0x91,0x06,0xd9,0x00,0x01,0x01,0xf5,0x06,0x74,0x00,0x01,0x01,0xc2, 0x06,0x60,0x00,0x01,0x01,0xf4,0x06,0x2e,0x00,0x01,0x01,0x90,0xfe,0x42,0x00,0x01,0x01,0xc2,0xfd,0x97,0x00,0x01,0x01,0x95,0x04,0x47,0x00,0x01,0x01,0x63,0x04,0xc9,0x00,0x01,0x01,0xdb,0x04,0x4b,0x00,0x01,0x03,0x6b,0xfe,0xf0,0x00,0x01,0x01,0x5e,0x04,0x7d,0x00,0x01,0x02,0x8a,0xfe,0xf0,0x00,0x01,0x02,0x3b,0x06,0xe5,0x00,0x01, 0x01,0x2c,0x06,0xe5,0x00,0x01,0x01,0xa5,0x07,0x35,0x00,0x01,0x01,0x2c,0x07,0xfd,0x00,0x01,0x01,0xd7,0x05,0x9d,0x00,0x01,0x01,0x2c,0x07,0xf5,0x00,0x01,0x01,0x41,0xff,0x0a,0x00,0x01,0x01,0x5e,0xfe,0x42,0x00,0x01,0x01,0xa5,0xff,0x27,0x00,0x01,0x01,0xd7,0x05,0x6b,0x00,0x01,0x00,0xfa,0x08,0xef,0x00,0x01,0x01,0x90,0x08,0x40, 0x00,0x01,0x01,0x5e,0x07,0x99,0x00,0x01,0x01,0x90,0x08,0xb1,0x00,0x01,0x02,0x8f,0xfd,0x92,0x00,0x01,0x01,0x2c,0xfd,0x97,0x00,0x01,0x02,0x5d,0x05,0x7a,0x00,0x01,0x00,0xcd,0xfe,0xf5,0x00,0x01,0x02,0x5d,0x05,0x72,0x00,0x01,0x00,0xcd,0xfe,0xb9,0x00,0x01,0x02,0x5d,0x05,0x0a,0x00,0x01,0x01,0xc2,0x04,0x48,0x00,0x01,0x01,0x90, 0xfd,0xcc,0x00,0x01,0x01,0xc2,0x05,0x95,0x00,0x01,0x01,0xc2,0x05,0xc7,0x00,0x01,0x01,0xc2,0x05,0xbd,0x00,0x01,0x01,0xc2,0x04,0xdd,0x00,0x01,0x01,0x90,0x05,0xf5,0x00,0x01,0x01,0xc2,0x04,0x15,0x00,0x01,0x01,0xf4,0xfe,0xf1,0x00,0x01,0x01,0xae,0x03,0x3f,0x00,0x01,0x01,0xc6,0x06,0x40,0x00,0x01,0x01,0xc6,0x04,0x90,0x00,0x01, 0x01,0x90,0x05,0xbe,0x00,0x01,0x01,0xc6,0x04,0xdc,0x00,0x01,0x01,0x2c,0xff,0x27,0x00,0x01,0x01,0xc6,0x03,0xe9,0x00,0x01,0x00,0xfa,0xff,0x22,0x00,0x01,0x00,0xc8,0xff,0x27,0x00,0x01,0x00,0xc8,0xff,0x22,0x00,0x01,0x02,0x8a,0xff,0x0a,0x00,0x01,0x01,0xf5,0x05,0x8e,0x00,0x01,0x01,0xf4,0xfe,0x42,0x00,0x01,0x02,0x5f,0xfd,0xcd, 0x00,0x01,0x01,0xd7,0x05,0x41,0x00,0x01,0x02,0x62,0x05,0x16,0x00,0x01,0x02,0x62,0xff,0x92,0x00,0x01,0x01,0x1a,0x06,0x69,0x00,0x01,0x01,0x7e,0x06,0x69,0x00,0x01,0x01,0x7f,0x06,0x40,0x00,0x01,0x01,0xc5,0x05,0xaa,0x00,0x01,0x00,0xe6,0x06,0x40,0x00,0x01,0x01,0xe0,0xff,0x2a,0x00,0x01,0x01,0x18,0x06,0x0e,0x00,0x01,0x02,0x12, 0xfd,0xcd,0x00,0x01,0x01,0x0f,0xff,0x3c,0x00,0x01,0x00,0xfa,0xfe,0x42,0x00,0x01,0x01,0x72,0xfe,0x42,0x00,0x01,0x01,0x41,0xff,0x0d,0x00,0x01,0x01,0x5e,0xfd,0xe1,0x00,0x01,0x02,0x3b,0x05,0xbe,0x00,0x01,0x01,0xb0,0xfd,0x97,0x00,0x01,0x01,0xb0,0xfd,0xe1,0x00,0x01,0x01,0x2c,0x04,0x89,0x00,0x01,0x01,0x91,0x06,0x07,0x00,0x01, 0x01,0xf5,0x05,0x84,0x00,0x01,0x01,0x91,0x06,0xed,0x00,0x01,0x01,0xf5,0x06,0x6a,0x00,0x01,0x01,0xc2,0xfe,0x42,0x00,0x01,0x01,0xf4,0xfd,0x83,0x00,0x01,0x01,0xd7,0x05,0x55,0x00,0x01,0x01,0xd7,0x04,0xdd,0x00,0x01,0x01,0x90,0xfd,0x97,0x00,0x01,0x01,0x01,0x04,0xdd,0x00,0x01,0x01,0x4a,0x04,0xdd,0x00,0x01,0x02,0x5f,0xfe,0x63, 0x00,0x01,0x02,0x44,0xfe,0x42,0x00,0x01,0x00,0x9b,0xfe,0x91,0x00,0x01,0x02,0x5d,0x06,0xc8,0x00,0x01,0x01,0x5e,0x08,0x1e,0x00,0x01,0x02,0x5d,0x05,0xc7,0x00,0x01,0x01,0x90,0x07,0x1d,0x00,0x01,0x01,0x90,0x05,0x20,0x00,0x01,0x01,0xc6,0x04,0x47,0x00,0x01,0x00,0xfa,0xff,0x2b,0x00,0x01,0x00,0xfa,0xfe,0xd6,0x00,0x01,0x01,0x7e, 0x04,0x82,0x00,0x01,0x01,0x7e,0x05,0xc1,0x00,0x01,0x02,0xee,0xff,0x25,0x00,0x01,0x02,0x2a,0x05,0x78,0x00,0x01,0x02,0x2a,0x04,0x2c,0x00,0x01,0x02,0x2a,0x06,0x84,0x00,0x01,0x02,0x2a,0x05,0x58,0x00,0x01,0x01,0x5e,0x04,0xe9,0x00,0x01,0x01,0x7f,0x05,0x1b,0x00,0x01,0x01,0x5e,0x04,0x50,0x00,0x01,0x02,0x26,0xfd,0xcd,0x00,0x01, 0x00,0xfa,0x05,0x70,0x00,0x01,0x01,0x7e,0x07,0x41,0x00,0x01,0x01,0x7e,0x06,0xd9,0x00,0x01,0x02,0x09,0x04,0xa4,0x00,0x01,0x02,0x09,0x05,0x76,0x00,0x01,0x02,0x09,0x05,0x9d,0x00,0x01,0x02,0x09,0x05,0x6b,0x00,0x01,0x02,0x5d,0x05,0x7e,0x00,0x01,0x00,0xcd,0xfe,0xf0,0x00,0x01,0x01,0x83,0x04,0x75,0x00,0x01,0x01,0x83,0x03,0xc0, 0x00,0x01,0x01,0x7e,0x06,0x40,0x00,0x01,0x02,0x09,0x05,0x55,0x00,0x01,0x02,0x09,0x04,0xdd,0x00,0x01,0x00,0x9b,0xfe,0x8c,0x00,0x01,0x02,0xa4,0xfd,0xcc,0x00,0x01,0x02,0x26,0xfd,0xd1,0x00,0x01,0x02,0xa4,0xfd,0xc8,0x00,0x01,0x01,0xf4,0x03,0xd5,0x00,0x01,0x02,0x26,0xfd,0xc8,0x00,0x01,0x01,0x2c,0x05,0xaf,0x00,0x01,0x01,0x90, 0x07,0x3f,0x00,0x01,0x01,0xaa,0x06,0xbe,0x00,0x01,0x01,0xf4,0x06,0x77,0x00,0x01,0x00,0xfa,0x07,0xa0,0x00,0x01,0x01,0x90,0xff,0x9c,0x00,0x01,0x01,0x90,0xff,0x5c,0x00,0x01,0x01,0xc6,0x05,0xee,0x00,0x01,0x01,0xc6,0x05,0x43,0x00,0x01,0x01,0x90,0x06,0x5a,0x00,0x01,0x00,0xc8,0xff,0x08,0x00,0x01,0x01,0xc6,0x03,0xb7,0x00,0x01, 0x00,0xfa,0xfd,0x46,0x00,0x01,0x01,0xd9,0x05,0x27,0x00,0x01,0x02,0x3d,0xfd,0xcd,0x00,0x01,0x01,0xd8,0x05,0x27,0x00,0x01,0x02,0x3c,0xfd,0xcd,0x00,0x01,0x01,0x6c,0x05,0xd2,0x00,0x01,0x01,0x6c,0x03,0xd1,0x00,0x01,0x02,0x26,0xfd,0x46,0x00,0x01,0x01,0x2c,0x04,0xba,0x00,0x01,0x01,0x5e,0x04,0x54,0x00,0x01,0x00,0xc8,0x06,0xf1, 0x00,0x01,0x01,0x2c,0xff,0x2c,0x00,0x01,0x00,0xc8,0x07,0xaa,0x00,0x01,0x00,0xc8,0x05,0x8a,0x00,0x01,0x01,0x2c,0xfd,0xcc,0x00,0x01,0x00,0xc8,0x07,0xa9,0x00,0x01,0x00,0xc8,0x06,0x1b,0x00,0x01,0x00,0xc8,0x07,0x28,0x00,0x01,0x01,0x5e,0x04,0x3b,0x00,0x01,0x00,0xfa,0x04,0x89,0x00,0x01,0x01,0x5e,0x04,0x39,0x00,0x01,0x01,0x5e, 0xff,0x0a,0x00,0x01,0x00,0xfa,0xff,0x27,0x00,0x01,0x01,0x5e,0x05,0x83,0x00,0x01,0x00,0xfa,0x05,0xaf,0x00,0x01,0x00,0xfa,0x04,0xec,0x00,0x01,0x00,0xfa,0x04,0x54,0x00,0x01,0x01,0x2c,0x04,0x36,0x00,0x01,0x01,0x90,0xff,0x0a,0x00,0x01,0x01,0x2c,0x04,0xfe,0x00,0x01,0x00,0xf8,0x06,0x1e,0x00,0x01,0x00,0x94,0xff,0x86,0x00,0x01, 0x00,0xc6,0xff,0x86,0x00,0x01,0x00,0xf8,0x08,0x40,0x00,0x01,0x00,0xf8,0x07,0x99,0x00,0x01,0x00,0xf8,0x08,0xb1,0x00,0x01,0x00,0x94,0xfd,0x97,0x00,0x01,0x00,0xc6,0xfd,0x97,0x00,0x01,0x01,0xc9,0x02,0xd2,0x00,0x01,0x01,0x65,0xfd,0xcd,0x00,0x01,0x01,0xc9,0x04,0x6b,0x00,0x01,0x01,0x97,0x06,0x1d,0x00,0x01,0x01,0xc9,0x05,0x13, 0x00,0x01,0x01,0x65,0xfd,0xc9,0x00,0x01,0x01,0x65,0xfd,0xaf,0x00,0x01,0x01,0xc9,0x05,0x83,0x00,0x01,0x01,0xc9,0x05,0x20,0x00,0x01,0x01,0xc9,0x07,0x3f,0x00,0x01,0x01,0xc6,0x04,0xc2,0x00,0x01,0x01,0xc6,0x04,0x4f,0x00,0x01,0x01,0xc6,0x05,0x67,0x00,0x01,0x01,0xc6,0x03,0x04,0x00,0x01,0x00,0xcc,0xfe,0xcd,0x00,0x01,0x01,0xae, 0x03,0x04,0x00,0x01,0x00,0x9a,0xfe,0xf0,0x00,0x01,0x00,0x9a,0xff,0x08,0x00,0x01,0x01,0xf8,0xff,0x6e,0x00,0x01,0x01,0x6c,0x01,0xc5,0x00,0x01,0x00,0xcc,0xff,0x22,0x00,0x01,0x01,0x30,0xfe,0xa4,0x00,0x01,0x00,0xc8,0x05,0xe2,0x00,0x01,0x00,0xc8,0xff,0x2a,0x00,0x01,0x00,0x64,0x05,0x4c,0x00,0x01,0x00,0xb4,0xff,0x2a,0x00,0x01, 0x02,0x3a,0x03,0xd7,0x00,0x01,0x01,0x40,0xff,0x24,0x00,0x01,0x01,0x86,0xfd,0x8a,0x00,0x01,0x02,0x58,0x05,0x32,0x00,0x01,0x02,0xbc,0xfd,0xcd,0x00,0x01,0x02,0x26,0x05,0x32,0x00,0x01,0x03,0xde,0x05,0x50,0x00,0x01,0x02,0x3a,0xff,0x22,0x00,0x01,0x01,0xe0,0x06,0xc2,0x00,0x01,0x01,0xe0,0xfe,0x52,0x00,0x01,0x02,0x9e,0x04,0x2a, 0x00,0x01,0x01,0x68,0x04,0x47,0x00,0x01,0x02,0xe4,0xfc,0x7c,0x00,0x01,0x01,0xd6,0x05,0xaa,0x00,0x01,0x01,0x68,0x05,0x24,0x00,0x01,0x02,0x8a,0xfe,0x48,0x00,0x01,0x01,0x7c,0x06,0x54,0x00,0x01,0x02,0x9e,0x05,0xfa,0x00,0x01,0x02,0x6c,0xff,0x2b,0x00,0x01,0x02,0x94,0x06,0x0e,0x00,0x01,0x01,0x36,0x05,0x1e,0x00,0x01,0x00,0x6e, 0xff,0x10,0x00,0x01,0x01,0x72,0x05,0x96,0x00,0x01,0x01,0x40,0xfe,0x52,0x00,0x01,0x01,0x4a,0xfe,0x52,0x00,0x01,0x01,0x40,0x04,0xf6,0x00,0x01,0x00,0x64,0xfe,0xd4,0x00,0x01,0x02,0x08,0x05,0x0a,0x00,0x01,0x01,0x72,0x05,0x64,0x00,0x01,0x01,0xf4,0x04,0x38,0x00,0x01,0x01,0x90,0x03,0x20,0x00,0x01,0x00,0xdc,0xfd,0xcd,0x00,0x01, 0x01,0x72,0xfd,0xcd,0x00,0x01,0x01,0xea,0x04,0x10,0x00,0x01,0x02,0x58,0xfe,0x52,0x00,0x01,0x01,0xce,0xfd,0x94,0x00,0x01,0x07,0x43,0xfd,0x6c,0x00,0x01,0x04,0xa4,0xfd,0x6c,0x00,0x01,0x01,0x6b,0x05,0xd8,0x00,0x01,0x01,0xc3,0xfe,0xe2,0x00,0x01,0x01,0x90,0x06,0x40,0x00,0x01,0x02,0x3b,0x04,0xb0,0x00,0x01,0x01,0x90,0x05,0xc3, 0x00,0x01,0x02,0x2a,0x06,0x40,0x00,0x01,0x02,0x32,0x05,0x46,0x00,0x01,0x02,0x8a,0xfd,0x7a,0x00,0x01,0x02,0x26,0xfd,0x7a,0x00,0x01,0x01,0x90,0x05,0xaa,0x00,0x01,0x01,0x5e,0x05,0x91,0x00,0x01,0x02,0x2a,0x04,0x90,0x00,0x01,0x06,0xf4,0x06,0xc2,0x00,0x01,0x06,0xf4,0xff,0x2a,0x00,0x01,0x05,0x0a,0x08,0x7a,0x00,0x01,0x04,0xb0, 0xff,0x2a,0x00,0x01,0x08,0xfc,0x06,0x32,0x00,0x01,0x08,0xfc,0xff,0x9c,0x00,0x01,0x0a,0x0a,0x03,0x26,0x00,0x01,0x09,0xa6,0xfd,0xcd,0x00,0x01,0x07,0xd0,0x03,0xe8,0x00,0x01,0x07,0x62,0xfe,0x3e,0x00,0x01,0x06,0x5e,0x06,0x54,0x00,0x01,0x05,0x46,0xfe,0x70,0x00,0x01,0x09,0x92,0x05,0x88,0x00,0x01,0x09,0x92,0xff,0x2a,0x00,0x01, 0x07,0x08,0x06,0x5e,0x00,0x01,0x04,0xe2,0x05,0xbe,0x00,0x01,0x01,0x03,0x07,0xda,0x00,0x01,0x00,0x7e,0x08,0x52,0x00,0x01,0x01,0x03,0x07,0x26,0x00,0x01,0x00,0xc4,0x08,0x52,0x00,0x01,0x01,0x03,0x08,0x2a,0x00,0x01,0x01,0x03,0x07,0x6c,0x00,0x01,0x01,0x03,0x08,0x3e,0x00,0x01,0x01,0x03,0x08,0x98,0x00,0x01,0x00,0xef,0x09,0x24, 0x00,0x01,0x00,0xf5,0x08,0x3e,0x00,0x01,0x01,0x03,0x09,0x38,0x00,0x01,0x00,0xef,0x08,0x5c,0x00,0x01,0x00,0xe9,0x08,0x98,0x00,0x01,0x01,0x03,0x08,0x66,0x00,0x01,0x00,0xec,0x08,0x2a,0x00,0x01,0x01,0x03,0x08,0x16,0x00,0x01,0x01,0x03,0x07,0xf8,0x00,0x01,0x01,0x1f,0x08,0x8e,0x00,0x01,0x01,0x0c,0x08,0x66,0x00,0x01,0x01,0x03, 0x08,0xde,0x00,0x01,0x00,0xf9,0x08,0x34,0x00,0x01,0x00,0xeb,0x08,0x34,0x00,0x01,0x01,0x11,0x08,0x3e,0x00,0x01,0x01,0x1c,0x08,0xd4,0x00,0x01,0x00,0xf3,0x07,0xf8,0x00,0x01,0x00,0xc4,0x08,0x70,0x00,0x01,0x01,0x03,0x08,0x34,0x00,0x01,0x00,0xf9,0x09,0x1a,0x00,0x01,0x01,0x03,0x07,0x30,0x00,0x01,0x01,0x03,0x08,0x48,0x00,0x01, 0x01,0x03,0x07,0xe4,0x00,0x01,0x01,0x03,0x07,0x3a,0x00,0x01,0x01,0x42,0x08,0x52,0x00,0x01,0x01,0x03,0x08,0x7a,0x00,0x01,0x00,0xf8,0x09,0x1a,0x00,0x01,0x00,0xd7,0x08,0xfc,0x00,0x01,0x01,0x03,0x07,0x12,0x00,0x01,0x00,0xe1,0x08,0x34,0x00,0x01,0x01,0x03,0x08,0x52,0x00,0x01,0x01,0x03,0x08,0xb6,0x00,0x01,0x00,0xfa,0x07,0x9e, 0x00,0x01,0x01,0x03,0x08,0xca,0x00,0x01,0x00,0xfa,0x08,0x52,0x00,0x01,0x00,0xfa,0x08,0x98,0x00,0x01,0x01,0x18,0x07,0xd0,0x00,0x01,0x01,0x18,0x08,0x61,0x00,0x01,0x01,0x40,0x08,0x98,0x00,0x01,0x01,0x7c,0x09,0x47,0x00,0x01,0x00,0xc8,0x07,0x78,0x00,0x01,0x01,0x68,0x07,0x78,0x00,0x01,0x00,0xfa,0x08,0x27,0x00,0x01,0x01,0x2c, 0x08,0x98,0x00,0x01,0x01,0xe0,0x08,0x5b,0x00,0x01,0x00,0xdc,0x09,0x2a,0x00,0x01,0x00,0xfa,0x08,0x69,0x00,0x01,0x00,0xfa,0x08,0x2c,0x00,0x01,0x00,0xc8,0x08,0x95,0x00,0x01,0x00,0xa0,0x08,0x95,0x00,0x01,0x01,0x40,0x08,0x95,0x00,0x01,0x02,0x80,0x08,0x95,0x00,0x01,0x01,0x4a,0x08,0x95,0x00,0x01,0x01,0x2c,0x08,0x5b,0x00,0x01, 0x01,0x03,0x06,0xf4,0x00,0x01,0x02,0x5a,0x09,0xc4,0x00,0x01,0x01,0x05,0x08,0x65,0x00,0x01,0x00,0xc9,0x09,0x2a,0x00,0x01,0x00,0xfa,0x09,0x8b,0x00,0x01,0x01,0x03,0x08,0xd9,0x00,0x01,0x00,0x1d,0x0a,0x5b,0x00,0x01,0xff,0x8e,0x09,0xe7,0x00,0x01,0xff,0x97,0x09,0xe7,0x00,0x01,0xff,0x47,0x09,0xff,0x00,0x01,0xff,0x79,0x09,0xa9, 0x00,0x01,0xff,0xcd,0x09,0xa9,0x00,0x01,0x01,0x7a,0x08,0x53,0x00,0x01,0x01,0x93,0x08,0x38,0x00,0x01,0x01,0x03,0xfe,0x0c,0x00,0x01,0x01,0x03,0xfe,0xd4,0x00,0x01,0x00,0xb2,0xfd,0xbc,0x00,0x01,0x01,0x03,0xfd,0xbc,0x00,0x01,0x00,0xec,0xfd,0xc6,0x00,0x01,0x01,0x1f,0xfd,0xc6,0x00,0x01,0x01,0x03,0xfe,0x48,0x00,0x01,0x01,0x03, 0xfe,0x70,0x00,0x01,0x00,0xfa,0xfe,0x53,0x00,0x01,0x01,0x2c,0xfd,0x8b,0x00,0x01,0x00,0xbe,0xfe,0x5c,0x00,0x01,0x01,0x5e,0xfe,0x5c,0x00,0x01,0x00,0xc8,0xfd,0xa5,0x00,0x01,0x01,0x7c,0xfd,0x5e,0x00,0x01,0x01,0x04,0xfd,0xbd,0x00,0x01,0x00,0x8c,0xfd,0x3a,0x00,0x01,0x01,0x03,0xfc,0x8b,0x00,0x01,0x00,0x00,0xfe,0x09,0x00,0x01, 0x02,0x62,0xff,0xe2,0x00,0x01,0x02,0xb7,0x00,0x00,0x00,0x01,0x02,0xc9,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x02,0xad,0x00,0x50,0x00,0x01,0x00,0xdf,0xff,0x44,0x00,0x01,0x02,0xb2,0x00,0x50,0x00,0x01,0x02,0x3a,0xfe,0x42,0x00,0x01,0x01,0x36,0x00,0x00,0x00,0x01,0x02,0xb8,0x00,0x00,0x00,0x01,0x01,0xa4,0x00,0x00, 0x00,0x01,0x01,0xc6,0x00,0x00,0x00,0x01,0x01,0xb3,0x00,0x00,0x00,0x01,0x03,0x20,0x00,0x00,0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x01,0x01,0x75,0x00,0x00,0x00,0x01,0x00,0xef,0x00,0x00,0x00,0x01,0x00,0x95,0x00,0x00,0x00,0x01,0x02,0x2a,0x00,0x00,0x00,0x01,0x01,0x9b,0x00,0x00,0x00,0x01,0x01,0x15,0x00,0x00,0x00,0x01,0x00,0xbb, 0x00,0x00,0x00,0x01,0x01,0xd9,0x00,0x00,0x00,0x01,0x01,0x4a,0x00,0x00,0x00,0x01,0x00,0xc4,0x00,0x00,0x00,0x01,0x00,0x6a,0x00,0x00,0x00,0x01,0x01,0x50,0x00,0x00,0x00,0x01,0x00,0xc1,0x00,0x00,0x00,0x01,0x00,0x3b,0x00,0x00,0x00,0x01,0xff,0xe1,0x00,0x00,0x00,0x01,0x02,0x26,0x00,0x00,0x00,0x01,0x01,0x97,0x00,0x00,0x00,0x01, 0x00,0xdf,0x00,0x00,0x00,0x01,0x00,0x3f,0x00,0x00,0x00,0x01,0x02,0x5d,0x00,0x00,0x00,0x01,0x01,0xce,0x00,0x00,0x00,0x01,0x01,0x48,0x00,0x00,0x00,0x01,0x00,0xee,0x00,0x00,0x00,0x01,0x00,0xb6,0x00,0x00,0x00,0x01,0x00,0x27,0x00,0x00,0x00,0x01,0xff,0xa1,0x00,0x00,0x00,0x01,0xff,0x47,0x00,0x00,0x00,0x01,0x01,0x3a,0x00,0x00, 0x00,0x01,0x00,0xab,0x00,0x00,0x00,0x01,0xff,0xf3,0x00,0x00,0x00,0x01,0xff,0xcb,0x00,0x00,0x00,0x01,0x02,0x5b,0x00,0x00,0x00,0x01,0x01,0xcc,0x00,0x00,0x00,0x01,0x01,0x46,0x00,0x00,0x00,0x01,0x00,0xec,0x00,0x00,0x00,0x01,0x02,0x5a,0x00,0x00,0x00,0x01,0x01,0xcb,0x00,0x00,0x00,0x01,0x01,0x45,0x00,0x00,0x00,0x01,0x00,0xeb, 0x00,0x00,0x00,0x01,0x01,0x49,0x00,0x00,0x00,0x01,0x00,0xba,0x00,0x00,0x00,0x01,0xff,0xf5,0x00,0x00,0x00,0x01,0xff,0x3b,0x00,0x00,0x00,0x01,0x01,0x68,0x00,0x00,0x00,0x01,0x00,0xd9,0x00,0x00,0x00,0x01,0x00,0x53,0x00,0x00,0x00,0x01,0xff,0xf9,0x00,0x00,0x00,0x01,0x01,0x6d,0x00,0x00,0x00,0x01,0x00,0xde,0x00,0x00,0x00,0x01, 0x00,0x58,0x00,0x00,0x00,0x01,0xff,0xfe,0x00,0x00,0x00,0x01,0x02,0x62,0x00,0x00,0x00,0x01,0x01,0xd3,0x00,0x00,0x00,0x01,0x01,0x4d,0x00,0x00,0x00,0x01,0x00,0xf3,0x00,0x00,0x00,0x01,0xfe,0x98,0x00,0x00,0x00,0x01,0xfd,0x91,0x00,0x00,0x00,0x01,0xfc,0xd7,0x00,0x00,0x00,0x01,0x01,0x0e,0x00,0x00,0x00,0x01,0x00,0x7f,0x00,0x00, 0x00,0x01,0xff,0x9f,0x00,0x00,0x00,0x01,0x02,0x57,0x00,0x00,0x00,0x01,0x01,0xc8,0x00,0x00,0x00,0x01,0x01,0x42,0x00,0x00,0x00,0x01,0x00,0xe8,0x00,0x00,0x00,0x01,0x02,0x08,0x00,0x00,0x00,0x01,0x01,0x79,0x00,0x00,0x00,0x01,0x00,0x99,0x00,0x00,0x00,0x01,0x01,0xd1,0x00,0x00,0x00,0x01,0x00,0x61,0x00,0x00,0x00,0x01,0xff,0xa7, 0x00,0x00,0x00,0x01,0x01,0xef,0x00,0x00,0x00,0x01,0x01,0x60,0x00,0x00,0x00,0x01,0x00,0xda,0x00,0x00,0x00,0x01,0x00,0x80,0x00,0x00,0x00,0x01,0x00,0xbf,0x00,0x00,0x00,0x01,0xff,0xb6,0x00,0x00,0x00,0x01,0xfe,0xaf,0x00,0x00,0x00,0x01,0xfd,0xf5,0x00,0x00,0x00,0x01,0x01,0xae,0x00,0x00,0x00,0x01,0x01,0x1f,0x00,0x00,0x00,0x01, 0x02,0x53,0x00,0x00,0x00,0x01,0x01,0xc4,0x00,0x00,0x00,0x01,0x01,0xbe,0x00,0x00,0x00,0x01,0x01,0xaa,0x00,0x00,0x00,0x01,0x03,0x1b,0x00,0x00,0x00,0x01,0x02,0x8c,0x00,0x00,0x00,0x01,0x01,0xc0,0x00,0x00,0x00,0x01,0x01,0x34,0x00,0x00,0x00,0x01,0x02,0xa3,0x00,0x00,0x00,0x01,0x02,0x14,0x00,0x00,0x00,0x01,0x01,0x8e,0x00,0x00, 0x00,0x01,0x02,0x9e,0x00,0x00,0x00,0x01,0x02,0x0f,0x00,0x00,0x00,0x01,0x01,0x89,0x00,0x00,0x00,0x01,0x01,0x2f,0x00,0x00,0x00,0x01,0x01,0xbb,0x00,0x00,0x00,0x01,0x01,0x2c,0x00,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x00,0x01,0x00,0x4c,0x00,0x00,0x00,0x01,0x01,0xcd,0x00,0x00,0x00,0x01,0x01,0x3e,0x00,0x00,0x00,0x01,0x00,0xb8, 0x00,0x00,0x00,0x01,0x00,0x5e,0x00,0x00,0x00,0x01,0x01,0xe5,0x00,0x00,0x00,0x01,0x01,0x56,0x00,0x00,0x00,0x01,0x00,0xd0,0x00,0x00,0x00,0x01,0x00,0x76,0x00,0x00,0x00,0x01,0x00,0xc5,0x00,0x00,0x00,0x01,0xff,0xe5,0x00,0x00,0x00,0x01,0x01,0xd4,0x00,0x00,0x00,0x01,0x00,0xfc,0x00,0x00,0x00,0x01,0x00,0x6d,0x00,0x00,0x00,0x01, 0xff,0xe7,0x00,0x00,0x00,0x01,0xff,0x8d,0x00,0x00,0x00,0x01,0x01,0x62,0x00,0x00,0x00,0x01,0x00,0xd3,0x00,0x00,0x00,0x01,0x00,0x1b,0x00,0x00,0x00,0x01,0x00,0xe6,0xff,0x9c,0x00,0x01,0x00,0xca,0x00,0x00,0x00,0x01,0x00,0x8a,0x00,0x00,0x00,0x01,0x01,0x1d,0x00,0x00,0x00,0x01,0x01,0x12,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0x00, 0x00,0x01,0x01,0x10,0x00,0x00,0x00,0x01,0x00,0xf2,0x00,0x00,0x00,0x01,0x00,0x97,0x00,0x00,0x00,0x01,0x00,0xb4,0x00,0x00,0x00,0x01,0xff,0xac,0x00,0x00,0x00,0x01,0x01,0x17,0x00,0x00,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x01,0x00,0xb5,0x00,0x00,0x00,0x01,0x00,0xbe,0x00,0x00,0x00,0x01,0x00,0x66,0x00,0x00,0x00,0x01,0x00,0x98, 0x00,0x00,0x00,0x01,0x00,0xc0,0x00,0x00,0x00,0x01,0x01,0x80,0x00,0x00,0x00,0x01,0xff,0xb4,0x00,0x00,0x00,0x01,0x01,0x58,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01,0xff,0xec,0x00,0x00,0x00,0x01,0x00,0x69,0x00,0x00,0x00,0x01,0xff,0xc4,0x00,0x00,0x00,0x01,0x00,0xd2,0x00,0x00,0x00,0x01, 0x01,0x18,0x00,0x00,0x00,0x01,0x00,0xed,0x00,0x00,0x00,0x01,0x02,0x60,0x00,0x00,0x00,0x01,0x03,0xd5,0x00,0x00,0x00,0x01,0x03,0x29,0x00,0x00,0x00,0x01,0x01,0xa6,0x00,0x00,0x00,0x01,0x01,0x98,0x00,0x00,0x00,0x01,0x00,0xe4,0x00,0x00,0x00,0x01,0x02,0xa8,0x00,0x00,0x00,0x01,0x04,0x6c,0x00,0x00,0x00,0x01,0x03,0x7a,0x00,0x00, 0x00,0x01,0x01,0x9d,0x00,0x00,0x00,0x01,0x00,0x8e,0x00,0x00,0x00,0x01,0x01,0xeb,0x00,0x00,0x00,0x01,0x03,0xee,0x00,0x00,0x00,0x01,0x02,0xfc,0x00,0x00,0x00,0x01,0x01,0x47,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x00,0x01,0x01,0xa0,0x00,0x00,0x00,0x01,0x02,0xf8,0x00,0x00,0x00,0x01,0x02,0x0d,0x00,0x00,0x00,0x01,0x00,0xf5, 0x00,0x00,0x00,0x01,0x01,0x13,0x00,0x00,0x00,0x01,0x00,0x60,0x00,0x00,0x00,0x01,0x03,0xa2,0x00,0x00,0x00,0x01,0x02,0xba,0x00,0x00,0x00,0x01,0x01,0x19,0x00,0x00,0x00,0x01,0x01,0x11,0x00,0x00,0x00,0x01,0x02,0xae,0x00,0x00,0x00,0x01,0x04,0xc1,0x00,0x00,0x00,0x01,0x03,0xcf,0x00,0x00,0x00,0x01,0x01,0xb5,0x00,0x00,0x00,0x01, 0x00,0x84,0x00,0x00,0x00,0x01,0x02,0x3b,0x00,0x00,0x00,0x01,0x01,0x0c,0x00,0x00,0x00,0x01,0x01,0x3d,0x00,0x00,0x00,0x01,0x00,0x6c,0x00,0x00,0x00,0x01,0x02,0xc4,0x00,0x00,0x00,0x01,0x01,0xdc,0x00,0x00,0x00,0x01,0x01,0x25,0x00,0x00,0x00,0x01,0x04,0xbb,0x00,0x00,0x00,0x01,0x03,0xc9,0x00,0x00,0x00,0x01,0x01,0x90,0x00,0x00, 0x00,0x01,0x02,0xc1,0x00,0x00,0x00,0x01,0x05,0x02,0x00,0x00,0x00,0x01,0x04,0x10,0x00,0x00,0x00,0x01,0x01,0x72,0x00,0x00,0x00,0x01,0x02,0x3c,0x00,0x00,0x00,0x01,0x01,0xb8,0x00,0x00,0x00,0x01,0x03,0xce,0x00,0x00,0x00,0x01,0x02,0xdc,0x00,0x00,0x00,0x01,0x01,0x26,0x00,0x00,0x00,0x01,0x03,0xc4,0x00,0x00,0x00,0x01,0x02,0xd2, 0x00,0x00,0x00,0x01,0x01,0x43,0x00,0x00,0x00,0x01,0xff,0x1e,0x00,0x00,0x00,0x01,0x02,0x2b,0x00,0x00,0x00,0x01,0x03,0xec,0x00,0x00,0x00,0x01,0x03,0x38,0x00,0x00,0x00,0x01,0x02,0xe6,0x00,0x00,0x00,0x01,0xff,0xd7,0x00,0x00,0x00,0x01,0x00,0x59,0x00,0x00,0x00,0x01,0x01,0x04,0x00,0x00,0x00,0x01,0x02,0xbf,0x00,0x00,0x00,0x01, 0x04,0xe3,0x00,0x00,0x00,0x01,0x03,0xf1,0x00,0x00,0x00,0x01,0x02,0xbe,0x00,0x00,0x00,0x01,0x04,0xe9,0x00,0x00,0x00,0x01,0x03,0xf7,0x00,0x00,0x00,0x01,0x01,0xab,0x00,0x00,0x00,0x01,0x00,0x62,0x00,0x00,0x00,0x01,0x01,0x6a,0x00,0x00,0x00,0x01,0x02,0xec,0x00,0x00,0x00,0x01,0x01,0x96,0x00,0x00,0x00,0x01,0x01,0x1b,0x00,0x00, 0x00,0x01,0x01,0x39,0x00,0x00,0x00,0x01,0x00,0xdc,0x00,0x00,0x00,0x01,0x02,0xb3,0x00,0x00,0x00,0x01,0x04,0xd0,0x00,0x00,0x00,0x01,0x03,0xde,0x00,0x00,0x00,0x01,0x01,0x86,0x00,0x00,0x00,0x01,0x00,0xb3,0x00,0x00,0x00,0x01,0x02,0x71,0x00,0x00,0x00,0x01,0x04,0x2c,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x00,0x00,0x01,0x01,0x6c, 0x00,0x00,0x00,0x01,0x01,0x4e,0x00,0x00,0x00,0x01,0x00,0xb2,0x00,0x00,0x00,0x01,0x04,0x3a,0x00,0x00,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x01,0x5c,0x00,0x00,0x00,0x01,0x02,0x45,0x00,0x00,0x00,0x01,0x04,0x75,0x00,0x00,0x00,0x01,0x03,0x83,0x00,0x00,0x00,0x01,0x00,0x64,0x00,0x00,0x00,0x01,0x02,0x33,0x00,0x00,0x00,0x01, 0x04,0x04,0x00,0x00,0x00,0x01,0x02,0xd3,0x00,0x00,0x00,0x01,0x00,0xaa,0x00,0x00,0x00,0x01,0x02,0x5e,0x00,0x00,0x00,0x01,0x04,0x26,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x00,0x00,0x01,0x01,0x63,0x00,0x00,0x00,0x01,0x01,0x4f,0x00,0x00,0x00,0x01,0x01,0x0b,0x00,0x00,0x00,0x01,0x02,0xaf,0x00,0x00,0x00,0x01,0x04,0xd3,0x00,0x00, 0x00,0x01,0x03,0xcd,0x00,0x00,0x00,0x01,0x03,0x1f,0x00,0x00,0x00,0x01,0x05,0xd9,0x00,0x00,0x00,0x01,0x04,0xe5,0x00,0x00,0x00,0x01,0x01,0x77,0x00,0x00,0x00,0x01,0x02,0xf4,0x00,0x00,0x00,0x01,0x05,0x24,0x00,0x00,0x00,0x01,0x04,0x32,0x00,0x00,0x00,0x01,0x02,0x17,0x00,0x00,0x00,0x01,0x03,0x71,0x00,0x00,0x00,0x01,0x02,0x7f, 0x00,0x00,0x00,0x01,0xff,0x1e,0x01,0x04,0x00,0x01,0xff,0xd7,0x00,0xdc,0x00,0x01,0x00,0x59,0x00,0xf0,0x00,0x01,0x02,0x29,0x00,0x00,0x00,0x01,0x03,0x96,0x00,0x00,0x00,0x01,0x02,0xa4,0x00,0x00,0x00,0x01,0x07,0x17,0x00,0x00,0x00,0x01,0x02,0xf1,0x00,0x00,0x00,0x01,0x05,0xca,0x00,0x00,0x00,0x01,0xff,0x26,0x00,0x00,0x00,0x01, 0x03,0x4e,0x00,0x00,0x00,0x01,0x01,0x77,0x00,0xdc,0x00,0x01,0x00,0x75,0x00,0x00,0x00,0x01,0x00,0xe3,0x00,0x00,0x00,0x01,0x01,0x9c,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x01,0x02,0x82,0x00,0x00,0x00,0x01,0x01,0x52,0x00,0x00,0x00,0x01,0x01,0x83,0x00,0x00,0x00,0x01,0x01,0x8d,0x00,0x00,0x00,0x01,0x00,0x94,0x00,0x00, 0x00,0x01,0x01,0x7f,0x00,0x00,0x00,0x01,0xff,0x7a,0x00,0x00,0x00,0x01,0x02,0xa7,0x00,0x00,0x00,0x01,0x01,0x12,0x00,0xf0,0x00,0x01,0x01,0x5a,0x00,0x00,0x00,0x01,0x01,0x3d,0x00,0xdc,0x00,0x01,0x00,0xc9,0x00,0x00,0x00,0x01,0xff,0x81,0x00,0x00,0x00,0x01,0x01,0xeb,0x00,0xdc,0x00,0x01,0x04,0x54,0x00,0x00,0x00,0x01,0x03,0x07, 0x00,0x00,0x00,0x01,0x00,0x3a,0x00,0x00,0x00,0x01,0xff,0x5e,0x00,0x00,0x00,0x01,0x01,0xc8,0x00,0xdc,0x00,0x01,0x04,0x31,0x00,0x00,0x00,0x01,0x02,0xe4,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0xad,0x00,0x00,0x00,0x01,0xff,0xdb,0x00,0x00,0x00,0x01,0x02,0x45,0x00,0xdc,0x00,0x01,0x04,0xae,0x00,0x00,0x00,0x01, 0x01,0x2a,0x00,0x00,0x00,0x01,0x02,0x91,0x00,0x00,0x00,0x01,0x04,0x8a,0x00,0x00,0x00,0x01,0x03,0x39,0x00,0x00,0x00,0x01,0x03,0x98,0x00,0x00,0x00,0x01,0x00,0xd6,0x00,0x00,0x00,0x01,0x01,0xe0,0x00,0x00,0x00,0x01,0x02,0x0b,0x00,0x00,0x00,0x01,0x01,0x7d,0x00,0x00,0x00,0x01,0xff,0x36,0x00,0x00,0x00,0x01,0x01,0xa0,0x00,0xdc, 0x00,0x01,0x04,0x09,0x00,0x00,0x00,0x01,0x02,0xbc,0x00,0x00,0x00,0x01,0xff,0xef,0x00,0x00,0x00,0x01,0x00,0x85,0x00,0x00,0x00,0x01,0x00,0x44,0x00,0x00,0x00,0x01,0x02,0xae,0x00,0xdc,0x00,0x01,0x05,0x17,0x00,0x00,0x00,0x01,0x00,0xfd,0x00,0x00,0x00,0x01,0x01,0x93,0x00,0x00,0x00,0x01,0x02,0xf4,0x00,0xdc,0x00,0x01,0x05,0x5d, 0x00,0x00,0x00,0x01,0x02,0x86,0x00,0x00,0x00,0x01,0x03,0x99,0x00,0x00,0x00,0x01,0x02,0x35,0x00,0x00,0x00,0x01,0x03,0x36,0x00,0x00,0x00,0x01,0x01,0xac,0x00,0x00,0x00,0x01,0x02,0x2c,0x00,0x00,0x00,0x01,0x02,0x02,0x00,0x00,0x00,0x01,0x02,0xb9,0x00,0x00,0x00,0x01,0x01,0x6f,0x00,0x00,0x00,0x01,0x03,0xca,0x00,0x00,0x00,0x01, 0x02,0xb6,0x00,0x00,0x00,0x01,0x04,0x11,0x00,0x00,0x00,0x01,0x01,0xa5,0x00,0x00,0x00,0x01,0x03,0xb9,0x00,0x00,0x00,0x01,0x01,0xc9,0x00,0x00,0x00,0x01,0x02,0xdd,0x00,0x00,0x00,0x01,0x03,0xf0,0x00,0x00,0x00,0x01,0x03,0xf8,0x00,0x00,0x00,0x01,0xff,0xb0,0x00,0x00,0x00,0x01,0x01,0x53,0x00,0x00,0x00,0x01,0x03,0xdf,0x00,0x00, 0x00,0x01,0x02,0x64,0x00,0x00,0x00,0x01,0x03,0x3b,0x00,0x00,0x00,0x01,0x02,0x2d,0x00,0x00,0x00,0x01,0x04,0x25,0x00,0x00,0x00,0x01,0x02,0x4b,0x00,0x00,0x00,0x01,0x03,0x84,0x00,0x00,0x00,0x01,0x00,0xce,0x00,0x00,0x00,0x01,0x02,0x0a,0x00,0x00,0x00,0x01,0x02,0xed,0x00,0x00,0x00,0x01,0x03,0xba,0x00,0x00,0x00,0x01,0x03,0x77, 0x00,0x00,0x00,0x01,0x02,0xff,0x00,0x00,0x00,0x01,0x04,0x51,0x00,0x00,0x00,0x01,0x02,0xfa,0x00,0x00,0x00,0x01,0x04,0x33,0x00,0x00,0x00,0x01,0x02,0x80,0x00,0x00,0x00,0x01,0x02,0xa5,0x00,0x00,0x00,0x01,0x02,0x41,0x00,0x00,0x00,0x01,0x03,0xd0,0x00,0x00,0x00,0x01,0x01,0xb0,0x00,0x00,0x00,0x01,0x03,0xf2,0x00,0x00,0x00,0x01, 0x03,0xb2,0x00,0x00,0x00,0x01,0x02,0x24,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01,0xfe,0xac,0x00,0x00,0x00,0x01,0xff,0xce,0x00,0x00,0x00,0x01,0xff,0xd8,0x00,0x00,0x00,0x01,0xff,0xf6,0x00,0x00,0x00,0x01,0xff,0x74,0x00,0x00,0x00,0x01,0xfe,0xf2,0x00,0x00,0x00,0x01,0xfe,0xca,0x00,0x00,0x00,0x01,0x02,0x3a,0x00,0x00, 0x00,0x01,0x02,0x44,0x00,0x00,0x00,0x01,0xff,0x06,0x00,0x00,0x00,0x01,0x01,0x9a,0x00,0x00,0x00,0x01,0x02,0x4e,0x00,0x00,0x00,0x01,0xff,0x6a,0x00,0x00,0x00,0x01,0xfe,0xa2,0x00,0x00,0x00,0x01,0xff,0x1a,0x00,0x00,0x00,0x01,0xfe,0xe8,0x00,0x00,0x00,0x01,0xfd,0xd0,0x00,0x00,0x00,0x01,0xfd,0x76,0x00,0x00,0x00,0x01,0xfe,0x34, 0x00,0x00,0x00,0x01,0xfd,0x44,0x00,0x00,0x00,0x01,0xfd,0x1c,0x00,0x00,0x00,0x01,0xfe,0x2a,0x00,0x00,0x00,0x01,0xfe,0x52,0x00,0x00,0x00,0x01,0xfd,0x12,0x00,0x00,0x00,0x01,0xfe,0x66,0x00,0x00,0x00,0x01,0xfd,0x80,0x00,0x00,0x00,0x01,0xfd,0x62,0x00,0x00,0x00,0x01,0xfe,0x3e,0x00,0x00,0x00,0x01,0xfd,0xe4,0x00,0x00,0x00,0x01, 0xfd,0x3a,0x00,0x00,0x00,0x01,0xfe,0x5c,0x00,0x00,0x00,0x01,0xfd,0x4e,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x14,0x00,0x00,0x00,0x01,0xfe,0xd4,0x00,0x00,0x00,0x01,0xfe,0xc0,0x00,0x00,0x00,0x01,0xfe,0x70,0x00,0x00,0x00,0x01,0xfd,0xda,0x00,0x00,0x00,0x01,0xfd,0xc6,0x00,0x00, 0x00,0x01,0xfe,0x20,0x00,0x00,0x00,0x01,0xfe,0x8e,0x00,0x00,0x00,0x01,0xfd,0xf8,0x00,0x00,0x00,0x01,0xfe,0x16,0x00,0x00,0x00,0x01,0xfd,0xbc,0x00,0x00,0x00,0x01,0xfe,0x02,0x00,0x00,0x00,0x01,0xff,0xe2,0x00,0x00,0x00,0x01,0x00,0xfa,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x00,0x00,0x01,0xfd,0xf1,0x00,0x00,0x00,0x01,0xfd,0x8a, 0x00,0x00,0x00,0x01,0xfd,0xa8,0x00,0x00,0x00,0x01,0xfc,0xe0,0x00,0x00,0x00,0x01,0xfe,0x0c,0x00,0x00,0x00,0x01,0xfd,0xee,0x00,0x00,0x00,0x01,0x02,0x66,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0a,0x02,0xbc,0x0a,0x6a,0x00,0x15,0x61,0x72,0x61,0x62,0x00,0x80,0x62,0x6e,0x67,0x32,0x01,0x3c,0x63,0x79,0x72,0x6c,0x01,0x48,0x64,0x65, 0x76,0x32,0x01,0x70,0x67,0x6a,0x72,0x32,0x01,0xa4,0x67,0x72,0x65,0x6b,0x01,0x7c,0x67,0x75,0x72,0x32,0x01,0xb0,0x68,0x65,0x62,0x72,0x01,0xbc,0x6b,0x68,0x6d,0x72,0x01,0xd8,0x6b,0x6e,0x64,0x32,0x01,0xcc,0x6c,0x61,0x6f,0x20,0x01,0xe4,0x6c,0x61,0x74,0x6e,0x01,0xf0,0x6d,0x6c,0x6d,0x32,0x02,0x46,0x6d,0x6f,0x6e,0x67,0x02,0x52, 0x6d,0x79,0x6d,0x72,0x02,0x5e,0x6f,0x72,0x79,0x32,0x02,0x76,0x74,0x61,0x6c,0x75,0x02,0x6a,0x74,0x65,0x6c,0x32,0x02,0x8e,0x74,0x68,0x61,0x69,0x02,0x9a,0x74,0x69,0x62,0x74,0x02,0xa6,0x74,0x6d,0x6c,0x32,0x02,0x82,0x00,0x3c,0x00,0x05,0x41,0x52,0x41,0x20,0x00,0x22,0x4d,0x4c,0x59,0x20,0x00,0x54,0x4d,0x4f,0x52,0x20,0x00,0x6e, 0x53,0x4e,0x44,0x20,0x00,0x88,0x55,0x52,0x44,0x20,0x00,0xa2,0x00,0x00,0xff,0xff,0x00,0x0a,0x00,0x04,0x00,0x13,0x00,0x0a,0x00,0x28,0x00,0x2e,0x00,0x3d,0x00,0x4b,0x00,0x51,0x00,0x2f,0x00,0x1e,0x00,0x00,0xff,0xff,0x00,0x09,0x00,0x05,0x00,0x14,0x00,0x0b,0x00,0x29,0x00,0x3e,0x00,0x4c,0x00,0x52,0x00,0x30,0x00,0x1f,0x00,0x00, 0xff,0xff,0x00,0x0a,0x00,0x06,0x00,0x15,0x00,0x0c,0x00,0x2a,0x00,0x39,0x00,0x3f,0x00,0x4d,0x00,0x53,0x00,0x31,0x00,0x20,0x00,0x00,0xff,0xff,0x00,0x0a,0x00,0x07,0x00,0x16,0x00,0x0d,0x00,0x2b,0x00,0x3a,0x00,0x40,0x00,0x4e,0x00,0x54,0x00,0x32,0x00,0x21,0x00,0x00,0xff,0xff,0x00,0x0a,0x00,0x08,0x00,0x17,0x00,0x0e,0x00,0x2c, 0x00,0x3b,0x00,0x41,0x00,0x4f,0x00,0x55,0x00,0x33,0x00,0x22,0x00,0x00,0xff,0xff,0x00,0x0a,0x00,0x09,0x00,0x18,0x00,0x0f,0x00,0x2d,0x00,0x3c,0x00,0x42,0x00,0x50,0x00,0x56,0x00,0x34,0x00,0x23,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x78,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x0f,0x00,0x19,0x00,0x24, 0x00,0x35,0x00,0x43,0x00,0x47,0x00,0x5c,0x00,0x00,0x00,0x58,0x00,0x60,0x00,0x64,0x00,0x68,0x00,0x6c,0x00,0x70,0x00,0x74,0x00,0x79,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x7a,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x0f,0x00,0x1a,0x00,0x25,0x00,0x36,0x00,0x44,0x00,0x48,0x00,0x5d,0x00,0x01,0x00,0x59, 0x00,0x61,0x00,0x65,0x00,0x69,0x00,0x6d,0x00,0x71,0x00,0x75,0x00,0x7b,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x7c,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x7d,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x03,0x00,0x1b,0x00,0x10,0x00,0x57,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01, 0x00,0x7e,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x7f,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x80,0x00,0x0a,0x00,0x01,0x54,0x52,0x4b,0x20,0x00,0x30,0x00,0x00,0xff,0xff,0x00,0x10,0x00,0x1c,0x00,0x26,0x00,0x11,0x00,0x37,0x00,0x45,0x00,0x49,0x00,0x5e,0x00,0x02,0x00,0x5a,0x00,0x62,0x00,0x66, 0x00,0x6a,0x00,0x6e,0x00,0x72,0x00,0x76,0x00,0x81,0x00,0x00,0xff,0xff,0x00,0x10,0x00,0x1d,0x00,0x27,0x00,0x12,0x00,0x38,0x00,0x46,0x00,0x4a,0x00,0x5f,0x00,0x03,0x00,0x5b,0x00,0x63,0x00,0x67,0x00,0x6b,0x00,0x6f,0x00,0x73,0x00,0x77,0x00,0x82,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x83,0x00,0x04,0x00,0x00, 0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x84,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x85,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x86,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x87,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x88,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff, 0x00,0x01,0x00,0x89,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x8a,0x00,0x04,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x01,0x00,0x8b,0x00,0x8c,0x63,0x32,0x73,0x63,0x03,0x4a,0x63,0x32,0x73,0x63,0x03,0x50,0x63,0x32,0x73,0x63,0x03,0x56,0x63,0x32,0x73,0x63,0x03,0x60,0x63,0x61,0x6c,0x74,0x03,0x6a,0x63,0x61,0x6c,0x74, 0x03,0x70,0x63,0x61,0x6c,0x74,0x03,0x76,0x63,0x61,0x6c,0x74,0x03,0x7c,0x63,0x61,0x6c,0x74,0x03,0x82,0x63,0x61,0x6c,0x74,0x03,0x88,0x63,0x63,0x6d,0x70,0x03,0x8e,0x63,0x63,0x6d,0x70,0x03,0x98,0x63,0x63,0x6d,0x70,0x03,0xaa,0x63,0x63,0x6d,0x70,0x03,0xb4,0x63,0x63,0x6d,0x70,0x03,0xbe,0x63,0x63,0x6d,0x70,0x03,0xc8,0x63,0x63, 0x6d,0x70,0x03,0xda,0x63,0x63,0x6d,0x70,0x04,0x0c,0x63,0x63,0x6d,0x70,0x04,0x1a,0x64,0x6c,0x69,0x67,0x04,0x24,0x64,0x6c,0x69,0x67,0x04,0x2a,0x64,0x6c,0x69,0x67,0x04,0x30,0x64,0x6c,0x69,0x67,0x04,0x36,0x64,0x6c,0x69,0x67,0x04,0x3c,0x64,0x6c,0x69,0x67,0x04,0x42,0x64,0x6c,0x69,0x67,0x04,0x48,0x64,0x6c,0x69,0x67,0x04,0x4e, 0x64,0x6c,0x69,0x67,0x04,0x54,0x64,0x6c,0x69,0x67,0x04,0x5a,0x64,0x6c,0x69,0x67,0x04,0x62,0x66,0x69,0x6e,0x61,0x04,0x68,0x66,0x69,0x6e,0x61,0x04,0x6e,0x66,0x69,0x6e,0x61,0x04,0x74,0x66,0x69,0x6e,0x61,0x04,0x7a,0x66,0x69,0x6e,0x61,0x04,0x80,0x66,0x69,0x6e,0x61,0x04,0x86,0x66,0x72,0x61,0x63,0x04,0x8c,0x66,0x72,0x61,0x63, 0x04,0x96,0x66,0x72,0x61,0x63,0x04,0xa0,0x66,0x72,0x61,0x63,0x04,0xaa,0x69,0x6e,0x69,0x74,0x04,0xb4,0x69,0x6e,0x69,0x74,0x04,0xba,0x69,0x6e,0x69,0x74,0x04,0xc0,0x69,0x6e,0x69,0x74,0x04,0xc6,0x69,0x6e,0x69,0x74,0x04,0xcc,0x69,0x6e,0x69,0x74,0x04,0xd2,0x69,0x73,0x6f,0x6c,0x04,0xd8,0x6c,0x69,0x67,0x61,0x04,0xde,0x6c,0x69, 0x67,0x61,0x04,0xe8,0x6c,0x69,0x67,0x61,0x04,0xf2,0x6c,0x69,0x67,0x61,0x04,0xfa,0x6c,0x69,0x67,0x61,0x05,0x04,0x6c,0x69,0x67,0x61,0x05,0x0c,0x6c,0x6e,0x75,0x6d,0x05,0x16,0x6c,0x6e,0x75,0x6d,0x05,0x1e,0x6c,0x6e,0x75,0x6d,0x05,0x26,0x6c,0x6e,0x75,0x6d,0x05,0x2e,0x6c,0x6f,0x63,0x6c,0x05,0x36,0x6c,0x6f,0x63,0x6c,0x05,0x3c, 0x6c,0x6f,0x63,0x6c,0x05,0x42,0x6c,0x6f,0x63,0x6c,0x05,0x48,0x6d,0x65,0x64,0x69,0x05,0x4e,0x6d,0x65,0x64,0x69,0x05,0x54,0x6d,0x65,0x64,0x69,0x05,0x5a,0x6d,0x65,0x64,0x69,0x05,0x60,0x6d,0x65,0x64,0x69,0x05,0x66,0x6d,0x65,0x64,0x69,0x05,0x6c,0x6f,0x6e,0x75,0x6d,0x05,0x72,0x6f,0x6e,0x75,0x6d,0x05,0x7a,0x6f,0x6e,0x75,0x6d, 0x05,0x82,0x6f,0x6e,0x75,0x6d,0x05,0x8a,0x70,0x6e,0x75,0x6d,0x05,0x92,0x70,0x6e,0x75,0x6d,0x05,0x9a,0x70,0x6e,0x75,0x6d,0x05,0xa2,0x70,0x6e,0x75,0x6d,0x05,0xaa,0x72,0x63,0x6c,0x74,0x05,0xb2,0x72,0x63,0x6c,0x74,0x05,0xb8,0x72,0x63,0x6c,0x74,0x05,0xbe,0x72,0x63,0x6c,0x74,0x05,0xc4,0x72,0x63,0x6c,0x74,0x05,0xca,0x72,0x63, 0x6c,0x74,0x05,0xd0,0x72,0x6c,0x69,0x67,0x05,0xd6,0x72,0x6c,0x69,0x67,0x05,0xde,0x72,0x6c,0x69,0x67,0x05,0xe6,0x72,0x6c,0x69,0x67,0x05,0xee,0x72,0x6c,0x69,0x67,0x05,0xf6,0x72,0x6c,0x69,0x67,0x05,0xfe,0x72,0x6c,0x69,0x67,0x06,0x06,0x73,0x61,0x6c,0x74,0x06,0x0c,0x73,0x61,0x6c,0x74,0x06,0x18,0x73,0x61,0x6c,0x74,0x06,0x24, 0x73,0x61,0x6c,0x74,0x06,0x30,0x73,0x6d,0x63,0x70,0x06,0x3c,0x73,0x6d,0x63,0x70,0x06,0x42,0x73,0x6d,0x63,0x70,0x06,0x48,0x73,0x6d,0x63,0x70,0x06,0x54,0x73,0x73,0x30,0x31,0x06,0x60,0x73,0x73,0x30,0x31,0x06,0x66,0x73,0x73,0x30,0x31,0x06,0x6c,0x73,0x73,0x30,0x31,0x06,0x72,0x73,0x73,0x31,0x38,0x06,0x78,0x73,0x73,0x31,0x38, 0x06,0x80,0x73,0x73,0x31,0x38,0x06,0x88,0x73,0x73,0x31,0x38,0x06,0x90,0x73,0x73,0x31,0x39,0x06,0x98,0x73,0x73,0x31,0x39,0x06,0x9e,0x73,0x73,0x31,0x39,0x06,0xa4,0x73,0x73,0x31,0x39,0x06,0xaa,0x73,0x73,0x32,0x30,0x06,0xb0,0x73,0x73,0x32,0x30,0x06,0xba,0x73,0x73,0x32,0x30,0x06,0xc4,0x73,0x73,0x32,0x30,0x06,0xce,0x73,0x75, 0x62,0x73,0x06,0xd8,0x73,0x75,0x62,0x73,0x06,0xde,0x73,0x75,0x62,0x73,0x06,0xe4,0x73,0x75,0x62,0x73,0x06,0xea,0x73,0x75,0x70,0x73,0x06,0xf0,0x73,0x75,0x70,0x73,0x06,0xf6,0x73,0x75,0x70,0x73,0x06,0xfc,0x73,0x75,0x70,0x73,0x07,0x02,0x74,0x6e,0x75,0x6d,0x07,0x08,0x74,0x6e,0x75,0x6d,0x07,0x0e,0x74,0x6e,0x75,0x6d,0x07,0x16, 0x74,0x6e,0x75,0x6d,0x07,0x1c,0x74,0x6e,0x75,0x6d,0x07,0x24,0x74,0x6e,0x75,0x6d,0x07,0x2a,0x74,0x6e,0x75,0x6d,0x07,0x30,0x74,0x6e,0x75,0x6d,0x07,0x36,0x74,0x6e,0x75,0x6d,0x07,0x3c,0x74,0x6e,0x75,0x6d,0x07,0x42,0x74,0x6e,0x75,0x6d,0x07,0x6e,0x74,0x6e,0x75,0x6d,0x07,0x76,0x74,0x6e,0x75,0x6d,0x07,0x7c,0x74,0x6e,0x75,0x6d, 0x07,0x82,0x74,0x6e,0x75,0x6d,0x07,0x8a,0x74,0x6e,0x75,0x6d,0x07,0x90,0x74,0x6e,0x75,0x6d,0x07,0x96,0x74,0x6e,0x75,0x6d,0x07,0x9c,0x74,0x6e,0x75,0x6d,0x07,0xa2,0x74,0x6e,0x75,0x6d,0x07,0xa8,0x00,0x00,0x00,0x01,0x00,0x1d,0x00,0x00,0x00,0x01,0x00,0x1f,0x00,0x00,0x00,0x03,0x00,0x1d,0x00,0x1f,0x00,0x21,0x00,0x00,0x00,0x03, 0x00,0x1d,0x00,0x1f,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x03,0x00,0x05,0x00,0x08,0x00,0x0c,0x00,0x00,0x00,0x07,0x00,0x05,0x00,0x08,0x00,0x09,0x00,0x0a, 0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x00,0x00,0x03,0x00,0x05,0x00,0x08,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x05,0x00,0x08,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x05,0x00,0x08,0x00,0x0c,0x00,0x00,0x00,0x07,0x00,0x05,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x00,0x00,0x17,0x00,0x4e,0x00,0x4f,0x00,0x50, 0x00,0x51,0x00,0x52,0x00,0x53,0x00,0x54,0x00,0x55,0x00,0x56,0x00,0x57,0x00,0x58,0x00,0x59,0x00,0x5a,0x00,0x5b,0x00,0x5c,0x00,0x5d,0x00,0x5e,0x00,0x5f,0x00,0x60,0x00,0x61,0x00,0x62,0x00,0x63,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x18,0x00,0x19,0x00,0x1a,0x00,0x39,0x00,0x3a,0x00,0x00,0x00,0x03,0x00,0x18,0x00,0x19,0x00,0x1a, 0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x25,0x00,0x00,0x00,0x01,0x00,0x25,0x00,0x00,0x00,0x01,0x00,0x4d,0x00,0x00,0x00,0x02,0x00,0x25,0x00,0x26,0x00,0x00, 0x00,0x01,0x00,0x25,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x00,0x00,0x03,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x00,0x00,0x03, 0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x00,0x00,0x03,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x13, 0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x13,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x13,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x2f,0x00,0x31,0x00,0x00,0x00,0x02,0x00,0x2f, 0x00,0x31,0x00,0x00,0x00,0x02,0x00,0x2f,0x00,0x31,0x00,0x00,0x00,0x02,0x00,0x2f,0x00,0x31,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01, 0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x00,0x02,0x00,0x2a,0x00,0x2b,0x00,0x00,0x00,0x02,0x00,0x2a,0x00,0x2b,0x00,0x00,0x00,0x02,0x00,0x2a,0x00,0x2b,0x00,0x00,0x00,0x02,0x00,0x2a,0x00,0x2b,0x00,0x00,0x00,0x02,0x00,0x2c,0x00,0x2e,0x00,0x00,0x00,0x02,0x00,0x2c,0x00,0x2e,0x00,0x00, 0x00,0x02,0x00,0x2c,0x00,0x2e,0x00,0x00,0x00,0x02,0x00,0x2c,0x00,0x2e,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x11, 0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x11,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x4e,0x00,0x00,0x00,0x04,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x00,0x00,0x04,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37, 0x00,0x00,0x00,0x04,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x00,0x00,0x04,0x00,0x34,0x00,0x35,0x00,0x36,0x00,0x37,0x00,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x04,0x00,0x1e,0x00,0x20,0x00,0x22,0x00,0x23,0x00,0x00,0x00,0x04,0x00,0x1e,0x00,0x20,0x00,0x22,0x00,0x24,0x00,0x00,0x00,0x01, 0x00,0x35,0x00,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x00,0x01,0x00,0x35,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x33,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x33,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x33,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x36,0x00,0x00,0x00,0x01,0x00,0x36, 0x00,0x00,0x00,0x01,0x00,0x36,0x00,0x00,0x00,0x01,0x00,0x36,0x00,0x00,0x00,0x03,0x00,0x34,0x00,0x37,0x00,0x38,0x00,0x00,0x00,0x03,0x00,0x34,0x00,0x37,0x00,0x38,0x00,0x00,0x00,0x03,0x00,0x34,0x00,0x37,0x00,0x38,0x00,0x00,0x00,0x03,0x00,0x34,0x00,0x37,0x00,0x38,0x00,0x00,0x00,0x01,0x00,0x1b,0x00,0x00,0x00,0x01,0x00,0x1b, 0x00,0x00,0x00,0x01,0x00,0x1b,0x00,0x00,0x00,0x01,0x00,0x1b,0x00,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x3d,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0x3b,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x30, 0x00,0x00,0x00,0x01,0x00,0x3e,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x01,0x00,0x49,0x00,0x00,0x00,0x01,0x00,0x45,0x00,0x00,0x00,0x14,0x00,0x2d,0x00,0x30,0x00,0x3b,0x00,0x3c,0x00,0x3d,0x00,0x3e,0x00,0x3f,0x00,0x40,0x00,0x41,0x00,0x42,0x00,0x43,0x00,0x44,0x00,0x45,0x00,0x46,0x00,0x47, 0x00,0x48,0x00,0x49,0x00,0x4a,0x00,0x4b,0x00,0x4c,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0x43,0x00,0x00,0x00,0x01,0x00,0x4a,0x00,0x00,0x00,0x02,0x00,0x47,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x00,0x01,0x00,0x3f,0x00,0x00,0x00,0x01,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x41,0x00,0x00, 0x00,0x01,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x46,0x00,0x84,0x01,0x0a,0x01,0x1a,0x01,0x2a,0x01,0x3a,0x01,0x4a,0x01,0x64,0x01,0x74,0x01,0x84,0x01,0x94,0x01,0xb8,0x01,0xe6,0x02,0x00,0x02,0x1a,0x02,0x2a,0x02,0x44,0x02,0x54,0x02,0x64,0x02,0x74,0x02,0x84,0x02,0x94,0x02,0xa4,0x02,0xb4,0x02,0xc4,0x02,0xd4,0x02,0xf8,0x03,0x08, 0x03,0x18,0x03,0x28,0x03,0x38,0x03,0x48,0x03,0x58,0x03,0x68,0x03,0x78,0x03,0x88,0x03,0x98,0x03,0xa8,0x03,0xb8,0x03,0xc8,0x03,0xd8,0x03,0xe8,0x03,0xf8,0x04,0x08,0x04,0x18,0x04,0x28,0x04,0x38,0x04,0x48,0x04,0x58,0x04,0x68,0x04,0x78,0x04,0x88,0x04,0x98,0x04,0xa8,0x04,0xb8,0x04,0xc8,0x04,0xd8,0x04,0xe8,0x04,0xf8,0x05,0x08, 0x05,0x18,0x05,0x28,0x05,0x38,0x05,0x48,0x05,0x58,0x05,0x68,0x05,0x78,0x05,0x88,0x05,0x98,0x05,0xa8,0x05,0xb8,0x05,0xc8,0x05,0xd8,0x05,0xe8,0x05,0xf8,0x06,0x08,0x06,0x18,0x06,0x28,0x06,0x38,0x06,0x48,0x06,0x58,0x06,0x68,0x06,0x96,0x07,0xbe,0x07,0xce,0x07,0xde,0x07,0xee,0x07,0xfe,0x08,0x0e,0x08,0x1e,0x08,0x2e,0x08,0x3e, 0x08,0x4e,0x08,0x5e,0x08,0x6e,0x08,0x7e,0x08,0x8e,0x09,0x84,0x09,0x94,0x09,0xa4,0x0a,0x72,0x0a,0x82,0x0a,0x92,0x0b,0x06,0x0b,0x98,0x0b,0xa8,0x0b,0xb8,0x0b,0xc8,0x0b,0xd8,0x0b,0xe8,0x0b,0xf8,0x0c,0x08,0x0c,0x18,0x0c,0x28,0x0c,0x38,0x0c,0x48,0x0c,0x58,0x0c,0x68,0x0c,0x78,0x0c,0x88,0x0c,0x98,0x0c,0xa8,0x0c,0xb8,0x0c,0xc8, 0x0c,0xd8,0x0c,0xe8,0x0c,0xf8,0x0d,0x08,0x0d,0x18,0x0d,0x28,0x0d,0x38,0x0d,0x48,0x0d,0x58,0x0d,0x68,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x0c,0x66,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x0c,0x80,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01, 0x00,0x00,0x0c,0x7e,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x0c,0x80,0x00,0x07,0x00,0x09,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01,0x00,0x06,0x00,0x00,0x0c,0x92,0x00,0x01,0x00,0x06,0x00,0x00,0x0c,0x98,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x11,0x58,0x00,0x07, 0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x12,0x72,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x12,0x82,0x00,0x07,0x00,0x09,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x06,0x00,0x00,0x12,0xc6,0x00,0x01,0x00,0x06,0x00,0x00,0x12,0xd0,0x00,0x01,0x00,0x06,0x00,0x00, 0x12,0xdc,0x00,0x07,0x00,0x09,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0x0a,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0x14,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0x20,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0x2e,0x00,0x07,0x00,0x01,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01,0x00,0x06,0x00,0x00, 0x13,0x6a,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0x74,0x00,0x07,0x00,0x01,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0xa2,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0xac,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x13,0xde,0x00,0x07,0x00,0x09,0x00,0x02,0x00,0x0a,0x00,0x12,0x00,0x01, 0x00,0x06,0x00,0x00,0x14,0x0e,0x00,0x01,0x00,0x06,0x00,0x00,0x14,0x1c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x14,0x44,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x19,0x4e,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x1d,0x54,0x00,0x07, 0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x21,0x62,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x21,0xc6,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x22,0x00,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x22,0x68,0x00,0x07, 0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x22,0xa2,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x23,0xcc,0x00,0x07,0x01,0x01,0x00,0x03,0x00,0x0c,0x00,0x14,0x00,0x1c,0x00,0x01,0x00,0x06,0x00,0x00,0x24,0x5c,0x00,0x01,0x00,0x06,0x00,0x00,0x27,0x74,0x00,0x01,0x00,0x06,0x00,0x00, 0x27,0x80,0x00,0x07,0x02,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x2f,0x74,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x2f,0xf6,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x35,0x5a,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x36,0xf2,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x37,0x06,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x37,0x2a,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x37,0x94,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x37,0xfe,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x38,0x52,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x38,0xa8,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3b,0x78,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x3e,0x4c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3e,0x4a,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x3e,0x48,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x3e,0x62,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x3e,0x82,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x3e,0x80,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3e,0x9c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3e,0xb0,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x3e,0xc4,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3e,0xd8,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3e,0xec,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3f,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x3f,0x14,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3f,0x28,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x3f,0x3c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x3f,0x50,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x3f,0xf6,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x41,0x0c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x41,0x62,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x42,0x9a,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x43,0x42,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x43,0x40,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x43,0x48,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x43,0xd2,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x44,0x5c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0x70,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0x84,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0x98,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x44,0xac,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0xc0,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0xd4,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x44,0xe8,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x44,0xfc,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x10,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x24,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x38,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x45,0x4c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x60,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x74,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0x88,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x45,0x9c,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x45,0xb0,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x45,0xc4,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x45,0xcc,0x00,0x07,0x00,0x01,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x26, 0x00,0x01,0x00,0x06,0x00,0x00,0x45,0xd0,0x00,0x01,0x00,0x06,0x00,0x00,0x45,0xda,0x00,0x01,0x00,0x06,0x00,0x00,0x45,0xe6,0x00,0x01,0x00,0x06,0x00,0x00,0x45,0xf2,0x00,0x07,0x00,0x01,0x00,0x1d,0x00,0x40,0x00,0x48,0x00,0x50,0x00,0x58,0x00,0x60,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00,0x90,0x00,0x98,0x00,0xa0, 0x00,0xa8,0x00,0xb0,0x00,0xb8,0x00,0xc0,0x00,0xc8,0x00,0xd0,0x00,0xd8,0x00,0xe0,0x00,0xe8,0x00,0xf0,0x00,0xf8,0x01,0x00,0x01,0x08,0x01,0x10,0x01,0x18,0x01,0x20,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x44,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x52,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x62,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x72, 0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x84,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x90,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0x9e,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0xac,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0xbc,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0xcc,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0xde,0x00,0x01,0x00,0x06,0x00,0x00,0x46,0xee, 0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x0c,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x1a,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x2a,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x3a,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x48,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x58,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x6a, 0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x7c,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x8a,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0x9a,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0xaa,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0xba,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0xcc,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0xde,0x00,0x01,0x00,0x06,0x00,0x00,0x47,0xf2, 0x00,0x01,0x00,0x06,0x00,0x00,0x48,0x04,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x48,0xde,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x48,0xdc,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x48,0xe8,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0x49,0x0c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x49,0x36,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x4a,0xd6,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x4b,0x0c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0x4b,0x1c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x59,0xc8,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x5a,0x70,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x5b,0xe2,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08, 0x00,0x01,0x00,0x04,0x00,0x00,0x5c,0x08,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x5c,0x10,0x00,0x07,0x00,0x01,0x00,0x18,0x00,0x36,0x00,0x3e,0x00,0x46,0x00,0x4e,0x00,0x56,0x00,0x5e,0x00,0x66,0x00,0x6e,0x00,0x76,0x00,0x7e,0x00,0x86,0x00,0x8e,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6, 0x00,0xbe,0x00,0xc6,0x00,0xce,0x00,0xd6,0x00,0xde,0x00,0xe6,0x00,0xee,0x00,0x01,0x00,0x06,0x00,0x00,0x5b,0xe0,0x00,0x01,0x00,0x06,0x00,0x00,0x5b,0xec,0x00,0x01,0x00,0x06,0x00,0x00,0x5b,0xfa,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x0a,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x1c,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x2a,0x00,0x01, 0x00,0x06,0x00,0x00,0x5c,0x3a,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x4c,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x60,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x6c,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x7a,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x8a,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0x9c,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0xaa,0x00,0x01, 0x00,0x06,0x00,0x00,0x5c,0xb8,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0xc8,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0xd8,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0xea,0x00,0x01,0x00,0x06,0x00,0x00,0x5c,0xfc,0x00,0x01,0x00,0x06,0x00,0x00,0x5d,0x10,0x00,0x01,0x00,0x06,0x00,0x00,0x5d,0x24,0x00,0x01,0x00,0x06,0x00,0x00,0x5d,0x30,0x00,0x01, 0x00,0x06,0x00,0x00,0x5d,0x3e,0x00,0x01,0x00,0x06,0x00,0x00,0x5d,0x4a,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x1c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x5e,0x3a,0x00,0x07,0x00,0x01,0x00,0x14,0x00,0x2e,0x00,0x36,0x00,0x3e,0x00,0x46,0x00,0x4e,0x00,0x56, 0x00,0x5e,0x00,0x66,0x00,0x6e,0x00,0x76,0x00,0x7e,0x00,0x86,0x00,0x8e,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6,0x00,0xbe,0x00,0xc6,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x24,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x34,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x42,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x52,0x00,0x01,0x00,0x06, 0x00,0x00,0x5e,0x60,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x70,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x7e,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x8e,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0x9c,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0xac,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0xba,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0xca,0x00,0x01,0x00,0x06, 0x00,0x00,0x5e,0xd8,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0xe8,0x00,0x01,0x00,0x06,0x00,0x00,0x5e,0xf6,0x00,0x01,0x00,0x06,0x00,0x00,0x5f,0x06,0x00,0x01,0x00,0x06,0x00,0x00,0x5f,0x14,0x00,0x01,0x00,0x06,0x00,0x00,0x5f,0x24,0x00,0x01,0x00,0x06,0x00,0x00,0x5f,0x32,0x00,0x01,0x00,0x06,0x00,0x00,0x5f,0x42,0x00,0x07,0x00,0x01, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x06,0x00,0x00,0x60,0x46,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x60,0xc4,0x00,0x07,0x00,0x01,0x00,0x0b,0x00,0x1c,0x00,0x24,0x00,0x2c,0x00,0x34,0x00,0x3c,0x00,0x44,0x00,0x4c,0x00,0x54,0x00,0x5c,0x00,0x64,0x00,0x6c,0x00,0x01,0x00,0x06,0x00,0x00,0x60,0xec, 0x00,0x01,0x00,0x06,0x00,0x00,0x60,0xfc,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x0c,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x1a,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x28,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x36,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x44,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x52,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x60, 0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x6e,0x00,0x01,0x00,0x06,0x00,0x00,0x61,0x7c,0x00,0x07,0x00,0x01,0x00,0x0e,0x00,0x22,0x00,0x2a,0x00,0x32,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x6a,0x00,0x72,0x00,0x7a,0x00,0x82,0x00,0x8a,0x00,0x01,0x00,0x06,0x00,0x00,0x62,0x5e,0x00,0x01,0x00,0x06,0x00,0x00, 0x62,0x6a,0x00,0x01,0x00,0x06,0x00,0x00,0x63,0x06,0x00,0x01,0x00,0x06,0x00,0x00,0x63,0x2e,0x00,0x01,0x00,0x06,0x00,0x00,0x64,0x20,0x00,0x01,0x00,0x06,0x00,0x00,0x64,0x42,0x00,0x01,0x00,0x06,0x00,0x00,0x65,0x22,0x00,0x01,0x00,0x06,0x00,0x00,0x65,0x36,0x00,0x01,0x00,0x06,0x00,0x00,0x65,0xee,0x00,0x01,0x00,0x06,0x00,0x00, 0x66,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x66,0xb0,0x00,0x01,0x00,0x06,0x00,0x00,0x66,0xe0,0x00,0x01,0x00,0x06,0x00,0x00,0x67,0xd6,0x00,0x01,0x00,0x06,0x00,0x00,0x68,0x00,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x68,0xe2,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x68,0xe0,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x69,0x18,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x69,0x50,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x6a,0x0c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00, 0x6a,0xc8,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x6b,0x84,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6b,0xa8,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6b,0xea,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x6c,0x22,0x00,0x07,0x00,0x09,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6c,0xfe,0x00,0x07,0x01,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6d,0xc0,0x00,0x07,0x01,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6d,0xda,0x00,0x07,0x02,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x6d,0xf4,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6e,0x08,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6e,0x1c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x6e,0x1a,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x00, 0x6e,0x18,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6e,0x16,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x6e,0x2c,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x6e,0x34,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00, 0x6e,0xb8,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x00,0x6f,0x58,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x73,0xb4,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x73,0xc0,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00, 0x74,0x38,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x74,0x9e,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x74,0xc6,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00,0x74,0xea,0x00,0x07,0x00,0x01,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x00,0x00, 0x75,0x1a,0x00,0x02,0x00,0x0e,0x00,0x04,0x0e,0x19,0x0e,0x1f,0x0e,0x63,0x0e,0x64,0x00,0x02,0x00,0x04,0x08,0xf8,0x08,0xf8,0x00,0x00,0x09,0x05,0x09,0x05,0x00,0x01,0x09,0x2d,0x09,0x2d,0x00,0x02,0x0a,0x68,0x0a,0x68,0x00,0x03,0x00,0x02,0x00,0x08,0x00,0x01,0x0a,0x3e,0x00,0x01,0x00,0x01,0x09,0xdd,0x00,0x02,0x00,0x0a,0x00,0x02, 0x0e,0x19,0x0e,0x1f,0x00,0x01,0x00,0x02,0x08,0xf8,0x09,0x05,0x00,0x02,0x00,0x0e,0x00,0x04,0x0a,0x3c,0x08,0xdd,0x0a,0x3d,0x0e,0x15,0x00,0x02,0x00,0x03,0x09,0x53,0x09,0x53,0x00,0x00,0x09,0x55,0x09,0x56,0x00,0x01,0x0e,0x14,0x0e,0x14,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x1e,0x00,0x01,0x04,0xd8,0x00,0x00,0x00,0x00,0x00,0x03, 0x00,0x00,0x00,0x01,0x04,0xca,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x66,0x00,0x02,0x00,0xc9,0x08,0xc7,0x08,0xca,0x00,0x00,0x08,0xcf,0x08,0xcf,0x00,0x04,0x08,0xd1,0x08,0xd1,0x00,0x05,0x08,0xd3,0x08,0xd3,0x00,0x06,0x08,0xe4,0x08,0xe4,0x00,0x07,0x08,0xe7,0x08,0xe7,0x00,0x08,0x08,0xf1,0x08,0xf3,0x00,0x09,0x08,0xf5,0x08,0xf7, 0x00,0x0c,0x08,0xfa,0x08,0xfb,0x00,0x0f,0x08,0xff,0x09,0x00,0x00,0x11,0x09,0x02,0x09,0x02,0x00,0x13,0x09,0x08,0x09,0x20,0x00,0x14,0x09,0x22,0x09,0x2b,0x00,0x2d,0x09,0x34,0x09,0x35,0x00,0x37,0x09,0x3e,0x09,0x3e,0x00,0x39,0x09,0x40,0x09,0x40,0x00,0x3a,0x09,0x42,0x09,0x43,0x00,0x3b,0x09,0x45,0x09,0x46,0x00,0x3d,0x09,0x48, 0x09,0x48,0x00,0x3f,0x09,0x4a,0x09,0x4b,0x00,0x40,0x09,0x4d,0x09,0x4e,0x00,0x42,0x09,0x59,0x09,0x59,0x00,0x44,0x09,0x5b,0x09,0x5b,0x00,0x45,0x09,0x5d,0x09,0x60,0x00,0x46,0x09,0x63,0x09,0x68,0x00,0x4a,0x09,0x6c,0x09,0x6c,0x00,0x50,0x09,0x72,0x09,0x72,0x00,0x51,0x09,0x7c,0x09,0x7c,0x00,0x52,0x09,0x80,0x09,0x8c,0x00,0x53, 0x09,0x8e,0x09,0x8e,0x00,0x60,0x09,0x90,0x09,0x90,0x00,0x61,0x09,0x92,0x09,0x92,0x00,0x62,0x09,0x94,0x09,0x94,0x00,0x63,0x09,0x96,0x09,0x96,0x00,0x64,0x09,0x98,0x09,0x99,0x00,0x65,0x09,0x9b,0x09,0x9c,0x00,0x67,0x09,0x9e,0x09,0x9f,0x00,0x69,0x09,0xa1,0x09,0xa2,0x00,0x6b,0x09,0xa4,0x09,0xa5,0x00,0x6d,0x09,0xa7,0x09,0xa8, 0x00,0x6f,0x09,0xaa,0x09,0xb9,0x00,0x71,0x09,0xbb,0x09,0xbb,0x00,0x81,0x09,0xbd,0x09,0xbd,0x00,0x82,0x09,0xbf,0x09,0xbf,0x00,0x83,0x09,0xc1,0x09,0xc1,0x00,0x84,0x09,0xc3,0x09,0xc5,0x00,0x85,0x09,0xc8,0x09,0xc9,0x00,0x88,0x09,0xcc,0x09,0xcc,0x00,0x8a,0x09,0xcf,0x09,0xcf,0x00,0x8b,0x09,0xd2,0x09,0xd2,0x00,0x8c,0x09,0xd5, 0x09,0xd7,0x00,0x8d,0x09,0xd9,0x09,0xd9,0x00,0x90,0x09,0xdb,0x09,0xdb,0x00,0x91,0x09,0xdd,0x09,0xdd,0x00,0x92,0x09,0xdf,0x09,0xdf,0x00,0x93,0x09,0xe1,0x09,0xe1,0x00,0x94,0x09,0xe3,0x09,0xe3,0x00,0x95,0x09,0xe5,0x09,0xe5,0x00,0x96,0x09,0xe7,0x09,0xe7,0x00,0x97,0x09,0xe9,0x09,0xe9,0x00,0x98,0x09,0xeb,0x09,0xeb,0x00,0x99, 0x09,0xed,0x09,0xed,0x00,0x9a,0x09,0xef,0x09,0xef,0x00,0x9b,0x09,0xf1,0x09,0xf1,0x00,0x9c,0x09,0xf3,0x09,0xf3,0x00,0x9d,0x09,0xf5,0x09,0xf6,0x00,0x9e,0x09,0xf8,0x09,0xf8,0x00,0xa0,0x09,0xfa,0x09,0xfb,0x00,0xa1,0x09,0xfd,0x0a,0x08,0x00,0xa3,0x0a,0x0a,0x0a,0x0e,0x00,0xaf,0x0a,0x24,0x0a,0x24,0x00,0xb4,0x0a,0x26,0x0a,0x26, 0x00,0xb5,0x0a,0x28,0x0a,0x29,0x00,0xb6,0x0a,0x32,0x0a,0x3b,0x00,0xb8,0x0a,0x3e,0x0a,0x3f,0x00,0xc2,0x0a,0x41,0x0a,0x42,0x00,0xc4,0x0a,0x54,0x0a,0x59,0x00,0xc6,0x0a,0x72,0x0a,0x72,0x00,0xcc,0x0a,0x74,0x0a,0x74,0x00,0xcd,0x0a,0x76,0x0a,0x76,0x00,0xce,0x0a,0x78,0x0a,0x78,0x00,0xcf,0x0a,0x7a,0x0a,0x7a,0x00,0xd0,0x0a,0x7c, 0x0a,0x7c,0x00,0xd1,0x0a,0x7e,0x0a,0x7e,0x00,0xd2,0x0a,0x80,0x0a,0x81,0x00,0xd3,0x0a,0x83,0x0a,0x84,0x00,0xd5,0x0a,0x86,0x0a,0x89,0x00,0xd7,0x0a,0x8b,0x0a,0x8c,0x00,0xdb,0x0a,0x8f,0x0a,0x90,0x00,0xdd,0x0a,0x93,0x0a,0x94,0x00,0xdf,0x0a,0x97,0x0a,0x97,0x00,0xe1,0x0a,0x9a,0x0a,0x9a,0x00,0xe2,0x0a,0x9d,0x0a,0x9d,0x00,0xe3, 0x0a,0xa0,0x0a,0xa0,0x00,0xe4,0x0a,0xa3,0x0a,0xa3,0x00,0xe5,0x0a,0xa6,0x0a,0xa6,0x00,0xe6,0x0a,0xa8,0x0a,0xa8,0x00,0xe7,0x0a,0xaa,0x0a,0xaa,0x00,0xe8,0x0a,0xac,0x0a,0xac,0x00,0xe9,0x0a,0xae,0x0a,0xae,0x00,0xea,0x0a,0xb0,0x0a,0xb1,0x00,0xeb,0x0a,0xb4,0x0a,0xb6,0x00,0xed,0x0a,0xb9,0x0a,0xba,0x00,0xf0,0x0b,0x0c,0x0b,0x1a, 0x00,0xf2,0x0e,0x20,0x0e,0x21,0x01,0x01,0x0e,0x24,0x0e,0x24,0x01,0x03,0x0e,0x26,0x0e,0x26,0x01,0x04,0x0e,0x28,0x0e,0x28,0x01,0x05,0x0e,0x2a,0x0e,0x2a,0x01,0x06,0x0e,0x2f,0x0e,0x31,0x01,0x07,0x0e,0x33,0x0e,0x33,0x01,0x0a,0x0e,0x35,0x0e,0x35,0x01,0x0b,0x0e,0x37,0x0e,0x37,0x01,0x0c,0x0e,0x39,0x0e,0x39,0x01,0x0d,0x0e,0x3c, 0x0e,0x3c,0x01,0x0e,0x0e,0x3f,0x0e,0x40,0x01,0x0f,0x0e,0x43,0x0e,0x44,0x01,0x11,0x0e,0x47,0x0e,0x48,0x01,0x13,0x0e,0x4b,0x0e,0x4c,0x01,0x15,0x0e,0x4f,0x0e,0x50,0x01,0x17,0x0e,0x53,0x0e,0x55,0x01,0x19,0x0e,0x57,0x0e,0x57,0x01,0x1c,0x0e,0x59,0x0e,0x59,0x01,0x1d,0x0e,0x5e,0x0e,0x5e,0x01,0x1e,0x0e,0x6e,0x0e,0x6e,0x01,0x1f, 0x0e,0x70,0x0e,0x70,0x01,0x20,0x0e,0x74,0x0e,0x75,0x01,0x21,0x0e,0x78,0x0e,0x78,0x01,0x23,0x0e,0x7a,0x0e,0x7a,0x01,0x24,0x0e,0x7c,0x0e,0x7c,0x01,0x25,0x0e,0x7e,0x0e,0x7e,0x01,0x26,0x0e,0x80,0x0e,0x80,0x01,0x27,0x0e,0x82,0x0e,0x82,0x01,0x28,0x0e,0x84,0x0e,0x84,0x01,0x29,0x0e,0x86,0x0e,0x86,0x01,0x2a,0x0e,0x8f,0x0e,0x98, 0x01,0x2b,0x0e,0x9a,0x0e,0x9a,0x01,0x35,0x0e,0x9c,0x0e,0x9c,0x01,0x36,0x0e,0x9e,0x0e,0x9e,0x01,0x37,0x0e,0xa0,0x0e,0xa0,0x01,0x38,0x0e,0xa2,0x0e,0xa2,0x01,0x39,0x0e,0xa5,0x0e,0xab,0x01,0x3a,0x0e,0xae,0x0e,0xae,0x01,0x41,0x0e,0xb1,0x0e,0xb1,0x01,0x42,0x0e,0xb3,0x0e,0xb3,0x01,0x43,0x0e,0xb5,0x0e,0xb5,0x01,0x44,0x0e,0xb7, 0x0e,0xb7,0x01,0x45,0x0e,0xb9,0x0e,0xb9,0x01,0x46,0x0e,0xbb,0x0e,0xbb,0x01,0x47,0x0e,0xbd,0x0e,0xbd,0x01,0x48,0x0e,0xbf,0x0e,0xbf,0x01,0x49,0x0e,0xc1,0x0e,0xc1,0x01,0x4a,0x0e,0xc3,0x0e,0xc3,0x01,0x4b,0x0e,0xc5,0x0e,0xc5,0x01,0x4c,0x0e,0xc7,0x0e,0xc7,0x01,0x4d,0x0e,0xc9,0x0e,0xcd,0x01,0x4e,0x0e,0xcf,0x0e,0xd0,0x01,0x53, 0x0e,0xd3,0x0e,0xd3,0x01,0x55,0x0e,0xd5,0x0e,0xd5,0x01,0x56,0x0e,0xda,0x0e,0xe3,0x01,0x57,0x0e,0xe6,0x0e,0xe6,0x01,0x61,0x0e,0xec,0x0e,0xec,0x01,0x62,0x0e,0xee,0x0e,0xee,0x01,0x63,0x0e,0xf0,0x0e,0xf0,0x01,0x64,0x0e,0xf2,0x0e,0xf2,0x01,0x65,0x0e,0xf4,0x0e,0xf4,0x01,0x66,0x0e,0xf6,0x0e,0xf6,0x01,0x67,0x0e,0xf8,0x0e,0xf8, 0x01,0x68,0x0e,0xfa,0x0e,0xfa,0x01,0x69,0x0e,0xfc,0x0e,0xfc,0x01,0x6a,0x0f,0x00,0x0f,0x03,0x01,0x6b,0x0f,0x05,0x0f,0x0a,0x01,0x6f,0x0f,0x0c,0x0f,0x0c,0x01,0x75,0x0f,0x0e,0x0f,0x0e,0x01,0x76,0x0f,0x10,0x0f,0x10,0x01,0x77,0x0f,0x12,0x0f,0x12,0x01,0x78,0x0f,0x14,0x0f,0x14,0x01,0x79,0x0f,0x16,0x0f,0x17,0x01,0x7a,0x0f,0x1a, 0x0f,0x1b,0x01,0x7c,0x0f,0x1e,0x0f,0x1f,0x01,0x7e,0x0f,0x22,0x0f,0x25,0x01,0x80,0x0f,0x28,0x0f,0x2d,0x01,0x84,0x0f,0x30,0x0f,0x31,0x01,0x8a,0x0f,0x34,0x0f,0x35,0x01,0x8c,0x0f,0x38,0x0f,0x41,0x01,0x8e,0x0f,0x44,0x0f,0x45,0x01,0x98,0x0f,0x48,0x0f,0x49,0x01,0x9a,0x0f,0x4c,0x0f,0x4d,0x01,0x9c,0x0f,0x62,0x0f,0x6b,0x01,0x9e, 0x0f,0x98,0x0f,0xa4,0x01,0xa8,0x0f,0xa6,0x0f,0xb3,0x01,0xb5,0x0f,0xb5,0x0f,0xbc,0x01,0xc3,0x14,0x55,0x14,0x5c,0x01,0xcb,0x14,0x73,0x14,0x73,0x01,0xd3,0x14,0x76,0x14,0x76,0x01,0xd4,0x14,0x79,0x14,0x79,0x01,0xd5,0x14,0x7d,0x14,0x7e,0x01,0xd6,0x14,0x81,0x14,0x81,0x01,0xd8,0x14,0x84,0x14,0x84,0x01,0xd9,0x14,0x87,0x14,0x87, 0x01,0xda,0x14,0xad,0x14,0xae,0x01,0xdb,0x00,0x01,0x00,0x01,0x09,0x28,0x00,0x01,0x01,0x0e,0x00,0x0c,0x00,0x1e,0x00,0x30,0x00,0x42,0x00,0x4c,0x00,0x5e,0x00,0x70,0x00,0x7a,0x00,0xb4,0x00,0xbe,0x00,0xd0,0x00,0xf2,0x01,0x04,0x00,0x02,0x00,0x06,0x00,0x0c,0x0e,0x62,0x00,0x02,0x09,0x32,0x0e,0x69,0x00,0x02,0x09,0x7e,0x00,0x02, 0x00,0x06,0x00,0x0c,0x0a,0x68,0x00,0x02,0x09,0x32,0x0e,0x66,0x00,0x02,0x09,0x7e,0x00,0x01,0x00,0x04,0x0e,0x6b,0x00,0x02,0x09,0x7f,0x00,0x02,0x00,0x06,0x00,0x0c,0x0a,0x65,0x00,0x02,0x09,0x32,0x0e,0x67,0x00,0x02,0x09,0x7e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0a,0x66,0x00,0x02,0x09,0x32,0x0e,0x68,0x00,0x02,0x09,0x7e,0x00,0x01, 0x00,0x04,0x0e,0x6c,0x00,0x02,0x09,0x7f,0x00,0x07,0x00,0x10,0x00,0x16,0x00,0x1c,0x00,0x22,0x00,0x28,0x00,0x2e,0x00,0x34,0x0a,0x65,0x00,0x02,0x09,0x2f,0x0a,0x66,0x00,0x02,0x09,0x30,0x0a,0x68,0x00,0x02,0x09,0x2d,0x0e,0x62,0x00,0x02,0x09,0x2c,0x0e,0x64,0x00,0x02,0x0e,0x63,0x0e,0x65,0x00,0x02,0x09,0x73,0x13,0xe9,0x00,0x02, 0x09,0x73,0x00,0x01,0x00,0x04,0x0e,0x6a,0x00,0x02,0x09,0x7e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0e,0x65,0x00,0x02,0x09,0x32,0x13,0xe9,0x00,0x02,0x09,0x32,0x00,0x04,0x00,0x0a,0x00,0x10,0x00,0x16,0x00,0x1c,0x0e,0x66,0x00,0x02,0x09,0x2d,0x0e,0x67,0x00,0x02,0x09,0x2f,0x0e,0x68,0x00,0x02,0x09,0x30,0x0e,0x6a,0x00,0x02,0x09,0x33, 0x00,0x02,0x00,0x06,0x00,0x0c,0x0e,0x6b,0x00,0x02,0x09,0x2e,0x0e,0x6c,0x00,0x02,0x09,0x31,0x00,0x01,0x00,0x04,0x0e,0x64,0x00,0x02,0x09,0x32,0x00,0x02,0x00,0x04,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x73,0x09,0x73,0x00,0x08,0x09,0x7e,0x09,0x7f,0x00,0x09,0x0e,0x63,0x0e,0x63,0x00,0x0b,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x08, 0x00,0x02,0x00,0x06,0x00,0x0c,0x0a,0x67,0x00,0x02,0x09,0x31,0x0a,0x69,0x00,0x02,0x09,0x2e,0x00,0x01,0x00,0x01,0x09,0x32,0x00,0x01,0x00,0x52,0x00,0x01,0x00,0x08,0x00,0x09,0x00,0x14,0x00,0x1a,0x00,0x20,0x00,0x26,0x00,0x2c,0x00,0x32,0x00,0x38,0x00,0x3e,0x00,0x44,0x11,0x9a,0x00,0x02,0x08,0xd8,0x11,0x9b,0x00,0x02,0x08,0xd9, 0x11,0x9c,0x00,0x02,0x08,0xda,0x11,0x9d,0x00,0x02,0x08,0xdb,0x11,0x9e,0x00,0x02,0x08,0xdc,0x11,0x9f,0x00,0x02,0x08,0xdd,0x11,0xa0,0x00,0x02,0x08,0xde,0x11,0xa1,0x00,0x02,0x08,0xdf,0x11,0xa2,0x00,0x02,0x08,0xe0,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x03,0x00,0x01,0x00,0x3c,0x00,0x01,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x00, 0x00,0x67,0x00,0x03,0x00,0x02,0x00,0x48,0x00,0x52,0x00,0x01,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x03,0x00,0x03,0x00,0x34,0x00,0x34,0x00,0x3e,0x00,0x01,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x01,0x00,0x02,0x0a,0x14,0x14,0x6b,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f, 0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x02,0x00,0x01,0x14,0x88,0x14,0x96,0x00,0x00,0x00,0x01,0x00,0x01,0x0a,0x14,0x00,0x03,0x00,0x01,0x00,0x54,0x00,0x01,0x00,0x6a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x03,0x00,0x02,0x00,0x6e,0x00,0x42,0x00,0x01,0x00,0x58,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68, 0x00,0x03,0x00,0x03,0x00,0x5a,0x00,0x5a,0x00,0x2e,0x00,0x01,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x03,0x00,0x04,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x18,0x00,0x01,0x00,0x2e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x02,0x00,0x03,0x0a,0x44,0x0a,0x44,0x00,0x00,0x0a,0x47,0x0a,0x47,0x00,0x01,0x13,0x45, 0x13,0x45,0x00,0x02,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x03,0x00,0x01,0x00,0x26,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x03,0x00,0x02,0x00,0x30,0x00,0x3a,0x00,0x01, 0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x01,0x00,0x01,0x0a,0x45,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x14,0x9a,0x00,0x03,0x00,0x01,0x00,0x26,0x00,0x01,0x00,0x2e, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6a,0x00,0x03,0x00,0x02,0x00,0x32,0x00,0x3c,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6a,0x00,0x01,0x00,0x02,0x0a,0x45,0x0a,0x46,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x02,0x00,0x01,0x14,0x9e, 0x14,0xac,0x00,0x00,0x00,0x01,0x00,0x01,0x14,0x9a,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x24,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6b,0x00,0x02,0x00,0x02,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x53,0x09,0x55,0x00,0x0a,0x00,0x01,0x00,0x02,0x14,0x03,0x14,0x2b,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00, 0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2e,0x00,0x03,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x01,0x00,0x00,0x00,0x6c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x04,0x00,0x2e,0x00,0x2e,0x00,0x2e,0x00,0x2e,0x00,0x01,0x00,0x00,0x00,0x6c,0x00,0x02,0x00,0x03,0x0a,0x44, 0x0a,0x44,0x00,0x00,0x0a,0x47,0x0a,0x47,0x00,0x01,0x13,0x45,0x13,0x45,0x00,0x02,0x00,0x02,0x00,0x01,0x14,0x9e,0x14,0xac,0x00,0x00,0x00,0x02,0x01,0xc8,0x00,0xe1,0x08,0xf2,0x08,0xc9,0x08,0xc8,0x0e,0x24,0x08,0xca,0x09,0x02,0x08,0xc7,0x0e,0x26,0x08,0xf6,0x0e,0x28,0x0e,0x2a,0x08,0xcf,0x08,0xd1,0x08,0xd3,0x0e,0x2f,0x0e,0x30, 0x0b,0x0c,0x0b,0x0d,0x0e,0x31,0x0e,0x33,0x0e,0x35,0x0e,0x37,0x0e,0x39,0x0e,0x3c,0x08,0xe4,0x08,0xe7,0x0e,0x53,0x0e,0x54,0x0e,0x55,0x09,0x59,0x0e,0x57,0x0e,0x59,0x08,0xf3,0x0e,0x5e,0x08,0xf7,0x08,0xf5,0x0e,0x6e,0x0e,0x82,0x09,0x43,0x0b,0x0e,0x0e,0xb1,0x0e,0xbd,0x09,0x4b,0x09,0x4d,0x0e,0x78,0x0e,0x8f,0x0b,0x0f,0x0e,0xcf, 0x09,0x72,0x0e,0xda,0x0e,0xdb,0x09,0x66,0x09,0x68,0x0e,0xa8,0x0e,0x70,0x09,0x81,0x09,0x83,0x09,0x85,0x09,0x87,0x0e,0x74,0x0e,0x75,0x09,0x8b,0x0e,0x7a,0x0e,0x7c,0x0e,0x7e,0x0e,0x80,0x0e,0x84,0x0e,0x86,0x09,0x99,0x09,0x9c,0x09,0x9f,0x09,0xa2,0x09,0xa5,0x09,0xa8,0x0e,0x90,0x0e,0x91,0x0e,0x92,0x0e,0x93,0x0e,0x94,0x0e,0x95, 0x0e,0x96,0x0e,0x97,0x0b,0x10,0x0b,0x11,0x0b,0x12,0x0b,0x13,0x0b,0x14,0x0b,0x15,0x0b,0x16,0x0e,0x98,0x0e,0x9a,0x0e,0x9c,0x0e,0x9e,0x0e,0xa0,0x0e,0xa2,0x09,0xc5,0x0e,0xa5,0x0e,0xa6,0x0e,0xa7,0x0e,0xa9,0x0e,0xaa,0x0e,0xab,0x0e,0xae,0x0e,0xb3,0x0e,0xb5,0x0e,0xb7,0x0e,0xb9,0x0e,0xbb,0x0e,0xbf,0x0e,0xc1,0x0e,0xc3,0x0e,0xc5, 0x0e,0xc7,0x0e,0xc9,0x0e,0xca,0x0e,0xcb,0x0e,0xcc,0x0e,0xcd,0x0e,0xd0,0x0e,0xd3,0x0e,0xd5,0x09,0xfb,0x0e,0xdc,0x0e,0xdd,0x0e,0xde,0x0e,0xdf,0x0e,0xe0,0x0e,0xe1,0x0e,0xe2,0x0e,0xe3,0x0a,0x06,0x0a,0x08,0x0e,0xe6,0x0a,0x0c,0x0a,0x0e,0x0e,0xec,0x0e,0xee,0x0a,0x29,0x0a,0x3f,0x0a,0x55,0x0a,0x57,0x0a,0x59,0x0e,0xf0,0x0e,0xf2, 0x0e,0xf4,0x0e,0xf6,0x0e,0xf8,0x0e,0xfa,0x0e,0xfc,0x0a,0x81,0x0a,0x84,0x0f,0x00,0x0f,0x01,0x0f,0x02,0x0f,0x03,0x0a,0x8c,0x0a,0x90,0x0a,0x94,0x0f,0x05,0x0f,0x06,0x0f,0x07,0x0f,0x08,0x0f,0x09,0x0f,0x0a,0x0f,0x0c,0x0f,0x0e,0x0f,0x10,0x0f,0x12,0x0a,0xb1,0x0b,0x17,0x0b,0x18,0x0f,0x14,0x0b,0x1a,0x0e,0x21,0x0e,0x40,0x0e,0x44, 0x0e,0x48,0x0e,0x4c,0x0e,0x50,0x0f,0x17,0x0f,0x1b,0x0f,0x1f,0x0f,0x23,0x0f,0x25,0x0f,0x29,0x0f,0x2b,0x0f,0x2d,0x0f,0x31,0x0f,0x35,0x0f,0x39,0x0f,0x3b,0x0f,0x3d,0x0f,0x3f,0x0f,0x41,0x0f,0x45,0x0f,0x49,0x0f,0x4d,0x13,0x00,0x13,0x05,0x13,0x0b,0x13,0x0f,0x13,0x13,0x13,0x17,0x13,0x1b,0x13,0x1f,0x13,0x23,0x13,0x25,0x13,0x27, 0x13,0x29,0x14,0x07,0x14,0x0a,0x14,0x0e,0x14,0x12,0x14,0x14,0x14,0x16,0x14,0x6d,0x14,0x70,0x14,0x73,0x14,0x76,0x14,0x79,0x14,0x7d,0x14,0x7e,0x14,0x81,0x14,0x84,0x14,0x87,0x00,0x02,0x00,0x8d,0x08,0xf1,0x08,0xf1,0x00,0x00,0x09,0x08,0x09,0x20,0x00,0x01,0x09,0x22,0x09,0x2b,0x00,0x1a,0x09,0x3e,0x09,0x3e,0x00,0x24,0x09,0x40, 0x09,0x40,0x00,0x25,0x09,0x42,0x09,0x42,0x00,0x26,0x09,0x45,0x09,0x46,0x00,0x27,0x09,0x48,0x09,0x48,0x00,0x29,0x09,0x4a,0x09,0x4a,0x00,0x2a,0x09,0x4e,0x09,0x4e,0x00,0x2b,0x09,0x5b,0x09,0x5b,0x00,0x2c,0x09,0x5d,0x09,0x60,0x00,0x2d,0x09,0x63,0x09,0x65,0x00,0x31,0x09,0x67,0x09,0x67,0x00,0x34,0x09,0x6c,0x09,0x6c,0x00,0x35, 0x09,0x7c,0x09,0x7c,0x00,0x36,0x09,0x80,0x09,0x80,0x00,0x37,0x09,0x82,0x09,0x82,0x00,0x38,0x09,0x84,0x09,0x84,0x00,0x39,0x09,0x86,0x09,0x86,0x00,0x3a,0x09,0x88,0x09,0x8a,0x00,0x3b,0x09,0x8c,0x09,0x8c,0x00,0x3e,0x09,0x8e,0x09,0x8e,0x00,0x3f,0x09,0x90,0x09,0x90,0x00,0x40,0x09,0x92,0x09,0x92,0x00,0x41,0x09,0x94,0x09,0x94, 0x00,0x42,0x09,0x96,0x09,0x96,0x00,0x43,0x09,0x98,0x09,0x98,0x00,0x44,0x09,0x9b,0x09,0x9b,0x00,0x45,0x09,0x9e,0x09,0x9e,0x00,0x46,0x09,0xa1,0x09,0xa1,0x00,0x47,0x09,0xa4,0x09,0xa4,0x00,0x48,0x09,0xa7,0x09,0xa7,0x00,0x49,0x09,0xaa,0x09,0xb9,0x00,0x4a,0x09,0xbb,0x09,0xbb,0x00,0x5a,0x09,0xbd,0x09,0xbd,0x00,0x5b,0x09,0xbf, 0x09,0xbf,0x00,0x5c,0x09,0xc1,0x09,0xc1,0x00,0x5d,0x09,0xc3,0x09,0xc4,0x00,0x5e,0x09,0xc8,0x09,0xc9,0x00,0x60,0x09,0xcc,0x09,0xcc,0x00,0x62,0x09,0xcf,0x09,0xcf,0x00,0x63,0x09,0xd2,0x09,0xd2,0x00,0x64,0x09,0xd5,0x09,0xd7,0x00,0x65,0x09,0xd9,0x09,0xd9,0x00,0x68,0x09,0xdb,0x09,0xdb,0x00,0x69,0x09,0xdd,0x09,0xdd,0x00,0x6a, 0x09,0xdf,0x09,0xdf,0x00,0x6b,0x09,0xe1,0x09,0xe1,0x00,0x6c,0x09,0xe3,0x09,0xe3,0x00,0x6d,0x09,0xe5,0x09,0xe5,0x00,0x6e,0x09,0xe7,0x09,0xe7,0x00,0x6f,0x09,0xe9,0x09,0xe9,0x00,0x70,0x09,0xeb,0x09,0xeb,0x00,0x71,0x09,0xed,0x09,0xed,0x00,0x72,0x09,0xef,0x09,0xef,0x00,0x73,0x09,0xf1,0x09,0xf1,0x00,0x74,0x09,0xf3,0x09,0xf3, 0x00,0x75,0x09,0xf5,0x09,0xf6,0x00,0x76,0x09,0xf8,0x09,0xf8,0x00,0x78,0x09,0xfa,0x09,0xfa,0x00,0x79,0x09,0xfd,0x0a,0x05,0x00,0x7a,0x0a,0x07,0x0a,0x07,0x00,0x83,0x0a,0x0a,0x0a,0x0b,0x00,0x84,0x0a,0x0d,0x0a,0x0d,0x00,0x86,0x0a,0x24,0x0a,0x24,0x00,0x87,0x0a,0x26,0x0a,0x26,0x00,0x88,0x0a,0x28,0x0a,0x28,0x00,0x89,0x0a,0x3e, 0x0a,0x3e,0x00,0x8a,0x0a,0x54,0x0a,0x54,0x00,0x8b,0x0a,0x56,0x0a,0x56,0x00,0x8c,0x0a,0x58,0x0a,0x58,0x00,0x8d,0x0a,0x72,0x0a,0x72,0x00,0x8e,0x0a,0x74,0x0a,0x74,0x00,0x8f,0x0a,0x76,0x0a,0x76,0x00,0x90,0x0a,0x78,0x0a,0x78,0x00,0x91,0x0a,0x7a,0x0a,0x7a,0x00,0x92,0x0a,0x7c,0x0a,0x7c,0x00,0x93,0x0a,0x7e,0x0a,0x7e,0x00,0x94, 0x0a,0x80,0x0a,0x80,0x00,0x95,0x0a,0x83,0x0a,0x83,0x00,0x96,0x0a,0x86,0x0a,0x89,0x00,0x97,0x0a,0x8b,0x0a,0x8b,0x00,0x9b,0x0a,0x8f,0x0a,0x8f,0x00,0x9c,0x0a,0x93,0x0a,0x93,0x00,0x9d,0x0a,0x97,0x0a,0x97,0x00,0x9e,0x0a,0x9a,0x0a,0x9a,0x00,0x9f,0x0a,0x9d,0x0a,0x9d,0x00,0xa0,0x0a,0xa0,0x0a,0xa0,0x00,0xa1,0x0a,0xa3,0x0a,0xa3, 0x00,0xa2,0x0a,0xa6,0x0a,0xa6,0x00,0xa3,0x0a,0xa8,0x0a,0xa8,0x00,0xa4,0x0a,0xaa,0x0a,0xaa,0x00,0xa5,0x0a,0xac,0x0a,0xac,0x00,0xa6,0x0a,0xae,0x0a,0xae,0x00,0xa7,0x0a,0xb0,0x0a,0xb0,0x00,0xa8,0x0a,0xb4,0x0a,0xb6,0x00,0xa9,0x0b,0x19,0x0b,0x19,0x00,0xac,0x0e,0x20,0x0e,0x20,0x00,0xad,0x0e,0x3f,0x0e,0x3f,0x00,0xae,0x0e,0x43, 0x0e,0x43,0x00,0xaf,0x0e,0x47,0x0e,0x47,0x00,0xb0,0x0e,0x4b,0x0e,0x4b,0x00,0xb1,0x0e,0x4f,0x0e,0x4f,0x00,0xb2,0x0f,0x16,0x0f,0x16,0x00,0xb3,0x0f,0x1a,0x0f,0x1a,0x00,0xb4,0x0f,0x1e,0x0f,0x1e,0x00,0xb5,0x0f,0x22,0x0f,0x22,0x00,0xb6,0x0f,0x24,0x0f,0x24,0x00,0xb7,0x0f,0x28,0x0f,0x28,0x00,0xb8,0x0f,0x2a,0x0f,0x2a,0x00,0xb9, 0x0f,0x2c,0x0f,0x2c,0x00,0xba,0x0f,0x30,0x0f,0x30,0x00,0xbb,0x0f,0x34,0x0f,0x34,0x00,0xbc,0x0f,0x38,0x0f,0x38,0x00,0xbd,0x0f,0x3a,0x0f,0x3a,0x00,0xbe,0x0f,0x3c,0x0f,0x3c,0x00,0xbf,0x0f,0x3e,0x0f,0x3e,0x00,0xc0,0x0f,0x40,0x0f,0x40,0x00,0xc1,0x0f,0x44,0x0f,0x44,0x00,0xc2,0x0f,0x48,0x0f,0x48,0x00,0xc3,0x0f,0x4c,0x0f,0x4c, 0x00,0xc4,0x13,0x02,0x13,0x02,0x00,0xc5,0x13,0x04,0x13,0x04,0x00,0xc6,0x13,0x08,0x13,0x08,0x00,0xc7,0x13,0x0c,0x13,0x0c,0x00,0xc8,0x13,0x10,0x13,0x10,0x00,0xc9,0x13,0x14,0x13,0x14,0x00,0xca,0x13,0x18,0x13,0x18,0x00,0xcb,0x13,0x1c,0x13,0x1c,0x00,0xcc,0x13,0x20,0x13,0x20,0x00,0xcd,0x13,0x24,0x13,0x24,0x00,0xce,0x13,0x26, 0x13,0x26,0x00,0xcf,0x13,0x28,0x13,0x28,0x00,0xd0,0x14,0x04,0x14,0x04,0x00,0xd1,0x14,0x09,0x14,0x09,0x00,0xd2,0x14,0x0b,0x14,0x0b,0x00,0xd3,0x14,0x0f,0x14,0x0f,0x00,0xd4,0x14,0x13,0x14,0x13,0x00,0xd5,0x14,0x15,0x14,0x15,0x00,0xd6,0x14,0x53,0x14,0x5c,0x00,0xd7,0x00,0x02,0x01,0x36,0x00,0x98,0x0e,0xd8,0x0e,0x25,0x0e,0x27, 0x0e,0x29,0x0e,0x2b,0x0e,0x2c,0x0e,0x2d,0x0e,0x2e,0x0e,0x32,0x0e,0x34,0x0e,0x36,0x0e,0x38,0x0e,0x3b,0x0e,0x3e,0x08,0xe3,0x08,0xe6,0x08,0xe9,0x08,0xec,0x0e,0x56,0x09,0x3f,0x0e,0x58,0x0e,0x5a,0x0e,0x5d,0x0e,0x60,0x0e,0x61,0x09,0x3b,0x0e,0x83,0x0e,0x8d,0x0e,0xb2,0x0e,0xbe,0x0e,0xe4,0x0e,0x79,0x09,0x62,0x09,0x6e,0x0e,0x72, 0x0e,0x77,0x0e,0x7b,0x0e,0x7d,0x0e,0x7f,0x0e,0x81,0x0e,0x85,0x0e,0x87,0x0e,0x88,0x0e,0x89,0x0e,0x8a,0x0e,0x8b,0x0e,0x8c,0x0e,0x8e,0x0e,0x99,0x0e,0x9b,0x0e,0x9d,0x0e,0x9f,0x0e,0xa1,0x0e,0xa4,0x09,0xc7,0x09,0x3d,0x09,0xcb,0x09,0xce,0x09,0xd1,0x09,0xd4,0x0e,0xad,0x0e,0xb0,0x0e,0xb4,0x0e,0xb6,0x0e,0xb8,0x0e,0xba,0x0e,0xbc, 0x0e,0xc0,0x0e,0xc2,0x0e,0xc4,0x0e,0xc6,0x0e,0xc8,0x0a,0x5f,0x0a,0x60,0x0a,0x61,0x0a,0x62,0x0e,0xce,0x0e,0xd2,0x0e,0xd4,0x0e,0xd6,0x0e,0xd9,0x0e,0xe5,0x0e,0xe8,0x0e,0xea,0x0e,0xed,0x0e,0xef,0x0a,0x2b,0x0e,0xba,0x0a,0x5b,0x0e,0xf1,0x0e,0xf3,0x0e,0xf5,0x0e,0xf7,0x0e,0xf9,0x0e,0xfb,0x0e,0xfd,0x0e,0xfe,0x0e,0xff,0x0f,0x04, 0x0a,0x8e,0x0a,0x92,0x0a,0x96,0x0a,0x99,0x0a,0x9c,0x0a,0x9f,0x0a,0xa2,0x0a,0xa5,0x0f,0x0b,0x0f,0x0d,0x0f,0x0f,0x0f,0x11,0x0f,0x13,0x0a,0xb3,0x0f,0x15,0x0e,0x23,0x0e,0x42,0x0e,0x46,0x0e,0x4a,0x0e,0x4e,0x0e,0x52,0x0f,0x19,0x0f,0x1d,0x0f,0x21,0x0f,0x27,0x0f,0x2f,0x0f,0x33,0x0f,0x37,0x0f,0x43,0x0f,0x47,0x0f,0x4b,0x0f,0x4f, 0x13,0x01,0x13,0x07,0x13,0x0a,0x13,0x0e,0x13,0x12,0x13,0x16,0x13,0x1a,0x13,0x1e,0x13,0x22,0x14,0x06,0x14,0x0d,0x14,0x11,0x14,0x6e,0x14,0x71,0x14,0x74,0x14,0x77,0x14,0x7a,0x14,0x7f,0x14,0x82,0x14,0x85,0x0e,0x5a,0x00,0x02,0x00,0x7a,0x08,0xf1,0x08,0xf1,0x00,0x00,0x09,0x0c,0x09,0x0c,0x00,0x01,0x09,0x0e,0x09,0x0e,0x00,0x02, 0x09,0x10,0x09,0x14,0x00,0x03,0x09,0x19,0x09,0x20,0x00,0x08,0x09,0x22,0x09,0x28,0x00,0x10,0x09,0x2a,0x09,0x2b,0x00,0x17,0x09,0x3e,0x09,0x3e,0x00,0x19,0x09,0x40,0x09,0x40,0x00,0x1a,0x09,0x42,0x09,0x42,0x00,0x1b,0x09,0x46,0x09,0x46,0x00,0x1c,0x09,0x48,0x09,0x48,0x00,0x1d,0x09,0x4a,0x09,0x4a,0x00,0x1e,0x09,0x5b,0x09,0x5b, 0x00,0x1f,0x09,0x60,0x09,0x60,0x00,0x20,0x09,0x6c,0x09,0x6c,0x00,0x21,0x09,0x7c,0x09,0x7c,0x00,0x22,0x09,0x8a,0x09,0x8a,0x00,0x23,0x09,0x8c,0x09,0x8c,0x00,0x24,0x09,0x8e,0x09,0x8e,0x00,0x25,0x09,0x90,0x09,0x90,0x00,0x26,0x09,0x92,0x09,0x92,0x00,0x27,0x09,0x94,0x09,0x94,0x00,0x28,0x09,0x96,0x09,0x96,0x00,0x29,0x09,0x98, 0x09,0x98,0x00,0x2a,0x09,0x9b,0x09,0x9b,0x00,0x2b,0x09,0x9e,0x09,0x9e,0x00,0x2c,0x09,0xa1,0x09,0xa1,0x00,0x2d,0x09,0xa4,0x09,0xa4,0x00,0x2e,0x09,0xa7,0x09,0xa7,0x00,0x2f,0x09,0xb9,0x09,0xb9,0x00,0x30,0x09,0xbb,0x09,0xbb,0x00,0x31,0x09,0xbd,0x09,0xbd,0x00,0x32,0x09,0xbf,0x09,0xbf,0x00,0x33,0x09,0xc1,0x09,0xc1,0x00,0x34, 0x09,0xc3,0x09,0xc4,0x00,0x35,0x09,0xc8,0x09,0xc9,0x00,0x37,0x09,0xcc,0x09,0xcc,0x00,0x39,0x09,0xcf,0x09,0xcf,0x00,0x3a,0x09,0xd2,0x09,0xd2,0x00,0x3b,0x09,0xd5,0x09,0xd7,0x00,0x3c,0x09,0xd9,0x09,0xd9,0x00,0x3f,0x09,0xdb,0x09,0xdb,0x00,0x40,0x09,0xdd,0x09,0xdd,0x00,0x41,0x09,0xdf,0x09,0xdf,0x00,0x42,0x09,0xe1,0x09,0xe1, 0x00,0x43,0x09,0xe3,0x09,0xe3,0x00,0x44,0x09,0xe5,0x09,0xe5,0x00,0x45,0x09,0xe7,0x09,0xe7,0x00,0x46,0x09,0xe9,0x09,0xe9,0x00,0x47,0x09,0xeb,0x09,0xeb,0x00,0x48,0x09,0xed,0x09,0xed,0x00,0x49,0x09,0xef,0x09,0xef,0x00,0x4a,0x09,0xf1,0x09,0xf1,0x00,0x4b,0x09,0xf3,0x09,0xf3,0x00,0x4c,0x09,0xf5,0x09,0xf6,0x00,0x4d,0x09,0xf8, 0x09,0xf8,0x00,0x4f,0x09,0xfa,0x09,0xfa,0x00,0x50,0x0a,0x07,0x0a,0x07,0x00,0x51,0x0a,0x0b,0x0a,0x0b,0x00,0x52,0x0a,0x0d,0x0a,0x0d,0x00,0x53,0x0a,0x24,0x0a,0x24,0x00,0x54,0x0a,0x26,0x0a,0x26,0x00,0x55,0x0a,0x28,0x0a,0x28,0x00,0x56,0x0a,0x3e,0x0a,0x3e,0x00,0x57,0x0a,0x58,0x0a,0x58,0x00,0x58,0x0a,0x72,0x0a,0x72,0x00,0x59, 0x0a,0x74,0x0a,0x74,0x00,0x5a,0x0a,0x76,0x0a,0x76,0x00,0x5b,0x0a,0x78,0x0a,0x78,0x00,0x5c,0x0a,0x7a,0x0a,0x7a,0x00,0x5d,0x0a,0x7c,0x0a,0x7c,0x00,0x5e,0x0a,0x7e,0x0a,0x7e,0x00,0x5f,0x0a,0x80,0x0a,0x80,0x00,0x60,0x0a,0x83,0x0a,0x83,0x00,0x61,0x0a,0x89,0x0a,0x89,0x00,0x62,0x0a,0x8b,0x0a,0x8b,0x00,0x63,0x0a,0x8f,0x0a,0x8f, 0x00,0x64,0x0a,0x93,0x0a,0x93,0x00,0x65,0x0a,0x97,0x0a,0x97,0x00,0x66,0x0a,0x9a,0x0a,0x9a,0x00,0x67,0x0a,0x9d,0x0a,0x9d,0x00,0x68,0x0a,0xa0,0x0a,0xa0,0x00,0x69,0x0a,0xa3,0x0a,0xa3,0x00,0x6a,0x0a,0xa6,0x0a,0xa6,0x00,0x6b,0x0a,0xa8,0x0a,0xa8,0x00,0x6c,0x0a,0xaa,0x0a,0xaa,0x00,0x6d,0x0a,0xac,0x0a,0xac,0x00,0x6e,0x0a,0xae, 0x0a,0xae,0x00,0x6f,0x0a,0xb0,0x0a,0xb0,0x00,0x70,0x0a,0xb6,0x0a,0xb6,0x00,0x71,0x0e,0x20,0x0e,0x20,0x00,0x72,0x0e,0x3f,0x0e,0x3f,0x00,0x73,0x0e,0x43,0x0e,0x43,0x00,0x74,0x0e,0x47,0x0e,0x47,0x00,0x75,0x0e,0x4b,0x0e,0x4b,0x00,0x76,0x0e,0x4f,0x0e,0x4f,0x00,0x77,0x0f,0x16,0x0f,0x16,0x00,0x78,0x0f,0x1a,0x0f,0x1a,0x00,0x79, 0x0f,0x1e,0x0f,0x1e,0x00,0x7a,0x0f,0x24,0x0f,0x24,0x00,0x7b,0x0f,0x2c,0x0f,0x2c,0x00,0x7c,0x0f,0x30,0x0f,0x30,0x00,0x7d,0x0f,0x34,0x0f,0x34,0x00,0x7e,0x0f,0x40,0x0f,0x40,0x00,0x7f,0x0f,0x44,0x0f,0x44,0x00,0x80,0x0f,0x48,0x0f,0x48,0x00,0x81,0x0f,0x4c,0x0f,0x4c,0x00,0x82,0x13,0x02,0x13,0x02,0x00,0x83,0x13,0x04,0x13,0x04, 0x00,0x84,0x13,0x08,0x13,0x08,0x00,0x85,0x13,0x0c,0x13,0x0c,0x00,0x86,0x13,0x10,0x13,0x10,0x00,0x87,0x13,0x14,0x13,0x14,0x00,0x88,0x13,0x18,0x13,0x18,0x00,0x89,0x13,0x1c,0x13,0x1c,0x00,0x8a,0x13,0x20,0x13,0x20,0x00,0x8b,0x14,0x04,0x14,0x04,0x00,0x8c,0x14,0x0b,0x14,0x0b,0x00,0x8d,0x14,0x0f,0x14,0x0f,0x00,0x8e,0x14,0x53, 0x14,0x57,0x00,0x8f,0x14,0x59,0x14,0x5c,0x00,0x94,0x00,0x02,0x01,0x38,0x00,0x99,0x0e,0xd7,0x08,0xf9,0x08,0xcb,0x08,0xcc,0x08,0xcd,0x08,0xce,0x08,0xd0,0x08,0xd2,0x08,0xd4,0x08,0xd5,0x08,0xd6,0x08,0xe1,0x0e,0x3a,0x0e,0x3d,0x08,0xe2,0x08,0xe5,0x08,0xe8,0x08,0xeb,0x08,0xed,0x08,0xee,0x08,0xef,0x08,0xf0,0x0e,0x5b,0x0e,0x5f, 0x08,0xf4,0x0e,0x6f,0x09,0x41,0x09,0x44,0x09,0x47,0x09,0x49,0x09,0x4c,0x09,0x5c,0x09,0x61,0x09,0x6d,0x0e,0x71,0x0e,0x76,0x09,0x8d,0x09,0x8f,0x09,0x91,0x09,0x93,0x09,0x95,0x09,0x97,0x09,0x9a,0x09,0x9d,0x09,0xa0,0x09,0xa3,0x09,0xa6,0x09,0xa9,0x09,0xba,0x09,0xbc,0x09,0xbe,0x09,0xc0,0x09,0xc2,0x0e,0xa3,0x09,0xc6,0x09,0x3c, 0x09,0xca,0x09,0xcd,0x09,0xd0,0x09,0xd3,0x0e,0xac,0x0e,0xaf,0x09,0xd8,0x09,0xda,0x09,0xdc,0x09,0xde,0x09,0xe0,0x09,0xe2,0x09,0xe4,0x09,0xe6,0x09,0xe8,0x09,0xea,0x09,0xec,0x09,0xee,0x09,0xf0,0x09,0xf2,0x09,0xf4,0x0e,0xd1,0x09,0xf7,0x09,0xf9,0x09,0xfc,0x0a,0x09,0x0e,0xe7,0x0e,0xe9,0x0a,0x10,0x0a,0x25,0x0a,0x27,0x0a,0x2a, 0x09,0xde,0x0a,0x5a,0x0a,0x73,0x0a,0x75,0x0a,0x77,0x0a,0x79,0x0a,0x7b,0x0a,0x7d,0x0a,0x7f,0x0a,0x82,0x0a,0x85,0x0a,0x8a,0x0a,0x8d,0x0a,0x91,0x0a,0x95,0x0a,0x98,0x0a,0x9b,0x0a,0x9e,0x0a,0xa1,0x0a,0xa4,0x0a,0xa7,0x0a,0xa9,0x0a,0xab,0x0a,0xad,0x0a,0xaf,0x0a,0xb2,0x0a,0xb7,0x0e,0x22,0x0e,0x41,0x0e,0x45,0x0e,0x49,0x0e,0x4d, 0x0e,0x51,0x0f,0x18,0x0f,0x1c,0x0f,0x20,0x0f,0x26,0x0f,0x2e,0x0f,0x32,0x0f,0x36,0x0f,0x42,0x0f,0x46,0x0f,0x4a,0x0f,0x4e,0x13,0x03,0x13,0x06,0x13,0x09,0x13,0x0d,0x13,0x11,0x13,0x15,0x13,0x19,0x13,0x1d,0x13,0x21,0x14,0x05,0x14,0x0c,0x14,0x10,0x14,0x6f,0x14,0x72,0x14,0x75,0x14,0x78,0x14,0x7b,0x14,0x80,0x14,0x83,0x14,0x86, 0x08,0xf0,0x00,0x02,0x00,0x7b,0x08,0xf1,0x08,0xf1,0x00,0x00,0x09,0x0c,0x09,0x0c,0x00,0x01,0x09,0x0e,0x09,0x0e,0x00,0x02,0x09,0x10,0x09,0x14,0x00,0x03,0x09,0x19,0x09,0x20,0x00,0x08,0x09,0x22,0x09,0x28,0x00,0x10,0x09,0x2a,0x09,0x2b,0x00,0x17,0x09,0x3e,0x09,0x3e,0x00,0x19,0x09,0x40,0x09,0x40,0x00,0x1a,0x09,0x42,0x09,0x42, 0x00,0x1b,0x09,0x46,0x09,0x46,0x00,0x1c,0x09,0x48,0x09,0x48,0x00,0x1d,0x09,0x4a,0x09,0x4a,0x00,0x1e,0x09,0x5b,0x09,0x5b,0x00,0x1f,0x09,0x60,0x09,0x60,0x00,0x20,0x09,0x6c,0x09,0x6c,0x00,0x21,0x09,0x7c,0x09,0x7c,0x00,0x22,0x09,0x8a,0x09,0x8a,0x00,0x23,0x09,0x8c,0x09,0x8c,0x00,0x24,0x09,0x8e,0x09,0x8e,0x00,0x25,0x09,0x90, 0x09,0x90,0x00,0x26,0x09,0x92,0x09,0x92,0x00,0x27,0x09,0x94,0x09,0x94,0x00,0x28,0x09,0x96,0x09,0x96,0x00,0x29,0x09,0x98,0x09,0x98,0x00,0x2a,0x09,0x9b,0x09,0x9b,0x00,0x2b,0x09,0x9e,0x09,0x9e,0x00,0x2c,0x09,0xa1,0x09,0xa1,0x00,0x2d,0x09,0xa4,0x09,0xa4,0x00,0x2e,0x09,0xa7,0x09,0xa7,0x00,0x2f,0x09,0xb9,0x09,0xb9,0x00,0x30, 0x09,0xbb,0x09,0xbb,0x00,0x31,0x09,0xbd,0x09,0xbd,0x00,0x32,0x09,0xbf,0x09,0xbf,0x00,0x33,0x09,0xc1,0x09,0xc1,0x00,0x34,0x09,0xc3,0x09,0xc4,0x00,0x35,0x09,0xc8,0x09,0xc9,0x00,0x37,0x09,0xcc,0x09,0xcc,0x00,0x39,0x09,0xcf,0x09,0xcf,0x00,0x3a,0x09,0xd2,0x09,0xd2,0x00,0x3b,0x09,0xd5,0x09,0xd7,0x00,0x3c,0x09,0xd9,0x09,0xd9, 0x00,0x3f,0x09,0xdb,0x09,0xdb,0x00,0x40,0x09,0xdd,0x09,0xdd,0x00,0x41,0x09,0xdf,0x09,0xdf,0x00,0x42,0x09,0xe1,0x09,0xe1,0x00,0x43,0x09,0xe3,0x09,0xe3,0x00,0x44,0x09,0xe5,0x09,0xe5,0x00,0x45,0x09,0xe7,0x09,0xe7,0x00,0x46,0x09,0xe9,0x09,0xe9,0x00,0x47,0x09,0xeb,0x09,0xeb,0x00,0x48,0x09,0xed,0x09,0xed,0x00,0x49,0x09,0xef, 0x09,0xef,0x00,0x4a,0x09,0xf1,0x09,0xf1,0x00,0x4b,0x09,0xf3,0x09,0xf3,0x00,0x4c,0x09,0xf5,0x09,0xf6,0x00,0x4d,0x09,0xf8,0x09,0xf8,0x00,0x4f,0x09,0xfa,0x09,0xfa,0x00,0x50,0x0a,0x07,0x0a,0x07,0x00,0x51,0x0a,0x0b,0x0a,0x0b,0x00,0x52,0x0a,0x0d,0x0a,0x0d,0x00,0x53,0x0a,0x10,0x0a,0x10,0x00,0x54,0x0a,0x24,0x0a,0x24,0x00,0x55, 0x0a,0x26,0x0a,0x26,0x00,0x56,0x0a,0x28,0x0a,0x28,0x00,0x57,0x0a,0x3e,0x0a,0x3e,0x00,0x58,0x0a,0x58,0x0a,0x58,0x00,0x59,0x0a,0x72,0x0a,0x72,0x00,0x5a,0x0a,0x74,0x0a,0x74,0x00,0x5b,0x0a,0x76,0x0a,0x76,0x00,0x5c,0x0a,0x78,0x0a,0x78,0x00,0x5d,0x0a,0x7a,0x0a,0x7a,0x00,0x5e,0x0a,0x7c,0x0a,0x7c,0x00,0x5f,0x0a,0x7e,0x0a,0x7e, 0x00,0x60,0x0a,0x80,0x0a,0x80,0x00,0x61,0x0a,0x83,0x0a,0x83,0x00,0x62,0x0a,0x89,0x0a,0x89,0x00,0x63,0x0a,0x8b,0x0a,0x8b,0x00,0x64,0x0a,0x8f,0x0a,0x8f,0x00,0x65,0x0a,0x93,0x0a,0x93,0x00,0x66,0x0a,0x97,0x0a,0x97,0x00,0x67,0x0a,0x9a,0x0a,0x9a,0x00,0x68,0x0a,0x9d,0x0a,0x9d,0x00,0x69,0x0a,0xa0,0x0a,0xa0,0x00,0x6a,0x0a,0xa3, 0x0a,0xa3,0x00,0x6b,0x0a,0xa6,0x0a,0xa6,0x00,0x6c,0x0a,0xa8,0x0a,0xa8,0x00,0x6d,0x0a,0xaa,0x0a,0xaa,0x00,0x6e,0x0a,0xac,0x0a,0xac,0x00,0x6f,0x0a,0xae,0x0a,0xae,0x00,0x70,0x0a,0xb0,0x0a,0xb0,0x00,0x71,0x0a,0xb6,0x0a,0xb6,0x00,0x72,0x0e,0x20,0x0e,0x20,0x00,0x73,0x0e,0x3f,0x0e,0x3f,0x00,0x74,0x0e,0x43,0x0e,0x43,0x00,0x75, 0x0e,0x47,0x0e,0x47,0x00,0x76,0x0e,0x4b,0x0e,0x4b,0x00,0x77,0x0e,0x4f,0x0e,0x4f,0x00,0x78,0x0f,0x16,0x0f,0x16,0x00,0x79,0x0f,0x1a,0x0f,0x1a,0x00,0x7a,0x0f,0x1e,0x0f,0x1e,0x00,0x7b,0x0f,0x24,0x0f,0x24,0x00,0x7c,0x0f,0x2c,0x0f,0x2c,0x00,0x7d,0x0f,0x30,0x0f,0x30,0x00,0x7e,0x0f,0x34,0x0f,0x34,0x00,0x7f,0x0f,0x40,0x0f,0x40, 0x00,0x80,0x0f,0x44,0x0f,0x44,0x00,0x81,0x0f,0x48,0x0f,0x48,0x00,0x82,0x0f,0x4c,0x0f,0x4c,0x00,0x83,0x13,0x02,0x13,0x02,0x00,0x84,0x13,0x04,0x13,0x04,0x00,0x85,0x13,0x08,0x13,0x08,0x00,0x86,0x13,0x0c,0x13,0x0c,0x00,0x87,0x13,0x10,0x13,0x10,0x00,0x88,0x13,0x14,0x13,0x14,0x00,0x89,0x13,0x18,0x13,0x18,0x00,0x8a,0x13,0x1c, 0x13,0x1c,0x00,0x8b,0x13,0x20,0x13,0x20,0x00,0x8c,0x14,0x04,0x14,0x04,0x00,0x8d,0x14,0x0b,0x14,0x0b,0x00,0x8e,0x14,0x0f,0x14,0x0f,0x00,0x8f,0x14,0x53,0x14,0x57,0x00,0x90,0x14,0x59,0x14,0x5c,0x00,0x95,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x46,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x02,0x00,0x08,0x08,0xee, 0x08,0xee,0x00,0x00,0x09,0x3f,0x09,0x3f,0x00,0x01,0x09,0xec,0x09,0xec,0x00,0x02,0x09,0xee,0x09,0xee,0x00,0x03,0x09,0xf0,0x09,0xf0,0x00,0x04,0x09,0xf2,0x09,0xf2,0x00,0x05,0x0a,0x5f,0x0a,0x62,0x00,0x06,0x0a,0xb2,0x0a,0xb3,0x00,0x0a,0x00,0x02,0x00,0x07,0x08,0xc7,0x08,0xca,0x00,0x00,0x09,0x81,0x09,0x81,0x00,0x04,0x09,0x83, 0x09,0x83,0x00,0x05,0x09,0x85,0x09,0x85,0x00,0x06,0x09,0x87,0x09,0x87,0x00,0x07,0x0f,0x29,0x0f,0x29,0x00,0x08,0x0f,0x2b,0x0f,0x2b,0x00,0x09,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6e,0x00,0x02,0x00,0x01,0x0f,0x8c,0x0f,0x97,0x00,0x00,0x00,0x02,0x00,0x07,0x08,0xc7,0x08,0xca, 0x00,0x00,0x09,0x81,0x09,0x81,0x00,0x04,0x09,0x83,0x09,0x83,0x00,0x05,0x09,0x85,0x09,0x85,0x00,0x06,0x09,0x87,0x09,0x87,0x00,0x07,0x0f,0x29,0x0f,0x29,0x00,0x08,0x0f,0x2b,0x0f,0x2b,0x00,0x09,0x00,0x01,0x00,0x62,0x00,0x03,0x00,0x0c,0x00,0x2a,0x00,0x44,0x00,0x02,0x00,0x06,0x00,0x14,0x14,0x97,0x00,0x06,0x09,0x3f,0x09,0x3f, 0x09,0x32,0x09,0x73,0x08,0xf3,0x14,0x97,0x00,0x04,0x09,0x3f,0x09,0x3f,0x08,0xf3,0x00,0x02,0x00,0x06,0x00,0x12,0x09,0x71,0x00,0x05,0x09,0x3f,0x09,0x32,0x09,0x73,0x08,0xf3,0x09,0x71,0x00,0x03,0x09,0x3f,0x08,0xf3,0x00,0x02,0x00,0x06,0x00,0x14,0x0a,0x63,0x00,0x06,0x08,0xee,0x09,0x3f,0x09,0x32,0x09,0x73,0x08,0xf3,0x0a,0x63, 0x00,0x04,0x08,0xee,0x09,0x3f,0x08,0xf3,0x00,0x02,0x00,0x03,0x08,0xe8,0x08,0xe8,0x00,0x00,0x08,0xee,0x08,0xee,0x00,0x01,0x09,0x0d,0x09,0x0d,0x00,0x02,0x00,0x01,0x00,0x34,0x00,0x03,0x00,0x0c,0x00,0x1a,0x00,0x26,0x00,0x01,0x00,0x04,0x14,0x97,0x00,0x04,0x09,0x3f,0x09,0x3f,0x09,0x72,0x00,0x01,0x00,0x04,0x09,0x71,0x00,0x03, 0x09,0x3f,0x09,0x72,0x00,0x01,0x00,0x04,0x0a,0x63,0x00,0x04,0x08,0xee,0x09,0x3f,0x09,0x72,0x00,0x02,0x00,0x03,0x08,0xe8,0x08,0xe8,0x00,0x00,0x08,0xee,0x08,0xee,0x00,0x01,0x09,0x0d,0x09,0x0d,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0xb8,0x00,0x01,0x00,0x00,0x00,0x6f,0x00,0x02,0x00,0x1b,0x08,0xd4, 0x08,0xd6,0x00,0x00,0x08,0xe1,0x08,0xe1,0x00,0x03,0x09,0xba,0x09,0xba,0x00,0x04,0x09,0xbc,0x09,0xbc,0x00,0x05,0x09,0xbe,0x09,0xbe,0x00,0x06,0x09,0xc0,0x09,0xc0,0x00,0x07,0x09,0xc2,0x09,0xc2,0x00,0x08,0x0a,0x25,0x0a,0x25,0x00,0x09,0x0a,0x27,0x0a,0x27,0x00,0x0a,0x0a,0x8a,0x0a,0x8a,0x00,0x0b,0x0a,0xb7,0x0a,0xb7,0x00,0x0c, 0x0e,0x32,0x0e,0x32,0x00,0x0d,0x0e,0x34,0x0e,0x34,0x00,0x0e,0x0e,0x36,0x0e,0x36,0x00,0x0f,0x0e,0x38,0x0e,0x38,0x00,0x10,0x0e,0x99,0x0e,0x99,0x00,0x11,0x0e,0x9b,0x0e,0x9b,0x00,0x12,0x0e,0x9d,0x0e,0x9d,0x00,0x13,0x0e,0x9f,0x0e,0x9f,0x00,0x14,0x0e,0xa1,0x0e,0xa1,0x00,0x15,0x0e,0xed,0x0e,0xed,0x00,0x16,0x0e,0xef,0x0e,0xef, 0x00,0x17,0x0f,0x04,0x0f,0x04,0x00,0x18,0x0f,0x15,0x0f,0x15,0x00,0x19,0x0f,0x20,0x0f,0x21,0x00,0x1a,0x0f,0x46,0x0f,0x47,0x00,0x1c,0x0f,0x4a,0x0f,0x4b,0x00,0x1e,0x00,0x02,0x00,0x15,0x08,0xf5,0x08,0xf5,0x00,0x00,0x08,0xf7,0x08,0xf7,0x00,0x01,0x09,0x02,0x09,0x02,0x00,0x02,0x09,0x4b,0x09,0x4b,0x00,0x03,0x09,0x8b,0x09,0x8b, 0x00,0x04,0x0a,0x06,0x0a,0x06,0x00,0x05,0x0a,0x08,0x0a,0x08,0x00,0x06,0x0a,0x0e,0x0a,0x0e,0x00,0x07,0x0a,0x57,0x0a,0x57,0x00,0x08,0x0a,0xb5,0x0a,0xb5,0x00,0x09,0x0b,0x0c,0x0b,0x0d,0x00,0x0a,0x0b,0x0f,0x0b,0x17,0x00,0x0c,0x0e,0x48,0x0e,0x48,0x00,0x15,0x0e,0x4c,0x0e,0x4c,0x00,0x16,0x0e,0x50,0x0e,0x50,0x00,0x17,0x0f,0x02, 0x0f,0x02,0x00,0x18,0x0f,0x23,0x0f,0x23,0x00,0x19,0x0f,0x2d,0x0f,0x2d,0x00,0x1a,0x0f,0x31,0x0f,0x31,0x00,0x1b,0x0f,0x35,0x0f,0x35,0x00,0x1c,0x14,0x7d,0x14,0x7e,0x00,0x1d,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x70,0x00,0x02,0x00,0x01,0x0f,0x6c,0x0f,0x8b,0x00,0x00,0x00,0x02, 0x00,0x16,0x08,0xf5,0x08,0xf5,0x00,0x00,0x08,0xf7,0x08,0xf7,0x00,0x01,0x09,0x02,0x09,0x02,0x00,0x02,0x09,0x4b,0x09,0x4b,0x00,0x03,0x09,0x8b,0x09,0x8b,0x00,0x04,0x0a,0x06,0x0a,0x06,0x00,0x05,0x0a,0x08,0x0a,0x08,0x00,0x06,0x0a,0x0c,0x0a,0x0c,0x00,0x07,0x0a,0x0e,0x0a,0x0e,0x00,0x08,0x0a,0x57,0x0a,0x57,0x00,0x09,0x0a,0xb5, 0x0a,0xb5,0x00,0x0a,0x0b,0x0c,0x0b,0x17,0x00,0x0b,0x0e,0x21,0x0e,0x21,0x00,0x17,0x0e,0x48,0x0e,0x48,0x00,0x18,0x0e,0x4c,0x0e,0x4c,0x00,0x19,0x0e,0x50,0x0e,0x50,0x00,0x1a,0x0f,0x02,0x0f,0x02,0x00,0x1b,0x0f,0x23,0x0f,0x23,0x00,0x1c,0x0f,0x2d,0x0f,0x2d,0x00,0x1d,0x0f,0x31,0x0f,0x31,0x00,0x1e,0x0f,0x35,0x0f,0x35,0x00,0x1f, 0x14,0x7d,0x14,0x7e,0x00,0x20,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x03,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x71,0x00,0x02,0x00,0x7d,0x08,0xca,0x08,0xcb,0x00,0x00,0x08,0xce,0x08,0xce,0x00,0x02,0x08,0xf4,0x08,0xf4,0x00,0x03,0x09,0x0a,0x09,0x0b,0x00,0x04,0x09,0x17,0x09,0x18,0x00,0x06,0x09,0x29,0x09,0x29,0x00,0x08, 0x09,0x2e,0x09,0x2e,0x00,0x09,0x09,0x31,0x09,0x31,0x00,0x0a,0x09,0x41,0x09,0x41,0x00,0x0b,0x09,0x44,0x09,0x45,0x00,0x0c,0x09,0x4c,0x09,0x4c,0x00,0x0e,0x09,0x5e,0x09,0x5e,0x00,0x0f,0x09,0x61,0x09,0x62,0x00,0x10,0x09,0x77,0x09,0x77,0x00,0x12,0x09,0x7f,0x09,0x7f,0x00,0x13,0x09,0x84,0x09,0x85,0x00,0x14,0x09,0x88,0x09,0x89, 0x00,0x16,0x09,0x8f,0x09,0x8f,0x00,0x18,0x09,0x91,0x09,0x91,0x00,0x19,0x09,0x97,0x09,0x97,0x00,0x1a,0x09,0xa0,0x09,0xa0,0x00,0x1b,0x09,0xa3,0x09,0xa3,0x00,0x1c,0x09,0xa9,0x09,0xac,0x00,0x1d,0x09,0xae,0x09,0xae,0x00,0x21,0x09,0xb2,0x09,0xb8,0x00,0x22,0x09,0xba,0x09,0xba,0x00,0x29,0x09,0xbc,0x09,0xbc,0x00,0x2a,0x09,0xbe, 0x09,0xbe,0x00,0x2b,0x09,0xc0,0x09,0xc0,0x00,0x2c,0x09,0xca,0x09,0xcb,0x00,0x2d,0x09,0xcd,0x09,0xce,0x00,0x2f,0x09,0xd0,0x09,0xd1,0x00,0x31,0x09,0xe0,0x09,0xe0,0x00,0x33,0x09,0xe6,0x09,0xe6,0x00,0x34,0x09,0xe8,0x09,0xe8,0x00,0x35,0x09,0xf2,0x09,0xf2,0x00,0x36,0x09,0xf4,0x09,0xf4,0x00,0x37,0x09,0xf7,0x09,0xf7,0x00,0x38, 0x09,0xfc,0x0a,0x04,0x00,0x39,0x0a,0x0a,0x0a,0x0a,0x00,0x42,0x0a,0x1a,0x0a,0x1a,0x00,0x43,0x0a,0x21,0x0a,0x21,0x00,0x44,0x0a,0x23,0x0a,0x23,0x00,0x45,0x0a,0x25,0x0a,0x25,0x00,0x46,0x0a,0x27,0x0a,0x27,0x00,0x47,0x0a,0x2a,0x0a,0x2b,0x00,0x48,0x0a,0x50,0x0a,0x50,0x00,0x4a,0x0a,0x56,0x0a,0x57,0x00,0x4b,0x0a,0x5b,0x0a,0x5b, 0x00,0x4d,0x0a,0x62,0x0a,0x62,0x00,0x4e,0x0a,0x6f,0x0a,0x6f,0x00,0x4f,0x0a,0x73,0x0a,0x73,0x00,0x50,0x0a,0x75,0x0a,0x75,0x00,0x51,0x0a,0x77,0x0a,0x77,0x00,0x52,0x0a,0x79,0x0a,0x79,0x00,0x53,0x0a,0x7b,0x0a,0x7b,0x00,0x54,0x0a,0x7d,0x0a,0x7d,0x00,0x55,0x0a,0x85,0x0a,0x88,0x00,0x56,0x0a,0x98,0x0a,0x99,0x00,0x5a,0x0a,0x9b, 0x0a,0x9c,0x00,0x5c,0x0a,0xa4,0x0a,0xa5,0x00,0x5e,0x0a,0xa9,0x0a,0xa9,0x00,0x60,0x0a,0xab,0x0a,0xab,0x00,0x61,0x0a,0xb4,0x0a,0xb5,0x00,0x62,0x0b,0x0c,0x0b,0x18,0x00,0x64,0x0e,0x1e,0x0e,0x1e,0x00,0x71,0x0e,0x22,0x0e,0x23,0x00,0x72,0x0e,0x27,0x0e,0x27,0x00,0x74,0x0e,0x2c,0x0e,0x2c,0x00,0x75,0x0e,0x45,0x0e,0x46,0x00,0x76, 0x0e,0x49,0x0e,0x4a,0x00,0x78,0x0e,0x4d,0x0e,0x4e,0x00,0x7a,0x0e,0x51,0x0e,0x52,0x00,0x7c,0x0e,0x61,0x0e,0x61,0x00,0x7e,0x0e,0x6b,0x0e,0x6c,0x00,0x7f,0x0e,0x74,0x0e,0x75,0x00,0x81,0x0e,0x7d,0x0e,0x7d,0x00,0x83,0x0e,0x7f,0x0e,0x7f,0x00,0x84,0x0e,0x83,0x0e,0x83,0x00,0x85,0x0e,0x87,0x0e,0x87,0x00,0x86,0x0e,0x8a,0x0e,0x8b, 0x00,0x87,0x0e,0x8d,0x0e,0x8e,0x00,0x89,0x0e,0x90,0x0e,0x92,0x00,0x8b,0x0e,0x94,0x0e,0x94,0x00,0x8e,0x0e,0x99,0x0e,0x99,0x00,0x8f,0x0e,0x9b,0x0e,0x9b,0x00,0x90,0x0e,0x9d,0x0e,0x9d,0x00,0x91,0x0e,0x9f,0x0e,0x9f,0x00,0x92,0x0e,0xbc,0x0e,0xbc,0x00,0x93,0x0e,0xc4,0x0e,0xc4,0x00,0x94,0x0e,0xc6,0x0e,0xc6,0x00,0x95,0x0e,0xce, 0x0e,0xce,0x00,0x96,0x0e,0xd4,0x0e,0xd4,0x00,0x97,0x0e,0xd8,0x0e,0xd9,0x00,0x98,0x0e,0xdc,0x0e,0xe4,0x00,0x9a,0x0e,0xe6,0x0e,0xea,0x00,0xa3,0x0e,0xed,0x0e,0xed,0x00,0xa8,0x0e,0xef,0x0e,0xef,0x00,0xa9,0x0e,0xf1,0x0e,0xf1,0x00,0xaa,0x0e,0xf3,0x0e,0xf3,0x00,0xab,0x0e,0xf5,0x0e,0xf5,0x00,0xac,0x0e,0xf7,0x0e,0xf7,0x00,0xad, 0x0e,0xf9,0x0e,0xf9,0x00,0xae,0x0e,0xfb,0x0e,0xfb,0x00,0xaf,0x0e,0xff,0x0f,0x02,0x00,0xb0,0x0f,0x0d,0x0f,0x0d,0x00,0xb4,0x0f,0x0f,0x0f,0x0f,0x00,0xb5,0x0f,0x18,0x0f,0x19,0x00,0xb6,0x0f,0x1c,0x0f,0x1d,0x00,0xb8,0x0f,0x22,0x0f,0x23,0x00,0xba,0x0f,0x2e,0x0f,0x2f,0x00,0xbc,0x0f,0x32,0x0f,0x33,0x00,0xbe,0x0f,0x36,0x0f,0x3b, 0x00,0xc0,0x0f,0x42,0x0f,0x43,0x00,0xc6,0x0f,0x64,0x0f,0x64,0x00,0xc8,0x0f,0x68,0x0f,0x68,0x00,0xc9,0x0f,0x98,0x0f,0xa6,0x00,0xca,0x13,0x2c,0x13,0x2c,0x00,0xd9,0x13,0x2f,0x13,0x2f,0x00,0xda,0x13,0x33,0x13,0x35,0x00,0xdb,0x13,0x38,0x13,0x38,0x00,0xde,0x13,0x3c,0x13,0x3c,0x00,0xdf,0x13,0x3f,0x13,0x40,0x00,0xe0,0x14,0x62, 0x14,0x62,0x00,0xe2,0x14,0x6c,0x14,0x6c,0x00,0xe3,0x00,0x02,0x00,0x04,0x09,0x66,0x09,0x66,0x00,0x00,0x09,0x68,0x09,0x68,0x00,0x01,0x0f,0x3d,0x0f,0x3d,0x00,0x02,0x0f,0x3f,0x0f,0x3f,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x28,0x04,0xfa,0x00,0x01,0x07,0x86,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x72,0x00,0x03,0x00,0x02,0x00,0x14, 0x07,0x8e,0x00,0x01,0x07,0x72,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x72,0x00,0x02,0x00,0xcd,0x08,0xcb,0x08,0xce,0x00,0x00,0x08,0xd0,0x08,0xd0,0x00,0x04,0x08,0xd2,0x08,0xd2,0x00,0x05,0x08,0xd4,0x08,0xd6,0x00,0x06,0x08,0xe1,0x08,0xe3,0x00,0x09,0x08,0xe5,0x08,0xe6,0x00,0x0c,0x08,0xe8,0x08,0xe9,0x00,0x0e,0x08,0xeb,0x08,0xf0, 0x00,0x10,0x08,0xf4,0x08,0xf4,0x00,0x16,0x08,0xf9,0x08,0xfb,0x00,0x17,0x08,0xff,0x09,0x00,0x00,0x1a,0x09,0x21,0x09,0x21,0x00,0x1c,0x09,0x34,0x09,0x35,0x00,0x1d,0x09,0x3b,0x09,0x3d,0x00,0x1f,0x09,0x3f,0x09,0x3f,0x00,0x22,0x09,0x41,0x09,0x41,0x00,0x23,0x09,0x44,0x09,0x44,0x00,0x24,0x09,0x47,0x09,0x47,0x00,0x25,0x09,0x49, 0x09,0x49,0x00,0x26,0x09,0x4c,0x09,0x4c,0x00,0x27,0x09,0x5c,0x09,0x5c,0x00,0x28,0x09,0x61,0x09,0x62,0x00,0x29,0x09,0x6d,0x09,0x6e,0x00,0x2b,0x09,0x8d,0x09,0x8d,0x00,0x2d,0x09,0x8f,0x09,0x8f,0x00,0x2e,0x09,0x91,0x09,0x91,0x00,0x2f,0x09,0x93,0x09,0x93,0x00,0x30,0x09,0x95,0x09,0x95,0x00,0x31,0x09,0x97,0x09,0x97,0x00,0x32, 0x09,0x9a,0x09,0x9a,0x00,0x33,0x09,0x9d,0x09,0x9d,0x00,0x34,0x09,0xa0,0x09,0xa0,0x00,0x35,0x09,0xa3,0x09,0xa3,0x00,0x36,0x09,0xa6,0x09,0xa6,0x00,0x37,0x09,0xa9,0x09,0xa9,0x00,0x38,0x09,0xba,0x09,0xba,0x00,0x39,0x09,0xbc,0x09,0xbc,0x00,0x3a,0x09,0xbe,0x09,0xbe,0x00,0x3b,0x09,0xc0,0x09,0xc0,0x00,0x3c,0x09,0xc2,0x09,0xc2, 0x00,0x3d,0x09,0xc6,0x09,0xc7,0x00,0x3e,0x09,0xca,0x09,0xcb,0x00,0x40,0x09,0xcd,0x09,0xce,0x00,0x42,0x09,0xd0,0x09,0xd1,0x00,0x44,0x09,0xd3,0x09,0xd4,0x00,0x46,0x09,0xd8,0x09,0xd8,0x00,0x48,0x09,0xda,0x09,0xda,0x00,0x49,0x09,0xdc,0x09,0xdc,0x00,0x4a,0x09,0xde,0x09,0xde,0x00,0x4b,0x09,0xe0,0x09,0xe0,0x00,0x4c,0x09,0xe2, 0x09,0xe2,0x00,0x4d,0x09,0xe4,0x09,0xe4,0x00,0x4e,0x09,0xe6,0x09,0xe6,0x00,0x4f,0x09,0xe8,0x09,0xe8,0x00,0x50,0x09,0xea,0x09,0xea,0x00,0x51,0x09,0xec,0x09,0xec,0x00,0x52,0x09,0xee,0x09,0xee,0x00,0x53,0x09,0xf0,0x09,0xf0,0x00,0x54,0x09,0xf2,0x09,0xf2,0x00,0x55,0x09,0xf4,0x09,0xf4,0x00,0x56,0x09,0xf7,0x09,0xf7,0x00,0x57, 0x09,0xf9,0x09,0xf9,0x00,0x58,0x09,0xfc,0x09,0xfc,0x00,0x59,0x0a,0x09,0x0a,0x09,0x00,0x5a,0x0a,0x10,0x0a,0x10,0x00,0x5b,0x0a,0x25,0x0a,0x25,0x00,0x5c,0x0a,0x27,0x0a,0x27,0x00,0x5d,0x0a,0x2a,0x0a,0x2b,0x00,0x5e,0x0a,0x32,0x0a,0x3b,0x00,0x60,0x0a,0x41,0x0a,0x42,0x00,0x6a,0x0a,0x5a,0x0a,0x5b,0x00,0x6c,0x0a,0x5f,0x0a,0x62, 0x00,0x6e,0x0a,0x73,0x0a,0x73,0x00,0x72,0x0a,0x75,0x0a,0x75,0x00,0x73,0x0a,0x77,0x0a,0x77,0x00,0x74,0x0a,0x79,0x0a,0x79,0x00,0x75,0x0a,0x7b,0x0a,0x7b,0x00,0x76,0x0a,0x7d,0x0a,0x7d,0x00,0x77,0x0a,0x7f,0x0a,0x7f,0x00,0x78,0x0a,0x82,0x0a,0x82,0x00,0x79,0x0a,0x85,0x0a,0x85,0x00,0x7a,0x0a,0x8a,0x0a,0x8a,0x00,0x7b,0x0a,0x8d, 0x0a,0x8e,0x00,0x7c,0x0a,0x91,0x0a,0x92,0x00,0x7e,0x0a,0x95,0x0a,0x96,0x00,0x80,0x0a,0x98,0x0a,0x99,0x00,0x82,0x0a,0x9b,0x0a,0x9c,0x00,0x84,0x0a,0x9e,0x0a,0x9f,0x00,0x86,0x0a,0xa1,0x0a,0xa2,0x00,0x88,0x0a,0xa4,0x0a,0xa5,0x00,0x8a,0x0a,0xa7,0x0a,0xa7,0x00,0x8c,0x0a,0xa9,0x0a,0xa9,0x00,0x8d,0x0a,0xab,0x0a,0xab,0x00,0x8e, 0x0a,0xad,0x0a,0xad,0x00,0x8f,0x0a,0xaf,0x0a,0xaf,0x00,0x90,0x0a,0xb2,0x0a,0xb3,0x00,0x91,0x0a,0xb7,0x0a,0xb7,0x00,0x93,0x0a,0xb9,0x0a,0xba,0x00,0x94,0x0e,0x22,0x0e,0x23,0x00,0x96,0x0e,0x25,0x0e,0x25,0x00,0x98,0x0e,0x27,0x0e,0x27,0x00,0x99,0x0e,0x29,0x0e,0x29,0x00,0x9a,0x0e,0x2b,0x0e,0x2e,0x00,0x9b,0x0e,0x32,0x0e,0x32, 0x00,0x9f,0x0e,0x34,0x0e,0x34,0x00,0xa0,0x0e,0x36,0x0e,0x36,0x00,0xa1,0x0e,0x38,0x0e,0x38,0x00,0xa2,0x0e,0x3a,0x0e,0x3b,0x00,0xa3,0x0e,0x3d,0x0e,0x3e,0x00,0xa5,0x0e,0x41,0x0e,0x42,0x00,0xa7,0x0e,0x45,0x0e,0x46,0x00,0xa9,0x0e,0x49,0x0e,0x4a,0x00,0xab,0x0e,0x4d,0x0e,0x4e,0x00,0xad,0x0e,0x51,0x0e,0x52,0x00,0xaf,0x0e,0x56, 0x0e,0x56,0x00,0xb1,0x0e,0x58,0x0e,0x58,0x00,0xb2,0x0e,0x5a,0x0e,0x5b,0x00,0xb3,0x0e,0x5d,0x0e,0x5d,0x00,0xb5,0x0e,0x5f,0x0e,0x61,0x00,0xb6,0x0e,0x6f,0x0e,0x6f,0x00,0xb9,0x0e,0x71,0x0e,0x72,0x00,0xba,0x0e,0x76,0x0e,0x77,0x00,0xbc,0x0e,0x79,0x0e,0x79,0x00,0xbe,0x0e,0x7b,0x0e,0x7b,0x00,0xbf,0x0e,0x7d,0x0e,0x7d,0x00,0xc0, 0x0e,0x7f,0x0e,0x7f,0x00,0xc1,0x0e,0x81,0x0e,0x81,0x00,0xc2,0x0e,0x83,0x0e,0x83,0x00,0xc3,0x0e,0x85,0x0e,0x85,0x00,0xc4,0x0e,0x87,0x0e,0x8e,0x00,0xc5,0x0e,0x99,0x0e,0x99,0x00,0xcd,0x0e,0x9b,0x0e,0x9b,0x00,0xce,0x0e,0x9d,0x0e,0x9d,0x00,0xcf,0x0e,0x9f,0x0e,0x9f,0x00,0xd0,0x0e,0xa1,0x0e,0xa1,0x00,0xd1,0x0e,0xa3,0x0e,0xa4, 0x00,0xd2,0x0e,0xac,0x0e,0xad,0x00,0xd4,0x0e,0xaf,0x0e,0xb0,0x00,0xd6,0x0e,0xb2,0x0e,0xb2,0x00,0xd8,0x0e,0xb4,0x0e,0xb4,0x00,0xd9,0x0e,0xb6,0x0e,0xb6,0x00,0xda,0x0e,0xb8,0x0e,0xb8,0x00,0xdb,0x0e,0xba,0x0e,0xba,0x00,0xdc,0x0e,0xbc,0x0e,0xbc,0x00,0xdd,0x0e,0xbe,0x0e,0xbe,0x00,0xde,0x0e,0xc0,0x0e,0xc0,0x00,0xdf,0x0e,0xc2, 0x0e,0xc2,0x00,0xe0,0x0e,0xc4,0x0e,0xc4,0x00,0xe1,0x0e,0xc6,0x0e,0xc6,0x00,0xe2,0x0e,0xc8,0x0e,0xc8,0x00,0xe3,0x0e,0xce,0x0e,0xce,0x00,0xe4,0x0e,0xd1,0x0e,0xd2,0x00,0xe5,0x0e,0xd4,0x0e,0xd4,0x00,0xe7,0x0e,0xd6,0x0e,0xd9,0x00,0xe8,0x0e,0xe4,0x0e,0xe5,0x00,0xec,0x0e,0xe7,0x0e,0xea,0x00,0xee,0x0e,0xed,0x0e,0xed,0x00,0xf2, 0x0e,0xef,0x0e,0xef,0x00,0xf3,0x0e,0xf1,0x0e,0xf1,0x00,0xf4,0x0e,0xf3,0x0e,0xf3,0x00,0xf5,0x0e,0xf5,0x0e,0xf5,0x00,0xf6,0x0e,0xf7,0x0e,0xf7,0x00,0xf7,0x0e,0xf9,0x0e,0xf9,0x00,0xf8,0x0e,0xfb,0x0e,0xfb,0x00,0xf9,0x0e,0xfd,0x0e,0xff,0x00,0xfa,0x0f,0x04,0x0f,0x04,0x00,0xfd,0x0f,0x0b,0x0f,0x0b,0x00,0xfe,0x0f,0x0d,0x0f,0x0d, 0x00,0xff,0x0f,0x0f,0x0f,0x0f,0x01,0x00,0x0f,0x11,0x0f,0x11,0x01,0x01,0x0f,0x13,0x0f,0x13,0x01,0x02,0x0f,0x15,0x0f,0x15,0x01,0x03,0x0f,0x18,0x0f,0x19,0x01,0x04,0x0f,0x1c,0x0f,0x1d,0x01,0x06,0x0f,0x20,0x0f,0x21,0x01,0x08,0x0f,0x26,0x0f,0x27,0x01,0x0a,0x0f,0x2e,0x0f,0x2f,0x01,0x0c,0x0f,0x32,0x0f,0x33,0x01,0x0e,0x0f,0x36, 0x0f,0x37,0x01,0x10,0x0f,0x42,0x0f,0x43,0x01,0x12,0x0f,0x46,0x0f,0x47,0x01,0x14,0x0f,0x4a,0x0f,0x4b,0x01,0x16,0x0f,0x4e,0x0f,0x4f,0x01,0x18,0x0f,0x6c,0x0f,0x6c,0x01,0x1a,0x0f,0x6e,0x0f,0x6e,0x01,0x1b,0x0f,0x70,0x0f,0x70,0x01,0x1c,0x0f,0x72,0x0f,0x72,0x01,0x1d,0x0f,0x74,0x0f,0x74,0x01,0x1e,0x0f,0x76,0x0f,0x76,0x01,0x1f, 0x0f,0x78,0x0f,0x78,0x01,0x20,0x0f,0x7a,0x0f,0x7a,0x01,0x21,0x0f,0x7c,0x0f,0x7c,0x01,0x22,0x0f,0x7e,0x0f,0x7e,0x01,0x23,0x0f,0x80,0x0f,0x80,0x01,0x24,0x0f,0x82,0x0f,0x82,0x01,0x25,0x0f,0x84,0x0f,0x84,0x01,0x26,0x0f,0x86,0x0f,0x86,0x01,0x27,0x0f,0x88,0x0f,0x88,0x01,0x28,0x0f,0x8a,0x0f,0x8a,0x01,0x29,0x0f,0x8c,0x0f,0x8c, 0x01,0x2a,0x0f,0x8e,0x0f,0x8e,0x01,0x2b,0x0f,0x90,0x0f,0x90,0x01,0x2c,0x0f,0x92,0x0f,0x92,0x01,0x2d,0x0f,0x94,0x0f,0x94,0x01,0x2e,0x0f,0x96,0x0f,0x96,0x01,0x2f,0x00,0x02,0x00,0x6c,0x08,0xca,0x08,0xcb,0x00,0x00,0x08,0xce,0x08,0xce,0x00,0x02,0x08,0xf4,0x08,0xf4,0x00,0x03,0x09,0x0a,0x09,0x0b,0x00,0x04,0x09,0x17,0x09,0x18, 0x00,0x06,0x09,0x29,0x09,0x29,0x00,0x08,0x09,0x41,0x09,0x41,0x00,0x09,0x09,0x44,0x09,0x45,0x00,0x0a,0x09,0x4c,0x09,0x4c,0x00,0x0c,0x09,0x5e,0x09,0x5e,0x00,0x0d,0x09,0x61,0x09,0x62,0x00,0x0e,0x09,0x77,0x09,0x77,0x00,0x10,0x09,0x7f,0x09,0x7f,0x00,0x11,0x09,0x84,0x09,0x85,0x00,0x12,0x09,0x88,0x09,0x89,0x00,0x14,0x09,0x8f, 0x09,0x8f,0x00,0x16,0x09,0x91,0x09,0x91,0x00,0x17,0x09,0x97,0x09,0x97,0x00,0x18,0x09,0xa0,0x09,0xa0,0x00,0x19,0x09,0xa3,0x09,0xa3,0x00,0x1a,0x09,0xa9,0x09,0xac,0x00,0x1b,0x09,0xae,0x09,0xae,0x00,0x1f,0x09,0xb2,0x09,0xb8,0x00,0x20,0x09,0xba,0x09,0xba,0x00,0x27,0x09,0xbc,0x09,0xbc,0x00,0x28,0x09,0xbe,0x09,0xbe,0x00,0x29, 0x09,0xc0,0x09,0xc0,0x00,0x2a,0x09,0xca,0x09,0xcb,0x00,0x2b,0x09,0xcd,0x09,0xce,0x00,0x2d,0x09,0xd0,0x09,0xd1,0x00,0x2f,0x09,0xe0,0x09,0xe0,0x00,0x31,0x09,0xe6,0x09,0xe6,0x00,0x32,0x09,0xe8,0x09,0xe8,0x00,0x33,0x09,0xf2,0x09,0xf2,0x00,0x34,0x09,0xf4,0x09,0xf4,0x00,0x35,0x09,0xf7,0x09,0xf7,0x00,0x36,0x09,0xfc,0x0a,0x04, 0x00,0x37,0x0a,0x0a,0x0a,0x0a,0x00,0x40,0x0a,0x25,0x0a,0x25,0x00,0x41,0x0a,0x27,0x0a,0x27,0x00,0x42,0x0a,0x2a,0x0a,0x2b,0x00,0x43,0x0a,0x56,0x0a,0x57,0x00,0x45,0x0a,0x5b,0x0a,0x5b,0x00,0x47,0x0a,0x62,0x0a,0x62,0x00,0x48,0x0a,0x73,0x0a,0x73,0x00,0x49,0x0a,0x75,0x0a,0x75,0x00,0x4a,0x0a,0x77,0x0a,0x77,0x00,0x4b,0x0a,0x79, 0x0a,0x79,0x00,0x4c,0x0a,0x7b,0x0a,0x7b,0x00,0x4d,0x0a,0x7d,0x0a,0x7d,0x00,0x4e,0x0a,0x85,0x0a,0x88,0x00,0x4f,0x0a,0x98,0x0a,0x99,0x00,0x53,0x0a,0x9b,0x0a,0x9c,0x00,0x55,0x0a,0xa4,0x0a,0xa5,0x00,0x57,0x0a,0xa9,0x0a,0xa9,0x00,0x59,0x0a,0xab,0x0a,0xab,0x00,0x5a,0x0a,0xb4,0x0a,0xb5,0x00,0x5b,0x0b,0x0c,0x0b,0x18,0x00,0x5d, 0x0e,0x22,0x0e,0x23,0x00,0x6a,0x0e,0x27,0x0e,0x27,0x00,0x6c,0x0e,0x2c,0x0e,0x2c,0x00,0x6d,0x0e,0x45,0x0e,0x46,0x00,0x6e,0x0e,0x49,0x0e,0x4a,0x00,0x70,0x0e,0x4d,0x0e,0x4e,0x00,0x72,0x0e,0x51,0x0e,0x52,0x00,0x74,0x0e,0x61,0x0e,0x61,0x00,0x76,0x0e,0x74,0x0e,0x75,0x00,0x77,0x0e,0x7d,0x0e,0x7d,0x00,0x79,0x0e,0x7f,0x0e,0x7f, 0x00,0x7a,0x0e,0x83,0x0e,0x83,0x00,0x7b,0x0e,0x87,0x0e,0x87,0x00,0x7c,0x0e,0x8a,0x0e,0x8b,0x00,0x7d,0x0e,0x8d,0x0e,0x8e,0x00,0x7f,0x0e,0x90,0x0e,0x92,0x00,0x81,0x0e,0x94,0x0e,0x94,0x00,0x84,0x0e,0x99,0x0e,0x99,0x00,0x85,0x0e,0x9b,0x0e,0x9b,0x00,0x86,0x0e,0x9d,0x0e,0x9d,0x00,0x87,0x0e,0x9f,0x0e,0x9f,0x00,0x88,0x0e,0xbc, 0x0e,0xbc,0x00,0x89,0x0e,0xc4,0x0e,0xc4,0x00,0x8a,0x0e,0xc6,0x0e,0xc6,0x00,0x8b,0x0e,0xce,0x0e,0xce,0x00,0x8c,0x0e,0xd4,0x0e,0xd4,0x00,0x8d,0x0e,0xd8,0x0e,0xd9,0x00,0x8e,0x0e,0xdc,0x0e,0xe4,0x00,0x90,0x0e,0xe6,0x0e,0xea,0x00,0x99,0x0e,0xed,0x0e,0xed,0x00,0x9e,0x0e,0xef,0x0e,0xef,0x00,0x9f,0x0e,0xf1,0x0e,0xf1,0x00,0xa0, 0x0e,0xf3,0x0e,0xf3,0x00,0xa1,0x0e,0xf5,0x0e,0xf5,0x00,0xa2,0x0e,0xf7,0x0e,0xf7,0x00,0xa3,0x0e,0xf9,0x0e,0xf9,0x00,0xa4,0x0e,0xfb,0x0e,0xfb,0x00,0xa5,0x0e,0xff,0x0f,0x02,0x00,0xa6,0x0f,0x0d,0x0f,0x0d,0x00,0xaa,0x0f,0x0f,0x0f,0x0f,0x00,0xab,0x0f,0x18,0x0f,0x19,0x00,0xac,0x0f,0x1c,0x0f,0x1d,0x00,0xae,0x0f,0x22,0x0f,0x23, 0x00,0xb0,0x0f,0x2e,0x0f,0x2f,0x00,0xb2,0x0f,0x32,0x0f,0x33,0x00,0xb4,0x0f,0x36,0x0f,0x3b,0x00,0xb6,0x0f,0x42,0x0f,0x43,0x00,0xbc,0x0f,0x64,0x0f,0x64,0x00,0xbe,0x0f,0x68,0x0f,0x68,0x00,0xbf,0x0f,0x98,0x0f,0xa6,0x00,0xc0,0x00,0x02,0x00,0x04,0x09,0x66,0x09,0x66,0x00,0x00,0x09,0x68,0x09,0x68,0x00,0x01,0x0f,0x3d,0x0f,0x3d, 0x00,0x02,0x0f,0x3f,0x0f,0x3f,0x00,0x03,0x00,0x02,0x00,0x13,0x09,0x2e,0x09,0x2e,0x00,0x00,0x09,0x31,0x09,0x31,0x00,0x01,0x09,0x77,0x09,0x77,0x00,0x02,0x09,0x7f,0x09,0x7f,0x00,0x03,0x0a,0x1a,0x0a,0x1a,0x00,0x04,0x0a,0x21,0x0a,0x21,0x00,0x05,0x0a,0x23,0x0a,0x23,0x00,0x06,0x0a,0x50,0x0a,0x50,0x00,0x07,0x0a,0x6f,0x0a,0x6f, 0x00,0x08,0x0e,0x1e,0x0e,0x1e,0x00,0x09,0x0e,0x6b,0x0e,0x6c,0x00,0x0a,0x13,0x2c,0x13,0x2c,0x00,0x0c,0x13,0x2f,0x13,0x2f,0x00,0x0d,0x13,0x33,0x13,0x35,0x00,0x0e,0x13,0x38,0x13,0x38,0x00,0x11,0x13,0x3c,0x13,0x3c,0x00,0x12,0x13,0x3f,0x13,0x40,0x00,0x13,0x14,0x62,0x14,0x62,0x00,0x15,0x14,0x6c,0x14,0x6c,0x00,0x16,0x00,0x03, 0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x28,0x00,0x01,0x00,0x00,0x00,0x73,0x00,0x02,0x00,0x03,0x00,0x4c,0x00,0x4d,0x00,0x00,0x01,0x62,0x01,0x62,0x00,0x02,0x05,0x6d,0x05,0x6d,0x00,0x03,0x00,0x02,0x00,0x11,0x02,0x44,0x02,0x44,0x00,0x00,0x02,0x46,0x02,0x47,0x00,0x01,0x04,0x62,0x04,0x73,0x00,0x03,0x04,0x79,0x04,0x79, 0x00,0x15,0x04,0x9b,0x04,0x9d,0x00,0x16,0x04,0xa0,0x04,0xa2,0x00,0x19,0x04,0xa4,0x04,0xa4,0x00,0x1c,0x04,0xa8,0x04,0xaa,0x00,0x1d,0x05,0xfd,0x06,0x00,0x00,0x20,0x06,0x66,0x06,0x72,0x00,0x24,0x07,0x55,0x07,0x57,0x00,0x31,0x07,0x5c,0x07,0x5c,0x00,0x34,0x07,0xef,0x07,0xef,0x00,0x35,0x08,0x4c,0x08,0x4d,0x00,0x36,0x08,0x4f, 0x08,0x4f,0x00,0x38,0x0a,0xdb,0x0a,0xe0,0x00,0x39,0x0a,0xe2,0x0a,0xe2,0x00,0x3f,0x00,0x01,0x05,0x6a,0x00,0x05,0x00,0x10,0x01,0x22,0x02,0x34,0x03,0x46,0x04,0x58,0x00,0x1c,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x6a,0x00,0x72,0x00,0x7a,0x00,0x82,0x00,0x88,0x00,0x90,0x00,0x98,0x00,0xa0,0x00,0xa8, 0x00,0xb0,0x00,0xb6,0x00,0xbe,0x00,0xc6,0x00,0xce,0x00,0xd6,0x00,0xde,0x00,0xe4,0x00,0xec,0x00,0xf4,0x00,0xfc,0x01,0x04,0x01,0x0c,0x06,0xae,0x00,0x03,0x06,0xa2,0x06,0xa3,0x06,0xaf,0x00,0x03,0x06,0xa2,0x06,0xa4,0x06,0xb0,0x00,0x03,0x06,0xa2,0x06,0xa5,0x06,0xb1,0x00,0x03,0x06,0xa2,0x06,0xa6,0x06,0xb2,0x00,0x03,0x06,0xa3, 0x06,0xa2,0x06,0xb3,0x00,0x03,0x06,0xa3,0x06,0xa3,0x06,0xb4,0x00,0x03,0x06,0xa3,0x06,0xa4,0x06,0xb5,0x00,0x03,0x06,0xa3,0x06,0xa5,0x06,0xb6,0x00,0x03,0x06,0xa3,0x06,0xa6,0x06,0xb7,0x00,0x02,0x06,0xa3,0x06,0xb8,0x00,0x03,0x06,0xa4,0x06,0xa2,0x06,0xb9,0x00,0x03,0x06,0xa4,0x06,0xa3,0x06,0xba,0x00,0x03,0x06,0xa4,0x06,0xa4, 0x06,0xbb,0x00,0x03,0x06,0xa4,0x06,0xa5,0x06,0xbc,0x00,0x03,0x06,0xa4,0x06,0xa6,0x06,0xbd,0x00,0x02,0x06,0xa4,0x06,0xbe,0x00,0x03,0x06,0xa5,0x06,0xa2,0x06,0xbf,0x00,0x03,0x06,0xa5,0x06,0xa3,0x06,0xc0,0x00,0x03,0x06,0xa5,0x06,0xa4,0x06,0xc1,0x00,0x03,0x06,0xa5,0x06,0xa5,0x06,0xc2,0x00,0x03,0x06,0xa5,0x06,0xa6,0x06,0xc3, 0x00,0x02,0x06,0xa5,0x06,0xc4,0x00,0x03,0x06,0xa6,0x06,0xa2,0x06,0xc5,0x00,0x03,0x06,0xa6,0x06,0xa3,0x06,0xc6,0x00,0x03,0x06,0xa6,0x06,0xa4,0x06,0xc7,0x00,0x03,0x06,0xa6,0x06,0xa5,0x06,0xc8,0x00,0x03,0x06,0xa6,0x06,0xa6,0x06,0xc9,0x00,0x02,0x06,0xa6,0x00,0x1c,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62, 0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00,0x90,0x00,0x98,0x00,0xa0,0x00,0xa8,0x00,0xb0,0x00,0xb6,0x00,0xbe,0x00,0xc6,0x00,0xce,0x00,0xd6,0x00,0xde,0x00,0xe4,0x00,0xec,0x00,0xf4,0x00,0xfc,0x01,0x04,0x01,0x0c,0x06,0xca,0x00,0x03,0x06,0xa2,0x06,0xa2,0x06,0xcb,0x00,0x03,0x06,0xa2,0x06,0xa3,0x06,0xcc,0x00,0x03, 0x06,0xa2,0x06,0xa4,0x06,0xcd,0x00,0x03,0x06,0xa2,0x06,0xa5,0x06,0xce,0x00,0x03,0x06,0xa2,0x06,0xa6,0x06,0xcf,0x00,0x02,0x06,0xa2,0x06,0xd0,0x00,0x03,0x06,0xa3,0x06,0xa2,0x06,0xd1,0x00,0x03,0x06,0xa3,0x06,0xa4,0x06,0xd2,0x00,0x03,0x06,0xa3,0x06,0xa5,0x06,0xd3,0x00,0x03,0x06,0xa3,0x06,0xa6,0x06,0xd4,0x00,0x03,0x06,0xa4, 0x06,0xa2,0x06,0xd5,0x00,0x03,0x06,0xa4,0x06,0xa3,0x06,0xd6,0x00,0x03,0x06,0xa4,0x06,0xa4,0x06,0xd7,0x00,0x03,0x06,0xa4,0x06,0xa5,0x06,0xd8,0x00,0x03,0x06,0xa4,0x06,0xa6,0x06,0xd9,0x00,0x02,0x06,0xa4,0x06,0xda,0x00,0x03,0x06,0xa5,0x06,0xa2,0x06,0xdb,0x00,0x03,0x06,0xa5,0x06,0xa3,0x06,0xdc,0x00,0x03,0x06,0xa5,0x06,0xa4, 0x06,0xdd,0x00,0x03,0x06,0xa5,0x06,0xa5,0x06,0xde,0x00,0x03,0x06,0xa5,0x06,0xa6,0x06,0xdf,0x00,0x02,0x06,0xa5,0x06,0xe0,0x00,0x03,0x06,0xa6,0x06,0xa2,0x06,0xe1,0x00,0x03,0x06,0xa6,0x06,0xa3,0x06,0xe2,0x00,0x03,0x06,0xa6,0x06,0xa4,0x06,0xe3,0x00,0x03,0x06,0xa6,0x06,0xa5,0x06,0xe4,0x00,0x03,0x06,0xa6,0x06,0xa6,0x06,0xe5, 0x00,0x02,0x06,0xa6,0x00,0x1c,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00,0x90,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6,0x00,0xbe,0x00,0xc6,0x00,0xce,0x00,0xd6,0x00,0xde,0x00,0xe4,0x00,0xec,0x00,0xf4,0x00,0xfc,0x01,0x04,0x01,0x0c,0x06,0xe6, 0x00,0x03,0x06,0xa2,0x06,0xa2,0x06,0xe7,0x00,0x03,0x06,0xa2,0x06,0xa3,0x06,0xe8,0x00,0x03,0x06,0xa2,0x06,0xa4,0x06,0xe9,0x00,0x03,0x06,0xa2,0x06,0xa5,0x06,0xea,0x00,0x03,0x06,0xa2,0x06,0xa6,0x06,0xeb,0x00,0x02,0x06,0xa2,0x06,0xeb,0x00,0x03,0x06,0xa3,0x06,0xa2,0x06,0xec,0x00,0x03,0x06,0xa3,0x06,0xa3,0x06,0xed,0x00,0x03, 0x06,0xa3,0x06,0xa4,0x06,0xee,0x00,0x03,0x06,0xa3,0x06,0xa5,0x06,0xef,0x00,0x03,0x06,0xa3,0x06,0xa6,0x06,0xf0,0x00,0x02,0x06,0xa3,0x06,0xf1,0x00,0x03,0x06,0xa4,0x06,0xa2,0x06,0xf2,0x00,0x03,0x06,0xa4,0x06,0xa3,0x06,0xf3,0x00,0x03,0x06,0xa4,0x06,0xa5,0x06,0xf4,0x00,0x03,0x06,0xa4,0x06,0xa6,0x06,0xf5,0x00,0x03,0x06,0xa5, 0x06,0xa2,0x06,0xf6,0x00,0x03,0x06,0xa5,0x06,0xa3,0x06,0xf7,0x00,0x03,0x06,0xa5,0x06,0xa4,0x06,0xf8,0x00,0x03,0x06,0xa5,0x06,0xa5,0x06,0xf9,0x00,0x03,0x06,0xa5,0x06,0xa6,0x06,0xfa,0x00,0x02,0x06,0xa5,0x06,0xfb,0x00,0x03,0x06,0xa6,0x06,0xa2,0x06,0xfc,0x00,0x03,0x06,0xa6,0x06,0xa3,0x06,0xfd,0x00,0x03,0x06,0xa6,0x06,0xa4, 0x06,0xfe,0x00,0x03,0x06,0xa6,0x06,0xa5,0x06,0xff,0x00,0x03,0x06,0xa6,0x06,0xa6,0x07,0x00,0x00,0x02,0x06,0xa6,0x00,0x1c,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00,0x90,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6,0x00,0xbe,0x00,0xc4,0x00,0xcc, 0x00,0xd4,0x00,0xdc,0x00,0xe4,0x00,0xea,0x00,0xf2,0x00,0xfa,0x01,0x02,0x01,0x0a,0x07,0x01,0x00,0x03,0x06,0xa2,0x06,0xa2,0x07,0x02,0x00,0x03,0x06,0xa2,0x06,0xa3,0x07,0x03,0x00,0x03,0x06,0xa2,0x06,0xa4,0x07,0x04,0x00,0x03,0x06,0xa2,0x06,0xa5,0x07,0x05,0x00,0x03,0x06,0xa2,0x06,0xa6,0x07,0x06,0x00,0x02,0x06,0xa2,0x07,0x07, 0x00,0x03,0x06,0xa3,0x06,0xa2,0x07,0x08,0x00,0x03,0x06,0xa3,0x06,0xa3,0x07,0x09,0x00,0x03,0x06,0xa3,0x06,0xa4,0x07,0x0a,0x00,0x03,0x06,0xa3,0x06,0xa5,0x07,0x0b,0x00,0x03,0x06,0xa3,0x06,0xa6,0x07,0x0c,0x00,0x02,0x06,0xa3,0x07,0x0d,0x00,0x03,0x06,0xa4,0x06,0xa2,0x07,0x0e,0x00,0x03,0x06,0xa4,0x06,0xa3,0x07,0x0f,0x00,0x03, 0x06,0xa4,0x06,0xa4,0x07,0x10,0x00,0x03,0x06,0xa4,0x06,0xa5,0x07,0x11,0x00,0x03,0x06,0xa4,0x06,0xa6,0x07,0x12,0x00,0x02,0x06,0xa4,0x07,0x13,0x00,0x03,0x06,0xa5,0x06,0xa2,0x07,0x14,0x00,0x03,0x06,0xa5,0x06,0xa3,0x07,0x15,0x00,0x03,0x06,0xa5,0x06,0xa4,0x07,0x16,0x00,0x03,0x06,0xa5,0x06,0xa6,0x07,0x1c,0x00,0x02,0x06,0xa6, 0x07,0x17,0x00,0x03,0x06,0xa6,0x06,0xa2,0x07,0x18,0x00,0x03,0x06,0xa6,0x06,0xa3,0x07,0x19,0x00,0x03,0x06,0xa6,0x06,0xa4,0x07,0x1a,0x00,0x03,0x06,0xa6,0x06,0xa5,0x07,0x1b,0x00,0x03,0x06,0xa6,0x06,0xa6,0x00,0x1c,0x00,0x3a,0x00,0x42,0x00,0x4a,0x00,0x52,0x00,0x5a,0x00,0x62,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88, 0x00,0x90,0x00,0x96,0x00,0x9e,0x00,0xa6,0x00,0xae,0x00,0xb6,0x00,0xbe,0x00,0xc4,0x00,0xcc,0x00,0xd4,0x00,0xdc,0x00,0xe4,0x00,0xec,0x00,0xf2,0x00,0xfa,0x01,0x02,0x01,0x0a,0x07,0x1d,0x00,0x03,0x06,0xa2,0x06,0xa2,0x07,0x1e,0x00,0x03,0x06,0xa2,0x06,0xa3,0x07,0x1f,0x00,0x03,0x06,0xa2,0x06,0xa4,0x07,0x20,0x00,0x03,0x06,0xa2, 0x06,0xa5,0x07,0x21,0x00,0x03,0x06,0xa2,0x06,0xa6,0x07,0x22,0x00,0x02,0x06,0xa2,0x07,0x23,0x00,0x03,0x06,0xa3,0x06,0xa2,0x07,0x24,0x00,0x03,0x06,0xa3,0x06,0xa3,0x07,0x25,0x00,0x03,0x06,0xa3,0x06,0xa4,0x07,0x26,0x00,0x03,0x06,0xa3,0x06,0xa5,0x07,0x27,0x00,0x03,0x06,0xa3,0x06,0xa6,0x07,0x28,0x00,0x02,0x06,0xa3,0x07,0x29, 0x00,0x03,0x06,0xa4,0x06,0xa2,0x07,0x2a,0x00,0x03,0x06,0xa4,0x06,0xa3,0x07,0x2b,0x00,0x03,0x06,0xa4,0x06,0xa4,0x07,0x2c,0x00,0x03,0x06,0xa4,0x06,0xa5,0x07,0x2d,0x00,0x03,0x06,0xa4,0x06,0xa6,0x07,0x2e,0x00,0x02,0x06,0xa4,0x07,0x2f,0x00,0x03,0x06,0xa5,0x06,0xa2,0x07,0x30,0x00,0x03,0x06,0xa5,0x06,0xa3,0x07,0x31,0x00,0x03, 0x06,0xa5,0x06,0xa4,0x07,0x32,0x00,0x03,0x06,0xa5,0x06,0xa5,0x07,0x33,0x00,0x03,0x06,0xa5,0x06,0xa6,0x07,0x34,0x00,0x02,0x06,0xa5,0x07,0x35,0x00,0x03,0x06,0xa6,0x06,0xa2,0x07,0x36,0x00,0x03,0x06,0xa6,0x06,0xa3,0x07,0x37,0x00,0x03,0x06,0xa6,0x06,0xa4,0x07,0x38,0x00,0x03,0x06,0xa6,0x06,0xa5,0x00,0x02,0x00,0x01,0x06,0xa2, 0x06,0xa6,0x00,0x00,0x00,0x01,0x01,0x92,0x00,0x03,0x00,0x0c,0x00,0x6e,0x01,0x00,0x00,0x08,0x00,0x12,0x00,0x1c,0x00,0x26,0x00,0x30,0x00,0x3a,0x00,0x44,0x00,0x4e,0x00,0x58,0x08,0x62,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x46,0x08,0x63,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x47,0x08,0x64,0x00,0x04,0x04,0x64,0x04,0x73,0x02,0x46, 0x08,0x65,0x00,0x04,0x04,0x64,0x04,0x73,0x02,0x47,0x08,0x66,0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x46,0x08,0x67,0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x47,0x08,0x68,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x46,0x08,0x69,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x47,0x00,0x0c,0x00,0x1a,0x00,0x24,0x00,0x2e,0x00,0x38,0x00,0x42,0x00,0x4c, 0x00,0x56,0x00,0x60,0x00,0x6a,0x00,0x74,0x00,0x7e,0x00,0x88,0x08,0x6a,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x46,0x08,0x6b,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x47,0x08,0x6c,0x00,0x04,0x04,0x64,0x04,0x73,0x02,0x46,0x08,0x6d,0x00,0x04,0x04,0x64,0x04,0x73,0x02,0x47,0x08,0x6e,0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x46,0x08,0x6f, 0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x47,0x08,0x70,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x46,0x08,0x71,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x47,0x08,0x7a,0x00,0x04,0x04,0x68,0x04,0x64,0x02,0x46,0x08,0x7b,0x00,0x04,0x04,0x68,0x04,0x64,0x02,0x47,0x08,0x7c,0x00,0x04,0x04,0x68,0x04,0x66,0x02,0x46,0x08,0x7d,0x00,0x04,0x04,0x68, 0x04,0x66,0x02,0x47,0x00,0x0c,0x00,0x1a,0x00,0x24,0x00,0x2e,0x00,0x38,0x00,0x42,0x00,0x4c,0x00,0x56,0x00,0x60,0x00,0x6a,0x00,0x74,0x00,0x7e,0x00,0x88,0x08,0x72,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x46,0x08,0x73,0x00,0x04,0x04,0x64,0x04,0x72,0x02,0x47,0x08,0x74,0x00,0x04,0x04,0x64,0x04,0x73,0x02,0x46,0x08,0x75,0x00,0x04, 0x04,0x64,0x04,0x73,0x02,0x47,0x08,0x76,0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x46,0x08,0x77,0x00,0x04,0x04,0x66,0x04,0x72,0x02,0x47,0x08,0x78,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x46,0x08,0x79,0x00,0x04,0x04,0x66,0x04,0x73,0x02,0x47,0x08,0x7e,0x00,0x04,0x04,0x68,0x04,0x64,0x02,0x46,0x08,0x7f,0x00,0x04,0x04,0x68,0x04,0x64, 0x02,0x47,0x08,0x80,0x00,0x04,0x04,0x68,0x04,0x66,0x02,0x46,0x08,0x81,0x00,0x04,0x04,0x68,0x04,0x66,0x02,0x47,0x00,0x02,0x00,0x03,0x01,0x2f,0x01,0x2f,0x00,0x00,0x01,0xc9,0x01,0xc9,0x00,0x01,0x01,0xd2,0x01,0xd2,0x00,0x02,0x00,0x02,0x00,0x1a,0x00,0x0a,0x08,0xa5,0x08,0xa6,0x08,0xa7,0x08,0xa8,0x08,0xa9,0x08,0xaa,0x08,0xab, 0x08,0xac,0x08,0xad,0x08,0xae,0x00,0x02,0x00,0x01,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02,0x00,0x1e,0x00,0x0c,0x08,0x99,0x08,0x98,0x08,0x96,0x08,0x97,0x08,0x9a,0x08,0x9b,0x08,0x9c,0x08,0x9d,0x08,0x9e,0x08,0x9f,0x08,0x95,0x01,0x37,0x00,0x02,0x00,0x03,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x4c,0x00,0x4c,0x00,0x0a,0x00,0x51, 0x00,0x51,0x00,0x0b,0x00,0x02,0x00,0x64,0x00,0x2f,0x0d,0x8a,0x0d,0x8b,0x0d,0x8c,0x0d,0x8d,0x0d,0x8e,0x0d,0x90,0x0d,0x92,0x0d,0x93,0x0d,0x94,0x0d,0x95,0x0d,0x96,0x0d,0x97,0x0d,0x98,0x0d,0x99,0x0d,0x9a,0x0d,0x9b,0x0d,0x9c,0x0d,0x9d,0x0d,0x9e,0x0d,0x9f,0x0d,0xa0,0x0d,0xa1,0x0d,0xa2,0x0d,0xa3,0x0d,0xa4,0x0d,0xa5,0x0d,0xa6, 0x0d,0xa7,0x0d,0xa8,0x0d,0xa9,0x0d,0xaa,0x0d,0xab,0x0d,0xac,0x0d,0xad,0x0d,0xae,0x0d,0xaf,0x0d,0xb0,0x0d,0xb1,0x0d,0xb2,0x0d,0xb3,0x0d,0xb4,0x0d,0xb5,0x0d,0xb6,0x0d,0xb7,0x0d,0xb8,0x0d,0x8f,0x0d,0x91,0x00,0x02,0x00,0x03,0x01,0xdb,0x02,0x06,0x00,0x00,0x02,0x33,0x02,0x33,0x00,0x2c,0x02,0xb5,0x02,0xb6,0x00,0x2d,0x00,0x02, 0x00,0x64,0x00,0x2f,0x0d,0x98,0x0d,0x99,0x0d,0x9a,0x0d,0x9b,0x0d,0x9c,0x0d,0x9d,0x0d,0x9e,0x0d,0x9f,0x0d,0xa0,0x0d,0xa1,0x0d,0xa2,0x0d,0xa3,0x0d,0xa4,0x0d,0xa5,0x0d,0xa6,0x0d,0xa7,0x0d,0xa8,0x0d,0xa9,0x0d,0xaa,0x0d,0xab,0x0d,0xac,0x0d,0xad,0x0d,0xae,0x0d,0xaf,0x0d,0xb0,0x0d,0xb1,0x0d,0xb2,0x0d,0xb3,0x0d,0xb4,0x0d,0xb5, 0x0d,0xb6,0x0d,0xb7,0x0d,0x8a,0x0d,0x8b,0x0d,0x8c,0x0d,0x8d,0x0d,0x8e,0x0d,0x90,0x0d,0x92,0x0d,0x93,0x0d,0x94,0x0d,0x95,0x0d,0x96,0x0d,0x97,0x0d,0xb8,0x0d,0x8f,0x0d,0x91,0x00,0x02,0x00,0x03,0x02,0x07,0x02,0x32,0x00,0x00,0x02,0x34,0x02,0x34,0x00,0x2c,0x02,0xb7,0x02,0xb8,0x00,0x2d,0x00,0x02,0x00,0x48,0x00,0x21,0x0d,0x6c, 0x0d,0x6b,0x0d,0x70,0x0d,0x7d,0x0d,0x81,0x0d,0x82,0x0d,0x83,0x0d,0x84,0x0d,0x85,0x0d,0x86,0x0d,0x87,0x0d,0x69,0x0d,0x6a,0x0d,0x6d,0x0d,0x6e,0x0d,0x6f,0x0d,0x71,0x0d,0x72,0x0d,0x73,0x0d,0x74,0x0d,0x75,0x0d,0x76,0x0d,0x77,0x0d,0x78,0x0d,0x79,0x0d,0x7a,0x0d,0x7b,0x0d,0x7c,0x0d,0x7e,0x0d,0x7f,0x0d,0x80,0x0d,0x88,0x0d,0x89, 0x00,0x02,0x00,0x04,0x00,0xa9,0x00,0xa9,0x00,0x00,0x01,0x2c,0x01,0x2e,0x00,0x01,0x01,0xa1,0x01,0xa7,0x00,0x04,0x01,0xa9,0x01,0xbe,0x00,0x0b,0x00,0x02,0x00,0x4a,0x00,0x22,0x0d,0x69,0x0d,0x6c,0x0d,0x6d,0x0d,0x7a,0x0d,0x7b,0x0d,0x7d,0x0d,0x81,0x0d,0x82,0x0d,0x83,0x0d,0x84,0x0d,0x6a,0x0d,0x6b,0x0d,0x6e,0x0d,0x6f,0x0d,0x70, 0x0d,0x71,0x0d,0x72,0x0d,0x73,0x0d,0x74,0x0d,0x75,0x0d,0x76,0x0d,0x77,0x0d,0x79,0x0d,0x7a,0x0d,0x7c,0x0d,0x7e,0x0d,0x7f,0x0d,0x80,0x0d,0x88,0x0d,0x89,0x0d,0x85,0x0d,0x86,0x0d,0x87,0x0d,0x78,0x00,0x02,0x00,0x04,0x01,0x2f,0x01,0x34,0x00,0x00,0x01,0xbf,0x01,0xc2,0x00,0x06,0x01,0xc4,0x01,0xda,0x00,0x0a,0x02,0x37,0x02,0x37, 0x00,0x21,0x00,0x02,0x01,0x08,0x00,0x81,0x0d,0xbe,0x0c,0xeb,0x0c,0xec,0x0c,0xed,0x0c,0xee,0x0c,0xef,0x0c,0xf0,0x0c,0xf1,0x0c,0xf2,0x0c,0xf3,0x0c,0xf4,0x0c,0xf5,0x0c,0xf6,0x0c,0xf7,0x0c,0xf8,0x0c,0xf9,0x0c,0xfa,0x0c,0xfb,0x0c,0xfc,0x0c,0xfd,0x0c,0xfe,0x0c,0xff,0x0d,0x00,0x0d,0x01,0x0d,0x02,0x0d,0x03,0x0d,0x04,0x0d,0x10, 0x0d,0x11,0x0d,0x12,0x0d,0x14,0x0d,0x1b,0x0d,0x20,0x0d,0x24,0x0d,0x05,0x0d,0x08,0x0d,0x0c,0x0d,0x0f,0x0d,0x1f,0x0d,0x06,0x0d,0x61,0x0d,0x0e,0x0d,0x15,0x0d,0x0d,0x0d,0x16,0x0d,0x13,0x0d,0x18,0x0d,0x19,0x0d,0x1a,0x0d,0x17,0x0d,0x1d,0x0d,0x1e,0x0d,0x1c,0x0d,0x22,0x0d,0x23,0x0d,0x21,0x0d,0x07,0x0d,0x51,0x0d,0x65,0x0d,0x0a, 0x0d,0x25,0x0d,0x09,0x0d,0x33,0x0d,0x3c,0x0d,0x50,0x0d,0x29,0x0d,0x2a,0x0d,0x27,0x0d,0x28,0x0d,0x2c,0x0d,0x2d,0x0d,0x31,0x0d,0x32,0x0d,0x40,0x0d,0x42,0x0d,0x43,0x0d,0x44,0x0d,0x46,0x0d,0x4a,0x0d,0x4b,0x0d,0x4d,0x0d,0x4e,0x0d,0x52,0x0d,0x54,0x0d,0x59,0x0d,0x5a,0x0d,0x63,0x0d,0x64,0x0d,0x3d,0x0d,0x26,0x0d,0xbf,0x0d,0x35, 0x0d,0x2e,0x0d,0x2f,0x0d,0x30,0x0d,0xc0,0x0d,0x2b,0x0d,0x34,0x0d,0x36,0x0d,0x37,0x0d,0x38,0x0d,0x39,0x0d,0x3a,0x0d,0x3b,0x0d,0x3e,0x0d,0x3f,0x0d,0x41,0x0d,0x45,0x0d,0x47,0x0d,0x48,0x0d,0x49,0x0d,0x4c,0x0d,0x4f,0x0d,0x55,0x0d,0x56,0x0d,0x57,0x0d,0x58,0x0d,0x5b,0x0d,0x5c,0x0d,0x60,0x0d,0x66,0x0d,0x67,0x0d,0x68,0x0d,0x5d, 0x0d,0x5e,0x0d,0x5f,0x0d,0x62,0x0d,0xc1,0x0d,0x0b,0x00,0x02,0x00,0x4e,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x24,0x00,0x3d,0x00,0x01,0x00,0x62,0x00,0x68,0x00,0x1b,0x00,0x91,0x00,0x92,0x00,0x22,0x00,0xad,0x00,0xb0,0x00,0x24,0x00,0xbb,0x00,0xbb,0x00,0x28,0x00,0xc7,0x00,0xd5,0x00,0x29,0x00,0xe1,0x00,0xe1,0x00,0x38,0x00,0xe3, 0x00,0xe3,0x00,0x39,0x00,0xe5,0x00,0xe5,0x00,0x3a,0x00,0xe8,0x00,0xe8,0x00,0x3b,0x00,0xea,0x00,0xea,0x00,0x3c,0x00,0xec,0x00,0xec,0x00,0x3d,0x00,0xf7,0x00,0xf7,0x00,0x3e,0x00,0xf9,0x00,0xfa,0x00,0x3f,0x00,0xfc,0x00,0xfc,0x00,0x41,0x00,0xfe,0x00,0xfe,0x00,0x42,0x01,0x03,0x01,0x03,0x00,0x43,0x01,0x05,0x01,0x05,0x00,0x44, 0x01,0x07,0x01,0x07,0x00,0x45,0x01,0x09,0x01,0x0a,0x00,0x46,0x01,0x0c,0x01,0x0c,0x00,0x48,0x01,0x0e,0x01,0x0e,0x00,0x49,0x01,0x10,0x01,0x10,0x00,0x4a,0x01,0x12,0x01,0x12,0x00,0x4b,0x01,0x14,0x01,0x14,0x00,0x4c,0x01,0x16,0x01,0x16,0x00,0x4d,0x01,0x18,0x01,0x18,0x00,0x4e,0x01,0x1a,0x01,0x1a,0x00,0x4f,0x01,0x1c,0x01,0x1c, 0x00,0x50,0x01,0x1e,0x01,0x1e,0x00,0x51,0x01,0x20,0x01,0x20,0x00,0x52,0x01,0x22,0x01,0x22,0x00,0x53,0x01,0x24,0x01,0x24,0x00,0x54,0x01,0x26,0x01,0x26,0x00,0x55,0x01,0x28,0x01,0x28,0x00,0x56,0x01,0x2a,0x01,0x2a,0x00,0x57,0x01,0x39,0x01,0x39,0x00,0x58,0x01,0x45,0x01,0x45,0x00,0x59,0x01,0x47,0x01,0x47,0x00,0x5a,0x01,0x49, 0x01,0x49,0x00,0x5b,0x01,0x4b,0x01,0x4b,0x00,0x5c,0x01,0x4d,0x01,0x4d,0x00,0x5d,0x01,0x4f,0x01,0x4f,0x00,0x5e,0x01,0x51,0x01,0x51,0x00,0x5f,0x01,0x53,0x01,0x53,0x00,0x60,0x01,0x55,0x01,0x55,0x00,0x61,0x01,0x57,0x01,0x57,0x00,0x62,0x01,0x59,0x01,0x59,0x00,0x63,0x01,0x5b,0x01,0x5b,0x00,0x64,0x01,0x5d,0x01,0x5d,0x00,0x65, 0x01,0x5f,0x01,0x5f,0x00,0x66,0x01,0x61,0x01,0x61,0x00,0x67,0x01,0x63,0x01,0x63,0x00,0x68,0x01,0x65,0x01,0x65,0x00,0x69,0x01,0x68,0x01,0x68,0x00,0x6a,0x01,0x6a,0x01,0x6a,0x00,0x6b,0x01,0x6c,0x01,0x6c,0x00,0x6c,0x01,0x6e,0x01,0x6e,0x00,0x6d,0x01,0x70,0x01,0x70,0x00,0x6e,0x01,0x72,0x01,0x72,0x00,0x6f,0x01,0x74,0x01,0x74, 0x00,0x70,0x01,0x76,0x01,0x76,0x00,0x71,0x01,0x78,0x01,0x78,0x00,0x72,0x01,0x7a,0x01,0x7a,0x00,0x73,0x01,0x7c,0x01,0x7c,0x00,0x74,0x01,0x7e,0x01,0x7e,0x00,0x75,0x01,0x80,0x01,0x80,0x00,0x76,0x01,0x82,0x01,0x82,0x00,0x77,0x01,0x85,0x01,0x85,0x00,0x78,0x01,0x87,0x01,0x87,0x00,0x79,0x01,0x89,0x01,0x89,0x00,0x7a,0x01,0x8c, 0x01,0x8c,0x00,0x7b,0x01,0x8e,0x01,0x8e,0x00,0x7c,0x01,0x90,0x01,0x90,0x00,0x7d,0x01,0x92,0x01,0x92,0x00,0x7e,0x02,0x3d,0x02,0x3d,0x00,0x7f,0x0b,0x21,0x0b,0x21,0x00,0x80,0x00,0x02,0x01,0x06,0x00,0x80,0x0d,0xbe,0x0c,0xeb,0x0c,0xec,0x0c,0xed,0x0c,0xee,0x0c,0xef,0x0c,0xf0,0x0c,0xf1,0x0c,0xf2,0x0c,0xf4,0x0c,0xf5,0x0c,0xf6, 0x0c,0xf7,0x0c,0xf8,0x0c,0xf9,0x0c,0xfa,0x0c,0xfb,0x0c,0xfc,0x0c,0xfd,0x0c,0xfe,0x0c,0xff,0x0d,0x00,0x0d,0x01,0x0d,0x02,0x0d,0x03,0x0d,0x04,0x0d,0x0d,0x0d,0x0c,0x0d,0x0e,0x0d,0x10,0x0d,0x0f,0x0d,0x11,0x0d,0x12,0x0d,0x14,0x0d,0x13,0x0d,0x15,0x0d,0x16,0x0d,0x18,0x0d,0x17,0x0d,0x19,0x0d,0x1a,0x0d,0x1b,0x0d,0x1d,0x0d,0x1c, 0x0d,0x1e,0x0d,0x20,0x0d,0x1f,0x0d,0x22,0x0d,0x21,0x0d,0x23,0x0d,0x24,0x0d,0x0b,0x0d,0x05,0x0d,0x08,0x0d,0x06,0x0d,0x61,0x0c,0xf3,0x0d,0x07,0x0d,0x51,0x0d,0x65,0x0d,0x0a,0x0d,0x25,0x0d,0x09,0x0d,0x33,0x0d,0x50,0x0d,0x29,0x0d,0x2a,0x0d,0x2d,0x0d,0x27,0x0d,0x28,0x0d,0x2c,0x0d,0x31,0x0d,0x32,0x0d,0x40,0x0d,0x42,0x0d,0x43, 0x0d,0x44,0x0d,0x46,0x0d,0x4a,0x0d,0x4b,0x0d,0x4d,0x0d,0x4e,0x0d,0x52,0x0d,0x54,0x0d,0x59,0x0d,0x5a,0x0d,0x63,0x0d,0x64,0x0d,0x3d,0x0d,0x26,0x0d,0xbf,0x0d,0x35,0x0d,0x2e,0x0d,0x2f,0x0d,0x30,0x0d,0xc0,0x0d,0x2b,0x0d,0x34,0x0d,0x36,0x0d,0x37,0x0d,0x38,0x0d,0x39,0x0d,0x3a,0x0d,0x3b,0x0d,0x3e,0x0d,0x3f,0x0d,0x41,0x0d,0x45, 0x0d,0x47,0x0d,0x48,0x0d,0x49,0x0d,0x4c,0x0d,0x4f,0x0d,0x55,0x0d,0x56,0x0d,0x57,0x0d,0x58,0x0d,0x5b,0x0d,0x5c,0x0d,0x60,0x0d,0x66,0x0d,0x67,0x0d,0x68,0x0d,0x5d,0x0d,0x5e,0x0d,0x5f,0x0d,0x62,0x0d,0xc1,0x00,0x02,0x00,0x4f,0x00,0x09,0x00,0x09,0x00,0x00,0x00,0x44,0x00,0x4b,0x00,0x01,0x00,0x4d,0x00,0x5d,0x00,0x09,0x00,0x69, 0x00,0x81,0x00,0x1a,0x00,0x89,0x00,0x89,0x00,0x33,0x00,0xa0,0x00,0xa1,0x00,0x34,0x00,0xb1,0x00,0xb1,0x00,0x36,0x00,0xba,0x00,0xba,0x00,0x37,0x00,0xd6,0x00,0xd6,0x00,0x38,0x00,0xe2,0x00,0xe2,0x00,0x39,0x00,0xe4,0x00,0xe4,0x00,0x3a,0x00,0xe6,0x00,0xe6,0x00,0x3b,0x00,0xe9,0x00,0xe9,0x00,0x3c,0x00,0xeb,0x00,0xeb,0x00,0x3d, 0x00,0xed,0x00,0xed,0x00,0x3e,0x00,0xf8,0x00,0xf8,0x00,0x3f,0x00,0xfb,0x00,0xfb,0x00,0x40,0x00,0xfd,0x00,0xfd,0x00,0x41,0x00,0xff,0x01,0x00,0x00,0x42,0x01,0x04,0x01,0x04,0x00,0x44,0x01,0x06,0x01,0x06,0x00,0x45,0x01,0x08,0x01,0x08,0x00,0x46,0x01,0x0b,0x01,0x0b,0x00,0x47,0x01,0x0d,0x01,0x0d,0x00,0x48,0x01,0x0f,0x01,0x0f, 0x00,0x49,0x01,0x11,0x01,0x11,0x00,0x4a,0x01,0x13,0x01,0x13,0x00,0x4b,0x01,0x15,0x01,0x15,0x00,0x4c,0x01,0x17,0x01,0x17,0x00,0x4d,0x01,0x19,0x01,0x19,0x00,0x4e,0x01,0x1b,0x01,0x1b,0x00,0x4f,0x01,0x1d,0x01,0x1d,0x00,0x50,0x01,0x1f,0x01,0x1f,0x00,0x51,0x01,0x21,0x01,0x21,0x00,0x52,0x01,0x23,0x01,0x23,0x00,0x53,0x01,0x25, 0x01,0x25,0x00,0x54,0x01,0x27,0x01,0x27,0x00,0x55,0x01,0x29,0x01,0x29,0x00,0x56,0x01,0x2b,0x01,0x2b,0x00,0x57,0x01,0x3a,0x01,0x3a,0x00,0x58,0x01,0x46,0x01,0x46,0x00,0x59,0x01,0x48,0x01,0x48,0x00,0x5a,0x01,0x4a,0x01,0x4a,0x00,0x5b,0x01,0x4c,0x01,0x4c,0x00,0x5c,0x01,0x4e,0x01,0x4e,0x00,0x5d,0x01,0x50,0x01,0x50,0x00,0x5e, 0x01,0x52,0x01,0x52,0x00,0x5f,0x01,0x54,0x01,0x54,0x00,0x60,0x01,0x56,0x01,0x56,0x00,0x61,0x01,0x58,0x01,0x58,0x00,0x62,0x01,0x5a,0x01,0x5a,0x00,0x63,0x01,0x5c,0x01,0x5c,0x00,0x64,0x01,0x5e,0x01,0x5e,0x00,0x65,0x01,0x60,0x01,0x60,0x00,0x66,0x01,0x62,0x01,0x62,0x00,0x67,0x01,0x64,0x01,0x64,0x00,0x68,0x01,0x66,0x01,0x66, 0x00,0x69,0x01,0x69,0x01,0x69,0x00,0x6a,0x01,0x6b,0x01,0x6b,0x00,0x6b,0x01,0x6d,0x01,0x6d,0x00,0x6c,0x01,0x6f,0x01,0x6f,0x00,0x6d,0x01,0x71,0x01,0x71,0x00,0x6e,0x01,0x73,0x01,0x73,0x00,0x6f,0x01,0x75,0x01,0x75,0x00,0x70,0x01,0x77,0x01,0x77,0x00,0x71,0x01,0x79,0x01,0x79,0x00,0x72,0x01,0x7b,0x01,0x7b,0x00,0x73,0x01,0x7d, 0x01,0x7d,0x00,0x74,0x01,0x7f,0x01,0x7f,0x00,0x75,0x01,0x81,0x01,0x81,0x00,0x76,0x01,0x83,0x01,0x83,0x00,0x77,0x01,0x86,0x01,0x86,0x00,0x78,0x01,0x88,0x01,0x88,0x00,0x79,0x01,0x8a,0x01,0x8a,0x00,0x7a,0x01,0x8d,0x01,0x8d,0x00,0x7b,0x01,0x8f,0x01,0x8f,0x00,0x7c,0x01,0x91,0x01,0x91,0x00,0x7d,0x01,0x93,0x01,0x93,0x00,0x7e, 0x02,0x3e,0x02,0x3e,0x00,0x7f,0x00,0x02,0x00,0x08,0x00,0x01,0x0c,0xf3,0x00,0x01,0x00,0x01,0x00,0x4c,0x00,0x02,0x00,0x08,0x00,0x01,0x0d,0x3c,0x00,0x01,0x00,0x01,0x00,0x4c,0x00,0x01,0x00,0x24,0x00,0x01,0x00,0x08,0x00,0x03,0x00,0x08,0x00,0x10,0x00,0x16,0x0d,0xbd,0x00,0x03,0x00,0x49,0x00,0x4f,0x0d,0xbb,0x00,0x02,0x00,0x49, 0x0d,0xba,0x00,0x02,0x00,0x4f,0x00,0x01,0x00,0x01,0x00,0x49,0x00,0x01,0x00,0x28,0x00,0x02,0x00,0x0a,0x00,0x1e,0x00,0x02,0x00,0x06,0x00,0x0e,0x0d,0xbc,0x00,0x03,0x00,0x49,0x00,0x4c,0x0d,0xb9,0x00,0x02,0x00,0x4c,0x00,0x01,0x00,0x04,0x0d,0xbc,0x00,0x02,0x00,0x4c,0x00,0x01,0x00,0x02,0x00,0x49,0x0d,0xbb,0x00,0x02,0x00,0x08, 0x00,0x01,0x00,0xbc,0x00,0x01,0x00,0x01,0x00,0x12,0x00,0x03,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x74,0x00,0x02,0x00,0x02,0x00,0xbc,0x00,0xbc,0x00,0x00,0x0c,0xe1,0x0c,0xea,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x08,0x8d,0x00,0xf0, 0x00,0xf1,0x00,0xf2,0x02,0x38,0x02,0x39,0x08,0x8e,0x02,0x3a,0x02,0x3b,0x08,0x8f,0x00,0x02,0x00,0x01,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xc3,0x0c,0xc4,0x0c,0xc5,0x0c,0xc6,0x0c,0xc7,0x0c,0xc8,0x0c,0xc9,0x0c,0xca,0x0c,0xcb,0x0c,0xcc,0x00,0x02,0x00,0x01,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02, 0x00,0x1a,0x00,0x0a,0x0c,0xb9,0x0c,0xba,0x0c,0xbb,0x0c,0xbc,0x0c,0xbd,0x0c,0xbe,0x0c,0xbf,0x0c,0xc0,0x0c,0xc1,0x0c,0xc2,0x00,0x02,0x00,0x01,0x0c,0xcd,0x0c,0xd6,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4,0x0c,0xd5,0x0c,0xd6,0x00,0x02,0x00,0x01, 0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1a,0x00,0x1b,0x00,0x1c,0x00,0x02,0x00,0x01,0x0c,0xcd,0x0c,0xd6,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xb9,0x0c,0xba,0x0c,0xbb,0x0c,0xbc,0x0c,0xbd,0x0c,0xbe,0x0c,0xbf,0x0c,0xc0, 0x0c,0xc1,0x0c,0xc2,0x00,0x02,0x00,0x01,0x0c,0xc3,0x0c,0xcc,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1a,0x00,0x1b,0x00,0x1c,0x00,0x02,0x00,0x01,0x0c,0xc3,0x0c,0xcc,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xc3,0x0c,0xc4,0x0c,0xc5,0x0c,0xc6, 0x0c,0xc7,0x0c,0xc8,0x0c,0xc9,0x0c,0xca,0x0c,0xcb,0x0c,0xcc,0x00,0x02,0x00,0x01,0x0c,0xb9,0x0c,0xc2,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4,0x0c,0xd5,0x0c,0xd6,0x00,0x02,0x00,0x01,0x0c,0xb9,0x0c,0xc2,0x00,0x00,0x00,0x01,0x00,0x9a,0x00,0x06, 0x00,0x12,0x00,0x38,0x00,0x44,0x00,0x50,0x00,0x6a,0x00,0x76,0x00,0x03,0x00,0x08,0x00,0x12,0x00,0x1c,0x10,0xb9,0x00,0x04,0x00,0x39,0x00,0x36,0x00,0x14,0x10,0xba,0x00,0x04,0x00,0x39,0x00,0x36,0x00,0x15,0x10,0xbb,0x00,0x04,0x00,0x39,0x00,0x36,0x00,0x16,0x00,0x01,0x00,0x04,0x08,0xc5,0x00,0x03,0x00,0x35,0x00,0x30,0x00,0x01, 0x00,0x04,0x10,0xbc,0x00,0x03,0x00,0x39,0x00,0x36,0x00,0x02,0x00,0x06,0x00,0x10,0x10,0xfb,0x00,0x04,0x00,0x25,0x00,0x36,0x00,0x33,0x10,0xfd,0x00,0x04,0x00,0x31,0x00,0x25,0x00,0x36,0x00,0x01,0x00,0x04,0x08,0xc6,0x00,0x03,0x00,0x2f,0x00,0x30,0x00,0x03,0x00,0x08,0x00,0x12,0x00,0x1a,0x10,0xfc,0x00,0x04,0x00,0x3a,0x00,0x36, 0x00,0x33,0x08,0xc4,0x00,0x03,0x00,0x3a,0x00,0x2d,0x08,0xc3,0x00,0x04,0x00,0x3a,0x00,0x31,0x00,0x2d,0x00,0x02,0x00,0x04,0x00,0x29,0x00,0x29,0x00,0x00,0x00,0x2f,0x00,0x31,0x00,0x01,0x00,0x35,0x00,0x35,0x00,0x04,0x00,0x3d,0x00,0x3d,0x00,0x05,0x00,0x02,0x00,0x80,0x00,0x3d,0x10,0xe5,0x10,0xbd,0x10,0xbe,0x10,0xbf,0x10,0xe6, 0x10,0xe7,0x10,0xe8,0x10,0xe9,0x10,0xea,0x10,0xeb,0x10,0xec,0x10,0xed,0x10,0xc0,0x10,0xc1,0x10,0xf9,0x10,0xc2,0x10,0xc3,0x10,0xc4,0x10,0xee,0x10,0xef,0x10,0xf0,0x10,0xf1,0x10,0xf2,0x10,0xf3,0x10,0xf4,0x10,0xc5,0x10,0xf5,0x10,0xf6,0x10,0xc6,0x10,0xc7,0x10,0xc8,0x10,0xc9,0x10,0xca,0x10,0xf7,0x10,0xcb,0x10,0xcc,0x10,0xcd, 0x10,0xce,0x10,0xcf,0x10,0xd0,0x10,0xd1,0x10,0xd2,0x10,0xd3,0x10,0xd4,0x10,0xd5,0x10,0xd6,0x10,0xd7,0x10,0xd8,0x10,0xd9,0x10,0xda,0x10,0xdb,0x10,0xdc,0x10,0xdd,0x10,0xde,0x10,0xdf,0x10,0xe0,0x10,0xe1,0x10,0xf8,0x10,0xe2,0x10,0xe3,0x10,0xe4,0x00,0x02,0x00,0x1b,0x00,0x05,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x0a,0x00,0x01, 0x00,0x0d,0x00,0x0d,0x00,0x05,0x00,0x0f,0x00,0x11,0x00,0x06,0x00,0x1d,0x00,0x1e,0x00,0x09,0x00,0x42,0x00,0x42,0x00,0x0b,0x00,0x85,0x00,0x86,0x00,0x0c,0x00,0x8c,0x00,0x8c,0x00,0x0e,0x00,0x97,0x00,0x98,0x00,0x0f,0x00,0x9a,0x00,0x9a,0x00,0x11,0x00,0xaa,0x00,0xab,0x00,0x12,0x00,0xb2,0x00,0xb2,0x00,0x14,0x00,0xb4,0x00,0xb7, 0x00,0x15,0x00,0xbd,0x00,0xbd,0x00,0x19,0x00,0xc4,0x00,0xc5,0x00,0x1a,0x00,0xf3,0x00,0xf6,0x00,0x1c,0x01,0x38,0x01,0x38,0x00,0x20,0x01,0x94,0x01,0x94,0x00,0x21,0x01,0x96,0x01,0x96,0x00,0x22,0x01,0x98,0x01,0x9b,0x00,0x23,0x07,0xd2,0x07,0xd8,0x00,0x27,0x07,0xda,0x07,0xdf,0x00,0x2e,0x08,0x56,0x08,0x59,0x00,0x34,0x08,0x8c, 0x08,0x8c,0x00,0x38,0x08,0xbd,0x08,0xbd,0x00,0x39,0x0a,0x64,0x0a,0x64,0x00,0x3a,0x0b,0x2a,0x0b,0x2b,0x00,0x3b,0x00,0x02,0x00,0x56,0x00,0x28,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4,0x0c,0xd5,0x0c,0xd6,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4, 0x0c,0xd5,0x0c,0xd6,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4,0x0c,0xd5,0x0c,0xd6,0x0c,0xcd,0x0c,0xce,0x0c,0xcf,0x0c,0xd0,0x0c,0xd1,0x0c,0xd2,0x0c,0xd3,0x0c,0xd4,0x0c,0xd5,0x0c,0xd6,0x00,0x02,0x00,0x02,0x00,0x13,0x00,0x1c,0x00,0x00,0x0c,0xb9,0x0c,0xd6,0x00,0x0a,0x00,0x02,0x00,0xa2, 0x00,0x4e,0x0c,0xd7,0x0c,0xd8,0x0c,0xd9,0x0c,0xda,0x0c,0xdb,0x0c,0xdc,0x0c,0xdd,0x0c,0xde,0x0c,0xdf,0x0c,0xe0,0x0d,0xf2,0x0d,0xf3,0x10,0x9a,0x10,0x9b,0x10,0xa5,0x10,0xaf,0x10,0xb6,0x10,0xac,0x10,0xad,0x10,0xb7,0x10,0xb8,0x10,0xa9,0x10,0xb1,0x10,0x99,0x10,0xa6,0x10,0xa7,0x10,0xab,0x10,0xae,0x10,0xa8,0x10,0x96,0x10,0xb2, 0x10,0xa3,0x10,0xa2,0x10,0x9c,0x10,0x9e,0x10,0x9d,0x10,0xa0,0x10,0x9f,0x10,0xa1,0x10,0xa4,0x10,0xb4,0x10,0xb5,0x10,0xb0,0x10,0xb3,0x10,0x98,0x10,0x97,0x10,0xaa,0x0c,0xd7,0x0c,0xd8,0x0c,0xd9,0x0c,0xda,0x0c,0xdb,0x0c,0xdc,0x0c,0xdd,0x0c,0xde,0x0c,0xdf,0x0c,0xe0,0x0c,0xd7,0x0c,0xd8,0x0c,0xd9,0x0c,0xda,0x0c,0xdb,0x0c,0xdc, 0x0c,0xdd,0x0c,0xde,0x0c,0xdf,0x0c,0xe0,0x0c,0xd7,0x0c,0xd8,0x0c,0xd9,0x0c,0xda,0x0c,0xdb,0x0c,0xdc,0x0c,0xdd,0x0c,0xde,0x0c,0xdf,0x0c,0xe0,0x10,0x95,0x00,0x02,0x00,0x1b,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x2c,0x00,0x2c,0x00,0x0a,0x00,0x34,0x00,0x34,0x00,0x0b,0x00,0xcc,0x00,0xcf,0x00,0x0c,0x00,0xf9,0x00,0xf9,0x00,0x10, 0x01,0x39,0x01,0x39,0x00,0x11,0x01,0x5b,0x01,0x5b,0x00,0x12,0x01,0x5d,0x01,0x5d,0x00,0x13,0x01,0x5f,0x01,0x5f,0x00,0x14,0x01,0x61,0x01,0x61,0x00,0x15,0x01,0xa4,0x01,0xa4,0x00,0x16,0x01,0xae,0x01,0xae,0x00,0x17,0x01,0xbd,0x01,0xbd,0x00,0x18,0x01,0xe0,0x01,0xe0,0x00,0x19,0x02,0x7f,0x02,0x7f,0x00,0x1a,0x02,0x81,0x02,0x81, 0x00,0x1b,0x02,0xb5,0x02,0xb5,0x00,0x1c,0x03,0x0f,0x03,0x0f,0x00,0x1d,0x03,0x11,0x03,0x11,0x00,0x1e,0x03,0xad,0x03,0xb4,0x00,0x1f,0x04,0x3f,0x04,0x42,0x00,0x27,0x04,0xf9,0x04,0xf9,0x00,0x2b,0x05,0x2c,0x05,0x2c,0x00,0x2c,0x05,0x2e,0x05,0x2e,0x00,0x2d,0x06,0x21,0x06,0x21,0x00,0x2e,0x0c,0xb9,0x0c,0xd6,0x00,0x2f,0x0d,0xe4, 0x0d,0xe4,0x00,0x4d,0x00,0x02,0x00,0x42,0x00,0x1e,0x0d,0xf5,0x0d,0xf6,0x0d,0xf7,0x0d,0xf8,0x0d,0xf9,0x0d,0xfa,0x0d,0xfb,0x0d,0xfc,0x0d,0xfd,0x0d,0xfe,0x0d,0xff,0x0e,0x00,0x0e,0x01,0x0e,0x0b,0x0e,0x02,0x0e,0x03,0x0e,0x04,0x0e,0x05,0x0e,0x06,0x0e,0x07,0x0e,0x08,0x0e,0x09,0x0e,0x0a,0x0e,0x0f,0x0e,0x10,0x0e,0x0e,0x0e,0x0c, 0x0e,0x0d,0x0e,0x11,0x0e,0x12,0x00,0x02,0x00,0x13,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x01,0x00,0x1e,0x00,0x1e,0x00,0x02,0x00,0x22,0x00,0x22,0x00,0x03,0x00,0xb4,0x00,0xb7,0x00,0x04,0x00,0xc4,0x00,0xc5,0x00,0x08,0x01,0x08,0x01,0x08,0x00,0x0a,0x01,0x10,0x01,0x11,0x00,0x0b,0x01,0x23,0x01,0x23,0x00,0x0d, 0x01,0x3b,0x01,0x3b,0x00,0x0e,0x01,0x55,0x01,0x56,0x00,0x0f,0x01,0x65,0x01,0x66,0x00,0x11,0x01,0x6a,0x01,0x6b,0x00,0x13,0x01,0x72,0x01,0x73,0x00,0x15,0x01,0x94,0x01,0x94,0x00,0x17,0x01,0x9c,0x01,0x9c,0x00,0x18,0x01,0x9e,0x01,0x9e,0x00,0x19,0x02,0x3d,0x02,0x3e,0x00,0x1a,0x02,0xaf,0x02,0xb0,0x00,0x1c,0x00,0x02,0x00,0x08, 0x00,0x01,0x0d,0xf4,0x00,0x01,0x00,0x01,0x00,0x09,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x11,0x84,0x00,0x02,0x11,0x83,0x00,0x01,0x00,0x01,0x11,0x82,0x00,0x01,0x00,0x8a,0x00,0x0b,0x00,0x1c,0x00,0x26,0x00,0x30,0x00,0x3a,0x00,0x44,0x00,0x4e,0x00,0x58,0x00,0x62,0x00,0x6c,0x00,0x76,0x00,0x80,0x00,0x01, 0x00,0x04,0x11,0x8e,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x98,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x8f,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x90,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x91,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x92,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x93, 0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x94,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x95,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x96,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x97,0x00,0x02,0x11,0x8d,0x00,0x02,0x00,0x02,0x00,0x06,0x00,0x06,0x00,0x00,0x0c,0xcd,0x0c,0xd6,0x00,0x01,0x00,0x01,0x00,0x8a, 0x00,0x0b,0x00,0x1c,0x00,0x26,0x00,0x30,0x00,0x3a,0x00,0x44,0x00,0x4e,0x00,0x58,0x00,0x62,0x00,0x6c,0x00,0x76,0x00,0x80,0x00,0x01,0x00,0x04,0x11,0x8e,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x98,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x8f,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x90,0x00,0x02,0x11,0x8d, 0x00,0x01,0x00,0x04,0x11,0x91,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x92,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x93,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x94,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x95,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04,0x11,0x96,0x00,0x02,0x11,0x8d,0x00,0x01,0x00,0x04, 0x11,0x97,0x00,0x02,0x11,0x8d,0x00,0x02,0x00,0x02,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x13,0x00,0x1c,0x00,0x01,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xa4,0x11,0xa5,0x11,0xa6,0x11,0xa7,0x11,0xa8,0x11,0xa9,0x11,0xaa,0x11,0xab,0x11,0xac,0x11,0xad,0x00,0x02,0x00,0x01,0x0f,0xd6,0x0f,0xdf,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a, 0x11,0xb8,0x11,0xb9,0x11,0xba,0x11,0xbb,0x11,0xbc,0x11,0xbd,0x11,0xbe,0x11,0xbf,0x11,0xc0,0x11,0xc1,0x00,0x02,0x00,0x01,0x0f,0xea,0x0f,0xf3,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xae,0x11,0xaf,0x11,0xb0,0x11,0xb1,0x11,0xb2,0x11,0xb3,0x11,0xb4,0x11,0xb5,0x11,0xb6,0x11,0xb7,0x00,0x02,0x00,0x01,0x0f,0xe0,0x0f,0xe9, 0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xc2,0x11,0xc3,0x11,0xc4,0x11,0xc5,0x11,0xc6,0x11,0xc7,0x11,0xc8,0x11,0xc9,0x11,0xca,0x11,0xcb,0x00,0x02,0x00,0x01,0x0f,0xf4,0x0f,0xfd,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xcc,0x11,0xcd,0x11,0xce,0x11,0xcf,0x11,0xd0,0x11,0xd1,0x11,0xd2,0x11,0xd3,0x11,0xd4,0x11,0xd5, 0x00,0x02,0x00,0x01,0x0f,0xfe,0x10,0x07,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xd6,0x11,0xd7,0x11,0xd8,0x11,0xd9,0x11,0xda,0x11,0xdb,0x11,0xdc,0x11,0xdd,0x11,0xde,0x11,0xdf,0x00,0x02,0x00,0x01,0x10,0x08,0x10,0x11,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xe0,0x11,0xe1,0x11,0xe2,0x11,0xe3,0x11,0xe4,0x11,0xe5, 0x11,0xe6,0x11,0xe7,0x11,0xe8,0x11,0xe9,0x00,0x02,0x00,0x01,0x10,0x12,0x10,0x1b,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xea,0x11,0xeb,0x11,0xec,0x11,0xed,0x11,0xee,0x11,0xef,0x11,0xf0,0x11,0xf1,0x11,0xf2,0x11,0xf3,0x00,0x02,0x00,0x01,0x10,0x1c,0x10,0x25,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xf4,0x11,0xf5, 0x11,0xf6,0x11,0xf7,0x11,0xf8,0x11,0xf9,0x11,0xfa,0x11,0xfb,0x11,0xfc,0x11,0xfd,0x00,0x02,0x00,0x01,0x10,0x26,0x10,0x2f,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x11,0xfe,0x11,0xff,0x12,0x00,0x12,0x01,0x12,0x02,0x12,0x03,0x12,0x04,0x12,0x05,0x12,0x06,0x12,0x07,0x00,0x02,0x00,0x01,0x10,0x30,0x10,0x39,0x00,0x00,0x00,0x02, 0x00,0x1a,0x00,0x0a,0x12,0x08,0x12,0x09,0x12,0x0a,0x12,0x0b,0x12,0x0c,0x12,0x0d,0x12,0x0e,0x12,0x0f,0x12,0x10,0x12,0x11,0x00,0x02,0x00,0x01,0x10,0x3a,0x10,0x43,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x12,0x12,0x13,0x12,0x14,0x12,0x15,0x12,0x16,0x12,0x17,0x12,0x18,0x12,0x19,0x12,0x1a,0x12,0x1b,0x00,0x02,0x00,0x01, 0x10,0x44,0x10,0x4d,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x1c,0x12,0x1d,0x12,0x1e,0x12,0x1f,0x12,0x20,0x12,0x21,0x12,0x22,0x12,0x23,0x12,0x24,0x12,0x25,0x00,0x02,0x00,0x01,0x10,0x4e,0x10,0x57,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x26,0x12,0x27,0x12,0x28,0x12,0x29,0x12,0x2a,0x12,0x2b,0x12,0x2c,0x12,0x2d, 0x12,0x2e,0x12,0x2f,0x00,0x02,0x00,0x01,0x10,0x58,0x10,0x61,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x30,0x12,0x31,0x12,0x32,0x12,0x33,0x12,0x34,0x12,0x35,0x12,0x36,0x12,0x37,0x12,0x38,0x12,0x39,0x00,0x02,0x00,0x01,0x10,0x62,0x10,0x6b,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x3a,0x12,0x3b,0x12,0x3c,0x12,0x3d, 0x12,0x3e,0x12,0x3f,0x12,0x40,0x12,0x41,0x12,0x42,0x12,0x43,0x00,0x02,0x00,0x01,0x10,0x6c,0x10,0x75,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a,0x12,0x44,0x12,0x45,0x12,0x46,0x12,0x47,0x12,0x48,0x12,0x49,0x12,0x4a,0x12,0x4b,0x12,0x4c,0x12,0x4d,0x00,0x02,0x00,0x01,0x10,0x76,0x10,0x7f,0x00,0x00,0x00,0x02,0x00,0x1a,0x00,0x0a, 0x12,0x4f,0x12,0x50,0x12,0x51,0x12,0x52,0x12,0x53,0x12,0x54,0x12,0x55,0x12,0x56,0x12,0x57,0x12,0x58,0x00,0x02,0x00,0x01,0x10,0x81,0x10,0x8a,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x0b,0xb7,0x00,0x02,0x0b,0x74,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x01,0x00,0x14,0x00,0x01,0x00,0x08,0x00,0x01, 0x00,0x04,0x0b,0xb7,0x00,0x03,0x08,0xc4,0x0b,0x74,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x4e,0x00,0x01,0x00,0x54,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x02,0x00,0x82,0x00,0x88,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x28,0x00,0x02, 0x00,0x6e,0x00,0xa2,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x14,0x00,0x02,0x00,0x5a,0x00,0x94,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x01,0x00,0x01,0x0b,0x7a,0x00,0x02,0x00,0x0a,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0x5f,0x0b,0x5f,0x00,0x0a,0x0b,0x67,0x0b,0x67,0x00,0x0b, 0x0b,0xb9,0x0b,0xb9,0x00,0x0c,0x0b,0xbf,0x0b,0xbf,0x00,0x0d,0x0b,0xc4,0x0b,0xc4,0x00,0x0e,0x0b,0xc9,0x0b,0xc9,0x00,0x0f,0x0b,0xd0,0x0b,0xd5,0x00,0x10,0x0b,0xd8,0x0b,0xd8,0x00,0x16,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02, 0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0xdb,0x00,0x01,0x00,0x01,0x0b,0xc8,0x00,0x03,0x00,0x02,0x02,0xbc,0x02,0xea,0x00,0x01,0x02,0xf0,0x00,0x01,0x02,0xf6,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x03,0x02,0xa6, 0x02,0xa6,0x02,0xd4,0x00,0x01,0x02,0xda,0x00,0x01,0x02,0xe0,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x03,0x02,0x8e,0x02,0xf0,0x02,0xbc,0x00,0x01,0x02,0xc2,0x00,0x01,0x02,0xc8,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x04,0x02,0x76,0x02,0x76,0x02,0xd8,0x02,0xa4,0x00,0x01,0x02,0xaa,0x00,0x01,0x02,0xb0,0x00,0x01, 0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0xc6,0x00,0x01,0x02,0x90,0x00,0x01,0x02,0xcc,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x02,0x48,0x02,0xb2,0x00,0x01,0x02,0x7c,0x00,0x01,0x02,0xb8,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x9c,0x00,0x01,0x02,0x66,0x00,0x02,0x02,0xdc,0x02,0x32,0x00,0x01, 0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x02,0x1c,0x02,0x86,0x00,0x01,0x02,0x50,0x00,0x02,0x02,0xc6,0x02,0x1c,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x6e,0x00,0x01,0x02,0x38,0x00,0x03,0x02,0xae,0x02,0xb4,0x02,0xba,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x01,0xec,0x02,0x56,0x00,0x01,0x02,0x20, 0x00,0x03,0x02,0x96,0x02,0x9c,0x02,0xa2,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x3c,0x00,0x01,0x02,0x06,0x00,0x03,0x02,0x7c,0x02,0x82,0x02,0x3c,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x01,0xba,0x02,0x24,0x00,0x01,0x01,0xee,0x00,0x03,0x02,0x64,0x02,0x6a,0x02,0x24,0x00,0x01,0x00,0x00,0x00,0x76, 0x00,0x03,0x00,0x01,0x02,0x5c,0x00,0x01,0x01,0xd4,0x00,0x01,0x02,0x10,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x48,0x00,0x01,0x01,0xc0,0x00,0x02,0x02,0x36,0x01,0x8c,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x32,0x00,0x01,0x01,0xaa,0x00,0x03,0x02,0x20,0x02,0x26,0x01,0xe0,0x00,0x01,0x00,0x00, 0x00,0x76,0x00,0x03,0x00,0x01,0x02,0x1a,0x00,0x01,0x01,0x92,0x00,0x03,0x02,0x08,0x02,0x0e,0x02,0x14,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x01,0x46,0x02,0x02,0x00,0x01,0x01,0x7a,0x00,0x01,0x01,0xb6,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x01,0x30,0x01,0xec,0x00,0x01,0x01,0x64,0x00,0x02,0x01,0xda, 0x01,0x30,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x01,0x18,0x01,0xd4,0x00,0x01,0x01,0x4c,0x00,0x03,0x01,0xc2,0x01,0xc8,0x01,0x82,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02,0x00,0xfe,0x01,0xba,0x00,0x01,0x01,0x32,0x00,0x03,0x01,0xa8,0x01,0xae,0x01,0xb4,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x02, 0x01,0xa6,0x01,0xac,0x00,0x01,0x01,0x18,0x00,0x01,0x01,0x1e,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x03,0x01,0x90,0x01,0x84,0x01,0x96,0x00,0x01,0x01,0x02,0x00,0x01,0x01,0x08,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x03,0x01,0x6c,0x01,0x78,0x01,0x7e,0x00,0x01,0x00,0xea,0x00,0x01,0x00,0xf0,0x00,0x01,0x00,0x00, 0x00,0x76,0x00,0x03,0x00,0x03,0x00,0x9e,0x01,0x60,0x01,0x66,0x00,0x01,0x00,0xd2,0x00,0x01,0x00,0xd8,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x04,0x00,0x86,0x00,0x86,0x01,0x48,0x01,0x4e,0x00,0x01,0x00,0xba,0x00,0x01,0x00,0xc0,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x04,0x00,0x6c,0x01,0x2e,0x01,0x22,0x01,0x34, 0x00,0x01,0x00,0xa0,0x00,0x01,0x00,0xa6,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x05,0x00,0x52,0x00,0x52,0x01,0x14,0x01,0x08,0x01,0x1a,0x00,0x01,0x00,0x86,0x00,0x01,0x00,0x8c,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x04,0x00,0x36,0x00,0xec,0x00,0xf8,0x00,0xfe,0x00,0x01,0x00,0x6a,0x00,0x01,0x00,0x70,0x00,0x01, 0x00,0x00,0x00,0x76,0x00,0x03,0x00,0x05,0x00,0x1c,0x00,0x1c,0x00,0xd2,0x00,0xde,0x00,0xe4,0x00,0x01,0x00,0x50,0x00,0x01,0x00,0x56,0x00,0x01,0x00,0x00,0x00,0x76,0x00,0x02,0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61,0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd, 0x00,0x11,0x0b,0xe1,0x0b,0xe1,0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x01,0x00,0x01,0x0b,0x74,0x00,0x01,0x00,0x01,0x0b,0xc7,0x00,0x02,0x00,0x06,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x68,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1f,0x0b,0x97,0x0b,0x9a,0x00,0x2d,0x0b,0x9d,0x0b,0xb7,0x00,0x31,0x12,0x5f,0x12,0x62, 0x00,0x4c,0x00,0x01,0x00,0x02,0x0b,0x5e,0x0b,0x61,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x09,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x69,0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1e,0x0b,0x97,0x0b,0x9a,0x00,0x2c,0x0b,0x9d,0x0b,0xa6,0x00,0x30,0x0b,0xa8,0x0b,0xb2,0x00,0x3a,0x0b,0xb4,0x0b,0xb7,0x00,0x45,0x0b,0xe0, 0x0b,0xe0,0x00,0x49,0x12,0x5f,0x12,0x62,0x00,0x4a,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x01,0x00,0x01,0x0b,0x6d,0x00,0x01,0x00,0x01,0x0b,0x5e,0x00,0x01,0x00,0x01,0x0b,0xde,0x00,0x01,0x00,0x01,0x0b,0x64,0x00,0x01,0x00,0x01,0x0b,0x81,0x00,0x02,0x00,0x08,0x00,0x01,0x0b,0xd8,0x00,0x01,0x00,0x01,0x0b,0xd0,0x00,0x01,0x00,0x16, 0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x0b,0x8c,0x00,0x04,0x08,0xc4,0x0b,0x71,0x0b,0x5a,0x00,0x01,0x00,0x01,0x0b,0x71,0x00,0x01,0x00,0x2a,0x00,0x03,0x00,0x0c,0x00,0x16,0x00,0x20,0x00,0x01,0x00,0x04,0x12,0x59,0x00,0x02,0x0b,0x5f,0x00,0x01,0x00,0x04,0x12,0x5a,0x00,0x02,0x0b,0x5f,0x00,0x01,0x00,0x04,0x12,0x5b,0x00,0x02, 0x0b,0x5f,0x00,0x02,0x00,0x01,0x0b,0x54,0x0b,0x56,0x00,0x00,0x00,0x01,0x00,0x30,0x00,0x03,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x01,0x00,0x04,0x12,0x59,0x00,0x03,0x08,0xc4,0x0b,0x5f,0x00,0x01,0x00,0x04,0x12,0x5a,0x00,0x03,0x08,0xc4,0x0b,0x5f,0x00,0x01,0x00,0x04,0x12,0x5b,0x00,0x03,0x08,0xc4,0x0b,0x5f,0x00,0x02,0x00,0x01, 0x0b,0x54,0x0b,0x56,0x00,0x00,0x00,0x01,0x01,0xaa,0x00,0x01,0x00,0x08,0x00,0x34,0x00,0x6a,0x00,0x70,0x00,0x76,0x00,0x7c,0x00,0x82,0x00,0x88,0x00,0x8e,0x00,0x94,0x00,0x9a,0x00,0xa0,0x00,0xa6,0x00,0xac,0x00,0xb2,0x00,0xb8,0x00,0xbe,0x00,0xc4,0x00,0xca,0x00,0xd0,0x00,0xd6,0x00,0xdc,0x00,0xe2,0x00,0xe8,0x00,0xee,0x00,0xf4, 0x00,0xfa,0x01,0x00,0x01,0x06,0x01,0x0c,0x01,0x12,0x01,0x18,0x01,0x1e,0x01,0x24,0x01,0x2a,0x01,0x30,0x01,0x36,0x01,0x3c,0x01,0x42,0x01,0x48,0x01,0x4e,0x01,0x54,0x01,0x5a,0x01,0x60,0x01,0x66,0x01,0x6c,0x01,0x72,0x01,0x78,0x01,0x7e,0x01,0x84,0x01,0x8a,0x01,0x90,0x01,0x96,0x01,0x9c,0x0b,0x53,0x00,0x02,0x0b,0x53,0x0b,0x54, 0x00,0x02,0x0b,0x54,0x0b,0x55,0x00,0x02,0x0b,0x55,0x0b,0x56,0x00,0x02,0x0b,0x56,0x0b,0x57,0x00,0x02,0x0b,0x57,0x0b,0x58,0x00,0x02,0x0b,0x58,0x0b,0x59,0x00,0x02,0x0b,0x59,0x0b,0x5a,0x00,0x02,0x0b,0x5a,0x0b,0x5b,0x00,0x02,0x0b,0x5b,0x0b,0x5c,0x00,0x02,0x0b,0x5c,0x0b,0x5d,0x00,0x02,0x0b,0x5d,0x0b,0x5e,0x00,0x02,0x0b,0x5e, 0x0b,0x5f,0x00,0x02,0x0b,0x5f,0x0b,0x61,0x00,0x02,0x0b,0x61,0x0b,0x66,0x00,0x02,0x0b,0x66,0x0b,0x67,0x00,0x02,0x0b,0x67,0x0b,0xb9,0x00,0x02,0x0b,0xb9,0x0b,0xbf,0x00,0x02,0x0b,0xbf,0x0b,0xc0,0x00,0x02,0x0b,0xc0,0x0b,0xc1,0x00,0x02,0x0b,0xc1,0x0b,0xc2,0x00,0x02,0x0b,0xc2,0x0b,0xc3,0x00,0x02,0x0b,0xc3,0x0b,0xc4,0x00,0x02, 0x0b,0xc4,0x0b,0xc5,0x00,0x02,0x0b,0xc5,0x0b,0xc6,0x00,0x02,0x0b,0xc6,0x0b,0xc7,0x00,0x02,0x0b,0xc7,0x0b,0xc8,0x00,0x02,0x0b,0xc8,0x0b,0xc9,0x00,0x02,0x0b,0xc9,0x0b,0xca,0x00,0x02,0x0b,0xca,0x0b,0xcb,0x00,0x02,0x0b,0xcb,0x0b,0xcc,0x00,0x02,0x0b,0xcc,0x0b,0xcd,0x00,0x02,0x0b,0xcd,0x0b,0xce,0x00,0x02,0x0b,0xce,0x0b,0xcf, 0x00,0x02,0x0b,0xcf,0x0b,0xd0,0x00,0x02,0x0b,0xd0,0x0b,0xd1,0x00,0x02,0x0b,0xd1,0x0b,0xd2,0x00,0x02,0x0b,0xd2,0x0b,0xd3,0x00,0x02,0x0b,0xd3,0x0b,0xd4,0x00,0x02,0x0b,0xd4,0x0b,0xd5,0x00,0x02,0x0b,0xd5,0x0b,0xd6,0x00,0x02,0x0b,0xd6,0x0b,0xd7,0x00,0x02,0x0b,0xd7,0x0b,0xd8,0x00,0x02,0x0b,0xd8,0x0b,0xd9,0x00,0x02,0x0b,0xd9, 0x0b,0xda,0x00,0x02,0x0b,0xda,0x0b,0xdb,0x00,0x02,0x0b,0xdb,0x0b,0xdc,0x00,0x02,0x0b,0xdc,0x0b,0xdd,0x00,0x02,0x0b,0xdd,0x0b,0xe1,0x00,0x02,0x0b,0xe1,0x12,0x5c,0x00,0x02,0x12,0x5c,0x12,0x5d,0x00,0x02,0x12,0x5d,0x12,0x5e,0x00,0x02,0x12,0x5e,0x00,0x01,0x00,0x01,0x0a,0x43,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x12,0x00,0x01, 0x00,0x18,0x00,0x01,0x00,0x00,0x00,0x77,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x02,0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61,0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd,0x00,0x11,0x0b,0xe1,0x0b,0xe1,0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x01,0x00,0x1a, 0x00,0x01,0x00,0x08,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xdf,0x00,0x02,0x07,0x39,0x0b,0xdf,0x00,0x02,0x08,0xc4,0x00,0x01,0x00,0x01,0x0b,0x78,0x00,0x01,0x0e,0x76,0x00,0x84,0x01,0x0e,0x01,0x28,0x01,0x42,0x01,0x5c,0x01,0x76,0x01,0x90,0x01,0xaa,0x01,0xc4,0x01,0xde,0x01,0xf8,0x02,0x12,0x02,0x2c,0x02,0x46,0x02,0x60,0x02,0x7a, 0x02,0x94,0x02,0xae,0x02,0xc8,0x02,0xe2,0x02,0xfc,0x03,0x16,0x03,0x30,0x03,0x4a,0x03,0x64,0x03,0x7e,0x03,0x98,0x03,0xb2,0x03,0xcc,0x03,0xe6,0x04,0x00,0x04,0x1a,0x04,0x34,0x04,0x4e,0x04,0x68,0x04,0x82,0x04,0x9c,0x04,0xb6,0x04,0xd0,0x04,0xea,0x05,0x04,0x05,0x1e,0x05,0x38,0x05,0x52,0x05,0x6c,0x05,0x86,0x05,0xa0,0x05,0xba, 0x05,0xd4,0x05,0xee,0x06,0x08,0x06,0x22,0x06,0x3c,0x06,0x56,0x06,0x70,0x06,0x8a,0x06,0xa4,0x06,0xbe,0x06,0xd8,0x06,0xf2,0x07,0x0c,0x07,0x26,0x07,0x40,0x07,0x5a,0x07,0x74,0x07,0x8e,0x07,0xa8,0x07,0xc2,0x07,0xdc,0x07,0xf6,0x08,0x10,0x08,0x2a,0x08,0x44,0x08,0x5e,0x08,0x78,0x08,0x92,0x08,0xac,0x08,0xc6,0x08,0xe0,0x08,0xfa, 0x09,0x14,0x09,0x2e,0x09,0x48,0x09,0x62,0x09,0x7c,0x09,0x96,0x09,0xb0,0x09,0xca,0x09,0xe4,0x09,0xfe,0x0a,0x18,0x0a,0x32,0x0a,0x4c,0x0a,0x66,0x0a,0x80,0x0a,0x9a,0x0a,0xb4,0x0a,0xce,0x0a,0xe8,0x0b,0x02,0x0b,0x1c,0x0b,0x36,0x0b,0x50,0x0b,0x6a,0x0b,0x84,0x0b,0x9e,0x0b,0xb8,0x0b,0xd2,0x0b,0xec,0x0c,0x06,0x0c,0x20,0x0c,0x3a, 0x0c,0x54,0x0c,0x6e,0x0c,0x88,0x0c,0xa2,0x0c,0xbc,0x0c,0xd6,0x0c,0xf0,0x0d,0x0a,0x0d,0x24,0x0d,0x3e,0x0d,0x58,0x0d,0x72,0x0d,0x8c,0x0d,0xa6,0x0d,0xc0,0x0d,0xda,0x0d,0xf4,0x0e,0x0e,0x0e,0x28,0x0e,0x42,0x0e,0x5c,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0a,0x43,0x00,0x02,0x07,0x39,0x0a,0x43,0x00,0x02,0x08,0xc4,0x0a,0x43, 0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x53,0x00,0x02,0x07,0x39,0x0b,0x53,0x00,0x02,0x08,0xc4,0x0b,0x53,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x54,0x00,0x02,0x07,0x39,0x0b,0x54,0x00,0x02,0x08,0xc4,0x0b,0x54,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14, 0x0b,0x55,0x00,0x02,0x07,0x39,0x0b,0x55,0x00,0x02,0x08,0xc4,0x0b,0x55,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x56,0x00,0x02,0x07,0x39,0x0b,0x56,0x00,0x02,0x08,0xc4,0x0b,0x56,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x57,0x00,0x02,0x07,0x39,0x0b,0x57,0x00,0x02,0x08,0xc4, 0x0b,0x57,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x58,0x00,0x02,0x07,0x39,0x0b,0x58,0x00,0x02,0x08,0xc4,0x0b,0x58,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x59,0x00,0x02,0x07,0x39,0x0b,0x59,0x00,0x02,0x08,0xc4,0x0b,0x59,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e, 0x00,0x14,0x0b,0x5a,0x00,0x02,0x07,0x39,0x0b,0x5a,0x00,0x02,0x08,0xc4,0x0b,0x5a,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x5b,0x00,0x02,0x07,0x39,0x0b,0x5b,0x00,0x02,0x08,0xc4,0x0b,0x5b,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x5c,0x00,0x02,0x07,0x39,0x0b,0x5c,0x00,0x02, 0x08,0xc4,0x0b,0x5c,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x5d,0x00,0x02,0x07,0x39,0x0b,0x5d,0x00,0x02,0x08,0xc4,0x0b,0x5d,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x5e,0x00,0x02,0x07,0x39,0x0b,0x5e,0x00,0x02,0x08,0xc4,0x0b,0x5e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08, 0x00,0x0e,0x00,0x14,0x0b,0x5f,0x00,0x02,0x07,0x39,0x0b,0x5f,0x00,0x02,0x08,0xc4,0x0b,0x5f,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x61,0x00,0x02,0x07,0x39,0x0b,0x61,0x00,0x02,0x08,0xc4,0x0b,0x61,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x66,0x00,0x02,0x07,0x39,0x0b,0x66, 0x00,0x02,0x08,0xc4,0x0b,0x66,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x67,0x00,0x02,0x07,0x39,0x0b,0x67,0x00,0x02,0x08,0xc4,0x0b,0x67,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x68,0x00,0x02,0x07,0x39,0x0b,0x68,0x00,0x02,0x08,0xc4,0x0b,0x68,0x00,0x02,0x08,0xc3,0x00,0x03, 0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x69,0x00,0x02,0x07,0x39,0x0b,0x69,0x00,0x02,0x08,0xc4,0x0b,0x69,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6a,0x00,0x02,0x07,0x39,0x0b,0x6a,0x00,0x02,0x08,0xc4,0x0b,0x6a,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6b,0x00,0x02,0x07,0x39, 0x0b,0x6b,0x00,0x02,0x08,0xc4,0x0b,0x6b,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6c,0x00,0x02,0x07,0x39,0x0b,0x6c,0x00,0x02,0x08,0xc4,0x0b,0x6c,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6d,0x00,0x02,0x07,0x39,0x0b,0x6d,0x00,0x02,0x08,0xc4,0x0b,0x6d,0x00,0x02,0x08,0xc3, 0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6e,0x00,0x02,0x07,0x39,0x0b,0x6e,0x00,0x02,0x08,0xc4,0x0b,0x6e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x6f,0x00,0x02,0x07,0x39,0x0b,0x6f,0x00,0x02,0x08,0xc4,0x0b,0x6f,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x70,0x00,0x02, 0x07,0x39,0x0b,0x70,0x00,0x02,0x08,0xc4,0x0b,0x70,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x71,0x00,0x02,0x07,0x39,0x0b,0x71,0x00,0x02,0x08,0xc4,0x0b,0x71,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x72,0x00,0x02,0x07,0x39,0x0b,0x72,0x00,0x02,0x08,0xc4,0x0b,0x72,0x00,0x02, 0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x73,0x00,0x02,0x07,0x39,0x0b,0x73,0x00,0x02,0x08,0xc4,0x0b,0x73,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x74,0x00,0x02,0x07,0x39,0x0b,0x74,0x00,0x02,0x08,0xc4,0x0b,0x74,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x75, 0x00,0x02,0x07,0x39,0x0b,0x75,0x00,0x02,0x08,0xc4,0x0b,0x75,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x76,0x00,0x02,0x07,0x39,0x0b,0x76,0x00,0x02,0x08,0xc4,0x0b,0x76,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x77,0x00,0x02,0x07,0x39,0x0b,0x77,0x00,0x02,0x08,0xc4,0x0b,0x77, 0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x78,0x00,0x02,0x07,0x39,0x0b,0x78,0x00,0x02,0x08,0xc4,0x0b,0x78,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x79,0x00,0x02,0x07,0x39,0x0b,0x79,0x00,0x02,0x08,0xc4,0x0b,0x79,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14, 0x0b,0x7a,0x00,0x02,0x07,0x39,0x0b,0x7a,0x00,0x02,0x08,0xc4,0x0b,0x7a,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x7b,0x00,0x02,0x07,0x39,0x0b,0x7b,0x00,0x02,0x08,0xc4,0x0b,0x7b,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x7c,0x00,0x02,0x07,0x39,0x0b,0x7c,0x00,0x02,0x08,0xc4, 0x0b,0x7c,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x7d,0x00,0x02,0x07,0x39,0x0b,0x7d,0x00,0x02,0x08,0xc4,0x0b,0x7d,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x7e,0x00,0x02,0x07,0x39,0x0b,0x7e,0x00,0x02,0x08,0xc4,0x0b,0x7e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e, 0x00,0x14,0x0b,0x7f,0x00,0x02,0x07,0x39,0x0b,0x7f,0x00,0x02,0x08,0xc4,0x0b,0x7f,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x80,0x00,0x02,0x07,0x39,0x0b,0x80,0x00,0x02,0x08,0xc4,0x0b,0x80,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x81,0x00,0x02,0x07,0x39,0x0b,0x81,0x00,0x02, 0x08,0xc4,0x0b,0x81,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x82,0x00,0x02,0x07,0x39,0x0b,0x82,0x00,0x02,0x08,0xc4,0x0b,0x82,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x83,0x00,0x02,0x07,0x39,0x0b,0x83,0x00,0x02,0x08,0xc4,0x0b,0x83,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08, 0x00,0x0e,0x00,0x14,0x0b,0x84,0x00,0x02,0x07,0x39,0x0b,0x84,0x00,0x02,0x08,0xc4,0x0b,0x84,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x85,0x00,0x02,0x07,0x39,0x0b,0x85,0x00,0x02,0x08,0xc4,0x0b,0x85,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x88,0x00,0x02,0x07,0x39,0x0b,0x88, 0x00,0x02,0x08,0xc4,0x0b,0x88,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x89,0x00,0x02,0x07,0x39,0x0b,0x89,0x00,0x02,0x08,0xc4,0x0b,0x89,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8a,0x00,0x02,0x07,0x39,0x0b,0x8a,0x00,0x02,0x08,0xc4,0x0b,0x8a,0x00,0x02,0x08,0xc3,0x00,0x03, 0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8b,0x00,0x02,0x07,0x39,0x0b,0x8b,0x00,0x02,0x08,0xc4,0x0b,0x8b,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8c,0x00,0x02,0x07,0x39,0x0b,0x8c,0x00,0x02,0x08,0xc4,0x0b,0x8c,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8d,0x00,0x02,0x07,0x39, 0x0b,0x8d,0x00,0x02,0x08,0xc4,0x0b,0x8d,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8e,0x00,0x02,0x07,0x39,0x0b,0x8e,0x00,0x02,0x08,0xc4,0x0b,0x8e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x8f,0x00,0x02,0x07,0x39,0x0b,0x8f,0x00,0x02,0x08,0xc4,0x0b,0x8f,0x00,0x02,0x08,0xc3, 0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x90,0x00,0x02,0x07,0x39,0x0b,0x90,0x00,0x02,0x08,0xc4,0x0b,0x90,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x91,0x00,0x02,0x07,0x39,0x0b,0x91,0x00,0x02,0x08,0xc4,0x0b,0x91,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x92,0x00,0x02, 0x07,0x39,0x0b,0x92,0x00,0x02,0x08,0xc4,0x0b,0x92,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x93,0x00,0x02,0x07,0x39,0x0b,0x93,0x00,0x02,0x08,0xc4,0x0b,0x93,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x94,0x00,0x02,0x07,0x39,0x0b,0x94,0x00,0x02,0x08,0xc4,0x0b,0x94,0x00,0x02, 0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x95,0x00,0x02,0x07,0x39,0x0b,0x95,0x00,0x02,0x08,0xc4,0x0b,0x95,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x97,0x00,0x02,0x07,0x39,0x0b,0x97,0x00,0x02,0x08,0xc4,0x0b,0x97,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x98, 0x00,0x02,0x07,0x39,0x0b,0x98,0x00,0x02,0x08,0xc4,0x0b,0x98,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x99,0x00,0x02,0x07,0x39,0x0b,0x99,0x00,0x02,0x08,0xc4,0x0b,0x99,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x9a,0x00,0x02,0x07,0x39,0x0b,0x9a,0x00,0x02,0x08,0xc4,0x0b,0x9a, 0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x9d,0x00,0x02,0x07,0x39,0x0b,0x9d,0x00,0x02,0x08,0xc4,0x0b,0x9d,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0x9e,0x00,0x02,0x07,0x39,0x0b,0x9e,0x00,0x02,0x08,0xc4,0x0b,0x9e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14, 0x0b,0x9f,0x00,0x02,0x07,0x39,0x0b,0x9f,0x00,0x02,0x08,0xc4,0x0b,0x9f,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa0,0x00,0x02,0x07,0x39,0x0b,0xa0,0x00,0x02,0x08,0xc4,0x0b,0xa0,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa1,0x00,0x02,0x07,0x39,0x0b,0xa1,0x00,0x02,0x08,0xc4, 0x0b,0xa1,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa2,0x00,0x02,0x07,0x39,0x0b,0xa2,0x00,0x02,0x08,0xc4,0x0b,0xa2,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa3,0x00,0x02,0x07,0x39,0x0b,0xa3,0x00,0x02,0x08,0xc4,0x0b,0xa3,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e, 0x00,0x14,0x0b,0xa4,0x00,0x02,0x07,0x39,0x0b,0xa4,0x00,0x02,0x08,0xc4,0x0b,0xa4,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa5,0x00,0x02,0x07,0x39,0x0b,0xa5,0x00,0x02,0x08,0xc4,0x0b,0xa5,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa6,0x00,0x02,0x07,0x39,0x0b,0xa6,0x00,0x02, 0x08,0xc4,0x0b,0xa6,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa7,0x00,0x02,0x07,0x39,0x0b,0xa7,0x00,0x02,0x08,0xc4,0x0b,0xa7,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xa8,0x00,0x02,0x07,0x39,0x0b,0xa8,0x00,0x02,0x08,0xc4,0x0b,0xa8,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08, 0x00,0x0e,0x00,0x14,0x0b,0xa9,0x00,0x02,0x07,0x39,0x0b,0xa9,0x00,0x02,0x08,0xc4,0x0b,0xa9,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xaa,0x00,0x02,0x07,0x39,0x0b,0xaa,0x00,0x02,0x08,0xc4,0x0b,0xaa,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xab,0x00,0x02,0x07,0x39,0x0b,0xab, 0x00,0x02,0x08,0xc4,0x0b,0xab,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xac,0x00,0x02,0x07,0x39,0x0b,0xac,0x00,0x02,0x08,0xc4,0x0b,0xac,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xad,0x00,0x02,0x07,0x39,0x0b,0xad,0x00,0x02,0x08,0xc4,0x0b,0xad,0x00,0x02,0x08,0xc3,0x00,0x03, 0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xae,0x00,0x02,0x07,0x39,0x0b,0xae,0x00,0x02,0x08,0xc4,0x0b,0xae,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xaf,0x00,0x02,0x07,0x39,0x0b,0xaf,0x00,0x02,0x08,0xc4,0x0b,0xaf,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb0,0x00,0x02,0x07,0x39, 0x0b,0xb0,0x00,0x02,0x08,0xc4,0x0b,0xb0,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb1,0x00,0x02,0x07,0x39,0x0b,0xb1,0x00,0x02,0x08,0xc4,0x0b,0xb1,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb2,0x00,0x02,0x07,0x39,0x0b,0xb2,0x00,0x02,0x08,0xc4,0x0b,0xb2,0x00,0x02,0x08,0xc3, 0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb3,0x00,0x02,0x07,0x39,0x0b,0xb3,0x00,0x02,0x08,0xc4,0x0b,0xb3,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb4,0x00,0x02,0x07,0x39,0x0b,0xb4,0x00,0x02,0x08,0xc4,0x0b,0xb4,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb5,0x00,0x02, 0x07,0x39,0x0b,0xb5,0x00,0x02,0x08,0xc4,0x0b,0xb5,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb6,0x00,0x02,0x07,0x39,0x0b,0xb6,0x00,0x02,0x08,0xc4,0x0b,0xb6,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb7,0x00,0x02,0x07,0x39,0x0b,0xb7,0x00,0x02,0x08,0xc4,0x0b,0xb7,0x00,0x02, 0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xb9,0x00,0x02,0x07,0x39,0x0b,0xb9,0x00,0x02,0x08,0xc4,0x0b,0xb9,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xbf,0x00,0x02,0x07,0x39,0x0b,0xbf,0x00,0x02,0x08,0xc4,0x0b,0xbf,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc0, 0x00,0x02,0x07,0x39,0x0b,0xc0,0x00,0x02,0x08,0xc4,0x0b,0xc0,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc1,0x00,0x02,0x07,0x39,0x0b,0xc1,0x00,0x02,0x08,0xc4,0x0b,0xc1,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc2,0x00,0x02,0x07,0x39,0x0b,0xc2,0x00,0x02,0x08,0xc4,0x0b,0xc2, 0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc3,0x00,0x02,0x07,0x39,0x0b,0xc3,0x00,0x02,0x08,0xc4,0x0b,0xc3,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc4,0x00,0x02,0x07,0x39,0x0b,0xc4,0x00,0x02,0x08,0xc4,0x0b,0xc4,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14, 0x0b,0xc5,0x00,0x02,0x07,0x39,0x0b,0xc5,0x00,0x02,0x08,0xc4,0x0b,0xc5,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc6,0x00,0x02,0x07,0x39,0x0b,0xc6,0x00,0x02,0x08,0xc4,0x0b,0xc6,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc7,0x00,0x02,0x07,0x39,0x0b,0xc7,0x00,0x02,0x08,0xc4, 0x0b,0xc7,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc8,0x00,0x02,0x07,0x39,0x0b,0xc8,0x00,0x02,0x08,0xc4,0x0b,0xc8,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xc9,0x00,0x02,0x07,0x39,0x0b,0xc9,0x00,0x02,0x08,0xc4,0x0b,0xc9,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e, 0x00,0x14,0x0b,0xca,0x00,0x02,0x07,0x39,0x0b,0xca,0x00,0x02,0x08,0xc4,0x0b,0xca,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xcb,0x00,0x02,0x07,0x39,0x0b,0xcb,0x00,0x02,0x08,0xc4,0x0b,0xcb,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xcc,0x00,0x02,0x07,0x39,0x0b,0xcc,0x00,0x02, 0x08,0xc4,0x0b,0xcc,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xcd,0x00,0x02,0x07,0x39,0x0b,0xcd,0x00,0x02,0x08,0xc4,0x0b,0xcd,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xce,0x00,0x02,0x07,0x39,0x0b,0xce,0x00,0x02,0x08,0xc4,0x0b,0xce,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08, 0x00,0x0e,0x00,0x14,0x0b,0xcf,0x00,0x02,0x07,0x39,0x0b,0xcf,0x00,0x02,0x08,0xc4,0x0b,0xcf,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd0,0x00,0x02,0x07,0x39,0x0b,0xd0,0x00,0x02,0x08,0xc4,0x0b,0xd0,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd1,0x00,0x02,0x07,0x39,0x0b,0xd1, 0x00,0x02,0x08,0xc4,0x0b,0xd1,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd2,0x00,0x02,0x07,0x39,0x0b,0xd2,0x00,0x02,0x08,0xc4,0x0b,0xd2,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd3,0x00,0x02,0x07,0x39,0x0b,0xd3,0x00,0x02,0x08,0xc4,0x0b,0xd3,0x00,0x02,0x08,0xc3,0x00,0x03, 0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd4,0x00,0x02,0x07,0x39,0x0b,0xd4,0x00,0x02,0x08,0xc4,0x0b,0xd4,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd5,0x00,0x02,0x07,0x39,0x0b,0xd5,0x00,0x02,0x08,0xc4,0x0b,0xd5,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd6,0x00,0x02,0x07,0x39, 0x0b,0xd6,0x00,0x02,0x08,0xc4,0x0b,0xd6,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd7,0x00,0x02,0x07,0x39,0x0b,0xd7,0x00,0x02,0x08,0xc4,0x0b,0xd7,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd8,0x00,0x02,0x07,0x39,0x0b,0xd8,0x00,0x02,0x08,0xc4,0x0b,0xd8,0x00,0x02,0x08,0xc3, 0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xd9,0x00,0x02,0x07,0x39,0x0b,0xd9,0x00,0x02,0x08,0xc4,0x0b,0xd9,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xda,0x00,0x02,0x07,0x39,0x0b,0xda,0x00,0x02,0x08,0xc4,0x0b,0xda,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xdb,0x00,0x02, 0x07,0x39,0x0b,0xdb,0x00,0x02,0x08,0xc4,0x0b,0xdb,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xdc,0x00,0x02,0x07,0x39,0x0b,0xdc,0x00,0x02,0x08,0xc4,0x0b,0xdc,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xdd,0x00,0x02,0x07,0x39,0x0b,0xdd,0x00,0x02,0x08,0xc4,0x0b,0xdd,0x00,0x02, 0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x0b,0xe1,0x00,0x02,0x07,0x39,0x0b,0xe1,0x00,0x02,0x08,0xc4,0x0b,0xe1,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x5c,0x00,0x02,0x07,0x39,0x12,0x5c,0x00,0x02,0x08,0xc4,0x12,0x5c,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x5d, 0x00,0x02,0x07,0x39,0x12,0x5d,0x00,0x02,0x08,0xc4,0x12,0x5d,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x5e,0x00,0x02,0x07,0x39,0x12,0x5e,0x00,0x02,0x08,0xc4,0x12,0x5e,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x5f,0x00,0x02,0x07,0x39,0x12,0x5f,0x00,0x02,0x08,0xc4,0x12,0x5f, 0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x60,0x00,0x02,0x07,0x39,0x12,0x60,0x00,0x02,0x08,0xc4,0x12,0x60,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14,0x12,0x61,0x00,0x02,0x07,0x39,0x12,0x61,0x00,0x02,0x08,0xc4,0x12,0x61,0x00,0x02,0x08,0xc3,0x00,0x03,0x00,0x08,0x00,0x0e,0x00,0x14, 0x12,0x62,0x00,0x02,0x07,0x39,0x12,0x62,0x00,0x02,0x08,0xc4,0x12,0x62,0x00,0x02,0x08,0xc3,0x00,0x02,0x00,0x0b,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x53,0x0b,0x5f,0x00,0x01,0x0b,0x61,0x0b,0x61,0x00,0x0e,0x0b,0x66,0x0b,0x85,0x00,0x0f,0x0b,0x88,0x0b,0x95,0x00,0x2f,0x0b,0x97,0x0b,0x9a,0x00,0x3d,0x0b,0x9d,0x0b,0xb7,0x00,0x41, 0x0b,0xb9,0x0b,0xb9,0x00,0x5c,0x0b,0xbf,0x0b,0xdd,0x00,0x5d,0x0b,0xe1,0x0b,0xe1,0x00,0x7c,0x12,0x5c,0x12,0x62,0x00,0x7d,0x00,0x01,0x00,0xa2,0x00,0x0d,0x00,0x20,0x00,0x2a,0x00,0x34,0x00,0x3e,0x00,0x48,0x00,0x52,0x00,0x5c,0x00,0x66,0x00,0x70,0x00,0x7a,0x00,0x84,0x00,0x8e,0x00,0x98,0x00,0x01,0x00,0x04,0x0b,0x53,0x00,0x02, 0x0b,0x53,0x00,0x01,0x00,0x04,0x0b,0x54,0x00,0x02,0x0b,0x54,0x00,0x01,0x00,0x04,0x0b,0x55,0x00,0x02,0x0b,0x55,0x00,0x01,0x00,0x04,0x0b,0x56,0x00,0x02,0x0b,0x56,0x00,0x01,0x00,0x04,0x0b,0x57,0x00,0x02,0x0b,0x57,0x00,0x01,0x00,0x04,0x0b,0x58,0x00,0x02,0x0b,0x58,0x00,0x01,0x00,0x04,0x0b,0x59,0x00,0x02,0x0b,0x59,0x00,0x01, 0x00,0x04,0x0b,0x5a,0x00,0x02,0x0b,0x5a,0x00,0x01,0x00,0x04,0x0b,0x5b,0x00,0x02,0x0b,0x5b,0x00,0x01,0x00,0x04,0x0b,0x5c,0x00,0x02,0x0b,0x5c,0x00,0x01,0x00,0x04,0x0b,0x5d,0x00,0x02,0x0b,0x5d,0x00,0x01,0x00,0x04,0x0b,0xb9,0x00,0x02,0x0b,0xb9,0x00,0x01,0x00,0x04,0x0b,0xde,0x00,0x02,0x0b,0xde,0x00,0x02,0x00,0x03,0x0b,0x53, 0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b,0x0b,0xde,0x0b,0xde,0x00,0x0c,0x00,0x01,0x01,0x5a,0x00,0x16,0x00,0x32,0x00,0x3c,0x00,0x4e,0x00,0x60,0x00,0x72,0x00,0x84,0x00,0x8e,0x00,0x98,0x00,0xa2,0x00,0xac,0x00,0xb6,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x01,0x0c,0x01,0x16,0x01,0x20,0x01,0x2a, 0x01,0x48,0x00,0x01,0x00,0x04,0x0b,0x9d,0x00,0x02,0x0b,0x5e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0x9e,0x00,0x02,0x0b,0x5e,0x0b,0xb4,0x00,0x02,0x0b,0x61,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0x9f,0x00,0x02,0x0b,0x5e,0x12,0x5f,0x00,0x02,0x0b,0x61,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xa0,0x00,0x02,0x0b,0x5e,0x12,0x60,0x00,0x02, 0x0b,0x61,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xa1,0x00,0x02,0x0b,0x5e,0x12,0x61,0x00,0x02,0x0b,0x61,0x00,0x01,0x00,0x04,0x0b,0xa2,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xa3,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xa4,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xa5,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04, 0x0b,0xa6,0x00,0x02,0x0b,0x5e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xa7,0x00,0x02,0x0b,0x5e,0x0b,0xb5,0x00,0x02,0x0b,0x61,0x00,0x01,0x00,0x04,0x0b,0xa8,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xa9,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xaa,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xab,0x00,0x02,0x0b,0x5e, 0x00,0x01,0x00,0x04,0x0b,0xac,0x00,0x02,0x0b,0x5e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xad,0x00,0x02,0x0b,0x5e,0x0b,0xb6,0x00,0x02,0x0b,0x61,0x00,0x01,0x00,0x04,0x0b,0xae,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xaf,0x00,0x02,0x0b,0x5e,0x00,0x01,0x00,0x04,0x0b,0xb0,0x00,0x02,0x0b,0x5e,0x00,0x03,0x00,0x08,0x00,0x0e, 0x00,0x16,0x0b,0xb1,0x00,0x02,0x0b,0x5e,0x0b,0x99,0x00,0x03,0x0b,0x63,0x0b,0x5e,0x0b,0x9a,0x00,0x03,0x0b,0x64,0x0b,0x5e,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0xb2,0x00,0x02,0x0b,0x5e,0x12,0x62,0x00,0x02,0x0b,0x61,0x00,0x02,0x00,0x06,0x0b,0x68,0x0b,0x6e,0x00,0x00,0x0b,0x70,0x0b,0x74,0x00,0x07,0x0b,0x76,0x0b,0x76,0x00,0x0c, 0x0b,0x78,0x0b,0x79,0x00,0x0d,0x0b,0x7b,0x0b,0x7c,0x00,0x0f,0x0b,0x7e,0x0b,0x82,0x00,0x11,0x00,0x01,0x00,0x2e,0x00,0x02,0x00,0x0a,0x00,0x1c,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0x97,0x00,0x02,0x0b,0x63,0x0b,0x98,0x00,0x02,0x0b,0x64,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0x99,0x00,0x02,0x0b,0x63,0x0b,0x9a,0x00,0x02,0x0b,0x64, 0x00,0x01,0x00,0x02,0x0b,0x81,0x0b,0xb1,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x0b,0xb3,0x00,0x02,0x0b,0x5c,0x00,0x01,0x00,0x01,0x0b,0x6d,0x00,0x02,0x00,0x08,0x00,0x01,0x0b,0x5c,0x00,0x01,0x00,0x01,0x0b,0xde,0x00,0x03,0x00,0x00,0x00,0x02,0x02,0x38,0x02,0x40,0x00,0x01,0x02,0x46,0x00,0x01,0x00,0x00, 0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x02,0x24,0x02,0x2c,0x00,0x02,0x02,0x6c,0x02,0x32,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x02,0x0e,0x02,0x16,0x00,0x03,0x02,0x56,0x02,0x56,0x02,0x1c,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0xf6,0x01,0xfe,0x00,0x04,0x02,0x3e,0x02,0x3e, 0x02,0x3e,0x02,0x04,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0xdc,0x01,0xe4,0x00,0x02,0x02,0x46,0x02,0x4c,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0xc6,0x01,0xce,0x00,0x03,0x02,0x0e,0x02,0x30,0x02,0x36,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0xae, 0x01,0xb6,0x00,0x04,0x01,0xf6,0x01,0xf6,0x02,0x18,0x02,0x1e,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x94,0x01,0x9c,0x00,0x05,0x01,0xdc,0x01,0xdc,0x01,0xdc,0x01,0xfe,0x02,0x04,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x78,0x01,0x80,0x00,0x01,0x01,0xf8,0x00,0x01,0x00,0x00, 0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x64,0x01,0x6c,0x00,0x02,0x01,0xac,0x01,0xe4,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x4e,0x01,0x56,0x00,0x03,0x01,0x96,0x01,0x96,0x01,0xce,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x36,0x01,0x3e,0x00,0x04,0x01,0x7e,0x01,0x7e, 0x01,0x7e,0x01,0xb6,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x1c,0x01,0x24,0x00,0x02,0x01,0x86,0x01,0xa2,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x01,0x06,0x01,0x0e,0x00,0x02,0x01,0x70,0x01,0x92,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0xf0,0x00,0xf8, 0x00,0x03,0x01,0x38,0x01,0x5a,0x01,0x76,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0xd8,0x00,0xe0,0x00,0x03,0x01,0x20,0x01,0x42,0x01,0x64,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0xc0,0x00,0xc8,0x00,0x04,0x01,0x08,0x01,0x08,0x01,0x2a,0x01,0x46,0x00,0x01,0x00,0x00,0x00,0x78, 0x00,0x03,0x00,0x00,0x00,0x02,0x00,0xa6,0x00,0xae,0x00,0x04,0x00,0xee,0x00,0xee,0x01,0x10,0x01,0x32,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x8c,0x00,0x94,0x00,0x05,0x00,0xd4,0x00,0xd4,0x00,0xd4,0x00,0xf6,0x01,0x12,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x70,0x00,0x78, 0x00,0x05,0x00,0xb8,0x00,0xb8,0x00,0xb8,0x00,0xda,0x00,0xfc,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x54,0x00,0x5c,0x00,0x01,0x00,0xe6,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x48,0x00,0x02,0x00,0xd8,0x00,0xd2,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00, 0x00,0x02,0x00,0x2a,0x00,0x32,0x00,0x01,0x00,0xf0,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x16,0x00,0x1e,0x00,0x02,0x00,0xae,0x00,0xdc,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x01,0x00,0x02,0x0b,0x74,0x0b,0xa8,0x00,0x01,0x00,0x01,0x0b,0x5c,0x00,0x02,0x00,0x09,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x69, 0x0b,0x85,0x00,0x01,0x0b,0x88,0x0b,0x95,0x00,0x1e,0x0b,0x97,0x0b,0x9a,0x00,0x2c,0x0b,0x9d,0x0b,0xa6,0x00,0x30,0x0b,0xa8,0x0b,0xb2,0x00,0x3a,0x0b,0xb4,0x0b,0xb7,0x00,0x45,0x0b,0xe0,0x0b,0xe0,0x00,0x49,0x12,0x5f,0x12,0x62,0x00,0x4a,0x00,0x02,0x00,0x05,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf, 0x0b,0xdd,0x00,0x02,0x0b,0xe1,0x0b,0xe1,0x00,0x21,0x12,0x5c,0x12,0x5d,0x00,0x22,0x00,0x01,0x00,0x01,0x0b,0x68,0x00,0x02,0x00,0x02,0x0b,0x53,0x0b,0x5d,0x00,0x00,0x0b,0xb9,0x0b,0xb9,0x00,0x0b,0x00,0x01,0x00,0x01,0x0b,0x9d,0x00,0x01,0x00,0x01,0x0b,0xb3,0x00,0x01,0x00,0x01,0x0b,0xa2,0x00,0x01,0x00,0x01,0x0b,0xc7,0x00,0x02, 0x00,0x07,0x0b,0x53,0x0b,0x5f,0x00,0x00,0x0b,0x61,0x0b,0x61,0x00,0x0d,0x0b,0x66,0x0b,0x67,0x00,0x0e,0x0b,0xb9,0x0b,0xb9,0x00,0x10,0x0b,0xbf,0x0b,0xdd,0x00,0x11,0x0b,0xe1,0x0b,0xe1,0x00,0x30,0x12,0x5c,0x12,0x5e,0x00,0x31,0x00,0x01,0x00,0x01,0x0b,0xdc,0x00,0x03,0x00,0x02,0x00,0x16,0x00,0x1c,0x00,0x02,0x00,0x22,0x00,0x28, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x79,0x00,0x01,0x00,0x01,0x0b,0x53,0x00,0x01,0x00,0x01,0x0b,0x7e,0x00,0x01,0x00,0x01,0x0a,0x43,0x00,0x01,0x00,0x01,0x0b,0x57,0x00,0x01,0x00,0x1a,0x00,0x01,0x00,0x08,0x00,0x02,0x00,0x06,0x00,0x0c,0x0b,0x88,0x00,0x02,0x0b,0x53,0x0b,0x89,0x00,0x02,0x0b,0x5b,0x00,0x01,0x00,0x01,0x0b,0x72, 0x00,0x03,0x00,0x02,0x01,0xcc,0x01,0xe8,0x00,0x01,0x01,0xee,0x00,0x02,0x02,0x1c,0x02,0x56,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0xb4,0x01,0xd0,0x00,0x01,0x01,0xd6,0x00,0x01,0x02,0x54,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x9e,0x02,0x66,0x00,0x01,0x01,0xc0,0x00,0x02,0x01,0xee,0x02,0x28, 0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x86,0x02,0x4e,0x00,0x01,0x01,0xa8,0x00,0x01,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x70,0x02,0x3e,0x00,0x01,0x01,0x92,0x00,0x02,0x01,0xc0,0x01,0xfa,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x58,0x02,0x26,0x00,0x01,0x01,0x7a, 0x00,0x01,0x01,0xf8,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x42,0x02,0x16,0x00,0x01,0x01,0x64,0x00,0x02,0x01,0x92,0x01,0xcc,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x2a,0x01,0xfe,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0xca,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x01,0x14,0x01,0xee, 0x00,0x01,0x01,0x36,0x00,0x02,0x01,0x64,0x01,0x9e,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0xfc,0x01,0xd6,0x00,0x01,0x01,0x1e,0x00,0x01,0x01,0x9c,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0xe6,0x01,0xc6,0x00,0x01,0x01,0x08,0x00,0x02,0x01,0x36,0x01,0x70,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03, 0x00,0x02,0x00,0xce,0x01,0xae,0x00,0x01,0x00,0xf0,0x00,0x01,0x01,0x6e,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0xb8,0x01,0x9e,0x00,0x01,0x00,0xda,0x00,0x02,0x01,0x08,0x01,0x42,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0xa0,0x01,0x86,0x00,0x01,0x00,0xc2,0x00,0x01,0x01,0x40,0x00,0x01,0x00,0x00, 0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x8a,0x01,0x76,0x00,0x01,0x00,0xac,0x00,0x02,0x00,0xda,0x01,0x14,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x72,0x01,0x5e,0x00,0x01,0x00,0x94,0x00,0x01,0x01,0x12,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x5c,0x01,0x4e,0x00,0x01,0x00,0x7e,0x00,0x02,0x00,0xac, 0x00,0xe6,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x44,0x01,0x36,0x00,0x01,0x00,0x66,0x00,0x01,0x00,0xe4,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x2e,0x01,0x26,0x00,0x01,0x00,0x50,0x00,0x02,0x00,0x7e,0x00,0xb8,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x03,0x00,0x02,0x00,0x16,0x01,0x0e,0x00,0x01, 0x00,0x38,0x00,0x01,0x00,0xb6,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x02,0x00,0x04,0x0b,0x54,0x0b,0x56,0x00,0x00,0x0b,0x58,0x0b,0x5b,0x00,0x03,0x0b,0x5d,0x0b,0x5d,0x00,0x07,0x0b,0xb9,0x0b,0xb9,0x00,0x08,0x00,0x01,0x00,0x01,0x0b,0x6a,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf, 0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x02,0x00,0x09,0x0b,0x6a,0x0b,0x6b,0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x02,0x0b,0x71,0x0b,0x71,0x00,0x04,0x0b,0x7d,0x0b,0x7d,0x00,0x05,0x0b,0x7f,0x0b,0x80,0x00,0x06,0x0b,0x9f, 0x0b,0xa0,0x00,0x08,0x0b,0xa2,0x0b,0xa3,0x00,0x0a,0x0b,0xa5,0x0b,0xa5,0x00,0x0c,0x0b,0xaf,0x0b,0xb0,0x00,0x0d,0x00,0x02,0x00,0x03,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0xb9,0x0b,0xb9,0x00,0x0a,0x00,0x02,0x00,0x06,0x0b,0x72,0x0b,0x72,0x00,0x00,0x0b,0x77,0x0b,0x77,0x00,0x01,0x0b,0x7b,0x0b,0x7b, 0x00,0x02,0x0b,0x88,0x0b,0x89,0x00,0x03,0x0b,0xa6,0x0b,0xa6,0x00,0x05,0x0b,0xac,0x0b,0xac,0x00,0x06,0x00,0x01,0x00,0x01,0x0b,0x9f,0x00,0x01,0x00,0x01,0x0b,0x6d,0x00,0x01,0x00,0x01,0x0b,0xa2,0x00,0x01,0x00,0x01,0x0b,0x71,0x00,0x01,0x00,0x01,0x0b,0xa5,0x00,0x01,0x00,0x01,0x0b,0x78,0x00,0x01,0x00,0x01,0x0b,0xaa,0x00,0x01, 0x00,0x01,0x0b,0x6e,0x00,0x01,0x00,0x01,0x0b,0xa3,0x00,0x03,0x00,0x02,0x00,0x14,0x00,0x14,0x00,0x01,0x00,0x54,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7b,0x00,0x02,0x00,0x0a,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0x5f,0x0b,0x5f,0x00,0x0a,0x0b,0x67,0x0b,0x67,0x00,0x0b,0x0b,0xb9,0x0b,0xb9,0x00,0x0c, 0x0b,0xbf,0x0b,0xbf,0x00,0x0d,0x0b,0xc4,0x0b,0xc4,0x00,0x0e,0x0b,0xc9,0x0b,0xc9,0x00,0x0f,0x0b,0xd0,0x0b,0xd5,0x00,0x10,0x0b,0xd8,0x0b,0xd8,0x00,0x16,0x00,0x02,0x00,0x09,0x0b,0x53,0x0b,0x53,0x00,0x00,0x0b,0x5a,0x0b,0x5a,0x00,0x01,0x0b,0x5f,0x0b,0x5f,0x00,0x02,0x0b,0x67,0x0b,0x67,0x00,0x03,0x0b,0xbf,0x0b,0xbf,0x00,0x04, 0x0b,0xc4,0x0b,0xc4,0x00,0x05,0x0b,0xc9,0x0b,0xc9,0x00,0x06,0x0b,0xd0,0x0b,0xd5,0x00,0x07,0x0b,0xd8,0x0b,0xd8,0x00,0x0d,0x00,0x01,0x00,0x36,0x00,0x04,0x00,0x0e,0x00,0x16,0x00,0x26,0x00,0x2e,0x00,0x01,0x00,0x04,0x0b,0x67,0x00,0x01,0x00,0x02,0x00,0x06,0x00,0x0c,0x12,0x5d,0x00,0x02,0x04,0x67,0x12,0x5c,0x00,0x01,0x00,0x01, 0x00,0x04,0x12,0x5d,0x00,0x01,0x00,0x01,0x00,0x04,0x12,0x5c,0x00,0x01,0x00,0x02,0x00,0x03,0x02,0x45,0x02,0x45,0x00,0x00,0x04,0x67,0x04,0x68,0x00,0x01,0x0b,0x66,0x0b,0x66,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xf6,0x00,0x04,0x01,0x3c,0x01,0x76,0x01,0x76,0x01,0xb6,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00, 0x00,0x01,0x00,0xde,0x00,0x04,0x01,0x24,0x01,0x5e,0x01,0x5e,0x01,0xa4,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xc6,0x00,0x03,0x01,0x0c,0x01,0x92,0x01,0x86,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xb0,0x00,0x03,0x00,0xf6,0x01,0x7c,0x01,0x76,0x00,0x01,0x00,0x00,0x00,0x7c, 0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x9a,0x00,0x03,0x00,0xe0,0x01,0x6c,0x01,0x5a,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x84,0x00,0x03,0x00,0xca,0x01,0x56,0x01,0x4a,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x6e,0x00,0x03,0x00,0xb4,0x01,0x46,0x01,0x2e,0x00,0x01,0x00,0x00, 0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x58,0x00,0x03,0x00,0x9e,0x01,0x30,0x01,0x1e,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x03,0x00,0x88,0x01,0x20,0x01,0x26,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x2c,0x00,0x03,0x00,0x72,0x01,0x0a,0x01,0x16,0x00,0x01, 0x00,0x00,0x00,0x7c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x16,0x00,0x03,0x00,0x5c,0x00,0xf4,0x01,0x06,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x02,0x00,0x0b,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x53,0x0b,0x5f,0x00,0x01,0x0b,0x61,0x0b,0x61,0x00,0x0e,0x0b,0x66,0x0b,0x85,0x00,0x0f,0x0b,0x88,0x0b,0x95,0x00,0x2f,0x0b,0x97,0x0b,0x9a, 0x00,0x3d,0x0b,0x9d,0x0b,0xb7,0x00,0x41,0x0b,0xb9,0x0b,0xb9,0x00,0x5c,0x0b,0xbf,0x0b,0xdd,0x00,0x5d,0x0b,0xe1,0x0b,0xe1,0x00,0x7c,0x12,0x5c,0x12,0x62,0x00,0x7d,0x00,0x02,0x00,0x09,0x0b,0x6a,0x0b,0x6a,0x00,0x00,0x0b,0x6d,0x0b,0x6e,0x00,0x01,0x0b,0x71,0x0b,0x71,0x00,0x03,0x0b,0x77,0x0b,0x78,0x00,0x04,0x0b,0x9f,0x0b,0x9f, 0x00,0x06,0x0b,0xa2,0x0b,0xa3,0x00,0x07,0x0b,0xa5,0x0b,0xa5,0x00,0x09,0x0b,0xaa,0x0b,0xaa,0x00,0x0a,0x12,0x5f,0x12,0x5f,0x00,0x0b,0x00,0x02,0x00,0x0a,0x0b,0x53,0x0b,0x5b,0x00,0x00,0x0b,0x5d,0x0b,0x5d,0x00,0x09,0x0b,0x5f,0x0b,0x5f,0x00,0x0a,0x0b,0x67,0x0b,0x67,0x00,0x0b,0x0b,0xb9,0x0b,0xb9,0x00,0x0c,0x0b,0xbf,0x0b,0xbf, 0x00,0x0d,0x0b,0xc4,0x0b,0xc4,0x00,0x0e,0x0b,0xc9,0x0b,0xc9,0x00,0x0f,0x0b,0xd0,0x0b,0xd5,0x00,0x10,0x0b,0xd8,0x0b,0xd8,0x00,0x16,0x00,0x01,0x00,0x01,0x0b,0xdb,0x00,0x01,0x00,0x01,0x0b,0xc8,0x00,0x01,0x00,0x01,0x12,0x5b,0x00,0x01,0x00,0x01,0x12,0x59,0x00,0x01,0x00,0x01,0x12,0x5a,0x00,0x01,0x00,0x01,0x0b,0x5f,0x00,0x01, 0x00,0x01,0x0b,0x55,0x00,0x01,0x00,0x01,0x0b,0x54,0x00,0x01,0x00,0x01,0x0b,0x56,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x2a,0x00,0x30,0x00,0x36,0x00,0x3c,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x16,0x00,0x1c,0x00,0x22,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7d,0x00,0x01,0x00,0x01,0x08,0xef, 0x00,0x01,0x00,0x01,0x0e,0x2d,0x00,0x01,0x00,0x01,0x0e,0x58,0x00,0x01,0x00,0x01,0x0e,0x2f,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14, 0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a, 0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x12,0x00,0x62,0x00,0x68,0x00,0x6e,0x00,0x76,0x00,0x7c,0x00,0x82,0x00,0x68,0x00,0x88,0x00,0x76,0x00,0x90,0x00,0x68,0x00,0x96,0x00,0x9c,0x00,0x76,0x00,0xa2,0x00,0xa8,0x00,0x68,0x00,0xae,0x00,0x01,0x00,0xb4,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x12,0x00,0x32, 0x00,0x38,0x00,0x3e,0x00,0x46,0x00,0x4c,0x00,0x52,0x00,0x38,0x00,0x58,0x00,0x46,0x00,0x60,0x00,0x38,0x00,0x66,0x00,0x6c,0x00,0x46,0x00,0x72,0x00,0x78,0x00,0x38,0x00,0x7e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7e,0x00,0x01,0x00,0x01,0x08,0xd6,0x00,0x01,0x00,0x01,0x09,0x3f,0x00,0x01,0x00,0x02,0x08,0xf7,0x09,0x4b,0x00,0x01, 0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x09,0x0d,0x00,0x01,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x02,0x08,0xf3,0x09,0x60,0x00,0x01,0x00,0x01,0x08,0xe2,0x00,0x01,0x00,0x01,0x0e,0x61,0x00,0x01,0x00,0x01,0x08,0xf3,0x00,0x01,0x00,0x01,0x09,0x29,0x00,0x01,0x00,0x01,0x08,0xd4,0x00,0x01,0x00,0x01,0x0e,0x57,0x00,0x02,0x00,0x13, 0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69, 0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x0f,0x00,0x56,0x00,0x5c,0x00,0x62,0x00,0x6a, 0x00,0x70,0x00,0x6a,0x00,0x76,0x00,0x5c,0x00,0x7c,0x00,0x82,0x00,0x6a,0x00,0x8a,0x00,0x90,0x00,0x5c,0x00,0x96,0x00,0x01,0x00,0x9c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0f,0x00,0x2c,0x00,0x32,0x00,0x38,0x00,0x40,0x00,0x46,0x00,0x40,0x00,0x4c,0x00,0x32,0x00,0x52,0x00,0x58,0x00,0x40,0x00,0x60,0x00,0x66,0x00,0x32,0x00,0x6c, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7f,0x00,0x01,0x00,0x01,0x08,0xd6,0x00,0x01,0x00,0x01,0x09,0x3f,0x00,0x01,0x00,0x02,0x08,0xf7,0x09,0x4b,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x0a,0x63,0x00,0x01,0x00,0x01,0x08,0xe2,0x00,0x01,0x00,0x01,0x0e,0x61,0x00,0x01,0x00,0x02,0x08,0xf3,0x09,0x60,0x00,0x01,0x00,0x01, 0x09,0x29,0x00,0x01,0x00,0x01,0x08,0xd4,0x00,0x01,0x00,0x01,0x0e,0x57,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f, 0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c, 0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x3a,0x00,0x40,0x00,0x46,0x00,0x3a,0x00,0x4c,0x00,0x52,0x00,0x58,0x00,0x5e,0x00,0x01,0x00,0x66,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x1e,0x00,0x24,0x00,0x2a,0x00,0x1e,0x00,0x30,0x00,0x36,0x00,0x3c,0x00,0x42,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x80,0x00,0x01, 0x00,0x01,0x08,0xce,0x00,0x01,0x00,0x01,0x09,0x59,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x09,0x3f,0x00,0x01,0x00,0x01,0x08,0xc7,0x00,0x01,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x02,0x08,0xf3,0x09,0x60,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09, 0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c, 0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x36,0x00,0x3c,0x00,0x42,0x00,0x36,0x00,0x48,0x00,0x4e,0x00,0x54,0x00,0x01,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07, 0x00,0x1c,0x00,0x22,0x00,0x28,0x00,0x1c,0x00,0x2e,0x00,0x34,0x00,0x3a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x81,0x00,0x01,0x00,0x01,0x08,0xce,0x00,0x01,0x00,0x01,0x09,0x59,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x08,0xfb,0x00,0x01,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x02,0x08,0xf3,0x09,0x60,0x00,0x02,0x00,0x13, 0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69, 0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x72,0x00,0x78,0x00,0x7e,0x00,0x84, 0x00,0x8a,0x00,0x90,0x00,0x96,0x00,0x9c,0x00,0x84,0x00,0x8a,0x00,0x90,0x00,0xa2,0x00,0xa8,0x00,0xae,0x00,0xb4,0x00,0x84,0x00,0x8a,0x00,0x90,0x00,0xa2,0x00,0xa8,0x00,0xba,0x00,0x7e,0x00,0x01,0x00,0xc0,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x3a,0x00,0x40,0x00,0x46,0x00,0x4c,0x00,0x52,0x00,0x58,0x00,0x5e,0x00,0x64, 0x00,0x4c,0x00,0x52,0x00,0x58,0x00,0x6a,0x00,0x70,0x00,0x76,0x00,0x7c,0x00,0x4c,0x00,0x52,0x00,0x58,0x00,0x6a,0x00,0x70,0x00,0x82,0x00,0x46,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x82,0x00,0x01,0x00,0x01,0x08,0xcb,0x00,0x01,0x00,0x01,0x0e,0x32,0x00,0x01,0x00,0x01,0x0e,0x57,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01, 0x09,0x0d,0x00,0x01,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x01,0x09,0x3f,0x00,0x01,0x00,0x01,0x08,0xf3,0x00,0x01,0x00,0x01,0x0b,0x0c,0x00,0x01,0x00,0x01,0x08,0xd0,0x00,0x01,0x00,0x01,0x0e,0x58,0x00,0x01,0x00,0x01,0x0e,0x59,0x00,0x01,0x00,0x01,0x0e,0x61,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37, 0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16,0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a, 0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f,0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x03,0x00,0x00,0x00,0x13,0x00,0x66,0x00,0x6c,0x00,0x72,0x00,0x78,0x00,0x7e,0x00,0x78,0x00,0x84,0x00,0x8a,0x00,0x90, 0x00,0x96,0x00,0x9c,0x00,0xa2,0x00,0x78,0x00,0x84,0x00,0x8a,0x00,0x90,0x00,0x96,0x00,0xa8,0x00,0x72,0x00,0x01,0x00,0xae,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x13,0x00,0x34,0x00,0x3a,0x00,0x40,0x00,0x46,0x00,0x4c,0x00,0x46,0x00,0x52,0x00,0x58,0x00,0x5e,0x00,0x64,0x00,0x6a,0x00,0x70,0x00,0x46,0x00,0x52,0x00,0x58,0x00,0x5e, 0x00,0x64,0x00,0x76,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x83,0x00,0x01,0x00,0x01,0x08,0xcb,0x00,0x01,0x00,0x01,0x0e,0x32,0x00,0x01,0x00,0x01,0x0e,0x57,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x01,0x0a,0x63,0x00,0x01,0x00,0x01,0x09,0x0d,0x00,0x01,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x01,0x0b,0x0c,0x00,0x01, 0x00,0x01,0x08,0xd0,0x00,0x01,0x00,0x01,0x0e,0x58,0x00,0x01,0x00,0x01,0x0e,0x59,0x00,0x01,0x00,0x01,0x0e,0x61,0x00,0x02,0x00,0x13,0x09,0x2c,0x09,0x33,0x00,0x00,0x09,0x37,0x09,0x37,0x00,0x08,0x09,0x73,0x09,0x75,0x00,0x09,0x09,0x77,0x09,0x77,0x00,0x0c,0x09,0x7e,0x09,0x7f,0x00,0x0d,0x0a,0x0f,0x0a,0x13,0x00,0x0f,0x0a,0x16, 0x0a,0x1b,0x00,0x14,0x0a,0x1e,0x0a,0x1f,0x00,0x1a,0x0a,0x21,0x0a,0x23,0x00,0x1c,0x0a,0x4b,0x0a,0x53,0x00,0x1f,0x0a,0x65,0x0a,0x69,0x00,0x28,0x0a,0x6c,0x0a,0x71,0x00,0x2d,0x0e,0x1a,0x0e,0x1e,0x00,0x33,0x0e,0x62,0x0e,0x6c,0x00,0x38,0x13,0x2a,0x13,0x44,0x00,0x43,0x13,0xe9,0x13,0xe9,0x00,0x5e,0x14,0x17,0x14,0x17,0x00,0x5f, 0x14,0x5d,0x14,0x6a,0x00,0x60,0x14,0x6c,0x14,0x6c,0x00,0x6e,0x00,0x02,0x00,0x08,0x00,0x01,0x0e,0x5c,0x00,0x01,0x00,0x01,0x09,0x28,0x00,0x02,0x00,0x32,0x00,0x16,0x14,0x88,0x14,0x89,0x14,0x8a,0x14,0x8b,0x14,0x8c,0x14,0x8d,0x14,0x8e,0x14,0x8f,0x14,0x90,0x14,0x91,0x14,0x88,0x14,0x89,0x14,0x8a,0x14,0x8b,0x14,0x92,0x14,0x93, 0x14,0x94,0x14,0x8f,0x14,0x90,0x14,0x91,0x14,0x95,0x14,0x96,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x02,0x00,0x32,0x00,0x16,0x14,0x9e,0x14,0x9f,0x14,0xa0,0x14,0xa1,0x14,0xa2,0x14,0xa3,0x14,0xa4,0x14,0xa5,0x14,0xa6,0x14,0xa7,0x14,0x9e,0x14,0x9f, 0x14,0xa0,0x14,0xa1,0x14,0xa8,0x14,0xa9,0x14,0xaa,0x14,0xa5,0x14,0xa6,0x14,0xa7,0x14,0xab,0x14,0xac,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x01,0x00,0xb6,0x00,0x16,0x00,0x32,0x00,0x38,0x00,0x3e,0x00,0x44,0x00,0x4a,0x00,0x50,0x00,0x56,0x00,0x5c, 0x00,0x62,0x00,0x68,0x00,0x6e,0x00,0x74,0x00,0x7a,0x00,0x80,0x00,0x86,0x00,0x8c,0x00,0x92,0x00,0x98,0x00,0x9e,0x00,0xa4,0x00,0xaa,0x00,0xb0,0x00,0x02,0x14,0x9a,0x14,0x9e,0x00,0x02,0x14,0x9a,0x14,0x9f,0x00,0x02,0x14,0x9a,0x14,0xa0,0x00,0x02,0x14,0x9a,0x14,0xa1,0x00,0x02,0x14,0x9a,0x14,0xa2,0x00,0x02,0x14,0x9a,0x14,0xa3, 0x00,0x02,0x14,0x9a,0x14,0xa4,0x00,0x02,0x14,0x9a,0x14,0xa5,0x00,0x02,0x14,0x9a,0x14,0xa6,0x00,0x02,0x14,0x9a,0x14,0xa7,0x00,0x02,0x14,0x9a,0x14,0x9e,0x00,0x02,0x14,0x9a,0x14,0x9f,0x00,0x02,0x14,0x9a,0x14,0xa0,0x00,0x02,0x14,0x9a,0x14,0xa1,0x00,0x02,0x14,0x9a,0x14,0xa8,0x00,0x02,0x14,0x9a,0x14,0xa9,0x00,0x02,0x14,0x9a, 0x14,0xaa,0x00,0x02,0x14,0x9a,0x14,0xa5,0x00,0x02,0x14,0x9a,0x14,0xa6,0x00,0x02,0x14,0x9a,0x14,0xa7,0x00,0x02,0x14,0x9a,0x14,0xab,0x00,0x02,0x14,0x9a,0x14,0xac,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x01,0x00,0xb6,0x00,0x16,0x00,0x32,0x00,0x38, 0x00,0x3e,0x00,0x44,0x00,0x4a,0x00,0x50,0x00,0x56,0x00,0x5c,0x00,0x62,0x00,0x68,0x00,0x6e,0x00,0x74,0x00,0x7a,0x00,0x80,0x00,0x86,0x00,0x8c,0x00,0x92,0x00,0x98,0x00,0x9e,0x00,0xa4,0x00,0xaa,0x00,0xb0,0x00,0x02,0x14,0x9a,0x14,0x9e,0x00,0x02,0x14,0x9a,0x14,0x9f,0x00,0x02,0x14,0x9a,0x14,0xa0,0x00,0x02,0x14,0x9a,0x14,0xa1, 0x00,0x02,0x14,0x9a,0x14,0xa2,0x00,0x02,0x14,0x9a,0x14,0xa3,0x00,0x02,0x14,0x9a,0x14,0xa4,0x00,0x02,0x14,0x9a,0x14,0xa5,0x00,0x02,0x14,0x9a,0x14,0xa6,0x00,0x02,0x14,0x9a,0x14,0xa7,0x00,0x02,0x14,0x9a,0x14,0x9e,0x00,0x02,0x14,0x9a,0x14,0x9f,0x00,0x02,0x14,0x9a,0x14,0xa0,0x00,0x02,0x14,0x9a,0x14,0xa1,0x00,0x02,0x14,0x9a, 0x14,0xa8,0x00,0x02,0x14,0x9a,0x14,0xa9,0x00,0x02,0x14,0x9a,0x14,0xaa,0x00,0x02,0x14,0x9a,0x14,0xa5,0x00,0x02,0x14,0x9a,0x14,0xa6,0x00,0x02,0x14,0x9a,0x14,0xa7,0x00,0x02,0x14,0x9a,0x14,0xab,0x00,0x02,0x14,0x9a,0x14,0xac,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0,0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d, 0x00,0x14,0x00,0x01,0x00,0xb6,0x00,0x16,0x00,0x32,0x00,0x38,0x00,0x3e,0x00,0x44,0x00,0x4a,0x00,0x50,0x00,0x56,0x00,0x5c,0x00,0x62,0x00,0x68,0x00,0x6e,0x00,0x74,0x00,0x7a,0x00,0x80,0x00,0x86,0x00,0x8c,0x00,0x92,0x00,0x98,0x00,0x9e,0x00,0xa4,0x00,0xaa,0x00,0xb0,0x00,0x02,0x14,0x2b,0x08,0xd7,0x00,0x02,0x14,0x2b,0x08,0xd8, 0x00,0x02,0x14,0x2b,0x08,0xd9,0x00,0x02,0x14,0x2b,0x08,0xda,0x00,0x02,0x14,0x2b,0x08,0xdb,0x00,0x02,0x14,0x2b,0x08,0xdc,0x00,0x02,0x14,0x2b,0x08,0xdd,0x00,0x02,0x14,0x2b,0x08,0xde,0x00,0x02,0x14,0x2b,0x08,0xdf,0x00,0x02,0x14,0x2b,0x08,0xe0,0x00,0x02,0x14,0x2b,0x08,0xd7,0x00,0x02,0x14,0x2b,0x08,0xd8,0x00,0x02,0x14,0x2b, 0x08,0xd9,0x00,0x02,0x14,0x2b,0x08,0xda,0x00,0x02,0x14,0x2b,0x09,0x53,0x00,0x02,0x14,0x2b,0x09,0x54,0x00,0x02,0x14,0x2b,0x09,0x55,0x00,0x02,0x14,0x2b,0x08,0xde,0x00,0x02,0x14,0x2b,0x08,0xdf,0x00,0x02,0x14,0x2b,0x08,0xe0,0x00,0x02,0x14,0x2b,0x0a,0x3c,0x00,0x02,0x14,0x2b,0x0a,0x3d,0x00,0x02,0x00,0x03,0x08,0xd7,0x08,0xe0, 0x00,0x00,0x09,0x4f,0x09,0x58,0x00,0x0a,0x0a,0x3c,0x0a,0x3d,0x00,0x14,0x00,0x01,0x00,0x1e,0x00,0x03,0x00,0x0c,0x00,0x12,0x00,0x18,0x00,0x02,0x14,0x99,0x0a,0x44,0x00,0x02,0x14,0x9c,0x0a,0x47,0x00,0x02,0x14,0x9d,0x13,0x45,0x00,0x02,0x00,0x03,0x0a,0x44,0x0a,0x44,0x00,0x00,0x0a,0x47,0x0a,0x47,0x00,0x01,0x13,0x45,0x13,0x45, 0x00,0x02,0x00,0x02,0x00,0x1e,0x00,0x0c,0x0f,0x8c,0x0f,0x8d,0x0f,0x8e,0x0f,0x90,0x0f,0x92,0x0f,0x94,0x0f,0x8f,0x0f,0x91,0x0f,0x93,0x0f,0x95,0x0f,0x96,0x0f,0x97,0x00,0x02,0x00,0x08,0x08,0xee,0x08,0xee,0x00,0x00,0x09,0x3f,0x09,0x3f,0x00,0x01,0x09,0xec,0x09,0xec,0x00,0x02,0x09,0xee,0x09,0xee,0x00,0x03,0x09,0xf0,0x09,0xf0, 0x00,0x04,0x09,0xf2,0x09,0xf2,0x00,0x05,0x0a,0x5f,0x0a,0x62,0x00,0x06,0x0a,0xb2,0x0a,0xb3,0x00,0x0a,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0f,0x65,0x0f,0x63,0x0f,0x62,0x0f,0x64,0x0f,0x66,0x0f,0x67,0x0f,0x68,0x0f,0x69,0x0f,0x6a,0x0f,0x6b,0x00,0x02,0x00,0x07,0x08,0xc7,0x08,0xca,0x00,0x00,0x09,0x81,0x09,0x81,0x00,0x04,0x09,0x83, 0x09,0x83,0x00,0x05,0x09,0x85,0x09,0x85,0x00,0x06,0x09,0x87,0x09,0x87,0x00,0x07,0x0f,0x29,0x0f,0x29,0x00,0x08,0x0f,0x2b,0x0f,0x2b,0x00,0x09,0x00,0x02,0x00,0x46,0x00,0x20,0x0f,0x6c,0x0f,0x6e,0x0f,0x82,0x0f,0x84,0x0f,0x70,0x0f,0x72,0x0f,0x74,0x0f,0x86,0x0f,0x88,0x0f,0x76,0x0f,0x8a,0x0f,0x78,0x0f,0x7a,0x0f,0x6d,0x0f,0x6f, 0x0f,0x83,0x0f,0x85,0x0f,0x71,0x0f,0x73,0x0f,0x75,0x0f,0x87,0x0f,0x89,0x0f,0x77,0x0f,0x8b,0x0f,0x79,0x0f,0x7b,0x0f,0x7c,0x0f,0x7d,0x0f,0x7e,0x0f,0x7f,0x0f,0x80,0x0f,0x81,0x00,0x02,0x00,0x1b,0x08,0xd4,0x08,0xd6,0x00,0x00,0x08,0xe1,0x08,0xe1,0x00,0x03,0x09,0xba,0x09,0xba,0x00,0x04,0x09,0xbc,0x09,0xbc,0x00,0x05,0x09,0xbe, 0x09,0xbe,0x00,0x06,0x09,0xc0,0x09,0xc0,0x00,0x07,0x09,0xc2,0x09,0xc2,0x00,0x08,0x0a,0x25,0x0a,0x25,0x00,0x09,0x0a,0x27,0x0a,0x27,0x00,0x0a,0x0a,0x8a,0x0a,0x8a,0x00,0x0b,0x0a,0xb7,0x0a,0xb7,0x00,0x0c,0x0e,0x32,0x0e,0x32,0x00,0x0d,0x0e,0x34,0x0e,0x34,0x00,0x0e,0x0e,0x36,0x0e,0x36,0x00,0x0f,0x0e,0x38,0x0e,0x38,0x00,0x10, 0x0e,0x99,0x0e,0x99,0x00,0x11,0x0e,0x9b,0x0e,0x9b,0x00,0x12,0x0e,0x9d,0x0e,0x9d,0x00,0x13,0x0e,0x9f,0x0e,0x9f,0x00,0x14,0x0e,0xa1,0x0e,0xa1,0x00,0x15,0x0e,0xed,0x0e,0xed,0x00,0x16,0x0e,0xef,0x0e,0xef,0x00,0x17,0x0f,0x04,0x0f,0x04,0x00,0x18,0x0f,0x15,0x0f,0x15,0x00,0x19,0x0f,0x20,0x0f,0x21,0x00,0x1a,0x0f,0x46,0x0f,0x47, 0x00,0x1c,0x0f,0x4a,0x0f,0x4b,0x00,0x1e,0x00,0x02,0x00,0x4a,0x00,0x22,0x0f,0xac,0x0f,0xab,0x0f,0xa7,0x0f,0xbd,0x0f,0xad,0x0f,0xae,0x0f,0xaf,0x0f,0xbe,0x0f,0xb0,0x0f,0xa2,0x0f,0xa5,0x0f,0x98,0x0f,0x99,0x0f,0xc3,0x0f,0x9a,0x0f,0x9b,0x0f,0x9c,0x0f,0x9d,0x0f,0x9e,0x0f,0x9f,0x0f,0xa0,0x0f,0xa1,0x0f,0xa4,0x0f,0xbf,0x0f,0xa8, 0x0f,0xa9,0x0f,0xaa,0x0f,0xa3,0x0f,0xa6,0x0f,0xb1,0x0f,0xb2,0x0f,0xb3,0x14,0xad,0x14,0xae,0x00,0x02,0x00,0x16,0x08,0xf5,0x08,0xf5,0x00,0x00,0x08,0xf7,0x08,0xf7,0x00,0x01,0x09,0x02,0x09,0x02,0x00,0x02,0x09,0x4b,0x09,0x4b,0x00,0x03,0x09,0x8b,0x09,0x8b,0x00,0x04,0x0a,0x06,0x0a,0x06,0x00,0x05,0x0a,0x08,0x0a,0x08,0x00,0x06, 0x0a,0x0c,0x0a,0x0c,0x00,0x07,0x0a,0x0e,0x0a,0x0e,0x00,0x08,0x0a,0x57,0x0a,0x57,0x00,0x09,0x0a,0xb5,0x0a,0xb5,0x00,0x0a,0x0b,0x0c,0x0b,0x17,0x00,0x0b,0x0e,0x21,0x0e,0x21,0x00,0x17,0x0e,0x48,0x0e,0x48,0x00,0x18,0x0e,0x4c,0x0e,0x4c,0x00,0x19,0x0e,0x50,0x0e,0x50,0x00,0x1a,0x0f,0x02,0x0f,0x02,0x00,0x1b,0x0f,0x23,0x0f,0x23, 0x00,0x1c,0x0f,0x2d,0x0f,0x2d,0x00,0x1d,0x0f,0x31,0x0f,0x31,0x00,0x1e,0x0f,0x35,0x0f,0x35,0x00,0x1f,0x14,0x7d,0x14,0x7e,0x00,0x20,0x00,0x02,0x00,0x0e,0x00,0x04,0x0f,0xb6,0x0f,0xb8,0x0f,0xba,0x0f,0xbc,0x00,0x02,0x00,0x04,0x09,0x66,0x09,0x66,0x00,0x00,0x09,0x68,0x09,0x68,0x00,0x01,0x0f,0x3d,0x0f,0x3d,0x00,0x02,0x0f,0x3f, 0x0f,0x3f,0x00,0x03,0x00,0x02,0x00,0x0e,0x00,0x04,0x0f,0xb5,0x0f,0xb7,0x0f,0xb9,0x0f,0xbb,0x00,0x02,0x00,0x04,0x09,0x66,0x09,0x66,0x00,0x00,0x09,0x68,0x09,0x68,0x00,0x01,0x0f,0x3d,0x0f,0x3d,0x00,0x02,0x0f,0x3f,0x0f,0x3f,0x00,0x03,0x00,0x02,0x00,0x0e,0x00,0x04,0x00,0xd6,0x06,0xac,0x11,0x8c,0x06,0xad,0x00,0x02,0x00,0x03, 0x00,0x4c,0x00,0x4d,0x00,0x00,0x01,0x62,0x01,0x62,0x00,0x02,0x05,0x6d,0x05,0x6d,0x00,0x03,0x00,0x02,0x00,0x1a,0x00,0x0a,0x0c,0xe1,0x0c,0xe2,0x0c,0xe3,0x0c,0xe4,0x0c,0xe5,0x0c,0xe6,0x0c,0xe7,0x0c,0xe8,0x0c,0xe9,0x0c,0xea,0x00,0x02,0x00,0x01,0x00,0x13,0x00,0x1c,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x01,0x0b,0x8d,0x00,0x01, 0x00,0x01,0x0b,0x7a,0x00,0x02,0x00,0x08,0x00,0x01,0x0b,0xd6,0x00,0x01,0x00,0x01,0x0b,0xc7,0x00,0x02,0x00,0x08,0x00,0x01,0x0a,0x43,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x1e,0x00,0x02,0x00,0x0a,0x00,0x14,0x00,0x01,0x00,0x04,0x0b,0x8a,0x00,0x02,0x0b,0x5c,0x00,0x01,0x00,0x04,0x0b,0x8b,0x00,0x02,0x0b,0x5c,0x00,0x01, 0x00,0x02,0x0b,0x74,0x0b,0xa8,0x00,0x01,0x00,0x12,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x0b,0x57,0x00,0x02,0x0b,0x57,0x00,0x01,0x00,0x01,0x0a,0x43,0x00,0x01,0x00,0x66,0x00,0x0c,0x00,0x1e,0x00,0x24,0x00,0x2a,0x00,0x30,0x00,0x36,0x00,0x3c,0x00,0x42,0x00,0x48,0x00,0x4e,0x00,0x54,0x00,0x5a,0x00,0x60,0x00,0x02,0x0b,0x5f, 0x0b,0x07,0x00,0x02,0x0b,0x67,0x0b,0x07,0x00,0x02,0x0b,0xbf,0x0b,0x07,0x00,0x02,0x0b,0xc4,0x0b,0x07,0x00,0x02,0x0b,0xc9,0x0b,0x07,0x00,0x02,0x0b,0xd0,0x0b,0x07,0x00,0x02,0x0b,0xd1,0x0b,0x07,0x00,0x02,0x0b,0xd2,0x0b,0x07,0x00,0x02,0x0b,0xd3,0x0b,0x07,0x00,0x02,0x0b,0xd4,0x0b,0x07,0x00,0x02,0x0b,0xd5,0x0b,0x07,0x00,0x02, 0x0b,0xd8,0x0b,0x07,0x00,0x02,0x00,0x07,0x0b,0x5f,0x0b,0x5f,0x00,0x00,0x0b,0x67,0x0b,0x67,0x00,0x01,0x0b,0xbf,0x0b,0xbf,0x00,0x02,0x0b,0xc4,0x0b,0xc4,0x00,0x03,0x0b,0xc9,0x0b,0xc9,0x00,0x04,0x0b,0xd0,0x0b,0xd5,0x00,0x05,0x0b,0xd8,0x0b,0xd8,0x00,0x0b,0x00,0x01,0x00,0x76,0x00,0x0e,0x00,0x22,0x00,0x28,0x00,0x2e,0x00,0x34, 0x00,0x3a,0x00,0x40,0x00,0x46,0x00,0x4c,0x00,0x52,0x00,0x58,0x00,0x5e,0x00,0x64,0x00,0x6a,0x00,0x70,0x00,0x02,0x0b,0x53,0x11,0x86,0x00,0x02,0x0b,0x5a,0x11,0x86,0x00,0x02,0x0b,0x5f,0x11,0x86,0x00,0x02,0x0b,0x67,0x11,0x86,0x00,0x02,0x0b,0xbf,0x11,0x86,0x00,0x02,0x0b,0xc4,0x11,0x86,0x00,0x02,0x0b,0xc9,0x11,0x86,0x00,0x02, 0x0b,0xd0,0x11,0x86,0x00,0x02,0x0b,0xd1,0x11,0x86,0x00,0x02,0x0b,0xd2,0x11,0x86,0x00,0x02,0x0b,0xd3,0x11,0x86,0x00,0x02,0x0b,0xd4,0x11,0x86,0x00,0x02,0x0b,0xd5,0x11,0x86,0x00,0x02,0x0b,0xd8,0x11,0x86,0x00,0x02,0x00,0x09,0x0b,0x53,0x0b,0x53,0x00,0x00,0x0b,0x5a,0x0b,0x5a,0x00,0x01,0x0b,0x5f,0x0b,0x5f,0x00,0x02,0x0b,0x67, 0x0b,0x67,0x00,0x03,0x0b,0xbf,0x0b,0xbf,0x00,0x04,0x0b,0xc4,0x0b,0xc4,0x00,0x05,0x0b,0xc9,0x0b,0xc9,0x00,0x06,0x0b,0xd0,0x0b,0xd5,0x00,0x07,0x0b,0xd8,0x0b,0xd8,0x00,0x0d,0x00,0x01,0x04,0x26,0x00,0x84,0x01,0x0e,0x01,0x14,0x01,0x1a,0x01,0x20,0x01,0x26,0x01,0x2c,0x01,0x32,0x01,0x38,0x01,0x3e,0x01,0x44,0x01,0x4a,0x01,0x50, 0x01,0x56,0x01,0x5c,0x01,0x62,0x01,0x68,0x01,0x6e,0x01,0x74,0x01,0x7a,0x01,0x80,0x01,0x86,0x01,0x8c,0x01,0x92,0x01,0x98,0x01,0x9e,0x01,0xa4,0x01,0xaa,0x01,0xb0,0x01,0xb6,0x01,0xbc,0x01,0xc2,0x01,0xc8,0x01,0xce,0x01,0xd4,0x01,0xda,0x01,0xe0,0x01,0xe6,0x01,0xec,0x01,0xf2,0x01,0xf8,0x01,0xfe,0x02,0x04,0x02,0x0a,0x02,0x10, 0x02,0x16,0x02,0x1c,0x02,0x22,0x02,0x28,0x02,0x2e,0x02,0x34,0x02,0x3a,0x02,0x40,0x02,0x46,0x02,0x4c,0x02,0x52,0x02,0x58,0x02,0x5e,0x02,0x64,0x02,0x6a,0x02,0x70,0x02,0x76,0x02,0x7c,0x02,0x82,0x02,0x88,0x02,0x8e,0x02,0x94,0x02,0x9a,0x02,0xa0,0x02,0xa6,0x02,0xac,0x02,0xb2,0x02,0xb8,0x02,0xbe,0x02,0xc4,0x02,0xca,0x02,0xd0, 0x02,0xd6,0x02,0xdc,0x02,0xe2,0x02,0xe8,0x02,0xee,0x02,0xf4,0x02,0xfa,0x03,0x00,0x03,0x06,0x03,0x0c,0x03,0x12,0x03,0x18,0x03,0x1e,0x03,0x24,0x03,0x2a,0x03,0x30,0x03,0x36,0x03,0x3c,0x03,0x42,0x03,0x48,0x03,0x4e,0x03,0x54,0x03,0x5a,0x03,0x60,0x03,0x66,0x03,0x6c,0x03,0x72,0x03,0x78,0x03,0x7e,0x03,0x84,0x03,0x8a,0x03,0x90, 0x03,0x96,0x03,0x9c,0x03,0xa2,0x03,0xa8,0x03,0xae,0x03,0xb4,0x03,0xba,0x03,0xc0,0x03,0xc6,0x03,0xcc,0x03,0xd2,0x03,0xd8,0x03,0xde,0x03,0xe4,0x03,0xea,0x03,0xf0,0x03,0xf6,0x03,0xfc,0x04,0x02,0x04,0x08,0x04,0x0e,0x04,0x14,0x04,0x1a,0x04,0x20,0x00,0x02,0x0a,0x43,0x11,0x86,0x00,0x02,0x0b,0x53,0x11,0x86,0x00,0x02,0x0b,0x54, 0x11,0x86,0x00,0x02,0x0b,0x55,0x11,0x86,0x00,0x02,0x0b,0x56,0x11,0x86,0x00,0x02,0x0b,0x57,0x11,0x86,0x00,0x02,0x0b,0x58,0x11,0x86,0x00,0x02,0x0b,0x59,0x11,0x86,0x00,0x02,0x0b,0x5a,0x11,0x86,0x00,0x02,0x0b,0x5b,0x11,0x86,0x00,0x02,0x0b,0x5c,0x11,0x86,0x00,0x02,0x0b,0x5d,0x11,0x86,0x00,0x02,0x0b,0x5e,0x11,0x86,0x00,0x02, 0x0b,0x5f,0x11,0x86,0x00,0x02,0x0b,0x61,0x11,0x86,0x00,0x02,0x0b,0x66,0x11,0x86,0x00,0x02,0x0b,0x67,0x11,0x86,0x00,0x02,0x0b,0x68,0x11,0x86,0x00,0x02,0x0b,0x69,0x11,0x86,0x00,0x02,0x0b,0x6a,0x11,0x86,0x00,0x02,0x0b,0x6b,0x11,0x86,0x00,0x02,0x0b,0x6c,0x11,0x86,0x00,0x02,0x0b,0x6d,0x11,0x86,0x00,0x02,0x0b,0x6e,0x11,0x86, 0x00,0x02,0x0b,0x6f,0x11,0x86,0x00,0x02,0x0b,0x70,0x11,0x86,0x00,0x02,0x0b,0x71,0x11,0x86,0x00,0x02,0x0b,0x72,0x11,0x86,0x00,0x02,0x0b,0x73,0x11,0x86,0x00,0x02,0x0b,0x74,0x11,0x86,0x00,0x02,0x0b,0x75,0x11,0x86,0x00,0x02,0x0b,0x76,0x11,0x86,0x00,0x02,0x0b,0x77,0x11,0x86,0x00,0x02,0x0b,0x78,0x11,0x86,0x00,0x02,0x0b,0x79, 0x11,0x86,0x00,0x02,0x0b,0x7a,0x11,0x86,0x00,0x02,0x0b,0x7b,0x11,0x86,0x00,0x02,0x0b,0x7c,0x11,0x86,0x00,0x02,0x0b,0x7d,0x11,0x86,0x00,0x02,0x0b,0x7e,0x11,0x86,0x00,0x02,0x0b,0x7f,0x11,0x86,0x00,0x02,0x0b,0x80,0x11,0x86,0x00,0x02,0x0b,0x81,0x11,0x86,0x00,0x02,0x0b,0x82,0x11,0x86,0x00,0x02,0x0b,0x83,0x11,0x86,0x00,0x02, 0x0b,0x84,0x11,0x86,0x00,0x02,0x0b,0x85,0x11,0x86,0x00,0x02,0x0b,0x88,0x11,0x86,0x00,0x02,0x0b,0x89,0x11,0x86,0x00,0x02,0x0b,0x8a,0x11,0x86,0x00,0x02,0x0b,0x8b,0x11,0x86,0x00,0x02,0x0b,0x8c,0x11,0x86,0x00,0x02,0x0b,0x8d,0x11,0x86,0x00,0x02,0x0b,0x8e,0x11,0x86,0x00,0x02,0x0b,0x8f,0x11,0x86,0x00,0x02,0x0b,0x90,0x11,0x86, 0x00,0x02,0x0b,0x91,0x11,0x86,0x00,0x02,0x0b,0x92,0x11,0x86,0x00,0x02,0x0b,0x93,0x11,0x86,0x00,0x02,0x0b,0x94,0x11,0x86,0x00,0x02,0x0b,0x95,0x11,0x86,0x00,0x02,0x0b,0x97,0x11,0x86,0x00,0x02,0x0b,0x98,0x11,0x86,0x00,0x02,0x0b,0x99,0x11,0x86,0x00,0x02,0x0b,0x9a,0x11,0x86,0x00,0x02,0x0b,0x9d,0x11,0x86,0x00,0x02,0x0b,0x9e, 0x11,0x86,0x00,0x02,0x0b,0x9f,0x11,0x86,0x00,0x02,0x0b,0xa0,0x11,0x86,0x00,0x02,0x0b,0xa1,0x11,0x86,0x00,0x02,0x0b,0xa2,0x11,0x86,0x00,0x02,0x0b,0xa3,0x11,0x86,0x00,0x02,0x0b,0xa4,0x11,0x86,0x00,0x02,0x0b,0xa5,0x11,0x86,0x00,0x02,0x0b,0xa6,0x11,0x86,0x00,0x02,0x0b,0xa7,0x11,0x86,0x00,0x02,0x0b,0xa8,0x11,0x86,0x00,0x02, 0x0b,0xa9,0x11,0x86,0x00,0x02,0x0b,0xaa,0x11,0x86,0x00,0x02,0x0b,0xab,0x11,0x86,0x00,0x02,0x0b,0xac,0x11,0x86,0x00,0x02,0x0b,0xad,0x11,0x86,0x00,0x02,0x0b,0xae,0x11,0x86,0x00,0x02,0x0b,0xaf,0x11,0x86,0x00,0x02,0x0b,0xb0,0x11,0x86,0x00,0x02,0x0b,0xb1,0x11,0x86,0x00,0x02,0x0b,0xb2,0x11,0x86,0x00,0x02,0x0b,0xb3,0x11,0x86, 0x00,0x02,0x0b,0xb4,0x11,0x86,0x00,0x02,0x0b,0xb5,0x11,0x86,0x00,0x02,0x0b,0xb6,0x11,0x86,0x00,0x02,0x0b,0xb7,0x11,0x86,0x00,0x02,0x0b,0xb9,0x11,0x86,0x00,0x02,0x0b,0xbf,0x11,0x86,0x00,0x02,0x0b,0xc0,0x11,0x86,0x00,0x02,0x0b,0xc1,0x11,0x86,0x00,0x02,0x0b,0xc2,0x11,0x86,0x00,0x02,0x0b,0xc3,0x11,0x86,0x00,0x02,0x0b,0xc4, 0x11,0x86,0x00,0x02,0x0b,0xc5,0x11,0x86,0x00,0x02,0x0b,0xc6,0x11,0x86,0x00,0x02,0x0b,0xc7,0x11,0x86,0x00,0x02,0x0b,0xc8,0x11,0x86,0x00,0x02,0x0b,0xc9,0x11,0x86,0x00,0x02,0x0b,0xca,0x11,0x86,0x00,0x02,0x0b,0xcb,0x11,0x86,0x00,0x02,0x0b,0xcc,0x11,0x86,0x00,0x02,0x0b,0xcd,0x11,0x86,0x00,0x02,0x0b,0xce,0x11,0x86,0x00,0x02, 0x0b,0xcf,0x11,0x86,0x00,0x02,0x0b,0xd0,0x11,0x86,0x00,0x02,0x0b,0xd1,0x11,0x86,0x00,0x02,0x0b,0xd2,0x11,0x86,0x00,0x02,0x0b,0xd3,0x11,0x86,0x00,0x02,0x0b,0xd4,0x11,0x86,0x00,0x02,0x0b,0xd5,0x11,0x86,0x00,0x02,0x0b,0xd6,0x11,0x86,0x00,0x02,0x0b,0xd7,0x11,0x86,0x00,0x02,0x0b,0xd8,0x11,0x86,0x00,0x02,0x0b,0xd9,0x11,0x86, 0x00,0x02,0x0b,0xda,0x11,0x86,0x00,0x02,0x0b,0xdb,0x11,0x86,0x00,0x02,0x0b,0xdc,0x11,0x86,0x00,0x02,0x0b,0xdd,0x11,0x86,0x00,0x02,0x0b,0xe1,0x11,0x86,0x00,0x02,0x12,0x5c,0x11,0x86,0x00,0x02,0x12,0x5d,0x11,0x86,0x00,0x02,0x12,0x5e,0x11,0x86,0x00,0x02,0x12,0x5f,0x11,0x86,0x00,0x02,0x12,0x60,0x11,0x86,0x00,0x02,0x12,0x61, 0x11,0x86,0x00,0x02,0x12,0x62,0x11,0x86,0x00,0x02,0x00,0x0b,0x0a,0x43,0x0a,0x43,0x00,0x00,0x0b,0x53,0x0b,0x5f,0x00,0x01,0x0b,0x61,0x0b,0x61,0x00,0x0e,0x0b,0x66,0x0b,0x85,0x00,0x0f,0x0b,0x88,0x0b,0x95,0x00,0x2f,0x0b,0x97,0x0b,0x9a,0x00,0x3d,0x0b,0x9d,0x0b,0xb7,0x00,0x41,0x0b,0xb9,0x0b,0xb9,0x00,0x5c,0x0b,0xbf,0x0b,0xdd, 0x00,0x5d,0x0b,0xe1,0x0b,0xe1,0x00,0x7c,0x12,0x5c,0x12,0x62,0x00,0x7d,0x00,0x01,0x00,0x16,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x13,0xef,0x00,0x04,0x0e,0x2d,0x0e,0x58,0x0e,0x2f,0x00,0x01,0x00,0x01,0x08,0xef,0x00,0x01,0x00,0x82,0x00,0x01,0x00,0x08,0x00,0x03,0x00,0x08,0x00,0x2e,0x00,0x54,0x13,0xf0,0x00,0x12,0x09,0x3f, 0x08,0xf7,0x00,0x03,0x09,0x0d,0x08,0xee,0x09,0x3f,0x08,0xf3,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x08,0xf3,0x00,0x03,0x09,0x29,0x08,0xd4,0x09,0x3f,0x0e,0x57,0x13,0xf0,0x00,0x12,0x09,0x3f,0x09,0x4b,0x00,0x03,0x09,0x0d,0x08,0xee,0x09,0x3f,0x08,0xf3,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x08,0xf3,0x00,0x03,0x09,0x29, 0x08,0xd4,0x09,0x3f,0x0e,0x57,0x13,0xf0,0x00,0x12,0x09,0x3f,0x09,0x4b,0x00,0x03,0x09,0x0d,0x08,0xee,0x09,0x3f,0x09,0x60,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x08,0xf3,0x00,0x03,0x09,0x29,0x08,0xd4,0x09,0x3f,0x0e,0x57,0x00,0x01,0x00,0x01,0x08,0xd6,0x00,0x01,0x00,0x70,0x00,0x01,0x00,0x08,0x00,0x03,0x00,0x08,0x00,0x28, 0x00,0x48,0x13,0xf0,0x00,0x0f,0x09,0x3f,0x08,0xf7,0x00,0x03,0x0a,0x63,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x08,0xf3,0x00,0x03,0x09,0x29,0x08,0xd4,0x09,0x3f,0x0e,0x57,0x13,0xf0,0x00,0x0f,0x09,0x3f,0x09,0x4b,0x00,0x03,0x0a,0x63,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x08,0xf3,0x00,0x03,0x09,0x29,0x08,0xd4,0x09,0x3f, 0x0e,0x57,0x13,0xf0,0x00,0x0f,0x09,0x3f,0x09,0x4b,0x00,0x03,0x0a,0x63,0x00,0x03,0x08,0xe2,0x09,0x3f,0x0e,0x61,0x09,0x60,0x00,0x03,0x09,0x29,0x08,0xd4,0x09,0x3f,0x0e,0x57,0x00,0x01,0x00,0x01,0x08,0xd6,0x00,0x01,0x00,0x32,0x00,0x01,0x00,0x08,0x00,0x02,0x00,0x06,0x00,0x18,0x13,0xf1,0x00,0x08,0x09,0x59,0x00,0x03,0x08,0xce, 0x09,0x3f,0x08,0xc7,0x08,0xee,0x08,0xf3,0x13,0xf1,0x00,0x08,0x09,0x59,0x00,0x03,0x08,0xce,0x09,0x3f,0x08,0xc7,0x08,0xee,0x09,0x60,0x00,0x01,0x00,0x01,0x08,0xce,0x00,0x01,0x00,0x2e,0x00,0x01,0x00,0x08,0x00,0x02,0x00,0x06,0x00,0x16,0x13,0xf1,0x00,0x07,0x09,0x59,0x00,0x03,0x08,0xce,0x08,0xfb,0x08,0xee,0x08,0xf3,0x13,0xf1, 0x00,0x07,0x09,0x59,0x00,0x03,0x08,0xce,0x08,0xfb,0x08,0xee,0x09,0x60,0x00,0x01,0x00,0x01,0x08,0xce,0x00,0x01,0x00,0x3a,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x13,0xf2,0x00,0x16,0x0e,0x32,0x0e,0x57,0x00,0x03,0x09,0x0d,0x08,0xee,0x09,0x3f,0x08,0xf3,0x00,0x03,0x09,0x0d,0x08,0xee,0x0b,0x0c,0x08,0xd0,0x0e,0x58,0x0e,0x59, 0x00,0x03,0x09,0x0d,0x08,0xee,0x0b,0x0c,0x08,0xd0,0x0e,0x61,0x0e,0x57,0x00,0x01,0x00,0x01,0x08,0xcb,0x00,0x01,0x00,0x34,0x00,0x01,0x00,0x08,0x00,0x01,0x00,0x04,0x13,0xf2,0x00,0x13,0x0e,0x32,0x0e,0x57,0x00,0x03,0x0a,0x63,0x00,0x03,0x09,0x0d,0x08,0xee,0x0b,0x0c,0x08,0xd0,0x0e,0x58,0x0e,0x59,0x00,0x03,0x09,0x0d,0x08,0xee, 0x0b,0x0c,0x08,0xd0,0x0e,0x61,0x0e,0x57,0x00,0x01,0x00,0x01,0x08,0xcb,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x02,0x64,0x6c,0x6e,0x67,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x2c,0x73,0x6c,0x6e,0x67,0x00,0x00,0x00,0x54, 0x00,0x00,0x00,0x2c,0x4c,0x61,0x74,0x6e,0x2c,0x47,0x72,0x65,0x6b,0x2c,0x43,0x79,0x72,0x6c,0x2c,0x41,0x72,0x6d,0x6e,0x2c,0x47,0x65,0x6f,0x72,0x2c,0x47,0x65,0x6f,0x6b,0x2c,0x41,0x72,0x61,0x62,0x2c,0x48,0x65,0x62,0x72,0x2c,0x4c,0x69,0x73,0x75,0x4c,0x61,0x74,0x6e,0x2c,0x47,0x72,0x65,0x6b,0x2c,0x43,0x79,0x72,0x6c,0x2c,0x41, 0x72,0x6d,0x6e,0x2c,0x47,0x65,0x6f,0x72,0x2c,0x47,0x65,0x6f,0x6b,0x2c,0x41,0x72,0x61,0x62,0x2c,0x48,0x65,0x62,0x72,0x2c,0x4c,0x69,0x73,0x75, }; read_only global String8 rd_default_main_font_bytes = {rd_default_main_font_bytes__data, sizeof(rd_default_main_font_bytes__data)}; read_only global U8 rd_default_code_font_bytes__data[] = { 0x00,0x01,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x04,0x00,0x10,0x47,0x44,0x45,0x46,0x14,0xdc,0x05,0x92,0x00,0x03,0xa6,0x14,0x00,0x00,0x02,0x2a,0x47,0x50,0x4f,0x53,0x68,0xe9,0x9a,0x47,0x00,0x03,0xa8,0x40,0x00,0x00,0x23,0x96,0x47,0x53,0x55,0x42,0x28,0xdb,0xc9,0x88,0x00,0x03,0xcb,0xd8,0x00,0x00,0x62,0x14,0x4f,0x53,0x2f,0x32, 0x12,0x35,0x0b,0x84,0x00,0x00,0x01,0x98,0x00,0x00,0x00,0x60,0x63,0x6d,0x61,0x70,0x5a,0x24,0x58,0xda,0x00,0x00,0x1d,0x34,0x00,0x00,0x42,0x6a,0x63,0x76,0x74,0x20,0x27,0x58,0x0f,0x1a,0x00,0x00,0x6e,0x84,0x00,0x00,0x00,0xa8,0x66,0x70,0x67,0x6d,0x62,0x2f,0x03,0x7f,0x00,0x00,0x5f,0xa0,0x00,0x00,0x0e,0x0c,0x67,0x61,0x73,0x70, 0x00,0x00,0x00,0x10,0x00,0x03,0xa6,0x0c,0x00,0x00,0x00,0x08,0x67,0x6c,0x79,0x66,0x6c,0x17,0x21,0x7d,0x00,0x00,0x8a,0x6c,0x00,0x02,0xc9,0x3c,0x68,0x65,0x61,0x64,0x1b,0x2b,0x60,0x84,0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x36,0x68,0x68,0x65,0x61,0x00,0x35,0x07,0x57,0x00,0x00,0x01,0x54,0x00,0x00,0x00,0x24,0x68,0x6d,0x74,0x78, 0x54,0xf6,0x4a,0x0f,0x00,0x00,0x01,0xf8,0x00,0x00,0x1b,0x3c,0x6c,0x6f,0x63,0x61,0x08,0x34,0x21,0x64,0x00,0x00,0x6f,0x2c,0x00,0x00,0x1b,0x40,0x6d,0x61,0x78,0x70,0x0f,0xc8,0x14,0x44,0x00,0x00,0x01,0x78,0x00,0x00,0x00,0x20,0x6e,0x61,0x6d,0x65,0x94,0x4b,0x4e,0x5d,0x00,0x03,0x53,0xa8,0x00,0x00,0x06,0x2f,0x70,0x6f,0x73,0x74, 0x5d,0x5a,0x9a,0x04,0x00,0x03,0x59,0xd8,0x00,0x00,0x4c,0x33,0x70,0x72,0x65,0x70,0x8a,0xcd,0x9c,0x1e,0x00,0x00,0x6d,0xac,0x00,0x00,0x00,0xd6,0x00,0x01,0x00,0x00,0x00,0x02,0x4d,0xd3,0x13,0x13,0x3d,0xf7,0x5f,0x0f,0x3c,0xf5,0x00,0x0f,0x03,0xe8,0x00,0x00,0x00,0x00,0xdf,0xe8,0x66,0x79,0x00,0x00,0x00,0x00,0xdf,0xe8,0x68,0x84, 0xf9,0x39,0xfe,0x70,0x02,0xfd,0x04,0x60,0x00,0x00,0x00,0x06,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x03,0xfc,0xfe,0xd4,0x00,0x00,0x02,0x58,0xf9,0x39,0xff,0x5b,0x02,0xfd,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xcf,0x00,0x01,0x00,0x00,0x06,0xcf,0x01,0xb8, 0x00,0x6e,0x00,0x87,0x00,0x06,0x00,0x02,0x02,0x94,0x03,0xf6,0x00,0x8d,0x00,0x00,0x05,0x60,0x0e,0x0c,0x00,0x03,0x00,0x01,0x00,0x04,0x02,0x58,0x01,0x90,0x00,0x05,0x00,0x00,0x02,0x8a,0x02,0x58,0x00,0x00,0x00,0x4b,0x02,0x8a,0x02,0x58,0x00,0x00,0x01,0x5e,0x00,0x32,0x01,0x40,0x00,0x00,0x02,0x00,0x00,0x09,0x00,0x00,0x00,0x00, 0x00,0x00,0xa0,0x04,0x02,0xff,0x12,0x00,0xf9,0xfb,0x02,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x4a,0x42,0x00,0x00,0x00,0xc0,0x00,0x0d,0xff,0xff,0x03,0xfc,0xfe,0xd4,0x00,0x00,0x03,0xfc,0x01,0x2c,0x20,0x00,0x01,0x9f,0xdf,0xd7,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x00,0x00,0x20,0x00,0x06,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x32, 0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32, 0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c, 0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64, 0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x42,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x5f,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x0a, 0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x5c, 0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x75,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58, 0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58, 0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x48, 0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x32, 0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x55, 0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43, 0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43, 0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x57,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x3f,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x54, 0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x58, 0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xd4,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55, 0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x61,0x02,0x58,0x00,0x61, 0x02,0x58,0x00,0x67,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5c, 0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54, 0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x57,0x02,0x58,0x00,0x57,0x02,0x58,0x00,0x70,0x02,0x58,0x00,0x70, 0x02,0x58,0x00,0x70,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0xa5,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36, 0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x41, 0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0xff,0xfb,0x02,0x58,0xff,0xfb,0x02,0x58,0xff,0xfb,0x02,0x58,0xff,0xfb,0x02,0x58,0xff,0xfb,0x02,0x58,0xff,0xfb,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x22,0x02,0x58,0x00,0x22,0x02,0x58,0x00,0x22,0x02,0x58,0x00,0x22,0x02,0x58,0x00,0x22,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64, 0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0xaf,0x02,0x58,0x00,0xb9,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x06, 0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x2e, 0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5e,0x02,0x58,0xff,0xfb,0x02,0x58,0x00,0x3c,0x02,0x58,0xff,0xfb,0x02,0x58,0x00,0x35,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x4e,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69, 0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x38,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x51,0x02,0x58,0x00,0x59,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x5f,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x06,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x56,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x82, 0x02,0x58,0x00,0x1b,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x67,0x02,0x58,0x00,0x67,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x58, 0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x30,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x4e,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x3e,0x02,0x58,0x00,0x55, 0x02,0x58,0x00,0x57,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3f,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5b,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x49,0x02,0x58,0x00,0x64, 0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x4e,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x32, 0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5c, 0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x0a,0x02,0x58,0xff,0x8d,0x02,0x58,0xff,0x8d,0x02,0x58,0xff,0x8d,0x02,0x58,0xff,0xb0,0x02,0x58,0xff,0x83,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x23, 0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x67,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x36, 0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x5a, 0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x54,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x5c,0x02,0x58,0x00,0x30,0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x1a,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x4b, 0x02,0x58,0x00,0x4a,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x4a,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x1b,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x5f,0x02,0x58,0x00,0x4a,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x4a,0x02,0x58,0x00,0x4b, 0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x4a,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x36,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x4b, 0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x1e, 0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x4c,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x40,0x02,0x58,0x00,0x52,0x02,0x58,0x00,0x42,0x02,0x58,0x00,0x40,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x49, 0x02,0x58,0x00,0x42,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x8f,0x02,0x58,0x00,0x8d,0x02,0x58,0x00,0x86,0x02,0x58,0x00,0x94,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x8b, 0x02,0x58,0x00,0x8f,0x02,0x58,0x00,0x8d,0x02,0x58,0x00,0x86,0x02,0x58,0x00,0x94,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x8f,0x02,0x58,0x00,0x8d,0x02,0x58,0x00,0x86,0x02,0x58,0x00,0x94,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x8b, 0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x8f,0x02,0x58,0x00,0x8d,0x02,0x58,0x00,0x86,0x02,0x58,0x00,0x94,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x8b,0x02,0x58,0x00,0x9a,0x02,0x58,0x00,0x90,0x02,0x58,0x00,0x84,0x02,0x58,0x00,0x9a,0x02,0x58,0x00,0x90,0x02,0x58,0x00,0x84, 0x02,0x58,0x00,0x9a,0x02,0x58,0x00,0x90,0x02,0x58,0x00,0x84,0x02,0x58,0x00,0x9a,0x02,0x58,0x00,0x90,0x02,0x58,0x00,0x84,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x8a,0x02,0x58,0x00,0x8a,0x02,0x58,0x00,0x8a,0x02,0x58,0x00,0x8a,0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x05, 0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x89,0x02,0x58,0x00,0x91,0x02,0x58,0x00,0x4c,0x02,0x58,0x00,0xda,0x02,0x58,0x00,0xd2,0x02,0x58,0x00,0xd9,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0xe1,0x02,0x58,0x00,0xe1,0x02,0x58,0x00,0x82,0x02,0x58,0x00,0x73, 0x02,0x58,0x00,0xda,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x24,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x87,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0xda,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0xd9,0x00,0x00,0xff,0x1a, 0x00,0x00,0xff,0x79,0x02,0x58,0x00,0xb9,0x02,0x58,0x00,0x73,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x5f,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x5f,0x02,0x58,0x00,0x6e,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0x87, 0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x78,0x02,0x58,0x00,0xa0,0x02,0x58,0x00,0x73,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0xdc,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0xd2, 0x02,0x58,0x00,0xdc,0x02,0x58,0x00,0xd2,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x8f,0x02,0x58,0x00,0xf9,0x02,0x58,0xfe,0x34,0x02,0x58,0xfb,0xdc,0x02,0x58,0xf9,0x4d,0x02,0x58,0xfb,0xa6,0x02,0x58,0xfe,0x5c,0x02,0x58,0xfd,0xfd, 0x02,0x58,0xfb,0xa5,0x02,0x58,0xfd,0xfd,0x02,0x58,0xfb,0xa5,0x02,0x58,0xfe,0x11,0x02,0x58,0xfe,0x0c,0x02,0x58,0xf9,0x7f,0x02,0x58,0xf9,0x7f,0x02,0x58,0xfc,0x09,0x02,0x58,0xfe,0x43,0x02,0x58,0xfe,0x34,0x02,0x58,0xfe,0xbb,0x02,0x58,0xfe,0x8e,0x02,0x58,0xfe,0x3e,0x02,0x58,0xfe,0xd4,0x02,0x58,0xfc,0x90,0x02,0x58,0xfc,0x71, 0x02,0x58,0xfe,0x82,0x02,0x58,0xfe,0x5c,0x02,0x58,0xfe,0xd1,0x02,0x58,0xfc,0xc9,0x02,0x58,0xfc,0x44,0x02,0x58,0xfe,0xb3,0x02,0x58,0xfc,0x2c,0x02,0x58,0xfe,0x52,0x02,0x58,0xfe,0x81,0x02,0x58,0xfe,0x81,0x02,0x58,0xfe,0xc5,0x02,0x58,0xfc,0xbd,0x02,0x58,0xfe,0xc5,0x02,0x58,0xfc,0x68,0x02,0x58,0xfd,0xf8,0x02,0x58,0xfb,0xa5, 0x02,0x58,0xfe,0x90,0x02,0x58,0xfe,0x90,0x02,0x58,0xfe,0x5c,0x02,0x58,0xfb,0xfa,0x02,0x58,0xfe,0x52,0x02,0x58,0xfb,0x9c,0x02,0x58,0xfd,0xe5,0x02,0x58,0xfd,0xcc,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xe9,0x02,0x58,0xfb,0x91, 0x02,0x58,0xf9,0x39,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfd,0xcb,0x02,0x58,0xfb,0x73,0x02,0x58,0xfd,0xf3,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfe,0x11,0x02,0x58,0xfb,0xa0,0x02,0x58,0xfe,0x16,0x02,0x58,0xfe,0x3e,0x02,0x58,0xfb,0xfa,0x02,0x58,0xfc,0x13,0x02,0x58,0xfe,0x66,0x02,0x58,0xfe,0x66,0x02,0x58,0xfc,0x22,0x02,0x58,0xfd,0xe4, 0x02,0x58,0xfe,0x5c,0x02,0x58,0xfc,0x0e,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0xa0,0x02,0x58,0x00,0x73,0x02,0x58,0x00,0x2e,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0xda,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x13,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x58,0x02,0x58,0x00,0x48,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x1d, 0x02,0x58,0x00,0x9e,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0xda,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x9b,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x1b,0x02,0x58,0x00,0x9f,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x23,0x02,0x58,0xff,0xf6, 0x02,0x58,0x00,0x23,0x02,0x58,0x00,0xa5,0x02,0x58,0x00,0xe6,0x02,0x58,0x00,0x78,0x02,0x58,0x00,0x97,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x23,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x2d, 0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x41,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x46,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x2d, 0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55, 0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x64, 0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x23,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x2b,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x5d,0x02,0x58,0x00,0x9b, 0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x0e,0x02,0x58,0xff,0xfb,0x02,0x58,0x00,0x78,0x02,0x58,0x00,0xa0,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0xd9,0x02,0x58,0x00,0x23, 0x02,0x58,0x00,0x1e,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x73,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x73,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x00, 0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00, 0x02,0x58,0x00,0x43,0x02,0x58,0x00,0x1d,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x32,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x3c,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x28, 0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x2f,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x3c,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x6e, 0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x6e,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x0a,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x0a, 0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x05,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x0a,0x02,0x58,0xff,0xd8,0x02,0x58,0xff,0xd8,0x02,0x58,0xff,0xb0,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00, 0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x01,0x2c,0x02,0x58,0x02,0x0d,0x02,0x58,0x00,0x00,0x02,0x58,0x01,0x2c,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00, 0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0x01,0x2c,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6, 0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0xb4,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6, 0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x96, 0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x8c,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec, 0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa, 0x02,0x58,0x00,0x4b,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec, 0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec, 0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x19, 0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec, 0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec, 0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x96,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xc8,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa, 0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0xfa,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x44,0x02,0x58,0x00,0x44,0x02,0x58,0x00,0x3c,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x32, 0x02,0x58,0x00,0x32,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x32,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x1e, 0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00, 0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x5e,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0xaa,0x02,0x58,0x00,0x7d, 0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x46,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x58,0x02,0x58,0xff,0xf6,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x42,0x02,0x58,0x00,0x1f,0x02,0x58,0x00,0x27, 0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x19,0x02,0x58,0x00,0x41,0x02,0x58,0x00,0x4d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x0f,0x02,0x58,0x00,0x96,0x02,0x58,0x00,0xd2,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0xff,0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x46, 0x02,0x58,0x00,0x50,0x02,0x58,0x00,0x1e,0x02,0x58,0x00,0x3c,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x28,0x02,0x58,0x00,0x14,0x02,0x58,0x00,0x20,0x02,0x58,0x00,0x20,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0xc3,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0xc3,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d, 0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x34,0x02,0x58,0x00,0x3e,0x02,0x58,0x00,0x3e,0x02,0x58,0x00,0x20,0x02,0x58,0x00,0x2d,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x51, 0x02,0x58,0x00,0x14,0x02,0x58,0xff,0x5b,0x02,0x58,0xff,0xc9,0x02,0x58,0xff,0xa9,0x02,0x58,0x00,0x0a,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x64,0x02,0x58,0x00,0x00,0x02,0x58,0xff,0xec,0x02,0x58,0x00,0x52,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x2d,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec,0x02,0x58,0xff,0xec, 0x02,0x58,0x00,0xf5,0x02,0x58,0x00,0x06,0x02,0x58,0x00,0x23,0x02,0x58,0x00,0x2d,0x02,0x58,0xff,0xf6,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x25,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x49,0x02,0x58,0x00,0x2d,0x02,0x58,0x00,0x0f, 0x02,0x58,0x00,0x37,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x8c,0x02,0x58,0xfe,0x13,0x02,0x58,0xfe,0x07,0x02,0x58,0xfb,0xc8,0x02,0x58,0xfd,0xda,0x02,0x58,0xfb,0x82,0x02,0x58,0xfd,0xdf,0x02,0x58,0xfd,0xd5,0x02,0x58,0xfd,0xc6,0x02,0x58,0xfb,0x73,0x02,0x58,0xfd,0xd5,0x02,0x58,0xfe,0xa7,0x02,0x58,0xfb,0xd2,0x02,0x58,0xfe,0xbb, 0x02,0x58,0xfe,0xbb,0x02,0x58,0xfe,0xe3,0x02,0x58,0xfc,0xa4,0x02,0x58,0xfc,0xc7,0x02,0x58,0xfa,0xc9,0x02,0x58,0xfc,0xa4,0x02,0x58,0xfc,0xd6,0x02,0x58,0xfe,0xa7,0x02,0x58,0xfb,0xd2,0x02,0x58,0xfe,0xbb,0x02,0x58,0xfe,0x13,0x02,0x58,0xfe,0x20,0x02,0x58,0xfb,0xff,0x02,0x58,0xfd,0xda,0x02,0x58,0xfe,0x2a,0x02,0x58,0xfb,0xa0, 0x02,0x58,0xfb,0xa0,0x02,0x58,0xfd,0xf8,0x02,0x58,0xfb,0xa5,0x02,0x58,0xfb,0xa5,0x02,0x58,0xfd,0xfd,0x02,0x58,0xfb,0xa5,0x02,0x58,0xfb,0xa5,0x02,0x58,0xfb,0xa1,0x02,0x58,0xfe,0x0c,0x02,0x58,0xfb,0xb3,0x02,0x58,0xfe,0x61,0x02,0x58,0xfe,0x89,0x02,0x58,0xfe,0xcf,0x02,0x58,0xfb,0xb3,0x02,0x58,0xfe,0x2a,0x02,0x58,0xfb,0xb3, 0x02,0x58,0xfb,0xb3,0x02,0x58,0xfc,0x6d,0x02,0x58,0xfd,0xf3,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfe,0x89,0x02,0x58,0xfb,0xcd,0x02,0x58,0xf9,0x43,0x02,0x58,0xfd,0xee,0x02,0x58,0xfb,0xb4,0x02,0x58,0xfe,0x98,0x02,0x58,0xfc,0x77,0x02,0x58,0xfa,0x7e,0x02,0x58,0xfb,0xe6, 0x02,0x58,0xfe,0x07,0x02,0x58,0xfb,0xbe,0x02,0x58,0xf9,0x43,0x02,0x58,0xfd,0xee,0x02,0x58,0xfb,0xb4,0x02,0x58,0xfe,0xcf,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xf9,0x43,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfe,0x34,0x02,0x58,0xfe,0x47,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfb,0xf5, 0x02,0x58,0xfb,0x9b,0x02,0x58,0xfd,0xf3,0x02,0x58,0xfb,0xb4,0x02,0x58,0xfb,0x9b,0x02,0x58,0xfe,0x2a,0x02,0x58,0xfb,0xf5,0x02,0x58,0xfe,0x11,0x02,0x58,0xfd,0xee,0x02,0x58,0xfd,0xee,0x02,0x58,0xfe,0x57,0x02,0x58,0xfb,0x96,0x02,0x58,0xfe,0x39,0x02,0x58,0xfd,0xf8,0x02,0x58,0xfb,0xa0,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x41, 0x02,0x58,0x00,0xa5,0x02,0x58,0x00,0xd2,0x02,0x58,0x00,0xa5,0x02,0x58,0x00,0x37,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0xa5,0x00,0x00,0xfe,0x25,0x00,0x00,0xfe,0x8d,0x00,0x00,0xfe,0x4a,0x00,0x00,0xfe,0x90,0x00,0x00,0xfe,0x3b,0x00,0x00,0xff,0x60,0x00,0x00,0xfe,0x1f,0x00,0x00,0xfe,0x1f,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x5c, 0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x7a,0x00,0x00,0xfd,0xf0,0x00,0x00,0xfe,0x7a,0x00,0x00,0xff,0x18,0x00,0x00,0xfe,0x8d,0x00,0x00,0xfe,0x5c,0x00,0x00,0xfe,0x66,0x00,0x00,0xfe,0x75,0x00,0x00,0xfe,0x61,0x00,0x00,0xfd,0x8a,0x00,0x00,0xfd,0xcb,0x00,0x00,0xfe,0x16,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0xe5, 0x02,0x58,0x00,0xa2,0x02,0x58,0x00,0xe8,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x77,0x02,0x58,0x00,0x77,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0xcd,0x02,0x58,0x00,0xb9,0x00,0x00,0xfe,0x66,0x00,0x00,0xfe,0x25,0x00,0x00,0xfe,0x8d,0x00,0x00,0xfe,0x4a,0x00,0x00,0xfe,0x90, 0x00,0x00,0xfe,0x3b,0x00,0x00,0xfe,0x1f,0x00,0x00,0xfe,0x1f,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x5c,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x7a,0x00,0x00,0xfd,0xf0,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x7a,0x00,0x00,0xff,0x1b,0x00,0x00,0xfe,0x8d,0x00,0x00,0xfe,0x25,0x00,0x00,0xfe,0x66,0x00,0x00,0xfe,0x75, 0x00,0x00,0xfe,0x61,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x34,0x02,0x58,0x00,0x7d,0x02,0x58,0x00,0xe5,0x02,0x58,0x00,0xa2,0x02,0x58,0x00,0xe8,0x02,0x58,0x00,0x93,0x02,0x58,0x00,0x77,0x02,0x58,0x00,0x77,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0xb4,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0x8c,0x02,0x58,0x00,0xd2,0x02,0x58,0x00,0xe1, 0x02,0x58,0x00,0x7d,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x2a,0x00,0x00,0xfe,0x2a,0x00,0x00,0xfe,0x2a,0x00,0x00,0xfe,0x34,0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x2f,0x00,0x00,0xfe,0x2f,0x00,0x00,0xfe,0x2f,0x00,0x00,0xfe,0x2f,0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x20, 0x00,0x00,0xfe,0x20,0x00,0x00,0xfe,0x20,0x02,0x58,0x00,0x5a,0x02,0x58,0x00,0x69,0x02,0x58,0x00,0x32,0x02,0x58,0xff,0xd8,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x00,0x02,0x58,0x00,0x55,0x02,0x58,0x00,0x55,0x00,0x00,0x00,0x00,0x02,0x58,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x24, 0x00,0x00,0x00,0x04,0x00,0x00,0x0f,0x12,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x24,0x00,0x03,0x00,0x0a,0x00,0x00,0x0f,0x12,0x00,0x04,0x0e,0xee,0x00,0x00,0x01,0xa8,0x01,0x00,0x00,0x07,0x00,0xa8,0x00,0x0d,0x00,0x2f,0x00,0x39,0x00,0x7e,0x01,0x31,0x01,0x7f,0x01,0x90,0x01,0x92,0x01,0x9b,0x01,0xa1,0x01,0xb0,0x01,0xce,0x01,0xd0, 0x01,0xd2,0x01,0xd4,0x01,0xd6,0x01,0xd8,0x01,0xda,0x01,0xdc,0x01,0xe7,0x01,0xeb,0x01,0xf5,0x01,0xff,0x02,0x1b,0x02,0x33,0x02,0x37,0x02,0x59,0x02,0xba,0x02,0xbc,0x02,0xc7,0x02,0xc9,0x02,0xdd,0x02,0xf3,0x02,0xf7,0x03,0x04,0x03,0x0c,0x03,0x0f,0x03,0x12,0x03,0x1b,0x03,0x23,0x03,0x28,0x03,0x38,0x03,0x75,0x03,0x7e,0x03,0x8a, 0x03,0x8c,0x03,0x90,0x03,0xa1,0x03,0xa9,0x03,0xb0,0x03,0xc9,0x03,0xcf,0x03,0xd7,0x04,0x0c,0x04,0x1a,0x04,0x23,0x04,0x3a,0x04,0x43,0x04,0x4f,0x04,0x5c,0x04,0x5f,0x04,0x93,0x04,0x9b,0x04,0xa3,0x04,0xb1,0x04,0xb7,0x04,0xbb,0x04,0xd9,0x04,0xdf,0x04,0xe9,0x04,0xf5,0x0a,0xea,0x1e,0x85,0x1e,0x9e,0x1e,0xf9,0x20,0x01,0x20,0x0b, 0x20,0x10,0x20,0x14,0x20,0x16,0x20,0x22,0x20,0x24,0x20,0x26,0x20,0x30,0x20,0x34,0x20,0x3a,0x20,0x3f,0x20,0x46,0x20,0x70,0x20,0x79,0x20,0x7a,0x20,0x7c,0x20,0x89,0x20,0xac,0x20,0xae,0x20,0xb4,0x20,0xbd,0x20,0xbf,0x21,0x02,0x21,0x0d,0x21,0x13,0x21,0x16,0x21,0x1a,0x21,0x1d,0x21,0x22,0x21,0x24,0x21,0x2e,0x21,0x40,0x21,0x8b, 0x21,0x99,0x21,0x9e,0x21,0xa0,0x21,0xa3,0x21,0xa7,0x21,0xaa,0x21,0xad,0x21,0xbe,0x21,0xc9,0x21,0xd4,0x21,0xdb,0x21,0xdf,0x21,0xe5,0x21,0xe8,0x21,0xea,0x22,0x0c,0x22,0x13,0x22,0x15,0x22,0x1a,0x22,0x1e,0x22,0x25,0x22,0x2b,0x22,0x39,0x22,0x3c,0x22,0x3e,0x22,0x43,0x22,0x45,0x22,0x49,0x22,0x4b,0x22,0x4d,0x22,0x54,0x22,0x57, 0x22,0x65,0x22,0x73,0x22,0x7c,0x22,0x89,0x22,0x99,0x22,0xa5,0x22,0xb4,0x22,0xb8,0x22,0xbd,0x22,0xc4,0x22,0xc6,0x22,0xca,0x22,0xce,0x22,0xd0,0x22,0xe2,0x22,0xf1,0x23,0x05,0x23,0x0b,0x23,0x18,0x23,0x1f,0x23,0x26,0x23,0x28,0x23,0x2b,0x23,0x7a,0x23,0x8b,0x23,0x95,0x23,0xad,0x23,0xce,0x23,0xfe,0x24,0x21,0x24,0x24,0x25,0x94, 0x25,0x9f,0x25,0xa1,0x25,0xab,0x25,0xcc,0x25,0xcf,0x25,0xd5,0x25,0xe6,0x25,0xeb,0x25,0xef,0x25,0xf6,0x26,0x6d,0x26,0x6f,0x26,0x87,0x26,0xa1,0x27,0x13,0x27,0x15,0x27,0x17,0x27,0x36,0x27,0x71,0x27,0x94,0x27,0x9e,0x27,0xc6,0x27,0xdc,0x27,0xeb,0x27,0xf7,0x29,0x16,0x29,0x4a,0x29,0x88,0x2a,0x00,0x2a,0x06,0x2b,0x58,0xe0,0xa2, 0xe0,0xb3,0xfe,0x62,0xfe,0xff,0xff,0x5b,0xff,0x5d,0xff,0xfd,0xff,0xff,0x00,0x00,0x00,0x0d,0x00,0x20,0x00,0x30,0x00,0x3a,0x00,0xa0,0x01,0x34,0x01,0x8f,0x01,0x92,0x01,0x9b,0x01,0xa0,0x01,0xaf,0x01,0xcd,0x01,0xd0,0x01,0xd2,0x01,0xd4,0x01,0xd6,0x01,0xd8,0x01,0xda,0x01,0xdc,0x01,0xe6,0x01,0xea,0x01,0xf4,0x01,0xfc,0x02,0x18, 0x02,0x32,0x02,0x37,0x02,0x59,0x02,0xb9,0x02,0xbc,0x02,0xc6,0x02,0xc9,0x02,0xd8,0x02,0xf3,0x02,0xf7,0x03,0x00,0x03,0x06,0x03,0x0f,0x03,0x12,0x03,0x1b,0x03,0x23,0x03,0x25,0x03,0x36,0x03,0x74,0x03,0x7e,0x03,0x84,0x03,0x8c,0x03,0x8e,0x03,0x91,0x03,0xa3,0x03,0xaa,0x03,0xb1,0x03,0xca,0x03,0xd5,0x04,0x01,0x04,0x0e,0x04,0x1b, 0x04,0x24,0x04,0x3b,0x04,0x44,0x04,0x51,0x04,0x5e,0x04,0x90,0x04,0x9a,0x04,0xa2,0x04,0xae,0x04,0xb6,0x04,0xba,0x04,0xd8,0x04,0xdc,0x04,0xe4,0x04,0xf4,0x0a,0xea,0x1e,0x80,0x1e,0x9e,0x1e,0xa0,0x20,0x01,0x20,0x0b,0x20,0x10,0x20,0x13,0x20,0x16,0x20,0x18,0x20,0x24,0x20,0x26,0x20,0x30,0x20,0x32,0x20,0x39,0x20,0x3c,0x20,0x44, 0x20,0x70,0x20,0x74,0x20,0x7a,0x20,0x7c,0x20,0x80,0x20,0xab,0x20,0xae,0x20,0xb4,0x20,0xbd,0x20,0xbf,0x21,0x02,0x21,0x0d,0x21,0x13,0x21,0x15,0x21,0x19,0x21,0x1d,0x21,0x22,0x21,0x24,0x21,0x2e,0x21,0x40,0x21,0x8a,0x21,0x90,0x21,0x9d,0x21,0xa0,0x21,0xa2,0x21,0xa5,0x21,0xa9,0x21,0xad,0x21,0xbe,0x21,0xc9,0x21,0xd0,0x21,0xdb, 0x21,0xde,0x21,0xe5,0x21,0xe7,0x21,0xea,0x22,0x00,0x22,0x0e,0x22,0x15,0x22,0x18,0x22,0x1e,0x22,0x23,0x22,0x27,0x22,0x34,0x22,0x3c,0x22,0x3e,0x22,0x43,0x22,0x45,0x22,0x47,0x22,0x4b,0x22,0x4d,0x22,0x54,0x22,0x57,0x22,0x5f,0x22,0x6a,0x22,0x7a,0x22,0x82,0x22,0x8e,0x22,0x9b,0x22,0xb4,0x22,0xb8,0x22,0xbb,0x22,0xc2,0x22,0xc6, 0x22,0xc8,0x22,0xce,0x22,0xd0,0x22,0xe2,0x22,0xee,0x23,0x02,0x23,0x08,0x23,0x18,0x23,0x1c,0x23,0x24,0x23,0x28,0x23,0x2b,0x23,0x36,0x23,0x89,0x23,0x95,0x23,0x9b,0x23,0xce,0x23,0xfb,0x24,0x00,0x24,0x23,0x25,0x00,0x25,0x95,0x25,0xa0,0x25,0xaa,0x25,0xb2,0x25,0xce,0x25,0xd4,0x25,0xe6,0x25,0xe7,0x25,0xef,0x25,0xf6,0x26,0x6d, 0x26,0x6f,0x26,0x87,0x26,0xa0,0x27,0x13,0x27,0x15,0x27,0x17,0x27,0x36,0x27,0x6e,0x27,0x94,0x27,0x9c,0x27,0xc5,0x27,0xdc,0x27,0xe6,0x27,0xf5,0x29,0x16,0x29,0x4a,0x29,0x87,0x2a,0x00,0x2a,0x05,0x2b,0x58,0xe0,0xa0,0xe0,0xb0,0xfe,0x62,0xfe,0xff,0xff,0x5b,0xff,0x5d,0xff,0xfd,0xff,0xff,0x03,0xb3,0x00,0x00,0x02,0xa4,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x36,0xff,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x33,0xff,0x53,0xff,0x80,0xff,0x84,0xff,0x7f,0xff,0x7e,0xff,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xd7,0xfe,0x9a,0x00,0x00,0x03,0xa8,0x03,0xbf,0x03,0x9d,0x00,0x00,0x03,0x10,0x03,0x0d,0x00,0x00,0x00,0x00, 0x03,0x66,0x03,0x64,0x03,0x5c,0x03,0x55,0x03,0x54,0x03,0x47,0x02,0xee,0x00,0x3d,0x00,0x00,0xfe,0xe1,0x00,0x00,0xfe,0xc0,0xfe,0xbf,0x00,0x00,0xfe,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xbc,0x00,0x00,0xfd,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x3e,0x00,0x00,0xe1,0xe9,0x00,0x00,0xe3,0xbb,0xe3,0xb2,0xe3,0x4b,0xe3,0x46,0xe3,0x21,0x00,0x00,0xe3,0x17,0xe3,0x07,0xe4,0x09,0x00,0x00,0xe3,0x2e,0x00,0x00,0x00,0x00,0xe2,0x92,0xe2,0x92,0xe3,0xc1,0xe3,0x6a,0xe2,0x64,0xe3,0x1b,0xe3,0x1e,0xe3,0x15,0xe3,0x0d,0xe3,0x03,0xe1,0xa0,0xe1,0x9a, 0xe4,0xae,0x00,0x00,0xe1,0x96,0xe1,0x94,0xe4,0x98,0xe1,0x95,0xe4,0x96,0xe3,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xde,0xe2,0xdd,0xe2,0xdc,0xe2,0xdc,0xe2,0xcf,0xe2,0xc9,0xe2,0xbf,0x00,0x00,0xe2,0xb3,0x00,0x00,0xe2,0x9f,0xe2,0xa8,0xe3,0xf8,0x00,0x00,0x00,0x00,0xe1,0xc8,0x00,0x00,0xe2,0x06,0x00,0x00,0xe1,0xff,0x00,0x00, 0xe2,0x12,0xe1,0xaf,0xe1,0x8d,0xe1,0x92,0x00,0x00,0xe2,0x19,0xe1,0x9b,0xe1,0x81,0xe1,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x54,0xe1,0x44,0x00,0x00,0x00,0x00,0xe1,0x93,0x00,0x00,0xe1,0x0c,0xe1,0x10,0xe1,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xd1,0x00,0x00,0x00,0x00,0xe2,0xbd,0xe2,0xb8, 0x00,0x00,0x00,0x00,0xe1,0xf0,0x00,0x00,0xe2,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0x17,0xdf,0x28,0xdf,0x20,0x00,0x00,0x00,0x00,0xde,0xe9,0xde,0xdd,0xde,0xe5,0xde,0xcd,0xde,0xc9,0xdf,0xf3,0xdf,0xf2,0xdf,0x24,0xdf,0x0c,0xde,0x9b,0xde,0x9a,0xde,0x99,0xde,0x7b,0x00,0x00,0xdc,0xff,0xdc,0xf8,0x00,0x00,0xdc,0x13, 0x00,0x00,0xdc,0xa2,0xdb,0x2d,0xda,0xa4,0xd9,0xce,0xd9,0xfe,0xd9,0xfa,0xda,0x99,0x26,0x24,0x26,0x17,0x05,0xd8,0x04,0xc2,0x03,0xee,0x03,0xed,0x05,0xf9,0x00,0x01,0x00,0x00,0x01,0xa6,0x00,0x00,0x01,0xc2,0x02,0x4a,0x03,0x6c,0x04,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf8,0x03,0xfa,0x03,0xfc,0x03,0xfe,0x04,0x04,0x04,0x0a,0x00,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x04,0x0a,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0e,0x00,0x00,0x04,0x18,0x00,0x00, 0x00,0x00,0x04,0x18,0x00,0x00,0x04,0x22,0x04,0x2c,0x04,0x30,0x04,0x46,0x00,0x00,0x04,0x5c,0x00,0x00,0x04,0x86,0x04,0x9c,0x04,0xb2,0x04,0xb4,0x04,0xba,0x04,0xbc,0x04,0xbe,0x04,0xc4,0x04,0xc6,0x04,0xc8,0x04,0xca,0x04,0xd0,0x04,0xda,0x00,0x00,0x04,0xda,0x00,0x00,0x04,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x05,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x98,0x00,0x00,0x05,0x9a,0x05,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x80,0x05,0x82,0x05,0x94,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x88,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8a,0x05,0xa2,0x00,0x00,0x05,0xaa,0x00,0x00,0x05,0xac,0x00,0x00,0x05,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xac,0x05,0xb8,0x05,0xca, 0x05,0xce,0x05,0xdc,0x05,0xf2,0x00,0x00,0x00,0x00,0x06,0x02,0x06,0x06,0x00,0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x0c,0x06,0x12,0x00,0x00,0x06,0x16,0x06,0x1c,0x00,0x00,0x00,0x00,0x06,0x1c,0x06,0xa4,0x00,0x00,0x06,0xa6,0x00,0x00,0x06,0xc8,0x06,0xce,0x07,0x10,0x07,0x12,0x00,0x00,0x00,0x00,0x00,0x00, 0x08,0x34,0x08,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x50,0x00,0x00,0x00,0x00,0x08,0x52,0x00,0x00,0x08,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xbe,0x03,0x2e,0x03,0x6a,0x03,0x3a,0x03,0xc5,0x04,0x38,0x05,0xb5,0x03,0x6b,0x03,0x43,0x03,0x44,0x03,0x34,0x04,0x15,0x03,0x2a,0x03,0x57,0x03,0x29,0x03,0x3d,0x03,0x2b,0x03,0x2c,0x04,0x1c,0x04,0x19,0x04,0x1b,0x03,0x30,0x05,0xb4,0x00,0x01,0x00,0x1a,0x00,0x1b,0x00,0x21,0x00,0x25, 0x00,0x38,0x00,0x39,0x00,0x40,0x00,0x43,0x00,0x4f,0x00,0x51,0x00,0x53,0x00,0x59,0x00,0x5a,0x00,0x60,0x00,0x7a,0x00,0x7c,0x00,0x7d,0x00,0x81,0x00,0x89,0x00,0x8e,0x00,0xa1,0x00,0xa2,0x00,0xa7,0x00,0xa8,0x00,0xb1,0x03,0x47,0x03,0x3e,0x03,0x48,0x04,0x23,0x03,0x5c,0x06,0x82,0x00,0xbd,0x00,0xd6,0x00,0xd7,0x00,0xdd,0x00,0xe1, 0x00,0xf4,0x00,0xf5,0x00,0xfc,0x00,0xff,0x01,0x0d,0x01,0x10,0x01,0x13,0x01,0x1a,0x01,0x1b,0x01,0x22,0x01,0x3d,0x01,0x3f,0x01,0x40,0x01,0x44,0x01,0x4c,0x01,0x51,0x01,0x69,0x01,0x6a,0x01,0x6f,0x01,0x70,0x01,0x79,0x03,0x45,0x05,0xbe,0x03,0x46,0x04,0x22,0x03,0xbf,0x03,0x2f,0x03,0xc3,0x03,0xcb,0x03,0xc4,0x03,0xcd,0x05,0xbf, 0x05,0xb7,0x06,0x80,0x05,0xb8,0x01,0xc6,0x03,0x65,0x04,0x21,0x03,0x58,0x05,0xb9,0x06,0x8a,0x05,0xbb,0x04,0x1f,0x03,0x04,0x03,0x05,0x06,0x83,0x04,0x30,0x05,0xb6,0x03,0x32,0x06,0x8b,0x03,0x03,0x01,0xc7,0x03,0x66,0x03,0x22,0x03,0x21,0x03,0x23,0x03,0x31,0x00,0x12,0x00,0x02,0x00,0x0a,0x00,0x17,0x00,0x10,0x00,0x16,0x00,0x18, 0x00,0x1e,0x00,0x32,0x00,0x26,0x00,0x29,0x00,0x2f,0x00,0x4a,0x00,0x44,0x00,0x46,0x00,0x47,0x00,0x22,0x00,0x5f,0x00,0x6b,0x00,0x61,0x00,0x63,0x00,0x78,0x00,0x69,0x04,0x17,0x00,0x76,0x00,0x94,0x00,0x8f,0x00,0x91,0x00,0x92,0x00,0xa9,0x00,0x7b,0x01,0x4a,0x00,0xce,0x00,0xbe,0x00,0xc6,0x00,0xd3,0x00,0xcc,0x00,0xd2,0x00,0xd4, 0x00,0xda,0x00,0xee,0x00,0xe2,0x00,0xe5,0x00,0xeb,0x01,0x08,0x01,0x01,0x01,0x04,0x01,0x05,0x00,0xde,0x01,0x21,0x01,0x2e,0x01,0x23,0x01,0x26,0x01,0x3b,0x01,0x2c,0x04,0x18,0x01,0x39,0x01,0x5c,0x01,0x52,0x01,0x55,0x01,0x56,0x01,0x71,0x01,0x3e,0x01,0x73,0x00,0x14,0x00,0xd0,0x00,0x03,0x00,0xbf,0x00,0x15,0x00,0xd1,0x00,0x1c, 0x00,0xd8,0x00,0x1f,0x00,0xdb,0x00,0x20,0x00,0xdc,0x00,0x1d,0x00,0xd9,0x00,0x23,0x00,0xdf,0x00,0x24,0x00,0xe0,0x00,0x34,0x00,0xf0,0x00,0x27,0x00,0xe3,0x00,0x30,0x00,0xec,0x00,0x35,0x00,0xf1,0x00,0x28,0x00,0xe4,0x00,0x3d,0x00,0xf9,0x00,0x3b,0x00,0xf7,0x00,0x3f,0x00,0xfb,0x00,0x3e,0x00,0xfa,0x00,0x42,0x00,0xfe,0x00,0x41, 0x00,0xfd,0x00,0x4e,0x01,0x0c,0x00,0x4c,0x01,0x0a,0x00,0x45,0x01,0x02,0x00,0x4d,0x01,0x0b,0x00,0x48,0x01,0x00,0x00,0x50,0x01,0x0f,0x00,0x52,0x01,0x11,0x01,0x12,0x00,0x54,0x01,0x14,0x00,0x56,0x01,0x17,0x00,0x55,0x01,0x16,0x00,0x57,0x01,0x18,0x00,0x58,0x01,0x19,0x00,0x5b,0x01,0x1c,0x00,0x5d,0x01,0x1f,0x00,0x5c,0x01,0x1e, 0x01,0x1d,0x00,0x5e,0x01,0x20,0x00,0x74,0x01,0x37,0x00,0x62,0x01,0x24,0x00,0x73,0x01,0x36,0x00,0x79,0x01,0x3c,0x00,0x7e,0x01,0x41,0x00,0x80,0x01,0x43,0x00,0x7f,0x01,0x42,0x00,0x82,0x01,0x45,0x00,0x85,0x01,0x48,0x00,0x84,0x01,0x47,0x00,0x83,0x01,0x46,0x00,0x8c,0x01,0x4f,0x00,0x8b,0x01,0x4e,0x00,0x8a,0x01,0x4d,0x00,0xa0, 0x01,0x68,0x00,0x9d,0x01,0x65,0x00,0x90,0x01,0x53,0x00,0x9f,0x01,0x67,0x00,0x9c,0x01,0x64,0x00,0x9e,0x01,0x66,0x00,0xa4,0x01,0x6c,0x00,0xaa,0x01,0x72,0x00,0xab,0x00,0xb2,0x01,0x7a,0x00,0xb4,0x01,0x7c,0x00,0xb3,0x01,0x7b,0x01,0x4b,0x00,0x88,0x00,0x36,0x00,0x6d,0x01,0x30,0x00,0x96,0x01,0x5e,0x00,0x09,0x00,0xc5,0x00,0x3c, 0x00,0xf8,0x00,0x75,0x01,0x38,0x00,0x3a,0x00,0xf6,0x00,0x19,0x00,0xd5,0x00,0x77,0x01,0x3a,0x00,0x86,0x01,0x49,0x00,0x8d,0x01,0x50,0x00,0xaf,0x01,0x77,0x06,0x67,0x06,0x65,0x06,0x87,0x06,0x81,0x06,0x88,0x06,0x8c,0x06,0x89,0x06,0x84,0x06,0x6a,0x06,0x6b,0x06,0x6e,0x06,0x72,0x06,0x73,0x06,0x70,0x06,0x69,0x06,0x68,0x06,0x74, 0x06,0x71,0x06,0x6c,0x06,0x6f,0x06,0xb0,0x06,0xb2,0x02,0x69,0x03,0xba,0x02,0x6a,0x02,0x6b,0x02,0x6c,0x02,0x6e,0x02,0x6f,0x02,0x90,0x02,0x70,0x02,0x71,0x02,0x96,0x02,0x97,0x02,0x98,0x02,0x8e,0x02,0x93,0x02,0x8f,0x02,0x92,0x02,0x94,0x02,0x91,0x02,0x95,0x02,0x72,0x02,0x9a,0x02,0x9b,0x02,0x99,0x01,0xd0,0x01,0xf6,0x01,0xcc, 0x01,0xee,0x01,0xed,0x01,0xf0,0x01,0xf1,0x01,0xf2,0x01,0xeb,0x01,0xec,0x01,0xf3,0x01,0xd6,0x01,0xe0,0x01,0xe7,0x01,0xc8,0x01,0xc9,0x01,0xca,0x01,0xcb,0x01,0xce,0x01,0xcf,0x01,0xd1,0x01,0xd2,0x01,0xd3,0x01,0xd4,0x01,0xd5,0x01,0xe1,0x01,0xe2,0x01,0xe4,0x01,0xe3,0x01,0xe5,0x01,0xe6,0x01,0xe9,0x01,0xea,0x01,0xe8,0x01,0xef, 0x01,0xf4,0x01,0xf5,0x02,0x0c,0x02,0x0d,0x02,0x0e,0x02,0x0f,0x02,0x12,0x02,0x13,0x02,0x15,0x02,0x16,0x02,0x17,0x02,0x18,0x02,0x19,0x02,0x25,0x02,0x26,0x02,0x28,0x02,0x27,0x02,0x29,0x02,0x2a,0x02,0x2d,0x02,0x2e,0x02,0x2c,0x02,0x33,0x02,0x38,0x02,0x39,0x02,0x14,0x02,0x3a,0x02,0x10,0x02,0x32,0x02,0x31,0x02,0x34,0x02,0x35, 0x02,0x36,0x02,0x2f,0x02,0x30,0x02,0x37,0x02,0x1a,0x02,0x24,0x02,0x2b,0x01,0xcd,0x02,0x11,0x01,0xf7,0x02,0x3b,0x01,0xf8,0x02,0x3c,0x01,0xf9,0x02,0x3d,0x01,0xfa,0x02,0x3e,0x01,0xfb,0x02,0x3f,0x01,0xfc,0x02,0x40,0x01,0xfd,0x02,0x41,0x01,0xfe,0x02,0x42,0x01,0xff,0x02,0x43,0x02,0x00,0x02,0x44,0x02,0x01,0x02,0x45,0x02,0x02, 0x02,0x46,0x02,0x03,0x02,0x47,0x02,0x04,0x02,0x48,0x00,0xa6,0x01,0x6e,0x00,0xa3,0x01,0x6b,0x00,0xa5,0x01,0x6d,0x00,0x11,0x00,0xcd,0x00,0x13,0x00,0xcf,0x00,0x0b,0x00,0xc7,0x00,0x0d,0x00,0xc9,0x00,0x0e,0x00,0xca,0x00,0x0f,0x00,0xcb,0x00,0x0c,0x00,0xc8,0x00,0x04,0x00,0xc0,0x00,0x06,0x00,0xc2,0x00,0x07,0x00,0xc3,0x00,0x08, 0x00,0xc4,0x00,0x05,0x00,0xc1,0x00,0x31,0x00,0xed,0x00,0x33,0x00,0xef,0x00,0x37,0x00,0xf2,0x00,0x2a,0x00,0xe6,0x00,0x2c,0x00,0xe8,0x00,0x2d,0x00,0xe9,0x00,0x2e,0x00,0xea,0x00,0x2b,0x00,0xe7,0x00,0x4b,0x01,0x09,0x00,0x49,0x01,0x07,0x00,0x6a,0x01,0x2d,0x00,0x6c,0x01,0x2f,0x00,0x64,0x01,0x27,0x00,0x66,0x01,0x29,0x00,0x67, 0x01,0x2a,0x00,0x68,0x01,0x2b,0x00,0x65,0x01,0x28,0x00,0x6e,0x01,0x31,0x00,0x70,0x01,0x33,0x00,0x71,0x01,0x34,0x00,0x72,0x01,0x35,0x00,0x6f,0x01,0x32,0x00,0x93,0x01,0x5b,0x00,0x95,0x01,0x5d,0x00,0x97,0x01,0x5f,0x00,0x99,0x01,0x61,0x00,0x9a,0x01,0x62,0x00,0x9b,0x01,0x63,0x00,0x98,0x01,0x60,0x00,0xad,0x01,0x75,0x00,0xac, 0x01,0x74,0x00,0xae,0x01,0x76,0x00,0xb0,0x01,0x78,0x03,0x61,0x03,0x62,0x03,0x5d,0x03,0x63,0x03,0x5f,0x03,0x60,0x03,0x5e,0x03,0x64,0x05,0xc0,0x05,0xc2,0x03,0x33,0x05,0xbc,0x05,0xbd,0x03,0x69,0x03,0x38,0x03,0x39,0x03,0x3c,0x03,0x3f,0x03,0x20,0x03,0x35,0x03,0x36,0x02,0xad,0x05,0xc3,0x05,0xff,0x05,0xfe,0x04,0x77,0x04,0x71, 0x04,0x73,0x04,0x75,0x04,0x79,0x04,0x7a,0x04,0x78,0x04,0x72,0x04,0x74,0x04,0x76,0x04,0x7b,0x04,0x7d,0x04,0x8c,0x04,0x89,0x04,0x8a,0x04,0x8b,0x04,0x8d,0x05,0xe8,0x05,0xe7,0x04,0x65,0x03,0xd6,0x04,0x2f,0x03,0xea,0x04,0x62,0x04,0x25,0x04,0x2b,0x03,0xeb,0x03,0xe2,0x04,0x0b,0x03,0xe3,0x04,0x5d,0x04,0x0a,0x03,0xe5,0x04,0x2c, 0x03,0xd8,0x04,0x2d,0x04,0x16,0x03,0xf9,0x04,0x4d,0x03,0xd4,0x04,0x2e,0x03,0xdc,0x03,0xde,0x04,0x31,0x04,0x63,0x03,0xd1,0x04,0x40,0x04,0x3e,0x03,0xdf,0x03,0xe9,0x04,0x04,0x04,0x20,0x04,0x09,0x04,0x3f,0x04,0x1a,0x03,0xe7,0x04,0x0f,0x04,0x5a,0x04,0x1e,0x04,0x1d,0x03,0xfb,0x03,0xfa,0x03,0xd2,0x04,0x0c,0x04,0x10,0x04,0x0d, 0x04,0x11,0x04,0x0e,0x03,0xf7,0x03,0xec,0x04,0x3c,0x04,0x5c,0x04,0x3d,0x04,0x5b,0x04,0x5f,0x04,0x13,0x04,0x14,0x04,0x41,0x04,0x42,0x04,0x05,0x04,0x06,0x03,0xfd,0x04,0x55,0x04,0x57,0x04,0x56,0x04,0x58,0x04,0x4f,0x04,0x50,0x04,0x70,0x04,0x6d,0x04,0x6e,0x04,0x6c,0x04,0x6f,0x04,0x69,0x04,0x6b,0x04,0x6a,0x04,0x53,0x04,0x52, 0x04,0x54,0x04,0x51,0x04,0x4b,0x04,0x61,0x04,0x60,0x04,0x67,0x04,0x68,0x04,0x01,0x04,0x07,0x04,0x02,0x04,0x03,0x03,0xdb,0x03,0xd3,0x03,0xf3,0x04,0x47,0x03,0xe4,0x03,0xf8,0x04,0x66,0x03,0xe1,0x05,0xe1,0x05,0xca,0x04,0x91,0x05,0xf4,0x03,0x4f,0x03,0x52,0x03,0x50,0x03,0x53,0x05,0xce,0x05,0xcd,0x05,0xcb,0x05,0xcc,0x04,0x92, 0x05,0xe6,0x05,0xe4,0x05,0x65,0x05,0xa0,0x05,0x8f,0x05,0x8c,0x05,0x8b,0x05,0x91,0x05,0x87,0x05,0x6d,0x05,0x6b,0x05,0x9f,0x05,0x68,0x05,0x97,0x05,0x86,0x05,0x93,0x05,0x90,0x05,0x82,0x05,0x9d,0x05,0x92,0x05,0x96,0x05,0x69,0x05,0x79,0x05,0x72,0x05,0x8e,0x05,0x8a,0x05,0x78,0x05,0xa9,0x05,0x98,0x05,0xa8,0x05,0x71,0x05,0x99, 0x05,0x89,0x05,0xa7,0x05,0x7a,0x05,0x8d,0x05,0x9b,0x05,0x73,0x05,0x75,0x05,0x80,0x05,0x6e,0x05,0xa5,0x05,0x9a,0x05,0x6c,0x05,0x88,0x05,0xa6,0x05,0x70,0x05,0xa1,0x05,0x7f,0x05,0x6a,0x05,0x77,0x05,0x81,0x05,0xa3,0x05,0x7c,0x05,0x6f,0x05,0x74,0x05,0xaa,0x05,0xa2,0x05,0x9e,0x05,0x94,0x05,0x95,0x05,0x76,0x05,0xa4,0x05,0x7d, 0x05,0x9c,0x05,0x83,0x05,0x67,0x05,0x7b,0x05,0x7e,0x05,0x84,0x05,0x66,0x05,0xe0,0x05,0xd5,0x05,0xc7,0x04,0x34,0x04,0x32,0x04,0x33,0x04,0x37,0x04,0x35,0x04,0x36,0x03,0xf6,0x03,0xf4,0x03,0xf5,0x04,0x4a,0x04,0x48,0x04,0x49,0x03,0xf2,0x03,0xf1,0x03,0xf0,0x03,0xd9,0x04,0x46,0x04,0x45,0x04,0x44,0x05,0xef,0x05,0xf0,0x05,0xf2, 0x05,0xf3,0x05,0xee,0x05,0xfa,0x05,0xfb,0x05,0xd7,0x05,0xd8,0x05,0xda,0x05,0xb2,0x05,0xc5,0x05,0xb3,0x05,0xdf,0x05,0xeb,0x06,0x01,0x05,0xdd,0x05,0xc9,0x05,0xf8,0x05,0xf7,0x05,0xcf,0x05,0xd2,0x05,0xd4,0x05,0xd3,0x05,0xd1,0x05,0xec,0x05,0xfd,0x05,0xd9,0x05,0xc8,0x05,0xd6,0x05,0xfc,0x05,0xdb,0x05,0xdc,0x05,0xde,0x05,0xf5, 0x06,0x00,0x05,0xf9,0x05,0xd0,0x05,0xc6,0x05,0xed,0x05,0x2e,0x05,0x08,0x05,0x3b,0x05,0x15,0x05,0x34,0x05,0x0e,0x05,0x35,0x05,0x0f,0x05,0x31,0x05,0x0b,0x05,0x32,0x05,0x0c,0x05,0x2d,0x04,0xfc,0x04,0xf6,0x05,0x07,0x05,0x2c,0x04,0xfa,0x04,0xf4,0x05,0x06,0x05,0x3a,0x05,0x55,0x05,0x4f,0x05,0x14,0x05,0x39,0x05,0x53,0x05,0x4d, 0x05,0x12,0x05,0x3e,0x05,0x61,0x05,0x4e,0x04,0xf7,0x05,0x5e,0x04,0xfd,0x05,0x54,0x05,0x18,0x05,0x3d,0x05,0x60,0x05,0x4c,0x04,0xf5,0x05,0x5d,0x04,0xfb,0x05,0x52,0x05,0x17,0x05,0x2b,0x05,0x1a,0x05,0x40,0x04,0xf9,0x04,0xf3,0x05,0x43,0x05,0x1d,0x05,0x05,0x05,0x38,0x05,0x1b,0x05,0x41,0x05,0x51,0x05,0x4b,0x05,0x44,0x05,0x1e, 0x05,0x11,0x05,0x3c,0x05,0x1c,0x05,0x42,0x05,0x5f,0x05,0x4a,0x04,0xf8,0x05,0x5c,0x05,0x20,0x05,0x46,0x05,0x19,0x05,0x3f,0x04,0xfe,0x05,0x50,0x05,0x45,0x05,0x1f,0x05,0x16,0x05,0x28,0x05,0x02,0x05,0x29,0x05,0x03,0x04,0xe8,0x04,0xec,0x05,0x01,0x04,0xf2,0x04,0xe7,0x05,0x00,0x04,0xf1,0x04,0xe6,0x05,0x58,0x05,0x49,0x04,0xeb, 0x05,0x57,0x05,0x48,0x04,0xea,0x05,0x64,0x05,0x5b,0x04,0xef,0x05,0x63,0x05,0x5a,0x04,0xee,0x04,0xff,0x04,0xf0,0x04,0xe5,0x05,0x56,0x05,0x47,0x04,0xe9,0x05,0x62,0x05,0x59,0x04,0xed,0x05,0x22,0x05,0x21,0x05,0x23,0x05,0x24,0x05,0x27,0x05,0x26,0x05,0x25,0x05,0x2f,0x05,0x36,0x05,0x33,0x05,0x2a,0x05,0x09,0x05,0x10,0x05,0x0d, 0x05,0x04,0x05,0x30,0x05,0x37,0x05,0x0a,0x05,0x13,0x04,0xa2,0x04,0x9a,0x04,0x9b,0x04,0x9c,0x04,0x9d,0x04,0x9e,0x04,0x9f,0x04,0xa0,0x04,0xa1,0x04,0xaa,0x04,0xa9,0x04,0xa8,0x04,0xa7,0x04,0xa6,0x04,0xa5,0x04,0xa4,0x04,0xab,0x04,0xb7,0x04,0xb8,0x04,0xb9,0x04,0xa3,0x04,0xd1,0x04,0xd5,0x04,0xdd,0x04,0xe1,0x04,0xd2,0x04,0xd6, 0x04,0xde,0x04,0xe2,0x04,0xd9,0x04,0xdb,0x04,0xd3,0x04,0xd7,0x04,0xdf,0x04,0xe3,0x04,0xd4,0x04,0xd8,0x04,0xe0,0x04,0xe4,0x04,0xda,0x04,0xdc,0x04,0xc4,0x04,0xc5,0x04,0xc6,0x04,0xc1,0x04,0xc7,0x04,0xbb,0x04,0xc0,0x04,0xc2,0x04,0xba,0x03,0x4c,0x03,0x4e,0x03,0x4b,0x03,0x4d,0x03,0x51,0x03,0x54,0x03,0xb6,0x03,0xb9,0x03,0xb4, 0x03,0xb7,0x03,0xb5,0x03,0xb8,0x00,0x0c,0x00,0x00,0x00,0x00,0x33,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x46,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x03,0xc0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x03,0xbe,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x21,0x00,0x00,0x03,0x2e,0x00,0x00,0x00,0x22,0x00,0x00, 0x00,0x22,0x00,0x00,0x03,0x6a,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x23,0x00,0x00,0x03,0x3a,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x24,0x00,0x00,0x03,0xc5,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x25,0x00,0x00,0x04,0x38,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x26,0x00,0x00,0x05,0xb5,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x27,0x00,0x00, 0x03,0x6b,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x29,0x00,0x00,0x03,0x43,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x2a,0x00,0x00,0x03,0x34,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x2b,0x00,0x00,0x04,0x15,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2c,0x00,0x00,0x03,0x2a,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x2d,0x00,0x00,0x03,0x57,0x00,0x00, 0x00,0x2e,0x00,0x00,0x00,0x2e,0x00,0x00,0x03,0x29,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x2f,0x00,0x00,0x03,0x3d,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x39,0x00,0x00,0x02,0xd4,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x3b,0x00,0x00,0x03,0x2b,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x3c,0x00,0x00,0x04,0x1c,0x00,0x00,0x00,0x3d,0x00,0x00, 0x00,0x3d,0x00,0x00,0x04,0x19,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x3e,0x00,0x00,0x04,0x1b,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3f,0x00,0x00,0x03,0x30,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x05,0xb4,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x43,0x00,0x00, 0x00,0x1a,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x43,0x00,0x00, 0x00,0x4a,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x50,0x00,0x00, 0x00,0x50,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x81,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x89,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0x57,0x00,0x00, 0x00,0xa1,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0xa7,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x5b,0x00,0x00,0x03,0x47,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x5c,0x00,0x00,0x03,0x3e,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x5d,0x00,0x00,0x03,0x48,0x00,0x00, 0x00,0x5e,0x00,0x00,0x00,0x5e,0x00,0x00,0x04,0x23,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0x5c,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x06,0x82,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0xbd,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0x64,0x00,0x00, 0x00,0x64,0x00,0x00,0x00,0xdd,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0xe1,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x6a,0x00,0x00, 0x01,0x0d,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x6b,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x01,0x13,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x6e,0x00,0x00,0x01,0x1a,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x6f,0x00,0x00,0x01,0x22,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x00,0x01,0x3d,0x00,0x00, 0x00,0x71,0x00,0x00,0x00,0x72,0x00,0x00,0x01,0x3f,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x73,0x00,0x00,0x01,0x44,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x74,0x00,0x00,0x01,0x4c,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x75,0x00,0x00,0x01,0x51,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x77,0x00,0x00,0x01,0x69,0x00,0x00,0x00,0x78,0x00,0x00, 0x00,0x79,0x00,0x00,0x01,0x6f,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x7a,0x00,0x00,0x01,0x79,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x7b,0x00,0x00,0x03,0x45,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x7c,0x00,0x00,0x05,0xbe,0x00,0x00,0x00,0x7d,0x00,0x00,0x00,0x7d,0x00,0x00,0x03,0x46,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x7e,0x00,0x00, 0x04,0x22,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xa0,0x00,0x00,0x03,0xbf,0x00,0x00,0x00,0xa1,0x00,0x00,0x00,0xa1,0x00,0x00,0x03,0x2f,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0xa2,0x00,0x00,0x03,0xc3,0x00,0x00,0x00,0xa3,0x00,0x00,0x00,0xa3,0x00,0x00,0x03,0xcb,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0xa4,0x00,0x00,0x03,0xc4,0x00,0x00, 0x00,0xa5,0x00,0x00,0x00,0xa5,0x00,0x00,0x03,0xcd,0x00,0x00,0x00,0xa6,0x00,0x00,0x00,0xa6,0x00,0x00,0x05,0xbf,0x00,0x00,0x00,0xa7,0x00,0x00,0x00,0xa7,0x00,0x00,0x05,0xb7,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0xa8,0x00,0x00,0x06,0x80,0x00,0x00,0x00,0xa9,0x00,0x00,0x00,0xa9,0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0xaa,0x00,0x00, 0x00,0xaa,0x00,0x00,0x01,0xc6,0x00,0x00,0x00,0xab,0x00,0x00,0x00,0xab,0x00,0x00,0x03,0x65,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0xac,0x00,0x00,0x04,0x21,0x00,0x00,0x00,0xad,0x00,0x00,0x00,0xad,0x00,0x00,0x03,0x58,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0xae,0x00,0x00,0x05,0xb9,0x00,0x00,0x00,0xaf,0x00,0x00,0x00,0xaf,0x00,0x00, 0x06,0x8a,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,0xb0,0x00,0x00,0x05,0xbb,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0xb1,0x00,0x00,0x04,0x1f,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xb3,0x00,0x00,0x03,0x04,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0xb4,0x00,0x00,0x06,0x83,0x00,0x00,0x00,0xb5,0x00,0x00,0x00,0xb5,0x00,0x00,0x04,0x30,0x00,0x00, 0x00,0xb6,0x00,0x00,0x00,0xb6,0x00,0x00,0x05,0xb6,0x00,0x00,0x00,0xb7,0x00,0x00,0x00,0xb7,0x00,0x00,0x03,0x32,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0xb8,0x00,0x00,0x06,0x8b,0x00,0x00,0x00,0xb9,0x00,0x00,0x00,0xb9,0x00,0x00,0x03,0x03,0x00,0x00,0x00,0xba,0x00,0x00,0x00,0xba,0x00,0x00,0x01,0xc7,0x00,0x00,0x00,0xbb,0x00,0x00, 0x00,0xbb,0x00,0x00,0x03,0x66,0x00,0x00,0x00,0xbc,0x00,0x00,0x00,0xbc,0x00,0x00,0x03,0x22,0x00,0x00,0x00,0xbd,0x00,0x00,0x00,0xbd,0x00,0x00,0x03,0x21,0x00,0x00,0x00,0xbe,0x00,0x00,0x00,0xbe,0x00,0x00,0x03,0x23,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0xbf,0x00,0x00,0x03,0x31,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xc0,0x00,0x00, 0x00,0x12,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0xc5,0x00,0x00,0x00,0x16,0x00,0x00, 0x00,0xc6,0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0xca,0x00,0x00,0x00,0xca,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0xcb,0x00,0x00, 0x00,0xcb,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0xcd,0x00,0x00,0x00,0xcd,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0xce,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0xd1,0x00,0x00, 0x00,0x5f,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0xd3,0x00,0x00,0x00,0xd3,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0xd5,0x00,0x00,0x00,0xd5,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0xd6,0x00,0x00,0x00,0x69,0x00,0x00, 0x00,0xd7,0x00,0x00,0x00,0xd7,0x00,0x00,0x04,0x17,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0xda,0x00,0x00,0x00,0xda,0x00,0x00,0x00,0x8f,0x00,0x00,0x00,0xdb,0x00,0x00,0x00,0xdc,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0xdd,0x00,0x00, 0x00,0xdd,0x00,0x00,0x00,0xa9,0x00,0x00,0x00,0xde,0x00,0x00,0x00,0xde,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0xdf,0x00,0x00,0x00,0xdf,0x00,0x00,0x01,0x4a,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0xce,0x00,0x00,0x00,0xe1,0x00,0x00,0x00,0xe1,0x00,0x00,0x00,0xbe,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0xe2,0x00,0x00, 0x00,0xc6,0x00,0x00,0x00,0xe3,0x00,0x00,0x00,0xe3,0x00,0x00,0x00,0xd3,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0xe5,0x00,0x00,0x00,0xe5,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0xe6,0x00,0x00,0x00,0xe6,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0xe7,0x00,0x00,0x00,0xe7,0x00,0x00,0x00,0xda,0x00,0x00, 0x00,0xe8,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0xee,0x00,0x00,0x00,0xe9,0x00,0x00,0x00,0xe9,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0xea,0x00,0x00,0x00,0xea,0x00,0x00,0x00,0xe5,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0xec,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0xed,0x00,0x00, 0x00,0xed,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0xee,0x00,0x00,0x00,0xef,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xde,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0xf1,0x00,0x00,0x01,0x21,0x00,0x00,0x00,0xf2,0x00,0x00,0x00,0xf2,0x00,0x00,0x01,0x2e,0x00,0x00,0x00,0xf3,0x00,0x00,0x00,0xf3,0x00,0x00, 0x01,0x23,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0xf4,0x00,0x00,0x01,0x26,0x00,0x00,0x00,0xf5,0x00,0x00,0x00,0xf5,0x00,0x00,0x01,0x3b,0x00,0x00,0x00,0xf6,0x00,0x00,0x00,0xf6,0x00,0x00,0x01,0x2c,0x00,0x00,0x00,0xf7,0x00,0x00,0x00,0xf7,0x00,0x00,0x04,0x18,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xf8,0x00,0x00,0x01,0x39,0x00,0x00, 0x00,0xf9,0x00,0x00,0x00,0xf9,0x00,0x00,0x01,0x5c,0x00,0x00,0x00,0xfa,0x00,0x00,0x00,0xfa,0x00,0x00,0x01,0x52,0x00,0x00,0x00,0xfb,0x00,0x00,0x00,0xfc,0x00,0x00,0x01,0x55,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,0xfd,0x00,0x00,0x01,0x71,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x01,0x3e,0x00,0x00,0x00,0xff,0x00,0x00, 0x00,0xff,0x00,0x00,0x01,0x73,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x01,0x03,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0xbf,0x00,0x00,0x01,0x04,0x00,0x00,0x01,0x04,0x00,0x00, 0x00,0x15,0x00,0x00,0x01,0x05,0x00,0x00,0x01,0x05,0x00,0x00,0x00,0xd1,0x00,0x00,0x01,0x06,0x00,0x00,0x01,0x06,0x00,0x00,0x00,0x1c,0x00,0x00,0x01,0x07,0x00,0x00,0x01,0x07,0x00,0x00,0x00,0xd8,0x00,0x00,0x01,0x08,0x00,0x00,0x01,0x08,0x00,0x00,0x00,0x1f,0x00,0x00,0x01,0x09,0x00,0x00,0x01,0x09,0x00,0x00,0x00,0xdb,0x00,0x00, 0x01,0x0a,0x00,0x00,0x01,0x0a,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0x0b,0x00,0x00,0x01,0x0b,0x00,0x00,0x00,0xdc,0x00,0x00,0x01,0x0c,0x00,0x00,0x01,0x0c,0x00,0x00,0x00,0x1d,0x00,0x00,0x01,0x0d,0x00,0x00,0x01,0x0d,0x00,0x00,0x00,0xd9,0x00,0x00,0x01,0x0e,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x23,0x00,0x00,0x01,0x0f,0x00,0x00, 0x01,0x0f,0x00,0x00,0x00,0xdf,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x24,0x00,0x00,0x01,0x11,0x00,0x00,0x01,0x11,0x00,0x00,0x00,0xe0,0x00,0x00,0x01,0x12,0x00,0x00,0x01,0x12,0x00,0x00,0x00,0x34,0x00,0x00,0x01,0x13,0x00,0x00,0x01,0x13,0x00,0x00,0x00,0xf0,0x00,0x00,0x01,0x14,0x00,0x00,0x01,0x14,0x00,0x00, 0x00,0x27,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x15,0x00,0x00,0x00,0xe3,0x00,0x00,0x01,0x16,0x00,0x00,0x01,0x16,0x00,0x00,0x00,0x30,0x00,0x00,0x01,0x17,0x00,0x00,0x01,0x17,0x00,0x00,0x00,0xec,0x00,0x00,0x01,0x18,0x00,0x00,0x01,0x18,0x00,0x00,0x00,0x35,0x00,0x00,0x01,0x19,0x00,0x00,0x01,0x19,0x00,0x00,0x00,0xf1,0x00,0x00, 0x01,0x1a,0x00,0x00,0x01,0x1a,0x00,0x00,0x00,0x28,0x00,0x00,0x01,0x1b,0x00,0x00,0x01,0x1b,0x00,0x00,0x00,0xe4,0x00,0x00,0x01,0x1c,0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x3d,0x00,0x00,0x01,0x1d,0x00,0x00,0x01,0x1d,0x00,0x00,0x00,0xf9,0x00,0x00,0x01,0x1e,0x00,0x00,0x01,0x1e,0x00,0x00,0x00,0x3b,0x00,0x00,0x01,0x1f,0x00,0x00, 0x01,0x1f,0x00,0x00,0x00,0xf7,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x3f,0x00,0x00,0x01,0x21,0x00,0x00,0x01,0x21,0x00,0x00,0x00,0xfb,0x00,0x00,0x01,0x22,0x00,0x00,0x01,0x22,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x23,0x00,0x00,0x01,0x23,0x00,0x00,0x00,0xfa,0x00,0x00,0x01,0x24,0x00,0x00,0x01,0x24,0x00,0x00, 0x00,0x42,0x00,0x00,0x01,0x25,0x00,0x00,0x01,0x25,0x00,0x00,0x00,0xfe,0x00,0x00,0x01,0x26,0x00,0x00,0x01,0x26,0x00,0x00,0x00,0x41,0x00,0x00,0x01,0x27,0x00,0x00,0x01,0x27,0x00,0x00,0x00,0xfd,0x00,0x00,0x01,0x28,0x00,0x00,0x01,0x28,0x00,0x00,0x00,0x4e,0x00,0x00,0x01,0x29,0x00,0x00,0x01,0x29,0x00,0x00,0x01,0x0c,0x00,0x00, 0x01,0x2a,0x00,0x00,0x01,0x2a,0x00,0x00,0x00,0x4c,0x00,0x00,0x01,0x2b,0x00,0x00,0x01,0x2b,0x00,0x00,0x01,0x0a,0x00,0x00,0x01,0x2c,0x00,0x00,0x01,0x2c,0x00,0x00,0x00,0x45,0x00,0x00,0x01,0x2d,0x00,0x00,0x01,0x2d,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x2e,0x00,0x00,0x01,0x2e,0x00,0x00,0x00,0x4d,0x00,0x00,0x01,0x2f,0x00,0x00, 0x01,0x2f,0x00,0x00,0x01,0x0b,0x00,0x00,0x01,0x30,0x00,0x00,0x01,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x01,0x31,0x00,0x00,0x01,0x31,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x34,0x00,0x00,0x01,0x34,0x00,0x00,0x00,0x50,0x00,0x00,0x01,0x35,0x00,0x00,0x01,0x35,0x00,0x00,0x01,0x0f,0x00,0x00,0x01,0x36,0x00,0x00,0x01,0x36,0x00,0x00, 0x00,0x52,0x00,0x00,0x01,0x37,0x00,0x00,0x01,0x38,0x00,0x00,0x01,0x11,0x00,0x00,0x01,0x39,0x00,0x00,0x01,0x39,0x00,0x00,0x00,0x54,0x00,0x00,0x01,0x3a,0x00,0x00,0x01,0x3a,0x00,0x00,0x01,0x14,0x00,0x00,0x01,0x3b,0x00,0x00,0x01,0x3b,0x00,0x00,0x00,0x56,0x00,0x00,0x01,0x3c,0x00,0x00,0x01,0x3c,0x00,0x00,0x01,0x17,0x00,0x00, 0x01,0x3d,0x00,0x00,0x01,0x3d,0x00,0x00,0x00,0x55,0x00,0x00,0x01,0x3e,0x00,0x00,0x01,0x3e,0x00,0x00,0x01,0x16,0x00,0x00,0x01,0x3f,0x00,0x00,0x01,0x3f,0x00,0x00,0x00,0x57,0x00,0x00,0x01,0x40,0x00,0x00,0x01,0x40,0x00,0x00,0x01,0x18,0x00,0x00,0x01,0x41,0x00,0x00,0x01,0x41,0x00,0x00,0x00,0x58,0x00,0x00,0x01,0x42,0x00,0x00, 0x01,0x42,0x00,0x00,0x01,0x19,0x00,0x00,0x01,0x43,0x00,0x00,0x01,0x43,0x00,0x00,0x00,0x5b,0x00,0x00,0x01,0x44,0x00,0x00,0x01,0x44,0x00,0x00,0x01,0x1c,0x00,0x00,0x01,0x45,0x00,0x00,0x01,0x45,0x00,0x00,0x00,0x5d,0x00,0x00,0x01,0x46,0x00,0x00,0x01,0x46,0x00,0x00,0x01,0x1f,0x00,0x00,0x01,0x47,0x00,0x00,0x01,0x47,0x00,0x00, 0x00,0x5c,0x00,0x00,0x01,0x48,0x00,0x00,0x01,0x48,0x00,0x00,0x01,0x1e,0x00,0x00,0x01,0x49,0x00,0x00,0x01,0x49,0x00,0x00,0x01,0x1d,0x00,0x00,0x01,0x4a,0x00,0x00,0x01,0x4a,0x00,0x00,0x00,0x5e,0x00,0x00,0x01,0x4b,0x00,0x00,0x01,0x4b,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x4c,0x00,0x00,0x01,0x4c,0x00,0x00,0x00,0x74,0x00,0x00, 0x01,0x4d,0x00,0x00,0x01,0x4d,0x00,0x00,0x01,0x37,0x00,0x00,0x01,0x4e,0x00,0x00,0x01,0x4e,0x00,0x00,0x00,0x62,0x00,0x00,0x01,0x4f,0x00,0x00,0x01,0x4f,0x00,0x00,0x01,0x24,0x00,0x00,0x01,0x50,0x00,0x00,0x01,0x50,0x00,0x00,0x00,0x73,0x00,0x00,0x01,0x51,0x00,0x00,0x01,0x51,0x00,0x00,0x01,0x36,0x00,0x00,0x01,0x52,0x00,0x00, 0x01,0x52,0x00,0x00,0x00,0x79,0x00,0x00,0x01,0x53,0x00,0x00,0x01,0x53,0x00,0x00,0x01,0x3c,0x00,0x00,0x01,0x54,0x00,0x00,0x01,0x54,0x00,0x00,0x00,0x7e,0x00,0x00,0x01,0x55,0x00,0x00,0x01,0x55,0x00,0x00,0x01,0x41,0x00,0x00,0x01,0x56,0x00,0x00,0x01,0x56,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0x57,0x00,0x00,0x01,0x57,0x00,0x00, 0x01,0x43,0x00,0x00,0x01,0x58,0x00,0x00,0x01,0x58,0x00,0x00,0x00,0x7f,0x00,0x00,0x01,0x59,0x00,0x00,0x01,0x59,0x00,0x00,0x01,0x42,0x00,0x00,0x01,0x5a,0x00,0x00,0x01,0x5a,0x00,0x00,0x00,0x82,0x00,0x00,0x01,0x5b,0x00,0x00,0x01,0x5b,0x00,0x00,0x01,0x45,0x00,0x00,0x01,0x5c,0x00,0x00,0x01,0x5c,0x00,0x00,0x00,0x85,0x00,0x00, 0x01,0x5d,0x00,0x00,0x01,0x5d,0x00,0x00,0x01,0x48,0x00,0x00,0x01,0x5e,0x00,0x00,0x01,0x5e,0x00,0x00,0x00,0x84,0x00,0x00,0x01,0x5f,0x00,0x00,0x01,0x5f,0x00,0x00,0x01,0x47,0x00,0x00,0x01,0x60,0x00,0x00,0x01,0x60,0x00,0x00,0x00,0x83,0x00,0x00,0x01,0x61,0x00,0x00,0x01,0x61,0x00,0x00,0x01,0x46,0x00,0x00,0x01,0x62,0x00,0x00, 0x01,0x62,0x00,0x00,0x00,0x8c,0x00,0x00,0x01,0x63,0x00,0x00,0x01,0x63,0x00,0x00,0x01,0x4f,0x00,0x00,0x01,0x64,0x00,0x00,0x01,0x64,0x00,0x00,0x00,0x8b,0x00,0x00,0x01,0x65,0x00,0x00,0x01,0x65,0x00,0x00,0x01,0x4e,0x00,0x00,0x01,0x66,0x00,0x00,0x01,0x66,0x00,0x00,0x00,0x8a,0x00,0x00,0x01,0x67,0x00,0x00,0x01,0x67,0x00,0x00, 0x01,0x4d,0x00,0x00,0x01,0x68,0x00,0x00,0x01,0x68,0x00,0x00,0x00,0xa0,0x00,0x00,0x01,0x69,0x00,0x00,0x01,0x69,0x00,0x00,0x01,0x68,0x00,0x00,0x01,0x6a,0x00,0x00,0x01,0x6a,0x00,0x00,0x00,0x9d,0x00,0x00,0x01,0x6b,0x00,0x00,0x01,0x6b,0x00,0x00,0x01,0x65,0x00,0x00,0x01,0x6c,0x00,0x00,0x01,0x6c,0x00,0x00,0x00,0x90,0x00,0x00, 0x01,0x6d,0x00,0x00,0x01,0x6d,0x00,0x00,0x01,0x53,0x00,0x00,0x01,0x6e,0x00,0x00,0x01,0x6e,0x00,0x00,0x00,0x9f,0x00,0x00,0x01,0x6f,0x00,0x00,0x01,0x6f,0x00,0x00,0x01,0x67,0x00,0x00,0x01,0x70,0x00,0x00,0x01,0x70,0x00,0x00,0x00,0x9c,0x00,0x00,0x01,0x71,0x00,0x00,0x01,0x71,0x00,0x00,0x01,0x64,0x00,0x00,0x01,0x72,0x00,0x00, 0x01,0x72,0x00,0x00,0x00,0x9e,0x00,0x00,0x01,0x73,0x00,0x00,0x01,0x73,0x00,0x00,0x01,0x66,0x00,0x00,0x01,0x74,0x00,0x00,0x01,0x74,0x00,0x00,0x00,0xa4,0x00,0x00,0x01,0x75,0x00,0x00,0x01,0x75,0x00,0x00,0x01,0x6c,0x00,0x00,0x01,0x76,0x00,0x00,0x01,0x76,0x00,0x00,0x00,0xaa,0x00,0x00,0x01,0x77,0x00,0x00,0x01,0x77,0x00,0x00, 0x01,0x72,0x00,0x00,0x01,0x78,0x00,0x00,0x01,0x78,0x00,0x00,0x00,0xab,0x00,0x00,0x01,0x79,0x00,0x00,0x01,0x79,0x00,0x00,0x00,0xb2,0x00,0x00,0x01,0x7a,0x00,0x00,0x01,0x7a,0x00,0x00,0x01,0x7a,0x00,0x00,0x01,0x7b,0x00,0x00,0x01,0x7b,0x00,0x00,0x00,0xb4,0x00,0x00,0x01,0x7c,0x00,0x00,0x01,0x7c,0x00,0x00,0x01,0x7c,0x00,0x00, 0x01,0x7d,0x00,0x00,0x01,0x7d,0x00,0x00,0x00,0xb3,0x00,0x00,0x01,0x7e,0x00,0x00,0x01,0x7e,0x00,0x00,0x01,0x7b,0x00,0x00,0x01,0x7f,0x00,0x00,0x01,0x7f,0x00,0x00,0x01,0x4b,0x00,0x00,0x01,0x8f,0x00,0x00,0x01,0x8f,0x00,0x00,0x00,0x88,0x00,0x00,0x01,0x90,0x00,0x00,0x01,0x90,0x00,0x00,0x00,0x36,0x00,0x00,0x01,0x92,0x00,0x00, 0x01,0x92,0x00,0x00,0x03,0xc8,0x00,0x00,0x01,0x9b,0x00,0x00,0x01,0x9b,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0xa0,0x00,0x00,0x01,0xa0,0x00,0x00,0x00,0x6d,0x00,0x00,0x01,0xa1,0x00,0x00,0x01,0xa1,0x00,0x00,0x01,0x30,0x00,0x00,0x01,0xaf,0x00,0x00,0x01,0xaf,0x00,0x00,0x00,0x96,0x00,0x00,0x01,0xb0,0x00,0x00,0x01,0xb0,0x00,0x00, 0x01,0x5e,0x00,0x00,0x01,0xcd,0x00,0x00,0x01,0xcd,0x00,0x00,0x00,0x09,0x00,0x00,0x01,0xce,0x00,0x00,0x01,0xce,0x00,0x00,0x00,0xc5,0x00,0x00,0x01,0xd0,0x00,0x00,0x01,0xd0,0x00,0x00,0x01,0x03,0x00,0x00,0x01,0xd2,0x00,0x00,0x01,0xd2,0x00,0x00,0x01,0x25,0x00,0x00,0x01,0xd4,0x00,0x00,0x01,0xd4,0x00,0x00,0x01,0x54,0x00,0x00, 0x01,0xd6,0x00,0x00,0x01,0xd6,0x00,0x00,0x01,0x5a,0x00,0x00,0x01,0xd8,0x00,0x00,0x01,0xd8,0x00,0x00,0x01,0x57,0x00,0x00,0x01,0xda,0x00,0x00,0x01,0xda,0x00,0x00,0x01,0x58,0x00,0x00,0x01,0xdc,0x00,0x00,0x01,0xdc,0x00,0x00,0x01,0x59,0x00,0x00,0x01,0xe6,0x00,0x00,0x01,0xe6,0x00,0x00,0x00,0x3c,0x00,0x00,0x01,0xe7,0x00,0x00, 0x01,0xe7,0x00,0x00,0x00,0xf8,0x00,0x00,0x01,0xea,0x00,0x00,0x01,0xea,0x00,0x00,0x00,0x75,0x00,0x00,0x01,0xeb,0x00,0x00,0x01,0xeb,0x00,0x00,0x01,0x38,0x00,0x00,0x01,0xf4,0x00,0x00,0x01,0xf4,0x00,0x00,0x00,0x3a,0x00,0x00,0x01,0xf5,0x00,0x00,0x01,0xf5,0x00,0x00,0x00,0xf6,0x00,0x00,0x01,0xfc,0x00,0x00,0x01,0xfc,0x00,0x00, 0x00,0x19,0x00,0x00,0x01,0xfd,0x00,0x00,0x01,0xfd,0x00,0x00,0x00,0xd5,0x00,0x00,0x01,0xfe,0x00,0x00,0x01,0xfe,0x00,0x00,0x00,0x77,0x00,0x00,0x01,0xff,0x00,0x00,0x01,0xff,0x00,0x00,0x01,0x3a,0x00,0x00,0x02,0x18,0x00,0x00,0x02,0x18,0x00,0x00,0x00,0x86,0x00,0x00,0x02,0x19,0x00,0x00,0x02,0x19,0x00,0x00,0x01,0x49,0x00,0x00, 0x02,0x1a,0x00,0x00,0x02,0x1a,0x00,0x00,0x00,0x8d,0x00,0x00,0x02,0x1b,0x00,0x00,0x02,0x1b,0x00,0x00,0x01,0x50,0x00,0x00,0x02,0x32,0x00,0x00,0x02,0x32,0x00,0x00,0x00,0xaf,0x00,0x00,0x02,0x33,0x00,0x00,0x02,0x33,0x00,0x00,0x01,0x77,0x00,0x00,0x02,0x37,0x00,0x00,0x02,0x37,0x00,0x00,0x01,0x0e,0x00,0x00,0x02,0x59,0x00,0x00, 0x02,0x59,0x00,0x00,0x00,0xf3,0x00,0x00,0x02,0xb9,0x00,0x00,0x02,0xb9,0x00,0x00,0x06,0x67,0x00,0x00,0x02,0xba,0x00,0x00,0x02,0xba,0x00,0x00,0x06,0x65,0x00,0x00,0x02,0xbc,0x00,0x00,0x02,0xbc,0x00,0x00,0x06,0x64,0x00,0x00,0x02,0xc6,0x00,0x00,0x02,0xc7,0x00,0x00,0x06,0x85,0x00,0x00,0x02,0xc9,0x00,0x00,0x02,0xc9,0x00,0x00, 0x06,0x66,0x00,0x00,0x02,0xd8,0x00,0x00,0x02,0xd8,0x00,0x00,0x06,0x87,0x00,0x00,0x02,0xd9,0x00,0x00,0x02,0xd9,0x00,0x00,0x06,0x81,0x00,0x00,0x02,0xda,0x00,0x00,0x02,0xda,0x00,0x00,0x06,0x88,0x00,0x00,0x02,0xdb,0x00,0x00,0x02,0xdb,0x00,0x00,0x06,0x8c,0x00,0x00,0x02,0xdc,0x00,0x00,0x02,0xdc,0x00,0x00,0x06,0x89,0x00,0x00, 0x02,0xdd,0x00,0x00,0x02,0xdd,0x00,0x00,0x06,0x84,0x00,0x00,0x02,0xf3,0x00,0x00,0x02,0xf3,0x00,0x00,0x06,0x03,0x00,0x00,0x02,0xf7,0x00,0x00,0x02,0xf7,0x00,0x00,0x06,0x04,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x01,0x00,0x00,0x06,0x6a,0x00,0x00,0x03,0x02,0x00,0x00,0x03,0x02,0x00,0x00,0x06,0x6e,0x00,0x00,0x03,0x03,0x00,0x00, 0x03,0x04,0x00,0x00,0x06,0x72,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x06,0x70,0x00,0x00,0x03,0x07,0x00,0x00,0x03,0x07,0x00,0x00,0x06,0x69,0x00,0x00,0x03,0x08,0x00,0x00,0x03,0x08,0x00,0x00,0x06,0x68,0x00,0x00,0x03,0x09,0x00,0x00,0x03,0x09,0x00,0x00,0x06,0x74,0x00,0x00,0x03,0x0a,0x00,0x00,0x03,0x0a,0x00,0x00, 0x06,0x71,0x00,0x00,0x03,0x0b,0x00,0x00,0x03,0x0b,0x00,0x00,0x06,0x6c,0x00,0x00,0x03,0x0c,0x00,0x00,0x03,0x0c,0x00,0x00,0x06,0x6f,0x00,0x00,0x03,0x0f,0x00,0x00,0x03,0x0f,0x00,0x00,0x06,0x75,0x00,0x00,0x03,0x12,0x00,0x00,0x03,0x12,0x00,0x00,0x06,0x76,0x00,0x00,0x03,0x1b,0x00,0x00,0x03,0x1b,0x00,0x00,0x06,0x77,0x00,0x00, 0x03,0x23,0x00,0x00,0x03,0x23,0x00,0x00,0x06,0x78,0x00,0x00,0x03,0x25,0x00,0x00,0x03,0x28,0x00,0x00,0x06,0x79,0x00,0x00,0x03,0x36,0x00,0x00,0x03,0x38,0x00,0x00,0x06,0x7d,0x00,0x00,0x03,0x74,0x00,0x00,0x03,0x75,0x00,0x00,0x06,0x62,0x00,0x00,0x03,0x7e,0x00,0x00,0x03,0x7e,0x00,0x00,0x03,0xbb,0x00,0x00,0x03,0x84,0x00,0x00, 0x03,0x84,0x00,0x00,0x06,0xb0,0x00,0x00,0x03,0x85,0x00,0x00,0x03,0x85,0x00,0x00,0x06,0xb2,0x00,0x00,0x03,0x86,0x00,0x00,0x03,0x86,0x00,0x00,0x02,0x69,0x00,0x00,0x03,0x87,0x00,0x00,0x03,0x87,0x00,0x00,0x03,0xba,0x00,0x00,0x03,0x88,0x00,0x00,0x03,0x8a,0x00,0x00,0x02,0x6a,0x00,0x00,0x03,0x8c,0x00,0x00,0x03,0x8c,0x00,0x00, 0x02,0x6d,0x00,0x00,0x03,0x8e,0x00,0x00,0x03,0x8f,0x00,0x00,0x02,0x6e,0x00,0x00,0x03,0x90,0x00,0x00,0x03,0x90,0x00,0x00,0x02,0x90,0x00,0x00,0x03,0x91,0x00,0x00,0x03,0xa1,0x00,0x00,0x02,0x51,0x00,0x00,0x03,0xa3,0x00,0x00,0x03,0xa9,0x00,0x00,0x02,0x62,0x00,0x00,0x03,0xaa,0x00,0x00,0x03,0xab,0x00,0x00,0x02,0x70,0x00,0x00, 0x03,0xac,0x00,0x00,0x03,0xae,0x00,0x00,0x02,0x96,0x00,0x00,0x03,0xaf,0x00,0x00,0x03,0xaf,0x00,0x00,0x02,0x8e,0x00,0x00,0x03,0xb0,0x00,0x00,0x03,0xb0,0x00,0x00,0x02,0x93,0x00,0x00,0x03,0xb1,0x00,0x00,0x03,0xc9,0x00,0x00,0x02,0x75,0x00,0x00,0x03,0xca,0x00,0x00,0x03,0xca,0x00,0x00,0x02,0x8f,0x00,0x00,0x03,0xcb,0x00,0x00, 0x03,0xcb,0x00,0x00,0x02,0x92,0x00,0x00,0x03,0xcc,0x00,0x00,0x03,0xcc,0x00,0x00,0x02,0x94,0x00,0x00,0x03,0xcd,0x00,0x00,0x03,0xcd,0x00,0x00,0x02,0x91,0x00,0x00,0x03,0xce,0x00,0x00,0x03,0xce,0x00,0x00,0x02,0x95,0x00,0x00,0x03,0xcf,0x00,0x00,0x03,0xcf,0x00,0x00,0x02,0x72,0x00,0x00,0x03,0xd5,0x00,0x00,0x03,0xd6,0x00,0x00, 0x02,0x9a,0x00,0x00,0x03,0xd7,0x00,0x00,0x03,0xd7,0x00,0x00,0x02,0x99,0x00,0x00,0x04,0x01,0x00,0x00,0x04,0x01,0x00,0x00,0x01,0xd0,0x00,0x00,0x04,0x02,0x00,0x00,0x04,0x02,0x00,0x00,0x01,0xf6,0x00,0x00,0x04,0x03,0x00,0x00,0x04,0x03,0x00,0x00,0x01,0xcc,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x01,0xee,0x00,0x00, 0x04,0x05,0x00,0x00,0x04,0x05,0x00,0x00,0x01,0xed,0x00,0x00,0x04,0x06,0x00,0x00,0x04,0x08,0x00,0x00,0x01,0xf0,0x00,0x00,0x04,0x09,0x00,0x00,0x04,0x0a,0x00,0x00,0x01,0xeb,0x00,0x00,0x04,0x0b,0x00,0x00,0x04,0x0b,0x00,0x00,0x01,0xf3,0x00,0x00,0x04,0x0c,0x00,0x00,0x04,0x0c,0x00,0x00,0x01,0xd6,0x00,0x00,0x04,0x0e,0x00,0x00, 0x04,0x0e,0x00,0x00,0x01,0xe0,0x00,0x00,0x04,0x0f,0x00,0x00,0x04,0x0f,0x00,0x00,0x01,0xe7,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x13,0x00,0x00,0x01,0xc8,0x00,0x00,0x04,0x14,0x00,0x00,0x04,0x15,0x00,0x00,0x01,0xce,0x00,0x00,0x04,0x16,0x00,0x00,0x04,0x1a,0x00,0x00,0x01,0xd1,0x00,0x00,0x04,0x1b,0x00,0x00,0x04,0x23,0x00,0x00, 0x01,0xd7,0x00,0x00,0x04,0x24,0x00,0x00,0x04,0x25,0x00,0x00,0x01,0xe1,0x00,0x00,0x04,0x26,0x00,0x00,0x04,0x26,0x00,0x00,0x01,0xe4,0x00,0x00,0x04,0x27,0x00,0x00,0x04,0x27,0x00,0x00,0x01,0xe3,0x00,0x00,0x04,0x28,0x00,0x00,0x04,0x29,0x00,0x00,0x01,0xe5,0x00,0x00,0x04,0x2a,0x00,0x00,0x04,0x2b,0x00,0x00,0x01,0xe9,0x00,0x00, 0x04,0x2c,0x00,0x00,0x04,0x2c,0x00,0x00,0x01,0xe8,0x00,0x00,0x04,0x2d,0x00,0x00,0x04,0x2d,0x00,0x00,0x01,0xef,0x00,0x00,0x04,0x2e,0x00,0x00,0x04,0x2f,0x00,0x00,0x01,0xf4,0x00,0x00,0x04,0x30,0x00,0x00,0x04,0x33,0x00,0x00,0x02,0x0c,0x00,0x00,0x04,0x34,0x00,0x00,0x04,0x35,0x00,0x00,0x02,0x12,0x00,0x00,0x04,0x36,0x00,0x00, 0x04,0x3a,0x00,0x00,0x02,0x15,0x00,0x00,0x04,0x3b,0x00,0x00,0x04,0x43,0x00,0x00,0x02,0x1b,0x00,0x00,0x04,0x44,0x00,0x00,0x04,0x45,0x00,0x00,0x02,0x25,0x00,0x00,0x04,0x46,0x00,0x00,0x04,0x46,0x00,0x00,0x02,0x28,0x00,0x00,0x04,0x47,0x00,0x00,0x04,0x47,0x00,0x00,0x02,0x27,0x00,0x00,0x04,0x48,0x00,0x00,0x04,0x49,0x00,0x00, 0x02,0x29,0x00,0x00,0x04,0x4a,0x00,0x00,0x04,0x4b,0x00,0x00,0x02,0x2d,0x00,0x00,0x04,0x4c,0x00,0x00,0x04,0x4c,0x00,0x00,0x02,0x2c,0x00,0x00,0x04,0x4d,0x00,0x00,0x04,0x4d,0x00,0x00,0x02,0x33,0x00,0x00,0x04,0x4e,0x00,0x00,0x04,0x4f,0x00,0x00,0x02,0x38,0x00,0x00,0x04,0x51,0x00,0x00,0x04,0x51,0x00,0x00,0x02,0x14,0x00,0x00, 0x04,0x52,0x00,0x00,0x04,0x52,0x00,0x00,0x02,0x3a,0x00,0x00,0x04,0x53,0x00,0x00,0x04,0x53,0x00,0x00,0x02,0x10,0x00,0x00,0x04,0x54,0x00,0x00,0x04,0x54,0x00,0x00,0x02,0x32,0x00,0x00,0x04,0x55,0x00,0x00,0x04,0x55,0x00,0x00,0x02,0x31,0x00,0x00,0x04,0x56,0x00,0x00,0x04,0x58,0x00,0x00,0x02,0x34,0x00,0x00,0x04,0x59,0x00,0x00, 0x04,0x5a,0x00,0x00,0x02,0x2f,0x00,0x00,0x04,0x5b,0x00,0x00,0x04,0x5b,0x00,0x00,0x02,0x37,0x00,0x00,0x04,0x5c,0x00,0x00,0x04,0x5c,0x00,0x00,0x02,0x1a,0x00,0x00,0x04,0x5e,0x00,0x00,0x04,0x5e,0x00,0x00,0x02,0x24,0x00,0x00,0x04,0x5f,0x00,0x00,0x04,0x5f,0x00,0x00,0x02,0x2b,0x00,0x00,0x04,0x90,0x00,0x00,0x04,0x90,0x00,0x00, 0x01,0xcd,0x00,0x00,0x04,0x91,0x00,0x00,0x04,0x91,0x00,0x00,0x02,0x11,0x00,0x00,0x04,0x92,0x00,0x00,0x04,0x92,0x00,0x00,0x01,0xf7,0x00,0x00,0x04,0x93,0x00,0x00,0x04,0x93,0x00,0x00,0x02,0x3b,0x00,0x00,0x04,0x9a,0x00,0x00,0x04,0x9a,0x00,0x00,0x01,0xf8,0x00,0x00,0x04,0x9b,0x00,0x00,0x04,0x9b,0x00,0x00,0x02,0x3c,0x00,0x00, 0x04,0xa2,0x00,0x00,0x04,0xa2,0x00,0x00,0x01,0xf9,0x00,0x00,0x04,0xa3,0x00,0x00,0x04,0xa3,0x00,0x00,0x02,0x3d,0x00,0x00,0x04,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x01,0xfa,0x00,0x00,0x04,0xaf,0x00,0x00,0x04,0xaf,0x00,0x00,0x02,0x3e,0x00,0x00,0x04,0xb0,0x00,0x00,0x04,0xb0,0x00,0x00,0x01,0xfb,0x00,0x00,0x04,0xb1,0x00,0x00, 0x04,0xb1,0x00,0x00,0x02,0x3f,0x00,0x00,0x04,0xb6,0x00,0x00,0x04,0xb6,0x00,0x00,0x01,0xfc,0x00,0x00,0x04,0xb7,0x00,0x00,0x04,0xb7,0x00,0x00,0x02,0x40,0x00,0x00,0x04,0xba,0x00,0x00,0x04,0xba,0x00,0x00,0x01,0xfd,0x00,0x00,0x04,0xbb,0x00,0x00,0x04,0xbb,0x00,0x00,0x02,0x41,0x00,0x00,0x04,0xd8,0x00,0x00,0x04,0xd8,0x00,0x00, 0x01,0xfe,0x00,0x00,0x04,0xd9,0x00,0x00,0x04,0xd9,0x00,0x00,0x02,0x42,0x00,0x00,0x04,0xdc,0x00,0x00,0x04,0xdc,0x00,0x00,0x01,0xff,0x00,0x00,0x04,0xdd,0x00,0x00,0x04,0xdd,0x00,0x00,0x02,0x43,0x00,0x00,0x04,0xde,0x00,0x00,0x04,0xde,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0xdf,0x00,0x00,0x04,0xdf,0x00,0x00,0x02,0x44,0x00,0x00, 0x04,0xe4,0x00,0x00,0x04,0xe4,0x00,0x00,0x02,0x01,0x00,0x00,0x04,0xe5,0x00,0x00,0x04,0xe5,0x00,0x00,0x02,0x45,0x00,0x00,0x04,0xe6,0x00,0x00,0x04,0xe6,0x00,0x00,0x02,0x02,0x00,0x00,0x04,0xe7,0x00,0x00,0x04,0xe7,0x00,0x00,0x02,0x46,0x00,0x00,0x04,0xe8,0x00,0x00,0x04,0xe8,0x00,0x00,0x02,0x03,0x00,0x00,0x04,0xe9,0x00,0x00, 0x04,0xe9,0x00,0x00,0x02,0x47,0x00,0x00,0x04,0xf4,0x00,0x00,0x04,0xf4,0x00,0x00,0x02,0x04,0x00,0x00,0x04,0xf5,0x00,0x00,0x04,0xf5,0x00,0x00,0x02,0x48,0x00,0x00,0x0a,0xea,0x00,0x00,0x0a,0xea,0x00,0x00,0x03,0x28,0x00,0x00,0x1e,0x80,0x00,0x00,0x1e,0x80,0x00,0x00,0x00,0xa6,0x00,0x00,0x1e,0x81,0x00,0x00,0x1e,0x81,0x00,0x00, 0x01,0x6e,0x00,0x00,0x1e,0x82,0x00,0x00,0x1e,0x82,0x00,0x00,0x00,0xa3,0x00,0x00,0x1e,0x83,0x00,0x00,0x1e,0x83,0x00,0x00,0x01,0x6b,0x00,0x00,0x1e,0x84,0x00,0x00,0x1e,0x84,0x00,0x00,0x00,0xa5,0x00,0x00,0x1e,0x85,0x00,0x00,0x1e,0x85,0x00,0x00,0x01,0x6d,0x00,0x00,0x1e,0x9e,0x00,0x00,0x1e,0x9e,0x00,0x00,0x00,0x87,0x00,0x00, 0x1e,0xa0,0x00,0x00,0x1e,0xa0,0x00,0x00,0x00,0x11,0x00,0x00,0x1e,0xa1,0x00,0x00,0x1e,0xa1,0x00,0x00,0x00,0xcd,0x00,0x00,0x1e,0xa2,0x00,0x00,0x1e,0xa2,0x00,0x00,0x00,0x13,0x00,0x00,0x1e,0xa3,0x00,0x00,0x1e,0xa3,0x00,0x00,0x00,0xcf,0x00,0x00,0x1e,0xa4,0x00,0x00,0x1e,0xa4,0x00,0x00,0x00,0x0b,0x00,0x00,0x1e,0xa5,0x00,0x00, 0x1e,0xa5,0x00,0x00,0x00,0xc7,0x00,0x00,0x1e,0xa6,0x00,0x00,0x1e,0xa6,0x00,0x00,0x00,0x0d,0x00,0x00,0x1e,0xa7,0x00,0x00,0x1e,0xa7,0x00,0x00,0x00,0xc9,0x00,0x00,0x1e,0xa8,0x00,0x00,0x1e,0xa8,0x00,0x00,0x00,0x0e,0x00,0x00,0x1e,0xa9,0x00,0x00,0x1e,0xa9,0x00,0x00,0x00,0xca,0x00,0x00,0x1e,0xaa,0x00,0x00,0x1e,0xaa,0x00,0x00, 0x00,0x0f,0x00,0x00,0x1e,0xab,0x00,0x00,0x1e,0xab,0x00,0x00,0x00,0xcb,0x00,0x00,0x1e,0xac,0x00,0x00,0x1e,0xac,0x00,0x00,0x00,0x0c,0x00,0x00,0x1e,0xad,0x00,0x00,0x1e,0xad,0x00,0x00,0x00,0xc8,0x00,0x00,0x1e,0xae,0x00,0x00,0x1e,0xae,0x00,0x00,0x00,0x04,0x00,0x00,0x1e,0xaf,0x00,0x00,0x1e,0xaf,0x00,0x00,0x00,0xc0,0x00,0x00, 0x1e,0xb0,0x00,0x00,0x1e,0xb0,0x00,0x00,0x00,0x06,0x00,0x00,0x1e,0xb1,0x00,0x00,0x1e,0xb1,0x00,0x00,0x00,0xc2,0x00,0x00,0x1e,0xb2,0x00,0x00,0x1e,0xb2,0x00,0x00,0x00,0x07,0x00,0x00,0x1e,0xb3,0x00,0x00,0x1e,0xb3,0x00,0x00,0x00,0xc3,0x00,0x00,0x1e,0xb4,0x00,0x00,0x1e,0xb4,0x00,0x00,0x00,0x08,0x00,0x00,0x1e,0xb5,0x00,0x00, 0x1e,0xb5,0x00,0x00,0x00,0xc4,0x00,0x00,0x1e,0xb6,0x00,0x00,0x1e,0xb6,0x00,0x00,0x00,0x05,0x00,0x00,0x1e,0xb7,0x00,0x00,0x1e,0xb7,0x00,0x00,0x00,0xc1,0x00,0x00,0x1e,0xb8,0x00,0x00,0x1e,0xb8,0x00,0x00,0x00,0x31,0x00,0x00,0x1e,0xb9,0x00,0x00,0x1e,0xb9,0x00,0x00,0x00,0xed,0x00,0x00,0x1e,0xba,0x00,0x00,0x1e,0xba,0x00,0x00, 0x00,0x33,0x00,0x00,0x1e,0xbb,0x00,0x00,0x1e,0xbb,0x00,0x00,0x00,0xef,0x00,0x00,0x1e,0xbc,0x00,0x00,0x1e,0xbc,0x00,0x00,0x00,0x37,0x00,0x00,0x1e,0xbd,0x00,0x00,0x1e,0xbd,0x00,0x00,0x00,0xf2,0x00,0x00,0x1e,0xbe,0x00,0x00,0x1e,0xbe,0x00,0x00,0x00,0x2a,0x00,0x00,0x1e,0xbf,0x00,0x00,0x1e,0xbf,0x00,0x00,0x00,0xe6,0x00,0x00, 0x1e,0xc0,0x00,0x00,0x1e,0xc0,0x00,0x00,0x00,0x2c,0x00,0x00,0x1e,0xc1,0x00,0x00,0x1e,0xc1,0x00,0x00,0x00,0xe8,0x00,0x00,0x1e,0xc2,0x00,0x00,0x1e,0xc2,0x00,0x00,0x00,0x2d,0x00,0x00,0x1e,0xc3,0x00,0x00,0x1e,0xc3,0x00,0x00,0x00,0xe9,0x00,0x00,0x1e,0xc4,0x00,0x00,0x1e,0xc4,0x00,0x00,0x00,0x2e,0x00,0x00,0x1e,0xc5,0x00,0x00, 0x1e,0xc5,0x00,0x00,0x00,0xea,0x00,0x00,0x1e,0xc6,0x00,0x00,0x1e,0xc6,0x00,0x00,0x00,0x2b,0x00,0x00,0x1e,0xc7,0x00,0x00,0x1e,0xc7,0x00,0x00,0x00,0xe7,0x00,0x00,0x1e,0xc8,0x00,0x00,0x1e,0xc8,0x00,0x00,0x00,0x4b,0x00,0x00,0x1e,0xc9,0x00,0x00,0x1e,0xc9,0x00,0x00,0x01,0x09,0x00,0x00,0x1e,0xca,0x00,0x00,0x1e,0xca,0x00,0x00, 0x00,0x49,0x00,0x00,0x1e,0xcb,0x00,0x00,0x1e,0xcb,0x00,0x00,0x01,0x07,0x00,0x00,0x1e,0xcc,0x00,0x00,0x1e,0xcc,0x00,0x00,0x00,0x6a,0x00,0x00,0x1e,0xcd,0x00,0x00,0x1e,0xcd,0x00,0x00,0x01,0x2d,0x00,0x00,0x1e,0xce,0x00,0x00,0x1e,0xce,0x00,0x00,0x00,0x6c,0x00,0x00,0x1e,0xcf,0x00,0x00,0x1e,0xcf,0x00,0x00,0x01,0x2f,0x00,0x00, 0x1e,0xd0,0x00,0x00,0x1e,0xd0,0x00,0x00,0x00,0x64,0x00,0x00,0x1e,0xd1,0x00,0x00,0x1e,0xd1,0x00,0x00,0x01,0x27,0x00,0x00,0x1e,0xd2,0x00,0x00,0x1e,0xd2,0x00,0x00,0x00,0x66,0x00,0x00,0x1e,0xd3,0x00,0x00,0x1e,0xd3,0x00,0x00,0x01,0x29,0x00,0x00,0x1e,0xd4,0x00,0x00,0x1e,0xd4,0x00,0x00,0x00,0x67,0x00,0x00,0x1e,0xd5,0x00,0x00, 0x1e,0xd5,0x00,0x00,0x01,0x2a,0x00,0x00,0x1e,0xd6,0x00,0x00,0x1e,0xd6,0x00,0x00,0x00,0x68,0x00,0x00,0x1e,0xd7,0x00,0x00,0x1e,0xd7,0x00,0x00,0x01,0x2b,0x00,0x00,0x1e,0xd8,0x00,0x00,0x1e,0xd8,0x00,0x00,0x00,0x65,0x00,0x00,0x1e,0xd9,0x00,0x00,0x1e,0xd9,0x00,0x00,0x01,0x28,0x00,0x00,0x1e,0xda,0x00,0x00,0x1e,0xda,0x00,0x00, 0x00,0x6e,0x00,0x00,0x1e,0xdb,0x00,0x00,0x1e,0xdb,0x00,0x00,0x01,0x31,0x00,0x00,0x1e,0xdc,0x00,0x00,0x1e,0xdc,0x00,0x00,0x00,0x70,0x00,0x00,0x1e,0xdd,0x00,0x00,0x1e,0xdd,0x00,0x00,0x01,0x33,0x00,0x00,0x1e,0xde,0x00,0x00,0x1e,0xde,0x00,0x00,0x00,0x71,0x00,0x00,0x1e,0xdf,0x00,0x00,0x1e,0xdf,0x00,0x00,0x01,0x34,0x00,0x00, 0x1e,0xe0,0x00,0x00,0x1e,0xe0,0x00,0x00,0x00,0x72,0x00,0x00,0x1e,0xe1,0x00,0x00,0x1e,0xe1,0x00,0x00,0x01,0x35,0x00,0x00,0x1e,0xe2,0x00,0x00,0x1e,0xe2,0x00,0x00,0x00,0x6f,0x00,0x00,0x1e,0xe3,0x00,0x00,0x1e,0xe3,0x00,0x00,0x01,0x32,0x00,0x00,0x1e,0xe4,0x00,0x00,0x1e,0xe4,0x00,0x00,0x00,0x93,0x00,0x00,0x1e,0xe5,0x00,0x00, 0x1e,0xe5,0x00,0x00,0x01,0x5b,0x00,0x00,0x1e,0xe6,0x00,0x00,0x1e,0xe6,0x00,0x00,0x00,0x95,0x00,0x00,0x1e,0xe7,0x00,0x00,0x1e,0xe7,0x00,0x00,0x01,0x5d,0x00,0x00,0x1e,0xe8,0x00,0x00,0x1e,0xe8,0x00,0x00,0x00,0x97,0x00,0x00,0x1e,0xe9,0x00,0x00,0x1e,0xe9,0x00,0x00,0x01,0x5f,0x00,0x00,0x1e,0xea,0x00,0x00,0x1e,0xea,0x00,0x00, 0x00,0x99,0x00,0x00,0x1e,0xeb,0x00,0x00,0x1e,0xeb,0x00,0x00,0x01,0x61,0x00,0x00,0x1e,0xec,0x00,0x00,0x1e,0xec,0x00,0x00,0x00,0x9a,0x00,0x00,0x1e,0xed,0x00,0x00,0x1e,0xed,0x00,0x00,0x01,0x62,0x00,0x00,0x1e,0xee,0x00,0x00,0x1e,0xee,0x00,0x00,0x00,0x9b,0x00,0x00,0x1e,0xef,0x00,0x00,0x1e,0xef,0x00,0x00,0x01,0x63,0x00,0x00, 0x1e,0xf0,0x00,0x00,0x1e,0xf0,0x00,0x00,0x00,0x98,0x00,0x00,0x1e,0xf1,0x00,0x00,0x1e,0xf1,0x00,0x00,0x01,0x60,0x00,0x00,0x1e,0xf2,0x00,0x00,0x1e,0xf2,0x00,0x00,0x00,0xad,0x00,0x00,0x1e,0xf3,0x00,0x00,0x1e,0xf3,0x00,0x00,0x01,0x75,0x00,0x00,0x1e,0xf4,0x00,0x00,0x1e,0xf4,0x00,0x00,0x00,0xac,0x00,0x00,0x1e,0xf5,0x00,0x00, 0x1e,0xf5,0x00,0x00,0x01,0x74,0x00,0x00,0x1e,0xf6,0x00,0x00,0x1e,0xf6,0x00,0x00,0x00,0xae,0x00,0x00,0x1e,0xf7,0x00,0x00,0x1e,0xf7,0x00,0x00,0x01,0x76,0x00,0x00,0x1e,0xf8,0x00,0x00,0x1e,0xf8,0x00,0x00,0x00,0xb0,0x00,0x00,0x1e,0xf9,0x00,0x00,0x1e,0xf9,0x00,0x00,0x01,0x78,0x00,0x00,0x20,0x01,0x00,0x00,0x20,0x01,0x00,0x00, 0x03,0xbc,0x00,0x00,0x20,0x0b,0x00,0x00,0x20,0x0b,0x00,0x00,0x03,0xbd,0x00,0x00,0x20,0x10,0x00,0x00,0x20,0x10,0x00,0x00,0x03,0x5b,0x00,0x00,0x20,0x13,0x00,0x00,0x20,0x14,0x00,0x00,0x03,0x59,0x00,0x00,0x20,0x16,0x00,0x00,0x20,0x16,0x00,0x00,0x03,0x37,0x00,0x00,0x20,0x18,0x00,0x00,0x20,0x19,0x00,0x00,0x03,0x61,0x00,0x00, 0x20,0x1a,0x00,0x00,0x20,0x1a,0x00,0x00,0x03,0x5d,0x00,0x00,0x20,0x1b,0x00,0x00,0x20,0x1b,0x00,0x00,0x03,0x63,0x00,0x00,0x20,0x1c,0x00,0x00,0x20,0x1d,0x00,0x00,0x03,0x5f,0x00,0x00,0x20,0x1e,0x00,0x00,0x20,0x1e,0x00,0x00,0x03,0x5e,0x00,0x00,0x20,0x1f,0x00,0x00,0x20,0x1f,0x00,0x00,0x03,0x64,0x00,0x00,0x20,0x20,0x00,0x00, 0x20,0x20,0x00,0x00,0x05,0xc0,0x00,0x00,0x20,0x21,0x00,0x00,0x20,0x21,0x00,0x00,0x05,0xc2,0x00,0x00,0x20,0x22,0x00,0x00,0x20,0x22,0x00,0x00,0x03,0x33,0x00,0x00,0x20,0x24,0x00,0x00,0x20,0x24,0x00,0x00,0x03,0x3b,0x00,0x00,0x20,0x26,0x00,0x00,0x20,0x26,0x00,0x00,0x03,0x2d,0x00,0x00,0x20,0x30,0x00,0x00,0x20,0x30,0x00,0x00, 0x04,0x39,0x00,0x00,0x20,0x32,0x00,0x00,0x20,0x33,0x00,0x00,0x05,0xbc,0x00,0x00,0x20,0x34,0x00,0x00,0x20,0x34,0x00,0x00,0x03,0x69,0x00,0x00,0x20,0x39,0x00,0x00,0x20,0x3a,0x00,0x00,0x03,0x67,0x00,0x00,0x20,0x3c,0x00,0x00,0x20,0x3d,0x00,0x00,0x03,0x38,0x00,0x00,0x20,0x3e,0x00,0x00,0x20,0x3e,0x00,0x00,0x03,0x3c,0x00,0x00, 0x20,0x3f,0x00,0x00,0x20,0x3f,0x00,0x00,0x03,0x3f,0x00,0x00,0x20,0x44,0x00,0x00,0x20,0x44,0x00,0x00,0x03,0x20,0x00,0x00,0x20,0x45,0x00,0x00,0x20,0x46,0x00,0x00,0x03,0x35,0x00,0x00,0x20,0x70,0x00,0x00,0x20,0x70,0x00,0x00,0x03,0x02,0x00,0x00,0x20,0x74,0x00,0x00,0x20,0x79,0x00,0x00,0x03,0x06,0x00,0x00,0x20,0x7a,0x00,0x00, 0x20,0x7a,0x00,0x00,0x04,0x3b,0x00,0x00,0x20,0x7c,0x00,0x00,0x20,0x7c,0x00,0x00,0x03,0xe6,0x00,0x00,0x20,0x80,0x00,0x00,0x20,0x89,0x00,0x00,0x02,0xe4,0x00,0x00,0x20,0xab,0x00,0x00,0x20,0xac,0x00,0x00,0x03,0xc6,0x00,0x00,0x20,0xae,0x00,0x00,0x20,0xae,0x00,0x00,0x03,0xcc,0x00,0x00,0x20,0xb4,0x00,0x00,0x20,0xb4,0x00,0x00, 0x03,0xc9,0x00,0x00,0x20,0xbd,0x00,0x00,0x20,0xbd,0x00,0x00,0x03,0xca,0x00,0x00,0x20,0xbf,0x00,0x00,0x20,0xbf,0x00,0x00,0x03,0xc2,0x00,0x00,0x21,0x02,0x00,0x00,0x21,0x02,0x00,0x00,0x02,0xa2,0x00,0x00,0x21,0x0d,0x00,0x00,0x21,0x0d,0x00,0x00,0x02,0xa7,0x00,0x00,0x21,0x13,0x00,0x00,0x21,0x13,0x00,0x00,0x05,0xc1,0x00,0x00, 0x21,0x15,0x00,0x00,0x21,0x15,0x00,0x00,0x02,0xad,0x00,0x00,0x21,0x16,0x00,0x00,0x21,0x16,0x00,0x00,0x05,0xc3,0x00,0x00,0x21,0x19,0x00,0x00,0x21,0x1a,0x00,0x00,0x02,0xaf,0x00,0x00,0x21,0x1d,0x00,0x00,0x21,0x1d,0x00,0x00,0x02,0xb1,0x00,0x00,0x21,0x22,0x00,0x00,0x21,0x22,0x00,0x00,0x05,0xba,0x00,0x00,0x21,0x24,0x00,0x00, 0x21,0x24,0x00,0x00,0x02,0xb9,0x00,0x00,0x21,0x2e,0x00,0x00,0x21,0x2e,0x00,0x00,0x05,0xc4,0x00,0x00,0x21,0x40,0x00,0x00,0x21,0x40,0x00,0x00,0x04,0x5e,0x00,0x00,0x21,0x8a,0x00,0x00,0x21,0x8a,0x00,0x00,0x05,0xff,0x00,0x00,0x21,0x8b,0x00,0x00,0x21,0x8b,0x00,0x00,0x05,0xfe,0x00,0x00,0x21,0x90,0x00,0x00,0x21,0x90,0x00,0x00, 0x04,0x77,0x00,0x00,0x21,0x91,0x00,0x00,0x21,0x91,0x00,0x00,0x04,0x71,0x00,0x00,0x21,0x92,0x00,0x00,0x21,0x92,0x00,0x00,0x04,0x73,0x00,0x00,0x21,0x93,0x00,0x00,0x21,0x93,0x00,0x00,0x04,0x75,0x00,0x00,0x21,0x94,0x00,0x00,0x21,0x95,0x00,0x00,0x04,0x79,0x00,0x00,0x21,0x96,0x00,0x00,0x21,0x96,0x00,0x00,0x04,0x78,0x00,0x00, 0x21,0x97,0x00,0x00,0x21,0x97,0x00,0x00,0x04,0x72,0x00,0x00,0x21,0x98,0x00,0x00,0x21,0x98,0x00,0x00,0x04,0x74,0x00,0x00,0x21,0x99,0x00,0x00,0x21,0x99,0x00,0x00,0x04,0x76,0x00,0x00,0x21,0x9d,0x00,0x00,0x21,0x9d,0x00,0x00,0x04,0x7b,0x00,0x00,0x21,0x9e,0x00,0x00,0x21,0x9e,0x00,0x00,0x04,0x7d,0x00,0x00,0x21,0xa0,0x00,0x00, 0x21,0xa0,0x00,0x00,0x04,0x7e,0x00,0x00,0x21,0xa2,0x00,0x00,0x21,0xa3,0x00,0x00,0x04,0x7f,0x00,0x00,0x21,0xa5,0x00,0x00,0x21,0xa7,0x00,0x00,0x04,0x81,0x00,0x00,0x21,0xa9,0x00,0x00,0x21,0xaa,0x00,0x00,0x04,0x85,0x00,0x00,0x21,0xad,0x00,0x00,0x21,0xad,0x00,0x00,0x04,0x7c,0x00,0x00,0x21,0xbe,0x00,0x00,0x21,0xbe,0x00,0x00, 0x04,0x87,0x00,0x00,0x21,0xc9,0x00,0x00,0x21,0xc9,0x00,0x00,0x04,0x88,0x00,0x00,0x21,0xd0,0x00,0x00,0x21,0xd0,0x00,0x00,0x04,0x8c,0x00,0x00,0x21,0xd1,0x00,0x00,0x21,0xd3,0x00,0x00,0x04,0x89,0x00,0x00,0x21,0xd4,0x00,0x00,0x21,0xd4,0x00,0x00,0x04,0x8d,0x00,0x00,0x21,0xdb,0x00,0x00,0x21,0xdb,0x00,0x00,0x04,0x8e,0x00,0x00, 0x21,0xde,0x00,0x00,0x21,0xde,0x00,0x00,0x05,0xe8,0x00,0x00,0x21,0xdf,0x00,0x00,0x21,0xdf,0x00,0x00,0x05,0xe7,0x00,0x00,0x21,0xe5,0x00,0x00,0x21,0xe5,0x00,0x00,0x04,0x84,0x00,0x00,0x21,0xe7,0x00,0x00,0x21,0xe8,0x00,0x00,0x04,0x8f,0x00,0x00,0x21,0xea,0x00,0x00,0x21,0xea,0x00,0x00,0x05,0xe2,0x00,0x00,0x22,0x00,0x00,0x00, 0x22,0x00,0x00,0x00,0x04,0x65,0x00,0x00,0x22,0x01,0x00,0x00,0x22,0x01,0x00,0x00,0x03,0xd6,0x00,0x00,0x22,0x02,0x00,0x00,0x22,0x02,0x00,0x00,0x04,0x2f,0x00,0x00,0x22,0x03,0x00,0x00,0x22,0x03,0x00,0x00,0x03,0xea,0x00,0x00,0x22,0x04,0x00,0x00,0x22,0x04,0x00,0x00,0x04,0x62,0x00,0x00,0x22,0x05,0x00,0x00,0x22,0x05,0x00,0x00, 0x04,0x25,0x00,0x00,0x22,0x06,0x00,0x00,0x22,0x06,0x00,0x00,0x04,0x2b,0x00,0x00,0x22,0x07,0x00,0x00,0x22,0x07,0x00,0x00,0x03,0xeb,0x00,0x00,0x22,0x08,0x00,0x00,0x22,0x08,0x00,0x00,0x03,0xe2,0x00,0x00,0x22,0x09,0x00,0x00,0x22,0x09,0x00,0x00,0x04,0x0b,0x00,0x00,0x22,0x0a,0x00,0x00,0x22,0x0a,0x00,0x00,0x03,0xe3,0x00,0x00, 0x22,0x0b,0x00,0x00,0x22,0x0b,0x00,0x00,0x04,0x5d,0x00,0x00,0x22,0x0c,0x00,0x00,0x22,0x0c,0x00,0x00,0x04,0x0a,0x00,0x00,0x22,0x0e,0x00,0x00,0x22,0x0e,0x00,0x00,0x03,0xe5,0x00,0x00,0x22,0x0f,0x00,0x00,0x22,0x0f,0x00,0x00,0x04,0x2c,0x00,0x00,0x22,0x10,0x00,0x00,0x22,0x10,0x00,0x00,0x03,0xd8,0x00,0x00,0x22,0x11,0x00,0x00, 0x22,0x11,0x00,0x00,0x04,0x2d,0x00,0x00,0x22,0x12,0x00,0x00,0x22,0x12,0x00,0x00,0x04,0x16,0x00,0x00,0x22,0x13,0x00,0x00,0x22,0x13,0x00,0x00,0x03,0xf9,0x00,0x00,0x22,0x15,0x00,0x00,0x22,0x15,0x00,0x00,0x03,0xdd,0x00,0x00,0x22,0x18,0x00,0x00,0x22,0x18,0x00,0x00,0x04,0x4d,0x00,0x00,0x22,0x19,0x00,0x00,0x22,0x19,0x00,0x00, 0x03,0xd4,0x00,0x00,0x22,0x1a,0x00,0x00,0x22,0x1a,0x00,0x00,0x04,0x2e,0x00,0x00,0x22,0x1e,0x00,0x00,0x22,0x1e,0x00,0x00,0x04,0x24,0x00,0x00,0x22,0x23,0x00,0x00,0x22,0x23,0x00,0x00,0x03,0xdc,0x00,0x00,0x22,0x24,0x00,0x00,0x22,0x24,0x00,0x00,0x03,0xde,0x00,0x00,0x22,0x25,0x00,0x00,0x22,0x25,0x00,0x00,0x04,0x31,0x00,0x00, 0x22,0x27,0x00,0x00,0x22,0x2b,0x00,0x00,0x04,0x26,0x00,0x00,0x22,0x34,0x00,0x00,0x22,0x34,0x00,0x00,0x04,0x63,0x00,0x00,0x22,0x35,0x00,0x00,0x22,0x35,0x00,0x00,0x03,0xd1,0x00,0x00,0x22,0x36,0x00,0x00,0x22,0x36,0x00,0x00,0x04,0x40,0x00,0x00,0x22,0x37,0x00,0x00,0x22,0x37,0x00,0x00,0x04,0x3e,0x00,0x00,0x22,0x38,0x00,0x00, 0x22,0x38,0x00,0x00,0x03,0xdf,0x00,0x00,0x22,0x39,0x00,0x00,0x22,0x39,0x00,0x00,0x03,0xe9,0x00,0x00,0x22,0x3c,0x00,0x00,0x22,0x3c,0x00,0x00,0x04,0x4e,0x00,0x00,0x22,0x3e,0x00,0x00,0x22,0x3e,0x00,0x00,0x03,0xed,0x00,0x00,0x22,0x43,0x00,0x00,0x22,0x43,0x00,0x00,0x03,0xd0,0x00,0x00,0x22,0x45,0x00,0x00,0x22,0x45,0x00,0x00, 0x03,0xd7,0x00,0x00,0x22,0x47,0x00,0x00,0x22,0x47,0x00,0x00,0x04,0x04,0x00,0x00,0x22,0x48,0x00,0x00,0x22,0x48,0x00,0x00,0x04,0x20,0x00,0x00,0x22,0x49,0x00,0x00,0x22,0x49,0x00,0x00,0x04,0x09,0x00,0x00,0x22,0x4b,0x00,0x00,0x22,0x4b,0x00,0x00,0x04,0x64,0x00,0x00,0x22,0x4d,0x00,0x00,0x22,0x4d,0x00,0x00,0x03,0xe8,0x00,0x00, 0x22,0x54,0x00,0x00,0x22,0x54,0x00,0x00,0x03,0xd5,0x00,0x00,0x22,0x57,0x00,0x00,0x22,0x57,0x00,0x00,0x04,0x4c,0x00,0x00,0x22,0x5f,0x00,0x00,0x22,0x5f,0x00,0x00,0x04,0x3f,0x00,0x00,0x22,0x60,0x00,0x00,0x22,0x60,0x00,0x00,0x04,0x1a,0x00,0x00,0x22,0x61,0x00,0x00,0x22,0x61,0x00,0x00,0x03,0xe7,0x00,0x00,0x22,0x62,0x00,0x00, 0x22,0x62,0x00,0x00,0x04,0x0f,0x00,0x00,0x22,0x63,0x00,0x00,0x22,0x63,0x00,0x00,0x04,0x5a,0x00,0x00,0x22,0x64,0x00,0x00,0x22,0x64,0x00,0x00,0x04,0x1e,0x00,0x00,0x22,0x65,0x00,0x00,0x22,0x65,0x00,0x00,0x04,0x1d,0x00,0x00,0x22,0x6a,0x00,0x00,0x22,0x6a,0x00,0x00,0x03,0xfb,0x00,0x00,0x22,0x6b,0x00,0x00,0x22,0x6b,0x00,0x00, 0x03,0xfa,0x00,0x00,0x22,0x6c,0x00,0x00,0x22,0x6c,0x00,0x00,0x03,0xd2,0x00,0x00,0x22,0x6d,0x00,0x00,0x22,0x6d,0x00,0x00,0x04,0x0c,0x00,0x00,0x22,0x6e,0x00,0x00,0x22,0x6e,0x00,0x00,0x04,0x10,0x00,0x00,0x22,0x6f,0x00,0x00,0x22,0x6f,0x00,0x00,0x04,0x0d,0x00,0x00,0x22,0x70,0x00,0x00,0x22,0x70,0x00,0x00,0x04,0x11,0x00,0x00, 0x22,0x71,0x00,0x00,0x22,0x71,0x00,0x00,0x04,0x0e,0x00,0x00,0x22,0x72,0x00,0x00,0x22,0x72,0x00,0x00,0x03,0xf7,0x00,0x00,0x22,0x73,0x00,0x00,0x22,0x73,0x00,0x00,0x03,0xec,0x00,0x00,0x22,0x7a,0x00,0x00,0x22,0x7a,0x00,0x00,0x04,0x3c,0x00,0x00,0x22,0x7b,0x00,0x00,0x22,0x7b,0x00,0x00,0x04,0x5c,0x00,0x00,0x22,0x7c,0x00,0x00, 0x22,0x7c,0x00,0x00,0x04,0x3d,0x00,0x00,0x22,0x82,0x00,0x00,0x22,0x82,0x00,0x00,0x04,0x5b,0x00,0x00,0x22,0x83,0x00,0x00,0x22,0x83,0x00,0x00,0x04,0x5f,0x00,0x00,0x22,0x84,0x00,0x00,0x22,0x85,0x00,0x00,0x04,0x13,0x00,0x00,0x22,0x86,0x00,0x00,0x22,0x87,0x00,0x00,0x04,0x41,0x00,0x00,0x22,0x88,0x00,0x00,0x22,0x89,0x00,0x00, 0x04,0x05,0x00,0x00,0x22,0x8e,0x00,0x00,0x22,0x8e,0x00,0x00,0x03,0xfd,0x00,0x00,0x22,0x8f,0x00,0x00,0x22,0x8f,0x00,0x00,0x04,0x55,0x00,0x00,0x22,0x90,0x00,0x00,0x22,0x90,0x00,0x00,0x04,0x57,0x00,0x00,0x22,0x91,0x00,0x00,0x22,0x91,0x00,0x00,0x04,0x56,0x00,0x00,0x22,0x92,0x00,0x00,0x22,0x92,0x00,0x00,0x04,0x58,0x00,0x00, 0x22,0x93,0x00,0x00,0x22,0x94,0x00,0x00,0x04,0x4f,0x00,0x00,0x22,0x95,0x00,0x00,0x22,0x95,0x00,0x00,0x04,0x70,0x00,0x00,0x22,0x96,0x00,0x00,0x22,0x97,0x00,0x00,0x04,0x6d,0x00,0x00,0x22,0x98,0x00,0x00,0x22,0x98,0x00,0x00,0x04,0x6c,0x00,0x00,0x22,0x99,0x00,0x00,0x22,0x99,0x00,0x00,0x04,0x6f,0x00,0x00,0x22,0x9b,0x00,0x00, 0x22,0x9b,0x00,0x00,0x04,0x69,0x00,0x00,0x22,0x9c,0x00,0x00,0x22,0x9c,0x00,0x00,0x04,0x6b,0x00,0x00,0x22,0x9d,0x00,0x00,0x22,0x9d,0x00,0x00,0x04,0x6a,0x00,0x00,0x22,0x9e,0x00,0x00,0x22,0x9e,0x00,0x00,0x04,0x53,0x00,0x00,0x22,0x9f,0x00,0x00,0x22,0x9f,0x00,0x00,0x04,0x52,0x00,0x00,0x22,0xa0,0x00,0x00,0x22,0xa0,0x00,0x00, 0x04,0x54,0x00,0x00,0x22,0xa1,0x00,0x00,0x22,0xa1,0x00,0x00,0x04,0x51,0x00,0x00,0x22,0xa2,0x00,0x00,0x22,0xa2,0x00,0x00,0x04,0x4b,0x00,0x00,0x22,0xa3,0x00,0x00,0x22,0xa3,0x00,0x00,0x04,0x61,0x00,0x00,0x22,0xa4,0x00,0x00,0x22,0xa4,0x00,0x00,0x04,0x60,0x00,0x00,0x22,0xa5,0x00,0x00,0x22,0xa5,0x00,0x00,0x04,0x67,0x00,0x00, 0x22,0xb4,0x00,0x00,0x22,0xb4,0x00,0x00,0x04,0x08,0x00,0x00,0x22,0xb8,0x00,0x00,0x22,0xb8,0x00,0x00,0x03,0xfc,0x00,0x00,0x22,0xbb,0x00,0x00,0x22,0xbb,0x00,0x00,0x04,0x68,0x00,0x00,0x22,0xbc,0x00,0x00,0x22,0xbc,0x00,0x00,0x04,0x01,0x00,0x00,0x22,0xbd,0x00,0x00,0x22,0xbd,0x00,0x00,0x04,0x07,0x00,0x00,0x22,0xc2,0x00,0x00, 0x22,0xc3,0x00,0x00,0x04,0x02,0x00,0x00,0x22,0xc4,0x00,0x00,0x22,0xc4,0x00,0x00,0x03,0xdb,0x00,0x00,0x22,0xc6,0x00,0x00,0x22,0xc6,0x00,0x00,0x04,0x59,0x00,0x00,0x22,0xc8,0x00,0x00,0x22,0xc8,0x00,0x00,0x03,0xd3,0x00,0x00,0x22,0xc9,0x00,0x00,0x22,0xc9,0x00,0x00,0x03,0xf3,0x00,0x00,0x22,0xca,0x00,0x00,0x22,0xca,0x00,0x00, 0x04,0x47,0x00,0x00,0x22,0xce,0x00,0x00,0x22,0xce,0x00,0x00,0x03,0xda,0x00,0x00,0x22,0xd0,0x00,0x00,0x22,0xd0,0x00,0x00,0x03,0xe0,0x00,0x00,0x22,0xe2,0x00,0x00,0x22,0xe2,0x00,0x00,0x04,0x12,0x00,0x00,0x22,0xee,0x00,0x00,0x22,0xee,0x00,0x00,0x03,0xe4,0x00,0x00,0x22,0xef,0x00,0x00,0x22,0xef,0x00,0x00,0x03,0xf8,0x00,0x00, 0x22,0xf0,0x00,0x00,0x22,0xf0,0x00,0x00,0x04,0x66,0x00,0x00,0x22,0xf1,0x00,0x00,0x22,0xf1,0x00,0x00,0x03,0xe1,0x00,0x00,0x23,0x02,0x00,0x00,0x23,0x02,0x00,0x00,0x05,0xe1,0x00,0x00,0x23,0x03,0x00,0x00,0x23,0x03,0x00,0x00,0x05,0xca,0x00,0x00,0x23,0x04,0x00,0x00,0x23,0x04,0x00,0x00,0x04,0x91,0x00,0x00,0x23,0x05,0x00,0x00, 0x23,0x05,0x00,0x00,0x05,0xf4,0x00,0x00,0x23,0x08,0x00,0x00,0x23,0x08,0x00,0x00,0x03,0x4f,0x00,0x00,0x23,0x09,0x00,0x00,0x23,0x09,0x00,0x00,0x03,0x52,0x00,0x00,0x23,0x0a,0x00,0x00,0x23,0x0a,0x00,0x00,0x03,0x50,0x00,0x00,0x23,0x0b,0x00,0x00,0x23,0x0b,0x00,0x00,0x03,0x53,0x00,0x00,0x23,0x18,0x00,0x00,0x23,0x18,0x00,0x00, 0x05,0xe9,0x00,0x00,0x23,0x1c,0x00,0x00,0x23,0x1c,0x00,0x00,0x05,0xce,0x00,0x00,0x23,0x1d,0x00,0x00,0x23,0x1d,0x00,0x00,0x05,0xcd,0x00,0x00,0x23,0x1e,0x00,0x00,0x23,0x1f,0x00,0x00,0x05,0xcb,0x00,0x00,0x23,0x24,0x00,0x00,0x23,0x24,0x00,0x00,0x04,0x92,0x00,0x00,0x23,0x25,0x00,0x00,0x23,0x25,0x00,0x00,0x05,0xe6,0x00,0x00, 0x23,0x26,0x00,0x00,0x23,0x26,0x00,0x00,0x05,0xe4,0x00,0x00,0x23,0x28,0x00,0x00,0x23,0x28,0x00,0x00,0x05,0xe5,0x00,0x00,0x23,0x2b,0x00,0x00,0x23,0x2b,0x00,0x00,0x05,0xe3,0x00,0x00,0x23,0x36,0x00,0x00,0x23,0x36,0x00,0x00,0x05,0x65,0x00,0x00,0x23,0x37,0x00,0x00,0x23,0x37,0x00,0x00,0x05,0xa0,0x00,0x00,0x23,0x38,0x00,0x00, 0x23,0x38,0x00,0x00,0x05,0x8f,0x00,0x00,0x23,0x39,0x00,0x00,0x23,0x39,0x00,0x00,0x05,0x8c,0x00,0x00,0x23,0x3a,0x00,0x00,0x23,0x3a,0x00,0x00,0x05,0x8b,0x00,0x00,0x23,0x3b,0x00,0x00,0x23,0x3b,0x00,0x00,0x05,0x91,0x00,0x00,0x23,0x3c,0x00,0x00,0x23,0x3c,0x00,0x00,0x05,0x87,0x00,0x00,0x23,0x3d,0x00,0x00,0x23,0x3d,0x00,0x00, 0x05,0x6d,0x00,0x00,0x23,0x3e,0x00,0x00,0x23,0x3e,0x00,0x00,0x05,0x6b,0x00,0x00,0x23,0x3f,0x00,0x00,0x23,0x3f,0x00,0x00,0x05,0x9f,0x00,0x00,0x23,0x40,0x00,0x00,0x23,0x40,0x00,0x00,0x05,0x68,0x00,0x00,0x23,0x41,0x00,0x00,0x23,0x41,0x00,0x00,0x05,0x97,0x00,0x00,0x23,0x42,0x00,0x00,0x23,0x42,0x00,0x00,0x05,0x86,0x00,0x00, 0x23,0x43,0x00,0x00,0x23,0x43,0x00,0x00,0x05,0x93,0x00,0x00,0x23,0x44,0x00,0x00,0x23,0x44,0x00,0x00,0x05,0x90,0x00,0x00,0x23,0x45,0x00,0x00,0x23,0x45,0x00,0x00,0x05,0x82,0x00,0x00,0x23,0x46,0x00,0x00,0x23,0x46,0x00,0x00,0x05,0x9d,0x00,0x00,0x23,0x47,0x00,0x00,0x23,0x47,0x00,0x00,0x05,0x92,0x00,0x00,0x23,0x48,0x00,0x00, 0x23,0x48,0x00,0x00,0x05,0x96,0x00,0x00,0x23,0x49,0x00,0x00,0x23,0x49,0x00,0x00,0x05,0x69,0x00,0x00,0x23,0x4a,0x00,0x00,0x23,0x4a,0x00,0x00,0x05,0x79,0x00,0x00,0x23,0x4b,0x00,0x00,0x23,0x4b,0x00,0x00,0x05,0x72,0x00,0x00,0x23,0x4c,0x00,0x00,0x23,0x4c,0x00,0x00,0x05,0x8e,0x00,0x00,0x23,0x4d,0x00,0x00,0x23,0x4d,0x00,0x00, 0x05,0x8a,0x00,0x00,0x23,0x4e,0x00,0x00,0x23,0x4e,0x00,0x00,0x05,0x78,0x00,0x00,0x23,0x4f,0x00,0x00,0x23,0x4f,0x00,0x00,0x05,0xa9,0x00,0x00,0x23,0x50,0x00,0x00,0x23,0x50,0x00,0x00,0x05,0x98,0x00,0x00,0x23,0x51,0x00,0x00,0x23,0x51,0x00,0x00,0x05,0xa8,0x00,0x00,0x23,0x52,0x00,0x00,0x23,0x52,0x00,0x00,0x05,0x71,0x00,0x00, 0x23,0x53,0x00,0x00,0x23,0x53,0x00,0x00,0x05,0x99,0x00,0x00,0x23,0x54,0x00,0x00,0x23,0x54,0x00,0x00,0x05,0x89,0x00,0x00,0x23,0x55,0x00,0x00,0x23,0x55,0x00,0x00,0x05,0xa7,0x00,0x00,0x23,0x56,0x00,0x00,0x23,0x56,0x00,0x00,0x05,0x7a,0x00,0x00,0x23,0x57,0x00,0x00,0x23,0x57,0x00,0x00,0x05,0x8d,0x00,0x00,0x23,0x58,0x00,0x00, 0x23,0x58,0x00,0x00,0x05,0x9b,0x00,0x00,0x23,0x59,0x00,0x00,0x23,0x59,0x00,0x00,0x05,0x73,0x00,0x00,0x23,0x5a,0x00,0x00,0x23,0x5a,0x00,0x00,0x05,0x75,0x00,0x00,0x23,0x5b,0x00,0x00,0x23,0x5b,0x00,0x00,0x05,0x80,0x00,0x00,0x23,0x5c,0x00,0x00,0x23,0x5c,0x00,0x00,0x05,0x6e,0x00,0x00,0x23,0x5d,0x00,0x00,0x23,0x5d,0x00,0x00, 0x05,0xa5,0x00,0x00,0x23,0x5e,0x00,0x00,0x23,0x5e,0x00,0x00,0x05,0x9a,0x00,0x00,0x23,0x5f,0x00,0x00,0x23,0x5f,0x00,0x00,0x05,0x6c,0x00,0x00,0x23,0x60,0x00,0x00,0x23,0x60,0x00,0x00,0x05,0x88,0x00,0x00,0x23,0x61,0x00,0x00,0x23,0x61,0x00,0x00,0x05,0xa6,0x00,0x00,0x23,0x62,0x00,0x00,0x23,0x62,0x00,0x00,0x05,0x70,0x00,0x00, 0x23,0x63,0x00,0x00,0x23,0x63,0x00,0x00,0x05,0xa1,0x00,0x00,0x23,0x64,0x00,0x00,0x23,0x64,0x00,0x00,0x05,0x7f,0x00,0x00,0x23,0x65,0x00,0x00,0x23,0x65,0x00,0x00,0x05,0x6a,0x00,0x00,0x23,0x66,0x00,0x00,0x23,0x66,0x00,0x00,0x05,0x77,0x00,0x00,0x23,0x67,0x00,0x00,0x23,0x67,0x00,0x00,0x05,0x81,0x00,0x00,0x23,0x68,0x00,0x00, 0x23,0x68,0x00,0x00,0x05,0xa3,0x00,0x00,0x23,0x69,0x00,0x00,0x23,0x69,0x00,0x00,0x05,0x7c,0x00,0x00,0x23,0x6a,0x00,0x00,0x23,0x6a,0x00,0x00,0x05,0x6f,0x00,0x00,0x23,0x6b,0x00,0x00,0x23,0x6b,0x00,0x00,0x05,0x74,0x00,0x00,0x23,0x6c,0x00,0x00,0x23,0x6c,0x00,0x00,0x05,0xaa,0x00,0x00,0x23,0x6d,0x00,0x00,0x23,0x6d,0x00,0x00, 0x05,0xa2,0x00,0x00,0x23,0x6e,0x00,0x00,0x23,0x6e,0x00,0x00,0x05,0x9e,0x00,0x00,0x23,0x6f,0x00,0x00,0x23,0x70,0x00,0x00,0x05,0x94,0x00,0x00,0x23,0x71,0x00,0x00,0x23,0x71,0x00,0x00,0x05,0x76,0x00,0x00,0x23,0x72,0x00,0x00,0x23,0x72,0x00,0x00,0x05,0xa4,0x00,0x00,0x23,0x73,0x00,0x00,0x23,0x73,0x00,0x00,0x05,0x7d,0x00,0x00, 0x23,0x74,0x00,0x00,0x23,0x74,0x00,0x00,0x05,0x9c,0x00,0x00,0x23,0x75,0x00,0x00,0x23,0x75,0x00,0x00,0x05,0x83,0x00,0x00,0x23,0x76,0x00,0x00,0x23,0x76,0x00,0x00,0x05,0x67,0x00,0x00,0x23,0x77,0x00,0x00,0x23,0x77,0x00,0x00,0x05,0x7b,0x00,0x00,0x23,0x78,0x00,0x00,0x23,0x78,0x00,0x00,0x05,0x7e,0x00,0x00,0x23,0x79,0x00,0x00, 0x23,0x79,0x00,0x00,0x05,0x84,0x00,0x00,0x23,0x7a,0x00,0x00,0x23,0x7a,0x00,0x00,0x05,0x66,0x00,0x00,0x23,0x89,0x00,0x00,0x23,0x89,0x00,0x00,0x05,0xe0,0x00,0x00,0x23,0x8a,0x00,0x00,0x23,0x8a,0x00,0x00,0x05,0xd5,0x00,0x00,0x23,0x8b,0x00,0x00,0x23,0x8b,0x00,0x00,0x05,0xc7,0x00,0x00,0x23,0x95,0x00,0x00,0x23,0x95,0x00,0x00, 0x05,0x85,0x00,0x00,0x23,0x9b,0x00,0x00,0x23,0x9b,0x00,0x00,0x04,0x34,0x00,0x00,0x23,0x9c,0x00,0x00,0x23,0x9d,0x00,0x00,0x04,0x32,0x00,0x00,0x23,0x9e,0x00,0x00,0x23,0x9e,0x00,0x00,0x04,0x37,0x00,0x00,0x23,0x9f,0x00,0x00,0x23,0xa0,0x00,0x00,0x04,0x35,0x00,0x00,0x23,0xa1,0x00,0x00,0x23,0xa1,0x00,0x00,0x03,0xf6,0x00,0x00, 0x23,0xa2,0x00,0x00,0x23,0xa3,0x00,0x00,0x03,0xf4,0x00,0x00,0x23,0xa4,0x00,0x00,0x23,0xa4,0x00,0x00,0x04,0x4a,0x00,0x00,0x23,0xa5,0x00,0x00,0x23,0xa6,0x00,0x00,0x04,0x48,0x00,0x00,0x23,0xa7,0x00,0x00,0x23,0xa7,0x00,0x00,0x03,0xf2,0x00,0x00,0x23,0xa8,0x00,0x00,0x23,0xa8,0x00,0x00,0x03,0xf1,0x00,0x00,0x23,0xa9,0x00,0x00, 0x23,0xa9,0x00,0x00,0x03,0xf0,0x00,0x00,0x23,0xaa,0x00,0x00,0x23,0xaa,0x00,0x00,0x03,0xd9,0x00,0x00,0x23,0xab,0x00,0x00,0x23,0xab,0x00,0x00,0x04,0x46,0x00,0x00,0x23,0xac,0x00,0x00,0x23,0xac,0x00,0x00,0x04,0x45,0x00,0x00,0x23,0xad,0x00,0x00,0x23,0xad,0x00,0x00,0x04,0x44,0x00,0x00,0x23,0xce,0x00,0x00,0x23,0xce,0x00,0x00, 0x05,0xea,0x00,0x00,0x23,0xfb,0x00,0x00,0x23,0xfc,0x00,0x00,0x05,0xef,0x00,0x00,0x23,0xfd,0x00,0x00,0x23,0xfe,0x00,0x00,0x05,0xf2,0x00,0x00,0x24,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x05,0xee,0x00,0x00,0x24,0x01,0x00,0x00,0x24,0x02,0x00,0x00,0x05,0xfa,0x00,0x00,0x24,0x03,0x00,0x00,0x24,0x04,0x00,0x00,0x05,0xd7,0x00,0x00, 0x24,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x05,0xda,0x00,0x00,0x24,0x06,0x00,0x00,0x24,0x06,0x00,0x00,0x05,0xb2,0x00,0x00,0x24,0x07,0x00,0x00,0x24,0x07,0x00,0x00,0x05,0xc5,0x00,0x00,0x24,0x08,0x00,0x00,0x24,0x08,0x00,0x00,0x05,0xb3,0x00,0x00,0x24,0x09,0x00,0x00,0x24,0x09,0x00,0x00,0x05,0xdf,0x00,0x00,0x24,0x0a,0x00,0x00, 0x24,0x0a,0x00,0x00,0x05,0xeb,0x00,0x00,0x24,0x0b,0x00,0x00,0x24,0x0b,0x00,0x00,0x06,0x01,0x00,0x00,0x24,0x0c,0x00,0x00,0x24,0x0c,0x00,0x00,0x05,0xdd,0x00,0x00,0x24,0x0d,0x00,0x00,0x24,0x0d,0x00,0x00,0x05,0xc9,0x00,0x00,0x24,0x0e,0x00,0x00,0x24,0x0e,0x00,0x00,0x05,0xf8,0x00,0x00,0x24,0x0f,0x00,0x00,0x24,0x0f,0x00,0x00, 0x05,0xf7,0x00,0x00,0x24,0x10,0x00,0x00,0x24,0x10,0x00,0x00,0x05,0xcf,0x00,0x00,0x24,0x11,0x00,0x00,0x24,0x11,0x00,0x00,0x05,0xd2,0x00,0x00,0x24,0x12,0x00,0x00,0x24,0x12,0x00,0x00,0x05,0xd4,0x00,0x00,0x24,0x13,0x00,0x00,0x24,0x13,0x00,0x00,0x05,0xd3,0x00,0x00,0x24,0x14,0x00,0x00,0x24,0x14,0x00,0x00,0x05,0xd1,0x00,0x00, 0x24,0x15,0x00,0x00,0x24,0x15,0x00,0x00,0x05,0xec,0x00,0x00,0x24,0x16,0x00,0x00,0x24,0x16,0x00,0x00,0x05,0xfd,0x00,0x00,0x24,0x17,0x00,0x00,0x24,0x17,0x00,0x00,0x05,0xd9,0x00,0x00,0x24,0x18,0x00,0x00,0x24,0x18,0x00,0x00,0x05,0xc8,0x00,0x00,0x24,0x19,0x00,0x00,0x24,0x19,0x00,0x00,0x05,0xd6,0x00,0x00,0x24,0x1a,0x00,0x00, 0x24,0x1a,0x00,0x00,0x05,0xfc,0x00,0x00,0x24,0x1b,0x00,0x00,0x24,0x1c,0x00,0x00,0x05,0xdb,0x00,0x00,0x24,0x1d,0x00,0x00,0x24,0x1d,0x00,0x00,0x05,0xde,0x00,0x00,0x24,0x1e,0x00,0x00,0x24,0x1e,0x00,0x00,0x05,0xf5,0x00,0x00,0x24,0x1f,0x00,0x00,0x24,0x1f,0x00,0x00,0x06,0x00,0x00,0x00,0x24,0x20,0x00,0x00,0x24,0x20,0x00,0x00, 0x05,0xf9,0x00,0x00,0x24,0x21,0x00,0x00,0x24,0x21,0x00,0x00,0x05,0xd0,0x00,0x00,0x24,0x23,0x00,0x00,0x24,0x23,0x00,0x00,0x05,0xc6,0x00,0x00,0x24,0x24,0x00,0x00,0x24,0x24,0x00,0x00,0x05,0xed,0x00,0x00,0x25,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x05,0x2e,0x00,0x00,0x25,0x01,0x00,0x00,0x25,0x01,0x00,0x00,0x05,0x08,0x00,0x00, 0x25,0x02,0x00,0x00,0x25,0x02,0x00,0x00,0x05,0x3b,0x00,0x00,0x25,0x03,0x00,0x00,0x25,0x03,0x00,0x00,0x05,0x15,0x00,0x00,0x25,0x04,0x00,0x00,0x25,0x04,0x00,0x00,0x05,0x34,0x00,0x00,0x25,0x05,0x00,0x00,0x25,0x05,0x00,0x00,0x05,0x0e,0x00,0x00,0x25,0x06,0x00,0x00,0x25,0x06,0x00,0x00,0x05,0x35,0x00,0x00,0x25,0x07,0x00,0x00, 0x25,0x07,0x00,0x00,0x05,0x0f,0x00,0x00,0x25,0x08,0x00,0x00,0x25,0x08,0x00,0x00,0x05,0x31,0x00,0x00,0x25,0x09,0x00,0x00,0x25,0x09,0x00,0x00,0x05,0x0b,0x00,0x00,0x25,0x0a,0x00,0x00,0x25,0x0a,0x00,0x00,0x05,0x32,0x00,0x00,0x25,0x0b,0x00,0x00,0x25,0x0b,0x00,0x00,0x05,0x0c,0x00,0x00,0x25,0x0c,0x00,0x00,0x25,0x0c,0x00,0x00, 0x05,0x2d,0x00,0x00,0x25,0x0d,0x00,0x00,0x25,0x0d,0x00,0x00,0x04,0xfc,0x00,0x00,0x25,0x0e,0x00,0x00,0x25,0x0e,0x00,0x00,0x04,0xf6,0x00,0x00,0x25,0x0f,0x00,0x00,0x25,0x0f,0x00,0x00,0x05,0x07,0x00,0x00,0x25,0x10,0x00,0x00,0x25,0x10,0x00,0x00,0x05,0x2c,0x00,0x00,0x25,0x11,0x00,0x00,0x25,0x11,0x00,0x00,0x04,0xfa,0x00,0x00, 0x25,0x12,0x00,0x00,0x25,0x12,0x00,0x00,0x04,0xf4,0x00,0x00,0x25,0x13,0x00,0x00,0x25,0x13,0x00,0x00,0x05,0x06,0x00,0x00,0x25,0x14,0x00,0x00,0x25,0x14,0x00,0x00,0x05,0x3a,0x00,0x00,0x25,0x15,0x00,0x00,0x25,0x15,0x00,0x00,0x05,0x55,0x00,0x00,0x25,0x16,0x00,0x00,0x25,0x16,0x00,0x00,0x05,0x4f,0x00,0x00,0x25,0x17,0x00,0x00, 0x25,0x17,0x00,0x00,0x05,0x14,0x00,0x00,0x25,0x18,0x00,0x00,0x25,0x18,0x00,0x00,0x05,0x39,0x00,0x00,0x25,0x19,0x00,0x00,0x25,0x19,0x00,0x00,0x05,0x53,0x00,0x00,0x25,0x1a,0x00,0x00,0x25,0x1a,0x00,0x00,0x05,0x4d,0x00,0x00,0x25,0x1b,0x00,0x00,0x25,0x1b,0x00,0x00,0x05,0x12,0x00,0x00,0x25,0x1c,0x00,0x00,0x25,0x1c,0x00,0x00, 0x05,0x3e,0x00,0x00,0x25,0x1d,0x00,0x00,0x25,0x1d,0x00,0x00,0x05,0x61,0x00,0x00,0x25,0x1e,0x00,0x00,0x25,0x1e,0x00,0x00,0x05,0x4e,0x00,0x00,0x25,0x1f,0x00,0x00,0x25,0x1f,0x00,0x00,0x04,0xf7,0x00,0x00,0x25,0x20,0x00,0x00,0x25,0x20,0x00,0x00,0x05,0x5e,0x00,0x00,0x25,0x21,0x00,0x00,0x25,0x21,0x00,0x00,0x04,0xfd,0x00,0x00, 0x25,0x22,0x00,0x00,0x25,0x22,0x00,0x00,0x05,0x54,0x00,0x00,0x25,0x23,0x00,0x00,0x25,0x23,0x00,0x00,0x05,0x18,0x00,0x00,0x25,0x24,0x00,0x00,0x25,0x24,0x00,0x00,0x05,0x3d,0x00,0x00,0x25,0x25,0x00,0x00,0x25,0x25,0x00,0x00,0x05,0x60,0x00,0x00,0x25,0x26,0x00,0x00,0x25,0x26,0x00,0x00,0x05,0x4c,0x00,0x00,0x25,0x27,0x00,0x00, 0x25,0x27,0x00,0x00,0x04,0xf5,0x00,0x00,0x25,0x28,0x00,0x00,0x25,0x28,0x00,0x00,0x05,0x5d,0x00,0x00,0x25,0x29,0x00,0x00,0x25,0x29,0x00,0x00,0x04,0xfb,0x00,0x00,0x25,0x2a,0x00,0x00,0x25,0x2a,0x00,0x00,0x05,0x52,0x00,0x00,0x25,0x2b,0x00,0x00,0x25,0x2b,0x00,0x00,0x05,0x17,0x00,0x00,0x25,0x2c,0x00,0x00,0x25,0x2c,0x00,0x00, 0x05,0x2b,0x00,0x00,0x25,0x2d,0x00,0x00,0x25,0x2d,0x00,0x00,0x05,0x1a,0x00,0x00,0x25,0x2e,0x00,0x00,0x25,0x2e,0x00,0x00,0x05,0x40,0x00,0x00,0x25,0x2f,0x00,0x00,0x25,0x2f,0x00,0x00,0x04,0xf9,0x00,0x00,0x25,0x30,0x00,0x00,0x25,0x30,0x00,0x00,0x04,0xf3,0x00,0x00,0x25,0x31,0x00,0x00,0x25,0x31,0x00,0x00,0x05,0x43,0x00,0x00, 0x25,0x32,0x00,0x00,0x25,0x32,0x00,0x00,0x05,0x1d,0x00,0x00,0x25,0x33,0x00,0x00,0x25,0x33,0x00,0x00,0x05,0x05,0x00,0x00,0x25,0x34,0x00,0x00,0x25,0x34,0x00,0x00,0x05,0x38,0x00,0x00,0x25,0x35,0x00,0x00,0x25,0x35,0x00,0x00,0x05,0x1b,0x00,0x00,0x25,0x36,0x00,0x00,0x25,0x36,0x00,0x00,0x05,0x41,0x00,0x00,0x25,0x37,0x00,0x00, 0x25,0x37,0x00,0x00,0x05,0x51,0x00,0x00,0x25,0x38,0x00,0x00,0x25,0x38,0x00,0x00,0x05,0x4b,0x00,0x00,0x25,0x39,0x00,0x00,0x25,0x39,0x00,0x00,0x05,0x44,0x00,0x00,0x25,0x3a,0x00,0x00,0x25,0x3a,0x00,0x00,0x05,0x1e,0x00,0x00,0x25,0x3b,0x00,0x00,0x25,0x3b,0x00,0x00,0x05,0x11,0x00,0x00,0x25,0x3c,0x00,0x00,0x25,0x3c,0x00,0x00, 0x05,0x3c,0x00,0x00,0x25,0x3d,0x00,0x00,0x25,0x3d,0x00,0x00,0x05,0x1c,0x00,0x00,0x25,0x3e,0x00,0x00,0x25,0x3e,0x00,0x00,0x05,0x42,0x00,0x00,0x25,0x3f,0x00,0x00,0x25,0x3f,0x00,0x00,0x05,0x5f,0x00,0x00,0x25,0x40,0x00,0x00,0x25,0x40,0x00,0x00,0x05,0x4a,0x00,0x00,0x25,0x41,0x00,0x00,0x25,0x41,0x00,0x00,0x04,0xf8,0x00,0x00, 0x25,0x42,0x00,0x00,0x25,0x42,0x00,0x00,0x05,0x5c,0x00,0x00,0x25,0x43,0x00,0x00,0x25,0x43,0x00,0x00,0x05,0x20,0x00,0x00,0x25,0x44,0x00,0x00,0x25,0x44,0x00,0x00,0x05,0x46,0x00,0x00,0x25,0x45,0x00,0x00,0x25,0x45,0x00,0x00,0x05,0x19,0x00,0x00,0x25,0x46,0x00,0x00,0x25,0x46,0x00,0x00,0x05,0x3f,0x00,0x00,0x25,0x47,0x00,0x00, 0x25,0x47,0x00,0x00,0x04,0xfe,0x00,0x00,0x25,0x48,0x00,0x00,0x25,0x48,0x00,0x00,0x05,0x50,0x00,0x00,0x25,0x49,0x00,0x00,0x25,0x49,0x00,0x00,0x05,0x45,0x00,0x00,0x25,0x4a,0x00,0x00,0x25,0x4a,0x00,0x00,0x05,0x1f,0x00,0x00,0x25,0x4b,0x00,0x00,0x25,0x4b,0x00,0x00,0x05,0x16,0x00,0x00,0x25,0x4c,0x00,0x00,0x25,0x4c,0x00,0x00, 0x05,0x28,0x00,0x00,0x25,0x4d,0x00,0x00,0x25,0x4d,0x00,0x00,0x05,0x02,0x00,0x00,0x25,0x4e,0x00,0x00,0x25,0x4e,0x00,0x00,0x05,0x29,0x00,0x00,0x25,0x4f,0x00,0x00,0x25,0x4f,0x00,0x00,0x05,0x03,0x00,0x00,0x25,0x50,0x00,0x00,0x25,0x50,0x00,0x00,0x04,0xe8,0x00,0x00,0x25,0x51,0x00,0x00,0x25,0x51,0x00,0x00,0x04,0xec,0x00,0x00, 0x25,0x52,0x00,0x00,0x25,0x52,0x00,0x00,0x05,0x01,0x00,0x00,0x25,0x53,0x00,0x00,0x25,0x53,0x00,0x00,0x04,0xf2,0x00,0x00,0x25,0x54,0x00,0x00,0x25,0x54,0x00,0x00,0x04,0xe7,0x00,0x00,0x25,0x55,0x00,0x00,0x25,0x55,0x00,0x00,0x05,0x00,0x00,0x00,0x25,0x56,0x00,0x00,0x25,0x56,0x00,0x00,0x04,0xf1,0x00,0x00,0x25,0x57,0x00,0x00, 0x25,0x57,0x00,0x00,0x04,0xe6,0x00,0x00,0x25,0x58,0x00,0x00,0x25,0x58,0x00,0x00,0x05,0x58,0x00,0x00,0x25,0x59,0x00,0x00,0x25,0x59,0x00,0x00,0x05,0x49,0x00,0x00,0x25,0x5a,0x00,0x00,0x25,0x5a,0x00,0x00,0x04,0xeb,0x00,0x00,0x25,0x5b,0x00,0x00,0x25,0x5b,0x00,0x00,0x05,0x57,0x00,0x00,0x25,0x5c,0x00,0x00,0x25,0x5c,0x00,0x00, 0x05,0x48,0x00,0x00,0x25,0x5d,0x00,0x00,0x25,0x5d,0x00,0x00,0x04,0xea,0x00,0x00,0x25,0x5e,0x00,0x00,0x25,0x5e,0x00,0x00,0x05,0x64,0x00,0x00,0x25,0x5f,0x00,0x00,0x25,0x5f,0x00,0x00,0x05,0x5b,0x00,0x00,0x25,0x60,0x00,0x00,0x25,0x60,0x00,0x00,0x04,0xef,0x00,0x00,0x25,0x61,0x00,0x00,0x25,0x61,0x00,0x00,0x05,0x63,0x00,0x00, 0x25,0x62,0x00,0x00,0x25,0x62,0x00,0x00,0x05,0x5a,0x00,0x00,0x25,0x63,0x00,0x00,0x25,0x63,0x00,0x00,0x04,0xee,0x00,0x00,0x25,0x64,0x00,0x00,0x25,0x64,0x00,0x00,0x04,0xff,0x00,0x00,0x25,0x65,0x00,0x00,0x25,0x65,0x00,0x00,0x04,0xf0,0x00,0x00,0x25,0x66,0x00,0x00,0x25,0x66,0x00,0x00,0x04,0xe5,0x00,0x00,0x25,0x67,0x00,0x00, 0x25,0x67,0x00,0x00,0x05,0x56,0x00,0x00,0x25,0x68,0x00,0x00,0x25,0x68,0x00,0x00,0x05,0x47,0x00,0x00,0x25,0x69,0x00,0x00,0x25,0x69,0x00,0x00,0x04,0xe9,0x00,0x00,0x25,0x6a,0x00,0x00,0x25,0x6a,0x00,0x00,0x05,0x62,0x00,0x00,0x25,0x6b,0x00,0x00,0x25,0x6b,0x00,0x00,0x05,0x59,0x00,0x00,0x25,0x6c,0x00,0x00,0x25,0x6c,0x00,0x00, 0x04,0xed,0x00,0x00,0x25,0x6d,0x00,0x00,0x25,0x6d,0x00,0x00,0x05,0x22,0x00,0x00,0x25,0x6e,0x00,0x00,0x25,0x6e,0x00,0x00,0x05,0x21,0x00,0x00,0x25,0x6f,0x00,0x00,0x25,0x70,0x00,0x00,0x05,0x23,0x00,0x00,0x25,0x71,0x00,0x00,0x25,0x71,0x00,0x00,0x05,0x27,0x00,0x00,0x25,0x72,0x00,0x00,0x25,0x72,0x00,0x00,0x05,0x26,0x00,0x00, 0x25,0x73,0x00,0x00,0x25,0x73,0x00,0x00,0x05,0x25,0x00,0x00,0x25,0x74,0x00,0x00,0x25,0x74,0x00,0x00,0x05,0x2f,0x00,0x00,0x25,0x75,0x00,0x00,0x25,0x75,0x00,0x00,0x05,0x36,0x00,0x00,0x25,0x76,0x00,0x00,0x25,0x76,0x00,0x00,0x05,0x33,0x00,0x00,0x25,0x77,0x00,0x00,0x25,0x77,0x00,0x00,0x05,0x2a,0x00,0x00,0x25,0x78,0x00,0x00, 0x25,0x78,0x00,0x00,0x05,0x09,0x00,0x00,0x25,0x79,0x00,0x00,0x25,0x79,0x00,0x00,0x05,0x10,0x00,0x00,0x25,0x7a,0x00,0x00,0x25,0x7a,0x00,0x00,0x05,0x0d,0x00,0x00,0x25,0x7b,0x00,0x00,0x25,0x7b,0x00,0x00,0x05,0x04,0x00,0x00,0x25,0x7c,0x00,0x00,0x25,0x7c,0x00,0x00,0x05,0x30,0x00,0x00,0x25,0x7d,0x00,0x00,0x25,0x7d,0x00,0x00, 0x05,0x37,0x00,0x00,0x25,0x7e,0x00,0x00,0x25,0x7e,0x00,0x00,0x05,0x0a,0x00,0x00,0x25,0x7f,0x00,0x00,0x25,0x7f,0x00,0x00,0x05,0x13,0x00,0x00,0x25,0x80,0x00,0x00,0x25,0x80,0x00,0x00,0x04,0xa2,0x00,0x00,0x25,0x81,0x00,0x00,0x25,0x88,0x00,0x00,0x04,0x9a,0x00,0x00,0x25,0x89,0x00,0x00,0x25,0x89,0x00,0x00,0x04,0xaa,0x00,0x00, 0x25,0x8a,0x00,0x00,0x25,0x8a,0x00,0x00,0x04,0xa9,0x00,0x00,0x25,0x8b,0x00,0x00,0x25,0x8b,0x00,0x00,0x04,0xa8,0x00,0x00,0x25,0x8c,0x00,0x00,0x25,0x8c,0x00,0x00,0x04,0xa7,0x00,0x00,0x25,0x8d,0x00,0x00,0x25,0x8d,0x00,0x00,0x04,0xa6,0x00,0x00,0x25,0x8e,0x00,0x00,0x25,0x8e,0x00,0x00,0x04,0xa5,0x00,0x00,0x25,0x8f,0x00,0x00, 0x25,0x8f,0x00,0x00,0x04,0xa4,0x00,0x00,0x25,0x90,0x00,0x00,0x25,0x90,0x00,0x00,0x04,0xab,0x00,0x00,0x25,0x91,0x00,0x00,0x25,0x93,0x00,0x00,0x04,0xb7,0x00,0x00,0x25,0x94,0x00,0x00,0x25,0x94,0x00,0x00,0x04,0xa3,0x00,0x00,0x25,0x95,0x00,0x00,0x25,0x9f,0x00,0x00,0x04,0xac,0x00,0x00,0x25,0xa0,0x00,0x00,0x25,0xa1,0x00,0x00, 0x04,0xc8,0x00,0x00,0x25,0xaa,0x00,0x00,0x25,0xab,0x00,0x00,0x04,0xca,0x00,0x00,0x25,0xb2,0x00,0x00,0x25,0xb2,0x00,0x00,0x04,0xd1,0x00,0x00,0x25,0xb3,0x00,0x00,0x25,0xb3,0x00,0x00,0x04,0xd5,0x00,0x00,0x25,0xb4,0x00,0x00,0x25,0xb4,0x00,0x00,0x04,0xdd,0x00,0x00,0x25,0xb5,0x00,0x00,0x25,0xb5,0x00,0x00,0x04,0xe1,0x00,0x00, 0x25,0xb6,0x00,0x00,0x25,0xb6,0x00,0x00,0x04,0xd2,0x00,0x00,0x25,0xb7,0x00,0x00,0x25,0xb7,0x00,0x00,0x04,0xd6,0x00,0x00,0x25,0xb8,0x00,0x00,0x25,0xb8,0x00,0x00,0x04,0xde,0x00,0x00,0x25,0xb9,0x00,0x00,0x25,0xb9,0x00,0x00,0x04,0xe2,0x00,0x00,0x25,0xba,0x00,0x00,0x25,0xba,0x00,0x00,0x04,0xd9,0x00,0x00,0x25,0xbb,0x00,0x00, 0x25,0xbb,0x00,0x00,0x04,0xdb,0x00,0x00,0x25,0xbc,0x00,0x00,0x25,0xbc,0x00,0x00,0x04,0xd3,0x00,0x00,0x25,0xbd,0x00,0x00,0x25,0xbd,0x00,0x00,0x04,0xd7,0x00,0x00,0x25,0xbe,0x00,0x00,0x25,0xbe,0x00,0x00,0x04,0xdf,0x00,0x00,0x25,0xbf,0x00,0x00,0x25,0xbf,0x00,0x00,0x04,0xe3,0x00,0x00,0x25,0xc0,0x00,0x00,0x25,0xc0,0x00,0x00, 0x04,0xd4,0x00,0x00,0x25,0xc1,0x00,0x00,0x25,0xc1,0x00,0x00,0x04,0xd8,0x00,0x00,0x25,0xc2,0x00,0x00,0x25,0xc2,0x00,0x00,0x04,0xe0,0x00,0x00,0x25,0xc3,0x00,0x00,0x25,0xc3,0x00,0x00,0x04,0xe4,0x00,0x00,0x25,0xc4,0x00,0x00,0x25,0xc4,0x00,0x00,0x04,0xda,0x00,0x00,0x25,0xc5,0x00,0x00,0x25,0xc5,0x00,0x00,0x04,0xdc,0x00,0x00, 0x25,0xc6,0x00,0x00,0x25,0xc8,0x00,0x00,0x04,0xc4,0x00,0x00,0x25,0xc9,0x00,0x00,0x25,0xc9,0x00,0x00,0x04,0xc1,0x00,0x00,0x25,0xca,0x00,0x00,0x25,0xca,0x00,0x00,0x04,0xc7,0x00,0x00,0x25,0xcb,0x00,0x00,0x25,0xcb,0x00,0x00,0x04,0xbb,0x00,0x00,0x25,0xcc,0x00,0x00,0x25,0xcc,0x00,0x00,0x04,0xc0,0x00,0x00,0x25,0xce,0x00,0x00, 0x25,0xce,0x00,0x00,0x04,0xc2,0x00,0x00,0x25,0xcf,0x00,0x00,0x25,0xcf,0x00,0x00,0x04,0xba,0x00,0x00,0x25,0xd4,0x00,0x00,0x25,0xd5,0x00,0x00,0x04,0xbd,0x00,0x00,0x25,0xe6,0x00,0x00,0x25,0xe6,0x00,0x00,0x04,0xc3,0x00,0x00,0x25,0xe7,0x00,0x00,0x25,0xeb,0x00,0x00,0x04,0xcc,0x00,0x00,0x25,0xef,0x00,0x00,0x25,0xef,0x00,0x00, 0x04,0xbc,0x00,0x00,0x25,0xf6,0x00,0x00,0x25,0xf6,0x00,0x00,0x04,0xbf,0x00,0x00,0x26,0x6d,0x00,0x00,0x26,0x6d,0x00,0x00,0x06,0x60,0x00,0x00,0x26,0x6f,0x00,0x00,0x26,0x6f,0x00,0x00,0x06,0x61,0x00,0x00,0x26,0x87,0x00,0x00,0x26,0x87,0x00,0x00,0x05,0xab,0x00,0x00,0x26,0xa0,0x00,0x00,0x26,0xa1,0x00,0x00,0x05,0xac,0x00,0x00, 0x27,0x13,0x00,0x00,0x27,0x13,0x00,0x00,0x05,0xae,0x00,0x00,0x27,0x15,0x00,0x00,0x27,0x15,0x00,0x00,0x05,0xaf,0x00,0x00,0x27,0x17,0x00,0x00,0x27,0x17,0x00,0x00,0x05,0xb0,0x00,0x00,0x27,0x36,0x00,0x00,0x27,0x36,0x00,0x00,0x05,0xb1,0x00,0x00,0x27,0x6e,0x00,0x00,0x27,0x6e,0x00,0x00,0x03,0x4c,0x00,0x00,0x27,0x6f,0x00,0x00, 0x27,0x6f,0x00,0x00,0x03,0x4e,0x00,0x00,0x27,0x70,0x00,0x00,0x27,0x70,0x00,0x00,0x03,0x4b,0x00,0x00,0x27,0x71,0x00,0x00,0x27,0x71,0x00,0x00,0x03,0x4d,0x00,0x00,0x27,0x94,0x00,0x00,0x27,0x94,0x00,0x00,0x04,0x93,0x00,0x00,0x27,0x9c,0x00,0x00,0x27,0x9e,0x00,0x00,0x04,0x94,0x00,0x00,0x27,0xc5,0x00,0x00,0x27,0xc5,0x00,0x00, 0x03,0x51,0x00,0x00,0x27,0xc6,0x00,0x00,0x27,0xc6,0x00,0x00,0x03,0x54,0x00,0x00,0x27,0xdc,0x00,0x00,0x27,0xdc,0x00,0x00,0x03,0xef,0x00,0x00,0x27,0xe6,0x00,0x00,0x27,0xe6,0x00,0x00,0x03,0xb6,0x00,0x00,0x27,0xe7,0x00,0x00,0x27,0xe7,0x00,0x00,0x03,0xb9,0x00,0x00,0x27,0xe8,0x00,0x00,0x27,0xe8,0x00,0x00,0x03,0xb4,0x00,0x00, 0x27,0xe9,0x00,0x00,0x27,0xe9,0x00,0x00,0x03,0xb7,0x00,0x00,0x27,0xea,0x00,0x00,0x27,0xea,0x00,0x00,0x03,0xb5,0x00,0x00,0x27,0xeb,0x00,0x00,0x27,0xeb,0x00,0x00,0x03,0xb8,0x00,0x00,0x27,0xf5,0x00,0x00,0x27,0xf7,0x00,0x00,0x04,0x97,0x00,0x00,0x29,0x16,0x00,0x00,0x29,0x16,0x00,0x00,0x04,0x43,0x00,0x00,0x29,0x4a,0x00,0x00, 0x29,0x4a,0x00,0x00,0x03,0xee,0x00,0x00,0x29,0x87,0x00,0x00,0x29,0x88,0x00,0x00,0x03,0x55,0x00,0x00,0x2a,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x03,0xfe,0x00,0x00,0x2a,0x05,0x00,0x00,0x2a,0x06,0x00,0x00,0x03,0xff,0x00,0x00,0x2b,0x58,0x00,0x00,0x2b,0x58,0x00,0x00,0x05,0xf1,0x00,0x00,0xe0,0xa0,0x00,0x00,0xe0,0xa2,0x00,0x00, 0x06,0xc4,0x00,0x00,0xe0,0xb0,0x00,0x00,0xe0,0xb3,0x00,0x00,0x06,0xc7,0x00,0x00,0xfe,0x62,0x00,0x00,0xfe,0x62,0x00,0x00,0x04,0x3a,0x00,0x00,0xfe,0xff,0x00,0x00,0xfe,0xff,0x00,0x00,0x03,0xc1,0x00,0x00,0xff,0x5b,0x00,0x00,0xff,0x5b,0x00,0x00,0x03,0x49,0x00,0x00,0xff,0x5d,0x00,0x00,0xff,0x5d,0x00,0x00,0x03,0x4a,0x00,0x00, 0xff,0xfd,0x00,0x00,0xff,0xfd,0x00,0x00,0x05,0xf6,0x00,0x01,0x69,0x10,0x00,0x01,0x69,0x10,0x00,0x00,0x02,0x9f,0x00,0x01,0xd5,0x38,0x00,0x01,0xd5,0x39,0x00,0x00,0x02,0xa0,0x00,0x01,0xd5,0x3b,0x00,0x01,0xd5,0x3e,0x00,0x00,0x02,0xa3,0x00,0x01,0xd5,0x40,0x00,0x01,0xd5,0x44,0x00,0x00,0x02,0xa8,0x00,0x01,0xd5,0x46,0x00,0x01, 0xd5,0x46,0x00,0x00,0x02,0xae,0x00,0x01,0xd5,0x4a,0x00,0x01,0xd5,0x50,0x00,0x00,0x02,0xb2,0x00,0x01,0xd5,0x52,0x00,0x01,0xd5,0x6b,0x00,0x00,0x02,0xba,0x00,0x00,0xb0,0x00,0x2c,0x20,0xb0,0x00,0x55,0x58,0x45,0x59,0x20,0x20,0x4b,0xb8,0x00,0x0e,0x51,0x4b,0xb0,0x06,0x53,0x5a,0x58,0xb0,0x34,0x1b,0xb0,0x28,0x59,0x60,0x66,0x20, 0x8a,0x55,0x58,0xb0,0x02,0x25,0x61,0xb9,0x08,0x00,0x08,0x00,0x63,0x63,0x23,0x62,0x1b,0x21,0x21,0xb0,0x00,0x59,0xb0,0x00,0x43,0x23,0x44,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x01,0x2c,0xb0,0x20,0x60,0x66,0x2d,0xb0,0x02,0x2c,0x23,0x21,0x23,0x21,0x2d,0xb0,0x03,0x2c,0x20,0x64,0xb3,0x03,0x14,0x15,0x00,0x42,0x43,0xb0, 0x13,0x43,0x20,0x60,0x60,0x42,0xb1,0x02,0x14,0x43,0x42,0xb1,0x25,0x03,0x43,0xb0,0x02,0x43,0x54,0x78,0x20,0xb0,0x0c,0x23,0xb0,0x02,0x43,0x43,0x61,0x64,0xb0,0x04,0x50,0x78,0xb2,0x02,0x02,0x02,0x43,0x60,0x42,0xb0,0x21,0x65,0x1c,0x21,0xb0,0x02,0x43,0x43,0xb2,0x0e,0x15,0x01,0x42,0x1c,0x20,0xb0,0x02,0x43,0x23,0x42,0xb2,0x13, 0x01,0x13,0x43,0x60,0x42,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb2,0x16,0x01,0x02,0x43,0x60,0x42,0x2d,0xb0,0x04,0x2c,0xb0,0x03,0x2b,0xb0,0x15,0x43,0x58,0x23,0x21,0x23,0x21,0xb0,0x16,0x43,0x43,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0x1b,0x20,0x64,0x20,0xb0,0xc0,0x50,0xb0,0x04,0x26,0x5a,0xb2,0x28,0x01,0x0d,0x43,0x45,0x63,0x45, 0xb0,0x06,0x45,0x58,0x21,0xb0,0x03,0x25,0x59,0x52,0x5b,0x58,0x21,0x23,0x21,0x1b,0x8a,0x58,0x20,0xb0,0x50,0x50,0x58,0x21,0xb0,0x40,0x59,0x1b,0x20,0xb0,0x38,0x50,0x58,0x21,0xb0,0x38,0x59,0x59,0x20,0xb1,0x01,0x0d,0x43,0x45,0x63,0x45,0x61,0x64,0xb0,0x28,0x50,0x58,0x21,0xb1,0x01,0x0d,0x43,0x45,0x63,0x45,0x20,0xb0,0x30,0x50, 0x58,0x21,0xb0,0x30,0x59,0x1b,0x20,0xb0,0xc0,0x50,0x58,0x20,0x66,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x0a,0x50,0x58,0x60,0x1b,0x20,0xb0,0x20,0x50,0x58,0x21,0xb0,0x0a,0x60,0x1b,0x20,0xb0,0x36,0x50,0x58,0x21,0xb0,0x36,0x60,0x1b,0x60,0x59,0x59,0x59,0x1b,0xb0,0x02,0x25,0xb0,0x0c,0x43,0x63,0xb0,0x00,0x52,0x58,0xb0,0x00,0x4b,0xb0, 0x0a,0x50,0x58,0x21,0xb0,0x0c,0x43,0x1b,0x4b,0xb0,0x1e,0x50,0x58,0x21,0xb0,0x1e,0x4b,0x61,0xb8,0x10,0x00,0x63,0xb0,0x0c,0x43,0x63,0xb8,0x05,0x00,0x62,0x59,0x59,0x64,0x61,0x59,0xb0,0x01,0x2b,0x59,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0x59,0x20,0x64,0xb0,0x16,0x43,0x23,0x42,0x59,0x2d,0xb0,0x05,0x2c,0x20,0x45,0x20,0xb0, 0x04,0x25,0x61,0x64,0x20,0xb0,0x07,0x43,0x50,0x58,0xb0,0x07,0x23,0x42,0xb0,0x08,0x23,0x42,0x1b,0x21,0x21,0x59,0xb0,0x01,0x60,0x2d,0xb0,0x06,0x2c,0x23,0x21,0x23,0x21,0xb0,0x03,0x2b,0x20,0x64,0xb1,0x07,0x62,0x42,0x20,0xb0,0x08,0x23,0x42,0xb0,0x06,0x45,0x58,0x1b,0xb1,0x01,0x0d,0x43,0x45,0x63,0xb1,0x01,0x0d,0x43,0xb0,0x05, 0x60,0x45,0x63,0xb0,0x05,0x2a,0x21,0x20,0xb0,0x08,0x43,0x20,0x8a,0x20,0x8a,0xb0,0x01,0x2b,0xb1,0x30,0x05,0x25,0xb0,0x04,0x26,0x51,0x58,0x60,0x50,0x1b,0x61,0x52,0x59,0x58,0x23,0x59,0x21,0x59,0x20,0xb0,0x40,0x53,0x58,0xb0,0x01,0x2b,0x1b,0x21,0xb0,0x40,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0x2d,0xb0,0x07,0x2c,0xb0,0x09, 0x43,0x2b,0xb2,0x00,0x02,0x00,0x43,0x60,0x42,0x2d,0xb0,0x08,0x2c,0xb0,0x09,0x23,0x42,0x23,0x20,0xb0,0x00,0x23,0x42,0x61,0xb0,0x02,0x62,0x66,0xb0,0x01,0x63,0xb0,0x01,0x60,0xb0,0x07,0x2a,0x2d,0xb0,0x09,0x2c,0x20,0x20,0x45,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0, 0x01,0x63,0x60,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0a,0x2c,0xb2,0x09,0x0e,0x00,0x43,0x45,0x42,0x2a,0x21,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x0b,0x2c,0xb0,0x00,0x43,0x23,0x44,0xb2,0x00,0x01,0x00,0x43,0x60,0x42,0x2d,0xb0,0x0c,0x2c,0x20,0x20,0x45,0x20,0xb0,0x01,0x2b,0x23,0xb0,0x00,0x43,0xb0,0x04,0x25,0x60,0x20,0x45, 0x8a,0x23,0x61,0x20,0x64,0x20,0xb0,0x20,0x50,0x58,0x21,0xb0,0x00,0x1b,0xb0,0x30,0x50,0x58,0xb0,0x20,0x1b,0xb0,0x40,0x59,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb0,0x03,0x25,0x23,0x61,0x44,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0d,0x2c,0x20,0x20,0x45,0x20,0xb0,0x01,0x2b,0x23,0xb0,0x00,0x43,0xb0,0x04,0x25,0x60,0x20,0x45,0x8a, 0x23,0x61,0x20,0x64,0xb0,0x24,0x50,0x58,0xb0,0x00,0x1b,0xb0,0x40,0x59,0x23,0xb0,0x00,0x50,0x58,0x65,0x59,0xb0,0x03,0x25,0x23,0x61,0x44,0x44,0xb0,0x01,0x60,0x2d,0xb0,0x0e,0x2c,0x20,0xb0,0x00,0x23,0x42,0xb3,0x0d,0x0c,0x00,0x03,0x45,0x50,0x58,0x21,0x1b,0x23,0x21,0x59,0x2a,0x21,0x2d,0xb0,0x0f,0x2c,0xb1,0x02,0x02,0x45,0xb0, 0x64,0x61,0x44,0x2d,0xb0,0x10,0x2c,0xb0,0x01,0x60,0x20,0x20,0xb0,0x0f,0x43,0x4a,0xb0,0x00,0x50,0x58,0x20,0xb0,0x0f,0x23,0x42,0x59,0xb0,0x10,0x43,0x4a,0xb0,0x00,0x52,0x58,0x20,0xb0,0x10,0x23,0x42,0x59,0x2d,0xb0,0x11,0x2c,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0x20,0xb8,0x04,0x00,0x63,0x8a,0x23,0x61,0xb0,0x11,0x43,0x60, 0x20,0x8a,0x60,0x20,0xb0,0x11,0x23,0x42,0x23,0x2d,0xb0,0x12,0x2c,0x4b,0x54,0x58,0xb1,0x04,0x64,0x44,0x59,0x24,0xb0,0x0d,0x65,0x23,0x78,0x2d,0xb0,0x13,0x2c,0x4b,0x51,0x58,0x4b,0x53,0x58,0xb1,0x04,0x64,0x44,0x59,0x1b,0x21,0x59,0x24,0xb0,0x13,0x65,0x23,0x78,0x2d,0xb0,0x14,0x2c,0xb1,0x00,0x12,0x43,0x55,0x58,0xb1,0x12,0x12, 0x43,0xb0,0x01,0x61,0x42,0xb0,0x11,0x2b,0x59,0xb0,0x00,0x43,0xb0,0x02,0x25,0x42,0xb1,0x0f,0x02,0x25,0x42,0xb1,0x10,0x02,0x25,0x42,0xb0,0x01,0x16,0x23,0x20,0xb0,0x03,0x25,0x50,0x58,0xb1,0x01,0x00,0x43,0x60,0xb0,0x04,0x25,0x42,0x8a,0x8a,0x20,0x8a,0x23,0x61,0xb0,0x10,0x2a,0x21,0x23,0xb0,0x01,0x61,0x20,0x8a,0x23,0x61,0xb0, 0x10,0x2a,0x21,0x1b,0xb1,0x01,0x00,0x43,0x60,0xb0,0x02,0x25,0x42,0xb0,0x02,0x25,0x61,0xb0,0x10,0x2a,0x21,0x59,0xb0,0x0f,0x43,0x47,0xb0,0x10,0x43,0x47,0x60,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60, 0x59,0x66,0xb0,0x01,0x63,0x60,0xb1,0x00,0x00,0x13,0x23,0x44,0xb0,0x01,0x43,0xb0,0x00,0x3e,0xb2,0x01,0x01,0x01,0x43,0x60,0x42,0x2d,0xb0,0x15,0x2c,0x00,0xb1,0x00,0x02,0x45,0x54,0x58,0xb0,0x12,0x23,0x42,0x20,0x45,0xb0,0x0e,0x23,0x42,0xb0,0x0d,0x23,0xb0,0x05,0x60,0x42,0x20,0x60,0xb7,0x18,0x18,0x01,0x00,0x11,0x00,0x13,0x00, 0x42,0x42,0x42,0x8a,0x60,0x20,0xb0,0x14,0x23,0x42,0xb0,0x01,0x61,0xb1,0x14,0x08,0x2b,0xb0,0x8b,0x2b,0x1b,0x22,0x59,0x2d,0xb0,0x16,0x2c,0xb1,0x00,0x15,0x2b,0x2d,0xb0,0x17,0x2c,0xb1,0x01,0x15,0x2b,0x2d,0xb0,0x18,0x2c,0xb1,0x02,0x15,0x2b,0x2d,0xb0,0x19,0x2c,0xb1,0x03,0x15,0x2b,0x2d,0xb0,0x1a,0x2c,0xb1,0x04,0x15,0x2b,0x2d, 0xb0,0x1b,0x2c,0xb1,0x05,0x15,0x2b,0x2d,0xb0,0x1c,0x2c,0xb1,0x06,0x15,0x2b,0x2d,0xb0,0x1d,0x2c,0xb1,0x07,0x15,0x2b,0x2d,0xb0,0x1e,0x2c,0xb1,0x08,0x15,0x2b,0x2d,0xb0,0x1f,0x2c,0xb1,0x09,0x15,0x2b,0x2d,0xb0,0x2b,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0xb0,0x06,0x60,0x4b,0x54,0x58,0x23,0x20,0x2e,0xb0,0x01,0x5d, 0x1b,0x21,0x21,0x59,0x2d,0xb0,0x2c,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0xb0,0x16,0x60,0x4b,0x54,0x58,0x23,0x20,0x2e,0xb0,0x01,0x71,0x1b,0x21,0x21,0x59,0x2d,0xb0,0x2d,0x2c,0x23,0x20,0xb0,0x10,0x62,0x66,0xb0,0x01,0x63,0xb0,0x26,0x60,0x4b,0x54,0x58,0x23,0x20,0x2e,0xb0,0x01,0x72,0x1b,0x21,0x21,0x59,0x2d,0xb0, 0x20,0x2c,0x00,0xb0,0x0f,0x2b,0xb1,0x00,0x02,0x45,0x54,0x58,0xb0,0x12,0x23,0x42,0x20,0x45,0xb0,0x0e,0x23,0x42,0xb0,0x0d,0x23,0xb0,0x05,0x60,0x42,0x20,0x60,0xb0,0x01,0x61,0xb5,0x18,0x18,0x01,0x00,0x11,0x00,0x42,0x42,0x8a,0x60,0xb1,0x14,0x08,0x2b,0xb0,0x8b,0x2b,0x1b,0x22,0x59,0x2d,0xb0,0x21,0x2c,0xb1,0x00,0x20,0x2b,0x2d, 0xb0,0x22,0x2c,0xb1,0x01,0x20,0x2b,0x2d,0xb0,0x23,0x2c,0xb1,0x02,0x20,0x2b,0x2d,0xb0,0x24,0x2c,0xb1,0x03,0x20,0x2b,0x2d,0xb0,0x25,0x2c,0xb1,0x04,0x20,0x2b,0x2d,0xb0,0x26,0x2c,0xb1,0x05,0x20,0x2b,0x2d,0xb0,0x27,0x2c,0xb1,0x06,0x20,0x2b,0x2d,0xb0,0x28,0x2c,0xb1,0x07,0x20,0x2b,0x2d,0xb0,0x29,0x2c,0xb1,0x08,0x20,0x2b,0x2d, 0xb0,0x2a,0x2c,0xb1,0x09,0x20,0x2b,0x2d,0xb0,0x2e,0x2c,0x20,0x3c,0xb0,0x01,0x60,0x2d,0xb0,0x2f,0x2c,0x20,0x60,0xb0,0x18,0x60,0x20,0x43,0x23,0xb0,0x01,0x60,0x43,0xb0,0x02,0x25,0x61,0xb0,0x01,0x60,0xb0,0x2e,0x2a,0x21,0x2d,0xb0,0x30,0x2c,0xb0,0x2f,0x2b,0xb0,0x2f,0x2a,0x2d,0xb0,0x31,0x2c,0x20,0x20,0x47,0x20,0x20,0xb0,0x0e, 0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x61,0x38,0x23,0x20,0x8a,0x55,0x58,0x20,0x47,0x20,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x61,0x38,0x1b,0x21,0x59,0x2d,0xb0,0x32,0x2c, 0x00,0xb1,0x00,0x02,0x45,0x54,0x58,0xb1,0x0e,0x06,0x45,0x42,0xb0,0x01,0x16,0xb0,0x31,0x2a,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x1b,0x22,0x59,0x2d,0xb0,0x33,0x2c,0x00,0xb0,0x0f,0x2b,0xb1,0x00,0x02,0x45,0x54,0x58,0xb1,0x0e,0x06,0x45,0x42,0xb0,0x01,0x16,0xb0,0x31,0x2a,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x1b,0x22, 0x59,0x2d,0xb0,0x34,0x2c,0x20,0x35,0xb0,0x01,0x60,0x2d,0xb0,0x35,0x2c,0x00,0xb1,0x0e,0x06,0x45,0x42,0xb0,0x01,0x45,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0xb0,0x01,0x2b,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01, 0x63,0xb0,0x01,0x2b,0xb0,0x00,0x16,0xb4,0x00,0x00,0x00,0x00,0x00,0x44,0x3e,0x23,0x38,0xb1,0x34,0x01,0x15,0x2a,0x21,0x2d,0xb0,0x36,0x2c,0x20,0x3c,0x20,0x47,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0xb0,0x00,0x43,0x61,0x38,0x2d,0xb0,0x37,0x2c,0x2e, 0x17,0x3c,0x2d,0xb0,0x38,0x2c,0x20,0x3c,0x20,0x47,0x20,0xb0,0x0e,0x43,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0xb0,0x00,0x43,0x61,0xb0,0x01,0x43,0x63,0x38,0x2d,0xb0,0x39,0x2c,0xb1,0x02,0x00,0x16,0x25,0x20,0x2e,0x20,0x47,0xb0,0x00,0x23,0x42,0xb0,0x02,0x25,0x49,0x8a, 0x8a,0x47,0x23,0x47,0x23,0x61,0x20,0x58,0x62,0x1b,0x21,0x59,0xb0,0x01,0x23,0x42,0xb2,0x38,0x01,0x01,0x15,0x14,0x2a,0x2d,0xb0,0x3a,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x04,0x25,0xb0,0x04,0x25,0x47,0x23,0x47,0x23,0x61,0xb1,0x0c,0x00,0x42,0xb0,0x0b,0x43,0x2b,0x65,0x8a,0x2e,0x23,0x20,0x20,0x3c,0x8a,0x38,0x2d,0xb0, 0x3b,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x04,0x25,0xb0,0x04,0x25,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x06,0x23,0x42,0xb1,0x0c,0x00,0x42,0xb0,0x0b,0x43,0x2b,0x20,0xb0,0x60,0x50,0x58,0x20,0xb0,0x40,0x51,0x58,0xb3,0x04,0x20,0x05,0x20,0x1b,0xb3,0x04,0x26,0x05,0x1a,0x59,0x42,0x42,0x23,0x20,0xb0,0x0a,0x43, 0x20,0x8a,0x23,0x47,0x23,0x47,0x23,0x61,0x23,0x46,0x60,0xb0,0x06,0x43,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x20,0xb0,0x01,0x2b,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x04,0x43,0x60,0x64,0x23,0xb0,0x05,0x43,0x61,0x64,0x50,0x58,0xb0,0x04,0x43,0x61,0x1b,0xb0,0x05,0x43,0x60,0x59,0xb0, 0x03,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x61,0x23,0x20,0x20,0xb0,0x04,0x26,0x23,0x46,0x61,0x38,0x1b,0x23,0xb0,0x0a,0x43,0x46,0xb0,0x02,0x25,0xb0,0x0a,0x43,0x47,0x23,0x47,0x23,0x61,0x60,0x20,0xb0,0x06,0x43,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66, 0xb0,0x01,0x63,0x60,0x23,0x20,0xb0,0x01,0x2b,0x23,0xb0,0x06,0x43,0x60,0xb0,0x01,0x2b,0xb0,0x05,0x25,0x61,0xb0,0x05,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0xb0,0x04,0x26,0x61,0x20,0xb0,0x04,0x25,0x60,0x64,0x23,0xb0,0x03,0x25,0x60,0x64,0x50,0x58,0x21,0x1b,0x23,0x21,0x59,0x23, 0x20,0x20,0xb0,0x04,0x26,0x23,0x46,0x61,0x38,0x59,0x2d,0xb0,0x3c,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0x20,0x20,0xb0,0x05,0x26,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x23,0x3c,0x38,0x2d,0xb0,0x3d,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0xb0,0x0a,0x23,0x42,0x20,0x20,0x20,0x46,0x23,0x47,0xb0,0x01,0x2b,0x23,0x61, 0x38,0x2d,0xb0,0x3e,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0xb0,0x03,0x25,0xb0,0x02,0x25,0x47,0x23,0x47,0x23,0x61,0xb0,0x00,0x54,0x58,0x2e,0x20,0x3c,0x23,0x21,0x1b,0xb0,0x02,0x25,0xb0,0x02,0x25,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x05,0x25,0xb0,0x04,0x25,0x47,0x23,0x47,0x23,0x61,0xb0,0x06,0x25,0xb0,0x05,0x25,0x49,0xb0, 0x02,0x25,0x61,0xb9,0x08,0x00,0x08,0x00,0x63,0x63,0x23,0x20,0x58,0x62,0x1b,0x21,0x59,0x63,0xb8,0x04,0x00,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x23,0x2e,0x23,0x20,0x20,0x3c,0x8a,0x38,0x23,0x21,0x59,0x2d,0xb0,0x3f,0x2c,0xb0,0x00,0x16,0xb0,0x17,0x23,0x42,0x20,0xb0,0x0a,0x43,0x20,0x2e, 0x47,0x23,0x47,0x23,0x61,0x20,0x60,0xb0,0x20,0x60,0x66,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x23,0x20,0x20,0x3c,0x8a,0x38,0x2d,0xb0,0x40,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d, 0xb0,0x41,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x52,0x1b,0x50,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x42,0x2c,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43, 0x58,0x52,0x1b,0x50,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x43,0x2c,0xb0,0x3a,0x2b,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x44,0x2c,0xb0,0x3b,0x2b,0x8a,0x20,0x20,0x3c,0xb0,0x06,0x23,0x42,0x8a, 0x38,0x23,0x20,0x2e,0x46,0xb0,0x02,0x25,0x46,0xb0,0x17,0x43,0x58,0x50,0x1b,0x52,0x59,0x58,0x20,0x3c,0x59,0x2e,0xb1,0x30,0x01,0x14,0x2b,0xb0,0x06,0x43,0x2e,0xb0,0x30,0x2b,0x2d,0xb0,0x45,0x2c,0xb0,0x00,0x16,0xb0,0x04,0x25,0xb0,0x04,0x26,0x20,0x20,0x20,0x46,0x23,0x47,0x61,0xb0,0x0c,0x23,0x42,0x2e,0x47,0x23,0x47,0x23,0x61, 0xb0,0x0b,0x43,0x2b,0x23,0x20,0x3c,0x20,0x2e,0x23,0x38,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x46,0x2c,0xb1,0x0a,0x04,0x25,0x42,0xb0,0x00,0x16,0xb0,0x04,0x25,0xb0,0x04,0x25,0x20,0x2e,0x47,0x23,0x47,0x23,0x61,0x20,0xb0,0x06,0x23,0x42,0xb1,0x0c,0x00,0x42,0xb0,0x0b,0x43,0x2b,0x20,0xb0,0x60,0x50,0x58,0x20,0xb0,0x40,0x51,0x58, 0xb3,0x04,0x20,0x05,0x20,0x1b,0xb3,0x04,0x26,0x05,0x1a,0x59,0x42,0x42,0x23,0x20,0x47,0xb0,0x06,0x43,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x60,0x20,0xb0,0x01,0x2b,0x20,0x8a,0x8a,0x61,0x20,0xb0,0x04,0x43,0x60,0x64,0x23,0xb0,0x05,0x43,0x61,0x64,0x50,0x58,0xb0,0x04,0x43,0x61,0x1b, 0xb0,0x05,0x43,0x60,0x59,0xb0,0x03,0x25,0xb0,0x02,0x62,0x20,0xb0,0x00,0x50,0x58,0xb0,0x40,0x60,0x59,0x66,0xb0,0x01,0x63,0x61,0xb0,0x02,0x25,0x46,0x61,0x38,0x23,0x20,0x3c,0x23,0x38,0x1b,0x21,0x20,0x20,0x46,0x23,0x47,0xb0,0x01,0x2b,0x23,0x61,0x38,0x21,0x59,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x47,0x2c,0xb1,0x00,0x3a,0x2b, 0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x48,0x2c,0xb1,0x00,0x3b,0x2b,0x21,0x23,0x20,0x20,0x3c,0xb0,0x06,0x23,0x42,0x23,0x38,0xb1,0x30,0x01,0x14,0x2b,0xb0,0x06,0x43,0x2e,0xb0,0x30,0x2b,0x2d,0xb0,0x49,0x2c,0xb0,0x00,0x15,0x20,0x47,0xb0,0x00,0x23,0x42,0xb2,0x00,0x01,0x01,0x15,0x14,0x13,0x2e,0xb0,0x36,0x2a,0x2d,0xb0,0x4a, 0x2c,0xb0,0x00,0x15,0x20,0x47,0xb0,0x00,0x23,0x42,0xb2,0x00,0x01,0x01,0x15,0x14,0x13,0x2e,0xb0,0x36,0x2a,0x2d,0xb0,0x4b,0x2c,0xb1,0x00,0x01,0x14,0x13,0xb0,0x37,0x2a,0x2d,0xb0,0x4c,0x2c,0xb0,0x39,0x2a,0x2d,0xb0,0x4d,0x2c,0xb0,0x00,0x16,0x45,0x23,0x20,0x2e,0x20,0x46,0x8a,0x23,0x61,0x38,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0, 0x4e,0x2c,0xb0,0x0a,0x23,0x42,0xb0,0x4d,0x2b,0x2d,0xb0,0x4f,0x2c,0xb2,0x00,0x00,0x46,0x2b,0x2d,0xb0,0x50,0x2c,0xb2,0x00,0x01,0x46,0x2b,0x2d,0xb0,0x51,0x2c,0xb2,0x01,0x00,0x46,0x2b,0x2d,0xb0,0x52,0x2c,0xb2,0x01,0x01,0x46,0x2b,0x2d,0xb0,0x53,0x2c,0xb2,0x00,0x00,0x47,0x2b,0x2d,0xb0,0x54,0x2c,0xb2,0x00,0x01,0x47,0x2b,0x2d, 0xb0,0x55,0x2c,0xb2,0x01,0x00,0x47,0x2b,0x2d,0xb0,0x56,0x2c,0xb2,0x01,0x01,0x47,0x2b,0x2d,0xb0,0x57,0x2c,0xb3,0x00,0x00,0x00,0x43,0x2b,0x2d,0xb0,0x58,0x2c,0xb3,0x00,0x01,0x00,0x43,0x2b,0x2d,0xb0,0x59,0x2c,0xb3,0x01,0x00,0x00,0x43,0x2b,0x2d,0xb0,0x5a,0x2c,0xb3,0x01,0x01,0x00,0x43,0x2b,0x2d,0xb0,0x5b,0x2c,0xb3,0x00,0x00, 0x01,0x43,0x2b,0x2d,0xb0,0x5c,0x2c,0xb3,0x00,0x01,0x01,0x43,0x2b,0x2d,0xb0,0x5d,0x2c,0xb3,0x01,0x00,0x01,0x43,0x2b,0x2d,0xb0,0x5e,0x2c,0xb3,0x01,0x01,0x01,0x43,0x2b,0x2d,0xb0,0x5f,0x2c,0xb2,0x00,0x00,0x45,0x2b,0x2d,0xb0,0x60,0x2c,0xb2,0x00,0x01,0x45,0x2b,0x2d,0xb0,0x61,0x2c,0xb2,0x01,0x00,0x45,0x2b,0x2d,0xb0,0x62,0x2c, 0xb2,0x01,0x01,0x45,0x2b,0x2d,0xb0,0x63,0x2c,0xb2,0x00,0x00,0x48,0x2b,0x2d,0xb0,0x64,0x2c,0xb2,0x00,0x01,0x48,0x2b,0x2d,0xb0,0x65,0x2c,0xb2,0x01,0x00,0x48,0x2b,0x2d,0xb0,0x66,0x2c,0xb2,0x01,0x01,0x48,0x2b,0x2d,0xb0,0x67,0x2c,0xb3,0x00,0x00,0x00,0x44,0x2b,0x2d,0xb0,0x68,0x2c,0xb3,0x00,0x01,0x00,0x44,0x2b,0x2d,0xb0,0x69, 0x2c,0xb3,0x01,0x00,0x00,0x44,0x2b,0x2d,0xb0,0x6a,0x2c,0xb3,0x01,0x01,0x00,0x44,0x2b,0x2d,0xb0,0x6b,0x2c,0xb3,0x00,0x00,0x01,0x44,0x2b,0x2d,0xb0,0x6c,0x2c,0xb3,0x00,0x01,0x01,0x44,0x2b,0x2d,0xb0,0x6d,0x2c,0xb3,0x01,0x00,0x01,0x44,0x2b,0x2d,0xb0,0x6e,0x2c,0xb3,0x01,0x01,0x01,0x44,0x2b,0x2d,0xb0,0x6f,0x2c,0xb1,0x00,0x3c, 0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x70,0x2c,0xb1,0x00,0x3c,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x71,0x2c,0xb1,0x00,0x3c,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x72,0x2c,0xb0,0x00,0x16,0xb1,0x00,0x3c,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x73,0x2c,0xb1,0x01,0x3c,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x74,0x2c,0xb1,0x01,0x3c,0x2b,0xb0,0x41, 0x2b,0x2d,0xb0,0x75,0x2c,0xb0,0x00,0x16,0xb1,0x01,0x3c,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x76,0x2c,0xb1,0x00,0x3d,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x77,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x78,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x79,0x2c,0xb1,0x00,0x3d,0x2b,0xb0,0x42,0x2b,0x2d,0xb0, 0x7a,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x7b,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x7c,0x2c,0xb1,0x01,0x3d,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x7d,0x2c,0xb1,0x00,0x3e,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x7e,0x2c,0xb1,0x00,0x3e,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x7f,0x2c,0xb1,0x00,0x3e,0x2b, 0xb0,0x41,0x2b,0x2d,0xb0,0x80,0x2c,0xb1,0x00,0x3e,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x81,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x82,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x83,0x2c,0xb1,0x01,0x3e,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x84,0x2c,0xb1,0x00,0x3f,0x2b,0x2e,0xb1,0x30,0x01,0x14,0x2b,0x2d,0xb0,0x85, 0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x86,0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x87,0x2c,0xb1,0x00,0x3f,0x2b,0xb0,0x42,0x2b,0x2d,0xb0,0x88,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x40,0x2b,0x2d,0xb0,0x89,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x41,0x2b,0x2d,0xb0,0x8a,0x2c,0xb1,0x01,0x3f,0x2b,0xb0,0x42,0x2b,0x2d, 0xb0,0x8b,0x2c,0xb2,0x0b,0x00,0x03,0x45,0x50,0x58,0xb0,0x06,0x1b,0xb2,0x04,0x02,0x03,0x45,0x58,0x23,0x21,0x1b,0x21,0x59,0x59,0x42,0x2b,0xb0,0x08,0x65,0xb0,0x03,0x24,0x50,0x78,0xb1,0x05,0x01,0x15,0x45,0x58,0x30,0x59,0x2d,0x00,0x4b,0xb8,0x00,0xc8,0x52,0x58,0xb1,0x01,0x01,0x8e,0x59,0xb0,0x01,0xb9,0x08,0x00,0x08,0x00,0x63, 0x70,0xb1,0x00,0x07,0x42,0xb6,0x00,0x00,0x41,0x31,0x21,0x05,0x00,0x2a,0xb1,0x00,0x07,0x42,0x40,0x0c,0x4e,0x04,0x46,0x04,0x36,0x08,0x26,0x08,0x18,0x07,0x05,0x0a,0x2a,0xb1,0x00,0x07,0x42,0x40,0x0c,0x52,0x02,0x4a,0x02,0x3e,0x06,0x2e,0x06,0x1f,0x05,0x05,0x0a,0x2a,0xb1,0x00,0x0c,0x42,0xbe,0x13,0xc0,0x11,0xc0,0x0d,0xc0,0x09, 0xc0,0x06,0x40,0x00,0x05,0x00,0x0b,0x2a,0xb1,0x00,0x11,0x42,0xbe,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x05,0x00,0x0b,0x2a,0xb9,0x00,0x03,0x00,0x00,0x44,0xb1,0x24,0x01,0x88,0x51,0x58,0xb0,0x40,0x88,0x58,0xb9,0x00,0x03,0x00,0x64,0x44,0xb1,0x28,0x01,0x88,0x51,0x58,0xb8,0x08,0x00,0x88,0x58,0xb9,0x00,0x03, 0x00,0x00,0x44,0x59,0x1b,0xb1,0x27,0x01,0x88,0x51,0x58,0xba,0x08,0x80,0x00,0x01,0x04,0x40,0x88,0x63,0x54,0x58,0xb9,0x00,0x03,0x00,0x00,0x44,0x59,0x59,0x59,0x59,0x59,0x40,0x0c,0x50,0x02,0x48,0x02,0x38,0x06,0x28,0x06,0x1a,0x05,0x05,0x0e,0x2a,0xb8,0x01,0xff,0x85,0xb0,0x04,0x8d,0xb1,0x02,0x00,0x44,0xb3,0x05,0x64,0x06,0x00, 0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5a,0x00,0x5a,0x00,0x50,0x00,0x50,0x02,0xda,0x00,0x00,0x02,0x26,0x00,0x00, 0xff,0x4c,0x02,0xe4,0xff,0xf6,0x02,0x30,0xff,0xf8,0xff,0x4c,0x00,0x5a,0x00,0x5a,0x00,0x50,0x00,0x50,0x02,0xda,0x00,0x00,0x02,0xda,0x02,0x26,0x00,0x00,0xff,0x4c,0x02,0xe4,0xff,0xf6,0x02,0xe4,0x02,0x2e,0xff,0xf8,0xff,0x4c,0x00,0x5a,0x00,0x5a,0x00,0x50,0x00,0x50,0x02,0xda,0x00,0x00,0x02,0xda,0x02,0x26,0x00,0x00,0xff,0x4c, 0x02,0xe4,0xff,0xf6,0x03,0x09,0x02,0x30,0xff,0xf8,0xff,0x4c,0x00,0x47,0x00,0x47,0x00,0x40,0x00,0x40,0x01,0x3b,0xff,0x7b,0x01,0x40,0xff,0x76,0x00,0x47,0x00,0x47,0x00,0x40,0x00,0x40,0x03,0x3e,0x01,0x7e,0x03,0x43,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xd4,0x00,0x00,0x00,0xec,0x00,0x00,0x01,0x04, 0x00,0x00,0x01,0x1c,0x00,0x00,0x01,0x3c,0x00,0x00,0x01,0x54,0x00,0x00,0x01,0x6c,0x00,0x00,0x01,0x84,0x00,0x00,0x01,0x9c,0x00,0x00,0x01,0xb4,0x00,0x00,0x01,0xcc,0x00,0x00,0x01,0xec,0x00,0x00,0x02,0x04,0x00,0x00,0x02,0x1c,0x00,0x00,0x02,0x34,0x00,0x00,0x02,0x4c,0x00,0x00,0x02,0x64,0x00,0x00,0x02,0x7c,0x00,0x00,0x02,0x94, 0x00,0x00,0x02,0xac,0x00,0x00,0x03,0x78,0x00,0x00,0x03,0x90,0x00,0x00,0x03,0xa8,0x00,0x00,0x04,0x28,0x00,0x00,0x04,0x40,0x00,0x00,0x04,0xe0,0x00,0x00,0x05,0x70,0x00,0x00,0x05,0x88,0x00,0x00,0x05,0xa0,0x00,0x00,0x06,0xb8,0x00,0x00,0x06,0xd0,0x00,0x00,0x06,0xe8,0x00,0x00,0x07,0x58,0x00,0x00,0x07,0xe8,0x00,0x00,0x08,0x00, 0x00,0x00,0x08,0x90,0x00,0x00,0x08,0xec,0x00,0x00,0x09,0x04,0x00,0x00,0x09,0x1c,0x00,0x00,0x09,0x34,0x00,0x00,0x09,0x4c,0x00,0x00,0x09,0x64,0x00,0x00,0x09,0x84,0x00,0x00,0x09,0x9c,0x00,0x00,0x09,0xb4,0x00,0x00,0x09,0xcc,0x00,0x00,0x09,0xe4,0x00,0x00,0x09,0xfc,0x00,0x00,0x0a,0x14,0x00,0x00,0x0a,0x2c,0x00,0x00,0x0a,0x44, 0x00,0x00,0x0a,0x5c,0x00,0x00,0x0b,0x20,0x00,0x00,0x0b,0xf0,0x00,0x00,0x0c,0x08,0x00,0x00,0x0c,0x5c,0x00,0x00,0x0c,0xf4,0x00,0x00,0x0d,0x0c,0x00,0x00,0x0d,0x24,0x00,0x00,0x0d,0x3c,0x00,0x00,0x0d,0x54,0x00,0x00,0x0d,0x6c,0x00,0x00,0x0d,0x84,0x00,0x00,0x0d,0xd8,0x00,0x00,0x0e,0x58,0x00,0x00,0x0e,0x70,0x00,0x00,0x0e,0xc4, 0x00,0x00,0x0e,0xdc,0x00,0x00,0x0e,0xf4,0x00,0x00,0x0f,0x0c,0x00,0x00,0x0f,0x24,0x00,0x00,0x0f,0x3c,0x00,0x00,0x0f,0x54,0x00,0x00,0x0f,0x6c,0x00,0x00,0x0f,0x84,0x00,0x00,0x0f,0x9c,0x00,0x00,0x10,0x50,0x00,0x00,0x10,0x68,0x00,0x00,0x10,0xcc,0x00,0x00,0x10,0xe4,0x00,0x00,0x11,0x44,0x00,0x00,0x11,0x5c,0x00,0x00,0x11,0x98, 0x00,0x00,0x11,0xb0,0x00,0x00,0x11,0xc8,0x00,0x00,0x11,0xe0,0x00,0x00,0x12,0x04,0x00,0x00,0x12,0x64,0x00,0x00,0x12,0xdc,0x00,0x00,0x13,0x40,0x00,0x00,0x13,0x58,0x00,0x00,0x13,0x70,0x00,0x00,0x13,0x88,0x00,0x00,0x14,0x08,0x00,0x00,0x14,0x20,0x00,0x00,0x14,0xa4,0x00,0x00,0x14,0xbc,0x00,0x00,0x14,0xd4,0x00,0x00,0x14,0xec, 0x00,0x00,0x15,0x04,0x00,0x00,0x15,0x24,0x00,0x00,0x15,0x3c,0x00,0x00,0x15,0x54,0x00,0x00,0x15,0x6c,0x00,0x00,0x15,0x84,0x00,0x00,0x15,0x9c,0x00,0x00,0x15,0xb4,0x00,0x00,0x15,0xcc,0x00,0x00,0x16,0x74,0x00,0x00,0x16,0x8c,0x00,0x00,0x16,0xa4,0x00,0x00,0x16,0xbc,0x00,0x00,0x16,0xd4,0x00,0x00,0x16,0xec,0x00,0x00,0x17,0x04, 0x00,0x00,0x17,0x1c,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0xec,0x00,0x00,0x19,0x04,0x00,0x00,0x19,0x1c,0x00,0x00,0x1a,0x7c,0x00,0x00,0x1a,0xe8,0x00,0x00,0x1b,0x5c,0x00,0x00,0x1b,0xfc,0x00,0x00,0x1c,0x7c,0x00,0x00,0x1c,0x94,0x00,0x00,0x1c,0xac,0x00,0x00,0x1c,0xc4,0x00,0x00,0x1d,0x78,0x00,0x00,0x1d,0x90,0x00,0x00,0x1d,0xa8, 0x00,0x00,0x1e,0xe4,0x00,0x00,0x1e,0xfc,0x00,0x00,0x1f,0x14,0x00,0x00,0x1f,0xac,0x00,0x00,0x20,0x4c,0x00,0x00,0x20,0x90,0x00,0x00,0x20,0xf4,0x00,0x00,0x21,0x0c,0x00,0x00,0x21,0xc8,0x00,0x00,0x21,0xe0,0x00,0x00,0x22,0x40,0x00,0x00,0x22,0x58,0x00,0x00,0x22,0x70,0x00,0x00,0x22,0x88,0x00,0x00,0x22,0xa0,0x00,0x00,0x22,0xb8, 0x00,0x00,0x22,0xd0,0x00,0x00,0x22,0xe8,0x00,0x00,0x23,0x6c,0x00,0x00,0x23,0x84,0x00,0x00,0x23,0x9c,0x00,0x00,0x23,0xb4,0x00,0x00,0x23,0xcc,0x00,0x00,0x23,0xe4,0x00,0x00,0x23,0xfc,0x00,0x00,0x24,0x14,0x00,0x00,0x24,0xcc,0x00,0x00,0x24,0xe4,0x00,0x00,0x24,0xfc,0x00,0x00,0x25,0x54,0x00,0x00,0x25,0xe8,0x00,0x00,0x26,0x00, 0x00,0x00,0x26,0x18,0x00,0x00,0x26,0x30,0x00,0x00,0x26,0x48,0x00,0x00,0x26,0xc4,0x00,0x00,0x27,0x24,0x00,0x00,0x27,0x3c,0x00,0x00,0x27,0x54,0x00,0x00,0x27,0x6c,0x00,0x00,0x27,0x84,0x00,0x00,0x27,0x9c,0x00,0x00,0x27,0xb4,0x00,0x00,0x27,0xcc,0x00,0x00,0x27,0xe4,0x00,0x00,0x28,0x3c,0x00,0x00,0x28,0x54,0x00,0x00,0x28,0x6c, 0x00,0x00,0x28,0x84,0x00,0x00,0x29,0x10,0x00,0x00,0x29,0x28,0x00,0x00,0x29,0x40,0x00,0x00,0x29,0x58,0x00,0x00,0x29,0x70,0x00,0x00,0x29,0xcc,0x00,0x00,0x29,0xe4,0x00,0x00,0x2a,0x94,0x00,0x00,0x2b,0x88,0x00,0x00,0x2b,0xa0,0x00,0x00,0x2b,0xb8,0x00,0x00,0x2b,0xd0,0x00,0x00,0x2b,0xf0,0x00,0x00,0x2c,0x08,0x00,0x00,0x2c,0x20, 0x00,0x00,0x2c,0x38,0x00,0x00,0x2c,0x50,0x00,0x00,0x2c,0x68,0x00,0x00,0x2c,0x80,0x00,0x00,0x2c,0xa0,0x00,0x00,0x2c,0xb8,0x00,0x00,0x2c,0xd0,0x00,0x00,0x2c,0xe8,0x00,0x00,0x2d,0x00,0x00,0x00,0x2d,0x18,0x00,0x00,0x2d,0x30,0x00,0x00,0x2d,0x48,0x00,0x00,0x2d,0x60,0x00,0x00,0x2e,0xe0,0x00,0x00,0x2e,0xf8,0x00,0x00,0x2f,0x10, 0x00,0x00,0x30,0x6c,0x00,0x00,0x30,0x84,0x00,0x00,0x31,0x54,0x00,0x00,0x31,0xe4,0x00,0x00,0x31,0xfc,0x00,0x00,0x32,0x14,0x00,0x00,0x33,0x2c,0x00,0x00,0x33,0x44,0x00,0x00,0x33,0x5c,0x00,0x00,0x34,0x2c,0x00,0x00,0x35,0x00,0x00,0x00,0x35,0xf8,0x00,0x00,0x36,0xf0,0x00,0x00,0x37,0x94,0x00,0x00,0x37,0xac,0x00,0x00,0x37,0xc4, 0x00,0x00,0x37,0xdc,0x00,0x00,0x37,0xf4,0x00,0x00,0x38,0x0c,0x00,0x00,0x38,0x2c,0x00,0x00,0x38,0x44,0x00,0x00,0x38,0x5c,0x00,0x00,0x38,0x74,0x00,0x00,0x38,0x8c,0x00,0x00,0x38,0xa4,0x00,0x00,0x38,0xbc,0x00,0x00,0x38,0xd4,0x00,0x00,0x38,0xec,0x00,0x00,0x39,0x04,0x00,0x00,0x3a,0x0c,0x00,0x00,0x3a,0x24,0x00,0x00,0x3a,0xc4, 0x00,0x00,0x3b,0x28,0x00,0x00,0x3c,0x10,0x00,0x00,0x3c,0x28,0x00,0x00,0x3c,0x40,0x00,0x00,0x3c,0x58,0x00,0x00,0x3c,0x70,0x00,0x00,0x3c,0x88,0x00,0x00,0x3c,0xa0,0x00,0x00,0x3d,0x10,0x00,0x00,0x3d,0x20,0x00,0x00,0x3d,0x44,0x00,0x00,0x3d,0x5c,0x00,0x00,0x3d,0xa8,0x00,0x00,0x3d,0xc0,0x00,0x00,0x3d,0xd8,0x00,0x00,0x3d,0xf0, 0x00,0x00,0x3e,0x08,0x00,0x00,0x3e,0x20,0x00,0x00,0x3e,0x38,0x00,0x00,0x3e,0x58,0x00,0x00,0x3e,0x70,0x00,0x00,0x3e,0x88,0x00,0x00,0x3e,0xa0,0x00,0x00,0x3f,0xc8,0x00,0x00,0x3f,0xe0,0x00,0x00,0x3f,0xf8,0x00,0x00,0x40,0x50,0x00,0x00,0x40,0x68,0x00,0x00,0x40,0xcc,0x00,0x00,0x40,0xe4,0x00,0x00,0x40,0xf4,0x00,0x00,0x41,0x4c, 0x00,0x00,0x41,0x64,0x00,0x00,0x41,0xe0,0x00,0x00,0x41,0xf8,0x00,0x00,0x42,0x10,0x00,0x00,0x42,0x34,0x00,0x00,0x42,0xa4,0x00,0x00,0x43,0x64,0x00,0x00,0x43,0xf4,0x00,0x00,0x44,0x0c,0x00,0x00,0x44,0x30,0x00,0x00,0x44,0x48,0x00,0x00,0x44,0x60,0x00,0x00,0x45,0x14,0x00,0x00,0x45,0x2c,0x00,0x00,0x45,0xac,0x00,0x00,0x45,0xc4, 0x00,0x00,0x45,0xdc,0x00,0x00,0x45,0xf4,0x00,0x00,0x46,0x0c,0x00,0x00,0x46,0x24,0x00,0x00,0x46,0x44,0x00,0x00,0x46,0x5c,0x00,0x00,0x46,0x74,0x00,0x00,0x46,0x8c,0x00,0x00,0x46,0xa4,0x00,0x00,0x46,0xbc,0x00,0x00,0x46,0xd4,0x00,0x00,0x46,0xec,0x00,0x00,0x47,0xc8,0x00,0x00,0x47,0xe0,0x00,0x00,0x47,0xf8,0x00,0x00,0x48,0x10, 0x00,0x00,0x48,0x28,0x00,0x00,0x48,0x40,0x00,0x00,0x48,0x58,0x00,0x00,0x48,0x70,0x00,0x00,0x49,0x54,0x00,0x00,0x4a,0x18,0x00,0x00,0x4a,0x30,0x00,0x00,0x4a,0x48,0x00,0x00,0x4b,0x50,0x00,0x00,0x4c,0x1c,0x00,0x00,0x4c,0xf0,0x00,0x00,0x4d,0xc0,0x00,0x00,0x4e,0x58,0x00,0x00,0x4e,0x70,0x00,0x00,0x4e,0x88,0x00,0x00,0x4e,0xa0, 0x00,0x00,0x4f,0x50,0x00,0x00,0x4f,0x68,0x00,0x00,0x4f,0x80,0x00,0x00,0x50,0xb4,0x00,0x00,0x50,0xcc,0x00,0x00,0x50,0xe4,0x00,0x00,0x51,0x90,0x00,0x00,0x51,0xdc,0x00,0x00,0x52,0x4c,0x00,0x00,0x52,0xd4,0x00,0x00,0x52,0xf8,0x00,0x00,0x53,0xe8,0x00,0x00,0x54,0x00,0x00,0x00,0x54,0x60,0x00,0x00,0x54,0x78,0x00,0x00,0x54,0x90, 0x00,0x00,0x54,0xa8,0x00,0x00,0x54,0xc0,0x00,0x00,0x54,0xd8,0x00,0x00,0x55,0x04,0x00,0x00,0x55,0x30,0x00,0x00,0x55,0x5c,0x00,0x00,0x55,0x88,0x00,0x00,0x55,0xa0,0x00,0x00,0x55,0xb8,0x00,0x00,0x55,0xd0,0x00,0x00,0x56,0x6c,0x00,0x00,0x56,0x84,0x00,0x00,0x56,0x9c,0x00,0x00,0x56,0xb4,0x00,0x00,0x56,0xcc,0x00,0x00,0x56,0xe4, 0x00,0x00,0x56,0xfc,0x00,0x00,0x57,0x14,0x00,0x00,0x57,0xc8,0x00,0x00,0x57,0xe0,0x00,0x00,0x57,0xf8,0x00,0x00,0x58,0x50,0x00,0x00,0x58,0xe8,0x00,0x00,0x59,0x00,0x00,0x00,0x59,0x18,0x00,0x00,0x59,0x30,0x00,0x00,0x59,0x48,0x00,0x00,0x59,0xc4,0x00,0x00,0x5a,0x24,0x00,0x00,0x5a,0x3c,0x00,0x00,0x5a,0x54,0x00,0x00,0x5a,0x6c, 0x00,0x00,0x5a,0x84,0x00,0x00,0x5a,0x9c,0x00,0x00,0x5a,0xb4,0x00,0x00,0x5a,0xcc,0x00,0x00,0x5a,0xe4,0x00,0x00,0x5b,0x3c,0x00,0x00,0x5b,0x54,0x00,0x00,0x5b,0x6c,0x00,0x00,0x5b,0x84,0x00,0x00,0x5b,0x94,0x00,0x00,0x5b,0xe0,0x00,0x00,0x5b,0xf8,0x00,0x00,0x5c,0x10,0x00,0x00,0x5c,0x28,0x00,0x00,0x5c,0x4c,0x00,0x00,0x5c,0xbc, 0x00,0x00,0x5d,0x48,0x00,0x00,0x5d,0xe8,0x00,0x00,0x5e,0x0c,0x00,0x00,0x5f,0x20,0x00,0x00,0x5f,0x38,0x00,0x00,0x60,0xbc,0x00,0x00,0x60,0xd4,0x00,0x00,0x60,0xec,0x00,0x00,0x61,0x04,0x00,0x00,0x61,0x1c,0x00,0x00,0x61,0x34,0x00,0x00,0x61,0x4c,0x00,0x00,0x61,0x64,0x00,0x00,0x62,0x04,0x00,0x00,0x62,0x1c,0x00,0x00,0x62,0x90, 0x00,0x00,0x62,0xa8,0x00,0x00,0x62,0xc0,0x00,0x00,0x62,0xd8,0x00,0x00,0x63,0x7c,0x00,0x00,0x64,0x04,0x00,0x00,0x64,0xd0,0x00,0x00,0x65,0x5c,0x00,0x00,0x65,0x74,0x00,0x00,0x65,0x8c,0x00,0x00,0x65,0xa4,0x00,0x00,0x65,0xbc,0x00,0x00,0x66,0x1c,0x00,0x00,0x66,0x34,0x00,0x00,0x66,0x44,0x00,0x00,0x66,0xb8,0x00,0x00,0x67,0x64, 0x00,0x00,0x67,0x7c,0x00,0x00,0x67,0x94,0x00,0x00,0x67,0xac,0x00,0x00,0x68,0x1c,0x00,0x00,0x68,0x34,0x00,0x00,0x68,0x4c,0x00,0x00,0x68,0x64,0x00,0x00,0x68,0x7c,0x00,0x00,0x68,0x94,0x00,0x00,0x68,0xac,0x00,0x00,0x68,0xc4,0x00,0x00,0x68,0xdc,0x00,0x00,0x69,0x6c,0x00,0x00,0x6a,0x28,0x00,0x00,0x6b,0x0c,0x00,0x00,0x6b,0xdc, 0x00,0x00,0x6d,0x00,0x00,0x00,0x6d,0xcc,0x00,0x00,0x6e,0x8c,0x00,0x00,0x6f,0x9c,0x00,0x00,0x70,0x80,0x00,0x00,0x70,0x98,0x00,0x00,0x70,0xb0,0x00,0x00,0x70,0xc8,0x00,0x00,0x70,0xe0,0x00,0x00,0x70,0xf8,0x00,0x00,0x71,0xd0,0x00,0x00,0x72,0xb8,0x00,0x00,0x73,0xc0,0x00,0x00,0x74,0xc8,0x00,0x00,0x76,0x48,0x00,0x00,0x76,0xcc, 0x00,0x00,0x77,0x44,0x00,0x00,0x77,0xac,0x00,0x00,0x78,0xa8,0x00,0x00,0x79,0x30,0x00,0x00,0x79,0x40,0x00,0x00,0x79,0xb8,0x00,0x00,0x79,0xc8,0x00,0x00,0x7a,0x08,0x00,0x00,0x7a,0x20,0x00,0x00,0x7a,0x8c,0x00,0x00,0x7b,0x0c,0x00,0x00,0x7b,0x1c,0x00,0x00,0x7b,0x34,0x00,0x00,0x7b,0xb8,0x00,0x00,0x7c,0x88,0x00,0x00,0x7c,0xec, 0x00,0x00,0x7d,0x04,0x00,0x00,0x7d,0x14,0x00,0x00,0x7d,0x2c,0x00,0x00,0x7d,0xb4,0x00,0x00,0x7d,0xc4,0x00,0x00,0x7d,0xd4,0x00,0x00,0x7d,0xe4,0x00,0x00,0x7e,0x28,0x00,0x00,0x7e,0x38,0x00,0x00,0x7e,0x48,0x00,0x00,0x7e,0x58,0x00,0x00,0x7e,0xb4,0x00,0x00,0x7e,0xcc,0x00,0x00,0x7f,0xf0,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x5c, 0x00,0x00,0x80,0xb4,0x00,0x00,0x81,0x08,0x00,0x00,0x81,0x6c,0x00,0x00,0x81,0xe4,0x00,0x00,0x82,0x54,0x00,0x00,0x82,0xd0,0x00,0x00,0x83,0x58,0x00,0x00,0x84,0x28,0x00,0x00,0x84,0xb4,0x00,0x00,0x84,0xc4,0x00,0x00,0x85,0x68,0x00,0x00,0x85,0xfc,0x00,0x00,0x86,0x0c,0x00,0x00,0x86,0x24,0x00,0x00,0x86,0x34,0x00,0x00,0x86,0xb0, 0x00,0x00,0x87,0x8c,0x00,0x00,0x88,0x14,0x00,0x00,0x88,0xac,0x00,0x00,0x89,0x08,0x00,0x00,0x89,0x7c,0x00,0x00,0x89,0xe0,0x00,0x00,0x89,0xf0,0x00,0x00,0x8a,0x68,0x00,0x00,0x8a,0xd4,0x00,0x00,0x8b,0x30,0x00,0x00,0x8b,0xd0,0x00,0x00,0x8b,0xe8,0x00,0x00,0x8c,0x00,0x00,0x00,0x8c,0x18,0x00,0x00,0x8c,0x30,0x00,0x00,0x8c,0xcc, 0x00,0x00,0x8c,0xe4,0x00,0x00,0x8d,0x64,0x00,0x00,0x8d,0x74,0x00,0x00,0x8d,0x8c,0x00,0x00,0x8d,0xfc,0x00,0x00,0x8e,0x70,0x00,0x00,0x8e,0x88,0x00,0x00,0x8f,0x60,0x00,0x00,0x8f,0x70,0x00,0x00,0x90,0x14,0x00,0x00,0x90,0xb4,0x00,0x00,0x90,0xf4,0x00,0x00,0x91,0x0c,0x00,0x00,0x91,0x78,0x00,0x00,0x91,0xf8,0x00,0x00,0x92,0x08, 0x00,0x00,0x92,0x20,0x00,0x00,0x92,0x9c,0x00,0x00,0x93,0x68,0x00,0x00,0x93,0xc8,0x00,0x00,0x93,0xe0,0x00,0x00,0x94,0x3c,0x00,0x00,0x94,0x54,0x00,0x00,0x94,0xdc,0x00,0x00,0x95,0x4c,0x00,0x00,0x95,0x9c,0x00,0x00,0x95,0xac,0x00,0x00,0x95,0xf0,0x00,0x00,0x96,0x00,0x00,0x00,0x96,0x10,0x00,0x00,0x96,0x54,0x00,0x00,0x96,0x64, 0x00,0x00,0x96,0x7c,0x00,0x00,0x97,0x34,0x00,0x00,0x97,0x44,0x00,0x00,0x97,0x9c,0x00,0x00,0x97,0xf4,0x00,0x00,0x98,0x48,0x00,0x00,0x98,0xac,0x00,0x00,0x99,0x24,0x00,0x00,0x99,0x90,0x00,0x00,0x9a,0x04,0x00,0x00,0x9a,0x88,0x00,0x00,0x9b,0x8c,0x00,0x00,0x9c,0x14,0x00,0x00,0x9c,0x24,0x00,0x00,0x9c,0xc8,0x00,0x00,0x9d,0x6c, 0x00,0x00,0x9d,0x84,0x00,0x00,0x9d,0x9c,0x00,0x00,0x9d,0xb4,0x00,0x00,0x9e,0x40,0x00,0x00,0x9f,0x18,0x00,0x00,0x9f,0x98,0x00,0x00,0xa0,0x40,0x00,0x00,0xa0,0x9c,0x00,0x00,0xa1,0x08,0x00,0x00,0xa1,0x68,0x00,0x00,0xa1,0x78,0x00,0x00,0xa1,0xf0,0x00,0x00,0xa2,0x5c,0x00,0x00,0xa2,0xb8,0x00,0x00,0xa3,0x5c,0x00,0x00,0xa3,0x74, 0x00,0x00,0xa3,0x8c,0x00,0x00,0xa3,0xa4,0x00,0x00,0xa3,0xbc,0x00,0x00,0xa4,0x58,0x00,0x00,0xa4,0x70,0x00,0x00,0xa4,0x88,0x00,0x00,0xa5,0x08,0x00,0x00,0xa5,0x64,0x00,0x00,0xa5,0x7c,0x00,0x00,0xa5,0xe8,0x00,0x00,0xa5,0xf8,0x00,0x00,0xa6,0x10,0x00,0x00,0xa6,0xbc,0x00,0x00,0xa6,0xcc,0x00,0x00,0xa6,0xdc,0x00,0x00,0xa6,0xec, 0x00,0x00,0xa7,0x50,0x00,0x00,0xa7,0x60,0x00,0x00,0xa7,0x70,0x00,0x00,0xa7,0x80,0x00,0x00,0xa8,0x20,0x00,0x00,0xa8,0x30,0x00,0x00,0xa8,0x40,0x00,0x00,0xa8,0x90,0x00,0x00,0xa8,0xa0,0x00,0x00,0xa8,0xb0,0x00,0x00,0xa9,0x24,0x00,0x00,0xa9,0x34,0x00,0x00,0xa9,0x44,0x00,0x00,0xa9,0x54,0x00,0x00,0xa9,0xbc,0x00,0x00,0xa9,0xcc, 0x00,0x00,0xa9,0xdc,0x00,0x00,0xa9,0xec,0x00,0x00,0xa9,0xfc,0x00,0x00,0xaa,0x78,0x00,0x00,0xab,0x44,0x00,0x00,0xab,0x5c,0x00,0x00,0xab,0x74,0x00,0x00,0xab,0x8c,0x00,0x00,0xab,0xa4,0x00,0x00,0xab,0xbc,0x00,0x00,0xab,0xd4,0x00,0x00,0xab,0xec,0x00,0x00,0xac,0x04,0x00,0x00,0xac,0x1c,0x00,0x00,0xac,0xac,0x00,0x00,0xac,0xbc, 0x00,0x00,0xad,0x48,0x00,0x00,0xae,0x14,0x00,0x00,0xae,0xe8,0x00,0x00,0xaf,0x48,0x00,0x00,0xaf,0xf4,0x00,0x00,0xb0,0xc4,0x00,0x00,0xb1,0x40,0x00,0x00,0xb1,0x50,0x00,0x00,0xb1,0xec,0x00,0x00,0xb2,0x44,0x00,0x00,0xb2,0x54,0x00,0x00,0xb2,0xb0,0x00,0x00,0xb3,0x54,0x00,0x00,0xb3,0x64,0x00,0x00,0xb4,0x2c,0x00,0x00,0xb4,0x3c, 0x00,0x00,0xb4,0xd4,0x00,0x00,0xb5,0x6c,0x00,0x00,0xb5,0xf0,0x00,0x00,0xb6,0x88,0x00,0x00,0xb6,0xe8,0x00,0x00,0xb6,0xf8,0x00,0x00,0xb7,0xa8,0x00,0x00,0xb7,0xb8,0x00,0x00,0xb8,0x30,0x00,0x00,0xb8,0xe4,0x00,0x00,0xb8,0xfc,0x00,0x00,0xb9,0x14,0x00,0x00,0xb9,0x2c,0x00,0x00,0xb9,0x44,0x00,0x00,0xb9,0x5c,0x00,0x00,0xb9,0x74, 0x00,0x00,0xb9,0x8c,0x00,0x00,0xb9,0xa4,0x00,0x00,0xba,0x9c,0x00,0x00,0xbc,0x6c,0x00,0x00,0xbc,0x84,0x00,0x00,0xbd,0x10,0x00,0x00,0xbd,0x20,0x00,0x00,0xbd,0xe4,0x00,0x00,0xbd,0xf4,0x00,0x00,0xbe,0x6c,0x00,0x00,0xbf,0x20,0x00,0x00,0xbf,0x20,0x00,0x00,0xbf,0xac,0x00,0x00,0xc0,0x98,0x00,0x00,0xc1,0x48,0x00,0x00,0xc1,0xe8, 0x00,0x00,0xc2,0x58,0x00,0x00,0xc2,0xc0,0x00,0x00,0xc3,0x90,0x00,0x00,0xc4,0x18,0x00,0x00,0xc4,0x7c,0x00,0x00,0xc5,0x0c,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc5,0xf4,0x00,0x00,0xc6,0x9c,0x00,0x00,0xc7,0x1c,0x00,0x00,0xc7,0xd8,0x00,0x00,0xc8,0x78,0x00,0x00,0xc9,0x50,0x00,0x00,0xca,0x20,0x00,0x00,0xcb,0x18,0x00,0x00,0xcb,0x70, 0x00,0x00,0xcb,0xf0,0x00,0x00,0xcc,0x64,0x00,0x00,0xcd,0x3c,0x00,0x00,0xcd,0xb8,0x00,0x00,0xce,0x3c,0x00,0x00,0xce,0xb8,0x00,0x00,0xd0,0x00,0x00,0x00,0xd1,0x24,0x00,0x00,0xd1,0xd0,0x00,0x00,0xd2,0xf0,0x00,0x00,0xd3,0xc4,0x00,0x00,0xd4,0x54,0x00,0x00,0xd5,0x88,0x00,0x00,0xd6,0x24,0x00,0x00,0xd7,0x24,0x00,0x00,0xd8,0x30, 0x00,0x00,0xd8,0xc4,0x00,0x00,0xd9,0x30,0x00,0x00,0xda,0x80,0x00,0x00,0xdb,0x54,0x00,0x00,0xdc,0x0c,0x00,0x00,0xdd,0x28,0x00,0x00,0xde,0x48,0x00,0x00,0xdf,0x14,0x00,0x00,0xe0,0x10,0x00,0x00,0xe0,0xac,0x00,0x00,0xe1,0x2c,0x00,0x00,0xe1,0xa0,0x00,0x00,0xe2,0x80,0x00,0x00,0xe2,0xf4,0x00,0x00,0xe3,0x84,0x00,0x00,0xe3,0xf0, 0x00,0x00,0xe4,0xa8,0x00,0x00,0xe4,0xfc,0x00,0x00,0xe5,0x80,0x00,0x00,0xe6,0x18,0x00,0x00,0xe6,0x78,0x00,0x00,0xe7,0x08,0x00,0x00,0xe7,0xac,0x00,0x00,0xe8,0x28,0x00,0x00,0xe9,0x0c,0x00,0x00,0xe9,0xac,0x00,0x00,0xea,0x50,0x00,0x00,0xea,0xe4,0x00,0x00,0xeb,0xa4,0x00,0x00,0xec,0x68,0x00,0x00,0xed,0x48,0x00,0x00,0xed,0xf8, 0x00,0x00,0xee,0x18,0x00,0x00,0xee,0x38,0x00,0x00,0xee,0x58,0x00,0x00,0xee,0x78,0x00,0x00,0xee,0x98,0x00,0x00,0xee,0xb8,0x00,0x00,0xee,0xd8,0x00,0x00,0xee,0xf8,0x00,0x00,0xef,0x18,0x00,0x00,0xef,0x38,0x00,0x00,0xef,0x58,0x00,0x00,0xef,0x78,0x00,0x00,0xef,0x98,0x00,0x00,0xef,0xb8,0x00,0x00,0xef,0xd8,0x00,0x00,0xef,0xf8, 0x00,0x00,0xf0,0x18,0x00,0x00,0xf0,0x38,0x00,0x00,0xf0,0x58,0x00,0x00,0xf0,0x78,0x00,0x00,0xf0,0x94,0x00,0x00,0xf0,0xb0,0x00,0x00,0xf0,0xcc,0x00,0x00,0xf0,0xe8,0x00,0x00,0xf1,0x04,0x00,0x00,0xf1,0x20,0x00,0x00,0xf1,0x3c,0x00,0x00,0xf1,0x58,0x00,0x00,0xf1,0x74,0x00,0x00,0xf1,0x90,0x00,0x00,0xf2,0x14,0x00,0x00,0xf2,0x68, 0x00,0x00,0xf2,0xf0,0x00,0x00,0xf3,0x84,0x00,0x00,0xf3,0xe4,0x00,0x00,0xf4,0x70,0x00,0x00,0xf5,0x04,0x00,0x00,0xf5,0x80,0x00,0x00,0xf6,0x58,0x00,0x00,0xf6,0xec,0x00,0x00,0xf7,0x0c,0x00,0x00,0xf7,0x2c,0x00,0x00,0xf7,0x4c,0x00,0x00,0xf7,0x6c,0x00,0x00,0xf7,0x8c,0x00,0x00,0xf7,0xac,0x00,0x00,0xf7,0xc8,0x00,0x00,0xf7,0xe4, 0x00,0x00,0xf8,0x00,0x00,0x00,0xf8,0x88,0x00,0x00,0xf9,0x48,0x00,0x00,0xfa,0x04,0x00,0x00,0xfa,0x24,0x00,0x00,0xfa,0x44,0x00,0x00,0xfa,0x60,0x00,0x00,0xfb,0x44,0x00,0x00,0xfb,0x64,0x00,0x00,0xfb,0x80,0x00,0x00,0xfb,0x9c,0x00,0x00,0xfc,0x4c,0x00,0x00,0xfc,0x84,0x00,0x00,0xfd,0x78,0x00,0x00,0xfe,0x44,0x00,0x00,0xff,0x98, 0x00,0x00,0xff,0xb8,0x00,0x00,0xff,0xc8,0x00,0x00,0xff,0xe8,0x00,0x01,0x00,0x70,0x00,0x01,0x01,0x10,0x00,0x01,0x01,0x58,0x00,0x01,0x01,0xa8,0x00,0x01,0x02,0x24,0x00,0x01,0x02,0xb4,0x00,0x01,0x03,0x5c,0x00,0x01,0x03,0xc8,0x00,0x01,0x04,0x38,0x00,0x01,0x05,0x0c,0x00,0x01,0x05,0xe8,0x00,0x01,0x06,0x08,0x00,0x01,0x06,0x54, 0x00,0x01,0x07,0x00,0x00,0x01,0x07,0x5c,0x00,0x01,0x07,0xb4,0x00,0x01,0x07,0xfc,0x00,0x01,0x08,0x14,0x00,0x01,0x08,0xbc,0x00,0x01,0x09,0x60,0x00,0x01,0x09,0x70,0x00,0x01,0x09,0xb0,0x00,0x01,0x09,0xe4,0x00,0x01,0x0a,0x1c,0x00,0x01,0x0a,0x74,0x00,0x01,0x0a,0xf4,0x00,0x01,0x0b,0x14,0x00,0x01,0x0b,0x34,0x00,0x01,0x0b,0x78, 0x00,0x01,0x0b,0xbc,0x00,0x01,0x0c,0x6c,0x00,0x01,0x0d,0x1c,0x00,0x01,0x0d,0x68,0x00,0x01,0x0d,0xb4,0x00,0x01,0x0d,0xc4,0x00,0x01,0x0d,0xd4,0x00,0x01,0x0e,0x14,0x00,0x01,0x0e,0x58,0x00,0x01,0x0e,0x94,0x00,0x01,0x0e,0xd0,0x00,0x01,0x0f,0x14,0x00,0x01,0x0f,0x58,0x00,0x01,0x10,0x24,0x00,0x01,0x10,0x68,0x00,0x01,0x10,0xac, 0x00,0x01,0x11,0x70,0x00,0x01,0x11,0xbc,0x00,0x01,0x12,0x04,0x00,0x01,0x12,0x3c,0x00,0x01,0x12,0x4c,0x00,0x01,0x12,0x84,0x00,0x01,0x12,0xbc,0x00,0x01,0x12,0xcc,0x00,0x01,0x13,0x0c,0x00,0x01,0x13,0x7c,0x00,0x01,0x13,0x94,0x00,0x01,0x14,0x20,0x00,0x01,0x14,0x50,0x00,0x01,0x14,0xa4,0x00,0x01,0x14,0xc4,0x00,0x01,0x15,0x14, 0x00,0x01,0x15,0x94,0x00,0x01,0x15,0xfc,0x00,0x01,0x16,0x64,0x00,0x01,0x16,0xac,0x00,0x01,0x16,0xf0,0x00,0x01,0x17,0x30,0x00,0x01,0x17,0x48,0x00,0x01,0x17,0x80,0x00,0x01,0x17,0xd0,0x00,0x01,0x18,0x38,0x00,0x01,0x19,0xa4,0x00,0x01,0x1a,0x04,0x00,0x01,0x1a,0x70,0x00,0x01,0x1a,0xd8,0x00,0x01,0x1b,0x78,0x00,0x01,0x1b,0xd4, 0x00,0x01,0x1c,0x58,0x00,0x01,0x1d,0x1c,0x00,0x01,0x1d,0x34,0x00,0x01,0x1e,0xa8,0x00,0x01,0x20,0x1c,0x00,0x01,0x20,0x3c,0x00,0x01,0x21,0x00,0x00,0x01,0x21,0x18,0x00,0x01,0x21,0x7c,0x00,0x01,0x21,0xa0,0x00,0x01,0x22,0x74,0x00,0x01,0x22,0x8c,0x00,0x01,0x22,0xac,0x00,0x01,0x22,0xd0,0x00,0x01,0x22,0xe8,0x00,0x01,0x23,0x0c, 0x00,0x01,0x23,0x24,0x00,0x01,0x23,0x48,0x00,0x01,0x23,0x7c,0x00,0x01,0x23,0x94,0x00,0x01,0x25,0xa8,0x00,0x01,0x26,0x8c,0x00,0x01,0x26,0xb0,0x00,0x01,0x26,0xd4,0x00,0x01,0x26,0xec,0x00,0x01,0x27,0x10,0x00,0x01,0x27,0x28,0x00,0x01,0x27,0x48,0x00,0x01,0x27,0xc4,0x00,0x01,0x28,0x70,0x00,0x01,0x28,0x88,0x00,0x01,0x28,0xa0, 0x00,0x01,0x28,0xb8,0x00,0x01,0x28,0xd8,0x00,0x01,0x2a,0x04,0x00,0x01,0x2a,0x30,0x00,0x01,0x2a,0x48,0x00,0x01,0x2a,0x6c,0x00,0x01,0x2b,0x50,0x00,0x01,0x2c,0xe8,0x00,0x01,0x2d,0xc0,0x00,0x01,0x2f,0x0c,0x00,0x01,0x30,0x54,0x00,0x01,0x32,0x24,0x00,0x01,0x33,0x30,0x00,0x01,0x34,0xa8,0x00,0x01,0x36,0x88,0x00,0x01,0x37,0xe0, 0x00,0x01,0x38,0x98,0x00,0x01,0x39,0x88,0x00,0x01,0x39,0xac,0x00,0x01,0x39,0xe0,0x00,0x01,0x3a,0x48,0x00,0x01,0x3a,0xb0,0x00,0x01,0x3b,0x1c,0x00,0x01,0x3b,0x34,0x00,0x01,0x3b,0xb8,0x00,0x01,0x3b,0xd8,0x00,0x01,0x3c,0x28,0x00,0x01,0x3c,0x78,0x00,0x01,0x3c,0xe0,0x00,0x01,0x3d,0x18,0x00,0x01,0x3d,0xc0,0x00,0x01,0x3e,0x94, 0x00,0x01,0x3e,0xdc,0x00,0x01,0x3f,0x50,0x00,0x01,0x3f,0xb0,0x00,0x01,0x3f,0xf8,0x00,0x01,0x40,0x5c,0x00,0x01,0x40,0xbc,0x00,0x01,0x40,0xdc,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x40,0xec,0x00,0x01,0x41,0xc4,0x00,0x01,0x42,0x78, 0x00,0x01,0x43,0x68,0x00,0x01,0x44,0x40,0x00,0x01,0x45,0x5c,0x00,0x01,0x46,0x2c,0x00,0x01,0x46,0xa8,0x00,0x01,0x47,0x94,0x00,0x01,0x48,0x30,0x00,0x01,0x48,0xe8,0x00,0x01,0x49,0x68,0x00,0x01,0x4a,0x00,0x00,0x01,0x4a,0xa8,0x00,0x01,0x4b,0x68,0x00,0x01,0x4c,0x48,0x00,0x01,0x4c,0xf0,0x00,0x01,0x4d,0x8c,0x00,0x01,0x4d,0xd4, 0x00,0x01,0x4d,0xf0,0x00,0x01,0x4e,0xa8,0x00,0x01,0x4f,0x74,0x00,0x01,0x50,0x7c,0x00,0x01,0x50,0xd4,0x00,0x01,0x51,0x08,0x00,0x01,0x51,0x64,0x00,0x01,0x51,0x98,0x00,0x01,0x51,0xc8,0x00,0x01,0x51,0xd8,0x00,0x01,0x52,0x34,0x00,0x01,0x52,0xa0,0x00,0x01,0x53,0x5c,0x00,0x01,0x54,0x08,0x00,0x01,0x54,0x94,0x00,0x01,0x55,0x10, 0x00,0x01,0x55,0xbc,0x00,0x01,0x55,0xec,0x00,0x01,0x56,0x44,0x00,0x01,0x56,0xb8,0x00,0x01,0x57,0x5c,0x00,0x01,0x57,0xf8,0x00,0x01,0x58,0x58,0x00,0x01,0x58,0xc0,0x00,0x01,0x59,0xb8,0x00,0x01,0x5a,0x50,0x00,0x01,0x5a,0xa0,0x00,0x01,0x5b,0x2c,0x00,0x01,0x5b,0x7c,0x00,0x01,0x5b,0xf8,0x00,0x01,0x5c,0x48,0x00,0x01,0x5c,0x90, 0x00,0x01,0x5c,0xc4,0x00,0x01,0x5d,0x08,0x00,0x01,0x5d,0x4c,0x00,0x01,0x5e,0x04,0x00,0x01,0x5e,0xa4,0x00,0x01,0x5f,0x04,0x00,0x01,0x5f,0x68,0x00,0x01,0x5f,0xd0,0x00,0x01,0x60,0x60,0x00,0x01,0x61,0x00,0x00,0x01,0x61,0xc4,0x00,0x01,0x62,0x0c,0x00,0x01,0x62,0x58,0x00,0x01,0x62,0xdc,0x00,0x01,0x63,0x40,0x00,0x01,0x63,0xa0, 0x00,0x01,0x64,0xe8,0x00,0x01,0x66,0x2c,0x00,0x01,0x67,0x3c,0x00,0x01,0x67,0xc0,0x00,0x01,0x68,0x30,0x00,0x01,0x69,0xc0,0x00,0x01,0x6a,0xd4,0x00,0x01,0x6b,0xe4,0x00,0x01,0x6c,0xb0,0x00,0x01,0x6d,0x2c,0x00,0x01,0x6e,0x08,0x00,0x01,0x6f,0x24,0x00,0x01,0x6f,0xa8,0x00,0x01,0x70,0x84,0x00,0x01,0x71,0xa8,0x00,0x01,0x72,0x50, 0x00,0x01,0x72,0xfc,0x00,0x01,0x73,0x74,0x00,0x01,0x73,0x84,0x00,0x01,0x73,0xbc,0x00,0x01,0x74,0x58,0x00,0x01,0x74,0xb0,0x00,0x01,0x75,0x2c,0x00,0x01,0x75,0x68,0x00,0x01,0x75,0xa8,0x00,0x01,0x76,0x14,0x00,0x01,0x76,0x84,0x00,0x01,0x77,0x08,0x00,0x01,0x77,0x34,0x00,0x01,0x77,0x98,0x00,0x01,0x78,0x50,0x00,0x01,0x78,0xb0, 0x00,0x01,0x79,0x9c,0x00,0x01,0x7a,0x78,0x00,0x01,0x7a,0xd0,0x00,0x01,0x7b,0x28,0x00,0x01,0x7b,0x8c,0x00,0x01,0x7b,0xec,0x00,0x01,0x7c,0x50,0x00,0x01,0x7c,0x60,0x00,0x01,0x7c,0xb8,0x00,0x01,0x7d,0x28,0x00,0x01,0x7d,0x94,0x00,0x01,0x7e,0x48,0x00,0x01,0x7e,0x58,0x00,0x01,0x7e,0xa0,0x00,0x01,0x7e,0xd4,0x00,0x01,0x7f,0x10, 0x00,0x01,0x7f,0x54,0x00,0x01,0x7f,0x64,0x00,0x01,0x7f,0xa0,0x00,0x01,0x7f,0xdc,0x00,0x01,0x81,0x28,0x00,0x01,0x82,0xd8,0x00,0x01,0x83,0x30,0x00,0x01,0x83,0x88,0x00,0x01,0x83,0xfc,0x00,0x01,0x84,0x94,0x00,0x01,0x85,0x68,0x00,0x01,0x86,0x88,0x00,0x01,0x86,0x98,0x00,0x01,0x87,0x28,0x00,0x01,0x87,0xb4,0x00,0x01,0x88,0x94, 0x00,0x01,0x88,0xe4,0x00,0x01,0x89,0x58,0x00,0x01,0x89,0xa0,0x00,0x01,0x89,0xe4,0x00,0x01,0x89,0xf4,0x00,0x01,0x8a,0x30,0x00,0x01,0x8a,0x6c,0x00,0x01,0x8a,0xb8,0x00,0x01,0x8b,0x70,0x00,0x01,0x8b,0xec,0x00,0x01,0x8b,0xfc,0x00,0x01,0x8c,0x48,0x00,0x01,0x8c,0x90,0x00,0x01,0x8d,0x14,0x00,0x01,0x8d,0x84,0x00,0x01,0x8e,0x00, 0x00,0x01,0x8e,0x98,0x00,0x01,0x8e,0xe4,0x00,0x01,0x8f,0x50,0x00,0x01,0x8f,0x98,0x00,0x01,0x90,0x04,0x00,0x01,0x90,0x48,0x00,0x01,0x90,0xdc,0x00,0x01,0x91,0x4c,0x00,0x01,0x91,0xc0,0x00,0x01,0x92,0x48,0x00,0x01,0x92,0xcc,0x00,0x01,0x93,0x38,0x00,0x01,0x93,0x80,0x00,0x01,0x93,0xc8,0x00,0x01,0x94,0xb8,0x00,0x01,0x95,0x60, 0x00,0x01,0x97,0x44,0x00,0x01,0x97,0xb8,0x00,0x01,0x98,0x68,0x00,0x01,0x98,0xac,0x00,0x01,0x99,0x2c,0x00,0x01,0x9a,0x64,0x00,0x01,0x9b,0x18,0x00,0x01,0x9b,0xec,0x00,0x01,0x9c,0xa0,0x00,0x01,0x9d,0x54,0x00,0x01,0x9e,0x3c,0x00,0x01,0x9f,0x00,0x00,0x01,0x9f,0xd0,0x00,0x01,0xa0,0x24,0x00,0x01,0xa0,0x88,0x00,0x01,0xa0,0xf4, 0x00,0x01,0xa1,0x54,0x00,0x01,0xa1,0xa8,0x00,0x01,0xa2,0x10,0x00,0x01,0xa2,0x74,0x00,0x01,0xa2,0xd4,0x00,0x01,0xa3,0x60,0x00,0x01,0xa3,0xc4,0x00,0x01,0xa4,0xa0,0x00,0x01,0xa5,0x8c,0x00,0x01,0xa6,0x34,0x00,0x01,0xa6,0xd4,0x00,0x01,0xa7,0x6c,0x00,0x01,0xa8,0x00,0x00,0x01,0xa8,0x64,0x00,0x01,0xa8,0xf8,0x00,0x01,0xa9,0x58, 0x00,0x01,0xa9,0xd0,0x00,0x01,0xaa,0x6c,0x00,0x01,0xab,0x00,0x00,0x01,0xab,0x38,0x00,0x01,0xab,0xf0,0x00,0x01,0xac,0x48,0x00,0x01,0xac,0xec,0x00,0x01,0xad,0x38,0x00,0x01,0xad,0xd4,0x00,0x01,0xae,0x98,0x00,0x01,0xaf,0x54,0x00,0x01,0xaf,0xd0,0x00,0x01,0xb0,0x48,0x00,0x01,0xb0,0x70,0x00,0x01,0xb0,0xe8,0x00,0x01,0xb1,0x64, 0x00,0x01,0xb2,0x18,0x00,0x01,0xb2,0x60,0x00,0x01,0xb2,0xa8,0x00,0x01,0xb3,0x30,0x00,0x01,0xb3,0xb8,0x00,0x01,0xb4,0x7c,0x00,0x01,0xb4,0xb4,0x00,0x01,0xb4,0xe8,0x00,0x01,0xb5,0x1c,0x00,0x01,0xb5,0x50,0x00,0x01,0xb5,0x84,0x00,0x01,0xb5,0xb8,0x00,0x01,0xb5,0xec,0x00,0x01,0xb6,0x20,0x00,0x01,0xb6,0x54,0x00,0x01,0xb6,0x8c, 0x00,0x01,0xb6,0xbc,0x00,0x01,0xb6,0xec,0x00,0x01,0xb7,0x1c,0x00,0x01,0xb7,0x50,0x00,0x01,0xb7,0x84,0x00,0x01,0xb7,0xb8,0x00,0x01,0xb7,0xec,0x00,0x01,0xb8,0x20,0x00,0x01,0xb8,0x54,0x00,0x01,0xb8,0x88,0x00,0x01,0xb8,0xbc,0x00,0x01,0xb8,0xf0,0x00,0x01,0xb9,0x30,0x00,0x01,0xb9,0x84,0x00,0x01,0xb9,0xc4,0x00,0x01,0xba,0x04, 0x00,0x01,0xba,0x38,0x00,0x01,0xba,0x90,0x00,0x01,0xba,0xd0,0x00,0x01,0xbd,0x1c,0x00,0x01,0xc1,0xbc,0x00,0x01,0xc4,0x08,0x00,0x01,0xc4,0x58,0x00,0x01,0xc4,0xec,0x00,0x01,0xc5,0x80,0x00,0x01,0xc6,0x1c,0x00,0x01,0xc6,0x98,0x00,0x01,0xc7,0x4c,0x00,0x01,0xc8,0x80,0x00,0x01,0xc9,0x58,0x00,0x01,0xca,0x64,0x00,0x01,0xca,0xe0, 0x00,0x01,0xcb,0x08,0x00,0x01,0xcb,0x40,0x00,0x01,0xcb,0x88,0x00,0x01,0xcc,0x10,0x00,0x01,0xcc,0x40,0x00,0x01,0xcc,0x94,0x00,0x01,0xcc,0xc8,0x00,0x01,0xcd,0x18,0x00,0x01,0xcd,0x6c,0x00,0x01,0xcd,0xc0,0x00,0x01,0xce,0x10,0x00,0x01,0xce,0x64,0x00,0x01,0xce,0xc8,0x00,0x01,0xce,0xf8,0x00,0x01,0xcf,0x18,0x00,0x01,0xcf,0x3c, 0x00,0x01,0xcf,0x60,0x00,0x01,0xcf,0xac,0x00,0x01,0xcf,0xdc,0x00,0x01,0xd0,0x1c,0x00,0x01,0xd0,0x50,0x00,0x01,0xd0,0x70,0x00,0x01,0xd0,0x90,0x00,0x01,0xd0,0xc0,0x00,0x01,0xd0,0xec,0x00,0x01,0xd1,0x1c,0x00,0x01,0xd1,0x3c,0x00,0x01,0xd1,0x64,0x00,0x01,0xd1,0x84,0x00,0x01,0xd1,0xcc,0x00,0x01,0xd1,0xf8,0x00,0x01,0xd2,0x34, 0x00,0x01,0xd2,0x60,0x00,0x01,0xd2,0xe4,0x00,0x01,0xd3,0x50,0x00,0x01,0xd3,0xbc,0x00,0x01,0xd4,0x14,0x00,0x01,0xd4,0x94,0x00,0x01,0xd4,0xfc,0x00,0x01,0xd5,0x64,0x00,0x01,0xd5,0xb0,0x00,0x01,0xd6,0x60,0x00,0x01,0xd6,0xec,0x00,0x01,0xd7,0x74,0x00,0x01,0xd7,0xcc,0x00,0x01,0xd8,0x20,0x00,0x01,0xd8,0x74,0x00,0x01,0xd8,0xc0, 0x00,0x01,0xd9,0x04,0x00,0x01,0xd9,0x5c,0x00,0x01,0xd9,0xa0,0x00,0x01,0xd9,0xf8,0x00,0x01,0xda,0x58,0x00,0x01,0xda,0xa4,0x00,0x01,0xda,0xe8,0x00,0x01,0xdb,0x40,0x00,0x01,0xdb,0x84,0x00,0x01,0xdb,0xdc,0x00,0x01,0xdc,0x3c,0x00,0x01,0xdc,0xa8,0x00,0x01,0xdd,0x00,0x00,0x01,0xdd,0x58,0x00,0x01,0xdd,0xa8,0x00,0x01,0xdd,0xfc, 0x00,0x01,0xde,0x30,0x00,0x01,0xde,0x7c,0x00,0x01,0xde,0xc0,0x00,0x01,0xdf,0x04,0x00,0x01,0xdf,0x3c,0x00,0x01,0xdf,0x74,0x00,0x01,0xdf,0xc0,0x00,0x01,0xe0,0x3c,0x00,0x01,0xe0,0xcc,0x00,0x01,0xe1,0x04,0x00,0x01,0xe1,0x68,0x00,0x01,0xe1,0xdc,0x00,0x01,0xe2,0x10,0x00,0x01,0xe2,0x5c,0x00,0x01,0xe2,0xa0,0x00,0x01,0xe2,0xe4, 0x00,0x01,0xe3,0x28,0x00,0x01,0xe3,0x5c,0x00,0x01,0xe3,0xb8,0x00,0x01,0xe4,0x08,0x00,0x01,0xe4,0x58,0x00,0x01,0xe4,0xc0,0x00,0x01,0xe5,0x18,0x00,0x01,0xe5,0x70,0x00,0x01,0xe5,0xd4,0x00,0x01,0xe6,0x2c,0x00,0x01,0xe6,0x80,0x00,0x01,0xe6,0xe0,0x00,0x01,0xe7,0x48,0x00,0x01,0xe7,0xa0,0x00,0x01,0xe7,0xf8,0x00,0x01,0xe8,0x50, 0x00,0x01,0xe8,0xac,0x00,0x01,0xe9,0x18,0x00,0x01,0xe9,0x58,0x00,0x01,0xe9,0x98,0x00,0x01,0xe9,0xe8,0x00,0x01,0xea,0x3c,0x00,0x01,0xea,0x70,0x00,0x01,0xea,0xbc,0x00,0x01,0xeb,0x00,0x00,0x01,0xeb,0x44,0x00,0x01,0xeb,0x7c,0x00,0x01,0xeb,0xb4,0x00,0x01,0xec,0x00,0x00,0x01,0xec,0x7c,0x00,0x01,0xed,0x0c,0x00,0x01,0xed,0x44, 0x00,0x01,0xed,0xa8,0x00,0x01,0xee,0x1c,0x00,0x01,0xee,0x50,0x00,0x01,0xee,0x94,0x00,0x01,0xee,0xe0,0x00,0x01,0xef,0x24,0x00,0x01,0xef,0x68,0x00,0x01,0xef,0x9c,0x00,0x01,0xef,0xfc,0x00,0x01,0xf0,0x4c,0x00,0x01,0xf0,0x9c,0x00,0x01,0xf1,0x04,0x00,0x01,0xf1,0x5c,0x00,0x01,0xf1,0xb4,0x00,0x01,0xf2,0x18,0x00,0x01,0xf2,0x70, 0x00,0x01,0xf2,0xc4,0x00,0x01,0xf3,0x24,0x00,0x01,0xf3,0x8c,0x00,0x01,0xf3,0xe4,0x00,0x01,0xf4,0x38,0x00,0x01,0xf4,0x8c,0x00,0x01,0xf4,0xec,0x00,0x01,0xf5,0x38,0x00,0x01,0xf5,0x90,0x00,0x01,0xf5,0xd4,0x00,0x01,0xf6,0x2c,0x00,0x01,0xf6,0x70,0x00,0x01,0xf6,0xd0,0x00,0x01,0xf7,0x1c,0x00,0x01,0xf7,0x74,0x00,0x01,0xf7,0xb8, 0x00,0x01,0xf8,0x10,0x00,0x01,0xf8,0x54,0x00,0x01,0xf8,0xbc,0x00,0x01,0xf9,0x14,0x00,0x01,0xf9,0x6c,0x00,0x01,0xf9,0xe4,0x00,0x01,0xfa,0x48,0x00,0x01,0xfa,0xb0,0x00,0x01,0xfb,0x0c,0x00,0x01,0xfb,0x5c,0x00,0x01,0xfb,0xac,0x00,0x01,0xfc,0x0c,0x00,0x01,0xfc,0x5c,0x00,0x01,0xfc,0xac,0x00,0x01,0xfd,0x30,0x00,0x01,0xfd,0x94, 0x00,0x01,0xfd,0xf8,0x00,0x01,0xfe,0x54,0x00,0x01,0xff,0x0c,0x00,0x01,0xff,0xe0,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x58,0x00,0x02,0x01,0x48,0x00,0x02,0x02,0x3c,0x00,0x02,0x03,0x08,0x00,0x02,0x03,0xac,0x00,0x02,0x04,0x60,0x00,0x02,0x04,0xc0,0x00,0x02,0x05,0x7c,0x00,0x02,0x06,0x04,0x00,0x02,0x06,0x88,0x00,0x02,0x07,0x0c, 0x00,0x02,0x08,0x20,0x00,0x02,0x08,0x84,0x00,0x02,0x08,0x9c,0x00,0x02,0x09,0x14,0x00,0x02,0x09,0xd8,0x00,0x02,0x0a,0x3c,0x00,0x02,0x0a,0x98,0x00,0x02,0x0b,0x84,0x00,0x02,0x0b,0x9c,0x00,0x02,0x0b,0xac,0x00,0x02,0x0c,0x28,0x00,0x02,0x0d,0x00,0x00,0x02,0x0d,0x9c,0x00,0x02,0x0e,0x3c,0x00,0x02,0x0e,0xa8,0x00,0x02,0x0f,0x58, 0x00,0x02,0x10,0x24,0x00,0x02,0x10,0x78,0x00,0x02,0x10,0xe0,0x00,0x02,0x11,0xb0,0x00,0x02,0x12,0x64,0x00,0x02,0x13,0x10,0x00,0x02,0x13,0xc0,0x00,0x02,0x14,0x44,0x00,0x02,0x15,0x1c,0x00,0x02,0x15,0xc8,0x00,0x02,0x16,0x58,0x00,0x02,0x16,0xe8,0x00,0x02,0x17,0x80,0x00,0x02,0x17,0xa0,0x00,0x02,0x18,0x60,0x00,0x02,0x18,0xf4, 0x00,0x02,0x19,0xc4,0x00,0x02,0x1a,0xec,0x00,0x02,0x1b,0xac,0x00,0x02,0x1c,0x20,0x00,0x02,0x1c,0xd0,0x00,0x02,0x1d,0x6c,0x00,0x02,0x1d,0xf0,0x00,0x02,0x1e,0x54,0x00,0x02,0x1e,0xf0,0x00,0x02,0x1f,0x60,0x00,0x02,0x1f,0xf8,0x00,0x02,0x20,0x58,0x00,0x02,0x20,0xa8,0x00,0x02,0x21,0x54,0x00,0x02,0x22,0x4c,0x00,0x02,0x22,0x70, 0x00,0x02,0x22,0x88,0x00,0x02,0x23,0x4c,0x00,0x02,0x23,0xf4,0x00,0x02,0x24,0xbc,0x00,0x02,0x25,0x14,0x00,0x02,0x25,0x74,0x00,0x02,0x26,0x54,0x00,0x02,0x27,0x44,0x00,0x02,0x27,0xdc,0x00,0x02,0x28,0x20,0x00,0x02,0x28,0x4c,0x00,0x02,0x28,0x84,0x00,0x02,0x28,0xbc,0x00,0x02,0x28,0xf4,0x00,0x02,0x29,0xbc,0x00,0x02,0x2a,0xfc, 0x00,0x02,0x2b,0xdc,0x00,0x02,0x2d,0x04,0x00,0x02,0x2d,0x64,0x00,0x02,0x2e,0x78,0x00,0x02,0x2f,0x90,0x00,0x02,0x30,0x98,0x00,0x02,0x31,0x60,0x00,0x02,0x31,0xe8,0x00,0x02,0x32,0x08,0x00,0x02,0x32,0x38,0x00,0x02,0x32,0x68,0x00,0x02,0x32,0xc0,0x00,0x02,0x33,0x18,0x00,0x02,0x33,0xc8,0x00,0x02,0x34,0x40,0x00,0x02,0x35,0x5c, 0x00,0x02,0x36,0x18,0x00,0x02,0x36,0xe0,0x00,0x02,0x37,0x4c,0x00,0x02,0x37,0xfc,0x00,0x02,0x38,0xe4,0x00,0x02,0x39,0xe4,0x00,0x02,0x3a,0x20,0x00,0x02,0x3a,0x5c,0x00,0x02,0x3a,0xa0,0x00,0x02,0x3a,0xdc,0x00,0x02,0x3b,0x20,0x00,0x02,0x3b,0xd8,0x00,0x02,0x3c,0x74,0x00,0x02,0x3d,0x30,0x00,0x02,0x3d,0xe0,0x00,0x02,0x3f,0x0c, 0x00,0x02,0x3f,0xe8,0x00,0x02,0x40,0xc4,0x00,0x02,0x41,0x98,0x00,0x02,0x42,0x64,0x00,0x02,0x42,0xf4,0x00,0x02,0x43,0xd4,0x00,0x02,0x45,0x18,0x00,0x02,0x45,0xf4,0x00,0x02,0x46,0xf0,0x00,0x02,0x47,0x88,0x00,0x02,0x48,0xc0,0x00,0x02,0x49,0x50,0x00,0x02,0x4a,0x34,0x00,0x02,0x4a,0x8c,0x00,0x02,0x4b,0x3c,0x00,0x02,0x4b,0xbc, 0x00,0x02,0x4c,0x3c,0x00,0x02,0x4d,0x3c,0x00,0x02,0x4d,0xa0,0x00,0x02,0x4e,0x20,0x00,0x02,0x4e,0xa4,0x00,0x02,0x50,0x10,0x00,0x02,0x50,0xa8,0x00,0x02,0x51,0x28,0x00,0x02,0x51,0xe0,0x00,0x02,0x52,0x74,0x00,0x02,0x53,0x28,0x00,0x02,0x54,0x00,0x00,0x02,0x54,0xd8,0x00,0x02,0x55,0x74,0x00,0x02,0x55,0xc0,0x00,0x02,0x56,0x28, 0x00,0x02,0x56,0x90,0x00,0x02,0x57,0xb8,0x00,0x02,0x58,0xa8,0x00,0x02,0x59,0xa8,0x00,0x02,0x5a,0xd4,0x00,0x02,0x5b,0xe8,0x00,0x02,0x5c,0xec,0x00,0x02,0x5e,0x14,0x00,0x02,0x5f,0x54,0x00,0x02,0x60,0x64,0x00,0x02,0x61,0x00,0x00,0x02,0x61,0x84,0x00,0x02,0x62,0x88,0x00,0x02,0x63,0x10,0x00,0x02,0x63,0xbc,0x00,0x02,0x63,0xd0, 0x00,0x02,0x64,0x88,0x00,0x02,0x65,0x70,0x00,0x02,0x66,0x5c,0x00,0x02,0x67,0x68,0x00,0x02,0x68,0x80,0x00,0x02,0x6a,0x00,0x00,0x02,0x6a,0xc8,0x00,0x02,0x6b,0xcc,0x00,0x02,0x6d,0x9c,0x00,0x02,0x70,0x14,0x00,0x02,0x71,0x70,0x00,0x02,0x71,0xdc,0x00,0x02,0x72,0x54,0x00,0x02,0x73,0x14,0x00,0x02,0x73,0x78,0x00,0x02,0x73,0x90, 0x00,0x02,0x74,0x18,0x00,0x02,0x74,0x78,0x00,0x02,0x75,0x34,0x00,0x02,0x75,0xd8,0x00,0x02,0x76,0x78,0x00,0x02,0x77,0x00,0x00,0x02,0x77,0x98,0x00,0x02,0x78,0x1c,0x00,0x02,0x79,0x14,0x00,0x02,0x79,0xa8,0x00,0x02,0x7a,0x60,0x00,0x02,0x7a,0xf0,0x00,0x02,0x7b,0xcc,0x00,0x02,0x7c,0xe4,0x00,0x02,0x7d,0xbc,0x00,0x02,0x7e,0x14, 0x00,0x02,0x7e,0x88,0x00,0x02,0x7f,0x40,0x00,0x02,0x7f,0xf8,0x00,0x02,0x80,0xb0,0x00,0x02,0x81,0x4c,0x00,0x02,0x81,0xc8,0x00,0x02,0x82,0x30,0x00,0x02,0x82,0xc0,0x00,0x02,0x82,0xe4,0x00,0x02,0x83,0x08,0x00,0x02,0x83,0x58,0x00,0x02,0x83,0xfc,0x00,0x02,0x84,0x20,0x00,0x02,0x84,0xa0,0x00,0x02,0x85,0x38,0x00,0x02,0x85,0x58, 0x00,0x02,0x85,0xc4,0x00,0x02,0x86,0x30,0x00,0x02,0x86,0x98,0x00,0x02,0x87,0x08,0x00,0x02,0x87,0x78,0x00,0x02,0x87,0x9c,0x00,0x02,0x87,0xc8,0x00,0x02,0x88,0xa4,0x00,0x02,0x88,0xbc,0x00,0x02,0x88,0xdc,0x00,0x02,0x89,0x60,0x00,0x02,0x8a,0x00,0x00,0x02,0x8a,0xbc,0x00,0x02,0x8b,0x60,0x00,0x02,0x8c,0x68,0x00,0x02,0x8d,0x94, 0x00,0x02,0x8e,0x9c,0x00,0x02,0x8f,0x30,0x00,0x02,0x8f,0xf4,0x00,0x02,0x90,0x44,0x00,0x02,0x90,0xc8,0x00,0x02,0x91,0x6c,0x00,0x02,0x92,0x34,0x00,0x02,0x92,0xfc,0x00,0x02,0x93,0x8c,0x00,0x02,0x93,0xe4,0x00,0x02,0x93,0xfc,0x00,0x02,0x94,0x7c,0x00,0x02,0x95,0x14,0x00,0x02,0x95,0x34,0x00,0x02,0x96,0xb8,0x00,0x02,0x98,0x00, 0x00,0x02,0x99,0x80,0x00,0x02,0x9b,0x3c,0x00,0x02,0x9b,0xa8,0x00,0x02,0x9c,0x44,0x00,0x02,0x9d,0x0c,0x00,0x02,0x9e,0xb0,0x00,0x02,0x9f,0xf4,0x00,0x02,0xa0,0xfc,0x00,0x02,0xa2,0xec,0x00,0x02,0xa3,0x74,0x00,0x02,0xa3,0xf8,0x00,0x02,0xa4,0xa8,0x00,0x02,0xa5,0x20,0x00,0x02,0xa5,0xc0,0x00,0x02,0xa5,0xf8,0x00,0x02,0xa6,0x08, 0x00,0x02,0xa6,0x44,0x00,0x02,0xa6,0x9c,0x00,0x02,0xa6,0xb0,0x00,0x02,0xa6,0xec,0x00,0x02,0xa7,0x6c,0x00,0x02,0xa7,0xc0,0x00,0x02,0xa7,0xfc,0x00,0x02,0xa8,0x38,0x00,0x02,0xa8,0x94,0x00,0x02,0xa8,0xc8,0x00,0x02,0xa9,0x14,0x00,0x02,0xa9,0x60,0x00,0x02,0xa9,0xc4,0x00,0x02,0xaa,0x4c,0x00,0x02,0xab,0x04,0x00,0x02,0xab,0x44, 0x00,0x02,0xab,0xc8,0x00,0x02,0xac,0x14,0x00,0x02,0xac,0x50,0x00,0x02,0xac,0xc8,0x00,0x02,0xad,0x1c,0x00,0x02,0xad,0xa0,0x00,0x02,0xad,0xdc,0x00,0x02,0xae,0x50,0x00,0x02,0xae,0xb8,0x00,0x02,0xae,0xf8,0x00,0x02,0xaf,0x38,0x00,0x02,0xaf,0x78,0x00,0x02,0xaf,0x8c,0x00,0x02,0xaf,0xa0,0x00,0x02,0xaf,0xb4,0x00,0x02,0xaf,0xc8, 0x00,0x02,0xaf,0xdc,0x00,0x02,0xaf,0xf0,0x00,0x02,0xb0,0x04,0x00,0x02,0xb0,0x18,0x00,0x02,0xb0,0x2c,0x00,0x02,0xb0,0x40,0x00,0x02,0xb0,0x54,0x00,0x02,0xb0,0x68,0x00,0x02,0xb0,0x7c,0x00,0x02,0xb0,0x8c,0x00,0x02,0xb1,0x04,0x00,0x02,0xb1,0x50,0x00,0x02,0xb1,0x84,0x00,0x02,0xb1,0xb8,0x00,0x02,0xb2,0x0c,0x00,0x02,0xb2,0x50, 0x00,0x02,0xb2,0x94,0x00,0x02,0xb2,0xf0,0x00,0x02,0xb3,0x70,0x00,0x02,0xb4,0x20,0x00,0x02,0xb4,0x58,0x00,0x02,0xb4,0xd4,0x00,0x02,0xb5,0x18,0x00,0x02,0xb5,0x70,0x00,0x02,0xb5,0xac,0x00,0x02,0xb6,0x14,0x00,0x02,0xb6,0x60,0x00,0x02,0xb6,0xd4,0x00,0x02,0xb7,0x08,0x00,0x02,0xb7,0x94,0x00,0x02,0xb8,0x10,0x00,0x02,0xb8,0x6c, 0x00,0x02,0xb8,0xa4,0x00,0x02,0xb8,0xb8,0x00,0x02,0xb8,0xcc,0x00,0x02,0xb8,0xe0,0x00,0x02,0xb8,0xf4,0x00,0x02,0xb9,0x08,0x00,0x02,0xb9,0x1c,0x00,0x02,0xb9,0x30,0x00,0x02,0xb9,0x44,0x00,0x02,0xb9,0x58,0x00,0x02,0xb9,0x6c,0x00,0x02,0xb9,0x80,0x00,0x02,0xb9,0xbc,0x00,0x02,0xb9,0xf0,0x00,0x02,0xba,0xc0,0x00,0x02,0xbb,0x1c, 0x00,0x02,0xbb,0x98,0x00,0x02,0xbc,0x14,0x00,0x02,0xbc,0xe8,0x00,0x02,0xbd,0xec,0x00,0x02,0xbe,0x50,0x00,0x02,0xbe,0xc0,0x00,0x02,0xbf,0x80,0x00,0x02,0xc0,0x74,0x00,0x02,0xc0,0xf4,0x00,0x02,0xc1,0x74,0x00,0x02,0xc2,0x4c,0x00,0x02,0xc3,0x18,0x00,0x02,0xc3,0x7c,0x00,0x02,0xc3,0xec,0x00,0x02,0xc4,0xac,0x00,0x02,0xc5,0x68, 0x00,0x02,0xc5,0xec,0x00,0x02,0xc6,0x9c,0x00,0x02,0xc7,0x70,0x00,0x02,0xc7,0xa8,0x00,0x02,0xc7,0xf0,0x00,0x02,0xc8,0x30,0x00,0x02,0xc8,0x78,0x00,0x02,0xc9,0x24,0x00,0x02,0xc9,0x3c,0x00,0x02,0xc9,0x3c,0x00,0x02,0xc9,0x3c,0x00,0x03,0x00,0x5a,0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x03,0x00,0x06,0x00,0x09,0x00,0x31,0x40,0x2e, 0x09,0x04,0x02,0x03,0x02,0x01,0x4c,0x00,0x00,0x00,0x02,0x03,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x00,0x00,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x33,0x11,0x21,0x11,0x25,0x01,0x21,0x13,0x21,0x11,0x5a,0x01,0xa4,0xfe,0x8e,0x01,0x2c, 0xfe,0xd4,0x14,0x01,0x2c,0x02,0xda,0xfd,0x26,0x6d,0x02,0x3b,0xfd,0x8a,0x02,0x3b,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x07,0x00,0x10,0x00,0x2c,0x40,0x29,0x0d,0x01,0x04,0x00,0x01,0x4c,0x00,0x04,0x00,0x02,0x01,0x04,0x02,0x68,0x00,0x00,0x00,0x38,0x4d,0x05,0x03,0x02,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x09, 0x08,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x06,0x09,0x19,0x2b,0x33,0x13,0x33,0x13,0x23,0x27,0x23,0x07,0x13,0x33,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x32,0xbe,0x79,0xbd,0x5b,0x30,0xdd,0x30,0x42,0xb8,0x38,0x10,0x12,0x02,0x02,0x12,0x10,0x02,0xda,0xfd,0x26,0xc2,0xc2,0x01,0x0e,0xe1,0x40,0x56,0x0d,0x0d,0x56,0x3f,0x00,0x00,0x00, 0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x00,0x27,0x06,0xbc,0x02,0x58, 0x00,0x00,0x02,0x06,0x00,0x01,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x2b,0x02,0x26,0x03,0xb6,0x00,0x27,0x06,0x95,0x02,0x58,0x00,0x00,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xbd,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xbe,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xbf,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x01,0x00,0x00, 0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x67,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xc0,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x2b,0x02,0x26, 0x03,0xb6,0x00,0x27,0x06,0x93,0x02,0x58,0x00,0x00,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xc1,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00, 0x00,0x07,0x06,0xc2,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0xc3,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb1,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x2b,0x02,0x26, 0x02,0xda,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x9e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xd4,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0x93,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x32,0xff,0x35,0x02,0x49,0x02,0xda,0x00,0x16,0x00,0x1f,0x00,0x65,0x40,0x0a,0x1c,0x01,0x06,0x00,0x13,0x01,0x01,0x04,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x1f,0x00,0x06,0x00,0x04,0x01, 0x06,0x04,0x68,0x00,0x00,0x00,0x38,0x4d,0x07,0x05,0x02,0x01,0x01,0x39,0x4d,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x1c,0x00,0x06,0x00,0x04,0x01,0x06,0x04,0x68,0x00,0x02,0x00,0x03,0x02,0x03,0x63,0x00,0x00,0x00,0x38,0x4d,0x07,0x05,0x02,0x01,0x01,0x39,0x01,0x4e,0x59,0x40,0x10,0x00,0x00,0x18,0x17, 0x00,0x16,0x00,0x16,0x16,0x21,0x25,0x11,0x11,0x08,0x09,0x1b,0x2b,0x33,0x13,0x33,0x13,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x27,0x23,0x07,0x13,0x33,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x32,0xbe,0x79,0xbd,0x11,0x21,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x21,0x29,0x30,0xdd,0x30,0x42, 0xb8,0x38,0x10,0x12,0x02,0x02,0x12,0x10,0x02,0xda,0xfd,0x26,0x1b,0x2d,0x15,0x16,0x1c,0x3c,0x35,0x28,0x1b,0x36,0x1f,0xc0,0xc2,0x01,0x0e,0xe1,0x40,0x56,0x0d,0x0d,0x56,0x3f,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xe2,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x96,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32, 0x00,0x00,0x02,0x26,0x03,0xb1,0x02,0x26,0x00,0x01,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0f,0x00,0x13,0x00,0x3f,0x40,0x3c,0x00,0x02,0x00,0x03,0x08,0x02,0x03,0x67,0x00,0x08,0x00,0x06,0x04,0x08,0x06,0x67,0x09,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38, 0x4d,0x00,0x04,0x04,0x05,0x5f,0x0a,0x07,0x02,0x05,0x05,0x39,0x05,0x4e,0x00,0x00,0x13,0x12,0x11,0x10,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x09,0x1d,0x2b,0x33,0x13,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x21,0x35,0x23,0x07,0x13,0x33,0x11,0x23,0x1e,0x91,0x01,0x8b,0xb6,0x9d,0x9d,0xb6,0xfe, 0xf4,0x8d,0x28,0x36,0x7f,0x38,0x02,0xda,0x52,0xe4,0x52,0xff,0x00,0x52,0xcb,0xcb,0x01,0x16,0x01,0x72,0xff,0xff,0x00,0x1e,0x00,0x00,0x02,0x3a,0x03,0xb6,0x02,0x26,0x00,0x18,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0x00,0x03,0x00,0x5d,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x10,0x00,0x19,0x00,0x22,0x00,0x39,0x40,0x36, 0x08,0x01,0x05,0x02,0x01,0x4c,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x01,0x5f,0x06,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x22,0x20,0x1c,0x1a,0x19,0x17,0x13,0x11,0x00,0x10,0x00,0x0f,0x21,0x07,0x09,0x17,0x2b,0x33,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x07, 0x15,0x1e,0x02,0x15,0x14,0x06,0x23,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x5d,0xcf,0x64,0x71,0x47,0x39,0x2b,0x41,0x25,0x73,0x64,0x86,0x76,0x3a,0x43,0x42,0x3a,0x77,0x7c,0x3f,0x49,0x49,0x3f,0x7c,0x02,0xda,0x64,0x59,0x38,0x5a,0x0b,0x03,0x05,0x32,0x4d,0x2e,0x5e,0x6d,0x01, 0xa3,0x3e,0x35,0x35,0x3e,0xfd,0xc8,0x43,0x3a,0x3c,0x4b,0x00,0x00,0x01,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x02,0xe4,0x00,0x1b,0x00,0x3b,0x40,0x38,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00, 0x4e,0x01,0x00,0x19,0x18,0x16,0x14,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1b,0x01,0x1b,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x01,0x34,0x64,0x74,0x74,0x64,0x62,0x74,0x5a,0x41,0x3b,0x3b,0x43,0x43,0x3b, 0x3b,0x41,0x5a,0x74,0x0a,0x70,0x62,0x01,0x4a,0x62,0x70,0x71,0x61,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0x43,0x3e,0x61,0x71,0x00,0x00,0x00,0xff,0xff,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x03,0xb6,0x02,0x26,0x00,0x1b,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x03,0xb6,0x02,0x26, 0x00,0x1b,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x5d,0x00,0x00,0x00,0x01,0x00,0x5c,0xff,0x35,0x02,0x0a,0x02,0xe4,0x00,0x2f,0x00,0x95,0x40,0x0a,0x09,0x01,0x07,0x05,0x28,0x01,0x01,0x07,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x36,0x00,0x03,0x04,0x06,0x04,0x03,0x06,0x80,0x00,0x06,0x05,0x04,0x06,0x05,0x7e,0x00,0x01,0x07,0x00, 0x07,0x01,0x72,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x3f,0x4d,0x00,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08,0x3d,0x08,0x4e,0x1b,0x40,0x34,0x00,0x03,0x04,0x06,0x04,0x03,0x06,0x80,0x00,0x06,0x05,0x04,0x06,0x05,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x00,0x80,0x00,0x00,0x09, 0x01,0x08,0x00,0x08,0x63,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x3f,0x07,0x4e,0x59,0x40,0x11,0x00,0x00,0x00,0x2f,0x00,0x2e,0x12,0x12,0x25,0x22,0x12,0x27,0x14,0x21,0x0a,0x09,0x1e,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x26,0x26,0x35,0x11,0x34,0x36,0x33, 0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0x22,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xd2,0x46,0x16,0x1b,0x37,0x32,0x18,0x49,0x53,0x74,0x64,0x62,0x74,0x5a,0x41,0x3b,0x3b,0x43,0x43,0x3b,0x3b,0x41,0x5a,0x74,0x62,0x03,0x01,0x09,0x1a,0x38,0x26,0x42,0x36,0xcb, 0x37,0x17,0x0d,0x11,0x1a,0x41,0x10,0x6a,0x52,0x01,0x4a,0x62,0x70,0x71,0x61,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0x43,0x3e,0x61,0x71,0x19,0x03,0x14,0x24,0x1a,0x22,0x31,0x00,0x00,0xff,0xff,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x03,0xb6,0x02,0x26,0x00,0x1b,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x5c, 0xff,0xf6,0x02,0x0a,0x03,0xb0,0x02,0x26,0x00,0x1b,0x00,0x00,0x00,0x07,0x06,0x8f,0x02,0x5d,0x00,0x00,0x00,0x02,0x00,0x5c,0x00,0x00,0x02,0x00,0x02,0xda,0x00,0x0b,0x00,0x15,0x00,0x27,0x40,0x24,0x00,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x15,0x13, 0x0e,0x0c,0x00,0x0b,0x00,0x0a,0x21,0x05,0x09,0x17,0x2b,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x11,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x23,0x5c,0xbd,0x47,0x67,0x39,0x39,0x67,0x47,0x63,0x63,0x42,0x4b,0x4b,0x42,0x63,0x02,0xda,0x36,0x62,0x43,0xfe,0xdd,0x43,0x63,0x36,0x50,0x4a,0x42,0x01,0x23,0x41, 0x4a,0x00,0x00,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x02,0x00,0x02,0xda,0x00,0x0f,0x00,0x1d,0x00,0x37,0x40,0x34,0x06,0x01,0x01,0x07,0x01,0x00,0x04,0x01,0x00,0x67,0x00,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x04,0x04,0x03,0x5f,0x08,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x1d,0x1c,0x1b,0x1a,0x19,0x17,0x12,0x10, 0x00,0x0f,0x00,0x0e,0x21,0x11,0x11,0x09,0x09,0x19,0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x11,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x23,0x15,0x33,0x15,0x23,0x5c,0x52,0x52,0xbd,0x47,0x67,0x39,0x39,0x67,0x47,0x63,0x63,0x42,0x4b,0x4b,0x42,0x63,0x6c,0x6c,0x01,0x4f,0x4b,0x01, 0x40,0x36,0x62,0x43,0xfe,0xdd,0x43,0x63,0x36,0x50,0x4a,0x42,0x01,0x23,0x41,0x4a,0xf0,0x4b,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x21,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x02,0x00,0x02,0xda,0x00,0x0f,0x00,0x1d,0x00,0x37,0x40,0x34,0x06,0x01, 0x01,0x07,0x01,0x00,0x04,0x01,0x00,0x67,0x00,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x04,0x04,0x03,0x5f,0x08,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x1d,0x1c,0x1b,0x1a,0x19,0x17,0x12,0x10,0x00,0x0f,0x00,0x0e,0x21,0x11,0x11,0x09,0x09,0x19,0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x11,0x14, 0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x23,0x15,0x33,0x15,0x23,0x5c,0x52,0x52,0xbd,0x47,0x67,0x39,0x39,0x67,0x47,0x63,0x63,0x42,0x4b,0x4b,0x42,0x63,0x6c,0x6c,0x01,0x4f,0x4b,0x01,0x40,0x36,0x62,0x43,0xfe,0xdd,0x43,0x63,0x36,0x50,0x4a,0x42,0x01,0x23,0x41,0x4a,0xf0,0x4b,0x00,0x00,0x00,0x01,0x00,0x64, 0x00,0x00,0x02,0x08,0x02,0xda,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x05,0x5f,0x06,0x01,0x05,0x05,0x39,0x05,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x33,0x11,0x21,0x15,0x21,0x15,0x21, 0x15,0x21,0x11,0x21,0x15,0x64,0x01,0xa4,0xfe,0xb5,0x01,0x28,0xfe,0xd8,0x01,0x4b,0x02,0xda,0x52,0xe2,0x50,0xfe,0xfc,0x52,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x6c,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00, 0x00,0x07,0x06,0x95,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x71, 0x03,0xfc,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0xc0,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0xff,0x2b,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x27,0x06,0x9e,0x02,0x62,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x25,0x00,0x00, 0x00,0x07,0x06,0xc1,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x30,0x03,0xfc,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0xc2,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xfc,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0xc3,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08, 0x03,0xb1,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb0,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x8f,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0xff,0x2b,0x02,0x08,0x02,0xda,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x9e,0x02,0x62,0x00,0x00, 0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb6,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xd4,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0x93,0x02,0x26,0x00,0x25,0x00,0x00, 0x00,0x07,0x06,0x98,0x02,0x62,0x00,0x00,0x00,0x01,0x00,0x64,0xff,0x35,0x02,0x0d,0x02,0xda,0x00,0x1b,0x00,0x6e,0x4b,0xb0,0x15,0x50,0x58,0x40,0x29,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x05,0x5f,0x09,0x08,0x02,0x05,0x05,0x39,0x4d,0x00,0x06,0x06,0x07,0x5f, 0x00,0x07,0x07,0x3d,0x07,0x4e,0x1b,0x40,0x26,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x06,0x00,0x07,0x06,0x07,0x63,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x05,0x5f,0x09,0x08,0x02,0x05,0x05,0x39,0x05,0x4e,0x59,0x40,0x11,0x00,0x00,0x00,0x1b,0x00,0x1b,0x21,0x25,0x11,0x11,0x11,0x11,0x11,0x11, 0x0a,0x09,0x1e,0x2b,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0x21,0x15,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x64,0x01,0xa4,0xfe,0xb5,0x01,0x28,0xfe,0xd8,0x01,0x4b,0x2f,0x21,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x20,0x27,0x02,0xda,0x52,0xe2,0x50,0xfe,0xfc,0x52,0x1b,0x2d, 0x15,0x16,0x1c,0x3c,0x35,0x28,0x1a,0x36,0x1e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0xff,0xf6,0x02,0x24,0x02,0xe4,0x00,0x2d,0x00,0x4e,0x40,0x4b,0x07,0x01,0x05,0x04,0x01,0x4c,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x07,0x05,0x06,0x05,0x07,0x06,0x80,0x00,0x04,0x00,0x05,0x07,0x04,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00, 0x01,0x01,0x3e,0x4d,0x00,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x2a,0x29,0x27,0x25,0x21,0x1f,0x1e,0x1c,0x18,0x16,0x14,0x13,0x10,0x0e,0x00,0x2d,0x01,0x2d,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23, 0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x0e,0x02,0x01,0x35,0x48,0x6d,0x3e,0x4e,0x3e,0x34,0x41,0x37,0x61,0x40,0x42,0x65,0x38,0x5a,0x4a,0x3b,0x38,0x46,0x47,0x39,0x57,0x56,0x43,0x53,0x53,0x43,0x41,0x54,0x01,0x5a,0x01,0x3d,0x6b,0x0a,0x35,0x5e,0x3e,0x47,0x67,0x0b,0x03, 0x0d,0x5b,0x3c,0x38,0x55,0x30,0x35,0x5e,0x3f,0x3a,0x48,0x41,0x35,0x36,0x44,0x50,0x4b,0x3c,0x3c,0x4b,0x48,0x3a,0x3e,0x5f,0x35,0x00,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb1,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x62,0x00,0x00,0x00,0x01,0x00,0x5f,0x00,0x00,0x02,0x0d,0x02,0xda,0x00,0x09, 0x00,0x29,0x40,0x26,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x09,0x1a,0x2b,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0x5f,0x01,0xae,0xfe,0xaa,0x01,0x3c,0xfe,0xc6,0x02,0xda, 0x52,0xf2,0x52,0xfe,0xbc,0x00,0x00,0x00,0x00,0x01,0x00,0x58,0xff,0xf6,0x02,0x06,0x02,0xe4,0x00,0x1f,0x00,0x3e,0x40,0x3b,0x00,0x02,0x03,0x06,0x03,0x02,0x06,0x80,0x00,0x06,0x00,0x05,0x04,0x06,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x04,0x04,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00, 0x1c,0x1b,0x1a,0x19,0x16,0x14,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1f,0x01,0x1f,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x23,0x35,0x33,0x15,0x14,0x06,0x01,0x30,0x64,0x74,0x74,0x64,0x62,0x74,0x5a,0x41,0x3b,0x3b, 0x43,0x43,0x3b,0x3b,0x41,0x94,0xee,0x74,0x0a,0x70,0x62,0x01,0x4a,0x62,0x70,0x71,0x61,0x3e,0x43,0x42,0x3e,0xfe,0xb5,0x3e,0x44,0x44,0x3e,0x64,0x52,0xb6,0x61,0x71,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x06,0x03,0xb6,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x06, 0x03,0xb6,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x06,0x03,0xb6,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x06,0x03,0xb6,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0x10,0x02,0x06,0x02,0xe4,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0xa0,0x02,0x5c,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x06,0x03,0xb0,0x02,0x26,0x00,0x39,0x00,0x00,0x00,0x07,0x06,0x8f,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5d,0x00,0x00,0x01,0xfb,0x02,0xda,0x00,0x0b,0x00,0x27,0x40,0x24, 0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x02,0x01,0x00,0x00,0x38,0x4d,0x06,0x05,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x5d,0x5a,0xea,0x5a,0x5a,0xea,0x02,0xda,0xfe,0xc8,0x01,0x38,0xfd,0x26,0x01, 0x50,0xfe,0xb0,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x02,0x4e,0x02,0xda,0x00,0x13,0x00,0x17,0x00,0x3b,0x40,0x38,0x05,0x03,0x02,0x01,0x0b,0x06,0x02,0x00,0x0a,0x01,0x00,0x67,0x00,0x0a,0x00,0x08,0x07,0x0a,0x08,0x67,0x04,0x01,0x02,0x02,0x38,0x4d,0x0c,0x09,0x02,0x07,0x07,0x39,0x07,0x4e,0x00,0x00,0x17,0x16,0x15,0x14,0x00,0x13, 0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0d,0x09,0x1f,0x2b,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x11,0x11,0x33,0x35,0x23,0x5d,0x53,0x53,0x5a,0xea,0x5a,0x53,0x53,0x5a,0xea,0xea,0xea,0x02,0x0d,0x4b,0x82,0x82,0x82,0x82,0x4b,0xfd,0xf3,0x01,0x50,0xfe, 0xb0,0x01,0xa2,0x6b,0xff,0xff,0x00,0x5d,0x00,0x00,0x01,0xfb,0x03,0xb6,0x02,0x26,0x00,0x40,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x69,0x00,0x00,0x01,0xef,0x02,0xda,0x00,0x0b,0x00,0x29,0x40,0x26,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x04,0x01,0x00,0x00,0x05,0x5f,0x06,0x01,0x05, 0x05,0x39,0x05,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x33,0x15,0x69,0x95,0x95,0x01,0x86,0x95,0x95,0x52,0x02,0x36,0x52,0x52,0xfd,0xca,0x52,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb6,0x02,0x26,0x00,0x43,0x00,0x00, 0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb6,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb6,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef, 0x03,0xb1,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb0,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x8f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x69,0xff,0x2b,0x01,0xef,0x02,0xda,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x9e,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb6,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xd4,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0x93,0x02,0x26,0x00,0x43,0x00,0x00, 0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x69,0xff,0x35,0x01,0xef,0x02,0xda,0x00,0x1b,0x00,0x62,0x4b,0xb0,0x15,0x50,0x58,0x40,0x23,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x04,0x01,0x00,0x00,0x05,0x5f,0x09,0x08,0x02,0x05,0x05,0x39,0x4d,0x00,0x06,0x06,0x07,0x5f,0x00,0x07,0x07,0x3d,0x07,0x4e, 0x1b,0x40,0x20,0x00,0x06,0x00,0x07,0x06,0x07,0x63,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x04,0x01,0x00,0x00,0x05,0x5f,0x09,0x08,0x02,0x05,0x05,0x39,0x05,0x4e,0x59,0x40,0x11,0x00,0x00,0x00,0x1b,0x00,0x1b,0x21,0x25,0x11,0x11,0x11,0x11,0x11,0x11,0x0a,0x09,0x1e,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x21,0x15, 0x23,0x11,0x33,0x15,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x69,0x95,0x95,0x01,0x86,0x95,0x95,0xa2,0x21,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x20,0x27,0x52,0x02,0x36,0x52,0x52,0xfd,0xca,0x52,0x1b,0x2d,0x15,0x16,0x1c,0x3c,0x35,0x28,0x1a,0x36,0x1e,0x00,0x00,0x00,0xff,0xff,0x00,0x69, 0x00,0x00,0x01,0xef,0x03,0xb1,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x2d,0xff,0xf6,0x01,0xef,0x02,0xda,0x00,0x0f,0x00,0x2b,0x40,0x28,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x03,0x03,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x0c, 0x0b,0x08,0x06,0x04,0x03,0x00,0x0f,0x01,0x0f,0x05,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x01,0x0e,0x69,0x78,0x5a,0x47,0x40,0x40,0x47,0x5a,0x79,0x0a,0x76,0x66,0x43,0x49,0x49,0x43,0x02,0x08,0xfd,0xf8,0x66,0x76,0x00,0x00,0x00,0xff,0xff,0x00,0x2d,0xff,0xf6,0x02,0x77, 0x03,0xb6,0x02,0x26,0x00,0x4f,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0xee,0x00,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x0c,0x00,0x2d,0x40,0x2a,0x07,0x01,0x04,0x01,0x01,0x4c,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x02,0x01,0x00,0x00,0x38,0x4d,0x06,0x05,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x0c, 0x00,0x0c,0x11,0x12,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x13,0x33,0x03,0x13,0x23,0x03,0x23,0x11,0x5c,0x5a,0x6c,0xa2,0x62,0xb5,0xbf,0x67,0xaa,0x69,0x02,0xda,0xfe,0xc6,0x01,0x3a,0xfe,0xa0,0xfe,0x86,0x01,0x51,0xfe,0xaf,0xff,0xff,0x00,0x5c,0xff,0x10,0x02,0x30,0x02,0xda,0x02,0x26,0x00,0x51,0x00,0x00, 0x00,0x07,0x06,0xa0,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x05,0x00,0x1f,0x40,0x1c,0x00,0x00,0x00,0x38,0x4d,0x00,0x01,0x01,0x02,0x60,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x09,0x18,0x2b,0x33,0x11,0x33,0x11,0x21,0x15,0x82,0x5a,0x01,0x4a,0x02, 0xda,0xfd,0x78,0x52,0xff,0xff,0x00,0x75,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x00,0x53,0x00,0x00,0x00,0x07,0x06,0x91,0x01,0xe5,0x00,0x00,0xff,0xff,0x00,0x82,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x26,0x00,0x53,0x00,0x00,0x00,0x07,0x06,0x6d,0x01,0xf9,0x00,0x00,0xff,0xff,0x00,0x82,0xff,0x10,0x02,0x26,0x02,0xda,0x02,0x26, 0x00,0x53,0x00,0x00,0x00,0x07,0x06,0xa0,0x02,0x80,0x00,0x00,0xff,0xff,0x00,0x82,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x26,0x00,0x53,0x00,0x00,0x01,0x07,0x03,0x29,0x00,0xa5,0x01,0x13,0x00,0x09,0xb1,0x01,0x01,0xb8,0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x14,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0d,0x00,0x2c,0x40,0x29, 0x0a,0x09,0x08,0x07,0x04,0x03,0x02,0x01,0x08,0x01,0x00,0x01,0x4c,0x00,0x00,0x00,0x38,0x4d,0x00,0x01,0x01,0x02,0x60,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x15,0x15,0x04,0x09,0x18,0x2b,0x33,0x11,0x07,0x35,0x37,0x11,0x33,0x11,0x37,0x15,0x07,0x11,0x21,0x15,0x82,0x6e,0x6e,0x5a,0xaa,0xaa,0x01,0x4a, 0x01,0x30,0x4a,0x50,0x4a,0x01,0x5a,0xfe,0xe3,0x73,0x50,0x73,0xfe,0xe5,0x52,0x00,0x00,0x01,0x00,0x48,0x00,0x00,0x02,0x10,0x02,0xda,0x00,0x13,0x00,0x2e,0x40,0x2b,0x0f,0x0c,0x03,0x03,0x03,0x00,0x01,0x4c,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x01,0x01,0x00,0x00,0x38,0x4d,0x05,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00, 0x00,0x13,0x00,0x13,0x16,0x11,0x12,0x11,0x06,0x09,0x1a,0x2b,0x33,0x11,0x33,0x13,0x13,0x33,0x11,0x23,0x11,0x34,0x36,0x36,0x37,0x03,0x23,0x03,0x16,0x16,0x15,0x11,0x48,0x85,0x5d,0x61,0x85,0x57,0x03,0x06,0x04,0x76,0x4e,0x71,0x08,0x06,0x02,0xda,0xfe,0xc4,0x01,0x3c,0xfd,0x26,0x01,0x59,0x31,0x7f,0x82,0x34,0xfe,0x87,0x01,0x70, 0x4a,0xb0,0x63,0xfe,0xa7,0x00,0x00,0x00,0x00,0x01,0x00,0x5a,0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x11,0x00,0x24,0x40,0x21,0x0c,0x03,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x38,0x4d,0x04,0x03,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x11,0x00,0x11,0x11,0x16,0x11,0x05,0x09,0x19,0x2b,0x33,0x11,0x33,0x13,0x2e,0x02, 0x35,0x11,0x33,0x11,0x23,0x03,0x1e,0x02,0x15,0x11,0x5a,0x78,0xdf,0x02,0x05,0x03,0x57,0x78,0xde,0x02,0x04,0x03,0x02,0xda,0xfd,0x8f,0x19,0x49,0x51,0x24,0x01,0x9a,0xfd,0x26,0x02,0x71,0x18,0x49,0x51,0x25,0xfe,0x66,0x00,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x5a,0x00,0x00,0x00,0x07,0x06,0x91, 0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x5a,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x10,0x01,0xfe,0x02,0xda,0x02,0x26,0x00,0x5a,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0x4c,0x01,0xfe,0x02,0xda,0x00,0x19, 0x00,0x2f,0x40,0x2c,0x0f,0x06,0x05,0x03,0x01,0x02,0x01,0x4c,0x03,0x01,0x02,0x02,0x38,0x4d,0x00,0x01,0x01,0x39,0x4d,0x00,0x00,0x00,0x04,0x61,0x05,0x01,0x04,0x04,0x3d,0x04,0x4e,0x00,0x00,0x00,0x19,0x00,0x18,0x16,0x11,0x18,0x21,0x06,0x09,0x1a,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x03,0x1e,0x02,0x15,0x11,0x23,0x11,0x33,0x13, 0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0xf0,0x41,0x35,0x3e,0xfc,0x02,0x04,0x03,0x57,0x78,0xdf,0x02,0x05,0x03,0x57,0x70,0x5d,0xb4,0x52,0x3d,0x34,0x02,0x62,0x18,0x49,0x51,0x25,0xfe,0x66,0x02,0xda,0xfd,0xdb,0x19,0x49,0x52,0x24,0x01,0x4d,0xfd,0x35,0x58,0x6b,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0xb1,0x02,0x26, 0x00,0x5a,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0xf6,0x02,0x00,0x02,0xe4,0x00,0x0d,0x00,0x1b,0x00,0x2d,0x40,0x2a,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x0f,0x0e,0x01,0x00,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08, 0x06,0x00,0x0d,0x01,0x0d,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x01,0x2c,0x62,0x72,0x72,0x62,0x62,0x72,0x72,0x62,0x3b,0x3f,0x3f,0x3b,0x3a,0x40,0x40,0x0a,0x72,0x6a,0x01,0x36,0x6a,0x72,0x72,0x69,0xfe, 0xc9,0x6a,0x72,0x51,0x43,0x3e,0x01,0x4a,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x67,0x03,0xfc,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0xc0,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x2b,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00, 0x00,0x27,0x06,0x9e,0x02,0x58,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x1c,0x03,0xfc,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0xc1,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x26,0x03,0xfc,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0xc2,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xfc,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0xc3,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb1,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x2b,0x02,0x00,0x02,0xe4,0x02,0x26,0x00,0x60,0x00,0x00, 0x00,0x07,0x06,0x9e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xd4,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0xf6,0x02,0x12, 0x03,0x2a,0x00,0x15,0x00,0x23,0x00,0x3e,0x40,0x3b,0x09,0x01,0x04,0x01,0x10,0x01,0x03,0x04,0x02,0x4c,0x00,0x02,0x01,0x02,0x85,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x06,0x01,0x03,0x03,0x00,0x61,0x05,0x01,0x00,0x00,0x3f,0x00,0x4e,0x17,0x16,0x01,0x00,0x1e,0x1c,0x16,0x23,0x17,0x23,0x0d,0x0c,0x08,0x06,0x00,0x15, 0x01,0x15,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x36,0x35,0x35,0x33,0x15,0x14,0x07,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x01,0x2c,0x62,0x72,0x72,0x62,0x50,0x35,0x16,0x4b,0x30,0x1e,0x72,0x62,0x3b,0x3f,0x3f,0x3b,0x3a,0x40,0x40,0x0a, 0x72,0x6a,0x01,0x36,0x6a,0x72,0x26,0x07,0x1a,0x4b,0x50,0x3a,0x19,0x33,0x4b,0xfe,0xc9,0x6a,0x72,0x51,0x43,0x3e,0x01,0x4a,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x12,0x03,0xb6,0x02,0x26,0x00,0x6d,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x2b,0x02,0x12, 0x03,0x2a,0x02,0x26,0x00,0x6d,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x12,0x03,0xb6,0x02,0x26,0x00,0x6d,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x44,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x12,0x03,0xd4,0x02,0x26,0x00,0x6d,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x4e,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x12,0x03,0xb1,0x02,0x26,0x00,0x6d,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x10,0x03,0xb6,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x92,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0x93,0x02,0x26,0x00,0x60,0x00,0x00, 0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x35,0x02,0x00,0x02,0xe4,0x00,0x1d,0x00,0x2b,0x00,0x64,0x4b,0xb0,0x15,0x50,0x58,0x40,0x21,0x00,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x07,0x01,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x03,0x03,0x00,0x5f,0x06,0x01,0x00,0x00,0x3d,0x00,0x4e, 0x1b,0x40,0x1e,0x00,0x03,0x06,0x01,0x00,0x03,0x00,0x63,0x00,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x07,0x01,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x17,0x1f,0x1e,0x01,0x00,0x26,0x24,0x1e,0x2b,0x1f,0x2b,0x1c,0x1a,0x0e,0x0c,0x07,0x05,0x00,0x1d,0x01,0x1d,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35, 0x34,0x37,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x03,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x01,0x7b,0x37,0x43,0x38,0x0d,0x62,0x72,0x72,0x62,0x62,0x72,0x2b,0x27,0x1d,0x21,0x1a,0x1e,0x19,0x3c,0x9d,0x3b,0x3f,0x3f, 0x3b,0x3a,0x40,0x40,0xcb,0x35,0x28,0x2e,0x36,0x70,0x62,0x01,0x4a,0x62,0x70,0x6f,0x62,0xfe,0xb5,0x3b,0x5a,0x1a,0x18,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x01,0x12,0x43,0x3e,0x01,0x4a,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0x00,0x00,0x03,0x00,0x23,0xff,0xd8,0x02,0x35,0x02,0xee,0x00,0x15,0x00,0x1c,0x00,0x23,0x00,0x75,0x40,0x13, 0x09,0x01,0x04,0x00,0x22,0x21,0x18,0x17,0x0c,0x01,0x06,0x05,0x04,0x14,0x01,0x02,0x05,0x03,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x06,0x01,0x03,0x02,0x03,0x86,0x00,0x04,0x04,0x00,0x61,0x01,0x01,0x00,0x00,0x3e,0x4d,0x07,0x01,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x3f,0x02,0x4e,0x1b,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x06, 0x01,0x03,0x02,0x03,0x86,0x00,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x3e,0x4d,0x07,0x01,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x3f,0x02,0x4e,0x59,0x40,0x14,0x1e,0x1d,0x00,0x00,0x1d,0x23,0x1e,0x23,0x1b,0x19,0x00,0x15,0x00,0x15,0x26,0x12,0x26,0x08,0x09,0x19,0x2b,0x17,0x37,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x17,0x37,0x33,0x07, 0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x27,0x07,0x13,0x11,0x13,0x26,0x23,0x22,0x06,0x13,0x32,0x36,0x35,0x11,0x03,0x16,0x23,0x4c,0x17,0x72,0x62,0x5c,0x38,0x21,0x54,0x46,0x11,0x72,0x62,0x55,0x37,0x29,0x3b,0xe0,0x1f,0x47,0x3a,0x40,0x7a,0x3b,0x3f,0xda,0x20,0x28,0x86,0x2d,0x3d,0x01,0x4a,0x62,0x70,0x31,0x3b,0x7d,0x29,0x35,0xfe, 0xb5,0x62,0x70,0x2b,0x49,0x02,0x3a,0xfe,0xc3,0x01,0x8d,0x31,0x43,0xfd,0xf7,0x43,0x3e,0x01,0x29,0xfe,0x7e,0x28,0x00,0x00,0xff,0xff,0x00,0x23,0xff,0xd8,0x02,0x35,0x03,0xb6,0x02,0x26,0x00,0x76,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb1,0x02,0x26,0x00,0x60,0x00,0x00, 0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x28,0xff,0xf6,0x02,0x3f,0x02,0xe4,0x00,0x1d,0x00,0x2b,0x00,0xe3,0x4b,0xb0,0x15,0x50,0x58,0x40,0x0a,0x0b,0x01,0x03,0x01,0x19,0x01,0x00,0x06,0x02,0x4c,0x1b,0x40,0x0a,0x0b,0x01,0x03,0x09,0x19,0x01,0x08,0x06,0x02,0x4c,0x59,0x4b,0xb0,0x15,0x50,0x58,0x40,0x23,0x00,0x04, 0x00,0x05,0x06,0x04,0x05,0x67,0x09,0x01,0x03,0x03,0x01,0x61,0x02,0x01,0x01,0x01,0x3e,0x4d,0x0b,0x08,0x02,0x06,0x06,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x38,0x00,0x04,0x00,0x05,0x06,0x04,0x05,0x67,0x00,0x09,0x09,0x01,0x61,0x02,0x01,0x01,0x01,0x3e,0x4d,0x00,0x03,0x03,0x01, 0x61,0x02,0x01,0x01,0x01,0x3e,0x4d,0x00,0x06,0x06,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x33,0x00,0x04,0x00,0x05,0x06,0x04,0x05,0x67,0x00,0x09,0x09,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d, 0x00,0x06,0x06,0x07,0x5f,0x00,0x07,0x07,0x39,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x0a,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x59,0x40,0x1f,0x1f,0x1e,0x01,0x00,0x26,0x24,0x1e,0x2b,0x1f,0x2b,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x08,0x06,0x00,0x1d,0x01,0x1d,0x0c,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x11, 0x34,0x36,0x33,0x32,0x16,0x16,0x17,0x33,0x35,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x21,0x35,0x23,0x0e,0x02,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0xc3,0x48,0x53,0x53,0x48,0x23,0x2e,0x1a,0x03,0x05,0x01,0x09,0xb1,0x98,0x98,0xb1,0xfe,0xf7,0x05,0x03,0x1a,0x2e,0x0a,0x2a,0x30,0x30, 0x2a,0x2a,0x30,0x30,0x0a,0x66,0x58,0x01,0x72,0x58,0x66,0x1d,0x29,0x14,0x50,0x52,0xe6,0x52,0xfe,0x52,0x50,0x13,0x2a,0x1d,0x50,0x3b,0x33,0x01,0x72,0x33,0x3b,0x3b,0x33,0xfe,0x8e,0x33,0x3b,0x00,0x00,0x00,0x00,0x02,0x00,0x5c,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x2b,0x40,0x28,0x00,0x03,0x00,0x01,0x02,0x03, 0x01,0x67,0x00,0x04,0x04,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x0a,0x24,0x21,0x06,0x09,0x18,0x2b,0x33,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x5c,0xeb,0x66,0x79,0x79,0x66,0x91,0x91,0x3b, 0x47,0x47,0x3b,0x91,0x02,0xda,0x75,0x62,0x62,0x75,0xfe,0xd4,0x01,0x7d,0x49,0x3d,0x3e,0x48,0x00,0x00,0x00,0x02,0x00,0x5a,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0d,0x00,0x16,0x00,0x2f,0x40,0x2c,0x00,0x01,0x00,0x05,0x04,0x01,0x05,0x67,0x00,0x04,0x00,0x02,0x03,0x04,0x02,0x67,0x00,0x00,0x00,0x38,0x4d,0x06,0x01,0x03,0x03,0x39, 0x03,0x4e,0x00,0x00,0x16,0x14,0x10,0x0e,0x00,0x0d,0x00,0x0d,0x25,0x21,0x11,0x07,0x09,0x19,0x2b,0x33,0x11,0x33,0x15,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x5a,0x5a,0x99,0x42,0x61,0x36,0x76,0x63,0x99,0x99,0x3a,0x42,0x43,0x39,0x99,0x02,0xda,0x96,0x32,0x5a,0x3c,0x5b, 0x6d,0xb4,0x01,0x04,0x41,0x37,0x38,0x40,0x00,0x02,0x00,0x50,0xff,0x4c,0x02,0x0e,0x02,0xe4,0x00,0x13,0x00,0x21,0x00,0x38,0x40,0x35,0x12,0x01,0x00,0x03,0x01,0x4c,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x06,0x01,0x03,0x03,0x00,0x61,0x00,0x00,0x00,0x3f,0x4d,0x05,0x01,0x02,0x02,0x3d,0x02,0x4e,0x15,0x14,0x00,0x00, 0x1c,0x1a,0x14,0x21,0x15,0x21,0x00,0x13,0x00,0x13,0x25,0x23,0x07,0x09,0x18,0x2b,0x05,0x27,0x22,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x17,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x01,0xa6,0x67,0x04,0x0a,0x05,0x65,0x77,0x77,0x65,0x65,0x77,0x3a,0x35, 0x75,0xe2,0x3b,0x47,0x47,0x3b,0x3b,0x47,0x47,0xb4,0xab,0x01,0x75,0x62,0x01,0x40,0x62,0x75,0x75,0x62,0xfe,0xc0,0x43,0x64,0x19,0xc1,0xfa,0x4a,0x3d,0x01,0x40,0x3e,0x49,0x49,0x3e,0xfe,0xc0,0x3d,0x4a,0x00,0x00,0x02,0x00,0x5d,0x00,0x00,0x02,0x21,0x02,0xda,0x00,0x0e,0x00,0x17,0x00,0x33,0x40,0x30,0x09,0x01,0x02,0x04,0x01,0x4c, 0x00,0x04,0x00,0x02,0x01,0x04,0x02,0x67,0x00,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x06,0x03,0x02,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x17,0x15,0x11,0x0f,0x00,0x0e,0x00,0x0e,0x11,0x17,0x21,0x07,0x09,0x19,0x2b,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x13,0x23,0x03,0x23,0x11,0x11,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x23,0x5d,0xe1,0x41,0x62,0x36,0x4c,0x3f,0x95,0x63,0x8f,0x79,0x88,0x38,0x44,0x44,0x38,0x88,0x02,0xda,0x35,0x5e,0x3f,0x4a,0x6a,0x15,0xfe,0xc1,0x01,0x36,0xfe,0xca,0x01,0x87,0x47,0x3a,0x3b,0x46,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x21,0x03,0xb6,0x02,0x26,0x00,0x7d,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00, 0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x21,0x03,0xb6,0x02,0x26,0x00,0x7d,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5d,0xff,0x10,0x02,0x21,0x02,0xda,0x02,0x26,0x00,0x7d,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x48,0xff,0xf6,0x02,0x10,0x02,0xe4,0x00,0x29,0x00,0x3b,0x40,0x38, 0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x3e,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x1e,0x1c,0x1a,0x19,0x16,0x14,0x08,0x06,0x04,0x03,0x00,0x29,0x01,0x29,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16, 0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x01,0x30,0x6a,0x7e,0x5a,0x4e,0x40,0x3e,0x4a,0x2f,0x2c,0x6f,0x45,0x4f,0x34,0x5e,0x3d,0x3e,0x5f,0x36,0x5a,0x44,0x35,0x35,0x42,0x2b,0x27,0x72,0x49, 0x51,0x7a,0x0a,0x70,0x62,0x3d,0x45,0x48,0x3a,0x2c,0x41,0x0c,0x1f,0x14,0x67,0x46,0x3a,0x58,0x31,0x31,0x57,0x39,0x32,0x3f,0x3f,0x32,0x28,0x39,0x0b,0x20,0x14,0x6f,0x4c,0x60,0x72,0x00,0xff,0xff,0x00,0x48,0xff,0xf6,0x02,0x10,0x03,0xb6,0x02,0x26,0x00,0x81,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x48, 0xff,0xf6,0x02,0x10,0x03,0xb6,0x02,0x26,0x00,0x81,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x48,0xff,0x35,0x02,0x10,0x02,0xe4,0x00,0x3d,0x00,0x95,0x40,0x0a,0x09,0x01,0x07,0x03,0x36,0x01,0x01,0x07,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x36,0x00,0x05,0x06,0x02,0x06,0x05,0x02,0x80,0x00,0x02,0x03, 0x06,0x02,0x03,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x72,0x00,0x06,0x06,0x04,0x61,0x00,0x04,0x04,0x3e,0x4d,0x00,0x03,0x03,0x07,0x61,0x00,0x07,0x07,0x3f,0x4d,0x00,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08,0x3d,0x08,0x4e,0x1b,0x40,0x34,0x00,0x05,0x06,0x02,0x06,0x05,0x02,0x80,0x00,0x02,0x03,0x06,0x02,0x03,0x7e,0x00,0x01,0x07, 0x00,0x07,0x01,0x00,0x80,0x00,0x00,0x09,0x01,0x08,0x00,0x08,0x63,0x00,0x06,0x06,0x04,0x61,0x00,0x04,0x04,0x3e,0x4d,0x00,0x03,0x03,0x07,0x61,0x00,0x07,0x07,0x3f,0x07,0x4e,0x59,0x40,0x11,0x00,0x00,0x00,0x3d,0x00,0x3c,0x1b,0x22,0x13,0x2c,0x22,0x14,0x14,0x21,0x0a,0x09,0x1e,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23, 0x37,0x26,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xcd,0x46,0x16,0x1b,0x37,0x32,0x18,0x4f,0x5c,0x5a,0x4e,0x40, 0x3e,0x4a,0x2f,0x2c,0x6f,0x45,0x4f,0x34,0x5e,0x3d,0x3e,0x5f,0x36,0x5a,0x44,0x35,0x35,0x42,0x2b,0x27,0x72,0x49,0x51,0x7a,0x66,0x03,0x02,0x09,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x40,0x0f,0x6b,0x53,0x3d,0x45,0x48,0x3a,0x2c,0x41,0x0c,0x1f,0x14,0x67,0x46,0x3a,0x58,0x31,0x31,0x57,0x39,0x32,0x3f,0x3f,0x32, 0x28,0x39,0x0b,0x20,0x14,0x6f,0x4c,0x60,0x72,0x19,0x03,0x14,0x24,0x1a,0x22,0x31,0xff,0xff,0x00,0x48,0xff,0xf6,0x02,0x10,0x03,0xb6,0x02,0x26,0x00,0x81,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x48,0xff,0x10,0x02,0x10,0x02,0xe4,0x02,0x26,0x00,0x81,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00, 0x00,0x01,0x00,0x5c,0x00,0x00,0x02,0x1c,0x02,0xda,0x00,0x20,0x00,0x38,0x40,0x35,0x1a,0x07,0x02,0x01,0x05,0x01,0x4c,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x69,0x00,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x02,0x61,0x07,0x06,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x20,0x00,0x20,0x22,0x24,0x21,0x25, 0x12,0x24,0x08,0x09,0x1c,0x2b,0x33,0x11,0x34,0x36,0x36,0x33,0x33,0x15,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x37,0x23,0x22,0x06,0x15,0x11,0x5c,0x34,0x5f,0x3f,0xe3,0xa2,0x4e,0x5f,0x36,0x60,0x41,0x43,0x39,0x3c,0x46,0x46,0x3c,0x2d,0xa4,0x84,0x37,0x41,0x02,0x0c,0x3e, 0x5d,0x33,0x58,0xdb,0x05,0x70,0x5b,0x40,0x61,0x36,0x52,0x48,0x3d,0x3c,0x46,0x4e,0xe1,0x42,0x3a,0xfd,0xf4,0x00,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0xe4,0x00,0x16,0x00,0x1f,0x00,0x43,0x40,0x40,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x67,0x00,0x02,0x02,0x04,0x61,0x00, 0x04,0x04,0x3e,0x4d,0x08,0x01,0x05,0x05,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x18,0x17,0x01,0x00,0x1c,0x1b,0x17,0x1f,0x18,0x1f,0x11,0x0f,0x0d,0x0c,0x0a,0x08,0x05,0x04,0x00,0x16,0x01,0x16,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x21,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x15,0x11, 0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x15,0x14,0x16,0x01,0x2c,0x61,0x71,0x01,0x4a,0x3d,0x3b,0x3a,0x3e,0x5a,0x70,0x62,0x64,0x6e,0x70,0x62,0x3e,0x3a,0xf0,0x3b,0x0a,0x73,0x5f,0xc8,0x83,0x3e,0x43,0x44,0x3e,0x61,0x71,0x70,0x62,0xfe,0xb6,0x5f,0x73,0x4b,0x46,0x41,0x82,0x82,0x41,0x46,0x00,0x01,0x00,0x37,0x00,0x00,0x02,0x21, 0x02,0xda,0x00,0x07,0x00,0x21,0x40,0x1e,0x02,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xff,0xc8,0x01,0xea,0xc8,0x02,0x88,0x52,0x52,0xfd,0x78,0x00,0x00,0x00,0x01,0x00,0x37, 0x00,0x00,0x02,0x21,0x02,0xda,0x00,0x0f,0x00,0x2f,0x40,0x2c,0x05,0x01,0x01,0x06,0x01,0x00,0x07,0x01,0x00,0x67,0x04,0x01,0x02,0x02,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x08,0x01,0x07,0x07,0x39,0x07,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x09,0x1d,0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x23, 0x35,0x21,0x15,0x23,0x11,0x33,0x15,0x23,0x11,0xff,0x91,0x91,0xc8,0x01,0xea,0xc8,0x91,0x91,0x01,0x27,0x4b,0x01,0x16,0x52,0x52,0xfe,0xea,0x4b,0xfe,0xd9,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x21,0x03,0xb6,0x02,0x26,0x00,0x89,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x37,0xff,0x35,0x02,0x21, 0x02,0xda,0x00,0x19,0x00,0x6f,0x40,0x0b,0x08,0x01,0x05,0x06,0x01,0x4c,0x07,0x01,0x06,0x01,0x4b,0x4b,0xb0,0x15,0x50,0x58,0x40,0x24,0x00,0x05,0x06,0x04,0x06,0x05,0x04,0x80,0x02,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x07,0x01,0x06,0x06,0x39,0x4d,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40, 0x21,0x00,0x05,0x06,0x04,0x06,0x05,0x04,0x80,0x00,0x04,0x00,0x03,0x04,0x03,0x63,0x02,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x59,0x40,0x0f,0x00,0x00,0x00,0x19,0x00,0x19,0x14,0x21,0x28,0x11,0x11,0x11,0x08,0x09,0x1c,0x2b,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x07,0x1e,0x02, 0x15,0x14,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0xff,0xc8,0x01,0xea,0xc8,0x0c,0x1a,0x38,0x26,0x42,0x36,0x55,0x46,0x16,0x1b,0x37,0x32,0x19,0x02,0x88,0x52,0x52,0xfd,0x78,0x23,0x03,0x14,0x24,0x1a,0x22,0x31,0x37,0x17,0x0d,0x11,0x1a,0x45,0x00,0xff,0xff,0x00,0x37,0xff,0x10,0x02,0x21,0x02,0xda,0x02,0x26, 0x00,0x89,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0xda,0x00,0x11,0x00,0x24,0x40,0x21,0x03,0x01,0x01,0x01,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x0e,0x0d,0x0a,0x08,0x05,0x04,0x00,0x11,0x01,0x11,0x05,0x09,0x16,0x2b,0x05,0x22, 0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x01,0x2c,0x66,0x6c,0x5a,0x3b,0x3d,0x3c,0x3c,0x5a,0x6b,0x0a,0x71,0x61,0x02,0x12,0xfd,0xee,0x3c,0x46,0x46,0x3c,0x02,0x12,0xfd,0xee,0x62,0x70,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x91, 0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb1,0x02,0x26, 0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x2b,0x01,0xfe,0x02,0xda,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb6,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x5a, 0xff,0xf6,0x01,0xfe,0x03,0xd4,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0xf6,0x02,0x53,0x03,0x48,0x00,0x1a,0x00,0x31,0x40,0x2e,0x17,0x01,0x02,0x01,0x01,0x4c,0x00,0x04,0x01,0x04,0x85,0x03,0x01,0x01,0x01,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x05,0x01,0x00,0x00,0x3f,0x00, 0x4e,0x01,0x00,0x13,0x12,0x0f,0x0d,0x0a,0x08,0x05,0x04,0x00,0x1a,0x01,0x1a,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x11,0x14,0x06,0x01,0x2c,0x66,0x6c,0x5a,0x3b,0x3d,0x3c,0x3c,0x41,0x10,0x13,0x4b,0x2e,0x27,0x6b,0x0a,0x71, 0x61,0x02,0x12,0xfd,0xee,0x3c,0x46,0x46,0x3c,0x02,0x12,0x13,0x10,0x4b,0x50,0x27,0x31,0x06,0xfe,0x2e,0x62,0x70,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x53,0x03,0xb6,0x02,0x26,0x00,0x96,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x2b,0x02,0x53,0x03,0x48,0x02,0x26,0x00,0x96,0x00,0x00, 0x00,0x07,0x06,0x9e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x53,0x03,0xb6,0x02,0x26,0x00,0x96,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x53,0x03,0xd4,0x02,0x26,0x00,0x96,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x53, 0x03,0xb1,0x02,0x26,0x00,0x96,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x10,0x03,0xb6,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x92,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x93,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00, 0x00,0x01,0x00,0x5a,0xff,0x35,0x01,0xfe,0x02,0xda,0x00,0x20,0x00,0x56,0x4b,0xb0,0x15,0x50,0x58,0x40,0x1c,0x04,0x01,0x02,0x02,0x38,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x05,0x05,0x00,0x5f,0x06,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x19,0x00,0x05,0x06,0x01,0x00,0x05,0x00,0x63,0x04,0x01,0x02,0x02, 0x38,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x13,0x01,0x00,0x1f,0x1d,0x14,0x13,0x10,0x0e,0x0b,0x0a,0x07,0x05,0x00,0x20,0x01,0x20,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x37,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x07,0x07,0x06,0x06,0x15, 0x14,0x16,0x33,0x33,0x15,0x01,0x7b,0x37,0x43,0x38,0x0d,0x62,0x70,0x5a,0x3e,0x3a,0x3b,0x3d,0x5a,0x50,0x1d,0x21,0x1a,0x1e,0x19,0x3c,0xcb,0x35,0x28,0x2e,0x36,0x70,0x62,0x02,0x12,0xfd,0xee,0x3e,0x43,0x43,0x3e,0x02,0x12,0xfd,0xee,0x79,0x36,0x18,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe, 0x03,0xe2,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x96,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xb1,0x02,0x26,0x00,0x8e,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0c,0x00,0x21,0x40,0x1e,0x06,0x01,0x02,0x00,0x01,0x4c,0x01,0x01, 0x00,0x00,0x38,0x4d,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x0c,0x00,0x0c,0x18,0x11,0x04,0x09,0x18,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0xee,0xbc,0x5c,0x7d,0x0d,0x11,0x04,0x04,0x13,0x0d,0x78,0x5d,0xbd,0x02,0xda,0xfe,0x0f,0x34,0x58,0x17,0x17,0x59,0x34,0x01,0xf0,0xfd,0x26,0x00, 0x00,0x01,0x00,0x14,0x00,0x00,0x02,0x44,0x02,0xda,0x00,0x1e,0x00,0x26,0x40,0x23,0x1a,0x06,0x02,0x03,0x00,0x01,0x4c,0x02,0x01,0x02,0x00,0x00,0x38,0x4d,0x05,0x04,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x1e,0x00,0x1e,0x11,0x18,0x18,0x11,0x06,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33, 0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x23,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x6b,0x57,0x53,0x39,0x04,0x04,0x01,0x02,0x07,0x04,0x48,0x61,0x42,0x04,0x08,0x02,0x02,0x05,0x04,0x3b,0x4f,0x59,0x71,0x42,0x04,0x04,0x02,0x02,0x04,0x05,0x47,0x02,0xda,0xfd,0xe4,0x21,0x47,0x15,0x15,0x47,0x21,0x02,0x1c,0xfd,0xe4, 0x21,0x47,0x15,0x15,0x47,0x21,0x02,0x1c,0xfd,0x26,0x02,0x26,0x22,0x41,0x12,0x12,0x41,0x22,0xfd,0xda,0xff,0xff,0x00,0x14,0x00,0x00,0x02,0x44,0x03,0xb6,0x02,0x26,0x00,0xa2,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x14,0x00,0x00,0x02,0x44,0x03,0xb6,0x02,0x26,0x00,0xa2,0x00,0x00,0x00,0x07,0x06,0x93, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x14,0x00,0x00,0x02,0x44,0x03,0xb1,0x02,0x26,0x00,0xa2,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x14,0x00,0x00,0x02,0x44,0x03,0xb6,0x02,0x26,0x00,0xa2,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0x00,0x01,0x00,0x28,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x17, 0x00,0x26,0x40,0x23,0x13,0x0d,0x07,0x01,0x04,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x38,0x4d,0x04,0x03,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x17,0x00,0x17,0x12,0x18,0x12,0x05,0x09,0x19,0x2b,0x33,0x13,0x03,0x33,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x03,0x13,0x23,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07, 0x28,0xd2,0xc7,0x68,0x71,0x09,0x13,0x06,0x05,0x13,0x09,0x73,0x63,0xc7,0xd2,0x67,0x7d,0x09,0x13,0x05,0x05,0x13,0x09,0x7e,0x01,0x72,0x01,0x68,0xd8,0x11,0x27,0x0b,0x0b,0x27,0x11,0xd8,0xfe,0x9e,0xfe,0x88,0xe8,0x11,0x27,0x0c,0x0c,0x26,0x11,0xe9,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x35,0x02,0xda,0x00,0x0e,0x00,0x23,0x40,0x20, 0x0d,0x07,0x01,0x03,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x38,0x4d,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x0e,0x00,0x0e,0x18,0x12,0x04,0x09,0x18,0x2b,0x33,0x11,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x11,0xff,0xdc,0x60,0x8e,0x0c,0x0e,0x02,0x02,0x0f,0x0c,0x8e,0x5d,0xdc,0x01,0x11,0x01, 0xc9,0xfe,0xd4,0x19,0x23,0x08,0x08,0x23,0x19,0x01,0x2c,0xfe,0x37,0xfe,0xef,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xb6,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xb6,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xb1,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x23,0xff,0x2b,0x02,0x35,0x02,0xda,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x9e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xb6,0x02,0x26,0x00,0xa8,0x00,0x00, 0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xd4,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x99,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0x93,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35, 0x03,0xb1,0x02,0x26,0x00,0xa8,0x00,0x00,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x55,0x00,0x00,0x02,0x03,0x02,0xda,0x00,0x09,0x00,0x2c,0x40,0x29,0x06,0x01,0x02,0x02,0x00,0x01,0x4c,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00, 0x09,0x00,0x09,0x12,0x11,0x12,0x05,0x09,0x19,0x2b,0x33,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x55,0x01,0x49,0xfe,0xbc,0x01,0x9f,0xfe,0xb7,0x01,0x53,0x5a,0x02,0x2e,0x52,0x5a,0xfd,0xd2,0x52,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x03,0x03,0xb6,0x02,0x26,0x00,0xb1,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00, 0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x03,0x03,0xb6,0x02,0x26,0x00,0xb1,0x00,0x00,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x03,0x03,0xb0,0x02,0x26,0x00,0xb1,0x00,0x00,0x00,0x07,0x06,0x8f,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x19,0x00,0x00,0x02,0x3f,0x02,0xda,0x00,0x18,0x00,0x2d,0x40,0x2a, 0x17,0x06,0x02,0x03,0x01,0x01,0x4c,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x02,0x01,0x00,0x00,0x38,0x4d,0x05,0x04,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x18,0x00,0x18,0x11,0x18,0x18,0x11,0x06,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33, 0x03,0x23,0x03,0x03,0x62,0x49,0x53,0x30,0x03,0x03,0x01,0x02,0x04,0x07,0x4c,0x66,0x45,0x06,0x07,0x01,0x01,0x05,0x03,0x32,0x4f,0x4b,0x73,0x53,0x59,0x02,0xda,0xfd,0xe4,0x21,0x3d,0x15,0x15,0x3c,0x22,0x01,0x90,0xfe,0x70,0x22,0x3c,0x15,0x15,0x3d,0x21,0x02,0x1c,0xfd,0x26,0x01,0xf4,0xfe,0x0c,0x00,0x00,0x00,0xff,0xff,0x00,0x19, 0x00,0x00,0x02,0x3f,0x03,0xb6,0x02,0x26,0x00,0xb5,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x19,0x00,0x00,0x02,0x3f,0x03,0xb6,0x02,0x26,0x00,0xb5,0x00,0x00,0x00,0x07,0x06,0x93,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x19,0x00,0x00,0x02,0x3f,0x03,0xb1,0x02,0x26,0x00,0xb5,0x00,0x00,0x00,0x07,0x06,0x8e, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x19,0x00,0x00,0x02,0x3f,0x03,0xb6,0x02,0x26,0x00,0xb5,0x00,0x00,0x00,0x07,0x06,0x90,0x02,0x4e,0x00,0x00,0x00,0x02,0x00,0x5d,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x05,0x00,0x09,0x00,0x2b,0x40,0x28,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x02,0x01,0x00,0x00,0x38,0x4d,0x05,0x03,0x04,0x03,0x01, 0x01,0x39,0x01,0x4e,0x06,0x06,0x00,0x00,0x06,0x09,0x06,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x12,0x06,0x09,0x17,0x2b,0x21,0x03,0x13,0x33,0x03,0x13,0x21,0x11,0x33,0x11,0x01,0xbf,0xf9,0xf9,0x67,0xf0,0xfa,0xfe,0x2d,0x5a,0x01,0x7c,0x01,0x5e,0xfe,0xa2,0xfe,0x84,0x02,0xda,0xfd,0x26,0x00,0xff,0xff,0x00,0x5d,0xff,0x10,0x02,0x30, 0x02,0xda,0x02,0x26,0x00,0xba,0x00,0x00,0x00,0x07,0x06,0xa0,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x4c,0x02,0x00,0x02,0xe4,0x00,0x18,0x00,0x26,0x00,0x3e,0x40,0x3b,0x12,0x04,0x02,0x02,0x03,0x01,0x4c,0x06,0x01,0x03,0x04,0x02,0x04,0x03,0x02,0x80,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x02,0x02,0x00, 0x60,0x05,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1a,0x19,0x01,0x00,0x21,0x1f,0x19,0x26,0x1a,0x26,0x17,0x15,0x0c,0x0a,0x00,0x18,0x01,0x18,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x26,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x15,0x14,0x16,0x33,0x33,0x15,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22, 0x06,0x15,0x11,0x14,0x16,0x01,0x8b,0x44,0x52,0x4a,0x53,0x72,0x62,0x62,0x72,0x5e,0x53,0x21,0x1b,0x6e,0xcd,0x3b,0x3f,0x3f,0x3b,0x3a,0x40,0x40,0xb4,0x4f,0x42,0x1e,0x0f,0x6e,0x5a,0x01,0x36,0x6a,0x72,0x72,0x69,0xfe,0xc9,0x60,0x70,0x0a,0x1b,0x1c,0x23,0x52,0xfb,0x43,0x3e,0x01,0x4a,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0x00, 0x00,0x02,0x00,0x43,0xff,0xf6,0x01,0xfc,0x02,0x30,0x00,0x1b,0x00,0x26,0x00,0x84,0xb5,0x18,0x01,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x28,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x67,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x05,0x08, 0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x2c,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x67,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x05,0x05,0x39,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1b,0x1d,0x1c,0x01,0x00,0x22,0x20,0x1c,0x26, 0x1d,0x26,0x17,0x16,0x13,0x11,0x0f,0x0e,0x0c,0x0a,0x08,0x06,0x00,0x1b,0x01,0x1b,0x0a,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x35,0x34,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0xfc,0x55,0x64,0x2e,0x52, 0x35,0xaa,0x75,0x34,0x40,0x02,0x5a,0x05,0x6f,0x5c,0x64,0x6b,0x59,0x02,0x08,0x56,0x31,0x42,0x4e,0xa0,0x2c,0x37,0x3d,0x0a,0x5f,0x4d,0x33,0x4c,0x2b,0x2b,0x6b,0x26,0x22,0x41,0x55,0x60,0x56,0xfe,0x86,0x64,0x33,0x3b,0x4c,0x40,0x37,0x4d,0x35,0x2c,0x2e,0x35,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x11,0x02,0x26, 0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x7a,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb4,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43, 0xff,0x2b,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x27,0x06,0x78,0x02,0x5d,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x7a,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb5,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0xa2,0x02,0x26, 0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb6,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0xa0,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb7,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43, 0xff,0xf6,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x02,0x76,0x03,0x84,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb8,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0x2b,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x27,0x06,0x78, 0x02,0x5d,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x02,0x26,0x03,0x84,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xb9,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x02,0x2b,0x03,0xa2,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xba,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43, 0xff,0xf6,0x01,0xfc,0x03,0xa0,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0xbb,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x09,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0x2b,0x01,0xfc,0x02,0x30,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x78, 0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x11,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x53,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x39,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x02,0xe9,0x02,0x26, 0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x5d,0x00,0x00,0x00,0x02,0x00,0x43,0xff,0x35,0x02,0x31,0x02,0x30,0x00,0x2b,0x00,0x36,0x00,0xea,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0a,0x28,0x01,0x08,0x09,0x16,0x01,0x00,0x08,0x02,0x4c,0x1b,0x40,0x0b,0x28,0x01,0x08,0x09,0x01,0x4c,0x16,0x01,0x07,0x01,0x4b,0x59,0x4b,0xb0,0x15,0x50, 0x58,0x40,0x32,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x67,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x4d,0x00,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3d,0x06,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x2f,0x00,0x03,0x02, 0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x67,0x00,0x05,0x00,0x06,0x05,0x06,0x63,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x33,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x67,0x00, 0x05,0x00,0x06,0x05,0x06,0x63,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x07,0x07,0x39,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x0a,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x59,0x40,0x1f,0x2d,0x2c,0x01,0x00,0x32,0x30,0x2c,0x36,0x2d,0x36,0x27,0x26,0x21,0x1f,0x1e,0x1c,0x13,0x11,0x0f,0x0e,0x0c,0x0a,0x08,0x06,0x00,0x2b, 0x01,0x2b,0x0c,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x35,0x34,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x33,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0xfc,0x55,0x64, 0x2e,0x52,0x35,0xaa,0x75,0x34,0x40,0x02,0x5a,0x05,0x6f,0x5c,0x64,0x6b,0x02,0x22,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x20,0x27,0x0d,0x02,0x08,0x56,0x31,0x42,0x4e,0xa0,0x2c,0x37,0x3d,0x0a,0x5f,0x4d,0x33,0x4c,0x2b,0x2b,0x6b,0x26,0x22,0x41,0x55,0x60,0x56,0xfe,0x86,0x1c,0x2c,0x15,0x16,0x1c,0x3c,0x35,0x28,0x1a,0x36,0x1e,0x64, 0x33,0x3b,0x4c,0x40,0x37,0x4d,0x35,0x2c,0x2e,0x35,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x44,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x71,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x03,0x0c,0x02,0x26,0x00,0xbd,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x5d,0x00,0x00,0x00,0x03,0x00,0x1f, 0xff,0xf6,0x02,0x35,0x02,0x30,0x00,0x2d,0x00,0x36,0x00,0x41,0x00,0xa9,0x40,0x0a,0x15,0x01,0x03,0x02,0x2b,0x01,0x07,0x08,0x02,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x33,0x00,0x03,0x02,0x01,0x02,0x03,0x72,0x00,0x08,0x06,0x07,0x07,0x08,0x72,0x0a,0x01,0x01,0x0d,0x01,0x06,0x08,0x01,0x06,0x67,0x0b,0x01,0x02,0x02,0x04,0x61,0x05, 0x01,0x04,0x04,0x41,0x4d,0x0f,0x0c,0x02,0x07,0x07,0x00,0x62,0x09,0x0e,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x35,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x08,0x06,0x07,0x06,0x08,0x07,0x80,0x0a,0x01,0x01,0x0d,0x01,0x06,0x08,0x01,0x06,0x67,0x0b,0x01,0x02,0x02,0x04,0x61,0x05,0x01,0x04,0x04,0x41,0x4d,0x0f,0x0c,0x02, 0x07,0x07,0x00,0x62,0x09,0x0e,0x02,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x27,0x38,0x37,0x01,0x00,0x3d,0x3b,0x37,0x41,0x38,0x41,0x34,0x32,0x2f,0x2e,0x29,0x27,0x25,0x24,0x22,0x20,0x1d,0x1c,0x19,0x17,0x13,0x11,0x0f,0x0e,0x0c,0x0a,0x07,0x05,0x00,0x2d,0x01,0x2d,0x10,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35, 0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x13,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x03,0x32,0x36,0x35,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0xb2,0x41,0x52,0x54,0x43,0x51,0x24, 0x20,0x1f,0x26,0x4f,0x4b,0x3c,0x31,0x44,0x05,0x05,0x41,0x2e,0x41,0x50,0xde,0x25,0x20,0x20,0x25,0x54,0x50,0x41,0x2b,0x41,0x08,0x08,0x46,0x75,0x8a,0x25,0x20,0x1f,0x26,0x98,0x21,0x27,0x4f,0x1f,0x26,0x29,0x0a,0x5e,0x4b,0x4a,0x5b,0x4b,0x29,0x2d,0x27,0x20,0x41,0x51,0x31,0x28,0x28,0x31,0x59,0x47,0x90,0x6a,0x28,0x2d,0x28,0x20, 0x41,0x52,0x32,0x28,0x28,0x32,0x01,0x4e,0x4c,0x27,0x2e,0x2e,0x27,0xfe,0xb1,0x2e,0x27,0x6a,0x34,0x2c,0x2b,0x34,0x00,0x00,0xff,0xff,0x00,0x1f,0xff,0xf6,0x02,0x35,0x03,0x11,0x02,0x26,0x00,0xd4,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0x00,0x02,0x00,0x5c,0xff,0xf6,0x02,0x01,0x02,0xda,0x00,0x14,0x00,0x22,0x00,0x6b, 0xb6,0x0a,0x03,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x01,0x06,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x21,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x41,0x4d,0x00,0x01, 0x01,0x39,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x17,0x16,0x15,0x01,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x0f,0x0d,0x08,0x07,0x06,0x05,0x00,0x14,0x01,0x14,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x27,0x23,0x15,0x23,0x11,0x33,0x15,0x07,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06, 0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x4c,0x3e,0x50,0x07,0x01,0x5a,0x5a,0x02,0x01,0x08,0x51,0x3e,0x53,0x62,0x62,0x71,0x39,0x40,0x40,0x39,0x37,0x41,0x41,0x0a,0x3d,0x36,0x69,0x02,0xda,0xa0,0x7d,0x35,0x3e,0x6e,0x5f,0xa1,0x5e,0x6e,0x4e,0x3c,0x43,0xa0,0x44,0x3b,0x46,0x3e,0x96,0x3e,0x46, 0x00,0x01,0x00,0x58,0xff,0xf6,0x02,0x0b,0x02,0x30,0x00,0x1b,0x00,0x3b,0x40,0x38,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x19,0x18,0x16,0x14,0x0f,0x0d,0x0b,0x0a,0x08, 0x06,0x00,0x1b,0x01,0x1b,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x01,0x34,0x64,0x78,0x78,0x64,0x5f,0x75,0x03,0x5a,0x03,0x42,0x38,0x3b,0x47,0x47,0x3b,0x38,0x42,0x03,0x5a,0x03,0x75,0x0a,0x70,0x62,0x96, 0x62,0x70,0x66,0x58,0x35,0x39,0x43,0x3e,0x97,0x3e,0x44,0x3a,0x34,0x58,0x66,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x0b,0x03,0x11,0x02,0x26,0x00,0xd7,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x6a,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x0b,0x03,0x11,0x02,0x26,0x00,0xd7,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x60,0x00,0x00, 0x00,0x01,0x00,0x58,0xff,0x35,0x02,0x0b,0x02,0x30,0x00,0x2f,0x00,0x95,0x40,0x0a,0x09,0x01,0x07,0x05,0x28,0x01,0x01,0x07,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x36,0x00,0x03,0x04,0x06,0x04,0x03,0x06,0x80,0x00,0x06,0x05,0x04,0x06,0x05,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x72,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x41, 0x4d,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x3f,0x4d,0x00,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08,0x3d,0x08,0x4e,0x1b,0x40,0x34,0x00,0x03,0x04,0x06,0x04,0x03,0x06,0x80,0x00,0x06,0x05,0x04,0x06,0x05,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x00,0x80,0x00,0x00,0x09,0x01,0x08,0x00,0x08,0x63,0x00,0x04,0x04,0x02,0x61,0x00,0x02, 0x02,0x41,0x4d,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x3f,0x07,0x4e,0x59,0x40,0x11,0x00,0x00,0x00,0x2f,0x00,0x2e,0x12,0x12,0x25,0x22,0x12,0x27,0x14,0x21,0x0a,0x09,0x1e,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x14, 0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x23,0x22,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xd1,0x46,0x16,0x1b,0x37,0x32,0x18,0x49,0x56,0x78,0x64,0x5f,0x75,0x03,0x5a,0x03,0x42,0x38,0x3b,0x47,0x47,0x3b,0x38,0x42,0x03,0x5a,0x03,0x75,0x5f,0x03,0x02,0x09,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x41,0x10,0x6a, 0x52,0x96,0x62,0x70,0x66,0x58,0x35,0x39,0x43,0x3e,0x97,0x3e,0x44,0x3a,0x34,0x58,0x66,0x19,0x03,0x14,0x24,0x1a,0x22,0x31,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x0b,0x03,0x11,0x02,0x26,0x00,0xd7,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x60,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x0b,0x03,0x09,0x02,0x26,0x00,0xd7,0x00,0x00, 0x00,0x07,0x06,0x69,0x02,0x60,0x00,0x00,0x00,0x02,0x00,0x57,0xff,0xf6,0x01,0xfc,0x02,0xda,0x00,0x14,0x00,0x22,0x00,0x6b,0xb6,0x11,0x0a,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x03,0x06,0x02,0x00, 0x00,0x3f,0x00,0x4e,0x1b,0x40,0x21,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x39,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x17,0x16,0x15,0x01,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x10,0x0f,0x0e,0x0d,0x08,0x06,0x00,0x14,0x01,0x14,0x08, 0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x27,0x35,0x33,0x11,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x0c,0x52,0x63,0x62,0x53,0x3e,0x51,0x08,0x01,0x02,0x5a,0x5a,0x01,0x07,0x50,0x20,0x38,0x40,0x40,0x38,0x39,0x40,0x40,0x0a,0x6e, 0x5e,0xa1,0x5f,0x6e,0x3e,0x35,0x7d,0xa0,0xfd,0x26,0x69,0x36,0x3d,0x4e,0x46,0x3e,0x96,0x3e,0x46,0x3b,0x44,0xa0,0x43,0x3c,0x00,0x02,0x00,0x46,0xff,0xf6,0x02,0x12,0x02,0xdf,0x00,0x20,0x00,0x2c,0x00,0x4c,0x40,0x49,0x19,0x18,0x16,0x13,0x12,0x11,0x10,0x07,0x01,0x03,0x01,0x4c,0x17,0x01,0x03,0x4a,0x00,0x02,0x01,0x05,0x01,0x02, 0x05,0x80,0x00,0x01,0x00,0x05,0x04,0x01,0x05,0x6a,0x00,0x03,0x03,0x38,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x22,0x21,0x01,0x00,0x28,0x26,0x21,0x2c,0x22,0x2c,0x15,0x14,0x0c,0x0b,0x09,0x07,0x00,0x20,0x01,0x20,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17, 0x33,0x26,0x26,0x27,0x27,0x07,0x35,0x37,0x27,0x33,0x17,0x37,0x15,0x07,0x17,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2b,0x44,0x68,0x39,0x35,0x5f,0x3f,0x2c,0x3b,0x0b,0x0e,0x04,0x20,0x1c,0x41,0xa3,0x78,0x48,0x68,0x2c,0x94,0x6a,0x4e,0x2c,0x35,0x3a,0x67,0x46,0x40,0x4d, 0x4d,0x40,0x3e,0x4d,0x4d,0x0a,0x38,0x66,0x43,0x43,0x63,0x37,0x26,0x12,0x0a,0x35,0x25,0x5b,0x4c,0x50,0x38,0x63,0x40,0x45,0x50,0x31,0x71,0x40,0x8e,0x40,0x46,0x69,0x3a,0x50,0x50,0x41,0x41,0x50,0x50,0x41,0x41,0x50,0x00,0x00,0x00,0x03,0x00,0x3f,0xff,0xf6,0x02,0x5c,0x02,0xda,0x00,0x14,0x00,0x18,0x00,0x26,0x00,0x81,0xb6,0x11, 0x0a,0x02,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x24,0x09,0x01,0x05,0x05,0x02,0x5f,0x04,0x01,0x02,0x02,0x38,0x4d,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x0a,0x01,0x06,0x06,0x00,0x61,0x03,0x08,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x28,0x09,0x01,0x05,0x05,0x02,0x5f,0x04,0x01,0x02,0x02,0x38,0x4d, 0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x39,0x4d,0x0a,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1f,0x1a,0x19,0x15,0x15,0x01,0x00,0x21,0x1f,0x19,0x26,0x1a,0x26,0x15,0x18,0x15,0x18,0x17,0x16,0x10,0x0f,0x0e,0x0d,0x08,0x06,0x00,0x14,0x01,0x14,0x0b,0x09,0x16,0x2b,0x17, 0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x27,0x35,0x33,0x11,0x23,0x35,0x23,0x06,0x06,0x13,0x37,0x33,0x07,0x01,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xe4,0x4c,0x59,0x59,0x4c,0x39,0x47,0x06,0x03,0x02,0x5a,0x5a,0x01,0x06,0x47,0xdc,0x0f,0x54,0x18,0xfe,0xbe,0x32,0x37,0x37,0x32,0x31, 0x38,0x38,0x0a,0x6c,0x5b,0xab,0x5c,0x6c,0x3e,0x35,0x7d,0xa0,0xfd,0x26,0x69,0x35,0x3e,0x02,0x30,0xb4,0xb4,0xfe,0x1e,0x43,0x3c,0xa0,0x3c,0x43,0x43,0x3c,0xa0,0x3c,0x43,0x00,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x02,0x58,0x02,0xda,0x00,0x1c,0x00,0x2a,0x00,0x83,0xb6,0x19,0x0a,0x02,0x08,0x09,0x01,0x4c,0x4b,0xb0,0x18,0x50, 0x58,0x40,0x25,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x69,0x00,0x04,0x04,0x38,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x07,0x0a,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x29,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x69,0x00,0x04,0x04, 0x38,0x4d,0x00,0x07,0x07,0x39,0x4d,0x0b,0x01,0x08,0x08,0x00,0x61,0x0a,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1f,0x1e,0x1d,0x01,0x00,0x25,0x23,0x1d,0x2a,0x1e,0x2a,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x08,0x06,0x00,0x1c,0x01,0x1c,0x0c,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32, 0x16,0x17,0x33,0x27,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x0c,0x52,0x60,0x5f,0x53,0x3e,0x4e,0x07,0x03,0x02,0xa6,0xa6,0x5a,0x5e,0x5e,0x5a,0x01,0x07,0x4e,0x20,0x38,0x3e,0x3e,0x38,0x39,0x3d,0x3d,0x0a,0x6e, 0x5e,0x65,0x5f,0x6e,0x3e,0x35,0x7d,0x3c,0x4b,0x55,0x55,0x4b,0xfd,0xc6,0x69,0x36,0x3d,0x4e,0x46,0x3e,0x5a,0x3e,0x46,0x44,0x40,0x5a,0x40,0x44,0x00,0x02,0x00,0x54,0xff,0xf6,0x02,0x04,0x02,0x30,0x00,0x17,0x00,0x20,0x00,0x3e,0x40,0x3b,0x00,0x04,0x02,0x03,0x02,0x04,0x03,0x80,0x00,0x05,0x00,0x02,0x04,0x05,0x02,0x67,0x00,0x06, 0x06,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x1e,0x1c,0x19,0x18,0x15,0x14,0x12,0x10,0x0d,0x0c,0x08,0x06,0x00,0x17,0x01,0x17,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x15,0x21,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33, 0x06,0x06,0x03,0x21,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x2c,0x61,0x77,0x77,0x61,0x41,0x61,0x36,0xfe,0xa8,0x46,0x3a,0x32,0x41,0x07,0x5a,0x09,0x74,0xd7,0x01,0x00,0x43,0x3d,0x3d,0x43,0x0a,0x75,0x67,0x82,0x67,0x75,0x34,0x5e,0x40,0x62,0x34,0x3d,0x47,0x27,0x21,0x45,0x51,0x01,0x4c,0x1c,0x41,0x47,0x47,0x41,0x00,0x00,0x00, 0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00, 0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x71,0x03,0x84,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0xb8,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0x2b,0x02,0x04, 0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x27,0x06,0x78,0x02,0x58,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x21,0x03,0x84,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0xb9,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x26,0x03,0xa2,0x02,0x26,0x00,0xe1,0x00,0x00, 0x00,0x07,0x06,0xba,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0xa0,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0xbb,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x09,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04, 0x03,0x09,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0x2b,0x02,0x04,0x02,0x30,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x11,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00, 0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x39,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x02,0xe9,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x35,0x02,0x00,0x02,0x30,0x00,0x25,0x00,0x2e,0x00,0x84, 0x4b,0xb0,0x15,0x50,0x58,0x40,0x30,0x00,0x05,0x03,0x04,0x03,0x05,0x04,0x80,0x00,0x07,0x00,0x03,0x05,0x07,0x03,0x67,0x00,0x08,0x08,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x06,0x06,0x00,0x60,0x09,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x2d,0x00,0x05,0x03,0x04,0x03,0x05, 0x04,0x80,0x00,0x07,0x00,0x03,0x05,0x07,0x03,0x67,0x00,0x06,0x09,0x01,0x00,0x06,0x00,0x64,0x00,0x08,0x08,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x19,0x01,0x00,0x2c,0x2a,0x27,0x26,0x24,0x22,0x19,0x18,0x17,0x15,0x12,0x11,0x0e,0x0c,0x07,0x05,0x00,0x25,0x01,0x25, 0x0a,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x37,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x21,0x15,0x14,0x16,0x33,0x32,0x37,0x33,0x06,0x06,0x07,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x01,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x01,0x75,0x37,0x43,0x3b,0x0a,0x61,0x73,0x73,0x61,0x62,0x72,0xfe, 0xb0,0x3f,0x3d,0x69,0x0f,0x5a,0x05,0x32,0x27,0x10,0x22,0x1e,0x1e,0x19,0x3c,0xfe,0xed,0xf8,0x3e,0x3e,0x3d,0x3f,0xcb,0x35,0x28,0x2f,0x35,0x73,0x5f,0x96,0x5f,0x73,0x73,0x5f,0x61,0x35,0x41,0x45,0x4a,0x2b,0x40,0x13,0x0d,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x02,0x0c,0x1d,0x41,0x46,0x46,0x41,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04, 0x03,0x0c,0x02,0x26,0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0x30,0x00,0x15,0x00,0x1e,0x00,0x43,0x40,0x40,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x67,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x08,0x01,0x05,0x05, 0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x17,0x16,0x01,0x00,0x1b,0x1a,0x16,0x1e,0x17,0x1e,0x10,0x0e,0x0c,0x0b,0x0a,0x08,0x05,0x04,0x00,0x15,0x01,0x15,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x21,0x35,0x34,0x26,0x23,0x22,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x15, 0x14,0x16,0x01,0x2c,0x61,0x71,0x01,0x4c,0x3c,0x3e,0x67,0x0f,0x5a,0x09,0x70,0x57,0x62,0x70,0x70,0x62,0x3e,0x3c,0xf4,0x3d,0x0a,0x73,0x5f,0x61,0x35,0x41,0x45,0x4a,0x45,0x51,0x73,0x5f,0x96,0x5f,0x73,0x4b,0x46,0x41,0x1d,0x1d,0x41,0x46,0x00,0x00,0x00,0x01,0x00,0x37,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x12,0x00,0x2d,0x40,0x2a, 0x04,0x01,0x01,0x05,0x01,0x00,0x06,0x01,0x00,0x67,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x00,0x00,0x00,0x12,0x00,0x12,0x11,0x12,0x21,0x23,0x11,0x11,0x08,0x09,0x1c,0x2b,0x33,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0xd7,0xa0, 0xa0,0x52,0x48,0xa1,0xa1,0x40,0xe1,0xe1,0x01,0x89,0x52,0x73,0x41,0x4b,0x52,0x3a,0x73,0x52,0xfe,0x77,0x00,0x02,0x00,0x58,0xff,0x4c,0x01,0xfb,0x02,0x30,0x00,0x1c,0x00,0x2a,0x00,0x6f,0xb6,0x15,0x07,0x02,0x05,0x06,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x20,0x08,0x01,0x05,0x00,0x01,0x00,0x05,0x01,0x69,0x00,0x06,0x06,0x02, 0x61,0x03,0x01,0x02,0x02,0x41,0x4d,0x00,0x00,0x00,0x04,0x5f,0x07,0x01,0x04,0x04,0x3d,0x04,0x4e,0x1b,0x40,0x24,0x08,0x01,0x05,0x00,0x01,0x00,0x05,0x01,0x69,0x00,0x03,0x03,0x3b,0x4d,0x00,0x06,0x06,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x00,0x00,0x00,0x04,0x5f,0x07,0x01,0x04,0x04,0x3d,0x04,0x4e,0x59,0x40,0x15,0x1e,0x1d,0x00, 0x00,0x25,0x23,0x1d,0x2a,0x1e,0x2a,0x00,0x1c,0x00,0x1b,0x14,0x25,0x27,0x21,0x09,0x09,0x1a,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x35,0x37,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35,0x33,0x11,0x14,0x06,0x23,0x03,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xa1,0x9b, 0x2f,0x36,0x02,0x03,0x08,0x4e,0x3b,0x55,0x62,0x62,0x55,0x3b,0x4e,0x08,0x02,0x59,0x67,0x59,0x11,0x38,0x40,0x40,0x38,0x39,0x3f,0x3f,0xb4,0x52,0x35,0x2d,0x32,0x5a,0x31,0x35,0x6c,0x5e,0x74,0x5e,0x6e,0x38,0x31,0x5f,0xfd,0xda,0x53,0x61,0x01,0x25,0x46,0x3e,0x69,0x3e,0x46,0x42,0x38,0x7d,0x38,0x42,0x00,0x00,0xff,0xff,0x00,0x58, 0xff,0x4c,0x01,0xfb,0x03,0x11,0x02,0x26,0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x5f,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x4c,0x01,0xfb,0x03,0x11,0x02,0x26,0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x55,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x4c,0x01,0xfb,0x03,0x11,0x02,0x26,0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x6f, 0x02,0x55,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x4c,0x01,0xfb,0x03,0x11,0x02,0x26,0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x55,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x4c,0x01,0xfb,0x03,0x70,0x02,0x26,0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x76,0x02,0x55,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0x4c,0x01,0xfb,0x03,0x09,0x02,0x26, 0x00,0xf5,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x55,0x00,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x14,0x00,0x2d,0x40,0x2a,0x03,0x01,0x02,0x03,0x01,0x4c,0x00,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x05,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x14,0x00,0x14,0x23, 0x13,0x24,0x11,0x06,0x09,0x1a,0x2b,0x33,0x11,0x33,0x11,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x5c,0x5a,0x01,0x07,0x4c,0x3f,0x53,0x62,0x5a,0x3f,0x36,0x38,0x41,0x02,0xda,0xfe,0xe3,0x37,0x3c,0x66,0x58,0xfe,0x8e,0x01,0x63,0x3e,0x43,0x46,0x40,0xfe,0xa2,0x00,0xff,0xff,0x00,0x00, 0x00,0x00,0x01,0xfe,0x02,0xda,0x02,0x06,0x02,0x37,0x00,0x00,0xff,0xff,0xff,0xd4,0x00,0x00,0x01,0xfe,0x03,0xc5,0x02,0x26,0x00,0xfc,0x00,0x00,0x01,0x07,0x06,0x6e,0x01,0xb5,0x00,0xb4,0x00,0x08,0xb1,0x01,0x01,0xb0,0xb4,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x09,0x02,0x26,0x01,0x00,0x00,0x00, 0x00,0x07,0x06,0x69,0x02,0x67,0x00,0x00,0x00,0x01,0x00,0x55,0x00,0x00,0x02,0x2b,0x02,0x26,0x00,0x09,0x00,0x27,0x40,0x24,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x03,0x01,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x09,0x1a,0x2b,0x33,0x35,0x33, 0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x55,0xc3,0xaf,0x01,0x09,0xb9,0x52,0x01,0x82,0x52,0xfe,0x2c,0x52,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x11,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x71,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x11,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x70, 0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x11,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x11,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x09,0x02,0x26, 0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x09,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0x2b,0x02,0x2b,0x03,0x09,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x27,0x06,0x69,0x02,0x67,0x00,0x00,0x00,0x07,0x06,0x78, 0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x11,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x39,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x02,0xe9,0x02,0x26, 0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x67,0x00,0x00,0x00,0x02,0x00,0x55,0xff,0x35,0x02,0x2b,0x03,0x09,0x00,0x0b,0x00,0x25,0x00,0xb6,0x4b,0xb0,0x11,0x50,0x58,0x40,0x2d,0x0a,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x40,0x4d,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x3b,0x4d,0x05,0x01,0x02,0x02,0x06,0x5f,0x0b,0x09, 0x02,0x06,0x06,0x39,0x4d,0x00,0x07,0x07,0x08,0x5f,0x00,0x08,0x08,0x3d,0x08,0x4e,0x1b,0x4b,0xb0,0x15,0x50,0x58,0x40,0x2b,0x00,0x01,0x0a,0x01,0x00,0x04,0x01,0x00,0x69,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x3b,0x4d,0x05,0x01,0x02,0x02,0x06,0x5f,0x0b,0x09,0x02,0x06,0x06,0x39,0x4d,0x00,0x07,0x07,0x08,0x5f,0x00,0x08,0x08, 0x3d,0x08,0x4e,0x1b,0x40,0x28,0x00,0x01,0x0a,0x01,0x00,0x04,0x01,0x00,0x69,0x00,0x07,0x00,0x08,0x07,0x08,0x63,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x3b,0x4d,0x05,0x01,0x02,0x02,0x06,0x5f,0x0b,0x09,0x02,0x06,0x06,0x39,0x06,0x4e,0x59,0x59,0x40,0x1f,0x0c,0x0c,0x01,0x00,0x0c,0x25,0x0c,0x25,0x20,0x1e,0x1d,0x1b,0x16,0x15, 0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x35,0x33,0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x01,0x3b,0x21,0x26,0x26,0x21,0x21,0x26, 0x26,0xfe,0xf9,0xc3,0xaf,0x01,0x09,0xb9,0xcf,0x21,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x20,0x27,0x02,0x89,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfd,0x77,0x52,0x01,0x82,0x52,0xfe,0x2c,0x52,0x1b,0x2d,0x15,0x16,0x1c,0x3c,0x35,0x28,0x1a,0x36,0x1e,0x00,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x0c,0x02,0x26, 0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0x4c,0x01,0xc3,0x03,0x09,0x02,0x26,0x01,0x0e,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0xa8,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0x4c,0x01,0xb3,0x02,0x26,0x00,0x0d,0x00,0x25,0x40,0x22,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x00,0x00, 0x00,0x03,0x5f,0x04,0x01,0x03,0x03,0x3d,0x03,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0c,0x11,0x13,0x21,0x05,0x09,0x19,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x11,0x21,0x35,0x21,0x11,0x14,0x06,0x23,0x5a,0x7c,0x3e,0x45,0xfe,0xfc,0x01,0x5e,0x78,0x65,0xb4,0x52,0x44,0x3d,0x01,0xb5,0x52,0xfd,0xf9,0x61,0x72,0x00,0x00,0xff,0xff,0x00,0x55, 0xff,0x4c,0x02,0x31,0x03,0x11,0x02,0x26,0x01,0x0e,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0xa8,0x00,0x00,0x00,0x01,0x00,0x61,0x00,0x00,0x02,0x2f,0x02,0xda,0x00,0x0c,0x00,0x31,0x40,0x2e,0x07,0x01,0x04,0x01,0x01,0x4c,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x00,0x00,0x00,0x38,0x4d,0x00,0x02,0x02,0x3b,0x4d,0x06,0x05,0x02,0x03, 0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x0c,0x00,0x0c,0x11,0x12,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x37,0x33,0x03,0x13,0x23,0x27,0x23,0x15,0x61,0x5a,0x69,0x9a,0x67,0xb1,0xbb,0x69,0xa0,0x6b,0x02,0xda,0xfe,0x69,0xe3,0xfe,0xfa,0xfe,0xe0,0xf5,0xf5,0x00,0x00,0x00,0xff,0xff,0x00,0x61,0xff,0x10,0x02,0x2f, 0x02,0xda,0x02,0x26,0x01,0x10,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x67,0x00,0x00,0x02,0x35,0x02,0x26,0x02,0x06,0x02,0x19,0x00,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0d,0x00,0x28,0x40,0x25,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x03,0x03,0x00,0x5f,0x04, 0x01,0x00,0x00,0x39,0x00,0x4e,0x01,0x00,0x0c,0x0a,0x07,0x06,0x05,0x04,0x00,0x0d,0x01,0x0d,0x05,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x14,0x16,0x33,0x33,0x15,0x01,0x7c,0x49,0x57,0xbe,0x01,0x18,0x26,0x20,0xaa,0x55,0x46,0x01,0xed,0x52,0xfd,0xc1,0x22,0x27,0x52,0xff,0xff,0x00,0x1e,0x00,0x00,0x02,0x26, 0x03,0xb6,0x02,0x26,0x01,0x13,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x26,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xe4,0x00,0x15,0x00,0x2c,0x40,0x29,0x11,0x0b,0x0a,0x08,0x05,0x04,0x03,0x02,0x08,0x01,0x00,0x01,0x4c,0x09,0x01,0x00,0x4a,0x00,0x00,0x00,0x38,0x4d,0x03,0x02,0x02,0x01,0x01,0x39,0x01,0x4e,0x00,0x00, 0x00,0x15,0x00,0x15,0x15,0x16,0x04,0x09,0x18,0x2b,0x33,0x13,0x27,0x07,0x35,0x37,0x27,0x33,0x17,0x37,0x15,0x07,0x13,0x23,0x03,0x26,0x26,0x27,0x14,0x06,0x07,0x03,0x32,0xcc,0x04,0xa0,0x86,0x2c,0x60,0x1b,0xa7,0x8d,0xdd,0x60,0x83,0x0d,0x0c,0x05,0x08,0x0c,0x7e,0x02,0x1d,0x09,0x50,0x50,0x43,0x71,0x49,0x53,0x50,0x47,0xfd,0xb3, 0x01,0x65,0x23,0x36,0x0f,0x0f,0x36,0x23,0xfe,0x9b,0x00,0x00,0xff,0xff,0x00,0x1e,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x26,0x01,0x13,0x00,0x00,0x00,0x07,0x06,0x6d,0x02,0x3a,0x00,0x00,0xff,0xff,0x00,0x1e,0xff,0x10,0x02,0x26,0x02,0xda,0x02,0x26,0x01,0x13,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x6c,0x00,0x00,0xff,0xff,0x00,0x0a, 0x00,0x00,0x02,0x75,0x02,0xda,0x00,0x26,0x01,0x13,0xec,0x00,0x01,0x07,0x03,0x29,0x00,0xf7,0x01,0x13,0x00,0x09,0xb1,0x01,0x01,0xb8,0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x15,0x00,0x2c,0x40,0x29,0x15,0x0a,0x09,0x08,0x07,0x02,0x01,0x00,0x08,0x02,0x00,0x01,0x4c,0x00,0x00,0x00, 0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x03,0x39,0x03,0x4e,0x21,0x27,0x11,0x13,0x04,0x09,0x1a,0x2b,0x37,0x35,0x37,0x11,0x23,0x35,0x21,0x11,0x37,0x15,0x07,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x35,0x64,0x78,0xbe,0x01,0x18,0xa0,0xa0,0x26,0x20,0xaa,0xaa,0x49,0x57,0xe6,0x50,0x51, 0x01,0x01,0x52,0xfe,0xea,0x6c,0x50,0x6c,0xd9,0x22,0x27,0x52,0x55,0x46,0x9c,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x30,0x00,0x24,0x00,0x56,0xb6,0x0a,0x03,0x02,0x03,0x04,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x16,0x06,0x01,0x04,0x04,0x00,0x61,0x02,0x01,0x02,0x00,0x00,0x3b,0x4d,0x08,0x07,0x05,0x03,0x03,0x03, 0x39,0x03,0x4e,0x1b,0x40,0x1a,0x00,0x00,0x00,0x3b,0x4d,0x06,0x01,0x04,0x04,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x08,0x07,0x05,0x03,0x03,0x03,0x39,0x03,0x4e,0x59,0x40,0x10,0x00,0x00,0x00,0x24,0x00,0x24,0x23,0x13,0x23,0x13,0x25,0x24,0x11,0x09,0x09,0x1d,0x2b,0x33,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x33, 0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x3c,0x4e,0x02,0x05,0x31,0x26,0x24,0x32,0x0b,0x01,0x07,0x31,0x26,0x35,0x3f,0x54,0x20,0x1c,0x1b,0x20,0x4a,0x20,0x1b,0x1c,0x20,0x02,0x26,0x49,0x25,0x2e,0x2a,0x24,0x24,0x2a,0x4f,0x3f,0xfe,0x5e,0x01, 0xa3,0x21,0x27,0x26,0x21,0xfe,0x5c,0x01,0xa3,0x21,0x27,0x26,0x21,0xfe,0x5c,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x01,0xfe,0x02,0x30,0x00,0x14,0x00,0x4c,0xb5,0x03,0x01,0x02,0x03,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x13,0x00,0x03,0x03,0x00,0x61,0x01,0x01,0x00,0x00,0x3b,0x4d,0x05,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x1b, 0x40,0x17,0x00,0x00,0x00,0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x05,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x59,0x40,0x0d,0x00,0x00,0x00,0x14,0x00,0x14,0x23,0x13,0x24,0x11,0x06,0x09,0x1a,0x2b,0x33,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x5c, 0x5a,0x01,0x07,0x4c,0x3f,0x53,0x62,0x5a,0x3f,0x36,0x38,0x41,0x02,0x26,0x69,0x37,0x3c,0x66,0x58,0xfe,0x8e,0x01,0x62,0x3f,0x43,0x46,0x40,0xfe,0xa2,0x00,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x1b,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x67,0x00,0x00,0xff,0xff,0xff,0xf6,0x00,0x00,0x01,0xfe, 0x03,0x16,0x02,0x26,0x01,0x1b,0x00,0x00,0x01,0x07,0x06,0x7a,0x01,0x90,0x03,0x75,0x00,0x09,0xb1,0x01,0x01,0xb8,0x03,0x75,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x1b,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x5d,0x00,0x00,0xff,0xff,0x00,0x5c,0xff,0x10,0x01,0xfe,0x02,0x30,0x02,0x26, 0x01,0x1b,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5e,0xff,0x4c,0x01,0xfc,0x02,0x30,0x00,0x1c,0x00,0x5f,0xb5,0x11,0x01,0x02,0x01,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1c,0x00,0x01,0x01,0x03,0x61,0x04,0x01,0x03,0x03,0x3b,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x00,0x00,0x05,0x61,0x06,0x01,0x05, 0x05,0x3d,0x05,0x4e,0x1b,0x40,0x20,0x00,0x03,0x03,0x3b,0x4d,0x00,0x01,0x01,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x00,0x00,0x05,0x61,0x06,0x01,0x05,0x05,0x3d,0x05,0x4e,0x59,0x40,0x0e,0x00,0x00,0x00,0x1c,0x00,0x1b,0x24,0x11,0x13,0x25,0x21,0x07,0x09,0x1b,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x11, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0xf0,0x3f,0x35,0x3e,0x3d,0x36,0x38,0x3f,0x5a,0x5a,0x01,0x06,0x4b,0x3f,0x53,0x60,0x70,0x5d,0xb4,0x52,0x3d,0x34,0x01,0x59,0x3b,0x41,0x46,0x40,0xfe,0xa2,0x02,0x26,0x69,0x37,0x3c,0x66,0x58,0xfe,0x9d,0x58,0x6b,0x00, 0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfe,0x03,0x0c,0x02,0x26,0x01,0x1b,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x5d,0x00,0x00,0x00,0x02,0x00,0x54,0xff,0xf8,0x02,0x04,0x02,0x2e,0x00,0x0d,0x00,0x1b,0x00,0x2d,0x40,0x2a,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x42,0x00, 0x4e,0x0f,0x0e,0x01,0x00,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x63,0x75,0x74,0x64,0x64,0x74,0x75,0x63,0x3b,0x43,0x43,0x3b,0x3a, 0x44,0x44,0x08,0x74,0x68,0x7e,0x69,0x73,0x73,0x69,0x7e,0x68,0x74,0x50,0x42,0x40,0x92,0x40,0x42,0x42,0x40,0x92,0x40,0x42,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00, 0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x71, 0x03,0x84,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0xb8,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0x2b,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x27,0x06,0x78,0x02,0x58,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x21,0x03,0x84,0x02,0x26,0x01,0x22,0x00,0x00, 0x00,0x07,0x06,0xb9,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x26,0x03,0xa2,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0xba,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0xa0,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0xbb,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04, 0x03,0x09,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0x2b,0x02,0x04,0x02,0x2e,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00, 0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x39,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x54,0xff,0xf8,0x02,0x1c,0x02,0x80,0x00,0x17,0x00,0x25,0x00,0x71,0xb5,0x12,0x01,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x21,0x00,0x03,0x01,0x03,0x85,0x00,0x02,0x02,0x3b,0x4d, 0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x42,0x00,0x4e,0x1b,0x40,0x24,0x00,0x03,0x01,0x03,0x85,0x00,0x02,0x01,0x05,0x01,0x02,0x05,0x80,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x42,0x00,0x4e,0x59,0x40, 0x17,0x19,0x18,0x01,0x00,0x20,0x1e,0x18,0x25,0x19,0x25,0x0e,0x0d,0x0b,0x09,0x08,0x06,0x00,0x17,0x01,0x17,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01, 0x2c,0x63,0x75,0x74,0x64,0x45,0x32,0x0b,0x23,0x4b,0x20,0x1c,0x24,0x75,0x63,0x3b,0x43,0x43,0x3b,0x3a,0x44,0x44,0x08,0x74,0x68,0x7e,0x69,0x73,0x1c,0x23,0x4b,0x50,0x1f,0x2e,0x0a,0x36,0x51,0x7e,0x68,0x74,0x50,0x42,0x40,0x92,0x40,0x42,0x42,0x40,0x92,0x40,0x42,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x1c,0x03,0x11,0x02,0x26, 0x01,0x30,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0x2b,0x02,0x1c,0x02,0x80,0x02,0x26,0x01,0x30,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x1c,0x03,0x11,0x02,0x26,0x01,0x30,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x44,0x00,0x00,0xff,0xff,0x00,0x54, 0xff,0xf8,0x02,0x1c,0x03,0x39,0x02,0x26,0x01,0x30,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x1c,0x03,0x0c,0x02,0x26,0x01,0x30,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x10,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x6c, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x02,0xe9,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x35,0x02,0x00,0x02,0x30,0x00,0x1e,0x00,0x2c,0x00,0x64,0x4b,0xb0,0x15,0x50,0x58,0x40,0x21,0x00,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x07,0x01,0x04, 0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x03,0x03,0x00,0x5f,0x06,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x1e,0x00,0x03,0x06,0x01,0x00,0x03,0x00,0x63,0x00,0x05,0x05,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x07,0x01,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x17,0x20,0x1f,0x01,0x00,0x27,0x25,0x1f,0x2c, 0x20,0x2c,0x1d,0x1b,0x0f,0x0d,0x08,0x06,0x00,0x1e,0x01,0x1e,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x37,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x07,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x03,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x74,0x37, 0x43,0x19,0x22,0x09,0x62,0x72,0x72,0x62,0x62,0x72,0x2e,0x2b,0x18,0x22,0x1e,0x1e,0x19,0x3c,0x96,0x3b,0x3f,0x3f,0x3b,0x3a,0x40,0x40,0xcb,0x35,0x28,0x16,0x2f,0x1f,0x70,0x62,0x96,0x62,0x70,0x6f,0x62,0x97,0x3e,0x5b,0x1a,0x14,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x01,0x11,0x42,0x40,0x96,0x40,0x42,0x42,0x40,0x96,0x40,0x42,0x00,0x00, 0x00,0x03,0x00,0x23,0xff,0xe2,0x02,0x35,0x02,0x4e,0x00,0x15,0x00,0x1e,0x00,0x27,0x00,0x4a,0x40,0x47,0x09,0x01,0x04,0x00,0x26,0x25,0x19,0x0c,0x01,0x05,0x05,0x04,0x14,0x01,0x02,0x05,0x03,0x4c,0x00,0x01,0x00,0x01,0x85,0x06,0x01,0x03,0x02,0x03,0x86,0x00,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x41,0x4d,0x07,0x01,0x05,0x05,0x02, 0x61,0x00,0x02,0x02,0x3f,0x02,0x4e,0x20,0x1f,0x00,0x00,0x1f,0x27,0x20,0x27,0x1c,0x1a,0x00,0x15,0x00,0x15,0x26,0x12,0x26,0x08,0x09,0x19,0x2b,0x17,0x37,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x17,0x37,0x33,0x07,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x27,0x07,0x37,0x14,0x17,0x13,0x26,0x23,0x22,0x06,0x15,0x13,0x32,0x36,0x35,0x35, 0x34,0x27,0x03,0x16,0x23,0x51,0x1c,0x72,0x62,0x4c,0x34,0x2e,0x5b,0x54,0x1f,0x72,0x62,0x50,0x36,0x29,0x30,0x03,0xcc,0x20,0x30,0x3c,0x43,0x7f,0x3c,0x43,0x04,0xd0,0x20,0x1e,0x72,0x31,0x43,0x96,0x62,0x70,0x22,0x40,0x76,0x32,0x47,0x97,0x62,0x70,0x26,0x3a,0xe6,0x11,0x0e,0x01,0x20,0x17,0x44,0x3e,0xfe,0xe8,0x45,0x3d,0x96,0x15, 0x13,0xfe,0xdb,0x1b,0xff,0xff,0x00,0x23,0xff,0xe2,0x02,0x35,0x03,0x11,0x02,0x26,0x01,0x39,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x0c,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x23,0xff,0xf6,0x02,0x35,0x02,0x30,0x00,0x28, 0x00,0x36,0x00,0x3f,0x00,0x59,0x40,0x56,0x0b,0x01,0x09,0x08,0x24,0x01,0x04,0x05,0x02,0x4c,0x00,0x05,0x03,0x04,0x03,0x05,0x04,0x80,0x00,0x09,0x00,0x03,0x05,0x09,0x03,0x67,0x0a,0x01,0x08,0x08,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x0c,0x07,0x02,0x04,0x04,0x00,0x61,0x06,0x0b,0x02,0x00,0x00,0x3f,0x00,0x4e,0x2a,0x29,0x01, 0x00,0x3d,0x3b,0x38,0x37,0x31,0x2f,0x29,0x36,0x2a,0x36,0x21,0x1f,0x1d,0x1c,0x1a,0x18,0x15,0x14,0x11,0x0f,0x08,0x06,0x00,0x28,0x01,0x28,0x0d,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x17,0x33,0x3e,0x02,0x33,0x32,0x16,0x15,0x15,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x23,0x22, 0x26,0x26,0x27,0x23,0x0e,0x02,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x13,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0xb4,0x43,0x4e,0x4e,0x43,0x28,0x33,0x1a,0x01,0x04,0x02,0x19,0x33,0x28,0x43,0x4e,0xde,0x24,0x1f,0x1a,0x25,0x04,0x55,0x0a,0x4c,0x38,0x28,0x33,0x19,0x02,0x04,0x01,0x1a,0x33,0x1e, 0x1f,0x24,0x24,0x1f,0x20,0x26,0x26,0xb9,0x89,0x26,0x20,0x1f,0x24,0x0a,0x57,0x49,0xfa,0x4a,0x56,0x1a,0x25,0x11,0x11,0x25,0x1a,0x56,0x4a,0x96,0x64,0x26,0x2d,0x20,0x1a,0x3e,0x49,0x1a,0x25,0x11,0x11,0x25,0x1a,0x4d,0x2d,0x26,0xfa,0x26,0x2d,0x2d,0x26,0xfa,0x26,0x2d,0x01,0x00,0x4d,0x26,0x2d,0x2d,0x26,0x00,0x00,0x02,0x00,0x5c, 0xff,0x4c,0x02,0x01,0x02,0x30,0x00,0x14,0x00,0x22,0x00,0x68,0xb6,0x11,0x03,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x05,0x05,0x00,0x61,0x01,0x01,0x00,0x00,0x3b,0x4d,0x07,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f,0x4d,0x06,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x21,0x00,0x00,0x00,0x3b,0x4d, 0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f,0x4d,0x06,0x01,0x03,0x03,0x3d,0x03,0x4e,0x59,0x40,0x14,0x16,0x15,0x00,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x00,0x14,0x00,0x14,0x25,0x24,0x11,0x08,0x09,0x19,0x2b,0x17,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15, 0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x15,0x37,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x5c,0x5a,0x01,0x07,0x50,0x3e,0x53,0x62,0x62,0x53,0x3e,0x50,0x07,0x03,0x02,0x78,0x39,0x40,0x40,0x39,0x37,0x41,0x41,0xb4,0x02,0xda,0x69,0x36,0x3d,0x6d,0x5f,0xa1,0x5f,0x6e,0x3e,0x35,0x7d,0xa0,0xf8,0x3c,0x43, 0xa0,0x44,0x3b,0x46,0x3e,0x96,0x3e,0x46,0x00,0x02,0x00,0x57,0xff,0x56,0x01,0xfc,0x02,0xda,0x00,0x14,0x00,0x22,0x00,0x6c,0xb6,0x12,0x04,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x31,0x50,0x58,0x40,0x21,0x00,0x00,0x00,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f, 0x4d,0x06,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x21,0x06,0x01,0x03,0x02,0x03,0x86,0x00,0x00,0x00,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f,0x02,0x4e,0x59,0x40,0x14,0x16,0x15,0x00,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x00,0x14,0x00,0x14,0x25,0x25,0x11, 0x08,0x09,0x19,0x2b,0x17,0x11,0x33,0x15,0x07,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x11,0x37,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x57,0x5a,0x02,0x01,0x08,0x51,0x3e,0x53,0x62,0x62,0x53,0x3e,0x50,0x07,0x01,0x78,0x39,0x40,0x40,0x39,0x37,0x41,0x41,0xaa,0x03, 0x84,0xa0,0x7d,0x35,0x3e,0x6e,0x5f,0xa1,0x5e,0x6e,0x3d,0x36,0xfe,0xed,0xee,0x3c,0x43,0xa0,0x44,0x3b,0x46,0x3e,0x96,0x3e,0x46,0x00,0x00,0x00,0x00,0x02,0x00,0x57,0xff,0x4c,0x01,0xfc,0x02,0x30,0x00,0x14,0x00,0x22,0x00,0x68,0xb6,0x10,0x02,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x05,0x05,0x01,0x61, 0x02,0x01,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x3f,0x4d,0x06,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x21,0x00,0x02,0x02,0x3b,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x3f,0x4d,0x06,0x01,0x03,0x03,0x3d,0x03,0x4e,0x59,0x40,0x14,0x16, 0x15,0x00,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x00,0x14,0x00,0x14,0x14,0x25,0x25,0x08,0x09,0x19,0x2b,0x05,0x35,0x37,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35,0x33,0x11,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0xa2,0x02,0x03,0x07,0x50,0x3e,0x53,0x62, 0x63,0x52,0x3e,0x50,0x07,0x01,0x5a,0xd2,0x38,0x40,0x40,0x38,0x39,0x40,0x40,0xb4,0xa0,0x7d,0x35,0x3e,0x6e,0x5f,0xa1,0x5f,0x6d,0x3d,0x36,0x69,0xfd,0x26,0xf8,0x46,0x3e,0x96,0x3e,0x46,0x3a,0x40,0xaa,0x40,0x3a,0x00,0x00,0x00,0x00,0x01,0x00,0x70,0x00,0x00,0x02,0x12,0x02,0x30,0x00,0x13,0x00,0x5a,0xb5,0x03,0x01,0x02,0x03,0x01, 0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1a,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x03,0x03,0x00,0x61,0x01,0x01,0x00,0x00,0x3b,0x4d,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x1e,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x00,0x00,0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x05,0x01,0x04,0x04, 0x39,0x04,0x4e,0x59,0x40,0x0d,0x00,0x00,0x00,0x13,0x00,0x13,0x22,0x13,0x24,0x11,0x06,0x09,0x1a,0x2b,0x33,0x11,0x33,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x23,0x35,0x34,0x23,0x22,0x06,0x15,0x11,0x70,0x5a,0x02,0x07,0x4c,0x40,0x56,0x5d,0x5a,0x75,0x3b,0x3e,0x02,0x26,0x69,0x35,0x3e,0x67,0x5f,0x2f,0x2f,0x78,0x44,0x40, 0xfe,0xa2,0x00,0x00,0xff,0xff,0x00,0x70,0x00,0x00,0x02,0x12,0x03,0x11,0x02,0x26,0x01,0x40,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x76,0x00,0x00,0xff,0xff,0x00,0x70,0x00,0x00,0x02,0x12,0x03,0x11,0x02,0x26,0x01,0x40,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x6c,0x00,0x00,0xff,0xff,0x00,0x23,0xff,0x10,0x02,0x12,0x02,0x30,0x02,0x26, 0x01,0x40,0x00,0x00,0x00,0x07,0x06,0x7a,0x01,0xbd,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0xf8,0x02,0x03,0x02,0x2e,0x00,0x28,0x00,0x3b,0x40,0x38,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x41,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x42,0x00, 0x4e,0x01,0x00,0x1e,0x1b,0x19,0x18,0x16,0x13,0x09,0x06,0x04,0x03,0x00,0x28,0x01,0x27,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x16,0x15,0x14,0x06,0x23,0x01,0x16, 0x5c,0x65,0x5a,0x36,0x31,0x2c,0x32,0x37,0x41,0x98,0x38,0x3e,0x63,0x57,0x2c,0x50,0x65,0x04,0x5b,0x02,0x33,0x29,0x2c,0x2e,0x34,0x35,0x8e,0x8c,0x65,0x5c,0x08,0x53,0x4c,0x26,0x2b,0x2c,0x28,0x47,0x09,0x16,0x08,0x4d,0x3f,0x48,0x52,0x4f,0x40,0x1d,0x26,0x2a,0x24,0x3a,0x08,0x14,0x14,0x90,0x4d,0x55,0x00,0x00,0xff,0xff,0x00,0x55, 0xff,0xf8,0x02,0x03,0x03,0x11,0x02,0x26,0x01,0x44,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0xf8,0x02,0x03,0x03,0x11,0x02,0x26,0x01,0x44,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0x35,0x02,0x03,0x02,0x2e,0x00,0x3a,0x00,0x95,0x40,0x0a,0x09,0x01,0x07,0x03, 0x33,0x01,0x01,0x07,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x36,0x00,0x05,0x06,0x02,0x06,0x05,0x02,0x80,0x00,0x02,0x03,0x06,0x02,0x03,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x72,0x00,0x06,0x06,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x03,0x03,0x07,0x61,0x00,0x07,0x07,0x42,0x4d,0x00,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08, 0x3d,0x08,0x4e,0x1b,0x40,0x34,0x00,0x05,0x06,0x02,0x06,0x05,0x02,0x80,0x00,0x02,0x03,0x06,0x02,0x03,0x7e,0x00,0x01,0x07,0x00,0x07,0x01,0x00,0x80,0x00,0x00,0x09,0x01,0x08,0x00,0x08,0x63,0x00,0x06,0x06,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x03,0x03,0x07,0x61,0x00,0x07,0x07,0x42,0x07,0x4e,0x59,0x40,0x11,0x00,0x00,0x00, 0x3a,0x00,0x39,0x29,0x32,0x12,0x3a,0x32,0x14,0x14,0x21,0x0a,0x09,0x1e,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x26,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x16,0x15,0x14,0x06, 0x23,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xd7,0x46,0x16,0x1b,0x37,0x32,0x17,0x50,0x57,0x5a,0x36,0x31,0x2c,0x32,0x37,0x41,0x98,0x38,0x3e,0x63,0x57,0x2c,0x50,0x65,0x04,0x5b,0x02,0x33,0x29,0x2c,0x2e,0x34,0x35,0x8e,0x8c,0x65,0x5c,0x0d,0x09,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x3e,0x06,0x51,0x47,0x26, 0x2b,0x2c,0x28,0x47,0x09,0x16,0x08,0x4d,0x3f,0x48,0x52,0x4f,0x40,0x1d,0x26,0x2a,0x24,0x3a,0x08,0x14,0x14,0x90,0x4d,0x55,0x1b,0x03,0x14,0x24,0x1a,0x22,0x31,0x00,0xff,0xff,0x00,0x55,0xff,0xf8,0x02,0x03,0x03,0x11,0x02,0x26,0x01,0x44,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0x10,0x02,0x03, 0x02,0x2e,0x02,0x26,0x01,0x44,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x02,0x18,0x02,0xe4,0x00,0x2a,0x00,0x37,0x40,0x34,0x0c,0x01,0x03,0x04,0x01,0x4c,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x69,0x00,0x05,0x05,0x00,0x61,0x00,0x00,0x00,0x3e,0x4d,0x00,0x02,0x02,0x01,0x61,0x07,0x06,0x02, 0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x00,0x2a,0x00,0x2a,0x24,0x21,0x24,0x21,0x2d,0x24,0x08,0x09,0x1c,0x2b,0x33,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11, 0x5c,0x35,0x5f,0x3f,0x3f,0x5e,0x35,0x41,0x34,0x3e,0x4e,0x38,0x63,0x42,0x3a,0x30,0x3e,0x4d,0x48,0x3a,0x39,0x2e,0x35,0x43,0x43,0x35,0x36,0x43,0x02,0x16,0x3d,0x5d,0x34,0x2f,0x52,0x37,0x3b,0x5a,0x0d,0x03,0x0b,0x68,0x48,0x3c,0x5c,0x34,0x52,0x48,0x3a,0x3a,0x48,0x50,0x42,0x35,0x35,0x42,0x46,0x38,0xfd,0xea,0x00,0x01,0x00,0xa5, 0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x0b,0x00,0x1f,0x40,0x1c,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x21,0x23,0x04,0x09,0x18,0x2b,0x33,0x11,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x11,0xa5,0x5d,0x4c,0xb0,0xb0,0x23,0x2c,0x02,0x3b,0x47,0x58, 0x50,0x2c,0x24,0xfd,0xc6,0x00,0x00,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x08,0x02,0xc1,0x00,0x13,0x00,0x35,0x40,0x32,0x00,0x03,0x02,0x03,0x85,0x05,0x01,0x01,0x01,0x02,0x5f,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x06,0x06,0x00,0x60,0x07,0x01,0x00,0x00,0x39,0x00,0x4e,0x01,0x00,0x12,0x10,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07, 0x06,0x05,0x04,0x00,0x13,0x01,0x13,0x08,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x14,0x16,0x33,0x33,0x15,0x01,0x63,0x44,0x52,0x9e,0x9e,0x5a,0xe1,0xe1,0x21,0x1b,0xa0,0x4f,0x42,0x01,0x43,0x52,0x9b,0x9b,0x52,0xfe,0xbd,0x1c,0x23,0x52,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x08, 0x02,0xc1,0x00,0x1b,0x00,0x3e,0x40,0x3b,0x00,0x03,0x02,0x03,0x85,0x06,0x01,0x00,0x0b,0x0a,0x02,0x07,0x08,0x00,0x07,0x67,0x05,0x01,0x01,0x01,0x02,0x5f,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x08,0x08,0x09,0x60,0x00,0x09,0x09,0x39,0x09,0x4e,0x00,0x00,0x00,0x1b,0x00,0x1b,0x18,0x16,0x23,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x0c,0x09,0x1f,0x2b,0x37,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x35,0x55,0x78,0x9e,0x9e,0x5a,0xe1,0xe1,0xb4,0xb4,0x21,0x1b,0xa0,0xa0,0x44,0x52,0xef,0x4b,0x9a,0x52,0x9b,0x9b,0x52,0x9a,0x4b,0x5e,0x1c,0x23,0x52,0x4f,0x42,0x5e,0x00, 0xff,0xff,0x00,0x2f,0x00,0x00,0x02,0x08,0x03,0x21,0x02,0x26,0x01,0x4c,0x00,0x00,0x01,0x07,0x06,0x6d,0x02,0x12,0x00,0x47,0x00,0x08,0xb1,0x01,0x01,0xb0,0x47,0xb0,0x35,0x2b,0x00,0x00,0x00,0x01,0x00,0x2f,0xff,0x35,0x02,0x08,0x02,0xc1,0x00,0x25,0x00,0x87,0x40,0x0a,0x09,0x01,0x08,0x07,0x1e,0x01,0x01,0x08,0x02,0x4c,0x4b,0xb0, 0x15,0x50,0x58,0x40,0x2f,0x00,0x04,0x03,0x04,0x85,0x00,0x01,0x08,0x00,0x08,0x01,0x00,0x80,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3b,0x4d,0x00,0x07,0x07,0x08,0x5f,0x00,0x08,0x08,0x39,0x4d,0x00,0x00,0x00,0x09,0x5f,0x0a,0x01,0x09,0x09,0x3d,0x09,0x4e,0x1b,0x40,0x2c,0x00,0x04,0x03,0x04,0x85,0x00,0x01,0x08,0x00, 0x08,0x01,0x00,0x80,0x00,0x00,0x0a,0x01,0x09,0x00,0x09,0x63,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3b,0x4d,0x00,0x07,0x07,0x08,0x5f,0x00,0x08,0x08,0x39,0x08,0x4e,0x59,0x40,0x12,0x00,0x00,0x00,0x25,0x00,0x24,0x11,0x23,0x11,0x11,0x11,0x11,0x15,0x14,0x21,0x0b,0x09,0x1f,0x2b,0x05,0x35,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x37,0x26,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x14,0x16,0x33,0x33,0x15,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0x01,0x09,0x46,0x16,0x1b,0x37,0x32,0x1c,0x30,0x36,0x9e,0x9e,0x5a,0xe1,0xe1,0x21,0x1b,0xa0,0x99,0x0c,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x4b,0x0d,0x49, 0x35,0x01,0x43,0x52,0x9b,0x9b,0x52,0xfe,0xbd,0x1c,0x23,0x52,0x23,0x03,0x14,0x24,0x1a,0x22,0x31,0x00,0xff,0xff,0x00,0x2f,0xff,0x10,0x02,0x08,0x02,0xc1,0x02,0x26,0x01,0x4c,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x94,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0x26,0x00,0x11,0x00,0x24,0x40,0x21,0x03,0x01,0x01,0x01, 0x3b,0x4d,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x0e,0x0d,0x0a,0x08,0x05,0x04,0x00,0x11,0x01,0x11,0x05,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x01,0x2b,0x5f,0x72,0x5a,0x40,0x37,0x38,0x41,0x5a,0x74,0x0a,0x71,0x61,0x01,0x5e, 0xfe,0xa2,0x3c,0x47,0x47,0x3c,0x01,0x5e,0xfe,0xa2,0x61,0x71,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a, 0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x09,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x68, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xf4,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x27,0x06,0x68,0x02,0x58,0x00,0x00,0x01,0x07,0x06,0x6b,0x02,0x62,0x00,0xe3,0x00,0x08,0xb1,0x03,0x01,0xb0,0xe3,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xf4,0x02,0x26,0x01,0x51,0x00,0x00, 0x00,0x27,0x06,0x68,0x02,0x58,0x00,0x00,0x01,0x07,0x06,0x6f,0x02,0x58,0x00,0xe3,0x00,0x08,0xb1,0x03,0x01,0xb0,0xe3,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xf4,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x27,0x06,0x68,0x02,0x58,0x00,0x00,0x01,0x07,0x06,0x6a,0x02,0x4e,0x00,0xe3,0x00,0x08,0xb1,0x03, 0x01,0xb0,0xe3,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0xcc,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x27,0x06,0x68,0x02,0x58,0x00,0x00,0x01,0x07,0x06,0x73,0x02,0x58,0x00,0xe3,0x00,0x08,0xb1,0x03,0x01,0xb0,0xe3,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x2b,0x01,0xfe,0x02,0x26,0x02,0x26, 0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x39,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a, 0xff,0xf6,0x02,0x58,0x02,0x94,0x00,0x19,0x00,0x4e,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x1c,0x00,0x03,0x00,0x00,0x03,0x70,0x00,0x04,0x04,0x00,0x61,0x02,0x01,0x00,0x00,0x3b,0x4d,0x00,0x01,0x01,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x1b,0x40,0x1b,0x00,0x03,0x00,0x03,0x85,0x00,0x04,0x04,0x00,0x61,0x02,0x01,0x00,0x00,0x3b,0x4d, 0x00,0x01,0x01,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x59,0x40,0x09,0x23,0x13,0x12,0x23,0x23,0x11,0x06,0x09,0x1c,0x2b,0x37,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x11,0x14,0x06,0x23,0x22,0x26,0x5a,0x5a,0x40,0x37,0x38,0x41,0x46,0x23,0x4b,0x2b,0x2f,0x74,0x5f,0x5f, 0x72,0xc8,0x01,0x5e,0xfe,0xa2,0x3e,0x45,0x45,0x3e,0x01,0x5e,0x23,0x4b,0x50,0x2b,0x34,0xfe,0xe3,0x61,0x71,0x71,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x11,0x02,0x26,0x01,0x5e,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x2b,0x02,0x58,0x02,0x94,0x02,0x26,0x01,0x5e,0x00,0x00, 0x00,0x07,0x06,0x78,0x02,0x57,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x11,0x02,0x26,0x01,0x5e,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x39,0x02,0x26,0x01,0x5e,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58, 0x03,0x0c,0x02,0x26,0x01,0x5e,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x10,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x6c,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0xe9,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00, 0x00,0x01,0x00,0x5a,0xff,0x35,0x01,0xfe,0x02,0x26,0x00,0x1f,0x00,0x56,0x4b,0xb0,0x15,0x50,0x58,0x40,0x1c,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x05,0x05,0x00,0x60,0x06,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x19,0x00,0x05,0x06,0x01,0x00,0x05,0x00,0x64,0x04,0x01,0x02,0x02, 0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x13,0x01,0x00,0x1e,0x1c,0x13,0x12,0x10,0x0e,0x0c,0x0b,0x08,0x06,0x00,0x1f,0x01,0x1f,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x37,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x32,0x35,0x11,0x33,0x11,0x14,0x07,0x07,0x06,0x06,0x15,0x14, 0x16,0x33,0x33,0x15,0x01,0x74,0x37,0x43,0x19,0x22,0x09,0x62,0x70,0x5a,0x78,0x78,0x5a,0x57,0x18,0x22,0x1e,0x1e,0x19,0x3c,0xcb,0x35,0x28,0x16,0x2f,0x1f,0x70,0x62,0x01,0x5e,0xfe,0xa2,0x82,0x82,0x01,0x5e,0xfe,0xa2,0x7f,0x34,0x14,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x44,0x02,0x26, 0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x71,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x0c,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x36,0x00,0x00,0x02,0x22,0x02,0x26,0x00,0x0c,0x00,0x21,0x40,0x1e,0x06,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x3b,0x4d, 0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x0c,0x00,0x0c,0x18,0x11,0x04,0x09,0x18,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0xf1,0xbb,0x61,0x78,0x0b,0x10,0x04,0x05,0x0e,0x0a,0x78,0x5f,0xbb,0x02,0x26,0xfe,0x8e,0x21,0x3d,0x11,0x11,0x3d,0x21,0x01,0x72,0xfd,0xda,0x00,0x00,0x01,0x00,0x1f, 0x00,0x00,0x02,0x39,0x02,0x26,0x00,0x1e,0x00,0x27,0x40,0x24,0x1a,0x0f,0x06,0x03,0x03,0x00,0x01,0x4c,0x02,0x01,0x02,0x00,0x00,0x3b,0x4d,0x05,0x04,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x1e,0x00,0x1e,0x11,0x18,0x18,0x11,0x06,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x13,0x16,0x16, 0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x23,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x79,0x5a,0x4e,0x38,0x03,0x06,0x01,0x02,0x05,0x04,0x45,0x5a,0x45,0x04,0x07,0x01,0x02,0x06,0x03,0x3a,0x4a,0x5e,0x63,0x3f,0x04,0x07,0x02,0x01,0x08,0x05,0x42,0x02,0x26,0xfe,0x7c,0x16,0x35,0x11,0x11,0x35,0x16,0x01,0x84,0xfe,0x7c,0x16,0x35,0x11, 0x11,0x35,0x16,0x01,0x84,0xfd,0xda,0x01,0x7c,0x1c,0x3f,0x11,0x11,0x3f,0x1c,0xfe,0x84,0x00,0x00,0x00,0xff,0xff,0x00,0x1f,0x00,0x00,0x02,0x39,0x03,0x11,0x02,0x26,0x01,0x6a,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x1f,0x00,0x00,0x02,0x39,0x03,0x11,0x02,0x26,0x01,0x6a,0x00,0x00,0x00,0x07,0x06,0x6e, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x1f,0x00,0x00,0x02,0x39,0x03,0x09,0x02,0x26,0x01,0x6a,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x1f,0x00,0x00,0x02,0x39,0x03,0x11,0x02,0x26,0x01,0x6a,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0x26,0x00,0x17, 0x00,0x26,0x40,0x23,0x13,0x0d,0x07,0x01,0x04,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x3b,0x4d,0x04,0x03,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x00,0x17,0x00,0x17,0x12,0x18,0x12,0x05,0x09,0x19,0x2b,0x33,0x13,0x03,0x33,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x03,0x13,0x23,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07, 0x32,0xc3,0xb7,0x6a,0x6d,0x07,0x0d,0x04,0x03,0x0d,0x07,0x6d,0x6a,0xb7,0xc2,0x6a,0x76,0x07,0x0d,0x05,0x04,0x0f,0x08,0x76,0x01,0x1b,0x01,0x0b,0xaa,0x0b,0x1a,0x08,0x08,0x1a,0x0b,0xaa,0xfe,0xf4,0xfe,0xe6,0xb4,0x0b,0x1d,0x09,0x09,0x1d,0x0b,0xb4,0x00,0x01,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x26,0x00,0x0d,0x00,0x22,0x40,0x1f, 0x07,0x01,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x3b,0x4d,0x03,0x01,0x02,0x02,0x3d,0x02,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x18,0x12,0x04,0x09,0x18,0x2b,0x17,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x01,0xb2,0x51,0xcd,0x61,0x82,0x08,0x0e,0x03,0x03,0x0e,0x07,0x79,0x5f,0xfe,0xee,0xb4,0xd6,0x02, 0x04,0xfe,0xac,0x14,0x2c,0x10,0x10,0x2c,0x14,0x01,0x54,0xfd,0x26,0x00,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00, 0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x09,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x2b,0x02,0x22,0x02,0x26,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0xf8,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0x70,0x00,0x00, 0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x39,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0xe9,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22, 0x03,0x0c,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a,0x00,0x00,0x01,0xfe,0x02,0x26,0x00,0x09,0x00,0x2c,0x40,0x29,0x06,0x01,0x02,0x02,0x00,0x01,0x4c,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x3b,0x4d,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00, 0x09,0x00,0x09,0x12,0x11,0x12,0x05,0x09,0x19,0x2b,0x33,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x5a,0x01,0x34,0xfe,0xd4,0x01,0x91,0xfe,0xc6,0x01,0x45,0x5a,0x01,0x7a,0x52,0x5a,0xfe,0x86,0x52,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x79,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00, 0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x79,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0x09,0x02,0x26,0x01,0x79,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x1c,0x02,0xda,0x02,0x06,0x00,0x87,0x00,0x00, 0x00,0x01,0x00,0x41,0x00,0x00,0x02,0x2b,0x02,0xda,0x00,0x09,0x00,0x27,0x40,0x24,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x03,0x01,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x09,0x1a,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x41, 0xc8,0xb4,0x01,0x0e,0xc8,0x52,0x02,0x36,0x52,0xfd,0x78,0x52,0xff,0xff,0x00,0x41,0x00,0x00,0x02,0x2b,0x03,0xb6,0x02,0x26,0x01,0x7e,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x53,0x00,0x00,0xff,0xff,0x00,0x41,0x00,0x00,0x02,0x2b,0x02,0xda,0x02,0x26,0x01,0x7e,0x00,0x00,0x00,0x07,0x06,0x6d,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x41, 0xff,0x10,0x02,0x2b,0x02,0xda,0x00,0x27,0x06,0x7a,0x02,0x5d,0x00,0x00,0x02,0x06,0x01,0x7e,0x00,0x00,0xff,0xff,0x00,0x41,0x00,0x00,0x02,0xa7,0x02,0xda,0x00,0x27,0x03,0x29,0x01,0x29,0x01,0x13,0x03,0x06,0x01,0x7e,0x00,0x00,0x00,0x09,0xb1,0x00,0x01,0xb8,0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x41,0x00,0x00,0x02,0x2b, 0x02,0xda,0x00,0x11,0x00,0x34,0x40,0x31,0x0e,0x0d,0x0c,0x0b,0x06,0x05,0x04,0x03,0x08,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x03,0x01,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x11,0x00,0x11,0x15,0x11,0x15,0x11,0x06,0x09,0x1a,0x2b,0x33,0x35,0x33,0x35,0x07,0x35, 0x37,0x35,0x23,0x35,0x21,0x11,0x37,0x15,0x07,0x11,0x33,0x15,0x41,0xc8,0x8c,0x8c,0xb4,0x01,0x0e,0x8c,0x8c,0xc8,0x52,0xf3,0x5f,0x50,0x5f,0xf3,0x52,0xfe,0xf7,0x5f,0x50,0x5f,0xfe,0xd1,0x52,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0xff,0xf6,0x02,0x24,0x02,0xc1,0x00,0x19,0x00,0x3f,0x40,0x3c,0x00,0x03,0x02,0x03,0x85,0x00,0x07,0x01, 0x06,0x01,0x07,0x06,0x80,0x05,0x01,0x01,0x01,0x02,0x5f,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x16,0x14,0x12,0x10,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x19,0x01,0x19,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x33,0x15, 0x33,0x15,0x23,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x01,0x70,0x54,0x63,0x96,0x96,0x5a,0xe1,0xe1,0x32,0x2b,0x2b,0x31,0x58,0x61,0x0a,0x62,0x54,0x01,0x28,0x52,0x9b,0x9b,0x52,0xfe,0xd8,0x2f,0x37,0x37,0x2f,0x03,0x03,0x54,0x62,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0xff,0xf6,0x02,0x24,0x02,0xc1,0x00,0x21, 0x00,0x48,0x40,0x45,0x00,0x03,0x02,0x03,0x85,0x00,0x09,0x07,0x08,0x07,0x09,0x08,0x80,0x06,0x01,0x00,0x0c,0x0b,0x02,0x07,0x09,0x00,0x07,0x67,0x05,0x01,0x01,0x01,0x02,0x5f,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x08,0x08,0x0a,0x61,0x00,0x0a,0x0a,0x3f,0x0a,0x4e,0x00,0x00,0x00,0x21,0x00,0x21,0x1e,0x1c,0x19,0x17,0x23,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x0d,0x09,0x1f,0x2b,0x37,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x55,0x64,0x96,0x96,0x5a,0xe1,0xe1,0xc8,0xc8,0x32,0x2b,0x2b,0x31,0x58,0x61,0x53,0x54,0x63,0xef,0x4b, 0x9a,0x52,0x9b,0x9b,0x52,0x9a,0x4b,0x43,0x2f,0x37,0x37,0x2f,0x03,0x03,0x54,0x62,0x62,0x54,0x43,0x00,0xff,0xff,0x00,0x23,0xff,0xf6,0x02,0x24,0x03,0x21,0x02,0x26,0x01,0x84,0x00,0x00,0x01,0x07,0x06,0x6d,0x02,0x12,0x00,0x47,0x00,0x08,0xb1,0x01,0x01,0xb0,0x47,0xb0,0x35,0x2b,0x00,0x00,0x00,0x01,0x00,0x23,0xff,0x35,0x02,0x24, 0x02,0xc1,0x00,0x2d,0x00,0x98,0x40,0x0a,0x09,0x01,0x09,0x07,0x26,0x01,0x01,0x09,0x02,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x36,0x00,0x04,0x03,0x04,0x85,0x00,0x08,0x02,0x07,0x02,0x08,0x07,0x80,0x00,0x01,0x09,0x00,0x09,0x01,0x72,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3b,0x4d,0x00,0x07,0x07,0x09,0x61,0x00,0x09, 0x09,0x3f,0x4d,0x00,0x00,0x00,0x0a,0x5f,0x0b,0x01,0x0a,0x0a,0x3d,0x0a,0x4e,0x1b,0x40,0x34,0x00,0x04,0x03,0x04,0x85,0x00,0x08,0x02,0x07,0x02,0x08,0x07,0x80,0x00,0x01,0x09,0x00,0x09,0x01,0x00,0x80,0x00,0x00,0x0b,0x01,0x0a,0x00,0x0a,0x63,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3b,0x4d,0x00,0x07,0x07,0x09,0x61, 0x00,0x09,0x09,0x3f,0x09,0x4e,0x59,0x40,0x14,0x00,0x00,0x00,0x2d,0x00,0x2c,0x25,0x22,0x22,0x23,0x11,0x11,0x11,0x11,0x15,0x14,0x21,0x0c,0x09,0x1f,0x2b,0x05,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x26,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14, 0x06,0x23,0x22,0x23,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0x01,0x09,0x46,0x16,0x1b,0x37,0x32,0x19,0x38,0x3f,0x96,0x96,0x5a,0xe1,0xe1,0x32,0x2b,0x2b,0x31,0x58,0x61,0x53,0x05,0x04,0x09,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x44,0x10,0x5a,0x43,0x01,0x28,0x52,0x9b,0x9b,0x52,0xfe,0xd8,0x2f,0x37,0x37,0x2f,0x03, 0x03,0x54,0x62,0x19,0x03,0x14,0x24,0x1a,0x22,0x31,0x00,0x00,0xff,0xff,0x00,0x23,0xff,0x10,0x02,0x24,0x02,0xc1,0x02,0x26,0x01,0x84,0x00,0x00,0x00,0x07,0x06,0x7a,0x02,0x94,0x00,0x00,0x00,0x03,0x00,0x32,0xff,0x42,0x02,0x46,0x02,0x30,0x00,0x26,0x00,0x32,0x00,0x40,0x00,0xd1,0x40,0x0a,0x08,0x01,0x04,0x06,0x07,0x01,0x09,0x05, 0x02,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x2a,0x0b,0x01,0x06,0x00,0x04,0x05,0x06,0x04,0x69,0x00,0x05,0x00,0x09,0x08,0x05,0x09,0x67,0x07,0x01,0x03,0x03,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x0c,0x01,0x08,0x08,0x00,0x5f,0x0a,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x4b,0xb0,0x31,0x50,0x58,0x40,0x32,0x0b,0x01,0x06,0x00,0x04, 0x05,0x06,0x04,0x69,0x00,0x05,0x00,0x09,0x08,0x05,0x09,0x67,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x0c,0x01,0x08,0x08,0x00,0x5f,0x0a,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x2f,0x0b,0x01,0x06,0x00,0x04,0x05,0x06,0x04,0x69,0x00,0x05,0x00,0x09,0x08,0x05,0x09, 0x67,0x0c,0x01,0x08,0x0a,0x01,0x00,0x08,0x00,0x63,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x3b,0x03,0x4e,0x59,0x59,0x40,0x23,0x35,0x33,0x28,0x27,0x01,0x00,0x3c,0x39,0x33,0x40,0x35,0x40,0x2e,0x2c,0x27,0x32,0x28,0x32,0x1f,0x1d,0x1b,0x19,0x13,0x12,0x11,0x10,0x0f,0x0d,0x00, 0x26,0x01,0x25,0x0d,0x09,0x16,0x2b,0x17,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x33,0x15,0x23,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x23,0x15,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0xe2,0x33,0x50,0x2d,0x51,0x40,0x34,0x3a,0x6e,0x5e,0x2e,0x19,0xde,0xb9,0x29,0x33,0x6c,0x5c,0x09,0x08,0x77,0x34,0x4f,0x2e,0x2e,0x4f,0x34,0x66,0x38,0x40,0x40,0x38,0x38,0x42,0x42,0x07,0xa6,0x26,0x31,0x31,0x26,0xa6,0x25,0x32,0x32,0xbe,0x29,0x49,0x30,0x42,0x57,0x0a,0x5f,0x13,0x50,0x39, 0x50,0x5e,0x0a,0x4a,0x01,0x05,0x2d,0x30,0x4b,0x57,0x4e,0x2a,0x4a,0x31,0x30,0x49,0x29,0x01,0xdc,0x36,0x2e,0x2e,0x36,0x36,0x2e,0x2e,0x36,0xfe,0x72,0x30,0x27,0x27,0x30,0x30,0x27,0x27,0x30,0x00,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x11,0x02,0x26,0x01,0x89,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00, 0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x11,0x02,0x26,0x01,0x89,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x11,0x02,0x26,0x01,0x89,0x00,0x00,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x11,0x02,0x26,0x01,0x89,0x00,0x00, 0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x70,0x02,0x26,0x01,0x89,0x00,0x00,0x00,0x07,0x06,0x76,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x32,0xff,0x42,0x02,0x46,0x03,0x09,0x02,0x26,0x01,0x89,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x42,0x01,0xfe, 0x03,0x09,0x02,0x26,0x01,0x91,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0xe3,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0x42,0x01,0xee,0x02,0x26,0x00,0x15,0x00,0x58,0x4b,0xb0,0x31,0x50,0x58,0x40,0x1e,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x3b,0x4d,0x00,0x02,0x02,0x00,0x61,0x05,0x01,0x00,0x00, 0x3d,0x00,0x4e,0x1b,0x40,0x1b,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x02,0x05,0x01,0x00,0x02,0x00,0x65,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x3b,0x03,0x4e,0x59,0x40,0x11,0x01,0x00,0x11,0x10,0x0f,0x0e,0x0b,0x09,0x06,0x05,0x00,0x15,0x01,0x15,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x35,0x33,0x15,0x14,0x16, 0x33,0x32,0x36,0x35,0x11,0x21,0x35,0x21,0x11,0x14,0x06,0x06,0x01,0x24,0x3c,0x5b,0x33,0x5a,0x3f,0x31,0x32,0x3e,0xfe,0xf3,0x01,0x67,0x33,0x5b,0xbe,0x32,0x58,0x3a,0x4a,0x4a,0x34,0x40,0x40,0x34,0x01,0xce,0x52,0xfd,0xe0,0x3a,0x58,0x32,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x42,0x02,0x6c,0x03,0x11,0x02,0x26,0x01,0x91,0x00,0x00, 0x00,0x07,0x06,0x6e,0x02,0xe3,0x00,0x00,0x00,0x01,0xff,0xfb,0xff,0xf6,0x02,0x1f,0x02,0xda,0x00,0x13,0x00,0x32,0x40,0x2f,0x00,0x04,0x01,0x03,0x01,0x04,0x03,0x80,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x03,0x03,0x00,0x61,0x05,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x10,0x0f,0x0c,0x0a,0x07,0x06,0x05,0x04, 0x00,0x13,0x01,0x13,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x01,0x60,0x58,0x67,0xa6,0x01,0x00,0x36,0x2f,0x2f,0x36,0x5a,0x66,0x0a,0x66,0x57,0x01,0xd5,0x52,0xfd,0xd9,0x31,0x3c,0x3c,0x31,0x4b,0x4b,0x57,0x66,0x00,0x00,0x00,0xff,0xff,0xff,0xfb, 0xff,0xf6,0x02,0x1f,0x03,0xb6,0x02,0x26,0x01,0x93,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x30,0x00,0x00,0xff,0xff,0xff,0xfb,0xff,0xf6,0x02,0x1f,0x02,0xda,0x00,0x27,0x06,0x6d,0x02,0x58,0x00,0x00,0x02,0x06,0x01,0x93,0x00,0x00,0xff,0xff,0xff,0xfb,0xff,0x10,0x02,0x1f,0x02,0xda,0x00,0x27,0x06,0x7a,0x02,0x5d,0x00,0x00,0x02,0x06, 0x01,0x93,0x00,0x00,0x00,0x02,0xff,0xfb,0xff,0xf6,0x02,0x4d,0x02,0xda,0x00,0x13,0x00,0x1f,0x00,0x43,0x40,0x40,0x00,0x04,0x05,0x03,0x05,0x04,0x03,0x80,0x00,0x06,0x08,0x01,0x05,0x04,0x06,0x05,0x69,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x15,0x14,0x01, 0x00,0x1b,0x19,0x14,0x1f,0x15,0x1f,0x10,0x0f,0x0c,0x0a,0x07,0x06,0x05,0x04,0x00,0x13,0x01,0x13,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x61,0x58,0x68,0xa6,0x01,0x00,0x37,0x2f, 0x2f,0x37,0x5a,0x67,0x41,0x25,0x2d,0x2d,0x25,0x25,0x2d,0x2d,0x0a,0x66,0x57,0x01,0xd5,0x52,0xfd,0xd9,0x31,0x3a,0x3a,0x31,0x29,0x29,0x57,0x66,0x01,0x23,0x2c,0x23,0x25,0x2e,0x2e,0x25,0x23,0x2c,0x00,0x00,0x00,0x01,0xff,0xfb,0xff,0xf6,0x02,0x1f,0x02,0xda,0x00,0x1b,0x00,0x38,0x40,0x35,0x1b,0x0a,0x09,0x08,0x07,0x02,0x01,0x07, 0x03,0x00,0x00,0x01,0x02,0x03,0x02,0x4c,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x3f,0x04,0x4e,0x23,0x13,0x27,0x11,0x13,0x05,0x09,0x1b,0x2b,0x37,0x35,0x37,0x35,0x23,0x35,0x21,0x11,0x37,0x15,0x07,0x15,0x14,0x16,0x33,0x32,0x36,0x35, 0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x23,0x7e,0xa6,0x01,0x00,0x9a,0x9a,0x36,0x2f,0x2f,0x36,0x5a,0x66,0x59,0x58,0x67,0xe6,0x50,0x55,0xfd,0x52,0xfe,0xee,0x68,0x50,0x68,0xc5,0x31,0x3c,0x3c,0x31,0x4b,0x4b,0x57,0x66,0x66,0x57,0x88,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x30,0x00,0x23,0x00,0x64,0xb6,0x0a, 0x03,0x02,0x05,0x04,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x05,0x04,0x03,0x04,0x05,0x03,0x80,0x06,0x01,0x04,0x04,0x00,0x61,0x02,0x01,0x02,0x00,0x00,0x3b,0x4d,0x08,0x07,0x02,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x21,0x00,0x05,0x04,0x03,0x04,0x05,0x03,0x80,0x00,0x00,0x00,0x3b,0x4d,0x06,0x01,0x04,0x04,0x01,0x61, 0x02,0x01,0x01,0x01,0x41,0x4d,0x08,0x07,0x02,0x03,0x03,0x39,0x03,0x4e,0x59,0x40,0x10,0x00,0x00,0x00,0x23,0x00,0x23,0x23,0x13,0x23,0x13,0x24,0x24,0x11,0x09,0x09,0x1d,0x2b,0x33,0x11,0x33,0x17,0x33,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34, 0x26,0x23,0x22,0x06,0x15,0x11,0x3c,0x51,0x02,0x01,0x05,0x2e,0x25,0x24,0x32,0x0b,0x07,0x31,0x26,0x35,0x40,0x56,0x1d,0x1a,0x1b,0x20,0x50,0x1f,0x1a,0x1a,0x1f,0x02,0x26,0x49,0x26,0x2d,0x29,0x23,0x23,0x29,0x4f,0x3f,0xfe,0x5e,0x01,0xa3,0x21,0x27,0x26,0x21,0xcd,0xcc,0x21,0x27,0x26,0x21,0xfe,0x5c,0x00,0x00,0x00,0x01,0x00,0x22, 0x00,0x00,0x02,0x36,0x02,0x26,0x00,0x18,0x00,0x2e,0x40,0x2b,0x17,0x0f,0x06,0x03,0x03,0x01,0x01,0x4c,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x02,0x01,0x00,0x00,0x3b,0x4d,0x05,0x04,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x18,0x00,0x18,0x11,0x18,0x18,0x11,0x06,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36, 0x36,0x37,0x13,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x23,0x03,0x03,0x6c,0x4a,0x52,0x2f,0x03,0x06,0x01,0x02,0x08,0x06,0x45,0x58,0x43,0x05,0x0c,0x01,0x02,0x06,0x03,0x2e,0x4e,0x4b,0x67,0x57,0x5a,0x02,0x26,0xfe,0x84,0x16,0x39,0x0b,0x0b,0x39,0x16,0x01,0x0f,0xfe,0xf1,0x16,0x37,0x0c,0x0c,0x37,0x16,0x01,0x7c, 0xfd,0xda,0x01,0x5f,0xfe,0xa1,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x02,0x36,0x03,0x11,0x02,0x26,0x01,0x9a,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x02,0x36,0x03,0x11,0x02,0x26,0x01,0x9a,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x02,0x36, 0x03,0x09,0x02,0x26,0x01,0x9a,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x02,0x36,0x03,0x11,0x02,0x26,0x01,0x9a,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x37,0x02,0xda,0x00,0x03,0x00,0x09,0x00,0x2f,0x40,0x2c,0x08,0x05,0x02,0x01,0x02,0x01, 0x4c,0x00,0x00,0x00,0x38,0x4d,0x00,0x02,0x02,0x3b,0x4d,0x05,0x03,0x04,0x03,0x01,0x01,0x39,0x01,0x4e,0x04,0x04,0x00,0x00,0x04,0x09,0x04,0x09,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x33,0x11,0x33,0x11,0x21,0x03,0x13,0x33,0x03,0x13,0x64,0x5a,0x01,0x04,0xf6,0xe6,0x71,0xe5,0xf9,0x02,0xda,0xfd,0x26,0x01,0x22, 0x01,0x04,0xfe,0xfd,0xfe,0xdd,0x00,0x00,0xff,0xff,0x00,0x64,0xff,0x10,0x02,0x37,0x02,0xda,0x00,0x27,0x06,0x7a,0x02,0x58,0x00,0x00,0x02,0x06,0x01,0x9f,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x37,0x02,0x26,0x02,0x06,0x02,0x4b,0x00,0x00,0x00,0x01,0x00,0x41,0x00,0x00,0x02,0x09,0x02,0xda,0x00,0x16,0x00,0x35,0x40,0x32, 0x05,0x01,0x02,0x06,0x01,0x01,0x00,0x02,0x01,0x67,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x07,0x01,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08,0x39,0x08,0x4e,0x00,0x00,0x00,0x16,0x00,0x16,0x11,0x11,0x12,0x21,0x23,0x11,0x11,0x11,0x0a,0x09,0x1e,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15, 0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x41,0x9b,0x9b,0x9b,0x52,0x48,0x93,0x93,0x40,0xd3,0xd3,0xd3,0x52,0x01,0x39,0x50,0x75,0x41,0x49,0x50,0x3a,0x75,0x50,0xfe,0xc7,0x52,0x00,0x01,0x00,0x46,0x00,0x00,0x02,0x23,0x02,0x27,0x00,0x14,0x00,0x6e,0x4b,0xb0,0x1e,0x50,0x58,0xb5,0x07,0x01,0x00,0x01,0x01,0x4c,0x1b,0xb5, 0x07,0x01,0x00,0x04,0x01,0x4c,0x59,0x4b,0xb0,0x1e,0x50,0x58,0x40,0x19,0x04,0x01,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x02,0x3b,0x4d,0x05,0x01,0x00,0x00,0x06,0x5f,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x1b,0x40,0x23,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x02,0x3b,0x4d,0x00,0x04,0x04,0x02,0x5f,0x03,0x01,0x02,0x02,0x3b,0x4d, 0x05,0x01,0x00,0x00,0x06,0x5f,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x59,0x40,0x0f,0x00,0x00,0x00,0x14,0x00,0x14,0x13,0x21,0x24,0x11,0x11,0x11,0x08,0x09,0x1c,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x33,0x15,0x33,0x36,0x36,0x37,0x37,0x15,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x46,0x91,0x87,0xda,0x01,0x0d,0x4e,0x39,0x64,0x63,0x42, 0x4d,0xd3,0x52,0x01,0x82,0x52,0x88,0x3e,0x49,0x01,0x01,0x5b,0x43,0x3a,0xfd,0x52,0xff,0xff,0x00,0x46,0x00,0x00,0x02,0x23,0x03,0x11,0x00,0x27,0x06,0x6b,0x02,0x76,0x00,0x00,0x02,0x06,0x01,0xa3,0x00,0x00,0xff,0xff,0x00,0x46,0x00,0x00,0x02,0x23,0x03,0x11,0x00,0x27,0x06,0x6f,0x02,0x6c,0x00,0x00,0x02,0x06,0x01,0xa3,0x00,0x00, 0xff,0xff,0x00,0x46,0xff,0x10,0x02,0x23,0x02,0x27,0x00,0x27,0x06,0x7a,0x02,0x1c,0x00,0x00,0x02,0x06,0x01,0xa3,0x00,0x00,0x00,0x01,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x26,0x00,0x15,0x00,0x22,0x40,0x1f,0x0b,0x05,0x02,0x00,0x01,0x01,0x4c,0x02,0x01,0x01,0x01,0x3b,0x4d,0x00,0x00,0x00,0x03,0x60,0x00,0x03,0x03,0x3d,0x03,0x4e, 0x23,0x18,0x14,0x20,0x04,0x09,0x1a,0x2b,0x17,0x33,0x32,0x36,0x37,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x06,0x06,0x23,0x23,0x42,0x66,0x19,0x25,0x0b,0x12,0xcd,0x61,0x82,0x07,0x0f,0x03,0x03,0x0e,0x07,0x79,0x5f,0xdb,0x13,0x4c,0x31,0x75,0x61,0x1e,0x19,0x2a,0x02,0x26,0xfe,0x8a,0x14,0x2c,0x10,0x10, 0x2c,0x14,0x01,0x76,0xfd,0x9a,0x37,0x3d,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22, 0x03,0x09,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x2b,0x02,0x22,0x02,0x26,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0xf8,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00, 0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x39,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0xe9,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x0c,0x02,0x26,0x01,0xa7,0x00,0x00, 0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x02,0x26,0x00,0x14,0x00,0x4c,0xb5,0x03,0x01,0x03,0x02,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x13,0x05,0x04,0x02,0x02,0x02,0x3b,0x4d,0x00,0x03,0x03,0x00,0x61,0x01,0x01,0x00,0x00,0x39,0x00,0x4e,0x1b,0x40,0x17,0x05,0x04,0x02,0x02,0x02,0x3b, 0x4d,0x00,0x00,0x00,0x39,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x0d,0x00,0x00,0x00,0x14,0x00,0x14,0x23,0x13,0x24,0x11,0x06,0x09,0x1a,0x2b,0x01,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0xfc,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63, 0x5a,0x3f,0x36,0x38,0x41,0x02,0x26,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x03,0x11,0x00,0x14,0x00,0x18,0x00,0x6a,0xb5,0x03,0x01,0x03,0x02,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1e,0x00,0x05,0x06,0x05,0x85,0x08,0x01,0x06,0x02,0x06, 0x85,0x07,0x04,0x02,0x02,0x02,0x3b,0x4d,0x00,0x03,0x03,0x00,0x61,0x01,0x01,0x00,0x00,0x39,0x00,0x4e,0x1b,0x40,0x22,0x00,0x05,0x06,0x05,0x85,0x08,0x01,0x06,0x02,0x06,0x85,0x07,0x04,0x02,0x02,0x02,0x3b,0x4d,0x00,0x00,0x00,0x39,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x40,0x15,0x15,0x15,0x00,0x00, 0x15,0x18,0x15,0x18,0x17,0x16,0x00,0x14,0x00,0x14,0x23,0x13,0x24,0x11,0x09,0x09,0x1a,0x2b,0x01,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x27,0x37,0x33,0x07,0x01,0xfc,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0xb0,0x6a,0x61,0x6f,0x02,0x26,0xfd, 0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x5f,0x8c,0x8c,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x03,0x11,0x00,0x0d,0x00,0x22,0x00,0x7a,0xb5,0x11,0x01,0x07,0x06,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x22,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x09,0x01,0x00,0x06,0x02,0x00, 0x69,0x0a,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x07,0x07,0x04,0x62,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x26,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x09,0x01,0x00,0x06,0x02,0x00,0x69,0x0a,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x04,0x04,0x39,0x4d,0x00,0x07,0x07,0x05,0x62,0x00,0x05,0x05,0x3f,0x05,0x4e,0x59,0x40,0x1d, 0x0e,0x0e,0x01,0x00,0x0e,0x22,0x0e,0x22,0x1f,0x1d,0x1a,0x19,0x16,0x14,0x10,0x0f,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00,0x0d,0x01,0x0d,0x0b,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x17,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35, 0x11,0x01,0x2c,0x48,0x58,0x47,0x30,0x28,0x29,0x31,0x47,0x58,0x88,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x80,0x50,0x41,0x27,0x30,0x30,0x27,0x41,0x50,0x5a,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc, 0x03,0x11,0x00,0x06,0x00,0x1b,0x00,0x75,0x40,0x0a,0x05,0x01,0x01,0x00,0x0a,0x01,0x06,0x05,0x02,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1f,0x00,0x00,0x01,0x00,0x85,0x08,0x02,0x02,0x01,0x05,0x01,0x85,0x09,0x07,0x02,0x05,0x05,0x3b,0x4d,0x00,0x06,0x06,0x03,0x62,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x23,0x00,0x00,0x01, 0x00,0x85,0x08,0x02,0x02,0x01,0x05,0x01,0x85,0x09,0x07,0x02,0x05,0x05,0x3b,0x4d,0x00,0x03,0x03,0x39,0x4d,0x00,0x06,0x06,0x04,0x62,0x00,0x04,0x04,0x3f,0x04,0x4e,0x59,0x40,0x19,0x07,0x07,0x00,0x00,0x07,0x1b,0x07,0x1b,0x18,0x16,0x13,0x12,0x0f,0x0d,0x09,0x08,0x00,0x06,0x00,0x06,0x11,0x11,0x0a,0x09,0x18,0x2b,0x13,0x37,0x33, 0x17,0x23,0x27,0x07,0x05,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x77,0x8b,0x53,0x8c,0x63,0x52,0x50,0x01,0x20,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x85,0x8c,0x8c,0x4e,0x4e,0x5f,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e, 0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x03,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x03,0x09,0x00,0x0b,0x00,0x17,0x00,0x2c,0x00,0xa2,0xb5,0x1b,0x01,0x07,0x06,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x21,0x0a,0x02,0x09,0x03,0x00,0x00,0x01,0x61,0x03,0x01,0x01,0x01,0x40,0x4d,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x07,0x07, 0x04,0x61,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1f,0x03,0x01,0x01,0x0a,0x02,0x09,0x03,0x00,0x06,0x01,0x00,0x69,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x07,0x07,0x04,0x61,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x23,0x03,0x01,0x01,0x0a,0x02,0x09,0x03,0x00,0x06,0x01,0x00,0x69,0x0b, 0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x04,0x04,0x39,0x4d,0x00,0x07,0x07,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x59,0x59,0x40,0x21,0x18,0x18,0x0d,0x0c,0x01,0x00,0x18,0x2c,0x18,0x2c,0x29,0x27,0x24,0x23,0x20,0x1e,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x09,0x16,0x2b,0x01,0x22,0x26,0x35, 0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x9b,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x01,0x22,0x5a,0x01,0x07,0x4c, 0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x89,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x63,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x02,0x00,0x5a,0xff,0x2b,0x01,0xfc,0x02,0x26,0x00,0x0b,0x00,0x20,0x00,0x68,0xb5,0x0f,0x01,0x05, 0x04,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1b,0x00,0x01,0x07,0x01,0x00,0x01,0x00,0x65,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x05,0x05,0x02,0x61,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x1b,0x40,0x1f,0x00,0x01,0x07,0x01,0x00,0x01,0x00,0x65,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x05,0x05,0x03, 0x61,0x00,0x03,0x03,0x3f,0x03,0x4e,0x59,0x40,0x19,0x0c,0x0c,0x01,0x00,0x0c,0x20,0x0c,0x20,0x1d,0x1b,0x18,0x17,0x14,0x12,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16, 0x33,0x32,0x36,0x35,0x11,0x01,0x2c,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0xaf,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0xd5,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x02,0xfb,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc, 0x03,0x11,0x00,0x03,0x00,0x18,0x00,0x6d,0xb5,0x07,0x01,0x05,0x04,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1e,0x00,0x00,0x01,0x00,0x85,0x07,0x01,0x01,0x04,0x01,0x85,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x05,0x05,0x02,0x62,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x1b,0x40,0x22,0x00,0x00,0x01,0x00,0x85,0x07,0x01,0x01,0x04, 0x01,0x85,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x05,0x05,0x03,0x62,0x00,0x03,0x03,0x3f,0x03,0x4e,0x59,0x40,0x18,0x04,0x04,0x00,0x00,0x04,0x18,0x04,0x18,0x15,0x13,0x10,0x0f,0x0c,0x0a,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x09,0x17,0x2b,0x01,0x27,0x33,0x17,0x17,0x11,0x23,0x35,0x23,0x06,0x06, 0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x0b,0x73,0x64,0x6e,0x92,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x85,0x8c,0x8c,0x5f,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc, 0x03,0x39,0x00,0x0e,0x00,0x23,0x00,0xa6,0xb5,0x12,0x01,0x06,0x05,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x23,0x08,0x01,0x02,0x00,0x05,0x00,0x02,0x72,0x00,0x01,0x00,0x00,0x02,0x01,0x00,0x67,0x09,0x07,0x02,0x05,0x05,0x3b,0x4d,0x00,0x06,0x06,0x03,0x61,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40, 0x24,0x08,0x01,0x02,0x00,0x05,0x00,0x02,0x05,0x80,0x00,0x01,0x00,0x00,0x02,0x01,0x00,0x67,0x09,0x07,0x02,0x05,0x05,0x3b,0x4d,0x00,0x06,0x06,0x03,0x61,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x28,0x08,0x01,0x02,0x00,0x05,0x00,0x02,0x05,0x80,0x00,0x01,0x00,0x00,0x02,0x01,0x00,0x67,0x09,0x07,0x02,0x05,0x05,0x3b,0x4d, 0x00,0x03,0x03,0x39,0x4d,0x00,0x06,0x06,0x04,0x61,0x00,0x04,0x04,0x3f,0x04,0x4e,0x59,0x59,0x40,0x19,0x0f,0x0f,0x00,0x00,0x0f,0x23,0x0f,0x23,0x20,0x1e,0x1b,0x1a,0x17,0x15,0x11,0x10,0x00,0x0e,0x00,0x0e,0x21,0x24,0x0a,0x09,0x18,0x2b,0x01,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x07,0x07,0x17,0x11,0x23, 0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x02,0x32,0x0e,0x20,0x50,0x69,0x26,0x2f,0x11,0x28,0xa5,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x85,0x3f,0x13,0x0d,0x14,0x41,0x27,0x23,0x20,0x16,0x34,0x5f,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72, 0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x01,0x00,0x5a,0xff,0xf6,0x02,0x58,0x02,0x94,0x00,0x1c,0x00,0x8f,0xb5,0x19,0x01,0x02,0x05,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x1e,0x00,0x04,0x01,0x01,0x04,0x70,0x00,0x05,0x05,0x01,0x5f,0x03,0x01,0x01,0x01,0x3b,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x07,0x02,0x00,0x00,0x3f, 0x00,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x00,0x04,0x01,0x04,0x85,0x00,0x05,0x05,0x01,0x5f,0x03,0x01,0x01,0x01,0x3b,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x07,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x21,0x00,0x04,0x01,0x04,0x85,0x00,0x05,0x05,0x01,0x5f,0x03,0x01,0x01,0x01,0x3b,0x4d,0x00,0x06,0x06,0x39,0x4d,0x00, 0x02,0x02,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x59,0x40,0x15,0x01,0x00,0x18,0x17,0x16,0x15,0x12,0x11,0x0f,0x0d,0x0a,0x08,0x05,0x04,0x00,0x1c,0x01,0x1c,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x11,0x23,0x35,0x23, 0x06,0x06,0x01,0x0f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x48,0x23,0x4b,0x2d,0x2f,0x5a,0x01,0x07,0x4c,0x0a,0x66,0x58,0x01,0x72,0xfe,0x98,0x3a,0x40,0x44,0x40,0x01,0x5e,0x23,0x4b,0x50,0x2b,0x34,0xfe,0x1b,0x69,0x37,0x3c,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x11,0x02,0x26,0x01,0xb8,0x00,0x00,0x00,0x07,0x06,0x6b, 0x02,0x62,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x2b,0x02,0x58,0x02,0x94,0x02,0x26,0x01,0xb8,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x57,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x11,0x02,0x26,0x01,0xb8,0x00,0x00,0x00,0x07,0x06,0x6a,0x02,0x4e,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x39,0x02,0x26, 0x01,0xb8,0x00,0x00,0x00,0x07,0x06,0x74,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x02,0x58,0x03,0x0c,0x02,0x26,0x01,0xb8,0x00,0x00,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x5a,0xff,0xf6,0x02,0x10,0x03,0x11,0x00,0x03,0x00,0x07,0x00,0x1c,0x00,0x77,0xb5,0x0b,0x01,0x07,0x06,0x01,0x4c,0x4b,0xb0,0x18, 0x50,0x58,0x40,0x1f,0x02,0x01,0x00,0x0a,0x03,0x09,0x03,0x01,0x06,0x00,0x01,0x67,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x07,0x07,0x04,0x61,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x23,0x02,0x01,0x00,0x0a,0x03,0x09,0x03,0x01,0x06,0x00,0x01,0x67,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x04,0x04,0x39,0x4d,0x00,0x07, 0x07,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x59,0x40,0x20,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x1c,0x08,0x1c,0x19,0x17,0x14,0x13,0x10,0x0e,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x09,0x17,0x2b,0x01,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x05,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35, 0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x46,0x6e,0x5c,0x73,0xfe,0xf6,0x6e,0x5c,0x73,0x01,0x12,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x85,0x8c,0x8c,0x8c,0x8c,0x5f,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x02,0x00,0x5a, 0xff,0xf6,0x01,0xfc,0x02,0xe9,0x00,0x03,0x00,0x18,0x00,0x96,0xb5,0x07,0x01,0x05,0x04,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1e,0x07,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x05,0x05,0x02,0x61,0x03,0x01,0x02,0x02,0x39,0x02,0x4e,0x1b,0x4b,0xb0,0x21,0x50,0x58,0x40,0x22, 0x07,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x3f,0x03,0x4e,0x1b,0x40,0x20,0x00,0x00,0x07,0x01,0x01,0x04,0x00,0x01,0x67,0x08,0x06,0x02,0x04,0x04,0x3b,0x4d,0x00,0x02,0x02,0x39,0x4d,0x00,0x05,0x05,0x03,0x61,0x00, 0x03,0x03,0x3f,0x03,0x4e,0x59,0x59,0x40,0x18,0x04,0x04,0x00,0x00,0x04,0x18,0x04,0x18,0x15,0x13,0x10,0x0f,0x0c,0x0a,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x17,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x8c,0x01,0x40,0x30,0x5a, 0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x9e,0x4b,0x4b,0x78,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0x35,0x02,0x20,0x02,0x26,0x00,0x23,0x00,0xa0,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0a,0x07,0x01,0x03,0x02,0x06,0x01,0x01, 0x03,0x02,0x4c,0x1b,0x40,0x0a,0x07,0x01,0x03,0x02,0x06,0x01,0x05,0x03,0x02,0x4c,0x59,0x4b,0xb0,0x15,0x50,0x58,0x40,0x1d,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x05,0x01,0x01,0x01,0x3f,0x4d,0x00,0x06,0x06,0x00,0x5f,0x07,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1a,0x00,0x06,0x07, 0x01,0x00,0x06,0x00,0x63,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x03,0x03,0x01,0x61,0x05,0x01,0x01,0x01,0x3f,0x01,0x4e,0x1b,0x40,0x1e,0x00,0x06,0x07,0x01,0x00,0x06,0x00,0x63,0x04,0x01,0x02,0x02,0x3b,0x4d,0x00,0x05,0x05,0x39,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3f,0x01,0x4e,0x59,0x59,0x40,0x15,0x01,0x00,0x22,0x20, 0x1b,0x1a,0x19,0x18,0x15,0x13,0x10,0x0f,0x0c,0x0a,0x00,0x23,0x01,0x23,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x01,0xd2,0x37,0x43,0x21,0x29,0x01,0x07,0x4c,0x3f, 0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x5a,0x10,0x21,0x1e,0x1e,0x19,0x3c,0xcb,0x35,0x28,0x1b,0x37,0x1e,0x67,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0xfd,0xda,0x1b,0x2d,0x15,0x16,0x1c,0x3c,0x00,0x00,0x03,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x03,0x44,0x00,0x0b,0x00,0x17,0x00,0x2c,0x00,0x84,0xb5,0x1b, 0x01,0x07,0x06,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x25,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x0a,0x01,0x02,0x09,0x01,0x00,0x06,0x02,0x00,0x69,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x07,0x07,0x04,0x61,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x29,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x0a,0x01,0x02,0x09, 0x01,0x00,0x06,0x02,0x00,0x69,0x0b,0x08,0x02,0x06,0x06,0x3b,0x4d,0x00,0x04,0x04,0x39,0x4d,0x00,0x07,0x07,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x59,0x40,0x21,0x18,0x18,0x0d,0x0c,0x01,0x00,0x18,0x2c,0x18,0x2c,0x29,0x27,0x24,0x23,0x20,0x1e,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x09, 0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x2c,0x36,0x42,0x42,0x36,0x36,0x42,0x42,0x36,0x1b,0x21,0x21,0x1b,0x1b,0x21,0x21, 0xeb,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x60,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x33,0x3f,0x35,0x21,0x1c,0x1c,0x22,0x22,0x1c,0x1c,0x21,0x6f,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfc,0x03,0x0c,0x00,0x19, 0x00,0x2e,0x00,0xfc,0xb5,0x1d,0x01,0x09,0x08,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x2a,0x00,0x01,0x01,0x03,0x61,0x05,0x01,0x03,0x03,0x40,0x4d,0x02,0x0b,0x02,0x00,0x00,0x04,0x61,0x00,0x04,0x04,0x38,0x4d,0x0c,0x0a,0x02,0x08,0x08,0x3b,0x4d,0x00,0x09,0x09,0x06,0x61,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x1b,0x4b,0xb0,0x18, 0x50,0x58,0x40,0x28,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x02,0x0b,0x02,0x00,0x00,0x04,0x61,0x00,0x04,0x04,0x38,0x4d,0x0c,0x0a,0x02,0x08,0x08,0x3b,0x4d,0x00,0x09,0x09,0x06,0x61,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x1b,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x2a,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02, 0x0b,0x02,0x00,0x08,0x04,0x00,0x6a,0x0c,0x0a,0x02,0x08,0x08,0x3b,0x4d,0x00,0x06,0x06,0x39,0x4d,0x00,0x09,0x09,0x07,0x61,0x00,0x07,0x07,0x3f,0x07,0x4e,0x1b,0x40,0x38,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x0b,0x01,0x00,0x08,0x04, 0x00,0x6a,0x0c,0x0a,0x02,0x08,0x08,0x3b,0x4d,0x00,0x06,0x06,0x39,0x4d,0x00,0x09,0x09,0x07,0x61,0x00,0x07,0x07,0x3f,0x07,0x4e,0x59,0x59,0x59,0x40,0x21,0x1a,0x1a,0x01,0x00,0x1a,0x2e,0x1a,0x2e,0x2b,0x29,0x26,0x25,0x22,0x20,0x1c,0x1b,0x16,0x15,0x13,0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x0d,0x09,0x16,0x2b, 0x01,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x17,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x01,0x72,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x32,0x28,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x31, 0x61,0x5a,0x01,0x07,0x4c,0x3f,0x52,0x63,0x5a,0x3f,0x36,0x38,0x41,0x02,0x8a,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x64,0xfd,0xda,0x69,0x37,0x3c,0x66,0x58,0x01,0x72,0xfe,0x9e,0x3f,0x43,0x46,0x40,0x01,0x5e,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x2e,0x02,0xe4,0x00,0x17, 0x00,0x3d,0x40,0x3a,0x00,0x01,0x02,0x03,0x02,0x01,0x03,0x80,0x07,0x01,0x03,0x06,0x01,0x04,0x05,0x03,0x04,0x67,0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x3e,0x4d,0x00,0x05,0x05,0x39,0x05,0x4e,0x01,0x00,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x08,0x06,0x04,0x03,0x00,0x17,0x01,0x17,0x09,0x09,0x16,0x2b,0x01, 0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x01,0x75,0x53,0x66,0x58,0x36,0x2b,0x2b,0x37,0xe1,0xe1,0x5a,0x96,0x96,0x68,0x02,0xe4,0x62,0x54,0x2f,0x37,0x37,0x2f,0x8f,0x52,0xfe,0xb3,0x01,0x4d,0x52,0x8f,0x54,0x62,0x00,0x01,0x00,0x41,0x00,0x00,0x02,0x09, 0x02,0xda,0x00,0x16,0x00,0x37,0x40,0x34,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x06,0x01,0x01,0x01,0x02,0x5f,0x05,0x01,0x02,0x02,0x3b,0x4d,0x07,0x01,0x00,0x00,0x08,0x5f,0x09,0x01,0x08,0x08,0x39,0x08,0x4e,0x00,0x00,0x00,0x16,0x00,0x16,0x11,0x11,0x12,0x21,0x23,0x11,0x11,0x11,0x0a,0x09,0x1e,0x2b,0x33,0x35,0x33, 0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x41,0x9b,0x9b,0x9b,0x52,0x48,0x93,0x93,0x40,0xd3,0xd3,0xd3,0x52,0x01,0x84,0x50,0x2a,0x41,0x49,0x50,0x3a,0x2a,0x50,0xfe,0x7c,0x52,0x00,0x00,0x00,0x01,0x00,0x37,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x12,0x00,0x2f,0x40,0x2c, 0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x05,0x01,0x00,0x00,0x01,0x5f,0x04,0x01,0x01,0x01,0x3b,0x4d,0x07,0x01,0x06,0x06,0x39,0x06,0x4e,0x00,0x00,0x00,0x12,0x00,0x12,0x11,0x12,0x21,0x23,0x11,0x11,0x08,0x09,0x1c,0x2b,0x33,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11, 0xd7,0xa0,0xa0,0x52,0x48,0xa1,0xa1,0x40,0xe1,0xe1,0x01,0xd4,0x52,0x28,0x41,0x4b,0x52,0x3a,0x28,0x52,0xfe,0x2c,0x00,0x00,0x00,0x02,0x00,0xaf,0x01,0xc2,0x01,0xa4,0x02,0xe4,0x00,0x1b,0x00,0x25,0x00,0x8f,0xb5,0x18,0x01,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x2c,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x04, 0x00,0x02,0x03,0x04,0x02,0x69,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x67,0x09,0x01,0x06,0x00,0x00,0x06,0x59,0x09,0x01,0x06,0x06,0x00,0x61,0x05,0x08,0x02,0x00,0x06,0x00,0x51,0x1b,0x40,0x33,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x05,0x06,0x00,0x06,0x05,0x00,0x80,0x00,0x04,0x00,0x02,0x03,0x04,0x02,0x69,0x00,0x01,0x00, 0x07,0x06,0x01,0x07,0x67,0x09,0x01,0x06,0x05,0x00,0x06,0x59,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x06,0x00,0x51,0x59,0x40,0x1b,0x1d,0x1c,0x01,0x00,0x22,0x20,0x1c,0x25,0x1d,0x25,0x17,0x16,0x13,0x11,0x0f,0x0e,0x0c,0x0a,0x07,0x05,0x00,0x1b,0x01,0x1b,0x0a,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35, 0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x22,0x15,0x14,0x16,0x01,0x12,0x2d,0x36,0x38,0x31,0x5a,0x23,0x1e,0x1a,0x24,0x03,0x32,0x05,0x3d,0x31,0x35,0x3e,0x2f,0x03,0x0a,0x33,0x16,0x27,0x2c,0x5a,0x37,0x22,0x01,0xc2,0x2f,0x27,0x27,0x2e,0x1d, 0x17,0x1b,0x16,0x12,0x26,0x2a,0x30,0x2a,0xc3,0x37,0x1c,0x20,0x26,0x24,0x1f,0x1a,0x2d,0x16,0x1a,0x00,0x00,0x02,0x00,0xb9,0x01,0xbd,0x01,0x9f,0x02,0xdf,0x00,0x0d,0x00,0x1b,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00, 0x51,0x0f,0x0e,0x01,0x00,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x34,0x3f,0x3f,0x34,0x34,0x3f,0x3f,0x34,0x1d,0x24,0x24,0x1d,0x1d, 0x24,0x24,0x01,0xbd,0x3a,0x2f,0x50,0x2f,0x3a,0x3a,0x2f,0x50,0x2f,0x3a,0x28,0x24,0x1d,0x50,0x1d,0x24,0x24,0x1d,0x50,0x1d,0x24,0x00,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x06,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x5e,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x0c,0x00,0x15,0x00,0x31,0x40,0x2e,0x00,0x02, 0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x00,0x04,0x04,0x03,0x5f,0x06,0x01,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x15,0x13,0x0f,0x0d,0x00,0x0c,0x00,0x0b,0x21,0x11,0x11,0x07,0x07,0x19,0x2b,0x33,0x11,0x21,0x15,0x21,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34, 0x26,0x23,0x23,0x5e,0x01,0x96,0xfe,0xc4,0x79,0x68,0x79,0x79,0x68,0x79,0x79,0x3e,0x46,0x46,0x3e,0x79,0x02,0xda,0x52,0xd8,0x76,0x62,0x61,0x77,0x52,0x49,0x3d,0x3e,0x48,0x00,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x12,0x02,0xda,0x02,0x06,0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x02,0x2b,0x02,0xda,0x00,0x05, 0x00,0x1f,0x40,0x1c,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x03,0x01,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x07,0x18,0x2b,0x33,0x11,0x21,0x15,0x21,0x11,0x82,0x01,0xa9,0xfe,0xb1,0x02,0xda,0x52,0xfd,0x78,0x00,0x00,0x00,0xff,0xff,0x00,0x82,0x00,0x00,0x02,0x2b,0x03,0xb6,0x02,0x26, 0x01,0xcb,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x76,0x00,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x02,0x2b,0x03,0x39,0x00,0x07,0x00,0x47,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x17,0x00,0x01,0x00,0x00,0x01,0x70,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x04,0x01,0x03,0x03,0x1b,0x03,0x4e,0x1b,0x40,0x16,0x00,0x01,0x00,0x01,0x85, 0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x04,0x01,0x03,0x03,0x1b,0x03,0x4e,0x59,0x40,0x0c,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x21,0x35,0x33,0x15,0x21,0x11,0x82,0x01,0x54,0x55,0xfe,0xb1,0x02,0xda,0x5f,0xb1,0xfd,0x78,0x00,0x00,0x00,0x00,0x02,0x00,0x19,0xff,0x74,0x02,0x3f, 0x02,0xda,0x00,0x0e,0x00,0x15,0x00,0x33,0x40,0x30,0x08,0x05,0x02,0x03,0x00,0x03,0x53,0x00,0x07,0x07,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x06,0x02,0x02,0x00,0x00,0x04,0x5f,0x00,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x12,0x11,0x10,0x0f,0x00,0x0e,0x00,0x0e,0x11,0x11,0x11,0x14,0x11,0x09,0x07,0x1b,0x2b,0x17,0x35,0x33,0x36,0x36, 0x37,0x13,0x21,0x11,0x33,0x15,0x23,0x35,0x21,0x15,0x37,0x33,0x11,0x23,0x03,0x06,0x06,0x19,0x2d,0x11,0x24,0x01,0x07,0x01,0x76,0x46,0x50,0xfe,0x7a,0x3b,0xfb,0xc6,0x05,0x01,0x20,0x8c,0xd9,0x1e,0x79,0x46,0x01,0xb0,0xfd,0x73,0xd9,0x8c,0x8c,0xd9,0x02,0x3d,0xfe,0xa0,0x4d,0x76,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08, 0x02,0xda,0x02,0x06,0x00,0x25,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x08,0x03,0xb1,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x62,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x00,0x02,0x52,0x02,0xda,0x00,0x15,0x00,0x36,0x40,0x33,0x0c,0x01,0x02,0x06,0x01,0x01,0x4c,0x03,0x01,0x01,0x08,0x01,0x06,0x05,0x01,0x06, 0x67,0x04,0x02,0x02,0x00,0x00,0x1a,0x4d,0x0a,0x09,0x07,0x03,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x15,0x00,0x15,0x11,0x11,0x11,0x12,0x11,0x11,0x11,0x11,0x12,0x0b,0x07,0x1f,0x2b,0x33,0x13,0x03,0x33,0x13,0x33,0x11,0x33,0x11,0x33,0x13,0x33,0x03,0x13,0x23,0x03,0x23,0x11,0x23,0x11,0x23,0x03,0x06,0x86,0x7c,0x5e,0x6a,0x2e, 0x4c,0x30,0x68,0x5e,0x7d,0x87,0x5d,0x75,0x2e,0x4c,0x30,0x74,0x01,0x7b,0x01,0x5f,0xfe,0xc1,0x01,0x3f,0xfe,0xc1,0x01,0x3f,0xfe,0xa0,0xfe,0x86,0x01,0x57,0xfe,0xa9,0x01,0x57,0xfe,0xa9,0x00,0x01,0x00,0x34,0xff,0xf6,0x02,0x16,0x02,0xe4,0x00,0x2d,0x00,0x4e,0x40,0x4b,0x26,0x01,0x03,0x04,0x01,0x4c,0x00,0x06,0x05,0x04,0x05,0x06, 0x04,0x80,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x04,0x00,0x03,0x01,0x04,0x03,0x67,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x1f,0x4d,0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e,0x01,0x00,0x20,0x1e,0x1b,0x1a,0x18,0x16,0x12,0x10,0x0f,0x0d,0x09,0x07,0x05,0x04,0x00,0x2d,0x01,0x2d,0x09,0x07,0x16,0x2b, 0x05,0x22,0x26,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x23,0x46,0x6b,0x3d,0x01,0x5a,0x02,0x53,0x41,0x43,0x53,0x53,0x43,0x56,0x57,0x39,0x47, 0x46,0x38,0x3b,0x4a,0x5a,0x39,0x64,0x42,0x40,0x61,0x37,0x41,0x34,0x3e,0x4e,0x3d,0x6e,0x0a,0x35,0x5f,0x3e,0x3a,0x48,0x4b,0x3c,0x3c,0x4b,0x50,0x44,0x36,0x35,0x41,0x48,0x3a,0x3f,0x5e,0x35,0x30,0x55,0x38,0x3c,0x5b,0x0d,0x03,0x0b,0x67,0x47,0x3e,0x5e,0x35,0x00,0x00,0x00,0x01,0x00,0x5a,0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x11, 0x00,0x24,0x40,0x21,0x10,0x07,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x1a,0x4d,0x04,0x03,0x02,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x00,0x11,0x00,0x11,0x11,0x16,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x33,0x11,0x14,0x06,0x06,0x07,0x13,0x33,0x11,0x23,0x11,0x34,0x36,0x36,0x37,0x03,0x5a,0x57,0x03,0x04,0x02,0xde,0x78,0x57, 0x03,0x05,0x02,0xdf,0x02,0xda,0xfe,0x66,0x24,0x51,0x49,0x19,0x02,0x71,0xfd,0x26,0x01,0x9a,0x25,0x51,0x49,0x18,0xfd,0x8f,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0xb6,0x02,0x26,0x01,0xd3,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0x51,0x00,0x00, 0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x30,0x03,0xb6,0x02,0x26,0x00,0x51,0x00,0x00,0x00,0x07,0x06,0x91,0x02,0x62,0x00,0x00,0x00,0x01,0x00,0x14,0xff,0xfb,0x01,0xfa,0x02,0xda,0x00,0x0f,0x00,0x4d,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x17,0x00,0x03,0x03,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x00,0x00,0x00,0x02,0x61,0x05,0x04,0x02,0x02, 0x02,0x1b,0x02,0x4e,0x1b,0x40,0x1b,0x00,0x03,0x03,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x00,0x02,0x02,0x1b,0x4d,0x00,0x00,0x00,0x04,0x61,0x05,0x01,0x04,0x04,0x22,0x04,0x4e,0x59,0x40,0x0d,0x00,0x00,0x00,0x0f,0x00,0x0e,0x11,0x11,0x13,0x21,0x06,0x07,0x1a,0x2b,0x17,0x35,0x33,0x32,0x36,0x37,0x13,0x21,0x11,0x23,0x11,0x23,0x03, 0x06,0x06,0x23,0x14,0x12,0x2c,0x27,0x01,0x08,0x01,0x78,0x5a,0xc5,0x07,0x02,0x51,0x56,0x05,0x54,0x4f,0x60,0x01,0xdc,0xfd,0x26,0x02,0x88,0xfe,0x76,0x86,0x7d,0x00,0xff,0xff,0x00,0x48,0x00,0x00,0x02,0x10,0x02,0xda,0x02,0x06,0x00,0x59,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x01,0xfb,0x02,0xda,0x02,0x06,0x00,0x40,0x00,0x00, 0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x02,0xe4,0x02,0x06,0x00,0x60,0x00,0x00,0x00,0x01,0x00,0x5e,0x00,0x00,0x01,0xfa,0x02,0xda,0x00,0x07,0x00,0x21,0x40,0x1e,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x04,0x03,0x02,0x01,0x01,0x1b,0x01,0x4e,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x07,0x19,0x2b,0x33, 0x11,0x21,0x11,0x23,0x11,0x23,0x11,0x5e,0x01,0x9c,0x5a,0xe8,0x02,0xda,0xfd,0x26,0x02,0x88,0xfd,0x78,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x06,0x00,0x7a,0x00,0x00,0xff,0xff,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x02,0xe4,0x02,0x06,0x00,0x1b,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x21,0x02,0xda,0x02,0x06, 0x00,0x89,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0d,0x00,0x22,0x40,0x1f,0x07,0x01,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x1a,0x4d,0x03,0x01,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x18,0x12,0x04,0x07,0x18,0x2b,0x33,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13, 0x33,0x01,0xbf,0x4a,0xd7,0x62,0x83,0x0d,0x10,0x02,0x02,0x0e,0x0b,0x73,0x62,0xfe,0xf9,0xbd,0x02,0x1d,0xfe,0x9b,0x22,0x3d,0x0f,0x0f,0x3d,0x22,0x01,0x65,0xfd,0x26,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x01,0xdf,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x2e,0xff,0xe7,0x02,0x2a, 0x03,0x02,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0xb2,0x4b,0xb0,0x0f,0x50,0x58,0x40,0x2c,0x00,0x02,0x01,0x01,0x02,0x70,0x0a,0x01,0x05,0x00,0x00,0x05,0x71,0x03,0x01,0x01,0x09,0x01,0x06,0x07,0x01,0x06,0x6a,0x08,0x0b,0x02,0x07,0x00,0x00,0x07,0x59,0x08,0x0b,0x02,0x07,0x07,0x00,0x61,0x04,0x01,0x00,0x07,0x00,0x51,0x1b,0x4b,0xb0, 0x11,0x50,0x58,0x40,0x2b,0x00,0x02,0x01,0x01,0x02,0x70,0x0a,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x09,0x01,0x06,0x07,0x01,0x06,0x6a,0x08,0x0b,0x02,0x07,0x00,0x00,0x07,0x59,0x08,0x0b,0x02,0x07,0x07,0x00,0x61,0x04,0x01,0x00,0x07,0x00,0x51,0x1b,0x40,0x2a,0x00,0x02,0x01,0x02,0x85,0x0a,0x01,0x05,0x00,0x05,0x86,0x03,0x01, 0x01,0x09,0x01,0x06,0x07,0x01,0x06,0x6a,0x08,0x0b,0x02,0x07,0x00,0x00,0x07,0x59,0x08,0x0b,0x02,0x07,0x07,0x00,0x61,0x04,0x01,0x00,0x07,0x00,0x51,0x59,0x59,0x40,0x1a,0x18,0x18,0x00,0x00,0x27,0x26,0x21,0x20,0x18,0x1f,0x18,0x1f,0x1a,0x19,0x00,0x17,0x00,0x17,0x17,0x11,0x11,0x17,0x11,0x0c,0x07,0x1b,0x2b,0x17,0x35,0x22,0x26, 0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x35,0x33,0x15,0x32,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x15,0x27,0x11,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0xff,0x3c,0x5e,0x37,0x36,0x5f,0x3c,0x5a,0x3d,0x5e,0x36,0x37,0x5e,0x3c,0x56,0x38,0x49,0x49,0x8a,0x38,0x49,0x49,0x38,0x19,0x50,0x34,0x5d,0x3f, 0xdb,0x41,0x5f,0x35,0x4b,0x4b,0x35,0x5f,0x41,0xdb,0x3f,0x5d,0x34,0x50,0x9c,0x01,0xe8,0x49,0x40,0xdb,0x3d,0x47,0x47,0x3d,0xdb,0x40,0x49,0x00,0xff,0xff,0x00,0x28,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0xa7,0x00,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x01,0xf9,0x02,0xda,0x00,0x0f,0x00,0x25,0x40,0x22,0x00,0x02,0x00,0x00, 0x04,0x02,0x00,0x67,0x03,0x01,0x01,0x01,0x1a,0x4d,0x05,0x01,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x23,0x13,0x21,0x06,0x07,0x1a,0x2b,0x21,0x11,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x11,0x33,0x11,0x01,0x9f,0x8c,0x5e,0x6a,0x5a,0x3f,0x39,0x82,0x5a,0x01,0x0f,0x60,0x54,0x01,0x17,0xfe, 0xe9,0x30,0x34,0x01,0x7b,0xfd,0x26,0x00,0x00,0x01,0x00,0x5e,0xff,0x74,0x02,0x35,0x02,0xda,0x00,0x0b,0x00,0x29,0x40,0x26,0x06,0x01,0x05,0x02,0x05,0x54,0x03,0x01,0x01,0x01,0x1a,0x4d,0x04,0x01,0x02,0x02,0x00,0x60,0x00,0x00,0x00,0x1b,0x00,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x05, 0x35,0x21,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x01,0xe5,0xfe,0x79,0x5a,0xd8,0x5a,0x4b,0x8c,0x8c,0x02,0xda,0xfd,0x76,0x02,0x8a,0xfd,0x76,0xdc,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0xda,0x00,0x0b,0x00,0x25,0x40,0x22,0x04,0x02,0x02,0x00,0x00,0x1a,0x4d,0x03,0x01,0x01,0x01,0x05,0x60,0x06,0x01,0x05, 0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x33,0x03,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x3e,0x02,0x55,0x77,0x4a,0x76,0x54,0x02,0xda,0xfd,0x74,0x02,0x8c,0xfd,0x74,0x02,0x8c,0xfd,0x26,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x74,0x02,0x53,0x02,0xda,0x00,0x0f, 0x00,0x2d,0x40,0x2a,0x08,0x01,0x07,0x02,0x07,0x54,0x05,0x03,0x02,0x01,0x01,0x1a,0x4d,0x06,0x04,0x02,0x02,0x02,0x00,0x60,0x00,0x00,0x00,0x1b,0x00,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x05,0x35,0x21,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x02, 0x03,0xfe,0x39,0x51,0x78,0x46,0x78,0x51,0x3f,0x8c,0x8c,0x02,0xda,0xfd,0x74,0x02,0x8c,0xfd,0x74,0x02,0x8c,0xfd,0x74,0xda,0x00,0x01,0x00,0x5e,0xff,0x83,0x01,0xfa,0x02,0xda,0x00,0x0b,0x00,0x4d,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x19,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x03,0x01,0x01,0x01,0x1a,0x4d,0x00,0x02,0x02,0x00,0x60,0x04, 0x01,0x00,0x00,0x1b,0x00,0x4e,0x1b,0x40,0x18,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x01,0x1a,0x4d,0x00,0x02,0x02,0x00,0x60,0x04,0x01,0x00,0x00,0x1b,0x00,0x4e,0x59,0x40,0x0e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x17,0x35,0x23,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x23,0x15,0xff, 0xa1,0x5a,0xe8,0x5a,0xa1,0x7d,0x7d,0x02,0xda,0xfd,0x78,0x02,0x88,0xfd,0x26,0x7d,0x00,0x02,0x00,0x5e,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0c,0x00,0x15,0x00,0x2b,0x40,0x28,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x00,0x00,0x00,0x1a,0x4d,0x00,0x03,0x03,0x02,0x60,0x05,0x01,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x15,0x13,0x0f, 0x0d,0x00,0x0c,0x00,0x0b,0x21,0x11,0x06,0x07,0x18,0x2b,0x33,0x11,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x5e,0x5a,0x92,0x42,0x63,0x37,0x37,0x63,0x42,0x92,0x8d,0x3b,0x49,0x49,0x3b,0x8d,0x02,0xda,0xfe,0xd4,0x36,0x60,0x41,0x40,0x61,0x36,0x52,0x49,0x3c,0x3c,0x49, 0x00,0x02,0xff,0xfb,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0e,0x00,0x17,0x00,0x31,0x40,0x2e,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x00,0x04,0x04,0x03,0x5f,0x06,0x01,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x17,0x15,0x11,0x0f,0x00,0x0e,0x00,0x0d,0x21,0x11,0x11,0x07,0x07,0x19, 0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x87,0x8c,0xe6,0x69,0x42,0x63,0x37,0x37,0x63,0x42,0x69,0x64,0x3b,0x49,0x49,0x3b,0x64,0x02,0x88,0x52,0xfe,0xd4,0x36,0x60,0x41,0x40,0x61,0x36,0x52,0x49,0x3c,0x3c,0x49,0x00,0x00,0x00,0x03,0x00,0x3c, 0x00,0x00,0x02,0x1c,0x02,0xda,0x00,0x0b,0x00,0x0f,0x00,0x19,0x00,0x36,0x40,0x33,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x69,0x03,0x01,0x00,0x00,0x1a,0x4d,0x00,0x05,0x05,0x02,0x60,0x08,0x04,0x07,0x03,0x02,0x02,0x1b,0x02,0x4e,0x0c,0x0c,0x00,0x00,0x19,0x17,0x12,0x10,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x00,0x0b,0x00,0x0a,0x21,0x11, 0x09,0x07,0x18,0x2b,0x33,0x11,0x33,0x11,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x21,0x11,0x33,0x11,0x25,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0x3c,0x54,0x2e,0x5a,0x6a,0x6a,0x5a,0x01,0x0a,0x54,0xfe,0x74,0x2e,0x33,0x3d,0x3d,0x33,0x2e,0x02,0xda,0xfe,0xd4,0x66,0x58,0x33,0x57,0x66,0x02,0xda,0xfd,0x26,0x4f,0x3c,0x33, 0x32,0x33,0x3c,0x00,0x00,0x02,0xff,0xfb,0xff,0xfb,0x02,0x44,0x02,0xda,0x00,0x17,0x00,0x21,0x00,0x6a,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x20,0x00,0x02,0x00,0x07,0x00,0x02,0x07,0x69,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x06,0x01,0x00,0x00,0x03,0x61,0x08,0x05,0x02,0x03,0x03,0x1b,0x03,0x4e,0x1b,0x40,0x2a,0x00,0x02, 0x00,0x07,0x00,0x02,0x07,0x69,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x06,0x01,0x00,0x00,0x03,0x5f,0x00,0x03,0x03,0x1b,0x4d,0x06,0x01,0x00,0x00,0x05,0x61,0x08,0x01,0x05,0x05,0x22,0x05,0x4e,0x59,0x40,0x12,0x00,0x00,0x21,0x1f,0x1a,0x18,0x00,0x17,0x00,0x16,0x11,0x25,0x21,0x13,0x21,0x09,0x07,0x1b,0x2b,0x07,0x35, 0x33,0x32,0x36,0x37,0x13,0x21,0x11,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x23,0x11,0x23,0x03,0x06,0x06,0x23,0x25,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0x05,0x12,0x1d,0x1a,0x01,0x05,0x01,0x1e,0x3c,0x48,0x58,0x58,0x48,0x8c,0x7b,0x04,0x01,0x46,0x48,0x01,0x5e,0x3c,0x24,0x28,0x28,0x24,0x3c,0x05,0x50,0x39,0x3e,0x02, 0x18,0xfe,0xd4,0x55,0x46,0x78,0x46,0x55,0x02,0x8f,0xfe,0x33,0x68,0x5f,0x50,0x2c,0x24,0x78,0x24,0x2c,0x00,0x02,0x00,0x35,0x00,0x00,0x02,0x44,0x02,0xda,0x00,0x13,0x00,0x1d,0x00,0x33,0x40,0x30,0x03,0x01,0x01,0x08,0x01,0x05,0x07,0x01,0x05,0x69,0x02,0x01,0x00,0x00,0x1a,0x4d,0x00,0x07,0x07,0x04,0x60,0x09,0x06,0x02,0x04,0x04, 0x1b,0x04,0x4e,0x00,0x00,0x1d,0x1b,0x16,0x14,0x00,0x13,0x00,0x13,0x11,0x25,0x21,0x11,0x11,0x11,0x0a,0x07,0x1c,0x2b,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x23,0x11,0x23,0x11,0x37,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0x35,0x50,0x93,0x50,0x3c,0x4a,0x56,0x56,0x4a,0x8c,0x93, 0xe3,0x3c,0x26,0x2a,0x2a,0x26,0x3c,0x02,0xda,0xfe,0xd4,0x01,0x2c,0xfe,0xd4,0x54,0x47,0x78,0x47,0x54,0x01,0x63,0xfe,0x9d,0x4b,0x2b,0x25,0x78,0x26,0x2a,0x00,0x00,0xff,0xff,0x00,0x48,0xff,0xf6,0x02,0x10,0x02,0xe4,0x02,0x06,0x00,0x81,0x00,0x00,0x00,0x01,0x00,0x5c,0xff,0xf6,0x02,0x0a,0x02,0xe4,0x00,0x1f,0x00,0x48,0x40,0x45, 0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x07,0x05,0x06,0x05,0x07,0x06,0x80,0x00,0x04,0x00,0x05,0x07,0x04,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x1f,0x4d,0x00,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e,0x01,0x00,0x1d,0x1c,0x1a,0x18,0x15,0x14,0x13,0x12,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1f, 0x01,0x1f,0x09,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x01,0x34,0x64,0x74,0x74,0x64,0x62,0x74,0x5a,0x41,0x3b,0x3b,0x43,0xdf,0xdf,0x43,0x3b,0x3b,0x41,0x5a,0x74,0x0a,0x70,0x62,0x01,0x4a, 0x62,0x70,0x71,0x61,0x3e,0x43,0x43,0x3e,0x6f,0x52,0x89,0x3e,0x43,0x43,0x3e,0x61,0x71,0x00,0x00,0x00,0x00,0x01,0x00,0x4e,0xff,0xf6,0x01,0xfc,0x02,0xe4,0x00,0x1f,0x00,0x3b,0x40,0x38,0x00,0x05,0x04,0x03,0x04,0x05,0x03,0x80,0x00,0x00,0x02,0x01,0x02,0x00,0x01,0x80,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x67,0x00,0x04,0x04,0x06, 0x61,0x00,0x06,0x06,0x1f,0x4d,0x00,0x01,0x01,0x07,0x61,0x00,0x07,0x07,0x20,0x07,0x4e,0x25,0x22,0x12,0x23,0x11,0x13,0x22,0x10,0x08,0x07,0x1e,0x2b,0x37,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x26,0x4e,0x5a,0x42, 0x3a,0x3b,0x43,0xdf,0xdf,0x43,0x3b,0x3a,0x42,0x5a,0x74,0x62,0x64,0x74,0x74,0x64,0x62,0x74,0xc8,0x3e,0x43,0x43,0x3e,0x89,0x52,0x6f,0x3e,0x43,0x43,0x3e,0x61,0x71,0x70,0x62,0xfe,0xb6,0x62,0x70,0x71,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x02,0xda,0x02,0x06,0x00,0x43,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef, 0x03,0xb1,0x02,0x26,0x00,0x43,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x2d,0xff,0xf6,0x01,0xef,0x02,0xda,0x02,0x06,0x00,0x4f,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x16,0x00,0x34,0x40,0x31,0x15,0x07,0x02,0x04,0x05,0x01,0x4c,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x02, 0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x1a,0x4d,0x07,0x06,0x02,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x00,0x16,0x00,0x16,0x22,0x13,0x23,0x11,0x11,0x11,0x08,0x07,0x1c,0x2b,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x15,0x37,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x23,0x22,0x07,0x07,0x11,0x6e,0x6e,0x01,0x40,0x78,0x10,0x4c, 0x57,0x47,0x55,0x5a,0x57,0x31,0x3a,0x33,0x02,0x8b,0x4f,0x4f,0xfa,0x11,0x52,0x61,0x52,0xfe,0xbf,0x01,0x2d,0x77,0x3d,0x36,0xfe,0xcf,0x00,0x00,0x00,0x02,0x00,0x3c,0xff,0xf6,0x02,0x3a,0x02,0xe4,0x00,0x15,0x00,0x23,0x00,0x73,0x4b,0xb0,0x18,0x50,0x58,0x40,0x21,0x00,0x04,0x00,0x01,0x06,0x04,0x01,0x67,0x00,0x07,0x07,0x03,0x61, 0x05,0x01,0x03,0x03,0x1a,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x02,0x08,0x02,0x00,0x00,0x20,0x00,0x4e,0x1b,0x40,0x29,0x00,0x04,0x00,0x01,0x06,0x04,0x01,0x67,0x00,0x03,0x03,0x1a,0x4d,0x00,0x07,0x07,0x05,0x61,0x00,0x05,0x05,0x1f,0x4d,0x00,0x02,0x02,0x1b,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e, 0x59,0x40,0x1b,0x17,0x16,0x01,0x00,0x1e,0x1c,0x16,0x23,0x17,0x23,0x10,0x0e,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x15,0x01,0x15,0x0a,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x23,0x11,0x23,0x11,0x33,0x11,0x33,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15, 0x11,0x14,0x16,0x01,0x90,0x4b,0x58,0x5e,0x53,0x53,0x5e,0x58,0x4b,0x4e,0x5c,0x5c,0x4e,0x29,0x2e,0x2e,0x29,0x29,0x2e,0x2e,0x0a,0x64,0x55,0xa2,0xfe,0xaf,0x02,0xda,0xfe,0xc7,0x8a,0x56,0x63,0x63,0x56,0xfe,0x84,0x55,0x64,0x4a,0x3a,0x35,0x01,0x7c,0x35,0x3a,0x3a,0x35,0xfe,0x84,0x35,0x3a,0x00,0x02,0x00,0x38,0x00,0x00,0x01,0xf9, 0x02,0xda,0x00,0x0e,0x00,0x17,0x00,0x38,0x40,0x35,0x01,0x01,0x02,0x04,0x01,0x4c,0x07,0x01,0x04,0x00,0x02,0x01,0x04,0x02,0x67,0x00,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x1a,0x4d,0x06,0x03,0x02,0x01,0x01,0x1b,0x01,0x4e,0x10,0x0f,0x00,0x00,0x13,0x11,0x0f,0x17,0x10,0x17,0x00,0x0e,0x00,0x0e,0x11,0x11,0x27,0x08,0x07,0x19,0x2b, 0x33,0x13,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x11,0x23,0x11,0x23,0x03,0x13,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x38,0x96,0x42,0x4c,0x36,0x62,0x41,0xe0,0x5a,0x74,0x8b,0x79,0x86,0x86,0x37,0x45,0x44,0x01,0x40,0x14,0x6a,0x4a,0x3f,0x5e,0x35,0xfd,0x26,0x01,0x36,0xfe,0xca,0x01,0x86,0x01,0x04,0x47,0x3b,0x3a,0x48,0x00, 0x00,0x01,0x00,0x00,0xff,0x4c,0x02,0x17,0x02,0xda,0x00,0x1e,0x00,0x3e,0x40,0x3b,0x14,0x0b,0x02,0x02,0x01,0x01,0x4c,0x00,0x06,0x00,0x01,0x02,0x06,0x01,0x69,0x05,0x01,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x1a,0x4d,0x00,0x02,0x02,0x1b,0x4d,0x00,0x00,0x00,0x07,0x61,0x08,0x01,0x07,0x07,0x1e,0x07,0x4e,0x00,0x00,0x00,0x1e,0x00, 0x1d,0x23,0x11,0x11,0x11,0x13,0x24,0x21,0x09,0x07,0x1d,0x2b,0x05,0x35,0x33,0x32,0x36,0x35,0x11,0x34,0x23,0x22,0x07,0x07,0x11,0x23,0x11,0x23,0x35,0x21,0x15,0x23,0x15,0x37,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x01,0x04,0x46,0x35,0x3e,0x57,0x31,0x3a,0x33,0x5a,0x6e,0x01,0x40,0x78,0x10,0x4c,0x57,0x47,0x55,0x70,0x5d, 0xb4,0x52,0x3d,0x34,0x01,0x1e,0x77,0x3d,0x36,0xfe,0xcf,0x02,0x8b,0x4f,0x4f,0xfa,0x11,0x52,0x61,0x52,0xfe,0xce,0x58,0x6b,0x00,0x01,0x00,0x1e,0x00,0x00,0x02,0x2b,0x02,0xda,0x00,0x0d,0x00,0x2d,0x40,0x2a,0x04,0x01,0x01,0x05,0x01,0x00,0x06,0x01,0x00,0x67,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x1a,0x4d,0x07,0x01,0x06,0x06, 0x1b,0x06,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x08,0x07,0x1c,0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x15,0x21,0x15,0x33,0x15,0x23,0x11,0x82,0x64,0x64,0x01,0xa9,0xfe,0xb1,0xa0,0xa0,0x01,0x46,0x50,0x01,0x44,0x52,0xf2,0x50,0xfe,0xba,0x00,0x01,0x00,0x51,0xff,0x74,0x02,0x49,0x02,0xda,0x00,0x10, 0x00,0x36,0x40,0x33,0x07,0x01,0x06,0x01,0x01,0x4c,0x00,0x01,0x00,0x06,0x03,0x01,0x06,0x67,0x00,0x03,0x00,0x04,0x03,0x04,0x63,0x02,0x01,0x00,0x00,0x1a,0x4d,0x08,0x07,0x02,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x10,0x00,0x10,0x11,0x11,0x11,0x12,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x33,0x11,0x33,0x11,0x33,0x13,0x33,0x03, 0x13,0x33,0x15,0x23,0x35,0x23,0x03,0x23,0x11,0x51,0x5a,0x6c,0xa2,0x62,0xb5,0x97,0x4c,0x50,0x3b,0xaa,0x69,0x02,0xda,0xfe,0xc6,0x01,0x3a,0xfe,0xa0,0xfe,0xd6,0xdc,0x8c,0x01,0x51,0xfe,0xaf,0x00,0x00,0x00,0x00,0x01,0x00,0x59,0xff,0x74,0x02,0x26,0x02,0xda,0x00,0x0f,0x00,0x30,0x40,0x2d,0x00,0x01,0x00,0x06,0x03,0x01,0x06,0x67, 0x00,0x03,0x00,0x04,0x03,0x04,0x63,0x02,0x01,0x00,0x00,0x1a,0x4d,0x08,0x07,0x02,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x35,0x23,0x11,0x23,0x11,0x59,0x5a,0xea,0x5a,0x2f,0x50,0x39,0xea,0x02,0xda, 0xfe,0xc8,0x01,0x38,0xfd,0x76,0xdc,0x8c,0x01,0x50,0xfe,0xb0,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x02,0xda,0x02,0x06,0x00,0xa8,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x35,0x02,0xda,0x00,0x14,0x00,0x2f,0x40,0x2c,0x08,0x01,0x00,0x01,0x01,0x4c,0x03,0x01,0x00,0x07,0x06,0x02,0x04,0x05,0x00,0x04,0x68,0x02,0x01,0x01, 0x01,0x1a,0x4d,0x00,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x14,0x00,0x14,0x11,0x11,0x11,0x18,0x11,0x11,0x08,0x07,0x1c,0x2b,0x37,0x35,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x33,0x15,0x23,0x15,0x23,0x35,0x7d,0x82,0xdc,0x60,0x8e,0x0c,0x0e,0x02,0x02,0x0f,0x0c,0x8e,0x5d,0xdc,0x82,0x82,0x5a,0xc6, 0x4b,0x01,0xc9,0xfe,0xd4,0x19,0x23,0x08,0x08,0x23,0x19,0x01,0x2c,0xfe,0x37,0x4b,0xc6,0xc6,0x00,0x00,0x00,0x01,0x00,0x41,0xff,0x74,0x02,0x1e,0x02,0xda,0x00,0x13,0x00,0x2e,0x40,0x2b,0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x67,0x00,0x04,0x00,0x05,0x04,0x05,0x63,0x03,0x01,0x01,0x01,0x1a,0x4d,0x07,0x01,0x06,0x06,0x1b,0x06,0x4e, 0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x23,0x13,0x21,0x08,0x07,0x1c,0x2b,0x21,0x11,0x23,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x35,0x01,0x95,0x8c,0x5e,0x6a,0x5a,0x3f,0x39,0x82,0x5a,0x2f,0x50,0x01,0x0f,0x60,0x54,0x01,0x17,0xfe,0xe9,0x30,0x34,0x01,0x7b,0xfd,0x76,0xdc,0x8c, 0x00,0x01,0x00,0x5f,0x00,0x00,0x02,0x0d,0x02,0xda,0x00,0x0f,0x00,0x25,0x40,0x22,0x00,0x00,0x00,0x02,0x01,0x00,0x02,0x67,0x05,0x01,0x04,0x04,0x1a,0x4d,0x03,0x01,0x01,0x01,0x1b,0x01,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x23,0x13,0x21,0x06,0x07,0x1a,0x2b,0x13,0x11,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x23, 0x11,0x23,0x11,0xb9,0x8c,0x5e,0x6a,0x5a,0x3f,0x39,0x82,0x5a,0x02,0xda,0xfe,0xf1,0x60,0x54,0xfe,0xe9,0x01,0x17,0x30,0x34,0xfe,0x85,0x02,0xda,0x00,0x02,0x00,0x54,0xff,0xf6,0x01,0xfe,0x02,0xe4,0x00,0x16,0x00,0x1f,0x00,0x43,0x40,0x40,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x67,0x00,0x02, 0x02,0x04,0x61,0x00,0x04,0x04,0x1f,0x4d,0x08,0x01,0x05,0x05,0x00,0x61,0x07,0x01,0x00,0x00,0x20,0x00,0x4e,0x18,0x17,0x01,0x00,0x1c,0x1b,0x17,0x1f,0x18,0x1f,0x11,0x0f,0x0d,0x0c,0x0a,0x08,0x05,0x04,0x00,0x16,0x01,0x16,0x09,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x21,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33, 0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x23,0x15,0x14,0x16,0x01,0x29,0x62,0x73,0x01,0x50,0x42,0x39,0x39,0x42,0x5a,0x73,0x62,0x62,0x73,0x73,0x62,0x39,0x42,0xf6,0x42,0x0a,0x71,0x61,0xd1,0x7a,0x3b,0x46,0x46,0x3c,0x61,0x71,0x71,0x61,0xfe,0xb6,0x61,0x71,0x50,0x46,0x3c,0x7f,0x7f,0x3c,0x46,0xff,0xff,0x00,0x06, 0x00,0x00,0x02,0x52,0x03,0xb1,0x02,0x26,0x01,0xd1,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x34,0xff,0xf6,0x02,0x16,0x03,0xb1,0x02,0x26,0x01,0xd2,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x03,0xb1,0x02,0x26,0x01,0xd3,0x00,0x00,0x00,0x07,0x06,0x8e, 0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x03,0xb1,0x02,0x26,0x00,0x60,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0xe4,0x00,0x0d,0x00,0x16,0x00,0x1f,0x00,0x39,0x40,0x36,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01, 0x1f,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x20,0x00,0x4e,0x18,0x17,0x01,0x00,0x1c,0x1b,0x17,0x1f,0x18,0x1f,0x14,0x12,0x0f,0x0e,0x08,0x06,0x00,0x0d,0x01,0x0d,0x08,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x03,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x13,0x32, 0x36,0x35,0x35,0x23,0x15,0x14,0x16,0x01,0x2c,0x62,0x70,0x70,0x62,0x62,0x70,0x70,0xdb,0xf2,0x3e,0x3b,0x3b,0x3e,0x79,0x3b,0x3e,0xf2,0x3f,0x0a,0x71,0x62,0x01,0x49,0x62,0x70,0x70,0x62,0xfe,0xb7,0x61,0x72,0x01,0xa8,0x74,0x40,0x43,0x43,0x40,0xfe,0x33,0x44,0x40,0x85,0x85,0x40,0x44,0x00,0xff,0xff,0x00,0x4b,0x00,0x00,0x01,0xf9, 0x03,0xb1,0x02,0x26,0x01,0xe3,0x00,0x00,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x0a,0x00,0x00,0x02,0x4e,0x02,0xda,0x00,0x05,0x00,0x0b,0x00,0x0f,0x00,0x38,0x40,0x35,0x0a,0x07,0x04,0x01,0x04,0x01,0x00,0x01,0x4c,0x04,0x02,0x02,0x00,0x00,0x38,0x4d,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x01,0x39,0x01,0x4e,0x0c, 0x0c,0x06,0x06,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x06,0x0b,0x06,0x0b,0x09,0x08,0x00,0x05,0x00,0x05,0x12,0x09,0x09,0x17,0x2b,0x21,0x03,0x13,0x33,0x03,0x13,0x21,0x13,0x03,0x33,0x13,0x03,0x33,0x11,0x33,0x11,0x01,0xf1,0x8b,0x8b,0x53,0x88,0x92,0xfd,0xbc,0x92,0x88,0x54,0x8a,0x8b,0x9f,0x4c,0x01,0x7c,0x01,0x5e,0xfe,0xa2, 0xfe,0x84,0x01,0x7e,0x01,0x5c,0xfe,0xa2,0xfe,0x84,0x02,0xda,0xfd,0x26,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0xba,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x30,0x03,0xb6,0x00,0x27,0x06,0x91,0x02,0x62,0x00,0x00,0x02,0x06,0x00,0xba,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x74,0x02,0x47, 0x02,0xda,0x00,0x0a,0x00,0x0e,0x00,0x34,0x40,0x31,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x01,0x00,0x02,0x01,0x02,0x63,0x04,0x01,0x00,0x00,0x38,0x4d,0x07,0x05,0x06,0x03,0x03,0x03,0x39,0x03,0x4e,0x0b,0x0b,0x00,0x00,0x0b,0x0e,0x0b,0x0e,0x0d,0x0c,0x00,0x0a,0x00,0x0a,0x11,0x22,0x12,0x08,0x09,0x19,0x2b,0x21,0x03,0x13,0x33, 0x03,0x13,0x35,0x33,0x15,0x23,0x35,0x21,0x11,0x33,0x11,0x01,0xba,0xf9,0xf9,0x67,0xf0,0xc6,0x50,0x50,0xfe,0x61,0x5a,0x01,0x7c,0x01,0x5e,0xfe,0xa2,0xfe,0xd3,0x01,0xdc,0x8c,0x02,0xda,0xfd,0x26,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x14,0x00,0x28,0x40,0x25,0x0b,0x05,0x02,0x00,0x01,0x01,0x4c,0x02, 0x01,0x01,0x01,0x38,0x4d,0x00,0x00,0x00,0x03,0x60,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x14,0x00,0x13,0x18,0x13,0x21,0x05,0x09,0x19,0x2b,0x33,0x35,0x33,0x32,0x37,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x06,0x06,0x23,0x42,0x6a,0x33,0x16,0x14,0xd7,0x62,0x83,0x0d,0x10,0x02,0x02,0x0e, 0x0b,0x73,0x62,0xda,0x13,0x4d,0x31,0x53,0x37,0x33,0x02,0x1d,0xfe,0x9b,0x22,0x3d,0x0f,0x0f,0x3d,0x22,0x01,0x65,0xfd,0x9a,0x37,0x3d,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb6,0x02,0x26,0x02,0x09,0x00,0x00,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03, 0x00,0x1f,0x00,0x77,0x4b,0xb0,0x18,0x50,0x58,0x40,0x24,0x00,0x00,0x00,0x07,0x05,0x00,0x07,0x69,0x00,0x05,0x00,0x04,0x02,0x05,0x04,0x69,0x09,0x01,0x02,0x08,0x01,0x01,0x02,0x01,0x63,0x00,0x03,0x03,0x06,0x5f,0x00,0x06,0x06,0x3b,0x03,0x4e,0x1b,0x40,0x2b,0x00,0x00,0x00,0x07,0x05,0x00,0x07,0x69,0x00,0x06,0x00,0x03,0x04,0x06, 0x03,0x67,0x00,0x05,0x00,0x04,0x02,0x05,0x04,0x69,0x09,0x01,0x02,0x01,0x01,0x02,0x59,0x09,0x01,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x02,0x01,0x4f,0x59,0x40,0x1a,0x05,0x04,0x00,0x00,0x1a,0x18,0x16,0x15,0x13,0x11,0x0c,0x0a,0x08,0x07,0x04,0x1f,0x05,0x1f,0x00,0x03,0x00,0x03,0x11,0x0a,0x09,0x17,0x2b,0x11,0x11,0x21,0x11,0x01, 0x32,0x36,0x35,0x23,0x14,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x33,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x02,0x58,0xfe,0xdc,0x62,0x74,0x5a,0x41,0x3b,0x3b,0x43,0x43,0x3b,0x3b,0x41,0x5a,0x74,0x62,0x64,0x74,0x74,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x01,0x22,0x71,0x61,0x3e,0x43,0x43,0x3e,0x01,0x4a, 0x3e,0x43,0x43,0x3e,0x61,0x71,0x70,0x62,0xfe,0xb6,0x62,0x70,0xff,0xff,0x00,0x43,0xff,0xf6,0x01,0xfc,0x02,0x30,0x02,0x06,0x00,0xbd,0x00,0x00,0x00,0x02,0x00,0x56,0xff,0xf6,0x02,0x02,0x02,0xe4,0x00,0x16,0x00,0x24,0x00,0x36,0x40,0x33,0x0d,0x01,0x02,0x03,0x01,0x4c,0x09,0x08,0x02,0x01,0x4a,0x00,0x01,0x00,0x03,0x02,0x01,0x03, 0x69,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x20,0x00,0x4e,0x18,0x17,0x01,0x00,0x1f,0x1d,0x17,0x24,0x18,0x24,0x11,0x0f,0x00,0x16,0x01,0x16,0x06,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x37,0x15,0x07,0x06,0x15,0x15,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26, 0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x63,0x73,0x6d,0x6a,0xb6,0xa8,0x9a,0x0c,0x51,0x3e,0x5f,0x67,0x73,0x63,0x3a,0x42,0x42,0x3a,0x3a,0x42,0x42,0x0a,0x74,0x63,0xfd,0x79,0x86,0x0a,0x11,0x59,0x0f,0x0e,0xa4,0x2d,0x30,0x37,0x74,0x61,0x62,0x63,0x74,0x50,0x49,0x3e,0x62,0x3e,0x49,0x49,0x3e,0x62,0x3e,0x49,0x00,0x00,0x00, 0x00,0x03,0x00,0x5c,0x00,0x00,0x02,0x0d,0x02,0x26,0x00,0x0f,0x00,0x18,0x00,0x21,0x00,0x39,0x40,0x36,0x08,0x01,0x05,0x02,0x01,0x4c,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x00,0x04,0x04,0x01,0x5f,0x06,0x01,0x01,0x01,0x1b,0x01,0x4e,0x00,0x00,0x21,0x1f,0x1b,0x19,0x18,0x16, 0x12,0x10,0x00,0x0f,0x00,0x0e,0x21,0x07,0x07,0x17,0x2b,0x33,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x5c,0xf1,0x53,0x60,0x3f,0x32,0x3c,0x42,0x66,0x57,0x9c,0x99,0x2a,0x30,0x30,0x2a,0x99,0x9c,0x2f, 0x35,0x35,0x2f,0x9c,0x02,0x26,0x4a,0x40,0x2e,0x3f,0x04,0x04,0x04,0x4c,0x3c,0x47,0x54,0x01,0x40,0x28,0x24,0x23,0x28,0xfe,0x78,0x2c,0x28,0x27,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x87,0x00,0x00,0x02,0x12,0x02,0x26,0x00,0x05,0x00,0x1f,0x40,0x1c,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x03,0x01,0x02,0x02,0x1b,0x02, 0x4e,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x07,0x18,0x2b,0x33,0x11,0x21,0x15,0x21,0x11,0x87,0x01,0x8b,0xfe,0xcf,0x02,0x26,0x52,0xfe,0x2c,0x00,0x00,0x00,0xff,0xff,0x00,0x87,0x00,0x00,0x02,0x12,0x03,0x11,0x02,0x26,0x02,0x0f,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x80,0x00,0x00,0x00,0x01,0x00,0x82,0x00,0x00,0x02,0x0d, 0x02,0x8f,0x00,0x07,0x00,0x47,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x17,0x00,0x01,0x00,0x00,0x01,0x70,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x04,0x01,0x03,0x03,0x1b,0x03,0x4e,0x1b,0x40,0x16,0x00,0x01,0x00,0x01,0x85,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x04,0x01,0x03,0x03,0x1b,0x03,0x4e,0x59,0x40,0x0c, 0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x21,0x35,0x33,0x15,0x21,0x11,0x82,0x01,0x36,0x55,0xfe,0xcf,0x02,0x26,0x69,0xbb,0xfe,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,0x1b,0xff,0x74,0x02,0x3a,0x02,0x26,0x00,0x0f,0x00,0x17,0x00,0x33,0x40,0x30,0x08,0x05,0x02,0x03,0x00,0x03,0x53,0x00,0x07,0x07, 0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x06,0x02,0x02,0x00,0x00,0x04,0x5f,0x00,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x13,0x12,0x11,0x10,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x15,0x11,0x09,0x07,0x1b,0x2b,0x17,0x35,0x33,0x3e,0x02,0x37,0x37,0x21,0x11,0x33,0x15,0x23,0x35,0x21,0x15,0x37,0x33,0x11,0x23,0x07,0x0e,0x02,0x1b,0x2a,0x0d, 0x19,0x12,0x01,0x04,0x01,0x6d,0x4b,0x50,0xfe,0x81,0x34,0xf6,0xbe,0x02,0x01,0x10,0x17,0x8c,0xdc,0x0c,0x31,0x58,0x48,0xf9,0xfe,0x2a,0xdc,0x8c,0x8c,0xdc,0x01,0x88,0xad,0x47,0x58,0x31,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x02,0x30,0x02,0x06,0x00,0xe1,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf6,0x02,0x04,0x03,0x09,0x02,0x26, 0x00,0xe1,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x0f,0x00,0x00,0x02,0x49,0x02,0x26,0x00,0x15,0x00,0x36,0x40,0x33,0x0c,0x01,0x02,0x06,0x01,0x01,0x4c,0x03,0x01,0x01,0x08,0x01,0x06,0x05,0x01,0x06,0x67,0x04,0x02,0x02,0x00,0x00,0x1c,0x4d,0x0a,0x09,0x07,0x03,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00, 0x15,0x00,0x15,0x11,0x11,0x11,0x12,0x11,0x11,0x11,0x11,0x12,0x0b,0x07,0x1f,0x2b,0x33,0x13,0x03,0x33,0x17,0x33,0x35,0x33,0x15,0x33,0x37,0x33,0x03,0x13,0x23,0x27,0x23,0x15,0x23,0x35,0x23,0x07,0x0f,0x7b,0x73,0x56,0x65,0x35,0x4a,0x33,0x68,0x55,0x73,0x7b,0x59,0x69,0x36,0x4a,0x36,0x6a,0x01,0x1c,0x01,0x0a,0xed,0xed,0xed,0xed, 0xfe,0xf9,0xfe,0xe1,0xfb,0xfb,0xfb,0xfb,0x00,0x01,0x00,0x46,0xff,0xf9,0x02,0x0d,0x02,0x2d,0x00,0x2d,0x00,0x4e,0x40,0x4b,0x26,0x01,0x03,0x04,0x01,0x4c,0x00,0x06,0x05,0x04,0x05,0x06,0x04,0x80,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x04,0x00,0x03,0x01,0x04,0x03,0x67,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x21,0x4d, 0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x22,0x00,0x4e,0x01,0x00,0x21,0x1e,0x1c,0x1b,0x19,0x16,0x12,0x10,0x0f,0x0d,0x09,0x06,0x04,0x03,0x00,0x2d,0x01,0x2c,0x09,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x22,0x06,0x07, 0x23,0x36,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x23,0x01,0x0a,0x5a,0x6a,0x5a,0x39,0x31,0x35,0x34,0x3c,0x3c,0x34,0x78,0x75,0x2f,0x37,0x36,0x2f,0x2f,0x2c,0x35,0x02,0x5a,0x02,0x66,0x55,0x2f,0x5a,0x69,0x3f,0x32,0x3c,0x42,0x6f,0x5f,0x07,0x55,0x49,0x23,0x2a,0x2d,0x27,0x29,0x2f,0x4e,0x2a, 0x24,0x23,0x29,0x22,0x1d,0x41,0x4d,0x4a,0x45,0x2e,0x3f,0x04,0x04,0x04,0x4c,0x3c,0x4b,0x59,0x00,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x01,0xfc,0x02,0x26,0x00,0x0f,0x00,0x24,0x40,0x21,0x0e,0x06,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x1c,0x4d,0x04,0x03,0x02,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11, 0x15,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x33,0x11,0x14,0x06,0x07,0x13,0x33,0x11,0x23,0x11,0x34,0x36,0x37,0x03,0x5c,0x56,0x03,0x08,0xe5,0x70,0x56,0x03,0x08,0xe5,0x02,0x26,0xfe,0xd8,0x2b,0x5c,0x1d,0x01,0xcc,0xfd,0xda,0x01,0x29,0x2c,0x5c,0x1d,0xfe,0x32,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfc,0x03,0x11,0x02,0x26, 0x02,0x17,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0x00,0x01,0x00,0x67,0x00,0x00,0x02,0x35,0x02,0x26,0x00,0x0c,0x00,0x2d,0x40,0x2a,0x07,0x01,0x04,0x01,0x01,0x4c,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x02,0x01,0x00,0x00,0x1c,0x4d,0x06,0x05,0x02,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x00,0x0c,0x00,0x0c,0x11,0x12, 0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x33,0x11,0x33,0x15,0x33,0x37,0x33,0x03,0x13,0x23,0x27,0x23,0x15,0x67,0x5a,0x6b,0x98,0x67,0xb2,0xbc,0x69,0x9f,0x6c,0x02,0x26,0xe3,0xe3,0xfe,0xf8,0xfe,0xe2,0xf1,0xf1,0xff,0xff,0x00,0x67,0x00,0x00,0x02,0x35,0x03,0x11,0x02,0x26,0x02,0x19,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x65,0x00,0x00, 0x00,0x01,0x00,0x19,0xff,0xf9,0x01,0xfc,0x02,0x26,0x00,0x0f,0x00,0x4d,0x4b,0xb0,0x21,0x50,0x58,0x40,0x17,0x00,0x03,0x03,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x00,0x00,0x00,0x02,0x61,0x05,0x04,0x02,0x02,0x02,0x1b,0x02,0x4e,0x1b,0x40,0x1b,0x00,0x03,0x03,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x00,0x02,0x02,0x1b,0x4d,0x00,0x00, 0x00,0x04,0x61,0x05,0x01,0x04,0x04,0x22,0x04,0x4e,0x59,0x40,0x0d,0x00,0x00,0x00,0x0f,0x00,0x0e,0x11,0x11,0x13,0x21,0x06,0x07,0x1a,0x2b,0x17,0x35,0x33,0x32,0x36,0x37,0x13,0x21,0x11,0x23,0x11,0x23,0x07,0x06,0x06,0x23,0x19,0x0f,0x2e,0x25,0x01,0x06,0x01,0x7a,0x5a,0xc7,0x05,0x03,0x4e,0x58,0x07,0x54,0x48,0x5d,0x01,0x34,0xfd, 0xda,0x01,0xd4,0xe6,0x83,0x72,0x00,0x00,0x00,0x01,0x00,0x48,0x00,0x00,0x02,0x10,0x02,0x26,0x00,0x12,0x00,0x2e,0x40,0x2b,0x0e,0x0b,0x03,0x03,0x03,0x00,0x01,0x4c,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x01,0x01,0x00,0x00,0x1c,0x4d,0x05,0x04,0x02,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x00,0x12,0x00,0x12,0x15,0x11,0x12,0x11, 0x06,0x07,0x1a,0x2b,0x33,0x11,0x33,0x13,0x13,0x33,0x11,0x23,0x35,0x34,0x36,0x37,0x03,0x23,0x03,0x16,0x16,0x15,0x15,0x48,0x76,0x6c,0x6d,0x79,0x56,0x03,0x0a,0x75,0x52,0x6e,0x09,0x03,0x02,0x26,0xfe,0xf3,0x01,0x0d,0xfd,0xda,0x55,0x8f,0xd0,0x46,0xfe,0xdd,0x01,0x13,0x3e,0xc0,0x97,0x55,0x00,0x01,0x00,0x5c,0x00,0x00,0x01,0xfc, 0x02,0x26,0x00,0x0b,0x00,0x27,0x40,0x24,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x02,0x01,0x00,0x00,0x1c,0x4d,0x06,0x05,0x02,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x33,0x11,0x33,0x15,0x33,0x35,0x33,0x11,0x23,0x35,0x23,0x15,0x5c,0x5a,0xec,0x5a,0x5a,0xec,0x02, 0x26,0xe3,0xe3,0xfd,0xda,0xf1,0xf1,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x02,0x2e,0x02,0x06,0x01,0x22,0x00,0x00,0x00,0x01,0x00,0x5c,0x00,0x00,0x01,0xfc,0x02,0x26,0x00,0x07,0x00,0x21,0x40,0x1e,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x04,0x03,0x02,0x01,0x01,0x1b,0x01,0x4e,0x00,0x00,0x00,0x07,0x00,0x07, 0x11,0x11,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x21,0x11,0x23,0x11,0x23,0x11,0x5c,0x01,0xa0,0x5a,0xec,0x02,0x26,0xfd,0xda,0x01,0xd4,0xfe,0x2c,0xff,0xff,0x00,0x5c,0xff,0x4c,0x02,0x01,0x02,0x30,0x02,0x06,0x01,0x3d,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x0b,0x02,0x30,0x02,0x06,0x00,0xd7,0x00,0x00,0x00,0x01,0x00,0x37, 0x00,0x00,0x02,0x21,0x02,0x26,0x00,0x07,0x00,0x21,0x40,0x1e,0x02,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x04,0x01,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x07,0x19,0x2b,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xff,0xc8,0x01,0xea,0xc8,0x01,0xd4,0x52,0x52,0xfe,0x2c,0x00,0x00, 0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x26,0x02,0x06,0x01,0x70,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0x70,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x30,0xff,0x4c,0x02,0x28,0x02,0xda,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0x42,0x40,0x3f,0x00,0x02,0x02,0x1a, 0x4d,0x09,0x01,0x06,0x06,0x01,0x61,0x03,0x01,0x01,0x01,0x1c,0x4d,0x08,0x0b,0x02,0x07,0x07,0x00,0x61,0x04,0x01,0x00,0x00,0x1b,0x4d,0x0a,0x01,0x05,0x05,0x1e,0x05,0x4e,0x18,0x18,0x00,0x00,0x27,0x26,0x21,0x20,0x18,0x1f,0x18,0x1f,0x1a,0x19,0x00,0x17,0x00,0x17,0x17,0x11,0x11,0x17,0x11,0x0c,0x07,0x1b,0x2b,0x17,0x35,0x2e,0x02, 0x35,0x35,0x34,0x36,0x36,0x37,0x35,0x33,0x15,0x1e,0x02,0x15,0x15,0x14,0x06,0x06,0x07,0x15,0x27,0x11,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0xff,0x3d,0x5e,0x34,0x34,0x5e,0x3d,0x5a,0x3e,0x5d,0x34,0x34,0x5d,0x3e,0x53,0x3c,0x45,0x45,0x88,0x3c,0x45,0x45,0x3c,0xb4,0xb4,0x02,0x36,0x5f,0x3d,0x80, 0x3d,0x5e,0x36,0x01,0xb4,0xb4,0x01,0x36,0x5e,0x3d,0x80,0x3d,0x5f,0x36,0x02,0xb4,0xfb,0x01,0x98,0x46,0x3b,0x94,0x3c,0x47,0x47,0x3c,0x94,0x3b,0x46,0x00,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0x26,0x02,0x06,0x01,0x6f,0x00,0x00,0x00,0x01,0x00,0x4e,0x00,0x00,0x01,0xf4,0x02,0x26,0x00,0x0f,0x00,0x25,0x40,0x22, 0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x67,0x03,0x01,0x01,0x01,0x1c,0x4d,0x05,0x01,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x23,0x13,0x21,0x06,0x07,0x1a,0x2b,0x21,0x35,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x33,0x11,0x33,0x11,0x01,0x9a,0x93,0x55,0x64,0x5a,0x35,0x2d,0x90,0x5a,0xbf,0x5a,0x4c, 0xc1,0xc1,0x27,0x2e,0x01,0x16,0xfd,0xda,0x00,0x01,0x00,0x5c,0xff,0x74,0x02,0x3a,0x02,0x26,0x00,0x0b,0x00,0x29,0x40,0x26,0x06,0x01,0x05,0x02,0x05,0x54,0x03,0x01,0x01,0x01,0x1c,0x4d,0x04,0x01,0x02,0x02,0x00,0x60,0x00,0x00,0x00,0x1b,0x00,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x05, 0x35,0x21,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x01,0xea,0xfe,0x72,0x5a,0xdf,0x5a,0x4b,0x8c,0x8c,0x02,0x26,0xfe,0x2a,0x01,0xd6,0xfe,0x2a,0xdc,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x26,0x00,0x0b,0x00,0x25,0x40,0x22,0x04,0x02,0x02,0x00,0x00,0x1c,0x4d,0x03,0x01,0x01,0x01,0x05,0x60,0x06,0x01,0x05, 0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x33,0x03,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x3e,0x02,0x55,0x77,0x4a,0x76,0x54,0x02,0x26,0xfe,0x26,0x01,0xda,0xfe,0x26,0x01,0xda,0xfd,0xda,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x74,0x02,0x53,0x02,0x26,0x00,0x0f, 0x00,0x2d,0x40,0x2a,0x08,0x01,0x07,0x02,0x07,0x54,0x05,0x03,0x02,0x01,0x01,0x1c,0x4d,0x06,0x04,0x02,0x02,0x02,0x00,0x60,0x00,0x00,0x00,0x1b,0x00,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x05,0x35,0x21,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x02, 0x03,0xfe,0x39,0x51,0x76,0x46,0x76,0x51,0x43,0x8c,0x8c,0x02,0x26,0xfe,0x26,0x01,0xda,0xfe,0x26,0x01,0xda,0xfe,0x26,0xd8,0x00,0x01,0x00,0x5c,0xff,0x83,0x01,0xfc,0x02,0x26,0x00,0x0b,0x00,0x4d,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x19,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x03,0x01,0x01,0x01,0x1c,0x4d,0x00,0x02,0x02,0x00,0x60,0x04, 0x01,0x00,0x00,0x1b,0x00,0x4e,0x1b,0x40,0x18,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x01,0x1c,0x4d,0x00,0x02,0x02,0x00,0x60,0x04,0x01,0x00,0x00,0x1b,0x00,0x4e,0x59,0x40,0x0e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x07,0x1b,0x2b,0x17,0x35,0x23,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x23,0x15,0xff, 0xa3,0x5a,0xec,0x5a,0xa3,0x7d,0x7d,0x02,0x26,0xfe,0x2c,0x01,0xd4,0xfd,0xda,0x7d,0x00,0x02,0x00,0x69,0x00,0x00,0x02,0x28,0x02,0x26,0x00,0x0a,0x00,0x13,0x00,0x2b,0x40,0x28,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x00,0x00,0x00,0x1c,0x4d,0x00,0x03,0x03,0x02,0x60,0x05,0x01,0x02,0x02,0x1b,0x02,0x4e,0x00,0x00,0x13,0x11,0x0d, 0x0b,0x00,0x0a,0x00,0x09,0x21,0x11,0x06,0x07,0x18,0x2b,0x33,0x11,0x33,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x69,0x5a,0x9d,0x5d,0x6b,0x6c,0x5c,0x9d,0x9d,0x34,0x37,0x37,0x34,0x9d,0x02,0x26,0xca,0x5d,0x51,0x50,0x5e,0x52,0x2f,0x2d,0x2d,0x2f,0x00,0x00,0x00,0x00,0x02,0x00,0x19, 0x00,0x00,0x02,0x3a,0x02,0x26,0x00,0x0c,0x00,0x15,0x00,0x31,0x40,0x2e,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x00,0x04,0x04,0x03,0x5f,0x06,0x01,0x03,0x03,0x1b,0x03,0x4e,0x00,0x00,0x15,0x13,0x0f,0x0d,0x00,0x0c,0x00,0x0b,0x21,0x11,0x11,0x07,0x07,0x19,0x2b,0x33,0x11,0x23, 0x35,0x33,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0xa5,0x8c,0xe6,0x73,0x5d,0x6b,0x6c,0x5c,0x73,0x73,0x34,0x37,0x37,0x34,0x73,0x01,0xd6,0x50,0xca,0x5d,0x51,0x50,0x5e,0x52,0x2f,0x2d,0x2d,0x2f,0x00,0x00,0x03,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x26,0x00,0x0a,0x00,0x0e,0x00,0x17, 0x00,0x36,0x40,0x33,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x69,0x03,0x01,0x00,0x00,0x1c,0x4d,0x00,0x05,0x05,0x02,0x60,0x08,0x04,0x07,0x03,0x02,0x02,0x1b,0x02,0x4e,0x0b,0x0b,0x00,0x00,0x17,0x15,0x11,0x0f,0x0b,0x0e,0x0b,0x0e,0x0d,0x0c,0x00,0x0a,0x00,0x09,0x21,0x11,0x09,0x07,0x18,0x2b,0x33,0x11,0x33,0x15,0x33,0x32,0x16,0x15, 0x14,0x06,0x23,0x21,0x11,0x33,0x11,0x25,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x3c,0x54,0x37,0x59,0x67,0x67,0x59,0x01,0x01,0x54,0xfe,0x74,0x37,0x34,0x3c,0x3c,0x34,0x37,0x02,0x26,0xca,0x5e,0x50,0x50,0x5e,0x02,0x26,0xfd,0xda,0x48,0x37,0x2f,0x2f,0x37,0x00,0x00,0x00,0x02,0x00,0x05,0xff,0xfb,0x02,0x42,0x02,0x26,0x00,0x17, 0x00,0x21,0x00,0x9c,0x4b,0xb0,0x27,0x50,0x58,0x40,0x20,0x00,0x02,0x00,0x07,0x00,0x02,0x07,0x69,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x06,0x01,0x00,0x00,0x03,0x61,0x08,0x05,0x02,0x03,0x03,0x1b,0x03,0x4e,0x1b,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x2b,0x00,0x02,0x00,0x07,0x00,0x02,0x07,0x69,0x00,0x04,0x04,0x01,0x5f, 0x00,0x01,0x01,0x1c,0x4d,0x00,0x00,0x00,0x03,0x61,0x08,0x05,0x02,0x03,0x03,0x1b,0x4d,0x00,0x06,0x06,0x03,0x61,0x08,0x05,0x02,0x03,0x03,0x1b,0x03,0x4e,0x1b,0x40,0x28,0x00,0x02,0x00,0x07,0x00,0x02,0x07,0x69,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x01,0x1c,0x4d,0x00,0x06,0x06,0x03,0x5f,0x00,0x03,0x03,0x1b,0x4d,0x00,0x00,0x00, 0x05,0x61,0x08,0x01,0x05,0x05,0x22,0x05,0x4e,0x59,0x59,0x40,0x12,0x00,0x00,0x21,0x1f,0x1a,0x18,0x00,0x17,0x00,0x16,0x11,0x25,0x21,0x13,0x21,0x09,0x07,0x1b,0x2b,0x17,0x35,0x33,0x32,0x36,0x37,0x13,0x21,0x15,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x23,0x11,0x23,0x03,0x06,0x06,0x23,0x25,0x33,0x32,0x36,0x35,0x35,0x34,0x26, 0x23,0x23,0x05,0x12,0x19,0x1e,0x01,0x04,0x01,0x11,0x3e,0x48,0x58,0x58,0x48,0x8b,0x71,0x03,0x01,0x4d,0x41,0x01,0x50,0x3e,0x24,0x27,0x27,0x24,0x3e,0x05,0x55,0x3e,0x34,0x01,0x64,0xc8,0x55,0x45,0x2a,0x45,0x55,0x01,0xd9,0xfe,0xe9,0x5b,0x6c,0x4f,0x2c,0x24,0x2a,0x24,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,0x3e,0x00,0x00,0x02,0x42, 0x02,0x26,0x00,0x13,0x00,0x1d,0x00,0x33,0x40,0x30,0x03,0x01,0x01,0x08,0x01,0x05,0x07,0x01,0x05,0x69,0x02,0x01,0x00,0x00,0x1c,0x4d,0x00,0x07,0x07,0x04,0x60,0x09,0x06,0x02,0x04,0x04,0x1b,0x04,0x4e,0x00,0x00,0x1d,0x1b,0x16,0x14,0x00,0x13,0x00,0x13,0x11,0x25,0x21,0x11,0x11,0x11,0x0a,0x07,0x1c,0x2b,0x33,0x11,0x33,0x15,0x33, 0x35,0x33,0x15,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x23,0x11,0x23,0x11,0x37,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0x3e,0x53,0x8b,0x49,0x3d,0x48,0x58,0x58,0x48,0x86,0x8b,0xd4,0x3d,0x24,0x29,0x29,0x24,0x3d,0x02,0x26,0xc8,0xc8,0xc8,0x55,0x46,0x28,0x46,0x55,0x01,0x13,0xfe,0xed,0x4b,0x2c,0x24,0x28,0x24,0x2c,0x00, 0xff,0xff,0x00,0x55,0xff,0xf8,0x02,0x03,0x02,0x2e,0x02,0x06,0x01,0x44,0x00,0x00,0x00,0x01,0x00,0x57,0xff,0xf6,0x02,0x08,0x02,0x30,0x00,0x1f,0x00,0x48,0x40,0x45,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x07,0x05,0x06,0x05,0x07,0x06,0x80,0x00,0x04,0x00,0x05,0x07,0x04,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01, 0x21,0x4d,0x00,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e,0x01,0x00,0x1d,0x1c,0x1a,0x18,0x15,0x14,0x13,0x12,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1f,0x01,0x1f,0x09,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33, 0x32,0x36,0x37,0x33,0x06,0x06,0x01,0x32,0x64,0x77,0x77,0x64,0x5f,0x74,0x03,0x5a,0x03,0x41,0x38,0x3b,0x46,0xb7,0xb7,0x46,0x3b,0x38,0x41,0x03,0x5a,0x03,0x74,0x0a,0x70,0x62,0x96,0x62,0x70,0x65,0x54,0x31,0x38,0x44,0x3e,0x1e,0x50,0x29,0x3d,0x44,0x39,0x31,0x55,0x65,0x00,0x01,0x00,0x50,0xff,0xf6,0x02,0x01,0x02,0x30,0x00,0x1f, 0x00,0x48,0x40,0x45,0x00,0x06,0x05,0x04,0x05,0x06,0x04,0x80,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x04,0x00,0x03,0x01,0x04,0x03,0x67,0x00,0x05,0x05,0x07,0x61,0x00,0x07,0x07,0x21,0x4d,0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e,0x01,0x00,0x1a,0x18,0x16,0x15,0x13,0x11,0x0e,0x0d,0x0c,0x0b,0x08,0x06, 0x04,0x03,0x00,0x1f,0x01,0x1f,0x09,0x07,0x16,0x2b,0x05,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x23,0x35,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x01,0x26,0x5f,0x74,0x03,0x5a,0x03,0x42,0x37,0x3b,0x46,0xb7,0xb7,0x46,0x3b,0x37,0x42,0x03,0x5a,0x03,0x74,0x5f, 0x64,0x77,0x77,0x0a,0x65,0x55,0x31,0x39,0x44,0x3d,0x29,0x50,0x1e,0x3e,0x44,0x38,0x31,0x54,0x65,0x70,0x62,0x96,0x62,0x70,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x09,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x2b,0x03,0x09,0x02,0x26,0x01,0x00,0x00,0x00, 0x00,0x07,0x06,0x68,0x02,0x67,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0x4c,0x01,0xc3,0x03,0x09,0x02,0x26,0x01,0x0e,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0xa8,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0xfe,0x02,0xda,0x00,0x1c,0x00,0x39,0x40,0x36,0x09,0x01,0x05,0x06,0x01,0x4c,0x02,0x01,0x00,0x09,0x08,0x02,0x03,0x04,0x00,0x03, 0x67,0x00,0x04,0x00,0x06,0x05,0x04,0x06,0x69,0x00,0x01,0x01,0x1a,0x4d,0x07,0x01,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x1c,0x00,0x1c,0x13,0x23,0x13,0x24,0x11,0x11,0x11,0x11,0x0a,0x07,0x1e,0x2b,0x11,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06, 0x15,0x11,0x23,0x11,0x5c,0x5a,0xa8,0xa8,0x01,0x07,0x4c,0x3f,0x53,0x62,0x5a,0x3f,0x36,0x38,0x41,0x5a,0x02,0x3a,0x4b,0x55,0x55,0x4b,0xb9,0x37,0x3c,0x66,0x58,0xfe,0xca,0x01,0x2c,0x3b,0x41,0x46,0x40,0xfe,0xde,0x02,0x3a,0x00,0x00,0x02,0x00,0x3c,0xff,0xf6,0x02,0x30,0x02,0x30,0x00,0x15,0x00,0x23,0x00,0x73,0x4b,0xb0,0x18,0x50, 0x58,0x40,0x21,0x00,0x04,0x00,0x01,0x06,0x04,0x01,0x67,0x00,0x07,0x07,0x03,0x61,0x05,0x01,0x03,0x03,0x1c,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x02,0x08,0x02,0x00,0x00,0x20,0x00,0x4e,0x1b,0x40,0x29,0x00,0x04,0x00,0x01,0x06,0x04,0x01,0x67,0x00,0x03,0x03,0x1c,0x4d,0x00,0x07,0x07,0x05,0x61,0x00,0x05,0x05,0x21,0x4d,0x00,0x02, 0x02,0x1b,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x20,0x00,0x4e,0x59,0x40,0x1b,0x17,0x16,0x01,0x00,0x1e,0x1c,0x16,0x23,0x17,0x23,0x10,0x0e,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x15,0x01,0x15,0x0a,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x23,0x15,0x23,0x11,0x33,0x15,0x33,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x8b,0x47,0x53,0x62,0x53,0x53,0x62,0x53,0x47,0x4c,0x59,0x59,0x4b,0x26,0x2b,0x2b,0x26,0x25,0x2a,0x2a,0x0a,0x5c,0x4e,0x53,0xf3,0x02,0x26,0xeb,0x4b,0x4e,0x5c,0x5c,0x4e,0xe6,0x4e,0x5c,0x46,0x36,0x2e,0xe6,0x2e,0x36,0x36,0x2e, 0xe6,0x2e,0x36,0x00,0x00,0x02,0x00,0x3f,0x00,0x00,0x01,0xfc,0x02,0x26,0x00,0x0d,0x00,0x16,0x00,0x38,0x40,0x35,0x01,0x01,0x02,0x04,0x01,0x4c,0x07,0x01,0x04,0x00,0x02,0x01,0x04,0x02,0x67,0x00,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x1c,0x4d,0x06,0x03,0x02,0x01,0x01,0x1b,0x01,0x4e,0x0f,0x0e,0x00,0x00,0x12,0x10,0x0e,0x16,0x0f, 0x16,0x00,0x0d,0x00,0x0d,0x11,0x11,0x26,0x08,0x07,0x19,0x2b,0x33,0x37,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x11,0x23,0x35,0x23,0x07,0x13,0x33,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0x3f,0x8d,0x3a,0x46,0x6c,0x5c,0xe8,0x5a,0x74,0x82,0x68,0x8e,0x8e,0x31,0x3b,0x3b,0xd6,0x0e,0x59,0x3d,0x50,0x5c,0xfd,0xda,0xd0,0xd0,0x01,0x1e,0xb9, 0x31,0x2c,0x2b,0x31,0x00,0x01,0x00,0x00,0xff,0x4c,0x01,0xfc,0x02,0xda,0x00,0x24,0x00,0x43,0x40,0x40,0x19,0x01,0x02,0x01,0x01,0x4c,0x06,0x01,0x04,0x07,0x01,0x03,0x08,0x04,0x03,0x67,0x00,0x08,0x00,0x01,0x02,0x08,0x01,0x69,0x00,0x05,0x05,0x1a,0x4d,0x00,0x02,0x02,0x1b,0x4d,0x00,0x00,0x00,0x09,0x61,0x0a,0x01,0x09,0x09,0x1e, 0x09,0x4e,0x00,0x00,0x00,0x24,0x00,0x23,0x24,0x11,0x11,0x11,0x11,0x11,0x13,0x25,0x21,0x0b,0x07,0x1f,0x2b,0x17,0x35,0x33,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0xfa,0x25,0x3e,0x45,0x3d,0x36, 0x38,0x3f,0x5a,0x5e,0x5e,0x5a,0xa6,0xa6,0x01,0x06,0x4b,0x3f,0x53,0x60,0x78,0x65,0xb4,0x53,0x43,0x3d,0x01,0x0d,0x3b,0x41,0x46,0x40,0xfe,0xde,0x02,0x3a,0x4b,0x55,0x55,0x4b,0xb9,0x37,0x3c,0x66,0x58,0xfe,0xe9,0x61,0x72,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x21,0x02,0x26,0x00,0x0d,0x00,0x2d,0x40,0x2a,0x04,0x01,0x01,0x05, 0x01,0x00,0x06,0x01,0x00,0x67,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x1c,0x4d,0x07,0x01,0x06,0x06,0x1b,0x06,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x08,0x07,0x1c,0x2b,0x33,0x35,0x23,0x35,0x33,0x35,0x21,0x15,0x21,0x15,0x33,0x15,0x23,0x15,0x96,0x64,0x64,0x01,0x8b,0xfe,0xcf,0xaf,0xaf,0xeb,0x52, 0xe9,0x52,0x97,0x52,0xeb,0x00,0x00,0x00,0x00,0x01,0x00,0x5c,0xff,0x74,0x02,0x3a,0x02,0x26,0x00,0x10,0x00,0x36,0x40,0x33,0x07,0x01,0x06,0x01,0x01,0x4c,0x00,0x01,0x00,0x06,0x03,0x01,0x06,0x67,0x00,0x03,0x00,0x04,0x03,0x04,0x63,0x02,0x01,0x00,0x00,0x1c,0x4d,0x08,0x07,0x02,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x10,0x00, 0x10,0x11,0x11,0x11,0x12,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x33,0x11,0x33,0x15,0x33,0x37,0x33,0x03,0x17,0x33,0x15,0x23,0x35,0x23,0x27,0x23,0x15,0x5c,0x5a,0x62,0xa0,0x67,0xb9,0x88,0x4c,0x50,0x31,0xa0,0x63,0x02,0x26,0xe3,0xe3,0xfe,0xfa,0xd0,0xdc,0x8c,0xf5,0xf5,0x00,0x01,0x00,0x5b,0xff,0x74,0x02,0x26,0x02,0x26,0x00,0x0f, 0x00,0x30,0x40,0x2d,0x00,0x01,0x00,0x06,0x03,0x01,0x06,0x67,0x00,0x03,0x00,0x04,0x03,0x04,0x63,0x02,0x01,0x00,0x00,0x1c,0x4d,0x08,0x07,0x02,0x05,0x05,0x1b,0x05,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x07,0x1d,0x2b,0x33,0x11,0x33,0x15,0x33,0x35,0x33,0x11,0x33,0x15,0x23,0x35,0x23,0x35, 0x23,0x15,0x5b,0x5a,0xe8,0x5a,0x2f,0x50,0x39,0xe8,0x02,0x26,0xe5,0xe5,0xfe,0x2a,0xdc,0x8c,0xef,0xef,0xff,0xff,0x00,0x3c,0xff,0x4c,0x02,0x1c,0x02,0x26,0x02,0x06,0x02,0x77,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x4c,0x02,0x1c,0x02,0x26,0x00,0x14,0x00,0x2f,0x40,0x2c,0x08,0x01,0x00,0x01,0x01,0x4c,0x03,0x01,0x00,0x07,0x06,0x02, 0x04,0x05,0x00,0x04,0x68,0x02,0x01,0x01,0x01,0x1c,0x4d,0x00,0x05,0x05,0x1e,0x05,0x4e,0x00,0x00,0x00,0x14,0x00,0x14,0x11,0x11,0x11,0x18,0x11,0x11,0x08,0x07,0x1c,0x2b,0x17,0x35,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x33,0x15,0x23,0x15,0x23,0x35,0x7d,0x82,0xc3,0x5f,0x7c,0x0c,0x0a,0x03,0x03,0x09, 0x0b,0x79,0x5c,0xc3,0x82,0x82,0x5a,0x4b,0x4b,0x02,0x26,0xfe,0x93,0x22,0x35,0x11,0x11,0x35,0x22,0x01,0x6d,0xfd,0xda,0x4b,0x69,0x69,0x00,0x00,0x00,0x01,0x00,0x49,0xff,0x74,0x02,0x1c,0x02,0x26,0x00,0x13,0x00,0x2e,0x40,0x2b,0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x67,0x00,0x04,0x00,0x05,0x04,0x05,0x63,0x03,0x01,0x01,0x01,0x1c, 0x4d,0x07,0x01,0x06,0x06,0x1b,0x06,0x4e,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x23,0x13,0x21,0x08,0x07,0x1c,0x2b,0x21,0x35,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x35,0x01,0x95,0x93,0x55,0x64,0x5a,0x35,0x2d,0x90,0x5a,0x2d,0x50,0xbf,0x5a,0x4c,0xc1,0xc1,0x27,0x2e,0x01, 0x16,0xfe,0x2a,0xdc,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x64,0x00,0x00,0x02,0x0a,0x02,0x26,0x00,0x0f,0x00,0x25,0x40,0x22,0x00,0x00,0x00,0x02,0x01,0x00,0x02,0x67,0x05,0x01,0x04,0x04,0x1c,0x4d,0x03,0x01,0x01,0x01,0x1b,0x01,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x23,0x13,0x21,0x06,0x07,0x1a,0x2b,0x13,0x15,0x33,0x32,0x16, 0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x23,0x11,0x23,0x11,0xbe,0x93,0x56,0x63,0x5a,0x35,0x2d,0x90,0x5a,0x02,0x26,0xbf,0x59,0x4d,0xc1,0xc1,0x27,0x2e,0xfe,0xea,0x02,0x26,0x00,0x00,0x00,0x00,0x02,0x00,0x54,0xff,0xf6,0x02,0x04,0x02,0x30,0x00,0x17,0x00,0x20,0x00,0x3e,0x40,0x3b,0x00,0x04,0x03,0x02,0x03,0x04,0x02,0x80,0x00,0x02, 0x00,0x05,0x06,0x02,0x05,0x67,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x00,0x21,0x4d,0x00,0x06,0x06,0x01,0x61,0x00,0x01,0x01,0x20,0x01,0x4e,0x01,0x00,0x1e,0x1c,0x19,0x18,0x15,0x14,0x12,0x10,0x0d,0x0c,0x08,0x06,0x00,0x17,0x01,0x17,0x08,0x07,0x16,0x2b,0x01,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x26,0x35,0x35,0x21, 0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x13,0x21,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x01,0x2c,0x62,0x76,0x76,0x62,0x41,0x61,0x36,0x01,0x58,0x45,0x3b,0x32,0x41,0x07,0x5a,0x09,0x74,0xd7,0xff,0x00,0x43,0x3d,0x3d,0x43,0x02,0x30,0x75,0x67,0x82,0x67,0x75,0x34,0x5f,0x3f,0x62,0x34,0x3d,0x47,0x27,0x21,0x45,0x51,0xfe, 0xb4,0x1c,0x41,0x47,0x47,0x41,0x00,0x00,0xff,0xff,0x00,0x0f,0x00,0x00,0x02,0x49,0x03,0x09,0x02,0x26,0x02,0x15,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x46,0xff,0xf9,0x02,0x0d,0x03,0x09,0x02,0x26,0x02,0x16,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfc, 0x03,0x09,0x02,0x26,0x02,0x17,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x09,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0x00,0x03,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0x30,0x00,0x0d,0x00,0x16,0x00,0x1f,0x00,0x39,0x40,0x36,0x00,0x02,0x00,0x05, 0x04,0x02,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x21,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x20,0x00,0x4e,0x18,0x17,0x01,0x00,0x1c,0x1b,0x17,0x1f,0x18,0x1f,0x14,0x12,0x0f,0x0e,0x08,0x06,0x00,0x0d,0x01,0x0d,0x08,0x07,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14, 0x06,0x03,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x13,0x32,0x36,0x35,0x35,0x23,0x15,0x14,0x16,0x01,0x2c,0x61,0x71,0x71,0x61,0x60,0x72,0x72,0xda,0xf4,0x3f,0x3b,0x3a,0x40,0x7a,0x3b,0x3f,0xf4,0x40,0x0a,0x72,0x61,0x95,0x62,0x70,0x72,0x5f,0x96,0x61,0x72,0x01,0x45,0x23,0x3f,0x44,0x44,0x3f,0xfe,0xe7,0x44,0x40,0x27,0x27,0x40, 0x44,0x00,0x00,0x00,0xff,0xff,0x00,0x4e,0x00,0x00,0x01,0xf4,0x03,0x09,0x02,0x26,0x02,0x27,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0x42,0x01,0xfe,0x03,0x09,0x02,0x26,0x01,0x91,0x00,0x00,0x00,0x07,0x06,0x69,0x02,0xe3,0x00,0x00,0x00,0x03,0x00,0x0a,0x00,0x00,0x02,0x4e,0x02,0x26,0x00,0x05, 0x00,0x0b,0x00,0x0f,0x00,0x38,0x40,0x35,0x0a,0x07,0x04,0x01,0x04,0x01,0x00,0x01,0x4c,0x04,0x02,0x02,0x00,0x00,0x3b,0x4d,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x01,0x39,0x01,0x4e,0x0c,0x0c,0x06,0x06,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x06,0x0b,0x06,0x0b,0x09,0x08,0x00,0x05,0x00,0x05,0x12,0x09,0x09,0x17,0x2b,0x21,0x03, 0x13,0x33,0x03,0x13,0x21,0x13,0x03,0x33,0x13,0x03,0x33,0x11,0x33,0x11,0x01,0xf7,0x97,0x87,0x53,0x86,0x9a,0xfd,0xbc,0x9a,0x86,0x53,0x87,0x97,0xa5,0x4c,0x01,0x1a,0x01,0x0c,0xfe,0xf5,0xfe,0xe5,0x01,0x1b,0x01,0x0b,0xfe,0xf4,0xfe,0xe6,0x02,0x26,0xfd,0xda,0x00,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x37,0x02,0x26,0x00,0x05, 0x00,0x09,0x00,0x2b,0x40,0x28,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x02,0x01,0x00,0x00,0x3b,0x4d,0x05,0x03,0x04,0x03,0x01,0x01,0x39,0x01,0x4e,0x06,0x06,0x00,0x00,0x06,0x09,0x06,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x12,0x06,0x09,0x17,0x2b,0x21,0x03,0x13,0x33,0x03,0x13,0x21,0x11,0x33,0x11,0x01,0xc2,0xf6,0xe6,0x71,0xe5,0xf9, 0xfe,0x2d,0x5a,0x01,0x1a,0x01,0x0c,0xfe,0xf5,0xfe,0xe5,0x02,0x26,0xfd,0xda,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x37,0x03,0x11,0x02,0x26,0x02,0x4b,0x00,0x00,0x00,0x07,0x06,0x6b,0x02,0x62,0x00,0x00,0x00,0x02,0x00,0x64,0xff,0x74,0x02,0x3a,0x02,0x26,0x00,0x09,0x00,0x0d,0x00,0x34,0x40,0x31,0x04,0x01,0x02,0x01,0x00,0x01, 0x4c,0x00,0x01,0x00,0x02,0x01,0x02,0x63,0x04,0x01,0x00,0x00,0x3b,0x4d,0x07,0x05,0x06,0x03,0x03,0x03,0x39,0x03,0x4e,0x0a,0x0a,0x00,0x00,0x0a,0x0d,0x0a,0x0d,0x0c,0x0b,0x00,0x09,0x00,0x09,0x11,0x12,0x12,0x08,0x09,0x19,0x2b,0x21,0x03,0x13,0x33,0x03,0x17,0x33,0x15,0x23,0x35,0x21,0x11,0x33,0x11,0x01,0xc2,0xf6,0xe6,0x71,0xe5, 0xb3,0x49,0x50,0xfe,0x7a,0x5a,0x01,0x1a,0x01,0x0c,0xfe,0xf5,0xcb,0xdc,0x8c,0x02,0x26,0xfd,0xda,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x26,0x02,0x06,0x01,0xa7,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0x4c,0x02,0x22,0x03,0x11,0x02,0x26,0x01,0xa7,0x00,0x00,0x00,0x07,0x06,0x70,0x02,0x58,0x00,0x00,0x00,0x02,0x00,0x00, 0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x1f,0x00,0x48,0x40,0x45,0x00,0x00,0x00,0x07,0x05,0x00,0x07,0x69,0x00,0x06,0x00,0x03,0x04,0x06,0x03,0x67,0x00,0x05,0x00,0x04,0x02,0x05,0x04,0x69,0x09,0x01,0x02,0x01,0x01,0x02,0x59,0x09,0x01,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x02,0x01,0x4f,0x05,0x04,0x00,0x00,0x1a,0x18,0x16, 0x15,0x13,0x11,0x0c,0x0a,0x08,0x07,0x04,0x1f,0x05,0x1f,0x00,0x03,0x00,0x03,0x11,0x0a,0x09,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0x32,0x36,0x37,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x02,0x58,0xfe,0xdc,0x5f,0x75,0x03,0x5a,0x03,0x42,0x38,0x3b, 0x47,0x47,0x3b,0x38,0x42,0x03,0x5a,0x03,0x75,0x5f,0x64,0x78,0x78,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x01,0x22,0x66,0x58,0x34,0x3a,0x44,0x3e,0x97,0x3e,0x43,0x39,0x35,0x58,0x66,0x70,0x62,0x96,0x62,0x70,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x06,0x00,0x01,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x12, 0x02,0xda,0x02,0x06,0x00,0x1a,0x00,0x00,0xff,0xff,0x00,0x82,0x00,0x00,0x02,0x2b,0x02,0xda,0x02,0x06,0x01,0xcb,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x03,0x00,0x0c,0x00,0x26,0x40,0x23,0x0a,0x01,0x02,0x00,0x01,0x4c,0x00,0x00,0x00,0x28,0x4d,0x00,0x02,0x02,0x01,0x60,0x03,0x01,0x01,0x01,0x29,0x01, 0x4e,0x00,0x00,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x04,0x08,0x17,0x2b,0x33,0x13,0x33,0x13,0x01,0x03,0x21,0x03,0x26,0x26,0x27,0x06,0x06,0x32,0xbe,0x79,0xbd,0xfe,0xe2,0x66,0x01,0x15,0x67,0x0d,0x12,0x05,0x04,0x13,0x02,0xda,0xfd,0x26,0x01,0xf0,0xfe,0x60,0x01,0x9f,0x34,0x5b,0x16,0x16,0x5a,0x00,0x00,0x00,0xff,0xff,0x00,0x64, 0x00,0x00,0x02,0x08,0x02,0xda,0x02,0x06,0x00,0x25,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x00,0x02,0x03,0x02,0xda,0x02,0x06,0x00,0xb1,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x01,0xfb,0x02,0xda,0x02,0x06,0x00,0x40,0x00,0x00,0x00,0x03,0x00,0x58,0xff,0xf6,0x02,0x00,0x02,0xe4,0x00,0x0d,0x00,0x1b,0x00,0x1f,0x00,0x3e,0x40,0x3b, 0x00,0x04,0x08,0x01,0x05,0x02,0x04,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x2e,0x4d,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x2f,0x00,0x4e,0x1c,0x1c,0x0f,0x0e,0x01,0x00,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x09,0x08,0x16,0x2b,0x05,0x22,0x26,0x35, 0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x27,0x35,0x33,0x15,0x01,0x2c,0x62,0x72,0x72,0x62,0x62,0x72,0x72,0x62,0x3b,0x3f,0x3f,0x3b,0x3a,0x40,0x40,0x20,0xb4,0x0a,0x70,0x62,0x01,0x4a,0x62,0x70,0x6f,0x62,0xfe,0xb5,0x62,0x70,0x51,0x43,0x3e,0x01, 0x4a,0x3e,0x43,0x43,0x3e,0xfe,0xb6,0x3e,0x43,0xfe,0x52,0x52,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x02,0xda,0x02,0x06,0x00,0x43,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0x51,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0c,0x00,0x1b,0x40,0x18,0x00,0x00,0x00,0x28, 0x4d,0x03,0x02,0x02,0x01,0x01,0x29,0x01,0x4e,0x00,0x00,0x00,0x0c,0x00,0x0c,0x11,0x11,0x04,0x08,0x18,0x2b,0x33,0x13,0x33,0x13,0x23,0x03,0x26,0x26,0x31,0x30,0x06,0x07,0x03,0x32,0xbe,0x79,0xbd,0x5b,0x7b,0x11,0x13,0x13,0x11,0x7a,0x02,0xda,0xfd,0x26,0x01,0xef,0x47,0x5e,0x5d,0x47,0xfe,0x10,0x00,0x00,0x00,0xff,0xff,0x00,0x48, 0x00,0x00,0x02,0x10,0x02,0xda,0x02,0x06,0x00,0x59,0x00,0x00,0xff,0xff,0x00,0x5a,0x00,0x00,0x01,0xfe,0x02,0xda,0x02,0x06,0x00,0x5a,0x00,0x00,0x00,0x03,0x00,0x50,0x00,0x00,0x02,0x08,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x3d,0x40,0x3a,0x00,0x02,0x07,0x01,0x03,0x04,0x02,0x03,0x67,0x06,0x01,0x01,0x01,0x00,0x5f,0x00, 0x00,0x00,0x28,0x4d,0x00,0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x05,0x29,0x05,0x4e,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x08,0x17,0x2b,0x13,0x35,0x21,0x15,0x01,0x35,0x21,0x15,0x01,0x35,0x21,0x15,0x50,0x01,0xb8,0xfe,0x66,0x01,0x7c,0xfe,0x66, 0x01,0xb8,0x02,0x88,0x52,0x52,0xfe,0xc1,0x52,0x52,0xfe,0xb7,0x52,0x52,0x00,0x00,0xff,0xff,0x00,0x58,0xff,0xf6,0x02,0x00,0x02,0xe4,0x02,0x06,0x00,0x60,0x00,0x00,0xff,0xff,0x00,0x5e,0x00,0x00,0x01,0xfa,0x02,0xda,0x02,0x06,0x01,0xdb,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x06,0x00,0x7a,0x00,0x00, 0x00,0x01,0x00,0x4b,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0b,0x00,0x34,0x40,0x31,0x08,0x02,0x02,0x02,0x01,0x01,0x4c,0x03,0x01,0x01,0x01,0x01,0x02,0x02,0x4b,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x28,0x4d,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x03,0x29,0x03,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x12,0x11,0x14,0x05,0x08, 0x19,0x2b,0x33,0x35,0x13,0x03,0x35,0x21,0x15,0x21,0x13,0x03,0x21,0x15,0x4b,0xe8,0xe8,0x01,0xdb,0xfe,0x8f,0xeb,0xec,0x01,0x72,0x50,0x01,0x23,0x01,0x17,0x50,0x50,0xfe,0xed,0xfe,0xd9,0x50,0x00,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x21,0x02,0xda,0x02,0x06,0x00,0x89,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35, 0x02,0xda,0x02,0x06,0x00,0xa8,0x00,0x00,0xff,0xff,0x00,0x2e,0xff,0xe7,0x02,0x2a,0x03,0x02,0x02,0x06,0x01,0xe1,0x00,0x00,0xff,0xff,0x00,0x28,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0xa7,0x00,0x00,0x00,0x01,0x00,0x36,0x00,0x00,0x02,0x22,0x02,0xda,0x00,0x19,0x00,0x2b,0x40,0x28,0x04,0x01,0x02,0x06,0x01,0x00,0x07,0x02, 0x00,0x6a,0x05,0x03,0x02,0x01,0x01,0x28,0x4d,0x08,0x01,0x07,0x07,0x29,0x07,0x4e,0x00,0x00,0x00,0x19,0x00,0x19,0x14,0x13,0x11,0x11,0x13,0x14,0x11,0x09,0x08,0x1d,0x2b,0x33,0x35,0x22,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x11,0x33,0x11,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x06,0x23,0x15,0xff,0x3c,0x5a,0x33,0x54, 0x43,0x38,0x4e,0x38,0x43,0x54,0x32,0x5b,0x3c,0xaa,0x34,0x5d,0x3f,0x01,0x60,0xfe,0xa0,0x3d,0x45,0x01,0xe2,0xfe,0x1e,0x45,0x3d,0x01,0x60,0xfe,0xa0,0x3f,0x5d,0x34,0xaa,0x00,0x00,0x00,0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x27,0x02,0xe4,0x00,0x27,0x00,0x5f,0x4b,0xb0,0x2a,0x50,0x58,0x40,0x20,0x06,0x01,0x04,0x05,0x00,0x00,0x04, 0x72,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x2e,0x4d,0x02,0x01,0x00,0x00,0x03,0x60,0x08,0x07,0x02,0x03,0x03,0x29,0x03,0x4e,0x1b,0x40,0x21,0x06,0x01,0x04,0x05,0x00,0x05,0x04,0x00,0x80,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x2e,0x4d,0x02,0x01,0x00,0x00,0x03,0x60,0x08,0x07,0x02,0x03,0x03,0x29,0x03,0x4e,0x59,0x40,0x10, 0x00,0x00,0x00,0x27,0x00,0x27,0x15,0x25,0x11,0x11,0x27,0x28,0x11,0x09,0x08,0x1d,0x2b,0x33,0x35,0x33,0x35,0x2e,0x02,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x06,0x07,0x15,0x33,0x15,0x23,0x35,0x32,0x36,0x35,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x15,0x32,0x91,0x18,0x36,0x25,0x77,0x65,0x65, 0x77,0x25,0x35,0x19,0x92,0xd3,0x28,0x32,0x47,0x3b,0x3b,0x47,0x32,0x28,0x50,0x05,0x03,0x23,0x45,0x35,0x01,0x18,0x62,0x75,0x75,0x62,0xfe,0xe8,0x35,0x44,0x23,0x03,0x06,0x50,0x6e,0x49,0x39,0x01,0x1d,0x3e,0x49,0x49,0x3e,0xfe,0xe3,0x39,0x49,0x6e,0xff,0xff,0x00,0x0a,0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x26,0x00,0x01,0x00,0x00, 0x00,0x07,0x06,0xb1,0xff,0x29,0x00,0x00,0xff,0xff,0xff,0x8d,0x00,0x00,0x02,0x08,0x02,0xda,0x02,0x26,0x00,0x25,0x00,0x00,0x00,0x07,0x06,0xb1,0xfe,0xac,0x00,0x00,0xff,0xff,0xff,0x8d,0x00,0x00,0x01,0xfb,0x02,0xda,0x00,0x27,0x06,0xb1,0xfe,0xac,0x00,0x00,0x02,0x06,0x00,0x40,0x00,0x00,0xff,0xff,0xff,0x8d,0x00,0x00,0x01,0xef, 0x02,0xda,0x00,0x27,0x06,0xb1,0xfe,0xac,0x00,0x00,0x02,0x06,0x00,0x43,0x00,0x00,0xff,0xff,0xff,0xb0,0xff,0xf6,0x02,0x00,0x02,0xe4,0x00,0x27,0x06,0xb1,0xfe,0xcf,0x00,0x00,0x02,0x06,0x00,0x60,0x00,0x00,0xff,0xff,0xff,0x83,0x00,0x00,0x02,0x35,0x02,0xda,0x00,0x27,0x06,0xb1,0xfe,0xa2,0x00,0x00,0x02,0x06,0x00,0xa8,0x00,0x00, 0xff,0xff,0xff,0xb0,0x00,0x00,0x02,0x27,0x02,0xe4,0x02,0x26,0x02,0x68,0x00,0x00,0x00,0x07,0x06,0xb1,0xfe,0xcf,0x00,0x00,0xff,0xff,0x00,0x69,0x00,0x00,0x01,0xef,0x03,0xb1,0x00,0x27,0x06,0x8e,0x02,0x58,0x00,0x00,0x02,0x06,0x00,0x43,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x02,0x35,0x03,0xb1,0x00,0x27,0x06,0x8e,0x02,0x58, 0x00,0x00,0x02,0x06,0x00,0xa8,0x00,0x00,0x00,0x01,0x00,0x5c,0xff,0x4c,0x02,0x44,0x02,0xda,0x00,0x17,0x00,0x42,0x40,0x3f,0x07,0x01,0x07,0x01,0x01,0x4c,0x00,0x03,0x07,0x06,0x07,0x03,0x06,0x80,0x00,0x01,0x00,0x07,0x03,0x01,0x07,0x67,0x02,0x01,0x00,0x00,0x28,0x4d,0x09,0x08,0x02,0x06,0x06,0x29,0x4d,0x00,0x05,0x05,0x04,0x61, 0x00,0x04,0x04,0x2d,0x04,0x4e,0x00,0x00,0x00,0x17,0x00,0x17,0x11,0x12,0x21,0x23,0x12,0x11,0x11,0x11,0x0a,0x08,0x1e,0x2b,0x33,0x11,0x33,0x11,0x33,0x13,0x33,0x03,0x13,0x33,0x15,0x14,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x23,0x03,0x23,0x11,0x5c,0x5a,0x6c,0xa2,0x62,0xb5,0x9b,0x38,0x5f,0x5c,0x1d,0x1d,0x2d,0x38,0x25,0xaa, 0x69,0x02,0xda,0xfe,0xc6,0x01,0x3a,0xfe,0xa0,0xfe,0xcd,0x47,0x58,0x5c,0x4f,0x37,0x2e,0x01,0x51,0xfe,0xaf,0x00,0x00,0x00,0xff,0xff,0x00,0x5d,0x00,0x00,0x02,0x30,0x02,0xda,0x02,0x06,0x00,0xba,0x00,0x00,0x00,0x02,0x00,0x5d,0xff,0x4c,0x02,0x44,0x02,0xda,0x00,0x10,0x00,0x14,0x00,0x40,0x40,0x3d,0x0a,0x07,0x02,0x03,0x02,0x01, 0x4c,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x05,0x01,0x02,0x02,0x38,0x4d,0x08,0x06,0x02,0x01,0x01,0x39,0x4d,0x00,0x00,0x00,0x04,0x61,0x07,0x01,0x04,0x04,0x3d,0x04,0x4e,0x11,0x11,0x00,0x00,0x11,0x14,0x11,0x14,0x13,0x12,0x00,0x10,0x00,0x0f,0x12,0x12,0x12,0x21,0x09,0x09,0x1a,0x2b,0x05,0x35,0x33,0x32,0x36,0x35,0x23,0x03, 0x13,0x33,0x03,0x13,0x33,0x15,0x14,0x06,0x23,0x25,0x11,0x33,0x11,0x01,0x6c,0x1d,0x2d,0x38,0x2f,0xf9,0xf9,0x67,0xf0,0xcb,0x43,0x5f,0x5c,0xfe,0xd4,0x5a,0xb4,0x4f,0x37,0x2e,0x01,0x7c,0x01,0x5e,0xfe,0xa2,0xfe,0xcb,0x47,0x58,0x5c,0xb4,0x02,0xda,0xfd,0x26,0x00,0x00,0x00,0x02,0x00,0x55,0xff,0xf6,0x01,0xfc,0x02,0x30,0x00,0x13, 0x00,0x21,0x00,0x67,0xb6,0x10,0x0a,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x19,0x00,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01,0x31,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x03,0x06,0x02,0x00,0x00,0x2f,0x00,0x4e,0x1b,0x40,0x21,0x00,0x02,0x02,0x2b,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x31,0x4d,0x00,0x03, 0x03,0x29,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x2f,0x00,0x4e,0x59,0x40,0x17,0x15,0x14,0x01,0x00,0x1c,0x1a,0x14,0x21,0x15,0x21,0x0f,0x0e,0x0d,0x0c,0x08,0x06,0x00,0x13,0x01,0x13,0x08,0x08,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x27,0x33,0x11,0x23,0x35,0x23,0x06,0x06,0x27, 0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x0c,0x52,0x65,0x64,0x53,0x3e,0x50,0x07,0x03,0x02,0x5a,0x5a,0x01,0x07,0x50,0x20,0x38,0x40,0x40,0x38,0x39,0x42,0x42,0x0a,0x6e,0x5e,0xa1,0x5f,0x6e,0x3e,0x35,0x69,0xfd,0xda,0x69,0x36,0x3d,0x4e,0x46,0x3e,0x96,0x3e,0x46,0x44,0x40,0x96,0x40,0x44,0x00,0x00, 0x00,0x02,0x00,0x5c,0xff,0x4c,0x02,0x1a,0x02,0xe4,0x00,0x1b,0x00,0x31,0x00,0x48,0x40,0x45,0x0c,0x01,0x04,0x05,0x18,0x01,0x03,0x04,0x02,0x4c,0x00,0x05,0x00,0x04,0x03,0x05,0x04,0x69,0x00,0x06,0x06,0x00,0x61,0x00,0x00,0x00,0x2e,0x4d,0x08,0x01,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x2f,0x4d,0x07,0x01,0x02,0x02,0x2d,0x02,0x4e, 0x1d,0x1c,0x00,0x00,0x2c,0x2a,0x26,0x24,0x23,0x21,0x1c,0x31,0x1d,0x31,0x00,0x1b,0x00,0x1b,0x2e,0x24,0x09,0x08,0x18,0x2b,0x17,0x11,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x1e,0x02,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x15,0x37,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x35, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x5c,0x34,0x5e,0x3d,0x3d,0x5b,0x34,0x40,0x33,0x2d,0x43,0x26,0x35,0x60,0x3f,0x3c,0x4d,0x07,0x03,0x03,0x86,0x3a,0x48,0x48,0x3b,0x37,0x27,0x34,0x40,0x40,0x34,0x34,0x41,0x4b,0xb4,0x02,0xc5,0x3f,0x5f,0x35,0x2d,0x51,0x35,0x38,0x56,0x0d,0x03,0x06,0x36,0x53,0x33,0x41,0x63,0x37,0x3c, 0x34,0x7a,0xa0,0xfc,0x4f,0x3f,0x3f,0x4f,0x4c,0x3f,0x33,0x33,0x3f,0x48,0x3b,0xfe,0xc5,0x3f,0x4f,0x00,0x00,0x01,0x00,0x3c,0xff,0x4c,0x02,0x1c,0x02,0x26,0x00,0x0e,0x00,0x23,0x40,0x20,0x0d,0x07,0x01,0x03,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x00,0x2b,0x4d,0x03,0x01,0x02,0x02,0x2d,0x02,0x4e,0x00,0x00,0x00,0x0e,0x00,0x0e,0x18, 0x12,0x04,0x08,0x18,0x2b,0x17,0x35,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x15,0xff,0xc3,0x5f,0x7c,0x0c,0x0a,0x03,0x03,0x09,0x0b,0x79,0x5c,0xc3,0xb4,0xb4,0x02,0x26,0xfe,0x93,0x22,0x35,0x11,0x11,0x35,0x22,0x01,0x6d,0xfd,0xda,0xb4,0x00,0x00,0x00,0x02,0x00,0x54,0xff,0xf6,0x02,0x04,0x02,0xda,0x00,0x16, 0x00,0x24,0x00,0x3f,0x40,0x3c,0x0c,0x01,0x01,0x03,0x01,0x4c,0x00,0x01,0x00,0x05,0x04,0x01,0x05,0x69,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x28,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x2f,0x00,0x4e,0x18,0x17,0x01,0x00,0x1f,0x1d,0x17,0x24,0x18,0x24,0x10,0x0f,0x0e,0x0d,0x08,0x07,0x00,0x16,0x01,0x16,0x08, 0x08,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x33,0x26,0x26,0x27,0x35,0x21,0x15,0x21,0x1e,0x02,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x61,0x77,0x31,0x58,0x3a,0x06,0x22,0x57,0x38,0x01,0x89,0xfe,0xdc,0x61,0x89,0x49,0x76,0x62,0x39,0x43,0x1b,0x23,0x3f, 0x37,0x46,0x45,0x0a,0x73,0x64,0x61,0x3f,0x5e,0x35,0x1c,0x42,0x2a,0x52,0x4b,0x43,0x78,0x86,0x59,0x82,0x7d,0x50,0x51,0x5e,0x3f,0x58,0x29,0x4b,0x3c,0x61,0x40,0x47,0x00,0x01,0x00,0x4b,0xff,0xf9,0x02,0x12,0x02,0x2d,0x00,0x2d,0x00,0x52,0x40,0x4f,0x00,0x03,0x04,0x05,0x04,0x03,0x05,0x80,0x00,0x01,0x05,0x06,0x05,0x01,0x06,0x80, 0x00,0x08,0x06,0x07,0x06,0x08,0x07,0x80,0x00,0x05,0x00,0x06,0x08,0x05,0x06,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x31,0x4d,0x00,0x07,0x07,0x00,0x62,0x09,0x01,0x00,0x00,0x32,0x00,0x4e,0x02,0x00,0x2b,0x2a,0x28,0x25,0x21,0x1f,0x1e,0x1c,0x18,0x15,0x13,0x12,0x10,0x0d,0x07,0x06,0x00,0x2d,0x02,0x2d,0x0a,0x08,0x16,0x2b, 0x05,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x01,0x4e,0x35,0x5f,0x6f,0x42,0x3c,0x32,0x3f,0x69,0x5a,0x2f,0x56,0x66,0x01,0x5a,0x01,0x36, 0x2c,0x2f,0x2e,0x37,0x37,0x2f,0x75,0x78,0x34,0x3c,0x3c,0x34,0x35,0x31,0x39,0x5a,0x6a,0x07,0x59,0x4b,0x3c,0x4c,0x04,0x04,0x04,0x3f,0x2e,0x45,0x4a,0x4d,0x41,0x1d,0x22,0x29,0x23,0x24,0x2a,0x4e,0x2f,0x29,0x27,0x2d,0x2a,0x23,0x49,0x55,0x00,0x00,0x00,0x01,0x00,0x69,0xff,0x47,0x02,0x30,0x02,0xda,0x00,0x1e,0x00,0x18,0x40,0x15, 0x12,0x01,0x02,0x00,0x49,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x28,0x00,0x4e,0x11,0x1e,0x02,0x08,0x18,0x2b,0x05,0x27,0x37,0x36,0x35,0x34,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x21,0x35,0x21,0x15,0x07,0x06,0x06,0x15,0x14,0x17,0x17,0x16,0x16,0x15,0x14,0x07,0x01,0xe4,0x46,0x2e,0x0a,0x22,0x84,0x65,0x62,0x62,0x6d, 0x86,0xfe,0xba,0x01,0xb3,0xba,0x5a,0x52,0x89,0x81,0x2f,0x32,0x1b,0xb9,0x2a,0x49,0x10,0x0e,0x1a,0x0b,0x26,0x1d,0x62,0x49,0x43,0x8d,0x5c,0x71,0x52,0x5a,0xa6,0x50,0x6f,0x2f,0x4d,0x28,0x25,0x0d,0x3c,0x26,0x27,0x29,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfe,0x02,0x30,0x02,0x06,0x01,0x1b,0x00,0x00,0x00,0x03,0x00,0x58, 0xff,0xf6,0x02,0x00,0x02,0xda,0x00,0x0d,0x00,0x16,0x00,0x1f,0x00,0x39,0x40,0x36,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x28,0x4d,0x07,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x2f,0x00,0x4e,0x18,0x17,0x01,0x00,0x1c,0x1b,0x17,0x1f,0x18,0x1f,0x14,0x12,0x0f,0x0e,0x08,0x06,0x00, 0x0d,0x01,0x0d,0x08,0x08,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x03,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x13,0x32,0x36,0x35,0x35,0x23,0x15,0x14,0x16,0x01,0x2c,0x62,0x72,0x72,0x62,0x62,0x72,0x72,0xdc,0xf4,0x3f,0x3b,0x3a,0x40,0x7a,0x3b,0x3f,0xf4,0x40,0x0a,0x70,0x62,0x01,0x40, 0x62,0x70,0x6f,0x62,0xfe,0xbf,0x62,0x70,0x01,0x9d,0x75,0x40,0x42,0x42,0x40,0xfe,0x3e,0x42,0x40,0x7d,0x7d,0x40,0x42,0x00,0x00,0x01,0x00,0x37,0x00,0x00,0x02,0x26,0x02,0x26,0x00,0x0d,0x00,0x28,0x40,0x25,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x2b,0x4d,0x00,0x03,0x03,0x00,0x5f,0x04,0x01,0x00,0x00,0x29,0x00,0x4e,0x01,0x00, 0x0c,0x0a,0x07,0x06,0x05,0x04,0x00,0x0d,0x01,0x0d,0x05,0x08,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x14,0x16,0x33,0x33,0x15,0x01,0x9a,0x49,0x57,0xc3,0x01,0x1d,0x26,0x20,0x8c,0x55,0x46,0x01,0x39,0x52,0xfe,0x75,0x22,0x27,0x52,0xff,0xff,0x00,0x67,0x00,0x00,0x02,0x35,0x02,0x26,0x02,0x06,0x02,0x19,0x00,0x00, 0x00,0x01,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0d,0x00,0x22,0x40,0x1f,0x09,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x00,0x28,0x4d,0x03,0x02,0x02,0x01,0x01,0x29,0x01,0x4e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x12,0x04,0x08,0x18,0x2b,0x33,0x13,0x27,0x33,0x01,0x23,0x03,0x26,0x26,0x27,0x14,0x06,0x07,0x03,0x32,0xcc, 0x4a,0x60,0x01,0x12,0x60,0x83,0x0d,0x0c,0x05,0x08,0x0c,0x7e,0x02,0x1d,0xbd,0xfd,0x26,0x01,0x65,0x23,0x36,0x0f,0x0f,0x36,0x23,0xfe,0x9b,0x00,0x00,0x01,0x00,0x5d,0xff,0x4c,0x01,0xfb,0x02,0x26,0x00,0x18,0x00,0x57,0xb5,0x0e,0x01,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x18,0x02,0x01,0x00,0x00,0x2b,0x4d,0x00,0x01, 0x01,0x03,0x61,0x04,0x01,0x03,0x03,0x29,0x4d,0x06,0x01,0x05,0x05,0x2d,0x05,0x4e,0x1b,0x40,0x1c,0x02,0x01,0x00,0x00,0x2b,0x4d,0x00,0x03,0x03,0x29,0x4d,0x00,0x01,0x01,0x04,0x61,0x00,0x04,0x04,0x2f,0x4d,0x06,0x01,0x05,0x05,0x2d,0x05,0x4e,0x59,0x40,0x0e,0x00,0x00,0x00,0x18,0x00,0x18,0x24,0x11,0x13,0x23,0x11,0x07,0x08,0x1b, 0x2b,0x17,0x11,0x33,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x23,0x35,0x23,0x06,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x15,0x5d,0x5a,0x3c,0x37,0x38,0x3f,0x5a,0x58,0x03,0x03,0x36,0x3e,0x3e,0x30,0x03,0x03,0x02,0xb4,0x02,0xda,0xfe,0xa2,0x3e,0x46,0x46,0x3e,0x01,0x5e,0xfd,0xda,0x69,0x35,0x3e,0x3e,0x35,0x7d,0xa0,0x00, 0xff,0xff,0x00,0x36,0x00,0x00,0x02,0x22,0x02,0x26,0x02,0x06,0x01,0x69,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0x47,0x02,0x1f,0x02,0xe4,0x00,0x2e,0x00,0x3a,0x40,0x37,0x1f,0x01,0x02,0x01,0x01,0x4c,0x14,0x13,0x02,0x02,0x49,0x00,0x04,0x00,0x01,0x00,0x04,0x01,0x80,0x00,0x01,0x00,0x02,0x01,0x02,0x63,0x05,0x01,0x00,0x00,0x03,0x61, 0x00,0x03,0x03,0x2e,0x00,0x4e,0x01,0x00,0x2c,0x2b,0x28,0x26,0x0a,0x08,0x07,0x05,0x00,0x2e,0x01,0x2e,0x06,0x08,0x16,0x2b,0x01,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x16,0x16,0x07,0x07,0x27,0x37,0x36,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x36,0x33, 0x32,0x16,0x16,0x17,0x23,0x26,0x26,0x01,0x45,0x37,0x44,0x44,0x37,0x92,0x8e,0x42,0x53,0x74,0x8f,0x4a,0x1e,0x2a,0x29,0x46,0x2b,0x0e,0x0a,0x1c,0x8b,0x5e,0x5b,0x4e,0x3e,0x34,0x41,0x37,0x62,0x40,0x40,0x5e,0x36,0x02,0x5a,0x04,0x40,0x02,0x92,0x42,0x32,0x31,0x39,0x50,0x46,0x38,0x4e,0x23,0x2c,0x17,0x65,0x44,0x42,0x27,0x46,0x18, 0x24,0x09,0x2c,0x1e,0x5e,0x45,0x42,0x60,0x0b,0x03,0x0d,0x51,0x39,0x35,0x53,0x2f,0x2d,0x4e,0x33,0x29,0x33,0x00,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x02,0x2e,0x02,0x06,0x01,0x22,0x00,0x00,0x00,0x01,0x00,0x19,0xff,0xfb,0x02,0x2b,0x02,0x26,0x00,0x13,0x00,0x59,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x19,0x05,0x03,0x02, 0x01,0x01,0x04,0x5f,0x00,0x04,0x04,0x2b,0x4d,0x00,0x06,0x06,0x00,0x61,0x02,0x07,0x02,0x00,0x00,0x32,0x00,0x4e,0x1b,0x40,0x1d,0x05,0x03,0x02,0x01,0x01,0x04,0x5f,0x00,0x04,0x04,0x2b,0x4d,0x00,0x02,0x02,0x29,0x4d,0x00,0x06,0x06,0x00,0x61,0x07,0x01,0x00,0x00,0x32,0x00,0x4e,0x59,0x40,0x15,0x01,0x00,0x12,0x10,0x0d,0x0c,0x0b, 0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x13,0x01,0x13,0x08,0x08,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x23,0x11,0x23,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x14,0x16,0x33,0x33,0x15,0x02,0x18,0x4c,0x5b,0xad,0x57,0x54,0x02,0x11,0x63,0x29,0x23,0x18,0x05,0x60,0x4f,0x01,0x2c,0xfe,0x2a,0x01,0xd6,0x50,0x50,0xfe,0xce,0x29,0x2c,0x54, 0x00,0x02,0x00,0x5e,0xff,0x4c,0x01,0xfe,0x02,0x30,0x00,0x11,0x00,0x1f,0x00,0x38,0x40,0x35,0x0e,0x01,0x03,0x04,0x01,0x4c,0x00,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x31,0x4d,0x06,0x01,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x2f,0x4d,0x05,0x01,0x02,0x02,0x2d,0x02,0x4e,0x13,0x12,0x00,0x00,0x1a,0x18,0x12,0x1f,0x13,0x1f,0x00,0x11, 0x00,0x11,0x25,0x23,0x07,0x08,0x18,0x2b,0x17,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x15,0x37,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x5e,0x70,0x61,0x61,0x6e,0x5f,0x53,0x3e,0x4e,0x07,0x03,0x02,0x76,0x39,0x3d,0x3d,0x39,0x39,0x3d,0x3f,0xb4,0x02,0x18,0x5f, 0x6d,0x6d,0x5f,0xa1,0x5f,0x6e,0x3e,0x35,0x7d,0xa0,0xf8,0x44,0x40,0x96,0x40,0x44,0x44,0x40,0x96,0x3e,0x46,0x00,0x00,0x00,0x00,0x01,0x00,0x5a,0xff,0x47,0x02,0x0b,0x02,0x30,0x00,0x1f,0x00,0x1d,0x40,0x1a,0x1f,0x01,0x01,0x49,0x00,0x01,0x02,0x01,0x86,0x00,0x02,0x02,0x00,0x61,0x00,0x00,0x00,0x31,0x02,0x4e,0x22,0x12,0x2b,0x03, 0x08,0x19,0x2b,0x05,0x37,0x36,0x26,0x27,0x27,0x26,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x07,0x07,0x01,0x59,0x2b,0x0e,0x0a,0x1c,0x76,0x4a,0x52,0x77,0x64,0x5f,0x74,0x03,0x5a,0x03,0x41,0x38,0x3b,0x46,0x31,0x2b,0x7a,0x4a,0x1e,0x2a,0x29,0x92,0x46, 0x18,0x24,0x09,0x25,0x17,0x63,0x44,0x82,0x62,0x70,0x66,0x58,0x35,0x39,0x43,0x3e,0x83,0x25,0x3a,0x0e,0x26,0x17,0x65,0x44,0x42,0x00,0x00,0x00,0x00,0x02,0x00,0x55,0xff,0xf6,0x02,0x3a,0x02,0x26,0x00,0x14,0x00,0x22,0x00,0x30,0x40,0x2d,0x04,0x01,0x02,0x02,0x01,0x5f,0x00,0x01,0x01,0x2b,0x4d,0x06,0x01,0x03,0x03,0x00,0x61,0x05, 0x01,0x00,0x00,0x2f,0x00,0x4e,0x16,0x15,0x01,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x0c,0x0b,0x0a,0x08,0x00,0x14,0x01,0x14,0x07,0x08,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x21,0x15,0x23,0x15,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01, 0x29,0x40,0x5f,0x35,0x35,0x5f,0x40,0x01,0x11,0xa9,0x32,0x3a,0x35,0x5f,0x40,0x39,0x41,0x41,0x39,0x39,0x41,0x41,0x0a,0x35,0x5e,0x3f,0x8c,0x3f,0x5f,0x34,0x52,0x03,0x04,0x43,0x36,0x8c,0x3f,0x5e,0x35,0x50,0x46,0x3c,0x8c,0x3c,0x46,0x46,0x3c,0x8c,0x3c,0x46,0x00,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x08,0x02,0x26,0x00,0x0f, 0x00,0x2b,0x40,0x28,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x2b,0x4d,0x00,0x04,0x04,0x00,0x5f,0x05,0x01,0x00,0x00,0x29,0x00,0x4e,0x01,0x00,0x0e,0x0c,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x0f,0x01,0x0f,0x06,0x08,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x14,0x16,0x33,0x33,0x15,0x01,0x6d,0x44, 0x52,0xa8,0x01,0xd9,0xd7,0x21,0x1b,0x96,0x4f,0x42,0x01,0x43,0x52,0x52,0xfe,0xbd,0x1c,0x23,0x52,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0x26,0x02,0x06,0x01,0x51,0x00,0x00,0x00,0x02,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x2b,0x00,0x1e,0x00,0x27,0x00,0x3b,0x40,0x38,0x0b,0x01,0x01,0x06,0x01,0x4c,0x0a,0x01,0x02,0x4a, 0x00,0x06,0x06,0x02,0x5f,0x00,0x02,0x02,0x2b,0x4d,0x05,0x01,0x01,0x01,0x00,0x61,0x03,0x01,0x00,0x00,0x29,0x4d,0x07,0x01,0x04,0x04,0x2d,0x04,0x4e,0x00,0x00,0x26,0x25,0x20,0x1f,0x00,0x1e,0x00,0x1e,0x17,0x21,0x1f,0x11,0x08,0x08,0x1a,0x2b,0x17,0x35,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x37,0x15,0x06,0x06,0x15,0x07,0x06, 0x16,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x15,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0xff,0x3b,0x5b,0x33,0x22,0x3e,0x28,0x16,0x1d,0x01,0x01,0x46,0x38,0x50,0x3c,0x5b,0x34,0x33,0x5a,0x3c,0x08,0x38,0x45,0x42,0x35,0x06,0xb4,0xb4,0x34,0x5e,0x3d,0x92,0x34,0x56,0x39,0x07,0x5f,0x05,0x3b,0x26,0x9c, 0x3a,0x49,0x01,0xdf,0x32,0x58,0x3b,0x92,0x3d,0x5e,0x34,0xb4,0xfb,0x49,0x3a,0x9c,0x36,0x44,0x00,0x00,0xff,0xff,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0x26,0x02,0x06,0x01,0x6f,0x00,0x00,0x00,0x01,0x00,0x36,0xff,0x4c,0x02,0x22,0x02,0x26,0x00,0x17,0x00,0x2d,0x40,0x2a,0x05,0x03,0x02,0x01,0x01,0x2b,0x4d,0x04,0x01,0x02,0x02,0x00, 0x62,0x06,0x01,0x00,0x00,0x29,0x4d,0x08,0x01,0x07,0x07,0x2d,0x07,0x4e,0x00,0x00,0x00,0x17,0x00,0x17,0x13,0x13,0x11,0x11,0x13,0x13,0x11,0x09,0x08,0x1d,0x2b,0x17,0x35,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x33,0x11,0x33,0x11,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0x15,0xff,0x5c,0x6d,0x54,0x3e,0x3d,0x4e,0x3d,0x3e, 0x54,0x6d,0x5c,0xb4,0xb4,0x6c,0x5e,0x01,0x5c,0xfe,0xa4,0x3d,0x44,0x01,0xdd,0xfe,0x23,0x44,0x3d,0x01,0x5c,0xfe,0xa4,0x5e,0x6c,0xb4,0x00,0x00,0x00,0x01,0x00,0x36,0xff,0xf6,0x02,0x22,0x02,0x30,0x00,0x2d,0x00,0x34,0x40,0x31,0x2a,0x01,0x01,0x02,0x01,0x4c,0x20,0x1f,0x08,0x07,0x04,0x02,0x4a,0x00,0x02,0x01,0x02,0x85,0x03,0x01, 0x01,0x01,0x00,0x61,0x04,0x05,0x02,0x00,0x00,0x2f,0x00,0x4e,0x01,0x00,0x28,0x26,0x19,0x17,0x14,0x13,0x10,0x0e,0x00,0x2d,0x01,0x2d,0x06,0x08,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x15,0x06,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x27,0x35,0x16, 0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x06,0x06,0xb5,0x3a,0x45,0x4c,0x41,0x19,0x1f,0x22,0x1c,0x1c,0x20,0x4e,0x20,0x1c,0x1d,0x21,0x21,0x1c,0x44,0x4e,0x44,0x3b,0x31,0x41,0x05,0x02,0x04,0x40,0x0a,0x5c,0x4f,0xbb,0x57,0x73,0x0a,0x5f,0x05,0x3c,0x2e,0xc7,0x29,0x30,0x30,0x29,0xbe,0xbe,0x29,0x30,0x30,0x29,0xc7,0x2b, 0x39,0x06,0x5f,0x0a,0x70,0x55,0xbb,0x4f,0x5c,0x3f,0x35,0x35,0x3f,0x00,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x26,0x03,0x11,0x02,0x26,0x02,0x7d,0x00,0x00,0x00,0x06,0x06,0xb0,0x19,0x00,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x26,0x03,0x09,0x02,0x26,0x02,0x7d,0x00,0x00,0x00,0x07,0x06,0x68,0x02,0x53,0x00,0x00, 0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x26,0x03,0x84,0x02,0x26,0x02,0x7d,0x00,0x00,0x00,0x06,0x06,0xb2,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x06,0x06,0xb0,0x1e,0x00,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x09,0x02,0x26,0x01,0x51,0x00,0x00, 0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x03,0x84,0x02,0x26,0x01,0x51,0x00,0x00,0x00,0x06,0x06,0xb2,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x54,0xff,0xf8,0x02,0x04,0x03,0x11,0x02,0x26,0x01,0x22,0x00,0x00,0x00,0x06,0x06,0xb0,0x1e,0x00,0x00,0x00,0xff,0xff,0x00,0x36,0xff,0xf6,0x02,0x22, 0x03,0x11,0x02,0x26,0x02,0x8d,0x00,0x00,0x00,0x06,0x06,0xb0,0x14,0x00,0x00,0x00,0x00,0x03,0x00,0x55,0xff,0xf6,0x01,0xfc,0x03,0x11,0x00,0x03,0x00,0x17,0x00,0x25,0x00,0x84,0xb6,0x14,0x0e,0x02,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x24,0x00,0x00,0x01,0x00,0x85,0x08,0x01,0x01,0x03,0x01,0x85,0x00,0x07,0x07,0x03, 0x61,0x04,0x01,0x03,0x03,0x31,0x4d,0x0a,0x01,0x06,0x06,0x02,0x61,0x05,0x09,0x02,0x02,0x02,0x2f,0x02,0x4e,0x1b,0x40,0x2c,0x00,0x00,0x01,0x00,0x85,0x08,0x01,0x01,0x03,0x01,0x85,0x00,0x04,0x04,0x2b,0x4d,0x00,0x07,0x07,0x03,0x61,0x00,0x03,0x03,0x31,0x4d,0x00,0x05,0x05,0x29,0x4d,0x0a,0x01,0x06,0x06,0x02,0x61,0x09,0x01,0x02, 0x02,0x2f,0x02,0x4e,0x59,0x40,0x1e,0x19,0x18,0x05,0x04,0x00,0x00,0x20,0x1e,0x18,0x25,0x19,0x25,0x13,0x12,0x11,0x10,0x0c,0x0a,0x04,0x17,0x05,0x17,0x00,0x03,0x00,0x03,0x11,0x0b,0x08,0x17,0x2b,0x13,0x37,0x33,0x07,0x03,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x27,0x33,0x11,0x23,0x35,0x23,0x06,0x06,0x27,0x32, 0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xea,0x6a,0x64,0x6f,0x3d,0x52,0x65,0x64,0x53,0x3e,0x50,0x07,0x03,0x02,0x5a,0x5a,0x01,0x07,0x50,0x20,0x38,0x40,0x40,0x38,0x39,0x42,0x42,0x02,0x85,0x8c,0x8c,0xfd,0x71,0x6e,0x5e,0xa1,0x5f,0x6e,0x3e,0x35,0x69,0xfd,0xda,0x69,0x36,0x3d,0x4e,0x46,0x3e,0x96,0x3e,0x46, 0x44,0x40,0x96,0x40,0x44,0x00,0x00,0x00,0x00,0x02,0x00,0x4b,0xff,0xf9,0x02,0x12,0x03,0x11,0x00,0x2d,0x00,0x31,0x01,0x43,0x4b,0xb0,0x13,0x50,0x58,0x40,0x40,0x00,0x09,0x0a,0x09,0x85,0x0c,0x01,0x0a,0x02,0x0a,0x85,0x00,0x03,0x04,0x05,0x04,0x03,0x72,0x00,0x01,0x05,0x06,0x05,0x01,0x06,0x80,0x00,0x08,0x06,0x07,0x06,0x08,0x07, 0x80,0x00,0x05,0x00,0x06,0x08,0x05,0x06,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x31,0x4d,0x00,0x07,0x07,0x00,0x62,0x0b,0x01,0x00,0x00,0x32,0x00,0x4e,0x1b,0x4b,0xb0,0x14,0x50,0x58,0x40,0x41,0x00,0x09,0x0a,0x09,0x85,0x0c,0x01,0x0a,0x02,0x0a,0x85,0x00,0x03,0x04,0x05,0x04,0x03,0x05,0x80,0x00,0x01,0x05,0x06,0x05,0x01, 0x06,0x80,0x00,0x08,0x06,0x07,0x06,0x08,0x07,0x80,0x00,0x05,0x00,0x06,0x08,0x05,0x06,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x31,0x4d,0x00,0x07,0x07,0x00,0x62,0x0b,0x01,0x00,0x00,0x32,0x00,0x4e,0x1b,0x4b,0xb0,0x15,0x50,0x58,0x40,0x40,0x00,0x09,0x0a,0x09,0x85,0x0c,0x01,0x0a,0x02,0x0a,0x85,0x00,0x03,0x04,0x05,0x04, 0x03,0x72,0x00,0x01,0x05,0x06,0x05,0x01,0x06,0x80,0x00,0x08,0x06,0x07,0x06,0x08,0x07,0x80,0x00,0x05,0x00,0x06,0x08,0x05,0x06,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x31,0x4d,0x00,0x07,0x07,0x00,0x62,0x0b,0x01,0x00,0x00,0x32,0x00,0x4e,0x1b,0x40,0x41,0x00,0x09,0x0a,0x09,0x85,0x0c,0x01,0x0a,0x02,0x0a,0x85,0x00,0x03, 0x04,0x05,0x04,0x03,0x05,0x80,0x00,0x01,0x05,0x06,0x05,0x01,0x06,0x80,0x00,0x08,0x06,0x07,0x06,0x08,0x07,0x80,0x00,0x05,0x00,0x06,0x08,0x05,0x06,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x31,0x4d,0x00,0x07,0x07,0x00,0x62,0x0b,0x01,0x00,0x00,0x32,0x00,0x4e,0x59,0x59,0x59,0x40,0x21,0x2e,0x2e,0x02,0x00,0x2e,0x31,0x2e, 0x31,0x30,0x2f,0x2b,0x2a,0x28,0x25,0x21,0x1f,0x1e,0x1c,0x18,0x15,0x13,0x12,0x10,0x0d,0x07,0x06,0x00,0x2d,0x02,0x2d,0x0d,0x08,0x16,0x2b,0x05,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14, 0x16,0x33,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x03,0x37,0x33,0x07,0x01,0x4e,0x35,0x5f,0x6f,0x42,0x3c,0x32,0x3f,0x69,0x5a,0x2f,0x56,0x66,0x01,0x5a,0x01,0x36,0x2c,0x2f,0x2e,0x37,0x37,0x2f,0x75,0x78,0x34,0x3c,0x3c,0x34,0x35,0x31,0x39,0x5a,0x6a,0xb8,0x6a,0x64,0x6f,0x07,0x59,0x4b,0x3c,0x4c,0x04,0x04,0x04,0x3f,0x2e,0x45,0x4a, 0x4d,0x41,0x1d,0x22,0x29,0x23,0x24,0x2a,0x4e,0x2f,0x29,0x27,0x2d,0x2a,0x23,0x49,0x55,0x02,0x8c,0x8c,0x8c,0x00,0x00,0x00,0xff,0xff,0x00,0x5c,0x00,0x00,0x01,0xfe,0x03,0x11,0x02,0x26,0x01,0x1b,0x00,0x00,0x00,0x06,0x06,0xb0,0x23,0x00,0x00,0x00,0x00,0x01,0x00,0x5c,0xff,0x4c,0x02,0x26,0x02,0x26,0x00,0x1a,0x00,0x39,0x40,0x36, 0x19,0x06,0x02,0x02,0x00,0x01,0x4c,0x00,0x02,0x00,0x05,0x00,0x02,0x05,0x80,0x01,0x01,0x00,0x00,0x2b,0x4d,0x07,0x06,0x02,0x05,0x05,0x29,0x4d,0x00,0x04,0x04,0x03,0x61,0x00,0x03,0x03,0x2d,0x03,0x4e,0x00,0x00,0x00,0x1a,0x00,0x1a,0x12,0x21,0x23,0x11,0x15,0x11,0x08,0x08,0x1c,0x2b,0x33,0x11,0x33,0x11,0x14,0x06,0x07,0x13,0x33, 0x11,0x33,0x15,0x14,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x23,0x11,0x34,0x36,0x37,0x03,0x5c,0x56,0x03,0x08,0xe5,0x70,0x2a,0x5f,0x5c,0x1d,0x1d,0x2d,0x38,0x2a,0x03,0x08,0xe5,0x02,0x26,0xfe,0xd8,0x2b,0x5c,0x1d,0x01,0xcc,0xfe,0x21,0x47,0x58,0x5c,0x4f,0x37,0x2e,0x01,0x29,0x2c,0x5c,0x1d,0xfe,0x32,0x00,0xff,0xff,0x00,0x30, 0xff,0x4c,0x02,0x28,0x02,0xda,0x02,0x06,0x02,0x25,0x00,0x00,0x00,0x02,0x00,0x0f,0xff,0xf6,0x02,0x49,0x02,0x26,0x00,0x18,0x00,0x2c,0x00,0x49,0x40,0x46,0x16,0x01,0x05,0x06,0x01,0x4c,0x00,0x06,0x01,0x05,0x01,0x06,0x05,0x80,0x08,0x03,0x02,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x2b,0x4d,0x07,0x0a,0x02,0x05,0x05,0x00,0x61,0x04, 0x09,0x02,0x00,0x00,0x2f,0x00,0x4e,0x1a,0x19,0x01,0x00,0x29,0x26,0x23,0x21,0x1e,0x1d,0x19,0x2c,0x1a,0x2c,0x14,0x12,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x00,0x18,0x01,0x18,0x0b,0x08,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x23,0x35,0x21,0x15,0x23,0x16,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x27,0x32, 0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x35,0x35,0x34,0x23,0x23,0x22,0x15,0x15,0x14,0xb5,0x3a,0x44,0x27,0x24,0x73,0x02,0x3a,0x73,0x24,0x27,0x43,0x3b,0x31,0x3e,0x08,0x07,0x3e,0x1e,0x1d,0x21,0x4a,0x21,0x1d,0x3d,0x3d,0xc6,0x3d,0x0a,0x56,0x4b,0xbc,0x2e,0x42,0x11,0x52,0x52,0x11,0x42,0x2e,0xbc,0x4b,0x56,0x39,0x32,0x32, 0x39,0x4c,0x2c,0x28,0xc3,0xc3,0x28,0x2c,0x54,0xea,0x54,0x54,0xea,0x54,0x00,0x00,0xff,0xff,0x00,0x64,0x00,0x00,0x02,0x37,0x02,0x26,0x02,0x06,0x02,0x4b,0x00,0x00,0x00,0x01,0x00,0x1a,0xff,0x4c,0x02,0x21,0x02,0x2a,0x00,0x15,0x00,0x29,0x40,0x26,0x14,0x0e,0x01,0x03,0x03,0x00,0x01,0x4c,0x00,0x00,0x00,0x01,0x61,0x02,0x01,0x01, 0x01,0x3b,0x4d,0x04,0x01,0x03,0x03,0x3d,0x03,0x4e,0x00,0x00,0x00,0x15,0x00,0x15,0x1a,0x21,0x23,0x05,0x09,0x19,0x2b,0x05,0x35,0x03,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x17,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x15,0x01,0x09,0x8b,0x11,0x35,0x1e,0x1e,0x3a,0x51,0x10,0x4e,0x0b,0x09,0x03,0x03,0x0b,0x0b,0x74,0x5c, 0xbe,0xb4,0xb4,0x01,0xa7,0x31,0x52,0x36,0x35,0xfe,0xfa,0x22,0x35,0x11,0x11,0x35,0x22,0x01,0x6d,0xfd,0xda,0xb4,0x00,0x00,0x00,0x01,0x00,0x2f,0xff,0xfb,0x02,0x44,0x02,0xdf,0x00,0x1a,0x00,0x59,0xb6,0x0d,0x07,0x02,0x04,0x02,0x01,0x4c,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x17,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x00, 0x04,0x04,0x00,0x61,0x01,0x05,0x02,0x00,0x00,0x42,0x00,0x4e,0x1b,0x40,0x1b,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x00,0x01,0x01,0x39,0x4d,0x00,0x04,0x04,0x00,0x61,0x05,0x01,0x00,0x00,0x42,0x00,0x4e,0x59,0x40,0x11,0x01,0x00,0x19,0x17,0x14,0x12,0x11,0x0f,0x0c,0x0b,0x00,0x1a,0x01,0x1a,0x06,0x09,0x16,0x2b,0x05, 0x22,0x26,0x27,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x23,0x13,0x27,0x26,0x23,0x23,0x35,0x33,0x32,0x17,0x13,0x16,0x33,0x33,0x15,0x02,0x1c,0x3a,0x50,0x11,0x48,0x07,0x0b,0x03,0x03,0x0c,0x08,0x7d,0x61,0xca,0x23,0x12,0x30,0x3c,0x4b,0x66,0x24,0xa9,0x11,0x35,0x28,0x05,0x37,0x34,0xea,0x19,0x2b,0x10,0x10,0x2c,0x14,0xfe,0xac, 0x02,0x04,0x5b,0x2d,0x53,0x6a,0xfe,0x09,0x31,0x52,0x00,0x00,0x00,0x03,0x00,0x2e,0x00,0x00,0x02,0x2a,0x02,0xda,0x00,0x07,0x00,0x0b,0x00,0x14,0x00,0x3a,0x40,0x37,0x11,0x01,0x06,0x05,0x01,0x4c,0x00,0x06,0x00,0x02,0x04,0x06,0x02,0x67,0x00,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x01,0x5f,0x07,0x03,0x02, 0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x09,0x19,0x2b,0x33,0x13,0x33,0x13,0x23,0x27,0x23,0x07,0x25,0x33,0x03,0x23,0x03,0x33,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x2e,0xaa,0xa8,0xaa,0x98,0x32,0xd4,0x32,0x01,0x5c,0x3e,0x98,0x3d,0x8a,0xc1,0x43,0x0c,0x0e,0x02, 0x02,0x10,0x0c,0x02,0xda,0xfd,0x26,0xd5,0xd5,0x28,0x02,0x8a,0xfe,0x4b,0x01,0x29,0x37,0x46,0x0d,0x0b,0x49,0x36,0x00,0x00,0x00,0x06,0x00,0x4b,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x0e,0x00,0x12,0x00,0x1c,0x00,0x23,0x00,0x2b,0x00,0x32,0x00,0x4d,0x40,0x4a,0x23,0x1d,0x18,0x17,0x04,0x04,0x03,0x08,0x01,0x07,0x04,0x32,0x2c,0x28, 0x27,0x04,0x02,0x07,0x03,0x4c,0x00,0x04,0x00,0x07,0x02,0x04,0x07,0x67,0x05,0x01,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x06,0x01,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x2b,0x29,0x26,0x24,0x1c,0x1a,0x15,0x13,0x12,0x11,0x10,0x0f,0x00,0x0e,0x00,0x0d,0x21,0x09,0x09,0x17,0x2b,0x33,0x11,0x33, 0x32,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x11,0x23,0x13,0x33,0x32,0x36,0x37,0x11,0x26,0x26,0x23,0x23,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x03,0x33,0x32,0x37,0x11,0x26,0x23,0x23,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x4b,0xf2,0x5c,0x6c,0x3c,0x35,0x3e,0x45,0x74,0x63,0xcb,0x3c,0x3c,0x66,0x67,0x0d, 0x18,0x0a,0x0a,0x18,0x0d,0x67,0xbf,0x1f,0x22,0x22,0x1f,0xbf,0x6a,0x19,0x13,0x13,0x19,0x6a,0xbf,0x27,0x2c,0x2c,0x27,0x02,0xda,0x64,0x56,0x43,0x58,0x0e,0x0d,0x5c,0x47,0x5b,0x6c,0x28,0x02,0x8a,0xfe,0xd9,0x03,0x02,0x01,0x1d,0x02,0x03,0xfe,0xef,0x12,0x41,0x2b,0x2b,0x40,0x12,0xfd,0x8c,0x04,0x01,0x33,0x04,0xfe,0xd6,0x13,0x48, 0x32,0x32,0x47,0x13,0x00,0x02,0x00,0x4a,0xff,0xf6,0x02,0x0e,0x02,0xe4,0x00,0x19,0x00,0x21,0x00,0x4a,0x40,0x47,0x1b,0x10,0x02,0x02,0x03,0x1a,0x11,0x02,0x04,0x05,0x02,0x4c,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00, 0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x04,0x00,0x51,0x01,0x00,0x17,0x16,0x14,0x12,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x19,0x01,0x19,0x07,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x07,0x11,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x27,0x11,0x06,0x06,0x15,0x11,0x14,0x16, 0x01,0x2c,0x67,0x7b,0x7b,0x67,0x69,0x79,0x2a,0x62,0x56,0x2e,0x24,0x24,0x2e,0x56,0x62,0x2a,0x79,0xe5,0x1c,0x20,0x20,0x0a,0x77,0x65,0x01,0x36,0x65,0x77,0x77,0x65,0x53,0x61,0x0f,0xfd,0x80,0x0f,0x61,0x53,0x65,0x77,0x4f,0x02,0x50,0x18,0x47,0x2e,0xfe,0xca,0x2e,0x47,0x00,0x04,0x00,0x4b,0x00,0x00,0x02,0x0e,0x02,0xda,0x00,0x09, 0x00,0x0d,0x00,0x17,0x00,0x1f,0x00,0x36,0x40,0x33,0x1f,0x18,0x13,0x12,0x04,0x02,0x03,0x01,0x4c,0x05,0x01,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x04,0x01,0x02,0x02,0x01,0x5f,0x06,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x17,0x15,0x10,0x0e,0x0d,0x0c,0x0b,0x0a,0x00,0x09,0x00,0x08,0x21,0x07,0x09,0x17,0x2b,0x33,0x11, 0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x27,0x33,0x11,0x23,0x13,0x33,0x32,0x36,0x37,0x11,0x26,0x26,0x23,0x23,0x13,0x36,0x36,0x35,0x11,0x34,0x26,0x27,0x4b,0xdb,0x6b,0x7d,0x7d,0x6b,0xb1,0x3c,0x3c,0x66,0x4b,0x19,0x2c,0x13,0x13,0x2c,0x19,0x4b,0xcd,0x1d,0x1f,0x1f,0x1d,0x02,0xda,0x77,0x65,0xfe,0xde,0x65,0x77,0x28,0x02,0x8a, 0xfd,0x76,0x09,0x07,0x02,0x6a,0x08,0x08,0xfd,0x9f,0x17,0x47,0x2d,0x01,0x22,0x2d,0x47,0x17,0x00,0x00,0x00,0x02,0x00,0x55,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x0b,0x00,0x0f,0x00,0x35,0x40,0x32,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x07,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x06,0x01,0x04,0x04,0x05,0x5f,0x08, 0x01,0x05,0x05,0x39,0x05,0x4e,0x00,0x00,0x0f,0x0e,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x09,0x09,0x1b,0x2b,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x25,0x33,0x11,0x23,0x55,0x01,0xbd,0xfe,0xd5,0x01,0x08,0xfe,0xf8,0x01,0x2b,0xfe,0x6e,0x3c,0x3c,0x02,0xda,0x28,0xfe,0xdf,0x28,0xfe,0xbf, 0x28,0x28,0x02,0x8a,0x00,0x02,0x00,0x5a,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x09,0x00,0x0d,0x00,0x33,0x40,0x30,0x00,0x02,0x00,0x03,0x05,0x02,0x03,0x67,0x06,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x05,0x05,0x04,0x5f,0x07,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x0d,0x0c,0x0b,0x0a,0x00,0x09,0x00,0x09,0x11, 0x11,0x11,0x11,0x08,0x09,0x1a,0x2b,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x21,0x11,0x27,0x33,0x11,0x23,0x5a,0x01,0xbd,0xfe,0xd5,0x01,0x08,0xfe,0xf8,0x67,0x3c,0x3c,0x02,0xda,0x28,0xfe,0xdf,0x28,0xfe,0x97,0x28,0x02,0x8a,0x00,0x03,0x00,0x4a,0xff,0xf6,0x02,0x0e,0x02,0xe4,0x00,0x1c,0x00,0x24,0x00,0x2a,0x00,0x4f,0x40,0x4c, 0x1e,0x10,0x02,0x02,0x03,0x25,0x1d,0x15,0x11,0x04,0x04,0x05,0x02,0x4c,0x00,0x02,0x03,0x06,0x03,0x02,0x06,0x80,0x00,0x06,0x07,0x01,0x05,0x04,0x06,0x05,0x67,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x04,0x04,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x2a,0x29,0x19,0x18,0x17,0x16,0x14,0x12,0x0f, 0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1c,0x01,0x1c,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x07,0x11,0x16,0x33,0x32,0x37,0x11,0x23,0x35,0x33,0x15,0x14,0x06,0x27,0x11,0x06,0x06,0x15,0x11,0x14,0x16,0x05,0x36,0x36,0x35,0x35,0x23,0x01,0x2c,0x67,0x7b,0x7b,0x67,0x69,0x79, 0x2a,0x62,0x56,0x2e,0x24,0x24,0x2e,0x2e,0x24,0x50,0xe0,0x7a,0xe4,0x1c,0x20,0x20,0x01,0x14,0x1d,0x1f,0x3c,0x0a,0x77,0x65,0x01,0x36,0x65,0x77,0x77,0x65,0x53,0x61,0x0f,0xfd,0x80,0x0f,0x0f,0x01,0x1d,0x28,0xa0,0x65,0x77,0x4f,0x02,0x50,0x18,0x47,0x2e,0xfe,0xca,0x2e,0x47,0x18,0x18,0x47,0x2e,0x78,0x00,0x00,0x00,0x03,0x00,0x4b, 0x00,0x00,0x02,0x0d,0x02,0xda,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x3f,0x40,0x3c,0x02,0x01,0x00,0x09,0x01,0x07,0x01,0x00,0x07,0x67,0x00,0x01,0x00,0x04,0x06,0x01,0x04,0x67,0x08,0x01,0x06,0x03,0x03,0x06,0x57,0x08,0x01,0x06,0x06,0x03,0x5f,0x0a,0x05,0x02,0x03,0x06,0x03,0x4f,0x00,0x00,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c, 0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0b,0x06,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x23,0x11,0x23,0x11,0x27,0x33,0x11,0x23,0x01,0x33,0x11,0x23,0x4b,0x90,0xa2,0x90,0x90,0xa2,0x66,0x3c,0x3c,0x01,0x32,0x3c,0x3c,0x02,0xda,0xfe,0xb5,0x01,0x4b,0xfd,0x26,0x01,0x67,0xfe,0x99,0x28,0x02,0x8a,0xfd,0x76,0x02, 0x8a,0x00,0x00,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x02,0x08,0x02,0xda,0x00,0x0b,0x00,0x0f,0x00,0x2f,0x40,0x2c,0x07,0x03,0x02,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x06,0x04,0x02,0x00,0x00,0x05,0x5f,0x08,0x01,0x05,0x05,0x39,0x05,0x4e,0x00,0x00,0x0f,0x0e,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x09, 0x09,0x1b,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x33,0x15,0x27,0x33,0x11,0x23,0x50,0x95,0x95,0x01,0xb8,0x93,0x93,0xf9,0x3c,0x3c,0x28,0x02,0x8a,0x28,0x28,0xfd,0x76,0x28,0x28,0x02,0x8a,0x00,0x02,0x00,0x1b,0xff,0xf6,0x02,0x49,0x02,0xda,0x00,0x12,0x00,0x18,0x00,0x3f,0x40,0x3c,0x13,0x09,0x02,0x02,0x01,0x01, 0x4c,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x06,0x05,0x02,0x03,0x03,0x04,0x5f,0x00,0x04,0x04,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x18,0x17,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00,0x12,0x01,0x12,0x08,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32, 0x37,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x14,0x06,0x37,0x36,0x36,0x35,0x11,0x23,0xff,0x69,0x7b,0x2a,0x65,0x55,0x30,0x24,0xa1,0x01,0x97,0x66,0x7b,0x15,0x1d,0x1f,0x3c,0x0a,0x77,0x65,0x53,0x61,0x0f,0x02,0x85,0x28,0x28,0xfe,0x20,0x65,0x77,0x50,0x17,0x47,0x2e,0x01,0xe0,0x00,0x00,0x00,0x00,0x03,0x00,0x4b,0x00,0x00,0x02,0x45, 0x02,0xda,0x00,0x0c,0x00,0x10,0x00,0x14,0x00,0x43,0x40,0x40,0x13,0x07,0x02,0x01,0x07,0x14,0x01,0x04,0x01,0x02,0x4c,0x00,0x01,0x00,0x04,0x06,0x01,0x04,0x67,0x00,0x07,0x07,0x00,0x5f,0x02,0x01,0x00,0x00,0x38,0x4d,0x08,0x01,0x06,0x06,0x03,0x60,0x09,0x05,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x12,0x11,0x10,0x0f,0x0e,0x0d, 0x00,0x0c,0x00,0x0c,0x11,0x12,0x11,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x13,0x33,0x07,0x13,0x23,0x03,0x23,0x11,0x27,0x33,0x11,0x23,0x01,0x33,0x03,0x07,0x4b,0x90,0x3a,0xe3,0x33,0xa1,0xbb,0xa0,0x7e,0x4c,0x66,0x3c,0x3c,0x01,0x50,0x42,0x99,0x29,0x02,0xda,0xfe,0xad,0x01,0x53,0xf0,0xfe,0x16,0x01,0x5f,0xfe, 0xa1,0x28,0x02,0x8a,0xfd,0x76,0x01,0x98,0x3d,0x00,0x00,0x00,0x00,0x02,0x00,0x64,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x05,0x00,0x09,0x00,0x29,0x40,0x26,0x00,0x04,0x04,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x03,0x01,0x01,0x01,0x02,0x5f,0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x09,0x08,0x07,0x06,0x00,0x05,0x00,0x05,0x11, 0x11,0x06,0x09,0x18,0x2b,0x33,0x11,0x33,0x11,0x21,0x15,0x25,0x33,0x11,0x23,0x64,0x90,0x01,0x32,0xfe,0x68,0x3c,0x3c,0x02,0xda,0xfd,0x4e,0x28,0x28,0x02,0x8a,0x00,0x00,0x03,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x14,0x00,0x18,0x00,0x1c,0x00,0x43,0x40,0x40,0x0f,0x0c,0x02,0x05,0x00,0x16,0x03,0x02,0x03,0x05,0x02,0x4c, 0x00,0x03,0x05,0x06,0x05,0x03,0x06,0x80,0x07,0x01,0x05,0x05,0x00,0x5f,0x01,0x01,0x00,0x00,0x38,0x4d,0x00,0x06,0x06,0x02,0x5f,0x08,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x00,0x14,0x00,0x14,0x16,0x11,0x12,0x11,0x09,0x09,0x1a,0x2b,0x33,0x11,0x33,0x17,0x37,0x33,0x11,0x23,0x11,0x34,0x36, 0x36,0x37,0x03,0x23,0x03,0x1e,0x02,0x15,0x11,0x13,0x37,0x27,0x23,0x01,0x33,0x11,0x23,0x32,0xad,0x50,0x4f,0xa8,0x90,0x02,0x02,0x01,0x88,0x32,0x8b,0x02,0x02,0x02,0x9f,0x20,0x57,0x40,0x01,0x3c,0x3c,0x3c,0x02,0xda,0xdf,0xdf,0xfd,0x26,0x01,0xb8,0x33,0x65,0x56,0x1b,0xfe,0x84,0x01,0x7c,0x1b,0x56,0x65,0x33,0xfe,0x48,0x01,0x68, 0x59,0xf1,0xfd,0x76,0x02,0x8a,0x00,0x00,0x00,0x02,0x00,0x5f,0x00,0x00,0x01,0xf9,0x02,0xda,0x00,0x0f,0x00,0x13,0x00,0x35,0x40,0x32,0x0b,0x03,0x02,0x04,0x05,0x01,0x4c,0x01,0x01,0x00,0x00,0x05,0x04,0x00,0x05,0x67,0x00,0x04,0x02,0x02,0x04,0x57,0x00,0x04,0x04,0x02,0x5f,0x06,0x03,0x02,0x02,0x04,0x02,0x4f,0x00,0x00,0x13,0x12, 0x11,0x10,0x00,0x0f,0x00,0x0f,0x11,0x15,0x11,0x07,0x06,0x19,0x2b,0x33,0x11,0x33,0x13,0x26,0x26,0x35,0x11,0x33,0x11,0x23,0x03,0x16,0x16,0x15,0x11,0x25,0x33,0x01,0x23,0x5f,0x7c,0xf9,0x03,0x02,0x2a,0x7e,0xf7,0x02,0x02,0x01,0x10,0x43,0xfe,0xe4,0x42,0x02,0xda,0xfd,0xc7,0x20,0x50,0x1b,0x01,0xae,0xfd,0x26,0x02,0x3a,0x21,0x4f, 0x1c,0xfe,0x52,0x27,0x02,0x8c,0x00,0x00,0x00,0x04,0x00,0x4a,0xff,0xf6,0x02,0x0e,0x02,0xe4,0x00,0x0d,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0x3a,0x40,0x37,0x27,0x20,0x19,0x18,0x16,0x15,0x11,0x10,0x08,0x02,0x03,0x01,0x4c,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f, 0x00,0x4e,0x0f,0x0e,0x01,0x00,0x14,0x12,0x0e,0x17,0x0f,0x17,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x32,0x37,0x11,0x26,0x23,0x22,0x07,0x11,0x16,0x27,0x11,0x06,0x06,0x15,0x11,0x14,0x16,0x05,0x36,0x36,0x35,0x11,0x34,0x26,0x27,0x01,0x2c, 0x68,0x7a,0x7a,0x68,0x68,0x7a,0x7a,0x68,0x2e,0x24,0x24,0x2e,0x2e,0x24,0x24,0x4e,0x1c,0x20,0x20,0x01,0x14,0x1d,0x1f,0x1f,0x1d,0x0a,0x77,0x65,0x01,0x36,0x65,0x77,0x77,0x65,0xfe,0xca,0x65,0x77,0x28,0x0f,0x02,0x80,0x0f,0x0f,0xfd,0x80,0x0f,0x27,0x02,0x50,0x17,0x48,0x2e,0xfe,0xca,0x2e,0x48,0x17,0x17,0x48,0x2e,0x01,0x36,0x2e, 0x48,0x17,0x00,0x00,0x00,0x04,0x00,0x4b,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0a,0x00,0x0e,0x00,0x16,0x00,0x1b,0x00,0x41,0x40,0x3e,0x1b,0x17,0x13,0x12,0x04,0x05,0x04,0x01,0x4c,0x00,0x00,0x06,0x01,0x04,0x05,0x00,0x04,0x67,0x00,0x05,0x00,0x01,0x03,0x05,0x01,0x67,0x00,0x03,0x02,0x02,0x03,0x57,0x00,0x03,0x03,0x02,0x5f,0x07, 0x01,0x02,0x03,0x02,0x4f,0x00,0x00,0x16,0x14,0x11,0x0f,0x0e,0x0d,0x0c,0x0b,0x00,0x0a,0x00,0x0a,0x24,0x21,0x08,0x06,0x18,0x2b,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x11,0x27,0x33,0x11,0x23,0x13,0x33,0x32,0x37,0x11,0x26,0x23,0x23,0x13,0x36,0x35,0x34,0x27,0x4b,0x01,0x09,0x60,0x72,0x73,0x5f,0x79,0x66,0x3c,0x3c, 0x66,0x79,0x1e,0x16,0x16,0x1e,0x79,0xd7,0x42,0x42,0x02,0xda,0x6e,0x5c,0x5c,0x6e,0xfe,0xba,0x28,0x02,0x8a,0xfe,0xbc,0x07,0x01,0x36,0x07,0xfe,0xd6,0x2c,0x5c,0x5e,0x2a,0x00,0x00,0x00,0x00,0x04,0x00,0x4a,0xff,0x4c,0x02,0x0e,0x02,0xe4,0x00,0x12,0x00,0x1c,0x00,0x24,0x00,0x2c,0x00,0x47,0x40,0x44,0x2c,0x25,0x1e,0x1d,0x1b,0x1a, 0x16,0x15,0x08,0x03,0x04,0x11,0x01,0x00,0x03,0x02,0x4c,0x05,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x69,0x06,0x01,0x03,0x00,0x00,0x03,0x59,0x06,0x01,0x03,0x03,0x00,0x61,0x00,0x00,0x03,0x00,0x51,0x14,0x13,0x00,0x00,0x19,0x17,0x13,0x1c,0x14,0x1c,0x00,0x12,0x00,0x12,0x25,0x22,0x07,0x06,0x18,0x2b,0x05, 0x27,0x06,0x23,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x17,0x27,0x32,0x37,0x11,0x26,0x23,0x22,0x07,0x11,0x16,0x27,0x11,0x06,0x06,0x15,0x11,0x14,0x16,0x05,0x36,0x36,0x35,0x11,0x34,0x26,0x27,0x01,0xc1,0x6a,0x13,0x18,0x67,0x7b,0x7b,0x67,0x67,0x7b,0x43,0x3e,0x71,0xd2,0x2e,0x24,0x24,0x2e,0x2e, 0x24,0x24,0x4e,0x1c,0x20,0x20,0x01,0x14,0x1d,0x1f,0x1f,0x1d,0xb4,0xad,0x03,0x77,0x65,0x01,0x36,0x65,0x77,0x77,0x65,0xfe,0xca,0x4b,0x6a,0x17,0xba,0xd2,0x0f,0x02,0x80,0x0f,0x0f,0xfd,0x80,0x0f,0x28,0x02,0x4e,0x17,0x47,0x2e,0xfe,0xca,0x2e,0x47,0x17,0x17,0x47,0x2e,0x01,0x36,0x2e,0x47,0x17,0x00,0x00,0x00,0x00,0x05,0x00,0x4b, 0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0d,0x00,0x11,0x00,0x19,0x00,0x20,0x00,0x26,0x00,0x4e,0x40,0x4b,0x1e,0x1d,0x16,0x15,0x04,0x06,0x05,0x08,0x01,0x02,0x06,0x02,0x4c,0x00,0x00,0x07,0x01,0x05,0x06,0x00,0x05,0x67,0x00,0x06,0x09,0x01,0x02,0x04,0x06,0x02,0x69,0x08,0x01,0x04,0x01,0x01,0x04,0x57,0x08,0x01,0x04,0x04,0x01,0x5f, 0x0a,0x03,0x02,0x01,0x04,0x01,0x4f,0x00,0x00,0x26,0x24,0x22,0x21,0x19,0x17,0x14,0x12,0x11,0x10,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x16,0x21,0x0b,0x06,0x19,0x2b,0x33,0x11,0x21,0x32,0x16,0x15,0x14,0x06,0x07,0x13,0x23,0x03,0x23,0x11,0x27,0x33,0x11,0x23,0x13,0x33,0x32,0x37,0x11,0x26,0x23,0x23,0x05,0x34,0x26,0x27,0x11,0x36, 0x36,0x03,0x33,0x03,0x06,0x23,0x23,0x4b,0x01,0x04,0x60,0x72,0x4e,0x44,0xab,0xa7,0x9e,0x1a,0x66,0x3c,0x3c,0x66,0x74,0x1e,0x1a,0x1a,0x1e,0x74,0x01,0x1c,0x25,0x21,0x20,0x26,0x46,0x43,0x8f,0x0b,0x0b,0x2d,0x02,0xda,0x6e,0x5c,0x4c,0x66,0x11,0xfe,0xb3,0x01,0x46,0xfe,0xba,0x28,0x02,0x8a,0xfe,0xbc,0x08,0x01,0x34,0x08,0xa2,0x2d, 0x45,0x15,0xfe,0xf2,0x15,0x46,0xfe,0x44,0x01,0x1f,0x01,0x00,0x00,0x02,0x00,0x41,0xff,0xf6,0x02,0x17,0x02,0xe4,0x00,0x27,0x00,0x41,0x00,0x3a,0x40,0x37,0x3f,0x01,0x03,0x04,0x32,0x01,0x01,0x00,0x02,0x4c,0x00,0x03,0x04,0x00,0x04,0x03,0x00,0x80,0x00,0x00,0x01,0x04,0x00,0x01,0x7e,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e, 0x4d,0x00,0x01,0x01,0x05,0x61,0x00,0x05,0x05,0x3f,0x05,0x4e,0x2b,0x22,0x12,0x2b,0x22,0x10,0x06,0x09,0x1c,0x2b,0x37,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x13,0x14, 0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x06,0x06,0x41,0x2a,0x61,0x52,0x3a,0x44,0x31,0x2b,0x6d,0x3e,0x49,0x81,0x6d,0x5c,0x6b,0x2a,0x57,0x4a,0x37,0x40,0x32,0x2b,0x6e,0x41,0x4c,0x86,0x73,0x66,0x77,0x35,0x3b,0x33,0x6d,0x36,0x3f,0x23,0x1f,0x31,0x39,0x3f, 0x35,0x6c,0x38,0x41,0x27,0x20,0x2f,0x37,0xc0,0x4a,0x57,0x4c,0x40,0x24,0x40,0x13,0x31,0x1c,0x67,0x3d,0x60,0x71,0x65,0x56,0x44,0x4f,0x3f,0x36,0x1f,0x39,0x13,0x31,0x1d,0x72,0x46,0x67,0x79,0x6d,0x01,0xb5,0x31,0x55,0x17,0x32,0x19,0x53,0x2f,0x2b,0x4a,0x14,0x12,0x5e,0x3e,0x3a,0x5f,0x17,0x30,0x19,0x4e,0x2a,0x29,0x3d,0x0b,0x0b, 0x54,0x00,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x07,0x00,0x0b,0x00,0x2b,0x40,0x28,0x05,0x02,0x02,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x00,0x04,0x04,0x03,0x5f,0x06,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x0b,0x0a,0x09,0x08,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x07,0x09,0x19,0x2b,0x33, 0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x27,0x33,0x11,0x23,0xe5,0xb3,0x01,0xf4,0xb1,0x66,0x3c,0x3c,0x02,0xb2,0x28,0x28,0xfd,0x4e,0x28,0x02,0x8a,0x00,0x02,0x00,0x4a,0xff,0xf6,0x02,0x0e,0x02,0xda,0x00,0x10,0x00,0x16,0x00,0x32,0x40,0x2f,0x11,0x06,0x02,0x02,0x04,0x01,0x4c,0x00,0x04,0x04,0x01,0x5f,0x03,0x01,0x01,0x01,0x38,0x4d, 0x00,0x02,0x02,0x00,0x61,0x05,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x13,0x12,0x0d,0x0c,0x09,0x07,0x05,0x04,0x00,0x10,0x01,0x10,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x27,0x11,0x23,0x11,0x14,0x16,0x01,0x2c,0x67,0x7b,0x90,0x24,0x2e,0x56,0x62,0x2a,0x7a, 0xe4,0x3c,0x20,0x0a,0x77,0x65,0x02,0x08,0xfd,0x53,0x0f,0x61,0x53,0x02,0x08,0xfd,0xf8,0x65,0x77,0x4f,0x02,0x6d,0xfe,0x20,0x2e,0x47,0x00,0x00,0x00,0x02,0x00,0x2e,0x00,0x00,0x02,0x2a,0x02,0xda,0x00,0x0c,0x00,0x10,0x00,0x2f,0x40,0x2c,0x06,0x01,0x03,0x04,0x01,0x4c,0x00,0x04,0x04,0x00,0x5f,0x01,0x01,0x00,0x00,0x38,0x4d,0x00, 0x03,0x03,0x02,0x5f,0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x10,0x0f,0x0e,0x0d,0x00,0x0c,0x00,0x0c,0x18,0x11,0x06,0x09,0x18,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x27,0x33,0x03,0x23,0xdd,0xaf,0x98,0x7f,0x0d,0x0e,0x01,0x02,0x0f,0x0d,0x7f,0x2c,0xaf,0x7b,0x3d,0x9a,0x3e,0x02,0xda,0xfd, 0xe4,0x37,0x42,0x11,0x11,0x43,0x36,0x02,0x1c,0xfd,0x26,0x28,0x02,0x8a,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0xda,0x00,0x1f,0x00,0x23,0x00,0x2d,0x00,0x3a,0x40,0x37,0x2d,0x29,0x1a,0x0f,0x06,0x05,0x05,0x06,0x01,0x4c,0x00,0x06,0x06,0x00,0x5f,0x02,0x01,0x02,0x00,0x00,0x38,0x4d,0x07,0x01,0x05,0x05,0x03,0x60, 0x08,0x04,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x25,0x24,0x23,0x22,0x21,0x20,0x00,0x1f,0x00,0x1f,0x11,0x18,0x18,0x11,0x09,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x23,0x27,0x26,0x26,0x35,0x23,0x06,0x06,0x07,0x07,0x27,0x33,0x03,0x23, 0x01,0x33,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x59,0x59,0x92,0x45,0x04,0x01,0x03,0x05,0x04,0x04,0x56,0x38,0x5f,0x05,0x04,0x03,0x04,0x02,0x03,0x40,0x2a,0x5d,0x8e,0x28,0x08,0x0d,0x02,0x02,0x0b,0x08,0x30,0x69,0x3c,0x51,0x3c,0x01,0x5f,0x3e,0x59,0x07,0x09,0x04,0x04,0x0b,0x05,0x08,0x02,0xda,0xfd,0xe4,0x1b,0x25,0x22,0x22, 0x25,0x1b,0x02,0x1c,0xfd,0xe4,0x1b,0x25,0x22,0x22,0x25,0x1b,0x02,0x1c,0xfd,0x26,0xd5,0x2e,0x65,0x21,0x28,0x66,0x26,0xd5,0x27,0x02,0x8c,0xfd,0x74,0x01,0xeb,0x27,0x46,0x1e,0x1c,0x48,0x27,0x3b,0x00,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0b,0x00,0x0f,0x00,0x34,0x40,0x31,0x0a,0x07,0x04,0x01,0x04,0x04, 0x05,0x01,0x4c,0x00,0x05,0x05,0x00,0x5f,0x01,0x01,0x00,0x00,0x38,0x4d,0x00,0x04,0x04,0x02,0x60,0x06,0x03,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x0f,0x0e,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x12,0x12,0x12,0x07,0x09,0x19,0x2b,0x33,0x13,0x03,0x33,0x13,0x13,0x33,0x03,0x13,0x23,0x03,0x03,0x25,0x33,0x01,0x23,0x22,0xcb,0xcf,0xa9, 0x85,0xa2,0x31,0xbd,0xd8,0xa9,0x8e,0xb1,0x01,0x5c,0x46,0xfe,0xb6,0x45,0x01,0x43,0x01,0x97,0xfe,0xfb,0x01,0x05,0xfe,0xcf,0xfe,0x57,0x01,0x17,0xfe,0xe9,0x28,0x02,0x8a,0x00,0x00,0x00,0x00,0x02,0x00,0x14,0x00,0x00,0x02,0x44,0x02,0xda,0x00,0x0e,0x00,0x14,0x00,0x33,0x40,0x30,0x14,0x11,0x0d,0x07,0x01,0x05,0x03,0x04,0x01,0x4c, 0x00,0x04,0x04,0x00,0x5f,0x01,0x01,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x02,0x5f,0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x13,0x12,0x10,0x0f,0x00,0x0e,0x00,0x0e,0x18,0x12,0x06,0x09,0x18,0x2b,0x33,0x11,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x11,0x27,0x33,0x35,0x03,0x23,0x13,0xe6,0xd2,0xa2,0x92, 0x0a,0x0f,0x03,0x03,0x12,0x0a,0x92,0x2f,0xce,0x66,0x3c,0xb4,0x42,0xba,0x01,0x04,0x01,0xd6,0xfe,0xba,0x16,0x2a,0x0a,0x0b,0x2c,0x16,0x01,0x43,0xfe,0x45,0xfe,0xe1,0x28,0xf7,0x01,0x93,0xfe,0x60,0x00,0x00,0x00,0x02,0x00,0x46,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x09,0x00,0x0d,0x00,0x3c,0x40,0x39,0x06,0x01,0x02,0x02,0x00,0x01, 0x4c,0x00,0x01,0x04,0x01,0x00,0x02,0x01,0x00,0x67,0x07,0x05,0x02,0x02,0x03,0x03,0x02,0x57,0x07,0x05,0x02,0x02,0x02,0x03,0x5f,0x06,0x01,0x03,0x02,0x03,0x4f,0x0a,0x0a,0x00,0x00,0x0a,0x0d,0x0a,0x0d,0x0c,0x0b,0x00,0x09,0x00,0x09,0x12,0x11,0x12,0x08,0x06,0x19,0x2b,0x33,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x25,0x01, 0x23,0x01,0x46,0x01,0x2e,0xfe,0xdc,0x01,0xbd,0xfe,0xd2,0x01,0x33,0xfe,0xa0,0x01,0x30,0x41,0xfe,0xd0,0x2c,0x02,0x86,0x28,0x2c,0xfd,0x7a,0x28,0x28,0x02,0x8a,0xfd,0x76,0x00,0x00,0x00,0x00,0x04,0x00,0x36,0xff,0xf6,0x02,0x10,0x02,0x30,0x00,0x1a,0x00,0x23,0x00,0x2d,0x00,0x32,0x00,0xb2,0x4b,0xb0,0x18,0x50,0x58,0x40,0x11,0x20, 0x01,0x02,0x04,0x2f,0x2e,0x2b,0x18,0x04,0x06,0x08,0x2c,0x01,0x00,0x06,0x03,0x4c,0x1b,0x40,0x11,0x20,0x01,0x02,0x04,0x2f,0x2e,0x2b,0x18,0x04,0x06,0x08,0x2c,0x01,0x07,0x06,0x03,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x29,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x08,0x06,0x01,0x08,0x67,0x00,0x02,0x02,0x04, 0x61,0x00,0x04,0x04,0x41,0x4d,0x0a,0x07,0x02,0x06,0x06,0x00,0x61,0x05,0x09,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x31,0x00,0x03,0x02,0x01,0x02,0x03,0x01,0x80,0x00,0x01,0x00,0x08,0x06,0x01,0x08,0x67,0x00,0x02,0x02,0x04,0x61,0x00,0x04,0x04,0x41,0x4d,0x00,0x06,0x06,0x05,0x5f,0x00,0x05,0x05,0x39,0x4d,0x0a,0x01,0x07,0x07, 0x00,0x61,0x09,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1d,0x25,0x24,0x01,0x00,0x2a,0x28,0x24,0x2d,0x25,0x2d,0x1c,0x1b,0x17,0x16,0x13,0x11,0x0f,0x0e,0x0c,0x0a,0x07,0x05,0x00,0x1a,0x01,0x1a,0x0b,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x36,0x36,0x33,0x32,0x16,0x15, 0x11,0x23,0x35,0x06,0x06,0x37,0x33,0x11,0x34,0x26,0x27,0x16,0x16,0x15,0x03,0x32,0x36,0x35,0x35,0x23,0x22,0x07,0x15,0x16,0x27,0x35,0x06,0x15,0x14,0xe7,0x52,0x5f,0x5e,0x52,0x9a,0x44,0x3b,0x39,0x49,0x03,0x2a,0x03,0x68,0x67,0x73,0x79,0x90,0x10,0x50,0x8a,0x3c,0x4a,0x44,0x26,0x2c,0xc0,0x45,0x51,0x9a,0x11,0x0f,0x11,0x3b,0x3c, 0x0a,0x5a,0x4d,0x4b,0x57,0x38,0x44,0x4a,0x45,0x3a,0x4a,0x60,0x5f,0x5a,0xfe,0x89,0x53,0x2b,0x32,0x32,0x01,0x4f,0x3e,0x4e,0x0a,0x10,0x51,0x35,0xfe,0xa7,0x4a,0x3f,0x70,0x03,0xf3,0x03,0x11,0xd8,0x20,0x4a,0x4e,0x00,0x00,0x00,0x00,0x04,0x00,0x4b,0xff,0xf6,0x02,0x17,0x02,0xda,0x00,0x11,0x00,0x15,0x00,0x23,0x00,0x2a,0x00,0x9e, 0x4b,0xb0,0x18,0x50,0x58,0x40,0x0e,0x2a,0x24,0x1a,0x08,0x03,0x05,0x04,0x07,0x19,0x01,0x00,0x04,0x02,0x4c,0x1b,0x40,0x0e,0x2a,0x24,0x1a,0x08,0x03,0x05,0x04,0x07,0x19,0x01,0x06,0x04,0x02,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x00,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x07,0x07,0x03,0x61,0x00,0x03,0x03, 0x41,0x4d,0x09,0x06,0x02,0x04,0x04,0x00,0x61,0x01,0x08,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x2b,0x00,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x07,0x07,0x03,0x61,0x00,0x03,0x03,0x41,0x4d,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x01,0x39,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59, 0x40,0x1b,0x17,0x16,0x01,0x00,0x1e,0x1c,0x16,0x23,0x17,0x23,0x15,0x14,0x13,0x12,0x0c,0x0a,0x07,0x06,0x05,0x04,0x00,0x11,0x01,0x11,0x0a,0x09,0x16,0x2b,0x05,0x22,0x26,0x27,0x15,0x23,0x11,0x33,0x11,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x25,0x33,0x11,0x23,0x13,0x32,0x36,0x37,0x11,0x26,0x26,0x23,0x22,0x06,0x15,0x15, 0x14,0x16,0x37,0x36,0x35,0x35,0x34,0x26,0x27,0x01,0x6e,0x37,0x4c,0x10,0x90,0x90,0x10,0x4c,0x37,0x4e,0x5b,0x5b,0xfe,0xb9,0x3c,0x3c,0xef,0x09,0x12,0x08,0x08,0x12,0x09,0x3f,0x4a,0x4a,0x8c,0x3c,0x1f,0x1d,0x0a,0x30,0x2a,0x50,0x02,0xda,0xfe,0xfc,0x2a,0x30,0x6c,0x5c,0xab,0x5b,0x6c,0x32,0x02,0x8a,0xfd,0x6c,0x02,0x02,0x01,0xe2, 0x02,0x02,0x56,0x4a,0xab,0x49,0x56,0x16,0x29,0x60,0xab,0x2f,0x47,0x14,0x00,0x00,0x00,0x02,0x00,0x4b,0xff,0xf6,0x02,0x0d,0x02,0x30,0x00,0x19,0x00,0x21,0x00,0x47,0x40,0x44,0x1b,0x10,0x02,0x02,0x03,0x1a,0x11,0x02,0x04,0x05,0x02,0x4c,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x00,0x03,0x03, 0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x17,0x16,0x14,0x12,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x19,0x01,0x19,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x07,0x11,0x16,0x33,0x32,0x36,0x35,0x33,0x14, 0x06,0x27,0x11,0x06,0x06,0x15,0x15,0x14,0x16,0x01,0x2f,0x69,0x7b,0x7b,0x69,0x66,0x78,0x2a,0x61,0x53,0x2f,0x25,0x25,0x2f,0x53,0x61,0x2a,0x78,0xe4,0x1c,0x20,0x20,0x0a,0x71,0x60,0x97,0x61,0x71,0x71,0x61,0x4e,0x5c,0x0e,0xfe,0x32,0x0e,0x5b,0x4e,0x60,0x71,0x4d,0x01,0x9f,0x16,0x43,0x2b,0x97,0x2b,0x42,0x00,0x00,0x04,0x00,0x41, 0xff,0xf6,0x02,0x0d,0x02,0xda,0x00,0x11,0x00,0x15,0x00,0x23,0x00,0x2a,0x00,0x9e,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0e,0x25,0x24,0x20,0x0f,0x0a,0x05,0x04,0x07,0x21,0x01,0x00,0x04,0x02,0x4c,0x1b,0x40,0x0e,0x25,0x24,0x20,0x0f,0x0a,0x05,0x04,0x07,0x21,0x01,0x06,0x04,0x02,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x00,0x05, 0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x09,0x06,0x02,0x04,0x04,0x00,0x61,0x03,0x08,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x2b,0x00,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03, 0x39,0x4d,0x09,0x01,0x06,0x06,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1b,0x17,0x16,0x01,0x00,0x1e,0x1c,0x16,0x23,0x17,0x23,0x15,0x14,0x13,0x12,0x0e,0x0d,0x0c,0x0b,0x08,0x06,0x00,0x11,0x01,0x11,0x0a,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x11,0x33,0x11,0x23,0x35,0x06,0x06, 0x37,0x33,0x11,0x23,0x03,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x11,0x16,0x16,0x27,0x11,0x06,0x06,0x15,0x15,0x14,0xea,0x4e,0x5b,0x5b,0x4e,0x37,0x4c,0x10,0x90,0x90,0x10,0x4c,0x86,0x3c,0x3c,0xb3,0x3f,0x4a,0x4a,0x3f,0x09,0x12,0x08,0x08,0x12,0x44,0x1c,0x20,0x0a,0x6c,0x5b,0xab,0x5c,0x6c,0x30,0x2a,0x01,0x04,0xfd, 0x26,0x50,0x2a,0x30,0x32,0x02,0x8a,0xfd,0x6c,0x56,0x49,0xab,0x4a,0x56,0x02,0x02,0xfe,0x1e,0x02,0x02,0x16,0x01,0xbe,0x14,0x47,0x2f,0xab,0x60,0x00,0x04,0x00,0x46,0xff,0xf6,0x02,0x12,0x02,0x30,0x00,0x15,0x00,0x1c,0x00,0x22,0x00,0x2a,0x00,0x4f,0x40,0x4c,0x24,0x22,0x1c,0x18,0x04,0x05,0x06,0x23,0x0d,0x02,0x03,0x04,0x02,0x4c, 0x00,0x04,0x02,0x03,0x02,0x04,0x03,0x80,0x07,0x01,0x05,0x00,0x02,0x04,0x05,0x02,0x67,0x00,0x06,0x06,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x1e,0x1d,0x1b,0x19,0x17,0x16,0x13,0x12,0x10,0x0e,0x0c,0x0b,0x08,0x06,0x00,0x15,0x01,0x15,0x09,0x09,0x16,0x2b,0x05, 0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x21,0x15,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x03,0x33,0x35,0x26,0x23,0x22,0x07,0x17,0x33,0x35,0x34,0x26,0x27,0x01,0x11,0x06,0x06,0x15,0x15,0x14,0x16,0x01,0x2e,0x6b,0x7d,0x7d,0x6b,0x69,0x7b,0xfe,0xc4,0x26,0x32,0x53,0x64,0x03,0x2a,0x03,0x7b,0xbe,0xac,0x25,0x2f, 0x32,0x26,0xd6,0x3c,0x1f,0x1d,0xff,0x00,0x1c,0x20,0x20,0x0a,0x71,0x60,0x97,0x61,0x71,0x71,0x61,0x5a,0xd7,0x0f,0x56,0x49,0x5b,0x6c,0x01,0x36,0xce,0x0e,0x0f,0xcd,0x32,0x2b,0x43,0x16,0xfe,0x62,0x01,0x9d,0x16,0x42,0x2b,0x97,0x2b,0x42,0x00,0x00,0x00,0x02,0x00,0x41,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x14,0x00,0x1a,0x00,0x40, 0x40,0x3d,0x17,0x01,0x02,0x04,0x01,0x4c,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x06,0x01,0x01,0x01,0x02,0x5f,0x05,0x01,0x02,0x02,0x3b,0x4d,0x09,0x07,0x02,0x00,0x00,0x08,0x5f,0x0a,0x01,0x08,0x08,0x39,0x08,0x4e,0x00,0x00,0x16,0x15,0x00,0x14,0x00,0x14,0x11,0x11,0x11,0x11,0x23,0x11,0x11,0x11,0x0b,0x09,0x1e,0x2b, 0x33,0x35,0x33,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x25,0x33,0x11,0x06,0x06,0x15,0x41,0x8d,0x8d,0x8d,0x3d,0x3d,0xca,0xb4,0xb4,0xb4,0xb4,0xfe,0xe6,0x3c,0x1d,0x1f,0x28,0x01,0xd6,0x28,0x37,0x3b,0x42,0x28,0x8c,0x28,0xfe,0x2a,0x28,0x28,0x02,0x89,0x04,0x2f,0x21,0x00,0x00, 0x00,0x04,0x00,0x41,0xff,0x4c,0x02,0x0d,0x02,0x30,0x00,0x19,0x00,0x25,0x00,0x2a,0x00,0x32,0x00,0x9f,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0f,0x2c,0x2b,0x24,0x23,0x13,0x06,0x06,0x05,0x06,0x26,0x01,0x00,0x01,0x02,0x4c,0x1b,0x40,0x12,0x23,0x01,0x07,0x06,0x2c,0x2b,0x24,0x13,0x06,0x05,0x05,0x07,0x26,0x01,0x00,0x01,0x03,0x4c,0x59, 0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x07,0x01,0x06,0x06,0x02,0x61,0x03,0x01,0x02,0x02,0x41,0x4d,0x09,0x01,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x00,0x00,0x04,0x5f,0x08,0x01,0x04,0x04,0x3d,0x04,0x4e,0x1b,0x40,0x2b,0x00,0x06,0x06,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x00,0x07,0x07,0x03,0x5f,0x00,0x03,0x03,0x3b, 0x4d,0x09,0x01,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x3f,0x4d,0x00,0x00,0x00,0x04,0x5f,0x08,0x01,0x04,0x04,0x3d,0x04,0x4e,0x59,0x40,0x17,0x1b,0x1a,0x00,0x00,0x2a,0x29,0x22,0x20,0x1a,0x25,0x1b,0x25,0x00,0x19,0x00,0x18,0x13,0x25,0x24,0x31,0x0a,0x09,0x1a,0x2b,0x17,0x35,0x33,0x32,0x32,0x37,0x35,0x06,0x06,0x23,0x22,0x26,0x35, 0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x35,0x33,0x11,0x14,0x06,0x23,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x07,0x11,0x16,0x17,0x36,0x35,0x11,0x23,0x01,0x11,0x06,0x06,0x15,0x15,0x14,0x16,0x6d,0xfd,0x05,0x0a,0x04,0x10,0x4a,0x37,0x4f,0x5c,0x5c,0x4f,0x37,0x4a,0x10,0x90,0x58,0x4b,0x74,0x40,0x47,0x47,0x40,0x15,0x10,0x10, 0xc6,0x3c,0x3c,0xff,0x00,0x1c,0x20,0x20,0xb4,0x28,0x01,0xd8,0x29,0x2e,0x6c,0x5b,0xab,0x5c,0x6c,0x2e,0x29,0x4d,0xfd,0xcb,0x4c,0x59,0xd2,0x56,0x49,0xab,0x4a,0x56,0x04,0xfe,0x1e,0x04,0x9c,0x1e,0x51,0x02,0x0d,0xfe,0x37,0x01,0xbc,0x14,0x46,0x2f,0xab,0x2f,0x45,0x00,0x00,0x03,0x00,0x4b,0x00,0x00,0x02,0x10,0x02,0xda,0x00,0x12, 0x00,0x16,0x00,0x1b,0x00,0x40,0x40,0x3d,0x1b,0x0c,0x03,0x03,0x05,0x03,0x01,0x4c,0x00,0x06,0x06,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x07,0x01,0x05,0x05,0x02,0x5f,0x08,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x18,0x17,0x16,0x15,0x14,0x13,0x00,0x12,0x00,0x12,0x22,0x13, 0x23,0x11,0x09,0x09,0x1a,0x2b,0x33,0x11,0x33,0x11,0x36,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x26,0x23,0x22,0x06,0x15,0x11,0x27,0x33,0x11,0x23,0x01,0x33,0x11,0x34,0x27,0x4b,0x90,0x11,0x48,0x34,0x4d,0x5b,0x90,0x0f,0x13,0x3d,0x46,0x66,0x3c,0x3c,0x01,0x35,0x3c,0x3c,0x02,0xda,0xfe,0xfe,0x2a,0x2e,0x6c,0x5c,0xfe,0x98,0x02, 0x04,0x04,0x56,0x4a,0xfe,0x98,0x28,0x02,0x8a,0xfd,0x76,0x01,0x40,0x60,0x29,0x00,0x00,0x04,0x00,0x41,0x00,0x00,0x02,0x26,0x03,0x19,0x00,0x0b,0x00,0x17,0x00,0x21,0x00,0x25,0x00,0x8b,0x4b,0xb0,0x11,0x50,0x58,0x40,0x2d,0x0c,0x01,0x02,0x0b,0x01,0x00,0x06,0x02,0x00,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x40,0x4d,0x0a, 0x01,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3b,0x4d,0x09,0x07,0x02,0x04,0x04,0x08,0x5f,0x0d,0x01,0x08,0x08,0x39,0x08,0x4e,0x1b,0x40,0x2b,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x0c,0x01,0x02,0x0b,0x01,0x00,0x06,0x02,0x00,0x69,0x0a,0x01,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3b,0x4d,0x09,0x07,0x02,0x04,0x04,0x08,0x5f,0x0d, 0x01,0x08,0x08,0x39,0x08,0x4e,0x59,0x40,0x25,0x18,0x18,0x0d,0x0c,0x01,0x00,0x25,0x24,0x23,0x22,0x18,0x21,0x18,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0e,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34, 0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x35,0x33,0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x25,0x33,0x11,0x23,0x01,0x3b,0x29,0x31,0x31,0x29,0x29,0x31,0x31,0x29,0x17,0x1b,0x1b,0x17,0x17,0x1b,0x1b,0xe3,0xb3,0x9a,0x01,0x2a,0xa2,0xfe,0xf8,0x3c,0x3c,0x02,0x7d,0x2a,0x24,0x24,0x2a,0x2a,0x24,0x24,0x2a,0x23,0x18,0x13,0x14,0x17,0x17, 0x14,0x13,0x18,0xfd,0x60,0x28,0x01,0xd6,0x28,0xfe,0x02,0x28,0x28,0x01,0xd6,0x00,0x00,0x04,0x00,0x4b,0xff,0x4c,0x01,0xbd,0x03,0x19,0x00,0x0b,0x00,0x17,0x00,0x24,0x00,0x29,0x00,0x8b,0xb6,0x25,0x1c,0x02,0x04,0x05,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x2b,0x0a,0x01,0x02,0x09,0x01,0x00,0x06,0x02,0x00,0x69,0x00,0x03,0x03, 0x01,0x61,0x00,0x01,0x01,0x40,0x4d,0x08,0x01,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3b,0x4d,0x00,0x04,0x04,0x07,0x5f,0x0b,0x01,0x07,0x07,0x3d,0x07,0x4e,0x1b,0x40,0x29,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x0a,0x01,0x02,0x09,0x01,0x00,0x06,0x02,0x00,0x69,0x08,0x01,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3b,0x4d,0x00,0x04, 0x04,0x07,0x5f,0x0b,0x01,0x07,0x07,0x3d,0x07,0x4e,0x59,0x40,0x21,0x18,0x18,0x0d,0x0c,0x01,0x00,0x29,0x28,0x18,0x24,0x18,0x23,0x20,0x1f,0x1e,0x1d,0x1b,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34, 0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x35,0x33,0x32,0x37,0x11,0x23,0x35,0x21,0x11,0x14,0x06,0x23,0x37,0x36,0x35,0x11,0x23,0x01,0x63,0x29,0x31,0x31,0x29,0x29,0x31,0x31,0x29,0x17,0x1b,0x1b,0x17,0x17,0x1b,0x1b,0xfe,0xff,0x9f,0x1c,0x16,0xbd,0x01,0x4d,0x66,0x5c,0x5c,0x3c,0x3c,0x02,0x7d,0x2a,0x24,0x24,0x2a,0x2a,0x24,0x24, 0x2a,0x23,0x18,0x13,0x14,0x17,0x17,0x14,0x13,0x18,0xfc,0xac,0x28,0x06,0x02,0x84,0x28,0xfd,0xe4,0x59,0x65,0x40,0x26,0x58,0x01,0xf4,0x00,0x00,0x00,0x03,0x00,0x4b,0x00,0x00,0x02,0x32,0x02,0xda,0x00,0x0c,0x00,0x10,0x00,0x14,0x00,0x47,0x40,0x44,0x13,0x07,0x02,0x01,0x02,0x14,0x01,0x04,0x01,0x02,0x4c,0x00,0x01,0x00,0x04,0x06, 0x01,0x04,0x67,0x00,0x07,0x07,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x02,0x02,0x3b,0x4d,0x08,0x01,0x06,0x06,0x03,0x60,0x09,0x05,0x02,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x00,0x0c,0x00,0x0c,0x11,0x12,0x11,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x33,0x11,0x33,0x11,0x33,0x37,0x33,0x07,0x13,0x23,0x03, 0x23,0x11,0x27,0x33,0x11,0x23,0x01,0x33,0x03,0x07,0x4b,0x90,0x37,0xd6,0x3e,0x99,0xa5,0xa8,0x67,0x48,0x66,0x3c,0x3c,0x01,0x36,0x44,0x82,0x2a,0x02,0xda,0xfe,0x51,0xfb,0xaf,0xfe,0x89,0x01,0x03,0xfe,0xfd,0x28,0x02,0x8a,0xfd,0x76,0x01,0x2a,0x2f,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0a,0x00,0x0f,0x00,0x31, 0x40,0x2e,0x0b,0x01,0x03,0x01,0x01,0x4c,0x04,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x03,0x03,0x00,0x5f,0x05,0x01,0x00,0x00,0x39,0x00,0x4e,0x01,0x00,0x0d,0x0c,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x0a,0x01,0x0a,0x06,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x27,0x11,0x23,0x11, 0x14,0x01,0x6a,0x43,0x49,0xac,0x01,0x3d,0xb7,0xe1,0x3c,0x47,0x40,0x02,0x26,0x2d,0xfd,0x53,0x2d,0x30,0x02,0x7d,0xfd,0xda,0x48,0x00,0x00,0x00,0x00,0x04,0x00,0x0f,0x00,0x00,0x02,0x49,0x02,0x30,0x00,0x1c,0x00,0x22,0x00,0x28,0x00,0x2c,0x00,0xc1,0x4b,0xb0,0x1a,0x50,0x58,0x40,0x0e,0x28,0x22,0x09,0x03,0x04,0x07,0x05,0x01,0x4c, 0x12,0x01,0x05,0x01,0x4b,0x1b,0x40,0x11,0x28,0x22,0x02,0x0a,0x05,0x09,0x03,0x02,0x07,0x0a,0x02,0x4c,0x12,0x01,0x05,0x01,0x4b,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1d,0x0a,0x01,0x05,0x05,0x00,0x61,0x02,0x01,0x02,0x00,0x00,0x3b,0x4d,0x09,0x08,0x02,0x07,0x07,0x03,0x60,0x0b,0x06,0x04,0x03,0x03,0x03,0x39,0x03,0x4e,0x1b,0x4b, 0xb0,0x1a,0x50,0x58,0x40,0x27,0x0a,0x01,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x0a,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x3b,0x4d,0x09,0x08,0x02,0x07,0x07,0x03,0x60,0x0b,0x06,0x04,0x03,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x25,0x00,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x00,0x0a,0x0a,0x00,0x5f, 0x00,0x00,0x00,0x3b,0x4d,0x09,0x08,0x02,0x07,0x07,0x03,0x60,0x0b,0x06,0x04,0x03,0x03,0x03,0x39,0x03,0x4e,0x59,0x59,0x40,0x17,0x00,0x00,0x2c,0x2b,0x2a,0x29,0x24,0x23,0x1e,0x1d,0x00,0x1c,0x00,0x1c,0x11,0x15,0x13,0x24,0x23,0x11,0x0c,0x09,0x1c,0x2b,0x33,0x11,0x33,0x15,0x36,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16, 0x15,0x11,0x23,0x11,0x06,0x06,0x15,0x11,0x23,0x11,0x06,0x06,0x15,0x11,0x25,0x33,0x11,0x34,0x26,0x27,0x03,0x33,0x11,0x34,0x26,0x27,0x03,0x33,0x11,0x23,0x0f,0x8c,0x07,0x34,0x29,0x26,0x38,0x0a,0x06,0x39,0x2d,0x36,0x40,0x8e,0x24,0x2a,0x82,0x24,0x2a,0x01,0x46,0x3c,0x20,0x1c,0xd0,0x32,0x1b,0x17,0xda,0x3c,0x3c,0x02,0x26,0x42, 0x23,0x29,0x2a,0x24,0x24,0x2a,0x46,0x3b,0xfe,0x51,0x02,0x07,0x04,0x32,0x28,0xfe,0x57,0x02,0x08,0x02,0x34,0x29,0xfe,0x57,0x28,0x01,0x81,0x23,0x31,0x07,0xfe,0x24,0x01,0x81,0x21,0x2e,0x0a,0xfe,0x26,0x01,0xd6,0x00,0x00,0x00,0x00,0x03,0x00,0x4b,0x00,0x00,0x02,0x10,0x02,0x30,0x00,0x12,0x00,0x16,0x00,0x1b,0x00,0x7a,0x4b,0xb0, 0x18,0x50,0x58,0xb7,0x1b,0x0c,0x03,0x03,0x05,0x03,0x01,0x4c,0x1b,0x40,0x0b,0x0c,0x01,0x06,0x03,0x1b,0x03,0x02,0x05,0x06,0x02,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1a,0x06,0x01,0x03,0x03,0x00,0x61,0x01,0x01,0x00,0x00,0x3b,0x4d,0x07,0x01,0x05,0x05,0x02,0x5f,0x08,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x1b,0x40,0x22,0x00, 0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x06,0x06,0x00,0x5f,0x00,0x00,0x00,0x3b,0x4d,0x07,0x01,0x05,0x05,0x02,0x5f,0x08,0x04,0x02,0x02,0x02,0x39,0x02,0x4e,0x59,0x40,0x13,0x00,0x00,0x18,0x17,0x16,0x15,0x14,0x13,0x00,0x12,0x00,0x12,0x22,0x13,0x23,0x11,0x09,0x09,0x1a,0x2b,0x33,0x11,0x33,0x15,0x36,0x36,0x33,0x32, 0x16,0x15,0x11,0x23,0x11,0x26,0x23,0x22,0x06,0x15,0x11,0x27,0x33,0x11,0x23,0x01,0x33,0x11,0x34,0x27,0x4b,0x90,0x11,0x48,0x34,0x4d,0x5b,0x90,0x0f,0x13,0x3d,0x46,0x66,0x3c,0x3c,0x01,0x35,0x3c,0x3c,0x02,0x26,0x4b,0x29,0x2c,0x6c,0x5c,0xfe,0x98,0x02,0x04,0x04,0x56,0x4a,0xfe,0x98,0x28,0x01,0xd6,0xfe,0x2a,0x01,0x40,0x60,0x29, 0x00,0x04,0x00,0x46,0xff,0xf6,0x02,0x12,0x02,0x30,0x00,0x0d,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0x3a,0x40,0x37,0x27,0x20,0x19,0x18,0x16,0x15,0x11,0x10,0x08,0x02,0x03,0x01,0x4c,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x0f,0x0e,0x01,0x00,0x14,0x12, 0x0e,0x17,0x0f,0x17,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x37,0x11,0x26,0x23,0x22,0x07,0x11,0x16,0x27,0x11,0x06,0x06,0x15,0x15,0x14,0x16,0x05,0x36,0x36,0x35,0x35,0x34,0x26,0x27,0x01,0x2c,0x6a,0x7c,0x7c,0x6a,0x6a,0x7c,0x7c,0x6a, 0x31,0x25,0x25,0x31,0x30,0x26,0x26,0x50,0x1c,0x20,0x20,0x01,0x1c,0x1d,0x1f,0x1f,0x1d,0x0a,0x71,0x60,0x97,0x61,0x71,0x71,0x61,0x97,0x60,0x71,0x28,0x0f,0x01,0xcc,0x0f,0x0f,0xfe,0x34,0x0f,0x26,0x01,0x9e,0x16,0x43,0x2b,0x97,0x2b,0x42,0x16,0x16,0x42,0x2b,0x97,0x2b,0x43,0x16,0x00,0x00,0x00,0x04,0x00,0x4b,0xff,0x4c,0x02,0x17, 0x02,0x30,0x00,0x11,0x00,0x1f,0x00,0x23,0x00,0x2a,0x00,0x98,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0b,0x2a,0x24,0x16,0x15,0x10,0x03,0x06,0x04,0x05,0x01,0x4c,0x1b,0x40,0x0e,0x16,0x01,0x07,0x05,0x2a,0x24,0x15,0x10,0x03,0x05,0x04,0x07,0x02,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x07,0x01,0x05,0x05,0x00,0x61,0x01,0x01,0x00, 0x00,0x3b,0x4d,0x09,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f,0x4d,0x00,0x06,0x06,0x03,0x5f,0x08,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x2b,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x07,0x07,0x00,0x5f,0x00,0x00,0x00,0x3b,0x4d,0x09,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3f,0x4d,0x00,0x06,0x06,0x03, 0x5f,0x08,0x01,0x03,0x03,0x3d,0x03,0x4e,0x59,0x40,0x18,0x13,0x12,0x00,0x00,0x23,0x22,0x21,0x20,0x1a,0x18,0x12,0x1f,0x13,0x1f,0x00,0x11,0x00,0x11,0x25,0x23,0x11,0x0a,0x09,0x19,0x2b,0x17,0x11,0x33,0x15,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x11,0x37,0x32,0x36,0x37,0x11,0x26,0x26,0x23,0x22,0x06, 0x15,0x15,0x14,0x16,0x07,0x33,0x11,0x23,0x01,0x36,0x36,0x35,0x35,0x34,0x27,0x4b,0x90,0x10,0x4c,0x37,0x4e,0x5b,0x5b,0x4e,0x37,0x4c,0x10,0x89,0x09,0x12,0x08,0x08,0x12,0x09,0x3f,0x4a,0x4a,0xb0,0x3c,0x3c,0x01,0x3c,0x1d,0x1f,0x3c,0xb4,0x02,0xda,0x50,0x2a,0x30,0x6b,0x5c,0xab,0x5c,0x6c,0x30,0x2a,0xfe,0xfc,0xd2,0x02,0x02,0x01, 0xe2,0x02,0x02,0x55,0x4a,0xab,0x49,0x57,0xaa,0x02,0x8a,0xfe,0x36,0x14,0x47,0x2f,0xab,0x60,0x29,0x00,0x00,0x04,0x00,0x41,0xff,0x4c,0x02,0x0d,0x02,0x30,0x00,0x11,0x00,0x1f,0x00,0x23,0x00,0x2a,0x00,0x98,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0b,0x25,0x24,0x1d,0x1c,0x0e,0x01,0x06,0x04,0x05,0x01,0x4c,0x1b,0x40,0x0e,0x1c,0x01,0x07, 0x05,0x25,0x24,0x1d,0x0e,0x01,0x05,0x04,0x07,0x02,0x4c,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x07,0x01,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01,0x41,0x4d,0x09,0x01,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x3f,0x4d,0x00,0x06,0x06,0x03,0x5f,0x08,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x2b,0x00,0x05,0x05,0x01,0x61,0x00,0x01, 0x01,0x41,0x4d,0x00,0x07,0x07,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x09,0x01,0x04,0x04,0x00,0x61,0x00,0x00,0x00,0x3f,0x4d,0x00,0x06,0x06,0x03,0x5f,0x08,0x01,0x03,0x03,0x3d,0x03,0x4e,0x59,0x40,0x18,0x13,0x12,0x00,0x00,0x23,0x22,0x21,0x20,0x1a,0x18,0x12,0x1f,0x13,0x1f,0x00,0x11,0x00,0x11,0x13,0x25,0x23,0x0a,0x09,0x19,0x2b, 0x05,0x11,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x35,0x33,0x11,0x25,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x11,0x16,0x16,0x17,0x33,0x11,0x23,0x01,0x11,0x06,0x15,0x15,0x14,0x16,0x01,0x7d,0x10,0x4c,0x37,0x4e,0x5b,0x5b,0x4e,0x37,0x4c,0x10,0x90,0xfe,0xe7,0x3f,0x4a,0x4a,0x3f,0x09,0x12, 0x08,0x08,0x12,0xbc,0x3c,0x3c,0xff,0x00,0x3c,0x20,0xb4,0x01,0x04,0x2a,0x30,0x6c,0x5c,0xab,0x5c,0x6b,0x30,0x2a,0x50,0xfd,0x26,0xd2,0x57,0x49,0xab,0x4a,0x55,0x02,0x02,0xfe,0x1e,0x02,0x02,0xaa,0x02,0x8a,0xfe,0x36,0x01,0xbe,0x29,0x60,0xab,0x2f,0x47,0x00,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x00,0x02,0x30,0x02,0x30,0x00,0x19, 0x00,0x1d,0x00,0x77,0xb5,0x07,0x01,0x04,0x01,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x23,0x00,0x04,0x01,0x00,0x01,0x04,0x00,0x80,0x09,0x05,0x02,0x01,0x01,0x02,0x61,0x03,0x01,0x02,0x02,0x3b,0x4d,0x08,0x06,0x02,0x00,0x00,0x07,0x5f,0x0a,0x01,0x07,0x07,0x39,0x07,0x4e,0x1b,0x40,0x2b,0x00,0x04,0x01,0x00,0x01,0x04,0x00,0x80, 0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x41,0x4d,0x09,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x08,0x06,0x02,0x00,0x00,0x07,0x5f,0x0a,0x01,0x07,0x07,0x39,0x07,0x4e,0x59,0x40,0x14,0x00,0x00,0x1d,0x1c,0x1b,0x1a,0x00,0x19,0x00,0x19,0x13,0x23,0x13,0x23,0x11,0x11,0x11,0x0b,0x09,0x1d,0x2b,0x33,0x35,0x33,0x11,0x23, 0x35,0x33,0x15,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x33,0x15,0x27,0x33,0x11,0x23,0x2d,0x5f,0x5f,0xef,0x0f,0x40,0x2f,0x4e,0x48,0x2a,0x35,0x3f,0x3b,0x3b,0x78,0xde,0x3c,0x3c,0x28,0x01,0xd6,0x28,0x48,0x27,0x2b,0x6c,0x5c,0x23,0x23,0x4a,0x56,0x56,0x4a,0xfe,0xc0,0x28,0x28,0x01,0xd6, 0x00,0x02,0x00,0x4b,0xff,0xf6,0x02,0x0d,0x02,0x30,0x00,0x27,0x00,0x41,0x00,0x3b,0x40,0x38,0x3f,0x01,0x04,0x02,0x01,0x4c,0x32,0x01,0x01,0x01,0x4b,0x00,0x03,0x04,0x00,0x04,0x03,0x00,0x80,0x00,0x00,0x01,0x04,0x00,0x01,0x7e,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x41,0x4d,0x00,0x01,0x01,0x05,0x61,0x00,0x05,0x05,0x3f,0x05, 0x4e,0x2b,0x22,0x12,0x2b,0x22,0x10,0x06,0x09,0x1c,0x2b,0x37,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x13,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x36,0x36, 0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x06,0x06,0x4b,0x2a,0x05,0x5b,0x48,0x34,0x3c,0x22,0x1d,0x8f,0x33,0x3b,0x77,0x65,0x56,0x6f,0x0a,0x2a,0x09,0x4f,0x39,0x34,0x3c,0x1e,0x19,0x86,0x3b,0x44,0x7c,0x6b,0x60,0x76,0x2b,0x2b,0x25,0x90,0x2b,0x31,0x1d,0x17,0x2c,0x34,0x35,0x2d,0x85,0x27,0x2e,0x21,0x1a,0x2e,0x39, 0x8f,0x34,0x3c,0x2d,0x26,0x1c,0x2a,0x09,0x2b,0x0f,0x52,0x37,0x50,0x5c,0x4b,0x41,0x2f,0x35,0x2d,0x26,0x18,0x25,0x08,0x27,0x11,0x5c,0x3d,0x4e,0x5b,0x53,0x01,0x42,0x2b,0x3f,0x0b,0x2b,0x0d,0x3c,0x26,0x1f,0x32,0x0c,0x09,0x42,0x2f,0x30,0x49,0x0d,0x27,0x0b,0x37,0x24,0x1d,0x34,0x0d,0x0a,0x44,0x00,0x00,0x00,0x00,0x03,0x00,0x37, 0x00,0x00,0x02,0x12,0x02,0xc1,0x00,0x10,0x00,0x14,0x00,0x1a,0x00,0x46,0x40,0x43,0x15,0x01,0x06,0x01,0x01,0x4c,0x00,0x03,0x00,0x08,0x02,0x03,0x08,0x67,0x09,0x05,0x02,0x01,0x01,0x02,0x5f,0x07,0x04,0x02,0x02,0x02,0x3b,0x4d,0x00,0x06,0x06,0x00,0x5f,0x0a,0x01,0x00,0x00,0x39,0x00,0x4e,0x01,0x00,0x17,0x16,0x14,0x13,0x12,0x11, 0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x10,0x01,0x10,0x0b,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x01,0x33,0x35,0x23,0x13,0x11,0x23,0x11,0x14,0x16,0x01,0x3b,0x3f,0x3b,0x8a,0x8a,0x90,0xc1,0xc1,0xbc,0xfe,0xde,0x3c,0x3c,0x3c,0x3c,0x1f, 0x40,0x3d,0x01,0x81,0x28,0x9b,0x9b,0x28,0xfe,0x2a,0x28,0x02,0x26,0x73,0xfd,0x91,0x01,0xd4,0xfe,0x7f,0x22,0x2c,0x00,0x00,0x00,0x02,0x00,0x50,0xff,0xf6,0x02,0x08,0x02,0x26,0x00,0x10,0x00,0x16,0x00,0x32,0x40,0x2f,0x11,0x06,0x02,0x02,0x04,0x01,0x4c,0x00,0x04,0x04,0x01,0x5f,0x03,0x01,0x01,0x01,0x3b,0x4d,0x00,0x02,0x02,0x00, 0x61,0x05,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x13,0x12,0x0d,0x0c,0x09,0x07,0x05,0x04,0x00,0x10,0x01,0x10,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x16,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x27,0x11,0x23,0x11,0x14,0x16,0x01,0x2d,0x66,0x77,0x90,0x24,0x29,0x52,0x5f,0x2a,0x76,0xdc,0x3c,0x20,0x0a, 0x77,0x65,0x01,0x54,0xfe,0x06,0x0e,0x61,0x53,0x01,0x54,0xfe,0xac,0x65,0x77,0x4e,0x01,0xba,0xfe,0xd4,0x2e,0x49,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x00,0x02,0x2b,0x02,0x26,0x00,0x0c,0x00,0x10,0x00,0x2f,0x40,0x2c,0x06,0x01,0x03,0x04,0x01,0x4c,0x00,0x04,0x04,0x00,0x5f,0x01,0x01,0x00,0x00,0x3b,0x4d,0x00,0x03,0x03,0x02,0x5f, 0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x10,0x0f,0x0e,0x0d,0x00,0x0c,0x00,0x0c,0x18,0x11,0x06,0x09,0x18,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x27,0x33,0x03,0x23,0xdc,0xaf,0x99,0x76,0x11,0x14,0x02,0x02,0x15,0x10,0x75,0x2c,0xae,0x81,0x3e,0x94,0x3f,0x02,0x26,0xfe,0x8e,0x35,0x48,0x0b, 0x0b,0x49,0x34,0x01,0x72,0xfd,0xda,0x28,0x01,0xd6,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x26,0x00,0x21,0x00,0x25,0x00,0x30,0x00,0x39,0x40,0x36,0x30,0x2b,0x10,0x06,0x04,0x05,0x06,0x01,0x4c,0x00,0x06,0x06,0x00,0x5f,0x02,0x01,0x02,0x00,0x00,0x3b,0x4d,0x07,0x01,0x05,0x05,0x03,0x60,0x08,0x04,0x02,0x03,0x03, 0x39,0x03,0x4e,0x00,0x00,0x27,0x26,0x25,0x24,0x23,0x22,0x00,0x21,0x00,0x21,0x11,0x1a,0x19,0x11,0x09,0x09,0x1a,0x2b,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x3e,0x02,0x37,0x13,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x26,0x36,0x37,0x13,0x33,0x03,0x23,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x27,0x33,0x03,0x23,0x01,0x33,0x03,0x26, 0x26,0x27,0x23,0x06,0x06,0x07,0x07,0x62,0x62,0x92,0x49,0x04,0x05,0x02,0x01,0x03,0x06,0x04,0x4c,0x34,0x5f,0x05,0x06,0x02,0x03,0x01,0x02,0x01,0x03,0x44,0x2e,0x61,0x98,0x24,0x04,0x0b,0x02,0x01,0x09,0x05,0x20,0x75,0x3d,0x55,0x3d,0x01,0x50,0x3d,0x50,0x06,0x0b,0x02,0x02,0x02,0x0c,0x05,0x0b,0x02,0x26,0xfe,0x71,0x16,0x21,0x15, 0x0e,0x10,0x17,0x16,0x01,0x90,0xfe,0x70,0x16,0x20,0x15,0x14,0x10,0x09,0x0e,0x11,0x01,0x8f,0xfd,0xda,0xa2,0x12,0x41,0x1e,0x16,0x43,0x18,0xa2,0x28,0x01,0xd6,0xfe,0x2a,0x01,0x5f,0x1b,0x43,0x16,0x16,0x43,0x1b,0x3a,0x00,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x3a,0x02,0x26,0x00,0x0b,0x00,0x0f,0x00,0x34,0x40,0x31,0x0a,0x07, 0x04,0x01,0x04,0x04,0x05,0x01,0x4c,0x00,0x05,0x05,0x00,0x5f,0x01,0x01,0x00,0x00,0x3b,0x4d,0x00,0x04,0x04,0x02,0x60,0x06,0x03,0x02,0x02,0x02,0x39,0x02,0x4e,0x00,0x00,0x0f,0x0e,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x12,0x12,0x12,0x07,0x09,0x19,0x2b,0x33,0x37,0x03,0x33,0x17,0x37,0x33,0x07,0x13,0x23,0x27,0x07,0x25,0x33,0x01,0x23, 0x3a,0xb2,0xce,0xb2,0x7e,0x8b,0x35,0xa9,0xd5,0xb2,0x84,0x94,0x01,0x30,0x4a,0xfe,0xcc,0x48,0xed,0x01,0x39,0xbf,0xbf,0xe3,0xfe,0xbd,0xc8,0xc8,0x28,0x01,0xd6,0x00,0x00,0x02,0x00,0x2d,0xff,0x4c,0x02,0x2b,0x02,0x26,0x00,0x0f,0x00,0x19,0x00,0x31,0x40,0x2e,0x13,0x10,0x09,0x06,0x04,0x00,0x04,0x01,0x4c,0x00,0x04,0x04,0x01,0x5f, 0x02,0x01,0x01,0x01,0x3b,0x4d,0x00,0x00,0x00,0x03,0x61,0x05,0x01,0x03,0x03,0x3d,0x03,0x4e,0x00,0x00,0x15,0x14,0x00,0x0f,0x00,0x0e,0x12,0x14,0x21,0x06,0x09,0x19,0x2b,0x17,0x35,0x33,0x32,0x36,0x37,0x37,0x03,0x33,0x13,0x13,0x33,0x01,0x06,0x06,0x23,0x37,0x36,0x36,0x37,0x03,0x23,0x13,0x1e,0x02,0x4f,0x2b,0x2f,0x3d,0x13,0x1e, 0xea,0x9f,0x99,0x98,0x2e,0xfe,0xf1,0x18,0x54,0x36,0xb4,0x05,0x10,0x0a,0x9e,0x42,0x8e,0x08,0x14,0x13,0xb4,0x28,0x31,0x2b,0x44,0x02,0x12,0xfe,0xa5,0x01,0x5b,0xfd,0x9b,0x36,0x3f,0xf9,0x0c,0x2c,0x18,0x01,0x69,0xfe,0xb7,0x12,0x2c,0x27,0x00,0x00,0x00,0x02,0x00,0x46,0x00,0x00,0x02,0x12,0x02,0x26,0x00,0x09,0x00,0x0d,0x00,0x32, 0x40,0x2f,0x06,0x01,0x02,0x02,0x00,0x01,0x4c,0x05,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x3b,0x4d,0x04,0x01,0x02,0x02,0x03,0x5f,0x06,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x0d,0x0c,0x0b,0x0a,0x00,0x09,0x00,0x09,0x12,0x11,0x12,0x07,0x09,0x19,0x2b,0x33,0x35,0x01,0x21,0x35,0x21,0x15,0x01,0x21,0x15,0x25,0x33,0x01,0x23, 0x46,0x01,0x1e,0xfe,0xeb,0x01,0xb6,0xfe,0xe4,0x01,0x29,0xfe,0x62,0x47,0x01,0x1d,0x46,0x29,0x01,0xd5,0x28,0x2a,0xfe,0x2c,0x28,0x28,0x01,0xd6,0x00,0x03,0x00,0x50,0xff,0xf6,0x02,0x08,0x02,0xe4,0x00,0x0e,0x00,0x1c,0x00,0x28,0x00,0x3e,0x40,0x3b,0x00,0x05,0x08,0x01,0x04,0x02,0x05,0x04,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01, 0x01,0x3e,0x4d,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x1e,0x1d,0x10,0x0f,0x01,0x00,0x24,0x22,0x1d,0x28,0x1e,0x28,0x17,0x15,0x0f,0x1c,0x10,0x1c,0x08,0x06,0x00,0x0e,0x01,0x0e,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x06,0x27,0x32,0x36,0x35,0x11, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x65,0x77,0x77,0x65,0x65,0x77,0x36,0x63,0x43,0x3c,0x49,0x49,0x3c,0x3c,0x49,0x49,0x3c,0x1b,0x21,0x21,0x1b,0x1b,0x21,0x21,0x0a,0x75,0x62,0x01,0x40,0x62,0x75,0x75,0x62,0xfe,0xc0,0x41,0x61,0x35,0x4d,0x4d,0x3d, 0x01,0x40,0x3d,0x4d,0x4d,0x3d,0xfe,0xc0,0x3d,0x4d,0xf3,0x1e,0x1c,0x1b,0x1d,0x1d,0x1b,0x1c,0x1e,0x00,0x00,0x01,0x00,0x5a,0x00,0x00,0x02,0x1c,0x02,0xda,0x00,0x0a,0x00,0x29,0x40,0x26,0x05,0x04,0x03,0x03,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0x38,0x4d,0x02,0x01,0x00,0x00,0x03,0x60,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00, 0x00,0x0a,0x00,0x0a,0x11,0x14,0x11,0x05,0x09,0x19,0x2b,0x33,0x35,0x33,0x11,0x07,0x35,0x37,0x33,0x11,0x33,0x15,0x5a,0xc6,0xc6,0xa5,0x7b,0xa2,0x52,0x02,0x3a,0x94,0x67,0x7b,0xfd,0x78,0x52,0x00,0x00,0x00,0x00,0x01,0x00,0x4c,0x00,0x00,0x02,0x0f,0x02,0xe4,0x00,0x18,0x00,0x34,0x40,0x31,0x01,0x01,0x03,0x01,0x01,0x4c,0x00,0x01, 0x00,0x03,0x00,0x01,0x03,0x80,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x18,0x00,0x18,0x16,0x22,0x12,0x27,0x06,0x09,0x1a,0x2b,0x33,0x35,0x13,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07, 0x07,0x21,0x15,0x56,0xf3,0x35,0x2c,0x45,0x3b,0x3d,0x47,0x5a,0x03,0x78,0x63,0x65,0x77,0x39,0x45,0xc5,0x01,0x4c,0x53,0x01,0x04,0x38,0x58,0x2a,0x3c,0x47,0x49,0x3e,0x63,0x74,0x72,0x62,0x34,0x74,0x48,0xce,0x52,0x00,0x00,0x00,0x00,0x01,0x00,0x46,0xff,0xf6,0x01,0xfe,0x02,0xda,0x00,0x1c,0x00,0x43,0x40,0x40,0x16,0x15,0x10,0x03, 0x03,0x04,0x01,0x4c,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x01,0x02,0x04,0x01,0x02,0x7e,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x05,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x14,0x13,0x12,0x11,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x1c,0x01,0x1c,0x07,0x09,0x16,0x2b,0x05,0x22,0x26, 0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23,0x35,0x37,0x21,0x35,0x21,0x15,0x07,0x16,0x16,0x15,0x15,0x14,0x06,0x01,0x21,0x65,0x76,0x5a,0x46,0x3c,0x3c,0x46,0x46,0x3c,0x4f,0xb3,0xfe,0xd4,0x01,0x92,0xb0,0x5a,0x68,0x77,0x0a,0x71,0x61,0x3c,0x46,0x46,0x3c,0x32,0x3c,0x46,0x4e,0xbe,0x52,0x54,0xbb,0x07,0x6f, 0x5b,0x32,0x61,0x71,0x00,0x01,0x00,0x46,0x00,0x00,0x01,0xea,0x02,0xda,0x00,0x0b,0x00,0x30,0x40,0x2d,0x06,0x03,0x02,0x02,0x03,0x01,0x4c,0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x68,0x00,0x01,0x01,0x38,0x4d,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x12,0x12,0x11,0x06,0x09, 0x1a,0x2b,0x21,0x35,0x21,0x35,0x01,0x33,0x01,0x15,0x33,0x35,0x33,0x11,0x01,0x90,0xfe,0xb6,0x01,0x0a,0x66,0xfe,0xea,0xf0,0x5a,0xa0,0x8d,0x01,0xad,0xfe,0x3f,0x27,0xb2,0xfe,0x5c,0x00,0x00,0x01,0x00,0x4b,0xff,0xf6,0x02,0x03,0x02,0xda,0x00,0x1b,0x00,0x3e,0x40,0x3b,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x06,0x00,0x03, 0x01,0x06,0x03,0x67,0x00,0x05,0x05,0x04,0x5f,0x00,0x04,0x04,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x16,0x14,0x13,0x12,0x11,0x10,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x1b,0x01,0x1b,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x23, 0x11,0x21,0x15,0x21,0x17,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x01,0x26,0x65,0x76,0x5a,0x46,0x3c,0x3c,0x46,0x44,0x3a,0xc7,0x01,0x85,0xfe,0xcf,0x02,0x76,0x65,0x6e,0x77,0x0a,0x71,0x61,0x3c,0x46,0x46,0x3c,0x2d,0x3c,0x46,0x01,0x63,0x52,0xbf,0x6f,0x65,0x2d,0x61,0x71,0x00,0x02,0x00,0x40,0xff,0xf6,0x02,0x18,0x02,0xda,0x00,0x15, 0x00,0x21,0x00,0x38,0x40,0x35,0x0a,0x01,0x04,0x02,0x01,0x4c,0x00,0x02,0x00,0x04,0x03,0x02,0x04,0x6a,0x00,0x01,0x01,0x38,0x4d,0x06,0x01,0x03,0x03,0x00,0x61,0x05,0x01,0x00,0x00,0x3f,0x00,0x4e,0x17,0x16,0x01,0x00,0x1d,0x1b,0x16,0x21,0x17,0x21,0x0f,0x0d,0x09,0x08,0x00,0x15,0x01,0x15,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x26, 0x35,0x34,0x36,0x37,0x13,0x33,0x03,0x17,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2d,0x46,0x6b,0x3c,0x24,0x1f,0xa9,0x64,0xb4,0x03,0x0d,0x34,0x1f,0x41,0x61,0x37,0x3c,0x69,0x47,0x41,0x51,0x51,0x41,0x41,0x51,0x51,0x0a,0x3b,0x69,0x45,0x30,0x65,0x37, 0x01,0x2f,0xfe,0xc7,0x02,0x11,0x12,0x39,0x64,0x42,0x46,0x6b,0x3c,0x50,0x56,0x45,0x45,0x56,0x56,0x45,0x45,0x56,0x00,0x00,0x00,0x01,0x00,0x52,0x00,0x00,0x02,0x22,0x02,0xda,0x00,0x08,0x00,0x52,0xb5,0x07,0x01,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x18,0x00,0x01,0x00,0x03,0x00,0x01,0x72,0x00,0x00,0x00,0x02,0x5f, 0x00,0x02,0x02,0x38,0x4d,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x19,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x59,0x40,0x0c,0x00,0x00,0x00,0x08,0x00,0x08,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x33,0x01,0x21,0x15,0x23,0x35,0x21,0x15, 0x01,0xbe,0x01,0x04,0xfe,0xea,0x5a,0x01,0xd0,0xfe,0xfe,0x02,0x88,0x76,0xc8,0x54,0xfd,0x7a,0x00,0x00,0x00,0x03,0x00,0x42,0xff,0xf6,0x02,0x16,0x02,0xe4,0x00,0x1d,0x00,0x29,0x00,0x35,0x00,0x45,0x40,0x42,0x16,0x07,0x02,0x05,0x02,0x01,0x4c,0x07,0x01,0x02,0x00,0x05,0x04,0x02,0x05,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01, 0x3e,0x4d,0x08,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x3f,0x00,0x4e,0x2b,0x2a,0x1f,0x1e,0x01,0x00,0x31,0x2f,0x2a,0x35,0x2b,0x35,0x25,0x23,0x1e,0x29,0x1f,0x29,0x10,0x0e,0x00,0x1d,0x01,0x1d,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14, 0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x13,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x45,0x6a,0x3b,0x4f,0x42,0x39,0x44,0x36,0x61,0x3f,0x40,0x60,0x36,0x44,0x39,0x42,0x4f,0x3b,0x69,0x46,0x38,0x44,0x44,0x38,0x37,0x45,0x45,0x37,0x40, 0x50,0x50,0x40,0x40,0x50,0x50,0x0a,0x36,0x61,0x3f,0x45,0x64,0x0b,0x03,0x0d,0x59,0x3a,0x39,0x57,0x31,0x31,0x57,0x39,0x3a,0x59,0x0d,0x03,0x0b,0x64,0x45,0x3f,0x61,0x36,0x01,0xb0,0x42,0x35,0x35,0x42,0x42,0x35,0x35,0x42,0xfe,0xa1,0x4b,0x3c,0x3d,0x4b,0x4b,0x3d,0x3c,0x4b,0x00,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x02,0x18, 0x02,0xe4,0x00,0x15,0x00,0x21,0x00,0x36,0x40,0x33,0x01,0x01,0x00,0x03,0x01,0x4c,0x06,0x01,0x03,0x00,0x00,0x02,0x03,0x00,0x69,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x05,0x01,0x02,0x02,0x39,0x02,0x4e,0x17,0x16,0x00,0x00,0x1d,0x1b,0x16,0x21,0x17,0x21,0x00,0x15,0x00,0x15,0x26,0x24,0x07,0x09,0x18,0x2b,0x33,0x13, 0x27,0x06,0x06,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x03,0x11,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xc3,0xb4,0x03,0x0a,0x36,0x20,0x3f,0x5f,0x36,0x3c,0x6a,0x45,0x47,0x6a,0x3c,0x24,0x1f,0xa9,0x41,0x51,0x51,0x41,0x41,0x51,0x51,0x01,0x39,0x02,0x10,0x13,0x39,0x64, 0x42,0x47,0x6a,0x3c,0x3b,0x69,0x45,0x30,0x65,0x37,0xfe,0xd1,0x01,0x5e,0x56,0x45,0x45,0x56,0x56,0x45,0x45,0x56,0x00,0x00,0x00,0x03,0x00,0x50,0xff,0xf6,0x02,0x08,0x02,0xe4,0x00,0x0e,0x00,0x16,0x00,0x1e,0x00,0x36,0x40,0x33,0x1c,0x1b,0x11,0x10,0x04,0x03,0x02,0x01,0x4c,0x00,0x02,0x02,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x05, 0x01,0x03,0x03,0x00,0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x18,0x17,0x01,0x00,0x17,0x1e,0x18,0x1e,0x15,0x13,0x08,0x06,0x00,0x0e,0x01,0x0e,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x06,0x03,0x11,0x01,0x26,0x26,0x23,0x22,0x06,0x13,0x32,0x36,0x35,0x11,0x01,0x16,0x16,0x01, 0x2c,0x65,0x77,0x77,0x65,0x65,0x77,0x36,0x63,0xc8,0x01,0x05,0x0b,0x44,0x31,0x3c,0x49,0x85,0x3c,0x49,0xfe,0xfb,0x0b,0x44,0x0a,0x75,0x62,0x01,0x40,0x62,0x75,0x75,0x62,0xfe,0xc0,0x41,0x61,0x35,0x02,0x17,0xfe,0xec,0x01,0x3c,0x2d,0x35,0x4d,0xfd,0xf9,0x4d,0x3d,0x01,0x14,0xfe,0xc4,0x2d,0x35,0x00,0x00,0x00,0x00,0x01,0x00,0x58, 0x00,0x00,0x02,0x13,0x02,0xe4,0x00,0x22,0x00,0x2e,0x40,0x2b,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x04,0x39,0x04,0x4e,0x00,0x00,0x00,0x22,0x00,0x22,0x1b,0x23,0x12,0x2b,0x06,0x09,0x1a,0x2b,0x33,0x35,0x34,0x36,0x36,0x37,0x37,0x36, 0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x3e,0x02,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x07,0x06,0x06,0x15,0x15,0x21,0x15,0x59,0x2b,0x4a,0x2d,0x64,0x28,0x2f,0x48,0x3a,0x3a,0x48,0x5a,0x02,0x39,0x62,0x3f,0x42,0x64,0x38,0x4a,0x40,0x66,0x2b,0x44,0x01,0x60,0x80,0x34,0x57,0x42,0x13,0x2b,0x11,0x48,0x29,0x3c,0x4b,0x4b, 0x3c,0x40,0x60,0x37,0x37,0x60,0x40,0x44,0x72,0x1c,0x2c,0x13,0x4c,0x35,0x29,0x52,0x00,0x02,0x00,0x55,0xff,0xf6,0x02,0x11,0x02,0xe4,0x00,0x1b,0x00,0x29,0x00,0x49,0x40,0x46,0x12,0x01,0x05,0x06,0x01,0x4c,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x04,0x00,0x06,0x05,0x04,0x06,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01, 0x3e,0x4d,0x08,0x01,0x05,0x05,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x1d,0x1c,0x01,0x00,0x24,0x22,0x1c,0x29,0x1d,0x29,0x16,0x14,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1b,0x01,0x1b,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x36,0x36,0x33,0x32, 0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x34,0x67,0x78,0x76,0x65,0x5b,0x72,0x07,0x5a,0x05,0x43,0x33,0x3b,0x45,0x0b,0x4f,0x3d,0x5e,0x6d,0x77,0x67,0x3d,0x47,0x47,0x3d,0x3d,0x47,0x47,0x0a,0x74,0x63,0x01,0x40,0x63,0x74,0x59,0x47,0x22,0x2e,0x49,0x3e,0xa5,0x30,0x37, 0x74,0x63,0x2b,0x63,0x74,0x50,0x49,0x3e,0x2b,0x3e,0x49,0x49,0x3e,0x2b,0x3e,0x49,0x00,0x02,0x00,0x49,0xff,0xf6,0x02,0x03,0x02,0xe4,0x00,0x1b,0x00,0x29,0x00,0x49,0x40,0x46,0x0b,0x01,0x05,0x06,0x01,0x4c,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x08,0x01,0x05,0x00,0x03,0x01,0x05,0x03,0x69,0x00,0x06,0x06,0x04,0x61,0x00,0x04, 0x04,0x3e,0x4d,0x00,0x02,0x02,0x00,0x61,0x07,0x01,0x00,0x00,0x3f,0x00,0x4e,0x1d,0x1c,0x01,0x00,0x24,0x22,0x1c,0x29,0x1d,0x29,0x16,0x14,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x1b,0x01,0x1b,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x06,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x11,0x14,0x06,0x03,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x28,0x5b,0x72,0x07,0x5a,0x05,0x43,0x33,0x3b,0x45,0x0a,0x4e,0x3e,0x5e,0x6c,0x76,0x66,0x67,0x77,0x76,0x67,0x3d,0x46,0x46,0x3d,0x3d,0x46,0x46,0x0a,0x5b,0x4a,0x25,0x30,0x49,0x3e,0xb8,0x32,0x39,0x74,0x63,0x1c,0x63,0x74,0x74, 0x63,0xfe,0xc0,0x63,0x74,0x01,0x74,0x49,0x3e,0x1c,0x3e,0x49,0x49,0x3e,0x1c,0x3e,0x49,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0xff,0xf6,0x02,0x16,0x02,0xe5,0x00,0x1b,0x00,0x29,0x00,0x37,0x00,0x36,0x40,0x33,0x31,0x1d,0x15,0x07,0x04,0x03,0x02,0x01,0x4c,0x00,0x02,0x02,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x05,0x01,0x03,0x03,0x00, 0x61,0x04,0x01,0x00,0x00,0x3f,0x00,0x4e,0x2b,0x2a,0x01,0x00,0x2a,0x37,0x2b,0x37,0x25,0x23,0x0f,0x0d,0x00,0x1b,0x01,0x1b,0x06,0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x17,0x37,0x36,0x36,0x35,0x34,0x26, 0x23,0x22,0x06,0x15,0x14,0x16,0x13,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x07,0x06,0x06,0x15,0x14,0x16,0x01,0x2c,0x46,0x6a,0x3a,0x4f,0x42,0x41,0x40,0x39,0x62,0x3f,0x3f,0x63,0x38,0x40,0x41,0x42,0x4f,0x3a,0x69,0x64,0x1d,0x19,0x2f,0x3a,0x48,0x3a,0x3a,0x48,0x38,0x4a,0x42,0x50,0x36,0x31,0x2b,0x2e,0x30,0x34,0x50,0x0a,0x31,0x57, 0x39,0x3e,0x6b,0x1e,0x20,0x59,0x33,0x37,0x54,0x30,0x30,0x54,0x37,0x32,0x59,0x21,0x1e,0x6b,0x3e,0x39,0x57,0x31,0x01,0xb5,0x0b,0x0a,0x12,0x43,0x28,0x31,0x3d,0x3e,0x30,0x29,0x42,0xfe,0x8a,0x45,0x38,0x2c,0x47,0x13,0x11,0x12,0x13,0x47,0x2b,0x38,0x45,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0xf6,0x02,0x03,0x02,0xda,0x00,0x20, 0x00,0x4d,0x40,0x4a,0x17,0x01,0x03,0x07,0x01,0x4c,0x00,0x04,0x03,0x01,0x03,0x04,0x01,0x80,0x00,0x01,0x02,0x03,0x01,0x02,0x7e,0x00,0x07,0x00,0x03,0x04,0x07,0x03,0x69,0x00,0x06,0x06,0x05,0x5f,0x00,0x05,0x05,0x38,0x4d,0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x1b,0x19,0x16,0x15,0x14,0x13,0x12, 0x11,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x20,0x01,0x20,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x11,0x21,0x15,0x21,0x17,0x36,0x36,0x33,0x36,0x16,0x15,0x15,0x14,0x06,0x01,0x2a,0x5b,0x73,0x07,0x5a,0x05,0x43,0x34,0x3a,0x44,0x44,0x3a,0x27,0x39,0x0d, 0x5a,0x01,0x85,0xfe,0xcf,0x02,0x0d,0x48,0x35,0x5b,0x64,0x75,0x0a,0x5c,0x4e,0x29,0x31,0x46,0x3c,0x47,0x3c,0x46,0x28,0x1e,0x01,0x8f,0x52,0xf5,0x24,0x29,0x01,0x6f,0x63,0x47,0x61,0x71,0xff,0xff,0x00,0x89,0xff,0x76,0x01,0xcf,0x01,0x40,0x03,0x07,0x03,0x02,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x96,0xff,0x7b,0x01,0xe0,0x01,0x3b,0x03,0x07,0x03,0x03,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x93,0xff,0x7b,0x01,0xc9,0x01,0x40,0x03,0x07,0x03,0x04,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8b,0xff,0x76,0x01,0xce,0x01,0x3b,0x03,0x07,0x03,0x05,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8f,0xff,0x7b,0x01,0xbd,0x01,0x3b,0x03,0x07,0x03,0x06,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8d,0xff,0x76,0x01,0xcf,0x01,0x3b,0x03,0x07,0x03,0x07,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x86,0xff,0x76,0x01,0xd2,0x01,0x3b,0x03,0x07,0x03,0x08,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x94,0xff,0x7b,0x01,0xce,0x01,0x3b,0x03,0x07,0x03,0x09,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x87,0xff,0x6c,0x01,0xd1,0x01,0x36,0x03,0x07,0x03,0x0a,0x00,0x00,0xfd,0xf3,0x00,0x09,0xb1,0x00,0x03,0xb8,0xfd,0xf3,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8b,0xff,0x7b,0x01,0xcd,0x01,0x40,0x03,0x07,0x03,0x0b,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x89,0xff,0xfb,0x01,0xcf,0x01,0xc5,0x03,0x07,0x03,0x02,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x82,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x96,0x00,0x00,0x01,0xe0,0x01,0xc0,0x03,0x07,0x03,0x03,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x93,0x00,0x00,0x01,0xc9,0x01,0xc5,0x03,0x07,0x03,0x04,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8b,0xff,0xfb,0x01,0xce,0x01,0xc0,0x03,0x07,0x03,0x05,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8f,0x00,0x00,0x01,0xbd,0x01,0xc0,0x03,0x07,0x03,0x06,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8d,0xff,0xfb,0x01,0xcf,0x01,0xc0,0x03,0x07,0x03,0x07,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x86,0xff,0xfb,0x01,0xd2,0x01,0xc0,0x03,0x07,0x03,0x08,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x82,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x94,0x00,0x00,0x01,0xce,0x01,0xc0,0x03,0x07,0x03,0x09,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x87,0xff,0xfb,0x01,0xd1,0x01,0xc5,0x03,0x07,0x03,0x0a,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x03,0xb8,0xfe,0x82,0xb0,0x35, 0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8b,0x00,0x00,0x01,0xcd,0x01,0xc5,0x03,0x07,0x03,0x0b,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x89,0x01,0x15,0x01,0xcf,0x02,0xdf,0x03,0x06,0x03,0x02,0x00,0x9c,0x00,0x09,0xb1,0x00,0x02,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00, 0xff,0xff,0x00,0x96,0x01,0x1a,0x01,0xe0,0x02,0xda,0x03,0x06,0x03,0x03,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x93,0x01,0x1a,0x01,0xc9,0x02,0xdf,0x03,0x06,0x03,0x04,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8b,0x01,0x15,0x01,0xce, 0x02,0xda,0x03,0x06,0x03,0x05,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8f,0x01,0x1a,0x01,0xbd,0x02,0xda,0x03,0x06,0x03,0x06,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8d,0x01,0x15,0x01,0xcf,0x02,0xda,0x03,0x06,0x03,0x07,0x00,0x9c, 0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x86,0x01,0x15,0x01,0xd2,0x02,0xda,0x03,0x06,0x03,0x08,0x00,0x9c,0x00,0x09,0xb1,0x00,0x02,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x94,0x01,0x1a,0x01,0xce,0x02,0xda,0x03,0x06,0x03,0x09,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c, 0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x87,0x01,0x15,0x01,0xd1,0x02,0xdf,0x03,0x06,0x03,0x0a,0x00,0x9c,0x00,0x09,0xb1,0x00,0x03,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8b,0x01,0x1a,0x01,0xcd,0x02,0xdf,0x03,0x06,0x03,0x0b,0x00,0x9c,0x00,0x09,0xb1,0x00,0x02,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0x00,0x02,0x00,0x89, 0x01,0x79,0x01,0xcf,0x03,0x43,0x00,0x0d,0x00,0x1b,0x00,0x2d,0x40,0x2a,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x52,0x4d,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x00,0x53,0x00,0x4e,0x0f,0x0e,0x01,0x00,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x35,0x34,0x36, 0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x49,0x5a,0x5a,0x49,0x49,0x5a,0x5a,0x49,0x29,0x33,0x33,0x29,0x29,0x33,0x33,0x01,0x79,0x5c,0x49,0x81,0x49,0x5b,0x5b,0x49,0x81,0x49,0x5c,0x40,0x38,0x2d,0x81,0x2c,0x38,0x38,0x2c,0x81,0x2d,0x38,0x00,0x00,0x00, 0x00,0x01,0x00,0x96,0x01,0x7e,0x01,0xe0,0x03,0x3e,0x00,0x0a,0x00,0x29,0x40,0x26,0x05,0x04,0x03,0x03,0x00,0x01,0x01,0x4c,0x00,0x01,0x01,0x50,0x4d,0x02,0x01,0x00,0x00,0x03,0x60,0x04,0x01,0x03,0x03,0x51,0x03,0x4e,0x00,0x00,0x00,0x0a,0x00,0x0a,0x11,0x14,0x11,0x05,0x0b,0x19,0x2b,0x13,0x35,0x33,0x11,0x07,0x35,0x37,0x33,0x11, 0x33,0x15,0x96,0x90,0x8d,0x74,0x60,0x73,0x01,0x7e,0x41,0x01,0x44,0x55,0x49,0x47,0xfe,0x81,0x41,0x00,0x00,0x01,0x00,0x93,0x01,0x7e,0x01,0xc9,0x03,0x43,0x00,0x1a,0x00,0x34,0x40,0x31,0x01,0x01,0x03,0x01,0x01,0x4c,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x02,0x52,0x4d,0x00,0x03,0x03,0x04, 0x5f,0x05,0x01,0x04,0x04,0x51,0x04,0x4e,0x00,0x00,0x00,0x1a,0x00,0x1a,0x17,0x23,0x12,0x27,0x06,0x0b,0x1a,0x2b,0x13,0x35,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x3e,0x02,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x07,0x33,0x15,0x9c,0xb7,0x14,0x18,0x2f,0x23,0x22,0x31,0x47,0x02,0x2a,0x45,0x29,0x2c,0x45,0x29, 0x2a,0x24,0x8c,0xdc,0x01,0x7e,0x4d,0x9e,0x11,0x25,0x16,0x23,0x2b,0x2c,0x24,0x2b,0x40,0x25,0x23,0x3f,0x2a,0x24,0x3e,0x1f,0x77,0x41,0x00,0x00,0x00,0x01,0x00,0x8b,0x01,0x79,0x01,0xce,0x03,0x3e,0x00,0x1a,0x00,0x43,0x40,0x40,0x15,0x14,0x0f,0x03,0x03,0x04,0x01,0x4c,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x01,0x02,0x04, 0x01,0x02,0x7e,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x05,0x50,0x4d,0x00,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00,0x53,0x00,0x4e,0x01,0x00,0x13,0x12,0x11,0x10,0x0e,0x0c,0x08,0x06,0x04,0x03,0x00,0x1a,0x01,0x1a,0x07,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x37,0x23,0x35, 0x21,0x15,0x07,0x16,0x16,0x15,0x14,0x06,0x01,0x2c,0x47,0x5a,0x47,0x32,0x28,0x28,0x32,0x32,0x28,0x29,0x73,0xd5,0x01,0x1d,0x75,0x3c,0x49,0x5a,0x01,0x79,0x52,0x42,0x25,0x2f,0x2f,0x25,0x25,0x2e,0x45,0x58,0x41,0x48,0x5c,0x07,0x4c,0x3a,0x42,0x52,0x00,0x01,0x00,0x8f,0x01,0x7e,0x01,0xbd,0x03,0x3e,0x00,0x0b,0x00,0x30,0x40,0x2d, 0x06,0x03,0x02,0x02,0x03,0x01,0x4c,0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x68,0x00,0x01,0x01,0x50,0x4d,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x04,0x51,0x04,0x4e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x12,0x12,0x11,0x06,0x0b,0x1a,0x2b,0x01,0x35,0x23,0x35,0x37,0x33,0x03,0x15,0x33,0x35,0x33,0x11,0x01,0x76,0xe7,0xae,0x50,0xb8, 0xa1,0x47,0x01,0x7e,0x69,0x5d,0xfa,0xfe,0xf6,0x0d,0x72,0xfe,0xe5,0x00,0x00,0x00,0x00,0x01,0x00,0x8d,0x01,0x79,0x01,0xcf,0x03,0x3e,0x00,0x19,0x00,0x3e,0x40,0x3b,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x06,0x00,0x03,0x01,0x06,0x03,0x67,0x00,0x05,0x05,0x04,0x5f,0x00,0x04,0x04,0x50,0x4d,0x00,0x02,0x02,0x00,0x61,0x07, 0x01,0x00,0x00,0x53,0x00,0x4e,0x01,0x00,0x15,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0c,0x08,0x06,0x04,0x03,0x00,0x19,0x01,0x19,0x08,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x21,0x15,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2f,0x49,0x59,0x46,0x32,0x2a,0x28,0x30,0x30, 0x28,0x8b,0x01,0x1a,0xd7,0x48,0x4a,0x56,0x58,0x01,0x79,0x50,0x44,0x28,0x2c,0x2f,0x25,0x26,0x2e,0xdd,0x3f,0x62,0x4e,0x42,0x42,0x52,0x00,0x00,0x00,0x02,0x00,0x86,0x01,0x79,0x01,0xd2,0x03,0x3e,0x00,0x10,0x00,0x1c,0x00,0x38,0x40,0x35,0x08,0x01,0x04,0x02,0x01,0x4c,0x00,0x02,0x00,0x04,0x03,0x02,0x04,0x6a,0x00,0x01,0x01,0x50, 0x4d,0x06,0x01,0x03,0x03,0x00,0x61,0x05,0x01,0x00,0x00,0x53,0x00,0x4e,0x12,0x11,0x01,0x00,0x18,0x16,0x11,0x1c,0x12,0x1c,0x0c,0x0a,0x07,0x06,0x00,0x10,0x01,0x10,0x07,0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x37,0x37,0x33,0x07,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14, 0x16,0x01,0x2d,0x4b,0x5c,0x24,0x7e,0x4d,0x81,0x04,0x1b,0x31,0x40,0x4e,0x5b,0x4b,0x2a,0x34,0x34,0x2a,0x29,0x35,0x34,0x01,0x79,0x55,0x43,0x32,0x39,0xc2,0xc5,0x25,0x4e,0x3f,0x43,0x55,0x40,0x31,0x27,0x27,0x31,0x31,0x27,0x27,0x31,0x00,0x00,0x00,0x00,0x01,0x00,0x94,0x01,0x7e,0x01,0xce,0x03,0x3e,0x00,0x08,0x00,0x52,0xb5,0x07, 0x01,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x18,0x00,0x01,0x00,0x03,0x00,0x01,0x72,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x50,0x4d,0x04,0x01,0x03,0x03,0x51,0x03,0x4e,0x1b,0x40,0x19,0x00,0x01,0x00,0x03,0x00,0x01,0x03,0x80,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x02,0x50,0x4d,0x04,0x01,0x03,0x03,0x51,0x03,0x4e, 0x59,0x40,0x0c,0x00,0x00,0x00,0x08,0x00,0x08,0x11,0x11,0x11,0x05,0x0b,0x19,0x2b,0x13,0x13,0x23,0x15,0x23,0x35,0x21,0x15,0x03,0xd8,0xb1,0xaf,0x46,0x01,0x3a,0xa8,0x01,0x7e,0x01,0x80,0x4e,0x8e,0x4c,0xfe,0x8c,0x00,0x00,0x00,0x00,0x03,0x00,0x87,0x01,0x79,0x01,0xd1,0x03,0x43,0x00,0x19,0x00,0x25,0x00,0x31,0x00,0x45,0x40,0x42, 0x13,0x06,0x02,0x05,0x02,0x01,0x4c,0x07,0x01,0x02,0x00,0x05,0x04,0x02,0x05,0x69,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x52,0x4d,0x08,0x01,0x04,0x04,0x00,0x61,0x06,0x01,0x00,0x00,0x53,0x00,0x4e,0x27,0x26,0x1b,0x1a,0x01,0x00,0x2d,0x2b,0x26,0x31,0x27,0x31,0x21,0x1f,0x1a,0x25,0x1b,0x25,0x0e,0x0c,0x00,0x19,0x01,0x19,0x09, 0x0b,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x15,0x16,0x16,0x15,0x14,0x06,0x03,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x49,0x5c,0x3a,0x2e,0x2a,0x33,0x55,0x45,0x46, 0x56,0x34,0x2c,0x2f,0x3a,0x5b,0x4a,0x27,0x30,0x30,0x27,0x26,0x2f,0x2f,0x26,0x2a,0x36,0x36,0x2a,0x2a,0x36,0x36,0x01,0x79,0x49,0x3a,0x2e,0x3d,0x04,0x04,0x08,0x34,0x22,0x35,0x41,0x41,0x35,0x22,0x34,0x08,0x04,0x04,0x3d,0x2e,0x3a,0x49,0x01,0x0b,0x24,0x1d,0x1d,0x25,0x25,0x1d,0x1d,0x24,0xce,0x29,0x21,0x21,0x29,0x29,0x21,0x21, 0x29,0x00,0x00,0x00,0x00,0x02,0x00,0x8b,0x01,0x7e,0x01,0xcd,0x03,0x43,0x00,0x12,0x00,0x1e,0x00,0x36,0x40,0x33,0x01,0x01,0x00,0x03,0x01,0x4c,0x06,0x01,0x03,0x00,0x00,0x02,0x03,0x00,0x69,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x52,0x4d,0x05,0x01,0x02,0x02,0x51,0x02,0x4e,0x14,0x13,0x00,0x00,0x1a,0x18,0x13,0x1e,0x14,0x1e, 0x00,0x12,0x00,0x12,0x24,0x24,0x07,0x0b,0x18,0x2b,0x13,0x37,0x23,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xe7,0x7e,0x04,0x0a,0x26,0x1d,0x3f,0x4a,0x57,0x49,0x4a,0x58,0x16,0x16,0x6d,0x08,0x26,0x33,0x30,0x29,0x29,0x30,0x30, 0x01,0x7e,0xc5,0x10,0x15,0x4f,0x3e,0x44,0x54,0x54,0x44,0x21,0x3c,0x23,0xad,0xd5,0x31,0x27,0x27,0x31,0x31,0x27,0x27,0x31,0xff,0xff,0x00,0x9a,0xff,0x7b,0x01,0xce,0x01,0x40,0x03,0x07,0x03,0x15,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x90,0xff,0x76,0x01,0xd4, 0x01,0x40,0x03,0x07,0x03,0x16,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x84,0xff,0x76,0x01,0xc8,0x01,0x40,0x03,0x07,0x03,0x17,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x9a,0x00,0x00,0x01,0xce, 0x01,0xc5,0x03,0x07,0x03,0x15,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x90,0xff,0xfb,0x01,0xd4,0x01,0xc5,0x03,0x07,0x03,0x16,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x84,0xff,0xfb,0x01,0xc8, 0x01,0xc5,0x03,0x07,0x03,0x17,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x9a,0x01,0x1a,0x01,0xce,0x02,0xdf,0x03,0x06,0x03,0x15,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x90,0x01,0x15,0x01,0xd4,0x02,0xdf,0x03,0x06, 0x03,0x16,0x00,0x9c,0x00,0x09,0xb1,0x00,0x02,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x84,0x01,0x15,0x01,0xc8,0x02,0xdf,0x03,0x06,0x03,0x17,0x00,0x9c,0x00,0x09,0xb1,0x00,0x02,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x9a,0x01,0x7e,0x01,0xce,0x03,0x43,0x00,0x1e,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03, 0x00,0x01,0x03,0x80,0x00,0x02,0x00,0x00,0x01,0x02,0x00,0x69,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x1e,0x00,0x1e,0x19,0x22,0x12,0x2a,0x06,0x09,0x1a,0x2b,0x13,0x35,0x34,0x3e,0x04,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x0e, 0x04,0x15,0x33,0x15,0xa0,0x21,0x35,0x3a,0x35,0x21,0x2d,0x23,0x26,0x2e,0x48,0x56,0x46,0x43,0x55,0x22,0x34,0x3c,0x34,0x22,0xe7,0x01,0x7e,0x39,0x2f,0x3b,0x26,0x1b,0x1a,0x24,0x1c,0x20,0x27,0x2d,0x23,0x40,0x50,0x4a,0x3d,0x29,0x34,0x22,0x1a,0x1c,0x28,0x20,0x41,0x00,0x00,0x02,0x00,0x90,0x01,0x79,0x01,0xd4,0x03,0x43,0x00,0x1a, 0x00,0x26,0x00,0x4d,0x40,0x4a,0x12,0x01,0x05,0x06,0x01,0x4c,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x00,0x06,0x05,0x04,0x06,0x69,0x08,0x01,0x05,0x00,0x00,0x05,0x59,0x08,0x01,0x05,0x05,0x00,0x61,0x07,0x01,0x00,0x05,0x00,0x51,0x1c,0x1b,0x01,0x00,0x22,0x20,0x1b,0x26,0x1c, 0x26,0x16,0x14,0x0f,0x0d,0x0b,0x0a,0x08,0x06,0x00,0x1a,0x01,0x1a,0x09,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x32,0x49,0x59,0x56,0x4c,0x44,0x56, 0x04,0x45,0x04,0x31,0x24,0x2b,0x32,0x01,0x16,0x54,0x41,0x53,0x59,0x49,0x29,0x32,0x32,0x2a,0x2a,0x32,0x33,0x01,0x79,0x54,0x43,0x94,0x4a,0x55,0x45,0x37,0x1b,0x23,0x34,0x2d,0x50,0x4c,0x4f,0x41,0x43,0x54,0x3f,0x31,0x27,0x27,0x31,0x31,0x27,0x27,0x31,0x00,0x00,0x00,0x00,0x02,0x00,0x84,0x01,0x79,0x01,0xc8,0x03,0x43,0x00,0x1a, 0x00,0x26,0x00,0x4c,0x40,0x49,0x0b,0x01,0x05,0x06,0x01,0x4c,0x00,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x00,0x04,0x00,0x06,0x05,0x04,0x06,0x69,0x08,0x01,0x05,0x00,0x03,0x01,0x05,0x03,0x69,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x07,0x01,0x00,0x02,0x00,0x51,0x1c,0x1b,0x01,0x00,0x22,0x20,0x1b,0x26,0x1c,0x26, 0x15,0x13,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x1a,0x01,0x1a,0x09,0x09,0x16,0x2b,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x31,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x26,0x43,0x57,0x04,0x45,0x05,0x30,0x24, 0x2c,0x31,0x16,0x55,0x41,0x53,0x59,0x49,0x49,0x59,0x56,0x4b,0x2a,0x32,0x33,0x2a,0x29,0x32,0x32,0x01,0x79,0x44,0x34,0x18,0x21,0x34,0x2c,0x55,0x4c,0x4e,0x40,0x42,0x52,0x52,0x42,0x97,0x49,0x56,0xe0,0x2f,0x27,0x26,0x30,0x30,0x26,0x26,0x30,0x00,0xff,0xff,0x00,0x87,0xff,0x6c,0x01,0xd1,0x01,0x36,0x03,0x07,0x03,0x1b,0x00,0x00, 0xfd,0xf3,0x00,0x09,0xb1,0x00,0x03,0xb8,0xfd,0xf3,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x87,0xff,0xfb,0x01,0xd1,0x01,0xc5,0x03,0x07,0x03,0x1b,0x00,0x00,0xfe,0x82,0x00,0x09,0xb1,0x00,0x03,0xb8,0xfe,0x82,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x87,0x01,0x10,0x01,0xd1,0x02,0xda,0x03,0x06,0x03,0x1b,0x00,0x97, 0x00,0x09,0xb1,0x00,0x03,0xb8,0xff,0x97,0xb0,0x35,0x2b,0x00,0x00,0x03,0x00,0x87,0x01,0x79,0x01,0xd1,0x03,0x43,0x00,0x1b,0x00,0x29,0x00,0x37,0x00,0x3a,0x40,0x37,0x31,0x1d,0x15,0x07,0x04,0x03,0x02,0x01,0x4c,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x69,0x05,0x01,0x03,0x00,0x00,0x03,0x59,0x05,0x01,0x03,0x03,0x00,0x61,0x04,0x01, 0x00,0x03,0x00,0x51,0x2b,0x2a,0x01,0x00,0x2a,0x37,0x2b,0x37,0x25,0x23,0x0f,0x0d,0x00,0x1b,0x01,0x1b,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x37,0x37,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x17,0x16,0x16,0x15,0x14,0x06,0x03,0x17,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15, 0x14,0x16,0x17,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x07,0x06,0x06,0x15,0x14,0x16,0x01,0x2c,0x49,0x5c,0x28,0x20,0x26,0x1a,0x1f,0x2a,0x56,0x44,0x44,0x56,0x25,0x1d,0x1c,0x20,0x22,0x27,0x5b,0x72,0x2a,0x2b,0x11,0x17,0x2f,0x26,0x25,0x30,0x1a,0x3b,0x2b,0x35,0x19,0x14,0x31,0x35,0x14,0x19,0x35,0x01,0x79,0x49,0x3a,0x1f,0x2d,0x0e, 0x10,0x0c,0x0e,0x2f,0x1b,0x36,0x43,0x43,0x36,0x1e,0x2e,0x0d,0x0c,0x0f,0x0f,0x2d,0x1e,0x3a,0x49,0x01,0x19,0x13,0x12,0x08,0x1c,0x13,0x1c,0x23,0x23,0x1c,0x12,0x1b,0xe4,0x25,0x1e,0x14,0x1e,0x09,0x17,0x17,0x08,0x1e,0x14,0x1e,0x26,0x00,0x00,0x00,0xff,0xff,0x00,0x8a,0xff,0x76,0x01,0xcc,0x01,0x3b,0x03,0x07,0x03,0x1f,0x00,0x00, 0xfd,0xfd,0x00,0x09,0xb1,0x00,0x01,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x8a,0x01,0x15,0x01,0xcc,0x02,0xda,0x03,0x06,0x03,0x1f,0x00,0x9c,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0x9c,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8a,0x01,0x10,0x01,0xcc,0x02,0xd5,0x03,0x06,0x03,0x1f,0x00,0x97,0x00,0x09,0xb1,0x00, 0x01,0xb8,0xff,0x97,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x8a,0x01,0x79,0x01,0xcc,0x03,0x3e,0x00,0x1e,0x00,0x50,0x40,0x4d,0x16,0x01,0x03,0x07,0x01,0x4c,0x00,0x04,0x03,0x01,0x03,0x04,0x01,0x80,0x00,0x01,0x02,0x03,0x01,0x02,0x7e,0x00,0x05,0x00,0x06,0x07,0x05,0x06,0x67,0x00,0x07,0x00,0x03,0x04,0x07,0x03,0x69,0x00,0x02,0x00, 0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x1a,0x18,0x15,0x14,0x13,0x12,0x11,0x10,0x0e,0x0c,0x08,0x06,0x04,0x03,0x00,0x1e,0x01,0x1e,0x09,0x09,0x16,0x2b,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x07,0x23,0x11,0x21,0x15,0x23,0x15,0x36,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x01,0x2a,0x40,0x59,0x07,0x48,0x05,0x31,0x22,0x28,0x32,0x32,0x28,0x1b,0x29,0x0b,0x41,0x01,0x1c,0xd9,0x0d,0x34,0x22,0x3e,0x4e,0x5a,0x01,0x79,0x43,0x35,0x19,0x1f,0x33,0x25,0x26,0x32,0x1a,0x12,0x01,0x01,0x40,0x88,0x14,0x1a,0x53,0x40,0x42,0x56,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x02,0x53, 0x02,0xda,0x00,0x03,0x00,0x19,0x40,0x16,0x00,0x00,0x00,0x38,0x4d,0x02,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x33,0x01,0x33,0x01,0x05,0x01,0xf9,0x55,0xfe,0x07,0x02,0xda,0xfd,0x26,0x00,0x00,0x00,0x00,0x02,0x00,0x05,0x00,0x00,0x02,0x53,0x02,0xda,0x00,0x12,0x00,0x2e,0x00,0x6a, 0xb1,0x06,0x64,0x44,0x40,0x5f,0x0a,0x09,0x05,0x03,0x01,0x02,0x28,0x14,0x02,0x09,0x07,0x29,0x01,0x05,0x09,0x03,0x4c,0x04,0x01,0x02,0x01,0x02,0x85,0x00,0x07,0x06,0x09,0x06,0x07,0x09,0x80,0x03,0x01,0x01,0x00,0x00,0x08,0x01,0x00,0x68,0x00,0x08,0x00,0x06,0x07,0x08,0x06,0x69,0x00,0x09,0x05,0x05,0x09,0x57,0x00,0x09,0x09,0x05, 0x5f,0x0c,0x0a,0x0b,0x03,0x05,0x09,0x05,0x4f,0x13,0x13,0x00,0x00,0x13,0x2e,0x13,0x2e,0x2d,0x2b,0x22,0x20,0x1e,0x1d,0x1b,0x19,0x00,0x12,0x00,0x12,0x12,0x11,0x17,0x11,0x11,0x0d,0x09,0x1b,0x2b,0xb1,0x06,0x00,0x44,0x33,0x01,0x23,0x35,0x33,0x35,0x06,0x06,0x07,0x07,0x35,0x37,0x33,0x11,0x33,0x15,0x13,0x33,0x01,0x33,0x35,0x37, 0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x15,0x36,0x36,0x33,0x33,0x15,0x05,0x01,0x18,0xff,0x76,0x04,0x12,0x0b,0x3e,0x46,0x55,0x6b,0xc3,0x55,0xfe,0x07,0xe1,0x78,0x46,0x24,0x1d,0x1d,0x24,0x3c,0x02,0x45,0x36,0x38,0x45,0x2d,0x29,0x5d,0x0b,0x2a,0x16,0x6d,0x01,0x95,0x32, 0xec,0x07,0x15,0x0a,0x36,0x46,0x3d,0xfe,0xed,0x07,0x01,0x1a,0xfd,0x26,0x40,0x45,0x28,0x2b,0x1d,0x23,0x23,0x1d,0x34,0x3e,0x3e,0x32,0x1f,0x3c,0x17,0x34,0x0a,0x02,0x06,0x32,0x00,0x00,0x00,0x02,0x00,0x05,0x00,0x00,0x02,0x53,0x02,0xda,0x00,0x12,0x00,0x1e,0x00,0x6a,0xb1,0x06,0x64,0x44,0x40,0x5f,0x0a,0x09,0x05,0x03,0x01,0x02, 0x0f,0x01,0x00,0x01,0x19,0x16,0x02,0x08,0x09,0x03,0x4c,0x04,0x01,0x02,0x01,0x02,0x85,0x00,0x07,0x00,0x09,0x00,0x07,0x09,0x80,0x03,0x01,0x01,0x00,0x00,0x07,0x01,0x00,0x68,0x00,0x09,0x08,0x05,0x09,0x57,0x00,0x08,0x00,0x06,0x05,0x08,0x06,0x68,0x00,0x09,0x09,0x05,0x5f,0x0c,0x0a,0x0b,0x03,0x05,0x09,0x05,0x4f,0x13,0x13,0x00, 0x00,0x13,0x1e,0x13,0x1e,0x1d,0x1c,0x1b,0x1a,0x18,0x17,0x15,0x14,0x00,0x12,0x00,0x12,0x12,0x11,0x17,0x11,0x11,0x0d,0x09,0x1b,0x2b,0xb1,0x06,0x00,0x44,0x33,0x01,0x23,0x35,0x33,0x35,0x06,0x06,0x07,0x07,0x35,0x37,0x33,0x11,0x33,0x15,0x13,0x33,0x01,0x21,0x35,0x23,0x35,0x37,0x33,0x07,0x15,0x33,0x35,0x33,0x15,0x05,0x01,0x18, 0xff,0x76,0x04,0x12,0x0b,0x3e,0x46,0x55,0x61,0xcd,0x55,0xfe,0x07,0x01,0x86,0xaf,0x7e,0x45,0x87,0x73,0x3c,0x01,0x95,0x32,0xec,0x07,0x15,0x0a,0x36,0x46,0x3d,0xfe,0xed,0x15,0x01,0x28,0xfd,0x26,0x46,0x50,0xaf,0xbd,0x10,0x59,0xd1,0x00,0x00,0x00,0x00,0x03,0x00,0x05,0x00,0x00,0x02,0x53,0x02,0xda,0x00,0x1a,0x00,0x1e,0x00,0x2a, 0x00,0xd3,0xb1,0x06,0x64,0x44,0x40,0x0d,0x15,0x14,0x0f,0x03,0x03,0x04,0x25,0x22,0x02,0x0a,0x0b,0x02,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x42,0x00,0x03,0x04,0x01,0x04,0x03,0x72,0x00,0x09,0x00,0x0b,0x00,0x09,0x0b,0x80,0x06,0x01,0x05,0x00,0x04,0x03,0x05,0x04,0x67,0x00,0x01,0x02,0x07,0x01,0x57,0x00,0x02,0x0d,0x01,0x00,0x09, 0x02,0x00,0x69,0x00,0x0b,0x0a,0x07,0x0b,0x57,0x00,0x0a,0x00,0x08,0x07,0x0a,0x08,0x68,0x00,0x0b,0x0b,0x07,0x60,0x0f,0x0c,0x0e,0x03,0x07,0x0b,0x07,0x50,0x1b,0x40,0x43,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x09,0x00,0x0b,0x00,0x09,0x0b,0x80,0x06,0x01,0x05,0x00,0x04,0x03,0x05,0x04,0x67,0x00,0x01,0x02,0x07,0x01,0x57, 0x00,0x02,0x0d,0x01,0x00,0x09,0x02,0x00,0x69,0x00,0x0b,0x0a,0x07,0x0b,0x57,0x00,0x0a,0x00,0x08,0x07,0x0a,0x08,0x68,0x00,0x0b,0x0b,0x07,0x60,0x0f,0x0c,0x0e,0x03,0x07,0x0b,0x07,0x50,0x59,0x40,0x29,0x1f,0x1f,0x1b,0x1b,0x01,0x00,0x1f,0x2a,0x1f,0x2a,0x29,0x28,0x27,0x26,0x24,0x23,0x21,0x20,0x1b,0x1e,0x1b,0x1e,0x1d,0x1c,0x13, 0x12,0x11,0x10,0x0e,0x0c,0x08,0x06,0x04,0x03,0x00,0x1a,0x01,0x1a,0x10,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x13,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x37,0x23,0x35,0x33,0x15,0x07,0x16,0x16,0x15,0x14,0x06,0x03,0x01,0x33,0x01,0x21,0x35,0x23,0x35,0x37,0x33,0x07,0x15,0x33,0x35,0x33,0x15, 0x9a,0x3a,0x46,0x3c,0x25,0x1f,0x1e,0x25,0x25,0x1d,0x1e,0x51,0x9c,0xd7,0x55,0x2d,0x38,0x46,0xce,0x01,0xf9,0x55,0xfe,0x07,0x01,0x86,0xaf,0x7e,0x45,0x87,0x73,0x3c,0x01,0x90,0x3a,0x2f,0x19,0x1e,0x1e,0x19,0x19,0x1e,0x39,0x3f,0x32,0x37,0x42,0x06,0x38,0x2a,0x2f,0x3a,0xfe,0x70,0x02,0xda,0xfd,0x26,0x46,0x50,0xaf,0xbd,0x10,0x59, 0xd1,0x00,0x00,0x00,0xff,0xff,0x00,0x89,0xff,0x76,0x01,0xcf,0x01,0x40,0x03,0x07,0x03,0x02,0x00,0x00,0xfd,0xfd,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfd,0xfd,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x89,0x01,0x79,0x01,0xcf,0x03,0x43,0x02,0x06,0x03,0x02,0x00,0x00,0xff,0xff,0x00,0x89,0xff,0xe4,0x01,0xcf,0x01,0xae,0x03,0x07, 0x03,0x02,0x00,0x00,0xfe,0x6b,0x00,0x09,0xb1,0x00,0x02,0xb8,0xfe,0x6b,0xb0,0x35,0x2b,0x00,0x00,0x00,0x00,0x02,0x00,0x91,0x01,0x8b,0x01,0xc7,0x03,0x48,0x00,0x0d,0x00,0x1b,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00, 0x51,0x0f,0x0e,0x01,0x00,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x48,0x53,0x53,0x48,0x48,0x53,0x53,0x48,0x28,0x2d,0x2d,0x28,0x28, 0x2d,0x2d,0x01,0x8b,0x4f,0x46,0x94,0x45,0x4f,0x4f,0x45,0x94,0x46,0x4f,0x3f,0x2e,0x28,0x94,0x28,0x2d,0x2d,0x28,0x94,0x28,0x2e,0x00,0x00,0x00,0x00,0x02,0x00,0x4c,0xff,0xf6,0x02,0x0c,0x02,0x8a,0x00,0x15,0x00,0x22,0x00,0x32,0x40,0x2f,0x1f,0x0e,0x0b,0x08,0x04,0x03,0x01,0x01,0x4c,0x02,0x01,0x01,0x03,0x01,0x85,0x00,0x03,0x00, 0x00,0x03,0x59,0x00,0x03,0x03,0x00,0x61,0x04,0x01,0x00,0x03,0x00,0x51,0x01,0x00,0x1a,0x18,0x0d,0x0c,0x0a,0x09,0x00,0x15,0x01,0x15,0x05,0x06,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x27,0x33,0x17,0x37,0x33,0x07,0x17,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x27,0x27,0x07,0x06, 0x06,0x01,0x2c,0x43,0x63,0x36,0x2b,0x22,0x5b,0xac,0x68,0x79,0x79,0x66,0xac,0x5d,0x23,0x28,0x36,0x62,0xc6,0x46,0x3c,0x3c,0x46,0x30,0x52,0x53,0x16,0x19,0x0a,0x32,0x56,0x34,0x2e,0x51,0x28,0x69,0xc8,0x8b,0x8b,0xc7,0x6b,0x29,0x51,0x2c,0x34,0x56,0x32,0xc4,0x30,0x44,0x44,0x30,0x37,0x36,0x60,0x60,0x19,0x37,0x00,0x01,0x00,0xda, 0xff,0xf6,0x01,0x7e,0x00,0x98,0x00,0x0b,0x00,0x1a,0x40,0x17,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x07,0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x25,0x2d,0x2d,0x25,0x25,0x2d,0x2d,0x0a,0x2c,0x23,0x25,0x2e,0x2e,0x25, 0x23,0x2c,0x00,0x00,0x00,0x01,0x00,0xd2,0xff,0x60,0x01,0x75,0x00,0x92,0x00,0x03,0x00,0x35,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0c,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x01,0x3d,0x01,0x4e,0x1b,0x40,0x11,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x59,0x40,0x0a,0x00,0x00,0x00,0x03, 0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x17,0x13,0x33,0x03,0xd2,0x37,0x6c,0x46,0xa0,0x01,0x32,0xfe,0xce,0x00,0x02,0x00,0xd9,0xff,0xf6,0x01,0x7f,0x02,0x30,0x00,0x0b,0x00,0x17,0x00,0x2d,0x40,0x2a,0x04,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x03,0x03,0x02,0x61,0x05,0x01,0x02,0x02,0x3f,0x02,0x4e,0x0d,0x0c,0x01, 0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x29,0x2a,0x2a,0x29,0x29,0x2a,0x2a,0x29,0x29,0x2a,0x2a,0x29,0x29,0x2a,0x2a,0x01,0x9c,0x28,0x22,0x22,0x28, 0x28,0x22,0x22,0x28,0xfe,0x5a,0x28,0x22,0x22,0x28,0x28,0x22,0x22,0x28,0x00,0x00,0x00,0x02,0x00,0xcd,0xff,0x60,0x01,0x81,0x02,0x30,0x00,0x0d,0x00,0x11,0x00,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x17,0x04,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x4d,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40, 0x14,0x00,0x02,0x05,0x01,0x03,0x02,0x03,0x63,0x04,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x00,0x4e,0x59,0x40,0x13,0x0e,0x0e,0x01,0x00,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x08,0x05,0x00,0x0d,0x01,0x0c,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x03,0x13,0x33,0x03,0x01,0x22, 0x21,0x2a,0x2b,0x20,0x14,0x20,0x2b,0x2a,0x21,0x69,0x37,0x6c,0x46,0x01,0x9a,0x2a,0x21,0x20,0x2b,0x2b,0x20,0x21,0x2a,0xfd,0xc6,0x01,0x32,0xfe,0xce,0x00,0x00,0x00,0x00,0x03,0x00,0x3c,0xff,0xf6,0x02,0x1c,0x00,0xaa,0x00,0x0d,0x00,0x1b,0x00,0x29,0x00,0x30,0x40,0x2d,0x05,0x03,0x02,0x01,0x01,0x00,0x61,0x08,0x04,0x07,0x02,0x06, 0x05,0x00,0x00,0x3f,0x00,0x4e,0x1d,0x1c,0x0f,0x0e,0x01,0x00,0x24,0x22,0x1c,0x29,0x1d,0x29,0x16,0x14,0x0e,0x1b,0x0f,0x1b,0x08,0x06,0x00,0x0d,0x01,0x0d,0x09,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x33,0x22, 0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x01,0xea,0x16,0x1c,0x1c,0x16,0x17,0x1b,0x1b,0xfe,0x6d,0x16,0x1c,0x1c,0x16,0x17,0x1b,0x1b,0xa7,0x16,0x1c,0x1c,0x16,0x17,0x1b,0x1b,0x0a,0x1e,0x19,0x46,0x19,0x1e,0x1e,0x19,0x46,0x19,0x1e,0x1e,0x19,0x46,0x19,0x1e,0x1e,0x19,0x46,0x19,0x1e,0x1e,0x19,0x46,0x19,0x1e, 0x1e,0x19,0x46,0x19,0x1e,0x00,0x00,0x00,0x00,0x02,0x00,0xe1,0xff,0xfb,0x01,0x77,0x02,0xda,0x00,0x03,0x00,0x11,0x00,0x2c,0x40,0x29,0x04,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x02,0x61,0x05,0x01,0x02,0x02,0x42,0x02,0x4e,0x05,0x04,0x00,0x00,0x0c,0x09,0x04,0x11,0x05,0x10,0x00,0x03,0x00,0x03,0x11, 0x06,0x09,0x17,0x2b,0x25,0x03,0x33,0x03,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x01,0x03,0x0c,0x6a,0x0c,0x38,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xdc,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x02,0x00,0xe1,0xff,0x4c,0x01,0x77,0x02,0x2b,0x00,0x0d, 0x00,0x11,0x00,0x2d,0x40,0x2a,0x04,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x3b,0x4d,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x03,0x3d,0x03,0x4e,0x0e,0x0e,0x01,0x00,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x08,0x05,0x00,0x0d,0x01,0x0c,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x03, 0x13,0x33,0x13,0x01,0x1d,0x1a,0x22,0x22,0x1a,0x1e,0x1a,0x22,0x1f,0x1d,0x44,0x0c,0x52,0x0c,0x01,0xb3,0x22,0x1a,0x1a,0x22,0x23,0x1a,0x19,0x22,0xfd,0x99,0x02,0x03,0xfd,0xfd,0x00,0x00,0x00,0x02,0x00,0x82,0xff,0xfb,0x01,0xe5,0x02,0xda,0x00,0x14,0x00,0x22,0x00,0x70,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x26,0x07,0x01,0x04,0x03,0x06, 0x03,0x04,0x72,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x06,0x06,0x05,0x61,0x08,0x01,0x05,0x05,0x42,0x05,0x4e,0x1b,0x40,0x27,0x07,0x01,0x04,0x03,0x06,0x03,0x04,0x06,0x80,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00, 0x06,0x06,0x05,0x61,0x08,0x01,0x05,0x05,0x42,0x05,0x4e,0x59,0x40,0x15,0x16,0x15,0x00,0x00,0x1d,0x1a,0x15,0x22,0x16,0x21,0x00,0x14,0x00,0x14,0x16,0x21,0x24,0x21,0x09,0x09,0x1a,0x2b,0x37,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x15,0x07,0x22,0x26,0x35,0x34,0x36,0x33, 0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xce,0x32,0x40,0x4b,0x4b,0x41,0x7d,0x7d,0x46,0x67,0x39,0x30,0x55,0x38,0x3d,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0xaa,0x47,0x3b,0x3b,0x47,0x55,0x35,0x60,0x42,0x39,0x5b,0x36,0x03,0x5f,0xdc,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x02,0x00,0x73,0xff,0x4c,0x01,0xd6, 0x02,0x2b,0x00,0x0d,0x00,0x22,0x00,0x74,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x26,0x00,0x04,0x00,0x03,0x03,0x04,0x72,0x00,0x03,0x00,0x05,0x06,0x03,0x05,0x6a,0x07,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x3b,0x4d,0x00,0x06,0x06,0x02,0x5f,0x08,0x01,0x02,0x02,0x3d,0x02,0x4e,0x1b,0x40,0x27,0x00,0x04,0x00,0x03,0x00,0x04,0x03,0x80, 0x00,0x03,0x00,0x05,0x06,0x03,0x05,0x6a,0x07,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x3b,0x4d,0x00,0x06,0x06,0x02,0x5f,0x08,0x01,0x02,0x02,0x3d,0x02,0x4e,0x59,0x40,0x19,0x0f,0x0e,0x01,0x00,0x21,0x1f,0x1b,0x19,0x18,0x17,0x16,0x15,0x0e,0x22,0x0f,0x22,0x08,0x05,0x00,0x0d,0x01,0x0c,0x09,0x09,0x16,0x2b,0x01,0x22,0x26,0x35, 0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x03,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x37,0x35,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x01,0x4f,0x1c,0x20,0x22,0x1a,0x1e,0x1a,0x22,0x22,0x1a,0x14,0x46,0x67,0x39,0x30,0x55,0x38,0x5a,0x32,0x40,0x4b,0x4c,0x40,0x7d,0x01,0xb3,0x22,0x19,0x1a,0x23,0x22,0x1a, 0x1a,0x22,0xfd,0x99,0x35,0x61,0x41,0x3a,0x5a,0x36,0x03,0x5f,0xaa,0x47,0x3b,0x3b,0x47,0x55,0x00,0x00,0xff,0xff,0x00,0xda,0x01,0x04,0x01,0x7e,0x01,0xa6,0x03,0x07,0x03,0x29,0x00,0x00,0x01,0x0e,0x00,0x09,0xb1,0x00,0x01,0xb8,0x01,0x0e,0xb0,0x35,0x2b,0x00,0x00,0x00,0x00,0x01,0x00,0xb4,0x00,0xf5,0x01,0xa4,0x01,0xe5,0x00,0x0b, 0x00,0x1f,0x40,0x1c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07,0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0x25,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0xf5,0x44,0x34,0x35,0x43,0x43,0x35,0x34,0x44,0x00, 0x00,0x01,0x00,0x24,0x00,0x67,0x02,0x34,0x02,0x6c,0x00,0x2c,0x00,0x1b,0x40,0x18,0x29,0x25,0x24,0x20,0x1c,0x1b,0x17,0x0e,0x0a,0x09,0x05,0x01,0x0c,0x00,0x49,0x00,0x00,0x00,0x76,0x13,0x12,0x01,0x09,0x16,0x2b,0x37,0x27,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x37,0x17,0x16,0x16,0x17,0x26,0x26,0x35,0x35,0x33,0x15,0x14,0x06, 0x07,0x36,0x36,0x37,0x37,0x17,0x07,0x06,0x06,0x07,0x16,0x16,0x17,0x17,0x07,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0xb1,0x45,0x41,0x0d,0x2d,0x14,0x1c,0x3e,0x12,0x6b,0x1c,0x6c,0x11,0x38,0x17,0x05,0x05,0x54,0x06,0x05,0x18,0x37,0x12,0x6c,0x1c,0x6b,0x12,0x3e,0x1c,0x14,0x2e,0x0c,0x41,0x45,0x41,0x0c,0x22,0x0c,0x0c,0x22,0x0c,0x67, 0x31,0x5d,0x12,0x34,0x14,0x04,0x10,0x07,0x28,0x4f,0x28,0x06,0x1a,0x0e,0x1a,0x37,0x13,0x7d,0x7d,0x13,0x37,0x1a,0x0e,0x1a,0x06,0x28,0x4f,0x28,0x07,0x10,0x04,0x14,0x35,0x11,0x5d,0x31,0x5e,0x11,0x3c,0x1a,0x1a,0x3b,0x12,0x00,0x00,0x01,0x00,0xcd,0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x0b,0x00,0x32,0x40,0x2f,0x00,0x00,0x00,0x01, 0x02,0x00,0x01,0x67,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x06,0x01,0x05,0x04,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x17,0x11,0x33,0x15,0x23,0x11,0x33,0x15,0x23,0x11,0x33,0x15,0xcd,0xf5,0x9b,0x9b,0x9b,0x96,0x6e,0x03, 0xac,0x50,0xfe,0xb1,0x50,0xfe,0x93,0x50,0x00,0x01,0x00,0x96,0xff,0x92,0x01,0x8b,0x03,0x3e,0x00,0x0b,0x00,0x2c,0x40,0x29,0x00,0x05,0x00,0x04,0x03,0x05,0x04,0x67,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x11,0x11,0x11,0x11,0x11,0x10,0x06,0x09, 0x1c,0x2b,0x05,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x01,0x8b,0xf0,0x96,0x9b,0x9b,0x9b,0xf5,0x6e,0x50,0x01,0x6d,0x50,0x01,0x4f,0x50,0x00,0x00,0x00,0x02,0x00,0x7d,0xff,0x92,0x01,0xdb,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x22,0x40,0x1f,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x03,0x04,0x03,0x01,0x01,0x76,0x04, 0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x17,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x7d,0x5a,0xaa,0x5a,0x6e,0x03,0xac,0xfc,0x54,0x03,0xac,0xfc,0x54,0x00,0xff,0xff,0x00,0x69,0xff,0xfb,0x01,0xef,0x02,0xda,0x00,0x26,0x03,0x2e,0x88,0x00,0x00,0x06,0x03,0x2e,0x78,0x00,0x00,0x00, 0x00,0x02,0x00,0x87,0xff,0xfb,0x01,0xea,0x02,0xda,0x00,0x16,0x00,0x24,0x00,0x3f,0x40,0x3c,0x15,0x05,0x02,0x03,0x00,0x01,0x4c,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x06,0x01,0x03,0x03,0x00,0x5f,0x00,0x00,0x00,0x3b,0x4d,0x00,0x05,0x05,0x04,0x61,0x07,0x01,0x04,0x04,0x42,0x04,0x4e,0x18,0x17,0x00,0x00,0x1f,0x1c, 0x17,0x24,0x18,0x23,0x00,0x16,0x00,0x16,0x21,0x27,0x12,0x08,0x09,0x19,0x2b,0x37,0x27,0x35,0x33,0x15,0x07,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x0f,0x02,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xdf,0x0d,0x5a,0x03,0x30,0x37,0x4b,0x41,0x7d,0x7d,0x46,0x67,0x39, 0x6a,0x5b,0x06,0x2f,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xcd,0xf5,0x64,0x64,0x3e,0x0a,0x43,0x32,0x3b,0x47,0x55,0x35,0x60,0x42,0x57,0x6e,0x07,0x6a,0xd2,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x02,0x00,0x23,0x00,0x00,0x02,0x35,0x02,0xda,0x00,0x1b,0x00,0x1f,0x00,0x47,0x40,0x44,0x07,0x05,0x02,0x03,0x0f,0x08, 0x02,0x02,0x01,0x03,0x02,0x68,0x0e,0x09,0x02,0x01,0x0c,0x0a,0x02,0x00,0x0b,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x10,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x00,0x00,0x1f,0x1e,0x1d,0x1c,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x1f,0x2b,0x33, 0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x13,0x33,0x37,0x23,0x53,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0xd2,0x41,0xb4,0x41,0xd2, 0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0x01,0x13,0xb4,0xff,0xff,0x00,0xda,0xff,0xf6,0x01,0x7e,0x00,0x98,0x02,0x06,0x03,0x29,0x00,0x00,0x00,0x01,0xff,0xf6,0x02,0xee,0x02,0x62,0x03,0x3e,0x00,0x03,0x00,0x26,0xb1,0x06,0x64,0x44,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01, 0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x03,0x35,0x21,0x15,0x0a,0x02,0x6c,0x02,0xee,0x50,0x50,0x00,0x00,0x01,0x00,0x4b,0xff,0x92,0x02,0x0d,0x03,0x3e,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17, 0x2b,0x17,0x01,0x33,0x01,0x4b,0x01,0x63,0x5f,0xfe,0x9d,0x6e,0x03,0xac,0xfc,0x54,0x00,0x01,0x00,0x4b,0xff,0x92,0x02,0x0d,0x03,0x3e,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x05,0x01,0x33,0x01,0x01,0xae,0xfe,0x9d,0x5f,0x01,0x63, 0x6e,0x03,0xac,0xfc,0x54,0x00,0x00,0x00,0x00,0x01,0x00,0x0a,0xff,0x4c,0x02,0x4e,0x00,0x00,0x00,0x0f,0x00,0x24,0x40,0x21,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x02,0x00,0x5f,0x04,0x01,0x00,0x00,0x3d,0x00,0x4e,0x01,0x00,0x0c,0x0b,0x09,0x06,0x04,0x03,0x00,0x0f,0x01,0x0e,0x05,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x33,0x14, 0x16,0x33,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0xb4,0x4e,0x5c,0x5a,0x31,0x29,0xdc,0x29,0x31,0x5a,0x5c,0x4e,0xb4,0x61,0x53,0x2e,0x36,0x36,0x2e,0x53,0x61,0x00,0x00,0x02,0x00,0xd9,0x00,0x46,0x01,0x7f,0x02,0x80,0x00,0x0b,0x00,0x17,0x00,0x30,0x40,0x2d,0x00,0x01,0x04,0x01,0x00,0x03,0x01,0x00,0x69,0x00,0x03,0x02,0x02,0x03, 0x59,0x00,0x03,0x03,0x02,0x61,0x05,0x01,0x02,0x03,0x02,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x25,0x2e,0x2e,0x25,0x26,0x2d, 0x2d,0x26,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0x01,0xea,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0xfe,0x5c,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0x00,0x00,0x00,0xff,0xff,0xff,0x1a,0x01,0x09,0xff,0xbe,0x01,0xab,0x01,0x07,0x03,0x29,0xfe,0x40,0x01,0x13,0x00,0x09,0xb1,0x00,0x01,0xb8,0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x00, 0xff,0xff,0xff,0x79,0x01,0x09,0x00,0x1d,0x01,0xab,0x01,0x07,0x03,0x29,0xfe,0x9f,0x01,0x13,0x00,0x09,0xb1,0x00,0x01,0xb8,0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x00,0x00,0x01,0x00,0xb9,0xff,0x88,0x01,0xe5,0x03,0x48,0x00,0x11,0x00,0x06,0xb3,0x07,0x00,0x01,0x32,0x2b,0x05,0x26,0x26,0x35,0x35,0x34,0x36,0x37,0x15,0x0e,0x02,0x15, 0x15,0x14,0x16,0x16,0x17,0x01,0xe5,0x8f,0x9d,0x9d,0x8f,0x40,0x5f,0x33,0x33,0x5f,0x40,0x78,0x20,0xcc,0x9a,0xb4,0x9a,0xcc,0x20,0x57,0x0f,0x54,0x7d,0x4f,0xb4,0x4e,0x7e,0x54,0x0f,0x00,0x00,0x01,0x00,0x73,0xff,0x88,0x01,0x9f,0x03,0x48,0x00,0x11,0x00,0x06,0xb3,0x0b,0x00,0x01,0x32,0x2b,0x17,0x35,0x3e,0x02,0x35,0x35,0x34,0x26, 0x26,0x27,0x35,0x16,0x16,0x15,0x15,0x14,0x06,0x73,0x41,0x5e,0x33,0x33,0x5e,0x41,0x8f,0x9d,0x9d,0x78,0x57,0x0f,0x54,0x7e,0x4e,0xb4,0x4f,0x7d,0x54,0x0f,0x57,0x20,0xcc,0x9a,0xb4,0x9a,0xcc,0x00,0x00,0x00,0x00,0x01,0x00,0x4b,0xff,0x92,0x01,0xf9,0x03,0x3e,0x00,0x24,0x00,0x3d,0x40,0x3a,0x1b,0x01,0x01,0x02,0x01,0x4c,0x00,0x03, 0x00,0x04,0x02,0x03,0x04,0x69,0x00,0x02,0x00,0x01,0x05,0x02,0x01,0x67,0x00,0x05,0x00,0x00,0x05,0x59,0x00,0x05,0x05,0x00,0x61,0x06,0x01,0x00,0x05,0x00,0x51,0x01,0x00,0x23,0x21,0x15,0x13,0x12,0x10,0x0b,0x09,0x08,0x06,0x00,0x24,0x01,0x24,0x07,0x09,0x16,0x2b,0x05,0x22,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x36, 0x27,0x27,0x26,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x07,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x01,0xcc,0x58,0x68,0x07,0x0f,0x05,0x28,0x41,0x73,0x73,0x41,0x28,0x05,0x0f,0x07,0x68,0x58,0x2d,0x2d,0x2f,0x34,0x04,0x0f,0x05,0x42,0x4b,0x4b,0x42,0x05,0x0f,0x04,0x34,0x2f,0x2d,0x6e,0x57,0x4f,0xa4,0x35, 0x2f,0x50,0x2f,0x35,0xa4,0x4f,0x57,0x50,0x2b,0x2b,0xa4,0x3b,0x47,0x07,0x07,0x4e,0x3a,0xa4,0x2b,0x2b,0x50,0x00,0x00,0x00,0x00,0x01,0x00,0x5f,0xff,0x92,0x02,0x0d,0x03,0x3e,0x00,0x26,0x00,0x38,0x40,0x35,0x09,0x01,0x04,0x03,0x01,0x4c,0x00,0x02,0x00,0x01,0x03,0x02,0x01,0x69,0x00,0x03,0x00,0x04,0x00,0x03,0x04,0x67,0x00,0x00, 0x05,0x05,0x00,0x59,0x00,0x00,0x00,0x05,0x61,0x06,0x01,0x05,0x00,0x05,0x51,0x00,0x00,0x00,0x26,0x00,0x25,0x21,0x26,0x21,0x2c,0x21,0x07,0x09,0x1b,0x2b,0x17,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x37,0x26,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x17, 0x17,0x16,0x06,0x06,0x23,0x5f,0x2d,0x2f,0x37,0x07,0x19,0x09,0x3a,0x33,0x33,0x3a,0x09,0x19,0x07,0x37,0x2f,0x2d,0x2d,0x3b,0x59,0x2d,0x08,0x19,0x08,0x2b,0x41,0x7d,0x7d,0x40,0x2c,0x08,0x19,0x08,0x2d,0x59,0x3b,0x6e,0x50,0x2b,0x2b,0xa4,0x39,0x4f,0x09,0x08,0x46,0x39,0xa4,0x2b,0x2b,0x50,0x27,0x4a,0x35,0xa4,0x35,0x2f,0x50,0x2f, 0x35,0xa4,0x34,0x4b,0x27,0x00,0x00,0x00,0x00,0x01,0x00,0xcd,0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x07,0x00,0x28,0x40,0x25,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x17,0x11, 0x33,0x15,0x23,0x11,0x33,0x15,0xcd,0xf5,0x9b,0x9b,0x6e,0x03,0xac,0x50,0xfc,0xf4,0x50,0x00,0x00,0x00,0x00,0x01,0x00,0x96,0xff,0x92,0x01,0x8b,0x03,0x3e,0x00,0x07,0x00,0x28,0x40,0x25,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x03,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00, 0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x17,0x35,0x33,0x11,0x23,0x35,0x33,0x11,0x96,0x9b,0x9b,0xf5,0x6e,0x50,0x03,0x0c,0x50,0xfc,0x54,0x00,0x00,0x00,0xff,0xff,0x00,0x4b,0xff,0x92,0x01,0xf9,0x03,0x3e,0x02,0x06,0x03,0x45,0x00,0x00,0xff,0xff,0x00,0x5f,0xff,0x92,0x02,0x0d,0x03,0x3e,0x02,0x06,0x03,0x46,0x00,0x00, 0x00,0x01,0x00,0x6e,0x00,0x00,0x01,0xef,0x02,0xda,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x33,0x03,0x13,0x33,0x03,0x13,0xf3,0x85,0x85,0xfc,0x85,0x85,0x01,0x6b,0x01,0x6f,0xfe,0x93,0xfe,0x93, 0x00,0x01,0x00,0x96,0x00,0x00,0x01,0xc5,0x02,0xda,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x21,0x03,0x13,0x33,0x03,0x13,0x01,0x1d,0x87,0x87,0xa8,0x87,0x87,0x01,0x6b,0x01,0x6f,0xfe,0x93,0xfe, 0x93,0x00,0x00,0x00,0x00,0x01,0x00,0x69,0x00,0x00,0x01,0xea,0x02,0xda,0x00,0x05,0x00,0x18,0x40,0x15,0x05,0x02,0x02,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x12,0x10,0x02,0x06,0x18,0x2b,0x21,0x23,0x13,0x03,0x33,0x13,0x01,0x65,0xfc,0x85,0x85,0xfc,0x85,0x01,0x6d,0x01,0x6d,0xfe,0x91,0x00,0x00,0x00, 0x00,0x01,0x00,0x93,0x00,0x00,0x01,0xc2,0x02,0xda,0x00,0x05,0x00,0x18,0x40,0x15,0x05,0x02,0x02,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x12,0x10,0x02,0x06,0x18,0x2b,0x21,0x23,0x13,0x03,0x33,0x13,0x01,0x3b,0xa8,0x87,0x87,0xa8,0x87,0x01,0x6d,0x01,0x6d,0xfe,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0xcd, 0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x17,0x11,0x33,0x15,0x23,0x11,0xcd,0xf5,0x9b,0x6e,0x03,0xac,0x50,0xfc,0xa4,0x00,0x00,0x00, 0x00,0x01,0x00,0xcd,0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x17,0x11,0x33,0x11,0x33,0x15,0xcd,0x5a,0x9b,0x6e,0x03,0xac,0xfc,0xa4, 0x50,0x00,0x00,0x00,0x00,0x01,0x00,0x87,0xff,0x92,0x01,0xea,0x03,0x48,0x00,0x26,0x00,0x5c,0x4b,0xb0,0x0e,0x50,0x58,0x40,0x20,0x05,0x01,0x04,0x03,0x01,0x03,0x04,0x72,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x1b,0x40,0x21,0x05,0x01,0x04,0x03, 0x01,0x03,0x04,0x01,0x80,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x59,0x40,0x0d,0x00,0x00,0x00,0x26,0x00,0x26,0x2c,0x21,0x2b,0x23,0x06,0x06,0x1a,0x2b,0x13,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x06,0x06,0x15,0x14,0x16,0x33, 0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x36,0x37,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0xb9,0x54,0x46,0x45,0x52,0x22,0x14,0x79,0x36,0x24,0x41,0x37,0x87,0x87,0x5f,0x73,0x09,0x21,0x25,0x85,0x21,0x14,0x1e,0x1f,0x1c,0x24,0x02,0x9c,0x1b,0x42,0x4f,0x4e,0x41,0x2b,0x53,0x21,0xca,0x5a,0x6e,0x25,0x3c,0x45,0x50, 0x70,0x5f,0x10,0x43,0x61,0x3b,0xd6,0x35,0x49,0x13,0x1a,0x27,0x24,0x1d,0x1b,0x00,0x00,0x01,0x00,0x96,0xff,0x92,0x01,0x8b,0x03,0x3e,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06, 0x18,0x2b,0x05,0x11,0x23,0x35,0x33,0x11,0x01,0x31,0x9b,0xf5,0x6e,0x03,0x5c,0x50,0xfc,0x54,0x00,0x00,0x00,0x01,0x00,0x96,0xff,0x92,0x01,0x8b,0x03,0x3e,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x03,0x01,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05, 0x11,0x11,0x04,0x06,0x18,0x2b,0x17,0x35,0x33,0x11,0x33,0x11,0x96,0x9b,0x5a,0x6e,0x50,0x03,0x5c,0xfc,0x54,0x00,0x00,0x00,0x00,0x01,0x00,0x78,0xff,0x92,0x01,0xdb,0x03,0x48,0x00,0x26,0x00,0x54,0x4b,0xb0,0x0e,0x50,0x58,0x40,0x1f,0x00,0x00,0x01,0x03,0x01,0x00,0x72,0x00,0x04,0x00,0x01,0x00,0x04,0x01,0x69,0x00,0x03,0x02,0x02, 0x03,0x57,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x03,0x02,0x4f,0x1b,0x40,0x20,0x00,0x00,0x01,0x03,0x01,0x00,0x03,0x80,0x00,0x04,0x00,0x01,0x00,0x04,0x01,0x69,0x00,0x03,0x02,0x02,0x03,0x57,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x03,0x02,0x4f,0x59,0xb7,0x2b,0x21,0x2c,0x23,0x10,0x05,0x06,0x1b,0x2b,0x01,0x23,0x35,0x34,0x26,0x23, 0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x1e,0x02,0x15,0x14,0x06,0x23,0x23,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x01,0xa9,0x5a,0x23,0x1d,0x1f,0x1e,0x14,0x21,0x85,0x25,0x21,0x09,0x73,0x5f,0x87,0x87,0x37,0x41,0x24,0x36,0x79,0x14,0x22,0x52,0x45,0x46,0x54,0x02,0x9c,0x1b,0x1d, 0x24,0x27,0x1a,0x13,0x49,0x35,0xd6,0x3b,0x61,0x43,0x10,0x5f,0x70,0x50,0x45,0x3c,0x25,0x6e,0x5a,0xca,0x21,0x53,0x2b,0x41,0x4e,0x4f,0x42,0x00,0x00,0x02,0x00,0xa0,0xff,0x88,0x01,0xe5,0x03,0x48,0x00,0x09,0x00,0x11,0x00,0x08,0xb5,0x0b,0x0a,0x09,0x00,0x02,0x32,0x2b,0x05,0x2e,0x02,0x35,0x35,0x34,0x36,0x36,0x37,0x03,0x11,0x06, 0x06,0x15,0x15,0x14,0x16,0x01,0xe5,0x62,0x93,0x50,0x50,0x93,0x62,0x55,0x46,0x50,0x50,0x78,0x10,0x6b,0xa5,0x66,0xb4,0x67,0xa4,0x6b,0x10,0xfc,0xb3,0x02,0xde,0x24,0x92,0x61,0xb4,0x5f,0x91,0x00,0x00,0x00,0x00,0x02,0x00,0x73,0xff,0x88,0x01,0xb8,0x03,0x48,0x00,0x09,0x00,0x11,0x00,0x08,0xb5,0x11,0x0a,0x01,0x00,0x02,0x32,0x2b, 0x17,0x11,0x1e,0x02,0x15,0x15,0x14,0x06,0x06,0x27,0x36,0x36,0x35,0x35,0x34,0x26,0x27,0x73,0x63,0x92,0x50,0x50,0x92,0x0e,0x46,0x50,0x50,0x46,0x78,0x03,0xc0,0x10,0x6b,0xa4,0x67,0xb4,0x66,0xa5,0x6b,0x63,0x23,0x91,0x5f,0xb4,0x61,0x92,0x24,0x00,0x00,0x01,0x00,0x8c,0x01,0x22,0x01,0xcc,0x01,0x72,0x00,0x03,0x00,0x1e,0x40,0x1b, 0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x8c,0x01,0x40,0x01,0x22,0x50,0x50,0x00,0xff,0xff,0x00,0x8c,0x01,0x22,0x01,0xcc,0x01,0x72,0x02,0x06,0x03,0x57,0x00,0x00,0x00,0x01,0x00,0x50,0x01,0x22,0x02,0x08, 0x01,0x72,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x50,0x01,0xb8,0x01,0x22,0x50,0x50,0x00,0x00,0x01,0x00,0x00,0x01,0x22,0x02,0x58,0x01,0x72,0x00,0x03,0x00,0x1e,0x40,0x1b, 0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x11,0x35,0x21,0x15,0x02,0x58,0x01,0x22,0x50,0x50,0x00,0x00,0xff,0xff,0x00,0x8c,0x01,0x22,0x01,0xcc,0x01,0x72,0x02,0x06,0x03,0x57,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x9c,0x02,0x1c, 0xff,0xe7,0x00,0x03,0x00,0x26,0xb1,0x06,0x64,0x44,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x17,0x35,0x21,0x15,0x3c,0x01,0xe0,0x64,0x4b,0x4b,0x00,0x00,0x00,0x01,0x00,0xdc,0xff,0x60,0x01,0x86, 0x00,0x91,0x00,0x0f,0x00,0x35,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0c,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x01,0x3d,0x01,0x4e,0x1b,0x40,0x11,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x59,0x40,0x0a,0x00,0x00,0x00,0x0f,0x00,0x0f,0x17,0x03,0x09,0x17,0x2b,0x17,0x37,0x36,0x36,0x35, 0x34,0x26,0x27,0x33,0x16,0x16,0x15,0x14,0x06,0x07,0x07,0xdc,0x38,0x09,0x0a,0x1c,0x19,0x65,0x16,0x19,0x0e,0x0b,0x2d,0xa0,0x7b,0x14,0x2a,0x0f,0x1d,0x39,0x13,0x14,0x38,0x1d,0x14,0x38,0x19,0x63,0x00,0x00,0xff,0xff,0x00,0x69,0xff,0x60,0x02,0x05,0x00,0x91,0x00,0x26,0x03,0x5d,0x8d,0x00,0x00,0x06,0x03,0x5d,0x7f,0x00,0x00,0x00, 0x00,0x02,0x00,0x69,0x01,0xa9,0x01,0xed,0x02,0xda,0x00,0x0f,0x00,0x1f,0x00,0x24,0x40,0x21,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x01,0x38,0x00,0x4e,0x10,0x10,0x00,0x00,0x10,0x1f,0x10,0x1f,0x18,0x17,0x00,0x0f,0x00,0x0f,0x17,0x06,0x09,0x17,0x2b,0x01,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x23,0x26,0x26,0x35, 0x34,0x36,0x37,0x37,0x23,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x01,0xed,0x38,0x09,0x0a,0x1c,0x19,0x65,0x16,0x19,0x0e,0x0b,0x2d,0x76,0x38,0x09,0x0a,0x1c,0x19,0x65,0x16,0x19,0x0e,0x0b,0x2d,0x02,0xda,0x7b,0x13,0x2b,0x0f,0x1d,0x39,0x13,0x14,0x39,0x1c,0x14,0x38,0x19,0x63,0x7b,0x13,0x2b, 0x0f,0x1d,0x39,0x13,0x14,0x39,0x1c,0x14,0x38,0x19,0x63,0x00,0xff,0xff,0x00,0x69,0x01,0xaf,0x01,0xef,0x02,0xe0,0x00,0x27,0x03,0x5d,0xff,0x8d,0x02,0x4f,0x01,0x07,0x03,0x5d,0x00,0x69,0x02,0x4f,0x00,0x12,0xb1,0x00,0x01,0xb8,0x02,0x4f,0xb0,0x35,0x2b,0xb1,0x01,0x01,0xb8,0x02,0x4f,0xb0,0x35,0x2b,0x00,0x00,0x00,0x01,0x00,0xd2, 0x01,0xa9,0x01,0x7c,0x02,0xda,0x00,0x0f,0x00,0x19,0x40,0x16,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x01,0x38,0x00,0x4e,0x00,0x00,0x00,0x0f,0x00,0x0f,0x17,0x03,0x09,0x17,0x2b,0x01,0x07,0x06,0x06,0x15,0x14,0x16,0x17,0x23,0x26,0x26,0x35,0x34,0x36,0x37,0x37,0x01,0x7c,0x38,0x09,0x0a,0x1c,0x19,0x65,0x16,0x19,0x0e,0x0b,0x2d, 0x02,0xda,0x7b,0x13,0x2b,0x0f,0x1d,0x39,0x13,0x14,0x39,0x1c,0x14,0x38,0x19,0x63,0xff,0xff,0x00,0xdc,0x01,0xa9,0x01,0x86,0x02,0xda,0x03,0x07,0x03,0x5d,0x00,0x00,0x02,0x49,0x00,0x09,0xb1,0x00,0x01,0xb8,0x02,0x49,0xb0,0x35,0x2b,0x00,0x00,0x00,0x00,0x01,0x00,0xd2,0x01,0xa9,0x01,0x7c,0x02,0xda,0x00,0x0f,0x00,0x13,0x40,0x10, 0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x01,0x38,0x00,0x4e,0x17,0x10,0x02,0x09,0x18,0x2b,0x01,0x23,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0x7c,0x64,0x2d,0x0b,0x0e,0x19,0x16,0x65,0x19,0x1c,0x0a,0x09,0x01,0xa9,0x63,0x19,0x38,0x14,0x1d,0x38,0x14,0x13,0x39,0x1d,0x0f,0x2a,0x14,0x00,0x00,0x00, 0x00,0x02,0x00,0x69,0x01,0xa9,0x01,0xef,0x02,0xda,0x00,0x0f,0x00,0x1f,0x00,0x17,0x40,0x14,0x02,0x01,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x01,0x38,0x00,0x4e,0x17,0x17,0x17,0x10,0x04,0x09,0x1a,0x2b,0x01,0x23,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x23,0x27,0x26,0x26,0x35,0x34,0x36,0x37, 0x33,0x06,0x06,0x15,0x14,0x16,0x17,0x01,0xef,0x64,0x2d,0x0b,0x0e,0x19,0x16,0x65,0x19,0x1c,0x0a,0x09,0xa4,0x64,0x2d,0x0b,0x0e,0x19,0x16,0x65,0x19,0x1c,0x0a,0x09,0x01,0xa9,0x63,0x19,0x38,0x14,0x1d,0x38,0x14,0x13,0x39,0x1d,0x0f,0x2a,0x14,0x7b,0x63,0x19,0x38,0x14,0x1d,0x38,0x14,0x13,0x39,0x1d,0x0f,0x2a,0x14,0x00,0x00,0x00, 0x00,0x02,0x00,0x1e,0x00,0x28,0x02,0x33,0x02,0x08,0x00,0x05,0x00,0x0b,0x00,0x33,0x40,0x30,0x0a,0x07,0x04,0x01,0x04,0x01,0x00,0x01,0x4c,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x09,0x08,0x00,0x05,0x00,0x05,0x12,0x06, 0x09,0x17,0x2b,0x25,0x27,0x37,0x33,0x07,0x17,0x21,0x27,0x37,0x33,0x07,0x17,0x01,0xcc,0xc0,0xbf,0x68,0xc4,0xc4,0xfe,0xab,0xc0,0xbf,0x6a,0xc4,0xc4,0x28,0xf0,0xf0,0xee,0xf2,0xf0,0xf0,0xee,0xf2,0x00,0x00,0x00,0x02,0x00,0x25,0x00,0x28,0x02,0x3a,0x02,0x08,0x00,0x05,0x00,0x0b,0x00,0x33,0x40,0x30,0x0a,0x07,0x04,0x01,0x04,0x01, 0x00,0x01,0x4c,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x09,0x08,0x00,0x05,0x00,0x05,0x12,0x06,0x09,0x17,0x2b,0x25,0x37,0x27,0x33,0x17,0x07,0x21,0x37,0x27,0x33,0x17,0x07,0x01,0x12,0xc0,0xc1,0x69,0xc0,0xbf,0xfe,0xab, 0xc0,0xc1,0x67,0xc0,0xbf,0x28,0xf1,0xef,0xf0,0xf0,0xf1,0xef,0xf0,0xf0,0x00,0x00,0x00,0x01,0x00,0x93,0x00,0x28,0x01,0xc6,0x02,0x08,0x00,0x05,0x00,0x25,0x40,0x22,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03, 0x09,0x17,0x2b,0x25,0x27,0x37,0x33,0x07,0x17,0x01,0x5d,0xca,0xca,0x66,0xcc,0xcf,0x28,0xf0,0xf0,0xee,0xf2,0x00,0x00,0x00,0x00,0x01,0x00,0x93,0x00,0x28,0x01,0xc6,0x02,0x08,0x00,0x05,0x00,0x25,0x40,0x22,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f, 0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x09,0x17,0x2b,0x37,0x37,0x27,0x33,0x17,0x07,0x96,0xcc,0xcf,0x69,0xca,0xca,0x28,0xee,0xf2,0xf0,0xf0,0xff,0xff,0x00,0x14,0x01,0xa3,0x02,0x44,0x02,0xd5,0x00,0x27,0x03,0x2a,0xff,0x42,0x02,0x43,0x00,0x27,0x03,0x2a,0x00,0x09,0x02,0x43,0x01,0x07,0x03,0x2a,0x00,0xcf,0x02,0x43,0x00,0x1b, 0xb1,0x00,0x01,0xb8,0x02,0x43,0xb0,0x35,0x2b,0xb1,0x01,0x01,0xb8,0x02,0x43,0xb0,0x35,0x2b,0xb1,0x02,0x01,0xb8,0x02,0x43,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x8f,0x01,0xae,0x01,0xc9,0x02,0xda,0x00,0x26,0x03,0x6b,0x96,0x00,0x00,0x06,0x03,0x6b,0x6a,0x00,0x00,0x00,0x00,0x01,0x00,0xf9,0x01,0xae,0x01,0x5f,0x02,0xda,0x00,0x03, 0x00,0x19,0x40,0x16,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x01,0x4e,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x01,0x03,0x33,0x03,0x01,0x01,0x08,0x66,0x07,0x01,0xae,0x01,0x2c,0xfe,0xd4,0x00,0x00,0x00,0x02,0xfe,0x34,0x01,0x22,0x01,0xcc,0x01,0x72,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x02,0x01, 0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x2d,0x01,0x9f,0xfc,0x68,0x01,0x9f,0x01,0x22,0x50,0x50,0x50,0x50,0x00,0x00,0x03,0xfb,0xdc, 0x01,0x22,0x01,0xcc,0x01,0x72,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x36,0x40,0x33,0x04,0x02,0x02,0x00,0x01,0x01,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x01,0x5f,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x00,0x01,0x4f,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11, 0x09,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x0f,0x01,0xbd,0xfa,0x10,0x01,0xbd,0x5f,0x01,0xb8,0x01,0x22,0x50,0x50,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x02,0xf9,0x4d,0xff,0x74,0x01,0xf4,0x03,0x20,0x00,0x29,0x00,0x50,0x00,0x84,0xb5,0x33,0x01,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58, 0x40,0x24,0x0b,0x05,0x02,0x02,0x0c,0x06,0x02,0x01,0x00,0x02,0x01,0x67,0x08,0x01,0x00,0x0f,0x0d,0x0e,0x03,0x07,0x00,0x07,0x65,0x09,0x01,0x03,0x03,0x04,0x61,0x0a,0x01,0x04,0x04,0x40,0x03,0x4e,0x1b,0x40,0x2b,0x0a,0x01,0x04,0x09,0x01,0x03,0x02,0x04,0x03,0x69,0x0b,0x05,0x02,0x02,0x0c,0x06,0x02,0x01,0x00,0x02,0x01,0x67,0x08, 0x01,0x00,0x07,0x07,0x00,0x59,0x08,0x01,0x00,0x00,0x07,0x61,0x0f,0x0d,0x0e,0x03,0x07,0x00,0x07,0x51,0x59,0x40,0x20,0x2a,0x2a,0x00,0x00,0x2a,0x50,0x2a,0x4f,0x49,0x47,0x46,0x44,0x3e,0x3c,0x3b,0x39,0x2d,0x2b,0x00,0x29,0x00,0x28,0x21,0x26,0x21,0x26,0x11,0x16,0x21,0x10,0x09,0x1d,0x2b,0x05,0x35,0x33,0x32,0x36,0x27,0x27,0x26, 0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x06,0x23,0x21,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x37,0x26,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15, 0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x06,0x23,0xfe,0x34,0x2d,0x2f,0x37,0x07,0x19,0x04,0x0c,0x0f,0xfa,0x8f,0x05,0x75,0x11,0x0f,0x05,0x19,0x07,0x37,0x2f,0x2d,0x2d,0x3b,0x59,0x2d,0x08,0x19,0x08,0x2b,0x41,0x7d,0x7d,0x40,0x2c,0x08,0x19,0x08,0x2d,0x59,0x3b,0x01,0xe5,0x2d,0x2f,0x37,0x07,0x19,0x09,0x3a,0x33,0x33,0x3a,0x09,0x19, 0x07,0x37,0x2f,0x2d,0x2d,0x3b,0x59,0x2d,0x08,0x19,0x08,0x2b,0x41,0x7d,0x7d,0x40,0x2c,0x08,0x19,0x08,0x2d,0x59,0x3b,0x8c,0x50,0x2b,0x2b,0xa4,0x1e,0x33,0x13,0x50,0x11,0x33,0x20,0xa4,0x2b,0x2b,0x50,0x27,0x4a,0x35,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x34,0x4b,0x27,0x50,0x2b,0x2b,0xa4,0x39,0x4f,0x09,0x08,0x46,0x39,0xa4,0x2b, 0x2b,0x50,0x27,0x4a,0x35,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x34,0x4b,0x27,0x00,0x00,0x01,0xfb,0xa6,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0c,0x00,0x2a,0x40,0x27,0x02,0x01,0x02,0x03,0x01,0x4c,0x00,0x00,0x03,0x00,0x85,0x00,0x01,0x02,0x01,0x86,0x00,0x03,0x02,0x02,0x03,0x57,0x00,0x03,0x03,0x02,0x60,0x00,0x02,0x03,0x02,0x50, 0x11,0x13,0x12,0x10,0x04,0x09,0x1a,0x2b,0x13,0x33,0x13,0x03,0x23,0x37,0x36,0x37,0x21,0x35,0x21,0x26,0x27,0xbc,0x6a,0xe7,0xe8,0x69,0xbe,0x08,0x08,0xfa,0x1c,0x05,0xe4,0x0a,0x0a,0x02,0x71,0xfe,0xd9,0xfe,0xd9,0xef,0x0a,0x06,0x50,0x08,0x0c,0x00,0x00,0x01,0xfe,0x5c,0xff,0xab,0x01,0x59,0x02,0xee,0x00,0x07,0x00,0x47,0x4b,0xb0, 0x18,0x50,0x58,0x40,0x14,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x04,0x01,0x03,0x03,0x02,0x5f,0x00,0x02,0x02,0x38,0x03,0x4e,0x1b,0x40,0x19,0x00,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x59,0x40,0x0c,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11, 0x11,0x05,0x09,0x19,0x2b,0x17,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0xff,0xfd,0x5d,0x02,0xa3,0x5a,0x55,0x01,0x77,0x50,0x01,0x7c,0xfc,0xbd,0x00,0x00,0x01,0xfd,0xfd,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0e,0x00,0x2a,0x40,0x27,0x02,0x01,0x02,0x03,0x01,0x4c,0x00,0x00,0x03,0x00,0x85,0x00,0x01,0x02,0x01,0x86,0x00,0x03,0x02,0x02, 0x03,0x57,0x00,0x03,0x03,0x02,0x60,0x00,0x02,0x03,0x02,0x50,0x11,0x23,0x12,0x10,0x04,0x09,0x1a,0x2b,0x13,0x33,0x13,0x03,0x23,0x37,0x36,0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x27,0xbc,0x6a,0xe7,0xe8,0x69,0xbe,0x03,0x07,0x03,0xfc,0x76,0x03,0x8a,0x04,0x08,0x05,0x02,0x71,0xfe,0xd9,0xfe,0xd9,0xef,0x04,0x08,0x04,0x50,0x05,0x0a, 0x05,0x00,0x00,0x00,0x00,0x02,0xfb,0xa5,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0e,0x00,0x1a,0x00,0x3c,0x40,0x39,0x19,0x13,0x0d,0x03,0x00,0x01,0x01,0x4c,0x04,0x01,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x68,0x04,0x01,0x02,0x02,0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x02,0x03,0x4f,0x0f,0x0f,0x00,0x00,0x0f, 0x1a,0x0f,0x1a,0x18,0x17,0x00,0x0e,0x00,0x0e,0x14,0x11,0x23,0x08,0x09,0x19,0x2b,0x27,0x37,0x36,0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x33,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x70,0xbe,0x03,0x07,0x03,0xfb,0x4a,0x04,0xb6,0x04,0x08,0x05,0xba,0x6a,0xe7,0xe8,0xc3,0xbe,0x13,0x1a,0x05, 0x05,0x1c,0x15,0xba,0x6a,0xe7,0xe8,0x23,0xef,0x04,0x08,0x04,0x50,0x05,0x0a,0x05,0xeb,0xfe,0xd9,0xfe,0xd9,0xef,0x17,0x1c,0x04,0x05,0x1f,0x19,0xeb,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x00,0x00,0x01,0xfd,0xfd,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0a,0x00,0x2e,0x40,0x2b,0x08,0x01,0x00,0x01,0x01,0x4c,0x00,0x02,0x01,0x03,0x02,0x57, 0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x0a,0x00,0x0a,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x25,0x27,0x21,0x35,0x21,0x37,0x33,0x07,0x07,0x17,0x17,0x01,0x8a,0xc8,0xfd,0x3b,0x02,0xc5,0xc9,0x69,0xbe,0x2e,0x32,0xba,0x23,0xff,0x50,0xff,0xef,0x37,0x3d,0xeb, 0x00,0x02,0xfb,0xa5,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0a,0x00,0x12,0x00,0x3c,0x40,0x39,0x10,0x0c,0x08,0x03,0x00,0x01,0x01,0x4c,0x04,0x01,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x04,0x01,0x02,0x02,0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x02,0x03,0x4f,0x0b,0x0b,0x00,0x00,0x0b,0x12,0x0b,0x12,0x0e, 0x0d,0x00,0x0a,0x00,0x0a,0x11,0x11,0x11,0x08,0x09,0x19,0x2b,0x37,0x27,0x21,0x35,0x21,0x37,0x33,0x07,0x07,0x17,0x17,0x33,0x03,0x13,0x33,0x07,0x07,0x17,0x17,0x5e,0xc8,0xfc,0x0f,0x03,0xf1,0xc9,0x69,0xbe,0x2e,0x32,0xba,0xc2,0xe7,0xe8,0x69,0xbe,0x2e,0x32,0xba,0x23,0xff,0x50,0xff,0xef,0x37,0x3d,0xeb,0x01,0x27,0x01,0x27,0xef, 0x37,0x3d,0xeb,0x00,0x00,0x01,0xfe,0x11,0x00,0xdc,0x01,0xef,0x01,0xb8,0x00,0x1d,0x00,0x6e,0x4b,0xb0,0x11,0x50,0x58,0x40,0x22,0x00,0x04,0x00,0x06,0x03,0x04,0x06,0x69,0x00,0x03,0x01,0x00,0x03,0x59,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x03,0x03,0x00,0x61,0x05,0x07,0x02,0x00,0x03,0x00,0x51,0x1b,0x40,0x29,0x00,0x05, 0x01,0x00,0x01,0x05,0x00,0x80,0x00,0x04,0x00,0x06,0x03,0x04,0x06,0x69,0x00,0x03,0x01,0x00,0x03,0x59,0x00,0x02,0x00,0x01,0x05,0x02,0x01,0x67,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x03,0x00,0x51,0x59,0x40,0x15,0x01,0x00,0x19,0x17,0x14,0x13,0x10,0x0e,0x0a,0x08,0x05,0x04,0x03,0x02,0x00,0x1d,0x01,0x1d,0x08,0x09,0x16,0x2b, 0x37,0x22,0x27,0x21,0x35,0x21,0x15,0x14,0x16,0x33,0x32,0x3e,0x03,0x33,0x32,0x16,0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x22,0x0e,0x03,0x64,0x62,0x27,0xfe,0x36,0x02,0x0d,0x27,0x1f,0x1a,0x27,0x23,0x29,0x39,0x2a,0x46,0x55,0x55,0x26,0x20,0x1b,0x27,0x24,0x29,0x38,0xdc,0x46,0x50,0x05,0x22,0x24,0x1d,0x2b,0x2c,0x1d,0x50,0x41,0x3c, 0x3c,0x20,0x26,0x1d,0x2b,0x2c,0x1d,0x00,0xff,0xff,0xfe,0x0c,0xff,0x92,0x01,0xcc,0x03,0x3e,0x00,0x27,0x03,0x45,0xfd,0xc1,0x00,0x00,0x00,0x06,0x03,0x45,0xd3,0x00,0x00,0x03,0xf9,0x7f,0xff,0x74,0x02,0x03,0x03,0x20,0x00,0x24,0x00,0x4a,0x00,0x4f,0x00,0x8d,0xb7,0x4e,0x4d,0x1b,0x03,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58, 0x40,0x24,0x0b,0x08,0x02,0x02,0x0c,0x07,0x02,0x01,0x05,0x02,0x01,0x67,0x0d,0x01,0x05,0x0f,0x06,0x0e,0x03,0x00,0x05,0x00,0x65,0x0a,0x01,0x04,0x04,0x03,0x61,0x09,0x01,0x03,0x03,0x40,0x04,0x4e,0x1b,0x40,0x2b,0x09,0x01,0x03,0x0a,0x01,0x04,0x02,0x03,0x04,0x69,0x0b,0x08,0x02,0x02,0x0c,0x07,0x02,0x01,0x05,0x02,0x01,0x67,0x0d, 0x01,0x05,0x00,0x00,0x05,0x59,0x0d,0x01,0x05,0x05,0x00,0x61,0x0f,0x06,0x0e,0x03,0x00,0x05,0x00,0x51,0x59,0x40,0x27,0x26,0x25,0x01,0x00,0x49,0x47,0x42,0x41,0x40,0x3f,0x3a,0x38,0x37,0x35,0x30,0x2e,0x2d,0x2b,0x25,0x4a,0x26,0x4a,0x23,0x21,0x15,0x13,0x12,0x10,0x0b,0x09,0x08,0x06,0x00,0x24,0x01,0x24,0x10,0x09,0x16,0x2b,0x05, 0x22,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x07,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x21,0x22,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x07,0x21, 0x15,0x21,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x01,0x16,0x17,0x35,0x06,0xfb,0x00,0x58,0x68,0x07,0x0f,0x05,0x28,0x41,0x73,0x73,0x41,0x28,0x05,0x0f,0x07,0x68,0x58,0x2d,0x2d,0x2f,0x34,0x04,0x0f,0x05,0x42,0x4b,0x4b,0x42,0x05,0x0f,0x04,0x34,0x2f,0x2d,0x01,0xe8,0x58,0x68,0x07,0x0f,0x05,0x28,0x41,0x73,0x73,0x41,0x28,0x05, 0x0f,0x07,0x68,0x58,0x2d,0x2d,0x2f,0x34,0x04,0x0f,0x06,0x27,0x05,0x5f,0xfa,0xa3,0x25,0x06,0x0f,0x04,0x34,0x2f,0x2d,0xfe,0xfb,0x17,0x14,0x14,0x8c,0x57,0x4f,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x4f,0x57,0x50,0x2b,0x2b,0xa4,0x3b,0x47,0x07,0x07,0x4e,0x3a,0xa4,0x2b,0x2b,0x50,0x57,0x4f,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x4f, 0x57,0x50,0x2b,0x2b,0xa4,0x41,0x23,0x50,0x25,0x3f,0xa4,0x2b,0x2b,0x50,0x01,0xd9,0x02,0x06,0x0f,0x05,0x00,0x05,0xf9,0x7f,0xff,0x74,0x02,0x03,0x03,0x20,0x00,0x25,0x00,0x29,0x00,0x2d,0x00,0x32,0x00,0x40,0x00,0xaf,0xb6,0x30,0x2e,0x02,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x36,0x0a,0x05,0x02,0x02,0x10,0x0b,0x06, 0x03,0x01,0x09,0x02,0x01,0x67,0x00,0x07,0x0e,0x01,0x00,0x07,0x00,0x65,0x00,0x04,0x04,0x03,0x61,0x00,0x03,0x03,0x40,0x4d,0x0f,0x01,0x09,0x09,0x08,0x5f,0x00,0x08,0x08,0x38,0x4d,0x00,0x0d,0x0d,0x0c,0x61,0x11,0x01,0x0c,0x0c,0x42,0x0c,0x4e,0x1b,0x40,0x34,0x00,0x03,0x00,0x04,0x02,0x03,0x04,0x69,0x0a,0x05,0x02,0x02,0x10,0x0b, 0x06,0x03,0x01,0x09,0x02,0x01,0x67,0x00,0x07,0x0e,0x01,0x00,0x07,0x00,0x65,0x0f,0x01,0x09,0x09,0x08,0x5f,0x00,0x08,0x08,0x38,0x4d,0x00,0x0d,0x0d,0x0c,0x61,0x11,0x01,0x0c,0x0c,0x42,0x0c,0x4e,0x59,0x40,0x2f,0x34,0x33,0x2a,0x2a,0x26,0x26,0x01,0x00,0x3b,0x38,0x33,0x40,0x34,0x3f,0x2a,0x2d,0x2a,0x2d,0x2c,0x2b,0x26,0x29,0x26, 0x29,0x28,0x27,0x24,0x22,0x1d,0x1c,0x1b,0x1a,0x15,0x13,0x12,0x10,0x0b,0x09,0x08,0x06,0x00,0x25,0x01,0x25,0x12,0x09,0x16,0x2b,0x05,0x22,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x07,0x21,0x15,0x21,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x01, 0x03,0x33,0x03,0x37,0x35,0x21,0x15,0x25,0x16,0x17,0x35,0x06,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfb,0x00,0x58,0x68,0x07,0x0f,0x05,0x28,0x41,0x73,0x73,0x41,0x28,0x05,0x0f,0x07,0x68,0x58,0x2d,0x2d,0x2f,0x34,0x04,0x0f,0x06,0x27,0x01,0x25,0xfe,0xdd,0x25,0x06,0x0f,0x04,0x34,0x2f,0x2d,0x01, 0x28,0x0c,0x6a,0x0c,0x9d,0x04,0xbf,0xf8,0x25,0x0e,0x0c,0x0c,0x02,0x39,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0x8c,0x57,0x4f,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x4f,0x57,0x50,0x2b,0x2b,0xa4,0x41,0x23,0x50,0x25,0x3f,0xa4,0x2b,0x2b,0x50,0x01,0x63,0x02,0x03,0xfd,0xfd,0x4b,0x50,0x50,0x2b,0x01,0x03,0x08,0x02,0xfe,0xac, 0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0xff,0xff,0xfc,0x09,0xff,0x92,0x01,0x40,0x03,0x3e,0x00,0x27,0x03,0x45,0xfb,0xbe,0x00,0x00,0x00,0x27,0x03,0x2e,0xfd,0xf3,0x00,0x00,0x00,0x06,0x03,0x2e,0xc9,0x00,0x00,0x02,0xfe,0x43,0xff,0x92,0x01,0x45,0x03,0x3e,0x00,0x24,0x00,0x28,0x00,0x48,0x40,0x45,0x1b,0x01,0x01,0x02,0x01,0x4c, 0x06,0x01,0x03,0x00,0x04,0x02,0x03,0x04,0x67,0x00,0x02,0x00,0x01,0x05,0x02,0x01,0x67,0x00,0x05,0x00,0x00,0x05,0x57,0x00,0x05,0x05,0x00,0x5f,0x09,0x07,0x08,0x03,0x00,0x05,0x00,0x4f,0x25,0x25,0x01,0x00,0x25,0x28,0x25,0x28,0x27,0x26,0x23,0x21,0x15,0x13,0x12,0x10,0x0b,0x09,0x08,0x06,0x00,0x24,0x01,0x24,0x0a,0x09,0x16,0x2b, 0x07,0x22,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x07,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x33,0x11,0x33,0x11,0x3c,0x58,0x65,0x04,0x0a,0x03,0x26,0x41,0x6e,0x6e,0x41,0x26,0x03,0x0a,0x04,0x65,0x58,0x73,0x73,0x2f,0x32,0x02,0x0a, 0x03,0x35,0x32,0x31,0x36,0x03,0x0a,0x02,0x32,0x2f,0x73,0xb4,0x5a,0x6e,0x57,0x4f,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x4f,0x57,0x50,0x2b,0x2b,0xa4,0x39,0x4a,0x09,0x09,0x4a,0x39,0xa4,0x2b,0x2b,0x50,0x03,0xac,0xfc,0x54,0x00,0xff,0xff,0xfe,0x34,0xff,0x92,0x01,0xf4,0x03,0x3e,0x00,0x27,0x03,0x46,0xfd,0xd5,0x00,0x00,0x00,0x06, 0x03,0x46,0xe7,0x00,0x00,0x02,0xfe,0xbb,0xff,0x92,0x01,0x45,0x03,0x3e,0x00,0x07,0x00,0x0b,0x00,0x33,0x40,0x30,0x04,0x01,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x02,0x03,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07, 0x11,0x11,0x11,0x08,0x09,0x19,0x2b,0x05,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x33,0x11,0x33,0x11,0xfe,0xbb,0x01,0x81,0xfe,0xd9,0x01,0x27,0xaf,0x5a,0x6e,0x03,0xac,0x50,0xfc,0xf4,0x50,0x03,0xac,0xfc,0x54,0xff,0xff,0xfe,0x8e,0xff,0x92,0x01,0x9f,0x03,0x3e,0x00,0x27,0x03,0x47,0xfd,0xc1,0x00,0x00,0x01,0x06,0x04,0x1c,0x9c,0x0f, 0x00,0x08,0xb1,0x01,0x01,0xb0,0x0f,0xb0,0x35,0x2b,0x00,0x00,0x00,0x03,0xfe,0x3e,0xff,0x92,0x02,0x35,0x03,0x3e,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x5e,0x40,0x5b,0x00,0x04,0x00,0x03,0x06,0x04,0x03,0x67,0x09,0x07,0x02,0x05,0x13,0x10,0x02,0x0a,0x0b,0x05,0x0a,0x68,0x12,0x11,0x02,0x0b,0x0e,0x0c,0x02,0x00,0x0d,0x0b,0x00,0x67, 0x00,0x02,0x00,0x01,0x02,0x01,0x63,0x08,0x01,0x06,0x06,0x38,0x4d,0x14,0x0f,0x02,0x0d,0x0d,0x39,0x0d,0x4e,0x00,0x00,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x00,0x1f,0x00,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x15,0x09,0x1f,0x2b,0x33,0x37,0x21,0x11, 0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x11,0x21,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x13,0x21,0x15,0x21,0x33,0x33,0x37,0x23,0x53,0x27,0xfe,0xb9,0xf5,0x9b,0x9b,0xf5,0x01,0x7f,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x0e, 0xfe,0x8c,0x01,0x52,0x46,0xa0,0x22,0xa0,0xd2,0xfe,0xc0,0x50,0x03,0x0c,0x50,0xfe,0xca,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0x01,0xc7,0xb4,0xb4,0x00,0xff,0xff,0xfe,0xd4,0xff,0xf6,0x01,0x2e,0x00,0x98,0x00,0x27,0x03,0x29,0xfd,0xfa,0x00,0x00,0x00,0x06,0x03,0x29,0xb0,0x00,0xff,0xff,0xfc,0x90,0xff,0xf6,0x01,0x1a, 0x00,0x98,0x00,0x27,0x03,0x29,0xfb,0xb6,0x00,0x00,0x00,0x27,0x03,0x29,0xfd,0xa9,0x00,0x00,0x00,0x06,0x03,0x29,0x9c,0x00,0xff,0xff,0xfc,0x71,0xff,0xf6,0x01,0x45,0x02,0x53,0x00,0x27,0x04,0x1c,0xff,0x42,0x00,0x00,0x00,0x27,0x03,0x29,0xfb,0x97,0x00,0x00,0x00,0x07,0x03,0x29,0xfd,0x4d,0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0x82, 0xff,0xf6,0x01,0x81,0x02,0xda,0x00,0x27,0x03,0x29,0xfd,0xa8,0x00,0x00,0x00,0x06,0x03,0x30,0x9c,0x00,0xff,0xff,0xfe,0x5c,0x00,0xaa,0x02,0x03,0x01,0xea,0x00,0x27,0x03,0x33,0xfd,0xa8,0xff,0xdd,0x03,0x06,0x04,0x19,0x00,0x00,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0xdd,0xb0,0x35,0x2b,0x00,0xff,0xff,0xfe,0xd1,0xff,0xf6,0x01,0x2f, 0x02,0x30,0x00,0x27,0x03,0x2b,0xfd,0xf8,0x00,0x00,0x00,0x06,0x03,0x2b,0xb0,0x00,0xff,0xff,0xfc,0xc9,0xff,0xf6,0x00,0xdf,0x02,0x30,0x00,0x27,0x03,0x2b,0xfb,0xf0,0x00,0x00,0x00,0x27,0x03,0x2b,0xfd,0xa8,0x00,0x00,0x00,0x07,0x03,0x2b,0xff,0x60,0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0x44,0x00,0x2d,0x01,0x81,0x02,0x67,0x00,0x27, 0x03,0x2b,0xfb,0x6b,0x00,0x37,0x00,0x27,0x03,0x2b,0xfd,0x2f,0x00,0x37,0x01,0x07,0x04,0x19,0xff,0x7e,0x00,0x00,0x00,0x10,0xb1,0x00,0x02,0xb0,0x37,0xb0,0x35,0x2b,0xb1,0x02,0x02,0xb0,0x37,0xb0,0x35,0x2b,0xff,0xff,0xfe,0xb3,0xff,0xf6,0x01,0x81,0x02,0xda,0x00,0x26,0x03,0x30,0x9c,0x00,0x00,0x07,0x03,0x2b,0xfd,0xda,0x00,0x00, 0x00,0x05,0xfc,0x2c,0xff,0xf6,0x01,0xae,0x02,0xda,0x00,0x14,0x00,0x21,0x00,0x2f,0x00,0x3d,0x00,0x4b,0x01,0x3b,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x1b,0x1f,0x01,0x06,0x01,0x1e,0x01,0x05,0x06,0x20,0x1a,0x02,0x03,0x00,0x21,0x01,0x04,0x03,0x16,0x01,0x08,0x04,0x15,0x01,0x07,0x0a,0x06,0x4c,0x1b,0x40,0x1b,0x1f,0x01,0x06,0x01,0x1e, 0x01,0x05,0x06,0x20,0x1a,0x02,0x03,0x00,0x21,0x01,0x04,0x03,0x16,0x01,0x08,0x04,0x15,0x01,0x09,0x0a,0x06,0x4c,0x59,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x40,0x0b,0x01,0x04,0x03,0x08,0x03,0x04,0x72,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x0c,0x01,0x05,0x05,0x06,0x61,0x00,0x06, 0x06,0x41,0x4d,0x00,0x08,0x08,0x07,0x61,0x0e,0x09,0x0d,0x03,0x07,0x07,0x3f,0x4d,0x00,0x0a,0x0a,0x07,0x61,0x0e,0x09,0x0d,0x03,0x07,0x07,0x3f,0x07,0x4e,0x1b,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x41,0x0b,0x01,0x04,0x03,0x08,0x03,0x04,0x08,0x80,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38, 0x4d,0x0c,0x01,0x05,0x05,0x06,0x61,0x00,0x06,0x06,0x41,0x4d,0x00,0x08,0x08,0x07,0x61,0x0e,0x09,0x0d,0x03,0x07,0x07,0x3f,0x4d,0x00,0x0a,0x0a,0x07,0x61,0x0e,0x09,0x0d,0x03,0x07,0x07,0x3f,0x07,0x4e,0x1b,0x40,0x3d,0x0b,0x01,0x04,0x03,0x08,0x03,0x04,0x08,0x80,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x01,0x01,0x02,0x5f, 0x00,0x02,0x02,0x38,0x4d,0x0c,0x01,0x05,0x05,0x06,0x61,0x00,0x06,0x06,0x41,0x4d,0x00,0x0a,0x0a,0x09,0x61,0x0e,0x01,0x09,0x09,0x42,0x4d,0x00,0x08,0x08,0x07,0x61,0x0d,0x01,0x07,0x07,0x3f,0x07,0x4e,0x59,0x59,0x40,0x25,0x3f,0x3e,0x31,0x30,0x23,0x22,0x00,0x00,0x46,0x43,0x3e,0x4b,0x3f,0x4a,0x38,0x35,0x30,0x3d,0x31,0x3c,0x2a, 0x27,0x22,0x2f,0x23,0x2e,0x00,0x14,0x00,0x14,0x16,0x21,0x24,0x21,0x0f,0x09,0x1a,0x2b,0x25,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0x25,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06, 0x23,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x25,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfe,0x09,0x32,0x40,0x4b,0x4b,0x41,0x7d,0x7d,0x46,0x67,0x39,0x30,0x55,0x38,0x01,0x9d,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0xca,0x01,0xae,0xfa,0xc9,0x21,0x2a,0x2b,0x20, 0x14,0x20,0x2b,0x2a,0x21,0x14,0x21,0x2a,0x2b,0x20,0x14,0x20,0x2b,0x2a,0x21,0x01,0x9b,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0xaa,0x47,0x3b,0x3b,0x47,0x55,0x35,0x60,0x42,0x39,0x5b,0x36,0x03,0x5f,0x96,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0x5a,0xd7,0x64,0x82,0x2a,0x21,0x20,0x2b,0x2b,0x20,0x21,0x2a,0xfe, 0x5c,0x2a,0x21,0x20,0x2b,0x2b,0x20,0x21,0x2a,0x05,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x00,0x04,0xfe,0x52,0x00,0x64,0x01,0xd6,0x02,0x30,0x00,0x0b,0x00,0x0f,0x00,0x1b,0x00,0x1f,0x00,0x7b,0x4b,0xb0,0x18,0x50,0x58,0x40,0x24,0x00,0x02,0x00,0x00,0x02,0x57,0x0b,0x01,0x07,0x04,0x05,0x07,0x57,0x06,0x01,0x05,0x0a, 0x01,0x04,0x05,0x04,0x65,0x09,0x03,0x08,0x03,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x01,0x4e,0x1b,0x40,0x26,0x00,0x02,0x09,0x01,0x03,0x00,0x02,0x03,0x67,0x00,0x06,0x0b,0x01,0x07,0x04,0x06,0x07,0x67,0x00,0x05,0x0a,0x01,0x04,0x05,0x04,0x65,0x08,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x00,0x4e,0x59,0x40,0x23,0x1c, 0x1c,0x11,0x10,0x0c,0x0c,0x01,0x00,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x35,0x21,0x15,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37, 0x35,0x21,0x15,0xfe,0xa2,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xea,0x02,0x26,0xfc,0xcc,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xea,0x02,0x26,0x01,0x90,0x2b,0x25,0x24,0x2c,0x2c,0x24,0x25,0x2b,0x0a,0x50,0x50,0xfe,0xca,0x2c,0x25,0x24,0x2b,0x2b,0x24,0x25,0x2c,0x46,0x50,0x50,0x00,0x00,0x00,0xff,0xff,0xfe,0x81,0x00,0x2d,0x01,0x9f, 0x02,0x67,0x00,0x26,0x04,0x1b,0x9c,0x00,0x01,0x07,0x03,0x2b,0xfd,0xa8,0x00,0x37,0x00,0x08,0xb1,0x01,0x02,0xb0,0x37,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0xfe,0x81,0x00,0x2d,0x01,0x77,0x02,0x67,0x00,0x27,0x03,0x2b,0xfd,0xa8,0x00,0x37,0x01,0x07,0x04,0x1c,0xff,0x74,0x00,0x00,0x00,0x08,0xb1,0x00,0x02,0xb0,0x37,0xb0,0x35,0x2b, 0xff,0xff,0xfe,0xc5,0xff,0x60,0x01,0x31,0x02,0x30,0x00,0x27,0x03,0x2c,0xfd,0xf8,0x00,0x00,0x00,0x06,0x03,0x2c,0xb0,0x00,0xff,0xff,0xfc,0xbd,0xff,0x60,0x00,0xe1,0x02,0x30,0x00,0x27,0x03,0x2c,0xfd,0xa8,0x00,0x00,0x00,0x27,0x03,0x2c,0xff,0x60,0x00,0x00,0x00,0x07,0x03,0x2c,0xfb,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xc5, 0xff,0xfb,0x01,0x3b,0x02,0xda,0x00,0x27,0x03,0x2e,0xfd,0xe4,0x00,0x00,0x00,0x06,0x03,0x2e,0xc4,0x00,0xff,0xff,0xfc,0x68,0xff,0x92,0x01,0x9f,0x03,0x3e,0x00,0x27,0x03,0x2e,0xfb,0x87,0x00,0x00,0x00,0x27,0x03,0x2e,0xfd,0x5d,0x00,0x00,0x00,0x06,0x03,0x46,0x92,0x00,0x00,0x01,0xfd,0xf8,0x00,0x00,0x02,0x08,0x02,0x99,0x00,0x13, 0x00,0x35,0x40,0x32,0x00,0x04,0x03,0x04,0x85,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x68,0x07,0x01,0x01,0x08,0x01,0x00,0x09,0x01,0x00,0x67,0x0a,0x01,0x09,0x09,0x39,0x09,0x4e,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x09,0x1f,0x2b,0x23,0x37,0x21,0x35,0x21,0x37,0x21,0x35,0x21, 0x37,0x33,0x07,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0x98,0x3e,0xfe,0x52,0x01,0xcc,0x3a,0xfd,0xfa,0x02,0x24,0x40,0x46,0x40,0x01,0xa6,0xfe,0x3c,0x3a,0x01,0xfe,0xfd,0xe4,0x3e,0xaa,0x50,0xa0,0x50,0xaf,0xaf,0x50,0xa0,0x50,0xaa,0x00,0x00,0x00,0x00,0x01,0xfb,0xa5,0xff,0x92,0x02,0x03,0x03,0x3e,0x00,0x1b,0x00,0x4f,0x40,0x4c, 0x00,0x06,0x05,0x06,0x85,0x0e,0x01,0x0d,0x00,0x0d,0x86,0x07,0x01,0x05,0x08,0x01,0x04,0x03,0x05,0x04,0x68,0x09,0x01,0x03,0x0a,0x01,0x02,0x01,0x03,0x02,0x67,0x0b,0x01,0x01,0x00,0x00,0x01,0x57,0x0b,0x01,0x01,0x01,0x00,0x5f,0x0c,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x09,0x1f,0x2b,0x05,0x37,0x21,0x35,0x21,0x37,0x21,0x35,0x21,0x37,0x21,0x35,0x21,0x37,0x33,0x07,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0xfe,0x1f,0x44,0xfd,0x42,0x02,0xda,0x34,0xfc,0xf2,0x03,0x29,0x34,0xfc,0xa3,0x03,0x79,0x5a,0x46,0x5a,0x02,0x9f,0xfd, 0x45,0x34,0x02,0xef,0xfc,0xf6,0x34,0x03,0x3e,0xfc,0xa6,0x44,0x6e,0xba,0x4c,0x8c,0x4c,0x8c,0x4c,0xf6,0xf6,0x4c,0x8c,0x4c,0x8c,0x4c,0xba,0x00,0xff,0xff,0xfe,0x90,0xff,0xf6,0x01,0x2d,0x02,0xda,0x00,0x27,0x03,0x30,0xfe,0x0e,0x00,0x00,0x00,0x06,0x03,0x29,0xaf,0x00,0xff,0xff,0xfe,0x90,0xff,0xf6,0x01,0x4d,0x02,0xda,0x00,0x27, 0x03,0x30,0xfe,0x0e,0x00,0x00,0x00,0x06,0x03,0x2b,0xce,0x00,0xff,0xff,0xfe,0x5c,0xff,0xfb,0x01,0xb8,0x02,0xda,0x00,0x27,0x03,0x30,0xfd,0xda,0x00,0x00,0x00,0x06,0x03,0x30,0xd3,0x00,0xff,0xff,0xfb,0xfa,0xff,0xfb,0x01,0xbd,0x02,0xda,0x00,0x27,0x03,0x30,0xfb,0x78,0x00,0x00,0x00,0x27,0x03,0x30,0xfd,0xa8,0x00,0x00,0x00,0x06, 0x03,0x30,0xd8,0x00,0x00,0x04,0xfe,0x52,0xff,0xfb,0x01,0xcc,0x02,0xda,0x00,0x14,0x00,0x18,0x00,0x1e,0x00,0x2c,0x00,0xa5,0xb5,0x1a,0x01,0x04,0x07,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x32,0x00,0x05,0x0c,0x01,0x06,0x00,0x05,0x06,0x67,0x00,0x00,0x00,0x03,0x07,0x00,0x03,0x69,0x00,0x07,0x0d,0x08,0x0b,0x03,0x04,0x0a,0x07, 0x04,0x67,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x0a,0x0a,0x09,0x61,0x0e,0x01,0x09,0x09,0x42,0x09,0x4e,0x1b,0x40,0x39,0x0b,0x01,0x04,0x07,0x08,0x07,0x04,0x08,0x80,0x00,0x05,0x0c,0x01,0x06,0x00,0x05,0x06,0x67,0x00,0x00,0x00,0x03,0x07,0x00,0x03,0x69,0x00,0x07,0x0d,0x01,0x08,0x0a,0x07,0x08,0x67,0x00,0x01, 0x01,0x02,0x5f,0x00,0x02,0x02,0x38,0x4d,0x00,0x0a,0x0a,0x09,0x61,0x0e,0x01,0x09,0x09,0x42,0x09,0x4e,0x59,0x40,0x25,0x20,0x1f,0x19,0x19,0x15,0x15,0x00,0x00,0x27,0x24,0x1f,0x2c,0x20,0x2b,0x19,0x1e,0x19,0x1e,0x1d,0x1c,0x15,0x18,0x15,0x18,0x17,0x16,0x00,0x14,0x00,0x14,0x16,0x21,0x24,0x21,0x0f,0x09,0x1a,0x2b,0x25,0x35,0x33, 0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x15,0x25,0x35,0x21,0x15,0x05,0x35,0x36,0x37,0x21,0x15,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfe,0x9e,0x32,0x40,0x4b,0x4b,0x41,0x7d,0x7d,0x46,0x67,0x39,0x30,0x55,0x38,0x01,0x1c,0x01,0xb8,0xfd,0xa8,0x27, 0x09,0x02,0x28,0xfc,0xef,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0xaa,0x47,0x3b,0x3b,0x47,0x55,0x35,0x60,0x42,0x39,0x5b,0x36,0x03,0x5f,0xe6,0x50,0x50,0xf0,0x24,0x13,0x19,0x50,0xd2,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0xff,0xff,0xfb,0x9c,0x00,0x67,0x02,0x0c,0x03,0x0c,0x00,0x27,0x03,0x34,0xfb,0x78, 0x00,0x00,0x00,0x27,0x03,0x34,0xfd,0xa8,0x00,0xa0,0x01,0x06,0x03,0x34,0xd8,0x00,0x00,0x08,0xb1,0x01,0x01,0xb0,0xa0,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0xfd,0xe5,0x00,0x41,0x02,0x12,0x02,0x6c,0x00,0x26,0x04,0x1b,0x0f,0x00,0x00,0x07,0x03,0x34,0xfd,0xc1,0x00,0x00,0xff,0xff,0xfd,0xcc,0xff,0x92,0x02,0x0d,0x03,0x3e,0x00,0x27, 0x03,0x34,0xfd,0xa8,0xff,0xb0,0x03,0x06,0x03,0x3d,0x00,0x00,0x00,0x09,0xb1,0x00,0x01,0xb8,0xff,0xb0,0xb0,0x35,0x2b,0x00,0x00,0x03,0xfd,0xcb,0xff,0x88,0x01,0xe5,0x03,0x48,0x00,0x27,0x00,0x2d,0x00,0x31,0x00,0x4c,0x40,0x49,0x1e,0x1d,0x02,0x08,0x4a,0x27,0x00,0x02,0x01,0x49,0x0b,0x09,0x02,0x07,0x0f,0x0d,0x02,0x06,0x05,0x07, 0x06,0x68,0x0e,0x0c,0x02,0x05,0x04,0x02,0x02,0x00,0x01,0x05,0x00,0x67,0x0a,0x01,0x08,0x08,0x38,0x4d,0x03,0x01,0x01,0x01,0x39,0x01,0x4e,0x31,0x30,0x2f,0x2e,0x2d,0x2a,0x29,0x28,0x1a,0x19,0x18,0x17,0x16,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x13,0x10,0x09,0x1f,0x2b,0x05,0x26,0x26,0x27,0x21,0x07,0x23,0x37,0x23,0x07, 0x23,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x36,0x36,0x37,0x15,0x0e,0x02,0x15,0x15,0x14,0x16,0x16,0x17,0x01,0x21,0x35,0x34,0x35,0x21,0x05,0x33,0x37,0x23,0x01,0xe5,0x81,0x99,0x0f,0xfe,0x92,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46, 0x27,0x01,0x38,0x10,0x99,0x7e,0x40,0x5f,0x33,0x33,0x5f,0x40,0xfd,0x74,0x01,0x60,0xfe,0xc2,0xfe,0xf8,0xa0,0x22,0xa0,0x78,0x1d,0xac,0x81,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x7d,0xa7,0x1c,0x57,0x0f,0x54,0x7d,0x4f,0xb4,0x4e,0x7e,0x54,0x0f,0x01,0x34,0xaf,0x03,0x02,0xb4,0xb4,0x00,0x00,0x00,0x03,0xfd,0xcb, 0xff,0x92,0x02,0x03,0x03,0x3e,0x00,0x33,0x00,0x3f,0x00,0x43,0x00,0xd3,0xb5,0x26,0x01,0x07,0x08,0x01,0x4c,0x4b,0xb0,0x0f,0x50,0x58,0x40,0x44,0x00,0x0f,0x13,0x12,0x07,0x0f,0x72,0x00,0x0d,0x00,0x0e,0x09,0x0d,0x0e,0x69,0x0c,0x0a,0x02,0x08,0x16,0x14,0x02,0x07,0x13,0x08,0x07,0x68,0x00,0x13,0x00,0x12,0x06,0x13,0x12,0x67,0x15, 0x11,0x02,0x06,0x05,0x03,0x02,0x01,0x02,0x06,0x01,0x67,0x00,0x10,0x17,0x01,0x00,0x10,0x00,0x65,0x0b,0x01,0x09,0x09,0x38,0x4d,0x04,0x01,0x02,0x02,0x39,0x02,0x4e,0x1b,0x40,0x45,0x00,0x0f,0x13,0x12,0x13,0x0f,0x12,0x80,0x00,0x0d,0x00,0x0e,0x09,0x0d,0x0e,0x69,0x0c,0x0a,0x02,0x08,0x16,0x14,0x02,0x07,0x13,0x08,0x07,0x68,0x00, 0x13,0x00,0x12,0x06,0x13,0x12,0x67,0x15,0x11,0x02,0x06,0x05,0x03,0x02,0x01,0x02,0x06,0x01,0x67,0x00,0x10,0x17,0x01,0x00,0x10,0x00,0x65,0x0b,0x01,0x09,0x09,0x38,0x4d,0x04,0x01,0x02,0x02,0x39,0x02,0x4e,0x59,0x40,0x35,0x01,0x00,0x43,0x42,0x41,0x40,0x3f,0x3e,0x3c,0x3a,0x39,0x37,0x35,0x34,0x32,0x30,0x29,0x28,0x23,0x21,0x20, 0x1e,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x33,0x01,0x33,0x18,0x09,0x16,0x2b,0x05,0x22,0x26,0x37,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x27,0x26,0x36, 0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x07,0x15,0x16,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x01,0x21,0x26,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x37,0x21,0x05,0x33,0x37,0x23,0x01,0xd6,0x58,0x65,0x04,0x09,0xfe,0x28,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27, 0x01,0xa0,0x09,0x05,0x66,0x58,0x2d,0x2d,0x2f,0x33,0x03,0x0a,0x04,0x3c,0x3b,0x3c,0x3a,0x03,0x0a,0x02,0x32,0x2f,0x2d,0xfd,0x56,0x01,0xcb,0x06,0x2c,0x2f,0x4b,0x4b,0x2e,0x2d,0x06,0xfe,0x57,0xfe,0xf8,0xa0,0x22,0xa0,0x6e,0x57,0x4f,0x9a,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x90,0x4f,0x57,0x50,0x2b,0x2b,0x9f, 0x37,0x4f,0x02,0x05,0x02,0x52,0x37,0xa9,0x2b,0x2b,0x50,0x01,0x81,0x1a,0x18,0x50,0x18,0x1a,0xb4,0xb4,0x00,0x03,0xfd,0xcb,0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x5e,0x40,0x5b,0x00,0x0c,0x00,0x0d,0x08,0x0c,0x0d,0x67,0x0b,0x09,0x02,0x07,0x13,0x11,0x02,0x06,0x05,0x07,0x06,0x68,0x12,0x10,0x02,0x05, 0x04,0x02,0x02,0x00,0x01,0x05,0x00,0x67,0x00,0x0e,0x14,0x01,0x0f,0x0e,0x0f,0x63,0x0a,0x01,0x08,0x08,0x38,0x4d,0x03,0x01,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x00,0x1f,0x00,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x15,0x09,0x1f,0x2b,0x17,0x11,0x21,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x11,0x33,0x15,0x23,0x11,0x33,0x15,0x01,0x21,0x35,0x21,0x05,0x33,0x37,0x23,0xcd,0xfe,0x81,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27, 0x46,0x27,0x01,0x47,0xf5,0x9b,0x9b,0xfd,0x97,0x01,0x74,0xfe,0xae,0xfe,0xf8,0xa0,0x22,0xa0,0x6e,0x01,0x40,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x01,0x36,0x50,0xfc,0xf4,0x50,0x01,0x81,0xb4,0xb4,0xb4,0x00,0x00,0x04,0xfd,0xcb,0x00,0x00,0x01,0x7c,0x02,0xda,0x00,0x1b,0x00,0x27,0x00,0x2b,0x00,0x37,0x00,0xab, 0x4b,0xb0,0x11,0x50,0x58,0x40,0x37,0x07,0x05,0x02,0x03,0x11,0x08,0x02,0x02,0x0e,0x03,0x02,0x68,0x00,0x0f,0x15,0x01,0x0e,0x01,0x0f,0x0e,0x69,0x0c,0x0a,0x02,0x00,0x12,0x01,0x00,0x57,0x13,0x10,0x09,0x03,0x01,0x16,0x01,0x12,0x0b,0x01,0x12,0x69,0x06,0x01,0x04,0x04,0x38,0x4d,0x14,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x1b,0x40, 0x38,0x07,0x05,0x02,0x03,0x11,0x08,0x02,0x02,0x0e,0x03,0x02,0x68,0x00,0x0f,0x15,0x01,0x0e,0x13,0x0f,0x0e,0x69,0x10,0x09,0x02,0x01,0x0c,0x0a,0x02,0x00,0x12,0x01,0x00,0x67,0x00,0x13,0x16,0x01,0x12,0x0b,0x13,0x12,0x69,0x06,0x01,0x04,0x04,0x38,0x4d,0x14,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x59,0x40,0x2e,0x2d,0x2c,0x1d,0x1c, 0x00,0x00,0x33,0x31,0x2c,0x37,0x2d,0x37,0x2b,0x2a,0x29,0x28,0x23,0x21,0x1c,0x27,0x1d,0x27,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33, 0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x33,0x37,0x23,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xfd,0xfb,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x02,0xeb,0x24,0x2c, 0x2c,0x24,0x24,0x2c,0x2c,0xfd,0x23,0xa0,0x22,0xa0,0x02,0x97,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0x01,0xae,0x2b,0x25,0x24,0x2c,0x2c,0x24,0x25,0x2b,0x9b,0xb4,0xfe,0xbb,0x2c,0x25,0x24,0x2b,0x2b,0x24,0x25,0x2c,0x00,0x00,0x04,0xfd,0xcb,0xff,0xfb,0x01,0x8b, 0x02,0xda,0x00,0x03,0x00,0x1f,0x00,0x23,0x00,0x31,0x00,0xaf,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x30,0x09,0x07,0x02,0x05,0x11,0x0a,0x02,0x04,0x03,0x05,0x04,0x68,0x10,0x0b,0x02,0x03,0x0e,0x0c,0x02,0x14,0x04,0x01,0x13,0x03,0x01,0x67,0x08,0x06,0x02,0x00,0x00,0x38,0x4d,0x00,0x13,0x13,0x0d,0x5f,0x16,0x12,0x15,0x0f,0x04,0x0d,0x0d, 0x39,0x0d,0x4e,0x1b,0x40,0x3b,0x14,0x01,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x09,0x07,0x02,0x05,0x11,0x0a,0x02,0x04,0x03,0x05,0x04,0x68,0x10,0x0b,0x02,0x03,0x0e,0x0c,0x02,0x02,0x13,0x03,0x02,0x67,0x08,0x06,0x02,0x00,0x00,0x38,0x4d,0x15,0x0f,0x02,0x0d,0x0d,0x39,0x4d,0x00,0x13,0x13,0x12,0x61,0x16,0x01,0x12,0x12,0x42,0x12, 0x4e,0x59,0x40,0x36,0x25,0x24,0x04,0x04,0x00,0x00,0x2c,0x29,0x24,0x31,0x25,0x30,0x23,0x22,0x21,0x20,0x04,0x1f,0x04,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x17,0x09,0x17,0x2b,0x37,0x13,0x33,0x03,0x05, 0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x13,0x33,0x37,0x23,0x01,0x22,0x26,0x37,0x36,0x36,0x33,0x33,0x32,0x16,0x07,0x06,0x06,0x23,0xc9,0x58,0x6a,0x70,0xfc,0xe0,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27, 0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0x02,0x23,0x1a,0x1b,0x05,0x05,0x28,0x1a,0x1e,0x1d,0x19,0x05,0x05,0x29,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xd7,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0x01,0x13,0xb4,0xfe,0x34,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00, 0x00,0x03,0xfd,0xcb,0xff,0xfb,0x02,0x08,0x02,0xe4,0x00,0x34,0x00,0x38,0x00,0x46,0x01,0x0e,0x4b,0xb0,0x18,0x50,0x58,0x40,0x3c,0x07,0x05,0x02,0x03,0x14,0x0d,0x02,0x02,0x0b,0x03,0x02,0x68,0x00,0x0b,0x00,0x09,0x01,0x0b,0x09,0x69,0x13,0x0e,0x02,0x01,0x11,0x0f,0x0a,0x03,0x00,0x16,0x01,0x00,0x67,0x00,0x0c,0x0c,0x04,0x5f,0x08, 0x06,0x02,0x04,0x04,0x38,0x4d,0x00,0x16,0x16,0x10,0x5f,0x18,0x15,0x17,0x12,0x04,0x10,0x10,0x39,0x10,0x4e,0x1b,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x40,0x07,0x05,0x02,0x03,0x14,0x0d,0x02,0x02,0x0b,0x03,0x02,0x68,0x00,0x0b,0x00,0x09,0x01,0x0b,0x09,0x69,0x13,0x0e,0x02,0x01,0x11,0x0f,0x0a,0x03,0x00,0x16,0x01,0x00,0x67,0x06,0x01, 0x04,0x04,0x38,0x4d,0x00,0x0c,0x0c,0x08,0x61,0x00,0x08,0x08,0x3e,0x4d,0x00,0x16,0x16,0x10,0x5f,0x18,0x15,0x17,0x12,0x04,0x10,0x10,0x39,0x10,0x4e,0x1b,0x40,0x4b,0x00,0x0a,0x00,0x16,0x00,0x0a,0x16,0x80,0x07,0x05,0x02,0x03,0x14,0x0d,0x02,0x02,0x0b,0x03,0x02,0x68,0x00,0x0b,0x00,0x09,0x01,0x0b,0x09,0x69,0x13,0x0e,0x02,0x01, 0x11,0x0f,0x02,0x00,0x0a,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x00,0x0c,0x0c,0x08,0x61,0x00,0x08,0x08,0x3e,0x4d,0x17,0x12,0x02,0x10,0x10,0x39,0x4d,0x00,0x16,0x16,0x15,0x61,0x18,0x01,0x15,0x15,0x42,0x15,0x4e,0x59,0x59,0x40,0x30,0x3a,0x39,0x00,0x00,0x41,0x3e,0x39,0x46,0x3a,0x45,0x38,0x37,0x36,0x35,0x00,0x34,0x00, 0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x27,0x25,0x21,0x1f,0x1e,0x1d,0x1c,0x1b,0x24,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x19,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x21,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x13,0x33,0x37,0x23,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfd,0xfb,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xa2,0x3d,0x6c,0x47,0x49,0x6c,0x3b,0x67,0x56,0x5a, 0x32,0x41,0x48,0x50,0x44,0x45,0x51,0xfe,0xf9,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0x02,0x7e,0x1d,0x24,0x24,0x1d,0x14,0x1d,0x24,0x24,0x1d,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x01,0x41,0x63,0x37,0x36,0x63,0x43,0x5b,0x76,0x06,0x64,0xaf,0x4a,0x42,0x41,0x4b,0x4b,0x41,0x41,0xb4,0x41,0xd2,0xd2,0xd2, 0x01,0x13,0xb4,0xfe,0x34,0x1f,0x1c,0x1b,0x22,0x22,0x1b,0x1b,0x20,0x00,0x00,0x00,0x00,0x04,0xfd,0xe9,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x2b,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x6b,0x40,0x68,0x0b,0x09,0x07,0x05,0x04,0x03,0x1b,0x19,0x17,0x0c,0x04,0x02,0x01,0x03,0x02,0x68,0x1a,0x18,0x16,0x0d,0x04,0x01,0x14,0x12,0x10,0x0e, 0x04,0x00,0x0f,0x01,0x00,0x67,0x0a,0x08,0x06,0x03,0x04,0x04,0x38,0x4d,0x1c,0x15,0x13,0x11,0x04,0x0f,0x0f,0x39,0x0f,0x4e,0x00,0x00,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x00,0x2b,0x00,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15, 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x1d,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x23,0x07,0x13,0x33,0x37,0x23,0x17, 0x33,0x37,0x23,0x05,0x33,0x37,0x23,0xfe,0x19,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xf0,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xf0,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0xc4,0xf0,0x22,0xf0,0x01,0x14,0xa0,0x22,0xa0,0xd2,0x41,0xb4, 0x41,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x01,0x13,0xb4,0xb4,0xb4,0xb4,0xb4,0x00,0x00,0x00,0x06,0xfb,0x91,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x8f,0x40,0x8c,0x0f,0x0d,0x0b,0x09,0x07,0x05,0x06,0x03,0x27,0x25, 0x23,0x21,0x1f,0x10,0x06,0x02,0x01,0x03,0x02,0x68,0x26,0x24,0x22,0x20,0x1e,0x11,0x06,0x01,0x1c,0x1a,0x18,0x16,0x14,0x12,0x06,0x00,0x13,0x01,0x00,0x67,0x0e,0x0c,0x0a,0x08,0x06,0x05,0x04,0x04,0x38,0x4d,0x28,0x1d,0x1b,0x19,0x17,0x15,0x06,0x13,0x13,0x39,0x13,0x4e,0x00,0x00,0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46, 0x45,0x44,0x43,0x42,0x41,0x40,0x3f,0x3e,0x3d,0x3c,0x00,0x3b,0x00,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x29, 0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x13, 0x33,0x37,0x23,0x17,0x21,0x37,0x21,0x05,0x33,0x37,0x23,0x17,0x21,0x37,0x21,0x05,0x33,0x37,0x23,0xfb,0xc1,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x01,0x0e,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x01,0x0e,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27, 0xfe,0xf2,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xfe,0xf2,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0xc4,0x01,0x0e,0x22,0xfe,0xf2,0x01,0x32,0xa0,0x22,0xa0,0xc4,0x01,0x0e,0x22,0xfe,0xf2,0x01,0x32,0xa0,0x22,0xa0,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2, 0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x01,0x13,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0x00,0x00,0x08,0xf9,0x39,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x4b,0x00,0x4f,0x00,0x53,0x00,0x57,0x00,0x5b,0x00,0x5f,0x00,0x63,0x00,0x67,0x00,0xb3,0x40,0xb0,0x13,0x11,0x0f,0x0d,0x0b,0x09,0x07,0x05,0x08,0x03,0x33,0x31,0x2f,0x2d, 0x2b,0x29,0x27,0x14,0x08,0x02,0x01,0x03,0x02,0x68,0x32,0x30,0x2e,0x2c,0x2a,0x28,0x26,0x15,0x08,0x01,0x24,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x08,0x00,0x17,0x01,0x00,0x67,0x12,0x10,0x0e,0x0c,0x0a,0x08,0x06,0x07,0x04,0x04,0x38,0x4d,0x34,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x08,0x17,0x17,0x39,0x17,0x4e,0x00,0x00,0x67,0x66, 0x65,0x64,0x63,0x62,0x61,0x60,0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,0x4f,0x4e,0x4d,0x4c,0x00,0x4b,0x00,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29, 0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x35,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x33, 0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x23,0x37,0x21,0x07,0x23,0x37,0x23,0x07,0x13,0x33,0x37,0x23,0x17,0x21,0x37,0x21,0x05,0x33,0x37,0x23,0x17,0x21,0x37,0x21,0x05, 0x33,0x37,0x23,0x17,0x21,0x37,0x21,0x05,0x33,0x37,0x23,0xf9,0x69,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x01,0x18,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x01,0x18,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x01,0x18,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46, 0x27,0xfe,0xe8,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xfe,0xe8,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0xfe,0xe8,0x27,0x46,0x27,0xa0,0x27,0x32,0xa0,0x22,0xa0,0xc4,0x01,0x18,0x22,0xfe,0xe8,0x01,0x3c,0xa0,0x22,0xa0,0xc4,0x01,0x18,0x22,0xfe,0xe8,0x01,0x3c,0xa0,0x22,0xa0,0xc4,0x01,0x18,0x22,0xfe,0xe8,0x01,0x3c,0xa0,0x22,0xa0,0xd2, 0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0xd2,0x01,0x13,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0xb4,0x00,0x04,0xfd,0xcb,0x00,0x00,0x02,0x08,0x02,0xda,0x00,0x1b, 0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0xdf,0x4b,0xb0,0x18,0x50,0x58,0x40,0x2c,0x0e,0x07,0x05,0x03,0x03,0x11,0x15,0x0f,0x08,0x04,0x02,0x01,0x03,0x02,0x68,0x12,0x10,0x09,0x03,0x01,0x16,0x13,0x0c,0x0a,0x04,0x00,0x0b,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x14,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x1b,0x4b,0xb0,0x2e,0x50, 0x58,0x40,0x36,0x00,0x0e,0x03,0x02,0x0e,0x57,0x07,0x05,0x02,0x03,0x11,0x15,0x0f,0x08,0x04,0x02,0x01,0x03,0x02,0x68,0x0c,0x0a,0x02,0x00,0x13,0x01,0x00,0x57,0x12,0x10,0x09,0x03,0x01,0x16,0x01,0x13,0x0b,0x01,0x13,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x14,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x1b,0x40,0x38,0x07,0x05,0x02,0x03, 0x11,0x08,0x02,0x02,0x0f,0x03,0x02,0x68,0x00,0x0e,0x15,0x01,0x0f,0x12,0x0e,0x0f,0x67,0x10,0x09,0x02,0x01,0x0c,0x0a,0x02,0x00,0x13,0x01,0x00,0x67,0x00,0x12,0x16,0x01,0x13,0x0b,0x12,0x13,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x14,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x59,0x59,0x40,0x2e,0x24,0x24,0x1c,0x1c,0x00,0x00,0x24,0x27, 0x24,0x27,0x26,0x25,0x23,0x22,0x21,0x20,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x17,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23, 0x37,0x23,0x07,0x01,0x35,0x21,0x15,0x05,0x33,0x37,0x23,0x05,0x35,0x21,0x15,0xfd,0xfb,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x02,0x0f,0x01,0xb8,0xfc,0x6b,0xa0,0x22,0xa0,0x01,0xbb,0x01,0xb8,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41, 0xd2,0xd2,0xd2,0x01,0xc2,0x50,0x50,0xaf,0xb4,0xff,0x50,0x50,0x00,0x02,0xfd,0xcb,0xff,0x9c,0x02,0x1c,0x02,0xda,0x00,0x1d,0x00,0x21,0x00,0x4f,0x40,0x4c,0x09,0x07,0x02,0x05,0x10,0x0a,0x02,0x04,0x03,0x05,0x04,0x68,0x0f,0x0b,0x02,0x03,0x0c,0x02,0x02,0x00,0x01,0x03,0x00,0x67,0x00,0x0d,0x11,0x01,0x0e,0x0d,0x0e,0x63,0x08,0x01, 0x06,0x06,0x38,0x4d,0x00,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x21,0x20,0x1f,0x1e,0x00,0x1d,0x00,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x09,0x1f,0x2b,0x05,0x13,0x23,0x07,0x23,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33, 0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x21,0x15,0x01,0x33,0x37,0x23,0xfe,0xce,0x3a,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x2c,0x02,0xfa,0xfc,0x57,0xa0,0x22,0xa0,0x64,0x01,0x36,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xeb,0x4b,0x01,0x77, 0xb4,0x00,0x00,0x00,0x00,0x02,0xfb,0x73,0xff,0x9c,0x01,0xdb,0x03,0x43,0x00,0x2f,0x00,0x33,0x00,0x59,0x40,0x56,0x2e,0x01,0x0d,0x01,0x4b,0x25,0x24,0x02,0x06,0x4a,0x09,0x07,0x02,0x05,0x10,0x0a,0x02,0x04,0x03,0x05,0x04,0x68,0x0f,0x0b,0x02,0x03,0x0c,0x02,0x02,0x00,0x01,0x03,0x00,0x67,0x00,0x0d,0x11,0x01,0x0e,0x0d,0x0e,0x63, 0x08,0x01,0x06,0x06,0x38,0x4d,0x00,0x01,0x01,0x39,0x01,0x4e,0x00,0x00,0x33,0x32,0x31,0x30,0x00,0x2f,0x00,0x2f,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x09,0x1f,0x2b,0x05,0x13,0x23,0x07,0x23,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33, 0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x21,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x37,0x15,0x0e,0x02,0x15,0x15,0x14,0x16,0x16,0x17,0x15,0x01,0x33,0x37,0x23,0xfc,0x76,0x3a,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x2c,0x04,0x73,0x42,0x4c,0x49,0x87,0x5c, 0x40,0x5e,0x34,0x32,0x5d,0x3f,0xfa,0x44,0xa0,0x22,0xa0,0x64,0x01,0x36,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xeb,0x2a,0x9f,0x63,0xaa,0x62,0x9f,0x6e,0x17,0x55,0x0f,0x55,0x7e,0x4f,0xaa,0x4c,0x7c,0x54,0x10,0x4b,0x01,0x77,0xb4,0x00,0x00,0x00,0xff,0xff,0xfd,0xf3,0xff,0x92,0x02,0x34,0x03,0x3e,0x00,0x27, 0x03,0x3d,0xfd,0xa8,0x00,0x00,0x03,0x07,0x03,0x34,0x00,0x00,0x00,0x82,0x00,0x08,0xb1,0x01,0x01,0xb0,0x82,0xb0,0x35,0x2b,0xff,0xff,0xfb,0x9b,0xff,0x92,0x02,0x34,0x03,0x3e,0x00,0x27,0x03,0x3d,0xfb,0x50,0x00,0x00,0x00,0x27,0x03,0x34,0xfd,0xa8,0x00,0x82,0x03,0x07,0x03,0x34,0x00,0x00,0x00,0x82,0x00,0x10,0xb1,0x01,0x01,0xb0, 0x82,0xb0,0x35,0x2b,0xb1,0x02,0x01,0xb0,0x82,0xb0,0x35,0x2b,0x00,0x01,0xfe,0x11,0xff,0x92,0x01,0xea,0x03,0x3e,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x00,0x01,0x00,0x85,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x00, 0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x05,0x01,0x33,0x03,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x03,0xfe,0x11,0x01,0x63,0x5f,0x80,0x02,0x97,0xfd,0x4a,0x3c,0x02,0xf2,0xfc,0xf0,0x6a,0x6e,0x03,0xac,0xfe,0xac,0x50,0xa0,0x50,0xfe,0xe8,0x00,0x01,0xfb,0xa0,0xff,0x92,0x01,0xea,0x03,0x3e,0x00,0x0b, 0x00,0x34,0x40,0x31,0x00,0x00,0x01,0x00,0x85,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x05,0x01,0x33,0x03,0x21,0x15,0x21,0x07,0x21,0x15, 0x21,0x03,0xfb,0xa0,0x01,0x63,0x5f,0x80,0x05,0x08,0xfa,0xd9,0x3c,0x05,0x63,0xfa,0x7f,0x6a,0x6e,0x03,0xac,0xfe,0xac,0x50,0xa0,0x50,0xfe,0xe8,0x00,0x01,0xfe,0x16,0xff,0x92,0x01,0xd6,0x03,0x3e,0x00,0x10,0x00,0x23,0x40,0x20,0x0f,0x0b,0x07,0x06,0x05,0x04,0x03,0x07,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x10,0x00,0x10,0x11,0x03,0x09,0x17,0x2b,0x05,0x01,0x33,0x07,0x01,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x01,0xfe,0x16,0x01,0x63,0x5f,0x41,0x02,0x3f,0xfe,0x52,0x01,0x36,0x13,0x21,0x08,0x09,0x21,0x12,0xfe,0x1d,0xfe,0xfa,0x6e,0x03,0xac,0xad,0xfe,0xeb,0x64,0xd7,0x5a,0x97,0x09,0x0b, 0x02,0x02,0x0b,0x09,0xe9,0xfd,0x4b,0x00,0xff,0xff,0xfe,0x3e,0xff,0x92,0x01,0xc2,0x03,0x3e,0x00,0x26,0x03,0x3d,0xb5,0x00,0x00,0x07,0x03,0x3d,0xfd,0xf3,0x00,0x00,0x00,0x02,0xfb,0xfa,0xff,0x92,0x01,0xd6,0x03,0x3e,0x00,0x0b,0x00,0x0f,0x00,0x3f,0x40,0x3c,0x06,0x01,0x00,0x01,0x00,0x85,0x09,0x07,0x08,0x03,0x05,0x04,0x05,0x86, 0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x0c,0x0c,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x05,0x01,0x33,0x03,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x03,0x21,0x01,0x33,0x01,0xfd, 0xbd,0x01,0x63,0x5f,0x80,0x02,0xd7,0xfd,0x0a,0x3c,0x03,0x32,0xfc,0xb0,0x6a,0xfd,0xde,0x01,0x63,0x5f,0xfe,0x9d,0x6e,0x03,0xac,0xfe,0xac,0x50,0xa0,0x50,0xfe,0xe8,0x03,0xac,0xfc,0x54,0xff,0xff,0xfc,0x13,0xff,0x92,0x01,0x95,0x03,0x3e,0x00,0x27,0x03,0x3d,0xfb,0xc8,0x00,0x00,0x00,0x27,0x03,0x3d,0xfd,0xa8,0x00,0x00,0x00,0x06, 0x03,0x3d,0x88,0x00,0x00,0x01,0xfe,0x66,0xff,0x92,0x01,0x9a,0x03,0x3e,0x00,0x08,0x00,0x1f,0x40,0x1c,0x06,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x03,0x02,0x02,0x01,0x01,0x76,0x00,0x00,0x00,0x08,0x00,0x08,0x11,0x11,0x04,0x09,0x18,0x2b,0x05,0x01,0x33,0x01,0x23,0x01,0x27,0x07,0x01,0xfe,0x66,0x01,0x63,0x6e,0x01, 0x63,0x5f,0xfe,0xdc,0x17,0x16,0xfe,0xdc,0x6e,0x03,0xac,0xfc,0x54,0x03,0x0a,0x44,0x44,0xfc,0xf6,0x00,0x00,0x01,0xfe,0x66,0xff,0x92,0x01,0x9a,0x03,0x3e,0x00,0x08,0x00,0x1f,0x40,0x1c,0x04,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x08,0x00,0x08,0x14,0x11,0x04,0x09,0x18, 0x2b,0x07,0x01,0x33,0x01,0x17,0x37,0x01,0x33,0x01,0x37,0xfe,0x9d,0x5f,0x01,0x24,0x17,0x16,0x01,0x24,0x60,0xfe,0x9d,0x6e,0x03,0xac,0xfc,0xf6,0x44,0x44,0x03,0x0a,0xfc,0x54,0x00,0x00,0x00,0x01,0xfc,0x22,0xff,0x9c,0x01,0x86,0x02,0xee,0x00,0x07,0x00,0x41,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0f,0x02,0x01,0x00,0x04,0x01,0x03,0x00, 0x03,0x63,0x00,0x01,0x01,0x38,0x01,0x4e,0x1b,0x40,0x18,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x59,0x40,0x0c,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x05,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0xfc,0x22,0x02,0x85,0x5a, 0x02,0x85,0x64,0x4b,0x03,0x07,0xfc,0xf9,0x4b,0x00,0x00,0x00,0x00,0x01,0xfd,0xe4,0xff,0x9c,0x02,0x1c,0xff,0xe7,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x05,0x35,0x21,0x15,0xfd,0xe4,0x04,0x38, 0x64,0x4b,0x4b,0x00,0x00,0x04,0xfe,0x5c,0xff,0xfb,0x01,0x90,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x19,0x00,0x4e,0x40,0x4b,0x00,0x02,0x09,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x0a,0x01,0x05,0x07,0x04,0x05,0x67,0x08,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x07,0x07,0x06,0x61,0x0b,0x01,0x06,0x06, 0x42,0x06,0x4e,0x0d,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x14,0x11,0x0c,0x19,0x0d,0x18,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x09,0x17,0x2b,0x25,0x03,0x33,0x03,0x37,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23, 0xfe,0x7e,0x0c,0x6a,0x0c,0xcc,0x01,0xf4,0xfe,0x0c,0x01,0xf4,0xfd,0x08,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xc3,0x50,0x50,0xf0,0x50,0x50,0xaf,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x06,0xfc,0x0e,0xff,0xfb,0x01,0x90,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13, 0x00,0x21,0x00,0x64,0x40,0x61,0x04,0x01,0x02,0x0e,0x05,0x0d,0x03,0x03,0x06,0x02,0x03,0x67,0x08,0x01,0x06,0x10,0x09,0x0f,0x03,0x07,0x0b,0x06,0x07,0x67,0x0c,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x0b,0x0b,0x0a,0x61,0x11,0x01,0x0a,0x0a,0x42,0x0a,0x4e,0x15,0x14,0x10,0x10,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00, 0x00,0x1c,0x19,0x14,0x21,0x15,0x20,0x10,0x13,0x10,0x13,0x12,0x11,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x12,0x09,0x17,0x2b,0x25,0x03,0x33,0x03,0x37,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x05,0x22,0x26,0x35, 0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfc,0x30,0x0c,0x6a,0x0c,0xcc,0x01,0xe5,0x78,0x01,0xe5,0xfb,0xbe,0x01,0xe5,0x78,0x01,0xe5,0xfa,0xba,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xc3,0x50,0x50,0x50,0x50,0xf0,0x50,0x50,0x50,0x50,0xaf,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00, 0x00,0x01,0x00,0x7d,0xff,0x8d,0x01,0xe5,0x03,0x2f,0x00,0x06,0x00,0x1f,0x40,0x1c,0x05,0x02,0x01,0x03,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x13,0x03,0x06,0x17,0x2b,0x05,0x03,0x35,0x13,0x33,0x01,0x01,0x01,0x79,0xfc,0xfc,0x66,0xfe,0xe8,0x01,0x1e,0x73,0x01,0x95, 0x7a,0x01,0x93,0xfe,0x2d,0xfe,0x31,0x00,0x00,0x02,0x00,0x64,0xff,0x92,0x02,0x2a,0x03,0x3e,0x00,0x06,0x00,0x0d,0x00,0x2d,0x40,0x2a,0x0c,0x09,0x08,0x05,0x02,0x01,0x06,0x01,0x00,0x01,0x4c,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x03,0x04,0x03,0x01,0x01,0x76,0x07,0x07,0x00,0x00,0x07,0x0d,0x07,0x0d,0x0b,0x0a,0x00,0x06,0x00,0x06, 0x13,0x06,0x06,0x17,0x2b,0x05,0x01,0x35,0x01,0x33,0x01,0x01,0x33,0x01,0x35,0x01,0x33,0x01,0x01,0x01,0x75,0xfe,0xef,0x01,0x11,0x37,0xfe,0xe2,0x01,0x1e,0x47,0xfe,0xef,0x01,0x11,0x37,0xfe,0xe2,0x01,0x1e,0x6e,0x01,0xbc,0x33,0x01,0xbd,0xfe,0x2a,0xfe,0x2a,0x01,0xbc,0x33,0x01,0xbd,0xfe,0x2a,0xfe,0x2a,0x00,0x00,0x02,0x00,0xa0, 0xff,0x92,0x01,0xef,0x03,0x3e,0x00,0x07,0x00,0x0b,0x00,0x2d,0x40,0x2a,0x00,0x01,0x06,0x05,0x02,0x02,0x03,0x01,0x02,0x67,0x04,0x01,0x03,0x00,0x00,0x03,0x57,0x04,0x01,0x03,0x03,0x00,0x5f,0x00,0x00,0x03,0x00,0x4f,0x08,0x08,0x08,0x0b,0x08,0x0b,0x12,0x11,0x11,0x11,0x10,0x07,0x06,0x1b,0x2b,0x05,0x21,0x11,0x21,0x15,0x23,0x11, 0x33,0x01,0x11,0x33,0x11,0x01,0xef,0xfe,0xb1,0x01,0x4f,0xaf,0xaf,0xfe,0xe3,0x3c,0x6e,0x03,0xac,0x2d,0xfc,0xae,0x03,0x52,0xfc,0xae,0x03,0x52,0x00,0x01,0x00,0x73,0xff,0x8d,0x01,0xdb,0x03,0x2f,0x00,0x06,0x00,0x1f,0x40,0x1c,0x05,0x04,0x01,0x03,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00, 0x00,0x06,0x00,0x06,0x12,0x03,0x06,0x17,0x2b,0x17,0x01,0x01,0x33,0x13,0x15,0x03,0x73,0x01,0x1e,0xfe,0xe8,0x66,0xfc,0xfc,0x73,0x01,0xcf,0x01,0xd3,0xfe,0x6d,0x7a,0xfe,0x6b,0x00,0x00,0x00,0x02,0x00,0x2e,0xff,0x92,0x01,0xf4,0x03,0x3e,0x00,0x06,0x00,0x0d,0x00,0x20,0x40,0x1d,0x0d,0x0c,0x09,0x06,0x05,0x02,0x06,0x00,0x01,0x01, 0x4c,0x03,0x01,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x00,0x76,0x12,0x13,0x12,0x10,0x04,0x06,0x1a,0x2b,0x17,0x23,0x01,0x01,0x33,0x01,0x15,0x01,0x23,0x01,0x01,0x33,0x01,0x15,0xe3,0x37,0x01,0x1e,0xfe,0xe2,0x37,0x01,0x11,0xfe,0x71,0x37,0x01,0x1e,0xfe,0xe2,0x37,0x01,0x11,0x6e,0x01,0xd6,0x01,0xd6,0xfe,0x43,0x33,0xfe,0x44,0x01, 0xd6,0x01,0xd6,0xfe,0x43,0x33,0x00,0x00,0x00,0x02,0x00,0x69,0xff,0x92,0x01,0xb8,0x03,0x3e,0x00,0x07,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x04,0x01,0x01,0x00,0x02,0x01,0x67,0x05,0x01,0x00,0x03,0x03,0x00,0x57,0x05,0x01,0x00,0x00,0x03,0x5f,0x06,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x0b,0x0a,0x09,0x08,0x00,0x07,0x00,0x07, 0x11,0x11,0x11,0x07,0x06,0x19,0x2b,0x17,0x35,0x33,0x11,0x23,0x35,0x21,0x11,0x03,0x23,0x11,0x33,0x69,0xaf,0xaf,0x01,0x4f,0x32,0x3c,0x3c,0x6e,0x2d,0x03,0x52,0x2d,0xfc,0x54,0x03,0x7f,0xfc,0xae,0x00,0x00,0xff,0xff,0x00,0xda,0x01,0x09,0x01,0x7e,0x01,0xab,0x03,0x07,0x03,0x29,0x00,0x00,0x01,0x13,0x00,0x09,0xb1,0x00,0x01,0xb8, 0x01,0x13,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0xcd,0xff,0x60,0x01,0x81,0x02,0x30,0x02,0x06,0x03,0x2c,0x00,0x00,0x00,0x03,0x00,0x5d,0xff,0x74,0x02,0x12,0x03,0x67,0x00,0x1c,0x00,0x25,0x00,0x2e,0x00,0x55,0x40,0x52,0x0b,0x01,0x09,0x01,0x11,0x01,0x0b,0x08,0x17,0x01,0x00,0x0a,0x03,0x4c,0x04,0x01,0x02,0x01,0x02,0x85, 0x0c,0x07,0x02,0x05,0x00,0x05,0x86,0x00,0x08,0x00,0x0b,0x0a,0x08,0x0b,0x67,0x00,0x09,0x09,0x01,0x5f,0x03,0x01,0x01,0x01,0x38,0x4d,0x00,0x0a,0x0a,0x00,0x5f,0x06,0x01,0x00,0x00,0x39,0x00,0x4e,0x00,0x00,0x2e,0x2c,0x28,0x26,0x25,0x23,0x1f,0x1d,0x00,0x1c,0x00,0x1c,0x11,0x1e,0x11,0x11,0x11,0x11,0x11,0x0d,0x09,0x1d,0x2b,0x17, 0x35,0x23,0x11,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x16,0x16,0x15,0x14,0x06,0x07,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x23,0x15,0x03,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0xb3,0x56,0x56,0x3c,0x46,0x3c,0x44,0x4c,0x3a,0x34,0x3b,0x44,0x55,0x4c,0x3c,0x46,0x3a,0x76, 0x3a,0x43,0x42,0x3a,0x77,0x7c,0x3f,0x49,0x49,0x3f,0x7c,0x8c,0x8c,0x02,0xda,0x8d,0x8d,0x8d,0x94,0x10,0x5e,0x48,0x3b,0x52,0x0e,0x10,0x60,0x47,0x50,0x68,0x0e,0x91,0x8c,0x8c,0x02,0x2f,0x3e,0x35,0x35,0x3e,0xfd,0xc8,0x43,0x3a,0x3c,0x4b,0x00,0x00,0x00,0x02,0x00,0x58,0xff,0x74,0x02,0x0b,0x02,0xb2,0x00,0x1b,0x00,0x23,0x00,0x3f, 0x40,0x3c,0x20,0x12,0x0b,0x08,0x04,0x01,0x00,0x1f,0x1a,0x13,0x01,0x04,0x03,0x02,0x02,0x4c,0x00,0x01,0x00,0x02,0x00,0x01,0x02,0x80,0x00,0x02,0x03,0x00,0x02,0x03,0x7e,0x00,0x00,0x01,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x1b,0x00,0x1b,0x17,0x14,0x19,0x05,0x09,0x19,0x2b,0x05, 0x35,0x26,0x26,0x35,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x17,0x23,0x26,0x26,0x27,0x11,0x36,0x36,0x37,0x33,0x06,0x06,0x07,0x15,0x03,0x14,0x16,0x17,0x11,0x06,0x06,0x15,0x01,0x11,0x55,0x64,0x64,0x55,0x3c,0x55,0x66,0x03,0x5a,0x03,0x34,0x2d,0x2d,0x34,0x03,0x5a,0x03,0x66,0x55,0x9b,0x33,0x2c,0x2c,0x33,0x8c,0x84,0x0a, 0x6d,0x59,0x96,0x59,0x6d,0x0a,0x84,0x83,0x07,0x64,0x52,0x2e,0x38,0x06,0xfe,0x6a,0x06,0x38,0x2e,0x52,0x64,0x07,0x83,0x01,0x54,0x34,0x41,0x0a,0x01,0x94,0x0a,0x40,0x34,0x00,0x00,0x00,0x00,0x02,0x00,0x2b,0x00,0x71,0x02,0x2e,0x02,0x7b,0x00,0x1c,0x00,0x2a,0x00,0x6a,0x40,0x20,0x15,0x13,0x0f,0x0d,0x04,0x03,0x01,0x1b,0x16,0x0c, 0x08,0x04,0x02,0x03,0x1c,0x07,0x05,0x01,0x04,0x00,0x02,0x03,0x4c,0x14,0x0e,0x02,0x01,0x4a,0x06,0x01,0x00,0x49,0x4b,0xb0,0x21,0x50,0x58,0x40,0x13,0x04,0x01,0x02,0x00,0x00,0x02,0x00,0x65,0x00,0x03,0x03,0x01,0x61,0x00,0x01,0x01,0x41,0x03,0x4e,0x1b,0x40,0x1a,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x04,0x01,0x02,0x00,0x00, 0x02,0x59,0x04,0x01,0x02,0x02,0x00,0x61,0x00,0x00,0x02,0x00,0x51,0x59,0x40,0x0d,0x1e,0x1d,0x24,0x22,0x1d,0x2a,0x1e,0x2a,0x2c,0x22,0x05,0x09,0x18,0x2b,0x25,0x27,0x06,0x23,0x22,0x27,0x07,0x27,0x37,0x26,0x35,0x34,0x37,0x27,0x37,0x17,0x36,0x33,0x32,0x17,0x37,0x17,0x07,0x16,0x15,0x14,0x06,0x07,0x17,0x25,0x32,0x36,0x35,0x34, 0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0xef,0x57,0x2e,0x3d,0x3e,0x2f,0x55,0x3e,0x53,0x21,0x22,0x56,0x3f,0x58,0x30,0x3b,0x3f,0x30,0x54,0x3d,0x53,0x1f,0x11,0x0f,0x55,0xfe,0xff,0x38,0x4a,0x4a,0x38,0x25,0x3c,0x23,0x23,0x3c,0x71,0x57,0x1d,0x1d,0x55,0x3e,0x54,0x31,0x3f,0x40,0x31,0x56,0x3f,0x58,0x1c,0x1f,0x54,0x3d, 0x53,0x32,0x3d,0x1f,0x39,0x18,0x55,0x40,0x4c,0x39,0x39,0x4c,0x23,0x3c,0x26,0x26,0x3c,0x23,0x00,0x00,0x00,0x03,0x00,0x48,0xff,0x74,0x02,0x10,0x03,0x66,0x00,0x23,0x00,0x2a,0x00,0x32,0x00,0x3a,0x40,0x37,0x28,0x1a,0x13,0x10,0x04,0x02,0x01,0x32,0x27,0x1b,0x09,0x04,0x00,0x02,0x2b,0x22,0x08,0x01,0x04,0x03,0x00,0x03,0x4c,0x00, 0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x02,0x85,0x00,0x00,0x03,0x00,0x85,0x04,0x01,0x03,0x03,0x76,0x00,0x00,0x00,0x23,0x00,0x23,0x14,0x1c,0x14,0x05,0x09,0x19,0x2b,0x05,0x35,0x26,0x26,0x27,0x33,0x14,0x16,0x17,0x11,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x17,0x23,0x34,0x26,0x27,0x15,0x17,0x16,0x16,0x15, 0x14,0x06,0x07,0x15,0x03,0x14,0x16,0x17,0x35,0x06,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x01,0x13,0x5e,0x6b,0x02,0x5a,0x3b,0x36,0x1b,0x4b,0x51,0x63,0x54,0x3c,0x53,0x64,0x01,0x5a,0x31,0x2d,0x28,0x49,0x50,0x69,0x58,0x99,0x30,0x2d,0x2c,0x31,0x99,0x31,0x36,0x2f,0x2c,0x0c,0x8c,0x83,0x08,0x69,0x56,0x31,0x3e,0x07,0x01, 0x06,0x08,0x17,0x6c,0x49,0x50,0x68,0x08,0x84,0x83,0x08,0x68,0x52,0x2f,0x3b,0x07,0xf8,0x0d,0x17,0x6e,0x4a,0x52,0x6c,0x09,0x83,0x02,0xb6,0x2d,0x42,0x0e,0xe5,0x07,0x36,0xfd,0xf3,0x08,0x3c,0x30,0x2c,0x41,0x0e,0x04,0x00,0x00,0x00,0x03,0x00,0x5a,0xff,0xb0,0x02,0x58,0x02,0xda,0x00,0x1c,0x00,0x2a,0x00,0x2e,0x00,0x9a,0xb6,0x19, 0x0a,0x02,0x08,0x09,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x2e,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x69,0x0d,0x01,0x08,0x00,0x00,0x08,0x59,0x00,0x0a,0x0e,0x01,0x0b,0x0a,0x0b,0x63,0x07,0x0c,0x02,0x00,0x00,0x04,0x5f,0x00,0x04,0x04,0x38,0x04,0x4e,0x1b,0x40,0x2f,0x05,0x01, 0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x09,0x08,0x01,0x09,0x69,0x0d,0x01,0x08,0x0c,0x01,0x00,0x0a,0x08,0x00,0x69,0x00,0x0a,0x0e,0x01,0x0b,0x0a,0x0b,0x63,0x00,0x07,0x07,0x04,0x5f,0x00,0x04,0x04,0x38,0x07,0x4e,0x59,0x40,0x27,0x2b,0x2b,0x1e,0x1d,0x01,0x00,0x2b,0x2e,0x2b,0x2e,0x2d,0x2c,0x25,0x23,0x1d,0x2a, 0x1e,0x2a,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x08,0x06,0x00,0x1c,0x01,0x1c,0x0f,0x09,0x16,0x2b,0x25,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x27,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x23,0x35,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15, 0x15,0x14,0x16,0x07,0x35,0x21,0x15,0x01,0x0c,0x52,0x60,0x5f,0x53,0x3e,0x4e,0x07,0x03,0x02,0x74,0x74,0x5a,0x5e,0x5e,0x5a,0x01,0x07,0x4e,0x20,0x38,0x3e,0x3e,0x38,0x39,0x3d,0x3d,0x97,0x01,0xa4,0x32,0x6e,0x5e,0x29,0x5f,0x6e,0x3e,0x35,0x7d,0x3c,0x4b,0x55,0x55,0x4b,0xfe,0x02,0x69,0x36,0x3d,0x4e,0x46,0x3e,0x1e,0x3e,0x46,0x44, 0x40,0x1e,0x40,0x44,0xd0,0x50,0x50,0x00,0x00,0x01,0x00,0x13,0xff,0xf6,0x02,0x0a,0x02,0xe4,0x00,0x2b,0x00,0x60,0x40,0x5d,0x00,0x06,0x07,0x04,0x07,0x06,0x04,0x80,0x00,0x0d,0x01,0x0c,0x01,0x0d,0x0c,0x80,0x08,0x01,0x04,0x09,0x01,0x03,0x02,0x04,0x03,0x67,0x0a,0x01,0x02,0x0b,0x01,0x01,0x0d,0x02,0x01,0x67,0x00,0x07,0x07,0x05, 0x61,0x00,0x05,0x05,0x3e,0x4d,0x00,0x0c,0x0c,0x00,0x61,0x0e,0x01,0x00,0x00,0x3f,0x00,0x4e,0x01,0x00,0x29,0x28,0x26,0x24,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x17,0x15,0x13,0x12,0x10,0x0e,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x2b,0x01,0x2b,0x0f,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x23,0x35,0x33,0x35,0x23, 0x35,0x33,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x01,0x34,0x64,0x74,0x49,0x49,0x49,0x49,0x74,0x64,0x62,0x74,0x5a,0x41,0x3b,0x3b,0x43,0xad,0xad,0xad,0xad,0x43,0x3b,0x3b,0x41,0x5a,0x74,0x0a,0x70,0x62, 0x2d,0x41,0x64,0x41,0x37,0x62,0x70,0x71,0x61,0x3e,0x43,0x43,0x3e,0x37,0x41,0x64,0x41,0x2d,0x3e,0x43,0x43,0x3e,0x61,0x71,0x00,0x01,0x00,0x00,0xff,0x4c,0x02,0x17,0x02,0xda,0x00,0x1a,0x00,0x33,0x40,0x30,0x05,0x01,0x02,0x06,0x01,0x01,0x00,0x02,0x01,0x67,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x03,0x38,0x4d,0x00,0x00,0x00,0x07, 0x5f,0x08,0x01,0x07,0x07,0x3d,0x07,0x4e,0x00,0x00,0x00,0x1a,0x00,0x19,0x11,0x12,0x21,0x23,0x11,0x13,0x21,0x09,0x09,0x1d,0x2b,0x15,0x35,0x33,0x32,0x36,0x35,0x11,0x23,0x35,0x33,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x15,0x33,0x15,0x23,0x11,0x14,0x06,0x23,0x69,0x35,0x3e,0xa0,0xa0,0x51,0x49,0xa1,0xa1,0x40,0xe1,0xe1, 0x70,0x5d,0xb4,0x52,0x3d,0x34,0x01,0x2a,0x52,0xc4,0x42,0x49,0x50,0x3c,0xc3,0x52,0xfe,0xd6,0x58,0x6b,0x00,0x02,0x00,0x32,0xff,0xf6,0x02,0x26,0x02,0xe4,0x00,0x19,0x00,0x31,0x00,0x5a,0x40,0x57,0x00,0x02,0x01,0x00,0x01,0x02,0x00,0x80,0x00,0x09,0x07,0x08,0x07,0x09,0x08,0x80,0x04,0x01,0x00,0x0c,0x01,0x05,0x06,0x00,0x05,0x67, 0x00,0x06,0x0d,0x0b,0x02,0x07,0x09,0x06,0x07,0x67,0x00,0x01,0x01,0x03,0x61,0x00,0x03,0x03,0x3e,0x4d,0x00,0x08,0x08,0x0a,0x61,0x00,0x0a,0x0a,0x3f,0x0a,0x4e,0x1a,0x1a,0x00,0x00,0x1a,0x31,0x1a,0x31,0x2d,0x2b,0x29,0x28,0x26,0x24,0x1e,0x1d,0x1c,0x1b,0x00,0x19,0x00,0x19,0x16,0x22,0x12,0x26,0x11,0x0e,0x09,0x1b,0x2b,0x13,0x35, 0x21,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x33,0x15,0x05,0x35,0x21,0x15,0x21,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x37,0x32,0x01,0x17,0x25,0x15,0x1c,0x38,0x31,0x38,0x41,0x59,0x02,0x6e,0x61,0x59,0x69, 0x25,0x1e,0x09,0x7b,0xfe,0x0c,0x01,0xf4,0xfe,0xd2,0x10,0x16,0x1b,0x3b,0x31,0x38,0x44,0x59,0x01,0x72,0x61,0x59,0x6c,0x33,0x01,0x8e,0x46,0x20,0x12,0x2b,0x18,0x26,0x27,0x35,0x31,0x55,0x5f,0x4e,0x48,0x22,0x35,0x1b,0x08,0x46,0x92,0x46,0x46,0x0c,0x10,0x2d,0x18,0x25,0x32,0x3f,0x31,0x55,0x69,0x58,0x48,0x3b,0x2b,0x00,0x00,0x00, 0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x18,0x00,0x21,0x00,0x3d,0x40,0x3a,0x09,0x01,0x03,0x05,0x01,0x02,0x01,0x03,0x02,0x67,0x06,0x01,0x01,0x07,0x01,0x00,0x08,0x01,0x00,0x67,0x00,0x0a,0x0a,0x04,0x5f,0x00,0x04,0x04,0x38,0x4d,0x0b,0x01,0x08,0x08,0x39,0x08,0x4e,0x00,0x00,0x21,0x1f,0x1b,0x19,0x00,0x18,0x00, 0x18,0x11,0x11,0x26,0x21,0x11,0x11,0x11,0x11,0x0c,0x09,0x1e,0x2b,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x15,0x33,0x15,0x23,0x15,0x11,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x6e,0x50,0x50,0x50,0x50,0xdf,0x42,0x61,0x36,0x36,0x61,0x42,0x85,0xe6,0xe6,0x85,0x39, 0x43,0x43,0x39,0x85,0x9b,0x50,0x55,0x50,0x01,0x4a,0x33,0x5c,0x3e,0x3d,0x5d,0x33,0x55,0x50,0x9b,0x01,0x90,0x44,0x39,0x39,0x44,0x00,0x00,0x00,0x00,0x01,0x00,0x4b,0x00,0x00,0x02,0x17,0x02,0xe4,0x00,0x2a,0x00,0x42,0x40,0x3f,0x01,0x01,0x07,0x00,0x01,0x4c,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x05,0x01,0x01,0x06,0x01,0x00, 0x07,0x01,0x00,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x07,0x07,0x08,0x5f,0x09,0x01,0x08,0x08,0x39,0x08,0x4e,0x00,0x00,0x00,0x2a,0x00,0x2a,0x16,0x11,0x16,0x22,0x12,0x26,0x11,0x17,0x0a,0x09,0x1e,0x2b,0x33,0x35,0x3e,0x02,0x35,0x34,0x27,0x23,0x35,0x33,0x2e,0x02,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x23, 0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x16,0x17,0x33,0x15,0x23,0x16,0x15,0x14,0x06,0x06,0x07,0x21,0x15,0x4b,0x18,0x32,0x23,0x05,0x68,0x4b,0x0e,0x1e,0x14,0x74,0x62,0x63,0x73,0x01,0x5f,0x42,0x37,0x3a,0x40,0x18,0x22,0x0f,0xb9,0xa3,0x03,0x23,0x33,0x18,0x01,0x72,0x64,0x13,0x35,0x39,0x19,0x1b,0x18,0x50,0x1a,0x31,0x39,0x26, 0x55,0x64,0x65,0x59,0x32,0x3c,0x39,0x35,0x23,0x33,0x30,0x1f,0x50,0x14,0x16,0x2b,0x49,0x35,0x0e,0x50,0x00,0x01,0x00,0x2d,0x00,0x00,0x02,0x2b,0x02,0xda,0x00,0x17,0x00,0x36,0x40,0x33,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x10,0x03,0x00,0x01,0x4c,0x02,0x01,0x00,0x00,0x01,0x5f,0x00, 0x01,0x01,0x38,0x4d,0x04,0x01,0x03,0x03,0x39,0x03,0x4e,0x00,0x00,0x00,0x17,0x00,0x17,0x11,0x11,0x19,0x05,0x09,0x19,0x2b,0x21,0x35,0x07,0x35,0x37,0x35,0x07,0x35,0x37,0x35,0x23,0x35,0x21,0x15,0x23,0x15,0x37,0x15,0x07,0x15,0x37,0x15,0x07,0x15,0x01,0x00,0xb0,0xb0,0xb0,0xb0,0xd3,0x01,0xfe,0xd3,0xb0,0xb0,0xb0,0xb0,0xb7,0x30, 0x4b,0x30,0x64,0x30,0x4b,0x30,0xda,0x4f,0x4f,0xc2,0x30,0x4b,0x30,0x64,0x30,0x4b,0x30,0xcf,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x00,0x02,0x35,0x02,0xda,0x00,0x1c,0x00,0x3e,0x40,0x3b,0x0c,0x01,0x02,0x03,0x01,0x4c,0x05,0x01,0x02,0x06,0x01,0x01,0x00,0x02,0x01,0x68,0x07,0x01,0x00,0x0b,0x0a,0x02,0x08,0x09,0x00,0x08,0x67,0x04, 0x01,0x03,0x03,0x38,0x4d,0x00,0x09,0x09,0x39,0x09,0x4e,0x00,0x00,0x00,0x1c,0x00,0x1c,0x1b,0x1a,0x11,0x11,0x11,0x11,0x18,0x11,0x11,0x11,0x11,0x0c,0x09,0x1f,0x2b,0x37,0x35,0x33,0x35,0x23,0x35,0x33,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x3c,0xc3,0xc3, 0xa0,0xb9,0x60,0x8e,0x0c,0x0e,0x02,0x02,0x0f,0x0c,0x8e,0x5d,0xb9,0xa0,0xc3,0xc3,0xc3,0x5a,0x78,0x4b,0x4b,0x4b,0x01,0x81,0xfe,0xd4,0x19,0x23,0x08,0x08,0x23,0x19,0x01,0x2c,0xfe,0x7f,0x4b,0x4b,0x4b,0x78,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x58,0xff,0x4c,0x02,0x0b,0x02,0xda,0x00,0x21,0x00,0x42,0x40,0x3f,0x0b,0x08,0x02,0x02, 0x00,0x20,0x01,0x02,0x05,0x03,0x02,0x4c,0x00,0x01,0x02,0x04,0x02,0x01,0x04,0x80,0x00,0x04,0x03,0x02,0x04,0x03,0x7e,0x00,0x02,0x02,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x03,0x03,0x05,0x5f,0x06,0x01,0x05,0x05,0x3d,0x05,0x4e,0x00,0x00,0x00,0x21,0x00,0x21,0x12,0x25,0x22,0x14,0x19,0x07,0x09,0x1b,0x2b,0x05,0x35,0x26,0x26, 0x35,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x07,0x15,0x01,0x02,0x4e,0x5c,0x5c,0x4e,0x5a,0x4e,0x5e,0x03,0x5a,0x03,0x42,0x38,0x3b,0x47,0x47,0x3b,0x38,0x42,0x03,0x5a,0x03,0x5e,0x4e,0xb4,0xae,0x0d,0x6c,0x55,0x96,0x55,0x6c,0x0d, 0xae,0xad,0x0a,0x63,0x4e,0x35,0x39,0x43,0x3e,0x97,0x3e,0x44,0x3a,0x34,0x4e,0x63,0x0a,0xad,0x00,0x00,0x00,0x01,0x00,0x48,0xff,0x4c,0x02,0x10,0x03,0x84,0x00,0x2d,0x00,0x3a,0x40,0x37,0x2d,0x02,0x02,0x02,0x00,0x19,0x16,0x02,0x03,0x05,0x02,0x4c,0x00,0x01,0x02,0x04,0x02,0x01,0x04,0x80,0x00,0x04,0x05,0x02,0x04,0x05,0x7e,0x00, 0x00,0x00,0x02,0x01,0x00,0x02,0x69,0x00,0x05,0x05,0x03,0x5f,0x00,0x03,0x03,0x3d,0x03,0x4e,0x22,0x14,0x1d,0x22,0x14,0x10,0x06,0x09,0x1c,0x2b,0x01,0x33,0x15,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x26,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35, 0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x01,0x05,0x5a,0x47,0x56,0x5a,0x44,0x35,0x35,0x42,0x2b,0x27,0x72,0x49,0x51,0x5f,0x52,0x5a,0x57,0x66,0x5a,0x4e,0x40,0x3e,0x4a,0x2f,0x2c,0x6f,0x45,0x4f,0x5e,0x4d,0x03,0x84,0xa5,0x0f,0x65,0x48,0x32,0x3f,0x3f,0x32,0x28,0x39,0x0b,0x20,0x14,0x6f,0x4c,0x54,0x6e,0x0c,0xae,0xad, 0x0b,0x6c,0x58,0x3d,0x45,0x48,0x3a,0x2c,0x41,0x0c,0x1f,0x14,0x67,0x46,0x4e,0x68,0x0b,0x00,0x00,0x00,0x00,0x02,0x00,0x46,0x00,0xaa,0x02,0x12,0x02,0x39,0x00,0x1b,0x00,0x1f,0x00,0x86,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x30,0x00,0x02,0x00,0x04,0x01,0x02,0x72,0x08,0x01,0x05,0x01,0x03,0x04,0x05,0x72,0x00,0x00,0x00,0x04,0x01,0x00, 0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x09,0x01,0x07,0x06,0x07,0x4f,0x1b,0x40,0x32,0x00,0x02,0x00,0x04,0x00,0x02,0x04,0x80,0x08,0x01,0x05,0x01,0x03,0x01,0x05,0x03,0x80,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00, 0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x09,0x01,0x07,0x06,0x07,0x4f,0x59,0x40,0x16,0x1c,0x1c,0x00,0x00,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x00,0x1b,0x00,0x1b,0x24,0x23,0x12,0x24,0x23,0x0a,0x06,0x1b,0x2b,0x13,0x35,0x34,0x36,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22, 0x15,0x15,0x07,0x35,0x21,0x15,0x46,0x48,0x3a,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x01,0xcc,0x01,0x71,0x46,0x3b,0x47,0x1a,0x27,0x27,0x1a,0x37,0x46,0x46,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x37,0x46,0xc7,0x50,0x50,0x00,0x03,0x00,0x1d,0xff,0xf6,0x02,0x3b,0x02,0x30,0x00,0x0b, 0x00,0x17,0x00,0x23,0x00,0x3b,0x40,0x38,0x03,0x01,0x01,0x07,0x02,0x06,0x03,0x00,0x05,0x01,0x00,0x69,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x19,0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16, 0x2b,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x64,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x01,0x6f,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0xe9,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x01,0xb0, 0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfe,0x46,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x00,0x02,0x00,0x9e,0xff,0xc9,0x01,0xc6,0x02,0x5d,0x00,0x21,0x00,0x2f,0x00,0x08,0xb5,0x2c,0x25,0x0d,0x00,0x02,0x32,0x2b,0x17,0x35,0x36,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x37,0x26, 0x27,0x35,0x16,0x17,0x36,0x37,0x15,0x06,0x07,0x16,0x16,0x15,0x15,0x14,0x06,0x07,0x16,0x17,0x15,0x26,0x27,0x06,0x03,0x14,0x16,0x17,0x36,0x36,0x35,0x35,0x34,0x26,0x27,0x06,0x06,0x15,0xa8,0x34,0x29,0x38,0x2f,0x2f,0x38,0x29,0x34,0x50,0x3a,0x3a,0x50,0x34,0x29,0x38,0x2f,0x2f,0x38,0x29,0x34,0x50,0x3a,0x3a,0x28,0x2b,0x37,0x37, 0x2b,0x2b,0x37,0x37,0x2b,0x37,0x2d,0x0b,0x12,0x2d,0x7e,0x4b,0x14,0x4b,0x7e,0x2d,0x12,0x0b,0x2d,0x0e,0x1f,0x1f,0x0e,0x2d,0x0b,0x12,0x2d,0x7e,0x4b,0x14,0x4b,0x7e,0x2d,0x12,0x0b,0x2d,0x0e,0x1f,0x1f,0x01,0x32,0x43,0x71,0x28,0x28,0x71,0x43,0x14,0x43,0x71,0x28,0x28,0x71,0x43,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x32,0x02,0x58, 0x02,0x9b,0x00,0x05,0x00,0x08,0x00,0x0b,0x00,0x0a,0xb7,0x0b,0x09,0x07,0x06,0x01,0x00,0x03,0x32,0x2b,0x35,0x11,0x01,0x01,0x11,0x01,0x17,0x11,0x07,0x05,0x37,0x27,0x01,0x2c,0x01,0x2c,0xfe,0xd3,0xfb,0xd6,0xfe,0xe2,0xd5,0xd5,0x32,0x02,0x69,0xfe,0xef,0x01,0x11,0xfd,0x97,0x01,0x13,0xa0,0x01,0x86,0xc3,0xc5,0xc4,0xc2,0x00,0x00, 0xff,0xff,0x00,0xda,0x00,0xf0,0x01,0x7e,0x01,0x92,0x03,0x07,0x03,0x29,0x00,0x00,0x00,0xfa,0x00,0x08,0xb1,0x00,0x01,0xb0,0xfa,0xb0,0x35,0x2b,0x00,0x04,0x00,0x00,0x00,0x64,0x02,0x58,0x02,0x30,0x00,0x0b,0x00,0x0f,0x00,0x1b,0x00,0x1f,0x00,0x52,0x40,0x4f,0x00,0x02,0x09,0x01,0x03,0x00,0x02,0x03,0x67,0x00,0x01,0x08,0x01,0x00, 0x05,0x01,0x00,0x69,0x00,0x05,0x06,0x04,0x05,0x59,0x00,0x06,0x0b,0x01,0x07,0x04,0x06,0x07,0x67,0x00,0x05,0x05,0x04,0x61,0x0a,0x01,0x04,0x05,0x04,0x51,0x1c,0x1c,0x11,0x10,0x0c,0x0c,0x01,0x00,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x06, 0x16,0x2b,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x35,0x21,0x15,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x35,0x21,0x15,0x50,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0x86,0x01,0x5e,0xfd,0xf8,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0x86,0x01,0x5e,0x01,0x90,0x2b,0x25,0x24,0x2c,0x2c, 0x24,0x25,0x2b,0x0a,0x50,0x50,0xfe,0xca,0x2c,0x24,0x25,0x2b,0x2b,0x25,0x24,0x2c,0x46,0x50,0x50,0x00,0x00,0x01,0x00,0x9b,0xff,0xf6,0x01,0xc7,0x02,0x30,0x00,0x1f,0x00,0x6f,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x26,0x00,0x02,0x03,0x05,0x03,0x02,0x72,0x00,0x05,0x04,0x04,0x05,0x70,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04, 0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x06,0x01,0x00,0x04,0x00,0x52,0x1b,0x40,0x28,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x06,0x01,0x00,0x04,0x00,0x52,0x59,0x40,0x13,0x01,0x00,0x1c, 0x1b,0x18,0x16,0x11,0x0f,0x0c,0x0b,0x08,0x06,0x00,0x1f,0x01,0x1f,0x07,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x23,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x01,0x31,0x44,0x52,0x52,0x44,0x44,0x52,0x5a,0x21,0x1b,0x1b,0x21,0x21,0x1b, 0x1b,0x21,0x5a,0x52,0x0a,0x52,0x44,0x01,0x0e,0x44,0x52,0x52,0x44,0x28,0x32,0x1b,0x21,0x21,0x1b,0xfe,0xde,0x1b,0x21,0x21,0x1b,0x32,0x28,0x44,0x52,0x00,0x00,0x00,0x00,0x03,0x00,0x46,0x00,0x4c,0x02,0x12,0x02,0x9e,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0xa0,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x39,0x00,0x02,0x00,0x04,0x01,0x02,0x72, 0x0a,0x01,0x05,0x01,0x03,0x04,0x05,0x72,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00,0x06,0x0b,0x01,0x07,0x08,0x06,0x07,0x67,0x00,0x08,0x09,0x09,0x08,0x57,0x00,0x08,0x08,0x09,0x5f,0x0c,0x01,0x09,0x08,0x09,0x4f,0x1b,0x40,0x3b,0x00,0x02,0x00,0x04,0x00,0x02,0x04,0x80,0x0a,0x01,0x05, 0x01,0x03,0x01,0x05,0x03,0x80,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00,0x06,0x0b,0x01,0x07,0x08,0x06,0x07,0x67,0x00,0x08,0x09,0x09,0x08,0x57,0x00,0x08,0x08,0x09,0x5f,0x0c,0x01,0x09,0x08,0x09,0x4f,0x59,0x40,0x1e,0x20,0x20,0x1c,0x1c,0x00,0x00,0x20,0x23,0x20,0x23,0x22,0x21,0x1c, 0x1f,0x1c,0x1f,0x1e,0x1d,0x00,0x1b,0x00,0x1b,0x24,0x23,0x12,0x24,0x23,0x0d,0x06,0x1b,0x2b,0x13,0x35,0x34,0x36,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x15,0x15,0x07,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x46,0x48,0x3a,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25, 0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x01,0xcc,0xfe,0x34,0x01,0xcc,0x01,0xd6,0x46,0x3b,0x47,0x1a,0x27,0x27,0x1a,0x37,0x46,0x46,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x37,0x46,0xb2,0x4c,0x4c,0xd8,0x4c,0x4c,0x00,0x00,0x01,0x00,0x28,0xff,0x4c,0x02,0x30,0x02,0xda,0x00,0x0b,0x00,0x2c,0x40,0x29,0x03,0x01,0x01,0x00,0x01,0x85,0x04,0x02, 0x02,0x00,0x05,0x05,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x17,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x28,0x41,0x5a,0xd2,0x5a,0x41,0xb4,0x52,0x03,0x3c,0xfc,0xc4,0x03,0x3c,0xfc,0xc4,0x52,0x00, 0x00,0x01,0x00,0xff,0xfe,0xd4,0x01,0x59,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xff,0x5a,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0x1b,0x00,0x00,0x02,0x3c,0x02,0x2a,0x00,0x14, 0x00,0x13,0x40,0x10,0x14,0x10,0x0c,0x0b,0x00,0x05,0x00,0x4a,0x00,0x00,0x00,0x76,0x15,0x01,0x06,0x17,0x2b,0x01,0x0e,0x02,0x15,0x15,0x23,0x35,0x34,0x26,0x26,0x27,0x35,0x1e,0x02,0x17,0x3e,0x02,0x37,0x02,0x3c,0x44,0x66,0x37,0x64,0x36,0x63,0x43,0x4d,0x76,0x45,0x06,0x07,0x47,0x78,0x4d,0x01,0xd0,0x08,0x63,0xa2,0x69,0x5a,0x5a, 0x69,0xa2,0x63,0x08,0x5a,0x09,0x56,0x8f,0x5c,0x5c,0x8f,0x56,0x09,0x00,0x00,0x00,0x00,0x02,0x00,0x9f,0x00,0xbe,0x01,0xb9,0x01,0xd8,0x00,0x03,0x00,0x07,0x00,0x08,0xb5,0x06,0x04,0x02,0x00,0x02,0x32,0x2b,0x25,0x27,0x37,0x17,0x07,0x37,0x27,0x07,0x01,0x2c,0x8d,0x8d,0x8d,0x8d,0x54,0x54,0x54,0xbe,0x8d,0x8d,0x8d,0x54,0x54,0x54, 0x54,0x00,0x00,0x00,0x00,0x01,0x00,0xff,0x00,0x00,0x01,0x59,0x02,0xda,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x33,0x11,0x33,0x11,0xff,0x5a,0x02,0xda,0xfd,0x26,0x00,0xff,0xff,0x00,0x05,0x00,0x00,0x02,0x53,0x02,0xda,0x02,0x06, 0x03,0x20,0x00,0x00,0x00,0x01,0x00,0x7d,0x00,0x00,0x01,0xdb,0x02,0xda,0x00,0x0b,0x00,0x2c,0x40,0x29,0x0a,0x07,0x04,0x01,0x04,0x03,0x01,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x03,0x01,0x85,0x04,0x01,0x03,0x02,0x03,0x85,0x00,0x02,0x02,0x76,0x00,0x00,0x00,0x0b,0x00,0x0b,0x12,0x12,0x12,0x05,0x06,0x19,0x2b,0x37,0x37, 0x11,0x33,0x15,0x37,0x33,0x07,0x11,0x23,0x35,0x07,0x7d,0x82,0x5a,0x3c,0x46,0x82,0x5a,0x3c,0x8c,0xd1,0x01,0x7d,0xec,0x60,0xd1,0xfe,0x83,0xec,0x60,0x00,0x00,0x00,0x00,0x02,0x00,0x8c,0x00,0xaa,0x01,0xcc,0x01,0xea,0x00,0x0b,0x00,0x0f,0x00,0x30,0x40,0x2d,0x00,0x01,0x04,0x01,0x00,0x02,0x01,0x00,0x69,0x00,0x02,0x03,0x03,0x02, 0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f,0x0c,0x0c,0x01,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x35,0x21,0x15,0x01,0x2c,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0xc6,0x01,0x40,0x01,0x54,0x29,0x22, 0x22,0x29,0x29,0x22,0x22,0x29,0xaa,0x50,0x50,0x00,0x00,0x00,0x00,0x02,0x00,0x23,0x00,0x46,0x02,0x35,0x02,0x8a,0x00,0x15,0x00,0x29,0x00,0x48,0x40,0x45,0x00,0x01,0x00,0x02,0x05,0x01,0x02,0x67,0x00,0x05,0x00,0x06,0x07,0x05,0x06,0x67,0x00,0x07,0x09,0x01,0x04,0x03,0x07,0x04,0x67,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x03,0x03, 0x00,0x5f,0x08,0x01,0x00,0x03,0x00,0x4f,0x17,0x16,0x01,0x00,0x28,0x26,0x21,0x1f,0x1e,0x1c,0x16,0x29,0x17,0x29,0x14,0x12,0x0d,0x0b,0x0a,0x08,0x00,0x15,0x01,0x15,0x0a,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x21,0x15,0x27,0x22,0x26,0x35,0x35,0x34, 0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x33,0x15,0x01,0x18,0x4a,0x6f,0x3c,0x3c,0x6f,0x4a,0x01,0x1d,0xfe,0xe3,0x4b,0x5a,0x5a,0x4b,0x01,0x1d,0xf4,0x38,0x40,0x40,0x38,0xf4,0xea,0x17,0x1b,0x1b,0x17,0xea,0x46,0x3c,0x6c,0x48,0x64,0x49,0x6b,0x3c,0x46,0x5d,0x4d,0x64,0x4d,0x5d,0x46,0x9b,0x3d,0x36,0x28,0x36, 0x3d,0x46,0x1b,0x17,0x1e,0x17,0x1b,0x46,0x00,0x03,0xff,0xf6,0x00,0x19,0x02,0x62,0x02,0x83,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x41,0x40,0x3e,0x00,0x01,0x06,0x01,0x00,0x03,0x01,0x00,0x69,0x00,0x03,0x07,0x01,0x02,0x05,0x03,0x02,0x69,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x19, 0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x3d, 0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xd0,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xcf,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0x01,0xf7,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x00,0x00,0x01,0x00,0x23,0x00,0x46,0x02,0x3a,0x02,0x8a,0x00,0x1b, 0x00,0x37,0x40,0x34,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x00,0x05,0x00,0x00,0x05,0x57,0x00,0x05,0x05,0x00,0x5f,0x06,0x01,0x00,0x05,0x00,0x4f,0x01,0x00,0x1a,0x18,0x14,0x13,0x12,0x11,0x0d,0x0b,0x0a,0x08,0x00,0x1b,0x01,0x1b,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x35,0x34, 0x36,0x36,0x33,0x21,0x15,0x21,0x22,0x06,0x06,0x15,0x15,0x21,0x15,0x21,0x15,0x14,0x16,0x16,0x33,0x21,0x15,0x01,0x09,0x3e,0x69,0x3f,0x3f,0x69,0x3e,0x01,0x31,0xfe,0xcf,0x27,0x40,0x25,0x01,0xbd,0xfe,0x43,0x25,0x40,0x27,0x01,0x31,0x46,0x39,0x63,0x3e,0x90,0x3e,0x63,0x39,0x50,0x27,0x40,0x25,0x1e,0x50,0x1e,0x25,0x40,0x27,0x50, 0x00,0x01,0x00,0xa5,0x00,0xb6,0x01,0xbd,0x01,0xe2,0x00,0x17,0x00,0x37,0x40,0x34,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x00,0x05,0x00,0x00,0x05,0x57,0x00,0x05,0x05,0x00,0x5f,0x06,0x01,0x00,0x05,0x00,0x4f,0x01,0x00,0x16,0x14,0x11,0x10,0x0f,0x0e,0x0b,0x09,0x08,0x06,0x00,0x17,0x01, 0x17,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x15,0x33,0x15,0x23,0x15,0x14,0x16,0x33,0x33,0x15,0x01,0x1a,0x36,0x3f,0x3f,0x36,0xa3,0xa3,0x1f,0x24,0xe6,0xe6,0x24,0x1f,0xa3,0xb6,0x3f,0x36,0x42,0x36,0x3f,0x2d,0x24,0x1f,0x11,0x2a,0x11,0x1f,0x24,0x2d,0x00,0x00,0x03,0x00,0xe6, 0x00,0x19,0x01,0x73,0x02,0x83,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x41,0x40,0x3e,0x00,0x01,0x06,0x01,0x00,0x03,0x01,0x00,0x69,0x00,0x03,0x07,0x01,0x02,0x05,0x03,0x02,0x69,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x19,0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13, 0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2d,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0x20,0x20,0x27,0x27, 0x20,0x20,0x26,0x26,0x20,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0x01,0xf7,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x00,0x01,0x00,0x78,0x00,0x00,0x01,0xe0,0x01,0xfe,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x33,0x11,0x21,0x11,0x78,0x01,0x68,0x01,0xfe,0xfe,0x02,0x00,0x02,0x00,0x97,0x01,0xd2,0x01,0xc4,0x02,0xb2,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x2c,0x00,0x00,0x04,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01, 0x03,0x02,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x0b,0x17,0x2b,0x13,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x97,0x01,0x2d,0xfe,0xd3,0x01,0x2d,0x02,0x7a,0x38,0x38,0xa8,0x38,0x38,0x00,0x00,0x00,0x00,0x03,0x00,0x55,0x00,0x4c,0x02,0x03,0x02,0x48,0x00,0x03,0x00,0x07,0x00,0x0b, 0x00,0x40,0x40,0x3d,0x00,0x00,0x06,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x07,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x04,0x05,0x4f,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06, 0x17,0x2b,0x13,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x55,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0x52,0x01,0xae,0x01,0xfc,0x4c,0x4c,0xd8,0x4c,0x4c,0xd8,0x4c,0x4c,0x00,0x00,0x02,0x00,0x2d,0x00,0x73,0x02,0x2b,0x02,0x21,0x00,0x0f,0x00,0x1f,0x00,0x44,0x40,0x41,0x03,0x01,0x01,0x02,0x01,0x85,0x09,0x07,0x02,0x05, 0x06,0x05,0x86,0x00,0x02,0x08,0x01,0x00,0x04,0x02,0x00,0x67,0x00,0x04,0x06,0x06,0x04,0x57,0x00,0x04,0x04,0x06,0x5f,0x00,0x06,0x04,0x06,0x4f,0x10,0x10,0x01,0x00,0x10,0x1f,0x10,0x1f,0x1d,0x1a,0x18,0x17,0x15,0x12,0x0c,0x0b,0x09,0x06,0x04,0x03,0x00,0x0f,0x01,0x0e,0x0a,0x06,0x16,0x2b,0x13,0x22,0x26,0x35,0x33,0x14,0x16,0x33, 0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0x01,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x23,0x22,0x06,0x15,0xf5,0x5c,0x6c,0x5a,0x3b,0x33,0x6e,0x33,0x3b,0x5a,0x6c,0x5c,0xfe,0xca,0x6c,0x5c,0x6e,0x5c,0x6c,0x5a,0x3b,0x33,0x6e,0x33,0x3b,0x01,0x77,0x5c,0x4e,0x29,0x31,0x31,0x29,0x4e,0x5c,0xfe,0xfc,0x4e,0x5c,0x5c, 0x4e,0x29,0x31,0x31,0x29,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x69,0x02,0x58,0x02,0x2b,0x00,0x0b,0x00,0x0f,0x00,0x1b,0x00,0x41,0x40,0x3e,0x00,0x01,0x06,0x01,0x00,0x02,0x01,0x00,0x69,0x00,0x02,0x07,0x01,0x03,0x05,0x02,0x03,0x67,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x11, 0x10,0x0c,0x0c,0x01,0x00,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x35,0x21,0x15,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x08,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c, 0xfd,0xd4,0x01,0x5e,0xaa,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0x01,0x95,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0x73,0x50,0x50,0xb9,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0x00,0x00,0x00,0x01,0x00,0x50,0x00,0x00,0x01,0xf4,0x02,0xda,0x00,0x0b,0x00,0x32,0x40,0x2f,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x00,0x02,0x00,0x01, 0x00,0x02,0x01,0x67,0x00,0x00,0x05,0x05,0x00,0x57,0x00,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x33,0x35,0x21,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x50,0x01,0x4a,0xfe,0xd9,0x01,0x27,0xfe,0xb6,0x01,0xa4,0x52,0x01,0x02,0x52,0xe2, 0x52,0xfd,0x26,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x03,0x00,0x0c,0x00,0x2a,0x40,0x27,0x08,0x01,0x01,0x02,0x01,0x4c,0x00,0x01,0x02,0x01,0x86,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x03,0x01,0x02,0x00,0x02,0x4f,0x04,0x04,0x04,0x0c,0x04,0x0c,0x11,0x10,0x04,0x06,0x18,0x2b,0x13,0x21, 0x03,0x23,0x03,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x32,0x01,0xf4,0xbd,0x7b,0x4c,0x69,0x0d,0x11,0x04,0x04,0x13,0x0d,0x65,0x02,0xda,0xfd,0x26,0x02,0x8a,0xfe,0x5f,0x34,0x58,0x17,0x17,0x59,0x34,0x01,0xa0,0x00,0x00,0x00,0x00,0x02,0x00,0x50,0xff,0xfb,0x02,0x08,0x02,0xd0,0x00,0x0c,0x00,0x28,0x00,0x7d,0x40,0x0a,0x0c,0x0b, 0x0a,0x09,0x05,0x01,0x00,0x07,0x00,0x4a,0x4b,0xb0,0x11,0x50,0x58,0x40,0x27,0x00,0x02,0x00,0x04,0x01,0x02,0x72,0x06,0x01,0x05,0x01,0x03,0x04,0x05,0x72,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x05,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x62,0x00,0x03,0x01,0x03,0x52,0x1b,0x40,0x29,0x00,0x02,0x00,0x04,0x00,0x02,0x04, 0x80,0x06,0x01,0x05,0x01,0x03,0x01,0x05,0x03,0x80,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x05,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x62,0x00,0x03,0x01,0x03,0x52,0x59,0x40,0x13,0x0d,0x0d,0x0d,0x28,0x0d,0x28,0x25,0x23,0x20,0x1e,0x1b,0x1a,0x17,0x15,0x12,0x10,0x07,0x06,0x16,0x2b,0x37,0x35,0x25,0x36,0x36,0x37,0x26, 0x26,0x27,0x25,0x35,0x05,0x15,0x01,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x55,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0xca,0x01,0xae,0xfe,0x4d,0x47,0x3b,0x23,0x30,0x26,0x23,0x16,0x16,0x19,0x55,0x47,0x3b,0x23,0x31,0x25,0x24,0x15, 0x16,0x19,0xbe,0x57,0x98,0x09,0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0xfe,0x6b,0x14,0x3b,0x47,0x18,0x20,0x18,0x19,0x16,0x1c,0x14,0x3b,0x47,0x18,0x20,0x18,0x19,0x16,0x1c,0x00,0x00,0x01,0x00,0x23,0x00,0xb5,0x02,0x34,0x01,0xdf,0x00,0x25,0x00,0x2b,0x40,0x28,0x04,0x01,0x01,0x06,0x01,0x03,0x02,0x01,0x03,0x69,0x07,0x01, 0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x05,0x01,0x00,0x02,0x00,0x51,0x14,0x24,0x24,0x11,0x14,0x24,0x24,0x10,0x08,0x06,0x1e,0x2b,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x17,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x35,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x27,0x26,0x23,0x22,0x06,0x15, 0x14,0x16,0x33,0xb1,0x43,0x4b,0x4a,0x43,0x35,0x4d,0x13,0x16,0x16,0x36,0x20,0x22,0x23,0x20,0x44,0x4a,0x49,0x44,0x37,0x50,0x12,0x17,0x14,0x33,0x1f,0x23,0x23,0x20,0xb5,0x4e,0x46,0x47,0x4f,0x39,0x34,0x3d,0x3d,0x2b,0x28,0x26,0x2a,0x44,0x4d,0x47,0x47,0x4f,0x3a,0x34,0x42,0x38,0x2c,0x28,0x26,0x2a,0x00,0x00,0x00,0x01,0xff,0xb0, 0x00,0x71,0x02,0xa8,0x02,0x24,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x01,0x02,0x01,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x02,0x00,0x00,0x02,0x57,0x00,0x02,0x02,0x00,0x60,0x00,0x00,0x02,0x00,0x50,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x25,0x37,0x21,0x37,0x33,0x07,0x21,0x07,0x01,0x7f,0xbd,0xfd, 0x74,0xe9,0x40,0xbd,0x02,0x8c,0xe9,0x71,0xc3,0xf0,0xc3,0xf0,0x00,0x02,0x00,0x0a,0x00,0xeb,0x02,0x44,0x01,0xa9,0x00,0x0e,0x00,0x1a,0x00,0x34,0x40,0x31,0x00,0x02,0x00,0x05,0x03,0x02,0x05,0x69,0x00,0x03,0x00,0x00,0x04,0x03,0x00,0x67,0x06,0x01,0x04,0x01,0x01,0x04,0x59,0x06,0x01,0x04,0x04,0x01,0x61,0x00,0x01,0x04,0x01,0x51, 0x10,0x0f,0x16,0x14,0x0f,0x1a,0x10,0x1a,0x12,0x24,0x22,0x10,0x07,0x06,0x1a,0x2b,0x01,0x21,0x06,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x21,0x05,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x02,0x44,0xfe,0x82,0x07,0x33,0x23,0x28,0x37,0x37,0x28,0x23,0x33,0x07,0x01,0x7e,0xfe,0x25,0x18,0x1f,0x1f, 0x18,0x18,0x1f,0x1f,0x01,0x35,0x21,0x29,0x37,0x28,0x29,0x36,0x29,0x21,0x4c,0x1f,0x18,0x18,0x1f,0x1f,0x18,0x18,0x1f,0x00,0x00,0x01,0x00,0xff,0xff,0x92,0x01,0xe5,0x03,0xfc,0x00,0x0a,0x00,0x26,0x40,0x23,0x00,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x03,0x01,0x00,0x02,0x00,0x51,0x01,0x00, 0x09,0x07,0x05,0x04,0x00,0x0a,0x01,0x0a,0x04,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x33,0x11,0x14,0x33,0x33,0x15,0x01,0xb8,0x58,0x61,0x5a,0x5f,0x2d,0x6e,0x57,0x4f,0x03,0xc4,0xfc,0x3c,0x56,0x50,0x00,0x00,0x01,0x00,0x2d,0xfe,0xd4,0x01,0x59,0x03,0xfc,0x00,0x16,0x00,0x30,0x40,0x2d,0x12,0x01,0x00,0x01,0x01,0x4c,0x00,0x02, 0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x16,0x00,0x16,0x14,0x21,0x24,0x05,0x06,0x19,0x2b,0x13,0x11,0x34,0x26,0x26,0x23,0x23,0x35,0x33,0x32,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x07,0x16,0x16,0x15,0x11,0xff,0x0e,0x2b, 0x2b,0x6e,0x6e,0x2c,0x2a,0x0e,0x5a,0x33,0x32,0x31,0x34,0xfe,0xd4,0x02,0x08,0x24,0x2c,0x14,0x50,0x14,0x2d,0x23,0x02,0x08,0xfd,0xf8,0x39,0x4a,0x09,0x09,0x4a,0x39,0xfd,0xf8,0x00,0x00,0x00,0x01,0x00,0xff,0xfe,0xd4,0x01,0xe5,0x03,0x3e,0x00,0x0a,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x59, 0x00,0x00,0x00,0x01,0x61,0x00,0x01,0x00,0x01,0x51,0x00,0x00,0x00,0x0a,0x00,0x0a,0x21,0x23,0x04,0x06,0x18,0x2b,0x13,0x11,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x11,0xff,0x61,0x58,0x2d,0x2d,0x5f,0xfe,0xd4,0x03,0xc4,0x4f,0x57,0x50,0x56,0xfc,0x3c,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x32,0x02,0x58,0x02,0x9b,0x00,0x08, 0x00,0x0b,0x00,0x08,0xb5,0x0b,0x09,0x04,0x03,0x02,0x32,0x2b,0x25,0x07,0x25,0x01,0x11,0x01,0x25,0x17,0x05,0x05,0x37,0x27,0x02,0x58,0x22,0xfe,0xf5,0xfe,0xd5,0x01,0x2c,0x01,0x0b,0x21,0xfe,0xf8,0xfe,0xe2,0xd5,0xd5,0x75,0x26,0xf6,0xfe,0xed,0x02,0x69,0xfe,0xef,0xf2,0x24,0xf0,0xc5,0xc4,0xc2,0x00,0x00,0x00,0x00,0x01,0x00,0xff, 0xfe,0xd4,0x01,0x59,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xff,0x5a,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0xff,0xff,0x92,0x01,0xf4,0x03,0xfc,0x00,0x05,0x00,0x24,0x40,0x21, 0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x17,0x11,0x33,0x11,0x33,0x15,0xff,0x5a,0x9b,0x6e,0x04,0x6a,0xfb,0xe6,0x50,0x00,0x00,0x00,0x00,0x01,0x00,0xff,0xfe,0xd4,0x01,0xf4,0x03,0x3e,0x00,0x05, 0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x33,0x15,0x23,0x11,0xff,0xf5,0x9b,0xfe,0xd4,0x04,0x6a,0x50,0xfb,0xe6,0x00,0x00,0x00,0x02,0x00,0x41,0x00,0x00,0x02,0x17, 0x02,0xd0,0x00,0x0c,0x00,0x28,0x00,0x3b,0x40,0x38,0x0c,0x08,0x04,0x03,0x02,0x01,0x00,0x07,0x00,0x4a,0x00,0x01,0x04,0x03,0x01,0x59,0x02,0x01,0x00,0x00,0x04,0x03,0x00,0x04,0x69,0x00,0x01,0x01,0x03,0x62,0x06,0x05,0x02,0x03,0x01,0x03,0x52,0x0d,0x0d,0x0d,0x28,0x0d,0x28,0x25,0x23,0x20,0x1e,0x1b,0x1a,0x17,0x15,0x12,0x10,0x07, 0x06,0x16,0x2b,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x01,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x02,0x03,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x22,0x11,0x01,0x36,0xfe,0x3e,0x47,0x3b,0x23,0x39, 0x32,0x2c,0x16,0x16,0x19,0x55,0x47,0x3b,0x23,0x3a,0x31,0x2d,0x15,0x16,0x19,0xbe,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0xfe,0xe8,0x0f,0x3b,0x47,0x15,0x1c,0x15,0x19,0x16,0x17,0x0f,0x3b,0x47,0x15,0x1c,0x15,0x19,0x16,0x17,0x00,0x03,0xff,0xf6,0x01,0x08,0x02,0x62,0x01,0x94,0x00,0x0b,0x00,0x17,0x00,0x23, 0x00,0x37,0x40,0x34,0x05,0x03,0x02,0x01,0x00,0x00,0x01,0x59,0x05,0x03,0x02,0x01,0x01,0x00,0x61,0x08,0x04,0x07,0x02,0x06,0x05,0x00,0x01,0x00,0x51,0x19,0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x13,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x33,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x33,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x3d,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xd0,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xcf,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0x01,0x08,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x27, 0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x00,0x00,0x01,0x00,0x41,0xff,0xec,0x02,0x17,0x02,0x26,0x00,0x0f,0x00,0x2f,0x40,0x2c,0x00,0x04,0x03,0x04,0x86,0x00,0x00,0x07,0x01,0x01,0x02,0x00,0x01,0x67,0x06,0x01,0x02,0x03,0x03,0x02,0x57,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03, 0x4f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x08,0x06,0x1e,0x2b,0x13,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x35,0x23,0x46,0x01,0xcc,0xba,0xbf,0xbf,0x58,0xbf,0xbf,0xba,0x02,0x26,0x46,0xe1,0x50,0xc3,0xc3,0x50,0xe1,0x00,0x02,0x00,0x00,0x00,0x41,0x02,0x58,0x02,0x53,0x00,0x0c,0x00,0x19,0x00,0x08, 0xb5,0x17,0x0d,0x0a,0x00,0x02,0x32,0x2b,0x25,0x35,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x35,0x05,0x15,0x05,0x35,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x35,0x05,0x15,0x01,0x0e,0xd2,0x11,0x21,0x0a,0x0a,0x21,0x11,0xd2,0x01,0x4a,0xfd,0xa8,0xd2,0x11,0x21,0x0a,0x0a,0x21,0x11,0xd2,0x01,0x4a,0x41,0x53,0x96,0x0c,0x11,0x04, 0x04,0x14,0x0b,0x8f,0x56,0xe0,0x4e,0xe4,0x53,0x96,0x0c,0x11,0x04,0x04,0x14,0x0b,0x8f,0x56,0xe0,0x4e,0x00,0x02,0x00,0x00,0x00,0x41,0x02,0x58,0x02,0x53,0x00,0x0c,0x00,0x19,0x00,0x08,0xb5,0x10,0x0d,0x03,0x00,0x02,0x32,0x2b,0x25,0x25,0x35,0x25,0x15,0x07,0x06,0x06,0x07,0x16,0x16,0x17,0x17,0x05,0x25,0x35,0x25,0x15,0x07,0x06, 0x06,0x07,0x16,0x16,0x17,0x17,0x02,0x58,0xfe,0xb6,0x01,0x4a,0xd2,0x10,0x22,0x0a,0x0a,0x21,0x11,0xd2,0xfe,0xf2,0xfe,0xb6,0x01,0x4a,0xd2,0x10,0x22,0x0a,0x0a,0x21,0x11,0xd2,0x41,0xe4,0x4e,0xe0,0x56,0x8f,0x0b,0x14,0x04,0x04,0x11,0x0c,0x96,0x53,0xe4,0x4e,0xe0,0x56,0x8f,0x0b,0x14,0x04,0x04,0x11,0x0c,0x96,0x00,0x02,0x00,0x14, 0x00,0xeb,0x02,0x4e,0x01,0xa9,0x00,0x0e,0x00,0x1a,0x00,0x3a,0x40,0x37,0x00,0x01,0x00,0x05,0x00,0x01,0x05,0x69,0x00,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x07,0x01,0x04,0x02,0x02,0x04,0x59,0x07,0x01,0x04,0x04,0x02,0x61,0x00,0x02,0x04,0x02,0x51,0x10,0x0f,0x00,0x00,0x16,0x14,0x0f,0x1a,0x10,0x1a,0x00,0x0e,0x00,0x0e,0x24, 0x22,0x11,0x08,0x06,0x19,0x2b,0x13,0x35,0x21,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x14,0x01,0x7e,0x07,0x33,0x23,0x29,0x36,0x36,0x29,0x23,0x33,0x07,0x5d,0x18,0x1f,0x1f,0x18,0x18,0x1f,0x1f,0x01,0x35,0x2a,0x21,0x29,0x36,0x29,0x28,0x37,0x29, 0x21,0x22,0x1f,0x18,0x18,0x1f,0x1f,0x18,0x18,0x1f,0x00,0x00,0x00,0x02,0x00,0x46,0x00,0x00,0x02,0x12,0x02,0xda,0x00,0x13,0x00,0x1f,0x00,0x43,0x40,0x40,0x02,0x01,0x00,0x06,0x00,0x85,0x00,0x06,0x05,0x06,0x85,0x0a,0x01,0x09,0x04,0x01,0x04,0x09,0x01,0x80,0x07,0x01,0x05,0x08,0x01,0x04,0x09,0x05,0x04,0x67,0x00,0x01,0x03,0x03, 0x01,0x59,0x00,0x01,0x01,0x03,0x61,0x00,0x03,0x01,0x03,0x51,0x14,0x14,0x14,0x1f,0x14,0x1f,0x11,0x11,0x11,0x11,0x14,0x33,0x13,0x33,0x10,0x0b,0x06,0x1f,0x2b,0x13,0x33,0x11,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x17,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x46, 0x32,0x51,0x4a,0x32,0x4a,0x51,0x32,0x68,0x63,0x36,0x63,0x68,0xd2,0x78,0x78,0x28,0x78,0x78,0x02,0xda,0xfd,0xee,0x4a,0x51,0x51,0x4a,0x02,0x12,0xfd,0xee,0x61,0x67,0x67,0x61,0x73,0x79,0x26,0x79,0x79,0x26,0x79,0x00,0x00,0x00,0x00,0x03,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x2b,0x00,0x42,0x40,0x3f, 0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x00,0x05,0x08,0x01,0x04,0x02,0x05,0x04,0x69,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x02,0x00,0x51,0x21,0x20,0x11,0x10,0x01,0x00,0x27,0x25,0x20,0x2b,0x21,0x2b,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b, 0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a, 0x4a,0x76,0x44,0x44,0x76,0x4a,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0xcc,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d,0x02,0xda,0x00,0x07,0x00,0x20,0x40,0x1d, 0x03,0x01,0x01,0x02,0x01,0x86,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x00,0x02,0x4f,0x11,0x11,0x11,0x10,0x04,0x06,0x1a,0x2b,0x13,0x21,0x11,0x23,0x11,0x21,0x11,0x23,0x2b,0x02,0x02,0x5a,0xfe,0xb2,0x5a,0x02,0xda,0xfd,0x26,0x02,0x88,0xfd,0x78,0x00,0x00,0x00,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d, 0x02,0xda,0x00,0x07,0x00,0x26,0x40,0x23,0x02,0x01,0x00,0x01,0x00,0x85,0x00,0x01,0x03,0x03,0x01,0x57,0x00,0x01,0x01,0x03,0x5f,0x04,0x01,0x03,0x01,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x33,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x2b,0x5a,0x01,0x4e,0x5a,0x02,0xda,0xfd,0x78,0x02,0x88,0xfd, 0x26,0x00,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x50,0x02,0x2b,0x02,0xf0,0x00,0x03,0x00,0x10,0x00,0x3c,0x40,0x39,0x0c,0x01,0x03,0x02,0x01,0x4c,0x00,0x02,0x01,0x03,0x01,0x02,0x03,0x80,0x06,0x04,0x02,0x03,0x03,0x84,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x05,0x01,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04, 0x10,0x04,0x10,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x07,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0x01,0x13,0x33,0x13,0x23,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x2d,0x01,0xfe,0xfe,0x11,0xb3,0x7a,0xb3,0x5c,0x75,0x0c,0x11,0x04,0x04,0x12,0x0b,0x72,0x02,0xa5,0x4b,0x4b,0xfd,0xab,0x01,0xf4,0xfe,0x0c,0x01,0x40,0x20,0x3f, 0x10,0x10,0x3f,0x20,0xfe,0xc0,0x00,0x00,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d,0x02,0xda,0x00,0x13,0x00,0x26,0x40,0x23,0x04,0x03,0x02,0x01,0x02,0x01,0x86,0x00,0x00,0x02,0x02,0x00,0x59,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x00,0x02,0x51,0x00,0x00,0x00,0x13,0x00,0x13,0x33,0x13,0x33,0x05,0x06,0x19,0x2b,0x33,0x11,0x34,0x36, 0x33,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x23,0x22,0x06,0x15,0x11,0x2b,0x75,0x6f,0x3a,0x6f,0x75,0x5a,0x48,0x44,0x36,0x44,0x48,0x01,0xfe,0x6b,0x71,0x71,0x6b,0xfe,0x02,0x01,0xfe,0x44,0x48,0x48,0x44,0xfe,0x02,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d,0x02,0xda,0x00,0x13,0x00,0x20,0x40,0x1d,0x02,0x01,0x00,0x01, 0x00,0x85,0x00,0x01,0x03,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x61,0x00,0x03,0x01,0x03,0x51,0x33,0x13,0x33,0x10,0x04,0x06,0x1a,0x2b,0x13,0x33,0x11,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x2b,0x5a,0x48,0x44,0x36,0x44,0x48,0x5a,0x75,0x6f,0x3a,0x6f,0x75,0x02,0xda,0xfe,0x02,0x44, 0x48,0x48,0x44,0x01,0xfe,0xfe,0x02,0x6b,0x71,0x71,0x6b,0x00,0x00,0x01,0x00,0x46,0xff,0x9c,0x02,0x12,0x03,0x0c,0x00,0x2f,0x00,0xc6,0x40,0x0a,0x17,0x01,0x07,0x03,0x07,0x01,0x04,0x07,0x02,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x46,0x00,0x06,0x05,0x06,0x85,0x00,0x08,0x05,0x03,0x07,0x08,0x72,0x00,0x04,0x07,0x09,0x03,0x04,0x72, 0x00,0x0e,0x0d,0x0e,0x86,0x00,0x05,0x00,0x03,0x07,0x05,0x03,0x69,0x00,0x07,0x00,0x09,0x02,0x07,0x09,0x6a,0x0a,0x01,0x02,0x0b,0x01,0x01,0x00,0x02,0x01,0x67,0x0c,0x01,0x00,0x0d,0x0d,0x00,0x57,0x0c,0x01,0x00,0x00,0x0d,0x5f,0x10,0x0f,0x02,0x0d,0x00,0x0d,0x4f,0x1b,0x40,0x48,0x00,0x06,0x05,0x06,0x85,0x00,0x08,0x05,0x03,0x05, 0x08,0x03,0x80,0x00,0x04,0x07,0x09,0x07,0x04,0x09,0x80,0x00,0x0e,0x0d,0x0e,0x86,0x00,0x05,0x00,0x03,0x07,0x05,0x03,0x69,0x00,0x07,0x00,0x09,0x02,0x07,0x09,0x6a,0x0a,0x01,0x02,0x0b,0x01,0x01,0x00,0x02,0x01,0x67,0x0c,0x01,0x00,0x0d,0x0d,0x00,0x57,0x0c,0x01,0x00,0x00,0x0d,0x5f,0x10,0x0f,0x02,0x0d,0x00,0x0d,0x4f,0x59,0x40, 0x1e,0x00,0x00,0x00,0x2f,0x00,0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x23,0x21,0x12,0x11,0x14,0x23,0x12,0x24,0x11,0x11,0x11,0x11,0x06,0x1f,0x2b,0x37,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x17,0x37,0x33,0x07,0x36,0x35,0x35,0x33,0x15,0x14, 0x06,0x23,0x22,0x27,0x07,0x33,0x15,0x23,0x07,0x21,0x15,0x21,0x07,0x23,0x37,0x46,0x87,0x2f,0xb6,0xd0,0x29,0x1a,0x22,0x21,0x18,0x2f,0x55,0x47,0x3b,0x2b,0x35,0x23,0x0f,0x47,0x3f,0x51,0x2e,0x55,0x47,0x3b,0x0e,0x0c,0x21,0xbd,0xd7,0x2f,0x01,0x06,0xfe,0xe0,0x3b,0x3f,0x3b,0x4c,0x4c,0x8c,0x4c,0x7a,0x13,0x31,0x25,0x37,0x46,0x46, 0x3b,0x47,0x21,0x2f,0x13,0xd1,0xf0,0x01,0x36,0x46,0x46,0x3a,0x48,0x02,0x63,0x4c,0x8c,0x4c,0xb0,0xb0,0x00,0x02,0x00,0x23,0xff,0x92,0x02,0x3a,0x03,0x3e,0x00,0x1d,0x00,0x26,0x00,0xcc,0x40,0x0a,0x21,0x01,0x06,0x05,0x05,0x01,0x07,0x06,0x02,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x32,0x00,0x03,0x02,0x02,0x03,0x70,0x0c,0x01,0x0a, 0x00,0x00,0x0a,0x71,0x04,0x01,0x02,0x0b,0x01,0x05,0x06,0x02,0x05,0x68,0x00,0x06,0x00,0x07,0x01,0x06,0x07,0x67,0x08,0x01,0x01,0x00,0x00,0x01,0x57,0x08,0x01,0x01,0x01,0x00,0x5f,0x09,0x01,0x00,0x01,0x00,0x4f,0x1b,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x31,0x00,0x03,0x02,0x03,0x85,0x0c,0x01,0x0a,0x00,0x00,0x0a,0x71,0x04,0x01,0x02, 0x0b,0x01,0x05,0x06,0x02,0x05,0x68,0x00,0x06,0x00,0x07,0x01,0x06,0x07,0x67,0x08,0x01,0x01,0x00,0x00,0x01,0x57,0x08,0x01,0x01,0x01,0x00,0x5f,0x09,0x01,0x00,0x01,0x00,0x4f,0x1b,0x40,0x30,0x00,0x03,0x02,0x03,0x85,0x0c,0x01,0x0a,0x00,0x0a,0x86,0x04,0x01,0x02,0x0b,0x01,0x05,0x06,0x02,0x05,0x68,0x00,0x06,0x00,0x07,0x01,0x06, 0x07,0x67,0x08,0x01,0x01,0x00,0x00,0x01,0x57,0x08,0x01,0x01,0x01,0x00,0x5f,0x09,0x01,0x00,0x01,0x00,0x4f,0x59,0x59,0x40,0x16,0x00,0x00,0x24,0x22,0x00,0x1d,0x00,0x1d,0x1c,0x1b,0x11,0x11,0x11,0x11,0x11,0x11,0x28,0x11,0x11,0x0d,0x06,0x1f,0x2b,0x17,0x37,0x23,0x35,0x33,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x33,0x37, 0x33,0x07,0x33,0x15,0x23,0x03,0x33,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0x03,0x14,0x16,0x17,0x13,0x23,0x22,0x06,0x15,0x66,0x28,0x5c,0x7a,0x2d,0x53,0x63,0x3a,0x67,0x45,0x7f,0x37,0x46,0x37,0x6c,0x8a,0x74,0xfe,0xfe,0xe4,0x2c,0x01,0x48,0xfe,0x9a,0x28,0x2f,0x3f,0x3a,0x74,0x61,0x43,0x49,0x6e,0x6e,0x52,0x7a,0x0d,0x73,0x56,0x2c, 0x42,0x62,0x36,0x96,0x96,0x52,0xfe,0xc4,0x52,0x76,0x52,0x6e,0x02,0x12,0x3d,0x47,0x05,0x01,0x3b,0x48,0x42,0x00,0x00,0x00,0x00,0x02,0x00,0x1e,0xff,0x92,0x02,0x35,0x03,0x3e,0x00,0x21,0x00,0x29,0x00,0x91,0x40,0x0a,0x11,0x01,0x03,0x04,0x24,0x01,0x02,0x03,0x02,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x31,0x00,0x05,0x04,0x05,0x85, 0x00,0x09,0x08,0x08,0x09,0x71,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x0b,0x01,0x02,0x06,0x01,0x01,0x00,0x02,0x01,0x69,0x07,0x01,0x00,0x08,0x08,0x00,0x57,0x07,0x01,0x00,0x00,0x08,0x5f,0x0c,0x0a,0x02,0x08,0x00,0x08,0x4f,0x1b,0x40,0x30,0x00,0x05,0x04,0x05,0x85,0x00,0x09,0x08,0x09,0x86,0x00,0x04,0x00,0x03,0x02,0x04,0x03, 0x67,0x0b,0x01,0x02,0x06,0x01,0x01,0x00,0x02,0x01,0x69,0x07,0x01,0x00,0x08,0x08,0x00,0x57,0x07,0x01,0x00,0x00,0x08,0x5f,0x0c,0x0a,0x02,0x08,0x00,0x08,0x4f,0x59,0x40,0x16,0x00,0x00,0x27,0x25,0x00,0x21,0x00,0x21,0x20,0x1f,0x11,0x11,0x28,0x12,0x21,0x22,0x11,0x11,0x11,0x0d,0x06,0x1f,0x2b,0x33,0x35,0x33,0x37,0x23,0x35,0x33, 0x13,0x26,0x23,0x21,0x35,0x21,0x32,0x17,0x37,0x33,0x07,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x23,0x07,0x21,0x15,0x21,0x07,0x23,0x37,0x01,0x34,0x27,0x03,0x33,0x32,0x36,0x35,0x1e,0x8e,0x2c,0xba,0xd8,0x73,0x0c,0x0e,0xfe,0xcf,0x01,0x31,0x1d,0x1a,0x39,0x46,0x40,0x34,0x3c,0x3a,0x67,0x45,0x31,0x2c,0x01,0x34,0xfe,0xae,0x28, 0x46,0x28,0x01,0x4d,0x34,0x6b,0x13,0x43,0x49,0x52,0x76,0x52,0x01,0x3a,0x02,0x52,0x05,0x9b,0xb0,0x1a,0x63,0x43,0x2c,0x41,0x63,0x36,0x76,0x52,0x6e,0x6e,0x01,0xcc,0x4f,0x23,0xfe,0xdc,0x48,0x42,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x50,0x02,0x2b,0x02,0xf0,0x00,0x03,0x00,0x10,0x00,0x3c,0x40,0x39,0x0a,0x01,0x04,0x02,0x01,0x4c, 0x03,0x01,0x02,0x01,0x04,0x01,0x02,0x04,0x80,0x06,0x01,0x04,0x04,0x84,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x05,0x01,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x10,0x04,0x10,0x0f,0x0e,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x07,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0x01,0x03,0x33,0x13,0x16,0x16,0x17,0x36, 0x36,0x37,0x13,0x33,0x03,0x2d,0x01,0xfe,0xfe,0xc4,0xb3,0x5c,0x75,0x0c,0x11,0x04,0x04,0x12,0x0b,0x72,0x5b,0xb3,0x02,0xa5,0x4b,0x4b,0xfd,0xab,0x01,0xf4,0xfe,0xc0,0x20,0x3e,0x11,0x11,0x3e,0x20,0x01,0x40,0xfe,0x0c,0x00,0x00,0x00,0x03,0x00,0x55,0x00,0x00,0x02,0x03,0x02,0xd0,0x00,0x03,0x00,0x0c,0x00,0x10,0x00,0x28,0x40,0x25, 0x09,0x05,0x04,0x03,0x02,0x01,0x00,0x07,0x00,0x4a,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x0d,0x0d,0x0d,0x10,0x0d,0x10,0x1e,0x03,0x06,0x17,0x2b,0x25,0x25,0x35,0x25,0x03,0x11,0x07,0x06,0x06,0x07,0x16,0x16,0x17,0x03,0x35,0x21,0x15,0x02,0x03,0xfe,0x52,0x01,0xae,0x4c,0xea,0x13, 0x21,0x08,0x09,0x22,0x11,0x78,0x01,0xae,0xbe,0xd7,0x64,0xd7,0xfe,0x6f,0x01,0x13,0x72,0x09,0x0c,0x02,0x02,0x0e,0x08,0xfe,0x4f,0x50,0x50,0x00,0x00,0x01,0x00,0x46,0xff,0xc4,0x02,0x12,0x03,0x0c,0x00,0x3f,0x00,0xe4,0x40,0x18,0x15,0x01,0x01,0x06,0x18,0x01,0x05,0x01,0x26,0x07,0x02,0x02,0x05,0x27,0x06,0x02,0x0c,0x09,0x37,0x01, 0x08,0x0c,0x05,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x4f,0x00,0x04,0x03,0x04,0x85,0x00,0x06,0x03,0x01,0x05,0x06,0x72,0x00,0x02,0x05,0x07,0x01,0x02,0x72,0x00,0x09,0x00,0x0c,0x08,0x09,0x72,0x0e,0x01,0x0d,0x08,0x0a,0x0c,0x0d,0x72,0x00,0x0b,0x0a,0x0b,0x86,0x00,0x03,0x00,0x01,0x05,0x03,0x01,0x69,0x00,0x05,0x00,0x07,0x00,0x05, 0x07,0x6a,0x00,0x00,0x00,0x0c,0x08,0x00,0x0c,0x69,0x00,0x08,0x0d,0x0a,0x08,0x59,0x00,0x08,0x08,0x0a,0x62,0x00,0x0a,0x08,0x0a,0x52,0x1b,0x40,0x53,0x00,0x04,0x03,0x04,0x85,0x00,0x06,0x03,0x01,0x03,0x06,0x01,0x80,0x00,0x02,0x05,0x07,0x05,0x02,0x07,0x80,0x00,0x09,0x00,0x0c,0x00,0x09,0x0c,0x80,0x0e,0x01,0x0d,0x08,0x0a,0x08, 0x0d,0x0a,0x80,0x00,0x0b,0x0a,0x0b,0x86,0x00,0x03,0x00,0x01,0x05,0x03,0x01,0x69,0x00,0x05,0x00,0x07,0x00,0x05,0x07,0x6a,0x00,0x00,0x00,0x0c,0x08,0x00,0x0c,0x69,0x00,0x08,0x0d,0x0a,0x08,0x59,0x00,0x08,0x08,0x0a,0x62,0x00,0x0a,0x08,0x0a,0x52,0x59,0x40,0x1a,0x00,0x00,0x00,0x3f,0x00,0x3f,0x3d,0x3b,0x39,0x38,0x34,0x32,0x2f, 0x2e,0x26,0x23,0x12,0x23,0x13,0x23,0x12,0x24,0x23,0x0f,0x06,0x1f,0x2b,0x37,0x35,0x34,0x36,0x33,0x32,0x17,0x37,0x26,0x26,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x13,0x33,0x03,0x16,0x16,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x07,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06, 0x23,0x22,0x26,0x26,0x27,0x07,0x23,0x13,0x26,0x23,0x22,0x15,0x15,0x46,0x48,0x3a,0x1a,0x16,0x25,0x15,0x23,0x1b,0x2f,0x55,0x48,0x3a,0x2c,0x36,0x12,0x65,0x3f,0x78,0x08,0x13,0x0b,0x2f,0x55,0x47,0x3b,0x14,0x21,0x0d,0x23,0x13,0x1d,0x1e,0x15,0x2f,0x55,0x47,0x3b,0x24,0x30,0x21,0x0e,0x56,0x3f,0x67,0x0a,0x0b,0x2f,0x6e,0x46,0x3b, 0x47,0x08,0x6a,0x1a,0x2e,0x37,0x46,0x46,0x3b,0x47,0x25,0x17,0x01,0x1d,0xfe,0xad,0x07,0x09,0x37,0x46,0x46,0x3a,0x48,0x09,0x07,0x61,0x13,0x29,0x1d,0x37,0x46,0x46,0x3a,0x48,0x18,0x25,0x12,0xf4,0x01,0x22,0x05,0x37,0x46,0x00,0x00,0x03,0x00,0x23,0xff,0xc4,0x02,0x3a,0x03,0x0c,0x00,0x1c,0x00,0x22,0x00,0x2a,0x00,0x92,0x40,0x0a, 0x10,0x01,0x03,0x04,0x20,0x01,0x02,0x03,0x02,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x31,0x00,0x05,0x04,0x05,0x85,0x00,0x07,0x06,0x06,0x07,0x71,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x09,0x01,0x02,0x0a,0x01,0x01,0x00,0x02,0x01,0x67,0x0b,0x01,0x00,0x06,0x06,0x00,0x57,0x0b,0x01,0x00,0x00,0x06,0x5f,0x0c,0x08,0x02,0x06,0x00, 0x06,0x4f,0x1b,0x40,0x30,0x00,0x05,0x04,0x05,0x85,0x00,0x07,0x06,0x07,0x86,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x09,0x01,0x02,0x0a,0x01,0x01,0x00,0x02,0x01,0x67,0x0b,0x01,0x00,0x06,0x06,0x00,0x57,0x0b,0x01,0x00,0x00,0x06,0x5f,0x0c,0x08,0x02,0x06,0x00,0x06,0x4f,0x59,0x40,0x17,0x00,0x00,0x27,0x25,0x24,0x23,0x22,0x21, 0x00,0x1c,0x00,0x1c,0x11,0x28,0x12,0x21,0x21,0x11,0x11,0x11,0x0d,0x06,0x1e,0x2b,0x37,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x23,0x21,0x35,0x21,0x32,0x17,0x37,0x33,0x07,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x23,0x07,0x23,0x37,0x01,0x34,0x26,0x27,0x07,0x33,0x15,0x23,0x07,0x33,0x32,0x36,0x36,0x35,0x23,0x9f,0x3c,0xdb,0xf8, 0x3c,0x03,0xfe,0xcf,0x01,0x31,0x0f,0x0f,0x2f,0x3f,0x34,0x3e,0x50,0x3f,0x68,0x3f,0x6f,0x2e,0x3f,0x2e,0x01,0x3a,0x2c,0x23,0x37,0x86,0xa3,0x3c,0x53,0x28,0x3f,0x25,0x46,0x50,0xaa,0x50,0xaa,0x50,0x02,0x84,0x92,0x19,0x6b,0x46,0x90,0x3e,0x63,0x39,0x82,0x82,0x01,0x68,0x28,0x45,0x11,0x9c,0x50,0xaa,0x27,0x40,0x25,0x00,0x00,0x00, 0x00,0x03,0x00,0x23,0xff,0xc4,0x02,0x3a,0x03,0x0c,0x00,0x1d,0x00,0x25,0x00,0x2b,0x00,0x90,0x40,0x0a,0x29,0x01,0x06,0x05,0x01,0x01,0x07,0x06,0x02,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x30,0x00,0x01,0x00,0x00,0x01,0x70,0x0c,0x01,0x08,0x07,0x08,0x86,0x02,0x01,0x00,0x0a,0x01,0x03,0x04,0x00,0x03,0x68,0x09,0x01,0x04,0x0b,0x01, 0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x00,0x07,0x06,0x07,0x4f,0x1b,0x40,0x2f,0x00,0x01,0x00,0x01,0x85,0x0c,0x01,0x08,0x07,0x08,0x86,0x02,0x01,0x00,0x0a,0x01,0x03,0x04,0x00,0x03,0x68,0x09,0x01,0x04,0x0b,0x01,0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06, 0x07,0x5f,0x00,0x07,0x06,0x07,0x4f,0x59,0x40,0x17,0x00,0x00,0x2b,0x2a,0x22,0x20,0x1f,0x1e,0x00,0x1d,0x00,0x1d,0x21,0x31,0x11,0x11,0x11,0x11,0x11,0x28,0x0d,0x06,0x1e,0x2b,0x17,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x32,0x33,0x21,0x15,0x21,0x22,0x27,0x07, 0x03,0x33,0x37,0x23,0x22,0x06,0x06,0x15,0x15,0x14,0x16,0x17,0x37,0x23,0x78,0x34,0x3c,0x4d,0x3f,0x69,0x3e,0x6a,0x2e,0x3f,0x2e,0x88,0xa4,0x3c,0xe0,0xfd,0x3c,0x04,0x04,0x01,0x31,0xfe,0xcf,0x12,0x11,0x2f,0x3a,0x9e,0x3c,0x4e,0x27,0x40,0x25,0x29,0x22,0x36,0x81,0x3c,0x94,0x19,0x6a,0x45,0x90,0x3e,0x63,0x39,0x82,0x82,0x50,0xaa, 0x50,0xaa,0x50,0x03,0x85,0x01,0xcc,0xaa,0x27,0x40,0x25,0x8c,0x27,0x43,0x12,0x9a,0x00,0x01,0x00,0x2d,0x00,0x00,0x02,0x2b,0x02,0x99,0x00,0x29,0x00,0x57,0x40,0x54,0x11,0x01,0x03,0x02,0x26,0x01,0x08,0x09,0x02,0x4c,0x00,0x04,0x02,0x04,0x85,0x05,0x01,0x02,0x03,0x02,0x85,0x0c,0x0b,0x02,0x08,0x09,0x0a,0x09,0x08,0x0a,0x80,0x00, 0x0a,0x0a,0x84,0x00,0x03,0x06,0x01,0x01,0x00,0x03,0x01,0x69,0x07,0x01,0x00,0x09,0x09,0x00,0x59,0x07,0x01,0x00,0x00,0x09,0x61,0x00,0x09,0x00,0x09,0x51,0x00,0x00,0x00,0x29,0x00,0x29,0x25,0x24,0x23,0x21,0x12,0x22,0x12,0x14,0x11,0x22,0x12,0x22,0x12,0x0d,0x06,0x1f,0x2b,0x37,0x34,0x36,0x33,0x33,0x37,0x23,0x22,0x26,0x35,0x33, 0x14,0x16,0x33,0x33,0x37,0x33,0x07,0x36,0x36,0x35,0x33,0x14,0x06,0x23,0x23,0x07,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x23,0x07,0x23,0x37,0x06,0x06,0x15,0x2d,0x6c,0x5c,0x04,0x21,0x25,0x5c,0x6c,0x5a,0x3b,0x33,0x42,0x4d,0x46,0x4c,0x27,0x2c,0x5a,0x6c,0x5c,0x03,0x21,0x24,0x5c,0x6c,0x5a,0x3b,0x33,0x42,0x4b,0x46,0x4b,0x28, 0x2c,0x73,0x4e,0x5c,0x5a,0x5c,0x4e,0x29,0x31,0xd2,0xd0,0x06,0x2e,0x24,0x4e,0x5c,0x5a,0x5c,0x4e,0x29,0x31,0xcd,0xcb,0x06,0x2e,0x24,0x00,0x00,0x00,0x02,0x00,0x55,0xff,0xba,0x02,0x03,0x02,0xda,0x00,0x0f,0x00,0x18,0x00,0x23,0x40,0x20,0x16,0x12,0x11,0x0f,0x0b,0x0a,0x09,0x06,0x05,0x04,0x03,0x01,0x00,0x0d,0x01,0x00,0x01,0x4c, 0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x01,0x76,0x15,0x17,0x02,0x06,0x18,0x2b,0x37,0x35,0x37,0x37,0x27,0x35,0x17,0x37,0x33,0x03,0x17,0x15,0x07,0x07,0x23,0x37,0x37,0x27,0x07,0x37,0x36,0x36,0x37,0x26,0x26,0x55,0x87,0x41,0xc8,0xe2,0x56,0x3f,0x5f,0x96,0xff,0x4d,0x3f,0x40,0xd3,0x38,0x2b,0x63,0x13,0x21,0x08,0x09,0x22,0x41,0x57, 0x42,0xbc,0x63,0x5a,0x71,0xf8,0xfe,0xed,0x4b,0x64,0x7f,0xdf,0xb8,0xee,0x1c,0x7d,0x31,0x09,0x0d,0x02,0x02,0x0e,0x00,0x00,0x00,0x02,0x00,0x55,0xff,0x92,0x02,0x03,0x03,0x0c,0x00,0x17,0x00,0x20,0x00,0x6d,0x40,0x12,0x1e,0x1a,0x19,0x0f,0x0e,0x0d,0x0a,0x09,0x08,0x07,0x05,0x04,0x03,0x0d,0x00,0x01,0x01,0x4c,0x4b,0xb0,0x0c,0x50, 0x58,0x40,0x1f,0x00,0x01,0x00,0x01,0x85,0x00,0x04,0x03,0x03,0x04,0x71,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x1b,0x40,0x1e,0x00,0x01,0x00,0x01,0x85,0x00,0x04,0x03,0x04,0x86,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03, 0x00,0x03,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x17,0x00,0x17,0x11,0x11,0x15,0x19,0x11,0x07,0x06,0x1b,0x2b,0x33,0x35,0x33,0x37,0x07,0x35,0x37,0x37,0x27,0x35,0x05,0x37,0x33,0x07,0x17,0x15,0x07,0x07,0x21,0x15,0x21,0x07,0x23,0x37,0x13,0x27,0x07,0x37,0x36,0x36,0x37,0x26,0x26,0x55,0x63,0x40,0xa3,0xc5,0x2d,0xf2,0x01,0x0c,0x40, 0x3f,0x49,0x6c,0xc0,0x4c,0x01,0x0c,0xfe,0xd9,0x25,0x3f,0x25,0xee,0x0e,0x18,0x26,0x13,0x21,0x08,0x09,0x22,0x52,0xbe,0x51,0x57,0x60,0x89,0x78,0x5a,0x86,0xc1,0xdc,0x36,0x64,0x60,0xe4,0x52,0x6e,0x6e,0x01,0xde,0x07,0x4a,0x13,0x09,0x0d,0x02,0x02,0x0e,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0xc4,0x02,0x03,0x02,0xd9,0x00,0x1b, 0x00,0xca,0x4b,0xb0,0x09,0x50,0x58,0x40,0x34,0x00,0x05,0x04,0x04,0x05,0x70,0x00,0x0c,0x0b,0x0b,0x0c,0x71,0x06,0x01,0x04,0x07,0x01,0x03,0x02,0x04,0x03,0x68,0x08,0x01,0x02,0x09,0x01,0x01,0x00,0x02,0x01,0x67,0x0a,0x01,0x00,0x0b,0x0b,0x00,0x57,0x0a,0x01,0x00,0x00,0x0b,0x5f,0x0e,0x0d,0x02,0x0b,0x00,0x0b,0x4f,0x1b,0x4b,0xb0, 0x0a,0x50,0x58,0x40,0x33,0x00,0x05,0x04,0x05,0x85,0x00,0x0c,0x0b,0x0b,0x0c,0x71,0x06,0x01,0x04,0x07,0x01,0x03,0x02,0x04,0x03,0x68,0x08,0x01,0x02,0x09,0x01,0x01,0x00,0x02,0x01,0x67,0x0a,0x01,0x00,0x0b,0x0b,0x00,0x57,0x0a,0x01,0x00,0x00,0x0b,0x5f,0x0e,0x0d,0x02,0x0b,0x00,0x0b,0x4f,0x1b,0x40,0x32,0x00,0x05,0x04,0x05,0x85, 0x00,0x0c,0x0b,0x0c,0x86,0x06,0x01,0x04,0x07,0x01,0x03,0x02,0x04,0x03,0x68,0x08,0x01,0x02,0x09,0x01,0x01,0x00,0x02,0x01,0x67,0x0a,0x01,0x00,0x0b,0x0b,0x00,0x57,0x0a,0x01,0x00,0x00,0x0b,0x5f,0x0e,0x0d,0x02,0x0b,0x00,0x0b,0x4f,0x59,0x59,0x40,0x1a,0x00,0x00,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x06,0x1f,0x2b,0x37,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x21,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x21,0x07,0x23,0x37,0x55,0x7c,0x2e,0xaa,0xc2,0x2e,0xf0,0x01,0x09,0x2f,0x3f,0x2f,0x66,0x7f,0x2e,0xad,0xc5,0x2e,0xf3,0xfe,0xf4,0x2c,0x3f,0x2c, 0x4c,0x4c,0x8c,0x4c,0x8c,0x4c,0x91,0x91,0x4c,0x8c,0x4c,0x8c,0x4c,0x88,0x88,0x00,0x00,0x02,0x00,0x55,0xff,0xba,0x02,0x03,0x02,0xda,0x00,0x0f,0x00,0x18,0x00,0x29,0x40,0x26,0x16,0x12,0x11,0x0e,0x0d,0x0c,0x0b,0x09,0x08,0x07,0x03,0x02,0x01,0x0d,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00, 0x00,0x0f,0x00,0x0f,0x15,0x03,0x06,0x17,0x2b,0x17,0x13,0x27,0x35,0x37,0x37,0x33,0x07,0x37,0x15,0x07,0x07,0x17,0x15,0x27,0x03,0x13,0x17,0x37,0x07,0x06,0x06,0x07,0x16,0x16,0x78,0x62,0x85,0xe7,0x51,0x3f,0x44,0x7b,0x9f,0x3a,0xd9,0xf3,0x59,0x16,0x27,0x24,0x4b,0x13,0x21,0x08,0x09,0x22,0x46,0x01,0x1b,0x43,0x64,0x73,0xeb,0xc5, 0x3e,0x57,0x4e,0xa8,0x6b,0x5a,0x7a,0xfe,0xff,0x01,0x7a,0x13,0x68,0x25,0x09,0x0d,0x02,0x02,0x0d,0x00,0x00,0x02,0x00,0x55,0xff,0x92,0x02,0x03,0x03,0x0c,0x00,0x17,0x00,0x20,0x00,0x6d,0x40,0x12,0x1e,0x1a,0x19,0x10,0x0f,0x0e,0x0d,0x0b,0x0a,0x09,0x05,0x04,0x03,0x0d,0x00,0x01,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x1f,0x00, 0x01,0x00,0x01,0x85,0x00,0x04,0x03,0x03,0x04,0x71,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x1b,0x40,0x1e,0x00,0x01,0x00,0x01,0x85,0x00,0x04,0x03,0x04,0x86,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x59, 0x40,0x0e,0x00,0x00,0x00,0x17,0x00,0x17,0x11,0x11,0x19,0x15,0x11,0x07,0x06,0x1b,0x2b,0x33,0x35,0x33,0x37,0x27,0x35,0x25,0x37,0x33,0x07,0x37,0x15,0x07,0x07,0x17,0x15,0x27,0x07,0x21,0x15,0x21,0x07,0x23,0x37,0x13,0x17,0x37,0x07,0x06,0x06,0x07,0x16,0x16,0x55,0x63,0x4e,0xb1,0x01,0x20,0x2c,0x3f,0x1f,0x42,0x64,0x49,0xad,0xc7, 0x45,0x01,0x0c,0xfe,0xd9,0x25,0x3f,0x25,0x30,0x53,0x33,0x86,0x13,0x21,0x08,0x09,0x22,0x52,0xea,0x59,0x64,0x90,0x83,0x5d,0x21,0x57,0x31,0xda,0x56,0x5a,0x63,0xcf,0x52,0x6e,0x6e,0x01,0xb1,0x29,0x9b,0x42,0x09,0x0d,0x02,0x02,0x0d,0x00,0x00,0x00,0x00,0x02,0x00,0x23,0xff,0x92,0x02,0x3a,0x03,0x3e,0x00,0x17,0x00,0x1b,0x00,0xca, 0x4b,0xb0,0x09,0x50,0x58,0x40,0x34,0x00,0x03,0x02,0x02,0x03,0x70,0x00,0x0a,0x09,0x09,0x0a,0x71,0x04,0x01,0x02,0x0d,0x01,0x05,0x06,0x02,0x05,0x68,0x0c,0x01,0x06,0x07,0x01,0x01,0x00,0x06,0x01,0x67,0x08,0x01,0x00,0x09,0x09,0x00,0x57,0x08,0x01,0x00,0x00,0x09,0x5f,0x0e,0x0b,0x02,0x09,0x00,0x09,0x4f,0x1b,0x4b,0xb0,0x0c,0x50, 0x58,0x40,0x33,0x00,0x03,0x02,0x03,0x85,0x00,0x0a,0x09,0x09,0x0a,0x71,0x04,0x01,0x02,0x0d,0x01,0x05,0x06,0x02,0x05,0x68,0x0c,0x01,0x06,0x07,0x01,0x01,0x00,0x06,0x01,0x67,0x08,0x01,0x00,0x09,0x09,0x00,0x57,0x08,0x01,0x00,0x00,0x09,0x5f,0x0e,0x0b,0x02,0x09,0x00,0x09,0x4f,0x1b,0x40,0x32,0x00,0x03,0x02,0x03,0x85,0x00,0x0a, 0x09,0x0a,0x86,0x04,0x01,0x02,0x0d,0x01,0x05,0x06,0x02,0x05,0x68,0x0c,0x01,0x06,0x07,0x01,0x01,0x00,0x06,0x01,0x67,0x08,0x01,0x00,0x09,0x09,0x00,0x57,0x08,0x01,0x00,0x00,0x09,0x5f,0x0e,0x0b,0x02,0x09,0x00,0x09,0x4f,0x59,0x59,0x40,0x1a,0x00,0x00,0x1b,0x1a,0x19,0x18,0x00,0x17,0x00,0x17,0x16,0x15,0x14,0x13,0x11,0x11,0x11, 0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x06,0x1f,0x2b,0x33,0x35,0x33,0x37,0x23,0x11,0x21,0x37,0x33,0x07,0x33,0x15,0x23,0x03,0x33,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0x23,0x37,0x03,0x33,0x13,0x23,0x23,0x88,0x2c,0xb4,0x01,0x64,0x37,0x46,0x37,0x6d,0x8b,0x74,0xff,0xfe,0xe3,0x2c,0x01,0x49,0xfe,0x99,0x28,0x46,0x28,0x10,0x78,0x74, 0xec,0x52,0x76,0x01,0xe0,0x96,0x96,0x52,0xfe,0xc4,0x52,0x76,0x52,0x6e,0x6e,0x01,0x1a,0x01,0x3c,0x00,0x00,0x02,0x00,0x23,0xff,0xc4,0x02,0x3a,0x03,0x0c,0x00,0x17,0x00,0x1f,0x00,0x43,0x40,0x40,0x1a,0x01,0x04,0x03,0x01,0x01,0x05,0x04,0x02,0x4c,0x00,0x01,0x00,0x01,0x85,0x08,0x01,0x06,0x05,0x06,0x86,0x02,0x01,0x00,0x07,0x01, 0x03,0x04,0x00,0x03,0x69,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x04,0x05,0x4f,0x00,0x00,0x1d,0x1b,0x00,0x17,0x00,0x17,0x21,0x11,0x11,0x11,0x11,0x28,0x09,0x06,0x1c,0x2b,0x17,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x03,0x21,0x15,0x21,0x22,0x27,0x07,0x03, 0x14,0x17,0x13,0x23,0x22,0x06,0x15,0x78,0x43,0x46,0x52,0x3a,0x67,0x45,0x58,0x40,0x3f,0x40,0x9a,0xb7,0x6f,0x01,0x26,0xfe,0xcf,0x09,0x09,0x40,0x3a,0x5a,0x6d,0x3b,0x43,0x49,0x3c,0xbe,0x14,0x6e,0x4e,0x2c,0x42,0x62,0x36,0xb4,0xb4,0x52,0xfe,0xc4,0x52,0x01,0xb5,0x01,0x90,0x6b,0x19,0x01,0x36,0x48,0x42,0x00,0x00,0x02,0x00,0x1e, 0xff,0xc4,0x02,0x35,0x03,0x0c,0x00,0x17,0x00,0x1f,0x00,0x44,0x40,0x41,0x0b,0x01,0x01,0x02,0x1a,0x01,0x00,0x01,0x02,0x4c,0x00,0x03,0x02,0x03,0x85,0x00,0x05,0x04,0x05,0x86,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x07,0x01,0x00,0x04,0x04,0x00,0x59,0x07,0x01,0x00,0x00,0x04,0x5f,0x08,0x06,0x02,0x04,0x00,0x04,0x4f,0x00,0x00, 0x1d,0x1b,0x00,0x17,0x00,0x17,0x11,0x28,0x12,0x21,0x11,0x11,0x09,0x06,0x1c,0x2b,0x37,0x35,0x33,0x13,0x21,0x35,0x21,0x32,0x17,0x37,0x33,0x07,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x23,0x07,0x23,0x37,0x01,0x34,0x27,0x03,0x33,0x32,0x36,0x35,0x1e,0xb7,0x6f,0xfe,0xda,0x01,0x31,0x09,0x09,0x40,0x3f,0x43,0x46,0x52,0x3a,0x67, 0x45,0x58,0x40,0x3f,0x40,0x01,0x23,0x5a,0x6d,0x3b,0x43,0x49,0x78,0x52,0x01,0x3c,0x52,0x01,0xb5,0xbe,0x14,0x6e,0x4e,0x2c,0x41,0x63,0x36,0xb4,0xb4,0x01,0x04,0x6b,0x19,0xfe,0xca,0x48,0x42,0x00,0x00,0x00,0x00,0x01,0x00,0x41,0x00,0x5f,0x02,0x17,0x02,0x35,0x00,0x0b,0x00,0x4d,0x4b,0xb0,0x21,0x50,0x58,0x40,0x16,0x03,0x01,0x01, 0x04,0x01,0x00,0x05,0x01,0x00,0x67,0x06,0x01,0x05,0x05,0x02,0x5f,0x00,0x02,0x02,0x3b,0x05,0x4e,0x1b,0x40,0x1b,0x00,0x02,0x01,0x05,0x02,0x57,0x03,0x01,0x01,0x04,0x01,0x00,0x05,0x01,0x00,0x67,0x00,0x02,0x02,0x05,0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07, 0x09,0x1b,0x2b,0x25,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x01,0x00,0xbf,0xbf,0x58,0xbf,0xbf,0x5f,0xc3,0x50,0xc3,0xc3,0x50,0xc3,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x01,0x22,0x01,0xcc,0x01,0x72,0x02,0x06,0x03,0x57,0x00,0x00,0x00,0x01,0x00,0x69,0x00,0x88,0x01,0xee,0x02,0x0e,0x00,0x0b,0x00,0x06,0xb3,0x06, 0x00,0x01,0x32,0x2b,0x37,0x27,0x37,0x27,0x37,0x17,0x37,0x17,0x07,0x17,0x07,0x27,0x9c,0x33,0x8d,0x8d,0x33,0x8e,0x91,0x33,0x91,0x8e,0x34,0x8d,0x88,0x34,0x8d,0x8e,0x33,0x8d,0x91,0x34,0x91,0x8d,0x34,0x8e,0x00,0x03,0x00,0x64,0x00,0x37,0x01,0xf4,0x02,0x62,0x00,0x0b,0x00,0x0f,0x00,0x1b,0x00,0x41,0x40,0x3e,0x00,0x01,0x06,0x01, 0x00,0x02,0x01,0x00,0x69,0x00,0x02,0x07,0x01,0x03,0x05,0x02,0x03,0x67,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x11,0x10,0x0c,0x0c,0x01,0x00,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34, 0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x35,0x21,0x15,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0xee,0x01,0x90,0xc8,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0x01,0xcc,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0xa5,0x4b,0x4b,0xf0,0x29,0x22,0x22,0x29,0x29,0x22,0x22, 0x29,0x00,0x00,0x00,0x00,0x02,0x00,0x55,0x00,0xaa,0x02,0x03,0x01,0xea,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x2c,0x00,0x00,0x04,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06, 0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x55,0x01,0xae,0xfe,0x52,0x01,0xae,0x01,0x9a,0x50,0x50,0xf0,0x50,0x50,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0xc4,0x02,0x03,0x03,0x0c,0x00,0x13,0x00,0x3d,0x40,0x3a,0x00,0x04,0x03,0x04,0x85,0x0a,0x01,0x09,0x00,0x09,0x86,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02, 0x67,0x07,0x01,0x01,0x00,0x00,0x01,0x57,0x07,0x01,0x01,0x01,0x00,0x5f,0x08,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x06,0x1f,0x2b,0x17,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x13,0x33,0x03,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x78,0x51,0x74,0x91,0x38, 0xc9,0xe5,0x67,0x3f,0x67,0x8a,0xa6,0x38,0xde,0xfb,0x51,0x3c,0xe6,0x50,0xa0,0x50,0x01,0x22,0xfe,0xde,0x50,0xa0,0x50,0xe6,0x00,0x01,0x00,0x55,0x00,0x41,0x02,0x03,0x02,0x53,0x00,0x0c,0x00,0x06,0xb3,0x0a,0x00,0x01,0x32,0x2b,0x37,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0x55,0x01,0x36,0x13,0x21,0x08,0x09, 0x22,0x11,0xfe,0xca,0x01,0xae,0x41,0x57,0x98,0x09,0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0x00,0x00,0x01,0x00,0x55,0x00,0x41,0x02,0x03,0x02,0x53,0x00,0x0c,0x00,0x06,0xb3,0x03,0x00,0x01,0x32,0x2b,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x02,0x03,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08, 0x09,0x22,0x11,0x01,0x36,0x41,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0x00,0x00,0x00,0x02,0x00,0x55,0x00,0x00,0x02,0x03,0x02,0xd0,0x00,0x0c,0x00,0x10,0x00,0x28,0x40,0x25,0x0c,0x0b,0x0a,0x09,0x05,0x01,0x00,0x07,0x00,0x4a,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01, 0x4f,0x0d,0x0d,0x0d,0x10,0x0d,0x10,0x1e,0x03,0x06,0x17,0x2b,0x37,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0x01,0x35,0x21,0x15,0x55,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0xca,0x01,0xae,0xfe,0x52,0x01,0xae,0xbe,0x57,0x98,0x09,0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0xfe,0x6b,0x50,0x50,0x00, 0x00,0x02,0x00,0x55,0x00,0x00,0x02,0x03,0x02,0xd0,0x00,0x0c,0x00,0x10,0x00,0x28,0x40,0x25,0x0c,0x08,0x04,0x03,0x02,0x01,0x00,0x07,0x00,0x4a,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x0d,0x0d,0x0d,0x10,0x0d,0x10,0x1e,0x03,0x06,0x17,0x2b,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06, 0x07,0x16,0x16,0x17,0x05,0x01,0x35,0x21,0x15,0x02,0x03,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x22,0x11,0x01,0x36,0xfe,0x52,0x01,0xae,0xbe,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0xfe,0xe8,0x50,0x50,0x00,0x00,0x00,0x01,0x00,0x41,0x00,0x00,0x02,0x17,0x02,0x3a,0x00,0x0f,0x00,0x56,0x4b,0xb0, 0x18,0x50,0x58,0x40,0x1c,0x04,0x01,0x02,0x05,0x01,0x01,0x00,0x02,0x01,0x67,0x00,0x03,0x03,0x3b,0x4d,0x06,0x01,0x00,0x00,0x07,0x60,0x08,0x01,0x07,0x07,0x39,0x07,0x4e,0x1b,0x40,0x1c,0x00,0x03,0x02,0x03,0x85,0x04,0x01,0x02,0x05,0x01,0x01,0x00,0x02,0x01,0x67,0x06,0x01,0x00,0x00,0x07,0x60,0x08,0x01,0x07,0x07,0x39,0x07,0x4e, 0x59,0x40,0x10,0x00,0x00,0x00,0x0f,0x00,0x0f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x09,0x1d,0x2b,0x33,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x46,0xba,0xbf,0xbf,0x58,0xbf,0xbf,0xba,0x46,0xe1,0x50,0xc3,0xc3,0x50,0xe1,0x46,0xff,0xff,0x00,0x46,0x00,0x69,0x02,0x12,0x02,0x2b,0x02,0x26, 0x04,0x22,0x00,0x64,0x01,0x07,0x04,0x22,0x00,0x00,0xff,0x6f,0x00,0x11,0xb1,0x00,0x01,0xb0,0x64,0xb0,0x35,0x2b,0xb1,0x01,0x01,0xb8,0xff,0x6f,0xb0,0x35,0x2b,0x00,0x00,0x01,0x00,0x64,0x00,0xb9,0x01,0xf4,0x01,0x8b,0x00,0x05,0x00,0x46,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x17,0x03,0x01,0x02,0x00,0x00,0x02,0x71,0x00,0x01,0x00,0x00, 0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x16,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0b,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x09,0x18,0x2b,0x25,0x35,0x21,0x35,0x21,0x15,0x01,0x9f,0xfe,0xc5,0x01,0x90, 0xb9,0x82,0x50,0xd2,0x00,0x01,0x00,0x46,0x00,0xfa,0x02,0x12,0x01,0xc7,0x00,0x1b,0x00,0x68,0xb1,0x06,0x64,0x44,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x1b,0x02,0x01,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x03,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x62,0x06,0x05,0x02,0x03,0x01,0x03,0x52,0x1b,0x40,0x29,0x00,0x02,0x00,0x04,0x00, 0x02,0x04,0x80,0x06,0x01,0x05,0x01,0x03,0x01,0x05,0x03,0x80,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x05,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x62,0x00,0x03,0x01,0x03,0x52,0x59,0x40,0x0e,0x00,0x00,0x00,0x1b,0x00,0x1b,0x24,0x23,0x12,0x24,0x23,0x07,0x09,0x1b,0x2b,0xb1,0x06,0x00,0x44,0x37,0x35,0x34,0x36,0x33,0x32, 0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x15,0x15,0x46,0x48,0x3a,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0xff,0x46,0x3b,0x47,0x1a,0x27,0x27,0x1a,0x37,0x46,0x46,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x37,0x46,0x00,0x00,0x00,0x00,0x01,0x00,0x50, 0x01,0x54,0x02,0x08,0x02,0xda,0x00,0x0c,0x00,0x27,0xb1,0x06,0x64,0x44,0x40,0x1c,0x08,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x03,0x02,0x02,0x01,0x01,0x76,0x00,0x00,0x00,0x0c,0x00,0x0c,0x11,0x11,0x04,0x09,0x18,0x2b,0xb1,0x06,0x00,0x44,0x13,0x13,0x33,0x13,0x23,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x50,0xb3, 0x54,0xb1,0x51,0x70,0x08,0x0d,0x03,0x04,0x0e,0x09,0x73,0x01,0x54,0x01,0x86,0xfe,0x7a,0x01,0x02,0x14,0x25,0x0a,0x0a,0x25,0x14,0xfe,0xfe,0x00,0x00,0x03,0x00,0x23,0x00,0xa0,0x02,0x35,0x01,0xf9,0x00,0x1b,0x00,0x2a,0x00,0x39,0x00,0x4b,0x40,0x48,0x17,0x09,0x02,0x04,0x05,0x01,0x4c,0x02,0x01,0x01,0x07,0x01,0x05,0x04,0x01,0x05, 0x69,0x0a,0x06,0x09,0x03,0x04,0x00,0x00,0x04,0x59,0x0a,0x06,0x09,0x03,0x04,0x04,0x00,0x61,0x03,0x08,0x02,0x00,0x04,0x00,0x51,0x2c,0x2b,0x1d,0x1c,0x01,0x00,0x33,0x31,0x2b,0x39,0x2c,0x39,0x25,0x23,0x1c,0x2a,0x1d,0x2a,0x16,0x14,0x0f,0x0d,0x08,0x06,0x00,0x1b,0x01,0x1b,0x0b,0x06,0x16,0x2b,0x37,0x22,0x26,0x35,0x35,0x34,0x36, 0x33,0x32,0x17,0x33,0x3e,0x02,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x27,0x23,0x0e,0x02,0x27,0x32,0x3e,0x02,0x37,0x27,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x21,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x0e,0x02,0x07,0x17,0x16,0xa6,0x3b,0x48,0x4c,0x3d,0x66,0x24,0x03,0x05,0x1d,0x33,0x24,0x3b,0x48,0x4b,0x3e,0x66, 0x24,0x03,0x04,0x1e,0x32,0x1c,0x1d,0x24,0x15,0x0a,0x01,0x1f,0x16,0x2c,0x1f,0x27,0x27,0x01,0x19,0x20,0x26,0x26,0x20,0x1c,0x25,0x15,0x0a,0x01,0x1f,0x16,0xa0,0x4a,0x3d,0x4b,0x3d,0x4a,0x63,0x16,0x2d,0x20,0x4a,0x3d,0x4b,0x3d,0x4a,0x63,0x15,0x2e,0x20,0x3c,0x17,0x20,0x1c,0x06,0x54,0x34,0x29,0x22,0x4b,0x22,0x29,0x29,0x22,0x4b, 0x22,0x29,0x17,0x20,0x1c,0x06,0x54,0x34,0x00,0x03,0xff,0xf6,0x00,0x00,0x02,0x62,0x02,0xda,0x00,0x18,0x00,0x22,0x00,0x2c,0x00,0x4f,0x40,0x4c,0x0d,0x0a,0x02,0x04,0x00,0x2b,0x2a,0x1d,0x1c,0x04,0x05,0x04,0x17,0x01,0x02,0x02,0x05,0x03,0x4c,0x00,0x01,0x00,0x01,0x85,0x06,0x01,0x03,0x02,0x03,0x86,0x00,0x00,0x00,0x04,0x05,0x00, 0x04,0x69,0x07,0x01,0x05,0x02,0x02,0x05,0x59,0x07,0x01,0x05,0x05,0x02,0x61,0x00,0x02,0x05,0x02,0x51,0x24,0x23,0x00,0x00,0x23,0x2c,0x24,0x2c,0x20,0x1e,0x00,0x18,0x00,0x18,0x27,0x12,0x27,0x08,0x06,0x19,0x2b,0x33,0x37,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x17,0x37,0x33,0x07,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x22,0x26, 0x27,0x07,0x03,0x14,0x16,0x17,0x13,0x26,0x23,0x22,0x06,0x06,0x13,0x32,0x36,0x36,0x35,0x34,0x26,0x27,0x03,0x16,0x14,0x50,0x33,0x3b,0x51,0x8d,0x58,0x4f,0x43,0x3f,0x47,0x54,0x35,0x3d,0x51,0x8c,0x59,0x2a,0x4c,0x21,0x3a,0x0b,0x24,0x20,0xfc,0x2e,0x36,0x3f,0x63,0x3a,0xdc,0x3f,0x63,0x3a,0x27,0x21,0xfd,0x30,0x77,0x2a,0x7d,0x4a, 0x59,0x8c,0x51,0x22,0x5e,0x7e,0x2a,0x7e,0x4c,0x58,0x8d,0x51,0x13,0x12,0x57,0x01,0x68,0x33,0x57,0x1f,0x01,0x78,0x17,0x3c,0x68,0xfe,0xd8,0x3c,0x69,0x41,0x35,0x59,0x1f,0xfe,0x87,0x1a,0x00,0x01,0x00,0x3c,0x00,0x32,0x02,0x1c,0x02,0x26,0x00,0x0c,0x00,0x1f,0x40,0x1c,0x08,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x03, 0x02,0x02,0x01,0x01,0x76,0x00,0x00,0x00,0x0c,0x00,0x0c,0x11,0x11,0x04,0x06,0x18,0x2b,0x37,0x13,0x33,0x13,0x23,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x3c,0xb3,0x7a,0xb3,0x5c,0x75,0x0c,0x11,0x04,0x04,0x12,0x0b,0x72,0x32,0x01,0xf4,0xfe,0x0c,0x01,0x40,0x20,0x3f,0x10,0x10,0x3f,0x20,0xfe,0xc0,0x00,0x00,0x00,0x01,0x00,0x3c, 0x00,0x32,0x02,0x1c,0x02,0x26,0x00,0x0c,0x00,0x1f,0x40,0x1c,0x06,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x0c,0x00,0x0c,0x18,0x11,0x04,0x06,0x18,0x2b,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0xef,0xb3,0x5c,0x75,0x0c,0x11,0x04,0x04,0x12,0x0b, 0x72,0x5b,0xb3,0x32,0x01,0xf4,0xfe,0xc0,0x20,0x3e,0x11,0x11,0x3e,0x20,0x01,0x40,0xfe,0x0c,0x00,0x00,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d,0x02,0xda,0x00,0x13,0x00,0x26,0x40,0x23,0x04,0x03,0x02,0x01,0x02,0x01,0x86,0x00,0x00,0x02,0x02,0x00,0x59,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x00,0x02,0x51,0x00,0x00,0x00,0x13,0x00, 0x13,0x33,0x13,0x33,0x05,0x06,0x19,0x2b,0x33,0x11,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x23,0x22,0x06,0x15,0x11,0x2b,0x75,0x6f,0x3a,0x6f,0x75,0x5a,0x48,0x44,0x36,0x44,0x48,0x01,0xfe,0x6b,0x71,0x71,0x6b,0xfe,0x02,0x01,0xfe,0x44,0x48,0x48,0x44,0xfe,0x02,0x00,0x01,0x00,0x2b,0x00,0x00,0x02,0x2d, 0x02,0xda,0x00,0x13,0x00,0x20,0x40,0x1d,0x02,0x01,0x00,0x01,0x00,0x85,0x00,0x01,0x03,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x61,0x00,0x03,0x01,0x03,0x51,0x33,0x13,0x33,0x10,0x04,0x06,0x1a,0x2b,0x13,0x33,0x11,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x2b,0x5a,0x48,0x44,0x36,0x44, 0x48,0x5a,0x75,0x6f,0x3a,0x6f,0x75,0x02,0xda,0xfe,0x02,0x44,0x48,0x48,0x44,0x01,0xfe,0xfe,0x02,0x6b,0x71,0x71,0x6b,0x00,0x00,0x01,0x00,0x00,0xff,0x4c,0x02,0x17,0x02,0xda,0x00,0x12,0x00,0x28,0x40,0x25,0x00,0x01,0x00,0x02,0x00,0x01,0x02,0x67,0x00,0x00,0x03,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03, 0x4f,0x00,0x00,0x00,0x12,0x00,0x11,0x21,0x25,0x21,0x05,0x06,0x19,0x2b,0x15,0x35,0x33,0x32,0x36,0x35,0x11,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x15,0x11,0x14,0x06,0x23,0x69,0x35,0x3e,0x51,0x49,0xa1,0xa1,0x40,0x70,0x5d,0xb4,0x52,0x3d,0x34,0x02,0x40,0x42,0x49,0x50,0x3c,0xfd,0xc1,0x58,0x6b,0x00,0x00,0x00,0xff,0xff,0x00,0x32, 0x00,0x00,0x02,0x26,0x02,0xda,0x02,0x06,0x02,0x54,0x00,0x00,0x00,0x01,0x00,0x28,0xff,0x4c,0x02,0x30,0x02,0xda,0x00,0x0b,0x00,0x2a,0x40,0x27,0x06,0x05,0x02,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x04,0x02,0x02,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11, 0x07,0x06,0x1b,0x2b,0x17,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x23,0x11,0x23,0x11,0x6e,0x46,0x02,0x08,0x46,0x5a,0xc8,0xb4,0x03,0x3c,0x52,0x52,0xfc,0xc4,0x03,0x3c,0xfc,0xc4,0x00,0x00,0x00,0x01,0x00,0x37,0xff,0x4c,0x02,0x1c,0x02,0xda,0x00,0x0b,0x00,0x37,0x40,0x34,0x08,0x02,0x02,0x02,0x01,0x01,0x4c,0x03,0x01,0x01,0x01,0x01, 0x02,0x02,0x4b,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x12,0x11,0x14,0x05,0x06,0x19,0x2b,0x17,0x35,0x01,0x01,0x35,0x21,0x15,0x21,0x01,0x01,0x21,0x15,0x37,0x01,0x13,0xfe,0xed,0x01,0xe5,0xfe,0x89,0x01,0x12, 0xfe,0xec,0x01,0x79,0xb4,0x52,0x01,0x75,0x01,0x75,0x52,0x52,0xfe,0x8b,0xfe,0x8b,0x52,0x00,0x00,0x00,0x00,0x01,0x00,0x1e,0x00,0x00,0x02,0x49,0x02,0xda,0x00,0x0f,0x00,0x2e,0x40,0x2b,0x00,0x03,0x01,0x03,0x85,0x00,0x01,0x00,0x00,0x02,0x01,0x00,0x67,0x00,0x02,0x04,0x04,0x02,0x57,0x00,0x02,0x02,0x04,0x5f,0x05,0x01,0x04,0x02, 0x04,0x4f,0x00,0x00,0x00,0x0f,0x00,0x0f,0x14,0x14,0x11,0x11,0x06,0x06,0x1a,0x2b,0x21,0x03,0x23,0x35,0x33,0x13,0x16,0x16,0x07,0x33,0x26,0x36,0x37,0x13,0x33,0x03,0x01,0x0c,0x7f,0x6f,0xaf,0x63,0x08,0x06,0x01,0x09,0x01,0x07,0x09,0xa0,0x54,0xd4,0x01,0xd6,0x50,0xfe,0x7b,0x22,0x33,0x0b,0x0b,0x34,0x21,0x02,0x39,0xfd,0x26,0x00, 0x00,0x02,0x00,0x5a,0xff,0xf6,0x01,0xfe,0x02,0xda,0x00,0x1b,0x00,0x29,0x00,0x3f,0x40,0x3c,0x0c,0x0a,0x02,0x03,0x04,0x01,0x4c,0x00,0x02,0x01,0x02,0x85,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x69,0x06,0x01,0x03,0x00,0x00,0x03,0x59,0x06,0x01,0x03,0x03,0x00,0x61,0x05,0x01,0x00,0x03,0x00,0x51,0x1d,0x1c,0x01,0x00,0x24,0x22,0x1c, 0x29,0x1d,0x29,0x12,0x11,0x08,0x06,0x00,0x1b,0x01,0x1b,0x07,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35,0x34,0x2e,0x02,0x27,0x33,0x30,0x1e,0x03,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x2c,0x62,0x70,0x61,0x57,0x3e,0x4b,0x07,0x02, 0x31,0x4e,0x5a,0x2a,0x87,0x2b,0x40,0x40,0x2b,0x70,0x62,0x3a,0x3e,0x3d,0x3b,0x3a,0x3e,0x3e,0x0a,0x73,0x64,0x50,0x62,0x70,0x37,0x32,0x19,0x36,0x62,0x52,0x3e,0x13,0x1b,0x36,0x4e,0x67,0x3f,0xc8,0x64,0x73,0x50,0x46,0x41,0x50,0x42,0x45,0x46,0x41,0x50,0x41,0x46,0x00,0xff,0xff,0x00,0x5d,0xff,0x4c,0x01,0xfb,0x02,0x26,0x02,0x06, 0x02,0x80,0x00,0x00,0x00,0x02,0x00,0x9b,0x00,0x00,0x01,0xbd,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x22,0x40,0x1f,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x03,0x04,0x03,0x01,0x01,0x76,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x01,0x63, 0x5a,0xfe,0xde,0x5a,0x02,0xda,0xfd,0x26,0x02,0xda,0xfd,0x26,0x00,0x01,0x00,0xff,0xfe,0xd4,0x01,0x59,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xff,0x5a,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00, 0x00,0x01,0x00,0xff,0xff,0x88,0x02,0x2b,0x03,0xfc,0x00,0x0a,0x00,0x10,0x40,0x0d,0x0a,0x00,0x02,0x00,0x49,0x00,0x00,0x00,0x76,0x15,0x01,0x06,0x17,0x2b,0x05,0x2e,0x02,0x35,0x11,0x33,0x11,0x14,0x16,0x17,0x02,0x2b,0x5d,0x86,0x49,0x5a,0x71,0x61,0x78,0x17,0x6e,0xa0,0x61,0x02,0xee,0xfd,0x12,0x75,0xa2,0x17,0x00,0x01,0x00,0xff, 0xfe,0xd4,0x02,0x2b,0x03,0x48,0x00,0x0a,0x00,0x16,0x40,0x13,0x06,0x05,0x02,0x00,0x4a,0x01,0x01,0x00,0x00,0x76,0x00,0x00,0x00,0x0a,0x00,0x0a,0x02,0x06,0x16,0x2b,0x13,0x11,0x34,0x36,0x36,0x37,0x15,0x06,0x06,0x15,0x11,0xff,0x49,0x86,0x5d,0x61,0x71,0xfe,0xd4,0x02,0xee,0x62,0x9f,0x6e,0x17,0x58,0x17,0xa2,0x75,0xfd,0x12,0x00, 0xff,0xff,0x00,0xff,0xfe,0xd4,0x01,0x59,0x03,0xfc,0x02,0x06,0x04,0x32,0x00,0x00,0x00,0x01,0x00,0x2d,0xff,0x88,0x01,0x59,0x03,0xfc,0x00,0x0a,0x00,0x10,0x40,0x0d,0x01,0x00,0x02,0x00,0x49,0x00,0x00,0x00,0x76,0x15,0x01,0x06,0x17,0x2b,0x17,0x35,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x06,0x2d,0x62,0x70,0x5a,0x48,0x87,0x78, 0x58,0x17,0xa2,0x75,0x02,0xee,0xfd,0x12,0x61,0xa0,0x6e,0x00,0x00,0x01,0x00,0x2d,0xfe,0xd4,0x01,0x59,0x03,0x48,0x00,0x0a,0x00,0x10,0x40,0x0d,0x06,0x05,0x02,0x00,0x4a,0x00,0x00,0x00,0x76,0x10,0x01,0x06,0x17,0x2b,0x01,0x23,0x11,0x34,0x26,0x27,0x35,0x1e,0x02,0x15,0x01,0x59,0x5a,0x70,0x62,0x5d,0x87,0x48,0xfe,0xd4,0x02,0xee, 0x75,0xa2,0x17,0x58,0x17,0x6e,0x9f,0x62,0x00,0x05,0x00,0x0e,0xff,0xfb,0x02,0x4a,0x02,0xdf,0x00,0x0d,0x00,0x11,0x00,0x1f,0x00,0x2d,0x00,0x3b,0x00,0x99,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x2c,0x0c,0x01,0x04,0x0a,0x01,0x00,0x07,0x04,0x00,0x69,0x00,0x07,0x00,0x09,0x08,0x07,0x09,0x69,0x00,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01, 0x38,0x4d,0x0e,0x01,0x08,0x08,0x03,0x61,0x0d,0x06,0x0b,0x03,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x34,0x0c,0x01,0x04,0x0a,0x01,0x00,0x07,0x04,0x00,0x69,0x00,0x07,0x00,0x09,0x08,0x07,0x09,0x69,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x38,0x4d,0x0b,0x01,0x03,0x03,0x39,0x4d,0x0e,0x01,0x08,0x08,0x06, 0x61,0x0d,0x01,0x06,0x06,0x42,0x06,0x4e,0x59,0x40,0x2b,0x2f,0x2e,0x21,0x20,0x13,0x12,0x0e,0x0e,0x01,0x00,0x36,0x34,0x2e,0x3b,0x2f,0x3b,0x28,0x26,0x20,0x2d,0x21,0x2d,0x1a,0x18,0x12,0x1f,0x13,0x1f,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x08,0x06,0x00,0x0d,0x01,0x0d,0x0f,0x09,0x16,0x2b,0x13,0x22,0x26,0x37,0x35,0x26,0x36,0x33,0x32, 0x16,0x17,0x15,0x14,0x06,0x03,0x01,0x33,0x01,0x13,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x22,0x26,0x35,0x35,0x26,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x06,0x16,0x99,0x40,0x4b,0x01,0x01,0x4b,0x40,0x40,0x4b,0x01,0x4b,0xcc,0x01, 0xf2,0x4a,0xfe,0x0e,0x42,0x1e,0x23,0x23,0x1e,0x1e,0x23,0x23,0x01,0x42,0x40,0x4b,0x01,0x4c,0x40,0x40,0x4b,0x4b,0x40,0x1e,0x23,0x23,0x1f,0x1d,0x23,0x01,0x23,0x01,0x90,0x49,0x3e,0x41,0x3e,0x49,0x49,0x3e,0x41,0x3e,0x49,0xfe,0x70,0x02,0xda,0xfd,0x26,0x01,0xd4,0x24,0x1f,0x41,0x1f,0x24,0x24,0x1f,0x41,0x1f,0x24,0xfe,0x27,0x49, 0x3e,0x41,0x3e,0x49,0x49,0x3e,0x41,0x3e,0x49,0x45,0x23,0x1f,0x41,0x1f,0x24,0x24,0x1f,0x41,0x1f,0x23,0x00,0x06,0xff,0xfb,0xff,0xfb,0x02,0x72,0x02,0xdf,0x00,0x0d,0x00,0x11,0x00,0x1f,0x00,0x39,0x00,0x47,0x00,0x55,0x00,0xb7,0xb6,0x37,0x2a,0x02,0x0a,0x0b,0x01,0x4c,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x31,0x10,0x01,0x04,0x0e,0x01, 0x00,0x07,0x04,0x00,0x69,0x08,0x01,0x07,0x0d,0x01,0x0b,0x0a,0x07,0x0b,0x6a,0x00,0x05,0x05,0x01,0x61,0x02,0x01,0x01,0x01,0x38,0x4d,0x13,0x0c,0x12,0x03,0x0a,0x0a,0x03,0x61,0x09,0x11,0x06,0x0f,0x04,0x03,0x03,0x39,0x03,0x4e,0x1b,0x40,0x39,0x10,0x01,0x04,0x0e,0x01,0x00,0x07,0x04,0x00,0x69,0x08,0x01,0x07,0x0d,0x01,0x0b,0x0a, 0x07,0x0b,0x6a,0x00,0x02,0x02,0x38,0x4d,0x00,0x05,0x05,0x01,0x61,0x00,0x01,0x01,0x38,0x4d,0x0f,0x01,0x03,0x03,0x39,0x4d,0x13,0x0c,0x12,0x03,0x0a,0x0a,0x06,0x61,0x09,0x11,0x02,0x06,0x06,0x42,0x06,0x4e,0x59,0x40,0x37,0x49,0x48,0x3b,0x3a,0x21,0x20,0x13,0x12,0x0e,0x0e,0x01,0x00,0x50,0x4e,0x48,0x55,0x49,0x55,0x42,0x40,0x3a, 0x47,0x3b,0x47,0x35,0x33,0x2e,0x2c,0x28,0x26,0x20,0x39,0x21,0x39,0x1a,0x18,0x12,0x1f,0x13,0x1f,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x08,0x06,0x00,0x0d,0x01,0x0d,0x14,0x09,0x16,0x2b,0x13,0x22,0x26,0x27,0x35,0x26,0x36,0x33,0x32,0x16,0x17,0x15,0x14,0x06,0x03,0x01,0x33,0x01,0x13,0x32,0x36,0x35,0x35,0x26,0x26,0x23,0x22,0x06,0x15, 0x15,0x14,0x16,0x13,0x22,0x26,0x37,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x27,0x32,0x36,0x37,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x06,0x16,0x33,0x32,0x36,0x37,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x06,0x16,0x7d,0x37,0x40,0x01,0x01,0x41,0x37, 0x37,0x41,0x01,0x40,0xba,0x01,0xb6,0x43,0xfe,0x4a,0x3f,0x1a,0x1f,0x01,0x1e,0x1a,0x1a,0x1f,0x1f,0xf6,0x32,0x3b,0x01,0x3b,0x31,0x26,0x2e,0x02,0x03,0x2f,0x25,0x32,0x3a,0x3a,0x32,0x26,0x2e,0x02,0x04,0x2f,0x1f,0x17,0x1b,0x01,0x1c,0x17,0x17,0x1c,0x01,0x1c,0xbb,0x17,0x1b,0x01,0x1c,0x17,0x17,0x1c,0x01,0x1c,0x01,0xb8,0x3e,0x35, 0x41,0x35,0x3e,0x3e,0x35,0x41,0x35,0x3e,0xfe,0x48,0x02,0xda,0xfd,0x26,0x01,0xf3,0x1f,0x19,0x41,0x1a,0x1e,0x1e,0x1a,0x41,0x19,0x1f,0xfe,0x08,0x40,0x37,0x38,0x38,0x40,0x26,0x20,0x20,0x26,0x40,0x38,0x38,0x37,0x40,0x26,0x20,0x20,0x26,0x35,0x23,0x1f,0x38,0x1f,0x24,0x24,0x1f,0x38,0x1f,0x23,0x23,0x1f,0x38,0x1f,0x24,0x24,0x1f, 0x38,0x1f,0x23,0x00,0x00,0x01,0x00,0x78,0x00,0x00,0x01,0xe0,0x01,0x65,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b, 0x2b,0x21,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x01,0x07,0x8f,0x8f,0x4a,0x8f,0x8f,0x93,0x40,0x92,0x92,0x40,0x93,0x00,0x00,0x00,0x01,0x00,0xa0,0x01,0x31,0x01,0xb8,0x02,0x49,0x00,0x0b,0x00,0x2c,0x40,0x29,0x00,0x02,0x01,0x05,0x02,0x57,0x03,0x01,0x01,0x04,0x01,0x00,0x05,0x01,0x00,0x67,0x00,0x02,0x02,0x05, 0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x0b,0x1b,0x2b,0x01,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x01,0x04,0x64,0x64,0x50,0x64,0x64,0x01,0x31,0x69,0x46,0x69,0x69,0x46,0x69,0x00,0x00,0x00,0x00,0x01,0x00,0x37,0x00,0x37,0x02,0x08,0x02,0x58,0x00,0x12, 0x00,0x33,0x40,0x30,0x00,0x02,0x01,0x02,0x85,0x00,0x03,0x01,0x00,0x01,0x03,0x00,0x80,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x01,0x03,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x00,0x00,0x00,0x12,0x00,0x12,0x13,0x13,0x11,0x13,0x06,0x06,0x1a,0x2b,0x25,0x2e,0x02,0x23,0x35,0x32,0x36,0x36,0x37,0x33,0x0e, 0x02,0x07,0x1e,0x02,0x17,0x01,0xae,0x08,0x63,0xa3,0x69,0x69,0xa3,0x63,0x08,0x5a,0x09,0x56,0x8f,0x5c,0x5c,0x8f,0x56,0x09,0x37,0x45,0x65,0x37,0x64,0x36,0x63,0x43,0x4c,0x73,0x45,0x05,0x07,0x48,0x7a,0x4f,0x00,0x02,0x00,0x37,0x00,0x00,0x02,0x08,0x02,0xd5,0x00,0x12,0x00,0x16,0x00,0x47,0x40,0x44,0x00,0x02,0x01,0x02,0x85,0x00, 0x03,0x01,0x00,0x01,0x03,0x00,0x80,0x07,0x01,0x04,0x00,0x05,0x00,0x04,0x05,0x80,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x69,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05,0x06,0x5f,0x08,0x01,0x06,0x05,0x06,0x4f,0x13,0x13,0x00,0x00,0x13,0x16,0x13,0x16,0x15,0x14,0x00,0x12,0x00,0x12,0x13,0x13,0x11,0x13,0x09,0x06,0x1a,0x2b,0x25, 0x2e,0x02,0x23,0x35,0x32,0x36,0x36,0x37,0x33,0x0e,0x02,0x07,0x1e,0x02,0x17,0x05,0x35,0x21,0x15,0x01,0xae,0x08,0x63,0xa3,0x69,0x69,0xa3,0x63,0x08,0x5a,0x09,0x56,0x8f,0x5c,0x5c,0x8f,0x56,0x09,0xfe,0x2f,0x01,0xcc,0xb4,0x45,0x65,0x37,0x64,0x36,0x63,0x43,0x4c,0x73,0x45,0x05,0x07,0x48,0x7a,0x4f,0xb4,0x50,0x50,0x00,0x00,0x00, 0x00,0x04,0x00,0x37,0xff,0xf6,0x02,0x20,0x01,0xfe,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x47,0x40,0x44,0x03,0x01,0x01,0x09,0x02,0x08,0x03,0x00,0x05,0x01,0x00,0x69,0x07,0x01,0x05,0x04,0x04,0x05,0x59,0x07,0x01,0x05,0x05,0x04,0x61,0x0b,0x06,0x0a,0x03,0x04,0x05,0x04,0x51,0x25,0x24,0x19,0x18,0x0d,0x0c,0x01,0x00,0x2b, 0x29,0x24,0x2f,0x25,0x2f,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0xce,0x24,0x2e,0x2e,0x24,0x24,0x2e,0x2e,0xfe,0x97,0x24,0x2e,0x2e,0x24,0x24,0x2e,0x2e,0x24,0x24,0x2e,0x2e,0x24,0x24,0x2e,0x2e,0x01,0x21,0x24,0x2e,0x2e,0x24,0x24,0x2e,0x2e,0x01,0x5c,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d, 0xfe,0x9a,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d,0x2d,0x24,0x24,0x2d,0x00,0x00,0x00,0x04,0x00,0x55,0x00,0x4c,0x02,0x03,0x03,0x17,0x00,0x13,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0xaa,0x4b,0xb0,0x24,0x50,0x58,0x40,0x3b,0x0b,0x01,0x04,0x03,0x06,0x03,0x04,0x72,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00, 0x00,0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x06,0x0c,0x01,0x05,0x07,0x06,0x05,0x69,0x00,0x07,0x0d,0x01,0x08,0x09,0x07,0x08,0x67,0x00,0x09,0x0a,0x0a,0x09,0x57,0x00,0x09,0x09,0x0a,0x5f,0x0e,0x01,0x0a,0x09,0x0a,0x4f,0x1b,0x40,0x3c,0x0b,0x01,0x04,0x03,0x06,0x03,0x04,0x06,0x80,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00, 0x00,0x03,0x04,0x00,0x03,0x69,0x00,0x06,0x0c,0x01,0x05,0x07,0x06,0x05,0x69,0x00,0x07,0x0d,0x01,0x08,0x09,0x07,0x08,0x67,0x00,0x09,0x0a,0x0a,0x09,0x57,0x00,0x09,0x09,0x0a,0x5f,0x0e,0x01,0x0a,0x09,0x0a,0x4f,0x59,0x40,0x25,0x24,0x24,0x20,0x20,0x15,0x14,0x00,0x00,0x24,0x27,0x24,0x27,0x26,0x25,0x20,0x23,0x20,0x23,0x22,0x21, 0x1b,0x19,0x14,0x1f,0x15,0x1f,0x00,0x13,0x00,0x13,0x24,0x21,0x24,0x21,0x0f,0x06,0x1a,0x2b,0x13,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0xff,0x49,0x18,0x1d,0x1d,0x18, 0x86,0x87,0x33,0x3d,0x3d,0x33,0x13,0x1c,0x12,0x15,0x15,0x12,0x12,0x15,0x15,0xd7,0x01,0xae,0xfe,0x52,0x01,0xae,0x02,0x21,0x55,0x1d,0x18,0x18,0x1d,0x37,0x3a,0x32,0x2f,0x38,0x23,0x73,0x14,0x10,0x11,0x13,0x13,0x11,0x10,0x14,0x8a,0x4c,0x4c,0xd8,0x4c,0x4c,0x00,0x00,0xff,0xff,0x00,0xd9,0xff,0xf6,0x01,0x7f,0x02,0x30,0x02,0x06, 0x03,0x2b,0x00,0x00,0x00,0x02,0x00,0x23,0x00,0x00,0x02,0x3a,0x02,0xa8,0x00,0x15,0x00,0x19,0x00,0x3c,0x40,0x39,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x06,0x01,0x00,0x04,0x03,0x00,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x16,0x16,0x01,0x00,0x16,0x19,0x16,0x19, 0x18,0x17,0x14,0x12,0x0d,0x0b,0x0a,0x08,0x00,0x15,0x01,0x15,0x08,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x21,0x15,0x05,0x35,0x21,0x15,0x01,0x09,0x45,0x67,0x3a,0x3a,0x67,0x45,0x01,0x31,0xfe,0xcf,0x43,0x49,0x49,0x43,0x01,0x31,0xfd,0xf8,0x02,0x08, 0xc8,0x36,0x63,0x41,0x2c,0x42,0x62,0x36,0x52,0x48,0x42,0x28,0x42,0x48,0x52,0xc8,0x52,0x52,0x00,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x35,0x02,0xa8,0x00,0x15,0x00,0x19,0x00,0x39,0x40,0x36,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04, 0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x16,0x16,0x00,0x00,0x16,0x19,0x16,0x19,0x18,0x17,0x00,0x15,0x00,0x14,0x21,0x25,0x21,0x08,0x06,0x19,0x2b,0x37,0x35,0x21,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x32,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x05,0x35,0x21,0x15,0x1e,0x01,0x31,0x43,0x49,0x49,0x43,0xfe,0xcf, 0x01,0x31,0x45,0x67,0x3a,0x3a,0x67,0x45,0xfe,0xcf,0x02,0x08,0xc8,0x52,0x48,0x42,0x28,0x42,0x48,0x52,0x36,0x62,0x42,0x2c,0x41,0x63,0x36,0xc8,0x52,0x52,0x00,0x00,0x00,0x01,0xff,0xb0,0x00,0x4b,0x02,0xa8,0x01,0xdb,0x00,0x31,0x00,0x4c,0x40,0x49,0x14,0x09,0x02,0x01,0x00,0x2c,0x21,0x1a,0x13,0x08,0x01,0x06,0x06,0x01,0x2b,0x20, 0x02,0x05,0x06,0x03,0x4c,0x04,0x02,0x02,0x00,0x01,0x00,0x85,0x0a,0x09,0x07,0x03,0x05,0x06,0x05,0x86,0x03,0x01,0x01,0x06,0x06,0x01,0x59,0x03,0x01,0x01,0x01,0x06,0x62,0x08,0x01,0x06,0x01,0x06,0x52,0x00,0x00,0x00,0x31,0x00,0x31,0x27,0x11,0x27,0x12,0x17,0x21,0x17,0x21,0x12,0x0b,0x06,0x1f,0x2b,0x27,0x37,0x27,0x33,0x17,0x33, 0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x33,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x07,0x23,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x23,0x07,0x23,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x23,0x07,0x50,0x9f,0x9f,0x6a,0x7d,0x88,0x11,0x28,0x0d,0x07,0x19,0x0d,0x57,0x6a,0x7d,0x18,0x11,0x28,0x0d,0x07, 0x19,0x0d,0x57,0x6a,0x9c,0x9c,0x6a,0x57,0x0a,0x1a,0x09,0x0d,0x28,0x11,0x18,0x7d,0x6a,0x57,0x0a,0x1a,0x09,0x0d,0x28,0x11,0x88,0x7d,0x4b,0xc8,0xc8,0xa0,0x03,0x02,0x09,0x06,0x19,0x10,0x6d,0xa0,0x03,0x02,0x09,0x06,0x19,0x10,0x6d,0xc8,0xc8,0x6e,0x0d,0x19,0x07,0x09,0x01,0x03,0xa0,0x6e,0x0d,0x19,0x07,0x09,0x01,0x03,0xa0,0x00, 0x00,0x01,0x00,0x73,0xff,0x92,0x01,0x59,0x03,0xfc,0x00,0x0a,0x00,0x26,0x40,0x23,0x00,0x02,0x01,0x02,0x85,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x03,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07,0x06,0x04,0x02,0x00,0x0a,0x01,0x0a,0x04,0x06,0x16,0x2b,0x17,0x23,0x35,0x33,0x32,0x35,0x11,0x33,0x11,0x14,0x06,0xa0, 0x2d,0x2d,0x5f,0x5a,0x60,0x6e,0x50,0x56,0x03,0xc4,0xfc,0x3c,0x4f,0x57,0x00,0x00,0x00,0x01,0x00,0xff,0xfe,0xd4,0x02,0x2b,0x03,0xfc,0x00,0x16,0x00,0x2a,0x40,0x27,0x05,0x01,0x03,0x02,0x01,0x4c,0x00,0x01,0x02,0x01,0x85,0x00,0x00,0x03,0x00,0x86,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x02,0x03,0x4f, 0x21,0x24,0x18,0x10,0x04,0x06,0x1a,0x2b,0x01,0x23,0x11,0x34,0x36,0x37,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x06,0x15,0x01,0x59,0x5a,0x34,0x31,0x32,0x33,0x5a,0x0e,0x2b,0x2b,0x6e,0x6e,0x2b,0x2b,0x0e,0xfe,0xd4,0x02,0x08,0x39,0x4a,0x09,0x09,0x4a,0x39,0x02,0x08,0xfd,0xf8,0x23,0x2d,0x14, 0x50,0x14,0x2c,0x24,0x00,0x01,0x00,0x73,0xfe,0xd4,0x01,0x59,0x03,0x3e,0x00,0x0a,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x59,0x00,0x02,0x02,0x01,0x61,0x00,0x01,0x02,0x01,0x51,0x21,0x22,0x10,0x03,0x06,0x19,0x2b,0x01,0x23,0x11,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x01,0x59,0x5a,0x5f,0x2d, 0x2d,0x59,0x60,0xfe,0xd4,0x03,0xc4,0x56,0x50,0x57,0x4f,0x00,0x00,0x02,0x00,0x00,0x00,0x32,0x02,0x58,0x02,0x9b,0x00,0x08,0x00,0x0b,0x00,0x08,0xb5,0x0a,0x09,0x04,0x03,0x02,0x32,0x2b,0x11,0x37,0x05,0x01,0x11,0x01,0x05,0x27,0x25,0x05,0x11,0x07,0x23,0x01,0x09,0x01,0x2c,0xfe,0xd3,0xfe,0xf7,0x22,0x01,0x07,0x01,0x1f,0xd6,0x02, 0x58,0x25,0xf3,0x01,0x11,0xfd,0x97,0x01,0x13,0xf1,0x23,0xf0,0xc2,0x01,0x86,0xc3,0xff,0xff,0x00,0xff,0xfe,0xd4,0x01,0x59,0x03,0xfc,0x02,0x06,0x03,0xf4,0x00,0x00,0x00,0x01,0x00,0x64,0xff,0x92,0x01,0x59,0x03,0xfc,0x00,0x05,0x00,0x1e,0x40,0x1b,0x00,0x02,0x01,0x02,0x85,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f, 0x00,0x00,0x01,0x00,0x4f,0x11,0x11,0x10,0x03,0x06,0x19,0x2b,0x05,0x23,0x35,0x33,0x11,0x33,0x01,0x59,0xf5,0x9b,0x5a,0x6e,0x50,0x04,0x1a,0x00,0x00,0x01,0x00,0x64,0xfe,0xd4,0x01,0x59,0x03,0x3e,0x00,0x05,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x02,0x01, 0x4f,0x11,0x11,0x10,0x03,0x06,0x19,0x2b,0x01,0x23,0x11,0x23,0x35,0x33,0x01,0x59,0x5a,0x9b,0xf5,0xfe,0xd4,0x04,0x1a,0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02, 0x01,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x31,0x11,0x33,0x15,0x21,0x15,0x21,0x11,0x5a,0x01,0xfe,0xfe,0x02,0x02,0x58,0xff,0x50,0xfe,0xf7,0x00,0x00,0x04,0x00,0x55,0x00,0x4c,0x02,0x03,0x02,0xd1,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x52,0x40,0x4f,0x00,0x01,0x00,0x03,0x02,0x01, 0x03,0x69,0x09,0x01,0x02,0x08,0x01,0x00,0x04,0x02,0x00,0x69,0x00,0x04,0x0a,0x01,0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x0b,0x01,0x07,0x06,0x07,0x4f,0x1c,0x1c,0x18,0x18,0x0d,0x0c,0x01,0x00,0x1c,0x1f,0x1c,0x1f,0x1e,0x1d,0x18,0x1b,0x18,0x1b,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17, 0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x07,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x01,0x2c,0x36,0x42,0x42,0x36,0x36,0x42,0x42,0x36,0x1b,0x21,0x21,0x1b,0x1b,0x21,0x21,0xbc,0x01,0xae,0xfe,0x52, 0x01,0xae,0x01,0xed,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x33,0x3f,0x35,0x21,0x1c,0x1c,0x22,0x22,0x1c,0x1c,0x21,0xfe,0x4c,0x4c,0xd8,0x4c,0x4c,0x00,0x00,0x02,0x00,0xb4,0x00,0xd2,0x01,0xa4,0x01,0xc2,0x00,0x0b,0x00,0x17,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02, 0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0x35,0x23, 0x2d,0x2d,0x23,0x23,0x2d,0x2d,0xd2,0x44,0x34,0x35,0x43,0x43,0x35,0x34,0x44,0x28,0x2d,0x23,0x23,0x2d,0x2d,0x23,0x23,0x2d,0xff,0xff,0x00,0x46,0x00,0xfa,0x02,0x12,0x01,0xc7,0x02,0x06,0x04,0x22,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x17,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x03,0x02,0x01,0x02,0x01,0x86,0x00, 0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x00,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x33,0x11,0x21,0x11,0x23,0x11,0x21,0x11,0x3c,0x01,0xe0,0x5a,0xfe,0xd4,0x02,0x17,0xfd,0xe9,0x01,0xc5,0xfe,0x3b,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0x17,0x00,0x07, 0x00,0x20,0x40,0x1d,0x02,0x01,0x00,0x01,0x00,0x85,0x00,0x01,0x03,0x03,0x01,0x57,0x00,0x01,0x01,0x03,0x5f,0x00,0x03,0x01,0x03,0x4f,0x11,0x11,0x11,0x10,0x04,0x06,0x1a,0x2b,0x13,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x3c,0x5a,0x01,0x2c,0x5a,0xfe,0x20,0x02,0x17,0xfe,0x3b,0x01,0xc5,0xfd,0xe9,0x00,0x00,0x00,0x00,0x03,0x00,0x00, 0x00,0x1e,0x02,0x58,0x02,0x76,0x00,0x03,0x00,0x07,0x00,0x13,0x00,0x3b,0x40,0x38,0x00,0x00,0x00,0x03,0x05,0x00,0x03,0x67,0x00,0x05,0x07,0x01,0x04,0x02,0x05,0x04,0x69,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x06,0x01,0x01,0x02,0x01,0x4f,0x09,0x08,0x00,0x00,0x0f,0x0d,0x08,0x13,0x09,0x13,0x07,0x06,0x05,0x04, 0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0xfa,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0x1e,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0xfe,0xce,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x00, 0x00,0x03,0x00,0x00,0x00,0x1e,0x02,0x58,0x02,0x76,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x3b,0x40,0x38,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x67,0x00,0x04,0x07,0x01,0x05,0x02,0x04,0x05,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x06,0x01,0x01,0x02,0x01,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09, 0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x13,0x35,0x21,0x15,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x5a,0x01,0x40,0x1e,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0xfe,0xde,0x50,0x50,0x00,0x05,0x00,0x00,0x00,0x1e,0x02,0x58,0x02,0x76,0x00,0x03,0x00,0x06,0x00,0x09, 0x00,0x0c,0x00,0x0f,0x00,0x33,0x40,0x30,0x0c,0x0b,0x09,0x08,0x04,0x03,0x02,0x01,0x4c,0x00,0x00,0x00,0x02,0x03,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x00,0x00,0x0f,0x0e,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x01,0x37,0x21, 0x17,0x17,0x11,0x05,0x27,0x11,0x37,0x07,0x21,0x02,0x58,0xfe,0xd2,0xc2,0xfe,0x7a,0xf7,0xc9,0xfe,0xd0,0xc4,0xf8,0xcb,0x01,0x94,0x1e,0x02,0x58,0xfd,0xa8,0x01,0x64,0xc2,0xf6,0xc7,0x01,0x90,0xc9,0xc6,0xfe,0x76,0x91,0xcb,0x00,0x00,0x05,0x00,0x00,0x00,0x1e,0x02,0x58,0x02,0x76,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13, 0x00,0x4e,0x40,0x4b,0x00,0x00,0x05,0x01,0x02,0x03,0x00,0x02,0x67,0x04,0x0b,0x02,0x03,0x09,0x01,0x06,0x07,0x03,0x06,0x67,0x08,0x0c,0x02,0x07,0x01,0x01,0x07,0x57,0x08,0x0c,0x02,0x07,0x07,0x01,0x5f,0x0a,0x01,0x01,0x07,0x01,0x4f,0x0c,0x0c,0x04,0x04,0x00,0x00,0x13,0x12,0x11,0x10,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x0b,0x0a,0x09, 0x08,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0d,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x01,0x35,0x23,0x15,0x21,0x33,0x35,0x23,0x13,0x35,0x23,0x15,0x21,0x33,0x35,0x23,0x02,0x58,0xfe,0xa8,0xce,0x01,0x26,0xce,0xce,0xce,0xce,0xfe,0xda,0xce,0xce,0x1e,0x02,0x58,0xfd,0xa8,0x01,0x54,0xd2,0xd2,0xd2,0xfe,0x0c,0xd2, 0xd2,0xd2,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x5a,0x02,0x3a,0x02,0x3a,0x00,0x07,0x00,0x28,0x40,0x25,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x37,0x11,0x21,0x15,0x21,0x11, 0x21,0x15,0x23,0x02,0x17,0xfe,0x43,0x01,0xbd,0x5a,0x01,0xe0,0x52,0xfe,0xc4,0x52,0x00,0x02,0x00,0x23,0x00,0x00,0x02,0x3a,0x02,0xa8,0x00,0x07,0x00,0x0b,0x00,0x39,0x40,0x36,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x06,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01, 0x05,0x04,0x05,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x37,0x11,0x21,0x15,0x21,0x11,0x21,0x15,0x05,0x35,0x21,0x15,0x23,0x02,0x17,0xfe,0x43,0x01,0xbd,0xfd,0xe9,0x02,0x17,0xc8,0x01,0xe0,0x52,0xfe,0xc4,0x52,0xc8,0x52,0x52,0x00,0x00,0x00,0x01,0x00,0x1e, 0x00,0x5a,0x02,0x35,0x02,0x3a,0x00,0x07,0x00,0x22,0x40,0x1f,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x11,0x11,0x11,0x10,0x04,0x06,0x1a,0x2b,0x25,0x21,0x35,0x21,0x11,0x21,0x35,0x21,0x02,0x35,0xfd,0xe9,0x01,0xbd,0xfe,0x43,0x02,0x17,0x5a,0x52, 0x01,0x3c,0x52,0x00,0x00,0x02,0x00,0x1e,0x00,0x00,0x02,0x35,0x02,0xa8,0x00,0x07,0x00,0x0b,0x00,0x39,0x40,0x36,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b, 0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x37,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x05,0x35,0x21,0x15,0x1e,0x01,0xbd,0xfe,0x43,0x02,0x17,0xfd,0xe9,0x02,0x17,0xc8,0x52,0x01,0x3c,0x52,0xfe,0x20,0xc8,0x52,0x52,0x00,0x00,0x00,0x01,0x00,0xb4,0x00,0xda,0x01,0xa4,0x01,0xd0,0x00,0x09,0x00,0x18,0x40,0x15, 0x04,0x01,0x00,0x4a,0x09,0x08,0x07,0x01,0x04,0x00,0x49,0x01,0x01,0x00,0x00,0x76,0x12,0x12,0x02,0x06,0x18,0x2b,0x37,0x37,0x27,0x33,0x37,0x17,0x33,0x07,0x17,0x27,0xe3,0x1e,0x4d,0x5b,0x1d,0x1d,0x5b,0x4d,0x1e,0x49,0xda,0x63,0x36,0x5d,0x5d,0x36,0x63,0x43,0x00,0x00,0x00,0x04,0x00,0x55,0x00,0x54,0x02,0x03,0x02,0x40,0x00,0x03, 0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x51,0x40,0x4e,0x00,0x00,0x08,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x09,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x0a,0x01,0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x0b,0x01,0x07,0x06,0x07,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f, 0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x55,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0x52,0x01,0xae,0xfe,0x52,0x01,0xae,0x02,0x04,0x3c,0x3c,0x90,0x3c,0x3c,0x90, 0x3c,0x3c,0x90,0x3c,0x3c,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0x00,0x78,0x02,0x3a,0x02,0x58,0x00,0x15,0x00,0x2b,0x40,0x28,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x03,0x03,0x00,0x5f,0x04,0x01,0x00,0x03,0x00,0x4f,0x01,0x00,0x14,0x12,0x0d,0x0b,0x0a,0x08,0x00,0x15,0x01,0x15,0x05,0x06,0x16, 0x2b,0x25,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x21,0x15,0x21,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x21,0x15,0x01,0x09,0x45,0x67,0x3a,0x3a,0x67,0x45,0x01,0x31,0xfe,0xcf,0x43,0x49,0x49,0x43,0x01,0x31,0x78,0x36,0x63,0x41,0x2c,0x42,0x62,0x36,0x52,0x48,0x42,0x28,0x42,0x48,0x52,0x00,0x01,0x00,0x50,0x00,0x37,0x02,0x21, 0x02,0x58,0x00,0x12,0x00,0x33,0x40,0x30,0x00,0x01,0x02,0x01,0x85,0x00,0x00,0x02,0x03,0x02,0x00,0x03,0x80,0x05,0x01,0x04,0x03,0x04,0x86,0x00,0x02,0x00,0x03,0x02,0x59,0x00,0x02,0x02,0x03,0x61,0x00,0x03,0x02,0x03,0x51,0x00,0x00,0x00,0x12,0x00,0x12,0x11,0x13,0x13,0x14,0x06,0x06,0x1a,0x2b,0x37,0x3e,0x02,0x37,0x2e,0x02,0x27, 0x33,0x1e,0x02,0x33,0x15,0x22,0x06,0x06,0x07,0x50,0x09,0x56,0x8f,0x5c,0x5c,0x8f,0x56,0x09,0x5a,0x09,0x62,0xa3,0x69,0x69,0xa3,0x62,0x09,0x37,0x4f,0x7a,0x48,0x07,0x05,0x45,0x73,0x4c,0x43,0x63,0x36,0x64,0x37,0x65,0x45,0x00,0x00,0x01,0x00,0x23,0x00,0x46,0x02,0x3a,0x02,0x8a,0x00,0x1b,0x00,0x32,0x40,0x2f,0x00,0x04,0x00,0x03, 0x02,0x04,0x03,0x67,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x05,0x05,0x00,0x57,0x00,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x00,0x00,0x00,0x1b,0x00,0x1a,0x21,0x24,0x11,0x14,0x21,0x07,0x06,0x1b,0x2b,0x37,0x35,0x21,0x32,0x36,0x36,0x35,0x35,0x21,0x35,0x21,0x35,0x34,0x26,0x26,0x23,0x21,0x35,0x21,0x32, 0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x23,0x23,0x01,0x31,0x28,0x3f,0x25,0xfe,0x43,0x01,0xbd,0x25,0x3f,0x28,0xfe,0xcf,0x01,0x31,0x3f,0x68,0x3f,0x3f,0x68,0x3f,0x46,0x50,0x27,0x40,0x25,0x1e,0x50,0x1e,0x25,0x40,0x27,0x50,0x39,0x63,0x3e,0x90,0x3e,0x63,0x39,0x00,0x00,0x00,0x02,0x00,0x37,0xff,0x4c,0x02,0x1c,0x02,0xda,0x00,0x0b, 0x00,0x11,0x00,0x3a,0x40,0x37,0x11,0x0e,0x08,0x03,0x02,0x01,0x06,0x02,0x01,0x01,0x4c,0x00,0x00,0x05,0x01,0x01,0x02,0x00,0x01,0x67,0x04,0x01,0x02,0x03,0x03,0x02,0x57,0x04,0x01,0x02,0x02,0x03,0x5f,0x06,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x10,0x0f,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x12,0x11,0x14,0x07,0x06,0x19,0x2b,0x17,0x35, 0x13,0x03,0x35,0x21,0x15,0x21,0x13,0x03,0x21,0x15,0x25,0x33,0x13,0x03,0x23,0x13,0x37,0xfa,0xfa,0x01,0xe5,0xfe,0xb4,0xfa,0xfa,0x01,0x4c,0xfe,0x46,0x41,0xfd,0xfd,0x41,0xfc,0xb4,0x32,0x01,0x94,0x01,0x96,0x32,0x2e,0xfe,0x62,0xfe,0x6c,0x2e,0x2e,0x01,0x98,0x01,0x9a,0xfe,0x66,0x00,0x00,0x00,0x01,0x00,0x1e,0x00,0x78,0x02,0x35, 0x02,0x58,0x00,0x15,0x00,0x28,0x40,0x25,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x03,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x15,0x00,0x14,0x21,0x25,0x21,0x05,0x06,0x19,0x2b,0x37,0x35,0x21,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x21,0x35,0x21,0x32,0x16,0x16,0x15,0x15, 0x14,0x06,0x06,0x23,0x1e,0x01,0x31,0x43,0x49,0x49,0x43,0xfe,0xcf,0x01,0x31,0x45,0x67,0x3a,0x3a,0x67,0x45,0x78,0x52,0x48,0x42,0x28,0x42,0x48,0x52,0x36,0x62,0x42,0x2c,0x41,0x63,0x36,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57, 0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x33,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xff,0xff,0x02,0x58,0xff,0x02,0x08,0x50,0x50,0xfd,0xf8,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x07,0x00,0x24,0x40,0x21,0x00,0x03,0x02,0x03, 0x85,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x02,0x01,0x4f,0x11,0x11,0x11,0x10,0x04,0x06,0x1a,0x2b,0x21,0x23,0x11,0x21,0x35,0x21,0x35,0x33,0x02,0x58,0x5a,0xfe,0x02,0x01,0xfe,0x5a,0x01,0x09,0x50,0xff,0x00,0x00,0x00,0x03,0x00,0x43,0xff,0x92,0x01,0xf4,0x03,0x3e,0x00,0x13, 0x00,0x16,0x00,0x1a,0x00,0x96,0xb5,0x15,0x01,0x02,0x03,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x33,0x00,0x05,0x04,0x05,0x85,0x00,0x08,0x07,0x07,0x08,0x71,0x06,0x01,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x0e,0x0a,0x02,0x02,0x0b,0x01,0x01,0x00,0x02,0x01,0x67,0x0c,0x01,0x00,0x07,0x07,0x00,0x57,0x0c,0x01,0x00,0x00,0x07,0x5f, 0x0d,0x09,0x02,0x07,0x00,0x07,0x4f,0x1b,0x40,0x32,0x00,0x05,0x04,0x05,0x85,0x00,0x08,0x07,0x08,0x86,0x06,0x01,0x04,0x00,0x03,0x02,0x04,0x03,0x67,0x0e,0x0a,0x02,0x02,0x0b,0x01,0x01,0x00,0x02,0x01,0x67,0x0c,0x01,0x00,0x07,0x07,0x00,0x57,0x0c,0x01,0x00,0x00,0x07,0x5f,0x0d,0x09,0x02,0x07,0x00,0x07,0x4f,0x59,0x40,0x1c,0x14, 0x14,0x00,0x00,0x1a,0x19,0x18,0x17,0x14,0x16,0x14,0x16,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x06,0x1f,0x2b,0x33,0x35,0x33,0x13,0x23,0x35,0x33,0x37,0x21,0x35,0x21,0x37,0x33,0x07,0x33,0x11,0x21,0x07,0x23,0x37,0x01,0x35,0x07,0x17,0x23,0x03,0x33,0x50,0x39,0x5f,0x75,0x93,0x53,0xfe,0xf7,0x01, 0x27,0x25,0x46,0x25,0x37,0xfe,0xbd,0x28,0x46,0x28,0x01,0x2f,0x4e,0x4e,0x6c,0x5f,0xcb,0x52,0x01,0x02,0x52,0xe2,0x52,0x64,0x64,0xfd,0x26,0x6e,0x6e,0x01,0xa6,0xd4,0xd4,0x52,0xfe,0xfe,0x00,0x03,0x00,0x1d,0xff,0xf6,0x02,0x3b,0x02,0x30,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x3c,0x40,0x39,0x00,0x01,0x06,0x01,0x00,0x03,0x01,0x00, 0x69,0x05,0x01,0x03,0x02,0x02,0x03,0x59,0x05,0x01,0x03,0x03,0x02,0x61,0x08,0x04,0x07,0x03,0x02,0x03,0x02,0x51,0x19,0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22, 0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0xe9,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x01,0x6f,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x01,0xb0,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0xfe,0x46,0x23,0x1e,0x1d,0x22, 0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x00,0x03,0x00,0x41,0x00,0x26,0x02,0x17,0x02,0x6f,0x00,0x1b,0x00,0x37,0x00,0x53,0x01,0x0c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x65,0x00,0x02,0x00,0x04,0x01,0x02,0x72,0x12,0x01,0x05,0x01,0x03,0x04,0x05,0x72,0x00,0x08,0x06,0x0a,0x07,0x08,0x72,0x13,0x01,0x0b,0x07,0x09, 0x0a,0x0b,0x72,0x00,0x0e,0x0c,0x10,0x0d,0x0e,0x72,0x14,0x01,0x11,0x0d,0x0f,0x10,0x11,0x72,0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00,0x06,0x00,0x0a,0x07,0x06,0x0a,0x69,0x00,0x07,0x00,0x09,0x0c,0x07,0x09,0x6a,0x00,0x0c,0x00,0x10,0x0d,0x0c,0x10,0x69,0x00,0x0d,0x11,0x0f,0x0d,0x59, 0x00,0x0d,0x0d,0x0f,0x62,0x00,0x0f,0x0d,0x0f,0x52,0x1b,0x40,0x6b,0x00,0x02,0x00,0x04,0x00,0x02,0x04,0x80,0x12,0x01,0x05,0x01,0x03,0x01,0x05,0x03,0x80,0x00,0x08,0x06,0x0a,0x06,0x08,0x0a,0x80,0x13,0x01,0x0b,0x07,0x09,0x07,0x0b,0x09,0x80,0x00,0x0e,0x0c,0x10,0x0c,0x0e,0x10,0x80,0x14,0x01,0x11,0x0d,0x0f,0x0d,0x11,0x0f,0x80, 0x00,0x00,0x00,0x04,0x01,0x00,0x04,0x69,0x00,0x01,0x00,0x03,0x06,0x01,0x03,0x6a,0x00,0x06,0x00,0x0a,0x07,0x06,0x0a,0x69,0x00,0x07,0x00,0x09,0x0c,0x07,0x09,0x6a,0x00,0x0c,0x00,0x10,0x0d,0x0c,0x10,0x69,0x00,0x0d,0x11,0x0f,0x0d,0x59,0x00,0x0d,0x0d,0x0f,0x62,0x00,0x0f,0x0d,0x0f,0x52,0x59,0x40,0x2e,0x38,0x38,0x1c,0x1c,0x00, 0x00,0x38,0x53,0x38,0x53,0x50,0x4e,0x4b,0x49,0x46,0x45,0x42,0x40,0x3d,0x3b,0x1c,0x37,0x1c,0x37,0x34,0x32,0x2f,0x2d,0x2a,0x29,0x26,0x24,0x21,0x1f,0x00,0x1b,0x00,0x1b,0x23,0x23,0x13,0x23,0x23,0x15,0x06,0x1b,0x2b,0x13,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x23, 0x22,0x06,0x15,0x15,0x07,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x07,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x41,0x46,0x3c,0x26,0x39,0x2e,0x2b,0x18, 0x16,0x19,0x55,0x46,0x3c,0x26,0x39,0x2f,0x2b,0x17,0x16,0x19,0x55,0x46,0x3c,0x26,0x39,0x2e,0x2b,0x18,0x16,0x19,0x55,0x46,0x3c,0x26,0x39,0x2f,0x2b,0x17,0x16,0x19,0x55,0x46,0x3c,0x26,0x39,0x2e,0x2b,0x18,0x16,0x19,0x55,0x46,0x3c,0x26,0x39,0x2f,0x2b,0x17,0x16,0x19,0x01,0xd9,0x0f,0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0x0f, 0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0xd7,0x0f,0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0x0f,0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0xd7,0x0f,0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0x0f,0x3e,0x49,0x18,0x20,0x18,0x18,0x15,0x1e,0x00,0x00,0x00,0x02,0x00,0x32,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x07,0x00,0x10,0x00,0x33, 0x40,0x30,0x0b,0x01,0x03,0x04,0x01,0x4c,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x01,0x03,0x04,0x03,0x86,0x00,0x01,0x04,0x04,0x01,0x57,0x00,0x01,0x01,0x04,0x5f,0x00,0x04,0x01,0x04,0x4f,0x00,0x00,0x10,0x0f,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x06,0x06,0x19,0x2b,0x33,0x03,0x33,0x17,0x33,0x37,0x33,0x03,0x27,0x16,0x16,0x17,0x36, 0x36,0x37,0x37,0x23,0xef,0xbd,0x5b,0x32,0xd9,0x32,0x5c,0xbe,0x60,0x0d,0x13,0x04,0x05,0x12,0x0d,0x36,0xb4,0x02,0xda,0xca,0xca,0xfd,0x26,0xeb,0x34,0x5a,0x17,0x17,0x59,0x34,0xda,0x00,0x00,0x03,0xff,0xf6,0x00,0x19,0x02,0x62,0x02,0x83,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x41,0x40,0x3e,0x00,0x01,0x06,0x01,0x00,0x03,0x01,0x00, 0x69,0x00,0x03,0x07,0x01,0x02,0x05,0x03,0x02,0x69,0x00,0x05,0x04,0x04,0x05,0x59,0x00,0x05,0x05,0x04,0x61,0x08,0x01,0x04,0x05,0x04,0x51,0x19,0x18,0x0d,0x0c,0x01,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16, 0x15,0x14,0x06,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x1c,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xfe,0xf1,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0xfe,0xf0,0x20,0x27,0x27,0x20,0x20,0x26,0x26,0x01,0xf7,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27, 0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0xef,0x27,0x1f,0x20,0x26,0x26,0x20,0x1f,0x27,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x07,0x00,0x21,0x40,0x1e,0x00,0x00,0x01,0x00,0x85,0x03,0x01,0x01,0x02,0x02,0x01,0x57,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x11,0x11,0x11,0x10,0x04, 0x06,0x1a,0x2b,0x13,0x33,0x11,0x33,0x15,0x21,0x35,0x33,0xff,0x5a,0xff,0xfd,0xa8,0xff,0x02,0x58,0xfd,0xf8,0x50,0x50,0x00,0x00,0x02,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0xbc,0x00,0x0c,0x00,0x10,0x00,0x39,0x40,0x36,0x06,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x05,0x01,0x02,0x03,0x02,0x85,0x00,0x03,0x04,0x04, 0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x06,0x01,0x04,0x03,0x04,0x4f,0x0d,0x0d,0x00,0x00,0x0d,0x10,0x0d,0x10,0x0f,0x0e,0x00,0x0c,0x00,0x0c,0x18,0x11,0x07,0x06,0x18,0x2b,0x37,0x03,0x33,0x13,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x33,0x03,0x05,0x35,0x21,0x15,0xef,0xb3,0x5c,0x75,0x0c,0x11,0x04,0x04,0x12,0x0b,0x72,0x5b,0xb3,0xfe, 0xec,0x01,0xae,0xc8,0x01,0xf4,0xfe,0xc0,0x20,0x3e,0x11,0x11,0x3e,0x20,0x01,0x40,0xfe,0x0c,0xc8,0x50,0x50,0x00,0x00,0x00,0x00,0x06,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x1a,0x00,0x25,0x00,0x32,0x00,0x3f,0x00,0x4b,0x00,0x40,0x40,0x3d,0x4a,0x46,0x42,0x3e,0x3a,0x36,0x30,0x2c,0x27,0x25,0x22,0x1e,0x1a,0x17, 0x13,0x0f,0x02,0x01,0x01,0x4c,0x00,0x01,0x02,0x01,0x85,0x04,0x01,0x02,0x00,0x00,0x02,0x59,0x04,0x01,0x02,0x02,0x00,0x61,0x03,0x01,0x00,0x02,0x00,0x51,0x41,0x40,0x01,0x00,0x40,0x4b,0x41,0x4b,0x09,0x07,0x00,0x0f,0x01,0x0f,0x05,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06, 0x03,0x16,0x16,0x17,0x26,0x26,0x35,0x35,0x06,0x06,0x07,0x25,0x14,0x06,0x07,0x36,0x36,0x37,0x37,0x26,0x26,0x27,0x13,0x17,0x36,0x36,0x35,0x34,0x27,0x07,0x06,0x06,0x07,0x16,0x16,0x25,0x14,0x16,0x17,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x06,0x01,0x32,0x37,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x16,0x01,0x2c,0x58,0x8d, 0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0xd9,0x11,0x38,0x17,0x05,0x05,0x3c,0x60,0x1c,0x01,0x0c,0x06,0x05,0x18,0x37,0x12,0x62,0x1c,0x60,0x3c,0x55,0x3b,0x23,0x27,0x05,0x62,0x12,0x3e,0x1c,0x14,0x2e,0xfe,0x89,0x27,0x23,0x3b,0x0d,0x2d,0x14,0x1c,0x3e,0x12,0x62,0x05,0x01,0x04,0x3f,0x36,0x3b,0x0c,0x22,0x0c,0x0c,0x22,0x0c, 0x3b,0x36,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x01,0x96,0x06,0x1a,0x0e,0x1a,0x37,0x13,0x6b,0x09,0x42,0x32,0x12,0x13,0x37,0x1a,0x0e,0x1a,0x06,0x24,0x32,0x42,0x09,0xfe,0x9b,0x55,0x23,0x5f,0x37,0x1b,0x1b,0x25,0x07,0x10,0x04,0x14,0x35,0x53,0x37,0x5f,0x23,0x55,0x12,0x34,0x14,0x04,0x10,0x07,0x25, 0x1b,0xfe,0xe1,0x1a,0x56,0x11,0x3c,0x1a,0x1a,0x3b,0x12,0x56,0x1a,0x00,0x00,0x00,0x00,0x03,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x18,0x00,0x21,0x00,0x42,0x40,0x3f,0x00,0x01,0x07,0x01,0x02,0x03,0x01,0x02,0x69,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x67,0x08,0x01,0x04,0x00,0x00,0x04,0x59,0x08,0x01,0x04,0x04, 0x00,0x61,0x06,0x01,0x00,0x04,0x00,0x51,0x1a,0x19,0x11,0x10,0x01,0x00,0x1e,0x1d,0x19,0x21,0x1a,0x21,0x15,0x14,0x10,0x18,0x11,0x18,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x22,0x06,0x06,0x07,0x21,0x2e,0x02,0x03,0x32,0x36,0x36, 0x37,0x21,0x1e,0x02,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x43,0x6e,0x47,0x09,0x02,0x02,0x09,0x47,0x6e,0x43,0x43,0x6e,0x47,0x09,0xfd,0xfe,0x09,0x47,0x6e,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x02,0x3a,0x39,0x63,0x40,0x40,0x63,0x39,0xfd,0xf8,0x39,0x63,0x40,0x40, 0x63,0x39,0x00,0x00,0x00,0x04,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x16,0x00,0x20,0x00,0x27,0x00,0x4e,0x40,0x4b,0x00,0x01,0x09,0x01,0x02,0x03,0x01,0x02,0x69,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x67,0x00,0x04,0x00,0x07,0x06,0x04,0x07,0x67,0x0a,0x01,0x06,0x00,0x00,0x06,0x59,0x0a,0x01,0x06,0x06,0x00,0x61, 0x08,0x01,0x00,0x06,0x00,0x51,0x22,0x21,0x11,0x10,0x01,0x00,0x25,0x24,0x21,0x27,0x22,0x27,0x1f,0x1e,0x1a,0x19,0x14,0x13,0x10,0x16,0x11,0x16,0x09,0x07,0x00,0x0f,0x01,0x0f,0x0b,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x22,0x06,0x07,0x21,0x26,0x26,0x01,0x14,0x17, 0x21,0x36,0x35,0x34,0x27,0x21,0x06,0x01,0x32,0x36,0x37,0x21,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4b,0x78,0x20,0x01,0xc6,0x20,0x78,0xfe,0xb1,0x04,0x02,0x00,0x04,0x04,0xfe,0x00,0x04,0x01,0x04,0x4b,0x78,0x20,0xfe,0x3a,0x20,0x78,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59, 0x58,0x8d,0x51,0x02,0x3a,0x47,0x3b,0x3b,0x47,0xfe,0xfc,0x1a,0x18,0x18,0x1a,0x1a,0x18,0x18,0xfe,0xe2,0x47,0x3b,0x3b,0x47,0x00,0x03,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x19,0x00,0x23,0x00,0x3a,0x40,0x37,0x22,0x21,0x14,0x13,0x04,0x03,0x02,0x01,0x4c,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x69,0x05,0x01,0x03, 0x00,0x00,0x03,0x59,0x05,0x01,0x03,0x03,0x00,0x61,0x04,0x01,0x00,0x03,0x00,0x51,0x1b,0x1a,0x01,0x00,0x1a,0x23,0x1b,0x23,0x17,0x15,0x09,0x07,0x00,0x0f,0x01,0x0f,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x14,0x16,0x17,0x01,0x26,0x23,0x22,0x06,0x06,0x01,0x32, 0x36,0x36,0x35,0x34,0x26,0x27,0x01,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0xfe,0xa3,0x2f,0x28,0x01,0x21,0x36,0x3e,0x4a,0x76,0x44,0x01,0x04,0x4a,0x76,0x44,0x33,0x2b,0xfe,0xde,0x39,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x01,0x36,0x3c,0x66,0x23,0x01,0xaf,0x1a,0x44, 0x76,0xfe,0xb2,0x44,0x76,0x4a,0x3f,0x69,0x23,0xfe,0x4f,0x1e,0x00,0x03,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x1f,0x00,0x23,0x00,0x42,0x40,0x3f,0x00,0x01,0x00,0x03,0x04,0x01,0x03,0x69,0x00,0x04,0x08,0x01,0x05,0x02,0x04,0x05,0x67,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01, 0x00,0x02,0x00,0x51,0x20,0x20,0x11,0x10,0x01,0x00,0x20,0x23,0x20,0x23,0x22,0x21,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16, 0x27,0x35,0x21,0x15,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x56,0x01,0x40,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0xdc,0x50,0x50,0x00,0x00,0x00, 0x00,0x05,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x17,0x00,0x1f,0x00,0x27,0x00,0x2f,0x00,0x46,0x40,0x43,0x2d,0x2c,0x2b,0x25,0x24,0x23,0x1f,0x19,0x15,0x14,0x13,0x0b,0x03,0x02,0x01,0x4c,0x00,0x01,0x05,0x01,0x02,0x03,0x01,0x02,0x69,0x06,0x01,0x03,0x00,0x00,0x03,0x59,0x06,0x01,0x03,0x03,0x00,0x61,0x04,0x01, 0x00,0x03,0x00,0x51,0x29,0x28,0x11,0x10,0x01,0x00,0x28,0x2f,0x29,0x2f,0x10,0x17,0x11,0x17,0x09,0x07,0x00,0x0f,0x01,0x0f,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x22,0x06,0x07,0x17,0x37,0x26,0x26,0x13,0x17,0x36,0x36,0x35,0x34,0x26,0x27,0x05,0x14,0x16,0x17, 0x37,0x27,0x06,0x06,0x01,0x32,0x36,0x37,0x27,0x07,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x2e,0x51,0x21,0x9e,0x9f,0x20,0x50,0x04,0x9f,0x19,0x1b,0x1b,0x18,0xfe,0x2b,0x1a,0x18,0x9c,0x9c,0x18,0x1a,0x01,0x04,0x2d,0x4f,0x20,0x9e,0x9d,0x21,0x50,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51, 0x8c,0x59,0x58,0x8d,0x51,0x02,0x3a,0x1b,0x19,0x9d,0x9f,0x18,0x1a,0xfe,0xfb,0x9e,0x20,0x51,0x2e,0x2e,0x50,0x21,0x9f,0x2d,0x50,0x20,0x9c,0x9d,0x20,0x4f,0xfe,0xcf,0x1a,0x17,0x9f,0x9d,0x18,0x1b,0x00,0x00,0x00,0x03,0xff,0xf6,0x00,0x00,0x02,0x62,0x02,0x6c,0x00,0x0f,0x00,0x1f,0x00,0x2b,0x00,0x42,0x40,0x3f,0x00,0x01,0x00,0x03, 0x05,0x01,0x03,0x69,0x00,0x05,0x08,0x01,0x04,0x02,0x05,0x04,0x69,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x02,0x00,0x51,0x21,0x20,0x11,0x10,0x01,0x00,0x27,0x25,0x20,0x2b,0x21,0x2b,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x21,0x22,0x26,0x26, 0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44, 0x76,0x4a,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0xcc,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x00,0x00,0x05,0xff,0xf6,0x00,0x14,0x02,0x62,0x02,0x80,0x00,0x0f,0x00,0x15,0x00,0x1b,0x00,0x21,0x00,0x27, 0x00,0x4b,0x40,0x48,0x17,0x15,0x02,0x02,0x01,0x27,0x1d,0x02,0x00,0x04,0x02,0x4c,0x00,0x01,0x02,0x01,0x85,0x06,0x01,0x00,0x04,0x00,0x86,0x07,0x03,0x02,0x02,0x04,0x04,0x02,0x57,0x07,0x03,0x02,0x02,0x02,0x04,0x5f,0x05,0x08,0x02,0x04,0x02,0x04,0x4f,0x1c,0x1c,0x16,0x16,0x01,0x00,0x23,0x22,0x1c,0x21,0x1c,0x21,0x16,0x1b,0x16, 0x1b,0x11,0x10,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x33,0x2e,0x02,0x27,0x07,0x35,0x0e,0x02,0x07,0x05,0x15,0x3e,0x02,0x37,0x21,0x23,0x1e,0x02,0x17,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x2d,0xd5, 0x08,0x3a,0x5b,0x38,0x58,0x38,0x5b,0x3a,0x08,0x01,0x2d,0x38,0x5b,0x3a,0x08,0xfe,0xd3,0xd5,0x08,0x3a,0x5b,0x38,0x14,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x01,0x5e,0x39,0x5b,0x3c,0x09,0xd9,0xd9,0x09,0x3c,0x5b,0x39,0x50,0xd9,0x09,0x3c,0x5b,0x39,0x39,0x5b,0x3c,0x09,0x00,0x00,0x00,0x00,0x01,0x00,0x28, 0x00,0x00,0x02,0x30,0x02,0xe4,0x00,0x0e,0x00,0x15,0x40,0x12,0x0e,0x0d,0x0c,0x0b,0x07,0x04,0x00,0x07,0x00,0x4a,0x00,0x00,0x00,0x76,0x15,0x01,0x06,0x17,0x2b,0x01,0x27,0x26,0x26,0x27,0x11,0x23,0x11,0x06,0x06,0x07,0x07,0x35,0x25,0x05,0x02,0x30,0xb4,0x10,0x16,0x02,0x50,0x04,0x14,0x0e,0xb6,0x01,0x03,0x01,0x05,0x01,0x99,0xa0, 0x0e,0x1c,0x07,0xfd,0x96,0x02,0x6a,0x09,0x1c,0x0c,0xa2,0x6b,0xe2,0xe1,0x00,0x00,0x00,0x01,0x00,0x2f,0x00,0xed,0x02,0x1c,0x02,0xda,0x00,0x0e,0x00,0x26,0x40,0x23,0x0a,0x09,0x08,0x04,0x03,0x05,0x01,0x49,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x0e,0x00,0x0c,0x11, 0x03,0x06,0x17,0x2b,0x13,0x37,0x21,0x11,0x07,0x11,0x34,0x36,0x37,0x01,0x27,0x01,0x06,0x06,0x23,0x4c,0x4f,0x01,0x81,0x53,0x05,0x05,0xfe,0x95,0x39,0x01,0x6e,0x0a,0x24,0x14,0x02,0x8b,0x4f,0xfe,0x7b,0x53,0x01,0x1a,0x10,0x22,0x0b,0xfe,0x94,0x39,0x01,0x6e,0x07,0x02,0x00,0x01,0x00,0x14,0x00,0x32,0x02,0x4e,0x02,0x62,0x00,0x0d, 0x00,0x30,0x40,0x2d,0x0c,0x01,0x00,0x01,0x01,0x4c,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0d,0x00,0x0d,0x14,0x11,0x13,0x05,0x06,0x19,0x2b,0x25,0x37,0x36,0x37,0x21,0x35,0x21,0x26,0x26,0x27,0x27,0x33,0x13,0x03, 0x01,0x0a,0x9e,0x1a,0x1a,0xfe,0x38,0x01,0xc3,0x0c,0x19,0x0a,0x9e,0x69,0xdb,0xdc,0x32,0xc9,0x22,0x05,0x50,0x05,0x14,0x0d,0xca,0xfe,0xe9,0xfe,0xe7,0x00,0x00,0x00,0x00,0x01,0x00,0x2f,0x00,0x00,0x02,0x1c,0x01,0xed,0x00,0x0e,0x00,0x20,0x40,0x1d,0x0c,0x0b,0x07,0x06,0x05,0x05,0x00,0x4a,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00, 0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x1a,0x30,0x02,0x06,0x18,0x2b,0x37,0x21,0x32,0x16,0x17,0x01,0x37,0x01,0x26,0x26,0x35,0x11,0x17,0x11,0x21,0x4c,0x01,0x0f,0x14,0x24,0x0a,0xfe,0x92,0x39,0x01,0x6b,0x05,0x05,0x53,0xfe,0x7f,0x4f,0x02,0x07,0x01,0x6e,0x39,0xfe,0x94,0x0b,0x22,0x10,0x01,0x1a,0x53,0xfe,0x7b,0x00,0x00,0x00, 0x00,0x01,0x00,0x28,0xff,0xf6,0x02,0x30,0x02,0xda,0x00,0x0e,0x00,0x15,0x40,0x12,0x0b,0x08,0x04,0x03,0x02,0x01,0x00,0x07,0x00,0x49,0x00,0x00,0x00,0x76,0x19,0x01,0x06,0x17,0x2b,0x01,0x15,0x05,0x25,0x35,0x17,0x16,0x16,0x17,0x11,0x33,0x11,0x36,0x36,0x37,0x02,0x30,0xfe,0xfb,0xfe,0xfd,0xb6,0x0e,0x14,0x04,0x50,0x02,0x16,0x10, 0x01,0x41,0x6a,0xe1,0xe2,0x6b,0xa2,0x0c,0x1c,0x09,0x02,0x6a,0xfd,0x96,0x08,0x1b,0x0e,0x00,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0x00,0x02,0x29,0x01,0xed,0x00,0x0e,0x00,0x27,0x40,0x24,0x0a,0x09,0x08,0x04,0x03,0x05,0x01,0x4a,0x02,0x01,0x01,0x00,0x00,0x01,0x57,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00, 0x00,0x0e,0x00,0x0c,0x11,0x03,0x06,0x17,0x2b,0x25,0x07,0x21,0x11,0x37,0x11,0x14,0x06,0x07,0x01,0x17,0x01,0x36,0x36,0x33,0x02,0x0c,0x4f,0xfe,0x7f,0x53,0x05,0x05,0x01,0x6b,0x39,0xfe,0x92,0x0b,0x23,0x14,0x4f,0x4f,0x01,0x85,0x53,0xfe,0xe6,0x10,0x22,0x0b,0x01,0x6c,0x39,0xfe,0x92,0x07,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x0a, 0x00,0x32,0x02,0x44,0x02,0x62,0x00,0x0d,0x00,0x2a,0x40,0x27,0x02,0x01,0x03,0x02,0x01,0x4c,0x00,0x01,0x02,0x01,0x85,0x00,0x00,0x03,0x00,0x86,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x02,0x03,0x4f,0x11,0x14,0x12,0x10,0x04,0x06,0x1a,0x2b,0x25,0x23,0x03,0x13,0x33,0x07,0x06,0x06,0x07,0x21,0x15,0x21, 0x16,0x17,0x01,0x4e,0x68,0xdc,0xdb,0x69,0x9e,0x0a,0x19,0x0c,0x01,0xc3,0xfe,0x38,0x1a,0x1a,0x32,0x01,0x19,0x01,0x17,0xca,0x0d,0x14,0x05,0x50,0x05,0x22,0x00,0x00,0x00,0x01,0x00,0x3c,0x00,0xed,0x02,0x29,0x02,0xda,0x00,0x0e,0x00,0x20,0x40,0x1d,0x0c,0x0b,0x07,0x06,0x05,0x05,0x00,0x49,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01, 0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1a,0x30,0x02,0x06,0x18,0x2b,0x01,0x21,0x22,0x26,0x27,0x01,0x07,0x01,0x16,0x16,0x15,0x11,0x27,0x11,0x21,0x02,0x0c,0xfe,0xf1,0x14,0x23,0x0b,0x01,0x6e,0x39,0xfe,0x95,0x05,0x05,0x53,0x01,0x81,0x02,0x8b,0x02,0x07,0xfe,0x92,0x39,0x01,0x6c,0x0b,0x22,0x10,0xfe,0xe6,0x53,0x01,0x85,0x00, 0x00,0x01,0xff,0xb0,0x00,0x32,0x02,0xa8,0x02,0x62,0x00,0x17,0x00,0x35,0x40,0x32,0x12,0x05,0x02,0x05,0x02,0x01,0x4c,0x03,0x01,0x01,0x02,0x01,0x85,0x04,0x01,0x00,0x05,0x00,0x86,0x00,0x02,0x05,0x05,0x02,0x57,0x00,0x02,0x02,0x05,0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x00,0x00,0x00,0x17,0x00,0x17,0x12,0x14,0x14,0x12,0x13,0x07, 0x06,0x1b,0x2b,0x13,0x16,0x17,0x17,0x23,0x03,0x13,0x33,0x07,0x06,0x06,0x07,0x21,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x23,0x37,0x36,0x37,0x22,0x1a,0x1a,0x9e,0x68,0xdc,0xdb,0x69,0x9e,0x0a,0x19,0x0c,0x02,0x0a,0x0c,0x19,0x0a,0x9e,0x69,0xdb,0xdc,0x68,0x9e,0x1a,0x1a,0x01,0x22,0x05,0x22,0xc9,0x01,0x19,0x01,0x17,0xca,0x0d,0x14, 0x05,0x05,0x14,0x0d,0xca,0xfe,0xe9,0xfe,0xe7,0xc9,0x22,0x05,0x00,0x01,0x00,0x28,0xff,0x56,0x02,0x30,0x03,0x84,0x00,0x19,0x00,0x06,0xb3,0x19,0x0c,0x01,0x32,0x2b,0x37,0x35,0x17,0x16,0x16,0x17,0x11,0x06,0x06,0x07,0x07,0x35,0x25,0x05,0x15,0x27,0x26,0x26,0x27,0x11,0x36,0x36,0x37,0x37,0x15,0x05,0x28,0xb6,0x0e,0x14,0x04,0x04, 0x14,0x0e,0xb6,0x01,0x03,0x01,0x05,0xb4,0x10,0x16,0x02,0x02,0x16,0x10,0xb4,0xfe,0xfb,0x38,0x6b,0xa2,0x0c,0x1c,0x09,0x03,0x3a,0x09,0x1c,0x0c,0xa2,0x6b,0xe2,0xe1,0x6a,0xa0,0x0e,0x1c,0x07,0xfc,0xc6,0x08,0x1b,0x0e,0xa0,0x6a,0xe1,0x00,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0xa0,0x02,0x4e,0x01,0xbd,0x00,0x21,0x00,0x7d,0x40,0x0a, 0x11,0x01,0x02,0x03,0x14,0x01,0x06,0x00,0x02,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x29,0x08,0x01,0x07,0x01,0x04,0x06,0x07,0x72,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x67,0x00,0x00,0x00,0x06,0x01,0x00,0x06,0x69,0x00,0x01,0x07,0x04,0x01,0x59,0x00,0x01,0x01,0x04,0x61,0x05,0x01,0x04,0x01,0x04,0x51,0x1b,0x40,0x2a,0x08,0x01,0x07, 0x01,0x04,0x01,0x07,0x04,0x80,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x67,0x00,0x00,0x00,0x06,0x01,0x00,0x06,0x69,0x00,0x01,0x07,0x04,0x01,0x59,0x00,0x01,0x01,0x04,0x61,0x05,0x01,0x04,0x01,0x04,0x51,0x59,0x40,0x10,0x00,0x00,0x00,0x21,0x00,0x21,0x24,0x23,0x12,0x11,0x12,0x24,0x23,0x09,0x06,0x1d,0x2b,0x37,0x35,0x34,0x36,0x33, 0x32,0x1e,0x03,0x33,0x32,0x37,0x37,0x23,0x35,0x33,0x17,0x15,0x23,0x35,0x07,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x06,0x15,0x15,0x0a,0x4c,0x3a,0x23,0x2c,0x1d,0x15,0x17,0x11,0x1d,0x1c,0x55,0x8c,0xcd,0x46,0x50,0x4d,0x33,0x47,0x22,0x2c,0x1c,0x16,0x18,0x12,0x14,0x1f,0xa5,0x31,0x3d,0x4b,0x17,0x21,0x21,0x17,0x21,0x60,0x4e,0x46, 0xd7,0xa1,0x60,0x41,0x17,0x21,0x21,0x17,0x20,0x1a,0x31,0x00,0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e,0x01,0xc7,0x00,0x25,0x00,0x7f,0x40,0x0c,0x14,0x02,0x02,0x01,0x07,0x15,0x01,0x02,0x06,0x01,0x02,0x4c,0x4b,0xb0,0x0b,0x50,0x58,0x40,0x29,0x04,0x01,0x00,0x02,0x00,0x85,0x0a,0x09,0x02,0x05,0x06,0x06,0x05,0x71,0x00,0x02,0x00, 0x07,0x01,0x02,0x07,0x69,0x03,0x01,0x01,0x06,0x06,0x01,0x59,0x03,0x01,0x01,0x01,0x06,0x62,0x08,0x01,0x06,0x01,0x06,0x52,0x1b,0x40,0x28,0x04,0x01,0x00,0x02,0x00,0x85,0x0a,0x09,0x02,0x05,0x06,0x05,0x86,0x00,0x02,0x00,0x07,0x01,0x02,0x07,0x69,0x03,0x01,0x01,0x06,0x06,0x01,0x59,0x03,0x01,0x01,0x01,0x06,0x62,0x08,0x01,0x06, 0x01,0x06,0x52,0x59,0x40,0x12,0x00,0x00,0x00,0x25,0x00,0x25,0x23,0x23,0x21,0x13,0x11,0x23,0x23,0x21,0x13,0x0b,0x06,0x1f,0x2b,0x37,0x27,0x35,0x37,0x33,0x07,0x33,0x32,0x3e,0x02,0x33,0x32,0x1e,0x02,0x33,0x33,0x27,0x33,0x17,0x15,0x07,0x23,0x37,0x23,0x22,0x2e,0x02,0x23,0x22,0x0e,0x02,0x23,0x23,0x17,0x8d,0x83,0x83,0x5e,0x98, 0x34,0x11,0x1e,0x22,0x2b,0x1f,0x1f,0x2b,0x22,0x1e,0x11,0x47,0x98,0x69,0x79,0x79,0x68,0x6e,0x1e,0x24,0x2b,0x1c,0x1b,0x15,0x15,0x1b,0x1b,0x29,0x23,0x0d,0x6e,0x5f,0x91,0x46,0x91,0xa5,0x20,0x2b,0x20,0x20,0x2b,0x20,0xa5,0x91,0x46,0x91,0x74,0x20,0x29,0x20,0x20,0x29,0x20,0x74,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e, 0x01,0xc7,0x00,0x11,0x00,0x68,0xb6,0x04,0x03,0x02,0x05,0x02,0x01,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x22,0x03,0x01,0x01,0x02,0x02,0x01,0x70,0x06,0x01,0x00,0x05,0x05,0x00,0x71,0x04,0x01,0x02,0x05,0x05,0x02,0x57,0x04,0x01,0x02,0x02,0x05,0x60,0x08,0x07,0x02,0x05,0x02,0x05,0x50,0x1b,0x40,0x20,0x03,0x01,0x01,0x02,0x01,0x85, 0x06,0x01,0x00,0x05,0x00,0x86,0x04,0x01,0x02,0x05,0x05,0x02,0x57,0x04,0x01,0x02,0x02,0x05,0x60,0x08,0x07,0x02,0x05,0x02,0x05,0x50,0x59,0x40,0x10,0x00,0x00,0x00,0x11,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x13,0x11,0x09,0x06,0x1d,0x2b,0x37,0x17,0x23,0x27,0x35,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x21,0x15,0x21,0x17,0x23,0x27, 0x69,0x82,0x5e,0x83,0x83,0x5f,0x83,0x81,0x81,0x61,0x88,0x01,0x0a,0xfe,0xf5,0x88,0x60,0x81,0xeb,0x8c,0x91,0x46,0x91,0x8c,0x8c,0x8c,0x50,0x8c,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e,0x01,0xc7,0x00,0x11,0x00,0x61,0xb6,0x0f,0x0e,0x02,0x00,0x03,0x01,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x21,0x06,0x01,0x04, 0x03,0x03,0x04,0x70,0x07,0x01,0x01,0x00,0x00,0x01,0x71,0x05,0x01,0x03,0x00,0x00,0x03,0x57,0x05,0x01,0x03,0x03,0x00,0x60,0x02,0x01,0x00,0x03,0x00,0x50,0x1b,0x40,0x1f,0x06,0x01,0x04,0x03,0x04,0x85,0x07,0x01,0x01,0x00,0x01,0x86,0x05,0x01,0x03,0x00,0x00,0x03,0x57,0x05,0x01,0x03,0x03,0x00,0x60,0x02,0x01,0x00,0x03,0x00,0x50, 0x59,0x40,0x0b,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x08,0x06,0x1e,0x2b,0x25,0x23,0x07,0x23,0x37,0x21,0x35,0x21,0x27,0x33,0x17,0x33,0x27,0x33,0x17,0x15,0x07,0x23,0x01,0xef,0x81,0x81,0x60,0x88,0xfe,0xf5,0x01,0x0a,0x88,0x61,0x81,0x81,0x83,0x5f,0x83,0x83,0x5e,0xeb,0x8c,0x8c,0x50,0x8c,0x8c,0x8c,0x91,0x46,0x91,0x00,0x00, 0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e,0x01,0xc7,0x00,0x0e,0x00,0x61,0xb7,0x0b,0x04,0x03,0x03,0x05,0x02,0x01,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x1f,0x03,0x01,0x01,0x02,0x02,0x01,0x70,0x04,0x01,0x00,0x05,0x05,0x00,0x71,0x00,0x02,0x05,0x05,0x02,0x57,0x00,0x02,0x02,0x05,0x60,0x06,0x01,0x05,0x02,0x05,0x50,0x1b,0x40,0x1d, 0x03,0x01,0x01,0x02,0x01,0x85,0x04,0x01,0x00,0x05,0x00,0x86,0x00,0x02,0x05,0x05,0x02,0x57,0x00,0x02,0x02,0x05,0x60,0x06,0x01,0x05,0x02,0x05,0x50,0x59,0x40,0x0e,0x00,0x00,0x00,0x0e,0x00,0x0e,0x12,0x11,0x11,0x13,0x11,0x07,0x06,0x1b,0x2b,0x37,0x17,0x23,0x27,0x35,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0x17,0x23,0x27,0x69,0x82, 0x5e,0x83,0x83,0x5f,0x83,0x01,0x00,0x7d,0x68,0x9c,0x9c,0x67,0x7d,0xeb,0x8c,0x91,0x46,0x91,0x8c,0x8c,0xb3,0xb5,0x8c,0x00,0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e,0x01,0xc7,0x00,0x0e,0x00,0x5a,0xb7,0x0c,0x0b,0x04,0x03,0x00,0x03,0x01,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x1e,0x04,0x01,0x02,0x03,0x03,0x02,0x70,0x05,0x01,0x01, 0x00,0x00,0x01,0x71,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x03,0x03,0x00,0x60,0x00,0x00,0x03,0x00,0x50,0x1b,0x40,0x1c,0x04,0x01,0x02,0x03,0x02,0x85,0x05,0x01,0x01,0x00,0x01,0x86,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x03,0x03,0x00,0x60,0x00,0x00,0x03,0x00,0x50,0x59,0x40,0x09,0x13,0x11,0x11,0x12,0x11,0x10,0x06,0x06,0x1c,0x2b, 0x25,0x21,0x07,0x23,0x37,0x27,0x33,0x17,0x21,0x27,0x33,0x17,0x15,0x07,0x23,0x01,0xef,0xfe,0xff,0x7d,0x67,0x9c,0x9c,0x68,0x7d,0x01,0x00,0x83,0x5f,0x83,0x83,0x5e,0xeb,0x8c,0xb5,0xb3,0x8c,0x8c,0x91,0x46,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x6e,0x00,0x00,0x01,0xea,0x02,0x26,0x00,0x0d,0x00,0x32,0x40,0x2f,0x0a,0x09,0x08,0x05, 0x04,0x03,0x06,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x0d,0x00,0x0d,0x14,0x14,0x11,0x05,0x06,0x19,0x2b,0x33,0x35,0x33,0x11,0x07,0x35,0x37,0x33,0x17,0x15,0x27,0x11,0x33,0x15,0x6e,0x92,0x92,0x9c,0x46,0x9a, 0x92,0x92,0x50,0x01,0x6a,0x84,0x65,0x8b,0x8a,0x66,0x83,0xfe,0x97,0x50,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x5f,0x02,0x4e,0x01,0xc7,0x00,0x0d,0x00,0x60,0xb6,0x08,0x07,0x02,0x04,0x01,0x01,0x4c,0x4b,0xb0,0x09,0x50,0x58,0x40,0x1f,0x02,0x01,0x00,0x01,0x01,0x00,0x70,0x06,0x05,0x02,0x03,0x04,0x04,0x03,0x71,0x00,0x01,0x04,0x04, 0x01,0x57,0x00,0x01,0x01,0x04,0x60,0x00,0x04,0x01,0x04,0x50,0x1b,0x40,0x1d,0x02,0x01,0x00,0x01,0x00,0x85,0x06,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x04,0x04,0x01,0x57,0x00,0x01,0x01,0x04,0x60,0x00,0x04,0x01,0x04,0x50,0x59,0x40,0x0e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x13,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x37,0x11, 0x33,0x15,0x21,0x27,0x33,0x17,0x15,0x07,0x23,0x37,0x21,0x15,0x0a,0x52,0x01,0x93,0x83,0x5f,0x83,0x83,0x5e,0x82,0xfe,0x6d,0x5f,0x01,0x68,0x8c,0x8c,0x91,0x46,0x91,0x8c,0x8c,0x00,0x00,0x00,0x01,0x00,0x6e,0x00,0x00,0x01,0xea,0x02,0x26,0x00,0x0d,0x00,0x2b,0x40,0x28,0x0b,0x0a,0x09,0x06,0x05,0x04,0x06,0x02,0x01,0x01,0x4c,0x00, 0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x00,0x01,0x4f,0x14,0x14,0x11,0x10,0x04,0x06,0x1a,0x2b,0x13,0x21,0x15,0x23,0x11,0x37,0x15,0x07,0x23,0x27,0x35,0x17,0x11,0x23,0x6e,0x01,0x7c,0x92,0x92,0x9a,0x46,0x9c,0x92,0x92,0x02,0x26,0x50,0xfe,0x97,0x83,0x66,0x8a,0x8b,0x65,0x84, 0x01,0x6a,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x82,0x02,0x44,0x02,0x12,0x00,0x03,0x00,0x12,0x00,0x2e,0x40,0x2b,0x0b,0x01,0x05,0x02,0x01,0x4c,0x03,0x01,0x01,0x02,0x01,0x85,0x04,0x01,0x00,0x05,0x00,0x86,0x00,0x02,0x05,0x05,0x02,0x57,0x00,0x02,0x02,0x05,0x60,0x00,0x05,0x02,0x05,0x50,0x14,0x12,0x14,0x11,0x11,0x10,0x06,0x06, 0x1c,0x2b,0x25,0x23,0x11,0x33,0x05,0x21,0x26,0x26,0x27,0x27,0x33,0x17,0x07,0x23,0x37,0x36,0x36,0x37,0x21,0x02,0x44,0x55,0x55,0xfd,0xbc,0x01,0x57,0x05,0x15,0x0b,0x65,0x61,0xa0,0xa0,0x61,0x66,0x08,0x14,0x08,0xfe,0xa9,0x82,0x01,0x90,0xa0,0x02,0x14,0x0d,0x7d,0xc8,0xc8,0x80,0x0a,0x12,0x04,0x00,0x00,0x00,0x00,0x01,0x00,0x0a, 0x00,0x6e,0x02,0x4e,0x02,0xda,0x00,0x1e,0x00,0x3d,0x40,0x3a,0x01,0x01,0x04,0x01,0x01,0x4c,0x00,0x00,0x02,0x01,0x02,0x00,0x01,0x80,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x69,0x00,0x01,0x04,0x04,0x01,0x57,0x00,0x01,0x01,0x04,0x60,0x00,0x04,0x01,0x04,0x50,0x00,0x00,0x00,0x1e,0x00,0x1e,0x26,0x21, 0x24,0x33,0x12,0x07,0x06,0x1b,0x2b,0x37,0x27,0x37,0x33,0x07,0x06,0x06,0x07,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x23,0x16,0x16,0x17,0x17,0xaa,0xa0,0xa0,0x61,0x65,0x0a,0x16,0x05,0xcb,0x4b,0x5d,0x5d,0x4b,0x1e,0x1e,0x4d,0x74,0x41,0x41,0x74,0x4d,0xcb,0x08,0x14,0x08,0x66, 0x6e,0xc8,0xc8,0x7d,0x0d,0x14,0x02,0x50,0x46,0x45,0x51,0x50,0x3f,0x69,0x3e,0x46,0x68,0x38,0x04,0x12,0x0a,0x80,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x6e,0x02,0x4e,0x02,0xda,0x00,0x1e,0x00,0x37,0x40,0x34,0x1e,0x01,0x01,0x04,0x01,0x4c,0x00,0x05,0x03,0x04,0x03,0x05,0x04,0x80,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x00,0x03,0x05, 0x02,0x03,0x69,0x00,0x04,0x01,0x01,0x04,0x57,0x00,0x04,0x04,0x01,0x60,0x00,0x01,0x04,0x01,0x50,0x14,0x24,0x21,0x26,0x24,0x10,0x06,0x06,0x1c,0x2b,0x25,0x23,0x37,0x36,0x36,0x37,0x23,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x26,0x26,0x27,0x27,0x33,0x17,0x01,0xae,0x61,0x66, 0x08,0x14,0x08,0xcb,0x4c,0x75,0x41,0x41,0x75,0x4c,0x1e,0x1e,0x4b,0x5d,0x5d,0x4b,0xcb,0x05,0x15,0x0b,0x65,0x61,0xa0,0x6e,0x80,0x0a,0x12,0x04,0x38,0x68,0x46,0x3e,0x69,0x3f,0x50,0x51,0x45,0x46,0x50,0x02,0x14,0x0d,0x7d,0xc8,0x00,0x01,0x00,0xff,0xff,0x4c,0x01,0xf4,0x03,0x47,0x00,0x05,0x00,0x18,0x40,0x15,0x04,0x03,0x02,0x01, 0x04,0x00,0x4a,0x01,0x01,0x00,0x00,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x02,0x06,0x16,0x2b,0x17,0x11,0x17,0x15,0x27,0x11,0xff,0xf5,0xc3,0xb4,0x03,0xfb,0xee,0x41,0xbd,0xfc,0x77,0x00,0x00,0x01,0x00,0x0a,0xff,0xd9,0x02,0x4e,0x02,0x52,0x00,0x11,0x00,0x77,0x40,0x11,0x0d,0x0c,0x02,0x02,0x03,0x0e,0x05,0x02,0x01,0x02,0x10,0x0f, 0x02,0x00,0x01,0x03,0x4c,0x4b,0xb0,0x0b,0x50,0x58,0x40,0x25,0x00,0x04,0x03,0x03,0x04,0x70,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x23,0x00,0x04,0x03,0x04,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x00, 0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x11,0x00,0x11,0x11,0x11,0x12,0x11,0x11,0x07,0x06,0x1b,0x2b,0x05,0x37,0x21,0x35,0x21,0x27,0x37,0x21,0x35,0x21,0x27,0x33,0x17,0x15,0x07,0x17,0x15,0x07,0x01,0x8b,0x62,0xfe,0x1d, 0x01,0xe3,0x62,0x62,0xfe,0x1d,0x01,0xe3,0x62,0x62,0x61,0x61,0x61,0x61,0x27,0x77,0x50,0x77,0x74,0x50,0x77,0x7d,0x44,0x7a,0x7d,0x44,0x7d,0x00,0x00,0x02,0xff,0xf6,0xff,0x4c,0x02,0x62,0x03,0x47,0x00,0x05,0x00,0x0b,0x00,0x24,0x40,0x21,0x0a,0x09,0x08,0x07,0x04,0x03,0x02,0x01,0x08,0x00,0x4a,0x03,0x01,0x02,0x03,0x00,0x00,0x76, 0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x00,0x05,0x00,0x05,0x04,0x06,0x16,0x2b,0x05,0x11,0x17,0x15,0x27,0x11,0x23,0x11,0x07,0x35,0x37,0x11,0x01,0x6d,0xf5,0xc3,0xe6,0xc3,0xf5,0xb4,0x03,0xfb,0xee,0x41,0xbd,0xfc,0x77,0x03,0x89,0xbd,0x41,0xee,0xfc,0x05,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x23,0x02,0x58,0x02,0x71,0x00,0x0d, 0x00,0x6c,0xb6,0x0c,0x05,0x02,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x25,0x00,0x04,0x03,0x03,0x04,0x70,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x23,0x00,0x04,0x03,0x04,0x85,0x06,0x01, 0x05,0x00,0x05,0x86,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x11,0x12,0x11,0x11,0x07,0x06,0x1b,0x2b,0x25,0x37,0x21,0x35,0x21,0x37,0x27,0x21,0x35,0x21,0x27,0x33,0x13,0x03,0x01,0x07,0x6a,0xfe, 0x8f,0x01,0xb0,0x3f,0x3f,0xfe,0x50,0x01,0x71,0x6a,0x69,0xe8,0xe7,0x23,0x87,0x50,0x50,0x50,0x50,0x87,0xfe,0xd9,0xfe,0xd9,0x00,0x02,0xff,0xf6,0xff,0x42,0x02,0x62,0x03,0x3d,0x00,0x05,0x00,0x0b,0x00,0x18,0x40,0x15,0x0b,0x0a,0x09,0x08,0x05,0x04,0x03,0x02,0x08,0x00,0x49,0x01,0x01,0x00,0x00,0x76,0x15,0x10,0x02,0x06,0x18,0x2b, 0x01,0x33,0x11,0x37,0x15,0x07,0x03,0x33,0x11,0x27,0x35,0x17,0x01,0x6d,0x32,0xc3,0xf5,0xb4,0x32,0xf5,0xc3,0x03,0x3d,0xfc,0x77,0xbd,0x41,0xee,0x03,0xfb,0xfc,0x05,0xee,0x41,0xbd,0x00,0x00,0x01,0x00,0x00,0x00,0x23,0x02,0x58,0x02,0x71,0x00,0x0d,0x00,0x65,0xb6,0x09,0x02,0x02,0x04,0x03,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40, 0x24,0x00,0x01,0x02,0x02,0x01,0x70,0x00,0x00,0x05,0x05,0x00,0x71,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x68,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x04,0x05,0x4f,0x1b,0x40,0x22,0x00,0x01,0x02,0x01,0x85,0x00,0x00,0x05,0x00,0x86,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x68,0x00,0x04,0x05,0x05,0x04,0x57, 0x00,0x04,0x04,0x05,0x5f,0x00,0x05,0x04,0x05,0x4f,0x59,0x40,0x09,0x11,0x12,0x11,0x11,0x12,0x10,0x06,0x06,0x1c,0x2b,0x25,0x23,0x03,0x13,0x33,0x07,0x21,0x15,0x21,0x07,0x17,0x21,0x15,0x21,0x01,0x51,0x6a,0xe7,0xe8,0x69,0x6a,0x01,0x71,0xfe,0x50,0x3f,0x3f,0x01,0xb0,0xfe,0x8f,0x23,0x01,0x27,0x01,0x27,0x87,0x50,0x50,0x50,0x50, 0x00,0x02,0xff,0xb0,0x00,0x23,0x02,0xa8,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x77,0x40,0x09,0x13,0x10,0x08,0x01,0x04,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00,0x70,0x08,0x05,0x02,0x03,0x04,0x04,0x03,0x71,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00, 0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x1b,0x40,0x25,0x02,0x01,0x00,0x01,0x00,0x85,0x08,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00,0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x59,0x40,0x12,0x00,0x00,0x12,0x11,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x12, 0x11,0x11,0x12,0x09,0x06,0x1b,0x2b,0x37,0x03,0x13,0x33,0x07,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x17,0x27,0x21,0x37,0x27,0x21,0x07,0x97,0xe7,0xe8,0x69,0x6a,0x01,0x2a,0x6a,0x69,0xe8,0xe7,0x6a,0x6a,0xfe,0xd6,0x6a,0xa9,0x01,0xa8,0x3f,0x3f,0xfe,0x58,0x3f,0x23,0x01,0x27,0x01,0x27,0x87,0x87,0xfe,0xd9,0xfe,0xd9,0x87,0x87, 0xd7,0x50,0x50,0x50,0x00,0x01,0x00,0x00,0x00,0x23,0x02,0x58,0x02,0x71,0x00,0x10,0x00,0x7d,0xb5,0x0d,0x01,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x0f,0x50,0x58,0x40,0x2d,0x00,0x05,0x04,0x04,0x05,0x70,0x00,0x06,0x07,0x07,0x06,0x71,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x68,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x07,0x07, 0x00,0x57,0x00,0x00,0x00,0x07,0x5f,0x08,0x01,0x07,0x00,0x07,0x4f,0x1b,0x40,0x2b,0x00,0x05,0x04,0x05,0x85,0x00,0x06,0x07,0x06,0x86,0x00,0x04,0x00,0x03,0x02,0x04,0x03,0x68,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x07,0x07,0x00,0x57,0x00,0x00,0x00,0x07,0x5f,0x08,0x01,0x07,0x00,0x07,0x4f,0x59,0x40,0x10,0x00,0x00, 0x00,0x10,0x00,0x10,0x12,0x11,0x11,0x11,0x11,0x11,0x11,0x09,0x06,0x1d,0x2b,0x35,0x35,0x21,0x37,0x21,0x35,0x21,0x27,0x21,0x35,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x01,0x87,0x49,0xfe,0x30,0x01,0xd0,0x49,0xfe,0x79,0x01,0x4a,0x43,0x69,0xe8,0xe7,0x6a,0x43,0x78,0x4e,0x5d,0x4e,0x5d,0x4e,0x55,0xfe,0xd9,0xfe,0xd9,0x55,0x00,0x00, 0x00,0x02,0x00,0x14,0x00,0x00,0x02,0x44,0x03,0x16,0x00,0x0c,0x00,0x13,0x00,0x31,0x40,0x2e,0x0e,0x0c,0x02,0x03,0x4a,0x06,0x05,0x02,0x03,0x02,0x01,0x00,0x04,0x03,0x00,0x67,0x00,0x04,0x01,0x01,0x04,0x57,0x00,0x04,0x04,0x01,0x5f,0x00,0x01,0x04,0x01,0x4f,0x0d,0x0d,0x0d,0x13,0x0d,0x13,0x11,0x14,0x13,0x33,0x10,0x07,0x06,0x1b, 0x2b,0x01,0x23,0x11,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x11,0x23,0x01,0x13,0x27,0x07,0x33,0x11,0x33,0x11,0x02,0x44,0x9b,0x21,0x1b,0x82,0x1b,0x21,0x9b,0x01,0x18,0xc0,0xbf,0xbf,0x70,0x9c,0x01,0xe5,0xfe,0x57,0x1b,0x21,0x21,0x1b,0x01,0xa9,0x01,0x31,0xfe,0xf4,0xcf,0xcf,0xfe,0x21,0x01,0xdf,0x00,0x00,0x00,0x00,0x02,0x00,0x00, 0x00,0x32,0x02,0x58,0x02,0x6c,0x00,0x0c,0x00,0x13,0x00,0x33,0x40,0x30,0x0e,0x0c,0x02,0x03,0x02,0x01,0x4c,0x0f,0x0b,0x02,0x01,0x4a,0x0d,0x00,0x02,0x00,0x49,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x03,0x03,0x00,0x5f,0x00,0x00,0x03,0x00,0x4f,0x11,0x16,0x25,0x21,0x04,0x06,0x1a,0x2b,0x25, 0x35,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x33,0x35,0x01,0x05,0x37,0x27,0x15,0x21,0x15,0x21,0x01,0x27,0xeb,0x1b,0x21,0x21,0x1b,0xeb,0x01,0x31,0xfe,0xfb,0xc7,0xc7,0xfe,0xdc,0x01,0x24,0x32,0xa4,0x21,0x1b,0x7a,0x1b,0x21,0xa4,0xfe,0xe3,0xbb,0xbb,0xba,0x6c,0x9c,0x00,0x01,0x00,0x0a,0xff,0xf6,0x02,0x4e,0x01,0x56,0x00,0x05, 0x00,0x06,0xb3,0x04,0x00,0x01,0x32,0x2b,0x05,0x25,0x35,0x05,0x25,0x15,0x01,0x2b,0xfe,0xdf,0x01,0x27,0x01,0x1d,0x0a,0xf6,0x69,0xf9,0xfa,0x69,0x00,0x03,0xff,0xf6,0x01,0xae,0x02,0x62,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x0d,0x00,0x3e,0x40,0x3b,0x0c,0x01,0x04,0x01,0x01,0x4c,0x09,0x01,0x00,0x4a,0x07,0x05,0x02,0x04,0x01,0x04, 0x86,0x03,0x01,0x00,0x01,0x01,0x00,0x57,0x03,0x01,0x00,0x00,0x01,0x5f,0x02,0x06,0x02,0x01,0x00,0x01,0x4f,0x08,0x08,0x00,0x00,0x08,0x0d,0x08,0x0d,0x0b,0x0a,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x03,0x35,0x33,0x15,0x21,0x23,0x35,0x33,0x01,0x13,0x13,0x23,0x27,0x07,0x0a,0xb4,0x01,0xb8,0xb4,0xb4, 0xfd,0xd5,0xf5,0xf5,0x5f,0x96,0x96,0x02,0x8a,0x50,0x50,0x50,0xfe,0xd4,0x01,0x2c,0xfe,0xd4,0xb9,0xb9,0x00,0x01,0x00,0x0a,0x00,0x78,0x02,0x4e,0x02,0x1c,0x00,0x16,0x00,0x2f,0x40,0x2c,0x16,0x01,0x01,0x02,0x01,0x4c,0x05,0x01,0x01,0x01,0x4b,0x00,0x03,0x02,0x03,0x85,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x57,0x00, 0x02,0x02,0x01,0x5f,0x00,0x01,0x02,0x01,0x4f,0x16,0x31,0x27,0x10,0x04,0x06,0x1a,0x2b,0x25,0x23,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x21,0x35,0x21,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x01,0x9e,0x95,0x56,0x0c,0x1c,0x0c,0x13,0x26,0x0b,0xfe,0xbb,0x01,0x41,0x1a,0x26,0x06,0x05,0x18,0x10,0x57,0x91,0xb0,0x78, 0x68,0x0f,0x1c,0x08,0x04,0x01,0x03,0x6e,0x01,0x02,0x04,0x05,0x19,0x13,0x69,0xd2,0x00,0x01,0x00,0x05,0x00,0x64,0x02,0x4e,0x02,0x30,0x00,0x27,0x00,0x39,0x40,0x36,0x25,0x18,0x02,0x01,0x02,0x01,0x4c,0x09,0x01,0x01,0x01,0x4b,0x00,0x03,0x02,0x03,0x85,0x04,0x01,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02, 0x01,0x5f,0x00,0x01,0x02,0x01,0x4f,0x01,0x00,0x23,0x21,0x17,0x13,0x0f,0x0c,0x00,0x27,0x01,0x27,0x05,0x06,0x16,0x2b,0x25,0x22,0x26,0x35,0x34,0x37,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x21,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x17,0x17,0x07,0x06,0x01, 0x75,0x17,0x22,0x0e,0x08,0x1a,0x26,0x06,0x13,0x28,0x11,0xfe,0xf5,0x19,0x23,0x23,0x19,0x01,0x07,0x1a,0x2a,0x0c,0x0a,0x23,0x14,0x11,0x0d,0x22,0x17,0x1d,0x11,0xae,0xad,0x10,0x64,0x22,0x17,0x14,0x10,0x09,0x1e,0x27,0x04,0x04,0x01,0x03,0x20,0x17,0x17,0x20,0x02,0x02,0x04,0x09,0x23,0x15,0x13,0x10,0x14,0x17,0x20,0x19,0xcd,0xcf, 0x17,0x00,0x00,0x00,0x00,0x01,0x00,0x0a,0x00,0x69,0x02,0x4e,0x02,0x2b,0x00,0x06,0x00,0x26,0x40,0x23,0x06,0x01,0x00,0x01,0x01,0x4c,0x05,0x01,0x01,0x4a,0x00,0x01,0x00,0x49,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x11,0x11,0x02,0x06,0x18,0x2b,0x25,0x35,0x21,0x35,0x21,0x35,0x17,0x01, 0x8f,0xfe,0x7b,0x01,0x85,0xbf,0x69,0xbe,0x46,0xbe,0xe1,0x00,0x00,0x01,0x00,0x0a,0x00,0x69,0x02,0x4e,0x02,0x2b,0x00,0x06,0x00,0x26,0x40,0x23,0x06,0x01,0x00,0x01,0x01,0x4c,0x05,0x01,0x01,0x4a,0x00,0x01,0x00,0x49,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x11,0x11,0x02,0x06,0x18,0x2b, 0x25,0x35,0x21,0x35,0x21,0x35,0x17,0x01,0x8f,0xfe,0x7b,0x01,0x85,0xbf,0x69,0xaa,0x6e,0xaa,0xe1,0x00,0x00,0x01,0xff,0xd8,0x00,0x4b,0x02,0x80,0x02,0x49,0x00,0x16,0x00,0x3a,0x40,0x37,0x07,0x01,0x01,0x00,0x11,0x08,0x01,0x03,0x02,0x01,0x12,0x01,0x03,0x02,0x03,0x4c,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00, 0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x16,0x00,0x16,0x21,0x36,0x12,0x05,0x06,0x19,0x2b,0x37,0x27,0x37,0x33,0x07,0x06,0x06,0x07,0x15,0x36,0x36,0x33,0x21,0x15,0x21,0x22,0x26,0x27,0x15,0x16,0x16,0x17,0x17,0xa7,0xcf,0xce,0x67,0x86,0x0a,0x1a,0x09,0x0d,0x29,0x10,0x01,0xe0, 0xfe,0x20,0x10,0x29,0x0d,0x07,0x19,0x0d,0x89,0x4b,0xff,0xff,0xa5,0x0c,0x1a,0x07,0x09,0x02,0x02,0x50,0x04,0x01,0x09,0x06,0x1a,0x0f,0xa4,0x00,0x00,0x01,0xff,0xd8,0x00,0x4b,0x02,0x80,0x02,0x49,0x00,0x16,0x00,0x3a,0x40,0x37,0x0f,0x01,0x01,0x02,0x15,0x0e,0x05,0x03,0x00,0x01,0x04,0x01,0x03,0x00,0x03,0x4c,0x00,0x02,0x01,0x02, 0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x16,0x00,0x16,0x17,0x21,0x27,0x05,0x06,0x19,0x2b,0x25,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x21,0x35,0x21,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x07,0x01,0x4b,0x86,0x0a,0x1a, 0x09,0x0d,0x28,0x11,0xfe,0x20,0x01,0xe0,0x11,0x28,0x0d,0x07,0x19,0x0d,0x89,0x69,0xcf,0xce,0x4b,0xa5,0x0c,0x1a,0x07,0x09,0x01,0x03,0x50,0x03,0x02,0x09,0x06,0x1a,0x0f,0xa4,0xff,0xff,0x00,0x01,0xff,0xb0,0x00,0x4b,0x02,0xa8,0x02,0x49,0x00,0x29,0x00,0x43,0x40,0x40,0x10,0x07,0x02,0x01,0x00,0x24,0x1d,0x16,0x0f,0x08,0x01,0x06, 0x04,0x01,0x25,0x1c,0x02,0x03,0x04,0x03,0x4c,0x02,0x01,0x00,0x01,0x00,0x85,0x06,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x04,0x04,0x01,0x57,0x00,0x01,0x01,0x04,0x5f,0x00,0x04,0x01,0x04,0x4f,0x00,0x00,0x00,0x29,0x00,0x29,0x37,0x12,0x17,0x46,0x12,0x07,0x06,0x1b,0x2b,0x37,0x27,0x37,0x33,0x07,0x06,0x06,0x07,0x15,0x36,0x36, 0x33,0x21,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x07,0x23,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x21,0x22,0x26,0x27,0x15,0x16,0x16,0x17,0x17,0x7f,0xcf,0xce,0x67,0x86,0x0a,0x1a,0x09,0x0d,0x29,0x10,0x01,0x68,0x11,0x28,0x0d,0x07,0x19,0x0d,0x89,0x69,0xcf,0xce,0x67,0x86,0x0a,0x1a,0x09,0x0d,0x28,0x11,0xfe,0x98, 0x10,0x29,0x0d,0x07,0x19,0x0d,0x89,0x4b,0xff,0xff,0xa5,0x0c,0x1a,0x07,0x09,0x02,0x02,0x03,0x02,0x09,0x06,0x1a,0x0f,0xa4,0xff,0xff,0xa5,0x0c,0x1a,0x07,0x09,0x01,0x03,0x04,0x01,0x09,0x06,0x1a,0x0f,0xa4,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0xff,0x79,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00, 0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x35,0x21,0x15,0x02,0x58,0xfe,0xd4,0xa5,0xa5,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x00,0x1e,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03, 0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0x01,0x4a,0xfe,0xb6,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x00,0xc3,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe, 0xd4,0x01,0xef,0xfe,0x11,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x01,0x68,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x00,0x00, 0xfe,0xd4,0x02,0x58,0x02,0x0d,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0x03,0x39,0xfc,0xc7,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x02,0xb2,0x00,0x03,0x00,0x17,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0x03,0xde,0xfc,0x22,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0x57,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00, 0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0x04,0x83,0xfb,0x7d,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21, 0x11,0x02,0x58,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x68,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x58,0x01,0x68,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00, 0x00,0x01,0x00,0x00,0x03,0x57,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x35,0x21,0x15,0x02,0x58,0x03,0x57,0xa5,0xa5,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x00,0x4b, 0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x33,0x11,0x4b,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x01,0x00,0x00,0xfe,0xd4,0x00,0x96,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x33,0x11,0x96,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x01,0x00,0x00,0xfe,0xd4,0x00,0xc8,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x33, 0x11,0xc8,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x01,0x00,0x00,0xfe,0xd4,0x01,0x2c,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0x2c,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0x00, 0xfe,0xd4,0x01,0x77,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0x77,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x01,0xc2,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0xc2,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x0d,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00, 0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x02,0x0d,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x00,0x00,0x01,0x01,0x2c,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x01,0x11,0x21, 0x11,0x01,0x2c,0x01,0x2c,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00,0x01,0x02,0x0d,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x01,0x11,0x33,0x11,0x02,0x0d,0x4b,0xfe,0xd4,0x05,0x28,0xfa,0xd8,0x00,0x00, 0x00,0x01,0x00,0x00,0xfe,0xd4,0x01,0x2c,0x01,0x68,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0x2c,0xfe,0xd4,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x01,0x2c,0xfe,0xd4,0x02,0x58,0x01,0x68,0x00,0x03, 0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x01,0x11,0x21,0x11,0x01,0x2c,0x01,0x2c,0xfe,0xd4,0x02,0x94,0xfd,0x6c,0x00,0x00,0x01,0x00,0x00,0x01,0x68,0x01,0x2c,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x11,0x11,0x21,0x11,0x01,0x2c,0x01,0x68,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1d,0x40,0x1a,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x01,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x05,0x00, 0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x11,0x11,0x21,0x11,0x21,0x11,0x01,0x2c,0x01,0x2c,0xfe,0xd4,0x05,0x28,0xfd,0x6c,0xfd,0x6c,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x03,0x02,0x85,0x05,0x01, 0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x11,0x11,0x21,0x19,0x02,0x21,0x11,0x01,0x2c,0x01,0x2c,0x01,0x68,0x02,0x94,0xfd,0x6c,0xfd,0x6c,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1d,0x40,0x1a, 0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x01,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x11,0x11,0x21,0x11,0x21,0x11,0x02,0x58,0xfe,0xd4,0xfe,0xd4,0x05,0x28,0xfd,0x6c,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0xff,0xf6,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1d,0x40,0x1a, 0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x01,0x11,0x21,0x11,0x21,0x11,0x01,0x2c,0xfe,0xca,0x02,0x62,0xfe,0xd4,0x02,0x94,0x02,0x94,0xfa,0xd8,0x00,0x00,0x01,0x01,0x2c,0x01,0x68,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x17,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x01,0x11,0x21,0x11,0x01,0x2c,0x01,0x2c,0x01,0x68,0x02,0x94,0xfd,0x6c,0x00,0x00,0x02,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x01,0x02,0x01, 0x85,0x00,0x02,0x03,0x02,0x85,0x05,0x01,0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x01,0x11,0x21,0x11,0x01,0x11,0x21,0x11,0x01,0x2c,0x01,0x2c,0xfd,0xa8,0x01,0x2c,0x01,0x68,0x02,0x94,0xfd,0x6c,0xfd,0x6c,0x02,0x94,0xfd,0x6c,0x00,0x00,0x00,0x01,0x00,0x00, 0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1d,0x40,0x1a,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x11,0x11,0x21,0x11,0x21,0x11,0x01,0x2c,0x01,0x2c,0xfe,0xd4,0x02,0x94,0x02,0x94,0xfa,0xd8,0x00,0x00,0x00,0x00,0x37,0x00,0x3c, 0xff,0x10,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x53,0x00,0x57,0x00,0x5b,0x00,0x5f,0x00,0x63,0x00,0x67,0x00,0x6b,0x00,0x6f,0x00,0x73, 0x00,0x77,0x00,0x7b,0x00,0x7f,0x00,0x83,0x00,0x87,0x00,0x8b,0x00,0x8f,0x00,0x93,0x00,0x97,0x00,0x9b,0x00,0x9f,0x00,0xa3,0x00,0xa7,0x00,0xab,0x00,0xaf,0x00,0xb3,0x00,0xb7,0x00,0xbb,0x00,0xbf,0x00,0xc3,0x00,0xc7,0x00,0xcb,0x00,0xcf,0x00,0xd3,0x00,0xd7,0x00,0xdb,0x00,0x00,0x01,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35, 0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35, 0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35, 0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35, 0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x02,0x1c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0xfd,0xe4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x03,0xc0,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x6e,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1b,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x2b,0x00,0x2f,0x00,0x33,0x00,0x37,0x00,0x3b,0x00,0x3f,0x00,0x43,0x00,0x47,0x00,0x4b,0x00,0x4f,0x00,0x53,0x00,0x57,0x00,0x5b, 0x00,0x5f,0x00,0x63,0x00,0x67,0x00,0x6b,0x00,0x6f,0x00,0x73,0x00,0x77,0x00,0x7b,0x00,0x7f,0x00,0x83,0x00,0x87,0x00,0x8b,0x00,0x8f,0x00,0x93,0x00,0x97,0x00,0x9b,0x00,0x9f,0x00,0xa3,0x00,0xa7,0x00,0xab,0x00,0xaf,0x00,0xb3,0x00,0xb7,0x00,0xbb,0x00,0xbf,0x00,0xc3,0x00,0xc7,0x00,0xcb,0x00,0xcf,0x00,0xd3,0x00,0xd7,0x00,0xdb, 0x00,0xdf,0x00,0xe3,0x00,0xe7,0x00,0xeb,0x00,0xef,0x00,0xf3,0x00,0xf7,0x00,0xfb,0x00,0xff,0x01,0x03,0x01,0x07,0x01,0x0b,0x01,0x0f,0x01,0x13,0x01,0x17,0x01,0x1b,0x01,0x1f,0x01,0x23,0x01,0x27,0x01,0x2b,0x01,0x2f,0x01,0x33,0x01,0x37,0x01,0x3b,0x01,0x3f,0x01,0x43,0x01,0x47,0x01,0x4b,0x01,0x4f,0x01,0x53,0x01,0x57,0x01,0x5b, 0x01,0x5f,0x01,0x63,0x01,0x67,0x01,0x6b,0x01,0x6f,0x01,0x73,0x01,0x77,0x01,0x7b,0x01,0x7f,0x01,0x83,0x01,0x87,0x01,0x8b,0x01,0x8f,0x01,0x93,0x01,0x97,0x01,0x9b,0x01,0x9f,0x01,0xa3,0x01,0xa7,0x01,0xab,0x01,0xaf,0x01,0xb3,0x01,0xb7,0x00,0x00,0x01,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15, 0x23,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15, 0x07,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x17,0x35,0x33,0x15, 0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15, 0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15, 0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15, 0x21,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x05,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x07,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15, 0x05,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x17,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x23,0x35,0x33,0x15,0x02,0x1c,0x3c,0xb4,0x3c,0xb4,0x3c,0xb4,0x3c,0xb4,0x3c,0x01,0x68,0x3c,0xb4,0x3c,0xb4,0x3c,0xb4,0x3c,0xb4,0x3c,0x01,0xe0, 0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0xb4,0x3c,0xf0,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0x78,0x3c,0x01,0x2c,0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0x78,0x3c,0xfe,0xd4,0x3c,0xb4,0x3c,0xb4,0x3c,0x01,0x2c,0x3c,0x78,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0xb4,0x3c,0xfe,0xd4,0x3c,0xf0,0x3c,0xfe,0xd4,0x3c,0x3c, 0x3c,0xb4,0x3c,0xfd,0xe4,0x3c,0xf0,0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0x01,0x2c,0x3c,0xfe,0x20,0x3c,0x01,0xa4,0x3c,0xb4,0x3c,0xfe,0xd4,0x3c,0x3c,0x3c,0xf0,0x3c,0xfe,0xd4,0x3c,0xb4,0x3c,0xb4,0x3c,0x01,0x2c,0x3c,0xf0,0x3c,0x3c,0x3c,0xfe,0x5c,0x3c,0x3c,0x3c,0x01,0x2c,0x3c,0xf0,0x3c,0xfe,0xd4,0x3c,0x3c,0x3c,0x01,0x2c, 0x3c,0xb4,0x3c,0x78,0x3c,0xfe,0xd4,0x3c,0x01,0x2c,0x3c,0xfe,0xd4,0x3c,0xfe,0xd4,0x3c,0x01,0x68,0x3c,0xfe,0xd4,0x3c,0x3c,0x3c,0xb4,0x3c,0xfd,0xe4,0x3c,0x01,0x68,0x3c,0xfd,0xe4,0x3c,0xb4,0x3c,0x3c,0x3c,0xfe,0xd4,0x3c,0x78,0x3c,0x01,0x2c,0x3c,0xb4,0x3c,0xb4,0x3c,0x01,0x2c,0x3c,0x78,0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c, 0xb4,0x3c,0x01,0x68,0x3c,0xb4,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0xb4,0x3c,0x78,0x3c,0x01,0x2c,0x3c,0xb4,0x3c,0xb4,0x3c,0xfe,0xd4,0x3c,0x01,0xe0,0x3c,0xfe,0x5c,0x3c,0xb4,0x3c,0xb4,0x3c,0xfe,0xd4,0x3c,0x78,0x3c,0xb4,0x3c,0xb4,0x3c,0xfe,0xd4,0x3c,0xb4,0x3c,0x03,0xc0,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x29,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x3d,0x00,0x41,0x00,0x45,0x00,0x49,0x00,0x4d,0x00,0x51,0x00,0x55, 0x00,0x59,0x00,0x5d,0x00,0x61,0x00,0x65,0x00,0x69,0x00,0x6d,0x00,0x71,0x00,0x75,0x00,0x79,0x00,0x7d,0x00,0x81,0x00,0x85,0x00,0x89,0x00,0x8d,0x00,0x91,0x00,0x95,0x00,0x99,0x00,0x9d,0x00,0xa1,0x00,0xa5,0x00,0xa9,0x00,0xad,0x00,0xb1,0x00,0xb5,0x00,0xb9,0x00,0xbd,0x00,0xc1,0x00,0xc5,0x00,0xc9,0x00,0xcd,0x00,0xd1,0x00,0xd5, 0x00,0xd9,0x00,0xdd,0x00,0x00,0x11,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15, 0x33,0x35,0x33,0x11,0x03,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x17,0x33,0x35,0x23, 0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x15,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x15,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23, 0x07,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x15,0x33,0x35,0x23,0x05,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x07,0x33,0x35,0x23,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x01,0x68,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x01,0x68,0x3c,0x3c,0x78,0x3c,0x3c,0xf0,0x3c,0x3c,0x78,0x3c,0x3c,0xf0,0x3c,0x3c,0xfe,0x98,0x3c,0x3c,0xf0,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x01,0x68,0x3c,0x3c,0xf0,0x3c,0x3c,0x78, 0x3c,0x3c,0x3c,0x3c,0xf0,0x3c,0x3c,0x78,0x3c,0x3c,0xf0,0x3c,0x3c,0xfe,0x98,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x01,0x68,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0x3c,0x3c,0x01,0x68,0x3c,0x3c,0x78,0x3c,0x3c,0x78,0x3c,0x3c,0xfe,0xd4, 0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xfa,0xd8,0x04,0x74,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c, 0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0xb4,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x01,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f, 0x00,0x18,0x40,0x15,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x00,0x76,0x01,0x00,0x09,0x07,0x00,0x0f,0x01,0x0f,0x03,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c, 0x59,0x58,0x8d,0x51,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x11,0x10,0x01,0x00,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01, 0x0f,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x32,0x51, 0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04, 0x01,0x00,0x02,0x00,0x51,0x11,0x10,0x01,0x00,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d, 0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1d,0x00,0x3b,0x40,0x38,0x00,0x03, 0x04,0x02,0x04,0x03,0x02,0x80,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x69,0x06,0x01,0x02,0x00,0x00,0x02,0x59,0x06,0x01,0x02,0x02,0x00,0x61,0x05,0x01,0x00,0x02,0x00,0x51,0x11,0x10,0x01,0x00,0x17,0x16,0x15,0x14,0x10,0x1d,0x11,0x1d,0x09,0x07,0x00,0x0f,0x01,0x0f,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33, 0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x21,0x11,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0xfe,0xfc,0x4a,0x76,0x44,0x44,0x76,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x01,0x04, 0x44,0x76,0x4a,0x4a,0x76,0x44,0x00,0x00,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x15,0x00,0x2f,0x40,0x2c,0x00,0x02,0x03,0x00,0x03,0x02,0x00,0x80,0x04,0x01,0x00,0x00,0x84,0x00,0x01,0x03,0x03,0x01,0x59,0x00,0x01,0x01,0x03,0x61,0x00,0x03,0x01,0x03,0x51,0x01,0x00,0x13,0x12,0x11,0x10,0x09,0x07,0x00, 0x0f,0x01,0x0f,0x05,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x21,0x11,0x22,0x06,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0xfe,0xa3,0x01,0x04,0x4a,0x76,0x44,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x01,0x36, 0x01,0x04,0x44,0x76,0x00,0x03,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1d,0x00,0x23,0x00,0x3e,0x40,0x3b,0x1f,0x14,0x02,0x00,0x04,0x01,0x4c,0x05,0x01,0x00,0x04,0x00,0x86,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x02,0x04,0x04,0x02,0x57,0x00,0x02,0x02,0x04,0x5f,0x06,0x01,0x04,0x02,0x04,0x4f,0x1e,0x1e, 0x01,0x00,0x1e,0x23,0x1e,0x23,0x1b,0x19,0x16,0x15,0x09,0x07,0x00,0x0f,0x01,0x0f,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x14,0x16,0x16,0x17,0x11,0x21,0x2e,0x02,0x23,0x22,0x06,0x06,0x05,0x15,0x3e,0x02,0x37,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c, 0x51,0x51,0x8c,0xfe,0xa3,0x3d,0x6a,0x44,0x01,0x1c,0x06,0x46,0x71,0x46,0x4a,0x76,0x44,0x01,0x1d,0x40,0x65,0x3f,0x06,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x01,0x36,0x46,0x71,0x46,0x06,0x01,0x1c,0x44,0x6a,0x3d,0x44,0x76,0x63,0xea,0x06,0x3f,0x65,0x40,0x00,0x00,0x08,0xff,0xf6,0x00,0x32,0x02,0x62, 0x02,0x9e,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x35,0x00,0x3b,0x00,0x47,0x00,0x48,0x40,0x45,0x13,0x0e,0x04,0x03,0x01,0x00,0x43,0x3d,0x39,0x38,0x33,0x31,0x2f,0x2b,0x2a,0x22,0x21,0x1b,0x1a,0x16,0x15,0x11,0x0f,0x0b,0x05,0x13,0x02,0x01,0x44,0x3b,0x34,0x03,0x03,0x02,0x03,0x4c,0x00,0x00,0x00,0x01,0x02,0x00, 0x01,0x69,0x00,0x02,0x03,0x03,0x02,0x59,0x00,0x02,0x02,0x03,0x61,0x00,0x03,0x02,0x03,0x51,0x47,0x45,0x41,0x3f,0x24,0x21,0x04,0x06,0x18,0x2b,0x13,0x36,0x33,0x32,0x17,0x07,0x26,0x26,0x23,0x22,0x06,0x07,0x07,0x36,0x37,0x17,0x06,0x07,0x25,0x37,0x16,0x17,0x07,0x26,0x05,0x34,0x37,0x17,0x06,0x06,0x15,0x14,0x16,0x17,0x07,0x26, 0x05,0x36,0x36,0x35,0x34,0x26,0x27,0x37,0x16,0x15,0x14,0x07,0x05,0x37,0x16,0x17,0x07,0x26,0x25,0x36,0x37,0x17,0x06,0x07,0x07,0x37,0x16,0x16,0x33,0x32,0x36,0x37,0x17,0x06,0x23,0x22,0xdb,0x25,0x2c,0x2c,0x25,0x0d,0x10,0x22,0x12,0x12,0x21,0x11,0xcb,0x29,0x4a,0x19,0x3d,0x23,0x01,0x66,0x19,0x4a,0x29,0x2c,0x23,0xfe,0x0a,0x0a, 0x30,0x04,0x04,0x04,0x04,0x30,0x0a,0x02,0x32,0x04,0x04,0x04,0x04,0x30,0x0a,0x0a,0xfd,0xc5,0x2c,0x23,0x3d,0x19,0x4a,0x01,0x69,0x3d,0x23,0x2c,0x29,0x4a,0xed,0x0d,0x11,0x21,0x12,0x12,0x22,0x10,0x0d,0x25,0x2c,0x2c,0x02,0x94,0x0a,0x0a,0x30,0x04,0x04,0x04,0x04,0x60,0x4a,0x29,0x2c,0x23,0x3d,0x60,0x2c,0x29,0x4a,0x19,0x3d,0xc0, 0x2c,0x25,0x0d,0x10,0x22,0x12,0x12,0x21,0x11,0x0d,0x25,0x18,0x11,0x21,0x12,0x12,0x22,0x10,0x0d,0x25,0x2c,0x2c,0x25,0x4b,0x19,0x3d,0x23,0x2c,0x29,0x03,0x23,0x3d,0x19,0x4a,0x29,0x1d,0x30,0x04,0x04,0x04,0x04,0x30,0x0a,0x00,0x00,0x03,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x49,0x40,0x46, 0x00,0x05,0x03,0x04,0x03,0x05,0x04,0x80,0x08,0x01,0x04,0x02,0x03,0x04,0x02,0x7e,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x02,0x00,0x51,0x21,0x20,0x11,0x10,0x01,0x00,0x29,0x27,0x20,0x2f,0x21,0x2f,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00, 0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59, 0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x37,0x59,0x35,0x35,0x59,0x37,0x39,0x59,0x33,0x35,0x59,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x3f,0x35,0x59,0x37,0x37,0x59,0x35,0x33,0x59,0x39, 0x37,0x59,0x35,0x00,0x00,0x04,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x2f,0x00,0x3f,0x00,0x53,0x40,0x50,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x0b,0x01,0x06,0x0a,0x01,0x04,0x02,0x06,0x04,0x69,0x09,0x01,0x02,0x00,0x00,0x02,0x59,0x09,0x01,0x02,0x02,0x00, 0x61,0x08,0x01,0x00,0x02,0x00,0x51,0x31,0x30,0x21,0x20,0x11,0x10,0x01,0x00,0x39,0x37,0x30,0x3f,0x31,0x3f,0x29,0x27,0x20,0x2f,0x21,0x2f,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x0c,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35, 0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a, 0x76,0x44,0x44,0x76,0x4a,0x37,0x59,0x35,0x35,0x59,0x37,0x39,0x59,0x33,0x35,0x59,0x37,0x2b,0x44,0x27,0x27,0x44,0x2b,0x2b,0x44,0x27,0x27,0x44,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x3f,0x35,0x59,0x37,0x37,0x59,0x35,0x33,0x59,0x39, 0x37,0x59,0x35,0x2f,0x27,0x44,0x2b,0x2b,0x44,0x27,0x27,0x44,0x2b,0x2b,0x44,0x27,0x00,0x02,0x00,0xb4,0x00,0xf5,0x01,0xa4,0x01,0xe5,0x00,0x0b,0x00,0x17,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01, 0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0x35,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x2d,0xf5,0x44,0x34,0x35,0x43,0x43, 0x35,0x34,0x44,0x28,0x2d,0x23,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x00,0x01,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9f,0x00,0x03,0x00,0x06,0xb3,0x02,0x00,0x01,0x32,0x2b,0x25,0x09,0x02,0x01,0x2c,0xfe,0xca,0x01,0x36,0x01,0x36,0x32,0x01,0x36,0x01,0x37,0xfe,0xc9,0x00,0x00,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9f,0x00,0x03, 0x00,0x07,0x00,0x08,0xb5,0x06,0x04,0x02,0x00,0x02,0x32,0x2b,0x25,0x09,0x02,0x05,0x37,0x27,0x07,0x01,0x2c,0xfe,0xca,0x01,0x36,0x01,0x36,0xfe,0xca,0xe8,0xe8,0xe8,0x32,0x01,0x36,0x01,0x37,0xfe,0xc9,0xe8,0xe8,0xe9,0xe9,0x00,0x00,0x03,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9f,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0a,0xb7,0x0a, 0x08,0x06,0x04,0x02,0x00,0x03,0x32,0x2b,0x25,0x09,0x02,0x05,0x37,0x27,0x07,0x17,0x27,0x37,0x17,0x01,0x2c,0xfe,0xca,0x01,0x36,0x01,0x36,0xfe,0xca,0xe8,0xe8,0xe8,0xe8,0x8d,0x8d,0x8d,0x32,0x01,0x36,0x01,0x37,0xfe,0xc9,0xe8,0xe8,0xe9,0xe9,0x8d,0x8d,0x8d,0x8d,0x00,0x00,0x02,0x00,0x3c,0x00,0x00,0x02,0x1c,0x02,0xd0,0x00,0x07, 0x00,0x1b,0x00,0x25,0x40,0x22,0x18,0x17,0x12,0x0e,0x0d,0x06,0x05,0x02,0x01,0x09,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x07,0x00,0x07,0x13,0x03,0x06,0x17,0x2b,0x33,0x03,0x35,0x13,0x33,0x13,0x15,0x03,0x27,0x33,0x36,0x36,0x37,0x37,0x35,0x27,0x26,0x26,0x27,0x23,0x06,0x06,0x07, 0x07,0x15,0x17,0x16,0x16,0xf0,0xb4,0xb4,0x7e,0xae,0xae,0x43,0x04,0x07,0x1b,0x0f,0x62,0x62,0x0f,0x1b,0x07,0x04,0x07,0x1c,0x0f,0x63,0x63,0x10,0x1b,0x01,0x44,0x47,0x01,0x45,0xfe,0xbb,0x47,0xfe,0xbc,0x3c,0x0e,0x36,0x1d,0xbb,0x1f,0xbc,0x1d,0x36,0x0e,0x0e,0x36,0x1d,0xbc,0x1f,0xbb,0x1e,0x35,0x00,0x00,0x00,0x00,0x01,0x00,0x00, 0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x02,0x58,0x3c,0x02,0x58,0xfd,0xa8,0x00,0x02,0x00,0x00,0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00, 0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x3c,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0x00,0x00, 0x00,0x01,0x00,0x96,0x00,0xd2,0x01,0xc2,0x01,0xfe,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x37,0x11,0x21,0x11,0x96,0x01,0x2c,0xd2,0x01,0x2c,0xfe,0xd4,0x00,0x00,0x00,0x00,0x02,0x00,0x96,0x00,0xd2,0x01,0xc2,0x01,0xfe,0x00,0x03, 0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x37,0x11,0x21,0x11,0x27,0x33,0x35,0x23,0x96,0x01,0x2c,0xfa,0xc8,0xc8,0xd2,0x01,0x2c,0xfe, 0xd4,0x32,0xc8,0x00,0x00,0x02,0x00,0x00,0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x07,0x00,0x29,0x40,0x26,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x04,0x01,0x03,0x00,0x00,0x03,0x57,0x04,0x01,0x03,0x03,0x00,0x5f,0x00,0x00,0x03,0x00,0x4f,0x04,0x04,0x04,0x07,0x04,0x07,0x12,0x11,0x10,0x05,0x06,0x19,0x2b,0x25,0x21,0x11, 0x21,0x03,0x11,0x21,0x11,0x02,0x58,0xfd,0xa8,0x02,0x58,0x32,0xfe,0xfc,0x3c,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x00,0x00,0x02,0x00,0x00,0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01, 0x02,0x01,0x4f,0x00,0x00,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x02,0x58,0xfd,0xda,0x01,0x04,0xfe,0xfc,0x3c,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x06,0x00,0x2b,0x40,0x28,0x06,0x01, 0x02,0x00,0x01,0x4c,0x00,0x00,0x02,0x00,0x85,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x03,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x04,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x21,0x11,0x02,0x58,0xfd,0xda,0x01,0xf4,0x3c,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0x00,0x02,0x00,0x00, 0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x06,0x00,0x2c,0x40,0x29,0x06,0x01,0x00,0x02,0x01,0x4c,0x00,0x00,0x02,0x00,0x86,0x03,0x01,0x01,0x02,0x02,0x01,0x57,0x03,0x01,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x04,0x06,0x17,0x2b,0x01,0x11,0x21,0x11,0x05,0x21,0x11,0x02, 0x58,0xfd,0xa8,0x02,0x26,0xfe,0x0c,0x02,0x94,0xfd,0xa8,0x02,0x58,0x32,0xfe,0x0c,0x00,0x03,0x00,0x00,0x00,0x3c,0x02,0x58,0x02,0x94,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x31,0x40,0x2e,0x00,0x00,0x04,0x01,0x03,0x02,0x00,0x03,0x67,0x05,0x01,0x02,0x01,0x01,0x02,0x57,0x05,0x01,0x02,0x02,0x01,0x5f,0x06,0x01,0x01,0x02,0x01,0x4f, 0x00,0x00,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x07,0x06,0x17,0x2b,0x35,0x11,0x21,0x11,0x25,0x33,0x11,0x23,0x21,0x23,0x11,0x33,0x02,0x58,0xfd,0xda,0xe1,0xe1,0x01,0xf4,0xe1,0xe1,0x3c,0x02,0x58,0xfd,0xa8,0x32,0x01,0xf4,0xfe,0x0c,0x00,0x00,0x01,0xff,0xf6,0x00,0x3c,0x02,0x62,0x02,0x9e,0x00,0x02, 0x00,0x15,0x40,0x12,0x01,0x01,0x00,0x4a,0x01,0x01,0x00,0x00,0x76,0x00,0x00,0x00,0x02,0x00,0x02,0x02,0x06,0x16,0x2b,0x27,0x01,0x01,0x0a,0x01,0x36,0x01,0x36,0x3c,0x02,0x62,0xfd,0x9e,0x00,0x01,0x00,0x00,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x02,0x00,0x06,0xb3,0x01,0x00,0x01,0x32,0x2b,0x35,0x11,0x01,0x02,0x62,0x32,0x02,0x6c, 0xfe,0xca,0x00,0x00,0x00,0x01,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x94,0x00,0x02,0x00,0x0a,0xb7,0x00,0x00,0x00,0x76,0x11,0x01,0x06,0x17,0x2b,0x25,0x01,0x21,0x01,0x2c,0xfe,0xca,0x02,0x6c,0x32,0x02,0x62,0x00,0x01,0xff,0xf6,0x00,0x31,0x02,0x58,0x02,0x9e,0x00,0x02,0x00,0x06,0xb3,0x02,0x00,0x01,0x32,0x2b,0x25,0x01,0x01,0x02, 0x58,0xfd,0x9e,0x02,0x62,0x31,0x01,0x37,0x01,0x36,0x00,0x00,0x00,0x02,0xff,0xf6,0x00,0x3c,0x02,0x62,0x02,0x9e,0x00,0x02,0x00,0x05,0x00,0x24,0x40,0x21,0x05,0x01,0x02,0x01,0x4a,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x04,0x03,0x00,0x02,0x00,0x02,0x03,0x06,0x16,0x2b, 0x27,0x01,0x01,0x25,0x21,0x03,0x0a,0x01,0x36,0x01,0x36,0xfd,0xe7,0x01,0xc6,0xe3,0x3c,0x02,0x62,0xfd,0x9e,0x32,0x01,0xbf,0x00,0x02,0x00,0x00,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x05,0x03,0x01,0x00,0x02,0x32,0x2b,0x35,0x11,0x01,0x05,0x25,0x25,0x02,0x62,0xfd,0xd0,0x01,0xc0,0xfe,0x40,0x32,0x02, 0x6c,0xfe,0xca,0xe3,0xe3,0xe3,0x00,0x00,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x94,0x00,0x02,0x00,0x05,0x00,0x18,0x40,0x15,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x12,0x11,0x02,0x06,0x18,0x2b,0x25,0x01,0x21,0x01,0x13,0x21,0x01,0x2c,0xfe,0xca,0x02,0x6c,0xfe,0xca,0xe3,0xfe, 0x3a,0x32,0x02,0x62,0xfe,0x0f,0x01,0xbf,0x00,0x02,0xff,0xf6,0x00,0x32,0x02,0x58,0x02,0x9e,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x04,0x03,0x02,0x00,0x02,0x32,0x2b,0x25,0x01,0x01,0x03,0x11,0x05,0x02,0x58,0xfd,0x9e,0x02,0x62,0x32,0xfe,0x40,0x32,0x01,0x36,0x01,0x36,0xfd,0xe7,0x01,0xc6,0xe3,0x00,0x00,0x00,0x00,0x01,0x00,0x00, 0x00,0xd2,0x02,0x62,0x01,0xfe,0x00,0x02,0x00,0x06,0xb3,0x01,0x00,0x01,0x32,0x2b,0x35,0x11,0x05,0x02,0x62,0xd2,0x01,0x2c,0x96,0x00,0x00,0x00,0x00,0x01,0xff,0xf6,0x00,0xd2,0x02,0x58,0x01,0xfe,0x00,0x02,0x00,0x06,0xb3,0x02,0x00,0x01,0x32,0x2b,0x2d,0x02,0x02,0x58,0xfd,0x9e,0x02,0x62,0xd2,0x96,0x96,0x00,0x00,0x02,0x00,0x00, 0x00,0xd2,0x02,0x62,0x01,0xfe,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x05,0x03,0x01,0x00,0x02,0x32,0x2b,0x35,0x11,0x05,0x05,0x25,0x25,0x02,0x62,0xfd,0xd0,0x01,0x8e,0xfe,0x72,0xd2,0x01,0x2c,0x96,0x56,0x56,0x56,0x00,0x00,0x00,0x00,0x02,0xff,0xf6,0x00,0xd2,0x02,0x58,0x01,0xfe,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x04,0x03,0x02, 0x00,0x02,0x32,0x2b,0x2d,0x02,0x07,0x35,0x05,0x02,0x58,0xfd,0x9e,0x02,0x62,0x32,0xfe,0x72,0xd2,0x96,0x96,0xec,0xac,0x56,0x00,0x01,0x00,0x96,0x00,0xd2,0x01,0xc2,0x02,0x08,0x00,0x02,0x00,0x15,0x40,0x12,0x01,0x01,0x00,0x4a,0x01,0x01,0x00,0x00,0x76,0x00,0x00,0x00,0x02,0x00,0x02,0x02,0x06,0x16,0x2b,0x37,0x13,0x13,0x96,0x96, 0x96,0xd2,0x01,0x36,0xfe,0xca,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0xd2,0x01,0xcc,0x01,0xfe,0x00,0x02,0x00,0x06,0xb3,0x01,0x00,0x01,0x32,0x2b,0x37,0x11,0x05,0x96,0x01,0x36,0xd2,0x01,0x2c,0x96,0x00,0x00,0x00,0x01,0x00,0x96,0x00,0xc8,0x01,0xc2,0x01,0xfe,0x00,0x02,0x00,0x0f,0x40,0x0c,0x02,0x01,0x00,0x49,0x00,0x00,0x00,0x76, 0x10,0x01,0x06,0x17,0x2b,0x13,0x21,0x03,0x96,0x01,0x2c,0x96,0x01,0xfe,0xfe,0xca,0x00,0x01,0x00,0x8c,0x00,0xd2,0x01,0xc2,0x01,0xfe,0x00,0x02,0x00,0x06,0xb3,0x01,0x00,0x01,0x32,0x2b,0x01,0x11,0x25,0x01,0xc2,0xfe,0xca,0x01,0xfe,0xfe,0xd4,0x96,0x00,0x02,0x00,0x96,0x00,0xd2,0x01,0xc2,0x02,0x08,0x00,0x02,0x00,0x05,0x00,0x24, 0x40,0x21,0x05,0x01,0x02,0x01,0x4a,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x04,0x03,0x00,0x02,0x00,0x02,0x03,0x06,0x16,0x2b,0x37,0x13,0x13,0x27,0x33,0x27,0x96,0x96,0x96,0xec,0xac,0x56,0xd2,0x01,0x36,0xfe,0xca,0x28,0xb2,0x00,0x00,0x02,0x00,0x96,0x00,0xd2,0x01,0xcc, 0x01,0xfe,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x05,0x03,0x01,0x00,0x02,0x32,0x2b,0x37,0x11,0x05,0x05,0x37,0x27,0x96,0x01,0x36,0xfe,0xf2,0xb2,0xb2,0xd2,0x01,0x2c,0x96,0x56,0x56,0x56,0x00,0x02,0x00,0x96,0x00,0xc8,0x01,0xc2,0x01,0xfe,0x00,0x02,0x00,0x05,0x00,0x18,0x40,0x15,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01, 0x5f,0x00,0x01,0x00,0x01,0x4f,0x12,0x11,0x02,0x06,0x18,0x2b,0x25,0x03,0x21,0x07,0x37,0x23,0x01,0x2c,0x96,0x01,0x2c,0x96,0x56,0xac,0xc8,0x01,0x36,0xda,0xb2,0x00,0x00,0x02,0x00,0x8c,0x00,0xd2,0x01,0xc2,0x01,0xfe,0x00,0x02,0x00,0x05,0x00,0x08,0xb5,0x04,0x03,0x02,0x00,0x02,0x32,0x2b,0x2d,0x02,0x07,0x35,0x07,0x01,0xc2,0xfe, 0xca,0x01,0x36,0x28,0xb2,0xd2,0x96,0x96,0xec,0xac,0x56,0x00,0x00,0x03,0xff,0xec,0xfe,0x70,0x02,0x6c,0x02,0x08,0x00,0x03,0x00,0x09,0x00,0x0f,0x00,0x45,0x40,0x42,0x0a,0x07,0x09,0x03,0x04,0x03,0x04,0x86,0x00,0x00,0x08,0x01,0x01,0x02,0x00,0x01,0x67,0x06,0x01,0x02,0x03,0x03,0x02,0x57,0x06,0x01,0x02,0x02,0x03,0x5f,0x05,0x01, 0x03,0x02,0x03,0x4f,0x0a,0x0a,0x04,0x04,0x00,0x00,0x0a,0x0f,0x0a,0x0f,0x0e,0x0d,0x0c,0x0b,0x04,0x09,0x04,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0b,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x01,0x11,0x21,0x15,0x23,0x11,0x21,0x11,0x23,0x35,0x21,0x11,0x14,0x02,0x80,0xfe,0xf2,0x01,0x0e,0xaa,0xfe,0xd4,0xaa,0x01,0x0e, 0x01,0xa4,0x64,0x64,0xfc,0xcc,0x02,0xd0,0x64,0xfd,0x94,0x02,0x6c,0x64,0xfd,0x30,0x00,0x02,0xff,0xec,0xfe,0x70,0x01,0xc2,0x02,0x08,0x00,0x05,0x00,0x0b,0x00,0x38,0x40,0x35,0x07,0x05,0x06,0x03,0x02,0x03,0x02,0x86,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x04,0x03,0x03,0x04,0x57,0x00,0x04,0x04,0x03,0x5f,0x00,0x03,0x04, 0x03,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11,0x08,0x06,0x18,0x2b,0x01,0x11,0x21,0x35,0x21,0x11,0x21,0x11,0x23,0x35,0x21,0x11,0x01,0x5e,0xfe,0x8e,0x01,0xd6,0xfe,0xd4,0xaa,0x01,0x0e,0xfe,0x70,0x03,0x34,0x64,0xfc,0x68,0x02,0x6c,0x64,0xfd,0x30,0x00,0x00,0x02,0x00,0x96, 0xfe,0x70,0x02,0x6c,0x02,0x08,0x00,0x05,0x00,0x0b,0x00,0x38,0x40,0x35,0x07,0x05,0x06,0x03,0x02,0x04,0x02,0x86,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x67,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11, 0x08,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x21,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0x96,0x01,0xd6,0xfe,0x8e,0x64,0x01,0x0e,0xaa,0xfe,0x70,0x03,0x98,0x64,0xfc,0xcc,0x02,0xd0,0x64,0xfd,0x94,0x00,0x00,0x00,0x00,0x02,0xff,0xec,0x00,0xdc,0x02,0x6c,0x02,0x08,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x2c,0x00,0x00,0x04,0x01,0x01,0x02, 0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x14,0x02,0x80,0xfd,0x80,0x02,0x80,0x01,0xa4,0x64,0x64,0xc8,0x64,0x64,0x00,0x00,0x00, 0x00,0x03,0xff,0xec,0x00,0xdc,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x0b,0x00,0x0f,0x00,0x43,0x40,0x40,0x04,0x01,0x00,0x01,0x00,0x85,0x03,0x01,0x01,0x09,0x05,0x08,0x03,0x02,0x06,0x01,0x02,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x0a,0x01,0x07,0x06,0x07,0x4f,0x0c,0x0c,0x06,0x06,0x00,0x00,0x0c,0x0f,0x0c, 0x0f,0x0e,0x0d,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11,0x0b,0x06,0x18,0x2b,0x01,0x11,0x33,0x11,0x33,0x15,0x21,0x35,0x33,0x11,0x33,0x11,0x05,0x35,0x21,0x15,0x01,0x5e,0x64,0xaa,0xfd,0x80,0xaa,0x64,0xfe,0xf2,0x02,0x80,0x01,0xa4,0x02,0xbc,0xfd,0xa8,0x64,0x64,0x02,0x58,0xfd,0x44,0xc8,0x64,0x64, 0x00,0x02,0xff,0xec,0x00,0xdc,0x01,0xc2,0x04,0x60,0x00,0x05,0x00,0x0b,0x00,0x38,0x40,0x35,0x04,0x01,0x01,0x03,0x01,0x85,0x00,0x03,0x07,0x01,0x05,0x00,0x03,0x05,0x67,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x06,0x01,0x02,0x00,0x02,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05, 0x00,0x05,0x11,0x11,0x08,0x06,0x18,0x2b,0x27,0x35,0x21,0x11,0x33,0x11,0x25,0x35,0x33,0x11,0x33,0x11,0x14,0x01,0x72,0x64,0xfe,0x2a,0xaa,0x64,0xdc,0x64,0x03,0x20,0xfc,0x7c,0xc8,0x64,0x02,0x58,0xfd,0x44,0x00,0x02,0x00,0x96,0x00,0xdc,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x0b,0x00,0x38,0x40,0x35,0x03,0x01,0x00,0x04,0x00,0x85, 0x00,0x04,0x07,0x01,0x05,0x01,0x04,0x05,0x67,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x06,0x01,0x02,0x01,0x02,0x4f,0x06,0x06,0x00,0x00,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11,0x08,0x06,0x18,0x2b,0x37,0x11,0x33,0x11,0x21,0x15,0x25,0x11,0x33,0x11,0x33,0x15,0x96,0x64,0x01,0x72, 0xfe,0xf2,0x64,0xaa,0xdc,0x03,0x84,0xfc,0xe0,0x64,0xc8,0x02,0xbc,0xfd,0xa8,0x64,0x00,0x02,0x00,0x96,0xfe,0x70,0x01,0xc2,0x04,0x60,0x00,0x03,0x00,0x07,0x00,0x22,0x40,0x1f,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x03,0x04,0x03,0x01,0x01,0x76,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06, 0x17,0x2b,0x01,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x01,0x5e,0x64,0xfe,0xd4,0x64,0xfe,0x70,0x05,0xf0,0xfa,0x10,0x05,0xf0,0xfa,0x10,0x00,0x00,0x00,0x04,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x0b,0x00,0x11,0x00,0x17,0x00,0x59,0x40,0x56,0x03,0x01,0x01,0x00,0x01,0x85,0x0f,0x0b,0x0e,0x03,0x08,0x07,0x08,0x86, 0x04,0x01,0x00,0x0d,0x05,0x0c,0x03,0x02,0x06,0x00,0x02,0x67,0x0a,0x01,0x06,0x07,0x07,0x06,0x57,0x0a,0x01,0x06,0x06,0x07,0x5f,0x09,0x01,0x07,0x06,0x07,0x4f,0x12,0x12,0x0c,0x0c,0x06,0x06,0x00,0x00,0x12,0x17,0x12,0x17,0x16,0x15,0x14,0x13,0x0c,0x11,0x0c,0x11,0x10,0x0f,0x0e,0x0d,0x06,0x0b,0x06,0x0b,0x0a,0x09,0x08,0x07,0x00, 0x05,0x00,0x05,0x11,0x11,0x10,0x06,0x18,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x01,0x11,0x21,0x15,0x23,0x11,0x21,0x11,0x23,0x35,0x21,0x11,0x14,0xaa,0x64,0x64,0x64,0xaa,0xfe,0xf2,0x01,0x0e,0xaa,0xfe,0xd4,0xaa,0x01,0x0e,0x01,0xa4,0x64,0x02,0x58,0xfd,0x44,0x02,0xbc,0xfd,0xa8,0x64,0xfc,0xcc,0x02, 0xd0,0x64,0xfd,0x94,0x02,0x6c,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x03,0xff,0xec,0xfe,0x70,0x01,0xc2,0x04,0x60,0x00,0x03,0x00,0x09,0x00,0x0f,0x00,0x48,0x40,0x45,0x03,0x01,0x00,0x02,0x00,0x85,0x0a,0x07,0x08,0x03,0x01,0x05,0x01,0x86,0x00,0x02,0x09,0x01,0x04,0x06,0x02,0x04,0x67,0x00,0x06,0x05,0x05,0x06,0x57,0x00,0x06,0x06, 0x05,0x5f,0x00,0x05,0x06,0x05,0x4f,0x0a,0x0a,0x04,0x04,0x00,0x00,0x0a,0x0f,0x0a,0x0f,0x0e,0x0d,0x0c,0x0b,0x04,0x09,0x04,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0b,0x06,0x17,0x2b,0x01,0x11,0x33,0x11,0x01,0x35,0x33,0x11,0x33,0x11,0x03,0x11,0x23,0x35,0x21,0x11,0x01,0x5e,0x64,0xfe,0x2a,0xaa,0x64,0x64,0xaa,0x01, 0x0e,0xfe,0x70,0x05,0xf0,0xfa,0x10,0x03,0x34,0x64,0x02,0x58,0xfd,0x44,0xfc,0xcc,0x02,0x6c,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x03,0x00,0x96,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x03,0x00,0x09,0x00,0x0f,0x00,0x48,0x40,0x45,0x02,0x01,0x00,0x03,0x00,0x85,0x0a,0x07,0x08,0x03,0x01,0x06,0x01,0x86,0x00,0x03,0x09,0x01,0x04,0x05, 0x03,0x04,0x67,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05,0x06,0x5f,0x00,0x06,0x05,0x06,0x4f,0x0a,0x0a,0x04,0x04,0x00,0x00,0x0a,0x0f,0x0a,0x0f,0x0e,0x0d,0x0c,0x0b,0x04,0x09,0x04,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0b,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0x13,0x11,0x33,0x11,0x33,0x15,0x01,0x11,0x21,0x15, 0x23,0x11,0x96,0x64,0x64,0x64,0xaa,0xfe,0xf2,0x01,0x0e,0xaa,0xfe,0x70,0x05,0xf0,0xfa,0x10,0x03,0x34,0x02,0xbc,0xfd,0xa8,0x64,0xfc,0xcc,0x02,0xd0,0x64,0xfd,0x94,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x0b,0x00,0x2a,0x40,0x27,0x06,0x05,0x02,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01, 0x00,0x5f,0x04,0x02,0x02,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x23,0x11,0x23,0x11,0x96,0xaa,0x02,0x80,0xaa,0x64,0x64,0xfe,0x70,0x02,0xd0,0x64,0x64,0xfd,0x30,0x02,0xd0,0xfd,0x30,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0xc2, 0x01,0xa4,0x00,0x09,0x00,0x28,0x40,0x25,0x05,0x04,0x02,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x03,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x23,0x11,0x23,0x11,0x96,0xaa,0x01,0xd6,0x64,0x64,0xfe,0x70, 0x02,0xd0,0x64,0xfc,0xcc,0x02,0xd0,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0x00,0x96,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x09,0x00,0x28,0x40,0x25,0x05,0x04,0x02,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06, 0x1a,0x2b,0x13,0x11,0x21,0x15,0x23,0x11,0x23,0x11,0x23,0x11,0x96,0x01,0xd6,0xaa,0x64,0x64,0xfe,0x70,0x03,0x34,0x64,0xfd,0x30,0x02,0xd0,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00, 0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xc8,0xdc,0x02,0x80,0xdc,0xfe,0x70,0x02,0xd0,0x64,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x01,0xa4,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00, 0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0xc8,0xdc,0x01,0xa4,0xfe,0x70,0x02,0xd0,0x64,0xfc,0xcc,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x03,0xfc,0x00,0x09,0x00,0x2d,0x40,0x2a, 0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x11,0x33,0x11,0xc8,0xdc,0x01,0x0e,0x64,0x32,0xfe,0x70,0x02,0xd0,0x64, 0x02,0x58,0xfd,0xa8,0xfc,0xcc,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x23,0x11, 0xc8,0x01,0xa4,0xdc,0xfe,0x70,0x03,0x34,0x64,0xfd,0x30,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2d,0x40,0x2a,0x00,0x01,0x00,0x01,0x85,0x05,0x01,0x04,0x03,0x04,0x86,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x00,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11, 0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x33,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0xc8,0x32,0x64,0x01,0x0e,0xdc,0xfe,0x70,0x03,0x34,0x02,0xbc,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03, 0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0xc8,0xdc,0x01,0x0e,0x64,0x01,0x0e,0xdc,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd,0x44,0x64,0xfd, 0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x21,0x35,0x21,0x15,0x21,0x11, 0xfa,0xfe,0xf2,0x02,0x80,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0xc8,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x01,0xd6,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06, 0x18,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x72,0xfe,0x70,0x02,0x9e,0xc8,0xfc,0x9a,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x09,0x00,0x2c,0x40,0x29,0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x03,0x01,0x00,0x01,0x00,0x4f, 0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x35,0x33,0x11,0x33,0x11,0x23,0x11,0xfa,0xfe,0xf2,0xdc,0xc8,0x32,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfc,0xae,0xfd,0x62,0x00,0x00,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01, 0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x21,0x11,0xfa,0x01,0x72,0xfe,0xf2,0xfe,0x70,0x03,0x66,0xc8,0xfd,0x62,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2c,0x40,0x29, 0x00,0x01,0x02,0x01,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x02,0x00,0x00,0x02,0x57,0x00,0x02,0x02,0x00,0x5f,0x03,0x01,0x00,0x02,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x23,0x11,0x33,0x11,0x33,0x15,0x21,0x11,0xfa,0x32,0xc8,0xdc,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0x03,0x52, 0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11, 0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x21,0x11,0xfa,0xfe,0xf2,0xdc,0xc8,0xdc,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x00,0x00,0x02,0xff,0xec,0xfe,0x70,0x02,0x6c,0x02,0x08,0x00,0x03,0x00,0x0b,0x00,0x39,0x40,0x36,0x07,0x01,0x05,0x02,0x05,0x86, 0x00,0x00,0x06,0x01,0x01,0x03,0x00,0x01,0x67,0x00,0x03,0x02,0x02,0x03,0x57,0x00,0x03,0x03,0x02,0x5f,0x04,0x01,0x02,0x03,0x02,0x4f,0x04,0x04,0x00,0x00,0x04,0x0b,0x04,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x01,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x14,0x02,0x80, 0xfe,0x8e,0xfe,0xf2,0x02,0x80,0xfe,0xf2,0x01,0xa4,0x64,0x64,0xfc,0xcc,0x02,0x6c,0x64,0x64,0xfd,0x94,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x02,0x08,0x00,0x09,0x00,0x2e,0x40,0x2b,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01, 0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0x01,0x72,0xfe,0x70,0x02,0x6c,0x64,0x64,0x64,0xfc,0x68,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x02,0x08,0x00,0x09,0x00,0x2e,0x40,0x2b,0x05,0x01,0x04,0x03, 0x04,0x86,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0xfa,0x01,0x72,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x03,0x98,0x64, 0x64,0x64,0xfd,0x94,0x00,0x02,0x00,0x4b,0x01,0x0e,0x02,0x0d,0x01,0xd6,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x01,0x35, 0x33,0x15,0x21,0x35,0x33,0x15,0x01,0x77,0x96,0xfe,0x3e,0x96,0x01,0x0e,0xc8,0xc8,0xc8,0xc8,0x00,0x00,0x00,0x02,0x00,0xc8,0xff,0x6f,0x01,0x90,0x03,0x69,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x03,0x02,0x85,0x05,0x01,0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04, 0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0xc8,0xc8,0xc8,0xc8,0x01,0xcc,0x01,0x9d,0xfe,0x63,0xfd,0xa3,0x01,0x9f,0xfe,0x61,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x01,0x90,0x01,0xa4,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xc8,0xc8,0xfe,0x70,0x03,0x34,0xfc,0xcc,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00, 0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xc8,0xdc,0x02,0x80,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0xc8,0xfd,0x62,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x01,0xd6,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01, 0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0xc8,0xdc,0x01,0xa4,0xfe,0x70,0x02,0x9e,0xc8,0xfc,0x9a,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01, 0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x23,0x11,0xc8,0x01,0xa4,0xdc,0xfe,0x70,0x03,0x66,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x01,0xd6,0x00,0x03,0x00,0x1e,0x40,0x1b, 0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x14,0x02,0x80,0x01,0x0e,0xc8,0xc8,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x01,0x5e,0x01,0xd6,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00, 0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x14,0x01,0x72,0x01,0x0e,0xc8,0xc8,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x01,0xd6,0x00,0x07,0x00,0x28,0x40,0x25,0x00,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x00, 0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x03,0x35,0x21,0x15,0x21,0x15,0x21,0x15,0x14,0x01,0x72,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0xc8,0x32,0x64,0x32,0x00,0x00,0x04,0x00,0x19,0x01,0x0e,0x02,0x3f,0x01,0xd6,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x42, 0x40,0x3f,0x06,0x04,0x02,0x03,0x00,0x01,0x01,0x00,0x57,0x06,0x04,0x02,0x03,0x00,0x00,0x01,0x5f,0x0b,0x07,0x0a,0x05,0x09,0x03,0x08,0x07,0x01,0x00,0x01,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x06, 0x17,0x2b,0x01,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0xdb,0x64,0xfd,0xda,0x64,0x32,0x64,0x32,0x64,0x01,0x0e,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0x00,0x00,0x00,0x04,0x00,0xc8,0xff,0x3d,0x01,0x90,0x03,0xa7,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x51,0x40,0x4e,0x00,0x00, 0x08,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x09,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x0a,0x01,0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x0b,0x01,0x07,0x06,0x07,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07, 0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x06,0x17,0x2b,0x13,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0x02,0xd0,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0x00,0x00,0x00,0x00,0x01,0x00,0xfa,0x01,0x0e,0x02,0x6c, 0x01,0xd6,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0xfa,0x01,0x72,0x01,0x0e,0xc8,0xc8,0x00,0x00,0x03,0x00,0x25,0x01,0x0e,0x02,0x33,0x01,0xd6,0x00,0x03,0x00,0x07,0x00,0x0b, 0x00,0x36,0x40,0x33,0x04,0x02,0x02,0x00,0x01,0x01,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x01,0x5f,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x00,0x01,0x4f,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x01,0x35,0x33,0x15,0x21,0x35,0x33,0x15, 0x33,0x35,0x33,0x15,0x01,0xb5,0x7e,0xfd,0xf2,0x7e,0x4a,0x7e,0x01,0x0e,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0x00,0x03,0x00,0xc8,0xff,0x25,0x01,0x90,0x03,0xaa,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x3d,0x40,0x3a,0x00,0x00,0x01,0x00,0x85,0x06,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x03,0x02,0x85,0x07,0x01,0x03,0x04,0x03,0x85,0x00,0x04, 0x05,0x04,0x85,0x08,0x01,0x05,0x05,0x76,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0xc8,0xc8,0xc8,0xc8,0xc8,0xc8,0x02,0x64,0x01,0x46,0xfe,0xba,0xfe,0x52,0x01,0x65,0xfe, 0x9b,0xfe,0x6f,0x01,0x46,0xfe,0xba,0x00,0x00,0x01,0x00,0xc8,0x01,0x40,0x01,0x90,0x04,0x60,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xc8,0xc8,0x01,0x40,0x03,0x20,0xfc,0xe0,0x00,0x00,0x00,0x00,0x01,0xff,0xec, 0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x27,0x40,0x24,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x14,0xdc,0xc8,0xdc,0x01,0x0e,0xc8, 0x02,0x8a,0xfd,0x76,0xc8,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x01,0x90,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x03,0x01,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x03,0x35,0x33,0x11,0x33,0x11, 0x14,0xdc,0xc8,0x01,0x0e,0xc8,0x02,0x8a,0xfc,0xae,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x07,0x00,0x1f,0x40,0x1c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x00,0x85,0x04,0x01,0x03,0x03,0x76,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x23,0x11,0x33,0x11,0x23, 0x11,0xfa,0x32,0xc8,0x32,0xfe,0x70,0x02,0xd0,0x03,0x20,0xfc,0xe0,0xfd,0x30,0x00,0x00,0x01,0x00,0xc8,0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06, 0x18,0x2b,0x13,0x11,0x33,0x11,0x33,0x15,0xc8,0xc8,0xdc,0x01,0x0e,0x03,0x52,0xfd,0x76,0xc8,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xc8,0xc8,0xfe, 0x70,0x05,0xf0,0xfa,0x10,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11, 0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xdc,0xdc,0xc8,0xdc,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00, 0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0xc8,0xdc,0xdc,0xc8,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfa,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x07, 0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xc8,0xdc,0xdc,0xfe,0x70,0x05,0xf0,0xfd,0x76,0xc8,0xfd, 0x62,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0d,0x00,0x37,0x40,0x34,0x00,0x02,0x01,0x02,0x85,0x07,0x01,0x06,0x00,0x06,0x86,0x03,0x01,0x01,0x04,0x00,0x01,0x57,0x00,0x04,0x00,0x05,0x00,0x04,0x05,0x67,0x03,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11, 0x11,0x11,0x11,0x11,0x11,0x08,0x06,0x1c,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x11,0x33,0x15,0x33,0x15,0x23,0x11,0xc8,0xdc,0x01,0x0e,0x64,0x32,0xdc,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0x32,0x64,0xfd,0x30,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x09,0x00,0x2e,0x40,0x2b,0x05,0x01,0x04,0x00, 0x04,0x86,0x00,0x01,0x02,0x00,0x01,0x57,0x00,0x02,0x00,0x03,0x00,0x02,0x03,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x35,0x21,0x15,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x72,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0xc8, 0x32,0x64,0xfd,0x30,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x04,0x00,0x57,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x00,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b, 0x03,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x14,0x01,0x0e,0x64,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0xc8,0x02,0x8a,0xfd,0x44,0x64,0x32,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x00,0x01,0x03,0x00,0x01,0x57,0x00,0x03,0x00, 0x04,0x00,0x03,0x04,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x44,0x64,0xfd,0x30, 0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x09,0x00,0x2e,0x40,0x2b,0x05,0x01,0x04,0x03,0x04,0x86,0x00,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x23,0x35, 0x33,0x35,0x21,0x15,0x23,0x11,0xc8,0xdc,0xdc,0x01,0xa4,0xdc,0xfe,0x70,0x02,0xd0,0x64,0x32,0xc8,0xfd,0x62,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x02,0x03,0x02,0x85,0x00,0x03,0x01,0x04,0x03,0x57,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x03,0x03,0x04,0x5f, 0x05,0x01,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0xc8,0xdc,0xdc,0xc8,0xdc,0x01,0x0e,0x32,0x64,0x02,0xbc,0xfd,0x76,0xc8,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x02,0x03,0x02, 0x85,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x03,0x01,0x04,0x03,0x57,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xdc,0xdc,0xc8,0xdc,0xdc, 0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0d,0x00,0x36,0x40,0x33,0x00,0x02,0x01,0x02,0x85,0x07,0x01,0x06,0x00,0x06,0x86,0x00,0x01,0x03,0x00,0x01,0x57,0x00,0x03,0x00,0x04,0x00,0x03,0x04,0x67,0x00,0x01,0x01,0x00,0x5f,0x05,0x01,0x00,0x01,0x00,0x4f, 0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x08,0x06,0x1c,0x2b,0x13,0x11,0x21,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x23,0x11,0xfa,0xfe,0xf2,0xdc,0xc8,0xdc,0xdc,0x32,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x44,0x64,0x32,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x01,0xa4,0x00,0x0d, 0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x00,0x00,0x00,0x0d,0x00,0x0d,0x21,0x24,0x04,0x06,0x18,0x2b,0x13,0x11,0x34,0x26,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x16,0x15,0x11,0xfa,0x3a,0x69,0x48,0x23,0x23,0x66,0x96,0x53,0xfe,0x70,0x01, 0xe0,0x49,0x6c,0x3b,0x64,0x54,0x99,0x67,0xfe,0x20,0x00,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x0d,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x59,0x00,0x00,0x00,0x01,0x61,0x00,0x01,0x00,0x01,0x51,0x00,0x00,0x00,0x0d,0x00,0x0d,0x21,0x24,0x04,0x06,0x18,0x2b,0x13,0x11, 0x34,0x36,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x06,0x15,0x11,0xfa,0x53,0x97,0x65,0x23,0x23,0x47,0x6a,0x3a,0xfe,0x70,0x01,0xe0,0x67,0x99,0x54,0x64,0x3b,0x6c,0x49,0xfe,0x20,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x40,0x01,0x5e,0x04,0x60,0x00,0x0d,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x59,0x00, 0x00,0x00,0x02,0x61,0x03,0x01,0x02,0x00,0x02,0x51,0x00,0x00,0x00,0x0d,0x00,0x0c,0x14,0x21,0x04,0x06,0x18,0x2b,0x03,0x35,0x33,0x32,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x06,0x23,0x14,0x23,0x48,0x69,0x3a,0x64,0x53,0x96,0x66,0x01,0x40,0x64,0x3b,0x6c,0x49,0x01,0xcc,0xfe,0x34,0x67,0x99,0x54,0x00,0x00,0x00,0x01,0x00,0xfa, 0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x0d,0x00,0x26,0x40,0x23,0x00,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x03,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x0c,0x0a,0x06,0x05,0x00,0x0d,0x01,0x0d,0x04,0x06,0x16,0x2b,0x01,0x22,0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x16,0x33,0x33,0x15,0x02,0x49, 0x65,0x97,0x53,0x64,0x3a,0x6a,0x47,0x23,0x01,0x40,0x54,0x99,0x67,0x01,0xcc,0xfe,0x34,0x49,0x6c,0x3b,0x64,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xff,0x60,0x02,0x6c,0x03,0x70,0x00,0x0f,0x00,0x28,0x40,0x25,0x0e,0x0b,0x0a,0x09,0x06,0x03,0x02,0x01,0x08,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x04,0x03,0x02,0x02,0x02, 0x76,0x00,0x00,0x00,0x0f,0x00,0x0f,0x14,0x12,0x14,0x05,0x06,0x19,0x2b,0x07,0x35,0x01,0x01,0x35,0x33,0x13,0x13,0x33,0x15,0x01,0x01,0x15,0x23,0x03,0x03,0x14,0x01,0x0d,0xfe,0xf3,0x50,0xf0,0xf0,0x50,0xfe,0xf3,0x01,0x0d,0x50,0xf0,0xf0,0xa0,0x28,0x01,0xe0,0x01,0xe0,0x28,0xfe,0x57,0x01,0xa9,0x28,0xfe,0x20,0xfe,0x20,0x28,0x01, 0xa9,0xfe,0x57,0x00,0x00,0x01,0xff,0xec,0xff,0x60,0x02,0x6c,0x03,0x70,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x05,0x01,0x35,0x33,0x01,0x15,0x02,0x1c,0xfd,0xd0,0x50,0x02,0x30,0xa0,0x03,0xe8, 0x28,0xfc,0x18,0x28,0x00,0x01,0xff,0xec,0xff,0x60,0x02,0x6c,0x03,0x70,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x07,0x35,0x01,0x33,0x15,0x01,0x14,0x02,0x30,0x50,0xfd,0xd0,0xa0,0x28,0x03,0xe8, 0x28,0xfc,0x18,0x00,0x00,0x02,0x00,0x46,0x01,0x40,0x02,0x12,0x01,0xa4,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x01,0x35, 0x33,0x15,0x21,0x35,0x33,0x15,0x01,0x72,0xa0,0xfe,0x34,0xa0,0x01,0x40,0x64,0x64,0x64,0x64,0x00,0x00,0x00,0x02,0x00,0xfa,0xff,0x5b,0x01,0x5e,0x03,0x7d,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x03,0x02,0x85,0x05,0x01,0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04, 0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0xfa,0x64,0x64,0x64,0x01,0xb8,0x01,0xc5,0xfe,0x3b,0xfd,0xa3,0x01,0xc7,0xfe,0x39,0x00,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x01,0x5e,0x01,0xa4,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xfa,0x64,0xfe,0x70,0x03,0x34,0xfc,0xcc,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x07,0x00,0x26,0x40,0x23,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00, 0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x02,0x80,0xfe,0xf2,0xfe,0x70,0x02,0xd0,0x64,0x64,0xfd,0x30,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x01,0xa4,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01, 0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x72,0xfe,0x70,0x02,0xd0,0x64,0xfc,0xcc,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x01,0xa4,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01, 0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x21,0x11,0xfa,0x01,0x72,0xfe,0xf2,0xfe,0x70,0x03,0x34,0x64,0xfd,0x30,0x00,0x01,0xff,0xec,0x01,0x40,0x02,0x6c,0x01,0xa4,0x00,0x03,0x00,0x1e,0x40,0x1b, 0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x14,0x02,0x80,0x01,0x40,0x64,0x64,0x00,0x00,0x01,0xff,0xec,0x01,0x40,0x01,0x5e,0x01,0xa4,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00, 0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x03,0x35,0x21,0x15,0x14,0x01,0x72,0x01,0x40,0x64,0x64,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x01,0xd6,0x00,0x07,0x00,0x28,0x40,0x25,0x00,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x02, 0x02,0x03,0x5f,0x04,0x01,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x35,0x21,0x35,0x21,0x35,0x21,0x15,0xfa,0xfe,0xf2,0x01,0x0e,0x01,0x72,0x01,0x0e,0x32,0x64,0x32,0xc8,0x00,0x00,0x04,0x00,0x19,0x01,0x40,0x02,0x3f,0x01,0xa4,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x42, 0x40,0x3f,0x06,0x04,0x02,0x03,0x00,0x01,0x01,0x00,0x57,0x06,0x04,0x02,0x03,0x00,0x00,0x01,0x5f,0x0b,0x07,0x0a,0x05,0x09,0x03,0x08,0x07,0x01,0x00,0x01,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x06, 0x17,0x2b,0x01,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x33,0x35,0x33,0x15,0x01,0xdb,0x64,0xfd,0xda,0x64,0x32,0x64,0x32,0x64,0x01,0x40,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x00,0x00,0x00,0x04,0x00,0xfa,0xff,0x3d,0x01,0x5e,0x03,0xa7,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x51,0x40,0x4e,0x00,0x00, 0x08,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x09,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x0a,0x01,0x05,0x06,0x04,0x05,0x67,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07,0x5f,0x0b,0x01,0x07,0x06,0x07,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07, 0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x06,0x17,0x2b,0x13,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0x03,0x35,0x33,0x15,0xfa,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x02,0xd0,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0xfe,0xcf,0xd7,0xd7,0x00,0x00,0x00,0x00,0x01,0x00,0xfa,0x01,0x40,0x02,0x6c, 0x01,0xa4,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0xfa,0x01,0x72,0x01,0x40,0x64,0x64,0x00,0x00,0x03,0x00,0x25,0x01,0x40,0x02,0x33,0x01,0xa4,0x00,0x03,0x00,0x07,0x00,0x0b, 0x00,0x36,0x40,0x33,0x04,0x02,0x02,0x00,0x01,0x01,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x01,0x5f,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x00,0x01,0x4f,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x01,0x35,0x33,0x15,0x21,0x35,0x33,0x15, 0x33,0x35,0x33,0x15,0x01,0xb5,0x7e,0xfd,0xf2,0x7e,0x4a,0x7e,0x01,0x40,0x64,0x64,0x64,0x64,0x64,0x64,0x00,0x03,0x00,0xfa,0xff,0x25,0x01,0x5e,0x03,0xaa,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x3d,0x40,0x3a,0x00,0x00,0x01,0x00,0x85,0x06,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x03,0x02,0x85,0x07,0x01,0x03,0x04,0x03,0x85,0x00,0x04, 0x05,0x04,0x85,0x08,0x01,0x05,0x05,0x76,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0xfa,0x64,0x64,0x64,0x64,0x64,0x02,0x58,0x01,0x52,0xfe,0xae,0xfe,0x69,0x01,0x4e,0xfe, 0xb2,0xfe,0x64,0x01,0x51,0xfe,0xaf,0x00,0x00,0x01,0x00,0xfa,0x01,0x40,0x01,0x5e,0x04,0x60,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xfa,0x64,0x01,0x40,0x03,0x20,0xfc,0xe0,0x00,0x00,0x00,0x00,0x01,0x00,0xc8, 0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x07,0x00,0x1f,0x40,0x1c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x00,0x85,0x04,0x01,0x03,0x03,0x76,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0xc8,0x32,0x64,0x32,0xfe,0x70,0x03,0x34,0x02,0xbc,0xfd,0x44,0xfc,0xcc,0x00, 0x00,0x01,0xff,0xec,0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x27,0x40,0x24,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x03,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x14,0x01,0x0e, 0x64,0x01,0x0e,0x01,0x40,0x64,0x02,0xbc,0xfd,0x44,0x64,0x00,0x00,0x01,0xff,0xec,0x01,0x40,0x01,0x5e,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x03,0x01,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x03,0x35, 0x21,0x11,0x33,0x11,0x14,0x01,0x0e,0x64,0x01,0x40,0x64,0x02,0xbc,0xfc,0xe0,0x00,0x00,0x01,0x00,0xfa,0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06, 0x18,0x2b,0x13,0x11,0x33,0x11,0x21,0x15,0xfa,0x64,0x01,0x0e,0x01,0x40,0x03,0x20,0xfd,0x44,0x64,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x01,0x5e,0x04,0x60,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x06,0x17,0x2b,0x13,0x11,0x33,0x11,0xfa,0x64,0xfe, 0x70,0x05,0xf0,0xfa,0x10,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11, 0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03, 0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfa,0x10,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c, 0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70, 0x05,0xf0,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0d,0x00,0x37,0x40,0x34,0x00,0x03,0x02,0x03,0x85,0x07,0x01,0x06,0x05,0x06,0x86,0x04,0x01,0x02,0x01,0x05,0x02,0x57,0x00,0x01,0x00,0x00,0x05,0x01,0x00,0x67,0x04,0x01,0x02,0x02,0x05,0x5f,0x00,0x05,0x02,0x05,0x4f,0x00,0x00,0x00, 0x0d,0x00,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x08,0x06,0x1c,0x2b,0x13,0x11,0x23,0x35,0x33,0x35,0x33,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0xc8,0xdc,0xdc,0x32,0x64,0x01,0x0e,0xdc,0xfe,0x70,0x02,0xd0,0x64,0x32,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x09,0x00,0x2e,0x40,0x2b, 0x05,0x01,0x04,0x03,0x04,0x86,0x00,0x02,0x01,0x03,0x02,0x57,0x00,0x01,0x00,0x00,0x03,0x01,0x00,0x67,0x00,0x02,0x02,0x03,0x5f,0x00,0x03,0x02,0x03,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x35,0x21,0x35,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x01,0x72,0xfe,0xf2,0xfe, 0x70,0x02,0xd0,0x64,0x32,0xc8,0xfd,0x62,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x02,0x03,0x02,0x85,0x00,0x03,0x01,0x04,0x03,0x57,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11, 0x06,0x06,0x1a,0x2b,0x13,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0x01,0x0e,0x01,0x0e,0x32,0x64,0x02,0xbc,0xfd,0x76,0xc8,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x02,0x03,0x02,0x85,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x03,0x01,0x04,0x03, 0x57,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd, 0x76,0xc8,0xfd,0x62,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x01,0xd6,0x00,0x09,0x00,0x2e,0x40,0x2b,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x01,0x02,0x00,0x01,0x57,0x00,0x02,0x00,0x03,0x00,0x02,0x03,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b, 0x13,0x11,0x23,0x35,0x21,0x15,0x33,0x15,0x23,0x11,0xc8,0xdc,0x01,0xa4,0xdc,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0x32,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x04,0x00,0x57,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00, 0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x00,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x14,0xdc,0xc8,0xdc,0xdc,0x01,0x0e,0xc8,0x02,0x8a,0xfd,0x44,0x64,0x32,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31, 0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x00,0x01,0x03,0x00,0x01,0x57,0x00,0x03,0x00,0x04,0x00,0x03,0x04,0x67,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xdc, 0xdc,0xc8,0xdc,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x44,0x64,0xfd,0x30,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0d,0x00,0x36,0x40,0x33,0x00,0x03,0x04,0x03,0x85,0x07,0x01,0x06,0x00,0x06,0x86,0x00,0x04,0x02,0x00,0x04,0x57,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x04,0x04,0x00,0x5f,0x05,0x01, 0x00,0x04,0x00,0x4f,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x11,0x11,0x11,0x11,0x11,0x08,0x06,0x1c,0x2b,0x13,0x11,0x23,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x21,0x11,0xfa,0x32,0xdc,0xdc,0xc8,0xdc,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0x32,0x64,0x02,0xbc,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0x01,0x40,0x02,0x6c, 0x04,0x60,0x00,0x0b,0x00,0x2c,0x40,0x29,0x03,0x01,0x01,0x00,0x01,0x85,0x04,0x02,0x02,0x00,0x05,0x05,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x14,0xaa, 0x64,0x64,0x64,0xaa,0x01,0x40,0x64,0x02,0xbc,0xfd,0x44,0x02,0xbc,0xfd,0x44,0x64,0x00,0x01,0xff,0xec,0x01,0x40,0x01,0xc2,0x04,0x60,0x00,0x09,0x00,0x29,0x40,0x26,0x03,0x01,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x04,0x04,0x00,0x57,0x02,0x01,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x00,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11, 0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x14,0xaa,0x64,0x64,0x64,0x01,0x40,0x64,0x02,0xbc,0xfd,0x44,0x02,0xbc,0xfc,0xe0,0x00,0x00,0x00,0x00,0x01,0x00,0x96,0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x29,0x40,0x26,0x02,0x01,0x00,0x01,0x00,0x85,0x03,0x01,0x01,0x04,0x04,0x01, 0x57,0x03,0x01,0x01,0x01,0x04,0x5f,0x05,0x01,0x04,0x01,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x96,0x64,0x64,0x64,0xaa,0x01,0x40,0x03,0x20,0xfd,0x44,0x02,0xbc,0xfd,0x44,0x64,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c, 0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x21, 0x11,0xfa,0xfe,0xf2,0xdc,0xc8,0xdc,0xfe,0xf2,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x27,0x40,0x24,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f, 0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x14,0xdc,0xc8,0xdc,0x01,0x40,0x64,0x02,0xbc,0xfd,0x44,0x64,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x09,0x00,0x2c,0x40,0x29,0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x00, 0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x03,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x21,0x35,0x33,0x11,0x33,0x11,0x23,0x11,0xfa,0xfe,0xf2,0xdc,0xc8,0x32,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfc,0xe0,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec, 0x01,0x40,0x01,0x90,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f,0x03,0x01,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x03,0x35,0x33,0x11,0x33,0x11,0x14,0xdc,0xc8,0x01,0x40,0x64,0x02,0xbc,0xfc,0xe0,0x00,0x00, 0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2c,0x40,0x29,0x00,0x01,0x02,0x01,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x02,0x00,0x00,0x02,0x57,0x00,0x02,0x02,0x00,0x5f,0x03,0x01,0x00,0x02,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x23,0x11,0x33,0x11, 0x33,0x15,0x21,0x11,0xfa,0x32,0xc8,0xdc,0xfe,0xf2,0xfe,0x70,0x02,0xd0,0x03,0x20,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0x00,0xc8,0x01,0x40,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00, 0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x33,0x11,0x33,0x15,0xc8,0xc8,0xdc,0x01,0x40,0x03,0x20,0xfd,0x44,0x64,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01, 0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0xc8,0xdc,0x01,0x0e,0x64,0x01,0x0e,0xdc,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x00,0x00,0x01,0xff,0xec, 0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x27,0x40,0x24,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x03,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x14,0x01,0x0e,0x64,0x01,0x0e,0x01, 0x0e,0xc8,0x02,0x8a,0xfd,0x76,0xc8,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90,0x04,0x60,0x00,0x09,0x00,0x2d,0x40,0x2a,0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06, 0x06,0x1a,0x2b,0x13,0x11,0x23,0x35,0x21,0x11,0x33,0x11,0x33,0x11,0xc8,0xdc,0x01,0x0e,0x64,0x32,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0xfc,0x9a,0x00,0x00,0x00,0x01,0xff,0xec,0x01,0x0e,0x01,0x5e,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x57,0x00,0x00,0x00,0x02,0x5f, 0x03,0x01,0x02,0x00,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x03,0x35,0x21,0x11,0x33,0x11,0x14,0x01,0x0e,0x64,0x01,0x0e,0xc8,0x02,0x8a,0xfc,0xae,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2d,0x40,0x2a,0x00,0x01,0x00,0x01,0x85,0x05,0x01,0x04,0x03,0x04,0x86,0x02, 0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x00,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x13,0x11,0x33,0x11,0x33,0x11,0x21,0x15,0x23,0x11,0xc8,0x32,0x64,0x01,0x0e,0xdc,0xfe,0x70,0x03,0x66,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x00,0x01,0x00,0xfa, 0x01,0x0e,0x02,0x6c,0x04,0x60,0x00,0x05,0x00,0x24,0x40,0x21,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x03,0x01,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x33,0x11,0x21,0x15,0xfa,0x64,0x01,0x0e,0x01,0x0e,0x03,0x52,0xfd,0x76,0xc8,0x00, 0x00,0x02,0xff,0xec,0x00,0xdc,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x0b,0x00,0x37,0x40,0x34,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07, 0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x03,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x05,0x35,0x21,0x15,0x14,0x01,0x0e,0x64,0x01,0x0e,0xfd,0x80,0x02,0x80,0x01,0xa4,0x64,0x02,0x58,0xfd,0xa8,0x64,0xc8,0x64,0x64,0x00,0x01,0xff,0xec,0x00,0xdc,0x01,0x5e,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x03,0x02,0x03,0x85,0x00,0x02,0x00, 0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x04,0x04,0x00,0x57,0x00,0x00,0x00,0x04,0x5f,0x05,0x01,0x04,0x00,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x27,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x14,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0x64,0xdc,0x64,0x64,0x64,0x02,0x58,0xfc,0x7c,0x00,0x00, 0x00,0x01,0x00,0xfa,0x00,0xdc,0x02,0x6c,0x04,0x60,0x00,0x09,0x00,0x2e,0x40,0x2b,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x06,0x06,0x1a,0x2b,0x37,0x11,0x33,0x11, 0x21,0x15,0x21,0x15,0x21,0x15,0xfa,0x64,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0xdc,0x03,0x84,0xfd,0xa8,0x64,0x64,0x64,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x13,0x00,0x38,0x40,0x35,0x04,0x01,0x02,0x01,0x02,0x85,0x0a,0x09,0x02,0x07,0x00,0x07,0x86,0x05,0x03,0x02,0x01,0x00,0x00,0x01,0x57,0x05,0x03,0x02, 0x01,0x01,0x00,0x5f,0x08,0x06,0x02,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x06,0x1f,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0x23,0x11,0x23,0x11,0x96,0xaa,0xaa,0x64,0x64,0x64,0xaa,0xaa,0x64,0x64,0xfe,0x70,0x02,0xd0, 0x64,0x02,0xbc,0xfd,0x44,0x02,0xbc,0xfd,0x44,0x64,0xfd,0x30,0x02,0xd0,0xfd,0x30,0x00,0x02,0xff,0xec,0xfe,0x70,0x01,0xc2,0x04,0x60,0x00,0x07,0x00,0x0b,0x00,0x35,0x40,0x32,0x04,0x01,0x02,0x01,0x02,0x85,0x07,0x05,0x06,0x03,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f, 0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x11,0x33,0x11,0x96,0xaa,0xaa,0x64,0x64,0x64,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfa,0x10,0x05,0xf0,0xfa,0x10,0x00,0x02,0x00,0x96,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x07, 0x00,0x0b,0x00,0x35,0x40,0x32,0x04,0x01,0x00,0x01,0x00,0x85,0x07,0x05,0x06,0x03,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x01,0x11,0x33,0x11,0x33,0x15,0x23, 0x11,0x21,0x11,0x33,0x11,0x01,0x5e,0x64,0xaa,0xaa,0xfe,0xd4,0x64,0xfe,0x70,0x05,0xf0,0xfd,0x44,0x64,0xfd,0x30,0x05,0xf0,0xfa,0x10,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01, 0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xdc,0xdc,0xc8,0xdc,0xdc,0xfe,0x70,0x02,0xd0,0x64,0x02,0xbc,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x90, 0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0xc8,0xdc,0xdc,0xc8,0xfe,0x70,0x02,0xd0, 0x64,0x02,0xbc,0xfa,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc8,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b, 0x13,0x11,0x33,0x11,0x33,0x15,0x23,0x11,0xc8,0xc8,0xdc,0xdc,0xfe,0x70,0x05,0xf0,0xfd,0x44,0x64,0xfd,0x30,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f, 0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0x9e,0xc8,0x02,0x8a,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e, 0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x21,0x35,0x21,0x11,0x33,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0x64,0xfe,0x70, 0x02,0x9e,0xc8,0x02,0x8a,0xfa,0x10,0x00,0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b, 0x13,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfa,0x64,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x05,0xf0,0xfd,0x76,0xc8,0xfd,0x62,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x13,0x00,0x3d,0x40,0x3a,0x00,0x04,0x03,0x04,0x85,0x0a,0x01,0x09,0x00,0x09,0x86,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x07,0x01,0x01, 0x00,0x00,0x01,0x57,0x07,0x01,0x01,0x01,0x00,0x5f,0x08,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x06,0x1f,0x2b,0x13,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0x01,0x0e, 0x64,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x02,0x6c,0x64,0x64,0x64,0x02,0x58,0xfd,0xa8,0x64,0x64,0x64,0xfd,0x94,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0xfe,0x70,0x01,0x5e,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x04,0x03,0x04,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x67,0x00, 0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x11,0x21,0x35,0x21,0x35,0x21,0x35,0x21,0x11,0x33,0x11,0xfa,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0x64,0xfe,0x70,0x02,0x6c,0x64,0x64,0x64,0x02,0x58,0xfa,0x10,0x00, 0x00,0x01,0x00,0xfa,0xfe,0x70,0x02,0x6c,0x04,0x60,0x00,0x0b,0x00,0x34,0x40,0x31,0x00,0x00,0x01,0x00,0x85,0x06,0x01,0x05,0x04,0x05,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06, 0x1b,0x2b,0x13,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0xfa,0x64,0x01,0x0e,0xfe,0xf2,0x01,0x0e,0xfe,0xf2,0xfe,0x70,0x05,0xf0,0xfd,0xa8,0x64,0x64,0x64,0xfd,0x94,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0xda,0x00,0x0b,0x00,0x2d,0x40,0x2a,0x00,0x02,0x03,0x01,0x01,0x00,0x02,0x01,0x67,0x04,0x01,0x00, 0x05,0x05,0x00,0x57,0x04,0x01,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x31,0x35,0x21,0x11,0x21,0x35,0x21,0x15,0x21,0x11,0x21,0x15,0x01,0x13,0xfe,0xed,0x02,0x58,0xfe,0xed,0x01,0x13,0x2d,0x02,0x80,0x2d,0x2d,0xfd,0x80,0x2d,0x00,0x00,0x00, 0x00,0x02,0x00,0x44,0xff,0xf5,0x02,0x2e,0x02,0x30,0x00,0x14,0x00,0x22,0x00,0x4d,0x40,0x4a,0x11,0x0e,0x0a,0x03,0x04,0x05,0x01,0x4c,0x00,0x02,0x01,0x05,0x01,0x02,0x05,0x80,0x00,0x03,0x04,0x00,0x04,0x03,0x00,0x80,0x00,0x01,0x00,0x05,0x04,0x01,0x05,0x69,0x07,0x01,0x04,0x03,0x00,0x04,0x59,0x07,0x01,0x04,0x04,0x00,0x61,0x06, 0x01,0x00,0x04,0x00,0x51,0x16,0x15,0x01,0x00,0x1d,0x1b,0x15,0x22,0x16,0x22,0x10,0x0f,0x0d,0x0c,0x08,0x06,0x00,0x14,0x01,0x14,0x08,0x06,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x37,0x33,0x03,0x13,0x23,0x27,0x23,0x06,0x06,0x27,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16, 0xf9,0x50,0x65,0x65,0x50,0x45,0x59,0x05,0x02,0x36,0x53,0x65,0x6c,0x55,0x3c,0x01,0x06,0x59,0x3f,0x2c,0x34,0x34,0x2c,0x2c,0x34,0x34,0x0b,0x67,0x57,0xbf,0x57,0x67,0x58,0x48,0x96,0xfe,0xf5,0xfe,0xe5,0xa6,0x50,0x61,0x4e,0x3c,0x34,0xbf,0x34,0x3c,0x3c,0x34,0xbf,0x34,0x3c,0x00,0x00,0x00,0x00,0x03,0x00,0x44,0xff,0x5b,0x02,0x2e, 0x02,0x30,0x00,0x14,0x00,0x22,0x00,0x26,0x00,0x5d,0x40,0x5a,0x11,0x0e,0x0a,0x03,0x04,0x05,0x01,0x4c,0x00,0x02,0x01,0x05,0x01,0x02,0x05,0x80,0x00,0x03,0x04,0x00,0x04,0x03,0x00,0x80,0x00,0x01,0x00,0x05,0x04,0x01,0x05,0x69,0x09,0x01,0x04,0x08,0x01,0x00,0x06,0x04,0x00,0x69,0x00,0x06,0x07,0x07,0x06,0x57,0x00,0x06,0x06,0x07, 0x5f,0x0a,0x01,0x07,0x06,0x07,0x4f,0x23,0x23,0x16,0x15,0x01,0x00,0x23,0x26,0x23,0x26,0x25,0x24,0x1d,0x1b,0x15,0x22,0x16,0x22,0x10,0x0f,0x0d,0x0c,0x08,0x06,0x00,0x14,0x01,0x14,0x0b,0x06,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x37,0x33,0x03,0x13,0x23,0x27,0x23,0x06,0x06,0x27,0x32,0x36,0x35, 0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x07,0x35,0x21,0x15,0xf9,0x50,0x65,0x65,0x50,0x45,0x59,0x05,0x02,0x36,0x53,0x65,0x6c,0x55,0x3c,0x01,0x06,0x59,0x3f,0x2c,0x34,0x34,0x2c,0x2c,0x34,0x34,0x87,0x01,0xe0,0x0b,0x67,0x57,0xbf,0x57,0x67,0x58,0x48,0x96,0xfe,0xf5,0xfe,0xe5,0xa6,0x50,0x61,0x4e,0x3c,0x34,0xbf,0x34, 0x3c,0x3c,0x34,0xbf,0x34,0x3c,0xe8,0x4b,0x4b,0x00,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x92,0x02,0x1c,0x03,0x3e,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x01,0x00,0x01,0x85,0x00,0x04,0x03,0x04,0x86,0x02,0x01,0x00,0x03,0x03,0x00,0x57,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b, 0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x13,0x35,0x33,0x03,0x33,0x13,0x33,0x15,0x23,0x13,0x23,0x03,0x3c,0xbd,0xae,0x5f,0xae,0xc4,0xa6,0x97,0x5f,0x97,0x01,0x22,0x50,0x01,0xcc,0xfe,0x34,0x50,0xfe,0x70,0x01,0x90,0x00,0xff,0xff,0xff,0xf6,0xff,0x92,0x02,0x62,0x03,0x3e,0x02,0x26,0x03,0x3e,0x00,0x00,0x00,0x06,0x04,0xbb, 0x00,0x00,0x00,0x00,0x00,0x04,0xff,0xf6,0x00,0x32,0x02,0x62,0x03,0xb1,0x00,0x0b,0x00,0x17,0x00,0x27,0x00,0x37,0x00,0x4d,0x40,0x4a,0x03,0x01,0x01,0x09,0x02,0x08,0x03,0x00,0x05,0x01,0x00,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x0b,0x01,0x06,0x04,0x04,0x06,0x59,0x0b,0x01,0x06,0x06,0x04,0x61,0x0a,0x01,0x04,0x06,0x04, 0x51,0x29,0x28,0x19,0x18,0x0d,0x0c,0x01,0x00,0x31,0x2f,0x28,0x37,0x29,0x37,0x21,0x1f,0x18,0x27,0x19,0x27,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x22,0x26, 0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x9b,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x52,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76, 0x4a,0x4a,0x76,0x44,0x44,0x76,0x03,0x31,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfd,0x01,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x00,0x00,0x04,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f, 0x00,0x1f,0x00,0x2b,0x00,0x37,0x00,0x53,0x40,0x50,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x0b,0x01,0x06,0x0a,0x01,0x04,0x02,0x06,0x04,0x69,0x09,0x01,0x02,0x00,0x00,0x02,0x59,0x09,0x01,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x02,0x00,0x51,0x2d,0x2c,0x21,0x20,0x11,0x10,0x01,0x00,0x33, 0x31,0x2c,0x37,0x2d,0x37,0x27,0x25,0x20,0x2b,0x21,0x2b,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x0c,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x35,0x34, 0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x36,0x49,0x49,0x36,0x36,0x49,0x49,0x36,0x23,0x2e,0x2e,0x23,0x22,0x2f,0x2f,0x32,0x51,0x8d,0x58, 0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x85,0x49,0x36,0x36,0x49,0x49,0x36,0x36,0x49,0x2e,0x2f,0x22,0x23,0x2e,0x2e,0x23,0x22,0x2f,0x00,0x03,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x29,0x00,0x4b,0x40,0x48,0x24,0x01,0x04,0x03, 0x29,0x28,0x27,0x21,0x04,0x02,0x04,0x02,0x4c,0x05,0x01,0x04,0x03,0x02,0x03,0x04,0x02,0x80,0x00,0x01,0x00,0x03,0x04,0x01,0x03,0x69,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x02,0x00,0x51,0x11,0x10,0x01,0x00,0x26,0x25,0x23,0x22,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01, 0x0f,0x08,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x37,0x27,0x33,0x37,0x17,0x33,0x07,0x17,0x27,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44, 0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x01,0x1e,0x4d,0x5b,0x1d,0x1d,0x5b,0x4d,0x1e,0x49,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x95,0x63,0x36,0x5d,0x5d,0x36,0x63,0x43,0x00,0x03,0xff,0xf6,0xff,0x92,0x02,0x62,0x03,0x3e,0x00,0x15, 0x00,0x1e,0x00,0x27,0x00,0x24,0x40,0x21,0x24,0x23,0x1b,0x1a,0x14,0x0c,0x09,0x01,0x08,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x15,0x00,0x15,0x1a,0x03,0x06,0x17,0x2b,0x05,0x35,0x2e,0x02,0x35,0x34,0x36,0x36,0x37,0x35,0x33,0x15,0x1e,0x02,0x15,0x14,0x06,0x06,0x07,0x15,0x01,0x14, 0x16,0x16,0x17,0x11,0x0e,0x02,0x05,0x34,0x26,0x26,0x27,0x11,0x3e,0x02,0x01,0x13,0x52,0x81,0x4a,0x4a,0x81,0x52,0x32,0x52,0x81,0x4a,0x4a,0x81,0x52,0xfe,0xe3,0x3d,0x6a,0x44,0x44,0x6a,0x3d,0x02,0x08,0x3d,0x6a,0x44,0x44,0x6a,0x3d,0x6e,0xa1,0x06,0x53,0x88,0x54,0x54,0x88,0x53,0x06,0xa1,0xa1,0x06,0x53,0x88,0x54,0x54,0x88,0x53, 0x06,0xa1,0x01,0xd6,0x46,0x71,0x46,0x06,0x02,0x06,0x06,0x46,0x71,0x46,0x46,0x71,0x46,0x06,0xfd,0xfa,0x06,0x46,0x71,0x00,0x00,0x03,0xff,0xf6,0xff,0x5b,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x23,0x00,0x41,0x40,0x3e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x07,0x01,0x02,0x06,0x01,0x00,0x04,0x02,0x00,0x69,0x00,0x04, 0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x04,0x05,0x4f,0x20,0x20,0x11,0x10,0x01,0x00,0x20,0x23,0x20,0x23,0x22,0x21,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x09,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35, 0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x03,0x35,0x21,0x15,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0xce,0x02,0x30,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44, 0x76,0x4a,0x4a,0x76,0x44,0xfe,0xf7,0x4b,0x4b,0x00,0x00,0x00,0x00,0x02,0x00,0x8c,0x00,0x68,0x01,0xcc,0x02,0x26,0x00,0x03,0x00,0x07,0x00,0x33,0x40,0x30,0x00,0x02,0x01,0x03,0x01,0x02,0x03,0x80,0x05,0x01,0x03,0x03,0x84,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x04,0x01,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00, 0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0x01,0x13,0x33,0x03,0x8c,0x01,0x40,0xfe,0xd9,0x50,0x82,0x82,0x01,0xdb,0x4b,0x4b,0xfe,0x8d,0x01,0x37,0xfe,0xc9,0x00,0x00,0x00,0x00,0x04,0x00,0x32,0x00,0x00,0x02,0x26,0x03,0xb1,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x24,0x00,0x42, 0x40,0x3f,0x09,0x01,0x05,0x06,0x05,0x86,0x03,0x01,0x01,0x08,0x02,0x07,0x03,0x00,0x04,0x01,0x00,0x69,0x00,0x04,0x06,0x06,0x04,0x57,0x00,0x04,0x04,0x06,0x5f,0x00,0x06,0x04,0x06,0x4f,0x18,0x18,0x0d,0x0c,0x01,0x00,0x21,0x20,0x18,0x1b,0x18,0x1b,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0a,0x06, 0x16,0x2b,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x33,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x03,0x21,0x03,0x27,0x36,0x36,0x37,0x13,0x21,0x13,0x16,0x16,0xbd,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xc1,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xca,0xbc,0x01,0xf4,0xbd,0x3c,0x04,0x13,0x0d, 0x65,0xfe,0xec,0x69,0x0d,0x11,0x03,0x31,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfc,0xcf,0x02,0xda,0xfd,0x26,0x46,0x17,0x59,0x34,0x01,0xa0,0xfe,0x5f,0x34,0x58,0x00,0x03,0x00,0x32,0xff,0x92,0x02,0x26,0x03,0x3e,0x00,0x0b,0x00,0x0e,0x00,0x11,0x00,0x42,0x40,0x3f,0x0f,0x0c,0x02,0x00, 0x06,0x01,0x4c,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x00,0x06,0x05,0x06,0x00,0x05,0x80,0x08,0x01,0x05,0x05,0x84,0x03,0x01,0x01,0x06,0x06,0x01,0x57,0x03,0x01,0x01,0x01,0x06,0x5f,0x07,0x01,0x06,0x01,0x06,0x4f,0x00,0x00,0x11,0x10,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x09,0x06,0x1b,0x2b,0x05,0x35,0x23,0x03, 0x33,0x35,0x33,0x15,0x33,0x03,0x23,0x15,0x03,0x03,0x23,0x13,0x13,0x23,0x01,0x13,0x25,0xbc,0xe1,0x32,0xe1,0xbd,0x24,0x2d,0x04,0x72,0xa2,0x72,0x72,0x6e,0x6e,0x02,0xda,0x64,0x64,0xfd,0x26,0x6e,0x01,0x21,0x01,0xd7,0xfe,0x29,0x01,0xd7,0x00,0x00,0x00,0x03,0x00,0x32,0xff,0x92,0x02,0x26,0x03,0x3e,0x00,0x0b,0x00,0x0e,0x00,0x11, 0x00,0x40,0x40,0x3d,0x11,0x0e,0x02,0x06,0x01,0x01,0x4c,0x00,0x02,0x01,0x02,0x85,0x03,0x01,0x01,0x06,0x01,0x85,0x08,0x01,0x05,0x00,0x05,0x86,0x07,0x01,0x06,0x00,0x00,0x06,0x57,0x07,0x01,0x06,0x06,0x00,0x5f,0x04,0x01,0x00,0x06,0x00,0x4f,0x00,0x00,0x10,0x0f,0x0d,0x0c,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x09,0x06, 0x1b,0x2b,0x05,0x35,0x23,0x13,0x33,0x35,0x33,0x15,0x33,0x13,0x23,0x15,0x27,0x33,0x11,0x13,0x33,0x03,0x01,0x13,0xe1,0xbe,0x23,0x32,0x24,0xbd,0xe1,0xa3,0x72,0x30,0x73,0x73,0x6e,0x6e,0x02,0xda,0x64,0x64,0xfd,0x26,0x6e,0xbe,0x01,0xd3,0xfe,0x2d,0x01,0xd2,0x00,0x00,0x00,0x03,0x00,0x2d,0xff,0x5b,0x02,0x2b,0x02,0xda,0x00,0x03, 0x00,0x0c,0x00,0x10,0x00,0x3c,0x40,0x39,0x09,0x01,0x02,0x00,0x01,0x4c,0x00,0x00,0x02,0x00,0x85,0x00,0x02,0x05,0x01,0x01,0x03,0x02,0x01,0x67,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x06,0x01,0x04,0x03,0x04,0x4f,0x0d,0x0d,0x00,0x00,0x0d,0x10,0x0d,0x10,0x0f,0x0e,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x07,0x06, 0x17,0x2b,0x33,0x13,0x33,0x13,0x25,0x21,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x35,0x21,0x15,0x32,0xbe,0x79,0xbd,0xfe,0x7c,0x01,0x15,0x67,0x0d,0x12,0x05,0x04,0x13,0x0d,0xdb,0x01,0xfe,0x02,0xda,0xfd,0x26,0x50,0x01,0x9f,0x34,0x5a,0x17,0x16,0x5a,0x34,0xfd,0x6b,0x4b,0x4b,0x00,0x00,0x00,0x03,0x00,0x32,0x00,0x00,0x02,0x26, 0x03,0xb1,0x00,0x19,0x00,0x1d,0x00,0x26,0x00,0x97,0x4b,0xb0,0x14,0x50,0x58,0x40,0x35,0x00,0x05,0x03,0x01,0x04,0x05,0x72,0x00,0x02,0x04,0x00,0x01,0x02,0x72,0x0a,0x01,0x07,0x08,0x07,0x86,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x09,0x01,0x00,0x06,0x04,0x00,0x6a,0x00,0x06,0x08,0x08,0x06,0x57,0x00,0x06,0x06,0x08, 0x5f,0x00,0x08,0x06,0x08,0x4f,0x1b,0x40,0x37,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x0a,0x01,0x07,0x08,0x07,0x86,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x09,0x01,0x00,0x06,0x04,0x00,0x6a,0x00,0x06,0x08,0x08,0x06,0x57,0x00,0x06,0x06,0x08,0x5f,0x00,0x08,0x06,0x08,0x4f, 0x59,0x40,0x1d,0x1a,0x1a,0x01,0x00,0x23,0x22,0x1a,0x1d,0x1a,0x1d,0x1c,0x1b,0x16,0x15,0x13,0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x0b,0x06,0x16,0x2b,0x01,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x03,0x03,0x21,0x03,0x27,0x36,0x36, 0x37,0x13,0x21,0x13,0x16,0x16,0x01,0x72,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x32,0x28,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x31,0xad,0xbc,0x01,0xf4,0xbd,0x3c,0x04,0x13,0x0d,0x65,0xfe,0xec,0x69,0x0d,0x11,0x03,0x2f,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0xfc,0xd1,0x02,0xda,0xfd,0x26, 0x46,0x17,0x59,0x34,0x01,0xa0,0xfe,0x5f,0x34,0x58,0x00,0x00,0x00,0x03,0xff,0xf6,0xff,0x5b,0x02,0x62,0x02,0x9f,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x27,0x40,0x24,0x07,0x06,0x05,0x03,0x02,0x01,0x06,0x00,0x4a,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x08,0x08,0x08,0x0b,0x08,0x0b, 0x19,0x03,0x06,0x17,0x2b,0x25,0x09,0x02,0x05,0x37,0x27,0x07,0x03,0x35,0x21,0x15,0x01,0x2c,0xfe,0xca,0x01,0x36,0x01,0x36,0xfe,0xca,0xe8,0xe8,0xe8,0x30,0x02,0x30,0x32,0x01,0x36,0x01,0x37,0xfe,0xc9,0xe8,0xe8,0xe9,0xe9,0xfd,0xf3,0x4b,0x4b,0x00,0xff,0xff,0x00,0x3c,0x00,0x32,0x02,0x1c,0x03,0x0c,0x00,0x27,0x06,0x72,0x02,0x58, 0x00,0x00,0x02,0x06,0x04,0x27,0x00,0x00,0x00,0x01,0x00,0x50,0xff,0x92,0x02,0x08,0x03,0x3e,0x00,0x17,0x00,0x28,0x40,0x25,0x16,0x0d,0x0a,0x01,0x04,0x03,0x00,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x03,0x00,0x85,0x04,0x01,0x03,0x03,0x76,0x00,0x00,0x00,0x17,0x00,0x17,0x15,0x15,0x15,0x05,0x06,0x19,0x2b,0x05,0x35, 0x26,0x26,0x35,0x11,0x33,0x11,0x14,0x16,0x17,0x11,0x33,0x11,0x36,0x36,0x35,0x11,0x33,0x11,0x14,0x06,0x07,0x15,0x01,0x13,0x5a,0x69,0x32,0x4e,0x43,0x32,0x43,0x4e,0x32,0x69,0x5a,0x6e,0xc9,0x08,0x75,0x5e,0x01,0x40,0xfe,0xbb,0x47,0x5a,0x08,0x02,0xb6,0xfd,0x4a,0x08,0x5a,0x47,0x01,0x45,0xfe,0xc0,0x5e,0x75,0x08,0xc9,0x00,0x00, 0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x19,0x00,0x22,0x00,0x2b,0x00,0x4b,0x40,0x48,0x00,0x00,0x01,0x00,0x85,0x07,0x01,0x01,0x0b,0x0c,0x02,0x08,0x09,0x01,0x08,0x69,0x0d,0x0a,0x02,0x09,0x06,0x01,0x02,0x03,0x09,0x02,0x69,0x05,0x01,0x03,0x04,0x04,0x03,0x57,0x05,0x01,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04, 0x4f,0x24,0x23,0x1b,0x1a,0x29,0x28,0x23,0x2b,0x24,0x2b,0x20,0x1f,0x1a,0x22,0x1b,0x22,0x14,0x21,0x11,0x11,0x12,0x14,0x21,0x10,0x0e,0x06,0x1e,0x2b,0x13,0x33,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x33,0x15,0x21,0x35,0x33,0x35,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x07,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x35, 0x17,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x15,0xff,0x5a,0x05,0x35,0x43,0x43,0x35,0x05,0xff,0xfd,0xa8,0xff,0x05,0x34,0x44,0x44,0x34,0x05,0x05,0x23,0x2d,0x2d,0x23,0x05,0x5f,0x23,0x2d,0x2d,0x23,0x05,0x02,0x58,0x91,0x43,0x35,0x34,0x44,0x87,0x50,0x50,0x87,0x44,0x34,0x35,0x43,0x28,0x2d,0x23,0x23,0x2d,0xa0,0xa0,0x2d,0x23,0x23, 0x2d,0xa0,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0x5b,0x02,0x58,0x02,0x58,0x00,0x07,0x00,0x0b,0x00,0x37,0x40,0x34,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09, 0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x31,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x05,0x35,0x21,0x15,0xff,0x5a,0xff,0xfd,0xa8,0x02,0x58,0x50,0x02,0x08,0xfd,0xf8,0x50,0xa5,0x4b,0x4b,0x00,0x00,0x01,0x00,0x00,0xff,0xf6,0x02,0x58,0x02,0xda,0x00,0x0e,0x00,0x2b,0x40,0x28,0x00,0x03,0x02,0x03,0x85,0x06,0x01,0x00, 0x01,0x00,0x86,0x04,0x01,0x02,0x01,0x01,0x02,0x57,0x04,0x01,0x02,0x02,0x01,0x5f,0x05,0x01,0x01,0x02,0x01,0x4f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1d,0x2b,0x05,0x27,0x33,0x35,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x15,0x33,0x01,0x2d,0xc9,0x9b,0xff,0xff,0x5a,0xff,0xff,0x9b,0x0a,0xa9,0xa6,0x50,0x01,0x45, 0xfe,0xbb,0x50,0xa6,0x00,0x02,0x00,0x50,0xff,0x5b,0x02,0x17,0x02,0x2d,0x00,0x2c,0x00,0x30,0x00,0x62,0x40,0x5f,0x07,0x01,0x05,0x04,0x01,0x4c,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x07,0x05,0x06,0x05,0x07,0x06,0x80,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x00,0x05,0x07,0x04,0x05,0x67,0x00,0x06,0x0a,0x01, 0x00,0x08,0x06,0x00,0x69,0x00,0x08,0x09,0x09,0x08,0x57,0x00,0x08,0x08,0x09,0x5f,0x0b,0x01,0x09,0x08,0x09,0x4f,0x2d,0x2d,0x02,0x00,0x2d,0x30,0x2d,0x30,0x2f,0x2e,0x2a,0x29,0x27,0x24,0x20,0x1e,0x1d,0x1b,0x18,0x15,0x13,0x12,0x10,0x0d,0x00,0x2c,0x02,0x2c,0x0c,0x06,0x16,0x2b,0x05,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26, 0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x05,0x35,0x21,0x15,0x01,0x4b,0x34,0x5b,0x6c,0x41,0x46,0x3a,0x3b,0x64,0x58,0x2e,0x53,0x6b,0x09,0x5f,0x05,0x38,0x2b,0x2e,0x5d,0x30,0x2e,0x7b,0x83, 0x33,0x35,0x37,0x31,0x34,0x2e,0x3b,0x04,0x5f,0x0a,0x6d,0xfe,0xc2,0x01,0x9e,0x07,0x58,0x49,0x3e,0x47,0x05,0x04,0x04,0x3a,0x31,0x47,0x4f,0x4c,0x42,0x1d,0x21,0x4b,0x24,0x2a,0x4e,0x30,0x28,0x25,0x30,0x1f,0x1a,0x40,0x49,0x9e,0x4b,0x4b,0x00,0x00,0xff,0xff,0x00,0x55,0x00,0x41,0x02,0x03,0x03,0x09,0x02,0x26,0x04,0x1b,0x00,0x00, 0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0xff,0xff,0x00,0x37,0x00,0x00,0x02,0x26,0x02,0x26,0x02,0x06,0x02,0x7d,0x00,0x00,0x00,0x02,0x00,0x37,0xff,0x5b,0x02,0x26,0x02,0x26,0x00,0x0d,0x00,0x11,0x00,0x3c,0x40,0x39,0x00,0x02,0x00,0x01,0x03,0x02,0x01,0x67,0x00,0x03,0x06,0x01,0x00,0x04,0x03,0x00,0x67,0x00,0x04,0x05,0x05,0x04, 0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x0e,0x0e,0x01,0x00,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x0c,0x0a,0x07,0x06,0x05,0x04,0x00,0x0d,0x01,0x0d,0x08,0x06,0x16,0x2b,0x21,0x22,0x26,0x35,0x11,0x23,0x35,0x21,0x11,0x14,0x16,0x33,0x33,0x15,0x05,0x35,0x21,0x15,0x01,0x9f,0x49,0x57,0xc8,0x01,0x22,0x26,0x20,0x87, 0xfe,0x16,0x01,0xea,0x55,0x46,0x01,0x39,0x52,0xfe,0x75,0x22,0x27,0x52,0xa5,0x4b,0x4b,0x00,0x00,0x00,0x00,0x04,0x00,0x7d,0x00,0xd2,0x01,0xdb,0x02,0xaf,0x00,0x0b,0x00,0x17,0x00,0x23,0x00,0x2f,0x00,0x4d,0x40,0x4a,0x03,0x01,0x01,0x09,0x02,0x08,0x03,0x00,0x05,0x01,0x00,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x0b,0x01, 0x06,0x04,0x04,0x06,0x59,0x0b,0x01,0x06,0x06,0x04,0x61,0x0a,0x01,0x04,0x06,0x04,0x51,0x25,0x24,0x19,0x18,0x0d,0x0c,0x01,0x00,0x2b,0x29,0x24,0x2f,0x25,0x2f,0x1f,0x1d,0x18,0x23,0x19,0x23,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0c,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14, 0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x9b,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x52,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0x35,0x23, 0x2d,0x2d,0x23,0x23,0x2d,0x2d,0x02,0x2f,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfe,0xa3,0x44,0x34,0x35,0x43,0x43,0x35,0x34,0x44,0x28,0x2d,0x23,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x00,0x00,0x03,0x00,0x8c,0xff,0x5b,0x01,0xcc,0x01,0xc2,0x00,0x0b,0x00,0x17,0x00,0x1b,0x00,0x41,0x40,0x3e, 0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x07,0x01,0x02,0x06,0x01,0x00,0x04,0x02,0x00,0x69,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x04,0x05,0x4f,0x18,0x18,0x0d,0x0c,0x01,0x00,0x18,0x1b,0x18,0x1b,0x1a,0x19,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x09,0x06,0x16,0x2b,0x25, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x03,0x35,0x21,0x15,0x01,0x2c,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0x35,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x2d,0x7d,0x01,0x40,0xd2,0x44,0x34,0x35,0x43,0x43,0x35,0x34,0x44,0x28,0x2d,0x23,0x23,0x2d,0x2d,0x23,0x23, 0x2d,0xfe,0x61,0x4b,0x4b,0x00,0x00,0x00,0x00,0x02,0x00,0x1e,0xff,0x92,0x02,0x3a,0x03,0x3e,0x00,0x14,0x00,0x1d,0x00,0x45,0x40,0x42,0x00,0x02,0x01,0x02,0x85,0x0a,0x01,0x07,0x00,0x07,0x86,0x03,0x01,0x01,0x09,0x01,0x04,0x05,0x01,0x04,0x69,0x0b,0x08,0x02,0x05,0x00,0x00,0x05,0x59,0x0b,0x08,0x02,0x05,0x05,0x00,0x61,0x06,0x01, 0x00,0x05,0x00,0x51,0x16,0x15,0x00,0x00,0x19,0x17,0x15,0x1d,0x16,0x1d,0x00,0x14,0x00,0x14,0x11,0x11,0x11,0x11,0x11,0x24,0x21,0x0c,0x06,0x1d,0x2b,0x05,0x11,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x23,0x11,0x03,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2a,0x30,0x65,0x77, 0x77,0x65,0x30,0x32,0xde,0xde,0xde,0xde,0x67,0x35,0x35,0x4c,0x59,0x59,0x6e,0x01,0x04,0x75,0x62,0x62,0x75,0xfa,0xfa,0x2d,0xfe,0xac,0x2d,0xfe,0xfc,0x01,0x31,0x01,0x54,0x5c,0x4e,0x4e,0x5c,0x00,0x00,0x00,0x00,0x01,0xff,0xec,0x00,0x00,0x02,0x58,0x02,0xda,0x00,0x0e,0x00,0x37,0x40,0x34,0x06,0x01,0x02,0x03,0x05,0x01,0x01,0x02, 0x04,0x01,0x00,0x01,0x03,0x4c,0x00,0x03,0x02,0x03,0x85,0x00,0x00,0x01,0x00,0x86,0x04,0x01,0x02,0x01,0x01,0x02,0x57,0x04,0x01,0x02,0x02,0x01,0x5f,0x05,0x01,0x01,0x02,0x01,0x4f,0x11,0x11,0x11,0x14,0x11,0x10,0x06,0x06,0x1c,0x2b,0x21,0x23,0x11,0x23,0x15,0x27,0x37,0x15,0x33,0x11,0x33,0x11,0x33,0x15,0x23,0x01,0x59,0x5a,0x77, 0x9c,0x9c,0x77,0x5a,0xff,0xff,0x01,0x45,0xa0,0xc8,0xc8,0xa0,0x01,0x45,0xfe,0xbb,0x50,0x00,0x00,0x00,0x00,0x01,0x00,0x37,0xff,0xf6,0x02,0x21,0x02,0x30,0x00,0x2a,0x00,0x3a,0x40,0x37,0x28,0x01,0x01,0x02,0x01,0x4c,0x1e,0x1d,0x08,0x07,0x04,0x02,0x4a,0x00,0x02,0x01,0x02,0x85,0x03,0x01,0x01,0x00,0x00,0x01,0x59,0x03,0x01,0x01, 0x01,0x00,0x61,0x04,0x05,0x02,0x00,0x01,0x00,0x51,0x01,0x00,0x26,0x24,0x18,0x16,0x13,0x12,0x0f,0x0d,0x00,0x2a,0x01,0x2a,0x06,0x06,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x15,0x06,0x06,0x15,0x15,0x14,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x35,0x35,0x34,0x26,0x27,0x35,0x16,0x16,0x15,0x15,0x14, 0x06,0x23,0x22,0x26,0x27,0x06,0x06,0xb5,0x3a,0x44,0x4b,0x41,0x1a,0x1d,0x3d,0x1d,0x21,0x4a,0x21,0x1d,0x3d,0x1f,0x1d,0x44,0x4d,0x43,0x3b,0x31,0x3f,0x07,0x07,0x3f,0x0a,0x56,0x4b,0xcf,0x53,0x6d,0x0a,0x5f,0x05,0x3a,0x2c,0xd0,0x54,0x2c,0x28,0xc3,0xc3,0x28,0x2c,0x54,0xd0,0x29,0x37,0x06,0x5f,0x0a,0x6a,0x51,0xcf,0x4b,0x56,0x39, 0x32,0x32,0x39,0x00,0x00,0x02,0x00,0x37,0xff,0x5b,0x02,0x21,0x02,0x30,0x00,0x2a,0x00,0x2e,0x00,0x4a,0x40,0x47,0x28,0x01,0x01,0x02,0x01,0x4c,0x1e,0x1d,0x08,0x07,0x04,0x02,0x4a,0x00,0x02,0x01,0x02,0x85,0x03,0x01,0x01,0x04,0x07,0x02,0x00,0x05,0x01,0x00,0x69,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05,0x06,0x5f,0x08,0x01, 0x06,0x05,0x06,0x4f,0x2b,0x2b,0x01,0x00,0x2b,0x2e,0x2b,0x2e,0x2d,0x2c,0x26,0x24,0x18,0x16,0x13,0x12,0x0f,0x0d,0x00,0x2a,0x01,0x2a,0x09,0x06,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x15,0x06,0x06,0x15,0x15,0x14,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x35,0x35,0x34,0x26,0x27,0x35,0x16,0x16,0x15, 0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x06,0x06,0x07,0x35,0x21,0x15,0xb5,0x3a,0x44,0x4b,0x41,0x1a,0x1d,0x3d,0x1d,0x21,0x4a,0x21,0x1d,0x3d,0x1f,0x1d,0x44,0x4d,0x43,0x3b,0x31,0x3f,0x07,0x07,0x3f,0xaf,0x01,0xea,0x0a,0x56,0x4b,0xcf,0x53,0x6d,0x0a,0x5f,0x05,0x3a,0x2c,0xd0,0x54,0x2c,0x28,0xc3,0xc3,0x28,0x2c,0x54,0xd0,0x29,0x37, 0x06,0x5f,0x0a,0x6a,0x51,0xcf,0x4b,0x56,0x39,0x32,0x32,0x39,0x9b,0x4b,0x4b,0x00,0x00,0x02,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x07,0x06,0x05, 0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x06,0x00,0x09,0x00,0x31,0x40,0x2e,0x09,0x06,0x02,0x03,0x02,0x01,0x4c,0x00, 0x00,0x00,0x02,0x03,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x00,0x00,0x08,0x07,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x03,0x21,0x01,0x05,0x21,0x01,0x02,0x58,0x32,0xfe,0x2a,0x01,0xd6,0xfe,0x0c,0x01,0xd8,0xfe,0x28,0x6f,0x03, 0xad,0xfc,0x53,0x03,0x80,0xfc,0xda,0x2d,0x03,0x29,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x0c,0x00,0x1c,0x00,0x25,0x00,0x55,0x40,0x52,0x25,0x1f,0x0a,0x07,0x04,0x04,0x05,0x01,0x4c,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x09,0x01,0x02,0x00,0x05,0x04,0x02,0x05,0x69,0x0a,0x01,0x04,0x00, 0x07,0x06,0x04,0x07,0x69,0x00,0x06,0x01,0x01,0x06,0x57,0x00,0x06,0x06,0x01,0x5f,0x08,0x01,0x01,0x06,0x01,0x4f,0x0e,0x0d,0x05,0x04,0x00,0x00,0x23,0x21,0x1e,0x1d,0x16,0x14,0x0d,0x1c,0x0e,0x1c,0x09,0x08,0x04,0x0c,0x05,0x0c,0x00,0x03,0x00,0x03,0x11,0x0b,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x32,0x16,0x17,0x35,0x21,0x15, 0x36,0x36,0x13,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x07,0x21,0x35,0x06,0x06,0x23,0x22,0x26,0x27,0x02,0x58,0xfe,0xd4,0x50,0x83,0x27,0xfe,0x0c,0x28,0x82,0x50,0x48,0x71,0x41,0x41,0x71,0x48,0x47,0x71,0x42,0x42,0x71,0xb3,0x01,0xf4,0x27,0x83,0x50,0x50,0x82,0x28,0x6f,0x03,0xad,0xfc,0x53, 0x03,0x04,0x46,0x3b,0xfd,0xfd,0x3c,0x45,0xfd,0xd9,0x42,0x71,0x47,0x47,0x71,0x42,0x42,0x71,0x47,0x47,0x71,0x42,0xb0,0xfe,0x3b,0x46,0x45,0x3c,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x13,0x00,0x1f,0x00,0x4c,0x40,0x49,0x00,0x00,0x00,0x03,0x05,0x00,0x03,0x67,0x00,0x05,0x09,0x01,0x04,0x07, 0x05,0x04,0x69,0x00,0x07,0x0a,0x01,0x06,0x02,0x07,0x06,0x69,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x02,0x01,0x4f,0x15,0x14,0x09,0x08,0x00,0x00,0x1b,0x19,0x14,0x1f,0x15,0x1f,0x0f,0x0d,0x08,0x13,0x09,0x13,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x0b,0x06,0x17,0x2b,0x15,0x11,0x21,0x11, 0x25,0x21,0x11,0x21,0x13,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0xfa,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0x26,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0xfe,0xde,0x29,0x22, 0x22,0x29,0x29,0x22,0x22,0x29,0xfe,0x5c,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x0d,0x00,0x16,0x00,0x4c,0x40,0x49,0x0d,0x0a,0x02,0x06,0x02,0x01,0x4c,0x00,0x05,0x06,0x04,0x06,0x05,0x04,0x80,0x00,0x00,0x08,0x01,0x03,0x02,0x00,0x03,0x67,0x00,0x02, 0x00,0x06,0x05,0x02,0x06,0x67,0x00,0x04,0x01,0x01,0x04,0x57,0x00,0x04,0x04,0x01,0x5f,0x07,0x01,0x01,0x04,0x01,0x4f,0x04,0x04,0x00,0x00,0x13,0x12,0x0c,0x0b,0x09,0x08,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x15,0x21,0x35,0x01,0x21,0x11,0x03,0x23,0x03,0x13,0x36, 0x36,0x37,0x13,0x21,0x13,0x16,0x16,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x01,0xf4,0xbd,0x79,0xbe,0xfe,0x05,0x0f,0x0e,0x70,0xfe,0xd9,0x6f,0x0e,0x14,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80,0x37,0x37,0xfc,0xad,0x02,0xf7,0xfd,0x4b,0x02,0xb6,0xfd,0x90,0x17,0x5a,0x34,0x01,0x9f,0xfe,0x60,0x34,0x59,0x00,0x00,0x00,0x04,0x00,0x00, 0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x09,0x00,0x12,0x00,0x16,0x00,0x50,0x40,0x4d,0x0f,0x01,0x04,0x02,0x08,0x05,0x02,0x06,0x04,0x02,0x4c,0x00,0x02,0x03,0x04,0x03,0x02,0x04,0x80,0x00,0x00,0x08,0x01,0x03,0x02,0x00,0x03,0x67,0x00,0x04,0x00,0x06,0x05,0x04,0x06,0x67,0x00,0x05,0x01,0x01,0x05,0x57,0x00,0x05,0x05,0x01, 0x5f,0x07,0x01,0x01,0x05,0x01,0x4f,0x04,0x04,0x00,0x00,0x16,0x15,0x14,0x13,0x0b,0x0a,0x04,0x09,0x04,0x09,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x11,0x13,0x33,0x13,0x11,0x01,0x21,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x21,0x35,0x21,0x02,0x58,0xfd,0xda,0xbe,0x79,0xbd,0xfe,0x73, 0x01,0x27,0x70,0x0d,0x12,0x05,0x04,0x12,0x0e,0xd6,0x01,0xf4,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80,0xfd,0x14,0x02,0xb5,0xfd,0x4b,0x02,0xec,0xfd,0x3f,0x01,0x9f,0x34,0x5b,0x16,0x16,0x5a,0x34,0xfd,0xce,0x42,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x08,0x00,0x0c,0x00,0x11,0x00,0x37, 0x40,0x34,0x11,0x10,0x0f,0x0c,0x0b,0x0a,0x08,0x05,0x08,0x03,0x02,0x01,0x4c,0x00,0x00,0x00,0x02,0x03,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x00,0x00,0x0e,0x0d,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x17,0x11,0x21,0x11, 0x13,0x37,0x27,0x07,0x03,0x21,0x11,0x07,0x27,0x02,0x58,0xfe,0xd4,0xfa,0xfe,0x0c,0xfa,0xe8,0xe8,0xe8,0x12,0x01,0xf4,0xfa,0xfa,0x6f,0x03,0xad,0xfc,0x53,0x03,0x0e,0xfb,0x01,0x6d,0xfe,0x93,0xfe,0xdc,0xe8,0xe9,0xe9,0xfe,0x56,0x01,0x6e,0xfa,0xfa,0x00,0x05,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x13, 0x00,0x17,0x00,0x23,0x00,0x5d,0x40,0x5a,0x00,0x00,0x0b,0x01,0x03,0x05,0x00,0x03,0x67,0x00,0x05,0x0c,0x01,0x04,0x02,0x05,0x04,0x69,0x00,0x02,0x00,0x07,0x09,0x02,0x07,0x67,0x00,0x09,0x0d,0x01,0x08,0x06,0x09,0x08,0x69,0x00,0x06,0x01,0x01,0x06,0x57,0x00,0x06,0x06,0x01,0x5f,0x0a,0x01,0x01,0x06,0x01,0x4f,0x19,0x18,0x09,0x08, 0x04,0x04,0x00,0x00,0x1f,0x1d,0x18,0x23,0x19,0x23,0x17,0x16,0x15,0x14,0x0f,0x0d,0x08,0x13,0x09,0x13,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0e,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x11,0x21,0x11,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x21,0x11,0x21,0x17,0x22,0x26,0x35,0x34, 0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfa,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0xfe,0xe0,0x01,0xf4,0xfe,0x0c,0xfa,0x25,0x2e,0x2e,0x25,0x26,0x2d,0x2d,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80,0xfe,0x7c,0x01,0x84,0xfe,0xd4,0x29,0x22,0x22,0x29,0x29,0x22,0x22,0x29,0xfd,0xd9,0x01,0x84,0xf2,0x29,0x22,0x22, 0x29,0x29,0x22,0x22,0x29,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x1e,0x00,0x47,0x40,0x44,0x14,0x13,0x11,0x10,0x04,0x04,0x03,0x12,0x01,0x02,0x04,0x02,0x4c,0x05,0x01,0x04,0x03,0x02,0x03,0x04,0x02,0x80,0x00,0x00,0x06,0x01,0x03,0x04,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00, 0x02,0x02,0x01,0x60,0x07,0x01,0x01,0x02,0x01,0x50,0x00,0x00,0x1e,0x1d,0x19,0x18,0x0c,0x0b,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x23,0x11,0x14,0x06,0x07,0x33,0x36,0x36,0x37,0x37,0x15,0x07,0x27,0x35,0x17,0x16,0x16,0x17,0x33,0x26,0x26,0x35,0x11,0x23,0x02,0x58, 0xfd,0xda,0x01,0xf4,0xcd,0x03,0x02,0x0a,0x05,0x1b,0x16,0x60,0xc7,0xc9,0x5f,0x16,0x1d,0x04,0x0a,0x01,0x04,0xcd,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0xfd,0xc1,0x16,0x2d,0x0d,0x06,0x1d,0x12,0x51,0x69,0xa9,0xa9,0x69,0x50,0x12,0x1d,0x07,0x0d,0x2d,0x16,0x02,0x3f,0x00,0x03,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03, 0x00,0x0e,0x00,0x14,0x00,0x3e,0x40,0x3b,0x14,0x11,0x0e,0x0b,0x07,0x05,0x04,0x02,0x01,0x4c,0x00,0x04,0x02,0x03,0x02,0x04,0x03,0x80,0x00,0x00,0x00,0x02,0x04,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x05,0x01,0x01,0x03,0x01,0x4f,0x00,0x00,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x00,0x03,0x00,0x03,0x11, 0x06,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x16,0x16,0x17,0x36,0x36,0x37,0x13,0x35,0x21,0x15,0x11,0x21,0x11,0x03,0x23,0x03,0x02,0x58,0xfe,0xb4,0x0b,0x12,0x04,0x05,0x13,0x0a,0xd7,0xfe,0x0c,0x01,0xf4,0xdb,0x3e,0xdb,0x6f,0x03,0xad,0xfc,0x53,0xf0,0x1c,0x3a,0x11,0x11,0x3b,0x1b,0x02,0x49,0x47,0x3c,0xfc,0xe9,0x02,0x8f,0xfd, 0xa8,0x02,0x58,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x47,0x40,0x44,0x00,0x00,0x09,0x01,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x04,0x00,0x07,0x06,0x04,0x07,0x67,0x00,0x06,0x01,0x01,0x06,0x57,0x00,0x06,0x06,0x01,0x5f,0x08,0x01, 0x01,0x06,0x01,0x4f,0x04,0x04,0x00,0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0a,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x11,0x21,0x11,0x01,0x21,0x35,0x21,0x11,0x21,0x11,0x21,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x01,0xf4,0xfe,0x0c,0x01,0xf4,0xfe,0x0c,0x6f, 0x03,0xad,0xfc,0x53,0x03,0x80,0xfe,0xf7,0x01,0x09,0xfe,0x07,0xa0,0xfe,0x06,0x01,0x0a,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x10,0x00,0x14,0x00,0x3b,0x40,0x38,0x14,0x13,0x0e,0x0a,0x09,0x06,0x05,0x07,0x03,0x02,0x01,0x4c,0x00,0x00,0x05,0x01,0x02,0x03,0x00,0x02,0x67,0x00, 0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x04,0x04,0x00,0x00,0x12,0x11,0x04,0x07,0x04,0x07,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x15,0x05,0x11,0x03,0x25,0x11,0x25,0x36,0x36,0x37,0x26,0x26,0x01,0x21,0x11,0x05,0x02,0x58,0xfd,0xda,0x01,0xf4,0x78,0xfe, 0x84,0x01,0x7c,0x13,0x21,0x08,0x09,0x22,0xfe,0x73,0x01,0xf4,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80,0x7c,0xfa,0x01,0x76,0xfe,0x6e,0xbc,0xfe,0x59,0xbb,0x09,0x0d,0x02,0x02,0x0e,0xfe,0x47,0x01,0x79,0xfa,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x02,0x26,0x04,0x4d,0x00,0x28,0x01,0x06,0x05,0x85, 0x00,0x00,0x00,0x08,0xb1,0x00,0x02,0xb0,0x28,0xb0,0x35,0x2b,0x00,0x02,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x1e,0x00,0x5a,0x40,0x57,0x17,0x01,0x06,0x05,0x18,0x11,0x0a,0x03,0x03,0x06,0x0b,0x01,0x04,0x03,0x03,0x4c,0x00,0x05,0x07,0x06,0x07,0x05,0x06,0x80,0x00,0x04,0x03,0x02,0x03,0x04,0x02,0x80,0x00,0x00, 0x00,0x07,0x05,0x00,0x07,0x67,0x00,0x06,0x00,0x03,0x04,0x06,0x03,0x68,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x1e,0x1d,0x1c,0x1a,0x13,0x12,0x10,0x0f,0x08,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x09,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x23,0x22,0x26, 0x27,0x15,0x16,0x16,0x17,0x17,0x23,0x27,0x37,0x33,0x07,0x06,0x06,0x07,0x15,0x36,0x36,0x33,0x33,0x11,0x21,0x02,0x58,0xfd,0xda,0x01,0xf4,0xf4,0x10,0x29,0x0d,0x09,0x1a,0x0a,0x57,0x6a,0x9c,0x9c,0x6a,0x57,0x0d,0x19,0x07,0x0d,0x29,0x10,0xf4,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x01,0x82,0x03,0x01,0x09,0x07,0x19,0x0d,0x6e, 0xc8,0xc8,0x6d,0x10,0x19,0x06,0x09,0x02,0x03,0x01,0x81,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x10,0x00,0x14,0x00,0x3b,0x40,0x38,0x14,0x13,0x0e,0x0a,0x09,0x06,0x05,0x07,0x03,0x02,0x01,0x4c,0x00,0x00,0x05,0x01,0x02,0x03,0x00,0x02,0x67,0x00,0x03,0x01,0x01,0x03,0x57,0x00,0x03,0x03, 0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x04,0x04,0x00,0x00,0x12,0x11,0x04,0x07,0x04,0x07,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x11,0x25,0x35,0x01,0x05,0x11,0x05,0x06,0x06,0x07,0x16,0x16,0x03,0x21,0x35,0x25,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x84,0x01,0x7c,0xfe,0x84,0x13,0x21,0x08,0x09, 0x22,0x67,0x01,0xf4,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80,0xfe,0x89,0xfa,0x7d,0xfe,0x41,0xbc,0x01,0xa7,0xbb,0x09,0x0d,0x02,0x02,0x0e,0xfe,0x64,0x7e,0xfa,0x00,0x05,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x1b,0x00,0x67,0x40,0x64,0x0f,0x01,0x05,0x03,0x02,0x03,0x05,0x02, 0x80,0x00,0x0c,0x0b,0x0a,0x0b,0x0c,0x0a,0x80,0x00,0x00,0x00,0x03,0x05,0x00,0x03,0x67,0x04,0x01,0x02,0x09,0x01,0x07,0x06,0x02,0x07,0x67,0x08,0x01,0x06,0x0d,0x01,0x0b,0x0c,0x06,0x0b,0x67,0x00,0x0a,0x01,0x01,0x0a,0x57,0x00,0x0a,0x0a,0x01,0x5f,0x0e,0x01,0x01,0x0a,0x01,0x4f,0x04,0x04,0x00,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16, 0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x04,0x0b,0x04,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x10,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x03,0x07,0x33,0x11,0x21,0x11,0x21,0x37,0x01,0x33,0x37,0x23,0x05,0x33,0x35,0x23,0x01,0x21,0x11,0x21,0x07,0x23,0x37,0x23,0x02,0x58,0x8e,0x40,0x9c,0xfe,0x0c, 0x01,0x12,0x40,0xfe,0xae,0xba,0x3a,0xf4,0x01,0x00,0xf4,0xba,0xfe,0xc6,0x01,0xf4,0xfe,0xee,0x3e,0x46,0x3e,0x9c,0x6f,0x03,0xad,0xfc,0x53,0x03,0x26,0xaf,0x01,0x09,0xfe,0xf7,0xaf,0xfe,0x61,0xa0,0xa0,0xa0,0xfe,0x06,0x01,0x0a,0xaa,0xaa,0x00,0x00,0x00,0x04,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x1c, 0x00,0x2a,0x00,0xa7,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x3a,0x0c,0x01,0x08,0x07,0x0a,0x07,0x08,0x72,0x00,0x00,0x00,0x03,0x06,0x00,0x03,0x67,0x00,0x06,0x00,0x05,0x04,0x06,0x05,0x67,0x00,0x04,0x00,0x07,0x08,0x04,0x07,0x69,0x00,0x0a,0x0d,0x01,0x09,0x02,0x0a,0x09,0x69,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x0b, 0x01,0x01,0x02,0x01,0x4f,0x1b,0x40,0x3b,0x0c,0x01,0x08,0x07,0x0a,0x07,0x08,0x0a,0x80,0x00,0x00,0x00,0x03,0x06,0x00,0x03,0x67,0x00,0x06,0x00,0x05,0x04,0x06,0x05,0x67,0x00,0x04,0x00,0x07,0x08,0x04,0x07,0x69,0x00,0x0a,0x0d,0x01,0x09,0x02,0x0a,0x09,0x69,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x0b,0x01,0x01, 0x02,0x01,0x4f,0x59,0x40,0x24,0x1e,0x1d,0x08,0x08,0x00,0x00,0x25,0x22,0x1d,0x2a,0x1e,0x29,0x08,0x1c,0x08,0x1c,0x1b,0x1a,0x14,0x12,0x11,0x0f,0x0b,0x09,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x0e,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x13,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x33,0x32, 0x16,0x16,0x15,0x14,0x06,0x06,0x07,0x15,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0x95,0x32,0x40,0x4b,0x4b,0x41,0x7d,0x7d,0x46,0x67,0x39,0x30,0x55,0x38,0x3d,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0xfd,0xbc, 0xb4,0x47,0x3b,0x3b,0x47,0x55,0x35,0x60,0x42,0x39,0x5b,0x36,0x03,0x69,0xd2,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x02,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x1e,0x00,0x5a,0x40,0x57,0x0d,0x01,0x04,0x05,0x1a,0x13,0x0c,0x03,0x07,0x04,0x19,0x01,0x06,0x07,0x03,0x4c,0x00,0x05,0x03,0x04,0x03,0x05, 0x04,0x80,0x00,0x06,0x07,0x02,0x07,0x06,0x02,0x80,0x00,0x00,0x00,0x03,0x05,0x00,0x03,0x67,0x00,0x04,0x00,0x07,0x06,0x04,0x07,0x68,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x08,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x1e,0x1c,0x15,0x14,0x12,0x11,0x0a,0x08,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x09,0x06, 0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x11,0x33,0x32,0x16,0x17,0x35,0x26,0x26,0x27,0x27,0x33,0x17,0x07,0x23,0x37,0x36,0x36,0x37,0x35,0x06,0x06,0x23,0x23,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0xf4,0x11,0x28,0x0d,0x07,0x19,0x0d,0x57,0x6a,0x9c,0x9c,0x6a,0x57,0x0a,0x1a,0x09,0x0d,0x28,0x11,0xf4,0x6f,0x03,0xad, 0xfc,0x53,0x2d,0x03,0x53,0xfe,0x7f,0x03,0x02,0x09,0x06,0x19,0x10,0x6d,0xc8,0xc8,0x6e,0x0d,0x19,0x07,0x09,0x01,0x03,0x00,0x00,0x03,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x06,0x00,0x09,0x00,0x3c,0x40,0x39,0x08,0x05,0x02,0x03,0x02,0x01,0x4c,0x00,0x00,0x05,0x01,0x02,0x03,0x00,0x02,0x67,0x06,0x01,0x03,0x01, 0x01,0x03,0x57,0x06,0x01,0x03,0x03,0x01,0x5f,0x04,0x01,0x01,0x03,0x01,0x4f,0x07,0x07,0x04,0x04,0x00,0x00,0x07,0x09,0x07,0x09,0x04,0x06,0x04,0x06,0x00,0x03,0x00,0x03,0x11,0x07,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x11,0x01,0x13,0x11,0x01,0x02,0x58,0xfd,0xda,0x01,0xd8,0x1c,0xfe,0x28,0x6f,0x03,0xad,0xfc,0x53,0x03,0x80, 0xfc,0xd6,0x03,0x2a,0xfc,0xad,0x03,0x29,0xfc,0xd7,0x00,0x00,0x00,0x02,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x1e,0x00,0x48,0x40,0x45,0x10,0x01,0x03,0x06,0x12,0x11,0x0f,0x0e,0x04,0x02,0x03,0x02,0x4c,0x04,0x01,0x03,0x06,0x02,0x06,0x03,0x02,0x80,0x00,0x00,0x00,0x06,0x03,0x00,0x06,0x67,0x05,0x01,0x02,0x01, 0x01,0x02,0x57,0x05,0x01,0x02,0x02,0x01,0x5f,0x07,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x1e,0x1d,0x1c,0x1b,0x17,0x16,0x0a,0x09,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x33,0x11,0x34,0x36,0x37,0x23,0x06,0x06,0x07,0x07,0x35,0x37,0x17,0x15,0x27,0x26,0x26,0x27,0x23,0x16,0x16,0x15,0x11, 0x33,0x11,0x21,0x02,0x58,0xfd,0xda,0xcd,0x04,0x01,0x0a,0x04,0x1d,0x16,0x5f,0xc9,0xc7,0x60,0x16,0x1b,0x05,0x0a,0x02,0x03,0xcd,0xfe,0x0c,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x02,0x40,0x16,0x2d,0x0d,0x07,0x1d,0x12,0x50,0x69,0xa9,0xa9,0x69,0x51,0x12,0x1d,0x06,0x0d,0x2d,0x16,0xfd,0xc0,0x03,0x53,0x00,0x00,0x00,0x00,0x03,0x00,0x00, 0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x09,0x00,0x14,0x00,0x43,0x40,0x40,0x14,0x10,0x0c,0x08,0x05,0x05,0x04,0x03,0x01,0x4c,0x06,0x01,0x03,0x02,0x04,0x02,0x03,0x04,0x80,0x00,0x00,0x00,0x02,0x03,0x00,0x02,0x67,0x00,0x04,0x01,0x01,0x04,0x57,0x00,0x04,0x04,0x01,0x5f,0x05,0x01,0x01,0x04,0x01,0x4f,0x04,0x04,0x00,0x00, 0x0b,0x0a,0x04,0x09,0x04,0x09,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x07,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x01,0x13,0x11,0x21,0x11,0x13,0x03,0x21,0x35,0x03,0x26,0x26,0x27,0x06,0x06,0x07,0x03,0x02,0x58,0xfe,0xf3,0xdb,0xfe,0x0c,0xdb,0xdb,0x01,0xf4,0xd9,0x0a,0x13,0x05,0x04,0x12,0x0b,0xd8,0x6f,0x03,0xad,0xfc,0x53,0x03,0x49, 0xfd,0xa8,0x02,0x8f,0xfd,0x71,0x02,0x58,0xfc,0xe4,0x42,0x02,0x4e,0x1b,0x3b,0x11,0x11,0x3a,0x1c,0xfd,0xb2,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xff,0x91,0x02,0x58,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x0d,0x00,0x49,0x40,0x46,0x0c,0x09,0x02,0x05,0x04,0x01,0x4c,0x00,0x04,0x03,0x05,0x03,0x04,0x05,0x80,0x07,0x01,0x05,0x02,0x03, 0x05,0x02,0x7e,0x00,0x00,0x00,0x03,0x04,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x06,0x01,0x01,0x02,0x01,0x4f,0x08,0x08,0x00,0x00,0x08,0x0d,0x08,0x0d,0x0b,0x0a,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x08,0x06,0x17,0x2b,0x15,0x11,0x21,0x11,0x25,0x21,0x11,0x21,0x13,0x27,0x35,0x33,0x15, 0x07,0x02,0x58,0xfd,0xda,0x01,0xf4,0xfe,0x0c,0xd6,0x0c,0x60,0x0b,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0xfe,0x9d,0x96,0x96,0x96,0x96,0x00,0x00,0x02,0x00,0x8c,0xff,0x5b,0x01,0xcc,0x02,0xda,0x00,0x05,0x00,0x09,0x00,0x38,0x40,0x35,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x01,0x02,0x01,0x85, 0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f,0x06,0x06,0x00,0x00,0x06,0x09,0x06,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x12,0x06,0x06,0x17,0x2b,0x01,0x27,0x35,0x33,0x15,0x07,0x03,0x35,0x21,0x15,0x01,0x08,0x0c,0x60,0x0b,0xc5,0x01,0x40,0x01,0xae,0x96,0x96,0x96,0x96,0xfd,0xad,0x4b,0x4b, 0x00,0x02,0x00,0x5e,0xff,0x4c,0x01,0xfe,0x02,0x30,0x00,0x11,0x00,0x1f,0x00,0x3c,0x40,0x39,0x0e,0x01,0x03,0x04,0x01,0x4c,0x05,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x00,0x04,0x03,0x00,0x04,0x69,0x06,0x01,0x03,0x01,0x01,0x03,0x59,0x06,0x01,0x03,0x03,0x01,0x61,0x00,0x01,0x03,0x01,0x51,0x13,0x12,0x00,0x00,0x1a,0x18,0x12,0x1f, 0x13,0x1f,0x00,0x11,0x00,0x11,0x25,0x23,0x07,0x06,0x18,0x2b,0x17,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x23,0x17,0x15,0x37,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x5e,0x70,0x61,0x61,0x6e,0x5f,0x53,0x3e,0x4e,0x07,0x03,0x02,0x76,0x39,0x3d,0x3d,0x39,0x39,0x3d,0x3f, 0xb4,0x02,0x18,0x5f,0x6d,0x6d,0x5f,0xa1,0x5f,0x6e,0x3e,0x35,0x7d,0xa0,0xf8,0x44,0x40,0x96,0x40,0x44,0x44,0x40,0x96,0x3e,0x46,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x6c,0x02,0xda,0x00,0x0e,0x00,0x3d,0x40,0x3a,0x09,0x01,0x01,0x02,0x0a,0x01,0x00,0x01,0x0b,0x01,0x05,0x00,0x03,0x4c,0x00,0x02,0x01,0x02,0x85,0x06, 0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0e,0x00,0x0e,0x14,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x33,0x11,0x23,0x35,0x33,0x11,0x33,0x11,0x33,0x35,0x17,0x07,0x35,0x23,0x11,0xff,0xff,0xff,0x5a,0x77,0x9c,0x9c,0x77,0x01,0x45, 0x50,0x01,0x45,0xfe,0xbb,0xa0,0xc8,0xc8,0xa0,0xfe,0xbb,0x00,0x00,0x03,0x00,0x8c,0xff,0x5b,0x01,0xcc,0x02,0xe4,0x00,0x0d,0x00,0x11,0x00,0x15,0x00,0x48,0x40,0x45,0x00,0x02,0x00,0x03,0x00,0x02,0x03,0x80,0x07,0x01,0x03,0x04,0x00,0x03,0x04,0x7e,0x00,0x01,0x06,0x01,0x00,0x02,0x01,0x00,0x69,0x00,0x04,0x05,0x05,0x04,0x57,0x00, 0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x04,0x05,0x4f,0x12,0x12,0x0e,0x0e,0x01,0x00,0x12,0x15,0x12,0x15,0x14,0x13,0x0e,0x11,0x0e,0x11,0x10,0x0f,0x08,0x05,0x00,0x0d,0x01,0x0c,0x09,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x03,0x13,0x33,0x03,0x07,0x35,0x21,0x15,0x01,0x22,0x21,0x2a, 0x2b,0x20,0x14,0x20,0x2b,0x2a,0x21,0x8c,0x50,0x82,0x82,0x6e,0x01,0x40,0x02,0x4e,0x2a,0x21,0x20,0x2b,0x2b,0x20,0x21,0x2a,0xfd,0xc6,0x01,0x37,0xfe,0xc9,0xb9,0x4b,0x4b,0x00,0x00,0x00,0x00,0x01,0x00,0x3c,0xff,0x92,0x02,0x1c,0x03,0x3e,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03, 0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1b,0x2b,0x17,0x13,0x23,0x35,0x33,0x13,0x33,0x03,0x33,0x15,0x23,0x03,0x4b,0x97,0xa6,0xc4,0xae,0x5f,0xae,0xbd,0xdb,0x97,0x6e,0x01,0x90,0x50,0x01,0xcc,0xfe,0x34,0x50, 0xfe,0x70,0x00,0x00,0x00,0x02,0x00,0xaa,0xff,0x91,0x01,0xae,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x04,0x01,0x01,0x02,0x01,0x4f,0x00,0x00,0x07,0x06,0x05,0x04,0x00,0x03,0x00,0x03,0x11,0x05,0x06,0x17,0x2b,0x17,0x11, 0x21,0x11,0x27,0x33,0x11,0x23,0xaa,0x01,0x04,0xd2,0xa0,0xa0,0x6f,0x03,0xad,0xfc,0x53,0x2d,0x03,0x53,0x00,0x03,0x00,0x7d,0x00,0xda,0x01,0xdb,0x02,0xaf,0x00,0x0b,0x00,0x17,0x00,0x21,0x00,0x42,0x40,0x3f,0x1c,0x01,0x04,0x00,0x01,0x4c,0x21,0x20,0x1f,0x19,0x04,0x04,0x49,0x05,0x01,0x04,0x00,0x04,0x86,0x03,0x01,0x01,0x00,0x00, 0x01,0x59,0x03,0x01,0x01,0x01,0x00,0x61,0x07,0x02,0x06,0x03,0x00,0x01,0x00,0x51,0x0d,0x0c,0x01,0x00,0x1e,0x1d,0x1b,0x1a,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x08,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06, 0x13,0x37,0x27,0x33,0x37,0x17,0x33,0x07,0x17,0x27,0x01,0x9b,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x09,0x1e,0x4d,0x5b,0x1d,0x1d,0x5b,0x4d,0x1e,0x49,0x02,0x2f,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfe,0xab,0x63,0x36,0x5d,0x5d,0x36,0x63,0x43, 0x00,0x01,0x00,0x41,0xff,0x92,0x02,0x17,0x03,0x3e,0x00,0x23,0x00,0x90,0x40,0x0c,0x0a,0x07,0x02,0x06,0x03,0x1c,0x19,0x02,0x07,0x02,0x02,0x4c,0x4b,0xb0,0x11,0x50,0x58,0x40,0x31,0x00,0x01,0x00,0x01,0x85,0x00,0x03,0x00,0x06,0x02,0x03,0x72,0x08,0x01,0x07,0x02,0x04,0x06,0x07,0x72,0x00,0x05,0x04,0x05,0x86,0x00,0x00,0x00,0x06, 0x02,0x00,0x06,0x69,0x00,0x02,0x07,0x04,0x02,0x59,0x00,0x02,0x02,0x04,0x62,0x00,0x04,0x02,0x04,0x52,0x1b,0x40,0x33,0x00,0x01,0x00,0x01,0x85,0x00,0x03,0x00,0x06,0x00,0x03,0x06,0x80,0x08,0x01,0x07,0x02,0x04,0x02,0x07,0x04,0x80,0x00,0x05,0x04,0x05,0x86,0x00,0x00,0x00,0x06,0x02,0x00,0x06,0x69,0x00,0x02,0x07,0x04,0x02,0x59, 0x00,0x02,0x02,0x04,0x62,0x00,0x04,0x02,0x04,0x52,0x59,0x40,0x10,0x00,0x00,0x00,0x23,0x00,0x23,0x23,0x13,0x23,0x13,0x23,0x13,0x23,0x09,0x06,0x1d,0x2b,0x13,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x11,0x33,0x11,0x16,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x26,0x27,0x11,0x23,0x11,0x26,0x26,0x23,0x22,0x06, 0x15,0x15,0x41,0x46,0x3c,0x17,0x28,0x11,0x32,0x14,0x25,0x15,0x16,0x19,0x55,0x46,0x3c,0x17,0x28,0x11,0x32,0x14,0x26,0x14,0x16,0x19,0x01,0x02,0x0f,0x3e,0x49,0x0b,0x08,0x01,0xb9,0xfe,0x2a,0x0d,0x13,0x18,0x15,0x1e,0x0f,0x3e,0x49,0x0a,0x08,0xfe,0x83,0x01,0x9a,0x0d,0x14,0x18,0x15,0x1e,0xff,0xff,0x00,0x46,0x00,0xfa,0x02,0x12, 0x02,0xaf,0x02,0x26,0x04,0x22,0x00,0x00,0x01,0x07,0x06,0x68,0x02,0x58,0xff,0xa6,0x00,0x09,0xb1,0x01,0x02,0xb8,0xff,0xa6,0xb0,0x35,0x2b,0x00,0xff,0xff,0x00,0x3c,0x00,0x32,0x02,0x1c,0x03,0x0c,0x00,0x27,0x06,0x72,0x02,0x58,0x00,0x00,0x02,0x06,0x04,0x26,0x00,0x00,0x00,0x03,0x00,0x50,0x00,0x00,0x02,0x08,0x02,0x30,0x00,0x11, 0x00,0x1d,0x00,0x29,0x00,0x49,0x40,0x46,0x08,0x03,0x02,0x01,0x04,0x01,0x86,0x00,0x00,0x00,0x02,0x05,0x00,0x02,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x0a,0x01,0x06,0x04,0x04,0x06,0x59,0x0a,0x01,0x06,0x06,0x04,0x61,0x09,0x01,0x04,0x06,0x04,0x51,0x1f,0x1e,0x13,0x12,0x00,0x00,0x25,0x23,0x1e,0x29,0x1f,0x29,0x19,0x17, 0x12,0x1d,0x13,0x1d,0x00,0x11,0x00,0x11,0x23,0x13,0x23,0x0b,0x06,0x19,0x2b,0x33,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x23,0x11,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x50,0x77,0x65,0x65,0x77,0x32,0x5c, 0x4e,0x4e,0x5c,0xaa,0x34,0x44,0x44,0x34,0x35,0x43,0x43,0x35,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x2d,0x01,0x54,0x65,0x77,0x77,0x65,0xfe,0xac,0x01,0x59,0x4e,0x5c,0x5c,0x4e,0xfe,0xa7,0xe6,0x44,0x34,0x35,0x43,0x43,0x35,0x34,0x44,0x28,0x2d,0x23,0x23,0x2d,0x2d,0x23,0x23,0x2d,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x58, 0x03,0x09,0x00,0x0b,0x00,0x17,0x00,0x1f,0x00,0x45,0x40,0x42,0x0a,0x01,0x07,0x04,0x07,0x86,0x03,0x01,0x01,0x09,0x02,0x08,0x03,0x00,0x05,0x01,0x00,0x69,0x00,0x05,0x04,0x04,0x05,0x57,0x00,0x05,0x05,0x04,0x5f,0x06,0x01,0x04,0x05,0x04,0x4f,0x18,0x18,0x0d,0x0c,0x01,0x00,0x18,0x1f,0x18,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x13, 0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0b,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x13,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x01,0x9b,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23, 0x25,0xff,0x02,0x58,0xff,0x02,0x89,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0xfd,0x77,0x02,0x08,0x50,0x50,0xfd,0xf8,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0x58,0x00,0x19,0x00,0x22,0x00,0x2b,0x00,0x52,0x40,0x4f,0x0c,0x01,0x07,0x00,0x07,0x86,0x00,0x03,0x04,0x01,0x02,0x01, 0x03,0x02,0x67,0x05,0x01,0x01,0x0e,0x0b,0x02,0x08,0x09,0x01,0x08,0x69,0x0a,0x0d,0x02,0x09,0x00,0x00,0x09,0x59,0x0a,0x0d,0x02,0x09,0x09,0x00,0x61,0x06,0x01,0x00,0x09,0x00,0x51,0x23,0x23,0x1a,0x1a,0x00,0x00,0x23,0x2b,0x23,0x2b,0x27,0x25,0x1a,0x22,0x1a,0x22,0x1e,0x1c,0x00,0x19,0x00,0x19,0x14,0x21,0x11,0x11,0x12,0x14,0x21, 0x0f,0x06,0x1d,0x2b,0x33,0x35,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35,0x23,0x35,0x21,0x15,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x27,0x33,0x35,0x23,0x22,0x06,0x15,0x14,0x16,0x37,0x23,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0xff,0x05,0x34,0x44,0x44,0x34,0x05,0xff,0x02,0x58,0xff,0x05,0x35,0x43,0x43,0x35, 0x05,0x5f,0x05,0x05,0x23,0x2d,0x2d,0x87,0x05,0x05,0x23,0x2d,0x2d,0x91,0x44,0x34,0x35,0x43,0x87,0x50,0x50,0x87,0x43,0x35,0x34,0x44,0x91,0xb9,0xa0,0x2d,0x23,0x23,0x2d,0xa0,0xa0,0x2d,0x23,0x23,0x2d,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0xfd,0x00,0x07,0x00,0x0b,0x00,0x2a,0x40,0x27,0x00,0x02,0x01,0x02,0x86,0x00, 0x04,0x00,0x05,0x00,0x04,0x05,0x67,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x00,0x01,0x4f,0x11,0x11,0x11,0x11,0x11,0x10,0x06,0x06,0x1c,0x2b,0x11,0x21,0x15,0x23,0x11,0x23,0x11,0x23,0x35,0x21,0x15,0x21,0x02,0x58,0xff,0x5a,0xff,0x02,0x58,0xfd,0xa8,0x02,0x58,0x50,0xfd,0xf8,0x02,0x08,0xf5,0x4b, 0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x58,0x02,0xe4,0x00,0x0e,0x00,0x2b,0x40,0x28,0x06,0x01,0x00,0x01,0x00,0x85,0x00,0x03,0x02,0x03,0x86,0x05,0x01,0x01,0x02,0x02,0x01,0x57,0x05,0x01,0x01,0x01,0x02,0x5f,0x04,0x01,0x02,0x01,0x02,0x4f,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x07,0x06,0x1d,0x2b,0x01,0x17,0x23,0x15,0x33,0x15,0x23, 0x11,0x23,0x11,0x23,0x35,0x33,0x35,0x23,0x01,0x2d,0xc7,0x9b,0xff,0xff,0x5a,0xff,0xff,0x9b,0x02,0xe4,0xa9,0xa6,0x50,0xfe,0xbb,0x01,0x45,0x50,0xa6,0x00,0x00,0x00,0x00,0x03,0x00,0x58,0xff,0xf6,0x02,0x00,0x02,0xe4,0x00,0x0d,0x00,0x1e,0x00,0x2f,0x00,0x58,0x40,0x55,0x1d,0x01,0x07,0x02,0x23,0x01,0x06,0x03,0x02,0x4c,0x00,0x01, 0x00,0x04,0x02,0x01,0x04,0x69,0x09,0x01,0x02,0x00,0x07,0x03,0x02,0x07,0x69,0x00,0x03,0x00,0x06,0x05,0x03,0x06,0x69,0x0a,0x01,0x05,0x00,0x00,0x05,0x59,0x0a,0x01,0x05,0x05,0x00,0x61,0x08,0x01,0x00,0x05,0x00,0x51,0x20,0x1f,0x0f,0x0e,0x01,0x00,0x2b,0x29,0x26,0x24,0x1f,0x2f,0x20,0x2f,0x1a,0x18,0x14,0x12,0x0e,0x1e,0x0f,0x1e, 0x08,0x06,0x00,0x0d,0x01,0x0d,0x0b,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x03,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x36,0x13,0x32,0x36,0x35,0x35,0x06,0x23,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x14,0x16,0x01,0x2c,0x62,0x72,0x72,0x62,0x62,0x72, 0x72,0x9a,0x1a,0x23,0x1b,0x1e,0x14,0x28,0x3f,0x3b,0x3a,0x40,0x0e,0x6c,0x3b,0x3f,0x0e,0x34,0x1a,0x23,0x1b,0x1e,0x14,0x28,0x40,0x0a,0x72,0x6a,0x01,0x36,0x6a,0x72,0x72,0x69,0xfe,0xc9,0x6a,0x72,0x01,0xd3,0x1d,0x25,0x1d,0x2d,0x7b,0x3e,0x43,0x43,0x3e,0x8c,0x43,0xfe,0x7e,0x43,0x3e,0x9a,0x43,0x1d,0x25,0x1d,0x2d,0x89,0x3e,0x43, 0x00,0x04,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x1f,0x00,0x2b,0x00,0x37,0x00,0x4d,0x40,0x4a,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x07,0x01,0x05,0x0b,0x06,0x0a,0x03,0x04,0x02,0x05,0x04,0x69,0x09,0x01,0x02,0x00,0x00,0x02,0x59,0x09,0x01,0x02,0x02,0x00,0x61,0x08,0x01,0x00,0x02,0x00,0x51,0x2d,0x2c,0x21, 0x20,0x11,0x10,0x01,0x00,0x33,0x31,0x2c,0x37,0x2d,0x37,0x27,0x25,0x20,0x2b,0x21,0x2b,0x19,0x17,0x10,0x1f,0x11,0x1f,0x09,0x07,0x00,0x0f,0x01,0x0f,0x0c,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16, 0x16,0x37,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x21,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0xda,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0xfe,0xc8,0x18,0x20,0x20,0x18, 0x18,0x20,0x20,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x32,0x44,0x76,0x4a,0x4a,0x76,0x44,0x44,0x76,0x4a,0x4a,0x76,0x44,0xd1,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x20,0x18,0x18,0x20,0x00,0x00,0x00,0x03,0xff,0xf6,0x00,0x00,0x02,0x62,0x02,0xe4,0x00,0x0e,0x00,0x14,0x00,0x1c, 0x00,0x3d,0x40,0x3a,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x67,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x69,0x07,0x01,0x04,0x00,0x00,0x04,0x59,0x07,0x01,0x04,0x04,0x00,0x5f,0x06,0x01,0x00,0x04,0x00,0x4f,0x16,0x15,0x01,0x00,0x1a,0x18,0x15,0x1c,0x16,0x1c,0x13,0x12,0x10,0x0f,0x08,0x06,0x00,0x0e,0x01,0x0d,0x08,0x06,0x16,0x2b,0x33, 0x22,0x35,0x34,0x37,0x13,0x36,0x33,0x32,0x17,0x13,0x16,0x15,0x14,0x23,0x25,0x33,0x13,0x35,0x23,0x15,0x13,0x32,0x35,0x34,0x23,0x22,0x15,0x14,0x3b,0x45,0x13,0xf2,0x10,0x21,0x21,0x10,0xf1,0x14,0x45,0xfe,0xf6,0x31,0x0a,0x44,0x21,0x2c,0x2c,0x2c,0x38,0x1a,0x2e,0x02,0x3e,0x26,0x26,0xfd,0xc2,0x2e,0x1a,0x38,0xc8,0x01,0x17,0x47, 0x47,0xfe,0x5e,0x2a,0x2a,0x2a,0x2a,0x00,0x00,0x01,0x00,0x14,0xff,0x92,0x02,0x44,0x03,0x48,0x00,0x05,0x00,0x1c,0x40,0x19,0x03,0x01,0x01,0x49,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x12,0x11,0x02,0x06,0x18,0x2b,0x01,0x03,0x21,0x01,0x13,0x21,0x01,0xd6,0xb4,0x01,0x22,0xfd,0xee,0xf5, 0xfe,0xed,0x03,0x48,0xfe,0x70,0xfd,0xda,0x01,0xa4,0x00,0x00,0x00,0x01,0x00,0x25,0x00,0x73,0x02,0x34,0x02,0x6e,0x00,0x05,0x00,0x06,0xb3,0x05,0x03,0x01,0x32,0x2b,0x13,0x37,0x17,0x13,0x17,0x01,0x25,0x3f,0x90,0xfb,0x45,0xfe,0xc9,0x01,0x48,0x42,0x8e,0x01,0x72,0x30,0xfe,0x35,0x00,0x00,0x00,0x01,0x00,0x42,0x00,0x64,0x02,0x16, 0x02,0x38,0x00,0x0b,0x00,0x06,0xb3,0x0a,0x04,0x01,0x32,0x2b,0x37,0x27,0x37,0x27,0x37,0x17,0x37,0x17,0x07,0x17,0x07,0x27,0x7b,0x38,0xb0,0xb1,0x3a,0xb1,0xb0,0x38,0xb0,0xb1,0x3a,0xb1,0x65,0x38,0xb0,0xb1,0x3a,0xb1,0xb0,0x38,0xb0,0xb1,0x3a,0xb1,0x00,0x01,0x00,0x1f,0x00,0x5b,0x02,0x39,0x02,0x75,0x00,0x0b,0x00,0x06,0xb3,0x0a, 0x04,0x01,0x32,0x2b,0x37,0x27,0x37,0x27,0x37,0x17,0x37,0x17,0x07,0x17,0x07,0x27,0x59,0x39,0xd3,0xd4,0x3a,0xd4,0xd2,0x39,0xd3,0xd4,0x3a,0xd4,0x5c,0x39,0xd2,0xd4,0x3a,0xd4,0xd3,0x39,0xd2,0xd4,0x3a,0xd4,0x00,0x01,0x00,0x27,0x00,0x3c,0x02,0x30,0x02,0x94,0x00,0x0b,0x00,0x06,0xb3,0x0a,0x04,0x01,0x32,0x2b,0x37,0x37,0x27,0x17, 0x37,0x17,0x37,0x07,0x17,0x27,0x07,0x27,0x27,0xab,0xaa,0xd7,0x2d,0x2c,0xd7,0xaa,0xab,0xd7,0x2d,0x2d,0xd2,0x96,0x96,0x49,0xdf,0xde,0x48,0x96,0x96,0x49,0xdf,0xdf,0x00,0x03,0x00,0x0f,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x07,0x00,0x10,0x00,0x1d,0x00,0x61,0x40,0x5e,0x0b,0x01,0x04,0x02,0x18,0x01,0x09,0x06,0x02,0x4c,0x00,0x02, 0x04,0x02,0x85,0x0b,0x03,0x02,0x01,0x00,0x05,0x00,0x01,0x05,0x80,0x07,0x01,0x05,0x06,0x00,0x05,0x06,0x7e,0x0c,0x0a,0x02,0x08,0x09,0x08,0x86,0x00,0x04,0x00,0x00,0x01,0x04,0x00,0x67,0x00,0x06,0x09,0x09,0x06,0x57,0x00,0x06,0x06,0x09,0x5f,0x00,0x09,0x06,0x09,0x4f,0x11,0x11,0x00,0x00,0x11,0x1d,0x11,0x1d,0x1c,0x1b,0x1a,0x19, 0x17,0x16,0x15,0x14,0x13,0x12,0x10,0x0f,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x0d,0x06,0x19,0x2b,0x01,0x27,0x23,0x07,0x23,0x13,0x33,0x13,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x33,0x03,0x11,0x33,0x15,0x33,0x37,0x33,0x07,0x17,0x23,0x27,0x23,0x15,0x01,0x3c,0x1c,0xb0,0x1b,0x46,0x94,0x4a,0x94,0x9e,0x08,0x12,0x02,0x02,0x12, 0x08,0x22,0x7d,0x11,0x42,0x4f,0x60,0x4a,0x71,0x7b,0x4e,0x66,0x4f,0x01,0x8b,0x41,0x41,0x01,0x4f,0xfe,0xb1,0xce,0x13,0x2a,0x0d,0x0d,0x2a,0x13,0x52,0xfd,0xf9,0x01,0x4f,0x86,0x86,0xa1,0xae,0x8f,0x8f,0x00,0x00,0x04,0x00,0x2d,0xff,0xfc,0x02,0x2f,0x02,0xda,0x00,0x0d,0x00,0x16,0x00,0x1f,0x00,0x4b,0x00,0x6c,0x40,0x69,0x07,0x01, 0x05,0x02,0x01,0x4c,0x00,0x0a,0x0b,0x07,0x0b,0x0a,0x07,0x80,0x00,0x07,0x08,0x0b,0x07,0x08,0x7e,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x04,0x0c,0x01,0x01,0x09,0x04,0x01,0x67,0x00,0x09,0x00,0x0b,0x0a,0x09,0x0b,0x69,0x00,0x08,0x06,0x06,0x08,0x59,0x00,0x08,0x08,0x06,0x61,0x0d, 0x01,0x06,0x08,0x06,0x51,0x21,0x20,0x00,0x00,0x3f,0x3c,0x3a,0x39,0x37,0x34,0x29,0x26,0x24,0x23,0x20,0x4b,0x21,0x4a,0x1f,0x1d,0x19,0x17,0x16,0x14,0x10,0x0e,0x00,0x0d,0x00,0x0c,0x21,0x0e,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x15, 0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x2d,0xc2,0x33,0x3f,0x37,0x21,0x27,0x40,0x34,0x8f,0x81,0x14, 0x1a,0x19,0x14,0x82,0x8c,0x17,0x1d,0x1d,0x17,0x8c,0x01,0x15,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x01,0x8b,0x01,0x4f,0x2e,0x26,0x39,0x14,0x08,0x2b,0x1e,0x29,0x34,0xbf,0x17,0x13,0x13, 0x19,0xdb,0x19,0x13,0x13,0x17,0xfd,0xe1,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0x00,0x00,0x00,0x02,0x00,0x2d,0xff,0x4c,0x02,0x30,0x02,0xe4,0x00,0x27,0x00,0x35,0x00,0x4b,0x40,0x48,0x19,0x01,0x07,0x03,0x01,0x4c, 0x00,0x03,0x00,0x07,0x06,0x03,0x07,0x69,0x09,0x01,0x06,0x00,0x02,0x05,0x06,0x02,0x69,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x05,0x05,0x00,0x5f,0x08,0x01,0x00,0x00,0x3d,0x00,0x4e,0x29,0x28,0x01,0x00,0x30,0x2e,0x28,0x35,0x29,0x35,0x26,0x24,0x1f,0x1d,0x17,0x15,0x10,0x0e,0x09,0x07,0x00,0x27,0x01,0x27,0x0a, 0x09,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x33,0x15,0x03,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0x45,0x55,0x7e,0x45,0x90,0x7e, 0x72,0x83,0x56,0x4a,0x49,0x57,0x46,0x40,0x29,0x36,0x09,0x02,0x55,0x50,0x5a,0x64,0x6b,0x5d,0x6e,0x23,0x26,0x2a,0x2a,0x26,0x26,0x2a,0x2a,0xb4,0x47,0x83,0x58,0x01,0x54,0x87,0x9b,0x83,0x72,0xfe,0xf1,0x4e,0x5b,0x58,0x47,0x74,0x4a,0x51,0x20,0x1c,0x46,0x55,0x5a,0x74,0x68,0xfe,0xac,0x64,0x73,0x4b,0x01,0x2e,0x31,0x2b,0x75,0x2c, 0x2f,0x30,0x2c,0x74,0x2b,0x31,0x00,0x00,0x00,0x02,0x00,0x19,0xff,0xf7,0x02,0x67,0x02,0xe4,0x00,0x24,0x00,0x30,0x00,0x9b,0x40,0x09,0x28,0x21,0x1e,0x1b,0x04,0x07,0x08,0x01,0x4c,0x4b,0xb0,0x1a,0x50,0x58,0x40,0x34,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x01,0x00,0x08,0x07,0x01,0x08,0x69,0x00,0x04,0x04,0x02,0x61,0x00, 0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x00,0x61,0x06,0x09,0x02,0x00,0x00,0x3f,0x4d,0x0a,0x01,0x07,0x07,0x00,0x61,0x06,0x09,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x31,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x01,0x00,0x08,0x07,0x01,0x08,0x69,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x06,0x5f, 0x00,0x06,0x06,0x39,0x4d,0x0a,0x01,0x07,0x07,0x00,0x61,0x09,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x1d,0x26,0x25,0x01,0x00,0x2b,0x29,0x25,0x30,0x26,0x30,0x20,0x1f,0x1d,0x1c,0x16,0x14,0x12,0x11,0x0e,0x0c,0x07,0x06,0x00,0x24,0x01,0x24,0x0b,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36, 0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x37,0x33,0x07,0x17,0x23,0x27,0x07,0x06,0x06,0x27,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xd7,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0xc3,0x5b,0x64,0x8f,0x91,0x63,0x61,0x2b,0x22,0x53, 0x26,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b,0x09,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55,0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfc,0x72,0xb0,0xbd,0x80,0x36,0x2a,0x29,0x51,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b,0x00,0x00,0x02,0x00,0x41,0xff,0x4c,0x01,0xf9,0x02,0xda,0x00,0x0a,0x00,0x0e,0x00,0x2a, 0x40,0x27,0x00,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x01,0x38,0x4d,0x06,0x04,0x05,0x03,0x02,0x02,0x3d,0x02,0x4e,0x0b,0x0b,0x00,0x00,0x0b,0x0e,0x0b,0x0e,0x0d,0x0c,0x00,0x0a,0x00,0x0a,0x25,0x11,0x07,0x09,0x18,0x2b,0x17,0x11,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x33,0x11,0x33,0x11,0x33,0x11,0xff,0x55,0x69,0x69,0x55,0x50,0x5a, 0x50,0xb4,0x01,0xea,0x5e,0x4c,0x50,0x4d,0x5d,0xfc,0x72,0x03,0x8e,0xfc,0x72,0x00,0x00,0x02,0x00,0x4d,0xff,0x66,0x02,0x0b,0x02,0xe4,0x00,0x3b,0x00,0x49,0x00,0x47,0x40,0x44,0x16,0x01,0x06,0x04,0x01,0x4c,0x00,0x04,0x05,0x06,0x05,0x04,0x06,0x80,0x00,0x06,0x01,0x05,0x06,0x01,0x7e,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x02, 0x07,0x01,0x00,0x02,0x00,0x65,0x00,0x05,0x05,0x03,0x61,0x00,0x03,0x03,0x3e,0x05,0x4e,0x01,0x00,0x33,0x32,0x27,0x24,0x22,0x21,0x1f,0x1c,0x09,0x06,0x04,0x03,0x00,0x3b,0x01,0x3a,0x08,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x2e,0x02,0x35,0x34,0x36,0x37,0x35,0x26,0x26, 0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x1e,0x02,0x15,0x14,0x06,0x23,0x13,0x16,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x06,0x15,0x14,0x16,0x17,0x01,0x13,0x5b,0x6b,0x5f,0x38,0x2f,0x32,0x32,0x39,0x33,0x32,0x5c,0x2e,0x44,0x26,0x3b, 0x34,0x34,0x38,0x66,0x57,0x32,0x4f,0x66,0x07,0x5f,0x04,0x32,0x27,0x32,0x2e,0x35,0x24,0x20,0x78,0x47,0x51,0x44,0x2f,0x15,0x37,0x2a,0x6a,0x5c,0x05,0x2c,0x38,0x2c,0x23,0x4a,0x2c,0x38,0x2b,0x22,0x9a,0x53,0x47,0x22,0x28,0x2e,0x28,0x24,0x33,0x08,0x0f,0x08,0x34,0x4a,0x28,0x3a,0x48,0x07,0x02,0x0c,0x4c,0x38,0x4a,0x57,0x4e,0x43, 0x1e,0x23,0x2c,0x26,0x21,0x2e,0x06,0x17,0x0d,0x62,0x3d,0x3a,0x45,0x03,0x02,0x02,0x21,0x41,0x33,0x4e,0x5b,0x01,0x55,0x07,0x42,0x35,0x23,0x36,0x06,0x0d,0x08,0x40,0x33,0x26,0x38,0x06,0x00,0x03,0x00,0x2d,0x00,0x6e,0x02,0x2b,0x02,0xe4,0x00,0x11,0x00,0x23,0x00,0x3f,0x00,0x69,0xb1,0x06,0x64,0x44,0x40,0x5e,0x00,0x06,0x07,0x09, 0x07,0x06,0x09,0x80,0x00,0x09,0x08,0x07,0x09,0x08,0x7e,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x00,0x05,0x00,0x07,0x06,0x05,0x07,0x69,0x00,0x08,0x0c,0x01,0x04,0x02,0x08,0x04,0x69,0x0b,0x01,0x02,0x00,0x00,0x02,0x59,0x0b,0x01,0x02,0x02,0x00,0x62,0x0a,0x01,0x00,0x02,0x00,0x52,0x25,0x24,0x13,0x12,0x01,0x00,0x3d,0x3c,0x3a, 0x38,0x33,0x31,0x2f,0x2e,0x2c,0x2a,0x24,0x3f,0x25,0x3f,0x1c,0x1a,0x12,0x23,0x13,0x23,0x0a,0x08,0x00,0x11,0x01,0x11,0x0d,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x25,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x15,0x14,0x06,0x06,0x27,0x32,0x36,0x36,0x35,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x15, 0x14,0x16,0x16,0x37,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x01,0x2c,0x4c,0x73,0x40,0x40,0x73,0x4c,0x4d,0x72,0x40,0x40,0x72,0x4d,0x3c,0x5a,0x32,0x32,0x5a,0x3c,0x3c,0x5a,0x32,0x32,0x5a,0x41,0x38,0x45,0x45,0x38,0x38,0x44,0x41, 0x21,0x1a,0x1b,0x21,0x21,0x1b,0x1a,0x21,0x41,0x44,0x6e,0x3c,0x6c,0x48,0x96,0x48,0x6c,0x3c,0x3c,0x6c,0x48,0x96,0x48,0x6c,0x3c,0x32,0x2f,0x56,0x39,0x96,0x39,0x55,0x30,0x30,0x55,0x39,0x96,0x39,0x56,0x2f,0x55,0x3f,0x34,0x82,0x34,0x3f,0x3f,0x34,0x1b,0x21,0x21,0x1b,0x82,0x1b,0x21,0x21,0x1b,0x34,0x3f,0x00,0x00,0x04,0x00,0x2d, 0x00,0x6e,0x02,0x2b,0x02,0xe4,0x00,0x11,0x00,0x23,0x00,0x30,0x00,0x39,0x00,0x63,0xb1,0x06,0x64,0x44,0x40,0x58,0x2b,0x01,0x06,0x08,0x01,0x4c,0x0b,0x07,0x02,0x05,0x06,0x02,0x06,0x05,0x02,0x80,0x00,0x01,0x00,0x03,0x04,0x01,0x03,0x69,0x00,0x04,0x00,0x09,0x08,0x04,0x09,0x69,0x00,0x08,0x00,0x06,0x05,0x08,0x06,0x67,0x00,0x02, 0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x0a,0x01,0x00,0x02,0x00,0x51,0x24,0x24,0x01,0x00,0x39,0x37,0x33,0x31,0x24,0x30,0x24,0x30,0x2f,0x2e,0x2d,0x2c,0x27,0x25,0x20,0x1e,0x17,0x15,0x0a,0x08,0x00,0x11,0x01,0x11,0x0c,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x25,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16, 0x15,0x15,0x14,0x06,0x06,0x25,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x17,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x17,0x23,0x27,0x23,0x15,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x2c,0x4c,0x73,0x40,0x40,0x73,0x4c,0x4d,0x72,0x40,0x40,0x72,0xfe,0xeb,0x32,0x5a,0x3c,0x3c, 0x5a,0x32,0x32,0x5a,0x3c,0x3c,0x5a,0x32,0x5a,0x72,0x36,0x3f,0x3c,0x42,0x40,0x3b,0x36,0x36,0x1a,0x1e,0x1e,0x1a,0x36,0x6e,0x3c,0x6c,0x48,0x96,0x48,0x6c,0x3c,0x3c,0x6c,0x48,0x96,0x48,0x6c,0x3c,0xf0,0x39,0x56,0x2f,0x2f,0x56,0x39,0x96,0x39,0x55,0x30,0x30,0x55,0x39,0xfa,0x01,0x5e,0x39,0x30,0x45,0x1a,0x96,0x8c,0x8c,0xbe,0x1d, 0x1a,0x1a,0x1d,0x00,0x00,0x02,0x00,0x0f,0x01,0x72,0x02,0x35,0x02,0xda,0x00,0x07,0x00,0x26,0x00,0x4d,0x40,0x4a,0x22,0x19,0x02,0x00,0x01,0x0e,0x01,0x07,0x00,0x02,0x4c,0x00,0x07,0x00,0x03,0x00,0x07,0x03,0x80,0x0a,0x08,0x06,0x09,0x04,0x03,0x03,0x84,0x05,0x04,0x02,0x01,0x00,0x00,0x01,0x57,0x05,0x04,0x02,0x01,0x01,0x00,0x5f, 0x02,0x01,0x00,0x01,0x00,0x4f,0x08,0x08,0x00,0x00,0x08,0x26,0x08,0x26,0x1e,0x1d,0x15,0x14,0x13,0x12,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x0b,0x06,0x19,0x2b,0x13,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x33,0x11,0x33,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x11,0x23,0x35,0x34,0x36,0x37,0x06,0x06,0x07,0x07,0x23, 0x27,0x26,0x26,0x27,0x16,0x16,0x15,0x15,0x73,0x64,0x01,0x04,0x64,0x87,0x50,0x22,0x05,0x09,0x02,0x02,0x07,0x05,0x21,0x4e,0x37,0x05,0x02,0x06,0x0e,0x03,0x1e,0x33,0x21,0x03,0x0e,0x06,0x02,0x06,0x01,0x72,0x01,0x36,0x32,0x32,0xfe,0xca,0x01,0x68,0x66,0x0e,0x2b,0x0e,0x0e,0x2b,0x0e,0x66,0xfe,0x98,0xdd,0x1c,0x3e,0x13,0x14,0x33, 0x09,0x67,0x68,0x09,0x32,0x14,0x13,0x3e,0x1c,0xdd,0x00,0x00,0x00,0x02,0x00,0x96,0x01,0xc2,0x01,0xc2,0x02,0xe4,0x00,0x0b,0x00,0x17,0x00,0x39,0xb1,0x06,0x64,0x44,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01, 0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x2c,0x43,0x53,0x53,0x43,0x43,0x53,0x53,0x43,0x26,0x2f,0x2f,0x26,0x25,0x30,0x30,0x01,0xc2, 0x51,0x40,0x41,0x50,0x50,0x41,0x40,0x51,0x38,0x31,0x28,0x28,0x32,0x32,0x28,0x28,0x31,0x00,0x00,0x00,0xff,0xff,0x00,0xd2,0x01,0xa3,0x01,0x75,0x02,0xd5,0x03,0x07,0x03,0x2a,0x00,0x00,0x02,0x43,0x00,0x09,0xb1,0x00,0x01,0xb8,0x02,0x43,0xb0,0x35,0x2b,0x00,0x00,0x00,0xff,0xff,0x00,0x69,0x01,0xa4,0x01,0xef,0x02,0xd6,0x00,0x27, 0x03,0x2a,0xff,0x97,0x02,0x44,0x01,0x07,0x03,0x2a,0x00,0x7a,0x02,0x44,0x00,0x12,0xb1,0x00,0x01,0xb8,0x02,0x44,0xb0,0x35,0x2b,0xb1,0x01,0x01,0xb8,0x02,0x44,0xb0,0x35,0x2b,0x00,0x00,0x00,0x01,0x00,0xff,0xff,0x92,0x01,0x59,0x03,0x3e,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00, 0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x17,0x11,0x33,0x11,0xff,0x5a,0x6e,0x03,0xac,0xfc,0x54,0x00,0x02,0x00,0xff,0xff,0x92,0x01,0x59,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x2c,0x00,0x00,0x04,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f, 0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x33,0x11,0xff,0x5a,0x5a,0x5a,0x01,0xc2,0x01,0x7c,0xfe,0x84,0xfd,0xd0,0x01,0x7c,0xfe,0x84,0x00,0x00,0x01,0x00,0x50,0xff,0x92,0x02,0x08,0x03,0x3e,0x00,0x0b,0x00,0x2f,0x40,0x2c,0x00,0x02,0x01,0x02, 0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x04,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x17,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0xff,0xaf,0xaf,0x5a,0xaf,0xaf,0x6e,0x02,0x76,0x50,0xe6, 0xe6,0x50,0xfd,0x8a,0x00,0x02,0x00,0x46,0x00,0x00,0x01,0xf4,0x02,0xe4,0x00,0x1e,0x00,0x28,0x00,0x38,0x40,0x35,0x20,0x1b,0x1a,0x13,0x07,0x06,0x05,0x04,0x08,0x02,0x03,0x01,0x4c,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x27,0x25, 0x18,0x16,0x0c,0x0a,0x00,0x1e,0x01,0x1e,0x05,0x06,0x16,0x2b,0x21,0x22,0x26,0x35,0x35,0x07,0x27,0x37,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x07,0x07,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x17,0x0e,0x02,0x03,0x15,0x37,0x36,0x35,0x35,0x34,0x23,0x22,0x06,0x01,0x51,0x4d,0x5a,0x46,0x1e,0x64,0x58,0x48,0x49,0x57,0x4f, 0x46,0x51,0x29,0x24,0x22,0x32,0x0b,0x44,0x09,0x2d,0x42,0x78,0x35,0x57,0x46,0x21,0x25,0x57,0x49,0x4a,0x1b,0x51,0x25,0x01,0x04,0x46,0x55,0x54,0x47,0x55,0x43,0x6c,0x1a,0x1f,0x6c,0x25,0x29,0x2a,0x13,0x2a,0x15,0x2f,0x21,0x02,0x49,0xe3,0x13,0x21,0x5a,0x55,0x49,0x26,0x00,0x01,0x00,0x50,0xff,0x92,0x02,0x08,0x03,0x3e,0x00,0x13, 0x00,0x3d,0x40,0x3a,0x00,0x04,0x03,0x04,0x85,0x0a,0x01,0x09,0x00,0x09,0x86,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x67,0x07,0x01,0x01,0x00,0x00,0x01,0x57,0x07,0x01,0x01,0x01,0x00,0x5f,0x08,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x09,0x1f,0x2b,0x17, 0x35,0x23,0x35,0x33,0x11,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x11,0x33,0x15,0x23,0x15,0xff,0xaf,0xaf,0xaf,0xaf,0x5a,0xaf,0xaf,0xaf,0xaf,0x6e,0xfa,0x50,0x01,0x22,0x50,0xf0,0xf0,0x50,0xfe,0xde,0x50,0xfa,0x00,0x00,0x00,0x03,0x00,0x1e,0x00,0x00,0x02,0x58,0x02,0xe4,0x00,0x0d,0x00,0x27,0x00,0x35,0x00,0x79,0x40,0x0a, 0x22,0x01,0x06,0x07,0x15,0x01,0x04,0x00,0x02,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1e,0x0a,0x01,0x06,0x08,0x01,0x00,0x04,0x06,0x00,0x69,0x00,0x07,0x07,0x01,0x5f,0x03,0x02,0x02,0x01,0x01,0x38,0x4d,0x09,0x05,0x02,0x04,0x04,0x39,0x04,0x4e,0x1b,0x40,0x22,0x0a,0x01,0x06,0x08,0x01,0x00,0x04,0x06,0x00,0x69,0x03,0x01,0x02,0x02, 0x38,0x4d,0x00,0x07,0x07,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x09,0x05,0x02,0x04,0x04,0x39,0x04,0x4e,0x59,0x40,0x1f,0x29,0x28,0x0e,0x0e,0x01,0x00,0x30,0x2e,0x28,0x35,0x29,0x35,0x0e,0x27,0x0e,0x27,0x1d,0x1c,0x1b,0x1a,0x10,0x0f,0x08,0x06,0x00,0x0d,0x01,0x0d,0x0b,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32, 0x16,0x15,0x15,0x14,0x06,0x01,0x11,0x33,0x13,0x1e,0x02,0x17,0x2e,0x02,0x35,0x11,0x33,0x11,0x23,0x03,0x2e,0x02,0x27,0x1e,0x02,0x15,0x11,0x01,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x01,0xf9,0x28,0x37,0x37,0x28,0x29,0x36,0x36,0xfd,0xfc,0x5f,0x75,0x06,0x10,0x11,0x06,0x02,0x06,0x04,0x46,0x5f,0x72, 0x05,0x11,0x11,0x07,0x02,0x05,0x03,0x01,0x95,0x0e,0x15,0x15,0x0e,0x0d,0x16,0x16,0x01,0x2c,0x3a,0x2f,0xe6,0x2f,0x3a,0x3a,0x2f,0xe6,0x2f,0x3a,0xfe,0xd4,0x02,0xda,0xfe,0x3b,0x15,0x44,0x4a,0x1d,0x1d,0x4c,0x4b,0x19,0x01,0xb8,0xfd,0x26,0x01,0xc6,0x17,0x44,0x49,0x1c,0x1c,0x4b,0x4b,0x1c,0xfe,0x48,0x01,0x63,0x12,0x16,0xfa,0x12, 0x16,0x16,0x12,0xfa,0x16,0x12,0x00,0x00,0x00,0x02,0x00,0x3c,0xff,0xf6,0x02,0x1c,0x02,0xe4,0x00,0x1a,0x00,0x23,0x00,0x4c,0x40,0x49,0x1e,0x1b,0x02,0x05,0x06,0x10,0x01,0x03,0x04,0x02,0x4c,0x00,0x04,0x02,0x03,0x02,0x04,0x03,0x80,0x00,0x01,0x00,0x06,0x05,0x01,0x06,0x69,0x00,0x05,0x00,0x02,0x04,0x05,0x02,0x67,0x00,0x03,0x00, 0x00,0x03,0x59,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x03,0x00,0x51,0x01,0x00,0x22,0x20,0x1d,0x1c,0x17,0x16,0x14,0x12,0x0f,0x0e,0x0a,0x08,0x00,0x1a,0x01,0x1a,0x08,0x06,0x16,0x2b,0x05,0x22,0x26,0x26,0x35,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x15,0x21,0x11,0x16,0x16,0x33,0x32,0x36,0x37,0x33,0x0e,0x02,0x03,0x15, 0x21,0x35,0x26,0x26,0x23,0x22,0x06,0x01,0x2c,0x47,0x6d,0x3c,0x3c,0x6d,0x47,0x49,0x6b,0x3c,0xfe,0x84,0x0c,0x49,0x37,0x3b,0x62,0x14,0x32,0x10,0x44,0x5b,0xc0,0x01,0x18,0x0c,0x48,0x38,0x37,0x49,0x0a,0x41,0x76,0x4d,0xe6,0x4e,0x75,0x41,0x41,0x74,0x4f,0x79,0xfe,0xfd,0x15,0x2c,0x3d,0x31,0x2e,0x46,0x27,0x02,0x80,0xdd,0xdd,0x15, 0x2c,0x2c,0x00,0x00,0x00,0x04,0x00,0x2d,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0d,0x00,0x16,0x00,0x1f,0x00,0x25,0x00,0x57,0x40,0x54,0x07,0x01,0x05,0x02,0x01,0x4c,0x00,0x06,0x01,0x07,0x01,0x06,0x07,0x80,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x00,0x05,0x04,0x02,0x05,0x67,0x00,0x04,0x09,0x01,0x01,0x06,0x04,0x01, 0x67,0x00,0x07,0x08,0x08,0x07,0x57,0x00,0x07,0x07,0x08,0x5f,0x0a,0x01,0x08,0x07,0x08,0x4f,0x20,0x20,0x00,0x00,0x20,0x25,0x20,0x25,0x24,0x23,0x22,0x21,0x1f,0x1d,0x19,0x17,0x16,0x14,0x10,0x0e,0x00,0x0d,0x00,0x0c,0x21,0x0b,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32, 0x36,0x35,0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x13,0x11,0x33,0x11,0x33,0x15,0x2d,0xc2,0x33,0x3f,0x37,0x21,0x27,0x40,0x34,0x8f,0x81,0x14,0x1a,0x19,0x14,0x82,0x8c,0x17,0x1d,0x1d,0x17,0x8c,0xab,0x42,0xde,0x01,0x8b,0x01,0x4f,0x2e,0x26,0x39,0x14,0x08,0x2b,0x1e,0x29,0x34,0xbf,0x17,0x13,0x13,0x19, 0xdb,0x19,0x13,0x13,0x17,0xfd,0xe5,0x01,0x4f,0xfe,0xed,0x3c,0x00,0x01,0x00,0x28,0xff,0x4c,0x02,0x30,0x00,0x00,0x00,0x07,0x00,0x49,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x18,0x02,0x01,0x00,0x01,0x01,0x00,0x70,0x00,0x01,0x03,0x03,0x01,0x57,0x00,0x01,0x01,0x03,0x60,0x04,0x01,0x03,0x01,0x03,0x50,0x1b,0x40,0x17,0x02,0x01,0x00,0x01, 0x00,0x85,0x00,0x01,0x03,0x03,0x01,0x57,0x00,0x01,0x01,0x03,0x60,0x04,0x01,0x03,0x01,0x03,0x50,0x59,0x40,0x0c,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x06,0x19,0x2b,0x17,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x28,0x5a,0x01,0x54,0x5a,0xb4,0xb4,0x64,0x64,0xb4,0x00,0x00,0x00,0x00,0x02,0x00,0x14,0x00,0x56,0x02,0x4e, 0x02,0x89,0x00,0x06,0x00,0x20,0x00,0x47,0x40,0x44,0x05,0x02,0x01,0x03,0x02,0x04,0x06,0x01,0x03,0x02,0x02,0x4c,0x00,0x00,0x05,0x00,0x85,0x00,0x02,0x04,0x03,0x04,0x02,0x03,0x80,0x00,0x05,0x00,0x04,0x02,0x05,0x04,0x69,0x00,0x03,0x01,0x01,0x03,0x59,0x00,0x03,0x03,0x01,0x61,0x06,0x01,0x01,0x03,0x01,0x51,0x08,0x07,0x1a,0x19, 0x18,0x17,0x11,0x0f,0x0c,0x0b,0x07,0x20,0x08,0x20,0x13,0x07,0x06,0x17,0x2b,0x01,0x27,0x07,0x35,0x33,0x07,0x17,0x07,0x22,0x26,0x26,0x35,0x33,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x35,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x01,0x55,0xe1,0x60,0xf9,0x65,0xe2,0x4f,0x4e,0x7d,0x48,0x4e,0x33,0x5a,0x38,0x39, 0x59,0x33,0x33,0x59,0x39,0x4f,0x7c,0x48,0x48,0x7c,0x01,0x18,0xd8,0x60,0xf9,0x65,0xd8,0xf6,0x47,0x7c,0x4d,0x39,0x5a,0x35,0x35,0x5a,0x39,0x39,0x5b,0x34,0x47,0x47,0x7a,0x4e,0x4d,0x7c,0x47,0x00,0x00,0x00,0x00,0x02,0x00,0x20,0x00,0x00,0x02,0x2b,0x02,0xdf,0x00,0x1b,0x00,0x2d,0x00,0x60,0x40,0x5d,0x28,0x1f,0x02,0x08,0x06,0x01, 0x4c,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x07,0x01,0x06,0x00,0x08,0x00,0x06,0x08,0x80,0x0b,0x09,0x02,0x08,0x08,0x84,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x61,0x0a,0x01,0x00,0x04,0x00,0x51,0x1c,0x1c,0x01,0x00,0x1c,0x2d,0x1c,0x2d, 0x27,0x26,0x25,0x24,0x1e,0x1d,0x19,0x18,0x16,0x14,0x10,0x0e,0x0c,0x0b,0x09,0x07,0x00,0x1b,0x01,0x1b,0x0c,0x06,0x16,0x2b,0x13,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x03,0x11,0x33,0x13,0x2e,0x02,0x35,0x35,0x33,0x11,0x23,0x03, 0x1e,0x02,0x15,0x15,0xcf,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x39,0x5a,0x10,0x44,0x0b,0x35,0x1f,0x2e,0x3d,0x3d,0x2e,0x1f,0x35,0x0b,0x44,0x10,0x5a,0x13,0x50,0xb2,0x05,0x06,0x02,0x41,0x50,0xb2,0x06,0x05,0x02,0x01,0x86,0x2d,0x4e,0x31,0x32,0x4e,0x2d,0x3e,0x32,0x18,0x1e,0x41,0x32,0x31,0x41,0x1e,0x18,0x31,0x3f,0xfe,0x7a,0x01,0x4f, 0xfe,0xf7,0x1e,0x26,0x30,0x2c,0x69,0xfe,0xb1,0x01,0x09,0x1c,0x26,0x31,0x2d,0x69,0x00,0x03,0x00,0x20,0x00,0x00,0x02,0x3f,0x02,0xdf,0x00,0x1b,0x00,0x29,0x00,0x32,0x00,0x6b,0x40,0x68,0x24,0x01,0x08,0x0a,0x01,0x4c,0x00,0x02,0x03,0x05,0x03,0x02,0x05,0x80,0x00,0x05,0x04,0x03,0x05,0x04,0x7e,0x0d,0x09,0x02,0x07,0x08,0x07,0x86, 0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x00,0x04,0x0c,0x01,0x00,0x06,0x04,0x00,0x69,0x00,0x06,0x00,0x0b,0x0a,0x06,0x0b,0x68,0x00,0x0a,0x08,0x08,0x0a,0x57,0x00,0x0a,0x0a,0x08,0x5f,0x00,0x08,0x0a,0x08,0x4f,0x1c,0x1c,0x01,0x00,0x32,0x30,0x2c,0x2a,0x1c,0x29,0x1c,0x29,0x28,0x27,0x26,0x25,0x1f,0x1d,0x19,0x18,0x16,0x14,0x10, 0x0e,0x0c,0x0b,0x09,0x07,0x00,0x1b,0x01,0x1b,0x0e,0x06,0x16,0x2b,0x13,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x03,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x17,0x23,0x27,0x23,0x15,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23, 0xcf,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x39,0x5a,0x10,0x44,0x0b,0x35,0x1f,0x2e,0x3d,0x3d,0x2e,0x1f,0x35,0x0b,0x44,0x10,0x5a,0x13,0xc6,0x38,0x44,0x34,0x2b,0x67,0x50,0x64,0x54,0x85,0x19,0x1f,0x1e,0x19,0x86,0x01,0x86,0x2d,0x4e,0x31,0x32,0x4e,0x2d,0x3e,0x32,0x18,0x1e,0x41,0x32,0x31,0x41,0x1e,0x18,0x31,0x3f,0xfe,0x7a,0x01,0x4f, 0x3d,0x2f,0x28,0x32,0x06,0x83,0x81,0x81,0xb3,0x1b,0x15,0x16,0x1c,0x00,0x00,0x00,0x00,0x01,0x00,0x23,0x01,0xd6,0x02,0x35,0x02,0xe4,0x00,0x05,0x00,0x18,0x40,0x15,0x04,0x01,0x02,0x00,0x4a,0x02,0x01,0x02,0x00,0x00,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x13,0x01,0x01,0x23,0x27,0x07,0x23,0x01,0x09,0x01, 0x09,0x6e,0x9a,0x9e,0x01,0xd6,0x01,0x0e,0xfe,0xf2,0xa2,0xa2,0x00,0x01,0x00,0xc3,0xff,0x92,0x01,0xef,0x00,0xbe,0x00,0x05,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x01,0x02,0x4f,0x11,0x11,0x10,0x03,0x06,0x19,0x2b,0x37,0x33,0x15,0x33,0x15,0x21,0xc3,0x5a, 0xd2,0xfe,0xd4,0xbe,0xdc,0x50,0x00,0x00,0x00,0x01,0x00,0x69,0xff,0x92,0x01,0x95,0x00,0xbe,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x85,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x25,0x11,0x21,0x35,0x33,0x35, 0x01,0x95,0xfe,0xd4,0xd2,0xbe,0xfe,0xd4,0x50,0xdc,0x00,0x00,0x00,0x01,0x00,0x69,0x02,0x12,0x01,0x95,0x03,0x3e,0x00,0x05,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x00,0x86,0x00,0x02,0x01,0x01,0x02,0x57,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x02,0x01,0x4f,0x11,0x11,0x10,0x03,0x06,0x19,0x2b,0x01,0x23,0x35,0x23,0x35,0x21,0x01,0x95, 0x5a,0xd2,0x01,0x2c,0x02,0x12,0xdc,0x50,0x00,0x01,0x00,0xc3,0x02,0x12,0x01,0xef,0x03,0x3e,0x00,0x05,0x00,0x24,0x40,0x21,0x03,0x01,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x00,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x11,0x04,0x06,0x18,0x2b,0x13,0x11,0x21,0x15,0x23,0x15, 0xc3,0x01,0x2c,0xd2,0x02,0x12,0x01,0x2c,0x50,0xdc,0x00,0x00,0x00,0x03,0x00,0x2d,0x00,0x00,0x02,0x26,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x1f,0x00,0x54,0x40,0x51,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x0a,0x01,0x01,0x05,0x02,0x01,0x67,0x00,0x05,0x00,0x06,0x07,0x05,0x06,0x67,0x00,0x07,0x00,0x08,0x09,0x07,0x08, 0x67,0x0b,0x01,0x09,0x04,0x04,0x09,0x57,0x0b,0x01,0x09,0x09,0x04,0x5f,0x00,0x04,0x09,0x04,0x4f,0x14,0x14,0x00,0x00,0x14,0x1f,0x14,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x09,0x21,0x0c,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32, 0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d,0x3e,0x3e,0x2d,0x54,0x01,0xb7,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31,0x31,0x3d,0xfd,0x9a,0x3a,0x01,0x4f,0x3a,0x56, 0x2f,0x56,0x00,0x00,0x00,0x03,0x00,0x2d,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x19,0x00,0x45,0x40,0x42,0x00,0x04,0x01,0x05,0x01,0x04,0x05,0x80,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x07,0x01,0x01,0x04,0x02,0x01,0x67,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05,0x06,0x5f,0x08,0x01,0x06,0x05, 0x06,0x4f,0x14,0x14,0x00,0x00,0x14,0x19,0x14,0x19,0x18,0x17,0x16,0x15,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x09,0x21,0x09,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x13,0x11,0x33,0x11,0x33,0x15,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d, 0x3e,0x3e,0x2d,0x54,0xab,0x42,0xde,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31,0x31,0x3d,0xfd,0x60,0x01,0x4f,0xfe,0xed,0x3c,0x00,0x00,0x00,0x00,0x03,0x00,0x2d,0x00,0x00,0x02,0x0e,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x1f,0x00,0x58,0x40,0x55,0x1a,0x17,0x02,0x06,0x07,0x01,0x4c,0x00,0x05,0x01,0x07,0x01, 0x05,0x07,0x80,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x09,0x01,0x01,0x05,0x02,0x01,0x67,0x00,0x07,0x06,0x08,0x07,0x57,0x00,0x06,0x00,0x04,0x08,0x06,0x04,0x67,0x00,0x07,0x07,0x08,0x5f,0x0a,0x01,0x08,0x07,0x08,0x4f,0x14,0x14,0x00,0x00,0x14,0x1f,0x14,0x1f,0x1e,0x1d,0x1c,0x1b,0x19,0x18,0x16,0x15,0x13,0x11,0x0d, 0x0b,0x00,0x0a,0x00,0x09,0x21,0x0b,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x35,0x23,0x35,0x37,0x33,0x07,0x15,0x33,0x35,0x33,0x15,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d,0x3e,0x3e,0x2d,0x54,0x01,0x5f,0xcd,0xa3,0x4e,0xb2,0x8e, 0x40,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31,0x31,0x3d,0xfd,0x60,0x42,0x59,0xb4,0xc7,0x0a,0x63,0xe1,0x00,0x00,0x00,0x00,0x03,0x00,0x2d,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x1e,0x00,0x51,0x40,0x4e,0x19,0x18,0x17,0x03,0x04,0x05,0x01,0x4c,0x00,0x05,0x01,0x04,0x01,0x05,0x04,0x80, 0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x08,0x01,0x01,0x05,0x02,0x01,0x67,0x06,0x01,0x04,0x07,0x07,0x04,0x57,0x06,0x01,0x04,0x04,0x07,0x5f,0x09,0x01,0x07,0x04,0x07,0x4f,0x14,0x14,0x00,0x00,0x14,0x1e,0x14,0x1e,0x1d,0x1c,0x1b,0x1a,0x16,0x15,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x09,0x21,0x0a,0x06,0x17,0x2b,0x13, 0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x13,0x35,0x33,0x35,0x07,0x35,0x37,0x33,0x11,0x33,0x15,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d,0x3e,0x3e,0x2d,0x54,0x94,0x83,0x7a,0x61,0x5b,0x68,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31, 0x31,0x3d,0xfd,0x60,0x3c,0xd8,0x57,0x4b,0x47,0xfe,0xed,0x3c,0x00,0x03,0x00,0x2d,0xff,0xfb,0x02,0x15,0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x2e,0x00,0xa6,0xb7,0x29,0x28,0x23,0x03,0x07,0x08,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x38,0x00,0x07,0x08,0x05,0x08,0x07,0x72,0x00,0x05,0x06,0x08,0x05,0x06,0x7e,0x00,0x00,0x00,0x03, 0x02,0x00,0x03,0x67,0x00,0x02,0x0a,0x01,0x01,0x09,0x02,0x01,0x67,0x00,0x09,0x00,0x08,0x07,0x09,0x08,0x67,0x00,0x06,0x04,0x04,0x06,0x59,0x00,0x06,0x06,0x04,0x61,0x0b,0x01,0x04,0x06,0x04,0x51,0x1b,0x40,0x39,0x00,0x07,0x08,0x05,0x08,0x07,0x05,0x80,0x00,0x05,0x06,0x08,0x05,0x06,0x7e,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67, 0x00,0x02,0x0a,0x01,0x01,0x09,0x02,0x01,0x67,0x00,0x09,0x00,0x08,0x07,0x09,0x08,0x67,0x00,0x06,0x04,0x04,0x06,0x59,0x00,0x06,0x06,0x04,0x61,0x0b,0x01,0x04,0x06,0x04,0x51,0x59,0x40,0x1e,0x15,0x14,0x00,0x00,0x27,0x26,0x25,0x24,0x22,0x20,0x1c,0x1a,0x18,0x17,0x14,0x2e,0x15,0x2e,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x09,0x21, 0x0c,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x35,0x37,0x23,0x35,0x33,0x15,0x07,0x16,0x16,0x15,0x14,0x06,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d,0x3e,0x3e, 0x2d,0x54,0x01,0x11,0x42,0x52,0x42,0x2d,0x25,0x25,0x2e,0x2d,0x25,0x1e,0x56,0xba,0xfa,0x4c,0x2f,0x39,0x53,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31,0x31,0x3d,0xfd,0x5b,0x4a,0x3a,0x21,0x29,0x20,0x19,0x19,0x1e,0x35,0x39,0x3c,0x46,0x34,0x08,0x37,0x28,0x32,0x41,0x00,0x03,0x00,0x2d,0x00,0x00,0x02,0x22, 0x02,0xda,0x00,0x0a,0x00,0x13,0x00,0x2c,0x00,0x57,0x40,0x54,0x15,0x01,0x07,0x05,0x01,0x4c,0x00,0x05,0x04,0x07,0x04,0x05,0x07,0x80,0x00,0x00,0x00,0x03,0x02,0x00,0x03,0x67,0x00,0x02,0x09,0x01,0x01,0x06,0x02,0x01,0x67,0x00,0x06,0x00,0x04,0x05,0x06,0x04,0x69,0x00,0x07,0x08,0x08,0x07,0x57,0x00,0x07,0x07,0x08,0x5f,0x0a,0x01, 0x08,0x07,0x08,0x4f,0x14,0x14,0x00,0x00,0x14,0x2c,0x14,0x2c,0x2b,0x2a,0x24,0x22,0x20,0x1f,0x1d,0x1b,0x13,0x11,0x0d,0x0b,0x00,0x0a,0x00,0x09,0x21,0x0b,0x06,0x17,0x2b,0x13,0x11,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x13,0x35,0x37,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06, 0x15,0x23,0x36,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x07,0x07,0x33,0x15,0x2d,0x96,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x54,0x54,0x2d,0x3e,0x3e,0x2d,0x54,0x9b,0x9a,0x17,0x1c,0x26,0x23,0x25,0x2c,0x42,0x03,0x50,0x40,0x41,0x4a,0x2c,0x24,0x54,0xad,0x01,0x8b,0x01,0x4f,0x2b,0x4b,0x32,0x31,0x4b,0x2b,0x39,0x3d,0x31,0x31,0x3d,0xfd,0x60, 0x3e,0x5b,0x0e,0x20,0x11,0x1e,0x23,0x2a,0x24,0x3f,0x4a,0x42,0x38,0x23,0x3a,0x14,0x2d,0x3c,0x00,0x00,0x00,0x05,0xff,0xf6,0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x16,0x00,0x1f,0x00,0x26,0x00,0x2d,0x00,0x40,0x40,0x3d,0x2c,0x2b,0x23,0x22,0x04,0x00,0x04,0x01,0x4c,0x05,0x01,0x00,0x04,0x00,0x86,0x00,0x01,0x06,0x01,0x02, 0x03,0x01,0x02,0x69,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x11,0x10,0x01,0x00,0x1c,0x1b,0x14,0x13,0x10,0x16,0x11,0x16,0x09,0x07,0x00,0x0f,0x01,0x0f,0x07,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x22,0x06,0x07,0x21,0x26, 0x26,0x03,0x36,0x36,0x37,0x37,0x21,0x17,0x16,0x16,0x25,0x34,0x27,0x03,0x3e,0x02,0x25,0x14,0x16,0x16,0x17,0x03,0x06,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x45,0x70,0x23,0x01,0xb0,0x23,0x70,0x45,0x0c,0x1b,0x0d,0x88,0xfe,0x89,0x88,0x0d,0x1a,0x01,0x10,0x14,0xd6,0x43,0x6a,0x3d,0xfd,0xf8,0x3c, 0x68,0x42,0xd3,0x13,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x58,0x8d,0x51,0x02,0x3a,0x3c,0x33,0x33,0x3c,0xfe,0x20,0x17,0x2f,0x16,0xe8,0xe8,0x16,0x2f,0xc5,0x37,0x30,0xfe,0x96,0x06,0x47,0x70,0x46,0x45,0x70,0x46,0x07,0x01,0x67,0x2f,0x00,0x02,0x00,0x34,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0b,0x00,0x25,0x00,0x5f, 0x40,0x5c,0x20,0x1d,0x12,0x03,0x09,0x06,0x01,0x4c,0x07,0x01,0x06,0x00,0x09,0x00,0x06,0x09,0x80,0x00,0x09,0x08,0x00,0x09,0x08,0x7e,0x0c,0x0a,0x02,0x08,0x08,0x84,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x0b,0x01,0x05,0x00,0x00,0x05,0x57,0x0b,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x05, 0x00,0x4f,0x0c,0x0c,0x00,0x00,0x0c,0x25,0x0c,0x25,0x1f,0x1e,0x19,0x18,0x17,0x16,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0d,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x13,0x11,0x33,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x11,0x23,0x35,0x34,0x36,0x37,0x07,0x23,0x27, 0x1e,0x02,0x15,0x15,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0x70,0x5b,0x37,0x0a,0x0b,0x04,0x04,0x0c,0x0a,0x35,0x5a,0x40,0x04,0x0a,0x56,0x43,0x58,0x05,0x07,0x04,0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x3b,0x01,0x4f,0x7b,0x16,0x1b,0x11,0x11,0x1a,0x18,0x7a,0xfe,0xb1,0x5f,0x44,0x61,0x26,0xca,0xc7,0x19,0x35, 0x46,0x34,0x5f,0x00,0x00,0x02,0x00,0x34,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0b,0x00,0x23,0x00,0x57,0x40,0x54,0x1f,0x19,0x13,0x0d,0x04,0x08,0x06,0x01,0x4c,0x07,0x01,0x06,0x00,0x08,0x00,0x06,0x08,0x80,0x0b,0x09,0x02,0x08,0x08,0x84,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x0a,0x01, 0x05,0x00,0x00,0x05,0x57,0x0a,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x05,0x00,0x4f,0x0c,0x0c,0x00,0x00,0x0c,0x23,0x0c,0x23,0x1b,0x1a,0x18,0x17,0x0f,0x0e,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0c,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x13,0x37,0x27,0x33,0x17,0x16,0x16,0x17,0x36, 0x36,0x37,0x37,0x33,0x07,0x17,0x23,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0x70,0x7e,0x7d,0x4e,0x42,0x0d,0x08,0x07,0x05,0x09,0x0c,0x40,0x4d,0x7d,0x7d,0x4f,0x41,0x0d,0x0a,0x06,0x05,0x06,0x0d,0x42,0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x3b,0xa9,0xa6,0x56,0x10,0x18, 0x0e,0x0e,0x18,0x10,0x56,0xa8,0xa7,0x55,0x11,0x1a,0x0d,0x0d,0x19,0x11,0x56,0x00,0x00,0x02,0x00,0x34,0x00,0x00,0x02,0x49,0x02,0xda,0x00,0x0b,0x00,0x13,0x00,0x4d,0x40,0x4a,0x0b,0x01,0x09,0x06,0x09,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x0a,0x01,0x05,0x00,0x00,0x07,0x05,0x00, 0x67,0x00,0x07,0x06,0x06,0x07,0x57,0x00,0x07,0x07,0x06,0x5f,0x08,0x01,0x06,0x07,0x06,0x4f,0x0c,0x0c,0x00,0x00,0x0c,0x13,0x0c,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0c,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x13,0x11,0x23,0x35,0x21,0x15,0x23, 0x11,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0xf9,0x98,0x01,0x72,0x98,0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x3b,0x01,0x13,0x3c,0x3c,0xfe,0xed,0x00,0x04,0x00,0x34,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x0b,0x00,0x19,0x00,0x22,0x00,0x2b,0x00,0x61,0x40,0x5e,0x13,0x01,0x0b,0x08,0x01,0x4c,0x00,0x01,0x00,0x02, 0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x0c,0x01,0x05,0x00,0x00,0x06,0x05,0x00,0x67,0x00,0x06,0x00,0x09,0x08,0x06,0x09,0x67,0x00,0x08,0x00,0x0b,0x0a,0x08,0x0b,0x67,0x00,0x0a,0x07,0x07,0x0a,0x57,0x00,0x0a,0x0a,0x07,0x5f,0x0d,0x01,0x07,0x0a,0x07,0x4f,0x0c,0x0c,0x00,0x00,0x2b,0x29,0x25,0x23,0x22,0x20, 0x1c,0x1a,0x0c,0x19,0x0c,0x18,0x0f,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0e,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23, 0x23,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0x7f,0xc2,0x33,0x3f,0x37,0x21,0x27,0x40,0x34,0x8f,0x81,0x14,0x1a,0x19,0x14,0x82,0x8c,0x17,0x1d,0x1d,0x17,0x8c,0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x3b,0x01,0x4f,0x2e,0x26,0x39,0x14,0x08,0x2b,0x1e,0x29,0x34,0xbf,0x17,0x13,0x13,0x19,0xdb,0x19,0x13,0x13,0x17, 0x00,0x02,0x00,0x34,0xff,0xc6,0x02,0x46,0x02,0xda,0x00,0x0b,0x00,0x2f,0x00,0xb7,0x40,0x0c,0x29,0x1b,0x1a,0x03,0x09,0x0a,0x2e,0x01,0x06,0x09,0x02,0x4c,0x4b,0xb0,0x12,0x50,0x58,0x40,0x3e,0x00,0x0a,0x08,0x09,0x09,0x0a,0x72,0x00,0x0b,0x06,0x0b,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04, 0x67,0x0c,0x01,0x05,0x00,0x00,0x07,0x05,0x00,0x67,0x00,0x07,0x00,0x08,0x0a,0x07,0x08,0x69,0x00,0x09,0x06,0x06,0x09,0x59,0x00,0x09,0x09,0x06,0x62,0x0d,0x01,0x06,0x09,0x06,0x52,0x1b,0x40,0x3f,0x00,0x0a,0x08,0x09,0x08,0x0a,0x09,0x80,0x00,0x0b,0x06,0x0b,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05, 0x03,0x04,0x67,0x0c,0x01,0x05,0x00,0x00,0x07,0x05,0x00,0x67,0x00,0x07,0x00,0x08,0x0a,0x07,0x08,0x69,0x00,0x09,0x06,0x06,0x09,0x59,0x00,0x09,0x09,0x06,0x62,0x0d,0x01,0x06,0x09,0x06,0x52,0x59,0x40,0x1e,0x0d,0x0c,0x00,0x00,0x2d,0x2c,0x2b,0x2a,0x28,0x26,0x22,0x20,0x15,0x13,0x0c,0x2f,0x0d,0x2f,0x00,0x0b,0x00,0x0b,0x11,0x11, 0x11,0x11,0x11,0x0e,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x01,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x07,0x27,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x37,0x27,0x33,0x17,0x23,0x27,0x06,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca, 0x01,0x1a,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x32,0x4f,0x2e,0x21,0x2d,0x05,0x05,0x3e,0x2d,0x2d,0x3e,0x3e,0x2d,0x0a,0x09,0x36,0x4b,0x8e,0x4b,0x30,0x1c,0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x36,0x2d,0x4e,0x31,0x32,0x4e,0x2d,0x2d,0x4e,0x32,0x3a,0x2e,0x36,0x0b,0x1a,0x0d,0x31,0x41,0x41,0x31,0x31,0x41,0x02,0x46,0xb7, 0x3e,0x09,0x00,0x00,0x00,0x02,0x00,0x34,0xff,0xfb,0x02,0x3a,0x02,0xda,0x00,0x0b,0x00,0x27,0x00,0x62,0x40,0x5f,0x00,0x08,0x09,0x0b,0x09,0x08,0x0b,0x80,0x00,0x0b,0x0a,0x09,0x0b,0x0a,0x7e,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x0c,0x01,0x05,0x00,0x00,0x07,0x05,0x00,0x67,0x00,0x07, 0x00,0x09,0x08,0x07,0x09,0x69,0x00,0x0a,0x06,0x06,0x0a,0x59,0x00,0x0a,0x0a,0x06,0x61,0x0d,0x01,0x06,0x0a,0x06,0x51,0x0d,0x0c,0x00,0x00,0x25,0x24,0x22,0x20,0x1c,0x1a,0x18,0x17,0x15,0x13,0x0c,0x27,0x0d,0x27,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0e,0x06,0x1b,0x2b,0x01,0x15,0x21,0x11,0x21,0x15,0x23,0x15,0x33,0x15, 0x23,0x15,0x01,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x33,0x06,0x06,0x01,0x5e,0xfe,0xd6,0x01,0x2a,0xe8,0xca,0xca,0x01,0x21,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x39,0x5a,0x10,0x44,0x0b,0x35,0x1f,0x2e,0x3d,0x3d,0x2e,0x1f,0x35,0x0b,0x44,0x10,0x5a, 0x01,0xc5,0x3a,0x01,0x4f,0x3a,0x56,0x2f,0x56,0xfe,0x36,0x2d,0x4e,0x31,0x32,0x4e,0x2d,0x3e,0x32,0x18,0x1e,0x41,0x32,0x31,0x41,0x1e,0x18,0x31,0x3f,0x00,0x00,0x00,0x00,0x02,0x00,0x3e,0xff,0xfc,0x02,0x2f,0x02,0xda,0x00,0x09,0x00,0x35,0x00,0x61,0x40,0x5e,0x0b,0x01,0x04,0x03,0x08,0x03,0x04,0x08,0x80,0x00,0x09,0x0a,0x06,0x0a, 0x09,0x06,0x80,0x00,0x06,0x07,0x0a,0x06,0x07,0x7e,0x00,0x00,0x00,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x08,0x00,0x0a,0x09,0x08,0x0a,0x69,0x00,0x07,0x05,0x05,0x07,0x59,0x00,0x07,0x07,0x05,0x61,0x0c,0x01,0x05,0x07,0x05,0x51,0x0b,0x0a,0x00,0x00,0x29,0x26,0x24,0x23,0x21,0x1e,0x13,0x10,0x0e, 0x0d,0x0a,0x35,0x0b,0x34,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x0d,0x06,0x1a,0x2b,0x13,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17, 0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x3e,0x01,0x2a,0xe8,0xca,0xca,0x01,0x04,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x01,0x8b,0x01,0x4f,0x3a,0x56,0x3a,0x85,0xfe,0x71,0x3a,0x31,0x16,0x1b, 0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0x00,0x00,0x00,0x02,0x00,0x3e,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x09,0x00,0x13,0x00,0x55,0x40,0x52,0x0a,0x01,0x04,0x03,0x05,0x03,0x04,0x05,0x80,0x0b,0x01,0x09,0x08,0x09,0x86,0x00,0x00,0x00, 0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x00,0x03,0x04,0x02,0x03,0x67,0x00,0x05,0x00,0x06,0x07,0x05,0x06,0x67,0x00,0x07,0x08,0x08,0x07,0x57,0x00,0x07,0x07,0x08,0x5f,0x00,0x08,0x07,0x08,0x4f,0x0a,0x0a,0x00,0x00,0x0a,0x13,0x0a,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x00,0x09,0x00,0x09,0x11,0x11,0x11,0x11,0x0c,0x06,0x1a, 0x2b,0x13,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x13,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x3e,0x01,0x2a,0xe8,0xca,0xca,0x86,0x01,0x2a,0xe8,0xca,0xca,0x01,0x8b,0x01,0x4f,0x3a,0x56,0x3a,0x85,0xfe,0x75,0x01,0x4f,0x3a,0x56,0x3a,0x85,0x00,0x00,0x00,0x00,0x02,0x00,0x20,0xff,0xfc,0x02,0x2f,0x02,0xdf,0x00,0x1f, 0x00,0x4b,0x00,0x65,0x40,0x62,0x00,0x01,0x02,0x05,0x02,0x01,0x05,0x80,0x00,0x0b,0x0c,0x08,0x0c,0x0b,0x08,0x80,0x00,0x08,0x09,0x0c,0x08,0x09,0x7e,0x00,0x00,0x00,0x02,0x01,0x00,0x02,0x69,0x00,0x05,0x00,0x04,0x03,0x05,0x04,0x67,0x00,0x03,0x00,0x06,0x0a,0x03,0x06,0x69,0x00,0x0a,0x00,0x0c,0x0b,0x0a,0x0c,0x69,0x00,0x09,0x07, 0x07,0x09,0x59,0x00,0x09,0x09,0x07,0x61,0x0d,0x01,0x07,0x09,0x07,0x51,0x21,0x20,0x3f,0x3c,0x3a,0x39,0x37,0x34,0x29,0x26,0x24,0x23,0x20,0x4b,0x21,0x4a,0x24,0x11,0x12,0x24,0x22,0x12,0x23,0x0e,0x06,0x1d,0x2b,0x13,0x34,0x36,0x36,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x37,0x23,0x35, 0x33,0x15,0x14,0x06,0x06,0x23,0x22,0x26,0x26,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x20,0x2e,0x4f,0x32,0x39,0x59,0x10,0x44,0x0b,0x34,0x1f, 0x2e,0x3d,0x3d,0x2e,0x20,0x36,0x0d,0x63,0xa7,0x2c,0x4b,0x30,0x32,0x4f,0x2e,0x01,0x64,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x02,0x32,0x32,0x4e,0x2d,0x3d,0x2d,0x14,0x1c,0x41,0x32,0x31, 0x41,0x20,0x27,0x39,0x0e,0x33,0x4d,0x2c,0x2d,0x4e,0xfd,0xfb,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x00,0x02,0x49,0x02,0xda,0x00,0x0b,0x00,0x13,0x00,0x4c,0x40,0x49,0x02,0x01, 0x00,0x01,0x00,0x85,0x0a,0x05,0x02,0x03,0x04,0x07,0x04,0x03,0x07,0x80,0x0b,0x01,0x09,0x06,0x09,0x86,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x67,0x00,0x07,0x06,0x06,0x07,0x57,0x00,0x07,0x07,0x06,0x5f,0x08,0x01,0x06,0x07,0x06,0x4f,0x0c,0x0c,0x00,0x00,0x0c,0x13,0x0c,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11, 0x11,0x11,0x11,0x11,0x0c,0x06,0x1b,0x2b,0x13,0x11,0x33,0x15,0x33,0x35,0x33,0x11,0x23,0x35,0x23,0x15,0x01,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0x2d,0x42,0xb2,0x42,0x42,0xb2,0x01,0x00,0x98,0x01,0x72,0x98,0x01,0x8b,0x01,0x4f,0x84,0x84,0xfe,0xb1,0x8f,0x8f,0xfe,0x75,0x01,0x13,0x3c,0x3c,0xfe,0xed,0x00,0x00,0x00,0x04,0xff,0xf6, 0x00,0x32,0x02,0x62,0x02,0x9e,0x00,0x0f,0x00,0x21,0x00,0x27,0x00,0x2d,0x00,0x50,0x40,0x4d,0x2c,0x23,0x19,0x03,0x00,0x05,0x01,0x4c,0x07,0x01,0x00,0x05,0x00,0x86,0x00,0x01,0x08,0x01,0x02,0x03,0x01,0x02,0x69,0x04,0x01,0x03,0x05,0x05,0x03,0x57,0x04,0x01,0x03,0x03,0x05,0x5f,0x0a,0x06,0x09,0x03,0x05,0x03,0x05,0x4f,0x28,0x28, 0x22,0x22,0x11,0x10,0x01,0x00,0x28,0x2d,0x28,0x2d,0x22,0x27,0x22,0x27,0x1e,0x1d,0x15,0x14,0x10,0x21,0x11,0x21,0x09,0x07,0x00,0x0f,0x01,0x0f,0x0b,0x06,0x16,0x2b,0x25,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x14,0x06,0x06,0x03,0x22,0x06,0x06,0x07,0x33,0x17,0x16,0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x2e, 0x02,0x13,0x07,0x3e,0x02,0x37,0x21,0x1e,0x02,0x17,0x27,0x01,0x2c,0x58,0x8d,0x51,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c,0x59,0x46,0x71,0x47,0x05,0x77,0x59,0x0e,0x19,0x0c,0x0c,0x1b,0x0d,0x59,0x76,0x05,0x47,0x71,0x60,0x8c,0x40,0x66,0x3e,0x05,0xfd,0xfa,0x05,0x3d,0x64,0x3f,0x8b,0x32,0x51,0x8d,0x58,0x59,0x8c,0x51,0x51,0x8c, 0x59,0x58,0x8d,0x51,0x02,0x3a,0x3e,0x6b,0x44,0x97,0x16,0x2f,0x17,0x17,0x2f,0x16,0x97,0x44,0x6b,0x3e,0xfe,0xe6,0xed,0x06,0x40,0x67,0x40,0x40,0x66,0x40,0x06,0xec,0x00,0x02,0x00,0x51,0x00,0x00,0x02,0x07,0x02,0x30,0x00,0x04,0x00,0x09,0x00,0x28,0x40,0x25,0x09,0x08,0x07,0x03,0x02,0x01,0x06,0x01,0x4a,0x00,0x01,0x00,0x00,0x01, 0x57,0x00,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x00,0x00,0x06,0x05,0x00,0x04,0x00,0x04,0x03,0x06,0x16,0x2b,0x33,0x11,0x37,0x17,0x11,0x25,0x21,0x11,0x27,0x07,0x51,0xdb,0xdb,0xfe,0x7c,0x01,0x52,0xa9,0xa9,0x01,0x5b,0xd5,0xd5,0xfe,0xa5,0x32,0x01,0x11,0xa5,0xa5,0x00,0x00,0x00,0x04,0x00,0x14,0x00,0x00,0x02,0x44, 0x03,0x16,0x00,0x06,0x00,0x0d,0x00,0x17,0x00,0x1b,0x00,0x53,0x40,0x50,0x08,0x06,0x02,0x03,0x4a,0x0a,0x05,0x02,0x03,0x02,0x01,0x00,0x04,0x03,0x00,0x67,0x00,0x04,0x00,0x01,0x07,0x04,0x01,0x67,0x0b,0x01,0x07,0x0c,0x01,0x09,0x08,0x07,0x09,0x67,0x00,0x08,0x06,0x06,0x08,0x57,0x00,0x08,0x08,0x06,0x5f,0x00,0x06,0x08,0x06,0x4f, 0x18,0x18,0x0e,0x0e,0x07,0x07,0x18,0x1b,0x18,0x1b,0x1a,0x19,0x0e,0x17,0x0e,0x17,0x14,0x11,0x07,0x0d,0x07,0x0d,0x11,0x14,0x11,0x11,0x10,0x0d,0x06,0x1b,0x2b,0x01,0x23,0x15,0x23,0x35,0x23,0x01,0x13,0x27,0x07,0x33,0x15,0x33,0x35,0x13,0x15,0x14,0x06,0x23,0x23,0x22,0x26,0x35,0x35,0x17,0x15,0x33,0x35,0x02,0x44,0x9b,0xfa,0x9b, 0x01,0x18,0xba,0xba,0xba,0x6c,0x9c,0x2f,0x21,0x1b,0x82,0x1b,0x21,0x2f,0x9c,0x01,0xe5,0xd6,0xd6,0x01,0x31,0xfe,0xf5,0xcd,0xcd,0xd6,0xd6,0xfe,0xb4,0x83,0x1b,0x21,0x21,0x1b,0x83,0x26,0x71,0x71,0x00,0x00,0x00,0x02,0xff,0x5b,0x00,0x41,0x02,0x8f,0x02,0xa3,0x00,0x0a,0x00,0x16,0x00,0x29,0x40,0x26,0x16,0x15,0x14,0x13,0x12,0x11, 0x10,0x0f,0x0e,0x0d,0x0c,0x02,0x0c,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x00,0x76,0x01,0x00,0x05,0x03,0x00,0x0a,0x01,0x0a,0x03,0x06,0x16,0x2b,0x25,0x21,0x01,0x01,0x21,0x32,0x16,0x15,0x11,0x14,0x06,0x27,0x27,0x37,0x27,0x07,0x27,0x07,0x17,0x07,0x17,0x37,0x17,0x02,0x2e,0xfe,0x5c,0xfe,0xd1,0x01,0x33, 0x01,0xa0,0x2c,0x35,0x35,0x17,0x9e,0x9b,0x43,0x9b,0x9a,0x48,0x9c,0x99,0x45,0x98,0x9b,0x41,0x01,0x2c,0x01,0x36,0x36,0x2c,0xfe,0x62,0x2b,0x37,0x96,0x9c,0x9c,0x43,0x9b,0x9b,0x47,0x9c,0x99,0x44,0x99,0x9b,0x00,0x02,0xff,0xc9,0x00,0x41,0x02,0xfd,0x02,0xa3,0x00,0x0a,0x00,0x16,0x00,0x29,0x40,0x26,0x16,0x15,0x14,0x13,0x12,0x11, 0x10,0x0f,0x0e,0x0d,0x0c,0x09,0x0c,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x00,0x76,0x01,0x00,0x08,0x06,0x00,0x0a,0x01,0x0a,0x03,0x06,0x16,0x2b,0x37,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x21,0x01,0x01,0x25,0x17,0x37,0x17,0x37,0x27,0x37,0x27,0x07,0x27,0x07,0x17,0x2a,0x2b,0x36,0x36,0x2b,0x01,0xa0,0x01, 0x33,0xfe,0xd1,0xfe,0x47,0x48,0x9b,0x98,0x45,0x99,0x9c,0x48,0x9a,0x9b,0x43,0x9b,0x41,0x37,0x2b,0x01,0x9e,0x2c,0x36,0xfe,0xca,0xfe,0xd4,0x96,0x47,0x9b,0x99,0x44,0x99,0x9c,0x47,0x9b,0x9b,0x43,0x9c,0x00,0x00,0x09,0xff,0xa9,0x00,0x41,0x02,0xaf,0x02,0xa3,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x1d,0x00,0x21,0x00,0x25,0x00,0x29, 0x00,0x2d,0x00,0x31,0x00,0x64,0x40,0x61,0x00,0x01,0x0a,0x07,0x05,0x03,0x03,0x02,0x01,0x03,0x67,0x09,0x08,0x04,0x03,0x02,0x10,0x0e,0x02,0x0c,0x06,0x02,0x0c,0x67,0x0f,0x0d,0x0b,0x03,0x06,0x00,0x12,0x11,0x06,0x12,0x67,0x00,0x11,0x00,0x00,0x11,0x57,0x00,0x11,0x11,0x00,0x60,0x13,0x01,0x00,0x11,0x00,0x50,0x01,0x00,0x31,0x30, 0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x09,0x06,0x00,0x0f,0x01,0x0e,0x14,0x06,0x16,0x2b,0x37,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x21,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x01,0x33,0x35,0x23,0x17,0x33, 0x35,0x23,0x01,0x33,0x11,0x23,0x15,0x33,0x23,0x33,0x35,0x23,0x03,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x17,0x33,0x35,0x23,0x01,0x21,0x35,0x21,0x14,0x2f,0x3c,0x36,0x2b,0x02,0x44,0x2c,0x35,0x35,0x2c,0xfd,0x9f,0x6c,0x6c,0x98,0x6c,0x6c,0x01,0x7a,0x6c,0xb6,0x4a,0xe2,0x6c,0x6c,0xe6,0x6c,0x6c,0x98,0x6c,0x6c,0x98,0x6c,0x6c,0xfe, 0x86,0x01,0xe6,0xfe,0x1a,0x41,0x3c,0x2f,0x01,0x95,0x2c,0x36,0x36,0x2c,0xfe,0x61,0x2b,0x36,0x01,0x9e,0x80,0x80,0x80,0xfe,0xd4,0x01,0x2c,0x80,0x80,0xfe,0xd4,0x80,0x80,0x80,0x80,0x80,0xfe,0xd4,0x80,0x00,0x00,0x02,0x00,0x0a,0x00,0x00,0x02,0x4e,0x02,0xda,0x00,0x07,0x00,0x0b,0x00,0x33,0x40,0x30,0x04,0x01,0x01,0x07,0x05,0x02, 0x00,0x02,0x01,0x00,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x06,0x01,0x03,0x02,0x03,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x06,0x19,0x2b,0x21,0x03,0x23,0x35,0x33,0x13,0x33,0x15,0x03,0x35,0x33,0x15,0x01,0x69,0xbc,0xa3,0xe5,0xbd,0xa2,0xcc,0xcc, 0x02,0x8a,0x50,0xfd,0x76,0x50,0x02,0x8a,0x50,0x50,0x00,0x00,0x00,0x01,0x00,0x64,0xff,0xe2,0x01,0xf4,0x02,0xdb,0x00,0x16,0x00,0x3f,0x40,0x3c,0x12,0x01,0x08,0x49,0x00,0x03,0x02,0x03,0x85,0x09,0x01,0x08,0x07,0x08,0x86,0x04,0x01,0x02,0x05,0x01,0x01,0x00,0x02,0x01,0x67,0x06,0x01,0x00,0x07,0x07,0x00,0x57,0x06,0x01,0x00,0x00, 0x07,0x5f,0x0a,0x01,0x07,0x00,0x07,0x4f,0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x0b,0x06,0x1f,0x2b,0x13,0x33,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x33,0x07,0x27,0x33,0x35,0x23,0x6e,0x93,0x93,0x93,0x56,0x93,0x93,0x93,0x93,0x9d,0xc2,0xce,0x9d,0x93,0x01,0x94, 0x59,0x50,0x9e,0x9e,0x50,0x59,0x50,0x7e,0xe4,0xe4,0x7e,0x00,0x00,0x01,0x00,0x64,0xff,0xff,0x01,0xf4,0x02,0xf8,0x00,0x16,0x00,0x44,0x40,0x41,0x05,0x01,0x01,0x4a,0x02,0x01,0x01,0x00,0x01,0x85,0x00,0x07,0x06,0x07,0x86,0x03,0x01,0x00,0x0b,0x0a,0x02,0x04,0x05,0x00,0x04,0x67,0x09,0x01,0x05,0x06,0x06,0x05,0x57,0x09,0x01,0x05, 0x05,0x06,0x5f,0x08,0x01,0x06,0x05,0x06,0x4f,0x00,0x00,0x00,0x16,0x00,0x16,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x12,0x11,0x11,0x0c,0x06,0x1f,0x2b,0x13,0x35,0x33,0x35,0x23,0x37,0x17,0x23,0x15,0x33,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x23,0x35,0x33,0x35,0x6e,0x93,0x9d,0xce,0xc2,0x9d,0x93,0x93,0x93,0x93,0x56, 0x93,0x93,0x01,0x46,0x50,0x7e,0xe4,0xe4,0x7e,0x50,0x59,0x50,0x9e,0x9e,0x50,0x59,0x00,0x06,0x00,0x00,0x00,0x48,0x02,0x58,0x02,0x9c,0x00,0x0a,0x00,0x0e,0x00,0x19,0x00,0x24,0x00,0x2f,0x00,0x5f,0x00,0x6e,0x40,0x6b,0x0f,0x01,0x0d,0x05,0x01,0x01,0x00,0x0d,0x01,0x69,0x0e,0x14,0x04,0x03,0x00,0x10,0x0c,0x02,0x03,0x02,0x00,0x03, 0x69,0x11,0x0b,0x02,0x02,0x13,0x08,0x15,0x03,0x06,0x07,0x02,0x06,0x69,0x09,0x01,0x07,0x0a,0x0a,0x07,0x59,0x09,0x01,0x07,0x07,0x0a,0x61,0x12,0x16,0x02,0x0a,0x07,0x0a,0x51,0x31,0x30,0x1b,0x1a,0x10,0x0f,0x5c,0x5b,0x58,0x56,0x52,0x50,0x4f,0x4d,0x49,0x47,0x44,0x43,0x40,0x3e,0x3a,0x38,0x37,0x35,0x30,0x5f,0x31,0x5f,0x2e,0x2c, 0x28,0x26,0x20,0x1e,0x1a,0x24,0x1b,0x24,0x15,0x13,0x0f,0x19,0x10,0x19,0x11,0x12,0x24,0x21,0x17,0x06,0x1a,0x2b,0x01,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x03,0x33,0x35,0x23,0x27,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x05,0x23,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x05,0x35,0x23,0x22,0x06, 0x15,0x14,0x16,0x33,0x32,0x36,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x35,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x33,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x23,0x15,0x14,0x06,0x01,0x9c,0x41,0x1c,0x25,0x25,0x1c,0x1c,0x25,0xa6, 0x6c,0x6c,0x7b,0x41,0x25,0x1c,0x1c,0x25,0x25,0x01,0x7e,0x41,0x25,0x1c,0x1c,0x25,0x25,0xfe,0xc3,0x41,0x1c,0x25,0x25,0x1c,0x1c,0x25,0x41,0x34,0x47,0x47,0x34,0x41,0x41,0x34,0x47,0x47,0x34,0x35,0x46,0x6c,0x47,0x34,0x35,0x46,0x46,0x35,0x41,0x41,0x35,0x46,0x46,0x35,0x34,0x47,0x6c,0x46,0x02,0x24,0x41,0x25,0x1c,0x1c,0x25,0x25, 0xfe,0xf8,0x74,0x37,0x41,0x1c,0x25,0x25,0x1c,0x1c,0x25,0xe2,0x41,0x1c,0x25,0x25,0x1c,0x1c,0x25,0x41,0x41,0x25,0x1c,0x1c,0x25,0x25,0x5c,0x44,0x34,0x34,0x44,0x74,0x44,0x34,0x34,0x44,0x44,0x34,0x41,0x41,0x34,0x44,0x44,0x34,0x34,0x44,0x74,0x44,0x34,0x34,0x44,0x44,0x34,0x41,0x41,0x34,0x44,0x00,0x00,0x00,0x00,0x02,0xff,0xec, 0x00,0x32,0x02,0x67,0x02,0xda,0x00,0x11,0x00,0x1a,0x00,0x3d,0x40,0x3a,0x19,0x02,0x02,0x00,0x04,0x1a,0x01,0x02,0x03,0x05,0x02,0x4c,0x12,0x00,0x02,0x02,0x49,0x00,0x01,0x00,0x04,0x00,0x01,0x04,0x67,0x00,0x00,0x00,0x05,0x03,0x00,0x05,0x67,0x00,0x03,0x02,0x02,0x03,0x57,0x00,0x03,0x03,0x02,0x5f,0x00,0x02,0x03,0x02,0x4f,0x11, 0x11,0x12,0x25,0x33,0x13,0x06,0x06,0x1c,0x2b,0x25,0x01,0x01,0x15,0x33,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x21,0x07,0x35,0x21,0x11,0x23,0x11,0x23,0x35,0x07,0x01,0x1d,0xfe,0xcf,0x01,0x31,0x4c,0x21,0x1b,0x86,0x1b,0x21,0x21,0x1b,0xfe,0xf2,0x2c,0x01,0x47,0xa0,0xa7,0xc5,0x32,0x01,0x1d,0x01,0x1d,0xa5, 0xd7,0x1b,0x21,0x21,0x1b,0xfe,0x76,0x1b,0x21,0x40,0x6b,0x01,0xaa,0xfe,0xee,0x6c,0xb8,0x00,0x00,0x00,0x00,0x02,0x00,0x52,0x00,0x00,0x02,0x30,0x02,0xda,0x00,0x05,0x00,0x0f,0x00,0x48,0x40,0x45,0x00,0x00,0x01,0x00,0x85,0x09,0x01,0x07,0x06,0x07,0x86,0x00,0x01,0x08,0x01,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03, 0x04,0x67,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05,0x06,0x5f,0x00,0x06,0x05,0x06,0x4f,0x06,0x06,0x00,0x00,0x06,0x0f,0x06,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11,0x0a,0x06,0x18,0x2b,0x13,0x11,0x33,0x11,0x33,0x15,0x03,0x11,0x21,0x15,0x23,0x15,0x33,0x15,0x23,0x15,0x52,0x42,0xde,0x6c, 0x01,0x2a,0xe8,0xca,0xca,0x01,0x8b,0x01,0x4f,0xfe,0xed,0x3c,0xfe,0x75,0x01,0x4f,0x3a,0x56,0x3a,0x85,0x00,0x02,0x00,0x2d,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x11,0x00,0x1e,0x00,0x54,0x40,0x51,0x0c,0x03,0x02,0x02,0x00,0x19,0x01,0x08,0x05,0x02,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x0a,0x03,0x02,0x02,0x04,0x02,0x85,0x06,0x01, 0x04,0x05,0x04,0x85,0x0b,0x09,0x02,0x07,0x08,0x07,0x86,0x00,0x05,0x08,0x08,0x05,0x57,0x00,0x05,0x05,0x08,0x5f,0x00,0x08,0x05,0x08,0x4f,0x12,0x12,0x00,0x00,0x12,0x1e,0x12,0x1e,0x1d,0x1c,0x1b,0x1a,0x18,0x17,0x16,0x15,0x14,0x13,0x00,0x11,0x00,0x11,0x11,0x16,0x11,0x0c,0x06,0x19,0x2b,0x13,0x11,0x33,0x13,0x2e,0x02,0x35,0x35, 0x33,0x11,0x23,0x03,0x1e,0x02,0x15,0x15,0x13,0x11,0x33,0x15,0x33,0x37,0x33,0x07,0x17,0x23,0x27,0x23,0x15,0x2d,0x50,0xb2,0x05,0x06,0x02,0x41,0x50,0xb2,0x06,0x05,0x02,0x87,0x42,0x4f,0x60,0x4a,0x71,0x7b,0x4e,0x66,0x4f,0x01,0x8b,0x01,0x4f,0xfe,0xf7,0x1e,0x25,0x31,0x2c,0x69,0xfe,0xb1,0x01,0x09,0x1c,0x26,0x31,0x2d,0x69,0xfe, 0x75,0x01,0x4f,0x86,0x86,0xa1,0xae,0x8f,0x8f,0x00,0x00,0x00,0x00,0x02,0x00,0x2d,0x00,0x00,0x02,0x3a,0x02,0xda,0x00,0x11,0x00,0x17,0x00,0x43,0x40,0x40,0x0c,0x03,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x07,0x03,0x02,0x02,0x04,0x02,0x85,0x00,0x04,0x05,0x04,0x85,0x00,0x05,0x06,0x06,0x05,0x57,0x00,0x05,0x05, 0x06,0x5f,0x08,0x01,0x06,0x05,0x06,0x4f,0x12,0x12,0x00,0x00,0x12,0x17,0x12,0x17,0x16,0x15,0x14,0x13,0x00,0x11,0x00,0x11,0x11,0x16,0x11,0x09,0x06,0x19,0x2b,0x13,0x11,0x33,0x13,0x2e,0x02,0x35,0x35,0x33,0x11,0x23,0x03,0x1e,0x02,0x15,0x15,0x13,0x11,0x33,0x11,0x33,0x15,0x2d,0x50,0xb2,0x05,0x06,0x02,0x41,0x50,0xb2,0x06,0x05, 0x02,0xac,0x42,0xde,0x01,0x8b,0x01,0x4f,0xfe,0xf7,0x1e,0x25,0x31,0x2c,0x69,0xfe,0xb1,0x01,0x09,0x1c,0x26,0x31,0x2d,0x69,0xfe,0x75,0x01,0x4f,0xfe,0xed,0x3c,0x00,0x00,0x02,0x00,0x2d,0xff,0xf6,0x02,0x2b,0x02,0xda,0x00,0x11,0x00,0x23,0x00,0x46,0x40,0x43,0x0c,0x03,0x02,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x08, 0x03,0x02,0x02,0x05,0x02,0x85,0x07,0x01,0x05,0x06,0x05,0x85,0x00,0x06,0x04,0x04,0x06,0x59,0x00,0x06,0x06,0x04,0x61,0x09,0x01,0x04,0x06,0x04,0x51,0x13,0x12,0x00,0x00,0x20,0x1f,0x1c,0x1a,0x17,0x16,0x12,0x23,0x13,0x23,0x00,0x11,0x00,0x11,0x11,0x16,0x11,0x0a,0x06,0x19,0x2b,0x13,0x11,0x33,0x13,0x2e,0x02,0x35,0x35,0x33,0x11, 0x23,0x03,0x1e,0x02,0x15,0x15,0x01,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x2d,0x50,0xb2,0x05,0x06,0x02,0x41,0x50,0xb2,0x06,0x05,0x02,0x01,0x22,0x45,0x56,0x42,0x31,0x28,0x28,0x31,0x42,0x56,0x01,0x8b,0x01,0x4f,0xfe,0xf7,0x1e,0x25,0x31,0x2c,0x69,0xfe,0xb1,0x01,0x09,0x1c,0x26, 0x31,0x2d,0x69,0xfe,0x6b,0x53,0x47,0xbf,0xbf,0x2c,0x32,0x32,0x2c,0xbf,0xbf,0x47,0x53,0x00,0x00,0x00,0x00,0x02,0xff,0xec,0xff,0xf6,0x02,0x6c,0x02,0xd5,0x00,0x0d,0x00,0x37,0x00,0x32,0x40,0x2f,0x00,0x01,0x00,0x01,0x85,0x04,0x01,0x00,0x03,0x00,0x85,0x00,0x03,0x02,0x02,0x03,0x59,0x00,0x03,0x03,0x02,0x61,0x05,0x01,0x02,0x03, 0x02,0x51,0x0f,0x0e,0x01,0x00,0x24,0x22,0x0e,0x37,0x0f,0x37,0x08,0x06,0x00,0x0d,0x01,0x0d,0x06,0x06,0x16,0x2b,0x25,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x07,0x22,0x2e,0x02,0x35,0x34,0x36,0x37,0x36,0x36,0x17,0x16,0x06,0x07,0x06,0x06,0x15,0x14,0x16,0x16,0x33,0x32,0x36,0x36,0x35,0x34,0x26,0x27, 0x26,0x26,0x37,0x36,0x16,0x17,0x16,0x16,0x15,0x14,0x0e,0x02,0x01,0x2c,0x16,0x21,0x21,0x16,0x17,0x20,0x20,0x17,0x43,0x74,0x58,0x31,0x32,0x2a,0x15,0x33,0x10,0x10,0x07,0x14,0x19,0x1d,0x34,0x5d,0x3c,0x3c,0x5d,0x34,0x1c,0x1a,0x14,0x07,0x10,0x11,0x32,0x15,0x2b,0x31,0x31,0x58,0x74,0xe1,0x23,0x19,0x01,0x7c,0x19,0x23,0x23,0x19, 0xfe,0x84,0x19,0x23,0xeb,0x30,0x57,0x72,0x42,0x41,0x72,0x2b,0x16,0x07,0x11,0x10,0x30,0x17,0x1c,0x4b,0x2c,0x3d,0x5f,0x36,0x36,0x5f,0x3d,0x2c,0x4b,0x1c,0x17,0x30,0x10,0x11,0x07,0x16,0x2a,0x73,0x41,0x42,0x72,0x57,0x30,0x00,0x00,0x03,0xff,0xec,0xff,0xf6,0x02,0x6c,0x02,0x6c,0x00,0x13,0x00,0x23,0x00,0x31,0x00,0x49,0x40,0x46, 0x00,0x05,0x03,0x04,0x03,0x05,0x04,0x80,0x08,0x01,0x04,0x02,0x03,0x04,0x02,0x7e,0x00,0x01,0x00,0x03,0x05,0x01,0x03,0x69,0x07,0x01,0x02,0x00,0x00,0x02,0x59,0x07,0x01,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x02,0x00,0x51,0x25,0x24,0x15,0x14,0x01,0x00,0x2c,0x2a,0x24,0x31,0x25,0x31,0x1d,0x1b,0x14,0x23,0x15,0x23,0x0b,0x09,0x00, 0x13,0x01,0x13,0x09,0x06,0x16,0x2b,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x37,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x01,0x2c,0x43,0x74,0x58,0x31,0x31,0x58,0x74,0x43,0x43, 0x74,0x58,0x31,0x31,0x58,0x74,0x43,0x3c,0x62,0x39,0x39,0x62,0x3c,0x3c,0x61,0x3a,0x3a,0x61,0x3c,0x16,0x21,0x21,0x16,0x17,0x20,0x20,0x0a,0x30,0x57,0x72,0x42,0x42,0x72,0x57,0x30,0x30,0x57,0x72,0x42,0x42,0x72,0x57,0x30,0x5f,0x3b,0x64,0x3d,0x3d,0x64,0x3b,0x3b,0x64,0x3d,0x3d,0x64,0x3b,0x46,0x23,0x19,0xb4,0x19,0x23,0x23,0x19, 0xb4,0x19,0x23,0x00,0x00,0x02,0xff,0xec,0xff,0xf6,0x02,0x6c,0x02,0x6c,0x00,0x13,0x00,0x23,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x15,0x14,0x01,0x00,0x1d,0x1b,0x14,0x23,0x15,0x23,0x0b,0x09,0x00,0x13,0x01, 0x13,0x06,0x06,0x16,0x2b,0x05,0x22,0x2e,0x02,0x35,0x34,0x3e,0x02,0x33,0x32,0x1e,0x02,0x15,0x14,0x0e,0x02,0x27,0x32,0x36,0x36,0x35,0x34,0x26,0x26,0x23,0x22,0x06,0x06,0x15,0x14,0x16,0x16,0x01,0x2c,0x43,0x74,0x58,0x31,0x31,0x58,0x74,0x43,0x43,0x74,0x58,0x31,0x31,0x58,0x74,0x43,0x3c,0x62,0x39,0x39,0x62,0x3c,0x3c,0x61,0x3a, 0x3a,0x61,0x0a,0x30,0x57,0x72,0x42,0x42,0x72,0x57,0x30,0x30,0x57,0x72,0x42,0x42,0x72,0x57,0x30,0x5f,0x3b,0x64,0x3d,0x3d,0x64,0x3b,0x3b,0x64,0x3d,0x3d,0x64,0x3b,0x00,0x01,0x00,0xf5,0xff,0xfb,0x01,0x63,0x02,0x67,0x00,0x0d,0x00,0x18,0x40,0x15,0x00,0x01,0x00,0x01,0x85,0x02,0x01,0x00,0x00,0x76,0x01,0x00,0x08,0x06,0x00,0x0d, 0x01,0x0d,0x03,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x01,0x2c,0x16,0x21,0x21,0x16,0x17,0x20,0x20,0x05,0x23,0x19,0x01,0xf4,0x19,0x23,0x23,0x19,0xfe,0x0c,0x19,0x23,0x00,0x00,0x00,0x01,0x00,0x06,0xff,0xf7,0x02,0x66,0x02,0x57,0x00,0x15,0x00,0x16,0x40,0x13,0x0f,0x07,0x02,0x00, 0x4a,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x01,0x76,0x15,0x1d,0x02,0x06,0x18,0x2b,0x37,0x26,0x26,0x36,0x36,0x37,0x36,0x37,0x06,0x06,0x16,0x17,0x16,0x16,0x36,0x37,0x06,0x07,0x0e,0x02,0x26,0x64,0x2f,0x2f,0x01,0x30,0x30,0x27,0x2b,0x1e,0x05,0x2e,0x2e,0x2f,0x82,0x89,0x3a,0x16,0x27,0x30,0x75,0x7c,0x75,0x55,0x2f,0x75,0x7c,0x75, 0x30,0x27,0x16,0x39,0x8a,0x82,0x2e,0x2f,0x2e,0x05,0x1e,0x2b,0x27,0x30,0x30,0x01,0x2f,0x00,0x00,0x00,0x00,0x02,0x00,0x23,0x01,0x4a,0x02,0x35,0x02,0xda,0x00,0x03,0x00,0x09,0x00,0x34,0x40,0x31,0x08,0x05,0x02,0x02,0x01,0x01,0x4c,0x05,0x03,0x02,0x02,0x01,0x02,0x86,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x04, 0x01,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x09,0x04,0x09,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x06,0x06,0x17,0x2b,0x13,0x35,0x21,0x15,0x09,0x02,0x23,0x27,0x07,0x37,0x01,0xea,0xfe,0x02,0x01,0x09,0x01,0x09,0x6e,0x9a,0x9e,0x02,0x8a,0x50,0x50,0xfe,0xc0,0x01,0x0e,0xfe,0xf2,0xa2,0xa2,0x00,0x00,0x00,0x00,0x03,0x00,0x2d, 0xff,0xfc,0x02,0x2f,0x02,0xda,0x00,0x0d,0x00,0x16,0x00,0x42,0x00,0x6b,0x40,0x68,0x08,0x01,0x02,0x04,0x01,0x4c,0x0c,0x03,0x02,0x01,0x02,0x09,0x02,0x01,0x09,0x80,0x00,0x0a,0x0b,0x07,0x0b,0x0a,0x07,0x80,0x00,0x07,0x08,0x0b,0x07,0x08,0x7e,0x00,0x00,0x00,0x05,0x04,0x00,0x05,0x67,0x00,0x04,0x00,0x02,0x01,0x04,0x02,0x67,0x00, 0x09,0x00,0x0b,0x0a,0x09,0x0b,0x69,0x00,0x08,0x06,0x06,0x08,0x59,0x00,0x08,0x08,0x06,0x61,0x0d,0x01,0x06,0x08,0x06,0x51,0x18,0x17,0x00,0x00,0x36,0x33,0x31,0x30,0x2e,0x2b,0x20,0x1d,0x1b,0x1a,0x17,0x42,0x18,0x41,0x16,0x14,0x10,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x16,0x21,0x0e,0x06,0x19,0x2b,0x13,0x11,0x33,0x32,0x16,0x15,0x14, 0x06,0x07,0x17,0x23,0x27,0x23,0x15,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x01,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x2d,0xc6,0x38,0x44, 0x34,0x2b,0x67,0x50,0x64,0x54,0x85,0x19,0x1f,0x1e,0x19,0x86,0x01,0x15,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x01,0x8b,0x01,0x4f,0x3d,0x2f,0x28,0x32,0x06,0x83,0x81,0x81,0xb3,0x1b,0x15, 0x16,0x1c,0xfd,0x5c,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0x00,0x00,0x00,0x03,0xff,0xf6,0xff,0xf5,0x02,0x62,0x02,0xe4,0x00,0x14,0x00,0x27,0x00,0x35,0x00,0x53,0x40,0x50,0x00,0x03,0x06,0x02,0x06,0x03,0x02,0x80, 0x00,0x01,0x00,0x04,0x05,0x01,0x04,0x69,0x00,0x05,0x00,0x06,0x03,0x05,0x06,0x69,0x00,0x02,0x00,0x08,0x07,0x02,0x08,0x69,0x0a,0x01,0x07,0x00,0x00,0x07,0x59,0x0a,0x01,0x07,0x07,0x00,0x61,0x09,0x01,0x00,0x07,0x00,0x51,0x2a,0x28,0x01,0x00,0x31,0x2e,0x28,0x35,0x2a,0x35,0x27,0x25,0x21,0x1f,0x1e,0x1c,0x18,0x17,0x16,0x15,0x0b, 0x09,0x00,0x14,0x01,0x14,0x0b,0x06,0x16,0x2b,0x05,0x22,0x27,0x03,0x26,0x35,0x34,0x37,0x13,0x36,0x33,0x32,0x17,0x13,0x16,0x16,0x15,0x14,0x07,0x03,0x06,0x03,0x33,0x35,0x36,0x36,0x35,0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x17,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x01, 0x2c,0x23,0x23,0xd4,0x1c,0x1b,0xd5,0x23,0x23,0x23,0x23,0xd5,0x0e,0x0d,0x1c,0xd4,0x22,0x48,0x35,0x2c,0x33,0x3e,0x35,0x3f,0x3f,0x1c,0x21,0x21,0x1c,0x21,0x13,0x12,0x0e,0x11,0x11,0x0e,0x12,0x0d,0x11,0x11,0x0b,0x2a,0x01,0x03,0x23,0x23,0x24,0x22,0x01,0x0b,0x2b,0x2b,0xfe,0xf5,0x11,0x24,0x11,0x23,0x23,0xfe,0xfd,0x2a,0x01,0x20, 0x35,0x02,0x38,0x2d,0x32,0x3a,0x32,0x20,0x1d,0x1c,0x23,0xc5,0x13,0x0d,0x0e,0x12,0x12,0x0e,0x0d,0x13,0x00,0x02,0x00,0x25,0x00,0x00,0x02,0x2e,0x02,0xde,0x00,0x2b,0x00,0x37,0x00,0x62,0x40,0x5f,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00,0x02,0x0c, 0x01,0x00,0x08,0x02,0x00,0x69,0x00,0x08,0x09,0x01,0x07,0x06,0x08,0x07,0x67,0x0a,0x01,0x06,0x0b,0x0b,0x06,0x57,0x0a,0x01,0x06,0x06,0x0b,0x5f,0x0d,0x01,0x0b,0x06,0x0b,0x4f,0x2c,0x2c,0x01,0x00,0x2c,0x37,0x2c,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06,0x04,0x03,0x00,0x2b, 0x01,0x2a,0x0e,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x35,0x33,0x35,0x23,0x35,0x21,0x15,0x23,0x15,0x33,0x15,0xbc,0x40, 0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x1d,0x7d,0x7d,0x01,0x3c,0x7d,0x7d,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11, 0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0x3c,0xd7,0x3c,0x3c,0xd7,0x3c,0x00,0x00,0x00,0x00,0x03,0x00,0x25,0xff,0xfb,0x02,0x3f,0x02,0xde,0x00,0x2b,0x00,0x3b,0x00,0x47,0x00,0x61,0x40,0x5e,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00, 0x02,0x0a,0x01,0x00,0x07,0x02,0x00,0x69,0x00,0x07,0x00,0x09,0x08,0x07,0x09,0x69,0x0c,0x01,0x08,0x06,0x06,0x08,0x59,0x0c,0x01,0x08,0x08,0x06,0x61,0x0b,0x01,0x06,0x08,0x06,0x51,0x3d,0x3c,0x2d,0x2c,0x01,0x00,0x43,0x41,0x3c,0x47,0x3d,0x47,0x35,0x33,0x2c,0x3b,0x2d,0x3b,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06,0x04,0x03,0x00, 0x2b,0x01,0x2a,0x0d,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x22,0x26,0x26,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15, 0x14,0x06,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0xbb,0x32,0x4f,0x2e,0x2e,0x4f,0x32,0x32,0x4f,0x2e,0x2e,0x4f,0x32, 0x2d,0x3e,0x3e,0x2d,0x2d,0x3e,0x3e,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x74,0x2d,0x4e,0x31,0x32,0x4e,0x2d,0x2d,0x4e,0x32,0x31,0x4e,0x2d,0x3a,0x41,0x31,0x31,0x42,0x42,0x31,0x31,0x41,0x00,0x00, 0x00,0x03,0x00,0x25,0x00,0x00,0x02,0x3a,0x02,0xde,0x00,0x2b,0x00,0x36,0x00,0x3f,0x00,0x62,0x40,0x5f,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x0c,0x01,0x08,0x07,0x08,0x86,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00,0x02,0x0b,0x01,0x00,0x06,0x02,0x00,0x69,0x00,0x06,0x00,0x0a,0x09,0x06, 0x0a,0x67,0x00,0x09,0x07,0x07,0x09,0x57,0x00,0x09,0x09,0x07,0x5f,0x00,0x07,0x09,0x07,0x4f,0x2c,0x2c,0x01,0x00,0x3f,0x3d,0x39,0x37,0x2c,0x36,0x2c,0x36,0x35,0x33,0x2f,0x2d,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06,0x04,0x03,0x00,0x2b,0x01,0x2a,0x0d,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35, 0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x23,0x15,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c, 0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x2a,0xbf,0x38,0x44,0x44,0x38,0x7d,0x7e,0x19,0x1f,0x1e,0x19,0x7f,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a, 0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0x01,0x4f,0x3f,0x2f,0x2e,0x3e,0x75,0xaf,0x1d,0x15,0x16,0x1e,0x00,0x00,0x02,0x00,0x25,0x00,0x00,0x02,0x2b,0x02,0xde,0x00,0x2b,0x00,0x37,0x00,0x66,0x40,0x63,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x08,0x01,0x06,0x00,0x07,0x00,0x06,0x07,0x80,0x0d,0x0b, 0x02,0x09,0x0a,0x09,0x86,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00,0x02,0x0c,0x01,0x00,0x06,0x02,0x00,0x69,0x00,0x07,0x0a,0x0a,0x07,0x57,0x00,0x07,0x07,0x0a,0x5f,0x00,0x0a,0x07,0x0a,0x4f,0x2c,0x2c,0x01,0x00,0x2c,0x37,0x2c,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x2f,0x2e,0x2d,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06, 0x04,0x03,0x00,0x2b,0x01,0x2a,0x0e,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x11,0x33,0x15,0x33,0x35,0x33,0x11,0x23,0x35, 0x23,0x15,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x20,0x42,0xb2,0x42,0x42,0xb2,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11, 0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0x01,0x4f,0x84,0x84,0xfe,0xb1,0x8f,0x8f,0x00,0x00,0x00,0x02,0x00,0x25,0x00,0x00,0x02,0x3a,0x02,0xde,0x00,0x2b,0x00,0x43,0x00,0x62,0x40,0x5f,0x3f,0x39,0x33,0x2d,0x04,0x08,0x06,0x01,0x4c,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01, 0x02,0x7e,0x07,0x01,0x06,0x00,0x08,0x00,0x06,0x08,0x80,0x0b,0x09,0x02,0x08,0x08,0x84,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x0a,0x01,0x00,0x02,0x00,0x51,0x2c,0x2c,0x01,0x00,0x2c,0x43,0x2c,0x43,0x3b,0x3a,0x38,0x37,0x2f,0x2e,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06, 0x04,0x03,0x00,0x2b,0x01,0x2a,0x0c,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x37,0x27,0x33,0x17,0x16,0x16,0x17,0x36,0x36, 0x37,0x37,0x33,0x07,0x17,0x23,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x11,0x7e,0x7d,0x4e,0x42,0x0d,0x08,0x07,0x05,0x09,0x0c,0x40,0x4d,0x7d, 0x7d,0x4f,0x41,0x0d,0x0a,0x06,0x05,0x06,0x0d,0x42,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0xa9,0xa6,0x56,0x10,0x18,0x0e,0x0e,0x18,0x10,0x56,0xa8,0xa7,0x55,0x11,0x1a,0x0d,0x0d,0x19,0x11,0x56, 0x00,0x04,0x00,0x25,0x00,0x00,0x02,0x3a,0x02,0xde,0x00,0x2b,0x00,0x39,0x00,0x42,0x00,0x4b,0x00,0x6d,0x40,0x6a,0x33,0x01,0x0b,0x08,0x01,0x4c,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00,0x02,0x0c,0x01,0x00,0x06,0x02,0x00,0x69,0x00,0x06,0x00,0x09, 0x08,0x06,0x09,0x67,0x00,0x08,0x00,0x0b,0x0a,0x08,0x0b,0x67,0x00,0x0a,0x07,0x07,0x0a,0x57,0x00,0x0a,0x0a,0x07,0x5f,0x0d,0x01,0x07,0x0a,0x07,0x4f,0x2c,0x2c,0x01,0x00,0x4b,0x49,0x45,0x43,0x42,0x40,0x3c,0x3a,0x2c,0x39,0x2c,0x38,0x2f,0x2d,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06,0x04,0x03,0x00,0x2b,0x01,0x2a,0x0e,0x06,0x16, 0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x11,0x33,0x32,0x16,0x15,0x14,0x07,0x16,0x16,0x15,0x14,0x06,0x23,0x27,0x33,0x32,0x36,0x35, 0x34,0x26,0x23,0x23,0x15,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x23,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x20,0xc2,0x33,0x3f,0x37,0x21,0x27,0x40,0x34,0x8f,0x81,0x14,0x1a,0x19,0x14, 0x82,0x8c,0x17,0x1d,0x1d,0x17,0x8c,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0x01,0x4f,0x2e,0x26,0x39,0x14,0x08,0x2b,0x1e,0x29,0x34,0xbf,0x17,0x13,0x13,0x19,0xdb,0x19,0x13,0x13,0x17,0x00,0x00, 0x00,0x02,0x00,0x25,0x00,0x00,0x02,0x2b,0x02,0xde,0x00,0x2b,0x00,0x3d,0x00,0x60,0x40,0x5d,0x38,0x2f,0x02,0x08,0x06,0x01,0x4c,0x00,0x04,0x05,0x01,0x05,0x04,0x01,0x80,0x00,0x01,0x02,0x05,0x01,0x02,0x7e,0x07,0x01,0x06,0x00,0x08,0x00,0x06,0x08,0x80,0x0b,0x09,0x02,0x08,0x08,0x84,0x00,0x03,0x00,0x05,0x04,0x03,0x05,0x69,0x00, 0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x0a,0x01,0x00,0x02,0x00,0x51,0x2c,0x2c,0x01,0x00,0x2c,0x3d,0x2c,0x3d,0x37,0x36,0x35,0x34,0x2e,0x2d,0x1f,0x1c,0x1a,0x19,0x17,0x14,0x09,0x06,0x04,0x03,0x00,0x2b,0x01,0x2a,0x0c,0x06,0x16,0x2b,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27, 0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0x13,0x11,0x33,0x13,0x2e,0x02,0x35,0x35,0x33,0x11,0x23,0x03,0x1e,0x02,0x15,0x15,0xbc,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d, 0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16,0x58,0x33,0x3b,0x4e,0x44,0x20,0x50,0xb2,0x05,0x06,0x02,0x41,0x50,0xb2,0x06,0x05,0x02,0x01,0x87,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0xfe,0x79,0x01,0x4f, 0xfe,0xf7,0x1e,0x26,0x30,0x2c,0x69,0xfe,0xb1,0x01,0x09,0x1c,0x26,0x31,0x2d,0x69,0x00,0x01,0x00,0x5a,0x00,0x00,0x02,0x12,0x02,0xe4,0x00,0x1c,0x00,0x43,0x40,0x40,0x16,0x15,0x10,0x03,0x04,0x03,0x01,0x4c,0x00,0x01,0x02,0x03,0x02,0x01,0x03,0x80,0x00,0x03,0x04,0x02,0x03,0x04,0x7e,0x00,0x02,0x02,0x00,0x61,0x06,0x01,0x00,0x00, 0x3e,0x4d,0x00,0x04,0x04,0x05,0x60,0x00,0x05,0x05,0x39,0x05,0x4e,0x01,0x00,0x14,0x13,0x12,0x11,0x0f,0x0d,0x08,0x06,0x04,0x03,0x00,0x1c,0x01,0x1c,0x07,0x09,0x16,0x2b,0x01,0x32,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x33,0x33,0x15,0x07,0x21,0x15,0x21,0x35,0x37,0x26,0x26,0x35,0x35,0x34,0x36,0x01,0x37, 0x65,0x76,0x5a,0x46,0x3c,0x3c,0x46,0x46,0x3c,0x4f,0xb3,0x01,0x2c,0xfe,0x6e,0xb0,0x5a,0x68,0x77,0x02,0xe4,0x71,0x61,0x3c,0x46,0x46,0x3c,0x32,0x3c,0x46,0x4e,0xbe,0x52,0x54,0xbb,0x07,0x6f,0x5b,0x32,0x61,0x71,0x00,0x00,0x00,0x00,0x01,0x00,0x49,0xff,0xf6,0x02,0x0c,0x02,0xda,0x00,0x18,0x00,0x34,0x40,0x31,0x01,0x01,0x01,0x03, 0x01,0x4c,0x00,0x01,0x03,0x00,0x03,0x01,0x00,0x80,0x00,0x03,0x03,0x04,0x5f,0x05,0x01,0x04,0x04,0x38,0x4d,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x02,0x3f,0x02,0x4e,0x00,0x00,0x00,0x18,0x00,0x18,0x16,0x22,0x12,0x27,0x06,0x09,0x1a,0x2b,0x01,0x15,0x03,0x06,0x06,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x06,0x06,0x23,0x22,0x26, 0x35,0x34,0x36,0x37,0x37,0x21,0x35,0x02,0x02,0xf3,0x34,0x2d,0x45,0x3b,0x3d,0x47,0x5a,0x03,0x78,0x63,0x65,0x77,0x39,0x45,0xc5,0xfe,0xb4,0x02,0xda,0x53,0xfe,0xfc,0x37,0x59,0x2a,0x3c,0x47,0x49,0x3e,0x63,0x74,0x73,0x61,0x35,0x73,0x48,0xce,0x52,0x00,0x02,0x00,0x2d,0xff,0xfc,0x02,0x2f,0x02,0xda,0x00,0x11,0x00,0x3d,0x00,0x59, 0x40,0x56,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x08,0x09,0x05,0x09,0x08,0x05,0x80,0x00,0x05,0x06,0x09,0x05,0x06,0x7e,0x00,0x02,0x0a,0x01,0x00,0x07,0x02,0x00,0x69,0x00,0x07,0x00,0x09,0x08,0x07,0x09,0x69,0x00,0x06,0x04,0x04,0x06,0x59,0x00,0x06,0x06,0x04,0x61,0x0b,0x01,0x04,0x06,0x04,0x51,0x13,0x12,0x01,0x00,0x31,0x2e,0x2c, 0x2b,0x29,0x26,0x1b,0x18,0x16,0x15,0x12,0x3d,0x13,0x3c,0x0e,0x0d,0x0a,0x08,0x05,0x04,0x00,0x11,0x01,0x11,0x0c,0x06,0x16,0x2b,0x13,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x16,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x13,0x22,0x26,0x27,0x33,0x16,0x16,0x33,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36, 0x33,0x33,0x32,0x16,0x17,0x23,0x26,0x26,0x23,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x23,0xc8,0x45,0x56,0x42,0x31,0x28,0x28,0x31,0x42,0x56,0x77,0x40,0x52,0x05,0x42,0x03,0x2e,0x24,0x19,0x25,0x2b,0x1c,0x19,0x58,0x31,0x39,0x4a,0x3f,0x19,0x3d,0x4e,0x07,0x42,0x04,0x2b,0x21,0x19,0x21,0x26,0x1b,0x16, 0x58,0x33,0x3b,0x4e,0x44,0x01,0x81,0x53,0x47,0xbf,0xbf,0x2c,0x32,0x32,0x2c,0xbf,0xbf,0x47,0x53,0xfe,0x7b,0x3a,0x31,0x16,0x1b,0x18,0x14,0x10,0x16,0x03,0x0a,0x05,0x32,0x25,0x2d,0x35,0x33,0x2c,0x11,0x14,0x13,0x11,0x0f,0x14,0x02,0x0a,0x06,0x34,0x26,0x31,0x39,0x00,0x00,0x02,0x00,0x0f,0x00,0x00,0x02,0x49,0x02,0xda,0x00,0x0c, 0x00,0x14,0x00,0x3a,0x40,0x37,0x03,0x01,0x01,0x00,0x01,0x4c,0x02,0x01,0x00,0x01,0x00,0x85,0x00,0x01,0x04,0x01,0x85,0x07,0x01,0x06,0x03,0x06,0x86,0x00,0x04,0x03,0x03,0x04,0x57,0x00,0x04,0x04,0x03,0x5f,0x05,0x01,0x03,0x04,0x03,0x4f,0x0d,0x0d,0x0d,0x14,0x0d,0x14,0x11,0x11,0x12,0x11,0x11,0x17,0x08,0x06,0x1c,0x2b,0x13,0x16, 0x16,0x17,0x36,0x36,0x37,0x37,0x33,0x03,0x23,0x03,0x33,0x01,0x11,0x23,0x35,0x21,0x15,0x23,0x11,0xad,0x08,0x12,0x02,0x02,0x10,0x07,0x57,0x48,0x94,0x4a,0x94,0x45,0x01,0x1b,0x98,0x01,0x72,0x98,0x02,0x0c,0x13,0x29,0x0e,0x0e,0x29,0x13,0xce,0xfe,0xb1,0x01,0x4f,0xfd,0x26,0x01,0x13,0x3c,0x3c,0xfe,0xed,0x00,0x00,0x02,0x00,0x37, 0x00,0x00,0x02,0x53,0x02,0xda,0x00,0x1a,0x00,0x23,0x00,0x42,0x40,0x3f,0x06,0x01,0x04,0x03,0x01,0x4c,0x00,0x03,0x06,0x01,0x04,0x05,0x03,0x04,0x67,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x08,0x01,0x05,0x05,0x00,0x5f,0x07,0x01,0x00,0x00,0x39,0x00,0x4e,0x1c,0x1b,0x01,0x00,0x1f,0x1d,0x1b,0x23,0x1c,0x23,0x19,0x18, 0x17,0x15,0x11,0x0f,0x0e,0x0c,0x00,0x1a,0x01,0x1a,0x09,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x23,0x11,0x27,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x17,0x67,0x79,0x51,0x40,0x39,0x47,0x6f,0x5e,0xad,0xad,0x35,0x3e, 0x3f,0x36,0x01,0x3c,0x73,0xca,0x70,0x70,0x3c,0x47,0x47,0x70,0x5f,0x45,0x61,0x08,0x03,0x0b,0x59,0x3a,0x56,0x66,0x52,0x3d,0x35,0x34,0x3e,0x50,0xfe,0xac,0x52,0x01,0x02,0x46,0x3b,0x3b,0x46,0x00,0x00,0x00,0xff,0xff,0x00,0xb4,0xff,0x06,0x01,0xa4,0xff,0xce,0x00,0x07,0x06,0x79,0x02,0x58,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x8c, 0xff,0x2e,0x01,0xcc,0xff,0xb0,0x00,0x19,0x00,0x6d,0xb1,0x06,0x64,0x44,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x1b,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x02,0x06,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x29,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04, 0x02,0x00,0x80,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x06,0x01,0x00,0x04,0x00,0x52,0x59,0x40,0x13,0x01,0x00,0x16,0x15,0x13,0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x07,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x05,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23, 0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x01,0x72,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x32,0x28,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x31,0xd2,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x00,0x00,0x01,0xfe,0x13,0xff,0x4c,0x01,0xf9,0x03,0x84,0x00,0x36, 0x00,0x41,0x40,0x3e,0x36,0x02,0x02,0x01,0x00,0x0c,0x06,0x05,0x03,0x03,0x01,0x08,0x01,0x04,0x03,0x22,0x1f,0x07,0x03,0x02,0x04,0x04,0x4c,0x00,0x03,0x01,0x04,0x01,0x03,0x04,0x80,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x69,0x00,0x04,0x04,0x02,0x5f,0x00,0x02,0x02,0x3d,0x02,0x4e,0x2a,0x28,0x26,0x25,0x21,0x20,0x13,0x11,0x10,0x05, 0x09,0x17,0x2b,0x01,0x33,0x15,0x16,0x17,0x01,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x23,0x35,0x26,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0xfe,0xd0,0x5a,0x40,0x41,0x02, 0x4e,0xfe,0x61,0x01,0x27,0x13,0x20,0x08,0x09,0x21,0x11,0xfe,0x08,0x4c,0x49,0x35,0x42,0x2b,0x27,0x72,0x47,0x53,0x5f,0x52,0x5a,0x57,0x66,0x5a,0x4e,0x40,0x3e,0x4a,0x31,0x2a,0x6f,0x45,0x4f,0x5e,0x4d,0x03,0x84,0xa4,0x0b,0x23,0xfe,0xca,0x64,0xd7,0x5a,0x97,0x0a,0x0d,0x02,0x02,0x0a,0x09,0x01,0x0a,0x2a,0x3f,0x32,0x28,0x39,0x0b, 0x20,0x14,0x71,0x4d,0x52,0x6d,0x0c,0xae,0xad,0x0b,0x6c,0x58,0x3d,0x45,0x47,0x38,0x2d,0x43,0x0c,0x1f,0x14,0x67,0x46,0x4e,0x68,0x0b,0x00,0x00,0x00,0x01,0xfe,0x07,0xff,0x4c,0x02,0x01,0x03,0x84,0x00,0x36,0x00,0x48,0x40,0x45,0x21,0x1e,0x02,0x04,0x02,0x06,0x01,0x03,0x04,0x0b,0x07,0x05,0x04,0x04,0x01,0x03,0x35,0x01,0x00,0x01, 0x04,0x4c,0x00,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x00,0x02,0x00,0x04,0x03,0x02,0x04,0x69,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x00,0x42,0x4d,0x06,0x01,0x05,0x05,0x3d,0x05,0x4e,0x00,0x00,0x00,0x36,0x00,0x36,0x22,0x14,0x1d,0x2e,0x11,0x07,0x09,0x1b,0x2b,0x17,0x35,0x26,0x27,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16, 0x17,0x05,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0xf6,0x6d,0x90,0xfe,0x0e,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x21,0x12,0x01,0x9b,0x8e,0x65,0x48,0x54,0x31,0x2a, 0x6f,0x45,0x4f,0x5e,0x4d,0x5a,0x47,0x56,0x5a,0x44,0x35,0x35,0x42,0x2b,0x27,0x72,0x47,0x53,0x5e,0x53,0xb4,0xab,0x06,0x3f,0xdc,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x03,0x0a,0x08,0xb3,0x3e,0x45,0x3a,0x2d,0x43,0x0c,0x1f,0x14,0x67,0x46,0x4e,0x68,0x0b,0xa2,0xa5,0x0f,0x65,0x48,0x32,0x3f,0x3f,0x32,0x28,0x39,0x0b,0x20,0x14,0x71, 0x4d,0x50,0x6a,0x0f,0xb0,0x00,0x00,0x00,0x00,0x01,0xfb,0xc8,0xff,0x4c,0x01,0xe0,0x03,0x84,0x00,0x40,0x00,0x42,0x40,0x3f,0x21,0x1e,0x02,0x03,0x02,0x2b,0x27,0x25,0x24,0x0b,0x07,0x06,0x05,0x04,0x09,0x01,0x03,0x3f,0x26,0x02,0x00,0x01,0x03,0x4c,0x00,0x02,0x00,0x03,0x01,0x02,0x03,0x69,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x00, 0x42,0x4d,0x05,0x01,0x04,0x04,0x3d,0x04,0x4e,0x00,0x00,0x00,0x40,0x00,0x40,0x33,0x31,0x1d,0x2e,0x11,0x06,0x09,0x19,0x2b,0x05,0x35,0x26,0x27,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x16,0x33,0x32,0x36,0x35,0x34,0x26,0x27,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x01,0x15,0x05,0x35, 0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0x26,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0xfe,0xb7,0x6d,0x90,0xfe,0x0e,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x21,0x12,0x01,0x9b,0x8e,0x65,0x4d,0x4f,0x31,0x2a,0x6f,0x45,0x4f,0x5e,0x4d,0x5a,0x3f,0x42,0x02,0x4e,0xfe,0x61,0x01,0x27,0x13, 0x20,0x08,0x09,0x21,0x11,0xfe,0x08,0x26,0x4c,0x23,0x35,0x42,0x2b,0x27,0x72,0x47,0x53,0x5c,0x55,0xb4,0xab,0x06,0x3f,0xdc,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x03,0x0a,0x08,0xb3,0x3e,0x47,0x38,0x2d,0x43,0x0c,0x1f,0x14,0x67,0x46,0x4e,0x68,0x0b,0xa2,0xa5,0x0a,0x23,0xfe,0xca,0x64,0xd7,0x5a,0x97,0x0a,0x0d,0x02,0x02,0x0a,0x09, 0x01,0x0a,0x14,0x16,0x3f,0x32,0x28,0x39,0x0b,0x20,0x14,0x71,0x4d,0x4f,0x6b,0x0f,0xb0,0x00,0x00,0x00,0x00,0x03,0xfd,0xda,0x00,0x00,0x02,0x62,0x02,0xda,0x00,0x32,0x00,0x3b,0x00,0x44,0x00,0x5c,0x40,0x59,0x0e,0x01,0x01,0x05,0x01,0x4c,0x08,0x01,0x05,0x0d,0x0b,0x09,0x03,0x01,0x0a,0x05,0x01,0x67,0x07,0x01,0x04,0x04,0x03,0x5f, 0x06,0x01,0x03,0x03,0x38,0x4d,0x10,0x0c,0x0f,0x03,0x0a,0x0a,0x00,0x5f,0x02,0x0e,0x02,0x00,0x00,0x39,0x00,0x4e,0x3d,0x3c,0x34,0x33,0x01,0x00,0x40,0x3e,0x3c,0x44,0x3d,0x44,0x37,0x35,0x33,0x3b,0x34,0x3b,0x31,0x30,0x2f,0x2d,0x29,0x27,0x26,0x24,0x1f,0x1d,0x19,0x17,0x16,0x14,0x09,0x07,0x06,0x05,0x00,0x32,0x01,0x32,0x11,0x09, 0x16,0x2b,0x21,0x22,0x26,0x35,0x34,0x37,0x23,0x11,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x23,0x11,0x25,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x21,0x33, 0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x12,0x67,0x79,0x40,0xdc,0xdc,0x67,0x79,0x51,0x40,0x39,0x47,0x6f,0x5e,0xaa,0xaa,0x35,0x3e,0x41,0x34,0x01,0xcd,0x20,0x24,0x6f,0x5e,0xb4,0xb4,0x35,0x3e,0x41,0x34,0x01,0x50,0x74,0xfc,0xcb,0x83,0x83,0x3c,0x47,0x47,0x02,0x94,0x83,0x83,0x3c,0x47,0x47,0x6e,0x61,0x54,0x31,0xfe,0xac,0x6e, 0x61,0x45,0x61,0x08,0x03,0x0b,0x59,0x3a,0x59,0x63,0x50,0x3b,0x38,0x36,0x3d,0x15,0x3e,0x27,0x59,0x63,0x50,0x3b,0x38,0x36,0x3d,0x50,0xfe,0xac,0x50,0x01,0x04,0x44,0x3e,0x3e,0x44,0x01,0x04,0x44,0x3e,0x3e,0x44,0x00,0x00,0x00,0x00,0x04,0xfb,0x82,0x00,0x00,0x02,0x62,0x02,0xda,0x00,0x4a,0x00,0x53,0x00,0x5c,0x00,0x65,0x00,0x76, 0x40,0x73,0x16,0x01,0x01,0x07,0x01,0x4c,0x0d,0x0a,0x02,0x07,0x14,0x12,0x10,0x0e,0x03,0x05,0x01,0x0f,0x07,0x01,0x67,0x0c,0x09,0x02,0x06,0x06,0x05,0x5f,0x0b,0x08,0x02,0x05,0x05,0x38,0x4d,0x18,0x13,0x17,0x11,0x16,0x05,0x0f,0x0f,0x00,0x5f,0x04,0x02,0x15,0x03,0x00,0x00,0x39,0x00,0x4e,0x5e,0x5d,0x55,0x54,0x4c,0x4b,0x01,0x00, 0x61,0x5f,0x5d,0x65,0x5e,0x65,0x58,0x56,0x54,0x5c,0x55,0x5c,0x4f,0x4d,0x4b,0x53,0x4c,0x53,0x49,0x48,0x47,0x45,0x41,0x3f,0x3e,0x3c,0x37,0x35,0x31,0x2f,0x2e,0x2c,0x27,0x25,0x21,0x1f,0x1e,0x1c,0x11,0x0f,0x0e,0x0d,0x09,0x07,0x06,0x05,0x00,0x4a,0x01,0x4a,0x19,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x34,0x37,0x23,0x11,0x23,0x22, 0x26,0x35,0x34,0x37,0x23,0x11,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x23, 0x11,0x25,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x21,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x21,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x01,0x12,0x67,0x79,0x40,0xdc,0xdc,0x67,0x79,0x40,0xdc,0xdc,0x67,0x79,0x51,0x40,0x39,0x47,0x6f,0x5e,0xaa,0xaa,0x35,0x3e,0x41,0x34,0x01,0xcd,0x20,0x24,0x6f,0x5e,0xb4,0xb4,0x35,0x3e, 0x41,0x34,0x01,0xcd,0x20,0x24,0x6f,0x5e,0xb4,0xb4,0x35,0x3e,0x41,0x34,0x01,0x50,0x74,0xfa,0x73,0x83,0x83,0x3c,0x47,0x47,0x02,0x94,0x83,0x83,0x3c,0x47,0x47,0x02,0x94,0x83,0x83,0x3c,0x47,0x47,0x6e,0x61,0x54,0x31,0xfe,0xac,0x6e,0x61,0x54,0x31,0xfe,0xac,0x6e,0x61,0x45,0x61,0x08,0x03,0x0b,0x59,0x3a,0x59,0x63,0x50,0x3b,0x38, 0x36,0x3d,0x15,0x3e,0x27,0x59,0x63,0x50,0x3b,0x38,0x36,0x3d,0x15,0x3e,0x27,0x59,0x63,0x50,0x3b,0x38,0x36,0x3d,0x50,0xfe,0xac,0x50,0x01,0x04,0x44,0x3e,0x3e,0x44,0x01,0x04,0x44,0x3e,0x3e,0x44,0x01,0x04,0x44,0x3e,0x3e,0x44,0x00,0x03,0xfd,0xdf,0x00,0x00,0x02,0x08,0x02,0xda,0x00,0x1a,0x00,0x23,0x00,0x27,0x00,0x53,0x40,0x50, 0x06,0x01,0x04,0x03,0x01,0x4c,0x00,0x03,0x06,0x01,0x04,0x07,0x03,0x04,0x67,0x00,0x07,0x0b,0x01,0x08,0x05,0x07,0x08,0x67,0x00,0x02,0x02,0x01,0x5f,0x00,0x01,0x01,0x38,0x4d,0x0a,0x01,0x05,0x05,0x00,0x5f,0x09,0x01,0x00,0x00,0x39,0x00,0x4e,0x24,0x24,0x1c,0x1b,0x01,0x00,0x24,0x27,0x24,0x27,0x26,0x25,0x1f,0x1d,0x1b,0x23,0x1c, 0x23,0x19,0x18,0x17,0x15,0x11,0x0f,0x0e,0x0c,0x00,0x1a,0x01,0x1a,0x0c,0x09,0x16,0x2b,0x21,0x22,0x26,0x35,0x34,0x36,0x37,0x35,0x26,0x26,0x35,0x34,0x36,0x33,0x33,0x15,0x23,0x22,0x06,0x15,0x14,0x16,0x33,0x21,0x15,0x21,0x11,0x27,0x33,0x11,0x23,0x22,0x06,0x15,0x14,0x16,0x25,0x35,0x21,0x15,0xfe,0xbf,0x67,0x79,0x51,0x40,0x39, 0x47,0x6f,0x5e,0xad,0xad,0x35,0x3e,0x3f,0x36,0x03,0x49,0xfd,0x80,0xca,0x70,0x70,0x3c,0x47,0x47,0x01,0xab,0x01,0xdb,0x70,0x5f,0x45,0x61,0x08,0x03,0x0b,0x59,0x3a,0x56,0x66,0x52,0x3d,0x35,0x34,0x3e,0x50,0xfe,0xac,0x52,0x01,0x02,0x46,0x3b,0x3b,0x46,0x12,0x50,0x50,0x00,0x02,0xfd,0xd5,0xff,0x9c,0x02,0x1c,0x02,0xe4,0x00,0x27, 0x00,0x31,0x00,0x7a,0xb5,0x19,0x01,0x07,0x03,0x01,0x4c,0x4b,0xb0,0x21,0x50,0x58,0x40,0x26,0x09,0x01,0x06,0x00,0x02,0x05,0x06,0x02,0x69,0x00,0x05,0x08,0x01,0x00,0x05,0x00,0x63,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x4d,0x00,0x07,0x07,0x03,0x61,0x00,0x03,0x03,0x3b,0x07,0x4e,0x1b,0x40,0x24,0x00,0x03,0x00,0x07,0x06, 0x03,0x07,0x69,0x09,0x01,0x06,0x00,0x02,0x05,0x06,0x02,0x69,0x00,0x05,0x08,0x01,0x00,0x05,0x00,0x63,0x00,0x04,0x04,0x01,0x61,0x00,0x01,0x01,0x3e,0x04,0x4e,0x59,0x40,0x1b,0x29,0x28,0x01,0x00,0x2e,0x2c,0x28,0x31,0x29,0x31,0x26,0x24,0x1f,0x1d,0x17,0x15,0x10,0x0e,0x09,0x07,0x00,0x27,0x01,0x27,0x0a,0x09,0x16,0x2b,0x05,0x22, 0x26,0x26,0x35,0x11,0x34,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x21,0x15,0x01,0x32,0x35,0x35,0x34,0x23,0x22,0x15,0x15,0x14,0xfe,0xed,0x55,0x7e,0x45,0x90,0x7e,0x75,0x80,0x56,0x4a,0x49,0x57,0x46,0x40,0x29, 0x36,0x09,0x02,0x56,0x4f,0x5a,0x64,0x6b,0x5d,0x03,0x2f,0xfd,0x1c,0x50,0x50,0x50,0x64,0x47,0x83,0x58,0x01,0x04,0x87,0x9b,0x7d,0x73,0xe2,0x4e,0x5b,0x56,0x49,0x74,0x4a,0x51,0x20,0x1c,0x23,0x4d,0x53,0x74,0x68,0xfe,0xfc,0x64,0x73,0x4b,0x01,0x10,0x5c,0x75,0x5b,0x5c,0x74,0x5c,0x00,0x00,0x00,0x04,0xfd,0xc6,0xff,0xf7,0x02,0x62, 0x02,0xe4,0x00,0x24,0x00,0x45,0x00,0x51,0x00,0x5d,0x00,0xcc,0x40,0x0b,0x55,0x49,0x42,0x21,0x1e,0x1b,0x06,0x0d,0x0e,0x01,0x4c,0x4b,0xb0,0x1a,0x50,0x58,0x40,0x41,0x0a,0x01,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x08,0x01,0x01,0x10,0x01,0x0e,0x0d,0x01,0x0e,0x69,0x0b,0x01,0x04,0x04,0x02,0x61,0x09,0x01,0x02,0x02,0x3e,0x4d,0x00, 0x05,0x05,0x00,0x61,0x0c,0x12,0x07,0x06,0x11,0x05,0x00,0x00,0x3f,0x4d,0x14,0x0f,0x13,0x03,0x0d,0x0d,0x00,0x61,0x0c,0x12,0x07,0x06,0x11,0x05,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x3b,0x0a,0x01,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x08,0x01,0x01,0x10,0x01,0x0e,0x0d,0x01,0x0e,0x69,0x0b,0x01,0x04,0x04,0x02,0x61,0x09,0x01,0x02, 0x02,0x3e,0x4d,0x00,0x05,0x05,0x06,0x5f,0x0c,0x01,0x06,0x06,0x39,0x4d,0x14,0x0f,0x13,0x03,0x0d,0x0d,0x00,0x61,0x12,0x07,0x11,0x03,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x35,0x53,0x52,0x47,0x46,0x26,0x25,0x01,0x00,0x58,0x56,0x52,0x5d,0x53,0x5d,0x4c,0x4a,0x46,0x51,0x47,0x51,0x41,0x40,0x3b,0x39,0x37,0x36,0x33,0x31,0x2c,0x2b, 0x25,0x45,0x26,0x45,0x20,0x1f,0x1d,0x1c,0x16,0x14,0x12,0x11,0x0e,0x0c,0x07,0x06,0x00,0x24,0x01,0x24,0x15,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x37,0x33,0x07,0x17,0x23,0x27,0x07,0x06,0x06,0x21,0x22,0x26, 0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x01,0x23,0x27,0x07,0x06,0x06,0x25,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x21,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xd2,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37, 0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0xc3,0x5b,0x64,0x8f,0x91,0x63,0x61,0x2b,0x22,0x53,0xfd,0x86,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0x01,0x84,0x63,0x61,0x2b,0x22,0x53,0x02,0x28,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b,0xfd,0xe3,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b, 0x09,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55,0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfc,0x72,0xb0,0xbd,0x80,0x36,0x2a,0x29,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55,0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfe,0x09,0x80,0x36,0x2a,0x29,0x51,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b, 0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b,0x00,0x06,0xfb,0x73,0xff,0xf7,0x02,0x5d,0x02,0xe4,0x00,0x24,0x00,0x45,0x00,0x66,0x00,0x72,0x00,0x7e,0x00,0x8a,0x00,0xfd,0x40,0x0d,0x82,0x76,0x6a,0x63,0x42,0x21,0x1e,0x1b,0x08,0x13,0x14,0x01,0x4c,0x4b,0xb0,0x1a,0x50,0x58,0x40,0x4e,0x10,0x0a,0x02,0x03,0x04,0x01,0x04,0x03,0x01,0x80, 0x0e,0x08,0x02,0x01,0x18,0x16,0x02,0x14,0x13,0x01,0x14,0x69,0x11,0x0b,0x02,0x04,0x04,0x02,0x61,0x0f,0x09,0x02,0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x00,0x61,0x12,0x1b,0x0d,0x0c,0x1a,0x07,0x06,0x19,0x08,0x00,0x00,0x3f,0x4d,0x1e,0x17,0x1d,0x15,0x1c,0x05,0x13,0x13,0x00,0x61,0x12,0x1b,0x0d,0x0c,0x1a,0x07,0x06,0x19,0x08,0x00, 0x00,0x3f,0x00,0x4e,0x1b,0x40,0x45,0x10,0x0a,0x02,0x03,0x04,0x01,0x04,0x03,0x01,0x80,0x0e,0x08,0x02,0x01,0x18,0x16,0x02,0x14,0x13,0x01,0x14,0x69,0x11,0x0b,0x02,0x04,0x04,0x02,0x61,0x0f,0x09,0x02,0x02,0x02,0x3e,0x4d,0x00,0x05,0x05,0x06,0x5f,0x12,0x0c,0x02,0x06,0x06,0x39,0x4d,0x1e,0x17,0x1d,0x15,0x1c,0x05,0x13,0x13,0x00, 0x61,0x1b,0x0d,0x1a,0x07,0x19,0x05,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x4d,0x80,0x7f,0x74,0x73,0x68,0x67,0x47,0x46,0x26,0x25,0x01,0x00,0x85,0x83,0x7f,0x8a,0x80,0x8a,0x79,0x77,0x73,0x7e,0x74,0x7e,0x6d,0x6b,0x67,0x72,0x68,0x72,0x62,0x61,0x5c,0x5a,0x58,0x57,0x54,0x52,0x4d,0x4c,0x46,0x66,0x47,0x66,0x41,0x40,0x3b,0x39,0x37, 0x36,0x33,0x31,0x2c,0x2b,0x25,0x45,0x26,0x45,0x20,0x1f,0x1d,0x1c,0x16,0x14,0x12,0x11,0x0e,0x0c,0x07,0x06,0x00,0x24,0x01,0x24,0x1f,0x09,0x16,0x2b,0x17,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x37,0x33,0x07,0x17,0x23,0x27,0x07, 0x06,0x06,0x21,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x01,0x23,0x27,0x07,0x06,0x06,0x21,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x01,0x23, 0x27,0x07,0x06,0x06,0x25,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x21,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x21,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0xcd,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0xc3,0x5b,0x64,0x8f,0x91,0x63, 0x61,0x2b,0x22,0x53,0xfb,0x38,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0x01,0x84,0x63,0x61,0x2b,0x22,0x53,0x02,0x22,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0x01,0x84,0x63,0x61,0x2b,0x22,0x53,0xfd,0x8c,0x39,0x28,0x34,0x7d,0x1e,0x2f, 0x37,0x3b,0x02,0x7f,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b,0x02,0x7f,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b,0x09,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55,0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfc,0x72,0xb0,0xbd,0x80,0x36,0x2a,0x29,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55, 0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfe,0x09,0x80,0x36,0x2a,0x29,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55,0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfe,0x09,0x80,0x36,0x2a,0x29,0x51,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b, 0x00,0x03,0xfd,0xd5,0xff,0xf7,0x02,0x1c,0x02,0xe4,0x00,0x26,0x00,0x32,0x00,0x36,0x00,0xbc,0x40,0x0f,0x1b,0x01,0x0a,0x09,0x2a,0x20,0x02,0x0b,0x0a,0x23,0x01,0x08,0x0b,0x03,0x4c,0x4b,0xb0,0x1a,0x50,0x58,0x40,0x39,0x00,0x03,0x04,0x05,0x04,0x03,0x05,0x80,0x00,0x05,0x00,0x06,0x09,0x05,0x06,0x67,0x00,0x01,0x00,0x09,0x0a,0x01, 0x09,0x69,0x00,0x0a,0x0e,0x01,0x0b,0x08,0x0a,0x0b,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x0d,0x01,0x08,0x08,0x00,0x61,0x07,0x0c,0x02,0x00,0x00,0x3f,0x00,0x4e,0x1b,0x40,0x3d,0x00,0x03,0x04,0x05,0x04,0x03,0x05,0x80,0x00,0x05,0x00,0x06,0x09,0x05,0x06,0x67,0x00,0x01,0x00,0x09,0x0a,0x01,0x09,0x69,0x00,0x0a, 0x0e,0x01,0x0b,0x08,0x0a,0x0b,0x67,0x00,0x04,0x04,0x02,0x61,0x00,0x02,0x02,0x3e,0x4d,0x00,0x07,0x07,0x39,0x4d,0x0d,0x01,0x08,0x08,0x00,0x61,0x0c,0x01,0x00,0x00,0x3f,0x00,0x4e,0x59,0x40,0x27,0x33,0x33,0x28,0x27,0x01,0x00,0x33,0x36,0x33,0x36,0x35,0x34,0x2d,0x2b,0x27,0x32,0x28,0x32,0x22,0x21,0x1f,0x1e,0x1d,0x1c,0x16,0x14, 0x12,0x11,0x0e,0x0c,0x07,0x06,0x00,0x26,0x01,0x26,0x0f,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x35,0x34,0x36,0x37,0x27,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x16,0x15,0x23,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x17,0x17,0x37,0x21,0x15,0x21,0x07,0x17,0x23,0x27,0x07,0x06,0x06,0x27,0x32,0x37,0x37,0x27,0x23,0x22,0x06,0x15,0x15,0x14, 0x16,0x25,0x35,0x21,0x15,0xfe,0x93,0x58,0x66,0x5a,0x4c,0x1c,0x36,0x60,0x4d,0x37,0x53,0x2f,0x58,0x35,0x2c,0x25,0x2f,0x1d,0xc3,0xbf,0x01,0xfb,0xfe,0x2a,0xb4,0x91,0x63,0x61,0x2b,0x22,0x53,0x26,0x39,0x28,0x34,0x7d,0x1e,0x2f,0x37,0x3b,0x01,0xd9,0x01,0xdb,0x09,0x67,0x58,0x39,0x50,0x60,0x04,0x24,0x47,0x37,0x47,0x58,0x30,0x55, 0x39,0x32,0x3f,0x2e,0x26,0x27,0x25,0xfc,0xef,0x50,0xdd,0xbd,0x80,0x36,0x2a,0x29,0x51,0x33,0x42,0xa0,0x3b,0x33,0x39,0x33,0x3b,0x62,0x50,0x50,0x00,0x01,0xfe,0xa7,0xff,0xab,0x01,0xa4,0x02,0xee,0x00,0x07,0x00,0x47,0x4b,0xb0,0x18,0x50,0x58,0x40,0x14,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x04,0x01,0x03,0x03,0x00,0x5f,0x00, 0x00,0x00,0x38,0x03,0x4e,0x1b,0x40,0x19,0x00,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x59,0x40,0x0c,0x00,0x00,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x05,0x09,0x19,0x2b,0x05,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0xfe,0xa7,0x5a,0x02,0xa3,0xfd,0x5d, 0x55,0x03,0x43,0xfe,0x84,0x50,0xfe,0x89,0x00,0x01,0xfb,0xd2,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x12,0x00,0x33,0x40,0x30,0x0a,0x01,0x04,0x01,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x68,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x12,0x00,0x12, 0x23,0x12,0x14,0x11,0x11,0x07,0x09,0x1b,0x2b,0x25,0x11,0x33,0x15,0x21,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x23,0x37,0x36,0x36,0x37,0x21,0x15,0xfb,0xd2,0x5a,0x05,0x5b,0x04,0x08,0x05,0xba,0x6a,0xe7,0xe8,0x69,0xbe,0x03,0x07,0x03,0xfa,0xa5,0x23,0x02,0x4e,0xff,0x05,0x0a,0x05,0xeb,0xfe,0xd9,0xfe,0xd9,0xef,0x04,0x08,0x04,0xff, 0x00,0x02,0xfe,0xbb,0xff,0x92,0x01,0xbd,0x03,0x3e,0x00,0x24,0x00,0x28,0x00,0x43,0x40,0x40,0x09,0x01,0x04,0x03,0x01,0x4c,0x06,0x01,0x02,0x00,0x01,0x03,0x02,0x01,0x67,0x00,0x03,0x00,0x04,0x00,0x03,0x04,0x67,0x00,0x00,0x05,0x05,0x00,0x57,0x00,0x00,0x00,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x00,0x05,0x4f,0x25,0x25,0x00,0x00, 0x25,0x28,0x25,0x28,0x27,0x26,0x00,0x24,0x00,0x23,0x21,0x25,0x21,0x2c,0x21,0x0a,0x09,0x1b,0x2b,0x07,0x35,0x33,0x32,0x36,0x27,0x27,0x26,0x36,0x37,0x26,0x26,0x37,0x37,0x36,0x26,0x23,0x23,0x35,0x33,0x32,0x16,0x07,0x07,0x06,0x16,0x33,0x33,0x15,0x23,0x22,0x06,0x17,0x17,0x16,0x06,0x23,0x21,0x11,0x33,0x11,0x37,0x73,0x2f,0x32, 0x02,0x0a,0x03,0x36,0x31,0x32,0x35,0x03,0x0a,0x02,0x32,0x2f,0x73,0x73,0x59,0x65,0x05,0x0a,0x03,0x26,0x41,0x6e,0x6e,0x40,0x27,0x03,0x0a,0x05,0x65,0x59,0xfe,0x7f,0x5a,0x6e,0x50,0x2b,0x2b,0xa4,0x39,0x4a,0x09,0x09,0x4a,0x39,0xa4,0x2b,0x2b,0x50,0x57,0x4f,0xa4,0x35,0x2f,0x50,0x2f,0x35,0xa4,0x4f,0x57,0x03,0xac,0xfc,0x54,0x00, 0x00,0x02,0xfe,0xbb,0xff,0x92,0x01,0x45,0x03,0x3e,0x00,0x07,0x00,0x0b,0x00,0x33,0x40,0x30,0x04,0x01,0x02,0x00,0x01,0x00,0x02,0x01,0x67,0x00,0x00,0x03,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x00,0x03,0x4f,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08, 0x09,0x19,0x2b,0x07,0x35,0x21,0x11,0x21,0x35,0x21,0x11,0x21,0x11,0x33,0x11,0x3c,0x01,0x27,0xfe,0xd9,0x01,0x81,0xfd,0x76,0x5a,0x6e,0x50,0x03,0x0c,0x50,0xfc,0x54,0x03,0xac,0xfc,0x54,0xff,0xff,0xfe,0xe3,0xff,0x92,0x01,0x1d,0x03,0x3e,0x00,0x26,0x05,0xbe,0xc4,0x00,0x00,0x07,0x05,0xbe,0xfd,0xe4,0x00,0x00,0x00,0x02,0xfc,0xa4, 0xff,0xab,0x01,0x72,0x02,0xee,0x00,0x07,0x00,0x0b,0x00,0x56,0x4b,0xb0,0x18,0x50,0x58,0x40,0x17,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x07,0x05,0x06,0x03,0x03,0x03,0x00,0x5f,0x04,0x01,0x00,0x00,0x38,0x03,0x4e,0x1b,0x40,0x1d,0x04,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x04,0x01,0x00,0x00, 0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x00,0x03,0x4f,0x59,0x40,0x14,0x08,0x08,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x00,0x07,0x00,0x07,0x11,0x11,0x11,0x08,0x09,0x19,0x2b,0x05,0x11,0x33,0x11,0x21,0x15,0x21,0x11,0x21,0x11,0x33,0x11,0xfe,0x52,0x5a,0x02,0xc6,0xfd,0x3a,0xfd,0xf8,0x5a,0x55,0x03,0x43,0xfe,0x84,0x50,0xfe,0x89, 0x03,0x43,0xfc,0xbd,0x00,0x03,0xfc,0xc7,0xff,0x92,0x00,0xe1,0x03,0x3e,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x2d,0x40,0x2a,0x04,0x02,0x02,0x00,0x01,0x00,0x85,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x01,0x76,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09, 0x06,0x17,0x2b,0x17,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x87,0x5a,0xfb,0xe6,0x5a,0x01,0x86,0x5a,0x6e,0x03,0xac,0xfc,0x54,0x03,0xac,0xfc,0x54,0x03,0xac,0xfc,0x54,0x00,0x04,0xfa,0xc9,0xff,0xab,0x00,0xd2,0x02,0xee,0x00,0x03,0x00,0x07,0x00,0x0d,0x00,0x16,0x00,0x5f,0x40,0x0a,0x16,0x12,0x0e,0x0c,0x0b,0x05, 0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x12,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x01,0x00,0x5f,0x04,0x02,0x02,0x00,0x00,0x38,0x01,0x4e,0x1b,0x40,0x19,0x04,0x02,0x02,0x00,0x01,0x01,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x01,0x5f,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x00,0x01,0x4f,0x59,0x40,0x1a,0x08,0x08,0x04,0x04, 0x00,0x00,0x08,0x0d,0x08,0x0d,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x09,0x17,0x2b,0x05,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x11,0x33,0x01,0x15,0x01,0x35,0x01,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0xfc,0x77,0x5a,0xfd,0xf8,0x5a,0x03,0x02,0x5a,0x02,0x53,0xfd,0xad,0x01,0xbd,0x16,0x27,0x0a, 0x0a,0x27,0x16,0xfe,0x43,0x55,0x03,0x43,0xfc,0xbd,0x03,0x43,0xfc,0xbd,0x03,0x43,0xfe,0x8e,0x64,0xfe,0x93,0x68,0x01,0x0e,0x0e,0x15,0x04,0x05,0x17,0x0d,0x01,0x12,0x00,0x02,0xfc,0xa4,0xff,0xab,0x01,0x72,0x02,0xee,0x00,0x0b,0x00,0x0f,0x00,0x68,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1f,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00, 0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x09,0x07,0x08,0x03,0x05,0x05,0x00,0x5f,0x06,0x01,0x00,0x00,0x38,0x05,0x4e,0x1b,0x40,0x25,0x06,0x01,0x00,0x01,0x05,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x06,0x01,0x00,0x00,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x00,0x05,0x4f,0x59,0x40, 0x16,0x0c,0x0c,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x05,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x11,0x33,0x11,0xfe,0x52,0x5a,0x02,0xc6,0xfd,0x3a,0x02,0xc6,0xfd,0x3a,0xfd,0xf8,0x5a,0x55,0x03,0x43,0xfe,0xfc,0x50,0xa0,0x50,0xff,0x03, 0x43,0xfc,0xbd,0x00,0x00,0x03,0xfc,0xd6,0xff,0xab,0x01,0x31,0x02,0xee,0x00,0x03,0x00,0x09,0x00,0x12,0x00,0x50,0x40,0x0a,0x12,0x0e,0x0a,0x08,0x07,0x05,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0f,0x05,0x03,0x04,0x03,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x00,0x38,0x01,0x4e,0x1b,0x40,0x15,0x02,0x01,0x00,0x01,0x01, 0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x59,0x40,0x12,0x04,0x04,0x00,0x00,0x04,0x09,0x04,0x09,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x05,0x11,0x33,0x11,0x21,0x11,0x33,0x01,0x15,0x01,0x35,0x01,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0xfc,0xd6,0x5a,0x01,0x54,0x5a,0x02, 0x53,0xfd,0xad,0x01,0xbd,0x16,0x27,0x0a,0x0a,0x27,0x16,0xfe,0x43,0x55,0x03,0x43,0xfc,0xbd,0x03,0x43,0xfe,0x8e,0x64,0xfe,0x93,0x68,0x01,0x0e,0x0e,0x15,0x04,0x05,0x17,0x0d,0x01,0x12,0x00,0x01,0xfe,0xa7,0xff,0xab,0x01,0xa4,0x02,0xee,0x00,0x0b,0x00,0x59,0x4b,0xb0,0x18,0x50,0x58,0x40,0x1c,0x00,0x01,0x00,0x02,0x03,0x01,0x02, 0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x06,0x01,0x05,0x05,0x00,0x5f,0x00,0x00,0x00,0x38,0x05,0x4e,0x1b,0x40,0x21,0x00,0x00,0x01,0x05,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x00,0x00,0x00,0x05,0x5f,0x06,0x01,0x05,0x00,0x05,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x0b, 0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x05,0x11,0x33,0x11,0x21,0x15,0x21,0x15,0x21,0x15,0x21,0x15,0xfe,0xa7,0x5a,0x02,0xa3,0xfd,0x5d,0x02,0xa3,0xfd,0x5d,0x55,0x03,0x43,0xfe,0xfc,0x50,0xa0,0x50,0xff,0x00,0x00,0x02,0xfb,0xd2,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0c,0x00,0x17,0x00,0x40,0x40,0x3d,0x12,0x07, 0x02,0x06,0x07,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x00,0x04,0x03,0x06,0x04,0x67,0x02,0x01,0x00,0x00,0x03,0x5f,0x08,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x17,0x16,0x0e,0x0d,0x00,0x0c,0x00,0x0c,0x11,0x12,0x11,0x11,0x11,0x09,0x09,0x1b,0x2b,0x25,0x11,0x33,0x15, 0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x15,0x35,0x21,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x21,0xfb,0xd2,0x5a,0x04,0xfb,0x6b,0x6a,0xe7,0xe8,0x69,0x6b,0xfb,0x05,0x05,0x3b,0x13,0x13,0x1a,0x05,0x05,0x1c,0x15,0x10,0xfa,0xc6,0x23,0x02,0x4e,0x87,0x87,0xfe,0xd9,0xfe,0xd9,0x87,0x87,0xd7,0x18,0x17,0x1c,0x04,0x05,0x1f,0x19, 0x14,0x00,0x00,0x00,0x00,0x02,0xfe,0xbb,0xff,0xab,0x01,0x68,0x02,0xee,0x00,0x05,0x00,0x0e,0x00,0x41,0x40,0x0a,0x0e,0x0a,0x06,0x04,0x03,0x05,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0c,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x01,0x4e,0x1b,0x40,0x11,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01, 0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x59,0x40,0x0a,0x00,0x00,0x00,0x05,0x00,0x05,0x11,0x03,0x09,0x17,0x2b,0x05,0x11,0x33,0x01,0x15,0x01,0x35,0x01,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0xfe,0xbb,0x5a,0x02,0x53,0xfd,0xad,0x01,0xbd,0x16,0x27,0x0a,0x0a,0x27,0x16,0xfe,0x43,0x55,0x03,0x43,0xfe,0x8e,0x64,0xfe,0x93,0x68,0x01,0x0e, 0x0e,0x15,0x04,0x05,0x17,0x0d,0x01,0x12,0x00,0x03,0xfe,0x13,0xff,0x74,0x01,0xf9,0x03,0x66,0x00,0x2d,0x00,0x34,0x00,0x3c,0x00,0x36,0x40,0x33,0x3c,0x32,0x31,0x25,0x24,0x1d,0x17,0x16,0x13,0x10,0x09,0x0b,0x00,0x01,0x35,0x2c,0x19,0x18,0x08,0x01,0x06,0x02,0x00,0x02,0x4c,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x00,0x85,0x03, 0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x2d,0x00,0x2d,0x1c,0x14,0x04,0x09,0x18,0x2b,0x05,0x35,0x26,0x26,0x27,0x33,0x14,0x16,0x17,0x11,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x17,0x01,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0x26,0x26,0x27,0x15,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x03,0x14, 0x16,0x17,0x35,0x06,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0xfe,0xde,0x5e,0x6b,0x02,0x5a,0x3b,0x36,0x1b,0x4b,0x51,0x63,0x54,0x3c,0x44,0x4d,0x02,0x4e,0xfe,0x61,0x01,0x27,0x13,0x20,0x08,0x09,0x21,0x11,0xfe,0x0d,0x26,0x35,0x19,0x28,0x49,0x50,0x69,0x58,0x99,0x30,0x2d,0x2c,0x31,0x99,0x31,0x36,0x2f,0x2c,0x0c,0x8c,0x83, 0x08,0x69,0x56,0x31,0x3e,0x07,0x01,0x06,0x08,0x17,0x6c,0x49,0x50,0x68,0x08,0x84,0x84,0x08,0x28,0xfe,0xca,0x64,0xd7,0x5a,0x97,0x0a,0x0d,0x02,0x02,0x0a,0x09,0x01,0x08,0x14,0x14,0x02,0xf8,0x0d,0x17,0x6e,0x4a,0x52,0x6c,0x09,0x83,0x02,0xb6,0x2d,0x42,0x0e,0xe5,0x07,0x36,0xfd,0xf3,0x08,0x3c,0x30,0x2c,0x42,0x0d,0x04,0x00,0x00, 0x00,0x01,0xfe,0x20,0x00,0x5f,0x01,0xe0,0x02,0x35,0x00,0x13,0x00,0x5a,0x4b,0xb0,0x21,0x50,0x58,0x40,0x1a,0x05,0x03,0x02,0x01,0x08,0x06,0x02,0x00,0x07,0x01,0x00,0x67,0x0a,0x09,0x02,0x07,0x07,0x02,0x5f,0x04,0x01,0x02,0x02,0x3b,0x07,0x4e,0x1b,0x40,0x20,0x04,0x01,0x02,0x01,0x07,0x02,0x57,0x05,0x03,0x02,0x01,0x08,0x06,0x02, 0x00,0x07,0x01,0x00,0x67,0x04,0x01,0x02,0x02,0x07,0x5f,0x0a,0x09,0x02,0x07,0x02,0x07,0x4f,0x59,0x40,0x12,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x09,0x1f,0x2b,0x25,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x21,0x15,0xfe,0xdf,0xbf,0xbf, 0x58,0x01,0x92,0x58,0xbf,0xbf,0x58,0xfe,0x6e,0x5f,0xc3,0x50,0xc3,0xc3,0xc3,0xc3,0x50,0xc3,0xc3,0xc3,0x00,0x01,0xfb,0xff,0x00,0x5f,0x01,0xa9,0x02,0x35,0x00,0x1b,0x00,0x6b,0x4b,0xb0,0x21,0x50,0x58,0x40,0x1e,0x07,0x05,0x03,0x03,0x01,0x0c,0x0a,0x08,0x03,0x00,0x09,0x01,0x00,0x67,0x0e,0x0d,0x0b,0x03,0x09,0x09,0x02,0x5f,0x06, 0x04,0x02,0x02,0x02,0x3b,0x09,0x4e,0x1b,0x40,0x25,0x06,0x04,0x02,0x02,0x01,0x09,0x02,0x57,0x07,0x05,0x03,0x03,0x01,0x0c,0x0a,0x08,0x03,0x00,0x09,0x01,0x00,0x67,0x06,0x04,0x02,0x02,0x02,0x09,0x5f,0x0e,0x0d,0x0b,0x03,0x09,0x02,0x09,0x4f,0x59,0x40,0x1a,0x00,0x00,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13, 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0x09,0x1f,0x2b,0x25,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x21,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x23,0x35,0x21,0x15,0x23,0x35,0x21,0x15,0xfc,0xbe,0xbf,0xbf,0x58,0x01,0x92,0x58,0x01,0x92,0x58,0xbf,0xbf,0x58,0xfe,0x6e,0x58,0xfe,0x6e,0x5f,0xc3,0x50,0xc3, 0xc3,0xc3,0xc3,0xc3,0xc3,0x50,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x02,0xfd,0xda,0x00,0x2d,0x02,0x12,0x02,0x67,0x00,0x0b,0x00,0x18,0x00,0x3e,0x40,0x3b,0x17,0x16,0x15,0x03,0x01,0x02,0x11,0x01,0x00,0x01,0x18,0x0d,0x0c,0x03,0x05,0x00,0x03,0x4c,0x00,0x02,0x01,0x05,0x02,0x57,0x03,0x01,0x01,0x04,0x01,0x00,0x05,0x01,0x00,0x67, 0x00,0x02,0x02,0x05,0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x25,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x25,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0xfe,0xcb,0xf1,0xf1,0x58,0xf1,0xf1,0x01,0x41,0x01,0x36,0x13,0x21, 0x08,0x09,0x22,0x11,0xfe,0xca,0x01,0xae,0x2d,0xf5,0x50,0xf5,0xf5,0x50,0xf5,0x14,0x57,0x98,0x09,0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0x00,0x04,0xfe,0x2a,0x00,0x64,0x01,0xae,0x02,0x30,0x00,0x0b,0x00,0x0f,0x00,0x1b,0x00,0x1f,0x00,0x6f,0x4b,0xb0,0x18,0x50,0x58,0x40,0x22,0x00,0x03,0x00,0x00,0x03,0x57,0x00,0x06,0x04, 0x05,0x06,0x57,0x07,0x01,0x05,0x09,0x01,0x04,0x05,0x04,0x65,0x02,0x08,0x02,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x01,0x4e,0x1b,0x40,0x24,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x67,0x00,0x07,0x00,0x06,0x04,0x07,0x06,0x67,0x00,0x05,0x09,0x01,0x04,0x05,0x04,0x65,0x08,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x00,0x4e, 0x59,0x40,0x1b,0x11,0x10,0x01,0x00,0x1f,0x1e,0x1d,0x1c,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0f,0x0e,0x0d,0x0c,0x07,0x05,0x00,0x0b,0x01,0x0b,0x0a,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x25,0x21,0x35,0x21,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x25,0x21,0x35,0x21,0x01, 0x5e,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xfe,0xce,0xfd,0xda,0x02,0x26,0x01,0x0e,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xfe,0xce,0xfd,0xda,0x02,0x26,0x01,0x90,0x2b,0x25,0x24,0x2c,0x2c,0x24,0x25,0x2b,0x0a,0x50,0xfe,0x7a,0x2c,0x25,0x24,0x2b,0x2b,0x24,0x25,0x2c,0x46,0x50,0x00,0x00,0x00,0x00,0x06,0xfb,0xa0,0x00,0x64,0x02,0x08, 0x02,0x30,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x1f,0x00,0x23,0x00,0x27,0x00,0x97,0x4b,0xb0,0x18,0x50,0x58,0x40,0x2a,0x04,0x01,0x02,0x00,0x00,0x02,0x57,0x11,0x0b,0x10,0x03,0x09,0x06,0x07,0x09,0x57,0x0a,0x08,0x02,0x07,0x0f,0x01,0x06,0x07,0x06,0x65,0x0e,0x05,0x0d,0x03,0x0c,0x05,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x01, 0x4e,0x1b,0x40,0x2c,0x04,0x01,0x02,0x0e,0x05,0x0d,0x03,0x03,0x00,0x02,0x03,0x67,0x0a,0x01,0x08,0x11,0x0b,0x10,0x03,0x09,0x06,0x08,0x09,0x67,0x00,0x07,0x0f,0x01,0x06,0x07,0x06,0x65,0x0c,0x01,0x00,0x00,0x01,0x61,0x00,0x01,0x01,0x41,0x00,0x4e,0x59,0x40,0x33,0x24,0x24,0x20,0x20,0x15,0x14,0x10,0x10,0x0c,0x0c,0x01,0x00,0x24, 0x27,0x24,0x27,0x26,0x25,0x20,0x23,0x20,0x23,0x22,0x21,0x1b,0x19,0x14,0x1f,0x15,0x1f,0x10,0x13,0x10,0x13,0x12,0x11,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x07,0x05,0x00,0x0b,0x01,0x0b,0x12,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x37,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x01,0x22,0x26,0x35,0x34, 0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x25,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0xfe,0xd4,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xef,0x02,0x21,0xf9,0x98,0x02,0x21,0x01,0x13,0x24,0x2c,0x2c,0x24,0x24,0x2c,0x2c,0xfc,0xa8,0x02,0x21,0x02,0x26,0x02,0x21,0x01,0x90,0x2b,0x25,0x24,0x2c,0x2c,0x24,0x25,0x2b,0x0a,0x50,0x50,0x50,0x50,0xfe, 0xca,0x2c,0x24,0x25,0x2b,0x2b,0x25,0x24,0x2c,0x46,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x06,0xfb,0xa0,0xff,0xfb,0x02,0x08,0x02,0xda,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x21,0x00,0x64,0x40,0x61,0x04,0x01,0x02,0x0e,0x05,0x0d,0x03,0x03,0x06,0x02,0x03,0x67,0x08,0x01,0x06,0x10,0x09,0x0f,0x03,0x07,0x0b,0x06, 0x07,0x67,0x0c,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x0b,0x0b,0x0a,0x61,0x11,0x01,0x0a,0x0a,0x42,0x0a,0x4e,0x15,0x14,0x10,0x10,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x1c,0x19,0x14,0x21,0x15,0x20,0x10,0x13,0x10,0x13,0x12,0x11,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04, 0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x12,0x09,0x17,0x2b,0x25,0x03,0x33,0x03,0x37,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfe,0xab,0x0c,0x6a,0x0c,0xea,0x02,0x21,0xf9,0x98,0x02,0x21,0xfd,0xdf,0x02,0x21,0x02,0x26, 0x02,0x21,0xfc,0xbd,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xc3,0x50,0x50,0x50,0x50,0xf0,0x50,0x50,0x50,0x50,0xaf,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0x00,0x00,0x02,0xfd,0xf8,0x00,0xaa,0x02,0x08,0x01,0xea,0x00,0x03,0x00,0x07,0x00,0x2f,0x40,0x2c,0x00,0x00,0x04,0x01,0x01,0x02, 0x00,0x01,0x67,0x00,0x02,0x03,0x03,0x02,0x57,0x00,0x02,0x02,0x03,0x5f,0x05,0x01,0x03,0x02,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x01,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0xfd,0xf8,0x04,0x10,0xfb,0xf0,0x04,0x10,0x01,0x9a,0x50,0x50,0xf0,0x50,0x50,0x00,0x00, 0x00,0x03,0xfb,0xa5,0x00,0x4c,0x02,0x03,0x02,0x48,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x40,0x40,0x3d,0x00,0x00,0x06,0x01,0x01,0x02,0x00,0x01,0x67,0x00,0x02,0x07,0x01,0x03,0x04,0x02,0x03,0x67,0x00,0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x08,0x01,0x05,0x04,0x05,0x4f,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0b,0x08, 0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x09,0x17,0x2b,0x01,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0xfb,0xa5,0x06,0x5e,0xf9,0xa2,0x06,0x5e,0xf9,0xa2,0x06,0x5e,0x01,0xfc,0x4c,0x4c,0xd8,0x4c,0x4c,0xd8,0x4c,0x4c,0x00,0x01,0xfb,0xa5,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x13, 0x00,0x6c,0xb6,0x12,0x08,0x02,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x25,0x00,0x04,0x03,0x03,0x04,0x70,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x23,0x00,0x04,0x03,0x04,0x85,0x06,0x01, 0x05,0x00,0x05,0x86,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x18,0x11,0x11,0x07,0x09,0x1b,0x2b,0x37,0x37,0x21,0x35,0x21,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x21,0x35,0x21,0x27,0x33, 0x13,0x03,0xbc,0x6b,0xfa,0x7e,0x05,0xc2,0x13,0x13,0x1a,0x05,0x05,0x1c,0x15,0x10,0xfa,0x3f,0x05,0x82,0x6b,0x6a,0xe7,0xe8,0x23,0x87,0x50,0x18,0x17,0x1c,0x04,0x05,0x1f,0x19,0x14,0x50,0x87,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x00,0x00,0x01,0xfd,0xfd,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x13,0x00,0x6c,0xb6,0x12,0x08,0x02,0x01,0x02, 0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x25,0x00,0x04,0x03,0x03,0x04,0x70,0x06,0x01,0x05,0x00,0x00,0x05,0x71,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x23,0x00,0x04,0x03,0x04,0x85,0x06,0x01,0x05,0x00,0x05,0x86,0x00,0x03,0x00,0x02, 0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x18,0x11,0x11,0x07,0x09,0x1b,0x2b,0x37,0x37,0x21,0x35,0x21,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x21,0x35,0x21,0x27,0x33,0x13,0x03,0xbc,0x6b,0xfc,0xd6,0x03,0x6a, 0x13,0x13,0x1a,0x05,0x05,0x1c,0x15,0x10,0xfc,0x97,0x03,0x2a,0x6b,0x6a,0xe7,0xe8,0x23,0x87,0x50,0x18,0x17,0x1c,0x04,0x05,0x1f,0x19,0x14,0x50,0x87,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x00,0x00,0x02,0xfb,0xa5,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x13,0x00,0x1f,0x00,0x47,0x40,0x44,0x1e,0x18,0x12,0x08,0x04,0x01,0x02,0x01,0x4c,0x06, 0x01,0x04,0x03,0x05,0x04,0x57,0x00,0x03,0x00,0x02,0x01,0x03,0x02,0x68,0x00,0x01,0x00,0x00,0x05,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x04,0x05,0x4f,0x14,0x14,0x00,0x00,0x14,0x1f,0x14,0x1f,0x1d,0x1c,0x00,0x13,0x00,0x13,0x11,0x11,0x18,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x27,0x37,0x21,0x35,0x21, 0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x21,0x35,0x21,0x27,0x33,0x13,0x03,0x33,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x70,0x6b,0xfb,0xaa,0x04,0x96,0x13,0x13,0x1a,0x05,0x05,0x1c,0x15,0x10,0xfb,0x6b,0x04,0x56,0x6b,0x6a,0xe7,0xe8,0xc3,0xbe,0x13,0x1a,0x05,0x05,0x1c,0x15,0xba,0x6a,0xe7,0xe8,0x23,0x87,0x50, 0x18,0x17,0x1c,0x04,0x05,0x1f,0x19,0x14,0x50,0x87,0xfe,0xd9,0xfe,0xd9,0xef,0x17,0x1c,0x04,0x05,0x1f,0x19,0xeb,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x00,0x02,0xfb,0xa5,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0f,0x00,0x17,0x00,0x47,0x40,0x44,0x15,0x11,0x0d,0x05,0x04,0x01,0x02,0x01,0x4c,0x06,0x01,0x04,0x03,0x05,0x04,0x57,0x00,0x03, 0x00,0x02,0x01,0x03,0x02,0x67,0x00,0x01,0x00,0x00,0x05,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x04,0x05,0x4f,0x10,0x10,0x00,0x00,0x10,0x17,0x10,0x17,0x13,0x12,0x00,0x0f,0x00,0x0f,0x11,0x11,0x12,0x11,0x11,0x0a,0x09,0x1b,0x2b,0x37,0x27,0x21,0x35,0x21,0x27,0x37,0x21,0x35,0x21,0x37,0x33,0x07, 0x07,0x17,0x17,0x33,0x03,0x13,0x33,0x07,0x07,0x17,0x17,0x72,0x6a,0xfb,0x9d,0x04,0x25,0x3f,0x3f,0xfb,0xdb,0x04,0x64,0x6a,0x69,0xbe,0x2e,0x32,0xba,0xae,0xe7,0xe8,0x69,0xbe,0x2e,0x32,0xba,0x23,0x87,0x50,0x50,0x50,0x50,0x87,0xef,0x37,0x3d,0xeb,0x01,0x27,0x01,0x27,0xef,0x37,0x3d,0xeb,0x00,0x01,0xfb,0xa1,0x00,0x00,0x02,0x09, 0x02,0x99,0x00,0x13,0x00,0x35,0x40,0x32,0x00,0x04,0x03,0x04,0x85,0x05,0x01,0x03,0x06,0x01,0x02,0x01,0x03,0x02,0x68,0x07,0x01,0x01,0x08,0x01,0x00,0x09,0x01,0x00,0x67,0x0a,0x01,0x09,0x09,0x39,0x09,0x4e,0x00,0x00,0x00,0x13,0x00,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0b,0x09,0x1f,0x2b,0x21,0x37,0x21,0x35,0x21, 0x37,0x21,0x35,0x21,0x37,0x33,0x07,0x21,0x15,0x21,0x07,0x21,0x15,0x21,0x07,0xfe,0x53,0x3e,0xfd,0x10,0x03,0x0e,0x3a,0xfc,0xb8,0x03,0x66,0x40,0x48,0x40,0x02,0xba,0xfd,0x28,0x3a,0x03,0x12,0xfc,0xd0,0x3e,0xaa,0x50,0xa0,0x50,0xaf,0xaf,0x50,0xa0,0x50,0xaa,0x00,0x00,0x00,0x01,0xfe,0x0c,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x0e, 0x00,0x2e,0x40,0x2b,0x04,0x01,0x02,0x01,0x01,0x4c,0x00,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x0e,0x00,0x0e,0x11,0x11,0x18,0x05,0x09,0x19,0x2b,0x25,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x33,0x17,0x21,0x15,0x21,0x07,0xfe, 0x0c,0xbe,0x13,0x1a,0x05,0x05,0x1c,0x15,0xba,0x6a,0xc8,0x02,0xc5,0xfd,0x3b,0xc9,0x23,0xef,0x17,0x1c,0x04,0x05,0x1f,0x19,0xeb,0xff,0x50,0xff,0x00,0x01,0xfb,0xb3,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x19,0x00,0x34,0x40,0x31,0x11,0x04,0x02,0x04,0x01,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x04,0x03,0x01, 0x04,0x68,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x19,0x00,0x19,0x23,0x12,0x14,0x11,0x18,0x07,0x09,0x1b,0x2b,0x25,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x33,0x17,0x21,0x26,0x26,0x27,0x27,0x33,0x13,0x03,0x23,0x37,0x36,0x36,0x37,0x21,0x07,0xfb,0xb3,0xbe,0x13,0x1a,0x05,0x05,0x1d, 0x14,0xba,0x6a,0xc8,0x04,0xa1,0x04,0x07,0x05,0xba,0x6a,0xe7,0xe8,0x69,0xbe,0x03,0x07,0x03,0xfb,0x5e,0xc9,0x23,0xef,0x17,0x1c,0x04,0x05,0x1e,0x1a,0xeb,0xff,0x05,0x0a,0x05,0xeb,0xfe,0xd9,0xfe,0xd9,0xef,0x04,0x08,0x04,0xff,0xff,0xff,0xfe,0x61,0xff,0x92,0x01,0x59,0x03,0x3e,0x00,0x27,0x04,0x1b,0xfe,0x0c,0x00,0x0f,0x01,0x06, 0x03,0x48,0xce,0x00,0x00,0x08,0xb1,0x00,0x01,0xb0,0x0f,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0xfe,0x89,0x00,0x2d,0x01,0x7f,0x02,0x67,0x00,0x27,0x04,0x1b,0xfe,0x34,0x00,0x00,0x03,0x06,0x03,0x2b,0x00,0x37,0x00,0x08,0xb1,0x01,0x02,0xb0,0x37,0xb0,0x35,0x2b,0x00,0x00,0x00,0x02,0xfe,0xcf,0xff,0xb6,0x01,0x31,0x02,0xbc,0x00,0x0d, 0x00,0x11,0x00,0x08,0xb5,0x10,0x0e,0x0b,0x00,0x02,0x32,0x2b,0x25,0x35,0x25,0x36,0x36,0x37,0x35,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0x01,0x35,0x25,0x15,0xfe,0xcf,0x01,0xea,0x11,0x1f,0x07,0x07,0x1f,0x11,0xfe,0x16,0x02,0x62,0xfd,0x9e,0x02,0x62,0x96,0x5a,0xa8,0x06,0x06,0x01,0x07,0x01,0x06,0x06,0xab,0x58,0xe1,0x64,0xfe,0x3f, 0x5a,0xe1,0x5a,0x00,0x00,0x02,0xfb,0xb3,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0d,0x00,0x19,0x00,0x42,0x40,0x3f,0x19,0x13,0x08,0x01,0x04,0x06,0x07,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x00,0x04,0x03,0x06,0x04,0x67,0x02,0x01,0x00,0x00,0x03,0x5f,0x08,0x05,0x02,0x03, 0x00,0x03,0x4f,0x00,0x00,0x18,0x17,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x09,0x09,0x1b,0x2b,0x25,0x13,0x03,0x33,0x17,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x07,0x37,0x21,0x37,0x36,0x36,0x37,0x26,0x26,0x27,0x27,0x21,0x17,0xfb,0xb3,0xeb,0xeb,0x6a,0x6a,0x04,0xa0,0x6b,0x6a,0xe7,0xe8,0x69,0x6b,0xfb,0x5f, 0x6a,0xa9,0x04,0xa2,0x13,0x13,0x1a,0x05,0x05,0x1c,0x15,0x10,0xfb,0x5f,0x3f,0x23,0x01,0x26,0x01,0x28,0x87,0x87,0xfe,0xd9,0xfe,0xd9,0x87,0x87,0xd7,0x18,0x17,0x1c,0x04,0x05,0x1f,0x19,0x14,0x50,0x00,0x00,0xff,0xff,0xfe,0x2a,0x00,0x40,0x01,0xd7,0x02,0x53,0x00,0x26,0x04,0x1b,0xd4,0x00,0x01,0x07,0x04,0x1b,0xfd,0xd5,0xff,0xff, 0x00,0x09,0xb1,0x01,0x01,0xb8,0xff,0xff,0xb0,0x35,0x2b,0x00,0x00,0x02,0xfb,0xb3,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x08,0x00,0x0e,0x00,0x3c,0x40,0x39,0x0d,0x0a,0x01,0x03,0x02,0x01,0x01,0x4c,0x04,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x04,0x01,0x00,0x00,0x03,0x5f,0x07,0x05,0x06,0x03,0x03, 0x00,0x03,0x4f,0x09,0x09,0x00,0x00,0x09,0x0e,0x09,0x0e,0x0c,0x0b,0x00,0x08,0x00,0x08,0x11,0x11,0x12,0x08,0x09,0x19,0x2b,0x25,0x13,0x03,0x33,0x17,0x21,0x15,0x21,0x07,0x21,0x13,0x03,0x33,0x13,0x03,0xfc,0xdf,0xeb,0xeb,0x6a,0xc8,0x03,0xf2,0xfc,0x0e,0xc9,0xfe,0x6b,0xeb,0xeb,0x6a,0xe7,0xe8,0x23,0x01,0x26,0x01,0x28,0xff,0x50, 0xff,0x01,0x26,0x01,0x28,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x00,0x00,0x02,0xfb,0xb3,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x47,0x40,0x44,0x12,0x0f,0x08,0x01,0x04,0x03,0x02,0x01,0x4c,0x06,0x01,0x00,0x01,0x05,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x67,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x06,0x01, 0x00,0x00,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x00,0x05,0x4f,0x0e,0x0e,0x00,0x00,0x0e,0x13,0x0e,0x13,0x11,0x10,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x0a,0x09,0x1b,0x2b,0x25,0x13,0x03,0x33,0x17,0x21,0x15,0x21,0x17,0x07,0x21,0x15,0x21,0x07,0x21,0x13,0x03,0x33,0x13,0x03,0xfc,0xdf,0xeb,0xeb,0x6a,0x6a,0x04,0x50,0xfb, 0xee,0x3f,0x3f,0x04,0x12,0xfb,0xaf,0x6a,0xfe,0x6b,0xeb,0xeb,0x6a,0xe7,0xe8,0x23,0x01,0x26,0x01,0x28,0x87,0x50,0x50,0x50,0x50,0x87,0x01,0x26,0x01,0x28,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0xff,0xff,0xfc,0x6d,0x00,0x41,0x02,0x03,0x02,0x53,0x00,0x27,0x04,0x1b,0xfc,0x18,0x00,0x00,0x00,0x27,0x04,0x1b,0xfe,0x0c,0x00,0x00,0x02,0x06, 0x04,0x1b,0x00,0x00,0x00,0x01,0xfd,0xf3,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0e,0x00,0x30,0x40,0x2d,0x01,0x01,0x02,0x01,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x60,0x00,0x02,0x01,0x02,0x50,0x00,0x00,0x00,0x0e,0x00,0x0e,0x11,0x23,0x12,0x05,0x09, 0x19,0x2b,0x25,0x03,0x13,0x33,0x07,0x06,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x17,0x17,0xfe,0xda,0xe7,0xe8,0x69,0xbe,0x03,0x07,0x03,0x03,0x7b,0xfc,0x86,0x04,0x08,0x04,0xba,0x23,0x01,0x27,0x01,0x27,0xef,0x04,0x08,0x04,0x50,0x04,0x0b,0x05,0xeb,0x00,0x01,0xfb,0x9b,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x0e,0x00,0x30,0x40,0x2d, 0x01,0x01,0x02,0x01,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x04,0x01,0x03,0x02,0x03,0x86,0x00,0x01,0x02,0x02,0x01,0x57,0x00,0x01,0x01,0x02,0x60,0x00,0x02,0x01,0x02,0x50,0x00,0x00,0x00,0x0e,0x00,0x0e,0x11,0x23,0x12,0x05,0x09,0x19,0x2b,0x25,0x03,0x13,0x33,0x07,0x06,0x06,0x07,0x21,0x15,0x21,0x16,0x16,0x17,0x17,0xfc,0x82,0xe7, 0xe8,0x69,0xbe,0x03,0x07,0x03,0x05,0xe2,0xfa,0x1a,0x05,0x0a,0x06,0xba,0x23,0x01,0x27,0x01,0x27,0xef,0x04,0x08,0x04,0x4b,0x05,0x0d,0x07,0xeb,0x00,0x01,0xfb,0x9b,0x00,0x23,0x01,0xd6,0x02,0x71,0x00,0x0c,0x00,0x33,0x40,0x30,0x09,0x01,0x02,0x05,0x01,0x4c,0x04,0x01,0x00,0x05,0x01,0x00,0x57,0x06,0x01,0x05,0x00,0x02,0x01,0x05, 0x02,0x68,0x04,0x01,0x00,0x00,0x01,0x5f,0x03,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x0c,0x00,0x0c,0x12,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x01,0x35,0x33,0x11,0x23,0x35,0x21,0x17,0x23,0x03,0x13,0x33,0x07,0x01,0x7c,0x5a,0x5a,0xfa,0xa6,0xca,0x6a,0xe7,0xe8,0x69,0xcb,0x01,0x72,0xff,0xfd,0xb2,0xff,0xff,0x01,0x27,0x01, 0x27,0xff,0x00,0x00,0x00,0x01,0xfb,0x9b,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0d,0x00,0x35,0x40,0x32,0x08,0x01,0x02,0x04,0x01,0x01,0x4c,0x02,0x01,0x00,0x01,0x00,0x85,0x06,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x04,0x04,0x01,0x57,0x00,0x01,0x01,0x04,0x60,0x00,0x04,0x01,0x04,0x50,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x12, 0x11,0x11,0x12,0x07,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x17,0xfc,0x82,0xe7,0xe8,0x69,0xcb,0x05,0x66,0xcb,0x6a,0xe7,0xe8,0x69,0xcb,0xfa,0x9b,0xca,0x23,0x01,0x27,0x01,0x27,0xff,0xff,0xfe,0xd9,0xfe,0xd9,0xff,0xff,0x00,0x00,0x01,0xfb,0x9b,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0d, 0x00,0x34,0x40,0x31,0x08,0x01,0x02,0x04,0x01,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x04,0x03,0x01,0x04,0x68,0x02,0x01,0x00,0x00,0x03,0x5f,0x06,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x07,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x37,0x33,0x03,0x13, 0x23,0x27,0x21,0x17,0xfc,0x82,0xe7,0xe8,0x69,0xcb,0x04,0xa1,0xc9,0x69,0xe7,0xe7,0x6a,0xc8,0xfb,0x60,0xca,0x23,0x01,0x27,0x01,0x27,0xff,0xff,0xfe,0xda,0xfe,0xd8,0xff,0xff,0x00,0x00,0xff,0xff,0xfe,0x89,0x00,0x2d,0x01,0x7f,0x02,0x67,0x00,0x27,0x04,0x1c,0xfe,0x34,0x00,0x00,0x03,0x06,0x03,0x2b,0x00,0x37,0x00,0x08,0xb1,0x01, 0x02,0xb0,0x37,0xb0,0x35,0x2b,0x00,0x00,0xff,0xff,0xfb,0xcd,0x00,0x2d,0x01,0xa9,0x02,0x67,0x00,0x27,0x04,0x1c,0xfb,0x78,0x00,0x00,0x00,0x27,0x03,0x2b,0xfd,0xa8,0x00,0x37,0x01,0x06,0x04,0x1c,0xa6,0x00,0x00,0x08,0xb1,0x01,0x02,0xb0,0x37,0xb0,0x35,0x2b,0x00,0x00,0x00,0x04,0xf9,0x43,0xff,0xfb,0x02,0x03,0x02,0xda,0x00,0x03, 0x00,0x10,0x00,0x14,0x00,0x22,0x00,0x62,0x40,0x5f,0x05,0x01,0x04,0x03,0x01,0x4c,0x00,0x02,0x00,0x03,0x00,0x02,0x03,0x80,0x0b,0x01,0x05,0x09,0x08,0x09,0x05,0x08,0x80,0x06,0x01,0x03,0x0c,0x07,0x02,0x04,0x01,0x03,0x04,0x68,0x0a,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x4d,0x00,0x09,0x09,0x08,0x61,0x0d,0x01,0x08,0x08, 0x42,0x08,0x4e,0x16,0x15,0x11,0x11,0x04,0x04,0x00,0x00,0x1d,0x1a,0x15,0x22,0x16,0x21,0x11,0x14,0x11,0x14,0x13,0x12,0x04,0x10,0x04,0x10,0x0d,0x0c,0x0b,0x0a,0x07,0x06,0x00,0x03,0x00,0x03,0x11,0x0e,0x09,0x17,0x2b,0x25,0x03,0x33,0x03,0x05,0x03,0x13,0x33,0x07,0x06,0x07,0x21,0x15,0x21,0x16,0x17,0x17,0x25,0x35,0x21,0x15,0x01, 0x22,0x26,0x35,0x34,0x36,0x33,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0xfc,0x53,0x0c,0x6a,0x0c,0xfd,0x85,0xe7,0xe8,0x69,0xbe,0x07,0x06,0x01,0xeb,0xfe,0x16,0x08,0x08,0xba,0x02,0xb0,0x04,0xbf,0xfa,0x6a,0x1a,0x22,0x22,0x1a,0x1e,0x1d,0x1f,0x22,0x1a,0xd7,0x02,0x03,0xfd,0xfd,0xb4,0x01,0x27,0x01,0x27,0xef,0x08,0x08,0x50,0x0a,0x0a, 0xeb,0xff,0x50,0x50,0xfe,0xd9,0x22,0x1a,0x1a,0x22,0x21,0x1a,0x1a,0x23,0x00,0x00,0xff,0xff,0xfd,0xee,0x00,0x41,0x02,0x20,0x02,0x6c,0x00,0x27,0x04,0x1c,0xfd,0x99,0x00,0x00,0x00,0x06,0x03,0x34,0xec,0x00,0xff,0xff,0xfb,0xb4,0x00,0x41,0x01,0xf4,0x02,0x6c,0x00,0x27,0x04,0x1c,0xfb,0x5f,0x00,0x00,0x00,0x26,0x04,0x1b,0xf1,0x00, 0x00,0x07,0x03,0x34,0xfd,0xa8,0x00,0x00,0x00,0x02,0xfe,0x98,0xff,0xab,0x01,0x45,0x02,0xee,0x00,0x05,0x00,0x0e,0x00,0x41,0x40,0x0a,0x0b,0x07,0x06,0x02,0x01,0x05,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0c,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x01,0x4e,0x1b,0x40,0x11,0x00,0x00,0x01,0x01,0x00,0x57, 0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x59,0x40,0x0a,0x00,0x00,0x00,0x05,0x00,0x05,0x13,0x03,0x09,0x17,0x2b,0x17,0x01,0x35,0x01,0x33,0x11,0x27,0x11,0x01,0x06,0x06,0x07,0x16,0x16,0x17,0xeb,0xfd,0xad,0x02,0x53,0x5a,0x5a,0xfe,0x43,0x16,0x27,0x0a,0x0a,0x27,0x16,0x55,0x01,0x6d,0x64,0x01,0x72,0xfc,0xbd,0x68, 0x02,0x70,0xfe,0xee,0x0d,0x17,0x05,0x04,0x15,0x0e,0x00,0x00,0x00,0x03,0xfc,0x77,0xff,0xab,0x00,0xd2,0x02,0xee,0x00,0x03,0x00,0x09,0x00,0x12,0x00,0x50,0x40,0x0a,0x0f,0x0b,0x0a,0x06,0x05,0x05,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x0f,0x05,0x03,0x04,0x03,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x00,0x38,0x01,0x4e, 0x1b,0x40,0x15,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x59,0x40,0x12,0x04,0x04,0x00,0x00,0x04,0x09,0x04,0x09,0x08,0x07,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x17,0x11,0x33,0x11,0x21,0x01,0x35,0x01,0x33,0x11,0x27,0x11,0x01,0x06,0x06,0x07,0x16,0x16, 0x17,0x78,0x5a,0xfd,0xf8,0xfd,0xad,0x02,0x53,0x5a,0x5a,0xfe,0x43,0x16,0x27,0x0a,0x0a,0x27,0x16,0x55,0x03,0x43,0xfc,0xbd,0x01,0x6d,0x64,0x01,0x72,0xfc,0xbd,0x68,0x02,0x70,0xfe,0xee,0x0d,0x17,0x05,0x04,0x15,0x0e,0x00,0x00,0x00,0x04,0xfa,0x7e,0xff,0xab,0x00,0x87,0x02,0xee,0x00,0x03,0x00,0x07,0x00,0x0d,0x00,0x16,0x00,0x5f, 0x40,0x0a,0x13,0x0f,0x0e,0x0a,0x09,0x05,0x01,0x00,0x01,0x4c,0x4b,0xb0,0x18,0x50,0x58,0x40,0x12,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x01,0x00,0x5f,0x04,0x02,0x02,0x00,0x00,0x38,0x01,0x4e,0x1b,0x40,0x19,0x04,0x02,0x02,0x00,0x01,0x01,0x00,0x57,0x04,0x02,0x02,0x00,0x00,0x01,0x5f,0x08,0x05,0x07,0x03,0x06,0x05,0x01,0x00,0x01, 0x4f,0x59,0x40,0x1a,0x08,0x08,0x04,0x04,0x00,0x00,0x08,0x0d,0x08,0x0d,0x0c,0x0b,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x09,0x09,0x17,0x2b,0x17,0x11,0x33,0x11,0x21,0x11,0x33,0x11,0x21,0x01,0x35,0x01,0x33,0x11,0x27,0x11,0x01,0x06,0x06,0x07,0x16,0x16,0x17,0x2d,0x5a,0xfd,0xf8,0x5a,0xfd,0xf8,0xfd,0xad,0x02, 0x53,0x5a,0x5a,0xfe,0x43,0x16,0x27,0x0a,0x0a,0x27,0x16,0x55,0x03,0x43,0xfc,0xbd,0x03,0x43,0xfc,0xbd,0x01,0x6d,0x64,0x01,0x72,0xfc,0xbd,0x68,0x02,0x70,0xfe,0xee,0x0d,0x17,0x05,0x04,0x15,0x0e,0x00,0x00,0x00,0x03,0xfb,0xe6,0xff,0x92,0x01,0xc2,0x03,0x0c,0x00,0x03,0x00,0x10,0x00,0x1d,0x00,0x2a,0x40,0x27,0x1d,0x19,0x15,0x14, 0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x09,0x05,0x04,0x0e,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x05,0x11,0x33,0x11,0x37,0x35,0x01,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0x35,0x01,0x15,0x01,0x01,0x35,0x01,0x15,0x01,0x06,0x06,0x07,0x16,0x16, 0x17,0x01,0xfe,0xa7,0x5a,0x6e,0x01,0xbd,0x14,0x27,0x0a,0x0a,0x27,0x14,0xfe,0x43,0x02,0x53,0xfc,0x77,0xfd,0xad,0x02,0x53,0xfe,0x43,0x13,0x26,0x0b,0x0b,0x26,0x13,0x01,0xbd,0x6e,0x03,0x7a,0xfc,0x86,0x18,0x6b,0x01,0x10,0x0c,0x15,0x04,0x05,0x16,0x0c,0x01,0x16,0x67,0xfe,0x8e,0x64,0xfe,0x91,0x01,0x6f,0x64,0x01,0x72,0x6b,0xfe, 0xeb,0x0c,0x16,0x05,0x05,0x15,0x0b,0xfe,0xee,0x00,0x00,0x00,0x00,0x03,0xfe,0x07,0xff,0x74,0x02,0x01,0x03,0x66,0x00,0x2d,0x00,0x34,0x00,0x3c,0x00,0x49,0x40,0x46,0x32,0x24,0x1d,0x1a,0x06,0x05,0x03,0x02,0x3c,0x31,0x25,0x13,0x0b,0x07,0x05,0x04,0x08,0x01,0x03,0x2c,0x01,0x04,0x00,0x03,0x4c,0x35,0x01,0x01,0x01,0x4b,0x00,0x02, 0x03,0x02,0x85,0x00,0x03,0x01,0x03,0x85,0x05,0x01,0x04,0x00,0x04,0x86,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x00,0x42,0x00,0x4e,0x00,0x00,0x00,0x2d,0x00,0x2d,0x14,0x19,0x1f,0x11,0x06,0x09,0x1a,0x2b,0x05,0x35,0x26,0x27,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x16,0x16,0x17,0x11,0x27,0x26,0x26,0x35,0x34, 0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x17,0x23,0x34,0x26,0x27,0x15,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x03,0x14,0x16,0x17,0x35,0x06,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0x01,0x04,0x79,0x69,0xfd,0xe5,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x21,0x12,0x01,0xc5,0x2c,0x5d,0x37,0x1b,0x4a,0x52,0x63,0x54,0x3c,0x53, 0x64,0x01,0x5a,0x31,0x2d,0x28,0x49,0x50,0x69,0x58,0x99,0x30,0x2d,0x2c,0x31,0x99,0x31,0x36,0x30,0x2b,0x0c,0x8c,0x83,0x04,0x2f,0xee,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x03,0x0c,0x08,0xc4,0x13,0x15,0x02,0x01,0x07,0x08,0x17,0x6b,0x4a,0x50,0x68,0x08,0x84,0x83,0x08,0x68,0x52,0x2f,0x3b,0x07,0xf8,0x0d,0x17,0x6d,0x4b,0x52,0x6c, 0x09,0x83,0x02,0xb6,0x2d,0x42,0x0e,0xe5,0x07,0x36,0xfd,0xf3,0x08,0x3c,0x30,0x2c,0x42,0x0d,0x04,0x00,0x00,0x03,0xfb,0xbe,0xff,0x74,0x01,0xea,0x03,0x66,0x00,0x37,0x00,0x3e,0x00,0x46,0x00,0x48,0x40,0x45,0x46,0x3c,0x3b,0x2f,0x2e,0x28,0x24,0x22,0x21,0x1d,0x1a,0x13,0x0b,0x07,0x06,0x05,0x04,0x11,0x01,0x02,0x23,0x01,0x00,0x01, 0x36,0x01,0x03,0x00,0x03,0x4c,0x3f,0x01,0x01,0x01,0x4b,0x00,0x02,0x01,0x02,0x85,0x04,0x01,0x03,0x00,0x03,0x86,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x00,0x42,0x00,0x4e,0x00,0x00,0x00,0x37,0x00,0x37,0x19,0x1f,0x11,0x05,0x09,0x19,0x2b,0x05,0x35,0x26,0x27,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x16,0x16, 0x17,0x11,0x27,0x26,0x26,0x35,0x34,0x36,0x37,0x35,0x33,0x15,0x16,0x16,0x17,0x01,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x01,0x26,0x27,0x15,0x17,0x16,0x16,0x15,0x14,0x06,0x07,0x15,0x03,0x14,0x16,0x17,0x35,0x06,0x06,0x13,0x36,0x36,0x35,0x34,0x26,0x27,0x27,0xfe,0xbb,0x79,0x69,0xfd,0xe5,0x01,0xae,0xfe,0xca,0x13, 0x21,0x08,0x09,0x21,0x12,0x01,0xc5,0x2c,0x5d,0x37,0x1b,0x4a,0x52,0x63,0x54,0x3c,0x23,0x50,0x25,0x02,0x5b,0xfe,0x52,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfd,0xf8,0x3f,0x34,0x28,0x49,0x50,0x69,0x58,0x99,0x30,0x2d,0x2c,0x31,0x99,0x31,0x36,0x30,0x2b,0x0c,0x8c,0x83,0x04,0x2f,0xee,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x03, 0x0c,0x08,0xc4,0x13,0x15,0x02,0x01,0x07,0x08,0x16,0x6c,0x4a,0x50,0x67,0x08,0x85,0x85,0x04,0x19,0x13,0xfe,0xcb,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x01,0x0a,0x20,0x08,0xf8,0x0d,0x17,0x6d,0x4b,0x52,0x6c,0x09,0x83,0x02,0xb6,0x2d,0x42,0x0e,0xe5,0x07,0x36,0xfd,0xf3,0x08,0x3c,0x30,0x2c,0x41,0x0e,0x04,0x00,0x00, 0x00,0x04,0xf9,0x43,0x00,0x00,0x02,0x03,0x02,0xda,0x00,0x1b,0x00,0x24,0x00,0x28,0x00,0x2c,0x00,0x7d,0x40,0x7a,0x1d,0x01,0x10,0x0f,0x01,0x4c,0x00,0x0e,0x04,0x03,0x04,0x0e,0x03,0x80,0x17,0x01,0x11,0x00,0x0b,0x00,0x11,0x0b,0x80,0x07,0x05,0x02,0x03,0x13,0x08,0x02,0x02,0x0f,0x03,0x02,0x68,0x14,0x01,0x0f,0x18,0x15,0x02,0x10, 0x01,0x0f,0x10,0x68,0x12,0x09,0x02,0x01,0x0c,0x0a,0x02,0x00,0x11,0x01,0x00,0x67,0x06,0x01,0x04,0x04,0x38,0x4d,0x16,0x0d,0x02,0x0b,0x0b,0x39,0x0b,0x4e,0x29,0x29,0x1c,0x1c,0x00,0x00,0x29,0x2c,0x29,0x2c,0x2b,0x2a,0x28,0x27,0x26,0x25,0x1c,0x24,0x1c,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x00,0x1b,0x00,0x1b,0x1a,0x19,0x18,0x17, 0x16,0x15,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x19,0x09,0x1f,0x2b,0x21,0x37,0x23,0x35,0x33,0x37,0x23,0x35,0x33,0x37,0x33,0x07,0x33,0x37,0x33,0x07,0x33,0x15,0x23,0x07,0x33,0x15,0x23,0x07,0x23,0x37,0x23,0x07,0x25,0x03,0x13,0x33,0x07,0x21,0x15,0x21,0x17,0x25,0x33,0x37,0x23,0x05,0x35,0x21,0x15,0xfb,0xa3, 0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0x46,0x27,0x57,0x62,0x22,0x61,0x6c,0x27,0x46,0x27,0xa0,0x27,0xfe,0x41,0xe7,0xe8,0x69,0xcb,0x01,0x69,0xfe,0x98,0xca,0x01,0x87,0xa0,0x22,0xa0,0x01,0x93,0x04,0x33,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0xd2,0x41,0xb4,0x41,0xd2,0xd2,0xd2,0x23,0x01,0x27,0x01,0x27,0xff,0x50, 0xff,0xf0,0xb4,0xa5,0x50,0x50,0x00,0x00,0x00,0x02,0xfd,0xee,0x00,0x2d,0x02,0x26,0x02,0x67,0x00,0x0b,0x00,0x18,0x00,0x3e,0x40,0x3b,0x10,0x0f,0x0e,0x03,0x01,0x02,0x14,0x01,0x00,0x01,0x18,0x0d,0x0c,0x03,0x05,0x00,0x03,0x4c,0x00,0x02,0x01,0x05,0x02,0x57,0x03,0x01,0x01,0x04,0x01,0x00,0x05,0x01,0x00,0x67,0x00,0x02,0x02,0x05, 0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x37,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0xdd,0xf1,0xf1,0x58,0xf1,0xf1,0xfe,0x67,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08, 0x09,0x22,0x11,0x01,0x36,0x2d,0xf5,0x50,0xf5,0xf5,0x50,0xf5,0x14,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0x00,0x00,0x00,0x00,0x03,0xfb,0xb4,0x00,0x2d,0x01,0xf4,0x02,0x67,0x00,0x0b,0x00,0x18,0x00,0x25,0x00,0x45,0x40,0x42,0x24,0x23,0x22,0x10,0x0f,0x0e,0x06,0x01,0x02,0x1e,0x14,0x02,0x00,0x01,0x25,0x1a, 0x19,0x18,0x0d,0x0c,0x06,0x05,0x00,0x03,0x4c,0x00,0x02,0x01,0x05,0x02,0x57,0x03,0x01,0x01,0x04,0x01,0x00,0x05,0x01,0x00,0x67,0x00,0x02,0x02,0x05,0x5f,0x06,0x01,0x05,0x02,0x05,0x4f,0x00,0x00,0x00,0x0b,0x00,0x0b,0x11,0x11,0x11,0x11,0x11,0x07,0x09,0x1b,0x2b,0x25,0x35,0x23,0x35,0x33,0x35,0x33,0x15,0x33,0x15,0x23,0x15,0x25, 0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0xfe,0xa8,0xf1,0xf1,0x58,0xf1,0xf1,0xfe,0x62,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x22,0x11,0x01,0x36,0x02,0xe4,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0xca,0x01,0xae,0x2d,0xf5, 0x50,0xf5,0xf5,0x50,0xf5,0x14,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0x5a,0x57,0x98,0x09,0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0x00,0x00,0x02,0xfe,0xcf,0xff,0xb6,0x01,0x31,0x02,0xbc,0x00,0x0d,0x00,0x11,0x00,0x08,0xb5,0x10,0x0e,0x03,0x00,0x02,0x32,0x2b,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06, 0x07,0x15,0x32,0x16,0x17,0x05,0x11,0x25,0x35,0x05,0x01,0x31,0xfd,0x9e,0x02,0x62,0xfe,0x16,0x11,0x1e,0x08,0x08,0x1e,0x11,0x01,0xea,0xfd,0x9e,0x02,0x62,0x96,0xe1,0x64,0xe1,0x5a,0xa8,0x06,0x06,0x01,0x07,0x06,0x06,0xab,0xfe,0xc7,0xe2,0x58,0xe2,0x00,0x02,0xfb,0x9b,0x00,0x23,0x01,0xd6,0x02,0x71,0x00,0x0c,0x00,0x11,0x00,0x40, 0x40,0x3d,0x11,0x01,0x02,0x06,0x07,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x00,0x04,0x03,0x06,0x04,0x67,0x02,0x01,0x00,0x00,0x03,0x5f,0x08,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x10,0x0f,0x0e,0x0d,0x00,0x0c,0x00,0x0c,0x11,0x11,0x11,0x11,0x12,0x09,0x09,0x1b,0x2b, 0x25,0x03,0x13,0x33,0x07,0x21,0x35,0x33,0x11,0x23,0x35,0x21,0x17,0x27,0x21,0x35,0x21,0x07,0xfc,0x82,0xe7,0xe8,0x69,0x6b,0x04,0xfb,0x5a,0x5a,0xfb,0x05,0x6b,0xaa,0x05,0x3a,0xfa,0xc5,0x3d,0x23,0x01,0x27,0x01,0x27,0x87,0x87,0xfd,0xb2,0x87,0x87,0xd7,0xa0,0x4f,0x00,0x00,0x01,0xfb,0x9b,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x0d, 0x00,0x6c,0xb6,0x08,0x01,0x02,0x03,0x02,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x25,0x00,0x00,0x01,0x01,0x00,0x70,0x06,0x01,0x05,0x04,0x04,0x05,0x71,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x1b,0x40,0x23,0x00,0x00,0x01,0x00,0x85,0x06,0x01, 0x05,0x04,0x05,0x86,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x04,0x04,0x03,0x57,0x00,0x03,0x03,0x04,0x5f,0x00,0x04,0x03,0x04,0x4f,0x59,0x40,0x0e,0x00,0x00,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x07,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x15,0x21,0x07,0x17,0x21,0x15,0x21,0x17,0xfc,0x82,0xe7,0xe8, 0x69,0x6b,0x05,0x82,0xfa,0x3e,0x3d,0x3e,0x05,0xc1,0xfa,0x7e,0x6b,0x23,0x01,0x27,0x01,0x27,0x87,0x50,0x4f,0x51,0x50,0x87,0x00,0x02,0xf9,0x43,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x77,0x40,0x09,0x13,0x10,0x08,0x01,0x04,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00, 0x70,0x08,0x05,0x02,0x03,0x04,0x04,0x03,0x71,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00,0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x1b,0x40,0x25,0x02,0x01,0x00,0x01,0x00,0x85,0x08,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00, 0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x59,0x40,0x12,0x00,0x00,0x12,0x11,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x09,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x17,0x27,0x21,0x37,0x27,0x21,0x07,0xfa,0x2a,0xe7,0xe8,0x69,0x6b,0x06,0xfe,0x6b,0x6a,0xe7,0xe8,0x69, 0x6b,0xf9,0x02,0x6b,0xaa,0x07,0x7d,0x41,0x42,0xf8,0x83,0x3d,0x23,0x01,0x27,0x01,0x27,0x87,0x87,0xfe,0xd9,0xfe,0xd9,0x87,0x87,0xd7,0x4f,0x51,0x4f,0x00,0x00,0x00,0x00,0x02,0xfb,0x9b,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x77,0x40,0x09,0x13,0x10,0x08,0x01,0x04,0x06,0x07,0x01,0x4c,0x4b,0xb0,0x0a,0x50,0x58, 0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00,0x70,0x08,0x05,0x02,0x03,0x04,0x04,0x03,0x71,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00,0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x1b,0x40,0x25,0x02,0x01,0x00,0x01,0x00,0x85,0x08,0x05,0x02,0x03,0x04,0x03,0x86,0x00,0x01,0x00,0x07,0x06,0x01,0x07, 0x68,0x00,0x06,0x04,0x04,0x06,0x57,0x00,0x06,0x06,0x04,0x5f,0x00,0x04,0x06,0x04,0x4f,0x59,0x40,0x12,0x00,0x00,0x12,0x11,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x09,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x27,0x33,0x13,0x03,0x23,0x37,0x21,0x17,0x27,0x21,0x37,0x27,0x21,0x07,0xfc,0x82,0xe7,0xe8,0x69, 0x6b,0x04,0xa6,0x6b,0x6a,0xe7,0xe8,0x69,0x6b,0xfb,0x5a,0x6b,0xaa,0x05,0x25,0x41,0x42,0xfa,0xdb,0x3e,0x23,0x01,0x27,0x01,0x27,0x87,0x87,0xfe,0xd9,0xfe,0xd9,0x87,0x87,0xd7,0x4f,0x51,0x4f,0x00,0x00,0x00,0x00,0x02,0xfb,0x9b,0x00,0x23,0x01,0xf4,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x42,0x40,0x3f,0x13,0x10,0x08,0x01,0x04,0x06, 0x07,0x01,0x4c,0x02,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x07,0x06,0x01,0x07,0x68,0x00,0x06,0x00,0x04,0x03,0x06,0x04,0x67,0x02,0x01,0x00,0x00,0x03,0x5f,0x08,0x05,0x02,0x03,0x00,0x03,0x4f,0x00,0x00,0x12,0x11,0x0f,0x0e,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x09,0x09,0x1b,0x2b,0x25,0x03,0x13,0x33,0x07,0x21, 0x37,0x33,0x03,0x13,0x23,0x27,0x21,0x17,0x27,0x21,0x27,0x37,0x21,0x07,0xfc,0x82,0xe7,0xe8,0x69,0x6b,0x04,0xa0,0x6a,0x69,0xe8,0xe8,0x6a,0x6a,0xfb,0x61,0x6b,0xaa,0x04,0xa0,0x3f,0x3f,0xfb,0x5f,0x3d,0x23,0x01,0x27,0x01,0x27,0x87,0x87,0xfe,0xda,0xfe,0xd8,0x87,0x87,0xd7,0x50,0x50,0x4f,0x00,0x02,0xfe,0x34,0x00,0x28,0x01,0xcc, 0x02,0x6c,0x00,0x05,0x00,0x13,0x00,0x08,0xb5,0x0e,0x06,0x03,0x00,0x02,0x32,0x2b,0x35,0x25,0x35,0x25,0x05,0x15,0x05,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x05,0x06,0x07,0x16,0x17,0xfe,0x34,0x01,0xcc,0x01,0xcc,0xfe,0x38,0x01,0x4e,0x14,0x17,0x04,0x04,0x18,0x11,0xfe,0xab,0xfe,0xb7,0x25,0x0c,0x0c,0x25,0x28,0xf0,0x64,0xf0, 0xf0,0x64,0x91,0xaa,0x0a,0x0c,0x02,0x02,0x0a,0x09,0xb0,0xac,0x13,0x03,0x03,0x13,0xff,0xff,0xfe,0x47,0x00,0x41,0x01,0xd6,0x02,0x53,0x00,0x27,0x04,0x1c,0xfd,0xf2,0x00,0x00,0x00,0x06,0x04,0x1c,0xd3,0x00,0x00,0x02,0xfb,0x9b,0x00,0x23,0x02,0x03,0x02,0x71,0x00,0x08,0x00,0x0e,0x00,0x3c,0x40,0x39,0x0d,0x0a,0x01,0x03,0x02,0x01, 0x01,0x4c,0x04,0x01,0x00,0x01,0x03,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x04,0x01,0x00,0x00,0x03,0x5f,0x07,0x05,0x06,0x03,0x03,0x00,0x03,0x4f,0x09,0x09,0x00,0x00,0x09,0x0e,0x09,0x0e,0x0c,0x0b,0x00,0x08,0x00,0x08,0x11,0x11,0x12,0x08,0x09,0x19,0x2b,0x25,0x03,0x13,0x33,0x07,0x21,0x15,0x21,0x13,0x21,0x03,0x13, 0x33,0x03,0x13,0xfd,0xae,0xe7,0xe8,0x69,0xcb,0x04,0xb6,0xfb,0x46,0xcf,0xfe,0x6a,0xe7,0xe8,0x69,0xea,0xea,0x23,0x01,0x27,0x01,0x27,0xff,0x4b,0xfe,0xfc,0x01,0x27,0x01,0x27,0xfe,0xda,0xfe,0xd8,0x00,0x00,0x00,0x02,0xfb,0x9b,0x00,0x23,0x01,0xdb,0x02,0x71,0x00,0x0d,0x00,0x13,0x00,0x47,0x40,0x44,0x12,0x0f,0x08,0x01,0x04,0x03, 0x02,0x01,0x4c,0x06,0x01,0x00,0x01,0x05,0x00,0x57,0x00,0x01,0x00,0x02,0x03,0x01,0x02,0x68,0x00,0x03,0x00,0x04,0x05,0x03,0x04,0x67,0x06,0x01,0x00,0x00,0x05,0x5f,0x09,0x07,0x08,0x03,0x05,0x00,0x05,0x4f,0x0e,0x0e,0x00,0x00,0x0e,0x13,0x0e,0x13,0x11,0x10,0x00,0x0d,0x00,0x0d,0x11,0x12,0x11,0x11,0x12,0x0a,0x09,0x1b,0x2b,0x25, 0x03,0x13,0x33,0x07,0x21,0x15,0x21,0x07,0x17,0x21,0x15,0x21,0x17,0x21,0x03,0x13,0x33,0x03,0x13,0xfd,0xae,0xe7,0xe8,0x69,0x6b,0x04,0x2e,0xfb,0x92,0x3f,0x40,0x04,0x6d,0xfb,0xd2,0x6b,0xfe,0x6a,0xe7,0xe8,0x69,0xe9,0xe9,0x23,0x01,0x27,0x01,0x27,0x87,0x50,0x4f,0x51,0x50,0x87,0x01,0x27,0x01,0x27,0xfe,0xda,0xfe,0xd8,0x00,0x00, 0xff,0xff,0xfb,0xf5,0x00,0x41,0x01,0xbd,0x02,0x53,0x00,0x27,0x04,0x1c,0xfb,0xa0,0x00,0x00,0x00,0x27,0x04,0x1c,0xfd,0xad,0x00,0x00,0x00,0x06,0x04,0x1c,0xba,0x00,0x00,0x02,0xfb,0x9b,0x00,0x23,0x02,0x12,0x02,0x71,0x00,0x4c,0x00,0x52,0x00,0xa6,0x40,0x09,0x51,0x4e,0x4b,0x01,0x04,0x02,0x09,0x01,0x4c,0x4b,0xb0,0x0d,0x50,0x58, 0x40,0x34,0x00,0x07,0x01,0x09,0x02,0x07,0x72,0x0f,0x01,0x00,0x01,0x0e,0x00,0x57,0x05,0x03,0x02,0x01,0x0d,0x0b,0x02,0x09,0x02,0x01,0x09,0x6a,0x06,0x04,0x02,0x02,0x0c,0x0a,0x02,0x08,0x0e,0x02,0x08,0x6a,0x0f,0x01,0x00,0x00,0x0e,0x5f,0x12,0x10,0x11,0x03,0x0e,0x00,0x0e,0x4f,0x1b,0x40,0x35,0x00,0x07,0x01,0x09,0x01,0x07,0x09, 0x80,0x0f,0x01,0x00,0x01,0x0e,0x00,0x57,0x05,0x03,0x02,0x01,0x0d,0x0b,0x02,0x09,0x02,0x01,0x09,0x6a,0x06,0x04,0x02,0x02,0x0c,0x0a,0x02,0x08,0x0e,0x02,0x08,0x6a,0x0f,0x01,0x00,0x00,0x0e,0x5f,0x12,0x10,0x11,0x03,0x0e,0x00,0x0e,0x4f,0x59,0x40,0x24,0x4d,0x4d,0x00,0x00,0x4d,0x52,0x4d,0x52,0x50,0x4f,0x00,0x4c,0x00,0x4c,0x4a, 0x48,0x44,0x42,0x3e,0x3c,0x38,0x36,0x32,0x30,0x23,0x12,0x24,0x24,0x24,0x24,0x24,0x21,0x12,0x13,0x09,0x1f,0x2b,0x25,0x03,0x13,0x33,0x07,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23, 0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x23,0x07,0x13,0x21,0x03,0x13,0x33,0x03,0x13,0xfd,0xae,0xe7,0xe8,0x69,0x98,0x1e,0x26,0x31,0x22,0x1c,0x1e,0x15,0x15,0x1e,0x1c,0x22,0x32,0x25,0x25,0x34,0x24,0x1d,0x1f,0x14,0x15,0x1f,0x1d,0x24,0x33,0x25,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32, 0x21,0x1b,0x1e,0x15,0x15,0x1f,0x1e,0x24,0x33,0x26,0x25,0x33,0x24,0x1d,0x1f,0x15,0x15,0x1e,0x1c,0x22,0x31,0x26,0x26,0x31,0x22,0x1c,0x1e,0x15,0x5a,0x16,0xea,0xfe,0x6a,0xe7,0xe8,0x69,0xe9,0xe9,0x23,0x01,0x27,0x01,0x27,0xbf,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a, 0x37,0x28,0x28,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1c,0xfe,0xd8,0x01,0x27,0x01,0x27,0xfe,0xda,0xfe,0xd8,0x00,0x01,0xfd,0xf3,0x00,0x23,0x02,0x12,0x02,0x71,0x00,0x3d,0x00,0xa0,0x40,0x0b,0x3c,0x01,0x07,0x03,0x01,0x4c,0x01,0x01,0x01,0x01,0x4b,0x4b, 0xb0,0x0d,0x50,0x58,0x40,0x37,0x00,0x00,0x02,0x00,0x85,0x00,0x06,0x02,0x08,0x03,0x06,0x72,0x00,0x01,0x08,0x03,0x08,0x01,0x03,0x80,0x0c,0x01,0x0b,0x07,0x0b,0x86,0x04,0x01,0x02,0x0a,0x01,0x08,0x01,0x02,0x08,0x6a,0x05,0x01,0x03,0x07,0x07,0x03,0x59,0x05,0x01,0x03,0x03,0x07,0x62,0x09,0x01,0x07,0x03,0x07,0x52,0x1b,0x40,0x38, 0x00,0x00,0x02,0x00,0x85,0x00,0x06,0x02,0x08,0x02,0x06,0x08,0x80,0x00,0x01,0x08,0x03,0x08,0x01,0x03,0x80,0x0c,0x01,0x0b,0x07,0x0b,0x86,0x04,0x01,0x02,0x0a,0x01,0x08,0x01,0x02,0x08,0x6a,0x05,0x01,0x03,0x07,0x07,0x03,0x59,0x05,0x01,0x03,0x03,0x07,0x62,0x09,0x01,0x07,0x03,0x07,0x52,0x59,0x40,0x16,0x00,0x00,0x00,0x3d,0x00, 0x3d,0x38,0x36,0x32,0x30,0x24,0x23,0x12,0x24,0x24,0x24,0x24,0x21,0x12,0x0d,0x09,0x1f,0x2b,0x25,0x03,0x13,0x33,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x02,0x07, 0x17,0xfe,0xda,0xe7,0xe8,0x69,0xeb,0x0d,0x15,0x1e,0x1c,0x22,0x32,0x25,0x25,0x34,0x24,0x1d,0x1f,0x14,0x15,0x1f,0x1d,0x24,0x33,0x25,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x21,0x1b,0x1e,0x15,0x15,0x1f,0x1e,0x24,0x33,0x26,0x25,0x33,0x24,0x1d,0x1f,0x15,0x17,0x22,0x20,0x29,0x1e,0xb6,0x23,0x01,0x27,0x01, 0x27,0xfe,0xd9,0x15,0x1f,0x1f,0x15,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x38,0x28,0x28,0x3a,0x49,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x17,0x21,0x1f,0x07,0xe6,0x00,0x00,0x00,0x00,0x03,0xfb,0xb4,0x00,0x41,0x01,0xf4,0x02,0x53,0x00,0x0c,0x00,0x19,0x00,0x4d,0x00,0xa4,0x40,0x1f, 0x18,0x02,0x02,0x01,0x07,0x12,0x08,0x02,0x04,0x01,0x19,0x01,0x02,0x02,0x04,0x03,0x4c,0x17,0x16,0x04,0x03,0x04,0x03,0x4a,0x0e,0x0d,0x0c,0x00,0x04,0x00,0x49,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x2c,0x00,0x07,0x03,0x01,0x04,0x07,0x72,0x00,0x02,0x04,0x00,0x01,0x02,0x72,0x05,0x01,0x03,0x09,0x01,0x01,0x04,0x03,0x01,0x69,0x06,0x01, 0x04,0x02,0x00,0x04,0x59,0x06,0x01,0x04,0x04,0x00,0x62,0x08,0x0a,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x2e,0x00,0x07,0x03,0x01,0x03,0x07,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x05,0x01,0x03,0x09,0x01,0x01,0x04,0x03,0x01,0x69,0x06,0x01,0x04,0x02,0x00,0x04,0x59,0x06,0x01,0x04,0x04,0x00,0x62,0x08,0x0a,0x02,0x00, 0x04,0x00,0x52,0x59,0x40,0x1b,0x1b,0x1a,0x49,0x47,0x43,0x41,0x3e,0x3d,0x3b,0x39,0x35,0x33,0x2f,0x2d,0x29,0x27,0x24,0x23,0x21,0x1f,0x1a,0x4d,0x1b,0x4d,0x0b,0x09,0x16,0x2b,0x25,0x25,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x35,0x05,0x15,0x05,0x22,0x2e,0x03, 0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0xfd,0x62,0xfe,0x52,0x01,0xae,0xfe,0xca,0x13,0x21,0x08,0x09,0x22,0x11,0x01,0x36,0x02,0xe4,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0xca, 0x01,0xae,0xfc,0x81,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x48,0x3a,0x25,0x31,0x22,0x1b,0x1e,0x15,0x15,0x1d,0x1b,0x21,0x32,0x25,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x21,0x1b,0x1e,0x15,0x15,0x1d,0x1b,0x21,0x31,0x41,0xd7,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0x99,0x5a,0x57,0x98,0x09, 0x0d,0x02,0x02,0x0e,0x08,0x99,0x5a,0xd7,0x64,0x33,0x1a,0x27,0x27,0x1a,0x37,0x28,0x28,0x3b,0x47,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x37,0x28,0x28,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x00,0x01,0xfb,0x9b,0x00,0x23,0x02,0x12,0x02,0x71,0x00,0x66,0x00,0xb3,0x40,0x0b,0x12,0x01,0x0a,0x04, 0x0f,0x06,0x02,0x03,0x0c,0x02,0x4c,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x37,0x00,0x02,0x04,0x02,0x85,0x00,0x0a,0x04,0x0c,0x03,0x0a,0x72,0x00,0x01,0x00,0x01,0x86,0x08,0x06,0x02,0x04,0x10,0x0e,0x02,0x0c,0x03,0x04,0x0c,0x69,0x09,0x07,0x05,0x03,0x03,0x00,0x00,0x03,0x59,0x09,0x07,0x05,0x03,0x03,0x03,0x00,0x62,0x0f,0x0d,0x0b,0x11, 0x04,0x00,0x03,0x00,0x52,0x1b,0x40,0x38,0x00,0x02,0x04,0x02,0x85,0x00,0x0a,0x04,0x0c,0x04,0x0a,0x0c,0x80,0x00,0x01,0x00,0x01,0x86,0x08,0x06,0x02,0x04,0x10,0x0e,0x02,0x0c,0x03,0x04,0x0c,0x69,0x09,0x07,0x05,0x03,0x03,0x00,0x00,0x03,0x59,0x09,0x07,0x05,0x03,0x03,0x03,0x00,0x62,0x0f,0x0d,0x0b,0x11,0x04,0x00,0x03,0x00,0x52, 0x59,0x40,0x29,0x01,0x00,0x62,0x60,0x5c,0x5a,0x56,0x54,0x50,0x4e,0x4a,0x48,0x44,0x42,0x3f,0x3e,0x3c,0x3a,0x36,0x34,0x30,0x2e,0x2a,0x28,0x24,0x22,0x1e,0x1c,0x18,0x16,0x11,0x10,0x0e,0x0d,0x00,0x66,0x01,0x66,0x12,0x09,0x16,0x2b,0x25,0x22,0x2e,0x03,0x27,0x06,0x06,0x07,0x16,0x16,0x17,0x17,0x23,0x03,0x13,0x33,0x07,0x1e,0x03, 0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0xfc,0xd6,0x24,0x30,0x22,0x1b,0x1b,0x13, 0x09,0x0c,0x02,0x04,0x19,0x15,0xba,0x6a,0xe7,0xe8,0x69,0xa2,0x1a,0x23,0x1c,0x1e,0x15,0x15,0x1e,0x1c,0x22,0x32,0x25,0x26,0x31,0x22,0x1c,0x1e,0x15,0x15,0x1e,0x1c,0x22,0x32,0x25,0x25,0x34,0x24,0x1d,0x1f,0x14,0x15,0x1f,0x1d,0x24,0x33,0x25,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x21,0x1b,0x1e,0x15,0x15, 0x1f,0x1e,0x24,0x33,0x26,0x25,0x33,0x24,0x1d,0x1f,0x15,0x15,0x1e,0x1c,0x22,0x31,0x26,0x26,0x31,0x22,0x1c,0x1e,0x15,0x15,0x1e,0x1c,0x22,0x31,0xe5,0x18,0x24,0x26,0x1c,0x03,0x0b,0x0d,0x03,0x04,0x1f,0x1a,0xeb,0x01,0x27,0x01,0x27,0xcc,0x0c,0x27,0x27,0x1b,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27, 0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x37,0x28,0x28,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x00,0x00,0x01,0xfe,0x2a,0xff,0x92,0x01,0xea,0x03,0x3e,0x00,0x10,0x00,0x23,0x40,0x20,0x0d,0x09,0x05,0x04,0x03,0x02,0x01,0x07, 0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x10,0x00,0x10,0x1e,0x03,0x09,0x17,0x2b,0x17,0x37,0x01,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x01,0x33,0x01,0x28,0x2b,0xfd,0xd7,0x01,0xae,0xfe,0xca,0x11,0x1c,0x07,0x07,0x1c,0x11,0x01,0xcd,0x01,0x1c,0x5f,0xfe,0x9d,0x6e, 0x71,0x01,0x15,0x64,0xd7,0x5a,0x97,0x09,0x0c,0x02,0x02,0x0c,0x09,0xe6,0x02,0xf0,0xfc,0x54,0x00,0x00,0x00,0x01,0xfb,0xf5,0xff,0x92,0x01,0xb3,0x03,0x3e,0x00,0x1d,0x00,0x2a,0x40,0x27,0x1c,0x18,0x14,0x13,0x12,0x11,0x10,0x0d,0x09,0x05,0x04,0x03,0x02,0x01,0x0e,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01, 0x76,0x00,0x00,0x00,0x1d,0x00,0x1d,0x1e,0x03,0x09,0x17,0x2b,0x05,0x37,0x01,0x35,0x25,0x15,0x05,0x06,0x06,0x07,0x16,0x16,0x17,0x05,0x01,0x33,0x07,0x01,0x15,0x05,0x35,0x25,0x36,0x36,0x37,0x26,0x26,0x27,0x25,0x01,0xfd,0xf3,0x2b,0xfd,0xd7,0x01,0xae,0xfe,0xca,0x11,0x1c,0x07,0x07,0x1c,0x11,0x01,0xcd,0x01,0x1c,0x5f,0x3d,0x02, 0x3b,0xfe,0x52,0x01,0x36,0x13,0x21,0x08,0x09,0x22,0x11,0xfe,0x20,0xfe,0xf7,0x6e,0x71,0x01,0x15,0x64,0xd7,0x5a,0x97,0x09,0x0c,0x02,0x02,0x0c,0x09,0xe6,0x02,0xf0,0xa3,0xfe,0xe1,0x64,0xd7,0x57,0x98,0x09,0x0d,0x02,0x02,0x0d,0x09,0xf0,0xfd,0x42,0x00,0x01,0xfe,0x11,0x00,0xdc,0x01,0xf4,0x01,0xb8,0x00,0x1e,0x00,0x6e,0x4b,0xb0, 0x11,0x50,0x58,0x40,0x22,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x06,0x00,0x04,0x59,0x00,0x05,0x00,0x06,0x00,0x05,0x06,0x67,0x00,0x04,0x04,0x00,0x61,0x02,0x07,0x02,0x00,0x04,0x00,0x51,0x1b,0x40,0x29,0x00,0x02,0x06,0x00,0x06,0x02,0x00,0x80,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x06,0x00,0x04,0x59, 0x00,0x05,0x00,0x06,0x02,0x05,0x06,0x67,0x00,0x04,0x04,0x00,0x61,0x07,0x01,0x00,0x04,0x00,0x51,0x59,0x40,0x15,0x01,0x00,0x1c,0x1b,0x1a,0x18,0x16,0x14,0x10,0x0e,0x0b,0x0a,0x07,0x05,0x00,0x1e,0x01,0x1e,0x08,0x09,0x16,0x2b,0x27,0x22,0x2e,0x03,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x03,0x33,0x32,0x36, 0x35,0x35,0x21,0x15,0x21,0x06,0x06,0x64,0x29,0x38,0x29,0x24,0x27,0x1b,0x1f,0x27,0x55,0x55,0x46,0x2a,0x39,0x29,0x23,0x27,0x1a,0x20,0x26,0x02,0x12,0xfe,0x2f,0x13,0x46,0xdc,0x1d,0x2b,0x2c,0x1d,0x26,0x20,0x3c,0x3c,0x41,0x50,0x1d,0x2b,0x2c,0x1d,0x28,0x1e,0x05,0x50,0x21,0x25,0x00,0x00,0x00,0x02,0xfd,0xee,0xff,0x4c,0x02,0x30, 0x02,0xe4,0x00,0x44,0x00,0x52,0x00,0xcb,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x0b,0x2e,0x19,0x02,0x0c,0x03,0x42,0x01,0x00,0x04,0x02,0x4c,0x1b,0x40,0x0b,0x2e,0x19,0x02,0x0c,0x03,0x42,0x01,0x02,0x04,0x02,0x4c,0x59,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x38,0x00,0x07,0x00,0x0c,0x01,0x07,0x0c,0x69,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69, 0x00,0x04,0x02,0x0d,0x02,0x00,0x0b,0x04,0x00,0x69,0x0e,0x01,0x0b,0x00,0x06,0x09,0x0b,0x06,0x69,0x00,0x08,0x08,0x05,0x61,0x00,0x05,0x05,0x3e,0x4d,0x00,0x09,0x09,0x0a,0x5f,0x00,0x0a,0x0a,0x3d,0x0a,0x4e,0x1b,0x40,0x3f,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x00,0x07,0x00,0x0c,0x01,0x07,0x0c,0x69,0x00,0x03,0x00,0x01,0x04, 0x03,0x01,0x69,0x00,0x04,0x0d,0x01,0x00,0x0b,0x04,0x00,0x69,0x0e,0x01,0x0b,0x00,0x06,0x09,0x0b,0x06,0x69,0x00,0x08,0x08,0x05,0x61,0x00,0x05,0x05,0x3e,0x4d,0x00,0x09,0x09,0x0a,0x5f,0x00,0x0a,0x0a,0x3d,0x0a,0x4e,0x59,0x40,0x25,0x46,0x45,0x01,0x00,0x4d,0x4b,0x45,0x52,0x46,0x52,0x3e,0x3c,0x3b,0x39,0x34,0x32,0x2c,0x2a,0x25, 0x23,0x1e,0x1c,0x17,0x15,0x11,0x0f,0x0b,0x0a,0x07,0x05,0x00,0x44,0x01,0x44,0x0f,0x09,0x16,0x2b,0x27,0x22,0x2e,0x03,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x36,0x36,0x33,0x32,0x1e,0x03,0x33,0x32,0x36,0x37,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x22,0x26,0x35,0x35,0x34,0x36,0x33,0x32,0x16,0x17,0x33,0x35, 0x34,0x26,0x23,0x22,0x06,0x15,0x11,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x26,0x35,0x35,0x06,0x06,0x05,0x32,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x15,0x14,0x16,0x62,0x31,0x45,0x32,0x29,0x2a,0x1a,0x1e,0x28,0x55,0x28,0x46,0x2b,0x2c,0x3c,0x2e,0x2a,0x33,0x24,0x39,0x4c,0x0a,0x90,0x7e,0x72,0x83,0x56,0x4a,0x49,0x57, 0x46,0x40,0x29,0x36,0x09,0x02,0x55,0x50,0x5a,0x64,0x6b,0x5d,0x6e,0x6e,0x55,0x7e,0x45,0x19,0x49,0x01,0xc5,0x26,0x2a,0x2a,0x26,0x26,0x2a,0x2a,0xfa,0x1a,0x27,0x27,0x1a,0x25,0x1c,0x3c,0x3c,0x28,0x3f,0x25,0x1a,0x27,0x27,0x1a,0x3e,0x33,0x0c,0x87,0x9b,0x83,0x72,0xfe,0xf1,0x4e,0x5b,0x58,0x47,0x74,0x4a,0x51,0x20,0x1c,0x46,0x55, 0x5a,0x74,0x68,0xfe,0xac,0x64,0x73,0x4b,0x47,0x83,0x58,0xcf,0x20,0x23,0x80,0x31,0x2b,0x75,0x2c,0x2f,0x30,0x2c,0x74,0x2b,0x31,0x00,0x00,0x00,0x00,0x01,0xfd,0xee,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x3d,0x00,0xa0,0x40,0x0b,0x01,0x01,0x01,0x05,0x01,0x4c,0x3c,0x01,0x09,0x01,0x4b,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x37,0x00,0x0a, 0x06,0x0a,0x85,0x00,0x04,0x06,0x00,0x05,0x04,0x72,0x00,0x09,0x00,0x05,0x00,0x09,0x05,0x80,0x0c,0x01,0x0b,0x01,0x0b,0x86,0x08,0x01,0x06,0x02,0x01,0x00,0x09,0x06,0x00,0x6a,0x07,0x01,0x05,0x01,0x01,0x05,0x59,0x07,0x01,0x05,0x05,0x01,0x62,0x03,0x01,0x01,0x05,0x01,0x52,0x1b,0x40,0x38,0x00,0x0a,0x06,0x0a,0x85,0x00,0x04,0x06, 0x00,0x06,0x04,0x00,0x80,0x00,0x09,0x00,0x05,0x00,0x09,0x05,0x80,0x0c,0x01,0x0b,0x01,0x0b,0x86,0x08,0x01,0x06,0x02,0x01,0x00,0x09,0x06,0x00,0x6a,0x07,0x01,0x05,0x01,0x01,0x05,0x59,0x07,0x01,0x05,0x05,0x01,0x62,0x03,0x01,0x01,0x05,0x01,0x52,0x59,0x40,0x16,0x00,0x00,0x00,0x3d,0x00,0x3d,0x3b,0x3a,0x39,0x37,0x24,0x24,0x24, 0x22,0x13,0x24,0x24,0x24,0x25,0x0d,0x09,0x1f,0x2b,0x37,0x37,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x33,0x03,0x33,0x13,0x03,0xbc,0xb6,0x1e,0x29,0x20,0x22,0x17,0x15, 0x1f,0x1d,0x24,0x32,0x26,0x25,0x34,0x24,0x1e,0x1f,0x15,0x15,0x1e,0x1b,0x21,0x31,0x26,0x3a,0x48,0x55,0x2f,0x14,0x1e,0x1b,0x22,0x32,0x25,0x25,0x33,0x24,0x1d,0x1f,0x15,0x14,0x1f,0x1d,0x24,0x34,0x25,0x26,0x31,0x22,0x1c,0x1e,0x15,0x10,0xee,0x6a,0xe7,0xe8,0x23,0xe5,0x08,0x1e,0x22,0x17,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a, 0x1a,0x27,0x27,0x1a,0x48,0x3a,0x28,0x28,0x37,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x15,0x1f,0x1f,0x15,0x01,0x27,0xfe,0xd9,0xfe,0xd9,0x00,0x00,0x01,0xfe,0x57,0x00,0xe6,0x01,0xae,0x01,0xb3,0x00,0x33,0x00,0x83,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x2c,0x00,0x07,0x03,0x01,0x04,0x07,0x72,0x00,0x02,0x04,0x00, 0x01,0x02,0x72,0x05,0x01,0x03,0x09,0x01,0x01,0x04,0x03,0x01,0x69,0x06,0x01,0x04,0x02,0x00,0x04,0x59,0x06,0x01,0x04,0x04,0x00,0x62,0x08,0x0a,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x2e,0x00,0x07,0x03,0x01,0x03,0x07,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x05,0x01,0x03,0x09,0x01,0x01,0x04,0x03,0x01,0x69,0x06,0x01, 0x04,0x02,0x00,0x04,0x59,0x06,0x01,0x04,0x04,0x00,0x62,0x08,0x0a,0x02,0x00,0x04,0x00,0x52,0x59,0x40,0x1b,0x01,0x00,0x2f,0x2d,0x29,0x27,0x24,0x23,0x21,0x1f,0x1b,0x19,0x15,0x13,0x0f,0x0d,0x0a,0x09,0x07,0x05,0x00,0x33,0x01,0x33,0x0b,0x09,0x16,0x2b,0x27,0x22,0x2e,0x03,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e, 0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x5f,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x48,0x3a,0x25,0x31,0x22,0x1b,0x1e,0x15,0x15,0x1d,0x1b,0x21,0x32,0x25,0x25,0x32,0x22,0x1b,0x1e,0x14,0x2f,0x55,0x47,0x3b,0x25,0x32,0x21,0x1b,0x1e,0x15, 0x15,0x1d,0x1b,0x21,0x31,0xe6,0x1a,0x27,0x27,0x1a,0x37,0x28,0x28,0x3b,0x47,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x37,0x28,0x28,0x3a,0x48,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x00,0x01,0xfb,0x96,0x00,0x23,0x02,0x0d,0x02,0x71,0x00,0x61,0x00,0xf7,0x40,0x0b,0x5d,0x01,0x08,0x0a,0x60,0x01,0x02,0x09, 0x00,0x02,0x4c,0x4b,0xb0,0x0d,0x50,0x58,0x40,0x38,0x00,0x10,0x0a,0x10,0x85,0x00,0x08,0x0a,0x00,0x09,0x08,0x72,0x12,0x01,0x11,0x01,0x11,0x86,0x0e,0x0c,0x02,0x0a,0x06,0x04,0x02,0x03,0x00,0x09,0x0a,0x00,0x69,0x0f,0x0d,0x0b,0x03,0x09,0x01,0x01,0x09,0x59,0x0f,0x0d,0x0b,0x03,0x09,0x09,0x01,0x62,0x07,0x05,0x03,0x03,0x01,0x09, 0x01,0x52,0x1b,0x4b,0xb0,0x17,0x50,0x58,0x40,0x39,0x00,0x10,0x0a,0x10,0x85,0x00,0x08,0x0a,0x00,0x0a,0x08,0x00,0x80,0x12,0x01,0x11,0x01,0x11,0x86,0x0e,0x0c,0x02,0x0a,0x06,0x04,0x02,0x03,0x00,0x09,0x0a,0x00,0x69,0x0f,0x0d,0x0b,0x03,0x09,0x01,0x01,0x09,0x59,0x0f,0x0d,0x0b,0x03,0x09,0x09,0x01,0x62,0x07,0x05,0x03,0x03,0x01, 0x09,0x01,0x52,0x1b,0x40,0x40,0x00,0x10,0x0a,0x10,0x85,0x00,0x08,0x0a,0x02,0x0a,0x08,0x02,0x80,0x00,0x00,0x02,0x09,0x02,0x00,0x09,0x80,0x12,0x01,0x11,0x01,0x11,0x86,0x0e,0x0c,0x02,0x0a,0x06,0x04,0x02,0x02,0x00,0x0a,0x02,0x69,0x0f,0x0d,0x0b,0x03,0x09,0x01,0x01,0x09,0x59,0x0f,0x0d,0x0b,0x03,0x09,0x09,0x01,0x62,0x07,0x05, 0x03,0x03,0x01,0x09,0x01,0x52,0x59,0x59,0x40,0x22,0x00,0x00,0x00,0x61,0x00,0x61,0x5f,0x5e,0x59,0x57,0x53,0x51,0x4d,0x4b,0x47,0x45,0x41,0x3f,0x3b,0x39,0x35,0x33,0x13,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x12,0x13,0x09,0x1f,0x2b,0x37,0x13,0x27,0x0e,0x04,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22, 0x0e,0x03,0x23,0x22,0x2e,0x03,0x23,0x22,0x0e,0x03,0x23,0x22,0x26,0x35,0x35,0x33,0x15,0x14,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x03,0x33,0x32,0x1e,0x03,0x33,0x32,0x3e,0x02,0x37,0x27,0x33,0x13,0x03,0xbc,0xee,0x12,0x14,0x1e,0x1b,0x22,0x32,0x25,0x25,0x32,0x22,0x1c, 0x1e,0x15,0x15,0x1e,0x1c,0x22,0x31,0x26,0x25,0x32,0x22,0x1c,0x1e,0x15,0x15,0x1f,0x1d,0x24,0x32,0x26,0x25,0x34,0x24,0x1e,0x1f,0x15,0x15,0x1e,0x1b,0x21,0x31,0x26,0x3a,0x48,0x55,0x2f,0x14,0x1e,0x1b,0x22,0x32,0x25,0x26,0x32,0x24,0x1d,0x1f,0x15,0x14,0x1f,0x1d,0x24,0x34,0x25,0x26,0x31,0x22,0x1c,0x1e,0x15,0x15,0x1e,0x1c,0x22, 0x32,0x25,0x26,0x31,0x22,0x1c,0x1e,0x15,0x16,0x1e,0x1d,0x24,0x1c,0xa7,0x6a,0xe7,0xe8,0x23,0x01,0x26,0x14,0x01,0x18,0x24,0x23,0x18,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x48,0x3a,0x28,0x28,0x37,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a, 0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x27,0x27,0x1a,0x1a,0x25,0x25,0x0a,0xd3,0xfe,0xd9,0xfe,0xd9,0x00,0x02,0xfe,0x39,0x00,0xaa,0x01,0x9f,0x02,0xf8,0x00,0x0e,0x00,0x12,0x00,0x3d,0x40,0x3a,0x0a,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x06,0x03,0x02,0x02,0x04,0x01,0x02,0x67,0x00, 0x04,0x05,0x05,0x04,0x57,0x00,0x04,0x04,0x05,0x5f,0x07,0x01,0x05,0x04,0x05,0x4f,0x0f,0x0f,0x00,0x00,0x0f,0x12,0x0f,0x12,0x11,0x10,0x00,0x0e,0x00,0x0e,0x11,0x11,0x11,0x08,0x09,0x19,0x2b,0x01,0x13,0x33,0x13,0x21,0x15,0x21,0x27,0x26,0x26,0x27,0x06,0x06,0x07,0x07,0x05,0x35,0x21,0x15,0xfe,0x39,0xc8,0x54,0x9b,0x01,0xaf,0xfe, 0x1b,0x77,0x0a,0x0b,0x02,0x02,0x0d,0x0b,0x7c,0x01,0x24,0x01,0xe5,0x01,0x9a,0x01,0x5e,0xfe,0xf2,0x50,0xe1,0x14,0x1e,0x07,0x07,0x1e,0x14,0xe1,0xf0,0x50,0x50,0x00,0x00,0x04,0xfd,0xf8,0x00,0xaa,0x02,0x08,0x01,0xea,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x46,0x40,0x43,0x02,0x01,0x00,0x09,0x03,0x08,0x03,0x01,0x04,0x00, 0x01,0x67,0x06,0x01,0x04,0x05,0x05,0x04,0x57,0x06,0x01,0x04,0x04,0x05,0x5f,0x0b,0x07,0x0a,0x03,0x05,0x04,0x05,0x4f,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x0c,0x0f,0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x0c,0x09,0x17,0x2b,0x01,0x35,0x21,0x15,0x33,0x35, 0x21,0x15,0x05,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0xfd,0xf8,0x01,0xcc,0x78,0x01,0xcc,0xfb,0xf0,0x01,0xcc,0x78,0x01,0xcc,0x01,0x9a,0x50,0x50,0x50,0x50,0xf0,0x50,0x50,0x50,0x50,0x00,0x00,0x06,0xfb,0xa0,0x00,0xaa,0x02,0x08,0x01,0xea,0x00,0x03,0x00,0x07,0x00,0x0b,0x00,0x0f,0x00,0x13,0x00,0x17,0x00,0x5d,0x40,0x5a,0x04,0x02, 0x02,0x00,0x0e,0x05,0x0d,0x03,0x0c,0x05,0x01,0x06,0x00,0x01,0x67,0x0a,0x08,0x02,0x06,0x07,0x07,0x06,0x57,0x0a,0x08,0x02,0x06,0x06,0x07,0x5f,0x11,0x0b,0x10,0x09,0x0f,0x05,0x07,0x06,0x07,0x4f,0x14,0x14,0x10,0x10,0x0c,0x0c,0x08,0x08,0x04,0x04,0x00,0x00,0x14,0x17,0x14,0x17,0x16,0x15,0x10,0x13,0x10,0x13,0x12,0x11,0x0c,0x0f, 0x0c,0x0f,0x0e,0x0d,0x08,0x0b,0x08,0x0b,0x0a,0x09,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x12,0x09,0x17,0x2b,0x13,0x35,0x21,0x15,0x21,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x05,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x33,0x35,0x21,0x15,0x3c,0x01,0xcc,0xf9,0x98,0x01,0xcc,0x8c,0x01,0xcc,0xfb,0xdc,0x01,0xcc,0x8c, 0x01,0xcc,0x78,0x01,0xcc,0x01,0x9a,0x50,0x50,0x50,0x50,0x50,0x50,0xf0,0x50,0x50,0x50,0x50,0x50,0x50,0x00,0x02,0x00,0x8c,0xff,0xf6,0x01,0xcc,0x02,0xda,0x00,0x0e,0x00,0x1a,0x00,0x24,0x40,0x21,0x0f,0x03,0x00,0x03,0x02,0x49,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x02,0x02,0x01,0x59,0x00,0x01,0x01,0x02,0x61,0x00,0x02,0x01,0x02, 0x51,0x2e,0x24,0x11,0x03,0x06,0x19,0x2b,0x17,0x11,0x33,0x11,0x33,0x36,0x36,0x33,0x32,0x16,0x15,0x15,0x14,0x06,0x07,0x27,0x37,0x36,0x36,0x35,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x8c,0x5a,0x01,0x06,0x36,0x29,0x3a,0x46,0x4f,0x46,0x51,0x35,0x29,0x2e,0x25,0x21,0x21,0x25,0x0a,0x02,0xe4,0xfe,0xc0,0x27,0x2f,0x54,0x47,0x55,0x43, 0x6c,0x1a,0x3a,0x14,0x10,0x40,0x2b,0x55,0x23,0x26,0x26,0x23,0x00,0x02,0x00,0x41,0x00,0x00,0x02,0x17,0x02,0xda,0x00,0x1b,0x00,0x1f,0x00,0x40,0x40,0x3d,0x0e,0x01,0x00,0x01,0x1f,0x1e,0x1d,0x1c,0x1b,0x18,0x17,0x14,0x13,0x12,0x11,0x10,0x0f,0x0d,0x0a,0x09,0x06,0x05,0x04,0x03,0x02,0x01,0x16,0x02,0x00,0x00,0x01,0x03,0x02,0x03, 0x4c,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x00,0x85,0x00,0x02,0x03,0x02,0x85,0x00,0x03,0x03,0x76,0x13,0x19,0x13,0x17,0x04,0x06,0x1a,0x2b,0x37,0x35,0x37,0x35,0x07,0x35,0x37,0x35,0x33,0x15,0x37,0x35,0x33,0x15,0x37,0x15,0x07,0x15,0x37,0x15,0x07,0x15,0x23,0x35,0x07,0x15,0x23,0x35,0x13,0x15,0x37,0x35,0x41,0x69,0x69,0x69, 0x3c,0x8c,0x3c,0x69,0x69,0x69,0x69,0x3c,0x8c,0x3c,0x3c,0x8c,0x50,0x41,0x37,0xc1,0x37,0x41,0x37,0xb6,0x96,0x49,0xa7,0x87,0x37,0x41,0x37,0xc1,0x37,0x41,0x37,0xb6,0x96,0x49,0xa7,0x87,0x01,0x22,0xc1,0x49,0xc1,0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x01,0x9a,0x01,0x77,0x02,0xd1,0x00,0x03,0x00,0x19,0x40,0x16,0x02,0x01,0x01,0x00, 0x01,0x86,0x00,0x00,0x00,0x28,0x00,0x4e,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x08,0x17,0x2b,0x13,0x13,0x33,0x03,0xa5,0x50,0x82,0x82,0x01,0x9a,0x01,0x37,0xfe,0xc9,0x00,0x00,0x00,0xff,0xff,0x00,0xd2,0xff,0x60,0x01,0x75,0x00,0x92,0x02,0x06,0x03,0x2a,0x00,0x00,0x00,0x01,0x00,0xa5,0x01,0xd1,0x01,0x77,0x03,0x08,0x00,0x03, 0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x13,0x13,0x33,0x03,0xa5,0x50,0x82,0x82,0x01,0xd1,0x01,0x37,0xfe,0xc9,0x00,0x00,0x02,0x00,0x37,0x01,0x99,0x02,0x1c,0x02,0xd0,0x00,0x03,0x00,0x07,0x00,0x2a, 0xb1,0x06,0x64,0x44,0x40,0x1f,0x02,0x01,0x00,0x01,0x00,0x85,0x05,0x03,0x04,0x03,0x01,0x01,0x76,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x13,0x33,0x03,0x21,0x13,0x33,0x03,0x01,0x4a,0x50,0x82,0x82,0xfe,0x9d,0x50,0x82,0x82,0x01,0x99,0x01,0x37, 0xfe,0xc9,0x01,0x37,0xfe,0xc9,0x00,0x00,0xff,0xff,0x00,0x8c,0x02,0x9e,0x01,0xcc,0x02,0xe9,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x01,0x9a,0x01,0x77,0x02,0xd1,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03, 0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x13,0x13,0x33,0x03,0xa5,0x50,0x82,0x82,0x01,0x9a,0x01,0x37,0xfe,0xc9,0x00,0x00,0x02,0xfe,0x25,0x02,0x89,0xff,0x83,0x03,0x09,0x00,0x0b,0x00,0x17,0x00,0x33,0xb1,0x06,0x64,0x44,0x40,0x28,0x03,0x01,0x01,0x00,0x00,0x01,0x59,0x03,0x01,0x01,0x01,0x00,0x61,0x05,0x02,0x04,0x03,0x00, 0x01,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xbd,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d, 0x1d,0x23,0x23,0x02,0x89,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x00,0x00,0x01,0xfe,0x8d,0x02,0x89,0xff,0x1b,0x03,0x09,0x00,0x0b,0x00,0x27,0xb1,0x06,0x64,0x44,0x40,0x1c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07, 0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xfe,0xd4,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x02,0x89,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x01,0xfe,0x4a,0x02,0x85,0xff,0x1c,0x03,0x11,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x27,0x33,0x17,0xfe,0xbd,0x73,0x64,0x6e,0x02,0x85,0x8c,0x8c,0x00,0x00,0x00,0x01,0xfe,0x90,0x02,0x85,0xff,0x5b,0x03,0x11,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00, 0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x37,0x33,0x07,0xfe,0x90,0x6a,0x61,0x6f,0x02,0x85,0x8c,0x8c,0x00,0x00,0x00,0x02,0xfe,0x3b,0x02,0x85,0xff,0xb8,0x03,0x11,0x00,0x03,0x00,0x07,0x00,0x32,0xb1,0x06,0x64,0x44,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00, 0x57,0x02,0x01,0x00,0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0xfe,0xee,0x6e,0x5c,0x73,0xfe,0xf6,0x6e,0x5c,0x73,0x02,0x85,0x8c,0x8c,0x8c,0x8c,0x00,0x00, 0x00,0x01,0xff,0x60,0x02,0x26,0xff,0xc3,0x02,0xda,0x00,0x03,0x00,0x19,0x40,0x16,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x00,0x38,0x01,0x4e,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x03,0x37,0x33,0x07,0xa0,0x0f,0x54,0x18,0x02,0x26,0xb4,0xb4,0x00,0x00,0x01,0xfe,0x1f,0x02,0x85,0xff,0x89,0x03,0x11,0x00,0x06, 0x00,0x27,0xb1,0x06,0x64,0x44,0x40,0x1c,0x05,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x03,0x02,0x02,0x01,0x01,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x11,0x11,0x04,0x09,0x18,0x2b,0xb1,0x06,0x00,0x44,0x01,0x37,0x33,0x17,0x23,0x27,0x07,0xfe,0x1f,0x8b,0x53,0x8c,0x63,0x52,0x50,0x02,0x85,0x8c,0x8c,0x4e,0x4e,0x00,0x00, 0x00,0x01,0xfe,0x1f,0x02,0x85,0xff,0x89,0x03,0x11,0x00,0x06,0x00,0x27,0xb1,0x06,0x64,0x44,0x40,0x1c,0x03,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x12,0x11,0x04,0x09,0x18,0x2b,0xb1,0x06,0x00,0x44,0x01,0x27,0x33,0x17,0x37,0x33,0x07,0xfe,0xab,0x8c,0x63, 0x52,0x50,0x65,0x8b,0x02,0x85,0x8c,0x4e,0x4e,0x8c,0x00,0x00,0x00,0x01,0xfe,0x34,0x02,0x80,0xff,0x74,0x03,0x11,0x00,0x0d,0x00,0x31,0xb1,0x06,0x64,0x44,0x40,0x26,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00, 0x0d,0x01,0x0d,0x05,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xfe,0xd4,0x48,0x58,0x47,0x30,0x28,0x29,0x31,0x47,0x58,0x02,0x80,0x50,0x41,0x27,0x30,0x30,0x27,0x41,0x50,0x00,0x00,0x00,0x02,0xfe,0x5c,0x02,0x60,0xff,0x4c,0x03,0x44,0x00,0x0b,0x00,0x17,0x00,0x39, 0xb1,0x06,0x64,0x44,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x01,0x22,0x26,0x35,0x34,0x36,0x33, 0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xfe,0xd4,0x36,0x42,0x42,0x36,0x36,0x42,0x42,0x36,0x1b,0x21,0x21,0x1b,0x1b,0x21,0x21,0x02,0x60,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x33,0x3f,0x35,0x21,0x1c,0x1c,0x22,0x22,0x1c,0x1c,0x21,0x00,0x00,0x00,0x00,0x01,0xfe,0x34,0x02,0x8a,0xff,0x74, 0x03,0x0c,0x00,0x19,0x00,0x6d,0xb1,0x06,0x64,0x44,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x1b,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x02,0x06,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x29,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x00, 0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x06,0x01,0x00,0x04,0x00,0x52,0x59,0x40,0x13,0x01,0x00,0x16,0x15,0x13,0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x07,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x03,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33, 0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0xe6,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x32,0x28,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x31,0x02,0x8a,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x00,0x00,0x01,0xfe,0x34,0x02,0x9e,0xff,0x74,0x02,0xe9,0x00,0x03,0x00,0x26,0xb1,0x06, 0x64,0x44,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x35,0x21,0x15,0xfe,0x34,0x01,0x40,0x02,0x9e,0x4b,0x4b,0x00,0x01,0xfe,0x7a,0x02,0x85,0xff,0x38,0x03,0x39,0x00,0x0e,0x00,0x4e,0xb1,0x06, 0x64,0x44,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x17,0x03,0x01,0x02,0x00,0x00,0x02,0x71,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x16,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0b,0x00,0x00,0x00,0x0e, 0x00,0x0e,0x21,0x24,0x04,0x09,0x18,0x2b,0xb1,0x06,0x00,0x44,0x01,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x07,0x07,0xfe,0xaa,0x32,0x0e,0x20,0x50,0x69,0x26,0x2f,0x11,0x28,0x02,0x85,0x3f,0x13,0x0d,0x14,0x41,0x27,0x23,0x20,0x16,0x34,0x00,0x00,0x00,0x02,0xfd,0xf0,0x02,0x85,0xff,0x6d,0x03,0x11,0x00,0x03, 0x00,0x07,0x00,0x25,0xb1,0x06,0x64,0x44,0x40,0x1a,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x11,0x11,0x11,0x10,0x04,0x09,0x1a,0x2b,0xb1,0x06,0x00,0x44,0x01,0x23,0x27,0x33,0x05,0x23,0x27,0x33,0xfe,0xba,0x57,0x73,0x5c,0x01,0x21,0x57,0x73,0x5c,0x02,0x85,0x8c,0x8c,0x8c, 0x00,0x01,0xfe,0x7a,0x02,0x85,0xff,0x47,0x03,0x70,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x02,0x01,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x03,0x07,0x23,0x37,0xb9,0x50,0x7d,0x82,0x03,0x70,0xeb,0xeb,0x00,0x00,0x00,0x00,0x01,0xff,0x18, 0x01,0xe5,0xff,0xa0,0x02,0x94,0x00,0x0a,0x00,0x4e,0xb1,0x06,0x64,0x44,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x17,0x00,0x01,0x00,0x00,0x01,0x70,0x00,0x00,0x02,0x02,0x00,0x59,0x00,0x00,0x00,0x02,0x62,0x03,0x01,0x02,0x00,0x02,0x52,0x1b,0x40,0x16,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x02,0x02,0x00,0x59,0x00,0x00,0x00,0x02,0x62,0x03, 0x01,0x02,0x00,0x02,0x52,0x59,0x40,0x0b,0x00,0x00,0x00,0x0a,0x00,0x09,0x12,0x21,0x04,0x09,0x18,0x2b,0xb1,0x06,0x00,0x44,0x03,0x35,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0xe8,0x1a,0x23,0x4b,0x3a,0x2f,0x01,0xe5,0x41,0x23,0x4b,0x50,0x2b,0x34,0x00,0x00,0x00,0x00,0x01,0xfe,0x8d,0xff,0x2b,0xff,0x1b,0xff,0xab,0x00,0x0b, 0x00,0x27,0xb1,0x06,0x64,0x44,0x40,0x1c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07,0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xfe,0xd4,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0xd5,0x22, 0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x02,0xfe,0x5c,0xff,0x06,0xff,0x4c,0xff,0xce,0x00,0x0b,0x00,0x17,0x00,0x39,0xb1,0x06,0x64,0x44,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c, 0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xfe,0xd4,0x36,0x42,0x42,0x36,0x36,0x42,0x42,0x37,0x1c,0x21,0x20,0x1d,0x1a,0x21,0x21,0xfa,0x37,0x2d,0x2d,0x37,0x37, 0x2d,0x2d,0x37,0x33,0x1b,0x16,0x1a,0x18,0x1b,0x17,0x16,0x1b,0x00,0x01,0xfe,0x66,0xff,0x10,0xff,0x2e,0xff,0xa1,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x05,0x37,0x33,0x07,0xfe,0x66,0x5f, 0x69,0x69,0xf0,0x91,0x91,0x00,0x00,0x00,0x00,0x01,0xfe,0x75,0xff,0x35,0xff,0x42,0x00,0x1a,0x00,0x12,0x00,0x36,0xb1,0x06,0x64,0x44,0x40,0x2b,0x0b,0x01,0x01,0x02,0x01,0x4c,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x00,0x03,0x03,0x00,0x59,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f,0x00,0x00,0x00,0x12,0x00, 0x11,0x11,0x14,0x21,0x05,0x09,0x19,0x2b,0xb1,0x06,0x00,0x44,0x05,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x33,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xfe,0x75,0x46,0x16,0x1b,0x37,0x32,0x23,0x39,0x15,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x5f,0x3d,0x03,0x14,0x24,0x1a,0x22,0x31,0x00,0x00,0x01,0xfe,0x61, 0xff,0x35,0xff,0x29,0x00,0x0a,0x00,0x10,0x00,0x2e,0xb1,0x06,0x64,0x44,0x40,0x23,0x00,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x60,0x03,0x01,0x00,0x02,0x00,0x50,0x01,0x00,0x0f,0x0d,0x07,0x06,0x00,0x10,0x01,0x10,0x04,0x09,0x16,0x2b,0xb1,0x06,0x00,0x44,0x05,0x22,0x26,0x35,0x34,0x36,0x37,0x33, 0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0xfe,0xdb,0x37,0x43,0x26,0x2f,0x4b,0x0b,0x22,0x1e,0x1e,0x19,0x3c,0xcb,0x35,0x28,0x1d,0x3a,0x21,0x09,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x00,0x00,0x01,0xfd,0x8a,0x01,0x22,0x00,0x1e,0x01,0x68,0x00,0x03,0x00,0x26,0xb1,0x06,0x64,0x44,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00, 0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x35,0x21,0x15,0xfd,0x8a,0x02,0x94,0x01,0x22,0x46,0x46,0x00,0x01,0xfd,0xcb,0xff,0xe2,0xff,0xdd,0x02,0x4e,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x05,0x01,0x33,0x01,0xfd,0xcb,0x01,0xb7,0x5b,0xfe,0x48,0x1e,0x02,0x6c,0xfd,0x94,0x00,0x00,0x00,0x00,0x01,0xfe,0x16,0xff,0x92,0xff,0x92,0x02,0x94,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01, 0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0xb1,0x06,0x00,0x44,0x05,0x01,0x33,0x01,0xfe,0x16,0x01,0x3d,0x3f,0xfe,0xc3,0x6e,0x03,0x02,0xfc,0xfe,0x00,0x00,0x00,0xff,0xff,0x00,0x7d,0x02,0x89,0x01,0xdb,0x03,0x09,0x00,0x07,0x06,0x68,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xe5,0x02,0x89,0x01,0x73, 0x03,0x09,0x00,0x07,0x06,0x69,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa2,0x02,0x85,0x01,0x74,0x03,0x11,0x00,0x07,0x06,0x6a,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xe8,0x02,0x85,0x01,0xb3,0x03,0x11,0x00,0x07,0x06,0x6b,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x93,0x02,0x85,0x02,0x10,0x03,0x11,0x00,0x07, 0x06,0x6c,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x77,0x02,0x85,0x01,0xe1,0x03,0x11,0x00,0x07,0x06,0x6e,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x77,0x02,0x85,0x01,0xe1,0x03,0x11,0x00,0x07,0x06,0x6f,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x02,0x80,0x01,0xcc,0x03,0x11,0x00,0x07,0x06,0x70,0x02,0x58, 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xb4,0x02,0x60,0x01,0xa4,0x03,0x44,0x00,0x07,0x06,0x71,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x02,0x8a,0x01,0xcc,0x03,0x0c,0x00,0x07,0x06,0x72,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x02,0x9e,0x01,0xcc,0x02,0xe9,0x00,0x07,0x06,0x73,0x02,0x58,0x00,0x00,0x00,0x00, 0xff,0xff,0x00,0xcd,0xff,0x35,0x01,0x9a,0x00,0x1a,0x00,0x07,0x06,0x7b,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xb9,0xff,0x35,0x01,0x81,0x00,0x0a,0x00,0x07,0x06,0x7c,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0x66,0xff,0x10,0xff,0x2e,0xff,0xa1,0x02,0x06,0x06,0x7a,0x00,0x00,0x00,0x02,0xfe,0x25,0x03,0x31,0xff,0x83, 0x03,0xb1,0x00,0x0b,0x00,0x17,0x00,0x2b,0x40,0x28,0x03,0x01,0x01,0x00,0x00,0x01,0x59,0x03,0x01,0x01,0x01,0x00,0x61,0x05,0x02,0x04,0x03,0x00,0x01,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0x03,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23, 0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xbd,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x03,0x31,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x00,0x00,0x01,0xfe,0x8d,0x03,0x30,0xff,0x1b,0x03,0xb0,0x00,0x0b,0x00,0x1f,0x40,0x1c, 0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07,0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xfe,0xd4,0x21,0x26,0x26,0x21,0x21,0x26,0x26,0x03,0x30,0x23,0x1d,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x00,0x01,0xfe,0x4a, 0x03,0x2a,0xff,0x1c,0x03,0xb6,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x01,0x27,0x33,0x17,0xfe,0xbd,0x73,0x64,0x6e,0x03,0x2a,0x8c,0x8c,0x00,0x00,0x00,0x01,0xfe,0x90,0x03,0x2a,0xff,0x5b,0x03,0xb6,0x00,0x03,0x00,0x17,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x01,0x37,0x33,0x07,0xfe,0x90,0x6a,0x61,0x6f,0x03,0x2a,0x8c,0x8c,0x00,0x00,0x00,0x02,0xfe,0x3b,0x03,0x2a,0xff,0xb8,0x03,0xb6,0x00,0x03,0x00,0x07,0x00,0x2a,0x40,0x27,0x02,0x01,0x00,0x01,0x01,0x00,0x57,0x02,0x01,0x00, 0x00,0x01,0x5f,0x05,0x03,0x04,0x03,0x01,0x00,0x01,0x4f,0x04,0x04,0x00,0x00,0x04,0x07,0x04,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x06,0x09,0x17,0x2b,0x01,0x37,0x33,0x07,0x21,0x37,0x33,0x07,0xfe,0xee,0x6e,0x5c,0x73,0xfe,0xf6,0x6e,0x5c,0x73,0x03,0x2a,0x8c,0x8c,0x8c,0x8c,0x00,0x00,0x00,0x01,0xfe,0x1f,0x03,0x2a,0xff,0x89, 0x03,0xb6,0x00,0x06,0x00,0x1f,0x40,0x1c,0x05,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x03,0x02,0x02,0x01,0x01,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x11,0x11,0x04,0x09,0x18,0x2b,0x01,0x37,0x33,0x17,0x23,0x27,0x07,0xfe,0x1f,0x8b,0x53,0x8c,0x63,0x52,0x50,0x03,0x2a,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x00,0x01,0xfe,0x1f, 0x03,0x2a,0xff,0x89,0x03,0xb6,0x00,0x06,0x00,0x1f,0x40,0x1c,0x03,0x01,0x02,0x00,0x01,0x4c,0x01,0x01,0x00,0x02,0x00,0x85,0x03,0x01,0x02,0x02,0x76,0x00,0x00,0x00,0x06,0x00,0x06,0x12,0x11,0x04,0x09,0x18,0x2b,0x01,0x27,0x33,0x17,0x37,0x33,0x07,0xfe,0xab,0x8c,0x63,0x52,0x50,0x65,0x8b,0x03,0x2a,0x8c,0x4e,0x4e,0x8c,0x00,0x00, 0x00,0x01,0xfe,0x34,0x03,0x25,0xff,0x74,0x03,0xb6,0x00,0x0d,0x00,0x29,0x40,0x26,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00,0x0d,0x01,0x0d,0x05,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32, 0x36,0x35,0x33,0x14,0x06,0xfe,0xd4,0x48,0x58,0x47,0x30,0x28,0x29,0x31,0x47,0x58,0x03,0x25,0x50,0x41,0x27,0x30,0x30,0x27,0x41,0x50,0x00,0x00,0x00,0x02,0xfe,0x5c,0x02,0xfe,0xff,0x4c,0x03,0xe2,0x00,0x0b,0x00,0x17,0x00,0x31,0x40,0x2e,0x00,0x01,0x00,0x03,0x02,0x01,0x03,0x69,0x05,0x01,0x02,0x00,0x00,0x02,0x59,0x05,0x01,0x02, 0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00,0x0b,0x01,0x0b,0x06,0x09,0x16,0x2b,0x01,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x27,0x32,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0xfe,0xd4,0x36,0x42,0x42,0x36,0x36,0x42,0x42,0x36,0x1b, 0x21,0x21,0x1b,0x1b,0x21,0x21,0x02,0xfe,0x3f,0x33,0x33,0x3f,0x3f,0x33,0x33,0x3f,0x35,0x21,0x1c,0x1c,0x22,0x22,0x1c,0x1c,0x21,0x00,0x00,0x00,0x00,0x01,0xfe,0x34,0x03,0x2f,0xff,0x74,0x03,0xb1,0x00,0x19,0x00,0x65,0x4b,0xb0,0x2e,0x50,0x58,0x40,0x1b,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x00,0x00,0x04,0x59, 0x00,0x04,0x04,0x00,0x62,0x02,0x06,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x29,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x06,0x01,0x00,0x04,0x00,0x52,0x59,0x40,0x13,0x01,0x00,0x16,0x15,0x13, 0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x07,0x09,0x16,0x2b,0x03,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0xe6,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x32,0x28,0x1e,0x26,0x1a,0x18,0x11,0x1e,0x41,0x31,0x03,0x2f,0x15,0x1c,0x15,0x23,0x1e, 0x1e,0x2d,0x32,0x15,0x1c,0x15,0x23,0x1e,0x1e,0x2d,0x32,0x00,0x00,0x01,0xfe,0x34,0x03,0x48,0xff,0x74,0x03,0x93,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x01,0x35,0x21,0x15,0xfe,0x34,0x01,0x40, 0x03,0x48,0x4b,0x4b,0x00,0x01,0xfe,0x7a,0x03,0x20,0xff,0x33,0x03,0xd4,0x00,0x0e,0x00,0x46,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x17,0x03,0x01,0x02,0x00,0x00,0x02,0x71,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x1b,0x40,0x16,0x03,0x01,0x02,0x00,0x02,0x86,0x00,0x01,0x00,0x00,0x01,0x57,0x00, 0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x59,0x40,0x0b,0x00,0x00,0x00,0x0e,0x00,0x0e,0x21,0x24,0x04,0x09,0x18,0x2b,0x01,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x07,0x07,0xfe,0xaa,0x2d,0x0e,0x20,0x4b,0x50,0x2f,0x3a,0x11,0x23,0x03,0x20,0x3f,0x14,0x0c,0x14,0x41,0x29,0x22,0x1c,0x19,0x34,0x00,0x00, 0x00,0x02,0xfd,0xf0,0x03,0x2a,0xff,0x6d,0x03,0xb6,0x00,0x03,0x00,0x07,0x00,0x1d,0x40,0x1a,0x03,0x01,0x01,0x00,0x00,0x01,0x57,0x03,0x01,0x01,0x01,0x00,0x5f,0x02,0x01,0x00,0x01,0x00,0x4f,0x11,0x11,0x11,0x10,0x04,0x09,0x1a,0x2b,0x01,0x23,0x27,0x33,0x05,0x23,0x27,0x33,0xfe,0xba,0x57,0x73,0x5c,0x01,0x21,0x57,0x73,0x5c,0x03, 0x2a,0x8c,0x8c,0x8c,0x00,0x01,0xfe,0x34,0x03,0x25,0xff,0x74,0x03,0xb6,0x00,0x0d,0x00,0x26,0x40,0x23,0x04,0x03,0x02,0x01,0x02,0x01,0x86,0x00,0x00,0x02,0x02,0x00,0x59,0x00,0x00,0x00,0x02,0x61,0x00,0x02,0x00,0x02,0x51,0x00,0x00,0x00,0x0d,0x00,0x0d,0x22,0x12,0x22,0x05,0x06,0x19,0x2b,0x01,0x34,0x36,0x33,0x32,0x16,0x15,0x23, 0x34,0x26,0x23,0x22,0x06,0x15,0xfe,0x34,0x58,0x48,0x48,0x58,0x47,0x31,0x29,0x28,0x30,0x03,0x25,0x41,0x50,0x50,0x41,0x27,0x30,0x30,0x27,0x00,0x00,0x01,0xfe,0x7a,0x03,0x2a,0xff,0x38,0x03,0xfc,0x00,0x03,0x00,0x1f,0x40,0x1c,0x02,0x01,0x01,0x00,0x00,0x01,0x57,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00,0x01,0x00,0x4f,0x00,0x00, 0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x03,0x07,0x23,0x37,0xc8,0x41,0x7d,0x73,0x03,0xfc,0xd2,0xd2,0x00,0x00,0x00,0x00,0x01,0xff,0x1b,0x02,0x99,0xff,0xa6,0x03,0x48,0x00,0x0b,0x00,0x3c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x12,0x00,0x01,0x00,0x00,0x01,0x70,0x03,0x01,0x02,0x02,0x00,0x61,0x00,0x00,0x00,0x38,0x02,0x4e,0x1b, 0x40,0x11,0x00,0x01,0x00,0x01,0x85,0x03,0x01,0x02,0x02,0x00,0x61,0x00,0x00,0x00,0x38,0x02,0x4e,0x59,0x40,0x0b,0x00,0x00,0x00,0x0b,0x00,0x0a,0x13,0x21,0x04,0x09,0x18,0x2b,0x03,0x35,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x23,0xe5,0x1d,0x10,0x13,0x4b,0x39,0x30,0x02,0x99,0x41,0x13,0x10,0x4b,0x50,0x2b,0x34,0x00,0x00, 0x00,0x01,0xfe,0x8d,0xff,0x2b,0xff,0x1b,0xff,0xab,0x00,0x0b,0x00,0x1f,0x40,0x1c,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x02,0x01,0x00,0x01,0x00,0x51,0x01,0x00,0x07,0x05,0x00,0x0b,0x01,0x0b,0x03,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xfe,0xd4,0x21,0x26,0x26,0x21,0x21, 0x26,0x26,0xd5,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x02,0xfe,0x25,0xff,0x2b,0xff,0x83,0xff,0xab,0x00,0x0b,0x00,0x17,0x00,0x2b,0x40,0x28,0x03,0x01,0x01,0x00,0x00,0x01,0x59,0x03,0x01,0x01,0x01,0x00,0x61,0x05,0x02,0x04,0x03,0x00,0x01,0x00,0x51,0x0d,0x0c,0x01,0x00,0x13,0x11,0x0c,0x17,0x0d,0x17,0x07,0x05,0x00, 0x0b,0x01,0x0b,0x06,0x06,0x16,0x2b,0x07,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0xbd,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xd5,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22, 0x00,0x01,0xfe,0x66,0xff,0x10,0xff,0x2e,0xff,0xa1,0x00,0x03,0x00,0x17,0x40,0x14,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x05,0x37,0x33,0x07,0xfe,0x66,0x5f,0x69,0x69,0xf0,0x91,0x91,0x00,0x00,0x00,0x00,0x01,0xfe,0x75,0xff,0x35,0xff,0x42,0x00,0x1a,0x00,0x12, 0x00,0x4e,0xb5,0x0b,0x01,0x01,0x02,0x01,0x4c,0x4b,0xb0,0x15,0x50,0x58,0x40,0x14,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x03,0x3d,0x03,0x4e,0x1b,0x40,0x19,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x00,0x03,0x03,0x00,0x59,0x00,0x00,0x00,0x03,0x5f,0x04,0x01,0x03,0x00,0x03,0x4f, 0x59,0x40,0x0c,0x00,0x00,0x00,0x12,0x00,0x11,0x11,0x14,0x21,0x05,0x09,0x19,0x2b,0x05,0x35,0x33,0x32,0x36,0x35,0x34,0x26,0x23,0x37,0x33,0x07,0x1e,0x02,0x15,0x14,0x06,0x23,0xfe,0x75,0x46,0x16,0x1b,0x37,0x32,0x23,0x39,0x15,0x1a,0x38,0x26,0x42,0x36,0xcb,0x37,0x17,0x0d,0x11,0x1a,0x5f,0x3d,0x03,0x14,0x24,0x1a,0x22,0x31,0x00, 0x00,0x01,0xfe,0x61,0xff,0x35,0xff,0x29,0x00,0x0a,0x00,0x10,0x00,0x42,0x4b,0xb0,0x15,0x50,0x58,0x40,0x11,0x00,0x01,0x02,0x01,0x85,0x00,0x02,0x02,0x00,0x60,0x03,0x01,0x00,0x00,0x3d,0x00,0x4e,0x1b,0x40,0x16,0x00,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x60,0x03,0x01,0x00,0x02,0x00,0x50,0x59, 0x40,0x0d,0x01,0x00,0x0f,0x0d,0x07,0x06,0x00,0x10,0x01,0x10,0x04,0x09,0x16,0x2b,0x05,0x22,0x26,0x35,0x34,0x36,0x37,0x33,0x07,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0xfe,0xdb,0x37,0x43,0x26,0x2f,0x4b,0x0b,0x22,0x1e,0x1e,0x19,0x3c,0xcb,0x35,0x28,0x1d,0x3a,0x21,0x09,0x1c,0x2d,0x15,0x16,0x1c,0x3c,0x00,0x00,0x01,0xfe,0x34, 0xff,0x10,0xff,0x74,0xff,0xa1,0x00,0x0d,0x00,0x29,0x40,0x26,0x03,0x01,0x01,0x02,0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00,0x0d,0x01,0x0d,0x05,0x06,0x16,0x2b,0x05,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14, 0x06,0xfe,0xd4,0x48,0x58,0x47,0x30,0x28,0x29,0x31,0x47,0x58,0xf0,0x50,0x41,0x27,0x30,0x30,0x27,0x41,0x50,0x00,0x00,0x00,0x00,0x01,0xfe,0x34,0xff,0x3d,0xff,0x74,0xff,0x88,0x00,0x03,0x00,0x1e,0x40,0x1b,0x00,0x00,0x01,0x01,0x00,0x57,0x00,0x00,0x00,0x01,0x5f,0x02,0x01,0x01,0x00,0x01,0x4f,0x00,0x00,0x00,0x03,0x00,0x03,0x11, 0x03,0x06,0x17,0x2b,0x05,0x35,0x21,0x15,0xfe,0x34,0x01,0x40,0xc3,0x4b,0x4b,0x00,0xff,0xff,0x00,0x7d,0x03,0x31,0x01,0xdb,0x03,0xb1,0x00,0x07,0x06,0x8e,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xe5,0x03,0x30,0x01,0x73,0x03,0xb0,0x00,0x07,0x06,0x8f,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xa2,0x03,0x2a,0x01,0x74, 0x03,0xb6,0x00,0x07,0x06,0x90,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xe8,0x03,0x2a,0x01,0xb3,0x03,0xb6,0x00,0x07,0x06,0x91,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x93,0x03,0x2a,0x02,0x10,0x03,0xb6,0x00,0x07,0x06,0x92,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x77,0x03,0x2a,0x01,0xe1,0x03,0xb6,0x00,0x07, 0x06,0x93,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x77,0x03,0x2a,0x01,0xe1,0x03,0xb6,0x00,0x07,0x06,0x94,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x03,0x25,0x01,0xcc,0x03,0xb6,0x00,0x07,0x06,0x95,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0xb4,0x02,0xfe,0x01,0xa4,0x03,0xe2,0x00,0x07,0x06,0x96,0x02,0x58, 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x03,0x2f,0x01,0xcc,0x03,0xb1,0x00,0x07,0x06,0x97,0x02,0x58,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x8c,0x03,0x48,0x01,0xcc,0x03,0x93,0x00,0x07,0x06,0x98,0x02,0x58,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0xd2,0x02,0x85,0x01,0xa0,0x03,0x11,0x00,0x03,0x00,0x1f,0xb1,0x06,0x64,0x44,0x40,0x14, 0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x08,0x17,0x2b,0xb1,0x06,0x00,0x44,0x13,0x37,0x33,0x07,0xd2,0x6a,0x64,0x6f,0x02,0x85,0x8c,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0xe1,0x02,0x3a,0x01,0x77,0x02,0xda,0x00,0x03,0x00,0x19,0x40,0x16,0x02,0x01,0x01,0x01,0x00,0x5f,0x00,0x00, 0x00,0x38,0x01,0x4e,0x00,0x00,0x00,0x03,0x00,0x03,0x11,0x03,0x09,0x17,0x2b,0x13,0x37,0x33,0x07,0xe1,0x38,0x5e,0x40,0x02,0x3a,0xa0,0xa0,0x00,0x00,0x03,0x00,0x7d,0x02,0x89,0x01,0xdb,0x03,0x84,0x00,0x03,0x00,0x0f,0x00,0x1b,0x00,0x77,0xb1,0x06,0x64,0x44,0x4b,0xb0,0x0a,0x50,0x58,0x40,0x24,0x00,0x00,0x03,0x03,0x00,0x70,0x06, 0x01,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x05,0x01,0x03,0x01,0x02,0x03,0x59,0x05,0x01,0x03,0x03,0x02,0x62,0x08,0x04,0x07,0x03,0x02,0x03,0x02,0x52,0x1b,0x40,0x23,0x00,0x00,0x03,0x00,0x85,0x06,0x01,0x01,0x03,0x02,0x03,0x01,0x02,0x80,0x05,0x01,0x03,0x01,0x02,0x03,0x59,0x05,0x01,0x03,0x03,0x02,0x62,0x08,0x04,0x07,0x03,0x02, 0x03,0x02,0x52,0x59,0x40,0x1a,0x11,0x10,0x05,0x04,0x00,0x00,0x17,0x15,0x10,0x1b,0x11,0x1b,0x0b,0x09,0x04,0x0f,0x05,0x0f,0x00,0x03,0x00,0x03,0x11,0x09,0x08,0x17,0x2b,0xb1,0x06,0x00,0x44,0x01,0x37,0x33,0x07,0x17,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14,0x06,0x23,0x22,0x26,0x35,0x34,0x36,0x33,0x32,0x16,0x15,0x14, 0x06,0x01,0x03,0x4e,0x50,0x58,0x52,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0xfb,0x1d,0x23,0x23,0x1d,0x1d,0x23,0x23,0x03,0x01,0x83,0x83,0x78,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x22,0x1d,0x1e,0x23,0x23,0x1e,0x1d,0x22,0x00,0x00,0x01,0xfe,0x34,0x02,0x80,0xff,0x74,0x03,0x11,0x00,0x0d,0x00,0x29,0x40,0x26,0x03,0x01,0x01,0x02, 0x01,0x85,0x00,0x02,0x00,0x00,0x02,0x59,0x00,0x02,0x02,0x00,0x61,0x04,0x01,0x00,0x02,0x00,0x51,0x01,0x00,0x0b,0x0a,0x08,0x06,0x04,0x03,0x00,0x0d,0x01,0x0d,0x05,0x06,0x16,0x2b,0x01,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xfe,0xd4,0x48,0x58,0x47,0x30,0x28,0x29,0x31,0x47,0x58,0x02,0x80,0x50,0x41, 0x27,0x30,0x30,0x27,0x41,0x50,0x00,0x00,0x00,0x02,0xfe,0x2a,0x02,0x80,0xff,0x7e,0x03,0x7a,0x00,0x03,0x00,0x11,0x00,0x3b,0x40,0x38,0x00,0x00,0x03,0x00,0x85,0x05,0x01,0x03,0x01,0x03,0x85,0x06,0x01,0x01,0x04,0x01,0x85,0x00,0x04,0x02,0x02,0x04,0x59,0x00,0x04,0x04,0x02,0x62,0x07,0x01,0x02,0x04,0x02,0x52,0x05,0x04,0x00,0x00, 0x0f,0x0e,0x0c,0x0a,0x08,0x07,0x04,0x11,0x05,0x11,0x00,0x03,0x00,0x03,0x11,0x08,0x09,0x17,0x2b,0x01,0x37,0x33,0x07,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xfe,0x95,0x73,0x60,0x78,0x1c,0x4c,0x5e,0x46,0x37,0x2d,0x2d,0x37,0x46,0x5d,0x02,0xf8,0x82,0x82,0x78,0x48,0x3a,0x1f,0x27,0x27,0x1f,0x3a, 0x48,0x00,0x00,0x00,0x00,0x02,0xfe,0x2a,0x02,0x80,0xff,0x7e,0x03,0x7a,0x00,0x03,0x00,0x11,0x00,0x3b,0x40,0x38,0x00,0x00,0x03,0x00,0x85,0x05,0x01,0x03,0x01,0x03,0x85,0x06,0x01,0x01,0x04,0x01,0x85,0x00,0x04,0x02,0x02,0x04,0x59,0x00,0x04,0x04,0x02,0x62,0x07,0x01,0x02,0x04,0x02,0x52,0x05,0x04,0x00,0x00,0x0f,0x0e,0x0c,0x0a, 0x08,0x07,0x04,0x11,0x05,0x11,0x00,0x03,0x00,0x03,0x11,0x08,0x09,0x17,0x2b,0x01,0x27,0x33,0x17,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xfe,0xb8,0x78,0x60,0x73,0x3f,0x4c,0x5e,0x46,0x37,0x2d,0x2d,0x37,0x46,0x5d,0x02,0xf8,0x82,0x82,0x78,0x48,0x3a,0x1f,0x27,0x27,0x1f,0x3a,0x48,0x00,0x00,0x00, 0x00,0x02,0xfe,0x2a,0x02,0x80,0xff,0x7e,0x03,0xa2,0x00,0x0f,0x00,0x1d,0x00,0x78,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x29,0x06,0x01,0x04,0x00,0x02,0x00,0x04,0x02,0x80,0x07,0x01,0x02,0x05,0x00,0x02,0x70,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x69,0x00,0x05,0x03,0x03,0x05,0x59,0x00,0x05,0x05,0x03,0x61,0x08,0x01,0x03,0x05,0x03,0x51, 0x1b,0x40,0x2a,0x06,0x01,0x04,0x00,0x02,0x00,0x04,0x02,0x80,0x07,0x01,0x02,0x05,0x00,0x02,0x05,0x7e,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x69,0x00,0x05,0x03,0x03,0x05,0x59,0x00,0x05,0x05,0x03,0x61,0x08,0x01,0x03,0x05,0x03,0x51,0x59,0x40,0x17,0x11,0x10,0x00,0x00,0x1b,0x1a,0x18,0x16,0x14,0x13,0x10,0x1d,0x11,0x1d,0x00,0x0f, 0x00,0x0f,0x21,0x24,0x09,0x09,0x18,0x2b,0x01,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x06,0x0f,0x02,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xfe,0xa5,0x2d,0x09,0x1b,0x37,0x41,0x2b,0x33,0x09,0x08,0x23,0x20,0x4c,0x5e,0x46,0x37,0x2d,0x2d,0x37,0x46,0x5d,0x02,0xf8,0x3d,0x0c,0x0d, 0x18,0x3c,0x27,0x20,0x0d,0x19,0x0b,0x32,0x78,0x48,0x3a,0x1f,0x27,0x27,0x1f,0x3a,0x48,0x00,0x00,0x00,0x00,0x02,0xfe,0x34,0x02,0x85,0xff,0x74,0x03,0xa0,0x00,0x19,0x00,0x27,0x00,0x95,0x4b,0xb0,0x1e,0x50,0x58,0x40,0x2d,0x09,0x01,0x07,0x00,0x08,0x00,0x07,0x08,0x80,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02, 0x0a,0x02,0x00,0x07,0x04,0x00,0x6a,0x00,0x08,0x06,0x06,0x08,0x59,0x00,0x08,0x08,0x06,0x61,0x0b,0x01,0x06,0x08,0x06,0x51,0x1b,0x40,0x3b,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02,0x04,0x00,0x04,0x02,0x00,0x80,0x09,0x01,0x07,0x00,0x08,0x00,0x07,0x08,0x80,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x0a,0x01, 0x00,0x07,0x04,0x00,0x6a,0x00,0x08,0x06,0x06,0x08,0x59,0x00,0x08,0x08,0x06,0x61,0x0b,0x01,0x06,0x08,0x06,0x51,0x59,0x40,0x1f,0x1b,0x1a,0x01,0x00,0x25,0x24,0x22,0x20,0x1e,0x1d,0x1a,0x27,0x1b,0x27,0x16,0x15,0x13,0x11,0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x0c,0x09,0x16,0x2b,0x03,0x22,0x2e,0x02,0x23,0x22,0x15, 0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0xea,0x1f,0x25,0x18,0x16,0x11,0x1e,0x41,0x34,0x2a,0x20,0x25,0x17,0x16,0x11,0x1e,0x41,0x34,0x6c,0x48,0x58,0x41,0x34,0x2a,0x2b,0x35,0x41,0x58,0x03,0x2c,0x13,0x19,0x13, 0x1e,0x19,0x14,0x28,0x30,0x13,0x19,0x13,0x1e,0x19,0x14,0x28,0x30,0xa7,0x48,0x3a,0x1f,0x28,0x28,0x1f,0x3a,0x48,0x00,0x00,0x00,0x02,0xfe,0x20,0x02,0x85,0x00,0x19,0x03,0x84,0x00,0x03,0x00,0x0a,0x00,0x33,0x40,0x30,0x09,0x01,0x03,0x01,0x01,0x4c,0x00,0x00,0x02,0x00,0x85,0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x01,0x03,0x01,0x85, 0x06,0x04,0x02,0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04,0x0a,0x04,0x0a,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x07,0x09,0x17,0x2b,0x03,0x37,0x33,0x07,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xbe,0x73,0x64,0x78,0xfe,0x7f,0x8a,0x54,0x8b,0x65,0x50,0x51,0x02,0xf8,0x8c,0x8c,0x73,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x02,0xfe,0x20, 0x02,0x85,0xff,0xc9,0x03,0x84,0x00,0x03,0x00,0x0a,0x00,0x3f,0x40,0x3c,0x09,0x01,0x03,0x01,0x01,0x4c,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x80,0x05,0x01,0x01,0x03,0x00,0x01,0x03,0x7e,0x00,0x00,0x02,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x06,0x04,0x02,0x03,0x00,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x0a,0x04,0x0a,0x08,0x07, 0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x07,0x09,0x17,0x2b,0x03,0x27,0x33,0x17,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0x96,0x82,0x64,0x7d,0xfe,0x57,0x8a,0x54,0x8b,0x65,0x50,0x51,0x02,0xf8,0x8c,0x8c,0x73,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x02,0xfe,0x20,0x02,0x85,0xff,0xce,0x03,0xa2,0x00,0x0e,0x00,0x15,0x00,0x75,0xb5,0x14,0x01,0x04, 0x02,0x01,0x4c,0x4b,0xb0,0x0c,0x50,0x58,0x40,0x25,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x06,0x01,0x02,0x04,0x00,0x02,0x70,0x07,0x05,0x02,0x04,0x04,0x84,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x1b,0x40,0x26,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x06,0x01,0x02,0x04,0x00,0x02, 0x04,0x7e,0x07,0x05,0x02,0x04,0x04,0x84,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x59,0x40,0x15,0x0f,0x0f,0x00,0x00,0x0f,0x15,0x0f,0x15,0x13,0x12,0x11,0x10,0x00,0x0e,0x00,0x0e,0x21,0x24,0x08,0x09,0x18,0x2b,0x03,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x07,0x07, 0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xb1,0x2d,0x09,0x20,0x32,0x37,0x2e,0x36,0x11,0x23,0xfe,0x86,0x8a,0x54,0x8b,0x65,0x50,0x51,0x02,0xf8,0x3d,0x0e,0x0a,0x19,0x3c,0x28,0x23,0x15,0x18,0x32,0x73,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x00,0x02,0xfe,0x20,0x02,0x85,0xff,0x89,0x03,0xa0,0x00,0x19,0x00,0x20,0x00,0x92,0xb5,0x1f,0x01,0x07, 0x06,0x01,0x4c,0x4b,0xb0,0x1e,0x50,0x58,0x40,0x29,0x00,0x06,0x00,0x07,0x00,0x06,0x07,0x80,0x0a,0x08,0x02,0x07,0x07,0x84,0x05,0x01,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x00,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x02,0x09,0x02,0x00,0x04,0x00,0x52,0x1b,0x40,0x37,0x00,0x05,0x03,0x01,0x03,0x05,0x01,0x80,0x00,0x02, 0x04,0x00,0x04,0x02,0x00,0x80,0x00,0x06,0x00,0x07,0x00,0x06,0x07,0x80,0x0a,0x08,0x02,0x07,0x07,0x84,0x00,0x03,0x00,0x01,0x04,0x03,0x01,0x69,0x00,0x04,0x02,0x00,0x04,0x59,0x00,0x04,0x04,0x00,0x62,0x09,0x01,0x00,0x04,0x00,0x52,0x59,0x40,0x1d,0x1a,0x1a,0x01,0x00,0x1a,0x20,0x1a,0x20,0x1e,0x1d,0x1c,0x1b,0x16,0x15,0x13,0x11, 0x0e,0x0c,0x09,0x08,0x06,0x04,0x00,0x19,0x01,0x19,0x0b,0x09,0x16,0x2b,0x03,0x22,0x2e,0x02,0x23,0x22,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x35,0x35,0x33,0x15,0x14,0x06,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xea,0x1f,0x25,0x18,0x16,0x11,0x1e,0x41,0x34,0x2a,0x20,0x25,0x17,0x16,0x11,0x1e,0x41,0x34,0xfe, 0xe0,0x8a,0x54,0x8b,0x65,0x50,0x51,0x03,0x2c,0x13,0x19,0x13,0x1e,0x19,0x14,0x28,0x30,0x13,0x19,0x13,0x1e,0x19,0x14,0x28,0x30,0xa7,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x00,0x02,0xfe,0x2f,0x03,0x0c,0xff,0x79,0x03,0xfc,0x00,0x03,0x00,0x13,0x00,0x3b,0x40,0x38,0x00,0x00,0x03,0x00,0x85,0x05,0x01,0x03,0x01,0x03,0x85,0x06,0x01,0x01, 0x04,0x01,0x85,0x00,0x04,0x02,0x02,0x04,0x59,0x00,0x04,0x04,0x02,0x62,0x07,0x01,0x02,0x04,0x02,0x52,0x05,0x04,0x00,0x00,0x10,0x0f,0x0d,0x0a,0x08,0x07,0x04,0x13,0x05,0x12,0x00,0x03,0x00,0x03,0x11,0x08,0x09,0x17,0x2b,0x01,0x37,0x33,0x07,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0xfe, 0x95,0x69,0x60,0x6e,0x35,0x40,0x4c,0x46,0x26,0x20,0x31,0x21,0x26,0x46,0x4c,0x41,0x03,0x84,0x78,0x78,0x78,0x46,0x3c,0x20,0x26,0x26,0x20,0x3c,0x46,0x00,0x00,0x00,0x00,0x02,0xfe,0x2f,0x03,0x0c,0xff,0x79,0x03,0xfc,0x00,0x03,0x00,0x13,0x00,0x3b,0x40,0x38,0x00,0x00,0x03,0x00,0x85,0x05,0x01,0x03,0x01,0x03,0x85,0x06,0x01,0x01, 0x04,0x01,0x85,0x00,0x04,0x02,0x02,0x04,0x59,0x00,0x04,0x04,0x02,0x62,0x07,0x01,0x02,0x04,0x02,0x52,0x05,0x04,0x00,0x00,0x10,0x0f,0x0d,0x0a,0x08,0x07,0x04,0x13,0x05,0x12,0x00,0x03,0x00,0x03,0x11,0x08,0x09,0x17,0x2b,0x01,0x27,0x33,0x17,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33,0x32,0x36,0x35,0x33,0x14,0x06,0x23,0xfe, 0xb8,0x64,0x60,0x5f,0x58,0x40,0x4c,0x46,0x26,0x20,0x31,0x21,0x26,0x46,0x4c,0x41,0x03,0x84,0x78,0x78,0x78,0x46,0x3c,0x20,0x26,0x26,0x20,0x3c,0x46,0x00,0x00,0x00,0x00,0x02,0xfe,0x2f,0x03,0x0c,0xff,0x79,0x03,0xfc,0x00,0x0f,0x00,0x1f,0x00,0x78,0x4b,0xb0,0x0f,0x50,0x58,0x40,0x29,0x06,0x01,0x04,0x00,0x02,0x00,0x04,0x02,0x80, 0x07,0x01,0x02,0x05,0x00,0x02,0x70,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x05,0x03,0x03,0x05,0x59,0x00,0x05,0x05,0x03,0x61,0x08,0x01,0x03,0x05,0x03,0x51,0x1b,0x40,0x2a,0x06,0x01,0x04,0x00,0x02,0x00,0x04,0x02,0x80,0x07,0x01,0x02,0x05,0x00,0x02,0x05,0x7e,0x00,0x01,0x00,0x00,0x04,0x01,0x00,0x67,0x00,0x05,0x03,0x03, 0x05,0x59,0x00,0x05,0x05,0x03,0x61,0x08,0x01,0x03,0x05,0x03,0x51,0x59,0x40,0x17,0x11,0x10,0x00,0x00,0x1c,0x1b,0x19,0x16,0x14,0x13,0x10,0x1f,0x11,0x1e,0x00,0x0f,0x00,0x0f,0x21,0x24,0x09,0x09,0x18,0x2b,0x01,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x06,0x0f,0x02,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33, 0x32,0x36,0x35,0x33,0x14,0x06,0x23,0xfe,0xa6,0x2f,0x07,0x0a,0x49,0x61,0x1a,0x1d,0x08,0x08,0x20,0x36,0x40,0x4c,0x46,0x26,0x20,0x31,0x21,0x26,0x46,0x4c,0x41,0x03,0x70,0x38,0x08,0x08,0x08,0x3c,0x19,0x17,0x0d,0x1c,0x0b,0x28,0x64,0x46,0x3c,0x20,0x26,0x26,0x20,0x3c,0x46,0x00,0x00,0x00,0x00,0x02,0xfe,0x2f,0x03,0x0c,0xff,0x79, 0x03,0xfc,0x00,0x1b,0x00,0x2b,0x00,0x55,0x40,0x52,0x18,0x16,0x02,0x03,0x02,0x0a,0x08,0x02,0x00,0x01,0x02,0x4c,0x07,0x01,0x05,0x00,0x06,0x00,0x05,0x06,0x80,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x03,0x08,0x01,0x00,0x05,0x03,0x00,0x69,0x00,0x06,0x04,0x04,0x06,0x59,0x00,0x06,0x06,0x04,0x61,0x09,0x01,0x04,0x06,0x04, 0x51,0x1d,0x1c,0x01,0x00,0x28,0x27,0x25,0x22,0x20,0x1f,0x1c,0x2b,0x1d,0x2a,0x14,0x12,0x0f,0x0d,0x06,0x04,0x00,0x1b,0x01,0x1b,0x0a,0x09,0x16,0x2b,0x03,0x22,0x2e,0x02,0x23,0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x07,0x22,0x26,0x35,0x33,0x14,0x16,0x33,0x33, 0x32,0x36,0x35,0x33,0x14,0x06,0x23,0xdf,0x1f,0x2a,0x1e,0x1b,0x11,0x0d,0x11,0x41,0x31,0x29,0x20,0x29,0x1d,0x1a,0x11,0x0e,0x10,0x41,0x2f,0x8f,0x40,0x4c,0x46,0x26,0x20,0x31,0x21,0x26,0x46,0x4c,0x41,0x03,0x98,0x0e,0x13,0x0e,0x10,0x0e,0x07,0x07,0x26,0x2d,0x0e,0x13,0x0e,0x11,0x0d,0x07,0x07,0x26,0x2d,0x8c,0x3c,0x3c,0x20,0x1c, 0x1c,0x20,0x3c,0x3c,0x00,0x02,0xfe,0x20,0x03,0x0c,0x00,0x0f,0x03,0xfc,0x00,0x03,0x00,0x0a,0x00,0x33,0x40,0x30,0x09,0x01,0x03,0x01,0x01,0x4c,0x00,0x00,0x02,0x00,0x85,0x00,0x02,0x01,0x02,0x85,0x05,0x01,0x01,0x03,0x01,0x85,0x06,0x04,0x02,0x03,0x03,0x76,0x04,0x04,0x00,0x00,0x04,0x0a,0x04,0x0a,0x08,0x07,0x06,0x05,0x00,0x03, 0x00,0x03,0x11,0x07,0x09,0x17,0x2b,0x03,0x37,0x33,0x07,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xc0,0x69,0x66,0x6e,0xfe,0x7f,0x8a,0x54,0x8b,0x65,0x50,0x51,0x03,0x84,0x78,0x78,0x78,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x02,0xfe,0x20,0x03,0x0c,0xff,0xc4,0x03,0xfc,0x00,0x03,0x00,0x0a,0x00,0x3f,0x40,0x3c,0x09,0x01,0x03,0x01,0x01,0x4c, 0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x80,0x05,0x01,0x01,0x03,0x00,0x01,0x03,0x7e,0x00,0x00,0x02,0x03,0x00,0x57,0x00,0x00,0x00,0x03,0x5f,0x06,0x04,0x02,0x03,0x00,0x03,0x4f,0x04,0x04,0x00,0x00,0x04,0x0a,0x04,0x0a,0x08,0x07,0x06,0x05,0x00,0x03,0x00,0x03,0x11,0x07,0x09,0x17,0x2b,0x03,0x27,0x33,0x17,0x05,0x37,0x33,0x17,0x23, 0x27,0x07,0x9b,0x78,0x64,0x73,0xfe,0x5c,0x8a,0x54,0x8b,0x65,0x50,0x51,0x03,0x84,0x78,0x78,0x78,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x02,0xfe,0x20,0x03,0x0c,0xff,0xce,0x03,0xfc,0x00,0x0e,0x00,0x15,0x00,0x75,0xb5,0x14,0x01,0x04,0x02,0x01,0x4c,0x4b,0xb0,0x0f,0x50,0x58,0x40,0x25,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x06,0x01, 0x02,0x04,0x00,0x02,0x70,0x07,0x05,0x02,0x04,0x04,0x84,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x61,0x00,0x00,0x01,0x00,0x51,0x1b,0x40,0x26,0x00,0x03,0x00,0x02,0x00,0x03,0x02,0x80,0x06,0x01,0x02,0x04,0x00,0x02,0x04,0x7e,0x07,0x05,0x02,0x04,0x04,0x84,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x01,0x00,0x61,0x00, 0x00,0x01,0x00,0x51,0x59,0x40,0x15,0x0f,0x0f,0x00,0x00,0x0f,0x15,0x0f,0x15,0x13,0x12,0x11,0x10,0x00,0x0e,0x00,0x0e,0x21,0x24,0x08,0x09,0x18,0x2b,0x03,0x37,0x36,0x35,0x34,0x23,0x23,0x35,0x33,0x32,0x16,0x15,0x14,0x07,0x07,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xb4,0x30,0x08,0x0f,0x42,0x55,0x20,0x26,0x10,0x24,0xfe,0x86,0x8a, 0x54,0x8b,0x65,0x50,0x51,0x03,0x70,0x2f,0x08,0x0b,0x10,0x3a,0x22,0x1c,0x1c,0x10,0x22,0x64,0x8c,0x8c,0x4e,0x4e,0x00,0x00,0x00,0x02,0xfe,0x20,0x03,0x0c,0xff,0x88,0x03,0xfc,0x00,0x1b,0x00,0x22,0x00,0x53,0x40,0x50,0x18,0x16,0x02,0x03,0x02,0x0a,0x08,0x02,0x00,0x01,0x21,0x01,0x05,0x04,0x03,0x4c,0x00,0x04,0x00,0x05,0x00,0x04, 0x05,0x80,0x08,0x06,0x02,0x05,0x05,0x84,0x00,0x03,0x01,0x00,0x03,0x59,0x00,0x02,0x00,0x01,0x00,0x02,0x01,0x69,0x00,0x03,0x03,0x00,0x61,0x07,0x01,0x00,0x03,0x00,0x51,0x1c,0x1c,0x01,0x00,0x1c,0x22,0x1c,0x22,0x20,0x1f,0x1e,0x1d,0x14,0x12,0x0f,0x0d,0x06,0x04,0x00,0x1b,0x01,0x1b,0x09,0x09,0x16,0x2b,0x03,0x22,0x2e,0x02,0x23, 0x22,0x06,0x15,0x15,0x23,0x35,0x34,0x36,0x33,0x32,0x1e,0x02,0x33,0x32,0x36,0x35,0x35,0x33,0x15,0x14,0x06,0x05,0x37,0x33,0x17,0x23,0x27,0x07,0xdf,0x1f,0x2a,0x1e,0x1b,0x11,0x0d,0x11,0x41,0x31,0x29,0x20,0x29,0x1d,0x1a,0x11,0x0e,0x10,0x41,0x2f,0xfe,0xd6,0x74,0x80,0x74,0x65,0x4f,0x51,0x03,0x98,0x0e,0x13,0x0e,0x10,0x0e,0x07, 0x07,0x26,0x2d,0x0e,0x13,0x0e,0x11,0x0d,0x07,0x07,0x26,0x2d,0x8c,0x6e,0x6e,0x49,0x49,0x00,0x00,0x00,0x00,0x02,0x00,0x5a,0xfe,0xf2,0x02,0x58,0x03,0xca,0x00,0x03,0x00,0x1a,0x00,0x2a,0x40,0x27,0x0f,0x01,0x01,0x00,0x03,0x00,0x02,0x03,0x01,0x02,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x03,0x01,0x85,0x04,0x01,0x03,0x03, 0x76,0x04,0x04,0x04,0x1a,0x04,0x1a,0x12,0x1b,0x11,0x05,0x06,0x19,0x2b,0x13,0x11,0x33,0x11,0x03,0x11,0x34,0x36,0x37,0x37,0x36,0x36,0x35,0x35,0x23,0x37,0x17,0x23,0x15,0x14,0x06,0x07,0x07,0x06,0x06,0x15,0x11,0x5a,0x78,0x78,0x2c,0x25,0x91,0x19,0x1d,0x6e,0xaa,0xaa,0x6e,0x28,0x20,0x9b,0x19,0x1c,0x01,0x6c,0x02,0x5e,0xfd,0xfb, 0xfd,0x2d,0x01,0x7d,0x2c,0x59,0x1b,0x6c,0x12,0x2d,0x13,0xaa,0xaa,0xaa,0xb4,0x25,0x4b,0x18,0x73,0x13,0x34,0x1d,0xfe,0x8e,0x00,0x02,0x00,0x69,0xff,0x42,0x01,0xef,0x03,0x7a,0x00,0x05,0x00,0x1e,0x00,0x47,0x40,0x44,0x00,0x00,0x01,0x00,0x85,0x00,0x01,0x09,0x01,0x02,0x03,0x01,0x02,0x67,0x05,0x01,0x03,0x00,0x07,0x04,0x03,0x07, 0x67,0x00,0x04,0x06,0x06,0x04,0x57,0x00,0x04,0x04,0x06,0x5f,0x0a,0x08,0x02,0x06,0x04,0x06,0x4f,0x06,0x06,0x00,0x00,0x06,0x1e,0x06,0x1e,0x1a,0x19,0x15,0x14,0x13,0x12,0x0d,0x0c,0x08,0x07,0x00,0x05,0x00,0x05,0x11,0x11,0x0b,0x06,0x18,0x2b,0x13,0x11,0x33,0x11,0x33,0x15,0x03,0x11,0x33,0x13,0x16,0x16,0x17,0x33,0x32,0x26,0x26, 0x35,0x11,0x33,0x11,0x23,0x03,0x26,0x26,0x27,0x23,0x16,0x16,0x15,0x11,0x69,0x50,0xdd,0xf1,0x5d,0x81,0x0c,0x15,0x05,0x0a,0x01,0x08,0x08,0x4b,0x5c,0x80,0x0c,0x17,0x06,0x0a,0x05,0x0b,0x01,0x90,0x01,0xea,0xfe,0x61,0x4b,0xfd,0xb2,0x01,0xea,0xfe,0xdb,0x1c,0x47,0x17,0x30,0x41,0x1b,0x01,0x13,0xfe,0x16,0x01,0x25,0x1c,0x47,0x17, 0x1b,0x51,0x20,0xfe,0xed,0x00,0x00,0x00,0x00,0x03,0x00,0x32,0xff,0xb0,0x02,0x26,0x03,0x6b,0x00,0x1a,0x00,0x23,0x00,0x32,0x00,0x44,0x40,0x41,0x32,0x26,0x02,0x06,0x07,0x01,0x4c,0x00,0x02,0x00,0x05,0x01,0x02,0x05,0x69,0x04,0x03,0x02,0x01,0x00,0x07,0x06,0x01,0x07,0x69,0x00,0x06,0x00,0x00,0x06,0x57,0x00,0x06,0x06,0x00,0x5f, 0x08,0x01,0x00,0x06,0x00,0x4f,0x01,0x00,0x2d,0x2b,0x25,0x24,0x21,0x1f,0x1c,0x1b,0x14,0x12,0x0e,0x0c,0x08,0x06,0x00,0x1a,0x01,0x19,0x09,0x06,0x16,0x2b,0x17,0x22,0x26,0x35,0x11,0x34,0x36,0x33,0x33,0x35,0x34,0x36,0x36,0x33,0x32,0x16,0x16,0x15,0x15,0x33,0x32,0x16,0x15,0x11,0x14,0x06,0x23,0x01,0x33,0x35,0x34,0x26,0x23,0x22, 0x06,0x15,0x13,0x33,0x35,0x36,0x36,0x35,0x34,0x26,0x23,0x22,0x06,0x15,0x14,0x16,0x17,0x6e,0x19,0x23,0x23,0x19,0x0a,0x30,0x51,0x33,0x35,0x51,0x2e,0x0a,0x19,0x23,0x23,0x19,0xfe,0xde,0xc8,0x37,0x2d,0x2d,0x37,0x37,0x59,0x12,0x26,0x37,0x2d,0x2d,0x37,0x25,0x12,0x50,0x23,0x19,0x01,0xb2,0x19,0x23,0xe7,0x33,0x4d,0x2a,0x2c,0x4c, 0x32,0xe7,0x23,0x19,0xfe,0x4e,0x19,0x23,0x02,0x2b,0xe6,0x2d,0x37,0x37,0x2d,0xfd,0x71,0xa0,0x07,0x28,0x22,0x28,0x31,0x31,0x28,0x22,0x28,0x07,0x00,0x01,0xff,0xd8,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x04,0x00,0x17,0x40,0x14,0x04,0x01,0x00,0x01,0x01,0x4c,0x00,0x01,0x00,0x01,0x85,0x00,0x00,0x00,0x76,0x11,0x10,0x02,0x06,0x18, 0x2b,0x13,0x23,0x11,0x33,0x01,0x0a,0x32,0x32,0x02,0x4e,0xfe,0xd4,0x05,0x28,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b, 0x11,0x01,0x01,0x33,0x01,0x01,0x01,0xe2,0xfe,0x24,0x70,0x01,0xe2,0xfe,0x1e,0xfe,0xd4,0x02,0x92,0x02,0x96,0xfd,0x6c,0xfd,0x6c,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x80,0x03,0xfc,0x00,0x04,0x00,0x1d,0x40,0x1a,0x01,0x01,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00,0x04, 0x00,0x04,0x12,0x03,0x06,0x17,0x2b,0x09,0x02,0x33,0x11,0x02,0x4e,0xfd,0xb2,0x02,0x4e,0x32,0xfe,0xd4,0x02,0x94,0x02,0x94,0xfa,0xd8,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0xd4,0x02,0x58,0x03,0xfc,0x00,0x05,0x00,0x1e,0x40,0x1b,0x04,0x01,0x02,0x01,0x00,0x01,0x4c,0x00,0x00,0x01,0x00,0x85,0x02,0x01,0x01,0x01,0x76,0x00,0x00,0x00, 0x05,0x00,0x05,0x12,0x03,0x06,0x17,0x2b,0x09,0x02,0x33,0x01,0x01,0x01,0xe2,0xfe,0x1e,0x01,0xe2,0x70,0xfe,0x24,0x01,0xe2,0xfe,0xd4,0x02,0x94,0x02,0x94,0xfd,0x6a,0xfd,0x6e,0x00,0x00,0x00,0x01,0x00,0x55,0xff,0x35,0x02,0x2b,0x02,0x26,0x00,0x19,0x00,0x5f,0x4b,0xb0,0x15,0x50,0x58,0x40,0x22,0x00,0x01,0x01,0x02,0x5f,0x00,0x02, 0x02,0x3b,0x4d,0x03,0x01,0x00,0x00,0x04,0x5f,0x08,0x07,0x02,0x04,0x04,0x39,0x4d,0x00,0x05,0x05,0x06,0x5f,0x00,0x06,0x06,0x3d,0x06,0x4e,0x1b,0x40,0x1f,0x00,0x05,0x00,0x06,0x05,0x06,0x63,0x00,0x01,0x01,0x02,0x5f,0x00,0x02,0x02,0x3b,0x4d,0x03,0x01,0x00,0x00,0x04,0x5f,0x08,0x07,0x02,0x04,0x04,0x39,0x04,0x4e,0x59,0x40,0x10, 0x00,0x00,0x00,0x19,0x00,0x19,0x21,0x25,0x11,0x11,0x11,0x11,0x11,0x09,0x09,0x1d,0x2b,0x33,0x35,0x33,0x11,0x23,0x35,0x21,0x11,0x33,0x15,0x23,0x06,0x06,0x15,0x14,0x16,0x33,0x33,0x15,0x23,0x22,0x26,0x35,0x34,0x36,0x37,0x55,0xc3,0xaf,0x01,0x09,0xb9,0xcf,0x21,0x1e,0x1e,0x19,0x3c,0x4e,0x37,0x43,0x20,0x27,0x52,0x01,0x82,0x52, 0xfe,0x2c,0x52,0x1b,0x2d,0x15,0x16,0x1c,0x3c,0x35,0x28,0x1a,0x36,0x1e,0x00,0x00,0xff,0xff,0x00,0x55,0xff,0x2b,0x02,0x2b,0x02,0x26,0x02,0x26,0x01,0x00,0x00,0x00,0x00,0x07,0x06,0x78,0x02,0x67,0x00,0x00,0x00,0x00,0x00,0x16,0x01,0x0e,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00, 0x01,0x01,0x00,0x13,0x00,0x14,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x17,0x00,0x27,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x0b,0x00,0x3e,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x00,0x00,0xbc,0x00,0x49,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x01,0x00,0x1c,0x01,0x05,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x02,0x00,0x0e, 0x01,0x21,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x03,0x00,0x3c,0x01,0x2f,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x04,0x00,0x2c,0x01,0x6b,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x05,0x00,0x54,0x01,0x97,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x06,0x00,0x2a,0x01,0xeb,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x07,0x00,0x62,0x02,0x15,0x00,0x03, 0x00,0x01,0x04,0x09,0x00,0x08,0x00,0x12,0x02,0x77,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x09,0x00,0x4a,0x02,0x89,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0b,0x00,0x32,0x02,0xd3,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0c,0x00,0x32,0x03,0x05,0x00,0x03,0x00,0x01,0x04,0x09,0x00,0x0d,0x01,0x22,0x03,0x37,0x00,0x03,0x00,0x01,0x04,0x09, 0x00,0x0e,0x00,0x36,0x04,0x59,0x00,0x03,0x00,0x01,0x04,0x09,0x01,0x00,0x00,0x28,0x04,0x8f,0x00,0x03,0x00,0x01,0x04,0x09,0x01,0x01,0x00,0x26,0x04,0xb7,0x00,0x03,0x00,0x01,0x04,0x09,0x01,0x02,0x00,0x2e,0x04,0xdd,0x00,0x03,0x00,0x01,0x04,0x09,0x01,0x03,0x00,0x16,0x05,0x0b,0x43,0x6c,0x61,0x73,0x73,0x69,0x63,0x20,0x63,0x6f, 0x6e,0x73,0x74,0x72,0x75,0x63,0x74,0x69,0x6f,0x6e,0x43,0x6c,0x6f,0x73,0x65,0x64,0x20,0x63,0x6f,0x6e,0x73,0x74,0x72,0x75,0x63,0x74,0x69,0x6f,0x6e,0x42,0x72,0x6f,0x6b,0x65,0x6e,0x20,0x65,0x71,0x75,0x61,0x6c,0x73,0x20,0x6c,0x69,0x67,0x61,0x74,0x75,0x72,0x65,0x73,0x52,0x61,0x73,0x65,0x64,0x20,0x62,0x61,0x72,0x20,0x66,0x00, 0x43,0x00,0x6f,0x00,0x70,0x00,0x79,0x00,0x72,0x00,0x69,0x00,0x67,0x00,0x68,0x00,0x74,0x00,0x20,0x00,0x32,0x00,0x30,0x00,0x32,0x00,0x30,0x00,0x20,0x00,0x54,0x00,0x68,0x00,0x65,0x00,0x20,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00, 0x6f,0x00,0x20,0x00,0x50,0x00,0x72,0x00,0x6f,0x00,0x6a,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x41,0x00,0x75,0x00,0x74,0x00,0x68,0x00,0x6f,0x00,0x72,0x00,0x73,0x00,0x20,0x00,0x28,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x67,0x00,0x69,0x00,0x74,0x00,0x68,0x00,0x75,0x00, 0x62,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x2f,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x2f,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x29,0x00,0x4a,0x00,0x65,0x00, 0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72,0x00,0x32,0x00,0x2e,0x00,0x33,0x00,0x30,0x00,0x34,0x00,0x3b,0x00,0x4a,0x00,0x42,0x00,0x3b,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00, 0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x2d,0x00,0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x20,0x00, 0x52,0x00,0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x32,0x00,0x2e,0x00,0x33,0x00,0x30,0x00,0x34,0x00,0x3b,0x00,0x20,0x00,0x74,0x00,0x74,0x00,0x66,0x00,0x61,0x00,0x75,0x00,0x74,0x00,0x6f,0x00,0x68,0x00,0x69,0x00,0x6e,0x00, 0x74,0x00,0x20,0x00,0x28,0x00,0x76,0x00,0x31,0x00,0x2e,0x00,0x38,0x00,0x2e,0x00,0x34,0x00,0x2e,0x00,0x37,0x00,0x2d,0x00,0x35,0x00,0x64,0x00,0x35,0x00,0x62,0x00,0x29,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x2d,0x00,0x52,0x00, 0x65,0x00,0x67,0x00,0x75,0x00,0x6c,0x00,0x61,0x00,0x72,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x4d,0x00,0x6f,0x00,0x6e,0x00,0x6f,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x74,0x00,0x72,0x00,0x61,0x00,0x64,0x00,0x65,0x00,0x6d,0x00, 0x61,0x00,0x72,0x00,0x6b,0x00,0x20,0x00,0x6f,0x00,0x66,0x00,0x20,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x20,0x00,0x73,0x00,0x2e,0x00,0x72,0x00,0x2e,0x00,0x6f,0x00,0x2e,0x00,0x4a,0x00,0x65,0x00,0x74,0x00,0x42,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00, 0x50,0x00,0x68,0x00,0x69,0x00,0x6c,0x00,0x69,0x00,0x70,0x00,0x70,0x00,0x20,0x00,0x4e,0x00,0x75,0x00,0x72,0x00,0x75,0x00,0x6c,0x00,0x6c,0x00,0x69,0x00,0x6e,0x00,0x2c,0x00,0x20,0x00,0x4b,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x74,0x00,0x61,0x00,0x6e,0x00,0x74,0x00,0x69,0x00,0x6e,0x00,0x20,0x00,0x42,0x00,0x75,0x00,0x6c,0x00, 0x65,0x00,0x6e,0x00,0x6b,0x00,0x6f,0x00,0x76,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,0x77,0x00,0x77,0x00,0x2e,0x00,0x6a,0x00,0x65,0x00,0x74,0x00,0x62,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x68,0x00,0x74,0x00, 0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,0x77,0x00,0x77,0x00,0x2e,0x00,0x6a,0x00,0x65,0x00,0x74,0x00,0x62,0x00,0x72,0x00,0x61,0x00,0x69,0x00,0x6e,0x00,0x73,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x46,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00, 0x20,0x00,0x53,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x75,0x00,0x6e,0x00,0x64,0x00,0x65,0x00,0x72,0x00,0x20,0x00,0x74,0x00,0x68,0x00,0x65,0x00,0x20,0x00, 0x53,0x00,0x49,0x00,0x4c,0x00,0x20,0x00,0x4f,0x00,0x70,0x00,0x65,0x00,0x6e,0x00,0x20,0x00,0x46,0x00,0x6f,0x00,0x6e,0x00,0x74,0x00,0x20,0x00,0x4c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x2c,0x00,0x20,0x00,0x56,0x00,0x65,0x00,0x72,0x00,0x73,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x31,0x00, 0x2e,0x00,0x31,0x00,0x2e,0x00,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x63,0x00,0x65,0x00,0x6e,0x00,0x73,0x00,0x65,0x00,0x20,0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x76,0x00,0x61,0x00,0x69,0x00,0x6c,0x00,0x61,0x00,0x62,0x00,0x6c,0x00,0x65,0x00,0x20,0x00,0x77,0x00,0x69,0x00, 0x74,0x00,0x68,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x46,0x00,0x41,0x00,0x51,0x00,0x20,0x00,0x61,0x00,0x74,0x00,0x3a,0x00,0x20,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x73,0x00,0x2e,0x00,0x73,0x00,0x69,0x00,0x6c,0x00, 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,0x4f,0x00,0x46,0x00,0x4c,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,0x73,0x00,0x3a,0x00,0x2f,0x00,0x2f,0x00,0x73,0x00,0x63,0x00,0x72,0x00,0x69,0x00,0x70,0x00,0x74,0x00,0x73,0x00,0x2e,0x00,0x73,0x00,0x69,0x00,0x6c,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00, 0x4f,0x00,0x46,0x00,0x4c,0x00,0x43,0x00,0x6c,0x00,0x61,0x00,0x73,0x00,0x73,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x63,0x00,0x6f,0x00,0x6e,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x43,0x00,0x6c,0x00,0x6f,0x00,0x73,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x63,0x00,0x6f,0x00, 0x6e,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x75,0x00,0x63,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x42,0x00,0x72,0x00,0x6f,0x00,0x6b,0x00,0x65,0x00,0x6e,0x00,0x20,0x00,0x65,0x00,0x71,0x00,0x75,0x00,0x61,0x00,0x6c,0x00,0x73,0x00,0x20,0x00,0x6c,0x00,0x69,0x00,0x67,0x00,0x61,0x00,0x74,0x00,0x75,0x00,0x72,0x00,0x65,0x00, 0x73,0x00,0x52,0x00,0x61,0x00,0x73,0x00,0x65,0x00,0x64,0x00,0x20,0x00,0x62,0x00,0x61,0x00,0x72,0x00,0x20,0x00,0x66,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x65,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xcf,0x00,0x00,0x00,0x24,0x00,0xc9, 0x01,0x02,0x01,0x03,0x01,0x04,0x01,0x05,0x01,0x06,0x01,0x07,0x01,0x08,0x00,0xc7,0x01,0x09,0x01,0x0a,0x01,0x0b,0x01,0x0c,0x01,0x0d,0x00,0x62,0x01,0x0e,0x00,0xad,0x01,0x0f,0x01,0x10,0x01,0x11,0x00,0x63,0x00,0xae,0x00,0x90,0x01,0x12,0x00,0x25,0x00,0x26,0x00,0xfd,0x00,0xff,0x00,0x64,0x01,0x13,0x01,0x14,0x00,0x27,0x00,0xe9, 0x01,0x15,0x01,0x16,0x00,0x28,0x00,0x65,0x01,0x17,0x01,0x18,0x00,0xc8,0x01,0x19,0x01,0x1a,0x01,0x1b,0x01,0x1c,0x01,0x1d,0x00,0xca,0x01,0x1e,0x01,0x1f,0x00,0xcb,0x01,0x20,0x01,0x21,0x01,0x22,0x01,0x23,0x01,0x24,0x00,0x29,0x00,0x2a,0x01,0x25,0x00,0xf8,0x01,0x26,0x01,0x27,0x01,0x28,0x01,0x29,0x00,0x2b,0x01,0x2a,0x01,0x2b, 0x00,0x2c,0x00,0xcc,0x01,0x2c,0x00,0xcd,0x00,0xce,0x00,0xfa,0x01,0x2d,0x00,0xcf,0x01,0x2e,0x01,0x2f,0x01,0x30,0x01,0x31,0x00,0x2d,0x01,0x32,0x00,0x2e,0x01,0x33,0x00,0x2f,0x01,0x34,0x01,0x35,0x01,0x36,0x01,0x37,0x00,0xe2,0x00,0x30,0x00,0x31,0x01,0x38,0x01,0x39,0x01,0x3a,0x01,0x3b,0x00,0x66,0x00,0x32,0x00,0xd0,0x01,0x3c, 0x00,0xd1,0x01,0x3d,0x01,0x3e,0x01,0x3f,0x01,0x40,0x01,0x41,0x00,0x67,0x01,0x42,0x00,0xd3,0x01,0x43,0x01,0x44,0x01,0x45,0x01,0x46,0x01,0x47,0x01,0x48,0x01,0x49,0x01,0x4a,0x01,0x4b,0x01,0x4c,0x00,0x91,0x01,0x4d,0x00,0xaf,0x00,0xb0,0x00,0x33,0x00,0xed,0x00,0x34,0x00,0x35,0x01,0x4e,0x01,0x4f,0x01,0x50,0x00,0x36,0x01,0x51, 0x00,0xe4,0x00,0xfb,0x01,0x52,0x01,0x53,0x01,0x54,0x01,0x55,0x00,0x37,0x01,0x56,0x01,0x57,0x01,0x58,0x01,0x59,0x00,0x38,0x00,0xd4,0x01,0x5a,0x00,0xd5,0x00,0x68,0x01,0x5b,0x00,0xd6,0x01,0x5c,0x01,0x5d,0x01,0x5e,0x01,0x5f,0x01,0x60,0x01,0x61,0x01,0x62,0x01,0x63,0x01,0x64,0x01,0x65,0x01,0x66,0x01,0x67,0x00,0x39,0x00,0x3a, 0x01,0x68,0x01,0x69,0x01,0x6a,0x01,0x6b,0x00,0x3b,0x00,0x3c,0x00,0xeb,0x01,0x6c,0x00,0xbb,0x01,0x6d,0x01,0x6e,0x01,0x6f,0x01,0x70,0x01,0x71,0x00,0x3d,0x01,0x72,0x00,0xe6,0x01,0x73,0x01,0x74,0x01,0x75,0x01,0x76,0x01,0x77,0x01,0x78,0x01,0x79,0x01,0x7a,0x01,0x7b,0x00,0x44,0x00,0x69,0x01,0x7c,0x01,0x7d,0x01,0x7e,0x01,0x7f, 0x01,0x80,0x01,0x81,0x01,0x82,0x00,0x6b,0x01,0x83,0x01,0x84,0x01,0x85,0x01,0x86,0x01,0x87,0x00,0x6c,0x01,0x88,0x00,0x6a,0x01,0x89,0x01,0x8a,0x01,0x8b,0x00,0x6e,0x00,0x6d,0x00,0xa0,0x01,0x8c,0x00,0x45,0x00,0x46,0x00,0xfe,0x01,0x00,0x00,0x6f,0x01,0x8d,0x01,0x8e,0x00,0x47,0x00,0xea,0x01,0x8f,0x01,0x01,0x00,0x48,0x00,0x70, 0x01,0x90,0x01,0x91,0x00,0x72,0x01,0x92,0x01,0x93,0x01,0x94,0x01,0x95,0x01,0x96,0x00,0x73,0x01,0x97,0x01,0x98,0x00,0x71,0x01,0x99,0x01,0x9a,0x01,0x9b,0x01,0x9c,0x01,0x9d,0x00,0x49,0x00,0x4a,0x01,0x9e,0x00,0xf9,0x01,0x9f,0x01,0xa0,0x01,0xa1,0x01,0xa2,0x00,0x4b,0x01,0xa3,0x01,0xa4,0x00,0x4c,0x00,0xd7,0x00,0x74,0x01,0xa5, 0x01,0xa6,0x00,0x76,0x00,0x77,0x01,0xa7,0x01,0xa8,0x00,0x75,0x01,0xa9,0x01,0xaa,0x01,0xab,0x01,0xac,0x00,0x4d,0x01,0xad,0x01,0xae,0x00,0x4e,0x01,0xaf,0x01,0xb0,0x00,0x4f,0x01,0xb1,0x01,0xb2,0x01,0xb3,0x01,0xb4,0x01,0xb5,0x00,0xe3,0x00,0x50,0x00,0x51,0x01,0xb6,0x01,0xb7,0x01,0xb8,0x01,0xb9,0x01,0xba,0x00,0x78,0x00,0x52, 0x00,0x79,0x01,0xbb,0x01,0xbc,0x00,0x7b,0x01,0xbd,0x01,0xbe,0x01,0xbf,0x01,0xc0,0x01,0xc1,0x00,0x7c,0x01,0xc2,0x00,0x7a,0x01,0xc3,0x01,0xc4,0x01,0xc5,0x01,0xc6,0x01,0xc7,0x01,0xc8,0x01,0xc9,0x01,0xca,0x01,0xcb,0x01,0xcc,0x00,0xa1,0x01,0xcd,0x00,0x7d,0x00,0xb1,0x00,0x53,0x00,0xee,0x00,0x54,0x00,0x55,0x01,0xce,0x01,0xcf, 0x01,0xd0,0x00,0x56,0x01,0xd1,0x00,0xe5,0x00,0xfc,0x01,0xd2,0x01,0xd3,0x00,0x89,0x01,0xd4,0x00,0x57,0x01,0xd5,0x01,0xd6,0x01,0xd7,0x01,0xd8,0x00,0x58,0x00,0x7e,0x01,0xd9,0x01,0xda,0x00,0x80,0x00,0x81,0x01,0xdb,0x01,0xdc,0x01,0xdd,0x01,0xde,0x01,0xdf,0x00,0x7f,0x01,0xe0,0x01,0xe1,0x01,0xe2,0x01,0xe3,0x01,0xe4,0x01,0xe5, 0x01,0xe6,0x01,0xe7,0x01,0xe8,0x01,0xe9,0x01,0xea,0x01,0xeb,0x00,0x59,0x00,0x5a,0x01,0xec,0x01,0xed,0x01,0xee,0x01,0xef,0x00,0x5b,0x00,0x5c,0x00,0xec,0x01,0xf0,0x00,0xba,0x01,0xf1,0x01,0xf2,0x01,0xf3,0x01,0xf4,0x01,0xf5,0x00,0x5d,0x01,0xf6,0x00,0xe7,0x01,0xf7,0x01,0xf8,0x01,0xf9,0x01,0xfa,0x01,0xfb,0x01,0xfc,0x01,0xfd, 0x01,0xfe,0x01,0xff,0x02,0x00,0x02,0x01,0x02,0x02,0x02,0x03,0x02,0x04,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x08,0x02,0x09,0x02,0x0a,0x02,0x0b,0x02,0x0c,0x02,0x0d,0x02,0x0e,0x02,0x0f,0x02,0x10,0x02,0x11,0x02,0x12,0x02,0x13,0x02,0x14,0x02,0x15,0x02,0x16,0x02,0x17,0x02,0x18,0x02,0x19,0x02,0x1a,0x02,0x1b,0x02,0x1c,0x02,0x1d, 0x02,0x1e,0x02,0x1f,0x02,0x20,0x02,0x21,0x02,0x22,0x02,0x23,0x02,0x24,0x02,0x25,0x02,0x26,0x02,0x27,0x02,0x28,0x02,0x29,0x02,0x2a,0x02,0x2b,0x02,0x2c,0x02,0x2d,0x02,0x2e,0x02,0x2f,0x02,0x30,0x02,0x31,0x02,0x32,0x02,0x33,0x02,0x34,0x02,0x35,0x02,0x36,0x02,0x37,0x02,0x38,0x02,0x39,0x02,0x3a,0x02,0x3b,0x02,0x3c,0x02,0x3d, 0x02,0x3e,0x02,0x3f,0x02,0x40,0x00,0x9d,0x00,0x9e,0x02,0x41,0x02,0x42,0x02,0x43,0x02,0x44,0x02,0x45,0x02,0x46,0x02,0x47,0x02,0x48,0x02,0x49,0x02,0x4a,0x02,0x4b,0x02,0x4c,0x02,0x4d,0x02,0x4e,0x02,0x4f,0x02,0x50,0x02,0x51,0x02,0x52,0x02,0x53,0x02,0x54,0x02,0x55,0x02,0x56,0x02,0x57,0x02,0x58,0x02,0x59,0x02,0x5a,0x02,0x5b, 0x02,0x5c,0x02,0x5d,0x02,0x5e,0x02,0x5f,0x02,0x60,0x02,0x61,0x02,0x62,0x02,0x63,0x02,0x64,0x02,0x65,0x02,0x66,0x02,0x67,0x02,0x68,0x02,0x69,0x02,0x6a,0x02,0x6b,0x02,0x6c,0x02,0x6d,0x02,0x6e,0x02,0x6f,0x02,0x70,0x02,0x71,0x02,0x72,0x02,0x73,0x02,0x74,0x02,0x75,0x02,0x76,0x02,0x77,0x02,0x78,0x02,0x79,0x02,0x7a,0x02,0x7b, 0x02,0x7c,0x02,0x7d,0x02,0x7e,0x02,0x7f,0x02,0x80,0x02,0x81,0x02,0x82,0x02,0x83,0x02,0x84,0x02,0x85,0x02,0x86,0x02,0x87,0x02,0x88,0x02,0x89,0x02,0x8a,0x02,0x8b,0x02,0x8c,0x02,0x8d,0x02,0x8e,0x02,0x8f,0x02,0x90,0x02,0x91,0x02,0x92,0x02,0x93,0x02,0x94,0x02,0x95,0x02,0x96,0x02,0x97,0x02,0x98,0x02,0x99,0x02,0x9a,0x02,0x9b, 0x02,0x9c,0x02,0x9d,0x02,0x9e,0x02,0x9f,0x02,0xa0,0x02,0xa1,0x02,0xa2,0x02,0xa3,0x02,0xa4,0x02,0xa5,0x02,0xa6,0x02,0xa7,0x02,0xa8,0x02,0xa9,0x02,0xaa,0x02,0xab,0x02,0xac,0x02,0xad,0x02,0xae,0x02,0xaf,0x02,0xb0,0x02,0xb1,0x02,0xb2,0x02,0xb3,0x02,0xb4,0x02,0xb5,0x02,0xb6,0x02,0xb7,0x02,0xb8,0x02,0xb9,0x02,0xba,0x02,0xbb, 0x02,0xbc,0x02,0xbd,0x02,0xbe,0x02,0xbf,0x02,0xc0,0x02,0xc1,0x02,0xc2,0x02,0xc3,0x02,0xc4,0x02,0xc5,0x02,0xc6,0x02,0xc7,0x02,0xc8,0x02,0xc9,0x02,0xca,0x02,0xcb,0x02,0xcc,0x02,0xcd,0x02,0xce,0x02,0xcf,0x02,0xd0,0x02,0xd1,0x02,0xd2,0x02,0xd3,0x02,0xd4,0x02,0xd5,0x02,0xd6,0x02,0xd7,0x02,0xd8,0x02,0xd9,0x02,0xda,0x02,0xdb, 0x02,0xdc,0x02,0xdd,0x02,0xde,0x02,0xdf,0x02,0xe0,0x02,0xe1,0x02,0xe2,0x02,0xe3,0x02,0xe4,0x02,0xe5,0x02,0xe6,0x02,0xe7,0x02,0xe8,0x02,0xe9,0x02,0xea,0x02,0xeb,0x02,0xec,0x02,0xed,0x02,0xee,0x02,0xef,0x02,0xf0,0x02,0xf1,0x02,0xf2,0x02,0xf3,0x02,0xf4,0x02,0xf5,0x02,0xf6,0x02,0xf7,0x02,0xf8,0x02,0xf9,0x02,0xfa,0x02,0xfb, 0x02,0xfc,0x00,0x9b,0x02,0xfd,0x02,0xfe,0x02,0xff,0x03,0x00,0x03,0x01,0x03,0x02,0x03,0x03,0x03,0x04,0x03,0x05,0x03,0x06,0x03,0x07,0x03,0x08,0x03,0x09,0x03,0x0a,0x03,0x0b,0x03,0x0c,0x03,0x0d,0x03,0x0e,0x03,0x0f,0x03,0x10,0x03,0x11,0x03,0x12,0x03,0x13,0x03,0x14,0x03,0x15,0x03,0x16,0x03,0x17,0x03,0x18,0x03,0x19,0x03,0x1a, 0x03,0x1b,0x03,0x1c,0x03,0x1d,0x03,0x1e,0x03,0x1f,0x03,0x20,0x03,0x21,0x03,0x22,0x03,0x23,0x03,0x24,0x03,0x25,0x03,0x26,0x03,0x27,0x03,0x28,0x03,0x29,0x03,0x2a,0x03,0x2b,0x03,0x2c,0x03,0x2d,0x03,0x2e,0x03,0x2f,0x03,0x30,0x03,0x31,0x03,0x32,0x03,0x33,0x03,0x34,0x03,0x35,0x03,0x36,0x03,0x37,0x03,0x38,0x03,0x39,0x03,0x3a, 0x03,0x3b,0x03,0x3c,0x03,0x3d,0x03,0x3e,0x03,0x3f,0x03,0x40,0x03,0x41,0x03,0x42,0x03,0x43,0x03,0x44,0x03,0x45,0x03,0x46,0x03,0x47,0x03,0x48,0x03,0x49,0x03,0x4a,0x03,0x4b,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1a,0x00,0x1b,0x00,0x1c,0x03,0x4c,0x03,0x4d,0x03,0x4e,0x03,0x4f,0x03,0x50, 0x03,0x51,0x03,0x52,0x03,0x53,0x03,0x54,0x03,0x55,0x03,0x56,0x03,0x57,0x03,0x58,0x03,0x59,0x03,0x5a,0x03,0x5b,0x03,0x5c,0x03,0x5d,0x03,0x5e,0x03,0x5f,0x03,0x60,0x03,0x61,0x03,0x62,0x03,0x63,0x03,0x64,0x03,0x65,0x03,0x66,0x03,0x67,0x03,0x68,0x03,0x69,0x03,0x6a,0x03,0x6b,0x03,0x6c,0x03,0x6d,0x03,0x6e,0x03,0x6f,0x03,0x70, 0x03,0x71,0x03,0x72,0x03,0x73,0x03,0x74,0x03,0x75,0x03,0x76,0x03,0x77,0x03,0x78,0x03,0x79,0x03,0x7a,0x03,0x7b,0x03,0x7c,0x03,0x7d,0x03,0x7e,0x03,0x7f,0x03,0x80,0x03,0x81,0x03,0x82,0x03,0x83,0x03,0x84,0x03,0x85,0x03,0x86,0x03,0x87,0x03,0x88,0x03,0x89,0x03,0x8a,0x03,0x8b,0x03,0x8c,0x03,0x8d,0x00,0xbc,0x00,0xf4,0x00,0xf5, 0x00,0xf6,0x03,0x8e,0x03,0x8f,0x03,0x90,0x03,0x91,0x03,0x92,0x00,0x11,0x00,0x0f,0x00,0x1d,0x00,0x1e,0x00,0xab,0x00,0x04,0x00,0xa3,0x00,0x22,0x00,0xa2,0x00,0xc3,0x00,0x87,0x00,0x0d,0x03,0x93,0x03,0x94,0x03,0x95,0x03,0x96,0x03,0x97,0x00,0x06,0x03,0x98,0x03,0x99,0x00,0x12,0x00,0x3f,0x03,0x9a,0x03,0x9b,0x03,0x9c,0x03,0x9d, 0x00,0x0b,0x00,0x0c,0x00,0x5e,0x00,0x60,0x00,0x3e,0x00,0x40,0x03,0x9e,0x03,0x9f,0x03,0xa0,0x03,0xa1,0x03,0xa2,0x03,0xa3,0x03,0xa4,0x03,0xa5,0x03,0xa6,0x03,0xa7,0x03,0xa8,0x03,0xa9,0x03,0xaa,0x03,0xab,0x00,0x10,0x03,0xac,0x00,0xb2,0x00,0xb3,0x03,0xad,0x00,0x42,0x00,0xc4,0x00,0xc5,0x00,0xb4,0x00,0xb5,0x00,0xb6,0x00,0xb7, 0x03,0xae,0x03,0xaf,0x00,0xa9,0x00,0xaa,0x00,0xbe,0x00,0xbf,0x03,0xb0,0x00,0x05,0x00,0x0a,0x03,0xb1,0x03,0xb2,0x03,0xb3,0x03,0xb4,0x03,0xb5,0x03,0xb6,0x03,0xb7,0x03,0xb8,0x03,0xb9,0x03,0xba,0x03,0xbb,0x03,0xbc,0x03,0xbd,0x03,0xbe,0x03,0xbf,0x03,0xc0,0x03,0xc1,0x03,0xc2,0x03,0xc3,0x03,0xc4,0x03,0xc5,0x03,0xc6,0x03,0xc7, 0x03,0xc8,0x03,0xc9,0x03,0xca,0x03,0xcb,0x03,0xcc,0x03,0xcd,0x03,0xce,0x03,0xcf,0x03,0xd0,0x03,0xd1,0x03,0xd2,0x03,0xd3,0x03,0xd4,0x03,0xd5,0x03,0xd6,0x03,0xd7,0x03,0xd8,0x03,0xd9,0x03,0xda,0x03,0xdb,0x03,0xdc,0x03,0xdd,0x03,0xde,0x03,0xdf,0x03,0xe0,0x03,0xe1,0x03,0xe2,0x03,0xe3,0x03,0xe4,0x03,0xe5,0x03,0xe6,0x03,0xe7, 0x03,0xe8,0x03,0xe9,0x03,0xea,0x03,0xeb,0x03,0xec,0x03,0xed,0x03,0xee,0x03,0xef,0x03,0xf0,0x03,0xf1,0x03,0xf2,0x03,0xf3,0x03,0xf4,0x03,0xf5,0x03,0xf6,0x03,0xf7,0x03,0xf8,0x03,0xf9,0x03,0xfa,0x03,0xfb,0x03,0xfc,0x03,0xfd,0x03,0xfe,0x03,0xff,0x04,0x00,0x04,0x01,0x04,0x02,0x00,0x03,0x04,0x03,0x04,0x04,0x04,0x05,0x04,0x06, 0x00,0x84,0x00,0xbd,0x00,0x07,0x04,0x07,0x04,0x08,0x00,0xa6,0x04,0x09,0x04,0x0a,0x00,0x85,0x04,0x0b,0x00,0x96,0x04,0x0c,0x04,0x0d,0x04,0x0e,0x04,0x0f,0x04,0x10,0x04,0x11,0x04,0x12,0x04,0x13,0x04,0x14,0x04,0x15,0x04,0x16,0x04,0x17,0x04,0x18,0x04,0x19,0x04,0x1a,0x04,0x1b,0x04,0x1c,0x04,0x1d,0x04,0x1e,0x04,0x1f,0x04,0x20, 0x04,0x21,0x04,0x22,0x04,0x23,0x04,0x24,0x04,0x25,0x04,0x26,0x04,0x27,0x04,0x28,0x04,0x29,0x04,0x2a,0x04,0x2b,0x04,0x2c,0x04,0x2d,0x04,0x2e,0x04,0x2f,0x04,0x30,0x04,0x31,0x04,0x32,0x04,0x33,0x04,0x34,0x04,0x35,0x04,0x36,0x04,0x37,0x04,0x38,0x04,0x39,0x04,0x3a,0x04,0x3b,0x04,0x3c,0x04,0x3d,0x04,0x3e,0x04,0x3f,0x04,0x40, 0x04,0x41,0x04,0x42,0x04,0x43,0x04,0x44,0x04,0x45,0x04,0x46,0x04,0x47,0x04,0x48,0x04,0x49,0x04,0x4a,0x04,0x4b,0x04,0x4c,0x04,0x4d,0x04,0x4e,0x04,0x4f,0x04,0x50,0x04,0x51,0x04,0x52,0x00,0x0e,0x00,0xef,0x00,0xf0,0x00,0xb8,0x00,0x20,0x00,0x8f,0x00,0x21,0x00,0x1f,0x00,0x95,0x00,0x94,0x00,0x93,0x00,0xa7,0x00,0xa4,0x00,0x61, 0x00,0x41,0x00,0x92,0x04,0x53,0x04,0x54,0x04,0x55,0x04,0x56,0x04,0x57,0x00,0x9c,0x04,0x58,0x00,0x9a,0x00,0x99,0x00,0xa5,0x00,0x98,0x04,0x59,0x04,0x5a,0x04,0x5b,0x04,0x5c,0x04,0x5d,0x04,0x5e,0x04,0x5f,0x04,0x60,0x00,0x08,0x00,0xc6,0x04,0x61,0x04,0x62,0x04,0x63,0x04,0x64,0x04,0x65,0x04,0x66,0x04,0x67,0x04,0x68,0x04,0x69, 0x04,0x6a,0x04,0x6b,0x04,0x6c,0x04,0x6d,0x04,0x6e,0x04,0x6f,0x04,0x70,0x04,0x71,0x04,0x72,0x04,0x73,0x04,0x74,0x04,0x75,0x04,0x76,0x04,0x77,0x04,0x78,0x04,0x79,0x04,0x7a,0x04,0x7b,0x04,0x7c,0x04,0x7d,0x04,0x7e,0x04,0x7f,0x04,0x80,0x04,0x81,0x04,0x82,0x04,0x83,0x04,0x84,0x04,0x85,0x04,0x86,0x04,0x87,0x04,0x88,0x04,0x89, 0x04,0x8a,0x04,0x8b,0x04,0x8c,0x04,0x8d,0x04,0x8e,0x04,0x8f,0x04,0x90,0x04,0x91,0x04,0x92,0x04,0x93,0x04,0x94,0x04,0x95,0x04,0x96,0x04,0x97,0x04,0x98,0x04,0x99,0x04,0x9a,0x04,0x9b,0x04,0x9c,0x04,0x9d,0x04,0x9e,0x04,0x9f,0x04,0xa0,0x04,0xa1,0x04,0xa2,0x04,0xa3,0x04,0xa4,0x04,0xa5,0x04,0xa6,0x04,0xa7,0x04,0xa8,0x04,0xa9, 0x04,0xaa,0x04,0xab,0x04,0xac,0x04,0xad,0x04,0xae,0x04,0xaf,0x04,0xb0,0x04,0xb1,0x04,0xb2,0x04,0xb3,0x04,0xb4,0x04,0xb5,0x04,0xb6,0x04,0xb7,0x04,0xb8,0x04,0xb9,0x04,0xba,0x04,0xbb,0x04,0xbc,0x04,0xbd,0x04,0xbe,0x04,0xbf,0x04,0xc0,0x04,0xc1,0x04,0xc2,0x04,0xc3,0x04,0xc4,0x04,0xc5,0x04,0xc6,0x04,0xc7,0x04,0xc8,0x04,0xc9, 0x04,0xca,0x04,0xcb,0x04,0xcc,0x04,0xcd,0x04,0xce,0x04,0xcf,0x04,0xd0,0x04,0xd1,0x04,0xd2,0x04,0xd3,0x04,0xd4,0x04,0xd5,0x04,0xd6,0x04,0xd7,0x04,0xd8,0x04,0xd9,0x04,0xda,0x04,0xdb,0x04,0xdc,0x04,0xdd,0x04,0xde,0x04,0xdf,0x04,0xe0,0x04,0xe1,0x04,0xe2,0x04,0xe3,0x04,0xe4,0x04,0xe5,0x04,0xe6,0x04,0xe7,0x04,0xe8,0x04,0xe9, 0x04,0xea,0x04,0xeb,0x04,0xec,0x04,0xed,0x00,0xb9,0x04,0xee,0x04,0xef,0x04,0xf0,0x04,0xf1,0x04,0xf2,0x04,0xf3,0x04,0xf4,0x04,0xf5,0x04,0xf6,0x04,0xf7,0x04,0xf8,0x04,0xf9,0x04,0xfa,0x04,0xfb,0x04,0xfc,0x04,0xfd,0x04,0xfe,0x04,0xff,0x05,0x00,0x05,0x01,0x05,0x02,0x05,0x03,0x05,0x04,0x05,0x05,0x05,0x06,0x05,0x07,0x05,0x08, 0x05,0x09,0x05,0x0a,0x05,0x0b,0x05,0x0c,0x05,0x0d,0x05,0x0e,0x05,0x0f,0x05,0x10,0x05,0x11,0x05,0x12,0x05,0x13,0x05,0x14,0x05,0x15,0x05,0x16,0x05,0x17,0x05,0x18,0x05,0x19,0x05,0x1a,0x05,0x1b,0x05,0x1c,0x05,0x1d,0x05,0x1e,0x05,0x1f,0x05,0x20,0x05,0x21,0x05,0x22,0x05,0x23,0x05,0x24,0x05,0x25,0x05,0x26,0x05,0x27,0x05,0x28, 0x05,0x29,0x05,0x2a,0x05,0x2b,0x05,0x2c,0x05,0x2d,0x05,0x2e,0x05,0x2f,0x05,0x30,0x05,0x31,0x05,0x32,0x05,0x33,0x05,0x34,0x05,0x35,0x05,0x36,0x05,0x37,0x05,0x38,0x05,0x39,0x05,0x3a,0x05,0x3b,0x05,0x3c,0x05,0x3d,0x05,0x3e,0x05,0x3f,0x05,0x40,0x05,0x41,0x05,0x42,0x05,0x43,0x05,0x44,0x05,0x45,0x05,0x46,0x05,0x47,0x05,0x48, 0x05,0x49,0x05,0x4a,0x05,0x4b,0x05,0x4c,0x05,0x4d,0x05,0x4e,0x05,0x4f,0x05,0x50,0x05,0x51,0x05,0x52,0x05,0x53,0x05,0x54,0x05,0x55,0x05,0x56,0x05,0x57,0x05,0x58,0x05,0x59,0x05,0x5a,0x05,0x5b,0x05,0x5c,0x05,0x5d,0x05,0x5e,0x05,0x5f,0x05,0x60,0x05,0x61,0x05,0x62,0x05,0x63,0x05,0x64,0x05,0x65,0x05,0x66,0x05,0x67,0x05,0x68, 0x05,0x69,0x05,0x6a,0x05,0x6b,0x05,0x6c,0x05,0x6d,0x05,0x6e,0x05,0x6f,0x05,0x70,0x05,0x71,0x05,0x72,0x05,0x73,0x05,0x74,0x05,0x75,0x05,0x76,0x05,0x77,0x05,0x78,0x05,0x79,0x05,0x7a,0x05,0x7b,0x05,0x7c,0x05,0x7d,0x05,0x7e,0x05,0x7f,0x05,0x80,0x05,0x81,0x05,0x82,0x05,0x83,0x05,0x84,0x05,0x85,0x05,0x86,0x05,0x87,0x05,0x88, 0x05,0x89,0x05,0x8a,0x05,0x8b,0x05,0x8c,0x05,0x8d,0x05,0x8e,0x05,0x8f,0x05,0x90,0x05,0x91,0x05,0x92,0x05,0x93,0x05,0x94,0x05,0x95,0x05,0x96,0x05,0x97,0x05,0x98,0x05,0x99,0x05,0x9a,0x05,0x9b,0x05,0x9c,0x05,0x9d,0x05,0x9e,0x05,0x9f,0x05,0xa0,0x05,0xa1,0x05,0xa2,0x05,0xa3,0x05,0xa4,0x05,0xa5,0x05,0xa6,0x05,0xa7,0x05,0xa8, 0x05,0xa9,0x05,0xaa,0x05,0xab,0x05,0xac,0x05,0xad,0x05,0xae,0x05,0xaf,0x05,0xb0,0x05,0xb1,0x05,0xb2,0x05,0xb3,0x05,0xb4,0x05,0xb5,0x05,0xb6,0x05,0xb7,0x05,0xb8,0x05,0xb9,0x05,0xba,0x05,0xbb,0x05,0xbc,0x05,0xbd,0x05,0xbe,0x05,0xbf,0x05,0xc0,0x05,0xc1,0x05,0xc2,0x05,0xc3,0x05,0xc4,0x05,0xc5,0x05,0xc6,0x05,0xc7,0x05,0xc8, 0x05,0xc9,0x05,0xca,0x05,0xcb,0x05,0xcc,0x05,0xcd,0x05,0xce,0x05,0xcf,0x05,0xd0,0x05,0xd1,0x05,0xd2,0x05,0xd3,0x05,0xd4,0x05,0xd5,0x05,0xd6,0x05,0xd7,0x05,0xd8,0x05,0xd9,0x00,0x23,0x00,0x09,0x00,0x88,0x00,0x86,0x00,0x8b,0x00,0x8a,0x00,0x8c,0x00,0x83,0x05,0xda,0x05,0xdb,0x00,0x5f,0x00,0xe8,0x00,0x82,0x05,0xdc,0x00,0xc2, 0x05,0xdd,0x05,0xde,0x05,0xdf,0x05,0xe0,0x05,0xe1,0x05,0xe2,0x05,0xe3,0x05,0xe4,0x05,0xe5,0x05,0xe6,0x05,0xe7,0x05,0xe8,0x05,0xe9,0x05,0xea,0x05,0xeb,0x05,0xec,0x05,0xed,0x05,0xee,0x05,0xef,0x05,0xf0,0x05,0xf1,0x05,0xf2,0x05,0xf3,0x05,0xf4,0x05,0xf5,0x05,0xf6,0x05,0xf7,0x05,0xf8,0x05,0xf9,0x05,0xfa,0x05,0xfb,0x05,0xfc, 0x05,0xfd,0x05,0xfe,0x05,0xff,0x06,0x00,0x06,0x01,0x06,0x02,0x06,0x03,0x06,0x04,0x06,0x05,0x06,0x06,0x06,0x07,0x06,0x08,0x06,0x09,0x06,0x0a,0x06,0x0b,0x06,0x0c,0x06,0x0d,0x06,0x0e,0x06,0x0f,0x06,0x10,0x06,0x11,0x06,0x12,0x06,0x13,0x06,0x14,0x06,0x15,0x06,0x16,0x06,0x17,0x06,0x18,0x06,0x19,0x06,0x1a,0x06,0x1b,0x06,0x1c, 0x06,0x1d,0x06,0x1e,0x06,0x1f,0x06,0x20,0x06,0x21,0x06,0x22,0x06,0x23,0x06,0x24,0x06,0x25,0x06,0x26,0x06,0x27,0x06,0x28,0x06,0x29,0x06,0x2a,0x06,0x2b,0x06,0x2c,0x06,0x2d,0x06,0x2e,0x06,0x2f,0x06,0x30,0x06,0x31,0x06,0x32,0x06,0x33,0x06,0x34,0x06,0x35,0x06,0x36,0x06,0x37,0x06,0x38,0x06,0x39,0x06,0x3a,0x06,0x3b,0x06,0x3c, 0x06,0x3d,0x06,0x3e,0x06,0x3f,0x06,0x40,0x06,0x41,0x06,0x42,0x06,0x43,0x06,0x44,0x06,0x45,0x06,0x46,0x06,0x47,0x06,0x48,0x06,0x49,0x06,0x4a,0x06,0x4b,0x06,0x4c,0x06,0x4d,0x06,0x4e,0x06,0x4f,0x06,0x50,0x06,0x51,0x06,0x52,0x06,0x53,0x06,0x54,0x06,0x55,0x06,0x56,0x06,0x57,0x06,0x58,0x06,0x59,0x06,0x5a,0x06,0x5b,0x06,0x5c, 0x06,0x5d,0x06,0x5e,0x06,0x5f,0x06,0x60,0x06,0x61,0x06,0x62,0x06,0x63,0x06,0x64,0x06,0x65,0x06,0x66,0x06,0x67,0x06,0x68,0x06,0x69,0x06,0x6a,0x06,0x6b,0x06,0x6c,0x06,0x6d,0x06,0x6e,0x06,0x6f,0x06,0x70,0x06,0x71,0x06,0x72,0x06,0x73,0x06,0x74,0x06,0x75,0x06,0x76,0x06,0x77,0x06,0x78,0x06,0x79,0x06,0x7a,0x06,0x7b,0x06,0x7c, 0x06,0x7d,0x06,0x7e,0x06,0x7f,0x06,0x80,0x06,0x81,0x06,0x82,0x06,0x83,0x06,0x84,0x06,0x85,0x06,0x86,0x06,0x87,0x06,0x88,0x06,0x89,0x06,0x8a,0x06,0x8b,0x06,0x8c,0x06,0x8d,0x06,0x8e,0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x00,0x8e,0x00,0xdc,0x00,0x43, 0x00,0x8d,0x00,0xdf,0x00,0xd8,0x00,0xe1,0x00,0xdb,0x00,0xdd,0x00,0xd9,0x00,0xda,0x00,0xde,0x00,0xe0,0x06,0x9a,0x06,0x9b,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0x9f,0x06,0xa0,0x06,0xa1,0x06,0xa2,0x06,0xa3,0x06,0xa4,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x06,0xac,0x06,0xad,0x06,0xae,0x06,0xaf, 0x06,0xb0,0x06,0xb1,0x06,0xb2,0x06,0xb3,0x06,0xb4,0x06,0xb5,0x06,0xb6,0x06,0xb7,0x06,0xb8,0x06,0xb9,0x06,0xba,0x06,0xbb,0x06,0xbc,0x06,0xbd,0x06,0xbe,0x06,0xbf,0x06,0xc0,0x06,0xc1,0x06,0xc2,0x06,0xc3,0x06,0xc4,0x06,0xc5,0x06,0xc6,0x06,0xc7,0x06,0xc8,0x06,0xc9,0x06,0xca,0x06,0xcb,0x06,0xcc,0x06,0xcd,0x06,0xce,0x06,0xcf, 0x06,0xd0,0x06,0xd1,0x06,0xd2,0x06,0xd3,0x06,0xd4,0x06,0xd5,0x06,0xd6,0x06,0xd7,0x06,0xd8,0x06,0xd9,0x06,0xda,0x06,0xdb,0x06,0x41,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x45,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x36,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x30,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x32,0x07, 0x75,0x6e,0x69,0x31,0x45,0x42,0x34,0x07,0x75,0x6e,0x69,0x30,0x31,0x43,0x44,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x34,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x43,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x36,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x38,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x41,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x30,0x07, 0x75,0x6e,0x69,0x31,0x45,0x41,0x32,0x07,0x41,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x41,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x07,0x41,0x45,0x61,0x63,0x75,0x74,0x65,0x0b,0x43,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x0a,0x43,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x06,0x44,0x63,0x61,0x72,0x6f,0x6e,0x06,0x44,0x63, 0x72,0x6f,0x61,0x74,0x06,0x45,0x62,0x72,0x65,0x76,0x65,0x06,0x45,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x45,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x36,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x30,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x32,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x34,0x0a,0x45,0x64,0x6f,0x74,0x61, 0x63,0x63,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x38,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x41,0x07,0x45,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x45,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x07,0x75,0x6e,0x69,0x30,0x31,0x39,0x30,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x43,0x07,0x75,0x6e,0x69,0x30,0x31,0x46,0x34,0x06,0x47,0x63, 0x61,0x72,0x6f,0x6e,0x0b,0x47,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30,0x31,0x32,0x32,0x0a,0x47,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x04,0x48,0x62,0x61,0x72,0x0b,0x48,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x06,0x49,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x31, 0x45,0x43,0x41,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x38,0x07,0x49,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x49,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x06,0x49,0x74,0x69,0x6c,0x64,0x65,0x0b,0x4a,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30,0x31,0x33,0x36,0x06,0x4c,0x61,0x63,0x75,0x74,0x65,0x06,0x4c,0x63, 0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x33,0x42,0x04,0x4c,0x64,0x6f,0x74,0x06,0x4e,0x61,0x63,0x75,0x74,0x65,0x06,0x4e,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x34,0x35,0x03,0x45,0x6e,0x67,0x06,0x4f,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x30,0x07,0x75,0x6e,0x69,0x31,0x45, 0x44,0x38,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x32,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x34,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x36,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x43,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x45,0x05,0x4f,0x68,0x6f,0x72,0x6e,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x41,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x32, 0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x43,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x45,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x30,0x0d,0x4f,0x68,0x75,0x6e,0x67,0x61,0x72,0x75,0x6d,0x6c,0x61,0x75,0x74,0x07,0x4f,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x45,0x41,0x0b,0x4f,0x73,0x6c,0x61,0x73,0x68,0x61,0x63,0x75, 0x74,0x65,0x06,0x52,0x61,0x63,0x75,0x74,0x65,0x06,0x52,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x35,0x36,0x06,0x53,0x61,0x63,0x75,0x74,0x65,0x0b,0x53,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30,0x32,0x31,0x38,0x07,0x75,0x6e,0x69,0x31,0x45,0x39,0x45,0x07,0x75,0x6e,0x69,0x30, 0x31,0x38,0x46,0x04,0x54,0x62,0x61,0x72,0x06,0x54,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x36,0x32,0x07,0x75,0x6e,0x69,0x30,0x32,0x31,0x41,0x06,0x55,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x34,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x36,0x05,0x55,0x68,0x6f,0x72,0x6e,0x07,0x75,0x6e,0x69, 0x31,0x45,0x45,0x38,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x30,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x41,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x43,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x45,0x0d,0x55,0x68,0x75,0x6e,0x67,0x61,0x72,0x75,0x6d,0x6c,0x61,0x75,0x74,0x07,0x55,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x55,0x6f,0x67,0x6f,0x6e, 0x65,0x6b,0x05,0x55,0x72,0x69,0x6e,0x67,0x06,0x55,0x74,0x69,0x6c,0x64,0x65,0x06,0x57,0x61,0x63,0x75,0x74,0x65,0x0b,0x57,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x09,0x57,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x06,0x57,0x67,0x72,0x61,0x76,0x65,0x0b,0x59,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07, 0x75,0x6e,0x69,0x31,0x45,0x46,0x34,0x06,0x59,0x67,0x72,0x61,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x36,0x07,0x75,0x6e,0x69,0x30,0x32,0x33,0x32,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x38,0x06,0x5a,0x61,0x63,0x75,0x74,0x65,0x0a,0x5a,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x06,0x57,0x2e,0x63,0x76,0x30,0x37,0x0b, 0x57,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x30,0x37,0x10,0x57,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x30,0x37,0x0e,0x57,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x2e,0x63,0x76,0x30,0x37,0x0b,0x57,0x67,0x72,0x61,0x76,0x65,0x2e,0x63,0x76,0x30,0x37,0x06,0x4b,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75, 0x6e,0x69,0x30,0x31,0x33,0x36,0x2e,0x63,0x76,0x30,0x38,0x06,0x51,0x2e,0x63,0x76,0x31,0x36,0x06,0x61,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x46,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x37,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x31,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x33,0x07,0x75,0x6e,0x69,0x31,0x45,0x42, 0x35,0x07,0x75,0x6e,0x69,0x30,0x31,0x43,0x45,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x35,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x44,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x37,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x39,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x42,0x07,0x75,0x6e,0x69,0x31,0x45,0x41,0x31,0x07,0x75,0x6e,0x69,0x31,0x45,0x41, 0x33,0x07,0x61,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x61,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x07,0x61,0x65,0x61,0x63,0x75,0x74,0x65,0x0b,0x63,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x0a,0x63,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x06,0x64,0x63,0x61,0x72,0x6f,0x6e,0x06,0x65,0x62,0x72,0x65,0x76,0x65,0x06,0x65, 0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x46,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x37,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x31,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x33,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x35,0x0a,0x65,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x39, 0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x42,0x07,0x65,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x65,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x07,0x75,0x6e,0x69,0x31,0x45,0x42,0x44,0x07,0x75,0x6e,0x69,0x30,0x32,0x35,0x39,0x07,0x75,0x6e,0x69,0x30,0x31,0x46,0x35,0x06,0x67,0x63,0x61,0x72,0x6f,0x6e,0x0b,0x67,0x63,0x69,0x72,0x63,0x75,0x6d,0x66, 0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30,0x31,0x32,0x33,0x0a,0x67,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x04,0x68,0x62,0x61,0x72,0x0b,0x68,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x06,0x69,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x30,0x09,0x69,0x2e,0x6c,0x6f,0x63,0x6c,0x54,0x52,0x4b, 0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x42,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x39,0x07,0x69,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x69,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x06,0x69,0x74,0x69,0x6c,0x64,0x65,0x07,0x75,0x6e,0x69,0x30,0x32,0x33,0x37,0x0b,0x6a,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30, 0x31,0x33,0x37,0x0c,0x6b,0x67,0x72,0x65,0x65,0x6e,0x6c,0x61,0x6e,0x64,0x69,0x63,0x06,0x6c,0x61,0x63,0x75,0x74,0x65,0x07,0x75,0x6e,0x69,0x30,0x31,0x39,0x42,0x06,0x6c,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x33,0x43,0x04,0x6c,0x64,0x6f,0x74,0x06,0x6e,0x61,0x63,0x75,0x74,0x65,0x0b,0x6e,0x61,0x70,0x6f,0x73, 0x74,0x72,0x6f,0x70,0x68,0x65,0x06,0x6e,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x34,0x36,0x03,0x65,0x6e,0x67,0x06,0x6f,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x32,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x31,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x39,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x33, 0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x35,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x37,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x44,0x07,0x75,0x6e,0x69,0x31,0x45,0x43,0x46,0x05,0x6f,0x68,0x6f,0x72,0x6e,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x42,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x33,0x07,0x75,0x6e,0x69,0x31,0x45,0x44,0x44,0x07,0x75, 0x6e,0x69,0x31,0x45,0x44,0x46,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x31,0x0d,0x6f,0x68,0x75,0x6e,0x67,0x61,0x72,0x75,0x6d,0x6c,0x61,0x75,0x74,0x07,0x6f,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x45,0x42,0x0b,0x6f,0x73,0x6c,0x61,0x73,0x68,0x61,0x63,0x75,0x74,0x65,0x06,0x72,0x61,0x63,0x75,0x74,0x65,0x06, 0x72,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30,0x31,0x35,0x37,0x06,0x73,0x61,0x63,0x75,0x74,0x65,0x0b,0x73,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x30,0x32,0x31,0x39,0x05,0x6c,0x6f,0x6e,0x67,0x73,0x04,0x74,0x62,0x61,0x72,0x06,0x74,0x63,0x61,0x72,0x6f,0x6e,0x07,0x75,0x6e,0x69,0x30, 0x31,0x36,0x33,0x07,0x75,0x6e,0x69,0x30,0x32,0x31,0x42,0x06,0x75,0x62,0x72,0x65,0x76,0x65,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x34,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x38,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x41,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x43,0x07,0x75,0x6e,0x69,0x30,0x31,0x44,0x36,0x07,0x75,0x6e,0x69,0x31,0x45, 0x45,0x35,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x37,0x05,0x75,0x68,0x6f,0x72,0x6e,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x39,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x31,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x42,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x44,0x07,0x75,0x6e,0x69,0x31,0x45,0x45,0x46,0x0d,0x75,0x68,0x75,0x6e,0x67,0x61,0x72, 0x75,0x6d,0x6c,0x61,0x75,0x74,0x07,0x75,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x07,0x75,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x05,0x75,0x72,0x69,0x6e,0x67,0x06,0x75,0x74,0x69,0x6c,0x64,0x65,0x06,0x77,0x61,0x63,0x75,0x74,0x65,0x0b,0x77,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x09,0x77,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73, 0x06,0x77,0x67,0x72,0x61,0x76,0x65,0x0b,0x79,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x35,0x06,0x79,0x67,0x72,0x61,0x76,0x65,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x37,0x07,0x75,0x6e,0x69,0x30,0x32,0x33,0x33,0x07,0x75,0x6e,0x69,0x31,0x45,0x46,0x39,0x06,0x7a,0x61,0x63,0x75,0x74, 0x65,0x0a,0x7a,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x0f,0x67,0x65,0x72,0x6d,0x61,0x6e,0x64,0x62,0x6c,0x73,0x2e,0x63,0x61,0x6c,0x74,0x06,0x6c,0x2e,0x63,0x76,0x30,0x31,0x0b,0x6c,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x30,0x31,0x0b,0x6c,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x30,0x31,0x0c,0x75,0x6e,0x69,0x30, 0x31,0x33,0x43,0x2e,0x63,0x76,0x30,0x31,0x09,0x6c,0x64,0x6f,0x74,0x2e,0x63,0x76,0x30,0x31,0x0b,0x6c,0x73,0x6c,0x61,0x73,0x68,0x2e,0x63,0x76,0x30,0x31,0x06,0x74,0x2e,0x63,0x76,0x30,0x32,0x09,0x74,0x62,0x61,0x72,0x2e,0x63,0x76,0x30,0x32,0x0b,0x74,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x30,0x32,0x0c,0x75,0x6e,0x69,0x30, 0x31,0x36,0x33,0x2e,0x63,0x76,0x30,0x32,0x0c,0x75,0x6e,0x69,0x30,0x32,0x31,0x42,0x2e,0x63,0x76,0x30,0x32,0x06,0x67,0x2e,0x63,0x76,0x30,0x33,0x0c,0x75,0x6e,0x69,0x30,0x31,0x46,0x35,0x2e,0x63,0x76,0x30,0x33,0x0b,0x67,0x62,0x72,0x65,0x76,0x65,0x2e,0x63,0x76,0x30,0x33,0x0b,0x67,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x30, 0x33,0x10,0x67,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x30,0x33,0x0c,0x75,0x6e,0x69,0x30,0x31,0x32,0x33,0x2e,0x63,0x76,0x30,0x33,0x0f,0x67,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x2e,0x63,0x76,0x30,0x33,0x06,0x6a,0x2e,0x63,0x76,0x30,0x34,0x0c,0x75,0x6e,0x69,0x30,0x32,0x33,0x37,0x2e,0x63, 0x76,0x30,0x34,0x10,0x6a,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x30,0x34,0x06,0x6c,0x2e,0x63,0x76,0x30,0x35,0x0b,0x6c,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x30,0x35,0x0b,0x6c,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x30,0x35,0x0c,0x75,0x6e,0x69,0x30,0x31,0x33,0x43,0x2e,0x63,0x76,0x30,0x35, 0x09,0x6c,0x64,0x6f,0x74,0x2e,0x63,0x76,0x30,0x35,0x0b,0x6c,0x73,0x6c,0x61,0x73,0x68,0x2e,0x63,0x76,0x30,0x35,0x06,0x6d,0x2e,0x63,0x76,0x30,0x36,0x06,0x77,0x2e,0x63,0x76,0x30,0x37,0x0b,0x77,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x30,0x37,0x10,0x77,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x30, 0x37,0x0e,0x77,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x2e,0x63,0x76,0x30,0x37,0x0b,0x77,0x67,0x72,0x61,0x76,0x65,0x2e,0x63,0x76,0x30,0x37,0x06,0x6b,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x31,0x33,0x37,0x2e,0x63,0x76,0x30,0x38,0x11,0x6b,0x67,0x72,0x65,0x65,0x6e,0x6c,0x61,0x6e,0x64,0x69,0x63,0x2e,0x63,0x76, 0x30,0x38,0x06,0x66,0x2e,0x63,0x76,0x30,0x39,0x06,0x72,0x2e,0x63,0x76,0x31,0x30,0x0b,0x72,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x31,0x30,0x0b,0x72,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x31,0x30,0x0c,0x75,0x6e,0x69,0x30,0x31,0x35,0x37,0x2e,0x63,0x76,0x31,0x30,0x06,0x79,0x2e,0x63,0x76,0x31,0x31,0x0b,0x79,0x61,0x63, 0x75,0x74,0x65,0x2e,0x63,0x76,0x31,0x31,0x10,0x79,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x31,0x31,0x0e,0x79,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x31,0x45,0x46,0x35,0x2e,0x63,0x76,0x31,0x31,0x0b,0x79,0x67,0x72,0x61,0x76,0x65,0x2e,0x63,0x76,0x31, 0x31,0x0c,0x75,0x6e,0x69,0x31,0x45,0x46,0x37,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x30,0x32,0x33,0x33,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x31,0x45,0x46,0x39,0x2e,0x63,0x76,0x31,0x31,0x06,0x75,0x2e,0x63,0x76,0x31,0x32,0x0b,0x75,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x76,0x31,0x32,0x0b,0x75,0x62,0x72,0x65, 0x76,0x65,0x2e,0x63,0x76,0x31,0x32,0x10,0x75,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x76,0x31,0x32,0x0e,0x75,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6e,0x69,0x31,0x45,0x45,0x35,0x2e,0x63,0x76,0x31,0x32,0x0b,0x75,0x67,0x72,0x61,0x76,0x65,0x2e,0x63,0x76,0x31,0x32, 0x0c,0x75,0x6e,0x69,0x31,0x45,0x45,0x37,0x2e,0x63,0x76,0x31,0x32,0x0a,0x75,0x68,0x6f,0x72,0x6e,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6e,0x69,0x31,0x45,0x45,0x39,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6e,0x69,0x31,0x45,0x46,0x31,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6e,0x69,0x31,0x45,0x45,0x42,0x2e,0x63,0x76,0x31,0x32,0x0c, 0x75,0x6e,0x69,0x31,0x45,0x45,0x44,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6e,0x69,0x31,0x45,0x45,0x46,0x2e,0x63,0x76,0x31,0x32,0x12,0x75,0x68,0x75,0x6e,0x67,0x61,0x72,0x75,0x6d,0x6c,0x61,0x75,0x74,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x2e,0x63,0x76,0x31,0x32,0x0c,0x75,0x6f,0x67,0x6f,0x6e,0x65, 0x6b,0x2e,0x63,0x76,0x31,0x32,0x0a,0x75,0x72,0x69,0x6e,0x67,0x2e,0x63,0x76,0x31,0x32,0x0b,0x75,0x74,0x69,0x6c,0x64,0x65,0x2e,0x63,0x76,0x31,0x32,0x06,0x66,0x2e,0x63,0x76,0x31,0x37,0x0b,0x66,0x2e,0x63,0x76,0x30,0x39,0x2e,0x73,0x73,0x32,0x30,0x06,0x66,0x2e,0x73,0x73,0x32,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x30,0x07, 0x75,0x6e,0x69,0x30,0x34,0x31,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x39,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x31,0x07, 0x75,0x6e,0x69,0x30,0x34,0x31,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x43,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x43,0x07, 0x75,0x6e,0x69,0x30,0x34,0x31,0x44,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x31,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x45,0x07, 0x75,0x6e,0x69,0x30,0x34,0x32,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x43,0x07, 0x75,0x6e,0x69,0x30,0x34,0x32,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x44,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x36,0x07, 0x75,0x6e,0x69,0x30,0x34,0x30,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x32,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x30,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x39,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x39,0x41,0x07, 0x75,0x6e,0x69,0x30,0x34,0x41,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x41,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x44,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x44,0x43,0x07,0x75,0x6e,0x69,0x30,0x34,0x44,0x45,0x07, 0x75,0x6e,0x69,0x30,0x34,0x45,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x45,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x45,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x46,0x34,0x0c,0x75,0x6e,0x69,0x30,0x34,0x31,0x36,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x31,0x41,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x30, 0x43,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x39,0x41,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x32,0x33,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x30,0x34,0x30,0x45,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x30,0x34,0x32,0x31,0x2e,0x63,0x76,0x39,0x39,0x07,0x75,0x6e,0x69,0x30,0x34, 0x33,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x39,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x35,0x07,0x75,0x6e,0x69,0x30,0x34, 0x35,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x43,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x42,0x07,0x75,0x6e,0x69,0x30,0x34, 0x33,0x43,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x44,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x33,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x30,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x33,0x07,0x75,0x6e,0x69,0x30,0x34, 0x35,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x46,0x07,0x75,0x6e,0x69,0x30,0x34, 0x34,0x43,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x41,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x34,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x44,0x07,0x75,0x6e,0x69,0x30,0x34, 0x35,0x36,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x38,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x45,0x07,0x75,0x6e,0x69,0x30,0x34,0x34,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x35,0x32,0x07,0x75,0x6e,0x69,0x30,0x34,0x39,0x33,0x07,0x75,0x6e,0x69,0x30,0x34, 0x39,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x41,0x33,0x07,0x75,0x6e,0x69,0x30,0x34,0x41,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x31,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x42,0x42,0x07,0x75,0x6e,0x69,0x30,0x34,0x44,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x44,0x44,0x07,0x75,0x6e,0x69,0x30,0x34, 0x44,0x46,0x07,0x75,0x6e,0x69,0x30,0x34,0x45,0x35,0x07,0x75,0x6e,0x69,0x30,0x34,0x45,0x37,0x07,0x75,0x6e,0x69,0x30,0x34,0x45,0x39,0x07,0x75,0x6e,0x69,0x30,0x34,0x46,0x35,0x0c,0x75,0x6e,0x69,0x30,0x34,0x35,0x38,0x2e,0x63,0x76,0x30,0x34,0x0c,0x75,0x6e,0x69,0x30,0x34,0x33,0x36,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69, 0x30,0x34,0x33,0x41,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x35,0x43,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x39,0x42,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x34,0x34,0x33,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e,0x69,0x30,0x34,0x35,0x45,0x2e,0x63,0x76,0x31,0x31,0x0c,0x75,0x6e, 0x69,0x30,0x34,0x34,0x31,0x2e,0x63,0x76,0x39,0x39,0x05,0x41,0x6c,0x70,0x68,0x61,0x04,0x42,0x65,0x74,0x61,0x05,0x47,0x61,0x6d,0x6d,0x61,0x07,0x75,0x6e,0x69,0x30,0x33,0x39,0x34,0x07,0x45,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x04,0x5a,0x65,0x74,0x61,0x03,0x45,0x74,0x61,0x05,0x54,0x68,0x65,0x74,0x61,0x04,0x49,0x6f,0x74,0x61,0x05, 0x4b,0x61,0x70,0x70,0x61,0x06,0x4c,0x61,0x6d,0x62,0x64,0x61,0x02,0x4d,0x75,0x02,0x4e,0x75,0x02,0x58,0x69,0x07,0x4f,0x6d,0x69,0x63,0x72,0x6f,0x6e,0x02,0x50,0x69,0x03,0x52,0x68,0x6f,0x05,0x53,0x69,0x67,0x6d,0x61,0x03,0x54,0x61,0x75,0x07,0x55,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x03,0x50,0x68,0x69,0x03,0x43,0x68,0x69,0x03,0x50, 0x73,0x69,0x07,0x75,0x6e,0x69,0x30,0x33,0x41,0x39,0x0a,0x41,0x6c,0x70,0x68,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x45,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x74,0x6f,0x6e,0x6f,0x73,0x08,0x45,0x74,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x09,0x49,0x6f,0x74,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x4f,0x6d,0x69,0x63,0x72,0x6f,0x6e,0x74,0x6f,0x6e, 0x6f,0x73,0x0c,0x55,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x74,0x6f,0x6e,0x6f,0x73,0x0a,0x4f,0x6d,0x65,0x67,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x49,0x6f,0x74,0x61,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x0f,0x55,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x07,0x75,0x6e,0x69,0x30,0x33,0x43,0x46,0x0a, 0x4b,0x61,0x70,0x70,0x61,0x2e,0x63,0x76,0x30,0x38,0x0c,0x75,0x6e,0x69,0x30,0x33,0x43,0x46,0x2e,0x63,0x76,0x30,0x38,0x05,0x61,0x6c,0x70,0x68,0x61,0x04,0x62,0x65,0x74,0x61,0x05,0x67,0x61,0x6d,0x6d,0x61,0x05,0x64,0x65,0x6c,0x74,0x61,0x07,0x65,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x04,0x7a,0x65,0x74,0x61,0x03,0x65,0x74,0x61,0x05, 0x74,0x68,0x65,0x74,0x61,0x04,0x69,0x6f,0x74,0x61,0x05,0x6b,0x61,0x70,0x70,0x61,0x06,0x6c,0x61,0x6d,0x62,0x64,0x61,0x07,0x75,0x6e,0x69,0x30,0x33,0x42,0x43,0x02,0x6e,0x75,0x02,0x78,0x69,0x07,0x6f,0x6d,0x69,0x63,0x72,0x6f,0x6e,0x03,0x72,0x68,0x6f,0x07,0x75,0x6e,0x69,0x30,0x33,0x43,0x32,0x05,0x73,0x69,0x67,0x6d,0x61,0x03, 0x74,0x61,0x75,0x07,0x75,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x03,0x70,0x68,0x69,0x03,0x63,0x68,0x69,0x03,0x70,0x73,0x69,0x05,0x6f,0x6d,0x65,0x67,0x61,0x09,0x69,0x6f,0x74,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x69,0x6f,0x74,0x61,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x11,0x69,0x6f,0x74,0x61,0x64,0x69,0x65,0x72,0x65,0x73,0x69, 0x73,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x75,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x74,0x6f,0x6e,0x6f,0x73,0x0f,0x75,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x14,0x75,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x6f,0x6d,0x69,0x63,0x72,0x6f,0x6e, 0x74,0x6f,0x6e,0x6f,0x73,0x0a,0x6f,0x6d,0x65,0x67,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0a,0x61,0x6c,0x70,0x68,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x0c,0x65,0x70,0x73,0x69,0x6c,0x6f,0x6e,0x74,0x6f,0x6e,0x6f,0x73,0x08,0x65,0x74,0x61,0x74,0x6f,0x6e,0x6f,0x73,0x07,0x75,0x6e,0x69,0x30,0x33,0x44,0x37,0x07,0x75,0x6e,0x69,0x30,0x33,0x44, 0x35,0x07,0x75,0x6e,0x69,0x30,0x33,0x44,0x36,0x0a,0x6b,0x61,0x70,0x70,0x61,0x2e,0x63,0x76,0x30,0x38,0x0a,0x67,0x61,0x6d,0x6d,0x61,0x2e,0x63,0x76,0x31,0x31,0x0b,0x6c,0x61,0x6d,0x62,0x64,0x61,0x2e,0x63,0x76,0x31,0x31,0x06,0x75,0x31,0x36,0x39,0x31,0x30,0x06,0x75,0x31,0x44,0x35,0x33,0x38,0x06,0x75,0x31,0x44,0x35,0x33,0x39, 0x07,0x75,0x6e,0x69,0x32,0x31,0x30,0x32,0x06,0x75,0x31,0x44,0x35,0x33,0x42,0x06,0x75,0x31,0x44,0x35,0x33,0x43,0x06,0x75,0x31,0x44,0x35,0x33,0x44,0x06,0x75,0x31,0x44,0x35,0x33,0x45,0x07,0x75,0x6e,0x69,0x32,0x31,0x30,0x44,0x06,0x75,0x31,0x44,0x35,0x34,0x30,0x06,0x75,0x31,0x44,0x35,0x34,0x31,0x06,0x75,0x31,0x44,0x35,0x34, 0x32,0x06,0x75,0x31,0x44,0x35,0x34,0x33,0x06,0x75,0x31,0x44,0x35,0x34,0x34,0x07,0x75,0x6e,0x69,0x32,0x31,0x31,0x35,0x06,0x75,0x31,0x44,0x35,0x34,0x36,0x07,0x75,0x6e,0x69,0x32,0x31,0x31,0x39,0x07,0x75,0x6e,0x69,0x32,0x31,0x31,0x41,0x07,0x75,0x6e,0x69,0x32,0x31,0x31,0x44,0x06,0x75,0x31,0x44,0x35,0x34,0x41,0x06,0x75,0x31, 0x44,0x35,0x34,0x42,0x06,0x75,0x31,0x44,0x35,0x34,0x43,0x06,0x75,0x31,0x44,0x35,0x34,0x44,0x06,0x75,0x31,0x44,0x35,0x34,0x45,0x06,0x75,0x31,0x44,0x35,0x34,0x46,0x06,0x75,0x31,0x44,0x35,0x35,0x30,0x07,0x75,0x6e,0x69,0x32,0x31,0x32,0x34,0x06,0x75,0x31,0x44,0x35,0x35,0x32,0x06,0x75,0x31,0x44,0x35,0x35,0x33,0x06,0x75,0x31, 0x44,0x35,0x35,0x34,0x06,0x75,0x31,0x44,0x35,0x35,0x35,0x06,0x75,0x31,0x44,0x35,0x35,0x36,0x06,0x75,0x31,0x44,0x35,0x35,0x37,0x06,0x75,0x31,0x44,0x35,0x35,0x38,0x06,0x75,0x31,0x44,0x35,0x35,0x39,0x06,0x75,0x31,0x44,0x35,0x35,0x41,0x06,0x75,0x31,0x44,0x35,0x35,0x42,0x06,0x75,0x31,0x44,0x35,0x35,0x43,0x06,0x75,0x31,0x44, 0x35,0x35,0x44,0x06,0x75,0x31,0x44,0x35,0x35,0x45,0x06,0x75,0x31,0x44,0x35,0x35,0x46,0x06,0x75,0x31,0x44,0x35,0x36,0x30,0x06,0x75,0x31,0x44,0x35,0x36,0x31,0x06,0x75,0x31,0x44,0x35,0x36,0x32,0x06,0x75,0x31,0x44,0x35,0x36,0x33,0x06,0x75,0x31,0x44,0x35,0x36,0x34,0x06,0x75,0x31,0x44,0x35,0x36,0x35,0x06,0x75,0x31,0x44,0x35, 0x36,0x36,0x06,0x75,0x31,0x44,0x35,0x36,0x37,0x06,0x75,0x31,0x44,0x35,0x36,0x38,0x06,0x75,0x31,0x44,0x35,0x36,0x39,0x06,0x75,0x31,0x44,0x35,0x36,0x41,0x06,0x75,0x31,0x44,0x35,0x36,0x42,0x09,0x7a,0x65,0x72,0x6f,0x2e,0x7a,0x65,0x72,0x6f,0x08,0x74,0x77,0x6f,0x2e,0x63,0x76,0x31,0x38,0x08,0x73,0x69,0x78,0x2e,0x63,0x76,0x31, 0x38,0x09,0x6e,0x69,0x6e,0x65,0x2e,0x63,0x76,0x31,0x38,0x0a,0x65,0x69,0x67,0x68,0x74,0x2e,0x63,0x76,0x31,0x39,0x09,0x66,0x69,0x76,0x65,0x2e,0x63,0x76,0x32,0x30,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x30,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x31,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x32,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x33, 0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x34,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x35,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x36,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x37,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x38,0x07,0x75,0x6e,0x69,0x32,0x30,0x38,0x39,0x09,0x7a,0x65,0x72,0x6f,0x2e,0x64,0x6e,0x6f,0x6d,0x08,0x6f,0x6e,0x65,0x2e,0x64, 0x6e,0x6f,0x6d,0x08,0x74,0x77,0x6f,0x2e,0x64,0x6e,0x6f,0x6d,0x0a,0x74,0x68,0x72,0x65,0x65,0x2e,0x64,0x6e,0x6f,0x6d,0x09,0x66,0x6f,0x75,0x72,0x2e,0x64,0x6e,0x6f,0x6d,0x09,0x66,0x69,0x76,0x65,0x2e,0x64,0x6e,0x6f,0x6d,0x08,0x73,0x69,0x78,0x2e,0x64,0x6e,0x6f,0x6d,0x0a,0x73,0x65,0x76,0x65,0x6e,0x2e,0x64,0x6e,0x6f,0x6d,0x0a, 0x65,0x69,0x67,0x68,0x74,0x2e,0x64,0x6e,0x6f,0x6d,0x09,0x6e,0x69,0x6e,0x65,0x2e,0x64,0x6e,0x6f,0x6d,0x09,0x7a,0x65,0x72,0x6f,0x2e,0x6e,0x75,0x6d,0x72,0x08,0x6f,0x6e,0x65,0x2e,0x6e,0x75,0x6d,0x72,0x08,0x74,0x77,0x6f,0x2e,0x6e,0x75,0x6d,0x72,0x0a,0x74,0x68,0x72,0x65,0x65,0x2e,0x6e,0x75,0x6d,0x72,0x09,0x66,0x6f,0x75,0x72, 0x2e,0x6e,0x75,0x6d,0x72,0x09,0x66,0x69,0x76,0x65,0x2e,0x6e,0x75,0x6d,0x72,0x08,0x73,0x69,0x78,0x2e,0x6e,0x75,0x6d,0x72,0x0a,0x73,0x65,0x76,0x65,0x6e,0x2e,0x6e,0x75,0x6d,0x72,0x0a,0x65,0x69,0x67,0x68,0x74,0x2e,0x6e,0x75,0x6d,0x72,0x09,0x6e,0x69,0x6e,0x65,0x2e,0x6e,0x75,0x6d,0x72,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x30, 0x07,0x75,0x6e,0x69,0x30,0x30,0x42,0x39,0x07,0x75,0x6e,0x69,0x30,0x30,0x42,0x32,0x07,0x75,0x6e,0x69,0x30,0x30,0x42,0x33,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x34,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x35,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x36,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x37,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x38, 0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x39,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x32,0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x36,0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x39,0x2e,0x63,0x76,0x31,0x38,0x0d,0x74,0x77,0x6f,0x2e,0x64,0x6e,0x6f,0x6d,0x2e,0x63,0x76,0x31,0x38,0x0d,0x73,0x69, 0x78,0x2e,0x64,0x6e,0x6f,0x6d,0x2e,0x63,0x76,0x31,0x38,0x0e,0x6e,0x69,0x6e,0x65,0x2e,0x64,0x6e,0x6f,0x6d,0x2e,0x63,0x76,0x31,0x38,0x0d,0x74,0x77,0x6f,0x2e,0x6e,0x75,0x6d,0x72,0x2e,0x63,0x76,0x31,0x38,0x0d,0x73,0x69,0x78,0x2e,0x6e,0x75,0x6d,0x72,0x2e,0x63,0x76,0x31,0x38,0x0e,0x6e,0x69,0x6e,0x65,0x2e,0x6e,0x75,0x6d,0x72, 0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x30,0x30,0x42,0x32,0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x32,0x30,0x37,0x36,0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x32,0x30,0x37,0x39,0x2e,0x63,0x76,0x31,0x38,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x38,0x2e,0x63,0x76,0x31,0x39,0x0f,0x65,0x69,0x67,0x68,0x74,0x2e, 0x64,0x6e,0x6f,0x6d,0x2e,0x63,0x76,0x31,0x39,0x0f,0x65,0x69,0x67,0x68,0x74,0x2e,0x6e,0x75,0x6d,0x72,0x2e,0x63,0x76,0x31,0x39,0x0c,0x75,0x6e,0x69,0x32,0x30,0x37,0x38,0x2e,0x63,0x76,0x31,0x39,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x35,0x2e,0x63,0x76,0x32,0x30,0x0e,0x66,0x69,0x76,0x65,0x2e,0x64,0x6e,0x6f,0x6d,0x2e,0x63,0x76, 0x32,0x30,0x0e,0x66,0x69,0x76,0x65,0x2e,0x6e,0x75,0x6d,0x72,0x2e,0x63,0x76,0x32,0x30,0x0c,0x75,0x6e,0x69,0x32,0x30,0x37,0x35,0x2e,0x63,0x76,0x32,0x30,0x0c,0x75,0x6e,0x69,0x32,0x30,0x38,0x30,0x2e,0x7a,0x65,0x72,0x6f,0x0e,0x7a,0x65,0x72,0x6f,0x2e,0x64,0x6e,0x6f,0x6d,0x2e,0x7a,0x65,0x72,0x6f,0x0e,0x7a,0x65,0x72,0x6f,0x2e, 0x6e,0x75,0x6d,0x72,0x2e,0x7a,0x65,0x72,0x6f,0x0c,0x75,0x6e,0x69,0x32,0x30,0x37,0x30,0x2e,0x7a,0x65,0x72,0x6f,0x07,0x75,0x6e,0x69,0x30,0x41,0x45,0x41,0x07,0x75,0x6e,0x69,0x32,0x30,0x34,0x35,0x07,0x75,0x6e,0x69,0x32,0x30,0x34,0x36,0x07,0x75,0x6e,0x69,0x32,0x30,0x31,0x36,0x09,0x65,0x78,0x63,0x6c,0x61,0x6d,0x64,0x62,0x6c, 0x07,0x75,0x6e,0x69,0x32,0x30,0x33,0x44,0x0e,0x6f,0x6e,0x65,0x64,0x6f,0x74,0x65,0x6e,0x6c,0x65,0x61,0x64,0x65,0x72,0x07,0x75,0x6e,0x69,0x32,0x30,0x33,0x45,0x07,0x75,0x6e,0x69,0x32,0x30,0x33,0x46,0x0a,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x63,0x61,0x73,0x65,0x1b,0x70,0x65,0x72,0x69,0x6f,0x64,0x63,0x65,0x6e,0x74,0x65,0x72,0x65, 0x64,0x2e,0x6c,0x6f,0x63,0x6c,0x43,0x41,0x54,0x2e,0x63,0x61,0x73,0x65,0x16,0x70,0x65,0x72,0x69,0x6f,0x64,0x63,0x65,0x6e,0x74,0x65,0x72,0x65,0x64,0x2e,0x6c,0x6f,0x63,0x6c,0x43,0x41,0x54,0x07,0x75,0x6e,0x69,0x46,0x46,0x35,0x42,0x07,0x75,0x6e,0x69,0x46,0x46,0x35,0x44,0x07,0x75,0x6e,0x69,0x32,0x37,0x37,0x30,0x07,0x75,0x6e, 0x69,0x32,0x37,0x36,0x45,0x07,0x75,0x6e,0x69,0x32,0x37,0x37,0x31,0x07,0x75,0x6e,0x69,0x32,0x37,0x36,0x46,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x41,0x07,0x75,0x6e,0x69,0x32,0x37,0x43,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x42,0x07,0x75,0x6e, 0x69,0x32,0x37,0x43,0x36,0x07,0x75,0x6e,0x69,0x32,0x39,0x38,0x37,0x07,0x75,0x6e,0x69,0x32,0x39,0x38,0x38,0x07,0x75,0x6e,0x69,0x30,0x30,0x41,0x44,0x07,0x75,0x6e,0x69,0x32,0x30,0x31,0x30,0x0d,0x71,0x75,0x6f,0x74,0x65,0x72,0x65,0x76,0x65,0x72,0x73,0x65,0x64,0x07,0x75,0x6e,0x69,0x32,0x30,0x31,0x46,0x07,0x75,0x6e,0x69,0x32, 0x30,0x33,0x34,0x12,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x19,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x28,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x62, 0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x5f,0x62,0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x62,0x61,0x72,0x2e, 0x6c,0x69,0x67,0x61,0x13,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x1b,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x6c,0x65,0x73,0x73, 0x2e,0x6c,0x69,0x67,0x61,0x15,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x16,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x2e,0x6c,0x69,0x67,0x61,0x18,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x62,0x72,0x61, 0x63,0x65,0x6c,0x65,0x66,0x74,0x2e,0x6c,0x69,0x67,0x61,0x26,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x23,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x65,0x78,0x63, 0x6c,0x61,0x6d,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1c,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x78,0x63,0x6c,0x61,0x6d,0x2e,0x6c,0x69,0x67,0x61,0x12,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x5f,0x62,0x61, 0x72,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x62,0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x5f,0x62,0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x14,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0x6c,0x65,0x66,0x74,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x15,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0x6c,0x65, 0x66,0x74,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x1c,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0x72,0x69,0x67,0x68,0x74,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x12,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x70,0x65,0x72,0x69,0x6f,0x64,0x2e,0x6c,0x69,0x67,0x61,0x19,0x70,0x65,0x72, 0x69,0x6f,0x64,0x5f,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x70,0x65,0x72,0x69,0x6f,0x64,0x2e,0x6c,0x69,0x67,0x61,0x17,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x14,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x2e,0x6c, 0x69,0x67,0x61,0x11,0x70,0x65,0x72,0x69,0x6f,0x64,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x10,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x16,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x16,0x63,0x6f, 0x6c,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x13,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1b,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e, 0x6c,0x69,0x67,0x61,0x10,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x12,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x18,0x73,0x65,0x6d,0x69,0x63,0x6f,0x6c, 0x6f,0x6e,0x5f,0x73,0x65,0x6d,0x69,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x22,0x73,0x65,0x6d,0x69,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x73,0x65,0x6d,0x69,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x73,0x65,0x6d,0x69,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x12,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x78,0x63,0x6c, 0x61,0x6d,0x2e,0x6c,0x69,0x67,0x61,0x1d,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x62,0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x11,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x17,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65, 0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x14,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x70,0x65,0x72,0x69,0x6f,0x64,0x2e,0x6c,0x69,0x67,0x61,0x13,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x16,0x71,0x75,0x65,0x73,0x74,0x69,0x6f, 0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x13,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c, 0x69,0x67,0x61,0x1f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x2e,0x6c,0x69,0x67,0x61,0x15,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x13,0x61,0x73,0x74,0x65,0x72,0x69, 0x73,0x6b,0x5f,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61,0x19,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x70,0x61,0x72,0x65,0x6e,0x6c,0x65,0x66,0x74,0x2e,0x6c,0x69,0x67,0x61,0x19,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x62,0x72,0x61,0x63,0x65,0x6c,0x65,0x66,0x74,0x2e,0x6c,0x69,0x67, 0x61,0x1b,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0x6c,0x65,0x66,0x74,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x16,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x65, 0x78,0x63,0x6c,0x61,0x6d,0x2e,0x6c,0x69,0x67,0x61,0x18,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x25,0x6e, 0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x30,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65, 0x72,0x73,0x69,0x67,0x6e,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72, 0x65,0x2e,0x6c,0x69,0x67,0x61,0x24,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x5f,0x70,0x61,0x72,0x65,0x6e,0x6c,0x65,0x66,0x74,0x2e,0x6c,0x69,0x67,0x61,0x13,0x73,0x6c,0x61,0x73,0x68,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x2e,0x6c,0x69,0x67,0x61,0x1c, 0x73,0x6c,0x61,0x73,0x68,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x2e,0x6c,0x69,0x67,0x61,0x10,0x73,0x6c,0x61,0x73,0x68,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x16,0x73,0x6c,0x61,0x73,0x68,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e, 0x6c,0x69,0x67,0x61,0x12,0x73,0x6c,0x61,0x73,0x68,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10,0x73,0x6c,0x61,0x73,0x68,0x5f,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61,0x16,0x73,0x6c,0x61,0x73,0x68,0x5f,0x73,0x6c,0x61,0x73,0x68,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x16, 0x73,0x6c,0x61,0x73,0x68,0x5f,0x73,0x6c,0x61,0x73,0x68,0x5f,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61,0x14,0x73,0x6c,0x61,0x73,0x68,0x5f,0x62,0x61,0x63,0x6b,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61,0x14,0x62,0x61,0x63,0x6b,0x73,0x6c,0x61,0x73,0x68,0x5f,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61, 0x1e,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x5f,0x62,0x61,0x72,0x5f,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x5f,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x2e,0x6c,0x69,0x67,0x61,0x16,0x65,0x78,0x63,0x6c,0x61, 0x6d,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x73,0x73,0x31,0x39,0x1c,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x73,0x73,0x31,0x39,0x07,0x75,0x6e,0x69,0x32,0x37,0x45,0x38,0x07,0x75,0x6e,0x69,0x32,0x37,0x45,0x41,0x07,0x75, 0x6e,0x69,0x32,0x37,0x45,0x36,0x07,0x75,0x6e,0x69,0x32,0x37,0x45,0x39,0x07,0x75,0x6e,0x69,0x32,0x37,0x45,0x42,0x07,0x75,0x6e,0x69,0x32,0x37,0x45,0x37,0x09,0x61,0x6e,0x6f,0x74,0x65,0x6c,0x65,0x69,0x61,0x07,0x75,0x6e,0x69,0x30,0x33,0x37,0x45,0x06,0x45,0x4d,0x71,0x75,0x61,0x64,0x0e,0x5a,0x45,0x52,0x4f,0x57,0x49,0x44,0x54, 0x48,0x53,0x50,0x41,0x43,0x45,0x07,0x75,0x6e,0x69,0x30,0x30,0x41,0x30,0x02,0x43,0x52,0x07,0x75,0x6e,0x69,0x46,0x45,0x46,0x46,0x07,0x75,0x6e,0x69,0x32,0x30,0x42,0x46,0x04,0x64,0x6f,0x6e,0x67,0x04,0x45,0x75,0x72,0x6f,0x07,0x75,0x6e,0x69,0x32,0x30,0x42,0x34,0x07,0x75,0x6e,0x69,0x32,0x30,0x42,0x44,0x07,0x75,0x6e,0x69,0x32, 0x30,0x41,0x45,0x09,0x63,0x65,0x6e,0x74,0x2e,0x63,0x76,0x31,0x34,0x0b,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x2e,0x63,0x76,0x31,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x34,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x33,0x35,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x43,0x07,0x75,0x6e,0x69,0x32,0x32,0x43,0x38,0x07,0x75,0x6e,0x69,0x32,0x32,0x31, 0x39,0x07,0x75,0x6e,0x69,0x32,0x32,0x35,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x31,0x09,0x63,0x6f,0x6e,0x67,0x72,0x75,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x31,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x41,0x07,0x75,0x6e,0x69,0x32,0x32,0x43,0x45,0x07,0x75,0x6e,0x69,0x32,0x32,0x43,0x34,0x07,0x75,0x6e,0x69,0x32, 0x32,0x32,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x31,0x35,0x07,0x75,0x6e,0x69,0x32,0x32,0x32,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x33,0x38,0x07,0x75,0x6e,0x69,0x32,0x32,0x44,0x30,0x07,0x75,0x6e,0x69,0x32,0x32,0x46,0x31,0x07,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x41,0x07,0x75,0x6e,0x69,0x32, 0x32,0x45,0x45,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x45,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x43,0x0b,0x65,0x71,0x75,0x69,0x76,0x61,0x6c,0x65,0x6e,0x63,0x65,0x07,0x75,0x6e,0x69,0x32,0x32,0x34,0x44,0x07,0x75,0x6e,0x69,0x32,0x32,0x33,0x39,0x0b,0x65,0x78,0x69,0x73,0x74,0x65,0x6e,0x74,0x69,0x61,0x6c,0x08,0x67,0x72,0x61,0x64, 0x69,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x33,0x45,0x07,0x75,0x6e,0x69,0x32,0x39,0x34,0x41,0x07,0x75,0x6e,0x69,0x32,0x37,0x44,0x43,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x37,0x07,0x75,0x6e,0x69, 0x32,0x32,0x43,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x32,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x31,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x32,0x07,0x75,0x6e,0x69,0x32,0x32,0x45,0x46,0x07,0x75,0x6e,0x69,0x32,0x32,0x31,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x42,0x07,0x75,0x6e,0x69, 0x32,0x32,0x36,0x41,0x07,0x75,0x6e,0x69,0x32,0x32,0x42,0x38,0x07,0x75,0x6e,0x69,0x32,0x32,0x38,0x45,0x07,0x75,0x6e,0x69,0x32,0x41,0x30,0x30,0x07,0x75,0x6e,0x69,0x32,0x41,0x30,0x35,0x07,0x75,0x6e,0x69,0x32,0x41,0x30,0x36,0x07,0x75,0x6e,0x69,0x32,0x32,0x42,0x43,0x07,0x75,0x6e,0x69,0x32,0x32,0x43,0x32,0x07,0x75,0x6e,0x69, 0x32,0x32,0x43,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x34,0x37,0x07,0x75,0x6e,0x69,0x32,0x32,0x38,0x38,0x07,0x75,0x6e,0x69,0x32,0x32,0x38,0x39,0x07,0x75,0x6e,0x69,0x32,0x32,0x42,0x44,0x07,0x75,0x6e,0x69,0x32,0x32,0x42,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x34,0x39,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x43,0x0a,0x6e,0x6f,0x74, 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x44,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x46,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x31,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x32,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x45,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x30,0x07,0x75,0x6e,0x69,0x32,0x32,0x45,0x32,0x09, 0x6e,0x6f,0x74,0x73,0x75,0x62,0x73,0x65,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x38,0x35,0x08,0x65,0x6d,0x70,0x74,0x79,0x73,0x65,0x74,0x0a,0x6c,0x6f,0x67,0x69,0x63,0x61,0x6c,0x61,0x6e,0x64,0x09,0x6c,0x6f,0x67,0x69,0x63,0x61,0x6c,0x6f,0x72,0x0c,0x69,0x6e,0x74,0x65,0x72,0x73,0x65,0x63,0x74,0x69,0x6f,0x6e,0x05,0x75,0x6e,0x69, 0x6f,0x6e,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x36,0x07,0x75,0x6e,0x69,0x30,0x30,0x42,0x35,0x07,0x75,0x6e,0x69,0x32,0x32,0x32,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x43,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x46,0x07,0x75,0x6e,0x69,0x32,0x33, 0x41,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x45,0x07,0x75,0x6e,0x69,0x46,0x45,0x36,0x32,0x07,0x75,0x6e,0x69,0x32,0x30,0x37,0x41,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x41,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x43,0x07,0x75,0x6e,0x69,0x32,0x32,0x33,0x37,0x07,0x75,0x6e,0x69,0x32,0x32,0x35,0x46,0x07,0x75,0x6e,0x69,0x32,0x32, 0x33,0x36,0x0c,0x72,0x65,0x66,0x6c,0x65,0x78,0x73,0x75,0x62,0x73,0x65,0x74,0x0e,0x72,0x65,0x66,0x6c,0x65,0x78,0x73,0x75,0x70,0x65,0x72,0x73,0x65,0x74,0x07,0x75,0x6e,0x69,0x32,0x39,0x31,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x43,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x42,0x07,0x75, 0x6e,0x69,0x32,0x32,0x43,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x41,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x32,0x07,0x75,0x6e,0x69,0x32,0x32,0x35,0x37,0x07,0x75,0x6e,0x69,0x32,0x32,0x31,0x38,0x07,0x73,0x69,0x6d,0x69,0x6c,0x61,0x72,0x07,0x75, 0x6e,0x69,0x32,0x32,0x39,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x31,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x46,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x45,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x30,0x07,0x75,0x6e,0x69,0x32,0x32,0x38,0x46,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x31,0x07,0x75, 0x6e,0x69,0x32,0x32,0x39,0x30,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x32,0x07,0x75,0x6e,0x69,0x32,0x32,0x43,0x36,0x07,0x75,0x6e,0x69,0x32,0x32,0x36,0x33,0x0c,0x70,0x72,0x6f,0x70,0x65,0x72,0x73,0x75,0x62,0x73,0x65,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x37,0x42,0x08,0x73,0x75,0x63,0x68,0x74,0x68,0x61,0x74,0x07,0x75,0x6e,0x69, 0x32,0x31,0x34,0x30,0x0e,0x70,0x72,0x6f,0x70,0x65,0x72,0x73,0x75,0x70,0x65,0x72,0x73,0x65,0x74,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x34,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x33,0x07,0x75,0x6e,0x69,0x32,0x32,0x30,0x34,0x09,0x74,0x68,0x65,0x72,0x65,0x66,0x6f,0x72,0x65,0x07,0x75,0x6e,0x69,0x32,0x32,0x34,0x42,0x09,0x75,0x6e, 0x69,0x76,0x65,0x72,0x73,0x61,0x6c,0x07,0x75,0x6e,0x69,0x32,0x32,0x46,0x30,0x07,0x75,0x6e,0x69,0x32,0x32,0x41,0x35,0x07,0x75,0x6e,0x69,0x32,0x32,0x42,0x42,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x42,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x44,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x43,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x38,0x07, 0x75,0x6e,0x69,0x32,0x32,0x39,0x36,0x0e,0x63,0x69,0x72,0x63,0x6c,0x65,0x6d,0x75,0x6c,0x74,0x69,0x70,0x6c,0x79,0x07,0x75,0x6e,0x69,0x32,0x32,0x39,0x39,0x0a,0x63,0x69,0x72,0x63,0x6c,0x65,0x70,0x6c,0x75,0x73,0x07,0x61,0x72,0x72,0x6f,0x77,0x75,0x70,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x37,0x0a,0x61,0x72,0x72,0x6f,0x77,0x72, 0x69,0x67,0x68,0x74,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x38,0x09,0x61,0x72,0x72,0x6f,0x77,0x64,0x6f,0x77,0x6e,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x39,0x09,0x61,0x72,0x72,0x6f,0x77,0x6c,0x65,0x66,0x74,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x36,0x09,0x61,0x72,0x72,0x6f,0x77,0x62,0x6f,0x74,0x68,0x09,0x61,0x72,0x72,0x6f,0x77, 0x75,0x70,0x64,0x6e,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x44,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x44,0x07,0x75,0x6e,0x69,0x32,0x31,0x39,0x45,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x30,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x32,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x33,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x35,0x07,0x75,0x6e,0x69, 0x32,0x31,0x41,0x36,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x37,0x07,0x75,0x6e,0x69,0x32,0x31,0x45,0x35,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x39,0x07,0x75,0x6e,0x69,0x32,0x31,0x41,0x41,0x07,0x75,0x6e,0x69,0x32,0x31,0x42,0x45,0x07,0x75,0x6e,0x69,0x32,0x31,0x43,0x39,0x0a,0x61,0x72,0x72,0x6f,0x77,0x64,0x62,0x6c,0x75,0x70,0x0d, 0x61,0x72,0x72,0x6f,0x77,0x64,0x62,0x6c,0x72,0x69,0x67,0x68,0x74,0x0c,0x61,0x72,0x72,0x6f,0x77,0x64,0x62,0x6c,0x64,0x6f,0x77,0x6e,0x0c,0x61,0x72,0x72,0x6f,0x77,0x64,0x62,0x6c,0x6c,0x65,0x66,0x74,0x0c,0x61,0x72,0x72,0x6f,0x77,0x64,0x62,0x6c,0x62,0x6f,0x74,0x68,0x07,0x75,0x6e,0x69,0x32,0x31,0x44,0x42,0x07,0x75,0x6e,0x69, 0x32,0x31,0x45,0x37,0x07,0x75,0x6e,0x69,0x32,0x31,0x45,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x34,0x07,0x75,0x6e,0x69,0x32,0x33,0x32,0x34,0x07,0x75,0x6e,0x69,0x32,0x37,0x39,0x34,0x07,0x75,0x6e,0x69,0x32,0x37,0x39,0x43,0x07,0x75,0x6e,0x69,0x32,0x37,0x39,0x44,0x07,0x75,0x6e,0x69,0x32,0x37,0x39,0x45,0x07,0x75,0x6e,0x69, 0x32,0x37,0x46,0x35,0x07,0x75,0x6e,0x69,0x32,0x37,0x46,0x36,0x07,0x75,0x6e,0x69,0x32,0x37,0x46,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x33,0x07,0x64,0x6e,0x62,0x6c,0x6f,0x63,0x6b,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x35,0x07,0x75,0x6e,0x69, 0x32,0x35,0x38,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x37,0x05,0x62,0x6c,0x6f,0x63,0x6b,0x07,0x75,0x70,0x62,0x6c,0x6f,0x63,0x6b,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x44,0x07,0x6c,0x66,0x62,0x6c,0x6f, 0x63,0x6b,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x38,0x39,0x07,0x72,0x74,0x62,0x6c,0x6f,0x63,0x6b,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x37,0x07,0x75,0x6e,0x69,0x32,0x35, 0x39,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x39,0x46,0x07,0x6c,0x74,0x73,0x68,0x61, 0x64,0x65,0x05,0x73,0x68,0x61,0x64,0x65,0x07,0x64,0x6b,0x73,0x68,0x61,0x64,0x65,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x46,0x06,0x63,0x69,0x72,0x63,0x6c,0x65,0x07,0x75,0x6e,0x69,0x32,0x35,0x45,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x44,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x44,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x46,0x36,0x07, 0x75,0x6e,0x69,0x32,0x35,0x43,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x45,0x0a,0x6f,0x70,0x65,0x6e,0x62,0x75,0x6c,0x6c,0x65,0x74,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x38,0x09,0x66,0x69,0x6c,0x6c,0x65, 0x64,0x62,0x6f,0x78,0x07,0x75,0x6e,0x69,0x32,0x35,0x41,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x41,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x41,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x45,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x45,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x45,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x45,0x41,0x07,0x75,0x6e,0x69, 0x32,0x35,0x45,0x42,0x07,0x74,0x72,0x69,0x61,0x67,0x75,0x70,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x36,0x07,0x74,0x72,0x69,0x61,0x67,0x64,0x6e,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x44,0x07,0x75,0x6e,0x69, 0x32,0x35,0x43,0x31,0x07,0x74,0x72,0x69,0x61,0x67,0x72,0x74,0x07,0x74,0x72,0x69,0x61,0x67,0x6c,0x66,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x45,0x07,0x75,0x6e,0x69, 0x32,0x35,0x43,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x42,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x43,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x34,0x07,0x75,0x6e,0x69, 0x32,0x35,0x35,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x30,0x07,0x75,0x6e,0x69, 0x32,0x35,0x36,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x46,0x07,0x75,0x6e,0x69, 0x32,0x35,0x34,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x34,0x07,0x75,0x6e,0x69, 0x32,0x35,0x35,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x46,0x07,0x75,0x6e,0x69, 0x32,0x35,0x30,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x37,0x07,0x75,0x6e,0x69, 0x32,0x35,0x37,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x42,0x07,0x75,0x6e,0x69, 0x32,0x35,0x32,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x41,0x07,0x75,0x6e,0x69, 0x32,0x35,0x34,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x33,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x31,0x07,0x75,0x6e,0x69, 0x32,0x35,0x34,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x34,0x07,0x75,0x6e,0x69, 0x32,0x35,0x37,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x37,0x44,0x07,0x75,0x6e,0x69, 0x32,0x35,0x33,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x30,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x36,0x07,0x75,0x6e,0x69, 0x32,0x35,0x32,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x34,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x38,0x07,0x75,0x6e,0x69, 0x32,0x35,0x35,0x43,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x36,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x45,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x36,0x07,0x75,0x6e,0x69, 0x32,0x35,0x34,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x39,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x37,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x42,0x07,0x75,0x6e,0x69, 0x32,0x35,0x35,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x42,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x46,0x07,0x75,0x6e,0x69,0x32,0x35,0x34,0x32,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x38,0x07,0x75,0x6e,0x69,0x32,0x35,0x32,0x30,0x07,0x75,0x6e,0x69,0x32,0x35,0x33,0x46,0x07,0x75,0x6e,0x69, 0x32,0x35,0x32,0x35,0x07,0x75,0x6e,0x69,0x32,0x35,0x31,0x44,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x41,0x07,0x75,0x6e,0x69,0x32,0x35,0x36,0x31,0x07,0x75,0x6e,0x69,0x32,0x35,0x35,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x36,0x07,0x75,0x6e,0x69, 0x32,0x33,0x34,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x46,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x43,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x41,0x07,0x75,0x6e,0x69, 0x32,0x33,0x36,0x32,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x32,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x31,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x36,0x07,0x75,0x6e,0x69, 0x32,0x33,0x34,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x37,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x34,0x07,0x75,0x6e,0x69, 0x32,0x33,0x35,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x37,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x39,0x35,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x32,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x43,0x07,0x75,0x6e,0x69, 0x32,0x33,0x36,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x34,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x39,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x37,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x43,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x38,0x07,0x75,0x6e,0x69, 0x32,0x33,0x34,0x34,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x37,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x46,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x31,0x07,0x75,0x6e,0x69, 0x32,0x33,0x35,0x30,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x34,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x33,0x46,0x07,0x75,0x6e,0x69, 0x32,0x33,0x33,0x37,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x37,0x32,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x31,0x07,0x75,0x6e,0x69,0x32,0x33,0x35,0x35,0x07,0x75,0x6e,0x69, 0x32,0x33,0x35,0x31,0x07,0x75,0x6e,0x69,0x32,0x33,0x34,0x46,0x07,0x75,0x6e,0x69,0x32,0x33,0x36,0x43,0x07,0x75,0x6e,0x69,0x32,0x36,0x38,0x37,0x07,0x75,0x6e,0x69,0x32,0x36,0x41,0x30,0x07,0x75,0x6e,0x69,0x32,0x36,0x41,0x31,0x07,0x75,0x6e,0x69,0x32,0x37,0x31,0x33,0x07,0x75,0x6e,0x69,0x32,0x37,0x31,0x35,0x07,0x75,0x6e,0x69, 0x32,0x37,0x31,0x37,0x07,0x75,0x6e,0x69,0x32,0x37,0x33,0x36,0x12,0x61,0x63,0x6b,0x6e,0x6f,0x77,0x6c,0x65,0x64,0x67,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x10,0x62,0x61,0x63,0x6b,0x73,0x70,0x61,0x63,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x06,0x6d,0x69,0x6e,0x75,0x74,0x65,0x06,0x73,0x65,0x63,0x6f,0x6e,0x64,0x07,0x75, 0x6e,0x69,0x32,0x31,0x31,0x33,0x07,0x75,0x6e,0x69,0x32,0x31,0x31,0x36,0x09,0x65,0x73,0x74,0x69,0x6d,0x61,0x74,0x65,0x64,0x0b,0x62,0x65,0x6c,0x6c,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x34,0x32,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x38,0x42,0x0d,0x63,0x61,0x6e,0x63,0x65,0x6c,0x63,0x6f,0x6e,0x74,0x72, 0x6f,0x6c,0x15,0x63,0x61,0x72,0x72,0x69,0x61,0x67,0x65,0x52,0x65,0x74,0x75,0x72,0x6e,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x33,0x07,0x75,0x6e,0x69,0x32,0x33,0x31,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x31,0x46,0x07,0x75,0x6e,0x69,0x32,0x33,0x31,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x31,0x43, 0x15,0x64,0x61,0x74,0x61,0x4c,0x69,0x6e,0x6b,0x45,0x73,0x63,0x61,0x70,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0d,0x64,0x65,0x6c,0x65,0x74,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x18,0x64,0x65,0x76,0x69,0x63,0x65,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x46,0x6f,0x75,0x72,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x17,0x64,0x65, 0x76,0x69,0x63,0x65,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x4f,0x6e,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x19,0x64,0x65,0x76,0x69,0x63,0x65,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x54,0x68,0x72,0x65,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x17,0x64,0x65,0x76,0x69,0x63,0x65,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x54,0x77,0x6f, 0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x33,0x38,0x41,0x12,0x65,0x6e,0x64,0x4f,0x66,0x4d,0x65,0x64,0x69,0x75,0x6d,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x10,0x65,0x6e,0x64,0x4f,0x66,0x54,0x65,0x78,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x18,0x65,0x6e,0x64,0x4f,0x66,0x54,0x72,0x61,0x6e,0x73,0x6d,0x69, 0x73,0x73,0x69,0x6f,0x6e,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x1d,0x65,0x6e,0x64,0x4f,0x66,0x54,0x72,0x61,0x6e,0x73,0x6d,0x69,0x73,0x73,0x69,0x6f,0x6e,0x42,0x6c,0x6f,0x63,0x6b,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0e,0x65,0x6e,0x71,0x75,0x69,0x72,0x79,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0d,0x65,0x73,0x63,0x61,0x70,0x65, 0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x14,0x66,0x69,0x6c,0x65,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0f,0x66,0x6f,0x72,0x6d,0x46,0x65,0x65,0x64,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x15,0x67,0x72,0x6f,0x75,0x70,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x63,0x6f,0x6e,0x74,0x72, 0x6f,0x6c,0x1b,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x74,0x61,0x6c,0x54,0x61,0x62,0x75,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x33,0x38,0x39,0x05,0x68,0x6f,0x75,0x73,0x65,0x07,0x75,0x6e,0x69,0x32,0x31,0x45,0x41,0x07,0x75,0x6e,0x69,0x32,0x33,0x32,0x42,0x07,0x75,0x6e,0x69, 0x32,0x33,0x32,0x36,0x07,0x75,0x6e,0x69,0x32,0x33,0x32,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x32,0x35,0x07,0x75,0x6e,0x69,0x32,0x31,0x44,0x46,0x07,0x75,0x6e,0x69,0x32,0x31,0x44,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x31,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x43,0x45,0x0f,0x6c,0x69,0x6e,0x65,0x46,0x65,0x65,0x64,0x63,0x6f,0x6e, 0x74,0x72,0x6f,0x6c,0x1a,0x6e,0x65,0x67,0x61,0x74,0x69,0x76,0x65,0x41,0x63,0x6b,0x6e,0x6f,0x77,0x6c,0x65,0x64,0x67,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0e,0x6e,0x65,0x77,0x6c,0x69,0x6e,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0b,0x6e,0x75,0x6c,0x6c,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x33, 0x46,0x42,0x07,0x75,0x6e,0x69,0x32,0x33,0x46,0x43,0x07,0x75,0x6e,0x69,0x32,0x42,0x35,0x38,0x07,0x75,0x6e,0x69,0x32,0x33,0x46,0x44,0x07,0x75,0x6e,0x69,0x32,0x33,0x46,0x45,0x07,0x75,0x6e,0x69,0x32,0x33,0x30,0x35,0x16,0x72,0x65,0x63,0x6f,0x72,0x64,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x63,0x6f,0x6e,0x74,0x72,0x6f, 0x6c,0x0b,0x72,0x65,0x70,0x6c,0x61,0x63,0x65,0x6d,0x65,0x6e,0x74,0x0e,0x73,0x68,0x69,0x66,0x74,0x49,0x6e,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0f,0x73,0x68,0x69,0x66,0x74,0x4f,0x75,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0c,0x73,0x70,0x61,0x63,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x15,0x73,0x74,0x61,0x72,0x74,0x4f, 0x66,0x48,0x65,0x61,0x64,0x69,0x6e,0x67,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x12,0x73,0x74,0x61,0x72,0x74,0x4f,0x66,0x54,0x65,0x78,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x11,0x73,0x75,0x62,0x73,0x74,0x69,0x74,0x75,0x74,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x16,0x73,0x79,0x6e,0x63,0x68,0x72,0x6f,0x6e,0x6f,0x75,0x73, 0x49,0x64,0x6c,0x65,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x07,0x75,0x6e,0x69,0x32,0x31,0x38,0x42,0x07,0x75,0x6e,0x69,0x32,0x31,0x38,0x41,0x14,0x75,0x6e,0x69,0x74,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x19,0x76,0x65,0x72,0x74,0x69,0x63,0x61,0x6c,0x54,0x61,0x62,0x75,0x6c,0x61,0x74, 0x69,0x6f,0x6e,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x0e,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x2e,0x63,0x76,0x31,0x35,0x07,0x75,0x6e,0x69,0x30,0x32,0x46,0x33,0x07,0x75,0x6e,0x69,0x30,0x32,0x46,0x37,0x18,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76, 0x31,0x34,0x15,0x6c,0x65,0x73,0x73,0x5f,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76,0x31,0x34,0x1d,0x6c,0x65,0x73,0x73,0x5f,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76,0x31,0x34,0x1d,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64, 0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76,0x31,0x35,0x27,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76,0x31,0x35,0x19,0x61,0x6d,0x70, 0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x63,0x76,0x31,0x35,0x12,0x61,0x74,0x5f,0x75,0x6e,0x64,0x65,0x72,0x73,0x63,0x6f,0x72,0x65,0x2e,0x6c,0x69,0x67,0x61,0x18,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x2e,0x6c,0x69, 0x67,0x61,0x22,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x2e,0x6c,0x69,0x67,0x61,0x14,0x61,0x6d,0x70,0x65,0x72,0x73,0x61,0x6e,0x64,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x62,0x61,0x72,0x5f,0x68, 0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x17,0x62,0x61,0x72,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x13,0x62,0x61,0x72,0x5f,0x62,0x72,0x61,0x63,0x65,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x15,0x62,0x61,0x72,0x5f,0x62,0x72,0x61,0x63,0x6b, 0x65,0x74,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x0c,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x13,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x10,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x18,0x62, 0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x12,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x14,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0e, 0x62,0x61,0x72,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x16,0x62,0x61,0x72,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10,0x62,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x13,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x5f,0x67,0x72, 0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0e,0x70,0x6c,0x75,0x73,0x5f,0x70,0x6c,0x75,0x73,0x2e,0x6c,0x69,0x67,0x61,0x13,0x70,0x6c,0x75,0x73,0x5f,0x70,0x6c,0x75,0x73,0x5f,0x70,0x6c,0x75,0x73,0x2e,0x6c,0x69,0x67,0x61,0x11,0x70,0x6c,0x75,0x73,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10, 0x65,0x71,0x75,0x61,0x6c,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x16,0x65,0x71,0x75,0x61,0x6c,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x17,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x10, 0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x16,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x18,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61, 0x12,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x14,0x65,0x71,0x75,0x61,0x6c,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c, 0x69,0x67,0x61,0x16,0x65,0x71,0x75,0x61,0x6c,0x5f,0x73,0x6c,0x61,0x73,0x68,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x13,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1b,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72, 0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x19,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0x72,0x69,0x67,0x68,0x74,0x2e,0x6c,0x69,0x67,0x61,0x12,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x12,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f, 0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x14,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x1b,0x67,0x72,0x65,0x61,0x74, 0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x1c,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65, 0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x17,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x14,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70, 0x68,0x65,0x6e,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x18,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x6c,0x65,0x73,0x73, 0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x14,0x6c,0x65,0x73,0x73,0x5f,0x63,0x6f,0x6c,0x6f,0x6e,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x1e,0x6c,0x65,0x73,0x73,0x5f,0x65,0x78,0x63,0x6c,0x61,0x6d,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x12, 0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x74,0x65,0x72,0x69,0x73,0x6b,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0d,0x6c,0x65,0x73,0x73,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x11,0x6c,0x65,0x73,0x73, 0x5f,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6c,0x65,0x73,0x73,0x5f,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6c,0x65,0x73,0x73,0x5f,0x62,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x10,0x6c,0x65,0x73,0x73,0x5f,0x64, 0x6f,0x6c,0x6c,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x18,0x6c,0x65,0x73,0x73,0x5f,0x64,0x6f,0x6c,0x6c,0x61,0x72,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x22,0x6c,0x65,0x73,0x73,0x5f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0x69,0x67,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x5f,0x68,0x79,0x70,0x68,0x65, 0x6e,0x2e,0x6c,0x69,0x67,0x61,0x0e,0x6c,0x65,0x73,0x73,0x5f,0x70,0x6c,0x75,0x73,0x2e,0x6c,0x69,0x67,0x61,0x16,0x6c,0x65,0x73,0x73,0x5f,0x70,0x6c,0x75,0x73,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x13,0x6c,0x65,0x73, 0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x62,0x61,0x72,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x1d,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e, 0x6c,0x69,0x67,0x61,0x17,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x14,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x11,0x6c,0x65,0x73,0x73,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c, 0x69,0x67,0x61,0x0e,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x15,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x14,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x13,0x6c,0x65, 0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x2e,0x6c,0x69,0x67,0x61,0x19,0x6c,0x65,0x73,0x73,0x5f,0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x2e,0x6c,0x69,0x67,0x61,0x14,0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x2e,0x6c,0x69,0x67,0x61, 0x1c,0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x1f,0x6c,0x65,0x73,0x73,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x2e,0x6c,0x69,0x67,0x61,0x0f,0x6c,0x65, 0x73,0x73,0x5f,0x73,0x6c,0x61,0x73,0x68,0x2e,0x6c,0x69,0x67,0x61,0x17,0x6c,0x65,0x73,0x73,0x5f,0x73,0x6c,0x61,0x73,0x68,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x16,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x68,0x79,0x70,0x68,0x65,0x6e,0x2e,0x6c,0x69,0x67,0x61,0x12,0x61,0x73,0x63, 0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x61,0x74,0x2e,0x6c,0x69,0x67,0x61,0x17,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x1a,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x2e,0x6c,0x69, 0x67,0x61,0x22,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x61,0x73,0x63,0x69,0x69,0x74,0x69,0x6c,0x64,0x65,0x5f,0x67,0x72,0x65,0x61,0x74,0x65,0x72,0x2e,0x6c,0x69,0x67,0x61,0x16,0x61,0x73,0x63,0x69,0x69,0x63,0x69,0x72,0x63,0x75,0x6d,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x15,0x65,0x71,0x75, 0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x73,0x73,0x31,0x39,0x1b,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x5f,0x65,0x71,0x75,0x61,0x6c,0x2e,0x6c,0x69,0x67,0x61,0x2e,0x73,0x73,0x31,0x39,0x07,0x75,0x6e,0x69,0x32,0x36,0x36,0x44,0x07,0x75,0x6e,0x69,0x32,0x36,0x36,0x46,0x07,0x75, 0x6e,0x69,0x30,0x33,0x37,0x34,0x07,0x75,0x6e,0x69,0x30,0x33,0x37,0x35,0x07,0x75,0x6e,0x69,0x30,0x32,0x42,0x43,0x07,0x75,0x6e,0x69,0x30,0x32,0x42,0x41,0x07,0x75,0x6e,0x69,0x30,0x32,0x43,0x39,0x07,0x75,0x6e,0x69,0x30,0x32,0x42,0x39,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x38,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x37,0x09,0x67, 0x72,0x61,0x76,0x65,0x63,0x6f,0x6d,0x62,0x09,0x61,0x63,0x75,0x74,0x65,0x63,0x6f,0x6d,0x62,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x42,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x43,0x2e,0x61,0x6c,0x74,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x43,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x07,0x75, 0x6e,0x69,0x30,0x33,0x30,0x41,0x09,0x74,0x69,0x6c,0x64,0x65,0x63,0x6f,0x6d,0x62,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x34,0x0d,0x68,0x6f,0x6f,0x6b,0x61,0x62,0x6f,0x76,0x65,0x63,0x6f,0x6d,0x62,0x07,0x75,0x6e,0x69,0x30,0x33,0x30,0x46,0x07,0x75,0x6e,0x69,0x30,0x33,0x31,0x32,0x07,0x75,0x6e,0x69,0x30,0x33,0x31,0x42,0x0c,0x64, 0x6f,0x74,0x62,0x65,0x6c,0x6f,0x77,0x63,0x6f,0x6d,0x62,0x07,0x75,0x6e,0x69,0x30,0x33,0x32,0x35,0x07,0x75,0x6e,0x69,0x30,0x33,0x32,0x36,0x07,0x75,0x6e,0x69,0x30,0x33,0x32,0x37,0x07,0x75,0x6e,0x69,0x30,0x33,0x32,0x38,0x07,0x75,0x6e,0x69,0x30,0x33,0x33,0x36,0x07,0x75,0x6e,0x69,0x30,0x33,0x33,0x37,0x07,0x75,0x6e,0x69,0x30, 0x33,0x33,0x38,0x0b,0x75,0x6e,0x69,0x30,0x33,0x32,0x36,0x2e,0x61,0x6c,0x74,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x38,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x37,0x2e,0x63,0x61,0x73,0x65,0x0e,0x67,0x72,0x61,0x76,0x65,0x63,0x6f,0x6d,0x62,0x2e,0x63,0x61,0x73,0x65,0x0e,0x61,0x63,0x75,0x74,0x65,0x63,0x6f, 0x6d,0x62,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x42,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x43,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30, 0x33,0x30,0x41,0x2e,0x63,0x61,0x73,0x65,0x0e,0x74,0x69,0x6c,0x64,0x65,0x63,0x6f,0x6d,0x62,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x34,0x2e,0x63,0x61,0x73,0x65,0x12,0x68,0x6f,0x6f,0x6b,0x61,0x62,0x6f,0x76,0x65,0x63,0x6f,0x6d,0x62,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x30,0x46,0x2e, 0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x31,0x31,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x31,0x32,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x31,0x42,0x2e,0x63,0x61,0x73,0x65,0x11,0x64,0x6f,0x74,0x62,0x65,0x6c,0x6f,0x77,0x63,0x6f,0x6d,0x62,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e, 0x69,0x30,0x33,0x32,0x34,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x32,0x36,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x32,0x37,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x32,0x38,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75,0x6e,0x69,0x30,0x33,0x32,0x45,0x2e,0x63,0x61,0x73,0x65,0x0c,0x75, 0x6e,0x69,0x30,0x33,0x33,0x31,0x2e,0x63,0x61,0x73,0x65,0x0d,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x2e,0x63,0x61,0x73,0x65,0x0e,0x64,0x6f,0x74,0x61,0x63,0x63,0x65,0x6e,0x74,0x2e,0x63,0x61,0x73,0x65,0x0a,0x67,0x72,0x61,0x76,0x65,0x2e,0x63,0x61,0x73,0x65,0x0a,0x61,0x63,0x75,0x74,0x65,0x2e,0x63,0x61,0x73,0x65,0x11,0x68, 0x75,0x6e,0x67,0x61,0x72,0x75,0x6d,0x6c,0x61,0x75,0x74,0x2e,0x63,0x61,0x73,0x65,0x0f,0x63,0x69,0x72,0x63,0x75,0x6d,0x66,0x6c,0x65,0x78,0x2e,0x63,0x61,0x73,0x65,0x0a,0x63,0x61,0x72,0x6f,0x6e,0x2e,0x63,0x61,0x73,0x65,0x0a,0x62,0x72,0x65,0x76,0x65,0x2e,0x63,0x61,0x73,0x65,0x09,0x72,0x69,0x6e,0x67,0x2e,0x63,0x61,0x73,0x65, 0x0a,0x74,0x69,0x6c,0x64,0x65,0x2e,0x63,0x61,0x73,0x65,0x0b,0x6d,0x61,0x63,0x72,0x6f,0x6e,0x2e,0x63,0x61,0x73,0x65,0x05,0x74,0x6f,0x6e,0x6f,0x73,0x0a,0x74,0x6f,0x6e,0x6f,0x73,0x2e,0x63,0x61,0x73,0x65,0x0d,0x64,0x69,0x65,0x72,0x65,0x73,0x69,0x73,0x74,0x6f,0x6e,0x6f,0x73,0x0b,0x62,0x72,0x65,0x76,0x65,0x63,0x6f,0x6d,0x62, 0x63,0x79,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x31,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x30,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x39,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x33,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x31,0x0b,0x75, 0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x30,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x39,0x0b,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x33,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x31,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x30,0x2e, 0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x39,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x33,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x31,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30, 0x33,0x30,0x30,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x39,0x2e,0x63,0x61,0x73,0x65,0x10,0x75,0x6e,0x69,0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x33,0x2e,0x63,0x61,0x73,0x65,0x07,0x75,0x6e,0x69,0x45,0x30,0x41,0x30,0x07,0x75,0x6e,0x69,0x45,0x30,0x41,0x31,0x07,0x75,0x6e,0x69,0x45,0x30, 0x41,0x32,0x07,0x75,0x6e,0x69,0x45,0x30,0x42,0x30,0x07,0x75,0x6e,0x69,0x45,0x30,0x42,0x31,0x07,0x75,0x6e,0x69,0x45,0x30,0x42,0x32,0x07,0x75,0x6e,0x69,0x45,0x30,0x42,0x33,0x0e,0x69,0x6f,0x67,0x6f,0x6e,0x65,0x6b,0x64,0x6f,0x74,0x6c,0x65,0x73,0x73,0x10,0x69,0x64,0x6f,0x74,0x62,0x65,0x6c,0x6f,0x77,0x64,0x6f,0x74,0x6c,0x65, 0x73,0x73,0x04,0x4e,0x55,0x4c,0x4c,0x03,0x53,0x50,0x43,0x00,0x00,0x01,0x00,0x01,0xff,0xff,0x00,0x0f,0x00,0x01,0x00,0x02,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0x00,0x02,0x00,0x4d,0x00,0x01,0x00,0x5d,0x00,0x01,0x00,0x5f,0x00,0x78,0x00,0x01,0x00,0x7a,0x00,0x7a,0x00,0x01,0x00,0x7c,0x00,0x86,0x00,0x01,0x00,0x89, 0x00,0xdd,0x00,0x01,0x00,0xe1,0x00,0xf2,0x00,0x01,0x00,0xf4,0x00,0xfc,0x00,0x01,0x00,0xfe,0x01,0x14,0x00,0x01,0x01,0x16,0x01,0x1f,0x00,0x01,0x01,0x21,0x01,0x3b,0x00,0x01,0x01,0x3d,0x01,0x49,0x00,0x01,0x01,0x4c,0x01,0x7c,0x00,0x01,0x01,0x7e,0x01,0xc2,0x00,0x01,0x01,0xc4,0x01,0xc5,0x00,0x01,0x01,0xc8,0x01,0xc8,0x00,0x01, 0x01,0xca,0x01,0xcc,0x00,0x01,0x01,0xcf,0x01,0xd6,0x00,0x01,0x01,0xd8,0x01,0xda,0x00,0x01,0x01,0xdc,0x01,0xe0,0x00,0x01,0x01,0xe2,0x01,0xe3,0x00,0x01,0x01,0xe9,0x01,0xea,0x00,0x01,0x01,0xed,0x01,0xf2,0x00,0x01,0x01,0xf4,0x01,0xf5,0x00,0x01,0x01,0xf7,0x01,0xfd,0x00,0x01,0x01,0xff,0x02,0x02,0x00,0x01,0x02,0x04,0x02,0x04, 0x00,0x01,0x02,0x06,0x02,0x0a,0x00,0x01,0x02,0x0c,0x02,0x0c,0x00,0x01,0x02,0x0f,0x02,0x10,0x00,0x01,0x02,0x13,0x02,0x1a,0x00,0x01,0x02,0x1e,0x02,0x1e,0x00,0x01,0x02,0x20,0x02,0x24,0x00,0x01,0x02,0x26,0x02,0x27,0x00,0x01,0x02,0x2e,0x02,0x2e,0x00,0x01,0x02,0x31,0x02,0x36,0x00,0x01,0x02,0x38,0x02,0x39,0x00,0x01,0x02,0x3b, 0x02,0x3b,0x00,0x01,0x02,0x3d,0x02,0x3d,0x00,0x01,0x02,0x40,0x02,0x46,0x00,0x01,0x02,0x48,0x02,0x49,0x00,0x01,0x02,0x4b,0x02,0x4f,0x00,0x01,0x02,0x51,0x02,0x53,0x00,0x01,0x02,0x55,0x02,0x57,0x00,0x01,0x02,0x59,0x02,0x5a,0x00,0x01,0x02,0x5c,0x02,0x5d,0x00,0x01,0x02,0x5f,0x02,0x5f,0x00,0x01,0x02,0x61,0x02,0x61,0x00,0x01, 0x02,0x63,0x02,0x64,0x00,0x01,0x02,0x66,0x02,0x66,0x00,0x01,0x02,0x69,0x02,0x6e,0x00,0x01,0x02,0x70,0x02,0x75,0x00,0x01,0x02,0x79,0x02,0x79,0x00,0x01,0x02,0x7b,0x02,0x7b,0x00,0x01,0x02,0x7d,0x02,0x7e,0x00,0x01,0x02,0x81,0x02,0x81,0x00,0x01,0x02,0x83,0x02,0x83,0x00,0x01,0x02,0x89,0x02,0x89,0x00,0x01,0x02,0x8b,0x02,0x8b, 0x00,0x01,0x02,0x8e,0x02,0x94,0x00,0x01,0x02,0x96,0x02,0x99,0x00,0x01,0x02,0x9c,0x02,0x9c,0x00,0x01,0x02,0xb0,0x02,0xb0,0x00,0x01,0x02,0xcc,0x02,0xcc,0x00,0x01,0x03,0xc3,0x03,0xc3,0x00,0x01,0x03,0xc7,0x03,0xc7,0x00,0x01,0x03,0xcd,0x03,0xcf,0x00,0x01,0x05,0x7d,0x05,0x7e,0x00,0x01,0x05,0xaa,0x05,0xaa,0x00,0x01,0x05,0xc5, 0x05,0xc5,0x00,0x01,0x05,0xd0,0x05,0xd0,0x00,0x01,0x05,0xeb,0x05,0xeb,0x00,0x01,0x05,0xed,0x05,0xed,0x00,0x01,0x06,0x05,0x06,0x06,0x00,0x02,0x06,0x68,0x06,0x7f,0x00,0x03,0x06,0x8d,0x06,0xa4,0x00,0x03,0x06,0xb3,0x06,0xc3,0x00,0x03,0x06,0xcb,0x06,0xcc,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x2a, 0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x0b,0x06,0x78,0x06,0x79,0x06,0x7a,0x06,0x7b,0x06,0x8d,0x06,0x9e,0x06,0x9f,0x06,0xa0,0x06,0xa1,0x06,0xa3,0x06,0xa4,0x00,0x02,0x00,0x03,0x06,0x68,0x06,0x76,0x00,0x00,0x06,0x8e,0x06,0x9c,0x00,0x0f,0x06,0xb3,0x06,0xc3,0x00,0x1e,0x00,0x01,0x00,0x03,0x06,0x6d,0x06,0x77,0x06,0x9d,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x16,0x00,0x24,0x00,0x0a,0x00,0x05,0x00,0x2c,0x00,0x34,0x00,0x3c,0x00,0x46,0x00,0x50,0x00,0x02,0x44,0x46,0x4c,0x54,0x00,0x1c,0x6c,0x61,0x74,0x6e,0x00,0x60,0x00,0x02,0x6d,0x61,0x72,0x6b,0x00,0x40,0x6d,0x6b,0x6d,0x6b,0x00,0x48,0x00,0x78,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x7e,0x00,0x04, 0x00,0x00,0x00,0x01,0x00,0x82,0x00,0x06,0x00,0x10,0x00,0x01,0x00,0x86,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x01,0x00,0x88,0x00,0x01,0x00,0x06,0x00,0x10,0x00,0x01,0x00,0x8a,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x34,0x00,0x08,0x41,0x5a,0x45,0x20,0x00,0x34, 0x43,0x41,0x54,0x20,0x00,0x34,0x43,0x52,0x54,0x20,0x00,0x34,0x4b,0x41,0x5a,0x20,0x00,0x34,0x4d,0x4f,0x4c,0x20,0x00,0x34,0x52,0x4f,0x4d,0x20,0x00,0x34,0x54,0x41,0x54,0x20,0x00,0x34,0x54,0x52,0x4b,0x20,0x00,0x34,0x00,0x00,0xff,0xff,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x42,0x01,0x66,0x00,0x01,0x00,0x54,0x02,0xca, 0x00,0x01,0x00,0x56,0x04,0xc6,0x00,0x05,0x03,0xc0,0x06,0x68,0x00,0x01,0x00,0x8e,0x00,0x8e,0x00,0x01,0x00,0xc4,0x00,0x76,0x00,0x01,0x00,0x54,0x00,0x9c,0x00,0x01,0x01,0xe8,0x00,0xe6,0x00,0x01,0x00,0x12,0x00,0x1c,0x00,0x01,0x00,0x24,0x00,0x0c,0x00,0x02,0x1d,0x1e,0x1d,0x24,0x00,0x01,0x00,0x03,0x06,0x6d,0x06,0x77,0x06,0x9d, 0x00,0x01,0x00,0x02,0x06,0x77,0x06,0x9d,0x00,0x03,0x00,0x00,0x1d,0x12,0x00,0x00,0x1d,0x18,0x00,0x00,0x1d,0x1e,0x00,0x02,0x00,0x03,0x06,0x68,0x06,0x7f,0x00,0x00,0x06,0x8d,0x06,0xa4,0x00,0x18,0x06,0xb3,0x06,0xc3,0x00,0x30,0x00,0x02,0x00,0x03,0x06,0x68,0x06,0x76,0x00,0x00,0x06,0x8e,0x06,0x9c,0x00,0x0f,0x06,0xb3,0x06,0xc3, 0x00,0x1e,0x00,0x0b,0x1c,0xf0,0x1c,0xea,0x1c,0xf6,0x1c,0xfc,0x1c,0xf6,0x1c,0xf0,0x1c,0xf0,0x1c,0xf6,0x1c,0xfc,0x1d,0x02,0x1d,0x08,0x00,0x01,0x00,0x0b,0x06,0x78,0x06,0x79,0x06,0x7a,0x06,0x7b,0x06,0x8d,0x06,0x9e,0x06,0x9f,0x06,0xa0,0x06,0xa1,0x06,0xa3,0x06,0xa4,0x00,0x02,0x00,0x04,0x06,0x68,0x06,0x6c,0x00,0x00,0x06,0x6e, 0x06,0x76,0x00,0x05,0x06,0x8e,0x06,0x9c,0x00,0x0e,0x06,0xb4,0x06,0xc3,0x00,0x1d,0x00,0x0b,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc0,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x00,0x1c,0xc6,0x00,0x2d, 0x1c,0x9e,0x1c,0x9e,0x1c,0xa4,0x1c,0xaa,0x1c,0xb0,0x1c,0xb6,0x1c,0xb6,0x1c,0xb6,0x1c,0xbc,0x1c,0xc2,0x1c,0xc8,0x1c,0xce,0x1c,0xd4,0x1c,0xda,0x1c,0xfe,0x1c,0xe0,0x1c,0xe6,0x1c,0xec,0x1c,0xf2,0x1d,0x16,0x1d,0x16,0x1d,0x16,0x1c,0xf8,0x1c,0xfe,0x1d,0x04,0x1d,0x0a,0x1d,0x10,0x1d,0x16,0x1d,0x1c,0x1d,0x22,0x1d,0x22,0x1d,0x28, 0x1d,0x40,0x1d,0x2e,0x1d,0x34,0x1d,0x3a,0x1d,0x40,0x1d,0x58,0x1d,0x58,0x1d,0x58,0x1d,0x58,0x1d,0x46,0x1d,0x4c,0x1d,0x52,0x1d,0x58,0x00,0x02,0x00,0x1b,0x00,0x60,0x00,0x74,0x00,0x00,0x00,0x78,0x00,0x78,0x00,0x15,0x00,0x8e,0x00,0x9d,0x00,0x16,0x00,0x9f,0x00,0xa0,0x00,0x26,0x00,0xbc,0x00,0xbc,0x00,0x28,0x00,0xdd,0x00,0xdd, 0x00,0x29,0x01,0x22,0x01,0x37,0x00,0x2a,0x01,0x3b,0x01,0x3b,0x00,0x40,0x01,0x4c,0x01,0x5d,0x00,0x41,0x01,0x64,0x01,0x65,0x00,0x53,0x01,0x67,0x01,0x68,0x00,0x55,0x01,0x84,0x01,0x88,0x00,0x57,0x01,0xb0,0x01,0xc2,0x00,0x5c,0x01,0xda,0x01,0xda,0x00,0x6f,0x02,0x02,0x02,0x02,0x00,0x70,0x02,0x1e,0x02,0x1e,0x00,0x71,0x02,0x46, 0x02,0x46,0x00,0x72,0x02,0x5f,0x02,0x5f,0x00,0x73,0x02,0x6d,0x02,0x6d,0x00,0x74,0x02,0x83,0x02,0x83,0x00,0x75,0x02,0x89,0x02,0x89,0x00,0x76,0x02,0x91,0x02,0x94,0x00,0x77,0x05,0xaa,0x05,0xaa,0x00,0x7b,0x05,0xc5,0x05,0xc5,0x00,0x7c,0x05,0xd0,0x05,0xd0,0x00,0x7d,0x05,0xeb,0x05,0xeb,0x00,0x7e,0x05,0xed,0x05,0xed,0x00,0x7f, 0x00,0x2f,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x5c,0x00,0x00,0x1c,0x62,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x68,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00, 0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x6e,0x00,0x00,0x1c,0x74,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x7a,0x00,0x00, 0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x7a,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x00,0x1c,0x80,0x00,0x80, 0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4, 0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xd4,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce, 0x1b,0xce,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xc8,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce, 0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xd4,0x1b,0xd4,0x1b,0xce,0x1b,0xce,0x1b,0xd4,0x1b,0xd4,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xce,0x1b,0xd4,0x1b,0xe0,0x1b,0xe0,0x1b,0xda,0x1b,0xe0, 0x00,0x41,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0x9c,0x00,0x00,0x1a,0xa2,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xa8,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x01, 0x1a,0xe4,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x03,0x19,0xd6,0x00,0x04,0x1a,0xea,0x00,0x04,0x1a,0xf0,0x00,0x04,0x1a,0xf6,0x00,0x02,0x19,0xd0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xae,0x00,0x00,0x1a,0xb4,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00, 0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x01,0x1a,0xc0,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x03,0x19,0xd6,0x00,0x02,0x19,0xd6,0x00,0x02, 0x19,0xd6,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xba,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x00, 0x1a,0xc0,0x00,0x00,0x1a,0xc0,0x00,0x02,0x00,0x45,0x00,0x01,0x00,0x5d,0x00,0x00,0x00,0x5f,0x00,0x78,0x00,0x5d,0x00,0x7a,0x00,0x7a,0x00,0x77,0x00,0x7c,0x00,0x86,0x00,0x78,0x00,0x89,0x00,0xdd,0x00,0x83,0x00,0xe1,0x00,0xf2,0x00,0xd8,0x00,0xf4,0x00,0xfc,0x00,0xea,0x00,0xfe,0x01,0x14,0x00,0xf3,0x01,0x16,0x01,0x1f,0x01,0x0a, 0x01,0x21,0x01,0x3b,0x01,0x14,0x01,0x3d,0x01,0x49,0x01,0x2f,0x01,0x4c,0x01,0x7c,0x01,0x3c,0x01,0x7e,0x01,0xc2,0x01,0x6d,0x01,0xc4,0x01,0xc5,0x01,0xb2,0x01,0xc8,0x01,0xc8,0x01,0xb4,0x01,0xca,0x01,0xcc,0x01,0xb5,0x01,0xcf,0x01,0xd6,0x01,0xb8,0x01,0xd8,0x01,0xda,0x01,0xc0,0x01,0xdc,0x01,0xe0,0x01,0xc3,0x01,0xe2,0x01,0xe3, 0x01,0xc8,0x01,0xe9,0x01,0xea,0x01,0xca,0x01,0xed,0x01,0xf2,0x01,0xcc,0x01,0xf4,0x01,0xf5,0x01,0xd2,0x01,0xf7,0x01,0xfd,0x01,0xd4,0x01,0xff,0x02,0x02,0x01,0xdb,0x02,0x04,0x02,0x04,0x01,0xdf,0x02,0x06,0x02,0x0a,0x01,0xe0,0x02,0x0c,0x02,0x0c,0x01,0xe5,0x02,0x0f,0x02,0x10,0x01,0xe6,0x02,0x13,0x02,0x1a,0x01,0xe8,0x02,0x1e, 0x02,0x1e,0x01,0xf0,0x02,0x20,0x02,0x21,0x01,0xf1,0x02,0x23,0x02,0x24,0x01,0xf3,0x02,0x26,0x02,0x27,0x01,0xf5,0x02,0x2e,0x02,0x2e,0x01,0xf7,0x02,0x31,0x02,0x36,0x01,0xf8,0x02,0x38,0x02,0x39,0x01,0xfe,0x02,0x3b,0x02,0x3b,0x02,0x00,0x02,0x40,0x02,0x46,0x02,0x01,0x02,0x48,0x02,0x49,0x02,0x08,0x02,0x4b,0x02,0x4f,0x02,0x0a, 0x02,0x51,0x02,0x53,0x02,0x0f,0x02,0x55,0x02,0x57,0x02,0x12,0x02,0x59,0x02,0x5a,0x02,0x15,0x02,0x5c,0x02,0x5d,0x02,0x17,0x02,0x5f,0x02,0x5f,0x02,0x19,0x02,0x61,0x02,0x61,0x02,0x1a,0x02,0x63,0x02,0x64,0x02,0x1b,0x02,0x66,0x02,0x66,0x02,0x1d,0x02,0x69,0x02,0x6e,0x02,0x1e,0x02,0x70,0x02,0x75,0x02,0x24,0x02,0x79,0x02,0x79, 0x02,0x2a,0x02,0x7b,0x02,0x7b,0x02,0x2b,0x02,0x7d,0x02,0x7e,0x02,0x2c,0x02,0x81,0x02,0x81,0x02,0x2e,0x02,0x83,0x02,0x83,0x02,0x2f,0x02,0x89,0x02,0x89,0x02,0x30,0x02,0x8b,0x02,0x8b,0x02,0x31,0x02,0x8e,0x02,0x94,0x02,0x32,0x02,0x96,0x02,0x99,0x02,0x39,0x02,0x9c,0x02,0x9c,0x02,0x3d,0x02,0xb0,0x02,0xb0,0x02,0x3e,0x02,0xcc, 0x02,0xcc,0x02,0x3f,0x03,0xc3,0x03,0xc3,0x02,0x40,0x03,0xc7,0x03,0xc7,0x02,0x41,0x03,0xcd,0x03,0xcf,0x02,0x42,0x05,0x7d,0x05,0x7e,0x02,0x45,0x05,0xaa,0x05,0xaa,0x02,0x47,0x06,0xcb,0x06,0xcc,0x02,0x48,0x02,0x4a,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0x66, 0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xe4,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0x66,0x00,0x00,0x1a,0xe8,0x1b,0xba,0x00,0x00,0x18,0xe4,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xe4,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xe4,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44, 0x1b,0xba,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xd2,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0x66,0x00,0x00,0x1a,0xe8,0x1b,0xba,0x00,0x00,0x18,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xde,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x18,0xe4,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00, 0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xe8,0x1b,0xba,0x00,0x00,0x19,0x26,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x19,0x14,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x19,0x1a,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x19,0x08,0x00,0x00, 0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x14,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x18,0x54,0x00,0x00,0x1c,0x1a,0x00,0x00, 0x00,0x00,0x18,0x5a,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x1c,0x14,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x18,0x5a,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x18,0x60,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x66, 0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0xc0,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x66,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x72,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x72,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x72,0x00,0x00,0x1b,0xc6, 0x1b,0xcc,0x00,0x00,0x18,0x6c,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x72,0x00,0x00,0x18,0x90,0x1b,0xcc,0x00,0x00,0x18,0x78,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x7e,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x84,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1b,0x2a,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00, 0x18,0x8a,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1b,0xc0,0x00,0x00,0x18,0x90,0x1b,0xcc,0x00,0x00,0x18,0x96,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0x9c,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x18,0xa2,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1b,0xc0,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1c,0x38,0x00,0x00, 0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x2a,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x18,0xae,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x18,0xae,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x18,0xae,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x18,0xae,0x00,0x00, 0x00,0x00,0x1b,0x66,0x00,0x00,0x18,0xae,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x18,0xa8,0x00,0x00,0x00,0x00,0x19,0x20,0x00,0x00,0x18,0xae,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38, 0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x19,0x20,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xe8, 0x1b,0xd2,0x00,0x00,0x19,0x26,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x19,0x14,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x19,0x1a,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0x30,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00, 0x18,0xb4,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x18,0xc6,0x00,0x00,0x18,0xcc,0x00,0x00,0x1c,0x50,0x18,0xba,0x00,0x00,0x18,0xcc,0x00,0x00,0x1c,0x50,0x18,0xc6,0x00,0x00,0x18,0xcc,0x00,0x00,0x1c,0x50,0x18,0xc6,0x00,0x00, 0x18,0xc0,0x00,0x00,0x1c,0x50,0x18,0xc6,0x00,0x00,0x18,0xcc,0x00,0x00,0x1c,0x50,0x18,0xc6,0x00,0x00,0x18,0xcc,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x54,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x66,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x66,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x18,0xd2, 0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x66,0x1c,0x3e,0x1a,0xe8,0x1c,0x4a,0x1c,0x50,0x18,0xd8,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x18,0xde,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x18,0xe4,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0xd8,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x1c,0x3e,0x1a,0xe8, 0x1c,0x4a,0x1c,0x50,0x19,0x26,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x19,0x14,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x4e,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x18,0xea,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0x4e,0x1c,0x3e,0x1a,0xe8,0x1c,0x4a,0x1c,0x50,0x18,0xf0,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50, 0x18,0xf6,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x18,0xfc,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x19,0x02,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x19,0x1a,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x1c,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x1b,0xb4,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x1b,0xb4, 0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38, 0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x1c,0x50,0x1c,0x38,0x19,0x0e,0x1c,0x44, 0x1c,0x4a,0x00,0x00,0x1b,0x54,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x66,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x66,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xd8,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x19,0x0e,0x1a,0xe8,0x1c,0x4a,0x00,0x00,0x19,0x26,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00, 0x19,0x14,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x54,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x19,0x0e,0x1a,0xe8,0x1c,0x4a,0x00,0x00,0x19,0x26,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x19,0x14,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xd8,0x19,0x0e, 0x1c,0x44,0x1c,0x4a,0x00,0x00,0x19,0x02,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x19,0x1a,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x19,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x08,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xd8,0x19,0x0e,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x19,0x26,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38, 0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xe8,0x00,0x00,0x00,0x00,0x19,0x26,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x19,0x14,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x19,0x1a,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x19,0x20,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50, 0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x19,0x26,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00, 0x1a,0xbe,0x00,0x00,0x00,0x00,0x1c,0x38,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x02,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0xfe,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x0a,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x2c,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x0a,0x00,0x00,0x19,0x56,0x1b,0x6c, 0x00,0x00,0x19,0x2c,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x32,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x4a,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x0a,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x0a,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x38,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x0a, 0x00,0x00,0x19,0x56,0x1b,0x6c,0x00,0x00,0x19,0x3e,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x44,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x4a,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x50,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1c,0x02,0x00,0x00,0x19,0x56,0x1b,0x6c,0x00,0x00,0x19,0x5c,0x00,0x00,0x1c,0x1a, 0x1b,0x6c,0x00,0x00,0x19,0x62,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x68,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1c,0x02,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x19,0x6e,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1a,0x10,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x1b,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x20,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x19,0x74,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x19,0x7a,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x1c,0x20,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x19,0x7a,0x00,0x00, 0x1c,0x26,0x00,0x00,0x00,0x00,0x19,0x80,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1b,0xfc,0x1c,0x32,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x1c,0x4a, 0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x16,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x00,0x00,0x1a,0xe8,0x1c,0x4a,0x00,0x00,0x1a,0x1c,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x22,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x28,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xea, 0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x1a,0xe8,0x1c,0x4a,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0xfa,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x0c,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x1b,0x18,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x19,0x86,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0x8c,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0x92,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0x92,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00, 0x19,0x92,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0x98,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0x9e,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x19,0xa4,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x19,0xaa,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1b,0x84,0x00,0x00,0x1c,0x44,0x1c,0x68,0x00,0x00,0x1c,0x5c,0x00,0x00, 0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xb0,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xb6,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xb6,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xb6,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x56,0x1c,0x68, 0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x62,0x1c,0x68,0x00,0x00,0x19,0xbc,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xc2,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xc8,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x19,0xce,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x1b,0x8a, 0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x19,0xd4,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x19,0xda,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1b,0xde,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xf8,0x00,0x00,0x1b,0xd2, 0x00,0x00,0x1c,0x50,0x19,0xe0,0x00,0x00,0x1b,0xd2,0x00,0x00,0x1c,0x50,0x19,0xf8,0x00,0x00,0x1b,0xd2,0x00,0x00,0x1c,0x50,0x19,0xf8,0x00,0x00,0x19,0xe6,0x00,0x00,0x1c,0x50,0x19,0xec,0x00,0x00,0x1c,0x44,0x00,0x00,0x19,0xf2,0x19,0xf8,0x00,0x00,0x1b,0xd2,0x00,0x00,0x1c,0x50,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00, 0x1c,0x02,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x19,0xfe,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x1a,0x04,0x00,0x00,0x00,0x00,0x1a,0x0a,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1a,0x10,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x1b,0xf6, 0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xa8,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xae,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xae,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xae,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x16,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xae,0x1b,0xf6,0x1a,0xe8,0x1c,0x4a, 0x1b,0xfc,0x1a,0x1c,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x22,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x28,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xea,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1c,0x32,0x1b,0xf6,0x1a,0xe8,0x1c,0x4a,0x1b,0xfc,0x1a,0xf4,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0xfa, 0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x34,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x2e,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x34,0x1b,0xf6,0x1a,0xe8,0x1c,0x4a,0x1b,0xfc,0x1a,0x3a,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x40,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1a,0x46,0x1b,0xf6,0x1c,0x44, 0x1c,0x4a,0x1b,0xfc,0x1b,0x06,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0x0c,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1c,0x32,0x1b,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x1b,0xf6,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x1b,0xf6,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x18,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc, 0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x5a,0x00,0x00,0x1b,0x60,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1a,0xd6,0x00,0x00,0x1a,0x4c,0x00,0x00,0x00,0x00,0x1a,0xc4,0x00,0x00,0x1a,0x4c,0x00,0x00,0x00,0x00,0x1a,0xca,0x00,0x00,0x1a,0x4c,0x00,0x00,0x00,0x00,0x1a,0xd6,0x00,0x00, 0x1a,0x52,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1a,0xbe,0x00,0x00, 0x00,0x00,0x1a,0x58,0x00,0x00,0x1a,0x82,0x00,0x00,0x1b,0xfc,0x1a,0x58,0x00,0x00,0x1a,0x82,0x00,0x00,0x1b,0xfc,0x1a,0x58,0x00,0x00,0x1a,0x82,0x00,0x00,0x1b,0xfc,0x1a,0x58,0x00,0x00,0x1a,0x82,0x00,0x00,0x1b,0xfc,0x1a,0x58,0x00,0x00,0x1a,0x88,0x00,0x00,0x1b,0xfc,0x1c,0x32,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xa8, 0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xae,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xea,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x5e,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x64,0x1b,0xf0,0x1c,0x44, 0x1c,0x4a,0x00,0x00,0x1a,0x6a,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0x70,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1a,0xe8,0x1c,0x4a,0x00,0x00,0x1a,0xf4,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1a,0xfa,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x1b,0x00,0x00,0x00,0x00,0x00, 0x1b,0xa8,0x00,0x00,0x1b,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1a,0xee,0x00,0x00,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1b,0x00,0x00,0x00,0x00,0x00,0x1a,0xfa,0x00,0x00,0x1b,0x00,0x00,0x00,0x00,0x00,0x1b,0x18,0x00,0x00,0x1b,0x00,0x00,0x00,0x00,0x00,0x1b,0x06,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x0c,0x1b,0xf0, 0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x12,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0x18,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae, 0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1a,0xe2,0x00,0x00,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1a,0xfa,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x0c,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x18,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x1b,0xfc,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00,0x1b,0xfc,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x1b,0xfc,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x1b,0xfc,0x1a,0x7c,0x00,0x00,0x1b,0xc6,0x00,0x00,0x00,0x00,0x1a,0x76,0x00,0x00,0x1b,0xc6,0x00,0x00,0x00,0x00, 0x1a,0x7c,0x00,0x00,0x1b,0xc6,0x00,0x00,0x00,0x00,0x1a,0x7c,0x00,0x00,0x1a,0xb2,0x00,0x00,0x00,0x00,0x1a,0x7c,0x00,0x00,0x1b,0xc6,0x00,0x00,0x00,0x00,0x1a,0x7c,0x00,0x00,0x1b,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x82,0x00,0x00,0x1a,0x8e,0x00,0x00,0x00,0x00,0x1a,0x82,0x00,0x00,0x1a,0x8e,0x00,0x00,0x00,0x00, 0x1a,0x82,0x00,0x00,0x1a,0x8e,0x00,0x00,0x00,0x00,0x1a,0x82,0x00,0x00,0x1a,0x8e,0x00,0x00,0x00,0x00,0x1a,0x88,0x00,0x00,0x1a,0x8e,0x1c,0x32,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1a,0x9a,0x00,0x00, 0x00,0x00,0x1b,0xae,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1a,0x94,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1a,0x9a,0x00,0x00,0x00,0x00,0x1b,0x9c,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1a,0xa0,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1a,0xa6,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1a,0xb8, 0x00,0x00,0x1b,0xd2,0x00,0x00,0x00,0x00,0x1a,0xac,0x00,0x00,0x1b,0xd2,0x00,0x00,0x00,0x00,0x1a,0xb8,0x00,0x00,0x1b,0xd2,0x00,0x00,0x00,0x00,0x1a,0xb8,0x00,0x00,0x1a,0xb2,0x00,0x00,0x00,0x00,0x1a,0xb8,0x00,0x00,0x1b,0xd2,0x00,0x00,0x00,0x00,0x1a,0xb8,0x00,0x00,0x1b,0xd2,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00, 0x1c,0x38,0x00,0x00,0x1a,0xbe,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1a,0xd6,0x00,0x00,0x1a,0xd0,0x00,0x00,0x00,0x00,0x1a,0xc4,0x00,0x00,0x1a,0xd0,0x00,0x00,0x00,0x00,0x1a,0xca,0x00,0x00,0x1a,0xd0,0x00,0x00,0x00,0x00,0x1a,0xd6,0x00,0x00, 0x1a,0xdc,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1a,0xe2,0x00,0x00,0x00,0x00,0x1a,0xf4,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1a,0xfa,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x0c,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x18,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0xa8,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0xae,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0xae, 0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0xea,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1a,0xe8,0x1b,0x1e,0x00,0x00,0x1a,0xf4,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1a,0xfa,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1b,0x00,0x1c,0x4a,0x00,0x00,0x1b,0xa8,0x1b,0xf0,0x1b,0x00, 0x1c,0x4a,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1a,0xee,0x1c,0x4a,0x00,0x00,0x1a,0xf4,0x1b,0xf0,0x1b,0x00,0x1c,0x4a,0x00,0x00,0x1a,0xfa,0x1b,0xf0,0x1b,0x00,0x1c,0x4a,0x00,0x00,0x1b,0x18,0x1b,0xf0,0x1b,0x00,0x1c,0x4a,0x00,0x00,0x1b,0x06,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0x0c,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00, 0x1c,0x32,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0x12,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1b,0x18,0x1b,0xf0,0x1c,0x44,0x1b,0x1e,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1c,0x38,0x00,0x00, 0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xc0,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1b,0x2a,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38, 0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x14,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x14,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x1b,0x5a,0x00,0x00,0x1b,0x60,0x00,0x00,0x00,0x00, 0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0x30,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x36,0x00,0x00, 0x1b,0x3c,0x00,0x00,0x00,0x00,0x1b,0x42,0x00,0x00,0x1c,0x0e,0x00,0x00,0x1b,0x48,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xd8,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1b,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x54,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0x5a, 0x00,0x00,0x1b,0x60,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x1c,0x1a,0x1b,0x6c,0x00,0x00,0x1b,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44, 0x1c,0x4a,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xde,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x1b,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x20,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00, 0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x56,0x1c,0x68, 0x00,0x00,0x1b,0x84,0x00,0x00,0x1c,0x56,0x1c,0x68,0x00,0x00,0x1b,0x8a,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x32,0x1b,0x96,0x00,0x00,0x1b,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xea,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1b,0xea,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x1b,0x9c,0x00,0x00,0x1b,0xa2,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xae,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00, 0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xc0,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00, 0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00, 0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xba,0x00,0x00,0x1b,0xc0,0x00,0x00,0x1b,0xc6,0x1b,0xcc,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1c,0x38, 0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x1b,0xd2,0x00,0x00,0x1b,0xd8,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44, 0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xde,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00, 0x1c,0x32,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1c,0x32,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x1b,0xf0, 0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1b,0xea,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x1b,0xf0,0x1c,0x44,0x1c,0x4a,0x00,0x00,0x1c,0x32,0x1b,0xf6,0x1c,0x44,0x1c,0x4a,0x1b,0xfc,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x02,0x00,0x00,0x1c,0x44,0x00,0x00, 0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x08,0x00,0x00,0x1c,0x0e,0x00,0x00,0x00,0x00,0x1c,0x20,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x1c,0x14,0x00,0x00,0x1c,0x1a,0x00,0x00,0x00,0x00,0x1c,0x38, 0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x20,0x00,0x00,0x1c,0x26,0x00,0x00,0x00,0x00,0x1c,0x38,0x00,0x00,0x1c,0x44,0x00,0x00,0x00,0x00,0x1c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x38,0x1c,0x3e,0x1c,0x44,0x1c,0x4a,0x1c,0x50,0x1c,0x5c,0x00,0x00,0x1c,0x56, 0x1c,0x68,0x00,0x00,0x1c,0x5c,0x00,0x00,0x1c,0x62,0x1c,0x68,0x00,0x00,0x00,0x01,0xff,0xb4,0x02,0x94,0x00,0x01,0xff,0xba,0x03,0x48,0x00,0x01,0xff,0x51,0x02,0x26,0x00,0x01,0xff,0x04,0x02,0x26,0x00,0x01,0xff,0x07,0x02,0xda,0x00,0x01,0xfe,0xd4,0xff,0x06,0x00,0x01,0xfe,0xd4,0xff,0x2b,0x00,0x01,0xfe,0xca,0xff,0x10,0x00,0x01, 0xfe,0xdb,0xff,0x35,0x00,0x01,0xfe,0xd4,0xff,0x10,0x00,0x01,0xfe,0xd4,0xff,0x3d,0x00,0x01,0xfe,0xca,0x00,0x00,0x00,0x01,0xfe,0xd4,0x00,0x00,0x00,0x01,0xfe,0xd4,0x03,0x09,0x00,0x01,0xfe,0xb3,0x03,0x11,0x00,0x01,0xfe,0xf5,0x03,0x11,0x00,0x01,0xfe,0xf9,0x03,0x11,0x00,0x01,0xfe,0xd4,0x03,0x11,0x00,0x01,0xfe,0xd4,0x03,0x44, 0x00,0x01,0xfe,0xd4,0x03,0x0c,0x00,0x01,0xfe,0xd4,0x02,0xe9,0x00,0x01,0xfe,0xd9,0x03,0x39,0x00,0x01,0xfe,0xae,0x03,0x11,0x00,0x01,0xfe,0xe0,0x03,0x70,0x00,0x01,0xfe,0xd4,0x03,0xb0,0x00,0x01,0xfe,0xb3,0x03,0xb6,0x00,0x01,0xfe,0xf5,0x03,0xb6,0x00,0x01,0xfe,0xf9,0x03,0xb6,0x00,0x01,0xfe,0xd4,0x03,0xe2,0x00,0x01,0xfe,0xd4, 0x03,0xb1,0x00,0x01,0xfe,0xd4,0x03,0x93,0x00,0x01,0xfe,0xd6,0x03,0xd4,0x00,0x01,0xfe,0xae,0x03,0xb6,0x00,0x01,0xfe,0xd4,0x03,0xb6,0x00,0x01,0xfe,0xd9,0x03,0xfc,0x00,0x01,0xfe,0xd4,0x03,0x7a,0x00,0x01,0xfe,0xd4,0x03,0xa2,0x00,0x01,0xff,0x1c,0x03,0x84,0x00,0x01,0xfe,0xf4,0x03,0x84,0x00,0x01,0xfe,0xf7,0x03,0xa2,0x00,0x01, 0xfe,0xd4,0x03,0xa0,0x00,0x01,0xff,0x17,0x03,0xfc,0x00,0x01,0xfe,0xf2,0x03,0xfc,0x00,0x01,0xfe,0xf7,0x03,0xfc,0x00,0x01,0xfe,0xd4,0x03,0xfc,0x00,0x01,0xfe,0xde,0x02,0x26,0x00,0x01,0xfe,0xca,0x02,0x26,0x00,0x01,0xfe,0xb6,0x02,0xda,0x00,0x01,0xfe,0xde,0x02,0xda,0x00,0x01,0xfe,0xca,0x02,0xda,0x00,0x01,0xfe,0xd4,0x02,0x26, 0x00,0x01,0xfe,0xd4,0x02,0xda,0x00,0x01,0x01,0x63,0x02,0x6d,0x00,0x01,0x02,0x44,0x02,0x26,0x00,0x01,0x02,0x44,0x02,0xda,0x00,0x01,0x02,0x44,0x04,0x65,0x00,0x01,0x03,0x0c,0x02,0xda,0x00,0x01,0xfe,0xec,0x02,0x26,0x00,0x01,0xfe,0xd4,0x01,0x45,0x00,0x01,0xfe,0xd4,0x01,0x18,0x00,0x01,0xfe,0xd4,0x01,0x13,0x00,0x01,0x01,0x5c, 0x03,0xb6,0x00,0x01,0x01,0x31,0x03,0xb6,0x00,0x01,0x01,0x31,0x03,0xb0,0x00,0x01,0x01,0x61,0x03,0xb6,0x00,0x01,0x01,0x79,0x03,0xfc,0x00,0x01,0x01,0x36,0x03,0xb6,0x00,0x01,0x01,0x54,0x03,0xfc,0x00,0x01,0x01,0x59,0x03,0xfc,0x00,0x01,0x01,0x36,0x03,0xfc,0x00,0x01,0x01,0x36,0x03,0xb0,0x00,0x01,0x01,0x36,0xff,0x2b,0x00,0x01, 0x01,0x0b,0x03,0xb6,0x00,0x01,0x01,0x38,0x03,0xd4,0x00,0x01,0x01,0x36,0x03,0x93,0x00,0x01,0x01,0x26,0xff,0x10,0x00,0x01,0x01,0x30,0x00,0x00,0x00,0x01,0x01,0xc2,0x03,0xb6,0x00,0x01,0x00,0xda,0x03,0xb6,0x00,0x01,0x01,0x4a,0xff,0x10,0x00,0x01,0x00,0xaf,0x02,0xda,0x00,0x01,0x01,0x54,0x00,0x00,0x00,0x01,0x01,0x6f,0x03,0xfc, 0x00,0x01,0x01,0x4a,0x03,0xfc,0x00,0x01,0x01,0x4f,0x03,0xfc,0x00,0x01,0x01,0x2c,0x03,0xfc,0x00,0x01,0x01,0x4d,0x03,0xb6,0x00,0x01,0x00,0xf7,0x03,0xb6,0x00,0x01,0x01,0x24,0x03,0xd4,0x00,0x01,0x01,0x22,0x03,0xb1,0x00,0x01,0x01,0x51,0x03,0xb6,0x00,0x01,0x01,0x2c,0x03,0xe2,0x00,0x01,0x01,0x81,0x02,0xda,0x00,0x01,0x01,0x2e, 0x03,0xd4,0x00,0x01,0x01,0x2c,0x03,0x93,0x00,0x01,0x01,0x2c,0x03,0xb0,0x00,0x01,0x01,0x01,0x03,0xb6,0x00,0x01,0x01,0x31,0x03,0x7a,0x00,0x01,0x01,0x31,0x03,0xa2,0x00,0x01,0x01,0x79,0x03,0x84,0x00,0x01,0x01,0x51,0x03,0x84,0x00,0x01,0x01,0x54,0x03,0xa2,0x00,0x01,0x01,0x31,0x03,0xa0,0x00,0x01,0x01,0x31,0x03,0x09,0x00,0x01, 0x01,0x31,0xff,0x2b,0x00,0x01,0x01,0x06,0x03,0x11,0x00,0x01,0x01,0x36,0x03,0x39,0x00,0x01,0x01,0x31,0x02,0xe9,0x00,0x01,0x01,0x31,0x03,0x44,0x00,0x01,0x01,0x5f,0x03,0x11,0x00,0x01,0x01,0x34,0x03,0x11,0x00,0x01,0x01,0x34,0x03,0x09,0x00,0x01,0x01,0x29,0x02,0x26,0x00,0x01,0x01,0x54,0x03,0x11,0x00,0x01,0x01,0x29,0x03,0x11, 0x00,0x01,0x01,0x35,0x03,0x70,0x00,0x01,0x01,0x29,0x03,0x09,0x00,0x01,0x00,0x89,0x02,0xda,0x00,0x01,0x00,0x89,0x03,0xc5,0x00,0x01,0x01,0x66,0x03,0x11,0x00,0x01,0x01,0x3b,0x03,0x11,0x00,0x01,0x01,0x10,0x03,0x11,0x00,0x01,0x01,0x40,0x03,0x39,0x00,0x01,0x01,0x3b,0x02,0xe9,0x00,0x01,0x01,0x3b,0x03,0x0c,0x00,0x01,0x01,0x7c, 0x02,0x26,0x00,0x01,0x01,0x7c,0x03,0x11,0x00,0x01,0x01,0x1b,0x03,0xb6,0x00,0x01,0x01,0x36,0xff,0x10,0x00,0x01,0x00,0xdc,0x02,0xda,0x00,0x01,0x01,0x18,0x01,0x6d,0x00,0x01,0x00,0xf0,0x02,0xda,0x00,0x01,0x01,0x5c,0x03,0x11,0x00,0x01,0x00,0x5a,0x02,0x85,0x00,0x01,0x01,0x31,0x03,0x11,0x00,0x01,0x01,0x31,0x03,0x0c,0x00,0x01, 0x01,0x74,0x03,0x84,0x00,0x01,0x01,0x4c,0x03,0x84,0x00,0x01,0x01,0x4f,0x03,0xa2,0x00,0x01,0x01,0x2c,0x03,0xa0,0x00,0x01,0x01,0x4d,0x03,0x11,0x00,0x01,0x01,0x22,0x02,0x26,0x00,0x01,0x00,0xf7,0x03,0x11,0x00,0x01,0x01,0x27,0x03,0x39,0x00,0x01,0x01,0x22,0x03,0x0c,0x00,0x01,0x00,0x91,0x00,0x00,0x00,0x01,0x00,0x87,0xff,0x10, 0x00,0x01,0x00,0xfa,0x02,0xc1,0x00,0x01,0x01,0x57,0x03,0xf4,0x00,0x01,0x01,0x2c,0x03,0xf4,0x00,0x01,0x01,0x01,0x03,0xf4,0x00,0x01,0x01,0x2c,0x03,0xcc,0x00,0x01,0x01,0x48,0x03,0xb6,0x00,0x01,0x01,0x1d,0x02,0xda,0x00,0x01,0x01,0x68,0x00,0x00,0x00,0x01,0x01,0x5e,0xff,0x10,0x00,0x01,0x01,0x13,0x01,0x13,0x00,0x01,0x01,0x38, 0x03,0x70,0x00,0x01,0x01,0x2c,0xfe,0xf2,0x00,0x01,0x01,0xb7,0x02,0x26,0x00,0x01,0x01,0xb7,0x03,0x11,0x00,0x01,0x01,0x25,0x03,0xb6,0x00,0x01,0x01,0x27,0xff,0x10,0x00,0x01,0x00,0xfa,0x02,0xda,0x00,0x01,0x01,0x22,0xff,0x10,0x00,0x01,0x01,0x6b,0x03,0x11,0x00,0x01,0x01,0x40,0x03,0x11,0x00,0x01,0x00,0xf5,0x00,0x00,0x00,0x01, 0x01,0x40,0x02,0x26,0x00,0x01,0x00,0xe6,0xff,0x10,0x00,0x01,0x01,0xcc,0xff,0x2b,0x00,0x01,0x01,0x2c,0xff,0x2b,0x00,0x01,0x01,0x2b,0xff,0x2b,0x00,0x01,0x01,0x01,0x03,0x11,0x00,0x01,0x01,0x31,0x03,0x39,0x00,0x01,0x01,0x2b,0x00,0x00,0x00,0x01,0x01,0x51,0x03,0x11,0x00,0x01,0x01,0x2c,0x02,0xe9,0x00,0x01,0x01,0x2c,0x03,0x44, 0x00,0x01,0x01,0x2c,0x03,0x0c,0x00,0x01,0x01,0xcd,0x00,0x00,0x00,0x01,0x01,0x6b,0x03,0xb6,0x00,0x01,0x01,0x36,0x03,0xb1,0x00,0x01,0x01,0xc2,0x02,0xda,0x00,0x01,0x01,0x21,0x02,0xda,0x00,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x01,0x28,0x02,0xda,0x00,0x01,0x01,0x28,0x01,0x6d,0x00,0x01,0x01,0x22,0x02,0xda,0x00,0x01,0x01,0x57, 0x03,0xb6,0x00,0x01,0x01,0x27,0x02,0xda,0x00,0x01,0x01,0x27,0x00,0x00,0x00,0x01,0x01,0x2c,0x03,0xb6,0x00,0x01,0x01,0xd1,0x00,0x00,0x00,0x01,0x01,0x4a,0x02,0x26,0x00,0x01,0x01,0x75,0x03,0x11,0x00,0x01,0x01,0x5a,0x03,0x11,0x00,0x01,0x01,0x3b,0x03,0x09,0x00,0x01,0x01,0x7c,0x03,0x09,0x00,0x01,0x01,0x4f,0x02,0x26,0x00,0x01, 0x00,0xfa,0x02,0x26,0x00,0x01,0x01,0xb7,0x03,0x09,0x00,0x01,0x01,0x27,0xfe,0xf2,0x00,0x01,0x01,0x57,0x03,0x11,0x00,0x01,0x01,0x2c,0x03,0x11,0x00,0x01,0x01,0x40,0x02,0xda,0x00,0x01,0x01,0xf4,0x00,0x00,0x00,0x01,0x01,0x36,0x02,0xda,0x00,0x01,0x01,0x36,0x00,0x00,0x00,0x01,0x01,0xb8,0x00,0x00,0x00,0x01,0x01,0x40,0x00,0x00, 0x00,0x01,0x01,0x2c,0x03,0xb1,0x00,0x01,0x01,0x2f,0x02,0x26,0x00,0x01,0x01,0x27,0x03,0x09,0x00,0x01,0x01,0x2c,0x03,0x09,0x00,0x01,0x01,0xa4,0x02,0x26,0x00,0x01,0x01,0x4c,0x02,0x26,0x00,0x01,0x01,0x2c,0x01,0x13,0x00,0x01,0x01,0x31,0x02,0x26,0x00,0x01,0x01,0x28,0x02,0x26,0x00,0x01,0x01,0x28,0x00,0x00,0x00,0x01,0x01,0x31, 0x02,0xda,0x00,0x01,0x01,0x31,0x00,0x00,0x00,0x01,0x01,0x34,0x02,0x26,0x00,0x01,0x01,0x34,0x00,0x00,0x00,0x01,0x01,0x27,0x02,0x26,0x00,0x01,0x01,0x2c,0x02,0x26,0x00,0x01,0x01,0x2c,0x02,0xda,0x00,0x01,0x01,0x40,0x02,0xbc,0x00,0x01,0x01,0x2c,0x00,0x00,0x00,0x01,0x01,0x5e,0x00,0x00,0x00,0x01,0x01,0x2c,0x01,0x6d,0x00,0x01, 0x01,0x3b,0x00,0x00,0x00,0x01,0x01,0x3b,0x02,0x26,0x00,0x01,0x01,0x3b,0xff,0x2b,0x00,0x01,0x01,0x4a,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0a,0x00,0x18,0x01,0x1c,0x00,0x02,0x44,0x46,0x4c,0x54,0x04,0xac,0x6c,0x61,0x74,0x6e,0x04,0xb0,0x00,0x2b,0x61,0x61,0x6c,0x74,0x05,0xb4,0x63,0x61,0x6c,0x74,0x05,0xe4,0x63,0x61, 0x73,0x65,0x04,0xd6,0x63,0x63,0x6d,0x70,0x05,0xc4,0x63,0x63,0x6d,0x70,0x05,0xd8,0x63,0x76,0x30,0x31,0x04,0xdc,0x63,0x76,0x30,0x32,0x04,0xe2,0x63,0x76,0x30,0x33,0x04,0xe8,0x63,0x76,0x30,0x34,0x04,0xee,0x63,0x76,0x30,0x35,0x04,0xf4,0x63,0x76,0x30,0x36,0x04,0xfa,0x63,0x76,0x30,0x37,0x05,0x00,0x63,0x76,0x30,0x38,0x05,0x06, 0x63,0x76,0x30,0x39,0x05,0x0c,0x63,0x76,0x31,0x30,0x05,0x12,0x63,0x76,0x31,0x31,0x05,0x18,0x63,0x76,0x31,0x32,0x05,0x1e,0x63,0x76,0x31,0x34,0x05,0x24,0x63,0x76,0x31,0x35,0x05,0x2a,0x63,0x76,0x31,0x36,0x05,0x30,0x63,0x76,0x31,0x37,0x05,0x36,0x63,0x76,0x31,0x38,0x05,0x3c,0x63,0x76,0x31,0x39,0x05,0x42,0x63,0x76,0x32,0x30, 0x05,0x48,0x63,0x76,0x39,0x39,0x05,0x4e,0x66,0x72,0x61,0x63,0x05,0xce,0x6c,0x6f,0x63,0x6c,0x05,0x54,0x6c,0x6f,0x63,0x6c,0x05,0x5a,0x6c,0x6f,0x63,0x6c,0x05,0x60,0x6c,0x6f,0x63,0x6c,0x05,0x66,0x6c,0x6f,0x63,0x6c,0x05,0x6c,0x6c,0x6f,0x63,0x6c,0x05,0x72,0x6c,0x6f,0x63,0x6c,0x05,0x78,0x6c,0x6f,0x63,0x6c,0x05,0x7e,0x6f,0x72, 0x64,0x6e,0x05,0xbc,0x73,0x69,0x6e,0x66,0x05,0x84,0x73,0x73,0x30,0x31,0x05,0x8a,0x73,0x73,0x30,0x32,0x05,0x90,0x73,0x73,0x31,0x39,0x05,0x96,0x73,0x73,0x32,0x30,0x05,0x9c,0x73,0x75,0x62,0x73,0x05,0xa2,0x73,0x75,0x70,0x73,0x05,0xa8,0x7a,0x65,0x72,0x6f,0x05,0xae,0x01,0xcc,0x06,0x18,0x06,0x20,0x06,0x28,0x06,0x30,0x06,0x38, 0x06,0x40,0x06,0x40,0x06,0x48,0x06,0x50,0x06,0x58,0x06,0x60,0x06,0x68,0x06,0x70,0x06,0x78,0x06,0x80,0x06,0x88,0x06,0x90,0x06,0x98,0x06,0xa0,0x06,0xa8,0x06,0xb0,0x0a,0x90,0x06,0xb8,0x06,0xc0,0x0a,0x90,0x06,0xc8,0x06,0xd0,0x0c,0x60,0x06,0xd8,0x06,0xe0,0x06,0xe8,0x06,0xf0,0x06,0xf8,0x07,0x00,0x07,0x28,0x07,0x08,0x07,0x10, 0x07,0x28,0x07,0x28,0x07,0x18,0x07,0x20,0x07,0x28,0x07,0x28,0x07,0x28,0x07,0x30,0x07,0x38,0x07,0x40,0x07,0x48,0x07,0x50,0x07,0x58,0x07,0x60,0x07,0x68,0x07,0x70,0x07,0x78,0x11,0xb0,0x07,0x80,0x11,0xba,0x07,0x88,0x07,0x90,0x07,0x98,0x07,0xd0,0x07,0xa0,0x07,0xa8,0x07,0xd0,0x07,0xd0,0x07,0xb0,0x07,0xb8,0x07,0xc0,0x07,0xc8, 0x07,0xd0,0x07,0xd8,0x07,0xe0,0x0d,0x70,0x07,0xe8,0x07,0xf0,0x07,0xf8,0x08,0x00,0x08,0x28,0x08,0x08,0x08,0x10,0x08,0x18,0x08,0x20,0x08,0x28,0x08,0x28,0x08,0x30,0x08,0x38,0x08,0x50,0x08,0x40,0x08,0x48,0x08,0x50,0x08,0x50,0x08,0x58,0x08,0x60,0x08,0x68,0x08,0x70,0x08,0x98,0x08,0x78,0x08,0x80,0x08,0x98,0x08,0x98,0x08,0x88, 0x08,0x90,0x08,0x98,0x08,0xa0,0x08,0xa8,0x0c,0x60,0x08,0xb0,0x08,0xb8,0x0e,0x40,0x08,0xc0,0x08,0xc8,0x08,0xd0,0x08,0xd8,0x0c,0x60,0x08,0xe0,0x08,0xe8,0x08,0xf0,0x08,0xf8,0x09,0x00,0x09,0x08,0x0e,0x40,0x09,0x10,0x09,0x18,0x0e,0x40,0x09,0x20,0x09,0x28,0x0e,0x40,0x0e,0x40,0x09,0x30,0x09,0x38,0x0e,0x40,0x09,0x40,0x09,0x48, 0x09,0x50,0x09,0x58,0x09,0x60,0x09,0x68,0x0c,0x28,0x0c,0x28,0x09,0x70,0x09,0x78,0x0c,0x28,0x09,0x80,0x09,0x88,0x09,0x90,0x09,0x98,0x09,0xa0,0x09,0xa8,0x0d,0xd8,0x09,0xb0,0x09,0xb8,0x0c,0x60,0x09,0xc0,0x09,0xc8,0x09,0xd0,0x09,0xd8,0x0d,0xd8,0x09,0xe0,0x09,0xe8,0x0d,0xd8,0x0d,0xd8,0x09,0xf0,0x09,0xf8,0x0a,0x00,0x0a,0x08, 0x0a,0x10,0x0a,0x18,0x0a,0x20,0x0a,0x28,0x0a,0x30,0x0a,0x38,0x0e,0x40,0x0a,0x40,0x0a,0x48,0x0d,0x70,0x0a,0x50,0x0a,0x58,0x0a,0x60,0x0a,0x68,0x0d,0x18,0x0a,0x70,0x0a,0x78,0x0a,0x80,0x0a,0x88,0x0a,0x90,0x0a,0x98,0x0a,0xa0,0x0d,0x70,0x0a,0xa8,0x0a,0xb0,0x0d,0x70,0x0a,0xb8,0x0a,0xc0,0x0a,0xc8,0x0a,0xd0,0x0d,0x70,0x0a,0xd8, 0x0a,0xe0,0x0d,0x70,0x0d,0x70,0x0a,0xe8,0x0a,0xf0,0x0d,0x70,0x0a,0xf8,0x0b,0x00,0x0b,0x08,0x0b,0x10,0x0b,0x18,0x0b,0x20,0x0b,0x28,0x0b,0x30,0x0b,0xa0,0x0b,0x38,0x0b,0x40,0x0b,0x58,0x0b,0x48,0x0b,0x50,0x0b,0x58,0x0b,0x58,0x0b,0x60,0x0b,0x68,0x0b,0xa0,0x0b,0xa0,0x0b,0x70,0x0b,0x78,0x0b,0x80,0x0b,0x88,0x0b,0x90,0x0b,0x98, 0x0b,0xa0,0x0b,0xa8,0x0b,0xb0,0x0c,0x28,0x0c,0x28,0x0b,0xb8,0x0b,0xc0,0x0c,0x28,0x0b,0xc8,0x0b,0xd0,0x0b,0xd8,0x0b,0xe0,0x0c,0x28,0x0b,0xe8,0x0b,0xf0,0x0c,0x28,0x0b,0xf8,0x0c,0x00,0x0c,0x08,0x0c,0x10,0x0c,0x18,0x0c,0x20,0x0c,0x28,0x0c,0x30,0x0c,0x38,0x0c,0x60,0x0c,0x40,0x0c,0x48,0x0c,0x60,0x0c,0x50,0x0c,0x58,0x0c,0x60, 0x0c,0x60,0x0c,0x68,0x0c,0x70,0x0c,0x88,0x0c,0x78,0x0c,0x80,0x0c,0x88,0x0c,0x88,0x0c,0x90,0x0c,0x98,0x0c,0xa0,0x0c,0xa8,0x0c,0xb0,0x0c,0xb8,0x0c,0xc0,0x0c,0xc8,0x0c,0xf0,0x0c,0xd0,0x0c,0xd8,0x0c,0xe0,0x0c,0xe8,0x0c,0xf0,0x0c,0xf0,0x0c,0xf8,0x0d,0x00,0x0d,0x08,0x0d,0x10,0x0d,0x18,0x0d,0x20,0x0d,0x28,0x0d,0x70,0x0d,0x30, 0x0d,0x38,0x0e,0x40,0x0d,0x40,0x0d,0x48,0x0e,0x40,0x0d,0x50,0x0d,0x58,0x0d,0x70,0x0d,0x60,0x0d,0x68,0x0d,0x70,0x0d,0x78,0x0d,0x80,0x0d,0xd8,0x0d,0x88,0x0d,0x90,0x0d,0xd8,0x0d,0x98,0x0d,0xa0,0x0d,0xd8,0x0d,0xa8,0x0d,0xb0,0x0d,0xd8,0x0d,0xb8,0x0d,0xc0,0x0d,0xc8,0x0d,0xd0,0x0d,0xd8,0x0d,0xe0,0x0d,0xe8,0x0d,0xf0,0x0d,0xf8, 0x0e,0xb8,0x0e,0x00,0x0e,0x08,0x0e,0x10,0x0e,0x18,0x0e,0x20,0x0e,0x28,0x0e,0x40,0x0e,0x30,0x0e,0x38,0x0e,0x40,0x0e,0x48,0x0e,0x50,0x0e,0x58,0x0e,0x60,0x0e,0x68,0x0e,0x70,0x0e,0x78,0x0e,0x80,0x0e,0x88,0x0e,0x90,0x0e,0xb8,0x0e,0x98,0x0e,0xa0,0x0e,0xa8,0x0e,0xb0,0x0e,0xb8,0x0e,0xc0,0x0e,0xc8,0x0e,0xd0,0x0e,0xd8,0x0e,0xe0, 0x0e,0xe8,0x0e,0xf0,0x0e,0xf8,0x0f,0x00,0x0f,0x08,0x0f,0x10,0x0f,0x18,0x0f,0x20,0x0f,0x28,0x0f,0x30,0x0f,0x38,0x0f,0x40,0x0f,0x48,0x0f,0x50,0x0f,0x58,0x0f,0x60,0x0f,0x68,0x0f,0x70,0x0f,0x78,0x0f,0x80,0x0f,0x88,0x0f,0x90,0x0f,0x98,0x0f,0xa0,0x0f,0xa8,0x0f,0xb0,0x0f,0xb8,0x0f,0xc0,0x0f,0xc8,0x0f,0xd0,0x0f,0xd8,0x0f,0xe0, 0x0f,0xe8,0x0f,0xf0,0x0f,0xf8,0x10,0x00,0x10,0x08,0x10,0x10,0x10,0x18,0x10,0x20,0x10,0x28,0x10,0x30,0x10,0x38,0x10,0x40,0x10,0x48,0x10,0x50,0x10,0x58,0x11,0xd8,0x10,0x60,0x10,0x60,0x10,0x68,0x10,0x70,0x10,0x70,0x10,0x78,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x88,0x10,0x88,0x10,0x90,0x10,0xa0,0x10,0x98, 0x10,0xa0,0x10,0xa0,0x10,0xa8,0x10,0xa8,0x10,0xb0,0x10,0xb8,0x10,0xc0,0x11,0xc4,0x10,0xc8,0x10,0xc8,0x11,0xce,0x10,0xd0,0x10,0xd8,0x10,0xe0,0x10,0xe8,0x10,0xf0,0x10,0xf8,0x11,0x00,0x11,0x08,0x11,0x10,0x11,0x18,0x11,0x20,0x11,0x28,0x11,0x30,0x11,0x38,0x11,0x40,0x11,0x48,0x11,0x50,0x11,0x58,0x11,0x60,0x11,0x68,0x11,0x70, 0x11,0x78,0x11,0x80,0x11,0x88,0x11,0x90,0x11,0x98,0x11,0xa0,0x11,0xa8,0x0e,0x4c,0x00,0x00,0x0e,0x92,0x00,0x08,0x41,0x5a,0x45,0x20,0x0e,0xdc,0x43,0x41,0x54,0x20,0x0f,0x28,0x43,0x52,0x54,0x20,0x0f,0x74,0x4b,0x41,0x5a,0x20,0x0f,0xc0,0x4d,0x4f,0x4c,0x20,0x10,0x0c,0x52,0x4f,0x4d,0x20,0x10,0x58,0x54,0x41,0x54,0x20,0x10,0xa4, 0x54,0x52,0x4b,0x20,0x10,0xf0,0x00,0x00,0x00,0x01,0x01,0xb2,0x00,0x00,0x00,0x01,0x01,0xb8,0x00,0x00,0x00,0x01,0x01,0xb9,0x00,0x00,0x00,0x01,0x01,0xba,0x00,0x00,0x00,0x01,0x01,0xbb,0x00,0x00,0x00,0x01,0x01,0xbc,0x00,0x00,0x00,0x01,0x01,0xbd,0x00,0x00,0x00,0x01,0x01,0xbe,0x00,0x00,0x00,0x01,0x01,0xbf,0x00,0x00,0x00,0x01, 0x01,0xc0,0x00,0x00,0x00,0x01,0x01,0xc1,0x00,0x00,0x00,0x01,0x01,0xc2,0x00,0x00,0x00,0x01,0x01,0xc3,0x00,0x00,0x00,0x01,0x01,0xc4,0x00,0x00,0x00,0x01,0x01,0xc5,0x00,0x00,0x00,0x01,0x01,0xc6,0x00,0x00,0x00,0x01,0x01,0xc7,0x00,0x00,0x00,0x01,0x01,0xc8,0x00,0x00,0x00,0x01,0x01,0xc9,0x00,0x00,0x00,0x01,0x01,0xca,0x00,0x00, 0x00,0x01,0x01,0xcb,0x00,0x00,0x00,0x01,0x01,0x9b,0x00,0x00,0x00,0x01,0x01,0xa2,0x00,0x00,0x00,0x01,0x01,0x9c,0x00,0x00,0x00,0x01,0x01,0x9d,0x00,0x00,0x00,0x01,0x01,0xa1,0x00,0x00,0x00,0x01,0x01,0xa0,0x00,0x00,0x00,0x01,0x01,0x9e,0x00,0x00,0x00,0x01,0x01,0x9f,0x00,0x00,0x00,0x01,0x01,0xa8,0x10,0x54,0x00,0x01,0x01,0xb4, 0x10,0x52,0x00,0x01,0x01,0xb5,0x10,0x50,0x00,0x01,0x01,0xb6,0x10,0x4e,0x00,0x01,0x01,0xb7,0x00,0x00,0x00,0x01,0x01,0xa7,0x00,0x00,0x00,0x01,0x01,0xa9,0x00,0x00,0x00,0x01,0x01,0xb3,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x01,0xaf,0x01,0xb1,0x00,0x00,0x00,0x03,0x01,0x94,0x01,0x97,0x01,0x9a,0x00,0x00, 0x00,0x03,0x01,0xaa,0x01,0xab,0x01,0xac,0x00,0x00,0x00,0x04,0x01,0x94,0x01,0x97,0x01,0x9a,0x01,0x9a,0x00,0x00,0x00,0x9a,0x00,0x02,0x00,0x04,0x00,0x07,0x00,0x0a,0x00,0x0d,0x00,0x10,0x00,0x13,0x00,0x16,0x00,0x19,0x00,0x1c,0x00,0x1e,0x00,0x20,0x00,0x23,0x00,0x27,0x00,0x2c,0x00,0x2e,0x00,0x30,0x00,0x32,0x00,0x34,0x00,0x36, 0x00,0x38,0x00,0x3a,0x00,0x3d,0x00,0x41,0x00,0x43,0x00,0x46,0x00,0x49,0x00,0x4b,0x00,0x4e,0x00,0x50,0x00,0x54,0x00,0x57,0x00,0x5b,0x00,0x5d,0x00,0x60,0x00,0x64,0x00,0x67,0x00,0x6a,0x00,0x6d,0x00,0x6f,0x00,0x72,0x00,0x74,0x00,0x76,0x00,0x79,0x00,0x7c,0x00,0x80,0x00,0x83,0x00,0x85,0x00,0x87,0x00,0x8b,0x00,0x8e,0x00,0x90, 0x00,0x92,0x00,0x95,0x00,0x98,0x00,0x9a,0x00,0x9d,0x00,0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00,0xa9,0x00,0xac,0x00,0xaf,0x00,0xb1,0x00,0xb4,0x00,0xb6,0x00,0xb9,0x00,0xbc,0x00,0xbf,0x00,0xc1,0x00,0xc4,0x00,0xc8,0x00,0xcb,0x00,0xcd,0x00,0xcf,0x00,0xd1,0x00,0xd4,0x00,0xd7,0x00,0xdb,0x00,0xdf,0x00,0xe1,0x00,0xe3,0x00,0xe6, 0x00,0xea,0x00,0xed,0x00,0xef,0x00,0xf2,0x00,0xf5,0x00,0xf7,0x00,0xf9,0x00,0xfc,0x00,0xff,0x01,0x02,0x01,0x06,0x01,0x09,0x01,0x0d,0x01,0x0f,0x01,0x11,0x01,0x13,0x01,0x16,0x01,0x18,0x01,0x1c,0x01,0x1e,0x01,0x21,0x01,0x24,0x01,0x27,0x01,0x2a,0x01,0x2d,0x01,0x30,0x01,0x33,0x01,0x36,0x01,0x39,0x01,0x3c,0x01,0x3e,0x01,0x41, 0x01,0x43,0x01,0x46,0x01,0x48,0x01,0x4a,0x01,0x4d,0x01,0x50,0x01,0x52,0x01,0x54,0x01,0x56,0x01,0x58,0x01,0x5b,0x01,0x5d,0x01,0x60,0x01,0x62,0x01,0x64,0x01,0x66,0x01,0x68,0x01,0x6a,0x01,0x6c,0x01,0x6e,0x01,0x70,0x01,0x72,0x01,0x74,0x01,0x76,0x01,0x78,0x01,0x7a,0x01,0x7c,0x01,0x7e,0x01,0x80,0x01,0x82,0x01,0x84,0x01,0x86, 0x01,0x88,0x01,0x8a,0x01,0x8c,0x01,0x8e,0x01,0x90,0x01,0x92,0x00,0x01,0x00,0x00,0x00,0x01,0x20,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x1d,0xcc,0x00,0x06,0x00,0x00,0x00,0x01,0x1b,0xf6,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0xba,0x00,0x06,0x00,0x00,0x00,0x01,0x1b,0x60,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0xb0,0x00,0x06,0x00,0x00, 0x00,0x01,0x10,0x3a,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0xa6,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0xa4,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x2a,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0x9a,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0x98,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x1a,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x1c,0x00,0x01,0x00,0x00, 0x00,0x01,0x11,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x20,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x22,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x24,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x26,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x28,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x2a,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x2c,0x00,0x06,0x00,0x00, 0x00,0x01,0x18,0xcc,0x00,0x01,0x00,0x00,0x00,0x01,0x18,0xd0,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x1e,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x20,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x22,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x24,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x9a,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0x0e,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0x92,0x00,0x01,0x00,0x00,0x00,0x01,0x0e,0x04,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x8a,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0xfa,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0xf8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xee,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xf0,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xf2,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0xf4,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xf6,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xf8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xfa,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xfe,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x02,0x00,0x01,0x00,0x00, 0x00,0x01,0x11,0x04,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1a,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x8e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x12,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x84,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xe6,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xe8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xea,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0xec,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x62,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xe6,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xe8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xea,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xec,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xee,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xf0,0x00,0x06,0x00,0x00, 0x00,0x01,0x10,0xf2,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xf4,0x00,0x06,0x00,0x00,0x00,0x01,0x0e,0xa2,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x18,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x16,0x00,0x06,0x00,0x00,0x00,0x01,0x0e,0x92,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x0c,0x00,0x06,0x00,0x00,0x00,0x01,0x0e,0x8a,0x00,0x01,0x00,0x00, 0x00,0x01,0x0d,0x02,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xb6,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xb8,0x00,0x06,0x00,0x00,0x00,0x01,0x0e,0x6a,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0xe6,0x00,0x06,0x00,0x00,0x00,0x01,0x0e,0x62,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0xdc,0x00,0x06,0x00,0x00, 0x00,0x01,0x10,0x9a,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x9c,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0xca,0x00,0x06,0x00,0x00,0x00,0x01,0x17,0x0c,0x00,0x01,0x00,0x00,0x00,0x01,0x17,0x10,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x86,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x88,0x00,0x06,0x00,0x00,0x00,0x01,0x19,0x28,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x82,0x00,0x06,0x00,0x00,0x00,0x01,0x16,0xf4,0x00,0x01,0x00,0x00,0x00,0x01,0x16,0xf8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x74,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x76,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x78,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x7a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x7c,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x7e,0x00,0x06,0x00,0x00,0x00,0x01,0x0d,0xd2,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0x50,0x00,0x06,0x00,0x00,0x00,0x01,0x0d,0xca,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0x46,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x60,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x62,0x00,0x06,0x00,0x00,0x00,0x01,0x16,0x9c,0x00,0x01,0x00,0x00, 0x00,0x01,0x16,0xa0,0x00,0x06,0x00,0x00,0x00,0x01,0x16,0xa4,0x00,0x01,0x00,0x00,0x00,0x01,0x16,0xa8,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x44,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x46,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x48,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x4a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x4c,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x4e,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x50,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x52,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x54,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x56,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x58,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x5a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x5c,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x5e,0x00,0x06,0x00,0x00,0x00,0x01,0x0d,0x22,0x00,0x01,0x00,0x00,0x00,0x01,0x0b,0x9c,0x00,0x06,0x00,0x00,0x00,0x01,0x0d,0x1a,0x00,0x01,0x00,0x00,0x00,0x01,0x0b,0x92,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x42,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x44,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x46,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x48,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x4a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x4c,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x4e,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x50,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x52,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x54,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0x56,0x00,0x06,0x00,0x00,0x00,0x01,0x15,0xbc,0x00,0x01,0x00,0x00,0x00,0x01,0x15,0xc0,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x48,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x4a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x4c,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x4e,0x00,0x06,0x00,0x00,0x00,0x01,0x0c,0x82,0x00,0x01,0x00,0x00, 0x00,0x01,0x0a,0xf8,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0xf6,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x38,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x3a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x3c,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x3e,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x42,0x00,0x06,0x00,0x00, 0x00,0x01,0x0c,0x42,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0xbc,0x00,0x06,0x00,0x00,0x00,0x01,0x0c,0x3a,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0xb2,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x24,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x26,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x28,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x2a,0x00,0x06,0x00,0x00, 0x00,0x01,0x10,0x2c,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x2e,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0x30,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x32,0x00,0x06,0x00,0x00,0x00,0x01,0x0b,0xf2,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x68,0x00,0x06,0x00,0x00,0x00,0x01,0x0b,0xea,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x5e,0x00,0x06,0x00,0x00, 0x00,0x01,0x0b,0xe2,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x54,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x52,0x00,0x06,0x00,0x00,0x00,0x01,0x0b,0xd2,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x48,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xec,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xee,0x00,0x06,0x00,0x00,0x00,0x01,0x14,0xa4,0x00,0x01,0x00,0x00, 0x00,0x01,0x14,0xa8,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xe0,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xe2,0x00,0x01,0x00,0x00,0x00,0x01,0x0a,0x16,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xdc,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xde,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xe0,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xe2,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0xe4,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xe6,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xe8,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xea,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xec,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xee,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xf0,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xf2,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0xf4,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0xf6,0x00,0x06,0x00,0x00,0x00,0x01,0x0b,0x22,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x9c,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x9a,0x00,0x06,0x00,0x00,0x00,0x01,0x0b,0x12,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x90,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0xd0,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0xd2,0x00,0x06,0x00,0x00,0x00,0x01,0x0a,0xfa,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x76,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x74,0x00,0x06,0x00,0x00,0x00,0x01,0x0a,0xea,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x6a,0x00,0x06,0x00,0x00,0x00,0x01,0x0a,0xe2,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x60,0x00,0x01,0x00,0x00, 0x00,0x01,0x09,0x5e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x94,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x96,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x98,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x9a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x9c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x9e,0x00,0x06,0x00,0x00,0x00,0x01,0x0a,0xa2,0x00,0x01,0x00,0x00, 0x00,0x01,0x09,0x24,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x90,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x92,0x00,0x06,0x00,0x00,0x00,0x01,0x0a,0x8a,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x0a,0x00,0x01,0x00,0x00,0x00,0x01,0x09,0x08,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x7c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x7e,0x00,0x06,0x00,0x00, 0x00,0x01,0x0a,0x6a,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0xee,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0xec,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x68,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x6a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x6c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x6e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x70,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x72,0x00,0x06,0x00,0x00,0x00,0x01,0x12,0xec,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0xf0,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x64,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x66,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x9a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x60,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x62,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0x64,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x66,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x68,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x6a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x6c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x6e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x70,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x72,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0x74,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x76,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x38,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x70,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x72,0x00,0x06,0x00,0x00,0x00,0x01,0x09,0x8a,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x12,0x54,0x00,0x01,0x00,0x00, 0x00,0x01,0x12,0x58,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x54,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x56,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x58,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x5a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x5c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x5e,0x00,0x01,0x00,0x00,0x00,0x01,0x07,0xdc,0x00,0x06,0x00,0x00, 0x00,0x01,0x12,0x24,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x28,0x00,0x06,0x00,0x00,0x00,0x01,0x12,0x2c,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x30,0x00,0x06,0x00,0x00,0x00,0x01,0x12,0x34,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x38,0x00,0x06,0x00,0x00,0x00,0x01,0x12,0x3c,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x40,0x00,0x06,0x00,0x00, 0x00,0x01,0x0f,0x18,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x20,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x22,0x00,0x01,0x00,0x00,0x00,0x01,0x07,0x6a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1c,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x20,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x22,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x24,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x26,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x28,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x2a,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0xcc,0x00,0x01,0x00,0x00, 0x00,0x01,0x11,0xd0,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x20,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x22,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0xb4,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0xb8,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x14,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x16,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x18,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1a,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x9c,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0xa0,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x0c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x0e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x10,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x12,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x84,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0x88,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x04,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x06,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x08,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x0a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x0c,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x0e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x12,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x14,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x16,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x18,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1a,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1c,0x00,0x01,0x00,0x00, 0x00,0x01,0x0f,0x1e,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x20,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x22,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x24,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x26,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x28,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x2a,0x00,0x06,0x00,0x00,0x00,0x01,0x10,0xec,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0xf0,0x00,0x06,0x00,0x00,0x00,0x01,0x0f,0x1c,0x00,0x01,0x00,0x00,0x00,0x01,0x0f,0x1e,0x00,0x01,0x00,0x00,0x00,0x01,0x14,0xd8,0x00,0x06,0x00,0x00,0x00,0x01,0x11,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x14,0x1c,0x00,0x04,0x00,0x00,0x00,0x01,0x10,0xcc,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0xa8,0x00,0x01,0x00,0x00, 0x00,0x01,0x10,0xca,0x00,0x06,0x00,0x00,0x00,0x01,0x06,0xf2,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x96,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x94,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x92,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x86,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x88,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x86,0x00,0x01,0x00,0x00, 0x00,0x01,0x05,0x84,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x90,0x00,0x04,0x00,0x00,0x00,0x01,0x06,0xb2,0x00,0x01,0x00,0x00,0x00,0x01,0x14,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x6a,0x00,0x01,0x00,0x00,0x00,0x01,0x14,0xac,0x00,0x01,0x00,0x00,0x00,0x01,0x13,0x42,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x6e,0x00,0x01,0x00,0x00, 0x00,0x01,0x0e,0x78,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xea,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x3e,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x54,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x2c,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0xc8,0x00,0x01,0x00,0x00, 0x00,0x01,0x12,0x52,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x1a,0x00,0x01,0x00,0x00,0x00,0x01,0x05,0x18,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0xf2,0x00,0x01,0x00,0x00,0x00,0x01,0x12,0x58,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x48,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x12,0x00,0x01,0x00,0x00,0x00,0x01,0x04,0xf6,0x00,0x01,0x00,0x00, 0x00,0x01,0x04,0xf4,0x00,0x01,0x00,0x00,0x00,0x01,0x11,0xe6,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x30,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x38,0x00,0x01,0x00,0x00,0x00,0x01,0x0d,0xe2,0x00,0x06,0x00,0x00,0x00,0x02,0x10,0xca,0x10,0xe0,0x00,0x06,0x00,0x00,0x00,0x02,0x10,0xec,0x11,0x02,0x00,0x06,0x00,0x00,0x00,0x02,0x10,0x6e, 0x10,0x80,0x00,0x06,0x00,0x00,0x00,0x02,0x10,0x88,0x10,0x9a,0x00,0x06,0x00,0x00,0x00,0x04,0x10,0xfa,0x11,0x4a,0x11,0x0c,0x11,0x1e,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10, 0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b, 0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06, 0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1a,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23, 0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1b,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27, 0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1c, 0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14, 0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1d,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e, 0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1e,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08, 0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x1f,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01, 0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x20,0x00,0x22,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29, 0x00,0x2a,0x00,0x00,0xff,0xff,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x09,0x00,0x0a,0x00,0x0b,0x00,0x0c,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,0x21,0x00,0x22,0x00,0x23, 0x00,0x24,0x00,0x25,0x00,0x26,0x00,0x27,0x00,0x28,0x00,0x29,0x00,0x2a,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x01,0x02,0x00,0x00,0x01,0x03,0x00,0x01,0x12,0x42,0x00,0x15,0x00,0x01,0x12,0x36,0x00,0x33,0x00,0x01,0x11,0xc0,0x00,0x31,0x00,0x01,0x11,0xba,0x03,0x89,0x00,0x01,0x11,0xba,0x00,0x35,0x00,0x01,0x11,0xb4, 0x03,0x88,0x00,0x01,0x11,0xb4,0x00,0x66,0x00,0x01,0x11,0xae,0x00,0x67,0x00,0x01,0x11,0xa8,0x00,0x68,0x00,0x01,0x11,0xa2,0x03,0x94,0x00,0x01,0x12,0x0c,0x00,0x6e,0x00,0x01,0x12,0x06,0x00,0x70,0x00,0x01,0x12,0x00,0x03,0x91,0x00,0x01,0x11,0x90,0x00,0x63,0x00,0x01,0x11,0x8a,0x03,0x9a,0x00,0x01,0x11,0x8a,0x02,0x08,0x00,0x01, 0x11,0x84,0x02,0x09,0x00,0x01,0x11,0x7e,0x02,0xb9,0x00,0x01,0x11,0x7e,0x00,0x56,0x00,0x01,0x11,0x78,0x00,0x57,0x00,0x01,0x11,0x72,0x03,0xa5,0x00,0x01,0x11,0x72,0x02,0x32,0x00,0x01,0x11,0x6c,0x02,0x35,0x00,0x01,0x11,0x6c,0x02,0x15,0x00,0x01,0x11,0x66,0x02,0x18,0x00,0x01,0x11,0x66,0x00,0x60,0x00,0x01,0x11,0x60,0x03,0xa0, 0x00,0x01,0x11,0x60,0x02,0x0a,0x00,0x01,0x11,0x5a,0x02,0x0b,0x00,0x01,0x11,0x94,0x00,0x59,0x00,0x01,0x11,0x54,0x00,0x60,0x00,0x01,0x11,0x4e,0x00,0x61,0x00,0x01,0x11,0x48,0x03,0xa2,0x00,0x01,0x11,0x7c,0x00,0x5a,0x00,0x01,0x11,0x76,0x03,0xa3,0x00,0x01,0x11,0x3c,0x00,0x55,0x00,0x01,0x11,0x36,0x01,0x10,0x00,0x01,0x11,0x36, 0x00,0x15,0x00,0x01,0x11,0x30,0x00,0x16,0x00,0x01,0x11,0x2a,0x03,0x77,0x00,0x01,0x11,0x2a,0x00,0x64,0x00,0x01,0x11,0x24,0x00,0x65,0x00,0x01,0x11,0x1e,0x03,0x9e,0x00,0x01,0x11,0x1e,0x00,0x57,0x00,0x01,0x11,0x18,0x00,0x58,0x00,0x01,0x11,0x12,0x01,0x19,0x00,0x01,0x11,0x12,0x00,0x55,0x00,0x01,0x11,0x0c,0x03,0x72,0x00,0x01, 0x10,0xe2,0x02,0xb5,0x00,0x01,0x10,0xd0,0x02,0xb3,0x00,0x01,0x11,0x00,0x02,0x39,0x00,0x01,0x10,0xbe,0x02,0xb2,0x00,0x01,0x10,0xf4,0x02,0xac,0x00,0x01,0x10,0x70,0x00,0x07,0x00,0x01,0x10,0xee,0x00,0x0f,0x00,0x01,0x10,0xe8,0x00,0x10,0x00,0x01,0x13,0x50,0x00,0x10,0x00,0x01,0x10,0xf2,0xff,0xe3,0x00,0x01,0x13,0x44,0x00,0x24, 0x00,0x01,0x13,0x34,0xff,0xf6,0x00,0x01,0x10,0x4c,0x00,0x0a,0x00,0x01,0x12,0x30,0x00,0x38,0x00,0x01,0x12,0x34,0x00,0x94,0x00,0x01,0x10,0x40,0x00,0x7f,0x00,0x01,0x10,0x46,0x00,0xae,0x00,0x01,0x12,0x2c,0x00,0x63,0x00,0x01,0x10,0x34,0x00,0x40,0x00,0x01,0x10,0x34,0x00,0xcf,0x00,0x01,0x10,0x34,0x00,0x01,0x13,0x12,0x00,0x01, 0x10,0x32,0x00,0x01,0x13,0x14,0x00,0x01,0x10,0x30,0x00,0x01,0x13,0x16,0x00,0x01,0x10,0x28,0x00,0x01,0x16,0x76,0x00,0x01,0x10,0x20,0x00,0x01,0x18,0xee,0x00,0x01,0x10,0x88,0x00,0x01,0x16,0x72,0x00,0x01,0x10,0x80,0x00,0x01,0x16,0x76,0x00,0x01,0x10,0x0e,0x00,0x01,0x16,0x7a,0x00,0x01,0x10,0x0c,0x00,0x01,0x12,0xf0,0x00,0x01, 0x10,0x04,0x00,0x01,0x16,0x76,0x00,0x01,0x10,0x02,0x00,0x01,0x16,0x7a,0x00,0x01,0x0f,0xfa,0x00,0x01,0x16,0x7e,0x00,0x01,0x0f,0xf8,0x00,0x01,0x1b,0x08,0x00,0x01,0x0f,0xf0,0x00,0x01,0x16,0x7a,0x00,0x01,0x0f,0xee,0x00,0x01,0x1b,0x0a,0x00,0x01,0x0f,0xe6,0x00,0x01,0x16,0x76,0x00,0x01,0x0f,0xe4,0x00,0x01,0x18,0x9c,0x00,0x01, 0x0f,0xe2,0x00,0x01,0x1a,0x4a,0x00,0x01,0x0f,0xda,0x00,0x01,0x1a,0xfc,0x00,0x01,0x10,0x12,0x00,0x01,0x16,0x62,0x00,0x01,0x0f,0xd0,0x00,0x01,0x12,0x9a,0x00,0x01,0x0f,0xc8,0x00,0x01,0x16,0x5e,0x00,0x01,0x0f,0xfa,0x00,0x01,0x16,0x62,0x00,0x01,0x0f,0xbe,0x00,0x01,0x18,0x72,0x00,0x01,0x0f,0xbc,0x00,0x01,0x1a,0x22,0x00,0x01, 0x0f,0xb4,0x00,0x01,0x18,0x70,0x00,0x01,0x0f,0xb2,0x00,0x01,0x12,0x74,0x00,0x01,0x0f,0xaa,0x00,0x01,0x16,0x46,0x00,0x01,0x0f,0xa8,0x00,0x01,0x12,0x6e,0x00,0x01,0x0f,0xa0,0x00,0x01,0x16,0x42,0x00,0x01,0x0f,0x9e,0x00,0x01,0x12,0x68,0x00,0x01,0x0f,0x9c,0x00,0x01,0x18,0x4e,0x00,0x01,0x0f,0x9a,0x00,0x01,0x12,0x62,0x00,0x01, 0x21,0xd0,0x00,0x01,0x0f,0x98,0x00,0x01,0x12,0x6c,0x00,0x02,0x12,0x5c,0x12,0x64,0x00,0x02,0x12,0x62,0x00,0x02,0x06,0xce,0x03,0x77,0x00,0x02,0x12,0x58,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x12,0x56,0x00,0x02,0x10,0xf6,0x16,0x08,0x00,0x02,0x12,0x4c,0x00,0x02,0x03,0x6e,0x06,0xce,0x00,0x02,0x12,0x42,0x00,0x02,0x06,0xce, 0x06,0xce,0x00,0x01,0x12,0x48,0x00,0x02,0x10,0xde,0x12,0x40,0x00,0x02,0x12,0x3e,0x00,0x02,0x03,0x79,0x06,0xce,0x00,0x01,0x12,0x3c,0x00,0x02,0x15,0xe0,0x0f,0x56,0x00,0x02,0x12,0x32,0x00,0x02,0x06,0xce,0x03,0x8f,0x00,0x01,0x13,0x08,0x00,0x02,0x0f,0x46,0x15,0xd6,0x00,0x02,0x12,0xfe,0x00,0x02,0x06,0x20,0x06,0xce,0x00,0x01, 0x12,0x24,0x00,0x02,0x0f,0x36,0x12,0x1c,0x00,0x02,0x12,0x1a,0x00,0x02,0x06,0x0b,0x06,0xce,0x00,0x01,0x12,0x20,0x00,0x02,0x0f,0x26,0x12,0x18,0x00,0x02,0x12,0x16,0x00,0x02,0x06,0x11,0x06,0xce,0x00,0x01,0x12,0x14,0x00,0x02,0x10,0x80,0x0f,0x16,0x00,0x02,0x12,0x0a,0x00,0x02,0x06,0xce,0x03,0x7c,0x00,0x01,0x12,0x08,0x00,0x02, 0x0f,0x06,0x10,0x72,0x00,0x02,0x11,0xfe,0x00,0x02,0x06,0x12,0x06,0xce,0x00,0x01,0x11,0xfc,0x00,0x02,0x1a,0x28,0x0e,0xf6,0x00,0x02,0x11,0xf2,0x00,0x02,0x06,0xce,0x03,0x7d,0x00,0x01,0x11,0xf8,0x00,0x02,0x11,0xf0,0x0e,0xe6,0x00,0x02,0x11,0xee,0x00,0x02,0x06,0xce,0x03,0x7a,0x00,0x02,0x11,0xec,0x00,0x02,0x03,0xaf,0x06,0xce, 0x00,0x02,0x11,0xe2,0x00,0x02,0x06,0xce,0x03,0xae,0x00,0x01,0x12,0xd0,0x00,0x02,0x15,0x40,0x0e,0xc2,0x00,0x02,0x12,0xc6,0x00,0x02,0x06,0xce,0x03,0xa8,0x00,0x01,0x12,0xbc,0x00,0x02,0x17,0x2c,0x0e,0xb2,0x00,0x02,0x12,0xb2,0x00,0x02,0x06,0xce,0x03,0xac,0x00,0x01,0x12,0xa8,0x00,0x02,0x11,0xb8,0x10,0x00,0x00,0x02,0x12,0x9e, 0x00,0x02,0x06,0xce,0x03,0xa9,0x00,0x01,0x11,0xac,0x00,0x02,0x0e,0x8e,0x18,0xa2,0x00,0x02,0x11,0xa2,0x00,0x02,0x03,0xa6,0x06,0xce,0x00,0x01,0x11,0x98,0x00,0x02,0x0f,0xde,0x18,0x9c,0x00,0x02,0x11,0x8e,0x00,0x02,0x03,0xa7,0x06,0xce,0x00,0x01,0x11,0x84,0x00,0x02,0x18,0x96,0x0e,0x6a,0x00,0x02,0x11,0x7a,0x00,0x02,0x06,0xce, 0x03,0x99,0x00,0x01,0x12,0x38,0x00,0x02,0x11,0x78,0x0e,0x5a,0x00,0x02,0x12,0x2e,0x00,0x02,0x06,0xce,0x03,0x82,0x00,0x01,0x11,0x6c,0x00,0x02,0x14,0xbe,0x0e,0x4a,0x00,0x02,0x11,0x62,0x00,0x02,0x06,0xce,0x03,0x81,0x00,0x01,0x13,0xd0,0x00,0x02,0x0e,0x3a,0x14,0xb4,0x00,0x02,0x13,0xc6,0x00,0x02,0x06,0x4f,0x06,0xce,0x00,0x02, 0x13,0xbc,0x00,0x02,0x06,0x34,0x06,0xce,0x00,0x01,0x11,0x4a,0x00,0x02,0x0e,0x20,0x11,0x42,0x00,0x02,0x11,0x40,0x00,0x02,0x06,0x4d,0x06,0xce,0x00,0x01,0x11,0x8e,0x00,0x02,0x0e,0x10,0x14,0x8c,0x00,0x02,0x11,0x84,0x00,0x02,0x06,0x39,0x06,0xce,0x00,0x01,0x11,0x7a,0x00,0x02,0x0e,0x00,0x14,0x82,0x00,0x02,0x11,0x70,0x00,0x02, 0x06,0xce,0x06,0x3a,0x00,0x01,0x11,0xfe,0x00,0x02,0x14,0x78,0x0d,0xf0,0x00,0x02,0x11,0xf4,0x00,0x02,0x06,0xce,0x06,0x52,0x00,0x01,0x11,0x12,0x00,0x02,0x11,0x02,0x11,0x0a,0x00,0x02,0x11,0x08,0x00,0x02,0x06,0xce,0x06,0x40,0x00,0x01,0x10,0xfe,0x00,0x02,0x14,0x5a,0x0f,0x12,0x00,0x02,0x10,0xf4,0x00,0x02,0x06,0xce,0x06,0x3f, 0x00,0x01,0x10,0xea,0x00,0x02,0x14,0x50,0x0d,0xb8,0x00,0x02,0x10,0xe0,0x00,0x02,0x06,0xce,0x06,0x3e,0x00,0x01,0x11,0x36,0x00,0x02,0x14,0x46,0x0d,0xa8,0x00,0x02,0x11,0x2c,0x00,0x02,0x06,0xce,0x03,0x70,0x00,0x01,0x11,0x82,0x00,0x02,0x10,0xca,0x0e,0xdc,0x00,0x02,0x11,0x78,0x00,0x02,0x06,0xce,0x03,0x72,0x00,0x01,0x11,0x6e, 0x00,0x02,0x15,0xda,0x0d,0x84,0x00,0x02,0x11,0x64,0x00,0x02,0x06,0xce,0x03,0x6f,0x00,0x01,0x11,0x5a,0x00,0x02,0x18,0x04,0x0d,0x74,0x00,0x02,0x11,0x50,0x00,0x02,0x06,0xce,0x03,0x71,0x00,0x01,0x11,0x3e,0x00,0x02,0x0d,0x64,0x15,0xbe,0x00,0x02,0x11,0x34,0x00,0x02,0x06,0x2e,0x06,0xce,0x00,0x01,0x10,0xaa,0x00,0x02,0x0d,0x54, 0x10,0x82,0x00,0x02,0x10,0xa0,0x00,0x02,0x06,0x2d,0x06,0xce,0x00,0x01,0x10,0x76,0x00,0x02,0x0d,0x44,0x18,0x3c,0x00,0x02,0x10,0x6c,0x00,0x02,0x06,0x2c,0x06,0xce,0x00,0x01,0x11,0x1a,0x00,0x02,0x0d,0x34,0x17,0x32,0x00,0x02,0x11,0x10,0x00,0x02,0x06,0x47,0x06,0xce,0x00,0x01,0x11,0x06,0x00,0x02,0x0d,0x24,0x13,0xb0,0x00,0x02, 0x10,0xfc,0x00,0x02,0x06,0x50,0x06,0xce,0x00,0x01,0x10,0xf2,0x00,0x02,0x0e,0x42,0x15,0x66,0x00,0x02,0x10,0xe8,0x00,0x02,0x06,0x49,0x06,0xce,0x00,0x01,0x10,0x2e,0x00,0x02,0x13,0x92,0x0d,0x00,0x00,0x02,0x10,0x24,0x00,0x02,0x03,0xb0,0x06,0xce,0x00,0x01,0x10,0x22,0x00,0x02,0x16,0xf0,0x0c,0xf0,0x00,0x02,0x10,0x18,0x00,0x02, 0x06,0xce,0x03,0x90,0x00,0x01,0x10,0x0e,0x00,0x02,0x15,0x36,0x0e,0x0c,0x00,0x02,0x10,0x04,0x00,0x02,0x06,0xce,0x03,0x91,0x00,0x01,0x0f,0xfa,0x00,0x02,0x0c,0xcc,0x15,0x2e,0x00,0x02,0x0f,0xf0,0x00,0x02,0x06,0xce,0x06,0x22,0x00,0x01,0x10,0x76,0x00,0x02,0x17,0xd0,0x0c,0xbc,0x00,0x02,0x10,0x6c,0x00,0x02,0x06,0xce,0x06,0x26, 0x00,0x01,0x0f,0xf2,0x00,0x02,0x0c,0xac,0x15,0x12,0x00,0x02,0x0f,0xe8,0x00,0x02,0x06,0xce,0x06,0x21,0x00,0x01,0x0f,0xde,0x00,0x02,0x13,0x24,0x0c,0x9c,0x00,0x02,0x0f,0xd4,0x00,0x02,0x06,0xce,0x03,0x89,0x00,0x01,0x0f,0xba,0x00,0x02,0x0f,0xb2,0x0c,0x8c,0x00,0x02,0x0f,0xb0,0x00,0x02,0x06,0xce,0x03,0x8a,0x00,0x01,0x0f,0xae, 0x00,0x02,0x13,0x06,0x0c,0x7c,0x00,0x02,0x0f,0xa4,0x00,0x02,0x06,0xce,0x03,0x8b,0x00,0x01,0x0f,0xd2,0x00,0x02,0x12,0xfc,0x0c,0x6c,0x00,0x02,0x0f,0xc8,0x00,0x02,0x06,0xce,0x03,0x87,0x00,0x01,0x0f,0x8e,0x00,0x02,0x12,0xf2,0x0c,0x5c,0x00,0x02,0x0f,0x84,0x00,0x02,0x06,0xce,0x03,0x86,0x00,0x01,0x0f,0x8a,0x00,0x02,0x0c,0x4c, 0x14,0xa6,0x00,0x02,0x0f,0x80,0x00,0x02,0x06,0x16,0x06,0xce,0x00,0x01,0x0f,0x76,0x00,0x02,0x0c,0x3c,0x14,0x9e,0x00,0x02,0x0f,0x6c,0x00,0x02,0x06,0x18,0x06,0xce,0x00,0x01,0x0f,0x62,0x00,0x02,0x0c,0x2c,0x0f,0x5a,0x00,0x02,0x0f,0x58,0x00,0x02,0x06,0x1b,0x06,0xce,0x00,0x01,0x0f,0x56,0x00,0x02,0x0c,0x1c,0x12,0xac,0x00,0x02, 0x0f,0x4c,0x00,0x02,0x06,0x14,0x06,0xce,0x00,0x01,0x0f,0x4a,0x00,0x02,0x0c,0x0c,0x12,0xa2,0x00,0x02,0x0f,0x40,0x00,0x02,0x06,0x17,0x06,0xce,0x00,0x01,0x0f,0x2e,0x00,0x02,0x0b,0xfc,0x12,0x98,0x00,0x02,0x0f,0x24,0x00,0x02,0x06,0x0f,0x06,0xce,0x00,0x01,0x0f,0x22,0x00,0x02,0x0b,0xec,0x12,0x8e,0x00,0x02,0x0f,0x18,0x00,0x02, 0x06,0x19,0x06,0xce,0x00,0x01,0x10,0xf6,0x00,0x02,0x0c,0xd2,0x0f,0x16,0x00,0x02,0x10,0xec,0x00,0x02,0x06,0x35,0x06,0xce,0x00,0x01,0x0f,0x0a,0x00,0x02,0x0b,0xc8,0x12,0x70,0x00,0x02,0x0f,0x00,0x00,0x02,0x03,0x93,0x06,0xce,0x00,0x01,0x0e,0xfe,0x00,0x02,0x16,0x6e,0x0b,0xb8,0x00,0x02,0x0e,0xf4,0x00,0x02,0x06,0xce,0x03,0x96, 0x00,0x01,0x0e,0xfa,0x00,0x02,0x0b,0xa8,0x0e,0xf2,0x00,0x02,0x0e,0xf0,0x00,0x02,0x03,0x92,0x06,0xce,0x00,0x01,0x0e,0xee,0x00,0x02,0x0b,0x98,0x12,0x3e,0x00,0x02,0x0e,0xe4,0x00,0x02,0x06,0x0e,0x06,0xce,0x00,0x01,0x0e,0xea,0x00,0x02,0x0e,0xe2,0x0b,0x88,0x00,0x02,0x0e,0xe0,0x00,0x02,0x06,0xce,0x03,0x83,0x00,0x01,0x0e,0xde, 0x00,0x02,0x0b,0x78,0x13,0xba,0x00,0x02,0x0e,0xd4,0x00,0x02,0x06,0xce,0x06,0x29,0x00,0x01,0x10,0x6a,0x00,0x02,0x0b,0x68,0x12,0x0c,0x00,0x02,0x10,0x60,0x00,0x02,0x06,0xce,0x06,0x38,0x00,0x01,0x0e,0xd6,0x00,0x02,0x0b,0x58,0x13,0x9e,0x00,0x02,0x0e,0xcc,0x00,0x02,0x06,0xce,0x06,0x4c,0x00,0x01,0x0e,0xaa,0x00,0x02,0x15,0x6c, 0x0b,0x48,0x00,0x02,0x0e,0xa0,0x00,0x02,0x06,0xce,0x06,0x25,0x00,0x01,0x0e,0x96,0x00,0x02,0x11,0xda,0x0c,0x10,0x00,0x02,0x0e,0x8c,0x00,0x02,0x06,0xce,0x06,0x27,0x00,0x01,0x0e,0x82,0x00,0x02,0x0b,0x24,0x11,0xd0,0x00,0x02,0x0e,0x78,0x00,0x02,0x06,0xce,0x06,0x2f,0x00,0x01,0x0e,0x6e,0x00,0x02,0x0b,0x14,0x11,0xc6,0x00,0x02, 0x0e,0x64,0x00,0x02,0x06,0x32,0x06,0xce,0x00,0x01,0x0e,0x62,0x00,0x02,0x0b,0x04,0x11,0xbc,0x00,0x02,0x0e,0x58,0x00,0x02,0x06,0x31,0x06,0xce,0x00,0x01,0x0e,0x4e,0x00,0x02,0x0a,0xf4,0x13,0x32,0x00,0x02,0x0e,0x44,0x00,0x02,0x06,0x2a,0x06,0xce,0x00,0x01,0x0e,0x3a,0x00,0x02,0x0a,0xe4,0x11,0x9e,0x00,0x02,0x0e,0x30,0x00,0x02, 0x06,0xce,0x06,0x2b,0x00,0x01,0x0e,0x3e,0x00,0x02,0x11,0x94,0x0a,0xd4,0x00,0x02,0x0e,0x34,0x00,0x02,0x06,0xce,0x06,0x53,0x00,0x01,0x0f,0xa2,0x00,0x02,0x13,0x02,0x0a,0xc4,0x00,0x02,0x0f,0x98,0x00,0x02,0x06,0xce,0x03,0x73,0x00,0x01,0x0f,0x8e,0x00,0x02,0x0e,0x06,0x0b,0x76,0x00,0x02,0x0f,0x84,0x00,0x02,0x06,0xce,0x03,0x74, 0x00,0x01,0x0d,0xfa,0x00,0x02,0x11,0x62,0x0b,0x68,0x00,0x02,0x0d,0xf0,0x00,0x02,0x06,0xce,0x06,0x28,0x00,0x01,0x0d,0xee,0x00,0x02,0x11,0x58,0x0b,0x5a,0x00,0x02,0x0d,0xe4,0x00,0x02,0x06,0xce,0x06,0x55,0x00,0x01,0x0d,0xfa,0x00,0x02,0x11,0x4e,0x0a,0x78,0x00,0x02,0x0d,0xf0,0x00,0x02,0x06,0xce,0x03,0x75,0x00,0x01,0x0d,0xd6, 0x00,0x02,0x0a,0x68,0x11,0x44,0x00,0x02,0x0d,0xcc,0x00,0x02,0x06,0x5c,0x06,0xce,0x00,0x01,0x0d,0xc2,0x00,0x02,0x0a,0x58,0x0d,0xba,0x00,0x02,0x0d,0xb8,0x00,0x02,0x06,0x5a,0x06,0xce,0x00,0x01,0x0d,0xbe,0x00,0x02,0x0a,0x48,0x0d,0xb6,0x00,0x02,0x0d,0xb4,0x00,0x02,0x06,0x58,0x06,0xce,0x00,0x01,0x0d,0xba,0x00,0x02,0x0d,0xb2, 0x0a,0x38,0x00,0x02,0x0d,0xb0,0x00,0x02,0x06,0xce,0x06,0x59,0x00,0x01,0x0d,0xb6,0x00,0x02,0x0a,0x28,0x0d,0xae,0x00,0x02,0x0d,0xac,0x00,0x02,0x06,0x5d,0x06,0xce,0x00,0x01,0x0d,0xb2,0x00,0x02,0x0a,0x18,0x0d,0xaa,0x00,0x02,0x0d,0xa8,0x00,0x02,0x06,0x42,0x06,0xce,0x00,0x01,0x0d,0xae,0x00,0x02,0x0d,0xa6,0x0a,0x08,0x00,0x02, 0x0d,0xa4,0x00,0x02,0x06,0xce,0x06,0x1c,0x00,0x01,0x0d,0xaa,0x00,0x02,0x09,0xf8,0x0d,0xa2,0x00,0x02,0x0d,0xa0,0x00,0x02,0x06,0x45,0x06,0xce,0x00,0x01,0x0d,0xa6,0x00,0x02,0x0d,0x9e,0x09,0xe8,0x00,0x02,0x0d,0x9c,0x00,0x02,0x06,0xce,0x06,0x1f,0x00,0x01,0x0d,0xa2,0x00,0x02,0x09,0xd8,0x0d,0x9a,0x00,0x02,0x0d,0x98,0x00,0x02, 0x06,0x3c,0x06,0xce,0x00,0x01,0x0d,0x9e,0x00,0x02,0x0d,0x96,0x09,0xc8,0x00,0x02,0x0d,0x94,0x00,0x02,0x06,0xce,0x03,0x98,0x00,0x01,0x0d,0x9a,0x00,0x02,0x09,0xb8,0x0d,0x92,0x00,0x02,0x0d,0x90,0x00,0x02,0x06,0x56,0x06,0xce,0x00,0x01,0x0d,0x96,0x00,0x02,0x0d,0x8e,0x09,0xa8,0x00,0x02,0x0d,0x8c,0x00,0x02,0x06,0xce,0x03,0xaa, 0x00,0x01,0x0d,0x92,0x00,0x02,0x0d,0x8a,0x09,0x98,0x00,0x02,0x0d,0x88,0x00,0x02,0x06,0xce,0x03,0x9b,0x00,0x01,0x0d,0x8e,0x00,0x02,0x0d,0x86,0x09,0x88,0x00,0x02,0x0d,0x84,0x00,0x02,0x06,0xce,0x03,0x9c,0x00,0x01,0x0d,0x8a,0x00,0x02,0x0d,0x82,0x09,0x78,0x00,0x02,0x0d,0x80,0x00,0x02,0x06,0xce,0x03,0x9a,0x00,0x01,0x0d,0x86, 0x00,0x02,0x09,0x68,0x0d,0x7e,0x00,0x02,0x0d,0x7c,0x00,0x02,0x03,0x9f,0x06,0xce,0x00,0x01,0x0d,0x7a,0x00,0x02,0x0f,0xfa,0x09,0x58,0x00,0x02,0x0d,0x70,0x00,0x02,0x06,0xce,0x03,0xa4,0x00,0x01,0x0d,0x76,0x00,0x02,0x09,0x48,0x0d,0x6e,0x00,0x02,0x0d,0x6c,0x00,0x02,0x03,0x9e,0x06,0xce,0x00,0x01,0x0d,0x72,0x00,0x02,0x09,0x38, 0x0d,0x6a,0x00,0x02,0x0d,0x68,0x00,0x02,0x03,0x9d,0x06,0xce,0x00,0x01,0x0d,0x6e,0x00,0x02,0x0d,0x66,0x09,0x28,0x00,0x02,0x0d,0x64,0x00,0x02,0x06,0xce,0x03,0xa3,0x00,0x01,0x0d,0x6a,0x00,0x02,0x09,0x18,0x0d,0x62,0x00,0x02,0x0d,0x60,0x00,0x02,0x03,0x7e,0x06,0xce,0x00,0x02,0x0d,0x5e,0x00,0x02,0x01,0xc5,0x01,0xc4,0x00,0x02, 0x0d,0x5c,0x00,0x02,0x02,0x0b,0x02,0x50,0x00,0x01,0x10,0xde,0x00,0x03,0x09,0x6c,0x0f,0x8c,0x0d,0x5a,0x00,0x02,0x10,0xd2,0x00,0x03,0x06,0xce,0x06,0xce,0x03,0x78,0x00,0x01,0x10,0xda,0x00,0x03,0x09,0x58,0x0d,0x48,0x10,0xd0,0x00,0x02,0x10,0xce,0x00,0x03,0x06,0xce,0x06,0x3b,0x06,0xce,0x00,0x01,0x10,0xcc,0x00,0x03,0x09,0x44, 0x0d,0x36,0x0f,0x64,0x00,0x02,0x10,0xc0,0x00,0x03,0x06,0xce,0x06,0x44,0x06,0xce,0x00,0x01,0x10,0xf0,0x00,0x03,0x09,0x30,0x09,0x34,0x10,0xbe,0x00,0x02,0x10,0xe4,0x00,0x03,0x06,0xce,0x06,0x4b,0x06,0xce,0x00,0x01,0x10,0xb0,0x00,0x03,0x09,0x20,0x09,0x24,0x0f,0x3c,0x00,0x02,0x10,0xa4,0x00,0x03,0x06,0xce,0x06,0x37,0x06,0xce, 0x00,0x01,0x10,0xa2,0x00,0x03,0x09,0x10,0x0f,0x2c,0x09,0x14,0x00,0x02,0x10,0x96,0x00,0x03,0x06,0x41,0x06,0xce,0x06,0xce,0x00,0x01,0x10,0x94,0x00,0x03,0x0f,0x1c,0x09,0x00,0x09,0x04,0x00,0x02,0x10,0x88,0x00,0x03,0x06,0xce,0x06,0xce,0x03,0x88,0x00,0x01,0x10,0x90,0x00,0x03,0x0c,0xc4,0x08,0xf0,0x10,0x86,0x00,0x02,0x10,0x84, 0x00,0x03,0x06,0xce,0x06,0x4a,0x06,0xce,0x00,0x01,0x10,0x82,0x00,0x03,0x08,0xdc,0x0e,0xf4,0x08,0xe0,0x00,0x02,0x10,0x76,0x00,0x03,0x06,0x54,0x06,0xce,0x06,0xce,0x00,0x01,0x10,0x74,0x00,0x03,0x08,0xcc,0x0e,0xe4,0x08,0xd0,0x00,0x02,0x10,0x68,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0x36,0x00,0x01,0x10,0x70,0x00,0x03,0x08,0xbc, 0x10,0x66,0x08,0xc0,0x00,0x02,0x10,0x64,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0x48,0x00,0x01,0x10,0x62,0x00,0x03,0x08,0xac,0x08,0xb0,0x0e,0xbc,0x00,0x02,0x10,0x56,0x00,0x03,0x06,0xce,0x06,0x1a,0x06,0xce,0x00,0x01,0x10,0x54,0x00,0x03,0x08,0x9c,0x08,0xa0,0x0e,0xac,0x00,0x02,0x10,0x48,0x00,0x03,0x06,0xce,0x06,0x10,0x06,0xce, 0x00,0x01,0x10,0x46,0x00,0x03,0x08,0x8c,0x08,0x90,0x0e,0x9c,0x00,0x02,0x10,0x3a,0x00,0x03,0x06,0xce,0x06,0x43,0x06,0xce,0x00,0x01,0x10,0x38,0x00,0x03,0x08,0x7c,0x08,0x80,0x0e,0x8c,0x00,0x02,0x10,0x2c,0x00,0x03,0x06,0xce,0x06,0x46,0x06,0xce,0x00,0x01,0x10,0x2a,0x00,0x03,0x08,0x6c,0x08,0x70,0x0e,0x7c,0x00,0x02,0x10,0x1e, 0x00,0x03,0x06,0xce,0x06,0x3d,0x06,0xce,0x00,0x01,0x10,0x1c,0x00,0x03,0x08,0x5c,0x08,0x60,0x0e,0x6c,0x00,0x02,0x10,0x10,0x00,0x03,0x06,0xce,0x06,0x57,0x06,0xce,0x00,0x01,0x10,0x0e,0x00,0x03,0x0e,0x5c,0x08,0x4c,0x08,0x50,0x00,0x02,0x10,0x02,0x00,0x03,0x06,0xce,0x03,0xa5,0x06,0xce,0x00,0x01,0x20,0x08,0x00,0x04,0x10,0x76, 0x10,0x80,0x10,0x8a,0x10,0x94,0x00,0x02,0x10,0xee,0x00,0x04,0x00,0x86,0x00,0x8d,0x01,0x49,0x01,0x50,0x00,0x02,0x10,0xec,0x00,0x04,0x01,0xc6,0x01,0xc7,0x01,0xc6,0x01,0xc7,0x00,0x02,0x10,0xea,0x00,0x04,0x03,0xb2,0x03,0xb3,0x06,0x5e,0x06,0x5f,0x00,0x02,0x10,0xe8,0x00,0x04,0x01,0x90,0x01,0x91,0x01,0x92,0x02,0x49,0x00,0x02, 0x10,0xe6,0x00,0x04,0x06,0x02,0x06,0x08,0x06,0x09,0x06,0x0a,0x00,0x02,0x05,0x8e,0x12,0x4c,0x10,0x4a,0x12,0x4c,0x00,0x02,0x0b,0x76,0x0f,0xac,0x00,0x02,0x12,0xb4,0x12,0x8c,0x12,0x64,0x12,0x8c,0x00,0x02,0x0b,0x66,0x0f,0xa2,0x00,0x02,0x11,0x24,0x00,0x05,0x03,0xce,0x03,0xcf,0x06,0x05,0x06,0x06,0x06,0x07,0x00,0x02,0x11,0x22, 0x00,0x05,0x02,0xe2,0x03,0x18,0x03,0x19,0x03,0x1a,0x03,0x1b,0x00,0x02,0x11,0x20,0x00,0x05,0x02,0xe3,0x03,0x1c,0x03,0x1d,0x03,0x1e,0x03,0x1f,0x00,0x02,0x0b,0x1e,0x11,0x34,0x11,0x44,0x11,0xda,0x00,0x03,0x0b,0x26,0x11,0x64,0x0f,0x68,0x00,0x02,0x11,0x42,0x00,0x06,0x01,0x7e,0x01,0x7f,0x01,0x80,0x01,0x81,0x01,0x82,0x01,0x83, 0x00,0x02,0x11,0x30,0x00,0x06,0x01,0x93,0x01,0x94,0x01,0x95,0x01,0x96,0x01,0x97,0x01,0x98,0x00,0x03,0x00,0x01,0x12,0x8e,0x00,0x01,0x05,0x0e,0x00,0x01,0x12,0x8e,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x01,0x10,0x4a,0x00,0x01,0x07,0x4e,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0xad,0x00,0x03,0x00,0x01,0x10,0xc2,0x00,0x01, 0x07,0x3c,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0xae,0x00,0x03,0x00,0x01,0x07,0x34,0x00,0x01,0x10,0x62,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0xb0,0x00,0x03,0x00,0x01,0x07,0x22,0x00,0x01,0x10,0x58,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0xb0,0x00,0x03,0x00,0x02,0x10,0x96,0x10,0xe6,0x00,0x01,0x04,0xb8,0x00,0x01,0x10,0xe6,0x00,0x01, 0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x01,0x10,0xd0,0x00,0x01,0x10,0x86,0x00,0x02,0x04,0xa2,0x10,0xd0,0x00,0x01,0x00,0x00,0x00,0x37,0x00,0x03,0x00,0x02,0x10,0x6a,0x10,0xba,0x00,0x01,0x10,0x70,0x00,0x01,0x10,0xba,0x00,0x01,0x00,0x00,0x00,0x39,0x00,0x03,0x00,0x01,0x10,0xa4,0x00,0x01,0x04,0x76,0x00,0x02,0x10,0x5a,0x10,0xa4, 0x00,0x01,0x00,0x00,0x00,0x39,0x00,0x03,0x00,0x00,0x00,0x01,0x10,0xcc,0x00,0x01,0x10,0x9c,0x00,0x01,0x00,0x00,0x01,0x95,0x00,0x03,0x00,0x01,0x11,0x78,0x00,0x01,0x11,0x78,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x95,0x00,0x03,0x00,0x01,0x11,0x8e,0x00,0x01,0x11,0x66,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x96,0x00,0x02,0x10,0x76, 0x00,0x0a,0x00,0xb5,0x00,0xb6,0x00,0xb7,0x00,0xb8,0x00,0xb9,0x01,0x9a,0x01,0x9b,0x01,0x9c,0x01,0x9d,0x01,0x9e,0x00,0x03,0x00,0x00,0x00,0x01,0x10,0x7c,0x00,0x02,0x10,0x6c,0x10,0x4c,0x00,0x01,0x00,0x00,0x01,0x96,0x00,0x02,0x10,0x7c,0x00,0x0b,0x03,0x02,0x03,0x03,0x03,0x04,0x03,0x05,0x03,0x06,0x03,0x07,0x03,0x08,0x03,0x09, 0x03,0x0a,0x03,0x0b,0x04,0x3b,0x00,0x02,0x11,0x9e,0x00,0x0f,0x01,0xa7,0x01,0xa8,0x01,0xa9,0x01,0xaa,0x01,0xab,0x01,0xac,0x01,0xad,0x01,0xae,0x01,0xaf,0x02,0x09,0x02,0x0a,0x02,0x4e,0x02,0x4f,0x02,0x9d,0x02,0x9e,0x00,0x02,0x11,0x9c,0x00,0x0f,0x02,0xdf,0x02,0xe0,0x02,0xe1,0x03,0x0c,0x03,0x0d,0x03,0x0e,0x03,0x0f,0x03,0x10, 0x03,0x11,0x03,0x12,0x03,0x13,0x03,0x14,0x03,0x15,0x03,0x16,0x03,0x17,0x00,0x02,0x11,0x9a,0x00,0x10,0x00,0xba,0x00,0xbb,0x01,0x9f,0x01,0xa0,0x01,0xa1,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x08,0x02,0x4a,0x02,0x4b,0x02,0x4c,0x02,0x4d,0x02,0x73,0x02,0x74,0x02,0x9c,0x00,0x02,0x11,0x1a,0x00,0x13,0x01,0xb0,0x01,0xb1,0x01,0xb2, 0x01,0xb3,0x01,0xb4,0x01,0xb5,0x01,0xb6,0x01,0xb7,0x01,0xb8,0x01,0xb9,0x01,0xba,0x01,0xbb,0x01,0xbc,0x01,0xbd,0x01,0xbe,0x01,0xbf,0x01,0xc0,0x01,0xc1,0x01,0xc2,0x00,0x01,0x13,0xd6,0x00,0x24,0x11,0xf8,0x11,0x90,0x11,0x98,0x11,0xa0,0x11,0xa8,0x11,0xb0,0x11,0xb8,0x11,0xc0,0x11,0xc8,0x11,0xd0,0x12,0x02,0x12,0x7e,0x11,0xd8, 0x12,0x0c,0x12,0x52,0x11,0x6c,0x12,0x16,0x12,0x22,0x12,0x6e,0x11,0x72,0x11,0x78,0x11,0xe0,0x12,0x2e,0x11,0x7e,0x11,0xe8,0x12,0xc2,0x12,0x3a,0x11,0x84,0x12,0x46,0x12,0xe2,0x13,0x4a,0x12,0xa8,0x12,0x60,0x11,0x8a,0x11,0xf0,0x12,0x92,0x00,0x02,0x13,0x42,0x00,0x26,0x00,0xb5,0x00,0xb6,0x00,0xb7,0x00,0xb8,0x00,0xb9,0x01,0xc3, 0x01,0x93,0x01,0x94,0x01,0x95,0x01,0x96,0x01,0x97,0x01,0x98,0x01,0x99,0x01,0x84,0x01,0x85,0x01,0x86,0x01,0x87,0x01,0x88,0x01,0x9a,0x01,0x9b,0x01,0x9c,0x01,0x9d,0x01,0x9e,0x01,0xa7,0x01,0xa8,0x01,0xa9,0x01,0xaa,0x01,0xab,0x01,0xac,0x01,0xad,0x01,0xae,0x01,0xaf,0x02,0x09,0x02,0x0a,0x02,0x4e,0x02,0x4f,0x02,0x9d,0x02,0x9e, 0x00,0x02,0x0f,0xd0,0x00,0x27,0x06,0x8e,0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x06,0x9a,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0xa0,0x06,0xa1,0x06,0xa2,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x06,0xac,0x06,0xad,0x06,0xae, 0x06,0xaf,0x06,0xb1,0x06,0xbc,0x06,0xbd,0x06,0xbe,0x06,0xbf,0x06,0xc0,0x06,0xc1,0x06,0xc2,0x06,0xc3,0x00,0x02,0x12,0x22,0x00,0x29,0x03,0x40,0x03,0x41,0x06,0x8e,0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x06,0x9a,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0xa0, 0x06,0xa1,0x06,0xa2,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x06,0xac,0x06,0xad,0x06,0xae,0x06,0xaf,0x06,0xb1,0x06,0xbc,0x06,0xbd,0x06,0xbe,0x06,0xbf,0x06,0xc0,0x06,0xc1,0x06,0xc2,0x06,0xc3,0x00,0x02,0x12,0xd6,0x00,0x2f,0x01,0x00,0x06,0xcc,0x06,0xcb,0x01,0x0e,0x01,0x91,0x01,0x00,0x01,0x0e, 0x01,0x91,0x06,0x8e,0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x06,0x9a,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0xa0,0x06,0xa1,0x06,0xa2,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x06,0xac,0x06,0xad,0x06,0xae,0x06,0xaf,0x06,0xb1, 0x06,0xbc,0x06,0xbd,0x06,0xbe,0x06,0xbf,0x06,0xc0,0x06,0xc1,0x06,0xc2,0x06,0xc3,0x00,0x02,0x12,0xca,0x00,0x3b,0x00,0xba,0x00,0xbb,0x01,0xa2,0x01,0x9f,0x01,0xa0,0x01,0xa1,0x01,0x7e,0x01,0x7f,0x01,0x80,0x01,0x81,0x01,0x82,0x01,0x83,0x01,0xa3,0x01,0xa4,0x01,0xa5,0x01,0xa6,0x01,0xb0,0x01,0xb1,0x01,0xb2,0x01,0xb3,0x01,0xb4, 0x01,0xb5,0x01,0xb6,0x01,0xb7,0x01,0xb8,0x01,0xb9,0x01,0xba,0x01,0xbb,0x01,0xbc,0x01,0xbd,0x01,0xbe,0x01,0xbf,0x01,0xc0,0x01,0xc1,0x01,0xc2,0x01,0xa7,0x01,0xa8,0x01,0xa9,0x01,0xaa,0x01,0xab,0x01,0xac,0x01,0xad,0x01,0xae,0x01,0xaf,0x02,0x05,0x02,0x06,0x02,0x07,0x02,0x09,0x02,0x0a,0x02,0x08,0x02,0x4a,0x02,0x4b,0x02,0x4c, 0x02,0x4e,0x02,0x4f,0x02,0x4d,0x02,0x9d,0x02,0x9c,0x02,0x9e,0x00,0x02,0x12,0xc4,0x00,0x3d,0x01,0xc6,0x01,0xc7,0x00,0x86,0x00,0x8d,0x01,0xc6,0x01,0x06,0x01,0xc7,0x01,0x49,0x01,0x7d,0x01,0x50,0x02,0xee,0x02,0xef,0x02,0xf0,0x02,0xf1,0x02,0xf2,0x02,0xf3,0x02,0xf4,0x02,0xf5,0x02,0xf6,0x02,0xf7,0x03,0x41,0x06,0xce,0x06,0x8e, 0x06,0x8f,0x06,0x90,0x06,0x91,0x06,0x92,0x06,0x93,0x06,0x94,0x06,0x95,0x06,0x96,0x06,0x97,0x06,0x98,0x06,0x99,0x06,0x9a,0x06,0x9c,0x06,0x9d,0x06,0x9e,0x06,0xa0,0x06,0xa1,0x06,0xa2,0x06,0xa5,0x06,0xa6,0x06,0xa7,0x06,0xa8,0x06,0xa9,0x06,0xaa,0x06,0xab,0x06,0xac,0x06,0xad,0x06,0xae,0x06,0xaf,0x06,0xb1,0x06,0xbc,0x06,0xbd, 0x06,0xbe,0x06,0xbf,0x06,0xc0,0x06,0xc1,0x06,0xc2,0x06,0xc3,0x00,0x01,0x00,0x01,0x00,0xff,0x00,0x01,0x00,0x01,0x02,0xd4,0x00,0x01,0x00,0x01,0x01,0x1a,0x00,0x01,0x00,0x01,0x00,0x7c,0x00,0x01,0x00,0x01,0x00,0xf4,0x00,0x01,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01, 0x03,0x34,0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x01,0x03,0x2c,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x01, 0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x01,0x03,0x32,0x00,0x01,0x12,0x30,0x00,0x01,0x00,0x01,0x01,0x4a,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x01,0x15,0x88,0x00,0x01,0x12,0x24,0x00,0x01,0x12,0x2e,0x00,0x01,0x12,0x38,0x00,0x01,0x12,0x42, 0x00,0x01,0x12,0x4c,0x00,0x01,0x12,0x56,0x00,0x01,0x12,0x60,0x00,0x01,0x12,0x6a,0x00,0x01,0x15,0x74,0x00,0x01,0x12,0x70,0x00,0x01,0x12,0x7a,0x00,0x01,0x12,0x84,0x00,0x01,0x15,0x74,0x00,0x01,0x15,0x80,0x00,0x01,0x12,0x86,0x00,0x01,0x12,0x90,0x00,0x01,0x15,0x84,0x00,0x01,0x15,0x90,0x00,0x01,0x12,0x92,0x00,0x01,0x12,0x9c, 0x00,0x01,0x15,0x94,0x00,0x01,0x12,0xa2,0x00,0x01,0x12,0xac,0x00,0x01,0x12,0xb6,0x00,0x01,0x12,0xc0,0x00,0x01,0x12,0xca,0x00,0x01,0x12,0xd4,0x00,0x01,0x15,0x88,0x00,0x01,0x12,0xda,0x00,0x01,0x15,0x90,0x00,0x01,0x12,0xe0,0x00,0x01,0x15,0x98,0x00,0x01,0x12,0xe6,0x00,0x01,0x12,0xf0,0x00,0x01,0x12,0xfa,0x00,0x01,0x13,0x04, 0x00,0x01,0x15,0x94,0x00,0x01,0x19,0xc4,0x00,0x01,0x15,0x9c,0x00,0x01,0x13,0x02,0x00,0x01,0x15,0xa4,0x00,0x01,0x15,0xb0,0x00,0x01,0x13,0x04,0x00,0x01,0x13,0x0e,0x00,0x01,0x13,0x18,0x00,0x01,0x13,0x22,0x00,0x01,0x13,0x2c,0x00,0x01,0x13,0x36,0x00,0x01,0x13,0x40,0x00,0x01,0x15,0xa0,0x00,0x01,0x15,0xac,0x00,0x01,0x15,0xb8, 0x00,0x01,0x15,0xc4,0x00,0x01,0x15,0xd0,0x00,0x01,0x15,0xdc,0x00,0x01,0x15,0xe8,0x00,0x01,0x13,0x2e,0x00,0x01,0x15,0xf0,0x00,0x01,0x13,0x34,0x00,0x01,0x13,0x3e,0x00,0x01,0x13,0x48,0x00,0x01,0x15,0xf0,0x00,0x01,0x13,0x4e,0x00,0x01,0x13,0x58,0x00,0x01,0x13,0x62,0x00,0x01,0x13,0x6c,0x00,0x01,0x13,0x76,0x00,0x01,0x13,0x80, 0x00,0x01,0x13,0x8a,0x00,0x01,0x13,0x94,0x00,0x01,0x13,0x9e,0x00,0x01,0x13,0xa8,0x00,0x01,0x13,0xb2,0x00,0x01,0x13,0xbc,0x00,0x01,0x13,0xc6,0x00,0x01,0x13,0xd0,0x00,0x01,0x13,0xda,0x00,0x01,0x13,0xe4,0x00,0x01,0x13,0xee,0x00,0x01,0x13,0xf8,0x00,0x01,0x14,0x02,0x00,0x01,0x14,0x0c,0x00,0x01,0x14,0x16,0x00,0x02,0x00,0x01, 0x01,0x4c,0x01,0x50,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0xf5,0x00,0xfb,0x00,0x00,0x00,0x02,0x00,0x01,0x01,0x40,0x01,0x43,0x00,0x00,0x00,0x02,0x20,0xe0,0x20,0xf2,0x00,0x02,0x18,0xfa,0x19,0x0a,0x00,0x02,0x13,0xf6,0x15,0x7e,0x00,0x02,0x13,0xfc,0x15,0x86,0x00,0x02,0x19,0x08,0x19,0x18,0x00,0x02,0x19,0x22,0x19,0x32,0x00,0x02, 0x19,0x3c,0x19,0x4c,0x00,0x02,0x19,0x56,0x19,0x66,0x00,0x02,0x19,0x70,0x19,0x80,0x00,0x02,0x19,0x8a,0x19,0x9a,0x00,0x02,0x19,0xa4,0x19,0xb4,0x00,0x02,0x19,0xbe,0x19,0xce,0x00,0x02,0x19,0xd8,0x19,0xe8,0x00,0x02,0x19,0xf2,0x1a,0x02,0x00,0x02,0x1a,0x0c,0x1a,0x1c,0x00,0x01,0x20,0xaa,0x00,0x01,0x20,0xb8,0x00,0x01,0x20,0xc6, 0x00,0x01,0x1a,0x1a,0x00,0x01,0x1a,0x26,0x00,0x01,0x1a,0x32,0x00,0x01,0x1a,0x3e,0x00,0x01,0x1a,0x4a,0x00,0x01,0x1a,0x56,0x00,0x01,0x1a,0x62,0x00,0x01,0x1a,0x6e,0x00,0x01,0x1a,0x7a,0x00,0x01,0x1a,0x86,0x00,0x01,0x1a,0x92,0x00,0x01,0x1a,0x9e,0x00,0x01,0x1a,0xaa,0x00,0x01,0x1a,0xb6,0x00,0x01,0x1a,0xc2,0x00,0x01,0x1a,0xce, 0x00,0x01,0x1a,0xda,0x00,0x01,0x1a,0xe6,0x00,0x01,0x1a,0xf2,0x00,0x01,0x1a,0xfe,0x00,0x01,0x1b,0x0a,0x00,0x01,0x1b,0x16,0x00,0x01,0x1b,0x22,0x00,0x01,0x1b,0x2e,0x00,0x01,0x1b,0x3a,0x00,0x01,0x1b,0x46,0x00,0x01,0x1b,0x52,0x00,0x01,0x1b,0x5e,0x00,0x01,0x1b,0x6a,0x00,0x02,0x00,0x01,0x02,0xf8,0x03,0x01,0x00,0x00,0x00,0x02, 0x00,0x01,0x02,0xd4,0x02,0xdd,0x00,0x00,0x00,0x04,0x14,0xb8,0x14,0xc4,0x1b,0x62,0x1b,0x70,0x00,0x04,0x14,0xc6,0x14,0xd2,0x1b,0x74,0x1b,0x82,0x00,0x04,0x14,0xd4,0x16,0xcc,0x1b,0x86,0x1b,0x94,0x00,0x04,0x14,0xd6,0x16,0x0e,0x1b,0x98,0x1b,0xa6,0x00,0x04,0x14,0xd8,0x14,0xe4,0x1b,0xaa,0x1b,0xb8,0x00,0x04,0x14,0xe6,0x16,0xc6, 0x1b,0xbc,0x1b,0xca,0x00,0x04,0x14,0xe8,0x14,0xf4,0x1b,0xce,0x1b,0xdc,0x00,0x04,0x14,0xf6,0x16,0xca,0x1b,0xe0,0x1b,0xee,0x00,0x04,0x1f,0xfc,0x20,0x0c,0x20,0x1c,0x20,0x2c,0x00,0x03,0x20,0x32,0x26,0xa4,0x26,0xb6,0x00,0x03,0x20,0x3a,0x26,0xc0,0x26,0xd2,0x00,0x01,0x00,0x02,0x03,0x45,0x03,0x57,0x00,0x01,0x00,0x02,0x03,0x46, 0x03,0x57,0x00,0x03,0x1b,0xc8,0x1b,0xd6,0x20,0x32,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x45,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x46,0x00,0x03,0x14,0xb6,0x16,0x7e,0x1b,0xcc,0x00,0x01,0x00,0x02,0x03,0x5c,0x05,0xb4,0x00,0x03,0x14,0xb2,0x14,0xbe,0x1b,0xca,0x00,0x01,0x00,0x02,0x03,0x46,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x47, 0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x48,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x47,0x04,0x1c,0x00,0x03,0x14,0xa2,0x16,0x5e,0x1b,0xb0,0x00,0x01,0x00,0x02,0x03,0x45,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x3d,0x03,0x3e,0x00,0x03,0x1b,0xa6,0x1e,0xf6,0x1f,0xda,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x3d,0x00,0x03,0x14,0x86,0x16,0x06, 0x1b,0xa4,0x00,0x01,0x00,0x02,0x03,0x29,0x04,0x1c,0x00,0x03,0x14,0x82,0x16,0xf2,0x1b,0xa2,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1c,0x00,0x03,0x1f,0xba,0x1f,0xca,0x26,0x34,0x00,0x03,0x26,0x3e,0x26,0x50,0x26,0x62,0x00,0x01,0x00,0x02,0x04,0x1c,0x05,0xbe,0x00,0x03,0x1b,0x88,0x1e,0x00,0x1f,0xc2,0x00,0x03,0x14,0x5e,0x15,0xd2, 0x1b,0x8e,0x00,0x01,0x00,0x02,0x03,0x48,0x04,0x1b,0x00,0x01,0x00,0x02,0x03,0x5c,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x2e,0x04,0x19,0x00,0x03,0x14,0x4a,0x16,0xa2,0x1b,0x7c,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x1b,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x03,0x16,0x76,0x16,0x82, 0x1b,0x6a,0x00,0x01,0x00,0x02,0x04,0x1b,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x57,0x05,0xbe,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xbe,0x00,0x03,0x1b,0x58,0x1d,0xd8,0x1f,0x6a,0x00,0x01,0x00,0x02,0x03,0x2b,0x03,0x30,0x00,0x01,0x00,0x02,0x03,0x30,0x04,0x19,0x00,0x03,0x13,0xfe,0x15,0x42,0x1b,0x4e,0x00,0x01,0x00,0x02,0x03,0x29, 0x03,0x30,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xb5,0x00,0x03,0x13,0xf2,0x16,0x1a,0x1b,0x44,0x00,0x01,0x00,0x02,0x03,0x29,0x04,0x19,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x03,0x1b,0x2a,0x1d,0x4e,0x1f,0x22,0x00,0x01,0x00,0x02,0x04,0x19, 0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x22,0x00,0x03,0x13,0xbe,0x15,0xf2,0x1b,0x20,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x22,0x00,0x03,0x13,0xba,0x15,0x22,0x1b,0x1e,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x22,0x00,0x03,0x13,0xb6,0x13,0xc2,0x1b,0x1c,0x00,0x01,0x00,0x02,0x04,0x22,0x05,0xb4,0x00,0x03,0x13,0xbe,0x15,0xaa, 0x1b,0x1a,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x23,0x00,0x03,0x13,0xba,0x13,0xc6,0x1b,0x18,0x00,0x01,0x00,0x02,0x03,0xc5,0x04,0x1c,0x00,0x03,0x13,0xc2,0x15,0xa2,0x1b,0x16,0x00,0x01,0x00,0x02,0x03,0xc5,0x04,0x1b,0x00,0x03,0x13,0xbe,0x13,0xca,0x1b,0x14,0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x1c,0x00,0x03,0x15,0x5e,0x15,0x82, 0x1b,0x12,0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x1b,0x00,0x03,0x13,0xb6,0x14,0xbe,0x1b,0x10,0x00,0x01,0x00,0x02,0x03,0x34,0x04,0x1c,0x00,0x03,0x13,0xb2,0x15,0x62,0x1b,0x0e,0x00,0x01,0x00,0x02,0x03,0x34,0x04,0x1b,0x00,0x03,0x13,0xae,0x14,0xaa,0x1b,0x0c,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x1c,0x00,0x03,0x15,0x12,0x15,0x42, 0x1b,0x0a,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x1b,0x00,0x03,0x13,0x9a,0x13,0xa6,0x1b,0x08,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x45,0x00,0x03,0x13,0xa2,0x13,0xae,0x1b,0x06,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x47,0x00,0x03,0x13,0xaa,0x13,0xb6,0x1b,0x04,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x43,0x00,0x03,0x13,0xb2,0x14,0x06, 0x1b,0x02,0x00,0x01,0x00,0x02,0x03,0x30,0x03,0x3a,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x5c,0x00,0x03,0x13,0xa6,0x14,0x12,0x1a,0xf8,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x3a,0x00,0x03,0x13,0xa2,0x13,0xea,0x1a,0xf6,0x00,0x01,0x00,0x02,0x03,0x2b,0x03,0x3a,0x00,0x03,0x13,0x9e,0x14,0xb2,0x1a,0xf4,0x00,0x01,0x00,0x02,0x03,0x3a, 0x04,0x19,0x00,0x03,0x13,0x9a,0x13,0xa6,0x1a,0xf2,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x48,0x00,0x01,0x00,0x02,0x00,0xf4,0x01,0xa2,0x00,0x01,0x00,0x02,0x01,0xdd,0x02,0x21,0x00,0x02,0x24,0x34,0x24,0x46,0x00,0x02,0x24,0x52,0x24,0x64,0x00,0x02,0x24,0x70,0x24,0x82,0x00,0x02,0x24,0x8e,0x24,0xa0,0x00,0x01,0x00,0x02,0x03,0x57, 0x04,0x1c,0x00,0x00,0x00,0x05,0x1d,0xa0,0x1d,0xae,0x24,0xa2,0x24,0xb2,0x24,0xc2,0x00,0x05,0x1c,0x2c,0x13,0xc4,0x1a,0xb2,0x1d,0xb0,0x1d,0xbe,0x00,0x05,0x1d,0xc0,0x1d,0xce,0x24,0xba,0x24,0xca,0x24,0xda,0x00,0x05,0x23,0x1c,0x23,0x2a,0x24,0xde,0x24,0xee,0x24,0xfe,0x00,0x05,0x1d,0xc4,0x1d,0xd2,0x25,0x02,0x25,0x12,0x25,0x22, 0x00,0x05,0x1a,0x8e,0x13,0x34,0x1a,0x9a,0x1d,0xd4,0x1d,0xe2,0x00,0x05,0x1d,0xe4,0x1d,0xf2,0x25,0x1a,0x25,0x2a,0x25,0x3a,0x00,0x05,0x1d,0xf4,0x1b,0x68,0x25,0x3e,0x25,0x4e,0x25,0x5e,0x00,0x05,0x1d,0xf6,0x1b,0x4e,0x25,0x62,0x25,0x72,0x25,0x82,0x00,0x05,0x1a,0x76,0x13,0x1c,0x1b,0x2a,0x1d,0xf8,0x1e,0x06,0x00,0x05,0x1e,0x08, 0x1e,0x16,0x25,0x7a,0x25,0x8a,0x25,0x9a,0x00,0x05,0x1e,0x18,0x1e,0x26,0x25,0x9e,0x25,0xae,0x25,0xbe,0x00,0x05,0x1e,0x28,0x1e,0x36,0x25,0xc2,0x25,0xd2,0x25,0xe2,0x00,0x05,0x1e,0x38,0x1e,0x46,0x25,0xe6,0x25,0xf6,0x26,0x06,0x00,0x04,0x26,0x0a,0x26,0x1a,0x2b,0xfa,0x2c,0x0c,0x00,0x04,0x1e,0x3e,0x1e,0x4c,0x26,0x20,0x26,0x30, 0x00,0x04,0x1a,0x32,0x12,0xcc,0x1a,0xda,0x1e,0x50,0x00,0x04,0x1a,0x34,0x1b,0x7e,0x13,0x9a,0x1e,0x54,0x00,0x04,0x1e,0x58,0x1e,0x66,0x26,0x22,0x26,0x32,0x00,0x04,0x1e,0x6a,0x1e,0x78,0x26,0x38,0x26,0x48,0x00,0x04,0x1a,0x22,0x1a,0x2e,0x12,0xa4,0x1e,0x7c,0x00,0x04,0x1e,0x80,0x1e,0x8e,0x26,0x44,0x26,0x54,0x00,0x04,0x1e,0x92, 0x1e,0xa0,0x26,0x5a,0x26,0x6a,0x00,0x04,0x1e,0xa4,0x1e,0xc0,0x1e,0xb2,0x26,0x70,0x00,0x04,0x1a,0x2a,0x1e,0xb6,0x1a,0x12,0x1e,0xc4,0x00,0x04,0x1a,0x14,0x1a,0x20,0x12,0x96,0x1e,0xc8,0x00,0x04,0x1e,0xcc,0x1e,0xda,0x26,0x62,0x26,0x72,0x00,0x04,0x1e,0xde,0x1e,0xec,0x26,0x78,0x26,0x88,0x00,0x04,0x1b,0x10,0x1a,0x0e,0x13,0x2c, 0x1e,0xf0,0x00,0x04,0x1a,0x10,0x1b,0x12,0x1b,0x2c,0x1e,0xf4,0x00,0x04,0x1a,0x12,0x12,0x34,0x1a,0x1e,0x1e,0xf8,0x00,0x04,0x1e,0xfc,0x21,0xa0,0x26,0x70,0x26,0x80,0x00,0x04,0x26,0x86,0x1f,0x00,0x26,0x96,0x26,0xa6,0x00,0x04,0x26,0xac,0x1f,0x04,0x26,0xbc,0x26,0xcc,0x00,0x04,0x1a,0x02,0x12,0x48,0x1a,0xb0,0x1f,0x08,0x00,0x04, 0x1a,0x04,0x1a,0xb2,0x12,0xe6,0x1f,0x0c,0x00,0x04,0x1a,0x06,0x12,0x04,0x1a,0x12,0x1f,0x10,0x00,0x04,0x1a,0x14,0x12,0xd2,0x1a,0x9e,0x1f,0x14,0x00,0x04,0x1f,0x18,0x1f,0x26,0x26,0xaa,0x26,0xba,0x00,0x04,0x1f,0x2a,0x26,0xc0,0x1a,0x0c,0x26,0xd0,0x00,0x04,0x1f,0x2e,0x21,0xc8,0x26,0xd6,0x26,0xe6,0x00,0x04,0x1f,0x32,0x1f,0x40, 0x26,0xec,0x26,0xfc,0x00,0x04,0x1f,0x44,0x1f,0x52,0x27,0x02,0x27,0x12,0x00,0x04,0x1f,0x56,0x21,0x0e,0x27,0x18,0x27,0x28,0x00,0x04,0x1a,0x28,0x1a,0x34,0x1a,0x40,0x1f,0x5a,0x00,0x04,0x1f,0x5e,0x27,0x24,0x19,0xde,0x27,0x34,0x00,0x04,0x1f,0x62,0x1f,0x70,0x1f,0x7e,0x27,0x3a,0x00,0x04,0x19,0xd8,0x1a,0x16,0x1a,0x22,0x1f,0x82, 0x00,0x04,0x1f,0x86,0x1f,0xda,0x27,0x36,0x27,0x46,0x00,0x04,0x19,0xd0,0x11,0x8e,0x19,0xdc,0x1f,0x8a,0x00,0x03,0x27,0x42,0x29,0x66,0x2a,0xb6,0x00,0x03,0x27,0x4a,0x27,0x5a,0x2a,0xc0,0x00,0x03,0x1f,0x7e,0x20,0xb8,0x27,0x62,0x00,0x03,0x20,0xd8,0x20,0xe6,0x27,0x6a,0x00,0x03,0x1f,0x7c,0x1f,0x8a,0x27,0x72,0x00,0x03,0x1f,0x90, 0x1f,0x9e,0x27,0x7a,0x00,0x03,0x1f,0xa4,0x1f,0xb2,0x27,0x82,0x00,0x03,0x1f,0xb8,0x21,0x2c,0x27,0x8a,0x00,0x03,0x1f,0xbe,0x20,0x88,0x27,0x92,0x00,0x03,0x1f,0xc4,0x1f,0xd2,0x27,0x9a,0x00,0x03,0x1f,0xd8,0x1f,0xe6,0x27,0xa2,0x00,0x03,0x1f,0xec,0x1f,0xfa,0x27,0xaa,0x00,0x03,0x20,0x00,0x20,0x0e,0x27,0xb2,0x00,0x03,0x20,0x14, 0x20,0x22,0x27,0xba,0x00,0x06,0x2a,0x6a,0x2a,0x7a,0x2d,0xde,0x2d,0xf0,0x2e,0x02,0x2e,0x14,0x00,0x06,0x20,0x1a,0x27,0xb4,0x2a,0x7c,0x11,0x12,0x27,0xc2,0x27,0xd0,0x00,0x06,0x20,0x18,0x11,0x10,0x0c,0xfc,0x20,0x24,0x27,0xd0,0x27,0xde,0x00,0x06,0x2a,0x70,0x27,0xde,0x19,0x44,0x2a,0x80,0x2a,0x90,0x2a,0xa0,0x00,0x06,0x20,0x14, 0x19,0x44,0x19,0x50,0x19,0x5c,0x27,0xde,0x27,0xec,0x00,0x05,0x27,0xec,0x28,0x5c,0x28,0x6a,0x2a,0x94,0x2a,0xa4,0x00,0x05,0x29,0x16,0x27,0xee,0x20,0x06,0x2a,0xa8,0x2a,0xb8,0x00,0x05,0x20,0x08,0x11,0x82,0x19,0x4e,0x20,0x7e,0x27,0xf0,0x00,0x05,0x29,0x9c,0x2d,0x0c,0x19,0x72,0x29,0xaa,0x2a,0xb0,0x00,0x05,0x27,0xe6,0x2d,0x00, 0x2d,0xb0,0x19,0x66,0x2a,0xb4,0x00,0x05,0x27,0xe8,0x2a,0xb8,0x27,0xf6,0x2a,0xc8,0x2a,0xd8,0x00,0x05,0x27,0xf8,0x2a,0xdc,0x1f,0xe4,0x2a,0xec,0x2a,0xfc,0x00,0x05,0x2b,0x00,0x2b,0x10,0x2d,0x9e,0x2d,0xb0,0x2d,0xc2,0x00,0x05,0x27,0xee,0x1f,0xda,0x1f,0xe8,0x2b,0x14,0x2b,0x24,0x00,0x05,0x27,0xf0,0x2b,0x28,0x27,0xfe,0x2b,0x38, 0x2b,0x48,0x00,0x05,0x28,0x00,0x2b,0x4c,0x28,0x0e,0x2b,0x5c,0x2b,0x6c,0x00,0x05,0x1f,0xd2,0x10,0x6e,0x18,0xd6,0x1f,0xde,0x28,0x10,0x00,0x05,0x20,0x12,0x18,0xfa,0x1f,0xde,0x19,0x14,0x28,0x12,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x45,0x03,0x57,0x00,0x04,0x2b,0x4e,0x2d,0x82,0x28,0x0a,0x2d,0x94,0x00,0x01,0x00,0x03,0x03,0x2e, 0x03,0x57,0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x57,0x04,0x1c,0x00,0x04,0x27,0xfc,0x2c,0x88,0x1f,0xea,0x2b,0x40,0x00,0x01,0x00,0x03,0x03,0x57,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x04,0x1b,0x04,0x1c,0x05,0xbe,0x00,0x01,0x00,0x03,0x03,0x2b,0x03,0x30,0x04,0x1b,0x00,0x04,0x2b,0x28,0x2d,0x60,0x2b,0x38,0x2d,0x72, 0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x04,0x1b,0x04,0x1c,0x04,0x22,0x00,0x01,0x00,0x03,0x03,0x57,0x04,0x1c,0x05,0xbe,0x00,0x04,0x27,0xba,0x2b,0x20,0x27,0xc8,0x2b,0x30,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x1c,0x05,0xbe,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x1b,0x05,0xbe,0x00,0x01,0x00,0x03, 0x03,0x57,0x04,0x1b,0x05,0xbe,0x00,0x01,0x00,0x03,0x03,0xc5,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x04,0x15,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x34,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x3d,0x04,0x1b,0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x43,0x03,0x5c,0x00,0x02,0x2a,0xe6,0x27,0x7c,0x00,0x02, 0x27,0x84,0x27,0x92,0x00,0x01,0x27,0x9a,0x00,0x07,0x18,0x00,0x2d,0x02,0x2b,0x72,0x10,0x1c,0x17,0xe8,0x2a,0xe6,0x2a,0xf4,0x00,0x07,0x27,0x94,0x2e,0x02,0x27,0xa2,0x27,0xae,0x0f,0x64,0x2a,0xf2,0x2b,0x00,0x00,0x06,0x27,0xaa,0x27,0xb6,0x0f,0x60,0x27,0xc2,0x27,0xce,0x2a,0xfe,0x00,0x06,0x2a,0xfe,0x1e,0xce,0x1e,0xdc,0x2b,0x0c, 0x2b,0x1a,0x2c,0xc4,0x00,0x06,0x27,0xbe,0x17,0xb8,0x27,0xca,0x0f,0x50,0x27,0xd6,0x2b,0x1a,0x00,0x06,0x1e,0xce,0x27,0xd4,0x27,0xe0,0x2b,0x28,0x0f,0xd2,0x2b,0x1a,0x00,0x06,0x27,0xde,0x2b,0x1a,0x2c,0xaa,0x17,0xa8,0x0f,0xc4,0x2b,0x28,0x00,0x04,0x0f,0x32,0x0f,0x38,0x0f,0x3e,0x0f,0x44,0x00,0x04,0x0f,0x40,0x0f,0x46,0x0f,0x4c, 0x0f,0x52,0x00,0x04,0x0f,0x4e,0x0f,0x54,0x0f,0x5a,0x0f,0x60,0x00,0x04,0x0f,0x5c,0x0f,0x62,0x0f,0x68,0x0f,0x6e,0x00,0x01,0x01,0x4a,0x00,0x01,0x00,0x01,0x00,0x08,0x17,0x76,0x1e,0x8e,0x2a,0xf8,0x17,0x90,0x2b,0x48,0x2b,0x04,0x2c,0x7c,0x2c,0x8a,0x00,0x08,0x2b,0x5a,0x0f,0x8c,0x2b,0x66,0x2a,0xfe,0x2b,0x4e,0x0f,0x5c,0x2c,0x86, 0x2c,0x94,0x00,0x08,0x2c,0x90,0x2a,0xf8,0x27,0x88,0x17,0x5e,0x27,0x96,0x2d,0x6a,0x2d,0x7a,0x2d,0x8a,0x00,0x07,0x2b,0x1e,0x2a,0xf6,0x2b,0x36,0x0f,0x5c,0x0f,0x68,0x0f,0x44,0x2c,0x8c,0x00,0x07,0x2c,0x8a,0x2c,0x98,0x2d,0xd0,0x2a,0xf2,0x1e,0x54,0x2d,0x78,0x2d,0x88,0x00,0x01,0x00,0x04,0x00,0x84,0x00,0x8c,0x01,0x47,0x01,0x4f, 0x00,0x01,0x00,0x04,0x00,0x01,0x00,0x60,0x00,0xbd,0x01,0x22,0x00,0x01,0x00,0x04,0x03,0x90,0x03,0x91,0x06,0x23,0x06,0x24,0x00,0x01,0x00,0x04,0x01,0x0d,0x01,0x0e,0x01,0x0f,0x02,0x36,0x00,0x01,0x00,0x04,0x05,0xb5,0x06,0x0c,0x06,0x0d,0x06,0x0e,0x00,0x01,0x00,0x01,0x03,0x20,0x00,0x08,0x2c,0x54,0x16,0xf8,0x2c,0x60,0x2c,0x6c, 0x2c,0x78,0x2c,0x84,0x2a,0xb0,0x2d,0x46,0x00,0x08,0x2c,0x7e,0x2c,0x8a,0x2c,0x96,0x2c,0xa2,0x2c,0xae,0x2c,0xba,0x0a,0x20,0x2d,0x42,0x00,0x08,0x2c,0xb4,0x0e,0xca,0x2d,0x6c,0x2d,0x7c,0x2d,0x8c,0x2d,0x9c,0x2d,0x3e,0x2d,0x4c,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0xbd,0x00,0x01,0x00,0x02,0x00,0x60,0x01,0x22,0x00,0x09,0x2a,0x76, 0x2a,0x82,0x2a,0x8e,0x0e,0xb4,0x2d,0xa6,0x2d,0x8a,0x2a,0x9a,0x0e,0xc0,0x2d,0x98,0x00,0x01,0x00,0x05,0x03,0xc3,0x03,0xc5,0x06,0x1c,0x06,0x42,0x06,0x43,0x00,0x01,0x00,0x05,0x02,0xdc,0x02,0xec,0x02,0xf6,0x03,0x00,0x03,0x0a,0x00,0x01,0x00,0x05,0x02,0xd9,0x02,0xe9,0x02,0xf3,0x02,0xfd,0x03,0x07,0x00,0x02,0x00,0x01,0x02,0xee, 0x02,0xf7,0x00,0x00,0x00,0x01,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x3e,0x00,0x02,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x01,0x06,0xce,0x06,0xce,0x00,0x02,0x00,0x02,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x01,0x00,0x01,0x00,0x06,0x01,0x13,0x01,0x14,0x01,0x16,0x01,0x17,0x01,0x18,0x01,0x19, 0x00,0x09,0x2d,0x32,0x2d,0x3e,0x2d,0x6e,0x2d,0x8a,0x2d,0x9a,0x2d,0x4a,0x2d,0x56,0x2d,0x62,0x2d,0x7c,0x00,0x01,0x00,0x05,0x03,0x29,0x03,0x32,0x03,0x33,0x03,0xbe,0x05,0xc6,0x00,0x02,0x00,0x02,0x06,0x68,0x06,0x6c,0x00,0x00,0x06,0x6e,0x06,0x76,0x00,0x05,0x00,0x02,0x00,0x02,0x00,0xa2,0x00,0xa6,0x00,0x00,0x01,0x6a,0x01,0x6e, 0x00,0x05,0x00,0x02,0x00,0x02,0x06,0x77,0x06,0x79,0x00,0x00,0x06,0x7b,0x06,0x7f,0x00,0x03,0x00,0x01,0x00,0x08,0x00,0xff,0x01,0x07,0x01,0x0b,0x01,0x0d,0x01,0x90,0x02,0x34,0x02,0x36,0x02,0x49,0x00,0x02,0x00,0x02,0x02,0xd4,0x02,0xdd,0x00,0x00,0x04,0x15,0x04,0x15,0x00,0x0a,0x00,0x02,0x00,0x05,0x02,0xd4,0x02,0xde,0x00,0x01, 0x03,0x57,0x03,0x57,0x00,0x03,0x04,0x1b,0x04,0x1b,0x00,0x04,0x04,0x1c,0x04,0x1c,0x00,0x02,0x05,0xbe,0x05,0xbe,0x00,0x05,0x00,0x02,0x00,0x06,0x00,0x01,0x00,0xbc,0x00,0x01,0x01,0xc8,0x01,0xfe,0x00,0x01,0x02,0x03,0x02,0x03,0x00,0x01,0x02,0x05,0x02,0x0a,0x00,0x01,0x02,0x51,0x02,0x74,0x00,0x01,0x02,0xa0,0x02,0xb9,0x00,0x01, 0x00,0x02,0x00,0x06,0x06,0x68,0x06,0x6c,0x00,0x01,0x06,0x6e,0x06,0x78,0x00,0x01,0x06,0x7a,0x06,0x7c,0x00,0x01,0x06,0x80,0x06,0x8a,0x00,0x01,0x06,0xb0,0x06,0xb0,0x00,0x01,0x06,0xb4,0x06,0xbb,0x00,0x01,0x00,0x02,0x00,0x06,0x06,0x8e,0x06,0x9a,0x00,0x01,0x06,0x9c,0x06,0x9e,0x00,0x01,0x06,0xa0,0x06,0xa2,0x00,0x01,0x06,0xa5, 0x06,0xaf,0x00,0x01,0x06,0xb1,0x06,0xb1,0x00,0x01,0x06,0xbc,0x06,0xc3,0x00,0x01,0x00,0x02,0x00,0x06,0x06,0x68,0x06,0x6c,0x00,0x00,0x06,0x6e,0x06,0x78,0x00,0x05,0x06,0x7a,0x06,0x7c,0x00,0x10,0x06,0x80,0x06,0x8a,0x00,0x13,0x06,0xb0,0x06,0xb0,0x00,0x1e,0x06,0xb4,0x06,0xbb,0x00,0x1f,0x00,0x02,0x00,0x06,0x00,0x01,0x00,0xbc, 0x00,0x00,0x01,0xc8,0x01,0xfe,0x00,0xbc,0x02,0x03,0x02,0x03,0x00,0xf3,0x02,0x05,0x02,0x0a,0x00,0xf4,0x02,0x51,0x02,0x74,0x00,0xfa,0x02,0xa0,0x02,0xb9,0x01,0x1e,0x00,0x02,0x00,0x07,0x00,0x01,0x00,0xbc,0x00,0x00,0x01,0xc8,0x01,0xfe,0x00,0xbc,0x02,0x03,0x02,0x03,0x00,0xf3,0x02,0x05,0x02,0x0a,0x00,0xf4,0x02,0x51,0x02,0x74, 0x00,0xfa,0x02,0xa0,0x02,0xb9,0x01,0x1e,0x02,0xd4,0x02,0xde,0x01,0x38,0x00,0x02,0x00,0x03,0x01,0x51,0x01,0x53,0x00,0x00,0x01,0x55,0x01,0x56,0x00,0x03,0x01,0x5b,0x01,0x68,0x00,0x05,0x00,0x01,0x00,0x0f,0x01,0x70,0x01,0x71,0x01,0x72,0x01,0x73,0x01,0x74,0x01,0x75,0x01,0x76,0x01,0x77,0x01,0x78,0x01,0xdf,0x01,0xe0,0x02,0x23, 0x02,0x24,0x02,0x77,0x02,0x7f,0x00,0x01,0x00,0x0f,0x02,0xd6,0x02,0xda,0x02,0xdd,0x02,0xe6,0x02,0xea,0x02,0xed,0x02,0xf0,0x02,0xf4,0x02,0xf7,0x02,0xfa,0x02,0xfe,0x03,0x01,0x03,0x04,0x03,0x08,0x03,0x0b,0x00,0x01,0x00,0x10,0x00,0x51,0x00,0x52,0x01,0x10,0x01,0x11,0x01,0x12,0x01,0xd1,0x01,0xd5,0x01,0xd6,0x01,0xf8,0x02,0x15, 0x02,0x19,0x02,0x1a,0x02,0x3c,0x02,0x5a,0x02,0x72,0x02,0x7e,0x00,0x02,0x03,0x41,0x03,0x42,0x00,0x02,0x03,0xae,0x06,0xce,0x00,0x02,0x03,0x9a,0x03,0xa5,0x00,0x02,0x03,0x9c,0x06,0xce,0x00,0x02,0x06,0x42,0x06,0xce,0x00,0x02,0x06,0x59,0x06,0xce,0x00,0x03,0x02,0xe5,0x02,0xf9,0x03,0x03,0x00,0x03,0x02,0xe6,0x02,0xfa,0x03,0x04, 0x00,0x03,0x02,0xe7,0x02,0xfb,0x03,0x05,0x00,0x03,0x02,0xe8,0x02,0xfc,0x03,0x06,0x00,0x03,0x02,0xe9,0x02,0xfd,0x03,0x07,0x00,0x03,0x02,0xea,0x02,0xfe,0x03,0x08,0x00,0x03,0x02,0xeb,0x02,0xff,0x03,0x09,0x00,0x03,0x02,0xec,0x03,0x00,0x03,0x0a,0x00,0x03,0x02,0xed,0x03,0x01,0x03,0x0b,0x00,0x03,0x03,0x8c,0x03,0x8d,0x06,0xce, 0x00,0x03,0x03,0x76,0x03,0x9b,0x06,0xce,0x00,0x03,0x06,0x12,0x06,0x2c,0x06,0xce,0x00,0x03,0x06,0x0c,0x06,0x0d,0x06,0xce,0x00,0x04,0x02,0xde,0x02,0xe4,0x02,0xf8,0x03,0x02,0x00,0x04,0x03,0x7f,0x03,0x80,0x03,0x92,0x06,0xce,0x00,0x04,0x03,0x79,0x03,0x8e,0x03,0x9e,0x06,0xce,0x00,0x05,0x03,0x97,0x03,0xa6,0x03,0xa7,0x06,0x3c, 0x06,0xce,0x00,0x05,0x03,0x7e,0x03,0xa0,0x03,0xa1,0x03,0xa2,0x06,0xce,0x00,0x05,0x03,0x6e,0x03,0x7b,0x03,0x8f,0x06,0x11,0x06,0xce,0x00,0x05,0x03,0xa4,0x03,0xb0,0x03,0xb1,0x06,0x0b,0x06,0xce,0x00,0x05,0x04,0x3b,0x06,0x1d,0x06,0x1e,0x06,0x45,0x06,0xce,0x00,0x06,0x03,0x82,0x03,0x87,0x03,0x94,0x03,0x95,0x03,0x9f,0x06,0xce, 0x00,0x06,0x03,0x75,0x06,0x52,0x06,0x53,0x06,0x55,0x06,0x5b,0x06,0xce,0x00,0x07,0x03,0x20,0x03,0x99,0x03,0xab,0x03,0xad,0x03,0xaf,0x06,0x56,0x06,0xce,0x00,0x09,0x03,0x40,0x03,0x84,0x03,0x85,0x03,0x93,0x03,0x9d,0x06,0x20,0x06,0x2d,0x06,0x39,0x06,0xce,0x00,0x0a,0x03,0x70,0x03,0x7a,0x03,0x7c,0x06,0x13,0x06,0x36,0x06,0x3e, 0x06,0x3f,0x06,0x40,0x06,0x48,0x06,0xce,0x00,0x0c,0x03,0x73,0x03,0x74,0x03,0x7d,0x03,0x81,0x03,0x8b,0x06,0x28,0x06,0x38,0x06,0x3a,0x06,0x4c,0x06,0x4e,0x06,0x51,0x06,0xce,0x00,0x0f,0x03,0x6c,0x03,0x6d,0x03,0x77,0x03,0x78,0x06,0x0f,0x06,0x14,0x06,0x2a,0x06,0x31,0x06,0x34,0x06,0x35,0x06,0x3b,0x06,0x44,0x06,0x4f,0x06,0x58, 0x06,0xce,0x00,0x19,0x03,0x83,0x03,0x86,0x03,0x89,0x03,0x90,0x03,0x91,0x03,0x96,0x03,0xa3,0x03,0xa8,0x03,0xa9,0x03,0xac,0x06,0x0e,0x06,0x17,0x06,0x19,0x06,0x21,0x06,0x22,0x06,0x23,0x06,0x24,0x06,0x29,0x06,0x2e,0x06,0x32,0x06,0x47,0x06,0x49,0x06,0x50,0x06,0x5d,0x06,0xce,0x00,0x02,0x00,0x08,0x03,0x2b,0x03,0x2b,0x00,0x00, 0x03,0x42,0x03,0x42,0x00,0x01,0x06,0x68,0x06,0x6c,0x00,0x02,0x06,0x6e,0x06,0x78,0x00,0x07,0x06,0x7a,0x06,0x7c,0x00,0x12,0x06,0x80,0x06,0x8a,0x00,0x15,0x06,0xb0,0x06,0xb0,0x00,0x20,0x06,0xb4,0x06,0xbb,0x00,0x21,0x00,0x22,0x03,0x6f,0x03,0x71,0x03,0x72,0x03,0x88,0x03,0x8a,0x03,0x98,0x03,0xaa,0x06,0x10,0x06,0x16,0x06,0x18, 0x06,0x1a,0x06,0x1b,0x06,0x1c,0x06,0x1f,0x06,0x25,0x06,0x26,0x06,0x27,0x06,0x2b,0x06,0x2f,0x06,0x30,0x06,0x33,0x06,0x37,0x06,0x3d,0x06,0x41,0x06,0x43,0x06,0x46,0x06,0x4a,0x06,0x4b,0x06,0x4d,0x06,0x54,0x06,0x57,0x06,0x5a,0x06,0x5c,0x06,0xce,0x00,0x02,0x00,0x0b,0x00,0xa2,0x00,0xa6,0x00,0x00,0x00,0xf4,0x00,0xf4,0x00,0x05, 0x01,0x13,0x01,0x14,0x00,0x06,0x01,0x16,0x01,0x1a,0x00,0x08,0x01,0x4c,0x01,0x50,0x00,0x0d,0x01,0x6a,0x01,0x6e,0x00,0x12,0x01,0x70,0x01,0x78,0x00,0x17,0x01,0xdf,0x01,0xe0,0x00,0x20,0x02,0x23,0x02,0x24,0x00,0x22,0x02,0x77,0x02,0x77,0x00,0x24,0x02,0x7f,0x02,0x7f,0x00,0x25,0x00,0x01,0x00,0x24,0x02,0xd4,0x02,0xd5,0x02,0xd6, 0x02,0xd7,0x02,0xd8,0x02,0xd9,0x02,0xda,0x02,0xdb,0x02,0xdc,0x02,0xdd,0x03,0x29,0x03,0x2b,0x03,0x2c,0x03,0x2e,0x03,0x30,0x03,0x32,0x03,0x34,0x03,0x3a,0x03,0x3d,0x03,0x3e,0x03,0x43,0x03,0x45,0x03,0x46,0x03,0x47,0x03,0x48,0x03,0x57,0x03,0x5c,0x03,0xc5,0x04,0x15,0x04,0x19,0x04,0x1b,0x04,0x1c,0x04,0x22,0x05,0xb4,0x05,0xb5, 0x05,0xbe,0x00,0x02,0x00,0x0e,0x00,0xff,0x00,0xff,0x00,0x00,0x01,0x07,0x01,0x07,0x00,0x01,0x01,0x0b,0x01,0x0b,0x00,0x02,0x01,0x0d,0x01,0x0d,0x00,0x03,0x01,0x90,0x01,0x90,0x00,0x04,0x02,0x34,0x02,0x34,0x00,0x05,0x02,0x36,0x02,0x36,0x00,0x06,0x02,0x49,0x02,0x49,0x00,0x07,0x06,0x68,0x06,0x6c,0x00,0x08,0x06,0x6e,0x06,0x78, 0x00,0x0d,0x06,0x7a,0x06,0x7c,0x00,0x18,0x06,0x80,0x06,0x8a,0x00,0x1b,0x06,0xb0,0x06,0xb0,0x00,0x26,0x06,0xb4,0x06,0xbb,0x00,0x27,0x00,0x02,0x00,0x13,0x00,0x51,0x00,0x52,0x00,0x00,0x00,0xf4,0x00,0xf4,0x00,0x02,0x01,0x10,0x01,0x14,0x00,0x03,0x01,0x16,0x01,0x19,0x00,0x08,0x01,0x40,0x01,0x43,0x00,0x0c,0x01,0x51,0x01,0x53, 0x00,0x10,0x01,0x55,0x01,0x56,0x00,0x13,0x01,0x5b,0x01,0x68,0x00,0x15,0x01,0x70,0x01,0x78,0x00,0x23,0x01,0xd1,0x01,0xd1,0x00,0x2c,0x01,0xd5,0x01,0xd6,0x00,0x2d,0x01,0xdf,0x01,0xe0,0x00,0x2f,0x01,0xf8,0x01,0xf8,0x00,0x31,0x02,0x15,0x02,0x15,0x00,0x32,0x02,0x19,0x02,0x1a,0x00,0x33,0x02,0x23,0x02,0x24,0x00,0x35,0x02,0x3c, 0x02,0x3c,0x00,0x37,0x02,0x77,0x02,0x77,0x00,0x38,0x02,0x7e,0x02,0x7f,0x00,0x39,0x00,0x02,0x00,0x13,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x01,0x00,0x84,0x00,0x84,0x00,0x02,0x00,0x8c,0x00,0x8c,0x00,0x03,0x00,0xbd,0x00,0xbd,0x00,0x04,0x00,0xff,0x00,0xff,0x00,0x05,0x01,0x22,0x01,0x22,0x00,0x06,0x01,0x47, 0x01,0x47,0x00,0x07,0x01,0x4a,0x01,0x4a,0x00,0x08,0x01,0x4f,0x01,0x4f,0x00,0x09,0x02,0xf8,0x03,0x01,0x00,0x0a,0x03,0x42,0x03,0x42,0x00,0x14,0x04,0x23,0x04,0x23,0x00,0x15,0x06,0x68,0x06,0x6c,0x00,0x16,0x06,0x6e,0x06,0x78,0x00,0x1b,0x06,0x7a,0x06,0x7c,0x00,0x26,0x06,0x80,0x06,0x8a,0x00,0x29,0x06,0xb0,0x06,0xb0,0x00,0x34, 0x06,0xb4,0x06,0xbb,0x00,0x35,0x05,0xc3,0x00,0x03,0x01,0x22,0x03,0x29,0x00,0x01,0x00,0x01,0x00,0x5a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1d,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2d,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x31,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x33,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x35,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x42,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x73,0x00,0x01,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x8f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x91,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x99,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, 0x00,0xa2,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xa4,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xa6,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xa8,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xaa,0x00,0x01,0x06,0xce,0x00,0x01, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xb5,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc0,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xcc,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xce,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xd0, 0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe0,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xee,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xf6,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xf8,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00, 0x00,0x01,0x00,0x00,0x01,0x0e,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x10,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x12,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x17,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x1d,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3d,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x42,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x49,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x5c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x01,0x61,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x63,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x65,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x67,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x6b,0x00,0x01,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x6d,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x71,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x73,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x77,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, 0x01,0x79,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x7d,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x7f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x81,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x83,0x00,0x01,0x06,0xce,0x00,0x01, 0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x85,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x87,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x89,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x8b,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x8d, 0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x8f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x93,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x48,0x03,0x48,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x17,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x44,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6b,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01, 0x00,0x00,0x00,0x77,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x81,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x96,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x00,0x00,0xb2,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01, 0x00,0x00,0x00,0xbd,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xc9,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe4,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xeb,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0xf0,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xf3,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x22,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x25,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01, 0x00,0x00,0x01,0x28,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x2e,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x34,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x37,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x01,0x3a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x3f,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x5e,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x01,0x00,0x00,0x00,0x31, 0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x01,0x03,0x45,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x45,0x03,0x57,0x00,0x00,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x3a,0x00,0x00,0x00,0x01,0x04,0x15, 0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x00,0x00,0x01,0x03,0x2c,0x00,0x01,0x00,0x01,0x03,0x2c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2c,0x03,0x2c,0x00,0x00,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x00,0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x01,0x05,0xb5,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xb5, 0x05,0xb5,0x00,0x00,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x00,0x00,0x01,0x05,0xb4,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x03,0x46,0x00,0x00,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x00, 0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x01,0x03,0x29,0x00,0x00,0x00,0x01,0x03,0x29, 0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x01,0x05,0xb4,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xb4,0x05,0xb4,0x00,0x00,0x00,0x01,0x04,0x23,0x00,0x01,0x00,0x01, 0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x03,0xc5,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0xc5,0x03,0xc5,0x00,0x00,0x00,0x01,0x03,0xc5,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x15,0x00,0x00, 0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x45,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x45,0x03,0x45,0x00,0x00,0x00,0x01,0x03,0x3a, 0x00,0x01,0x00,0x01,0x03,0x47,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x47,0x03,0x47,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x43,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x43,0x03,0x43,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01, 0x03,0x2e,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x48,0x00,0x01,0x00,0x01,0x03,0x3a,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x3a,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x29,0x03,0x29,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x30,0x03,0x30,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x03,0x2b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x5c,0x03,0x5c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x2e,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01, 0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x03,0x3d,0x00,0x00,0x06,0xb8,0x00,0x02,0x06,0x6b,0x06,0xb9,0x00,0x02,0x06,0x6a,0x06,0xba,0x00,0x02,0x06,0x74,0x06,0xbb,0x00,0x02,0x06,0x72,0x06,0xb4,0x00,0x02,0x06,0x6b,0x06,0xb5, 0x00,0x02,0x06,0x6a,0x06,0xb6,0x00,0x02,0x06,0x74,0x06,0xb7,0x00,0x02,0x06,0x72,0x06,0xc0,0x00,0x02,0x06,0x91,0x06,0xc1,0x00,0x02,0x06,0x90,0x06,0xc2,0x00,0x02,0x06,0x99,0x06,0xc3,0x00,0x02,0x06,0x97,0x06,0xbc,0x00,0x02,0x06,0x91,0x06,0xbd,0x00,0x02,0x06,0x90,0x06,0xbe,0x00,0x02,0x06,0x99,0x06,0xbf,0x00,0x02,0x06,0x97, 0x00,0x01,0x00,0x04,0x06,0x6e,0x06,0x70,0x06,0x93,0x06,0x95,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01, 0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe7,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x00,0x00,0x15,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x00,0x00,0x4d,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x8c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x8d,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x93,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x94,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xad,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xae,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xba,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xbb,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x01,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x31,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x32,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x4b,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x4c,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x4e,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x4f,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x00,0x01,0x5a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x84,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x84,0x00,0x01,0x06,0xce,0x00,0x01, 0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x86,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x86,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xb0,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xb0,0x00,0x01,0x06,0xce,0x00,0x01, 0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xe2,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe2,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x2b,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x47,0x00,0x01,0x06,0xce,0x00,0x01, 0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x47,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x01,0x51,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x51,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x01,0x53,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x53,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x55,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x55,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x69,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x69,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x6f,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x6f,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x75,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x75,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x7b,0x00,0x02,0x06,0xce,0x06,0xce, 0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x7b,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x91,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x00,0x01,0x91,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x45, 0x00,0x01,0x00,0x00,0x00,0x09,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x00,0x00,0x22,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x00,0x00,0x56,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xd5,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2c,0x00,0x01,0x00,0x00,0x00,0xd6,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x01,0x07,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x00,0x01,0x08,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x14,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x00,0x01,0x15,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x1f,0x00,0x00,0x00,0x01, 0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x00,0x01,0x20,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x2e,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x2e,0x03,0x2e,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x00, 0x00,0x2d,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x35,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x73,0x00,0x01,0x03,0x57,0x00,0x01, 0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xce,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xee,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x00,0x01,0x12,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x1d,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x61,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x57, 0x00,0x01,0x00,0x00,0x01,0x63,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xb4,0x00,0x01,0x00,0x00,0x01,0x65,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x67,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0xc5,0x00,0x01,0x00,0x00,0x01,0x6b,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x6d,0x00,0x00, 0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x00,0x01,0x71,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x73,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x00,0x01,0x77,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x79,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x01, 0x00,0x00,0x01,0x7d,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x7f,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x00,0x01,0x81,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x00,0x01,0x83,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x00,0x01,0x85,0x00,0x00,0x00,0x01, 0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x00,0x01,0x87,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x00,0x01,0x8b,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x00,0x01,0x8d,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x8f,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x00, 0x01,0x93,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x01,0x03,0x29,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x29,0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x01, 0x03,0x3d,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01, 0x00,0x01,0x05,0xbe,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x30,0x04,0x1b,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01,0x03,0x57, 0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x00,0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1b,0x04,0x1b,0x04,0x1b,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1c,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x5c,0x03,0x43,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x57,0x03,0x57,0x03,0x57,0x00,0x00, 0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x3d, 0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x03,0x06,0xce,0x06,0xce, 0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x11,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x1a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00, 0x00,0x68,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x70,0x00,0x01,0x01,0x13,0x00,0x01,0x00,0x01,0x01,0x13,0x00,0x01,0x00,0x00,0x01,0xa3,0x00,0x01,0x00,0x53,0x00,0x01,0x00,0x01,0x00,0x53,0x00,0x01,0x00,0x00,0x01,0xa4,0x00,0x01,0x01,0x7e,0x00,0x01,0x00,0x01,0x01,0x7e,0x00,0x01, 0x00,0x00,0x01,0xa5,0x00,0x01,0x01,0x93,0x00,0x01,0x00,0x01,0x01,0x93,0x00,0x01,0x00,0x00,0x01,0xa6,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x03,0x03,0x45,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x03,0x03,0x57,0x03,0x45,0x03,0x45,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x2e,0x00,0x01, 0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x05,0xbe,0x05,0xbe,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x01, 0x00,0x00,0x00,0x93,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x4b,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x3a,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x3a,0x03,0x3a,0x00,0x00, 0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x00,0x00,0x3c,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x02,0x03,0x3d,0x03,0x3d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3d,0x03,0x3d,0x03,0x3d,0x00,0x00,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x02, 0x04,0x15,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x15,0x04,0x15,0x04,0x15,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x02,0x03,0x29,0x03,0x29,0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x03,0x03,0x29,0x03,0x29,0x03,0x29,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01, 0x00,0x00,0x00,0xd3,0x00,0x01,0x03,0x2c,0x00,0x01,0x00,0x02,0x03,0x2c,0x03,0x2c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2c,0x03,0x2c,0x03,0x2c,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x02,0x03,0x2b,0x03,0x2b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2b,0x03,0x2b,0x03,0x2b,0x00,0x00,0x00,0x01,0x03,0x30, 0x00,0x01,0x00,0x02,0x03,0x30,0x03,0x30,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x30,0x03,0x30,0x03,0x30,0x00,0x00,0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x02,0x05,0xb5,0x05,0xb5,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xb5,0x05,0xb5,0x05,0xb5,0x00,0x00,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x02,0x03,0x46,0x03,0x46, 0x00,0x00,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x46,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0x42,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x02,0x03,0x29,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03, 0x03,0x29,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x1c,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1c,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x00,0x00,0x75,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x1c,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2b,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1c,0x04,0x22,0x04,0x22,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe, 0x05,0xbe,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x8f,0x00,0x00,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1c,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01, 0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x02,0x05,0xbe,0x03,0x5c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x03,0x5c,0x03,0x5c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xcc,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01, 0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x00,0x00,0xe0,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01, 0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0xf6,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x00,0x01,0x0e,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x17,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1c, 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x57,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03, 0x04,0x1b,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x02,0x04,0x1b,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x1b,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x00,0x01,0x42, 0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x22,0x04,0x22,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x22,0x04,0x22,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x22, 0x00,0x01,0x00,0x00,0x01,0x5c,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x5c,0x00,0x01,0x00,0x00,0x01,0x89,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x2b,0x00,0x01,0x00,0x02,0x03,0x30,0x04,0x1b,0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x03,0x03,0x30,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x22,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x57,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x57,0x05,0xbe, 0x05,0xbe,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0xc5,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0xc5,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c, 0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x15,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x34,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x34,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x1b, 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3d,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x02,0x03,0x5c,0x03,0x43,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x5c,0x03,0x43,0x03,0x43,0x00,0x00,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x01, 0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x03,0x48,0x00,0x00,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x57,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2b,0x04,0x19, 0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1c,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01, 0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x34,0x03,0x34,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19, 0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x45,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0e,0x00,0x02,0x06,0xce, 0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x88,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x88,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01, 0x00,0x00,0x00,0x89,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x05,0xbe,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0x8a,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1a,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x1b,0x00,0x03,0x06,0xce,0x06,0xce, 0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x69,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x70,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00, 0x00,0x71,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x2b,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x2c,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x24,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x3a, 0x00,0x01,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x3a,0x00,0x01,0x00,0x00,0x00,0x26,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x03,0x3d, 0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x51,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x00,0x00,0x52,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x34,0x00,0x01,0x00,0x00,0x00,0x53,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x58,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x15,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x29, 0x00,0x01,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x29,0x03,0x29,0x00,0x01,0x00,0x00,0x00,0x63,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7d,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c, 0x00,0x01,0x00,0x00,0x00,0x7f,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x9e,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x9f,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xa0,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0xd8,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x2c,0x00,0x01,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2c,0x03,0x2c,0x00,0x01,0x00,0x00,0x00,0xda,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xdc,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x2b, 0x00,0x01,0x00,0x00,0x00,0xdd,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x03,0x2b,0x00,0x01,0x00,0x00,0x00,0xde,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x0a,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x00,0x01,0x0b,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x30,0x03,0x30, 0x00,0x01,0x00,0x00,0x01,0x0c,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x19,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x05,0xb5,0x00,0x01,0x00,0x00,0x01,0x1a,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xb5,0x05,0xb5,0x00,0x01,0x00,0x00,0x01,0x1b,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x03,0x03,0x57, 0x03,0x46,0x03,0x46,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x03,0x57,0x03,0x46,0x03,0x46,0x03,0x46,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2e,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x18,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1c, 0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x29,0x04,0x1c,0x00,0x01,0x00,0x00,0x00,0x66,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x6c,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00, 0x00,0x01,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x1c,0x00,0x01,0x00,0x00,0x00,0x78,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x00,0x00,0x81,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x22,0x00,0x01,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x05,0xbe, 0x00,0x01,0x00,0x00,0x00,0x8c,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xaa,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xab,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x03,0x5c, 0x00,0x01,0x00,0x00,0x00,0xb3,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xe5,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x03,0x05,0xbe,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57, 0x00,0x01,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0xf1,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x03,0x05,0xbe,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xf3,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x19, 0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x25,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x26,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x1b, 0x00,0x01,0x00,0x00,0x01,0x31,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x34,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x35,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x37,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x19, 0x00,0x01,0x00,0x00,0x01,0x38,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x3a,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x3b,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3f,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b, 0x00,0x01,0x00,0x00,0x01,0x40,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x4e,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x22,0x00,0x01,0x00,0x00,0x01,0x59,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b, 0x00,0x01,0x00,0x00,0x01,0x5e,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x5f,0x00,0x01,0x03,0x45,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x03,0x3a,0x03,0x57, 0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x86,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x30,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x22,0x04,0x1b, 0x00,0x01,0x00,0x00,0x01,0x47,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x05,0xbe,0x00,0x01,0x00,0x00,0x01,0x51,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x55,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x57,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0xc5,0x04,0x1b, 0x00,0x01,0x00,0x00,0x01,0x69,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x15,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x6f,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x34,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x75,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x7b,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x5c,0x03,0x43, 0x00,0x01,0x00,0x00,0x01,0x91,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xb7,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x00,0x00,0xb8,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xfa,0x00,0x00, 0x00,0x01,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x00,0x00,0xfb,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x44,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x22,0x00,0x01,0x00,0x00,0x01,0x45,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x02,0x03,0x3d, 0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xa2,0x00,0x01,0x03,0x2e,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x03,0x2e,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01, 0x00,0x03,0x03,0x2e,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x00,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3d,0x04,0x19,0x04,0x19, 0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x3d,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x49,0x00,0x00,0x00,0x01,0x00,0x04, 0x03,0x2e,0x03,0x57,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19,0x05,0xbe,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00, 0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x98,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x99,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6e,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01, 0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x3d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x29, 0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x00,0x00,0x01,0x03,0x29,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xbe,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01, 0x03,0x2e,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x46,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x57, 0x03,0x46,0x03,0x46,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x70,0x00,0x01,0x03,0x3a,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x3a,0x03,0x3a,0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x04,0x03,0x3a,0x03,0x3a,0x03,0x3a,0x03,0x3a,0x00,0x00,0x00,0x03,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x03,0x2e,0x00,0x00,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x03,0x03,0x57,0x03,0x57,0x04,0x1b,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x03,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x04,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x01,0x05,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0x45,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x96,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x57,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x97,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xad,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xba,0x00,0x02, 0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x03,0x2e,0x04,0x19,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xbd,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2e,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xbe,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x00,0x00,0x02, 0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x2b,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xca,0x00,0x01,0x05,0xbe,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x05,0xbe,0x05,0xbe,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x01, 0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xec,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x22,0x00,0x00, 0x00,0x01,0x00,0x02,0x03,0x3d,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x23,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1c,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x28,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1c,0x00,0x01,0x00,0x00,0x01,0x29,0x00,0x01, 0x04,0x1c,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x57,0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x84,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x04,0x19,0x04,0x19,0x04,0x1b,0x04,0x1b,0x00,0x00,0x00,0x02, 0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xbe,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x05,0xbe,0x00,0x01,0x00,0x00,0x01,0x53,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x05,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x01, 0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xc3,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x00,0x00,0x4a,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x02,0x03,0x34,0x03,0x34, 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x34,0x03,0x34,0x03,0x3d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x34,0x03,0x34,0x03,0x29,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xa8,0x00,0x02,0x03,0x30,0x03,0x43, 0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xb5,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x22,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x03,0x57,0x00,0x00,0x00,0x02,0x03,0x30,0x03,0x43, 0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x57,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01, 0x04,0x19,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1b,0x04,0x19,0x00,0x00,0x00,0x03,0x06,0xce,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x01,0x03,0x3a, 0x00,0x01,0x00,0x00,0x00,0x29,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x03,0x3a,0x03,0x3a,0x00,0x01,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x3a,0x03,0x3a,0x03,0x3a,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x03,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x02,0x06,0xce, 0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xe7,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x02,0x05,0xbe,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x01,0x00,0x03,0x05,0xbe,0x05,0xbe,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xe9,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x57, 0x03,0x57,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x03,0x2e,0x03,0x57,0x03,0x57,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x2b,0x00,0x00,0x00,0x01,0x00,0x02, 0x03,0x34,0x03,0x34,0x00,0x01,0x00,0x00,0x00,0x4c,0x00,0x03,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x00,0x7b,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x9b,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x9c,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0x99,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x04,0x19, 0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x47,0x00,0x01,0x00,0x01,0x04,0x1c,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x03,0x34,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x1c,0x03,0xc5,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02, 0x04,0x1c,0x03,0x3d,0x00,0x00,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x04,0x15,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x03,0x34,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x03,0xc5,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x03,0x3d,0x00,0x01,0x00,0x01,0x03,0x48, 0x00,0x00,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x00,0x00,0x01,0x03,0x30,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x00,0x00,0x04,0x03,0x2e,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x03,0x57,0x00,0x00,0x00,0x02,0x06,0xce,0x06,0xce,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc5,0x00,0x01,0x06,0xce, 0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x19,0x00,0x01,0x00,0x00,0x00,0xc7,0x00,0x01,0x06,0xce,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x2e,0x00,0x00,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x01,0x00,0x00,0x01,0x2f,0x00,0x00,0x00,0x01, 0x00,0x01,0x04,0x1c,0x00,0x01,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x01,0x03,0x48,0x00,0x01,0x00,0x00,0x00,0xa6,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x02,0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x19,0x00,0x01,0x00,0x00,0x01,0x10,0x00,0x03,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x02, 0x04,0x19,0x04,0x1b,0x00,0x00,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x03,0x04,0x19,0x03,0x2b,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x03,0x04,0x19,0x03,0x2e,0x04,0x19,0x00,0x00,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x03,0x04,0x19,0x04,0x1c,0x04,0x1c,0x00,0x00,0x00,0x01,0x03,0x43,0x00,0x01,0x00,0x03,0x04,0x19, 0x03,0x3d,0x04,0x19,0x00,0x00,0x00,0x02,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x01,0x00,0x00,0x00,0xc0,0x00,0x03,0x04,0x1c,0x03,0x30,0x03,0x43,0x00,0x01,0x00,0x01,0x04,0x1b,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00, 0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x03,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01, 0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x04,0x00,0x00, }; read_only global String8 rd_default_code_font_bytes = {rd_default_code_font_bytes__data, sizeof(rd_default_code_font_bytes__data)}; read_only global U8 rd_icon_file_bytes__data[] = { 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x20,0x00,0x02,0x1e,0x00,0x00,0x16,0x00,0x00,0x00,0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x06,0x00,0x00,0x00,0x5c,0x72,0xa8,0x66,0x00,0x00,0x1d,0xc9,0x49,0x44,0x41,0x54,0x78, 0x9c,0xed,0xdd,0x7b,0x7c,0x14,0xe5,0xbd,0xc7,0xf1,0xcf,0x6e,0xb2,0x9b,0x04,0x12,0x20,0x10,0xae,0xe2,0x25,0x52,0x06,0x05,0xe5,0x12,0x14,0x6f,0xc7,0x56,0x99,0x5a,0xd4,0xaa,0xd5,0xda,0x8b,0xb7,0xa2,0x55,0x4f,0x6d,0x6b,0xab,0xb5,0xf6,0x72,0x7a,0xb1,0xb5,0x1e,0x41,0xce,0xd1,0xb6,0x5a,0x4f,0xeb,0xa9,0x56,0x8b,0x37,0xb4,0x5a, 0xfb,0xaa,0x56,0x5a,0xa4,0x1d,0xb5,0x20,0x2d,0x95,0x8a,0x8a,0xf5,0xa0,0x83,0x8a,0x37,0x10,0x08,0x90,0x70,0x0b,0xe4,0xb6,0x7b,0xfe,0x98,0x8d,0x44,0x48,0x42,0x36,0xf3,0xcc,0xfc,0x66,0x77,0x7e,0xef,0xd7,0x8b,0x57,0xbc,0x24,0xcf,0xf3,0xcb,0x32,0xcf,0x77,0x9f,0x99,0x9d,0x79,0x1e,0x50,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5, 0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x54,0xe1,0x4a,0x48,0x17,0xa0,0x82,0xe5,0x58,0x54,0x01,0xd5,0xc0,0xa0,0x4e,0x5f,0x3b,0xff,0x33,0x40,0x23,0xd0,0x90,0xfb,0xda,0xf9,0x9f,0x1b,0x6c,0x97,0x6d,0x61,0xd7,0xac,0xc2,0xa3,0x01,0x50,0xa0,0x1c,0x8b,0xa1,0xc0,0x54,0x60,0x0a,0x70,0x30,0x7b, 0x0f,0xec,0x6a,0x60,0x20,0x50,0xe2,0xb3,0xab,0x76,0x60,0x0b,0x9d,0x42,0x81,0xdd,0x41,0xf1,0x06,0xf0,0x3c,0xf0,0x9c,0xed,0x52,0xef,0xb3,0x1f,0x25,0x40,0x03,0xa0,0x00,0x38,0x16,0xfb,0x03,0x75,0x78,0x83,0xbd,0x2e,0xf7,0x67,0x3f,0xd1,0xa2,0xf6,0xb6,0x06,0x58,0xde,0xf9,0x8f,0xed,0xf2,0xae,0x6c,0x49,0x6a,0x5f,0x34,0x00,0x22, 0xc4,0xb1,0x48,0xe0,0xbd,0x9b,0xd7,0x75,0xfa,0x33,0x05,0x18,0x2a,0x59,0x97,0x0f,0xf5,0x78,0x33,0x84,0xce,0xa1,0xf0,0xba,0x6c,0x49,0xaa,0x33,0x0d,0x80,0x88,0x70,0x2c,0x7e,0x0f,0x9c,0x80,0x37,0x6d,0x2f,0x66,0x5b,0x80,0xa7,0x6d,0x97,0x33,0xa5,0x0b,0x51,0x1a,0x00,0x91,0xe0,0x58,0xd4,0xe2,0x9d,0x4f,0xc7,0x49,0xad,0xed,0xf2, 0xa6,0x74,0x11,0x71,0x97,0x94,0x2e,0x40,0x01,0x30,0x5d,0xba,0x00,0x01,0x71,0xfc,0x9d,0x23,0x47,0x03,0x20,0x1a,0xe2,0x38,0x18,0xe2,0xf8,0x3b,0x47,0x8e,0x06,0x40,0x34,0x9c,0x28,0x5d,0x80,0x80,0x38,0xfe,0xce,0x91,0xa3,0x01,0x20,0xcc,0xb1,0x38,0x04,0x18,0x29,0x5d,0x87,0x80,0x51,0x8e,0xc5,0x38,0xe9,0x22,0xe2,0x4e,0x03,0x40, 0x5e,0x9c,0xa7,0xc2,0x71,0xfe,0xdd,0x23,0x41,0x03,0x40,0x5e,0x9c,0x07,0x41,0x9c,0x7f,0xf7,0x48,0xd0,0x8f,0x01,0x05,0xe5,0x6e,0xfc,0xa9,0x07,0x86,0x48,0xd7,0x22,0x64,0x23,0x30,0xcc,0x76,0xc9,0x4a,0x17,0x12,0x57,0x3a,0x03,0x90,0x35,0x91,0xf8,0x0e,0x7e,0x80,0x1a,0xe0,0x70,0xe9,0x22,0xe2,0x4c,0x03,0x40,0x96,0x4e,0x81,0xf5, 0x35,0x10,0xa5,0x01,0x20,0x4b,0x0f,0x7e,0x7d,0x0d,0x44,0xe9,0x35,0x00,0x21,0x8e,0x45,0x09,0xb0,0x19,0x18,0x20,0x5d,0x8b,0xb0,0x2d,0xc0,0x10,0xdb,0xa5,0x5d,0xba,0x90,0x38,0xd2,0x19,0x80,0x9c,0xa9,0xe8,0xe0,0x07,0xef,0xe1,0xa7,0x3a,0xe9,0x22,0xe2,0x4a,0x03,0x40,0x8e,0x4e,0x7d,0x77,0xd3,0xd7,0x42,0x88,0x06,0x80,0x1c,0x3d, 0xe8,0x77,0xd3,0xd7,0x42,0x88,0x5e,0x03,0x10,0xe0,0x58,0xa4,0xf1,0x96,0xd6,0xea,0x27,0x5d,0x4b,0x44,0x34,0x01,0x83,0x6c,0x97,0x56,0xe9,0x42,0xe2,0x46,0x67,0x00,0x32,0x8e,0x42,0x07,0x7f,0x67,0xfd,0xf0,0x5e,0x13,0x15,0x32,0x0d,0x00,0x19,0x3a,0xe5,0xdd,0x9b,0xbe,0x26,0x02,0x34,0x00,0x64,0xe8,0xc1,0xbe,0x37,0x7d,0x4d,0x04, 0xe8,0x35,0x80,0x90,0x39,0x16,0x15,0x78,0x4b,0x6a,0xa7,0xa5,0x6b,0x89,0x98,0x66,0xa0,0xda,0x76,0xd9,0x29,0x5d,0x48,0x9c,0xe8,0x0c,0x20,0x7c,0xc7,0xa1,0x83,0xbf,0x2b,0x65,0xc0,0xb1,0xd2,0x45,0xc4,0x8d,0x06,0x40,0xf8,0x74,0xaa,0xdb,0x3d,0x7d,0x6d,0x42,0xa6,0x01,0x10,0x3e,0x3d,0xc8,0xbb,0xa7,0xaf,0x4d,0xc8,0xf4,0x1a,0x40, 0x88,0x1c,0x8b,0x01,0x78,0xf7,0xff,0xfb,0xdd,0xae,0xab,0x58,0xb5,0x01,0x83,0x75,0x3f,0xc2,0xf0,0xe8,0x0c,0x20,0x5c,0xc7,0xa3,0x83,0xbf,0x27,0xa5,0x78,0xaf,0x91,0x0a,0x89,0xce,0x00,0x42,0xe0,0x58,0x94,0x03,0x5f,0x00,0xbe,0x0d,0x8c,0x12,0x2e,0x27,0xea,0xd6,0x02,0x73,0x80,0x3b,0x6c,0x97,0x5d,0xd2,0xc5,0x14,0x3b,0x0d,0x80, 0x00,0xe5,0x3e,0xf2,0xfb,0x22,0xf0,0x2d,0x60,0x84,0x70,0x39,0x85,0xe6,0x3d,0xe0,0x46,0xe0,0x7f,0xf5,0xa3,0xc1,0xe0,0x68,0x00,0x04,0xc0,0xb1,0xe8,0x0f,0x7c,0x19,0xb8,0x1a,0x18,0x2e,0x5c,0x4e,0xa1,0x5b,0x0f,0xdc,0x04,0xdc,0x66,0xbb,0xec,0x90,0x2e,0xa6,0xd8,0x68,0x00,0x18,0xe4,0x58,0x54,0x02,0x5f,0x01,0xbe,0x4e,0xe1,0xee, 0xe8,0x1b,0x55,0xf5,0xc0,0x4f,0x80,0xff,0xb1,0x5d,0xb6,0x4b,0x17,0x53,0x2c,0x34,0x00,0x0c,0xc8,0x5d,0xdd,0xbf,0x02,0xf8,0x1a,0xf1,0x5e,0xe4,0x33,0x0c,0x9b,0x80,0x9b,0x81,0x9f,0xd9,0x2e,0x5b,0xa5,0x8b,0x29,0x74,0x05,0x15,0x00,0x8e,0x45,0x12,0xf8,0x11,0xb0,0x1a,0x58,0x60,0xbb,0xac,0x15,0xae,0x27,0x0d,0x7c,0x13,0xf8,0x06, 0x30,0x48,0xb2,0x96,0x18,0x6a,0x00,0x7e,0x0c,0xdc,0x68,0xbb,0xb4,0x48,0x16,0xe2,0x58,0x8c,0x02,0x4e,0x06,0x0e,0x02,0xae,0xb5,0x5d,0x32,0x92,0xf5,0xe4,0xa3,0xd0,0x02,0xe0,0x66,0xe0,0xca,0x4e,0xff,0xe9,0x5f,0xc0,0x02,0xe0,0x09,0x60,0xb1,0xed,0xd2,0x1c,0x62,0x2d,0x75,0xc0,0x5c,0x74,0x59,0x6b,0x69,0x2f,0x01,0x17,0xda,0x2e, 0xcf,0x87,0xd5,0xa1,0x63,0x51,0x86,0xf7,0x71,0xe5,0x0c,0xbc,0x81,0x7f,0x58,0xa7,0xff,0x7d,0xb3,0xed,0x72,0x55,0x58,0xb5,0xf8,0x55,0x30,0x01,0xe0,0x58,0x5c,0x89,0x37,0xf5,0xeb,0x4e,0x13,0xf0,0x34,0xb9,0x40,0xb0,0x5d,0xdc,0x80,0xea,0x48,0x01,0xd7,0x00,0xdf,0xc1,0xfb,0xdc,0x5a,0xc9,0x6b,0x03,0x6e,0x00,0xfe,0x33,0xa8,0x45, 0x45,0x1c,0x0b,0x8b,0xdd,0x03,0xfe,0x04,0x7a,0x5e,0xcf,0xe1,0x4a,0xdb,0xe5,0x67,0x41,0xd4,0x61,0x5a,0x41,0x04,0x80,0x63,0x71,0x26,0xf0,0x08,0xf9,0xdd,0xb8,0xb4,0x1a,0x6f,0x66,0xb0,0x00,0x78,0xd2,0xc4,0xdd,0x65,0x8e,0xc5,0x14,0xbc,0x77,0xfd,0x89,0x7e,0xdb,0x52,0x81,0x58,0x01,0x5c,0x64,0x62,0x36,0xe0,0x58,0x54,0x01,0x36, 0xde,0xa0,0x9f,0x01,0xd4,0xe6,0xf1,0xe3,0x19,0xe0,0x93,0xb6,0xcb,0xa3,0x7e,0xeb,0x08,0x5a,0xe4,0x03,0xc0,0xb1,0x98,0x86,0xf7,0xce,0x5e,0xe1,0xa3,0x99,0x56,0xe0,0x6f,0xec,0x0e,0x84,0x17,0xf2,0xd9,0x8e,0x2a,0xf7,0xae,0xff,0x7d,0xe0,0xbb,0xe8,0xbb,0x7e,0xd4,0xb5,0x02,0xb3,0x81,0x59,0xf9,0xcc,0x06,0x72,0xdb,0xb4,0x4d,0x61, 0xf7,0xbb,0xfc,0x31,0x40,0xca,0x47,0x1d,0x4d,0xc0,0x09,0xb6,0xcb,0x32,0x1f,0x6d,0x04,0x2e,0xd2,0x01,0xe0,0x58,0xd4,0x02,0x4b,0x81,0x61,0x86,0x9b,0x5e,0x0f,0x2c,0xc4,0x0b,0x84,0x85,0xb6,0x4b,0x7d,0x0f,0x35,0x4c,0xc6,0x7b,0xd7,0x9f,0x64,0xb8,0x06,0x15,0xac,0x17,0xf1,0xae,0x0d,0xbc,0xd8,0xdd,0x37,0x38,0x16,0x43,0x81,0x8f, 0xe1,0x0d,0xf8,0x93,0x30,0x7f,0xcf,0xc6,0x06,0xe0,0x68,0xdb,0x65,0xb5,0xe1,0x76,0x8d,0x89,0x6c,0x00,0x38,0x16,0xd5,0x78,0xef,0xda,0x87,0x04,0xdc,0x55,0x16,0x58,0xce,0xee,0xd9,0xc1,0xdf,0x6d,0x97,0xb6,0xdc,0xbb,0xfe,0xf7,0xf0,0xde,0xf5,0xfd,0xbc,0x13,0x28,0x39,0xad,0xc0,0x2c,0x60,0xb6,0xed,0xd2,0xea,0x58,0x94,0xe2,0xbd, 0xb3,0x9f,0x8c,0xf7,0x4e,0x5f,0x47,0xf0,0x63,0xe0,0x15,0xe0,0x58,0xdb,0xa5,0x21,0xe0,0x7e,0xfa,0x24,0x92,0x01,0x90,0xbb,0xca,0xba,0x10,0xf8,0xb0,0x40,0xf7,0x5b,0x01,0x07,0xef,0x9c,0x6f,0xb2,0x40,0xff,0xca,0xbc,0x17,0xf0,0xae,0x09,0xd9,0xc8,0x6c,0xc6,0xb2,0x08,0x38,0x49,0xfa,0xe3,0xca,0xae,0x44,0x2e,0x00,0x72,0xe7,0x62, 0xf7,0x03,0xe7,0x4a,0xd7,0xa2,0x94,0x41,0xf3,0x80,0x0b,0xa2,0xb6,0x15,0x7a,0x14,0x1f,0x07,0xbe,0x1e,0x1d,0xfc,0xaa,0xf8,0x9c,0x07,0xfc,0xa7,0x74,0x11,0x7b,0x8a,0xd4,0x0c,0xc0,0xb1,0xb8,0x14,0xb8,0x43,0xba,0x0e,0xa5,0x02,0x74,0xa9,0xed,0x72,0xa7,0x74,0x11,0x1d,0x22,0x13,0x00,0x8e,0xc5,0x47,0x81,0x3f,0xa1,0x1f,0xb3,0xa9, 0xe2,0xd6,0x06,0x9c,0x62,0xbb,0xfc,0x45,0xba,0x10,0x88,0x48,0x00,0xe4,0xae,0xf8,0xbf,0x0c,0x8c,0x94,0xae,0x45,0xa9,0x10,0xbc,0x07,0x4c,0x88,0xc2,0x27,0x03,0x51,0xb9,0x06,0xf0,0x33,0x74,0xf0,0xab,0xf8,0x18,0x09,0xdc,0x22,0x5d,0x04,0x44,0x60,0x06,0xe0,0x58,0x9c,0x0e,0x3c,0x26,0x5d,0x87,0x52,0x02,0x4e,0xb7,0x5d,0x1e,0x97, 0x2c,0x40,0x34,0x00,0x74,0xea,0xaf,0x62,0x4e,0xfc,0x54,0x40,0xfa,0x14,0xe0,0x16,0x74,0xf0,0xab,0xf8,0x1a,0x49,0xcf,0x4f,0xb8,0x06,0x4e,0x6c,0x06,0xa0,0x53,0x7f,0xa5,0xde,0x27,0x76,0x2a,0x20,0x12,0x00,0x3a,0xf5,0x57,0xea,0x03,0xd6,0xe2,0x9d,0x0a,0x34,0x86,0xdd,0xb1,0xd4,0x29,0x80,0x4e,0xfd,0x95,0xda,0x6d,0x14,0x42,0x9f, 0x0a,0x84,0x3e,0x03,0xd0,0xa9,0xbf,0x52,0xdd,0x0a,0xfd,0x54,0x20,0xd4,0x00,0xd0,0xa9,0xbf,0x52,0x3d,0x0a,0xfd,0x54,0x20,0xec,0x53,0x00,0x9d,0xfa,0x2b,0xd5,0xbd,0xd0,0x4f,0x05,0x42,0x9b,0x01,0x38,0x16,0xa7,0x01,0x7f,0x08,0xab,0x3f,0xa5,0x0a,0x58,0x68,0xa7,0x02,0xa1,0x04,0x40,0x6e,0x81,0x8f,0x55,0xc0,0xfe,0x61,0xf4,0xa7, 0x54,0x81,0x7b,0x07,0xf8,0x50,0x18,0x0b,0x88,0x84,0x75,0x0a,0x70,0x09,0x3a,0xf8,0x95,0xea,0xad,0xfd,0xf1,0xc6,0x4c,0xe0,0x02,0x9f,0x01,0xe4,0x76,0xcf,0x79,0x0d,0x0d,0x00,0xa5,0xf2,0xf1,0x36,0x30,0x36,0xe8,0x59,0x40,0x18,0x33,0x80,0xcf,0xa3,0x83,0x5f,0xa9,0x7c,0x1d,0x00,0x5c,0x14,0x74,0x27,0x81,0xce,0x00,0x72,0x2b,0xeb, 0xae,0x02,0x0e,0x0c,0xb2,0x1f,0xa5,0x8a,0xd4,0x5b,0x78,0xb3,0x80,0x40,0x76,0x3b,0x82,0xe0,0x67,0x00,0x17,0xa2,0x83,0x5f,0xa9,0xbe,0x3a,0x10,0x98,0x19,0x64,0x07,0x81,0xcd,0x00,0x72,0x6b,0xb0,0xbb,0xe4,0xb7,0xa5,0x92,0x52,0xea,0x83,0x56,0x03,0x96,0xed,0xd2,0x16,0x44,0xe3,0x41,0xce,0x00,0x66,0xa2,0x83,0x5f,0x29,0xbf,0x6a, 0x81,0xcf,0x05,0xd5,0x78,0x20,0x33,0x80,0xdc,0xbb,0xff,0xab,0xc0,0xc1,0x41,0xb4,0xaf,0x54,0xcc,0xbc,0x0e,0x8c,0xb3,0x5d,0xda,0x4d,0x37,0x1c,0xd4,0x0c,0xe0,0x7c,0x74,0xf0,0x2b,0x65,0xca,0x18,0xbc,0x31,0x65,0x9c,0xf1,0x19,0x80,0x63,0x51,0x82,0xb7,0x1f,0xda,0x87,0x4c,0xb7,0xad,0x54,0x8c,0xad,0x02,0x0e,0x35,0x3d,0x0b,0x08, 0x62,0x0d,0xfe,0xf3,0xd0,0xc1,0xdf,0xa3,0x64,0x2a,0xcd,0x90,0xe9,0xa7,0x33,0xea,0xd3,0x97,0x52,0x7d,0xe4,0x47,0x00,0xc8,0x66,0xb3,0x40,0x16,0x32,0x19,0xef,0x9f,0x73,0x7f,0xb2,0xd9,0xcc,0xfb,0xff,0x4c,0x36,0x4b,0x36,0x93,0xf1,0xbe,0x2f,0x9b,0xf5,0xbe,0xaf,0xf3,0xf7,0x93,0xfb,0xff,0xdd,0xfc,0x7c,0xc7,0xf7,0x43,0x76,0xf7, 0xcf,0x7c,0xa0,0xbf,0x3d,0xfa,0xee,0xa2,0x2f,0xb2,0x59,0xb2,0x74,0xf5,0xb3,0xbd,0xab,0xb5,0xf3,0xcf,0xaf,0x7b,0xf4,0x3e,0x36,0x3e,0xa9,0x4f,0x86,0xf7,0xd2,0x58,0xbc,0x1d,0xb3,0xee,0x33,0xd9,0xa8,0xd1,0x19,0x80,0x63,0x91,0x04,0x56,0x02,0x96,0xc9,0x76,0x8b,0x59,0xbf,0x03,0xc7,0x32,0xf2,0x33,0x97,0x32,0xf2,0xac,0x8b,0x48, 0x0f,0x31,0xbd,0x0b,0x7a,0xb4,0x65,0xdb,0x5a,0x59,0xf1,0xc5,0x33,0xd8,0xb4,0x78,0x81,0x74,0x29,0x85,0xe2,0x55,0x60,0xbc,0xed,0x92,0x31,0xd5,0xa0,0xe9,0x00,0x38,0x07,0x78,0xc0,0x64,0x9b,0x71,0x91,0x4c,0xa5,0x19,0x72,0xe2,0x69,0x1c,0x70,0xf1,0x37,0x18,0x38,0xe5,0x18,0xe9,0x72,0x42,0x93,0x69,0xde,0xc5,0x8b,0x97,0x9e,0x42, 0xc3,0xb3,0x4f,0x4b,0x97,0x52,0x28,0xce,0xb5,0x5d,0x1e,0x34,0xd5,0x98,0xe9,0x8b,0x80,0xa1,0x3c,0xc0,0x50,0x8c,0x32,0xad,0x2d,0xd4,0x2f,0xfc,0x1d,0xcb,0xcf,0x3f,0x9e,0x55,0x37,0x7c,0x9d,0x4c,0xf3,0x2e,0xe9,0x92,0x42,0x91,0x2c,0x2b,0x67,0xe2,0xed,0x8f,0x33,0x60,0xf2,0xd1,0xd2,0xa5,0x14,0x8a,0x8b,0x4d,0x36,0x66,0x6c,0x06, 0xe0,0x58,0x0c,0xc3,0x5b,0xd1,0xa4,0xc4,0x54,0x9b,0x71,0xd6,0xef,0xe0,0x43,0x18,0x3f,0x67,0x2e,0x03,0x26,0x1d,0x25,0x5d,0x4a,0x28,0xda,0xb6,0x36,0xb2,0x7c,0xe6,0x89,0x6c,0x5f,0xf9,0x82,0x74,0x29,0x51,0xd7,0x0e,0x8c,0xb4,0x5d,0xea,0x4d,0x34,0x66,0x72,0x06,0xf0,0x69,0x74,0xf0,0x1b,0xd3,0xf4,0xc6,0x2b,0x3c,0x77,0xee,0xbf, 0xf1,0xfa,0x8f,0xbf,0x43,0xa6,0x35,0xf0,0xc7,0xc2,0xc5,0x95,0x0e,0x18,0xc4,0x94,0x5f,0xff,0x99,0xfe,0x1f,0x1a,0x2f,0x5d,0x4a,0xd4,0x95,0xe0,0x8d,0x35,0x23,0x4c,0x06,0xc0,0x39,0x06,0xdb,0x52,0x40,0xb6,0xbd,0x8d,0xb7,0x6e,0x9f,0xc3,0xb2,0xb3,0xa6,0xd2,0xb4,0xfa,0x55,0xe9,0x72,0x02,0x97,0xaa,0xae,0x61,0xca,0xdc,0xbf,0x50, 0x71,0xc0,0x18,0xe9,0x52,0xa2,0xce,0xd8,0x58,0x33,0x72,0x0a,0xe0,0x58,0x8c,0xc6,0x7b,0x7e,0x59,0x7c,0xaf,0xc1,0x62,0x55,0x36,0x7c,0x3f,0xea,0xe6,0x2d,0xa6,0x62,0x74,0xf1,0xdf,0x5d,0xbd,0x6b,0xed,0x5b,0x2c,0x3f,0xff,0xc3,0xec,0x5a,0xfb,0xb6,0x74,0x29,0x51,0x95,0x05,0xf6,0xb7,0x5d,0xd6,0xf8,0x6d,0xc8,0x54,0x00,0x5c,0x0d, 0xdc,0x64,0xa2,0xad,0x42,0x52,0x5a,0x99,0xa0,0xfa,0xb0,0x34,0xe5,0x43,0x4b,0x28,0xab,0x4e,0x92,0xae,0x4e,0x52,0x36,0x38,0x49,0x32,0x95,0xa0,0x79,0x73,0x86,0x96,0xcd,0x19,0x9a,0x1b,0xda,0x69,0xde,0x94,0xa1,0x71,0x65,0x2b,0xbb,0xea,0xfd,0xdd,0xc3,0x51,0x31,0xba,0x96,0xba,0x79,0x8b,0x29,0x1b,0xbe,0x9f,0xa1,0xdf,0x20,0xba, 0x9a,0xde,0x5a,0xc5,0xf2,0xf3,0x3e,0x4c,0xcb,0xc6,0x75,0xd2,0xa5,0x44,0xd5,0xd5,0xb6,0xcb,0x4f,0xfc,0x36,0x62,0x2a,0x00,0x96,0x01,0x47,0x98,0x68,0x2b,0xea,0xca,0x6b,0x4a,0xa8,0x99,0x96,0x66,0xe8,0xb4,0x32,0x06,0x8d,0x4f,0x93,0xc8,0xe3,0xaa,0xc7,0xf6,0xd5,0x6d,0xd4,0x3f,0xdb,0x4c,0xfd,0xb2,0x66,0xb6,0xbf,0xd9,0xe6,0xe5, 0x78,0x9e,0xfa,0xd5,0x8e,0xa3,0xee,0xfe,0x45,0xb1,0xb8,0x67,0x60,0xc7,0xaa,0x97,0x59,0xfe,0xb9,0x13,0x68,0x6d,0xd8,0x28,0x5d,0x4a,0x14,0x2d,0xb3,0x5d,0xa6,0xf9,0x6d,0xc4,0x77,0x00,0x38,0x16,0x63,0xf0,0x96,0xfc,0x2a,0x6a,0xfd,0x46,0x95,0x30,0xe6,0x82,0x4a,0x86,0x1e,0x55,0x66,0xa4,0xbd,0x6d,0xaf,0xb7,0xf1,0xda,0xbd,0xdb, 0x69,0x78,0x29,0xff,0x0b,0x7c,0x95,0xe3,0x26,0x52,0x77,0xdf,0xd3,0x94,0x0e,0xa8,0x36,0x52,0x4b,0x94,0x6d,0x7b,0x79,0x39,0xcf,0x5f,0x38,0x9d,0xb6,0x6d,0x5b,0xa4,0x4b,0x89,0xa2,0x31,0xb6,0xcb,0x1b,0x7e,0x1a,0x30,0x71,0x11,0xb0,0xa8,0x2f,0xfe,0xa5,0xab,0x93,0x8c,0xbb,0xac,0x8a,0xa3,0x6e,0x19,0x62,0x6c,0xf0,0x03,0x54,0x8d, 0x29,0x65,0xca,0xb5,0x83,0x98,0x7c,0xcd,0x20,0x2a,0x0f,0xca,0xef,0x8e,0xec,0xed,0xaf,0xae,0xe0,0x85,0x4b,0x4e,0x8e,0xc5,0xbd,0x02,0x55,0x13,0xea,0x98,0x74,0xc7,0x1f,0x29,0xe9,0x57,0x29,0x5d,0x4a,0x14,0xf9,0x1e,0x7b,0xbe,0x3f,0xb6,0xbb,0x70,0x08,0xbf,0x00,0x8a,0x72,0x3e,0x3a,0xfc,0xdf,0xca,0x99,0x72,0xed,0x20,0x06,0x8e, 0x4b,0x91,0x08,0xe8,0xf2,0x66,0xc5,0x88,0x12,0xf6,0xfb,0x58,0x05,0xc9,0x74,0x82,0xc6,0x7f,0xb5,0xf4,0xfa,0xb4,0xa0,0x79,0xfd,0x1a,0x48,0x24,0xa8,0x3e,0x7a,0x7a,0x30,0x85,0x45,0x48,0xf9,0xc8,0xfd,0x19,0x38,0xf9,0x68,0x36,0x2c,0x78,0x98,0x6c,0x5b,0x20,0xeb,0x62,0x14,0xaa,0x61,0xf7,0x6c,0xe2,0x36,0x3f,0x0d,0xf8,0x3a,0xac, 0x1d,0x8b,0x09,0xc0,0xbf,0xfc,0xb4,0x11,0x45,0x89,0x04,0xd4,0x9e,0xdb,0x9f,0x83,0xce,0xee,0x1f,0x6a,0xbf,0x9b,0x9e,0x6b,0xe1,0xe5,0x9f,0x6e,0xa1,0x6d,0x67,0xef,0x52,0x20,0x99,0x2e,0x63,0xda,0xe3,0x2f,0xd1,0xef,0xc0,0xb1,0x01,0x57,0x16,0x0d,0x9b,0xfe,0xfa,0x47,0x5e,0xba,0xfc,0xac,0x58,0xdc,0x17,0x91,0x87,0x09,0xb6,0xcb, 0xff,0xf5,0xf5,0x87,0xfd,0x9e,0x02,0x14,0xdd,0xf4,0xbf,0xa4,0x3c,0xc1,0x61,0xdf,0x1a,0x18,0xfa,0xe0,0x07,0x18,0x32,0x35,0xcd,0xd4,0x39,0xd5,0x54,0x0c,0xef,0xdd,0xc4,0x2c,0xd3,0xd2,0x8c,0x7b,0xdd,0x57,0x02,0xae,0x2a,0x3a,0x86,0x7c,0xe4,0x54,0xc6,0xff,0xf8,0x7e,0x12,0x25,0x41,0x3c,0xc4,0x5a,0xb0,0x7c,0x8d,0x41,0xbf,0x01, 0xf0,0x59,0x9f,0x3f,0x1f,0x29,0x89,0x12,0x98,0xf8,0x9d,0x81,0x0c,0x9d,0x66,0xee,0x5c,0x3f,0x5f,0xfd,0x47,0x97,0x52,0x77,0x7d,0x35,0x65,0x83,0x7b,0xf7,0x57,0xb3,0xf9,0x99,0x85,0x6c,0x58,0xf0,0x70,0xc0,0x55,0x45,0xc7,0xb0,0x19,0x9f,0xe2,0xd0,0x1b,0xee,0x22,0x91,0x94,0xda,0xd9,0x3e,0x72,0x7c,0x8d,0xc1,0x3e,0xbf,0x8a,0x8e, 0x45,0x1d,0xde,0x33,0xca,0x45,0xc3,0xba,0xa4,0x8a,0xea,0xc3,0xd2,0xd2,0x65,0x50,0x36,0x38,0xc9,0xe1,0xdf,0x1e,0x48,0x32,0xdd,0xbb,0x33,0xb4,0x55,0xb3,0xaf,0xa2,0xbd,0x69,0x7b,0xc0,0x55,0x45,0xc7,0x88,0x4f,0x7c,0x0e,0xeb,0x07,0x3f,0x27,0xb0,0x0b,0x33,0x85,0xc5,0xca,0x8d,0xc5,0x3e,0xe9,0xf3,0x45,0xc0,0x0b,0x87,0xd0,0x04, 0x9c,0x08,0x8c,0xee,0x6b,0x1b,0x51,0xb2,0xdf,0xc9,0x15,0xd4,0x7e,0x26,0xfc,0x69,0x7f,0x77,0xca,0x06,0x97,0x50,0x31,0xbc,0x84,0xfa,0x7f,0x34,0xef,0xf3,0x7b,0xdb,0x77,0x6c,0xa3,0x75,0xd3,0x06,0x4a,0xaa,0x06,0xd0,0xb2,0x61,0x2d,0xad,0x9b,0xd6,0xd3,0xda,0xb0,0x91,0xb6,0xad,0x0d,0xb4,0x6d,0xdf,0x4a,0x66,0xe7,0x0e,0x32,0xcd, 0xbb,0xc8,0xb6,0xb5,0x92,0xcd,0x64,0x48,0x24,0x13,0x05,0xff,0x0e,0x3a,0xe0,0xf0,0x23,0x28,0xe9,0x5f,0xc5,0xe6,0x25,0x7f,0x96,0x2e,0x45,0xda,0x52,0xe0,0xd6,0x7b,0x36,0xb1,0xef,0x03,0xa5,0x0b,0x7e,0x2f,0x02,0x0e,0x00,0xfe,0x04,0x1c,0xeb,0xa7,0x1d,0x69,0x03,0xac,0x14,0x53,0x67,0x55,0x93,0x88,0xe0,0x98,0x58,0x75,0xd7,0x76, 0xde,0x99,0xdf,0x64,0xbc,0xdd,0x44,0x32,0x49,0xa2,0x34,0x45,0x22,0x95,0x26,0x99,0x4a,0xbf,0xff,0x35,0x99,0x4a,0x93,0x48,0x7f,0xf0,0xbf,0x75,0xf7,0x3d,0x89,0xd2,0xd4,0xee,0x7f,0xcf,0x7d,0x4d,0x0d,0x1a,0xc2,0x7e,0xe7,0x5f,0x4e,0xa2,0x24,0x9c,0xe7,0xc2,0x56,0x7c,0xf1,0x74,0x36,0x3e,0x15,0xca,0x46,0xba,0x51,0xb4,0x04,0x38, 0xc5,0x76,0xd9,0xd6,0xd7,0x06,0x7c,0x5d,0x4d,0xb1,0x5d,0xb6,0x3a,0x16,0x33,0x80,0xf9,0xc0,0x87,0xfd,0xb4,0x25,0x26,0x01,0x63,0x2f,0xaa,0x8c,0xe4,0xe0,0x07,0xa8,0x3d,0xa7,0x3f,0xeb,0x16,0xed,0xa2,0x75,0x9b,0xb1,0x45,0x60,0x00,0xc8,0x66,0x32,0x64,0x5b,0x9a,0xa1,0xa5,0xd9,0xd8,0x22,0x73,0x65,0xc3,0x46,0x31,0xe9,0xf6,0xf9, 0xa1,0x0d,0xfe,0x77,0xef,0xbd,0x95,0x8d,0x4f,0xcf,0x0f,0xa5,0xaf,0x08,0xfa,0x2b,0x70,0x9a,0xed,0xe2,0xeb,0xdc,0xcf,0xf7,0x61,0x9f,0x2b,0xe0,0x14,0xe0,0x49,0xbf,0x6d,0x49,0x18,0x3a,0xad,0x8c,0x81,0xe3,0x52,0xd2,0x65,0x74,0xab,0xb4,0x5f,0x82,0x03,0xcf,0xee,0x27,0x5d,0xc6,0x3e,0xf5,0x1f,0x7b,0x18,0x53,0x1f,0x5a,0x4a,0xe5, 0xa1,0x93,0x43,0xe9,0xef,0xdd,0x7b,0x6f,0xc5,0x9d,0x75,0x65,0x6e,0x2d,0xc4,0xd8,0x71,0x80,0x53,0xfd,0x0e,0x7e,0x30,0xf4,0x38,0xb0,0xed,0xd2,0x04,0x9c,0x06,0x2c,0x34,0xd1,0x5e,0x58,0x12,0x25,0x30,0xe6,0x82,0xe8,0xdf,0x61,0x36,0xfa,0x94,0x0a,0xca,0x87,0x45,0x77,0xa9,0x85,0xea,0x63,0x6c,0xa6,0x3e,0xb8,0x84,0xf2,0x91,0xe1, 0xec,0x01,0x1b,0xf3,0xc1,0xff,0x04,0x70,0x7a,0x6e,0xcc,0xf9,0x66,0x6c,0xe2,0x6b,0xbb,0xec,0x04,0xce,0x00,0xfe,0x68,0xaa,0xcd,0xa0,0x0d,0x3f,0xbe,0x9c,0x7e,0xa3,0xa2,0x3b,0xb0,0x3a,0x24,0x4b,0x13,0x1c,0xf4,0xc9,0x68,0xce,0x02,0x46,0x9c,0x39,0x93,0xc9,0x77,0x2e,0xa0,0xb4,0x72,0x40,0x28,0xfd,0xc5,0x7c,0xf0,0xcf,0x07,0x3e, 0x91,0x1b,0x6b,0x46,0x18,0x3d,0xf3,0xb5,0x5d,0x9a,0x81,0xb3,0x80,0x82,0x58,0xeb,0x79,0xd8,0x31,0x72,0x9f,0xf7,0xe7,0x6b,0xe8,0xd1,0x65,0x79,0x3d,0x79,0x18,0xb8,0x44,0x82,0xda,0xcb,0x7f,0xc0,0xf8,0xff,0xba,0x3b,0xb4,0x1b,0x73,0x62,0x3e,0xf8,0x1f,0x05,0x3e,0x99,0x1b,0x63,0xc6,0x18,0xbf,0xf4,0x65,0xbb,0xb4,0x00,0x9f,0x02, 0x1e,0x31,0xdd,0xb6,0x49,0x25,0xe5,0x09,0x06,0x4f,0x92,0xff,0xcc,0xbf,0xb7,0x52,0x55,0xc9,0xc8,0x5c,0xab,0x48,0x94,0xa6,0x38,0x74,0xd6,0x9d,0xd4,0x5e,0xf1,0xa3,0xd0,0xfa,0x8c,0xf9,0xe0,0x7f,0x04,0xf8,0x74,0x6e,0x6c,0x19,0x15,0xc8,0xb5,0xef,0xdc,0x7e,0xe6,0xe7,0x00,0x0f,0x05,0xd1,0xbe,0x09,0x83,0x27,0xa7,0x49,0xa6,0x0a, 0xeb,0x46,0x12,0xc9,0x3b,0x14,0x3b,0x94,0x56,0x0e,0x60,0xd2,0xed,0xf3,0x19,0x79,0xf6,0xe7,0x43,0xeb,0x33,0xe6,0x83,0xff,0x37,0xc0,0x39,0xb9,0x31,0x65,0x5c,0x60,0x1f,0x7e,0xe5,0xb6,0x33,0x3e,0x0f,0xb8,0x3f,0xa8,0x3e,0xfc,0xa8,0x39,0x52,0x7e,0x30,0xe5,0xab,0x46,0x38,0x00,0xca,0x46,0x8c,0xa6,0x6e,0xde,0x62,0x06,0x1f,0x77, 0x52,0x68,0x7d,0xc6,0x7c,0xf0,0xdf,0x07,0x9c,0x1f,0xd4,0xd6,0xe0,0x10,0xec,0xf6,0xe0,0xe4,0xf6,0x31,0x9b,0x09,0xcc,0x0d,0xb2,0x9f,0xbe,0xa8,0xdc,0xbf,0xf0,0x1e,0x28,0xa9,0x18,0x5e,0xd2,0xeb,0xdb,0x83,0x4d,0xab,0x1c,0x37,0x91,0x23,0x1e,0x5a,0x4a,0xe5,0xb8,0x89,0xa1,0xf5,0x19,0xf3,0xc1,0xff,0x6b,0xe0,0xc2,0x20,0x76,0x04, 0xee,0x2c,0xf0,0xdb,0x5f,0x72,0xdb,0x18,0x5d,0x0c,0xdc,0x11,0x74,0x5f,0xf9,0xe8,0xed,0xc3,0x36,0x51,0x53,0x56,0x1d,0x7e,0xdd,0x83,0x8f,0x3b,0x89,0xa9,0x0f,0x3c,0x13,0xea,0x5a,0x84,0x31,0x1f,0xfc,0x77,0x00,0x97,0x98,0xdc,0x02,0xac,0x3b,0xa1,0x1c,0x4d,0xb6,0x4b,0x16,0xb8,0x0c,0xf8,0x45,0x18,0xfd,0xed,0x4b,0xa2,0x04,0x52, 0x83,0x0a,0x34,0x00,0x42,0x0e,0xae,0x91,0x67,0x7f,0xde,0x5b,0x91,0xa7,0x7f,0x55,0x68,0x7d,0xc6,0x7c,0xf0,0xff,0x02,0xb8,0x2c,0x37,0x66,0x02,0x17,0xda,0x3c,0x38,0xf7,0x0b,0x5d,0xee,0x58,0xb4,0x02,0x57,0x86,0xd5,0x6f,0x57,0xd2,0x03,0x93,0x05,0xfb,0x20,0x59,0x3a,0xac,0x19,0x40,0x22,0x41,0xed,0x57,0xaf,0xa5,0xf6,0xf2,0x1f, 0x84,0xd3,0x5f,0x4e,0xcc,0x07,0xff,0xcd,0xb6,0xcb,0x55,0x61,0x76,0x18,0xfa,0xdb,0xa0,0xed,0xf2,0x35,0x84,0x97,0x10,0x4f,0x55,0x15,0xe6,0xbb,0x3f,0x40,0x6a,0x40,0xf0,0xb5,0x27,0x53,0x69,0xc6,0xcf,0x99,0xab,0x83,0x3f,0x5c,0x37,0x86,0x3d,0xf8,0x41,0x20,0x00,0x00,0x6c,0x97,0x6f,0x02,0x37,0x48,0xf4,0x0d,0x18,0x7f,0xb0,0x26, 0x4c,0xad,0x5b,0x83,0xad,0xbd,0xb4,0x6a,0x20,0x93,0x7e,0xf5,0x27,0x46,0x9c,0x39,0x33,0xd0,0x7e,0xf6,0x14,0xf3,0xc1,0x3f,0xdb,0x76,0xf9,0x96,0x44,0xc7,0x62,0x6f,0x85,0xb6,0xcb,0x77,0x81,0xeb,0x24,0xfa,0x6e,0xd9,0x92,0xe9,0xd3,0x9a,0xfc,0x51,0xd0,0xd2,0x10,0x5c,0x00,0x94,0x8f,0xdc,0x9f,0xa9,0x0f,0x3c,0x13,0xfa,0x42,0xa3, 0x31,0x1f,0xfc,0x3f,0xb2,0x5d,0xbe,0x27,0xd5,0xb9,0xe8,0x5c,0xd8,0x76,0xf9,0x21,0x70,0x4d,0xd8,0xfd,0x66,0xdb,0x73,0x21,0x50,0x80,0x9a,0x03,0x0a,0x80,0xca,0x43,0x27,0x33,0xf5,0xa1,0xa5,0xf4,0x1f,0x7b,0x58,0x20,0xed,0x77,0x27,0xe6,0x83,0xff,0xfb,0xb6,0xcb,0xb5,0x92,0x05,0x88,0x9f,0x0c,0xdb,0x2e,0xd7,0x03,0xb7,0x84,0xdd, 0x6f,0xf3,0xe6,0xc2,0x0c,0x80,0x20,0x66,0x00,0x43,0x8e,0x3f,0x99,0xa9,0xf3,0x16,0x53,0x36,0x6c,0x94,0xf1,0xb6,0x7b,0x12,0xf3,0xc1,0x7f,0xb3,0xed,0x32,0x4b,0xba,0x08,0xf1,0x00,0xc8,0x79,0x27,0xec,0x0e,0x77,0xbc,0x5b,0x78,0xeb,0xcb,0xef,0xda,0xd0,0x4e,0x7b,0xb3,0xd9,0xc1,0x32,0xea,0xd3,0x97,0x32,0xf1,0x97,0x8f,0x87,0xbe, 0xf1,0x46,0xcc,0x07,0x3f,0x08,0x1c,0xf3,0x5d,0x89,0x4a,0x00,0x0c,0x0a,0xbb,0xc3,0x8d,0xcb,0x8c,0x3e,0x54,0x15,0x8a,0x8d,0xcb,0x0c,0x3e,0x0b,0x92,0x48,0x70,0xf0,0xd7,0xae,0xe7,0x90,0xeb,0xef,0x08,0x6d,0x05,0x9f,0x0e,0x3a,0xf8,0x01,0x81,0x63,0xbe,0x2b,0x51,0xb9,0x1f,0x36,0xf4,0x4d,0xee,0x36,0x3d,0xdf,0x42,0xa6,0x2d,0x4b, 0xb2,0xb4,0x70,0x6e,0x08,0xa8,0x7f,0xd6,0x4c,0x68,0x25,0x53,0x69,0x0e,0x99,0x7d,0x27,0x23,0xce,0xb8,0xc0,0x48,0x7b,0xf9,0xd0,0xc1,0xff,0xbe,0x48,0x6c,0xec,0x18,0x95,0x19,0x40,0xe8,0x2f,0x46,0xfb,0xce,0x2c,0x0d,0x2b,0x02,0x79,0xc0,0x2a,0x10,0x6d,0xdb,0xb3,0x34,0xae,0xf4,0x3f,0x03,0x28,0x1d,0x30,0x88,0x49,0x77,0x2e,0xd0, 0xc1,0x2f,0x4f,0x03,0xa0,0x13,0x91,0x17,0x63,0xc3,0xdf,0x0b,0x67,0x73,0xcd,0xfa,0x67,0x9b,0xc9,0xfa,0x7c,0x2c,0xa4,0x7c,0xd4,0x81,0x4c,0x7d,0x60,0x09,0xd5,0x47,0x9d,0x68,0xa6,0xa8,0x3c,0xe8,0xe0,0xdf,0x8b,0x06,0x40,0x27,0x22,0xe7,0x43,0xeb,0x17,0x35,0xb3,0x73,0x5d,0xa0,0x0f,0x5b,0x19,0x91,0x6d,0x87,0x37,0x7f,0xbb,0xc3, 0x57,0x1b,0x55,0x13,0xea,0x38,0xe2,0xe1,0xa5,0xf4,0xff,0xd0,0x78,0x43,0x55,0xf5,0x9e,0x0e,0xfe,0x2e,0x45,0xe2,0x1a,0x40,0x54,0x02,0x40,0x24,0x0d,0x33,0x6d,0x59,0x5e,0xbf,0x3f,0xfa,0x3b,0xea,0xac,0x59,0xb0,0x93,0x9d,0xeb,0xfb,0x1e,0x54,0x43,0x3e,0x72,0x2a,0x75,0xf7,0x2f,0x22,0x5d,0x33,0xc2,0x60,0x55,0xbd,0xa3,0x83,0xbf, 0x5b,0x3a,0x03,0xe8,0x44,0xec,0xc5,0xd8,0xf0,0xf7,0x66,0xb6,0xbe,0x16,0xdd,0x6b,0x01,0xed,0x3b,0xb3,0xac,0xf6,0xf1,0xee,0x3f,0xea,0xb3,0x5f,0x60,0xe2,0x6d,0x8f,0x51,0x52,0x11,0xfe,0xae,0x47,0x3a,0xf8,0x7b,0xa4,0x01,0xd0,0x89,0xdc,0x74,0x28,0x0b,0xaf,0xcd,0xdd,0x1e,0xd9,0x63,0x74,0xf5,0xc3,0x3b,0xfa,0x74,0xff,0x7f,0x22, 0x99,0x64,0xcc,0xd7,0x67,0x73,0xc8,0x75,0xbf,0x0c,0xfd,0x63,0x3e,0xd0,0xc1,0xdf,0x0b,0x1a,0x00,0x00,0x8e,0x45,0x05,0x20,0xba,0xd6,0x55,0xe3,0xca,0x56,0x5e,0x9b,0x1b,0xbd,0x53,0x81,0x0d,0x7f,0x6f,0xe6,0x9d,0xc7,0xf2,0x5f,0xfe,0x3d,0x99,0x2e,0x63,0xfc,0x8d,0xf7,0x71,0xe0,0x65,0xdf,0x09,0xa0,0xaa,0x7d,0xd3,0xc1,0xdf,0x2b, 0x65,0x8e,0x45,0xb9,0x74,0x11,0xe2,0x01,0x40,0x44,0x92,0xf0,0x9d,0xf9,0x4d,0xbc,0xf7,0x64,0x74,0x3e,0x15,0xd8,0xb6,0xba,0x8d,0x95,0xb7,0x6e,0xcd,0x7b,0x0c,0xa5,0x06,0x0e,0x66,0xf2,0x5d,0x0b,0x19,0x7e,0xda,0xb9,0xc1,0x14,0xb6,0x0f,0x3a,0xf8,0xf3,0x22,0x7e,0xec,0x6b,0x00,0x74,0xc8,0xc2,0xab,0xb7,0x6f,0xa3,0x71,0xa5,0xfc, 0xf5,0x80,0x96,0xc6,0x0c,0x2f,0xcd,0xd9,0x92,0xf7,0x6d,0xbf,0x15,0xa3,0x6b,0x99,0xfa,0xe0,0x12,0x06,0x1d,0x29,0xb3,0x4d,0xa3,0x0e,0xfe,0xbc,0x89,0x1f,0xfb,0x51,0x08,0x80,0xc8,0xc8,0xb4,0x66,0x59,0x31,0xbb,0x91,0x4d,0xcb,0x8d,0x2f,0xbf,0xde,0x6b,0x4d,0xef,0xb5,0xb3,0xfc,0x07,0x0d,0xec,0xda,0x98,0xdf,0x55,0xff,0xaa,0xc3, 0x8e,0x60,0xea,0x43,0x4b,0xe9,0x77,0xf0,0x21,0x01,0x55,0xd6,0x33,0x1d,0xfc,0x85,0x29,0x0a,0x01,0xd0,0x20,0x5d,0x40,0x67,0x6d,0x4d,0x59,0x56,0xdc,0xd0,0xc8,0xdb,0x7d,0x38,0xf7,0xf6,0x6b,0xf3,0x8b,0x2d,0xfc,0xf3,0x3f,0x36,0xd3,0xb4,0x26,0xbf,0xc1,0x5f,0x33,0xfd,0x74,0xea,0xee,0xfb,0x2b,0xe9,0x21,0xc3,0x02,0xaa,0xac,0x67, 0x3a,0xf8,0xfb,0x4c,0xfc,0xd8,0xd7,0x00,0xe8,0x42,0x36,0x03,0xaf,0xdd,0xbd,0x9d,0x95,0xff,0xb3,0x95,0x4c,0x6b,0x38,0x07,0xf5,0x3b,0xf3,0x9b,0x78,0x71,0x56,0x23,0x6d,0xdb,0xf3,0xeb,0x6f,0xbf,0xf3,0xbe,0xcc,0xe1,0x3f,0xff,0x3d,0x25,0x15,0x32,0x7b,0x07,0xae,0xfb,0xfd,0x3d,0x3a,0xf8,0xfb,0x4e,0xfc,0xd8,0x8f,0xc4,0x93,0x30, 0x8e,0xc5,0x2e,0x84,0x3f,0x09,0xe8,0x4e,0x79,0x4d,0x09,0xb5,0xe7,0xf4,0x67,0xe4,0x09,0xe5,0x81,0xbc,0x5a,0x8d,0x2f,0xb7,0xf2,0xda,0xbd,0xdb,0xd9,0xba,0x2a,0xbf,0x6b,0x0f,0x89,0x64,0x92,0x31,0x57,0xcf,0xe1,0x80,0x4b,0xbf,0x69,0xbe,0xa8,0x3c,0xb4,0x6c,0x5c,0xc7,0xf2,0xcf,0x9d,0x48,0xd3,0x1b,0xaf,0x88,0xd6,0x51,0x80,0x9a, 0x6d,0x57,0xfe,0x53,0x80,0xa8,0x04,0xc0,0x3a,0x60,0xb8,0x74,0x1d,0x3d,0xa9,0x3c,0xb0,0x94,0x31,0x17,0x54,0x32,0xa4,0xce,0xcc,0x7e,0x82,0x3b,0xde,0x6e,0xe3,0xb5,0x7b,0xb7,0xb3,0xe9,0xf9,0x96,0xbc,0x97,0x27,0x4b,0x96,0x95,0x33,0xfe,0xbf,0xee,0x66,0xd8,0x29,0x9f,0x31,0x52,0x8b,0x5f,0x1a,0x02,0x7d,0xb2,0xce,0x76,0x19,0x29, 0x5d,0x44,0x54,0x02,0x60,0x25,0x20,0x73,0xf5,0x2a,0x4f,0xfd,0x46,0x95,0x50,0x73,0x64,0x19,0x43,0xa7,0x95,0x79,0x9b,0x75,0xe6,0xf1,0x0a,0x36,0xad,0x69,0xa7,0xfe,0xd9,0x66,0xea,0x9f,0x6d,0x66,0xdb,0xaa,0xd6,0x3e,0xcd,0x9a,0x4b,0xab,0x06,0x32,0xf1,0xb6,0xc7,0xc4,0xae,0xf4,0x77,0x47,0x43,0x20,0x6f,0x2b,0x6d,0x97,0xf0,0x1f, 0xcc,0xd8,0x43,0x54,0x02,0xe0,0x6f,0xc0,0x31,0xd2,0x75,0xe4,0x2b,0x3d,0x28,0xc9,0xe0,0x89,0x69,0xca,0x6a,0x92,0x94,0x0d,0x2e,0xa1,0xac,0x3a,0x49,0xba,0x3a,0x49,0x32,0x95,0xa0,0x79,0x73,0x3b,0x2d,0x0d,0x19,0x9a,0x37,0x67,0x68,0x6e,0xc8,0xd0,0xf8,0x72,0x0b,0x4d,0x6b,0xfd,0x3d,0x78,0x94,0xaa,0xae,0x61,0xf2,0x9d,0x4f,0x50, 0x35,0xa1,0xce,0xd0,0x6f,0x60,0x96,0x86,0x40,0x5e,0xfe,0x66,0xbb,0x1c,0x27,0x5d,0x44,0x54,0x16,0x04,0x69,0x94,0x2e,0xa0,0x2f,0x5a,0x1a,0x33,0xac,0x5b,0x14,0xce,0xcd,0x43,0x65,0xc3,0x46,0x31,0xf9,0xd7,0x7f,0x16,0x79,0x9a,0xaf,0xb7,0xd2,0x35,0x23,0xa8,0xbb,0xf7,0x29,0x0d,0x81,0xde,0x89,0xc4,0x31,0x1f,0x85,0x4f,0x01,0x20, 0x02,0x57,0x43,0xa3,0xac,0x62,0x74,0x2d,0x75,0xf3,0x16,0x47,0x7a,0xf0,0x77,0xe8,0x08,0x01,0xa9,0xfb,0x11,0x0a,0x48,0x24,0x8e,0x79,0x0d,0x80,0x28,0x4b,0x24,0x18,0x7e,0xea,0x67,0x39,0xe2,0x91,0x65,0x54,0xec,0x7f,0xb0,0x74,0x35,0xbd,0xa6,0x21,0xd0,0x2b,0x91,0x38,0xe6,0x35,0x00,0x22,0x2a,0x35,0x78,0x28,0x87,0xdd,0xf2,0x10, 0x13,0x7e,0xfa,0x20,0xa9,0x41,0x43,0xa4,0xcb,0xc9,0x9b,0x86,0xc0,0x3e,0x45,0xe2,0x98,0x8f,0x4a,0x00,0x44,0xe2,0x7c,0x28,0x2a,0x86,0xce,0x38,0x9b,0xa3,0xe7,0xbf,0xcc,0xb0,0x19,0x9f,0x92,0x2e,0xc5,0x17,0x0d,0x81,0x1e,0x45,0xe2,0x98,0x8f,0x4a,0x00,0xec,0x2f,0x5d,0x80,0xb4,0x44,0x32,0x49,0xcd,0xf4,0x33,0xa8,0x9b,0xb7,0x98, 0xc3,0x7f,0xf6,0x5b,0x52,0x83,0x87,0x4a,0x97,0x64,0x84,0x86,0x40,0xb7,0x22,0x71,0xcc,0x8b,0x7f,0x0c,0xe8,0x58,0x5c,0x83,0xd0,0x1e,0x81,0x51,0x90,0x2c,0x2b,0x67,0xc4,0x99,0x33,0x39,0xe0,0xe2,0xab,0xe9,0x77,0x90,0x25,0x5d,0x4e,0x60,0xf4,0x23,0xc2,0x2e,0x5d,0x93,0xdb,0x19,0x4b,0x8c,0x68,0x00,0x38,0x16,0xd7,0x21,0xb0,0x37, 0xa0,0xb4,0x54,0x75,0x0d,0xd5,0x47,0x9d,0xc8,0xe0,0x63,0x3f,0x4a,0xcd,0x47,0xcf,0x14,0x7b,0x88,0x27,0x6c,0x1a,0x02,0x5d,0xba,0x2e,0xb7,0x47,0xa6,0x08,0xb1,0x00,0x70,0x2c,0x66,0x03,0x32,0x4b,0xd6,0x98,0x92,0x48,0xf4,0xfa,0x21,0x98,0x44,0x49,0x09,0x55,0xe3,0xeb,0xa8,0x3e,0xf6,0xa3,0x54,0x1d,0x3a,0xd9,0xfb,0xd9,0x8e,0x36, 0xf6,0xfc,0xde,0xae,0xfe,0x5a,0xba,0xf8,0x3e,0x12,0x09,0x12,0x25,0x25,0x24,0x52,0x69,0x92,0xa5,0x29,0xef,0x6b,0x2a,0x9d,0xfb,0xba,0xc7,0xbf,0xef,0xf1,0xff,0x25,0x96,0x09,0x03,0x0d,0x81,0x6e,0xcc,0x96,0xda,0x21,0x58,0x24,0x00,0x1c,0x8b,0x9b,0x80,0xab,0x25,0xfa,0x56,0x9e,0x44,0x32,0x49,0xa2,0x53,0x28,0x54,0x1f,0x3d,0x9d, 0x09,0x3f,0x99,0x47,0xa2,0x24,0xf8,0x7b,0xc3,0x34,0x04,0xba,0x74,0x93,0xed,0x12,0xfa,0x93,0x5d,0xa1,0x07,0x80,0x63,0x71,0x0b,0x70,0x45,0xd8,0xfd,0xaa,0x7d,0xab,0xb1,0x3f,0xc1,0xe1,0xb7,0xfe,0x56,0x43,0x40,0xce,0x2d,0xb6,0xcb,0xd7,0xc2,0xec,0x30,0xb4,0x00,0x70,0x2c,0x12,0xc0,0xcf,0x81,0x2f,0x85,0xd5,0xa7,0xca,0x9f,0x86, 0x80,0xb8,0x5f,0x00,0x5f,0xb1,0xdd,0x7c,0x9f,0x11,0xed,0x9b,0x50,0x02,0xc0,0xb1,0x48,0x02,0xbf,0x04,0x2e,0x0d,0xa3,0x3f,0xe5,0x8f,0x86,0x80,0xb8,0x3b,0x80,0xcb,0xc2,0x08,0x81,0xc0,0x03,0x20,0x37,0xf8,0xef,0x02,0x2e,0x0c,0xba,0x2f,0x65,0x8e,0x86,0x80,0xb8,0xb9,0xc0,0x25,0xb6,0x4b,0xfe,0x9b,0x42,0xe4,0x21,0xd0,0x00,0x70, 0x2c,0x4a,0x80,0xbb,0x81,0xf3,0x83,0xec,0x47,0x05,0x43,0x43,0x40,0xdc,0xfd,0xc0,0x85,0xb6,0x4b,0x60,0x1b,0x58,0x06,0x16,0x00,0x8e,0x45,0x29,0xde,0x2f,0x10,0x8d,0x65,0x6b,0x54,0x9f,0x68,0x08,0x88,0xfb,0x0d,0x70,0x81,0xed,0xd2,0x16,0x44,0xe3,0x81,0x04,0x80,0x63,0x91,0x02,0x1e,0x04,0x3e,0x19,0x44,0xfb,0x2a,0x5c,0x1a,0x02, 0xe2,0x1e,0x01,0xce,0xb5,0x5d,0x8c,0x6f,0x5a,0x61,0x3c,0x00,0x1c,0x8b,0x34,0xf0,0x30,0x70,0x86,0xe9,0xb6,0x95,0x1c,0x0d,0x01,0x71,0x8f,0x02,0x9f,0xb1,0x5d,0x8c,0x6e,0x5a,0x61,0x34,0x00,0x1c,0x8b,0x32,0xe0,0x77,0xc0,0xa9,0x26,0xdb,0x55,0xd1,0xa0,0x21,0x20,0x6e,0x3e,0x70,0xb6,0xed,0xd2,0x6c,0xaa,0x41,0x63,0x01,0x90,0xdb, 0xe4,0xf3,0xf7,0xc0,0xc7,0x4c,0xb5,0xa9,0xa2,0x47,0x43,0x40,0xdc,0x42,0xe0,0x4c,0xdb,0x65,0xa7,0x89,0xc6,0x8c,0x04,0x80,0x63,0xd1,0x0f,0xf8,0x03,0x30,0xdd,0x44,0x7b,0x2a,0xda,0x34,0x04,0xc4,0x3d,0x09,0x9c,0x6e,0xbb,0xf8,0xde,0xbe,0xca,0x77,0x00,0x38,0x16,0x95,0x78,0x53,0x93,0x68,0xad,0x53,0xad,0x02,0xa5,0x21,0x20,0x6e, 0x11,0xf0,0x71,0xdb,0xc5,0xd7,0xbe,0xf6,0xbe,0x02,0xc0,0xb1,0x18,0x00,0xfc,0x09,0x38,0xd6,0x4f,0x3b,0xaa,0x30,0x69,0x08,0x88,0x5b,0x02,0x9c,0x62,0xbb,0x6c,0xeb,0x6b,0x03,0x7d,0x0e,0x00,0xc7,0x62,0x20,0xf0,0x04,0x70,0x54,0x5f,0xdb,0x50,0x85,0x4f,0x43,0x40,0xdc,0x3f,0x80,0x19,0xb6,0xcb,0x96,0xbe,0xfc,0xb0,0x9f,0x25,0xc1, 0xc6,0xa0,0x83,0x3f,0xf6,0x36,0x3a,0x8f,0xf2,0xd2,0x57,0x3f,0x45,0xb6,0x3d,0x90,0xfb,0x54,0x3e,0x40,0x97,0x17,0xeb,0xd2,0x51,0x78,0x63,0xb1,0x4f,0xfc,0x9e,0x02,0xb8,0xc0,0x58,0x3f,0x6d,0xa8,0xe2,0xa0,0x33,0x01,0x31,0xae,0xed,0x32,0xae,0xaf,0x3f,0xec,0x77,0x51,0xd0,0xdf,0xf8,0xfc,0x79,0x55,0x24,0x74,0x26,0x20,0xc6,0xd7, 0x18,0xf4,0x1b,0x00,0x0f,0xf8,0xfc,0x79,0x55,0x44,0x34,0x04,0x44,0xf8,0x1a,0x83,0xbe,0x02,0xc0,0x76,0xf9,0x3f,0xe0,0x5f,0x7e,0xda,0x50,0xc5,0x25,0xec,0x10,0x18,0x79,0x56,0xac,0x9f,0x32,0x7f,0xc9,0x76,0x59,0xe9,0xa7,0x01,0x13,0xfb,0x02,0x3c,0x68,0xa0,0x0d,0x55,0x44,0xc2,0x0c,0x81,0x4c,0xab,0xd1,0x5b,0xe3,0x0b,0x8d,0xef, 0xb1,0xa7,0x01,0xa0,0x02,0x11,0x56,0x08,0x64,0x35,0x00,0x7c,0xf1,0x1d,0x00,0xb6,0xcb,0xeb,0xc0,0x3f,0xfd,0xb6,0xa3,0x8a,0x4f,0x18,0x21,0x10,0xe3,0x19,0xc0,0x32,0xdb,0xe5,0x0d,0xbf,0x8d,0x98,0xda,0x1a,0x4c,0x67,0x01,0xaa,0x4b,0x41,0x87,0x40,0xb6,0xd5,0xf8,0x23,0xf2,0x85,0xc2,0xc8,0x98,0x33,0x15,0x00,0xbf,0x81,0x70,0x56, 0x31,0x55,0x85,0x27,0xc8,0x10,0x88,0xe9,0x0c,0x20,0x8b,0xa1,0x8f,0xe0,0x8d,0x04,0x80,0xed,0xf2,0x2e,0xde,0x7d,0xc9,0x4a,0x75,0x29,0xa8,0x10,0x88,0xe9,0x35,0x80,0x67,0x6c,0x97,0x35,0x26,0x1a,0x32,0xb9,0x3b,0xb0,0x9e,0x06,0xa8,0x1e,0x05,0x11,0x02,0x31,0x9d,0x01,0x18,0x1b,0x6b,0x26,0x03,0xe0,0x61,0x08,0x6e,0xf5,0x52,0x55, 0x1c,0x4c,0x87,0x40,0xb6,0x2d,0x76,0xd7,0x00,0xda,0xf1,0xc6,0x9a,0x11,0xc6,0x02,0xc0,0x76,0xd9,0x00,0x3c,0x65,0xaa,0x3d,0x55,0xbc,0x4c,0x86,0x40,0x0c,0x67,0x00,0x4f,0xda,0x2e,0xf5,0xa6,0x1a,0x33,0x39,0x03,0x00,0xb8,0xd3,0x70,0x7b,0xaa,0x48,0x99,0x0a,0x81,0x18,0x5e,0x03,0xb8,0xcb,0x64,0x63,0xa6,0x03,0xe0,0x21,0xe0,0x55, 0xc3,0x6d,0xaa,0x22,0x65,0x22,0x04,0x32,0x2d,0xb1,0x0a,0x80,0x57,0xf1,0xc6,0x98,0x31,0x46,0x03,0x20,0xb7,0x8d,0xd1,0x2c,0x93,0x6d,0xaa,0xe2,0xe6,0x37,0x04,0x62,0x76,0x0d,0xe0,0x7a,0xd3,0x5b,0x85,0x99,0x9e,0x01,0x00,0xcc,0x03,0x56,0x05,0xd0,0xae,0x2a,0x52,0x7e,0x42,0x20,0x46,0xa7,0x00,0xab,0x08,0xe0,0xe9,0x5b,0xe3,0x01, 0x90,0xdb,0xc7,0x4c,0x67,0x01,0x2a,0x2f,0x7d,0x0d,0x81,0x18,0x5d,0x04,0xbc,0x3e,0x88,0x3d,0x02,0x83,0x98,0x01,0x80,0xb7,0x27,0xe0,0xeb,0x01,0xb5,0xad,0x8a,0x54,0x5f,0x42,0x20,0x26,0x01,0xf0,0x3a,0xde,0x98,0x32,0x2e,0x90,0x00,0xc8,0x6d,0x64,0x38,0x3b,0x88,0xb6,0x55,0x71,0xcb,0x37,0x04,0x62,0x72,0x0a,0x30,0x2b,0xa8,0x1d, 0x82,0x83,0x9a,0x01,0x00,0xdc,0x03,0xac,0x0e,0xb0,0x7d,0x55,0xa4,0xf2,0x09,0x81,0x18,0x3c,0x0c,0xf4,0x06,0x70,0x6f,0x50,0x8d,0x07,0x16,0x00,0x3a,0x0b,0x50,0x7e,0xf4,0x36,0x04,0x62,0x70,0x0a,0x30,0x3b,0xa8,0xad,0xc1,0x21,0xd8,0x19,0x00,0xc0,0xdd,0xc0,0x5b,0x01,0xf7,0xa1,0x8a,0x54,0x6f,0x42,0xa0,0xc8,0x03,0xe0,0x4d,0xbc, 0x99,0x74,0x60,0x02,0x0d,0x80,0xdc,0x7e,0xe6,0x37,0x04,0xd9,0x87,0x2a,0x6e,0xfb,0x0a,0x81,0x22,0xbf,0x06,0x70,0x43,0x6e,0x0c,0x05,0x26,0xe8,0x19,0x00,0xc0,0xaf,0x81,0x77,0x42,0xe8,0x47,0x15,0xa9,0x9e,0x42,0xa0,0x88,0x6f,0x04,0x7a,0x1b,0x6f,0xec,0x04,0x2a,0xf0,0x00,0xb0,0x5d,0x5a,0x80,0x39,0x41,0xf7,0xa3,0x8a,0x5b,0x77, 0x21,0x50,0xc4,0xa7,0x00,0x73,0x82,0x7e,0xf7,0x87,0x70,0x66,0x00,0xe0,0x3d,0x24,0xa4,0xb3,0x00,0xe5,0x4b,0x57,0x21,0x50,0xa4,0x33,0x80,0x77,0x08,0xe9,0xc1,0xba,0x50,0x02,0xc0,0x76,0x69,0x06,0xbe,0x1c,0x46,0x5f,0xaa,0xb8,0x75,0x0e,0x81,0x6c,0x7b,0x3b,0xd9,0xf6,0xa2,0x5c,0x82,0xe2,0x4b,0xb9,0x99,0x73,0xe0,0xc2,0x9a,0x01, 0x60,0xbb,0x3c,0x4e,0x80,0x9f,0x67,0xaa,0xf8,0xe8,0x08,0x81,0xf6,0x9d,0x3b,0xa4,0x4b,0x09,0xc2,0x3d,0xb6,0xcb,0xfc,0xb0,0x3a,0xf3,0xb5,0x39,0x68,0xbe,0x1c,0x8b,0x6a,0xe0,0x65,0x60,0x64,0x98,0xfd,0xaa,0xe2,0x34,0xf8,0xb8,0x93,0xd8,0xbc,0xe4,0xcf,0xd2,0x65,0x98,0xb4,0x16,0x98,0x60,0xbb,0x34,0x86,0xd5,0x61,0xa8,0x01,0x00, 0xe0,0x58,0x9c,0x06,0xfc,0x21,0xec,0x7e,0x95,0x2a,0x00,0xa7,0xe7,0x66,0xca,0xa1,0x09,0xed,0x14,0xa0,0x83,0x9e,0x0a,0x28,0xd5,0xa5,0x7b,0xc2,0x1e,0xfc,0x20,0x10,0x00,0x39,0x57,0x02,0xef,0x09,0xf5,0xad,0x54,0xd4,0xac,0xc5,0x1b,0x13,0xa1,0x13,0x09,0x00,0xdb,0xa5,0x01,0xf8,0x82,0x44,0xdf,0x4a,0x45,0xd0,0x65,0x61,0x9e,0xf7, 0x77,0x26,0x35,0x03,0xd0,0x53,0x01,0xa5,0x3c,0x22,0x53,0xff,0x0e,0x62,0x01,0x90,0xa3,0xa7,0x02,0x2a,0xce,0xc4,0xa6,0xfe,0x1d,0x44,0x03,0x20,0x77,0x2a,0x70,0x99,0x64,0x0d,0x4a,0x09,0x12,0x9b,0xfa,0x77,0x90,0x9e,0x01,0x60,0xbb,0xfc,0x01,0xb8,0x4f,0xba,0x0e,0xa5,0x42,0x76,0xaf,0xe4,0xd4,0xbf,0x83,0x78,0x00,0xe4,0x5c,0x81, 0x9e,0x0a,0xa8,0xf8,0x78,0x0f,0xe1,0xa9,0x7f,0x87,0x48,0x04,0x40,0xee,0x54,0x60,0x26,0x04,0xb7,0xf2,0x89,0x52,0x11,0xd1,0x06,0xcc,0xcc,0x1d,0xf3,0xe2,0x22,0x11,0x00,0x00,0xb6,0xcb,0x5f,0x80,0x2f,0x49,0xd7,0xa1,0x54,0xc0,0xbe,0x98,0x3b,0xd6,0x23,0x21,0x32,0x01,0x00,0x60,0xbb,0xfc,0x0a,0x5d,0x47,0x50,0x15,0xaf,0x59,0xb6, 0x1b,0xad,0xfd,0x33,0x23,0x15,0x00,0x39,0xdf,0xc7,0xdb,0x5d,0x48,0xa9,0x62,0x72,0xbf,0xed,0xf2,0x7d,0xe9,0x22,0xf6,0x14,0xb9,0x00,0xb0,0x5d,0xb2,0xc0,0xc5,0xc0,0x22,0xa1,0x12,0xb6,0x00,0xbf,0x03,0x5e,0x10,0xea,0x5f,0x99,0xf7,0x02,0xde,0xdf,0xe9,0x16,0xa1,0xfe,0xff,0x8a,0x77,0x4c,0x47,0x4e,0xe4,0x02,0x00,0xde,0x5f,0x40, 0xe4,0x4c,0xe0,0x95,0x10,0xba,0xcb,0x02,0xff,0xc4,0xdb,0xce,0xec,0x78,0xa0,0xc6,0x76,0x39,0x1b,0x98,0x06,0x5c,0x0b,0xc1,0x2f,0xcb,0xa4,0x02,0xd3,0x0a,0xfc,0x10,0x38,0x32,0xf7,0x77,0x5a,0x83,0xf7,0x77,0x3c,0x0b,0xef,0xef,0x3c,0x1b,0x42,0x0d,0xaf,0x00,0x67,0x85,0xb5,0xc0,0x47,0xbe,0x42,0x7f,0x1c,0x38,0x1f,0x8e,0x45,0x2d, 0xb0,0x14,0x18,0x66,0xb8,0xe9,0xf5,0xc0,0x13,0xb9,0x3f,0x0b,0x6d,0x97,0x8d,0x3d,0xd4,0x30,0x19,0x98,0x0b,0x4c,0x32,0x5c,0x83,0x0a,0xd6,0x0b,0xc0,0x45,0xb6,0xcb,0x8b,0xdd,0x7d,0x83,0x63,0x31,0x14,0x38,0x09,0x38,0x19,0xf8,0x18,0x30,0xdc,0x70,0x0d,0xeb,0x81,0xa3,0x6d,0x97,0x37,0x0d,0xb7,0x6b,0x4c,0xa4,0x03,0x00,0xc0,0xb1, 0x98,0x06,0x3c,0x05,0xf4,0xf3,0xd1,0x4c,0x2b,0xb0,0x04,0x6f,0xc0,0x2f,0x00,0x5e,0xcc,0x9d,0x6a,0xf4,0xb6,0x86,0x14,0xf0,0x3d,0xe0,0xbb,0x40,0xca,0x47,0x1d,0x2a,0x78,0xad,0x78,0xef,0xf0,0xb3,0xf3,0x59,0x54,0xd3,0xb1,0x48,0x00,0x93,0x81,0x19,0x78,0x81,0x70,0x2c,0xfe,0xfe,0xae,0x9b,0x80,0x13,0x6c,0x97,0x65,0x3e,0xda,0x08, 0x5c,0xe4,0x03,0x00,0xc0,0xb1,0xf8,0x04,0xde,0x39,0x5c,0x3e,0xa7,0x2c,0x6f,0xb0,0x7b,0xc0,0x3f,0x65,0xbb,0x6c,0x33,0x50,0xc7,0x64,0xbc,0xcd,0x4e,0x26,0xfa,0x6d,0x4b,0x05,0xe2,0x45,0xbc,0x77,0x7d,0xdf,0xd7,0x6f,0x1c,0x8b,0x2a,0x60,0x3a,0x5e,0x20,0xcc,0x00,0x0e,0xce,0xe3,0xc7,0x33,0x78,0xd3,0xfe,0xc7,0xfc,0xd6,0x11,0xb4, 0x82,0x08,0x00,0x00,0xc7,0xe2,0x4a,0xe0,0xe6,0x1e,0xbe,0x65,0x07,0xf0,0x34,0xde,0x80,0x7f,0xc2,0x76,0x59,0x15,0x50,0x1d,0x29,0xbc,0x4f,0x2a,0xbe,0x0b,0x94,0x06,0xd1,0x87,0xca,0x5b,0xc7,0x36,0x74,0xd7,0x07,0xb5,0x94,0xb6,0x63,0x31,0x96,0xdd,0xb3,0x83,0x13,0x80,0xfe,0x3d,0x7c,0xfb,0x15,0xb6,0xcb,0xad,0x41,0xd4,0x61,0x5a, 0xc1,0x04,0x00,0x80,0x63,0x71,0x33,0x1f,0xbc,0x85,0xf2,0x25,0x72,0x03,0x1e,0x58,0x1c,0xe6,0x85,0x16,0xc7,0xa2,0x0e,0xef,0xda,0xc0,0xe1,0x61,0xf5,0xa9,0xba,0xb4,0x02,0xef,0x5d,0xff,0xf9,0xb0,0x3a,0x74,0x2c,0xd2,0x78,0x17,0x13,0x3b,0x02,0xa1,0xf3,0x31,0x70,0xb3,0xed,0x72,0x55,0x58,0xb5,0xf8,0x55,0x68,0x01,0x90,0xc4,0xbb, 0x32,0xbf,0x1a,0xef,0x5d,0x7e,0xad,0x70,0x3d,0x69,0xe0,0x9b,0xc0,0xd5,0x40,0xb5,0x64,0x2d,0x31,0xd4,0x00,0xdc,0x04,0xdc,0x18,0xc6,0x06,0x1a,0x3d,0x71,0x2c,0x46,0xe1,0x85,0x41,0x2d,0x70,0xad,0xed,0x92,0x91,0xac,0x27,0x1f,0x05,0x15,0x00,0x51,0xe5,0x58,0x0c,0x00,0xbe,0x0a,0x5c,0x05,0x0c,0x11,0x2e,0xa7,0xd8,0x6d,0x02,0x7e, 0x0a,0xdc,0x6a,0xbb,0x6c,0x95,0x2e,0xa6,0xd0,0x69,0x00,0x18,0xe4,0x58,0x54,0x02,0x97,0xe3,0xcd,0x08,0x86,0x0a,0x97,0x53,0x6c,0xea,0x81,0x1f,0x03,0x3f,0xb7,0x5d,0xb6,0x4b,0x17,0x53,0x2c,0x34,0x00,0x02,0xe0,0x58,0xf4,0xc7,0x7b,0xb0,0xe9,0x1b,0x98,0xff,0x6c,0x39,0x6e,0xd6,0x03,0x37,0x02,0xb7,0xd9,0x2e,0x4d,0xd2,0xc5,0x14, 0x1b,0x0d,0x80,0x00,0x39,0x16,0x15,0x78,0x2b,0x1e,0x7d,0x0b,0xdd,0x0c,0x25,0x5f,0xef,0x01,0xff,0x0d,0xfc,0xd2,0x76,0xd9,0x29,0x5d,0x4c,0xb1,0xd2,0x00,0x08,0x81,0x63,0x51,0x0e,0xfc,0x3b,0xf0,0x6d,0x60,0x3f,0xe1,0x72,0xa2,0x6e,0x0d,0xde,0x6e,0xd2,0xbf,0xb2,0x5d,0x76,0x49,0x17,0x53,0xec,0x34,0x00,0x42,0xe4,0x58,0x7c,0x1c, 0xe4,0x97,0x81,0x8a,0xb8,0x8f,0xdb,0x2e,0x7f,0x94,0x2e,0x22,0x2e,0x22,0xf9,0x30,0x50,0x11,0x5b,0x84,0xae,0x7a,0xd4,0x93,0x36,0x60,0xb1,0x74,0x11,0x71,0xa2,0x01,0x10,0xa2,0xdc,0xed,0xc8,0xcf,0x49,0xd7,0x11,0x61,0xff,0x34,0x71,0xcb,0xb6,0xea,0x3d,0x0d,0x80,0xf0,0x3d,0x29,0x5d,0x40,0x84,0xe9,0x6b,0x13,0x32,0x0d,0x80,0xf0, 0xe9,0x41,0xde,0x3d,0x7d,0x6d,0x42,0xa6,0x01,0x10,0xbe,0x25,0x10,0xcd,0xc5,0x21,0x84,0x35,0x03,0x7f,0x93,0x2e,0x22,0x6e,0x34,0x00,0x42,0x96,0xfb,0x4c,0x7b,0xa9,0x74,0x1d,0x11,0xb4,0x54,0x3f,0xef,0x0f,0x9f,0x06,0x80,0x0c,0x9d,0xea,0xee,0x4d,0x5f,0x13,0x01,0x1a,0x00,0x32,0xf4,0x60,0xdf,0x9b,0xbe,0x26,0x02,0x34,0x00,0x64, 0xfc,0x03,0xf4,0xbe,0xf6,0x4e,0x9a,0xf0,0x5e,0x13,0x15,0x32,0x0d,0x00,0x01,0xb9,0x85,0x4b,0x96,0x48,0xd7,0x11,0x21,0xcf,0x48,0x3f,0xd3,0x1f,0x57,0x1a,0x00,0x72,0x74,0xca,0xbb,0x9b,0xbe,0x16,0x42,0x34,0x00,0xe4,0xe8,0x41,0xbf,0x9b,0xbe,0x16,0x42,0x34,0x00,0xe4,0x3c,0x07,0xba,0xa2,0x0d,0xde,0x6e,0x3d,0xcb,0xa5,0x8b,0x88, 0x2b,0x0d,0x00,0x21,0xb6,0x4b,0x3b,0x72,0xdb,0x9f,0x45,0xc9,0xa2,0xdc,0x6b,0xa1,0x04,0x68,0x00,0xc8,0xd2,0xa9,0xaf,0xbe,0x06,0xa2,0x34,0x00,0x64,0xe9,0xc1,0xaf,0xaf,0x81,0x28,0x0d,0x00,0x59,0x2b,0xf0,0x56,0xb9,0x8d,0xab,0x8d,0x78,0x7b,0x3b,0x28,0x21,0x1a,0x00,0x82,0x72,0xfb,0x13,0x3e,0x2d,0x5d,0x87,0xa0,0xa7,0xf3,0xd9, 0xa3,0x51,0x99,0xa7,0x01,0x20,0x2f,0xce,0x53,0xe0,0x38,0xff,0xee,0x91,0xa0,0x01,0x20,0x2f,0xce,0x83,0x20,0xce,0xbf,0x7b,0x24,0xe8,0xa2,0xa0,0x11,0xe0,0x58,0xac,0x25,0x7e,0xcb,0x86,0xaf,0xb5,0x5d,0x5d,0x21,0x59,0x9a,0xce,0x00,0xa2,0xe1,0x29,0xe9,0x02,0x04,0xc4,0xf1,0x77,0x8e,0x1c,0x0d,0x80,0x68,0x88,0xe3,0x54,0x38,0x8e, 0xbf,0x73,0xe4,0x68,0x00,0x44,0x43,0x1c,0x07,0x83,0x23,0x5d,0x80,0xd2,0x00,0x88,0x04,0xdb,0x65,0x35,0xf0,0x28,0xde,0x7d,0xf1,0xc5,0xae,0x11,0x78,0xd4,0x76,0x79,0x4b,0xba,0x10,0xa5,0x17,0x01,0x23,0xc5,0xb1,0x48,0xe0,0xed,0x31,0x5f,0xb7,0xc7,0x9f,0x42,0xdd,0x69,0x78,0x03,0xf0,0x3c,0xde,0xc3,0x3e,0xcb,0x81,0xe5,0xb6,0xcb, 0x1b,0xb2,0x25,0xa9,0xce,0x34,0x00,0x0a,0x80,0x63,0x31,0x1a,0x2f,0x08,0xa6,0xb0,0x3b,0x14,0x46,0x8b,0x16,0xb5,0xb7,0x77,0xe9,0x34,0xd0,0xf1,0x06,0xfb,0x1a,0xd9,0x92,0xd4,0xbe,0x68,0x00,0x14,0x28,0xc7,0x62,0x28,0xbb,0xc3,0xa0,0x16,0x18,0x94,0xfb,0x53,0xdd,0xe9,0xeb,0x40,0xa0,0xd4,0x67,0x57,0x6d,0x78,0xa7,0x26,0x0d,0x78, 0xd3,0xf7,0x8e,0xaf,0x8d,0xc0,0x6a,0x76,0x0f,0xf6,0x7a,0x9f,0xfd,0x28,0x01,0x1a,0x00,0x45,0xce,0xb1,0xa8,0xe4,0x83,0xa1,0xb0,0x67,0x50,0xc0,0xde,0x03,0xfb,0xfd,0xc1,0x6e,0xbb,0x6c,0x0f,0xbb,0x66,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29,0xa5,0x94,0x52,0x4a,0x29, 0xd5,0x1b,0xff,0x0f,0x5c,0x56,0xd9,0x0b,0x64,0x90,0x3b,0x82,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; read_only global String8 rd_icon_file_bytes = {rd_icon_file_bytes__data, sizeof(rd_icon_file_bytes__data)}; C_LINKAGE_END #endif // RADDBG_META_H ================================================ FILE: src/raddbg/raddbg.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Embedded Data @embed_file rd_icon_font_bytes: "../data/icons.ttf" //@embed_file rd_default_main_font_bytes: "../data/Roboto-Regular.ttf" @embed_file rd_default_main_font_bytes: "../data/segoeui.ttf" //@embed_file rd_default_main_font_bytes: "../data/seguisb.ttf" //@embed_file rd_default_code_font_bytes: "../data/liberation-.ttf" //@embed_file rd_default_code_font_bytes: "../data/Inconsolata-Regular.ttf" @embed_file rd_default_code_font_bytes: "../data/JetBrainsMono-Regular.ttf" @embed_file rd_icon_file_bytes: "../data/logo.ico" //////////////////////////////// //~ rjf: Fixed Tab Tables @table(name display_name name_lower is_query icon description) RD_WatchTabFastPathTable: { {Watch "Watch" watches 0 Binoculars "An editable table interface for entering one or many expressions to evaluate, and visualizing and exploring their values."} {Locals "Locals" locals 1 Binoculars "Like the Watch tab, but not editable, and displays the set of local variables found at the selected thread's current location."} {Registers "Registers" registers 1 Binoculars "Like the Watch tab, but not editable, and displays the set of registers for the selected thread."} {Globals "Globals" globals 1 Binoculars "Like the Watch tab, but not editable, and displays all global variables from all loaded modules."} {ThreadLocals "Thread Locals" thread_locals 1 Binoculars "Like the Watch tab, but not editable, and displays all thread-local variables from all loaded modules."} {Types "Types" types 1 Binoculars "Like the Watch tab, but not editable, and displays all types from all loaded modules."} {Procedures "Procedures" procedures 1 Binoculars "Like the Watch tab, but not editable, and displays all procedures from all loaded modules."} {CallStack "Call Stack" call_stack 1 Thread "Displays the currently selected thread's call stack, and allows selecting a frame in the call stack, which will unwind the selected thread's registers and evaluate expressions within that frame's context."} {Targets "Targets" targets 1 Target "Displays, and allows editing of, the list of all targets."} {Breakpoints "Breakpoints" breakpoints 1 CircleFilled "Displays, and allows editing of, the list of all breakpoints."} {WatchPins "Watch Pins" watch_pins 1 Pin "Displays, and allows editing of, the list of all watch pins."} {DebugInfos "Debug Info" debug_infos 1 Module "Displays, and allows editing of, the list of all debug info files that the debugger has loaded."} {Threads "Threads" threads 1 Threads "Displays the list of all threads in all processes to which the debugger is attached."} {Processes "Processes" processes 1 Scheduler "Displays the list of all processes to which the debugger is attached."} {Machines "Machines" machines 1 Machine "Displays the list of all machines to which the debugger is connected."} {Modules "Modules" modules 1 Module "Displays the list of all modules in all processes to which the debugger is attached."} {FilePathMaps "File Path Map" file_path_maps 1 FileOutline "Displays, and allows editing of, the list of all file path maps. This allows remapping source code paths referenced by debug information to other paths on your local machine."} {TypeViews "Type Views" type_views 1 Binoculars "Displays, and allows editing of, the list of all type views, which allow automatically adjusting the visualizations for evaluations of a certain type."} } @table(name display_name name_lower view query icon) RD_ViewTabFastPathTable: { {Output "Output" output text "query:output" List } {Text "Text" text text "" FileOutline } {Disasm "Disassembly" disasm disasm "" Glasses } {Memory "Memory" memory memory "" Grid } {Bitmap "Bitmap" bitmap bitmap "" Bitmap } {Color "Color" color color "" Palette } {Geo3D "Geometry (3D)" geo3d geo3d "" Cube } } @table(name display_name name_lower icon) RD_FixedTabTable: { {GettingStarted "Getting Started" getting_started "getting_started" QuestionMark } } @gen { `#define RD_FixedTabXList \\`; @expand(RD_WatchTabFastPathTable a) `$(a.is_query -> 'X(' .. a.name_lower .. ')') $(a.is_query == 0 -> 'Y(' .. a.name_lower .. ', watch, ""' .. ')')\\`; @expand(RD_ViewTabFastPathTable a) `Y($(a.name_lower), $(a.view), "$(a.query)")\\`; @expand(RD_FixedTabTable a) `Z($(a.name_lower))\\`; ``; } @data(String8) rd_tab_fast_path_view_name_table: { @expand(RD_WatchTabFastPathTable a) `str8_lit_comp("watch")`, @expand(RD_ViewTabFastPathTable a) `str8_lit_comp("$(a.view)")`, } @data(String8) rd_tab_fast_path_query_name_table: { @expand(RD_WatchTabFastPathTable a) `str8_lit_comp("$(a.is_query -> 'query:' .. a.name_lower)")`, @expand(RD_ViewTabFastPathTable a) `str8_lit_comp("$(a.query)")`, } //////////////////////////////// //~ rjf: Vocabulary Map @table(code_name code_name_plural display_name display_name_plural icon_kind) RD_VocabTable: // NOTE(rjf): the _ character is used as a fastpath for default rules. when // pluralizing, you just append an `s`, and so on. { {type_view _ "Type View" _ Binoculars } {file_path_map _ "File Path Map" _ FileOutline } {watch_pin _ "Watch Pin" _ Pin } {debug_info _ "Debug Info" "Debug Info" Module } {watch watches "Watch" "Watches" Binoculars } {view _ "View" _ Binoculars } {breakpoint _ "Breakpoint" _ CircleFilled } {condition _ "Condition" _ Null } {location _ "Location" _ Null } {source_location _ "Source Location" _ Null } {address_location _ "Address Location" _ Null } {target _ "Target" _ Target } {color _ "Color" _ Palette } {theme_color _ "Theme Color" _ Palette } {executable _ "Executable" _ Module } {arguments arguments "Arguments" "Arguments" Null } {exe exes "Executable" _ Module } {dbg dbgs "Debug Info Path" _ Module } {vaddr_range _ "Virtual Address Range" _ Null } {min _ "Minimum" _ Null } {max _ "Maximum" _ Null } {working_directory working_directories "Working Directory" "Working Directories" FolderClosedFilled } {entry_point _ "Entry Point" _ Null } {stdout_path _ "Standard Output Path" _ Null } {stderr_path _ "Standard Error Path" _ Null } {stdin_path _ "Standard Input Path" _ Null } {window _ "Window" _ Window } {panel _ "Panel" _ Null } {tab _ "Tab" _ Null } {recent_project _ "Recent Project" _ Briefcase } {recent_file _ "Recent File" _ FileOutline } {src _ "Source" _ Null } {dst _ "Destination" _ Null } {source _ "Source" _ Null } {dest _ "Destination" _ Null } {conversion_task _ "Conversion Task" _ Null } {conversion_fail _ "Conversion Fail" _ Null } {lang _ "Language" _ Null } {arch _ "Architecture" _ Null } {expr _ "Expression" _ Null } {expression _ "Expression" _ Null } {size _ "Size" _ Null } {count _ "Count" _ Null } {bool _ "Boolean" _ Null } {w _ "Width" _ Null } {h _ "Height" _ Null } {fmt _ "Format" _ Null } {addresses addresses "Addresses" "Addresses" Null } {code_bytes code_bytes "Code Bytes" "Code Bytes" Null } {vtx _ "Vertex Buffer" _ Null } {vtx_size _ "Vertex Buffer Size" _ Null } {label _ "Label" _ Null } {thread _ "Thread" _ Thread } {threads "" "Threads" "" Threads } {process processes "Process" "Processes" Scheduler } {processes "" "Processes" "" Scheduler } {machine _ "Machine" _ Machine } {module _ "Module" _ Module } {getting_started "" "Getting Started" "" QuestionMark } {disasm "" "Disassembly" "" Glasses } {text "" "Text" "" FileOutline } {type _ "Type" _ Null } {procedure _ "Procedure" _ Null } {global_variable _ "Global Variable" _ Null } {global _ "Global" _ Null } {thread_variable _ "Thread Variable" _ Null } {thread_local _ "Thread Local" _ Null } {call_stack _ "Call Stack" _ Thread } {output _ "Output" _ List } {scheduler _ "Scheduler" _ Scheduler } {register _ "Register" _ Null } {local _ "Local" _ Null } {memory memories "Memory" "Memories" Grid } {hit_count hit_counts "Hit Count" "Hit Counts" Null } {enabled "" "Enabled" "Enabled" Null } {disabled "" "Disabled" "Disabled" Null } {debug_subprocesses "" "Debug Subprocesses" "" Null } {environment _ "Environment" _ Null } {frozen "" "Frozen" "" Null } {id _ "ID" _ Null } {last_modified_time _ "Last Modified Time" _ Null } {creation_time _ "Creation Time" _ Null } {data _ "Data" _ Null } {unattached_processes "" "Unattached Processes" "" Scheduler } {user _ "User" _ Person } {project _ "Project" _ Briefcase } {recent_project _ "Recent Project" _ Briefcase } {recent_file _ "Recent File" _ FileOutline } {show_addresses "" "Show Addresses" "" Null } {show_code_bytes "" "Show Code Bytes" "" Null } {show_source_lines "" "Show Source Lines" "" Null } {show_symbol_names "" "Show Symbol Names" "" Null } {show_line_numbers "" "Show Line Numbers" "" Null } {syntax syntaxes "Syntax" "Syntaxes" Null } {num_columns "" "Number of Columns" "" Null } {bytes_per_cell "" "Bytes Per Cell" "" Null } {bitmap _ "Bitmap" _ Bitmap } {geo3d "" "Geometry (3D)" "" Cube } {address_range_size _ "Address Range Size" _ Null } {break_on_read "" "Break On Read" "" Null } {break_on_write "" "Break On Write" "" Null } {break_on_execute "" "Break On Execution" "" Null } {yaw "" "Yaw" "" Null } {pitch "" "Pitch" "" Null } {zoom "" "Zoom" "" Null } {font_size "" "Font Size" "" Null } {row_height "" "Row Height" "" Null } {tab_height "" "Tab Height" "" Null } {rgba "" "RGBA" "" Palette } {path "" "Path" "" FileOutline } {guid "" "GUID" "" Null } } @struct RD_VocabInfo: { `String8 code_name`; `String8 code_name_plural`; `String8 display_name`; `String8 display_name_plural`; `RD_IconKind icon_kind`; } @data(RD_VocabInfo) rd_vocab_info_table: { @expand(RD_VocabTable a) `{str8_lit_comp("$(a.code_name)"), str8_lit_comp("$(a.code_name_plural == _ -> a.code_name .. 's')$(a.code_name_plural != _ -> a.code_name_plural)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.display_name_plural == _ -> a.display_name .. 's')$(a.display_name_plural != _ -> a.display_name_plural)"), RD_IconKind_$(a.icon_kind)}`; @expand(D_CmdTable a) `{str8_lit_comp("$(a.string)"), str8_lit_comp(""), str8_lit_comp("$(a.display_name)"), str8_lit_comp(""), RD_IconKind_$(a.canonical_icon)}`; @expand(RD_CmdTable a) `{str8_lit_comp("$(a.string)"), str8_lit_comp(""), str8_lit_comp("$(a.display_name)"), str8_lit_comp(""), RD_IconKind_$(a.canonical_icon)}`; @expand(RD_WatchTabFastPathTable a) `{str8_lit_comp("$(a.name_lower)"), str8_lit_comp(""), str8_lit_comp("$(a.display_name)"), str8_lit_comp(""), RD_IconKind_$(a.icon)}`; @expand(RD_ViewTabFastPathTable a) `{str8_lit_comp("$(a.name_lower)"), str8_lit_comp(""), str8_lit_comp("$(a.display_name)"), str8_lit_comp(""), RD_IconKind_$(a.icon)}`; } //////////////////////////////// //~ rjf: Schemas @table(name schema) RD_SchemaTable: { //- rjf: users / projects { user ``` @expand_commands(edit_user_theme) x: { //- rjf: animations @display_name('Animations') @description("Enables animations.") @default(1) 'animations': bool, @display_name('Scrolling Animations') @description("Enables scrolling animations.") @expand_if("$.animations") @default(1) 'scrolling_animations': bool, @display_name('Tooltip Animations') @description("Enables tooltip animations.") @expand_if("$.animations") @default(1) 'tooltip_animations': bool, @display_name('Menu Animations') @description("Enables menu animations.") @expand_if("$.animations") @default(1) 'menu_animations': bool, //- rjf: fonts @display_name('UI Font') @description("The name of, or path to, the font used when displaying non-code UI elements.") @default('') 'main_font': string, @display_name('Code Font') @description("The name of, or path to, the font used when displaying code.") @default('') 'code_font': string, //- rjf: theme @default("Default (Dark)") @display_name('User Theme') @description("The user's theme, which describes all colors used throughout the UI.") 'theme': string, @no_expand @display_name('User Theme') 'theme_colors': query, //- rjf: autocompletion @display_name('Autocompletion Lister') @description("Enables the autocompletion lister while typing expressions.") @default(1) 'autocompletion_lister': bool, @display_name('View Call Argument Helper') @description("Enables the view call argument helper, which shows view arguments and documentation, while typing expressions.") @default(1) 'view_call_argument_helper': bool, //- rjf: scope decorations @default(1) @display_name('Cursor Scope Lines') @description("Controls whether or not scopes containing the cursor in text views are drawn.") 'cursor_scope_lines': bool, //- rjf: cursor decorations @default(1) @display_name('Cursor Trail') @description("Controls whether or not a movement trail of the cursor is drawn.") 'cursor_trail': bool, //- rjf: thread & breakpoint decorations @default(1) @display_name('Thread Lines') @description("Controls whether or not a long horizontal line is drawn before the next line or instruction that the selected thread will execute in source and disassembly views.") 'thread_lines': bool, @default(1) @display_name('Thread Glow') @description("Controls whether or not a glowing effect is drawn on the selected thread in source and disassembly views.") 'thread_glow': bool, @default(1) @display_name('Breakpoint Lines') @description("Controls whether or not a long horizontal line is drawn before the line or instruction at which a breakpoint is placed, in source and disassembly views.") 'breakpoint_lines': bool, @default(1) @display_name('Breakpoint Glow') @description("Controls whether or not a glowing effect is drawn on breakpoints in source and disassembly views.") 'breakpoint_glow': bool, //- rjf: occluding background settings @default(0) @display_name('Opaque Backgrounds') @description("Controls whether or not all floating background colors are forced to be fully opaque.") 'opaque_backgrounds': bool, @default(1) @display_name('Background Blur') @description("Controls whether or not occluded regions behind floating elements are blurred.") 'background_blur': bool, //- rjf: appearance settings @default(1) @display_name('Drop Shadows') @description("Controls whether or not drop shadows are drawn.") 'drop_shadows': bool, @default(1.f) @display_name('Rounded Corner Amount') @description("Controls the degree to which UI corners are rounded.") 'rounded_corner_amount': @range[0, 1] f32, //- rjf: code formatting settings @default(2) @display_name('User Tab Width') 'tab_width': @range[1, 32] u64, //- rjf: windows style menu bar @default(1) @display_name('Focus Menu Bar With Alt') @description("Mimics standard Windows behavior of focusing the menu bar using the Alt key.") 'focus_menu_bar_with_alt': bool, //- rjf: native filesystem dialogues @default(0) @display_name('Use Native File System Dialog') @description("Uses the operating system's file system dialog box, rather than the debugger's built-in UI.") 'use_native_file_system_dialog': bool, } ``` } // TODO(rjf): the control codes could be fed from the CTRL_ExceptionCodeKindTable, but // we do not support that in this generator - we'd need a way to form a table-generated // string and put it into a table cell... { project ``` @expand_commands(edit_project_theme) x: { @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64, //- rjf: visualizers @display_name('Use Default C++ STL Type Visualizers') @description("Enables the built-in type views for C++ STL types.") @default(1) use_default_stl_type_views: bool, @display_name('Use Default Unreal Engine Type Visualizers') @description("Enables the built-in type views for Unreal Engine types.") @default(1) use_default_ue_type_views: bool, //- rjf: theme @default("None") @display_name('Project Theme') @description("The project's theme, which describes all colors used throughout the UI, and can override the user's theme.") 'theme': string, @no_expand @display_name('Project Theme') @description("The project's theme, which describes all colors used throughout the UI, and can override the user's theme.") 'theme_colors': query, //- rjf: exception settings @default(1) @display_name("Break On Win32 Control-C Exceptions") @description("Code: 0x40010005") win32_ctrl_c: bool; @default(1) @display_name("Break On Win32 Control-Break Exceptions") @description("Code: 0x40010008") win32_ctrl_break: bool; @default(0) @display_name("Break On Win32 WinRT Originate Error Exceptions") @description("Code: 0x40080201") win32_win_rt_originate_error: bool; @default(0) @display_name("Break On Win32 WinRT Transform Error Exceptions") @description("Code: 0x40080202") win32_win_rt_transform_error: bool; @default(0) @display_name("Break On Win32 RPC Call Cancelled Exceptions") @description("Code: 0x0000071a") win32_rpc_call_cancelled: bool; @default(0) @display_name("Break On Win32 Data Type Misalignment Exceptions") @description("Code: 0x80000002") win32_datatype_misalignment: bool; @default(1) @display_name("Break On Win32 Access Violation Exceptions") @description("Code: 0xc0000005") win32_access_violation: bool; @default(0) @display_name("Break On Win32 In Page Error Exceptions") @description("Code: 0xc0000006") win32_in_page_error: bool; @default(1) @display_name("Break On Win32 Invalid Handle Specified Exceptions") @description("Code: 0xc0000008") win32_invalid_handle: bool; @default(0) @display_name("Break On Win32 Not Enough Quota Exceptions") @description("Code: 0xc0000017") win32_not_enough_quota: bool; @default(0) @display_name("Break On Win32 Illegal Instruction Exceptions") @description("Code: 0xc000001d") win32_illegal_instruction: bool; @default(0) @display_name("Break On Win32 Cannot Continue From Exception Exceptions") @description("Code: 0xc0000025") win32_cannot_continue_exception: bool; @default(0) @display_name("Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions") @description("Code: 0xc0000026") win32_invalid_exception_disposition: bool; @default(0) @display_name("Break On Win32 Array Bounds Exceeded Exceptions") @description("Code: 0xc000008c") win32_array_bounds_exceeded: bool; @default(0) @display_name("Break On Win32 Floating-Point Denormal Operand Exceptions") @description("Code: 0xc000008d") win32_floating_point_denormal_operand: bool; @default(0) @display_name("Break On Win32 Floating-Point Division By Zero Exceptions") @description("Code: 0xc000008e") win32_floating_point_division_by_zero: bool; @default(0) @display_name("Break On Win32 Floating-Point Inexact Result Exceptions") @description("Code: 0xc000008f") win32_floating_point_inexact_result: bool; @default(0) @display_name("Break On Win32 Floating-Point Invalid Operation Exceptions") @description("Code: 0xc0000090") win32_floating_point_invalid_operation: bool; @default(0) @display_name("Break On Win32 Floating-Point Overflow Exceptions") @description("Code: 0xc0000091") win32_floating_point_overflow: bool; @default(0) @display_name("Break On Win32 Floating-Point Stack Check Exceptions") @description("Code: 0xc0000092") win32_floating_point_stack_check: bool; @default(0) @display_name("Break On Win32 Floating-Point Underflow Exceptions") @description("Code: 0xc0000093") win32_floating_point_underflow: bool; @default(0) @display_name("Break On Win32 Integer Division By Zero Exceptions") @description("Code: 0xc0000094") win32_integer_division_by_zero: bool; @default(0) @display_name("Break On Win32 Integer Overflow Exceptions") @description("Code: 0xc0000095") win32_integer_overflow: bool; @default(0) @display_name("Break On Win32 Privileged Instruction Exceptions") @description("Code: 0xc0000096") win32_privileged_instruction: bool; @default(0) @display_name("Break On Win32 Stack Overflow Exceptions") @description("Code: 0xc00000fd") win32_stack_overflow: bool; @default(0) @display_name("Break On Win32 Unable To Locate DLL Exceptions") @description("Code: 0xc0000135") win32_unable_to_locate_dll: bool; @default(0) @display_name("Break On Win32 Ordinal Not Found Exceptions") @description("Code: 0xc0000138") win32_ordinal_not_found: bool; @default(0) @display_name("Break On Win32 Entry Point Not Found Exceptions") @description("Code: 0xc0000139") win32_entry_point_not_found: bool; @default(0) @display_name("Break On Win32 DLL Initialization Failed Exceptions") @description("Code: 0xc0000142") win32_dll_initialization_failed: bool; @default(0) @display_name("Break On Win32 Floating Point SSE Multiple Faults Exceptions") @description("Code: 0xc00002b4") win32_floating_point_sse_multiple_faults: bool; @default(0) @display_name("Break On Win32 Floating Point SSE Multiple Traps Exceptions") @description("Code: 0xc00002b5") win32_floating_point_sse_multiple_traps: bool; @default(1) @display_name("Break On Win32 Assertion Failed Exceptions") @description("Code: 0xc0000420") win32_assertion_failed: bool; @default(0) @display_name("Break On Win32 Module Not Found Exceptions") @description("Code: 0xc06d007e") win32_module_not_found: bool; @default(0) @display_name("Break On Win32 Procedure Not Found Exceptions") @description("Code: 0xc06d007f") win32_procedure_not_found: bool; @default(1) @display_name("Break On Win32 Sanitizer Error Detected Exceptions") @description("Code: 0xe073616e") win32_sanitizer_error_detected: bool; @default(0) @display_name("Break On Win32 Sanitizer Raw Access Violation Exceptions") @description("Code: 0xe0736171") win32_sanitizer_raw_access_violation: bool; @default(1) @display_name("Break On Win32 DirectX Debug Layer Exceptions") @description("Code: 0x0000087a") win32_directx_debug_layer: bool; } ``` } //- rjf: theme colors { theme_color, ``` @collection_commands(add_theme_color, fork_theme, save_theme, save_and_set_theme) @row_commands(duplicate_cfg, remove_cfg) x: { @display_name('Tags') tags: string, @display_name('Value') value: @color @hex u32, } ``` } //- rjf: windows { window, ``` x: { //- rjf: text rasterization settings @default(1) @display_name('Smooth UI Text') @description("Controls whether or not UI text is fully anti-aliased, for a smoother appearance.") 'smooth_ui_text': bool, @default(1) @display_name('Hint UI Text') @description("Controls whether or not UI text is hinted, for better text readability at small sizes.") 'hint_ui_text': bool, @default(0) @display_name('Smooth Code Text') @description("Controls whether or not code text is fully anti-aliased, for a smoother appearance.") 'smooth_code_text': bool, @default(1) @display_name('Hint Code Text') @description("Controls whether or not code text is hinted, for better text readability at small sizes.") 'hint_code_text': bool, @default(11) @display_name('Window Font Size') @description("Controls the window's default font size. Does not apply to tabs with their own font size set.") 'font_size': @range[6, 72] u64, //- rjf: size settings @default(3.f) @display_name('Window Row Height') @description("Controls the window's default row height, in multiples of the font size. Does not apply to tabs with their own row height set.") 'row_height': @range[1.75f, 5.f] f32, @default(3.f) @description("Controls the height of tabs, in multiples of the font size.") 'tab_height': @range[1.75f, 5.f] f32, //- rjf: theme settings @default(1) @display_name('Use Project Theme') @description("Prefer using the project theme for this window, if any. If off, only the user's theme settings will be used.") 'use_project_theme': bool, } ``` } //- rjf: tabs { tab, ``` @row_commands(@file copy_tab_full_path, @file show_file_in_explorer, duplicate_tab, close_tab) x: { @override @display_name('Tab Font Size') @description("Controls the tab's font size.") @no_callee_helper 'font_size': @range[6, 72] u64, } ``` } //- rjf: views { watch, ``` @inherit(tab) x: { @override @display_name('Tab Row Height') @description("Controls the tab's row height, in multiples of the font size.") 'row_height': @range[1.75f, 5.f] f32, 'label': code_string, @description("The root expression which is evaluated to produce the watch window.") 'expression': expr_string, @no_expand 'watches': query, } ``` } { list, ``` x: { @description("An expression describing the first node in the list.") 'expression': expr_string, @order(0) @description("The name of the member which encodes the link to the next node.") 'member_name': code_string, } ``` } { text, ``` @inherit(tab) @expand_commands(@output clear_output) x: { @description("An expression to describe data which should be viewed as text or code.") 'expression': expr_string, @description("The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.") 'lang': code_string, @default(1) @description("Controls whether or not line numbers are shown.") 'show_line_numbers':bool, @no_callee_helper @default(1) @display_name('Line Wrapping') @description("Splits textual lines into multiple visual lines, so that all text is within the visible area.") 'line_wrapping': bool, @no_callee_helper @default(0) @display_name('Scroll To Bottom On Change') @description("Scrolls to the bottom if the text is changed.") 'scroll_to_bottom_on_change': bool, @no_callee_helper @no_revert @default(0) @display_name('Transient') @description("Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.") 'auto': bool, } ``` } { disasm, ``` @inherit(tab) x: { @description("An expression to describe the base address or offset of the disassembly.") 'expression': expr_string, 'arch': code_string, 'syntax': code_string, 'size': expr_string, @no_callee_helper @default(1) @description("Controls whether or not addresses are shown in the disassembly text.") 'show_addresses': bool, @no_callee_helper @default(0) @description("Controls whether or not code bytes are shown in the disassembly text.") 'show_code_bytes': bool, @no_callee_helper @default(1) @description("Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.") 'show_source_lines': bool, @no_callee_helper @default(1) @description("Controls whether or not disassembly text is decorated with symbol names.") 'show_symbol_names': bool, @no_callee_helper @default(1) @description("Controls whether or not line numbers are shown.") 'show_line_numbers': bool, } ``` } { memory, ``` @inherit(tab) x: { @description("An expression which refers to the base address of data which should be viewed as memory.") 'expression': expr_string, @display_name("Address Range Size") @description("The number of bytes of the viewed memory range.") 'size': expr_string, @display_name("Cursor Address") @description("The address of the cursor.") 'cursor': expr_string, @display_name("Cursor Size") @description("The size, in bytes, of the cursor.") 'cursor_size': @range[1, 16] u64, @default(16) @description("The number of columns to build before building new rows.") 'num_columns': @range[1, 64] u64, @default(1) @display_name("Track Mark To Cursor") @description("Ensures that the mark always follows the cursor, if the cursor value is updated.") 'track_mark_to_cursor': bool, } ``` } { bitmap, ``` @inherit(tab) x: { @description("An expression which refers to the base address of data which should be viewed as a bitmap.") 'expression': expr_string, @description("An expression describing the width of the bitmap, in pixels.") @order(0) 'w': u64, @description("An expression describing the height of the bitmap, in pixels.") @order(1) 'h': u64, @display_name("Bitmap Format") @description("The pixel format that the bitmap data should be interpreted as being within.") 'fmt': code_string, } ``` } { color, ``` @inherit(tab) x: { @display_name("Value") @description("An expression to describe the value or location of the color.") 'expression': expr_string, } ``` } { geo3d, ``` @inherit(tab) x: { @display_name("Expression") @description("An expression to describe the base address of the index buffer.") 'expression': expr_string, 'count': expr_string, 'vtx': expr_string, 'vtx_size': expr_string, 'yaw': @range[0, 1] f32, 'pitch': @range[-0.5, 0] f32, 'zoom': @range[0, 100] f32, } ``` } //- rjf: getting started { getting_started, ``` @inherit(tab) x: { } ``` } //- rjf: targets { target, ``` @row_commands(@cmd_line save_cfg_to_project, enable_cfg, launch_and_run, launch_and_step_into, duplicate_cfg, remove_cfg) @collection_commands(add_target) x: { 'label': code_string, 'executable': path, 'arguments': string, 'working_directory': path, 'entry_point': expr_string, 'stdout_path': @no_relativize path, 'stderr_path': @no_relativize path, 'stdin_path': @no_relativize path, 'environment': query, 'debug_subprocesses': bool, @no_revert @no_expand @default(0) 'enabled': bool, } ```, } //- rjf: breakpoints { breakpoint, ``` @row_commands(enable_cfg, duplicate_cfg, remove_cfg) @collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint, add_function_breakpoint, clear_breakpoints) x: { 'label': code_string, 'condition': expr_string, 'source_location': path_pt, 'address_location': expr_string, 'hit_count': u64, 'address_range_size': @or(0, 1, 2, 4, 8) u64, 'break_on_write': bool, 'break_on_read': bool, 'break_on_execute': bool, @no_revert @no_expand @default(1) 'enabled': bool, } ```, } //- rjf: watch pins { watch_pin, ``` @row_commands(duplicate_cfg, remove_cfg) @collection_commands(add_watch_pin, toggle_watch_pin) x: { 'expression': expr_string, 'source_location': path_pt, 'address_location': expr_string, } ```, } //- rjf: debug infos { debug_info, ``` @row_commands(enable_cfg, duplicate_cfg, remove_cfg) @collection_commands(load_debug_info) x: { 'path': @no_relativize path, @query 'guid': string, @no_revert @no_expand @default(1) 'enabled': bool, } ```, } //- rjf: file path maps { file_path_map, ```@collection_commands(add_file_path_map) @row_commands(remove_cfg) x:{'source': @no_relativize path, 'dest': @no_relativize path}```, } //- rjf: type views { type_view, ```@collection_commands(add_type_view) @row_commands(remove_cfg) x:{'type':expr_string, 'expr':expr_string}```, } //- rjf: recent projects { recent_project, ```x:{'path':path}```, } //- rjf: recent files { recent_file, ```x:{'path':path}```, } //- rjf: control entities { machine, ```x:{'label':code_string, @no_expand 'active':bool, 'unattached_processes':query, 'processes':query}```, } { process, ```x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'modules':query, 'threads':query}```, } { module, ```x:{'exe':path, 'dbg':path, 'vaddr_range':vaddr_range}```, } { thread, ```x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'call_stack':query}```, } } @struct RD_NameSchemaInfo: { `String8 name`; `String8 schema`; } @data(RD_NameSchemaInfo) rd_name_schema_info_table: { @expand(RD_SchemaTable a) `{str8_lit_comp("$(a.name)"), str8_lit_comp("$(a.schema)")}` } //////////////////////////////// //~ rjf: Registers Type Table @table(c_type name_lower name) RD_RegTable: { // rjf: ctrl entities {CTRL_Handle machine Machine } {CTRL_Handle module Module } {CTRL_Handle process Process } {CTRL_Handle thread Thread } {CTRL_Handle ctrl_entity CtrlEntity } // rjf: cfgs {CFG_ID window Window } {CFG_ID panel Panel } {CFG_ID tab Tab } {CFG_ID view View } {CFG_ID prev_tab PrevTab } {CFG_ID dst_panel DstPanel } {CFG_ID cfg Cfg } {CFG_IDList cfg_list CfgList } // rjf: evaluation space {E_Space eval_space EvalSpace } // rjf: frame selection {U64 unwind_count UnwindCount } {U64 inline_depth InlineDepth } // rjf: code / address location info {String8 file_path FilePath } {TxtPt cursor Cursor } {TxtPt mark Mark } {C_Key text_key TextKey } {TXT_LangKind lang_kind LangKind } {D_LineList lines Lines } {DI_Key dbgi_key DbgiKey } {U64 vaddr Vaddr } {U64 voff Voff } {Rng1U64 vaddr_range VaddrRange } {Rng1U64 voff_range VoffRange } // rjf: evaluation {String8 expr Expr } // rjf: ui context {UI_Key ui_key UIKey } {UI_Key src_ui_key SrcUIKey } {Vec2F32 off_px OffPx } {RD_RegSlot reg_slot RegSlot } // rjf: general parameters {U32 pid PID } {B32 force_confirm ForceConfirm } {B32 force_focus ForceFocus } {B32 prefer_disasm PreferDisasm } {B32 no_rich_tooltip NoRichTooltip } {B32 do_implicit_root DoImplicitRoot} {B32 do_lister DoLister } {B32 do_big_rows DoBigRows } {B32 all_windows AllWindows } {B32 non_graphical NonGraphical } {B32 prefer_new_tab PreferNewTab } {Dir2 dir2 Dir2 } {String8 string String } {String8 cmd_name CmdName } {`OS_Event *` os_event OSEvent } } @enum RD_RegSlot: { Null, @expand(RD_RegTable a) `$(a.name)`, COUNT, } @struct RD_Regs: { @expand(RD_RegTable a) `$(a.c_type) $(a.name_lower)` } @data(String8) rd_reg_slot_code_name_table: { `{0}`, @expand(RD_RegTable a) `str8_lit_comp("$(a.name_lower)")` } @data(Rng1U64) rd_reg_slot_range_table: { `{0}`, @expand(RD_RegTable a) `{OffsetOf(RD_Regs, $(a.name_lower)), OffsetOf(RD_Regs, $(a.name_lower)) + sizeof($(a.c_type))}` } @gen { `#define rd_regs_lit_init_top \\` @expand(RD_RegTable a) `.$(a.name_lower) = rd_regs()->$(a.name_lower),\\` ``; } //////////////////////////////// //~ rjf: Command Table @table(name ui_vis ipc_docs_vis text_pt_vis text_rng_vis q_expr q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_floating q_required canonical_icon string display_name desc search_tags ctx_filter) // / | | | | | \___ __________________________/ | | | | | | // / | | | | | \ / | | | | | | RD_CmdTable: // | | | | | | | | | | | | | { //- rjf: exiting {Exit 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 X "exit" "Exit" "Exits the debugger." "quit,close,abort" "" } //- rjf: palette {OpenPalette 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 List "open_palette" "Open Palette" "Opens the palette." "help,cmd,lister" "" } //- rjf: command runners {RunCommand 1 1 0 0 "query:commands" CmdName commands Nil Null 0 0 0 0 0 1 1 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" "" } {RunExternalDriverTextCommand 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 1 1 Null "run_ext_driver_text_command" "Run External Driver Text Command" "" "" "" } //- rjf: os event passthrough {OSEvent 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "os_event" "OS Event" "" "" "" } //- rjf: thread/frame selection {SelectThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Thread "select_thread" "Select Thread" "Selects a thread." "" "" } {SelectUnwind 0 1 0 0 "query:call_stack" Null null Nil Null 0 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" "" } {UpOneFrame 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the call stack frame above the currently selected." "" "" } {DownOneFrame 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the call stack frame below the currently selected." "callstack,unwind" "" } {SelectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_entity" "Select" "Selects a control entity." "" "" } {DeselectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_entity" "Deselect" "Deselects a control entity." "" "" } //- rjf: font sizes {IncWindowFontSize 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "inc_window_font_size" "Increase Window Font Size" "Increases the window's font size by one point." "" "" } {DecWindowFontSize 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "dec_window_font_size" "Decrease Window Font Size" "Decreases the window's font size by one point." "" "" } {IncViewFontSize 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "inc_view_font_size" "Increase View Font Size" "Increases the view's font size by one point." "" "" } {DecViewFontSize 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "dec_view_font_size" "Decrease View Font Size" "Decreases the view's font size by one point." "" "" } //- rjf: windows {OpenWindow 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "open_window" "Open New Window" "Opens a new window." "" "" } {WindowSettings 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Gear "window_settings" "Window Settings" "Opens settings for a window." "" "" } {CloseWindow 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "close_window" "Close Window" "Closes an opened window." "" "" } {ToggleFullscreen 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "toggle_fullscreen" "Toggle Fullscreen" "Toggles fullscreen view on the active window." "" "" } {BringToFront 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "bring_to_front" "Bring To Front" "Brings all windows to the front, and focuses the most recently focused window." "top" "" } //- rjf: popups {PopupAccept 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "popup_accept" "Popup Accept" "Accepts the active popup prompt." "" "" } {PopupCancel 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "popup_cancel" "Popup Cancel" "Cancels the active popup prompt." "" "" } //- rjf: keybindings {ResetToDefaultBindings 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "reset_to_default_bindings" "Reset To Default Bindings" "Resets all keybindings to their defaults." "" "" } //- rjf: panel splitting {ResetToDefaultPanels 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "reset_to_default_panels" "Reset To Default Panel Layout" "Resets the window to the default panel layout." "panel" "" } {ResetToCompactPanels 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "reset_to_compact_panels" "Reset To Compact Panel Layout" "Resets the window to the compact panel layout." "panel" "" } {ResetToSimplePanels 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Window "reset_to_simple_panels" "Reset To Simple Panel Layout" "Resets the window to the simple panel layout." "panel" "" } {NewPanelLeft 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 XSplit "new_panel_left" "Split Panel Left" "Creates a new panel to the left of the active panel." "panel" "" } {NewPanelUp 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 YSplit "new_panel_up" "Split Panel Up" "Creates a new panel at the top of the active panel." "panel" "" } {NewPanelRight 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 XSplit "new_panel_right" "Split Panel Right" "Creates a new panel to the right of the active panel." "panel" "" } {NewPanelDown 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 YSplit "new_panel_down" "Split Panel Down" "Creates a new panel at the bottom of the active panel." "panel" "" } {SplitPanel 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "split_panel" "Split Panel" "Creates a new panel in a given direction, and moves a tab to it, if specified." "" "" } //- rjf: panel rotation {RotatePanelColumns 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "rotate_panel_columns" "Rotate Panel Columns" "Rotates all panels at the closest column level of the panel hierarchy." "" "" } //- rjf: focused panel changing {NextPanel 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "next_panel" "Focus Next Panel" "Cycles the active panel forward." "" "" } {PrevPanel 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 LeftArrow "prev_panel" "Focus Previous Panel" "Cycles the active panel backwards." "" "" } {FocusPanel 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "focus_panel" "Focus Panel" "Focuses a new panel." "" "" } {FocusPanelRight 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "focus_panel_right" "Focus Panel Right" "Focuses a panel rightward of the currently focused panel." "" "" } {FocusPanelLeft 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 LeftArrow "focus_panel_left" "Focus Panel Left" "Focuses a panel leftward of the currently focused panel." "" "" } {FocusPanelUp 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 UpArrow "focus_panel_up" "Focus Panel Up" "Focuses a panel upward of the currently focused panel." "" "" } {FocusPanelDown 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 DownArrow "focus_panel_down" "Focus Panel Down" "Focuses a panel downward of the currently focused panel." "" "" } //- rjf: undo/redo {Undo 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Undo "undo" "Undo" "Undoes the previous action." "" "" } {Redo 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Redo "redo" "Redo" "Redoes the first previously undone action." "" "" } //- rjf: focus history {GoBack 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 LeftArrow "go_back" "Go Back" "Returns to the previously selected panel and tab in recorded history." "" "" } {GoForward 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "go_forward" "Go Forward" "Returns to the next selected panel and tab in recorded history." "" "" } //- rjf: panel removal {ClosePanel 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 ClosePanel "close_panel" "Close Panel" "Closes the currently active panel." "" "" } //- rjf: panel tab {FocusTab 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "focus_tab" "Focus Tab" "Focuses the passed tab within its containing panel." "" "" } {NextTab 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "next_tab" "Focus Next Tab" "Focuses the next tab on the active panel." "" "" } {PrevTab 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 LeftArrow "prev_tab" "Focus Previous Tab" "Focuses the previous tab on the active panel." "" "" } {MoveTabRight 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "move_tab_right" "Move Tab Right" "Moves the selected tab right one slot." "" "$tab," } {MoveTabLeft 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 LeftArrow "move_tab_left" "Move Tab Left" "Moves the selected tab left one slot." "" "$tab," } {OpenTab 1 1 0 0 "query:tab_commands" CmdName commands Nil Null 0 0 0 0 0 1 1 Null "open_tab" "Open New Tab" "Opens a new tab." "" "" } {BuildTab 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "build_tab" "Build Tab" "Opens a new tab with the parameterized view specification." "" "" } {DuplicateTab 1 1 0 0 "" Tab null Nil Null 0 0 0 0 0 0 0 Duplicate "duplicate_tab" "Duplicate Tab" "Duplicates a tab." "" "$tab," } {CopyTabFullPath 0 0 0 0 "" Tab null Nil Null 0 0 0 0 0 0 0 Clipboard "copy_tab_full_path" "Copy Full Path" "Copies the full path of the file being viewed by this tab." "" "$tab," } {CloseTab 1 1 0 0 "" Tab null Nil Null 0 0 0 0 0 0 0 X "close_tab" "Close Tab" "Closes the currently opened tab." "" "$tab," } {MoveView 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_view" "Move View" "Moves a view to a new panel." "" "" } {TabBarTop 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 UpArrow "tab_bar_top" "Anchor Tab Bar To Top" "Anchors a panel's tab bar to the top of the panel." "" "$tab," } {TabBarBottom 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 DownArrow "tab_bar_bottom" "Anchor Tab Bar To Bottom" "Anchors a panel's tab bar to the bottom of the panel." "" "$tab," } {TabSettings 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Gear "tab_settings" "Tab Settings" "Opens settings for a tab." "" "" } //- rjf: files {SetCurrentPath 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FileOutline "set_current_path" "Set Current Path" "Sets the debugger's current path, which is used as a starting point when browsing for files." "" "" } {Open 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 FileOutline "open" "Open" "Opens a file." "code,source,file" "" } {Switch 1 0 0 0 "query:recent_files, query:source_files" Cfg null RecentFile Null 0 0 0 0 0 1 1 FileOutline "switch" "Switch" "Switches to a recent file." "code,source,file" "" } {SwitchToPartnerFile 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FileOutline "switch_to_partner_file" "Switch To Partner File" "Switches to the focused file's partner; or from header to implementation or vice versa." "code,source,file" "" } {RecordFileInProject 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FileOutline "record_file_in_project" "Record File In Project" "Records the passed file path as a recent file in the currently loaded project." "" "" } {ShowFileInExplorer 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FolderClosedFilled "show_file_in_explorer" "Show File In Explorer" "Opens the operating system's file explorer and shows the selected file." "" "$file," } //- rjf: source <-> disasm {GoToDisassembly 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 Glasses "go_to_disassembly" "Go To Disassembly" "Goes to the disassembly, if any, for a given source code line." "code,source,disassembly,disasm" "$text_pt," } {GoToSource 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FileOutline "go_to_source" "Go To Source" "Goes to the source code, if any, for a given disassembly line." "code,source,disassembly,disasm" "" } //- rjf: override file links {SetFileReplacementPath 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_file_replacement_path" "Set File Replacement Path" "Sets the path which should be used as the replacement for the passed file." "" "" } //- rjf: setting config paths {NewUser 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Add "new_user" "New User" "Creates a new user file, and sets the current user path as that file's path." "new,user,project,layout" "" } {NewProject 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Add "new_project" "New Project" "Creates a new project file, and sets the current project path as that file's path." "new,user,project,layout" "" } {OpenUser 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Person "open_user" "Open User" "Opens a user file path, immediately loading it, and begins autosaving to it." "load,user,project,layout" "" } {OpenProject 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Briefcase "open_project" "Open Project" "Opens a project file path, immediately loading it, and begins autosaving to it." "project,project,session" "" } {OpenRecentProject 1 1 0 0 "query:recent_projects" Cfg null RecentProject Null 0 0 0 0 0 1 1 Briefcase "open_recent_project" "Open Recent Project" "Opens a recently used project file." "project,project,session" "" } {SaveUser 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Save "save_user" "Save User" "Saves user data to a file, and sets the current user path as that path." "load,user,project,layout" "" } {SaveProject 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Save "save_project" "Save Project" "Saves project data to a file, and sets the current project path as that path." "project,project,session" "" } {RecordUserAsLastOpened 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "record_user_as_last_opened" "Record User As Last Opened" "Records a file path as the last opened user." "" "" } {RecordProjectInUser 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "record_project_in_user" "Records Project In User" "Records a file path as a recent project in user data." "" "" } //- rjf: writing config changes {WriteUserData 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "write_user_data" "Write User Data" "Writes user data to the active user file." "" "" } {WriteProjectData 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "write_project_data" "Write Project Data" "Writes project data to the active project file." "" "" } //- rjf: opening user/project settings {UserSettings 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Gear "user_settings" "User Settings" "Opens user settings." "" "" } {ProjectSettings 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Gear "project_settings" "Project Settings" "Opens project settings." "" "" } //- rjf: meta controls {Edit 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Pencil "edit" "Edit" "Edits the current selection." "" "" } {Accept 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckFilled "accept" "Accept" "Accepts current changes, or answers prompts in the affirmative." "" "" } {Cancel 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 X "cancel" "Cancel" "Rejects current changes, exits temporary menus, or answers prompts in the negative." "" "" } //- rjf: directional movement & text controls {MoveLeft 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_left" "Move Left" "Moves the cursor or selection left." "" "" } {MoveRight 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_right" "Move Right" "Moves the cursor or selection right." "" "" } {MoveUp 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up" "Move Up" "Moves the cursor or selection up." "" "" } {MoveDown 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down" "Move Down" "Moves the cursor or selection down." "" "" } {MoveLeftSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_left_select" "Move Left Select" "Moves the cursor or selection left, while selecting." "" "" } {MoveRightSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_right_select" "Move Right Select" "Moves the cursor or selection right, while selecting." "" "" } {MoveUpSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_select" "Move Up Select" "Moves the cursor or selection up, while selecting." "" "" } {MoveDownSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_select" "Move Down Select" "Moves the cursor or selection down, while selecting." "" "" } {MoveLeftChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_left_chunk" "Move Left Chunk" "Moves the cursor or selection left one chunk." "" "" } {MoveRightChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_right_chunk" "Move Right Chunk" "Moves the cursor or selection right one chunk." "" "" } {MoveUpChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_chunk" "Move Up Chunk" "Moves the cursor or selection up one chunk." "" "" } {MoveDownChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_chunk" "Move Down Chunk" "Moves the cursor or selection down one chunk." "" "" } {MoveUpPage 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_page" "Move Up Page" "Moves the cursor or selection up one page." "" "" } {MoveDownPage 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_page" "Move Down Page" "Moves the cursor or selection down one page." "" "" } {MoveUpWhole 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_whole" "Move Up Whole" "Moves the cursor or selection to the beginning of the relevant content." "" "" } {MoveDownWhole 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_whole" "Move Down Whole" "Moves the cursor or selection to the end of the relevant content." "" "" } {MoveLeftChunkSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_left_chunk_select" "Move Left Chunk Select" "Moves the cursor or selection left one chunk." "" "" } {MoveRightChunkSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_right_chunk_select" "Move Right Chunk Select" "Moves the cursor or selection right one chunk." "" "" } {MoveUpChunkSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_chunk_select" "Move Up Chunk Select" "Moves the cursor or selection up one chunk." "" "" } {MoveDownChunkSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_chunk_select" "Move Down Chunk Select" "Moves the cursor or selection down one chunk." "" "" } {MoveUpPageSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_page_select" "Move Up Page Select" "Moves the cursor or selection up one page, while selecting." "" "" } {MoveDownPageSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_page_select" "Move Down Page Select" "Moves the cursor or selection down one page, while selecting." "" "" } {MoveUpWholeSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_whole_select" "Move Up Whole Select" "Moves the cursor or selection to the beginning of the relevant content, while selecting." "" "" } {MoveDownWholeSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_whole_select" "Move Down Whole Select" "Moves the cursor or selection to the end of the relevant content, while selecting." "" "" } {MoveUpReorder 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_up_reorder" "Move Up Reorder" "Moves the cursor or selection up, while swapping the currently selected element with that upward." "" "" } {MoveDownReorder 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_down_reorder" "Move Down Reorder" "Moves the cursor or selection down, while swapping the currently selected element with that downward." "" "" } {MoveHome 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_home" "Move Home" "Moves the cursor to the beginning of the line." "" "" } {MoveEnd 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_end" "Move End" "Moves the cursor to the end of the line." "" "" } {MoveHomeSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_home_select" "Move Home Select" "Moves the cursor to the beginning of the line, while selecting." "" "" } {MoveEndSelect 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_end_select" "Move End Select" "Moves the cursor to the end of the line, while selecting." "" "" } {SelectAll 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "select_all" "Select All" "Selects everything possible." "" "" } {DeleteSingle 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "delete_single" "Delete Single" "Deletes a single element to the right of the cursor, or the active selection." "" "" } {DeleteChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "delete_chunk" "Delete Chunk" "Deletes a chunk to the right of the cursor, or the active selection." "" "" } {BackspaceSingle 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "backspace_single" "Backspace Single" "Deletes a single element to the left of the cursor, or the active selection." "" "" } {BackspaceChunk 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "backspace_chunk" "Backspace Chunk" "Deletes a chunk to the left of the cursor, or the active selection." "" "" } {Copy 1 1 0 1 "" Null null Nil Null 0 0 0 0 0 0 0 Clipboard "copy" "Copy" "Copies the active selection to the clipboard." "" "$text_rng," } {Cut 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Clipboard "cut" "Cut" "Copies the active selection to the clipboard, then deletes it." "" "" } {Paste 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Clipboard "paste" "Paste" "Pastes the current contents of the clipboard." "" "" } {InsertText 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "insert_text" "Insert Text" "Inserts the text that was used to cause this command." "" "" } //- rjf: directionless navigation {MoveNext 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_next" "Move Next" "Moves the cursor or selection to the next element." "" "" } {MovePrev 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "move_prev" "Move Previous" "Moves the cursor or selection to the previous element." "" "" } //- rjf: code navigation {GoToLine 1 1 0 0 "" Cursor null Nil Null 0 0 0 0 1 0 1 Null "goto_line" "Go To Line" "Jumps to a line number in the current code file." "" "" } {GoToAddress 1 1 0 0 "" Vaddr null Nil Null 0 0 0 0 1 0 1 Null "goto_address" "Go To Address" "Jumps to an address in the current memory or disassembly view." "" "" } {CenterCursor 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "center_cursor" "Center Cursor" "Snaps the current code view to center the cursor." "" "" } {ContainCursor 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "contain_cursor" "Contain Cursor" "Snaps the current code view to contain the cursor." "" "" } {FindNext 1 1 0 0 "" Null null Nil Null 0 0 1 0 0 0 0 Find "find_next" "Find Next" "Searches the current code file forward (from the cursor) for the last searched string." "" "" } {FindPrev 1 1 0 0 "" Null null Nil Null 0 0 1 0 0 0 0 Find "find_prev" "Find Previous" "Searches the current code file backwards (from the cursor) for the last searched string." "" "" } //- rjf: thread finding {FindThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Find "find_thread" "Find Thread" "Jumps to the passed thread in either source code, disassembly, or both if they're already open." "" "" } {FindSelectedThread 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Find "find_selected_thread" "Find Selected Thread" "Jumps to the selected thread in either source code, disassembly, or both if they're already open." "" "" } //- rjf: name finding {GoToName 1 1 0 0 "query:procedures" String symbol_lister Nil Null 0 0 0 0 1 1 1 Null "goto_name" "Go To Name" "Searches for the passed string as a file, a symbol in debug info, and more, then jumps to it if possible." "" "$text_pt," } {GoToNameAtCursor 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "goto_name_at_cursor" "Go To Name At Cursor" "Searches for the text at the cursor as a file, a symbol in debug info, and more, then jumps to it if possible." "" "" } //- rjf: watch expressions {ToggleWatchExpression 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Binoculars "toggle_watch_expr" "Toggle Watch Expression" "Adds or removes an expression to an opened watch view." "" "$text_pt," } {ToggleWatchExpressionAtCursor 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_cursor" "Toggle Watch Expression At Cursor" "Adds or removes the expression that the cursor or selection is currently over to an opened watch view." "" "" } {ToggleWatchExpressionAtMouse 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_mouse" "Toggle Watch Expression At Mouse" "Adds or removes the expression that the mouse is currently over to an opened watch view." "" "" } //- rjf: general config operations {EnableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckHollow "enable_cfg" "Enable" "Enables a config tree." "" "" } {DisableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckFilled "disable_cfg" "Disable" "Disables a config tree." "" "" } {SelectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_cfg" "Select" "Selects a config tree, disabling all others of the same kind." "" "" } {DeselectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_cfg" "Deselect" "Deselects a config tree." "" "" } {RemoveCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Trash "remove_cfg" "Remove" "Removes a config tree." "" "" } {NameCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "name_cfg" "Name" "Equips a config tree with a label." "" "" } {ConditionCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "condition_cfg" "Condition" "Equips a config tree with a condition string." "" "" } {DuplicateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Duplicate "duplicate_cfg" "Duplicate" "Duplicates a config tree." "" "" } {RelocateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "relocate_cfg" "Relocate" "Relocates a config tree." "" "" } {SaveToProject 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Briefcase "save_cfg_to_project" "Save To Project" "Saves the config tree to the project." "" "" } //- rjf: breakpoints {AddBreakpoint 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CircleFilled "add_breakpoint" "Add Line Breakpoint" "Places a breakpoint at a given location (file path and line number, address, or symbol name)." "" "" } {AddAddressBreakpoint 1 0 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 CircleFilled "add_address_breakpoint" "Add Address Breakpoint" "Places a breakpoint on the specified address." "" "$breakpoints," } {AddFunctionBreakpoint 1 0 0 0 "query:procedures" String null Nil Null 0 0 0 0 1 1 1 CircleFilled "add_function_breakpoint" "Add Function Breakpoint" "Places a breakpoint on the first address of the specified function." "" "$breakpoints," } {ToggleBreakpoint 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 CircleFilled "toggle_breakpoint" "Toggle Line Breakpoint" "Places or removes a breakpoint at a given location (file path and line number, address, or symbol name)." "" "$text_pt," } {RemoveBreakpoint 1 0 0 0 "query:breakpoints" Cfg null Nil Null 0 0 0 0 1 1 1 Trash "remove_breakpoint" "Remove Breakpoint" "Removes an existing breakpoint." "delete" "$breakpoints," } {EnableBreakpoint 1 1 0 0 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 1 1 1 CheckFilled "enable_breakpoint" "Enable Breakpoint" "Enables a breakpoint." "" "" } {DisableBreakpoint 1 1 0 0 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 1 1 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" "" } {ClearBreakpoints 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Trash "clear_breakpoints" "Clear Breakpoints" "Removes all breakpoints." "" "" } {ListBreakpoints 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "list_breakpoints" "List Breakpoints" "Lists all breakpoints." "" "" } //- rjf: output {ClearOutput 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "clear_output" "Clear Output" "Clears all output." "" "" } //- rjf: watch pins {AddWatchPin 1 1 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," } {ToggleWatchPin 1 0 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" } //- rjf: debug infos {LoadDebugInfo 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Module "load_debug_info" "Load Debug Info" "Loads a debug info file." "" "$debug_infos," } {UnloadDebugInfo 1 1 0 0 "query:debug_infos" Cfg null Nil Null 0 0 0 0 1 1 1 Module "unload_debug_info" "Unload Debug Info" "Unloads a debug info file." "" "$debug_infos," } //- rjf: type views {AddTypeView 0 0 0 0 "" String null Nil Null 0 0 0 0 0 0 0 Binoculars "add_type_view" "Add Type View" "Adds a new type view." "" "" } //- rjf: file path maps {AddFilePathMap 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 FileOutline "add_file_path_map" "Add File Path Map" "Adds a new file path map." "" "" } //- rjf: themes {EditUserTheme 0 0 0 0 "query:themes" String null Nil Null 0 0 0 0 0 0 0 Palette "edit_user_theme" "Edit User Theme" "Edits the current user's theme." "color" "" } {EditProjectTheme 0 0 0 0 "query:themes" String null Nil Null 0 0 0 0 0 0 0 Palette "edit_project_theme" "Edit Project Theme" "Edits the current project's theme." "color" "" } {AddThemeColor 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Palette "add_theme_color" "Add Theme Color" "Adds a new theme color." "" "" } {ForkTheme 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Palette "fork_theme" "Fork Theme" "Imports all colors from the current theme so they can be individually edited." "" "" } {SaveTheme 0 0 0 0 "" String null Nil Null 1 0 0 0 0 1 1 Save "save_theme" "Save Theme" "Saves all theme colors to a new theme file." "" "" } {SaveAndSetTheme 0 0 0 0 "" String null Nil Null 1 0 0 0 0 1 1 Save "save_and_set_theme" "Save And Set Theme" "Saves all theme colors to a new theme file, and then sets that theme as the selected theme." "" "" } //- rjf: line operations {SetNextStatement 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 RightArrow "set_next_statement" "Set Next Statement" "Sets the selected thread's instruction pointer to the cursor's position." "" "$text_pt," } //- rjf: targets {AddTarget 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Target "add_target" "Add Target" "Adds a new target." "application,executable,debug" "$targets," } {SelectTarget 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 Target "select_target" "Select Target" "Selects a target." "" "" } {EnableTarget 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 CheckFilled "enable_target" "Enable Target" "Enables a target, in addition to all targets currently enabled." "" "" } {DisableTarget 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 CheckHollow "disable_target" "Disable Target" "Disables a target." "" "" } {RemoveTarget 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 Trash "remove_target" "Remove Target" "Removes a target." "delete" "" } //- rjf: attaching {RegisterAsJITDebugger 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "register_as_jit_debugger" "Register As Just-In-Time (JIT) Debugger" "Registers the RAD debugger as the just-in-time (JIT) debugger used by the operating system." "" "" } //- rjf: snap-to-code-location {FindCodeLocation 0 1 0 0 "" FilePath null Nil Null 0 0 0 0 0 1 1 FileOutline "find_code_location" "Find Code Location" "Finds a specific source code location given file, line, and column coordinates. Opens the file if necessary." "" "" } //- rjf: searching {Search 1 1 0 0 "" String null Nil Null 0 0 1 1 1 0 1 Find "search" "Search" "Begins searching within the active interface." "sort,search,filter,find" "" } {SearchBackwards 1 1 0 0 "" String null Nil Null 0 0 1 1 1 0 1 Find "search_backwards" "Search Backwards" "Begins searching backwards within the active interface." "sort,search,filter,find" "" } //- rjf: queries {PickFile 0 0 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 FileOutline "pick_file" "Pick File" "Opens the file browser to pick a file." "" "" } {PickFolder 0 0 0 0 `folder:\\"$input\\"` FilePath null Nil Null 0 1 0 0 0 1 1 FolderOpenFilled "pick_folder" "Pick Folder" "Opens the file browser to pick a folder." "" "" } {PickFileOrFolder 0 0 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 1 0 0 0 1 1 FileOutline "pick_file_or_folder" "Pick File/Folder" "Opens the file browser to pick a file or folder." "" "" } //- rjf: query stack {PushQuery 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "push_query" "Push Query" "Opens a new temporary query interface." "" "" } {CompleteQuery 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "complete_query" "Complete Query" "Completes and closes a query." "" "" } {CancelQuery 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "cancel_query" "Cancel Query" "Closes a query." "" "" } {UpdateQuery 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "update_query" "Update Query" "Updates a query input." "" "" } //- rjf: event buffers {OpenEventBuffer 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "open_event_buffer" "Open Event Buffer" "Opens a new event buffer, to which debugger events will be written, for external processing." "" "" } {CloseEventBuffer 0 1 0 0 "" Cfg null Nil Null 0 0 0 0 0 0 0 Null "close_event_buffer" "Close Event Buffer" "Closes an existing event buffer." "" "" } //- rjf: developer commands {ToggleDevMenu 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "toggle_dev_menu" "Toggle Developer Menu" "Opens and closes the developer menu." "" "" } {LogMarker 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "log_marker" "Log Marker" "Logs a marker in the application log, to denote specific points in time within the log." "" "" } } @enum RD_CmdKind: { `Null`, @expand(D_CmdTable a) `$(a.name)`, @expand(RD_CmdTable, a) `$(a.name)`, @expand(RD_WatchTabFastPathTable, a) `Open$(a.name)`, @expand(RD_ViewTabFastPathTable, a) `Open$(a.name)`, COUNT, `FirstTabFastPathCmd = RD_CmdKind_OpenWatch`, } @struct RD_Query: { `RD_QueryFlags flags`; `RD_RegSlot slot`; `String8 expr`; `String8 view_name`; `CTRL_EntityKind ctrl_entity_kind`; } @struct RD_CmdKindInfo: { `String8 string`; `String8 description`; `String8 search_tags`; `String8 ctx_filter`; `RD_CmdKindFlags flags`; `RD_Query query`; }; @data(RD_CmdKindInfo) @c_file rd_cmd_kind_info_table: { `{0}`, @expand(D_CmdTable, a) ```{ str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.desc)"), str8_lit_comp("$(a.search_tags)"), str8_lit_comp("$(a.ctx_filter)"), (RD_CmdKindFlag_ListInUI*$(a.ui_vis))|(RD_CmdKindFlag_ListInIPCDocs*$(a.ipc_docs_vis))|(RD_CmdKindFlag_ListInTextPt*$(a.text_pt_vis))|(RD_CmdKindFlag_ListInTextRng*$(a.text_rng_vis)), {(RD_QueryFlag_AllowFiles*$(a.q_allow_files))|(RD_QueryFlag_AllowFolders*$(a.q_allow_folders))|(RD_QueryFlag_CodeInput*$(a.q_is_code))|(RD_QueryFlag_KeepOldInput*$(a.q_keep_oi))|(RD_QueryFlag_SelectOldInput*$(a.q_select_oi))|(RD_QueryFlag_Floating*$(a.q_floating))|(RD_QueryFlag_Required*$(a.q_required)), RD_RegSlot_$(a.q_slot), str8_lit_comp("$(a.q_expr)"), str8_lit_comp("$(a.q_view != 'null' -> a.q_view)"), CTRL_EntityKind_$(a.q_ctrl_ent_kind)}}```; @expand(RD_CmdTable, a) ```{ str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.desc)"), str8_lit_comp("$(a.search_tags)"), str8_lit_comp("$(a.ctx_filter)"), (RD_CmdKindFlag_ListInUI*$(a.ui_vis))|(RD_CmdKindFlag_ListInIPCDocs*$(a.ipc_docs_vis))|(RD_CmdKindFlag_ListInTextPt*$(a.text_pt_vis))|(RD_CmdKindFlag_ListInTextRng*$(a.text_rng_vis)), {(RD_QueryFlag_AllowFiles*$(a.q_allow_files))|(RD_QueryFlag_AllowFolders*$(a.q_allow_folders))|(RD_QueryFlag_CodeInput*$(a.q_is_code))|(RD_QueryFlag_KeepOldInput*$(a.q_keep_oi))|(RD_QueryFlag_SelectOldInput*$(a.q_select_oi))|(RD_QueryFlag_Floating*$(a.q_floating))|(RD_QueryFlag_Required*$(a.q_required)), RD_RegSlot_$(a.q_slot), str8_lit_comp("$(a.q_expr)"), str8_lit_comp("$(a.q_view != 'null' -> a.q_view)"), CTRL_EntityKind_$(a.q_ctrl_ent_kind)}}```; @expand(RD_WatchTabFastPathTable, a) ```{ str8_lit_comp("$(a.name_lower)"), str8_lit_comp("Opens a $(a.display_name) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}```; @expand(RD_ViewTabFastPathTable, a) ```{ str8_lit_comp("$(a.name_lower)"), str8_lit_comp("Opens a $(a.display_name) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab}```; } //////////////////////////////// //~ rjf: Default Bindings @table(name key ctrl shift alt) RD_DefaultBindingTable: { //- rjf: low-level target control operations { "kill_all" F5 0 shift 0 } { "step_into_inst" F11 0 0 alt } { "step_over_inst" F10 0 0 alt } { "step_out" F11 0 shift 0 } { "halt" X ctrl shift 0 } { "halt" Pause 0 0 0 } //- rjf: high-level composite target control operations { "run" F5 0 0 0 } { "restart" F5 ctrl shift 0 } { "step_into" F11 0 0 0 } { "step_over" F10 0 0 0 } { "run_to_line" F10 ctrl 0 0 } { "set_next_statement" F10 ctrl shift 0 } //- rjf: font sizes { "inc_window_font_size" Equal 0 0 alt } { "dec_window_font_size" Minus 0 0 alt } //- rjf: windows { "window" N ctrl shift 0 } { "toggle_fullscreen" Return ctrl 0 0 } //- rjf: panel splitting { "new_panel_right" P ctrl 0 0 } { "new_panel_down" Minus ctrl 0 0 } //- rjf: panel rotation { "rotate_panel_columns" 2 ctrl 0 0 } //- rjf: focused panel changing { "next_panel" Comma ctrl 0 0 } { "prev_panel" Comma ctrl shift 0 } { "focus_panel_right" Right ctrl 0 alt } { "focus_panel_left" Left ctrl 0 alt } { "focus_panel_up" Up ctrl 0 alt } { "focus_panel_down" Down ctrl 0 alt } //- rjf: undo/redo { "undo" Z ctrl 0 0 } { "redo" Y ctrl 0 0 } //- rjf: focus history { "go_back" Left 0 0 alt } { "go_forward" Right 0 0 alt } //- rjf: panel removal { "close_panel" P ctrl shift alt } //- rjf: panel tab { "next_tab" PageDown ctrl 0 0 } { "prev_tab" PageUp ctrl 0 0 } { "next_tab" Tab ctrl 0 0 } { "prev_tab" Tab ctrl shift 0 } { "move_tab_right" PageDown ctrl shift 0 } { "move_tab_left" PageUp ctrl shift 0 } { "close_tab" W ctrl 0 0 } { "tab_bar_top" Up ctrl shift alt } { "tab_bar_bottom" Down ctrl shift alt } { "open_tab" T ctrl 0 0 } //- rjf: files { "open" O ctrl 0 0 } { "switch" I ctrl 0 0 } { "switch_to_partner_file" O 0 0 alt } //- rjf: setting config paths { "open_user" N ctrl shift alt } { "open_project" N ctrl 0 alt } { "open_user" O ctrl shift alt } { "open_project" O ctrl 0 alt } { "save_user" S ctrl shift alt } { "save_project" S ctrl shift 0 } //- rjf: meta controls { "edit" F2 0 0 0 } { "accept" Return 0 0 0 } { "accept" Space 0 0 0 } { "cancel" Esc 0 0 0 } //- rjf: directional movement & text controls { "move_left" Left 0 0 0 } { "move_right" Right 0 0 0 } { "move_up" Up 0 0 0 } { "move_down" Down 0 0 0 } { "move_left_select" Left 0 shift 0 } { "move_right_select" Right 0 shift 0 } { "move_up_select" Up 0 shift 0 } { "move_down_select" Down 0 shift 0 } { "move_left_chunk" Left ctrl 0 0 } { "move_right_chunk" Right ctrl 0 0 } { "move_up_chunk" Up ctrl 0 0 } { "move_down_chunk" Down ctrl 0 0 } { "move_up_page" PageUp 0 0 0 } { "move_down_page" PageDown 0 0 0 } { "move_up_whole" Home ctrl 0 0 } { "move_down_whole" End ctrl 0 0 } { "move_left_chunk_select" Left ctrl shift 0 } { "move_right_chunk_select" Right ctrl shift 0 } { "move_up_chunk_select" Up ctrl shift 0 } { "move_down_chunk_select" Down ctrl shift 0 } { "move_up_page_select" PageUp 0 shift 0 } { "move_down_page_select" PageDown 0 shift 0 } { "move_up_whole_select" Home ctrl shift 0 } { "move_down_whole_select" End ctrl shift 0 } { "move_up_reorder" Up 0 0 alt } { "move_down_reorder" Down 0 0 alt } { "move_home" Home 0 0 0 } { "move_end" End 0 0 0 } { "move_home_select" Home 0 shift 0 } { "move_end_select" End 0 shift 0 } { "select_all" A ctrl 0 0 } { "delete_single" Delete 0 0 0 } { "delete_chunk" Delete ctrl 0 0 } { "backspace_single" Backspace 0 0 0 } { "backspace_chunk" Backspace ctrl 0 0 } { "copy" C ctrl 0 0 } { "copy" Insert ctrl 0 0 } { "cut" X ctrl 0 0 } { "paste" V ctrl 0 0 } { "paste" Insert 0 shift 0 } { "insert_text" Null 0 0 0 } //- rjf: secondary navigation { "move_next" Tab 0 0 0 } { "move_prev" Tab 0 shift 0 } //- rjf: code navigation { "goto_line" G ctrl 0 0 } { "goto_address" G 0 0 alt } { "search" F ctrl 0 0 } { "search_backwards" R ctrl 0 0 } { "find_next" F3 0 0 0 } { "find_prev" F3 shift 0 0 } //- rjf: thread finding { "find_selected_thread" F4 0 0 0 } //- rjf: name finding { "goto_name" J ctrl 0 0 } { "goto_name_at_cursor" F12 0 0 0 } //- rjf: watch expressions { "toggle_watch_expr_at_cursor" W 0 0 alt } { "toggle_watch_expr_at_mouse" D ctrl 0 0 } { "toggle_watch_pin" F9 ctrl 0 0 } //- rjf: breakpoints { "toggle_breakpoint" F9 0 0 0 } { "add_address_breakpoint" F9 0 shift 0 } { "add_function_breakpoint" F9 ctrl shift 0 } //- rjf: attaching { "attach" F6 0 shift 0 } //- rjf: command lister { "open_palette" F1 0 0 0 } { "open_palette" P ctrl shift 0 } //- rjf: developer commands { "log_marker" M ctrl shift alt } { "toggle_dev_menu" D ctrl shift alt } } @data(`struct {String8 string; CFG_Binding binding;}`) @c_file rd_default_binding_table: { @expand(RD_DefaultBindingTable a) ```{str8_lit_comp("$(a.name)"), {OS_Key_$(a.key), 0 $(a.ctrl != 0 -> `|OS_Modifier_Ctrl`) $(a.shift != 0 -> `|OS_Modifier_Shift`) $(a.alt != 0 -> `|OS_Modifier_Alt`)}}```; } //////////////////////////////// //~ rjf: Binding Version Remap Table @table(old_name new_name) RD_BindingVersionRemapTable: { {"commands" "run_command"} {"load_user" "open_user"} {"load_profile" "open_profile"} {"load_project" "open_project"} {"open_profile" "open_project"} {"address_breakpoint" "add_address_breakpoint"} {"function_breakpoint" "add_function_breakpoint"} {"toggle_breakpoint_cursor" "toggle_breakpoint"} } @data(String8) rd_binding_version_remap_old_name_table: { @expand(RD_BindingVersionRemapTable a) `str8_lit_comp("$(a.old_name)")` } @data(String8) rd_binding_version_remap_new_name_table: { @expand(RD_BindingVersionRemapTable a) `str8_lit_comp("$(a.new_name)")` } //////////////////////////////// //~ rjf: Icons @table(name, text) RD_IconTable: { (Null "") (FolderOpenOutline "b") (FolderClosedOutline "c") (FolderOpenFilled "B") (FolderClosedFilled "C") (FileOutline "f") (FileFilled "F") (Play "g") (PlayStepForward "h") (Pause "r") (Stop "s") (Info "i") (WarningSmall "w") (WarningBig "W") (Unlocked "k") (Locked "K") (LeftArrow "L") (RightArrow "R") (UpArrow "U") (DownArrow "D") (Gear "G") (Pencil "P") (Trash "3") (Pin "p") (RadioHollow "O") (RadioFilled "o") (CheckHollow "!") (CheckFilled "1") (Check "V") (LeftCaret "<") (RightCaret ">") (UpCaret "^") (DownCaret "v") (UpScroll "9") (DownScroll "0") (LeftScroll "7") (RightScroll "8") (Add "+") (Minus "-") (Thread "'") (Threads '\\"') (Machine "M") (CircleFilled ".") (X "x") (Refresh "q") (Undo "j") (Redo "u") (Save "m") (Window "n") (Target "l") (Clipboard "a") (Scheduler "z") (Module "y") (XSplit "X") (YSplit "Y") (ClosePanel "S") (StepInto "T") (StepOver "Z") (StepOut "d") (Find "N") (Palette "E") (Thumbnails "H") (Glasses "e") (Binoculars "I") (List "J") (Grid "A") (QuestionMark "?") (Person "4") (Briefcase "5") (Dot "6") (Bitmap "&") (Cube "*") (WindowRestore "(") (WindowMinimize ")") (Duplicate "#") } @enum RD_IconKind: { @expand(RD_IconTable a) `$(a.name)`, COUNT, } @data(String8) rd_icon_kind_text_table: { @expand(RD_IconTable a) `str8_lit_comp("$(a.text)")`; } //////////////////////////////// //~ rjf: Theme Tables @table(name_upper name_lower display_string cfg) RD_ThemePresetTable: { //- rjf: default dark theme { DefaultDark default_dark "Default (Dark)", ```theme: { theme_color: {tags:"background", value: 0x1b1b1bff } theme_color: {tags:"alt background", value: 0x222222ff } theme_color: {tags:"pop background", value: 0x355b6eff } theme_color: {tags:"fresh background", value: 0x31393dff } theme_color: {tags:"match background", value: 0x31393dff } theme_color: {tags:"border", value: 0x404040ff } theme_color: {tags:"text", value: 0xe5e5e5ff } theme_color: {tags:"weak text", value: 0xa4a4a4ff } theme_color: {tags:"good text", value: 0x32a852ff } theme_color: {tags:"neutral text", value: 0x3a90bbff } theme_color: {tags:"bad text", value: 0xcf5242ff } theme_color: {tags:"hover", value: 0xffffffff } theme_color: {tags:"focus overlay", value: 0xfda20012 } theme_color: {tags:"focus border", value: 0xfda200ff } theme_color: {tags:"cursor", value: 0x8aff00ff } theme_color: {tags:"selection", value: 0x99ccff0f } theme_color: {tags:"inactive background", value: 0x0000002f } theme_color: {tags:"drop_shadow", value: 0x0000007f } theme_color: {tags:"good_pop background", value: 0x2c5b36ff } theme_color: {tags:"good_pop border", value: 0x568761ff } theme_color: {tags:"good_pop hover", value: 0xe3f5d3ff } theme_color: {tags:"good_pop weak text", value: 0xe3f5d3ff } theme_color: {tags:"bad_pop background", value: 0x803425ff } theme_color: {tags:"bad_pop hover", value: 0xff825cff } theme_color: {tags:"code_default", value: 0xcbcbcbff } theme_color: {tags:"code_symbol", value: 0x42a2cfff } theme_color: {tags:"code_type", value: 0xfec746ff } theme_color: {tags:"code_local", value: 0x98bc80ff } theme_color: {tags:"code_register", value: 0xb7afd5ff } theme_color: {tags:"code_keyword", value: 0xb38d4cff } theme_color: {tags:"code_delimiter_or_operator", value: 0x767676ff } theme_color: {tags:"code_numeric", value: 0x98abb1ff } theme_color: {tags:"code_numeric_alt_digit_group", value: 0x738287ff } theme_color: {tags:"code_string", value: 0x98abb1ff } theme_color: {tags:"code_meta", value: 0xd96759ff } theme_color: {tags:"code_comment", value: 0x717171ff } theme_color: {tags:"line_info_0", value: 0x4f3022ff } theme_color: {tags:"line_info_1", value: 0x4f3e15ff } theme_color: {tags:"line_info_2", value: 0x434e2aff } theme_color: {tags:"line_info_3", value: 0x36241fff } theme_color: {tags:"line_info_4", value: 0x4f3022ff } theme_color: {tags:"line_info_5", value: 0x4f3e15ff } theme_color: {tags:"line_info_6", value: 0x434e2aff } theme_color: {tags:"line_info_7", value: 0x36241fff } theme_color: {tags:"thread_0", value: 0xffcb7fff } theme_color: {tags:"thread_1", value: 0xb2ff65ff } theme_color: {tags:"thread_2", value: 0xff99e5ff } theme_color: {tags:"thread_3", value: 0x6598ffff } theme_color: {tags:"thread_4", value: 0x65ffcbff } theme_color: {tags:"thread_5", value: 0xff9819ff } theme_color: {tags:"thread_6", value: 0x9932ffff } theme_color: {tags:"thread_7", value: 0x65ff4cff } theme_color: {tags:"thread_unwound", value: 0xb2ccd8ff } theme_color: {tags:"thread_error", value: 0xb23219ff } theme_color: {tags:"breakpoint", value: 0xa72911ff } theme_color: {tags:"floating background", value: 0x1b1b1baf } theme_color: {tags:"floating background alt", value: 0x0000005f } theme_color: {tags:"floating background fresh", value: 0x31393d5f } theme_color: {tags:"floating border", value: 0xbfbfbf1f } theme_color: {tags:"floating scroll_bar background", value: 0x3b3b3b5f } theme_color: {tags:"floating scroll_bar border", value: 0x5f5f5f5f } theme_color: {tags:"menu_bar background", value: 0x2b3740ff } theme_color: {tags:"menu_bar border", value: 0x3e4c57ff } theme_color: {tags:"scroll_bar background", value: 0x2b2b2bff } theme_color: {tags:"scroll_bar border", value: 0x3f3f3fff } theme_color: {tags:"implicit background", value: 0x00000000 } theme_color: {tags:"implicit border", value: 0x00000000 } theme_color: {tags:"hollow background", value: 0x00000000 } theme_color: {tags:"hollow border", value: 0xffffff1f } theme_color: {tags:"tab background", value: 0x6f5135ff } theme_color: {tags:"tab border", value: 0x8a6e54ff } theme_color: {tags:"tab inactive background", value: 0x2b3740ff } theme_color: {tags:"tab inactive border", value: 0x3e4c57ff } theme_color: {tags:"tab auto background", value: 0x693847ff } theme_color: {tags:"tab auto border", value: 0x9e6274ff } theme_color: {tags:"tab auto inactive background", value: 0x2f2633ff } theme_color: {tags:"tab auto inactive border", value: 0x685073ff } theme_color: {tags:"drop_site background", value: 0xffffff05 } theme_color: {tags:"drop_site border", value: 0xffffff0f } } ``` } //- rjf: default light theme { DefaultLight default_light "Default (Light)", ```theme: { theme_color:{ tags: background , value: 0xffffffff } theme_color:{ tags: "alt background" , value: 0xf8f8f8ff } theme_color:{ tags: "pop background" , value: 0xcbe4f2ff } theme_color:{ tags: "menu_bar pop background" , value: 0x5aabd9ff } theme_color:{ tags: "fresh background" , value: 0xeaddceff } theme_color:{ tags: "match background" , value: 0xc1e9c4ff } theme_color:{ tags: border , value: 0xcbcbcbff } theme_color:{ tags: text , value: 0xff } theme_color:{ tags: "weak text" , value: 0x727272ff } theme_color:{ tags: "good text" , value: 0x217538ff } theme_color:{ tags: "neutral text" , value: 0x1a5b7cff } theme_color:{ tags: "bad text" , value: 0x972717ff } theme_color:{ tags: hover , value: 0xff } theme_color:{ tags: "focus overlay" , value: 0x67ff4b } theme_color:{ tags: "focus border" , value: 0x67ffff } theme_color:{ tags: cursor , value: 0xff } theme_color:{ tags: selection , value: 0x283d5166 } theme_color:{ tags: "inactive background" , value: 0x8 } theme_color:{ tags: drop_shadow , value: 0xb } theme_color:{ tags: "good_pop background" , value: 0x90c09aff } theme_color:{ tags: "good_pop border" , value: 0x1e7231ff } theme_color:{ tags: "good_pop hover" , value: 0xe3f5d3ff } theme_color:{ tags: "good_pop weak text" , value: 0xe3f5d3ff } theme_color:{ tags: "good_pop text" , value: 0xe3f5d3ff } theme_color:{ tags: "bad_pop background" , value: 0xa93620ff } theme_color:{ tags: "bad_pop text" , value: 0xffffffff } theme_color:{ tags: "bad_pop text weak" , value: 0xffffffff } theme_color:{ tags: "menu_bar bad_pop background" , value: 0xff2a00ff } theme_color:{ tags: "menu_bar bad_pop text" , value: 0xffffffff } theme_color:{ tags: "bad_pop hover" , value: 0xff825cff } theme_color:{ tags: code_default , value: 0x80808ff } theme_color:{ tags: code_symbol , value: 0x4ac3ff } theme_color:{ tags: code_type , value: 0xf46200ff } theme_color:{ tags: code_local , value: 0x317c00ff } theme_color:{ tags: code_register , value: 0x9a00ffff } theme_color:{ tags: code_keyword , value: 0xff0600ff } theme_color:{ tags: code_delimiter_or_operator , value: 0x8a8a8aff } theme_color:{ tags: code_numeric , value: 0x7d49ff } theme_color:{ tags: code_numeric_alt_digit_group , value: 0xb56aff } theme_color:{ tags: code_string , value: 0x63549fff } theme_color:{ tags: code_meta , value: 0xd96759ff } theme_color:{ tags: code_comment , value: 0x717171ff } theme_color:{ tags: line_info_0 , value: 0xe6d5cdff } theme_color:{ tags: line_info_1 , value: 0xdbcfb2ff } theme_color:{ tags: line_info_2 , value: 0xddeac1ff } theme_color:{ tags: line_info_3 , value: 0xddc4bdff } theme_color:{ tags: line_info_4 , value: 0xba917eff } theme_color:{ tags: thread_0 , value: 0xffa700ff } theme_color:{ tags: thread_1 , value: 0xb41fff } theme_color:{ tags: thread_2 , value: 0xff99e5ff } theme_color:{ tags: thread_3 , value: 0x6598ffff } theme_color:{ tags: thread_4 , value: 0x65ffcbff } theme_color:{ tags: thread_5 , value: 0xff9819ff } theme_color:{ tags: thread_6 , value: 0x9932ffff } theme_color:{ tags: thread_7 , value: 0x65ff4cff } theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff } theme_color:{ tags: thread_error , value: 0xb23219ff } theme_color:{ tags: breakpoint , value: 0xff2800ff } theme_color:{ tags: "floating background" , value: 0xffffffc7 } theme_color:{ tags: "floating background alt" , value: 0x23 } theme_color:{ tags: "floating background fresh" , value: 0xeaddceff } theme_color:{ tags: "floating border" , value: 0x88888884 } theme_color:{ tags: "scroll_bar background" , value: 0xe9e9e9ff } theme_color:{ tags: "scroll_bar border" , value: 0x5f5f5f5f } theme_color:{ tags: "floating scroll_bar background" , value: 0xe9e9e9ff } theme_color:{ tags: "floating scroll_bar border" , value: 0x5f5f5f5f } theme_color:{ tags: "menu_bar background" , value: 0x2b6b9aff } theme_color:{ tags: "menu_bar border" , value: 0x4d } theme_color:{ tags: "menu_bar text" , value: 0xffffffff } theme_color:{ tags: "menu_bar text weak" , value: 0xffffffff } theme_color:{ tags: "good menu_bar text" , value: 0x70db8dff } theme_color:{ tags: "bad menu_bar text" , value: 0xffa79bff } theme_color:{ tags: "neutral menu_bar text" , value: 0xc4dbe7ff } theme_color:{ tags: "implicit background" , value: 0x00000000 } theme_color:{ tags: "implicit border" , value: 0x00000000 } theme_color:{ tags: "hollow background" , value: 0x00000000 } theme_color:{ tags: "hollow border" , value: 0xffffff1f } theme_color:{ tags: "tab text" , value: 0xffffffff } theme_color:{ tags: "tab text weak" , value: 0xffffffff } theme_color:{ tags: "tab background" , value: 0xb67e48ff } theme_color:{ tags: "tab border" , value: 0x875b31ff } theme_color:{ tags: "tab inactive background" , value: 0xcacacaff } theme_color:{ tags: "tab inactive border" , value: 0xb5b5b5ff } theme_color:{ tags: "tab auto background" , value: 0xc41c69ff } theme_color:{ tags: "tab auto border" , value: 0x981039ff } theme_color:{ tags: "tab auto inactive background" , value: 0x9b88a3ff } theme_color:{ tags: "tab auto inactive border" , value: 0x373737ff } theme_color:{ tags: "drop_site background" , value: 0xffffff05 } theme_color:{ tags: "drop_site border" , value: 0xffffff0f } } ``` } //- rjf: vs dark theme { VSDark vs_dark "VS (Dark)", ```theme: { theme_color:{ tags: background , value: 0x1f1f1fff } theme_color:{ tags: "alt background" , value: 0x222222ff } theme_color:{ tags: "pop background" , value: 0x383167ff } theme_color:{ tags: "fresh background" , value: 0x31393dff } theme_color:{ tags: "match background" , value: 0x31393dff } theme_color:{ tags: border , value: 0x404040ff } theme_color:{ tags: text , value: 0xe5e5e5ff } theme_color:{ tags: "weak text" , value: 0xa4a4a4ff } theme_color:{ tags: "good text" , value: 0x32a852ff } theme_color:{ tags: "neutral text" , value: 0x3a90bbff } theme_color:{ tags: "bad text" , value: 0xcf5242ff } theme_color:{ tags: hover , value: 0xffffffff } theme_color:{ tags: "focus overlay" , value: 0x7160e81e } theme_color:{ tags: "focus border" , value: 0x7160e8ff } theme_color:{ tags: cursor , value: 0x8aff00ff } theme_color:{ tags: selection , value: 0x99ccff0f } theme_color:{ tags: "inactive background" , value: 0x0000002f } theme_color:{ tags: drop_shadow , value: 0x0000007f } theme_color:{ tags: "good_pop background" , value: 0x2c5b36ff } theme_color:{ tags: "good_pop border" , value: 0x568761ff } theme_color:{ tags: "good_pop hover" , value: 0xe3f5d3ff } theme_color:{ tags: "good_pop weak text" , value: 0xe3f5d3ff } theme_color:{ tags: "bad_pop background" , value: 0x803425ff } theme_color:{ tags: "bad_pop hover" , value: 0xff825cff } theme_color:{ tags: code_default , value: 0xe0e0e0ff } theme_color:{ tags: code_symbol , value: 0xdcdcaaff } theme_color:{ tags: code_type , value: 0x4ec9b0ff } theme_color:{ tags: code_local , value: 0x9cdcfeff } theme_color:{ tags: code_register , value: 0xb7afd5ff } theme_color:{ tags: code_keyword , value: 0x569cd6ff } theme_color:{ tags: code_delimiter_or_operator , value: 0x767676ff } theme_color:{ tags: code_numeric , value: 0xb5cea8ff } theme_color:{ tags: code_numeric_alt_digit_group , value: 0x7c986dff } theme_color:{ tags: code_string , value: 0xd69d85ff } theme_color:{ tags: code_meta , value: 0x9b9b9bff } theme_color:{ tags: code_comment , value: 0x51a644ff } theme_color:{ tags: line_info_0 , value: 0x4f3022ff } theme_color:{ tags: line_info_1 , value: 0x4f3e15ff } theme_color:{ tags: line_info_2 , value: 0x434e2aff } theme_color:{ tags: line_info_3 , value: 0x36241fff } theme_color:{ tags: line_info_4 , value: 0x4f3022ff } theme_color:{ tags: line_info_5 , value: 0x4f3e15ff } theme_color:{ tags: line_info_6 , value: 0x434e2aff } theme_color:{ tags: line_info_7 , value: 0x36241fff } theme_color:{ tags: thread_0 , value: 0xffdc48ff } theme_color:{ tags: thread_1 , value: 0xb2ff65ff } theme_color:{ tags: thread_2 , value: 0xff99e5ff } theme_color:{ tags: thread_3 , value: 0x6598ffff } theme_color:{ tags: thread_4 , value: 0x65ffcbff } theme_color:{ tags: thread_5 , value: 0xff9819ff } theme_color:{ tags: thread_6 , value: 0x9932ffff } theme_color:{ tags: thread_7 , value: 0x65ff4cff } theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff } theme_color:{ tags: thread_error , value: 0xb23219ff } theme_color:{ tags: breakpoint , value: 0xa72911ff } theme_color:{ tags: "floating background" , value: 0x1b1b1baf } theme_color:{ tags: "floating background alt" , value: 0x0000005f } theme_color:{ tags: "floating background fresh" , value: 0x31393d5f } theme_color:{ tags: "floating border" , value: 0xbfbfbf1f } theme_color:{ tags: "floating scroll_bar background" , value: 0x3b3b3b5f } theme_color:{ tags: "floating scroll_bar border" , value: 0x5f5f5f5f } theme_color:{ tags: "scroll_bar background" , value: 0x2b2b2bff } theme_color:{ tags: "scroll_bar border" , value: 0x3f3f3fff } theme_color:{ tags: "implicit background" , value: 0x00000000 } theme_color:{ tags: "implicit border" , value: 0x00000000 } theme_color:{ tags: "hollow background" , value: 0x00000000 } theme_color:{ tags: "hollow border" , value: 0xffffff1f } theme_color:{ tags: "tab background" , value: 0x333333ff } theme_color:{ tags: "tab border" , value: 0x7160e8ff } theme_color:{ tags: "tab inactive background" , value: 0x171717ff } theme_color:{ tags: "tab inactive border" , value: 0x3e4c57ff } theme_color:{ tags: "tab auto background" , value: 0x3f386dff } theme_color:{ tags: "tab auto border" , value: 0x7160e8ff } theme_color:{ tags: "tab auto inactive background" , value: 0x2f2633ff } theme_color:{ tags: "tab auto inactive border" , value: 0x685073ff } theme_color:{ tags: "drop_site background" , value: 0xffffff05 } theme_color:{ tags: "drop_site border" , value: 0xffffff0f } } ``` } //- rjf: to-do { VSLight vs_light "VS (Light)", ```theme: { theme_color:{tags: background, value: 0xffffffff} theme_color:{tags: "alt background", value: 0xefefefff} theme_color:{tags: "pop background", value: 0xe3eaf2ff} theme_color:{tags: "fresh background", value: 0xeccbbeff} theme_color:{tags: "match background", value: 0xedcbf9ff} theme_color:{tags: border, value: 0xe7e7e7ff} theme_color:{tags: text, value: 0xff} theme_color:{tags: "weak text", value: 0x353535ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: hover, value: 0xa7ffff} theme_color:{tags: "focus overlay", value: 0x8eff3f} theme_color:{tags: "focus border", value: 0x8effff} theme_color:{tags: cursor, value: 0xff} theme_color:{tags: selection, value: 0x56aaff77} theme_color:{tags: "inactive background", value: 0x17} theme_color:{tags: drop_shadow, value: 0xe7b27} theme_color:{tags: "good_pop background", value: 0x21a43dff} theme_color:{tags: "good_pop border", value: 0x21a43dff} theme_color:{tags: "good_pop hover", value: 0xe3f5d3ff} theme_color:{tags: "good_pop weak text", value: 0xe3f5d3ff} theme_color:{tags: "good_pop text", value: 0xe3f5d3ff} theme_color:{tags: "bad_pop background", value: 0xcb3f23ff} theme_color:{tags: "bad_pop text", value: 0xffcdc4ff} theme_color:{tags: "bad_pop text weak", value: 0xffcdc4ff} theme_color:{tags: "bad_pop hover", value: 0xff825cff} theme_color:{tags: code_default, value: 0x000000ff} theme_color:{tags: code_symbol, value: 0x74531fff} theme_color:{tags: code_type, value: 0x2b91afff} theme_color:{tags: code_local, value: 0x1f377fff} theme_color:{tags: code_register, value: 0x8a1bffff} theme_color:{tags: code_keyword, value: 0x0000ffff} theme_color:{tags: code_delimiter_or_operator, value: 0x767676ff} theme_color:{tags: code_numeric, value: 0xff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x1d1d1dff} theme_color:{tags: code_string, value: 0xa61515ff} theme_color:{tags: code_meta, value: 0x808080ff} theme_color:{tags: code_comment, value: 0x008000ff} theme_color:{tags: line_info_0, value: 0xb5d9c8ff} theme_color:{tags: line_info_1, value: 0xa9c1d0ff} theme_color:{tags: line_info_2, value: 0x99abc5ff} theme_color:{tags: line_info_3, value: 0xc6bcd5ff} theme_color:{tags: thread_0, value: 0xffb141ff} theme_color:{tags: thread_1, value: 0x66c407ff} theme_color:{tags: thread_unwound, value: 0x67b3d7ff} theme_color:{tags: thread_error, value: 0xff2900ff} theme_color:{tags: breakpoint, value: 0xff2800ff} theme_color:{tags: "floating background", value: 0xffffffff} theme_color:{tags: "floating background alt", value: 0x11} theme_color:{tags: "floating background fresh", value: 0xa0c2d318} theme_color:{tags: "floating border", value: 0x50} theme_color:{tags: "floating scroll_bar background", value: 0x3b3b3b5f} theme_color:{tags: "floating scroll_bar border", value: 0x5f5f5f5f} theme_color:{tags: "menu_bar background", value: 0xccd5f0ff} theme_color:{tags: "menu_bar border", value: 0xbabdc3ff} theme_color:{tags: "scroll_bar background", value: 0xe4e4e4ff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0xf5cc84ff} theme_color:{tags: "tab border", value: 0xae7718ff} theme_color:{tags: "tab inactive background", value: 0x3b4f81ff} theme_color:{tags: "tab inactive text", value: 0xffffffff} theme_color:{tags: "tab inactive border", value: 0x3b4f81ff} theme_color:{tags: "tab auto background", value: 0xe99595ff} theme_color:{tags: "tab auto border", value: 0xff6262ff} theme_color:{tags: "tab auto inactive background", value: 0xac6060ff} theme_color:{tags: "tab auto inactive border", value: 0xff6262ff} theme_color:{tags: "drop_site background", value: 0xffffff05} theme_color:{tags: "drop_site border", value: 0xa7ffff} } ``` } //- rjf: solarized (dark) theme { SolarizedDark solarized_dark "Solarized (Dark)", ```theme: { theme_color:{tags: background, value: 0x002a35ff} theme_color:{tags: "alt background", value: 0x053542ff} theme_color:{tags: "pop background", value: 0x355b6eff} theme_color:{tags: "fresh background", value: 0x31393dff} theme_color:{tags: "match background", value: 0x31393dff} theme_color:{tags: border, value: 0x65166ff} theme_color:{tags: text, value: 0xeee8d5ff} theme_color:{tags: "weak text", value: 0x93a1a1ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: hover, value: 0xca4b16ff} theme_color:{tags: "focus overlay", value: 0xca4b151f} theme_color:{tags: "focus border", value: 0xca4b16ff} theme_color:{tags: cursor, value: 0xca4b16ff} theme_color:{tags: selection, value: 0x99ccff0f} theme_color:{tags: "inactive background", value: 0x0000002f} theme_color:{tags: drop_shadow, value: 0x0000007f} theme_color:{tags: "good_pop background", value: 0x5f8700ff} theme_color:{tags: "good_pop border", value: 0x5f8700ff} theme_color:{tags: "bad_pop background", value: 0x810000ff} theme_color:{tags: code_default, value: 0x839496ff} theme_color:{tags: code_symbol, value: 0xb3880eff} theme_color:{tags: code_type, value: 0xb3880eff} theme_color:{tags: code_local, value: 0xeee8d5ff} theme_color:{tags: code_register, value: 0xeee8d5ff} theme_color:{tags: code_keyword, value: 0x849804ff} theme_color:{tags: code_delimiter_or_operator, value: 0x839496ff} theme_color:{tags: code_numeric, value: 0x2aa198ff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x19766bff} theme_color:{tags: code_string, value: 0x2aa198ff} theme_color:{tags: code_meta, value: 0xca4b16ff} theme_color:{tags: code_comment, value: 0x586e75ff} theme_color:{tags: line_info_0, value: 0x4f3022ff} theme_color:{tags: line_info_1, value: 0x4f3e15ff} theme_color:{tags: line_info_2, value: 0x434e2aff} theme_color:{tags: line_info_3, value: 0x36241fff} theme_color:{tags: thread_0, value: 0xffcb7fff} theme_color:{tags: thread_1, value: 0xb2ff65ff} theme_color:{tags: thread_unwound, value: 0xb2ccd8ff} theme_color:{tags: thread_error, value: 0xb23219ff} theme_color:{tags: breakpoint, value: 0xa72911ff} theme_color:{tags: "floating background", value: 0x2a3574} theme_color:{tags: "floating background alt", value: 0x4f} theme_color:{tags: "floating background fresh", value: 0x31393d5f} theme_color:{tags: "floating scroll_bar background", value: 0x53542ff} theme_color:{tags: "scroll_bar background", value: 0x53542ff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0x586e75ff} theme_color:{tags: "tab border", value: 0x90abb3ff} theme_color:{tags: "tab inactive background", value: 0x0} theme_color:{tags: "tab inactive border", value: 0x33494fff} theme_color:{tags: "tab auto background", value: 0x565ed2ff} theme_color:{tags: "tab auto border", value: 0xa2a6dfff} theme_color:{tags: "tab auto inactive background", value: 0} theme_color:{tags: "tab auto inactive border", value: 0x595fbcff} theme_color:{tags: "drop_site background", value: 0xffffff05} theme_color:{tags: "drop_site border", value: 0xffffff0f} } ``` } //- rjf: solarized light { SolarizedLight solarized_light "Solarized (Light)", ```theme: { theme_color:{tags: background, value: 0xfdf6e3ff} theme_color:{tags: "alt background", value: 0xeee8d5ff} theme_color:{tags: "pop background", value: 0x29a19890} theme_color:{tags: "fresh background", value: 0xf7d38dff} theme_color:{tags: "match background", value: 0xdcddddff} theme_color:{tags: border, value: 0xd1ccbdff} theme_color:{tags: "weak text", value: 0x93a1a1ff} theme_color:{tags: text, value: 0x657b83ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: hover, value: 0xca4b16ff} theme_color:{tags: "focus overlay", value: 0xca4b1454} theme_color:{tags: "focus border", value: 0xca4b16ff} theme_color:{tags: cursor, value: 0xca4b16ff} theme_color:{tags: selection, value: 0x8594a264} theme_color:{tags: "inactive background", value: 0x14} theme_color:{tags: drop_shadow, value: 0x3a} theme_color:{tags: "good_pop background", value: 0xd1e99aff} theme_color:{tags: "good_pop border", value: 0xd1e99aff} theme_color:{tags: "bad_pop background", value: 0xd26c6cff} theme_color:{tags: "bad_pop border", value: 0xd26c6cff} theme_color:{tags: "bad_pop weak text", value: 0xffffffff} theme_color:{tags: "bad_pop text", value: 0xffffffff} theme_color:{tags: code_default, value: 0x839496ff} theme_color:{tags: code_symbol, value: 0xb3880eff} theme_color:{tags: code_type, value: 0xb3880eff} theme_color:{tags: code_local, value: 0x657b83ff} theme_color:{tags: code_register, value: 0x947298ff} theme_color:{tags: code_keyword, value: 0x849804ff} theme_color:{tags: code_delimiter_or_operator, value: 0x839496ff} theme_color:{tags: code_numeric, value: 0x2aa198ff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x19766bff} theme_color:{tags: code_string, value: 0x2aa198ff} theme_color:{tags: code_meta, value: 0xca4b16ff} theme_color:{tags: code_comment, value: 0x586e75ff} theme_color:{tags: line_info_0, value: 0xeee1dbff} theme_color:{tags: line_info_1, value: 0xe5d5b1ff} theme_color:{tags: line_info_2, value: 0xd9e8b6ff} theme_color:{tags: line_info_3, value: 0xf5d5ccff} theme_color:{tags: thread_0, value: 0xffa100ff} theme_color:{tags: thread_1, value: 0x6edd00ff} theme_color:{tags: thread_unwound, value: 0x708f9eff} theme_color:{tags: thread_error, value: 0xff5231ff} theme_color:{tags: breakpoint, value: 0xff411dff} theme_color:{tags: "floating background", value: 0xfdf6e3b1} theme_color:{tags: "floating background alt", value: 0x22} theme_color:{tags: "floating background fresh", value: 0xf7d38dff} theme_color:{tags: "scroll_bar background", value: 0xeee6d0ff} theme_color:{tags: "scroll_bar floating background", value: 0xd5ccb5ff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0xfdf6e3ff} theme_color:{tags: "tab inactive background", value: 0xe0d6bbff} theme_color:{tags: "tab auto background", value: 0xf5cfe1ff} theme_color:{tags: "tab auto border", value: 0xa2a6dfff} theme_color:{tags: "tab auto inactive background", value: 0xc8a5b5ff} theme_color:{tags: "tab auto inactive border", value: 0x595fbcff} theme_color:{tags: "drop_site background", value: 0x29a19890} theme_color:{tags: "drop_site border", value: 0x81ddd690} } ``` } //- rjf: handmade hero theme { HandmadeHero handmade_hero "Handmade Hero", ```theme: { theme_color:{tags: background, value: 0x0c0c0cff} theme_color:{tags: "alt background", value: 0x161616ff} theme_color:{tags: "pop background", value: 0x355b6eff} theme_color:{tags: "fresh background", value: 0x31393dff} theme_color:{tags: "match background", value: 0x31393dff} theme_color:{tags: border, value: 0x404040ff} theme_color:{tags: text, value: 0xcac1b6ff} theme_color:{tags: "weak text", value: 0xa08563ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: hover, value: 0xffffffff} theme_color:{tags: "focus overlay", value: 0x7485971e} theme_color:{tags: "focus border", value: 0x5e6b79ff} theme_color:{tags: cursor, value: 0x00ee00ff} theme_color:{tags: selection, value: 0x99ccff0f} theme_color:{tags: "inactive background", value: 0x0000002f} theme_color:{tags: drop_shadow, value: 0x0000007f} theme_color:{tags: "good_pop background", value: 0x2c5b36ff} theme_color:{tags: "good_pop border", value: 0x568761ff} theme_color:{tags: "good_pop hover", value: 0xe3f5d3ff} theme_color:{tags: "good_pop weak text", value: 0xe3f5d3ff} theme_color:{tags: "bad_pop background", value: 0x803425ff} theme_color:{tags: "bad_pop hover", value: 0xff825cff} theme_color:{tags: code_default, value: 0xa08563ff} theme_color:{tags: code_symbol, value: 0xcc5735ff} theme_color:{tags: code_type, value: 0xd8a51cff} theme_color:{tags: code_local, value: 0xd6b995ff} theme_color:{tags: code_register, value: 0xc04047ff} theme_color:{tags: code_keyword, value: 0xac7b0aff} theme_color:{tags: code_delimiter_or_operator, value: 0x907553ff} theme_color:{tags: code_numeric, value: 0x6b8e23ff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x4f681cff} theme_color:{tags: code_string, value: 0x6b8e23ff} theme_color:{tags: code_meta, value: 0xdab98fff} theme_color:{tags: code_comment, value: 0x686868ff} theme_color:{tags: line_info_0, value: 0x4f3022ff} theme_color:{tags: line_info_1, value: 0x4f3e15ff} theme_color:{tags: line_info_2, value: 0x434e2aff} theme_color:{tags: line_info_3, value: 0x36241fff} theme_color:{tags: thread_0, value: 0xffcb7fff} theme_color:{tags: thread_1, value: 0xb2ff65ff} theme_color:{tags: thread_unwound, value: 0xb2ccd8ff} theme_color:{tags: thread_error, value: 0xb23219ff} theme_color:{tags: breakpoint, value: 0xa72911ff} theme_color:{tags: "floating background", value: 0x18181980} theme_color:{tags: "floating background alt", value: 0x0000005f} theme_color:{tags: "floating background fresh", value: 0x31393d5f} theme_color:{tags: "floating border", value: 0xbfbfbf1f} theme_color:{tags: "floating scroll_bar background", value: 0x3b3b3b5f} theme_color:{tags: "floating scroll_bar border", value: 0x5f5f5f5f} theme_color:{tags: "menu_bar background", value: 0x1f1f27ff} theme_color:{tags: "menu_bar border", value: 0x3d3d47ff} theme_color:{tags: "scroll_bar background", value: 0x2b2b2bff} theme_color:{tags: "scroll_bar border", value: 0x3f3f3fff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0x1f1f27ff} theme_color:{tags: "tab border", value: 0x3d3d47ff} theme_color:{tags: "tab text", value: 0xca9301ff} theme_color:{tags: "tab text weak", value: 0x8c690eff} theme_color:{tags: "tab inactive background", value: 0x171718ff} theme_color:{tags: "tab inactive border", value: 0x1f1f27ff} theme_color:{tags: "tab auto background", value: 0x243b38ff} theme_color:{tags: "tab auto border", value: 0x478980ff} theme_color:{tags: "tab auto inactive background", value: 0x102623ff} theme_color:{tags: "tab auto inactive border", value: 0x1e5850ff} theme_color:{tags: "drop_site background", value: 0xffffff05} theme_color:{tags: "drop_site border", value: 0xffffff0f} } ``` } //- rjf: naysayer { Naysayer naysayer "Naysayer", ```theme: { theme_color:{tags: background, value: 0x042327ff} theme_color:{tags: "alt background", value: 0x11b1fff} theme_color:{tags: "pop background", value: 0x355b6eff} theme_color:{tags: "pop text", value: 0xbad7e6ff} theme_color:{tags: "fresh background", value: 0x31393dff} theme_color:{tags: "match background", value: 0x31393dff} theme_color:{tags: border, value: 0x334d50ff} theme_color:{tags: text, value: 0xdad3beff} theme_color:{tags: "weak text", value: 0xb0a688ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: "menu_bar good text", value: 0x2a8242ff} theme_color:{tags: "menu_bar neutral text", value: 0x5681ff} theme_color:{tags: "menu_bar bad text", value: 0xa21200ff} theme_color:{tags: "menu_bar weak text", value: 0x313131ff} theme_color:{tags: "menu_bar bad_pop text weak", value: 0xffffffff} theme_color:{tags: hover, value: 0xffffffff} theme_color:{tags: "focus overlay", value: 0x86e08e20} theme_color:{tags: "focus border", value: 0x86e08fff} theme_color:{tags: cursor, value: 0x86e08fff} theme_color:{tags: selection, value: 0x99ccff0f} theme_color:{tags: "inactive background", value: 0x0000002f} theme_color:{tags: drop_shadow, value: 0x0000007f} theme_color:{tags: "good_pop background", value: 0x2c5b36ff} theme_color:{tags: "good_pop border", value: 0x568761ff} theme_color:{tags: "good_pop hover", value: 0xe3f5d3ff} theme_color:{tags: "good_pop weak text", value: 0xe3f5d3ff} theme_color:{tags: "bad_pop background", value: 0x803425ff} theme_color:{tags: "bad_pop hover", value: 0xff825cff} theme_color:{tags: code_default, value: 0xbdb395ff} theme_color:{tags: code_symbol, value: 0xcbe0f5ff} theme_color:{tags: code_type, value: 0xcbe0f5ff} theme_color:{tags: code_local, value: 0xd9cfb3ff} theme_color:{tags: code_register, value: 0xb7afd5ff} theme_color:{tags: code_keyword, value: 0x9de3c0ff} theme_color:{tags: code_delimiter_or_operator, value: 0x767676ff} theme_color:{tags: code_numeric, value: 0x2ca198ff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x217770ff} theme_color:{tags: code_string, value: 0x2ca198ff} theme_color:{tags: code_meta, value: 0xB0FFB0ff} theme_color:{tags: code_comment, value: 0x31b72cff} theme_color:{tags: line_info_0, value: 0x4f3022ff} theme_color:{tags: line_info_1, value: 0x4f3e15ff} theme_color:{tags: line_info_2, value: 0x434e2aff} theme_color:{tags: line_info_3, value: 0x36241fff} theme_color:{tags: thread_0, value: 0xffcb7fff} theme_color:{tags: thread_1, value: 0xb2ff65ff} theme_color:{tags: thread_unwound, value: 0xb2ccd8ff} theme_color:{tags: thread_error, value: 0xb23219ff} theme_color:{tags: breakpoint, value: 0xa72911ff} theme_color:{tags: "floating background", value: 0x3232792} theme_color:{tags: "floating background alt", value: 0x0000005f} theme_color:{tags: "floating background fresh", value: 0x31393d5f} theme_color:{tags: "floating scroll_bar background", value: 0xe363bff} theme_color:{tags: "menu_bar background", value: 0xb59e7aff} theme_color:{tags: "menu_bar text", value: 0xff} theme_color:{tags: "menu_bar border", value: 0x947d5aff} theme_color:{tags: "scroll_bar background", value: 0xe363bff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0x13533aff} theme_color:{tags: "tab border", value: 0x6c9182ff} theme_color:{tags: "tab inactive background", value: 0x0} theme_color:{tags: "tab inactive border", value: 0x947d5a6c} theme_color:{tags: "tab auto background", value: 0x5b3939ff} theme_color:{tags: "tab auto border", value: 0x875c5cff} theme_color:{tags: "tab auto inactive background", value: 0x251b1bff} theme_color:{tags: "tab auto inactive border", value: 0x563d3dff} theme_color:{tags: "drop_site background", value: 0xffffff05} theme_color:{tags: "drop_site border", value: 0xffffff0f} } ``` } //- rjf: 4coder theme { FourCoder four_coder "4coder", ```theme: { theme_color:{tags: background,value: 0xc0c0cff} theme_color:{tags: "alt background", value: 0x131313ff} theme_color:{tags: "pop background", value: 0x4c00ff} theme_color:{tags: "fresh background", value: 0x4c00ff} theme_color:{tags: "match background", value: 0x4c00ff} theme_color:{tags: border, value: 0x272727ff} theme_color:{tags: text, value: 0x90b080ff} theme_color:{tags: "weak text", value: 0x6b845fff} theme_color:{tags: "menu_bar background", value: 0x888888ff} theme_color:{tags: "menu_bar text", value: 0x20202ff} theme_color:{tags: "menu_bar text weak", value: 0x525252ff} theme_color:{tags: "good text", value: 0x32a852ff} theme_color:{tags: "neutral text", value: 0x3a90bbff} theme_color:{tags: "bad text", value: 0xcf5242ff} theme_color:{tags: hover, value: 0xee00ff} theme_color:{tags: "focus overlay", value: 0xee0012} theme_color:{tags: "focus border", value: 0x00ee00ff} theme_color:{tags: cursor, value: 0x00ee00ff} theme_color:{tags: selection, value: 0x99ccff0f} theme_color:{tags: "inactive background", value: 0x0000002f} theme_color:{tags: drop_shadow, value: 0x0000007f} theme_color:{tags: "good_pop background", value: 0x4900ff} theme_color:{tags: "good_pop border", value: 0x4900ff} theme_color:{tags: "bad_pop background", value: 0x430b00ff} theme_color:{tags: code_default, value: 0x90b080ff} theme_color:{tags: code_symbol, value: 0xbfd9b2ff} theme_color:{tags: code_type, value: 0xbfd9b2ff} theme_color:{tags: code_local, value: 0xbfd9b2ff} theme_color:{tags: code_register, value: 0xb84cffff} theme_color:{tags: code_keyword, value: 0xd08f1fff} theme_color:{tags: code_delimiter_or_operator, value: 0x90b080ff} theme_color:{tags: code_numeric, value: 0x50ff2fff} theme_color:{tags: code_numeric_alt_digit_group, value: 0x30af18ff} theme_color:{tags: code_string, value: 0x50ff2fff} theme_color:{tags: code_meta, value: 0x90b080ff} theme_color:{tags: code_comment, value: 0x1f90f0ff} theme_color:{tags: line_info_0, value: 0xa253dff} theme_color:{tags: line_info_1, value: 0x9103dff} theme_color:{tags: line_info_2, value: 0x1e083dff} theme_color:{tags: line_info_3, value: 0x1e083dff} theme_color:{tags: thread_0, value: 0xd08f1fff} theme_color:{tags: thread_1, value: 0x1ea5d0ff} theme_color:{tags: thread_unwound, value: 0xb2ccd8ff} theme_color:{tags: thread_error, value: 0xb23219ff} theme_color:{tags: breakpoint, value: 0xa72911ff} theme_color:{tags: "scroll_bar background", value: 0x1d1d1dff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0x15490cff} theme_color:{tags: "tab border", value: 0x15490cff} theme_color:{tags: "tab text", value: 0x90b080ff} theme_color:{tags: "tab text weak", value: 0x90b080ff} theme_color:{tags: "tab inactive background", value: 0x21321eff} theme_color:{tags: "tab inactive border", value: 0x21321eff} theme_color:{tags: "tab auto background", value: 0x674f3eff} theme_color:{tags: "tab auto border", value: 0x674f3eff} theme_color:{tags: "tab auto inactive background", value: 0x47382eff} theme_color:{tags: "tab auto inactive border", value: 0x47382eff} theme_color:{tags: "drop_site background", value: 0xffffff05} theme_color:{tags: "drop_site border", value: 0xffffff0f} } ``` } //- rjf: grove theme { Grove grove "Grove", ```theme: { theme_color:{ tags: background , value: 0x1b1f22ff } theme_color:{ tags: "alt background" , value: 0x232929ff } theme_color:{ tags: "pop background" , value: 0x2f4838ff } theme_color:{ tags: "fresh background" , value: 0x31393dff } theme_color:{ tags: "match background" , value: 0x31393dff } theme_color:{ tags: border , value: 0x485347ff } theme_color:{ tags: text , value: 0xffffffff } theme_color:{ tags: "weak text" , value: 0xa2a2a2ff } theme_color:{ tags: "good text" , value: 0x32a852ff } theme_color:{ tags: "neutral text" , value: 0x3a90bbff } theme_color:{ tags: "bad text" , value: 0xcf5242ff } theme_color:{ tags: hover , value: 0xffffffff } theme_color:{ tags: "focus overlay" , value: 0xfda20012 } theme_color:{ tags: "focus border" , value: 0xfda200ff } theme_color:{ tags: cursor , value: 0x8aff00ff } theme_color:{ tags: selection , value: 0x99ccff0f } theme_color:{ tags: "inactive background" , value: 0x0 } theme_color:{ tags: drop_shadow , value: 0x0000007f } theme_color:{ tags: "good_pop background" , value: 0x2c5b36ff } theme_color:{ tags: "good_pop border" , value: 0x568761ff } theme_color:{ tags: "good_pop hover" , value: 0xe3f5d3ff } theme_color:{ tags: "good_pop weak text" , value: 0xe3f5d3ff } theme_color:{ tags: "bad_pop background" , value: 0x803425ff } theme_color:{ tags: "bad_pop hover" , value: 0xff825cff } theme_color:{ tags: code_default , value: 0xad8b69ff } theme_color:{ tags: code_symbol , value: 0x87ad6aff } theme_color:{ tags: code_type , value: 0xb67474ff } theme_color:{ tags: code_local , value: 0xe9bf95ff } theme_color:{ tags: code_register , value: 0xa688b2ff } theme_color:{ tags: code_keyword , value: 0xe49e17ff } theme_color:{ tags: code_delimiter_or_operator , value: 0x795e43ff } theme_color:{ tags: code_numeric , value: 0x98b19eff } theme_color:{ tags: code_numeric_alt_digit_group , value: 0x688b71ff } theme_color:{ tags: code_string , value: 0x98b19eff } theme_color:{ tags: code_meta , value: 0xad5979ff } theme_color:{ tags: code_comment , value: 0x52675dff } theme_color:{ tags: line_info_0 , value: 0x4f3022ff } theme_color:{ tags: line_info_1 , value: 0x4f3e15ff } theme_color:{ tags: line_info_2 , value: 0x434e2aff } theme_color:{ tags: line_info_3 , value: 0x36241fff } theme_color:{ tags: line_info_4 , value: 0x4f3022ff } theme_color:{ tags: line_info_5 , value: 0x4f3e15ff } theme_color:{ tags: line_info_6 , value: 0x434e2aff } theme_color:{ tags: line_info_7 , value: 0x36241fff } theme_color:{ tags: thread_0 , value: 0xffc258ff } theme_color:{ tags: thread_1 , value: 0x82d331ff } theme_color:{ tags: thread_2 , value: 0xff99e5ff } theme_color:{ tags: thread_3 , value: 0x6598ffff } theme_color:{ tags: thread_4 , value: 0x65ffcbff } theme_color:{ tags: thread_5 , value: 0xff9819ff } theme_color:{ tags: thread_6 , value: 0x9932ffff } theme_color:{ tags: thread_7 , value: 0x65ff4cff } theme_color:{ tags: thread_unwound , value: 0xb2ccd8ff } theme_color:{ tags: thread_error , value: 0xb23219ff } theme_color:{ tags: breakpoint , value: 0xa72911ff } theme_color:{ tags: "floating background" , value: 0x1b1f2276 } theme_color:{ tags: "floating background alt" , value: 0x0000005f } theme_color:{ tags: "floating background fresh" , value: 0x31393d5f } theme_color:{ tags: "floating border" , value: 0xbfbfbf1f } theme_color:{ tags: "floating scroll_bar background" , value: 0x3b3b3b5f } theme_color:{ tags: "floating scroll_bar border" , value: 0x5f5f5f5f } theme_color:{ tags: "menu_bar background" , value: 0x243d32ff } theme_color:{ tags: "menu_bar border" , value: 0x597b63ff } theme_color:{ tags: "scroll_bar background" , value: 0x232929ff } theme_color:{ tags: "scroll_bar border" , value: 0x3c4a3fff } theme_color:{ tags: "implicit background" , value: 0x00000000 } theme_color:{ tags: "implicit border" , value: 0x00000000 } theme_color:{ tags: "hollow background" , value: 0x00000000 } theme_color:{ tags: "hollow border" , value: 0xffffff1f } theme_color:{ tags: "tab background" , value: 0x243d32ff } theme_color:{ tags: "tab border" , value: 0x597b63ff } theme_color:{ tags: "tab inactive background" , value: 0x30383eff } theme_color:{ tags: "tab inactive border" , value: 0x6b7680ff } theme_color:{ tags: "tab auto background" , value: 0x30636dff } theme_color:{ tags: "tab auto border" , value: 0x768f94ff } theme_color:{ tags: "tab auto inactive background" , value: 0x2f2633ff } theme_color:{ tags: "tab auto inactive border" , value: 0x685073ff } theme_color:{ tags: "drop_site background" , value: 0xffffff05 } theme_color:{ tags: "drop_site border" , value: 0xffffff0f } } ``` } //- rjf: todo { FarManager far_manager "Far Manager", ```theme: { theme_color:{tags: background, value: 0x000080ff} theme_color:{tags: "pop background", value: 0x8080ff} theme_color:{tags: "fresh background", value: 0x31393dff} theme_color:{tags: "match background", value: 0x31393dff} theme_color:{tags: border, value: 0x8080ff} theme_color:{tags: text, value: 0xffffffff} theme_color:{tags: "weak text", value: 0xffffffff} theme_color:{tags: "good text", value: 0x00ff00ff} theme_color:{tags: "neutral text", value: 0x00ffffff} theme_color:{tags: "bad text", value: 0xff0000ff} theme_color:{tags: hover, value: 0xffffffff} theme_color:{tags: "focus overlay", value: 0xffff0012} theme_color:{tags: "focus border", value: 0xffff00ff} theme_color:{tags: cursor, value: 0xffff00ff} theme_color:{tags: selection, value: 0xffff0018} theme_color:{tags: "inactive background", value: 0x0000002f} theme_color:{tags: drop_shadow, value: 0x0000007f} theme_color:{tags: "good_pop background", value: 0x6c17ff} theme_color:{tags: "good_pop border", value: 0x6c17ff} theme_color:{tags: "bad_pop background", value: 0xff0000ff} theme_color:{tags: code_default, value: 0xffffffff} theme_color:{tags: code_symbol, value: 0xffffff} theme_color:{tags: code_type, value: 0x00ff00ff} theme_color:{tags: code_local, value: 0x00ffffff} theme_color:{tags: code_register, value: 0xff00ffff} theme_color:{tags: code_keyword, value: 0xffffffff} theme_color:{tags: code_delimiter_or_operator, value: 0xffffffff} theme_color:{tags: code_numeric, value: 0xffff00ff} theme_color:{tags: code_numeric_alt_digit_group, value: 0xffff00ff} theme_color:{tags: code_string, value: 0xffff00ff} theme_color:{tags: code_meta, value: 0xff0000ff} theme_color:{tags: code_comment, value: 0x008080ff} theme_color:{tags: line_info_0, value: 0x8080ff} theme_color:{tags: line_info_1, value: 0x800080ff} theme_color:{tags: line_info_2, value: 0x800000ff} theme_color:{tags: line_info_3, value: 0x08000ff} theme_color:{tags: thread_0, value: 0xffff00ff} theme_color:{tags: thread_1, value: 0x00ff00ff} theme_color:{tags: thread_unwound, value: 0x00ffffff} theme_color:{tags: thread_error, value: 0xff0000ff} theme_color:{tags: breakpoint, value: 0xff0000ff} theme_color:{tags: "menu_bar background", value: 0x008080ff} theme_color:{tags: "menu_bar border", value: 0x8080ff} theme_color:{tags: "scroll_bar background", value: 0x008080ff} theme_color:{tags: "implicit background", value: 0x00000000} theme_color:{tags: "implicit border", value: 0x00000000} theme_color:{tags: "hollow background", value: 0x00000000} theme_color:{tags: "hollow border", value: 0xffffff1f} theme_color:{tags: "tab background", value: 0x8080ff} theme_color:{tags: "tab border", value: 0x8080ff} theme_color:{tags: "tab inactive background", value:0} theme_color:{tags: "tab auto background", value: 0x800000ff} theme_color:{tags: "tab auto border", value: 0x8080ff} theme_color:{tags: "tab auto inactive background", value: 0x300000ff} theme_color:{tags: "tab auto inactive border", value: 0x8080ff} theme_color:{tags: "drop_site background", value: 0x80ff} theme_color:{tags: "drop_site border", value: 0xffffff} } ``` } } @table(name lower_name) RD_CodeColorTable: { {CodeDefault "code_default"} {CodeSymbol "code_symbol"} {CodeType "code_type"} {CodeLocal "code_local"} {CodeRegister "code_register"} {CodeKeyword "code_keyword"} {CodeDelimiterOperator "code_delimiter_or_operator"} {CodeNumeric "code_numeric"} {CodeNumericAltDigitGroup "code_numeric_alt_digit_group"} {CodeString "code_string"} {CodeMeta "code_meta"} {CodeComment "code_comment"} {CodeLineNumbers "code_line_numbers"} {CodeLineNumbersSelected "code_line_numbers_selected"} } @enum RD_CodeColorSlot: { @expand(RD_CodeColorTable a) `$(a.name)`, COUNT } @data(String8) rd_code_color_slot_name_table: { @expand(RD_CodeColorTable a) `str8_lit_comp("$(a.lower_name)")` } @enum RD_ThemePreset: { @expand(RD_ThemePresetTable a) `$(a.name)`, COUNT, } @data(String8) rd_theme_preset_display_string_table: { @expand(RD_ThemePresetTable a) `str8_lit_comp("$(a.display_string)")`, } @data(String8) rd_theme_preset_code_string_table: { @expand(RD_ThemePresetTable a) `str8_lit_comp("$(a.name_lower)")`, } @data(String8) rd_theme_preset_cfg_string_table: { @expand(RD_ThemePresetTable a) `str8_lit_comp("$(a.cfg)")`, } //////////////////////////////// //~ rjf: Help/Docs/README @markdown raddbg_readme: { @title "The RAD Debugger (ALPHA)"; @p "The RAD Debugger is a native, user-mode, multi-process, graphical debugger. It currently only supports local-machine Windows x64 debugging with PDBs, but we're actively working on support and ports for other toolchains and platforms."; @subtitle "Getting Started"; @p "**Launching the debugger with your program information:** To launch the RAD Debugger with your executable and command line arguments, run `raddbg` from the command line like so:"; @p "```raddbg my_program.exe --foo --bar --baz```"; @p "For more information, see the **Command-Line Usage** section."; @p "**Basic commands and keybindings:** Default keyboard shortcuts for common debugger controls include:"; @unordered_list { @p "**Ctrl + O**: Open Source Code File"; @p "**F10**: Step Over"; @p "**F11**: Step Into"; @p "**Shift + F11**: Step Out"; @p "**F5**: Run"; @p "**Ctrl + Shift + X**, or **Pause**: Halt All Processes"; @p "**Shift + F5**: Kill All Processes"; @p "**Shift + F6**: Attach To Process"; @p "**Ctrl + F**: Search For Text (Forwards)"; @p "**F9**: Toggle Breakpoint At Cursor"; @p "**Ctrl + Comma**: Focus Next Panel"; @p "**Ctrl + Shift + Comma**: Focus Previous Panel"; @p "**Ctrl + Alt + Arrow Key**: Focus Panel In Direction"; @p "**Ctrl + Tab**: Focus Next Tab"; @p "**Ctrl + Shift + Tab**: Focus Previous Tab"; @p "**Ctrl + W**: Close Tab"; @p "**F1**: Open Palette (lists commands, keybindings, settings, threads, processes, modules, types, and many other things)"; } @p "For more information, see the **Commands** section."; @p "**Configuration files (users and projects):** The RAD Debugger stores configuration in two files. One is the 'user file', the other is the 'project file'. Both files are the same format and can store the same kinds of data, but the user file is preferred by the debugger for more likely user-related data (windows, keybindings, theme), and the project file is preferred by the debugger for more likely project-related data (executable debugging targets, breakpoints, recent source files). Project files are more likely to be what you'd check into source control, whereas a user file is more likely to have your personal debugger settings (which will apply identically regardless of which project file is opened)."; @p "The debugger autosaves user and project files. You do not need to manually save them. To switch which path you are using for either, you can use the `Open User` (Ctrl + Alt + Shift + O, by default), or `Open Project` (Ctrl + Alt + O, by default) commands respectively. If a file does not exist at the path you enter for either, then a new one will be created, and the debugger will begin autosaving to it. If the initial paths to these files are not specified on the command line (via `--user` or `--project`), then the debugger uses default paths for them. The user file path, by default, will be `%appdata%/raddbg/default.raddbg_user`. The project file path will be whatever project path was last loaded for the user, or if no such path exists, `%appdata%/raddbg/default.raddbg_project`. If you suspect that your configuration files are corrupted or causing the debugger to behave poorly, it might help to delete your `%appdata%/raddbg` folder (although it'd also help if you [sent it to us in a bug report](https://github.com/EpicGamesExt/raddebugger/issues), so that we can investigate why they were corrupted to begin with!)."; @p "For more information, see the `**User & Project Files** section."; @p "**Watch tabs and visualizers:** 'Watch' tabs in the RAD Debugger allow entering expressions, which can reference variables in your program, and visualize what their value is when your program is stopped at a particular time. These expressions roughly follow C expression syntax, but there are a number of extensions which can be used to visualize expressions in a more useful way. Here are some examples:"; @unordered_list { @p "`array(pointer, 64)`: Visualizes `pointer` as pointing to a 256-element array."; @p "`pointer, 64`: Visualizes `pointer` as pointing to a 256-element array."; @p "`pointer, count`: Visualizes `pointer` as pointing to a `count`-element array."; @p "`slice(some_slice_struct)`: Interprets a structure type as containing a base pointer and a count (either through an integer, or an 'end pointer'), and visualizes the base pointer, pointing to that many elements."; @p "`rows(some_struct, a, b, c)`: Displays the value of `some_struct`, but only showing members `a`, `b`, and `c`."; @p "`omit(some_struct, a, b, c)`: Displays the value of `some_struct`, but only showing members other than `a`, `b`, and `c`."; @p "`hex(my_int)`: Visualizes the value of `my_int` in base-16 (hexadecimal) form."; @p "`dec(my_int)`: Visualizes the value of `my_int` in base-10 (decimal) form."; @p "`bin(my_int)`: Visualizes the value of `my_int` in base-2 (binary) form."; @p "`oct(my_int)`: Visualizes the value of `my_int` in base-8 (octal) form."; @p "`my_int, x`: Visualizes the value of `my_int` in base-16 (hexadecimal) form."; @p "`my_int, d`: Visualizes the value of `my_int` in base-10 (decimal) form."; @p "`my_int, b`: Visualizes the value of `my_int` in base-2 (binary) form."; @p "`my_int, o`: Visualizes the value of `my_int` in base-8 (octal) form."; @p "`digits(bin(my_int), 32)`: Visualizes the value of `my_int` in base-2 (binary) form, showing at minimum 32 bits."; @p "`my_int.bin().digits(32)`: Visualizes the value of `my_int` in base-2 (binary) form, showing at minimum 32 bits."; @p "`bitmap(base_pointer, width, height, fmt=rgba8)`: Visualizes the data starting at `base_pointer` as a bitmap, with width `width` and height `height`, with format `rgba8`."; } @p "For more information, see the **Views** section."; @subtitle "Command-Line Usage"; @p "When run normally, either by launching through a file explorer or running from a command line without arguments, `raddbg` will open a new instance of the debugger, and await further operations. But it also supports a number of command line options for a number of other purposes. These options are specified with a `-` or `--` prefix, followed by the name of the option, and if the option requires an argument value, followed by a `:` or `=`, followed by the argument value. A list of the possible options follows:"; @unordered_list { @p "`--help` Displays a help menu which documents the possible command line options."; @p "`--user:` Use to specify the location of a user file which should be used. User files are used by default to store user-related settings, including window and panel setups, path mapping, and visual settings. If this file does not exist, it will be created as necessary. This file will be autosaved as user-related changes are made. For more information on user files, see the **User & Project Files** section."; @p "`--project:` Use to specify the location of a project file which should be used. Project files are used by default to store project-related settings. If this file does not exist, it will be created as necessary. This file will be autosaved as project-related changes are made. For more information on project files, read the 'User & Project Files' section."; @p "`--auto_step` This will step into all active targets after the debugger initially starts."; @p "`--auto_run` This will run all active targets after the debugger initially starts."; @p "`--quit_after_success` (or `-q`) This will close the debugger automatically after all processes exit, if they all exited successfully (with code 0), and ran with no interruptions."; @p "`--ipc` This will launch the debugger in the non-graphical IPC mode, which is used to communicate with another running instance of the debugger. The debugger instance will launch, send the specified command, then immediately terminate. This may be used by editors or other programs to control the debugger. For more information on the set of available commands, see the **Commands** section. For more information on driving another debugger instance with this argument, see the **Driving Another Debugger Instance** section."; } @p "On the command line, non-options (meaning any command line arguments *not* prefixed with a `-` or `--`) can also be specified. With normal usage, they are interpreted as the command line for a target (see the **Targets** section). When driving another debugger instance (using the `--ipc` argument), this additional command line text is used to encode a debugger command."; @p "The debugger will stop parsing `-` and `--` prefixes as arguments after seeing a standalone `--`, *or* after seeing the first non-option argument, when reading the command line left-to-right. Some examples of command line usage and their interpretations are below:"; @unordered_list { @p "`raddbg --foo --bar --a:b --c=d test.exe`: All options are used to configure `raddbg`. `test.exe` is interpreted as a target executable. `b` is interpreted as the parameter for the `a` option. `d` is interpreted as the parameter for the `c` option."; @p "`raddbg test.exe --foo --bar`: `test.exe`is interpreted as a target executable. `--foo --bar` is interpreted as arguments for `test.exe`, and thus are *not* used to configure `raddbg`."; @p "`raddbg -- test.exe`: `test.exe` is interpreted as a target executable."; @p "`raddbg --ipc find_code_location \"C:/foo/bar/baz.c:123:1\"`: `--ipc` configures `raddbg` to drive another instance of `raddbg`. The remainder of the text is interpreted as a command."; @p "`raddbg \"C:/path with spaces/test.exe\" --foo --bar`: A target is formed from the `test.exe` path, and `--foo --bar` are interpreted as arguments to the `test.exe` target."; } @subtitle "Windows, Panels, & Tabs"; @p "Each opened debugger window is subdivided into panels. Panels subdivide regions of their window without overlapping. Each panel can contain multiple tabs, and can have one tab selected at any time. Tabs can be dragged and dropped between panels. Each tab is used to view one of the many supported debugger interfaces, including source code, disassembly, memory, or watch tables. When a tab is selected, that interface will fill the tab's containing panel's region of the containing window."; @p "There are no 'special' windows, panels, or tabs; the debugger is written such that the number of windows, each window's panel organization, and the placement and arrangement of tabs can all be organized in a large variety of ways."; @p "A list of debugger interfaces, which can occupy tabs, are below:"; @unordered_list { @expand(RD_WatchTabFastPathTable a) @p "**$(a.display_name)**: $(a.description)"; } @p "You can open one of these tabs in any panel by clicking the `+` icon next to that panel's tabs, or by executing the `Open Tab` command (bound to Ctrl + T) by default."; @subtitle "Commands"; @p "The debugger, including implicitly with its UI, is operated almost entirely through 'commands'. Commands may be manually executed in the debugger UI within the palette (which you can open with F1 by default), or within the commands list which is opened when you execute the 'Run Command' command. Operations in the debugger UI are implemented with commands, so if it's ever unclear how to accomplish some operation through the UI, a useful fallback is searching for and running the command through the palette."; @p "Commands are also how a debugger instance launched with `--ipc` may communicate with a primary debugger instance."; @p "A list of commands, how they're referred to textually (for the purposes of `--ipc` debugger instances), and their descriptions, are below:"; @unordered_list { @expand(D_CmdTable a) @p "$(a.ipc_docs_vis == 1 -> '`'..a.display_name..'` '..'(`'..a.string..'`) '..a.desc)"; @expand(RD_CmdTable a) @p "$(a.ipc_docs_vis == 1 -> '`'..a.display_name..'` '..'(`'..a.string..'`) '..a.desc)"; } @subtitle "Targets"; @p "A *target* is one executable and configuration for launching that executable, including command line arguments and working directory (the directory from which the executable is launched). Each target may also have a custom label (prioritized over the executable name when visualizing the target, and also allows evaluation of the target in a Watch tab), and the name of a custom entry point function (when the default entry points - `main`, `WinMain`, etc. - are not desired when stepping into the program upon launch). The debugger can have several targets at once. Each target can also be enabled or disabled. Some operations work on all enabled targets - for instance, the `Run` or `Kill All` commands (standardly bound as F5 or Shift + F5). Enabling and disabling targets allows one to filter which targets are currently being worked with."; @p "To add a target, you can run the `Add Target` command. A target is also created automatically from command line arguments - the rules for how this happens can be found in the `Command-Line Usage` section."; @p "Targets created through command line usage are temporary, meaning they are not persistently saved across runs of the debugger. To change this, find the target in the `Targets` tab, and click the `Save To Project` button on that target's row. After doing so, the target will be restored across runs, and will no longer need to be specified on the command-line."; @subtitle "Views"; @p "*Views* are used to transform the way that evaluations in the debugger are visualized. An evaluation is produced by taking an expression string - for instance, the name of a variable - and using debug info and information from an attached process' live runtime (memory, registers, and so on) to interpret it."; @p "Evaluations may be visualized in a variety of ways. A 64-bit unsigned integer may be visualized as a textual representation of the value with a radix of 10. A 32-bit floating-point value may be visualized as a textual representation of the value. An array of 32-bit floating-point values can be visualized as a list of textual representations of those values."; @p "But all of these cases may be visualized in a number of other ways, as well. A 64-bit unsigned integer may be more usefully represented with a radix of 16, 8, or 2. An array of 32-bit floating-point values may encode the R, G, B, and A components of a color, or vertex positions for 3D geometry, or samples for a waveform. An array of bytes may encode raw pixel data for an image, or image data in a compressed format. A struct may have several members which are not useful to look at all the time. A struct may form the head of a linked list, and a flat linked list representation may be more preferable than the traditional watch view representation, which adds an additional layer of hierarchical nesting with the expansion of each 'next' pointer in a linked list. When designing the debugger, we felt that the traditional memory view and watch view representations of data in a debugged-process were not sufficient. Views were added to the traditional watch table structure to allow per-expression specification of extra visualization parameters."; @p "Views look just like function calls. They start with the name of the view, a `(`, then a list of expressions which form the arguments for the view (optionally delimited by `,`s), followed by a `)`. The meaning of these arguments can sometimes be inferred through their order; for example, in the case of `bitmap(ptr, 512, 256)`, the `bitmap` view uses the `ptr` as the primary expression to interpret as bitmap data, then assumes the widely-used pattern of width, then height, to interpret the following arguments as the dimensions of the bitmap. In other cases, arguments must be specifically named. For instance, the `fmt` argument in `bitmap(ptr, 512, 256, fmt=bgra8)` is required to override the `bitmap` view's default assumption of RGBA8 bitmap data."; @p "A list of currently-supported views are below:"; @unordered_list { // TODO(rjf): @lenses generate via metaprogram @p "`raw(expr)`: Ignores all views used in `expr`, including those automatically applied by type views."; @p "`bin(expr)`: Visualizes all numeric values evaluated in `expr` as base-2 (binary)."; @p "`oct(expr)`: Visualizes all numeric values evaluated in `expr` as base-8 (octal)."; @p "`dec(expr)`: Visualizes all numeric values evaluated in `expr` as base-10 (decimal)."; @p "`hex(expr)`: Visualizes all numeric values evaluated in `expr` as base-16 (hexadecimal)."; @p "`digits(expr, num)`: Visualizes at least `num` digits in all numeric values evaluated in `expr`."; @p "`no_string(expr)`: Disables textual string visualization with pointer evaluations in `expr`."; @p "`no_char(expr)`: Disables character visualization with character or integer evaluations in `expr`."; @p "`no_addr(expr)`: Disables explicit address visualization with pointer evaluations in `expr`."; @p "`sequence(expr)`: Interprets `expr` as an integer, encoding how many sub-expressions `expr` should expand to produce. This can be used in combination with the `table` view to easily generate tables, indexing amongst many arrays."; @p "`rows(expr, ...)`: Interpreting all post-`expr` arguments as member names, only expands to show those members of `expr`."; @p "`omit(expr, ...)`: Interpreting all post-`expr` arguments as member names, expands to show all members of `expr`, except those with matching names."; @p "`range1(expr, min, max)`: Expresses that `expr` is a bounded numeric value between `min` and `max`. Interpreted by the debugger to build slider UI for an evaluation."; @p "`array(expr, count)`: Expresses that `expr` points to `count` values, rather than 1, or the fixed size implied by a static array. When expanded, displays only that many values."; @p "`slice(expr)`: Expresses that `expr` evaluates to a structure type which bundles a base pointer and a count (encoding how many elements to which the base pointer points). This count can be expressed either as an integer, or as an 'end pointer'. When expanded, displays that many elements following that base pointer."; @p "`table(expr, ...)`: Expresses that `expr` should be expanded normally, but interprets all post-`expr` arguments as expressions which should be used to form cells for rows which are generated by this expression's expansions. This replaces the normal cells which are generated for an expansion in a Watch table."; @p "`text(expr, [lang = ...])`: Generates a text visualizer, interpreting `expr` as (being or pointing to) text."; @p "`disasm(expr, [size = ...]`: Generates a disassembly visualizer, interpreting `expr` as (being or pointing to) machine code."; @p "`memory(expr, [size = ...])`: Generates a memory visualizer, interpreting `expr` as (being or pointing to) raw bytes."; @p "`bitmap(expr, width, height, [fmt = ...])`: Generates a bitmap visualizer, interpreting `expr` as (being or pointing to) raw bitmap data, with `width` and `height` as dimensions."; @p "`color(expr)`: Generates a color picker, interpreting `expr` as a color value."; } @subtitle "Breakpoints"; @p "Breakpoints interrupt execution of attached processes. They may be placed on arbitrary addresses (e.g. by placing a breakpoint on an instruction within a disassembly view, or with an arbitrary expression, like the name of a function), or on lines of source code. In the latter case, the source code location is resolved to code addresses. If there is no code associated with a line of source code, then the resolution path chooses to use the next closest line of source code in the same file."; @p "Breakpoints may have stop conditions attached to them. When a breakpoint is hit by a thread, before it stops execution, the stop condition is evaluated, and if it evaluates to a nonzero value, only then is execution stopped."; @p "Each breakpoint has a hit count. Every time a breakpoint causes execution to stop, this counter is increased."; @p "Address breakpoints can also point to data, rather than code. This will cause execution to stop if some data is read from, written to, or executed. In this case, the debugger configures the hardware to use the available hardware data breakpoints feature. To enable this path, in the breakpoint's editor, express the number of bytes following the address that should be checked for writes/reads/executions (can be 1, 2, 4, or 8), and select whether or not you want to break on reads, writes, or executions."; @subtitle "User & Project Files"; @p "Applicable state controlling the debugger's appearance, behavior, targets, breakpoints, and other configurations is saved and reloaded across runs of the debugger through both *user files* and *project files*. These files are auto-saved. These files are written in a textual format which can be hand-edited as necessary, but they're also continuously re-read and re-written by the debugger. By default, the debugger uses `%appdata%/raddbg/default.raddbg_user` for its user file path, and `%appdata%/raddbg/default.raddbg_project` for its project file path. These paths can be overridden on the command line (see the 'Command-Line Usage' section)."; @p "The *user file* defaultly stores file path maps, windows (including their preferred monitor, placement, and size), each window's panel layout and tabs, keybindings, theme colors, and fonts."; @p "The *project file* defaultly stores targets, breakpoints, watch pins, and exception code filters."; @p "Because both can be hand-edited, however, if you want to store something normally stored in a user file in a project file, or vice versa, this can be done by hand transferring the textual data from one file to another. There is no path in the debugger's UI to support this transfer, currently, although this is planned."; @subtitle "Driving Another Debugger Instance"; @p "When the debugger is launched with the `--ipc` command-line argument, it does not launch another instance of the graphical debugger. Instead, it launches, sends a string encoding a command to a running instance of the graphical debugger, and then terminates. The set of commands which can be sent are identical to those which can be run from the debugger's UI itself, but these commands must be encoded textually (through the other command-line arguments). These commands are described in the 'Commands' section."; } ================================================ FILE: src/raddbg/raddbg_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xf0a215ff //////////////////////////////// //~ rjf: Generated Code #include "generated/raddbg.meta.c" //////////////////////////////// //~ rjf: Registers Type Functions internal void rd_regs_copy_contents(Arena *arena, RD_Regs *dst, RD_Regs *src) { MemoryCopyStruct(dst, src); dst->cfg_list = cfg_id_list_copy(arena, &src->cfg_list); dst->file_path = push_str8_copy(arena, src->file_path); dst->lines = d_line_list_copy(arena, &src->lines); dst->expr = push_str8_copy(arena, src->expr); dst->string = push_str8_copy(arena, src->string); dst->cmd_name = push_str8_copy(arena, src->cmd_name); if(dst->cfg_list.count == 0 && dst->cfg != 0) { cfg_id_list_push(arena, &dst->cfg_list, dst->cfg); } } internal RD_Regs * rd_regs_copy(Arena *arena, RD_Regs *src) { RD_Regs *dst = push_array(arena, RD_Regs, 1); rd_regs_copy_contents(arena, dst, src); return dst; } //////////////////////////////// //~ rjf: Commands Type Functions internal void rd_cmd_list_push_new(Arena *arena, RD_CmdList *cmds, String8 name, RD_Regs *regs) { RD_CmdNode *n = push_array(arena, RD_CmdNode, 1); n->cmd.name = push_str8_copy(arena, name); n->cmd.regs = rd_regs_copy(arena, regs); DLLPushBack(cmds->first, cmds->last, n); cmds->count += 1; } //////////////////////////////// //~ rjf: View UI Rule Functions internal RD_ViewUIRuleMap * rd_view_ui_rule_map_make(Arena *arena, U64 slots_count) { RD_ViewUIRuleMap *map = push_array(arena, RD_ViewUIRuleMap, 1); map->slots_count = slots_count; map->slots = push_array(arena, RD_ViewUIRuleSlot, map->slots_count); return map; } internal void rd_view_ui_rule_map_insert(Arena *arena, RD_ViewUIRuleMap *map, String8 string, RD_ViewUIFunctionType *ui) { U64 hash = d_hash_from_string(string); U64 slot_idx = hash%map->slots_count; RD_ViewUIRuleNode *n = push_array(arena, RD_ViewUIRuleNode, 1); n->v.name = push_str8_copy(arena, string); n->v.ui = ui; SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n); } internal RD_ViewUIRule * rd_view_ui_rule_from_string(String8 string) { RD_ViewUIRule *rule = &rd_nil_view_ui_rule; { RD_ViewUIRuleMap *map = rd_state->view_ui_rule_map; U64 hash = d_hash_from_string(string); U64 slot_idx = hash%map->slots_count; for(RD_ViewUIRuleNode *n = map->slots[slot_idx].first; n != 0; n = n->next) { if(str8_match(n->v.name, string, 0)) { rule = &n->v; break; } } } return rule; } //////////////////////////////// //~ rjf: Global Cross-Window UI Interaction State Functions internal B32 rd_drag_is_active(void) { return ((rd_state->drag_drop_state == RD_DragDropState_Dragging) || (rd_state->drag_drop_state == RD_DragDropState_Dropping)); } internal void rd_drag_begin(RD_RegSlot slot) { if(!rd_drag_is_active()) { arena_clear(rd_state->drag_drop_arena); rd_state->drag_drop_regs = rd_regs_copy(rd_state->drag_drop_arena, rd_regs()); rd_state->drag_drop_regs_slot = slot; rd_state->drag_drop_state = RD_DragDropState_Dragging; } } internal B32 rd_drag_drop(void) { B32 result = 0; if(rd_state->drag_drop_state == RD_DragDropState_Dropping) { result = 1; rd_state->drag_drop_state = RD_DragDropState_Null; } return result; } internal void rd_drag_kill(void) { rd_state->drag_drop_state = RD_DragDropState_Null; } internal void rd_set_hover_regs(RD_RegSlot slot) { rd_state->next_hover_regs = rd_regs_copy(rd_frame_arena(), rd_regs()); rd_state->next_hover_regs_slot = slot; } internal RD_Regs * rd_get_hover_regs(void) { return rd_state->hover_regs; } //////////////////////////////// //~ rjf: Config Functions internal B32 rd_cfg_is_project_filtered(CFG_Node *cfg) { CFG_Node *project = cfg_node_child_from_string(cfg, str8_lit("project")); B32 result = (project != &cfg_nil_node && !path_match_normalized(rd_state->project_path, project->first->string)); return result; } internal Vec4F32 rd_hsva_from_cfg(CFG_Node *cfg) { Vec4F32 hsva = {0}; CFG_Node *hsva_root = cfg_node_child_from_string(cfg, str8_lit("hsva")); CFG_Node *h = hsva_root->first; CFG_Node *s = h->next; CFG_Node *v = s->next; CFG_Node *a = v->next; hsva.x = (F32)f64_from_str8(h->string); hsva.y = (F32)f64_from_str8(s->string); hsva.z = (F32)f64_from_str8(v->string); hsva.w = (F32)f64_from_str8(a->string); return hsva; } internal Vec4F32 rd_color_from_cfg(CFG_Node *cfg) { Vec4F32 hsva = rd_hsva_from_cfg(cfg); Vec4F32 rgba = linear_from_srgba(rgba_from_hsva(hsva)); return rgba; } internal B32 rd_disabled_from_cfg(CFG_Node *cfg) { Temp scratch = scratch_begin(0, 0); MD_Node *child_schema = &md_nil_node; MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, cfg->string); for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next) { child_schema = md_child_from_string(n->v, str8_lit("enabled"), 0); } MD_Node *default_tag = md_tag_from_string(child_schema, str8_lit("default"), 0); String8 value_string = cfg_node_child_from_string(cfg, str8_lit("enabled"))->first->string; if(value_string.size == 0) { value_string = default_tag->first->string; } B32 is_enabled = !!e_value_from_string(value_string).u64; B32 is_disabled = !is_enabled; if(value_string.size == 0) { is_disabled = 0; } scratch_end(scratch); return is_disabled; } internal RD_Location rd_location_from_cfg(CFG_Node *cfg) { RD_Location dst_loc = {0}; { CFG_Node *src_loc = cfg_node_child_from_string(cfg, str8_lit("source_location")); CFG_Node *addr_loc = cfg_node_child_from_string(cfg, str8_lit("address_location")); if(src_loc != &cfg_nil_node) { String8TxtPtPair loc_description = str8_txt_pt_pair_from_string(src_loc->first->string); dst_loc.file_path = loc_description.string; dst_loc.pt = loc_description.pt; } else if(addr_loc != &cfg_nil_node) { dst_loc.expr = addr_loc->first->string; } } return dst_loc; } internal String8 rd_label_from_cfg(CFG_Node *cfg) { CFG_Node *label_root = cfg_node_child_from_string(cfg, str8_lit("label")); String8 result = label_root->first->string; return result; } internal String8 rd_expr_from_cfg(CFG_Node *cfg) { CFG_Node *expr_root = cfg_node_child_from_string(cfg, str8_lit("expression")); String8 result = expr_root->first->string; return result; } internal String8 rd_path_from_cfg(CFG_Node *cfg) { CFG_Node *root = cfg_node_child_from_string(cfg, str8_lit("path")); String8 result = root->first->string; return result; } internal D_Target rd_target_from_cfg(Arena *arena, CFG_Node *cfg) { D_Target target = {0}; target.exe = cfg_node_child_from_string(cfg, str8_lit("executable"))->first->string; target.args = cfg_node_child_from_string(cfg, str8_lit("arguments"))->first->string; target.working_directory = cfg_node_child_from_string(cfg, str8_lit("working_directory"))->first->string; target.custom_entry_point_name = cfg_node_child_from_string(cfg, str8_lit("entry_point"))->first->string; target.stdout_path = cfg_node_child_from_string(cfg, str8_lit("stdout_path"))->first->string; target.stderr_path = cfg_node_child_from_string(cfg, str8_lit("stderr_path"))->first->string; target.stdin_path = cfg_node_child_from_string(cfg, str8_lit("stdin_path"))->first->string; target.debug_subprocesses = !!e_value_from_string(cfg_node_child_from_string(cfg, str8_lit("debug_subprocesses"))->first->string).u64; for(CFG_Node *child = cfg->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("environment"), 0)) { str8_list_push(arena, &target.env, child->first->string); } } return target; } internal String8 rd_default_setting_from_names(String8 schema_name, String8 setting_name) { String8 result = {0}; { Temp scratch = scratch_begin(0, 0); MD_Node *setting_schema = &md_nil_node; MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, schema_name); for(MD_NodePtrNode *n = schemas.first; n != 0 && setting_schema == &md_nil_node; n = n->next) { setting_schema = md_child_from_string(n->v, setting_name, 0); } if(setting_schema != &md_nil_node) { MD_Node *default_tag = md_tag_from_string(setting_schema, str8_lit("default"), 0); if(default_tag != &md_nil_node) { result = default_tag->first->string; } } scratch_end(scratch); } return result; } internal String8 rd_setting_from_name(String8 name) { String8 result = {0}; if(name.size != 0) { Temp scratch = scratch_begin(0, 0); // rjf: find most-granular config scopes to begin looking for the setting typedef struct CfgSeedTask CfgSeedTask; struct CfgSeedTask { CfgSeedTask *next; CFG_Node *cfg; B32 allow_bucket_chains; }; CFG_Node *view_cfg = cfg_node_from_id(rd_regs()->view); if(view_cfg == &cfg_nil_node) { view_cfg = cfg_node_from_id(rd_regs()->tab); } CfgSeedTask panel_task = {0, &cfg_nil_node, 1}; if(panel_task.cfg == &cfg_nil_node) { panel_task.cfg = cfg_node_from_id(rd_regs()->panel); } if(panel_task.cfg == &cfg_nil_node) { panel_task.cfg = cfg_node_from_id(rd_regs()->window); } CfgSeedTask view_task = {&panel_task, view_cfg, 1}; CfgSeedTask *first_task = &view_task; CfgSeedTask *last_task = &panel_task; // rjf: for each task, look for the setting, follow parent chain upwards CFG_Node *setting = &cfg_nil_node; for(CfgSeedTask *t = first_task; t != 0; t = t->next) { for(CFG_Node *cfg = t->cfg; cfg != &cfg_nil_node; cfg = cfg->parent) { setting = cfg_node_child_from_string(cfg, name); if(setting != &cfg_nil_node) { goto break_all; } if(cfg->parent == cfg_node_root() && t->allow_bucket_chains) { String8 next_bucket = {0}; B32 allow_bucket_chains = 0; if(str8_match(cfg->string, str8_lit("user"), 0)) { next_bucket = str8_lit("project"); } else if(str8_match(cfg->string, str8_lit("project"), 0)) { next_bucket = str8_lit("user"); } else { allow_bucket_chains = 1; next_bucket = str8_lit("user"); } if(next_bucket.size != 0) { CfgSeedTask *task = push_array(scratch.arena, CfgSeedTask, 1); SLLQueuePush(first_task, last_task, task); task->cfg = cfg_node_child_from_string(cfg_node_root(), next_bucket); task->allow_bucket_chains = allow_bucket_chains; } } } } break_all:; // rjf: return resultant child string stored under this key result = setting->first->string; // rjf: no result -> look for default in schemas if(result.size == 0) { for(CfgSeedTask *t = first_task; t != 0; t = t->next) { for(CFG_Node *cfg = t->cfg; cfg != &cfg_nil_node; cfg = cfg->parent) { result = rd_default_setting_from_names(cfg->string, name); if(result.size != 0) { goto break_all2; } } } break_all2:; } scratch_end(scratch); } return result; } internal B32 rd_setting_b32_from_name(String8 name) { B32 result = 0; String8 value = rd_setting_from_name(name); if(value.size != 0) { Temp scratch = scratch_begin(0, 0); String8 expr = push_str8f(scratch.arena, "raw((bool)(%S))", value); E_Eval eval = e_eval_from_string(expr); result = !!e_value_eval_from_eval(eval).value.u64; scratch_end(scratch); } return result; } internal U64 rd_setting_u64_from_name(String8 name) { U64 result = 0; String8 value = rd_setting_from_name(name); if(value.size != 0) { Temp scratch = scratch_begin(0, 0); String8 expr = push_str8f(scratch.arena, "raw((uint64)(%S))", value); E_Eval eval = e_eval_from_string(expr); result = e_value_eval_from_eval(eval).value.u64; scratch_end(scratch); } return result; } internal F32 rd_setting_f32_from_name(String8 name) { F32 result = 0.f; String8 value = rd_setting_from_name(name); if(value.size != 0) { Temp scratch = scratch_begin(0, 0); String8 expr = push_str8f(scratch.arena, "raw((float32)(%S))", value); E_Eval eval = e_eval_from_string(expr); result = e_value_eval_from_eval(eval).value.f32; scratch_end(scratch); } return result; } internal CFG_Node * rd_immediate_cfg_from_key(String8 string) { CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); CFG_Node *immediate = &cfg_nil_node; CFG_Node *cfg = &cfg_nil_node; for(CFG_Node *child = transient->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("immediate"), 0)) { cfg = cfg_node_child_from_string(child, string); if(cfg != &cfg_nil_node) { immediate = child; break; } } } if(cfg == &cfg_nil_node) { immediate = cfg_node_new(rd_state->cfg, transient, str8_lit("immediate")); cfg = cfg_node_new(rd_state->cfg, immediate, string); } cfg_node_child_from_string_or_alloc(rd_state->cfg, immediate, str8_lit("hot")); return cfg; } internal CFG_Node * rd_immediate_cfg_from_keyf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 key = push_str8fv(scratch.arena, fmt, args); CFG_Node *result = rd_immediate_cfg_from_key(key); va_end(args); scratch_end(scratch); return result; } internal String8 rd_mapped_from_file_path(Arena *arena, String8 file_path) { Temp scratch = scratch_begin(&arena, 1); if(file_path.size != 0) { String8List file_path_parts = str8_split_path(scratch.arena, file_path); CFG_NodePtrList maps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("file_path_map")); String8 best_map_dst = {0}; U64 best_map_match_length = max_U64; String8Node *best_map_remaining_suffix_first = 0; for(CFG_NodePtrNode *n = maps.first; n != 0; n = n->next) { String8 map_src = cfg_node_child_from_string(n->v, str8_lit("source"))->first->string; String8List map_src_parts = str8_split_path(scratch.arena, map_src); B32 matches = 1; U64 match_length = 0; String8Node *file_path_part_n = file_path_parts.first; for(String8Node *map_src_n = map_src_parts.first; map_src_n != 0 && file_path_part_n != 0; map_src_n = map_src_n->next, file_path_part_n = file_path_part_n->next) { if(!str8_match(map_src_n->string, file_path_part_n->string, 0)) { matches = 0; break; } match_length += 1; } if(matches && match_length < best_map_match_length) { best_map_match_length = match_length; best_map_dst = cfg_node_child_from_string(n->v, str8_lit("dest"))->first->string; best_map_remaining_suffix_first = file_path_part_n; } } if(best_map_dst.size != 0) { String8List best_map_dst_parts = str8_split_path(scratch.arena, best_map_dst); for(String8Node *n = best_map_remaining_suffix_first; n != 0; n = n->next) { str8_list_push(scratch.arena, &best_map_dst_parts, n->string); } StringJoin join = {.sep = str8_lit("/")}; file_path = str8_list_join(scratch.arena, &best_map_dst_parts, &join); } } String8 result = push_str8_copy(arena, file_path); scratch_end(scratch); return result; } internal String8List rd_possible_overrides_from_file_path(Arena *arena, String8 file_path) { // NOTE(rjf): This path, given some target file path, scans all file path map // overrides, and collects the set of file paths which could've redirected // to the target file path given the set of file path maps. // // For example, if I have a rule saying D:/devel/ maps to C:/devel/, and I // feed in C:/devel/foo/bar.txt, then this path will construct // D:/devel/foo/bar.txt, as a possible option. // // It will also preserve C:/devel/foo/bar.txt in the resultant list, so that // overrideless files still work through this path, and both redirected // files and non-redirected files can go through the same path. // String8List result = {0}; str8_list_push(arena, &result, file_path); Temp scratch = scratch_begin(&arena, 1); PathStyle pth_style = PathStyle_Relative; String8List pth_parts = path_normalized_list_from_string(scratch.arena, file_path, &pth_style); { CFG_NodePtrList links = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("file_path_map")); for(CFG_NodePtrNode *n = links.first; n != 0; n = n->next) { //- rjf: unpack link CFG_Node *link = n->v; CFG_Node *src = cfg_node_child_from_string(link, str8_lit("source")); CFG_Node *dst = cfg_node_child_from_string(link, str8_lit("dest")); PathStyle src_style = PathStyle_Relative; PathStyle dst_style = PathStyle_Relative; String8List src_parts = path_normalized_list_from_string(scratch.arena, src->first->string, &src_style); String8List dst_parts = path_normalized_list_from_string(scratch.arena, dst->first->string, &dst_style); //- rjf: determine if this link can possibly redirect to the target file path B32 dst_redirects_to_pth = 0; String8Node *non_redirected_pth_first = 0; if(dst_style == pth_style && dst_parts.first != 0 && pth_parts.first != 0) { dst_redirects_to_pth = 1; String8Node *dst_n = dst_parts.first; String8Node *pth_n = pth_parts.first; for(;dst_n != 0 && pth_n != 0; dst_n = dst_n->next, pth_n = pth_n->next) { if(!str8_match(dst_n->string, pth_n->string, StringMatchFlag_CaseInsensitive)) { dst_redirects_to_pth = 0; break; } non_redirected_pth_first = pth_n->next; } } //- rjf: if this link can redirect to this path via `src` -> `dst`, compute // possible full source path, by taking `src` and appending non-redirected // suffix (which did not show up in `dst`) if(dst_redirects_to_pth) { String8List candidate_parts = src_parts; for(String8Node *p = non_redirected_pth_first; p != 0; p = p->next) { str8_list_push(scratch.arena, &candidate_parts, p->string); } StringJoin join = {0}; join.sep = str8_lit("/"); String8 candidate_path = str8_list_join(arena, &candidate_parts, &join); str8_list_push(arena, &result, candidate_path); } } } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Control Entity Info Extraction internal Vec4F32 rd_color_from_ctrl_entity(CTRL_Entity *entity) { Vec4F32 result = {0}; if(entity->rgba != 0) { result = linear_from_srgba(rgba_from_u32(entity->rgba)); } if(entity->rgba == 0) switch(entity->kind) { default:{}break; case CTRL_EntityKind_Thread: { CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); CTRL_Entity *main_thread = ctrl_entity_child_from_kind(process, CTRL_EntityKind_Thread); if(main_thread != entity) { result = ui_color_from_name(str8_lit("thread_1")); } else { result = ui_color_from_name(str8_lit("thread_0")); } }break; } return result; } internal String8 rd_name_from_ctrl_entity(Arena *arena, CTRL_Entity *entity) { String8 string = entity->string; if(string.size == 0) { string = str8_lit("unnamed"); } if(entity->kind == CTRL_EntityKind_Module) { string = str8_skip_last_slash(string); } return string; } //////////////////////////////// //~ rjf: Evaluation Spaces //- rjf: cfg <-> eval space internal CFG_Node * rd_cfg_from_eval_space(E_Space space) { CFG_Node *cfg = &cfg_nil_node; if(space.kind == RD_EvalSpaceKind_MetaCfg) { CFG_ID id = space.u64s[0]; cfg = cfg_node_from_id(id); } return cfg; } internal E_Space rd_eval_space_from_cfg(CFG_Node *cfg) { E_Space space = e_space_make(RD_EvalSpaceKind_MetaCfg); space.u64s[0] = cfg->id; return space; } //- rjf: ctrl entity <-> eval space internal CTRL_Entity * rd_ctrl_entity_from_eval_space(E_Space space) { CTRL_Entity *entity = &ctrl_entity_nil; if(space.kind == CTRL_EvalSpaceKind_Entity || space.kind == RD_EvalSpaceKind_MetaCtrlEntity || space.kind == RD_EvalSpaceKind_MetaUnattachedProcess) { CTRL_Handle handle; handle.machine_id = space.u64s[0]; handle.dmn_handle.u64[0] = space.u64s[1]; entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, handle); } return entity; } internal E_Space rd_eval_space_from_ctrl_entity(CTRL_Entity *entity, E_SpaceKind kind) { E_Space space = e_space_make(kind); space.u64s[0] = entity->handle.machine_id; space.u64s[1] = entity->handle.dmn_handle.u64[0]; return space; } //- rjf: command name <-> eval space internal String8 rd_cmd_name_from_eval(E_Eval eval) { String8 result = {0}; if(eval.space.kind == RD_EvalSpaceKind_MetaCmd) { result = e_string_from_id(eval.value.u64); } return result; } //- rjf: eval space reads/writes internal U64 rd_eval_space_gen(E_Space space) { U64 result = 0; switch(space.kind) { default: { result = ctrl_eval_space_gen(space); }break; case RD_EvalSpaceKind_MetaCfg: case RD_EvalSpaceKind_MetaQuery: { result = cfg_change_gen(); }break; } return result; } internal B32 rd_eval_space_read(E_Space space, void *out, Rng1U64 range) { Temp scratch = scratch_begin(0, 0); B32 result = 0; switch(space.kind) { default: { result = ctrl_eval_space_read(space, out, range); }break; //- rjf: interior control entity reads (inside process address space or thread register block) case CTRL_EvalSpaceKind_Entity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); switch(entity->kind) { default:{}break; case CTRL_EntityKind_Process: { CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, entity->handle, range, 0, rd_state->frame_eval_memread_endt_us); String8 data = slice.data; if(data.size == dim_1u64(range)) { result = 1; MemoryCopy(out, data.str, data.size); } }break; case CTRL_EntityKind_Thread: { Access *access = access_open(); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, entity->handle, 1, rd_state->frame_eval_memread_endt_us); U64 concrete_frame_idx = e_interpret_ctx->reg_unwind_count; if(concrete_frame_idx < call_stack.concrete_frames_count) { CTRL_CallStackFrame *f = call_stack.concrete_frames[concrete_frame_idx]; U64 regs_size = regs_block_size_from_arch(e_interpret_ctx->reg_arch); Rng1U64 legal_range = r1u64(0, regs_size); Rng1U64 read_range = intersect_1u64(legal_range, range); U64 read_size = dim_1u64(read_range); MemoryCopy(out, (U8 *)f->regs + read_range.min, read_size); result = (read_size == dim_1u64(range)); } access_close(access); }break; } }break; //- rjf: meta-config reads case RD_EvalSpaceKind_MetaCfg: { //- rjf: unpack cfg CFG_Node *root_cfg = rd_cfg_from_eval_space(space); String8 child_key = e_string_from_id(space.u64s[1]); CFG_Node *cfg = root_cfg; if(child_key.size != 0) { cfg = cfg_node_child_from_string(root_cfg, child_key); } //- rjf: determine data to read from, depending on child type in schema String8 read_data = {0}; if(child_key.size != 0) { // rjf: get schemas for the accessed child MD_Node *child_schema = &md_nil_node; MD_Node *expr_child_schema = &md_nil_node; { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, root_cfg->string); for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next) { child_schema = md_child_from_string(n->v, child_key, 0); if(child_schema != &md_nil_node) { expr_child_schema = md_child_from_string(n->v, str8_lit("expression"), 0); } } } String8 child_type_name = child_schema->first->string; // rjf: get value string (or default fallback) String8 value_string = cfg->first->string; if(value_string.size == 0) { value_string = md_tag_from_string(child_schema, str8_lit("default"), 0)->first->string; } // rjf: if this is an override child to a parent, fall back on defaults from parents if(value_string.size == 0 && !md_node_is_nil(md_tag_from_string(child_schema, str8_lit("override"), 0))) { for(CFG_Node *parent = root_cfg->parent; parent != &cfg_nil_node; parent = parent->parent) { CFG_Node *parent_child_w_key = cfg_node_child_from_string(parent, child_key); if(parent_child_w_key != &cfg_nil_node) { value_string = parent_child_w_key->first->string; break; } value_string = rd_default_setting_from_names(parent->string, child_key); if(value_string.size != 0) { break; } } } // rjf: if this is a query -> compute the value string based on query path if(md_node_has_tag(child_schema, str8_lit("query"), 0)) { // TODO(rjf): this needs to be replaced by hooks if(str8_match(child_schema->string, str8_lit("guid"), 0)) { Access *access = access_open(); String8 path = rd_path_from_cfg(root_cfg); U64 timestamp = 0; try_u64_from_str8_c_rules(cfg_node_child_from_string(root_cfg, str8_lit("timestamp"))->first->string, ×tamp); DI_Key key = di_key_from_path_timestamp(path, timestamp); RDI_Parsed *rdi = di_rdi_from_key(access, key, 0, 0); RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); Guid guid = {0}; MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid)); value_string = string_from_guid(scratch.arena, guid); access_close(access); } } // rjf: textual data if(str8_match(child_type_name, str8_lit("path"), 0) || str8_match(child_type_name, str8_lit("path_pt"), 0) || str8_match(child_type_name, str8_lit("code_string"), 0) || str8_match(child_type_name, str8_lit("expr_string"), 0) || str8_match(child_type_name, str8_lit("string"), 0)) { read_data = value_string; } // rjf: non-textual data else { E_Key parent_key = {0}; if(expr_child_schema != &md_nil_node && child_schema != expr_child_schema) { parent_key = e_key_from_string(cfg_node_child_from_string(root_cfg, expr_child_schema->string)->first->string); } E_ParentKey(parent_key) { if(str8_match(child_type_name, str8_lit("bool"), 0)) { B32 value = !!e_value_from_stringf("(bool)(%S)", value_string).u64; read_data = push_str8_copy(scratch.arena, str8_struct(&value)); } else if(str8_match(child_type_name, str8_lit("u64"), 0)) { U64 value = e_value_from_stringf("(uint64)(%S)", value_string).u64; read_data = push_str8_copy(scratch.arena, str8_struct(&value)); } else if(str8_match(child_type_name, str8_lit("u32"), 0)) { U64 value = e_value_from_stringf("(uint32)(%S)", value_string).u64; read_data = push_str8_copy(scratch.arena, str8_struct(&value)); } else if(str8_match(child_type_name, str8_lit("f32"), 0)) { F32 value = e_value_from_stringf("(float32)(%S)", value_string).f32; read_data = push_str8_copy(scratch.arena, str8_struct(&value)); } } } } // rjf: if no child key? -> just read from this cfg's child string - first 8 bytes -> offset of string (just 8), then string's content if(child_key.size == 0) { read_data = cfg->first->string; } // rjf: perform read Rng1U64 legal_range = r1u64(0, read_data.size); Rng1U64 read_range = intersect_1u64(range, legal_range); if(read_range.min < read_range.max) { result = 1; MemoryCopy(out, read_data.str + read_range.min, dim_1u64(read_range)); } }break; //- rjf: meta-entity reads case RD_EvalSpaceKind_MetaCtrlEntity: { // rjf: unpack cfg CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); String8 child_key = e_string_from_id(space.u64s[2]); // rjf: determine data to read from, depending on child name in schema String8 read_data = {0}; if(child_key.size != 0) { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, ctrl_entity_kind_code_name_table[entity->kind]); MD_Node *child_schema = &md_nil_node; for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next) { child_schema = md_child_from_string(n->v, child_key, 0); } if(str8_match(child_schema->string, str8_lit("exe"), 0) || str8_match(child_schema->string, str8_lit("label"), 0)) { read_data = entity->string; } else if(str8_match(child_schema->string, str8_lit("dbg"), 0)) { read_data = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath)->string; } else if(str8_match(child_schema->string, str8_lit("vaddr_range"), 0)) { read_data = str8_struct(&entity->vaddr_range); } else if(str8_match(child_schema->string, str8_lit("id"), 0)) { read_data = str8_struct(&entity->id); } else if(str8_match(child_schema->string, str8_lit("active"), 0)) { B32 is_frozen = ctrl_entity_tree_is_frozen(entity); B32 is_active = !is_frozen; read_data = push_str8_copy(scratch.arena, str8_struct(&is_active)); } } // rjf: perform read Rng1U64 legal_range = r1u64(0, read_data.size); Rng1U64 read_range = intersect_1u64(range, legal_range); if(read_range.min < read_range.max) { result = 1; MemoryCopy(out, read_data.str + read_range.min, dim_1u64(read_range)); } }break; } scratch_end(scratch); return result; } internal B32 rd_eval_space_write(E_Space space, void *in, Rng1U64 range) { B32 result = 0; switch(space.kind) { default:{}break; //- rjf: interior control entity writes (inside process address space or // thread register block) case CTRL_EvalSpaceKind_Entity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); switch(entity->kind) { default:{}break; case CTRL_EntityKind_Process: { result = ctrl_process_write(entity->handle, range, in); }break; case CTRL_EntityKind_Thread: { Temp scratch = scratch_begin(0, 0); U64 regs_size = regs_block_size_from_arch(entity->arch); Rng1U64 legal_range = r1u64(0, regs_size); Rng1U64 write_range = intersect_1u64(legal_range, range); U64 write_size = dim_1u64(write_range); void *new_regs = ctrl_reg_block_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, entity->handle); MemoryCopy((U8 *)new_regs + write_range.min, in, write_size); result = ctrl_thread_write_reg_block(entity->handle, new_regs); scratch_end(scratch); }break; } }break; //- rjf: meta-config writes case RD_EvalSpaceKind_MetaCfg: { result = 1; // rjf: unpack write info String8 write_string = str8_cstring_capped(in, (U8 *)in + dim_1u64(range)); // rjf: unpack cfg CFG_Node *root_cfg = rd_cfg_from_eval_space(space); String8 child_key = e_string_from_id(space.u64s[1]); // rjf: no child key? -> overwrite child string if(child_key.size == 0) { cfg_node_new_replace(rd_state->cfg, root_cfg, write_string); } // rjf: child key -> look up & edit child else { // rjf: modifying a label? -> poison this identifier in the macro map if(str8_match(child_key, str8_lit("label"), 0)) { String8 pre_edit_label = rd_label_from_cfg(root_cfg); if(!str8_match(pre_edit_label, write_string, 0)) { E_Expr *expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, pre_edit_label); if(expr != &e_expr_nil) { e_string2expr_map_inc_poison(e_ir_ctx->macro_map, pre_edit_label); e_string2expr_map_insert(e_cache->arena, e_ir_ctx->macro_map, write_string, expr); } } } // rjf: zero-range? delete child if(range.min == range.max) { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(root_cfg, child_key)); } // rjf: non-zero-range? create child if needed & write value else { CFG_Node *child_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, root_cfg, child_key); cfg_node_new_replace(rd_state->cfg, child_cfg, write_string); } } }break; //- rjf: meta-ctrl-entity writes case RD_EvalSpaceKind_MetaCtrlEntity: { Temp scratch = scratch_begin(0, 0); // rjf: unpack write info String8 write_string = str8_cstring_capped(in, (U8 *)in + dim_1u64(range)); // rjf: unpack cfg CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); String8 child_key = e_string_from_id(space.u64s[2]); // rjf: perform write, based on child name in schema if(child_key.size != 0) { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, ctrl_entity_kind_code_name_table[entity->kind]); MD_Node *child_schema = &md_nil_node; for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next) { child_schema = md_child_from_string(n->v, child_key, 0); } if(str8_match(child_schema->string, str8_lit("label"), 0)) { result = 1; ctrl_entity_equip_string(d_state->ctrl_entity_store, entity, write_string); rd_cmd(D_CmdKind_SetEntityName, .ctrl_entity = entity->handle, .string = write_string); } else if(str8_match(child_schema->string, str8_lit("dbg"), 0)) { // TODO(rjf) } else if(str8_match(child_schema->string, str8_lit("active"), 0)) { result = 1; B32 new_active = 0; MemoryCopy(&new_active, in, dim_1u64(range)); if(!new_active) { rd_cmd(D_CmdKind_FreezeEntity, .ctrl_entity = entity->handle); } else { rd_cmd(D_CmdKind_ThawEntity, .ctrl_entity = entity->handle); } } } scratch_end(scratch); }break; } return result; } //- rjf: asynchronous streamed reads -> hashes from spaces internal C_Key rd_key_from_eval_space_range(E_Space space, Rng1U64 range, B32 zero_terminated) { C_Key result = {0}; switch(space.kind) { case E_SpaceKind_HashStoreKey: { C_Root root = {space.u64_0}; C_ID id = {space.u128}; result = c_key_make(root, id); }break; case E_SpaceKind_File: { U64 file_path_string_id = space.u64_0; String8 file_path = e_string_from_id(file_path_string_id); result = fs_key_from_path_range(file_path, range, 0); }break; case CTRL_EvalSpaceKind_Entity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); if(entity->kind == CTRL_EntityKind_Process) { result = ctrl_key_from_process_vaddr_range(entity->handle, range, zero_terminated, 0, 0, 0); } }break; } return result; } //- rjf: space -> entire range internal Rng1U64 rd_whole_range_from_eval_space(E_Space space) { Rng1U64 result = {0}; switch(space.kind) { case E_SpaceKind_HashStoreKey: { C_Root root = {space.u64_0}; C_ID id = {space.u128}; C_Key key = c_key_make(root, id); U128 hash = c_hash_from_key(key, 0); Access *access = access_open(); { String8 data = c_data_from_hash(access, hash); result = r1u64(0, data.size); } access_close(access); }break; case E_SpaceKind_File: { U64 file_path_string_id = space.u64_0; String8 file_path = e_string_from_id(file_path_string_id); FileProperties props = os_properties_from_file_path(file_path); result = r1u64(0, props.size); }break; case CTRL_EvalSpaceKind_Entity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); if(entity->kind == CTRL_EntityKind_Process) { result = r1u64(0, 0x7FFFFFFFFFFFull); } }break; } return result; } //////////////////////////////// //~ rjf: Evaluation View Visualization & Interaction //- rjf: writing values back to child processes internal B32 rd_commit_eval_value_string(E_Eval dst_eval, String8 string) { B32 result = 0; if(dst_eval.irtree.mode == E_Mode_Offset) { Temp scratch = scratch_begin(0, 0); //- rjf: unpack type of destination E_TypeKey type_key = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind type_kind = e_type_kind_from_key(type_key); E_TypeKey direct_type_key = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_All); E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); //- rjf: determine data we'll write B32 got_commit_data = 0; String8 commit_data = {0}; B32 commit_at_ptr_dest = 0; if(!e_type_key_match(e_type_key_zero(), type_key)) { //- rjf: meta evaluations? -> always treat string as textual content, as-is, // and commit that. if(!got_commit_data && dst_eval.space.kind == RD_EvalSpaceKind_MetaCfg) { got_commit_data = 1; commit_data = string; } //- rjf: basic types or enums? treat string as an expression, cast to the // destination type, and compute commit data as being the binary representation // of the new value. if(!got_commit_data && ((E_TypeKind_FirstBasic <= type_kind && type_kind <= E_TypeKind_LastBasic) || type_kind == E_TypeKind_Enum)) { got_commit_data = 1; E_Eval src_eval = e_eval_from_stringf("(%S)(%S)", e_type_string_from_key(scratch.arena, type_key), string); commit_data = push_str8_copy(scratch.arena, str8_struct(&src_eval.value)); commit_data.size = Min(commit_data.size, e_type_byte_size_from_key(type_key)); } //- rjf: pointer or array to characters/integers? -> try to treat // new value string as textual data if(!got_commit_data && ((type_kind == E_TypeKind_Ptr || type_kind == E_TypeKind_Array) && (direct_type_kind == E_TypeKind_Char8 || direct_type_kind == E_TypeKind_Char16 || direct_type_kind == E_TypeKind_Char32 || direct_type_kind == E_TypeKind_UChar8 || direct_type_kind == E_TypeKind_UChar16 || direct_type_kind == E_TypeKind_UChar32 || e_type_kind_is_integer(direct_type_kind)))) { got_commit_data = 1; B32 is_quoted = 0; if(string.size >= 1 && string.str[0] == '"') { string = str8_skip(string, 1); is_quoted = 1; } if(string.size >= 1 && string.str[string.size-1] == '"') { string = str8_chop(string, 1); } if(is_quoted) { commit_data = raw_from_escaped_str8(scratch.arena, string); } else { commit_data = push_str8_copy(scratch.arena, string); } commit_data.size += 1; if(type_kind == E_TypeKind_Ptr) { commit_at_ptr_dest = 1; } switch(direct_type_kind) { default:{}break; case E_TypeKind_S16: case E_TypeKind_U16: case E_TypeKind_Char16: case E_TypeKind_UChar16: { String16 data16 = str16_from_8(scratch.arena, commit_data); commit_data = str8((U8 *)data16.str, data16.size*sizeof(U16)); }break; case E_TypeKind_Char32: case E_TypeKind_UChar32: case E_TypeKind_S32: case E_TypeKind_U32: { String32 data32 = str32_from_8(scratch.arena, commit_data); commit_data = str8((U8 *)data32.str, data32.size*sizeof(U32)); }break; } } //- rjf: pointer? -> try to treat new value as numeric value if(!got_commit_data && type_kind == E_TypeKind_Ptr) { E_Eval src_eval = e_eval_from_string(string); E_Eval src_eval_value = e_value_eval_from_eval(src_eval); E_TypeKind src_eval_value_type_kind = e_type_kind_from_key(src_eval_value.irtree.type_key); if((e_type_kind_is_pointer_or_ref(src_eval_value_type_kind) || e_type_kind_is_integer(src_eval_value_type_kind)) && src_eval_value.irtree.mode == E_Mode_Value) { got_commit_data = 1; commit_data = push_str8_copy(scratch.arena, str8_struct(&src_eval.value)); commit_data.size = Min(commit_data.size, e_type_byte_size_from_key(src_eval.irtree.type_key)); commit_data.size = Min(commit_data.size, e_type_byte_size_from_key(type_key)); } } } //- rjf: determine destination offset we'll write the new data to U64 dst_offset = dst_eval.value.u64; if(got_commit_data && commit_at_ptr_dest) { E_Eval dst_value_eval = e_value_eval_from_eval(dst_eval); dst_offset = dst_value_eval.value.u64; } //- rjf: if we have commit data, then write that data to the destination offset if(got_commit_data) { result = e_space_write(dst_eval.space, commit_data.str, r1u64(dst_offset, dst_offset + commit_data.size)); } scratch_end(scratch); } return result; } //- rjf: eval <-> file path internal String8 rd_file_path_from_eval(Arena *arena, E_Eval eval) { String8 result = {0}; switch(eval.space.kind) { default:{}break; case E_SpaceKind_File: { result = push_str8_copy(arena, e_string_from_id(eval.space.u64_0)); }break; case E_SpaceKind_FileSystem: { result = push_str8_copy(arena, e_string_from_id(eval.value.u64)); }break; } return result; } internal String8 rd_file_path_from_eval_string(Arena *arena, String8 string) { String8 result = {0}; { Temp scratch = scratch_begin(&arena, 1); E_Eval eval = e_eval_from_string(string); result = rd_file_path_from_eval(arena, eval); scratch_end(scratch); } return result; } internal String8 rd_eval_string_from_file_path(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); String8 string_escaped = escaped_from_raw_str8(scratch.arena, string); String8 result = push_str8f(arena, "file:\"%S\".data", string_escaped); scratch_end(scratch); return result; } //- rjf: eval -> query internal String8 rd_query_from_eval_string(Arena *arena, String8 string) { String8 result = {0}; { Temp scratch = scratch_begin(&arena, 1); E_Expr *expr = e_parse_from_string(string).expr; if(expr->kind == E_ExprKind_LeafIdentifier && str8_match(expr->qualifier, str8_lit("query"), 0)) { result = expr->string; } scratch_end(scratch); } return result; } //////////////////////////////// //~ rjf: View Functions internal CFG_Node * rd_view_from_eval(CFG_Node *parent, E_Eval eval) { Temp scratch = scratch_begin(0, 0); E_TypeKey type_key = eval.irtree.type_key; E_Type *type = e_type_from_key(type_key); String8 schema_name = str8_lit("watch"); B32 type_is_visualizer = 0; if(type->kind == E_TypeKind_Lens) { RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(type->name); if(view_ui_rule != &rd_nil_view_ui_rule) { schema_name = type->name; type_is_visualizer = 1; } } CFG_Node *view = cfg_node_child_from_string_or_alloc(rd_state->cfg, parent, schema_name); cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("selected")); { // rjf: get expression evaluation // TODO(rjf): we need to account for UFCS style expressions here... E_Eval expr_eval = eval; if(eval.expr->kind == E_ExprKind_Call && type_is_visualizer) { expr_eval = e_eval_from_expr(eval.expr->first->next); } // rjf: get arguments to view E_Expr **args = 0; U64 args_count = 0; if(type->args != 0) { args = type->args; args_count = type->count; } // rjf: reflect expr & arguments in cfg tree CFG_Node *expr_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr_root, e_full_expr_string_from_key(scratch.arena, expr_eval.key)); { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, schema_name); U64 unnamed_order_idx = 0; for EachIndex(arg_idx, args_count) { E_Expr *arg = args[arg_idx]; String8 param_name = {0}; E_Expr *arg_expr = arg; if(arg->kind == E_ExprKind_Define) { param_name = arg->first->string; arg_expr = arg->first->next; } else if(schemas.last != 0) { for MD_EachNode(schema_child, schemas.last->v->first) { MD_Node *order_tag = md_tag_from_string(schema_child, str8_lit("order"), 0); if(order_tag != &md_nil_node) { U64 schema_child_order_idx = 0; try_u64_from_str8_c_rules(order_tag->first->string, &schema_child_order_idx); if(schema_child_order_idx == unnamed_order_idx) { param_name = schema_child->string; arg_expr = arg; break; } } } unnamed_order_idx += 1; } CFG_Node *arg_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, param_name); cfg_node_new_replace(rd_state->cfg, arg_root, e_string_from_expr(scratch.arena, arg_expr, str8_zero())); } } } scratch_end(scratch); return view; } internal RD_ViewState * rd_view_state_from_cfg(CFG_Node *cfg) { RD_ViewState *view_state = &rd_nil_view_state; CFG_ID id = cfg->id; if(id != 0 && id == rd_state->view_state_last_accessed_id && id == rd_state->view_state_last_accessed->cfg_id) { view_state = rd_state->view_state_last_accessed; } else { U64 hash = d_hash_from_string(str8_struct(&id)); U64 slot_idx = hash%rd_state->view_state_slots_count; RD_ViewStateSlot *slot = &rd_state->view_state_slots[slot_idx]; for(RD_ViewState *v = slot->first; v != 0; v = v->hash_next) { if(v->cfg_id == id) { view_state = v; break; } } } if(view_state == &rd_nil_view_state) { view_state = rd_state->free_view_state; if(view_state) { SLLStackPop_N(rd_state->free_view_state, hash_next); } else { view_state = push_array(rd_state->arena, RD_ViewState, 1); } MemoryCopyStruct(view_state, &rd_nil_view_state); U64 hash = d_hash_from_string(str8_struct(&id)); U64 slot_idx = hash%rd_state->view_state_slots_count; RD_ViewStateSlot *slot = &rd_state->view_state_slots[slot_idx]; DLLPushBack_NP(slot->first, slot->last, view_state, hash_next, hash_prev); view_state->cfg_id = id; view_state->arena = arena_alloc(); view_state->arena_reset_pos = arena_pos(view_state->arena); view_state->ev_view = ev_view_alloc(); } if(view_state != &rd_nil_view_state) { view_state->last_frame_index_touched = rd_state->frame_index; } rd_state->view_state_last_accessed = view_state; rd_state->view_state_last_accessed_id = id; return view_state; } typedef struct RD_WatchRowExtrasDrawData RD_WatchRowExtrasDrawData; struct RD_WatchRowExtrasDrawData { B32 breaks_from_prev; }; internal UI_BOX_CUSTOM_DRAW(rd_watch_row_extras_custom_draw) { RD_WatchRowExtrasDrawData *draw_data = (RD_WatchRowExtrasDrawData *)user_data; if(draw_data->breaks_from_prev) DR_ClipScope(intersect_2f32(dr_top_clip(), box->rect)) { Vec4F32 shadow_color = ui_color_from_name(str8_lit("drop_shadow")); R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->rect.y0, box->rect.x1, (box->rect.y0+box->rect.y1)/2), shadow_color, 0, 0, 0); inst->colors[Corner_01] = inst->colors[Corner_11] = v4f32(0, 0, 0, 0); } } internal void rd_view_ui(Rng2F32 rect) { ProfBeginFunction(); CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *vs = rd_view_state_from_cfg(view); String8 view_name = view->string; String8 expr_string = rd_expr_from_cfg(view); B32 view_is_floating = 0; for(CFG_Node *p = view->parent; p != &cfg_nil_node; p = p->parent) { if(str8_match(p->string, str8_lit("immediate"), 0)) { view_is_floating = 1; break; } } ////////////////////////////// //- rjf: query extension // CFG_Node *query_root = cfg_node_child_from_string(view, str8_lit("query")); CFG_Node *input_root = cfg_node_child_from_string(query_root, str8_lit("input")); CFG_Node *cmd_root = cfg_node_child_from_string(query_root, str8_lit("cmd")); String8 current_input = input_root->first->string; B32 search_row_is_open = (vs->query_is_open); F32 search_row_open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "search_row_open_%p", view), (F32)!!search_row_is_open, .initial = (F32)!!search_row_is_open, .epsilon = 0.01f, .rate = rd_state->menu_animation_rate); if(search_row_open_t > 0.001f) { String8 cmd_name = cmd_root->first->string; RD_IconKind icon = rd_icon_kind_from_code_name(cmd_name); RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); //- rjf: store cfg's string into view's vs->query_string_size = Min(sizeof(vs->query_buffer), current_input.size); MemoryCopy(vs->query_buffer, current_input.str, vs->query_string_size); //- rjf: clamp cursor if(vs->query_cursor.column == 0) { vs->query_mark = txt_pt(1, 1); vs->query_cursor = txt_pt(1, vs->query_string_size+1); } //- rjf: determine dimensions F32 search_row_height_target = ui_top_px_height(); F32 search_row_height = search_row_open_t*search_row_height_target; search_row_height = Min(search_row_height, dim_2f32(rect).y); rect.y0 += search_row_height; rect.y0 = floor_f32(rect.y0); //- rjf: build container UI_Box *search_row = &ui_nil_box; UI_PrefHeight(ui_px(search_row_height, 1.f)) { search_row = ui_build_box_from_stringf(UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawDropShadow, "###search"); } //- rjf: build contents UI_Parent(search_row) UI_WidthFill UI_HeightFill UI_Focus(vs->query_is_open && !vs->contents_are_focused ? UI_FocusKind_On : UI_FocusKind_Off) RD_Font(cmd_kind_info->query.flags & RD_QueryFlag_CodeInput ? RD_FontSlot_Code : RD_FontSlot_Main) { if(cmd_name.size != 0) { UI_TextAlignment(UI_TextAlign_Center) UI_Transparency(1-search_row_open_t) UI_PrefWidth(ui_em(2.5f, 1.f)) UI_TagF("weak") RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[icon == RD_IconKind_Null ? RD_IconKind_Find : icon]); UI_Transparency(1-search_row_open_t) RD_Font(RD_FontSlot_Main) UI_PrefWidth(ui_text_dim(1, 1)) ui_label(rd_display_from_code_name(cmd_name)); ui_spacer(ui_em(0.5f, 1.f)); } UI_Key line_edit_key = {0}; RD_CellParams params = {0}; { params.flags |= !!(cmd_kind_info->query.flags & RD_QueryFlag_CodeInput) * RD_CellFlag_CodeContents; params.flags |= RD_CellFlag_Border; params.cursor = &vs->query_cursor; params.mark = &vs->query_mark; params.edit_buffer = vs->query_buffer; params.edit_string_size_out = &vs->query_string_size; params.edit_buffer_size = sizeof(vs->query_buffer); params.pre_edit_value = current_input; params.line_edit_key_out = &line_edit_key; } UI_Transparency(1-search_row_open_t) { UI_Signal sig = rd_cellf(¶ms, "###search"); #if 0 // TODO(rjf) if(ui_is_focus_active()) { rd_set_autocomp_regs(e_eval_nil, .ui_key = line_edit_key, .string = str8(vs->query_buffer, vs->query_string_size), .cursor = vs->query_cursor); } #endif if(ui_pressed(sig)) { vs->query_is_open = 1; vs->contents_are_focused = 0; rd_cmd(RD_CmdKind_FocusPanel); } } } //- rjf: commit string to view if(input_root == &cfg_nil_node) { input_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, query_root, str8_lit("input")); } cfg_node_new_replace(rd_state->cfg, input_root, str8(vs->query_buffer, vs->query_string_size)); } ////////////////////////////// //- rjf: build main view container // UI_Box *view_container = &ui_nil_box; UI_WidthFill UI_HeightFill { view_container = ui_build_box_from_key(0, ui_key_zero()); } ////////////////////////////// //- rjf: fill view container // UI_Parent(view_container) UI_FontSize(rd_font_size()) UI_PrefHeight(ui_px(floor_f32(ui_top_font_size()*rd_setting_f32_from_name(str8_lit("row_height"))), 1.f)) { //////////////////////////// //- rjf: special-case view: "getting started" // if(0){} else if(str8_match(view_name, str8_lit("getting_started"), 0)) { Temp scratch = scratch_begin(0, 0); ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) { CFG_NodePtrList targets = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); //- rjf: icon & info UI_Padding(ui_em(2.f, 1.f)) UI_TagF("weak") { //- rjf: icon { F32 icon_dim = ui_top_font_size()*10.f; UI_PrefHeight(ui_px(icon_dim, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_PrefWidth(ui_px(icon_dim, 1.f)) { R_Handle texture = rd_state->icon_texture; Vec2S32 texture_dim = r_size_from_tex2d(texture); ui_image(texture, R_Tex2DSampleKind_Linear, r2f32p(0, 0, texture_dim.x, texture_dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("")); } } //- rjf: info UI_Padding(ui_em(2.f, 1.f)) UI_WidthFill UI_PrefHeight(ui_em(2.f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_text_dim(10, 1)) { ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL)); } } //- rjf: targets state dependent helper B32 helper_built = 0; if(processes.count == 0) { helper_built = 1; switch(targets.count) { //- rjf: user has no targets. build helper for adding them case 0: { UI_PrefHeight(ui_em(3.75f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_em(22.f, 1.f)) UI_CornerRadius(ui_top_font_size()/2.f) UI_TagF("pop") if(ui_clicked(rd_icon_buttonf(RD_IconKind_Add, 0, "Add Target"))) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_AddTarget].string); } }break; //- rjf: user has 1 target. build helper for launching it case 1: { CFG_Node *target_cfg = cfg_node_ptr_list_first(&targets); D_Target target = rd_target_from_cfg(scratch.arena, target_cfg); String8 target_full_path = target.exe; String8 target_name = str8_skip_last_slash(target_full_path); UI_PrefHeight(ui_em(3.75f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_em(22.f, 1.f)) UI_CornerRadius(ui_top_font_size()/2.f) UI_TagF("good_pop") { if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Launch %S", target_name))) { rd_cmd(RD_CmdKind_LaunchAndRun, .cfg = target_cfg->id); } ui_spacer(ui_em(1.5f, 1)); if(ui_clicked(rd_icon_buttonf(RD_IconKind_StepInto, 0, "Step Into %S", target_name))) { rd_cmd(RD_CmdKind_LaunchAndStepInto, .cfg = target_cfg->id); } } }break; //- rjf: user has N targets. default: { helper_built = 0; }break; } } //- rjf: or text if(helper_built) { UI_TagF("weak") UI_PrefHeight(ui_em(2.25f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_WidthFill ui_labelf("- or -"); } //- rjf: helper text for command lister activation UI_TagF("weak") UI_PrefHeight(ui_em(2.25f, 1.f)) UI_Row UI_PrefWidth(ui_text_dim(10, 1)) UI_TextAlignment(UI_TextAlign_Center) UI_Padding(ui_pct(1, 0)) { ui_labelf("use"); UI_TextAlignment(UI_TextAlign_Center) rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string, str8_zero(), 1); ui_labelf("to search for commands and options"); } } scratch_end(scratch); } //////////////////////////// //- rjf: special-case view: pending // else if(str8_match(view_name, str8_lit("pending"), 0)) { Temp scratch = scratch_begin(0, 0); typedef struct State State; struct State { Arena *deferred_cmd_arena; RD_CmdList deferred_cmds; }; State *state = rd_view_state(State); if(state->deferred_cmd_arena == 0) { state->deferred_cmd_arena = rd_push_view_arena(); } rd_store_view_loading_info(1, 0, 0); // rjf: any commands sent to this view need to be deferred until loading is complete for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default:{}break; case RD_CmdKind_GoToLine: case RD_CmdKind_GoToAddress: case RD_CmdKind_CenterCursor: case RD_CmdKind_ContainCursor: { rd_cmd_list_push_new(state->deferred_cmd_arena, &state->deferred_cmds, cmd->name, cmd->regs); }break; } } // rjf: unpack view's target expression & hash E_Eval eval = e_eval_from_string(expr_string); Rng1U64 range = r1u64(0, 1024); C_Key key = rd_key_from_eval_space_range(eval.space, range, 0); U128 hash = c_hash_from_key(key, 0); // rjf: determine if hash's blob is ready, and which viewer to use B32 data_is_ready = 0; String8 new_view_name = {0}; { Access *access = access_open(); if(!u128_match(hash, u128_zero())) { String8 data = c_data_from_hash(access, hash); U64 num_utf8_bytes = 0; U64 num_unknown_bytes = 0; for(U64 idx = 0; idx < data.size && idx < range.max;) { UnicodeDecode decode = utf8_decode(data.str+idx, data.size-idx); if(decode.codepoint != max_U32 && (decode.inc > 1 || (10 <= decode.codepoint && decode.codepoint <= 13) || (32 <= decode.codepoint && decode.codepoint <= 126))) { num_utf8_bytes += decode.inc; idx += decode.inc; } else { num_unknown_bytes += 1; idx += 1; } } data_is_ready = 1; if(num_utf8_bytes > num_unknown_bytes*4 || num_unknown_bytes == 0) { new_view_name = str8_lit("text"); } else { new_view_name = str8_lit("memory"); } } access_close(access); } // rjf: if we don't have a viewer, just use the memory viewer. if(new_view_name.size == 0) { new_view_name = str8_lit("memory"); } // rjf: if data is ready and we have the name of a new visualizer, // dispatch deferred commands & change this view's string to be // that of the new visualizer. if(data_is_ready && new_view_name.size != 0) { for(RD_CmdNode *cmd_node = state->deferred_cmds.first; cmd_node != 0; cmd_node = cmd_node->next) { RD_Cmd *cmd = &cmd_node->cmd; rd_push_cmd(cmd->name, cmd->regs); } CFG_Node *view = cfg_node_from_id(rd_regs()->view); cfg_node_equip_string(rd_state->cfg, view, new_view_name); RD_ViewState *vs = rd_view_state_from_cfg(view); for(RD_ArenaExt *ext = vs->first_arena_ext; ext != 0; ext = ext->next) { arena_release(ext->arena); } arena_pop_to(vs->arena, vs->arena_reset_pos); vs->user_data = 0; vs->first_arena_ext = vs->last_arena_ext = 0; } // rjf: if we don't have a viewer, for whatever reason, then just // close the tab. if(data_is_ready && new_view_name.size == 0) { rd_cmd(RD_CmdKind_CloseTab); } scratch_end(scratch); } //////////////////////////// //- rjf: watch view // else if(str8_match(view_name, str8_lit("watch"), 0)) { Temp scratch = scratch_begin(0, 0); RD_Font(RD_FontSlot_Code) { if(expr_string.size == 0) { expr_string = push_str8f(scratch.arena, "query:config.$%I64x.watches", rd_regs()->view); } E_Eval eval = e_eval_from_string(expr_string); RD_WatchViewState *ewv = rd_view_state(RD_WatchViewState); UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); F32 entity_hover_t_rate = rd_setting_b32_from_name(str8_lit("hover_animations")) ? (1 - pow_f32(2, (-60.f * rd_state->frame_dt))) : 1.f; B32 is_first_frame = 0; if(ewv->initialized == 0) { is_first_frame = 1; ewv->initialized = 1; ewv->filter_arena = rd_push_view_arena(); ewv->text_edit_arena = rd_push_view_arena(); } ////////////////////////////// //- rjf: unpack arguments // EV_View *eval_view = rd_view_eval_view(); F32 row_height_px = ui_top_px_height(); S64 num_possible_visible_rows = (S64)(dim_2f32(rect).y/row_height_px); F32 row_string_max_size_px = dim_2f32(rect).x; EV_StringFlags string_flags = EV_StringFlag_ReadOnlyDisplayRules; String8 filter = rd_view_query_input(); Vec4F32 pop_background_rgba = {0}; UI_TagF("pop") pop_background_rgba = ui_color_from_name(str8_lit("background")); ////////////////////////////// //- rjf: whenever the filter changes, we want to reset the cursor/mark state // if(!str8_match(filter, ewv->last_filter, 0)) { MemoryZeroStruct(&ewv->cursor); MemoryZeroStruct(&ewv->mark); MemoryZeroStruct(&ewv->next_cursor); MemoryZeroStruct(&ewv->next_mark); arena_clear(ewv->filter_arena); ewv->last_filter = push_str8_copy(ewv->filter_arena, filter); } ////////////////////////////// //- rjf: decide if root should be implicit // // "implicit" means -> root is automatically expanded, row depth is 1 less than the // block tree structure would suggest. this would be used if the root is, for instance, // the "collection of all watches", to build a watch window. but this behavior is not // as desirable if we are just using some other expression as the root. // B32 implicit_root = (cfg_node_child_from_string(cfg_node_from_id(rd_regs()->view), str8_lit("explicit_root")) == &cfg_nil_node); ////////////////////////////// //- rjf: determine autocompletion string // String8 autocomplete_hint_string = ui_autocomplete_string(); ////////////////////////////// //- rjf: process commands // for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default:{}break; case RD_CmdKind_Search: case RD_CmdKind_SearchBackwards: { vs->query_is_open = 0; }break; } } ////////////////////////////// //- rjf: consume events & perform navigations/edits - calculate state // EV_BlockTree block_tree = {0}; EV_BlockRangeList block_ranges = {0}; UI_ScrollListRowBlockArray row_blocks = {0}; Vec2S64 cursor_tbl = {0}; Vec2S64 mark_tbl = {0}; Rng2S64 selection_tbl = {0}; ProfScope("consume events & perform navigations/edits - calculate state") UI_Focus(UI_FocusKind_On) { B32 state_dirty = 1; B32 snap_to_cursor = 0; B32 cursor_dirty__tbl = 0; for(UI_Event *event = 0;;) { ////////////////////////// //- rjf: state -> viz blocks // if(state_dirty) ProfScope("state -> viz blocks") { eval = e_eval_from_string(eval.string); MemoryZeroStruct(&block_tree); MemoryZeroStruct(&block_ranges); if(implicit_root || is_first_frame) { ev_key_set_expansion(eval_view, ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); } block_tree = ev_block_tree_from_eval(scratch.arena, eval_view, filter, eval); block_ranges = ev_block_range_list_from_tree(scratch.arena, &block_tree); if(implicit_root && block_ranges.first != 0) { block_ranges.count -= 1; block_ranges.first = block_ranges.first->next; } } ////////////////////////// //- rjf: block ranges -> ui row blocks // ProfScope("block ranges -> ui row blocks") { UI_ScrollListRowBlockChunkList row_block_chunks = {0}; for(EV_BlockRangeNode *n = block_ranges.first; n != 0; n = n->next) { UI_ScrollListRowBlock block = {0}; block.row_count = dim_1u64(n->v.range); block.item_count = n->v.block->viz_expand_info.single_item ? 1 : dim_1u64(n->v.range); ui_scroll_list_row_block_chunk_list_push(scratch.arena, &row_block_chunks, 256, &block); } row_blocks = ui_scroll_list_row_block_array_from_chunk_list(scratch.arena, &row_block_chunks); } ////////////////////////// //- rjf: conclude state update // if(state_dirty) { state_dirty = 0; } ////////////////////////////// //- rjf: 2D table coordinates * blocks -> stable cursor state // if(cursor_dirty__tbl) { cursor_dirty__tbl = 0; struct { RD_WatchPt *pt_state; Vec2S64 pt_tbl; } points[] = { {&ewv->cursor, cursor_tbl}, {&ewv->mark, mark_tbl}, }; for(U64 point_idx = 0; point_idx < ArrayCount(points); point_idx += 1) { EV_Key last_key = points[point_idx].pt_state->key; EV_Key last_parent_key = points[point_idx].pt_state->parent_key; points[point_idx].pt_state[0] = rd_watch_pt_from_tbl(&block_ranges, points[point_idx].pt_tbl); if(ev_key_match(ev_key_zero(), points[point_idx].pt_state->key) && points[point_idx].pt_tbl.y != 0) { points[point_idx].pt_state->key = last_parent_key; EV_ExpandNode *node = ev_expand_node_from_key(eval_view, last_parent_key); for(EV_ExpandNode *n = node; n != 0; n = n->parent) { points[point_idx].pt_state->key = n->key; if(n->expanded == 0) { break; } } } if(point_idx == 0 && (!ev_key_match(ewv->cursor.key, last_key) || !ev_key_match(ewv->cursor.parent_key, last_parent_key))) { ewv->text_editing = 0; } } ewv->next_cursor = ewv->cursor; ewv->next_mark = ewv->mark; } ////////////////////////// //- rjf: stable cursor state * blocks -> 2D table coordinates // EV_WindowedRowList mark_rows = {0}; Rng2S64 cursor_tbl_range = {0}; { // rjf: compute 2d table coordinates cursor_tbl = rd_tbl_from_watch_pt(&block_ranges, ewv->cursor); mark_tbl = rd_tbl_from_watch_pt(&block_ranges, ewv->mark); // rjf: compute legal coordinate range, given selection-defining row Rng1S64 cursor_x_range = {0}; { EV_Row *row = ev_row_from_num(scratch.arena, eval_view, &block_ranges, mark_tbl.y); RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); cursor_x_range = r1s64(0, (S64)row_info.cells.count-1); } cursor_tbl_range = r2s64(v2s64(cursor_x_range.min, 0), v2s64(cursor_x_range.max, block_tree.total_item_count - implicit_root)); // rjf: clamp x positions of cursor/mark tbl for EachEnumVal(Axis2, axis) { cursor_tbl.v[axis] = clamp_1s64(r1s64(cursor_tbl_range.min.v[axis], cursor_tbl_range.max.v[axis]), cursor_tbl.v[axis]); mark_tbl.v[axis] = clamp_1s64(r1s64(cursor_tbl_range.min.v[axis], cursor_tbl_range.max.v[axis]), mark_tbl.v[axis]); } // rjf: form selection range table coordinates selection_tbl = r2s64p(Min(cursor_tbl.x, mark_tbl.x), Min(cursor_tbl.y, mark_tbl.y), Max(cursor_tbl.x, mark_tbl.x), Max(cursor_tbl.y, mark_tbl.y)); } ////////////////////////// //- rjf: [table] snap to cursor // if(snap_to_cursor) { Rng1S64 global_vnum_range = r1s64(1, block_tree.total_row_count+1); if(contains_1s64(global_vnum_range, cursor_tbl.y)) { UI_ScrollPt *scroll_pt = &scroll_pos.y; //- rjf: compute visible row range Rng1S64 visible_row_num_range = r1s64(scroll_pt->idx + 1 - !!(scroll_pt->off < 0), scroll_pt->idx + 1 + num_possible_visible_rows); //- rjf: compute cursor row range from cursor item Rng1S64 cursor_visibility_row_num_range = {0}; cursor_visibility_row_num_range.min = ev_vnum_from_num(&block_ranges, cursor_tbl.y) - 1; cursor_visibility_row_num_range.max = cursor_visibility_row_num_range.min + 3; //- rjf: compute deltas & apply S64 min_delta = Min(0, cursor_visibility_row_num_range.min-visible_row_num_range.min); S64 max_delta = Max(0, cursor_visibility_row_num_range.max-visible_row_num_range.max); S64 new_num = (S64)scroll_pt->idx + 1 + min_delta + max_delta; new_num = clamp_1s64(global_vnum_range, new_num); if(new_num > 0) { U64 new_idx = (U64)(new_num - 1); ui_scroll_pt_target_idx(scroll_pt, new_idx); } } } ////////////////////////////// //- rjf: apply cursor/mark rugpull change // B32 cursor_rugpull = 0; if(!rd_watch_pt_match(ewv->cursor, ewv->next_cursor)) { cursor_rugpull = 1; ewv->cursor = ewv->next_cursor; ewv->mark = ewv->next_mark; } ////////////////////////// //- rjf: grab next event, if any - otherwise exit the loop, as we now have // the most up-to-date state // B32 next_event_good = ui_next_event(&event); if(!cursor_rugpull && (!next_event_good || !ui_is_focus_active())) { break; } UI_Event dummy_evt = zero_struct; UI_Event *evt = &dummy_evt; if(next_event_good) { evt = event; } B32 taken = 0; ////////////////////////////// //- rjf: consume query-completion events, if this view is being used as a lister // { if(evt->kind == UI_EventKind_Press && evt->slot == UI_EventActionSlot_Accept && selection_tbl.min.y == selection_tbl.max.y && (cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node)) { CFG_Node *query = cfg_node_child_from_string(view, str8_lit("query")); CFG_Node *cmd = cfg_node_child_from_string(query, str8_lit("cmd")); String8 cmd_name = cmd->first->string; // rjf: if we have no selection, just pick the first row EV_Row *row = 0; if(selection_tbl.min.y == 0 && selection_tbl.max.y == 0) { row = ev_row_from_num(scratch.arena, eval_view, &block_ranges, 1); } // rjf: if we do have a selection, compute that row else { row = ev_row_from_num(scratch.arena, eval_view, &block_ranges, selection_tbl.min.y); } // rjf: use row to complete query if(row->eval.expr != &e_expr_nil) { taken = 1; E_Eval eval = row->eval; // rjf: if we have a specific command we are trying to complete, then // fill registers based on this row's evaluation. if(cmd_name.size != 0) switch(eval.space.kind) { default: { U64 voff = 0; DI_Key dbgi_key = {0}; if(eval.space.kind == CTRL_EvalSpaceKind_Entity) { U64 vaddr = eval.value.u64; CTRL_Entity *process = rd_ctrl_entity_from_eval_space(eval.space); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); dbgi_key = ctrl_dbgi_key_from_module(module); voff = ctrl_voff_from_vaddr(module, vaddr); } else { voff = eval.value.u64; E_DbgInfo *dbg_info = e_dbg_info_from_type_key(eval.irtree.type_key); dbgi_key = dbg_info->dbgi_key; } { Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); String8 name = {0}; if(name.size == 0) { RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); name.str = rdi_name_from_procedure(rdi, procedure, &name.size); } if(name.size == 0) { RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff); name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &name.size); } if(name.size != 0) { rd_cmd(RD_CmdKind_CompleteQuery, .string = name); } access_close(access); } }break; case E_SpaceKind_File: case E_SpaceKind_FileSystem: { E_Type *type = e_type_from_key(eval.irtree.type_key); String8 file = rd_file_path_from_eval(scratch.arena, eval); if(str8_match(type->name, str8_lit("folder"), 0)) { String8 new_input_string = push_str8f(scratch.arena, "%S/", file); rd_cmd(RD_CmdKind_UpdateQuery, .string = new_input_string); } else { rd_cmd(RD_CmdKind_CompleteQuery, .file_path = file); } }break; case RD_EvalSpaceKind_MetaCfg: { CFG_Node *cfg = rd_cfg_from_eval_space(eval.space); rd_cmd(RD_CmdKind_CompleteQuery, .cfg = cfg->id); }break; case RD_EvalSpaceKind_MetaCtrlEntity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); RD_RegsScope(.ctrl_entity = entity->handle) { if(0){} else if(entity->kind == CTRL_EntityKind_Thread) { rd_regs()->thread = entity->handle; } else if(entity->kind == CTRL_EntityKind_Module) { rd_regs()->module = entity->handle; } else if(entity->kind == CTRL_EntityKind_Process) { rd_regs()->process = entity->handle; } else if(entity->kind == CTRL_EntityKind_Machine) { rd_regs()->machine = entity->handle; } rd_cmd(RD_CmdKind_CompleteQuery); } }break; case RD_EvalSpaceKind_MetaUnattachedProcess: { U64 pid = eval.value.u128.u64[0]; rd_cmd(RD_CmdKind_CompleteQuery, .pid = pid); }break; case RD_EvalSpaceKind_MetaCmd: { String8 cmd_name = rd_cmd_name_from_eval(eval); rd_cmd(RD_CmdKind_CompleteQuery, .cmd_name = cmd_name); }break; case RD_EvalSpaceKind_MetaTheme: { String8 name = e_string_from_id(eval.value.u64); rd_cmd(RD_CmdKind_CompleteQuery, .string = name); }break; } // rjf: if we do not have a specific command, then we can just // pick a sensible default based on what was selected. if(cmd_name.size == 0) { B32 did_cmd = 1; switch(eval.space.kind) { default: { String8 name = {0}; { U64 vaddr = eval.value.u64; CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); U64 voff = ctrl_voff_from_vaddr(module, vaddr); { Access *access = access_open(); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, 0); if(name.size == 0) { RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); name.str = rdi_name_from_procedure(rdi, procedure, &name.size); } if(name.size == 0) { RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff); name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &name.size); } access_close(access); } } if(name.size != 0) { rd_cmd(RD_CmdKind_GoToName, .string = name); } else { rd_cmd(RD_CmdKind_PushQuery, .expr = e_string_from_expr(scratch.arena, eval.expr, str8_zero())); } }break; case E_SpaceKind_File: case E_SpaceKind_FileSystem: { String8 file = rd_file_path_from_eval(scratch.arena, eval); rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = file, .vaddr = 0); }break; case RD_EvalSpaceKind_MetaCfg: { CFG_Node *cfg = rd_cfg_from_eval_space(eval.space); if(str8_match(cfg->string, str8_lit("recent_file"), 0)) { rd_cmd(RD_CmdKind_Switch, .cfg = cfg->id); } else if(str8_match(cfg->string, str8_lit("recent_project"), 0)) { rd_cmd(RD_CmdKind_OpenRecentProject, .cfg = cfg->id); } else if(e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)) == E_TypeKind_Set) { rd_cmd(RD_CmdKind_PushQuery, .expr = e_full_expr_string_from_key(scratch.arena, eval.key)); } else { did_cmd = 0; } }break; case RD_EvalSpaceKind_MetaQuery: { rd_cmd(RD_CmdKind_PushQuery, .expr = e_full_expr_string_from_key(scratch.arena, eval.key)); }break; case RD_EvalSpaceKind_MetaUnattachedProcess: { U64 pid = eval.value.u128.u64[0]; }break; case RD_EvalSpaceKind_MetaCmd: { String8 cmd_name = rd_cmd_name_from_eval(eval); rd_cmd(RD_CmdKind_RunCommand, .cmd_name = cmd_name); }break; case RD_EvalSpaceKind_MetaCtrlEntity: { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:control.%S", ctrl_string_from_handle(scratch.arena, entity->handle))); }break; } if(did_cmd) { rd_cmd(RD_CmdKind_CompleteQuery); } else { taken = 0; } } } } } ////////////////////////// //- rjf: begin editing on some operations // if(!ewv->text_editing && (evt->kind == UI_EventKind_Text || evt->flags & UI_EventFlag_Paste || (evt->kind == UI_EventKind_Press && evt->slot == UI_EventActionSlot_Edit)) && selection_tbl.min.x == selection_tbl.max.x && (selection_tbl.min.y != 0 || selection_tbl.max.y != 0)) { Vec2S64 selection_dim = dim_2s64(selection_tbl); arena_clear(ewv->text_edit_arena); ewv->text_edit_state_slots_count = u64_up_to_pow2(selection_dim.y+1); ewv->text_edit_state_slots_count = Max(ewv->text_edit_state_slots_count, 64); ewv->text_edit_state_slots = push_array(ewv->text_edit_arena, RD_WatchViewTextEditState*, ewv->text_edit_state_slots_count); EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); EV_WindowedRowNode *row_node = rows.first; B32 any_edits_started = 0; for(S64 y = selection_tbl.min.y; row_node != 0 && y <= selection_tbl.max.y; y += 1, row_node = row_node->next) { EV_Row *row = &row_node->row; RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); S64 cell_x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, cell_x += 1) { if(cell_x < selection_tbl.min.x || selection_tbl.max.x < cell_x) { continue; } RD_WatchRowCellInfo cell_info = rd_info_from_watch_row_cell(scratch.arena, row, string_flags & (~EV_StringFlag_ReadOnlyDisplayRules), &row_info, cell, ui_top_font(), ui_top_font_size(), row_string_max_size_px); if(cell_info.flags & RD_WatchCellFlag_CanEdit) { any_edits_started = 1; String8 string = {0}; if(cell_info.flags & RD_WatchCellFlag_NoEval) { string = cell->eval.string; } else { string = dr_string_from_fstrs(scratch.arena, &cell_info.eval_fstrs); } string.size = Min(string.size, sizeof(ewv->dummy_text_edit_state.input_buffer)); RD_WatchPt pt = {row->block->key, row->key, rd_id_from_watch_cell(cell)}; U64 hash = ev_hash_from_key(pt.key); U64 slot_idx = hash%ewv->text_edit_state_slots_count; RD_WatchViewTextEditState *edit_state = push_array(ewv->text_edit_arena, RD_WatchViewTextEditState, 1); SLLStackPush_N(ewv->text_edit_state_slots[slot_idx], edit_state, pt_hash_next); edit_state->pt = pt; edit_state->cursor = txt_pt(1, string.size+1); edit_state->mark = txt_pt(1, 1); edit_state->input_size = string.size; MemoryCopy(edit_state->input_buffer, string.str, string.size); edit_state->initial_size = string.size; MemoryCopy(edit_state->initial_buffer, string.str, string.size); } } } ewv->text_editing = any_edits_started; } ////////////////////////// //- rjf: [table] do cell-granularity multi-cursor 'accept' operations (expansions / etc.); if // cannot apply to multi-cursor, then just don't take the event // if(!ewv->text_editing && evt->slot == UI_EventActionSlot_Accept && (selection_tbl.min.y != 0 || selection_tbl.max.y != 0) && (selection_tbl.max.y - selection_tbl.min.y > 0)) { EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); EV_WindowedRowNode *row_node = rows.first; if(row_node != 0) { taken = 1; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row_node != 0; y += 1, row_node = row_node->next) { // rjf: unpack row info EV_Row *row = &row_node->row; RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); // rjf: loop through X selections and perform operations for each for(S64 x = selection_tbl.min.x; x <= selection_tbl.max.x; x += 1) { #if 0 // TODO(rjf): @cfg (multicursor watch window press operations) //- rjf: determine operation for this cell typedef enum OpKind { OpKind_Null, OpKind_DoExpand, } OpKind; OpKind kind = OpKind_Null; switch(row_kind) { default:{}break; case RD_WatchViewRowKind_Normal: { RD_WatchViewColumn *col = rd_watch_view_column_from_x(ewv, x); switch(col->kind) { default:{}break; case RD_WatchViewColumnKind_Expr: {kind = OpKind_DoExpand;}break; } }break; case RD_WatchViewRowKind_PrettyEntityControls: if((!rd_entity_is_nil(row_info.collection_entity) || row_info.collection_ctrl_entity != &ctrl_entity_nil) && selection_tbl.min.x == 1 && selection_tbl.max.x == 1) { kind = OpKind_DoExpand; }break; } //- rjf: perform operation switch(kind) { default:{taken = 0;}break; case OpKind_DoExpand: if(ev_row_is_expandable(row)) { B32 is_expanded = ev_expansion_from_key(eval_view, row->key); ev_key_set_expansion(eval_view, row->block->key, row->key, !is_expanded); }break; } #endif } } } } ////////////////////////// //- rjf: [text] apply textual edits // if(ewv->text_editing) { B32 editing_complete = ((evt->kind == UI_EventKind_Press && (evt->slot == UI_EventActionSlot_Cancel || evt->slot == UI_EventActionSlot_Accept)) || (evt->kind == UI_EventKind_Navigate && evt->delta_2s32.y != 0) || cursor_rugpull); rd_state->text_edit_mode = 1; if(editing_complete || ((evt->kind == UI_EventKind_Edit || evt->kind == UI_EventKind_Navigate || evt->kind == UI_EventKind_Text) && evt->delta_2s32.y == 0)) { taken = 1; EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); EV_WindowedRowNode *row_node = rows.first; for(S64 y = selection_tbl.min.y; row_node != 0 && y <= selection_tbl.max.y; y += 1, row_node = row_node->next) { EV_Row *row = &row_node->row; RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); S64 cell_x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, cell_x += 1) { if(cell_x < selection_tbl.min.x || selection_tbl.max.x < cell_x) { continue; } RD_WatchPt pt = {row->block->key, row->key, rd_id_from_watch_cell(cell)}; RD_WatchViewTextEditState *edit_state = rd_watch_view_text_edit_state_from_pt(ewv, pt); String8 string = str8(edit_state->input_buffer, edit_state->input_size); UI_TxtOp op = ui_single_line_txt_op_from_event(scratch.arena, evt, string, edit_state->cursor, edit_state->mark); // rjf: copy if(op.flags & UI_TxtOpFlag_Copy && selection_tbl.min.x == selection_tbl.max.x && selection_tbl.min.y == selection_tbl.max.y) { os_set_clipboard_text(op.copy); } // rjf: any valid *additive* op & autocomplete hint? -> perform autocomplete first, then re-compute op if(!(evt->flags & UI_EventFlag_Delete) && autocomplete_hint_string.size != 0) { String8 autocomplete_string = ui_autocomplete(); CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info; String8 new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(autocomp_cursor_info->replaced_range.min+1, autocomp_cursor_info->replaced_range.max+1), autocomplete_string); new_string.size = Min(sizeof(edit_state->input_buffer), new_string.size); MemoryCopy(edit_state->input_buffer, new_string.str, new_string.size); edit_state->input_size = new_string.size; edit_state->cursor = edit_state->mark = txt_pt(1, 1+autocomp_cursor_info->replaced_range.min+autocomplete_string.size); string = str8(edit_state->input_buffer, edit_state->input_size); op = ui_single_line_txt_op_from_event(scratch.arena, evt, string, edit_state->cursor, edit_state->mark); } // rjf: cancel? -> revert to initial string if(editing_complete && evt->slot == UI_EventActionSlot_Cancel) { string = str8(edit_state->initial_buffer, edit_state->initial_size); } // rjf: obtain edited string String8 new_string = string; if(!txt_pt_match(op.range.min, op.range.max) || op.replace.size != 0) { new_string = ui_push_string_replace_range(scratch.arena, string, r1s64(op.range.min.column, op.range.max.column), op.replace); } // rjf: commit to edit state new_string.size = Min(new_string.size, sizeof(edit_state->input_buffer)); MemoryCopy(edit_state->input_buffer, new_string.str, new_string.size); edit_state->input_size = new_string.size; edit_state->cursor = op.cursor; edit_state->mark = op.mark; // rjf: commit edited cell string - first try to commit eval value, if that path is // enabled on this cell, next try to commit expression string, if that path is enabled if(cell->kind == RD_WatchCellKind_Eval) { if(cell->flags & RD_WatchCellFlag_Expr && cell->flags & RD_WatchCellFlag_NoEval) { CFG_Node *cfg = row_info.group_cfg_child; String8 child_key = {0}; // str8_lit("expression"); if(cfg == &cfg_nil_node && editing_complete && new_string.size != 0) { CFG_Node *new_cfg_parent = row_info.group_cfg_parent; if(new_cfg_parent != &cfg_nil_node) { child_key = str8_zero(); } if(new_cfg_parent == &cfg_nil_node) { CFG_NodePtrList all_cfgs = cfg_node_top_level_list_from_string(scratch.arena, row_info.group_cfg_name); new_cfg_parent = cfg_node_ptr_list_last(&all_cfgs)->parent; } if(new_cfg_parent == &cfg_nil_node) { new_cfg_parent = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); } cfg = cfg_node_new(rd_state->cfg, new_cfg_parent, row_info.group_cfg_name); state_dirty = 1; snap_to_cursor = 1; } if(cfg != &cfg_nil_node) { CFG_Node *expr = child_key.size != 0 ? cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, child_key) : cfg; cfg_node_new_replace(rd_state->cfg, expr, new_string); } } else { B32 should_commit_asap = editing_complete; if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg) { should_commit_asap = 1; } else if(evt->slot != UI_EventActionSlot_Cancel) { should_commit_asap = editing_complete; } if(should_commit_asap) { B32 success = 0; success = rd_commit_eval_value_string(cell->eval, new_string); state_dirty = 1; if(!success) { log_user_error(str8_lit("Could not commit value successfully.")); } } } } } } } if(editing_complete) { ewv->text_editing = 0; } } ////////////////////////// //- rjf: [table] do cell-granularity copies // if(!ewv->text_editing && evt->flags & UI_EventFlag_Copy) { taken = 1; String8List strs = {0}; EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); EV_WindowedRowNode *row_node = rows.first; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row_node != 0; y += 1, row_node = row_node->next) { EV_Row *row = &row_node->row; RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); S64 cell_x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, cell_x += 1) { if(cell_x < selection_tbl.min.x || selection_tbl.max.x < cell_x) { continue; } RD_WatchRowCellInfo cell_info = rd_info_from_watch_row_cell(scratch.arena, row, string_flags, &row_info, cell, ui_top_font(), ui_top_font_size(), row_string_max_size_px); String8List cell_strings = {0}; str8_list_push(scratch.arena, &cell_strings, dr_string_from_fstrs(scratch.arena, &cell_info.expr_fstrs)); str8_list_push(scratch.arena, &cell_strings, dr_string_from_fstrs(scratch.arena, &cell_info.eval_fstrs)); String8 cell_string = str8_list_join(scratch.arena, &cell_strings, &(StringJoin){.sep = str8_lit(" ")}); cell_string = str8_skip_chop_whitespace(cell_string); U64 comma_pos = str8_find_needle(cell_string, 0, str8_lit(","), 0); if(selection_tbl.min.x != selection_tbl.max.x || selection_tbl.min.y != selection_tbl.max.y) { str8_list_pushf(scratch.arena, &strs, "%s%S%s%s", comma_pos < cell_string.size ? "\"" : "", cell_string, comma_pos < cell_string.size ? "\"" : "", cell_x+1 <= selection_tbl.max.x ? "," : ""); } else { str8_list_push(scratch.arena, &strs, cell_string); } } if(y+1 <= selection_tbl.max.y) { str8_list_push(scratch.arena, &strs, str8_lit("\n")); } } String8 string = str8_list_join(scratch.arena, &strs, 0); os_set_clipboard_text(string); } ////////////////////////// //- rjf: [table] do cell-granularity deletions // if(!ewv->text_editing && evt->flags & UI_EventFlag_Delete) { taken = 1; state_dirty = 1; snap_to_cursor = 1; CFG_NodePtrList cfgs_to_remove = {0}; RD_WatchPt next_cursor_pt = {0}; B32 next_cursor_set = 0; EV_WindowedRowList rows = ev_rows_from_num_range(scratch.arena, eval_view, &block_ranges, r1u64(selection_tbl.min.y, selection_tbl.max.y+1)); EV_WindowedRowNode *row_node = rows.first; for(S64 y = selection_tbl.min.y; row_node != 0 && y <= selection_tbl.max.y; y += 1, row_node = row_node->next) { EV_Row *row = &row_node->row; RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); S64 cell_x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, cell_x += 1) { if(cell_x < selection_tbl.min.x || selection_tbl.max.x < cell_x) { continue; } RD_WatchPt pt = {row->block->key, row->key, rd_id_from_watch_cell(cell)}; if(cell->flags & RD_WatchCellFlag_Expr && cell->flags & RD_WatchCellFlag_NoEval) { CFG_Node *cfg = row_info.group_cfg_child; if(cfg != &cfg_nil_node) { cfg_node_ptr_list_push(scratch.arena, &cfgs_to_remove, cfg); U64 deleted_num = ev_block_num_from_id(row->block, row->key.child_id); if(deleted_num != 0) { EV_Key parent_key = row->block->parent->key; EV_Key key = row->block->key; U64 fallback_id_prev = ev_block_id_from_num(row->block, deleted_num-1); U64 fallback_id_next = ev_block_id_from_num(row->block, deleted_num+1); if(fallback_id_next != 0) { parent_key = row->block->key; key = ev_key_make(row->key.parent_hash, fallback_id_next); } else if(fallback_id_prev != 0) { parent_key = row->block->key; key = ev_key_make(row->key.parent_hash, fallback_id_prev); } RD_WatchPt new_pt = {parent_key, key, pt.cell_id}; next_cursor_pt = new_pt; next_cursor_set = 1; state_dirty = 1; } } } else { rd_commit_eval_value_string(cell->eval, str8_zero()); } } } for(CFG_NodePtrNode *n = cfgs_to_remove.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, n->v); } if(next_cursor_set) { ewv->cursor = ewv->mark = ewv->next_cursor = ewv->next_mark = next_cursor_pt; } } ////////////////////////// //- rjf: [table] apply deltas to cursor & mark // if(!ewv->text_editing && !(evt->flags & UI_EventFlag_Delete) && !(evt->flags & UI_EventFlag_Reorder)) { B32 cursor_tbl_min_is_empty_selection[Axis2_COUNT] = {0, 1}; Vec2S32 delta = evt->delta_2s32; if(evt->flags & UI_EventFlag_PickSelectSide && !MemoryMatchStruct(&selection_tbl.min, &selection_tbl.max)) { if(delta.x > 0 || delta.y > 0) { cursor_tbl.x = selection_tbl.max.x; cursor_tbl.y = selection_tbl.max.y; } else if(delta.x < 0 || delta.y < 0) { cursor_tbl.x = selection_tbl.min.x; cursor_tbl.y = selection_tbl.min.y; } } if(evt->flags & UI_EventFlag_ZeroDeltaOnSelect && !MemoryMatchStruct(&selection_tbl.min, &selection_tbl.max)) { MemoryZeroStruct(&delta); } B32 moved = 1; switch(evt->delta_unit) { default:{moved = 0;}break; case UI_EventDeltaUnit_Char: { for EachEnumVal(Axis2, axis) { cursor_tbl.v[axis] += delta.v[axis]; if(cursor_tbl.v[axis] < cursor_tbl_range.min.v[axis]) { cursor_tbl.v[axis] = cursor_tbl_range.max.v[axis]; } if(cursor_tbl.v[axis] > cursor_tbl_range.max.v[axis]) { cursor_tbl.v[axis] = cursor_tbl_range.min.v[axis]; } cursor_tbl.v[axis] = clamp_1s64(r1s64(cursor_tbl_range.min.v[axis], cursor_tbl_range.max.v[axis]), cursor_tbl.v[axis]); } }break; case UI_EventDeltaUnit_Word: case UI_EventDeltaUnit_Line: case UI_EventDeltaUnit_Page: { cursor_tbl.x = (delta.x>0 ? (cursor_tbl_range.max.x) : delta.x<0 ? (cursor_tbl_range.min.x + !!cursor_tbl_min_is_empty_selection[Axis2_X]) : cursor_tbl.x); cursor_tbl.y += ((delta.y>0 ? +(num_possible_visible_rows-3) : delta.y<0 ? -(num_possible_visible_rows-3) : 0)); cursor_tbl.y = clamp_1s64(r1s64(cursor_tbl_range.min.y + !!cursor_tbl_min_is_empty_selection[Axis2_Y], cursor_tbl_range.max.y), cursor_tbl.y); }break; case UI_EventDeltaUnit_Whole: { for EachEnumVal(Axis2, axis) { cursor_tbl.v[axis] = (delta.v[0]>0 ? cursor_tbl_range.max.v[axis] : delta.v[0]<0 ? cursor_tbl_range.min.v[axis] + !!cursor_tbl_min_is_empty_selection[axis] : cursor_tbl.v[axis]); } }break; } if(moved) { taken = 1; cursor_dirty__tbl = 1; snap_to_cursor = 1; } } ////////////////////////// //- rjf: [table] stick table mark to cursor if needed // if(!ewv->text_editing) { if(taken && !(evt->flags & UI_EventFlag_KeepMark)) { mark_tbl = cursor_tbl; } } ////////////////////////// //- rjf: [table] do cell-granularity reorders // if(!ewv->text_editing && evt->flags & UI_EventFlag_Reorder) { taken = 1; if(filter.size == 0) { // rjf: determine blocks of each endpoint of the table selection EV_Block *selection_endpoint_blocks[2] = { ev_block_range_from_num(&block_ranges, selection_tbl.min.y).block, ev_block_range_from_num(&block_ranges, selection_tbl.max.y).block, }; // rjf: pick shallowest block within which we can do reordering U64 selection_depths[2] = { ev_depth_from_block(selection_endpoint_blocks[0]), ev_depth_from_block(selection_endpoint_blocks[1]), }; EV_Block *selection_block = (selection_depths[1] < selection_depths[0] ? selection_endpoint_blocks[1] : selection_endpoint_blocks[0]); // rjf: find selection keys within the block in which we are doing reordering EV_Key selection_keys_in_block[2] = {0}; { for EachElement(idx, selection_endpoint_blocks) { EV_Block *endpoint_block = selection_endpoint_blocks[idx]; if(endpoint_block == selection_block) { selection_keys_in_block[idx] = ev_key_from_num(&block_ranges, selection_tbl.v[idx].y); } else { for(;endpoint_block->parent != selection_block && endpoint_block != &ev_nil_block;) { endpoint_block = endpoint_block->parent; } if(endpoint_block->parent == selection_block) { selection_keys_in_block[idx] = endpoint_block->key; } } } EV_Key fallback_key = {0}; for EachElement(idx, selection_endpoint_blocks) { if(!ev_key_match(selection_keys_in_block[idx], ev_key_zero())) { fallback_key = selection_keys_in_block[idx]; } } for EachElement(idx, selection_endpoint_blocks) { if(ev_key_match(selection_keys_in_block[idx], ev_key_zero())) { selection_keys_in_block[idx] = fallback_key; } } } // rjf: determine collection info for the block String8 group_cfg_name = {0}; { E_IRTreeAndType block_irtree = selection_block->eval.irtree; E_TypeKey block_type_key = e_type_key_unwrap(block_irtree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind block_type_kind = e_type_kind_from_key(block_type_key); if(block_type_kind == E_TypeKind_Set) { E_Type *block_type = e_type_from_key(block_type_key); group_cfg_name = rd_singular_from_code_name_plural(block_type->name); if(group_cfg_name.size == 0) { group_cfg_name = block_type->name; } } } // rjf: map selection endpoints to cfgs CFG_Node *first_cfg = &cfg_nil_node; CFG_Node *last_cfg = &cfg_nil_node; if(group_cfg_name.size != 0) { first_cfg = cfg_node_from_id(selection_keys_in_block[0].child_id); last_cfg = cfg_node_from_id(selection_keys_in_block[1].child_id); } // rjf: reorder if(first_cfg != &cfg_nil_node && last_cfg != &cfg_nil_node) { CFG_Node *first_cfg_prev = &cfg_nil_node; CFG_Node *last_cfg_next = &cfg_nil_node; for(CFG_Node *prev = first_cfg->prev; prev != &cfg_nil_node; prev = prev->prev) { if(str8_match(prev->string, first_cfg->string, 0)) { first_cfg_prev = prev; break; } } for(CFG_Node *next = last_cfg->next; next != &cfg_nil_node; next = next->next) { if(str8_match(next->string, last_cfg->string, 0)) { last_cfg_next = next; break; } } if(evt->delta_2s32.y < 0 && first_cfg != &cfg_nil_node && first_cfg_prev != &cfg_nil_node) { state_dirty = 1; snap_to_cursor = 1; CFG_Node *parent = first_cfg_prev->parent; cfg_node_unhook(rd_state->cfg, parent, first_cfg_prev); cfg_node_insert_child(rd_state->cfg, parent, last_cfg, first_cfg_prev); } if(evt->delta_2s32.y > 0 && last_cfg != &cfg_nil_node && last_cfg_next != &cfg_nil_node) { state_dirty = 1; snap_to_cursor = 1; CFG_Node *parent = last_cfg_next->parent; cfg_node_unhook(rd_state->cfg, parent, last_cfg_next); cfg_node_insert_child(rd_state->cfg, parent, first_cfg_prev, last_cfg_next); } } } } ////////////////////////// //- rjf: consume event, if taken // if(taken && evt != &dummy_evt) { ui_eat_event(evt); } } } ////////////////////////////// //- rjf: autocomplete watches -> feed autocompletion info forward // if(rd_watch_pt_match(ewv->cursor, ewv->mark) && cfg_node_child_from_string(view, str8_lit("autocomplete")) != &cfg_nil_node) { U64 row_num = ev_num_from_key(&block_ranges, ewv->cursor.key); EV_Row *row = ev_row_from_num(scratch.arena, rd_view_eval_view(), &block_ranges, row_num); RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); RD_WatchCell *cell = row_info.cells.first; if(cell != 0) { RD_WatchRowCellInfo cell_info = rd_info_from_watch_row_cell(scratch.arena, row, 0, &row_info, cell, ui_top_font(), ui_top_font_size(), dim_2f32(rect).y); String8 string = dr_string_from_fstrs(ui_build_arena(), &cell_info.eval_fstrs); if(string.size != 0) { ui_set_autocomplete_string(string); } } } ////////////////////////////// //- rjf: build ui // B32 pressed = 0; ProfScope("build ui") { Vec2F32 rect_dim = dim_2f32(rect); F32 contents_width_px = (rect_dim.x - floor_f32(ui_bottom_font_size()*1.5f)); Rng1S64 visible_row_rng = {0}; UI_ScrollListParams scroll_list_params = {0}; { scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = row_height_px; scroll_list_params.dim_px = rect_dim; scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, 0)); scroll_list_params.item_range = r1s64(0, block_tree.total_row_count - !!implicit_root); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; scroll_list_params.row_blocks = row_blocks; } UI_BoxFlags disabled_flags = ui_top_flags(); if(d_ctrl_targets_running()) { disabled_flags |= UI_BoxFlag_Disabled; } UI_ScrollListSignal scroll_list_sig = {0}; UI_Focus(UI_FocusKind_On) UI_ScrollList(&scroll_list_params, &scroll_pos.y, 0, 0, &visible_row_rng, &scroll_list_sig) UI_Focus(UI_FocusKind_Null) { ui_set_next_pref_height(ui_children_sum(1)); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *table = ui_build_box_from_string(0, str8_lit("table")); UI_Parent(table) { Vec2F32 scroll_list_view_off_px = ui_top_parent()->parent->view_off; //////////////////////// //- rjf: viz blocks -> rows // EV_WindowedRowList rows = {0}; { rows = ev_windowed_row_list_from_block_range_list(scratch.arena, eval_view, &block_ranges, r1u64(visible_row_rng.min+1, visible_row_rng.max+2)); } //////////////////////// //- rjf: rows -> row infos // RD_WatchRowInfo *row_infos = push_array(scratch.arena, RD_WatchRowInfo, rows.count); { U64 idx = 0; for(EV_WindowedRowNode *row_node = rows.first; row_node != 0; row_node = row_node->next, idx += 1) { EV_Row *row = &row_node->row; row_infos[idx] = rd_watch_row_info_from_row(scratch.arena, row); } } //////////////////////// //- rjf: build boundaries // B32 cell_pcts_are_dirty = 0; ProfScope("build boundaries") { U64 idx = 0; U64 boundary_start_idx = 0; EV_Row *last_row = 0; RD_WatchRowInfo *last_row_info = 0; for(EV_WindowedRowNode *row_node = rows.first;; row_node = row_node->next, idx += 1) { //- rjf: determine if this row breaks the topology B32 is_new_topology = (row_node == 0); if(row_node != 0 && last_row_info != 0) { EV_Row *row = &row_node->row; RD_WatchRowInfo *row_info = &row_infos[idx]; for(RD_WatchCell *last_cell = last_row_info->cells.first, *this_cell = row_info->cells.first;; last_cell = last_cell->next, this_cell = this_cell->next) { if(last_cell == 0 && this_cell == 0) { break; } if((last_cell == 0 && this_cell != 0) || (last_cell != 0 && this_cell == 0)) { is_new_topology = 1; break; } if(rd_id_from_watch_cell(last_cell) != rd_id_from_watch_cell(this_cell)) { is_new_topology = 1; break; } } } //- rjf: if we reached a new topology, or the end -> build boundaries for all cell separations if(is_new_topology) { EV_Row *row = last_row; RD_WatchRowInfo *row_info = last_row_info; F32 row_width_px = contents_width_px; if(row_info != 0) { U64 row_hash = ev_hash_from_key(row->key); F32 cell_x_px = 0; U64 cell_idx = 0; for(RD_WatchCell *cell = row_info->cells.first; cell != 0 && cell->next != 0; cell = cell->next, cell_idx += 1) { if(cell->pct == 0 || cell->next->pct == 0) { continue; } U64 cell_id = rd_id_from_watch_cell(cell); F32 cell_width_px = cell->px + cell->pct * row_width_px; F32 next_cell_x_px = cell_x_px + cell_width_px; { Rng2F32 rect = r2f32p(next_cell_x_px - ui_top_font_size()*0.4f, boundary_start_idx*row_height_px, next_cell_x_px + ui_top_font_size()*0.4f, idx*row_height_px); UI_Rect(rect) UI_HoverCursor(OS_Cursor_LeftRight) { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Floating, "boundary_%I64x_%I64x", row_hash, cell_id); UI_Signal sig = ui_signal_from_box(box); if(ui_dragging(sig)) { typedef struct DragData DragData; struct DragData { F32 min_pct; F32 max_pct; }; if(ui_pressed(sig)) { DragData drag_data = {cell->pct, cell->next->pct}; ui_store_drag_struct(&drag_data); } DragData *drag_data = ui_get_drag_struct(DragData); F32 min_pct__pre = drag_data->min_pct; F32 max_pct__pre = drag_data->max_pct; F32 min_px__pre = min_pct__pre*row_width_px; F32 max_px__pre = max_pct__pre*row_width_px; F32 min_px__post = min_px__pre + ui_drag_delta().x; F32 max_px__post = max_px__pre - ui_drag_delta().x; F32 min_pct__post = min_px__post/row_width_px; F32 max_pct__post = max_px__post/row_width_px; if(min_pct__post < 0.05f) { min_pct__post = 0.05f; max_pct__post = (min_pct__pre + max_pct__pre) - min_pct__post; } if(max_pct__post < 0.05f) { max_pct__post = 0.05f; min_pct__post = (min_pct__pre + max_pct__pre) - max_pct__post; } if(ui_double_clicked(sig)) { F32 default_sum = cell->default_pct + cell->next->default_pct; F32 current_sum = min_pct__pre + max_pct__pre;; min_pct__post = current_sum * (cell->default_pct / default_sum); max_pct__post = current_sum * (cell->next->default_pct / default_sum); ui_kill_action(); } CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *style = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, row_info->cell_style_key); CFG_Node *min_cfg = &cfg_nil_node; CFG_Node *max_cfg = &cfg_nil_node; { CFG_Node *pct_child = style->first; U64 c_idx = 0; for(RD_WatchCell *c = row_info->cells.first; c != 0; c = c->next, c_idx += 1) { if(pct_child == &cfg_nil_node) { pct_child = cfg_node_newf(rd_state->cfg, style, "%f", c->pct); } if(c_idx == cell_idx) { min_cfg = pct_child; } if(c_idx == cell_idx+1) { max_cfg = pct_child; } pct_child = pct_child->next; } cfg_node_equip_stringf(rd_state->cfg, min_cfg, "%f", min_pct__post); cfg_node_equip_stringf(rd_state->cfg, max_cfg, "%f", max_pct__post); cell_pcts_are_dirty = 1; } } } } cell_x_px = next_cell_x_px; } } boundary_start_idx = idx; } //- rjf: advance if(row_node == 0) { break; } else { last_row = &row_node->row; last_row_info = &row_infos[idx]; } } } //////////////////////// //- rjf: if cell widths are dirty -> recompute row infos // if(cell_pcts_are_dirty) { U64 idx = 0; for(EV_WindowedRowNode *row_node = rows.first; row_node != 0; row_node = row_node->next, idx += 1) { EV_Row *row = &row_node->row; row_infos[idx] = rd_watch_row_info_from_row(scratch.arena, row); } } //////////////////////// //- rjf: do drag/drops // if(rd_drag_is_active()) { Vec2F32 rect_dim = dim_2f32(rect); ui_set_next_rect(r2f32p(0, 0, rect_dim.x, rect_dim.y)); UI_Box *drop_target = ui_build_box_from_stringf(UI_BoxFlag_DropSite|UI_BoxFlag_Floating, "watch_%I64x_drop", rd_regs()->view); UI_Signal sig = ui_signal_from_box(drop_target); if(ui_key_match(ui_drop_hot_key(), drop_target->key)) { Vec2F32 drag_pos = sub_2f32(ui_mouse(), rect.p0); RD_RegSlot drag_slot = rd_state->drag_drop_regs_slot; RD_Regs *drag_regs = rd_state->drag_drop_regs; //- rjf: obtain best fit for target block & prev-row for this drag EV_Block *drag_block = &ev_nil_block; U64 best_prev_row_block_num = 0; F32 best_prev_row_y = 0; { F32 best_prev_row_distance = inf32(); U64 local_row_idx = 0; F32 row_y = 0; for(EV_WindowedRowNode *row_node = rows.first; row_node != 0; row_node = row_node->next, local_row_idx += 1) { // rjf: unpack row EV_Row *row = &row_node->row; F32 row_height = row_height_px*row->visual_size; RD_WatchRowInfo *row_info = &row_infos[local_row_idx]; E_Type *block_type = e_type_from_key(row->block->eval.irtree.type_key); // rjf: determine if this row's block is good for the current drag/drop B32 block_is_good_for_drop = 0; if(drag_slot == RD_RegSlot_Expr && block_type->expand.id_from_num == E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(watches)) { block_is_good_for_drop = (drag_regs->cfg == 0 || (drag_regs->cfg != row_info->group_cfg_child->id)); } // rjf: if this block is good, then test this row/block & grab if appropriate if(block_is_good_for_drop) { if(drag_block == &ev_nil_block && row_y <= drag_pos.y && drag_pos.y <= row_y + row_height) { drag_block = row->block; } F32 row_distance = abs_f32(drag_pos.y - row_y); if(row_distance <= best_prev_row_distance) { U64 row_num = ev_block_num_from_id(row->block, row->key.child_id); best_prev_row_block_num = row_num-1; best_prev_row_distance = row_distance; best_prev_row_y = row_y; drag_block = row->block; } } row_y += row_height; } } //- rjf: unpack block/previous row info B32 drag_target_is_good = 0; CFG_Node *drag_parent_cfg = &cfg_nil_node; CFG_Node *drag_prev_cfg = &cfg_nil_node; if(drag_block != &ev_nil_block) { EV_Key prev_row_key = ev_key_make(ev_hash_from_key(drag_block->key), ev_block_id_from_num(drag_block, best_prev_row_block_num)); U64 prev_row_num = ev_num_from_key(&block_ranges, prev_row_key); EV_Row *prev_row = ev_row_from_num(scratch.arena, eval_view, &block_ranges, prev_row_num); RD_WatchRowInfo prev_row_info = rd_watch_row_info_from_row(scratch.arena, prev_row); drag_parent_cfg = rd_cfg_from_eval_space(drag_block->eval.space); drag_prev_cfg = prev_row_info.group_cfg_child; if(drag_regs->cfg == 0 || drag_prev_cfg->id != drag_regs->cfg) { drag_target_is_good = 1; } } //- rjf: drop if(drag_target_is_good && rd_drag_drop() && drag_parent_cfg != &cfg_nil_node) { switch(drag_slot) { default:{}break; case RD_RegSlot_Expr: { CFG_Node *cfg = cfg_node_from_id(drag_regs->cfg); if(cfg != &cfg_nil_node) { cfg_node_unhook(rd_state->cfg, cfg->parent, cfg); } if(cfg == &cfg_nil_node) { cfg = cfg_node_alloc(rd_state->cfg); cfg_node_equip_stringf(rd_state->cfg, cfg, "watch"); cfg_node_new(rd_state->cfg, cfg, drag_regs->expr); } cfg_node_insert_child(rd_state->cfg, drag_parent_cfg, drag_prev_cfg, cfg); }break; } } //- rjf: draw drop position if(drag_target_is_good) { DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) UI_TagF("pop") { Vec4F32 color = ui_color_from_name(str8_lit("background")); Rng2F32 drop_line_rect = r2f32p(rect.x0, rect.y0 + best_prev_row_y - ui_top_font_size()*0.5f, rect.x1, rect.y0 + best_prev_row_y + ui_top_font_size()*0.5f); R_Rect2DInst *inst = dr_rect(drop_line_rect, color, 0, 0, 1.f); inst->colors[Corner_10] = inst->colors[Corner_11] = v4f32(color.x, color.y, color.z, 0); } ui_box_equip_draw_bucket(drop_target, bucket); } } } //////////////////////// //- rjf: build table // ProfScope("build table") { UI_Key watch_rich_hover_key = ui_key_from_string(ui_active_seed_key(), str8_lit("###rich_hover")); F32 row_y_px = rect.y0; U64 local_row_idx = 0; U64 global_row_idx = rows.count_before_semantic; RD_WatchRowInfo last_row_info = {0}; for(EV_WindowedRowNode *row_node = rows.first; row_node != 0; (row_y_px += row_height_px * (row_node->row.visual_size), row_node = row_node->next, global_row_idx += 1, local_row_idx += 1)) { //////////////////////// //- rjf: unpack row info // ProfBegin("unpack row info"); EV_Row *row = &row_node->row; RD_WatchRowInfo *row_info = &row_infos[local_row_idx]; U64 row_hash = ev_hash_from_key(row->key); U64 row_depth = ev_depth_from_block(row->block); B32 row_selected = (selection_tbl.min.y <= global_row_idx+1 && global_row_idx+1 <= selection_tbl.max.y); B32 row_expanded = ev_expansion_from_key(eval_view, row->key); B32 next_row_expanded = row_expanded; B32 row_is_expandable = row_info->can_expand; if(implicit_root && row_depth > 0) { row_depth -= 1; } ProfEnd(); //////////////////////// //- rjf: determine if this row fits the last row's topology // B32 row_matches_last_row_topology = 1; if(row_node != rows.first) { for(RD_WatchCell *last_cell = last_row_info.cells.first, *this_cell = row_info->cells.first;; last_cell = last_cell->next, this_cell = this_cell->next) { if(last_cell == 0 && this_cell == 0) { break; } if((last_cell == 0 && this_cell != 0) || (last_cell != 0 && this_cell == 0)) { row_matches_last_row_topology = 0; break; } if(rd_id_from_watch_cell(last_cell) != rd_id_from_watch_cell(this_cell)) { row_matches_last_row_topology = 0; break; } } } //////////////////////// //- rjf: store last row's info, for next iteration // last_row_info = *row_info; //////////////////////// //- rjf: determine row's flags & color palette // ProfBegin("determine row's flags & color palette"); UI_BoxFlags row_flags = UI_BoxFlag_DisableFocusOverlay; { if(global_row_idx & 1) { ui_set_next_tag(str8_lit("alt")); row_flags |= UI_BoxFlag_DrawBackground; } if(!row_matches_last_row_topology) { row_flags |= UI_BoxFlag_DrawSideTop; } } ProfEnd(); //////////////////////// //- rjf: build row box // ui_set_next_flags(disabled_flags); ui_set_next_pref_width(ui_px(contents_width_px, 1.f)); ui_set_next_pref_height(ui_px(row_height_px*row->visual_size, 1.f)); ui_set_next_focus_hot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off); UI_Box *row_box = ui_build_box_from_stringf(row_flags|((!row_node->next)*UI_BoxFlag_DrawSideBottom)|UI_BoxFlag_Clickable, "row_%I64x", row_hash); RD_WatchRowExtrasDrawData *row_draw_data = push_array(ui_build_arena(), RD_WatchRowExtrasDrawData, 1); row_draw_data->breaks_from_prev = !row_matches_last_row_topology; ui_box_equip_custom_draw(row_box, rd_watch_row_extras_custom_draw, row_draw_data); ////////////////////// //- rjf: build row contents // RD_RegsScope(.module = row_info->module->handle) UI_Parent(row_box) { //////////////////// //- rjf: draw start of cache lines in expansions // if(row->eval.space.kind == CTRL_EvalSpaceKind_Entity && row_info->view_ui_rule == &rd_nil_view_ui_rule) { CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row->eval.space); if(space_entity->kind == CTRL_EntityKind_Process) { U64 row_offset = row->eval.value.u64; if((row->eval.irtree.mode == E_Mode_Offset || row->eval.irtree.mode == E_Mode_Null) && row_offset%64 == 0 && row_depth > 0) { ui_set_next_fixed_x(0); ui_set_next_fixed_y(0); ui_set_next_fixed_height(ui_top_font_size()*0.2f); ui_set_next_tag(str8_lit("pop")); ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawBackground, ui_key_zero()); } } } ////////////// //- rjf: draw mid-row cache line boundaries in expansions // if(row->eval.space.kind == CTRL_EvalSpaceKind_Entity && row_info->view_ui_rule == &rd_nil_view_ui_rule) { CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row->eval.space); if(space_entity->kind == CTRL_EntityKind_Process && (row->eval.irtree.mode == E_Mode_Offset || row->eval.irtree.mode == E_Mode_Null) && row->eval.value.u64%64 != 0 && row_depth > 0 && !row_expanded) { U64 next_off = (row->eval.value.u64 + e_type_byte_size_from_key(row->eval.irtree.type_key)); if(next_off%64 != 0 && row->eval.value.u64/64 < next_off/64) { ui_set_next_fixed_x(0); ui_set_next_fixed_y(row_height_px - ui_top_font_size()*0.5f); ui_set_next_fixed_height(ui_top_font_size()*1.f); ui_set_next_tag(str8_lit("pop")); ui_set_next_transparency(0.5f); ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawBackground, ui_key_zero()); } } } ////////////// //- rjf: build all cells // S64 cell_x = 0; F32 cell_x_px = 0; for(RD_WatchCell *cell = row_info->cells.first; cell != 0; cell = cell->next, cell_x += 1) { if(row_depth > 0) { ui_push_tagf("weak"); } //////////// //- rjf: unpack cell info // F32 cell_width_px = cell->px + cell->pct * (dim_2f32(rect).x - floor_f32(ui_top_font_size()*1.5f)); F32 next_cell_x_px = cell_x_px + cell_width_px; F32 cell_width_strictness = 0.f; if(cell->px != 0) { cell_width_strictness = 1.f; } F32 visual_row_string_max_size_px = cell_width_px * 1.5f; if(cell->flags & RD_WatchCellFlag_Expr && !(cell->flags & RD_WatchCellFlag_NoEval)) { visual_row_string_max_size_px /= 2.f; } U64 cell_id = rd_id_from_watch_cell(cell); RD_WatchPt cell_pt = {row->block->key, row->key, cell_id}; RD_WatchViewTextEditState *cell_edit_state = rd_watch_view_text_edit_state_from_pt(ewv, cell_pt); B32 cell_selected = (row_selected && selection_tbl.min.x <= cell_x && cell_x <= selection_tbl.max.x); RD_WatchRowCellInfo cell_info = rd_info_from_watch_row_cell(scratch.arena, row, string_flags, row_info, cell, ui_top_font(), ui_top_font_size(), visual_row_string_max_size_px); E_TypeKey cell_type_key = cell->eval.irtree.type_key; E_Type *cell_type = e_type_from_key(cell_type_key); E_Eval cell_value_eval = e_value_eval_from_eval(cell->eval); B32 cell_toggled = (cell_value_eval.value.u64 != 0); B32 next_cell_toggled = cell_toggled; //////////////////////// //- rjf: determine if cell evaluation's data is fresh and/or bad // ProfBegin("determine if cell evaluation's data is fresh and/or bad"); B32 cell_is_rich_hovered = 0; B32 cell_is_fresh = 0; B32 cell_is_bad = 0; U64 cell_vaddr_rng_size = e_type_byte_size_from_key(cell->eval.irtree.type_key); cell_vaddr_rng_size = Min(cell_vaddr_rng_size, 64); Rng1U64 cell_vaddr_rng = r1u64(cell->eval.value.u64, cell->eval.value.u64+cell_vaddr_rng_size); if(!(cell_info.flags & RD_WatchCellFlag_NoEval)) { switch(cell->eval.irtree.mode) { default:{}break; case E_Mode_Offset: { if(rd_state->hover_regs_slot == RD_RegSlot_VaddrRange && e_space_match(cell->eval.space, rd_get_hover_regs()->eval_space) && !ui_key_match(rd_get_hover_regs()->src_ui_key, watch_rich_hover_key)) { Rng1U64 intersection = intersect_1u64(cell_vaddr_rng, rd_get_hover_regs()->vaddr_range); cell_is_rich_hovered = (intersection.max > intersection.min); } CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(cell->eval.space); if(cell->eval.space.kind == CTRL_EvalSpaceKind_Entity && space_entity->kind == CTRL_EntityKind_Process) { CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, space_entity->handle, cell_vaddr_rng, 0, rd_state->frame_eval_memread_endt_us); for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) { if(slice.byte_changed_flags[idx] != 0) { cell_is_fresh = 1; } if(slice.byte_bad_flags[idx] != 0) { cell_is_bad = 1; } } } }break; } } ProfEnd(); //////////// //- rjf: compute slider parameters // E_Value cell_slider_min = zero_struct; E_Value cell_slider_max = zero_struct; E_TypeKind slider_value_type_kind = E_TypeKind_Null; F32 cell_slider_value = 0.f; if(str8_match(cell_type->name, str8_lit("range1"), 0) && cell_type->args != 0 && cell_type->count >= 2) { E_Key min_key = e_key_from_expr(cell_type->args[0]); E_Key max_key = e_key_from_expr(cell_type->args[1]); E_ParentKey(cell->eval.key) { E_TypeKey slider_value_type = e_type_key_unwrap(cell_type->direct_type_key, E_TypeUnwrapFlag_AllDecorative); slider_value_type_kind = e_type_kind_from_key(slider_value_type); String8 slider_type_name = e_type_string_from_key(scratch.arena, slider_value_type); cell_slider_min = e_value_from_key(e_key_wrapf(min_key, "(%S)$", slider_type_name)); cell_slider_max = e_value_from_key(e_key_wrapf(max_key, "(%S)$", slider_type_name)); } } switch(slider_value_type_kind) { default: if(e_type_kind_is_integer(slider_value_type_kind)) { cell_slider_value = ((F32)(cell_value_eval.value.s64 - cell_slider_min.s64)) / (cell_slider_max.s64 - cell_slider_min.s64); }break; case E_TypeKind_F32: { cell_slider_value = (cell_value_eval.value.f32 - cell_slider_min.f32) / (cell_slider_max.f32 - cell_slider_min.f32); }break; case E_TypeKind_F64: { cell_slider_value = (F32)((cell_value_eval.value.f64 - cell_slider_min.f64) / (cell_slider_max.f64 - cell_slider_min.f64)); }break; } F32 next_cell_slider_value = cell_slider_value; //////////// //- rjf: determine cell's palette // Vec4F32 cell_background_color_override = {0}; { if(cell_info.cfg->id == rd_get_hover_regs()->cfg && rd_state->hover_regs_slot == RD_RegSlot_Cfg) { CFG_Node *cfg = cell_info.cfg; Vec4F32 rgba = rd_color_from_cfg(cfg); rgba.w *= 0.05f; if(rgba.w == 0) { rgba = pop_background_rgba; rgba.w *= 0.5f; } rgba.w *= ui_anim(ui_key_from_stringf(ui_key_zero(), "###cfg_hover_t_%p", cfg), 1.f, .rate = entity_hover_t_rate); cell_background_color_override = rgba; } else if(ctrl_handle_match(cell_info.entity->handle, rd_get_hover_regs()->ctrl_entity) && rd_state->hover_regs_slot == RD_RegSlot_CtrlEntity) { CTRL_Entity *entity = cell_info.entity; Vec4F32 rgba = rd_color_from_ctrl_entity(entity); rgba.w *= 0.05f; if(rgba.w == 0) { rgba = pop_background_rgba; rgba.w *= 0.5f; } rgba.w *= ui_anim(ui_key_from_stringf(ui_key_zero(), "###entity_hover_t_%p", entity), 1.f, .rate = entity_hover_t_rate); cell_background_color_override = rgba; } else if(cell_is_rich_hovered) { UI_TagF(".") UI_TagF("pop") { cell_background_color_override = ui_color_from_name(str8_lit("background")); } } else if(cell_is_fresh) { UI_TagF(".") UI_TagF("fresh") { cell_background_color_override = ui_color_from_name(str8_lit("background")); } } else if(cell_is_bad) { UI_TagF(".") UI_TagF("bad_pop") { cell_background_color_override = ui_color_from_name(str8_lit("background")); cell_background_color_override.w *= 0.2f; } } } //////////// //- rjf: build cell container // UI_Box *cell_box = &ui_nil_box; UI_PrefWidth(ui_px(cell_width_px, cell_width_strictness)) { ui_set_next_fixed_height(floor_f32(row->visual_size * row_height_px)); cell_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideLeft, "cell_%I64x_%I64x", row_hash, cell_id); } //////////// //- rjf: build cell contents // CFG_Node *cell_view = &cfg_nil_node; B32 revert_cell = 0; UI_Signal sig = {0}; ProfScope("build cell contents") UI_Parent(cell_box) UI_FocusHot(cell_selected ? UI_FocusKind_On : UI_FocusKind_Off) UI_FocusActive((cell_selected && ewv->text_editing) ? UI_FocusKind_On : UI_FocusKind_Off) RD_Font(RD_FontSlot_Code) UI_TagF("weak") { //- rjf: cell has hook? -> build ui by calling hook if(cell->kind == RD_WatchCellKind_ViewUI && cell_info.view_ui_rule != &rd_nil_view_ui_rule) { CFG_Node *root = rd_immediate_cfg_from_keyf("view%I64x_%I64x", rd_regs()->view, row_hash); cell_view = rd_view_from_eval(root, cell->eval); Rng2F32 cell_rect = r2f32p(cell_x_px, row_y_px, next_cell_x_px, row_y_px + row_height_px*(row_node->visual_size_skipped + row->visual_size + row_node->visual_size_chopped)); ui_set_next_fixed_y(-1.f * (row_node->visual_size_skipped) * row_height_px); ui_set_next_fixed_height((row_node->visual_size_skipped + row->visual_size + row_node->visual_size_chopped) * row_height_px); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable|UI_BoxFlag_FloatingY, "###val_%I64x", row_hash); UI_Parent(box) RD_RegsScope(.view = cell_view->id, .file_path = rd_file_path_from_eval(scratch.arena, cell->eval)) UI_PermissionFlags(UI_PermissionFlag_Clicks|UI_PermissionFlag_ScrollX) UI_Flags(0) { // rjf: 'pull out' button UI_Signal pull_out_sig = {0}; UI_TagF(".") UI_TagF("tab") UI_Rect(r2f32p(floor_f32(ui_top_font_size()*1.5f), floor_f32(ui_top_font_size()*1.5f), floor_f32(ui_top_font_size()*1.5f + ui_top_font_size()*3.f), floor_f32(ui_top_font_size()*1.5f + ui_top_font_size()*3.f))) UI_CornerRadius(floor_f32(ui_top_font_size()*1.5f)) UI_TextAlignment(UI_TextAlign_Center) RD_Font(RD_FontSlot_Icons) UI_FontSize(floor_f32(ui_top_font_size()*0.9f)) { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_Floating| UI_BoxFlag_DrawText| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_DrawHotEffects, "%S###pull_out", rd_icon_kind_text_table[RD_IconKind_Window]); pull_out_sig = ui_signal_from_box(box); } if(ui_hovering(pull_out_sig)) UI_Tooltip RD_Font(RD_FontSlot_Main) { ui_state->tooltip_anchor_key = pull_out_sig.box->key; ui_labelf("Pull Out As New Tab"); } if(ui_dragging(pull_out_sig) && !contains_2f32(pull_out_sig.box->rect, ui_mouse())) { rd_drag_begin(RD_RegSlot_View); } // rjf: loading animation container UI_Box *loading_overlay_container = &ui_nil_box; UI_Parent(box) UI_WidthFill UI_HeightFill { loading_overlay_container = ui_build_box_from_key(UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, ui_key_zero()); } // rjf: view ui contents E_ParentKey(cell->eval.key) { cell_info.view_ui_rule->ui(cell->eval, cell_rect); } // rjf: loading fill UI_Parent(loading_overlay_container) { RD_ViewState *vs = rd_view_state_from_cfg(cell_view); rd_loading_overlay(cell_rect, vs->loading_t, vs->loading_progress_v, vs->loading_progress_v_target); } } sig = ui_signal_from_box(box); } //- rjf: cell is call stack frame? -> build arrow if this is the selected frame, otherwise leave empty else if(cell->kind == RD_WatchCellKind_CallStackFrame) { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%I64x_%I64x", cell_id, row_hash); sig = ui_signal_from_box(box); if(ctrl_handle_match(row_info->callstack_thread->handle, rd_base_regs()->thread) && row_info->callstack_unwind_index == rd_base_regs()->unwind_count && row_info->callstack_inline_depth == rd_base_regs()->inline_depth) { UI_Parent(box) UI_Flags(0) UI_TextAlignment(UI_TextAlign_Center) { Vec4F32 color = rd_color_from_ctrl_entity(row_info->callstack_thread); RD_Font(RD_FontSlot_Icons) UI_Flags(UI_BoxFlag_DisableTextTrunc) UI_TextColor(color) ui_label(rd_icon_kind_text_table[RD_IconKind_RightArrow]); } } } //- rjf: build general cell else { // rjf: compute visual params ProfBegin("compute visual params"); B32 cell_has_fancy_editors = (!(cell->flags & RD_WatchCellFlag_NoEval)); B32 is_button = !!(cell_info.flags & RD_WatchCellFlag_Button); B32 has_background = !!(cell_info.flags & RD_WatchCellFlag_Background); B32 is_toggle_switch = (cell_has_fancy_editors && cell->eval.irtree.mode != E_Mode_Null && e_type_kind_from_key(e_type_key_unwrap(cell->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)) == E_TypeKind_Bool); B32 is_slider = (cell_has_fancy_editors && cell->eval.irtree.mode != E_Mode_Null && cell_type->kind == E_TypeKind_Lens && str8_match(cell_type->name, str8_lit("range1"), 0)); B32 is_activated_on_single_click = !!(cell_info.flags & RD_WatchCellFlag_ActivateWithSingleClick); B32 is_non_code = !!(cell_info.flags & RD_WatchCellFlag_IsNonCode); String8 ghost_text = {0}; if(cell_selected && ewv->text_editing && cell->flags & RD_WatchCellFlag_Expr && cell->flags & RD_WatchCellFlag_NoEval) { is_non_code = 0; is_button = 0; is_activated_on_single_click = 0; } ProfEnd(); // rjf: determine query needle String8 needle = rd_view_query_input(); if(cell->eval.space.kind == E_SpaceKind_FileSystem) { needle = str8_skip_last_slash(needle); } // rjf: form cell build parameters UI_Key line_edit_key = {0}; RD_CellParams cell_params = {0}; ProfScope("form cell build parameters") { E_Type *block_type = e_type_from_key(row->block->eval.irtree.type_key); B32 cells_are_editable = !!(block_type->flags & E_TypeFlag_EditableChildren); // rjf: set up base parameters cell_params.flags = (RD_CellFlag_KeyboardClickable|RD_CellFlag_NoBackground|RD_CellFlag_CodeContents); cell_params.depth = (cell->flags & RD_WatchCellFlag_Indented ? row_depth : 0); cell_params.cursor = &cell_edit_state->cursor; cell_params.mark = &cell_edit_state->mark; cell_params.edit_buffer = cell_edit_state->input_buffer; cell_params.edit_buffer_size = sizeof(cell_edit_state->input_buffer); cell_params.edit_string_size_out = &cell_edit_state->input_size; cell_params.line_edit_key_out = &line_edit_key; cell_params.expanded_out = &next_row_expanded; cell_params.search_needle = needle; cell_params.meta_fstrs = cell_info.expr_fstrs; cell_params.value_fstrs = cell_info.eval_fstrs; if(row_height_px > ui_top_font_size()*3.5f) { cell_params.description = cell_info.description; } if(cell_selected && ewv->text_editing && cell->flags & RD_WatchCellFlag_NoEval) { MemoryZeroStruct(&cell_params.meta_fstrs); MemoryZeroStruct(&cell_params.description); } // rjf: extra edit button for meta-cfg strings if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg) { cell_params.flags |= RD_CellFlag_EmptyEditButton; } // rjf: extra revert button for non-default meta-cfgs if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg && !(cell->flags & RD_WatchCellFlag_NoEval)) { CFG_Node *cfg = rd_cfg_from_eval_space(cell->eval.space); String8 child_key = e_string_from_id(cell->eval.space.u64s[1]); CFG_Node *child_cfg = cfg_node_child_from_string(cfg, child_key); if(child_cfg != &cfg_nil_node) { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, cfg->string); if(schemas.count != 0) { MD_Node *child_schema = &md_nil_node; for(MD_NodePtrNode *n = schemas.first; md_node_is_nil(child_schema) && n != 0; n = n->next) { child_schema = md_child_from_string(n->v, child_key, 0); } if((md_node_has_tag(child_schema, str8_lit("override"), 0) || md_node_has_tag(child_schema, str8_lit("default"), 0)) && !md_node_has_tag(child_schema, str8_lit("no_revert"), 0)) { cell_params.flags |= RD_CellFlag_RevertButton; cell_params.revert_out = &revert_cell; } } } } // rjf: apply expander (or substitute space) if(!ewv->text_editing || !cell_selected || row_depth > 0) { if(row_is_expandable && cell == row_info->cells.first) { cell_params.flags |= RD_CellFlag_Expander; } else if(cells_are_editable && row_depth == !implicit_root && cell == row_info->cells.first) { cell_params.flags |= RD_CellFlag_ExpanderPlaceholder; } else if(row_depth != 0 && cell == row_info->cells.first) { cell_params.flags |= RD_CellFlag_ExpanderSpace; } } // rjf: apply blank cell ghost text if(row_info->cells.first == row_info->cells.last && cells_are_editable && row->eval.expr == &e_expr_nil) { ghost_text = str8_lit("Expression"); is_non_code = (!cell_selected || !ewv->text_editing); cell_params.flags &= ~(RD_CellFlag_Expander|RD_CellFlag_ExpanderSpace|RD_CellFlag_ExpanderPlaceholder); } // rjf: apply single-click-activation if(is_activated_on_single_click) { cell_params.flags |= RD_CellFlag_SingleClickActivate; } // rjf: apply code styles if(is_non_code) { cell_params.flags &= ~RD_CellFlag_CodeContents; } // rjf: apply button styles if(is_button) { cell_params.flags |= RD_CellFlag_Button; cell_params.flags &= ~RD_CellFlag_NoBackground; if(row_depth == 0) { cell_params.flags &= ~RD_CellFlag_ExpanderSpace; } } // rjf: apply background if(has_background) { cell_params.flags &= ~RD_CellFlag_NoBackground; } // rjf: apply toggle-switch if(is_toggle_switch) { cell_params.flags |= RD_CellFlag_ToggleSwitch; cell_params.toggled_out = &next_cell_toggled; } // rjf: apply slider if(is_slider) { cell_params.flags |= RD_CellFlag_Slider; cell_params.slider_value_out = &next_cell_slider_value; } // rjf: apply bindings if(cell->px == 0 && cell->eval.space.kind == RD_EvalSpaceKind_MetaCmd) { cell_params.flags |= RD_CellFlag_Bindings; cell_params.bindings_name = rd_cmd_name_from_eval(cell->eval); } // rjf: apply background override if(cell_background_color_override.w != 0) { cell_params.flags &= ~RD_CellFlag_NoBackground; } // rjf: apply type note if(!(cell_info.flags & RD_WatchCellFlag_NoEval) && e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Null && (cell->eval.space.kind == E_SpaceKind_Null || cell->eval.space.kind == CTRL_EvalSpaceKind_Entity) && row_info->callstack_thread == &ctrl_entity_nil && e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Function) UI_FontSize(ui_top_font_size()*0.9f) { if(cell_width_px >= ui_top_font_size()*8.f) { E_TypeKey type_key = cell->eval.irtree.type_key; String8 note_string = {0}; if(cell->eval.irtree.mode == E_Mode_Null && (row->block->eval.irtree.mode != E_Mode_Null || row->block->parent == &ev_nil_block)) { note_string = str8f(scratch.arena, "type (size: %I64u)", e_type_byte_size_from_key(type_key)); } else if(cell->eval.irtree.mode == E_Mode_Null) { note_string = str8f(scratch.arena, "type (size: %I64u, offset: %I64u)", e_type_byte_size_from_key(type_key), cell->eval.value.u64); } else { note_string = e_type_string_from_key(scratch.arena, type_key); } DR_FStrList note_fstrs = rd_fstrs_from_code_string(scratch.arena, 1, 0, ui_color_from_name(str8_lit("text")), note_string); F32 note_fstrs_width_px = dr_dim_from_fstrs(0, ¬e_fstrs).x + 10; note_fstrs_width_px = Min(note_fstrs_width_px, cell_width_px*0.5f); cell_params.note_fstrs = note_fstrs; cell_params.note_width = ui_px(note_fstrs_width_px, 1); } } } // rjf: build if(cell_background_color_override.w != 0) { ui_push_background_color(cell_background_color_override); } UI_TextAlignment(cell->px != 0 ? UI_TextAlign_Center : UI_TextAlign_Left) RD_Font(is_non_code ? RD_FontSlot_Main : RD_FontSlot_Code) { sig = rd_cellf(&cell_params, "%S###%I64x_row_%I64x", ghost_text, cell_x, row_hash); } if(cell_background_color_override.w != 0) { ui_pop_background_color(); } if(ui_is_focus_active() && selection_tbl.min.x == selection_tbl.max.x && selection_tbl.min.y == selection_tbl.max.y && txt_pt_match(cell_edit_state->cursor, cell_edit_state->mark)) { String8 input = str8(cell_edit_state->input_buffer, cell_edit_state->input_size); rd_set_autocomp_regs(cell->eval, .ui_key = line_edit_key, .string = input, .cursor = cell_edit_state->cursor); } } } //////////// //- rjf: handle interactions // { // rjf: hover -> debug log if(DEV_eval_compiler_tooltips) { if(ui_hovering(sig)) UI_Tooltip { String8 text = e_debug_log_from_expr_string(scratch.arena, cell->eval.string); String8List lines = str8_split(scratch.arena, text, (U8 *)"\n", 1, StringSplitFlag_KeepEmpties); for(String8Node *n = lines.first; n != 0; n = n->next) { if(n->string.size != 0) { ui_label(n->string); } } } } // rjf: hover -> rich hover cfgs if(ui_hovering(sig) && cell_info.cfg != &cfg_nil_node) { RD_RegsScope(.cfg = cell_info.cfg->id, .no_rich_tooltip = 1) rd_set_hover_regs(RD_RegSlot_Cfg); } // rjf: hover -> rich hover entities else if(ui_hovering(sig) && cell_info.entity != &ctrl_entity_nil) { RD_RegsScope(.ctrl_entity = cell_info.entity->handle, .no_rich_tooltip = 1) rd_set_hover_regs(RD_RegSlot_CtrlEntity); } // rjf: hover -> rich hover commands (mini only) else if(ui_hovering(sig) && cell_info.cmd_name.size != 0 && cell->px != 0) { RD_RegsScope(.cmd_name = cell_info.cmd_name, .ui_key = sig.box->key) rd_set_hover_regs(RD_RegSlot_CmdName); } // rjf: hover -> rich hover address ranges else if(ui_hovering(sig) && !(cell_info.flags & RD_WatchCellFlag_Expr)) { RD_RegsScope(.eval_space = cell->eval.space, .vaddr_range = cell_vaddr_rng, .src_ui_key = watch_rich_hover_key) rd_set_hover_regs(RD_RegSlot_VaddrRange); } // rjf: dragging -> drag/drop if(ui_dragging(sig) && !contains_2f32(sig.box->rect, ui_mouse()) && (!cell_selected || !ewv->text_editing)) { if(cell->eval.space.kind == E_SpaceKind_FileSystem) { String8 file_path = rd_file_path_from_eval(scratch.arena, cell->eval); RD_RegsScope(.file_path = file_path) rd_drag_begin(RD_RegSlot_FilePath); } else if(cell_info.cfg != &cfg_nil_node) { RD_RegsScope(.cfg = cell_info.cfg->id) rd_drag_begin(RD_RegSlot_Cfg); } else if(cell_info.entity != &ctrl_entity_nil) { RD_RegsScope(.ctrl_entity = cell_info.entity->handle) switch(cell_info.entity->kind) { default:{rd_drag_begin(RD_RegSlot_CtrlEntity);}break; case CTRL_EntityKind_Machine:{RD_RegsScope(.machine = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Machine);}break; case CTRL_EntityKind_Process:{RD_RegsScope(.process = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Process);}break; case CTRL_EntityKind_Module:{RD_RegsScope(.module = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Module);}break; case CTRL_EntityKind_Thread:{RD_RegsScope(.thread = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Thread);}break; } } else if(cell->eval.space.kind == CTRL_EvalSpaceKind_Entity || cell->eval.space.kind == E_SpaceKind_FileSystem || cell->eval.space.kind == E_SpaceKind_File || cell->eval.space.kind == E_SpaceKind_Null) { RD_RegsScope(.expr = e_full_expr_string_from_key(scratch.arena, cell->eval.key)) { if(cell->flags & RD_WatchCellFlag_Expr) { rd_regs()->cfg = row_info->group_cfg_child->id; } rd_drag_begin(RD_RegSlot_Expr); } } } // rjf: (normally) single-click -> move selection here if(!(cell_info.flags & RD_WatchCellFlag_ActivateWithSingleClick) && ui_pressed(sig)) { ewv->next_cursor = ewv->next_mark = cell_pt; pressed = 1; } // rjf: reversion if(revert_cell && cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg) { CFG_Node *cfg = rd_cfg_from_eval_space(cell->eval.space); String8 child_key = e_string_from_id(cell->eval.space.u64s[1]); cfg_node_release(rd_state->cfg, cfg_node_child_from_string(cfg, child_key)); } // rjf: activation (double-click normally, or single-clicks with special buttons) if((!(cell_info.flags & RD_WatchCellFlag_ActivateWithSingleClick) && ui_double_clicked(sig)) || ((cell_info.flags & RD_WatchCellFlag_ActivateWithSingleClick) && ui_clicked(sig)) || sig.f & UI_SignalFlag_KeyboardPressed) { // rjf: kill if a double-clickable cell if(!(cell_info.flags & RD_WatchCellFlag_ActivateWithSingleClick)) { ui_kill_action(); } // rjf: cell w/ a visualizer hook? -> // if keyboard: open in tab, if within tab // if double-click: focus this visualizer (via edit) if(cell->kind == RD_WatchCellKind_ViewUI && cell_info.view_ui_rule != &rd_nil_view_ui_rule && cell_view != &cfg_nil_node) { if(!view_is_floating && sig.f & UI_SignalFlag_KeyboardPressed) { cfg_node_unhook(rd_state->cfg, cell_view->parent, cell_view); cfg_node_insert_child(rd_state->cfg, view->parent, view, cell_view); rd_cmd(RD_CmdKind_FocusTab, .tab = cell_view->id); } else if(sig.f & UI_SignalFlag_DoubleClicked) { ewv->next_cursor = ewv->next_mark = cell_pt; if(!rd_watch_pt_match(ewv->cursor, cell_pt) && ewv->text_editing) { rd_cmd(RD_CmdKind_Accept); } rd_cmd(RD_CmdKind_Edit); } } // rjf: this watch window is a lister? -> move cursor & edit or accept else if(cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node || cfg_node_child_from_string(view, str8_lit("autocomplete")) != &cfg_nil_node) { ewv->next_cursor = ewv->next_mark = cell_pt; if(cell_info.flags & RD_WatchCellFlag_CanEdit) { // TODO(rjf): @hack - we really want navigations to be event-like, but we need // to insert a dumb no-op here so that the "rugpull" cursor move can take effect // before the edit command we are queueing up... rd_cmd(RD_CmdKind_Edit); rd_cmd(RD_CmdKind_Edit); } else { rd_cmd(RD_CmdKind_Edit); ewv->next_cursor = ewv->next_mark = cell_pt; rd_cmd(RD_CmdKind_Accept); } } // rjf: has a command name? -> push command else if(cell_info.cmd_name.size != 0) { String8 cmd_name = cell_info.cmd_name; RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(row->eval.space); CFG_Node *cfg = rd_cfg_from_eval_space(row->eval.space); if(cfg == &cfg_nil_node) { cfg = rd_cfg_from_eval_space(row->block->eval.space); } if(entity == &ctrl_entity_nil) { entity = rd_ctrl_entity_from_eval_space(row->eval.space); } RD_RegsScope(.cfg = cfg->id, .ctrl_entity = entity->handle) { if(cfg != &cfg_nil_node) { CFG_PanelTree panels = cfg_panel_tree_from_cfg(scratch.arena, cfg); CFG_PanelNode *parent_panel_node = cfg_panel_node_from_tree_cfg(panels.root, cfg->parent); if(parent_panel_node != &cfg_nil_panel_node) { rd_regs()->tab = rd_regs()->view = cfg->id; } } if(!(cmd_kind_info->query.flags & RD_QueryFlag_Required) || (cmd_kind_info->query.slot == RD_RegSlot_Cfg && cfg != &cfg_nil_node) || (cmd_kind_info->query.slot == RD_RegSlot_CtrlEntity && entity != &ctrl_entity_nil)) { rd_push_cmd(cell_info.cmd_name, rd_regs()); } else { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = cmd_name); } } } // rjf: row has callstack info? -> select unwind else if(row_info->callstack_thread != &ctrl_entity_nil) { rd_cmd(RD_CmdKind_SelectThread, .thread = row_info->callstack_thread->handle); rd_cmd(RD_CmdKind_SelectUnwind, .unwind_count = row_info->callstack_unwind_index, .inline_depth = row_info->callstack_inline_depth); } // rjf: can edit? -> begin editing else if(!(sig.f & UI_SignalFlag_KeyboardPressed) && cell_info.flags & RD_WatchCellFlag_CanEdit) { ewv->next_cursor = ewv->next_mark = cell_pt; if(!rd_watch_pt_match(ewv->cursor, cell_pt)) { // TODO(rjf): see above @hack rd_cmd(RD_CmdKind_Edit); } rd_cmd(RD_CmdKind_Edit); } // rjf: can expand? -> expand else if(sig.f & UI_SignalFlag_KeyboardPressed && row_is_expandable) { next_row_expanded = !row_expanded; } // rjf: can't edit, but has address info? -> go to address else if(cell->eval.space.kind == CTRL_EvalSpaceKind_Entity) { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(cell->eval.space); CTRL_Entity *process = ctrl_process_from_entity(entity); if(process != &ctrl_entity_nil) { U64 vaddr = cell->eval.value.u64; CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); U64 voff = ctrl_voff_from_vaddr(module, vaddr); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff); String8 file_path = {0}; TxtPt pt = {0}; if(lines.first != 0) { file_path = lines.first->v.file_path; pt = lines.first->v.pt; rd_cmd(RD_CmdKind_FindCodeLocation, .process = process->handle, .vaddr = vaddr, .file_path = file_path, .cursor = pt); } } } // rjf: can't edit, but has cfg? -> find or select else if(cell_info.cfg != &cfg_nil_node) { CFG_Node *cfg = cell_info.cfg; RD_Location loc = rd_location_from_cfg(cfg); if(loc.file_path.size != 0) { rd_cmd(RD_CmdKind_FindCodeLocation, .vaddr = 0, .file_path = loc.file_path, .cursor = loc.pt); } else if(loc.expr.size != 0) { U64 value = e_value_from_string(loc.expr).u64; rd_cmd(RD_CmdKind_FindCodeLocation, .vaddr = value); } else if(str8_match(cfg->string, str8_lit("target"), 0) && sig.event_flags & OS_Modifier_Ctrl) { rd_cmd(RD_CmdKind_EnableCfg, .cfg = cfg->id); } else if(str8_match(cfg->string, str8_lit("target"), 0)) { rd_cmd(RD_CmdKind_SelectCfg, .cfg = cfg->id); } } // rjf: can't edit, but has thread? -> select else if(cell_info.entity->kind == CTRL_EntityKind_Thread) { rd_cmd(RD_CmdKind_SelectThread, .thread = cell_info.entity->handle); } // rjf: other cases, but this watch window is floating, and this has a cfg/entity? -> push query else if(view_is_floating && (cell_info.entity != &ctrl_entity_nil || cell_info.cfg != &cfg_nil_node)) { rd_cmd(RD_CmdKind_PushQuery, .expr = e_full_expr_string_from_key(scratch.arena, cell->eval.key)); } } // rjf: hovering with inheritance string -> show tooltip if(ui_hovering(sig) && cell_info.inheritance_tooltip.size != 0) UI_Tooltip { UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(1, 1)) UI_TextPadding(0) { ui_labelf("Inherited from "); RD_Font(RD_FontSlot_Code) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("code_default")), cell_info.inheritance_tooltip); } } // rjf: hovering with error tooltip -> show tooltip if(ui_hovering(sig) && cell_info.error_tooltip.size != 0) UI_Tooltip { UI_PrefWidth(ui_children_sum(1)) rd_error_label(cell_info.error_tooltip); } } //////////// //- rjf: commit toggle changes // if(next_cell_toggled != cell_toggled) { rd_commit_eval_value_string(cell->eval, next_cell_toggled ? str8_lit("1") : str8_lit("0")); } //////////// //- rjf: commit slider changes // if(next_cell_slider_value != cell_slider_value) { String8 new_value_string = {0}; switch(slider_value_type_kind) { default: if(e_type_kind_is_integer(slider_value_type_kind)) { S64 new_value = (S64)((next_cell_slider_value * (cell_slider_max.s64 - cell_slider_min.s64)) + cell_slider_min.s64); new_value = Clamp(cell_slider_min.s64, new_value, cell_slider_max.s64); new_value_string = push_str8f(scratch.arena, "%I64d", new_value); }break; case E_TypeKind_F32: { F32 new_value = (next_cell_slider_value * (cell_slider_max.f32 - cell_slider_min.f32)) + cell_slider_min.f32; new_value = Clamp(cell_slider_min.f32, new_value, cell_slider_max.f32); new_value_string = push_str8f(scratch.arena, "%f", new_value); }break; case E_TypeKind_F64: { F64 new_value = (F64)((next_cell_slider_value * (cell_slider_max.f64 - cell_slider_min.f64)) + cell_slider_min.f64); new_value = Clamp(cell_slider_min.f64, new_value, cell_slider_max.f64); new_value_string = push_str8f(scratch.arena, "%f", new_value); }break; } rd_commit_eval_value_string(cell->eval, new_value_string); } //////////// //- rjf: bump x pixel coordinate // cell_x_px = next_cell_x_px; if(row_depth > 0) { ui_pop_tag(); } } } ////////////////////// //- rjf: commit expansion state changes // if(next_row_expanded != row_expanded) { if(!ev_key_match(ev_key_root(), row->key)) { ev_key_set_expansion(eval_view, row->block->key, row->key, next_row_expanded); } } } } } } } ////////////////////////////// //- rjf: general table-wide press logic // if(pressed) { rd_cmd(RD_CmdKind_FocusPanel); } ////////////////////////////// //- rjf: disable query if text editing is occurring // vs->contents_are_focused = ewv->text_editing; rd_store_view_scroll_pos(scroll_pos); } scratch_end(scratch); } //////////////////////////// //- rjf: visualizer hook // else { Temp scratch = scratch_begin(0, 0); RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(view_name); E_Eval expr_eval = e_eval_from_string(expr_string); // rjf: peek presses, steal focus from query bar for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && contains_2f32(rect, evt->pos)) { vs->contents_are_focused = 1; break; } } // rjf: 'pull out' button, if floating if(view_is_floating) { UI_Signal pull_out_sig = {0}; UI_TagF(".") UI_TagF("tab") UI_Rect(r2f32p(floor_f32(ui_top_font_size()*1.5f), floor_f32(ui_top_font_size()*1.5f), floor_f32(ui_top_font_size()*1.5f + ui_top_font_size()*3.f), floor_f32(ui_top_font_size()*1.5f + ui_top_font_size()*3.f))) UI_CornerRadius(floor_f32(ui_top_font_size()*1.5f)) UI_TextAlignment(UI_TextAlign_Center) RD_Font(RD_FontSlot_Icons) UI_FontSize(floor_f32(ui_top_font_size()*0.9f)) { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_Floating| UI_BoxFlag_DrawText| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_DrawHotEffects, "%S###pull_out", rd_icon_kind_text_table[RD_IconKind_Window]); pull_out_sig = ui_signal_from_box(box); } if(ui_dragging(pull_out_sig) && !contains_2f32(pull_out_sig.box->rect, ui_mouse())) { rd_drag_begin(RD_RegSlot_View); } if(ui_hovering(pull_out_sig)) UI_Tooltip RD_Font(RD_FontSlot_Main) { ui_state->tooltip_anchor_key = pull_out_sig.box->key; ui_labelf("Pull Out As New Tab"); } } // rjf: build ui via hook E_ParentKey(expr_eval.key) { view_ui_rule->ui(expr_eval, rect); } scratch_end(scratch); } } //////////////////////////// //- rjf: catchall completion controls // if(vs->query_is_open) UI_Focus(UI_FocusKind_On) { if(ui_is_focus_active() && ui_slot_press(UI_EventActionSlot_Cancel)) { vs->query_is_open = 0; vs->query_string_size = 0; } if(ui_is_focus_active() && ui_slot_press(UI_EventActionSlot_Accept)) { String8 cmd_name = rd_view_query_cmd(); String8 input = rd_view_query_input(); RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); RD_RegsScope() { rd_regs_fill_slot_from_string(cmd_kind_info->query.slot, str8_zero(), input); rd_cmd(RD_CmdKind_CompleteQuery); } } } vs->last_frame_index_built = rd_state->frame_index; ProfEnd(); } //////////////////////////////// //~ rjf: View Building API //- rjf: view info extraction internal Arena * rd_view_arena(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); return view_state->arena; } internal UI_ScrollPt2 rd_view_scroll_pos(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); return view_state->scroll_pos; } internal EV_View * rd_view_eval_view(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); return view_state->ev_view; } internal String8 rd_view_query_cmd(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *query = cfg_node_child_from_string(view, str8_lit("query")); CFG_Node *cmd = cfg_node_child_from_string(query, str8_lit("cmd")); String8 string = cmd->first->string; return string; } internal String8 rd_view_query_input(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *query = cfg_node_child_from_string(view, str8_lit("query")); CFG_Node *input = cfg_node_child_from_string(query, str8_lit("input")); String8 string = input->first->string; return string; } internal String8 rd_view_setting_from_name(String8 name) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); String8 result = cfg_node_child_from_string(view, name)->first->string; if(result.size == 0) { result = rd_default_setting_from_names(view->string, name); } return result; } internal E_Value rd_view_setting_value_from_name(String8 name) { String8 expr = rd_view_setting_from_name(name); E_Eval eval = e_eval_from_string(expr); E_Value result = e_value_eval_from_eval(eval).value; return result; } internal B32 rd_view_setting_b32_from_name(String8 name) { String8 string = rd_view_setting_from_name(name); B32 result = !!e_value_from_stringf("raw((bool)(%S))", string).u64; return result; } internal U64 rd_view_setting_u64_from_name(String8 name) { String8 string = rd_view_setting_from_name(name); U64 result = e_value_from_stringf("raw((uint64)(%S))", string).u64; return result; } internal F32 rd_view_setting_f32_from_name(String8 name) { String8 string = rd_view_setting_from_name(name); F32 result = e_value_from_stringf("raw((float32)(%S))", string).f32; return result; } //- rjf: evaluation & tag (a view's 'call') parameter extraction internal Rng1U64 rd_space_range_from_eval(E_Eval eval) { Rng1U64 range = e_range_from_eval(eval); U64 size_setting = rd_view_setting_value_from_name(str8_lit("size")).u64; if(size_setting != 0) { range.max = range.min + size_setting; } return range; } internal TXT_LangKind rd_lang_kind_from_eval(E_Eval eval) { TXT_LangKind lang_kind = TXT_LangKind_Null; Temp scratch = scratch_begin(0, 0); String8 file_path = rd_file_path_from_eval(scratch.arena, eval); if(file_path.size != 0) { lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(file_path)); } scratch_end(scratch); return lang_kind; } internal Arch rd_arch_from_eval(E_Eval eval) { // rjf: try implicitly from either `eval` itself, or from context CTRL_Entity *ctrl_entity = rd_ctrl_entity_from_eval_space(eval.space); CTRL_Entity *process = ctrl_process_from_entity(ctrl_entity); if(process == &ctrl_entity_nil) { process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); } Arch arch = process->arch; if(arch == Arch_Null) { arch = Arch_CURRENT; } // rjf: try arch arguments E_Type *type = e_type_from_key(eval.irtree.type_key); if(type->kind == E_TypeKind_Lens) { for EachIndex(idx, type->count) { E_Expr *arg = type->args[idx]; { String8 arg_arch_string = arg->string; if(arg->kind == E_ExprKind_Define && str8_match(arg->first->string, str8_lit("arch"), 0)) { arg_arch_string = arg->first->next->string; } if(str8_match(arg->first->next->string, str8_lit("x64"), 0)) { arch = Arch_x64; break; } } } } return arch; } //- rjf: pushing/attaching view resources internal void * rd_view_state_by_size(U64 size) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); if(view_state->user_data == 0) { view_state->user_data = push_array(view_state->arena, U8, size); } return view_state->user_data; } internal Arena * rd_push_view_arena(void) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); RD_ArenaExt *ext = push_array(view_state->arena, RD_ArenaExt, 1); ext->arena = arena_alloc(); SLLQueuePush(view_state->first_arena_ext, view_state->last_arena_ext, ext); return ext->arena; } //- rjf: storing view-attached state internal void rd_store_view_expr_string(String8 string) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, string); } internal void rd_store_view_loading_info(B32 is_loading, U64 progress_u64, U64 progress_u64_target) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); B32 loading_state_is_new = (is_loading && view_state->loading_t_target != (F32)!!is_loading); view_state->loading_t_target = (F32)!!is_loading; view_state->loading_progress_v = progress_u64; view_state->loading_progress_v_target = progress_u64_target; if(loading_state_is_new || view_state->last_frame_index_built+1 < rd_state->frame_index) { view_state->loading_t = view_state->loading_t_target; } } internal void rd_store_view_scroll_pos(UI_ScrollPt2 pos) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *view_state = rd_view_state_from_cfg(view); view_state->scroll_pos = pos; } internal void rd_store_view_param(String8 key, String8 value) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *child = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, key); cfg_node_new_replace(rd_state->cfg, child, value); } internal void rd_store_view_paramf(String8 key, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); rd_store_view_param(key, string); va_end(args); scratch_end(scratch); } //////////////////////////////// //~ rjf: Window Functions internal String8 rd_push_window_title(Arena *arena) { String8 result = push_str8f(arena, "%S - %s", str8_skip_last_slash(rd_state->project_path), BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ")"); return result; } internal CFG_Node * rd_window_from_cfg(CFG_Node *cfg) { CFG_Node *result = &cfg_nil_node; for(CFG_Node *c = cfg; c != &cfg_nil_node; c = c->parent) { if(c->parent->parent == cfg_node_root() && str8_match(c->string, str8_lit("window"), 0)) { result = c; break; } } return result; } internal RD_WindowState * rd_window_state_from_cfg(CFG_Node *cfg) { //- rjf: unpack CFG_Node *window_cfg = rd_window_from_cfg(cfg); CFG_ID id = window_cfg->id; //- rjf: scan for existing window RD_WindowState *ws = &rd_nil_window_state; if(id != 0 && id == rd_state->window_state_last_accessed_id && id == rd_state->window_state_last_accessed->cfg_id) { ws = rd_state->window_state_last_accessed; } else { U64 hash = d_hash_from_string(str8_struct(&id)); U64 slot_idx = hash%rd_state->window_state_slots_count; RD_WindowStateSlot *slot = &rd_state->window_state_slots[slot_idx]; for(RD_WindowState *w = slot->first; w != 0; w = w->hash_next) { if(w->cfg_id == id) { ws = w; break; } } } //- rjf: allocate/open new window if one was not found if(window_cfg != &cfg_nil_node && ws == &rd_nil_window_state) { Temp scratch = scratch_begin(0, 0); // rjf: unpack configuration options B32 has_pos = 0; Vec2F32 pos = {0}; Vec2F32 size = {0}; OS_Handle preferred_monitor = {0}; { CFG_Node *pos_cfg = cfg_node_child_from_string(window_cfg, str8_lit("pos")); has_pos = (pos_cfg != &cfg_nil_node); CFG_Node *size_cfg = cfg_node_child_from_string(window_cfg, str8_lit("size")); CFG_Node *monitor_cfg = cfg_node_child_from_string(window_cfg, str8_lit("monitor")); pos.x = (F32)f64_from_str8(pos_cfg->first->string); pos.y = (F32)f64_from_str8(pos_cfg->first->next->string); size.x = (F32)f64_from_str8(size_cfg->first->string); size.y = (F32)f64_from_str8(size_cfg->first->next->string); OS_HandleArray monitors = os_push_monitors_array(scratch.arena); for EachIndex(idx, monitors.count) { String8 monitor_name = os_name_from_monitor(scratch.arena, monitors.v[idx]); if(str8_match(monitor_name, monitor_cfg->first->string, StringMatchFlag_CaseInsensitive)) { preferred_monitor = monitors.v[idx]; break; } } } // rjf: allocate window ws = rd_state->free_window_state; if(ws != 0) { SLLStackPop_N(rd_state->free_window_state, order_next); } else { ws = push_array_no_zero(rd_state->arena, RD_WindowState, 1); } MemoryZeroStruct(ws); // rjf: fill out window ws->cfg_id = id; ws->arena = arena_alloc(); { String8 title = rd_push_window_title(scratch.arena); ws->os = os_window_open(r2f32p(pos.x, pos.y, pos.x+size.x, pos.y+size.y), (!has_pos*OS_WindowFlag_UseDefaultPosition)|OS_WindowFlag_CustomBorder, title); } ws->r = r_window_equip(ws->os); ws->ui = ui_state_alloc(); ws->drop_completion_arena = arena_alloc(); ws->query_arena = arena_alloc(); ws->hover_eval_arena = arena_alloc(); ws->autocomp_arena = arena_alloc(); ws->last_dpi = os_dpi_from_window(ws->os); OS_Handle zero_monitor = {0}; if(!os_handle_match(zero_monitor, preferred_monitor)) { os_window_set_monitor(ws->os, preferred_monitor); } if(cfg_node_child_from_string(window_cfg, str8_lit("fullscreen")) != &cfg_nil_node) { os_window_set_fullscreen(ws->os, 1); } if(cfg_node_child_from_string(window_cfg, str8_lit("maximized")) != &cfg_nil_node) { os_window_set_maximized(ws->os, 1); } // rjf: hook up window links U64 hash = d_hash_from_string(str8_struct(&id)); U64 slot_idx = hash%rd_state->window_state_slots_count; RD_WindowStateSlot *slot = &rd_state->window_state_slots[slot_idx]; DLLPushBack_NPZ(&rd_nil_window_state, rd_state->first_window_state, rd_state->last_window_state, ws, order_next, order_prev); DLLPushBack_NP(slot->first, slot->last, ws, hash_next, hash_prev); scratch_end(scratch); } //- rjf: touch window for this frame if(ws != &rd_nil_window_state) { ws->last_frame_index_touched = rd_state->frame_index; } rd_state->window_state_last_accessed_id = ws->cfg_id; rd_state->window_state_last_accessed = ws; return ws; } internal RD_WindowState * rd_window_state_from_os_handle(OS_Handle os) { RD_WindowState *ws = &rd_nil_window_state; { for(RD_WindowState *w = rd_state->first_window_state; w != &rd_nil_window_state; w = w->order_next) { if(os_handle_match(w->os, os)) { ws = w; break; } } } return ws; } #if COMPILER_MSVC && !BUILD_DEBUG NO_OPTIMIZE_BEGIN #endif internal void rd_window_frame(void) { Temp scratch = scratch_begin(0, 0); ProfBeginFunction(); ////////////////////////////// //- rjf: @window_frame_part unpack context // CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(cfg_node_from_id(rd_regs()->window)); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); B32 window_is_focused = (os_window_is_focused(ws->os) || ws->window_temporarily_focused_ipc); B32 popup_is_open = (rd_state->popup_active); B32 query_is_open = (ws->query_is_active); U64 hover_eval_open_delay_us = 400000; B32 hover_eval_is_open = (!popup_is_open && !query_is_open && ws->hover_eval_string.size != 0 && ws->hover_eval_firstt_us+hover_eval_open_delay_us < ws->hover_eval_lastt_us && rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us); if(!window_is_focused || popup_is_open) { ws->menu_bar_key_held = 0; } ws->window_temporarily_focused_ipc = 0; ui_select_state(ws->ui); ////////////////////////////// //- rjf: @window_frame_part fill panel/view interaction registers // rd_regs()->panel = panel_tree.focused->cfg->id; rd_regs()->tab = panel_tree.focused->selected_tab->id; rd_regs()->view = panel_tree.focused->selected_tab->id; ////////////////////////////// //- rjf: @window_frame_part compute window's theme // { Access *access = access_open(); //- rjf: try to find theme settings from the project, then the user. CFG_NodePtrList colors_cfgs = {0}; CFG_Node *theme_parents[] = { cfg_node_child_from_string(cfg_node_root(), str8_lit("project")), cfg_node_child_from_string(cfg_node_root(), str8_lit("user")) }; CFG_Node *theme_cfgs[] = { &cfg_nil_node, &cfg_nil_node, }; for EachIndex(idx, ArrayCount(theme_parents)) { CFG_Node *parent_cfg = theme_parents[idx]; if(theme_cfgs[idx] == &cfg_nil_node) { CFG_Node *possible_theme_cfg = cfg_node_child_from_string(parent_cfg, str8_lit("theme")); if(possible_theme_cfg != &cfg_nil_node) { theme_cfgs[idx] = possible_theme_cfg; } } for(CFG_Node *child = parent_cfg->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("theme_color"), 0)) { cfg_node_ptr_list_push_front(scratch.arena, &colors_cfgs, child); } } } //- rjf: choose which theme cfg to use CFG_Node *theme_cfg = theme_cfgs[1]; if(rd_setting_b32_from_name(str8_lit("use_project_theme"))) { theme_cfg = theme_cfgs[0]; if(theme_cfg == &cfg_nil_node) { theme_cfg = theme_cfgs[1]; } } //- rjf: map the theme config to the associated tree (either from a preset, or from a file) MD_Node *theme_tree = rd_theme_tree_from_name(scratch.arena, access, theme_cfg->first->string); if(colors_cfgs.count == 0 && theme_tree == &md_nil_node) { theme_tree = rd_state->theme_preset_trees[RD_ThemePreset_DefaultDark]; } //- rjf: build tasks for color applications - each task comprises of a metadesk // tree, describing the color patterns typedef struct ThemeTask ThemeTask; struct ThemeTask { ThemeTask *next; MD_Node *tree; }; ThemeTask start_task = {0, theme_tree}; ThemeTask *first_task = &start_task; ThemeTask *last_task = first_task; { for(CFG_NodePtrNode *n = colors_cfgs.first; n != 0; n = n->next) { ThemeTask *t = push_array(scratch.arena, ThemeTask, 1); SLLQueuePushFront(first_task, last_task, t); t->tree = md_tree_from_string(scratch.arena, cfg_string_from_tree(scratch.arena, rd_state->cfg_schema_table, str8_zero(), n->v)); } } //- rjf: apply theme tasks, build each color pattern for this window's // structured theme typedef struct ThemePatternNode ThemePatternNode; struct ThemePatternNode { ThemePatternNode *next; UI_ThemePattern pattern; }; ThemePatternNode *first_pattern = 0; ThemePatternNode *last_pattern = 0; U64 pattern_count = 0; for(ThemeTask *t = first_task; t != 0; t = t->next) { MD_Node *tree_root = t->tree; for(MD_Node *n = tree_root; !md_node_is_nil(n); n = md_node_rec_depth_first_pre(n, tree_root).next) { if(str8_match(n->string, str8_lit("theme_color"), 0)) { MD_Node *tags_child = md_child_from_string(n, str8_lit("tags"), 0); MD_Node *value_child = md_child_from_string(n, str8_lit("value"), 0); U8 split_char = ' '; String8List tags = str8_split(scratch.arena, tags_child->first->string, &split_char, 1, 0); U32 color_u32 = e_value_from_stringf("raw(%S)", value_child->first->string).u32; Vec4F32 color_linear = linear_from_srgba(rgba_from_u32(color_u32)); ThemePatternNode *node = push_array(scratch.arena, ThemePatternNode, 1); node->pattern.tags = str8_array_from_list(rd_frame_arena(), &tags); node->pattern.linear = color_linear; SLLQueuePush(first_pattern, last_pattern, node); pattern_count += 1; } } } //- rjf: convert to final pattern array ws->theme = push_array(rd_frame_arena(), UI_Theme, 1); ws->theme->patterns_count = pattern_count; ws->theme->patterns = push_array(rd_frame_arena(), UI_ThemePattern, ws->theme->patterns_count); { U64 idx = 0; for(ThemePatternNode *n = first_pattern; n != 0; n = n->next, idx += 1) { ws->theme->patterns[idx] = n->pattern; } } access_close(access); } ////////////////////////////// //- rjf: @window_frame_part compute window's font raster flags // { ws->font_slot_raster_flags[RD_FontSlot_Icons] = FNT_RasterFlag_Smooth; ws->font_slot_raster_flags[RD_FontSlot_Main] = (rd_setting_b32_from_name(str8_lit("smooth_ui_text"))*FNT_RasterFlag_Smooth)|(rd_setting_b32_from_name(str8_lit("hint_ui_text"))*FNT_RasterFlag_Hinted); ws->font_slot_raster_flags[RD_FontSlot_Code] = (rd_setting_b32_from_name(str8_lit("smooth_code_text"))*FNT_RasterFlag_Smooth)|(rd_setting_b32_from_name(str8_lit("hint_code_text"))*FNT_RasterFlag_Hinted); } ////////////////////////////// //- rjf: @window_frame_part pre-emptively rasterize common glyphs on the first frame // if(rd_state->first_window_state == ws && rd_state->last_window_state == ws && ws->frames_alive == 0) { F32 font_size = rd_font_size(); RD_FontSlot english_font_slots[] = {RD_FontSlot_Main, RD_FontSlot_Code}; RD_FontSlot icon_font_slot = RD_FontSlot_Icons; for(U64 idx = 0; idx < ArrayCount(english_font_slots); idx += 1) { Temp scratch = scratch_begin(0, 0); RD_FontSlot slot = english_font_slots[idx]; String8 sample_text = str8_lit("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$%^&*()-_+=[{]}\\|;:'\",<.>/?"); fnt_run_from_string(rd_font_from_slot(slot), font_size, 0, 0, 0, sample_text); fnt_run_from_string(rd_font_from_slot(slot), font_size, 0, 0, 0, sample_text); scratch_end(scratch); } for(RD_IconKind icon_kind = RD_IconKind_Null; icon_kind < RD_IconKind_COUNT; icon_kind = (RD_IconKind)(icon_kind+1)) { Temp scratch = scratch_begin(0, 0); fnt_run_from_string(rd_font_from_slot(icon_font_slot), font_size, 0, 0, FNT_RasterFlag_Smooth, rd_icon_kind_text_table[icon_kind]); fnt_run_from_string(rd_font_from_slot(icon_font_slot), font_size, 0, 0, FNT_RasterFlag_Smooth, rd_icon_kind_text_table[icon_kind]); fnt_run_from_string(rd_font_from_slot(icon_font_slot), font_size, 0, 0, FNT_RasterFlag_Smooth, rd_icon_kind_text_table[icon_kind]); scratch_end(scratch); } } ////////////////////////////// //- rjf: @window_frame_part commit window's position/status to underlying cfg tree // { Temp scratch = scratch_begin(0, 0); B32 is_fullscreen = os_window_is_fullscreen(ws->os); B32 is_maximized = os_window_is_maximized(ws->os); B32 is_minimized = os_window_is_minimized(ws->os); if(is_fullscreen) { cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("fullscreen")); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("fullscreen"))); } if(is_maximized) { cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("maximized")); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("maximized"))); } //- rjf: DPI changes -> xform font size / window size F32 dpi = os_dpi_from_window(ws->os); if(dpi != ws->last_dpi) { fnt_reset(); F32 current_font_size = rd_font_size(); F32 new_font_size = current_font_size * (dpi / ws->last_dpi); new_font_size = Clamp(6.f, new_font_size, 72.f); CFG_Node *font_size_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("font_size")); cfg_node_new_replacef(rd_state->cfg, font_size_cfg, "%I64u", (U64)new_font_size); ws->last_dpi = dpi; } //- rjf: commit position Rng2F32 window_rect = os_rect_from_window(ws->os); if(!is_fullscreen && !is_maximized && !is_minimized) { Vec2F32 pos = window_rect.p0; CFG_Node *pos_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("pos")); if((S32)pos.x != (S32)f64_from_str8(pos_root->first->string) || (S32)pos.y != (S32)f64_from_str8(pos_root->last->string)) { CFG_Node *x = pos_root->first; if(x == &cfg_nil_node) { x= cfg_node_alloc(rd_state->cfg); cfg_node_insert_child(rd_state->cfg, pos_root, &cfg_nil_node, x); } CFG_Node *y = x->next; if(y == &cfg_nil_node) { y = cfg_node_alloc(rd_state->cfg); cfg_node_insert_child(rd_state->cfg, pos_root, x, y); } cfg_node_equip_stringf(rd_state->cfg, x, "%i", (S32)pos.x); cfg_node_equip_stringf(rd_state->cfg, y, "%i", (S32)pos.y); } } //- rjf: commit size if(!is_fullscreen && !is_maximized && !is_minimized) { Vec2F32 size = dim_2f32(window_rect); CFG_Node *size_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("size")); if((S32)size.x != (S32)f64_from_str8(size_root->first->string) || (S32)size.y != (S32)f64_from_str8(size_root->last->string)) { CFG_Node *width = size_root->first; if(width == &cfg_nil_node) { width = cfg_node_alloc(rd_state->cfg); cfg_node_insert_child(rd_state->cfg, size_root, &cfg_nil_node, width); } CFG_Node *height = width->next; if(height == &cfg_nil_node) { height = cfg_node_alloc(rd_state->cfg); cfg_node_insert_child(rd_state->cfg, size_root, width, height); } cfg_node_equip_stringf(rd_state->cfg, width, "%i", (S32)size.x); cfg_node_equip_stringf(rd_state->cfg, height, "%i", (S32)size.y); } } //- rjf: commit monitor if(!is_minimized) { OS_Handle monitor = os_monitor_from_window(ws->os); String8 monitor_name = os_name_from_monitor(scratch.arena, monitor); CFG_Node *monitor_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("monitor")); if(!str8_match(monitor_root->first->string, monitor_name, 0)) { cfg_node_new_replace(rd_state->cfg, monitor_root, monitor_name); } } scratch_end(scratch); } ////////////////////////////// //- rjf: @window_frame_part build UI // UI_Box *lister_box = &ui_nil_box; ProfScope("build UI") { //////////////////////////// //- rjf: @window_ui_part set up // { // rjf: get top-level font size info F32 top_level_font_size = 0; RD_RegsScope(.view = 0, .tab = 0) top_level_font_size = rd_font_size(); // rjf: build icon info UI_IconInfo icon_info = {0}; { icon_info.icon_font = rd_font_from_slot(RD_FontSlot_Icons); icon_info.icon_kind_text_map[UI_IconKind_RightArrow] = rd_icon_kind_text_table[RD_IconKind_RightScroll]; icon_info.icon_kind_text_map[UI_IconKind_DownArrow] = rd_icon_kind_text_table[RD_IconKind_DownScroll]; icon_info.icon_kind_text_map[UI_IconKind_LeftArrow] = rd_icon_kind_text_table[RD_IconKind_LeftScroll]; icon_info.icon_kind_text_map[UI_IconKind_UpArrow] = rd_icon_kind_text_table[RD_IconKind_UpScroll]; icon_info.icon_kind_text_map[UI_IconKind_RightCaret] = rd_icon_kind_text_table[RD_IconKind_RightCaret]; icon_info.icon_kind_text_map[UI_IconKind_DownCaret] = rd_icon_kind_text_table[RD_IconKind_DownCaret]; icon_info.icon_kind_text_map[UI_IconKind_LeftCaret] = rd_icon_kind_text_table[RD_IconKind_LeftCaret]; icon_info.icon_kind_text_map[UI_IconKind_UpCaret] = rd_icon_kind_text_table[RD_IconKind_UpCaret]; icon_info.icon_kind_text_map[UI_IconKind_CheckHollow] = rd_icon_kind_text_table[RD_IconKind_CheckHollow]; icon_info.icon_kind_text_map[UI_IconKind_CheckFilled] = rd_icon_kind_text_table[RD_IconKind_CheckFilled]; } // rjf: build animation info UI_AnimationInfo animation_info = {0}; { animation_info.hot_animation_rate = rd_state->catchall_animation_rate; animation_info.active_animation_rate = rd_state->catchall_animation_rate; animation_info.focus_animation_rate = 1.f; animation_info.tooltip_animation_rate = rd_state->tooltip_animation_rate; animation_info.menu_animation_rate = rd_state->menu_animation_rate; animation_info.scroll_animation_rate = rd_state->scrolling_animation_rate; } // rjf: begin & push initial stack values ui_begin_build(ws->os, &ws->ui_events, &icon_info, ws->theme, &animation_info, rd_state->frame_dt, rd_state->frame_dt); ui_push_font(rd_font_from_slot(RD_FontSlot_Main)); ui_push_font_size(top_level_font_size); ui_push_text_padding(floor_f32(ui_top_font_size()*0.3f)); ui_push_pref_width(ui_px(floor_f32(ui_top_font_size()*20.f), 1.f)); ui_push_pref_height(ui_px(floor_f32(ui_top_font_size()*3.f), 1.f)); ui_push_blur_size(10.f); FNT_RasterFlags text_raster_flags = 0; if(rd_setting_b32_from_name(str8_lit("smooth_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Smooth;} if(rd_setting_b32_from_name(str8_lit("hint_ui_text"))) {text_raster_flags |= FNT_RasterFlag_Hinted;} ui_push_text_raster_flags(text_raster_flags); } //////////////////////////// //- rjf: @window_ui_part calculate code color slot RGBAs // for EachEnumVal(RD_CodeColorSlot, s) { ws->theme_code_colors[s] = ui_color_from_name(rd_code_color_slot_name_table[s]); } //////////////////////////// //- rjf: @window_ui_part calculate top-level rectangles/sizes // Rng2F32 window_rect = os_client_rect_from_window(ws->os); Vec2F32 window_rect_dim = dim_2f32(window_rect); F32 top_bar_dim_px = floor_f32(ui_top_font_size()*3.f); Rng2F32 top_bar_rect = r2f32p(window_rect.x0, window_rect.y0, window_rect.x0+window_rect_dim.x+1, window_rect.y0+top_bar_dim_px); Rng2F32 bottom_bar_rect = r2f32p(window_rect.x0, window_rect_dim.y - top_bar_dim_px, window_rect.x0+window_rect_dim.x, window_rect.y0+window_rect_dim.y); Rng2F32 content_rect = r2f32p(window_rect.x0, top_bar_rect.y1, window_rect.x0+window_rect_dim.x, bottom_bar_rect.y0); F32 window_edge_px = os_dpi_from_window(ws->os)*0.035f; content_rect = pad_2f32(content_rect, -window_edge_px); //////////////////////////// //- rjf: @window_ui_part truncated string hover // if(ui_string_hover_active()) UI_Tooltip { Temp scratch = scratch_begin(0, 0); DR_FStrList fstrs = ui_string_hover_fstrs(scratch.arena); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); scratch_end(scratch); } //////////////////////////// //- rjf: @window_ui_part rich hover / drag/drop tooltips // if((rd_state->hover_regs_slot != RD_RegSlot_Null && !rd_state->hover_regs->no_rich_tooltip) || (rd_state->drag_drop_regs_slot != RD_RegSlot_Null && rd_drag_is_active())) { Temp scratch = scratch_begin(0, 0); RD_RegSlot slot = ((rd_state->drag_drop_regs_slot != RD_RegSlot_Null && rd_drag_is_active()) ? rd_state->drag_drop_regs_slot : rd_state->hover_regs_slot); RD_Regs *regs = (((rd_state->drag_drop_regs_slot != RD_RegSlot_Null && rd_drag_is_active()) ? rd_state->drag_drop_regs : rd_state->hover_regs)); CTRL_Entity *ctrl_entity = &ctrl_entity_nil; ui_state->tooltip_anchor_key = regs->ui_key; ui_state->tooltip_can_overflow_window = rd_drag_is_active(); switch(slot) { default:{}break; //////////////////////// //- rjf: command tooltips // case RD_RegSlot_CmdName: UI_Tooltip { String8 cmd_name = regs->cmd_name; DR_FStrList fstrs = rd_title_fstrs_from_code_name(scratch.arena, cmd_name); UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(5, 1)) { UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); rd_cmd_binding_buttons(cmd_name, str8_zero(), 0); } }break; //////////////////////// //- rjf: file path tooltips // case RD_RegSlot_FilePath: UI_Tooltip { FileProperties props = os_properties_from_file_path(regs->file_path); ui_set_next_pref_width(ui_children_sum(1)); UI_Row { RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[props.flags & FilePropertyFlag_IsFolder ? RD_IconKind_FolderClosedFilled : RD_IconKind_FileOutline]); ui_label(regs->file_path); } }break; //////////////////////// //- rjf: cfg tooltips // case RD_RegSlot_Cfg: UI_Tooltip { // rjf: unpack CFG_Node *cfg = cfg_node_from_id(regs->cfg); DR_FStrList fstrs = rd_title_fstrs_from_cfg(scratch.arena, cfg, 0); // rjf: title UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(5, 1)) { UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); } }break; //////////////////////// //- rjf: control entity tooltips // case RD_RegSlot_Machine: {ctrl_entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, regs->machine); }goto ctrl_entity_tooltip; case RD_RegSlot_Process: {ctrl_entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, regs->process); }goto ctrl_entity_tooltip; case RD_RegSlot_Module: {ctrl_entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, regs->module); }goto ctrl_entity_tooltip; case RD_RegSlot_Thread: {ctrl_entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, regs->thread); }goto ctrl_entity_tooltip; case RD_RegSlot_CtrlEntity:{ctrl_entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, regs->ctrl_entity); }goto ctrl_entity_tooltip; ctrl_entity_tooltip:; UI_Tooltip { // rjf: unpack Arch arch = ctrl_entity->arch; String8 arch_str = string_from_arch(arch); DR_FStrList fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, ctrl_entity, 0); // rjf: title UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(5, 1)) { UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); ui_spacer(ui_em(0.5f, 1.f)); UI_FontSize(ui_top_font_size() - 1.f) UI_CornerRadius(ui_top_font_size()*0.5f) { UI_TagF("weak") UI_FlagsAdd(UI_BoxFlag_DrawBorder) ui_label(arch_str); ui_spacer(ui_em(0.5f, 1.f)); if(ctrl_entity->kind == CTRL_EntityKind_Thread || ctrl_entity->kind == CTRL_EntityKind_Process) { UI_TagF("weak") UI_FlagsAdd(UI_BoxFlag_DrawBorder) ui_labelf("ID: %i", (U32)ctrl_entity->id); } } } // rjf: debug info status if(ctrl_entity->kind == CTRL_EntityKind_Module) UI_TagF("weak") { Access *access = access_open(); CTRL_Entity *dbg_info_entity = ctrl_entity_child_from_kind(ctrl_entity, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = ctrl_dbgi_key_from_module(ctrl_entity); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); if(rdi->raw_data_size != 0) { ui_labelf("Debug information successfully loaded from %S", dbg_info_entity->string); } else if(dbg_info_entity->string.size != 0) { ui_labelf("Debug information not found at %S", dbg_info_entity->string); } else if(dbg_info_entity->string.size == 0) { ui_labelf("Debug information location not found in module file"); } access_close(access); } // rjf: unwind if(ctrl_entity->kind == CTRL_EntityKind_Thread) RD_Font(RD_FontSlot_Code) { Access *access = access_open(); Vec4F32 code_color = ui_color_from_name(str8_lit("code_default")); Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(ctrl_entity, CTRL_EntityKind_Process); B32 call_stack_high_priority = ctrl_handle_match(ctrl_entity->handle, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, ctrl_entity->handle, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); if(call_stack.frames_count != 0) { ui_spacer(ui_em(1.5f, 1.f)); } EV_StringParams string_params = {EV_StringFlag_ReadOnlyDisplayRules, .radix = 16}; String8 thread_handle_string = ctrl_string_from_handle(scratch.arena, ctrl_entity->handle); for(U64 idx = 0; idx < 16; idx += 1) { E_Eval rip_eval = e_eval_from_stringf("query:control.%S.call_stack[%I64u]", thread_handle_string, idx); if(rip_eval.irtree.mode != E_Mode_Value) { break; } String8 rip_value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), &string_params, ui_top_font(), ui_top_font_size(), ui_top_font_size()*40.f, rip_eval); rd_code_label(1, 0, code_color, rip_value_string); } access_close(access); } }break; //////////////////////// //- rjf: expression tooltips // case RD_RegSlot_Expr: UI_Tooltip RD_Font(RD_FontSlot_Code) { ui_set_next_pref_width(ui_children_sum(1)); UI_Row { rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), rd_state->drag_drop_regs->expr); E_Eval eval = e_eval_from_string(rd_state->drag_drop_regs->expr); if(eval.irtree.mode != E_Mode_Null) { EV_StringParams string_params = {.flags = EV_StringFlag_ReadOnlyDisplayRules, .radix = 10}; String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), &string_params, ui_top_font(), ui_top_font_size(), ui_top_font_size()*20.f, eval); if(value_string.size != 0) { ui_spacer(ui_em(2.f, 1.f)); rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); } } } }break; } scratch_end(scratch); } //////////////////////////// //- rjf: @window_ui_part drag/drop visualization tooltips // if(rd_drag_is_active() && window_is_focused) RD_RegsScope(.window = rd_state->drag_drop_regs->window, .panel = rd_state->drag_drop_regs->panel, .tab = 0, .view = rd_state->drag_drop_regs->view) { Temp scratch = scratch_begin(0, 0); CFG_Node *view = cfg_node_from_id(rd_state->drag_drop_regs->view); { //- rjf: tab dragging if(rd_state->drag_drop_regs_slot == RD_RegSlot_View && view != &cfg_nil_node) { CFG_Node *immediate_parent = &cfg_nil_node; for(CFG_Node *p = view->parent; p != &cfg_nil_node; p = p->parent) { if(str8_match(p->parent->string, str8_lit("immediate"), 0)) { immediate_parent = p->parent; break; } } if(immediate_parent != &cfg_nil_node) { cfg_node_child_from_string_or_alloc(rd_state->cfg, immediate_parent, str8_lit("hot")); } UI_Size main_width = ui_top_pref_width(); UI_Size main_height = ui_top_pref_height(); UI_TextAlign main_text_align = ui_top_text_alignment(); UI_Tooltip UI_PrefWidth(main_width) UI_PrefHeight(main_height) UI_TextAlignment(main_text_align) { ui_state->tooltip_can_overflow_window = 1; ui_set_next_pref_width(ui_em(60.f, 1.f)); ui_set_next_pref_height(ui_em(40.f, 1.f)); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *container = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(container) { UI_Row UI_PrefWidth(ui_text_dim(10, 1)) { DR_FStrList fstrs = rd_title_fstrs_from_cfg(scratch.arena, view, 0); UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(name_box, &fstrs); } ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *view_preview_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_preview_container"); UI_Parent(view_preview_container) UI_Focus(UI_FocusKind_Off) UI_WidthFill { rd_view_ui(view_preview_container->rect); } } } } } scratch_end(scratch); } //////////////////////////// //- rjf: @window_ui_part developer menu // if(ws->dev_menu_is_open) RD_Font(RD_FontSlot_Code) { ui_set_next_flags(UI_BoxFlag_ViewScrollY|UI_BoxFlag_AllowOverflowY|UI_BoxFlag_ViewClamp); UI_PaneF(r2f32p(30, 30, 30+ui_top_font_size()*100, ui_top_font_size()*60), "###dev_ctx_menu") { //- rjf: capture if(!ProfIsCapturing() && ui_clicked(ui_buttonf("Begin Profiler Capture###prof_cap"))) { ProfBeginCapture("raddbg"); } else if(ProfIsCapturing() && ui_clicked(ui_buttonf("End Profiler Capture###prof_cap"))) { ProfEndCapture(); } //- rjf: toggles for(U64 idx = 0; idx < ArrayCount(DEV_toggle_table); idx += 1) { if(ui_clicked(rd_icon_button(*DEV_toggle_table[idx].value_ptr ? RD_IconKind_CheckFilled : RD_IconKind_CheckHollow, 0, DEV_toggle_table[idx].name))) { *DEV_toggle_table[idx].value_ptr ^= 1; } } ui_divider(ui_em(1.f, 1.f)); //- rjf: draw registers ui_labelf("hover_reg_slot: %i", rd_state->hover_regs_slot); struct { String8 name; RD_Regs *regs; } regs_info[] = { {str8_lit("regs"), rd_regs()}, {str8_lit("hover_regs"), rd_state->hover_regs}, }; for EachElement(idx, regs_info) { ui_divider(ui_em(1.f, 1.f)); ui_label(regs_info[idx].name); RD_Regs *regs = regs_info[idx].regs; #define ID(name) ui_labelf("%s: $0x%I64x", #name, (regs->name)) ID(window); ID(panel); ID(view); #undef ID #define Handle(name) ui_labelf("%s: [0x%I64x, 0x%I64x]", #name, (regs->name).machine_id, (regs->name).dmn_handle.u64[0]) Handle(machine); Handle(process); Handle(module); Handle(thread); #undef Handle ui_labelf("file_path: \"%S\"", regs->file_path); ui_labelf("cursor: (L:%I64d, C:%I64d)", regs->cursor.line, regs->cursor.column); ui_labelf("mark: (L:%I64d, C:%I64d)", regs->mark.line, regs->mark.column); ui_labelf("unwind_count: %I64u", regs->unwind_count); ui_labelf("inline_depth: %I64u", regs->inline_depth); ui_labelf("text_key: [0x%I64x / 0x%I64x:0x%I64x]", regs->text_key.root.u64[0], regs->text_key.id.u128[0].u64[0], regs->text_key.id.u128[0].u64[1]); ui_labelf("lang_kind: '%S'", txt_extension_from_lang_kind(regs->lang_kind)); ui_labelf("vaddr_range: [0x%I64x, 0x%I64x)", regs->vaddr_range.min, regs->vaddr_range.max); ui_labelf("voff_range: [0x%I64x, 0x%I64x)", regs->voff_range.min, regs->voff_range.max); } ui_divider(ui_em(1.f, 1.f)); //- rjf: draw per-window stats for(RD_WindowState *w = rd_state->first_window_state; w != &rd_nil_window_state; w = w->order_next) { // rjf: calc ui hash chain length F64 avg_ui_hash_chain_length = 0; { F64 chain_count = 0; F64 chain_length_sum = 0; for(U64 idx = 0; idx < w->ui->box_table_size; idx += 1) { F64 chain_length = 0; for(UI_Box *b = w->ui->box_table[idx].hash_first; !ui_box_is_nil(b); b = b->hash_next) { chain_length += 1; } if(chain_length > 0) { chain_length_sum += chain_length; chain_count += 1; } } avg_ui_hash_chain_length = chain_length_sum / chain_count; } ui_labelf("Target Hz: %.2f", 1.f/rd_state->frame_dt); ui_labelf("Ctrl Run Index: %I64u", ctrl_run_gen()); ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_mem_gen()); ui_labelf("Window %p", w); ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_pref_height(ui_children_sum(1)); UI_Row { ui_spacer(ui_em(2.f, 1.f)); ui_labelf("Box Count: %I64u", w->ui->last_build_box_count); } ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_pref_height(ui_children_sum(1)); UI_Row { ui_spacer(ui_em(2.f, 1.f)); ui_labelf("Average UI Hash Chain Length: %f", avg_ui_hash_chain_length); } } ui_divider(ui_em(1.f, 1.f)); } } //////////////////////////// //- rjf: @window_ui_part drop-completion context menu // if(ws->top_drop_completion_task != 0) { RD_DropCompletionTask *task = ws->top_drop_completion_task; B32 done = 0; UI_CtxMenu(rd_state->drop_completion_key) UI_PrefWidth(ui_em(40.f, 1.f)) UI_TagF("implicit") { // rjf: file names UI_TagF("weak") UI_Row UI_Padding(ui_em(1.25f, 1.f)) { String8List strings = {0}; U64 idx = 0; for(String8Node *n = task->paths.first; n != 0 && idx < 20; n = n->next, idx += 1) { str8_list_push(scratch.arena, &strings, str8_skip_last_slash(n->string)); if(idx+1 == 20) { str8_list_push(scratch.arena, &strings, str8_lit("...")); } } StringJoin join = {.sep = str8_lit(", ")}; String8 string = str8_list_join(scratch.arena, &strings, &join); UI_PrefWidth(ui_pct(1, 0)) ui_label(string); } // rjf: option to add EXEs as targets if(task->exe) { if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "Add as target%s", (task->paths.node_count > 1) ? "s" : ""))) { for(String8Node *n = task->paths.first; n != 0; n = n->next) { rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string); } done = 1; } } // rjf: option to load files as debug info if(task->dbg) { if(ui_clicked(rd_icon_buttonf(RD_IconKind_Module, 0, "Load as debug info"))) { for(String8Node *n = task->paths.first; n != 0; n = n->next) { rd_cmd(RD_CmdKind_LoadDebugInfo, .file_path = n->string); } done = 1; } } // rjf: option to just open & view the file contents if(ui_clicked(rd_icon_buttonf(RD_IconKind_FileOutline, 0, "View file%s contents", (task->paths.node_count > 1) ? "s'" : ""))) { for(String8Node *n = task->paths.first; n != 0; n = n->next) { rd_cmd(RD_CmdKind_Open, .file_path = n->string); } done = 1; } } // rjf: pop task, close context menu if needed, when done if(done) { SLLStackPop(ws->top_drop_completion_task); if(ws->top_drop_completion_task == 0) { ui_ctx_menu_close(); } } } //////////////////////////// //- rjf: @window_ui_part popup // { if(rd_state->popup_t > 0.005f) UI_TextAlignment(UI_TextAlign_Center) UI_Focus(rd_state->popup_active ? UI_FocusKind_Root : UI_FocusKind_Off) { Vec2F32 window_dim = dim_2f32(window_rect); UI_Box *bg_box = &ui_nil_box; UI_Rect(window_rect) UI_ChildLayoutAxis(Axis2_X) UI_Focus(UI_FocusKind_On) UI_BlurSize(10*rd_state->popup_t) UI_Transparency(1-rd_state->popup_t) UI_TagF("floating") { bg_box = ui_build_box_from_stringf(UI_BoxFlag_FixedSize| UI_BoxFlag_Floating| UI_BoxFlag_Clickable| UI_BoxFlag_Scroll| UI_BoxFlag_DefaultFocusNav| UI_BoxFlag_DisableFocusOverlay| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_DrawBackground, "###popup_%p", ws); } if(rd_state->popup_active) UI_Parent(bg_box) UI_Transparency(1-rd_state->popup_t) { ui_ctx_menu_close(); UI_WidthFill UI_PrefHeight(ui_children_sum(1.f)) UI_Column UI_Padding(ui_pct(1, 0)) { UI_TextRasterFlags(rd_raster_flags_from_slot(RD_FontSlot_Main)) UI_FontSize(ui_top_font_size()*2.f) UI_PrefHeight(ui_em(3.f, 1.f)) ui_label(rd_state->popup_title); UI_PrefHeight(ui_em(3.f, 1.f)) UI_TagF("weak") ui_label(rd_state->popup_desc); ui_spacer(ui_em(1.5f, 1.f)); UI_Row UI_Padding(ui_pct(1.f, 0.f)) UI_PrefWidth(ui_em(16.f, 1.f)) UI_PrefHeight(ui_em(3.5f, 1.f)) UI_CornerRadius(ui_top_font_size()*0.5f) { UI_TagF("pop") if(ui_clicked(ui_buttonf("OK")) || (ui_key_match(bg_box->default_nav_focus_hot_key, ui_key_zero()) && ui_slot_press(UI_EventActionSlot_Accept))) { rd_cmd(RD_CmdKind_PopupAccept); } ui_spacer(ui_em(1.f, 1.f)); if(ui_clicked(ui_buttonf("Cancel")) || ui_slot_press(UI_EventActionSlot_Cancel)) { rd_cmd(RD_CmdKind_PopupCancel); } } ui_spacer(ui_em(3.f, 1.f)); } } ui_signal_from_box(bg_box); } } //////////////////////////// //- rjf: @window_ui_part build autocompletion callee info helper // F32 autocomp_callee_helper_height_px = 0; if(rd_setting_b32_from_name(str8_lit("view_call_argument_helper")) && ws->autocomp_regs != 0 && ws->autocomp_last_frame_index+1 >= rd_state->frame_index && ws->autocomp_cursor_info.callee_expr.size != 0) { E_Eval eval = e_eval_from_string(ws->autocomp_cursor_info.callee_expr); E_Type *type = e_type_from_key(eval.irtree.type_key); if(type->kind == E_TypeKind_LensSpec) UI_TagF("floating") { F32 open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "autocomp_callee_helper_t"), 1.f, .rate = rd_state->menu_animation_rate); //- rjf: determine rects/sizes F32 row_height_px = ui_top_font_size()*2.f; F32 padding_px = ui_top_font_size()*1.f; Vec2F32 callee_helper_pos = {0}; { UI_Box *anchor_box = ui_box_from_key(ws->autocomp_regs->ui_key); callee_helper_pos.x = anchor_box->rect.x0; callee_helper_pos.y = anchor_box->rect.y1; } F32 height_px_target = row_height_px*1.f + padding_px*2.f; autocomp_callee_helper_height_px = height_px_target * open_t; //- rjf: build top-level callee helper box UI_Box *callee_helper = &ui_nil_box; UI_FixedPos(callee_helper_pos) UI_Squish(0.1f-0.1f*open_t) UI_Transparency(1.f-open_t) UI_CornerRadius(ui_top_font_size()*0.25f) UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_px(height_px_target, 1.f)) { callee_helper = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_SquishAnchored|UI_BoxFlag_Clickable, "top_level_window_callee_helper"); } //- rjf: fill helper UI_Parent(callee_helper) UI_Padding(ui_px(padding_px, 1.f)) UI_PrefWidth(ui_children_sum(1)) UI_HeightFill UI_Column UI_PrefHeight(ui_px(row_height_px, 1.f)) UI_Padding(ui_px(padding_px, 1.f)) { // rjf: main name / args text UI_Row UI_TextPadding(0) UI_PrefWidth(ui_text_dim(0, 1)) RD_Font(RD_FontSlot_Code) { Vec4F32 code_default = ui_color_from_name(str8_lit("code_default")); String8 opener = push_str8f(scratch.arena, "%S(", type->name); rd_code_label(1, 0, code_default, opener); MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, type->name); B32 first = 1; UI_TagF(".") for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { for MD_EachNode(child, n->v->first) { if(md_node_has_tag(child, str8_lit("no_callee_helper"), 0)) { continue; } if(!first) { rd_code_label(1, 0, code_default, str8_lit(", ")); } first = 0; UI_Key arg_key = ui_key_from_stringf(ui_active_seed_key(), "###arg_%p", child); DR_FStrList arg_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, code_default, child->string); if(child == ws->autocomp_cursor_info.arg_schema) { ui_set_next_flags(UI_BoxFlag_DrawSideBottom); ui_set_next_tag(str8_lit("good_pop")); } UI_Box *arg_box = ui_build_box_from_key(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable|UI_BoxFlag_DrawHotEffects, arg_key); ui_box_equip_display_fstrs(arg_box, &arg_fstrs); UI_Signal arg_sig = ui_signal_from_box(arg_box); if(ui_hovering(arg_sig)) { String8 display_name = md_tag_from_string(child, str8_lit("display_name"), 0)->first->string; String8 desc = md_tag_from_string(child, str8_lit("description"), 0)->first->string; if(desc.size != 0) UI_Tooltip RD_Font(RD_FontSlot_Main) { ui_state->tooltip_anchor_key = arg_box->key; UI_Row { RD_Font(RD_FontSlot_Code) ui_label(child->string); if(display_name.size != 0) { ui_spacer(ui_em(0.5f, 1.f)); UI_TagF("weak") ui_label(display_name); } } UI_TagF("weak") ui_label(desc); } } } } rd_code_label(1, 0, code_default, str8_lit(")")); } } //- rjf: fall-through interactions with helper UI_Signal sig = ui_signal_from_box(callee_helper); (void)sig; } } //////////////////////////// //- rjf: @window_ui_part gather all tasks to build floating views // typedef struct FloatingViewTask FloatingViewTask; struct FloatingViewTask { FloatingViewTask *next; CFG_Node *view; RD_Regs *regs; Rng2F32 rect; B32 is_focused; B32 is_anchored; B32 force_inside_window_x; B32 force_inside_window_y; B32 only_secondary_navigation; B32 reset_open; UI_Signal signal; // NOTE(rjf): output, from build B32 pressed; B32 pressed_outside; }; FloatingViewTask *autocomp_floating_view_task = 0; FloatingViewTask *hover_eval_floating_view_task = 0; FloatingViewTask *query_floating_view_task = 0; FloatingViewTask *first_floating_view_task = 0; FloatingViewTask *last_floating_view_task = 0; RD_Font(RD_FontSlot_Code) { //- rjf: add autocompletion view task if(ws->autocomp_regs != 0 && ws->autocomp_last_frame_index+1 >= rd_state->frame_index) { // rjf: build view CFG_Node *root = rd_immediate_cfg_from_keyf("autocomp_view_%I64x", window->id); CFG_Node *view = cfg_node_child_from_string_or_alloc(rd_state->cfg, root, str8_lit("watch")); cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("autocomplete")); CFG_Node *query = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("query")); CFG_Node *input = cfg_node_child_from_string_or_alloc(rd_state->cfg, query, str8_lit("input")); cfg_node_new_replace(rd_state->cfg, input, ws->autocomp_cursor_info.filter); CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, ws->autocomp_cursor_info.list_expr); // rjf: determine container size EV_BlockTree predicted_block_tree = {0}; RD_RegsScope(.view = view->id, .tab = 0) { String8 expr = rd_expr_from_cfg(view); E_Eval list_eval = e_eval_from_string(expr); ev_key_set_expansion(rd_view_eval_view(), ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); predicted_block_tree = ev_block_tree_from_eval(scratch.arena, rd_view_eval_view(), rd_view_query_input(), list_eval); } F32 row_height_px = ui_top_px_height(); U64 max_row_count = (U64)floor_f32(ui_top_font_size()*30.f / row_height_px); U64 needed_row_count = Min(max_row_count, predicted_block_tree.total_row_count - 1); F32 width_px = floor_f32(30.f*ui_top_font_size()); F32 height_px = needed_row_count*row_height_px; // rjf: determine list top-level rect Rng2F32 rect = r2f32p(0, 0, 0, 0); if(!ui_key_match(ui_key_zero(), ws->autocomp_regs->ui_key)) { UI_Box *anchor_box = ui_box_from_key(ws->autocomp_regs->ui_key); rect.x0 = anchor_box->rect.x0; rect.y0 = anchor_box->rect.y1 + autocomp_callee_helper_height_px; rect.x1 = rect.x0 + width_px; rect.y1 = rect.y0 + height_px; } // rjf: push task if(predicted_block_tree.total_row_count > 1) { FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1); SLLQueuePush(first_floating_view_task, last_floating_view_task, t); autocomp_floating_view_task = t; t->view = view; t->rect = rect; t->is_focused = 1; t->is_anchored = 1; t->only_secondary_navigation = 1; } } //- rjf: try to add hover eval { B32 build_hover_eval = (hover_eval_is_open && !rd_drag_is_active()); // rjf: disable hover eval if hovered view is actively scrolling if(hover_eval_is_open) { for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } CFG_Node *tab = panel->selected_tab; if(tab != &cfg_nil_node) { RD_ViewState *vs = rd_view_state_from_cfg(tab); Rng2F32 panel_rect = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); if(contains_2f32(panel_rect, ui_mouse()) && (abs_f32(vs->scroll_pos.x.off) > 0.01f || abs_f32(vs->scroll_pos.y.off) > 0.01f)) { build_hover_eval = 0; ws->hover_eval_firstt_us = rd_state->time_in_us; } } } } // rjf: choose hover evaluation expression String8 hover_eval_expr = ws->hover_eval_string; // rjf: evaluate hover evaluation expression, & determine if it evaluates // such that we want to build a hover eval. E_Eval hover_eval = e_eval_from_string(hover_eval_expr); { if(hover_eval.msgs.max_kind > E_MsgKind_Null) { build_hover_eval = 0; } else if(hover_eval.space.kind == RD_EvalSpaceKind_MetaCfg && rd_cfg_from_eval_space(hover_eval.space) == &cfg_nil_node) { build_hover_eval = 0; } else if((hover_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || hover_eval.space.kind == CTRL_EvalSpaceKind_Entity) && rd_ctrl_entity_from_eval_space(hover_eval.space) == &ctrl_entity_nil) { build_hover_eval = 0; } } // rjf: request frames if we're waiting to open if(ws->hover_eval_string.size != 0 && !hover_eval_is_open && ws->hover_eval_lastt_us < ws->hover_eval_firstt_us+hover_eval_open_delay_us && rd_state->time_in_us - ws->hover_eval_lastt_us < hover_eval_open_delay_us*2) { rd_request_frame(); } // rjf: build hover eval task if(build_hover_eval) { // rjf: determine if we have a top-level visualizer EV_ExpandRule *expand_rule = ev_expand_rule_from_type_key(hover_eval.irtree.type_key); RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(expand_rule->string); // rjf: build view CFG_Node *root = rd_immediate_cfg_from_keyf("hover_eval_view_%I64x", ws->cfg_id); CFG_Node *view = rd_view_from_eval(root, hover_eval); cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("explicit_root")); // rjf: determine size of hover evaluation container EV_BlockTree predicted_block_tree = {0}; RD_RegsScope(.view = view->id, .tab = 0) { ev_key_set_expansion(rd_view_eval_view(), ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); predicted_block_tree = ev_block_tree_from_eval(scratch.arena, rd_view_eval_view(), str8_zero(), hover_eval); } F32 row_height_px = floor_f32(ui_top_font_size()*rd_setting_f32_from_name(str8_lit("row_height"))); U64 max_row_count = 12; U64 needed_row_count = Min(max_row_count, predicted_block_tree.total_row_count); F32 width_px = floor_f32(70.f*ui_top_font_size()); F32 height_px = needed_row_count*row_height_px; // rjf: if arbitrary visualizer, pick catchall size if(view_ui_rule != &rd_nil_view_ui_rule) { height_px = floor_f32(40.f*ui_top_font_size()); } // rjf: determine hover eval top-level rect Rng2F32 rect = r2f32p(ws->hover_eval_spawn_pos.x, ws->hover_eval_spawn_pos.y, ws->hover_eval_spawn_pos.x + width_px, ws->hover_eval_spawn_pos.y + height_px); // rjf: push hover eval task { FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1); SLLQueuePush(first_floating_view_task, last_floating_view_task, t); hover_eval_floating_view_task = t; t->view = view; t->rect = rect; t->is_focused = ws->hover_eval_focused; t->is_anchored = 1; t->force_inside_window_x = 1; } } // rjf: reset focus state if hover eval is not being built if(!build_hover_eval || ws->hover_eval_string.size == 0 || !hover_eval_is_open) { ws->hover_eval_focused = 0; } } //- rjf: force-close query, if it's anchored, but box is gone if(query_is_open) { UI_Box *box = ui_box_from_key(ws->query_regs->ui_key); if(!ui_key_match(ui_key_zero(), ws->query_regs->ui_key) && ui_box_is_nil(box)) { query_is_open = 0; rd_cmd(RD_CmdKind_CancelQuery); } } //- rjf: force-close query, if it has an expression, but that expression does not evaluate if(query_is_open) { String8 expr = ws->query_regs->expr; E_Eval eval = e_eval_from_string(expr); if(eval.msgs.max_kind > E_MsgKind_Null) { query_is_open = 0; rd_cmd(RD_CmdKind_CancelQuery); } else if(eval.space.kind == RD_EvalSpaceKind_MetaCfg && rd_cfg_from_eval_space(eval.space) == &cfg_nil_node) { query_is_open = 0; rd_cmd(RD_CmdKind_CancelQuery); } else if((eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || eval.space.kind == CTRL_EvalSpaceKind_Entity) && rd_ctrl_entity_from_eval_space(eval.space) == &ctrl_entity_nil) { query_is_open = 0; rd_cmd(RD_CmdKind_CancelQuery); } } //- rjf: try to add opened query if(query_is_open) { // rjf: unpack view for query CFG_Node *root = rd_immediate_cfg_from_keyf("window_query_%p", window); CFG_Node *view = cfg_node_child_from_string_or_alloc(rd_state->cfg, root, str8_lit("watch")); CFG_Node *query = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("query")); B32 is_lister = (cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node); B32 root_is_explicit = (cfg_node_child_from_string(view, str8_lit("explicit_root")) != &cfg_nil_node); RD_ViewState *vs = rd_view_state_from_cfg(view); // rjf: did this view ID change? -> reset open animation B32 reset_open = 0; if(view->id != ws->query_last_view_id) { ws->query_last_view_id = view->id; reset_open = 1; } // rjf: unpack query info String8 cmd_name = ws->query_regs->cmd_name; RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); String8 query_expr = ws->query_regs->expr; if(query_expr.size == 0 && cmd_name.size != 0) { query_expr = cmd_kind_info->query.expr; } B32 query_is_anchored = (!ui_box_is_nil(ui_box_from_key(ws->query_regs->ui_key))); B32 size_query_by_expr_eval = (query_is_anchored || query_expr.size == 0); // rjf: compute query expression if(query_expr.size == 0) { query_expr = str8(vs->query_buffer, vs->query_string_size); } else { U64 input_insertion_pos = str8_find_needle(query_expr, 0, str8_lit("$input"), 0); if(input_insertion_pos < query_expr.size) { String8 pre_insertion = str8_prefix(query_expr, input_insertion_pos); String8 post_insertion = str8_skip(query_expr, input_insertion_pos + 6); String8 input_text = str8(vs->query_buffer, vs->query_string_size); String8 input_text__escaped = escaped_from_raw_str8(scratch.arena, input_text); // TODO(rjf): @hack need to escape because this is putting the user's input // into a containing "folder:"..."" in all cases. but this is kinda shady // and should be replaced long-term with something more solid... query_expr = push_str8f(scratch.arena, "%S%S%S", pre_insertion, input_text__escaped, post_insertion); } } // rjf: store expression CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, query_expr); // rjf: evaluate query expression E_Eval query_eval = e_eval_from_string(query_expr); // rjf: determine & store row-height setting if(ws->query_regs->do_big_rows) { F32 row_height = 5.f; F32 row_height_px = row_height * ui_top_font_size(); CFG_Node *row_height_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("row_height")); cfg_node_new_replacef(rd_state->cfg, row_height_root, "%f", row_height); } // rjf: compute query view's top-level rectangle Rng2F32 rect = {0}; RD_RegsScope(.view = view->id, .tab = 0) { F32 row_height_px = ui_top_font_size() * rd_setting_f32_from_name(str8_lit("row_height")); Vec2F32 content_rect_center = center_2f32(content_rect); Vec2F32 content_rect_dim = dim_2f32(content_rect); ev_key_set_expansion(rd_view_eval_view(), ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); EV_BlockTree predicted_block_tree = ev_block_tree_from_eval(scratch.arena, rd_view_eval_view(), rd_view_query_input(), query_eval); F32 query_width_px = floor_f32(content_rect_dim.x * 0.35f); F32 max_query_height_px = content_rect_dim.y*0.8f; F32 query_height_px = max_query_height_px; if(size_query_by_expr_eval) { F32 search_row_open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "search_row_open_%p", view), (F32)!!vs->query_is_open, .initial = (F32)!!vs->query_is_open, .epsilon = 0.01f, .rate = rd_state->menu_animation_rate); query_height_px = row_height_px * (predicted_block_tree.total_row_count - !root_is_explicit) + ui_top_px_height()*search_row_open_t; query_height_px = Min(query_height_px, max_query_height_px); } rect = r2f32p(content_rect_center.x - query_width_px/2, content_rect_center.y - max_query_height_px/2.f, content_rect_center.x + query_width_px/2, content_rect_center.y - max_query_height_px/2.f + query_height_px); if(!ui_key_match(ui_key_zero(), ws->query_regs->ui_key)) { UI_Box *anchor_box = ui_box_from_key(ws->query_regs->ui_key); if(anchor_box != &ui_nil_box) { rect.x0 = anchor_box->rect.x0 + ws->query_regs->off_px.x; rect.y0 = anchor_box->rect.y1 + ws->query_regs->off_px.y; rect.x1 = rect.x0 + ui_top_font_size()*60.f; rect.y1 = rect.y0 + query_height_px; } } } // rjf: push query task { FloatingViewTask *t = push_array(scratch.arena, FloatingViewTask, 1); SLLQueuePush(first_floating_view_task, last_floating_view_task, t); query_floating_view_task = t; t->view = view; t->regs = ws->query_regs; t->rect = rect; t->is_focused = 1; t->is_anchored = query_is_anchored; t->reset_open = reset_open; t->force_inside_window_x = 1; t->force_inside_window_y = 1; } } } //////////////////////////// //- rjf: @window_ui_part build all floating views // ProfScope("build all floating views") RD_Font(RD_FontSlot_Code) UI_TagF("floating") UI_Focus(ui_any_ctx_menu_is_open() || ws->menu_bar_focused ? UI_FocusKind_Off : UI_FocusKind_Null) { F32 fast_open_rate = rd_state->menu_animation_rate; F32 slow_open_rate = rd_state->menu_animation_rate__slow; for(FloatingViewTask *t = first_floating_view_task; t != 0; t = t->next) { // rjf: unpack CFG_Node *view = t->view; Rng2F32 rect = t->rect; B32 is_focused = t->is_focused; B32 is_anchored = t->is_anchored; B32 only_secondary_navigation = t->only_secondary_navigation; F32 open_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "floating_view_open_%p", view), 1.f, .rate = is_anchored ? fast_open_rate : slow_open_rate, .reset = t->reset_open, .initial = 0.f); // rjf: force rect inside window if needed if(t->force_inside_window_x || t->force_inside_window_y) { B32 axis_mask[] = {t->force_inside_window_x, t->force_inside_window_y}; Rng2F32 window_rect = os_client_rect_from_window(ws->os); for EachEnumVal(Axis2, axis) { if(!axis_mask[axis]) { continue; } F32 max_delta = rect.p1.v[axis] - window_rect.p1.v[axis]; F32 min_delta = window_rect.p0.v[axis] - rect.p0.v[axis]; F32 total_delta = Max(min_delta, 0) - Max(max_delta, 0); rect.p0.v[axis] += total_delta; rect.p1.v[axis] += total_delta; } } // rjf: push view regs rd_push_regs(); { if(t->regs != 0) { rd_regs()->cfg = t->regs->cfg; } rd_regs()->view = view->id; String8 view_expr = rd_expr_from_cfg(view); String8 view_file_path = rd_file_path_from_eval_string(rd_frame_arena(), view_expr); // NOTE(rjf): we want to only fill out this view's file path slot if it // evaluates one - this way, a view can use the slot to know the selected // file path (if there is one). this is useful when pushing commandas which // apply to a cursor, for example. if(view_file_path.size != 0) { rd_regs()->file_path = view_file_path; } } // rjf: build UI_Focus(is_focused ? UI_FocusKind_On : UI_FocusKind_Off) UI_PermissionFlags(only_secondary_navigation ? UI_PermissionFlag_KeyboardSecondary|UI_PermissionFlag_Clicks|UI_PermissionFlag_ScrollX|UI_PermissionFlag_ScrollY : UI_PermissionFlag_All) { // rjf: build top-level container box UI_Box *container = &ui_nil_box; UI_Rect(rect) UI_ChildLayoutAxis(Axis2_Y) UI_Squish(0.1f-0.1f*open_t) UI_Transparency(1.f-open_t) UI_CornerRadius(ui_top_font_size()*0.25f) { container = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_RoundChildrenByParent| UI_BoxFlag_DisableFocusOverlay| UI_BoxFlag_DrawDropShadow| (UI_BoxFlag_SquishAnchored*!!is_anchored), "floating_view_container_%p", view); } // rjf: peek press inside/outside events { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && evt->key == OS_Key_LeftMouseButton) { if(contains_2f32(container->rect, evt->pos)) { t->pressed = 1; } else { t->pressed_outside = 1; } } } } // rjf: build overlay container for loading animation UI_Box *loading_overlay_container = &ui_nil_box; UI_Parent(container) UI_WidthFill UI_HeightFill { loading_overlay_container = ui_build_box_from_key(UI_BoxFlag_Floating, ui_key_zero()); } // rjf: build contents UI_Parent(container) UI_Focus(is_focused ? UI_FocusKind_Null : UI_FocusKind_Off) { ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *view_contents_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_contents_container"); UI_Parent(view_contents_container) UI_WidthFill { rd_view_ui(rect); } } // rjf: build loading overlay { RD_ViewState *vs = rd_view_state_from_cfg(view); F32 loading_t = vs->loading_t; if(loading_t > 0.01f) UI_Parent(loading_overlay_container) { rd_loading_overlay(rect, loading_t, vs->loading_progress_v, vs->loading_progress_v_target); } } // rjf: interact with container UI_Signal sig = ui_signal_from_box(container); t->signal = sig; } // rjf: pop interaction registers; commit if this is focused RD_Regs *view_regs = rd_pop_regs(); if(is_focused) { MemoryCopyStruct(rd_regs(), view_regs); } // rjf: is not anchored? -> darken rest of screen if(!is_anchored) { UI_TagF("inactive") UI_Transparency(1-open_t) UI_Rect(content_rect) ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_Floating, ui_key_zero()); } //- rjf: autocompletion view early-closing rules if(t == autocomp_floating_view_task) { B32 has_autocomplete_hint = ui_autocomplete_string().size != 0; B32 has_accept_operation = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && evt->slot == UI_EventActionSlot_Accept) { has_accept_operation = 1; break; } } if(has_autocomplete_hint && has_accept_operation) { autocomp_floating_view_task->signal.box->fixed_position = v2f32(10000, 10000); } } //- rjf: hover eval focus rules if(t == hover_eval_floating_view_task) { UI_Signal sig = hover_eval_floating_view_task->signal; if(ui_pressed(sig) || hover_eval_floating_view_task->pressed) { ws->hover_eval_focused = 1; } if(ui_mouse_over(sig) || ws->hover_eval_focused) { ws->hover_eval_lastt_us = rd_state->time_in_us; } else if(ws->hover_eval_lastt_us+1000000 < rd_state->time_in_us) { rd_request_frame(); } if(hover_eval_floating_view_task->pressed_outside || ui_slot_press(UI_EventActionSlot_Cancel)) { ws->hover_eval_focused = 0; MemoryZeroStruct(&ws->hover_eval_string); arena_clear(ws->hover_eval_arena); rd_request_frame(); } } //- rjf: query interactions if(t == query_floating_view_task) { CFG_Node *view = query_floating_view_task->view; RD_ViewState *vs = rd_view_state_from_cfg(query_floating_view_task->view); String8 cmd_name = ws->query_regs->cmd_name; RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); // rjf: close queries if(query_floating_view_task->pressed_outside || (cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node && !vs->query_is_open) || (cmd_name.size != 0 && !vs->query_is_open) || ui_slot_press(UI_EventActionSlot_Cancel)) { rd_cmd(RD_CmdKind_CancelQuery); } // rjf: any queries which take a file path mutate the debugger's "current path" if(cmd_kind_info->query.slot == RD_RegSlot_FilePath) { CFG_Node *query = cfg_node_child_from_string(view, str8_lit("query")); CFG_Node *input = cfg_node_child_from_string(query, str8_lit("input")); if(input != &cfg_nil_node) { String8 path_chopped = str8_chop_last_slash(input->first->string); CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *current_path = cfg_node_child_from_string_or_alloc(rd_state->cfg, user, str8_lit("current_path")); if(!str8_match(current_path->first->string, path_chopped, 0)) { rd_cmd(RD_CmdKind_SetCurrentPath, .file_path = path_chopped); } } } } } } //////////////////////////// //- rjf: @window_ui_part top bar // ProfScope("build top bar") { os_window_clear_custom_border_data(ws->os); os_window_push_custom_edges(ws->os, window_edge_px); os_window_push_custom_title_bar(ws->os, dim_2f32(top_bar_rect).y); ui_set_next_flags(UI_BoxFlag_DefaultFocusNav|UI_BoxFlag_DisableFocusOverlay); UI_Focus((ws->menu_bar_focused && window_is_focused && !ui_any_ctx_menu_is_open()) ? UI_FocusKind_On : UI_FocusKind_Null) UI_TagF("menu_bar") UI_Pane(top_bar_rect, str8_lit("###top_bar")) UI_WidthFill UI_Row UI_Focus(UI_FocusKind_Null) { UI_Key menu_bar_group_key = ui_key_from_string(ui_key_zero(), str8_lit("###top_bar_group")); MemoryZeroArray(ui_top_parent()->parent->corner_radii); //- rjf: left column { ui_set_next_flags(UI_BoxFlag_Clip|UI_BoxFlag_ViewScrollX|UI_BoxFlag_ViewClamp); UI_WidthFill UI_NamedRow(str8_lit("###menu_bar")) { //- rjf: icon UI_Padding(ui_em(0.5f, 1.f)) { UI_PrefWidth(ui_px(dim_2f32(top_bar_rect).y - ui_top_font_size()*0.8f, 1.f)) UI_Column UI_Padding(ui_em(0.4f, 1.f)) UI_HeightFill { R_Handle texture = rd_state->icon_texture; Vec2S32 texture_dim = r_size_from_tex2d(texture); ui_image(texture, R_Tex2DSampleKind_Linear, r2f32p(0, 0, texture_dim.x, texture_dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("")); } } //- rjf: menu items if(dim_2f32(top_bar_rect).x > ui_top_font_size()*60) { ui_set_next_flags(UI_BoxFlag_DrawBackground); UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(20, 1)) UI_GroupKey(menu_bar_group_key) { // rjf: file menu UI_Key file_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_file_menu_key_")); UI_CtxMenu(file_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { String8 cmds[] = { rd_cmd_kind_info_table[RD_CmdKind_Open].string, rd_cmd_kind_info_table[RD_CmdKind_Switch].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_NewUser].string, rd_cmd_kind_info_table[RD_CmdKind_OpenUser].string, rd_cmd_kind_info_table[RD_CmdKind_SaveUser].string, rd_cmd_kind_info_table[RD_CmdKind_UserSettings].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_NewProject].string, rd_cmd_kind_info_table[RD_CmdKind_OpenProject].string, rd_cmd_kind_info_table[RD_CmdKind_OpenRecentProject].string, rd_cmd_kind_info_table[RD_CmdKind_SaveProject].string, rd_cmd_kind_info_table[RD_CmdKind_ProjectSettings].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_Exit].string, }; U32 codepoints[] = { 'o', 'i', 0,//- 'w', 'u', 's', 'e', 0,//- 'j', 'p', 'r', 'a', 't', 0,//- 'x', }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); } // rjf: window menu UI_Key window_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_window_menu_key_")); UI_CtxMenu(window_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { String8 cmds[] = { rd_cmd_kind_info_table[RD_CmdKind_OpenWindow].string, rd_cmd_kind_info_table[RD_CmdKind_CloseWindow].string, rd_cmd_kind_info_table[RD_CmdKind_ToggleFullscreen].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_WindowSettings].string, }; U32 codepoints[] = { 'w', 'c', 'f', 0,//- 's', }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); } // rjf: panel menu UI_Key panel_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_panel_menu_key_")); UI_CtxMenu(panel_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { String8 cmds[] = { rd_cmd_kind_info_table[RD_CmdKind_NewPanelUp].string, rd_cmd_kind_info_table[RD_CmdKind_NewPanelDown].string, rd_cmd_kind_info_table[RD_CmdKind_NewPanelRight].string, rd_cmd_kind_info_table[RD_CmdKind_NewPanelLeft].string, rd_cmd_kind_info_table[RD_CmdKind_ClosePanel].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_NextPanel].string, rd_cmd_kind_info_table[RD_CmdKind_PrevPanel].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_TabBarTop].string, rd_cmd_kind_info_table[RD_CmdKind_TabBarBottom].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_ResetToDefaultPanels].string, rd_cmd_kind_info_table[RD_CmdKind_ResetToCompactPanels].string, rd_cmd_kind_info_table[RD_CmdKind_ResetToSimplePanels].string, }; U32 codepoints[] = { 'u', 'd', 'r', 'l', 'o', 0,//- 'n', 'p', 0,//- 0, 0, 0,//- 0, 0, 0, }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); } // rjf: view menu UI_Key tab_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_tab_menu_key_")); UI_CtxMenu(tab_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { String8 cmds[] = { rd_cmd_kind_info_table[RD_CmdKind_OpenTab].string, rd_cmd_kind_info_table[RD_CmdKind_CloseTab].string, rd_cmd_kind_info_table[RD_CmdKind_DuplicateTab].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_MoveTabLeft].string, rd_cmd_kind_info_table[RD_CmdKind_MoveTabRight].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_NextTab].string, rd_cmd_kind_info_table[RD_CmdKind_PrevTab].string, {0},//- rd_cmd_kind_info_table[RD_CmdKind_TabSettings].string, }; U32 codepoints[] = { 'o', 'c', 'd', 0,//- 'l', 'r', 0,//- 'n', 'p', 0,//- 's', }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); } // rjf: targets menu UI_Key targets_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_targets_menu_key_")); UI_CtxMenu(targets_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { Temp scratch = scratch_begin(0, 0); String8 cmds[] = { rd_cmd_kind_info_table[RD_CmdKind_AddTarget].string, rd_cmd_kind_info_table[RD_CmdKind_LaunchAndRun].string, rd_cmd_kind_info_table[RD_CmdKind_LaunchAndStepInto].string, }; U32 codepoints[] = { 'a', 'r', 's', }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); scratch_end(scratch); } // rjf: ctrl menu UI_Key ctrl_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_ctrl_menu_key_")); UI_CtxMenu(ctrl_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { String8 cmds[] = { rd_cmd_kind_info_table[D_CmdKind_Run].string, rd_cmd_kind_info_table[D_CmdKind_KillAll].string, rd_cmd_kind_info_table[D_CmdKind_Restart].string, rd_cmd_kind_info_table[D_CmdKind_Halt].string, {0},//- rd_cmd_kind_info_table[D_CmdKind_StepInto].string, rd_cmd_kind_info_table[D_CmdKind_StepOver].string, rd_cmd_kind_info_table[D_CmdKind_StepOut].string, {0},//- rd_cmd_kind_info_table[D_CmdKind_Attach].string, rd_cmd_kind_info_table[D_CmdKind_Detach].string, }; U32 codepoints[] = { 'r', 'k', 's', 'h', 0,//- 'i', 'o', 't', 0,//- 'a', 'd', }; Assert(ArrayCount(codepoints) == ArrayCount(cmds)); rd_cmd_list_menu_buttons(ArrayCount(cmds), cmds, codepoints); } // rjf: help menu UI_Key help_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("_help_menu_key_")); UI_CtxMenu(help_menu_key) UI_PrefWidth(ui_em(50.f, 1.f)) UI_TagF("implicit") { UI_Row UI_TextAlignment(UI_TextAlign_Center) UI_TagF("weak") ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL)); ui_spacer(ui_em(1.f, 1.f)); UI_PrefHeight(ui_children_sum(1)) UI_Row UI_Padding(ui_pct(1, 0)) { R_Handle texture = rd_state->icon_texture; Vec2S32 texture_dim = r_size_from_tex2d(texture); UI_PrefWidth(ui_px(ui_top_font_size()*10.f, 1.f)) UI_PrefHeight(ui_px(ui_top_font_size()*10.f, 1.f)) ui_image(texture, R_Tex2DSampleKind_Linear, r2f32p(0, 0, texture_dim.x, texture_dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("")); } ui_spacer(ui_em(1.f, 1.f)); CFG_KeyMapNodePtrList key_map_nodes = cfg_key_map_node_ptr_list_from_name(scratch.arena, rd_state->key_map, rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string); CFG_Binding binding = {0}; String8 binding_str = {0}; if(key_map_nodes.first != 0) { binding = key_map_nodes.first->v->binding; binding_str = os_string_from_modifiers_key(scratch.arena, binding.modifiers, binding.key); } UI_TagF(".") UI_Row UI_TextAlignment(UI_TextAlign_Center) UI_Padding(ui_pct(1, 0)) { UI_Signal sig = {0}; UI_PrefWidth(ui_children_sum(1)) UI_Flags(UI_BoxFlag_DrawBorder) UI_CornerRadius(ui_top_font_size()*0.5f) sig = ui_buttonf("###open_palette"); UI_Parent(sig.box) UI_PrefWidth(ui_text_dim(ui_top_font_size()*2.f, 1)) { ui_labelf("Search for commands & settings"); if(binding_str.size != 0) { UI_TagF("weak") ui_labelf("(%S)", binding_str); } } if(ui_clicked(sig)) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string); } } ui_spacer(ui_em(1.f, 1.f)); UI_TagF("pop") UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_text_dim(ui_top_font_size()*2.f, 1)) UI_CornerRadius(ui_top_font_size()*0.5f) { String8 url = str8_lit("https://github.com/EpicGamesExt/raddebugger/issues"); UI_Signal sig = ui_button(str8_lit("Submit request, issue, or bug report")); if(ui_clicked(sig)) { os_open_in_browser(url); } } ui_spacer(ui_em(0.5f, 1.f)); } // rjf: buttons UI_TextAlignment(UI_TextAlign_Center) UI_HeightFill { // rjf: set up table struct { String8 name; U32 codepoint; OS_Key key; UI_Key menu_key; } items[] = { {str8_lit("File"), 'f', OS_Key_F, file_menu_key}, {str8_lit("Window"), 'w', OS_Key_W, window_menu_key}, {str8_lit("Panel"), 'p', OS_Key_P, panel_menu_key}, {str8_lit("Tab"), 'b', OS_Key_V, tab_menu_key}, {str8_lit("Targets"), 't', OS_Key_T, targets_menu_key}, {str8_lit("Control"), 'c', OS_Key_C, ctrl_menu_key}, {str8_lit("Help"), 'h', OS_Key_H, help_menu_key}, }; // rjf: determine if one of the menus is already open B32 menu_open = 0; U64 open_menu_idx = 0; for(U64 idx = 0; idx < ArrayCount(items); idx += 1) { if(ui_ctx_menu_is_open(items[idx].menu_key)) { menu_open = 1; open_menu_idx = idx; break; } } // rjf: navigate between menus U64 open_menu_idx_prime = open_menu_idx; if(menu_open && ws->menu_bar_focused && window_is_focused) { for(UI_Event *evt = 0; ui_next_event(&evt);) { B32 taken = 0; if(evt->delta_2s32.x > 0) { taken = 1; open_menu_idx_prime += 1; open_menu_idx_prime = open_menu_idx_prime%ArrayCount(items); } if(evt->delta_2s32.x < 0) { taken = 1; open_menu_idx_prime = open_menu_idx_prime > 0 ? open_menu_idx_prime-1 : (ArrayCount(items)-1); } if(taken) { ui_eat_event(evt); } } } // rjf: make ui for(U64 idx = 0; idx < ArrayCount(items); idx += 1) { ui_set_next_fastpath_codepoint(items[idx].codepoint); B32 alt_fastpath_key = 0; if(rd_setting_b32_from_name(str8_lit("focus_menu_bar_with_alt")) && ui_key_press(OS_Modifier_Alt, items[idx].key)) { alt_fastpath_key = 1; } if((ws->menu_bar_key_held || ws->menu_bar_focused) && !ui_any_ctx_menu_is_open()) { ui_set_next_flags(UI_BoxFlag_DrawTextFastpathCodepoint); } UI_Signal sig = rd_menu_bar_button(items[idx].name); os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); if(menu_open) { if((ui_hovering(sig) && !ui_ctx_menu_is_open(items[idx].menu_key)) || (open_menu_idx_prime == idx && open_menu_idx_prime != open_menu_idx)) { ui_ctx_menu_open(items[idx].menu_key, sig.box->key, v2f32(0, sig.box->rect.y1-sig.box->rect.y0)); } } else if(ui_pressed(sig) || alt_fastpath_key) { if(ui_ctx_menu_is_open(items[idx].menu_key)) { ui_ctx_menu_close(); } else { ui_ctx_menu_open(items[idx].menu_key, sig.box->key, v2f32(0, sig.box->rect.y1-sig.box->rect.y0)); } } } } } } } } //- rjf: center column if(dim_2f32(top_bar_rect).x > ui_top_font_size()*60) UI_PrefWidth(ui_children_sum(1.f)) UI_Row UI_PrefWidth(ui_px(dim_2f32(top_bar_rect).y, 1)) RD_Font(RD_FontSlot_Icons) UI_FontSize(ui_top_font_size()*0.85f) { Temp scratch = scratch_begin(0, 0); CFG_NodePtrList targets = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); B32 can_send_signal = !d_ctrl_targets_running(); typedef struct CenterButtonTask CenterButtonTask; struct CenterButtonTask { String8 cmd_name; String8 tag; B32 is_enabled; }; CenterButtonTask center_button_tasks[] = { {rd_cmd_kind_info_table[RD_CmdKind_Run].string, str8_lit("good"), (can_send_signal || d_ctrl_last_run_frame_idx()+4 > d_frame_index())}, {rd_cmd_kind_info_table[RD_CmdKind_Restart].string, str8_lit("neutral"), processes.count != 0}, {rd_cmd_kind_info_table[RD_CmdKind_Halt].string, str8_lit("weak"), !can_send_signal}, {rd_cmd_kind_info_table[RD_CmdKind_KillAll].string, str8_lit("bad"), processes.count != 0}, {rd_cmd_kind_info_table[RD_CmdKind_StepOver].string, str8_lit("weak"), can_send_signal}, {rd_cmd_kind_info_table[RD_CmdKind_StepInto].string, str8_lit("weak"), can_send_signal}, {rd_cmd_kind_info_table[RD_CmdKind_StepOut].string, str8_lit("weak"), processes.count != 0 && can_send_signal}, }; UI_TextAlignment(UI_TextAlign_Center) for EachElement(idx, center_button_tasks) UI_Flags(center_button_tasks[idx].is_enabled ? 0 : UI_BoxFlag_Disabled) UI_Tag(center_button_tasks[idx].is_enabled ? center_button_tasks[idx].tag : str8_lit("weak")) { String8 cmd_name = center_button_tasks[idx].cmd_name; UI_Signal sig = ui_button(rd_icon_kind_text_table[rd_icon_kind_from_code_name(cmd_name)]); os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); if(ui_hovering(sig)) { RD_RegsScope(.cmd_name = cmd_name, .ui_key = sig.box->key) rd_set_hover_regs(RD_RegSlot_CmdName); } if(ui_clicked(sig)) { rd_push_cmd(cmd_name, rd_regs()); } } scratch_end(scratch); } //- rjf: right column UI_WidthFill UI_Row { B32 do_user_prof = (dim_2f32(top_bar_rect).x > ui_top_font_size()*80); ui_spacer(ui_pct(1, 0)); // rjf: loaded user viz if(do_user_prof) UI_TagF("pop") { ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_child_layout_axis(Axis2_X); UI_Box *user_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, "###loaded_user_button"); os_window_push_custom_title_bar_client_area(ws->os, user_box->rect); UI_Parent(user_box) UI_PrefWidth(ui_text_dim(10, 0)) UI_TextAlignment(UI_TextAlign_Center) { String8 user_path = rd_state->user_path; user_path = str8_chop_last_dot(user_path); RD_Font(RD_FontSlot_Icons) UI_TextRasterFlags(rd_raster_flags_from_slot(RD_FontSlot_Icons)) ui_label(rd_icon_kind_text_table[RD_IconKind_Person]); ui_label(str8_skip_last_slash(user_path)); } UI_Signal user_sig = ui_signal_from_box(user_box); if(ui_clicked(user_sig)) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_OpenUser].string); } } if(do_user_prof) { ui_spacer(ui_em(0.75f, 0)); } // rjf: loaded project viz if(do_user_prof) UI_TagF("pop") { ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_child_layout_axis(Axis2_X); UI_Box *prof_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, "###loaded_project_button"); os_window_push_custom_title_bar_client_area(ws->os, prof_box->rect); UI_Parent(prof_box) UI_PrefWidth(ui_text_dim(10, 0)) UI_TextAlignment(UI_TextAlign_Center) { String8 prof_path = rd_state->project_path; prof_path = str8_chop_last_dot(prof_path); RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[RD_IconKind_Briefcase]); ui_label(str8_skip_last_slash(prof_path)); } UI_Signal prof_sig = ui_signal_from_box(prof_box); if(ui_clicked(prof_sig)) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_OpenProject].string); } } if(do_user_prof) { ui_spacer(ui_em(0.75f, 0)); } // rjf: close dropdown UI_Key close_ctx_menu_key = ui_key_from_stringf(ui_key_zero(), "###close_ctx_menu"); UI_CtxMenu(close_ctx_menu_key) UI_TagF("implicit") { if(ui_clicked(rd_icon_buttonf(RD_IconKind_Window, 0, "Close Window"))) { rd_cmd(RD_CmdKind_CloseWindow); } if(ui_clicked(rd_icon_buttonf(RD_IconKind_X, 0, "Exit"))) { rd_cmd(RD_CmdKind_Exit); } } // rjf: min/max/close buttons { UI_Signal min_sig = {0}; UI_Signal max_sig = {0}; UI_Signal cls_sig = {0}; Vec2F32 bar_dim = dim_2f32(top_bar_rect); F32 button_dim = floor_f32(bar_dim.y); UI_PrefWidth(ui_px(button_dim, 1.f)) UI_FontSize(ui_top_font_size()*0.75f) { min_sig = rd_icon_buttonf(RD_IconKind_WindowMinimize, 0, "##minimize"); max_sig = rd_icon_buttonf(os_window_is_maximized(ws->os) ? RD_IconKind_WindowRestore : RD_IconKind_Window, 0, "##maximize"); } UI_PrefWidth(ui_px(button_dim, 1.f)) UI_TagF("bad_pop") { cls_sig = rd_icon_buttonf(RD_IconKind_X, 0, "##close"); } if(ui_clicked(min_sig)) { os_window_set_minimized(ws->os, 1); } if(ui_clicked(max_sig)) { os_window_set_maximized(ws->os, !os_window_is_maximized(ws->os)); } if(ui_clicked(cls_sig)) { if(ws->order_next != &rd_nil_window_state || ws->order_prev != &rd_nil_window_state) { ui_ctx_menu_open(close_ctx_menu_key, cls_sig.box->key, v2f32(0, dim_2f32(cls_sig.box->rect).y)); } else { rd_cmd(RD_CmdKind_Exit); } } os_window_push_custom_title_bar_client_area(ws->os, min_sig.box->rect); os_window_push_custom_title_bar_client_area(ws->os, max_sig.box->rect); os_window_push_custom_title_bar_client_area(ws->os, pad_2f32(cls_sig.box->rect, 2.f)); } } } } //////////////////////////// //- rjf: @window_ui_part bottom bar // ProfScope("build bottom bar") { //- rjf: unpack status info B32 is_running = d_ctrl_targets_running() && d_ctrl_last_run_frame_idx() < d_frame_index(); CTRL_Event stop_event = d_ctrl_last_stop_event(); String8 tag = str8_lit("pop"); CFG_NodePtrList tasks = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("conversion_task")); CFG_NodePtrList long_running_tasks = {0}; F32 alive_t_rate = 1 - pow_f32(2, (-5.f * rd_state->frame_dt)); for(CFG_NodePtrNode *n = tasks.first; n != 0; n = n->next) { CFG_Node *task = n->v; F32 task_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "task_anim_%I64u", task->id), 1.f, .rate = alive_t_rate); if(task_t > 0.5f) { cfg_node_ptr_list_push(scratch.arena, &long_running_tasks, task); } } if(rd_state->bind_change_active) { tag = str8_lit("pop"); } else if(ws->error_t >= 0.01f && ws->error_string_size != 0) { tag = str8_lit("bad_pop"); } else if(!is_running) { switch(stop_event.cause) { default: case CTRL_EventCause_Finished: { tag = str8_lit("good_pop"); }break; case CTRL_EventCause_UserBreakpoint: case CTRL_EventCause_InterruptedByException: case CTRL_EventCause_InterruptedByTrap: case CTRL_EventCause_InterruptedByHalt: { tag = str8_lit("bad_pop"); }break; } } //- rjf: compute fstrs for status explanation DR_FStrList status_fstrs = {0}; { if(rd_state->bind_change_active) { RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(rd_state->bind_change_cmd_name); String8 display_name = rd_display_from_code_name(info->string); String8 string = push_str8f(scratch.arena, "Currently rebinding \"%S\"", display_name); DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, string); } else if(ws->error_t >= 0.01f && ws->error_string_size != 0) { String8 error_string = str8(ws->error_buffer, ws->error_string_size); ws->error_t -= rd_state->frame_dt/8.f; rd_request_frame(); ui_set_next_pref_width(ui_children_sum(1)); UI_CornerRadius(4) UI_Row UI_PrefWidth(ui_text_dim(10, 1)) UI_TextAlignment(UI_TextAlign_Center) { DR_FStrList error_fstrs = rd_fstrs_from_rich_string(scratch.arena, error_string); DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_WarningBig], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, str8_lit(" ")); dr_fstrs_concat_in_place(&status_fstrs, &error_fstrs); } } else if(is_running) { DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_Play], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, str8_lit(" Running...")); if(long_running_tasks.count != 0) { String8 string = push_str8f(scratch.arena, " Loading %I64u debug information file%s...", long_running_tasks.count, long_running_tasks.count == 1 ? "" : "s"); dr_fstrs_push_new(scratch.arena, &status_fstrs, ¶ms, string); } } else { status_fstrs = rd_stop_explanation_fstrs_from_ctrl_event(scratch.arena, &stop_event); } } //- rjf: build bottom bar UI_Flags(UI_BoxFlag_DrawBackground) UI_CornerRadius(0) UI_Tag(tag) UI_Pane(bottom_bar_rect, str8_lit("###bottom_bar")) UI_WidthFill UI_Row UI_Flags(0) { Temp scratch = scratch_begin(0, 0); // rjf: developer frame-time indicator if(DEV_updating_indicator) { F32 animation_t = pow_f32(sin_f32(rd_state->time_in_seconds/2.f), 2.f); ui_spacer(ui_em(0.3f, 1.f)); ui_spacer(ui_em(1.5f*animation_t, 1.f)); UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("*"); ui_spacer(ui_em(1.5f*(1-animation_t), 1.f)); } // rjf: build status UI_PrefWidth(ui_text_dim(10, 1)) { ui_spacer(ui_em(1.f, 1.f)); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &status_fstrs); } ui_spacer(ui_pct(1, 0)); // rjf: version UI_FontSize(ui_top_font_size()*0.85f) UI_PrefWidth(ui_text_dim(10, 1)) UI_TextAlignment(UI_TextAlign_Center) { ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL)); } scratch_end(scratch); } } //////////////////////////// //- rjf: @window_ui_part panel non-leaf UI (drag boundaries, drag/drop sites) // B32 is_changing_panel_boundaries = 0; ProfScope("non-leaf panel UI") for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { ////////////////////////// //- rjf: continue on leaf panels // if(panel->first == &cfg_nil_panel_node) { continue; } ////////////////////////// //- rjf: grab info // Axis2 split_axis = panel->split_axis; Rng2F32 panel_rect = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); ////////////////////////// //- rjf: boundary tab-drag/drop sites // { CFG_Node *drag_view = cfg_node_from_id(rd_state->drag_drop_regs->view); if(rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View && drag_view != &cfg_nil_node) { //- rjf: params F32 drop_site_major_dim_px = ceil_f32(ui_top_font_size()*7.f); F32 drop_site_minor_dim_px = ceil_f32(ui_top_font_size()*5.f); F32 corner_radius = ui_top_font_size()*0.5f; F32 padding = ceil_f32(ui_top_font_size()*0.5f); //- rjf: special case - build Y boundary drop sites on root panel // // (this does not naturally follow from the below algorithm, since the // root level panel only splits on X) if(panel == panel_tree.root) UI_CornerRadius(corner_radius) { Vec2F32 panel_rect_center = center_2f32(panel_rect); Axis2 axis = axis2_flip(panel_tree.root->split_axis); for EachEnumVal(Side, side) { UI_Key key = ui_key_from_stringf(ui_key_zero(), "root_extra_split_%i", side); Rng2F32 site_rect = panel_rect; site_rect.p0.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] - drop_site_major_dim_px/2; site_rect.p1.v[axis2_flip(axis)] = panel_rect_center.v[axis2_flip(axis)] + drop_site_major_dim_px/2; site_rect.p0.v[axis] = panel_rect.v[side].v[axis] - drop_site_minor_dim_px/2; site_rect.p1.v[axis] = panel_rect.v[side].v[axis] + drop_site_minor_dim_px/2; // rjf: build UI_Box *site_box = &ui_nil_box; { F32 site_open_t = ui_anim(ui_key_from_stringf(key, "open_t"), 1.f, .rate = rd_state->menu_animation_rate); UI_Rect(site_rect) UI_Squish(0.1f-0.1f*site_open_t) UI_Transparency(1-site_open_t) { site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_DrawHotEffects, key); ui_signal_from_box(site_box); } UI_Box *site_box_viz = &ui_nil_box; UI_Parent(site_box) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) UI_Column UI_Padding(ui_px(padding, 1.f)) UI_GroupKey(key) { ui_set_next_child_layout_axis(axis2_flip(axis)); site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_DrawHotEffects, ui_key_zero()); } UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) { ui_set_next_child_layout_axis(axis); UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) { ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); ui_spacer(ui_px(padding, 1.f)); ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); } } } // rjf: viz if(ui_key_match(site_box->key, ui_drop_hot_key())) { Rng2F32 future_split_rect_target = site_rect; future_split_rect_target.p0.v[axis] -= drop_site_major_dim_px; future_split_rect_target.p1.v[axis] += drop_site_major_dim_px; future_split_rect_target.p0.v[axis2_flip(axis)] = panel_rect.p0.v[axis2_flip(axis)]; future_split_rect_target.p1.v[axis2_flip(axis)] = panel_rect.p1.v[axis2_flip(axis)]; future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); Rng2F32 future_split_rect = { ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v0"), future_split_rect_target.x0, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v1"), future_split_rect_target.y0, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v2"), future_split_rect_target.x1, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v3"), future_split_rect_target.y1, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), }; UI_Rect(future_split_rect) UI_TagF("drop_site") UI_CornerRadius(ui_top_font_size()*2.f) { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); } } // rjf: drop if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) { Dir2 dir = (axis == Axis2_Y ? (side == Side_Min ? Dir2_Up : Dir2_Down) : axis == Axis2_X ? (side == Side_Min ? Dir2_Left : Dir2_Right) : Dir2_Invalid); if(dir != Dir2_Invalid) { CFG_PanelNode *split_panel = panel; rd_cmd(RD_CmdKind_SplitPanel, .dst_panel = split_panel->cfg->id, .panel = rd_state->drag_drop_regs->panel, .view = rd_state->drag_drop_regs->view, .dir2 = dir); } } } } //- rjf: iterate all children, build boundary drop sites Axis2 split_axis = panel->split_axis; UI_CornerRadius(corner_radius) for(CFG_PanelNode *child = panel->first;; child = child->next) { // rjf: form rect Rng2F32 child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, child); Vec2F32 child_rect_center = center_2f32(child_rect); UI_Key key = ui_key_from_stringf(ui_key_zero(), "drop_boundary_%p_%p", panel->cfg, child->cfg); Rng2F32 site_rect = r2f32(child_rect_center, child_rect_center); site_rect.p0.v[split_axis] = child_rect.p0.v[split_axis] - drop_site_minor_dim_px/2; site_rect.p1.v[split_axis] = child_rect.p0.v[split_axis] + drop_site_minor_dim_px/2; site_rect.p0.v[axis2_flip(split_axis)] -= drop_site_major_dim_px/2; site_rect.p1.v[axis2_flip(split_axis)] += drop_site_major_dim_px/2; // rjf: build UI_Box *site_box = &ui_nil_box; { F32 site_open_t = ui_anim(ui_key_from_stringf(key, "open_t"), 1.f, .rate = rd_state->menu_animation_rate); UI_Rect(site_rect) UI_Squish(0.1f-0.1f*site_open_t) UI_Transparency(1-site_open_t) { site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_DrawHotEffects, key); ui_signal_from_box(site_box); } UI_Box *site_box_viz = &ui_nil_box; UI_Parent(site_box) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) UI_Column UI_Padding(ui_px(padding, 1.f)) UI_GroupKey(key) { ui_set_next_child_layout_axis(axis2_flip(split_axis)); site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_DrawHotEffects, ui_key_zero()); } UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) { ui_set_next_child_layout_axis(split_axis); UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) { ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); ui_spacer(ui_px(padding, 1.f)); ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); } } } // rjf: viz if(ui_key_match(site_box->key, ui_drop_hot_key())) { Rng2F32 future_split_rect_target = site_rect; future_split_rect_target.p0.v[split_axis] -= drop_site_major_dim_px; future_split_rect_target.p1.v[split_axis] += drop_site_major_dim_px; future_split_rect_target.p0.v[axis2_flip(split_axis)] = child_rect.p0.v[axis2_flip(split_axis)]; future_split_rect_target.p1.v[axis2_flip(split_axis)] = child_rect.p1.v[axis2_flip(split_axis)]; future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); Rng2F32 future_split_rect = { ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v0"), future_split_rect_target.x0, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v1"), future_split_rect_target.y0, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v2"), future_split_rect_target.x1, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v3"), future_split_rect_target.y1, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), }; UI_Rect(future_split_rect) UI_TagF("drop_site") UI_CornerRadius(ui_top_font_size()*2.f) { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); } } // rjf: drop if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) { Dir2 dir = (panel->split_axis == Axis2_X ? Dir2_Left : Dir2_Up); CFG_PanelNode *split_panel = child; if(split_panel == &cfg_nil_panel_node) { split_panel = panel->last; dir = (panel->split_axis == Axis2_X ? Dir2_Right : Dir2_Down); } rd_cmd(RD_CmdKind_SplitPanel, .dst_panel = split_panel->cfg->id, .panel = rd_state->drag_drop_regs->panel, .view = rd_state->drag_drop_regs->view, .dir2 = dir); } // rjf: exit on opl child if(child == &cfg_nil_panel_node) { break; } } } } ////////////////////////// //- rjf: do UI for drag boundaries between all children // for(CFG_PanelNode *child = panel->first; child != &cfg_nil_panel_node && child->next != &cfg_nil_panel_node; child = child->next) { CFG_PanelNode *min_child = child; CFG_PanelNode *max_child = min_child->next; Rng2F32 min_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, min_child); Rng2F32 max_child_rect = cfg_target_rect_from_panel_node_child(panel_rect, panel, max_child); Rng2F32 boundary_rect = {0}; { boundary_rect.p0.v[split_axis] = min_child_rect.p1.v[split_axis] - ui_top_font_size()/3; boundary_rect.p1.v[split_axis] = max_child_rect.p0.v[split_axis] + ui_top_font_size()/3; boundary_rect.p0.v[axis2_flip(split_axis)] = panel_rect.p0.v[axis2_flip(split_axis)]; boundary_rect.p1.v[axis2_flip(split_axis)] = panel_rect.p1.v[axis2_flip(split_axis)]; } UI_Rect(boundary_rect) { ui_set_next_hover_cursor(split_axis == Axis2_X ? OS_Cursor_LeftRight : OS_Cursor_UpDown); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%p_%p", min_child->cfg, max_child->cfg); UI_Signal sig = ui_signal_from_box(box); if(ui_double_clicked(sig)) { ui_kill_action(); F32 sum_pct = min_child->pct_of_parent + max_child->pct_of_parent; min_child->pct_of_parent = 0.5f * sum_pct; max_child->pct_of_parent = 0.5f * sum_pct; cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_child->pct_of_parent); cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_child->pct_of_parent); } else if(ui_pressed(sig)) { Vec2F32 v = {min_child->pct_of_parent, max_child->pct_of_parent}; ui_store_drag_struct(&v); } else if(ui_dragging(sig)) { Vec2F32 v = *ui_get_drag_struct(Vec2F32); Vec2F32 mouse_delta = ui_drag_delta(); F32 total_size = dim_2f32(panel_rect).v[split_axis]; F32 min_pct__before = v.v[0]; F32 min_pixels__before = min_pct__before * total_size; F32 min_pixels__after = min_pixels__before + mouse_delta.v[split_axis]; if(min_pixels__after < 50.f) { min_pixels__after = 50.f; } F32 min_pct__after = min_pixels__after / total_size; F32 pct_delta = min_pct__after - min_pct__before; F32 max_pct__before = v.v[1]; F32 max_pct__after = max_pct__before - pct_delta; F32 max_pixels__after = max_pct__after * total_size; if(max_pixels__after < 50.f) { max_pixels__after = 50.f; max_pct__after = max_pixels__after / total_size; pct_delta = -(max_pct__after - max_pct__before); min_pct__after = min_pct__before + pct_delta; } min_child->pct_of_parent = min_pct__after; max_child->pct_of_parent = max_pct__after; cfg_node_equip_stringf(rd_state->cfg, min_child->cfg, "%f", min_pct__after); cfg_node_equip_stringf(rd_state->cfg, max_child->cfg, "%f", max_pct__after); is_changing_panel_boundaries = 1; } } } } //////////////////////////// //- rjf: @window_ui_part animate panels // { B32 window_is_resizing = (ws->last_window_rect.x1 != window_rect.x1 || ws->last_window_rect.y1 != window_rect.y1); Vec2F32 content_rect_dim = dim_2f32(content_rect); if(content_rect_dim.x > 0 && content_rect_dim.y > 0) { for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); Rng2F32 target_rect_pct = r2f32p(target_rect_px.x0/content_rect_dim.x, target_rect_px.y0/content_rect_dim.y, target_rect_px.x1/content_rect_dim.x, target_rect_px.y1/content_rect_dim.y); B32 reset = (window_is_resizing || ws->window_layout_reset || ws->frames_alive < 5 || is_changing_panel_boundaries); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x0", panel->cfg), target_rect_pct.x0, .initial = target_rect_pct.x0, .reset = reset, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y0", panel->cfg), target_rect_pct.y0, .initial = target_rect_pct.y0, .reset = reset, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x1", panel->cfg), target_rect_pct.x1, .initial = target_rect_pct.x1, .reset = reset, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y1", panel->cfg), target_rect_pct.y1, .initial = target_rect_pct.y1, .reset = reset, .rate = rd_state->menu_animation_rate); } } ws->window_layout_reset = 0; } //////////////////////////// //- rjf: @window_ui_part panel leaf UI // if(content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0) { ProfScope("leaf panel UI") for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) {continue;} B32 panel_is_focused = (window_is_focused && !ws->menu_bar_focused && !query_is_open && !ui_any_ctx_menu_is_open() && !ws->hover_eval_focused && panel_tree.focused == panel); CFG_Node *selected_tab = panel->selected_tab; RD_ViewState *selected_tab_view_state = rd_view_state_from_cfg(selected_tab); ProfScope("leaf panel UI work - %.*s: %.*s", str8_varg(selected_tab->string), str8_varg(rd_expr_from_cfg(selected_tab))) UI_Focus(panel_is_focused ? UI_FocusKind_Null : UI_FocusKind_Off) { ////////////////////////// //- rjf: calculate UI rectangles // Vec2F32 content_rect_dim = dim_2f32(content_rect); Rng2F32 target_rect_px = cfg_target_rect_from_panel_node(content_rect, panel_tree.root, panel); Rng2F32 target_rect_pct = r2f32p(target_rect_px.x0 / content_rect_dim.x, target_rect_px.y0 / content_rect_dim.y, target_rect_px.x1 / content_rect_dim.x, target_rect_px.y1 / content_rect_dim.y); Rng2F32 panel_rect_pct = r2f32p(ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x0", panel->cfg), target_rect_pct.x0, .initial = target_rect_pct.x0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y0", panel->cfg), target_rect_pct.y0, .initial = target_rect_pct.y0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x1", panel->cfg), target_rect_pct.x1, .initial = target_rect_pct.x1, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y1", panel->cfg), target_rect_pct.y1, .initial = target_rect_pct.y1, .rate = rd_state->menu_animation_rate)); Rng2F32 panel_rect = r2f32p(panel_rect_pct.x0*content_rect_dim.x, panel_rect_pct.y0*content_rect_dim.y, panel_rect_pct.x1*content_rect_dim.x, panel_rect_pct.y1*content_rect_dim.y); panel_rect = pad_2f32(panel_rect, floor_f32(-ui_top_font_size()*0.15f)); panel_rect = r2f32p(round_f32(panel_rect.x0), round_f32(panel_rect.y0), round_f32(panel_rect.x1), round_f32(panel_rect.y1)); F32 tab_bar_rheight = floor_f32(ui_top_font_size()*3.5f); F32 tab_bar_vheight = floor_f32(ui_top_font_size()*rd_setting_f32_from_name(str8_lit("tab_height"))); F32 tab_bar_rv_diff = tab_bar_rheight - tab_bar_vheight; F32 tab_spacing = floor_f32(ui_top_font_size()*0.4f); Rng2F32 tab_bar_rect = r2f32p(panel_rect.x0, panel_rect.y0, panel_rect.x1, panel_rect.y0 + tab_bar_vheight); Rng2F32 content_rect = r2f32p(panel_rect.x0, panel_rect.y0+tab_bar_vheight, panel_rect.x1, panel_rect.y1); if(panel->tab_side == Side_Max) { tab_bar_rect.y0 = panel_rect.y1 - tab_bar_vheight; tab_bar_rect.y1 = panel_rect.y1; content_rect.y0 = panel_rect.y0; content_rect.y1 = panel_rect.y1 - tab_bar_vheight; } tab_bar_rect = intersect_2f32(tab_bar_rect, panel_rect); content_rect = intersect_2f32(content_rect, panel_rect); ////////////////////////// //- rjf: decide to skip this panel (e.g. if it is too small // B32 build_panel = (content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0); ////////////////////////// //- rjf: build combined split+movetab drag/drop sites // if(build_panel) { CFG_Node *view = cfg_node_from_id(rd_state->drag_drop_regs->view); if(rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View && view != &cfg_nil_node && contains_2f32(panel_rect, ui_mouse()) && ui_key_match(ui_drop_hot_key(), ui_key_zero())) { F32 drop_site_dim_px = ceil_f32(ui_top_font_size()*7.f); drop_site_dim_px = Min(drop_site_dim_px, dim_2f32(panel_rect).v[panel->split_axis]/4.f); drop_site_dim_px = Max(drop_site_dim_px, ceil_f32(ui_top_font_size()*3.f)); Vec2F32 drop_site_half_dim = v2f32(drop_site_dim_px/2, drop_site_dim_px/2); Vec2F32 panel_center = center_2f32(panel_rect); F32 corner_radius = ui_top_font_size()*0.5f; F32 padding = ceil_f32(ui_top_font_size()*0.5f); struct { UI_Key key; Dir2 split_dir; Rng2F32 rect; } sites[] = { { ui_key_from_stringf(ui_key_zero(), "drop_split_center_%p", panel->cfg), Dir2_Invalid, r2f32(sub_2f32(panel_center, drop_site_half_dim), add_2f32(panel_center, drop_site_half_dim)) }, { ui_key_from_stringf(ui_key_zero(), "drop_split_up_%p", panel->cfg), Dir2_Up, r2f32p(panel_center.x-drop_site_half_dim.x, panel_center.y-drop_site_half_dim.y - drop_site_half_dim.y*2, panel_center.x+drop_site_half_dim.x, panel_center.y+drop_site_half_dim.y - drop_site_half_dim.y*2), }, { ui_key_from_stringf(ui_key_zero(), "drop_split_down_%p", panel->cfg), Dir2_Down, r2f32p(panel_center.x-drop_site_half_dim.x, panel_center.y-drop_site_half_dim.y + drop_site_half_dim.y*2, panel_center.x+drop_site_half_dim.x, panel_center.y+drop_site_half_dim.y + drop_site_half_dim.y*2), }, { ui_key_from_stringf(ui_key_zero(), "drop_split_left_%p", panel->cfg), Dir2_Left, r2f32p(panel_center.x-drop_site_half_dim.x - drop_site_half_dim.x*2, panel_center.y-drop_site_half_dim.y, panel_center.x+drop_site_half_dim.x - drop_site_half_dim.x*2, panel_center.y+drop_site_half_dim.y), }, { ui_key_from_stringf(ui_key_zero(), "drop_split_right_%p", panel->cfg), Dir2_Right, r2f32p(panel_center.x-drop_site_half_dim.x + drop_site_half_dim.x*2, panel_center.y-drop_site_half_dim.y, panel_center.x+drop_site_half_dim.x + drop_site_half_dim.x*2, panel_center.y+drop_site_half_dim.y), }, }; UI_CornerRadius(corner_radius) for(U64 idx = 0; idx < ArrayCount(sites); idx += 1) { UI_Key key = sites[idx].key; Dir2 dir = sites[idx].split_dir; Rng2F32 rect = sites[idx].rect; Axis2 split_axis = axis2_from_dir2(dir); Side split_side = side_from_dir2(dir); if(dir != Dir2_Invalid && split_axis == panel->parent->split_axis) { continue; } UI_Box *site_box = &ui_nil_box; { F32 site_open_t = ui_anim(ui_key_from_stringf(key, "open_t"), 1.f, .rate = rd_state->menu_animation_rate); UI_Rect(rect) UI_Squish(0.1f-0.1f*site_open_t) UI_Transparency(1-site_open_t) { site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_DrawHotEffects, key); ui_signal_from_box(site_box); } UI_Box *site_box_viz = &ui_nil_box; UI_GroupKey(key) UI_Parent(site_box) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) UI_Column UI_Padding(ui_px(padding, 1.f)) { ui_set_next_child_layout_axis(axis2_flip(split_axis)); site_box_viz = ui_build_box_from_key(UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_DrawHotEffects, ui_key_zero()); } if(dir != Dir2_Invalid) { UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) { ui_set_next_child_layout_axis(split_axis); UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) UI_TagF("drop_site") { if(split_side == Side_Min) { ui_set_next_flags(UI_BoxFlag_DrawBackground); } ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); ui_spacer(ui_px(padding, 1.f)); if(split_side == Side_Max) { ui_set_next_flags(UI_BoxFlag_DrawBackground); } ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); } } } else { UI_Parent(site_box_viz) UI_WidthFill UI_HeightFill UI_Padding(ui_px(padding, 1.f)) { ui_set_next_child_layout_axis(split_axis); UI_Box *row_or_column = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(row_or_column) UI_Padding(ui_px(padding, 1.f)) UI_TagF("drop_site") { ui_build_box_from_key(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, ui_key_zero()); } } } } if(ui_key_match(site_box->key, ui_drop_hot_key()) && rd_drag_drop()) { if(dir != Dir2_Invalid) { rd_cmd(RD_CmdKind_SplitPanel, .dst_panel = panel->cfg->id, .panel = rd_state->drag_drop_regs->panel, .view = rd_state->drag_drop_regs->view, .dir2 = dir); } else { rd_cmd(RD_CmdKind_MoveView, .dst_panel = panel->cfg->id, .panel = rd_state->drag_drop_regs->panel, .view = rd_state->drag_drop_regs->view, .prev_tab = cfg_node_ptr_list_last(&panel->tabs)->id); } } } for(U64 idx = 0; idx < ArrayCount(sites); idx += 1) { B32 is_drop_hot = ui_key_match(ui_drop_hot_key(), sites[idx].key); if(is_drop_hot) { Axis2 split_axis = axis2_from_dir2(sites[idx].split_dir); Side split_side = side_from_dir2(sites[idx].split_dir); Rng2F32 future_split_rect_target = panel_rect; if(sites[idx].split_dir != Dir2_Invalid) { Vec2F32 panel_center = center_2f32(panel_rect); future_split_rect_target.v[side_flip(split_side)].v[split_axis] = panel_center.v[split_axis]; } future_split_rect_target = pad_2f32(future_split_rect_target, -ui_top_font_size()*2.f); Vec2F32 future_split_rect_target_center = center_2f32(future_split_rect_target); Rng2F32 future_split_rect = { ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v0"), future_split_rect_target.x0, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v1"), future_split_rect_target.y0, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v2"), future_split_rect_target.x1, .initial = future_split_rect_target_center.x, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "drop_site_v3"), future_split_rect_target.y1, .initial = future_split_rect_target_center.y, .rate = rd_state->menu_animation_rate), }; UI_Rect(future_split_rect) UI_TagF("drop_site") UI_CornerRadius(ui_top_font_size()*2.f) { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); } } } } } ////////////////////////// //- rjf: build catch-all panel drop-site // UI_Key catchall_drop_site_key = ui_key_from_stringf(ui_key_zero(), "catchall_drop_site_%p", panel->cfg); if(build_panel && rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View) UI_Rect(panel_rect) { UI_Box *catchall_drop_site = ui_build_box_from_key(UI_BoxFlag_DropSite, catchall_drop_site_key); ui_signal_from_box(catchall_drop_site); } ////////////////////////// //- rjf: panel not selected? -> darken // if(build_panel) if(panel != panel_tree.focused) { UI_Rect(content_rect) UI_TagF("inactive") ui_build_box_from_key(UI_BoxFlag_DrawBackground, ui_key_zero()); } ////////////////////////// //- rjf: build panel container box // UI_Box *panel_box = &ui_nil_box; if(build_panel) UI_Rect(content_rect) UI_ChildLayoutAxis(Axis2_Y) UI_CornerRadius(0) UI_Focus(UI_FocusKind_On) { UI_Key panel_key = ui_key_from_stringf(ui_key_zero(), "panel_box_%p", panel->cfg); panel_box = ui_build_box_from_key(UI_BoxFlag_MouseClickable| UI_BoxFlag_Clip| UI_BoxFlag_DrawBorder| UI_BoxFlag_DisableFocusOverlay| ((panel_tree.focused != panel)*UI_BoxFlag_DisableFocusBorder), panel_key); } ////////////////////////// //- rjf: loading animation for stable view // UI_Box *loading_overlay_container = &ui_nil_box; if(build_panel) UI_Parent(panel_box) UI_WidthFill UI_HeightFill { loading_overlay_container = ui_build_box_from_key(UI_BoxFlag_Floating, ui_key_zero()); } ////////////////////////// //- rjf: build selected tab view // if(build_panel) UI_Parent(panel_box) UI_Focus(panel_is_focused ? UI_FocusKind_Null : UI_FocusKind_Off) UI_WidthFill { //- rjf: push interaction registers, fill with per-view states rd_push_regs(.panel = panel->cfg->id, .tab = selected_tab->id, .view = selected_tab->id); { String8 view_expr = rd_expr_from_cfg(selected_tab); String8 view_file_path = rd_file_path_from_eval_string(rd_frame_arena(), view_expr); // NOTE(rjf): we want to only fill out this view's file path slot if it // evaluates one - this way, a view can use the slot to know the selected // file path (if there is one). this is useful when pushing commandas which // apply to a cursor, for example. if(view_file_path.size != 0) { rd_regs()->file_path = view_file_path; } } //- rjf: visualizers -> accept expression drops UI_Box *view_drop_site = &ui_nil_box; { RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(selected_tab->string); if(view_ui_rule != &rd_nil_view_ui_rule && rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_Expr && !str8_match(selected_tab->string, str8_lit("text"), 0) && !str8_match(selected_tab->string, str8_lit("disasm"), 0)) { UI_FixedSize(dim_2f32(content_rect)) view_drop_site = ui_build_box_from_stringf(UI_BoxFlag_DropSite|UI_BoxFlag_Floating, "drop_site_%I64x", selected_tab->id); } } //- rjf: build view container UI_Box *view_container_box = &ui_nil_box; UI_FixedWidth(dim_2f32(content_rect).x) UI_FixedHeight(dim_2f32(content_rect).y) UI_ChildLayoutAxis(Axis2_Y) { view_container_box = ui_build_box_from_key(0, ui_key_zero()); } //- rjf: build empty view UI_Parent(view_container_box) if(selected_tab == &cfg_nil_node && panel->parent != &cfg_nil_panel_node) { ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) UI_TagF("weak") UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) { UI_PrefHeight(ui_em(3.f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_em(15.f, 1.f)) UI_CornerRadius(ui_top_font_size()/2.f) UI_TagF("bad_pop") { if(ui_clicked(rd_icon_buttonf(RD_IconKind_X, 0, "Close Panel"))) { rd_cmd(RD_CmdKind_ClosePanel); } } } } //- rjf: build tab view UI_Parent(view_container_box) if(selected_tab != &cfg_nil_node) ProfScope("build tab view") { rd_view_ui(content_rect); } //- rjf: accept expression drops if(view_drop_site != &ui_nil_box) { UI_Signal sig = ui_signal_from_box(view_drop_site); if(ui_key_match(view_drop_site->key, ui_drop_hot_key())) { UI_Parent(view_drop_site) UI_WidthFill UI_HeightFill UI_TagF("drop_site") { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); } if(rd_drag_drop()) { rd_store_view_expr_string(rd_state->drag_drop_regs->expr); } } } //- rjf: pop interaction registers; commit if this is the selected view RD_Regs *view_regs = rd_pop_regs(); if(panel_is_focused) { MemoryCopyStruct(rd_regs(), view_regs); } } //////////////////////// //- rjf: loading? -> fill loading overlay container // if(build_panel) { F32 selected_tab_loading_t = selected_tab_view_state->loading_t; if(selected_tab_loading_t > 0.01f) UI_Parent(loading_overlay_container) { rd_loading_overlay(panel_rect, selected_tab_loading_t, selected_tab_view_state->loading_progress_v, selected_tab_view_state->loading_progress_v_target); } } ////////////////////////// //- rjf: consume panel fallthrough interaction events // if(build_panel) { UI_Signal panel_sig = ui_signal_from_box(panel_box); if(ui_pressed(panel_sig)) { rd_cmd(RD_CmdKind_FocusPanel, .panel = panel->cfg->id); } } ////////////////////////// //- rjf: compute tab build tasks // typedef struct TabTask TabTask; struct TabTask { TabTask *next; CFG_Node *tab; DR_FStrList fstrs; F32 tab_width; }; TabTask *first_tab_task = 0; TabTask *last_tab_task = 0; U64 tab_task_count = 0; F32 tab_close_width_px = ui_top_font_size()*2.5f; F32 max_tab_width_px = ui_top_font_size()*20.f; if(build_panel) UI_TagF("tab") { B32 reset = (ws->window_layout_reset || ws->frames_alive < 5 || is_changing_panel_boundaries); for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) { CFG_Node *tab = n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } UI_TagF(tab != panel->selected_tab ? "inactive" : "") { TabTask *t = push_array(scratch.arena, TabTask, 1); t->tab = tab; t->fstrs = rd_title_fstrs_from_cfg(scratch.arena, tab, 0); F32 tab_width_target = dr_dim_from_fstrs(ui_top_tab_size(), &t->fstrs).x + tab_close_width_px + ui_top_font_size()*1.f; tab_width_target = Min(max_tab_width_px, tab_width_target); t->tab_width = floor_f32(ui_anim(ui_key_from_stringf(ui_key_zero(), "tab_width_%p", tab), tab_width_target, .initial = reset ? tab_width_target : 0, .rate = rd_state->menu_animation_rate)); SLLQueuePush(first_tab_task, last_tab_task, t); tab_task_count += 1; } } } ////////////////////////// //- rjf: build tab bar container // UI_Box *tab_bar_box = &ui_nil_box; if(build_panel) UI_CornerRadius(0) UI_Rect(tab_bar_rect) { tab_bar_box = ui_build_box_from_stringf(UI_BoxFlag_Clip| UI_BoxFlag_AllowOverflowY| UI_BoxFlag_ViewClampX| UI_BoxFlag_ViewScrollX| UI_BoxFlag_Clickable, "tab_bar_%p", panel->cfg); if(panel->tab_side == Side_Max) { tab_bar_box->view_off.y = tab_bar_box->view_off_target.y = (tab_bar_rheight - tab_bar_vheight); } else { tab_bar_box->view_off.y = tab_bar_box->view_off_target.y = 0; } } ////////////////////////// //- rjf: determine tab drop site // B32 tab_drop_is_active = rd_drag_is_active() && ui_key_match(ui_drop_hot_key(), catchall_drop_site_key); CFG_Node *tab_drop_prev = &cfg_nil_node; if(build_panel) { F32 best_prev_distance_px = 1000000.f; TabTask start_boundary_tab_task = {first_tab_task, &cfg_nil_node}; F32 off = 0; for(TabTask *task = &start_boundary_tab_task; task != 0; task = task->next) { off += task->tab_width; Vec2F32 anchor_pt = v2f32(tab_bar_box->rect.x0 + off, tab_bar_box->rect.y1); F32 distance = length_2f32(sub_2f32(ui_mouse(), anchor_pt)); if(distance < best_prev_distance_px) { best_prev_distance_px = distance; tab_drop_prev = task->tab; } } } ////////////////////////// //- rjf: turn off drop visualization if this drag would be a no-op // if(tab_drop_is_active && rd_state->drag_drop_regs->panel == panel->cfg->id) { TabTask start_boundary_tab_task = {first_tab_task, &cfg_nil_node}; if(tab_drop_prev->id == rd_state->drag_drop_regs->view) { tab_drop_is_active = 0; } if(tab_drop_is_active) for(TabTask *t = &start_boundary_tab_task; t != 0; t = t->next) { if(t->tab == tab_drop_prev && t->next != 0 && t->next->tab->id == rd_state->drag_drop_regs->view) { tab_drop_is_active = 0; break; } } } ////////////////////////// //- rjf: build tab bar contents // if(build_panel) UI_Focus(UI_FocusKind_Off) UI_Parent(tab_bar_box) UI_Padding(ui_em(0.5f, 1.f)) UI_PrefHeight(ui_pct(1, 0)) UI_TagF("tab") { F32 corner_radius = ui_top_font_size()*0.6f; TabTask start_boundary_tab_task = {first_tab_task, &cfg_nil_node}; UI_CornerRadius00(panel->tab_side == Side_Min ? corner_radius : 0) UI_CornerRadius01(panel->tab_side == Side_Min ? 0 : corner_radius) UI_CornerRadius10(panel->tab_side == Side_Min ? corner_radius : 0) UI_CornerRadius11(panel->tab_side == Side_Min ? 0 : corner_radius) for(TabTask *tab_task = &start_boundary_tab_task; tab_task != 0; tab_task = tab_task->next) { CFG_Node *tab = tab_task->tab; //- rjf: build tab DR_FStrList tab_fstrs = tab_task->fstrs; F32 tab_width_px = tab_task->tab_width; if(tab != &cfg_nil_node) RD_RegsScope(.panel = panel->cfg->id, .view = tab->id, .tab = tab->id) { // rjf: gather info for this tab B32 tab_is_selected = (tab == panel->selected_tab); B32 tab_is_auto = rd_view_setting_b32_from_name(str8_lit("auto")); // rjf: begin vertical region for this tab ui_set_next_child_layout_axis(Axis2_Y); ui_set_next_pref_width(ui_px(tab_width_px, 1)); UI_Box *tab_column_box = ui_build_box_from_stringf(!is_changing_panel_boundaries*UI_BoxFlag_AnimatePosX, "tab_column_%p", tab); // rjf: choose palette B32 omit_name = 0; if(rd_drag_is_active() && rd_state->drag_drop_regs->view == tab->id && rd_state->drag_drop_regs_slot == RD_RegSlot_View) { omit_name = 1; } // rjf: build tab container box UI_Parent(tab_column_box) UI_PrefHeight(ui_px(tab_bar_vheight, 1)) UI_TagF(omit_name ? "hollow" : "") UI_TagF(!omit_name && !tab_is_selected ? "inactive" : "") UI_TagF(!omit_name && tab_is_auto ? "auto" : "") { if(panel->tab_side == Side_Max) { ui_spacer(ui_px(tab_bar_rv_diff-1.f, 1.f)); } else { ui_spacer(ui_px(1.f, 1.f)); } UI_Box *tab_box = ui_build_box_from_stringf(UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| (UI_BoxFlag_DrawDropShadow*tab_is_selected)| UI_BoxFlag_Clickable, "tab_%p", tab); // rjf: build tab contents if(!omit_name) UI_Parent(tab_box) { UI_WidthFill UI_Row { ui_spacer(ui_em(0.5f, 1.f)); UI_PrefWidth(ui_text_dim(10, 0)) { UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(name_box, &tab_fstrs); } } UI_PrefWidth(ui_px(tab_close_width_px, 1.f)) UI_TextAlignment(UI_TextAlign_Center) RD_Font(RD_FontSlot_Icons) UI_FontSize(ui_top_font_size()*0.75f) UI_TagF(".") UI_TagF("tab") UI_TagF("weak") UI_TagF("implicit") UI_CornerRadius00(0) UI_CornerRadius01(0) { UI_Box *close_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawText| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, "%S###close_view_%p", rd_icon_kind_text_table[RD_IconKind_X], tab); UI_Signal sig = ui_signal_from_box(close_box); if(ui_clicked(sig) || ui_middle_clicked(sig)) { rd_cmd(RD_CmdKind_CloseTab); } } } // rjf: consume events for tab clicking { UI_Signal sig = ui_signal_from_box(tab_box); if(ui_pressed(sig)) { rd_cmd(RD_CmdKind_FocusTab); rd_cmd(RD_CmdKind_FocusPanel); } else if(ui_dragging(sig) && !rd_drag_is_active() && length_2f32(ui_drag_delta()) > 10.f) { rd_drag_begin(RD_RegSlot_View); } else if(ui_right_clicked(sig)) { rd_cmd(RD_CmdKind_PushQuery, .ui_key = sig.box->key, .expr = push_str8f(scratch.arena, "query:config.$%I64x", tab->id)); } else if(ui_middle_clicked(sig)) { rd_cmd(RD_CmdKind_CloseTab); } } } // rjf: space for next tab { ui_spacer(ui_px(floor_f32(ui_top_font_size()*0.4f), 1.f)); } } //- rjf: if this is the currently active drop site's previous tab, then build empty space // to visualize where tab will be moved once dropped if(tab_drop_is_active && rd_drag_is_active() && rd_state->drag_drop_regs_slot == RD_RegSlot_View && tab == tab_drop_prev) { // rjf: begin vertical region for this spot ui_set_next_child_layout_axis(Axis2_Y); ui_set_next_pref_width(ui_px(ui_top_font_size()*4.f, 1)); UI_Box *tab_column_box = ui_build_box_from_stringf(!is_changing_panel_boundaries*UI_BoxFlag_AnimatePosX, "tab_column_%p", tab); // rjf: build spot container box UI_Parent(tab_column_box) UI_PrefHeight(ui_px(tab_bar_vheight, 1)) UI_TagF("hollow") { if(panel->tab_side == Side_Max) { ui_spacer(ui_px(tab_bar_rv_diff-1.f, 1.f)); } else { ui_spacer(ui_px(1.f, 1.f)); } ui_set_next_group_key(catchall_drop_site_key); UI_Box *tab_box = ui_build_box_from_key(UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_Clickable, ui_key_zero()); } // rjf: space for next tab { ui_spacer(ui_px(floor_f32(ui_top_font_size()*0.4f), 1.f)); } } } // rjf: build add-new-tab button UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_px(tab_bar_vheight, 1.f)) UI_PrefHeight(ui_px(tab_bar_vheight, 1.f)) UI_TagF(".") { ui_set_next_child_layout_axis(Axis2_Y); UI_Box *container = ui_build_box_from_stringf(!is_changing_panel_boundaries*UI_BoxFlag_AnimatePosX, "###add_new_tab"); UI_Parent(container) { if(panel->tab_side == Side_Max) { ui_spacer(ui_px(tab_bar_rv_diff-1.f, 1.f)); } else { ui_spacer(ui_px(1.f, 1.f)); } UI_CornerRadius00(panel->tab_side == Side_Min ? corner_radius : 0) UI_CornerRadius10(panel->tab_side == Side_Min ? corner_radius : 0) UI_CornerRadius01(panel->tab_side == Side_Max ? corner_radius : 0) UI_CornerRadius11(panel->tab_side == Side_Max ? corner_radius : 0) RD_Font(RD_FontSlot_Icons) UI_FontSize(ui_top_font_size()) UI_TagF("implicit") UI_TagF("weak") { UI_Box *add_new_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_Clickable| UI_BoxFlag_DisableTextTrunc, "%S##add_new_tab_button_%p", rd_icon_kind_text_table[RD_IconKind_Add], panel->cfg); UI_Signal sig = ui_signal_from_box(add_new_box); if(ui_pressed(sig)) { rd_cmd(RD_CmdKind_FocusPanel, .panel = panel->cfg->id); if(ws->query_is_active && ui_key_match(add_new_box->key, ws->query_regs->ui_key)) { rd_cmd(RD_CmdKind_CancelQuery); } else { rd_cmd(RD_CmdKind_PushQuery, .expr = str8_lit("query:tab_commands"), .panel = panel->cfg->id, .do_implicit_root = 1, .do_lister = 1, .ui_key = add_new_box->key); } } } } } // rjf: interact with tab bar ui_signal_from_box(tab_bar_box); } ////////////////////////// //- rjf: accept tab drops // if(tab_drop_is_active && rd_drag_drop() && rd_state->drag_drop_regs_slot == RD_RegSlot_View) { rd_cmd(RD_CmdKind_MoveView, .dst_panel = panel->cfg->id, .panel = rd_state->drag_drop_regs->panel, .view = rd_state->drag_drop_regs->view, .prev_tab = tab_drop_prev->id); } ////////////////////////// //- rjf: accept file drops // { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_FileDrop && contains_2f32(content_rect, evt->pos)) { B32 need_drop_completion = 0; arena_clear(ws->drop_completion_arena); ws->top_drop_completion_task = 0; ws->drop_completion_panel = panel->cfg->id; String8List exe_paths = {0}; String8List dbg_paths = {0}; for(String8Node *n = evt->paths.first; n != 0; n = n->next) { Temp scratch = scratch_begin(0, 0); String8 path = n->string; String8 ext = str8_skip_last_dot(path); if(str8_match(ext, str8_lit("exe"), StringMatchFlag_CaseInsensitive)) { str8_list_push(ws->drop_completion_arena, &exe_paths, str8_copy(ws->drop_completion_arena, path)); } else if(str8_match(ext, str8_lit("pdb"), StringMatchFlag_CaseInsensitive) || str8_match(ext, str8_lit("rdi"), StringMatchFlag_CaseInsensitive)) { str8_list_push(ws->drop_completion_arena, &dbg_paths, str8_copy(ws->drop_completion_arena, path)); } else { rd_cmd(RD_CmdKind_Open, .file_path = path, .panel = panel->cfg->id); } scratch_end(scratch); } if(dbg_paths.node_count != 0) { RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1); SLLStackPush(ws->top_drop_completion_task, t); t->dbg = 1; t->paths = dbg_paths; } if(exe_paths.node_count != 0) { RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1); SLLStackPush(ws->top_drop_completion_task, t); t->exe = 1; t->paths = exe_paths; } if(ws->top_drop_completion_task != 0) { ui_ctx_menu_open(rd_state->drop_completion_key, ui_key_zero(), evt->pos); } ui_eat_event(evt); } } } } } } //////////////////////////// //- rjf: @window_ui_part drag/drop cancelling // if(rd_drag_is_active() && ui_slot_press(UI_EventActionSlot_Cancel)) { rd_drag_kill(); ui_kill_action(); } //////////////////////////// //- rjf: @window_ui_part top-level font size changing // for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Scroll && evt->modifiers == OS_Modifier_Ctrl) { ui_eat_event(evt); if(evt->delta_2f32.y < 0) { rd_cmd(RD_CmdKind_IncWindowFontSize); } else if(evt->delta_2f32.y > 0) { rd_cmd(RD_CmdKind_DecWindowFontSize); } } } ui_end_build(); } ////////////////////////////// //- rjf: @window_frame_part hover eval cancelling // if(ws->hover_eval_string.size != 0 && ui_slot_press(UI_EventActionSlot_Cancel)) { MemoryZeroStruct(&ws->hover_eval_string); arena_clear(ws->hover_eval_arena); ws->hover_eval_focused = 0; rd_request_frame(); } ////////////////////////////// //- rjf: @window_frame_part animate // if(ui_animating_from_state(ws->ui)) { rd_request_frame(); } ////////////////////////////// //- rjf: @window_frame_part draw UI // ws->draw_bucket = dr_bucket_make(); DR_BucketScope(ws->draw_bucket) ProfScope("draw UI") { Temp scratch = scratch_begin(0, 0); F32 box_squish_epsilon = 0.001f; Rng2F32 window_rect = os_client_rect_from_window(ws->os); //- rjf: unpack settings F32 rounded_corner_amount = rd_setting_f32_from_name(str8_lit("rounded_corner_amount")); F32 border_softness = 1.f; B32 do_background_blur = rd_setting_b32_from_name(str8_lit("background_blur")); B32 force_opaque_floating_backgrounds = rd_setting_b32_from_name(str8_lit("opaque_backgrounds")); B32 do_drop_shadows = rd_setting_b32_from_name(str8_lit("drop_shadows")); Vec4F32 base_background_color = ui_color_from_name(str8_lit("background")); Vec4F32 base_border_color = ui_color_from_name(str8_lit("border")); Vec4F32 drop_shadow_color = ui_color_from_name(str8_lit("drop_shadow")); //- rjf: set up heatmap buckets F32 heatmap_bucket_size = 32.f; U64 *heatmap_buckets = 0; U64 heatmap_bucket_pitch = 0; U64 heatmap_bucket_count = 0; if(DEV_draw_ui_box_heatmap) { Rng2F32 rect = os_client_rect_from_window(ws->os); Vec2F32 size = dim_2f32(rect); Vec2S32 buckets_dim = {(S32)(size.x/heatmap_bucket_size), (S32)(size.y/heatmap_bucket_size)}; heatmap_bucket_pitch = buckets_dim.x; heatmap_bucket_count = buckets_dim.x*buckets_dim.y; heatmap_buckets = push_array(scratch.arena, U64, heatmap_bucket_count); } //- rjf: draw background color { dr_rect(os_client_rect_from_window(ws->os), base_background_color, 0, 0, 0); } //- rjf: draw window border { dr_rect(os_client_rect_from_window(ws->os), base_border_color, 0, 1.f, border_softness*0.5f); } //- rjf: recurse & draw U64 total_heatmap_sum_count = 0; UI_Box *hover_debug_box = &ui_nil_box; for(UI_Box *box = ui_root_from_state(ws->ui); !ui_box_is_nil(box);) { // rjf: get corner radii F32 box_corner_radii[Corner_COUNT] = { box->corner_radii[Corner_00]*rounded_corner_amount, box->corner_radii[Corner_01]*rounded_corner_amount, box->corner_radii[Corner_10]*rounded_corner_amount, box->corner_radii[Corner_11]*rounded_corner_amount, }; // rjf: get recursion UI_BoxRec rec = ui_box_rec_df_post(box, &ui_nil_box); // rjf: sum to box heatmap if(DEV_draw_ui_box_heatmap) { Vec2F32 center = center_2f32(box->rect); Vec2S32 p = v2s32(center.x / heatmap_bucket_size, center.y / heatmap_bucket_size); U64 bucket_idx = p.y * heatmap_bucket_pitch + p.x; if(bucket_idx < heatmap_bucket_count) { heatmap_buckets[bucket_idx] += 1; total_heatmap_sum_count += 1; } } // rjf: grab if debug if(box->flags & UI_BoxFlag_Debug && contains_2f32(box->rect, ui_mouse())) { hover_debug_box = box; } // rjf: push transparency if(box->transparency != 0) { dr_push_transparency(box->transparency); } // rjf: push squish if(box->squish > box_squish_epsilon) { Vec2F32 box_dim = dim_2f32(box->rect); Vec2F32 anchor_off = {0}; if(box->flags & UI_BoxFlag_SquishAnchored) { anchor_off.x = box_dim.x/2.f; } else { anchor_off.y = -box_dim.y/8.f; } Mat3x3F32 box2origin_xform = make_translate_3x3f32(v2f32(-box->rect.x0 - box_dim.x/2 + anchor_off.x, -box->rect.y0 + anchor_off.y)); Mat3x3F32 scale_xform = make_scale_3x3f32(v2f32(1-box->squish, 1-box->squish)); Mat3x3F32 origin2box_xform = make_translate_3x3f32(v2f32(box->rect.x0 + box_dim.x/2 - anchor_off.x, box->rect.y0 - anchor_off.y)); Mat3x3F32 xform = mul_3x3f32(origin2box_xform, mul_3x3f32(scale_xform, box2origin_xform)); dr_push_xform2d(xform); dr_push_tex2d_sample_kind(R_Tex2DSampleKind_Linear); } // rjf: draw drop shadow if(do_drop_shadows && box->flags & UI_BoxFlag_DrawDropShadow) { Rng2F32 drop_shadow_rect = shift_2f32(pad_2f32(box->rect, 8), v2f32(4, 4)); R_Rect2DInst *inst = dr_rect(drop_shadow_rect, drop_shadow_color, 0.8f, 0, 8.f); MemoryCopyArray(inst->corner_radii, box_corner_radii); } // rjf: blur background if(do_background_blur && box->flags & UI_BoxFlag_DrawBackgroundBlur) { R_PassParams_Blur *params = dr_blur(pad_2f32(box->rect, 1.f), box->blur_size*(1-box->transparency), 0); MemoryCopyArray(params->corner_radii, box_corner_radii); } // rjf: compute effective active t F32 effective_active_t = box->active_t; if(!(box->flags & UI_BoxFlag_DrawActiveEffects)) { effective_active_t = 0; } F32 t = box->hot_t*(1-effective_active_t); // rjf: compute background color Vec4F32 box_background_color = box->background_color; if(force_opaque_floating_backgrounds && box->flags & UI_BoxFlag_Floating && box->flags & UI_BoxFlag_DrawDropShadow) { box_background_color.w = 1.f; } // rjf: draw background if(box->flags & UI_BoxFlag_DrawBackground) { // rjf: hot effect extension (drop shadow) if(box->flags & UI_BoxFlag_DrawHotEffects) { Rng2F32 drop_shadow_rect = shift_2f32(pad_2f32(box->rect, 8), v2f32(4, 4)); Vec4F32 color = drop_shadow_color; color.w *= t*box_background_color.w; dr_rect(drop_shadow_rect, color, 0.8f, 0, 8.f); } // rjf: draw background R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, 1.f), box_background_color, 0, 0, border_softness*1.f); MemoryCopyArray(inst->corner_radii, box_corner_radii); // rjf: hot effect extension if(box->flags & UI_BoxFlag_DrawHotEffects) { B32 is_hot = !ui_key_match(box->key, ui_key_zero()) && ui_key_match(box->key, ui_hot_key()); Vec4F32 hover_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("hover")); // rjf: brighten { Vec4F32 color = hover_color; color.w *= 0.05f; if(!is_hot) { color.w *= t; } R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, 1.f), v4f32(0, 0, 0, 0), 0, 0, border_softness*1.f); inst->colors[Corner_00] = color; inst->colors[Corner_10] = color; MemoryCopyArray(inst->corner_radii, box_corner_radii); } // rjf: soft circle around mouse if(box->hot_t > 0.01f) DR_ClipScope(intersect_2f32(box->rect, dr_top_clip())) { Vec4F32 color = hover_color; color.w *= 0.02f; if(!is_hot) { color.w *= t; } Vec2F32 center = ui_mouse(); Vec2F32 box_dim = dim_2f32(box->rect); F32 max_dim = Max(box_dim.x, box_dim.y); F32 radius = box->font_size*12.f; radius = Min(max_dim, radius); dr_rect(pad_2f32(r2f32(center, center), radius), color, radius, 0, radius/3.f); } } // rjf: active effect extension if(box->flags & UI_BoxFlag_DrawActiveEffects) { Vec4F32 shadow_color = drop_shadow_color; shadow_color.w *= 0.5f*box->active_t; Vec2F32 shadow_size = { (box->rect.x1 - box->rect.x0)*0.60f*box->active_t, (box->rect.y1 - box->rect.y0)*0.60f*box->active_t, }; shadow_size.x = Clamp(0, shadow_size.x, box->font_size*2.f); shadow_size.y = Clamp(0, shadow_size.y, box->font_size*2.f); // rjf: top -> bottom dark effect { R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->rect.y0, box->rect.x1, box->rect.y0 + shadow_size.y), v4f32(0, 0, 0, 0), 0, 0, 1.f); inst->colors[Corner_00] = inst->colors[Corner_10] = shadow_color; inst->colors[Corner_01] = inst->colors[Corner_11] = v4f32(0.f, 0.f, 0.f, 0.0f); MemoryCopyArray(inst->corner_radii, box_corner_radii); } // rjf: bottom -> top light effect { R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->rect.y1 - shadow_size.y, box->rect.x1, box->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1.f); inst->colors[Corner_00] = inst->colors[Corner_10] = v4f32(0, 0, 0, 0); inst->colors[Corner_01] = inst->colors[Corner_11] = v4f32(1.0f, 1.0f, 1.0f, 0.08f*box->active_t); MemoryCopyArray(inst->corner_radii, box_corner_radii); } // rjf: left -> right dark effect { R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->rect.y0, box->rect.x0 + shadow_size.x, box->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1.f); inst->colors[Corner_10] = inst->colors[Corner_11] = v4f32(0.f, 0.f, 0.f, 0.f); inst->colors[Corner_00] = shadow_color; inst->colors[Corner_01] = shadow_color; MemoryCopyArray(inst->corner_radii, box_corner_radii); } // rjf: right -> left dark effect { R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x1 - shadow_size.x, box->rect.y0, box->rect.x1, box->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1.f); inst->colors[Corner_00] = inst->colors[Corner_01] = v4f32(0.f, 0.f, 0.f, 0.f); inst->colors[Corner_10] = shadow_color; inst->colors[Corner_11] = shadow_color; MemoryCopyArray(inst->corner_radii, box_corner_radii); } } } // rjf: draw string if(box->flags & UI_BoxFlag_DrawText) { Vec2F32 text_position = ui_box_text_position(box); if(DEV_draw_ui_text_pos) { dr_rect(r2f32p(text_position.x-4, text_position.y-4, text_position.x+4, text_position.y+4), v4f32(1, 0, 1, 1), 1, 0, 1); } F32 max_x = 100000.f; FNT_Run ellipses_run = {0}; if(!(box->flags & UI_BoxFlag_DisableTextTrunc)) { FNT_Tag ellipses_font = box->font; F32 ellipses_size = box->font_size; FNT_RasterFlags ellipses_raster_flags = box->text_raster_flags; if(box->display_fstrs.last) { ellipses_font = box->display_fstrs.last->v.params.font; ellipses_size = box->display_fstrs.last->v.params.size; ellipses_raster_flags = box->display_fstrs.last->v.params.raster_flags; } max_x = (box->rect.x1-text_position.x); ellipses_run = fnt_run_from_string(ellipses_font, ellipses_size, 0, box->tab_size, ellipses_raster_flags, str8_lit("...")); } if(box->flags & UI_BoxFlag_HasFuzzyMatchRanges) UI_TagF("match") { Vec4F32 match_color = ui_color_from_tags_key_name(ui_top_tags_key(), str8_lit("background")); dr_truncated_fancy_run_fuzzy_matches(text_position, &box->display_fruns, max_x, &box->fuzzy_match_ranges, match_color); } dr_truncated_fancy_run_list(text_position, &box->display_fruns, max_x, ellipses_run); } // rjf: draw focus viz if(DEV_draw_ui_focus_debug) { B32 focused = (box->flags & (UI_BoxFlag_FocusHot|UI_BoxFlag_FocusActive) && box->flags & UI_BoxFlag_Clickable); B32 disabled = 0; for(UI_Box *p = box; !ui_box_is_nil(p); p = p->parent) { if(p->flags & (UI_BoxFlag_FocusHotDisabled|UI_BoxFlag_FocusActiveDisabled)) { disabled = 1; break; } } if(focused) { Vec4F32 color = v4f32(0.3f, 0.8f, 0.3f, 1.f); if(disabled) { color = v4f32(0.8f, 0.3f, 0.3f, 1.f); } dr_rect(r2f32p(box->rect.x0-6, box->rect.y0-6, box->rect.x0+6, box->rect.y0+6), color, 2, 0, 1); dr_rect(box->rect, color, 2, 2, 1); } if(box->flags & (UI_BoxFlag_FocusHot|UI_BoxFlag_FocusActive)) { if(box->flags & (UI_BoxFlag_FocusHotDisabled|UI_BoxFlag_FocusActiveDisabled)) { dr_rect(r2f32p(box->rect.x0-6, box->rect.y0-6, box->rect.x0+6, box->rect.y0+6), v4f32(1, 0, 0, 0.2f), 2, 0, 1); } else { dr_rect(r2f32p(box->rect.x0-6, box->rect.y0-6, box->rect.x0+6, box->rect.y0+6), v4f32(0, 1, 0, 0.2f), 2, 0, 1); } } } // rjf: push clip if(box->flags & UI_BoxFlag_Clip) { Rng2F32 top_clip = dr_top_clip(); Rng2F32 new_clip = pad_2f32(box->rect, -1); if(top_clip.x1 != 0 || top_clip.y1 != 0) { new_clip = intersect_2f32(new_clip, top_clip); } dr_push_clip(new_clip); } // rjf: custom draw list if(box->flags & UI_BoxFlag_DrawBucket) { Mat3x3F32 xform = make_translate_3x3f32(box->position_delta); DR_XForm2DScope(xform) { dr_sub_bucket(box->draw_bucket); } } // rjf: call custom draw callback if(box->custom_draw != 0) { box->custom_draw(box, box->custom_draw_user_data); } // rjf: pop { S32 pop_idx = 0; for(UI_Box *b = box; !ui_box_is_nil(b) && pop_idx <= rec.pop_count; b = b->parent) { pop_idx += 1; if(b == box && rec.push_count != 0) { continue; } // rjf: pop clips if(b->flags & UI_BoxFlag_Clip) { dr_pop_clip(); } // rjf: get corner radii F32 b_corner_radii[Corner_COUNT] = { b->corner_radii[Corner_00]*rounded_corner_amount, b->corner_radii[Corner_01]*rounded_corner_amount, b->corner_radii[Corner_10]*rounded_corner_amount, b->corner_radii[Corner_11]*rounded_corner_amount, }; // rjf: draw border if(b->flags & UI_BoxFlag_DrawBorder) { Vec4F32 border_color = b->border_color; Rng2F32 b_border_rect = pad_2f32(b->rect, 1.f); R_Rect2DInst *inst = dr_rect(b_border_rect, border_color, 0, 1.f, border_softness*1.f); MemoryCopyArray(inst->corner_radii, b_corner_radii); // rjf: hover effect if(b->flags & UI_BoxFlag_DrawHotEffects) { Vec4F32 color = ui_color_from_tags_key_name(box->tags_key, str8_lit("hover")); if(ui_key_match(b->key, ui_key_zero()) || !ui_key_match(b->key, ui_hot_key())) { color.w *= b->hot_t; } color.w *= 0.01f; R_Rect2DInst *inst = dr_rect(b_border_rect, color, 0, 1.f, 1.f); MemoryCopyArray(inst->corner_radii, b_corner_radii); } } // rjf: debug border rendering if(b->flags & UI_BoxFlag_Debug) { R_Rect2DInst *inst = dr_rect(b->rect, v4f32(1*box->pref_size[Axis2_X].strictness, 0, 1, 0.25f), 0, 1.f, 0); MemoryCopyArray(inst->corner_radii, b_corner_radii); } // rjf: draw sides if(b->flags & (UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight)) { Vec4F32 border_color = b->border_color; Rng2F32 r = b->rect; F32 half_thickness = 1.f; F32 softness = 0.f; if(b->flags & UI_BoxFlag_DrawSideTop) { dr_rect(r2f32p(r.x0, r.y0, r.x1, r.y0+2*half_thickness), border_color, 0, 0, softness); } if(b->flags & UI_BoxFlag_DrawSideBottom) { dr_rect(r2f32p(r.x0, r.y1-2*half_thickness, r.x1, r.y1), border_color, 0, 0, softness); } if(b->flags & UI_BoxFlag_DrawSideLeft) { dr_rect(r2f32p(r.x0, r.y0, r.x0+2*half_thickness, r.y1), border_color, 0, 0, softness); } if(b->flags & UI_BoxFlag_DrawSideRight) { dr_rect(r2f32p(r.x1-2*half_thickness, r.y0, r.x1, r.y1), border_color, 0, 0, softness); } } // rjf: draw focus overlay if(b->flags & UI_BoxFlag_Clickable && !(b->flags & UI_BoxFlag_DisableFocusOverlay) && b->focus_hot_t > 0.01f) { String8 extras[] = {str8_lit("focus"), str8_lit("overlay")}; String8Array extras_array = {extras, ArrayCount(extras)}; Vec4F32 color = ui_color_from_tags_key_extras(b->tags_key, extras_array); color.w *= b->focus_hot_t; R_Rect2DInst *inst = dr_rect(b->rect, color, 0, 0, 0.f); MemoryCopyArray(inst->corner_radii, b_corner_radii); } // rjf: draw focus border if(b->flags & UI_BoxFlag_Clickable && !(b->flags & UI_BoxFlag_DisableFocusBorder) && b->focus_active_t > 0.01f) { Rng2F32 rect = b->rect; if(b->flags & UI_BoxFlag_Floating) { rect = pad_2f32(rect, 1.f); rect = intersect_2f32(window_rect, rect); } String8 extras[] = {str8_lit("focus"), str8_lit("border")}; String8Array extras_array = {extras, ArrayCount(extras)}; Vec4F32 color = ui_color_from_tags_key_extras(b->tags_key, extras_array); color.w *= b->focus_active_t; R_Rect2DInst *inst = dr_rect(rect, color, 0, 1.f, border_softness*1.f); MemoryCopyArray(inst->corner_radii, b_corner_radii); } // rjf: disabled overlay if(b->disabled_t >= 0.005f) { Vec4F32 disabled_overlay_color = v4f32(base_background_color.x, base_background_color.y, base_background_color.z, b->disabled_t*0.3f); R_Rect2DInst *inst = dr_rect(b->rect, disabled_overlay_color, 0, 0, 1); MemoryCopyArray(inst->corner_radii, b_corner_radii); } // rjf: pop squish if(b->squish > box_squish_epsilon) { dr_pop_xform2d(); dr_pop_tex2d_sample_kind(); } // rjf: pop transparency if(b->transparency != 0) { dr_pop_transparency(); } } } // rjf: next box = rec.next; } //- rjf: draw heatmap if(DEV_draw_ui_box_heatmap) { U64 uniform_dist_count = total_heatmap_sum_count / heatmap_bucket_count; uniform_dist_count = ClampBot(uniform_dist_count, 10); for(U64 bucket_idx = 0; bucket_idx < heatmap_bucket_count; bucket_idx += 1) { U64 x = bucket_idx % heatmap_bucket_pitch; U64 y = bucket_idx / heatmap_bucket_pitch; U64 bucket = heatmap_buckets[bucket_idx]; F32 pct = (F32)bucket / uniform_dist_count; pct = Clamp(0, pct, 1); Vec3F32 hsv = v3f32((1-pct) * 0.9411f, 1, 0.5f); Vec3F32 rgb = rgb_from_hsv(hsv); Rng2F32 rect = r2f32p(x*heatmap_bucket_size, y*heatmap_bucket_size, (x+1)*heatmap_bucket_size, (y+1)*heatmap_bucket_size); dr_rect(rect, v4f32(rgb.x, rgb.y, rgb.z, 0.3f), 0, 0, 0); } } //- rjf: draw hover debug box if(hover_debug_box != &ui_nil_box) { FNT_Tag font = rd_font_from_slot(RD_FontSlot_Code); Vec2F32 p = ui_mouse(); dr_rect(hover_debug_box->rect, v4f32(1, 1, 1, 0.2f), 0, 0, 0); dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "key: 0x%I64x", hover_debug_box->key.u64[0])); p.y += 20.f; dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "string: '%S'", hover_debug_box->string)); p.y += 20.f; } //- rjf: draw border/overlay color to signify error if(ws->error_t > 0.01f) UI_TagF("bad") { Vec4F32 color = ui_color_from_name(str8_lit("text")); color.w *= ws->error_t; Rng2F32 rect = os_client_rect_from_window(ws->os); dr_rect(pad_2f32(rect, 24.f), color, 0, 16.f, 12.f); dr_rect(rect, v4f32(color.x, color.y, color.z, color.w*0.025f), 0, 0, 0); } //- rjf: draw border/overlay color to signify rebinding if(rd_state->bind_change_active) UI_TagF("pop") { Vec4F32 color = ui_color_from_name(str8_lit("background")); Rng2F32 rect = os_client_rect_from_window(ws->os); dr_rect(pad_2f32(rect, 24.f), color, 0, 16.f, 12.f); dr_rect(rect, v4f32(color.x, color.y, color.z, color.w*0.025f), 0, 0, 0); } scratch_end(scratch); } ////////////////////////////// //- rjf: @window_frame_part update per-window frame counters/info // ws->frames_alive += 1; ws->last_window_rect = os_client_rect_from_window(ws->os); ProfEnd(); scratch_end(scratch); } #if COMPILER_MSVC && !BUILD_DEBUG NO_OPTIMIZE_END #endif //////////////////////////////// //~ rjf: Eval Visualization internal String8 rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringParams *params, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval) { Temp scratch = scratch_begin(&arena, 1); String8List strs = {0}; { EV_StringIter *iter = ev_string_iter_begin(scratch.arena, eval, params); F32 space_taken_px = 0; for(String8 string = {0}; ev_string_iter_next(scratch.arena, iter, &string);) { if(space_taken_px > max_size) { str8_list_push(scratch.arena, &strs, str8_lit("...")); break; } else { str8_list_push(scratch.arena, &strs, string); space_taken_px += fnt_dim_from_tag_size_string(font, font_size, 0, 0, string).x; } } } String8 result = str8_list_join(arena, &strs, 0); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Hover Eval internal void rd_set_hover_eval(Vec2F32 pos, String8 string) { CFG_Node *window_cfg = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window_cfg); if(ws->hover_eval_lastt_us < rd_state->time_in_us && ui_key_match(ui_active_key(UI_MouseButtonKind_Left), ui_key_zero()) && ui_key_match(ui_active_key(UI_MouseButtonKind_Middle), ui_key_zero()) && ui_key_match(ui_active_key(UI_MouseButtonKind_Right), ui_key_zero())) { B32 is_new_string = (!str8_match(ws->hover_eval_string, string, 0)); if(is_new_string) { ws->hover_eval_firstt_us = ws->hover_eval_lastt_us = rd_state->time_in_us; arena_clear(ws->hover_eval_arena); ws->hover_eval_string = push_str8_copy(ws->hover_eval_arena, string); ws->hover_eval_focused = 0; } ws->hover_eval_spawn_pos = pos; ws->hover_eval_lastt_us = rd_state->time_in_us; } } //////////////////////////////// //~ rjf: Autocompletion Lister internal void rd_set_autocomp_regs_(E_Eval dst_eval, RD_Regs *regs) { CFG_Node *window_cfg = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window_cfg); if(ws->autocomp_last_frame_index < rd_state->frame_index) { arena_clear(ws->autocomp_arena); //- rjf: calculate information about the cursor: // * what list should we generate? // * what string in the input should we replace? // etc. B32 is_allowed = 0; RD_AutocompCursorInfo cursor_info = {0}; { Temp scratch = scratch_begin(0, 0); // rjf: calculate most general list expression, given the dst_eval space B32 force_allow = 0; B32 expr_based_replace = 1; String8 list_expr = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types, query:constants"); { E_TypeKey maybe_enum_type = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums); if(dst_eval.space.kind == RD_EvalSpaceKind_MetaCfg) { CFG_Node *parent = rd_cfg_from_eval_space(dst_eval.space); String8 child_key = e_string_from_id(dst_eval.space.u64s[1]); MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, parent->string); MD_Node *child_schema = &md_nil_node; for(MD_NodePtrNode *n = schemas.first; n != 0 && md_node_is_nil(child_schema); n = n->next) { child_schema = md_child_from_string(n->v, child_key, 0); } if(str8_match(child_key, str8_lit("theme"), 0)) { list_expr = str8_lit("query:themes"); expr_based_replace = 0; force_allow = 1; } else if(!str8_match(child_schema->first->string, str8_lit("expr_string"), 0)) { MemoryZeroStruct(&list_expr); } } } // rjf: determine if autocompletion lister is allowed is_allowed = (force_allow || rd_setting_b32_from_name(str8_lit("autocompletion_lister"))); // rjf: tighten list_expr, and filter / replaced-range, if needed String8 filter = regs->string; Rng1U64 replaced_range = r1u64(0, filter.size); String8 callee_expr = {0}; U64 cursor_arg_idx = 0; if(expr_based_replace) { U64 cursor_off = (U64)(regs->cursor.column-1); E_Parse parse = e_parse_from_string(regs->string); //- rjf: cursor offset -> cursor containing node E_Expr *cursor_expr = &e_expr_nil; E_Expr *cursor_expr_parent = &e_expr_nil; { typedef struct ExprWalkTask ExprWalkTask; struct ExprWalkTask { ExprWalkTask *next; E_Expr *parent; E_Expr *expr; S32 depth; }; ExprWalkTask start_task = {0, &e_expr_nil, parse.expr}; ExprWalkTask *first_task = &start_task; ExprWalkTask *last_task = first_task; S32 best_depth = 0; for(E_Expr *chain = parse.expr->next; chain != &e_expr_nil; chain = chain->next) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); SLLQueuePush(first_task, last_task, task); task->parent = &e_expr_nil; task->expr = chain; } for(ExprWalkTask *t = first_task; t != 0; t = t->next) { E_Expr *e = t->expr; if(t->depth >= best_depth && (contains_1u64(e->range, cursor_off) || cursor_off == e->range.max)) { cursor_expr_parent = t->parent; cursor_expr = e; best_depth = t->depth; } for(E_Expr *child = e->first; child != &e_expr_nil; child = child->next) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); SLLQueuePush(first_task, last_task, task); task->parent = e; task->expr = child; task->depth = t->depth+1; } } } //- rjf: cursor is within a call? -> generate an expression for the callee, determine // which argument the cursor is on if(cursor_expr_parent->kind == E_ExprKind_Call) { E_Key callee_key = e_key_from_expr(cursor_expr_parent->first); callee_expr = e_full_expr_string_from_key(scratch.arena, callee_key); for(E_Expr *arg = cursor_expr->prev; arg != cursor_expr_parent->first && arg != &e_expr_nil; arg = arg->prev) { cursor_arg_idx += 1; } } else if(cursor_expr->kind == E_ExprKind_Call) { E_Key callee_key = e_key_from_expr(cursor_expr->first); callee_expr = e_full_expr_string_from_key(scratch.arena, callee_key); for(E_Expr *arg = cursor_expr->first->next; arg != &e_expr_nil; arg = arg->next) { cursor_arg_idx += 1; } } //- rjf: cursor is on right-hand-side of dot? -> show members of left-hand-side B32 did_special_cursor_case = 0; if(!did_special_cursor_case) { E_Expr *dot_expr = &e_expr_nil; if(cursor_expr->kind == E_ExprKind_MemberAccess && cursor_off == cursor_expr->range.max) { dot_expr = cursor_expr; } else if(cursor_expr_parent->kind == E_ExprKind_MemberAccess && cursor_expr == cursor_expr_parent->first->next) { dot_expr = cursor_expr_parent; } if(dot_expr != &e_expr_nil) { did_special_cursor_case = 1; E_Eval lhs_eval = e_eval_from_expr(dot_expr->first); E_Eval type_of_lhs_eval = e_eval_wrapf(lhs_eval, "typeof($)"); list_expr = e_full_expr_string_from_key(scratch.arena, type_of_lhs_eval.key); filter = cursor_expr->string; replaced_range = union_1u64(dot_expr->range, cursor_expr->range); } } //- rjf: cursor is on a leaf-identifier? -> replace just that identifier, keep the original list expression if(!did_special_cursor_case && cursor_expr->kind == E_ExprKind_LeafIdentifier) { did_special_cursor_case = 1; filter = str8_prefix(cursor_expr->string, cursor_off - cursor_expr->range.min); replaced_range = cursor_expr->range; } } // rjf: try to map the cursor, within a call, to some schema MD_Node *arg_schema = &md_nil_node; if(callee_expr.size != 0) { E_Eval callee_eval = e_eval_from_string(callee_expr); E_Type *callee_type = e_type_from_key(callee_eval.irtree.type_key); if(callee_type->kind == E_TypeKind_LensSpec) { U64 arg_idx = 0; MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, callee_type->name); for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; for MD_EachNode(child, schema->first) { if(!md_node_has_tag(child, str8_lit("no_callee_helper"), 0)) { if(cursor_arg_idx == arg_idx) { arg_schema = child; goto end_schema_search; } arg_idx += 1; } } } end_schema_search:; } } // rjf: fill bundle cursor_info.list_expr = push_str8_copy(ws->autocomp_arena, list_expr); cursor_info.filter = push_str8_copy(ws->autocomp_arena, filter); cursor_info.replaced_range = replaced_range; cursor_info.callee_expr = push_str8_copy(ws->autocomp_arena, callee_expr); cursor_info.arg_schema = arg_schema; scratch_end(scratch); } //- rjf: commit autocompletion info if(is_allowed) { ws->autocomp_last_frame_index = rd_state->frame_index; ws->autocomp_regs = rd_regs_copy(ws->autocomp_arena, regs); ws->autocomp_cursor_info = cursor_info; } } } //////////////////////////////// //~ rjf: Colors, Fonts, Config //- rjf: colors internal MD_Node * rd_theme_tree_from_name(Arena *arena, Access *access, String8 theme_name) { Temp scratch = scratch_begin(&arena, 1); MD_Node *theme_tree = &md_nil_node; if(theme_name.size != 0) { for EachEnumVal(RD_ThemePreset, p) { if(str8_match(theme_name, rd_theme_preset_display_string_table[p], 0)) { theme_tree = rd_state->theme_preset_trees[p]; break; } } if(theme_tree == &md_nil_node) { String8 path = push_str8f(scratch.arena, "%S/raddbg/themes/%S", os_get_process_info()->user_program_data_path, theme_name); U64 endt_us = os_now_microseconds()+100; if(rd_state->frame_index <= 5) { endt_us = os_now_microseconds()+50000; } U128 hash = fs_hash_from_path_range(path, r1u64(0, max_U64), endt_us); String8 data = c_data_from_hash(access, hash); theme_tree = md_tree_from_string(arena, data); } } scratch_end(scratch); return theme_tree; } internal Vec4F32 rd_rgba_from_code_color_slot(RD_CodeColorSlot slot) { RD_WindowState *ws = rd_window_state_from_cfg(cfg_node_from_id(rd_regs()->window)); Vec4F32 result = ws->theme_code_colors[slot]; return result; } internal RD_CodeColorSlot rd_code_color_slot_from_txt_token_kind(TXT_TokenKind kind) { RD_CodeColorSlot color = RD_CodeColorSlot_CodeDefault; switch(kind) { default:break; case TXT_TokenKind_Keyword:{color = RD_CodeColorSlot_CodeKeyword;}break; case TXT_TokenKind_Numeric:{color = RD_CodeColorSlot_CodeNumeric;}break; case TXT_TokenKind_String: {color = RD_CodeColorSlot_CodeString;}break; case TXT_TokenKind_Meta: {color = RD_CodeColorSlot_CodeMeta;}break; case TXT_TokenKind_Comment:{color = RD_CodeColorSlot_CodeComment;}break; case TXT_TokenKind_Symbol: {color = RD_CodeColorSlot_CodeDelimiterOperator;}break; } return color; } internal RD_CodeColorSlot rd_code_color_slot_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 string) { RD_CodeColorSlot color = RD_CodeColorSlot_CodeDefault; if(kind == TXT_TokenKind_Identifier || kind == TXT_TokenKind_Keyword) { B32 mapped = 0; // rjf: try to map as local if(!mapped && kind == TXT_TokenKind_Identifier) { U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string); if(local_num != 0) { mapped = 1; color = RD_CodeColorSlot_CodeLocal; } } // rjf: try to map as member if(!mapped && kind == TXT_TokenKind_Identifier) { U64 member_num = e_num_from_string(e_ir_ctx->member_map, string); if(member_num != 0) { mapped = 1; color = RD_CodeColorSlot_CodeLocal; } } // rjf: try to map as register if(!mapped) { U64 reg_num = e_num_from_string(e_ir_ctx->regs_map, string); if(reg_num != 0) { mapped = 1; color = RD_CodeColorSlot_CodeRegister; } } // rjf: try to map as register alias if(!mapped) { U64 alias_num = e_num_from_string(e_ir_ctx->reg_alias_map, string); if(alias_num != 0) { mapped = 1; color = RD_CodeColorSlot_CodeRegister; } } // rjf: try to map using asynchronous matching system if(!mapped && kind == TXT_TokenKind_Identifier) { DI_Match match = di_match_from_string(string, 0, di_key_zero(), 0); RDI_SectionKind section_kind = match.section_kind; mapped = 1; switch(section_kind) { default:{mapped = 0;}break; case RDI_SectionKind_Procedures: case RDI_SectionKind_GlobalVariables: case RDI_SectionKind_ThreadVariables: { color = RD_CodeColorSlot_CodeSymbol; }break; case RDI_SectionKind_TypeNodes: { color = RD_CodeColorSlot_CodeType; }break; } } } return color; } //- rjf: fonts/sizes internal F32 rd_font_size(void) { F32 size = rd_setting_f32_from_name(str8_lit("font_size")); size = Clamp(6.f, size, 72.f); return size; } internal FNT_Tag rd_font_from_slot(RD_FontSlot slot) { FNT_Tag tag = rd_state->font_slot_table[slot]; return tag; } internal FNT_RasterFlags rd_raster_flags_from_slot(RD_FontSlot slot) { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); FNT_RasterFlags flags = ws->font_slot_raster_flags[slot]; return flags; } //////////////////////////////// //~ rjf: Process Control Info Stringification internal String8 rd_string_from_exception_code(U32 code) { String8 string = {0}; for EachNonZeroEnumVal(CTRL_ExceptionCodeKind, k) { if(code == ctrl_exception_code_kind_code_table[k]) { string = ctrl_exception_code_kind_display_string_table[k]; break; } } return string; } internal DR_FStrList rd_stop_explanation_fstrs_from_ctrl_event(Arena *arena, CTRL_Event *event) { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, event->entity); DR_FStrList thread_fstrs = rd_title_fstrs_from_ctrl_entity(arena, thread, 0); DR_FStrList fstrs = {0}; DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; switch(event->cause) { default: { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit("Not running")); }break; //- rjf: finished operation; if active thread, completed thread, otherwise we're just stopped case CTRL_EventCause_Finished: { if(thread != &ctrl_entity_nil) { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" completed step")); } else { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit("Stopped")); } }break; //- rjf: stopped at entry point case CTRL_EventCause_EntryPoint: { if(thread != &ctrl_entity_nil) { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" stopped at entry point")); } else { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit("Stopped at entry point")); } }break; //- rjf: user breakpoint case CTRL_EventCause_UserBreakpoint: { if(thread != &ctrl_entity_nil) { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_CircleFilled], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit a breakpoint")); if(event->vaddr_rng.min != 0) { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" (Address: ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, push_str8f(arena, "0x%I64x", event->vaddr_rng.min), .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(")")); } } }break; //- rjf: exception case CTRL_EventCause_InterruptedByException: { if(thread != &ctrl_entity_nil) { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_WarningBig], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); switch(event->exception_kind) { default: { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit an exception: ")); String8 exception_code_string = str8_from_u64(arena, event->exception_code, 16, 0, 0); String8 exception_explanation_string = rd_string_from_exception_code(event->exception_code); String8 exception_info_string = push_str8f(arena, "%S%s%S%s", exception_code_string, exception_explanation_string.size != 0 ? " (" : "", exception_explanation_string, exception_explanation_string.size != 0 ? ")" : ""); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_info_string); }break; case CTRL_ExceptionKind_CppThrow: { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit a C++ exception: ")); String8 exception_code_string = str8_from_u64(arena, event->exception_code, 16, 0, 0); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_code_string); }break; case CTRL_ExceptionKind_MemoryRead: { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit an exception: ")); String8 exception_info_string = push_str8f(arena, "Access violation reading from address 0x%I64x", event->vaddr_rng.min); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_info_string); }break; case CTRL_ExceptionKind_MemoryWrite: { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit an exception: ")); String8 exception_info_string = push_str8f(arena, "Access violation writing to address 0x%I64x", event->vaddr_rng.min); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_info_string); }break; case CTRL_ExceptionKind_MemoryExecute: { dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit an exception: ")); String8 exception_code_string = str8_from_u64(arena, event->exception_code, 16, 0, 0); String8 exception_info_string = push_str8f(arena, "Access violation executing at address 0x%I64x", event->vaddr_rng.min); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_info_string); }break; } } else { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_WarningBig], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" Hit an exception: ")); String8 exception_code_string = str8_from_u64(arena, event->exception_code, 16, 0, 0); String8 exception_explanation_string = rd_string_from_exception_code(event->exception_code); String8 exception_info_string = push_str8f(arena, "%S%s%S%s", exception_code_string, exception_explanation_string.size != 0 ? " (" : "", exception_explanation_string, exception_explanation_string.size != 0 ? ")" : ""); dr_fstrs_push_new(arena, &fstrs, ¶ms, exception_info_string); } }break; //- rjf: trap case CTRL_EventCause_InterruptedByTrap: { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_WarningBig], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_concat_in_place(&fstrs, &thread_fstrs); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" hit a trap")); }break; //- rjf: halt case CTRL_EventCause_InterruptedByHalt: { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_Pause], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" Halted")); }break; } return fstrs; } //////////////////////////////// //~ rjf: Vocab Info Lookups internal RD_VocabInfo * rd_vocab_info_from_code_name(String8 code_name) { RD_VocabInfo *result = &rd_nil_vocab_info; if(code_name.size != 0) { U64 hash = d_hash_from_string(code_name); U64 slot_idx = hash%rd_state->vocab_info_map.single_slots_count; for(RD_VocabInfoMapNode *n = rd_state->vocab_info_map.single_slots[slot_idx].first; n != 0; n = n->single_next) { if(str8_match(n->v.code_name, code_name, 0)) { result = &n->v; break; } } } return result; } internal RD_VocabInfo * rd_vocab_info_from_code_name_plural(String8 code_name_plural) { RD_VocabInfo *result = &rd_nil_vocab_info; if(code_name_plural.size != 0) { U64 hash = d_hash_from_string(code_name_plural); U64 slot_idx = hash%rd_state->vocab_info_map.plural_slots_count; for(RD_VocabInfoMapNode *n = rd_state->vocab_info_map.plural_slots[slot_idx].first; n != 0; n = n->plural_next) { if(str8_match(n->v.code_name_plural, code_name_plural, 0)) { result = &n->v; break; } } } return result; } //////////////////////////////// //~ rjf: Continuous Frame Requests internal void rd_request_frame(void) { rd_state->num_frames_requested = 4; } //////////////////////////////// //~ rjf: Main State Accessors //- rjf: per-frame arena internal Arena * rd_frame_arena(void) { return rd_state->frame_arenas[rd_state->frame_index%ArrayCount(rd_state->frame_arenas)]; } //////////////////////////////// //~ rjf: Registers internal RD_Regs * rd_push_regs_(RD_Regs *regs) { RD_RegsNode *n = push_array(rd_frame_arena(), RD_RegsNode, 1); rd_regs_copy_contents(rd_frame_arena(), &n->v, regs); SLLStackPush(rd_state->top_regs, n); return &n->v; } internal RD_Regs * rd_pop_regs(void) { RD_Regs *regs = &rd_state->top_regs->v; SLLStackPop(rd_state->top_regs); if(rd_state->top_regs == 0) { rd_state->top_regs = &rd_state->base_regs; } return regs; } internal void rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 query_expr, String8 string) { switch(slot) { //- rjf: basic string cases default: case RD_RegSlot_String: case RD_RegSlot_FilePath: { String8TxtPtPair pair = str8_txt_pt_pair_from_string(string); rd_regs()->string = push_str8_copy(rd_frame_arena(), string); if(pair.pt.line != 0) { rd_regs()->file_path = push_str8_copy(rd_frame_arena(), pair.string); rd_regs()->cursor = pair.pt; } }break; case RD_RegSlot_Expr: { rd_regs()->expr = push_str8_copy(rd_frame_arena(), string); }break; case RD_RegSlot_CmdName: { rd_regs()->cmd_name = push_str8_copy(rd_frame_arena(), string); }break; //- rjf: ctrl entities case RD_RegSlot_Machine: case RD_RegSlot_Module: case RD_RegSlot_Process: case RD_RegSlot_Thread: case RD_RegSlot_CtrlEntity: { }break; //- rjf: cfgs case RD_RegSlot_Cfg: case RD_RegSlot_Window: case RD_RegSlot_Panel: case RD_RegSlot_Tab: case RD_RegSlot_View: case RD_RegSlot_PrevTab: case RD_RegSlot_DstPanel: { B32 good = 0; if(!good && str8_match(str8_prefix(string, 1), str8_lit("$"), 0)) { String8 numeric_part = str8_skip(string, 1); CFG_ID id = u64_from_str8(numeric_part, 16); rd_regs()->cfg = id; good = 1; } if(!good && query_expr.size != 0) { Temp scratch = scratch_begin(0, 0); CFG_Node *immediate = rd_immediate_cfg_from_keyf("###regs_fill_slot_view"); CFG_Node *view = cfg_node_newf(rd_state->cfg, immediate, "watch"); cfg_node_newf(rd_state->cfg, view, "lister"); RD_ViewState *vs = rd_view_state_from_cfg(view); EV_View *eval_view = vs->ev_view; { ev_key_set_expansion(eval_view, ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); E_Eval eval = e_eval_from_string(query_expr); EV_BlockTree block_tree = {0}; EV_BlockRangeList block_ranges = {0}; // TODO(rjf): @cleanup we only need to do this because we implicitly use // view info in the block tree build via raddbg-layer eval hooks, but we // should really keep all parameterization info in eval views themselves, // to not couple block tree building with frontend state... RD_RegsScope(.window = 0, .panel = 0, .view = view->id) { block_tree = ev_block_tree_from_eval(scratch.arena, eval_view, string, eval); block_ranges = ev_block_range_list_from_tree(scratch.arena, &block_tree); if(block_ranges.first != 0) { block_ranges.count -= 1; block_ranges.first = block_ranges.first->next; } } EV_Row *row = ev_row_from_num(scratch.arena, eval_view, &block_ranges, 1); rd_regs()->cfg = rd_cfg_from_eval_space(row->eval.space)->id; good = (rd_regs()->cfg != 0); } scratch_end(scratch); } if(!good) { E_Eval eval = e_eval_from_string(string); rd_regs()->cfg = rd_cfg_from_eval_space(eval.space)->id; good = (rd_regs()->cfg != 0); } }break; //- rjf: line numbers case RD_RegSlot_Cursor: { E_Eval eval = e_value_eval_from_eval(e_eval_from_string(string)); if(eval.msgs.max_kind == E_MsgKind_Null) { rd_regs()->cursor.column = 1; rd_regs()->cursor.line = (S64)eval.value.u64; } else { log_user_errorf("Couldn't interpret \"`%S`\" as a line number.", string); } }break; case RD_RegSlot_Vaddr: goto use_numeric_eval; case RD_RegSlot_Voff: goto use_numeric_eval; case RD_RegSlot_UnwindCount: goto use_numeric_eval; case RD_RegSlot_InlineDepth: goto use_numeric_eval; case RD_RegSlot_PID: goto use_numeric_eval; use_numeric_eval: { E_Eval eval = e_eval_from_string(string); if(eval.msgs.max_kind == E_MsgKind_Null) { E_TypeKind eval_type_kind = e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)); if(eval_type_kind == E_TypeKind_Ptr || eval_type_kind == E_TypeKind_LRef || eval_type_kind == E_TypeKind_RRef || e_space_match(eval.space, e_base_ctx->thread_reg_space)) { eval = e_value_eval_from_eval(eval); } U64 u64 = eval.value.u64; MemoryCopy((U8 *)(rd_regs()) + rd_reg_slot_range_table[slot].min, &u64, dim_1u64(rd_reg_slot_range_table[slot])); } else { log_user_errorf("Couldn't evaluate `%S` as an address.", string); } }break; } } //////////////////////////////// //~ rjf: Commands //- rjf: name -> info internal RD_CmdKind rd_cmd_kind_from_string(String8 string) { RD_CmdKind result = RD_CmdKind_Null; for(U64 idx = 0; idx < ArrayCount(rd_cmd_kind_info_table); idx += 1) { if(str8_match(string, rd_cmd_kind_info_table[idx].string, 0)) { result = (RD_CmdKind)idx; break; } } return result; } internal RD_CmdKindInfo * rd_cmd_kind_info_from_string(String8 string) { RD_CmdKindInfo *info = &rd_nil_cmd_kind_info; { // TODO(rjf): @dynamic_cmds extend this by looking up into dynamically-registered commands by views RD_CmdKind kind = rd_cmd_kind_from_string(string); if(kind != RD_CmdKind_Null) { info = &rd_cmd_kind_info_table[kind]; } } return info; } //- rjf: pushing internal void rd_push_cmd(String8 name, RD_Regs *regs) { rd_cmd_list_push_new(rd_state->cmds_arenas[0], &rd_state->cmds[0], name, regs); } //- rjf: iterating internal B32 rd_next_cmd(RD_Cmd **cmd) { U64 slot = rd_state->cmds_gen%ArrayCount(rd_state->cmds); RD_CmdNode *start_node = rd_state->cmds[slot].first; if(cmd[0] != 0) { start_node = CastFromMember(RD_CmdNode, cmd, cmd[0]); start_node = start_node->next; } cmd[0] = 0; if(start_node != 0) { cmd[0] = &start_node->cmd; } return !!cmd[0]; } internal B32 rd_next_view_cmd(RD_Cmd **cmd) { for(;rd_next_cmd(cmd);) { if(rd_regs()->view == cmd[0]->regs->view) { break; } } B32 result = !!cmd[0]; return result; } //////////////////////////////// //~ rjf: Main Layer Top-Level Calls #if !defined(STBI_INCLUDE_STB_IMAGE_H) # define STB_IMAGE_IMPLEMENTATION # define STBI_ONLY_PNG # define STBI_ONLY_BMP # include "third_party/stb/stb_image.h" #endif internal void rd_init(CmdLine *cmdln) { ProfBeginFunction(); Arena *arena = arena_alloc(); rd_state = push_array(arena, RD_State, 1); rd_state->arena = arena; rd_state->quit_after_success = (cmd_line_has_flag(cmdln, str8_lit("quit_after_success")) || cmd_line_has_flag(cmdln, str8_lit("q"))); rd_state->user_path_arena = arena_alloc(); rd_state->project_path_arena = arena_alloc(); rd_state->theme_path_arena = arena_alloc(); rd_state->user_cfg_string_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); rd_state->project_cfg_string_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); rd_state->cmdln_cfg_string_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); rd_state->transient_cfg_string_key = c_key_make(c_root_alloc(), c_id_make(0, 0)); for(U64 idx = 0; idx < ArrayCount(rd_state->frame_arenas); idx += 1) { rd_state->frame_arenas[idx] = arena_alloc(); } rd_state->log = log_alloc(); log_select(rd_state->log); { Temp scratch = scratch_begin(0, 0); String8 user_program_data_path = os_get_process_info()->user_program_data_path; String8 user_data_folder = push_str8f(scratch.arena, "%S/raddbg/logs", user_program_data_path); rd_state->log_path = push_str8f(rd_state->arena, "%S/ui_thread.raddbg_log", user_data_folder); os_make_directory(user_data_folder); os_write_data_to_file_path(rd_state->log_path, str8_zero()); scratch_end(scratch); } rd_state->num_frames_requested = 2; rd_state->seconds_until_autosave = 0.5f; rd_state->eval_cache = e_cache_alloc(); for(U64 idx = 0; idx < ArrayCount(rd_state->cmds_arenas); idx += 1) { rd_state->cmds_arenas[idx] = arena_alloc(); } rd_state->cmd_output_arena = arena_alloc(); rd_state->popup_arena = arena_alloc(); rd_state->ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("top_level_ctx_menu")); rd_state->drop_completion_key = ui_key_from_string(ui_key_zero(), str8_lit("drop_completion_ctx_menu")); rd_state->bind_change_arena = arena_alloc(); rd_state->drag_drop_arena = arena_alloc(); rd_state->drag_drop_regs = push_array(rd_state->drag_drop_arena, RD_Regs, 1); rd_state->top_regs = &rd_state->base_regs; // rjf: set up schemas { rd_state->cfg_schema_table = push_array(rd_state->arena, CFG_SchemaTable, 1); rd_state->cfg_schema_table->slots_count = 4096; rd_state->cfg_schema_table->slots = push_array(rd_state->arena, CFG_SchemaNode *, rd_state->cfg_schema_table->slots_count); for EachElement(idx, rd_name_schema_info_table) { MD_Node *schema = md_tree_from_string(rd_state->arena, rd_name_schema_info_table[idx].schema)->first; cfg_schema_table_insert(rd_state->arena, rd_state->cfg_schema_table, rd_name_schema_info_table[idx].name, schema); } } // rjf: set up theme presets { for EachEnumVal(RD_ThemePreset, p) { rd_state->theme_preset_trees[p] = md_tree_from_string(rd_state->arena, rd_theme_preset_cfg_string_table[p])->first; } } // rjf: set up vocab info map { rd_state->vocab_info_map.single_slots_count = 1024; rd_state->vocab_info_map.single_slots = push_array(rd_state->arena, RD_VocabInfoMapSlot, rd_state->vocab_info_map.single_slots_count); rd_state->vocab_info_map.plural_slots_count = 1024; rd_state->vocab_info_map.plural_slots = push_array(rd_state->arena, RD_VocabInfoMapSlot, rd_state->vocab_info_map.plural_slots_count); for EachElement(idx, rd_vocab_info_table) { RD_VocabInfoMapNode *n = push_array(rd_state->arena, RD_VocabInfoMapNode, 1); MemoryCopyStruct(&n->v, &rd_vocab_info_table[idx]); U64 single_hash = d_hash_from_string(n->v.code_name); U64 plural_hash = d_hash_from_string(n->v.code_name_plural); U64 single_slot_idx = single_hash%rd_state->vocab_info_map.single_slots_count; U64 plural_slot_idx = plural_hash%rd_state->vocab_info_map.plural_slots_count; if(n->v.code_name.size != 0) { SLLQueuePush_N(rd_state->vocab_info_map.single_slots[single_slot_idx].first, rd_state->vocab_info_map.single_slots[single_slot_idx].last, n, single_next); } if(n->v.code_name_plural.size != 0) { SLLQueuePush_N(rd_state->vocab_info_map.plural_slots[plural_slot_idx].first, rd_state->vocab_info_map.plural_slots[plural_slot_idx].last, n, plural_next); } } } // rjf: set up top-level config entity trees & tables { rd_state->cfg = cfg_state_alloc(); cfg_ctx_select(cfg_state_ctx(rd_state->cfg)); cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("user")); cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("project")); cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("command_line")); cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("transient")); } // rjf: set up loaded debug info cache { rd_state->loaded_dbg_info_slots_count = 4096; rd_state->loaded_dbg_info_slots = push_array(arena, RD_LoadedDbgInfoSlot, rd_state->loaded_dbg_info_slots_count); } // rjf: set up window cache { rd_state->window_state_slots_count = 64; rd_state->window_state_slots = push_array(arena, RD_WindowStateSlot, rd_state->window_state_slots_count); rd_state->first_window_state = rd_state->last_window_state = &rd_nil_window_state; } // rjf: set up view cache { rd_state->view_state_slots_count = 4096; rd_state->view_state_slots = push_array(arena, RD_ViewStateSlot, rd_state->view_state_slots_count); } //- rjf: setup initial target from command line args String8 implicit_user_arg = {0}; String8 implicit_project_arg = {0}; { Temp scratch = scratch_begin(0, 0); String8List target_args = {0}; { B32 after_first_non_flag = 0; for(U64 idx = 1; idx < cmdln->argc; idx += 1) { String8 arg = str8_cstring(cmdln->argv[idx]); B32 is_flag = (str8_match(str8_prefix(arg, 1), str8_lit("-"), 0) || str8_match(str8_prefix(arg, 1), str8_lit("--"), 0) || str8_match(str8_prefix(arg, 1), str8_lit("/"), 0)); B32 is_cfg = 0; if(!is_flag && !after_first_non_flag) { OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, arg); U8 raddbg_cfg_magic[] = "// raddbg "; U8 file_magic_maybe[ArrayCount(raddbg_cfg_magic)] = {0}; os_file_read(file, r1u64(0, 10), file_magic_maybe); if(MemoryMatchArray(raddbg_cfg_magic, file_magic_maybe)) { is_cfg = 1; U8 header_suffix_buffer[256] = {0}; String8 header_suffix = {0}; header_suffix.str = header_suffix_buffer; header_suffix.size = os_file_read(file, r1u64(10, 10+256), header_suffix_buffer); String8 header_type_suffix = str8_skip(header_suffix, str8_find_needle(header_suffix, 0, str8_lit(" "), 0)+1); if(str8_match(header_type_suffix, str8_lit("user"), StringMatchFlag_RightSideSloppy)) { implicit_user_arg = arg; } else if(str8_match(header_type_suffix, str8_lit("project"), StringMatchFlag_RightSideSloppy)) { implicit_project_arg = arg; } } os_file_close(file); } if(!is_flag) { after_first_non_flag = 1; } if(after_first_non_flag && !is_cfg) { str8_list_push(scratch.arena, &target_args, arg); } } } if(target_args.node_count > 0 && target_args.first->string.size != 0) { //- rjf: unpack command line inputs String8 executable_name_string = {0}; String8 arguments_string = {0}; String8 working_directory_string = {0}; { // rjf: unpack full executable path if(target_args.first->string.size != 0) { String8 exe_name = target_args.first->string; PathStyle style = path_style_from_str8(exe_name); if(style == PathStyle_Relative) { String8 current_path = os_get_current_path(scratch.arena); exe_name = push_str8f(scratch.arena, "%S/%S", current_path, exe_name); exe_name = path_normalized_from_string(scratch.arena, exe_name); } executable_name_string = exe_name; } // rjf: get current directory, use as working directory { working_directory_string = path_normalized_from_string(scratch.arena, os_get_current_path(scratch.arena)); } // rjf: unpack arguments String8List passthrough_args_list = {0}; for(String8Node *n = target_args.first->next; n != 0; n = n->next) { if(str8_find_needle(n->string, 0, str8_lit(" "), 0) < n->string.size) { str8_list_pushf(scratch.arena, &passthrough_args_list, "\"%S\"", n->string); } else { str8_list_push(scratch.arena, &passthrough_args_list, n->string); } } StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join); } //- rjf: build config tree CFG_Node *command_line_root = cfg_node_child_from_string(cfg_node_root(), str8_lit("command_line")); CFG_Node *target = cfg_node_new(rd_state->cfg, command_line_root, str8_lit("target")); CFG_Node *exe = cfg_node_new(rd_state->cfg, target, str8_lit("executable")); CFG_Node *args = cfg_node_new(rd_state->cfg, target, str8_lit("arguments")); CFG_Node *wdir = cfg_node_new(rd_state->cfg, target, str8_lit("working_directory")); cfg_node_new(rd_state->cfg, exe, executable_name_string); cfg_node_new(rd_state->cfg, args, arguments_string); cfg_node_new(rd_state->cfg, wdir, working_directory_string); rd_cmd(RD_CmdKind_SelectTarget, .cfg = target->id); } scratch_end(scratch); } // rjf: set up user / project paths { Temp scratch = scratch_begin(0, 0); // rjf: unpack command line arguments String8 user_path = cmd_line_string(cmdln, str8_lit("user")); String8 project_path = cmd_line_string(cmdln, str8_lit("project")); { if(user_path.size != 0) { user_path = path_absolute_dst_from_relative_dst_src(scratch.arena, user_path, os_get_process_info()->initial_path); } if(project_path.size != 0) { project_path = path_absolute_dst_from_relative_dst_src(scratch.arena, project_path, os_get_process_info()->initial_path); } } { String8 user_program_data_path = os_get_process_info()->user_program_data_path; String8 user_data_folder = push_str8f(scratch.arena, "%S/raddbg", user_program_data_path); os_make_directory(user_data_folder); if(user_path.size == 0) { user_path = implicit_user_arg; } if(user_path.size == 0) { String8 last_user_path = push_str8f(scratch.arena, "%S/last_user", user_data_folder); user_path = os_data_from_file_path(scratch.arena, last_user_path); } if(user_path.size == 0) { user_path = push_str8f(scratch.arena, "%S/default.raddbg_user", user_data_folder); } } if(project_path.size == 0) { project_path = implicit_project_arg; } if(project_path.size != 0) { arena_clear(rd_state->project_path_arena); rd_state->project_path = push_str8_copy(rd_state->project_path_arena, project_path); } // rjf: do initial load of user (project will be loaded by the initial user load if not specified) rd_cmd(RD_CmdKind_OpenUser, .file_path = user_path); if(project_path.size != 0) { rd_cmd(RD_CmdKind_OpenProject, .file_path = project_path); } scratch_end(scratch); } // rjf: unpack icon image data { Temp scratch = scratch_begin(0, 0); String8 data = rd_icon_file_bytes; U8 *ptr = data.str; U8 *opl = ptr+data.size; // rjf: read header #pragma pack(push, 1) typedef struct ICO_Header ICO_Header; struct ICO_Header { U16 reserved_padding; // must be 0 U16 image_type; // if 1 -> ICO, if 2 -> CUR U16 num_images; }; typedef struct ICO_Entry ICO_Entry; struct ICO_Entry { U8 image_width_px; U8 image_height_px; U8 num_colors; U8 reserved_padding; // should be 0 union { U16 ico_color_planes; // in ICO U16 cur_hotspot_x_px; // in CUR }; union { U16 ico_bits_per_pixel; // in ICO U16 cur_hotspot_y_px; // in CUR }; U32 image_data_size; U32 image_data_off; }; #pragma pack(pop) ICO_Header hdr = {0}; if(ptr+sizeof(hdr) < opl) { MemoryCopy(&hdr, ptr, sizeof(hdr)); ptr += sizeof(hdr); } // rjf: read image entries U64 entries_count = hdr.num_images; ICO_Entry *entries = push_array(scratch.arena, ICO_Entry, hdr.num_images); { U64 bytes_to_read = sizeof(ICO_Entry)*entries_count; bytes_to_read = Min(bytes_to_read, opl-ptr); MemoryCopy(entries, ptr, bytes_to_read); ptr += bytes_to_read; } // rjf: find largest image ICO_Entry *best_entry = 0; U64 best_entry_area = 0; for(U64 idx = 0; idx < entries_count; idx += 1) { ICO_Entry *entry = &entries[idx]; U64 width = entry->image_width_px; if(width == 0) { width = 256; } U64 height = entry->image_height_px; if(height == 0) { height = 256; } U64 entry_area = width*height; if(entry_area > best_entry_area) { best_entry = entry; best_entry_area = entry_area; } } // rjf: deserialize raw image data from best entry's offset U8 *image_data = 0; Vec2S32 image_dim = {0}; if(best_entry != 0) { U8 *file_data_ptr = data.str + best_entry->image_data_off; U64 file_data_size = best_entry->image_data_size; int width = 0; int height = 0; int components = 0; image_data = stbi_load_from_memory(file_data_ptr, file_data_size, &width, &height, &components, 4); image_dim.x = width; image_dim.y = height; } // rjf: upload to gpu texture rd_state->icon_texture = r_tex2d_alloc(R_ResourceKind_Static, image_dim, R_Tex2DFormat_RGBA8, image_data); // rjf: release stbi_image_free(image_data); scratch_end(scratch); } ProfEnd(); } internal void rd_frame(void) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); log_scope_begin(); rd_state->frame_depth += 1; ////////////////////////////// //- rjf: (DEBUG) take top-level cfg roots, stringize them, and store them to hash store // #if 0 { struct { C_Key key; String8 name; } table[] = { {rd_state->user_cfg_string_key, str8_lit("user")}, {rd_state->project_cfg_string_key, str8_lit("project")}, {rd_state->cmdln_cfg_string_key, str8_lit("command_line")}, {rd_state->transient_cfg_string_key, str8_lit("transient")}, }; for EachElement(idx, table) { Arena *arena = arena_alloc(); String8 data = cfg_string_from_tree(arena, rd_state->cfg_schema_table, str8_zero(), cfg_node_child_from_string(cfg_node_root(), table[idx].name)); c_submit_data(table[idx].key, &arena, data); } } #endif ////////////////////////////// //- rjf: do per-frame resets // arena_clear(rd_frame_arena()); rd_state->top_regs = &rd_state->base_regs; rd_regs_copy_contents(rd_frame_arena(), &rd_state->top_regs->v, &rd_state->top_regs->v); if(rd_state->next_hover_regs != 0) { rd_state->hover_regs = rd_regs_copy(rd_frame_arena(), rd_state->next_hover_regs); rd_state->hover_regs_slot = rd_state->next_hover_regs_slot; rd_state->next_hover_regs = 0; } else { rd_state->hover_regs = push_array(rd_frame_arena(), RD_Regs, 1); rd_state->hover_regs_slot = RD_RegSlot_Null; } B32 allow_text_hotkeys = !rd_state->text_edit_mode; rd_state->text_edit_mode = 0; if(rd_state->frame_depth == 1) { arena_clear(rd_state->cmd_output_arena); MemoryZeroStruct(&rd_state->cmd_outputs); } ////////////////////////////// //- rjf: iterate all tabs, touch their view-states // if(rd_state->frame_depth == 1) { Temp scratch = scratch_begin(0, 0); CFG_NodePtrList windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); for(CFG_NodePtrNode *n = windows.first; n != 0; n = n->next) { CFG_Node *window = n->v; CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(panel_tree.root, p).next) { for(CFG_NodePtrNode *n = p->tabs.first; n != 0; n = n->next) { CFG_Node *tab = n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } rd_view_state_from_cfg(tab); } } } scratch_end(scratch); } ////////////////////////////// //- rjf: apply debug info config trees -> loaded debug info cache // { U64 current_update_tick_idx = update_tick_idx(); //- rjf: for each debug info config, reflect in cache - open if needed CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info")); for EachNode(n, CFG_NodePtrNode, dbg_infos.first) { // rjf: unpack debug info config CFG_Node *di = n->v; String8 path = rd_path_from_cfg(di); CFG_Node *di_timestamp = cfg_node_child_from_string(di, str8_lit("timestamp")); U64 timestamp = 0; try_u64_from_str8_c_rules(di_timestamp->first->string, ×tamp); DI_Key key = di_key_from_path_timestamp(path, timestamp); // rjf: touch in cache U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count; RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx]; RD_LoadedDbgInfoNode *node = 0; for(RD_LoadedDbgInfoNode *n = slot->first; n != 0; n = n->hash_next) { if(di_key_match(key, n->key)) { node = n; break; } } if(node == 0) { node = rd_state->free_loaded_dbg_info_node; if(node) { SLLStackPop_N(rd_state->free_loaded_dbg_info_node, hash_next); } else { node = push_array(rd_state->arena, RD_LoadedDbgInfoNode, 1); } DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev); node->key = key; di_open(key); } node->last_tick_idx_touched = current_update_tick_idx; DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev); DLLPushBack_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev); } //- rjf: iterate least-recently-used loaded debug infos - if any have not been updated this tick, // then evict for(RD_LoadedDbgInfoNode *n = rd_state->loaded_dbg_info_lru_first, *next = 0; n != 0; n = next) { next = n->lru_next; if(n->last_tick_idx_touched >= current_update_tick_idx) { break; } U64 hash = u64_hash_from_str8(str8_struct(&n->key)); U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count; RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx]; DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, n, lru_next, lru_prev); DLLRemove_NP(slot->first, slot->last, n, hash_next, hash_prev); SLLStackPush_N(rd_state->free_loaded_dbg_info_node, n, hash_next); di_close(n->key, 0); } } ////////////////////////////// //- rjf: garbage collect untouched immediate cfg trees // if(rd_state->frame_depth == 1) { CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); for(CFG_Node *tln = transient->first, *next = &cfg_nil_node; tln != &cfg_nil_node; tln = next) { next = tln->next; if(str8_match(tln->string, str8_lit("immediate"), 0)) { if(cfg_node_child_from_string(tln, str8_lit("hot")) == &cfg_nil_node) { cfg_node_release(rd_state->cfg, tln); } } } for(CFG_Node *tln = transient->first; tln != &cfg_nil_node; tln = tln->next) { if(str8_match(tln->string, str8_lit("immediate"), 0)) { for(CFG_Node *child = tln->first, *next = &cfg_nil_node; child != &cfg_nil_node; child = next) { next = child->next; if(str8_match(child->string, str8_lit("hot"), 0)) { cfg_node_release(rd_state->cfg, child); } } } } } ////////////////////////////// //- rjf: garbage collect untouched view states // if(rd_state->frame_depth == 1) { for EachIndex(slot_idx, rd_state->view_state_slots_count) { for(RD_ViewState *vs = rd_state->view_state_slots[slot_idx].first, *next; vs != 0; vs = next) { next = vs->hash_next; if(vs->last_frame_index_touched+2 < rd_state->frame_index) { ev_view_release(vs->ev_view); for(RD_ArenaExt *ext = vs->first_arena_ext; ext != 0; ext = ext->next) { arena_release(ext->arena); } arena_release(vs->arena); DLLRemove_NP(rd_state->view_state_slots[slot_idx].first, rd_state->view_state_slots[slot_idx].last, vs, hash_next, hash_prev); SLLStackPush_N(rd_state->free_view_state, vs, hash_next); } } } } ////////////////////////////// //- rjf: sync with di parsers // ProfScope("sync with di parsers") { DI_EventList events = di_get_events(scratch.arena); for(DI_EventNode *n = events.first; n != 0; n = n->next) { DI_Event *event = &n->v; switch(event->kind) { default:{}break; case DI_EventKind_ConversionStarted: { CFG_Node *root = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); CFG_Node *task = cfg_node_new(rd_state->cfg, root, str8_lit("conversion_task")); cfg_node_new(rd_state->cfg, task, event->string); }break; case DI_EventKind_ConversionEnded: { CFG_Node *root = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); for(CFG_Node *tln = root->first; tln != &cfg_nil_node; tln = tln->next) { if(str8_match(tln->string, str8_lit("conversion_task"), 0) && str8_match(tln->first->string, event->string, 0)) { cfg_node_release(rd_state->cfg, tln); break; } } }break; } } } ////////////////////////////// //- rjf: animate all views // if(rd_state->frame_depth == 1) { B32 any_window_is_focused = 0; for(RD_WindowState *w = rd_state->first_window_state; w != &rd_nil_window_state; w = w->order_next) { if(os_window_is_focused(w->os)) { any_window_is_focused = 1; break; } } F32 slow_rate = 1 - pow_f32(2, (-10.f * rd_state->frame_dt)); F32 fast_rate = 1 - pow_f32(2, (-40.f * rd_state->frame_dt)); for EachIndex(slot_idx, rd_state->view_state_slots_count) { for(RD_ViewState *vs = rd_state->view_state_slots[slot_idx].first; vs != 0; vs = vs->hash_next) { F32 scroll_x_diff = (-vs->scroll_pos.x.off); F32 scroll_y_diff = (-vs->scroll_pos.y.off); F32 loading_t_diff = (vs->loading_t_target - vs->loading_t); vs->scroll_pos.x.off += scroll_x_diff*rd_state->scrolling_animation_rate; vs->scroll_pos.y.off += scroll_y_diff*rd_state->scrolling_animation_rate; vs->loading_t += loading_t_diff * slow_rate; if((any_window_is_focused && abs_f32(loading_t_diff) > 0.01f) || abs_f32(scroll_x_diff) > 0.01f || abs_f32(scroll_y_diff) > 0.01f) { rd_request_frame(); } if(abs_f32(scroll_x_diff) <= 0.01f) { vs->scroll_pos.x.off = 0; } if(abs_f32(scroll_y_diff) <= 0.01f) { vs->scroll_pos.y.off = 0; } CFG_Node *vcfg = cfg_node_from_id(vs->cfg_id); if(cfg_node_child_from_string(vcfg, str8_lit("selected")) != &cfg_nil_node) { if(vs->loading_t_target > 0.5f && any_window_is_focused) { rd_request_frame(); } vs->loading_t_target = 0; } } } } ////////////////////////////// //- rjf: get events from the OS // OS_EventList events = {0}; if(rd_state->frame_depth == 1) { events = os_get_events(scratch.arena, rd_state->num_frames_requested == 0 && !DEV_always_refresh); } ////////////////////////////// //- rjf: push frame scopes // Access *frame_access_restore = rd_state->frame_access; rd_state->frame_access = access_open(); ////////////////////////////// //- rjf: calculate avg length in us of last many frames // U64 frame_time_history_avg_us = 0; { U64 num_frames_in_history = Min(ArrayCount(rd_state->frame_time_us_history), rd_state->frame_index); U64 frame_time_history_sum_us = 0; if(num_frames_in_history > 0) { for(U64 idx = 0; idx < num_frames_in_history; idx += 1) { frame_time_history_sum_us += rd_state->frame_time_us_history[idx]; } frame_time_history_avg_us = frame_time_history_sum_us/num_frames_in_history; } } ////////////////////////////// //- rjf: pick target hz // // pick among a number of sensible targets to snap to, given how well // we've been performing // // TODO(rjf): maximize target, given all windows and their monitors // F32 target_hz = os_get_gfx_info()->default_refresh_rate; if(rd_state->frame_index > 32) { F32 possible_alternate_hz_targets[] = {target_hz, 60.f, 75.f, 120.f, 144.f, 165.f, 240.f, 360.f}; F32 best_target_hz = target_hz; S64 best_target_hz_frame_time_us_diff = max_S64; for(U64 idx = 0; idx < ArrayCount(possible_alternate_hz_targets); idx += 1) { F32 candidate = possible_alternate_hz_targets[idx]; if(candidate <= target_hz) { U64 candidate_frame_time_us = 1000000/(U64)candidate; S64 frame_time_us_diff = (S64)frame_time_history_avg_us - (S64)candidate_frame_time_us; if(abs_s64(frame_time_us_diff) < best_target_hz_frame_time_us_diff && frame_time_history_avg_us < candidate_frame_time_us + candidate_frame_time_us/4) { best_target_hz = candidate; best_target_hz_frame_time_us_diff = frame_time_us_diff; } } } target_hz = best_target_hz; } ////////////////////////////// //- rjf: given frame time history, decide on amount of time we're willing to wait for memory read results // for evaluations // { rd_state->frame_eval_memread_endt_us = 0; U64 frame_time_target_cap_us = (U64)(1000000/target_hz); if(frame_time_history_avg_us < frame_time_target_cap_us) { U64 spare_time = (frame_time_target_cap_us - frame_time_history_avg_us) + 4000; rd_state->frame_eval_memread_endt_us = os_now_microseconds() + spare_time; } } ////////////////////////////// //- rjf: target Hz -> delta time // rd_state->frame_dt = 1.f/target_hz; ////////////////////////////// //- rjf: begin measuring actual per-frame work // U64 begin_time_us = os_now_microseconds(); ////////////////////////////// //- rjf: bind change // if(!rd_state->popup_active && rd_state->bind_change_active) { if(os_key_press(&events, os_handle_zero(), 0, OS_Key_Esc)) { rd_request_frame(); rd_state->bind_change_active = 0; } if(os_key_press(&events, os_handle_zero(), 0, OS_Key_Delete)) { rd_request_frame(); cfg_node_release(rd_state->cfg, cfg_node_from_id(rd_state->bind_change_binding_id)); rd_state->bind_change_active = 0; } for(OS_Event *event = events.first, *next = 0; event != 0; event = next) { if(event->kind == OS_EventKind_Press && event->key != OS_Key_Esc && event->key != OS_Key_Return && event->key != OS_Key_Backspace && event->key != OS_Key_Delete && event->key != OS_Key_LeftMouseButton && event->key != OS_Key_RightMouseButton && event->key != OS_Key_MiddleMouseButton && event->key != OS_Key_Ctrl && event->key != OS_Key_Alt && event->key != OS_Key_Shift) { rd_state->bind_change_active = 0; CFG_Node *binding = cfg_node_from_id(rd_state->bind_change_binding_id); if(binding == &cfg_nil_node) { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *keybindings = cfg_node_child_from_string_or_alloc(rd_state->cfg, user, str8_lit("keybindings")); binding = cfg_node_new(rd_state->cfg, keybindings, str8_lit("")); } cfg_node_release_all_children(rd_state->cfg, binding); cfg_node_new(rd_state->cfg, binding, rd_state->bind_change_cmd_name); cfg_node_new(rd_state->cfg, binding, os_g_key_cfg_string_table[event->key]); if(event->modifiers & OS_Modifier_Ctrl) { cfg_node_new(rd_state->cfg, binding, str8_lit("ctrl")); } if(event->modifiers & OS_Modifier_Shift) { cfg_node_new(rd_state->cfg, binding, str8_lit("shift")); } if(event->modifiers & OS_Modifier_Alt) { cfg_node_new(rd_state->cfg, binding, str8_lit("alt")); } U32 codepoint = os_codepoint_from_modifiers_and_key(event->modifiers, event->key); os_text(&events, event->window, codepoint); os_eat_event(&events, event); rd_request_frame(); break; } } } ////////////////////////////// //- rjf: build key map from config // ProfScope("build key map from config") { rd_state->key_map = cfg_key_map_from_cfg(rd_frame_arena()); } ////////////////////////////// //- rjf: get fonts from config // ProfScope("get fonts from config") { String8 main_font_name = rd_setting_from_name(str8_lit("main_font")); String8 code_font_name = rd_setting_from_name(str8_lit("code_font")); rd_state->font_slot_table[RD_FontSlot_Main] = fnt_tag_from_path(main_font_name); rd_state->font_slot_table[RD_FontSlot_Code] = fnt_tag_from_path(code_font_name); if(fnt_tag_match(rd_state->font_slot_table[RD_FontSlot_Main], fnt_tag_zero())) { rd_state->font_slot_table[RD_FontSlot_Main] = fnt_tag_from_static_data_string(&rd_default_main_font_bytes); } if(fnt_tag_match(rd_state->font_slot_table[RD_FontSlot_Code], fnt_tag_zero())) { rd_state->font_slot_table[RD_FontSlot_Code] = fnt_tag_from_static_data_string(&rd_default_code_font_bytes); } rd_state->font_slot_table[RD_FontSlot_Icons] = fnt_tag_from_static_data_string(&rd_icon_font_bytes); } ////////////////////////////// //- rjf: consume events // ProfScope("consume events") { for(OS_Event *event = events.first, *next = 0; event != 0; event = next) RD_RegsScope() { next = event->next; RD_WindowState *ws = rd_window_state_from_os_handle(event->window); if(ws != 0 && ws != rd_window_state_from_cfg(cfg_node_from_id(rd_regs()->window))) { Temp scratch = scratch_begin(0, 0); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(ws->cfg_id)); rd_regs()->window = ws->cfg_id; rd_regs()->panel = panel_tree.focused->cfg->id; rd_regs()->tab = panel_tree.focused->selected_tab->id; rd_regs()->view = panel_tree.focused->selected_tab->id; scratch_end(scratch); } B32 take = 0; //- rjf: try drag/drop drop-kickoff if(rd_drag_is_active() && event->kind == OS_EventKind_Release && event->key == OS_Key_LeftMouseButton) { rd_state->drag_drop_state = RD_DragDropState_Dropping; } //- rjf: try window close if(!take && event->kind == OS_EventKind_WindowClose && ws != 0) { take = 1; rd_cmd(RD_CmdKind_Exit); } //- rjf: try menu bar operations if(rd_state->alt_menu_bar_enabled) { if(!take && event->kind == OS_EventKind_Press && event->key == OS_Key_Alt && event->modifiers == 0 && event->is_repeat == 0) { take = 1; rd_request_frame(); ws->menu_bar_focused_on_press = ws->menu_bar_focused; ws->menu_bar_key_held = 1; ws->menu_bar_focus_press_started = 1; } if(!take && event->kind == OS_EventKind_Release && event->key == OS_Key_Alt && event->modifiers == 0 && event->is_repeat == 0) { take = 1; rd_request_frame(); ws->menu_bar_key_held = 0; } if(ws->menu_bar_focused && event->kind == OS_EventKind_Press && event->key == OS_Key_Alt && event->modifiers == 0 && event->is_repeat == 0) { take = 1; rd_request_frame(); ws->menu_bar_focused = 0; } else if(ws->menu_bar_focus_press_started && !ws->menu_bar_focused && event->kind == OS_EventKind_Release && event->modifiers == 0 && event->key == OS_Key_Alt && event->is_repeat == 0) { take = 1; rd_request_frame(); ws->menu_bar_focused = !ws->menu_bar_focused_on_press; ws->menu_bar_focus_press_started = 0; } else if(event->kind == OS_EventKind_Press && event->key == OS_Key_Esc && ws->menu_bar_focused && !ui_any_ctx_menu_is_open()) { take = 1; rd_request_frame(); ws->menu_bar_focused = 0; } } //- rjf: try hotkey presses if(!take && event->kind == OS_EventKind_Press) { CFG_Binding binding = {event->key, event->modifiers}; CFG_KeyMapNodePtrList key_map_nodes = cfg_key_map_node_ptr_list_from_binding(scratch.arena, rd_state->key_map, binding); if(key_map_nodes.first != 0) { U32 hit_char = os_codepoint_from_modifiers_and_key(event->modifiers, event->key); if(hit_char == 0 || allow_text_hotkeys) { String8 cmd_name = key_map_nodes.first->v->name; for(U64 idx = 0; idx < ArrayCount(rd_binding_version_remap_old_name_table); idx += 1) { if(str8_match(rd_binding_version_remap_old_name_table[idx], cmd_name, StringMatchFlag_CaseInsensitive)) { cmd_name = rd_binding_version_remap_new_name_table[idx]; } } rd_cmd(RD_CmdKind_RunCommand, .cmd_name = cmd_name); if(allow_text_hotkeys) { os_text(&events, event->window, hit_char); next = event->next; } take = 1; if(event->modifiers & OS_Modifier_Alt) { ws->menu_bar_focus_press_started = 0; } } } else if(OS_Key_F1 <= event->key && event->key <= OS_Key_F19) { ws->menu_bar_focus_press_started = 0; } rd_request_frame(); } //- rjf: try text events if(!take && event->kind == OS_EventKind_Text) { String32 insertion32 = str32(&event->character, 1); String8 insertion8 = str8_from_32(scratch.arena, insertion32); rd_cmd(RD_CmdKind_InsertText, .string = insertion8); rd_request_frame(); take = 1; if(event->modifiers & OS_Modifier_Alt) { ws->menu_bar_focus_press_started = 0; } } //- rjf: do fall-through if(!take) { take = 1; rd_cmd(RD_CmdKind_OSEvent, .os_event = event); } //- rjf: take if(take) { os_eat_event(&events, event); } } } ////////////////////////////// //- rjf: loop - consume events in core, tick engine, and repeat // CTRL_Handle find_thread_retry = {0}; RD_Cmd *cmd = 0; ProfScope("loop - consume events in core, tick engine, and repeat") for(U64 cmd_process_loop_idx = 0; cmd_process_loop_idx < 3; cmd_process_loop_idx += 1) { //////////////////////////// //- rjf: gather all unique debug info keys, build map // typedef struct DbgInfoNode DbgInfoNode; struct DbgInfoNode { DbgInfoNode *hash_next; DbgInfoNode *order_next; DI_Key key; U64 idx; }; U64 dbg_info_slots_count = 4096; DbgInfoNode **dbg_info_slots = push_array(scratch.arena, DbgInfoNode *, dbg_info_slots_count); DbgInfoNode *first_dbg_info = 0; DbgInfoNode *last_dbg_info = 0; U64 dbg_infos_count = 0; { CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info")); for EachNode(n, CFG_NodePtrNode, dbg_infos.first) { CFG_Node *di = n->v; String8 path = rd_path_from_cfg(di); CFG_Node *timestamp_node = cfg_node_child_from_string(di, str8_lit("timestamp")); U64 timestamp = 0; try_u64_from_str8_c_rules(timestamp_node->first->string, ×tamp); DI_Key key = di_key_from_path_timestamp(path, timestamp); U64 hash = u64_hash_from_str8(str8_struct(&key)); U64 slot_idx = hash%dbg_info_slots_count; DbgInfoNode *node = 0; for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next) { if(di_key_match(n->key, key)) { node = n; break; } } if(node == 0) { node = push_array(scratch.arena, DbgInfoNode, 1); SLLStackPush_N(dbg_info_slots[slot_idx], node, hash_next); SLLQueuePush_N(first_dbg_info, last_dbg_info, node, order_next); node->key = key; node->idx = dbg_infos_count; dbg_infos_count += 1; } } } //////////////////////////// //- rjf: unpack basic evaluation context // ProfBegin("unpack eval-dependent info"); CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); Arch arch = thread->arch; U64 unwind_count = rd_regs()->unwind_count; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); ProfEnd(); //////////////////////////// //- rjf: produce all debug infos // U64 eval_dbg_infos_count = Max(1, dbg_infos_count); E_DbgInfo *eval_dbg_infos = push_array(scratch.arena, E_DbgInfo, eval_dbg_infos_count); E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0]; MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil); { U64 idx = 0; for(DbgInfoNode *n = first_dbg_info; n != 0; n = n->order_next) { eval_dbg_infos[idx].dbgi_key = n->key; eval_dbg_infos[idx].rdi = di_rdi_from_key(rd_state->frame_access, n->key, 0, 0); idx += 1; } } //////////////////////////// //- rjf: produce all eval modules // CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module); U64 eval_modules_count = Max(1, all_modules.count); E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count); E_Module *eval_modules_primary = &eval_modules[0]; eval_modules_primary->vaddr_range = r1u64(0, max_U64); ProfScope("produce all eval modules") { for EachIndex(eval_module_idx, all_modules.count) { CTRL_Entity *m = all_modules.v[eval_module_idx]; DI_Key dbgi_key = ctrl_dbgi_key_from_module(m); // rjf: dbgi key -> eval dbg info num U32 dbg_info_num = 0; { U64 hash = u64_hash_from_str8(str8_struct(&dbgi_key)); U64 slot_idx = hash%dbg_info_slots_count; for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next) { if(di_key_match(n->key, dbgi_key)) { dbg_info_num = n->idx+1; break; } } } // rjf: fill eval_modules[eval_module_idx].vaddr_range = m->vaddr_range; eval_modules[eval_module_idx].arch = m->arch; eval_modules[eval_module_idx].dbg_info_num = dbg_info_num; eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), CTRL_EvalSpaceKind_Entity); if(module == m) { eval_modules_primary = &eval_modules[eval_module_idx]; eval_dbg_infos_primary = (0 < dbg_info_num && dbg_info_num <= eval_dbg_infos_count) ? &eval_dbg_infos[dbg_info_num-1] : &e_dbg_info_nil; } } } //////////////////////////// //- rjf: begin evaluation // e_select_cache(rd_state->eval_cache); //////////////////////////// //- rjf: build base evaluation context // E_BaseCtx *eval_base_ctx = push_array(scratch.arena, E_BaseCtx, 1); { E_BaseCtx *ctx = eval_base_ctx; //- rjf: fill instruction pointer info ctx->thread_ip_vaddr = rip_vaddr; ctx->thread_ip_voff = rip_voff; ctx->thread_reg_space = rd_eval_space_from_ctrl_entity(thread, CTRL_EvalSpaceKind_Entity); ctx->thread_arch = thread->arch; ctx->thread_unwind_count = unwind_count; //- rjf: fill debug infos ctx->dbg_infos = eval_dbg_infos; ctx->dbg_infos_count = eval_dbg_infos_count; ctx->primary_dbg_info = eval_dbg_infos_primary; //- rjf: fill modules ctx->modules = eval_modules; ctx->modules_count = eval_modules_count; ctx->primary_module = eval_modules_primary; //- rjf: fill space hooks ctx->space_gen = rd_eval_space_gen; ctx->space_read = rd_eval_space_read; ctx->space_write = rd_eval_space_write; } e_select_base_ctx(eval_base_ctx); //////////////////////////// //- rjf: build extra types & maps // E_String2ExprMap *macro_map = push_array(scratch.arena, E_String2ExprMap, 1); macro_map[0] = e_string2expr_map_make(scratch.arena, 512); E_AutoHookMap *auto_hook_map = push_array(scratch.arena, E_AutoHookMap, 1); auto_hook_map[0] = e_auto_hook_map_make(scratch.arena, 512); rd_state->meta_name2type_map = push_array(rd_frame_arena(), E_String2TypeKeyMap, 1); rd_state->meta_name2type_map[0] = e_string2typekey_map_make(rd_frame_arena(), 256); EV_ExpandRuleTable *expand_rule_table = push_array(scratch.arena, EV_ExpandRuleTable, 1); rd_state->view_ui_rule_map = rd_view_ui_rule_map_make(scratch.arena, 512); ProfScope("build extra types & maps") { //- rjf: add macros for command groups { String8 names[] = { str8_lit("commands"), str8_lit("tab_commands"), str8_lit("text_pt_commands"), str8_lit("text_range_commands"), }; for EachElement(idx, names) { String8 name = names[idx]; E_TypeKey type_key = e_type_key_cons(.kind = E_TypeKind_Set, .flags = E_TypeFlag_StubSingleLineExpansion, .name = name, .access = E_TYPE_ACCESS_FUNCTION_NAME(commands), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(commands), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(commands), }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, name, expr); } } //- rjf: add macro for themes { String8 names[] = { str8_lit("themes"), }; for EachElement(idx, names) { String8 name = names[idx]; E_TypeKey type_key = e_type_key_cons(.kind = E_TypeKind_Set, .flags = E_TypeFlag_StubSingleLineExpansion, .name = name, .access = E_TYPE_ACCESS_FUNCTION_NAME(themes), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(themes), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(themes), }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, name, expr); } } //- rjf: build schema types & cache (name -> type) mapping for EachElement(idx, rd_name_schema_info_table) { String8 name = rd_name_schema_info_table[idx].name; E_TypeKey type_key = e_type_key_cons(.name = name, .kind = E_TypeKind_Set, .irext = E_TYPE_IREXT_FUNCTION_NAME(schema), .access = E_TYPE_ACCESS_FUNCTION_NAME(schema), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(schema), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(schema), }); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, name, type_key); } //- rjf: add macro for top-level config root { String8 name = str8_lit("config"); E_TypeKey type_key = e_type_key_cons(.name = name, .kind = E_TypeKind_Set, .access = E_TYPE_ACCESS_FUNCTION_NAME(cfgs)); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, name, type_key); } //- rjf: add macro for top-level control root { String8 name = str8_lit("control"); E_TypeKey type_key = e_type_key_cons(.name = name, .kind = E_TypeKind_Set, .access = E_TYPE_ACCESS_FUNCTION_NAME(control)); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, name, type_key); } //- rjf: add macros for config "slice" collections (targets, breakpoints, etc.) String8 evallable_cfg_names[] = { str8_lit("breakpoint"), str8_lit("watch_pin"), str8_lit("target"), str8_lit("debug_info"), str8_lit("file_path_map"), str8_lit("type_view"), str8_lit("recent_project"), str8_lit("recent_file"), }; for EachElement(cfg_name_idx, evallable_cfg_names) { String8 cfg_name = evallable_cfg_names[cfg_name_idx]; String8 collection_name = rd_plural_from_code_name(cfg_name); E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .irext = E_TYPE_IREXT_FUNCTION_NAME(cfgs_slice), .access = E_TYPE_ACCESS_FUNCTION_NAME(cfgs_slice), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(cfgs_slice), .range= E_TYPE_EXPAND_RANGE_FUNCTION_NAME(cfgs_slice), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(cfgs_slice), }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = collection_type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, collection_name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, collection_name, collection_type_key); } //- rjf: add macros for evallable top-level individual config entity trees - // things with names either explicitly attached, or that we can infer for EachElement(idx, rd_name_schema_info_table) { String8 name = rd_name_schema_info_table[idx].name; MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, name); B32 is_individually_evallable = 0; for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { if(md_node_has_child(n->v, str8_lit("label"), 0) || md_node_has_child(n->v, str8_lit("executable"), 0)) { is_individually_evallable = 1; break; } } if(is_individually_evallable) { E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); CFG_NodePtrList cfgs = cfg_node_top_level_list_from_string(scratch.arena, name); for(CFG_NodePtrNode *n = cfgs.first; n != 0; n = n->next) { CFG_Node *cfg = n->v; String8 label = rd_label_from_cfg(cfg); if(label.size != 0) { E_Space space = rd_eval_space_from_cfg(cfg); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; e_string2expr_map_insert(scratch.arena, macro_map, label, expr); } } } } //- rjf: add macros for windows/tabs CFG_NodePtrList watch_tabs = {0}; { CFG_NodePtrList windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); for(CFG_NodePtrNode *n = windows.first; n != 0; n = n->next) { CFG_Node *window = n->v; { E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, window->string); E_Space space = rd_eval_space_from_cfg(window); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; e_string2expr_map_insert(scratch.arena, macro_map, push_str8f(scratch.arena, "query:config.$%I64x", window->id), expr); } CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(panel_tree.root, p).next) { for(CFG_NodePtrNode *tab_n = p->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, tab->string); E_Space space = rd_eval_space_from_cfg(tab); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; e_string2expr_map_insert(scratch.arena, macro_map, push_str8f(scratch.arena, "query:config.$%I64x", tab->id), expr); if(str8_match(tab->string, str8_lit("watch"), 0)) { cfg_node_ptr_list_push(scratch.arena, &watch_tabs, tab); } } } } } //- rjf: add macros for all watches in all watch tabs which define identifiers for(CFG_NodePtrNode *n = watch_tabs.first; n != 0; n = n->next) { CFG_Node *watch_tab = n->v; for(CFG_Node *child = watch_tab->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("watch"), 0)) { CFG_Node *watch = child; String8 expr = watch->first->string; E_Parse parse = e_parse_from_string(expr); if(parse.msgs.max_kind == E_MsgKind_Null) { for(E_Expr *expr = parse.expr; expr != &e_expr_nil; expr = expr->next) { typedef struct ExprWalkTask ExprWalkTask; struct ExprWalkTask { ExprWalkTask *next; E_Expr *expr; }; ExprWalkTask start_task = {0, expr}; ExprWalkTask *first_task = &start_task; ExprWalkTask *last_task = first_task; for(ExprWalkTask *t = first_task; t != 0; t = t->next) { switch(t->expr->kind) { case E_ExprKind_Call:{}break; case E_ExprKind_Define: { E_Expr *lhs = t->expr->first; E_Expr *rhs = lhs->next; if(lhs->kind == E_ExprKind_LeafIdentifier) { e_string2expr_map_insert(scratch.arena, macro_map, lhs->string, rhs); } }break; default: { for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); SLLQueuePush(first_task, last_task, task); task->expr = child; } }break; } } } } } } } //- rjf: add macros for user/project { E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, str8_lit("user")); E_Space space = rd_eval_space_from_cfg(cfg_node_child_from_string(cfg_node_root(), str8_lit("user"))); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("user_settings"), expr); } { E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, str8_lit("project")); E_Space space = rd_eval_space_from_cfg(cfg_node_child_from_string(cfg_node_root(), str8_lit("project"))); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("project_settings"), expr); } //- rjf: add macros for evallable control entities String8 evallable_ctrl_names[] = { str8_lit("machine"), str8_lit("process"), str8_lit("thread"), str8_lit("module"), }; for EachElement(idx, evallable_ctrl_names) { String8 name = evallable_ctrl_names[idx]; CTRL_EntityKind kind = ctrl_entity_kind_from_string(name); CTRL_EntityArray array = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, kind); E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); for EachIndex(idx, array.count) { CTRL_Entity *entity = array.v[idx]; E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = type_key; if(entity->string.size != 0) { e_string2expr_map_insert(scratch.arena, macro_map, entity->string, expr); } if(kind == CTRL_EntityKind_Machine && entity->handle.machine_id == CTRL_MachineID_Local) { e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("local_machine"), expr); } if(kind == CTRL_EntityKind_Thread && ctrl_handle_match(rd_base_regs()->thread, entity->handle)) { e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("current_thread"), expr); } if(kind == CTRL_EntityKind_Process && ctrl_handle_match(rd_base_regs()->process, entity->handle)) { e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("current_process"), expr); } if(kind == CTRL_EntityKind_Module && ctrl_handle_match(rd_base_regs()->module, entity->handle)) { e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("current_module"), expr); } } } //- rjf: add macros for all ctrl entity collections for EachElement(ctrl_name_idx, evallable_ctrl_names) { String8 kind_name = evallable_ctrl_names[ctrl_name_idx]; String8 collection_name = rd_plural_from_code_name(kind_name); E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .access = E_TYPE_ACCESS_FUNCTION_NAME(ctrl_entities), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(ctrl_entities), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(ctrl_entities) }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = collection_type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, collection_name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, collection_name, collection_type_key); } //- rjf: add macro for call stack tree #if 0 { String8 collection_name = str8_lit("call_stack_tree"); E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .flags = E_TypeFlag_StubSingleLineExpansion, .access = E_TYPE_ACCESS_FUNCTION_NAME(call_stack_tree), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(call_stack_tree), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(call_stack_tree) }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafValue, r1u64(0, 0)); expr->value.u64 = 1; expr->type_key = collection_type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaCallStackTree); e_string2expr_map_insert(scratch.arena, macro_map, collection_name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, collection_name, collection_type_key); } #endif //- rjf: add macro / lookup rules for unattached processes { String8 collection_name = str8_lit("unattached_processes"); E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .flags = E_TypeFlag_StubSingleLineExpansion, .access = E_TYPE_ACCESS_FUNCTION_NAME(unattached_processes), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(unattached_processes), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(unattached_processes) }); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = collection_type_key; expr->space = e_space_make(RD_EvalSpaceKind_MetaCtrlEntity); e_string2expr_map_insert(scratch.arena, macro_map, collection_name, expr); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, collection_name, collection_type_key); } //- rjf: add macro for 'call_stack' -> 'query:current_thread.callstack' { E_Expr *expr = e_parse_from_string(str8_lit("query:current_thread.call_stack")).expr; e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("call_stack"), expr); } //- rjf: add types for queries { e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("environment"), e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("environment"), .irext = E_TYPE_IREXT_FUNCTION_NAME(environment), .access = E_TYPE_ACCESS_FUNCTION_NAME(environment), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(environment), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(environment), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(environment), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(environment), })); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("watches"), e_type_key_cons(.kind = E_TypeKind_Set, .flags = E_TypeFlag_EditableChildren|E_TypeFlag_StubSingleLineExpansion, .name = str8_lit("watches"), .irext = E_TYPE_IREXT_FUNCTION_NAME(watches), .access = E_TYPE_ACCESS_FUNCTION_NAME(watches), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(watches), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(watches), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(watches), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(watches), })); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("call_stack"), e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("call_stack"), .irext = E_TYPE_IREXT_FUNCTION_NAME(call_stack), .access = E_TYPE_ACCESS_FUNCTION_NAME(call_stack), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(call_stack), })); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("theme_colors"), e_type_key_cons(.kind = E_TypeKind_Set, .flags = E_TypeFlag_StubSingleLineExpansion, .name = str8_lit("theme_colors"), .irext = E_TYPE_IREXT_FUNCTION_NAME(cfgs_slice), .access = E_TYPE_ACCESS_FUNCTION_NAME(cfgs_slice), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(cfgs_query), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(cfgs_slice), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(cfgs_slice), })); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("environment"), e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("environment"), .irext = E_TYPE_IREXT_FUNCTION_NAME(environment), .access = E_TYPE_ACCESS_FUNCTION_NAME(environment), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(environment), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(environment), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(environment), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(environment), })); } //- rjf: add macro for collections with specific lookup rules (but no unique id rules) { struct { String8 name; E_TypeExpandInfoFunctionType *info; E_TypeExpandRangeFunctionType *range; } collection_infos[] = { #define Collection(name) {str8_lit_comp(#name), E_TYPE_EXPAND_INFO_FUNCTION_NAME(name), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(name)} Collection(locals), Collection(registers), #undef Collection }; for EachElement(idx, collection_infos) { String8 collection_name = collection_infos[idx].name; E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .expand = { .info = collection_infos[idx].info, .range = collection_infos[idx].range, }); expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); e_string2expr_map_insert(scratch.arena, macro_map, collection_name, expr); } } //- rjf: add macros for debug info table collections String8 debug_info_table_collection_names[] = { str8_lit_comp("procedures"), str8_lit_comp("thread_locals"), str8_lit_comp("constants"), str8_lit_comp("globals"), str8_lit_comp("types"), str8_lit_comp("source_files"), }; for EachElement(idx, debug_info_table_collection_names) { String8 name = debug_info_table_collection_names[idx]; E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .flags = E_TypeFlag_StubSingleLineExpansion, .name = name, .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(debug_info_table), .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(debug_info_table), .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(debug_info_table), .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(debug_info_table) }); e_string2expr_map_insert(scratch.arena, macro_map, name, expr); } //- rjf: add macro for output log { Access *access = access_open(); C_Key key = d_state->output_log_key; U128 hash = c_hash_from_key(key, 0); String8 data = c_data_from_hash(access, hash); E_Space space = e_space_make(E_SpaceKind_HashStoreKey); space.u64_0 = key.root.u64[0]; space.u128 = key.id.u128[0]; E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), data.size, 0); e_string2expr_map_insert(scratch.arena, macro_map, str8_lit("output"), expr); access_close(access); } //- rjf: (DEBUG) add macro for cfg strings #if 0 { struct { C_Key key; String8 name; } table[] = { {rd_state->user_cfg_string_key, str8_lit("raddbg_user_data")}, {rd_state->project_cfg_string_key, str8_lit("raddbg_project_data")}, {rd_state->cmdln_cfg_string_key, str8_lit("raddbg_command_line_data")}, {rd_state->transient_cfg_string_key, str8_lit("raddbg_transient_data")}, }; for EachElement(idx, table) { Access *access = access_open(); C_Key key = table[idx].key; U128 hash = c_hash_from_key(key, 0); String8 data = c_data_from_hash(access, hash); E_Space space = e_space_make(E_SpaceKind_HashStoreKey); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); space.u64_0 = key.root.u64[0]; space.u128 = key.id.u128[0]; expr->space = space; expr->mode = E_Mode_Offset; expr->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), data.size, 0); e_string2expr_map_insert(scratch.arena, macro_map, table[idx].name, expr); access_close(access); } } #endif //- rjf: choose set of lenses // TODO(rjf): @lenses generate via metaprogram struct { String8 name; B32 inherited_by_members; B32 inherited_by_elements; B32 array_like; E_TypeIRExtFunctionType *irext; E_TypeAccessFunctionType *access; E_TypeExpandRule expand; RD_ViewUIFunctionType *ui; EV_ExpandRuleInfoHookFunctionType *ev_expand; } lens_table[] = { {str8_lit("raw"), 0, 0, 0, 0, 0, {0}}, {str8_lit("bin"), 1, 1, 0, 0, 0, {0}}, {str8_lit("oct"), 1, 1, 0, 0, 0, {0}}, {str8_lit("dec"), 1, 1, 0, 0, 0, {0}}, {str8_lit("hex"), 1, 1, 0, 0, 0, {0}}, {str8_lit("digits"), 1, 1, 0, 0, 0, {0}}, {str8_lit("no_string"), 1, 1, 0, 0, 0, {0}}, {str8_lit("no_char"), 1, 1, 0, 0, 0, {0}}, {str8_lit("no_addr"), 1, 1, 0, 0, 0, {0}}, {str8_lit("sequence"), 0, 0, 1, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(sequence), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(sequence)}}, {str8_lit("rows"), 0, 0, 0, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(rows), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(rows)}}, {str8_lit("columns"), 0, 0, 0, 0, 0, {0}}, {str8_lit("flatten"), 0, 0, 0, 0, 0, {0}}, {str8_lit("omit"), 0, 0, 0, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(omit), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(omit)}}, {str8_lit("range1"), 0, 0, 0, 0, 0, {0}}, {str8_lit("array"), 0, 0, 1, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(array), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(array)}}, {str8_lit("slice"), 0, 0, 1, E_TYPE_IREXT_FUNCTION_NAME(slice), E_TYPE_ACCESS_FUNCTION_NAME(slice), {E_TYPE_EXPAND_INFO_FUNCTION_NAME(slice), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(slice)}}, {str8_lit("list"), 0, 0, 1, E_TYPE_IREXT_FUNCTION_NAME(list), E_TYPE_ACCESS_FUNCTION_NAME(list), {E_TYPE_EXPAND_INFO_FUNCTION_NAME(list), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(list)}}, {str8_lit("text"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(text), EV_EXPAND_RULE_INFO_FUNCTION_NAME(text)}, {str8_lit("disasm"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(disasm), EV_EXPAND_RULE_INFO_FUNCTION_NAME(disasm)}, {str8_lit("memory"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(memory), EV_EXPAND_RULE_INFO_FUNCTION_NAME(memory)}, {str8_lit("bitmap"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(bitmap), EV_EXPAND_RULE_INFO_FUNCTION_NAME(bitmap)}, {str8_lit("color"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(color), EV_EXPAND_RULE_INFO_FUNCTION_NAME(color)}, {str8_lit("geo3d"), 0, 0, 0, 0, 0, {0}, RD_VIEW_UI_FUNCTION_NAME(geo3d), EV_EXPAND_RULE_INFO_FUNCTION_NAME(geo3d)}, }; //- rjf: fill lenses in ev expand rule map, rd view ui rule map { for EachElement(idx, lens_table) { if(lens_table[idx].ui != 0) { rd_view_ui_rule_map_insert(scratch.arena, rd_state->view_ui_rule_map, lens_table[idx].name, lens_table[idx].ui); } if(lens_table[idx].ev_expand != 0) { ev_expand_rule_table_push_new(scratch.arena, expand_rule_table, lens_table[idx].name, lens_table[idx].ev_expand); } } } //- rjf: fill macros w/ types for lenses for EachElement(idx, lens_table) { E_TypeFlags type_flags = 0; if(lens_table[idx].inherited_by_members) { type_flags |= E_TypeFlag_InheritedByMembers; } if(lens_table[idx].inherited_by_elements) { type_flags |= E_TypeFlag_InheritedByElements; } if(lens_table[idx].array_like) { type_flags |= E_TypeFlag_ArrayLikeExpansion; } E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, r1u64(0, 0)); expr->type_key = e_type_key_cons(.kind = E_TypeKind_LensSpec, .flags = type_flags, .name = lens_table[idx].name, .irext = lens_table[idx].irext, .access = lens_table[idx].access, .expand = lens_table[idx].expand); e_string2expr_map_insert(scratch.arena, macro_map, lens_table[idx].name, expr); } } ev_select_expand_rule_table(expand_rule_table); //////////////////////////// //- rjf: gather config from loaded modules // CFG_NodePtrList immediate_type_views = {0}; CTRL_EntityArray modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module); ProfScope("gather config from loaded modules") { for EachIndex(idx, modules.count) { CTRL_Entity *module = modules.v[idx]; String8 raddbg_data = ctrl_raddbg_data_from_module(scratch.arena, module->handle); U8 split_char = 0; String8List raddbg_data_text_parts = str8_split(scratch.arena, raddbg_data, &split_char, 1, 0); U64 cfg_idx = 0; for(String8Node *text_n = raddbg_data_text_parts.first; text_n != 0; text_n = text_n->next) { String8 text = text_n->string; CFG_NodePtrList cfgs = cfg_node_ptr_list_from_string(scratch.arena, rd_state->cfg, rd_state->cfg_schema_table, str8_zero(), text); String8 module_name = ctrl_string_from_handle(scratch.arena, module->handle); for(CFG_NodePtrNode *n = cfgs.first; n != 0; n = n->next, cfg_idx += 1) { CFG_Node *immediate_root = rd_immediate_cfg_from_keyf("module_%S_cfg_%I64x", module_name, cfg_idx); cfg_node_release_all_children(rd_state->cfg, immediate_root); cfg_node_insert_child(rd_state->cfg, immediate_root, immediate_root->last, n->v); cfg_node_ptr_list_push(scratch.arena, &immediate_type_views, n->v); } } } } //////////////////////////// //- rjf: construct default immediate-mode configs based on loaded modules // ProfScope("construct default immediate-mode configs based on loaded modules") { local_persist read_only struct { B32 stl; B32 ue; String8 pattern; String8 expr; } type_views[] = { { 1, 0, str8_lit_comp("std::vector"), str8_lit_comp("slice(_Mypair._Myval2)") }, { 1, 0, str8_lit_comp("std::unique_ptr"), str8_lit_comp("_Mypair._Myval2") }, { 1, 0, str8_lit_comp("std::basic_string"), str8_lit_comp("_Mypair._Myval2._Myres <= 15 ? _Mypair._Myval2._Bx._Buf : array(_Mypair._Myval2._Bx._Ptr, _Mypair._Myval2._Mysize)") }, { 1, 0, str8_lit_comp("std::basic_string_view"), str8_lit_comp("array(_Mydata, _Mysize)") }, { 0, 1, str8_lit_comp("FString"), str8_lit_comp("(TCHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, { 0, 1, str8_lit_comp("FAnsiString"), str8_lit_comp("(ANSICHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, { 0, 1, str8_lit_comp("FUtf8String"), str8_lit_comp("(UTF8CHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, { 0, 1, str8_lit_comp("TStringView"), str8_lit_comp("DataPtr, Size") }, { 0, 1, str8_lit_comp("TArray"), str8_lit_comp("array(cast(element_type *)AllocatorInstance.Data, ArrayNum)") }, { 0, 1, str8_lit_comp("TSharedRef"), str8_lit_comp("Object") }, { 0, 1, str8_lit_comp("TRefCountPtr"), str8_lit_comp("Reference") }, { 0, 1, str8_lit_comp("FNameEntry"), str8_lit_comp("AnsiName, Header.Len") }, { 0, 1, str8_lit_comp("FNameEntryId"), str8_lit_comp("*(cast(FNameEntry *)(&GNameBlocksDebug[Value >> FNameDebugVisualizer::OffsetBits][FNameDebugVisualizer::EntryStride * (Value & FNameDebugVisualizer::OffsetMask)]))") }, { 0, 1, str8_lit_comp("TObjectPtr"), str8_lit_comp("DebugPtr") }, { 0, 1, str8_lit_comp("FColor"), str8_lit_comp("hex(color(Bits))") }, }; if(rd_state->use_default_stl_type_views) { for EachElement(idx, type_views) { if((type_views[idx].stl && rd_state->use_default_stl_type_views) || (type_views[idx].ue && rd_state->use_default_ue_type_views)) { CFG_Node *immediate_root = rd_immediate_cfg_from_keyf("default_type_vis_%I64x", idx); CFG_Node *type_view = cfg_node_child_from_string_or_alloc(rd_state->cfg, immediate_root, str8_lit("type_view")); CFG_Node *type = cfg_node_child_from_string_or_alloc(rd_state->cfg, type_view, str8_lit("type")); CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, type_view, str8_lit("expr")); cfg_node_new_replace(rd_state->cfg, type, type_views[idx].pattern); cfg_node_new_replace(rd_state->cfg, expr, type_views[idx].expr); cfg_node_ptr_list_push(scratch.arena, &immediate_type_views, type_view); } } } } //////////////////////////// //- rjf: add auto-hook rules for type views // { CFG_NodePtrList type_views = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("type_view")); CFG_NodePtrList rules_lists[] = { type_views, immediate_type_views, }; for EachElement(list_idx, rules_lists) { CFG_NodePtrList list = rules_lists[list_idx]; for(CFG_NodePtrNode *n = list.first; n != 0; n = n->next) { CFG_Node *rule = n->v; String8 type_string = cfg_node_child_from_string(rule, str8_lit("type"))->first->string; String8 expr_string = cfg_node_child_from_string(rule, str8_lit("expr"))->first->string; e_auto_hook_map_insert_new(scratch.arena, auto_hook_map, .type_pattern = type_string, .tag_expr_string = expr_string); } } } //////////////////////////// //- rjf: build IR evaluation context // E_IRCtx *ir_ctx = push_array(scratch.arena, E_IRCtx, 1); { E_IRCtx *ctx = ir_ctx; ctx->regs_map = ctrl_string2reg_from_arch(eval_base_ctx->primary_module->arch); ctx->reg_alias_map = ctrl_string2alias_from_arch(eval_base_ctx->primary_module->arch); ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff); ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff); ctx->macro_map = macro_map; ctx->auto_hook_map = auto_hook_map; } e_select_ir_ctx(ir_ctx); //////////////////////////// //- rjf: build eval interpretation context // E_InterpretCtx *interpret_ctx = push_array(scratch.arena, E_InterpretCtx, 1); { E_InterpretCtx *ctx = interpret_ctx; ctx->primary_space = eval_modules_primary->space; ctx->reg_arch = eval_modules_primary->arch; ctx->reg_space = rd_eval_space_from_ctrl_entity(thread, CTRL_EvalSpaceKind_Entity); ctx->reg_unwind_count = unwind_count; ctx->module_base = push_array(scratch.arena, U64, 1); ctx->module_base[0] = module->vaddr_range.min; ctx->frame_base = push_array(scratch.arena, U64, 1); ctx->tls_base = push_array(scratch.arena, U64, 1); ctx->tls_base[0] = d_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, rip_vaddr); } e_select_interpret_ctx(interpret_ctx, eval_dbg_infos_primary->rdi, rip_voff); //////////////////////////// //- rjf: evaluate unpacked settings (must be used earlier than this point in the frame, // but cannot evaluate before this point, so we need to prep for next frame // rd_state->alt_menu_bar_enabled = rd_setting_b32_from_name(str8_lit("focus_menu_bar_with_alt")); rd_state->use_default_stl_type_views = rd_setting_b32_from_name(str8_lit("use_default_stl_type_views")); rd_state->use_default_ue_type_views = rd_setting_b32_from_name(str8_lit("use_default_ue_type_views")); //////////////////////////// //- rjf: autosave if needed // { rd_state->seconds_until_autosave -= rd_state->frame_dt; if(rd_state->seconds_until_autosave <= 0.f) { rd_cmd(RD_CmdKind_WriteUserData); rd_cmd(RD_CmdKind_WriteProjectData); rd_state->seconds_until_autosave = 5.f; } } //////////////////////////// //- rjf: process top-level graphical commands // if(rd_state->frame_depth == 1) ProfScope("process top-level graphical commands") { for(;rd_next_cmd(&cmd);) RD_RegsScope() { // rjf: unpack command RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); rd_regs_copy_contents(rd_frame_arena(), rd_regs(), cmd->regs); // rjf: request frame rd_request_frame(); // rjf: process command CFG_Node *cfg = &cfg_nil_node; String8 dst_path = {0}; String8 bucket_name = {0}; Dir2 split_dir = Dir2_Invalid; CFG_Node *split_panel = &cfg_nil_node; U64 panel_sib_off = 0; U64 panel_child_off = 0; Vec2S32 panel_change_dir = {0}; switch(kind) { //- rjf: default cases case RD_CmdKind_Run: case RD_CmdKind_LaunchAndRun: case RD_CmdKind_LaunchAndStepInto: case RD_CmdKind_StepInto: case RD_CmdKind_StepOver: case RD_CmdKind_Restart: { // rjf: reset hit counts CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(processes.count == 0 || kind == RD_CmdKind_Restart) { CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = bps.first; n != 0; n = n->next) { CFG_Node *hit_count = cfg_node_child_from_string_or_alloc(rd_state->cfg, n->v, str8_lit("hit_count")); cfg_node_new_replace(rd_state->cfg, hit_count, str8_lit("0")); } } // rjf: determine if we have active targets CFG_NodePtrList targets = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); B32 has_active_targets = 0; for(CFG_NodePtrNode *n = targets.first; n != 0; n = n->next) { CFG_Node *target = n->v; if(!rd_disabled_from_cfg(target)) { has_active_targets = 1; break; } } // rjf: run -> refocus pre-stop focused window if(kind == RD_CmdKind_Run) { os_focus_external_window(rd_state->prestop_focused_window); } // rjf: run -> no active targets, no processes, but we only have one target? -> just launch it, then select it if((kind == RD_CmdKind_Run || kind == RD_CmdKind_StepInto || kind == RD_CmdKind_StepOver) && processes.count == 0 && targets.count == 1 && !has_active_targets) { rd_cmd(kind == RD_CmdKind_Run ? RD_CmdKind_LaunchAndRun : RD_CmdKind_LaunchAndStepInto, .cfg = targets.first->v->id); rd_cmd(RD_CmdKind_SelectTarget, .cfg = targets.first->v->id); break; } // rjf: run -> no targets at all, no processes? -> do helper for add-target if((kind == RD_CmdKind_Run || kind == RD_CmdKind_StepInto || kind == RD_CmdKind_StepOver) && targets.count == 0 && processes.count == 0) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_AddTarget].string); break; } // rjf: run -> no active targets, no processes? -> do helper for launch-and-run if((kind == RD_CmdKind_Run || kind == RD_CmdKind_StepInto || kind == RD_CmdKind_StepOver) && processes.count == 0 && !has_active_targets) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[kind == RD_CmdKind_Run ? RD_CmdKind_LaunchAndRun : RD_CmdKind_LaunchAndStepInto].string); break; } // rjf: if this is a low-level operation, e.g. launch-and-run or launch-and-step-into, // and we do not have any active targets, then let's just select the ones that we are // launching. if(!has_active_targets && (kind == RD_CmdKind_LaunchAndRun || kind == RD_CmdKind_LaunchAndStepInto)) { rd_cmd(RD_CmdKind_SelectTarget, .cfg = rd_regs()->cfg); } } // fallthrough default: { // rjf: try to run engine command if(D_CmdKind_Null < (D_CmdKind)kind && (D_CmdKind)kind < D_CmdKind_COUNT) { D_CmdParams params = {0}; params.machine = rd_regs()->machine; params.process = rd_regs()->process; params.thread = rd_regs()->thread; params.entity = rd_regs()->ctrl_entity; params.string = rd_regs()->string; params.file_path = rd_regs()->file_path; params.cursor = rd_regs()->cursor; params.vaddr = rd_regs()->vaddr; params.prefer_disasm = rd_regs()->prefer_disasm; params.pid = rd_regs()->pid; params.targets.count = 1; params.targets.v = push_array(scratch.arena, D_Target, params.targets.count); params.targets.v[0] = rd_target_from_cfg(scratch.arena, cfg_node_from_id(rd_regs()->cfg)); d_push_cmd((D_CmdKind)kind, ¶ms); } // rjf: try to open tabs, if this is a tab-fastpath-opener if(kind >= RD_CmdKind_FirstTabFastPathCmd) { U64 fast_path_idx = (kind - RD_CmdKind_FirstTabFastPathCmd); String8 view_name = rd_tab_fast_path_view_name_table[fast_path_idx]; String8 query_name = rd_tab_fast_path_query_name_table[fast_path_idx]; rd_cmd(RD_CmdKind_BuildTab, .string = view_name, .expr = query_name); } }break; //- rjf: open palette case RD_CmdKind_OpenPalette: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_Node *tab = panel_tree.focused->selected_tab; String8List exprs = {0}; { str8_list_pushf(scratch.arena, &exprs, "query:commands"); if(tab != &cfg_nil_node) { str8_list_pushf(scratch.arena, &exprs, "query:config.$%I64x", tab->id); } if(window != &cfg_nil_node) { str8_list_pushf(scratch.arena, &exprs, "query:config.$%I64x", window->id); } str8_list_pushf(scratch.arena, &exprs, "query:targets"); str8_list_pushf(scratch.arena, &exprs, "query:breakpoints"); str8_list_pushf(scratch.arena, &exprs, "query:recent_files"); str8_list_pushf(scratch.arena, &exprs, "query:recent_projects"); str8_list_pushf(scratch.arena, &exprs, "query:machines"); str8_list_pushf(scratch.arena, &exprs, "query:processes"); str8_list_pushf(scratch.arena, &exprs, "query:threads"); str8_list_pushf(scratch.arena, &exprs, "query:modules"); str8_list_pushf(scratch.arena, &exprs, "query:user_settings"); str8_list_pushf(scratch.arena, &exprs, "query:project_settings"); str8_list_pushf(scratch.arena, &exprs, "query:procedures"); str8_list_pushf(scratch.arena, &exprs, "query:types"); str8_list_pushf(scratch.arena, &exprs, "query:globals"); str8_list_pushf(scratch.arena, &exprs, "query:thread_locals"); str8_list_pushf(scratch.arena, &exprs, "query:source_files"); } String8 expr = str8_list_join(scratch.arena, &exprs, &(StringJoin){.sep = str8_lit(", ")}); rd_cmd(RD_CmdKind_PushQuery, .expr = expr, .do_implicit_root = 1, .do_lister = 1, .do_big_rows = 1, .view = tab->id, .tab = tab->id); }break; //- rjf: command fast paths case RD_CmdKind_RunCommand: case RD_CmdKind_OpenTab: { RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(cmd->regs->cmd_name); // rjf: command does not have a query - simply execute with the current registers if(!(info->query.flags & RD_QueryFlag_Required)) { RD_RegsScope(.cmd_name = str8_zero()) rd_push_cmd(cmd->regs->cmd_name, rd_regs()); } // rjf: command has filesystem query, user wants native filesystem UI -> get the path then run the command else if(info->query.slot == RD_RegSlot_FilePath && rd_setting_b32_from_name(str8_lit("use_native_file_system_dialog"))) { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *current_path = cfg_node_child_from_string(user, str8_lit("current_path")); String8 current_path_string = current_path->first->string; if(current_path_string.size == 0) { current_path_string = path_normalized_from_string(scratch.arena, os_get_current_path(scratch.arena)); } String8 file_path = os_graphical_pick_file(scratch.arena, current_path_string); file_path = path_normalized_from_string(scratch.arena, file_path); if(file_path.size != 0) { RD_RegsScope(.cmd_name = str8_zero(), .file_path = file_path) rd_push_cmd(cmd->regs->cmd_name, rd_regs()); rd_cmd(RD_CmdKind_SetCurrentPath, .file_path = str8_chop_last_slash(file_path)); } } // rjf: command has required query -> prep query else { rd_cmd(RD_CmdKind_PushQuery, .do_implicit_root = 1, .do_lister = info->query.expr.size != 0); } }break; //- rjf: external driver textual commands case RD_CmdKind_RunExternalDriverTextCommand: { String8 msg = rd_regs()->string; String8List msg_parts = str8_split(scratch.arena, msg, (U8 *)" ", 1, 0); CmdLine msg_cmd_line = cmd_line_from_string_list(scratch.arena, msg_parts); String8 cmd_kind_name = str8_list_first(&msg_cmd_line.inputs); RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_kind_name); if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope() { for EachNonZeroEnumVal(RD_RegSlot, s) { String8 reg_slot_name = rd_reg_slot_code_name_table[s]; String8 value = cmd_line_string(&msg_cmd_line, reg_slot_name); if(value.size != 0) { rd_regs_fill_slot_from_string(s, cmd_kind_info->query.expr, value); } } String8 primary_args_string = {0}; if(msg_cmd_line.inputs.first != 0) { String8List primary_args_strings = {0}; for(String8Node *n = msg_cmd_line.inputs.first->next; n != 0; n = n->next) { str8_list_push(scratch.arena, &primary_args_strings, n->string); } primary_args_string = str8_list_join(scratch.arena, &primary_args_strings, &(StringJoin){.sep = str8_lit(" ")}); } rd_regs_fill_slot_from_string(cmd_kind_info->query.slot, cmd_kind_info->query.expr, primary_args_string); rd_push_cmd(cmd_kind_name, rd_regs()); } else { log_user_errorf("`%S` is not a command.", cmd_kind_name); } }break; //- rjf: exiting case RD_CmdKind_Exit: { // rjf: if control processes are live, but this is not force-confirmed, then // get confirmation from user CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("lossy_exit_confirmation")); if(processes.count != 0 && !rd_regs()->force_confirm && !ui_key_match(rd_state->popup_key, key)) { rd_state->popup_key = key; rd_state->popup_active = 1; arena_clear(rd_state->popup_arena); MemoryZeroStruct(&rd_state->popup_cmds); rd_state->popup_title = push_str8f(rd_state->popup_arena, "Are you sure you want to exit?"); rd_state->popup_desc = push_str8f(rd_state->popup_arena, "The debugger is still attached to %slive process%s.", processes.count == 1 ? "a " : "", processes.count == 1 ? "" : "es"); RD_Regs *regs = rd_regs_copy(rd_frame_arena(), rd_regs()); regs->force_confirm = 1; rd_cmd_list_push_new(rd_state->popup_arena, &rd_state->popup_cmds, rd_cmd_kind_info_table[RD_CmdKind_Exit].string, regs); } // rjf: otherwise, actually exit else { rd_cmd(RD_CmdKind_WriteUserData); rd_cmd(RD_CmdKind_WriteProjectData); rd_state->quit = 1; } }break; //- rjf: windows case RD_CmdKind_OpenWindow: { CFG_Node *old_window = cfg_node_from_id(rd_regs()->window); CFG_Node *bucket = old_window->parent; if(bucket == &cfg_nil_node) { bucket = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); } CFG_Node *new_window = cfg_node_new(rd_state->cfg, bucket, str8_lit("window")); CFG_Node *size = cfg_node_new(rd_state->cfg, new_window, str8_lit("size")); cfg_node_newf(rd_state->cfg, size, "1280"); cfg_node_newf(rd_state->cfg, size, "720"); for(CFG_Node *old_child = old_window->first; old_child != &cfg_nil_node; old_child = old_child->next) { if(!str8_match(old_child->string, str8_lit("panels"), 0) && !str8_match(old_child->string, str8_lit("size"), 0) && !str8_match(old_child->string, str8_lit("pos"), 0) && !str8_match(old_child->string, str8_lit("monitor"), 0) && !str8_match(old_child->string, str8_lit("fullscreen"), 0) && !str8_match(old_child->string, str8_lit("maximized"), 0)) { CFG_Node *new_child = cfg_node_deep_copy(rd_state->cfg, old_child); cfg_node_insert_child(rd_state->cfg, new_window, new_window->last, new_child); } } CFG_Node *panels = cfg_node_new(rd_state->cfg, new_window, str8_lit("panels")); cfg_node_child_from_string_or_alloc(rd_state->cfg, panels, str8_lit("selected")); }break; case RD_CmdKind_WindowSettings: { String8 expr = push_str8f(scratch.arena, "query:config.$%I64x", rd_regs()->window); rd_cmd(RD_CmdKind_PushQuery, .expr = expr, .do_implicit_root = 1, .do_big_rows = 1, .do_lister = 1); }break; case RD_CmdKind_CloseWindow: { CFG_NodePtrList all_windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); CFG_Node *wcfg = cfg_node_from_id(rd_regs()->window); if(all_windows.count == 1 && all_windows.first->v == wcfg) { rd_cmd(RD_CmdKind_Exit); } else { cfg_node_release(rd_state->cfg, wcfg); } }break; case RD_CmdKind_ToggleFullscreen: { CFG_Node *wcfg = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(wcfg); if(ws != &rd_nil_window_state) { os_window_set_fullscreen(ws->os, !os_window_is_fullscreen(ws->os)); } }break; case RD_CmdKind_BringToFront: { CFG_Node *last_focused_wcfg = cfg_node_from_id(rd_state->last_focused_window); RD_WindowState *last_focused_ws = rd_window_state_from_cfg(last_focused_wcfg); if(last_focused_ws == &rd_nil_window_state) { last_focused_ws = rd_state->first_window_state; } if(last_focused_ws != &rd_nil_window_state) { os_window_set_minimized(last_focused_ws->os, 0); os_window_focus(last_focused_ws->os); } }break; //- rjf: confirmations case RD_CmdKind_PopupAccept: { rd_state->popup_active = 0; rd_state->popup_key = ui_key_zero(); for(RD_CmdNode *n = rd_state->popup_cmds.first; n != 0; n = n->next) { rd_push_cmd(n->cmd.name, n->cmd.regs); } }break; case RD_CmdKind_PopupCancel: { rd_state->popup_active = 0; rd_state->popup_key = ui_key_zero(); }break; //- rjf: keybindings case RD_CmdKind_ResetToDefaultBindings: { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_NodePtrList all_keybindings = cfg_node_child_list_from_string(scratch.arena, user, str8_lit("keybindings")); for(CFG_NodePtrNode *n = all_keybindings.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, n->v); } CFG_Node *keybindings = cfg_node_new(rd_state->cfg, user, str8_lit("keybindings")); for EachElement(idx, rd_default_binding_table) { String8 name = rd_default_binding_table[idx].string; CFG_Binding binding = rd_default_binding_table[idx].binding; CFG_Node *binding_root = cfg_node_new(rd_state->cfg, keybindings, str8_zero()); cfg_node_new(rd_state->cfg, binding_root, name); cfg_node_new(rd_state->cfg, binding_root, os_g_key_cfg_string_table[binding.key]); if(binding.modifiers & OS_Modifier_Ctrl) {cfg_node_newf(rd_state->cfg, binding_root, "ctrl");} if(binding.modifiers & OS_Modifier_Shift) {cfg_node_newf(rd_state->cfg, binding_root, "shift");} if(binding.modifiers & OS_Modifier_Alt) {cfg_node_newf(rd_state->cfg, binding_root, "alt");} } }break; //- rjf: config path saving/loading/applying case RD_CmdKind_OpenRecentProject: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); CFG_Node *path = cfg_node_child_from_string(cfg, str8_lit("path")); if(str8_match(cfg->string, str8_lit("recent_project"), 0) && path->first->string.size != 0) { rd_cmd(RD_CmdKind_OpenProject, .file_path = path->first->string); } }break; case RD_CmdKind_OpenUser: case RD_CmdKind_OpenProject: { String8 file_root_key = (kind == RD_CmdKind_OpenUser ? str8_lit("user") : kind == RD_CmdKind_OpenProject ? str8_lit("project") : str8_lit("other")); CFG_Node *file_root = cfg_node_child_from_string(cfg_node_root(), file_root_key); //- rjf: load the new file's data String8 file_path = rd_regs()->file_path; String8 file_data = os_data_from_file_path(scratch.arena, file_path); FileProperties file_props = os_properties_from_file_path(file_path); //- rjf: determine if the file is good B32 file_is_okay = 0; { String8 stored_path = (kind == RD_CmdKind_OpenUser ? rd_state->user_path : rd_state->project_path); file_is_okay = ((file_props.size == 0 && file_props.created == 0) || str8_match(file_path, stored_path, 0) || stored_path.size == 0 || str8_match(str8_prefix(file_data, 9), str8_lit("// raddbg"), 0)); } //- rjf: determine file's version String8 file_version = {0}; if(file_is_okay && file_props.size != 0) { file_version = str8_skip(file_data, 10); U64 line_end = str8_find_needle(file_version, 0, str8_lit("\n"), 0); file_version = str8_prefix(file_version, line_end); U64 first_space = str8_find_needle(file_version, 0, str8_lit(" "), 0); file_version = str8_prefix(file_version, first_space); file_version = str8_skip_chop_whitespace(file_version); } //- rjf: bad file -> alert user if(!file_is_okay) { log_user_errorf("\"%S\" appears to refer to an existing file which is not a RADDBG config file. This would overwrite the file.", file_path); } //- rjf: eliminate all old state under this file tree if(file_is_okay) { cfg_node_release_all_children(rd_state->cfg, file_root); } //- rjf: parse the new file, generate cfg entities for it CFG_NodePtrList file_cfg_list = {0}; if(file_is_okay) { U64 file_version_code = version_from_str8(file_version); if(file_version_code < Version(0, 9, 16)) { CFG_NodePtrList (*legacy_parse_function)(Arena *arena, String8 file_path, String8 data) = rd_cfg_tree_list_from_string__pre_0_9_16; file_cfg_list = legacy_parse_function(scratch.arena, file_path, file_data); } else { file_cfg_list = cfg_node_ptr_list_from_string(scratch.arena, rd_state->cfg, rd_state->cfg_schema_table, str8_chop_last_slash(file_path), file_data); } } //- rjf: store path if(file_is_okay) { switch(kind) { default:{}break; case RD_CmdKind_OpenUser: { arena_clear(rd_state->user_path_arena); rd_state->user_path = push_str8_copy(rd_state->user_path_arena, file_path); }break; case RD_CmdKind_OpenProject: { arena_clear(rd_state->project_path_arena); rd_state->project_path = push_str8_copy(rd_state->project_path_arena, file_path); }break; } } //- rjf: insert the new cfg entities into this file tree if(file_is_okay) { for(CFG_NodePtrNode *n = file_cfg_list.first; n != 0; n = n->next) { cfg_node_insert_child(rd_state->cfg, file_root, file_root->last, n->v); } } //- rjf: if config did not open any windows for the user, then we need to open a sensible default if(file_is_okay && kind == RD_CmdKind_OpenUser) { CFG_NodePtrList all_user_windows = cfg_node_child_list_from_string(scratch.arena, file_root, str8_lit("window")); if(all_user_windows.count == 0) { OS_Handle monitor = os_primary_monitor(); String8 monitor_name = os_name_from_monitor(scratch.arena, monitor); Vec2F32 monitor_dim = os_dim_from_monitor(monitor); F32 monitor_dpi = os_dpi_from_monitor(monitor); Vec2F32 window_dim = v2f32(monitor_dim.x*4/5, monitor_dim.y*4/5); if(window_dim.x == 0 || window_dim.y == 0) { window_dim = v2f32(1280, 720); } CFG_Node *new_window = cfg_node_new(rd_state->cfg, file_root, str8_lit("window")); CFG_Node *size = cfg_node_new(rd_state->cfg, new_window, str8_lit("size")); cfg_node_newf(rd_state->cfg, size, "%f", window_dim.x); cfg_node_newf(rd_state->cfg, size, "%f", window_dim.y); F32 line_height_guess = 11.f * (monitor_dpi / 96.f); F32 num_lines_in_monitor_height = monitor_dim.y / line_height_guess; if(num_lines_in_monitor_height < 100) { rd_cmd(RD_CmdKind_ResetToCompactPanels, .window = new_window->id); } else { rd_cmd(RD_CmdKind_ResetToDefaultPanels, .window = new_window->id); } } } //- rjf: if config did not define any keybindings for the user, then we need to build a sensible default if(file_is_okay && kind == RD_CmdKind_OpenUser) { CFG_NodePtrList all_keybindings = cfg_node_child_list_from_string(scratch.arena, file_root, str8_lit("keybindings")); if(all_keybindings.count == 0) { rd_cmd(RD_CmdKind_ResetToDefaultBindings); } } //- rjf: record last-opened user in config directory if(file_is_okay && kind == RD_CmdKind_OpenUser) { rd_cmd(RD_CmdKind_RecordUserAsLastOpened); } //- rjf: record recently-opened projects in the user if(file_is_okay && kind == RD_CmdKind_OpenProject) { rd_cmd(RD_CmdKind_RecordProjectInUser); } //- rjf: eliminate all project-filtered tab focuses if(file_is_okay && kind == RD_CmdKind_OpenProject) { CFG_NodePtrList windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); for(CFG_NodePtrNode *n = windows.first; n != 0; n = n->next) { CFG_PanelTree panels = cfg_panel_tree_from_cfg(scratch.arena, n->v); for(CFG_PanelNode *panel = panels.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panels.root, panel).next) { if(rd_cfg_is_project_filtered(panel->selected_tab)) { for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(!rd_cfg_is_project_filtered(tab)) { rd_cmd(RD_CmdKind_FocusTab, .tab = tab->id); break; } } } } } } //- rjf: if we've just loaded the user, and we do not have a project path, // then we should try to look at the user's data for recent projects and // load one of those, *or* just the default. if(file_is_okay && kind == RD_CmdKind_OpenUser && rd_state->project_path.size == 0) { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *recent_project = cfg_node_child_from_string(user, str8_lit("recent_project")); String8 project_path = rd_path_from_cfg(recent_project); if(project_path.size == 0) { String8 user_program_data_path = os_get_process_info()->user_program_data_path; String8 user_data_folder = push_str8f(scratch.arena, "%S/%S", user_program_data_path, str8_lit("raddbg")); os_make_directory(user_data_folder); project_path = push_str8f(scratch.arena, "%S/default.raddbg_project", user_data_folder); } rd_cmd(RD_CmdKind_OpenProject, .file_path = project_path); } //- rjf: update all window titles if(file_is_okay) { String8 window_title = rd_push_window_title(scratch.arena); for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { os_window_set_title(ws->os, window_title); } } }break; case RD_CmdKind_NewUser: case RD_CmdKind_NewProject: { String8 new_path = rd_regs()->file_path; B32 file_will_be_overwritten = (os_properties_from_file_path(new_path).created != 0); UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("new_config_overwrite_confirm")); if(file_will_be_overwritten && !rd_regs()->force_confirm && !ui_key_match(rd_state->popup_key, key)) { rd_state->popup_key = key; rd_state->popup_active = 1; arena_clear(rd_state->popup_arena); MemoryZeroStruct(&rd_state->popup_cmds); rd_state->popup_title = push_str8f(rd_state->popup_arena, "Are you sure you want to save to this path?"); rd_state->popup_desc = push_str8f(rd_state->popup_arena, "The existing file at '%S' will be overwritten.", new_path); RD_Regs *regs = rd_regs_copy(rd_frame_arena(), rd_regs()); regs->force_confirm = 1; rd_cmd_list_push_new(rd_state->popup_arena, &rd_state->popup_cmds, rd_cmd_kind_info_table[kind].string, regs); } else switch(kind) { default:{}break; case RD_CmdKind_NewUser: { os_delete_file_at_path(new_path); rd_cmd(RD_CmdKind_OpenUser, .file_path = new_path); }break; case RD_CmdKind_NewProject: { os_delete_file_at_path(new_path); rd_cmd(RD_CmdKind_OpenProject, .file_path = new_path); }break; } }break; case RD_CmdKind_SaveUser: case RD_CmdKind_SaveProject: { String8 new_path = rd_regs()->file_path; B32 file_will_be_overwritten = (os_properties_from_file_path(new_path).created != 0); UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("save_config_overwrite_confirm")); if(file_will_be_overwritten && !rd_regs()->force_confirm && !ui_key_match(rd_state->popup_key, key)) { rd_state->popup_key = key; rd_state->popup_active = 1; arena_clear(rd_state->popup_arena); MemoryZeroStruct(&rd_state->popup_cmds); rd_state->popup_title = push_str8f(rd_state->popup_arena, "Are you sure you want to save to this path?"); rd_state->popup_desc = push_str8f(rd_state->popup_arena, "The existing file at '%S' will be overwritten.", new_path); RD_Regs *regs = rd_regs_copy(rd_frame_arena(), rd_regs()); regs->force_confirm = 1; rd_cmd_list_push_new(rd_state->popup_arena, &rd_state->popup_cmds, rd_cmd_kind_info_table[kind].string, regs); } else switch(kind) { default:{}break; case RD_CmdKind_SaveUser: { arena_clear(rd_state->user_path_arena); rd_state->user_path = push_str8_copy(rd_state->user_path_arena, new_path); rd_cmd(RD_CmdKind_WriteUserData); rd_cmd(RD_CmdKind_RecordUserAsLastOpened); }break; case RD_CmdKind_SaveProject: { arena_clear(rd_state->project_path_arena); rd_state->project_path = push_str8_copy(rd_state->project_path_arena, new_path); rd_cmd(RD_CmdKind_WriteProjectData); rd_cmd(RD_CmdKind_RecordProjectInUser); }break; } }break; case RD_CmdKind_RecordProjectInUser: { String8 file_path = rd_regs()->file_path; CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_NodePtrList recent_projects = cfg_node_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); CFG_Node *recent_project = &cfg_nil_node; for(CFG_NodePtrNode *n = recent_projects.first; n != 0; n = n->next) { if(path_match_normalized(rd_path_from_cfg(n->v), file_path)) { recent_project = n->v; break; } } if(recent_project == &cfg_nil_node) { recent_project = cfg_node_new(rd_state->cfg, user, str8_lit("recent_project")); CFG_Node *path_root = cfg_node_new(rd_state->cfg, recent_project, str8_lit("path")); cfg_node_new(rd_state->cfg, path_root, file_path); } cfg_node_unhook(rd_state->cfg, user, recent_project); cfg_node_insert_child(rd_state->cfg, user, &cfg_nil_node, recent_project); recent_projects = cfg_node_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); if(recent_projects.count > 32) { cfg_node_release(rd_state->cfg, recent_projects.last->v); } }break; case RD_CmdKind_RecordUserAsLastOpened: { String8 file_path = rd_regs()->file_path; String8 last_user_path = push_str8f(scratch.arena, "%S/raddbg/last_user", os_get_process_info()->user_program_data_path); os_write_data_to_file_path(last_user_path, file_path); }break; //- rjf: writing config changes case RD_CmdKind_WriteUserData: dst_path = rd_state->user_path; bucket_name = str8_lit("user"); goto write; case RD_CmdKind_WriteProjectData: dst_path = rd_state->project_path; bucket_name = str8_lit("project"); goto write; write:; { B32 dst_exists = (os_properties_from_file_path(dst_path).created != 0); String8 temp_path = push_str8f(scratch.arena, "%S.temp", dst_path); String8 overwritten_path = push_str8f(scratch.arena, "%S.old", dst_path); CFG_Node *tree_root = cfg_node_child_from_string(cfg_node_root(), bucket_name); String8List strings = {0}; str8_list_pushf(scratch.arena, &strings, "// raddbg %s %S file\n\n", BUILD_VERSION_STRING_LITERAL, bucket_name); for(CFG_Node *child = tree_root->first; child != &cfg_nil_node; child = child->next) { str8_list_push(scratch.arena, &strings, cfg_string_from_tree(scratch.arena, rd_state->cfg_schema_table, str8_chop_last_slash(dst_path), child)); } String8 data = str8_list_join(scratch.arena, &strings, 0); B32 temp_write_good = os_write_data_to_file_path(temp_path, data); B32 old_del_good = (temp_write_good && os_delete_file_at_path(overwritten_path)); B32 old_move_good = (temp_write_good && (!dst_exists || os_move_file_path(overwritten_path, dst_path))); B32 new_move_good = (old_move_good && os_move_file_path(dst_path, temp_path)); if(new_move_good && dst_exists) { os_delete_file_at_path(overwritten_path); } else if(!new_move_good && old_move_good && dst_exists) { os_move_file_path(dst_path, overwritten_path); } }break; //- rjf: opening user/project settings case RD_CmdKind_UserSettings: { rd_cmd(RD_CmdKind_PushQuery, .expr = str8_lit("query:user_settings"), .do_implicit_root = 1, .do_big_rows = 1, .do_lister = 1); }break; case RD_CmdKind_ProjectSettings: { rd_cmd(RD_CmdKind_PushQuery, .expr = str8_lit("query:project_settings"), .do_implicit_root = 1, .do_big_rows = 1, .do_lister = 1); }break; //- rjf: font sizes case RD_CmdKind_IncWindowFontSize: cfg = cfg_node_from_id(rd_regs()->window); rd_regs()->view = 0; rd_regs()->tab = 0; goto inc_font_size; case RD_CmdKind_IncViewFontSize: cfg = cfg_node_from_id(rd_regs()->view); goto inc_font_size; inc_font_size:; if(cfg != &cfg_nil_node) { fnt_reset(); F32 current_font_size = rd_font_size(); F32 new_font_size = current_font_size+1; new_font_size = Clamp(6.f, new_font_size, 72.f); CFG_Node *font_size_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("font_size")); cfg_node_new_replacef(rd_state->cfg, font_size_cfg, "%I64u", (U64)new_font_size); }break; case RD_CmdKind_DecWindowFontSize: cfg = cfg_node_from_id(rd_regs()->window); rd_regs()->view = 0; rd_regs()->tab = 0; goto dec_font_size; case RD_CmdKind_DecViewFontSize: cfg = cfg_node_from_id(rd_regs()->view); goto dec_font_size; dec_font_size:; if(cfg != &cfg_nil_node) { fnt_reset(); F32 current_font_size = rd_font_size(); F32 new_font_size = current_font_size-1; new_font_size = Clamp(6.f, new_font_size, 72.f); CFG_Node *font_size_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("font_size")); cfg_node_new_replacef(rd_state->cfg, font_size_cfg, "%I64u", (U64)new_font_size); }break; //- rjf: panel creation case RD_CmdKind_NewPanelLeft: {split_dir = Dir2_Left;}goto split; case RD_CmdKind_NewPanelUp: {split_dir = Dir2_Up;}goto split; case RD_CmdKind_NewPanelRight:{split_dir = Dir2_Right;}goto split; case RD_CmdKind_NewPanelDown: {split_dir = Dir2_Down;}goto split; case RD_CmdKind_SplitPanel: { split_dir = rd_regs()->dir2; split_panel = cfg_node_from_id(rd_regs()->dst_panel); }goto split; split:; if(split_dir != Dir2_Invalid) { // rjf: unpack Axis2 split_axis = axis2_from_dir2(split_dir); Side split_side = side_from_dir2(split_dir); if(split_panel == &cfg_nil_node) { split_panel = cfg_node_from_id(rd_regs()->panel); } CFG_Node *new_panel_cfg = &cfg_nil_node; CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, split_panel); CFG_PanelNode *panel_root = panel_tree.root; CFG_PanelNode *panel = cfg_panel_node_from_tree_cfg(panel_root, split_panel); CFG_PanelNode *parent = panel->parent; // rjf: splitting on same axis as parent -> insert new sibling on same axis, adjust sizes if(parent != &cfg_nil_panel_node && parent->split_axis == split_axis) { CFG_Node *parent_cfg = parent->cfg; CFG_Node *panel_cfg = panel->cfg; CFG_Node *new_cfg = cfg_node_alloc(rd_state->cfg); cfg_node_insert_child(rd_state->cfg, parent_cfg, split_side == Side_Max ? panel_cfg : panel_cfg->prev, new_cfg); cfg_node_equip_stringf(rd_state->cfg, new_cfg, "%f", 1.f/(parent->child_count+1)); for(CFG_PanelNode *child = parent->first; child != &cfg_nil_panel_node; child = child->next) { F32 old_pct = child->pct_of_parent; F32 new_pct = old_pct * ((F32)(parent->child_count) / (parent->child_count+1)); cfg_node_equip_stringf(rd_state->cfg, child->cfg, "%f", new_pct); } new_panel_cfg = new_cfg; } // rjf: splitting on opposite axis as parent - need to create new replacement node, + new sibling else { CFG_Node *split_panel_prev = panel->prev->cfg; CFG_Node *new_parent = cfg_node_alloc(rd_state->cfg); CFG_Node *new_sibling = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, new_parent, split_panel->string); cfg_node_equip_string(rd_state->cfg, split_panel, str8_lit("0.5")); cfg_node_equip_string(rd_state->cfg, new_sibling, str8_lit("0.5")); if(parent->cfg != &cfg_nil_node) { cfg_node_unhook(rd_state->cfg, parent->cfg, split_panel); cfg_node_insert_child(rd_state->cfg, parent->cfg, split_panel_prev, new_parent); } else { cfg_node_equip_string(rd_state->cfg, new_parent, str8_lit("panels")); CFG_Node *window_cfg = rd_window_from_cfg(split_panel); cfg_node_insert_child(rd_state->cfg, window_cfg, window_cfg->last, new_parent); if(split_axis == Axis2_X) { cfg_node_child_from_string_or_alloc(rd_state->cfg, window_cfg, str8_lit("split_x")); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window_cfg, str8_lit("split_x"))); } } CFG_Node *min = split_panel; CFG_Node *max = new_sibling; if(split_side == Side_Min) { Swap(CFG_Node *, min, max); } cfg_node_insert_child(rd_state->cfg, new_parent, new_parent->last, min); cfg_node_insert_child(rd_state->cfg, new_parent, new_parent->last, max); new_panel_cfg = new_sibling; } // rjf: pre-emptively set up the animation rectangle, depending on where // the new panel was inserted { RD_WindowState *ws = rd_window_state_from_cfg(new_panel_cfg); if(ws != &rd_nil_window_state) { ui_select_state(ws->ui); CFG_PanelTree new_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, new_panel_cfg); CFG_PanelNode *new_panel = cfg_panel_node_from_tree_cfg(new_panel_tree.root, new_panel_cfg); Rng2F32 stub_content_rect = r2f32p(0, 0, 1000, 1000); Vec2F32 stub_content_rect_dim = dim_2f32(stub_content_rect); Rng2F32 new_rect_px = cfg_target_rect_from_panel_node(stub_content_rect, new_panel_tree.root, new_panel); Rng2F32 new_rect_pct = r2f32p(new_rect_px.x0/stub_content_rect_dim.x, new_rect_px.y0/stub_content_rect_dim.y, new_rect_px.x1/stub_content_rect_dim.x, new_rect_px.y1/stub_content_rect_dim.y); if(new_panel->prev != &cfg_nil_panel_node) { Rng2F32 target_prev_rect_px = cfg_target_rect_from_panel_node(stub_content_rect, panel_tree.root, cfg_panel_node_from_tree_cfg(panel_tree.root, new_panel->prev->cfg)); Rng2F32 target_prev_rect_pct = r2f32p(target_prev_rect_px.x0/stub_content_rect_dim.x, target_prev_rect_px.y0/stub_content_rect_dim.y, target_prev_rect_px.x1/stub_content_rect_dim.x, target_prev_rect_px.y1/stub_content_rect_dim.y); Rng2F32 prev_rect_pct = r2f32p(ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x0", new_panel->prev->cfg), target_prev_rect_pct.x0, .initial = target_prev_rect_pct.x0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y0", new_panel->prev->cfg), target_prev_rect_pct.y0, .initial = target_prev_rect_pct.y0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x1", new_panel->prev->cfg), target_prev_rect_pct.x1, .initial = target_prev_rect_pct.x1, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y1", new_panel->prev->cfg), target_prev_rect_pct.y1, .initial = target_prev_rect_pct.y1, .rate = rd_state->menu_animation_rate)); new_rect_pct = prev_rect_pct; new_rect_pct.p0.v[split_axis] = new_rect_pct.p1.v[split_axis]; } if(new_panel->next != &cfg_nil_panel_node) { Rng2F32 target_next_rect_px = cfg_target_rect_from_panel_node(stub_content_rect, panel_tree.root, cfg_panel_node_from_tree_cfg(panel_tree.root, new_panel->next->cfg)); Rng2F32 target_next_rect_pct = r2f32p(target_next_rect_px.x0/stub_content_rect_dim.x, target_next_rect_px.y0/stub_content_rect_dim.y, target_next_rect_px.x1/stub_content_rect_dim.x, target_next_rect_px.y1/stub_content_rect_dim.y); Rng2F32 next_rect_pct = r2f32p(ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x0", new_panel->next->cfg), target_next_rect_pct.x0, .initial = target_next_rect_pct.x0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y0", new_panel->next->cfg), target_next_rect_pct.y0, .initial = target_next_rect_pct.y0, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x1", new_panel->next->cfg), target_next_rect_pct.x1, .initial = target_next_rect_pct.x1, .rate = rd_state->menu_animation_rate), ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y1", new_panel->next->cfg), target_next_rect_pct.y1, .initial = target_next_rect_pct.y1, .rate = rd_state->menu_animation_rate)); new_rect_pct = next_rect_pct; new_rect_pct.p1.v[split_axis] = new_rect_pct.p0.v[split_axis]; } ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x0", new_panel->cfg), new_rect_pct.x0, .initial = new_rect_pct.x0, .reset = 1, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_x1", new_panel->cfg), new_rect_pct.x1, .initial = new_rect_pct.x1, .reset = 1, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y0", new_panel->cfg), new_rect_pct.y0, .initial = new_rect_pct.y0, .reset = 1, .rate = rd_state->menu_animation_rate); ui_anim(ui_key_from_stringf(ui_key_zero(), "panel_%p_y1", new_panel->cfg), new_rect_pct.y1, .initial = new_rect_pct.y1, .reset = 1, .rate = rd_state->menu_animation_rate); } } // rjf: if this split was caused by drag/dropping a tab, and the originating panel // has no further tabs, then close the originating panel CFG_Node *dragdrop_origin_panel_cfg = cfg_node_from_id(rd_regs()->panel); CFG_Node *dragdrop_tab = cfg_node_from_id(rd_regs()->view); if(kind == RD_CmdKind_SplitPanel && new_panel_cfg != &cfg_nil_node && dragdrop_tab != &cfg_nil_node && dragdrop_origin_panel_cfg != &cfg_nil_node) { cfg_node_unhook(rd_state->cfg, dragdrop_origin_panel_cfg, dragdrop_tab); cfg_node_insert_child(rd_state->cfg, new_panel_cfg, new_panel_cfg->last, dragdrop_tab); CFG_PanelTree origin_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, dragdrop_origin_panel_cfg); CFG_PanelNode *origin_panel = cfg_panel_node_from_tree_cfg(origin_panel_tree.root, dragdrop_origin_panel_cfg); if(origin_panel->selected_tab == &cfg_nil_node) { for(CFG_NodePtrNode *n = origin_panel->tabs.first; n != 0; n = n->next) { if(!rd_cfg_is_project_filtered(n->v)) { rd_cmd(RD_CmdKind_FocusTab, .panel = origin_panel->cfg->id, .tab = n->v->id); break; } } } if(origin_panel->cfg != split_panel && origin_panel->tabs.count == 0) { rd_cmd(RD_CmdKind_ClosePanel); } rd_cmd(RD_CmdKind_FocusTab, .panel = new_panel_cfg->id, .tab = dragdrop_tab->id); } // rjf: focus new panel if(new_panel_cfg != &cfg_nil_node) { rd_cmd(RD_CmdKind_FocusPanel, .panel = new_panel_cfg->id); } // rjf: tabs on bottom on split panel? -> tabs on bottom on new panel if(panel->tab_side == Side_Max && split_axis == Axis2_X) { rd_cmd(RD_CmdKind_TabBarBottom, .panel = new_panel_cfg->id); } }break; //- rjf: panel rotation case RD_CmdKind_RotatePanelColumns: { CFG_Node *panel_cfg = cfg_node_from_id(rd_regs()->panel); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, panel_cfg); CFG_PanelNode *panel = cfg_panel_node_from_tree_cfg(panel_tree.root, panel_cfg); CFG_PanelNode *parent = &cfg_nil_panel_node; for(CFG_PanelNode *p = panel->parent; p != &cfg_nil_panel_node; p = p->parent) { if(p->split_axis == Axis2_X) { parent = p; break; } } if(parent != &cfg_nil_panel_node && parent->child_count > 1) { CFG_Node *rotated = parent->first->cfg; cfg_node_unhook(rd_state->cfg, parent->cfg, parent->first->cfg); cfg_node_insert_child(rd_state->cfg, parent->cfg, parent->last->cfg, rotated); } }break; //- rjf: panel focusing case RD_CmdKind_NextPanel: panel_sib_off = OffsetOf(CFG_PanelNode, next); panel_child_off = OffsetOf(CFG_PanelNode, first); goto cycle; case RD_CmdKind_PrevPanel: panel_sib_off = OffsetOf(CFG_PanelNode, prev); panel_child_off = OffsetOf(CFG_PanelNode, last); goto cycle; cycle:; { CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(rd_regs()->window)); CFG_PanelNode *next_focused = &cfg_nil_panel_node; for(CFG_PanelNode *p = panel_tree.focused; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first(panel_tree.root, p, panel_sib_off, panel_child_off).next) { if(p != panel_tree.focused && p->first == &cfg_nil_panel_node) { next_focused = p; break; } } if(next_focused == &cfg_nil_panel_node) { for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first(panel_tree.root, p, panel_sib_off, panel_child_off).next) { if(p != panel_tree.focused && p->first == &cfg_nil_panel_node) { next_focused = p; break; } } } rd_cmd(RD_CmdKind_FocusPanel, .panel = next_focused->cfg->id); }break; case RD_CmdKind_FocusPanel: { CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, panel); CFG_Node *selection_cfg = &cfg_nil_node; for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(panel_tree.root, p).next) { CFG_Node *p_cfg = p->cfg; CFG_Node *p_selection = cfg_node_child_from_string(p_cfg, str8_lit("selected")); if(selection_cfg == &cfg_nil_node) { selection_cfg = p_selection; } else for(CFG_Node *s = p_selection; s != &cfg_nil_node; s = cfg_node_child_from_string(p_cfg, str8_lit("selected"))) { cfg_node_release(rd_state->cfg, s); } } if(selection_cfg == &cfg_nil_node) { selection_cfg = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, selection_cfg, str8_lit("selected")); } if(panel != &cfg_nil_node) { cfg_node_insert_child(rd_state->cfg, panel, &cfg_nil_node, selection_cfg); CFG_Node *window = rd_window_from_cfg(panel); RD_WindowState *ws = rd_window_state_from_cfg(window); ws->menu_bar_focused = 0; } }break; //- rjf: directional panel focus changing case RD_CmdKind_FocusPanelRight: panel_change_dir = v2s32(+1, +0); goto focus_panel_dir; case RD_CmdKind_FocusPanelLeft: panel_change_dir = v2s32(-1, +0); goto focus_panel_dir; case RD_CmdKind_FocusPanelUp: panel_change_dir = v2s32(+0, -1); goto focus_panel_dir; case RD_CmdKind_FocusPanelDown: panel_change_dir = v2s32(+0, +1); goto focus_panel_dir; focus_panel_dir:; { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *src_panel = panel_tree.focused; Rng2F32 src_panel_rect = cfg_target_rect_from_panel_node(r2f32(v2f32(0, 0), v2f32(1000, 1000)), panel_tree.root, src_panel); Vec2F32 src_panel_center = center_2f32(src_panel_rect); Vec2F32 src_panel_half_dim = scale_2f32(dim_2f32(src_panel_rect), 0.5f); Vec2F32 travel_dim = add_2f32(src_panel_half_dim, v2f32(10.f, 10.f)); Vec2F32 travel_dst = add_2f32(src_panel_center, mul_2f32(travel_dim, v2f32((F32)panel_change_dir.x, (F32)panel_change_dir.y))); CFG_PanelNode *dst_root = &cfg_nil_panel_node; for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(panel_tree.root, p).next) { if(p == src_panel || p->first != &cfg_nil_panel_node) { continue; } Rng2F32 p_rect = cfg_target_rect_from_panel_node(r2f32(v2f32(0, 0), v2f32(1000, 1000)), panel_tree.root, p); if(contains_2f32(p_rect, travel_dst)) { dst_root = p; break; } } if(dst_root != &cfg_nil_panel_node) { CFG_PanelNode *dst_panel = &cfg_nil_panel_node; for(CFG_PanelNode *p = dst_root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(dst_root, p).next) { if(p->first == &cfg_nil_panel_node && p != src_panel) { dst_panel = p; break; } } rd_cmd(RD_CmdKind_FocusPanel, .panel = dst_panel->cfg->id); } }break; //- rjf: undo/redo case RD_CmdKind_Undo:{}break; case RD_CmdKind_Redo:{}break; //- rjf: focus history case RD_CmdKind_GoBack:{}break; case RD_CmdKind_GoForward:{}break; //- rjf: files case RD_CmdKind_SetCurrentPath: { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *current_path = cfg_node_child_from_string_or_alloc(rd_state->cfg, user, str8_lit("current_path")); cfg_node_new_replace(rd_state->cfg, current_path, rd_regs()->file_path); }break; case RD_CmdKind_SetFileReplacementPath: { // NOTE(rjf): // // foo.c // C:/test/bar/baz/foo.c // -> override foo.c -> C:/test/bar/baz/foo.c // // C:/foo/bar/baz.c // D:/foo/bar/baz.c // -> override C: -> D: // // C:/1/2/foo/bar.c // C:/2/3/foo/bar.c // -> override C:/1/2 -> C:2/3 // // C:/foo/bar/baz.c // D:/1/2/3.c // -> override C:/foo/bar/baz.c -> D:/1/2/3.c //- rjf: unpack String8 src_path = rd_regs()->string; String8 dst_path = rd_regs()->file_path; String8List src_path_parts = str8_split_path(scratch.arena, src_path); String8List dst_path_parts = str8_split_path(scratch.arena, dst_path); //- rjf: reverse path parts String8List src_path_parts__reversed = {0}; String8List dst_path_parts__reversed = {0}; for(String8Node *n = src_path_parts.first; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &src_path_parts__reversed, n->string); } for(String8Node *n = dst_path_parts.first; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &dst_path_parts__reversed, n->string); } //- rjf: trace from each path upwards, in lock-step, to find the first difference // between the paths String8Node *first_diff_src = src_path_parts__reversed.first; String8Node *first_diff_dst = dst_path_parts__reversed.first; for(;first_diff_src != 0 && first_diff_dst != 0;) { if(!str8_match(first_diff_src->string, first_diff_dst->string, StringMatchFlag_CaseInsensitive) || first_diff_src->next == 0 || first_diff_dst->next == 0) { break; } first_diff_src = first_diff_src->next; first_diff_dst = first_diff_dst->next; } //- rjf: form final map paths String8List map_src_parts = {0}; String8List map_dst_parts = {0}; for(String8Node *n = first_diff_src; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &map_src_parts, n->string); } for(String8Node *n = first_diff_dst; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &map_dst_parts, n->string); } StringJoin map_join = {.sep = str8_lit("/")}; String8 map_src = str8_list_join(scratch.arena, &map_src_parts, &map_join); String8 map_dst = str8_list_join(scratch.arena, &map_dst_parts, &map_join); //- rjf: store as file path map cfg CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); { CFG_NodePtrList cfgs = cfg_node_child_list_from_string(scratch.arena, user, str8_lit("file_path_map")); CFG_Node *map = &cfg_nil_node; for(CFG_NodePtrNode *n = cfgs.first; n != 0; n = n->next) { CFG_Node *src = cfg_node_child_from_string(n->v, str8_lit("source")); if(path_match_normalized(src->first->string, map_src)) { map = n->v; break; } } if(map == &cfg_nil_node) { map = cfg_node_new(rd_state->cfg, user, str8_lit("file_path_map")); } CFG_Node *src = cfg_node_child_from_string_or_alloc(rd_state->cfg, map, str8_lit("source")); CFG_Node *dst = cfg_node_child_from_string_or_alloc(rd_state->cfg, map, str8_lit("dest")); cfg_node_new_replace(rd_state->cfg, src, map_src); cfg_node_new_replace(rd_state->cfg, dst, map_dst); } }break; //- rjf: panel removal case RD_CmdKind_ClosePanel: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *panel = cfg_panel_node_from_tree_cfg(panel_tree.root, cfg_node_from_id(rd_regs()->panel)); CFG_PanelNode *parent = panel->parent; if(parent != &cfg_nil_panel_node) { Axis2 split_axis = parent->split_axis; // NOTE(rjf): If we're removing all but the last child of this parent, // we should just remove both children. if(parent->child_count == 2) { CFG_PanelNode *discard_child = panel; CFG_PanelNode *keep_child = (panel == parent->first ? parent->last : parent->first); CFG_PanelNode *grandparent = parent->parent; CFG_PanelNode *parent_prev = parent->prev; F32 pct_of_parent = parent->pct_of_parent; // rjf: unhook kept child cfg_node_unhook(rd_state->cfg, parent->cfg, keep_child->cfg); // rjf: unhook this subtree if(grandparent != &cfg_nil_panel_node) { cfg_node_unhook(rd_state->cfg, grandparent->cfg, parent->cfg); } // rjf: release the containing tree { cfg_node_release(rd_state->cfg, parent->cfg); } // rjf: re-hook our kept child into the overall tree if(grandparent == &cfg_nil_panel_node) { if(keep_child->split_axis == Axis2_X) { cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("split_x")); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("split_x"))); } cfg_node_equip_string(rd_state->cfg, keep_child->cfg, str8_lit("panels")); cfg_node_insert_child(rd_state->cfg, window, window->last, keep_child->cfg); } else { cfg_node_insert_child(rd_state->cfg, grandparent->cfg, parent_prev->cfg, keep_child->cfg); cfg_node_equip_stringf(rd_state->cfg, keep_child->cfg, "%f", pct_of_parent); } // rjf: keep-child split-axis == grandparent split-axis? bubble keep-child up into grandparent's children if(grandparent != &cfg_nil_panel_node && grandparent->split_axis == keep_child->split_axis && keep_child->first != &cfg_nil_panel_node) { cfg_node_unhook(rd_state->cfg, grandparent->cfg, keep_child->cfg); CFG_Node *prev = parent_prev->cfg; for(CFG_PanelNode *child = keep_child->first, *next = &cfg_nil_panel_node; child != &cfg_nil_panel_node; child = next) { next = child->next; cfg_node_unhook(rd_state->cfg, keep_child->cfg, child->cfg); cfg_node_insert_child(rd_state->cfg, grandparent->cfg, prev, child->cfg); prev = child->cfg; F32 old_pct = child->pct_of_parent; F32 new_pct = old_pct * pct_of_parent; cfg_node_equip_stringf(rd_state->cfg, child->cfg, "%f", new_pct); } cfg_node_release(rd_state->cfg, keep_child->cfg); } // rjf: reset focus, if needed if(panel_tree.focused == discard_child) { CFG_PanelTree new_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *new_focused = cfg_panel_node_from_tree_cfg(panel_tree.root, keep_child->cfg); for(CFG_PanelNode *grandchild = new_focused; grandchild != &cfg_nil_panel_node; grandchild = grandchild->first) { new_focused = grandchild; } rd_cmd(RD_CmdKind_FocusPanel, .panel = new_focused->cfg->id); } } // NOTE(rjf): Otherwise we can just remove this child. else { // rjf: remove CFG_PanelNode *next = &cfg_nil_panel_node; F32 removed_size_pct = panel->pct_of_parent; if(next == &cfg_nil_panel_node) { next = panel->prev; } if(next == &cfg_nil_panel_node) { next = panel->next; } cfg_node_unhook(rd_state->cfg, parent->cfg, panel->cfg); cfg_node_release(rd_state->cfg, panel->cfg); // rjf: resize siblings to this node { CFG_PanelTree new_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *new_parent = cfg_panel_node_from_tree_cfg(new_panel_tree.root, parent->cfg); for(CFG_PanelNode *child = new_parent->first; child != &cfg_nil_panel_node; child = child->next) { CFG_Node *cfg = child->cfg; F32 old_pct = child->pct_of_parent; F32 new_pct = old_pct / (1.f-removed_size_pct); cfg_node_equip_stringf(rd_state->cfg, cfg, "%f", new_pct); } } // rjf: reset focus, if needed if(panel_tree.focused == panel) { CFG_PanelTree new_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *new_focused = cfg_panel_node_from_tree_cfg(panel_tree.root, next->cfg); for(CFG_PanelNode *grandchild = new_focused; grandchild != &cfg_nil_panel_node; grandchild = grandchild->first) { new_focused = grandchild; } rd_cmd(RD_CmdKind_FocusPanel, .panel = new_focused->cfg->id); } } } }break; //- rjf: panel tab controls case RD_CmdKind_FocusTab: { CFG_Node *tab = cfg_node_from_id(rd_regs()->tab); CFG_Node *panel = tab->parent; CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, panel); CFG_PanelNode *panel_node = cfg_panel_node_from_tree_cfg(panel_tree.root, panel); CFG_Node *selection_cfg = &cfg_nil_node; for(CFG_NodePtrNode *n = panel_node->tabs.first; n != 0; n = n->next) { CFG_Node *tab_selection_cfg = cfg_node_child_from_string(n->v, str8_lit("selected")); if(selection_cfg == &cfg_nil_node) { selection_cfg = tab_selection_cfg; } else for(CFG_Node *s = tab_selection_cfg; s != &cfg_nil_node; s = cfg_node_child_from_string(n->v, str8_lit("selected"))) { cfg_node_release(rd_state->cfg, s); } } if(selection_cfg == &cfg_nil_node) { selection_cfg = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, selection_cfg, str8_lit("selected")); } cfg_node_insert_child(rd_state->cfg, tab, &cfg_nil_node, selection_cfg); }break; case RD_CmdKind_NextTab: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *focused = panel_tree.focused; CFG_NodePtrNode *selected_tab_n = 0; for(CFG_NodePtrNode *n = focused->tabs.first; n != 0; n = n->next) { if(n->v == focused->selected_tab) { selected_tab_n = n; break; } } CFG_Node *next_selected_tab = &cfg_nil_node; U64 idx = 0; for(CFG_NodePtrNode *tab_n = selected_tab_n; tab_n != 0 && (tab_n != selected_tab_n || idx == 0); ((tab_n->next == 0) ? (tab_n = focused->tabs.first) : (tab_n = tab_n->next)), idx += 1) { if(!rd_cfg_is_project_filtered(tab_n->v) && tab_n != selected_tab_n) { next_selected_tab = tab_n->v; break; } } if(next_selected_tab != &cfg_nil_node) { rd_cmd(RD_CmdKind_FocusTab, .tab = next_selected_tab->id); } }break; case RD_CmdKind_PrevTab: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *focused = panel_tree.focused; CFG_NodePtrNode *selected_tab_n = 0; for(CFG_NodePtrNode *n = focused->tabs.last; n != 0; n = n->prev) { if(n->v == focused->selected_tab) { selected_tab_n = n; break; } } CFG_Node *next_selected_tab = &cfg_nil_node; U64 idx = 0; for(CFG_NodePtrNode *tab_n = selected_tab_n; tab_n != 0 && (tab_n != selected_tab_n || idx == 0); ((tab_n->prev == 0) ? (tab_n = focused->tabs.last) : (tab_n = tab_n->prev)), idx += 1) { if(!rd_cfg_is_project_filtered(tab_n->v) && tab_n != selected_tab_n) { next_selected_tab = tab_n->v; break; } } if(next_selected_tab != &cfg_nil_node) { rd_cmd(RD_CmdKind_FocusTab, .tab = next_selected_tab->id); } }break; case RD_CmdKind_MoveTabRight: case RD_CmdKind_MoveTabLeft: { CFG_Node *tab = cfg_node_from_id(rd_regs()->tab); CFG_Node *window = rd_window_from_cfg(tab); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); CFG_PanelNode *panel = cfg_panel_node_from_tree_cfg(panel_tree.root, tab->parent); CFG_NodePtrList filtered_tabs = {0}; for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) { if(rd_cfg_is_project_filtered(n->v)) { continue; } cfg_node_ptr_list_push(scratch.arena, &filtered_tabs, n->v); } CFG_Node *tab_prev2 = &cfg_nil_node; CFG_Node *tab_prev = &cfg_nil_node; CFG_Node *tab_next = &cfg_nil_node; { CFG_Node *prev2 = &cfg_nil_node; CFG_Node *prev = &cfg_nil_node; CFG_Node *next = &cfg_nil_node; for(CFG_NodePtrNode *n = filtered_tabs.first; n != 0; (prev2 = prev, prev = n->v, n = n->next)) { next = n->next ? n->next->v : &cfg_nil_node; if(n->v == tab) { tab_prev2 = prev2; tab_prev = prev; tab_next = next; break; } } } CFG_Node *new_prev = (kind == RD_CmdKind_MoveTabRight ? tab_next : tab_prev2); if(new_prev == tab_prev && filtered_tabs.last) { new_prev = filtered_tabs.last->v; } rd_cmd(RD_CmdKind_MoveView, .dst_panel = panel->cfg->id, .view = tab->id, .prev_tab = new_prev->id); }break; case RD_CmdKind_BuildTab: { String8 expr_file_path = rd_file_path_from_eval_string(scratch.arena, rd_regs()->expr); CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); CFG_Node *tab = cfg_node_new(rd_state->cfg, panel, rd_regs()->string); CFG_Node *expr = cfg_node_new(rd_state->cfg, tab, str8_lit("expression")); cfg_node_new(rd_state->cfg, expr, rd_regs()->expr); if(expr_file_path.size != 0) { CFG_Node *project = cfg_node_new(rd_state->cfg, tab, str8_lit("project")); cfg_node_new(rd_state->cfg, project, rd_state->project_path); } rd_cmd(RD_CmdKind_FocusTab, .tab = tab->id); }break; case RD_CmdKind_DuplicateTab: { CFG_Node *src = cfg_node_from_id(rd_regs()->tab); CFG_Node *dst = cfg_node_deep_copy(rd_state->cfg, src); cfg_node_insert_child(rd_state->cfg, src->parent, src, dst); rd_cmd(RD_CmdKind_FocusTab, .tab = dst->id); }break; case RD_CmdKind_CopyTabFullPath: { CFG_Node *tab = cfg_node_from_id(rd_regs()->tab); String8 expr = rd_expr_from_cfg(tab); String8 full_path = rd_file_path_from_eval_string(scratch.arena, expr); os_set_clipboard_text(full_path); }break; case RD_CmdKind_CloseTab: { CFG_Node *tab = cfg_node_from_id(rd_regs()->tab); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, tab); CFG_PanelNode *panel = cfg_panel_node_from_tree_cfg(panel_tree.root, tab->parent); if(panel->selected_tab == tab) { B32 found_selected = 0; CFG_Node *next_selected_tab = &cfg_nil_node; for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) { if(n->v == panel->selected_tab) { found_selected = 1; } else if(!rd_cfg_is_project_filtered(n->v)) { next_selected_tab = n->v; if(found_selected) { break; } } } rd_cmd(RD_CmdKind_FocusTab, .tab = next_selected_tab->id); } cfg_node_release(rd_state->cfg, tab); }break; case RD_CmdKind_MoveView: { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *prev_tab = cfg_node_from_id(rd_regs()->prev_tab); CFG_Node *src_panel = view->parent; CFG_Node *dst_panel = cfg_node_from_id(rd_regs()->dst_panel); if(dst_panel != &cfg_nil_node && prev_tab != view) { cfg_node_unhook(rd_state->cfg, src_panel, view); cfg_node_insert_child(rd_state->cfg, dst_panel, prev_tab, view); rd_cmd(RD_CmdKind_FocusTab, .panel = dst_panel->id, .tab = view->id); rd_cmd(RD_CmdKind_FocusPanel, .panel = dst_panel->id); CFG_PanelTree src_panel_tree = cfg_panel_tree_from_cfg(scratch.arena, src_panel); CFG_PanelNode *src_panel_node = cfg_panel_node_from_tree_cfg(src_panel_tree.root, src_panel); B32 src_panel_is_empty = 0; if(src_panel != dst_panel) { src_panel_is_empty = 1; for(CFG_NodePtrNode *n = src_panel_node->tabs.first; n != 0; n = n->next) { if(!rd_cfg_is_project_filtered(n->v)) { rd_cmd(RD_CmdKind_FocusTab, .panel = src_panel->id, .tab = n->v->id); src_panel_is_empty = 0; break; } } } if(src_panel_is_empty) { rd_cmd(RD_CmdKind_ClosePanel, .panel = src_panel->id); } } }break; case RD_CmdKind_TabBarTop: { CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); cfg_node_release(rd_state->cfg, cfg_node_child_from_string(panel, str8_lit("tabs_on_bottom"))); }break; case RD_CmdKind_TabBarBottom: { CFG_Node *panel = cfg_node_from_id(rd_regs()->panel); cfg_node_child_from_string_or_alloc(rd_state->cfg, panel, str8_lit("tabs_on_bottom")); }break; case RD_CmdKind_TabSettings: { String8 expr = push_str8f(scratch.arena, "query:config.$%I64x", rd_regs()->tab); rd_cmd(RD_CmdKind_PushQuery, .expr = expr, .do_implicit_root = 1, .do_big_rows = 1, .do_lister = 1); }break; //- rjf: files case RD_CmdKind_Open: { String8 path = path_absolute_dst_from_relative_dst_src(scratch.arena, rd_regs()->file_path, os_get_current_path(scratch.arena)); FileProperties props = os_properties_from_file_path(path); if(props.created != 0) { rd_cmd(RD_CmdKind_RecordFileInProject); rd_cmd(RD_CmdKind_BuildTab, .string = str8_lit("pending"), .expr = rd_eval_string_from_file_path(scratch.arena, path)); } else { log_user_errorf("Couldn't open file at \"%S\".", path); } }break; case RD_CmdKind_Switch: { String8 path = {0}; if(path.size == 0) { CFG_Node *recent_file = cfg_node_from_id(rd_regs()->cfg); CFG_Node *path_root = cfg_node_child_from_string(recent_file, str8_lit("path")); path = path_root->first->string; } if(path.size == 0) { path = rd_regs()->file_path; } rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = path, .cursor = txt_pt(0, 0), .vaddr = 0, .force_focus = 1, .prefer_new_tab = 1); }break; case RD_CmdKind_SwitchToPartnerFile: { String8 file_path = rd_regs()->file_path; String8 file_folder = str8_chop_last_slash(file_path); String8 file_name = str8_skip_last_slash(str8_chop_last_dot(file_path)); String8 file_ext = str8_skip_last_dot(file_path); String8 partner_ext_candidates[] = { str8_lit_comp("h"), str8_lit_comp("hpp"), str8_lit_comp("hxx"), str8_lit_comp("c"), str8_lit_comp("cc"), str8_lit_comp("cxx"), str8_lit_comp("cpp"), }; for(U64 idx = 0; idx < ArrayCount(partner_ext_candidates); idx += 1) { if(!str8_match(partner_ext_candidates[idx], file_ext, StringMatchFlag_CaseInsensitive)) { String8 candidate = push_str8f(scratch.arena, "%S.%S", file_name, partner_ext_candidates[idx]); String8 candidate_path = push_str8f(scratch.arena, "%S/%S", file_folder, candidate); FileProperties candidate_props = os_properties_from_file_path(candidate_path); if(candidate_props.modified != 0) { rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = candidate_path, .cursor = txt_pt(0, 0), .vaddr = 0, .prefer_new_tab = 1); break; } } } }break; case RD_CmdKind_RecordFileInProject: if(rd_regs()->file_path.size != 0) { String8 path = rd_regs()->file_path; CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_NodePtrList recent_files = cfg_node_child_list_from_string(scratch.arena, project, str8_lit("recent_file")); CFG_Node *recent_file = &cfg_nil_node; for(CFG_NodePtrNode *n = recent_files.first; n != 0; n = n->next) { if(path_match_normalized(rd_path_from_cfg(n->v), path)) { recent_file = n->v; break; } } if(recent_file == &cfg_nil_node) { recent_file = cfg_node_new(rd_state->cfg, project, str8_lit("recent_file")); CFG_Node *path_root = cfg_node_new(rd_state->cfg, recent_file, str8_lit("path")); cfg_node_new(rd_state->cfg, path_root, path); } cfg_node_unhook(rd_state->cfg, project, recent_file); cfg_node_insert_child(rd_state->cfg, project, &cfg_nil_node, recent_file); recent_files = cfg_node_child_list_from_string(scratch.arena, project, str8_lit("recent_file")); if(recent_files.count > 256) { cfg_node_release(rd_state->cfg, recent_files.last->v); } }break; case RD_CmdKind_ShowFileInExplorer: if(rd_regs()->file_path.size != 0) { String8 full_path = rd_regs()->file_path; os_show_in_filesystem_ui(full_path); }break; //- rjf: source <-> disasm case RD_CmdKind_GoToDisassembly: { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); U64 vaddr = 0; for(D_LineNode *n = rd_regs()->lines.first; n != 0; n = n->next) { CTRL_EntityList modules = ctrl_modules_from_dbgi_key(scratch.arena, &d_state->ctrl_entity_store->ctx, n->v.dbgi_key); CTRL_Entity *module = ctrl_module_from_thread_candidates(&d_state->ctrl_entity_store->ctx, thread, &modules); if(module != &ctrl_entity_nil) { vaddr = ctrl_vaddr_from_voff(module, n->v.voff_range.min); break; } } rd_cmd(RD_CmdKind_FindCodeLocation, .process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process)->handle, .vaddr = vaddr, .prefer_disasm = 1); }break; case RD_CmdKind_GoToSource: { if(rd_regs()->lines.first != 0) { rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = rd_regs()->lines.first->v.file_path, .cursor = rd_regs()->lines.first->v.pt, .vaddr = 0, .process = ctrl_handle_zero(), .prefer_disasm = 0); } }break; //- rjf: panel built-in layout builds case RD_CmdKind_ResetToDefaultPanels: case RD_CmdKind_ResetToCompactPanels: case RD_CmdKind_ResetToSimplePanels: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); CFG_Node *panels = cfg_node_child_from_string(window, str8_lit("panels")); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); //- rjf: define all of the "fixed" tabs we care about #define X(name) CFG_Node *name = &cfg_nil_node; #define Y(name, rule, expr) CFG_Node *name = &cfg_nil_node; #define Z(name) CFG_Node *name = &cfg_nil_node; RD_FixedTabXList #undef X #undef Y #undef Z //- rjf: find all the fixed tabs, and all text viewers B32 any_fixed_tabs_found = 0; CFG_NodePtrList texts = {0}; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) { CFG_Node *tab = n->v; B32 need_unhook = 1; if(0){} #define X(name) else if(str8_match(tab->string, str8_lit("watch"), 0) && str8_match(rd_expr_from_cfg(tab), str8_lit("query:" #name), 0)) {name = tab;} #define Y(name, rule, expr) else if(str8_match(tab->string, str8_lit(#rule), 0) && str8_match(rd_expr_from_cfg(tab), str8_lit(expr), 0)) {name = tab;} #define Z(name) else if(str8_match(tab->string, str8_lit(#name), 0)) {name = tab;} RD_FixedTabXList #undef X #undef Y #undef Z else if(str8_match(tab->string, str8_lit("text"), 0)) {cfg_node_ptr_list_push(scratch.arena, &texts, tab);} else { need_unhook = 0; } if(need_unhook) { cfg_node_unhook(rd_state->cfg, panel->cfg, tab); any_fixed_tabs_found = 1; } } } //- rjf: release the old panel tree cfg_node_release(rd_state->cfg, panels); //- rjf: allocate any missing tabs #define X(name) if(name == &cfg_nil_node) {name = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, name, str8_lit("watch")); CFG_Node *expr_cfg = cfg_node_new(rd_state->cfg, name, str8_lit("expression")); cfg_node_new(rd_state->cfg, expr_cfg, str8_lit("query:" #name));} #define Y(name, rule, expr) if(name == &cfg_nil_node) {name = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, name, str8_lit(#rule)); CFG_Node *expr_cfg = cfg_node_new(rd_state->cfg, name, str8_lit("expression")); cfg_node_new(rd_state->cfg, expr_cfg, str8_lit(expr));} #define Z(name) if(name == &cfg_nil_node && !any_fixed_tabs_found) {name = cfg_node_alloc(rd_state->cfg); cfg_node_equip_string(rd_state->cfg, name, str8_lit(#name));} RD_FixedTabXList #undef X #undef Y #undef Z //- rjf: eliminate all tab selections #define X(name) if(name != &cfg_nil_node) {cfg_node_release(rd_state->cfg, cfg_node_child_from_string(name, str8_lit("selected")));} #define Y(name, rule, expr) if(name != &cfg_nil_node) {cfg_node_release(rd_state->cfg, cfg_node_child_from_string(name, str8_lit("selected")));} #define Z(name) if(name != &cfg_nil_node) {cfg_node_release(rd_state->cfg, cfg_node_child_from_string(name, str8_lit("selected")));} RD_FixedTabXList #undef X #undef Y #undef Z for(CFG_NodePtrNode *n = texts.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(n->v, str8_lit("selected"))); } //- rjf: create the panel root panels = cfg_node_new(rd_state->cfg, window, str8_lit("panels")); //- rjf: rebuild the new panel tree switch(kind) { default:{}break; //- rjf: (default layout) case RD_CmdKind_ResetToDefaultPanels: { // rjf: root split cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("split_x")); CFG_Node *root_0 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.85")); CFG_Node *root_1 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.15")); // rjf: root_0 split CFG_Node *root_0_0 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.80")); CFG_Node *root_0_1 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.20")); // rjf: root_1 split CFG_Node *root_1_0 = cfg_node_new(rd_state->cfg, root_1, str8_lit("0.50")); CFG_Node *root_1_1 = cfg_node_new(rd_state->cfg, root_1, str8_lit("0.50")); cfg_node_insert_child(rd_state->cfg, root_1_0, root_1_0->last, targets); cfg_node_insert_child(rd_state->cfg, root_1_1, root_1_1->last, threads); cfg_node_insert_child(rd_state->cfg, root_1_1, root_1_1->last, processes); cfg_node_insert_child(rd_state->cfg, root_1_1, root_1_1->last, machines); cfg_node_new(rd_state->cfg, targets, str8_lit("selected")); cfg_node_new(rd_state->cfg, threads, str8_lit("selected")); // rjf: root 0_0 split CFG_Node *root_0_0_0 = cfg_node_new(rd_state->cfg, root_0_0, str8_lit("0.25")); CFG_Node *root_0_0_1 = cfg_node_new(rd_state->cfg, root_0_0, str8_lit("0.75")); // rjf: root_0_0_0 split CFG_Node *root_0_0_0_0 = cfg_node_new(rd_state->cfg, root_0_0_0, str8_lit("0.50")); CFG_Node *root_0_0_0_1 = cfg_node_new(rd_state->cfg, root_0_0_0, str8_lit("0.50")); cfg_node_insert_child(rd_state->cfg, root_0_0_0_0, root_0_0_0_0->last, disasm); cfg_node_new(rd_state->cfg, disasm, str8_lit("selected")); cfg_node_insert_child(rd_state->cfg, root_0_0_0_1, root_0_0_0_1->last, breakpoints); cfg_node_insert_child(rd_state->cfg, root_0_0_0_1, root_0_0_0_1->last, watch_pins); cfg_node_insert_child(rd_state->cfg, root_0_0_0_1, root_0_0_0_1->last, output); cfg_node_insert_child(rd_state->cfg, root_0_0_0_1, root_0_0_0_1->last, memory); cfg_node_new(rd_state->cfg, output, str8_lit("selected")); // rjf: root_0_1 split CFG_Node *root_0_1_0 = cfg_node_new(rd_state->cfg, root_0_1, str8_lit("0.60")); CFG_Node *root_0_1_1 = cfg_node_new(rd_state->cfg, root_0_1, str8_lit("0.40")); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, watches); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, locals); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, registers); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, globals); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, thread_locals); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, types); cfg_node_insert_child(rd_state->cfg, root_0_1_0, root_0_1_0->last, procedures); cfg_node_new(rd_state->cfg, watches, str8_lit("selected")); cfg_node_new(rd_state->cfg, root_0_1_0, str8_lit("tabs_on_bottom")); cfg_node_insert_child(rd_state->cfg, root_0_1_1, root_0_1_1->last, call_stack); cfg_node_insert_child(rd_state->cfg, root_0_1_1, root_0_1_1->last, modules); cfg_node_new(rd_state->cfg, call_stack, str8_lit("selected")); cfg_node_new(rd_state->cfg, root_0_1_1, str8_lit("tabs_on_bottom")); // rjf: fill main panel with getting started, OR all collected code views CFG_Node *main_panel = root_0_0_1; if(getting_started != &cfg_nil_node) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, getting_started); cfg_node_new(rd_state->cfg, getting_started, str8_lit("selected")); } else if(texts.first) { cfg_node_new(rd_state->cfg, texts.first->v, str8_lit("selected")); } for(CFG_NodePtrNode *n = texts.first; n != 0; n = n->next) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, n->v); } // rjf: set main panel as selected cfg_node_new(rd_state->cfg, main_panel, str8_lit("selected")); }break; //- rjf: (compact layout) case RD_CmdKind_ResetToCompactPanels: { // rjf: root split cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("split_x")); CFG_Node *root_0 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.25")); CFG_Node *root_1 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.75")); // rjf: root_0 split CFG_Node *root_0_0 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.25")); CFG_Node *root_0_1 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.25")); CFG_Node *root_0_2 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.25")); CFG_Node *root_0_3 = cfg_node_new(rd_state->cfg, root_0, str8_lit("0.25")); cfg_node_insert_child(rd_state->cfg, root_0_0, root_0_0->last, watches); cfg_node_insert_child(rd_state->cfg, root_0_0, root_0_0->last, types); cfg_node_new(rd_state->cfg, watches, str8_lit("selected")); cfg_node_insert_child(rd_state->cfg, root_0_1, root_0_1->last, threads); cfg_node_insert_child(rd_state->cfg, root_0_1, root_0_1->last, targets); cfg_node_insert_child(rd_state->cfg, root_0_1, root_0_1->last, breakpoints); cfg_node_insert_child(rd_state->cfg, root_0_1, root_0_1->last, watch_pins); cfg_node_new(rd_state->cfg, threads, str8_lit("selected")); cfg_node_insert_child(rd_state->cfg, root_0_2, root_0_2->last, disasm); cfg_node_insert_child(rd_state->cfg, root_0_2, root_0_2->last, output); cfg_node_new(rd_state->cfg, disasm, str8_lit("selected")); cfg_node_insert_child(rd_state->cfg, root_0_3, root_0_3->last, call_stack); cfg_node_insert_child(rd_state->cfg, root_0_3, root_0_3->last, modules); cfg_node_new(rd_state->cfg, call_stack, str8_lit("selected")); // rjf: fill main panel with getting started, OR all collected code views CFG_Node *main_panel = root_1; if(getting_started != &cfg_nil_node) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, getting_started); cfg_node_new(rd_state->cfg, getting_started, str8_lit("selected")); } else if(texts.first) { cfg_node_new(rd_state->cfg, texts.first->v, str8_lit("selected")); } for(CFG_NodePtrNode *n = texts.first; n != 0; n = n->next) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, n->v); } // rjf: set main panel as selected cfg_node_new(rd_state->cfg, main_panel, str8_lit("selected")); }break; //- rjf: simple layout case RD_CmdKind_ResetToSimplePanels: { // rjf: root split cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("split_x")); CFG_Node *root_0 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.25")); CFG_Node *root_1 = cfg_node_new(rd_state->cfg, panels, str8_lit("0.75")); // rjf: fill smaller panel with watch cfg_node_insert_child(rd_state->cfg, root_0, root_0->last, watches); cfg_node_new(rd_state->cfg, watches, str8_lit("selected")); // rjf: fill main panel with getting started, OR all collected code views CFG_Node *main_panel = root_1; if(getting_started != &cfg_nil_node) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, getting_started); cfg_node_new(rd_state->cfg, getting_started, str8_lit("selected")); } else if(texts.first) { cfg_node_new(rd_state->cfg, texts.first->v, str8_lit("selected")); } for(CFG_NodePtrNode *n = texts.first; n != 0; n = n->next) { cfg_node_insert_child(rd_state->cfg, main_panel, main_panel->last, n->v); } // rjf: set main panel as selected cfg_node_new(rd_state->cfg, main_panel, str8_lit("selected")); }break; } //- rjf: release any unused views from the previous layout #define X(name) if(name->parent == &cfg_nil_node) {cfg_node_release(rd_state->cfg, name);} #define Y(name, rule, expr) if(name->parent == &cfg_nil_node) {cfg_node_release(rd_state->cfg, name);} #define Z(name) if(name->parent == &cfg_nil_node) {cfg_node_release(rd_state->cfg, name);} RD_FixedTabXList #undef X #undef Y #undef Z //- rjf: remember that we reset the panel layouts RD_WindowState *ws = rd_window_state_from_cfg(window); if(ws != &rd_nil_window_state) { ws->window_layout_reset = 1; } }break; //- rjf: thread finding case RD_CmdKind_FindThread: { Access *access = access_open(); //- rjf: unpack thread info CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); U64 unwind_index = rd_regs()->unwind_count; U64 inline_depth = rd_regs()->inline_depth; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_index); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, rip_voff); D_Line line = {0}; { U64 idx = 0; for(D_LineNode *n = lines.first; n != 0; n = n->next, idx += 1) { line = n->v; if(idx == inline_depth) { break; } } } B32 missing_rip = (rip_vaddr == 0); B32 dbgi_missing = (di_key_match(di_key_zero(), dbgi_key)); B32 dbgi_pending = !dbgi_missing && rdi == &rdi_parsed_nil; B32 has_line_info = (line.voff_range.max != 0); B32 has_module = (module != &ctrl_entity_nil); B32 has_dbg_info = has_module && !dbgi_missing; //- rjf: find-code-location on each affected window if(!dbgi_pending && (has_line_info || has_module)) { rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = line.file_path, .cursor = line.pt, .process = process->handle, .voff = rip_voff, .vaddr = rip_vaddr, .unwind_count = unwind_index, .inline_depth = inline_depth, .all_windows = 1); } if(!missing_rip && !dbgi_pending && !has_line_info && !has_module) { rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = str8_zero(), .process = process->handle, .module = module->handle, .voff = rip_voff, .vaddr = rip_vaddr, .unwind_count = unwind_index, .inline_depth = inline_depth, .all_windows = 1); } // rjf: retry on stopped, pending debug info if(!d_ctrl_targets_running() && (dbgi_pending || missing_rip)) { find_thread_retry = thread->handle; } access_close(access); }break; case RD_CmdKind_FindSelectedThread: { CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread); rd_cmd(RD_CmdKind_FindThread, .thread = selected_thread->handle, .unwind_count = rd_base_regs()->unwind_count, .inline_depth = rd_base_regs()->inline_depth); }break; //- rjf: name finding case RD_CmdKind_GoToName: { String8 name = rd_regs()->string; if(name.size != 0) { B32 name_resolved = 0; // rjf: strip `s if(name.size >= 2 && name.str[0] == '`' && name.str[name.size-1] == '`') { name = str8_skip(str8_chop(name, 1), 1); } // rjf: try to resolve name as a symbol U64 voff = 0; DI_Key voff_dbgi_key = {0}; if(!name_resolved) { DI_Match match = {0}; if(match.idx == 0) { match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, rd_state->frame_eval_memread_endt_us); } if(match.idx == 0) { match = di_match_from_string(name, 0, di_key_zero(), rd_state->frame_eval_memread_endt_us); } if(match.section_kind == RDI_SectionKind_Procedures) { Access *access = access_open(); { name_resolved = 1; RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0); RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match.idx); voff = rdi_first_voff_from_procedure(rdi, procedure); voff_dbgi_key = match.key; } access_close(access); } } // rjf: try to resolve name as a file String8 file_path = {0}; if(!name_resolved) { // rjf: unpack quoted portion of string String8 file_part_of_name = name; U64 quote_pos = str8_find_needle(name, 0, str8_lit("\""), 0); if(quote_pos < name.size) { file_part_of_name = str8_skip(name, quote_pos+1); U64 ender_quote_pos = str8_find_needle(file_part_of_name, 0, str8_lit("\""), 0); file_part_of_name = str8_prefix(file_part_of_name, ender_quote_pos); } String8List search_parts = str8_split_path(scratch.arena, file_part_of_name); // rjf: get source path CFG_Node *src_view = cfg_node_from_id(rd_regs()->view); String8 src_view_expr = rd_expr_from_cfg(src_view); String8 src_file_path = rd_file_path_from_eval_string(scratch.arena, src_view_expr); String8List src_file_parts = str8_split_path(scratch.arena, src_file_path); // rjf: search for actual file Temp temp = temp_begin(scratch.arena); for(String8Node *n = src_file_parts.first; n != 0; n = n->next) { temp_end(temp); String8List try_path_parts = {0}; for(String8Node *src_n = src_file_parts.first; src_n != n && src_n != 0; src_n = src_n->next) { str8_list_push(temp.arena, &try_path_parts, src_n->string); } for(String8Node *try_n = search_parts.first; try_n != 0; try_n = try_n->next) { str8_list_push(temp.arena, &try_path_parts, try_n->string); } String8 try_path = str8_list_join(temp.arena, &try_path_parts, &(StringJoin){.sep = str8_lit("/")}); FileProperties try_props = os_properties_from_file_path(try_path); if(try_props.modified != 0) { name_resolved = 1; file_path = try_path; break; } } } // rjf: process resolved info if(!name_resolved) { log_user_errorf("`%S` could not be found.", name); } // rjf: name resolved to voff * dbg info if(name_resolved && voff != 0) { D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, voff_dbgi_key, voff); if(lines.first != 0) { CTRL_Entity *process = &ctrl_entity_nil; U64 vaddr = 0; CTRL_EntityList modules = ctrl_modules_from_dbgi_key(scratch.arena, &d_state->ctrl_entity_store->ctx, voff_dbgi_key); CTRL_Entity *module = ctrl_entity_list_first(&modules); process = ctrl_entity_ancestor_from_kind(module, CTRL_EntityKind_Process); if(process != &ctrl_entity_nil) { vaddr = module->vaddr_range.min + lines.first->v.voff_range.min; } rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = lines.first->v.file_path, .cursor = lines.first->v.pt, .process = process->handle, .module = module->handle, .vaddr = module->vaddr_range.min + lines.first->v.voff_range.min); } } // rjf: name resolved to a file path if(name_resolved && file_path.size != 0) { rd_cmd(RD_CmdKind_FindCodeLocation, .file_path = file_path, .cursor = txt_pt(1, 1), .vaddr = 0); } } }break; //- rjf: snap-to-code-location case RD_CmdKind_FindCodeLocation: { // NOTE(rjf): This command is where a lot of high-level flow things // in the debugger come together. It's that codepath that runs any // time a source code location is clicked in the UI, when a thread // is selected, or when a thread causes a halt (hitting a breakpoint // or exception or something). This is the logic that manages the // flow of how views and panels are changed, opened, etc. when // something like that happens. // // The gist of the intended rule for textual source code locations // is the following: // // 1. Try to find a panel that's viewing the file (has it open in a // tab, *and* that tab is selected). // 2. Try to find a panel that has the file open in a tab, but does not // currently have that tab selected. // 3. Try to find a panel that has ANY source code open in any tab. // 4. If the above things fail, try to pick the biggest panel, which // is generally a decent rule (because it matches the popular // debugger usage UI paradigm). // // The reason why this is a little more complicated than you might // imagine is because this debugger frontend does not have any special // "code panels" or anything like that, unlike e.g. VS or Remedy. All // panels are identical in nature to allow for the user to organize // the interface how they want, but in cases like this, we have to // "fish out" the best option given the user's configuration. This // can't be what the user wants in 100% of cases (this program cannot // read anyone's mind), but it does provide expected behavior in // common cases. // // The gist of the intended rule for finding disassembly locations is // the following: // // 1. Try to find a panel that's viewing disassembly already - if so, // snap it to the right address. // 2. If there is no disassembly tab open, then we need to open one // ONLY if source code was not found. // 3. If we need to open a disassembly tab, we will first try to pick // the biggest empty panel. // 4. If there is no empty panel, then we will pick the biggest // panel. //- rjf: grab things to find. path * point, process * address, etc. String8 file_path = {0}; TxtPt point = {0}; CTRL_Entity *thread = &ctrl_entity_nil; CTRL_Entity *process = &ctrl_entity_nil; U64 vaddr = 0; B32 require_disasm_snap = 0; B32 prefer_new_tab = 0; { file_path = rd_mapped_from_file_path(scratch.arena, rd_regs()->file_path); point = rd_regs()->cursor; thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); vaddr = rd_regs()->vaddr; prefer_new_tab = rd_regs()->prefer_new_tab; if(file_path.size == 0) { require_disasm_snap = 1; } } //- rjf: given a src code location, if no vaddr is specified, // try to map the src coordinates to a vaddr via line info if(vaddr == 0 && file_path.size != 0) { D_LineList lines = d_lines_from_file_path_line_num(scratch.arena, file_path, point.line); for(D_LineNode *n = lines.first; n != 0; n = n->next) { CTRL_EntityList modules = ctrl_modules_from_dbgi_key(scratch.arena, &d_state->ctrl_entity_store->ctx, n->v.dbgi_key); CTRL_Entity *module = ctrl_module_from_thread_candidates(&d_state->ctrl_entity_store->ctx, thread, &modules); vaddr = ctrl_vaddr_from_voff(module, n->v.voff_range.min); break; } } //- rjf: build task list for all windows we want to apply to typedef struct WindowTask WindowTask; struct WindowTask { WindowTask *next; CFG_Node *window; }; WindowTask start_window_task = {0, cfg_node_from_id(rd_regs()->window)}; WindowTask *first_window_task = &start_window_task; WindowTask *last_window_task = first_window_task; if(rd_regs()->all_windows) { for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { if(ws->cfg_id == rd_regs()->window) { continue; } WindowTask *t = push_array(scratch.arena, WindowTask, 1); SLLQueuePush(first_window_task, last_window_task, t); t->window = cfg_node_from_id(ws->cfg_id); } } //- rjf: for each window, determine how what it's viewing corresponds to the // location we need to be finding. typedef struct WindowInfo WindowInfo; struct WindowInfo { WindowInfo *next; CFG_Node *window; CFG_PanelTree panel_tree; CFG_PanelNode *panel_w_this_src_code; CFG_Node *view_w_this_src_code; CFG_PanelNode *panel_w_auto; CFG_Node *view_w_auto; CFG_PanelNode *panel_w_any_src_code; CFG_PanelNode *panel_w_disasm; CFG_Node *view_w_disasm; CFG_PanelNode *biggest_panel; CFG_PanelNode *biggest_empty_panel; }; WindowInfo *first_window_info = 0; WindowInfo *last_window_info = 0; for(WindowTask *t = first_window_task; t != 0; t = t->next) { CFG_Node *window = t->window; CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); WindowInfo *info = push_array(scratch.arena, WindowInfo, 1); SLLQueuePush(first_window_info, last_window_info, info); info->window = window; info->panel_tree = panel_tree; // rjf: first, try to find panel/view pair that already has the src file open info->panel_w_this_src_code = &cfg_nil_panel_node; info->view_w_this_src_code = &cfg_nil_node; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } String8 tab_expr = rd_expr_from_cfg(tab); String8 tab_file_path = rd_file_path_from_eval_string(scratch.arena, tab_expr); if((str8_match(tab->string, str8_lit("text"), 0) || str8_match(tab->string, str8_lit("pending"), 0)) && path_match_normalized(tab_file_path, file_path)) { info->panel_w_this_src_code = panel; info->view_w_this_src_code = tab; if(tab == panel->selected_tab) { break; } } } } // rjf: try to find panel/view pair that has any *auto* source code tab open info->panel_w_auto = &cfg_nil_panel_node; info->view_w_auto = &cfg_nil_node; if(!prefer_new_tab) { for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } RD_RegsScope(.tab = tab->id, .view = tab->id) { if(str8_match(tab->string, str8_lit("text"), 0) && rd_view_setting_b32_from_name(str8_lit("auto"))) { info->panel_w_auto = panel; info->view_w_auto = tab; } } } } } // rjf: find a panel that already has *any* code open (prioritize largest) info->panel_w_any_src_code = &cfg_nil_panel_node; { Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); F32 best_panel_area = 0; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } Rng2F32 panel_rect = cfg_target_rect_from_panel_node(root_rect, panel_tree.root, panel); Vec2F32 panel_rect_dim = dim_2f32(panel_rect); F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } String8 view_expr = rd_expr_from_cfg(tab); String8 file_path = rd_file_path_from_eval_string(scratch.arena, view_expr); if(str8_match(tab->string, str8_lit("text"), 0) && file_path.size != 0 && panel_area > best_panel_area) { info->panel_w_any_src_code = panel; best_panel_area = panel_area; break; } } } } // rjf: try to find panel/view pair that has disassembly open (prioritize largest) info->panel_w_disasm = &cfg_nil_panel_node; info->view_w_disasm = &cfg_nil_node; { Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); F32 best_panel_area = 0; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } Rng2F32 panel_rect = cfg_target_rect_from_panel_node(root_rect, panel_tree.root, panel); Vec2F32 panel_rect_dim = dim_2f32(panel_rect); F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } RD_RegsScope(.view = tab->id, .tab = tab->id) { B32 tab_is_selected = (tab == panel->selected_tab); String8 expr_string = rd_expr_from_cfg(tab); if(str8_match(tab->string, str8_lit("disasm"), 0) && expr_string.size == 0 && panel_area > best_panel_area) { info->panel_w_disasm = panel; info->view_w_disasm = tab; best_panel_area = panel_area; if(tab_is_selected) { break; } } } } } } // rjf: find the biggest panel info->biggest_panel = &cfg_nil_panel_node; { Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); F32 best_panel_area = 0; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } Rng2F32 panel_rect = cfg_target_rect_from_panel_node(root_rect, panel_tree.root, panel); Vec2F32 panel_rect_dim = dim_2f32(panel_rect); F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; if((best_panel_area == 0 || panel_area > best_panel_area)) { best_panel_area = panel_area; info->biggest_panel = panel; } } } // rjf: find the biggest empty panel info->biggest_empty_panel = &cfg_nil_panel_node; { Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); F32 best_panel_area = 0; for(CFG_PanelNode *panel = panel_tree.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { if(panel->first != &cfg_nil_panel_node) { continue; } Rng2F32 panel_rect = cfg_target_rect_from_panel_node(root_rect, panel_tree.root, panel); Vec2F32 panel_rect_dim = dim_2f32(panel_rect); F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; B32 panel_is_empty = 1; for(CFG_NodePtrNode *n = panel->tabs.first; n != 0; n = n->next) { CFG_Node *tab = n->v; if(!rd_cfg_is_project_filtered(tab)) { panel_is_empty = 0; break; } } if(panel_is_empty && (best_panel_area == 0 || panel_area > best_panel_area)) { best_panel_area = panel_area; info->biggest_empty_panel = panel; } } } } //- rjf: build find-code-location tasks for windows which we *definitely* want // to snap - in other words, windows with the destination things focused. typedef struct FindCodeLocTask FindCodeLocTask; struct FindCodeLocTask { FindCodeLocTask *next; CFG_Node *window; CFG_PanelNode *src_code_dst_panel; CFG_PanelNode *disasm_dst_panel; CFG_PanelNode *panel_w_this_src_code; CFG_Node *view_w_this_src_code; CFG_PanelNode *panel_w_auto; CFG_Node *view_w_auto; CFG_PanelNode *panel_w_disasm; CFG_Node *view_w_disasm; }; FindCodeLocTask *first_task = 0; FindCodeLocTask *last_task = 0; B32 did_src_code_snap = 0; B32 did_disasm_snap = 0; for(WindowInfo *info = first_window_info; info != 0; info = info->next) { // rjf: choose panel for source code CFG_PanelNode *src_code_dst_panel = &cfg_nil_panel_node; if(file_path.size != 0 && info->panel_w_this_src_code->selected_tab == info->view_w_this_src_code) { src_code_dst_panel = info->panel_w_this_src_code; } // rjf: choose panel for disassembly CFG_PanelNode *disasm_dst_panel = &cfg_nil_panel_node; if(vaddr != 0 && info->panel_w_disasm->selected_tab == info->view_w_disasm) { disasm_dst_panel = info->panel_w_disasm; } // rjf: push task if(src_code_dst_panel != &cfg_nil_panel_node || disasm_dst_panel != &cfg_nil_panel_node) { FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); SLLQueuePush(first_task, last_task, t); t->window = info->window; t->src_code_dst_panel = src_code_dst_panel; t->disasm_dst_panel = disasm_dst_panel; t->panel_w_this_src_code= info->panel_w_this_src_code; t->view_w_this_src_code = info->view_w_this_src_code; t->panel_w_auto = info->panel_w_auto; t->view_w_auto = info->view_w_auto; t->panel_w_disasm = info->panel_w_disasm; t->view_w_disasm = info->view_w_disasm; if(src_code_dst_panel != &cfg_nil_panel_node) { did_src_code_snap = 1; } if(disasm_dst_panel != &cfg_nil_panel_node) { did_disasm_snap = 1; } } } //- rjf: fallback: build find-code-location tasks for windows which have the // right things, but they're not focused. for(WindowInfo *info = first_window_info; info != 0; info = info->next) { // rjf: choose panel for source code CFG_PanelNode *src_code_dst_panel = &cfg_nil_panel_node; if(!did_src_code_snap && file_path.size != 0) { if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_this_src_code; } if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } } // rjf: choose panel for disassembly CFG_PanelNode *disasm_dst_panel = &cfg_nil_panel_node; if(!did_disasm_snap && vaddr != 0) { if(disasm_dst_panel == &cfg_nil_panel_node) { disasm_dst_panel = info->panel_w_disasm; } } // rjf: push task if(src_code_dst_panel != &cfg_nil_panel_node || disasm_dst_panel != &cfg_nil_panel_node) { FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); SLLQueuePush(first_task, last_task, t); t->window = info->window; t->src_code_dst_panel = src_code_dst_panel; t->disasm_dst_panel = disasm_dst_panel; t->panel_w_this_src_code= info->panel_w_this_src_code; t->view_w_this_src_code = info->view_w_this_src_code; t->panel_w_auto = info->panel_w_auto; t->view_w_auto = info->view_w_auto; t->panel_w_disasm = info->panel_w_disasm; t->view_w_disasm = info->view_w_disasm; if(src_code_dst_panel != &cfg_nil_panel_node) { did_src_code_snap = 1; } if(disasm_dst_panel != &cfg_nil_panel_node) { did_disasm_snap = 1; } } } //- rjf: fallback: build find-code-location tasks for windows w/ auto tabs for(WindowInfo *info = first_window_info; info != 0; info = info->next) { // rjf: choose panel for source code CFG_PanelNode *src_code_dst_panel = &cfg_nil_panel_node; if(!did_src_code_snap && file_path.size != 0) { if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } } // rjf: push task if(src_code_dst_panel != &cfg_nil_panel_node) { FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); SLLQueuePush(first_task, last_task, t); t->window = info->window; t->src_code_dst_panel = src_code_dst_panel; t->disasm_dst_panel = &cfg_nil_panel_node; t->panel_w_this_src_code= info->panel_w_this_src_code; t->view_w_this_src_code = info->view_w_this_src_code; t->panel_w_auto = info->panel_w_auto; t->view_w_auto = info->view_w_auto; t->panel_w_disasm = info->panel_w_disasm; t->view_w_disasm = info->view_w_disasm; if(src_code_dst_panel != &cfg_nil_panel_node) { did_src_code_snap = 1; } } } //- rjf: fallback: build find-code-location tasks for windows which did not // have the right things at all, but have reasonable candidate panels for // snapping. for(WindowInfo *info = first_window_info; info != 0; info = info->next) { // rjf: choose panel for source code CFG_PanelNode *src_code_dst_panel = &cfg_nil_panel_node; if(!did_src_code_snap && file_path.size != 0) { if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_this_src_code; } if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->panel_w_any_src_code; } if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->biggest_empty_panel; } if(src_code_dst_panel == &cfg_nil_panel_node) { src_code_dst_panel = info->biggest_panel; } } // rjf: choose panel for disassembly CFG_PanelNode *disasm_dst_panel = &cfg_nil_panel_node; if(!did_disasm_snap && vaddr != 0) { if(disasm_dst_panel == &cfg_nil_panel_node) { disasm_dst_panel = info->panel_w_disasm; } if(disasm_dst_panel == &cfg_nil_panel_node) { disasm_dst_panel = info->biggest_empty_panel; } if(disasm_dst_panel == &cfg_nil_panel_node) { disasm_dst_panel = info->biggest_panel; } } // rjf: push task if(src_code_dst_panel != &cfg_nil_panel_node || disasm_dst_panel != &cfg_nil_panel_node) { FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); SLLQueuePush(first_task, last_task, t); t->window = info->window; t->src_code_dst_panel = src_code_dst_panel; t->disasm_dst_panel = disasm_dst_panel; t->panel_w_this_src_code= info->panel_w_this_src_code; t->view_w_this_src_code = info->view_w_this_src_code; t->panel_w_auto = info->panel_w_auto; t->view_w_auto = info->view_w_auto; t->panel_w_disasm = info->panel_w_disasm; t->view_w_disasm = info->view_w_disasm; } } //- rjf: perform the find-code-location for each task for(FindCodeLocTask *t = first_task; t != 0; t = t->next) { CFG_PanelNode *src_code_dst_panel = t->src_code_dst_panel; CFG_PanelNode *disasm_dst_panel = t->disasm_dst_panel; // rjf: if disasm and source code match: // if disasm preferred, cancel source // if source preferred, cancel disasm if(disasm_dst_panel == src_code_dst_panel) { if(rd_regs()->prefer_disasm) { src_code_dst_panel = &cfg_nil_panel_node; } else { disasm_dst_panel = &cfg_nil_panel_node; } } // rjf: if disasm is not preferred, and we have no disassembly view // open at all, cancel disasm, so that it doesn't open if the user // doesn't want it. if(!rd_regs()->prefer_disasm && t->panel_w_disasm == &cfg_nil_panel_node && file_path.size != 0) { disasm_dst_panel = &cfg_nil_panel_node; } // rjf: if disasm is not preferred, and we have no disassembly view // *selected* at all, cancel disasm, so that it doesn't open if the user // doesn't want it. if(!rd_regs()->prefer_disasm && t->view_w_disasm != &cfg_nil_node && cfg_node_child_from_string(t->view_w_disasm, str8_lit("selected")) == &cfg_nil_node && file_path.size != 0) { disasm_dst_panel = &cfg_nil_panel_node; } // rjf: snap to source code if(file_path.size != 0 && src_code_dst_panel != &cfg_nil_panel_node) { CFG_PanelNode *dst_panel = src_code_dst_panel; // rjf: construct new view if needed CFG_Node *dst_tab = t->view_w_this_src_code; if(dst_tab == &cfg_nil_node && dst_panel == t->panel_w_auto && t->view_w_auto != &cfg_nil_node) { dst_tab = t->view_w_auto; RD_ViewState *vs = rd_view_state_from_cfg(dst_tab); vs->last_frame_index_built = 0; CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, dst_tab, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, rd_eval_string_from_file_path(scratch.arena, file_path)); cfg_node_new_replace(rd_state->cfg, cfg_node_child_from_string_or_alloc(rd_state->cfg, dst_tab, str8_lit("cursor_line")), str8_lit("1")); cfg_node_new_replace(rd_state->cfg, cfg_node_child_from_string_or_alloc(rd_state->cfg, dst_tab, str8_lit("cursor_column")), str8_lit("1")); cfg_node_new_replace(rd_state->cfg, cfg_node_child_from_string_or_alloc(rd_state->cfg, dst_tab, str8_lit("mark_line")), str8_lit("1")); cfg_node_new_replace(rd_state->cfg, cfg_node_child_from_string_or_alloc(rd_state->cfg, dst_tab, str8_lit("mark_column")), str8_lit("1")); } else if(dst_panel != &cfg_nil_panel_node && dst_tab == &cfg_nil_node) { dst_tab = cfg_node_new(rd_state->cfg, dst_panel->cfg, str8_lit("text")); CFG_Node *expr = cfg_node_new(rd_state->cfg, dst_tab, str8_lit("expression")); cfg_node_new(rd_state->cfg, expr, rd_eval_string_from_file_path(scratch.arena, file_path)); if(!prefer_new_tab) { CFG_Node *auto_root = cfg_node_new(rd_state->cfg, dst_tab, str8_lit("auto")); cfg_node_new(rd_state->cfg, auto_root, str8_lit("1")); } } // rjf: determine if we need a contain or center RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; if(dst_panel != &cfg_nil_panel_node && dst_tab == t->view_w_this_src_code && dst_panel->selected_tab == dst_tab) { cursor_snap_kind = RD_CmdKind_ContainCursor; } // rjf: move cursor & snap-to-cursor if(dst_panel != &cfg_nil_panel_node) RD_RegsScope(.window = t->window->id, .panel = dst_panel->cfg->id, .view = dst_tab->id, .tab = dst_tab->id) { if(rd_regs()->force_focus) { rd_cmd(RD_CmdKind_FocusPanel); } rd_cmd(RD_CmdKind_FocusTab); if(point.line != 0) { rd_cmd(RD_CmdKind_GoToLine, .cursor = point); } rd_cmd(cursor_snap_kind); } // rjf: record rd_cmd(RD_CmdKind_RecordFileInProject, .file_path = file_path); } // rjf: snap to disasm if(process != &ctrl_entity_nil && vaddr != 0 && disasm_dst_panel != &cfg_nil_panel_node) { CFG_PanelNode *dst_panel = disasm_dst_panel; // rjf: construct new tab if needed CFG_Node *dst_tab = t->view_w_disasm; if(dst_panel != &cfg_nil_panel_node && t->view_w_disasm == &cfg_nil_node) { dst_tab = cfg_node_new(rd_state->cfg, dst_panel->cfg, str8_lit("disasm")); } // rjf: determine if we need a contain or center RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; if(dst_tab == t->view_w_disasm && dst_panel->selected_tab == dst_tab) { cursor_snap_kind = RD_CmdKind_ContainCursor; } // rjf: move cursor & snap-to-cursor if(dst_panel != &cfg_nil_panel_node) RD_RegsScope(.window = t->window->id, .panel = dst_panel->cfg->id, .tab = dst_tab->id, .view = dst_tab->id) { rd_cmd(RD_CmdKind_FocusTab); rd_cmd(RD_CmdKind_GoToAddress, .process = process->handle, .vaddr = vaddr); rd_cmd(cursor_snap_kind); } } } }break; //- rjf: queries case RD_CmdKind_PushQuery: { String8 cmd_name = rd_regs()->cmd_name; RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); // rjf: close existing context menus { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); ui_ctx_menu_close(); ws->menu_bar_focused = 0; } // rjf: floating queries -> set up window to build immediate-mode top-level query CFG_Node *view = &cfg_nil_node; B32 is_floating = (cmd_name.size == 0 || cmd_kind_info->query.flags & RD_QueryFlag_Floating); if(is_floating) { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); if(ws != &rd_nil_window_state) { ws->query_is_active = 1; arena_clear(ws->query_arena); ws->query_regs = rd_regs_copy(ws->query_arena, rd_regs()); } CFG_Node *window_query = rd_immediate_cfg_from_keyf("window_query_%p", window); cfg_node_release_all_children(rd_state->cfg, window_query); view = cfg_node_child_from_string_or_alloc(rd_state->cfg, window_query, str8_lit("watch")); CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, rd_regs()->expr); } // rjf: non-floating -> embed in view else { view = cfg_node_from_id(rd_regs()->view); } // rjf: determine if the target view is a lister (and thus already has a command) B32 view_is_lister = (cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node); // rjf: target view is a lister -> do not do anything - cannot replace the command if(!view_is_lister) { // rjf: unpack view's query info CFG_Node *query = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("query")); CFG_Node *cmd = cfg_node_child_from_string_or_alloc(rd_state->cfg, query, str8_lit("cmd")); CFG_Node *input = cfg_node_child_from_string_or_alloc(rd_state->cfg, query, str8_lit("input")); if(is_floating) { if(rd_regs()->do_implicit_root) { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(view, str8_lit("explicit_root"))); } else { cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("explicit_root")); } if(!rd_regs()->do_lister) { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(view, str8_lit("lister"))); } else { cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("lister")); } } // rjf: choose initial input string String8 initial_input = {0}; if(cmd_name.size != 0) { if(cmd_kind_info->query.slot == RD_RegSlot_FilePath) { CFG_Node *user = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); CFG_Node *current_path = cfg_node_child_from_string(user, str8_lit("current_path")); String8 current_path_string = current_path->first->string; if(current_path_string.size == 0) { current_path_string = path_normalized_from_string(scratch.arena, os_get_current_path(scratch.arena)); } initial_input = current_path_string; initial_input = push_str8f(scratch.arena, "%S/", initial_input); } else if(cmd_kind_info->query.flags & RD_QueryFlag_KeepOldInput) { initial_input = input->first->string; } } // rjf: build query state String8 current_query_cmd_name = cmd->first->string; cfg_node_new_replace(rd_state->cfg, input, initial_input); cfg_node_new_replace(rd_state->cfg, cmd, cmd_name); RD_ViewState *vs = rd_view_state_from_cfg(view); if(cmd_name.size != 0) { if(!vs->query_is_open && cmd_kind_info->query.flags & RD_QueryFlag_SelectOldInput) { vs->query_cursor = txt_pt(1, 1+input->first->string.size); vs->query_mark = txt_pt(1, 1); } else { vs->query_cursor = txt_pt(1, 1+input->first->string.size); vs->query_mark = vs->query_cursor; } if(!str8_match(current_query_cmd_name, cmd_name, 0)) { vs->query_is_open = 1; } else { vs->query_is_open ^= 1; } } if(rd_regs()->do_lister) { vs->query_is_open = 1; } vs->contents_are_focused = 0; } }break; case RD_CmdKind_CompleteQuery: { // rjf: unpack params CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); CFG_Node *view = cfg_node_from_id(rd_regs()->view); String8 cmd_name = rd_view_query_cmd(); // rjf: find out if this view is a lister B32 is_lister = (cfg_node_child_from_string(view, str8_lit("lister")) != &cfg_nil_node); // rjf: push command if(cmd_name.size != 0) RD_RegsScope() { if(is_lister) { rd_regs()->view = ws->query_regs->view; } rd_push_cmd(cmd_name, rd_regs()); } // rjf: complete query, either by closing the query popup, or closing the // tab-embedded query edit RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); if(is_lister) { ws->query_is_active = 0; } else if(!(cmd_kind_info->query.flags & RD_QueryFlag_KeepOldInput)) { RD_ViewState *vs = rd_view_state_from_cfg(view); vs->query_is_open = 0; vs->query_string_size = 0; } }break; case RD_CmdKind_CancelQuery: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); if(ws != &rd_nil_window_state) { ws->query_is_active = 0; arena_clear(ws->query_arena); ws->query_regs = 0; } }break; case RD_CmdKind_UpdateQuery: { CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *query = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("query")); CFG_Node *input = cfg_node_child_from_string_or_alloc(rd_state->cfg, query, str8_lit("input")); cfg_node_new_replace(rd_state->cfg, input, rd_regs()->string); RD_ViewState *vs = rd_view_state_from_cfg(view); vs->query_cursor = vs->query_mark = txt_pt(1, rd_regs()->string.size+1); vs->query_string_size = Min(sizeof(vs->query_buffer), rd_regs()->string.size); MemoryCopy(vs->query_buffer, rd_regs()->string.str, vs->query_string_size); }break; //- rjf: event buffers case RD_CmdKind_OpenEventBuffer: { CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient")); CFG_Node *buffer = cfg_node_new(rd_state->cfg, transient, str8_lit("event_buffer")); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", buffer->id); }break; //- rjf: developer commands case RD_CmdKind_ToggleDevMenu: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); ws->dev_menu_is_open ^= 1; }break; //- rjf: general entity operations case RD_CmdKind_SelectCfg: case RD_CmdKind_SelectTarget: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); CFG_NodePtrList all_of_the_same_kind = cfg_node_top_level_list_from_string(scratch.arena, cfg->string); B32 is_selected = !rd_disabled_from_cfg(cfg); for(CFG_NodePtrNode *n = all_of_the_same_kind.first; n != 0; n = n->next) { CFG_Node *c = n->v; cfg_node_release(rd_state->cfg, cfg_node_child_from_string(c, str8_lit("enabled"))); } CFG_Node *enabled_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("enabled")); cfg_node_new_replace(rd_state->cfg, enabled_root, str8_lit("1")); }break; case RD_CmdKind_EnableCfg: case RD_CmdKind_EnableBreakpoint: case RD_CmdKind_EnableTarget: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); CFG_Node *enabled_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("enabled")); cfg_node_new_replacef(rd_state->cfg, enabled_root, "1"); }break; case RD_CmdKind_DisableCfg: case RD_CmdKind_DisableBreakpoint: case RD_CmdKind_DisableTarget: case RD_CmdKind_DeselectCfg: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); CFG_Node *enabled_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("enabled")); cfg_node_new_replacef(rd_state->cfg, enabled_root, "0"); }break; case RD_CmdKind_RemoveCfg: case RD_CmdKind_RemoveBreakpoint: case RD_CmdKind_RemoveTarget: case RD_CmdKind_CloseEventBuffer: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); cfg_node_release(rd_state->cfg, cfg); }break; case RD_CmdKind_NameCfg: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); if(rd_regs()->string.size != 0) { CFG_Node *label = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("label")); cfg_node_new(rd_state->cfg, label, rd_regs()->string); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(cfg, str8_lit("label"))); } }break; case RD_CmdKind_ConditionCfg: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); if(rd_regs()->string.size != 0) { CFG_Node *cnd = cfg_node_child_from_string_or_alloc(rd_state->cfg, cfg, str8_lit("condition")); cfg_node_new(rd_state->cfg, cnd, rd_regs()->string); } else { cfg_node_release(rd_state->cfg, cfg_node_child_from_string(cfg, str8_lit("condition"))); } }break; case RD_CmdKind_DuplicateCfg: { CFG_Node *src = cfg_node_from_id(rd_regs()->cfg); CFG_Node *dst = cfg_node_deep_copy(rd_state->cfg, src); cfg_node_insert_child(rd_state->cfg, src->parent, src, dst); }break; case RD_CmdKind_RelocateCfg: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); // rjf: release old location info { CFG_Node *src_loc = cfg_node_child_from_string(cfg, str8_lit("source_location")); CFG_Node *addr_loc = cfg_node_child_from_string(cfg, str8_lit("address_location")); cfg_node_release(rd_state->cfg, src_loc); cfg_node_release(rd_state->cfg, addr_loc); } // rjf: attach new location info { String8 file_path = rd_regs()->file_path; TxtPt pt = rd_regs()->cursor; String8 expr_string = rd_regs()->expr; U64 vaddr = rd_regs()->vaddr; if(expr_string.size == 0 && vaddr != 0) { expr_string = push_str8f(scratch.arena, "0x%I64x", vaddr); } if(file_path.size != 0 && pt.line != 0) { CFG_Node *src_loc = cfg_node_new(rd_state->cfg, cfg, str8_lit("source_location")); cfg_node_newf(rd_state->cfg, src_loc, "%S:%I64d:%I64d", file_path, pt.line, pt.column); } else if(expr_string.size != 0) { CFG_Node *vaddr_loc = cfg_node_new(rd_state->cfg, cfg, str8_lit("address_location")); cfg_node_new(rd_state->cfg, vaddr_loc, expr_string); } } }break; case RD_CmdKind_SaveToProject: { CFG_Node *cfg = cfg_node_from_id(rd_regs()->cfg); cfg_node_unhook(rd_state->cfg, cfg->parent, cfg); CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); cfg_node_insert_child(rd_state->cfg, project, project->last, cfg); }break; //- rjf: breakpoints case RD_CmdKind_AddBreakpoint: case RD_CmdKind_ToggleBreakpoint: { String8 file_path = rd_regs()->file_path; TxtPt pt = rd_regs()->cursor; U64 vaddr = rd_regs()->vaddr; String8 expr = rd_regs()->expr; if(expr.size == 0 && vaddr != 0) { expr = push_str8f(scratch.arena, "0x%I64x", vaddr); } if(file_path.size != 0 || expr.size != 0) { B32 already_exists = 0; CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = bps.first; n != 0; n = n->next) { CFG_Node *bp = n->v; CFG_Node *cnd = cfg_node_child_from_string(bp, str8_lit("condition")); RD_Location loc = rd_location_from_cfg(bp); B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc.file_path, file_path) && loc.pt.line == pt.line); B32 loc_matches_expr = (expr.size != 0 && str8_match(expr, loc.expr, 0)); if((loc_matches_file_pt || loc_matches_expr) && cnd->first->string.size == 0) { if(kind == RD_CmdKind_ToggleBreakpoint) { cfg_node_release(rd_state->cfg, bp); } already_exists = 1; break; } } if(!already_exists) { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_Node *bp = cfg_node_new(rd_state->cfg, project, str8_lit("breakpoint")); rd_cmd(RD_CmdKind_RelocateCfg, .cfg = bp->id); if(rd_regs()->do_lister && !rd_regs()->non_graphical) { rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", bp->id), .do_lister = 0); } str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", bp->id); } } }break; case RD_CmdKind_AddAddressBreakpoint: { rd_cmd(RD_CmdKind_AddBreakpoint, .file_path = str8_zero(), .do_lister = 1); }break; case RD_CmdKind_AddFunctionBreakpoint: { rd_cmd(RD_CmdKind_AddBreakpoint, .file_path = str8_zero(), .expr = rd_regs()->string); }break; case RD_CmdKind_ClearBreakpoints: { CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = bps.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, n->v); } }break; case RD_CmdKind_ListBreakpoints: { CFG_NodePtrList list = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = list.first; n != 0; n = n->next) { String8 string = cfg_string_from_tree(rd_state->cmd_output_arena, rd_state->cfg_schema_table, str8_zero(), n->v); str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, string); } }break; //- rjf: output case RD_CmdKind_ClearOutput: { MTX_Op op = {r1u64(0, 0xffffffffffffffffull), str8_lit("")}; mtx_push_op(d_state->output_log_key, op); }break; //- rjf: watch pins case RD_CmdKind_AddWatchPin: case RD_CmdKind_ToggleWatchPin: { String8 file_path = rd_regs()->file_path; TxtPt pt = rd_regs()->cursor; String8 expr_string = rd_regs()->expr; U64 vaddr = rd_regs()->vaddr; B32 removed_already_existing = 0; if(kind == RD_CmdKind_ToggleWatchPin) { CFG_NodePtrList wps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("watch_pin")); for(CFG_NodePtrNode *n = wps.first; n != 0; n = n->next) { CFG_Node *wp = n->v; CFG_Node *expr = cfg_node_child_from_string(wp, str8_lit("expression")); RD_Location loc = rd_location_from_cfg(wp); B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc.file_path, file_path) && loc.pt.line == pt.line); B32 loc_matches_expr = (expr_string.size != 0 && str8_match(expr_string, loc.expr, 0)); if((loc_matches_file_pt || loc_matches_expr) && str8_match(expr->first->string, expr_string, 0)) { cfg_node_release(rd_state->cfg, wp); removed_already_existing = 1; } } } if(!removed_already_existing) { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_Node *wp = cfg_node_new(rd_state->cfg, project, str8_lit("watch_pin")); CFG_Node *expr = cfg_node_new(rd_state->cfg, wp, str8_lit("expression")); cfg_node_new(rd_state->cfg, expr, expr_string); rd_cmd(RD_CmdKind_RelocateCfg, .cfg = wp->id, .expr = str8_zero()); } }break; //- rjf: debug infos case RD_CmdKind_LoadDebugInfo: { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info")); CFG_Node *path = cfg_node_new(rd_state->cfg, di, str8_lit("path")); cfg_node_new(rd_state->cfg, path, rd_regs()->file_path); }break; case RD_CmdKind_UnloadDebugInfo: { CFG_Node *di = cfg_node_from_id(rd_regs()->cfg); CFG_Node *path = cfg_node_child_from_string(di, str8_lit("path")); cfg_node_release(rd_state->cfg, di); }break; //- rjf: type views case RD_CmdKind_AddTypeView: { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); cfg_node_new(rd_state->cfg, project, str8_lit("type_view")); }break; //- rjf: file path maps case RD_CmdKind_AddFilePathMap: { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); cfg_node_new(rd_state->cfg, project, str8_lit("file_path_map")); }break; //- rjf: themes case RD_CmdKind_EditUserTheme: { CFG_Node *parent = cfg_node_child_from_string(cfg_node_root(), str8_lit("user")); rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x.theme_colors", parent->id)); }break; case RD_CmdKind_EditProjectTheme: { CFG_Node *parent = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x.theme_colors", parent->id)); }break; case RD_CmdKind_AddThemeColor: { Access *access = access_open(); CFG_Node *parent = cfg_node_from_id(rd_regs()->cfg); CFG_Node *theme = cfg_node_child_from_string_or_alloc(rd_state->cfg, parent, str8_lit("theme")); MD_Node *theme_tree = rd_theme_tree_from_name(scratch.arena, access, theme->first->string); if(theme_tree == &md_nil_node) { cfg_node_new_replace(rd_state->cfg, theme, rd_theme_preset_display_string_table[RD_ThemePreset_DefaultDark]); } CFG_Node *color = cfg_node_new(rd_state->cfg, parent, str8_lit("theme_color")); cfg_node_new(rd_state->cfg, color, str8_lit("tags")); CFG_Node *value = cfg_node_new(rd_state->cfg, color, str8_lit("value")); cfg_node_new(rd_state->cfg, value, str8_lit("0xffffffff")); access_close(access); }break; case RD_CmdKind_ForkTheme: { Access *access = access_open(); CFG_Node *parent = cfg_node_from_id(rd_regs()->cfg); CFG_NodePtrList colors = cfg_node_child_list_from_string(scratch.arena, parent, str8_lit("theme_color")); for(CFG_NodePtrNode *n = colors.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, n->v); } CFG_Node *theme_cfg = cfg_node_child_from_string(parent, str8_lit("theme")); String8 theme_name = theme_cfg->first->string; MD_Node *theme_tree = rd_theme_tree_from_name(scratch.arena, access, theme_name); if(theme_tree == &md_nil_node) { theme_tree = rd_state->theme_preset_trees[RD_ThemePreset_DefaultDark]; } for(MD_Node *n = theme_tree; !md_node_is_nil(n); n = md_node_rec_depth_first_pre(n, theme_tree).next) { if(str8_match(n->string, str8_lit("theme_color"), 0)) { CFG_Node *color = cfg_node_new(rd_state->cfg, parent, str8_lit("theme_color")); CFG_Node *tags = cfg_node_new(rd_state->cfg, color, str8_lit("tags")); CFG_Node *value = cfg_node_new(rd_state->cfg, color, str8_lit("value")); cfg_node_new(rd_state->cfg, tags, md_child_from_string(n, str8_lit("tags"), 0)->first->string); cfg_node_new(rd_state->cfg, value, md_child_from_string(n, str8_lit("value"), 0)->first->string); } } cfg_node_release(rd_state->cfg, theme_cfg); access_close(access); }break; case RD_CmdKind_SaveTheme: case RD_CmdKind_SaveAndSetTheme: { String8 name = rd_regs()->string; if(name.size != 0) { String8 themes_folder = push_str8f(scratch.arena, "%S/raddbg/themes", os_get_process_info()->user_program_data_path); if(os_make_directory(themes_folder)) { String8 dst_path = push_str8f(scratch.arena, "%S/%S", themes_folder, name); CFG_Node *parent = cfg_node_from_id(rd_regs()->cfg); CFG_NodePtrList colors = cfg_node_child_list_from_string(scratch.arena, parent, str8_lit("theme_color")); String8List strings = {0}; for(CFG_NodePtrNode *n = colors.first; n != 0; n = n->next) { str8_list_push(scratch.arena, &strings, cfg_string_from_tree(scratch.arena, rd_state->cfg_schema_table, str8_chop_last_slash(dst_path), n->v)); } String8 data = str8_list_join(scratch.arena, &strings, 0); if(os_write_data_to_file_path(dst_path, data)) { if(kind == RD_CmdKind_SaveAndSetTheme) { for(CFG_NodePtrNode *n = colors.first; n != 0; n = n->next) { cfg_node_release(rd_state->cfg, n->v); } CFG_Node *theme = cfg_node_child_from_string_or_alloc(rd_state->cfg, parent, str8_lit("theme")); cfg_node_new_replace(rd_state->cfg, theme, name); } } else { log_user_errorf("Could not successfully write to '%S'.", dst_path); } } } }break; //- rjf: watches case RD_CmdKind_ToggleWatchExpression: if(rd_regs()->string.size != 0) { // rjf: pick a watch tab from all the windows to toggle this expression within CFG_Node *watch_tab = &cfg_nil_node; { B32 watch_tab_has_no_label = 0; B32 watch_tab_matches_src_window = 0; CFG_NodePtrList windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); for(CFG_NodePtrNode *n = windows.first; n != 0; n = n->next) { CFG_Node *window = n->v; CFG_PanelTree panels = cfg_panel_tree_from_cfg(scratch.arena, window); for(CFG_PanelNode *panel = panels.root; panel != &cfg_nil_panel_node; panel = cfg_panel_node_rec__depth_first_pre(panels.root, panel).next) { for(CFG_NodePtrNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; CFG_Node *label = cfg_node_child_from_string(tab, str8_lit("label")); if(str8_match(tab->string, str8_lit("watch"), 0) && rd_expr_from_cfg(tab).size == 0) { B32 tab_has_no_label = (label->first->string.size == 0); B32 tab_matches_src_window = (window->id == rd_regs()->window); if(tab_has_no_label > watch_tab_has_no_label || tab_matches_src_window > watch_tab_matches_src_window || watch_tab == &cfg_nil_node) { watch_tab = tab; if(tab_has_no_label && tab_matches_src_window) { goto end_watch_tab_search; } } } } } } end_watch_tab_search:; } // rjf: find the existing watch in the selected tab, if it exists CFG_Node *existing_watch = &cfg_nil_node; for(CFG_Node *child = watch_tab->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("watch"), 0) && str8_match(child->first->string, rd_regs()->string, 0)) { existing_watch = child; break; } } // rjf: if this watch exists -> delete it if(existing_watch != &cfg_nil_node) { cfg_node_release(rd_state->cfg, existing_watch); } // rjf: otherwise, create it else if(watch_tab != &cfg_nil_node) { CFG_Node *watch = cfg_node_new(rd_state->cfg, watch_tab, str8_lit("watch")); cfg_node_new(rd_state->cfg, watch, rd_regs()->string); } }break; //- rjf: cursor operations case RD_CmdKind_GoToNameAtCursor: case RD_CmdKind_ToggleWatchExpressionAtCursor: { Access *access = access_open(); RD_Regs *regs = rd_regs(); C_Key text_key = regs->text_key; TXT_LangKind lang_kind = regs->lang_kind; TxtRng range = txt_rng(regs->cursor, regs->mark); U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(access, text_key, lang_kind, &hash); String8 data = c_data_from_hash(access, hash); Rng1U64 expr_off_range = {0}; if(range.min.column != range.max.column) { expr_off_range = r1u64(txt_off_from_info_pt(&info, range.min), txt_off_from_info_pt(&info, range.max)); } else { expr_off_range = txt_expr_off_range_from_info_data_pt(&info, data, range.min); } String8 expr = str8_substr(data, expr_off_range); rd_cmd((kind == RD_CmdKind_GoToNameAtCursor ? RD_CmdKind_GoToName : kind == RD_CmdKind_ToggleWatchExpressionAtCursor ? RD_CmdKind_ToggleWatchExpression : RD_CmdKind_GoToName), .string = expr); access_close(access); }break; case RD_CmdKind_SetNextStatement: { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); String8 file_path = rd_regs()->file_path; U64 new_rip_vaddr = rd_regs()->vaddr_range.min; if(file_path.size != 0) { D_LineList *lines = &rd_regs()->lines; for(D_LineNode *n = lines->first; n != 0; n = n->next) { CTRL_EntityList modules = ctrl_modules_from_dbgi_key(scratch.arena, &d_state->ctrl_entity_store->ctx, n->v.dbgi_key); CTRL_Entity *module = ctrl_module_from_thread_candidates(&d_state->ctrl_entity_store->ctx, thread, &modules); if(module != &ctrl_entity_nil) { new_rip_vaddr = ctrl_vaddr_from_voff(module, n->v.voff_range.min); break; } } } rd_cmd(RD_CmdKind_SetThreadIP, .vaddr = new_rip_vaddr); }break; //- rjf: targets case RD_CmdKind_AddTarget: { String8 file_path = rd_regs()->file_path; CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_Node *target = cfg_node_new(rd_state->cfg, project, str8_lit("target")); CFG_Node *exe = cfg_node_new(rd_state->cfg, target, str8_lit("executable")); cfg_node_new(rd_state->cfg, exe, file_path); String8 working_directory = str8_chop_last_slash(file_path); if(working_directory.size != 0) { CFG_Node *wdir = cfg_node_new(rd_state->cfg, target, str8_lit("working_directory")); cfg_node_newf(rd_state->cfg, wdir, "%S/", working_directory); } rd_cmd(RD_CmdKind_SelectTarget, .cfg = target->id); if(!rd_regs()->non_graphical) { rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", target->id)); } str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", target->id); }break; //- rjf: jit-debugger registration case RD_CmdKind_RegisterAsJITDebugger: { #if OS_WINDOWS char filename_cstr[MAX_PATH] = {0}; GetModuleFileName(0, filename_cstr, sizeof(filename_cstr)); String8 debugger_binary_path = str8_cstring(filename_cstr); String8 name8 = str8_lit("Debugger"); String8 data8 = push_str8f(scratch.arena, "%S --jit_pid:%%ld --jit_code:%%ld --jit_addr:0x%%p", debugger_binary_path); String16 name16 = str16_from_8(scratch.arena, name8); String16 data16 = str16_from_8(scratch.arena, data8); B32 likely_not_in_admin_mode = 0; { HKEY reg_key = 0; LSTATUS status = 0; status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\", 0, KEY_SET_VALUE, ®_key); likely_not_in_admin_mode = (status == ERROR_ACCESS_DENIED); status = RegSetValueExW(reg_key, (LPCWSTR)name16.str, 0, REG_SZ, (BYTE *)data16.str, data16.size*sizeof(U16)+2); RegCloseKey(reg_key); } { HKEY reg_key = 0; LSTATUS status = 0; status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\", 0, KEY_SET_VALUE, ®_key); likely_not_in_admin_mode = (status == ERROR_ACCESS_DENIED); status = RegSetValueExW(reg_key, (LPCWSTR)name16.str, 0, REG_SZ, (BYTE *)data16.str, data16.size*sizeof(U16)+2); RegCloseKey(reg_key); } if(likely_not_in_admin_mode) { log_user_error(str8_lit("Could not register as the just-in-time debugger, access was denied; try running the debugger as administrator.")); } #else log_user_error(str8_lit("Registering as the just-in-time debugger is currently not supported on this system.")); #endif }break; //- rjf: developer commands case RD_CmdKind_LogMarker: { log_infof("\"#MARKER\""); }break; //- rjf: os event passthrough case RD_CmdKind_OSEvent: { OS_Event *os_event = rd_regs()->os_event; RD_WindowState *ws = rd_window_state_from_os_handle(os_event->window); if(os_event != 0 && ws != &rd_nil_window_state) { UI_Event ui_event = zero_struct; UI_EventKind kind = UI_EventKind_Null; { switch(os_event->kind) { default:{}break; case OS_EventKind_Press: {kind = UI_EventKind_Press;}break; case OS_EventKind_Release: {kind = UI_EventKind_Release;}break; case OS_EventKind_MouseMove: {kind = UI_EventKind_MouseMove;}break; case OS_EventKind_Text: {kind = UI_EventKind_Text;}break; case OS_EventKind_Scroll: {kind = UI_EventKind_Scroll;}break; case OS_EventKind_FileDrop: {kind = UI_EventKind_FileDrop;}break; } } ui_event.kind = kind; ui_event.key = os_event->key; ui_event.modifiers = os_event->modifiers; ui_event.string = os_event->character ? str8_from_32(ui_build_arena(), str32(&os_event->character, 1)) : str8_zero(); ui_event.paths = str8_list_copy(ui_build_arena(), &os_event->strings); ui_event.pos = os_event->pos; ui_event.delta_2f32 = os_event->delta; ui_event.timestamp_us = os_event->timestamp_us; ui_event_list_push(scratch.arena, &ws->ui_events, &ui_event); } }break; //- rjf: debug control context management operations case RD_CmdKind_SelectEntity: { rd_cmd(RD_CmdKind_SelectThread, .thread = rd_regs()->ctrl_entity); }break; case RD_CmdKind_SelectThread: { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle)); CTRL_Entity *machine = ctrl_entity_ancestor_from_kind(process, CTRL_EntityKind_Machine); rd_state->base_regs.v.unwind_count = 0; rd_state->base_regs.v.inline_depth = 0; rd_state->base_regs.v.thread = thread->handle; rd_state->base_regs.v.module = module->handle; rd_state->base_regs.v.process = process->handle; rd_state->base_regs.v.machine = machine->handle; rd_cmd(RD_CmdKind_FindThread, .thread = thread->handle, .unwind_count = 0, .inline_depth = 0); }break; case RD_CmdKind_SelectUnwind: { Access *access = access_open(); CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, thread->handle, 1, os_now_microseconds()+10000); CTRL_CallStackFrame *frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth); if(frame == 0) { frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, 0); } if(frame) { rd_state->base_regs.v.unwind_count = rd_regs()->unwind_count; rd_state->base_regs.v.inline_depth = rd_regs()->inline_depth; } rd_cmd(RD_CmdKind_FindThread, .thread = thread->handle, .unwind_count = rd_state->base_regs.v.unwind_count, .inline_depth = rd_state->base_regs.v.inline_depth); access_close(access); }break; case RD_CmdKind_UpOneFrame: case RD_CmdKind_DownOneFrame: { Access *access = access_open(); CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, thread->handle, 1, os_now_microseconds()+10000); CTRL_CallStackFrame *current_frame = ctrl_call_stack_frame_from_unwind_and_inline_depth(&call_stack, rd_regs()->unwind_count, rd_regs()->inline_depth); CTRL_CallStackFrame *next_frame = current_frame; if(current_frame != 0) switch(kind) { default:{}break; case RD_CmdKind_UpOneFrame: if(current_frame > call_stack.frames) { next_frame = current_frame-1; }break; case RD_CmdKind_DownOneFrame: if(current_frame+1 < call_stack.frames + call_stack.frames_count) { next_frame = current_frame+1; }break; } if(next_frame != 0) { CTRL_CallStackFrame *next_base_frame = next_frame + next_frame->inline_depth; rd_cmd(RD_CmdKind_SelectUnwind, .unwind_count = next_frame->unwind_count, .inline_depth = next_frame->inline_depth); } access_close(access); }break; //- rjf: meta controls case RD_CmdKind_Edit: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Press; evt.slot = UI_EventActionSlot_Edit; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_Accept: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Press; evt.slot = UI_EventActionSlot_Accept; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_Cancel: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Press; evt.slot = UI_EventActionSlot_Cancel; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; //- rjf: directional movement & text controls // // NOTE(rjf): These all get funneled into a separate intermediate that // can be used by the UI build phase for navigation and stuff, as well // as builder codepaths that want to use these controls to modify text. // case RD_CmdKind_MoveLeft: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_PickSelectSide|UI_EventFlag_ZeroDeltaOnSelect|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveRight: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_PickSelectSide|UI_EventFlag_ZeroDeltaOnSelect|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUp: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDown: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveLeftSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveRightSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveLeftChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveRightChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_ExplicitDirectional|UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpPage: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Page; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownPage: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Page; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpWhole: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Whole; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownWhole: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Whole; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveLeftChunkSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveRightChunkSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpChunkSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownChunkSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark|UI_EventFlag_ExplicitDirectional; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpPageSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Page; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownPageSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Page; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpWholeSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Whole; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownWholeSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Whole; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveUpReorder: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Reorder; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveDownReorder: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Reorder; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveHome: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.delta_unit = UI_EventDeltaUnit_Line; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveEnd: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.delta_unit = UI_EventDeltaUnit_Line; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveHomeSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Line; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MoveEndSelect: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_KeepMark; evt.delta_unit = UI_EventDeltaUnit_Line; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_SelectAll: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt1 = zero_struct; evt1.kind = UI_EventKind_Navigate; evt1.delta_unit = UI_EventDeltaUnit_Whole; evt1.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt1); UI_Event evt2 = zero_struct; evt2.kind = UI_EventKind_Navigate; evt2.flags = UI_EventFlag_KeepMark; evt2.delta_unit = UI_EventDeltaUnit_Whole; evt2.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt2); }break; case RD_CmdKind_DeleteSingle: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Delete|UI_EventFlag_ZeroDeltaOnSelect; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_DeleteChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Delete|UI_EventFlag_ZeroDeltaOnSelect; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(+1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_BackspaceSingle: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Delete|UI_EventFlag_ZeroDeltaOnSelect; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_BackspaceChunk: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Delete|UI_EventFlag_ZeroDeltaOnSelect; evt.delta_unit = UI_EventDeltaUnit_Word; evt.delta_2s32 = v2s32(-1, +0); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_Copy: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Copy|UI_EventFlag_KeepMark; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_Cut: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Edit; evt.flags = UI_EventFlag_Copy|UI_EventFlag_Delete; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_Paste: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Text; evt.string = os_get_clipboard_text(scratch.arena); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_InsertText: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Text; evt.string = rd_regs()->string; ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; //- rjf: directionless navigation case RD_CmdKind_MoveNext: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, +1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; case RD_CmdKind_MovePrev: { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); UI_Event evt = zero_struct; evt.kind = UI_EventKind_Navigate; evt.flags = UI_EventFlag_Secondary; evt.delta_unit = UI_EventDeltaUnit_Char; evt.delta_2s32 = v2s32(+0, -1); ui_event_list_push(scratch.arena, &ws->ui_events, &evt); }break; } } } //////////////////////////// //- rjf: gather targets // D_TargetArray targets = {0}; ProfScope("gather targets") { CFG_NodePtrList target_cfgs = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("target")); targets.count = target_cfgs.count; targets.v = push_array(scratch.arena, D_Target, targets.count); U64 idx = 0; for(CFG_NodePtrNode *n = target_cfgs.first; n != 0; n = n->next) { CFG_Node *src = n->v; B32 src_is_disabled = rd_disabled_from_cfg(src); if(src_is_disabled) { targets.count -= 1; continue; } targets.v[idx] = rd_target_from_cfg(scratch.arena, src); idx += 1; } } //////////////////////////// //- rjf: gather breakpoints & meta-evals (for the engine, meta-evals can only be referenced by breakpoints) // D_BreakpointArray breakpoints = {0}; ProfScope("gather breakpoints & meta-evals") { CFG_NodePtrList bp_cfgs = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); breakpoints.count = bp_cfgs.count; breakpoints.v = push_array(scratch.arena, D_Breakpoint, breakpoints.count); U64 idx = 0; for(CFG_NodePtrNode *n = bp_cfgs.first; n != 0; n = n->next) { CFG_Node *src_bp = n->v; B32 src_bp_is_disabled = rd_disabled_from_cfg(src_bp); if(src_bp_is_disabled) { breakpoints.count -= 1; continue; } RD_Location src_bp_loc = rd_location_from_cfg(src_bp); String8 src_bp_cnd = cfg_node_child_from_string(src_bp, str8_lit("condition"))->first->string; //- rjf: walk conditional breakpoint expression tree - for each leaf identifier, // determine if it resolves to a meta-evaluation. if it does, compute the meta // evaluation data & store. // // for many conditions, we can statically-disqualify the breakpoint, if it only // references frontend-controlled meta-evaluation state. in such cases, we just // want to never send the user breakpoint to the control thread, since it cannot // be hit anyways. so in this pass, we can also gather information about whether // or not it is 'static', w.r.t. the control thread. // B32 is_static_for_ctrl_thread = 0; if(src_bp_cnd.size != 0) { typedef struct ExprWalkTask ExprWalkTask; struct ExprWalkTask { ExprWalkTask *next; E_Expr *expr; }; E_Expr *expr = e_parse_from_string(src_bp_cnd).expr; ExprWalkTask start_task = {0, expr}; ExprWalkTask *first_task = &start_task; for(ExprWalkTask *t = first_task; t != 0; t = t->next) { if(t->expr->kind == E_ExprKind_LeafIdentifier) { E_Expr *macro_expr = e_string2expr_map_lookup(e_ir_ctx->macro_map, t->expr->string); E_Eval eval = e_eval_from_string(t->expr->string); if(eval.msgs.max_kind == E_MsgKind_Null) { switch(eval.space.kind) { default:{is_static_for_ctrl_thread = 0;}break; case E_SpaceKind_Null: case RD_EvalSpaceKind_MetaCfg: { is_static_for_ctrl_thread = 1; }break; } } } for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next) { ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1); task->expr = child; task->next = t->next; t->next = task; } } } //- rjf: if this breakpoint is conditioned & static for the control thread, then // we can evaluate this condition early, and decide whether or not to send this // breakpoint. B32 is_statically_disqualified = 0; String8 non_ctrl_thread_static_condition = src_bp_cnd; if(is_static_for_ctrl_thread) { E_Eval eval = e_eval_from_string(src_bp_cnd); E_Eval value_eval = e_value_eval_from_eval(eval); if(value_eval.value.u64 == 0) { is_statically_disqualified = 1; } MemoryZeroStruct(&non_ctrl_thread_static_condition); } //- rjf: statically disqualified? -> skip if(is_statically_disqualified) { breakpoints.count -= 1; continue; } //- rjf: compute breakpoint flags D_BreakpointFlags flags = 0; if(str8_match(cfg_node_child_from_string(src_bp, str8_lit("break_on_write"))->first->string, str8_lit("1"), 0)) { flags |= D_BreakpointFlag_BreakOnWrite; } if(str8_match(cfg_node_child_from_string(src_bp, str8_lit("break_on_read"))->first->string, str8_lit("1"), 0)) { flags |= D_BreakpointFlag_BreakOnRead; } if(str8_match(cfg_node_child_from_string(src_bp, str8_lit("break_on_execute"))->first->string, str8_lit("1"), 0)) { flags |= D_BreakpointFlag_BreakOnExecute; } //- rjf: compute address range size U64 addr_range_size = 0; { CFG_Node *address_range_size_cfg = cfg_node_child_from_string(src_bp, str8_lit("address_range_size")); try_u64_from_str8_c_rules(address_range_size_cfg->first->string, &addr_range_size); } //- rjf: fill breakpoint D_Breakpoint *dst_bp = &breakpoints.v[idx]; dst_bp->flags = flags; dst_bp->id = src_bp->id; dst_bp->file_path = src_bp_loc.file_path; dst_bp->pt = src_bp_loc.pt; dst_bp->vaddr_expr = src_bp_loc.expr; dst_bp->condition = non_ctrl_thread_static_condition; dst_bp->size = addr_range_size; idx += 1; } } //////////////////////////// //- rjf: gather path maps // D_PathMapArray path_maps = {0}; { CFG_NodePtrList maps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("file_path_map")); path_maps.count = maps.count; path_maps.v = push_array(scratch.arena, D_PathMap, path_maps.count); U64 idx = 0; for(CFG_NodePtrNode *n = maps.first; n != 0; n = n->next, idx += 1) { CFG_Node *map = n->v; path_maps.v[idx].src = cfg_node_child_from_string(map, str8_lit("source"))->first->string; path_maps.v[idx].dst = cfg_node_child_from_string(map, str8_lit("dest"))->first->string; } } //////////////////////////// //- rjf: gather exception code filters // U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64] = {0}; { for EachNonZeroEnumVal(CTRL_ExceptionCodeKind, k) { String8 name = ctrl_exception_code_kind_lowercase_code_string_table[k]; B32 setting = rd_setting_b32_from_name(name); if(setting) { exception_code_filters[k/64] |= 1ull<<(k%64); } } } //////////////////////////// //- rjf: tick debug engine // U64 cmd_count_pre_tick = rd_state->cmds[0].count; D_EventList engine_events = d_tick(scratch.arena, &targets, &breakpoints, &path_maps, exception_code_filters); //////////////////////////// //- rjf: process debug engine events // for(D_EventNode *n = engine_events.first; n != 0; n = n->next) { D_Event *evt = &n->v; switch(evt->kind) { default:{}break; case D_EventKind_ModuleLoad: { CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, evt->module); CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); String8 new_path = debug_info_path->string; if(new_path.size != 0 && os_file_path_exists(new_path)) { CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info")); B32 path_found = 0; CFG_Node *found_di = &cfg_nil_node; for EachNode(n, CFG_NodePtrNode, dbg_infos.first) { CFG_Node *di = n->v; String8 path = rd_path_from_cfg(di); if(str8_match(path, new_path, 0)) { path_found = 1; found_di = di; break; } } if(!path_found) { CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project")); CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info")); CFG_Node *path_root = cfg_node_new(rd_state->cfg, di, str8_lit("path")); CFG_Node *timestamp_root = cfg_node_new(rd_state->cfg, di, str8_lit("timestamp")); cfg_node_new(rd_state->cfg, path_root, new_path); cfg_node_newf(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp); } else { CFG_Node *timestamp_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, found_di, str8_lit("timestamp")); cfg_node_new_replacef(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp); } } }break; case D_EventKind_ProcessEnd: if(rd_state->quit_after_success) { CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(evt->code == 0 && processes.count == 0) { rd_cmd(RD_CmdKind_Exit); } else if(evt->code != 0) { rd_state->quit_after_success = 0; } }break; case D_EventKind_Stop: { B32 need_refocus = (evt->cause != D_EventCause_SoftHalt); CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, evt->thread); U64 vaddr = evt->vaddr; CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); U64 voff = ctrl_voff_from_vaddr(module, vaddr); U64 test_cached_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle); // rjf: valid stop thread? -> select & snap if(need_refocus && thread != &ctrl_entity_nil && evt->cause != D_EventCause_Halt) { rd_cmd(RD_CmdKind_SelectThread, .thread = thread->handle); } // rjf: no stop-causing thread, but have selected thread? -> snap to selected CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread); if(need_refocus && (evt->cause == D_EventCause_Halt || thread == &ctrl_entity_nil) && selected_thread != &ctrl_entity_nil) { rd_cmd(RD_CmdKind_SelectThread, .thread = selected_thread->handle); } // rjf: no stop-causing thread, but don't have selected thread? -> snap to first available thread if(need_refocus && thread == &ctrl_entity_nil && selected_thread == &ctrl_entity_nil) { CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread); CTRL_Entity *first_available_thread = ctrl_entity_array_first(&threads); rd_cmd(RD_CmdKind_SelectThread, .thread = first_available_thread->handle); } // rjf: increment breakpoint hit counts if(evt->cause == D_EventCause_UserBreakpoint) { CFG_Node *bp = cfg_node_from_id(evt->id); if(bp != &cfg_nil_node) { CFG_Node *hit_count_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, bp, str8_lit("hit_count")); U64 hit_count = 0; try_u64_from_str8_c_rules(hit_count_root->first->string, &hit_count); hit_count += 1; cfg_node_new_replacef(rd_state->cfg, hit_count_root, "%I64u", hit_count); } } // rjf: focus window if none focused, and if we have a thread to snap to if(need_refocus && (selected_thread != &ctrl_entity_nil || thread != &ctrl_entity_nil)) { B32 any_window_is_focused = 0; for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { if(os_window_is_focused(ws->os)) { any_window_is_focused = 1; break; } } if(!any_window_is_focused) { CFG_Node *last_focused_window = cfg_node_from_id(rd_state->last_focused_window); RD_WindowState *ws = rd_window_state_from_cfg(last_focused_window); if(ws == &rd_nil_window_state) { ws = rd_state->first_window_state; } if(ws != &rd_nil_window_state) { rd_state->prestop_focused_window = os_focused_external_window(); os_window_set_minimized(ws->os, 0); os_window_bring_to_front(ws->os); os_window_focus(ws->os); } } } }break; } } //////////////////////////// //- rjf: early-out if no new commands // if(rd_state->cmds[0].count == cmd_count_pre_tick) { break; } } ////////////////////////////// //- rjf: retry find-thread // if(!ctrl_handle_match(ctrl_handle_zero(), find_thread_retry)) { rd_cmd(RD_CmdKind_FindThread, .thread = find_thread_retry); } //////////////////////////// //- rjf: rotate command slots, bump command gen counter // // in this step, we rotate the ring buffer of command batches (command // arenas & lists). when the cmds_gen (the position of the ring buffer) // is even, the command queue is in a "read/write" mode, and this is uniquely // usable by the core - this is done so that commands in the core can push // other commands, and have those other commands processed on the same frame. // // in view code, however, they can only use the current command queue in a // "read only" mode, because new commands pushed by those views must be // processed first by the core. so, before calling into view code, the // cmds_gen is incremented to be *odd*. this way, the views will *write* // commands into the 0 slot, but *read* from the 1 slot (which will contain // this frame's commands). // // after view code runs, the generation number is incremented back to even. // the commands pushed by the view will be in the queue, and the core can // treat that queue as r/w again. // if(rd_state->frame_depth == 1) { // rjf: rotate { Arena *first_arena = rd_state->cmds_arenas[0]; RD_CmdList first_cmds = rd_state->cmds[0]; MemoryCopy(rd_state->cmds_arenas, rd_state->cmds_arenas+1, sizeof(rd_state->cmds_arenas[0])*(ArrayCount(rd_state->cmds_arenas)-1)); MemoryCopy(rd_state->cmds, rd_state->cmds+1, sizeof(rd_state->cmds[0])*(ArrayCount(rd_state->cmds)-1)); rd_state->cmds_arenas[ArrayCount(rd_state->cmds_arenas)-1] = first_arena; rd_state->cmds[ArrayCount(rd_state->cmds_arenas)-1] = first_cmds; } // rjf: clear next batch { arena_clear(rd_state->cmds_arenas[0]); MemoryZeroStruct(&rd_state->cmds[0]); } // rjf: bump { rd_state->cmds_gen += 1; } } ////////////////////////////// //- rjf: compute all ambiguous paths from view titles // ProfScope("compute all ambiguous paths from view titles") { Temp scratch = scratch_begin(0, 0); rd_state->ambiguous_path_slots_count = 512; rd_state->ambiguous_path_slots = push_array(rd_frame_arena(), RD_AmbiguousPathNode *, rd_state->ambiguous_path_slots_count); for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { CFG_Node *window = cfg_node_from_id(ws->cfg_id); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, window); for(CFG_PanelNode *p = panel_tree.root; p != &cfg_nil_panel_node; p = cfg_panel_node_rec__depth_first_pre(panel_tree.root, p).next) { for(CFG_NodePtrNode *tab_n = p->tabs.first; tab_n != 0; tab_n = tab_n->next) { CFG_Node *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } RD_RegsScope(.tab = tab->id, .view = tab->id) { String8 eval_string = rd_expr_from_cfg(tab); String8 file_path = rd_file_path_from_eval_string(scratch.arena, eval_string); if(file_path.size != 0) { String8 name = str8_skip_last_slash(file_path); U64 hash = d_hash_from_string__case_insensitive(name); U64 slot_idx = hash%rd_state->ambiguous_path_slots_count; RD_AmbiguousPathNode *node = 0; for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx]; n != 0; n = n->next) { if(str8_match(n->name, name, StringMatchFlag_CaseInsensitive)) { node = n; break; } } if(node == 0) { node = push_array(rd_frame_arena(), RD_AmbiguousPathNode, 1); SLLStackPush(rd_state->ambiguous_path_slots[slot_idx], node); node->name = push_str8_copy(rd_frame_arena(), name); } str8_list_push(rd_frame_arena(), &node->paths, push_str8_copy(rd_frame_arena(), file_path)); } } } } } scratch_end(scratch); } ////////////////////////////// //- rjf: compute animation rates, given config // { F32 master_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("animations")); F32 scrolling_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("scrolling_animations")); F32 tooltip_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("tooltip_animations")); F32 menu_animations_f = (F32)!!rd_setting_b32_from_name(str8_lit("menu_animations")); rd_state->catchall_animation_rate = 1 - master_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); rd_state->menu_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-70.f * rd_state->frame_dt)); rd_state->menu_animation_rate__slow = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); rd_state->entity_alive_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-30.f * rd_state->frame_dt)); rd_state->rich_hover_animation_rate = 1 - master_animations_f*menu_animations_f*pow_f32(2, (-50.f * rd_state->frame_dt)); rd_state->scrolling_animation_rate = 1 - master_animations_f*scrolling_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); rd_state->tooltip_animation_rate = 1 - master_animations_f*tooltip_animations_f*pow_f32(2, (-60.f * rd_state->frame_dt)); } ////////////////////////////// //- rjf: animate confirmation // { F32 rate = rd_setting_b32_from_name(str8_lit("menu_animations")) ? 1 - pow_f32(2, (-30.f * rd_state->frame_dt)) : 1.f; B32 popup_open = rd_state->popup_active; rd_state->popup_t += rate * ((F32)!!popup_open-rd_state->popup_t); if(abs_f32(rd_state->popup_t - (F32)!!popup_open) > 0.005f) { rd_request_frame(); } } ////////////////////////////// //- rjf: update/render all windows // { dr_begin_frame(rd_font_from_slot(RD_FontSlot_Icons)); CFG_NodePtrList windows = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("window")); for(CFG_NodePtrNode *n = windows.first; n != 0; n = n->next) { CFG_Node *window = n->v; RD_WindowState *w = rd_window_state_from_cfg(window); B32 window_is_focused = os_window_is_focused(w->os); if(window_is_focused) { rd_state->last_focused_window = w->cfg_id; } rd_push_regs(); rd_regs()->window = w->cfg_id; rd_window_frame(); MemoryZeroStruct(&w->ui_events); RD_Regs *window_regs = rd_pop_regs(); if(rd_state->last_focused_window == w->cfg_id) { MemoryCopyStruct(rd_regs(), window_regs); } } } ////////////////////////////// //- rjf: garbage collect untouched window states // { for EachIndex(slot_idx, rd_state->window_state_slots_count) { for(RD_WindowState *ws = rd_state->window_state_slots[slot_idx].first, *next; ws != 0; ws = next) { next = ws->hash_next; CFG_Node *cfg = cfg_node_from_id(ws->cfg_id); if(cfg == &cfg_nil_node || ws->last_frame_index_touched < rd_state->frame_index || rd_state->quit) { ui_state_release(ws->ui); r_window_unequip(ws->os, ws->r); os_window_close(ws->os); arena_release(ws->drop_completion_arena); arena_release(ws->query_arena); arena_release(ws->hover_eval_arena); arena_release(ws->autocomp_arena); arena_release(ws->arena); DLLRemove_NPZ(&rd_nil_window_state, rd_state->first_window_state, rd_state->last_window_state, ws, order_next, order_prev); DLLRemove_NP(rd_state->window_state_slots[slot_idx].first, rd_state->window_state_slots[slot_idx].last, ws, hash_next, hash_prev); SLLStackPush_N(rd_state->free_window_state, ws, order_next); } } } } ////////////////////////////// //- rjf: simulate lag // if(DEV_simulate_lag) { os_sleep_milliseconds(300); } ////////////////////////////// //- rjf: end drag/drop if needed // if(rd_state->drag_drop_state == RD_DragDropState_Dropping) { rd_state->drag_drop_state = RD_DragDropState_Null; } ////////////////////////////// //- rjf: clear frame request state // if(rd_state->num_frames_requested > 0) { rd_state->num_frames_requested -= 1; } ////////////////////////////// //- rjf: close frame scopes // // NOTE(rjf): this always must happen before the refresh, since that // will sleep for vsync, and we do not want to hold handles for long, // since eviction threads may be waiting to get rid of stuff. // access_close(rd_state->frame_access); rd_state->frame_access = frame_access_restore; ////////////////////////////// //- rjf: submit rendering to all windows // ProfScope("submit rendering to all windows") { r_begin_frame(); for(RD_WindowState *w = rd_state->first_window_state; w != &rd_nil_window_state; w = w->order_next) { r_window_begin_frame(w->os, w->r); dr_submit_bucket(w->os, w->r, w->draw_bucket); r_window_end_frame(w->os, w->r); } r_end_frame(); } ////////////////////////////// //- rjf: show windows after first frame // if(rd_state->frame_depth == 1) { CFG_IDList windows_to_show = {0}; for(RD_WindowState *w = rd_state->first_window_state; w != &rd_nil_window_state; w = w->order_next) { if(w->frames_alive == 1) { cfg_id_list_push(scratch.arena, &windows_to_show, w->cfg_id); } } for(CFG_IDNode *n = windows_to_show.first; n != 0; n = n->next) { CFG_Node *window = cfg_node_from_id(n->v); RD_WindowState *ws = rd_window_state_from_cfg(window); os_window_first_paint(ws->os); } } ////////////////////////////// //- rjf: determine frame time, record into history // U64 end_time_us = os_now_microseconds(); U64 frame_time_us = end_time_us-begin_time_us; rd_state->frame_time_us_history[rd_state->frame_index%ArrayCount(rd_state->frame_time_us_history)] = frame_time_us; ////////////////////////////// //- rjf: [windows] clear pages from working set shortly after startup, many of which will not be needed // #if OS_WINDOWS if(di_load_count() < 50) { if(rd_state->frame_index == 15) ProfScope("SetProcessWorkingSetSize") { SetProcessWorkingSetSize(GetCurrentProcess(), max_U64, max_U64); } } #endif ////////////////////////////// //- rjf: bump frame time counters // rd_state->frame_index += 1; rd_state->time_in_seconds += rd_state->frame_dt; rd_state->time_in_us += frame_time_us; ////////////////////////////// //- rjf: bump command batch ring buffer generation // if(rd_state->frame_depth == 1) { rd_state->cmds_gen += 1; } ////////////////////////////// //- rjf: collect logs // ProfScope("collect logs") { LogScopeResult log = log_scope_end(scratch.arena); os_append_data_to_file_path(rd_state->log_path, log.strings[LogMsgKind_Info]); if(log.strings[LogMsgKind_UserError].size != 0) { String8 error_log = log.strings[LogMsgKind_UserError]; String8List error_log_lines = str8_split(scratch.arena, error_log, (U8 *)"\n", 1, 0); String8 error_log_string = str8_list_join(scratch.arena, &error_log_lines, &(StringJoin){.sep = str8_lit(" ")}); for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { ws->error_string_size = Min(sizeof(ws->error_buffer), error_log_string.size); MemoryCopy(ws->error_buffer, error_log_string.str, ws->error_string_size); ws->error_t = 1.f; } } } rd_state->frame_depth -= 1; scratch_end(scratch); ProfEnd(); } ================================================ FILE: src/raddbg/raddbg_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_CORE_H #define RADDBG_CORE_H //////////////////////////////// //~ rjf: Evaluation Spaces typedef U64 RD_EvalSpaceKind; enum { RD_EvalSpaceKind_MetaQuery = CTRL_EvalSpaceKind_FirstUserDefined, RD_EvalSpaceKind_MetaCfg, RD_EvalSpaceKind_MetaCmd, RD_EvalSpaceKind_MetaTheme, RD_EvalSpaceKind_MetaCtrlEntity, RD_EvalSpaceKind_MetaUnattachedProcess, RD_EvalSpaceKind_MetaCallStackTree, }; //////////////////////////////// //~ rjf: View UI Hook Types #define RD_VIEW_UI_FUNCTION_SIG(name) void name(E_Eval eval, Rng2F32 rect) #define RD_VIEW_UI_FUNCTION_NAME(name) rd_view_ui__##name #define RD_VIEW_UI_FUNCTION_DEF(name) internal RD_VIEW_UI_FUNCTION_SIG(RD_VIEW_UI_FUNCTION_NAME(name)) typedef RD_VIEW_UI_FUNCTION_SIG(RD_ViewUIFunctionType); typedef struct RD_ViewUIRule RD_ViewUIRule; struct RD_ViewUIRule { String8 name; RD_ViewUIFunctionType *ui; }; typedef struct RD_ViewUIRuleNode RD_ViewUIRuleNode; struct RD_ViewUIRuleNode { RD_ViewUIRuleNode *next; RD_ViewUIRule v; }; typedef struct RD_ViewUIRuleSlot RD_ViewUIRuleSlot; struct RD_ViewUIRuleSlot { RD_ViewUIRuleNode *first; RD_ViewUIRuleNode *last; }; typedef struct RD_ViewUIRuleMap RD_ViewUIRuleMap; struct RD_ViewUIRuleMap { RD_ViewUIRuleSlot *slots; U64 slots_count; }; //////////////////////////////// //~ rjf: Drag/Drop Types typedef enum RD_DragDropState { RD_DragDropState_Null, RD_DragDropState_Dragging, RD_DragDropState_Dropping, RD_DragDropState_COUNT } RD_DragDropState; //////////////////////////////// //~ rjf: Command Kind Types typedef U32 RD_QueryFlags; enum { RD_QueryFlag_AllowFiles = (1<<0), RD_QueryFlag_AllowFolders = (1<<1), RD_QueryFlag_CodeInput = (1<<2), RD_QueryFlag_KeepOldInput = (1<<3), RD_QueryFlag_SelectOldInput = (1<<4), RD_QueryFlag_Floating = (1<<5), RD_QueryFlag_Required = (1<<6), }; typedef U32 RD_CmdKindFlags; enum { RD_CmdKindFlag_ListInUI = (1<<0), RD_CmdKindFlag_ListInIPCDocs = (1<<1), RD_CmdKindFlag_ListInTab = (1<<2), RD_CmdKindFlag_ListInTextPt = (1<<3), RD_CmdKindFlag_ListInTextRng = (1<<4), }; //////////////////////////////// //~ rjf: Autocompletion Cursor Info Type typedef struct RD_AutocompCursorInfo RD_AutocompCursorInfo; struct RD_AutocompCursorInfo { String8 list_expr; String8 filter; Rng1U64 replaced_range; String8 callee_expr; MD_Node *arg_schema; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/raddbg.meta.h" //////////////////////////////// //~ rjf: View State Types typedef struct RD_ArenaExt RD_ArenaExt; struct RD_ArenaExt { RD_ArenaExt *next; Arena *arena; }; typedef struct RD_ViewState RD_ViewState; struct RD_ViewState { // rjf: hash links & key RD_ViewState *hash_next; RD_ViewState *hash_prev; CFG_ID cfg_id; // rjf: touch info U64 last_frame_index_touched; U64 last_frame_index_built; // rjf: loading indicator info F32 loading_t; F32 loading_t_target; U64 loading_progress_v; U64 loading_progress_v_target; // rjf: scroll position UI_ScrollPt2 scroll_pos; // rjf: eval visualization view state EV_View *ev_view; // rjf: view-lifetime allocation & user data extensions Arena *arena; U64 arena_reset_pos; RD_ArenaExt *first_arena_ext; RD_ArenaExt *last_arena_ext; void *user_data; // rjf: query state B32 query_is_open; TxtPt query_cursor; TxtPt query_mark; U8 query_buffer[KB(1)]; U64 query_string_size; // rjf: contents are focused (disables query focus) B32 contents_are_focused; }; typedef struct RD_ViewStateSlot RD_ViewStateSlot; struct RD_ViewStateSlot { RD_ViewState *first; RD_ViewState *last; }; //////////////////////////////// //~ rjf: Vocabulary Map typedef struct RD_VocabInfoMapNode RD_VocabInfoMapNode; struct RD_VocabInfoMapNode { RD_VocabInfoMapNode *single_next; RD_VocabInfoMapNode *plural_next; RD_VocabInfo v; }; typedef struct RD_VocabInfoMapSlot RD_VocabInfoMapSlot; struct RD_VocabInfoMapSlot { RD_VocabInfoMapNode *first; RD_VocabInfoMapNode *last; }; typedef struct RD_VocabInfoMap RD_VocabInfoMap; struct RD_VocabInfoMap { U64 single_slots_count; RD_VocabInfoMapSlot *single_slots; U64 plural_slots_count; RD_VocabInfoMapSlot *plural_slots; }; //////////////////////////////// //~ rjf: Structured Locations, Parsed From Config Trees typedef struct RD_Location RD_Location; struct RD_Location { String8 file_path; TxtPt pt; String8 expr; }; //////////////////////////////// //~ rjf: Command Types typedef struct RD_Cmd RD_Cmd; struct RD_Cmd { String8 name; RD_Regs *regs; }; typedef struct RD_CmdNode RD_CmdNode; struct RD_CmdNode { RD_CmdNode *next; RD_CmdNode *prev; RD_Cmd cmd; }; typedef struct RD_CmdList RD_CmdList; struct RD_CmdList { RD_CmdNode *first; RD_CmdNode *last; U64 count; }; //////////////////////////////// //~ rjf: Context Register Types typedef struct RD_RegsNode RD_RegsNode; struct RD_RegsNode { RD_RegsNode *next; RD_Regs v; }; //////////////////////////////// //~ rjf: Structured Theme Types, Parsed From Config typedef enum RD_FontSlot { RD_FontSlot_Main, RD_FontSlot_Code, RD_FontSlot_Icons, RD_FontSlot_COUNT } RD_FontSlot; //////////////////////////////// //~ rjf: Per-Window State typedef struct RD_DropCompletionTask RD_DropCompletionTask; struct RD_DropCompletionTask { RD_DropCompletionTask *next; B32 exe; B32 dbg; B32 cfg; String8List paths; }; typedef struct RD_WindowState RD_WindowState; struct RD_WindowState { // rjf: links & metadata RD_WindowState *order_next; RD_WindowState *order_prev; RD_WindowState *hash_next; RD_WindowState *hash_prev; CFG_ID cfg_id; U64 frames_alive; U64 last_frame_index_touched; // rjf: top-level info & handles Arena *arena; OS_Handle os; R_Handle r; UI_State *ui; F32 last_dpi; B32 window_temporarily_focused_ipc; B32 window_layout_reset; Rng2F32 last_window_rect; // rjf: theme (recomputed each frame) UI_Theme *theme; Vec4F32 theme_code_colors[RD_CodeColorSlot_COUNT]; // rjf: font raster flags (recomputed each frame) FNT_RasterFlags font_slot_raster_flags[RD_FontSlot_COUNT]; // rjf: dev interface state B32 dev_menu_is_open; // rjf: menu bar state B32 menu_bar_focused; B32 menu_bar_focused_on_press; B32 menu_bar_key_held; B32 menu_bar_focus_press_started; // rjf: drop-completion state Arena *drop_completion_arena; CFG_ID drop_completion_panel; RD_DropCompletionTask *top_drop_completion_task; // rjf: query state B32 query_is_active; Arena *query_arena; RD_Regs *query_regs; CFG_ID query_view_id; CFG_ID query_last_view_id; // rjf: hover eval state B32 hover_eval_focused; Arena *hover_eval_arena; Vec2F32 hover_eval_spawn_pos; String8 hover_eval_string; U64 hover_eval_firstt_us; U64 hover_eval_lastt_us; // rjf: autocompletion state U64 autocomp_last_frame_index; Arena *autocomp_arena; RD_Regs *autocomp_regs; RD_AutocompCursorInfo autocomp_cursor_info; // rjf: error state U8 error_buffer[512]; U64 error_string_size; F32 error_t; // rjf: per-frame ui events state UI_EventList ui_events; // rjf: per-frame drawing state DR_Bucket *draw_bucket; }; typedef struct RD_WindowStateSlot RD_WindowStateSlot; struct RD_WindowStateSlot { RD_WindowState *first; RD_WindowState *last; }; //////////////////////////////// //~ rjf: Main Per-Process Graphical State typedef struct RD_LoadedDbgInfoNode RD_LoadedDbgInfoNode; struct RD_LoadedDbgInfoNode { RD_LoadedDbgInfoNode *hash_next; RD_LoadedDbgInfoNode *hash_prev; RD_LoadedDbgInfoNode *lru_next; RD_LoadedDbgInfoNode *lru_prev; DI_Key key; U64 last_tick_idx_touched; }; typedef struct RD_LoadedDbgInfoSlot RD_LoadedDbgInfoSlot; struct RD_LoadedDbgInfoSlot { RD_LoadedDbgInfoNode *first; RD_LoadedDbgInfoNode *last; }; typedef struct RD_AmbiguousPathNode RD_AmbiguousPathNode; struct RD_AmbiguousPathNode { RD_AmbiguousPathNode *next; String8 name; String8List paths; }; typedef struct RD_State RD_State; struct RD_State { // rjf: basics Arena *arena; B32 quit; B32 quit_after_success; S32 frame_depth; U64 frame_eval_memread_endt_us; // rjf: config bucket paths Arena *user_path_arena; String8 user_path; Arena *project_path_arena; String8 project_path; Arena *theme_path_arena; String8 theme_path; // rjf: unpacked settings (cached, because they need to be used // earlier than setting evaluation is legal in a frame) B32 alt_menu_bar_enabled; B32 use_default_stl_type_views; B32 use_default_ue_type_views; // rjf: animation rates F32 catchall_animation_rate; F32 menu_animation_rate; F32 menu_animation_rate__slow; F32 entity_alive_animation_rate; F32 rich_hover_animation_rate; F32 scrolling_animation_rate; F32 tooltip_animation_rate; // rjf: serialized config debug string keys C_Key user_cfg_string_key; C_Key project_cfg_string_key; C_Key cmdln_cfg_string_key; C_Key transient_cfg_string_key; // rjf: default theme table MD_Node *theme_preset_trees[RD_ThemePreset_COUNT]; // rjf: vocab table RD_VocabInfoMap vocab_info_map; // rjf: log Log *log; String8 log_path; // rjf: frame history info U64 frame_index; Arena *frame_arenas[2]; U64 frame_time_us_history[64]; U64 num_frames_requested; F64 time_in_seconds; U64 time_in_us; // rjf: frame parameters F32 frame_dt; Access *frame_access; // rjf: evaluation cache E_Cache *eval_cache; // rjf: ambiguous path table (constructed from-scratch each frame) U64 ambiguous_path_slots_count; RD_AmbiguousPathNode **ambiguous_path_slots; // rjf: key map (constructed from-scratch each frame) CFG_KeyMap *key_map; // rjf: slot -> font tag map (constructed from-scratch each frame) FNT_Tag font_slot_table[RD_FontSlot_COUNT]; // rjf: meta name -> eval type key map (constructed from-scratch each frame) E_String2TypeKeyMap *meta_name2type_map; // rjf: name -> view ui map (constructed from-scratch each frame) RD_ViewUIRuleMap *view_ui_rule_map; // rjf: registers stack RD_RegsNode base_regs; RD_RegsNode *top_regs; // rjf: autosave state F32 seconds_until_autosave; // rjf: commands Arena *cmds_arenas[2]; RD_CmdList cmds[2]; U64 cmds_gen; Arena *cmd_output_arena; String8List cmd_outputs; // rjf: popup state UI_Key popup_key; B32 popup_active; F32 popup_t; Arena *popup_arena; RD_CmdList popup_cmds; String8 popup_title; String8 popup_desc; // rjf: text editing mode state B32 text_edit_mode; // rjf: contextual hover info RD_Regs *hover_regs; RD_RegSlot hover_regs_slot; RD_Regs *next_hover_regs; RD_RegSlot next_hover_regs_slot; // rjf: icon texture R_Handle icon_texture; // rjf: fixed ui keys UI_Key drop_completion_key; UI_Key ctx_menu_key; // rjf: drag/drop state Arena *drag_drop_arena; RD_Regs *drag_drop_regs; RD_RegSlot drag_drop_regs_slot; RD_DragDropState drag_drop_state; // rjf: cfg state CFG_State *cfg; CFG_SchemaTable *cfg_schema_table; // rjf: loaded debug info cache U64 loaded_dbg_info_slots_count; RD_LoadedDbgInfoSlot *loaded_dbg_info_slots; RD_LoadedDbgInfoNode *loaded_dbg_info_lru_first; RD_LoadedDbgInfoNode *loaded_dbg_info_lru_last; RD_LoadedDbgInfoNode *free_loaded_dbg_info_node; // rjf: window state cache U64 window_state_slots_count; RD_WindowStateSlot *window_state_slots; RD_WindowState *free_window_state; CFG_ID last_focused_window; RD_WindowState *first_window_state; RD_WindowState *last_window_state; CFG_ID window_state_last_accessed_id; RD_WindowState *window_state_last_accessed; // rjf: view state cache U64 view_state_slots_count; RD_ViewStateSlot *view_state_slots; RD_ViewState *free_view_state; CFG_ID view_state_last_accessed_id; RD_ViewState *view_state_last_accessed; // rjf: bind change Arena *bind_change_arena; B32 bind_change_active; CFG_ID bind_change_binding_id; String8 bind_change_cmd_name; // rjf: pre-stop focused window OS_Handle prestop_focused_window; }; //////////////////////////////// //~ rjf: Globals read_only global RD_VocabInfo rd_nil_vocab_info = {0}; read_only global RD_CmdKindInfo rd_nil_cmd_kind_info = {0}; RD_VIEW_UI_FUNCTION_DEF(null); read_only global RD_ViewUIRule rd_nil_view_ui_rule = { {0}, RD_VIEW_UI_FUNCTION_NAME(null), }; read_only global RD_ViewState rd_nil_view_state = { &rd_nil_view_state, &rd_nil_view_state, }; read_only global RD_WindowState rd_nil_window_state = { &rd_nil_window_state, &rd_nil_window_state, &rd_nil_window_state, &rd_nil_window_state, }; global RD_State *rd_state = 0; global CFG_ID rd_last_drag_drop_panel = 0; global CFG_ID rd_last_drag_drop_prev_tab = 0; //////////////////////////////// //~ rjf: Registers Type Functions internal void rd_regs_copy_contents(Arena *arena, RD_Regs *dst, RD_Regs *src); internal RD_Regs *rd_regs_copy(Arena *arena, RD_Regs *src); //////////////////////////////// //~ rjf: Commands Type Functions internal void rd_cmd_list_push_new(Arena *arena, RD_CmdList *cmds, String8 name, RD_Regs *regs); //////////////////////////////// //~ rjf: View UI Rule Functions internal RD_ViewUIRuleMap *rd_view_ui_rule_map_make(Arena *arena, U64 slots_count); internal void rd_view_ui_rule_map_insert(Arena *arena, RD_ViewUIRuleMap *map, String8 string, RD_ViewUIFunctionType *ui); internal RD_ViewUIRule *rd_view_ui_rule_from_string(String8 string); //////////////////////////////// //~ rjf: Global Cross-Window UI Interaction State Functions internal B32 rd_drag_is_active(void); internal void rd_drag_begin(RD_RegSlot slot); internal B32 rd_drag_drop(void); internal void rd_drag_kill(void); internal void rd_set_hover_regs(RD_RegSlot slot); internal RD_Regs *rd_get_hover_regs(void); //////////////////////////////// //~ rjf: Config Functions internal B32 rd_cfg_is_project_filtered(CFG_Node *cfg); internal Vec4F32 rd_hsva_from_cfg(CFG_Node *cfg); internal Vec4F32 rd_color_from_cfg(CFG_Node *cfg); internal B32 rd_disabled_from_cfg(CFG_Node *cfg); internal RD_Location rd_location_from_cfg(CFG_Node *cfg); internal String8 rd_label_from_cfg(CFG_Node *cfg); internal String8 rd_expr_from_cfg(CFG_Node *cfg); internal String8 rd_path_from_cfg(CFG_Node *cfg); internal D_Target rd_target_from_cfg(Arena *arena, CFG_Node *cfg); internal String8 rd_default_setting_from_names(String8 schema_name, String8 setting_name); internal String8 rd_setting_from_name(String8 name); internal B32 rd_setting_b32_from_name(String8 name); internal U64 rd_setting_u64_from_name(String8 name); internal F32 rd_setting_f32_from_name(String8 name); internal CFG_Node *rd_immediate_cfg_from_key(String8 string); internal CFG_Node *rd_immediate_cfg_from_keyf(char *fmt, ...); internal String8 rd_mapped_from_file_path(Arena *arena, String8 file_path); internal String8List rd_possible_overrides_from_file_path(Arena *arena, String8 file_path); //////////////////////////////// //~ rjf: Control Entity Info Extraction internal Vec4F32 rd_color_from_ctrl_entity(CTRL_Entity *entity); internal String8 rd_name_from_ctrl_entity(Arena *arena, CTRL_Entity *entity); //////////////////////////////// //~ rjf: Evaluation Spaces //- rjf: cfg <-> eval space internal CFG_Node *rd_cfg_from_eval_space(E_Space space); internal E_Space rd_eval_space_from_cfg(CFG_Node *cfg); //- rjf: ctrl entity <-> eval space internal CTRL_Entity *rd_ctrl_entity_from_eval_space(E_Space space); internal E_Space rd_eval_space_from_ctrl_entity(CTRL_Entity *entity, E_SpaceKind kind); //- rjf: command name <-> eval space internal String8 rd_cmd_name_from_eval(E_Eval eval); //- rjf: eval space reads/writes internal U64 rd_eval_space_gen(E_Space space); internal B32 rd_eval_space_read(E_Space space, void *out, Rng1U64 range); internal B32 rd_eval_space_write(E_Space space, void *in, Rng1U64 range); //- rjf: asynchronous streamed reads -> hashes from spaces internal C_Key rd_key_from_eval_space_range(E_Space space, Rng1U64 range, B32 zero_terminated); //- rjf: space -> entire range internal Rng1U64 rd_whole_range_from_eval_space(E_Space space); //////////////////////////////// //~ rjf: Evaluation Visualization //- rjf: writing values back to child processes internal B32 rd_commit_eval_value_string(E_Eval dst_eval, String8 string); //- rjf: eval <-> file path internal String8 rd_file_path_from_eval(Arena *arena, E_Eval eval); internal String8 rd_file_path_from_eval_string(Arena *arena, String8 string); internal String8 rd_eval_string_from_file_path(Arena *arena, String8 string); //- rjf: eval -> query internal String8 rd_query_from_eval_string(Arena *arena, String8 string); //////////////////////////////// //~ rjf: View Functions internal CFG_Node *rd_view_from_eval(CFG_Node *parent, E_Eval eval); internal RD_ViewState *rd_view_state_from_cfg(CFG_Node *cfg); internal void rd_view_ui(Rng2F32 rect); //////////////////////////////// //~ rjf: View Building API //- rjf: view info extraction internal Arena *rd_view_arena(void); internal UI_ScrollPt2 rd_view_scroll_pos(void); internal EV_View *rd_view_eval_view(void); internal String8 rd_view_query_cmd(void); internal String8 rd_view_query_input(void); internal String8 rd_view_setting_from_name(String8 string); internal E_Value rd_view_setting_value_from_name(String8 string); internal B32 rd_view_setting_b32_from_name(String8 string); internal U64 rd_view_setting_u64_from_name(String8 string); internal F32 rd_view_setting_f32_from_name(String8 string); //- rjf: evaluation & tag (a view's 'call') parameter extraction internal Rng1U64 rd_space_range_from_eval(E_Eval eval); internal TXT_LangKind rd_lang_kind_from_eval(E_Eval eval); internal Arch rd_arch_from_eval(E_Eval eval); //- rjf: pushing/attaching view resources internal void *rd_view_state_by_size(U64 size); #define rd_view_state(T) (T *)rd_view_state_by_size(sizeof(T)) internal Arena *rd_push_view_arena(void); //- rjf: storing view-attached state internal void rd_store_view_expr_string(String8 string); internal void rd_store_view_loading_info(B32 is_loading, U64 progress_u64, U64 progress_u64_target); internal void rd_store_view_scroll_pos(UI_ScrollPt2 pos); internal void rd_store_view_param(String8 key, String8 value); internal void rd_store_view_paramf(String8 key, char *fmt, ...); #define rd_store_view_param_f32(key, f32) rd_store_view_paramf((key), "%ff", (f32)) #define rd_store_view_param_s64(key, s64) rd_store_view_paramf((key), "%I64d", (s64)) #define rd_store_view_param_u64(key, u64) rd_store_view_paramf((key), "0x%I64x", (u64)) //////////////////////////////// //~ rjf: Window Functions internal String8 rd_push_window_title(Arena *arena); internal CFG_Node *rd_window_from_cfg(CFG_Node *cfg); internal RD_WindowState *rd_window_state_from_cfg(CFG_Node *cfg); internal RD_WindowState *rd_window_state_from_os_handle(OS_Handle os); internal void rd_window_frame(void); //////////////////////////////// //~ rjf: Eval Visualization internal String8 rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringParams *params, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval); //////////////////////////////// //~ rjf: Hover Eval internal void rd_set_hover_eval(Vec2F32 pos, String8 string); //////////////////////////////// //~ rjf: Autocompletion Lister internal void rd_set_autocomp_regs_(E_Eval dst_eval, RD_Regs *regs); #define rd_set_autocomp_regs(dst_eval, ...) rd_set_autocomp_regs_((dst_eval), &(RD_Regs){rd_regs_lit_init_top __VA_ARGS__}) //////////////////////////////// //~ rjf: Colors, Fonts, Config //- rjf: colors internal MD_Node *rd_theme_tree_from_name(Arena *arena, Access *access, String8 theme_name); internal Vec4F32 rd_rgba_from_code_color_slot(RD_CodeColorSlot slot); internal RD_CodeColorSlot rd_code_color_slot_from_txt_token_kind(TXT_TokenKind kind); internal RD_CodeColorSlot rd_code_color_slot_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 string); //- rjf: fonts internal F32 rd_font_size(void); internal FNT_Tag rd_font_from_slot(RD_FontSlot slot); internal FNT_RasterFlags rd_raster_flags_from_slot(RD_FontSlot slot); //////////////////////////////// //~ rjf: Process Control Info Stringification internal String8 rd_string_from_exception_code(U32 code); internal DR_FStrList rd_stop_explanation_fstrs_from_ctrl_event(Arena *arena, CTRL_Event *event); //////////////////////////////// //~ rjf: Vocab Info Lookups internal RD_VocabInfo *rd_vocab_info_from_code_name(String8 code_name); internal RD_VocabInfo *rd_vocab_info_from_code_name_plural(String8 code_name_plural); #define rd_plural_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->code_name_plural) #define rd_display_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->display_name) #define rd_display_plural_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->display_name_plural) #define rd_icon_kind_from_code_name(code_name) (rd_vocab_info_from_code_name(code_name)->icon_kind) #define rd_singular_from_code_name_plural(code_name_plural) (rd_vocab_info_from_code_name_plural(code_name_plural)->code_name) //////////////////////////////// //~ rjf: Continuous Frame Requests internal void rd_request_frame(void); //////////////////////////////// //~ rjf: Main State Accessors //- rjf: per-frame arena internal Arena *rd_frame_arena(void); //////////////////////////////// //~ rjf: Registers #define rd_regs() (&rd_state->top_regs->v) #define rd_base_regs() (&rd_state->base_regs.v) internal RD_Regs *rd_push_regs_(RD_Regs *regs); #define rd_push_regs(...) rd_push_regs_(&(RD_Regs){rd_regs_lit_init_top __VA_ARGS__}) internal RD_Regs *rd_pop_regs(void); #define RD_RegsScope(...) DeferLoop(rd_push_regs(__VA_ARGS__), rd_pop_regs()) internal void rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 query_expr, String8 string); //////////////////////////////// //~ rjf: Commands //- rjf: name -> info internal RD_CmdKind rd_cmd_kind_from_string(String8 string); internal RD_CmdKindInfo *rd_cmd_kind_info_from_string(String8 string); //- rjf: pushing internal void rd_push_cmd(String8 name, RD_Regs *regs); #define rd_cmd(kind, ...) rd_push_cmd(rd_cmd_kind_info_table[kind].string, &(RD_Regs){rd_regs_lit_init_top __VA_ARGS__}) //- rjf: iterating internal B32 rd_next_cmd(RD_Cmd **cmd); internal B32 rd_next_view_cmd(RD_Cmd **cmd); //////////////////////////////// //~ rjf: Main Layer Top-Level Calls internal void rd_init(CmdLine *cmdln); internal void rd_frame(void); #endif // RADDBG_CORE_H ================================================ FILE: src/raddbg/raddbg_eval.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: `commands` Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(commands) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_MemberAccess) { String8 cmd_name = expr->first->next->string; RD_CmdKindInfo *cmd_info = rd_cmd_kind_info_from_string(cmd_name); E_TypeKey cmd_type = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); cmd_type = e_type_key_cons_meta_description(cmd_type, cmd_info->description); result.type_key = cmd_type; result.mode = E_Mode_Value; result.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCmd), e_irtree_const_u(arena, e_id_from_string(cmd_name))); } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(commands) { E_TypeExpandInfo result = {0}; { Temp scratch = scratch_begin(&arena, 1); String8List cmd_names = {0}; E_Type *type = e_type_from_key(eval.irtree.type_key); for EachNonZeroEnumVal(RD_CmdKind, k) { RD_CmdKindInfo *info = &rd_cmd_kind_info_table[k]; if(info->flags & RD_CmdKindFlag_ListInUI && (!str8_match(type->name, str8_lit("text_pt_commands"), 0) || info->flags & RD_CmdKindFlag_ListInTextPt) && (!str8_match(type->name, str8_lit("text_range_commands"), 0) || info->flags & RD_CmdKindFlag_ListInTextRng) && (!str8_match(type->name, str8_lit("tab_commands"), 0) || info->flags & RD_CmdKindFlag_ListInTab)) { String8 code_name = info->string; String8 description = info->description; String8 search_tags = info->search_tags; String8 display_name = rd_display_from_code_name(code_name); FuzzyMatchRangeList desc_matches = fuzzy_match_find(scratch.arena, filter, description); FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, display_name); FuzzyMatchRangeList tags_matches = fuzzy_match_find(scratch.arena, filter, search_tags); B32 binding_matches_good = 0; CFG_KeyMapNodePtrList bindings = cfg_key_map_node_ptr_list_from_name(scratch.arena, rd_state->key_map, code_name); for(CFG_KeyMapNodePtr *n = bindings.first; n != 0; n = n->next) { String8 binding_text = os_string_from_modifiers_key(scratch.arena, n->v->binding.modifiers, n->v->binding.key); FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, binding_text); if(matches.count == matches.needle_part_count) { binding_matches_good = 1; break; } } if(name_matches.count == name_matches.needle_part_count || desc_matches.count == desc_matches.needle_part_count || tags_matches.count == tags_matches.needle_part_count || binding_matches_good) { str8_list_push(scratch.arena, &cmd_names, code_name); } } } String8Array *accel = push_array(arena, String8Array, 1); *accel = str8_array_from_list(arena, &cmd_names); result.user_data = accel; result.expr_count = accel->count; scratch_end(scratch); } return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(commands) { U64 out_idx = 0; String8Array *accel = (String8Array *)user_data; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { String8 cmd_name = accel->v[idx]; E_Eval cmd_eval = e_eval_from_stringf("query:commands.%S", cmd_name); evals_out[out_idx] = cmd_eval; } } //////////////////////////////// //~ rjf: `themes` Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(themes) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_ArrayIndex && expr->first->next->kind == E_ExprKind_LeafStringLiteral) { String8 theme_name = expr->first->next->string; E_TypeKey theme_type = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("theme")); result.type_key = theme_type; result.mode = E_Mode_Value; result.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaTheme), e_irtree_const_u(arena, e_id_from_string(theme_name))); } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(themes) { E_TypeExpandInfo result = {0}; { Temp scratch = scratch_begin(&arena, 1); //- rjf: gather presets String8List names = {0}; for EachEnumVal(RD_ThemePreset, p) { String8 name = rd_theme_preset_display_string_table[p]; FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, name); if(name_matches.count == name_matches.needle_part_count) { str8_list_push(scratch.arena, &names, name); } } //- rjf: gather theme files { String8 theme_folder = push_str8f(scratch.arena, "%S/raddbg/themes", os_get_process_info()->user_program_data_path); OS_FileIter *it = os_file_iter_begin(scratch.arena, theme_folder, OS_FileIterFlag_SkipFolders); for(OS_FileInfo info = {0}; os_file_iter_next(scratch.arena, it, &info);) { String8 name = info.name; FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, name); if(name_matches.count == name_matches.needle_part_count) { str8_list_push(scratch.arena, &names, push_str8_copy(arena, name)); } } os_file_iter_end(it); } //- rjf: flatten & build accelerator String8Array *accel = push_array(arena, String8Array, 1); *accel = str8_array_from_list(arena, &names); result.user_data = accel; result.expr_count = accel->count; scratch_end(scratch); } return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(themes) { U64 out_idx = 0; String8Array *accel = (String8Array *)user_data; for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { String8 name = accel->v[idx]; evals_out[out_idx] = e_eval_wrapf(eval, "$[\"%S\"]", name); } } //////////////////////////////// //~ rjf: `locals` Type Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(locals) { E_TypeExpandInfo result = {0}; Temp scratch = scratch_begin(&arena, 1); { E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_ir_ctx->locals_map); e_string2num_map_node_array_sort__in_place(&nodes); String8List exprs_filtered = {0}; for EachIndex(idx, nodes.count) { String8 local_expr_string = nodes.v[idx]->string; FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, local_expr_string); if(matches.count == matches.needle_part_count) { str8_list_push(scratch.arena, &exprs_filtered, local_expr_string); } } String8Array *accel = push_array(arena, String8Array, 1); *accel = str8_array_from_list(arena, &exprs_filtered); result.user_data = accel; result.expr_count = accel->count; } scratch_end(scratch); return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(locals) { String8Array *accel = (String8Array *)user_data; Rng1U64 legal_idx_range = r1u64(0, accel->count); Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { String8 expr_string = accel->v[read_range.min + idx]; evals_out[idx] = e_eval_from_string(expr_string); } } //////////////////////////////// //~ rjf: `registers` Type Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(registers) { Temp scratch = scratch_begin(&arena, 1); CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); Arch arch = thread->arch; U64 reg_count = regs_reg_code_count_from_arch(arch); String8 *reg_strings = regs_reg_code_string_table_from_arch(arch); String8List exprs_list = {0}; for(U64 idx = 1; idx < reg_count; idx += 1) { FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, reg_strings[idx]); if(matches.count == matches.needle_part_count) { str8_list_push(scratch.arena, &exprs_list, reg_strings[idx]); } } String8Array *accel = push_array(arena, String8Array, 1); *accel = str8_array_from_list(arena, &exprs_list); E_TypeExpandInfo info = {accel, accel->count}; scratch_end(scratch); return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(registers) { String8Array *accel = (String8Array *)user_data; Rng1U64 legal_idx_range = r1u64(0, accel->count); Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { String8 register_name = accel->v[read_range.min + idx]; String8 register_expr = push_str8f(arena, "reg:%S", register_name); evals_out[idx] = e_eval_from_string(register_expr); } } //////////////////////////////// //~ rjf: Schema Type Hooks typedef struct RD_SchemaIRExt RD_SchemaIRExt; struct RD_SchemaIRExt { CFG_Node *cfg; CTRL_Entity *entity; MD_NodePtrList schemas; }; E_TYPE_IREXT_FUNCTION_DEF(schema) { RD_SchemaIRExt *ext = push_array(arena, RD_SchemaIRExt, 1); { Temp scratch = scratch_begin(&arena, 1); E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpret = e_interpret(bytecode); E_TypeKey type_key = irtree->type_key; E_Type *type = e_type_from_key(type_key); ext->cfg = rd_cfg_from_eval_space(interpret.space); ext->entity = rd_ctrl_entity_from_eval_space(interpret.space); ext->schemas = cfg_schemas_from_name(arena, rd_state->cfg_schema_table, type->name); scratch_end(scratch); } E_IRExt result = {ext}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(schema) { RD_SchemaIRExt *ext = (RD_SchemaIRExt *)lhs_irtree->user_data; E_IRTreeAndType irtree = {&e_irnode_nil}; if(expr->kind == E_ExprKind_MemberAccess) { MD_Node *child_schema = &md_nil_node; for(MD_NodePtrNode *n = ext->schemas.first; n != 0; n = n->next) { for MD_EachNode(child, n->v->first) { if(str8_match(child->string, expr->first->next->string, 0)) { child_schema = child; break; } } } if(child_schema != &md_nil_node) { CFG_Node *cfg = ext->cfg; CTRL_Entity *entity = ext->entity; CFG_Node *child = cfg_node_child_from_string(cfg, child_schema->string); E_TypeKey child_type_key = zero_struct; B32 wrap_child_w_meta_expr = 0; B32 is_query_child = md_node_has_tag(child_schema, str8_lit("query"), 0); E_TypeFlags type_flags = (!!is_query_child * E_TypeFlag_IsNotEditable); if(0){} //- rjf: ctrl entity members else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0)) { child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsCodeText); } else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0)) { child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsPathText); } else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0)) { CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath); child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, type_flags|E_TypeFlag_IsPathText); } //- rjf: cfg members else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0) || str8_match(child_schema->first->string, str8_lit("expr_string"), 0)) { child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsCodeText); } else if(str8_match(child_schema->first->string, str8_lit("path"), 0) || str8_match(child_schema->first->string, str8_lit("path_pt"), 0)) { child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPathText); } else if(str8_match(child_schema->first->string, str8_lit("string"), 0)) { child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPlainText); } //- rjf: catchall cases else if(str8_match(child_schema->first->string, str8_lit("u64"), 0)) { child_type_key = e_type_key_basic(E_TypeKind_U64); wrap_child_w_meta_expr = 1; } else if(str8_match(child_schema->first->string, str8_lit("u32"), 0)) { child_type_key = e_type_key_basic(E_TypeKind_U32); wrap_child_w_meta_expr = 1; } else if(str8_match(child_schema->first->string, str8_lit("f32"), 0)) { child_type_key = e_type_key_basic(E_TypeKind_F32); wrap_child_w_meta_expr = 1; } else if(str8_match(child_schema->first->string, str8_lit("bool"), 0)) { child_type_key = e_type_key_basic(E_TypeKind_Bool); wrap_child_w_meta_expr = 1; } else if(str8_match(child_schema->first->string, str8_lit("vaddr_range"), 0)) { Temp scratch = scratch_begin(&arena, 1); E_MemberList vaddr_range_members_list = {0}; e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("min"), .off = 0); e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("max"), .off = 8); E_MemberArray vaddr_range_members = e_member_array_from_list(scratch.arena, &vaddr_range_members_list); child_type_key = e_type_key_cons(.kind = E_TypeKind_Struct, .name = str8_lit("vaddr_range"), .count = vaddr_range_members.count, .members = vaddr_range_members.v); scratch_end(scratch); } else if(str8_match(child_schema->first->string, str8_lit("query"), 0)) { child_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, child_schema->string); } //- rjf: extend child type with meta-expression information if(wrap_child_w_meta_expr) { Temp scratch = scratch_begin(&arena, 1); E_Expr *expr = e_parse_from_string(child->first->string).expr; B32 expr_is_simple = 0; if(expr->kind == E_ExprKind_LeafU64 || expr->kind == E_ExprKind_LeafF64 || expr->kind == E_ExprKind_LeafF32) { expr_is_simple = 1; } if((expr->kind == E_ExprKind_Pos || expr->kind == E_ExprKind_Neg) && expr->first == expr->last && (expr->first->kind == E_ExprKind_LeafU64 || expr->first->kind == E_ExprKind_LeafF64 || expr->first->kind == E_ExprKind_LeafF32)) { expr_is_simple = 1; } if(expr->kind == E_ExprKind_LeafIdentifier && (str8_match(expr->string, str8_lit("true"), 0) || str8_match(expr->string, str8_lit("false"), 0))) { expr_is_simple = 1; } if(!expr_is_simple && expr != &e_expr_nil) { child_type_key = e_type_key_cons_meta_expr(child_type_key, child->first->string); } scratch_end(scratch); } //- rjf: extend child type with decorative meta info { MD_Node *display_name = md_tag_from_string(child_schema, str8_lit("display_name"), 0); MD_Node *description = md_tag_from_string(child_schema, str8_lit("description"), 0); if(!md_node_is_nil(display_name)) { child_type_key = e_type_key_cons_meta_display_name(child_type_key, display_name->first->string); } if(!md_node_is_nil(description)) { child_type_key = e_type_key_cons_meta_description(child_type_key, description->first->string); } } //- rjf: extend child type with hex lens { MD_Node *hex = md_tag_from_string(child_schema->first, str8_lit("hex"), 0); if(!md_node_is_nil(hex)) { child_type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .name = str8_lit("hex"), .direct_key = child_type_key); } } //- rjf: extend child type with color lens { MD_Node *color = md_tag_from_string(child_schema->first, str8_lit("color"), 0); if(!md_node_is_nil(color)) { child_type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .name = str8_lit("color"), .direct_key = child_type_key); } } //- rjf: extend child type with ranges { MD_Node *range = md_tag_from_string(child_schema->first, str8_lit("range"), 0); if(!md_node_is_nil(range)) { E_Expr *min_bound = e_parse_from_string(range->first->string).expr; E_Expr *max_bound = e_parse_from_string(range->first->next->string).expr; E_Expr *args[] = { min_bound, max_bound, }; child_type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .name = str8_lit("range1"), .direct_key = child_type_key, .count = 2, .args = args); } } //- rjf: evaluate E_Space child_eval_space = zero_struct; if(cfg != &cfg_nil_node) { child_eval_space = e_space_make(RD_EvalSpaceKind_MetaCfg); child_eval_space.u64s[0] = cfg->id; child_eval_space.u64s[1] = e_id_from_string(child_schema->string); } else { child_eval_space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); child_eval_space.u64s[2] = e_id_from_string(child_schema->string); } irtree.root = e_irtree_set_space(arena, child_eval_space, e_push_irnode(arena, RDI_EvalOp_ConstU64)); irtree.type_key = child_type_key; irtree.mode = E_Mode_Offset; } } return irtree; } typedef struct RD_SchemaExpandAccel RD_SchemaExpandAccel; struct RD_SchemaExpandAccel { String8Array commands; MD_Node **children; U64 children_count; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(schema) { E_TypeExpandInfo result = {0}; { Temp scratch = scratch_begin(&arena, 1); // rjf: unpack RD_SchemaIRExt *ext = (RD_SchemaIRExt *)eval.irtree.user_data; // rjf: gather expansion commands String8Array commands = {0}; { String8List commands_list = {0}; for(MD_NodePtrNode *n = ext->schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; MD_Node *tag = md_tag_from_string(schema, str8_lit("expand_commands"), 0); for MD_EachNode(arg, tag->first) { B32 filtered = 0; if(md_node_has_tag(arg, str8_lit("output"), 0)) { String8 expr = rd_expr_from_cfg(ext->cfg); filtered = (!str8_match(expr, str8_lit("query:output"), 0)); } if(!filtered) { RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(arg->string); FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, rd_display_from_code_name(cmd_kind_info->string)); FuzzyMatchRangeList desc_matches = fuzzy_match_find(scratch.arena, filter, cmd_kind_info->description); FuzzyMatchRangeList tags_matches = fuzzy_match_find(scratch.arena, filter, cmd_kind_info->search_tags); if(name_matches.count == name_matches.needle_part_count || desc_matches.count == desc_matches.needle_part_count || tags_matches.count == tags_matches.needle_part_count) { str8_list_push(scratch.arena, &commands_list, arg->string); } } } } commands = str8_array_from_list(arena, &commands_list); } // rjf: gather expansion children typedef struct ExpandChildNode ExpandChildNode; struct ExpandChildNode { ExpandChildNode *next; MD_Node *n; }; ExpandChildNode *first_child_node = 0; ExpandChildNode *last_child_node = 0; U64 child_count = 0; for(MD_NodePtrNode *n = ext->schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; for MD_EachNode(child, schema->first) { if(!md_node_has_tag(child, str8_lit("no_expand"), 0)) { MD_Node *expand_check = md_tag_from_string(child, str8_lit("expand_if"), 0); B32 expand_this_child = 1; if(!md_node_is_nil(expand_check)) E_ParentKey(eval.key) { expand_this_child = !!e_value_from_string(expand_check->first->string).u64; } if(expand_this_child) { String8 display_name = md_tag_from_string(child, str8_lit("display_name"), 0)->first->string; if(display_name.size == 0) { display_name = rd_display_from_code_name(child->string); } String8 desc = md_tag_from_string(child, str8_lit("description"), 0)->first->string; FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, child->string); FuzzyMatchRangeList display_name_matches = fuzzy_match_find(scratch.arena, filter, display_name); FuzzyMatchRangeList desc_matches = fuzzy_match_find(scratch.arena, filter, desc); if(name_matches.count == name_matches.needle_part_count || display_name_matches.count == display_name_matches.needle_part_count || desc_matches.count == desc_matches.needle_part_count) { ExpandChildNode *n = push_array(scratch.arena, ExpandChildNode, 1); n->n = child; SLLQueuePush(first_child_node, last_child_node, n); child_count += 1; } } } } } // rjf: flatten expansion member list MD_Node **children = push_array(arena, MD_Node *, child_count); { U64 idx = 0; for(ExpandChildNode *n = first_child_node; n != 0; n = n->next, idx += 1) { children[idx] = n->n; } } // rjf: build accelerator for lookups RD_SchemaExpandAccel *accel = push_array(arena, RD_SchemaExpandAccel, 1); accel->commands = commands; accel->children = children; accel->children_count = child_count; // rjf: fill result result.user_data = accel; result.expr_count = child_count + commands.count; scratch_end(scratch); } return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(schema) { RD_SchemaExpandAccel *accel = (RD_SchemaExpandAccel *)user_data; Rng1U64 cmds_idx_range = r1u64(0, accel->commands.count); Rng1U64 chld_idx_range = r1u64(cmds_idx_range.max, cmds_idx_range.max + accel->children_count); U64 out_idx = 0; // rjf: read commands { Rng1U64 read_range = intersect_1u64(idx_range, cmds_idx_range); for(U64 idx = read_range.min; idx < read_range.max; idx += 1, out_idx += 1) { evals_out[out_idx] = e_eval_from_stringf("query:commands.%S", accel->commands.v[idx - cmds_idx_range.min]); } } // rjf: read children { Rng1U64 read_range = intersect_1u64(idx_range, chld_idx_range); for(U64 idx = read_range.min; idx < read_range.max; idx += 1, out_idx += 1) { MD_Node *child_schema = accel->children[idx - chld_idx_range.min]; evals_out[out_idx] = e_eval_wrapf(eval, "$.%S", child_schema->string); } } } //////////////////////////////// //~ rjf: Config Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(cfgs) { E_IRTreeAndType result = {&e_irnode_nil}; E_Expr *rhs = expr->first->next; if(rhs->kind == E_ExprKind_LeafIdentifier && str8_match(str8_prefix(rhs->string, 1), str8_lit("$"), 0)) { String8 numeric_part = str8_skip(rhs->string, 1); CFG_ID id = u64_from_str8(numeric_part, 16); CFG_Node *cfg = cfg_node_from_id(id); E_Space space = rd_eval_space_from_cfg(cfg); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); result.type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, cfg->string); result.mode = E_Mode_Offset; } return result; } //////////////////////////////// //~ rjf: Control Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(control) { E_IRTreeAndType result = {&e_irnode_nil}; E_Expr *rhs = expr->first->next; if(rhs->kind == E_ExprKind_LeafIdentifier && str8_match(str8_prefix(rhs->string, 1), str8_lit("$"), 0)) { CTRL_Handle handle = ctrl_handle_from_string(rhs->string); CTRL_Entity *entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, handle); E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); result.type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, ctrl_entity_kind_code_name_table[entity->kind]); result.mode = E_Mode_Offset; } return result; } //////////////////////////////// //~ rjf: Config Collection Type Hooks typedef struct RD_CfgsIRExt RD_CfgsIRExt; struct RD_CfgsIRExt { String8 cfg_name; String8Array cmds; CFG_NodePtrArray cfgs; Rng1U64 cmds_idx_range; Rng1U64 cfgs_idx_range; }; E_TYPE_IREXT_FUNCTION_DEF(cfgs_slice) { RD_CfgsIRExt *ext = push_array(arena, RD_CfgsIRExt, 1); { Temp scratch = scratch_begin(&arena, 1); //- rjf: determine which key we'll be gathering E_TypeKey type_key = irtree->type_key; E_Type *type = e_type_from_key(type_key); String8 cfg_name = rd_singular_from_code_name_plural(type->name); //- rjf: gather cfgs CFG_NodePtrList cfgs_list = cfg_node_top_level_list_from_string(scratch.arena, cfg_name); //- rjf: gather commands String8List cmds_list = {0}; { MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, cfg_name); for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; MD_Node *collection_cmds_root = md_tag_from_string(schema, str8_lit("collection_commands"), 0); for MD_EachNode(cmd, collection_cmds_root->first) { str8_list_push(arena, &cmds_list, cmd->string); } } } //- rjf: package & fill ext->cfg_name = cfg_name; ext->cfgs = cfg_node_ptr_array_from_list(arena, &cfgs_list); ext->cmds = str8_array_from_list(arena, &cmds_list); scratch_end(scratch); } E_IRExt result = {ext}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(cfgs_slice) { E_IRTreeAndType result = {&e_irnode_nil}; CFG_Node *cfg = &cfg_nil_node; RD_CfgsIRExt *ext = (RD_CfgsIRExt *)lhs_irtree->user_data; switch(expr->kind) { default:{}break; case E_ExprKind_ArrayIndex: { E_Value rhs_value = e_value_from_expr(expr->first->next); U64 rhs_idx = rhs_value.u64; if(0 <= rhs_idx && rhs_idx < ext->cfgs.count) { cfg = ext->cfgs.v[rhs_idx]; } }break; case E_ExprKind_MemberAccess: { String8 rhs_name = expr->first->next->string; CFG_ID id = 0; if(str8_match(str8_prefix(rhs_name, 1), str8_lit("$"), 0)) { id = u64_from_str8(str8_skip(rhs_name, 1), 16); cfg = cfg_node_from_id(id); } }break; } if(cfg != &cfg_nil_node) { result.root = e_irtree_set_space(arena, rd_eval_space_from_cfg(cfg), e_irtree_const_u(arena, 0)); result.mode = E_Mode_Offset; result.type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, ext->cfg_name); } return result; } typedef struct RD_CfgsExpandAccel RD_CfgsExpandAccel; struct RD_CfgsExpandAccel { String8Array cmds; CFG_NodePtrArray cfgs; Rng1U64 cmds_idx_range; Rng1U64 cfgs_idx_range; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(cfgs_slice) { RD_CfgsExpandAccel *accel = push_array(arena, RD_CfgsExpandAccel, 1); E_TypeExpandInfo info = {accel}; Temp scratch = scratch_begin(&arena, 1); { //- rjf: unpack RD_CfgsIRExt *ext = (RD_CfgsIRExt *)eval.irtree.user_data; //- rjf: filter cfgs CFG_NodePtrArray cfgs__filtered = ext->cfgs; if(filter.size != 0) { CFG_NodePtrList cfgs_list__filtered = {0}; for EachIndex(idx, ext->cfgs.count) { CFG_Node *cfg = ext->cfgs.v[idx]; DR_FStrList fstrs = rd_title_fstrs_from_cfg(scratch.arena, cfg, 1); String8 string = dr_string_from_fstrs(scratch.arena, &fstrs); FuzzyMatchRangeList fuzzy_matches = fuzzy_match_find(scratch.arena, filter, string); if(fuzzy_matches.count == fuzzy_matches.needle_part_count) { cfg_node_ptr_list_push(scratch.arena, &cfgs_list__filtered, cfg); } } cfgs__filtered = cfg_node_ptr_array_from_list(arena, &cfgs_list__filtered); } //- rjf: fill // TODO(rjf): @cleanup don't smuggle this through like this... if(cfg_node_child_from_string(cfg_node_from_id(rd_regs()->view), str8_lit("lister")) == &cfg_nil_node) { accel->cmds = ext->cmds; accel->cmds_idx_range = r1u64(0, accel->cmds.count); } accel->cfgs = cfgs__filtered; accel->cfgs_idx_range = r1u64(accel->cmds_idx_range.max, accel->cmds_idx_range.max + accel->cfgs.count); info.expr_count = (accel->cmds.count + accel->cfgs.count); } scratch_end(scratch); return info; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(cfgs_query) { RD_CfgsExpandAccel *accel = push_array(arena, RD_CfgsExpandAccel, 1); { Temp scratch = scratch_begin(&arena, 1); CFG_Node *root_cfg = rd_cfg_from_eval_space(eval.space); String8 child_key = e_string_from_id(eval.space.u64s[1]); String8 child_key_singular = rd_singular_from_code_name_plural(child_key); if(child_key_singular.size != 0) { child_key = child_key_singular; } String8List cmds = {0}; MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, child_key); for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; MD_Node *collection_cmds_root = md_tag_from_string(schema, str8_lit("collection_commands"), 0); for MD_EachNode(cmd, collection_cmds_root->first) { str8_list_push(scratch.arena, &cmds, cmd->string); } } CFG_NodePtrList children = cfg_node_child_list_from_string(scratch.arena, root_cfg, child_key); CFG_NodePtrList children__filtered = children; if(filter.size != 0) { MemoryZeroStruct(&children__filtered); for(CFG_NodePtrNode *n = children.first; n != 0; n = n->next) { DR_FStrList cfg_fstrs = rd_title_fstrs_from_cfg(scratch.arena, n->v, 1); String8 cfg_string = dr_string_from_fstrs(scratch.arena, &cfg_fstrs); FuzzyMatchRangeList ranges = fuzzy_match_find(scratch.arena, filter, cfg_string); if(ranges.count == ranges.needle_part_count) { cfg_node_ptr_list_push(scratch.arena, &children__filtered, n->v); } } } accel->cmds = str8_array_from_list(arena, &cmds); accel->cmds_idx_range = r1u64(0, accel->cmds.count); accel->cfgs = cfg_node_ptr_array_from_list(arena, &children__filtered); accel->cfgs_idx_range = r1u64(accel->cmds.count + 0, accel->cmds.count + accel->cfgs.count); scratch_end(scratch); } E_TypeExpandInfo info = {accel, accel->cfgs.count + accel->cmds.count}; return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(cfgs_slice) { RD_CfgsExpandAccel *accel = (RD_CfgsExpandAccel *)user_data; Rng1U64 cmds_idx_range = accel->cmds_idx_range; Rng1U64 cfgs_idx_range = accel->cfgs_idx_range; U64 dst_idx = 0; // rjf: fill commands { Rng1U64 read_range = intersect_1u64(cmds_idx_range, idx_range); U64 read_count = dim_1u64(read_range); E_Eval cmds_eval = e_eval_from_stringf("query:commands"); for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) { String8 cmd_name = accel->cmds.v[idx + read_range.min - cmds_idx_range.min]; E_Eval cmd_eval = e_eval_wrapf(cmds_eval, "$.%S", cmd_name); evals_out[dst_idx] = cmd_eval; } } // rjf: fill cfgs { Rng1U64 read_range = intersect_1u64(cfgs_idx_range, idx_range); U64 read_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) { CFG_Node *cfg = accel->cfgs.v[idx + read_range.min - cfgs_idx_range.min]; evals_out[dst_idx] = e_eval_from_stringf("query:config.$%I64x", cfg->id); } } } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(cfgs_slice) { U64 id = 0; RD_CfgsExpandAccel *accel = (RD_CfgsExpandAccel *)user_data; if(num != 0) { U64 idx = num-1; if(contains_1u64(accel->cfgs_idx_range, idx)) { CFG_Node *cfg = accel->cfgs.v[idx - accel->cfgs_idx_range.min]; id = cfg->id; } else if(contains_1u64(accel->cmds_idx_range, idx)) { id = num; id |= (1ull<<63); } } return id; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(cfgs_slice) { U64 num = 0; RD_CfgsExpandAccel *accel = (RD_CfgsExpandAccel *)user_data; if(id != 0) { if(id & (1ull<<63)) { num = id; num &= ~(1ull<<63); } else for EachIndex(idx, accel->cfgs.count) { if(accel->cfgs.v[idx]->id == id) { num = idx + accel->cfgs_idx_range.min + 1; break; } } } return num; } //////////////////////////////// //~ rjf: `call_stack` Type Hooks typedef struct RD_CallStackAccel RD_CallStackAccel; struct RD_CallStackAccel { Arch arch; CTRL_Handle process; CTRL_CallStack call_stack; }; E_TYPE_IREXT_FUNCTION_DEF(call_stack) { RD_CallStackAccel *accel = push_array(arena, RD_CallStackAccel, 1); { Temp scratch = scratch_begin(&arena, 1); E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interp = e_interpret(bytecode); CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(interp.space); if(entity->kind == CTRL_EntityKind_Thread) { B32 call_stack_high_priority = ctrl_handle_match(entity->handle, rd_base_regs()->thread); accel->arch = entity->arch; accel->process = ctrl_process_from_entity(entity)->handle; accel->call_stack = ctrl_call_stack_from_thread(rd_state->frame_access, entity->handle, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); } scratch_end(scratch); } E_IRExt result = {accel}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(call_stack) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_ArrayIndex) { RD_CallStackAccel *accel = (RD_CallStackAccel *)lhs_irtree->user_data; E_Value rhs_value = e_value_from_expr(expr->first->next); CTRL_CallStack *call_stack = &accel->call_stack; if(0 <= rhs_value.u64 && rhs_value.u64 < call_stack->frames_count) { CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, accel->process); CTRL_CallStackFrame *f = &call_stack->frames[rhs_value.u64]; result.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(process, CTRL_EvalSpaceKind_Entity), e_irtree_const_u(arena, regs_rip_from_arch_block(accel->arch, f->regs))); result.type_key = e_type_key_cons(.arch = process->arch, .kind = E_TypeKind_Ptr, .direct_key = e_type_key_basic(E_TypeKind_Function), .count = 1, .depth = f->inline_depth); result.mode = E_Mode_Value; } } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack) { RD_CallStackAccel *accel = (RD_CallStackAccel *)eval.irtree.user_data; E_TypeExpandInfo result = {0}; result.user_data = accel; result.expr_count = accel->call_stack.frames_count; return result; } //////////////////////////////// //~ rjf: `environment` Type Hooks typedef struct RD_EnvironmentAccel RD_EnvironmentAccel; struct RD_EnvironmentAccel { CFG_NodePtrArray cfgs; }; E_TYPE_IREXT_FUNCTION_DEF(environment) { RD_EnvironmentAccel *accel = push_array(arena, RD_EnvironmentAccel, 1); { Temp scratch = scratch_begin(&arena, 1); E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpret = e_interpret(bytecode); E_Space space = interpret.space; CFG_Node *target = rd_cfg_from_eval_space(space); CFG_NodePtrList env_strings = {0}; for(CFG_Node *child = target->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("environment"), 0)) { cfg_node_ptr_list_push(scratch.arena, &env_strings, child); } } accel->cfgs = cfg_node_ptr_array_from_list(arena, &env_strings); scratch_end(scratch); } E_IRExt result = {accel}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(environment) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_ArrayIndex) { RD_EnvironmentAccel *accel = (RD_EnvironmentAccel *)lhs_irtree->user_data; CFG_NodePtrArray *cfgs = &accel->cfgs; E_Value rhs_value = e_value_from_expr(expr->first->next); if(0 <= rhs_value.u64 && rhs_value.u64 < cfgs->count) { CFG_Node *cfg = cfgs->v[rhs_value.u64]; result.root = e_irtree_set_space(arena, rd_eval_space_from_cfg(cfg), e_irtree_const_u(arena, 0)); result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), cfg->first->string.size, E_TypeFlag_IsCodeText); result.mode = E_Mode_Offset; } } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(environment) { RD_EnvironmentAccel *accel = (RD_EnvironmentAccel *)eval.irtree.user_data; E_TypeExpandInfo result = {accel, accel->cfgs.count + 1}; return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(environment) { RD_EnvironmentAccel *accel = (RD_EnvironmentAccel *)user_data; Rng1U64 legal_idx_range = r1u64(0, accel->cfgs.count); Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { U64 cfg_idx = read_range.min + idx; if(cfg_idx < accel->cfgs.count) { evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", cfg_idx); } } } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(environment) { U64 id = 0; RD_EnvironmentAccel *accel = (RD_EnvironmentAccel *)user_data; if(1 <= num && num <= accel->cfgs.count) { U64 idx = (num-1); id = accel->cfgs.v[idx]->id; } else if(num == accel->cfgs.count+1) { id = max_U64; } return id; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(environment) { U64 num = 0; RD_EnvironmentAccel *accel = (RD_EnvironmentAccel *)user_data; if(id != 0 && id != max_U64) { for EachIndex(idx, accel->cfgs.count) { if(accel->cfgs.v[idx]->id == id) { num = idx+1; break; } } } else if(id == max_U64) { num = accel->cfgs.count + 1; } return num; } //////////////////////////////// //~ rjf: `watches` Type Hooks typedef struct RD_WatchesAccel RD_WatchesAccel; struct RD_WatchesAccel { CFG_NodePtrArray cfgs; }; E_TYPE_IREXT_FUNCTION_DEF(watches) { RD_WatchesAccel *accel = push_array(arena, RD_WatchesAccel, 1); { Temp scratch = scratch_begin(&arena, 1); E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpret = e_interpret(bytecode); E_Space space = interpret.space; CFG_Node *target = rd_cfg_from_eval_space(space); CFG_NodePtrList env_strings = {0}; for(CFG_Node *child = target->first; child != &cfg_nil_node; child = child->next) { if(str8_match(child->string, str8_lit("watch"), 0)) { cfg_node_ptr_list_push(scratch.arena, &env_strings, child); } } accel->cfgs = cfg_node_ptr_array_from_list(arena, &env_strings); scratch_end(scratch); } E_IRExt result = {accel}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(watches) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_ArrayIndex) { RD_WatchesAccel *accel = (RD_WatchesAccel *)lhs_irtree->user_data; CFG_NodePtrArray *cfgs = &accel->cfgs; E_Value rhs_value = e_value_from_expr(expr->first->next); if(0 <= rhs_value.u64 && rhs_value.u64 < cfgs->count) { CFG_Node *cfg = cfgs->v[rhs_value.u64]; result.root = e_irtree_set_space(arena, rd_eval_space_from_cfg(cfg), e_irtree_const_u(arena, 0)); result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), cfg->first->string.size, E_TypeFlag_IsCodeText); result.mode = E_Mode_Offset; } } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(watches) { RD_WatchesAccel *ext = (RD_WatchesAccel *)eval.irtree.user_data; RD_WatchesAccel *accel = push_array(arena, RD_WatchesAccel, 1); { CFG_NodePtrArray cfgs__filtered = ext->cfgs; if(filter.size != 0) { Temp scratch = scratch_begin(&arena, 1); CFG_NodePtrList cfgs_list__filtered = {0}; for EachIndex(idx, ext->cfgs.count) { CFG_Node *watch = ext->cfgs.v[idx]; String8 string = watch->first->string; FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, string); if(matches.count == matches.needle_part_count) { cfg_node_ptr_list_push(scratch.arena, &cfgs_list__filtered, watch); } } cfgs__filtered = cfg_node_ptr_array_from_list(arena, &cfgs_list__filtered); scratch_end(scratch); } accel->cfgs = cfgs__filtered; } E_TypeExpandInfo result = {accel, accel->cfgs.count + 1}; return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(watches) { RD_WatchesAccel *accel = (RD_WatchesAccel *)user_data; Rng1U64 legal_idx_range = r1u64(0, accel->cfgs.count); Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); U64 read_range_count = dim_1u64(read_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { U64 cfg_idx = read_range.min + idx; if(cfg_idx < accel->cfgs.count) { CFG_Node *cfg = accel->cfgs.v[cfg_idx]; evals_out[idx] = e_eval_from_string(cfg->first->string); } } } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(watches) { U64 id = 0; RD_WatchesAccel *accel = (RD_WatchesAccel *)user_data; if(1 <= num && num <= accel->cfgs.count) { U64 idx = (num-1); id = accel->cfgs.v[idx]->id; } else if(num == accel->cfgs.count+1) { id = max_U64; } return id; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(watches) { U64 num = 0; RD_WatchesAccel *accel = (RD_WatchesAccel *)user_data; if(id != 0 && id != max_U64) { for EachIndex(idx, accel->cfgs.count) { if(accel->cfgs.v[idx]->id == id) { num = idx+1; break; } } } else if(id == max_U64) { num = accel->cfgs.count + 1; } return num; } //////////////////////////////// //~ rjf: `unattached_processes` Type Hooks typedef struct RD_UnattachedProcessesAccel RD_UnattachedProcessesAccel; struct RD_UnattachedProcessesAccel { DMN_ProcessInfo *infos; CTRL_Entity **machines; U64 infos_count; }; E_TYPE_ACCESS_FUNCTION_DEF(unattached_processes) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_MemberAccess) { Temp scratch = scratch_begin(&arena, 1); // rjf: extract pid / name id from access string U64 pid = 0; U64 string_id = 0; { String8 pid_string = {0}; String8 name_id_string = {0}; U8 split_char = '$'; String8List parts = str8_split(scratch.arena, expr->first->next->string, &split_char, 1, 0); if(parts.first != 0 && parts.first->next != 0) { pid_string = parts.first->string; name_id_string = parts.first->next->string; pid = u64_from_str8(pid_string, 16); string_id = u64_from_str8(name_id_string, 16); } } // rjf: get machine entity from space E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree->root); String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); E_Interpretation interpret = e_interpret(bytecode); CTRL_Entity *machine = rd_ctrl_entity_from_eval_space(interpret.space); // rjf: build evaluation for this unattached process if(machine != &ctrl_entity_nil) { E_IRNode *value_irnode = e_push_irnode(arena, RDI_EvalOp_ConstU128); value_irnode->value.u128.u64[0] = pid; value_irnode->value.u128.u64[1] = string_id; E_Space space = rd_eval_space_from_ctrl_entity(machine, RD_EvalSpaceKind_MetaUnattachedProcess); result.root = e_irtree_set_space(arena, space, value_irnode); result.type_key = e_type_key_basic(E_TypeKind_U128); result.mode = E_Mode_Value; } scratch_end(scratch); } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes) { E_TypeExpandInfo info = {0}; { Temp scratch = scratch_begin(&arena, 1); //- rjf: evaluate lhs machine, if we have one CTRL_Entity *lhs_entity = rd_ctrl_entity_from_eval_space(eval.space); //- rjf: gather all machines we're searching through CTRL_EntityArray machines = {0}; if(lhs_entity->kind == CTRL_EntityKind_Machine) { machines.v = &lhs_entity; machines.count = 1; } else { machines = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Machine); } //- rjf: gather system processes from this machine typedef struct Node Node; struct Node { Node *next; CTRL_Entity *machine; DMN_ProcessInfo info; }; Node *first = 0; Node *last = 0; U64 count = 0; for EachIndex(idx, machines.count) { CTRL_Entity *machine = machines.v[idx]; DMN_ProcessIter iter = {0}; dmn_process_iter_begin(&iter); for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);) { B32 passes_filter = 1; if(filter.size != 0) { passes_filter = 0; FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, info.name); FuzzyMatchRangeList pid_matches = fuzzy_match_find(scratch.arena, filter, push_str8f(scratch.arena, "%I64u", info.pid)); if(name_matches.count == name_matches.needle_part_count || pid_matches.count == pid_matches.needle_part_count) { passes_filter = 1; } } if(passes_filter) { Node *node = push_array(scratch.arena, Node, 1); SLLQueuePush(first, last, node); node->machine = machine; node->info = info; count += 1; } } dmn_process_iter_end(&iter); } //- rjf: list -> array U64 infos_count = count; DMN_ProcessInfo *infos = push_array(arena, DMN_ProcessInfo, infos_count); CTRL_Entity **infos_machines = push_array(arena, CTRL_Entity *, infos_count); { U64 idx = 0; for(Node *n = first; n != 0; n = n->next, idx += 1) { infos[idx] = n->info; infos[idx].name = push_str8_copy(arena, infos[idx].name); infos_machines[idx] = n->machine; } } //- rjf: build accelerator RD_UnattachedProcessesAccel *accel = push_array(arena, RD_UnattachedProcessesAccel, 1); accel->infos = infos; accel->infos_count = infos_count; accel->machines = infos_machines; info.user_data = accel; info.expr_count = infos_count; scratch_end(scratch); } return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes) { RD_UnattachedProcessesAccel *accel = (RD_UnattachedProcessesAccel *)user_data; U64 out_idx = 0; E_TypeKey unattached_process_type = e_type_key_cons(.kind = E_TypeKind_U128, .name = str8_lit("unattached_process")); for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { CTRL_Entity *machine = accel->machines[idx]; String8 string = ctrl_string_from_handle(arena, machine->handle); evals_out[out_idx] = e_eval_wrapf(eval, "query:control.%S.unattached_processes.$%I64x$%I64x", string, accel->infos[idx].pid, e_id_from_string(accel->infos[idx].name)); } } //////////////////////////////// //~ rjf: Control Entity List Type Hooks (`processes`, `threads`, etc.) E_TYPE_ACCESS_FUNCTION_DEF(ctrl_entities) { E_IRTreeAndType result = {&e_irnode_nil}; { CTRL_Entity *entity = &ctrl_entity_nil; switch(expr->kind) { case E_ExprKind_MemberAccess: { String8 rhs_name = expr->first->next->string; CTRL_Handle handle = ctrl_handle_from_string(rhs_name); entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, handle); }break; case E_ExprKind_ArrayIndex: { E_Type *type = e_type_from_key(lhs_irtree->type_key); CTRL_EntityKind kind = ctrl_entity_kind_from_string(rd_singular_from_code_name_plural(type->name)); E_Value rhs_value = e_value_from_expr(expr->first->next); U64 rhs_idx = rhs_value.u64; CTRL_EntityArray entities = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, kind); if(0 <= rhs_idx && rhs_idx < entities.count) { entity = entities.v[rhs_idx]; } }break; } if(entity != &ctrl_entity_nil) { E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); String8 name = ctrl_entity_kind_code_name_table[entity->kind]; E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); result.type_key = type_key; result.mode = E_Mode_Offset; } } return result; } E_TYPE_EXPAND_INFO_FUNCTION_DEF(ctrl_entities) { E_TypeExpandInfo result = {0}; Temp scratch = scratch_begin(&arena, 1); { //- rjf: determine which entity we're looking under CTRL_Entity *scoping_entity = &ctrl_entity_nil; if(eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity) { scoping_entity = rd_ctrl_entity_from_eval_space(eval.space); } //- rjf: determine which type of child we're gathering E_TypeKey lhs_type_key = eval.irtree.type_key; E_Type *lhs_type = e_type_from_key(lhs_type_key); String8 name = rd_singular_from_code_name_plural(lhs_type->name); CTRL_EntityKind entity_kind = ctrl_entity_kind_from_string(name); //- rjf: gather array of all entities which fit the bill CTRL_EntityArray array = {0}; if(scoping_entity == &ctrl_entity_nil) { array = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, entity_kind); } else { CTRL_EntityList list = {0}; for(CTRL_Entity *child = scoping_entity->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind == entity_kind) { ctrl_entity_list_push(scratch.arena, &list, child); } } array = ctrl_entity_array_from_list(arena, &list); } //- rjf: filter the array CTRL_EntityArray array__filtered = array; if(filter.size != 0) { CTRL_EntityList list__filtered = {0}; for EachIndex(idx, array.count) { CTRL_Entity *entity = array.v[idx]; DR_FStrList fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, entity, 1); String8 title_string = dr_string_from_fstrs(scratch.arena, &fstrs); FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, title_string); if(matches.count == matches.needle_part_count) { ctrl_entity_list_push(scratch.arena, &list__filtered, entity); } } array__filtered = ctrl_entity_array_from_list(arena, &list__filtered); } //- rjf: list -> array & fill CTRL_EntityArray *accel = push_array(arena, CTRL_EntityArray, 1); *accel = array__filtered; result.user_data = accel; result.expr_count = accel->count; } scratch_end(scratch); return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(ctrl_entities) { CTRL_EntityArray *entities = (CTRL_EntityArray *)user_data; Rng1U64 legal_range = r1u64(0, entities->count); Rng1U64 read_range = intersect_1u64(legal_range, idx_range); U64 read_count = dim_1u64(read_range); for(U64 out_idx = 0; out_idx < read_count; out_idx += 1) { Temp scratch = scratch_begin(&arena, 1); CTRL_Entity *entity = entities->v[out_idx + read_range.min]; evals_out[out_idx] = e_eval_from_stringf("query:control.%S", ctrl_string_from_handle(scratch.arena, entity->handle)); scratch_end(scratch); } } //////////////////////////////// //~ rjf: Call Stack Tree Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(call_stack_tree) { E_IRTreeAndType result = {&e_irnode_nil}; if(expr->kind == E_ExprKind_MemberAccess) { String8 id_string = expr->first->next->string; U64 id = u64_from_str8(str8_skip(id_string, 1), 16); if(id != 0) { result.type_key = lhs_irtree->type_key; result.mode = E_Mode_Value; result.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCallStackTree), e_irtree_const_u(arena, id)); } } return result; } typedef struct RD_CallStackTreeExpandAccel RD_CallStackTreeExpandAccel; struct RD_CallStackTreeExpandAccel { CTRL_CallStackTreeNode *node; CTRL_CallStackTreeNode **children; CTRL_HandleArray threads; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack_tree) { Access *access = access_open(); CTRL_CallStackTree call_stack_tree = ctrl_call_stack_tree(access, 0); access_close(access); RD_CallStackTreeExpandAccel *accel = push_array(arena, RD_CallStackTreeExpandAccel, 1); accel->node = &ctrl_call_stack_tree_node_nil; U64 id = e_value_eval_from_eval(eval).value.u64; if(call_stack_tree.slots_count != 0) { for(CTRL_CallStackTreeNode *n = call_stack_tree.slots[id%call_stack_tree.slots_count]; n != 0; n = n->hash_next) { if(n->id == id) { accel->node = n; break; } } } accel->children = push_array(arena, CTRL_CallStackTreeNode *, accel->node->child_count); { U64 idx = 0; for(CTRL_CallStackTreeNode *n = accel->node->first; n != &ctrl_call_stack_tree_node_nil; n = n->next, idx += 1) { accel->children[idx] = n; } } accel->threads = ctrl_handle_array_from_list(arena, &accel->node->threads); E_TypeExpandInfo result = {accel}; result.expr_count = accel->node->child_count + accel->threads.count; return result; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(call_stack_tree) { Temp scratch = scratch_begin(&arena, 1); RD_CallStackTreeExpandAccel *accel = (RD_CallStackTreeExpandAccel *)user_data; CTRL_CallStackTreeNode *node = accel->node; U64 needed_row_count = dim_1u64(idx_range); for EachIndex(idx, needed_row_count) { E_Eval eval = e_eval_nil; if(idx < node->child_count) { eval = e_eval_from_stringf("query:call_stack_tree.$%I64x", accel->children[idx]->id); } else if(node->child_count <= idx && idx < node->child_count + accel->threads.count) { eval = e_eval_from_stringf("query:control.%S", ctrl_string_from_handle(scratch.arena, accel->threads.v[idx - node->child_count])); } evals_out[idx] = eval; } scratch_end(scratch); } //////////////////////////////// //~ rjf: Debug Info Tables Eval Hooks typedef struct RD_DebugInfoTableLookupAccel RD_DebugInfoTableLookupAccel; struct RD_DebugInfoTableLookupAccel { RDI_SectionKind section; DI_SearchItemArray items; }; E_TYPE_EXPAND_INFO_FUNCTION_DEF(debug_info_table) { Temp scratch = scratch_begin(&arena, 1); // rjf: determine which debug info section we're dealing with RDI_SectionKind section = RDI_SectionKind_NULL; { E_TypeKey lhs_type_key = eval.irtree.type_key; E_Type *lhs_type = e_type_from_key(lhs_type_key); if(0){} else if(str8_match(lhs_type->name, str8_lit("procedures"), 0)) {section = RDI_SectionKind_Procedures;} else if(str8_match(lhs_type->name, str8_lit("globals"), 0)) {section = RDI_SectionKind_GlobalVariables;} else if(str8_match(lhs_type->name, str8_lit("thread_locals"), 0)) {section = RDI_SectionKind_ThreadVariables;} else if(str8_match(lhs_type->name, str8_lit("constants"), 0)) {section = RDI_SectionKind_Constants;} else if(str8_match(lhs_type->name, str8_lit("types"), 0)) {section = RDI_SectionKind_UDTs;} else if(str8_match(lhs_type->name, str8_lit("source_files"), 0)) {section = RDI_SectionKind_SourceFiles;} } // rjf: gather debug info table items RD_DebugInfoTableLookupAccel *accel = push_array(arena, RD_DebugInfoTableLookupAccel, 1); if(section != RDI_SectionKind_NULL) { U64 endt_us = rd_state->frame_eval_memread_endt_us; B32 stale = 0; accel->section = section; accel->items = di_search_item_array_from_target_query(rd_state->frame_access, section, filter, endt_us, &stale); CFG_Node *last_successful_query_cfg = rd_immediate_cfg_from_keyf("last_successful_query_%I64x_%I64u", rd_regs()->view, (U64)section); if(stale) { String8 last_query = last_successful_query_cfg->first->string; accel->items = di_search_item_array_from_target_query(rd_state->frame_access, section, last_query, endt_us, 0); rd_request_frame(); } else { cfg_node_new_replace(rd_state->cfg, last_successful_query_cfg, filter); } } E_TypeExpandInfo info = {accel, accel->items.count}; scratch_end(scratch); return info; } E_TYPE_EXPAND_RANGE_FUNCTION_DEF(debug_info_table) { Temp scratch = scratch_begin(&arena, 1); RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; U64 needed_row_count = dim_1u64(idx_range); for EachIndex(idx, needed_row_count) { Access *access = access_open(); // rjf: unpack row DI_SearchItem *item = &accel->items.v[idx_range.min + idx]; RDI_Parsed *rdi = di_rdi_from_key(access, item->key, 0, 0); // rjf: get item's string String8 item_string = {0}; B32 item_is_path = 0; { U64 element_idx = item->idx; switch(accel->section) { default:{}break; case RDI_SectionKind_Procedures: { RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, element_idx); String8 symbol_name = {0}; symbol_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &symbol_name.size); item_string = symbol_name; }break; case RDI_SectionKind_GlobalVariables: { RDI_GlobalVariable *gvar = rdi_element_from_name_idx(rdi, GlobalVariables, element_idx); String8 symbol_name = {0}; symbol_name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &symbol_name.size); item_string = symbol_name; }break; case RDI_SectionKind_ThreadVariables: { RDI_ThreadVariable *tvar = rdi_element_from_name_idx(rdi, ThreadVariables, element_idx); String8 symbol_name = {0}; symbol_name.str = rdi_string_from_idx(rdi, tvar->name_string_idx, &symbol_name.size); item_string = symbol_name; }break; case RDI_SectionKind_Constants: { RDI_Constant *cnst = rdi_element_from_name_idx(rdi, Constants, element_idx); String8 symbol_name = {0}; symbol_name.str = rdi_string_from_idx(rdi, cnst->name_string_idx, &symbol_name.size); item_string = symbol_name; }break; case RDI_SectionKind_UDTs: { RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, element_idx); RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); String8 name = {0}; name.str = rdi_string_from_idx(rdi, type_node->user_defined.name_string_idx, &name.size); item_string = name; }break; case RDI_SectionKind_SourceFiles: { RDI_SourceFile *sf = rdi_element_from_name_idx(rdi, SourceFiles, element_idx); String8List path_parts = {0}; for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(rdi, FilePathNodes, sf->file_path_node_idx); fpn != rdi_element_from_name_idx(rdi, FilePathNodes, 0); fpn = rdi_element_from_name_idx(rdi, FilePathNodes, fpn->parent_path_node)) { String8 path_part = {0}; path_part.str = rdi_string_from_idx(rdi, fpn->name_string_idx, &path_part.size); str8_list_push_front(scratch.arena, &path_parts, path_part); } StringJoin join = {0}; join.sep = str8_lit("/"); item_string = str8_list_join(scratch.arena, &path_parts, &join); item_is_path = 1; }break; } } // rjf: build a valid expression string given item string String8 item_expr = item_string; if(item_is_path) { item_expr = push_str8f(scratch.arena, "file:\"%S\"", item_string); } else { B32 string_can_be_evalled = 1; E_TokenArray tokens = e_token_array_from_text(scratch.arena, item_string); for EachIndex(idx, tokens.count) { String8 token_string = str8_substr(item_string, tokens.v[idx].range); if(tokens.v[idx].kind != E_TokenKind_Identifier && !str8_match(token_string, str8_lit("."), 0)) { string_can_be_evalled = 0; break; } } if(!string_can_be_evalled) { item_expr = push_str8f(scratch.arena, "`%S`", item_string); } } // rjf: item's eval E_Eval item_eval = e_eval_from_string(item_expr); // rjf: fill evals_out[idx] = item_eval; temp_end(scratch); access_close(access); } scratch_end(scratch); } E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(debug_info_table) { RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; U64 id = 0; if(0 < num && num <= accel->items.count) { U64 hash = 5381; hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[num-1].key.u64[0])); hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[num-1].key.u64[1])); hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[num-1].idx)); id = hash; } return id; } E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(debug_info_table) { RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; U64 num = 0; for EachIndex(idx, accel->items.count) { U64 hash = 5381; hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[idx].key.u64[0])); hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[idx].key.u64[1])); hash = u64_hash_from_seed_str8(hash, str8_struct(&accel->items.v[idx].idx)); if(hash == id) { num = idx+1; break; } } return num; } ================================================ FILE: src/raddbg/raddbg_eval.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_EVAL_H #define RADDBG_EVAL_H //////////////////////////////// //~ rjf: `commands` Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(commands); E_TYPE_EXPAND_INFO_FUNCTION_DEF(commands); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(commands); //////////////////////////////// //~ rjf: `themes` Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(themes); E_TYPE_EXPAND_INFO_FUNCTION_DEF(themes); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(themes); //////////////////////////////// //~ rjf: `locals` Type Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(locals); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(locals); //////////////////////////////// //~ rjf: `registers` Type Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(registers); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(registers); //////////////////////////////// //~ rjf: Schema Type Hooks E_TYPE_IREXT_FUNCTION_DEF(schema); E_TYPE_ACCESS_FUNCTION_DEF(schema); E_TYPE_EXPAND_INFO_FUNCTION_DEF(schema); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(schema); //////////////////////////////// //~ rjf: Config Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(cfgs); //////////////////////////////// //~ rjf: Control Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(control); //////////////////////////////// //~ rjf: Config Slice Type Hooks E_TYPE_IREXT_FUNCTION_DEF(cfgs_slice); E_TYPE_EXPAND_INFO_FUNCTION_DEF(cfgs_query); E_TYPE_ACCESS_FUNCTION_DEF(cfgs_slice); E_TYPE_EXPAND_INFO_FUNCTION_DEF(cfgs_slice); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(cfgs_slice); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(cfgs_slice); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(cfgs_slice); //////////////////////////////// //~ rjf: `call_stack` Type Hooks E_TYPE_IREXT_FUNCTION_DEF(call_stack); E_TYPE_ACCESS_FUNCTION_DEF(call_stack); E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack); //////////////////////////////// //~ rjf: `environment` Type Hooks E_TYPE_IREXT_FUNCTION_DEF(environment); E_TYPE_ACCESS_FUNCTION_DEF(environment); E_TYPE_EXPAND_INFO_FUNCTION_DEF(environment); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(environment); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(environment); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(environment); //////////////////////////////// //~ rjf: `watches` Type Hooks E_TYPE_IREXT_FUNCTION_DEF(watches); E_TYPE_ACCESS_FUNCTION_DEF(watches); E_TYPE_EXPAND_INFO_FUNCTION_DEF(watches); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(watches); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(watches); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(watches); //////////////////////////////// //~ rjf: `unattached_processes` Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(unattached_processes); E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes); //////////////////////////////// //~ rjf: Control Entity List Type Hooks (`processes`, `threads`, etc.) E_TYPE_ACCESS_FUNCTION_DEF(ctrl_entities); E_TYPE_EXPAND_INFO_FUNCTION_DEF(ctrl_entities); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(ctrl_entities); //////////////////////////////// //~ rjf: Call Stack Tree Type Hooks E_TYPE_ACCESS_FUNCTION_DEF(call_stack_tree); E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack_tree); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(call_stack_tree); //////////////////////////////// //~ rjf: Debug Info Tables Eval Hooks E_TYPE_EXPAND_INFO_FUNCTION_DEF(debug_info_table); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(debug_info_table); E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(debug_info_table); E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(debug_info_table); #endif // RADDBG_EVAL_H ================================================ FILE: src/raddbg/raddbg_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "raddbg_core.c" #include "raddbg_eval.c" #include "raddbg_widgets.c" #include "raddbg_views.c" #include "raddbg_legacy_config.c" ================================================ FILE: src/raddbg/raddbg_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_INC_H #define RADDBG_INC_H #include "raddbg_core.h" #include "raddbg_eval.h" #include "raddbg_widgets.h" #include "raddbg_views.h" #include "raddbg_legacy_config.h" #endif // RADDBG_INC_H ================================================ FILE: src/raddbg/raddbg_legacy_config.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal CFG_NodePtrList rd_cfg_tree_list_from_string__pre_0_9_16(Arena *arena, String8 file_path, String8 data) { CFG_NodePtrList result = {0}; { Temp scratch = scratch_begin(&arena, 1); String8 folder_path = str8_skip_last_slash(file_path); MD_Node *src_root = md_parse_from_text(scratch.arena, file_path, data).root; { for MD_EachNode(tln, src_root->first) { //- rjf: targets if(str8_match(tln->string, str8_lit("target"), 0)) { String8 disabled_string = md_child_from_string(tln, str8_lit("disabled"), 0)->first->string; String8 executable = md_child_from_string(tln, str8_lit("executable"), 0)->first->string; String8 arguments = md_child_from_string(tln, str8_lit("arguments"), 0)->first->string; String8 working_directory = md_child_from_string(tln, str8_lit("working_directory"), 0)->first->string; String8 entry_point = md_child_from_string(tln, str8_lit("entry_point"), 0)->first->string; String8 stdout_path = md_child_from_string(tln, str8_lit("stdout_path"), 0)->first->string; String8 stderr_path = md_child_from_string(tln, str8_lit("stderr_path"), 0)->first->string; String8 stdin_path = md_child_from_string(tln, str8_lit("stdin_path"), 0)->first->string; String8 debug_subprocesses= md_child_from_string(tln, str8_lit("debug_subprocesses"), 0)->first->string; CFG_Node *dst_root = cfg_node_new(rd_state->cfg, &cfg_nil_node, str8_lit("target")); cfg_node_ptr_list_push(arena, &result, dst_root); { if(executable.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("executable")), path_absolute_dst_from_relative_dst_src(scratch.arena, executable, folder_path)); } if(arguments.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("arguments")), raw_from_escaped_str8(scratch.arena, arguments)); } if(working_directory.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("working_directory")), path_absolute_dst_from_relative_dst_src(scratch.arena, working_directory, folder_path)); } if(entry_point.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("entry_point")), raw_from_escaped_str8(scratch.arena, entry_point)); } if(stdout_path.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("stdout_path")), path_absolute_dst_from_relative_dst_src(scratch.arena, stdout_path, folder_path)); } if(stderr_path.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("stderr_path")), path_absolute_dst_from_relative_dst_src(scratch.arena, stderr_path, folder_path)); } if(stdin_path.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("stdin_path")), path_absolute_dst_from_relative_dst_src(scratch.arena, stdin_path, folder_path)); } if(debug_subprocesses.size != 0) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("debug_subprocesses")), raw_from_escaped_str8(scratch.arena, debug_subprocesses)); } if(!str8_match(disabled_string, str8_lit("1"), 0)) { cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("enabled")), str8_lit("1")); } } } //- rjf: recent files / projects if(str8_match(tln->string, str8_lit("recent_file"), 0) || str8_match(tln->string, str8_lit("recent_project"), 0)) { CFG_Node *dst_root = cfg_node_new(rd_state->cfg, &cfg_nil_node, tln->string); cfg_node_ptr_list_push(arena, &result, dst_root); cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("path")), path_absolute_dst_from_relative_dst_src(scratch.arena, tln->first->string, folder_path)); } //- rjf: file path maps if(str8_match(tln->string, str8_lit("file_path_map"), 0)) { String8 source = md_child_from_string(tln, str8_lit("source"), 0)->first->string; String8 dest = md_child_from_string(tln, str8_lit("dest"), 0)->first->string; CFG_Node *dst_root = cfg_node_new(rd_state->cfg, &cfg_nil_node, tln->string); cfg_node_ptr_list_push(arena, &result, dst_root); cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("source")), path_absolute_dst_from_relative_dst_src(scratch.arena, source, folder_path)); cfg_node_new(rd_state->cfg, cfg_node_new(rd_state->cfg, dst_root, str8_lit("dest")), path_absolute_dst_from_relative_dst_src(scratch.arena, dest, folder_path)); } } } scratch_end(scratch); } return result; } ================================================ FILE: src/raddbg/raddbg_legacy_config.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_LEGACY_CONFIG_H #define RADDBG_LEGACY_CONFIG_H internal CFG_NodePtrList rd_cfg_tree_list_from_string__pre_0_9_16(Arena *arena, String8 file_path, String8 data); #endif // RADDBG_LEGACY_CONFIG_H ================================================ FILE: src/raddbg/raddbg_main.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: post-0.9.20 TODO notes // //- urgent fixes // [ ] (use msvc assert as an example) show fastfail exception info (code, name, etc.) - comes from ExceptionInformation @fastfail // [ ] stepping w/ spoofs & shadow stack enabled - writing spoof will send a stack buffer overrun event @shadow_stack_step // [ ] hardware breakpoints regression (global eval in ctrl) // [ ] native filesystem dialog, resizing raddbg window -> crash! // [ ] stdout/stderr path target setting is now busted >:( // [ ] target ui entry point should override built-in entry point // [ ] list of all tabs in palette // [ ] u64 + (ptr - ptr) seems to produce unexpected results - double check with C rules? // //- flow notes // [ ] "skip breakpoint, run to source", when stopped at a non-source location // [ ] adjust menu bar rendering when not focused // [ ] treat int 0x29 similarly to int3 // [ ] auto_step, launching terminal, terminal steals focus from debugger... // //- memory view // [ ] have smaller visible range than entire memory space, within some bounds (e.g. 64KB) // [ ] dynamically expand memory space, based on scrolling // [ ] fix clicking through occluded panels etc. // [ ] disambiguate . character in ASCII columns // [ ] fix type intepretations of cursor in bottom pane // //- watch improvements // [ ] *ALL* expressions in watch windows need to be editable. // //- cfg improvements // [ ] config hot-reloading, using cfg wins // [ ] undo/redo, using cfg wins // [ ] back/forward, using cfg wins // [ ] mouse back button should make view to go back after I double clicked // on function to open it // [ ] expand %environment_variables% in target environment strings - is there // a way we can defer to the underlying shell in a non-horrible way...? // //- stepping or breakpoint oddness/fixes // [ ] halting during a spoof-ridden step leaves the spoofs in place!!! // (repro via LOTS of code on one line & halting) // [ ] stepping-onto a line with a conditional breakpoint, which fails, causes a // single step over the first instruction of that line, even if the thread // would've stopped at the first instruction due to the step, were that bp not // there. // [ ] breakpoints in optimized code? maybe early-terminating bp resolution loop? @bpmiss // - actually this seems to be potentially because of incomplete src-line-map info... // [ ] Mohit-reported breakpoint not hitting - may be similar thing to @bpmiss // //- ui improvements // [ ] we probably want to disable pop/pull out for transient things, e.g. theme color cfgs // (actually, just kill the tabs on load if they refer to transient things) // [ ] universal ctx menu address/watch options; e.g. watch -> memory; watch -> add watch // [ ] rich hover coverage; bitmap <-> geo <-> memory <-> disassembly <-> text; etc. // [ ] tooltip coverage pass (row commands, etc.) // [ ] visualize all breakpoints everywhere - source view should show up in // disasm, disasm should show up in source view, function should show up in // both, etc. // [ ] ** Function breakpoints should show up in the source listing. Without // them being visible, it is confusing when you run and you stop there, // because you're like "wait why did it stop" and then you later remember // that's because there was a function breakpoint there. // [ ] (reported by forrest) 'set-next-statement' -> prioritize current // module/symbol, in cases where one line maps to many voffs // [ ] "Browse..." buttons should adopt a more relevant starting search path, // if possible // [ ] (since browse buttons are currently gone i should just add them backin // while respecting this old todo) // [ ] For the Scheduler window, it would be nice if you could dim or // folderize threads that are not your threads - eg., if a thread doesn't // have any resolved stack pointers in your executable code, then you can // ignore it when you are focusing on your own code. I don't know what the // best way to detect this is, other than by walking the call stack... one // way might be to just have a way to separate threads you've named from // threads you haven't? Or, there could even be a debugger-specific API // that you use to tag them. Just some way that would make it easier to // focus on your own threads. // [ ] use backslashes on windows by default, forward slashes elsewhere (?) // [ ] For theme editing, when you hove the mouse over a theme color entry and // it highlights that entry, it might help to temporarily change that // color to white (or the inverse of the background color, or whatever) so // that the user can see what things on the screen use that theme color. // [ ] The hex format for color values in the config file was a real // mindbender. It's prefixed with "0x", so I was assuming it was either // Windows Big Endian (0xAARRGGBB) or Mac Little Endian (0xAABBGGRR). To // my surprise, it was neither - it was actually web format (RRGGBBAA), // which I was not expecting because that is normally written with a // number sign (#AARRGGBB) not an 0x. // [ ] It'd be nice to have a "goto byte" option for source views, for jumping // to error messages that are byte-based instead of line-based. // [ ] Clicking on either side of a scroll bar is idiosyncratic. Normally, // that is "page up" / "page down", but here it is "smooth scroll upward" // / "smooth scroll downward" for some reason? // [ ] Alt+8 to switch to disassembly would be nice (regardless on which // panel was previous, don't want to use ctrl+, multiple times) // Alt+8 for disasm and Alt+6 for memory view are shortcuts I often use // in VS // [ ] default font size is too small for me - not only source code, but // menus/tab/watch names (which don't resize). Maybe you could query // Windows for initial font size? // [ ] globally disable/configure default view rule-like things (string // viz for u8s in particular) // [ ] fancy string runs can include "weakness" information for text truncation // ... can prioritize certain parts of strings to be truncated before // others. would be good for e.g. the middle of a path // //- visualizer improvements // [ ] disasm starting address - need to use debug info for more correct results... // [ ] multidimensional `array` // [ ] 2-vector, 3-vector, quaternion // [ ] audio waveform views // //- eval improvements // [ ] maybe add extra caching layer to process memory querying? we pay a pretty // heavy cost even to just read 8 bytes... // [ ] serializing eval view maps (?) // [ ] EVAL LOOKUP RULES -> currently going 0 -> rdis_count, but we need // to prioritize the primary rdi // [ ] wide transforms // [ ] sum // [ ] plot // [ ] max view rule // [ ] min view rule // [ ] histogram view rule // [ ] diffs? // [ ] ** One very nice feature of RemedyBG that I use all the time is the // ability to put "$err, hr" into the watch window, which will just show // the value of GetLastError() as a string. This is super useful for // debugging, so you don't have to litter your own code with it. // (NOTE(rjf): NtQueryInformationThread) // [ ] C++ virtual inheritance member visualization // [ ] smart scopes - expression operators for "grab me the first type X" // [ ] "pinning" watch expressions, to attach it to a particular scope/evaluation context // //- control improvements // [ ] debug info overrides (both path-based AND module-based) // [ ] symbol server // [ ] can it ignore stepping into _RTC_CheckStackVars generated functions? // [ ] jump table thunks, on code w/o /INCREMENTAL:NO // [ ] investigate /DEBUG:FASTLINK - can we somehow alert that we do not // support it? // [ ] just-in-time debugging // [ ] step-out-of-loop // //- late-conversion performance improvements // [ ] live++ investigations - ctrl+alt+f11 in UE? // //- short-to-medium term future features // [ ] search-in-all-files // [ ] automatically snap to search matches when searching source files // [ ] memory view // [ ] memory view mutation controls // [ ] memory view user-made annotations // [ ] memory view searching // [ ] disasm view // [ ] visualize jump destinations in disasm // //- longer-term future features // [ ] long-term future notes from martins // [ ] core dump saving/loading // [ ] parallel call stacks view // [ ] parallel watch view // [ ] mixed native/interpreted/jit debugging // - it seems python has a top-level linked list of interpreter states, // which should allow the debugger to map native callstacks to python // code // //- code cleanup // [ ] eliminate explicit font parameters in the various ui paths (e.g. // code slice params) // [ ] font cache eviction (both for font tags, closing fp handles, and // rasterizations) //////////////////////////////// //~ rjf: Build Options #define BUILD_TITLE "The RAD Debugger" #define OS_FEATURE_GRAPHICAL 1 #define DMN_INIT_MANUAL 1 #define CTRL_INIT_MANUAL 1 #define OS_GFX_INIT_MANUAL 1 #define FP_INIT_MANUAL 1 #define R_INIT_MANUAL 1 #define FNT_INIT_MANUAL 1 #define D_INIT_MANUAL 1 #define RD_INIT_MANUAL 1 //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "x64/x64.h" #include "linker/hash_table.h" #include "os/os_inc.h" #include "artifact_cache/artifact_cache.h" #include "rdi/rdi_local.h" #include "rdi_make/rdi_make_local.h" #include "mdesk/mdesk.h" #include "config/config_inc.h" #include "content/content.h" #include "file_stream/file_stream.h" #include "text/text.h" #include "mutable_text/mutable_text.h" #include "coff/coff.h" #include "coff/coff_parse.h" #include "pe/pe.h" #include "elf/elf.h" #include "gnu/gnu.h" #include "elf/elf_parse.h" #include "elf/elf_dump.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" #include "msf/msf_parse.h" #include "pdb/pdb.h" #include "pdb/pdb_parse.h" #include "pdb/pdb_stringize.h" #include "dwarf/dwarf_inc.h" #include "rdi_from_coff/rdi_from_coff.h" #include "rdi_from_elf/rdi_from_elf.h" #include "rdi_from_pdb/rdi_from_pdb.h" #include "rdi_from_dwarf/rdi_from_dwarf.h" #include "radbin/radbin.h" #include "regs/regs.h" #include "regs/rdi/regs_rdi.h" #include "dbg_info/dbg_info.h" #include "disasm/disasm.h" #include "stap/stap_parse.h" #include "demon/demon_inc.h" #include "eval/eval_inc.h" #include "eval_visualization/eval_visualization_inc.h" #include "ctrl/ctrl_inc.h" #include "font_provider/font_provider_inc.h" #include "render/render_inc.h" #include "font_cache/font_cache.h" #include "draw/draw.h" #include "ui/ui_inc.h" #include "dbg_engine/dbg_engine_inc.h" #include "raddbg/raddbg_inc.h" //- rjf: [c] #include "base/base_inc.c" #include "x64/x64.c" #include "linker/hash_table.c" #include "os/os_inc.c" #include "artifact_cache/artifact_cache.c" #include "rdi/rdi_local.c" #include "rdi_make/rdi_make_local.c" #include "mdesk/mdesk.c" #include "config/config_inc.c" #include "content/content.c" #include "file_stream/file_stream.c" #include "text/text.c" #include "mutable_text/mutable_text.c" #include "coff/coff.c" #include "coff/coff_parse.c" #include "pe/pe.c" #include "elf/elf.c" #include "gnu/gnu.c" #include "elf/elf_parse.c" #include "elf/elf_dump.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c" #include "msf/msf_parse.c" #include "pdb/pdb.c" #include "pdb/pdb_parse.c" #include "pdb/pdb_stringize.c" #include "dwarf/dwarf_inc.c" #include "rdi_from_coff/rdi_from_coff.c" #include "rdi_from_elf/rdi_from_elf.c" #include "rdi_from_pdb/rdi_from_pdb.c" #include "rdi_from_dwarf/rdi_from_dwarf.c" #include "radbin/radbin.c" #include "regs/regs.c" #include "regs/rdi/regs_rdi.c" #include "dbg_info/dbg_info.c" #include "disasm/disasm.c" #include "stap/stap_parse.c" #include "demon/demon_inc.c" #include "eval/eval_inc.c" #include "eval_visualization/eval_visualization_inc.c" #include "ctrl/ctrl_inc.c" #include "font_provider/font_provider_inc.c" #include "render/render_inc.c" #include "font_cache/font_cache.c" #include "draw/draw.c" #include "ui/ui_inc.c" #include "dbg_engine/dbg_engine_inc.c" #include "raddbg/raddbg_inc.c" //////////////////////////////// //~ rjf: Top-Level Execution Types typedef enum ExecMode { ExecMode_Normal, ExecMode_IPCSender, ExecMode_BinaryUtility, ExecMode_Help, } ExecMode; typedef struct IPCInfo IPCInfo; struct IPCInfo { U64 msg_size; }; //////////////////////////////// //~ rjf: Globals //- rjf: IPC resources #define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); global Semaphore ipc_sender2main_signal_semaphore = {0}; global Semaphore ipc_sender2main_lock_semaphore = {0}; global U8 *ipc_sender2main_shared_memory_base = 0; global Semaphore ipc_main2sender_signal_semaphore = {0}; global Semaphore ipc_main2sender_lock_semaphore = {0}; global U8 *ipc_main2sender_shared_memory_base = 0; global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; global U64 ipc_s2m_ring_write_pos = 0; global U64 ipc_s2m_ring_read_pos = 0; global Mutex ipc_s2m_ring_mutex = {0}; global CondVar ipc_s2m_ring_cv = {0}; //////////////////////////////// //~ rjf: IPC Signaler Thread internal void ipc_signaler_thread__entry_point(void *p) { ThreadNameF("rd_ipc_signaler_thread"); for(;;) { if(os_semaphore_take(ipc_sender2main_signal_semaphore, max_U64)) { if(os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); MutexScope(ipc_s2m_ring_mutex) for(;;) { U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos; U64 available_size = (sizeof(ipc_s2m_ring_buffer) - unconsumed_size); if(available_size >= sizeof(U64)+sizeof(msg.size)) { ipc_s2m_ring_write_pos += ring_write_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, &msg.size); ipc_s2m_ring_write_pos += ring_write(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, msg.str, msg.size); break; } cond_var_wait(ipc_s2m_ring_cv, ipc_s2m_ring_mutex, max_U64); } cond_var_broadcast(ipc_s2m_ring_cv); os_send_wakeup_event(); ipc_info->msg_size = 0; os_semaphore_drop(ipc_sender2main_lock_semaphore); } } } } //////////////////////////////// //~ rjf: Ctrl -> Main Thread Wakeup Hook internal CTRL_WAKEUP_FUNCTION_DEF(wakeup_hook_ctrl) { os_send_wakeup_event(); } //////////////////////////////// //~ rjf: Per-Frame Entry Point internal B32 frame(void) { rd_frame(); return rd_state->quit; } //////////////////////////////// //~ rjf: Entry Point internal void entry_point(CmdLine *cmd_line) { Temp scratch = scratch_begin(0, 0); //- rjf: unpack command line arguments ExecMode exec_mode = ExecMode_Normal; B32 auto_run = 0; B32 auto_step = 0; B32 jit_attach = 0; U64 jit_pid = 0; U64 jit_code = 0; U64 jit_addr = 0; { if(cmd_line_has_flag(cmd_line, str8_lit("ipc"))) { exec_mode = ExecMode_IPCSender; } else if(cmd_line_has_flag(cmd_line, str8_lit("bin"))) { exec_mode = ExecMode_BinaryUtility; } else if(cmd_line_has_flag(cmd_line, str8_lit("?")) || cmd_line_has_flag(cmd_line, str8_lit("help"))) { exec_mode = ExecMode_Help; } auto_run = cmd_line_has_flag(cmd_line, str8_lit("auto_run")); auto_step = cmd_line_has_flag(cmd_line, str8_lit("auto_step")); String8 jit_pid_string = cmd_line_string(cmd_line, str8_lit("jit_pid")); String8 jit_code_string = cmd_line_string(cmd_line, str8_lit("jit_code")); String8 jit_addr_string = cmd_line_string(cmd_line, str8_lit("jit_addr")); try_u64_from_str8_c_rules(jit_pid_string, &jit_pid); try_u64_from_str8_c_rules(jit_code_string, &jit_code); try_u64_from_str8_c_rules(jit_addr_string, &jit_addr); jit_attach = (jit_addr != 0); } //- rjf: dispatch to top-level codepath based on execution mode switch(exec_mode) { //- rjf: normal execution default: case ExecMode_Normal: { //- rjf: windows -> turn off output handles, as we need to control those for target processes #if OS_WINDOWS HANDLE output_handles[3] = { GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE), }; for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) { B32 duplicate = 0; for(U64 idx2 = 0; idx2 < idx; idx2 += 1) { if(output_handles[idx2] == output_handles[idx]) { duplicate = 1; break; } } if(duplicate) { output_handles[idx] = 0; } } for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) { if(output_handles[idx] != 0) { CloseHandle(output_handles[idx]); } } SetStdHandle(STD_INPUT_HANDLE, 0); SetStdHandle(STD_OUTPUT_HANDLE, 0); SetStdHandle(STD_ERROR_HANDLE, 0); #endif //- rjf: manual layer initialization { dmn_init(); ctrl_init(); os_gfx_init(); fp_init(); r_init(cmd_line); fnt_init(); d_init(); rd_init(cmd_line); ctrl_set_wakeup_hook(wakeup_hook_ctrl); } //- rjf: set up shared resources for ipc to this instance; launch IPC signaler thread { Temp scratch = scratch_begin(0, 0); U32 instance_pid = os_get_process_info()->pid; // rjf: set up cross-process sender -> main ring buffer String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", instance_pid); String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", instance_pid); String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", instance_pid); OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); ipc_sender2main_signal_semaphore = semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); ipc_sender2main_lock_semaphore = semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); // rjf: set up cross-process main -> sender ring buffer String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", instance_pid); String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", instance_pid); String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", instance_pid); OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); ipc_main2sender_signal_semaphore = semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); ipc_main2sender_lock_semaphore = semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); // rjf: set up ipc-receiver -> main thread ring buffer; launch signaler thread ipc_s2m_ring_mutex = mutex_alloc(); ipc_s2m_ring_cv = cond_var_alloc(); IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; if(ipc_sender2main_shared_memory_base != 0) { MemoryZeroStruct(ipc_info); thread_launch(ipc_signaler_thread__entry_point, 0); } scratch_end(scratch); } //- rjf: main application loop { for(B32 quit = 0; !quit;) { //- rjf: consume IPC messages, dispatch UI commands B32 ipc_command_frame = 0; { Temp scratch = scratch_begin(0, 0); B32 consumed = 0; String8 msg = {0}; MutexScope(ipc_s2m_ring_mutex) { U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos; if(unconsumed_size >= sizeof(U64)) { consumed = 1; ipc_command_frame = 1; ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size); msg.size = Min(msg.size, unconsumed_size); msg.str = push_array(scratch.arena, U8, msg.size); ipc_s2m_ring_read_pos += ring_read(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, msg.str, msg.size); } } if(consumed) { cond_var_broadcast(ipc_s2m_ring_cv); } if(msg.size != 0) { log_infof("ipc_msg: \"%S\"", msg); RD_WindowState *dst_ws = rd_state->first_window_state; for(RD_WindowState *ws = dst_ws; ws != &rd_nil_window_state; ws = ws->order_next) { if(os_window_is_focused(ws->os)) { dst_ws = ws; break; } } if(dst_ws != &rd_nil_window_state) { dst_ws->window_temporarily_focused_ipc = 1; RD_RegsScope() { if(dst_ws->cfg_id != rd_regs()->window) { Temp scratch = scratch_begin(0, 0); CFG_PanelTree panel_tree = cfg_panel_tree_from_cfg(scratch.arena, cfg_node_from_id(dst_ws->cfg_id)); rd_regs()->window = dst_ws->cfg_id; rd_regs()->panel = panel_tree.focused->cfg->id; rd_regs()->tab = panel_tree.focused->selected_tab->id; rd_regs()->view = panel_tree.focused->selected_tab->id; scratch_end(scratch); } rd_cmd(RD_CmdKind_RunExternalDriverTextCommand, .string = msg); rd_request_frame(); } } } scratch_end(scratch); } //- rjf: update quit = update(); //- rjf: auto run if(auto_run) { auto_run = 0; rd_cmd(RD_CmdKind_Run); } //- rjf: auto step if(auto_step) { auto_step = 0; rd_cmd(RD_CmdKind_StepInto); } //- rjf: jit attach if(jit_attach) { jit_attach = 0; rd_cmd(RD_CmdKind_Attach, .pid = jit_pid); } //- rjf: gather command outputs & write them if(ipc_command_frame) { if(ipc_main2sender_shared_memory_base != 0 && os_semaphore_take(ipc_main2sender_lock_semaphore, os_now_microseconds()+5000000)) { IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; U8 *buffer = (U8 *)(ipc_info+1); U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); StringJoin join = {str8_lit(""), str8_lit("\0"), str8_lit("")}; String8 msg = str8_list_join(scratch.arena, &rd_state->cmd_outputs, &join); ipc_info->msg_size = Min(buffer_max, msg.size); MemoryCopy(buffer, msg.str, ipc_info->msg_size); os_semaphore_drop(ipc_main2sender_signal_semaphore); os_semaphore_drop(ipc_main2sender_lock_semaphore); } } } } }break; //- rjf: inter-process communication message sender case ExecMode_IPCSender: { Temp scratch = scratch_begin(0, 0); //- rjf: grab explicit PID argument U32 dst_pid = 0; if(cmd_line_has_argument(cmd_line, str8_lit("pid"))) { String8 dst_pid_string = cmd_line_string(cmd_line, str8_lit("pid")); U64 dst_pid_u64 = 0; if(dst_pid_string.size != 0 && try_u64_from_str8_c_rules(dst_pid_string, &dst_pid_u64)) { dst_pid = (U32)dst_pid_u64; } } //- rjf: no explicit PID? -> find PID to send message to, by looking for other raddbg instances if(dst_pid == 0) { U32 this_pid = os_get_process_info()->pid; DMN_ProcessIter it = {0}; dmn_process_iter_begin(&it); for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &it, &info);) { if(str8_match(str8_skip_last_slash(str8_chop_last_dot(cmd_line->exe_name)), str8_skip_last_slash(str8_chop_last_dot(info.name)), StringMatchFlag_CaseInsensitive) && this_pid != info.pid) { dst_pid = info.pid; break; } } dmn_process_iter_end(&it); } //- rjf: grab destination instance's shared memory resources String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", dst_pid); String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", dst_pid); String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", dst_pid); OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); ipc_sender2main_signal_semaphore = os_semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); ipc_sender2main_lock_semaphore = os_semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", dst_pid); String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", dst_pid); String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", dst_pid); OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); ipc_main2sender_signal_semaphore = os_semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); ipc_main2sender_lock_semaphore = os_semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); //- rjf: got resources -> write message B32 wrote_message = 0; if(dst_pid != 0 && ipc_sender2main_shared_memory_base != 0 && os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { wrote_message = 1; IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; U8 *buffer = (U8 *)(ipc_info+1); U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); String8List parts = {0}; { for EachIndex(idx, cmd_line->argc-1) { str8_list_push(scratch.arena, &parts, str8_cstring(cmd_line->argv[idx+1])); } } StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; String8 msg = str8_list_join(scratch.arena, &parts, &join); ipc_info->msg_size = Min(buffer_max, msg.size); MemoryCopy(buffer, msg.str, ipc_info->msg_size); os_semaphore_drop(ipc_sender2main_signal_semaphore); os_semaphore_drop(ipc_sender2main_lock_semaphore); } //- rjf: wrote message -> wait for outputs, read outputs String8List outputs = {0}; if(wrote_message && ipc_main2sender_shared_memory_base != 0 && os_semaphore_take(ipc_main2sender_signal_semaphore, os_now_microseconds()+10000000)) { if(os_semaphore_take(ipc_main2sender_lock_semaphore, max_U64)) { IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); U8 split_char = 0; outputs = str8_split(scratch.arena, msg, &split_char, 1, 0); os_semaphore_drop(ipc_main2sender_lock_semaphore); } } //- rjf: write outputs to stdout for(String8Node *n = outputs.first; n != 0; n = n->next) { fwrite(n->string.str, 1, n->string.size, stdout); } fflush(stdout); scratch_end(scratch); }break; //- rjf: built-in binary utility mode case ExecMode_BinaryUtility: { rb_entry_point(cmd_line); di_signal_completion(); }break; //- rjf: help message box case ExecMode_Help: { os_graphical_message(0, str8_lit("The RAD Debugger - Help"), str8_lit("The following options may be used when starting the RAD Debugger from the command line:\n\n" "--user:\n" "Use to specify the location of a user file which should be used. User files are used to store settings for users, including window and panel setups, path mapping, and visual settings. If this file does not exist, it will be created as necessary. This file will be autosaved as user-related changes are made.\n\n" "--project:\n" "Use to specify the location of a project file which should be used. Project files are used to store settings for users and projects. If this file does not exist, it will be created as necessary. This file will be autosaved as project-related changes are made.\n\n" "--auto_step\n" "This will step into all active targets after the debugger initially starts.\n\n" "--auto_run\n" "This will run all active targets after the debugger initially starts.\n\n" "--quit_after_success (or -q)\n" "This will close the debugger automatically after all processes exit, if they all exited successfully (with code 0), and ran with no interruptions.\n\n" "--ipc \n" "This will launch the debugger in the non-graphical IPC mode, which is used to communicate with another running instance of the debugger. The debugger instance will launch, send the specified command, then immediately terminate. This may be used by editors or other programs to control the debugger.\n\n")); }break; } scratch_end(scratch); } ================================================ FILE: src/raddbg/raddbg_views.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Code Views internal void rd_code_view_init(RD_CodeViewState *cv) { ProfBeginFunction(); if(cv->initialized == 0) { cv->initialized = 1; cv->preferred_column = 1; cv->find_text_arena = rd_push_view_arena(); cv->center_cursor = 1; rd_store_view_loading_info(1, 0, 0); } ProfEnd(); } internal RD_CodeViewBuildResult rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags flags, Rng2F32 rect, String8 text_data, TXT_TextInfo *text_info, DASM_LineArray *dasm_lines, Rng1U64 dasm_vaddr_range, DI_Key dasm_dbgi_key) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); ////////////////////////////// //- rjf: unpack state // UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); ////////////////////////////// //- rjf: extract invariants // F32 main_font_size = ui_bottom_font_size(); FNT_Tag code_font = rd_font_from_slot(RD_FontSlot_Code); F32 code_font_size = ui_top_font_size(); F32 code_tab_size = fnt_column_size_from_tag_size(code_font, code_font_size)*rd_setting_u64_from_name(str8_lit("tab_width")); FNT_Metrics code_font_metrics = fnt_metrics_from_tag_size(code_font, code_font_size); F32 code_line_height = ceil_f32(fnt_line_height_from_metrics(&code_font_metrics) * 1.5f); F32 big_glyph_advance = fnt_dim_from_tag_size_string(code_font, code_font_size, 0, 0, str8_lit("H")).x; Vec2F32 panel_box_dim = dim_2f32(rect); F32 scroll_bar_dim = floor_f32(main_font_size*1.5f); Vec2F32 code_area_dim = v2f32(panel_box_dim.x - scroll_bar_dim, panel_box_dim.y - scroll_bar_dim); S64 num_possible_visible_lines = (S64)(code_area_dim.y/code_line_height)+1; CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); B32 do_line_numbers = rd_setting_b32_from_name(str8_lit("show_line_numbers")); ////////////////////////////// //- rjf: unpack information about the viewed source file, if any // String8 file_path = rd_regs()->file_path; String8List file_path_possible_overrides = rd_possible_overrides_from_file_path(scratch.arena, file_path); ////////////////////////////// //- rjf: process commands // for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default: break; case RD_CmdKind_GoToLine: { cv->goto_line_num = cmd->regs->cursor.line; }break; case RD_CmdKind_CenterCursor: { cv->center_cursor = 1; }break; case RD_CmdKind_ContainCursor: { cv->contain_cursor = 1; }break; case RD_CmdKind_Search: { arena_clear(cv->find_text_arena); cv->find_text_fwd = push_str8_copy(cv->find_text_arena, cmd->regs->string); }break; case RD_CmdKind_SearchBackwards: { arena_clear(cv->find_text_arena); cv->find_text_bwd = push_str8_copy(cv->find_text_arena, cmd->regs->string); }break; case RD_CmdKind_FindNext: { String8 string = rd_view_query_input(); arena_clear(cv->find_text_arena); cv->find_text_fwd = push_str8_copy(cv->find_text_arena, string); }break; case RD_CmdKind_FindPrev: { String8 string = rd_view_query_input(); arena_clear(cv->find_text_arena); cv->find_text_bwd = push_str8_copy(cv->find_text_arena, string); }break; case RD_CmdKind_ToggleWatchExpressionAtMouse: { cv->watch_expr_at_mouse = 1; }break; } } ////////////////////////////// //- rjf: set up wrap cache // if(cv->wrap_arena == 0) { cv->wrap_arena = rd_push_view_arena(); } if(cv->wrap_total_vline_count == 0) { arena_clear(cv->wrap_arena); cv->wrap_total_vline_count = text_info->lines_count; cv->wrap_cache_slots_count = text_info->lines_count/64; cv->wrap_cache_slots = push_array(cv->wrap_arena, RD_CodeViewTLineWrapCacheSlot, cv->wrap_cache_slots_count); } ////////////////////////////// //- rjf: determine visible line range / count // Rng1S64 visible_line_num_range = r1s64(scroll_pos.y.idx + (S64)(scroll_pos.y.off) + 1 - !!(scroll_pos.y.off < 0), scroll_pos.y.idx + (S64)(scroll_pos.y.off) + 1 + num_possible_visible_lines); Rng1S64 target_visible_line_num_range = r1s64(scroll_pos.y.idx + 1, scroll_pos.y.idx + 1 + num_possible_visible_lines); U64 visible_line_count = 0; { visible_line_num_range.min = Clamp(1, visible_line_num_range.min, (S64)text_info->lines_count); visible_line_num_range.max = Clamp(1, visible_line_num_range.max, (S64)text_info->lines_count); visible_line_num_range.min = Max(1, visible_line_num_range.min); visible_line_num_range.max = Max(1, visible_line_num_range.max); target_visible_line_num_range.min = Clamp(1, target_visible_line_num_range.min, (S64)text_info->lines_count); target_visible_line_num_range.max = Clamp(1, target_visible_line_num_range.max, (S64)text_info->lines_count); target_visible_line_num_range.min = Max(1, target_visible_line_num_range.min); target_visible_line_num_range.max = Max(1, target_visible_line_num_range.max); visible_line_count = (U64)dim_1s64(visible_line_num_range)+1; } ////////////////////////////// //- rjf: calculate scroll bounds // S64 line_size_x = 0; Rng1S64 scroll_idx_rng[Axis2_COUNT] = {0}; { line_size_x = (text_info->lines_max_size*big_glyph_advance*3)/2; line_size_x = ClampBot(line_size_x, (S64)big_glyph_advance*120); line_size_x = ClampBot(line_size_x, (S64)code_area_dim.x); scroll_idx_rng[Axis2_X] = r1s64(0, line_size_x-(S64)code_area_dim.x); scroll_idx_rng[Axis2_Y] = r1s64(0, (S64)text_info->lines_count-1); } ////////////////////////////// //- rjf: calculate line-range-dependent info // F32 line_num_width_px = 0; if(do_line_numbers) { line_num_width_px = floor_f32(big_glyph_advance * (log10(visible_line_num_range.max) + 3)); } F32 priority_margin_width_px = 0; F32 catchall_margin_width_px = 0; if(flags & RD_CodeViewBuildFlag_Margins) { priority_margin_width_px = floor_f32(big_glyph_advance*3.5f); catchall_margin_width_px = floor_f32(big_glyph_advance*3.5f); } TXT_LineTokensSlice slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, text_info, text_data, visible_line_num_range); ////////////////////////////// //- rjf: selection on single line, no query? -> set search text // if(rd_regs()->cursor.line == rd_regs()->mark.line) { CFG_Node *view = cfg_node_from_id(rd_regs()->view); RD_ViewState *vs = rd_view_state_from_cfg(view); if(!vs->query_is_open) { CFG_Node *query = cfg_node_child_from_string_or_alloc(rd_state->cfg, view, str8_lit("query")); CFG_Node *input = cfg_node_child_from_string_or_alloc(rd_state->cfg, query, str8_lit("input")); String8 text = txt_string_from_info_data_txt_rng(text_info, text_data, txt_rng(rd_regs()->cursor, rd_regs()->mark)); if(text.size < 256) { cfg_node_new_replace(rd_state->cfg, input, text); } else { cfg_node_new_replace(rd_state->cfg, input, str8_zero()); } } } ////////////////////////////// //- rjf: get active search query // String8 search_query = rd_view_query_input(); B32 search_query_is_active = 0; ////////////////////////////// //- rjf: prepare code slice info bundle, for the viewable region of text // RD_CodeSliceParams code_slice_params = {0}; { // rjf: fill basics code_slice_params.flags = RD_CodeSliceFlag_Clickable; if(do_line_numbers) { code_slice_params.flags |= RD_CodeSliceFlag_LineNums; } if(flags & RD_CodeViewBuildFlag_Margins) { code_slice_params.flags |= RD_CodeSliceFlag_PriorityMargin|RD_CodeSliceFlag_CatchallMargin; } code_slice_params.line_num_range = visible_line_num_range; code_slice_params.line_text = push_array(scratch.arena, String8, visible_line_count); code_slice_params.line_ranges = push_array(scratch.arena, Rng1U64, visible_line_count); code_slice_params.line_tokens = push_array(scratch.arena, TXT_TokenArray, visible_line_count); code_slice_params.line_bps = push_array(scratch.arena, CFG_NodePtrList, visible_line_count); code_slice_params.line_ips = push_array(scratch.arena, CTRL_EntityList, visible_line_count); code_slice_params.line_pins = push_array(scratch.arena, CFG_NodePtrList, visible_line_count); code_slice_params.line_vaddrs = push_array(scratch.arena, U64, visible_line_count); code_slice_params.line_infos = push_array(scratch.arena, D_LineList, visible_line_count); code_slice_params.text_info = text_info; code_slice_params.text_data = text_data; code_slice_params.font = code_font; code_slice_params.font_size = code_font_size; code_slice_params.tab_size = code_tab_size; code_slice_params.line_height_px = code_line_height; code_slice_params.search_query = search_query; code_slice_params.priority_margin_width_px = priority_margin_width_px; code_slice_params.catchall_margin_width_px = catchall_margin_width_px; code_slice_params.line_num_width_px = line_num_width_px; code_slice_params.line_text_max_width_px = (F32)line_size_x; code_slice_params.margin_float_off_px = scroll_pos.x.idx + floor_f32(scroll_pos.x.off); // rjf: fill text info { S64 line_num = visible_line_num_range.min; U64 line_idx = visible_line_num_range.min-1; for(U64 visible_line_idx = 0; visible_line_idx < visible_line_count && line_idx < text_info->lines_count; visible_line_idx += 1, line_idx += 1, line_num += 1) { code_slice_params.line_text[visible_line_idx] = str8_substr(text_data, text_info->lines_ranges[line_idx]); code_slice_params.line_ranges[visible_line_idx] = text_info->lines_ranges[line_idx]; code_slice_params.line_tokens[visible_line_idx] = slice.line_tokens[visible_line_idx]; } } // rjf: find visible breakpoints for source code if(!dasm_lines) ProfScope("find visible breakpoints for source code") { CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = bps.first; n != 0; n = n->next) { CFG_Node *bp = n->v; RD_Location loc = rd_location_from_cfg(bp); if(visible_line_num_range.min <= loc.pt.line && loc.pt.line <= visible_line_num_range.max) { for(String8Node *override_n = file_path_possible_overrides.first; override_n != 0; override_n = override_n->next) { if(path_match_normalized(loc.file_path, override_n->string)) { U64 slice_line_idx = (U64)(loc.pt.line-visible_line_num_range.min); cfg_node_ptr_list_push(scratch.arena, &code_slice_params.line_bps[slice_line_idx], bp); break; } } } } } // rjf: find live threads mapping to source code if(!dasm_lines) ProfScope("find live threads mapping to this file") { CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread); for EachIndex(idx, threads.count) { CTRL_Entity *thread = threads.v[idx]; CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); U64 unwind_count = (thread == selected_thread) ? rd_regs()->unwind_count : 0; U64 inline_depth = (thread == selected_thread) ? rd_regs()->inline_depth : 0; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count; CTRL_Entity *module = ctrl_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr); U64 rip_voff = ctrl_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, rip_voff); for(D_LineNode *n = lines.first; n != 0; n = n->next) { if(visible_line_num_range.min <= n->v.pt.line && n->v.pt.line <= visible_line_num_range.max) { for(String8Node *override_n = file_path_possible_overrides.first; override_n != 0; override_n = override_n->next) { if(path_match_normalized(n->v.file_path, override_n->string)) { U64 slice_line_idx = n->v.pt.line-visible_line_num_range.min; ctrl_entity_list_push(scratch.arena, &code_slice_params.line_ips[slice_line_idx], thread); break; } } } } } } // rjf: find visible watch pins for source code if(!dasm_lines) ProfScope("find visible watch pins for source code") { CFG_NodePtrList wps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("watch_pin")); for(CFG_NodePtrNode *n = wps.first; n != 0; n = n->next) { CFG_Node *wp = n->v; RD_Location loc = rd_location_from_cfg(wp); if(visible_line_num_range.min <= loc.pt.line && loc.pt.line <= visible_line_num_range.max) { for(String8Node *override_n = file_path_possible_overrides.first; override_n != 0; override_n = override_n->next) { if(path_match_normalized(loc.file_path, override_n->string)) { U64 slice_line_idx = (loc.pt.line-visible_line_num_range.min); cfg_node_ptr_list_push(scratch.arena, &code_slice_params.line_pins[slice_line_idx], wp); break; } } } } } // rjf: find all src -> dasm info if(!dasm_lines) ProfScope("find all src -> dasm info for source code") { String8 file_path = rd_regs()->file_path; CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->module); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); D_LineListArray lines_array = d_lines_array_from_dbgi_key_file_path_line_range(scratch.arena, dbgi_key, file_path, visible_line_num_range); if(lines_array.count != 0) { MemoryCopy(code_slice_params.line_infos, lines_array.v, sizeof(D_LineList)*lines_array.count); } code_slice_params.relevant_dbgi_keys = lines_array.dbgi_keys; } // rjf: find live threads mapping to disasm if(dasm_lines) ProfScope("find live threads mapping to this disassembly") { CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread); for EachIndex(idx, threads.count) { CTRL_Entity *thread = threads.v[idx]; U64 unwind_count = (thread == selected_thread) ? rd_regs()->unwind_count : 0; U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); if(ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process) == process && contains_1u64(dasm_vaddr_range, rip_vaddr)) { U64 rip_off = rip_vaddr - dasm_vaddr_range.min; S64 line_num = dasm_line_array_idx_from_code_off__linear_scan(dasm_lines, rip_off)+1; if(contains_1s64(visible_line_num_range, line_num)) { U64 slice_line_idx = (line_num-visible_line_num_range.min); ctrl_entity_list_push(scratch.arena, &code_slice_params.line_ips[slice_line_idx], thread); } } } } // rjf: find breakpoints mapping to this disasm if(dasm_lines) ProfScope("find breakpoints mapping to this disassembly") { CFG_NodePtrList bps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); for(CFG_NodePtrNode *n = bps.first; n != 0; n = n->next) { CFG_Node *bp = n->v; RD_Location loc = rd_location_from_cfg(bp); E_Value loc_value = e_value_from_string(loc.expr); if(contains_1u64(dasm_vaddr_range, loc_value.u64)) { U64 off = loc_value.u64 - dasm_vaddr_range.min; U64 idx = dasm_line_array_idx_from_code_off__linear_scan(dasm_lines, off); S64 line_num = (S64)idx+1; if(contains_1s64(visible_line_num_range, line_num)) { U64 slice_line_idx = (line_num-visible_line_num_range.min); cfg_node_ptr_list_push(scratch.arena, &code_slice_params.line_bps[slice_line_idx], bp); } } } } // rjf: find watch pins mapping to this disasm if(dasm_lines) ProfScope("find watch pins mapping to this disassembly") { CFG_NodePtrList wps = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("watch_pin")); for(CFG_NodePtrNode *n = wps.first; n != 0; n = n->next) { CFG_Node *wp = n->v; RD_Location loc = rd_location_from_cfg(wp); E_Value loc_value = e_value_from_string(loc.expr); if(contains_1u64(dasm_vaddr_range, loc_value.u64)) { U64 off = loc_value.u64 - dasm_vaddr_range.min; U64 idx = dasm_line_array_idx_from_code_off__linear_scan(dasm_lines, off); S64 line_num = (S64)idx+1; if(contains_1s64(visible_line_num_range, line_num)) { U64 slice_line_idx = (line_num-visible_line_num_range.min); cfg_node_ptr_list_push(scratch.arena, &code_slice_params.line_pins[slice_line_idx], wp); } } } } // rjf: fill dasm -> src info if(dasm_lines) { CTRL_Entity *module = ctrl_module_from_process_vaddr(process, dasm_vaddr_range.min); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); for(S64 line_num = visible_line_num_range.min; line_num < visible_line_num_range.max; line_num += 1) { U64 vaddr = dasm_vaddr_range.min + dasm_line_array_code_off_from_idx(dasm_lines, line_num-1); U64 voff = ctrl_voff_from_vaddr(module, vaddr); U64 slice_idx = line_num-visible_line_num_range.min; code_slice_params.line_vaddrs[slice_idx] = vaddr; code_slice_params.line_infos[slice_idx] = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff); } } // rjf: add dasm dbgi key to relevant dbgis if(dasm_lines != 0) { di_key_list_push(scratch.arena, &code_slice_params.relevant_dbgi_keys, dasm_dbgi_key); } } ////////////////////////////// //- rjf: build container // UI_Box *container_box = &ui_nil_box; { ui_set_next_pref_width(ui_px(code_area_dim.x, 1)); ui_set_next_pref_height(ui_px(code_area_dim.y, 1)); ui_set_next_child_layout_axis(Axis2_Y); container_box = ui_build_box_from_stringf(UI_BoxFlag_Clip| UI_BoxFlag_Scroll| UI_BoxFlag_AllowOverflowX| UI_BoxFlag_AllowOverflowY, "###code_area"); } ////////////////////////////// //- rjf: cancelled search query -> center cursor // if(!search_query_is_active && cv->drifted_for_search) { cv->drifted_for_search = 0; cv->center_cursor = 1; } ////////////////////////////// //- rjf: do searching operations // { //- rjf: find text (forward) if(cv->find_text_fwd.size != 0) { B32 found = 0; B32 first = 1; S64 line_num_start = rd_regs()->cursor.line; S64 line_num_last = (S64)text_info->lines_count; for(S64 line_num = line_num_start; 1 <= line_num && line_num <= line_num_last; first = 0) { // rjf: gather line info String8 line_string = str8_substr(text_data, text_info->lines_ranges[line_num-1]); U64 search_start = 0; if(rd_regs()->cursor.line == line_num && first) { search_start = rd_regs()->cursor.column; } // rjf: search string U64 needle_pos = str8_find_needle(line_string, search_start, cv->find_text_fwd, StringMatchFlag_CaseInsensitive); if(needle_pos < line_string.size) { rd_regs()->mark.line = line_num; rd_regs()->mark.column = needle_pos+1; rd_regs()->cursor = rd_regs()->mark; rd_regs()->cursor.column += cv->find_text_fwd.size; found = 1; break; } // rjf: break if circled back around to cursor else if(line_num == line_num_start && !first) { break; } // rjf: increment line_num += 1; if(line_num > line_num_last) { line_num = 1; } } cv->center_cursor = found; if(found == 0) { log_user_errorf("Could not find `%S`", cv->find_text_fwd); } } //- rjf: find text (backward) if(cv->find_text_bwd.size != 0) { B32 found = 0; B32 first = 1; TxtRng rng = txt_rng(rd_regs()->cursor, rd_regs()->mark); S64 line_num_start = rng.min.line; S64 line_num_last = (S64)text_info->lines_count; for(S64 line_num = line_num_start; 1 <= line_num && line_num <= line_num_last; first = 0) { // rjf: gather line info String8 line_string = str8_substr(text_data, text_info->lines_ranges[line_num-1]); if(rng.min.line == line_num && first) { line_string = str8_prefix(line_string, rng.min.column-1); } // rjf: search string U64 next_needle_pos = line_string.size; for(U64 needle_pos = 0; needle_pos < line_string.size;) { needle_pos = str8_find_needle(line_string, needle_pos, cv->find_text_bwd, StringMatchFlag_CaseInsensitive); if(needle_pos < line_string.size) { next_needle_pos = needle_pos; needle_pos += 1; } } if(next_needle_pos < line_string.size) { rd_regs()->mark.line = line_num; rd_regs()->mark.column = next_needle_pos+1; rd_regs()->cursor = rd_regs()->mark; rd_regs()->cursor.column += cv->find_text_bwd.size; found = 1; break; } // rjf: break if circled back around to cursor line else if(line_num == line_num_start && !first) { break; } // rjf: increment line_num -= 1; if(line_num == 0) { line_num = line_num_last; } } cv->center_cursor = found; if(found == 0) { log_user_errorf("Could not find `%S`", cv->find_text_bwd); } } MemoryZeroStruct(&cv->find_text_fwd); MemoryZeroStruct(&cv->find_text_bwd); arena_clear(cv->find_text_arena); } ////////////////////////////// //- rjf: do goto line // if(cv->goto_line_num != 0 && text_info->lines_count != 0) { S64 line_num = cv->goto_line_num; cv->goto_line_num = 0; line_num = Clamp(1, line_num, text_info->lines_count); rd_regs()->cursor = rd_regs()->mark = txt_pt(line_num, 1); cv->center_cursor = !cv->force_contain_only && (!cv->contain_cursor || (line_num < target_visible_line_num_range.min+4 || target_visible_line_num_range.max-4 < line_num)); } ////////////////////////////// //- rjf: do keyboard interaction // B32 snap[Axis2_COUNT] = {0}; UI_Focus(UI_FocusKind_On) { if(ui_is_focus_active() && visible_line_num_range.max >= visible_line_num_range.min) { snap[Axis2_X] = snap[Axis2_Y] = rd_do_txt_controls(text_info, text_data, ClampBot(num_possible_visible_lines, 10) - 10, &rd_regs()->cursor, &rd_regs()->mark, &cv->preferred_column); } } ////////////////////////////// //- rjf: build container contents // UI_Parent(container_box) { //- rjf: build fractional space container_box->view_off.x = container_box->view_off_target.x = scroll_pos.x.idx + scroll_pos.x.off; container_box->view_off.y = container_box->view_off_target.y = code_line_height*mod_f32(scroll_pos.y.off, 1.f) + code_line_height*(scroll_pos.y.off < 0) - code_line_height*(scroll_pos.y.off == -1.f && scroll_pos.y.idx == 1); //- rjf: build code slice RD_CodeSliceSignal sig = {0}; UI_Focus(UI_FocusKind_On) { sig = rd_code_slicef(&code_slice_params, &rd_regs()->cursor, &rd_regs()->mark, &cv->preferred_column, "code_slice"); } //- rjf: press code slice? -> focus panel if(ui_pressed(sig.base)) { rd_cmd(RD_CmdKind_FocusPanel); } //- rjf: dragging & outside region? -> contain cursor if(ui_dragging(sig.base) && sig.base.event_flags == 0) { if(!contains_2f32(sig.base.box->rect, ui_mouse())) { cv->contain_cursor = 1; } else { snap[Axis2_X] = 1; } } //- rjf: ctrl+pressed? -> go to name if(ui_pressed(sig.base) && sig.base.event_flags & OS_Modifier_Ctrl) { ui_kill_action(); rd_cmd(RD_CmdKind_GoToName, .string = txt_string_from_info_data_txt_rng(text_info, text_data, sig.mouse_expr_rng)); } //- rjf: watch expr at mouse if(cv->watch_expr_at_mouse) { cv->watch_expr_at_mouse = 0; rd_cmd(RD_CmdKind_ToggleWatchExpression, .string = txt_string_from_info_data_txt_rng(text_info, text_data, sig.mouse_expr_rng)); } } ////////////////////////////// //- rjf: apply post-build view snapping rules // if(text_info->lines_count != 0) { TxtPt cursor = rd_regs()->cursor; B32 cursor_in_range = (1 <= cursor.line && cursor.line <= text_info->lines_count); // rjf: contain => snap if(cv->contain_cursor && text_info->lines_count != 0) { cv->contain_cursor = 0; snap[Axis2_X] = 1; snap[Axis2_Y] = 1; } // rjf: center cursor if(cv->center_cursor && text_info->lines_count != 0) { cv->center_cursor = 0; if(cursor_in_range) { String8 cursor_line = str8_substr(text_data, text_info->lines_ranges[cursor.line-1]); F32 cursor_advance = fnt_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, cursor.column-1)).x; // rjf: scroll x { S64 new_idx = (S64)(cursor_advance - code_area_dim.x/2); new_idx = Clamp(scroll_idx_rng[Axis2_X].min, new_idx, scroll_idx_rng[Axis2_X].max); ui_scroll_pt_target_idx(&scroll_pos.x, new_idx); snap[Axis2_X] = 0; } // rjf: scroll y { S64 new_idx = (cursor.line-1) - num_possible_visible_lines/2 + 2; new_idx = Clamp(scroll_idx_rng[Axis2_Y].min, new_idx, scroll_idx_rng[Axis2_Y].max); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); snap[Axis2_Y] = 0; } } } // rjf: snap in X if(snap[Axis2_X] && cursor_in_range) { String8 cursor_line = str8_substr(text_data, text_info->lines_ranges[cursor.line-1]); S64 cursor_off = (S64)(fnt_dim_from_tag_size_string(code_font, code_font_size, 0, code_tab_size, str8_prefix(cursor_line, cursor.column-1)).x + priority_margin_width_px + catchall_margin_width_px + line_num_width_px); Rng1S64 visible_pixel_range = { scroll_pos.x.idx, scroll_pos.x.idx + (S64)code_area_dim.x, }; Rng1S64 cursor_pixel_range = { cursor_off - (S64)(big_glyph_advance*4) - (S64)(priority_margin_width_px + catchall_margin_width_px + line_num_width_px), cursor_off + (S64)(big_glyph_advance*4), }; S64 min_delta = Min(0, cursor_pixel_range.min - visible_pixel_range.min); S64 max_delta = Max(0, cursor_pixel_range.max - visible_pixel_range.max); S64 new_idx = scroll_pos.x.idx+min_delta+max_delta; new_idx = Clamp(scroll_idx_rng[Axis2_X].min, new_idx, scroll_idx_rng[Axis2_X].max); ui_scroll_pt_target_idx(&scroll_pos.x, new_idx); } // rjf: snap in Y if(snap[Axis2_Y]) { Rng1S64 cursor_visibility_range = r1s64(cursor.line-4, cursor.line+4); cursor_visibility_range.min = ClampBot(0, cursor_visibility_range.min); cursor_visibility_range.max = ClampBot(0, cursor_visibility_range.max); S64 min_delta = Min(0, cursor_visibility_range.min-(target_visible_line_num_range.min)); S64 max_delta = Max(0, cursor_visibility_range.max-(target_visible_line_num_range.min+num_possible_visible_lines)); S64 new_idx = scroll_pos.y.idx+min_delta+max_delta; new_idx = Clamp(0, new_idx, (S64)text_info->lines_count-1); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } } ////////////////////////////// //- rjf: build horizontal scroll bar // { ui_set_next_fixed_x(0); ui_set_next_fixed_y(code_area_dim.y); ui_set_next_fixed_width(panel_box_dim.x - scroll_bar_dim); ui_set_next_fixed_height(scroll_bar_dim); { scroll_pos.x = ui_scroll_bar(Axis2_X, ui_px(scroll_bar_dim, 1.f), scroll_pos.x, scroll_idx_rng[Axis2_X], (S64)code_area_dim.x); } } ////////////////////////////// //- rjf: build vertical scroll bar // { ui_set_next_fixed_x(code_area_dim.x); ui_set_next_fixed_y(0); ui_set_next_fixed_width(scroll_bar_dim); ui_set_next_fixed_height(panel_box_dim.y - scroll_bar_dim); { scroll_pos.y = ui_scroll_bar(Axis2_Y, ui_px(scroll_bar_dim, 1.f), scroll_pos.y, scroll_idx_rng[Axis2_Y], num_possible_visible_lines); } } ////////////////////////////// //- rjf: top-level container interaction (scrolling) // if(text_info->lines_count != 0) { UI_Signal sig = ui_signal_from_box(container_box); if(sig.scroll.x != 0) { S64 new_idx = scroll_pos.x.idx+sig.scroll.x*big_glyph_advance; new_idx = clamp_1s64(scroll_idx_rng[Axis2_X], new_idx); ui_scroll_pt_target_idx(&scroll_pos.x, new_idx); } if(sig.scroll.y != 0) { S64 new_idx = scroll_pos.y.idx + sig.scroll.y; new_idx = clamp_1s64(scroll_idx_rng[Axis2_Y], new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } ui_scroll_pt_clamp_idx(&scroll_pos.x, scroll_idx_rng[Axis2_X]); ui_scroll_pt_clamp_idx(&scroll_pos.y, scroll_idx_rng[Axis2_Y]); if(ui_mouse_over(sig)) { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Scroll && evt->modifiers & OS_Modifier_Ctrl && evt->modifiers & OS_Modifier_Shift) { ui_eat_event(evt); if(evt->delta_2f32.y < 0) { rd_cmd(RD_CmdKind_IncViewFontSize); } else if(evt->delta_2f32.y > 0) { rd_cmd(RD_CmdKind_DecViewFontSize); } } } } } ////////////////////////////// //- rjf: build result // RD_CodeViewBuildResult result = {0}; { for(DI_KeyNode *n = code_slice_params.relevant_dbgi_keys.first; n != 0; n = n->next) { di_key_list_push(arena, &result.dbgi_keys, n->v); } } ////////////////////////////// //- rjf: store state // rd_store_view_scroll_pos(scroll_pos); cv->force_contain_only = 0; scratch_end(scratch); ProfEnd(); return result; } //////////////////////////////// //~ rjf: Watch Views //- rjf: cell list building internal U64 rd_id_from_watch_cell(RD_WatchCell *cell) { U64 result = 5381; result = e_hash_from_string(result, str8_struct(&cell->kind)); result = e_hash_from_string(result, str8_struct(&cell->index)); if(cell->index != 0) { result = e_hash_from_string(result, str8_struct(&cell->default_pct)); } return result; } internal RD_WatchCell * rd_watch_cell_list_push_new_(Arena *arena, RD_WatchCellList *list, RD_WatchCell *params) { RD_WatchCell *cell = push_array(arena, RD_WatchCell, 1); { cell->index = list->count; SLLQueuePush(list->first, list->last, cell); list->count += 1; } U64 index = cell->index; MemoryCopyStruct(cell, params); cell->index = index; if(cell->pct == 0) { cell->pct = cell->default_pct; } list->pct_sum += cell->pct; cell->next = 0; return cell; } //- rjf: watch view points <-> table coordinates internal B32 rd_watch_pt_match(RD_WatchPt a, RD_WatchPt b) { return (ev_key_match(a.parent_key, b.parent_key) && ev_key_match(a.key, b.key) && a.cell_id == b.cell_id); } internal RD_WatchPt rd_watch_pt_from_tbl(EV_BlockRangeList *block_ranges, Vec2S64 tbl) { RD_WatchPt pt = zero_struct; { Temp scratch = scratch_begin(0, 0); EV_Row *row = ev_row_from_num(scratch.arena, rd_view_eval_view(), block_ranges, (U64)tbl.y); RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); { S64 x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, x += 1) { if(x == tbl.x) { pt.cell_id = rd_id_from_watch_cell(cell); break; } } } pt.key = row->key; pt.parent_key = row->block->key; scratch_end(scratch); } return pt; } internal Vec2S64 rd_tbl_from_watch_pt(EV_BlockRangeList *block_ranges, RD_WatchPt pt) { Vec2S64 tbl = {0}; { Temp scratch = scratch_begin(0, 0); U64 num = ev_num_from_key(block_ranges, pt.key); EV_Row *row = ev_row_from_num(scratch.arena, rd_view_eval_view(), block_ranges, num); RD_WatchRowInfo row_info = rd_watch_row_info_from_row(scratch.arena, row); tbl.x = 0; { S64 x = 0; for(RD_WatchCell *cell = row_info.cells.first; cell != 0; cell = cell->next, x += 1) { U64 cell_id = rd_id_from_watch_cell(cell); if(cell_id == pt.cell_id) { tbl.x = x; break; } } } tbl.y = (S64)num; scratch_end(scratch); } return tbl; } //- rjf: row -> info internal RD_WatchRowInfo rd_watch_row_info_from_row(Arena *arena, EV_Row *row) { RD_WatchRowInfo info = { .module = &ctrl_entity_nil, .can_expand = ev_row_is_expandable(row), .group_cfg_parent = &cfg_nil_node, .group_cfg_child = &cfg_nil_node, .group_entity = &ctrl_entity_nil, .callstack_thread = &ctrl_entity_nil, .view_ui_rule = &rd_nil_view_ui_rule, }; { Temp scratch = scratch_begin(&arena, 1); //////////////////////////// //- rjf: unpack row's evaluation, key, & block info // E_Type *row_type = e_type_from_key(row->eval.irtree.type_key); EV_Key key = row->key; EV_Block *block = row->block; B32 block_is_root = (block->parent == &ev_nil_block); E_Eval block_eval = e_eval_from_key(row->block->eval.key); E_TypeKey block_type_key = e_type_key_unwrap(block_eval.irtree.type_key, E_TypeUnwrapFlag_Meta); E_TypeKind block_type_kind = e_type_kind_from_key(block_type_key); E_Type *block_type = e_type_from_key(block_type_key); CFG_Node *evalled_cfg = rd_cfg_from_eval_space(row->eval.space); CTRL_Entity *evalled_entity = (row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ? rd_ctrl_entity_from_eval_space(row->eval.space) : &ctrl_entity_nil); //////////////////////////// //- rjf: determine if this cfg/entity evaluation is top-level - e.g. if we // are evaluating a cfg tree, or some descendant of it // B32 is_top_level = 0; if(evalled_cfg != &cfg_nil_node) { E_TypeKey top_level_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, evalled_cfg->string); is_top_level = (row->eval.value.u64 == 0 && e_type_key_match(top_level_type_key, row->eval.irtree.type_key)); } if(evalled_entity != &ctrl_entity_nil) { String8 top_level_name = ctrl_entity_kind_code_name_table[evalled_entity->kind]; E_TypeKey top_level_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, top_level_name); is_top_level = (row->eval.value.u64 == 0 && e_type_key_match(top_level_type_key, row->eval.irtree.type_key)); } //////////////////////////// //- rjf: fill if row's expression is editable // if(block_type->flags & E_TypeFlag_EditableChildren || (e_key_match(row->eval.key, e_key_zero()) && row->eval.expr == &e_expr_nil)) { info.expr_is_editable = 1; } //////////////////////////// //- rjf: fill row's module // if(row->eval.space.kind == CTRL_EvalSpaceKind_Entity) { CTRL_Entity *row_ctrl_entity = rd_ctrl_entity_from_eval_space(row->eval.space); switch(row_ctrl_entity->kind) { default: case CTRL_EntityKind_Process: if(row->eval.irtree.mode == E_Mode_Offset) { info.module = ctrl_module_from_process_vaddr(row_ctrl_entity, row->eval.value.u64); }break; case CTRL_EntityKind_Thread: if(row->eval.irtree.mode == E_Mode_Value) { CTRL_Entity *process = ctrl_process_from_entity(row_ctrl_entity); info.module = ctrl_module_from_process_vaddr(process, d_query_cached_rip_from_thread(row_ctrl_entity)); }break; } } //////////////////////////// //- rjf: fill row's call stack info // if(block_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity && str8_match(str8_lit("call_stack"), block_type->name, 0)) { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(block_eval.space); if(entity->kind == CTRL_EntityKind_Thread) { Access *access = access_open(); info.callstack_thread = entity; U64 frame_num = ev_block_num_from_id(block, key.child_id); B32 call_stack_high_priority = ctrl_handle_match(entity->handle, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, entity->handle, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); if(1 <= frame_num && frame_num <= call_stack.frames_count) { CTRL_CallStackFrame *f = &call_stack.frames[frame_num-1]; info.callstack_unwind_index = f->unwind_count; info.callstack_inline_depth = f->inline_depth; info.callstack_vaddr = regs_rip_from_arch_block(entity->arch, f->regs); } access_close(access); } } //////////////////////////// //- rjf: fill row's ctrl entity // if(!block_is_root) { if(block_type_kind == E_TypeKind_Set && (block_eval.space.kind == RD_EvalSpaceKind_MetaQuery || block_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity)) { info.group_entity = rd_ctrl_entity_from_eval_space(row->eval.space); } } //////////////////////////// //- rjf: fill row's cfg group name / parent // if(!block_is_root) { if(block_type_kind == E_TypeKind_Set && (block_eval.space.kind == RD_EvalSpaceKind_MetaQuery || block_eval.space.kind == RD_EvalSpaceKind_MetaCfg)) { info.group_cfg_parent = rd_cfg_from_eval_space(block_eval.space); } } //////////////////////////// //- rjf: fill row's group cfg name // if(!block_is_root) { if(block_type_kind == E_TypeKind_Set) { String8 singular_name = rd_singular_from_code_name_plural(block_type->name); if(singular_name.size != 0) { info.group_cfg_name = singular_name; } else { info.group_cfg_name = block_type->name; } } } //////////////////////////// //- rjf: fill row's group cfg // if(!block_is_root) { if(info.group_cfg_name.size != 0 && (block_type->expand.id_from_num == E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice) || block_type->expand.id_from_num == E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(watches) || block_type->expand.id_from_num == E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(environment))) { CFG_ID id = row->key.child_id; info.group_cfg_child = cfg_node_from_id(id); } } //////////////////////////// //- rjf: fill row's view ui rule // info.view_ui_rule = rd_view_ui_rule_from_string(row->block->viz_expand_rule->string); //////////////////////////// //- rjf: find possible "columns" type // E_Type *maybe_table_type = block_type; for(;;) { if(maybe_table_type->kind == E_TypeKind_Lens && str8_match(maybe_table_type->name, str8_lit("columns"), 0)) { break; } else if(maybe_table_type->kind == E_TypeKind_Lens) { maybe_table_type = e_type_from_key(maybe_table_type->direct_type_key); continue; } else { break; } } //////////////////////////// //- rjf: @watch_row_build_cells table rows // if(0){} else if(block->parent != &ev_nil_block && maybe_table_type->kind == E_TypeKind_Lens && str8_match(maybe_table_type->name, str8_lit("columns"), 0) && maybe_table_type->count >= 1) { U64 column_count = maybe_table_type->count; info.cell_style_key = push_str8f(arena, "table_%I64u_cols", column_count); CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *style = cfg_node_child_from_string(view, info.cell_style_key); CFG_Node *w_cfg = style->first; F32 next_pct = 0; #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) E_ParentKey(row->eval.key) { for(U64 idx = 0; idx < maybe_table_type->count; idx += 1) { E_Eval cell_eval = e_eval_from_expr(maybe_table_type->args[idx]); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, cell_eval, .default_pct = 1.f/maybe_table_type->count, .pct = take_pct()); } } info.can_expand = 0; #undef take_pct } //////////////////////////// //- rjf: @watch_row_build_cells files / folders // else if(row->eval.space.kind == E_SpaceKind_FileSystem && e_type_kind_from_key(row->eval.irtree.type_key) == E_TypeKind_Set) { E_Type *type = e_type_from_key(row->eval.irtree.type_key); String8 file_path = e_string_from_id(row->eval.value.u64); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode, .pct = 1.f); if(str8_match(type->name, str8_lit("file"), 0)) { info.can_expand = 0; } } //////////////////////////// //- rjf: @watch_row_build_cells unattached processes // else if(row->eval.space.kind == RD_EvalSpaceKind_MetaUnattachedProcess && str8_match(row_type->name, str8_lit("unattached_process"), 0)) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells autocomplete rows // else if(cfg_node_child_from_string(cfg_node_from_id(rd_regs()->view), str8_lit("autocomplete")) != &cfg_nil_node) { info.can_expand = 0; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells lister rows // else if(cfg_node_child_from_string(cfg_node_from_id(rd_regs()->view), str8_lit("lister")) != &cfg_nil_node) { info.can_expand = 0; RD_WatchCellFlags extra_flags = RD_WatchCellFlag_Expr; if(e_type_kind_from_key(e_type_key_unwrap(row->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)) == E_TypeKind_Function) { extra_flags &= ~RD_WatchCellFlag_Expr; } if(row->eval.msgs.max_kind != E_MsgKind_Null) { extra_flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval; } rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = extra_flags|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells top-level cfg evaluations // else if(is_top_level && evalled_cfg != &cfg_nil_node) { CFG_Node *cfg = evalled_cfg; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Button|RD_WatchCellFlag_Indented, .pct = 1.f); MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, cfg->string); for(MD_NodePtrNode *n = schemas.first; n != 0; n = n->next) { MD_Node *schema = n->v; MD_Node *cmds_root = md_tag_from_string(schema, str8_lit("row_commands"), 0); for MD_EachNode(cmd, cmds_root->first) { B32 is_file_only = md_node_has_tag(cmd, str8_lit("file"), 0); B32 is_cmd_line_only = md_node_has_tag(cmd, str8_lit("cmd_line"), 0); if(is_file_only && e_eval_from_string(rd_expr_from_cfg(evalled_cfg)).space.kind != E_SpaceKind_File) { continue; } if(is_cmd_line_only) { B32 is_cmd_line = 0; CFG_Node *cmd_line = cfg_node_child_from_string(cfg_node_root(), str8_lit("command_line")); for(CFG_Node *p = evalled_cfg->parent; p != &cfg_nil_node; p = p->parent) { if(p == cmd_line) { is_cmd_line = 1; break; } } if(!is_cmd_line) { continue; } } String8 cmd_name = cmd->string; RD_CmdKind cmd_kind = rd_cmd_kind_from_string(cmd_name); switch(cmd_kind) { default:{}break; case RD_CmdKind_EnableCfg: { B32 is_disabled = rd_disabled_from_cfg(cfg); if(!is_disabled) { cmd_kind = RD_CmdKind_DisableCfg; } }break; case RD_CmdKind_DisableCfg: { B32 is_disabled = rd_disabled_from_cfg(cfg); if(is_disabled) { cmd_kind = RD_CmdKind_EnableCfg; } }break; case RD_CmdKind_SelectCfg: { B32 is_disabled = rd_disabled_from_cfg(cfg); if(!is_disabled) { cmd_kind = RD_CmdKind_DeselectCfg; } }break; case RD_CmdKind_DeselectCfg: { B32 is_disabled = rd_disabled_from_cfg(cfg); if(is_disabled) { cmd_kind = RD_CmdKind_SelectCfg; } }break; } if(cmd_kind == RD_CmdKind_EnableCfg || cmd_kind == RD_CmdKind_DisableCfg) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "enabled"), .flags = RD_WatchCellFlag_Background, .px = floor_f32(ui_top_font_size()*5.5f)); } else if(cmd_kind != RD_CmdKind_Null) { String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_from_stringf("query:commands.%S", cmd_name), .flags = RD_WatchCellFlag_ActivateWithSingleClick|RD_WatchCellFlag_Button, .px = floor_f32(ui_top_font_size()*3.f)); } } } } //////////////////////////// //- rjf: @watch_row_build_cells ctrl entity evaluations // else if(is_top_level && evalled_entity != &ctrl_entity_nil) { CTRL_Entity *entity = evalled_entity; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button, .pct = 1.f); if(entity->kind == CTRL_EntityKind_Machine || entity->kind == CTRL_EntityKind_Process || entity->kind == CTRL_EntityKind_Thread) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "active"), .px = floor_f32(ui_top_font_size()*5.5f)); } if(entity->kind == CTRL_EntityKind_Thread) { RD_CmdKind cmd_kind = RD_CmdKind_SelectEntity; if(ctrl_handle_match(entity->handle, rd_base_regs()->thread)) { cmd_kind = RD_CmdKind_DeselectEntity; } String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string; rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_from_stringf("query:commands.%S", cmd_name), .flags = RD_WatchCellFlag_ActivateWithSingleClick|RD_WatchCellFlag_Button, .px = floor_f32(ui_top_font_size()*3.f)); } } //////////////////////////// //- rjf: @watch_row_build_cells queries // else if(row->eval.space.kind == RD_EvalSpaceKind_MetaQuery || (row->eval.space.kind == RD_EvalSpaceKind_MetaCfg && e_type_kind_from_key(e_type_key_unwrap(row->eval.irtree.type_key, E_TypeUnwrapFlag_Meta)) == E_TypeKind_Set)) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells commands // else if(row->eval.space.kind == RD_EvalSpaceKind_MetaCmd) { E_Type *type = e_type_from_key(row->eval.irtree.type_key); if(type->kind == E_TypeKind_Set) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .pct = 1.f); } else { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented|RD_WatchCellFlag_Button|RD_WatchCellFlag_ActivateWithSingleClick, .pct = 1.f); } } //////////////////////////// //- rjf: @watch_row_build_cells view UI escape hatch // else if(info.view_ui_rule != &rd_nil_view_ui_rule) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_ViewUI, row->eval, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells "add new" expression rows // else if(row->eval.expr == &e_expr_nil && info.group_cfg_name.size != 0 && info.group_cfg_child == &cfg_nil_node) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells meta-evaluation booleans // else if(info.group_cfg_child == &cfg_nil_node && e_type_kind_from_key(e_type_key_unwrap(row->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)) == E_TypeKind_Bool && (row->eval.space.kind == RD_EvalSpaceKind_MetaCfg || row->eval.space.kind == RD_EvalSpaceKind_MetaCmd || row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity)) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_Indented, .pct = 1.f); } //////////////////////////// //- rjf: @watch_row_build_cells procedures (expr & eval, mostly expr) // else if(block_type->kind == E_TypeKind_Set && str8_match(block_type->name, str8_lit("procedures"), 0)) { info.cell_style_key = str8_lit("procedure_expr_eval"); CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *style = cfg_node_child_from_string(view, info.cell_style_key); CFG_Node *w_cfg = style->first; F32 next_pct = 0; #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .default_pct = 0.75f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, e_eval_wrapf(row->eval, "lens:hex((uint64)$)"), .default_pct = 0.25f, .pct = take_pct()); #undef take_pct } //////////////////////////// //- rjf: @watch_row_build_cells call stack frames // else if(info.callstack_thread != &ctrl_entity_nil) { info.cell_style_key = str8_lit("call_stack_frame"); CTRL_Entity *process = ctrl_process_from_entity(info.callstack_thread); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, info.callstack_vaddr); E_Eval module_eval = e_eval_from_stringf("query:control.%S", ctrl_string_from_handle(scratch.arena, module->handle)); CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *style = cfg_node_child_from_string(view, info.cell_style_key); CFG_Node *w_cfg = style->first; F32 next_pct = 0; #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_CallStackFrame, row->eval, .default_pct = 0.05f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .default_pct = 0.75f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, (module == &ctrl_entity_nil ? (E_Eval)zero_struct : module_eval), .default_pct = 0.20f, .pct = take_pct()); #undef take_pct } //////////////////////////// //- rjf: @watch_row_build_cells catchall (normal rows) // else { // rjf: disable expansion on meta string evaluations if(row->eval.space.kind == RD_EvalSpaceKind_MetaCfg || row->eval.space.kind == RD_EvalSpaceKind_MetaCmd || row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || row->eval.space.kind == E_SpaceKind_File) { E_TypeKey substantive_row_eval_type = e_type_key_unwrap(row->eval.irtree.type_key, E_TypeUnwrapFlag_Meta); if(e_type_kind_from_key(substantive_row_eval_type) == E_TypeKind_Array && e_type_kind_from_key(e_type_key_direct(substantive_row_eval_type)) == E_TypeKind_U8) { info.can_expand = 0; } } info.cell_style_key = str8_lit("normal"); CFG_Node *view = cfg_node_from_id(rd_regs()->view); CFG_Node *style = cfg_node_child_from_string(view, info.cell_style_key); CFG_Node *w_cfg = style->first; F32 next_pct = 0; #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .flags = RD_WatchCellFlag_Expr|RD_WatchCellFlag_NoEval|RD_WatchCellFlag_Indented, .default_pct = 0.35f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, row->eval, .default_pct = 0.65f, .pct = take_pct()); #undef take_pct } //////////////////////////// //- rjf: normalize all cell widths // if(abs_f32(info.cells.pct_sum - 1.f) > 0.01f) { F32 sum = info.cells.pct_sum; if(sum <= 0) { sum = 1.f; } for(RD_WatchCell *c = info.cells.first; c != 0; c = c->next) { c->pct /= sum; } } scratch_end(scratch); } return info; } //- rjf: row * cell -> string internal RD_WatchRowCellInfo rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_flags, RD_WatchRowInfo *row_info, RD_WatchCell *cell, FNT_Tag font, F32 font_size, F32 max_size_px) { Temp scratch = scratch_begin(&arena ,1); RD_WatchRowCellInfo result = { .flags = cell->flags, .view_ui_rule = &rd_nil_view_ui_rule, .cfg = &cfg_nil_node, .entity = &ctrl_entity_nil, }; ////////////////////////////// //- rjf: unpack evaluation // E_Type *block_type = e_type_from_key(row->block->eval.irtree.type_key); E_Type *cell_type = e_type_from_key(cell->eval.irtree.type_key); MD_NodePtrList cell_schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, cell_type->name); if(cell->eval.space.u64s[1] == 0 && cell_schemas.count != 0) { result.cfg = rd_cfg_from_eval_space(cell->eval.space); } if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity && cell->eval.space.u64s[2] == 0) { result.entity = rd_ctrl_entity_from_eval_space(cell->eval.space); } result.cmd_name = rd_cmd_name_from_eval(cell->eval); result.file_path = rd_file_path_from_eval(arena, cell->eval); for(E_Type *type = cell_type; type->kind == E_TypeKind_Lens; type = e_type_from_key(type->direct_type_key)) { RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(type->name); if(view_ui_rule != &rd_nil_view_ui_rule) { result.view_ui_rule = view_ui_rule; break; } } ////////////////////////////// //- rjf: determine cell description // for(E_Type *type = cell_type; type->kind != E_TypeKind_Null; type = e_type_from_key(type->direct_type_key)) { if(type->kind == E_TypeKind_MetaDescription) { result.description = type->name; break; } } ////////////////////////////// //- rjf: determine cell editability // if(cell->kind == RD_WatchCellKind_Eval) { if(cell->flags & RD_WatchCellFlag_Expr && cell->flags & RD_WatchCellFlag_NoEval) { if(row_info->expr_is_editable) { result.flags |= RD_WatchCellFlag_CanEdit; } } else { if(ev_type_key_is_editable(cell->eval.irtree.type_key) && cell->eval.irtree.mode == E_Mode_Offset) { result.flags |= RD_WatchCellFlag_CanEdit; } } } ////////////////////////////// //- rjf: build cell's visual appearance info // switch(cell->eval.space.kind) { //- rjf: default case: depending on cell info, generate string default: { if(0){} //- rjf: errors else if(cell->eval.msgs.max_kind > E_MsgKind_Null && !(cell->flags & RD_WatchCellFlag_NoEval)) { RD_Font(RD_FontSlot_Main) { DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; DR_FStrList fstrs = {0}; UI_TagF("weak") { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_WarningBig], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); for(E_Msg *msg = cell->eval.msgs.first; msg != 0; msg = msg->next) { DR_FStrList msg_fstrs = rd_fstrs_from_rich_string(arena, msg->text); dr_fstrs_concat_in_place(&fstrs, &msg_fstrs); if(msg->next) { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); } } } result.expr_fstrs = fstrs; } } //- rjf: cfg evaluation -> button for cfg else if(result.cfg != &cfg_nil_node) { result.expr_fstrs = rd_title_fstrs_from_cfg(arena, result.cfg, 0); result.flags |= RD_WatchCellFlag_Button; } //- rjf: entity evaluation -> button for entity else if(result.entity != &ctrl_entity_nil) { result.expr_fstrs = rd_title_fstrs_from_ctrl_entity(arena, result.entity, 1); result.flags |= RD_WatchCellFlag_Button; } //- rjf: buttons -> button for command else if(result.cmd_name.size != 0) { if(cell->px != 0) { DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; DR_FStrList fstrs = {0}; UI_TagF("weak") { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[rd_icon_kind_from_code_name(result.cmd_name)], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); } result.expr_fstrs = fstrs; } else { result.expr_fstrs = rd_title_fstrs_from_code_name(arena, result.cmd_name); } result.flags |= RD_WatchCellFlag_Button; } //- rjf: files -> button for file else if(result.file_path.size != 0) { result.expr_fstrs = rd_title_fstrs_from_file_path(arena, result.file_path); result.flags |= RD_WatchCellFlag_Button; } //- rjf: catchall cell -> need to form "left-hand-side", or "meta" string, for expression, and/or value string else { //- rjf: build left-hand-side strings DR_FStrList expr_fstrs = {0}; if(cell->flags & RD_WatchCellFlag_Expr) { B32 is_non_code = 0; String8 expr_string = {0}; // rjf: if this cell has a meta-display-name, then use that if(expr_string.size == 0) { for(E_Type *t = e_type_from_key(cell->eval.irtree.type_key); t != &e_type_nil; t = e_type_from_key(t->direct_type_key)) { if(t->kind == E_TypeKind_MetaDisplayName) { is_non_code = 1; expr_string = t->name; break; } } } // rjf: if this cell has no string specified, then we need to synthesize one from the evaluation if(expr_string.size == 0) { // rjf: defaultly fill the cell's expression string, before trying other things expr_string = cell->eval.string; // rjf: try to form a simpler expression string out of the expression tree itself, *if* this // is not an editable expression, and if this evaluation was successful, and if this evaluation // has a parent if(!e_key_match(cell->eval.parent_key, e_key_zero()) && !(block_type->flags & E_TypeFlag_EditableChildren) && cell->eval.msgs.max_kind == E_MsgKind_Null) { // rjf: first, locate a notable expression - we special-case things like member accesses // or array indices, so we should grab those if possible E_Expr *notable_expr = cell->eval.expr; for(B32 good = 0; !good;) { switch(notable_expr->kind) { default:{good = 1;}break; case E_ExprKind_Address: case E_ExprKind_Deref: case E_ExprKind_Cast: { notable_expr = notable_expr->last; }break; case E_ExprKind_Ref: { notable_expr = notable_expr->ref; }break; } } // rjf: generate expression extension string based on our notable expression switch(notable_expr->kind) { // rjf: default case -> just take whatever string was directly passed via the evaluation default:{}break; // rjf: array indices -> fast path to [index] case E_ExprKind_ArrayIndex: { expr_string = push_str8f(arena, "[%S]", e_string_from_expr(arena, notable_expr->last, str8_zero())); }break; // rjf: member accesses -> fast-path to .name case E_ExprKind_MemberAccess: { Temp scratch = scratch_begin(&arena, 1); // TODO(rjf): @cfg need to build inheritance tooltips #if 0 if(member.inheritance_key_chain.count != 0) { String8List strings = {0}; for(E_TypeKeyNode *n = member.inheritance_key_chain.first; n != 0; n = n->next) { String8 base_class_name = e_type_string_from_key(scratch.arena, n->v); str8_list_push(scratch.arena, &strings, base_class_name); } result.inheritance_tooltip = str8_list_join(arena, &strings, &(StringJoin){.sep = str8_lit_comp("::")}); } #endif // rjf: in meta-evaluation spaces, we will try to look up into our vocabulary map // to see if we have a fancy display string for this member. otherwise, we will just // do a code-string of ".member_name" String8 member_name = notable_expr->first->next->string; String8 fancy_name = {0}; if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg || cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || cell->eval.space.kind == E_SpaceKind_File || cell->eval.space.kind == E_SpaceKind_FileSystem) { fancy_name = rd_display_from_code_name(member_name); } if(fancy_name.size != 0) { is_non_code = 1; expr_string = fancy_name; } else if(member_name.size != 0) { expr_string = push_str8f(arena, ".%S", member_name); } scratch_end(scratch); }break; } } } // rjf: use expression string / params to generate fancy strings if(is_non_code) { DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), font_size, 0, 0}; dr_fstrs_push_new(arena, &expr_fstrs, ¶ms, expr_string); } else { expr_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), expr_string); } } //- rjf: evaluation -> need to form value string DR_FStrList eval_fstrs = {0}; if(!(cell->flags & RD_WatchCellFlag_NoEval)) { // rjf: determine string generation parameters based on evaluation EV_StringParams string_params = {string_flags, 10}; { if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCfg || cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity) { string_params.flags |= EV_StringFlag_DisableStringQuotes|EV_StringFlag_DisableAddresses; } if(cell->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity && rd_ctrl_entity_from_eval_space(cell->eval.space)->kind == CTRL_EntityKind_Module) { string_params.radix = 16; } if(cell->eval.space.kind == CTRL_EvalSpaceKind_Entity && rd_ctrl_entity_from_eval_space(cell->eval.space)->kind == CTRL_EntityKind_Thread) { string_params.radix = 16; } } // rjf: determine if code B32 is_code = 1; { E_Type *type = e_type_from_key(e_type_key_unwrap(cell->eval.irtree.type_key, E_TypeUnwrapFlag_Meta)); if(type->flags & (E_TypeFlag_IsPlainText|E_TypeFlag_IsPathText)) { is_code = 0; } } // rjf: generate string based on that expression & fill String8 string = rd_value_string_from_eval(arena, rd_view_query_input(), &string_params, font, font_size, max_size_px, cell->eval); if(is_code) { eval_fstrs = rd_fstrs_from_code_string(arena, 1, 0, ui_color_from_name(str8_lit("text")), string); } else UI_TagF("weak") { DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), font_size, 0, 0}; dr_fstrs_push_new(arena, &eval_fstrs, ¶ms, string); result.flags |= RD_WatchCellFlag_IsNonCode; } } //- rjf: if we have only the expression, then use the expression as the value if(cell->flags & RD_WatchCellFlag_NoEval) { result.eval_fstrs = expr_fstrs; } else { result.expr_fstrs = expr_fstrs; result.eval_fstrs = eval_fstrs; } } }break; //- rjf: unattached processes case RD_EvalSpaceKind_MetaUnattachedProcess: { U64 pid = cell->eval.value.u128.u64[0]; String8 name = e_string_from_id(cell->eval.value.u128.u64[1]); DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; DR_FStrList fstrs = {0}; UI_TagF("weak") { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_Scheduler], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); } dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, push_str8f(arena, "(PID: %I64u)", pid)); dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, name); result.expr_fstrs = fstrs; }break; //- rjf: unattached processes case RD_EvalSpaceKind_MetaTheme: { String8 name = e_string_from_id(cell->eval.value.u64); DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; DR_FStrList fstrs = {0}; UI_TagF("weak") { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_Palette], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); } dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, name); { Access *access = access_open(); MD_Node *theme_tree = rd_theme_tree_from_name(scratch.arena, access, name); U64 color_idx = 0; for(MD_Node *n = theme_tree; color_idx < 4 && !md_node_is_nil(n); n = md_node_rec_depth_first_pre(n, theme_tree).next) { if(str8_match(n->string, str8_lit("theme_color"), 0)) { String8 tags = md_child_from_string(n, str8_lit("tags"), 0)->first->string; if(str8_match(tags, str8_lit("background"), 0) || str8_match(tags, str8_lit("text"), 0) || str8_match(tags, str8_lit("focus border"), 0) || str8_match(tags, str8_lit("menu_bar background"), 0) || str8_match(tags, str8_lit("tab background"), 0) || str8_match(tags, str8_lit("code_default"), 0)) { U64 color = 0; if(try_u64_from_str8_c_rules(md_child_from_string(n, str8_lit("value"), 0)->first->string, &color)) { dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[RD_IconKind_CircleFilled], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = linear_from_srgba(rgba_from_u32((U32)color))); color_idx += 1; } } } } access_close(access); } result.eval_fstrs = fstrs; }break; } scratch_end(scratch); return result; } //- rjf: table coordinates -> text edit state internal RD_WatchViewTextEditState * rd_watch_view_text_edit_state_from_pt(RD_WatchViewState *wv, RD_WatchPt pt) { RD_WatchViewTextEditState *result = &wv->dummy_text_edit_state; if(wv->text_edit_state_slots_count != 0 && wv->text_editing != 0) { U64 hash = ev_hash_from_key(pt.key); U64 slot_idx = hash%wv->text_edit_state_slots_count; for(RD_WatchViewTextEditState *s = wv->text_edit_state_slots[slot_idx]; s != 0; s = s->pt_hash_next) { if(rd_watch_pt_match(pt, s->pt)) { result = s; break; } } } return result; } //////////////////////////////// //~ rjf: null @view_hook_impl RD_VIEW_UI_FUNCTION_DEF(null) {} //////////////////////////////// //~ rjf: text @view_hook_impl internal AC_Artifact rd_md5_artifact_create(String8 key, B32 *cancel_out, B32 *retry_out, U64 *gen_out) { AC_Artifact result = {0}; { Access *access = access_open(); U128 hash = {0}; str8_deserial_read_struct(key, 0, &hash); String8 data = c_data_from_hash(access, hash); MD5 md5 = md5_from_data(data); StaticAssert(sizeof(result) >= sizeof(md5), artifact_size_check); MemoryCopy(&result, &md5, Min(sizeof(result), sizeof(md5))); access_close(access); } return result; } internal AC_Artifact rd_sha1_artifact_create(String8 key, B32 *cancel_out, B32 *retry_out, U64 *gen_out) { AC_Artifact result = {0}; { Access *access = access_open(); U128 hash = {0}; str8_deserial_read_struct(key, 0, &hash); String8 data = c_data_from_hash(access, hash); SHA1 sha1 = sha1_from_data(data); StaticAssert(sizeof(result) >= sizeof(sha1), artifact_size_check); MemoryCopy(&result, &sha1, Min(sizeof(result), sizeof(sha1))); access_close(access); } return result; } internal AC_Artifact rd_sha256_artifact_create(String8 key, B32 *cancel_out, B32 *retry_out, U64 *gen_out) { AC_Artifact result = {0}; { Access *access = access_open(); U128 hash = {0}; str8_deserial_read_struct(key, 0, &hash); String8 data = c_data_from_hash(access, hash); SHA256 sha256 = sha256_from_data(data); StaticAssert(sizeof(result) >= sizeof(sha256), artifact_size_check); MemoryCopy(&result, &sha256, Min(sizeof(result), sizeof(sha256))); access_close(access); } return result; } internal MD5 rd_md5_from_hash(U128 hash) { Access *access = access_open(); AC_Artifact artifact = ac_artifact_from_key(access, str8_struct(&hash), rd_md5_artifact_create, 0, 0); MD5 md5 = {0}; MemoryCopy(&md5, &artifact, Min(sizeof(md5), sizeof(artifact))); access_close(access); return md5; } internal SHA1 rd_sha1_from_hash(U128 hash) { Access *access = access_open(); AC_Artifact artifact = ac_artifact_from_key(access, str8_struct(&hash), rd_sha1_artifact_create, 0, 0); SHA1 sha1 = {0}; MemoryCopy(&sha1, &artifact, Min(sizeof(sha1), sizeof(artifact))); access_close(access); return sha1; } internal SHA256 rd_sha256_from_hash(U128 hash) { Access *access = access_open(); AC_Artifact artifact = ac_artifact_from_key(access, str8_struct(&hash), rd_sha256_artifact_create, 0, 0); SHA256 sha256 = {0}; MemoryCopy(&sha256, &artifact, Min(sizeof(sha256), sizeof(artifact))); access_close(access); return sha256; } EV_EXPAND_RULE_INFO_FUNCTION_DEF(text) { EV_ExpandInfo info = {0}; info.row_count = 8; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(text) { RD_CodeViewState *cv = rd_view_state(RD_CodeViewState); rd_code_view_init(cv); Temp scratch = scratch_begin(0, 0); Access *access = access_open(); ////////////////////////////// //- rjf: set up invariants // F32 main_font_size = ui_bottom_font_size(); F32 bottom_bar_height = main_font_size*2.f; Rng2F32 code_area_rect = r2f32p(rect.x0, rect.y0, rect.x1, rect.y1 - bottom_bar_height); Rng2F32 bottom_bar_rect = r2f32p(rect.x0, rect.y1 - bottom_bar_height, rect.x1, rect.y1); ////////////////////////////// //- rjf: process code-file commands // ProfScope("process code-file commands") for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default:{}break; // rjf: override file picking case RD_CmdKind_PickFile: { String8 src = rd_regs()->file_path; String8 dst = cmd->regs->file_path; if(src.size != 0 && dst.size != 0) { // rjf: record src -> dst mapping rd_cmd(RD_CmdKind_SetFileReplacementPath, .string = src, .file_path = dst); // rjf: switch this view to viewing replacement file rd_store_view_expr_string(rd_eval_string_from_file_path(scratch.arena, dst)); } }break; } } ////////////////////////////// //- rjf: unpack parameterization info // ProfBegin("unpack parameterization info"); rd_regs()->file_path = rd_file_path_from_eval(rd_frame_arena(), eval); rd_regs()->vaddr = 0; rd_regs()->prefer_disasm = 0; rd_regs()->cursor.line = rd_view_setting_value_from_name(str8_lit("cursor_line")).s64; rd_regs()->cursor.column = rd_view_setting_value_from_name(str8_lit("cursor_column")).s64; rd_regs()->mark.line = rd_view_setting_value_from_name(str8_lit("mark_line")).s64; rd_regs()->mark.column = rd_view_setting_value_from_name(str8_lit("mark_column")).s64; if(rd_regs()->cursor.line == 0) { rd_regs()->cursor.line = 1; } if(rd_regs()->cursor.column == 0) { rd_regs()->cursor.column = 1; } if(rd_regs()->mark.line == 0) { rd_regs()->mark.line = 1; } if(rd_regs()->mark.column == 0) { rd_regs()->mark.column = 1; } String8List overrides = rd_possible_overrides_from_file_path(scratch.arena, rd_regs()->file_path); Rng1U64 range = rd_space_range_from_eval(eval); rd_regs()->text_key = rd_key_from_eval_space_range(eval.space, range, 1); String8 lang = rd_view_setting_from_name(str8_lit("lang")); if(lang.size == 0) { rd_regs()->lang_kind = rd_lang_kind_from_eval(eval); } else { rd_regs()->lang_kind = txt_lang_kind_from_extension(lang); } if(rd_regs()->lang_kind == TXT_LangKind_Null) { Access *access = access_open(); CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->module); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); if(rdi != &rdi_parsed_nil) { for EachNode(override_n, String8Node, overrides.first) { String8 file_path = override_n->string; String8 file_path_normalized = lower_from_str8(scratch.arena, path_normalized_from_string(scratch.arena, file_path)); B32 good_src_id = 0; U32 src_id = 0; RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { U32 src_id = ids[0]; RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap parsed_src_line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &parsed_src_line_map); if(src_line_map->voff_count != 0) { RDI_Unit *unit = rdi_unit_from_voff(rdi, parsed_src_line_map.voffs[0]); switch((RDI_LanguageEnum)unit->language) { case RDI_Language_NULL: case RDI_Language_COUNT: case RDI_Language_Masm: {}break; case RDI_Language_C: {rd_regs()->lang_kind = TXT_LangKind_C;}break; case RDI_Language_CPlusPlus:{rd_regs()->lang_kind = TXT_LangKind_CPlusPlus;}break; } } break; } } } } access_close(access); } U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(access, rd_regs()->text_key, rd_regs()->lang_kind, &hash); String8 data = c_data_from_hash(access, hash); B32 file_is_missing = (rd_regs()->file_path.size != 0 && os_properties_from_file_path(rd_regs()->file_path).modified == 0); B32 key_has_data = !u128_match(hash, u128_zero()) && info.lines_count; ProfEnd(); ////////////////////////////// //- rjf: update last hash - scroll-to-bottom if needed // if(rd_setting_b32_from_name(str8_lit("scroll_to_bottom_on_change")) && !u128_match(hash, cv->last_hash) && !u128_match(cv->last_hash, u128_zero())) { cv->goto_line_num = info.lines_count; cv->contain_cursor = 1; cv->force_contain_only = 1; } cv->last_hash = hash; ////////////////////////////// //- rjf: build missing file interface // if(file_is_missing) { UI_WidthFill UI_HeightFill UI_Column UI_Padding(ui_pct(1, 0)) { Temp scratch = scratch_begin(0, 0); UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_em(3, 1)) UI_Row UI_Padding(ui_pct(1, 0)) UI_PrefWidth(ui_text_dim(1, 1)) UI_TagF("weak") { RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[RD_IconKind_WarningBig]); ui_labelf("Could not find \"%S\".", rd_regs()->file_path); } UI_PrefHeight(ui_em(3, 1)) UI_Row UI_Padding(ui_pct(1, 0)) UI_PrefWidth(ui_text_dim(10, 1)) UI_CornerRadius(ui_top_font_size()/3) UI_PrefWidth(ui_text_dim(10, 1)) UI_Focus(UI_FocusKind_On) UI_TextAlignment(UI_TextAlign_Center) UI_TagF("pop") if(ui_clicked(ui_buttonf("Find alternative..."))) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_PickFile].string); } scratch_end(scratch); } } ////////////////////////////// //- rjf: code is not missing, but not ready -> equip loading info to this view // if(!file_is_missing && info.lines_count == 0 && eval.msgs.max_kind == E_MsgKind_Null) { rd_store_view_loading_info(1, info.bytes_processed, info.bytes_to_process); } ////////////////////////////// //- rjf: build code contents // DI_KeyList dbgi_keys = {0}; if(!file_is_missing) { RD_CodeViewBuildFlags flags = RD_CodeViewBuildFlag_All; if(rd_regs()->file_path.size == 0) { flags &= ~RD_CodeViewBuildFlag_Margins; } RD_CodeViewBuildResult result = rd_code_view_build(scratch.arena, cv, flags, code_area_rect, data, &info, 0, r1u64(0, 0), di_key_zero()); dbgi_keys = result.dbgi_keys; } ////////////////////////////// //- rjf: unpack cursor info // if(rd_regs()->file_path.size != 0) { CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->module); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, rd_regs()->file_path, rd_regs()->cursor.line); } ////////////////////////////// //- rjf: determine if file is out-of-date // B32 file_is_out_of_date = 0; { Temp scratch = scratch_begin(0, 0); // rjf: determine checksum in relevant debug infos RDI_ChecksumKind checksum_kind = RDI_ChecksumKind_NULL; String8 checksum_expected = {0}; for(DI_KeyNode *n = dbgi_keys.first; n != 0 && checksum_kind == RDI_ChecksumKind_NULL; n = n->next) { Access *access = access_open(); // rjf: unpack RDI DI_Key key = n->v; RDI_Parsed *rdi = di_rdi_from_key(access, key, 0, 0); // rjf: file_path_normalized * rdi -> src_id for EachNode(override_n, String8Node, overrides.first) { String8 file_path = override_n->string; String8 file_path_normalized = lower_from_str8(scratch.arena, path_normalized_from_string(scratch.arena, file_path)); B32 good_src_id = 0; U32 src_id = 0; if(rdi != &rdi_parsed_nil) { RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); RDI_ParsedNameMap map = {0}; rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); if(node != 0) { U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { U32 src_id = ids[0]; RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); checksum_kind = src->checksum_kind; RDI_SectionKind checksum_section_kind = rdi_section_kind_from_checksum_kind(checksum_kind); U64 checksum_size = rdi_section_element_size_table[checksum_section_kind]; U8 *checksum_data = (U8 *)rdi_section_raw_element_from_kind_idx(rdi, checksum_section_kind, src->checksum_idx); checksum_expected = str8_copy(scratch.arena, str8(checksum_data, checksum_size)); break; } } } } access_close(access); } // rjf: if we got a checksum, compute it locally - check if they match. switch(checksum_kind) { default:{}break; case RDI_ChecksumKind_MD5: { MD5 md5 = rd_md5_from_hash(hash); String8 md5_string = str8_struct(&md5); file_is_out_of_date = !MemoryIsZeroStruct(&md5) && !str8_match(md5_string, checksum_expected, 0); }break; case RDI_ChecksumKind_SHA1: { SHA1 sha1 = rd_sha1_from_hash(hash); String8 sha1_string = str8_struct(&sha1); file_is_out_of_date = !MemoryIsZeroStruct(&sha1) && !str8_match(sha1_string, checksum_expected, 0); }break; case RDI_ChecksumKind_SHA256: { SHA256 sha256 = rd_sha256_from_hash(hash); String8 sha256_string = str8_struct(&sha256); file_is_out_of_date = !MemoryIsZeroStruct(&sha256) && !str8_match(sha256_string, checksum_expected, 0); }break; case RDI_ChecksumKind_Timestamp: { FileProperties props = os_properties_from_file_path(rd_regs()->file_path); String8 timestamp_string = str8_struct(&props.modified); file_is_out_of_date = !MemoryIsZeroStruct(&props.modified) && !str8_match(timestamp_string, checksum_expected, 0); }break; } scratch_end(scratch); } ////////////////////////////// //- rjf: build bottom bar // if(!file_is_missing && key_has_data) UI_FontSize(main_font_size) UI_TagF(file_is_out_of_date ? "bad_pop" : ".") { ui_set_next_rect(shift_2f32(bottom_bar_rect, scale_2f32(rect.p0, -1.f))); ui_set_next_flags(UI_BoxFlag_DrawBackground); UI_Row UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_text_dim(10, 1)) UI_TagF("weak") { if(file_is_out_of_date) { UI_Box *box = &ui_nil_box; RD_Font(RD_FontSlot_Icons) { box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "%S###file_ood_warning", rd_icon_kind_text_table[RD_IconKind_WarningBig]); } UI_Signal sig = ui_signal_from_box(box); if(ui_hovering(sig)) UI_Tooltip { UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(1, 1)) UI_TextPadding(0) { UI_TagF("weak") ui_labelf("This file has changed since it was compiled."); } } } RD_Font(RD_FontSlot_Code) { if(rd_regs()->file_path.size != 0) { ui_label(rd_regs()->file_path); ui_spacer(ui_em(1.5f, 1)); } ui_labelf("Line: %I64d, Column: %I64d", rd_regs()->cursor.line, rd_regs()->cursor.column); ui_spacer(ui_pct(1, 0)); ui_labelf("(read only)"); ui_labelf("%s", info.line_end_kind == TXT_LineEndKind_LF ? "lf" : info.line_end_kind == TXT_LineEndKind_CRLF ? "crlf" : "bin"); } } } ////////////////////////////// //- rjf: store params // rd_store_view_param_s64(str8_lit("cursor_line"), rd_regs()->cursor.line); rd_store_view_param_s64(str8_lit("cursor_column"), rd_regs()->cursor.column); rd_store_view_param_s64(str8_lit("mark_line"), rd_regs()->mark.line); rd_store_view_param_s64(str8_lit("mark_column"), rd_regs()->mark.column); access_close(access); scratch_end(scratch); } //////////////////////////////// //~ rjf: disasm @view_hook_impl typedef struct RD_DisasmViewState RD_DisasmViewState; struct RD_DisasmViewState { B32 initialized; TxtPt cursor; TxtPt mark; CTRL_Handle temp_look_process; U64 temp_look_vaddr; U64 temp_look_run_gen; U64 goto_vaddr; RD_CodeViewState cv; }; EV_EXPAND_RULE_INFO_FUNCTION_DEF(disasm) { EV_ExpandInfo info = {0}; info.row_count = 8; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(disasm) { RD_DisasmViewState *dv = rd_view_state(RD_DisasmViewState); if(dv->initialized == 0) { dv->initialized = 1; dv->cursor = txt_pt(1, 1); dv->mark = txt_pt(1, 1); rd_code_view_init(&dv->cv); } RD_CodeViewState *cv = &dv->cv; Temp scratch = scratch_begin(0, 0); Access *access = access_open(); ////////////////////////////// //- rjf: if disassembly views are parameterized by a register-space evaluation, // we will interpret it as an address in the primary module. // if(e_space_match(eval.space, e_base_ctx->thread_reg_space)) { eval = e_value_eval_from_eval(eval); eval.space = e_base_ctx->primary_module->space; } ////////////////////////////// //- rjf: if disassembly views are not parameterized by anything, they // automatically snap to the selected thread's RIP, OR the "temp look // address" (commanded by go-to-disasm or go-to-address), rounded down to the // nearest 16K boundary // B32 auto_selected = 0; E_Space auto_space = {0}; if(eval.expr == &e_expr_nil) { if(dv->temp_look_vaddr != 0 && dv->temp_look_run_gen == ctrl_run_gen()) { auto_selected = 1; auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, dv->temp_look_process), CTRL_EvalSpaceKind_Entity); eval = e_eval_from_stringf("(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr); } else { auto_selected = 1; auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process), CTRL_EvalSpaceKind_Entity); eval = e_eval_from_stringf("(reg:rip & (~(0x4000 - 1)))"); } } ////////////////////////////// //- rjf: set up invariants // F32 main_font_size = ui_bottom_font_size(); F32 bottom_bar_height = main_font_size*2.f; Rng2F32 code_area_rect = r2f32p(rect.x0, rect.y0, rect.x1, rect.y1 - bottom_bar_height); Rng2F32 bottom_bar_rect = r2f32p(rect.x0, rect.y1 - bottom_bar_height, rect.x1, rect.y1); rd_regs()->file_path = str8_zero(); rd_regs()->cursor = dv->cursor; rd_regs()->mark = dv->mark; ////////////////////////////// //- rjf: process disassembly-specific commands // for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default: break; case RD_CmdKind_GoToAddress: { dv->temp_look_process = cmd->regs->process; dv->temp_look_vaddr = cmd->regs->vaddr; dv->temp_look_run_gen = ctrl_run_gen(); dv->goto_vaddr = cmd->regs->vaddr; }break; } } ////////////////////////////// //- rjf: unpack parameterization info // E_Space space = eval.space; if(auto_selected) { space = auto_space; } Rng1U64 range = rd_space_range_from_eval(eval); Arch arch = rd_arch_from_eval(eval); CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(space); CTRL_Entity *dasm_module = &ctrl_entity_nil; DI_Key dbgi_key = {0}; U64 base_vaddr = 0; switch(space_entity->kind) { default:{}break; case CTRL_EntityKind_Process: { if(arch == Arch_Null) { arch = space_entity->arch; } dasm_module = ctrl_module_from_process_vaddr(space_entity, range.min); dbgi_key = ctrl_dbgi_key_from_module(dasm_module); base_vaddr = dasm_module->vaddr_range.min; }break; } DASM_StyleFlags style_flags = 0; DASM_Syntax syntax = DASM_Syntax_Intel; { if(rd_setting_b32_from_name(str8_lit("show_addresses"))) { style_flags |= DASM_StyleFlag_Addresses; } if(rd_setting_b32_from_name(str8_lit("show_code_bytes"))) { style_flags |= DASM_StyleFlag_CodeBytes; } if(rd_setting_b32_from_name(str8_lit("show_source_lines"))) { style_flags |= DASM_StyleFlag_SourceFilesNames; style_flags |= DASM_StyleFlag_SourceLines; } if(rd_setting_b32_from_name(str8_lit("show_symbol_names"))) { style_flags |= DASM_StyleFlag_SymbolNames; } if(str8_match(rd_setting_from_name(str8_lit("syntax")), str8_lit("att"), 0)) { syntax = DASM_Syntax_ATT; } } C_Key dasm_key = rd_key_from_eval_space_range(space, range, 0); U128 dasm_data_hash = {0}; DASM_Params dasm_params = {0}; { dasm_params.vaddr = range.min; dasm_params.arch = arch; dasm_params.style_flags = style_flags; dasm_params.syntax = syntax; dasm_params.base_vaddr = base_vaddr; dasm_params.dbgi_key = dbgi_key; } DASM_Info dasm_info = dasm_info_from_key_params(access, dasm_key, &dasm_params, &dasm_data_hash); rd_regs()->text_key = dasm_info.text_key; rd_regs()->lang_kind = txt_lang_kind_from_arch(arch); U128 dasm_text_hash = {0}; TXT_TextInfo dasm_text_info = txt_text_info_from_key_lang(access, rd_regs()->text_key, rd_regs()->lang_kind, &dasm_text_hash); String8 dasm_text_data = c_data_from_hash(access, dasm_text_hash); B32 is_loading = (dasm_text_info.lines_count == 0 && dim_1u64(range) != 0 && eval.msgs.max_kind == E_MsgKind_Null && (space.kind != CTRL_EvalSpaceKind_Entity || space_entity != &ctrl_entity_nil)); B32 has_disasm = (dasm_text_info.lines_count != 0 && dasm_info.lines.count != 0); ////////////////////////////// //- rjf: is loading -> equip view with loading information // if(is_loading && !d_ctrl_targets_running()) { rd_store_view_loading_info(is_loading, 0, 0); } ////////////////////////////// //- rjf: do goto vaddr // if(!is_loading && has_disasm && dv->goto_vaddr != 0 && contains_1u64(range, dv->goto_vaddr)) { U64 vaddr = dv->goto_vaddr; U64 line_idx = dasm_line_array_idx_from_code_off__linear_scan(&dasm_info.lines, vaddr-range.min); if(line_idx < dasm_info.lines.count) { S64 line_num = (S64)(line_idx+1); dv->goto_vaddr = 0; cv->goto_line_num = line_num; } } ////////////////////////////// //- rjf: build code contents // if(!is_loading && has_disasm) { rd_code_view_build(scratch.arena, cv, RD_CodeViewBuildFlag_All, code_area_rect, dasm_text_data, &dasm_text_info, &dasm_info.lines, range, dbgi_key); } ////////////////////////////// //- rjf: unpack cursor info // if(!is_loading && has_disasm) { U64 off = dasm_line_array_code_off_from_idx(&dasm_info.lines, rd_regs()->cursor.line-1); rd_regs()->prefer_disasm = 1; rd_regs()->vaddr = range.min+off; rd_regs()->vaddr_range = r1u64(range.min+off, range.min+off); rd_regs()->voff_range = ctrl_voff_range_from_vaddr_range(dasm_module, rd_regs()->vaddr_range); rd_regs()->lines = d_lines_from_dbgi_key_voff(rd_frame_arena(), dbgi_key, rd_regs()->voff_range.min); } ////////////////////////////// //- rjf: build bottom bar // if(!is_loading && has_disasm) UI_FontSize(main_font_size) { ui_set_next_rect(shift_2f32(bottom_bar_rect, scale_2f32(rect.p0, -1.f))); ui_set_next_flags(UI_BoxFlag_DrawBackground); UI_Row UI_TextAlignment(UI_TextAlign_Center) UI_PrefWidth(ui_text_dim(10, 1)) UI_TagF("weak") RD_Font(RD_FontSlot_Code) { U64 cursor_vaddr = (1 <= rd_regs()->cursor.line && rd_regs()->cursor.line <= dasm_info.lines.count) ? (range.min+dasm_info.lines.v[rd_regs()->cursor.line-1].code_off) : 0; if(dasm_module != &ctrl_entity_nil) { ui_labelf("%S", dasm_module->string); ui_spacer(ui_em(1.5f, 1)); } ui_labelf("Address: 0x%I64x, Line: %I64d, Column: %I64d", cursor_vaddr, rd_regs()->cursor.line, rd_regs()->cursor.column); ui_spacer(ui_pct(1, 0)); ui_labelf("(read only)"); ui_labelf("bin"); } } ////////////////////////////// //- rjf: commit storage // dv->cursor = rd_regs()->cursor; dv->mark = rd_regs()->mark; access_close(access); scratch_end(scratch); } //////////////////////////////// //~ rjf: memory @view_hook_impl typedef struct RD_MemoryViewState RD_MemoryViewState; struct RD_MemoryViewState { Rng1U64 last_view_range; B32 last_view_range_inited; Rng1U64 last_cursor_range; B32 last_cursor_range_inited; U64 last_num_of_columns; B32 last_num_of_columns_inited; B32 center_cursor; B32 contain_cursor; B32 snap_scroll; }; EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory) { EV_ExpandInfo info = {0}; info.row_count = 16; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(memory) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); RD_MemoryViewState *mv = rd_view_state(RD_MemoryViewState); ////////////////////////////// //- rjf: if memory views are parameterized by a register-space evaluation, // we will interpret it as an address in the primary module. // if(e_space_match(eval.space, e_base_ctx->thread_reg_space)) { eval = e_value_eval_from_eval(eval); eval.space = e_base_ctx->primary_module->space; } ////////////////////////////// //- rjf: if memory views are parameterized by nothing, we will // default to showing the entire memory space of the primary module. // Rng1U64 view_range = rd_space_range_from_eval(eval); if(eval.space.kind == 0) { eval.space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process), CTRL_EvalSpaceKind_Entity); view_range = rd_whole_range_from_eval_space(eval.space); } ////////////////////////////// //- rjf: unpack parameterization info // Vec4F32 main_bg_color_rgba = ui_color_from_name(str8_lit("background")); Vec4F32 main_bg_color_hsva = hsva_from_rgba(main_bg_color_rgba); Vec4F32 main_tx_color_rgba = ui_color_from_name(str8_lit("text")); Vec4F32 main_tx_color_hsva = hsva_from_rgba(main_tx_color_rgba); F32 main_font_size = ui_bottom_font_size(); U64 cursor_base_vaddr = rd_view_setting_u64_from_name(str8_lit("cursor")); U64 mark_base_vaddr = rd_view_setting_u64_from_name(str8_lit("mark")); U64 cursor_size = rd_view_setting_u64_from_name(str8_lit("cursor_size")); cursor_size = ClampBot(1, cursor_size); U64 initial_cursor_base_vaddr = cursor_base_vaddr; U64 initial_mark_base_vaddr = mark_base_vaddr; U64 num_columns = rd_view_setting_u64_from_name(str8_lit("num_columns")); B32 track_mark_to_cursor = rd_view_setting_b32_from_name(str8_lit("track_mark_to_cursor")); if(num_columns == 0) { num_columns = 16; } num_columns = ClampBot(1, num_columns); UI_ScrollPt2 scroll_pos = rd_view_scroll_pos(); Vec4F32 selection_color = ui_color_from_name(str8_lit("selection")); Vec4F32 border_color = ui_color_from_name(str8_lit("selection")); ////////////////////////////// //- rjf: unpack rich hover info // UI_Key memory_rich_hover_key = ui_key_from_string(ui_active_seed_key(), str8_lit("###rich_hover")); Rng1U64 rich_hover_range = {0}; if(rd_state->hover_regs_slot == RD_RegSlot_VaddrRange && e_space_match(eval.space, rd_get_hover_regs()->eval_space) && !ui_key_match(rd_get_hover_regs()->src_ui_key, memory_rich_hover_key)) { rich_hover_range = rd_get_hover_regs()->vaddr_range; } ////////////////////////////// //- rjf: process commands // for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { default: break; case RD_CmdKind_CenterCursor: { mv->center_cursor = 1; }break; case RD_CmdKind_ContainCursor: { mv->contain_cursor = 1; }break; case RD_CmdKind_GoToAddress: { cursor_base_vaddr = mark_base_vaddr = cmd->regs->vaddr; mv->center_cursor = 1; }break; } } ////////////////////////////// //- rjf: unpack visual params // FNT_Tag font = rd_font_from_slot(RD_FontSlot_Code); FNT_RasterFlags font_raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code); F32 font_size = ui_top_font_size(); F32 big_glyph_advance = fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("H")).x; F32 row_height_px = floor_f32(font_size*2.f); F32 cell_width_px = floor_f32(font_size*2.f); ////////////////////////////// //- rjf: calculate rectangles // F32 scroll_bar_dim = floor_f32(main_font_size*1.5f); Vec2F32 panel_dim = dim_2f32(rect); F32 footer_dim = floor_f32(main_font_size*10.f); Rng2F32 header_rect = r2f32p(0, 0, panel_dim.x, row_height_px); Rng2F32 footer_rect = r2f32p(0, panel_dim.y-footer_dim, panel_dim.x-scroll_bar_dim, panel_dim.y); Rng2F32 content_rect = r2f32p(0, row_height_px, panel_dim.x-scroll_bar_dim, panel_dim.y); ////////////////////////////// //- rjf: determine visible range of rows (occluded & non-occluded) // S64 num_possible_visible_rows = num_possible_visible_rows = dim_2f32(rect).y/row_height_px;; S64 num_possible_nonoccluded_visible_rows = (dim_2f32(content_rect).y - dim_2f32(footer_rect).y) / row_height_px; ////////////////////////////// //- rjf: determine legal scroll range // U64 view_range_last = view_range.max; if(view_range_last != 0) { view_range_last -= 1; } Rng1S64 scroll_idx_rng = r1s64(0, (view_range_last - view_range.min) / num_columns); ////////////////////////////// //- rjf: on cursor rugpull -> update mark if needed // { Rng1U64 cursor_range = r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size); if(mv->last_cursor_range_inited && (mv->last_cursor_range.min != cursor_range.min || mv->last_cursor_range.max != cursor_range.max)) { mv->contain_cursor = 1; if(track_mark_to_cursor) { mark_base_vaddr = cursor_base_vaddr; } } } ////////////////////////////// //- rjf: on num of columns rugpull -> update scroll position // if(mv->last_num_of_columns != num_columns && mv->last_num_of_columns_inited) { mv->center_cursor = 1; mv->snap_scroll = 1; } mv->last_num_of_columns_inited = 1; mv->last_num_of_columns = num_columns; ////////////////////////////// //- rjf: loop: compute boundaries, take events, repeat // B32 need_update = 1; Rng1U64 cursor_valid_rng = {0}; for(;;) { //- rjf: break if no further updates needed if(!need_update) { break; } need_update = 0; //- rjf: take keyboard controls UI_Focus(UI_FocusKind_On) if(ui_is_focus_active()) { U64 next_cursor_base_vaddr = cursor_base_vaddr; U64 next_mark_base_vaddr = mark_base_vaddr; for(UI_Event *evt = 0; ui_next_event(&evt);) { Vec2S64 cell_delta = {0}; switch(evt->delta_unit) { default:{}break; case UI_EventDeltaUnit_Char: { cell_delta.x = (S64)evt->delta_2s32.x; cell_delta.y = (S64)evt->delta_2s32.y; }break; case UI_EventDeltaUnit_Word: case UI_EventDeltaUnit_Page: { if(evt->delta_2s32.x < 0) { cell_delta.x = -(S64)(cursor_base_vaddr%num_columns); } else if(evt->delta_2s32.x > 0) { cell_delta.x = (num_columns-1) - (S64)(cursor_base_vaddr%num_columns); } if(evt->delta_2s32.y < 0) { cell_delta.y = -4; } else if(evt->delta_2s32.y > 0) { cell_delta.y = +4; } }break; } B32 good_action = 0; if(evt->delta_2s32.x != 0 || evt->delta_2s32.y != 0) { good_action = 1; } if(good_action && evt->flags & UI_EventFlag_ZeroDeltaOnSelect && cursor_base_vaddr != mark_base_vaddr) { MemoryZeroStruct(&cell_delta); } if(good_action) { cell_delta.x = ClampBot(cell_delta.x, (S64)-next_cursor_base_vaddr); cell_delta.y = ClampBot(cell_delta.y, (S64)-(next_cursor_base_vaddr/num_columns)); next_cursor_base_vaddr += cell_delta.x; next_cursor_base_vaddr += cell_delta.y*num_columns; } if(good_action && evt->flags & UI_EventFlag_PickSelectSide && cursor_base_vaddr != mark_base_vaddr) { if(evt->delta_2s32.x < 0 || evt->delta_2s32.y < 0) { next_cursor_base_vaddr = Min(cursor_base_vaddr, mark_base_vaddr); } else { next_cursor_base_vaddr = Max(cursor_base_vaddr, mark_base_vaddr); } } if(good_action && !(evt->flags & UI_EventFlag_KeepMark)) { next_mark_base_vaddr = next_cursor_base_vaddr; } if(good_action) { need_update = 1; mv->contain_cursor = 1; ui_eat_event(evt); } } cursor_base_vaddr = next_cursor_base_vaddr; mark_base_vaddr = next_mark_base_vaddr; } //- rjf: clamp cursor cursor_valid_rng = view_range; if(cursor_valid_rng.max != 0) { cursor_valid_rng.max -= 1; } if(cursor_base_vaddr != initial_cursor_base_vaddr) { cursor_base_vaddr = clamp_1u64(cursor_valid_rng, cursor_base_vaddr); } if(mark_base_vaddr != initial_mark_base_vaddr) { mark_base_vaddr = clamp_1u64(cursor_valid_rng, mark_base_vaddr); } //- rjf: center cursor if range has changed if(mv->last_view_range_inited && (mv->last_view_range.max != view_range.max || mv->last_view_range.min != view_range.min)) { mv->center_cursor = 1; } mv->last_view_range_inited = 1; mv->last_view_range = view_range; //- rjf: center cursor if(mv->center_cursor && contains_1u64(view_range, cursor_base_vaddr)) { mv->center_cursor = 0; S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; S64 new_idx = (cursor_row_idx-num_possible_nonoccluded_visible_rows/2+1); new_idx = clamp_1s64(scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } //- rjf: contain cursor if(mv->contain_cursor && contains_1u64(view_range, cursor_base_vaddr)) { mv->contain_cursor = 0; Rng1S64 viz_range_nonoccluded_rows = {0}; viz_range_nonoccluded_rows.min = scroll_pos.y.idx + (S64)(content_rect.y0 / row_height_px); viz_range_nonoccluded_rows.max = viz_range_nonoccluded_rows.min + num_possible_nonoccluded_visible_rows; viz_range_nonoccluded_rows.min = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.min); viz_range_nonoccluded_rows.max = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.max); S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; Rng1S64 cursor_viz_range = r1s64(clamp_1s64(scroll_idx_rng, cursor_row_idx-2), clamp_1s64(scroll_idx_rng, cursor_row_idx+3)); S64 min_delta = Min(0, cursor_viz_range.min-viz_range_nonoccluded_rows.min); S64 max_delta = Max(0, cursor_viz_range.max-viz_range_nonoccluded_rows.max); S64 new_idx = scroll_pos.y.idx+min_delta+max_delta; new_idx = clamp_1s64(scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } //- rjf: snap scroll if(mv->snap_scroll) { mv->snap_scroll = 0; scroll_pos.y.off = 0; } } //////////////////////////// //- rjf: determine selection // Rng1U64 selection = union_1u64(r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size-1), r1u64(mark_base_vaddr, mark_base_vaddr+cursor_size-1)); //////////////////////////// //- rjf: determine visible range of rows (including occluded) // Rng1S64 viz_range_rows = {0}; { viz_range_rows.min = scroll_pos.y.idx + (S64)scroll_pos.y.off - !!(scroll_pos.y.off<0); viz_range_rows.max = scroll_pos.y.idx + (S64)scroll_pos.y.off + num_possible_visible_rows, viz_range_rows.min = clamp_1s64(scroll_idx_rng, viz_range_rows.min); viz_range_rows.max = clamp_1s64(scroll_idx_rng, viz_range_rows.max); } //////////////////////////// //- rjf: bump backwards if we are past the first // if(viz_range_rows.min > 0) { viz_range_rows.min -= 1; content_rect.y0 -= row_height_px; } //////////////////////////// //- rjf: determine visible range of bytes // Rng1U64 viz_range_bytes = {0}; { viz_range_bytes.min = view_range.min + (viz_range_rows.min)*num_columns; viz_range_bytes.max = view_range.min + (viz_range_rows.max+1)*num_columns+1; if(viz_range_bytes.min > viz_range_bytes.max) { Swap(U64, viz_range_bytes.min, viz_range_bytes.max); } viz_range_bytes = intersect_1u64(view_range, viz_range_bytes); } ////////////////////////////// //- rjf: produce fancy strings for all possible byte values in all cells // DR_FStrList byte_fstrs[256] = {0}; DR_FStrList byte_fstrs_selected[256] = {0}; { Vec4F32 selected_color = ui_color_from_name(str8_lit("text")); Vec4F32 full_color = {0}; UI_TagF("neutral") full_color = ui_color_from_name(str8_lit("text")); Vec4F32 zero_color = full_color; UI_TagF("weak") zero_color = ui_color_from_name(str8_lit("text")); for(U64 idx = 0; idx < ArrayCount(byte_fstrs); idx += 1) { U8 byte = (U8)idx; F32 pct = (byte/255.f); Vec4F32 text_color = mix_4f32(zero_color, full_color, pct); if(byte == 0) { text_color.w *= 0.5f; } { DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, text_color, font_size, 0, 0}}; dr_fstrs_push(scratch.arena, &byte_fstrs[idx], &fstr); } { DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, selected_color, font_size, 0, 0}}; dr_fstrs_push(scratch.arena, &byte_fstrs_selected[idx], &fstr); } } } ////////////////////////////// //- rjf: grab windowed memory // U64 visible_memory_size = dim_1u64(viz_range_bytes); U8 *visible_memory = push_array(scratch.arena, U8, visible_memory_size); U64 *visible_memory_change_flags = push_array(scratch.arena, U64, (visible_memory_size+63)/64); U64 *visible_memory_bad_flags = push_array(scratch.arena, U64, (visible_memory_size+63)/64); { e_space_read(eval.space, visible_memory, viz_range_bytes); } if(eval.space.kind == CTRL_EvalSpaceKind_Entity) { CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); if(entity->kind == CTRL_EntityKind_Process) { CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, entity->handle, viz_range_bytes, 0, 0); visible_memory_change_flags = slice.byte_changed_flags; visible_memory_bad_flags = slice.byte_bad_flags; } } ////////////////////////////// //- rjf: grab annotations for windowed range of memory // typedef struct Annotation Annotation; struct Annotation { String8 name_string; String8 kind_string; String8 type_string; Vec4F32 color; Rng1U64 vaddr_range; }; typedef struct AnnotationNode AnnotationNode; struct AnnotationNode { AnnotationNode *next; Annotation *v; }; typedef struct AnnotationList AnnotationList; struct AnnotationList { AnnotationNode *first; AnnotationNode *last; }; AnnotationList *visible_memory_annotations = push_array(scratch.arena, AnnotationList, visible_memory_size); { Access *access = access_open(); CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_Entity *selected_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process); CTRL_CallStack selected_call_stack = ctrl_call_stack_from_thread(access, selected_thread->handle, 1, 0); CTRL_Entity *eval_process = &ctrl_entity_nil; if(eval.space.kind == CTRL_EvalSpaceKind_Entity) { eval_process = rd_ctrl_entity_from_eval_space(eval.space); } //- rjf: fill unwind frame annotations if(selected_call_stack.concrete_frames_count != 0) UI_Tag(str8_lit("weak")) { U64 last_stack_top = regs_rsp_from_arch_block(selected_thread->arch, selected_call_stack.concrete_frames[0]->regs); for(U64 idx = 1; idx < selected_call_stack.concrete_frames_count; idx += 1) { CTRL_CallStackFrame *f = selected_call_stack.concrete_frames[idx]; U64 f_stack_top = regs_rsp_from_arch_block(selected_thread->arch, f->regs); Rng1U64 frame_vaddr_range = r1u64(last_stack_top, f_stack_top); Rng1U64 frame_vaddr_range_in_viz = intersect_1u64(frame_vaddr_range, viz_range_bytes); last_stack_top = f_stack_top; if(dim_1u64(frame_vaddr_range_in_viz) != 0) { Access *access = access_open(); U64 f_rip_vaddr = regs_rip_from_arch_block(selected_thread->arch, f->regs); CTRL_Entity *module = ctrl_module_from_process_vaddr(selected_process, f_rip_vaddr); U64 f_rip_voff = ctrl_voff_from_vaddr(module, f_rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, f_rip_voff); String8 procedure_name = {0}; procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); access_close(access); if(procedure_name.size != 0) { Annotation *annotation = push_array(scratch.arena, Annotation, 1); annotation->name_string = push_str8_copy(scratch.arena, procedure_name); annotation->kind_string = str8_lit("Call Stack Frame"); annotation->color = v4f32(0, 0, 0, 0); annotation->vaddr_range = frame_vaddr_range; for(U64 vaddr = frame_vaddr_range_in_viz.min; vaddr < frame_vaddr_range_in_viz.max; vaddr += 1) { U64 visible_byte_idx = vaddr - viz_range_bytes.min; AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, n); } } } } } //- rjf: fill selected thread stack range annotation if(selected_call_stack.concrete_frames_count > 0) { U64 stack_base_vaddr = selected_thread->stack_base; U64 stack_top_vaddr = regs_rsp_from_arch_block(selected_thread->arch, selected_call_stack.concrete_frames[0]->regs); Rng1U64 stack_vaddr_range = r1u64(stack_base_vaddr, stack_top_vaddr); Rng1U64 stack_vaddr_range_in_viz = intersect_1u64(stack_vaddr_range, viz_range_bytes); if(dim_1u64(stack_vaddr_range_in_viz) != 0) { Annotation *annotation = push_array(scratch.arena, Annotation, 1); annotation->name_string = selected_thread->string.size ? selected_thread->string : push_str8f(scratch.arena, "TID: %I64u", selected_thread->id); annotation->kind_string = str8_lit("Stack"); annotation->color = rd_color_from_ctrl_entity(selected_thread); annotation->vaddr_range = stack_vaddr_range; for(U64 vaddr = stack_vaddr_range_in_viz.min; vaddr < stack_vaddr_range_in_viz.max; vaddr += 1) { U64 visible_byte_idx = vaddr - viz_range_bytes.min; AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, n); } } } //- rjf: fill local variable annotations if(e_space_match(rd_eval_space_from_ctrl_entity(selected_process, CTRL_EvalSpaceKind_Entity), eval.space)) { Vec4F32 local_color = ui_color_from_name(str8_lit("code_local")); Vec4F32 color_gen_table[] = { mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.2f), mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.4f), mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.6f), mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.8f), }; U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count); for(E_String2NumMapNode *n = e_ir_ctx->locals_map->first; n != 0; n = n->order_next) { String8 local_name = n->string; E_Eval local_eval = e_eval_from_string(local_name); if(local_eval.irtree.mode == E_Mode_Offset) { E_TypeKind local_eval_type_kind = e_type_kind_from_key(local_eval.irtree.type_key); U64 local_eval_type_size = e_type_byte_size_from_key(local_eval.irtree.type_key); Rng1U64 vaddr_rng = r1u64(local_eval.value.u64, local_eval.value.u64+local_eval_type_size); Rng1U64 vaddr_rng_in_visible = intersect_1u64(viz_range_bytes, vaddr_rng); if(vaddr_rng_in_visible.max != vaddr_rng_in_visible.min) { Annotation *annotation = push_array(scratch.arena, Annotation, 1); { annotation->name_string = push_str8_copy(scratch.arena, local_name); annotation->kind_string = str8_lit("Local"); annotation->type_string = e_type_string_from_key(scratch.arena, local_eval.irtree.type_key); annotation->color = color_gen_table[(vaddr_rng.min/7)%ArrayCount(color_gen_table)]; annotation->vaddr_range = vaddr_rng; } for(U64 vaddr = vaddr_rng_in_visible.min; vaddr < vaddr_rng_in_visible.max; vaddr += 1) { AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); } } } } } //- rjf: fill procedures annotations if(eval_process != &ctrl_entity_nil) { Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); Vec4F32 color_gen_table[] = { mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.2f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.4f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.6f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.8f), }; for(U64 vaddr = viz_range_bytes.min, next_vaddr = 0; viz_range_bytes.min <= vaddr && vaddr <= viz_range_bytes.max; vaddr = next_vaddr) { next_vaddr = vaddr+1; Access *access = access_open(); CTRL_Entity *module = ctrl_module_from_process_vaddr(eval_process, vaddr); if(module != &ctrl_entity_nil) { U64 voff = ctrl_voff_from_vaddr(module, vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); RDI_Scope *root_scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); if(procedure->root_scope_idx != 0) { Rng1U64 voff_range = r1u64(rdi_first_voff_from_scope(rdi, root_scope), rdi_opl_voff_from_scope(rdi, root_scope)); Rng1U64 vaddr_range = ctrl_vaddr_range_from_voff_range(module, voff_range); next_vaddr = vaddr_range.max; next_vaddr = Max(next_vaddr, vaddr+1); Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); if(vaddr_range_in_visible.min < vaddr_range_in_visible.max) { String8 procedure_name = {0}; procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); Annotation *annotation = push_array(scratch.arena, Annotation, 1); { annotation->name_string = push_str8_copy(scratch.arena, procedure_name); annotation->kind_string = str8_lit("Procedure"); annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; annotation->vaddr_range = vaddr_range; } for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) { AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); } } } } access_close(access); } } //- rjf: fill globals annotations if(eval_process != &ctrl_entity_nil) { Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); Vec4F32 color_gen_table[] = { mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.2f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.4f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.6f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.8f), }; for(U64 vaddr = viz_range_bytes.min, next_vaddr = 0; viz_range_bytes.min <= vaddr && vaddr <= viz_range_bytes.max; vaddr = next_vaddr) { next_vaddr = vaddr+1; Access *access = access_open(); CTRL_Entity *module = ctrl_module_from_process_vaddr(eval_process, vaddr); if(module != &ctrl_entity_nil) { U64 voff = ctrl_voff_from_vaddr(module, vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff); if(gvar->voff != 0) { RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, gvar->type_idx); Rng1U64 voff_range = r1u64(gvar->voff, gvar->voff + type_node->byte_size); Rng1U64 vaddr_range = ctrl_vaddr_range_from_voff_range(module, voff_range); next_vaddr = vaddr_range.max; next_vaddr = Max(next_vaddr, vaddr+1); Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); if(vaddr_range_in_visible.min < vaddr_range_in_visible.max) { String8 gvar_name = {0}; gvar_name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &gvar_name.size); Annotation *annotation = push_array(scratch.arena, Annotation, 1); { annotation->name_string = push_str8_copy(scratch.arena, gvar_name); annotation->kind_string = str8_lit("Global"); annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; annotation->vaddr_range = vaddr_range; } for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) { AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); } } } } access_close(access); } } //- rjf: fill debuggee-specified annotations if(eval_process != &ctrl_entity_nil) UI_TagF(".") UI_TagF("pop") { Vec4F32 symbol_color = ui_color_from_name(str8_lit("background")); Vec4F32 color_gen_table[] = { mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.00f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.05f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.10f), mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.15f), }; for(CTRL_Entity *child = eval_process->first; child != &ctrl_entity_nil; child = child->next) { if(child->kind != CTRL_EntityKind_AddressRangeAnnotation) { continue; } String8 name = child->string; Rng1U64 vaddr_range = child->vaddr_range; Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); if(vaddr_range_in_visible.max > vaddr_range_in_visible.min) { Annotation *annotation = push_array(scratch.arena, Annotation, 1); { annotation->name_string = push_str8_copy(scratch.arena, name); annotation->kind_string = str8_lit("Annotation"); annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; annotation->vaddr_range = vaddr_range; } for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) { AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); n->v = annotation; SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); } } } } access_close(access); } ////////////////////////////// //- rjf: build main container // UI_Box *container_box = &ui_nil_box; { Vec2F32 dim = dim_2f32(rect); ui_set_next_fixed_width(dim.x); ui_set_next_fixed_height(dim.y); ui_set_next_child_layout_axis(Axis2_Y); container_box = ui_build_box_from_stringf(0, "memory_view_container"); } ////////////////////////////// //- rjf: build scroll bar // UI_Parent(container_box) UI_FontSize(main_font_size) { ui_set_next_fixed_x(content_rect.x1); ui_set_next_fixed_y(0); ui_set_next_fixed_width(scroll_bar_dim); ui_set_next_fixed_height(dim_2f32(rect).y); { scroll_pos.y = ui_scroll_bar(Axis2_Y, ui_px(scroll_bar_dim, 1.f), scroll_pos.y, scroll_idx_rng, num_possible_visible_rows); } } ////////////////////////////// //- rjf: build header // UI_Box *header_box = &ui_nil_box; UI_Parent(container_box) UI_TagF("floating") { UI_Rect(r2f32p(0, 0, dim_2f32(rect).x - scroll_bar_dim, row_height_px)) header_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideBottom| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawDropShadow| UI_BoxFlag_DrawBackgroundBlur| UI_BoxFlag_Floating, "table_header"); UI_Parent(header_box) RD_Font(RD_FontSlot_Code) UI_FontSize(font_size) { UI_PrefWidth(ui_px(big_glyph_advance*20.f, 1.f)) ui_labelf("Address"); UI_PrefWidth(ui_px(cell_width_px, 1.f)) UI_TextAlignment(UI_TextAlign_Center) { Rng1U64 col_selection_rng = r1u64(cursor_base_vaddr%num_columns, mark_base_vaddr%num_columns); for(U64 row_off = 0; row_off < num_columns; row_off += 1) { B32 column_is_selected = (selection.min%num_columns <= row_off && row_off <= selection.max%num_columns); UI_TagF(column_is_selected ? "" : "weak") ui_labelf("%I64X", row_off); } } ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f)); UI_WidthFill ui_labelf("ASCII"); } } ////////////////////////////// //- rjf: build footer // UI_Box *footer_box = &ui_nil_box; UI_Parent(container_box) UI_FontSize(main_font_size) UI_TagF("floating") { ui_set_next_fixed_x(footer_rect.x0); ui_set_next_fixed_y(footer_rect.y0); ui_set_next_fixed_width(dim_2f32(footer_rect).x); ui_set_next_fixed_height(dim_2f32(footer_rect).y); footer_box = ui_build_box_from_stringf(UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_DrawDropShadow, "footer"); UI_Parent(footer_box) RD_Font(RD_FontSlot_Code) { UI_PrefWidth(ui_em(7.5f, 1.f)) UI_HeightFill UI_Column UI_TagF("weak") UI_PrefHeight(ui_em(2.f, 0.f)) { ui_labelf("Address:"); ui_labelf("U8:"); ui_labelf("U16:"); ui_labelf("U32:"); ui_labelf("U64:"); } UI_PrefWidth(ui_em(45.f, 1.f)) UI_HeightFill UI_Column UI_PrefHeight(ui_em(2.f, 0.f)) { ui_labelf("%016I64X", cursor_base_vaddr); { U64 as_u8 = 0; U64 as_u16 = 0; U64 as_u32 = 0; U64 as_u64 = 0; e_space_read(eval.space, &as_u64, r1u64(cursor_base_vaddr, cursor_base_vaddr+1)); as_u32 = *(U32 *)&as_u64; as_u16 = *(U16 *)&as_u64; as_u8 = *(U8 *)&as_u64; ui_labelf("%02X (%I64u)", as_u8, as_u8); ui_labelf("%04X (%I64u)", as_u16, as_u16); ui_labelf("%08X (%I64u)", as_u32, as_u32); ui_labelf("%016I64X (%I64u)", as_u64, as_u64); } } } } ////////////////////////////// //- rjf: build scrollable box // UI_Box *scrollable_box = &ui_nil_box; UI_Parent(container_box) { ui_set_next_fixed_x(content_rect.x0); ui_set_next_fixed_y(content_rect.y0); ui_set_next_fixed_width(dim_2f32(content_rect).x); ui_set_next_fixed_height(dim_2f32(content_rect).y); scrollable_box = ui_build_box_from_stringf(UI_BoxFlag_Clip| UI_BoxFlag_Scroll| UI_BoxFlag_AllowOverflowY, "scrollable_box"); container_box->view_off.x = container_box->view_off_target.x = scroll_pos.x.idx + scroll_pos.x.off; scrollable_box->view_off.y = scrollable_box->view_off_target.y = floor_f32(row_height_px*mod_f32(scroll_pos.y.off, 1.f) + row_height_px*(scroll_pos.y.off < 0)); } ////////////////////////////// //- rjf: build row container/overlay // UI_Box *row_container_box = &ui_nil_box; UI_Box *row_overlay_box = &ui_nil_box; UI_Parent(scrollable_box) UI_WidthFill UI_HeightFill { ui_set_next_child_layout_axis(Axis2_Y); row_container_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "row_container"); UI_Parent(row_container_box) { row_overlay_box = ui_build_box_from_stringf(UI_BoxFlag_Floating, "row_overlay"); } } ////////////////////////////// //- rjf: interact with row container // U64 mouse_hover_byte_num = 0; { UI_Signal sig = ui_signal_from_box(row_container_box); // rjf: calculate hovered byte if(ui_hovering(sig) || ui_dragging(sig)) { Vec2F32 mouse_rel = sub_2f32(ui_mouse(), row_container_box->rect.p0); U64 row_idx = ClampBot(0, mouse_rel.y) / row_height_px; // rjf: try from cells if(mouse_hover_byte_num == 0) { U64 col_idx = ClampBot(mouse_rel.x-big_glyph_advance*20.f, 0)/cell_width_px; if(col_idx < num_columns) { mouse_hover_byte_num = viz_range_bytes.min + row_idx*num_columns + col_idx + 1; } } // rjf: try from ascii if(mouse_hover_byte_num == 0) { U64 col_idx = ClampBot(mouse_rel.x - (big_glyph_advance*20.f + cell_width_px*num_columns + big_glyph_advance*1.5f), 0)/big_glyph_advance; col_idx = ClampTop(col_idx, num_columns-1); mouse_hover_byte_num = viz_range_bytes.min + row_idx*num_columns + col_idx + 1; } mouse_hover_byte_num = Clamp(1, mouse_hover_byte_num, 0x7FFFFFFFFFFFull+1); } // rjf: press -> focus panel if(ui_pressed(sig)) { rd_cmd(RD_CmdKind_FocusPanel); } // rjf: click & drag -> select if(ui_dragging(sig) && mouse_hover_byte_num != 0) { if(!contains_2f32(sig.box->rect, ui_mouse())) { mv->contain_cursor = 1; } cursor_base_vaddr = mouse_hover_byte_num-1; if(ui_pressed(sig)) { mark_base_vaddr = cursor_base_vaddr; } } // rjf: ctrl+scroll -> change font size if(ui_hovering(sig)) { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Scroll && evt->modifiers & OS_Modifier_Ctrl) { ui_eat_event(evt); if(evt->delta_2f32.y < 0) { rd_cmd(RD_CmdKind_IncViewFontSize); } else if(evt->delta_2f32.y > 0) { rd_cmd(RD_CmdKind_DecViewFontSize); } } } } // rjf: rich hover if(mouse_hover_byte_num != 0) { Rng1U64 hovered_range = r1u64(mouse_hover_byte_num-1, mouse_hover_byte_num-1 + 1); if(ui_dragging(sig) && !ui_pressed(sig) && dim_1u64(selection) != 0) { hovered_range = selection; } RD_RegsScope(.vaddr_range = hovered_range, .eval_space = eval.space, .src_ui_key = memory_rich_hover_key) rd_set_hover_regs(RD_RegSlot_VaddrRange); } } ////////////////////////////// //- rjf: build rows // UI_Parent(row_container_box) RD_Font(RD_FontSlot_Code) UI_FontSize(font_size) { U8 *row_ascii_buffer = push_array(scratch.arena, U8, num_columns); UI_WidthFill UI_PrefHeight(ui_px(row_height_px, 1.f)) for(S64 row_idx = viz_range_rows.min; row_idx <= viz_range_rows.max; row_idx += 1) { Rng1U64 row_range_bytes = r1u64(view_range.min + row_idx*num_columns, view_range.min + (row_idx+1)*num_columns); if(row_range_bytes.min >= view_range.max) { break; } UI_BoxFlags row_flags = 0; UI_Box *row = ui_build_box_from_stringf(row_flags, "row_%I64x", row_range_bytes.min); UI_Parent(row) { UI_PrefWidth(ui_px(big_glyph_advance*20.f, 1.f)) { if(!(selection.max >= row_range_bytes.min && selection.min < row_range_bytes.max)) { ui_set_next_tag(str8_lit("weak")); } ui_labelf("0x%016I64x", row_range_bytes.min); } UI_PrefWidth(ui_px(cell_width_px, 1.f)) UI_TextAlignment(UI_TextAlign_Center) UI_CornerRadius(0) { for(U64 col_idx = 0; col_idx < num_columns; col_idx += 1) { // rjf: unpack information about this slot U64 visible_byte_idx = (row_idx-viz_range_rows.min)*num_columns + col_idx; U64 global_byte_idx = viz_range_bytes.min+visible_byte_idx; U64 global_byte_num = global_byte_idx+1; // rjf: build space, if this cell is out-of-range if(global_byte_idx >= viz_range_bytes.max) { ui_build_box_from_key(0, ui_key_zero()); } // rjf: build actual cell else { // rjf: unpack byte info B32 byte_is_selected = (selection.min <= global_byte_idx && global_byte_idx <= selection.max); U8 byte_value = visible_memory[visible_byte_idx]; B32 byte_is_bad = !!(visible_memory_bad_flags[visible_byte_idx/64] & (1ull<<(visible_byte_idx%64))); B32 byte_is_changed = !!(visible_memory_change_flags[visible_byte_idx/64] & (1ull<<(visible_byte_idx%64))); AnnotationNode *annotation_node = visible_memory_annotations[visible_byte_idx].first; // rjf: unpack visual cell info UI_BoxFlags cell_flags = 0; Vec4F32 cell_bg_rgba = {0}; Vec4F32 cell_bd_rgba = ui_color_from_name(str8_lit("text")); if(global_byte_num == mouse_hover_byte_num) { cell_flags |= UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawDropShadow; } if(annotation_node != 0) { cell_flags |= UI_BoxFlag_DrawBackground; Vec4F32 cell_bg_color_rgba = annotation_node->v->color; Vec4F32 cell_bg_color_hsva = hsva_from_rgba(cell_bg_color_rgba); cell_bg_rgba = mix_4f32(cell_bg_color_rgba, main_bg_color_rgba, clamp_1f32(r1f32(0, 1), 1.f - abs_f32(cell_bg_color_hsva.z - main_tx_color_hsva.z)*0.5f)); } if(selection.min == global_byte_idx) { cell_flags |= UI_BoxFlag_DrawSideLeft; } if(selection.max == global_byte_idx) { cell_flags |= UI_BoxFlag_DrawSideRight; } if(row_idx == (selection.min - view_range.min)/num_columns && selection.min <= global_byte_idx && global_byte_idx <= selection.max) { cell_flags |= UI_BoxFlag_DrawSideTop; } if(row_idx == (selection.max - view_range.min)/num_columns && selection.min <= global_byte_idx && global_byte_idx <= selection.max) { cell_flags |= UI_BoxFlag_DrawSideBottom; } if(contains_1u64(rich_hover_range, global_byte_idx)) UI_TagF("pop") { cell_flags |= UI_BoxFlag_DrawBackground; cell_bg_rgba = ui_color_from_name(str8_lit("background")); } if(byte_is_changed) UI_TagF("fresh") { cell_flags |= UI_BoxFlag_DrawBackground; cell_bg_rgba = ui_color_from_name(str8_lit("background")); } if(byte_is_bad) UI_TagF("bad_pop") { cell_flags |= UI_BoxFlag_DrawBackground; cell_bg_rgba = ui_color_from_name(str8_lit("background")); } // rjf: build if(cell_bd_rgba.w != 0) { ui_set_next_border_color(cell_bd_rgba); } if(cell_bg_rgba.w != 0) { ui_set_next_background_color(cell_bg_rgba); } UI_Box *cell_box = ui_build_box_from_key(UI_BoxFlag_DrawText|cell_flags, ui_key_zero()); if(byte_is_selected || byte_is_changed) { ui_box_equip_display_fstrs(cell_box, &byte_fstrs_selected[byte_value]); } else { ui_box_equip_display_fstrs(cell_box, &byte_fstrs[byte_value]); } { for(AnnotationNode *a_n = annotation_node; a_n != 0; a_n = a_n->next) { Annotation *a = a_n->v; if(global_byte_idx == a->vaddr_range.min) UI_Parent(row_overlay_box) { F32 size = cell_width_px/4.f + cell_width_px/8.f*ui_anim(ui_key_from_stringf(ui_active_seed_key(), "###annotation_hovered_%I64x_%I64x", a->vaddr_range.min, a->vaddr_range.max), (F32)!!(a->vaddr_range.min+1 <= mouse_hover_byte_num && mouse_hover_byte_num <= a->vaddr_range.max)); ui_set_next_border_color(a->color); ui_set_next_fixed_x(big_glyph_advance*20.f + col_idx*cell_width_px + -size*0.5f); ui_set_next_fixed_y((row_idx-viz_range_rows.min)*row_height_px + -size*0.5f); ui_set_next_fixed_width(size); ui_set_next_fixed_height(size); ui_set_next_corner_radius_00(cell_width_px/8.f); ui_set_next_corner_radius_01(cell_width_px/8.f); ui_set_next_corner_radius_10(cell_width_px/8.f); ui_set_next_corner_radius_11(cell_width_px/8.f); ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } if(global_byte_idx+1 == a->vaddr_range.max) UI_Parent(row_overlay_box) { F32 size = cell_width_px/4.f + cell_width_px/8.f*ui_anim(ui_key_from_stringf(ui_active_seed_key(), "###annotation_hovered_%I64x_%I64x", a->vaddr_range.min, a->vaddr_range.max), (F32)!!(a->vaddr_range.min+1 <= mouse_hover_byte_num && mouse_hover_byte_num <= a->vaddr_range.max)); ui_set_next_border_color(a->color); ui_set_next_fixed_x(big_glyph_advance*20.f + (col_idx+1)*cell_width_px + -size*0.5f); ui_set_next_fixed_y((row_idx-viz_range_rows.min)*row_height_px + row_height_px + -size*0.5f); ui_set_next_fixed_width(size); ui_set_next_fixed_height(size); ui_set_next_corner_radius_00(cell_width_px/8.f); ui_set_next_corner_radius_01(cell_width_px/8.f); ui_set_next_corner_radius_10(cell_width_px/8.f); ui_set_next_corner_radius_11(cell_width_px/8.f); ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawSideRight|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } } } if(annotation_node != 0 && mouse_hover_byte_num == global_byte_num) { UI_Tooltip UI_FontSize(ui_top_font_size()) UI_PrefHeight(ui_px(ui_top_font_size()*1.75f, 1.f)) { for(AnnotationNode *a_n = annotation_node; a_n != 0; a_n = a_n->next) { Annotation *a = a_n->v; UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(10, 1)) { RD_Font(RD_FontSlot_Code) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("code_default")), a->name_string); UI_TagF("weak") RD_Font(RD_FontSlot_Main) ui_label(a->kind_string); } if(a->type_string.size != 0) { rd_code_label(1.f, 1, ui_color_from_name(str8_lit("code_type")), a->type_string); } UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(str8_from_memory_size(scratch.arena, dim_1u64(a->vaddr_range))); if(a_n->next != 0) { ui_spacer(ui_em(1.5f, 1.f)); } } } } } } } ui_spacer(ui_px(big_glyph_advance*1.5f, 1.f)); UI_WidthFill { MemoryZero(row_ascii_buffer, num_columns); U64 num_bytes_this_row = 0; for(U64 col_idx = 0; col_idx < num_columns; col_idx += 1) { U64 visible_byte_idx = (row_idx-viz_range_rows.min)*num_columns + col_idx; if(visible_byte_idx < visible_memory_size) { U8 byte_value = visible_memory[visible_byte_idx]; row_ascii_buffer[col_idx] = byte_value; if(byte_value <= 32 || 127 < byte_value) { row_ascii_buffer[col_idx] = '.'; } num_bytes_this_row += 1; } } String8 ascii_text = str8(row_ascii_buffer, num_bytes_this_row); UI_Box *ascii_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "%S###ascii_row_%I64x", ascii_text, row_range_bytes.min); if(selection.max >= row_range_bytes.min && selection.min < row_range_bytes.max) { Rng1U64 selection_in_row = intersect_1u64(row_range_bytes, selection); DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) { Vec2F32 text_pos = ui_box_text_position(ascii_box); Vec4F32 color = selection_color; dr_rect(r2f32p(text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, selection_in_row.min+0-row_range_bytes.min)).x - font_size/8.f, ascii_box->rect.y0, text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, selection_in_row.max+1-row_range_bytes.min)).x + font_size/4.f, ascii_box->rect.y1), color, 0, 0, 1.f); } ui_box_equip_draw_bucket(ascii_box, bucket); } if(mouse_hover_byte_num != 0 && contains_1u64(row_range_bytes, mouse_hover_byte_num-1)) { DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) { Vec2F32 text_pos = ui_box_text_position(ascii_box); Vec4F32 color = border_color; dr_rect(r2f32p(text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, mouse_hover_byte_num-1-row_range_bytes.min)).x - font_size/8.f, ascii_box->rect.y0, text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, mouse_hover_byte_num+0-row_range_bytes.min)).x + font_size/4.f, ascii_box->rect.y1), color, 1.f, 3.f, 1.f); } ui_box_equip_draw_bucket(ascii_box, bucket); } } } } } ////////////////////////////// //- rjf: scroll // { UI_Signal sig = ui_signal_from_box(scrollable_box); if(sig.scroll.y != 0) { S64 new_idx = scroll_pos.y.idx + sig.scroll.y; new_idx = clamp_1s64(scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); } } ////////////////////////////// //- rjf: re-clamp // if(cursor_base_vaddr != initial_cursor_base_vaddr) { cursor_base_vaddr = clamp_1u64(cursor_valid_rng, cursor_base_vaddr); } if(mark_base_vaddr != initial_mark_base_vaddr) { mark_base_vaddr = clamp_1u64(cursor_valid_rng, mark_base_vaddr); } ////////////////////////////// //- rjf: save parameters // mv->last_cursor_range = r1u64(cursor_base_vaddr, cursor_base_vaddr + cursor_size); mv->last_cursor_range_inited = 1; if(cursor_base_vaddr != initial_cursor_base_vaddr) { rd_store_view_param_u64(str8_lit("cursor"), cursor_base_vaddr); } if(mark_base_vaddr != initial_mark_base_vaddr) { rd_store_view_param_u64(str8_lit("mark"), mark_base_vaddr); } rd_store_view_scroll_pos(scroll_pos); scratch_end(scratch); ProfEnd(); } //////////////////////////////// //~ rjf: "graph" EV_EXPAND_RULE_INFO_FUNCTION_DEF(graph) { EV_ExpandInfo info = {0}; info.row_count = 8; info.single_item = 1; return info; } //////////////////////////////// //~ rjf: bitmap @view_hook_impl typedef struct RD_BitmapTopology RD_BitmapTopology; struct RD_BitmapTopology { Vec2S16 dim; R_Tex2DFormat fmt; }; typedef struct RD_BitmapBoxDrawData RD_BitmapBoxDrawData; struct RD_BitmapBoxDrawData { Rng2F32 src; R_Handle texture; F32 loaded_t; B32 hovered; Vec2S32 mouse_px; F32 ui_per_bmp_px; }; typedef struct RD_BitmapCanvasBoxDrawData RD_BitmapCanvasBoxDrawData; struct RD_BitmapCanvasBoxDrawData { Vec2F32 view_center_pos; F32 zoom; }; internal AC_Artifact rd_bitmap_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { Access *access = access_open(); //- rjf: unpack key U128 hash = {0}; RD_BitmapTopology top = {0}; { U64 key_read_off = 0; key_read_off += str8_deserial_read_struct(key, key_read_off, &hash); key_read_off += str8_deserial_read_struct(key, key_read_off, &top); } String8 data = c_data_from_hash(access, hash); //- rjf: create texture R_Handle texture = {0}; if(top.dim.x > 0 && top.dim.y > 0 && data.size >= (U64)top.dim.x*(U64)top.dim.y*(U64)r_tex2d_format_bytes_per_pixel_table[top.fmt]) { texture = r_tex2d_alloc(R_ResourceKind_Static, v2s32(top.dim.x, top.dim.y), top.fmt, data.str); } //- rjf: bundle as artifact AC_Artifact artifact = {0}; StaticAssert(sizeof(artifact) >= sizeof(texture), tex_artifact_size_check); MemoryCopy(&artifact, &texture, Min(sizeof(texture), sizeof(artifact))); access_close(access); return artifact; } internal void rd_bitmap_artifact_destroy(AC_Artifact artifact) { R_Handle texture = {0}; MemoryCopy(&texture, &artifact, Min(sizeof(texture), sizeof(artifact))); r_tex2d_release(texture); } internal Vec2F32 rd_bitmap_screen_from_canvas_pos(Vec2F32 view_center_pos, F32 zoom, Rng2F32 rect, Vec2F32 cvs) { Vec2F32 scr = { (rect.x0+rect.x1)/2 + (cvs.x - view_center_pos.x) * zoom, (rect.y0+rect.y1)/2 + (cvs.y - view_center_pos.y) * zoom, }; return scr; } internal Rng2F32 rd_bitmap_screen_from_canvas_rect(Vec2F32 view_center_pos, F32 zoom, Rng2F32 rect, Rng2F32 cvs) { Rng2F32 scr = r2f32(rd_bitmap_screen_from_canvas_pos(view_center_pos, zoom, rect, cvs.p0), rd_bitmap_screen_from_canvas_pos(view_center_pos, zoom, rect, cvs.p1)); return scr; } internal Vec2F32 rd_bitmap_canvas_from_screen_pos(Vec2F32 view_center_pos, F32 zoom, Rng2F32 rect, Vec2F32 scr) { Vec2F32 cvs = { (scr.x - (rect.x0+rect.x1)/2) / zoom + view_center_pos.x, (scr.y - (rect.y0+rect.y1)/2) / zoom + view_center_pos.y, }; return cvs; } internal Rng2F32 rd_bitmap_canvas_from_screen_rect(Vec2F32 view_center_pos, F32 zoom, Rng2F32 rect, Rng2F32 scr) { Rng2F32 cvs = r2f32(rd_bitmap_canvas_from_screen_pos(view_center_pos, zoom, rect, scr.p0), rd_bitmap_canvas_from_screen_pos(view_center_pos, zoom, rect, scr.p1)); return cvs; } internal UI_BOX_CUSTOM_DRAW(rd_bitmap_view_canvas_box_draw) { RD_BitmapCanvasBoxDrawData *draw_data = (RD_BitmapCanvasBoxDrawData *)user_data; Rng2F32 rect_scrn = box->rect; Rng2F32 rect_cvs = rd_bitmap_canvas_from_screen_rect(draw_data->view_center_pos, draw_data->zoom, rect_scrn, rect_scrn); F32 grid_cell_size_cvs = box->font_size*10.f; F32 grid_line_thickness_px = Max(2.f, box->font_size*0.1f); Vec4F32 grid_line_color = {0}; UI_TagF("weak") { grid_line_color = ui_color_from_name(str8_lit("text")); } for EachEnumVal(Axis2, axis) { for(F32 v = rect_cvs.p0.v[axis] - mod_f32(rect_cvs.p0.v[axis], grid_cell_size_cvs); v < rect_cvs.p1.v[axis]; v += grid_cell_size_cvs) { Vec2F32 p_cvs = {0}; p_cvs.v[axis] = v; Vec2F32 p_scr = rd_bitmap_screen_from_canvas_pos(draw_data->view_center_pos, draw_data->zoom, rect_scrn, p_cvs); Rng2F32 rect = {0}; rect.p0.v[axis] = p_scr.v[axis] - grid_line_thickness_px/2; rect.p1.v[axis] = p_scr.v[axis] + grid_line_thickness_px/2; rect.p0.v[axis2_flip(axis)] = box->rect.p0.v[axis2_flip(axis)]; rect.p1.v[axis2_flip(axis)] = box->rect.p1.v[axis2_flip(axis)]; dr_rect(rect, grid_line_color, 0, 0, 1.f); } } } EV_EXPAND_RULE_INFO_FUNCTION_DEF(bitmap) { EV_ExpandInfo info = {0}; info.row_count = 8; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(bitmap) { Temp scratch = scratch_begin(0, 0); Access *access = access_open(); ////////////////////////////// //- rjf: if parameterized by a register-space evaluation, interpret as an // address in the primary module. // if(e_space_match(eval.space, e_base_ctx->thread_reg_space)) { eval = e_value_eval_from_eval(eval); eval.space = e_base_ctx->primary_module->space; } ////////////////////////////// //- rjf: evaluate expression // Vec2S32 dim = v2s32((S32)rd_view_setting_u64_from_name(str8_lit("w")), (S32)rd_view_setting_u64_from_name(str8_lit("h"))); String8 fmt_string = rd_view_setting_from_name(str8_lit("fmt")); R_Tex2DFormat fmt = R_Tex2DFormat_RGBA8; for EachEnumVal(R_Tex2DFormat, f) { if(str8_match(fmt_string, r_tex2d_format_display_string_table[f], StringMatchFlag_CaseInsensitive)) { fmt = f; break; } } Rng1U64 eval_range = e_range_from_eval(eval); U64 base_offset = eval_range.min; U64 expected_size = dim.x*dim.y*r_tex2d_format_bytes_per_pixel_table[fmt]; Rng1U64 offset_range = r1u64(base_offset, base_offset + expected_size); ////////////////////////////// //- rjf: unpack params // F32 zoom = rd_view_setting_value_from_name(str8_lit("zoom")).f32; Vec2F32 view_center_pos = { rd_view_setting_value_from_name(str8_lit("x")).f32, rd_view_setting_value_from_name(str8_lit("y")).f32, }; if(zoom == 0) { F32 available_dim_y = dim_2f32(rect).y; F32 image_dim_y = (F32)dim.y; if(image_dim_y != 0) { zoom = (available_dim_y / image_dim_y) * 0.8f; } else { zoom = 1.f; } } ////////////////////////////// //- rjf: map expression artifacts -> texture // C_Key texture_key = rd_key_from_eval_space_range(eval.space, offset_range, 0); RD_BitmapTopology topology = {v2s16(dim.x, dim.y), fmt}; U128 data_hash = {0}; R_Handle texture = {0}; for EachIndex(rewind_idx, C_KEY_HASH_HISTORY_COUNT) { U128 hash = c_hash_from_key(texture_key, rewind_idx); #pragma pack(push, 1) struct { U128 hash; RD_BitmapTopology top; } key_data = {hash, topology}; #pragma pack(pop) String8 key = str8_struct(&key_data); AC_Artifact artifact = ac_artifact_from_key(access, key, rd_bitmap_artifact_create, rd_bitmap_artifact_destroy, 0); R_Handle texture_candidate = {0}; MemoryCopy(&texture_candidate, &artifact, Min(sizeof(texture_candidate), sizeof(artifact))); if(!r_handle_match(texture_candidate, r_handle_zero())) { data_hash = hash; texture = texture_candidate; break; } } String8 data = c_data_from_hash(access, data_hash); ////////////////////////////// //- rjf: equip loading info // if(offset_range.max != offset_range.min && eval.string.size != 0 && eval.msgs.max_kind == E_MsgKind_Null && (u128_match(data_hash, u128_zero()) || r_handle_match(texture, r_handle_zero()) || data.size == 0)) { rd_store_view_loading_info(1, 0, 0); } ////////////////////////////// //- rjf: build canvas box // UI_Box *canvas_box = &ui_nil_box; Vec2F32 canvas_dim = dim_2f32(rect); Rng2F32 canvas_rect = r2f32p(0, 0, canvas_dim.x, canvas_dim.y); UI_Rect(canvas_rect) { canvas_box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable|UI_BoxFlag_Scroll, "bmp_canvas"); } ////////////////////////////// //- rjf: canvas dragging // UI_Signal canvas_sig = ui_signal_from_box(canvas_box); { if(ui_dragging(canvas_sig)) { if(ui_pressed(canvas_sig)) { rd_cmd(RD_CmdKind_FocusPanel); ui_store_drag_struct(&view_center_pos); } Vec2F32 start_view_center_pos = *ui_get_drag_struct(Vec2F32); Vec2F32 drag_delta_scr = ui_drag_delta(); Vec2F32 drag_delta_cvs = scale_2f32(drag_delta_scr, 1.f/zoom); Vec2F32 new_view_center_pos = sub_2f32(start_view_center_pos, drag_delta_cvs); view_center_pos = new_view_center_pos; } if(canvas_sig.scroll.y != 0) { F32 new_zoom = zoom - zoom*canvas_sig.scroll.y/10.f; new_zoom = Clamp(1.f/256.f, new_zoom, 256.f); Vec2F32 mouse_scr_pre = sub_2f32(ui_mouse(), rect.p0); Vec2F32 mouse_cvs = rd_bitmap_canvas_from_screen_pos(view_center_pos, zoom, canvas_rect, mouse_scr_pre); zoom = new_zoom; Vec2F32 mouse_scr_pst = rd_bitmap_screen_from_canvas_pos(view_center_pos, zoom, canvas_rect, mouse_cvs); Vec2F32 drift_scr = sub_2f32(mouse_scr_pst, mouse_scr_pre); view_center_pos = add_2f32(view_center_pos, scale_2f32(drift_scr, 1.f/new_zoom)); } if(ui_double_clicked(canvas_sig)) { ui_kill_action(); MemoryZeroStruct(&view_center_pos); zoom = 1.f; } } ////////////////////////////// //- rjf: equip canvas draw info // { RD_BitmapCanvasBoxDrawData *draw_data = push_array(ui_build_arena(), RD_BitmapCanvasBoxDrawData, 1); draw_data->view_center_pos = view_center_pos; draw_data->zoom = zoom; ui_box_equip_custom_draw(canvas_box, rd_bitmap_view_canvas_box_draw, draw_data); } ////////////////////////////// //- rjf: calculate image coordinates // Rng2F32 img_rect_cvs = r2f32p(-topology.dim.x/2, -topology.dim.y/2, +topology.dim.x/2, +topology.dim.y/2); Rng2F32 img_rect_scr = rd_bitmap_screen_from_canvas_rect(view_center_pos, zoom, canvas_rect, img_rect_cvs); ////////////////////////////// //- rjf: image-region canvas interaction // Vec2S32 mouse_bmp = {-1, -1}; if(ui_hovering(canvas_sig) && !ui_dragging(canvas_sig)) { Vec2F32 mouse_scr = sub_2f32(ui_mouse(), rect.p0); Vec2F32 mouse_cvs = rd_bitmap_canvas_from_screen_pos(view_center_pos, zoom, canvas_rect, mouse_scr); if(contains_2f32(img_rect_cvs, mouse_cvs)) { mouse_bmp = v2s32((S32)(mouse_cvs.x-img_rect_cvs.x0), (S32)(mouse_cvs.y-img_rect_cvs.y0)); S64 off_px = mouse_bmp.y*topology.dim.x + mouse_bmp.x; S64 off_bytes = off_px*r_tex2d_format_bytes_per_pixel_table[topology.fmt]; if(0 <= off_bytes && off_bytes+r_tex2d_format_bytes_per_pixel_table[topology.fmt] <= data.size && r_tex2d_format_bytes_per_pixel_table[topology.fmt] != 0) { RD_RegsScope(.vaddr_range = r1u64(offset_range.min + off_bytes, offset_range.min + off_bytes + r_tex2d_format_bytes_per_pixel_table[topology.fmt]), .eval_space = eval.space) rd_set_hover_regs(RD_RegSlot_VaddrRange); B32 color_is_good = 1; Vec4F32 color = {0}; switch(topology.fmt) { default:{color_is_good = 0;}break; case R_Tex2DFormat_R8: {color = v4f32(((U8 *)(data.str+off_bytes))[0]/255.f, 0, 0, 1);}break; case R_Tex2DFormat_RG8: {color = v4f32(((U8 *)(data.str+off_bytes))[0]/255.f, ((U8 *)(data.str+off_bytes))[1]/255.f, 0, 1);}break; case R_Tex2DFormat_RGBA8: {color = v4f32(((U8 *)(data.str+off_bytes))[0]/255.f, ((U8 *)(data.str+off_bytes))[1]/255.f, ((U8 *)(data.str+off_bytes))[2]/255.f, ((U8 *)(data.str+off_bytes))[3]/255.f);}break; case R_Tex2DFormat_BGRA8: {color = v4f32(((U8 *)(data.str+off_bytes))[2]/255.f, ((U8 *)(data.str+off_bytes))[1]/255.f, ((U8 *)(data.str+off_bytes))[0]/255.f, ((U8 *)(data.str+off_bytes))[3]/255.f);}break; case R_Tex2DFormat_R16: {color = v4f32(((U16 *)(data.str+off_bytes))[0]/(F32)max_U16, 0, 0, 1);}break; case R_Tex2DFormat_RGBA16: {color = v4f32(((U16 *)(data.str+off_bytes))[0]/(F32)max_U16, ((U16 *)(data.str+off_bytes))[1]/(F32)max_U16, ((U16 *)(data.str+off_bytes))[2]/(F32)max_U16, ((U16 *)(data.str+off_bytes))[3]/(F32)max_U16);}break; case R_Tex2DFormat_R32: {color = v4f32(((F32 *)(data.str+off_bytes))[0], 0, 0, 1);}break; case R_Tex2DFormat_RG32: {color = v4f32(((F32 *)(data.str+off_bytes))[0], ((F32 *)(data.str+off_bytes))[1], 0, 1);}break; case R_Tex2DFormat_RGBA32: {color = v4f32(((F32 *)(data.str+off_bytes))[0], ((F32 *)(data.str+off_bytes))[1], ((F32 *)(data.str+off_bytes))[2], ((F32 *)(data.str+off_bytes))[3]);}break; } if(color_is_good) { Vec4F32 hsva = hsva_from_rgba(color); ui_do_color_tooltip_hsva(hsva); } } } } ////////////////////////////// //- rjf: build image // UI_Parent(canvas_box) { if(0 <= mouse_bmp.x && mouse_bmp.x < dim.x && 0 <= mouse_bmp.x && mouse_bmp.x < dim.y) { F32 pixel_size_scr = 1.f*zoom; Rng2F32 indicator_rect_scr = r2f32p(img_rect_scr.x0 + mouse_bmp.x*pixel_size_scr, img_rect_scr.y0 + mouse_bmp.y*pixel_size_scr, img_rect_scr.x0 + (mouse_bmp.x+1)*pixel_size_scr, img_rect_scr.y0 + (mouse_bmp.y+1)*pixel_size_scr); UI_Rect(indicator_rect_scr) { ui_build_box_from_key(UI_BoxFlag_DrawBorder|UI_BoxFlag_Floating, ui_key_zero()); } } UI_Rect(img_rect_scr) UI_Flags(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_Floating) { ui_image(texture, R_Tex2DSampleKind_Nearest, r2f32p(0, 0, (F32)dim.x, (F32)dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("bmp_image")); } } ////////////////////////////// //- rjf: store params // rd_store_view_param_f32(str8_lit("zoom"), zoom); rd_store_view_param_f32(str8_lit("x"), view_center_pos.x); rd_store_view_param_f32(str8_lit("y"), view_center_pos.y); access_close(access); scratch_end(scratch); } //////////////////////////////// //~ rjf: rgba @view_hook_impl typedef struct RD_EvalColor RD_EvalColor; struct RD_EvalColor { Vec4F32 rgba; E_Eval rgba_evals[4]; }; internal RD_EvalColor rd_eval_color_from_eval(E_Eval eval) { Temp scratch = scratch_begin(0, 0); //- rjf: walk eval's type tree, find all four component evaluations E_Eval component_evals[4] = {0}; { typedef struct LeafTask LeafTask; struct LeafTask { LeafTask *next; E_Eval eval; }; U64 num_components_left = 4; LeafTask start_task = {0, eval}; LeafTask *first_task = &start_task; LeafTask *last_task = first_task; for(LeafTask *t = first_task; t != 0 && num_components_left > 0; t = t->next) { E_Type *type = e_type_from_key(e_type_key_unwrap(t->eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)); switch(type->kind) { default:{}break; // rjf: leaf >u32/s32 -> take all 4 components case E_TypeKind_U32: case E_TypeKind_S32: case E_TypeKind_U64: case E_TypeKind_S64: { component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0xff000000) >> 24) / 255.f")); component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x00ff0000) >> 16) / 255.f")); component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x0000ff00) >> 8) / 255.f")); component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)(($ & 0x000000ff) >> 0) / 255.f")); num_components_left -= 4; }break; //- rjf: array -> generate tasks for first four elements case E_TypeKind_Array: { component_evals[0] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[0])")); component_evals[1] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[1])")); component_evals[2] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[2])")); component_evals[3] = e_value_eval_from_eval(e_eval_wrapf(t->eval, "(float32)($[3])")); num_components_left -= 4; }break; } } } //- rjf: swizzle / extract the component values from the evals, depending on this lens // (the lens implicitly tells us the format) RD_EvalColor result = {0}; { E_Type *lens_type = e_type_from_key(eval.irtree.type_key); for(E_Type *t = lens_type; t->kind == E_TypeKind_Lens; t = e_type_from_key(t->direct_type_key)) { if(str8_match(t->name, str8_lit("color"), 0)) { lens_type = t; break; } } String8 format_string = str8_lit("rgba"); if(lens_type->kind == E_TypeKind_Lens && lens_type->count > 0) { format_string = lens_type->args[0]->string; } if(str8_match(format_string, str8_lit("rgba"), 0)) { result.rgba_evals[0] = component_evals[0]; result.rgba_evals[1] = component_evals[1]; result.rgba_evals[2] = component_evals[2]; result.rgba_evals[3] = component_evals[3]; } else if(str8_match(format_string, str8_lit("argb"), 0)) { result.rgba_evals[0] = component_evals[1]; result.rgba_evals[1] = component_evals[2]; result.rgba_evals[2] = component_evals[3]; result.rgba_evals[3] = component_evals[0]; } else if(str8_match(format_string, str8_lit("bgra"), 0)) { result.rgba_evals[0] = component_evals[2]; result.rgba_evals[1] = component_evals[1]; result.rgba_evals[2] = component_evals[0]; result.rgba_evals[3] = component_evals[3]; } else if(str8_match(format_string, str8_lit("abgr"), 0)) { result.rgba_evals[0] = component_evals[3]; result.rgba_evals[1] = component_evals[2]; result.rgba_evals[2] = component_evals[1]; result.rgba_evals[3] = component_evals[0]; } for EachIndex(idx, 4) { result.rgba.v[idx] = e_value_eval_from_eval(result.rgba_evals[idx]).value.f32; } } scratch_end(scratch); return result; } EV_EXPAND_RULE_INFO_FUNCTION_DEF(color) { EV_ExpandInfo info = {0}; info.row_count = 12; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(color) { Temp scratch = scratch_begin(0, 0); ////////////////////////////// //- rjf: unpack state // typedef struct RD_ColorViewState RD_ColorViewState; struct RD_ColorViewState { B32 initialized; U32 start_rgba_u32; Vec4F32 hsva; }; RD_ColorViewState *state = rd_view_state(RD_ColorViewState); RD_EvalColor eval_color = rd_eval_color_from_eval(eval); U32 rgba_u32 = u32_from_rgba(eval_color.rgba); if(!state->initialized || rgba_u32 != state->start_rgba_u32) { Vec4F32 rgba = eval_color.rgba; Vec4F32 hsva = hsva_from_rgba(rgba); state->initialized = 1; state->start_rgba_u32 = rgba_u32; state->hsva = hsva; } Vec4F32 hsva = state->hsva; Vec4F32 rgba = rgba_from_hsva(hsva); ////////////////////////////// //- rjf: calculate dimensions // Vec2F32 dim = dim_2f32(rect); F32 sv_dim_px = Min(dim.x, dim.y); F32 padding = sv_dim_px*0.2f; sv_dim_px -= padding*2.f; sv_dim_px = Min(sv_dim_px, ui_top_font_size()*70.f); ////////////////////////////// //- rjf: build UI // { UI_WidthFill UI_HeightFill UI_PrefHeight(ui_children_sum(1)) UI_Column UI_Padding(ui_pct(1.f, 0.f)) UI_PrefHeight(ui_children_sum(1)) UI_Row UI_Padding(ui_pct(1.f, 0.f)) UI_PrefWidth(ui_px(sv_dim_px, 1.f)) UI_PrefHeight(ui_px(sv_dim_px, 1.f)) RD_Font(RD_FontSlot_Code) { UI_Signal sv_sig = ui_sat_val_pickerf(hsva.x, &hsva.y, &hsva.z, "sat_val_picker"); UI_Signal h_sig = {0}; UI_Signal a_sig = {0}; ui_spacer(ui_em(1.f, 1.f)); UI_PrefWidth(ui_em(3.f, 1.f)) { h_sig = ui_hue_pickerf(&hsva.x, hsva.y, hsva.z, "hue_picker"); } ui_spacer(ui_em(1.f, 1.f)); UI_PrefWidth(ui_em(3.f, 1.f)) { a_sig = ui_alpha_pickerf(&hsva.w, "alpha_picker"); } ui_spacer(ui_em(1.f, 1.f)); UI_PrefWidth(ui_children_sum(1)) UI_Column { UI_PrefWidth(ui_em(6.f, 0.f)) UI_PrefHeight(ui_em(6.f, 0.f)) UI_BackgroundColor(linear_from_srgba(v4f32(rgba.x, rgba.y, rgba.z, 1.f))) UI_CornerRadius(4.f) UI_PrefWidth(ui_em(6.f, 1.f)) UI_PrefHeight(ui_em(6.f, 1.f)) ui_build_box_from_string(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, str8_lit("")); ui_spacer(ui_em(2.f, 1.f)); UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_children_sum(1)) UI_Row { UI_PrefWidth(ui_children_sum(1)) UI_Column UI_PrefWidth(ui_text_dim(10, 1)) UI_PrefHeight(ui_em(2.f, 0.f)) RD_Font(RD_FontSlot_Code) UI_TagF("weak") { ui_labelf("Hex"); ui_labelf("R"); ui_labelf("G"); ui_labelf("B"); ui_labelf("H"); ui_labelf("S"); ui_labelf("V"); ui_labelf("A"); } UI_PrefWidth(ui_children_sum(1)) UI_Column UI_PrefWidth(ui_text_dim(10, 1)) UI_PrefHeight(ui_em(2.f, 0.f)) RD_Font(RD_FontSlot_Code) { String8 hex_string = hex_string_from_rgba_4f32(scratch.arena, rgba); ui_label(hex_string); ui_labelf("%.2f", rgba.x); ui_labelf("%.2f", rgba.y); ui_labelf("%.2f", rgba.z); ui_labelf("%.2f", hsva.x); ui_labelf("%.2f", hsva.y); ui_labelf("%.2f", hsva.z); ui_labelf("%.2f", rgba.w); } } } if(ui_dragging(h_sig) || ui_dragging(sv_sig) || ui_dragging(a_sig)) { // TODO(rjf): hard-coding U32 committing for now E_Type *type = e_type_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative)); if(type->kind == E_TypeKind_U32 || type->kind == E_TypeKind_S32 || type->kind == E_TypeKind_U64 || type->kind == E_TypeKind_S64) { Vec4F32 new_rgba = rgba_from_hsva(hsva); U32 u32 = u32_from_rgba(new_rgba); String8 string = push_str8f(scratch.arena, "0x%x", u32); if(rd_commit_eval_value_string(eval, string)) { state->start_rgba_u32 = u32; state->hsva = hsva; } } } } } scratch_end(scratch); } //////////////////////////////// //~ rjf: geo3d @view_hook_impl typedef struct RD_Geo3DViewState RD_Geo3DViewState; struct RD_Geo3DViewState { F32 yaw; F32 pitch; F32 zoom; }; typedef struct RD_Geo3DBoxDrawData RD_Geo3DBoxDrawData; struct RD_Geo3DBoxDrawData { F32 yaw; F32 pitch; F32 zoom; R_Handle vertex_buffer; R_Handle index_buffer; }; internal AC_Artifact rd_geo3d_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { Access *access = access_open(); U128 hash = {0}; str8_deserial_read_struct(key, 0, &hash); String8 data = c_data_from_hash(access, hash); R_Handle buffer = {0}; if(data.size != 0) { buffer = r_buffer_alloc(R_ResourceKind_Static, data.size, data.str); } AC_Artifact artifact = {0}; MemoryCopy(&artifact, &buffer, Min(sizeof(artifact), sizeof(buffer))); access_close(access); return artifact; } internal void rd_geo3d_artifact_destroy(AC_Artifact artifact) { R_Handle buffer = {0}; MemoryCopy(&buffer, &artifact, Min(sizeof(buffer), sizeof(artifact))); r_buffer_release(buffer); } internal R_Handle rd_geo3d_buffer_from_key(Access *access, C_Key key) { R_Handle result = {0}; for EachIndex(rewind_idx, C_KEY_HASH_HISTORY_COUNT) { U128 hash = c_hash_from_key(key, rewind_idx); AC_Artifact artifact = ac_artifact_from_key(access, str8_struct(&hash), rd_geo3d_artifact_create, rd_geo3d_artifact_destroy, 0); R_Handle buffer = {0}; MemoryCopy(&buffer, &artifact, Min(sizeof(buffer), sizeof(artifact))); if(!r_handle_match(buffer, r_handle_zero())) { result = buffer; break; } } return result; } internal UI_BOX_CUSTOM_DRAW(rd_geo3d_box_draw) { RD_Geo3DBoxDrawData *draw_data = (RD_Geo3DBoxDrawData *)user_data; // rjf: get clip Rng2F32 clip = box->rect; for(UI_Box *b = box->parent; !ui_box_is_nil(b); b = b->parent) { if(b->flags & UI_BoxFlag_Clip) { clip = intersect_2f32(b->rect, clip); } } // rjf: calculate eye/target Vec3F32 target = {0}; Vec3F32 eye = v3f32(draw_data->zoom*cos_f32(draw_data->yaw)*sin_f32(draw_data->pitch), draw_data->zoom*sin_f32(draw_data->yaw)*sin_f32(draw_data->pitch), draw_data->zoom*cos_f32(draw_data->pitch)); // rjf: mesh Vec2F32 box_dim = dim_2f32(box->rect); R_PassParams_Geo3D *pass = dr_geo3d_begin(box->rect, make_look_at_4x4f32(eye, target, v3f32(0, 0, 1)), make_perspective_4x4f32(0.25f, box_dim.x/box_dim.y, 0.1f, 500.f)); pass->clip = clip; dr_mesh(draw_data->vertex_buffer, draw_data->index_buffer, R_GeoTopologyKind_Triangles, R_GeoVertexFlag_TexCoord|R_GeoVertexFlag_Normals|R_GeoVertexFlag_RGB, r_handle_zero(), mat_4x4f32(1.f)); } EV_EXPAND_RULE_INFO_FUNCTION_DEF(geo3d) { EV_ExpandInfo info = {0}; info.row_count = 16; info.single_item = 1; return info; } RD_VIEW_UI_FUNCTION_DEF(geo3d) { Temp scratch = scratch_begin(0, 0); Access *access = access_open(); RD_Geo3DViewState *state = rd_view_state(RD_Geo3DViewState); ////////////////////////////// //- rjf: if parameterized by a register-space evaluation, interpret as an // address in the primary module. // if(e_space_match(eval.space, e_base_ctx->thread_reg_space)) { eval = e_value_eval_from_eval(eval); eval.space = e_base_ctx->primary_module->space; } ////////////////////////////// //- rjf: unpack parameters // U64 count = rd_view_setting_u64_from_name(str8_lit("count")); U64 vtx_base_off = rd_view_setting_u64_from_name(str8_lit("vtx")); U64 vtx_size = rd_view_setting_u64_from_name(str8_lit("vtx_size")); F32 yaw_target = rd_view_setting_f32_from_name(str8_lit("yaw")); F32 pitch_target = rd_view_setting_f32_from_name(str8_lit("pitch")); F32 zoom_target = rd_view_setting_f32_from_name(str8_lit("zoom")); ////////////////////////////// //- rjf: evaluate & unpack expression // Rng1U64 eval_range = e_range_from_eval(eval); U64 base_offset = eval_range.min; Rng1U64 idxs_range = r1u64(base_offset, base_offset+count*sizeof(U32)); Rng1U64 vtxs_range = r1u64(vtx_base_off, vtx_base_off+vtx_size); C_Key idxs_key = rd_key_from_eval_space_range(eval.space, idxs_range, 0); C_Key vtxs_key = rd_key_from_eval_space_range(eval.space, vtxs_range, 0); R_Handle idxs_buffer = rd_geo3d_buffer_from_key(access, idxs_key); R_Handle vtxs_buffer = rd_geo3d_buffer_from_key(access, vtxs_key); ////////////////////////////// //- rjf: equip loading info // if(eval.string.size != 0 && eval.msgs.max_kind == E_MsgKind_Null && (r_handle_match(idxs_buffer, r_handle_zero()) || r_handle_match(vtxs_buffer, r_handle_zero()))) { rd_store_view_loading_info(1, 0, 0); } ////////////////////////////// //- rjf: do first-time camera initialization, if needed // if(zoom_target == 0) { yaw_target = -0.125f; pitch_target = -0.125f; zoom_target = 3.5f; } ////////////////////////////// //- rjf: animate camera // { F32 fast_rate = 1 - pow_f32(2, (-60.f * rd_state->frame_dt)); F32 slow_rate = 1 - pow_f32(2, (-30.f * rd_state->frame_dt)); state->zoom += (zoom_target - state->zoom) * slow_rate; state->yaw += (yaw_target - state->yaw) * fast_rate; state->pitch += (pitch_target - state->pitch) * fast_rate; if(abs_f32(state->zoom - zoom_target) > 0.001f || abs_f32(state->yaw - yaw_target) > 0.001f || abs_f32(state->pitch - pitch_target) > 0.001f) { rd_request_frame(); } } ////////////////////////////// //- rjf: build // if(count != 0 && !r_handle_match(idxs_buffer, r_handle_zero()) && !r_handle_match(vtxs_buffer, r_handle_zero())) { Vec2F32 dim = dim_2f32(rect); UI_Box *box = &ui_nil_box; UI_FixedSize(dim) { box = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable|UI_BoxFlag_Scroll, "geo_box"); } UI_Signal sig = ui_signal_from_box(box); if(ui_dragging(sig)) { if(ui_pressed(sig)) { rd_cmd(RD_CmdKind_FocusPanel); Vec2F32 data = v2f32(yaw_target, pitch_target); ui_store_drag_struct(&data); } Vec2F32 drag_delta = ui_drag_delta(); Vec2F32 drag_start_data = *ui_get_drag_struct(Vec2F32); yaw_target = drag_start_data.x + drag_delta.x/dim.x; pitch_target = drag_start_data.y + drag_delta.y/dim.y; } zoom_target += sig.scroll.y; zoom_target = Clamp(0.1f, zoom_target, 100.f); pitch_target = Clamp(-0.49f, pitch_target, -0.01f); RD_Geo3DBoxDrawData *draw_data = push_array(ui_build_arena(), RD_Geo3DBoxDrawData, 1); draw_data->yaw = state->yaw; draw_data->pitch = state->pitch; draw_data->zoom = state->zoom; draw_data->vertex_buffer = vtxs_buffer; draw_data->index_buffer = idxs_buffer; ui_box_equip_custom_draw(box, rd_geo3d_box_draw, draw_data); } ////////////////////////////// //- rjf: commit parameters // rd_store_view_param_f32(str8_lit("yaw"), yaw_target); rd_store_view_param_f32(str8_lit("pitch"), pitch_target); rd_store_view_param_f32(str8_lit("zoom"), zoom_target); access_close(access); scratch_end(scratch); } ================================================ FILE: src/raddbg/raddbg_views.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_VIEWS_H #define RADDBG_VIEWS_H //////////////////////////////// //~ rjf: Code View Types typedef U32 RD_CodeViewBuildFlags; enum { RD_CodeViewBuildFlag_Margins = (1<<0), RD_CodeViewBuildFlag_All = 0xffffffff, }; typedef struct RD_CodeViewTLineSplitNode RD_CodeViewTLineSplitNode; struct RD_CodeViewTLineSplitNode { RD_CodeViewTLineSplitNode *next; U64 off; }; typedef struct RD_CodeViewTLineWrapCacheNode RD_CodeViewTLineWrapCacheNode; struct RD_CodeViewTLineWrapCacheNode { RD_CodeViewTLineWrapCacheNode *hash_next; RD_CodeViewTLineWrapCacheNode *hash_prev; S64 line_num; RD_CodeViewTLineSplitNode *first_split; RD_CodeViewTLineSplitNode *last_split; }; typedef struct RD_CodeViewTLineWrapCacheSlot RD_CodeViewTLineWrapCacheSlot; struct RD_CodeViewTLineWrapCacheSlot { RD_CodeViewTLineWrapCacheNode *first; RD_CodeViewTLineWrapCacheNode *last; }; typedef struct RD_CodeViewState RD_CodeViewState; struct RD_CodeViewState { // rjf: stable state B32 initialized; S64 preferred_column; B32 drifted_for_search; U128 last_hash; // rjf: per-frame command info S64 goto_line_num; B32 center_cursor; B32 contain_cursor; B32 force_contain_only; B32 watch_expr_at_mouse; Arena *find_text_arena; String8 find_text_fwd; String8 find_text_bwd; // rjf: line wrapping cache & info Arena *wrap_arena; RD_CodeViewTLineWrapCacheSlot *wrap_cache_slots; U64 wrap_cache_slots_count; U64 wrap_total_vline_count; }; typedef struct RD_CodeViewBuildResult RD_CodeViewBuildResult; struct RD_CodeViewBuildResult { DI_KeyList dbgi_keys; }; //////////////////////////////// //~ rjf: Watch View Types typedef enum RD_WatchCellKind { RD_WatchCellKind_Eval, // an evaluation cell RD_WatchCellKind_ViewUI, // an arbitrary user interface, supplied by a hook RD_WatchCellKind_CallStackFrame, // a slot for a yellow arrow, to show call stack frame selection } RD_WatchCellKind; typedef U32 RD_WatchCellFlags; enum { RD_WatchCellFlag_Expr = (1<<0), RD_WatchCellFlag_NoEval = (1<<1), RD_WatchCellFlag_Button = (1<<2), RD_WatchCellFlag_Background = (1<<3), RD_WatchCellFlag_ActivateWithSingleClick = (1<<4), RD_WatchCellFlag_IsNonCode = (1<<5), RD_WatchCellFlag_CanEdit = (1<<6), RD_WatchCellFlag_IsErrored = (1<<7), RD_WatchCellFlag_Indented = (1<<8), }; typedef struct RD_WatchCell RD_WatchCell; struct RD_WatchCell { RD_WatchCell *next; RD_WatchCellKind kind; RD_WatchCellFlags flags; U64 index; E_Eval eval; F32 default_pct; F32 pct; F32 px; }; typedef struct RD_WatchCellList RD_WatchCellList; struct RD_WatchCellList { RD_WatchCell *first; RD_WatchCell *last; U64 count; F32 pct_sum; }; typedef struct RD_WatchRowInfo RD_WatchRowInfo; struct RD_WatchRowInfo { CTRL_Entity *module; B32 can_expand; B32 expr_is_editable; String8 group_cfg_name; CFG_Node *group_cfg_parent; CFG_Node *group_cfg_child; CTRL_Entity *group_entity; CTRL_Entity *callstack_thread; U64 callstack_unwind_index; U64 callstack_inline_depth; U64 callstack_vaddr; String8 cell_style_key; RD_WatchCellList cells; RD_ViewUIRule *view_ui_rule; }; typedef struct RD_WatchRowCellInfo RD_WatchRowCellInfo; struct RD_WatchRowCellInfo { RD_WatchCellFlags flags; CFG_Node *cfg; CTRL_Entity *entity; String8 cmd_name; String8 file_path; DR_FStrList expr_fstrs; DR_FStrList eval_fstrs; String8 description; String8 error_tooltip; String8 inheritance_tooltip; RD_ViewUIRule *view_ui_rule; }; typedef struct RD_WatchPt RD_WatchPt; struct RD_WatchPt { EV_Key parent_key; EV_Key key; U64 cell_id; }; typedef struct RD_WatchViewTextEditState RD_WatchViewTextEditState; struct RD_WatchViewTextEditState { RD_WatchViewTextEditState *pt_hash_next; RD_WatchPt pt; TxtPt cursor; TxtPt mark; U8 input_buffer[1024]; U64 input_size; U8 initial_buffer[1024]; U64 initial_size; }; typedef struct RD_WatchViewState RD_WatchViewState; struct RD_WatchViewState { B32 initialized; // rjf: filter history Arena *filter_arena; String8 last_filter; // rjf; table cursor state RD_WatchPt cursor; RD_WatchPt mark; RD_WatchPt next_cursor; RD_WatchPt next_mark; // rjf: text input state Arena *text_edit_arena; U64 text_edit_state_slots_count; RD_WatchViewTextEditState dummy_text_edit_state; RD_WatchViewTextEditState **text_edit_state_slots; B32 text_editing; }; //////////////////////////////// //~ rjf: Code View Functions internal void rd_code_view_init(RD_CodeViewState *cv); internal RD_CodeViewBuildResult rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags flags, Rng2F32 rect, String8 text_data, TXT_TextInfo *text_info, DASM_LineArray *dasm_lines, Rng1U64 dasm_vaddr_range, DI_Key dasm_dbgi_key); //////////////////////////////// //~ rjf: Watch View Functions //- rjf: cell list building internal U64 rd_id_from_watch_cell(RD_WatchCell *cell); internal RD_WatchCell *rd_watch_cell_list_push_new_(Arena *arena, RD_WatchCellList *list, RD_WatchCell *params); #define rd_watch_cell_list_push_new(arena, list, kind_, eval_, ...) rd_watch_cell_list_push_new_((arena), (list), &(RD_WatchCell){.kind = (kind_), .eval = (eval_), __VA_ARGS__}) //- rjf: watch view points <-> table coordinates internal B32 rd_watch_pt_match(RD_WatchPt a, RD_WatchPt b); internal RD_WatchPt rd_watch_pt_from_tbl(EV_BlockRangeList *block_ranges, Vec2S64 tbl); internal Vec2S64 rd_tbl_from_watch_pt(EV_BlockRangeList *block_ranges, RD_WatchPt pt); //- rjf: row -> info internal RD_WatchRowInfo rd_watch_row_info_from_row(Arena *arena, EV_Row *row); //- rjf: row * cell -> info internal RD_WatchRowCellInfo rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_flags, RD_WatchRowInfo *row_info, RD_WatchCell *cell, FNT_Tag font, F32 font_size, F32 max_size_px); //- rjf: table coordinates -> text edit state internal RD_WatchViewTextEditState *rd_watch_view_text_edit_state_from_pt(RD_WatchViewState *wv, RD_WatchPt pt); //////////////////////////////// //~ rjf: View Hooks // TODO(rjf): eliminate once we are predeclaring these with metacode RD_VIEW_UI_FUNCTION_DEF(null); EV_EXPAND_RULE_INFO_FUNCTION_DEF(text); EV_EXPAND_RULE_INFO_FUNCTION_DEF(disasm); EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory); EV_EXPAND_RULE_INFO_FUNCTION_DEF(bitmap); EV_EXPAND_RULE_INFO_FUNCTION_DEF(color); EV_EXPAND_RULE_INFO_FUNCTION_DEF(geo3d); RD_VIEW_UI_FUNCTION_DEF(text); RD_VIEW_UI_FUNCTION_DEF(disasm); RD_VIEW_UI_FUNCTION_DEF(memory); RD_VIEW_UI_FUNCTION_DEF(bitmap); RD_VIEW_UI_FUNCTION_DEF(color); RD_VIEW_UI_FUNCTION_DEF(geo3d); #endif // RADDBG_VIEWS_H ================================================ FILE: src/raddbg/raddbg_widgets.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: UI Widgets: Fancy Title Strings internal DR_FStrList rd_title_fstrs_from_cfg(Arena *arena, CFG_Node *cfg, B32 include_extras) { DR_FStrList result = {0}; { Temp scratch = scratch_begin(&arena, 1); //- rjf: unpack config B32 is_disabled = rd_disabled_from_cfg(cfg); RD_Location loc = rd_location_from_cfg(cfg); D_Target target = rd_target_from_cfg(scratch.arena, cfg); String8 label_string = rd_label_from_cfg(cfg); String8 expr_string = rd_expr_from_cfg(cfg); String8 collection_name = {0}; String8 file_path = rd_path_from_cfg(cfg); Vec4F32 rgba = rd_color_from_cfg(cfg); if(rgba.w == 0) { rgba = ui_color_from_name(str8_lit("text")); } Vec4F32 rgba_secondary = rgba; UI_TagF("weak") { rgba_secondary = ui_color_from_name(str8_lit("text")); } RD_IconKind icon_kind = rd_icon_kind_from_code_name(cfg->string); B32 is_from_command_line = 0; { CFG_Node *cmd_line_root = cfg_node_child_from_string(cfg_node_root(), str8_lit("command_line")); for(CFG_Node *p = cfg->parent; p != &cfg_nil_node; p = p->parent) { if(p == cmd_line_root) { is_from_command_line = 1; break; } } } B32 is_within_window = 0; { for(CFG_Node *p = cfg->parent; p != &cfg_nil_node; p = p->parent) { if(str8_match(p->string, str8_lit("window"), 0)) { is_within_window = 1; break; } } } if(expr_string.size != 0) { String8 query_name = rd_query_from_eval_string(arena, expr_string); if(query_name.size != 0) { String8 query_code_name = query_name; String8 query_display_name = rd_display_from_code_name(query_code_name); collection_name = query_display_name; if(query_display_name.size == 0) { query_code_name = rd_singular_from_code_name_plural(query_name); collection_name = rd_display_plural_from_code_name(query_code_name); } RD_IconKind query_icon_kind = rd_icon_kind_from_code_name(query_code_name); if(query_icon_kind != RD_IconKind_Null) { icon_kind = query_icon_kind; } } else { file_path = rd_file_path_from_eval_string(arena, expr_string); if(file_path.size != 0) { icon_kind = RD_IconKind_FileOutline; } } } //- rjf: set up color/size for all parts of the title // // the "running" part implies that it changes as things are added - // so if a primary title is pushed, we can make the rest of the title // more faded/smaller, but only after a primary title is pushed, // which could be caused by many different potential parts of a cfg. // DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), rgba, ui_top_font_size()}; B32 running_is_secondary = 0; #define start_secondary() if(!running_is_secondary){running_is_secondary = 1; params.color = rgba_secondary; params.size = ui_top_font_size()*0.95f;} //- rjf: disabled? -> soften color if(is_disabled) { params.color = rgba_secondary; } //- rjf: [breakpoints] push hit marker if(str8_match(cfg->string, str8_lit("breakpoint"), 0)) { CTRL_Event stop_event = d_ctrl_last_stop_event(); if(stop_event.cause == CTRL_EventCause_UserBreakpoint) { CFG_Node *bp = cfg_node_from_id(stop_event.u64_code); if(bp == cfg) { CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, stop_event.entity); Vec4F32 thread_color = rd_color_from_ctrl_entity(thread); if(thread_color.w == 0) { thread_color = rgba_secondary; } dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = thread_color); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } } } //- rjf: push icon if(icon_kind != RD_IconKind_Null) { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push warning icon for command-line entities if(is_from_command_line) { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_Info], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push view title, if from window, and no file path, and no label if(is_within_window && file_path.size == 0 && collection_name.size == 0 && label_string.size == 0) { String8 view_display_name = rd_display_from_code_name(cfg->string); if(view_display_name.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, view_display_name); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } } //- rjf: push bucket name if(cfg->parent == cfg_node_root()) { if(str8_match(cfg->string, str8_lit("user"), 0)) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("User"), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } else if(str8_match(cfg->string, str8_lit("project"), 0)) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("Project"), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } } //- rjf: push label if(label_string.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, label_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: push collection name if(collection_name.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, collection_name); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: query is file path - do specific file name strings else if(file_path.size != 0) { // rjf: compute disambiguated file name String8List qualifiers = {0}; String8 file_name = str8_skip_last_slash(file_path); if(rd_state->ambiguous_path_slots_count != 0) { U64 hash = d_hash_from_string__case_insensitive(file_name); U64 slot_idx = hash%rd_state->ambiguous_path_slots_count; RD_AmbiguousPathNode *node = 0; { for(RD_AmbiguousPathNode *n = rd_state->ambiguous_path_slots[slot_idx]; n != 0; n = n->next) { if(str8_match(n->name, file_name, StringMatchFlag_CaseInsensitive)) { node = n; break; } } } if(node != 0 && node->paths.node_count > 1) { // rjf: get all colliding paths String8Array collisions = str8_array_from_list(scratch.arena, &node->paths); // rjf: get all reversed path parts for each collision String8List *collision_parts_reversed = push_array(scratch.arena, String8List, collisions.count); for EachIndex(idx, collisions.count) { String8List parts = str8_split_path(scratch.arena, collisions.v[idx]); for(String8Node *n = parts.first; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &collision_parts_reversed[idx], n->string); } } // rjf: get the search path & its reversed parts String8List parts = str8_split_path(scratch.arena, file_path); String8List parts_reversed = {0}; for(String8Node *n = parts.first; n != 0; n = n->next) { str8_list_push_front(scratch.arena, &parts_reversed, n->string); } // rjf: iterate all collision part reversed lists, in lock-step with // search path; disqualify until we only have one path remaining; gather // qualifiers { U64 num_collisions_left = collisions.count; String8Node **collision_nodes = push_array(scratch.arena, String8Node *, collisions.count); for EachIndex(idx, collisions.count) { collision_nodes[idx] = collision_parts_reversed[idx].first; } for(String8Node *n = parts_reversed.first; num_collisions_left > 1 && n != 0; n = n->next) { B32 part_is_qualifier = 0; for EachIndex(idx, collisions.count) { if(collision_nodes[idx] != 0 && !str8_match(collision_nodes[idx]->string, n->string, StringMatchFlag_CaseInsensitive)) { collision_nodes[idx] = 0; num_collisions_left -= 1; part_is_qualifier = 1; } else if(collision_nodes[idx] != 0) { collision_nodes[idx] = collision_nodes[idx]->next; } } if(part_is_qualifier) { str8_list_push_front(scratch.arena, &qualifiers, n->string); } } } } } // rjf: push qualifiers if(qualifiers.node_count != 0) UI_TagF("weak") { for(String8Node *n = qualifiers.first; n != 0; n = n->next) { String8 string = push_str8f(arena, "<%S> ", n->string); dr_fstrs_push_new(arena, &result, ¶ms, string, .color = ui_color_from_name(str8_lit("text"))); } } // rjf: push file name dr_fstrs_push_new(arena, &result, ¶ms, push_str8_copy(arena, str8_skip_last_slash(file_path))); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: cfg has expression attached -> use that else if(expr_string.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, expr_string, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: push text location if(loc.file_path.size != 0) { String8 path = loc.file_path; if(!include_extras) { path = str8_skip_last_slash(loc.file_path); } String8 location_string = push_str8f(arena, "%S:%I64d:%I64d", path, loc.pt.line, loc.pt.column); dr_fstrs_push_new(arena, &result, ¶ms, location_string); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: push address location if(loc.expr.size != 0) { RD_Font(RD_FontSlot_Code) { DR_FStrList fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, params.color, loc.expr); dr_fstrs_concat_in_place(&result, &fstrs); } dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: push target executable name if(target.exe.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, str8_skip_last_slash(target.exe)); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); start_secondary(); } //- rjf: push target arguments if(target.args.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, target.args); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push conditions { String8 condition = cfg_node_child_from_string(cfg, str8_lit("condition"))->first->string; if(condition.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("if "), .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); RD_Font(RD_FontSlot_Code) { DR_FStrList fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, params.color, condition); dr_fstrs_concat_in_place(&result, &fstrs); } dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } } //- rjf: push disabled marker if(is_disabled) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("(Disabled)")); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push hit count { String8 hit_count_value_string = cfg_node_child_from_string(cfg, str8_lit("hit_count"))->first->string; U64 hit_count = 0; if(try_u64_from_str8_c_rules(hit_count_value_string, &hit_count) && hit_count != 0) { String8 hit_count_text = push_str8f(arena, "(%I64u hit%s)", hit_count, hit_count == 1 ? "" : "s"); dr_fstrs_push_new(arena, &result, ¶ms, hit_count_text); } } //- rjf: special case: type views if(str8_match(cfg->string, str8_lit("type_view"), 0)) { String8 src_string = cfg_node_child_from_string(cfg, str8_lit("type"))->first->string; String8 dst_string = cfg_node_child_from_string(cfg, str8_lit("expr"))->first->string; Vec4F32 src_color = rgba; Vec4F32 dst_color = rgba; DR_FStrList src_fstrs = {0}; DR_FStrList dst_fstrs = {0}; if(src_string.size == 0) { src_string = str8_lit("(type)"); src_color = rgba_secondary; dr_fstrs_push_new(arena, &src_fstrs, ¶ms, src_string, .color = src_color); } else RD_Font(RD_FontSlot_Code) { src_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, src_color, src_string); } if(dst_string.size == 0) { dst_string = str8_lit("(expression)"); dst_color = rgba_secondary; dr_fstrs_push_new(arena, &dst_fstrs, ¶ms, dst_string, .color = dst_color); } else RD_Font(RD_FontSlot_Code) { dst_fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, dst_color, dst_string); } dr_fstrs_concat_in_place(&result, &src_fstrs); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_concat_in_place(&result, &dst_fstrs); } //- rjf: special case: file path maps if(str8_match(cfg->string, str8_lit("file_path_map"), 0)) { String8 src_string = cfg_node_child_from_string(cfg, str8_lit("source"))->first->string; String8 dst_string = cfg_node_child_from_string(cfg, str8_lit("dest"))->first->string; Vec4F32 src_color = rgba; Vec4F32 dst_color = rgba; if(src_string.size == 0) { src_string = str8_lit("(source path)"); src_color = rgba_secondary; } if(dst_string.size == 0) { dst_string = str8_lit("(destination path)"); dst_color = rgba_secondary; } dr_fstrs_push_new(arena, &result, ¶ms, src_string, .color = src_color); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rgba_secondary); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, dst_string, .color = dst_color); } //- rjf: special case: colors if(str8_match(cfg->string, str8_lit("theme_color"), 0)) { String8 tags = cfg_node_child_from_string(cfg, str8_lit("tags"))->first->string; String8 color_string = cfg_node_child_from_string(cfg, str8_lit("value"))->first->string; U32 color_u32 = e_value_from_stringf("(uint32)(%S)", color_string).u32; Vec4F32 color = linear_from_srgba(rgba_from_u32(color_u32)); if(tags.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, tags); } else { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("Color"), .color = rgba_secondary); } dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_CircleFilled], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = color); } #undef start_secondary scratch_end(scratch); } return result; } internal DR_FStrList rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras) { DR_FStrList result = {0}; //- rjf: unpack entity info F32 extras_size = ui_top_font_size()*0.95f; Vec4F32 color = rd_color_from_ctrl_entity(entity); if(color.w == 0) { color = ui_color_from_name(str8_lit("text")); } Vec4F32 secondary_color = color; UI_TagF("weak") { secondary_color = ui_color_from_name(str8_lit("text")); } String8 name = rd_name_from_ctrl_entity(arena, entity); RD_IconKind icon_kind = RD_IconKind_Null; B32 name_is_code = 0; switch(entity->kind) { default:{}break; case CTRL_EntityKind_Machine: {icon_kind = RD_IconKind_Machine;}break; case CTRL_EntityKind_Process: {icon_kind = RD_IconKind_Threads;}break; case CTRL_EntityKind_Thread: {icon_kind = RD_IconKind_Thread; name_is_code = 1;}break; case CTRL_EntityKind_Module: {icon_kind = RD_IconKind_Module;}break; } //- rjf: set up drawing params DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Code), rd_raster_flags_from_slot(RD_FontSlot_Code), color, ui_top_font_size()}; //- rjf: push icon if(icon_kind != RD_IconKind_Null) { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = secondary_color); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push frozen icon, if frozen if((entity->kind == CTRL_EntityKind_Machine || entity->kind == CTRL_EntityKind_Process || entity->kind == CTRL_EntityKind_Thread) && ctrl_entity_tree_is_frozen(entity)) UI_TagF("bad") { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_Locked], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push selected icon, if selected thread if(entity->kind == CTRL_EntityKind_Thread) { B32 is_selected = ctrl_handle_match(entity->handle, rd_base_regs()->thread); if(is_selected) { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_RightArrow], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = color); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } } //- rjf: push containing process prefix if(entity->kind == CTRL_EntityKind_Thread || entity->kind == CTRL_EntityKind_Module) { CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process); if(processes.count > 1) { CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); String8 process_name = rd_name_from_ctrl_entity(arena, process); Vec4F32 process_color = rd_color_from_ctrl_entity(process); if(process_color.w == 0) { process_color = ui_color_from_name(str8_lit("text")); } if(process_name.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, process_name, .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = process_color); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, push_str8f(arena, "(PID: %I64u)", process->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.9f); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" / "), .color = secondary_color); } } } //- rjf: push name dr_fstrs_push_new(arena, &result, ¶ms, name, .font = rd_font_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main), .color = color); //- rjf: push PID if(entity->kind == CTRL_EntityKind_Process) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, push_str8f(arena, " (PID: %I64u)", entity->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = ui_top_font_size()*0.85f); } //- rjf: threads get callstack extras if(entity->kind == CTRL_EntityKind_Thread && include_extras) { Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); Access *access = access_open(); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); Arch arch = entity->arch; B32 call_stack_high_priority = ctrl_handle_match(entity->handle, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(access, entity->handle, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); B32 did_first_known = 0; for(U64 idx = 0, limit = 10; idx < call_stack.frames_count && idx < limit; idx += 1) { CTRL_CallStackFrame *f = &call_stack.frames[call_stack.frames_count - 1 - idx]; U64 rip_vaddr = regs_rip_from_arch_block(arch, f->regs); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); String8 name = {0}; { DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); if(rdi != &rdi_parsed_nil) { RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, rip_voff); name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); name = push_str8_copy(arena, name); } if(name.size == 0 && did_first_known) { name = str8_lit("???"); } if(name.size != 0) { did_first_known = 1; dr_fstrs_push_new(arena, &result, ¶ms, name, .size = extras_size, .color = symbol_color); if(idx+1 < call_stack.frames_count) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" > "), .color = secondary_color, .size = extras_size); if(idx+1 == limit) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("..."), .color = secondary_color, .size = extras_size); } } } } } access_close(access); } //- rjf: modules get debug info status extras if(entity->kind == CTRL_EntityKind_Module && include_extras) { Access *access = access_open(); DI_Key dbgi_key = ctrl_dbgi_key_from_module(entity); RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); if(rdi->raw_data_size == 0) { dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("(Debug information not loaded)"), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .size = extras_size, .color = secondary_color); } access_close(access); } return result; } internal DR_FStrList rd_title_fstrs_from_code_name(Arena *arena, String8 code_name) { DR_FStrList result = {0}; { RD_VocabInfo *info = rd_vocab_info_from_code_name(code_name); //- rjf: set up color/size for all parts of the title // // the "running" part implies that it changes as things are added - // so if a primary title is pushed, we can make the rest of the title // more faded/smaller, but only after a primary title is pushed, // which could be caused by many different potential parts of a cfg. // DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; //- rjf: push icon if(info->icon_kind != RD_IconKind_Null) UI_Tag(str8_lit("weak")) { dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[info->icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } //- rjf: push display name if(info->display_name.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, info->display_name); } //- rjf: push code name as a fallback else { dr_fstrs_push_new(arena, &result, ¶ms, code_name, .font = rd_font_from_slot(RD_FontSlot_Code), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code)); } } return result; } internal DR_FStrList rd_title_fstrs_from_file_path(Arena *arena, String8 file_path) { DR_FStrList fstrs = {0}; String8 file_name = str8_skip_last_slash(file_path); FileProperties props = os_properties_from_file_path(file_path); RD_IconKind icon_kind = RD_IconKind_FileOutline; if(props.flags & FilePropertyFlag_IsFolder) { icon_kind = RD_IconKind_FolderClosedFilled; } if(file_path.size == 0 || str8_match(file_path, str8_lit("/"), StringMatchFlag_SlashInsensitive)) { icon_kind = RD_IconKind_Machine; file_name = str8_lit("File System"); } DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; UI_TagF("weak") { dr_fstrs_push_new(arena, &fstrs, ¶ms, rd_icon_kind_text_table[icon_kind], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = ui_color_from_name(str8_lit("text"))); } dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); dr_fstrs_push_new(arena, &fstrs, ¶ms, file_name); return fstrs; } //////////////////////////////// //~ rjf: UI Widgets: Loading Overlay internal void rd_loading_overlay(Rng2F32 rect, F32 loading_t, U64 progress_v, U64 progress_v_target) { if(loading_t >= 0.001f) UI_Focus(UI_FocusKind_Off) { // rjf: set up dimensions F32 edge_padding = 30.f; F32 width = ui_top_font_size() * 10; F32 height = ui_top_font_size() * 1.f; F32 min_thickness = ui_top_font_size()/2; F32 trail = ui_top_font_size() * 4; F32 t = pow_f32(sin_f32((F32)rd_state->time_in_seconds / 1.8f), 2.f); F64 v = 1.f - abs_f32(0.5f - t); // rjf: build indicator UI_CornerRadius(height/3.f) UI_Transparency(1-loading_t) { // rjf: rects Rng2F32 indicator_region_rect = r2f32p((rect.x0 + rect.x1)/2 - width/2 - rect.x0, (rect.y0 + rect.y1)/2 - height/2 - rect.y0, (rect.x0 + rect.x1)/2 + width/2 - rect.x0, (rect.y0 + rect.y1)/2 + height/2 - rect.y0); Rng2F32 indicator_rect = r2f32p(indicator_region_rect.x0 + width*t - min_thickness/2 - trail*v, indicator_region_rect.y0, indicator_region_rect.x0 + width*t + min_thickness/2 + trail*v, indicator_region_rect.y1); indicator_rect.x0 = Clamp(indicator_region_rect.x0, indicator_rect.x0, indicator_region_rect.x1); indicator_rect.x1 = Clamp(indicator_region_rect.x0, indicator_rect.x1, indicator_region_rect.x1); indicator_rect = pad_2f32(indicator_rect, -1.f); // rjf: does the view have loading *progress* info? -> draw extra progress layer if(progress_v != progress_v_target) UI_TagF("drop_site") { F64 pct_done_f64 = ((F64)progress_v/(F64)progress_v_target); F32 pct_done = (F32)pct_done_f64; Rng2F32 pct_rect = r2f32p(indicator_region_rect.x0, indicator_region_rect.y0, indicator_region_rect.x0 + (indicator_region_rect.x1 - indicator_region_rect.x0)*pct_done, indicator_region_rect.y1); UI_Rect(pct_rect) ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_Floating, ui_key_zero()); } // rjf: fill UI_TagF("pop") UI_Rect(indicator_rect) ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_Floating, ui_key_zero()); // rjf: animated bar UI_Rect(indicator_region_rect) { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder|UI_BoxFlag_Floating|UI_BoxFlag_Clickable, "bg_system_status"); UI_Signal sig = ui_signal_from_box(box); } } // rjf: build background UI_WidthFill UI_HeightFill UI_Transparency(1-loading_t) UI_BlurSize(10.f*loading_t) { ui_set_next_blur_size(10.f*loading_t); ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_Floating, ui_key_zero()); } } } //////////////////////////////// //~ rjf: UI Widgets: Fancy Buttons internal void rd_cmd_binding_buttons(String8 name, String8 filter, B32 add_new) { Temp scratch = scratch_begin(0, 0); CFG_KeyMapNodePtrList key_map_nodes = cfg_key_map_node_ptr_list_from_name(scratch.arena, rd_state->key_map, name); //- rjf: build buttons for each binding UI_CornerRadius(ui_top_font_size()*0.5f) for(CFG_KeyMapNodePtr *n = key_map_nodes.first; n != 0; n = n->next) { ui_spacer(ui_em(1.f, 1.f)); CFG_Binding binding = n->v->binding; B32 rebinding_active_for_this_binding = (rd_state->bind_change_active && str8_match(rd_state->bind_change_cmd_name, name, 0) && n->v->cfg_id == rd_state->bind_change_binding_id); //- rjf: grab all conflicts B32 has_conflicts = 0; CFG_KeyMapNodePtrList nodes_with_this_binding = cfg_key_map_node_ptr_list_from_binding(scratch.arena, rd_state->key_map, binding); { for(CFG_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next) { if(!str8_match(n->v->name, n2->v->name, 0)) { has_conflicts = 1; break; } } } //- rjf: form binding string String8 keybinding_str = {0}; { if(binding.key != OS_Key_Null) { keybinding_str = os_string_from_modifiers_key(scratch.arena, binding.modifiers, binding.key); } else { keybinding_str = str8_lit("- no binding -"); } } //- rjf: compute fuzzy matches FuzzyMatchRangeList matches = {0}; if(filter.size != 0) { matches = fuzzy_match_find(scratch.arena, filter, keybinding_str); } //- rjf: build box ui_set_next_tag(has_conflicts ? str8_lit("bad_pop") : rebinding_active_for_this_binding ? str8_lit("pop") : str8_zero()); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_group_key(ui_key_zero()); ui_set_next_pref_width(ui_text_dim(ui_top_font_size()*1.f, 1)); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_Clickable| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground, "%S###bind_btn_%S_%x_%x", keybinding_str, name, binding.key, binding.modifiers); ui_box_equip_fuzzy_match_ranges(box, &matches); //- rjf: interaction UI_Signal sig = ui_signal_from_box(box); { // rjf: click => toggle activity if(!rd_state->bind_change_active && ui_clicked(sig)) { if((binding.key == OS_Key_Esc || binding.key == OS_Key_Delete) && binding.modifiers == 0) { log_user_error(str8_lit("Cannot rebind; this command uses a reserved keybinding.")); } else { arena_clear(rd_state->bind_change_arena); rd_state->bind_change_active = 1; rd_state->bind_change_cmd_name = push_str8_copy(rd_state->bind_change_arena, name); rd_state->bind_change_binding_id = n->v->cfg_id; } } else if(rd_state->bind_change_active && ui_clicked(sig)) { rd_state->bind_change_active = 0; } // rjf: hover w/ conflicts => show conflicts if(ui_hovering(sig) && has_conflicts) UI_Tooltip { UI_PrefWidth(ui_children_sum(1)) rd_error_label(str8_lit("This binding conflicts with those for:")); for(CFG_KeyMapNodePtr *n2 = nodes_with_this_binding.first; n2 != 0; n2 = n2->next) { if(!str8_match(n2->v->name, n->v->name, 0)) { String8 display_name = rd_display_from_code_name(n2->v->name); ui_labelf("%S", display_name); } } } } //- rjf: delete button if(rebinding_active_for_this_binding) UI_PrefWidth(ui_em(2.5f, 1.f)) UI_TagF("bad_pop") { ui_set_next_group_key(ui_key_zero()); UI_Signal sig = rd_icon_button(RD_IconKind_X, 0, str8_lit("###delete_binding")); if(ui_clicked(sig)) { cfg_node_release(rd_state->cfg, cfg_node_from_id(rd_state->bind_change_binding_id)); rd_state->bind_change_active = 0; } } } //- rjf: build "add new binding" button if(add_new) { B32 adding_new_binding = (rd_state->bind_change_active && str8_match(rd_state->bind_change_cmd_name, name, 0) && rd_state->bind_change_binding_id == 0); ui_spacer(ui_em(1.f, 1.f)); RD_Font(RD_FontSlot_Icons) UI_TagF(adding_new_binding ? "pop" : "") UI_CornerRadius(ui_top_font_size()*0.5f) { ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_group_key(ui_key_zero()); ui_set_next_pref_width(ui_text_dim(ui_top_font_size()*1.5f, 1)); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_Clickable| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground, "%S###add_binding", rd_icon_kind_text_table[RD_IconKind_Add]); UI_Signal sig = ui_signal_from_box(box); if(ui_clicked(sig)) { if(!adding_new_binding && ui_clicked(sig)) { arena_clear(rd_state->bind_change_arena); rd_state->bind_change_active = 1; rd_state->bind_change_cmd_name = push_str8_copy(rd_state->bind_change_arena, name); rd_state->bind_change_binding_id = 0; } else if(adding_new_binding && ui_clicked(sig)) { rd_state->bind_change_active = 0; } } } } scratch_end(scratch); } internal UI_Signal rd_menu_bar_button(String8 string) { UI_Box *box = ui_build_box_from_string(UI_BoxFlag_DrawText|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable|UI_BoxFlag_DrawHotEffects, string); UI_Signal sig = ui_signal_from_box(box); return sig; } internal UI_Signal rd_cmd_spec_button(String8 name) { RD_CmdKindInfo *info = rd_cmd_kind_info_from_string(name); ui_set_next_child_layout_axis(Axis2_X); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects| UI_BoxFlag_Clickable, "###cmd_%p", info); UI_Parent(box) UI_HeightFill UI_Padding(ui_em(1.f, 1.f)) { RD_IconKind canonical_icon = rd_icon_kind_from_code_name(name); if(canonical_icon != RD_IconKind_Null) { RD_Font(RD_FontSlot_Icons) UI_PrefWidth(ui_em(2.f, 1.f)) UI_TextAlignment(UI_TextAlign_Center) UI_TagF("weak") { ui_label(rd_icon_kind_text_table[canonical_icon]); } } UI_PrefWidth(ui_text_dim(10, 1.f)) { UI_Flags(UI_BoxFlag_DrawTextFastpathCodepoint) UI_FastpathCodepoint(box->fastpath_codepoint) ui_label(rd_display_from_code_name(name)); ui_spacer(ui_pct(1, 0)); ui_set_next_flags(UI_BoxFlag_Clickable); ui_set_next_group_key(ui_key_zero()); UI_PrefWidth(ui_children_sum(1)) UI_FontSize(ui_top_font_size()*0.95f) UI_HeightFill UI_NamedRow(str8_lit("###bindings")) UI_TagF("weak") UI_FastpathCodepoint(0) { rd_cmd_binding_buttons(name, str8_zero(), 1); } } } UI_Signal sig = ui_signal_from_box(box); return sig; } internal void rd_cmd_list_menu_buttons(U64 count, String8 *cmd_names, U32 *fastpath_codepoints) { Temp scratch = scratch_begin(0, 0); for EachIndex(idx, count) { if(cmd_names[idx].size == 0) { UI_TagF("floating") ui_divider(ui_em(1.f, 1.f)); } else { ui_set_next_fastpath_codepoint(fastpath_codepoints[idx]); UI_Signal sig = rd_cmd_spec_button(cmd_names[idx]); if(ui_clicked(sig)) { rd_cmd(RD_CmdKind_RunCommand, .cmd_name = cmd_names[idx]); ui_ctx_menu_close(); CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); ws->menu_bar_focused = 0; } } } scratch_end(scratch); } internal UI_Signal rd_icon_button(RD_IconKind kind, FuzzyMatchRangeList *matches, String8 string) { String8 display_string = ui_display_part_from_key_string(string); ui_set_next_child_layout_axis(Axis2_X); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, string); UI_Parent(box) { if(display_string.size == 0) { ui_spacer(ui_pct(1, 0)); } else { ui_spacer(ui_em(1.f, 1.f)); } UI_TextAlignment(UI_TextAlign_Center) RD_Font(RD_FontSlot_Icons) UI_PrefWidth(ui_em(2.f, 1.f)) UI_PrefHeight(ui_pct(1, 0)) UI_FlagsAdd(UI_BoxFlag_DisableTextTrunc) UI_TagF("weak") ui_label(rd_icon_kind_text_table[kind]); if(display_string.size != 0) { UI_PrefWidth(ui_pct(1.f, 0.f)) { UI_Box *box = ui_label(display_string).box; if(matches != 0) { ui_box_equip_fuzzy_match_ranges(box, matches); } } } if(display_string.size == 0) { ui_spacer(ui_pct(1, 0)); } else { ui_spacer(ui_em(1.f, 1.f)); } } UI_Signal result = ui_signal_from_box(box); return result; } internal UI_Signal rd_icon_buttonf(RD_IconKind kind, FuzzyMatchRangeList *matches, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = rd_icon_button(kind, matches, string); scratch_end(scratch); return sig; } //////////////////////////////// //~ rjf: UI Widgets: Text View typedef struct RD_ThreadBoxDrawExtData RD_ThreadBoxDrawExtData; struct RD_ThreadBoxDrawExtData { Vec4F32 thread_color; F32 progress_t; F32 alive_t; F32 hover_t; B32 is_selected; B32 is_frozen; B32 do_lines; B32 do_glow; }; internal UI_BOX_CUSTOM_DRAW(rd_thread_box_draw_extensions) { RD_ThreadBoxDrawExtData *u = (RD_ThreadBoxDrawExtData *)box->custom_draw_user_data; // rjf: draw line before next-to-execute line if(u->do_lines) { R_Rect2DInst *inst = dr_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0 - box->font_size*0.125f, box->parent->parent->parent->rect.x0 + box->font_size*260*u->alive_t, box->parent->rect.y0 + box->font_size*0.125f), v4f32(u->thread_color.x, u->thread_color.y, u->thread_color.z, 0), 0, 0, 1); inst->colors[Corner_00] = inst->colors[Corner_01] = u->thread_color; } // rjf: draw 'progress bar', showing thread's progress through the line's address range if(u->progress_t > 0) { Vec4F32 weak_thread_color = u->thread_color; weak_thread_color.w *= 0.4f; dr_rect(r2f32p(box->rect.x0, box->rect.y0, box->rect.x1, box->rect.y0 + (box->rect.y1-box->rect.y0)*u->progress_t), weak_thread_color, 0, 0, 1); } // rjf: draw rich hover fill if(u->hover_t > 0.001f) { Vec4F32 weak_thread_color = u->thread_color; weak_thread_color.w *= 0.15f*u->hover_t; R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->parent->rect.y0, box->rect.x0 + ui_top_font_size()*22.f*u->hover_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); inst->colors[Corner_00] = inst->colors[Corner_01] = weak_thread_color; } // rjf: draw slight fill on selected thread if(u->is_selected && u->do_glow) { Vec4F32 weak_thread_color = u->thread_color; weak_thread_color.w *= 0.1f; R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->parent->rect.y0, box->rect.x0 + ui_top_font_size()*22.f*u->alive_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); inst->colors[Corner_00] = inst->colors[Corner_01] = weak_thread_color; } // rjf: locked icon on frozen threads if(u->is_frozen) UI_TagF("bad") { F32 lock_icon_off = ui_top_font_size()*0.2f; Vec4F32 color = ui_color_from_name(str8_lit("text")); dr_text(rd_font_from_slot(RD_FontSlot_Icons), box->font_size, 0, 0, FNT_RasterFlag_Smooth, v2f32((box->rect.x0 + box->rect.x1)/2 + lock_icon_off/2, box->rect.y0 + lock_icon_off/2), color, rd_icon_kind_text_table[RD_IconKind_Locked]); } } typedef struct RD_BreakpointBoxDrawExtData RD_BreakpointBoxDrawExtData; struct RD_BreakpointBoxDrawExtData { Vec4F32 color; F32 alive_t; F32 hover_t; F32 remap_px_delta; B32 do_lines; B32 do_glow; B32 is_disabled; B32 is_conditioned; }; internal UI_BOX_CUSTOM_DRAW(rd_bp_box_draw_extensions) { RD_BreakpointBoxDrawExtData *u = (RD_BreakpointBoxDrawExtData *)box->custom_draw_user_data; // rjf: draw line before next-to-execute line if(u->do_lines) { R_Rect2DInst *inst = dr_rect(r2f32p(box->parent->parent->parent->rect.x0, box->parent->rect.y0 - box->font_size*0.125f, box->parent->parent->parent->rect.x0 + ui_top_font_size()*250.f*u->alive_t, box->parent->rect.y0 + box->font_size*0.125f), v4f32(u->color.x, u->color.y, u->color.z, 0), 0, 0, 1.f); inst->colors[Corner_00] = inst->colors[Corner_01] = u->color; } // rjf: draw rich hover fill if(u->hover_t > 0.001f) { Vec4F32 weak_color = u->color; weak_color.w *= 0.5f*u->hover_t; R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->parent->rect.y0, box->rect.x0 + ui_top_font_size()*22.f*u->hover_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); inst->colors[Corner_00] = inst->colors[Corner_01] = weak_color; } // rjf: draw slight fill if(u->do_glow) { Vec4F32 weak_thread_color = u->color; weak_thread_color.w *= 0.3f; R_Rect2DInst *inst = dr_rect(r2f32p(box->rect.x0, box->parent->rect.y0, box->rect.x0 + ui_top_font_size()*22.f*u->alive_t, box->parent->rect.y1), v4f32(0, 0, 0, 0), 0, 0, 1); inst->colors[Corner_00] = inst->colors[Corner_01] = weak_thread_color; } // rjf: draw remaps if(u->remap_px_delta != 0) { F32 remap_px_delta = u->remap_px_delta; F32 circle_advance = fnt_dim_from_tag_size_string(box->font, box->font_size, 0, 0, rd_icon_kind_text_table[RD_IconKind_CircleFilled]).x; Vec2F32 bp_text_pos = ui_box_text_position(box); Vec2F32 bp_center = v2f32(bp_text_pos.x + circle_advance/2, bp_text_pos.y); FNT_Metrics icon_font_metrics = fnt_metrics_from_tag_size(box->font, box->font_size); F32 icon_font_line_height = fnt_line_height_from_metrics(&icon_font_metrics); F32 remap_bar_thickness = 0.3f*ui_top_font_size(); Vec4F32 remap_color = u->color; remap_color.w *= 0.3f; R_Rect2DInst *inst = dr_rect(r2f32p(bp_center.x - remap_bar_thickness, bp_center.y + ClampTop(remap_px_delta, 0) + remap_bar_thickness, bp_center.x + remap_bar_thickness, bp_center.y + ClampBot(remap_px_delta, 0) - remap_bar_thickness), remap_color, 2.f, 0, 1.f); dr_text(box->font, box->font_size, 0, 0, FNT_RasterFlag_Smooth, v2f32(bp_text_pos.x, bp_center.y + remap_px_delta), remap_color, rd_icon_kind_text_table[RD_IconKind_CircleFilled]); } // rjf: draw conditioned marker if(u->is_conditioned) UI_TagF(u->is_disabled ? "weak" : "") { Temp scratch = scratch_begin(0, 0); Vec4F32 color = ui_color_from_name(str8_lit("text")); FNT_Run run = fnt_run_from_string(rd_font_from_slot(RD_FontSlot_Code), box->font_size*0.8f, 0, 0, FNT_RasterFlag_Smooth, str8_lit("if")); Vec2F32 p = center_2f32(box->rect); p.x -= run.dim.x*0.5f; p.y += run.descent; dr_text_run(p, color, run); scratch_end(scratch); } // rjf: draw disabled marker if(u->is_disabled) { Temp scratch = scratch_begin(0, 0); Vec4F32 color = ui_color_from_name(str8_lit("breakpoint")); FNT_Run run = fnt_run_from_string(rd_font_from_slot(RD_FontSlot_Icons), box->font_size*0.95f, 0, 0, FNT_RasterFlag_Smooth, str8_lit("x")); Vec2F32 box_dim = dim_2f32(box->rect); Vec2F32 p = center_2f32(box->rect); p.x += box_dim.x*0.1f; p.y -= box_dim.y*0.2f; dr_text_run(p, color, run); scratch_end(scratch); } } internal RD_CodeSliceSignal rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string) { RD_CodeSliceSignal result = {0}; ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); CTRL_Entity *selected_thread_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process); U64 selected_thread_rip_unwind_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count); CTRL_Entity *selected_thread_module = ctrl_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr); CTRL_Event stop_event = d_ctrl_last_stop_event(); CTRL_Entity *stopper_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, stop_event.entity); B32 is_focused = ui_is_focus_active(); B32 ctrlified = (os_get_modifiers() & OS_Modifier_Ctrl); Vec4F32 code_line_bgs[] = { ui_color_from_name(str8_lit("line_info_0")), ui_color_from_name(str8_lit("line_info_1")), ui_color_from_name(str8_lit("line_info_2")), ui_color_from_name(str8_lit("line_info_3")), }; F32 line_num_padding_px = ui_top_font_size()*1.f; F32 entity_alive_t_rate = rd_state->entity_alive_animation_rate; F32 entity_hover_t_rate = rd_state->rich_hover_animation_rate; B32 do_thread_lines = rd_setting_b32_from_name(str8_lit("thread_lines")); B32 do_thread_glow = rd_setting_b32_from_name(str8_lit("thread_glow")); B32 do_bp_lines = rd_setting_b32_from_name(str8_lit("breakpoint_lines")); B32 do_bp_glow = rd_setting_b32_from_name(str8_lit("breakpoint_glow")); B32 do_scope_lines = rd_setting_b32_from_name(str8_lit("cursor_scope_lines")); B32 do_cursor_trail = rd_setting_b32_from_name(str8_lit("cursor_trail")); Vec4F32 pop_color = {0}; UI_TagF("pop") { pop_color = ui_color_from_name(str8_lit("background")); } Vec4F32 highlight_color = {0}; UI_TagF("focus") { highlight_color = ui_color_from_name(str8_lit("border")); } ////////////////////////////// //- rjf: build top-level container // UI_Box *top_container_box = &ui_nil_box; Rng2F32 clipped_top_container_rect = {0}; { ui_set_next_child_layout_axis(Axis2_X); ui_set_next_pref_width(ui_px(params->line_text_max_width_px, 1)); ui_set_next_pref_height(ui_children_sum(1)); top_container_box = ui_build_box_from_string(UI_BoxFlag_DisableFocusEffects|UI_BoxFlag_DrawBorder, string); clipped_top_container_rect = top_container_box->rect; for(UI_Box *b = top_container_box; !ui_box_is_nil(b); b = b->parent) { if(b->flags & UI_BoxFlag_Clip) { clipped_top_container_rect = intersect_2f32(b->rect, clipped_top_container_rect); } } } ////////////////////////////// //- rjf: dragging cfgs/entities/expressions? -> drop site // B32 drop_can_hit_lines = 0; CFG_Node *drop_cfg = &cfg_nil_node; CTRL_Entity *drop_thread = &ctrl_entity_nil; String8 drop_expr = {0}; Vec4F32 drop_color = pop_color; UI_Key drop_site_key = ui_key_from_stringf(top_container_box->key, "drop_site"); if(rd_drag_is_active()) { CFG_Node *cfg = cfg_node_from_id(rd_state->drag_drop_regs->cfg); if(rd_state->drag_drop_regs_slot == RD_RegSlot_Cfg && (str8_match(cfg->string, str8_lit("breakpoint"), 0) || str8_match(cfg->string, str8_lit("watch_pin"), 0))) { drop_can_hit_lines = 1; drop_cfg = cfg; drop_color = linear_from_srgba(rd_color_from_cfg(cfg)); if(drop_color.w == 0) { drop_color = pop_color; } } if(rd_state->drag_drop_regs_slot == RD_RegSlot_Thread) { drop_can_hit_lines = 1; drop_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_state->drag_drop_regs->thread); drop_color = rd_color_from_ctrl_entity(drop_thread); if(drop_color.w == 0) { drop_color = pop_color; } } if(rd_state->drag_drop_regs_slot == RD_RegSlot_Expr) { drop_can_hit_lines = 1; drop_expr = rd_state->drag_drop_regs->expr; } if(drop_can_hit_lines) UI_WidthFill UI_HeightFill { UI_Box *drop_site_box = ui_build_box_from_key(UI_BoxFlag_DropSite|UI_BoxFlag_Floating, drop_site_key); ui_signal_from_box(drop_site_box); } } ////////////////////////////// //- rjf: build per-line background colors // Vec4F32 *line_bg_colors = push_array(scratch.arena, Vec4F32, dim_1s64(params->line_num_range)+1); { //- rjf: color line with stopper-thread red UI_TagF("bad_pop") { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num < params->line_num_range.max; line_num += 1, line_idx += 1) { CTRL_EntityList threads = params->line_ips[line_idx]; for(CTRL_EntityNode *n = threads.first; n != 0; n = n->next) { if(n->v == stopper_thread && (stop_event.cause == CTRL_EventCause_InterruptedByTrap || stop_event.cause == CTRL_EventCause_InterruptedByException)) { line_bg_colors[line_idx] = ui_color_from_name(str8_lit("background")); } } } } } ////////////////////////////// //- rjf: build priority margin // UI_Box *priority_margin_container_box = &ui_nil_box; if(params->flags & RD_CodeSliceFlag_PriorityMargin) UI_Focus(UI_FocusKind_Off) UI_Parent(top_container_box) ProfScope("build priority margins") { if(params->margin_float_off_px != 0) { ui_set_next_pref_width(ui_px(params->priority_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_build_box_from_key(0, ui_key_zero()); ui_set_next_fixed_x(floor_f32(params->margin_float_off_px)); } ui_set_next_pref_width(ui_px(params->priority_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_set_next_child_layout_axis(Axis2_Y); priority_margin_container_box = ui_build_box_from_string(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable), str8_lit("priority_margin_container")); UI_Parent(priority_margin_container_box) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { CTRL_EntityList line_ips = params->line_ips[line_idx]; ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num); UI_Parent(line_margin_box) { //- rjf: build margin thread ip ui for(CTRL_EntityNode *n = line_ips.first; n != 0; n = n->next) { // rjf: unpack thread CTRL_Entity *thread = n->v; if(thread != selected_thread) { continue; } U64 unwind_count = (thread == selected_thread) ? rd_regs()->unwind_count : 0; U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr); // rjf: thread info => color Vec4F32 color = rd_color_from_ctrl_entity(thread); { if(color.w == 0) { color = ui_color_from_name(str8_lit("thread_1")); } if(unwind_count != 0) { color = ui_color_from_name(str8_lit("thread_unwound")); } else if(thread == stopper_thread && (stop_event.cause == CTRL_EventCause_InterruptedByHalt || stop_event.cause == CTRL_EventCause_InterruptedByTrap || stop_event.cause == CTRL_EventCause_InterruptedByException)) { color = ui_color_from_name(str8_lit("thread_error")); } if(d_ctrl_targets_running() && d_ctrl_last_run_frame_idx() < d_frame_index()) { color.w *= 0.5f; } if(thread != selected_thread) { color.w *= 0.5f; } } // rjf: build thread box ui_set_next_hover_cursor(OS_Cursor_UpDownLeftRight); ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_font_size(params->font_size); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_text_color(color); UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%I64x_%p", line_num, thread); UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)| UI_BoxFlag_DrawText, thread_box_key); ui_box_equip_display_string(thread_box, rd_icon_kind_text_table[RD_IconKind_RightArrow]); UI_Signal thread_sig = ui_signal_from_box(thread_box); // rjf: custom draw { RD_Regs *hover_regs = rd_get_hover_regs(); B32 is_hovering = (ctrl_handle_match(hover_regs->ctrl_entity, thread->handle) && rd_state->hover_regs_slot == RD_RegSlot_CtrlEntity); RD_ThreadBoxDrawExtData *u = push_array(ui_build_arena(), RD_ThreadBoxDrawExtData, 1); u->thread_color = color; u->alive_t = ui_anim(ui_key_from_stringf(top_container_box->key, "###entity_alive_t_%p", thread), 1.f, .rate = entity_alive_t_rate); u->hover_t = ui_anim(ui_key_from_stringf(top_container_box->key, "###entity_hover_t_%p", thread), (F32)!!is_hovering, .rate = entity_hover_t_rate); u->is_selected = (thread == selected_thread); u->is_frozen = !!thread->is_frozen; u->do_lines = do_thread_lines; u->do_glow = do_thread_glow; ui_box_equip_custom_draw(thread_box, rd_thread_box_draw_extensions, u); // rjf: fill out progress t (progress into range of current line's // voff range) if(params->line_infos[line_idx].first != 0) { D_LineList *lines = ¶ms->line_infos[line_idx]; D_Line *line = 0; for(D_LineNode *n = lines->first; n != 0; n = n->next) { if(di_key_match(n->v.dbgi_key, dbgi_key)) { line = &n->v; break; } } if(line != 0) { Rng1U64 line_voff_rng = line->voff_range; Vec4F32 weak_thread_color = color; weak_thread_color.w *= 0.4f; F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0; progress_t = Clamp(0, progress_t, 1); u->progress_t = progress_t; } } } // rjf: interactions if(ui_hovering(thread_sig) && !rd_drag_is_active()) { RD_RegsScope(.ctrl_entity = thread->handle) rd_set_hover_regs(RD_RegSlot_CtrlEntity); } if(ui_right_clicked(thread_sig)) { rd_cmd(RD_CmdKind_PushQuery, .ui_key = thread_box->key, .expr = push_str8f(scratch.arena, "query:control.%S", ctrl_string_from_handle(scratch.arena, thread->handle))); } if(ui_dragging(thread_sig) && !contains_2f32(thread_box->rect, ui_mouse())) { RD_RegsScope(.thread = thread->handle) rd_drag_begin(RD_RegSlot_Thread); } } } } } } ////////////////////////////// //- rjf: build catchall margin // UI_Box *catchall_margin_container_box = &ui_nil_box; if(params->flags & RD_CodeSliceFlag_CatchallMargin) UI_Focus(UI_FocusKind_Off) UI_Parent(top_container_box) ProfScope("build catchall margins") UI_TagF("floating") { if(params->margin_float_off_px != 0) { ui_set_next_pref_width(ui_px(params->catchall_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_build_box_from_key(0, ui_key_zero()); ui_set_next_fixed_x(floor_f32(params->margin_float_off_px + params->priority_margin_width_px)); } ui_set_next_pref_width(ui_px(params->catchall_margin_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_set_next_child_layout_axis(Axis2_Y); catchall_margin_container_box = ui_build_box_from_string(UI_BoxFlag_DrawSideRight|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable), str8_lit("catchall_margin_container")); UI_Parent(catchall_margin_container_box) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { CTRL_EntityList line_ips = params->line_ips[line_idx]; CFG_NodePtrList line_bps = params->line_bps[line_idx]; CFG_NodePtrList line_pins = params->line_pins[line_idx]; ui_set_next_hover_cursor(OS_Cursor_HandPoint); ui_set_next_background_color(v4f32(0, 0, 0, 0)); UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num); UI_Parent(line_margin_box) { //- rjf: build margin thread ip ui for(CTRL_EntityNode *n = line_ips.first; n != 0; n = n->next) { // rjf: unpack thread CTRL_Entity *thread = n->v; if(thread == selected_thread) { continue; } U64 unwind_count = (thread == selected_thread) ? rd_regs()->unwind_count : 0; U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_count); CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); CTRL_Entity *module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr); // rjf: thread info => color Vec4F32 color = rd_color_from_ctrl_entity(thread); { if(color.w == 0) { color = ui_color_from_name(str8_lit("thread_1")); } if(unwind_count != 0) { color = ui_color_from_name(str8_lit("thread_unwound")); } else if(thread == stopper_thread && (stop_event.cause == CTRL_EventCause_InterruptedByHalt || stop_event.cause == CTRL_EventCause_InterruptedByTrap || stop_event.cause == CTRL_EventCause_InterruptedByException)) { color = ui_color_from_name(str8_lit("thread_error")); } if(d_ctrl_targets_running() && d_ctrl_last_run_frame_idx() < d_frame_index()) { color.w *= 0.5f; } if(thread != selected_thread) { color.w *= 0.8f; } } // rjf: build thread box ui_set_next_hover_cursor(OS_Cursor_UpDownLeftRight); ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_font_size(params->font_size); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_pct(1, 0)); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_text_color(color); UI_Key thread_box_key = ui_key_from_stringf(top_container_box->key, "###ip_%I64x_catchall_%p", line_num, thread); UI_Box *thread_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc| UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)| UI_BoxFlag_DrawText, thread_box_key); ui_box_equip_display_string(thread_box, rd_icon_kind_text_table[RD_IconKind_RightArrow]); UI_Signal thread_sig = ui_signal_from_box(thread_box); // rjf: custom draw { RD_Regs *hover_regs = rd_get_hover_regs(); B32 is_hovering = (ctrl_handle_match(hover_regs->ctrl_entity, thread->handle) && rd_state->hover_regs_slot == RD_RegSlot_CtrlEntity); RD_ThreadBoxDrawExtData *u = push_array(ui_build_arena(), RD_ThreadBoxDrawExtData, 1); u->thread_color = color; u->alive_t = ui_anim(ui_key_from_stringf(top_container_box->key, "###entity_alive_t_%p", thread), 1.f, .rate = entity_alive_t_rate); u->hover_t = ui_anim(ui_key_from_stringf(top_container_box->key, "###entity_hover_t_%p", thread), (F32)!!is_hovering, .rate = entity_hover_t_rate); u->is_selected = (thread == selected_thread); u->is_frozen = !!thread->is_frozen; ui_box_equip_custom_draw(thread_box, rd_thread_box_draw_extensions, u); // rjf: fill out progress t (progress into range of current line's // voff range) if(params->line_vaddrs[line_idx] == 0 && params->line_infos[line_idx].first != 0) { D_LineList *lines = ¶ms->line_infos[line_idx]; D_Line *line = 0; for(D_LineNode *n = lines->first; n != 0; n = n->next) { if(di_key_match(n->v.dbgi_key, dbgi_key)) { line = &n->v; break; } } if(line != 0) { Rng1U64 line_voff_rng = line->voff_range; Vec4F32 weak_thread_color = color; weak_thread_color.w *= 0.4f; F32 progress_t = (line_voff_rng.max != line_voff_rng.min) ? ((F32)(thread_rip_voff - line_voff_rng.min) / (F32)(line_voff_rng.max - line_voff_rng.min)) : 0; progress_t = Clamp(0, progress_t, 1); u->progress_t = progress_t; } } } // rjf: interactions if(ui_hovering(thread_sig) && !rd_drag_is_active()) { RD_RegsScope(.ctrl_entity = thread->handle) rd_set_hover_regs(RD_RegSlot_CtrlEntity); } if(ui_right_clicked(thread_sig)) { rd_cmd(RD_CmdKind_PushQuery, .ui_key = thread_box->key, .expr = push_str8f(scratch.arena, "query:control.%S", ctrl_string_from_handle(scratch.arena, thread->handle))); } if(ui_dragging(thread_sig) && !contains_2f32(thread_box->rect, ui_mouse())) { RD_RegsScope(.thread = thread->handle) rd_drag_begin(RD_RegSlot_Thread); } if(ui_double_clicked(thread_sig)) { rd_cmd(RD_CmdKind_SelectThread, .thread = thread->handle); ui_kill_action(); } } //- rjf: build margin breakpoint ui for(CFG_NodePtrNode *n = line_bps.first; n != 0; n = n->next) { CFG_Node *bp = n->v; Vec4F32 bp_rgba = rd_color_from_cfg(bp); if(bp_rgba.w == 0) { bp_rgba = ui_color_from_name(str8_lit("breakpoint")); } B32 bp_is_disabled = rd_disabled_from_cfg(bp); if(bp_is_disabled) { bp_rgba = v4f32(bp_rgba.x*0.45f, bp_rgba.y*0.45f, bp_rgba.z*0.45f, bp_rgba.w*0.45f); } // rjf: prep custom rendering data RD_BreakpointBoxDrawExtData *bp_draw = push_array(ui_build_arena(), RD_BreakpointBoxDrawExtData, 1); { RD_Regs *hover_regs = rd_get_hover_regs(); B32 is_hovering = (cfg_node_from_id(hover_regs->cfg) == bp && rd_state->hover_regs_slot == RD_RegSlot_Cfg); bp_draw->color = bp_rgba; bp_draw->alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "cfg_alive_t_%p", bp), 1.f, .rate = entity_alive_t_rate); bp_draw->hover_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "cfg_hover_t_%p", bp), (F32)!!is_hovering, .rate = entity_hover_t_rate); bp_draw->do_lines = do_bp_lines; bp_draw->do_glow = do_bp_glow; bp_draw->is_disabled = bp_is_disabled; bp_draw->is_conditioned = (cfg_node_child_from_string(bp, str8_lit("condition"))->first->string.size != 0); if(params->line_vaddrs[line_idx] == 0) { D_LineList *lines = ¶ms->line_infos[line_idx]; for(D_LineNode *n = lines->first; n != 0; n = n->next) { S64 remap_line = n->v.pt.line; if(remap_line != line_num) { bp_draw->remap_px_delta = (remap_line - line_num) * params->line_height_px; break; } } } } // rjf: build box for breakpoint ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_font_size(params->font_size * 1.f); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_text_color(bp_rgba); UI_Box *bp_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)| UI_BoxFlag_DisableTextTrunc, "%S##bp_%p", rd_icon_kind_text_table[RD_IconKind_CircleFilled], bp); ui_box_equip_custom_draw(bp_box, rd_bp_box_draw_extensions, bp_draw); UI_Signal bp_sig = ui_signal_from_box(bp_box); // rjf: bp hovering if(ui_hovering(bp_sig) && !rd_drag_is_active()) { RD_RegsScope(.cfg = bp->id) rd_set_hover_regs(RD_RegSlot_Cfg); } // rjf: bp right-click => open query if(ui_right_clicked(bp_sig)) { rd_cmd(RD_CmdKind_PushQuery, .ui_key = bp_box->key, .expr = push_str8f(scratch.arena, "query:config.$%I64x", bp->id)); } // rjf: shift+click => enable breakpoint if(ui_clicked(bp_sig) && bp_sig.event_flags & OS_Modifier_Shift) { rd_cmd(bp_is_disabled ? RD_CmdKind_EnableCfg : RD_CmdKind_DisableCfg, .cfg = bp->id); } // rjf: click => remove breakpoint if(ui_clicked(bp_sig) && bp_sig.event_flags == 0) { rd_cmd(RD_CmdKind_RemoveCfg, .cfg = bp->id); } // rjf: drag start if(ui_dragging(bp_sig) && !contains_2f32(bp_box->rect, ui_mouse())) { RD_RegsScope(.cfg = bp->id) rd_drag_begin(RD_RegSlot_Cfg); } } //- rjf: build margin watch pin ui for(CFG_NodePtrNode *n = line_pins.first; n != 0; n = n->next) { CFG_Node *pin = n->v; Vec4F32 color = rd_color_from_cfg(pin); if(color.w == 0) { color = ui_color_from_name(str8_lit("code_default")); } // rjf: build box for watch ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_font_size(params->font_size * 1.f); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_text_color(color); UI_Box *pin_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)| UI_BoxFlag_DisableTextTrunc, "%S##watch_%p", rd_icon_kind_text_table[RD_IconKind_Pin], pin); UI_Signal pin_sig = ui_signal_from_box(pin_box); // rjf: watch hovering if(ui_hovering(pin_sig) && !rd_drag_is_active()) { RD_RegsScope(.cfg = pin->id) rd_set_hover_regs(RD_RegSlot_Cfg); } // rjf: pin right-click => open query if(ui_right_clicked(pin_sig)) { rd_cmd(RD_CmdKind_PushQuery, .ui_key = pin_box->key, .expr = push_str8f(scratch.arena, "query:config.$%I64x", pin->id)); } // rjf: click => remove pin if(ui_clicked(pin_sig)) { rd_cmd(RD_CmdKind_RemoveCfg, .cfg = pin->id); } // rjf: drag start if(ui_dragging(pin_sig) && !contains_2f32(pin_box->rect, ui_mouse())) { RD_RegsScope(.cfg = pin->id) rd_drag_begin(RD_RegSlot_Cfg); } } } // rjf: empty margin interaction UI_Signal line_margin_sig = ui_signal_from_box(line_margin_box); if(ui_clicked(line_margin_sig)) { rd_cmd(RD_CmdKind_AddBreakpoint, .file_path = params->line_vaddrs[line_idx] ? str8_zero() : rd_regs()->file_path, .cursor = params->line_vaddrs[line_idx] ? txt_pt(0, 0) : txt_pt(line_num, 1), .vaddr = params->line_vaddrs[line_idx]); } } } } ////////////////////////////// //- rjf: build line numbers // if(params->flags & RD_CodeSliceFlag_LineNums) UI_Parent(top_container_box) ProfScope("build line numbers") UI_Focus(UI_FocusKind_Off) UI_TagF("floating") { TxtRng select_rng = txt_rng(*cursor, *mark); ui_set_next_fixed_x(floor_f32(params->margin_float_off_px + params->priority_margin_width_px + params->catchall_margin_width_px)); ui_set_next_pref_width(ui_px(params->line_num_width_px, 1.f)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_set_next_flags(UI_BoxFlag_DrawSideRight); UI_Column UI_PrefHeight(ui_px(params->line_height_px, 1.f)) RD_Font(RD_FontSlot_Code) UI_FontSize(params->font_size) UI_CornerRadius(0) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { B32 line_is_selected = (select_rng.min.line <= line_num && line_num <= select_rng.max.line); Vec4F32 bg_color = v4f32(0, 0, 0, 0); // rjf: line info on this line -> adjust bg color to visualize B32 has_line_info = 0; { S64 line_info_line_num = 0; F32 line_info_t = 0; D_LineList *lines = ¶ms->line_infos[line_idx]; for(D_LineNode *n = lines->first; n != 0; n = n->next) { has_line_info = (has_line_info || n->v.pt.line == line_num || params->line_vaddrs[line_idx] != 0); line_info_line_num = n->v.pt.line; line_info_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "dbgi_alive_t_%I64x_%I64x", n->v.dbgi_key.u64[0], n->v.dbgi_key.u64[1]), 1.f); } if(has_line_info) { Vec4F32 color = code_line_bgs[line_info_line_num % ArrayCount(code_line_bgs)]; color.w *= line_info_t; bg_color = color; } } // rjf: build line num box UI_TagF(line_is_selected ? "" : "weak") UI_BackgroundColor(bg_color) ui_build_box_from_stringf(UI_BoxFlag_DrawText|(UI_BoxFlag_DrawBackground*!!has_line_info), "%I64u##line_num", line_num); } } } ////////////////////////////// //- rjf: build background for line numbers & margins // { UI_Parent(top_container_box) UI_TagF("floating") { ui_set_next_pref_width(ui_px(params->priority_margin_width_px + params->catchall_margin_width_px + params->line_num_width_px, 1)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_set_next_fixed_x(floor_f32(params->margin_float_off_px)); ui_build_box_from_key(UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } } ////////////////////////////// //- rjf: build main text container box, for mouse interaction on both lines & line numbers // UI_Box *text_container_box = &ui_nil_box; UI_Parent(top_container_box) UI_Focus(UI_FocusKind_Off) { ui_set_next_hover_cursor(ctrlified ? OS_Cursor_HandPoint : OS_Cursor_IBar); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); text_container_box = ui_build_box_from_string(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable), str8_lit("text_container")); } ////////////////////////////// //- rjf: mouse -> text coordinates // TxtPt mouse_pt = {0}; ProfScope("mouse -> text coordinates") { Vec2F32 mouse = ui_mouse(); // rjf: mouse y => index U64 mouse_y_line_idx = (U64)((mouse.y - text_container_box->rect.y0) / params->line_height_px); // rjf: index => line num S64 line_num = (params->line_num_range.min + mouse_y_line_idx); String8 line_string = (params->line_num_range.min <= line_num && line_num <= params->line_num_range.max) ? (params->line_text[mouse_y_line_idx]) : str8_zero(); // rjf: mouse x * string => column S64 column = fnt_char_pos_from_tag_size_string_p(params->font, params->font_size, 0, params->tab_size, line_string, mouse.x-text_container_box->rect.x0-params->line_num_width_px-line_num_padding_px)+1; // rjf: bundle mouse_pt = txt_pt(line_num, column); // rjf: clamp { U64 last_line_size = params->line_text[dim_1s64(params->line_num_range)].size; TxtRng legal_pt_rng = txt_rng(txt_pt(params->line_num_range.min, 1), txt_pt(params->line_num_range.max, last_line_size+1)); if(txt_pt_less_than(mouse_pt, legal_pt_rng.min)) { mouse_pt = legal_pt_rng.min; } if(txt_pt_less_than(legal_pt_rng.max, mouse_pt)) { mouse_pt = legal_pt_rng.max; } } result.mouse_pt = mouse_pt; } ////////////////////////////// //- rjf: mouse point -> mouse token range, mouse line range // TxtRng mouse_token_rng = txt_rng(mouse_pt, mouse_pt); TxtRng mouse_line_rng = txt_rng(mouse_pt, mouse_pt); if(contains_1s64(params->line_num_range, mouse_pt.line)) { TXT_TokenArray *line_tokens = ¶ms->line_tokens[mouse_pt.line-params->line_num_range.min]; Rng1U64 line_range = params->line_ranges[mouse_pt.line-params->line_num_range.min]; U64 mouse_pt_off = (mouse_pt.column-1) + line_range.min; for(U64 line_token_idx = 0; line_token_idx < line_tokens->count; line_token_idx += 1) { TXT_Token *line_token = &line_tokens->v[line_token_idx]; if(contains_1u64(line_token->range, mouse_pt_off)) { Rng1U64 line_token_range_clamped = intersect_1u64(line_token->range, line_range); mouse_token_rng = txt_rng(txt_pt(mouse_pt.line, 1+line_token_range_clamped.min-line_range.min), txt_pt(mouse_pt.line, 1+line_token_range_clamped.max-line_range.min)); break; } } mouse_line_rng = txt_rng(txt_pt(mouse_pt.line, 1), txt_pt(mouse_pt.line, 1+(line_range.max-line_range.min))); } ////////////////////////////// //- rjf: determine starting offset for each at line, at which we can begin placing extra info to the right // F32 *line_extras_off = push_array(scratch.arena, F32, dim_1s64(params->line_num_range)+1); { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { F32 line_text_dim = fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, params->line_text[line_idx]).x + params->line_num_width_px + params->catchall_margin_width_px + params->priority_margin_width_px; line_extras_off[line_idx] = Max(line_text_dim, params->font_size*30); } } ////////////////////////////// //- rjf: produce per-line extra annotation containers // UI_Box **line_extras_boxes = push_array(scratch.arena, UI_Box *, dim_1s64(params->line_num_range)+1); UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) UI_Parent(text_container_box) UI_Focus(UI_FocusKind_Off) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num < params->line_num_range.max; line_num += 1, line_idx += 1) { ui_set_next_fixed_x(line_extras_off[line_idx]); ui_set_next_fixed_y(line_idx*params->line_height_px); line_extras_boxes[line_idx] = ui_build_box_from_stringf(0, "###extras_%I64x", line_idx); } } ////////////////////////////// //- rjf: build watch pin annotations // UI_Focus(UI_FocusKind_Off) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num < params->line_num_range.max; line_num += 1, line_idx += 1) { CFG_NodePtrList immediate_pins = {0}; String8 line_text = params->line_text[line_idx]; for(U64 off = 0, next_off = line_text.size; off < line_text.size; off = next_off) { // rjf: find next opener String8 markup_opener = str8_lit("raddbg_pin("); next_off = str8_find_needle(line_text, off, markup_opener, 0); next_off += markup_opener.size; // rjf: extract contents of markup String8 contents = {0}; S32 nest = 1; for(U64 off2 = next_off; off2 < line_text.size; off2 += 1) { if(line_text.str[off2] == '(') { nest += 1; } else if(line_text.str[off2] == ')') { nest -= 1; if(nest == 0) { contents = str8_substr(line_text, r1u64(next_off, off2)); break; } } } // rjf: gather arguments String8List args = {0}; { S32 nest = 0; U64 arg_start_off = 0; for(U64 contents_off = 0; contents_off <= contents.size; contents_off += 1) { if(nest == 0 && (contents_off == contents.size || contents.str[contents_off] == ',')) { String8 arg = str8_substr(contents, r1u64(arg_start_off, contents_off)); arg = str8_skip_chop_whitespace(arg); str8_list_push(scratch.arena, &args, arg); arg_start_off = contents_off+1; } if(contents_off < contents.size) { if(contents.str[contents_off] == '(') { nest += 1; } else if(contents.str[contents_off] == ')') { nest -= 1; } } } } // rjf: extract fixed arguments String8 expr_string = {0}; if(args.first != 0) { expr_string = args.first->string; } // rjf: build immediate pin for this markup if(expr_string.size != 0) { CFG_Node *immediate_root = rd_immediate_cfg_from_keyf("markup_pin_%I64x_%I64x", line_num, off); CFG_Node *pin = cfg_node_child_from_string_or_alloc(rd_state->cfg, immediate_root, str8_lit("watch_pin")); CFG_Node *expr = cfg_node_child_from_string_or_alloc(rd_state->cfg, pin, str8_lit("expression")); cfg_node_new_replace(rd_state->cfg, expr, expr_string); cfg_node_ptr_list_push(scratch.arena, &immediate_pins, pin); } } CFG_NodePtrList pin_lists[] = { params->line_pins[line_idx], immediate_pins, }; E_ParentKey(e_key_zero()) for EachElement(list_idx, pin_lists) { CFG_NodePtrList pins = pin_lists[list_idx]; if(pins.count != 0) UI_Parent(line_extras_boxes[line_idx]) RD_Font(RD_FontSlot_Code) UI_FontSize(params->font_size) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) { for(CFG_NodePtrNode *n = pins.first; n != 0; n = n->next) { CFG_Node *pin = n->v; String8 pin_expr = rd_expr_from_cfg(pin); E_Eval eval = e_eval_from_string(pin_expr); String8 eval_string = {0}; if(!e_type_key_match(e_type_key_zero(), eval.irtree.type_key)) { EV_StringParams string_params = {.flags = EV_StringFlag_ReadOnlyDisplayRules, .radix = 10}; eval_string = rd_value_string_from_eval(scratch.arena, str8_zero(), &string_params, params->font, params->font_size, params->font_size*60.f, eval); } ui_spacer(ui_em(1.5f, 1.f)); ui_set_next_pref_width(ui_children_sum(1)); UI_Key pin_box_key = ui_key_from_stringf(ui_key_zero(), "###pin_%p", pin); UI_Box *pin_box = ui_build_box_from_key(UI_BoxFlag_AnimatePos| UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder, pin_box_key); UI_Parent(pin_box) UI_PrefWidth(ui_text_dim(10, 1)) { Vec4F32 pin_color = rd_color_from_cfg(pin); if(pin_color.w == 0) { pin_color = ui_color_from_name(str8_lit("text")); } Vec4F32 default_code_color = ui_color_from_name(str8_lit("code_default")); rd_code_label(0.8f, 1, default_code_color, pin_expr); rd_code_label(0.6f, 1, default_code_color, eval_string); } UI_Signal pin_sig = ui_signal_from_box(pin_box); if(ui_key_match(pin_box_key, ui_hot_key())) { rd_set_hover_eval(v2f32(pin_box->rect.x0, pin_box->rect.y1-2.f), pin_expr); } } } } } } ////////////////////////////// //- rjf: interact with margin box & text box // B32 search_query_invalidated = 0; UI_Signal priority_margin_container_sig = ui_signal_from_box(priority_margin_container_box); UI_Signal catchall_margin_container_sig = ui_signal_from_box(catchall_margin_container_box); UI_Signal text_container_sig = ui_signal_from_box(text_container_box); { //- rjf: determine mouse drag range TxtRng mouse_drag_rng = txt_rng(mouse_pt, mouse_pt); if(text_container_sig.f & UI_SignalFlag_LeftTripleDragging) { mouse_drag_rng = mouse_line_rng; } else if(text_container_sig.f & UI_SignalFlag_LeftDoubleDragging) { mouse_drag_rng = mouse_token_rng; } //- rjf: clicking/dragging over the text container if(!ctrlified && ui_dragging(text_container_sig)) { if(mouse_pt.line == 0) { mouse_pt.column = 1; if(ui_mouse().y <= top_container_box->rect.y0) { mouse_pt.line = params->line_num_range.min - 2; } else if(ui_mouse().y >= top_container_box->rect.y1) { mouse_pt.line = params->line_num_range.max + 2; } } if(ui_pressed(text_container_sig)) { *cursor = mouse_drag_rng.max; *mark = mouse_drag_rng.min; } if(txt_pt_less_than(mouse_pt, *mark)) { *cursor = mouse_drag_rng.min; } else { *cursor = mouse_drag_rng.max; } *preferred_column = cursor->column; } //- rjf: dragging will invalidate the search string, so we don't want to draw it while dragging/releasing if(ui_dragging(text_container_sig) || ui_released(text_container_sig)) { search_query_invalidated = 1; } //- rjf: right-click => code context menu if(ui_right_clicked(text_container_sig)) { if(txt_pt_match(*cursor, *mark)) { *cursor = *mark = mouse_pt; } U64 vaddr = 0; D_LineList lines = {0}; if(params->line_num_range.min <= cursor->line && cursor->line < params->line_num_range.max) { vaddr = params->line_vaddrs[cursor->line - params->line_num_range.min]; lines = params->line_infos[cursor->line - params->line_num_range.min]; } rd_cmd(RD_CmdKind_FocusPanel); rd_cmd(RD_CmdKind_PushQuery, .expr = txt_pt_match(*cursor, *mark) ? str8_lit("query:text_pt_commands") : str8_lit("query:text_range_commands"), .do_implicit_root = 1, .do_lister = 1, .ui_key = ui_get_selected_state()->root->key, .off_px = ui_mouse(), .cursor = *cursor, .mark = *mark, .vaddr = vaddr, .lines = lines); } //- rjf: drop target is dropped -> process if(drop_can_hit_lines && ui_key_match(ui_drop_hot_key(), drop_site_key) && rd_drag_drop()) { if(rd_state->drag_drop_regs_slot == RD_RegSlot_Expr) { S64 line_num = mouse_pt.line; U64 line_idx = line_num - params->line_num_range.min; U64 line_vaddr = params->line_vaddrs[line_idx]; rd_cmd(RD_CmdKind_AddWatchPin, .expr = rd_state->drag_drop_regs->expr, .file_path = line_vaddr == 0 ? rd_regs()->file_path : str8_zero(), .cursor = line_vaddr == 0 ? txt_pt(line_num, 1) : txt_pt(0, 0), .vaddr = line_vaddr); } if(rd_state->drag_drop_regs_slot == RD_RegSlot_Cfg && drop_cfg != &cfg_nil_node) { S64 line_num = mouse_pt.line; U64 line_idx = line_num - params->line_num_range.min; U64 line_vaddr = params->line_vaddrs[line_idx]; rd_cmd(RD_CmdKind_RelocateCfg, .cfg = drop_cfg->id, .file_path = line_vaddr == 0 ? rd_regs()->file_path : str8_zero(), .cursor = line_vaddr == 0 ? txt_pt(line_num, 1) : txt_pt(0, 0), .vaddr = line_vaddr); } if(drop_thread != &ctrl_entity_nil) { S64 line_num = mouse_pt.line; U64 line_idx = line_num - params->line_num_range.min; U64 line_vaddr = params->line_vaddrs[line_idx]; CTRL_Entity *thread = drop_thread; U64 new_rip_vaddr = line_vaddr; if(params->line_vaddrs[line_idx] == 0) { D_LineList *lines = ¶ms->line_infos[line_idx]; for(D_LineNode *n = lines->first; n != 0; n = n->next) { CTRL_EntityList modules = ctrl_modules_from_dbgi_key(scratch.arena, &d_state->ctrl_entity_store->ctx, n->v.dbgi_key); CTRL_Entity *module = ctrl_module_from_thread_candidates(&d_state->ctrl_entity_store->ctx, thread, &modules); if(module != &ctrl_entity_nil) { new_rip_vaddr = ctrl_vaddr_from_voff(module, n->v.voff_range.min); break; } } } rd_cmd(RD_CmdKind_SetThreadIP, .thread = thread->handle, .vaddr = new_rip_vaddr); } } //- rjf: commit text container signal to main output result.base = text_container_sig; } ////////////////////////////// //- rjf: cursor -> scope info // TXT_ScopeNode *cursor_scope_node = &txt_scope_node_nil; if(params->text_info != 0) { cursor_scope_node = txt_scope_node_from_info_pt(params->text_info, rd_regs()->cursor); } ////////////////////////////// //- rjf: produce fancy strings for each line // DR_FStrList *lines_fstrs = push_array(scratch.arena, DR_FStrList, dim_1s64(params->line_num_range)+1); { DR_FStrParams fstr_params = { params->font, rd_raster_flags_from_slot(RD_FontSlot_Code), rd_rgba_from_code_color_slot(RD_CodeColorSlot_CodeDefault), params->font_size, }; U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { String8 line_string = params->line_text[line_idx]; Rng1U64 line_range = params->line_ranges[line_idx]; TXT_TokenArray *line_tokens = ¶ms->line_tokens[line_idx]; DR_FStrList fstrs = {0}; if(line_tokens->count == 0) { dr_fstrs_push_new(scratch.arena, &fstrs, &fstr_params, line_string); } else { TXT_Token *line_tokens_first = line_tokens->v; TXT_Token *line_tokens_opl = line_tokens->v + line_tokens->count; for(TXT_Token *token = line_tokens_first; token < line_tokens_opl; token += 1) { // rjf: token -> token string String8 token_string = {0}; { Rng1U64 token_range = r1u64(0, line_string.size); if(token->range.min > line_range.min) { token_range.min += token->range.min-line_range.min; } if(token->range.max < line_range.max) { token_range.max = token->range.max-line_range.min; } token_string = str8_substr(line_string, token_range); } // rjf: token -> token color RD_CodeColorSlot token_color_slot = rd_code_color_slot_from_txt_token_kind(token->kind); RD_CodeColorSlot lookup_color_slot = rd_code_color_slot_from_txt_token_kind_lookup_string(token->kind, token_string); Vec4F32 token_color = rd_rgba_from_code_color_slot(token_color_slot); if(lookup_color_slot != RD_CodeColorSlot_CodeDefault) { Vec4F32 lookup_color = rd_rgba_from_code_color_slot(lookup_color_slot); F32 lookup_color_mix_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "%S_lookup", token_string), 1.f); token_color = mix_4f32(token_color, lookup_color, lookup_color_mix_t); } // rjf: scope endpoints enclosing cursor -> highlight for(TXT_ScopeNode *scope_n = cursor_scope_node; scope_n != &txt_scope_node_nil; scope_n = txt_scope_node_from_info_num(params->text_info, scope_n->parent_num)) { if(params->text_info->tokens.v[scope_n->token_idx_range.min].range.min == token->range.min || params->text_info->tokens.v[scope_n->token_idx_range.max].range.min == token->range.min) { token_color = highlight_color; break; } } // rjf: push fancy string dr_fstrs_push_new(scratch.arena, &fstrs, &fstr_params, token_string, .color = token_color); } } lines_fstrs[line_idx] = fstrs; } } ////////////////////////////// //- rjf: equip cursor scope rendering info // if(do_scope_lines && cursor_scope_node != &txt_scope_node_nil) { F32 scope_line_thickness = params->font_size*0.1f; scope_line_thickness = Max(scope_line_thickness, 1.f); DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) { Vec2F32 text_base_pos = v2f32(text_container_box->rect.x0 + params->line_num_width_px + line_num_padding_px, text_container_box->rect.y0); F32 ancestor_chain_depth = 0; for(TXT_ScopeNode *scope_n = cursor_scope_node; scope_n != &txt_scope_node_nil; scope_n = txt_scope_node_from_info_num(params->text_info, scope_n->parent_num), ancestor_chain_depth += 1) { Vec4F32 scope_line_color = highlight_color; F32 scope_line_color_target = highlight_color.w; scope_line_color_target *= 1 - ancestor_chain_depth / 6.f; scope_line_color_target = Max(0.2f, scope_line_color_target); F32 scope_line_color_t = ui_anim(ui_key_from_stringf(text_container_box->key, "###scope_depth_%I64x_%I64x", scope_n->token_idx_range.min, scope_n->token_idx_range.max), scope_line_color_target, .rate = rd_state->menu_animation_rate__slow); scope_line_color.w = scope_line_color_t*0.5f; Rng1U64 token_idx_range = scope_n->token_idx_range; Rng1U64 off_range = r1u64(params->text_info->tokens.v[token_idx_range.min].range.min, params->text_info->tokens.v[token_idx_range.max].range.min); TxtRng txt_range = txt_rng(txt_pt_from_info_off__linear_scan(params->text_info, off_range.min), txt_pt_from_info_off__linear_scan(params->text_info, off_range.max)); //- rjf: single-line scopes (underline) if(txt_range.min.line == txt_range.max.line && contains_1s64(params->line_num_range, txt_range.min.line)) { S64 line_num = txt_range.min.line; U64 line_idx = (U64)(line_num - params->line_num_range.min); String8 line_string = params->line_text[line_idx]; Rng1U64 line_off_range = r1u64(off_range.min - params->line_ranges[line_idx].min, off_range.max+1 - params->line_ranges[line_idx].min); Rng1F32 x_px_range = r1f32(fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_string, line_off_range.min)).x, fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_string, line_off_range.max)).x); F32 line_y = line_idx*params->line_height_px; Rng2F32 underline_rect = r2f32p(text_base_pos.x + x_px_range.min, text_base_pos.y + line_y + params->line_height_px*0.5f, text_base_pos.x + x_px_range.max+1, text_base_pos.y + line_y + params->line_height_px + params->font_size*0.1f); F32 midpoint = center_1f32(r1f32(underline_rect.x0, underline_rect.x1)); F32 t = ui_anim(ui_key_from_stringf(text_container_box->key, "###scope_%I64x_%I64x", scope_n->token_idx_range.min, scope_n->token_idx_range.max), 1.f, .rate = rd_state->catchall_animation_rate); Rng2F32 underline_clip = {0}; underline_clip.x0 = mix_1f32(midpoint, underline_rect.x0 - params->font_size, t); underline_clip.x1 = mix_1f32(midpoint, underline_rect.x1 + params->font_size, t); underline_clip.y0 = underline_rect.y0 + (underline_rect.y1 - underline_rect.y0) * 0.65f; underline_clip.y1 = 10000; DR_ClipScope(underline_clip) { dr_rect(underline_rect, scope_line_color, params->font_size*0.1f, scope_line_thickness, 1.f); } } //- rjf: cross-line scopes if(txt_range.min.line != txt_range.max.line && params->line_num_range.max > txt_range.min.line && params->line_num_range.min < txt_range.max.line) { String8 opener_line = txt_string_from_info_data_line_num(params->text_info, params->text_data, txt_range.min.line); String8 closer_line = txt_string_from_info_data_line_num(params->text_info, params->text_data, txt_range.max.line); String8 opener_line_pre_opener = str8_prefix(opener_line, txt_range.min.column-1); String8 closer_line_pre_closer = str8_prefix(closer_line, txt_range.max.column-1); F32 opener_line_pre_opener_px = fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, opener_line_pre_opener).x; F32 closer_line_pre_closer_px = fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, closer_line_pre_closer).x; F32 indent_depth_px = Min(opener_line_pre_opener_px, closer_line_pre_closer_px); Rng1F32 scope_range_y_px = r1f32(0, dim_2f32(text_container_box->rect).y); if(contains_1s64(params->line_num_range, txt_range.min.line)) { scope_range_y_px.min = (txt_range.min.line - params->line_num_range.min) * params->line_height_px; } if(contains_1s64(params->line_num_range, txt_range.max.line)) { scope_range_y_px.max = ((txt_range.max.line - params->line_num_range.min) + 1) * params->line_height_px; } F32 midpoint = center_1f32(scope_range_y_px); F32 t = ui_anim(ui_key_from_stringf(text_container_box->key, "###scope_%I64x_%I64x", scope_n->token_idx_range.min, scope_n->token_idx_range.max), 1.f, .rate = rd_state->catchall_animation_rate); Rng2F32 scope_rect = r2f32p(text_base_pos.x + indent_depth_px - params->font_size*0.2f, text_base_pos.y + scope_range_y_px.min, text_base_pos.x + indent_depth_px - params->font_size*0.2f + params->font_size*1.f, text_base_pos.y + scope_range_y_px.max); Rng2F32 scope_clip_rect = {0}; { scope_clip_rect.x0 = scope_rect.x0 - params->font_size*10.f; scope_clip_rect.x1 = scope_rect.x0 + (scope_rect.x1 - scope_rect.x0)*0.4f; scope_clip_rect.y0 = mix_1f32(midpoint, scope_rect.y0 - params->font_size*0.1f, t); scope_clip_rect.y1 = mix_1f32(midpoint, scope_rect.y1 + params->font_size*0.1f, t); } DR_ClipScope(scope_clip_rect) { dr_rect(scope_rect, scope_line_color, params->font_size*0.1f, scope_line_thickness, 1.f); } } } } ui_box_equip_draw_bucket(text_container_box, bucket); } ////////////////////////////// //- rjf: build exception annotations // UI_Focus(UI_FocusKind_Off) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num < params->line_num_range.max; line_num += 1, line_idx += 1) { CTRL_EntityList threads = params->line_ips[line_idx]; for(CTRL_EntityNode *n = threads.first; n != 0; n = n->next) { CTRL_Entity *thread = n->v; if(thread == stopper_thread && (stop_event.cause == CTRL_EventCause_InterruptedByException || stop_event.cause == CTRL_EventCause_InterruptedByTrap)) { DR_FStrList explanation_fstrs = rd_stop_explanation_fstrs_from_ctrl_event(scratch.arena, &stop_event); UI_Parent(line_extras_boxes[line_idx]) UI_PrefWidth(ui_text_dim(10, 1)) UI_TextAlignment(UI_TextAlign_Center) UI_PrefHeight(ui_px(params->line_height_px, 1.f)) UI_TagF("bad_pop") { UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "###exception_info"); ui_box_equip_display_fstrs(box, &explanation_fstrs); } } } } } ////////////////////////////// //- rjf: mouse -> expression range info // TxtRng mouse_expr_rng = {0}; Vec2F32 mouse_expr_baseline_pos = {0}; String8 mouse_expr = {0}; B32 mouse_expr_is_explicit = 0; if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line)) ProfScope("mouse -> expression range") { TxtRng selected_rng = txt_rng(*cursor, *mark); if(!txt_pt_match(*cursor, *mark) && cursor->line == mark->line && ((txt_pt_less_than(selected_rng.min, mouse_pt) || txt_pt_match(selected_rng.min, mouse_pt)) && txt_pt_less_than(mouse_pt, selected_rng.max))) { U64 line_slice_idx = mouse_pt.line-params->line_num_range.min; String8 line_text = params->line_text[line_slice_idx]; F32 expr_hoff_px = params->line_num_width_px + fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, selected_rng.min.column-1)).x; result.mouse_expr_rng = mouse_expr_rng = selected_rng; mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); mouse_expr = str8_substr(line_text, r1u64(selected_rng.min.column-1, selected_rng.max.column-1)); mouse_expr_is_explicit = 1; } else { U64 line_slice_idx = mouse_pt.line-params->line_num_range.min; String8 line_text = params->line_text[line_slice_idx]; TXT_TokenArray line_tokens = params->line_tokens[line_slice_idx]; Rng1U64 line_range = params->line_ranges[line_slice_idx]; U64 mouse_pt_off = line_range.min + (mouse_pt.column-1); Rng1U64 expr_off_rng = txt_expr_off_range_from_line_off_range_string_tokens(mouse_pt_off, line_range, line_text, &line_tokens); if(expr_off_rng.max != expr_off_rng.min) { F32 expr_hoff_px = params->line_num_width_px + fnt_dim_from_tag_size_string(params->font, params->font_size, 0, params->tab_size, str8_prefix(line_text, expr_off_rng.min-line_range.min)).x; result.mouse_expr_rng = mouse_expr_rng = txt_rng(txt_pt(mouse_pt.line, 1+(expr_off_rng.min-line_range.min)), txt_pt(mouse_pt.line, 1+(expr_off_rng.max-line_range.min))); mouse_expr_baseline_pos = v2f32(text_container_box->rect.x0+expr_hoff_px, text_container_box->rect.y0+line_slice_idx*params->line_height_px + params->line_height_px*0.85f); mouse_expr = str8_substr(line_text, r1u64(expr_off_rng.min-line_range.min, expr_off_rng.max-line_range.min)); } } } ////////////////////////////// //- rjf: mouse -> set global frontend hovered line info // if(ui_hovering(text_container_sig) && contains_1s64(params->line_num_range, mouse_pt.line) && (ui_mouse().x - text_container_box->rect.x0 < params->line_num_width_px + line_num_padding_px)) { U64 line_slice_idx = mouse_pt.line-params->line_num_range.min; D_LineList *lines = ¶ms->line_infos[line_slice_idx]; if(lines->first != 0 && (params->line_vaddrs[line_slice_idx] != 0 || lines->first->v.pt.line == mouse_pt.line)) { RD_RegsScope(.process = selected_thread_process->handle, .vaddr_range = ctrl_vaddr_range_from_voff_range(selected_thread_module, lines->first->v.voff_range), .module = selected_thread_module->handle, .dbgi_key = lines->first->v.dbgi_key, .voff_range = lines->first->v.voff_range) { rd_set_hover_regs(RD_RegSlot_Null); } } } ////////////////////////////// //- rjf: hover eval // if(!ui_dragging(text_container_sig) && text_container_sig.event_flags == 0 && mouse_expr.size != 0) { E_Eval eval = e_eval_from_string(mouse_expr); B32 eval_implicit_hover = (eval.irtree.mode != E_Mode_Null && eval.space.kind == CTRL_EvalSpaceKind_Entity); if(eval.msgs.max_kind == E_MsgKind_Null && (eval_implicit_hover || mouse_expr_is_explicit)) { U64 line_vaddr = 0; if(contains_1s64(params->line_num_range, mouse_pt.line)) { U64 line_idx = mouse_pt.line-params->line_num_range.min; line_vaddr = params->line_vaddrs[line_idx]; } rd_set_hover_eval(mouse_expr_baseline_pos, mouse_expr); } } ////////////////////////////// //- rjf: dragging/dropping which applies to lines over this slice -> visualize // if(drop_can_hit_lines && ui_key_match(drop_site_key, ui_drop_hot_key())) { DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) { Vec4F32 color = drop_color; color.w *= 0.2f; Rng2F32 drop_line_rect = r2f32p(top_container_box->rect.x0, top_container_box->rect.y0 + (mouse_pt.line - params->line_num_range.min) * params->line_height_px, top_container_box->rect.x1, top_container_box->rect.y0 + (mouse_pt.line - params->line_num_range.min + 1) * params->line_height_px); R_Rect2DInst *inst = dr_rect(drop_line_rect, color, 0, 0, 1.f); inst->colors[Corner_10] = inst->colors[Corner_11] = v4f32(color.x, color.y, color.z, 0); } ui_box_equip_draw_bucket(text_container_box, bucket); } ////////////////////////////// //- rjf: (cursor*mark*list(flash_range)) -> list(text_range*color) // typedef struct TxtRngColorPairNode TxtRngColorPairNode; struct TxtRngColorPairNode { TxtRngColorPairNode *next; TxtRng rng; Vec4F32 color; }; TxtRngColorPairNode *first_txt_rng_color_pair = 0; TxtRngColorPairNode *last_txt_rng_color_pair = 0; { // rjf: push initial for cursor/mark { TxtRngColorPairNode *n = push_array(scratch.arena, TxtRngColorPairNode, 1); n->rng = txt_rng(*cursor, *mark); n->color = ui_color_from_name(str8_lit("selection")); SLLQueuePush(first_txt_rng_color_pair, last_txt_rng_color_pair, n); } // rjf: push for ctrlified mouse expr if(ctrlified && !txt_pt_match(result.mouse_expr_rng.max, result.mouse_expr_rng.min)) UI_Tag(str8_lit("pop")) { TxtRngColorPairNode *n = push_array(scratch.arena, TxtRngColorPairNode, 1); n->rng = result.mouse_expr_rng; n->color = ui_color_from_name(str8_lit("background")); n->color.w *= 0.2f; SLLQueuePush(first_txt_rng_color_pair, last_txt_rng_color_pair, n); } } ////////////////////////////// //- rjf: build line numbers region (line number interaction should be basically identical to lines) // if(params->flags & RD_CodeSliceFlag_LineNums) UI_Parent(text_container_box) ProfScope("build line number interaction box") UI_Focus(UI_FocusKind_Off) { ui_set_next_pref_width(ui_px(params->line_num_width_px, 1.f)); ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); ui_build_box_from_key(0, ui_key_zero()); } ////////////////////////////// //- rjf: build line text // UI_Parent(text_container_box) ProfScope("build line text") UI_Focus(UI_FocusKind_Off) { RD_Regs *hover_regs = rd_get_hover_regs(); Rng1U64 hover_voff_range = hover_regs->voff_range; if(hover_voff_range.min == 0 && hover_voff_range.max == 0) { CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, hover_regs->module); hover_voff_range = ctrl_voff_range_from_vaddr_range(module, hover_regs->vaddr_range); } ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); UI_WidthFill UI_Column UI_PrefHeight(ui_px(params->line_height_px, 1.f)) RD_Font(RD_FontSlot_Code) UI_FontSize(params->font_size) UI_CornerRadius(0) { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { String8 line_string = params->line_text[line_idx]; Rng1U64 line_range = params->line_ranges[line_idx]; DR_FStrList line_fstrs = lines_fstrs[line_idx]; ui_set_next_text_padding(line_num_padding_px); UI_Key line_key = ui_key_from_stringf(top_container_box->key, "ln_%I64x", line_num); Vec4F32 line_bg_color = line_bg_colors[line_idx]; if(line_bg_color.w != 0) { ui_set_next_flags(UI_BoxFlag_DrawBackground); ui_set_next_background_color(line_bg_color); } ui_set_next_tab_size(params->tab_size); UI_Box *line_box = ui_build_box_from_key(UI_BoxFlag_DisableTextTrunc|UI_BoxFlag_DrawText|UI_BoxFlag_DisableIDString, line_key); DR_Bucket *line_bucket = dr_bucket_make(); dr_push_bucket(line_bucket); ui_box_equip_display_fstrs(line_box, &line_fstrs); // rjf: extra rendering for strings that are currently being searched for if(!search_query_invalidated && params->search_query.size != 0) { for(U64 needle_pos = 0; needle_pos < line_string.size;) { needle_pos = str8_find_needle(line_string, needle_pos, params->search_query, StringMatchFlag_CaseInsensitive); if(needle_pos < line_string.size) { Rng1U64 match_range = r1u64(needle_pos, needle_pos+params->search_query.size); Rng1F32 match_column_pixel_off_range = { fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, match_range.min)).x, fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, match_range.max)).x, }; Rng2F32 match_rect = { line_box->rect.x0+line_num_padding_px+match_column_pixel_off_range.min, line_box->rect.y0, line_box->rect.x0+line_num_padding_px+match_column_pixel_off_range.max+2.f, line_box->rect.y1, }; Vec4F32 color = pop_color; if(!is_focused) { color.w *= 0.5f; } color.w *= 0.2f; dr_rect(match_rect, color, 4.f, 0, 1.f); needle_pos += 1; } } } // rjf: extra rendering for list(text_range*color) { U64 prev_line_size = (line_idx > 0) ? params->line_text[line_idx-1].size : 0; U64 next_line_size = (line_idx+1 < dim_1s64(params->line_num_range)) ? params->line_text[line_idx+1].size : 0; for(TxtRngColorPairNode *n = first_txt_rng_color_pair; n != 0; n = n->next) { TxtRng select_range = n->rng; TxtRng line_range = txt_rng(txt_pt(line_num, 1), txt_pt(line_num, line_string.size+1)); TxtRng select_range_in_line = txt_rng_intersect(select_range, line_range); if(!txt_pt_match(select_range_in_line.min, select_range_in_line.max) && txt_pt_less_than(select_range_in_line.min, select_range_in_line.max)) { TxtRng prev_line_range = txt_rng(txt_pt(line_num-1, 1), txt_pt(line_num-1, prev_line_size+1)); TxtRng next_line_range = txt_rng(txt_pt(line_num+1, 1), txt_pt(line_num+1, next_line_size+1)); TxtRng select_range_in_prev_line = txt_rng_intersect(prev_line_range, select_range); TxtRng select_range_in_next_line = txt_rng_intersect(next_line_range, select_range); B32 prev_line_good = (!txt_pt_match(select_range_in_prev_line.min, select_range_in_prev_line.max) && txt_pt_less_than(select_range_in_prev_line.min, select_range_in_prev_line.max)); B32 next_line_good = (!txt_pt_match(select_range_in_next_line.min, select_range_in_next_line.max) && txt_pt_less_than(select_range_in_next_line.min, select_range_in_next_line.max)); Rng1S64 select_column_range_in_line = { (select_range.min.line == line_num) ? select_range.min.column : 1, (select_range.max.line == line_num) ? select_range.max.column : (S64)(line_string.size+1), }; Rng1F32 select_column_pixel_off_range = { fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, select_column_range_in_line.min-1)).x, fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, select_column_range_in_line.max-1)).x, }; Rng2F32 select_rect = { line_box->rect.x0+line_num_padding_px+select_column_pixel_off_range.min-2.f, floor_f32(line_box->rect.y0) - 1.f, line_box->rect.x0+line_num_padding_px+select_column_pixel_off_range.max+2.f, ceil_f32(line_box->rect.y1) + 1.f, }; Vec4F32 color = n->color; if(!is_focused) { color.w *= 0.5f; } F32 rounded_radius = params->font_size*0.4f; R_Rect2DInst *inst = dr_rect(select_rect, color, rounded_radius, 0, 1); inst->corner_radii[Corner_00] = !prev_line_good || select_range_in_prev_line.min.column > select_range_in_line.min.column ? rounded_radius : 0.f; inst->corner_radii[Corner_10] = (!prev_line_good || select_range_in_line.max.column > select_range_in_prev_line.max.column || select_range_in_line.max.column < select_range_in_prev_line.min.column) ? rounded_radius : 0.f; inst->corner_radii[Corner_01] = (!next_line_good || select_range_in_next_line.min.column > select_range_in_line.min.column || select_range_in_next_line.max.column < select_range_in_line.min.column) ? rounded_radius : 0.f; inst->corner_radii[Corner_11] = !next_line_good || select_range_in_line.max.column > select_range_in_next_line.max.column ? rounded_radius : 0.f; } } } // rjf: extra rendering for cursor position if(cursor->line == line_num) { S64 column = cursor->column; Vec2F32 advance = fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, column-1)); F32 cursor_y = line_box->rect.y0-params->font_size*0.125f; F32 cursor_y__animated = ui_anim(ui_key_from_stringf(text_container_box->key, "cursor_y_px"), cursor_y); F32 cursor_off_pixels = advance.x; F32 cursor_off_pixels__animated = ui_anim(ui_key_from_stringf(text_container_box->key, "cursor_off_px"), cursor_off_pixels); F32 cursor_thickness = ClampBot(1.f, floor_f32(line_box->font_size/10.f)); Rng2F32 cursor_rect = { ui_box_text_position(line_box).x+cursor_off_pixels, line_box->rect.y0-params->font_size*0.125f, ui_box_text_position(line_box).x+cursor_off_pixels+cursor_thickness, line_box->rect.y1+params->font_size*0.125f, }; Rng1F32 trail_off_span = r1f32(cursor_off_pixels__animated, cursor_off_pixels); Rng2F32 trail_rect = { ui_box_text_position(line_box).x+trail_off_span.min, line_box->rect.y0-params->font_size*0.125f, ui_box_text_position(line_box).x+trail_off_span.max, line_box->rect.y1+params->font_size*0.125f, }; Vec4F32 cursor_color = ui_color_from_name(str8_lit("cursor")); Vec4F32 trail_color = cursor_color; if(!is_focused) { cursor_color.w *= 0.5f; } trail_color.w *= 0.25f; dr_rect(cursor_rect, cursor_color, 1.f, 0, 0.f); if(do_cursor_trail) { R_Rect2DInst *trail_inst = dr_rect(trail_rect, trail_color, ui_top_font_size()*0.2f, 0, 1.f); trail_inst->shear = cursor_y - cursor_y__animated; if(cursor_off_pixels > cursor_off_pixels__animated) { trail_inst->dst = shift_2f32(trail_inst->dst, v2f32(0, -trail_inst->shear)); trail_inst->colors[Corner_00].w *= 0.1f; trail_inst->colors[Corner_01].w *= 0.1f; } else { trail_inst->shear *= -1; trail_inst->colors[Corner_10].w *= 0.1f; trail_inst->colors[Corner_11].w *= 0.1f; } } } // rjf: extra rendering for lines with line-info that match the hovered { B32 matches = 0; S64 line_info_line_num = 0; D_LineList *lines = ¶ms->line_infos[line_idx]; for(D_LineNode *n = lines->first; n != 0; n = n->next) { if((n->v.pt.line == line_num || params->line_vaddrs[line_idx] != 0) && ((di_key_match(n->v.dbgi_key, hover_regs->dbgi_key) && n->v.voff_range.min <= hover_voff_range.min && hover_voff_range.min < n->v.voff_range.max) || (params->line_vaddrs[line_idx] == hover_regs->vaddr_range.min && hover_regs->vaddr_range.min != 0))) { matches = 1; line_info_line_num = n->v.pt.line; break; } } // rjf: matches => highlight background if(matches) { Vec4F32 highlight_color = code_line_bgs[line_info_line_num % ArrayCount(code_line_bgs)]; highlight_color.w *= 0.2f; dr_rect(line_box->rect, highlight_color, 0, 0, 0); } } // rjf: equip bucket if(line_bucket->passes.count != 0) { ui_box_equip_draw_bucket(line_box, line_bucket); } dr_pop_bucket(); } } } scratch_end(scratch); ProfEnd(); return result; } internal RD_CodeSliceSignal rd_code_slicef(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); RD_CodeSliceSignal sig = rd_code_slice(params, cursor, mark, preferred_column, string); va_end(args); scratch_end(scratch); return sig; } internal B32 rd_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column) { Temp scratch = scratch_begin(0, 0); B32 change = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind != UI_EventKind_Navigate && evt->kind != UI_EventKind_Edit) { continue; } B32 taken = 0; String8 line = txt_string_from_info_data_line_num(info, data, cursor->line); UI_TxtOp single_line_op = ui_single_line_txt_op_from_event(scratch.arena, evt, line, *cursor, *mark); //- rjf: invalid single-line op or endpoint units => try multiline if(evt->delta_unit == UI_EventDeltaUnit_Whole || single_line_op.flags & UI_TxtOpFlag_Invalid) { U64 line_count = info->lines_count; String8 prev_line = txt_string_from_info_data_line_num(info, data, cursor->line-1); String8 next_line = txt_string_from_info_data_line_num(info, data, cursor->line+1); Vec2S32 delta = evt->delta_2s32; //- rjf: wrap lines right if(evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x > 0 && cursor->column == line.size+1 && cursor->line+1 <= line_count) { cursor->line += 1; cursor->column = 1; *preferred_column = 1; change = 1; taken = 1; } //- rjf: wrap lines left if(evt->delta_unit != UI_EventDeltaUnit_Whole && delta.x < 0 && cursor->column == 1 && cursor->line-1 >= 1) { cursor->line -= 1; cursor->column = prev_line.size+1; *preferred_column = prev_line.size+1; change = 1; taken = 1; } //- rjf: movement down (plain) if(evt->delta_unit == UI_EventDeltaUnit_Char && delta.y > 0 && cursor->line+1 <= line_count) { cursor->line += 1; cursor->column = Min(*preferred_column, next_line.size+1); change = 1; taken = 1; } //- rjf: movement up (plain) if(evt->delta_unit == UI_EventDeltaUnit_Char && delta.y < 0 && cursor->line-1 >= 1) { cursor->line -= 1; cursor->column = Min(*preferred_column, prev_line.size+1); change = 1; taken = 1; } //- rjf: movement down (chunk) if(evt->delta_unit == UI_EventDeltaUnit_Word && delta.y > 0 && cursor->line+1 <= line_count) { for(S64 line_num = cursor->line+1; line_num <= line_count; line_num += 1) { String8 line = txt_string_from_info_data_line_num(info, data, line_num); U64 line_size = line.size; if(line_size == 0) { cursor->line = line_num; cursor->column = 1; break; } else if(line_num == line_count) { cursor->line = line_num; cursor->column = line_size+1; } } change = 1; taken = 1; } //- rjf: movement up (chunk) if(evt->delta_unit == UI_EventDeltaUnit_Word && delta.y < 0 && cursor->line-1 >= 1) { for(S64 line_num = cursor->line-1; line_num > 0; line_num -= 1) { String8 line = txt_string_from_info_data_line_num(info, data, line_num); U64 line_size = line.size; if(line_size == 0) { cursor->line = line_num; cursor->column = 1; break; } else if(line_num == 1) { cursor->line = line_num; cursor->column = 1; } } change = 1; taken = 1; } //- rjf: movement down (page) if(evt->delta_unit == UI_EventDeltaUnit_Page && delta.y > 0) { cursor->line += line_count_per_page; cursor->column = 1; cursor->line = Clamp(1, cursor->line, line_count); change = 1; taken = 1; } //- rjf: movement up (page) if(evt->delta_unit == UI_EventDeltaUnit_Page && delta.y < 0) { cursor->line -= line_count_per_page; cursor->column = 1; cursor->line = Clamp(1, cursor->line, line_count); change = 1; taken = 1; } //- rjf: movement to endpoint (+) if(evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y > 0 || delta.x > 0)) { *cursor = txt_pt(line_count, info->lines_count ? dim_1u64(info->lines_ranges[info->lines_count-1])+1 : 1); change = 1; taken = 1; } //- rjf: movement to endpoint (-) if(evt->delta_unit == UI_EventDeltaUnit_Whole && (delta.y < 0 || delta.x < 0)) { *cursor = txt_pt(1, 1); change = 1; taken = 1; } //- rjf: stick mark to cursor, when we don't want to keep it in the same spot if(!(evt->flags & UI_EventFlag_KeepMark)) { *mark = *cursor; } } //- rjf: valid single-line op => do single-line op else { *cursor = single_line_op.cursor; *mark = single_line_op.mark; *preferred_column = cursor->column; change = 1; taken = 1; } //- rjf: copy if(evt->flags & UI_EventFlag_Copy) { String8 text = txt_string_from_info_data_txt_rng(info, data, txt_rng(*cursor, *mark)); os_set_clipboard_text(text); taken = 1; } //- rjf: consume if(taken) { ui_eat_event(evt); } } scratch_end(scratch); return change; } //////////////////////////////// //~ rjf: UI Widgets: Fancy Labels internal DR_FStrList rd_fstrs_from_rich_string(Arena *arena, String8 string) { Temp scratch = scratch_begin(&arena, 1); typedef U32 StringPartFlags; enum { StringPartFlag_Code = (1<<0), StringPartFlag_Underline = (1<<1), StringPartFlag_Bright = (1<<2), }; typedef struct StringPart StringPart; struct StringPart { StringPart *next; StringPartFlags flags; String8 string; }; StringPart *first_part = 0; StringPart *last_part = 0; U64 active_part_start_idx = 0; StringPartFlags active_part_flags = 0; for(U64 idx = 0; idx <= string.size; idx += 1) { if(idx == string.size) { StringPart *p = push_array(scratch.arena, StringPart, 1); p->flags = active_part_flags; p->string = str8_substr(string, r1u64(active_part_start_idx, idx)); SLLQueuePush(first_part, last_part, p); } else if(string.str[idx] == '`') { StringPart *p = push_array(scratch.arena, StringPart, 1); p->flags = active_part_flags; p->string = str8_substr(string, r1u64(active_part_start_idx, idx)); SLLQueuePush(first_part, last_part, p); active_part_start_idx = idx+1; active_part_flags ^= StringPartFlag_Code; } } DR_FStrList fstrs = {0}; for(StringPart *p = first_part; p != 0; p = p->next) { DR_FStr fstr = {0}; { fstr.string = p->string; fstr.params.font = ui_top_font(); fstr.params.color = ui_color_from_name(str8_lit("text")); fstr.params.size = ui_top_font_size(); fstr.params.raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main); if(p->flags & StringPartFlag_Code) { fstr.params.font = rd_font_from_slot(RD_FontSlot_Code); fstr.params.raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Code); fstr.params.color = rd_rgba_from_code_color_slot(RD_CodeColorSlot_CodeDefault); } } dr_fstrs_push(arena, &fstrs, &fstr); } scratch_end(scratch); return fstrs; } internal UI_Signal rd_label(String8 string) { Temp scratch = scratch_begin(0, 0); DR_FStrList fstrs = rd_fstrs_from_rich_string(scratch.arena, string); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); UI_Signal sig = ui_signal_from_box(box); scratch_end(scratch); return sig; } internal UI_Signal rd_error_label(String8 string) { UI_Box *box = ui_build_box_from_key(0, ui_key_zero()); UI_Signal sig = ui_signal_from_box(box); UI_Parent(box) { ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_text_alignment(UI_TextAlign_Center); UI_TagF("weak") UI_PrefWidth(ui_em(2.25f, 1.f)) ui_label(rd_icon_kind_text_table[RD_IconKind_WarningBig]); UI_PrefWidth(ui_text_dim(10, 0)) rd_label(string); } return sig; } internal B32 rd_help_label(String8 string) { B32 result = 0; UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%S_help_label", string); UI_Signal sig = ui_signal_from_box(box); UI_Parent(box) { UI_PrefWidth(ui_pct(1, 0)) ui_label(string); if(ui_hovering(sig)) UI_PrefWidth(ui_em(2.25f, 1)) { result = 1; ui_set_next_font(rd_font_from_slot(RD_FontSlot_Icons)); ui_set_next_text_raster_flags(FNT_RasterFlag_Smooth); ui_set_next_text_alignment(UI_TextAlign_Center); UI_Box *help_hoverer = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawHotEffects, "###help_hoverer_%S", string); ui_box_equip_display_string(help_hoverer, rd_icon_kind_text_table[RD_IconKind_QuestionMark]); if(!contains_2f32(help_hoverer->rect, ui_mouse())) { result = 0; } } } return result; } internal DR_FStrList rd_fstrs_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); DR_FStrList fstrs = {0}; TXT_TokenArray tokens = txt_token_array_from_string__c_cpp(scratch.arena, 0, string); TXT_Token *tokens_opl = tokens.v+tokens.count; S32 indirection_counter = 0; indirection_size_change = 0; for(TXT_Token *token = tokens.v; token < tokens_opl; token += 1) { RD_CodeColorSlot token_color_slot = rd_code_color_slot_from_txt_token_kind(token->kind); Vec4F32 token_color_rgba = rd_rgba_from_code_color_slot(token_color_slot); token_color_rgba.w *= alpha; String8 token_string = str8_substr(string, token->range); if(str8_match(token_string, str8_lit("{"), 0)) { indirection_counter += 1; } if(str8_match(token_string, str8_lit("["), 0)) { indirection_counter += 1; } indirection_counter = ClampBot(0, indirection_counter); switch(token->kind) { default: { DR_FStr fstr = { token_string, { ui_top_font(), ui_top_text_raster_flags(), token_color_rgba, ui_top_font_size() * (1.f - !!indirection_size_change*(indirection_counter/10.f)), } }; dr_fstrs_push(arena, &fstrs, &fstr); }break; case TXT_TokenKind_Identifier: case TXT_TokenKind_Keyword: { RD_CodeColorSlot lookup_theme_color_slot = rd_code_color_slot_from_txt_token_kind_lookup_string(token->kind, token_string); if(lookup_theme_color_slot != RD_CodeColorSlot_CodeDefault) { Vec4F32 lookup_color = rd_rgba_from_code_color_slot(lookup_theme_color_slot); F32 lookup_color_mix_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "%S_lookup", token_string), 1.f); token_color_rgba = mix_4f32(token_color_rgba, lookup_color, lookup_color_mix_t); } DR_FStr fstr = { token_string, { ui_top_font(), ui_top_text_raster_flags(), token_color_rgba, ui_top_font_size() * (1.f - !!indirection_size_change*(indirection_counter/10.f)), }, }; dr_fstrs_push(arena, &fstrs, &fstr); }break; case TXT_TokenKind_Numeric: { Vec4F32 token_color_rgba_alt = rd_rgba_from_code_color_slot(RD_CodeColorSlot_CodeNumericAltDigitGroup); token_color_rgba_alt.w *= alpha; F32 font_size = ui_top_font_size() * (1.f - !!indirection_size_change*(indirection_counter/10.f)); // rjf: unpack string U32 base = 10; U64 prefix_skip = 0; U64 digit_group_size = 3; if(str8_match(str8_prefix(token_string, 2), str8_lit("0x"), StringMatchFlag_CaseInsensitive)) { base = 16; prefix_skip = 2; digit_group_size = 4; } else if(str8_match(str8_prefix(token_string, 2), str8_lit("0b"), StringMatchFlag_CaseInsensitive)) { base = 2; prefix_skip = 2; digit_group_size = 8; } else if(str8_match(str8_prefix(token_string, 2), str8_lit("0o"), StringMatchFlag_CaseInsensitive)) { base = 8; prefix_skip = 2; digit_group_size = 2; } // rjf: grab string parts U64 dot_pos = str8_find_needle(token_string, 0, str8_lit("."), 0); String8 prefix = str8_prefix(token_string, prefix_skip); String8 whole = str8_substr(token_string, r1u64(prefix_skip, dot_pos)); String8 decimal = str8_skip(token_string, dot_pos); // rjf: determine # of digits U64 num_digits = 0; for(U64 idx = 0; idx < whole.size; idx += 1) { num_digits += char_is_digit(whole.str[idx], base); } // rjf: push prefix { DR_FStr fstr = { prefix, { ui_top_font(), ui_top_text_raster_flags(), token_color_rgba, font_size, }, }; dr_fstrs_push(arena, &fstrs, &fstr); } // rjf: push digit groups { B32 odd = 0; U64 start_idx = 0; U64 num_digits_passed = digit_group_size - num_digits%digit_group_size; for(U64 idx = 0; idx <= whole.size; idx += 1) { U8 byte = idx < whole.size ? whole.str[idx] : 0; if(num_digits_passed >= digit_group_size || idx == whole.size) { num_digits_passed = 0; if(start_idx < idx) { DR_FStr fstr = { str8_substr(whole, r1u64(start_idx, idx)), { ui_top_font(), ui_top_text_raster_flags(), odd ? token_color_rgba_alt : token_color_rgba, font_size, }, }; dr_fstrs_push(arena, &fstrs, &fstr); start_idx = idx; odd ^= 1; } } if(char_is_digit(byte, base)) { num_digits_passed += 1; } } } // rjf: push decimal { DR_FStr fstr = { decimal, { ui_top_font(), ui_top_text_raster_flags(), token_color_rgba, font_size, }, }; dr_fstrs_push(arena, &fstrs, &fstr); } }break; } if(str8_match(token_string, str8_lit("}"), 0)) { indirection_counter -= 1; } if(str8_match(token_string, str8_lit("]"), 0)) { indirection_counter -= 1; } indirection_counter = ClampBot(0, indirection_counter); } scratch_end(scratch); ProfEnd(); return fstrs; } internal UI_Box * rd_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string) { Temp scratch = scratch_begin(0, 0); DR_FStrList fstrs = rd_fstrs_from_code_string(scratch.arena, alpha, indirection_size_change, base_color, string); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); scratch_end(scratch); return box; } //////////////////////////////// //~ rjf: UI Widgets: Line Edit internal UI_Signal rd_cell(RD_CellParams *params, String8 string) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); B32 do_cursor_trail = rd_setting_b32_from_name(str8_lit("cursor_trail")); ////////////////////////////// //- rjf: unpack visual metrics // F32 expander_size_px = floor_f32(ui_top_font_size()*2.f); ////////////////////////////// //- rjf: make key // UI_Key key = ui_key_from_string(ui_active_seed_key(), string); ////////////////////////////// //- rjf: calculate & push focus // B32 is_auto_focus_hot = ui_is_key_auto_focus_hot(key); B32 is_auto_focus_active = ui_is_key_auto_focus_active(key); if(is_auto_focus_hot) { ui_push_focus_hot(UI_FocusKind_On); } if(is_auto_focus_active) { ui_push_focus_active(UI_FocusKind_On); } B32 is_focus_hot = ui_is_focus_hot(); B32 is_focus_active = ui_is_focus_active(); B32 is_focus_hot_disabled = (!is_focus_hot && ui_top_focus_hot() == UI_FocusKind_On); B32 is_focus_active_disabled = (!is_focus_active && ui_top_focus_active() == UI_FocusKind_On); ////////////////////////////// //- rjf: determine which sub-cell components we'll build // // (the base line edit textual label / editor is always built, but this can be enriched // with extra widgets & metadata) // B32 build_toggle_switch = !!(params->flags & RD_CellFlag_ToggleSwitch) && !is_focus_active; B32 build_slider = !!(params->flags & RD_CellFlag_Slider) && !is_focus_active; B32 build_bindings = !!(params->flags & RD_CellFlag_Bindings) && !is_focus_active; B32 build_lhs_name_desc = (params->meta_fstrs.node_count != 0 || params->description.size != 0); B32 build_line_edit = (params->pre_edit_value.size != 0 || params->value_fstrs.node_count != 0); B32 build_note = (params->note_fstrs.node_count != 0 && !is_focus_active); DR_FStrList lhs_name_fstrs = params->meta_fstrs; DR_FStrList value_name_fstrs = params->value_fstrs; DR_FStrList note_fstrs = params->note_fstrs; ////////////////////////////// //- rjf: determine autocompletion string // String8 autocomplete_hint_string = {0}; if(is_focus_active) { autocomplete_hint_string = ui_autocomplete_string(); } ////////////////////////////// //- rjf: build top-level box // if(is_focus_active || is_focus_active_disabled) { ui_set_next_hover_cursor(OS_Cursor_IBar); } UI_Box *box = ui_build_box_from_key(UI_BoxFlag_MouseClickable| (!!build_lhs_name_desc*UI_BoxFlag_DisableFocusBorder)| (!!(params->flags & RD_CellFlag_KeyboardClickable)*UI_BoxFlag_KeyboardClickable)| UI_BoxFlag_ClickToFocus| (!!(params->flags & RD_CellFlag_Button)*UI_BoxFlag_DrawHotEffects)| (!!(params->flags & RD_CellFlag_SingleClickActivate)*UI_BoxFlag_DrawActiveEffects)| (!(params->flags & RD_CellFlag_NoBackground)*UI_BoxFlag_DrawBackground)| (!!(params->flags & RD_CellFlag_Border)*UI_BoxFlag_DrawBorder)| ((is_auto_focus_hot || is_auto_focus_active)*UI_BoxFlag_KeyboardClickable)| (is_focus_active || is_focus_active_disabled)*(UI_BoxFlag_Clip), key); ////////////////////////////// //- rjf: build indent // UI_Parent(box) for(S32 idx = 0; idx < params->depth; idx += 1) { ui_set_next_flags(UI_BoxFlag_DrawSideLeft); ui_spacer(ui_em(1.f, 1.f)); } ////////////////////////////// //- rjf: build expander (or placeholder, or space) // { //- rjf: build expander if(params->flags & RD_CellFlag_Expander) UI_PrefWidth(ui_px(expander_size_px, 1.f)) UI_Parent(box) UI_Flags(UI_BoxFlag_DrawSideLeft) UI_Focus(UI_FocusKind_Off) { UI_Signal expander_sig = ui_expanderf(params->expanded_out[0], "expander"); if(ui_pressed(expander_sig)) { params->expanded_out[0] ^= 1; } } //- rjf: build expander placeholder else if(params->flags & RD_CellFlag_ExpanderPlaceholder) UI_Parent(box) UI_PrefWidth(ui_px(expander_size_px, 1.f)) UI_Focus(UI_FocusKind_Off) { UI_TagF("weak") UI_Flags(UI_BoxFlag_DrawSideLeft) RD_Font(RD_FontSlot_Icons) UI_TextAlignment(UI_TextAlign_Center) ui_label(rd_icon_kind_text_table[RD_IconKind_Dot]); } //- rjf: build expander space else if(params->flags & RD_CellFlag_ExpanderSpace) UI_Parent(box) UI_Focus(UI_FocusKind_Off) { UI_Flags(UI_BoxFlag_DrawSideLeft) ui_spacer(ui_px(expander_size_px, 1.f)); } } ////////////////////////////// //- rjf: build left-hand-side container box // UI_Box *lhs_box = &ui_nil_box; if(build_lhs_name_desc) { UI_Parent(box) UI_WidthFill UI_ChildLayoutAxis(Axis2_Y) { if(ui_top_text_alignment() == UI_TextAlign_Left && (params->flags & (RD_CellFlag_Expander|RD_CellFlag_ExpanderSpace|RD_CellFlag_ExpanderPlaceholder)) == 0) { ui_spacer(ui_em(1.f, 1.f)); } lhs_box = ui_build_box_from_stringf(0, "lhs_box"); } } ////////////////////////////// //- rjf: build left-hand-side name/desc box // if(build_lhs_name_desc) UI_Parent(lhs_box) UI_Padding(ui_em(3.f, 0.f)) UI_WidthFill UI_HeightFill { FuzzyMatchRangeList fuzzy_matches = {0}; if(params->search_needle.size != 0) { fuzzy_matches = dr_fuzzy_match_find_from_fstrs(scratch.arena, &lhs_name_fstrs, params->search_needle); } UI_Row { UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(name_box, &lhs_name_fstrs); ui_box_equip_fuzzy_match_ranges(name_box, &fuzzy_matches); } if(params->description.size != 0) RD_Font(RD_FontSlot_Main) UI_FontSize(ui_top_font_size()*0.85f) { UI_Row { UI_Box *desc_box = ui_label(params->description).box; FuzzyMatchRangeList desc_fuzzy_matches = fuzzy_match_find(scratch.arena, params->search_needle, params->description); ui_box_equip_fuzzy_match_ranges(desc_box, &desc_fuzzy_matches); } } } ////////////////////////////// //- rjf: build line edit container box // UI_Box *edit_box = &ui_nil_box; if((is_focus_active || is_focus_active_disabled) || build_line_edit) UI_Parent(box) { B32 is_editing = (is_focus_active || is_focus_active_disabled); UI_Size edit_box_size = ui_pct(1, 0); if(build_lhs_name_desc) { if(is_editing) { edit_box_size = ui_px(floor_f32(dim_2f32(box->rect).x*0.5f), 1.f); } else { edit_box_size = ui_children_sum(1); } } UI_PrefWidth(edit_box_size) { if(ui_top_px_height() > ui_top_font_size()*3.f) { ui_set_next_pref_width(ui_children_sum(1)); UI_Column UI_Padding(ui_em(1, 0)) UI_Focus(UI_FocusKind_On) { UI_PrefHeight(ui_em(3.f, 1.f)) UI_CornerRadius(ui_top_font_size()*0.5f) edit_box = ui_build_box_from_stringf((!!is_editing*UI_BoxFlag_DrawBorder)| UI_BoxFlag_Clickable| UI_BoxFlag_DisableFocusOverlay, "edit_box"); if(params->line_edit_key_out) { params->line_edit_key_out[0] = edit_box->key; } } if(ui_top_text_alignment() == UI_TextAlign_Left) { ui_spacer(ui_em(1.f, 1.f)); } } else { edit_box = ui_build_box_from_stringf(0, "edit_box"); if(params->line_edit_key_out) { params->line_edit_key_out[0] = edit_box->key; } } } } ////////////////////////////// //- rjf: build edit-button, if line edit is embedded, and has no string // B32 edit_started = 0; if(params->flags & RD_CellFlag_EmptyEditButton && !is_focus_active && !is_focus_active_disabled && build_lhs_name_desc && build_line_edit && value_name_fstrs.total_size == 0) { UI_TagF(".") UI_TagF("weak") UI_TagF("implicit") UI_Parent(box) UI_PrefWidth(ui_em(2.f, 1.f)) { UI_Column UI_Padding(ui_pct(1, 0)) UI_PrefHeight(ui_em(2.f, 1.f)) UI_CornerRadius(ui_top_font_size()*0.5f) RD_Font(RD_FontSlot_Icons) UI_TextAlignment(UI_TextAlign_Center) { UI_Box *edit_start_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DisableFocusOverlay| UI_BoxFlag_DisableFocusBorder| UI_BoxFlag_Clickable, "%S##edit", rd_icon_kind_text_table[RD_IconKind_Pencil]); UI_Signal sig = ui_signal_from_box(edit_start_box); if(ui_pressed(sig)) { edit_started = 1; } } ui_spacer(ui_em(1.f, 1.f)); } } ////////////////////////////// //- rjf: build scrollable container box // UI_Box *scrollable_box = &ui_nil_box; if(edit_box != &ui_nil_box) { UI_Parent(edit_box) UI_PrefWidth(ui_children_sum(0)) { scrollable_box = ui_build_box_from_stringf(is_focus_active*(UI_BoxFlag_AllowOverflowX), "scroll_box_%p", params->edit_buffer); } } ////////////////////////////// //- rjf: build revert-button // if(params->flags & RD_CellFlag_RevertButton && !is_focus_active && !is_focus_active_disabled) { UI_Parent(edit_box) UI_PrefWidth(ui_em(2.f, 1.f)) { UI_TagF(".") UI_TagF("weak") UI_TagF("implicit") UI_Column UI_Padding(ui_pct(1, 0)) UI_PrefHeight(ui_em(2.f, 1.f)) UI_CornerRadius(ui_top_font_size()*0.5f) RD_Font(RD_FontSlot_Icons) UI_TextAlignment(UI_TextAlign_Center) { UI_Box *revert_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawBackground| UI_BoxFlag_DisableFocusOverlay| UI_BoxFlag_DisableFocusBorder| UI_BoxFlag_Clickable, "%S##revert", rd_icon_kind_text_table[RD_IconKind_Undo]); UI_Signal sig = ui_signal_from_box(revert_box); if(ui_pressed(sig) && params->revert_out) { params->revert_out[0] = 1; } } // TODO(rjf): @hack if(build_toggle_switch || build_slider) { ui_spacer(ui_em(1.f, 1.f)); } } } ////////////////////////////// //- rjf: build toggle-switch // if(build_toggle_switch) UI_Parent(box) { B32 is_toggled = !!params->toggled_out[0]; F32 toggle_t = ui_anim(ui_key_from_stringf(key, "toggled"), (F32)is_toggled, .initial = (F32)is_toggled, .rate = rd_state->menu_animation_rate); F32 height_px = ceil_f32(ui_top_font_size() * 1.75f); F32 padding_px = ceil_f32((ui_top_px_height() - height_px) / 2.f); UI_PrefWidth(ui_children_sum(1.f)) UI_HeightFill UI_Column UI_Padding(ui_px(padding_px, 1.f)) UI_Row { if(ui_top_text_alignment() == UI_TextAlign_Center) { ui_spacer(ui_em(1.f, 0.f)); } UI_PrefWidth(ui_em(3.5f, 1.f)) UI_PrefHeight(ui_px(height_px, 1.f)) UI_CornerRadius(floor_f32(height_px/2.f - 1.f)) UI_TagF(is_toggled ? "good_pop" : "") UI_GroupKey(ui_key_from_stringf(ui_key_zero(), "toggle_switch_group_key")) { UI_Box *switch_box = ui_build_box_from_stringf(UI_BoxFlag_DrawHotEffects|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable, "toggle_switch"); UI_Parent(switch_box) { RD_Font(RD_FontSlot_Icons) UI_PrefWidth(ui_pct(toggle_t, 0)) UI_Transparency(1.f - toggle_t) { ui_build_box_from_stringf(UI_BoxFlag_DisableTextTrunc | (toggle_t > 0.001f ? UI_BoxFlag_DrawText : 0), "%S", rd_icon_kind_text_table[RD_IconKind_Check]); } UI_BackgroundColor(ui_color_from_name(str8_lit("text"))) UI_PrefWidth(ui_px(height_px, 1.f)) { F32 extratoggler_padding_px = floor_f32(ui_top_font_size()*0.35f); F32 toggler_size_px = ceil_f32(height_px - extratoggler_padding_px*2.f) - 1.f; UI_Column UI_Padding(ui_px(extratoggler_padding_px, 1.f)) UI_Row UI_Padding(ui_px(extratoggler_padding_px, 1.f)) UI_PrefWidth(ui_px(toggler_size_px, 1.f)) UI_PrefHeight(ui_px(toggler_size_px, 1.f)) UI_CornerRadius(floor_f32(toggler_size_px/2.f - 1.f)) { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } } ui_spacer(ui_pct(1.f-toggle_t, 0)); } UI_Signal switch_sig = ui_signal_from_box(switch_box); // rjf: press -> toggle, & gather this key if(ui_pressed(switch_sig)) { if(ui_dragging(switch_sig)) { ui_store_drag_struct(&switch_box->key); } params->toggled_out[0] ^= 1; } // rjf: dragging -> check if key is in batch of touched keys. if so, do nothing, otherwise, toggle. // always store this new key if not in batch if(ui_dragging(switch_sig)) { String8 all_keys_data = ui_get_drag_data(sizeof(UI_Key)); UI_Key *keys = (UI_Key *)all_keys_data.str; U64 keys_count = all_keys_data.size / sizeof(UI_Key); B32 key_is_touched = 0; for EachIndex(idx, keys_count) { if(ui_key_match(keys[idx], switch_box->key)) { key_is_touched = 1; break; } } if(!key_is_touched) { params->toggled_out[0] ^= 1; UI_Key *new_keys = push_array(scratch.arena, UI_Key, keys_count+1); MemoryCopy(new_keys, keys, sizeof(UI_Key)*keys_count); new_keys[keys_count] = switch_box->key; ui_store_drag_data(str8((U8 *)new_keys, sizeof(UI_Key) * (keys_count+1))); } } } if(ui_top_text_alignment() == UI_TextAlign_Center) { ui_spacer(ui_em(1.f, 0.f)); } } if(ui_top_text_alignment() == UI_TextAlign_Left) { ui_spacer(ui_em(1.f, 1.f)); } } ////////////////////////////// //- rjf: build slider // if(build_slider) UI_Parent(box) { F32 height_px = ceil_f32(ui_top_font_size() * 1.75f); F32 padding_px = ceil_f32((ui_top_px_height() - height_px) / 2.f); UI_PrefWidth(ui_children_sum(1.f)) UI_HeightFill UI_Column UI_Padding(ui_px(padding_px, 1.f)) UI_Row UI_PrefWidth(ui_pct(0.5f - 0.2f*(!!build_lhs_name_desc), 0.f)) UI_PrefHeight(ui_px(height_px, 1.f)) UI_CornerRadius(floor_f32(height_px/2.f - 1.f)) { F32 extratoggler_padding_px = floor_f32(ui_top_font_size()*0.35f); F32 toggler_size_px = ceil_f32(height_px - extratoggler_padding_px*2.f) - 1.f; ui_set_next_hover_cursor(OS_Cursor_LeftRight); UI_Box *slider_box = ui_build_box_from_stringf(UI_BoxFlag_DrawHotEffects|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clickable, "slider"); UI_Parent(slider_box) UI_TagF("pop") { UI_Signal sig = ui_signal_from_box(slider_box); if(ui_dragging(sig)) { if(ui_pressed(sig)) { ui_store_drag_struct(params->slider_value_out); } F32 draggable_region_size_px = dim_2f32(slider_box->rect).x - (extratoggler_padding_px*2 + toggler_size_px); F32 initial_pct = *ui_get_drag_struct(F32); F32 current_pct = initial_pct + (ui_drag_delta().x / draggable_region_size_px); params->slider_value_out[0] = current_pct; } UI_Box *fill_box = &ui_nil_box; UI_PrefWidth(ui_children_sum(0)) UI_MinWidth(toggler_size_px + extratoggler_padding_px*2) fill_box = ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, ui_key_zero()); UI_Parent(fill_box) { ui_spacer(ui_pct(Clamp(0, params->slider_value_out[0], 1), 0.f)); UI_BackgroundColor(ui_color_from_name(str8_lit("text"))) UI_PrefWidth(ui_px(height_px, 1.f)) { UI_Column UI_Padding(ui_px(extratoggler_padding_px, 1.f)) UI_Row UI_Padding(ui_px(extratoggler_padding_px, 1.f)) UI_PrefWidth(ui_px(toggler_size_px, 1.f)) UI_PrefHeight(ui_px(toggler_size_px, 1.f)) UI_CornerRadius(floor_f32(toggler_size_px/2.f - 1.f)) { ui_build_box_from_key(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } } } ui_spacer(ui_pct(1-Clamp(0, params->slider_value_out[0], 1), 0.f)); } } ui_spacer(ui_em(1.f, 1.f)); } ////////////////////////////// //- rjf: build bindings // if(build_bindings) UI_Parent(box) RD_Font(RD_FontSlot_Main) UI_PermissionFlags(UI_PermissionFlag_Clicks) { UI_PrefWidth(ui_children_sum(1)) UI_Column UI_Padding(ui_px(ui_top_px_height()*0.2f, 1.f)) UI_HeightFill { UI_PrefWidth(ui_children_sum(1)) UI_Row UI_Padding(ui_em(1.f, 1.f)) { rd_cmd_binding_buttons(params->bindings_name, params->search_needle, 1); } } } ////////////////////////////// //- rjf: build notes // if(build_note) UI_Parent(box) UI_PrefWidth(params->note_width) { UI_Box *note_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(note_box, ¬e_fstrs); } ////////////////////////////// //- rjf: do non-textual edits (delete, copy, cut) // B32 commit = 0; if(!is_focus_active && is_focus_hot) { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->flags & UI_EventFlag_Copy) { os_set_clipboard_text(params->pre_edit_value); } if(evt->flags & UI_EventFlag_Delete) { commit = 1; params->edit_string_size_out[0] = 0; } } } ////////////////////////////// //- rjf: get signal // UI_Signal sig = ui_signal_from_box(box); if(commit) { sig.f |= UI_SignalFlag_Commit; } ////////////////////////////// //- rjf: do start/end editing interaction // B32 focus_started = 0; if(!is_focus_active) { B32 start_editing_via_sig = (ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed); B32 start_editing_via_typing = 0; if(is_focus_hot) { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->string.size != 0 || evt->flags & UI_EventFlag_Paste) { start_editing_via_typing = 1; break; } } } if(is_focus_hot && ui_slot_press(UI_EventActionSlot_Edit)) { start_editing_via_typing = 1; } if(start_editing_via_sig || start_editing_via_typing) { String8 edit_string = params->pre_edit_value; edit_string.size = Min(params->edit_buffer_size, params->pre_edit_value.size); MemoryCopy(params->edit_buffer, edit_string.str, edit_string.size); params->edit_string_size_out[0] = edit_string.size; ui_set_auto_focus_active_key(key); if(!(params->flags & RD_CellFlag_Button)) { ui_kill_action(); } params->cursor[0] = txt_pt(1, edit_string.size+1); params->mark[0] = txt_pt(1, 1); focus_started = 1; } } else if(is_focus_active && sig.f&UI_SignalFlag_KeyboardPressed) { ui_set_auto_focus_active_key(ui_key_zero()); sig.f |= UI_SignalFlag_Commit; } ////////////////////////////// //- rjf: take navigation actions for editing // B32 changes_made = 0; if(!(params->flags & RD_CellFlag_DisableEdit) && (is_focus_active || focus_started)) { Temp scratch = scratch_begin(0, 0); rd_state->text_edit_mode = 1; for(UI_Event *evt = 0; ui_next_event(&evt);) { String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); // rjf: do not consume anything that doesn't fit a single-line's operations B32 is_autocompletion_completion = (autocomplete_hint_string.size != 0 && evt->kind == UI_EventKind_Press && evt->slot == UI_EventActionSlot_Accept); if(!is_autocompletion_completion && ((evt->kind != UI_EventKind_Edit && evt->kind != UI_EventKind_Navigate && evt->kind != UI_EventKind_Text) || evt->delta_2s32.y != 0)) { continue; } // rjf: map this action to an op UI_TxtOp op = ui_single_line_txt_op_from_event(scratch.arena, evt, edit_string, params->cursor[0], params->mark[0]); // rjf: any valid *additive* op & autocomplete hint? -> perform autocomplete first, then re-compute op if(!(evt->flags & UI_EventFlag_Delete) && autocomplete_hint_string.size != 0) { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info; String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(autocomp_cursor_info->replaced_range.min+1, autocomp_cursor_info->replaced_range.max+1), autocomplete_hint_string); new_string.size = Min(params->edit_buffer_size, new_string.size); MemoryCopy(params->edit_buffer, new_string.str, new_string.size); params->edit_string_size_out[0] = new_string.size; params->cursor[0] = params->mark[0] = txt_pt(1, 1+autocomp_cursor_info->replaced_range.min+autocomplete_hint_string.size); edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); op = ui_single_line_txt_op_from_event(scratch.arena, evt, edit_string, params->cursor[0], params->mark[0]); MemoryZeroStruct(&autocomplete_hint_string); } // rjf: perform replace range if(!txt_pt_match(op.range.min, op.range.max) || op.replace.size != 0) { String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(op.range.min.column, op.range.max.column), op.replace); new_string.size = Min(params->edit_buffer_size, new_string.size); MemoryCopy(params->edit_buffer, new_string.str, new_string.size); params->edit_string_size_out[0] = new_string.size; } // rjf: perform copy if(op.flags & UI_TxtOpFlag_Copy) { os_set_clipboard_text(op.copy); } // rjf: commit op's changed cursor & mark to caller-provided state params->cursor[0] = op.cursor; params->mark[0] = op.mark; // rjf: consume event { if(!is_autocompletion_completion) { ui_eat_event(evt); } changes_made = 1; } } scratch_end(scratch); } ////////////////////////////// //- rjf: click-driven "start editing" // if(edit_started) { sig.f |= UI_SignalFlag_DoubleClicked; } ////////////////////////////// //- rjf: compute editable fancy strings // DR_FStrList fstrs = {0}; { //- rjf: (not editing) if(!is_focus_active && !is_focus_active_disabled && value_name_fstrs.total_size != 0) { fstrs = value_name_fstrs; } else if(!is_focus_active && !is_focus_active_disabled && params->flags & RD_CellFlag_CodeContents && params->pre_edit_value.size != 0) { String8 display_string = params->pre_edit_value; fstrs = rd_fstrs_from_code_string(scratch.arena, 1, 0, ui_color_from_name(str8_lit("text")), display_string); } else if(!is_focus_active && !is_focus_active_disabled) { String8 display_string = params->pre_edit_value; if(params->pre_edit_value.size == 0) { display_string = ui_display_part_from_key_string(string); } UI_TagF("weak") { DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; dr_fstrs_push_new(scratch.arena, &fstrs, ¶ms, display_string); } } //- rjf: (editing) else if(is_focus_active || is_focus_active_disabled) { String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); DR_FStrList edit_string_fstrs = {0}; if(params->flags & RD_CellFlag_CodeContents) { edit_string_fstrs = rd_fstrs_from_code_string(scratch.arena, 1.f, 0, ui_color_from_name(str8_lit("text")), edit_string); } else { String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); DR_FStrParams params = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; dr_fstrs_push_new(scratch.arena, &edit_string_fstrs, ¶ms, edit_string); } if(autocomplete_hint_string.size != 0) { CFG_Node *window = cfg_node_from_id(rd_regs()->window); RD_WindowState *ws = rd_window_state_from_cfg(window); RD_AutocompCursorInfo *autocomp_cursor_info = &ws->autocomp_cursor_info; String8 autocomplete_append_string = str8_skip(autocomplete_hint_string, params->cursor->column-1 - autocomp_cursor_info->replaced_range.min); U64 off = 0; U64 cursor_off = params->cursor->column-1; DR_FStrNode *prev_n = 0; for(DR_FStrNode *n = edit_string_fstrs.first; n != 0; n = n->next) { if(off <= cursor_off && cursor_off <= off+n->v.string.size) { prev_n = n; break; } off += n->v.string.size; } { DR_FStrNode *autocomp_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); DR_FStr *fstr = &autocomp_fstr_n->v; fstr->string = autocomplete_append_string; fstr->params.font = ui_top_font(); fstr->params.raster_flags = ui_top_text_raster_flags(); fstr->params.color = ui_color_from_name(str8_lit("text")); fstr->params.color.w *= 0.5f; fstr->params.size = ui_top_font_size(); autocomp_fstr_n->next = prev_n ? prev_n->next : 0; if(prev_n != 0) { prev_n->next = autocomp_fstr_n; } if(prev_n == 0) { edit_string_fstrs.first = edit_string_fstrs.last = autocomp_fstr_n; } if(prev_n != 0 && prev_n->next == 0) { edit_string_fstrs.last = autocomp_fstr_n; } edit_string_fstrs.node_count += 1; edit_string_fstrs.total_size += autocomplete_hint_string.size; if(prev_n != 0 && cursor_off - off < prev_n->v.string.size) { String8 full_string = prev_n->v.string; U64 chop_amt = full_string.size - (cursor_off - off); prev_n->v.string = str8_chop(full_string, chop_amt); edit_string_fstrs.total_size -= chop_amt; if(chop_amt != 0) { String8 post_cursor = str8_skip(full_string, cursor_off - off); DR_FStrNode *post_fstr_n = push_array(scratch.arena, DR_FStrNode, 1); DR_FStr *post_fstr = &post_fstr_n->v; MemoryCopyStruct(post_fstr, &prev_n->v); post_fstr->string = post_cursor; if(autocomp_fstr_n->next == 0) { edit_string_fstrs.last = post_fstr_n; } post_fstr_n->next = autocomp_fstr_n->next; autocomp_fstr_n->next = post_fstr_n; edit_string_fstrs.node_count += 1; edit_string_fstrs.total_size += post_cursor.size; } } } } fstrs = edit_string_fstrs; } } ////////////////////////////// //- rjf: build scrolled contents // TxtPt mouse_pt = {0}; F32 cursor_off = 0; if(scrollable_box != &ui_nil_box) UI_Parent(scrollable_box) { FuzzyMatchRangeList fuzzy_matches = {0}; if(params->search_needle.size != 0) { fuzzy_matches = dr_fuzzy_match_find_from_fstrs(scratch.arena, &fstrs, params->search_needle); } if(ui_top_text_alignment() == UI_TextAlign_Left && (params->flags & (RD_CellFlag_Expander|RD_CellFlag_ExpanderSpace|RD_CellFlag_ExpanderPlaceholder)) == 0) { ui_spacer(ui_em(0.5f, 1.f)); } if(is_focus_active) { ui_set_next_flags(UI_BoxFlag_DisableTextTrunc); } ui_set_next_pref_width(ui_text_dim(ui_top_font_size()*0.5f, 0)); UI_Box *text_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText, "###text_box"); ui_box_equip_display_fstrs(text_box, &fstrs); ui_box_equip_fuzzy_match_ranges(text_box, &fuzzy_matches); if(is_focus_active || is_focus_active_disabled) { String8 edit_string = str8(params->edit_buffer, params->edit_string_size_out[0]); UI_LineEditDrawData *draw_data = push_array(ui_build_arena(), UI_LineEditDrawData, 1); draw_data->edited_string = push_str8_copy(ui_build_arena(), edit_string); draw_data->cursor = params->cursor[0]; draw_data->mark = params->mark[0]; draw_data->trail = do_cursor_trail; ui_box_equip_custom_draw(text_box, ui_line_edit_draw, draw_data); Vec2F32 text2mouse = sub_2f32(ui_mouse(), ui_box_text_position(text_box)); FNT_Tag font = ui_top_font(); F32 font_size = ui_top_font_size(); if(params->flags & RD_CellFlag_CodeContents) { font = rd_font_from_slot(RD_FontSlot_Code); } U64 mouse_pt_off = fnt_char_pos_from_tag_size_string_p(font, font_size, 0, ui_top_tab_size(), edit_string, text2mouse.x); mouse_pt = txt_pt(1, 1+mouse_pt_off); cursor_off = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), str8_prefix(edit_string, params->cursor->column-1)).x; } } ////////////////////////////// //- rjf: click+drag // if(is_focus_active && ui_dragging(sig)) { if(ui_pressed(sig)) { params->mark[0] = mouse_pt; } params->cursor[0] = mouse_pt; } if(!is_focus_active && is_focus_active_disabled && ui_pressed(sig)) { params->cursor[0] = params->mark[0] = mouse_pt; } ////////////////////////////// //- rjf: focus cursor // if(scrollable_box != &ui_nil_box) { F32 visible_dim_px = dim_2f32(box->rect).x - expander_size_px - ui_top_font_size()*params->depth; if(visible_dim_px > 0) { Rng1F32 cursor_range_px = r1f32(cursor_off-ui_top_font_size()*2.f, cursor_off+ui_top_font_size()*1.f); Rng1F32 visible_range_px = r1f32(scrollable_box->view_off_target.x, scrollable_box->view_off_target.x + visible_dim_px); cursor_range_px.min = ClampBot(0, cursor_range_px.min); cursor_range_px.max = ClampBot(0, cursor_range_px.max); F32 min_delta = cursor_range_px.min-visible_range_px.min; F32 max_delta = cursor_range_px.max-visible_range_px.max; min_delta = Min(min_delta, 0); max_delta = Max(max_delta, 0); scrollable_box->view_off_target.x += min_delta; scrollable_box->view_off_target.x += max_delta; } if(!is_focus_active && !is_focus_active_disabled) { scrollable_box->view_off_target.x = scrollable_box->view_off.x = 0; } } ////////////////////////////// //- rjf: pop focus // if(is_auto_focus_hot) { ui_pop_focus_hot(); } if(is_auto_focus_active) { ui_pop_focus_active(); } ProfEnd(); scratch_end(scratch); return sig; } internal UI_Signal rd_cellf(RD_CellParams *params, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = rd_cell(params, string); scratch_end(scratch); return sig; } ================================================ FILE: src/raddbg/raddbg_widgets.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_WIDGETS_H #define RADDBG_WIDGETS_H //////////////////////////////// //~ rjf: Cell Types typedef U32 RD_CellFlags; enum { //- rjf: expander RD_CellFlag_Expander = (1<<0), RD_CellFlag_ExpanderSpace = (1<<1), RD_CellFlag_ExpanderPlaceholder = (1<<2), //- rjf: toggle switch extension RD_CellFlag_ToggleSwitch = (1<<3), //- rjf: slider extension RD_CellFlag_Slider = (1<<4), //- rjf: bindings extension RD_CellFlag_Bindings = (1<<5), //- rjf: extra button extensions RD_CellFlag_EmptyEditButton = (1<<6), RD_CellFlag_RevertButton = (1<<7), //- rjf: behavior RD_CellFlag_DisableEdit = (1<<8), RD_CellFlag_KeyboardClickable = (1<<9), RD_CellFlag_SingleClickActivate = (1<<10), //- rjf: contents description RD_CellFlag_CodeContents = (1<<11), //- rjf: appearance RD_CellFlag_Border = (1<<12), RD_CellFlag_NoBackground = (1<<13), RD_CellFlag_Button = (1<<14), }; typedef struct RD_CellParams RD_CellParams; struct RD_CellParams { //- rjf: catchall parameters RD_CellFlags flags; S32 depth; String8 pre_edit_value; DR_FStrList meta_fstrs; DR_FStrList value_fstrs; DR_FStrList note_fstrs; UI_Size note_width; String8 search_needle; String8 description; //- rjf: expander r/w info B32 *expanded_out; //- rjf: toggle-switch r/w info B32 *toggled_out; //- rjf: slider info r/w info F32 *slider_value_out; //- rjf: bindings name w info String8 bindings_name; //- rjf: revert out B32 *revert_out; //- rjf: text editing r/w info TxtPt *cursor; TxtPt *mark; U8 *edit_buffer; U64 edit_buffer_size; U64 *edit_string_size_out; UI_Key *line_edit_key_out; }; //////////////////////////////// //~ rjf: Code Slice Types typedef U32 RD_CodeSliceFlags; enum { RD_CodeSliceFlag_Clickable = (1<<0), RD_CodeSliceFlag_PriorityMargin = (1<<1), RD_CodeSliceFlag_CatchallMargin = (1<<2), RD_CodeSliceFlag_LineNums = (1<<3), }; typedef struct RD_CodeSliceParams RD_CodeSliceParams; struct RD_CodeSliceParams { // rjf: content RD_CodeSliceFlags flags; Rng1S64 line_num_range; String8 *line_text; Rng1U64 *line_ranges; TXT_TokenArray *line_tokens; CFG_NodePtrList *line_bps; CTRL_EntityList *line_ips; CFG_NodePtrList *line_pins; U64 *line_vaddrs; D_LineList *line_infos; DI_KeyList relevant_dbgi_keys; TXT_TextInfo *text_info; String8 text_data; // rjf: visual parameters FNT_Tag font; F32 font_size; F32 tab_size; String8 search_query; F32 line_height_px; F32 priority_margin_width_px; F32 catchall_margin_width_px; F32 line_num_width_px; F32 line_text_max_width_px; F32 margin_float_off_px; }; typedef struct RD_CodeSliceSignal RD_CodeSliceSignal; struct RD_CodeSliceSignal { UI_Signal base; TxtPt mouse_pt; TxtRng mouse_expr_rng; }; //////////////////////////////// //~ rjf: UI Building Helpers #define RD_Font(slot) UI_Font(rd_font_from_slot(slot)) UI_TextRasterFlags(rd_raster_flags_from_slot((slot))) //////////////////////////////// //~ rjf: UI Widgets: Fancy Title Strings internal DR_FStrList rd_title_fstrs_from_cfg(Arena *arena, CFG_Node *cfg, B32 include_extras); internal DR_FStrList rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_extras); internal DR_FStrList rd_title_fstrs_from_code_name(Arena *arena, String8 code_name); internal DR_FStrList rd_title_fstrs_from_file_path(Arena *arena, String8 file_path); //////////////////////////////// //~ rjf: UI Widgets: Loading Overlay internal void rd_loading_overlay(Rng2F32 rect, F32 loading_t, U64 progress_v, U64 progress_v_target); //////////////////////////////// //~ rjf: UI Widgets: Fancy Buttons internal void rd_cmd_binding_buttons(String8 name, String8 filter, B32 add_new); internal UI_Signal rd_menu_bar_button(String8 string); internal UI_Signal rd_cmd_spec_button(String8 name); internal void rd_cmd_list_menu_buttons(U64 count, String8 *cmd_names, U32 *fastpath_codepoints); internal UI_Signal rd_icon_button(RD_IconKind kind, FuzzyMatchRangeList *matches, String8 string); internal UI_Signal rd_icon_buttonf(RD_IconKind kind, FuzzyMatchRangeList *matches, char *fmt, ...); //////////////////////////////// //~ rjf: UI Widgets: Text View internal UI_BOX_CUSTOM_DRAW(rd_code_slice_text_draw_extensions); internal UI_BOX_CUSTOM_DRAW(rd_thread_box_draw_extensions); internal UI_BOX_CUSTOM_DRAW(rd_bp_box_draw_extensions); internal RD_CodeSliceSignal rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, String8 string); internal RD_CodeSliceSignal rd_code_slicef(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *preferred_column, char *fmt, ...); internal B32 rd_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, TxtPt *cursor, TxtPt *mark, S64 *preferred_column); //////////////////////////////// //~ rjf: UI Widgets: Fancy Labels internal DR_FStrList rd_fstrs_from_rich_string(Arena *arena, String8 string); internal UI_Signal rd_label(String8 string); internal UI_Signal rd_error_label(String8 string); internal B32 rd_help_label(String8 string); internal DR_FStrList rd_fstrs_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string); internal UI_Box *rd_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string); //////////////////////////////// //~ rjf: UI Widgets: Line Edit internal UI_Signal rd_cell(RD_CellParams *params, String8 string); internal UI_Signal rd_cellf(RD_CellParams *params, char *fmt, ...); #endif // RADDBG_WIDGETS_H ================================================ FILE: src/raddump/raddump.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO: // // Code View: // [x] Test .debug$S // [x] Test .debug$T // // Test dumper on following sections: // [x] .debug_abbrev // [ ] .debug_aranges // [ ] .debug_frame // [x] .debug_info // [x] .debug_line // [ ] .debug_loc // [ ] .debug_macinfo // [ ] .debug_pubnames // [ ] .debug_pubtypes // [x] .debug_str // [x] .debug_ranges // [ ] .debug_addr // [ ] .debug_loclists // [ ] .debug_rnglists // [ ] .debug_stroffsets // [ ] .debug_linestr // [ ] .debug_names // // [ ] port ELF dumper from internal repo // [ ] port COFF/PE resource dumper from internal repo // [x] hook up RDI symbolizer internal void rd_stderr(char *fmt, ...) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 f = push_str8fv(scratch.arena, fmt, args); fprintf(stderr, "%.*s\n", str8_varg(f)); va_end(args); scratch_end(scratch); } internal RDI_Parsed * rd_rdi_from_pe(Arena *arena, String8 pe_path) { Temp scratch = scratch_begin(&arena, 1); // make command line for converter String8List cmdl_string = {0}; str8_list_pushf(scratch.arena, &cmdl_string, "-pe:%S", pe_path); CmdLine cmdl = cmd_line_from_string_list(scratch.arena, cmdl_string); // run converter String8 raw_rdi = rc_rdi_from_cmd_line(scratch.arena, &cmdl); // load RDI RDI_Parsed *rdi = 0; if (raw_rdi.size) { rdi = push_array(arena, RDI_Parsed, 1); // TODO: check guid RDI_ParseStatus parse_status = rdi_parse(raw_rdi.str, raw_rdi.size, rdi); String8 parse_status_string = str8_zero(); if (parse_status == RDI_ParseStatus_Good) { } else if (parse_status == RDI_ParseStatus_HeaderDoesNotMatch) { parse_status_string = str8_lit("Header does not match"); } else if (parse_status == RDI_ParseStatus_UnsupportedVersionNumber) { parse_status_string = str8_lit("Unsupported version number"); } else if (parse_status == RDI_ParseStatus_InvalidDataSecionLayout) { parse_status_string = str8_lit("Invalid data section layout"); } else if (parse_status == RDI_ParseStatus_MissingRequiredSection) { parse_status_string = str8_lit("Missing required section"); } else { parse_status_string = push_str8f(scratch.arena, "unknown parse status code: %u", parse_status); } if (parse_status_string.size) { rdi = 0; rd_errorf("RDI parse status(%u): %S", parse_status, parse_status_string); } } scratch_end(scratch); return rdi; } internal String8 rd_proc_name_from_voff(RDI_Parsed *rdi, U64 voff) { RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); RDI_Procedure *proc = rdi_procedure_from_scope(rdi, scope); String8 name = {0}; name.str = rdi_string_from_idx(rdi, proc->name_string_idx, &name.size); return name; } internal String8 rd_format_proc_line(Arena *arena, RDI_Parsed *rdi, U64 voff) { RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); RDI_Procedure *proc = rdi_procedure_from_scope(rdi, scope); String8 name = {0}; name.str = rdi_string_from_idx(rdi, proc->name_string_idx, &name.size); U64 rel = voff - scope->voff_range_first; String8 result = str8_zero(); if (name.size) { if (rel) { result = push_str8f(arena, "%S+%llx", name, rel); } else { result = push_str8f(arena, "%S", name); } } return result; } internal String8 rd_path_from_file_path_node_idx(Arena *arena, RDI_Parsed *rdi, U32 file_path_node_idx, PathStyle style) { Temp scratch = scratch_begin(&arena, 1); String8List parts = {0}; for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(rdi, FilePathNodes, file_path_node_idx); fpn != rdi_element_from_name_idx(rdi, FilePathNodes, 0); fpn = rdi_element_from_name_idx(rdi, FilePathNodes, fpn->parent_path_node)) { String8 p; p.str = rdi_string_from_idx(rdi, fpn->name_string_idx, &p.size); str8_list_push_front(scratch.arena, &parts, p); } String8 path = str8_path_list_join_by_style(arena, &parts, style); scratch_end(scratch); return path; } internal RD_Line rd_line_from_voff(Arena *arena, RDI_Parsed *rdi, U64 voff, PathStyle path_style) { RDI_Line line = rdi_line_from_voff(rdi, voff); RDI_SourceFile *src_file = rdi_source_file_from_line(rdi, &line); String8 file_path = rd_path_from_file_path_node_idx(arena, rdi, src_file->file_path_node_idx, path_style); RD_Line result = {0}; result.file_path = file_path; result.line_num = line.line_num; return result; } internal String8 rd_format_line_from_voff(Arena *arena, RDI_Parsed *rdi, U64 voff, PathStyle path_style) { Temp scratch = scratch_begin(&arena, 1); RD_Line line = rd_line_from_voff(scratch.arena, rdi, voff, path_style); String8 result = push_str8f(arena, "%S:%u", line.file_path, line.line_num); scratch_end(scratch); return result; } internal B32 rd_is_rdi(String8 raw_data) { B32 is_rdi = 0; if (raw_data.size > 8) { U64 *magic = (U64 *)raw_data.str; is_rdi = *magic == RDI_MAGIC_CONSTANT; } return is_rdi; } internal String8 rd_string_from_reg_off(Arena *arena, String8 reg_str, S64 reg_off) { String8 result; if (reg_off > 0) { result = push_str8f(arena, "%S%+lld", reg_str, reg_off); } else { result = push_str8f(arena, "%S", reg_str); } return result; } internal String8 rd_string_from_flags(Arena *arena, String8List list, U64 remaining_flags) { String8 result; if (list.node_count == 0 && remaining_flags == 0) { result = str8_lit("0"); } else { Temp scratch = scratch_begin(&arena, 1); if (remaining_flags != 0) { str8_list_pushf(scratch.arena, &list, "Unknown flags: %#llx", remaining_flags); } result = str8_list_join(arena, &list, &(StringJoin){.sep = str8_lit(", ") }); scratch_end(scratch); } return result; } internal String8 rd_string_from_array_u32(Arena *arena, U32 *v, U64 count) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for (U64 i = 0; i < count; ++i) { str8_list_pushf(scratch.arena, &list, "%u", v[i]); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 rd_string_from_hex_u8(Arena *arena, U8 *v, U64 count) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for (U64 i = 0; i < count; ++i) { str8_list_pushf(scratch.arena, &list, "%#x", v[i]); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 rd_string_from_array_hex_u32(Arena *arena, U32 *v, U64 count) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for (U64 i = 0; i < count; ++i) { str8_list_pushf(scratch.arena, &list, "%#x", v[i]); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal String8 rd_string_from_array_hex_u64(Arena *arena, U64 *v, U64 count) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for (U64 i = 0; i < count; ++i) { str8_list_pushf(scratch.arena, &list, "%#llx", v[i]); } String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); scratch_end(scratch); return result; } internal void rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); String8 input_type_string = str8_lit("???"); if (coff_is_regular_archive(raw_data)) { input_type_string = str8_lit("Archive"); } else if (coff_is_thin_archive(raw_data)) { input_type_string = str8_lit("Thin Archive"); } else if (coff_is_big_obj(raw_data)) { input_type_string = str8_lit("Big Obj"); } else if (coff_is_obj(raw_data)) { input_type_string = str8_lit("Obj"); } else if (pe_check_magic(raw_data)) { input_type_string = str8_lit("COFF/PE"); } else if (rd_is_rdi(raw_data)) { input_type_string = str8_lit("RDI"); } else if (elf_check_magic(raw_data)) { U8 sig[ELF_Identifier_Max] = {0}; str8_deserial_read(raw_data, 0, &sig[0], sizeof(sig), 1); input_type_string = push_str8f(scratch.arena, "ELF (Class: %S)", elf_string_from_class(scratch.arena, sig[ELF_Identifier_Class])); } DateTime universal_dt = os_now_universal_time(); DateTime local_dt = os_local_time_from_universal(&universal_dt); String8 time = string_from_date_time(scratch.arena, &local_dt); String8 full_path = os_full_path_from_path(scratch.arena, input_path); rd_printf("# %S, [%S] %S", time, input_type_string, full_path); scratch_end(scratch); } internal int rd_marker_is_before(void *a, void *b) { return u64_is_before(&((RD_Marker*)a)->off, &((RD_Marker*)b)->off); } internal int rd_range_min_is_before(void *raw_a, void *raw_b) { Rng1U64 *a = raw_a; Rng1U64 *b = raw_b; return a->min < b->min; } internal U64 rd_range_bsearch(Rng1U64 *ranges, U64 count, U64 x) { if (count > 0 && ranges[0].min <= x && x < ranges[count - 1].min) { U64 first = 0; U64 opl = count; for (;;) { U64 mid = (first + opl)/2; if (ranges[mid].min < x) { first = mid; } else if (ranges[mid].min > x) { opl = mid; } else { first = mid; break; } if (opl - first <= 1) { break; } } return first; } return max_U64; } internal RD_MarkerArray * rd_section_markers_from_rdi(Arena *arena, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); U64 sect_count = 0; RDI_BinarySection *sect_lo = rdi_table_from_name(rdi, BinarySections, §_count); Rng1U64 *sect_vranges = push_array(scratch.arena, Rng1U64, sect_count); for (U64 i = 0; i < sect_count; ++i) { sect_vranges[i].min = sect_lo[i].voff_first; sect_vranges[i].max = i; } radsort(sect_vranges, sect_count, rd_range_min_is_before); U64 proc_count = 0; RDI_Procedure *proc_lo = rdi_table_from_name(rdi, Procedures, &proc_count); RD_MarkerList *markers = push_array(scratch.arena, RD_MarkerList, sect_count); for (U64 i = 0; i < proc_count; ++i) { RDI_Procedure *proc = proc_lo + i; U64 proc_voff_lo = rdi_first_voff_from_procedure(rdi, proc); U64 proc_voff_hi = rdi_opl_voff_from_procedure(rdi, proc); U64 sect_range_idx = rd_range_bsearch(sect_vranges, sect_count, proc_voff_lo); if (sect_range_idx < sect_count) { Rng1U64 sect_range = sect_vranges[sect_range_idx]; U64 sect_idx = sect_range.max; String8 name = str8_zero(); name.str = rdi_name_from_procedure(rdi, proc, &name.size); RD_MarkerNode *n = push_array(scratch.arena, RD_MarkerNode, 1); n->v.off = proc_voff_lo - sect_range.min; n->v.string = name; RD_MarkerList *list = &markers[sect_idx]; SLLQueuePush(list->first, list->last, n); ++list->count; } } // lists -> arrays RD_MarkerArray *result = push_array(arena, RD_MarkerArray, sect_count); for (U64 i = 0; i < sect_count; ++i) { result[i].count = 0; result[i].v = push_array(arena, RD_Marker, markers[i].count); for (RD_MarkerNode *n = markers[i].first; n != 0; n = n->next) { result[i].v[result[i].count++] = n->v; } } // sort arrays for (U64 i = 0; i < sect_count; ++i) { radsort(result[i].v, result[i].count, rd_marker_is_before); } scratch_end(scratch); return result; } internal RD_MarkerArray * rd_section_markers_from_coff_symbol_table(Arena *arena, String8 string_table, U64 section_count, COFF_Symbol32Array symbols) { Temp scratch = scratch_begin(&arena, 1); // extract markers from symbol table RD_MarkerList *markers = push_array(scratch.arena, RD_MarkerList, section_count+1); for (U64 symbol_idx = 0; symbol_idx < symbols.count; ++symbol_idx) { COFF_Symbol32 *symbol = &symbols.v[symbol_idx]; COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); B32 is_marker = interp == COFF_SymbolValueInterp_Regular && symbol->aux_symbol_count == 0 && (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static); if (is_marker) { String8 name = coff_read_symbol_name(string_table, &symbol->name); RD_MarkerNode *n = push_array(scratch.arena, RD_MarkerNode, 1); n->v.off = symbol->value; n->v.string = name; RD_MarkerList *list = &markers[symbol->section_number]; SLLQueuePush(list->first, list->last, n); ++list->count; } symbol_idx += symbol->aux_symbol_count; } // lists -> arrays RD_MarkerArray *result = push_array(arena, RD_MarkerArray, section_count); for (U64 i = 0; i < section_count; ++i) { result[i].count = 0; result[i].v = push_array(arena, RD_Marker, markers[i].count); for (RD_MarkerNode *n = markers[i].first; n != 0; n = n->next) { result[i].v[result[i].count++] = n->v; } } // sort arrays for (U64 i = 0; i < section_count; ++i) { radsort(result[i].v, result[i].count, rd_marker_is_before); } scratch_end(scratch); return result; } internal RD_DisasmResult rd_disasm_next_instruction(Arena *arena, Arch arch, U64 addr, String8 raw_code) { RD_DisasmResult result = {0}; switch (arch) { case Arch_Null: break; case Arch_x64: case Arch_x86: { ZydisMachineMode machine_mode = bit_size_from_arch(arch) == 32 ? ZYDIS_MACHINE_MODE_LEGACY_32 : ZYDIS_MACHINE_MODE_LONG_64; ZydisDisassembledInstruction inst = {0}; ZyanStatus status = ZydisDisassemble(machine_mode, addr, raw_code.str, raw_code.size, &inst, ZYDIS_FORMATTER_STYLE_INTEL); String8 text = str8_cstring_capped(inst.text, inst.text+sizeof(inst.text)); result.text = push_str8_copy(arena, text); result.size = inst.info.length; } break; default: NotImplemented; } return result; } internal void rd_print_disasm(Arena *arena, String8List *out, String8 indent, Arch arch, U64 image_base, U64 sect_off, U64 marker_count, RD_Marker *markers, String8 raw_code) { Temp scratch = scratch_begin(&arena, 1); U64 bytes_buffer_max = 256; char *bytes_buffer = push_array(scratch.arena, char, bytes_buffer_max); U64 decode_off = 0; U64 marker_cursor = 0; String8 to_decode = raw_code; for (; to_decode.size > 0; ) { Temp temp = temp_begin(scratch.arena); // decode instruction U64 addr = image_base + sect_off + decode_off; RD_DisasmResult disasm_result = rd_disasm_next_instruction(temp.arena, arch, addr, to_decode); // format instruction bytes String8 bytes; { U64 bytes_size = 0; for (U64 i = 0; i < disasm_result.size; ++i) { bytes_size += raddbg_snprintf(bytes_buffer + bytes_size, bytes_buffer_max-bytes_size, "%s%02x", i > 0 ? " " : "", to_decode.str[i]); } bytes = str8((U8*)bytes_buffer, bytes_size); } // print address marker if (marker_cursor < marker_count) { RD_Marker *m = &markers[marker_cursor]; // NOTE: markers must be sorted on address if (decode_off <= m->off && m->off < decode_off + disasm_result.size) { if (m->off != decode_off) { U64 off = m->off - decode_off; rd_printf("; %S+%#llx", m->string, addr); } else { rd_printf("; %S", m->string); } marker_cursor += 1; } } // print final line rd_printf("%#08x: %-32S %S", addr, bytes, disasm_result.text); // advance to_decode = str8_skip(to_decode, disasm_result.size); decode_off += disasm_result.size; temp_end(temp); } scratch_end(scratch); } internal String8 rd_format_hex_array(Arena *arena, U8 *ptr, U64 size) { U64 buf_max = 32 + size * 8; char *buf = push_array(arena, char, buf_max); U64 buf_size = 0; buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, "{ "); for (U64 i = 0; i < size; ++i) { buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, "%s0x%02x", i>0 ? ", " : "", ptr[i]); } buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, " }"); buf[buf_size] = '\0'; String8 result = str8((U8*)buf, buf_size); return result; } internal void rd_print_raw_data(Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data) { AssertAlways(bytes_per_row > 0); char temp_buffer[1024]; String8 to_format = raw_data; for (; to_format.size > 0; ) { String8 raw_row = str8_prefix(to_format, bytes_per_row); U64 temp_cursor = 0; // offset U64 offset = (U64)(raw_row.str-raw_data.str); temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer)-temp_cursor, "%#08llx: ", offset); // hex for (U64 i = 0; i < raw_row.size; ++i) { U8 b = raw_row.str[i]; temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer)-temp_cursor, "%s%02x", i>0 ? " " : "", b); } U64 hex_indent_size = (bytes_per_row - raw_row.size) * 3; MemorySet(temp_buffer+temp_cursor, ' ', hex_indent_size); temp_cursor += hex_indent_size; temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer) - temp_cursor, " "); // ascii for (U64 i = 0; i < raw_row.size; ++i) { U8 b = raw_row.str[i]; U8 c = b; if (c < ' ' || c > '~') { c = '.'; } temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer)-temp_cursor, "%c", c); } rd_printf("%.*s", temp_cursor, temp_buffer); // advance to_format = str8_skip(to_format, bytes_per_row); } } // CodeView internal String8 cv_string_from_reg_off(Arena *arena, CV_Arch arch, U32 reg_idx, U32 reg_off) { Temp scratch = scratch_begin(&arena, 1); String8 reg_str = cv_string_from_reg_id(scratch.arena, arch, reg_idx); String8 result = rd_string_from_reg_off(arena, reg_str, reg_off); scratch_end(scratch); return result; } internal void cv_print_binary_annots(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data) { if (raw_data.size) { Temp scratch = scratch_begin(&arena, 1); rd_printf("Binary Annotations:"); rd_indent(); U64 cursor = 0; for (; cursor < raw_data.size; ) { String8List op_list = {0}; U8 op; cursor += str8_deserial_read_struct(raw_data, cursor, &op); if (op == CV_InlineBinaryAnnotation_Null) { break; } U8 params[2]; U32 param_count = (op == CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset) ? 2 : 1; cursor += str8_deserial_read_array(raw_data, cursor, ¶ms[0], param_count); String8 opcode_str = cv_string_from_binary_opcode(op); str8_list_pushf(scratch.arena, &op_list, "%S", opcode_str); for (U32 i = 0; i < param_count; ++i) { str8_list_pushf(scratch.arena, &op_list, " %x", params[i]); } String8 op_str = str8_list_join(scratch.arena, &op_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", op_str); } rd_unindent(); rd_printf("Binary Annotations Length: %u bytes (%u bytes padding)", raw_data.size, raw_data.size - cursor); scratch_end(scratch); } } internal void cv_print_lvar_addr_range(Arena *arena, String8List *out, String8 indent, CV_LvarAddrRange range) { rd_printf("Address Range: %04x:%08x Size: %#x", range.sec, range.off, range.len); } internal void cv_print_lvar_addr_gap(Arena *arena, String8List *out, String8 indent, String8 raw_data) { U64 count = raw_data.size / sizeof(CV_LvarAddrGap); if (count > 0) { U64 cursor = 0; rd_printf("# Address Gaps"); rd_indent(); for (U64 i = 0; i < count; ++i) { CV_LvarAddrGap gap = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &gap); rd_printf("Off: %#x, Len %#x", gap.off, gap.len); } rd_unindent(); } } internal void cv_print_lvar_attr(Arena *arena, String8List *out, String8 indent, CV_LocalVarAttr attr) { Temp scratch = scratch_begin(&arena,1); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, attr.seg, attr.off)); rd_printf("Flags: %S", cv_string_from_local_flags(scratch.arena, attr.flags)); scratch_end(scratch); } internal void cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV_TypeIndex min_itype, CV_SymKind type, String8 raw_symbol) { Temp scratch = scratch_begin(&arena, 1); U64 cursor = 0; switch (type) { case CV_SymKind_THUNK32_ST: case CV_SymKind_THUNK32: { CV_SymThunk32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Next : %#x", sym.next); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); rd_printf("Length : %u", sym.len); rd_printf("Ordinal: %S", cv_string_from_thunk_ordinal(sym.ord)); } break; case CV_SymKind_FILESTATIC: { CV_SymFileStatic sym = {0}; String8 name = str8_zero(); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Flags: %S", cv_string_from_local_flags(scratch.arena, sym.flags)); } break; case CV_SymKind_CALLERS: case CV_SymKind_CALLEES: { CV_SymFunctionList sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); CV_TypeIndex *funcs = push_array(scratch.arena, CV_TypeIndex, sym.count); cursor += str8_deserial_read_array(raw_symbol, cursor, &funcs[0], sym.count); U32 invocation_count = (raw_symbol.size - cursor) / sizeof(U32); U32 *invocations = push_array(arena, U32, invocation_count); cursor += str8_deserial_read_array(raw_symbol, cursor, &invocations[0], invocation_count); rd_printf("Count: %u", sym.count); rd_indent(); for (U32 i = 0; i < sym.count; ++i) { U32 invoks = i < invocation_count ? invocations[i] : 0; rd_printf("%#08x (%u)", funcs[i], invoks); } rd_unindent(); } break; case CV_SymKind_INLINEES: { CV_SymInlinees sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Count: %u", sym.count); rd_indent(); for (U32 i = 0; i < sym.count; ++i) { U32 itype; cursor += str8_deserial_read_struct(raw_symbol, cursor, &itype); rd_printf("%S", cv_string_from_itype(arena, min_itype, itype)); } rd_unindent(); } break; case CV_SymKind_INLINESITE: { CV_SymInlineSite sym = {0}; String8 raw_annots = str8_skip(raw_symbol, sizeof(CV_SymInlineSite)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_annots.size; rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Inlinee: %S", cv_string_from_itemid(arena, sym.inlinee)); cv_print_binary_annots(arena, out, indent, arch, raw_annots); } break; case CV_SymKind_INLINESITE2: { CV_SymInlineSite2 sym = {0}; String8 raw_annots = str8_skip(raw_symbol, sizeof(CV_SymInlineSite2)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_annots.size; rd_printf("Parent : %#x", sym.parent_off); rd_printf("End : %#x", sym.end_off); rd_printf("Inlinee : %S", cv_string_from_itemid(arena, sym.inlinee)); rd_printf("Invocations: %u", sym.invocations); cv_print_binary_annots(arena, out, indent, arch, raw_annots); } break; case CV_SymKind_INLINESITE_END: { // nothing to report } break; case CV_SymKind_LTHREAD32_ST: case CV_SymKind_GTHREAD32_ST: case CV_SymKind_LTHREAD32: case CV_SymKind_GTHREAD32: { CV_SymThread32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("TSL Address: %S", cv_string_sec_off(scratch.arena, sym.tls_seg, sym.tls_off)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_OBJNAME: { CV_SymObjName sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Signature: %#x", sym.sig); } break; case CV_SymKind_BLOCK32_ST: case CV_SymKind_BLOCK32: { CV_SymBlock32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); rd_printf("Length : %u", sym.len); rd_printf("Name : %S", name); if (name.size) { } } break; case CV_SymKind_LABEL32_ST: case CV_SymKind_LABEL32: { CV_SymLabel32 sym = {0}; String8 name = str8_zero(); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Address: %S, Flags: %S, Name: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off), cv_string_from_proc_flags(scratch.arena, sym.flags), name); } break; case CV_SymKind_COMPILE: { Assert(!"TODO: test"); CV_SymCompile sym = {0}; String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); U32 language = CV_CompileFlags_Extract_Language(sym.flags); U32 float_prec = CV_CompileFlags_Extract_FloatPrec(sym.flags); U32 float_pkg = CV_CompileFlags_Extract_FloatPkg(sym.flags); U32 ambient_data = CV_CompileFlags_Extract_AmbientData(sym.flags); U32 mode = CV_CompileFlags_Extract_Mode(sym.flags); rd_printf("Arch : %#x (%S)", sym.machine, cv_string_from_arch(sym.machine)); rd_printf("Language : %#x (%S)", language, cv_string_from_language(language)); rd_printf("FloatPrec : %#x", float_prec); rd_printf("FloatPkg : %#x", float_pkg); rd_printf("Ambient Data : %#x", ambient_data); rd_printf("Mode : %#x", mode); rd_printf("Version String: %S", version_string); } break; case CV_SymKind_COMPILE2_ST: case CV_SymKind_COMPILE2: { Assert(!"TODO: test"); CV_SymCompile2 sym = {0}; String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); U32 language = CV_Compile2Flags_Extract_Language(sym.flags); rd_printf("Machine : %#x (%S)", sym.machine, cv_string_from_arch(sym.machine)); rd_printf("Flags : %#x", sym.flags); rd_printf("Language : %#x (%S)", language, cv_string_from_language(language)); rd_printf("Frontend Version: %u.%u", sym.ver_fe_major, sym.ver_fe_minor); rd_printf("Frontend Build : %u", sym.ver_fe_build); rd_printf("Backend Version : %u.%u", sym.ver_major, sym.ver_minor); rd_printf("Backend Build : %u", sym.ver_build); rd_printf("Version String : %S", version_string); } break; case CV_SymKind_COMPILE3: { CV_SymCompile3 sym = {0}; String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); U32 language = CV_Compile3Flags_Extract_Language(sym.flags); rd_printf("Machine : %#x (%S)", sym.machine, cv_string_from_arch(sym.machine)); rd_printf("Flags : %#x", sym.flags); rd_printf("Language : %#x (%S)", language, cv_string_from_language(language)); rd_printf("Frontend Version: %u.%u", sym.ver_fe_major, sym.ver_fe_minor); rd_printf("Frontend Build : %u", sym.ver_fe_build); rd_printf("Fontend QFE : %u", sym.ver_feqfe); rd_printf("Backend Version : %u.%u", sym.ver_major, sym.ver_minor); rd_printf("Backend Build : %u", sym.ver_build); rd_printf("Backend QFE : %u", sym.ver_qfe); rd_printf("Version String : %S", version_string); } break; case CV_SymKind_GPROC32_ST: case CV_SymKind_LPROC32_ST: case CV_SymKind_GPROC32_ID: case CV_SymKind_LPROC32_ID: case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { CV_SymProc32 sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); String8 name = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Next : %#x", sym.next); rd_printf("Address : %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); rd_printf("Length : %u", sym.len); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_proc_flags(scratch.arena, sym.flags)); rd_printf("Debug Start: %#x", sym.dbg_start); rd_printf("Debug End : %#x", sym.dbg_end); } break; case CV_SymKind_LDATA32_ST: case CV_SymKind_GDATA32_ST: case CV_SymKind_GDATA32: case CV_SymKind_LDATA32: { CV_SymData32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); } break; case CV_SymKind_CONSTANT_ST: case CV_SymKind_CONSTANT: { CV_SymConstant sym = {0}; CV_NumericParsed size = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += cv_read_numeric(raw_symbol, cursor, &size); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name: %S", name); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Size: %S", cv_string_from_numeric(scratch.arena, size)); } break; case CV_SymKind_FRAMEPROC: { CV_SymFrameproc sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); String8 flags = cv_string_from_frame_proc_flags(scratch.arena, sym.flags); U32 local_ptr = CV_FrameprocFlags_Extract_LocalBasePointer(sym.flags); U32 param_ptr = CV_FrameprocFlags_Extract_ParamBasePointer(sym.flags); rd_printf("Frame Size : %#x", sym.frame_size); rd_printf("Pad Size : %#x", sym.pad_size); rd_printf("Pad Offset : %#x", sym.pad_off); rd_printf("Save Registers Area: %u", sym.save_reg_size); rd_printf("Exception Handler : %S", cv_string_sec_off(arena, sym.eh_sec, sym.eh_off)); rd_printf("Flags : %S", flags); rd_printf("Local pointer : %S", cv_string_from_reg_id(scratch.arena, arch, cv_map_encoded_base_pointer(arch, local_ptr))); rd_printf("Param pointer : %S", cv_string_from_reg_id(scratch.arena, arch, cv_map_encoded_base_pointer(arch, param_ptr))); } break; case CV_SymKind_LOCAL: { CV_SymLocal sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Flags: %S", cv_string_from_local_flags(scratch.arena, sym.flags)); } break; case CV_SymKind_DEFRANGE: { CV_SymDefrange sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrange)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; rd_printf("Program: %#x", sym.program); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); } break; case CV_SymKind_DEFRANGE_REGISTER: { CV_SymDefrangeRegister sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeRegisterRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; rd_printf("Register : %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Attributes: %S", cv_string_from_range_attribs(scratch.arena, sym.attribs)); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); } break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: { CV_SymDefrangeFramepointerRel sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeFramepointerRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Offset: %#x", sym.off); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); } break; case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: { CV_SymDefrangeSubfieldRegister sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeSubfieldRegister)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; rd_printf("Register : %#x (%S)", sym.reg, cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Attributes : %#x (%S)", sym.attribs, cv_string_from_range_attribs(scratch.arena, sym.attribs)); rd_printf("Parent Offset: %#x", sym.field_offset); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); } break; case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { CV_SymDefrangeFramepointerRelFullScope sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Offset: %#x", sym.off); } break; case CV_SymKind_DEFRANGE_REGISTER_REL: { CV_SymDefrangeRegisterRel sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeRegisterRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_defrange_register_rel_flags(scratch.arena, sym.flags)); rd_printf("Address: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.reg_off)); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); } break; case CV_SymKind_END: case CV_SymKind_PROC_ID_END: { // no data } break; case CV_SymKind_UDT_ST: case CV_SymKind_UDT: { CV_SymUDT sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name: %S", name); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_BUILDINFO: { CV_SymBuildInfo sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("ID: %#x", sym.id); } break; case CV_SymKind_UNAMESPACE_ST: case CV_SymKind_UNAMESPACE: { String8 name = {0}; cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name: %S", name); } break; case CV_SymKind_REGREL32_ST: case CV_SymKind_REGREL32: { CV_SymRegrel32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Address: %S, Type: %S, Name: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.reg_off), cv_string_from_itype(scratch.arena, min_itype, sym.itype), name); } break; case CV_SymKind_CALLSITEINFO: { CV_SymCallSiteInfo sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); rd_printf("Pad : %u", sym.pad); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_FRAMECOOKIE: { CV_SymFrameCookie sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Address: %S", cv_string_sec_off(arena, sym.reg, sym.off)); rd_printf("Kind : %#x (%S)", sym.kind, cv_string_from_frame_cookie_kind(sym.kind)); rd_printf("Flags : %#x", sym.flags); // TODO: llvm and cvinfo.h don't define these flags... } break; case CV_SymKind_HEAPALLOCSITE: { CV_SymHeapAllocSite sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); String8 addr = cv_string_sec_off(arena, sym.sec, sym.off); String8 itype = cv_string_from_itype(arena, min_itype, sym.itype); rd_printf("Address : %S", addr); rd_printf("Type : %S", itype); rd_printf("Call instruction length: %x", sym.call_inst_len); } break; case CV_SymKind_ALIGN: { // spec: // Unused data. Use the length field that precedes every symbol record // to skip this record. The pad bytes must be zero. For sstGlobalSym // and sstGlobalPub, the length of the pad field must be at least the // sizeof (long). There must be an S_Align symbol at the end of these // tables with a pad field containing 0xffffffff. The sstStaticSym table // does not have this requirement } break; case CV_SymKind_SKIP: { // Unused data, tools use this symbol to reserve space for future expansion // in incremental builds. } break; case CV_SymKind_ENDARG: { // spec: // This symbol specifies the end of symbol records used in formal arguments for a function. Use of // this symbol is optional for OMF and required for MIPS-compiled code. In OMF format, the end // of arguments can also be deduced from the fact that arguments for a function have a positive // offset from the frame pointer. } break; case CV_SymKind_CVRESERVE: { // Reserved for MS debugger } break; case CV_SymKind_SSEARCH: { Assert(!"TODO: test"); CV_SymStartSearch sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Start Symbol: %#x", sym.start_symbol); rd_printf("Segment : %#x", sym.segment); } break; case CV_SymKind_RETURN: { Assert(!"TODO: test"); CV_SymReturn sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_generic_flags(scratch.arena, sym.flags)); rd_printf("Style : %#x (%S)", sym.style, cv_string_from_generic_style(sym.style)); if (sym.style == CV_GenericStyle_REG) { U8 count = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &count); String8 data = rd_format_hex_array(scratch.arena, raw_symbol.str, raw_symbol.size); rd_printf("Byte Count: %u", count); rd_printf("Data : %S", data); } } break; case CV_SymKind_ENTRYTHIS: { Assert(!"TODO: test"); U16 symbol_size = 0, symbol_type = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_size); cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_type); String8 raw_subsym = str8_skip(raw_symbol, cursor); cv_print_symbol(arena, out, indent, arch, min_itype, type, raw_subsym); } break; case CV_SymKind_SLINK32: { Assert(!"TODO: test"); CV_SymSLink32 sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Frame Size: %x", sym.frame_size); rd_printf("Address : %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.offset)); } break; case CV_SymKind_OEM: { Assert(!"TODO: test"); CV_SymOEM sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); // TODO: Not clear what to do about user data that follows, are we supposed to assume that // rest of the range is it? // // CV-spec doesn't even mention S_OEM just LF_OEM and cvdump.exe prints out type with guid... rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("ID : %S", string_from_guid(scratch.arena, sym.id)); } break; case CV_SymKind_VFTABLE32:{ Assert(!"TODO: test"); CV_SymVPath32 sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Root : %S", cv_string_from_itype(scratch.arena, min_itype, sym.root)); rd_printf("Path : %S", cv_string_from_itype(scratch.arena, min_itype, sym.path)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.seg, sym.off)); } break; case CV_SymKind_PUB32_ST: case CV_SymKind_PUB32: { CV_SymPub32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Flags : %S", cv_string_from_pub32_flags(scratch.arena, sym.flags)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); } break; case CV_SymKind_BPREL32_ST: case CV_SymKind_BPREL32: { Assert(!"TODO: test"); CV_SymBPRel32 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Offset: %#x", sym.off); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_REGISTER: { Assert(!"TODO: test"); CV_SymRegister sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Register: %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_PROCREF_ST: case CV_SymKind_DATAREF_ST: case CV_SymKind_LPROCREF_ST: case CV_SymKind_ANNOTATIONREF: case CV_SymKind_LPROCREF: case CV_SymKind_PROCREF: case CV_SymKind_DATAREF: { Assert(!"TODO: test"); CV_SymRef2 sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("SUC : %#x", sym.suc_name); rd_printf("IMod : %#x", sym.imod); rd_printf("Symbol Stream Offset: %#x", sym.sym_off); } break; case CV_SymKind_SEPCODE: { Assert(!"TODO: test"); CV_SymSepcode sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Length : %u", sym.len); rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_sepcode(scratch.arena, sym.flags)); rd_printf("Address : %S", cv_string_sec_off(scratch.arena, sym.sec, sym.sec_off)); rd_printf("Parent Address: %S", cv_string_sec_off(scratch.arena, sym.sec_parent, sym.sec_parent_off)); } break; case CV_SymKind_PARAMSLOT_ST: case CV_SymKind_LOCALSLOT_ST: case CV_SymKind_LOCALSLOT: { Assert(!"TODO: test"); CV_SymSlot sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name: %S", name); rd_printf("Slot: %u", sym.slot_index); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; case CV_SymKind_TRAMPOLINE: { Assert(!"TODO: test"); CV_SymTrampoline sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Type : %S", cv_string_from_trampoline_kind(sym.kind)); rd_printf("Thunk Size: %u", sym.thunk_size); rd_printf("Thunk : %S", cv_string_sec_off(scratch.arena, sym.thunk_sec, sym.thunk_sec_off)); rd_printf("Target : %S", cv_string_sec_off(scratch.arena, sym.target_sec, sym.target_sec_off)); } break; case CV_SymKind_POGODATA: { Assert(!"TODO: test"); CV_SymPogoInfo sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Invocations : %u", sym.invocations); rd_printf("Dynamic instruction count : %u", sym.dynamic_inst_count); rd_printf("Static instruction count : %u", sym.static_inst_count); rd_printf("Post inline static instruction count: %u", sym.post_inline_static_inst_count); } break; case CV_SymKind_MANYREG: { Assert(!"TODO: test"); CV_SymManyreg sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); rd_printf("Reg Count: %u", sym.count); rd_printf("Regs :"); rd_indent(); for (U8 i = 0; i < sym.count; ++i) { U8 v = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &v); rd_printf("%S", cv_string_from_reg_id(scratch.arena, arch, v)); } rd_unindent(); } break; case CV_SymKind_MANYREG2_ST: case CV_SymKind_MANYREG2: { Assert(!"TODO: test"); CV_SymManyreg sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); rd_printf("Reg Count: %u", sym.count); rd_printf("Regs :"); rd_indent(); for (U16 i = 0; i < sym.count; ++i) { U16 v = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &v); rd_printf("%S", cv_string_from_reg_id(scratch.arena, arch, v)); } rd_unindent(); } break; case CV_SymKind_SECTION: { Assert(!"TODO: test"); CV_SymSection sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Index : %u", sym.sec_index); rd_printf("Align : %u", sym.align); rd_printf("Virtual Offset : %#x", sym.rva); rd_printf("Size : %u", sym.size); rd_printf("Characteristics: %S", coff_string_from_section_flags(scratch.arena, sym.characteristics)); } break; case CV_SymKind_ENVBLOCK: { CV_SymEnvBlock sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); for (; cursor < raw_symbol.size; ) { String8 id = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &id); String8 path = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &path); if (id.size == 0 && path.size == 0) { break; } rd_printf("%S = %S", id, path); } } break; case CV_SymKind_COFFGROUP: { Assert(!"TODO: test"); CV_SymCoffGroup sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Size : %u", sym.size); rd_printf("Characteristics: %#x (%S)", sym.characteristics, coff_string_from_section_flags(scratch.arena, sym.characteristics)); rd_printf("Address : %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); } break; case CV_SymKind_EXPORT: { Assert(!"TODO: test"); CV_SymExport sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Ordinal: %#x", sym.ordinal); rd_printf("Flags : %S", cv_string_from_export_flags(scratch.arena, sym.flags)); } break; case CV_SymKind_ANNOTATION: { Assert(!"TODO: test"); CV_SymAnnotation sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Address : %S", cv_string_sec_off(scratch.arena, sym.seg, sym.off)); rd_printf("Count : %u", sym.count); rd_printf("Annotations:"); rd_indent(); for (U16 i = 0; i < sym.count; ++i) { String8 str = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &str); rd_printf("%S", str); } rd_unindent(); } break; case CV_SymKind_MANFRAMEREL: case CV_SymKind_ATTR_FRAMEREL: { Assert(!"TODO: test"); CV_SymAttrFrameRel sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Offset: %#x", sym.off); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); cv_print_lvar_attr(arena, out, indent, sym.attr); } break; case CV_SymKind_MANREGISTER: case CV_SymKind_ATTR_REGISTER: { Assert(!"TODO: test"); CV_SymAttrReg sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Register: %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); cv_print_lvar_attr(arena, out, indent, sym.attr); } break; case CV_SymKind_ATTR_REGREL: { Assert(!"TODO: test"); CV_SymAttrRegRel sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Address: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.off)); cv_print_lvar_attr(arena, out, indent, sym.attr); } break; case CV_SymKind_MANYREG_ST: case CV_SymKind_MANMANYREG: case CV_SymKind_ATTR_MANYREG: { Assert(!"TODO: test"); CV_SymAttrManyReg sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); U8 *regs = push_array(scratch.arena, U8, sym.count); cursor += str8_deserial_read_array(raw_symbol, cursor, ®s[0], sym.count); String8 name = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); cv_print_lvar_attr(arena, out, indent, sym.attr); rd_printf("Reg Count: %u", sym.count); rd_printf("Regs :"); rd_indent(); for (U8 i = 0; i < sym.count; ++i) { rd_printf("%S", cv_string_from_reg_id(scratch.arena, arch, regs[i])); } rd_unindent(); } break; case CV_SymKind_MOD_TYPEREF: { Assert(!"TODO: test"); CV_SymModTypeRef sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); String8List flags_list = {0}; if (sym.flags & CV_ModTypeRefFlag_None) { str8_list_pushf(scratch.arena, &flags_list, "No TypeRef"); } else if (sym.flags & CV_ModTypeRefFlag_OwnTMR) { str8_list_pushf(scratch.arena, &flags_list, "/Z7 TypeRef, SN=%04X", sym.word0); if (sym.flags & CV_ModTypeRefFlag_OwnTMPCT) { str8_list_pushf(scratch.arena, &flags_list, "own PCH types"); } if (sym.flags & CV_ModTypeRefFlag_RefTMPCT) { str8_list_pushf(scratch.arena, &flags_list, "reference PCH types in module %04X", (sym.word1+1)); } } else { str8_list_pushf(scratch.arena, &flags_list, "/Zi TypeRef"); if (sym.flags & CV_ModTypeRefFlag_OwnTM) { str8_list_pushf(scratch.arena, &flags_list, "SN=%04X (type), SN=%04X (ID)", sym.word0, sym.word1); } if (sym.flags & CV_ModTypeRefFlag_RefTM) { str8_list_pushf(scratch.arena, &flags_list, "shared with Module %04X", sym.word0+1); } } String8 flags_str = str8_list_join(scratch.arena, &flags_list, &(StringJoin){.sep=str8_lit(", ")}); rd_printf("%S", flags_str); } break; case CV_SymKind_DISCARDED: { Assert(!"TODO: test"); CV_SymDiscarded sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); U32 symbol_type = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_type); String8 raw_subsym = str8_skip(raw_symbol, cursor); rd_printf("Kind : %x", sym.kind); rd_printf("File ID : %x", sym.file_id); rd_printf("File Line Number: %u", sym.file_ln); rd_printf("# Discarded Symbol"); cv_print_symbol(arena, out, indent, arch, min_itype, symbol_type, raw_subsym); } break; case CV_SymKind_PDBMAP: { Assert(!"TODO: test"); String8 from = {0}; String8 to = {0}; cursor += str8_deserial_read_cstr(raw_symbol, cursor, &from); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &to); rd_printf("From: %S", from); rd_printf("To : %S", to); } break; case CV_SymKind_FASTLINK: { Assert(!"TODO: test"); CV_SymFastLink sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Flags: %#x", sym.flags); rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); } break; case CV_SymKind_ARMSWITCHTABLE: { Assert(!"TODO: test"); CV_SymArmSwitchTable sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); rd_printf("Base Address : %S", cv_string_sec_off(scratch.arena, sym.sec_base, sym.off_base)); rd_printf("Branch Address: %S", cv_string_sec_off(scratch.arena, sym.sec_branch, sym.off_branch)); rd_printf("Table Address : %S", cv_string_sec_off(scratch.arena, sym.sec_table, sym.off_table)); rd_printf("Entry count : %u", sym.entry_count); rd_printf("Switch Type : %x", sym.kind); } break; case CV_SymKind_REF_MINIPDB: { Assert(!"TODO: test"); CV_SymRefMiniPdb sym = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); rd_printf("Name : %S", name); rd_printf("Flags : %x", sym.flags); rd_printf("IMod : %04x", sym.imod); if (sym.flags & CV_RefMiniPdbFlag_UDT) { rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, (CV_TypeIndex)sym.data)); } else { rd_printf("Coff ISect: %#x", sym.data); } } break; // COBOL case CV_SymKind_CEXMODEL32: case CV_SymKind_COBOLUDT_ST: case CV_SymKind_COBOLUDT: // Pascal case CV_SymKind_WITH32_ST: case CV_SymKind_WITH32: //~ 16bit case CV_SymKind_REGISTER_16t: case CV_SymKind_CONSTANT_16t: case CV_SymKind_UDT_16t: case CV_SymKind_OBJNAME_ST: case CV_SymKind_COBOLUDT_16t: case CV_SymKind_MANYREG_16t: case CV_SymKind_BPREL16: case CV_SymKind_LDATA16: case CV_SymKind_GDATA16: case CV_SymKind_PUB16: case CV_SymKind_LPROC16: case CV_SymKind_GPROC16: case CV_SymKind_THUNK16: case CV_SymKind_BLOCK16: case CV_SymKind_WITH16: case CV_SymKind_LABEL16: case CV_SymKind_CEXMODEL16: case CV_SymKind_VFTABLE16: case CV_SymKind_REGREL16: case CV_SymKind_TI16_MAX: //~ 16:32 memory model case CV_SymKind_BPREL32_16t: case CV_SymKind_LDATA32_16t: case CV_SymKind_GDATA32_16t: case CV_SymKind_PUB32_16t: case CV_SymKind_LPROC32_16t: case CV_SymKind_GPROC32_16t: case CV_SymKind_VFTABLE32_16t: case CV_SymKind_REGREL32_16t: case CV_SymKind_LTHREAD32_16t: case CV_SymKind_GTHREAD32_16t: case CV_SymKind_LPROCMIPS_16t: case CV_SymKind_GPROCMIPS_16t: // MIPS case CV_SymKind_LPROCMIPS_ST: case CV_SymKind_GPROCMIPS_ST: case CV_SymKind_LPROCMIPS: case CV_SymKind_GPROCMIPS: case CV_SymKind_LPROCIA64: case CV_SymKind_GPROCIA64: case CV_SymKind_LPROCMIPS_ID: case CV_SymKind_GPROCMIPS_ID: // Managed case CV_SymKind_TOKENREF: case CV_SymKind_GMANPROC_ST: case CV_SymKind_LMANPROC_ST: case CV_SymKind_LMANDATA_ST: case CV_SymKind_GMANDATA_ST: case CV_SymKind_MANFRAMEREL_ST: case CV_SymKind_MANREGISTER_ST: case CV_SymKind_MANSLOT_ST: case CV_SymKind_MANTYPREF: case CV_SymKind_MANMANYREG_ST: case CV_SymKind_MANREGREL_ST: case CV_SymKind_MANMANYREG2_ST: case CV_SymKind_MANMANYREG2: case CV_SymKind_MANREGREL: case CV_SymKind_MANSLOT: case CV_SymKind_MANCONSTANT: case CV_SymKind_LMANDATA: case CV_SymKind_GMANDATA: case CV_SymKind_GMANPROC: case CV_SymKind_LMANPROC: // HLSL case CV_SymKind_DEFRANGE_DPC_PTR_TAG: case CV_SymKind_DPC_SYM_TAG_MAP: case CV_SymKind_DEFRANGE_HLSL: case CV_SymKind_GDATA_HLSL: case CV_SymKind_LDATA_HLSL: case CV_SymKind_LPROC32_DPC: case CV_SymKind_LPROC32_DPC_ID: case CV_SymKind_GDATA_HLSL32: case CV_SymKind_LDATA_HLSL32: case CV_SymKind_GDATA_HLSL32_EX: case CV_SymKind_LDATA_HLSL32_EX: // IA64 case CV_SymKind_LPROCIA64_ID: case CV_SymKind_GPROCIA64_ID: // VS2005 case CV_SymKind_DEFRANGE_2005: case CV_SymKind_DEFRANGE2_2005: case CV_SymKind_ST_MAX: case CV_SymKind_RESERVED1: case CV_SymKind_RESERVED2: case CV_SymKind_RESERVED3: case CV_SymKind_RESERVED4: { } break; } scratch_end(scratch); } internal U64 cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_itype, CV_LeafKind kind, String8 raw_leaf) { Temp scratch = scratch_begin(&arena, 1); U64 cursor = 0; switch (kind) { case CV_LeafKind_NOTYPE: { // empty } break; case CV_LeafKind_BITFIELD: { CV_LeafBitField lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Length : %u", lf.len); rd_printf("Position: %u", lf.pos); } break; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { CV_LeafStruct2 lf = {0}; CV_NumericParsed size = {0}; String8 name = str8_zero(); cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &size); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Fields : %S", cv_string_from_itype(scratch.arena, min_itype, lf.field_itype)); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); rd_printf("Derived : %S", cv_string_from_itype(scratch.arena, min_itype, lf.derived_itype)); rd_printf("VShape : %S", cv_string_from_itype(scratch.arena, min_itype, lf.vshape_itype)); rd_printf("Unknown : %#x", lf.unknown); if (lf.props & CV_TypeProp_HasUniqueName) { String8 unique_name = str8_zero(); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &unique_name); rd_printf("Unique Name: %S", unique_name); } } break; case CV_LeafKind_PRECOMP_ST: case CV_LeafKind_PRECOMP: { CV_LeafPreComp lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Start Index: %x", lf.start_index); rd_printf("Count : %u", lf.count); rd_printf("Signature : %x", lf.sig); } break; case CV_LeafKind_TYPESERVER2: { CV_LeafTypeServer2 lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Sig70: %S", string_from_guid(arena, lf.sig70)); rd_printf("Age : %u", lf.age); } break; case CV_LeafKind_BUILDINFO: { CV_LeafBuildInfo lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Entry Count: %u", lf.count); rd_indent(); for (U16 i = 0; i < lf.count; ++i) { CV_ItemId id = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &id); rd_printf("%S", cv_string_from_itemid(scratch.arena, id)); } rd_unindent(); } break; case CV_LeafKind_MFUNC_ID: { CV_LeafMFuncId lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Owner Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.owner_itype)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_VFUNCTAB: { CV_LeafVFuncTab lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_METHODLIST: { for (; cursor < raw_leaf.size; ) { CV_LeafMethodListMember ml = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &ml); U32 mprop = CV_FieldAttribs_Extract_MethodProp(ml.attribs); B32 has_vbase = (mprop == CV_MethodProp_PureIntro) || (mprop == CV_MethodProp_Intro); U32 vbase = 0; if (has_vbase) { cursor += str8_deserial_read_struct(raw_leaf, cursor, &vbase); } rd_printf("Attribs : %#x (%S)", ml.attribs, cv_string_from_field_attribs(scratch.arena, ml.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, ml.itype)); if (has_vbase) { rd_printf("Virtual Base: %x", vbase); } } } break; case CV_LeafKind_ONEMETHOD_ST: case CV_LeafKind_ONEMETHOD: { CV_LeafOneMethod lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); U32 mprop = CV_FieldAttribs_Extract_MethodProp(lf.attribs); B32 has_vbase = (mprop == CV_MethodProp_PureIntro) || (mprop == CV_MethodProp_Intro); U32 vbase = 0; if (has_vbase) { cursor += str8_deserial_read_struct(raw_leaf, cursor, &vbase); } String8 name = {0}; cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Field Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); if (has_vbase) { rd_printf("Virtual Base: %#x", vbase); } } break; case CV_LeafKind_METHOD_ST: case CV_LeafKind_METHOD: { CV_LeafMethod lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Count : %u", lf.count); rd_printf("Type List: %S", cv_string_from_itype(scratch.arena, min_itype, lf.list_itype)); } break; case CV_LeafKind_VBCLASS: case CV_LeafKind_IVBCLASS: { CV_LeafVBClass lf = {0}; CV_NumericParsed vbptr_off = {0}; CV_NumericParsed vbtable_off = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &vbptr_off); cursor += cv_read_numeric(raw_leaf, cursor, &vbtable_off); rd_printf("Attribs : %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Direct Base Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Virtual Base Ptr: %S", cv_string_from_itype(scratch.arena, min_itype, lf.vbptr_itype)); rd_printf("vbpoff : %S", cv_string_from_numeric(scratch.arena, vbptr_off)); rd_printf("vbind : %S", cv_string_from_numeric(scratch.arena, vbtable_off)); } break; case CV_LeafKind_BCLASS: { CV_LeafBClass lf = {0}; CV_NumericParsed offset = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &offset); rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Offset : %S", cv_string_from_numeric(scratch.arena, offset)); } break; case CV_LeafKind_VTSHAPE: { CV_LeafVTShape lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Entry Count: %u", lf.count); rd_indent(); for (U16 i = 0; i < lf.count; ++i) { U8 packed_kind = 0; str8_deserial_read_struct(raw_leaf, cursor + (i / 2), &packed_kind); U8 kind = (packed_kind >> ((i % 2)*4)) & 0xF; rd_printf("%S", cv_string_from_virtual_table_shape_kind(kind)); } rd_unindent(); cursor += (lf.count * sizeof(U8) + 1) / 2; } break; case CV_LeafKind_STMEMBER_ST: case CV_LeafKind_STMEMBER: { CV_LeafStMember lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_MFUNCTION: { CV_LeafMFunction lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Return Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.ret_itype)); rd_printf("Class Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.class_itype)); rd_printf("This Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.this_itype)); rd_printf("Call Kind : %#x (%S)", lf.call_kind, cv_string_from_call_kind(lf.call_kind)); rd_printf("Function Attribs: %#x (%S)", lf.attribs, cv_string_from_function_attribs(scratch.arena, lf.attribs)); rd_printf("Argument Count : %u", lf.arg_count); rd_printf("Argument Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.arg_itype)); } break; #if 0 case CV_LeafKind_SKIP_16t: { CV_LeafSkip_16t lf = {0}; cursor += str8_deserial_read_struct(base, range, cursor, &lf); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.type)); } break; #endif case CV_LeafKind_SKIP: { // ms-symbol-pdf: // This is used by incremental compilers to reserve space for indices. CV_LeafSkip lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_ENUM_ST: case CV_LeafKind_ENUM: { CV_LeafEnum lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Field Count: %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.base_itype)); rd_printf("Field : %S", cv_string_from_itype(scratch.arena, min_itype, lf.field_itype)); if (lf.props & CV_TypeProp_HasUniqueName) { String8 unique_name = {0}; cursor += str8_deserial_read_cstr(raw_leaf, cursor, &unique_name); rd_printf("Unique Name: %S", unique_name); } } break; case CV_LeafKind_ENUMERATE: { CV_LeafEnumerate lf = {0}; CV_NumericParsed value = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &value); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Attribs: %S", cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Value : %S", cv_string_from_numeric(scratch.arena, value)); } break; case CV_LeafKind_NESTTYPE_ST: case CV_LeafKind_NESTTYPE: { CV_LeafNestType lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Index: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_NOTTRAN: { // ms-symbol-pdf: // This is used when CVPACK encounters a type record that has no equivalent in the Microsoftsymbol information format. } break; case CV_LeafKind_UDT_SRC_LINE: { CV_LeafUDTSrcLine lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Type = %S, Source File = %x, Line = %u", cv_string_from_itype(scratch.arena, min_itype, lf.udt_itype), lf.src_string_id, lf.line); } break; case CV_LeafKind_STRING_ID: { CV_LeafStringId lf = {0}; String8 string = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &string); rd_printf("string : %S", string); rd_printf("Substrings: %S", cv_string_from_itemid(arena, lf.substr_list_id)); // TODO: print actual strings instead } break; case CV_LeafKind_POINTER: { CV_LeafPointer lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); CV_PointerKind kind = CV_PointerAttribs_Extract_Kind(lf.attribs); CV_PointerMode mode = CV_PointerAttribs_Extract_Mode(lf.attribs); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Attribs: %S", cv_string_from_pointer_attribs(arena, lf.attribs)); rd_indent(); if (mode == CV_PointerMode_PtrMem) { CV_TypeIndex itype = 0; CV_MemberPointerKind pm = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &itype); cursor += str8_deserial_read_struct(raw_leaf, cursor, &pm); rd_printf("Class Type: %S", cv_string_from_itype(scratch.arena, min_itype, itype)); rd_printf("Format : %S", cv_string_from_member_pointer_kind(pm)); } else { if (kind == CV_PointerKind_BaseSeg) { U16 seg; cursor += str8_deserial_read_struct(raw_leaf, cursor, &seg); rd_printf("Base Segment: %#04x", seg); } else if (kind == CV_PointerKind_BaseType) { CV_TypeIndex base_itype = 0; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &base_itype); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Base Type: %S", cv_string_from_itype(scratch.arena, min_itype, base_itype)); rd_printf("Name : %S", name); } } rd_unindent(); } break; case CV_LeafKind_UNION_ST: case CV_LeafKind_UNION: { CV_LeafUnion lf = {0}; CV_NumericParsed num = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Field Count: %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); rd_printf("Field : %S", cv_string_from_itype(scratch.arena, min_itype, lf.field_itype)); rd_printf("Size : %S", cv_string_from_numeric(scratch.arena, num)); if (lf.props & CV_TypeProp_HasUniqueName) { String8 unique_name = {0}; cursor += str8_deserial_read_cstr(raw_leaf, cursor, &unique_name); rd_printf("Unique Name: %S", unique_name); } } break; case CV_LeafKind_CLASS_ST: case CV_LeafKind_STRUCTURE_ST: case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { CV_LeafStruct lf = {0}; CV_NumericParsed num = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Field Count : %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); rd_printf("Field List Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.field_itype)); rd_printf("Derived Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.derived_itype)); rd_printf("VShape : %S", cv_string_from_itype(scratch.arena, min_itype, lf.vshape_itype)); rd_printf("Size : %S", cv_string_from_numeric(scratch.arena, num)); if (lf.props & CV_TypeProp_HasUniqueName) { String8 unique_name = {0}; cursor += str8_deserial_read_cstr(raw_leaf, cursor, &unique_name); rd_printf("Unique Name: %S", unique_name); } } break; case CV_LeafKind_SUBSTR_LIST: case CV_LeafKind_ARGLIST: { CV_LeafArgList lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Types %u", lf.count); rd_indent(); for (U32 i = 0; i < lf.count; ++i) { U32 itype = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &itype); rd_printf("%S", cv_string_from_itype(scratch.arena, min_itype, itype)); } rd_unindent(); } break; case CV_LeafKind_PROCEDURE: { CV_LeafProcedure lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); String8 call_kind = cv_string_from_call_kind(lf.call_kind); String8 func_attribs = cv_string_from_function_attribs(scratch.arena, lf.attribs); rd_printf("Return type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.ret_itype)); rd_printf("Call Convention : %#x (%S)", lf.call_kind, call_kind); rd_printf("Function Attribs : %#x (%S)", lf.attribs, func_attribs); rd_printf("Argumnet Count : %u", lf.arg_count); rd_printf("Argument List Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.arg_itype)); } break; case CV_LeafKind_FUNC_ID: { CV_LeafFuncId lf = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Scope Type: %#x (%S)", lf.scope_string_id, cv_string_from_itype(scratch.arena, min_itype, lf.scope_string_id)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_MODIFIER: { CV_LeafModifier lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Flags: %#x (%S)", lf.flags, cv_string_from_modifier_flags(scratch.arena, lf.flags)); } break; case CV_LeafKind_ARRAY_ST: case CV_LeafKind_ARRAY: { CV_LeafArray lf = {0}; CV_NumericParsed num = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); rd_printf("Entry type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.entry_itype)); rd_printf("Index type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.index_itype)); rd_printf("Length : %S", cv_string_from_numeric(scratch.arena, num)); } break; case CV_LeafKind_FIELDLIST: { for (U64 idx = 0; cursor < raw_leaf.size;) { U16 member_type = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &member_type); String8 raw_member = str8_skip(raw_leaf, cursor); rd_printf("list[%u] = %S", idx++, cv_string_from_leaf_name(arena, member_type)); rd_indent(); cursor += cv_print_leaf(arena, out, indent, min_itype, member_type, raw_member); cursor = AlignPow2(cursor, 4); rd_unindent(); } } break; case CV_LeafKind_MEMBER_ST: case CV_LeafKind_MEMBER: { CV_LeafMember lf = {0}; CV_NumericParsed num = {0}; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); rd_printf("Name : %S", name); rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Offset : %S", cv_string_from_numeric(scratch.arena, num)); } break; case CV_LeafKind_LABEL: { CV_LeafLabel lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Kind: %S", cv_string_from_label_kind(scratch.arena, lf.kind)); } break; case CV_LeafKind_ENDPRECOMP: { CV_LeafEndPreComp lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); rd_printf("Sig: %#x", lf.sig); } break; // 16bit case CV_LeafKind_OEM_16t: case CV_LeafKind_MODIFIER_16t: case CV_LeafKind_POINTER_16t: case CV_LeafKind_ARRAY_16t: case CV_LeafKind_CLASS_16t: case CV_LeafKind_STRUCTURE_16t: case CV_LeafKind_UNION_16t: case CV_LeafKind_ENUM_16t: case CV_LeafKind_PROCEDURE_16t: case CV_LeafKind_MFUNCTION_16t: case CV_LeafKind_COBOL0_16t: case CV_LeafKind_BARRAY_16t: case CV_LeafKind_DIMARRAY_16t: case CV_LeafKind_VFTPATH_16t: case CV_LeafKind_PRECOMP_16t: case CV_LeafKind_ARGLIST_16t: case CV_LeafKind_DEFARG_16t: case CV_LeafKind_FIELDLIST_16t: case CV_LeafKind_DERIVED_16t: case CV_LeafKind_BITFIELD_16t: case CV_LeafKind_METHODLIST_16t: case CV_LeafKind_DIMCONU_16t: case CV_LeafKind_DIMCONLU_16t: case CV_LeafKind_DIMVARU_16t: case CV_LeafKind_DIMVARLU_16t: case CV_LeafKind_BCLASS_16t: case CV_LeafKind_VBCLASS_16t: case CV_LeafKind_IVBCLASS_16t: case CV_LeafKind_ENUMERATE_ST: case CV_LeafKind_FRIENDFCN_16t: case CV_LeafKind_INDEX_16t: case CV_LeafKind_MEMBER_16t: case CV_LeafKind_STMEMBER_16t: case CV_LeafKind_METHOD_16t: case CV_LeafKind_NESTTYPE_16t: case CV_LeafKind_VFUNCTAB_16t: case CV_LeafKind_FRIENDCLS_16t: case CV_LeafKind_ONEMETHOD_16t: case CV_LeafKind_VFUNCOFF_16t: case CV_LeafKind_ST_MAX: // HLSL case CV_LeafKind_HLSL: // COBOL case CV_LeafKind_COBOL0: case CV_LeafKind_COBOL1: // Manged case CV_LeafKind_MANAGED_ST: // undefined case CV_LeafKind_LIST: case CV_LeafKind_REFSYM: case CV_LeafKind_BARRAY: case CV_LeafKind_DIMARRAY_ST: case CV_LeafKind_VFTPATH: case CV_LeafKind_OEM: case CV_LeafKind_ALIAS_ST: case CV_LeafKind_OEM2: case CV_LeafKind_DEFARG_ST: case CV_LeafKind_DERIVED: case CV_LeafKind_DIMCONU: case CV_LeafKind_DIMCONLU: case CV_LeafKind_DIMVARU: case CV_LeafKind_DIMVARLU: case CV_LeafKind_FRIENDFCN_ST: case CV_LeafKind_INDEX: case CV_LeafKind_FRIENDCLS: case CV_LeafKind_VFUNCOFF: case CV_LeafKind_MEMBERMODIFY_ST: case CV_LeafKind_TYPESERVER_ST: case CV_LeafKind_TYPESERVER: case CV_LeafKind_DIMARRAY: case CV_LeafKind_ALIAS: case CV_LeafKind_DEFARG: case CV_LeafKind_FRIENDFCN: case CV_LeafKind_NESTTYPEEX: case CV_LeafKind_MEMBERMODIFY: case CV_LeafKind_MANAGED: case CV_LeafKind_STRIDED_ARRAY: case CV_LeafKind_MODIFIER_EX: case CV_LeafKind_INTERFACE: case CV_LeafKind_BINTERFACE: case CV_LeafKind_VECTOR: case CV_LeafKind_MATRIX: case CV_LeafKind_VFTABLE: case CV_LeafKind_UDT_MOD_SRC_LINE: { rd_errorf("TODO: %#x", kind); } break; } scratch_end(scratch); return cursor; } internal void cv_print_debug_t(Arena *arena, String8List *out, String8 indent, CV_DebugT debug_t) { Temp scratch = scratch_begin(&arena, 1); for (U64 lf_idx = 0; lf_idx < debug_t.count; ++lf_idx) { CV_Leaf lf = cv_debug_t_get_leaf(debug_t, lf_idx); U64 offset = (U64)(lf.data.str-debug_t.v[0]); CV_TypeIndex itype = CV_MinComplexTypeIndex + lf_idx; rd_printf("LF_%S (%x) [%04llx-%04llx)", cv_string_from_leaf_kind(lf.kind), itype, offset, offset+lf.data.size); rd_indent(); cv_print_leaf(arena, out, indent, CV_MinComplexTypeIndex, lf.kind, lf.data); rd_unindent(); } scratch_end(scratch); } internal void cv_print_symbols_c13(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); B32 scope_depth = 0; for (U64 cursor = 0; cursor < raw_data.size; ) { CV_SymbolHeader header = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &header); if (header.size >= sizeof(header.kind)) { Temp temp = temp_begin(scratch.arena); U64 symbol_end = cursor + (header.size - sizeof(header.kind)); String8 raw_symbol = str8_substr(raw_data, rng_1u64(cursor, symbol_end)); if (header.kind == CV_SymKind_END || header.kind == CV_SymKind_INLINESITE_END) { if (scope_depth > 0) { rd_unindent(); --scope_depth; } else { rd_errorf("unbalanced scopes"); } } rd_printf("%S [%04llx-%04llx)", cv_string_from_symbol_type(temp.arena, header.kind), cursor, header.size-sizeof(header.size)); rd_indent(); cv_print_symbol(arena, out, indent, arch, CV_MinComplexTypeIndex, header.kind, raw_symbol); rd_unindent(); if (header.kind == CV_SymKind_BLOCK32 || header.kind == CV_SymKind_INLINESITE) { rd_indent(); ++scope_depth; } cursor = symbol_end; temp_end(temp); } else { rd_errorf("symbol must be at least two bytes long"); } } scratch_end(scratch); } internal void cv_print_lines_c13(Arena *arena, String8List *out, String8 indent, String8 raw_lines) { Temp scratch = scratch_begin(&arena, 1); U64 cursor = 0; CV_C13SubSecLinesHeader header = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &header); B32 has_columns = !!(header.flags & CV_C13SubSecLinesFlag_HasColumns); if (has_columns) { rd_errorf("TOOD: columns"); } rd_printf("%04x:%08x-%08x, flags = %04x", header.sec, header.sec_off, header.len, header.flags); for (; cursor < raw_lines.size; ) { CV_C13File file = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &file); rd_printf("file = %08x, line count = %u, block size %08x", file.file_off, file.num_lines, file.block_size); Temp temp = temp_begin(scratch.arena); String8List columns = {0}; for (U32 line_idx = 0; line_idx < file.num_lines; ++line_idx) { CV_C13Line line = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &line); B32 always_step_in_line_number = line.off == 0xFEEFEE; B32 never_step_in_line_number = line.off == 0xF00F00; U32 ln = CV_C13LineFlags_Extract_LineNumber(line.flags); //U32 delta = CV_C13LineFlags_Extract_DeltaToEnd(line.flags); //B32 is_stmt = CV_C13LineFlags_Extract_Statement(line.flags); if (always_step_in_line_number || never_step_in_line_number) { str8_list_pushf(temp.arena, &columns, "%x %08X", ln, line.off); } else { str8_list_pushf(temp.arena, &columns, "%5u %08X", ln, line.off); } if ((line_idx+1) % 4 == 0 || (line_idx+1) == file.num_lines) { String8 line_str = str8_list_join(scratch.arena, &columns, &(StringJoin){.sep=str8_lit("\t")}); rd_printf("%S", line_str); temp_end(temp); temp = temp_begin(scratch.arena); MemoryZeroStruct(&columns); } } temp_end(temp); if (cursor < raw_lines.size) { rd_newline(); } } scratch_end(scratch); } internal void cv_print_file_checksums(Arena *arena, String8List *out, String8 indent, String8 raw_chksums) { Temp scratch = scratch_begin(&arena, 1); rd_printf("%-8s %-8s %-8s %-16s", "File", "Size", "Type", "Checksum"); for (U64 cursor = 0; cursor < raw_chksums.size; ) { CV_C13Checksum chksum = {0}; cursor += str8_deserial_read_struct(raw_chksums, cursor, &chksum); Temp temp = temp_begin(scratch.arena); String8 chksum_str = str8_lit("???"); U8 *chksum_ptr = str8_deserial_get_raw_ptr(raw_chksums, cursor, chksum.len); if (chksum_ptr) { chksum_str = rd_format_hex_array(temp.arena, chksum_ptr, chksum.len); } rd_printf("%08x %08x %-8S %S", chksum.name_off, chksum.len, cv_string_from_c13_checksum_kind(chksum.kind), chksum_str); temp_end(temp); cursor += chksum.len; cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); } scratch_end(scratch); } internal void cv_print_string_table(Arena *arena, String8List *out, String8 indent, String8 raw_strtab) { for (U64 cursor = 0; cursor < raw_strtab.size; ) { String8 str = {0}; cursor += str8_deserial_read_cstr(raw_strtab, cursor, &str); rd_printf("%08x %S", cursor, str); } } internal void cv_print_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); U64 cursor = 0; U32 inlinee_sig = ~0u; cursor += str8_deserial_read_struct(raw_data, cursor, &inlinee_sig); switch (inlinee_sig) { case CV_C13InlineeLinesSig_NORMAL: { rd_printf("%-8s %-8s %-8s", "Inlinee", "File ID", "Base LN"); for (; cursor < raw_data.size; ) { CV_C13InlineeSourceLineHeader line = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &line); rd_printf("%08x %08x %8u", line.inlinee, line.file_off, line.first_source_ln); } } break; case CV_C13InlineeLinesSig_EXTRA_FILES: { rd_printf("%-8s %-8s %-8s %s", "Inlinee", "File ID", "Base LN", "Extra FileIDs"); for (; cursor < raw_data.size; ) { Temp temp = temp_begin(scratch.arena); CV_C13InlineeSourceLineHeader line = {0}; U32 extra_file_count = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &line); cursor += str8_deserial_read_struct(raw_data, cursor, &extra_file_count); String8List extra_files_list = {0}; for (U32 i = 0; i < extra_file_count; ++i) { U32 file_id = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &file_id); str8_list_pushf(temp.arena, &extra_files_list, "%08x", file_id); } String8 extra_files = str8_list_join(temp.arena, &extra_files_list, &(StringJoin){.sep=str8_lit(" ,")}); rd_printf("%08x %08x %u %S", line.inlinee, line.file_off, line.first_source_ln, extra_files); temp_end(temp); } } break; } scratch_end(scratch); } internal void cv_print_symbols_section(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_ss) { Temp scratch = scratch_begin(&arena, 1); U64 cursor = 0; U32 cv_sig = 0; cursor += str8_deserial_read_struct(raw_ss, cursor, &cv_sig); for (; cursor < raw_ss.size; ) { U64 sst_offset = 0; CV_C13SubSectionHeader ss_header = {0}; char *ss_ver = "???"; switch (cv_sig) { case CV_Signature_C6: { rd_printf("TODO: C6"); } break; case CV_Signature_C7: { rd_printf("TODO: C7"); } break; case CV_Signature_C11: { ss_header.kind = CV_C13SubSectionKind_Symbols; ss_header.size = raw_ss.size - sizeof(cv_sig); ss_ver = "C11"; } break; case CV_Signature_C13: { sst_offset = cursor; cursor += str8_deserial_read_struct(raw_ss, cursor, &ss_header); ss_ver = "C13"; } break; } U64 sst_end = cursor + ss_header.size; String8 raw_sst = str8_substr(raw_ss, rng_1u64(cursor, sst_end)); cursor = AlignPow2(sst_end, CV_C13SubSectionAlign); rd_printf("# %S %s [%llx-%llx)", cv_string_from_c13_subsection_kind(ss_header.kind), ss_ver, sst_offset, sst_end); rd_indent(); switch (ss_header.kind) { case CV_C13SubSectionKind_Symbols: { cv_print_symbols_c13(arena, out, indent, arch, raw_sst); rd_newline(); } break; case CV_C13SubSectionKind_Lines: { cv_print_lines_c13(arena, out, indent, raw_sst); rd_newline(); } break; case CV_C13SubSectionKind_FileChksms: { cv_print_file_checksums(arena, out, indent, raw_sst); rd_newline(); } break; case CV_C13SubSectionKind_StringTable: { cv_print_string_table(arena, out, indent, raw_sst); rd_newline(); } break; case CV_C13SubSectionKind_InlineeLines: { cv_print_inlinee_lines(arena, out, indent, raw_sst); rd_newline(); } break; case CV_C13SubSectionKind_FrameData: case CV_C13SubSectionKind_CrossScopeImports: case CV_C13SubSectionKind_CrossScopeExports: case CV_C13SubSectionKind_IlLines: case CV_C13SubSectionKind_FuncMDTokenMap: case CV_C13SubSectionKind_TypeMDTokenMap: case CV_C13SubSectionKind_MergedAssemblyInput: case CV_C13SubSectionKind_CoffSymbolRVA: case CV_C13SubSectionKind_XfgHashType: case CV_C13SubSectionKind_XfgHashVirtual: default: { rd_printf("TODO"); } break; } rd_unindent(); } scratch_end(scratch); } internal void cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *sections) { CV_Arch arch = ~0; { B32 keep_parsing = 1; for (U64 i = 0; i < section_count && keep_parsing; ++i) { COFF_SectionHeader *header = §ions[i]; String8 sect_name = coff_name_from_section_header(string_table, header); Rng1U64 sect_frange = rng_1u64(header->foff, header->foff+header->fsize); String8 raw_sect = str8_substr(raw_image, sect_frange); if (str8_match_lit(".debug$S", sect_name, 0)) { Temp scratch = scratch_begin(&arena, 1); CV_DebugS debug_s = cv_parse_debug_s(scratch.arena, raw_sect); for (String8Node *string_n = debug_s.data_list[CV_C13SubSectionIdxKind_Symbols].first; string_n != 0 && keep_parsing; string_n = string_n->next) { Temp temp = temp_begin(scratch.arena); CV_SymbolList symbol_list = {0}; cv_parse_symbol_sub_section(temp.arena, &symbol_list, 0, string_n->string, CV_SymbolAlign); for (CV_SymbolNode *symbol_n = symbol_list.first; symbol_n != 0 && keep_parsing; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; if (symbol.kind == CV_SymKind_COMPILE) { if (symbol.data.size >= sizeof(CV_SymCompile)) { CV_SymCompile *comp = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*comp)); arch = comp->machine; } else { rd_printf("not enough bytes to read S_COMPILE"); } keep_parsing = 0; } else if (symbol.kind == CV_SymKind_COMPILE2) { if (symbol.data.size >= sizeof(CV_SymCompile2)) { CV_SymCompile2 *comp = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*comp)); arch = comp->machine; } else { rd_printf("not enough bytes to read S_COMPILE2"); } keep_parsing = 0; } else if (symbol.kind == CV_SymKind_COMPILE3) { if (symbol.data.size >= sizeof(CV_SymCompile3)) { CV_SymCompile3 *comp = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*comp)); arch = comp->machine; } else { rd_printf("not enough bytes to read S_COMPILE3"); } keep_parsing = 0; } } temp_end(temp); } scratch_end(scratch); } } } for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ions[i]; String8 sect_name = coff_name_from_section_header(string_table, header); Rng1U64 sect_frange = rng_1u64(header->foff, header->foff+header->fsize); String8 raw_sect = str8_substr(raw_image, sect_frange); if (str8_match_lit(".debug$S", sect_name, 0)) { rd_printf("# .debug$S No. %llx", i+1); rd_indent(); cv_print_symbols_section(arena, out, indent, arch, raw_sect); rd_unindent(); } else if (str8_match_lit(".debug$T", sect_name, 0)) { Temp scratch = scratch_begin(&arena, 1); CV_Signature sig = 0; str8_deserial_read_struct(raw_sect, 0, &sig); String8 raw_types = str8_skip(raw_sect, sizeof(sig)); CV_DebugT debug_t = {0}; if (sig == CV_Signature_C13) { debug_t = cv_debug_t_from_data(scratch.arena, raw_types, CV_LeafAlign); } else { NotImplemented; } rd_printf("# .debug$T No. %llx", i+1); rd_indent(); cv_print_debug_t(arena, out, indent, debug_t); rd_unindent(); scratch_end(scratch); } } } // MSVC CRT internal void mscrt_print_eh_handler_type32(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, MSCRT_EhHandlerType32 *handler) { Temp scratch = scratch_begin(&arena, 1); String8 catch_line = rd_format_line_from_voff(scratch.arena, rdi, handler->catch_handler_voff, PathStyle_WindowsAbsolute); String8 adjectives_str = mscrt_string_from_eh_adjectives(scratch.arena, handler->adjectives); rd_printf("Adjectives : %#x (%S)", handler->adjectives, adjectives_str); rd_printf("Descriptor : %#x", handler->descriptor_voff); rd_printf("Catch Object Frame Offset: %#x", handler->catch_obj_frame_offset); rd_printf("Catch Handler : %#x%s%S", handler->catch_handler_voff, catch_line.size ? " " : "", catch_line); rd_printf("Delta to FP Handler : %#x", handler->fp_distance); scratch_end(scratch); } //////////////////////////////// //~ PE internal void pe_print_data_directory_ranges(Arena *arena, String8List *out, String8 indent, U64 count, PE_DataDirectory *dirs) { Temp scratch = scratch_begin(&arena, 1); rd_printf("# Data Directories"); rd_indent(); for (U64 i = 0; i < count; ++i) { String8 dir_name; if (i < PE_DataDirectoryIndex_COUNT) { dir_name = pe_string_from_data_directory_index(i); } else { dir_name = push_str8f(scratch.arena, "%#x", i); } rd_printf("%-16S [%08x-%08x) %m", dir_name, dirs[i].virt_off, dirs[i].virt_off+dirs[i].virt_size, dirs[i].virt_size); } rd_unindent(); scratch_end(scratch); } internal void pe_print_optional_header32(Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32 *opt_header, PE_DataDirectory *dirs) { Temp scratch = scratch_begin(&arena, 1); String8 subsystem = pe_string_from_subsystem(opt_header->subsystem); String8 dll_chars = pe_string_from_dll_characteristics(scratch.arena, opt_header->dll_characteristics); rd_printf("# PE Optional Header 32"); rd_indent(); rd_printf("Magic : %#x", opt_header->magic); rd_printf("Linker version : %u.%u", opt_header->major_linker_version, opt_header->minor_linker_version); rd_printf("Size of code : %#-8x (%m)", opt_header->sizeof_code, opt_header->sizeof_code); rd_printf("Size of inited data : %#-8x (%m)", opt_header->sizeof_inited_data, opt_header->sizeof_inited_data); rd_printf("Size of uninited data: %#-8x (%m)", opt_header->sizeof_uninited_data, opt_header->sizeof_uninited_data); rd_printf("Entry point : %#x", opt_header->entry_point_va); rd_printf("Code base : %#x", opt_header->code_base); rd_printf("Data base : %#x", opt_header->data_base); rd_printf("Image base : %#x", opt_header->image_base); rd_printf("Section align : %#x", opt_header->section_alignment); rd_printf("File align : %#x", opt_header->file_alignment); rd_printf("OS version : %u.%u", opt_header->major_os_ver, opt_header->minor_os_ver); rd_printf("Image Version : %u.%u", opt_header->major_img_ver, opt_header->minor_img_ver); rd_printf("Subsystem version : %u.%u", opt_header->major_subsystem_ver, opt_header->minor_subsystem_ver); rd_printf("Win32 version : %u", opt_header->win32_version_value); rd_printf("Size of image : %#x (%m)", opt_header->sizeof_image, opt_header->sizeof_image); rd_printf("Size of headers : %#x (%m)", opt_header->sizeof_headers, opt_header->sizeof_headers); rd_printf("Checksum : %#x", opt_header->check_sum); rd_printf("Subsystem : %#x (%S)", opt_header->subsystem, subsystem); rd_printf("DLL Characteristics : %#x (%S)", opt_header->dll_characteristics, dll_chars); rd_printf("Stack reserve : %#-8x (%m)", opt_header->sizeof_stack_reserve, opt_header->sizeof_stack_reserve); rd_printf("Stack commit : %#-8x (%m)", opt_header->sizeof_stack_commit, opt_header->sizeof_stack_commit); rd_printf("Heap reserve : %#-8x (%m)", opt_header->sizeof_heap_reserve, opt_header->sizeof_heap_reserve); rd_printf("Heap commit : %#-8x (%m)", opt_header->sizeof_heap_commit, opt_header->sizeof_heap_commit); rd_printf("Loader flags : %#x", opt_header->loader_flags); rd_printf("RVA and offset count : %u", opt_header->data_dir_count); rd_newline(); pe_print_data_directory_ranges(arena, out, indent, opt_header->data_dir_count, dirs); rd_newline(); rd_unindent(); scratch_end(scratch); } internal void pe_print_optional_header32plus(Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32Plus *opt_header, PE_DataDirectory *dirs) { Temp scratch = scratch_begin(&arena, 1); String8 subsystem = pe_string_from_subsystem(opt_header->subsystem); String8 dll_chars = pe_string_from_dll_characteristics(scratch.arena, opt_header->dll_characteristics); rd_printf("# PE Optional Header 32+"); rd_indent(); rd_printf("Magic : %#x", opt_header->magic); rd_printf("Linker version : %u.%u", opt_header->major_linker_version, opt_header->minor_linker_version); rd_printf("Size of code : %#-8x (%m)", opt_header->sizeof_code, opt_header->sizeof_code); rd_printf("Size of inited data : %#-8x (%m)", opt_header->sizeof_inited_data, opt_header->sizeof_inited_data); rd_printf("Size of uninited data: %#-8x (%m)", opt_header->sizeof_uninited_data, opt_header->sizeof_uninited_data); rd_printf("Entry point : %#x", opt_header->entry_point_va); rd_printf("Code base : %#x", opt_header->code_base); rd_printf("Image base : %#llx", opt_header->image_base); rd_printf("Section align : %#x", opt_header->section_alignment); rd_printf("File align : %#x", opt_header->file_alignment); rd_printf("OS version : %u.%u", opt_header->major_os_ver, opt_header->minor_os_ver); rd_printf("Image Version : %u.%u", opt_header->major_img_ver, opt_header->minor_img_ver); rd_printf("Subsystem version : %u.%u", opt_header->major_subsystem_ver, opt_header->minor_subsystem_ver); rd_printf("Win32 version : %u", opt_header->win32_version_value); rd_printf("Size of image : %#x (%m)", opt_header->sizeof_image, opt_header->sizeof_image); rd_printf("Size of headers : %#x (%m)", opt_header->sizeof_headers, opt_header->sizeof_headers); rd_printf("Checksum : %#x", opt_header->check_sum); rd_printf("Subsystem : %#llx (%S)", opt_header->subsystem, subsystem); rd_printf("DLL Characteristics : %#llx (%S)", opt_header->dll_characteristics, dll_chars); rd_printf("Stack reserve : %#-8llx (%M)", opt_header->sizeof_stack_reserve, opt_header->sizeof_stack_reserve); rd_printf("Stack commit : %#-8llx (%M)", opt_header->sizeof_stack_commit, opt_header->sizeof_stack_commit); rd_printf("Heap reserve : %#-8llx (%M)", opt_header->sizeof_heap_reserve, opt_header->sizeof_heap_reserve); rd_printf("Heap commit : %#-8llx (%M)", opt_header->sizeof_heap_commit, opt_header->sizeof_heap_commit); rd_printf("Loader flags : %#x", opt_header->loader_flags); rd_printf("RVA and offset count : %u", opt_header->data_dir_count); rd_newline(); pe_print_data_directory_ranges(arena, out, indent, opt_header->data_dir_count, dirs); rd_newline(); rd_unindent(); scratch_end(scratch); } internal void pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadConfig32 *lc) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, lc->time_stamp); String8 global_flag_clear = pe_string_from_global_flags(scratch.arena, lc->global_flag_clear); String8 global_flag_set = pe_string_from_global_flags(scratch.arena, lc->global_flag_set); rd_printf("# Load Config 32"); rd_indent(); rd_printf("Size: %m", lc->size); rd_printf("Time stamp: %#x (%S)", lc->time_stamp, time_stamp); rd_printf("Version: %u.%u", lc->major_version, lc->minor_version); rd_printf("Global flag clear: %#x %S", global_flag_clear); rd_printf("Global flag set: %#x %S", global_flag_set); rd_printf("Critical section timeout: %u", lc->critical_section_timeout); rd_printf("Decommit free block threshold: %#x", lc->decommit_free_block_threshold); rd_printf("Decommit total free threshold: %#x", lc->decommit_total_free_threshold); rd_printf("Lock prefix table: %#x", lc->lock_prefix_table); rd_printf("Maximum alloc size: %m", lc->maximum_allocation_size); rd_printf("Virtual memory threshold: %m", lc->virtual_memory_threshold); rd_printf("Process affinity mask: %#x", lc->process_affinity_mask); rd_printf("Process heap flags: %#x", lc->process_heap_flags); rd_printf("CSD version: %u", lc->csd_version); rd_printf("Edit list: %#x", lc->edit_list); rd_printf("Security Cookie: %#x", lc->security_cookie); if (lc->size < OffsetOf(PE_LoadConfig64, seh_handler_table)) { goto exit; } rd_newline(); rd_printf("SEH Handler Table: %#x", lc->seh_handler_table); rd_printf("SEH Handler Count: %u", lc->seh_handler_count); if (lc->size < OffsetOf(PE_LoadConfig64, guard_cf_check_func_ptr)) { goto exit; } rd_newline(); rd_printf("Guard CF Check Function: %#x", lc->guard_cf_check_func_ptr); rd_printf("Guard CF Dispatch Function: %#x", lc->guard_cf_dispatch_func_ptr); rd_printf("Guard CF Function Table: %#x", lc->guard_cf_func_table); rd_printf("Guard CF Function Count: %u", lc->guard_cf_func_count); rd_printf("Guard Flags: %#x", lc->guard_flags); if (lc->size < OffsetOf(PE_LoadConfig64, code_integrity)) { goto exit; } rd_newline(); rd_printf("Code integrity: { Flags = %#x, Catalog = %#x, Catalog Offset = %#x }", lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); rd_printf("Guard address taken IAT entry table: %#x", lc->guard_address_taken_iat_entry_table); rd_printf("Guard address taken IAT entry count: %u", lc->guard_address_taken_iat_entry_count); rd_printf("Guard long jump target table: %#x", lc->guard_long_jump_target_table); rd_printf("Guard long jump target count: %u", lc->guard_long_jump_target_count); rd_printf("Dynamic value reloc table: %#x", lc->dynamic_value_reloc_table); rd_printf("CHPE Metadata ptr: %#x", lc->chpe_metadata_ptr); rd_printf("Guard RF failure routine: %#x", lc->guard_rf_failure_routine); rd_printf("Guard RF failure routine func ptr: %#x", lc->guard_rf_failure_routine_func_ptr); rd_printf("Dynamic value reloc section: %#x", lc->dynamic_value_reloc_table_section); rd_printf("Dynamic value reloc section offset: %#x", lc->dynamic_value_reloc_table_offset); rd_printf("Guard RF verify SP func ptr: %#x", lc->guard_rf_verify_stack_pointer_func_ptr); rd_printf("Hot patch table offset: %#x", lc->hot_patch_table_offset); if (lc->size < OffsetOf(PE_LoadConfig64, enclave_config_ptr)) { goto exit; } rd_newline(); rd_printf("Enclave config ptr: %#x", lc->enclave_config_ptr); rd_printf("Volatile metadata ptr: %#x", lc->volatile_metadata_ptr); rd_printf("Guard EH continuation table: %#x", lc->guard_eh_continue_table); rd_printf("Guard EH continuation count: %u", lc->guard_eh_continue_count); rd_printf("Guard XFG check func ptr: %#x", lc->guard_xfg_check_func_ptr); rd_printf("Guard XFG dispatch func ptr: %#x", lc->guard_xfg_dispatch_func_ptr); rd_printf("Guard XFG table dispatch func ptr: %#x", lc->guard_xfg_table_dispatch_func_ptr); rd_printf("Cast guard OS determined failure mode: %#x", lc->cast_guard_os_determined_failure_mode); rd_newline(); exit:; rd_unindent(); scratch_end(scratch); } internal void pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadConfig64 *lc) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, lc->time_stamp); String8 global_flag_clear = pe_string_from_global_flags(scratch.arena, lc->global_flag_clear); String8 global_flag_set = pe_string_from_global_flags(scratch.arena, lc->global_flag_set); rd_printf("# Load Config 64"); rd_indent(); rd_printf("Size: %m", lc->size); rd_printf("Time stamp: %#x (%S)", lc->time_stamp, time_stamp); rd_printf("Version: %u.%u", lc->major_version, lc->minor_version); rd_printf("Global flag clear: %#x %S", lc->global_flag_clear, global_flag_clear); rd_printf("Global flag set: %#x %S", lc->global_flag_set, global_flag_set); rd_printf("Critical section timeout: %u", lc->critical_section_timeout); rd_printf("Decommit free block threshold: %#llx", lc->decommit_free_block_threshold); rd_printf("Decommit total free threshold: %#llx", lc->decommit_total_free_threshold); rd_printf("Lock prefix table: %#llx", lc->lock_prefix_table); rd_printf("Maximum alloc size: %M", lc->maximum_allocation_size); rd_printf("Virtual memory threshold: %M", lc->virtual_memory_threshold); rd_printf("Process affinity mask: %#x", lc->process_affinity_mask); rd_printf("Process heap flags: %#x", lc->process_heap_flags); rd_printf("CSD version: %u", lc->csd_version); rd_printf("Edit list: %#llx", lc->edit_list); rd_printf("Security Cookie: %#llx", lc->security_cookie); if (lc->size < OffsetOf(PE_LoadConfig64, seh_handler_table)) { goto exit; } rd_newline(); rd_printf("SEH Handler Table: %#llx", lc->seh_handler_table); rd_printf("SEH Handler Count: %llu", lc->seh_handler_count); if (lc->size < OffsetOf(PE_LoadConfig64, guard_cf_check_func_ptr)) { goto exit; } rd_newline(); rd_printf("Guard CF Check Function: %#llx", lc->guard_cf_check_func_ptr); rd_printf("Guard CF Dispatch Function: %#llx", lc->guard_cf_dispatch_func_ptr); rd_printf("Guard CF Function Table: %#llx", lc->guard_cf_func_table); rd_printf("Guard CF Function Count: %llu", lc->guard_cf_func_count); rd_printf("Guard Flags: %#x", lc->guard_flags); if (lc->size < OffsetOf(PE_LoadConfig64, code_integrity)) { goto exit; } rd_newline(); rd_printf("Code integrity: { Flags = %#x, Catalog = %#x, Catalog Offset = %#x }", lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); rd_printf("Guard address taken IAT entry table: %#llx", lc->guard_address_taken_iat_entry_table); rd_printf("Guard address taken IAT entry count: %llu", lc->guard_address_taken_iat_entry_count); rd_printf("Guard long jump target table: %#llx", lc->guard_long_jump_target_table); rd_printf("Guard long jump target count: %llu", lc->guard_long_jump_target_count); rd_printf("Dynamic value reloc table: %#llx", lc->dynamic_value_reloc_table); rd_printf("CHPE Metadata ptr: %#llx", lc->chpe_metadata_ptr); rd_printf("Guard RF failure routine: %#llx", lc->guard_rf_failure_routine); rd_printf("Guard RF failure routine func ptr: %#llx", lc->guard_rf_failure_routine_func_ptr); rd_printf("Dynamic value reloc section: %#llx", lc->dynamic_value_reloc_table_section); rd_printf("Dynamic value reloc section offset: %#llx", lc->dynamic_value_reloc_table_offset); rd_printf("Guard RF verify SP func ptr: %#llx", lc->guard_rf_verify_stack_pointer_func_ptr); rd_printf("Hot patch table offset: %#llx", lc->hot_patch_table_offset); if (lc->size < OffsetOf(PE_LoadConfig64, enclave_config_ptr)) { goto exit; } rd_newline(); rd_printf("Enclave config ptr: %#llx", lc->enclave_config_ptr); rd_printf("Volatile metadata ptr: %#llx", lc->volatile_metadata_ptr); rd_printf("Guard EH continuation table: %#llx", lc->guard_eh_continue_table); rd_printf("Guard EH continuation count: %llu", lc->guard_eh_continue_count); rd_printf("Guard XFG check func ptr: %#llx", lc->guard_xfg_check_func_ptr); rd_printf("Guard XFG dispatch func ptr: %#llx", lc->guard_xfg_dispatch_func_ptr); rd_printf("Guard XFG table dispatch func ptr: %#llx", lc->guard_xfg_table_dispatch_func_ptr); rd_printf("Cast guard OS determined failure mode: %#llx", lc->cast_guard_os_determined_failure_mode); rd_newline(); exit:; rd_unindent(); scratch_end(scratch); } internal void pe_print_tls(Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls) { Temp scratch = scratch_begin(&arena, 1); rd_printf("# TLS"); rd_indent(); String8 tls_chars = coff_string_from_section_flags(scratch.arena, tls.header.characteristics); rd_printf("Raw data start: %#llx", tls.header.raw_data_start); rd_printf("Raw data end: %#llx", tls.header.raw_data_end); rd_printf("Index address: %#llx", tls.header.index_address); rd_printf("Callbacks address: %#llx", tls.header.callbacks_address); rd_printf("Zero-fill size: %m", tls.header.zero_fill_size); rd_printf("Characteristics: %S", tls_chars); if (tls.callback_count) { rd_newline(); rd_printf("## Callbacks"); rd_indent(); for (U64 i = 0; i < tls.callback_count; ++i) { rd_printf("%#llx", tls.callback_addrs[i]); } rd_unindent(); } rd_unindent(); rd_newline(); scratch_end(scratch); } internal void pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir) { Temp scratch = scratch_begin(&arena, 1); rd_printf("# Debug Directory"); rd_indent(); PE_DebugInfoList debug_info_list = pe_debug_info_list_from_raw_debug_dir(scratch.arena, raw_data, raw_dir); U64 i = 0; for (PE_DebugInfoNode *entry = debug_info_list.first; entry != 0; entry = entry->next, ++i) { PE_DebugInfo *de = &entry->v; if (entry != debug_info_list.first) { rd_newline(); } rd_printf("Entry[%llu]", i); rd_indent(); // print header rd_printf("Characteristics: %#x", de->header.characteristics); rd_printf("Time Stamp: %S", coff_string_from_time_stamp(scratch.arena, de->header.time_stamp)); rd_printf("Version: %u.%u", de->header.major_ver, de->header.minor_ver); rd_printf("Type: %S", pe_string_from_debug_directory_type(de->header.type)); rd_printf("Size: %u", de->header.size); rd_printf("Data virt off: %#x", de->header.voff); rd_printf("Data file off: %#x", de->header.foff); rd_newline(); // print directory contents rd_indent(); switch (de->header.type) { case PE_DebugDirectoryType_ILTCG: case PE_DebugDirectoryType_MPX: case PE_DebugDirectoryType_EXCEPTION: case PE_DebugDirectoryType_FIXUP: case PE_DebugDirectoryType_OMAP_TO_SRC: case PE_DebugDirectoryType_OMAP_FROM_SRC: case PE_DebugDirectoryType_BORLAND: case PE_DebugDirectoryType_CLSID: case PE_DebugDirectoryType_REPRO: case PE_DebugDirectoryType_EX_DLLCHARACTERISTICS: { NotImplemented; } break; case PE_DebugDirectoryType_COFF_GROUP: { U64 off = 0; // TODO: is this version? U32 unknown = 0; off += str8_deserial_read_struct(de->u.raw_data, off, &unknown); if (unknown != 0) { rd_printf("TODO: unknown: %u", unknown); } rd_printf("%-8s %-8s %-8s", "VOFF", "Size", "Name"); for (; off < de->u.raw_data.size; ) { U32 voff = 0; U32 size = 0; String8 name = str8_zero(); off += str8_deserial_read_struct(de->u.raw_data, off, &voff); off += str8_deserial_read_struct(de->u.raw_data, off, &size); if (voff == 0 && size == 0) { break; } off += str8_deserial_read_cstr(de->u.raw_data, off, &name); off = AlignPow2(off, 4); rd_printf("%08x %08x %S", voff, size, name); } } break; case PE_DebugDirectoryType_VC_FEATURE: { MSCRT_VCFeatures *feat = str8_deserial_get_raw_ptr(de->u.raw_data, 0, sizeof(*feat)); if (feat) { rd_printf("Pre-VC++ 11.0: %u", feat->pre_vcpp); rd_printf("C/C++: %u", feat->c_cpp); rd_printf("/GS: %u", feat->gs); rd_printf("/sdl: %u", feat->sdl); rd_printf("guardN: %u", feat->guard_n); } else { rd_errorf("not enough bytes to read VC Features"); } } break; case PE_DebugDirectoryType_FPO: { PE_DebugFPO *fpo = str8_deserial_get_raw_ptr(de->u.raw_data, 0, sizeof(*fpo)); if (fpo) { U8 prolog_size = PE_FPOEncoded_Extract_PROLOG_SIZE(fpo->flags); U8 saved_regs_size = PE_FPOEncoded_Extract_SAVED_REGS_SIZE(fpo->flags); PE_FPOType type = PE_FPOEncoded_Extract_FRAME_TYPE(fpo->flags); PE_FPOFlags flags = PE_FPOEncoded_Extract_FLAGS(fpo->flags); String8 type_string = pe_string_from_fpo_type(type); String8 flags_string = pe_string_from_fpo_flags(scratch.arena, flags); rd_printf("Function offset: %#x", fpo->func_code_off); rd_printf("Function size: %#x", fpo->func_size); rd_printf("Locals size: %u", fpo->locals_size); rd_printf("Params size: %u", fpo->params_size); rd_printf("Prolog size: %u", prolog_size); rd_printf("Saved regs size: %u", saved_regs_size); rd_printf("Type: %S", type_string); rd_printf("Flags: %S", flags_string); } else { rd_errorf("not enough bytes to read FPO"); } } break; case PE_DebugDirectoryType_CODEVIEW: { switch (de->u.codeview.magic) { case PE_CODEVIEW_PDB20_MAGIC: { PE_CvHeaderPDB20 *header = &de->u.codeview.pdb20.header; rd_printf("Time stamp: %S", coff_string_from_time_stamp(scratch.arena, header->time_stamp)); rd_printf("Age: %u", header->age); rd_printf("Name: %S", de->u.codeview.pdb20.path); } break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 *header = &de->u.codeview.pdb70.header; rd_printf("GUID: %S", string_from_guid(scratch.arena, header->guid)); rd_printf("Age: %u", header->age); rd_printf("Name: %S", de->u.codeview.pdb70.path); } break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI *header = &de->u.codeview.rdi.header; rd_printf("GUID: %S", string_from_guid(scratch.arena, header->guid)); rd_printf("Name: %S", de->u.codeview.rdi.path); } break; default: { rd_errorf("unknown CodeView magic %#x", de->u.codeview.magic); } break; } } break; case PE_DebugDirectoryType_MISC: { PE_DebugMisc *misc = str8_deserial_get_raw_ptr(de->u.raw_data, 0, sizeof(*misc)); String8 type_string = pe_string_from_misc_type(misc->data_type); rd_printf("Data type: %S", type_string); rd_printf("Size: %u", misc->size); rd_printf("Unicode: %u", misc->unicode); switch (misc->data_type) { case PE_DebugMiscType_EXE_NAME: { String8 name; str8_deserial_read_cstr(de->u.raw_data, sizeof(*misc), &name); rd_printf("Name: %S", name); } break; default: { rd_printf("???"); } break; } } break; } rd_unindent(); rd_unindent(); } rd_unindent(); rd_newline(); scratch_end(scratch); } internal void pe_print_export_table(Arena *arena, String8List *out, String8 indent, PE_ParsedExportTable exptab) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, exptab.time_stamp); rd_printf("# Export Table"); rd_indent(); rd_printf("Characteristics: %u", exptab.flags); rd_printf("Time stamp: %S", time_stamp); rd_printf("Version: %u.%02u", exptab.major_ver, exptab.minor_ver); rd_printf("Ordinal base: %u", exptab.ordinal_base); rd_printf(""); rd_printf("%-4s %-8s %-8s %-8s", "No.", "Oridnal", "VOff", "Name"); for (U64 i = 0; i < exptab.export_count; ++i) { PE_ParsedExport *exp = exptab.exports+i; if (exp->forwarder.size) { rd_printf("%4u %8u %8x %S (forwarded to %S)", i, exp->ordinal, exp->voff, exp->name, exp->forwarder); } else { rd_printf("%4u %8u %8x %S", i, exp->ordinal, exp->voff, exp->name); } } rd_unindent(); scratch_end(scratch); } internal void pe_print_static_import_table(Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedStaticImportTable imptab) { Temp scratch = scratch_begin(&arena, 1); if (imptab.count) { rd_printf("# Import Table"); rd_indent(); for (U64 dll_idx = 0; dll_idx < imptab.count; ++dll_idx) { PE_ParsedStaticDLLImport *dll = imptab.v+dll_idx; rd_printf("Name: %S", dll->name); rd_printf("Import address table: %#llx", image_base + dll->import_address_table_voff); rd_printf("Import name table: %#llx", image_base + dll->import_name_table_voff); rd_printf("Time stamp: %#x", dll->time_stamp); rd_newline(); if (dll->import_count) { rd_indent(); for (U64 imp_idx = 0; imp_idx < dll->import_count; ++imp_idx) { PE_ParsedImport *imp = dll->imports+imp_idx; if (imp->type == PE_ParsedImport_Ordinal) { rd_printf("%#-6x", imp->u.ordinal); } else if (imp->type == PE_ParsedImport_Name) { rd_printf("%#-6x %S", imp->u.name.hint, imp->u.name.string); } } rd_unindent(); rd_newline(); } } rd_unindent(); } scratch_end(scratch); } internal void pe_print_delay_import_table(Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedDelayImportTable imptab) { if (imptab.count) { Temp scratch = scratch_begin(&arena, 1); rd_printf("# Delay Import Table"); rd_indent(); for (U64 dll_idx = 0; dll_idx < imptab.count; ++dll_idx) { PE_ParsedDelayDLLImport *dll = imptab.v+dll_idx; rd_printf("Attributes: %#08x", dll->attributes); rd_printf("Name: %S", dll->name); rd_printf("HMODULE address: %#llx", dll->module_handle_voff ? image_base + dll->module_handle_voff : 0); rd_printf("Import address table: %#llx", dll->iat_voff ? image_base + dll->iat_voff : 0); rd_printf("Import name table: %#llx", dll->name_table_voff ? image_base + dll->name_table_voff : 0); rd_printf("Bound import name table: %#llx", dll->bound_table_voff ? image_base + dll->bound_table_voff : 0); rd_printf("Unload import name table: %#llx", dll->unload_table_voff ? image_base + dll->unload_table_voff : 0); rd_printf("Time stamp: %#x", dll->time_stamp); rd_newline(); rd_indent(); rd_printf("%-16s %-16s %-8s %s", "BIAT", "UIAT", "Hint/Ord", "Name"); rd_printf("---------------- ---------------- -------- ----"); for (U64 imp_idx = 0; imp_idx < dll->import_count; ++imp_idx) { PE_ParsedImport *imp = dll->imports+imp_idx; String8 bound = str8_lit("NULL"); if (imp_idx < dll->bound_table_count) { U64 bound_addr = dll->bound_table[imp_idx]; bound = push_str8f(scratch.arena, "%#llx", bound_addr); } String8 unload = str8_lit("NULL"); if (imp_idx < dll->unload_table_count) { U64 unload_addr = dll->unload_table[imp_idx]; unload = push_str8f(scratch.arena, "%#llx", unload_addr); } if (imp->type == PE_ParsedImport_Ordinal) { rd_printf("%-16S %-16S 0x%-6x %S", bound, unload, imp->u.ordinal, str8_lit("[NONAME]")); } else if (imp->type == PE_ParsedImport_Name) { rd_printf("%-16S %-16S 0x%-6x %S", bound, unload, imp->u.name.hint, imp->u.name.string); } } rd_unindent(); rd_newline(); } rd_unindent(); scratch_end(scratch); } } internal void pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDir *root) { Temp scratch = scratch_begin(&arena, 1); // setup stack struct stack_s { struct stack_s *next; B32 print_table; B32 is_named; PE_ResourceNode *curr_name_node; PE_ResourceNode *curr_id_node; U64 name_idx; U64 id_idx; U64 dir_idx; U64 dir_id; String8 dir_name; PE_ResourceDir *table; } *stack = push_array(scratch.arena, struct stack_s, 1); stack->table = root; stack->print_table = 1; stack->is_named = 1; stack->dir_name = str8_lit("ROOT"); stack->curr_name_node = root->named_list.first; stack->curr_id_node = root->id_list.first; if (stack) { rd_printf("# Resources"); // traverse resource tree while (stack) { if (stack->print_table) { stack->print_table = 0; rd_indent(); if (stack->is_named) { rd_printf("[%u] %S { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", stack->dir_idx, stack->dir_name, stack->table->time_stamp, stack->table->major_version, stack->table->minor_version, stack->table->named_list.count, stack->table->id_list.count, stack->table->characteristics); } else { B32 is_actually_leaf = stack->table->id_list.count == 1 && stack->table->id_list.first->data.kind != PE_ResDataKind_DIR; if (is_actually_leaf) { rd_printf("[%u] %u { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", stack->dir_idx, stack->dir_id, stack->table->time_stamp, stack->table->major_version, stack->table->minor_version, stack->table->named_list.count, stack->table->id_list.count, stack->table->characteristics); } else { String8 id_str = pe_resource_kind_to_string(stack->dir_id); rd_printf("[%u] %S { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", stack->dir_idx, id_str, stack->dir_id, stack->table->time_stamp, stack->table->major_version, stack->table->minor_version, stack->table->named_list.count, stack->table->id_list.count, stack->table->characteristics); } } } while (stack->curr_name_node) { PE_ResourceNode *named_node = stack->curr_name_node; stack->curr_name_node = stack->curr_name_node->next; U64 name_idx = stack->name_idx++; PE_Resource *res = &named_node->data; if (res->kind == PE_ResDataKind_DIR) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); frame->table = res->u.dir; frame->print_table = 1; frame->dir_idx = stack->name_idx; frame->dir_name = res->id.u.string; frame->is_named = 1; frame->curr_name_node = frame->table->named_list.first; frame->curr_id_node = frame->table->id_list.first; SLLStackPush(stack, frame); goto yield; } else if (res->kind == PE_ResDataKind_COFF_LEAF) { COFF_ResourceDataEntry *entry = &res->u.leaf; rd_printf("[%u] %S Data VOFF: %#08x, Data Size: %#08x, Code Page: %u", name_idx, res->id.u.string, entry->data_voff, entry->data_size, entry->code_page); } else { InvalidPath; } } while (stack->curr_id_node) { PE_ResourceNode *id_node = stack->curr_id_node; PE_Resource *res = &id_node->data; stack->curr_id_node = stack->curr_id_node->next; U64 id_idx = stack->id_idx++; if (res->kind == PE_ResDataKind_DIR) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); frame->table = res->u.dir; frame->print_table = 1; frame->dir_idx = stack->table->named_list.count + id_idx; frame->dir_id = res->id.u.number; frame->curr_name_node = frame->table->named_list.first; frame->curr_id_node = frame->table->id_list.first; SLLStackPush(stack, frame); goto yield; } else if (res->kind == PE_ResDataKind_COFF_LEAF) { COFF_ResourceDataEntry *entry = &res->u.leaf; rd_printf("[%u] ID: %u Data VOFF: %#08x, Data Size: %#08x, Code Page: %u", id_idx, res->id.u.number, entry->data_voff, entry->data_size, entry->code_page); } else { InvalidPath; } } if (stack->curr_id_node == 0 && stack->curr_name_node == 0) { rd_unindent(); } SLLStackPop(stack); yield:; } rd_newline(); } scratch_end(scratch); } internal void pe_print_exceptions_x8664(Arena *arena, String8List *out, String8 indent, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); String8 raw_except = str8_substr(raw_data, except_frange); U64 count = raw_except.size / sizeof(PE_IntelPdata); for (U64 i = 0; i < count; ++i) { Temp temp = temp_begin(scratch.arena); U64 pdata_offset = i * sizeof(PE_IntelPdata); PE_IntelPdata *pdata = str8_deserial_get_raw_ptr(raw_except, pdata_offset, sizeof(*pdata)); String8 pdata_name = rd_proc_name_from_voff(rdi, pdata->voff_first); U64 unwind_info_offset = coff_foff_from_voff(sections, section_count, pdata->voff_unwind_info); PE_UnwindInfo *uwinfo = str8_deserial_get_raw_ptr(raw_data, unwind_info_offset, sizeof(*uwinfo)); U8 version = PE_UNWIND_INFO_VERSION_FROM_HDR(uwinfo->header); U8 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(uwinfo->header); U8 frame_register = PE_UNWIND_INFO_REG_FROM_FRAME(uwinfo->frame); U8 frame_offset = PE_UNWIND_INFO_OFF_FROM_FRAME(uwinfo->frame); B32 is_chained = (flags & PE_UnwindInfoFlag_CHAINED) != 0; B32 has_handler_data = !is_chained && (flags & (PE_UnwindInfoFlag_EHANDLER | PE_UnwindInfoFlag_UHANDLER)) != 0; String8 flags_str = str8_zero(); { U64 f = flags; String8List flags_list = {0}; if (f & PE_UnwindInfoFlag_EHANDLER) { f &= ~PE_UnwindInfoFlag_EHANDLER; str8_list_pushf(scratch.arena, &flags_list, "EHANDLER"); } if (f & PE_UnwindInfoFlag_UHANDLER) { f &= ~PE_UnwindInfoFlag_UHANDLER; str8_list_pushf(scratch.arena, &flags_list, "UHANDLER"); } if (f & PE_UnwindInfoFlag_CHAINED) { f &= ~PE_UnwindInfoFlag_CHAINED; str8_list_pushf(scratch.arena, &flags_list, "CHAINED"); } if (f) { str8_list_pushf(scratch.arena, &flags_list, "%#llx", f); } if (flags_list.node_count == 0) { str8_list_pushf(scratch.arena, &flags_list, "%#llx", f); } flags_str = str8_list_join(scratch.arena, &flags_list, &(StringJoin){.sep=str8_lit(", ")}); } U64 codes_offset = unwind_info_offset + sizeof(PE_UnwindInfo); PE_UnwindCode *code_ptr = str8_deserial_get_raw_ptr(raw_data, codes_offset, sizeof(*code_ptr) * uwinfo->codes_num); PE_UnwindCode *code_opl = code_ptr + uwinfo->codes_num; if (i > 0) { rd_newline(); } rd_printf("%08x %08x %08x %08x%s%S", pdata_offset, pdata->voff_first, pdata->voff_one_past_last, pdata->voff_unwind_info, pdata_name.size ? " " : "", pdata_name); rd_printf("Version: %u", version); rd_printf("Flags: %S", flags_str); rd_printf("Prolog Size: %#x", uwinfo->prolog_size); rd_printf("Code Count: %u", uwinfo->codes_num); rd_printf("Frame: %u", uwinfo->frame); rd_printf("Codes:"); rd_indent(); for (; code_ptr < code_opl;) { Temp code_temp = temp_begin(scratch.arena); String8List code_list = {0}; U8 operation_code = PE_UNWIND_OPCODE_FROM_FLAGS(code_ptr[0].flags); U8 operation_info = PE_UNWIND_INFO_FROM_FLAGS(code_ptr[0].flags); str8_list_pushf(code_temp.arena, &code_list, "%#04x:", code_ptr[0].off_in_prolog); switch (operation_code) { case PE_UnwindOpCode_PUSH_NONVOL: { String8 gpr = pe_string_from_unwind_gpr_x64(operation_info); str8_list_pushf(code_temp.arena, &code_list, "PUSH_NONVOL %S", gpr); code_ptr += 1; } break; case PE_UnwindOpCode_ALLOC_LARGE: { U64 size = 0; switch (operation_info) { case 0: { // 136B - 512K size = code_ptr[1].u16*8; } break; case 1: { // 512K - 4GB size = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); } break; default: break; } str8_list_pushf(code_temp.arena, &code_list, "ALLOC_LARGE size=%#x", size); code_ptr += 2; } break; case PE_UnwindOpCode_ALLOC_SMALL: { U64 size = operation_info*8 + 8; str8_list_pushf(code_temp.arena, &code_list, "ALLOC_SMALL size=%#x", size); code_ptr += 1; } break; case PE_UnwindOpCode_SET_FPREG: { U64 offset = frame_offset*16; String8 gpr = pe_string_from_unwind_gpr_x64(frame_register); str8_list_pushf(code_temp.arena, &code_list, "SET_FPREG %S, offset=%#x", gpr, offset); code_ptr += 1; } break; case PE_UnwindOpCode_SAVE_NONVOL: { String8 gpr = pe_string_from_unwind_gpr_x64(operation_info); U64 register_offset = code_ptr[1].u16*8; str8_list_pushf(code_temp.arena, &code_list, "SAVE_NONVOL %S, offset=%#x", gpr, register_offset); code_ptr += 2; } break; case PE_UnwindOpCode_SAVE_NONVOL_FAR: { String8 gpr = pe_string_from_unwind_gpr_x64(operation_info); U64 frame_offset = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); str8_list_pushf(code_temp.arena, &code_list, "SAVE_NONVOL_FAR %S, offset=%#x", gpr, frame_offset); code_ptr += 3; } break; case PE_UnwindOpCode_EPILOG: { str8_list_pushf(code_temp.arena, &code_list, "EPILOG flags=%#x", code_ptr[0].flags); code_ptr += 1; } break; case PE_UnwindOpCode_SPARE_CODE: { str8_list_pushf(code_temp.arena, &code_list, "SPARE_CODE"); code_ptr += 1; } break; case PE_UnwindOpCode_SAVE_XMM128: { String8 gpr = pe_string_from_unwind_gpr_x64(operation_info); U64 register_offset = code_ptr[1].u16*16; str8_list_pushf(code_temp.arena, &code_list, "SAVE_XMM128 %S, offset=%#x", gpr, register_offset); code_ptr += 2; } break; case PE_UnwindOpCode_SAVE_XMM128_FAR: { String8 gpr = pe_string_from_unwind_gpr_x64(operation_info); U64 frame_offset = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16); str8_list_pushf(code_temp.arena, &code_list, "SAVE_XMM128_FAR %S, offset=%#x", gpr, frame_offset); code_ptr += 3; } break; case PE_UnwindOpCode_PUSH_MACHFRAME: { str8_list_pushf(code_temp.arena, &code_list, "PUSH_MACHFRAME %s", operation_info == 1 ? "with error code" : "without error code"); code_ptr += 1; } break; default: { str8_list_pushf(code_temp.arena, &code_list, "UNKNOWN_OPCODE %#x", operation_code); code_ptr += 1; } break; } String8 code_line = str8_list_join(code_temp.arena, &code_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", code_line); temp_end(code_temp); } rd_unindent(); if (is_chained) { U64 next_pdata_offset = codes_offset + sizeof(PE_UnwindCode) * AlignPow2(uwinfo->codes_num, 2); PE_IntelPdata *next_pdata = str8_deserial_get_raw_ptr(raw_data, next_pdata_offset, sizeof(*next_pdata)); rd_printf("Chained: %#08x %#08x %#08x", next_pdata->voff_first, next_pdata->voff_one_past_last, next_pdata->voff_unwind_info); } if (has_handler_data) { #define ExceptionHandlerDataFlag_FuncInfo (1 << 0) #define ExceptionHandlerDataFlag_FuncInfo4 (1 << 1) #define ExceptionHandlerDataFlag_ScopeTable (1 << 2) #define ExceptionHandlerDataFlag_GS (1 << 3u) U64 actual_code_count = PE_UNWIND_INFO_GET_CODE_COUNT(uwinfo->codes_num); U64 read_cursor = codes_offset + actual_code_count * sizeof(PE_UnwindCode); U32 handler = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &handler); String8 handler_name = rd_proc_name_from_voff(rdi, handler); rd_printf("Handler: %#llx%s%S", handler, handler_name.size ? " " : "", handler_name); U32 handler_data_flags = 0; if (str8_match_lit("__GSHandlerCheck_EH4", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo4; } else if (str8_match_lit("__CxxFrameHandler4", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo4; } else if (str8_match_lit("__CxxFrameHandler3", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo; } else if (str8_match_lit("__C_specific_handler", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_ScopeTable; } else if (str8_match_lit("__GSHandlerCheck", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_GS; } else if (str8_match_lit("__GSHandlerCheck_SEH", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_ScopeTable|ExceptionHandlerDataFlag_GS; } else if (str8_match_lit("__GSHandlerCheck_EH", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo|ExceptionHandlerDataFlag_GS; } if (handler_data_flags & ExceptionHandlerDataFlag_FuncInfo) { MSCRT_FuncInfo func_info; read_cursor += mscrt_parse_func_info(arena, raw_data, section_count, sections, read_cursor, &func_info); rd_printf("Function Info:"); rd_indent(); rd_printf("Magic: %#x", func_info.magic); rd_printf("Max State: %u", func_info.max_state); rd_printf("Try Block Count: %u", func_info.try_block_map_count); rd_printf("IP Map Count: %u", func_info.ip_map_count); rd_printf("Frame Offset Unwind Helper: %#x", func_info.frame_offset_unwind_helper); rd_printf("ES Flags: %#x", func_info.eh_flags); rd_unindent(); if (func_info.ip_map_count > 0) { rd_printf("IP to State Map:"); rd_indent(); rd_printf("%8s %8s", "State", "IP"); for (U32 i = 0; i < func_info.ip_map_count; ++i) { MSCRT_IPState32 state = func_info.ip_map[i]; String8 line = rd_format_line_from_voff(scratch.arena, rdi, state.ip, PathStyle_WindowsAbsolute); rd_printf("%8d %08x %S", state.state, state.ip, line); } rd_unindent(); } if (func_info.max_state > 0) { rd_printf("Unwind Map:"); rd_indent(); rd_printf("%13s %10s %8s", "Current State", "Next State", "Action @"); for (U32 i = 0; i < func_info.max_state; ++i) { MSCRT_UnwindMap32 map = func_info.unwind_map[i]; String8 line = rd_format_line_from_voff(scratch.arena, rdi, map.action_virt_off, PathStyle_WindowsAbsolute); rd_printf("%13u %10d %8x %S", i, map.next_state, map.action_virt_off, line); } rd_unindent(); } for (U32 i = 0; i < func_info.try_block_map_count; ++i) { MSCRT_TryMapBlock try_block = func_info.try_block_map[i]; rd_printf("Try Map Block #%u", i); rd_indent(); rd_printf("Try State Low: %u", try_block.try_low); rd_printf("Try State High: %u", try_block.try_high); rd_printf("Catch State High: %u", try_block.catch_high); rd_printf("Catch Count: %u", try_block.catch_handlers_count); rd_printf("Catches:"); rd_indent(); for (U32 ihandler = 0; ihandler < try_block.catch_handlers_count; ++ihandler) { rd_printf("Catch #%u", ihandler); rd_indent(); mscrt_print_eh_handler_type32(arena, out, indent, rdi, &try_block.catch_handlers[ihandler]); rd_unindent(); } rd_unindent(); rd_unindent(); } if (func_info.es_type_list.count) { rd_printf("Exception Specific Types:"); rd_indent(); for (U32 i = 0; i < func_info.es_type_list.count; ++i) { if (i > 0) { rd_newline(); } mscrt_print_eh_handler_type32(arena, out, indent, rdi, &func_info.es_type_list.handlers[i]); } rd_unindent(); } } if (handler_data_flags & ExceptionHandlerDataFlag_FuncInfo4) { U32 func_info_voff = 0, unknown = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &func_info_voff); read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &unknown); U64 func_info_foff = coff_foff_from_voff(sections, section_count, func_info_voff); MSCRT_ParsedFuncInfoV4 func_info = {0}; mscrt_parse_func_info_v4(arena, raw_data, section_count, sections, func_info_foff, pdata->voff_first, &func_info); String8 header_str = str8_zero(); { String8List header_list = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_IsCatch) { str8_list_pushf(scratch.arena, &header_list, "IsCatch"); } if (func_info.header & MSCRT_FuncInfoV4Flag_IsSeparated) { str8_list_pushf(scratch.arena, &header_list, "IsSeparted"); } if (func_info.header & MSCRT_FuncInfoV4Flag_IsBBT) { str8_list_pushf(scratch.arena, &header_list, "IsBBT"); } if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { str8_list_pushf(scratch.arena, &header_list, "UnwindMap"); } if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { str8_list_pushf(scratch.arena, &header_list, "TryBlockMap"); } if (func_info.header & MSCRT_FuncInfoV4Flag_EHs) { str8_list_pushf(scratch.arena, &header_list, "EHs"); } if (func_info.header & MSCRT_FuncInfoV4Flag_NoExcept) { str8_list_pushf(scratch.arena, &header_list, "NoExcept"); } header_str = str8_list_join(scratch.arena, &header_list, &(StringJoin){.sep=str8_lit(", ")}); } rd_printf("Function Info V4:"); rd_indent(); rd_printf("Header: %#x %S", func_info.header, header_str); rd_printf("BBT Flags: %#x", func_info.bbt_flags); MSCRT_IP2State32V4 ip2state_map = func_info.ip2state_map; rd_printf("IP To State Map:"); rd_indent(); rd_printf("%8s %8s", "State", "IP"); for (U32 i = 0; i < ip2state_map.count; ++i) { String8 line_str = rd_format_line_from_voff(scratch.arena, rdi, ip2state_map.voffs[i], PathStyle_WindowsAbsolute); rd_printf("%8d %08X %S", ip2state_map.states[i], ip2state_map.voffs[i], line_str); } rd_unindent(); if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { MSCRT_UnwindMapV4 unwind_map = func_info.unwind_map; rd_printf("Unwind Map:"); rd_indent(); for (U32 i = 0; i < unwind_map.count; ++i) { MSCRT_UnwindEntryV4 *ue = &unwind_map.v[i]; String8 type_str = str8_zero(); switch (ue->type) { case MSCRT_UnwindMapV4Type_NoUW: type_str = str8_lit("NoUW"); break; case MSCRT_UnwindMapV4Type_DtorWithObj: type_str = str8_lit("DtorWithObj"); break; case MSCRT_UnwindMapV4Type_DtorWithPtrToObj: type_str = str8_lit("DtorWithPtrToObj"); break; case MSCRT_UnwindMapV4Type_VOFF: type_str = str8_lit("VOFF"); break; } if (ue->type == MSCRT_UnwindMapV4Type_DtorWithObj || ue->type == MSCRT_UnwindMapV4Type_DtorWithPtrToObj) { rd_printf("[%2u] NextOff=%u Type=%-16S Action=%#08x Object=%#x", i, ue->next_off, type_str, ue->action, ue->object); } else if (ue->type == MSCRT_UnwindMapV4Type_VOFF) { rd_printf("[%2u] NextOff=%u Type=%-16S Action=%#08x", i, ue->next_off, type_str, ue->action); } else { rd_printf("[%2u] NextOff=%u Type=%S", i, ue->next_off, type_str); } } rd_unindent(); } if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { MSCRT_TryBlockMapV4Array try_block_map = func_info.try_block_map; rd_printf("Try/Catch Blocks:"); rd_indent(); for (U32 i = 0; i < try_block_map.count; ++i) { MSCRT_TryBlockMapV4 *try_block = &try_block_map.v[i]; rd_printf("[%2u] TryLow %u TryHigh %u CatchHigh %u", i, try_block->try_low, try_block->try_high, try_block->catch_high); if (try_block->handlers.count) { for (U32 k = 0; k < try_block->handlers.count; ++k) { MSCRT_EhHandlerTypeV4 *handler = &try_block->handlers.v[k]; String8List line_list = {0}; str8_list_pushf(arena, &line_list, " "); str8_list_pushf(arena, &line_list, "CatchCodeVOff=%#08X", handler->catch_code_voff); if (handler->flags & MSCRT_EhHandlerV4Flag_Adjectives) { String8 adjectives = mscrt_string_from_eh_adjectives(arena, handler->adjectives); str8_list_pushf(arena, &line_list, "Adjectives=%S", adjectives); } if (handler->flags & MSCRT_EhHandlerV4Flag_DispType) { str8_list_pushf(arena, &line_list, "TypeVOff=%#x", handler->type_voff); } if (handler->flags & MSCRT_EhHandlerV4Flag_DispCatchObj) { str8_list_pushf(arena, &line_list, "CacthObjVOff=%#x", handler->catch_obj_voff); } if (handler->flags & MSCRT_EhHandlerV4Flag_ContIsVOff) { str8_list_pushf(arena, &line_list, "ContIsVOff"); } for (U32 icont = 0; icont < handler->catch_funclet_cont_addr_count; ++icont) { str8_list_pushf(arena, &line_list, "ContAddr[%u]=%#llx", icont, handler->catch_funclet_cont_addr[icont]); } String8 handler_str = str8_list_join(arena, &line_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", handler_str); } } } rd_unindent(); } } if (handler_data_flags & ExceptionHandlerDataFlag_ScopeTable) { U32 scope_count = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &scope_count); PE_HandlerScope *scopes = str8_deserial_get_raw_ptr(raw_data, read_cursor, sizeof(PE_HandlerScope)*scope_count); read_cursor += scope_count*sizeof(scopes[0]); rd_printf("Count of scope table entries: %u", scope_count); rd_indent(); rd_printf("%-8s %-8s %-8s %-8s", "Begin", "End", "Handler", "Target"); for (U32 i = 0; i < scope_count; ++i) { PE_HandlerScope scope = scopes[i]; rd_printf("%08x %08x %08x %08x", scope.begin, scope.end, scope.handler, scope.target); } rd_unindent(); } if (handler_data_flags & ExceptionHandlerDataFlag_GS) { U32 gs_data = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &gs_data); U32 flags = MSCRT_GSHandler_GetFlags(gs_data); U32 cookie_offset = MSCRT_GSHandler_GetCookieOffset(gs_data); U32 aligned_base_offset = 0; U32 alignment = 0; if (flags & MSCRT_GSHandlerFlag_HasAlignment) { read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &aligned_base_offset); read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &alignment); } String8 flags_str; { String8List flags_list = {0}; if (flags & MSCRT_GSHandlerFlag_EHandler) { str8_list_pushf(arena, &flags_list, "EHandler"); } if (flags & MSCRT_GSHandlerFlag_UHandler) { str8_list_pushf(arena, &flags_list, "UHandler"); } if (flags & MSCRT_GSHandlerFlag_HasAlignment) { str8_list_pushf(arena, &flags_list, "Has Alignment"); } if (flags == 0) { str8_list_pushf(arena, &flags_list, "None"); } flags_str = str8_list_join(arena, &flags_list, &(StringJoin){.sep=str8_lit(", ")}); } rd_printf("GS unwind flags: %S", flags_str); rd_printf("Cookie offset: %x", cookie_offset); if (flags & MSCRT_GSHandlerFlag_HasAlignment) { rd_printf("Aligned base offset: %x", aligned_base_offset); rd_printf("Alignment: %x", alignment); } } #undef ExceptionHandlerDataFlag_FuncInfo #undef ExceptionHandlerDataFlag_ScopeTable #undef ExceptionHandlerDataFlag_GS } temp_end(temp); } scratch_end(scratch); } internal void pe_print_exceptions(Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange, RDI_Parsed *rdi) { if (dim_1u64(except_frange)) { rd_printf("# Exceptions"); rd_indent(); rd_printf("%-8s %-8s %-8s %-8s", "Offset", "Begin", "End", "Unwind Info"); switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X64: case COFF_MachineType_X86: { pe_print_exceptions_x8664(arena, out, indent, section_count, sections, raw_data, except_frange, rdi); } break; default: NotImplemented; break; } rd_unindent(); rd_newline(); } } internal void pe_print_base_relocs(Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 base_reloc_franges, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); String8 raw_base_relocs = str8_substr(raw_data, base_reloc_franges); PE_BaseRelocBlockList base_relocs = pe_base_reloc_block_list_from_data(scratch.arena, raw_base_relocs); if (base_relocs.count) { rd_printf("# Base Relocs"); rd_indent(); U32 addr_size = 0; switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: addr_size = 4; break; case COFF_MachineType_X64: addr_size = 8; break; default: NotImplemented; } // convert blocks to string list U64 iblock = 0; for (PE_BaseRelocBlockNode *node = base_relocs.first; node != 0; node = node->next) { PE_BaseRelocBlock *block = &node->v; rd_printf("Block No. %u, Virt Off %#x, Reloc Count %u", iblock++, block->page_virt_off, block->entry_count); rd_indent(); for (U64 ientry = 0; ientry < block->entry_count; ++ientry) { PE_BaseRelocKind type = PE_BaseRelocKindFromEntry(block->entries[ientry]); U16 offset = PE_BaseRelocOffsetFromEntry(block->entries[ientry]); U64 apply_to_voff = block->page_virt_off + offset; U64 apply_to_foff = coff_foff_from_voff(sections, section_count, apply_to_voff); U64 apply_to = 0; str8_deserial_read(raw_data, apply_to_foff, &apply_to, addr_size, 1); U64 addr = image_base + apply_to; const char *type_str = "???"; switch (type) { case PE_BaseRelocKind_ABSOLUTE: type_str = "ABS"; break; case PE_BaseRelocKind_HIGH: type_str = "HIGH"; break; case PE_BaseRelocKind_LOW: type_str = "LOW"; break; case PE_BaseRelocKind_HIGHLOW: type_str = "HIGHLOW"; break; case PE_BaseRelocKind_HIGHADJ: type_str = "HIGHADJ"; break; case PE_BaseRelocKind_DIR64: type_str = "DIR64"; break; default: { switch (machine) { case COFF_MachineType_Arm: case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: { switch (type) { case PE_BaseRelocKind_ARM_MOV32: type_str = "ARM_MOV32"; break; case PE_BaseRelocKind_THUMB_MOV32: type_str = "THUMB_MOV32"; break; default: NotImplemented; } } break; // TODO: mips, loong, risc-v } } break; } if (type == PE_BaseRelocKind_ABSOLUTE) { rd_printf("%-4x %-12s", offset, type_str); } else { U64 reloc_voff = apply_to - image_base; String8 name = rd_format_proc_line(scratch.arena, rdi, reloc_voff); rd_printf("%-4x %-12s %016llx%s%S", offset, type_str, apply_to, name.size ? " " : "", name); } } rd_unindent(); rd_newline(); } rd_unindent(); } scratch_end(scratch); } internal void pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); PE_DosHeader *dos_header = str8_deserial_get_raw_ptr(raw_data, 0, sizeof(*dos_header)); if (!dos_header) { rd_errorf("not enough bytes to read DOS header"); goto exit; } Assert(dos_header->magic == PE_DOS_MAGIC); U32 pe_magic = 0; str8_deserial_read_struct(raw_data, dos_header->coff_file_offset, &pe_magic); if (pe_magic != PE_MAGIC) { rd_errorf("PE magic check failure, input file is not of PE format"); goto exit; } U64 file_header_off = dos_header->coff_file_offset+sizeof(pe_magic); COFF_FileHeader *file_header = str8_deserial_get_raw_ptr(raw_data, file_header_off, sizeof(*file_header)); if (!file_header) { rd_errorf("not enough bytes to read COFF header"); goto exit; } U64 opt_header_off = file_header_off + sizeof(*file_header); U16 opt_header_magic = 0; str8_deserial_read_struct(raw_data, opt_header_off, &opt_header_magic); if (opt_header_magic != PE_PE32_MAGIC && opt_header_magic != PE_PE32PLUS_MAGIC) { rd_errorf("unexpected optional header magic %#x", opt_header_magic); goto exit; } if (opt_header_magic == PE_PE32_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32)) { rd_errorf("unexpected optional header size in COFF header %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32)); goto exit; } if (opt_header_magic == PE_PE32PLUS_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32Plus)) { rd_errorf("unexpected optional header size %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32Plus)); goto exit; } U64 sections_off = file_header_off + sizeof(*file_header) + file_header->optional_header_size; COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sections_off, sizeof(*sections)*file_header->section_count); if (!sections) { rd_errorf("not enough bytes to read COFF section headers"); goto exit; } U64 string_table_off = file_header->symbol_table_foff + sizeof(COFF_Symbol16) * file_header->symbol_count; String8 raw_string_table = str8_substr(raw_data, rng_1u64(string_table_off, raw_data.size)); COFF_Symbol32Array symbols = coff_symbol_array_from_data_16(scratch.arena, raw_data, file_header->symbol_table_foff, file_header->symbol_count); U8 *raw_opt_header = push_array(scratch.arena, U8, file_header->optional_header_size); str8_deserial_read_array(raw_data, opt_header_off, raw_opt_header, file_header->optional_header_size); if (opts & RD_Option_Headers) { coff_print_file_header(arena, out, indent, file_header); rd_newline(); } Arch arch = arch_from_coff_machine(file_header->machine); U64 image_base = 0; U64 dir_count = 0; PE_DataDirectory *dirs = 0; if (opt_header_magic == PE_PE32_MAGIC) { PE_OptionalHeader32 *opt_header = (PE_OptionalHeader32 *)raw_opt_header; image_base = opt_header->image_base; dir_count = opt_header->data_dir_count; dirs = str8_deserial_get_raw_ptr(raw_data, opt_header_off+sizeof(*opt_header), sizeof(*dirs) * opt_header->data_dir_count); if (!dirs) { rd_errorf("unable to read data directories"); goto exit; } if (opts & RD_Option_Headers) { pe_print_optional_header32(arena, out, indent, opt_header, dirs); } } else if (opt_header_magic == PE_PE32PLUS_MAGIC) { PE_OptionalHeader32Plus *opt_header = (PE_OptionalHeader32Plus *)raw_opt_header; image_base = opt_header->image_base; dir_count = opt_header->data_dir_count; dirs = str8_deserial_get_raw_ptr(raw_data, opt_header_off+sizeof(*opt_header), sizeof(*dirs) * opt_header->data_dir_count); if (!dirs) { rd_errorf("unable to read data directories"); goto exit; } if (opts & RD_Option_Headers) { pe_print_optional_header32plus(arena, out, indent, opt_header, dirs); } } // map data directory RVA to file offsets Rng1U64 *dirs_file_ranges = push_array(scratch.arena, Rng1U64, dir_count); Rng1U64 *dirs_virt_ranges = push_array(scratch.arena, Rng1U64, dir_count); for (U64 i = 0; i < dir_count; ++i) { PE_DataDirectory dir = dirs[i]; U64 file_off = coff_foff_from_voff(sections, file_header->section_count, dir.virt_off); dirs_file_ranges[i] = r1u64(file_off, file_off+dir.virt_size); dirs_virt_ranges[i] = r1u64(dir.virt_off, dir.virt_off+dir.virt_size); } if (opts & RD_Option_Sections) { coff_print_section_table(arena, out, indent, raw_string_table, symbols, file_header->section_count, sections); } if (opts & RD_Option_Relocs) { coff_print_relocs(arena, out, indent, raw_data, raw_string_table, file_header->machine, file_header->section_count, sections, symbols); } if (opts & RD_Option_Symbols) { coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbols); } if (opts & RD_Option_Exports) { PE_ParsedExportTable exptab = pe_exports_from_data(arena, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXPORT], dirs_virt_ranges[PE_DataDirectoryIndex_EXPORT]); pe_print_export_table(arena, out, indent, exptab); } if (opts & RD_Option_Imports) { B32 is_pe32 = opt_header_magic == PE_PE32_MAGIC; PE_ParsedStaticImportTable static_imptab = pe_static_imports_from_data(arena, is_pe32, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_IMPORT]); PE_ParsedDelayImportTable delay_imptab = pe_delay_imports_from_data(arena, is_pe32, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_DELAY_IMPORT]); pe_print_static_import_table(arena, out, indent, image_base, static_imptab); pe_print_delay_import_table(arena, out, indent, image_base, delay_imptab); } if (opts & RD_Option_Resources) { String8 raw_dir = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_RESOURCES]); PE_ResourceDir *dir_root = pe_resource_table_from_directory_data(scratch.arena, raw_dir); pe_print_resources(arena, out, indent, dir_root); } if (opts & RD_Option_Exceptions) { pe_print_exceptions(arena, out, indent, file_header->machine, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXCEPTIONS], rdi); } if (opts & RD_Option_Relocs) { pe_print_base_relocs(arena, out, indent, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_BASE_RELOC], rdi); } if (opts & RD_Option_Debug) { if (PE_DataDirectoryIndex_DEBUG < dir_count) { String8 raw_dir = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_DEBUG]); pe_print_debug_diretory(arena, out, indent, raw_data, raw_dir); } } if (opts & RD_Option_Tls) { if (dim_1u64(dirs_file_ranges[PE_DataDirectoryIndex_TLS])) { PE_ParsedTLS tls = pe_tls_from_data(scratch.arena, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_TLS]); pe_print_tls(arena, out, indent, tls); } } if (opts & RD_Option_LoadConfig) { String8 raw_lc = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_LOAD_CONFIG]); if (raw_lc.size) { switch (file_header->machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: { PE_LoadConfig32 *lc = str8_deserial_get_raw_ptr(raw_lc, 0, sizeof(*lc)); if (lc) { pe_print_load_config32(arena, out, indent, lc); } else { rd_errorf("not enough bytes to parse 32bit load config"); } } break; case COFF_MachineType_X64: { PE_LoadConfig64 *lc = str8_deserial_get_raw_ptr(raw_lc, 0, sizeof(*lc)); if (lc) { pe_print_load_config64(arena, out, indent, lc); } else { rd_errorf("not enough bytes to parse 64bit load config"); } } break; default: NotImplemented; } } } RD_MarkerArray *section_markers = 0; if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) { if (rdi) { section_markers = rd_section_markers_from_rdi(scratch.arena, rdi); } else { section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, file_header->section_count, symbols); } } if (opts & RD_Option_Rawdata) { coff_raw_data_sections(arena, out, indent, raw_data, 0, section_markers, file_header->section_count, sections); } if (opts & RD_Option_Disasm) { coff_disasm_sections(arena, out, indent, raw_data, file_header->machine, 0, 1, section_markers, file_header->section_count, sections); } if (opts & RD_Option_Dwarf) { DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, file_header->section_count, sections); dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); } exit:; scratch_end(scratch); } #if 0 internal void elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); ELF_Bin bin = elf_bin_from_data(raw_data); Arch arch = arch_from_elf_machine(bin.hdr.e_machine); DW_Input dwarf_input = dw_input_from_elf_bin(scratch.arena, raw_data, &bin); ELF_Class elf_class = bin.hdr.e_ident[ELF_Identifier_Class]; ExecutableImageKind image_type = elf_class == ELF_Class_32 ? ExecutableImageKind_Elf32 : elf_class == ELF_Class_64 ? ExecutableImageKind_Elf64 : ELF_Class_None; B32 relaxed = 1; Rng1U64List cu_ranges = dw_unit_ranges_from_data(scratch.arena, dwarf_input.sec[DW_Section_Info].data); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &dwarf_input); if (bin.hdr.e_type == ELF_Type_Exec || bin.hdr.e_type == ELF_Type_Dyn) { U64 cu_idx = 0; for (Rng1U64Node *cu_range_n = cu_ranges.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++cu_idx) { Temp comp_temp = temp_begin(scratch.arena); U64 cu_base = cu_range_n->v.min; Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_cu_from_info_off(comp_temp.arena, &dwarf_input, lu_input, cu_range.min, relaxed); struct TagNode { struct TagNode *next; DW_Tag tag; }; struct TagNode *tag_stack = 0; struct TagNode *free_tags = 0; S32 lexical_block_depth = 0; for (U64 info_off = cu.first_tag_info_off, tag_size = 0; info_off < cu.info_range.max; info_off += tag_size) { DW_Tag tag = {0}; tag_size = dw_read_tag_cu(comp_temp.arena, &dwarf_input, &cu, info_off, &tag); if (tag.has_children) { struct TagNode *n = free_tags; if (n == 0) { n = push_array(comp_temp.arena, struct TagNode, 1); } else { SLLStackPop(free_tags); } n->tag = tag; SLLStackPush(tag_stack, n); } if (tag.kind == DW_TagKind_Null) { if (tag_stack) { struct TagNode *n = tag_stack; if ((n->tag.kind == DW_TagKind_SubProgram || n->tag.kind == DW_TagKind_LexicalBlock)) { Assert(lexical_block_depth > 0); --lexical_block_depth; } SLLStackPop(tag_stack); SLLStackPush(free_tags, n); } } else if (tag.kind == DW_TagKind_LexicalBlock || tag.kind == DW_TagKind_SubProgram) { ++lexical_block_depth; if (tag.kind == DW_TagKind_SubProgram) { String8 expr = dw_exprloc_from_tag_attrib_kind(&dwarf_input, &cu, tag, DW_AttribKind_FrameBase); if (expr.size > 0) { String8 expr_str = dw_single_line_string_from_expression(comp_temp.arena, expr, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); } } } else if (tag.kind == DW_Tag_VariaKindble || tag.kind == DW_Tag_FormalParameter) { #if 0 local_persist B32 is_global_var = 0; String8 name = dw_string_from_tag_attrib_kind(&dwarf_input, &cu, tag, DW_AttribKind_Name); DW_Attrib *location_attrib = dw_attrib_from_tag(&dwarf_input, &cu, tag, DW_AttribKind_Location); DW_AttribClass value_class = dw_value_class_from_attrib(&cu, location_attrib); if (value_class != DW_AttribClass_Null) { if (lexical_block_depth == 0) { rd_printf("%llx Global: %S", info_off, name); is_global_var = 1; } else { rd_printf("%llx Local: %S", info_off, name); is_global_var = 0; } rd_indent(); if (value_class == DW_AttribClass_LocListPtr || value_class == DW_AttribClass_LocList) { DW_LocList location = dw_loclist_from_tag_attrib_kind(comp_temp.arena, &dwarf_input, &cu, location_attrib); for (DW_LocNode *loc_n = location.first; loc_n != 0; loc_n = loc_n->next) { String8 expr_str = dw_single_line_string_from_expression(comp_temp.arena, loc_n->v.expr, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); rd_printf("[%llx-%llx] %S", loc_n->v.range.min, loc_n->v.range.max, expr_str); } } else if (value_class == DW_AttribClass_ExprLoc) { String8 expr = dw_exprloc_from_tag_attrib_kind(&dwarf_input, &cu, location_attrib); String8 expr_str = dw_single_line_string_from_expression(comp_temp.arena, expr, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); rd_printf("%S", expr_str); } rd_unindent(); } #endif } #if 0 if (tag.kind == DW_TagKind_LexicalBlock || tag.kind == DW_TagKind_CompileUnit || tag.kind == DW_TagKind_InlinedSubroutine || tag.kind == DW_TagKind_SubProgram) { Temp temp = temp_begin(comp_temp.arena); DW_Attrib *ranges_attrib = dw_attrib_from_tag(&dwarf_input, &cu, tag, DW_AttribKind_Ranges); if (ranges_attrib->attrib_kind == DW_AttribKind_Ranges) { Rng1U64List ranges = dw_rnglist_from_tag_attrib_kind(temp.arena, &dwarf_input, &cu, ranges_attrib); } temp_end(temp); } #endif } temp_end(comp_temp); } } else { fprintf(stderr, "Skipping unexpected ELF type %u\n", bin.hdr.e_type); } scratch_end(scratch); } #endif ================================================ FILE: src/raddump/raddump.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDUMP_H #define RADDUMP_H #define RD_INDENT_WIDTH 2 #define RD_INDENT_MAX 4096 #define rd_printf(f, ...) str8_list_pushf(arena, out, "%S" f, indent, __VA_ARGS__) #define rd_newline() str8_list_pushf(arena, out, ""); #define rd_errorf(f, ...) rd_stderr("ERROR: "f, __VA_ARGS__) #define rd_warningf(f, ...) rd_stderr("WARNING: "f, __VA_ARGS__) #define rd_indent() do { if (indent.size + RD_INDENT_WIDTH <= RD_INDENT_MAX) { indent.size += RD_INDENT_WIDTH; } else { Assert(!"indent overflow"); } } while (0) #define rd_unindent() do { if (indent.size >= RD_INDENT_WIDTH) { indent.size -= RD_INDENT_WIDTH; } else { Assert(!"unbalanced indent"); } } while (0) typedef U64 RD_Option; #define RD_Option_Help (1ull << 0) #define RD_Option_Version (1ull << 1) #define RD_Option_Headers (1ull << 2) #define RD_Option_Sections (1ull << 3) #define RD_Option_Debug (1ull << 4) #define RD_Option_Imports (1ull << 5) #define RD_Option_Exports (1ull << 6) #define RD_Option_Disasm (1ull << 7) #define RD_Option_Rawdata (1ull << 8) #define RD_Option_Tls (1ull << 9) #define RD_Option_Codeview (1ull << 10) #define RD_Option_Symbols (1ull << 11) #define RD_Option_Relocs (1ull << 12) #define RD_Option_Exceptions (1ull << 13) #define RD_Option_LoadConfig (1ull << 14) #define RD_Option_Resources (1ull << 15) #define RD_Option_LongNames (1ull << 16) // DWARF #define RD_Option_DebugInfo (1ull << 17) #define RD_Option_DebugAbbrev (1ull << 18) #define RD_Option_DebugLine (1ull << 19) #define RD_Option_DebugStr (1ull << 20) #define RD_Option_DebugLoc (1ull << 21) #define RD_Option_DebugRanges (1ull << 22) #define RD_Option_DebugARanges (1ull << 23) #define RD_Option_DebugAddr (1ull << 24) #define RD_Option_DebugLocLists (1ull << 25) #define RD_Option_DebugRngLists (1ull << 26) #define RD_Option_DebugPubNames (1ull << 27) #define RD_Option_DebugPubTypes (1ull << 28) #define RD_Option_DebugLineStr (1ull << 29) #define RD_Option_DebugStrOffsets (1ull << 30) #define RD_Option_Dwarf \ (RD_Option_DebugInfo | \ RD_Option_DebugAbbrev | \ RD_Option_DebugLine | \ RD_Option_DebugStr | \ RD_Option_DebugLoc | \ RD_Option_DebugRanges | \ RD_Option_DebugARanges | \ RD_Option_DebugAddr | \ RD_Option_DebugLocLists | \ RD_Option_DebugRngLists | \ RD_Option_DebugPubNames | \ RD_Option_DebugPubTypes | \ RD_Option_DebugLineStr | \ RD_Option_DebugStrOffsets) #define RD_Option_RelaxDwarfParser (1ull << 31ull) // RDI #define RD_Option_NoRdi (1ull << 32ull) #define RD_Option_RdiDataSections (1ull << 33ull) #define RD_Option_RdiTopLevelInfo (1ull << 34ull) #define RD_Option_RdiBinarySections (1ull << 35ull) #define RD_Option_RdiFilePaths (1ull << 36ull) #define RD_Option_RdiSourceFiles (1ull << 37ull) #define RD_Option_RdiLineTables (1ull << 38ull) #define RD_Option_RdiSourceLineMaps (1ull << 39ull) #define RD_Option_RdiUnits (1ull << 40ull) #define RD_Option_RdiUnitVMap (1ull << 41ull) #define RD_Option_RdiTypeNodes (1ull << 42ull) #define RD_Option_RdiUserDefinedTypes (1ull << 43ull) #define RD_Option_RdiGlobalVars (1ull << 44ull) #define RD_Option_RdiGlobalVarsVMap (1ull << 45ull) #define RD_Option_RdiThreadVars (1ull << 46ull) #define RD_Option_RdiConstants (1ull << 47ull) #define RD_Option_RdiProcedures (1ull << 48ull) #define RD_Option_RdiScopes (1ull << 49ull) #define RD_Option_RdiScopeVMap (1ull << 50ull) #define RD_Option_RdiInlineSites (1ull << 51ull) #define RD_Option_RdiNameMaps (1ull << 52ull) #define RD_Option_RdiStrings (1ull << 53ull) #define RD_Option_RdiAll (RD_Option_RdiDataSections | \ RD_Option_RdiTopLevelInfo | \ RD_Option_RdiBinarySections | \ RD_Option_RdiFilePaths | \ RD_Option_RdiSourceFiles | \ RD_Option_RdiLineTables | \ RD_Option_RdiSourceLineMaps | \ RD_Option_RdiUnits | \ RD_Option_RdiUnitVMap | \ RD_Option_RdiTypeNodes | \ RD_Option_RdiUserDefinedTypes | \ RD_Option_RdiGlobalVars | \ RD_Option_RdiGlobalVarsVMap | \ RD_Option_RdiThreadVars | \ RD_Option_RdiConstants | \ RD_Option_RdiProcedures | \ RD_Option_RdiScopes | \ RD_Option_RdiScopeVMap | \ RD_Option_RdiInlineSites | \ RD_Option_RdiNameMaps | \ RD_Option_RdiStrings) typedef struct RD_Marker { U64 off; String8 string; } RD_Marker; typedef struct RD_MarkerArray { U64 count; RD_Marker *v; } RD_MarkerArray; typedef struct MarkerNode { struct MarkerNode *next; RD_Marker v; } RD_MarkerNode; typedef struct RD_MarkerList { U64 count; RD_MarkerNode *first; RD_MarkerNode *last; } RD_MarkerList; typedef struct RD_DisasmResult { String8 text; U64 size; } RD_DisasmResult; typedef struct RD_Section { String8 name; String8 raw_data; } RD_Section; typedef struct RD_SectionArray { U64 count; RD_Section *v; } RD_SectionArray; typedef struct RD_Line { String8 file_path; U32 line_num; } RD_Line; //////////////////////////////// // raddump internal B32 rd_is_rdi(String8 raw_data); internal String8 rd_string_from_flags(Arena *arena, String8List list, U64 remaining_flags); internal void rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data); // Markers internal RD_MarkerArray * rd_section_markers_from_coff_symbol_table(Arena *arena, String8 string_table, U64 section_count, COFF_Symbol32Array symbols); // Sections internal RD_SectionArray rd_sections_from_coff_section_table(Arena *arnea, String8 raw_image, U64 string_table_off, U64 section_count, COFF_SectionHeader *sections); // Disasm internal RD_DisasmResult rd_disasm_next_instruction(Arena *arena, Arch arch, U64 addr, String8 raw_code); internal void rd_print_disasm (Arena *arena, String8List *out, String8 indent, Arch arch, U64 image_base, U64 sect_off, U64 marker_count, RD_Marker *markers, String8 raw_code); // Raw Data internal String8 rd_format_hex_array(Arena *arena, U8 *ptr, U64 size); internal void rd_print_raw_data (Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data); // CodeView internal void cv_print_binary_annots (Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data); internal void cv_print_lvar_addr_range(Arena *arena, String8List *out, String8 indent, CV_LvarAddrRange range); internal void cv_print_lvar_addr_gap (Arena *arena, String8List *out, String8 indent, String8 raw_data); internal void cv_print_lvar_attr (Arena *arena, String8List *out, String8 indent, CV_LocalVarAttr attr); internal void cv_print_symbol (Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV_TypeIndex min_itype, CV_SymKind type, String8 raw_symbol); internal U64 cv_print_leaf (Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_itype, CV_LeafKind kind, String8 raw_leaf); internal void cv_print_debug_t (Arena *arena, String8List *out, String8 indent, CV_DebugT debug_t); internal void cv_print_symbols_c13 (Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data); internal void cv_print_lines_c13 (Arena *arena, String8List *out, String8 indent, String8 raw_lines); internal void cv_print_file_checksums (Arena *arena, String8List *out, String8 indent, String8 raw_chksums); internal void cv_print_string_table (Arena *arena, String8List *out, String8 indent, String8 raw_strtab); internal void cv_print_inlinee_lines (Arena *arena, String8List *out, String8 indent, String8 raw_data); internal void cv_print_symbols_section(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_ss); // MSVC CRT internal void mscrt_print_eh_handler_type32(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, MSCRT_EhHandlerType32 *handler); // PE internal void pe_print_data_directory_ranges(Arena *arena, String8List *out, String8 indent, U64 count, PE_DataDirectory *dirs); internal void pe_print_optional_header32 (Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32 *opt_header, PE_DataDirectory *dirs); internal void pe_print_optional_header32plus(Arena *arena, String8List *out, String8 indent, PE_OptionalHeader32Plus *opt_header, PE_DataDirectory *dirs); internal void pe_print_load_config32 (Arena *arena, String8List *out, String8 indent, PE_LoadConfig32 *lc); internal void pe_print_load_config64 (Arena *arena, String8List *out, String8 indent, PE_LoadConfig64 *lc); internal void pe_print_tls (Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls); internal void pe_print_debug_diretory (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir); internal void pe_print_export_table (Arena *arena, String8List *out, String8 indent, PE_ParsedExportTable exptab); internal void pe_print_static_import_table (Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedStaticImportTable imptab); internal void pe_print_delay_import_table (Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedDelayImportTable imptab); internal void pe_print_resources (Arena *arena, String8List *out, String8 indent, PE_ResourceDir *root); internal void pe_print_exceptions_x8664 (Arena *arena, String8List *out, String8 indent, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange, RDI_Parsed *rdi); internal void pe_print_exceptions (Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 except_frange, RDI_Parsed *rdi); internal void pe_print_base_relocs (Arena *arena, String8List *out, String8 indent, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 base_reloc_franges, RDI_Parsed *rdi); internal void pe_print (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts, RDI_Parsed *rdi); #endif // RADDUMP_H ================================================ FILE: src/raddump/raddump_main.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #define BUILD_CONSOLE_INTERFACE 1 #define BUILD_TITLE "Epic Games Tools (R) RAD Dumper" //////////////////////////////// #include "linker/base_ext/base_blake3.h" #include "linker/base_ext/base_blake3.c" #include "third_party/xxHash/xxhash.c" #include "third_party/xxHash/xxhash.h" #include "third_party/radsort/radsort.h" #include "third_party/md5/md5.c" #include "third_party/md5/md5.h" #include "third_party/zydis/zydis.h" #include "third_party/zydis/zydis.c" #include "third_party/rad_lzb_simple/rad_lzb_simple.h" #include "third_party/rad_lzb_simple/rad_lzb_simple.c" #define SINFL_IMPLEMENTATION #include "third_party/sinfl/sinfl.h" //////////////////////////////// #include "base/base_inc.h" #include "linker/base_ext/base_inc.h" #include "os/os_inc.h" #include "async/async.h" #include "rdi_format/rdi_format_local.h" #include "rdi_make/rdi_make_local.h" #include "linker/hash_table.h" #include "coff/coff.h" #include "coff/coff_parse.h" #include "pe/pe.h" #include "elf/elf.h" #include "elf/elf_parse.h" #include "msvc_crt/msvc_crt.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" #include "msf/msf_parse.h" #include "pdb/pdb.h" #include "pdb/pdb_parse.h" #include "dwarf/dwarf.h" #include "dwarf/dwarf_parse.h" #include "dwarf/dwarf_expr.h" #include "dwarf/dwarf_unwind.h" #include "dwarf/dwarf_coff.h" #include "dwarf/dwarf_elf.h" #include "radcon/radcon.h" #include "radcon/radcon_coff.h" #include "radcon/radcon_cv.h" #include "radcon/radcon_elf.h" #include "radcon/radcon_pdb.h" #include "radcon/radcon_dwarf.h" #include "base/base_inc.c" #include "linker/base_ext/base_inc.c" #include "os/os_inc.c" #include "async/async.c" #include "rdi_format/rdi_format_local.c" #include "rdi_make/rdi_make_local.c" #include "linker/hash_table.c" #include "coff/coff.c" #include "coff/coff_parse.c" #include "pe/pe.c" #include "elf/elf.c" #include "elf/elf_parse.c" #include "msvc_crt/msvc_crt.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c" #include "msf/msf_parse.c" #include "pdb/pdb.c" #include "pdb/pdb_parse.c" #include "dwarf/dwarf.c" #include "dwarf/dwarf_parse.c" #include "dwarf/dwarf_expr.c" #include "dwarf/dwarf_unwind.c" #include "dwarf/dwarf_coff.c" #include "dwarf/dwarf_elf.c" #include "radcon/radcon_coff.c" #include "radcon/radcon_cv.c" #include "radcon/radcon_elf.c" #include "radcon/radcon_pdb.c" #include "radcon/radcon_dwarf.c" #include "radcon/radcon.c" #include "linker/thread_pool/thread_pool.h" #include "linker/thread_pool/thread_pool.c" #include "linker/codeview_ext/codeview.h" #include "linker/codeview_ext/codeview.c" #include "linker/rdi/rdi.h" #include "linker/rdi/rdi.c" #include "raddump/raddump.h" #include "raddump/raddump.c" //////////////////////////////// global read_only struct { RD_Option opt; char *name; char *help; } g_rd_dump_option_map[] = { { RD_Option_Help, "help", "Print help and exit" }, { RD_Option_Version, "version", "Print version and exit" }, { RD_Option_NoRdi, "nordi", "Don't load RAD Debug Info" }, { RD_Option_Headers, "headers", "Dump DOS header, file header, optional header, and/or archive header" }, { RD_Option_Sections, "sections", "Dump section headers as table" }, { RD_Option_Rawdata, "rawdata", "Dump raw section data" }, { RD_Option_Codeview, "cv", "Dump CodeView" }, { RD_Option_Disasm, "disasm", "Disassemble code sections" }, { RD_Option_Symbols, "symtab", "Dump COFF symbol table" }, { RD_Option_Relocs, "relocs", "Dump relocations" }, { RD_Option_Exceptions, "exceptions", "Dump exceptions" }, { RD_Option_Tls, "tls", "Dump Thread Local Storage directory" }, { RD_Option_Debug, "debug", "Dump debug directory" }, { RD_Option_Imports, "imports", "Dump import table" }, { RD_Option_Exports, "exports", "Dump export table" }, { RD_Option_LoadConfig, "loadconfig", "Dump load config" }, { RD_Option_Resources, "resources", "Dump resource directory" }, { RD_Option_LongNames, "longnames", "Dump archive long names" }, { RD_Option_DebugInfo, "debug_info", "Dump .debug_info" }, { RD_Option_DebugAbbrev, "debug_abbrev", "Dump .debug_abbrev" }, { RD_Option_DebugLine, "debug_line", "Dump .debug_line" }, { RD_Option_DebugStr, "debug_str", "Dump .debug_str" }, { RD_Option_DebugLoc, "debug_loc", "Dump .debug_loc" }, { RD_Option_DebugRanges, "debug_ranges", "Dump .debug_ranges" }, { RD_Option_DebugARanges, "debug_aranges", "Dump .debug_aranges" }, { RD_Option_DebugAddr, "debug_addr", "Dump .debug_addr" }, { RD_Option_DebugLocLists, "debug_loclists", "Dump .debug_loclists" }, { RD_Option_DebugRngLists, "debug_rnglists", "Dump .debug_rnglists" }, { RD_Option_DebugPubNames, "debug_pubnames", "Dump .debug_pubnames" }, { RD_Option_DebugPubTypes, "debug_pubtypes", "Dump .debug_putypes" }, { RD_Option_DebugLineStr, "debug_linestr", "Dump .debug_linestr" }, { RD_Option_DebugStrOffsets, "debug_stroffsets", "Dump .debug_stroffsets" }, { RD_Option_Dwarf, "dwarf", "Dump all DWARF sections" }, { RD_Option_RelaxDwarfParser, "relax_dwarf_parser", "Relaxes version requirement on attribute and form encodings" }, { RD_Option_RdiDataSections, "rdi_data_sections", "Dump data sections" }, { RD_Option_RdiTopLevelInfo, "rdi_top_level_info", "Dump top level info" }, { RD_Option_RdiBinarySections, "rdi_binary_sections", "Dump binary sections" }, { RD_Option_RdiFilePaths, "rdi_file_paths", "Dump file paths" }, { RD_Option_RdiSourceFiles, "rdi_source_files", "Dump source files" }, { RD_Option_RdiLineTables, "rdi_line_tables", "Dump line tables" }, { RD_Option_RdiSourceLineMaps, "rdi_source_line_maps", "Dump source line maps" }, { RD_Option_RdiUnits, "rdi_units", "Dump units" }, { RD_Option_RdiUnitVMap, "rdi_units_virtual_map", "Dump units virtual map" }, { RD_Option_RdiTypeNodes, "rdi_type_nodes", "Dump type nodes" }, { RD_Option_RdiUserDefinedTypes, "rdi_udt", "Dump user defined types" }, { RD_Option_RdiGlobalVars, "rdi_global_vars", "Dump global variables" }, { RD_Option_RdiThreadVars, "rdi_thread_vars", "Dump thread variables" }, { RD_Option_RdiConstants, "rdi_constants", "Dump constants" }, { RD_Option_RdiScopes, "rdi_scopes", "Dump scopes" }, { RD_Option_RdiScopeVMap, "rdi_scope_virtual_map", "Dump scope virtual map" }, { RD_Option_RdiInlineSites, "rdi_inline_sites", "Dump inline sites" }, { RD_Option_RdiNameMaps, "rdi_name_maps", "Dump name maps" }, { RD_Option_RdiStrings, "rdi_strings", "Dump strings" }, { RD_Option_Help, "h", "Alias for -help" }, { RD_Option_Version, "v", "Alias for -version" }, { RD_Option_Sections, "s", "Alias for -sections" }, { RD_Option_Exceptions, "e", "Alias for -exceptions" }, { RD_Option_Imports, "i", "Alias for -imports" }, { RD_Option_Exports, "x", "Alias for -exports" }, { RD_Option_LoadConfig, "l", "Alias for -loadconifg" }, { RD_Option_Resources, "c", "Alias for -resources" }, { RD_Option_Relocs, "r", "Alias for -relocs" }, }; internal void entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); // make indent String8List *out = push_array(arena, String8List, 1); String8 indent; { U64 indent_buffer_size = RD_INDENT_WIDTH * RD_INDENT_MAX; U8 *indent_buffer = push_array(arena, U8, indent_buffer_size); MemorySet(indent_buffer, ' ', indent_buffer_size); indent = str8(indent_buffer, 0); } // parse options RD_Option opts = 0; { for (CmdLineOpt *cmd = cmdline->options.first; cmd != 0; cmd = cmd->next) { RD_Option opt = 0; for (U64 opt_idx = 0; opt_idx < ArrayCount(g_rd_dump_option_map); ++opt_idx) { String8 opt_name = str8_cstring(g_rd_dump_option_map[opt_idx].name); if (str8_match(cmd->string, opt_name, StringMatchFlag_CaseInsensitive)) { opt = g_rd_dump_option_map[opt_idx].opt; break; } else if (str8_match_lit("all", cmd->string, StringMatchFlag_CaseInsensitive)) { opt = ~0ull & ~(RD_Option_Help|RD_Option_Version); break; } } if (opt == 0) { rd_errorf("Unknown argument: \"%S\"", cmd->string); goto exit; } opts |= opt; } } // print help if (opts & RD_Option_Help) { int longest_cmd_switch = 0; for (U64 opt_idx = 0; opt_idx < ArrayCount(g_rd_dump_option_map); ++opt_idx) { longest_cmd_switch = Max(longest_cmd_switch, strlen(g_rd_dump_option_map[opt_idx].name)); } rd_printf(BUILD_TITLE_STRING_LITERAL); rd_newline(); rd_printf("# Help"); rd_indent(); for (U64 opt_idx = 0; opt_idx < ArrayCount(g_rd_dump_option_map); ++opt_idx) { char *name = g_rd_dump_option_map[opt_idx].name; char *help = g_rd_dump_option_map[opt_idx].help; int indent_size = longest_cmd_switch - strlen(name) + 1; rd_printf("-%s%.*s%s", g_rd_dump_option_map[opt_idx].name, indent_size, indent.str, g_rd_dump_option_map[opt_idx].help); } rd_unindent(); goto exit; } // print version if (opts & RD_Option_Version) { rd_printf(BUILD_TITLE_STRING_LITERAL); rd_printf("\traddump "); goto exit; } // input check if (cmdline->inputs.node_count == 0) { rd_errorf("No input file specified"); goto exit; } else if (cmdline->inputs.node_count > 1) { rd_errorf("Too many inputs specified, expected one"); goto exit; } // read input String8 file_path = str8_list_first(&cmdline->inputs); String8 raw_data = os_data_from_file_path(arena, file_path); // is read ok? if (raw_data.size == 0) { rd_errorf("Unable to read input file \"%S\"", file_path); goto exit; } // format input rd_format_preamble(arena, out, indent, file_path, raw_data); if (rd_is_rdi(raw_data)) { RDI_Parsed rdi = {0}; RDI_ParseStatus parse_status = rdi_parse(raw_data.str, raw_data.size, &rdi); switch (parse_status) { case RDI_ParseStatus_Good: { RD_Option rdi_print_opts = opts; if ((rdi_print_opts & RD_Option_RdiAll) == 0) { rdi_print_opts |= RD_Option_RdiAll; } rdi_print(arena, out, indent, &rdi, rdi_print_opts); } break; case RDI_ParseStatus_HeaderDoesNotMatch: rd_errorf("RDI Parse: header does not match"); break; case RDI_ParseStatus_UnsupportedVersionNumber: rd_errorf("RDI Parse: unsupported version"); break; case RDI_ParseStatus_InvalidDataSecionLayout: rd_errorf("RDI Parse: invalid data section layout"); break; case RDI_ParseStatus_MissingRequiredSection: rd_errorf("RDI Parse: missing required section"); break; default: rd_errorf("RDI Parse: unknown parse status %u", parse_status); break; } } else if (coff_is_regular_archive(raw_data) || coff_is_thin_archive(raw_data)) { coff_print_archive(arena, out, indent, raw_data, opts); } else if (coff_is_big_obj(raw_data)) { coff_print_big_obj(arena, out, indent, raw_data, opts); } else if (coff_is_obj(raw_data)) { coff_print_obj(arena, out, indent, raw_data, opts); } else if (pe_check_magic(raw_data)) { RDI_Parsed *rdi = 0; if (!(opts & RD_Option_NoRdi)) { rdi = rd_rdi_from_pe(arena, file_path); } pe_print(arena, out, indent, raw_data, opts, rdi); } else if (pe_is_res(raw_data)) { //tool_out_coff_res(stdout, file_data); } else if (elf_check_magic(raw_data)) { //elf_print_dwarf_expressions(arena, out, indent, raw_data); } exit:; // print formatted string String8 out_string = str8_list_join(arena, out, &(StringJoin){ .sep = str8_lit("\n"),}); fprintf(stdout, "%.*s", str8_varg(out_string)); arena_release(arena); } ================================================ FILE: src/rdi/rdi.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated File Format @option library @gen_folder "lib_rdi" @h_name "rdi.h" @c_name "rdi.c" @h_header { "////////////////////////////////////////////////////////////////"; "//~ (R)AD (D)ebug (I)nfo Format Library"; "//"; "// Defines standard RDI debug information format types and"; "// functions."; ""; "#ifndef RDI_H"; "#define RDI_H"; ""; "////////////////////////////////////////////////////////////////"; "//~ Overridable Procedure Decoration"; ""; "#if !defined(RDI_PROC)"; "# define RDI_PROC static"; "#endif"; ""; "////////////////////////////////////////////////////////////////"; "//~ Overridable Basic Integer Types"; ""; "#if !defined(RDI_U8)"; "# define RDI_U8 RDI_U8"; "# define RDI_U16 RDI_U16"; "# define RDI_U32 RDI_U32"; "# define RDI_U64 RDI_U64"; "# define RDI_S8 RDI_S8"; "# define RDI_S16 RDI_S16"; "# define RDI_S32 RDI_S32"; "# define RDI_S64 RDI_S64"; "#include "; "typedef uint8_t RDI_U8;"; "typedef uint16_t RDI_U16;"; "typedef uint32_t RDI_U32;"; "typedef uint64_t RDI_U64;"; "typedef int8_t RDI_S8;"; "typedef int16_t RDI_S16;"; "typedef int32_t RDI_S32;"; "typedef int64_t RDI_S64;"; "#endif"; ""; "////////////////////////////////////////////////////////////////"; "//~ Checksum Types"; ""; "typedef union RDI_MD5 RDI_MD5;"; "union RDI_MD5 {RDI_U8 u8[16]; RDI_U64 u64[2];};"; ""; "typedef union RDI_SHA1 RDI_SHA1;"; "union RDI_SHA1 {RDI_U8 u8[20];};"; ""; "typedef union RDI_SHA256 RDI_SHA256;"; "union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};"; ""; "typedef union RDI_GUID RDI_GUID;"; "union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];};"; ""; "////////////////////////////////////////////////////////////////"; "//~ Overridable Enabling/Disabling Of Table Index Typechecking"; ""; "#if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING)"; "# define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0"; "#endif"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Constants"; ""; "// \"raddbg\\0\\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; "#define RDI_ENCODING_VERSION 17"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; ""; } @h_footer { "#endif // RDI_H"; } @c_header { "////////////////////////////////////////////////////////////////"; "//~ (R)AD (D)ebug (I)nfo Format Library"; "//"; "// Defines standard RDI debug information format types and"; "// functions."; ""; "#ifndef RDI_C"; "#define RDI_C"; ""; } @c_footer { "#endif // RDI_C"; } //////////////////////////////// //~ rjf: Format Header Tables @table(name type desc) RDI_HeaderMemberTable: { {magic RDI_U64 ""} {encoding_version RDI_U32 ""} {data_section_off RDI_U32 ""} {data_section_count RDI_U32 ""} } @xlist RDI_Header_XList: { @expand(RDI_HeaderMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Header: { @expand(RDI_HeaderMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Format Section Tables @table(name name_lower element_type value index_base_type desc) RDI_SectionTable: { {NULL null RDI_U8 0x0000 - ""} {TopLevelInfo top_level_info RDI_TopLevelInfo 0x0001 - ""} {StringData string_data RDI_U8 0x0002 - ""} {StringTable string_table RDI_U32 0x0003 U32 ""} {IndexRuns index_runs RDI_U32 0x0004 U32 ""} {BinarySections binary_sections RDI_BinarySection 0x0005 U32 ""} {FilePathNodes file_path_nodes RDI_FilePathNode 0x0006 U32 ""} {SourceFiles source_files RDI_SourceFile 0x0007 U32 ""} {LineTables line_tables RDI_LineTable 0x0008 U32 ""} {LineInfoVOffs line_info_voffs RDI_U64 0x0009 U32 ""} {LineInfoLines line_info_lines RDI_Line 0x000A U32 ""} {LineInfoColumns line_info_columns RDI_Column 0x000B U32 ""} {SourceLineMaps source_line_maps RDI_SourceLineMap 0x000C U32 ""} {SourceLineMapNumbers source_line_map_numbers RDI_U32 0x000D U32 ""} {SourceLineMapRanges source_line_map_ranges RDI_U32 0x000E U32 ""} {SourceLineMapVOffs source_line_map_voffs RDI_U64 0x000F U32 ""} {Units units RDI_Unit 0x0010 U32 ""} {UnitVMap unit_vmap RDI_VMapEntry 0x0011 - ""} {TypeNodes type_nodes RDI_TypeNode 0x0012 U32 ""} {UDTs udts RDI_UDT 0x0013 U32 ""} {Members members RDI_Member 0x0014 U32 ""} {EnumMembers enum_members RDI_EnumMember 0x0015 U32 ""} {GlobalVariables global_variables RDI_GlobalVariable 0x0016 U32 ""} {GlobalVMap global_vmap RDI_VMapEntry 0x0017 - ""} {ThreadVariables thread_variables RDI_ThreadVariable 0x0018 U32 ""} {Constants constants RDI_Constant 0x0019 U32 ""} {Procedures procedures RDI_Procedure 0x001A U32 ""} {Scopes scopes RDI_Scope 0x001B U32 ""} {ScopeVOffData scope_voff_data RDI_U64 0x001C U32 ""} {ScopeVMap scope_vmap RDI_VMapEntry 0x001D - ""} {InlineSites inline_sites RDI_InlineSite 0x001E U32 ""} {Locals locals RDI_Local 0x001F U32 ""} {LocationBlocks location_blocks RDI_LocationBlock 0x0020 U32 ""} {LocationData location_data RDI_U8 0x0021 U32 ""} {ConstantValueData constant_value_data RDI_U8 0x0022 U32 ""} {ConstantValueTable constant_value_table RDI_U32 0x0023 U32 ""} {MD5Checksums md5_checksums RDI_MD5 0x0024 U32 ""} {SHA1Checksums sha1_checksums RDI_SHA1 0x0025 U32 ""} {SHA256Checksums sha256_checksums RDI_SHA256 0x0026 U32 ""} {Timestamps timestamps RDI_U64 0x0027 U32 ""} {NameMaps name_maps RDI_NameMap 0x0028 U32 ""} {NameMapBuckets name_map_buckets RDI_NameMapBucket 0x0029 U32 ""} {NameMapNodes name_map_nodes RDI_NameMapNode 0x002A U32 ""} {COUNT count RDI_U8 0x002B - ""} } @table(name value) RDI_SectionEncodingTable: { {Unpacked 0} {LZB 1} } @table(name type desc) RDI_SectionMemberTable: { {encoding RDI_SectionEncoding ""} {pad RDI_U32 ""} {off RDI_U64 ""} {encoded_size RDI_U64 ""} {unpacked_size RDI_U64 ""} } @enum(RDI_U32) RDI_SectionKind: { @expand(RDI_SectionTable a) `$(a.name .. =>20) = $(a.value)`, } @enum(RDI_U32) RDI_SectionEncoding: { @expand(RDI_SectionEncodingTable a) `$(a.name .. =>10) = $(a.value)`, } @xlist RDI_SectionKind_XList: { @expand(RDI_SectionTable a) `$(a.name != COUNT -> a.name .. ', ' .. a.name_lower .. ', ' .. a.element_type)`; } @xlist RDI_SectionEncoding_XList: { @expand(RDI_SectionEncodingTable a) `$(a.name)`; } @xlist RDI_Section_XList: { @expand(RDI_SectionMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Section: { @expand(RDI_SectionMemberTable a) `$(a.type) $(a.name)` } @gen(enums) { `#if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING`; @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef struct RDI_" .. a.index_base_type .. "_" .. a.name .. =>50 .. " { RDI_" .. a.index_base_type .. " v; }".. " RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; `#else`; `typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table;`; `typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table;`; @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef RDI_" .. a.index_base_type .. "_Table RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; `#endif`; ``; } @gen(catchall) { @expand(RDI_SectionTable a) `$(a.name != COUNT && a.name != NULL -> "typedef " .. a.element_type .. =>40 .. " RDI_SectionElementType_" .. a.name .. ";")`; ``; } @data(RDI_U16) rdi_section_element_size_table: { @expand(RDI_SectionTable a) `sizeof($(a.element_type))`; } //////////////////////////////// //~ rjf: Common Type Tables @table(name type desc) RDI_VMapEntryMemberTable: { {voff RDI_U64 ""} {idx RDI_U64 ""} } @xlist RDI_VMapEntry_XList: { @expand(RDI_VMapEntryMemberTable a) `$(a.type), $(a.name)` } @struct RDI_VMapEntry: { @expand(RDI_VMapEntryMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Arch Info Tables @table(name value addr_size) RDI_ArchTable: { {NULL 0 0} {X86 1 4} {X64 2 8} } @table(name value) RDI_RegCodeX86Table: { {nil 0} {eax 1} {ecx 2} {edx 3} {ebx 4} {esp 5} {ebp 6} {esi 7} {edi 8} {fsbase 9} {gsbase 10} {eflags 11} {eip 12} {dr0 13} {dr1 14} {dr2 15} {dr3 16} {dr4 17} {dr5 18} {dr6 19} {dr7 20} {fpr0 21} {fpr1 22} {fpr2 23} {fpr3 24} {fpr4 25} {fpr5 26} {fpr6 27} {fpr7 28} {st0 29} {st1 30} {st2 31} {st3 32} {st4 33} {st5 34} {st6 35} {st7 36} {fcw 37} {fsw 38} {ftw 39} {fop 40} {fcs 41} {fds 42} {fip 43} {fdp 44} {mxcsr 45} {mxcsr_mask 46} {ss 47} {cs 48} {ds 49} {es 50} {fs 51} {gs 52} {ymm0 53} {ymm1 54} {ymm2 55} {ymm3 56} {ymm4 57} {ymm5 58} {ymm6 59} {ymm7 60} {tr 61} {ldtr 62} } @table(name value) RDI_RegCodeX64Table: { {nil 0} {rax 1} {rcx 2} {rdx 3} {rbx 4} {rsp 5} {rbp 6} {rsi 7} {rdi 8} {r8 9} {r9 10} {r10 11} {r11 12} {r12 13} {r13 14} {r14 15} {r15 16} {es 17} {cs 18} {ss 19} {ds 20} {fs 21} {gs 22} {rip 23} {rflags 24} {dr0 25} {dr1 26} {dr2 27} {dr3 28} {dr4 29} {dr5 30} {dr6 31} {dr7 32} {st0 33} {st1 34} {st2 35} {st3 36} {st4 37} {st5 38} {st6 39} {st7 40} {fpr0 41} {fpr1 42} {fpr2 43} {fpr3 44} {fpr4 45} {fpr5 46} {fpr6 47} {fpr7 48} {zmm0 49} {zmm1 50} {zmm2 51} {zmm3 52} {zmm4 53} {zmm5 54} {zmm6 55} {zmm7 56} {zmm8 57} {zmm9 58} {zmm10 59} {zmm11 60} {zmm12 61} {zmm13 62} {zmm14 63} {zmm15 64} {zmm16 65} {zmm17 66} {zmm18 67} {zmm19 68} {zmm20 69} {zmm21 70} {zmm22 71} {zmm23 72} {zmm24 73} {zmm25 74} {zmm26 75} {zmm27 76} {zmm28 77} {zmm29 78} {zmm30 79} {zmm31 80} {k0 81} {k1 82} {k2 83} {k3 84} {k4 85} {k5 86} {k6 87} {k7 88} {mxcsr 89} {fsbase 90} {gsbase 91} {fcw 92} {fsw 93} {ftw 94} {fop 95} {fcs 96} {fds 97} {fip 98} {fdp 99} {mxcsr_mask 100} {cetmsr 101} {cetssp 102} {tr 103} {ldtr 104} } @enum(RDI_U32) RDI_Arch: { @expand(RDI_ArchTable a) `$(a.name .. =>10) = $(a.value)` } @xlist RDI_Arch_XList: { @expand(RDI_ArchTable a) `$(a.name)`; } @enum(RDI_U8) RDI_RegCode: {nil} @enum(RDI_U8) RDI_RegCodeX86: { @expand(RDI_RegCodeX86Table a) `$(a.name .. =>10) = $(a.value)` } @enum(RDI_U8) RDI_RegCodeX64: { @expand(RDI_RegCodeX64Table a) `$(a.name .. =>10) = $(a.value)` } @xlist RDI_RegCodeX86_XList: { @expand(RDI_RegCodeX86Table a) `$(a.name), $(a.value)` } @xlist RDI_RegCodeX64_XList: { @expand(RDI_RegCodeX64Table a) `$(a.name), $(a.value)` } //////////////////////////////// //~ rjf: Top-Level Info Type Tables @table(name type desc) RDI_TopLevelInfoMemberTable: { {arch RDI_Arch ""} {exe_name_string_idx RDI_U32 ""} {exe_hash RDI_U64 ""} {voff_max RDI_U64 ""} {guid RDI_GUID ""} {producer_name_string_idx RDI_U32 ""} } @xlist RDI_TopLevelInfo_XList: { @expand(RDI_TopLevelInfoMemberTable a) `$(a.type), $(a.name)` } @struct RDI_TopLevelInfo: { @expand(RDI_TopLevelInfoMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Binary Section Info Type Tables @table(name value) RDI_BinarySectionFlagTable: { {Read `1<<0`} {Write `1<<1`} {Execute `1<<2`} } @table(name type desc) RDI_BinarySectionMemberTable: { {name_string_idx RDI_U32 ""} {flags RDI_BinarySectionFlags ""} {voff_first RDI_U64 ""} {voff_opl RDI_U64 ""} {foff_first RDI_U64 ""} {foff_opl RDI_U64 ""} } @enum(RDI_U32) RDI_BinarySectionFlags: { @expand(RDI_BinarySectionFlagTable a) `$(a.name .. =>10) = $(a.value)`; } @xlist RDI_BinarySectionFlags_XList: { @expand(RDI_BinarySectionFlagTable a) `$(a.name)`; } @xlist RDI_BinarySection_XList: { @expand(RDI_BinarySectionMemberTable a) `$(a.type), $(a.name)` } @struct RDI_BinarySection: { @expand(RDI_BinarySectionMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Checksum Type Tables @table(name value section) RDI_ChecksumKindTable: { {NULL 0 NULL } {MD5 1 MD5Checksums } {SHA1 2 SHA1Checksums } {SHA256 3 SHA256Checksums} {Timestamp 4 Timestamps } {COUNT 5 NULL } } @enum(RDI_U32) RDI_ChecksumKind: { @expand(RDI_ChecksumKindTable a) `$(a.name .. =>10) = $(a.value)` } @xlist RDI_ChecksumKind_XList: { @expand(RDI_ChecksumKindTable a) `$(a.name), $(a.section)`; } //////////////////////////////// //~ rjf: File Path Tree Info Type Tables @table(name type desc) RDI_FilePathNodeMemberTable: { {name_string_idx RDI_U32 ""} {parent_path_node RDI_U32 ""} {first_child RDI_U32 ""} {next_sibling RDI_U32 ""} {source_file_idx RDI_U32 ""} } @table(name type desc) RDI_SourceFileMemberTable: { {file_path_node_idx RDI_U32 ""} {normal_full_path_string_idx RDI_U32 ""} // usage of line map to go from a line number to an array of voffs // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) {source_line_map_idx RDI_U32 ""} {checksum_kind RDI_ChecksumKind ""} {checksum_idx RDI_U32 ""} } @xlist RDI_FilePathNode_XList: { @expand(RDI_FilePathNodeMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_SourceFile_XList: { @expand(RDI_SourceFileMemberTable a) `$(a.type), $(a.name)` } @struct RDI_FilePathNode: { @expand(RDI_FilePathNodeMemberTable a) `$(a.type) $(a.name)` } @struct RDI_SourceFile: { @expand(RDI_SourceFileMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Unit Info Type Tables @table(name type desc) RDI_UnitMemberTable: { {unit_name_string_idx RDI_U32 ""} {compiler_name_string_idx RDI_U32 ""} {source_file_path_node RDI_U32 ""} {object_file_path_node RDI_U32 ""} {archive_file_path_node RDI_U32 ""} {build_path_node RDI_U32 ""} {language RDI_Language ""} {line_table_idx RDI_U32 ""} } @xlist RDI_Unit_XList: { @expand(RDI_UnitMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Unit: { @expand(RDI_UnitMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Line Info Type Tables @table(name type desc) RDI_LineTableMemberTable: { // usage of line info to go from voff to file & line number: // (line_info_voffs * voff) -> (nil + index) // (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] {lines_count RDI_U32 ""} {cols_count RDI_U32 ""} } @table(name type desc) RDI_LineMemberTable: { {file_idx RDI_U32 ""} {line_num RDI_U32 ""} } @table(name type desc) RDI_ColumnMemberTable: { {col_first RDI_U16 ""} {col_opl RDI_U16 ""} } @table(name type desc) RDI_SourceLineMapMemberTable: { // usage of line map to go from a line number to an array of voffs // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) {line_count RDI_U32 ""} {voff_count RDI_U32 ""} {line_map_nums_base_idx RDI_U32 ""} // U32[line_count] (sorted - not closed ranges) {line_map_range_base_idx RDI_U32 ""} // U32[line_count + 1] (pairs form ranges) {line_map_voff_base_idx RDI_U32 ""} // U64[voff_count] (idx by line_map_range_data) } @xlist RDI_LineTable_XList: { @expand(RDI_LineTableMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_Line_XList: { @expand(RDI_LineMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_Column_XList: { @expand(RDI_ColumnMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_SourceLineMapMemberTable: { @expand(RDI_SourceLineMapMemberTable a) `$(a.type), $(a.name)` } @struct RDI_LineTable: { @expand(RDI_LineTableMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Line: { @expand(RDI_LineMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Column: { @expand(RDI_ColumnMemberTable a) `$(a.type) $(a.name)` } @struct RDI_SourceLineMap: { @expand(RDI_SourceLineMapMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Language Info Tables @table(name value) RDI_LanguageTable: { {NULL 0} {C 1} {CPlusPlus 2} {Masm 3} {COUNT 4} } @enum(RDI_U32) RDI_Language: { @expand(RDI_LanguageTable a) `$(a.name .. =>10) = $(a.value)` } @xlist RDI_Language_XList: { @expand(RDI_LanguageTable a) `$(a.name)`; } //////////////////////////////// //~ rjf: Type Info Tables @table(name value size bookend1 bookend2) RDI_TypeKindTable: { {NULL 0x0000 0 } //- {Void 0x0001 0 FirstBuiltIn } {Handle 0x0002 0xFFFFFFFF } {HResult 0x0003 4 } {Char8 0x0004 1 } {Char16 0x0005 2 } {Char32 0x0006 4 } {UChar8 0x0007 1 } {UChar16 0x0008 2 } {UChar32 0x0009 4 } {U8 0x000A 1 } {U16 0x000B 2 } {U32 0x000C 4 } {U64 0x000D 8 } {U128 0x000E 16 } {U256 0x000F 32 } {U512 0x0010 64 } {S8 0x0011 1 } {S16 0x0012 2 } {S32 0x0013 4 } {S64 0x0014 8 } {S128 0x0015 16 } {S256 0x0016 32 } {S512 0x0017 64 } {Bool 0x0018 1 } {F16 0x0019 2 } {F32 0x001A 4 } {F32PP 0x001B 4 } {F48 0x001C 6 } {F64 0x001D 8 } {F80 0x001E 10 } {F128 0x001F 16 } {ComplexF32 0x0020 8 } {ComplexF64 0x0021 16 } {ComplexF80 0x0022 20 } {ComplexF128 0x0023 32 LastBuiltIn } //- {Modifier 0x1000 0 FirstConstructed } {Ptr 0x1001 0 } {LRef 0x1002 0 } {RRef 0x1003 0 } {Array 0x1004 0 } {Function 0x1005 0 } {Method 0x1006 0 } {MemberPtr 0x1007 0 LastConstructed } //- {Struct 0x2000 0 FirstUserDefined FirstRecord } {Class 0x2001 0 } {Union 0x2002 0 LastRecord } {Enum 0x2003 0 } {Alias 0x2004 0 } {IncompleteStruct 0x2005 0 FirstIncomplete } {IncompleteUnion 0x2006 0 } {IncompleteClass 0x2007 0 } {IncompleteEnum 0x2008 0 LastIncomplete LastUserDefined} //- {Bitfield 0xF000 0 } {Variadic 0xF001 0 } {Count 0xF002 0 } } @table(name value) RDI_TypeModifierFlagTable: { {Const `1<<0`} {Volatile `1<<1`} {Restrict `1<<2`} } @table(name type_lhs type_rhs desc) RDI_TypeNodeMemberTable: { {kind RDI_TypeKind `` ""} {flags RDI_U16 `` ""} {byte_size RDI_U32 `` ""} } @table(name value) RDI_UDTFlagTable: { {EnumMembers `1<<0`} } @table(name type desc) RDI_UDTMemberTable: { {self_type_idx RDI_U32 ""} {flags RDI_UDTFlags ""} {member_first RDI_U32 ""} {member_count RDI_U32 ""} {file_idx RDI_U32 ""} {line RDI_U32 ""} {col RDI_U32 ""} } @table(name value) RDI_MemberKindTable: { {NULL 0x0000} {DataField 0x0001} {StaticData 0x0002} {Method 0x0100} {StaticMethod 0x0101} {VirtualMethod 0x0102} {VTablePtr 0x0200} {Base 0x0201} {VirtualBase 0x0202} {NestedType 0x0300} } @table(name type desc) RDI_MemberMemberTable: { {kind RDI_MemberKind ""} {pad RDI_U16 ""} {name_string_idx RDI_U32 ""} {type_idx RDI_U32 ""} {off RDI_U32 ""} } @table(name type desc) RDI_EnumMemberTable: { {name_string_idx RDI_U32 ""} {pad RDI_U32 ""} {val RDI_U64 ""} } @enum(RDI_U16) RDI_TypeKind: { @expand(RDI_TypeKindTable a) `$(a.name .. =>20) = $(a.value)`; @expand(RDI_TypeKindTable a) `$(a.bookend1 != "" -> a.bookend1 .. =>20 .. " = RDI_TypeKind_" .. a.name)`; @expand(RDI_TypeKindTable a) `$(a.bookend2 != "" -> a.bookend2 .. =>20 .. " = RDI_TypeKind_" .. a.name)`; } @enum(RDI_U16) RDI_TypeModifierFlags: { @expand(RDI_TypeModifierFlagTable a) `$(a.name .. =>20) = $(a.value)`, } @xlist RDI_TypeKind_XList: { @expand(RDI_TypeKindTable a) `$(a.name)`; } @xlist RDI_TypeModifierFlags_XList: { @expand(RDI_TypeModifierFlagTable a) `$(a.name)`; } @xlist RDI_TypeNode_XList: { @expand(RDI_TypeNodeMemberTable a) `$(a.type_lhs), $(a.name)` } @struct RDI_TypeNode: { @expand(RDI_TypeNodeMemberTable a) `$(a.type_lhs) $(a.name)$(a.type_rhs)` ``` union { // kind is 'built-in' struct { RDI_U32 name_string_idx; } built_in; // kind is 'constructed' struct { RDI_U32 direct_type_idx; RDI_U32 count; union { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; } constructed; // kind is 'user defined' struct { RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; } user_defined; // (kind = Bitfield) struct { RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; } bitfield; } ``` } @enum(RDI_U32) RDI_UDTFlags: { @expand(RDI_UDTFlagTable a) `$(a.name .. =>20) = $(a.value)` } @xlist RDI_UDTFlags_XList: { @expand(RDI_UDTFlagTable a) `$(a.name)`; } @xlist RDI_UDT_XList: { @expand(RDI_UDTMemberTable a) `$(a.type), $(a.name)` } @struct RDI_UDT: { @expand(RDI_UDTMemberTable a) `$(a.type) $(a.name)` } @enum(RDI_U16) RDI_MemberKind: { @expand(RDI_MemberKindTable a) `$(a.name .. =>25) = $(a.value)` } @xlist RDI_MemberKind_XList: { @expand(RDI_MemberKindTable a) `$(a.name)`; } @xlist RDI_Member_XList: { @expand(RDI_MemberMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_EnumMember_XList: { @expand(RDI_EnumMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Member: { @expand(RDI_MemberMemberTable a) `$(a.type) $(a.name)` } @struct RDI_EnumMember: { @expand(RDI_EnumMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Symbol Info Tables //- rjf: tables @table(name value) RDI_LinkFlagTable: { {External `1<<0`} {TypeScoped `1<<1`} {ProcScoped `1<<2`} } @table(name value) RDI_LocalKindTable: { {NULL 0x0} {Parameter 0x1} {Variable 0x2} } @table(name value) RDI_LocationKindTable: { {NULL 0x0} {AddrBytecodeStream 0x1} {ValBytecodeStream 0x2} {AddrRegPlusU16 0x3} {AddrAddrRegPlusU16 0x4} {ValReg 0x5} } @table(name type desc) RDI_GlobalVariableMemberTable: { {name_string_idx RDI_U32 ""} {link_flags RDI_LinkFlags ""} {voff RDI_U64 ""} {type_idx RDI_U32 ""} {container_idx RDI_U32 ""} } @table(name type desc) RDI_ThreadVariableMemberTable: { {name_string_idx RDI_U32 ""} {link_flags RDI_LinkFlags ""} {tls_off RDI_U32 ""} {type_idx RDI_U32 ""} {container_idx RDI_U32 ""} } @table(name type desc) RDI_ConstantMemberTable: { {name_string_idx RDI_U32 ""} {type_idx RDI_U32 ""} {constant_value_idx RDI_U32 ""} } @table(name type desc) RDI_ProcedureMemberTable: { {name_string_idx RDI_U32 ""} {link_name_string_idx RDI_U32 ""} {link_flags RDI_LinkFlags ""} {type_idx RDI_U32 ""} {root_scope_idx RDI_U32 ""} {container_idx RDI_U32 ""} {frame_base_location_first RDI_U32 ""} {frame_base_location_opl RDI_U32 ""} } @table(name type desc) RDI_ScopeMemberTable: { {proc_idx RDI_U32 ""} {parent_scope_idx RDI_U32 ""} {first_child_scope_idx RDI_U32 ""} {next_sibling_scope_idx RDI_U32 ""} {voff_range_first RDI_U32 ""} {voff_range_opl RDI_U32 ""} {local_first RDI_U32 ""} {local_count RDI_U32 ""} {inline_site_idx RDI_U32 ""} } @table(name type desc) RDI_InlineSiteMemberTable: { {name_string_idx RDI_U32 ""} {type_idx RDI_U32 ""} {owner_type_idx RDI_U32 ""} {line_table_idx RDI_U32 ""} } @table(name type desc) RDI_LocalMemberTable: { {kind RDI_LocalKind ""} {name_string_idx RDI_U32 ""} {type_idx RDI_U32 ""} {pad RDI_U32 ""} {location_first RDI_U32 ""} {location_opl RDI_U32 ""} } @table(name type desc) RDI_LocationBlockMemberTable: { {scope_off_first RDI_U32 } {scope_off_opl RDI_U32 } {location_data_off RDI_U32 } } @table(name type desc) RDI_LocationBytecodeStreamMemberTable: { {kind RDI_LocationKind ""} // [... 0] null terminated byte sequence RDI_EvalBytecodeStream } @table(name type desc) RDI_LocationRegPlusU16MemberTable: { {kind RDI_LocationKind } {reg_code RDI_RegCode } {offset RDI_U16 } } @table(name type desc) RDI_LocationRegMemberTable: { {kind RDI_LocationKind } {reg_code RDI_RegCode } } //- rjf: enums @enum(RDI_U32) RDI_LinkFlags: { @expand(RDI_LinkFlagTable a) `$(a.name .. =>20) = $(a.value)` } @enum(RDI_U32) RDI_LocalKind: { @expand(RDI_LocalKindTable a) `$(a.name .. =>20) = $(a.value)` } @enum(RDI_U8) RDI_LocationKind: { @expand(RDI_LocationKindTable a) `$(a.name .. =>20) = $(a.value)` } //- rjf: xlists @xlist RDI_LinkFlags_XList: { @expand(RDI_LinkFlagTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_LocalKind_XList: { @expand(RDI_LocalKindTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_LocationKind_XList: { @expand(RDI_LocationKindTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_GlobalVariable_XList: { @expand(RDI_GlobalVariableMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_ThreadVariable_XList: { @expand(RDI_ThreadVariableMemberTable a) `$(type), $(a.name)` } @xlist RDI_Procedure_XList: { @expand(RDI_ProcedureMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_Scope_XList: { @expand(RDI_ScopeMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_InlineSite_XList: { @expand(RDI_InlineSiteMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_Local_XList: { @expand(RDI_LocalMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_LocationBlock_XList: { @expand(RDI_LocationBlockMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_LocationBytecodeStream_XList: { @expand(RDI_LocationBytecodeStreamMemberTable a) `$(a.type), $(a.name)` } @xlist RDI_LocationRegPlusU16_XList: { @expand(RDI_LocationRegPlusU16MemberTable a) `$(a.type), $(a.name)` } @xlist RDI_LocationReg_XList: { @expand(RDI_LocationRegMemberTable a) `$(a.type), $(a.name)` } //- rjf: structs @struct RDI_GlobalVariable: { @expand(RDI_GlobalVariableMemberTable a) `$(a.type) $(a.name)` } @struct RDI_ThreadVariable: { @expand(RDI_ThreadVariableMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Constant: { @expand(RDI_ConstantMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Procedure: { @expand(RDI_ProcedureMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Scope: { @expand(RDI_ScopeMemberTable a) `$(a.type) $(a.name)` } @struct RDI_InlineSite: { @expand(RDI_InlineSiteMemberTable a) `$(a.type) $(a.name)` } @struct RDI_Local: { @expand(RDI_LocalMemberTable a) `$(a.type) $(a.name)` } @struct RDI_LocationBlock: { @expand(RDI_LocationBlockMemberTable a) `$(a.type) $(a.name)` } @struct RDI_LocationBytecodeStream: { @expand(RDI_LocationBytecodeStreamMemberTable a) `$(a.type) $(a.name)` } @struct RDI_LocationRegPlusU16: { @expand(RDI_LocationRegPlusU16MemberTable a) `$(a.type) $(a.name)` } @struct RDI_LocationReg: { @expand(RDI_LocationRegMemberTable a) `$(a.type) $(a.name)` } //////////////////////////////// //~ rjf: Evaluation Bytecode Tables @table(name value num_decodes num_pops num_pushes) RDI_EvalOpTable: { {Stop 0 0 0 0} {Noop 1 0 0 0} {Cond 2 1 1 0} {Skip 3 2 0 0} {MemRead 4 1 1 1} {RegRead 5 4 0 1} {RegReadDyn 6 0 1 1} {FrameOff 7 8 0 1} {ModuleOff 8 4 0 1} {TLSOff 9 4 0 1} {ObjectOff 10 0 0 0} {CFA 11 0 0 0} {ConstU8 12 1 0 1} {ConstU16 13 2 0 1} {ConstU32 14 4 0 1} {ConstU64 15 8 0 1} {ConstU128 16 16 0 1} {ConstString 17 1 0 1} {Abs 18 1 1 1} {Neg 19 1 1 1} {Add 20 1 2 1} {Sub 21 1 2 1} {Mul 22 1 2 1} {Div 23 1 2 1} {Mod 24 1 2 1} {LShift 25 2 2 1} {RShift 26 2 2 1} {BitAnd 27 1 2 1} {BitOr 28 1 2 1} {BitXor 29 1 2 1} {BitNot 30 1 1 1} {LogAnd 31 1 2 1} {LogOr 32 1 2 1} {LogNot 33 1 1 1} {EqEq 34 1 2 1} {NtEq 35 1 2 1} {LsEq 36 1 2 1} {GrEq 37 1 2 1} {Less 38 1 2 1} {Grtr 39 1 2 1} {Trunc 40 1 1 1} {TruncSigned 41 1 1 1} {Convert 42 2 1 1} {Pick 43 1 0 1} {Pop 44 0 1 0} {Insert 45 1 0 0} {ValueRead 46 1 2 1} {ByteSwap 47 1 1 1} {CallSiteValue 48 4 0 0} {PartialValue 49 4 0 0} {PartialValueBit 50 8 0 0} {Swap 51 0 2 2} // swaps the top two entries on the stack {COUNT 52 0 0 0} } // NOTE(rjf): "ck" -> "conversion kind, when converted to type group", used in square matrix form // e.g. x:0, y:0 means other -> other, x:3, y:1 means uint -> f32, etc. @table(name value ck0 ck1 ck2 ck3 ck4) RDI_EvalTypeGroupTable: { {Other 0 OtherToOther FromOther FromOther FromOther FromOther } {U 1 ToOther Noop Noop Legal Legal } {S 2 ToOther Noop Noop Legal Legal } {F32 3 ToOther Legal Legal Noop Legal } {F64 4 ToOther Legal Legal Legal Noop } {COUNT 5 Noop Noop Noop Noop Noop } } @table(name value error_string) RDI_EvalConversionKindTable: { {Noop 0 "" } {Legal 1 "" } {OtherToOther 2 "Cannot convert between these types."} {ToOther 3 "Cannot convert to this type." } {FromOther 4 "Cannot convert this type." } {COUNT 5 "" } } @enum(RDI_U8) RDI_EvalOp: { @expand(RDI_EvalOpTable a) `$(a.name .. =>20) = $(a.value)` } @enum(RDI_U8) RDI_EvalTypeGroup: { @expand(RDI_EvalTypeGroupTable a) `$(a.name .. =>20) = $(a.value)` } @enum(RDI_U8) RDI_EvalConversionKind: { @expand(RDI_EvalConversionKindTable a) `$(a.name .. =>20) = $(a.value)` } @xlist RDI_EvalOp_XList: { @expand(RDI_EvalOpTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_EvalTypeGroup_XList: { @expand(RDI_EvalTypeGroupTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_EvalConversionKind_XList: { @expand(RDI_EvalConversionKindTable a) `$(a.name != COUNT -> a.name)`; } @gen(enums) ``` #define RDI_EVAL_CTRLBITS(decodeN,popN,pushN) (((decodeN) << 8) | ((popN) << 4) | ((pushN) << 0)) #define RDI_DECODEN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 8) & 0xff) #define RDI_POPN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 4) & 0xf) #define RDI_PUSHN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 0) & 0xf) #define RDI_EncodeRegReadParam(reg,bytesize,bytepos) ((reg)|((bytesize)<<8)|((bytepos)<<16)) ``` @data(RDI_U16) rdi_eval_op_ctrlbits_table: { @expand(RDI_EvalOpTable a) `RDI_EVAL_CTRLBITS($(a.num_decodes), $(a.num_pops), $(a.num_pushes))`; } @data(`struct {RDI_EvalConversionKind dst_typegroups[RDI_EvalTypeGroup_COUNT];}`) @c_file rdi_eval_typegroup_conversion_kind_matrix: { @expand(RDI_EvalTypeGroupTable a) `{{RDI_EvalConversionKind_$(a.ck0), RDI_EvalConversionKind_$(a.ck1), RDI_EvalConversionKind_$(a.ck2), RDI_EvalConversionKind_$(a.ck3), RDI_EvalConversionKind_$(a.ck4)}}` } @data(`struct {RDI_U8 *str; RDI_U64 size;}`) @c_file rdi_eval_conversion_kind_message_string_table: { @expand(RDI_EvalConversionKindTable a) `{(RDI_U8 *)"$(a.error_string)", sizeof("$(a.error_string)")}` } //////////////////////////////// //~ rjf: Name Map Tables @table(name value) RDI_NameMapKindTable: { {NULL 0} {GlobalVariables 1} {ThreadVariables 2} {Constants 3} {Procedures 4} {Types 5} {LinkNameProcedures 6} {NormalSourcePaths 7} {COUNT 8} } @table(name type desc) RDI_NameMapMemberTable: { {bucket_base_idx RDI_U32 ""} {node_base_idx RDI_U32 ""} {bucket_count RDI_U32 ""} {node_count RDI_U32 ""} } @table(name type desc) RDI_NameMapBucketMemberTable: { {first_node RDI_U32 ""} {node_count RDI_U32 ""} } @table(name type desc) RDI_NameMapNodeMemberTable: { {string_idx RDI_U32 ""} {match_count RDI_U32 ""} // NOTE: if (match_count == 1) then this is the index of the matching item // if (match_count > 1) then this is the first for an index run of all the matches {match_idx_or_idx_run_first RDI_U32 ""} } @enum(RDI_U32) RDI_NameMapKind: { @expand(RDI_NameMapKindTable a) `$(a.name .. =>20) = $(a.value)` } @xlist RDI_NameMapKind_XList: { @expand(RDI_NameMapKindTable a) `$(a.name != COUNT -> a.name)`; } @xlist RDI_NameMap_XList: { @expand(RDI_NameMapMemberTable a) `$(a.type), $(a.val)` } @xlist RDI_NameMapBucket_XList: { @expand(RDI_NameMapBucketMemberTable a) `$(a.type), $(a.val)` } @xlist RDI_NameMapNode_XList: { @expand(RDI_NameMapNodeMemberTable a) `$(a.type), $(a.val)` } @struct RDI_NameMap: { @expand(RDI_NameMapMemberTable a) `$(a.type) $(a.val)` } @struct RDI_NameMapBucket: { @expand(RDI_NameMapBucketMemberTable a) `$(a.type) $(a.val)` } @struct RDI_NameMapNode: { @expand(RDI_NameMapNodeMemberTable a) `$(a.type) $(a.val)` } //////////////////////////////// //~ rjf: Functions @gen(functions) ``` RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out); RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); ``` @gen(functions) @c_file ``` RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size) { RDI_U64 result = 0; if(size != 0) { result = 5381; RDI_U8 *opl = ptr + size; for(;ptr < opl; ptr += 1) { result = ((result << 5) + result) + *ptr; } } return result; } ``` @gen(functions) @c_file { `RDI_PROC RDI_U8 *`; `rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out)`; `{`; `RDI_U8 *result = 0;`; `*size_out = 0;`; `switch (kind)`; `{`; `default:{}break;`; @expand(RDI_TypeKindTable a) ` case RDI_TypeKind_$(a.name): {result = (RDI_U8*)"$(a.name)"; *size_out = sizeof("$(a.name)")-1;}break;`, `}`; `return result;`; `}`; ``; } @gen(functions) @c_file { `RDI_PROC RDI_U32`; `rdi_size_from_basic_type_kind(RDI_TypeKind kind)`; `{`; `RDI_U32 result = 0;`; `switch(kind)`; `{`; `default:{}break;`; @expand(RDI_TypeKindTable a) `$(a.size != 0 -> " case RDI_TypeKind_" .. a.name .. ":{result = " .. a.size .. ";}break;")`, `}`; `return result;`; `}`; ``; } @gen(functions) @c_file { `RDI_PROC RDI_U32`; `rdi_addr_size_from_arch(RDI_Arch arch)`; `{`; `RDI_U32 result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(RDI_ArchTable a) `$(a.addr_size != 0 -> " case RDI_Arch_" .. a.name .. ":{result = " .. a.addr_size .. ";}break;")`; `}`; `return result;`; `}`; ``; } @gen(functions) @c_file ``` RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out) { RDI_EvalConversionKind k = rdi_eval_typegroup_conversion_kind_matrix[in].dst_typegroups[out]; return k; } ``` @gen(functions) @c_file ``` RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group) { RDI_S32 result = 0; switch(op) { case RDI_EvalOp_Neg: case RDI_EvalOp_Add: case RDI_EvalOp_Sub: case RDI_EvalOp_Mul: case RDI_EvalOp_Div: case RDI_EvalOp_EqEq:case RDI_EvalOp_NtEq: case RDI_EvalOp_LsEq:case RDI_EvalOp_GrEq: case RDI_EvalOp_Less:case RDI_EvalOp_Grtr: { if(group != RDI_EvalTypeGroup_Other) { result = 1; } }break; case RDI_EvalOp_Mod:case RDI_EvalOp_LShift:case RDI_EvalOp_RShift: case RDI_EvalOp_BitNot:case RDI_EvalOp_BitAnd:case RDI_EvalOp_BitXor: case RDI_EvalOp_BitOr:case RDI_EvalOp_LogNot:case RDI_EvalOp_LogAnd: case RDI_EvalOp_LogOr: { if(group == RDI_EvalTypeGroup_S || group == RDI_EvalTypeGroup_U) { result = 1; } }break; } return result; } ``` @gen(functions) @c_file ``` RDI_PROC RDI_U8 * rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out) { *size_out = rdi_eval_conversion_kind_message_string_table[kind].size; return rdi_eval_conversion_kind_message_string_table[kind].str; } ``` @gen(functions) @c_file { `RDI_PROC RDI_SectionKind`; `rdi_section_kind_from_checksum_kind(RDI_ChecksumKind kind)`; `{`; `RDI_SectionKind result = 0;`; `switch(kind)`; `{`; `default:{}break;`; @expand(RDI_ChecksumKindTable a) `case RDI_ChecksumKind_$(a.name):{result = RDI_SectionKind_$(a.section);}break;`, `}`; `return result;`; `}`; ``; } ================================================ FILE: src/rdi/rdi_local.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "lib_rdi/rdi.c" #include "lib_rdi/rdi_parse.c" //////////////////////////////// //~ rjf: RDI Enum <=> Base Enum internal Arch arch_from_rdi_arch(RDI_Arch arch) { Arch result = Arch_Null; switch((RDI_ArchEnum)arch) { case RDI_Arch_NULL:{}break; case RDI_Arch_X86:{result = Arch_x86;}break; case RDI_Arch_X64:{result = Arch_x64;}break; } return result; } //////////////////////////////// //~ rjf: Lookup Helpers internal String8 str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx) { String8 result = {0}; result.str = rdi_string_from_idx(rdi, idx, &result.size); return result; } //////////////////////////////// //~ rjf: String <=> Enum internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);}break; #define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);}break; RDI_SectionKind_XList #undef X } return result; } internal String8 rdi_string_from_arch(Arena *arena, RDI_Arch v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);} break; #define X(name) case RDI_Arch_##name:{result = str8_lit(#name);} break; RDI_Arch_XList #undef X } return result; } internal String8 rdi_string_from_language(Arena *arena, RDI_Language v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);}break; #define X(name) case RDI_Language_##name:{result = str8_lit(#name);}break; RDI_Language_XList #undef X } return result; } internal String8 rdi_string_from_local_kind(Arena *arena, RDI_LocalKind v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);}break; #define X(name) case RDI_LocalKind_##name:{result = str8_lit(#name);}break; RDI_LocalKind_XList #undef X } return result; } #if 0 internal String8 rdi_string_from_type_kind(Arena *arena, RDI_TypeKind v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);}break; #define X(name) case RDI_TypeKind_##name:{result = str8_lit(#name);}break; RDI_TypeKind_XList #undef X } return result; } #endif internal String8 rdi_string_from_member_kind(Arena *arena, RDI_MemberKind v) { String8 result = {0}; switch(v) { default:{result = push_str8f(arena, "", v);}break; #define X(name) case RDI_MemberKind_##name:{result = str8_lit(#name);}break; RDI_MemberKind_XList #undef X } return result; } internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind) { String8 result = {0}; switch(kind) { default:{}break; #define X(name) case RDI_NameMapKind_##name:{result = str8_lit(#name);}break; RDI_NameMapKind_XList #undef X } return result; } internal String8 rdi_string_from_reg_code_x86(U64 reg_code) { String8 result = {0}; switch(reg_code) { default:{}break; #define X(name, value) case RDI_RegCodeX86_##name:{result = str8_lit(#name);}break; RDI_RegCodeX86_XList #undef X } return result; } internal String8 rdi_string_from_reg_code_x64(U64 reg_code) { String8 result = {0}; switch(reg_code) { default:{}break; #define X(name, value) case RDI_RegCodeX64_##name:{result = str8_lit(#name);}break; RDI_RegCodeX64_XList #undef X } return result; } internal String8 rdi_string_from_reg_code(Arena *arena, RDI_Arch arch, U64 reg_code) { String8 result = {0}; switch(arch) { default: case RDI_Arch_NULL: {result = push_str8f(arena, "??? (%llu)", reg_code);}break; case RDI_Arch_X86: {result = rdi_string_from_reg_code_x86(reg_code);}break; case RDI_Arch_X64: {result = rdi_string_from_reg_code_x64(reg_code);}break; } return result; } internal String8 rdi_string_from_eval_op(Arena *arena, RDI_EvalOp op) { String8 result = {0}; switch(op) { default:{result = push_str8f(arena, "%#x", op);}break; #define X(name) case RDI_EvalOp_##name:{result = str8_lit(#name);}break; RDI_EvalOp_XList #undef X } return result; } internal String8 rdi_string_from_eval_type_group(Arena *arena, RDI_EvalTypeGroup eval_type_group) { String8 result = {0}; switch(eval_type_group) { default:{result = push_str8f(arena, "%#x", eval_type_group);}break; #define X(name) case RDI_EvalTypeGroup_##name:{result = str8_lit(#name);}break; RDI_EvalTypeGroup_XList #undef X } return result; } internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; #define X(name) if (flags & RDI_BinarySectionFlag_##name) { flags &= ~RDI_BinarySectionFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } RDI_BinarySectionFlags_XList; #undef X StringJoin join = {.sep = str8_lit("|")}; String8 result = str8_list_join(arena, &list, &join); if(result.size == 0) { result = str8_lit("None"); } scratch_end(scratch); return result; } internal String8 rdi_string_from_type_modifier_flags(Arena *arena, RDI_TypeModifierFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; #define X(name) if(flags & RDI_TypeModifierFlag_##name) { flags &= ~RDI_TypeModifierFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } RDI_TypeModifierFlags_XList; #undef X StringJoin join = {.sep = str8_lit("|")}; String8 result = str8_list_join(arena, &list, &join); if(result.size == 0) { result = str8_lit("None"); } scratch_end(scratch); return result; } internal String8 rdi_string_from_udt_flags(Arena *arena, RDI_UDTFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; #define X(name) if (flags & RDI_UDTFlag_##name) { flags &= ~RDI_UDTFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } RDI_UDTFlags_XList; #undef X StringJoin join = {.sep = str8_lit("|")}; String8 result = str8_list_join(arena, &list, &join); if(result.size == 0) { result = str8_lit("None"); } scratch_end(scratch); return result; } internal String8 rdi_string_from_link_flags(Arena *arena, RDI_LinkFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; #define X(name) if (flags & RDI_LinkFlag_##name) { flags &= ~RDI_LinkFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } RDI_LinkFlags_XList; #undef X StringJoin join = {.sep = str8_lit("|")}; String8 result = str8_list_join(arena, &list, &join); if(result.size == 0) { result = str8_lit("None"); } scratch_end(scratch); return result; } internal String8 rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) { Temp scratch = scratch_begin(&arena, 1); String8List fmt = {0}; for(U64 cursor = 0; cursor < bc.size; ) { RDI_EvalOp op = RDI_EvalOp_Stop; cursor += str8_deserial_read_struct(bc, cursor, &op); U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; U32 imm_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); String8 imm = {0}; cursor += str8_deserial_read_block(bc, cursor, imm_size, &imm); if (imm.size != imm_size) { str8_list_pushf(scratch.arena, &fmt, "(ERROR: not enough bytes to read immediate)"); break; } String8 imm_fmt = {0}; switch (op) { case RDI_EvalOp_Stop: goto exit; case RDI_EvalOp_Noop: break; case RDI_EvalOp_Cond: break; case RDI_EvalOp_Skip: { imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); } break; case RDI_EvalOp_MemRead: { imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); } break; case RDI_EvalOp_RegRead: { U32 regread = *(U32 *)imm.str; RDI_RegCode reg_code = Extract8(regread, 0); U8 byte_size = Extract8(regread, 1); U8 byte_off = Extract8(regread, 2); String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); imm_fmt = push_str8f(scratch.arena, "%S+%I64u, Size: %u", reg_str, byte_off, byte_size); } break; case RDI_EvalOp_RegReadDyn: break; case RDI_EvalOp_FrameOff: { imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); } break; case RDI_EvalOp_ModuleOff: { imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); } break; case RDI_EvalOp_TLSOff: { imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); } break; case RDI_EvalOp_ConstU8: { imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); } break; case RDI_EvalOp_ConstU16: { imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); } break; case RDI_EvalOp_ConstU32: { imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); } break; case RDI_EvalOp_ConstU64: { imm_fmt = push_str8f(scratch.arena, "%llu", *(U64 *)imm.str); } break; case RDI_EvalOp_ConstU128: { imm_fmt = push_str8f(scratch.arena, "Lo: %llu, Hi: %llu", *(U64 *)imm.str, *((U64 *)imm.str + 1)); } break; case RDI_EvalOp_ConstString: { U8 size = *(U8 *)imm.str; String8 string = {0}; cursor += str8_deserial_read_block(bc, cursor, size, &string); imm_fmt = push_str8f(scratch.arena, "(%u) \"%S\"", size, string); } break; case RDI_EvalOp_Abs: case RDI_EvalOp_Neg: case RDI_EvalOp_Add: case RDI_EvalOp_Sub: case RDI_EvalOp_Mul: case RDI_EvalOp_Div: case RDI_EvalOp_Mod: case RDI_EvalOp_LShift: case RDI_EvalOp_RShift: case RDI_EvalOp_BitAnd: case RDI_EvalOp_BitOr: case RDI_EvalOp_BitXor: case RDI_EvalOp_BitNot: case RDI_EvalOp_LogAnd: case RDI_EvalOp_LogOr: case RDI_EvalOp_LogNot: case RDI_EvalOp_EqEq: case RDI_EvalOp_NtEq: case RDI_EvalOp_LsEq: case RDI_EvalOp_GrEq: case RDI_EvalOp_Less: case RDI_EvalOp_Grtr: { U8 eval_type_group = *(U8 *)imm.str; imm_fmt = rdi_string_from_eval_type_group(scratch.arena, eval_type_group); } break; case RDI_EvalOp_Trunc: case RDI_EvalOp_TruncSigned: { U8 trunc = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", trunc); } break; case RDI_EvalOp_Convert: { U16 convert = *(U16 *)imm.str; U8 in = Extract8(convert, 0); U8 out = Extract8(convert, 1); String8 in_str = rdi_string_from_eval_type_group(scratch.arena, in); String8 out_str = rdi_string_from_eval_type_group(scratch.arena, out); imm_fmt = push_str8f(scratch.arena, "in: %S out: %S", in_str, out_str); } break; case RDI_EvalOp_Pick: { U8 pick = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", pick); } break; case RDI_EvalOp_Pop: break; case RDI_EvalOp_Insert: { U8 insert = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", insert); } break; case RDI_EvalOp_ValueRead: { U8 bytes_to_read = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); } break; case RDI_EvalOp_ByteSwap: { U8 byte_size = *(U8 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", byte_size); } break; case RDI_EvalOp_CallSiteValue: { U32 call_site_bc_size = *(U32 *)imm.str; String8 call_site_bc = {0}; cursor += str8_deserial_read_block(bc, cursor, call_site_bc_size, &call_site_bc); String8 call_site_str = rdi_string_from_bytecode(scratch.arena, arch, call_site_bc); imm_fmt = push_str8f(scratch.arena, "%S", call_site_str); } break; case RDI_EvalOp_PartialValue: { U32 partial_value_size = *(U32 *)imm.str; imm_fmt = push_str8f(scratch.arena, "%u", partial_value_size); } break; case RDI_EvalOp_PartialValueBit: { U64 partial_value = *(U64 *)imm.str; U32 bit_size = Extract32(partial_value, 0); U32 bit_off = Extract32(partial_value, 1); imm_fmt = push_str8f(scratch.arena, "Off: %u, Size: %u", bit_size, bit_off); } break; } String8 op_str = rdi_string_from_eval_op(scratch.arena, op); if (imm_fmt.size) { str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S(%S)", op_str, imm_fmt); } else { str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S", op_str); } } exit:; String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); scratch_end(scratch); return result; } internal String8List rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range) { String8List strings = {0}; Temp scratch = scratch_begin(&arena, 1); U64 location_block_count = 0; U64 location_data_size = 0; RDI_LocationBlock *location_block_array = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); Rng1U64 location_block_range_clamped = r1u64(ClampTop(location_block_range.min, location_block_count), ClampTop(location_block_range.max, location_block_count)); for(U64 block_idx = location_block_range_clamped.min; block_idx < location_block_range_clamped.max; block_idx +=1) { String8 qualifier = {0}; String8 location_info = {0}; RDI_LocationBlock *block_ptr = &location_block_array[block_idx]; if(block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32) { qualifier = str8_lit("*always*"); } else { qualifier = push_str8f(scratch.arena, "[%#08x, %#08x): ", block_ptr->scope_off_first, block_ptr->scope_off_opl); } if(block_ptr->location_data_off >= location_data_size) { location_info = push_str8f(scratch.arena, "", block_ptr->location_data_off); } else { U8 *loc_data_opl = location_data + location_data_size; U8 *loc_base_ptr = location_data + block_ptr->location_data_off; RDI_LocationKind kind = *(RDI_LocationKind *)loc_base_ptr; switch(kind) { default: { location_info = push_str8f(scratch.arena, "\?\?\? (%u)", kind); }break; case RDI_LocationKind_AddrBytecodeStream: { String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); location_info = push_str8f(scratch.arena, "AddrBytecodeStream(%S)", bc_str); }break; case RDI_LocationKind_ValBytecodeStream: { String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); location_info = push_str8f(scratch.arena, "ValBytecodeStream(%S)", bc_str); }break; case RDI_LocationKind_AddrRegPlusU16: { if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) { location_info = push_str8f(scratch.arena, "AddrRegPlusU16(\?\?\?)"); } else { RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16*)loc_base_ptr; location_info = push_str8f(scratch.arena, "AddrRegPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); } }break; case RDI_LocationKind_AddrAddrRegPlusU16: { if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) { location_info = push_str8f(scratch.arena, "AddrAddrRegPlusU16(\?\?\?)"); } else { RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16 *)loc_base_ptr; location_info = push_str8f(scratch.arena, "AddrAddrRegisterPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); } }break; case RDI_LocationKind_ValReg: { if(loc_base_ptr + sizeof(RDI_LocationReg) > loc_data_opl) { location_info = push_str8f(scratch.arena, "ValReg(\?\?\?)"); } else { RDI_LocationReg *loc = (RDI_LocationReg*)loc_base_ptr; location_info = push_str8f(scratch.arena, "ValReg(reg: %S)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code)); } } break; } } str8_list_pushf(arena, &strings, "%S: %S", qualifier, location_info); } scratch_end(scratch); return strings; } //////////////////////////////// //~ rjf: RDI Dumping internal String8List rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); String8 indent = str8_lit(" "); ////////////////////////////// //- rjf: set up // typedef struct DumpSubsetOutputNode DumpSubsetOutputNode; struct DumpSubsetOutputNode { DumpSubsetOutputNode *next; RDI_DumpSubset subset; String8List *lane_strings; }; local_persist DumpSubsetOutputNode *first_output_node = 0; local_persist DumpSubsetOutputNode *last_output_node = 0; local_persist String8List result_strings = {0}; String8List *strings = 0; #define dump(str) str8_list_push(arena, strings, (str)) #define dumpf(...) str8_list_pushf(arena, strings, __VA_ARGS__) #define DumpSubset(name) \ if(lane_idx() == 0)\ {\ DumpSubsetOutputNode *n = push_array(scratch.arena, DumpSubsetOutputNode, 1);\ SLLQueuePush(first_output_node, last_output_node, n);\ n->subset = RDI_DumpSubset_##name;\ n->lane_strings = push_array(scratch.arena, String8List, lane_count());\ }\ lane_sync();\ strings = &last_output_node->lane_strings[lane_idx()];\ lane_sync(); if(flags & RDI_DumpSubsetFlag_##name) ProfScope(#name) ////////////////////////////// //- rjf: dump data sections // DumpSubset(DataSections) { if(lane_idx() == 0) { dumpf("\n"); } Rng1U64 range = lane_range(rdi->sections_count); for EachInRange(idx, range) { Temp scratch = scratch_begin(&arena, 1); RDI_SectionKind kind = (RDI_SectionKind)idx; RDI_Section *section = &rdi->sections[idx]; String8 kind_str = rdi_string_from_data_section_kind(scratch.arena, kind); dumpf(" {%#010llx %10u %10u %*s} // data_section[%I64u]\n", section->off, section->encoded_size, section->unpacked_size, 24, kind_str.str, idx); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump top-level-info // DumpSubset(TopLevelInfo) { if(lane_idx() == 0) { RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); Temp scratch = scratch_begin(&arena, 1); Guid guid = {0}; MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid)); dumpf("\n"); dumpf(" arch: %S\n", rdi_string_from_arch(scratch.arena, tli->arch)); dumpf(" exe_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); dumpf(" voff_max: %#08llx\n", tli->voff_max); dumpf(" producer_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); dumpf(" guid: %S\n", string_from_guid(scratch.arena, guid)); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump binary sections // DumpSubset(BinarySections) { if(lane_idx() == 0) { dumpf("\n // %-16s %-16s %-12s %-12s %-12s %s\n", "name", "flags", "voff_first", "voff_opl", "foff_first", "foff_opl"); } U64 count = 0; RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { Temp scratch = scratch_begin(&arena, 1); RDI_BinarySection *bin_section = &v[idx]; String8 name = str8_from_rdi_string_idx(rdi, bin_section->name_string_idx); String8 flags = rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags); dumpf(" { %-16S %-16S 0x%-10I64x 0x%-10I64x 0x%-10I64x 0x%-10I64x } // binary_section[%I64u]\n", push_str8f(scratch.arena, "'%S'", name), push_str8f(scratch.arena, "`%S`", flags), bin_section->voff_first, bin_section->voff_opl, bin_section->foff_first, bin_section->foff_opl, idx); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump file paths // DumpSubset(FilePaths) { if(lane_idx() == 0) { dumpf("\n"); } U64 count = 0; RDI_FilePathNode *v = rdi_table_from_name(rdi, FilePathNodes, &count); RDI_FilePathNode *nil = &v[0]; Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_FilePathNode *root = &v[idx]; if(root->parent_path_node != 0) { continue; } S64 depth = 1; for(RDI_FilePathNode *n = root, *rec_next = nil; n != nil; n = rec_next) { // rjf: dump if(n->source_file_idx == 0) { dumpf("%.*s'%S'%s // file_path_node[%I64u]\n", depth*2, indent.str, str8_from_rdi_string_idx(rdi, n->name_string_idx), n->first_child ? ":" : "", (U64)(n - v)); } else { dumpf("%.*s'%S': source_file: %u // file_path_node[%I64u]\n", depth*2, indent.str, str8_from_rdi_string_idx(rdi, n->name_string_idx), n->source_file_idx, (U64)(n - v)); } // rjf: find next node rec_next = nil; if(n->first_child) { dumpf("%.*s{\n", depth*2, indent.str); rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, n->first_child); depth += 1; } else for(RDI_FilePathNode *p = n; p != nil && p != root; p = rdi_element_from_name_idx(rdi, FilePathNodes, p->parent_path_node), depth -= 1) { if(p->next_sibling) { rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, p->next_sibling); break; } dumpf("%.*s}\n", (depth-1)*2, indent.str); } } } } ////////////////////////////// //- rjf: dump source files // DumpSubset(SourceFiles) { U64 count = 0; RDI_SourceFile *v = rdi_table_from_name(rdi, SourceFiles, &count); U64 checksums_count[RDI_ChecksumKind_COUNT] = {0}; RDI_U8 *checksums_data[RDI_ChecksumKind_COUNT] = {0}; RDI_U64 checksums_element_sizes[RDI_ChecksumKind_COUNT] = {0}; for EachEnumVal(RDI_ChecksumKind, k) { RDI_SectionKind section_kind = rdi_section_kind_from_checksum_kind(k); checksums_data[k] = rdi_section_raw_table_from_kind(rdi, section_kind, &checksums_count[k]); checksums_element_sizes[k] = rdi_section_element_size_table[section_kind]; } Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_SourceFile *source_file = &v[idx]; RDI_ChecksumKind checksum_kind = source_file->checksum_kind; RDI_U32 checksum_idx = source_file->checksum_idx; String8 checksum_kind_name = {0}; switch(checksum_kind) { default:{checksum_kind_name = str8_lit("Null");}break; #define X(name, s) case RDI_ChecksumKind_##name:{checksum_kind_name = str8_lit(#name);}break; RDI_ChecksumKind_XList #undef X } String8 checksum_value = str8(checksums_data[checksum_kind] + checksums_element_sizes[checksum_kind]*checksum_idx, checksums_element_sizes[checksum_kind]); String8List checksum_vals = numeric_str8_list_from_data(arena, 16, checksum_value, 1); StringJoin join = {0}; join.sep = str8_lit(", "); String8 checksum_val_string = str8_list_join(arena, &checksum_vals, &join); dumpf("\n { file_path_node_idx: %4u, source_line_map: %4u, checksum_kind: %10S, checksum_value: %192S, path: %-192S } // source_file[%I64u]", source_file->file_path_node_idx, source_file->source_line_map_idx, checksum_kind_name, checksum_val_string, push_str8f(arena, "'%S'", str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)), idx); } if(lane_idx() == lane_count()-1) { dumpf("\n"); } } ////////////////////////////// //- rjf: dump units // DumpSubset(Units) { U64 count = 0; RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_Unit *unit = &v[idx]; Temp scratch = scratch_begin(&arena, 1); dumpf("\n // unit[%I64u]\n {\n", idx); dumpf(" unit_name: '%S'\n", str8_from_rdi_string_idx(rdi, unit->unit_name_string_idx)); dumpf(" compiler_name: '%S'\n", str8_from_rdi_string_idx(rdi, unit->compiler_name_string_idx)); dumpf(" source_file_path: %u\n", unit->source_file_path_node); dumpf(" object_file_path: %u\n", unit->object_file_path_node); dumpf(" archive_file_path: %u\n", unit->archive_file_path_node); dumpf(" build_path: %u\n", unit->build_path_node); dumpf(" language: %S\n", rdi_string_from_language(scratch.arena, unit->language)); dumpf(" line_table_idx: %u\n", unit->line_table_idx); dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump unit vmap // DumpSubset(UnitVMap) { if(lane_idx() == 0) { dumpf("\n"); } U64 count = 0; RDI_VMapEntry *v = rdi_table_from_name(rdi, UnitVMap, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { dumpf(" {0x%I64x => %I64u}\n", v[idx].voff, v[idx].idx); } } ////////////////////////////// //- rjf: dump line tables // DumpSubset(LineTables) { U64 count = 0; RDI_LineTable *v = rdi_table_from_name(rdi, LineTables, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_LineTable *line_table = &v[idx]; RDI_ParsedLineTable parsed_line_table = {0}; rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); dumpf("\n // line_table[%I64u]\n {\n", idx); for EachIndex(line_idx, parsed_line_table.count) { U64 first = parsed_line_table.voffs[line_idx]; U64 opl = parsed_line_table.voffs[line_idx + 1]; RDI_Line *line = parsed_line_table.lines + line_idx; RDI_Column *col = 0; if(line_idx < parsed_line_table.col_count) { col = parsed_line_table.cols + line_idx; } if(col == 0) { dumpf(" { [0x%08I64x, 0x%08I64x) file: %u, line: %u }\n", first, opl, line->file_idx, line->line_num); } else { dumpf(" { [0x%08I64x, 0x%08I64x) file: %u, line: %u, columns: [%u, %u) }\n", first, opl, line->file_idx, line->line_num, col->col_first, col->col_opl); } } dumpf(" }\n"); } } ////////////////////////////// //- rjf: dump source line maps // DumpSubset(SourceLineMaps) { U64 count = 0; RDI_SourceLineMap *v = rdi_table_from_name(rdi, SourceLineMaps, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { Temp scratch = scratch_begin(&arena, 1); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, &v[idx], &line_map); dumpf("\n // source_line_map[%I64u]\n {\n", idx); for EachIndex(line_num_idx, line_map.count) { Temp temp = temp_begin(scratch.arena); String8List list = {0}; U32 voff_lo = line_map.ranges[line_num_idx]; U32 voff_hi = ClampTop(line_map.ranges[line_num_idx + 1], line_map.voff_count); for(U64 voff_idx = voff_lo; voff_idx < voff_hi; voff_idx += 1) { str8_list_pushf(temp.arena, &list, "%#llx", line_map.voffs[voff_idx]); } String8 voffs_string = str8_list_join(temp.arena, &list, &(StringJoin){.sep = str8_lit(", ")}); dumpf(" %u: (%S)\n", line_map.nums[line_num_idx], voffs_string); temp_end(temp); } dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump type nodes // DumpSubset(TypeNodes) { U64 count = 0; RDI_TypeNode *v = rdi_table_from_name(rdi, TypeNodes, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { Temp scratch = scratch_begin(&arena, 1); RDI_TypeNode *type = &v[idx]; String8 type_kind_str = {0}; type_kind_str.str = rdi_string_from_type_kind(type->kind, &type_kind_str.size); dumpf("\n // type[%I64u]\n {\n", idx); dumpf(" kind: %S\n", type_kind_str); if(type->kind == RDI_TypeKind_Modifier) { dumpf(" flags: %S\n", rdi_string_from_type_modifier_flags(scratch.arena, type->flags)); } else if(type->flags != 0) { dumpf(" flags: %#x (missing stringizer path)\n", type->flags); } dumpf(" byte_size: %u\n", type->byte_size); if(RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) { dumpf(" name: '%S'\n", str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx)); } else if(type->kind == RDI_TypeKind_Array) { dumpf(" constructed__direct_type: %u\n", type->constructed.direct_type_idx); dumpf(" constructed__array_count: %u\n", type->constructed.count); } else if(type->kind == RDI_TypeKind_Function) { U32 param_idx_count = 0; U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); String8List param_idx_strings = {0}; for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) { str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); } String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); dumpf(" constructed__params: %S // idx_run[%u]\n", param_idx_str, type->constructed.param_idx_run_first); dumpf(" return_type: %u\n", type->constructed.direct_type_idx); } else if(type->kind == RDI_TypeKind_Method) { U32 param_idx_count = 0; U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); String8 this_type_str = str8_lit("\?\?\?"); if(param_idx_count > 0) { this_type_str = push_str8f(scratch.arena, "%u", param_idx_array[0]); param_idx_count -= 1; param_idx_array += 1; } String8List param_idx_strings = {0}; for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) { str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); } String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); dumpf(" constructed__this_type: %S // idx_run[%u]\n", this_type_str, type->constructed.param_idx_run_first); dumpf(" constructed__params: %S // idx_run[%u]\n", param_idx_str, type->constructed.param_idx_run_first); dumpf(" return_type: %u\n", type->constructed.direct_type_idx); } else if(RDI_TypeKind_FirstConstructed <= type->kind && type->kind <= RDI_TypeKind_LastConstructed) { dumpf(" constructed__direct_type: %u\n", type->constructed.direct_type_idx); } else if(RDI_TypeKind_FirstUserDefined <= type->kind && type->kind <= RDI_TypeKind_LastUserDefined) { dumpf(" name: '%S'\n", str8_from_rdi_string_idx(rdi, type->user_defined.name_string_idx)); dumpf(" user_defined__direct_type: %u\n", type->user_defined.direct_type_idx); dumpf(" user_defined__udt: %u\n", type->user_defined.udt_idx); } else if(type->kind == RDI_TypeKind_Bitfield) { dumpf(" bitfield__off: %u\n", type->bitfield.off); dumpf(" bitfield__size: %u\n", type->bitfield.size); } dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump user defined types // DumpSubset(UserDefinedTypes) { U64 count = 0; RDI_UDT *v = rdi_table_from_name(rdi, UDTs, &count); U64 all_members_count = 0; RDI_Member *all_members = rdi_table_from_name(rdi, Members, &all_members_count); U64 all_enum_members_count = 0; RDI_EnumMember *all_enum_members = rdi_table_from_name(rdi, EnumMembers, &all_enum_members_count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_UDT *udt = &v[idx]; Temp scratch = scratch_begin(&arena, 1); dumpf("\n // udt[%I64u]\n {\n", idx); dumpf(" self_type: %u\n", udt->self_type_idx); dumpf(" flags: `%S`\n", rdi_string_from_udt_flags(scratch.arena, udt->flags)); if(udt->file_idx != 0) { dumpf(" loc: {file: %u, line: %u, col: %u}\n", udt->file_idx, udt->line, udt->col); } if(udt->flags & RDI_UDTFlag_EnumMembers) { U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_enum_members_count); U32 member_lo = ClampTop(udt->member_first, member_hi); if(member_lo < member_hi) { dumpf(" enum_members:\n"); dumpf(" {\n"); for(U32 enum_member_idx = member_lo; enum_member_idx < member_hi; enum_member_idx += 1) { RDI_EnumMember *enum_member = &all_enum_members[enum_member_idx]; dumpf(" '%S': %I64u\n", str8_from_rdi_string_idx(rdi, enum_member->name_string_idx), enum_member->val); } dumpf(" }\n"); } } else { U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_members_count); U32 member_lo = ClampTop(udt->member_first, member_hi); if(member_lo < member_hi) { dumpf(" members:\n"); dumpf(" {\n"); for(U32 member_idx = member_lo; member_idx < member_hi; member_idx += 1) { RDI_Member *member = &all_members[member_idx]; String8 kind_str = rdi_string_from_member_kind(scratch.arena, member->kind); String8 name_str = str8_from_rdi_string_idx(rdi, member->name_string_idx); dumpf(" '%S': { kind: %S, type: %u, off: %u }\n", name_str, kind_str, member->type_idx, member->off); } dumpf(" }\n"); } } dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump global variables // DumpSubset(GlobalVariables) { U64 count = 0; RDI_GlobalVariable *v = rdi_table_from_name(rdi, GlobalVariables, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_GlobalVariable *gvar = &v[idx]; Temp scratch = scratch_begin(&arena, 1); dumpf("\n '%S': // global_variable[%I64u]\n {\n", str8_from_rdi_string_idx(rdi, gvar->name_string_idx), idx); dumpf(" link_flags: `%S`\n", rdi_string_from_link_flags(scratch.arena, gvar->link_flags)); dumpf(" voff: %#08x\n", gvar->voff); dumpf(" type_idx: %u\n", gvar->type_idx); dumpf(" container_idx: %u\n", gvar->container_idx); dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump global variables vmap // DumpSubset(GlobalVariablesVMap) { if(lane_idx() == 0) { dumpf("\n"); } U64 count = 0; RDI_VMapEntry *v = rdi_table_from_name(rdi, GlobalVMap, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { dumpf(" {0x%I64x => %I64u}\n", v[idx].voff, v[idx].idx); } } ////////////////////////////// //- rjf: dump thread variables // DumpSubset(ThreadVariables) { U64 count = 0; RDI_ThreadVariable *v = rdi_table_from_name(rdi, ThreadVariables, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_ThreadVariable *tvar = &v[idx]; Temp scratch = scratch_begin(&arena, 1); dumpf("\n '%S': // thread_variable[%I64u]\n {\n", str8_from_rdi_string_idx(rdi, tvar->name_string_idx), idx); dumpf(" link_flags: `%S`\n", rdi_string_from_link_flags(scratch.arena, tvar->link_flags)); dumpf(" tls_off: %#08x\n", tvar->tls_off); dumpf(" type_idx: %u\n", tvar->type_idx); dumpf(" container_idx: %u\n", tvar->container_idx); dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump constants // DumpSubset(Constants) { U64 count = 0; RDI_Constant *v = rdi_table_from_name(rdi, Constants, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_Constant *cnst = &v[idx]; dumpf("\n '%S': // constant[%I64u]\n {\n", str8_from_rdi_string_idx(rdi, cnst->name_string_idx), idx); dumpf(" type_idx: %u\n", cnst->type_idx); dumpf(" }\n"); } } ////////////////////////////// //- rjf: dump procedures // DumpSubset(Procedures) { RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); U64 count = 0; RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_Procedure *proc = &v[idx]; Temp scratch = scratch_begin(&arena, 1); dumpf("\n '%S': // procedure[%I64u]\n {\n", str8_from_rdi_string_idx(rdi, proc->name_string_idx), idx); dumpf(" link_name: '%S'\n", str8_from_rdi_string_idx(rdi, proc->link_name_string_idx)); dumpf(" link_flags: `%S`\n", rdi_string_from_link_flags(scratch.arena, proc->link_flags)); dumpf(" type_idx: %u\n", proc->type_idx); dumpf(" root_scope_idx: %u\n", proc->root_scope_idx); dumpf(" container_idx: %u\n", proc->container_idx); if(proc->frame_base_location_first != 0) { String8List frame_base_location_strings = rdi_strings_from_locations(scratch.arena, rdi, tli->arch, r1u64(proc->frame_base_location_first, proc->frame_base_location_opl)); dumpf(" frame_base: // (first: %u, opl: %u)\n", proc->frame_base_location_first, proc->frame_base_location_opl); dumpf(" {\n"); for(String8Node *n = frame_base_location_strings.first; n != 0; n = n->next) { dumpf(" %S\n", n->string); } dumpf(" }\n"); } dumpf(" }\n"); scratch_end(scratch); } } ////////////////////////////// //- rjf: dump scopes // DumpSubset(Scopes) { if(lane_idx() == 0) { dumpf("\n"); } RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); U64 scope_voffs_count = 0; U64 *scope_voffs = rdi_table_from_name(rdi, ScopeVOffData, &scope_voffs_count); U64 locals_count = 0; RDI_Local *locals = rdi_table_from_name(rdi, Locals, &locals_count); U64 count = 0; RDI_Scope *v = rdi_table_from_name(rdi, Scopes, &count); RDI_Scope *nil = &v[0]; Rng1U64 range = lane_range(count); for EachInRange(idx, range) { if(v[idx].parent_scope_idx != 0) { continue; } RDI_Scope *root = &v[idx]; S64 depth = 1; for(RDI_Scope *scope = root, *rec_next = nil; scope != nil; scope = rec_next) { // rjf: scope list(voff_range) => string String8 voff_range_list_string = {0}; { U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voffs_count); U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voffs_count); U32 voff_range_count = (voff_range_hi - voff_range_lo); U64 *voff_ptr = scope_voffs + voff_range_lo; Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; for(U64 i = 0; i+2 <= voff_range_count; i += 2) { str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", voff_ptr[i+0], voff_ptr[i+1]); } voff_range_list_string = str8_list_join(arena, &list, &(StringJoin){.sep = str8_lit(", ")}); scratch_end(scratch); } // rjf: scope procedure -> name String8 procedure_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx)->name_string_idx); if(procedure_name.size == 0) { procedure_name = str8_lit("???"); } // rjf: scope inline site -> name String8 inline_site_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, InlineSites, scope->inline_site_idx)->name_string_idx); if(inline_site_name.size == 0) { inline_site_name = str8_lit("???"); } // rjf: dump dumpf("%.*s// scope[%I64u]\n", depth*2, indent.str, (U64)(scope - v)); dumpf("%.*s{\n", depth*2, indent.str); dumpf("%.*s proc_idx: %u // %S\n", depth*2, indent.str, scope->proc_idx, procedure_name); dumpf("%.*s first_child_scope_idx: %u\n", depth*2, indent.str, scope->first_child_scope_idx); dumpf("%.*s next_sibling_scope_idx: %u\n", depth*2, indent.str, scope->next_sibling_scope_idx); if(scope->inline_site_idx != 0) { dumpf("%.*s inline_site_idx: %u ('%S')\n", depth*2, indent.str, scope->inline_site_idx, inline_site_name); } dumpf("%.*s voff_ranges: %S\n", depth*2, indent.str, voff_range_list_string); dumpf("%.*s locals:\n", depth*2, indent.str); dumpf("%.*s {\n", depth*2, indent.str); { U32 local_lo = ClampTop(scope->local_first, locals_count); U32 local_hi = ClampTop(local_lo + scope->local_count, locals_count); if(local_lo < local_hi) { for(U32 local_idx = local_lo; local_idx < local_hi; local_idx += 1) { Temp scratch = scratch_begin(&arena, 1); RDI_Local *local_ptr = &locals[local_idx]; dumpf("%.*s '%S': // local[%u]\n", depth*2, indent.str, str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx), local_idx); dumpf("%.*s {\n", depth*2, indent.str); dumpf("%.*s kind: %S\n", depth*2, indent.str, rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); dumpf("%.*s type_idx: %u\n", depth*2, indent.str, local_ptr->type_idx); dumpf("%.*s locations:\n", depth*2, indent.str); dumpf("%.*s {\n", depth*2, indent.str); if(local_ptr->location_first < local_ptr->location_opl) { String8List locations_strings = rdi_strings_from_locations(arena, rdi, tli->arch, r1u64(local_ptr->location_first, local_ptr->location_opl)); for(String8Node *n = locations_strings.first; n != 0; n = n->next) { dumpf("%.*s %S\n", depth*2, indent.str, n->string); } } dumpf("%.*s }\n", depth*2, indent.str); dumpf("%.*s }\n", depth*2, indent.str); scratch_end(scratch); } } } dumpf("%.*s }\n", depth*2, indent.str); // rjf: get next recursion rec_next = nil; if(scope->first_child_scope_idx) { rec_next = rdi_element_from_name_idx(rdi, Scopes, scope->first_child_scope_idx); depth += 1; } else for(RDI_Scope *p = scope; p != nil; p = rdi_element_from_name_idx(rdi, Scopes, p->parent_scope_idx), depth -= 1) { dumpf("%.*s} // scope[/%I64u] \n", depth*2, indent.str, (U64)(p-v)); if(p->next_sibling_scope_idx != 0) { rec_next = rdi_element_from_name_idx(rdi, Scopes, p->next_sibling_scope_idx); break; } } } } } ////////////////////////////// //- rjf: dump scope vmap // DumpSubset(ScopeVMap) { if(lane_idx() == 0) { dumpf("\n"); } U64 count = 0; RDI_VMapEntry *v = rdi_table_from_name(rdi, ScopeVMap, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { dumpf(" {0x%I64x => %I64u}\n", v[idx].voff, v[idx].idx); } } ////////////////////////////// //- rjf: dump inline sites // DumpSubset(InlineSites) { U64 count = 0; RDI_InlineSite *v = rdi_table_from_name(rdi, InlineSites, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_InlineSite *inline_site = &v[idx]; Temp scratch = scratch_begin(&arena, 1); String8 inline_site_idx = push_str8f(scratch.arena, "inline_site[%u]", idx); String8 type_idx = push_str8f(scratch.arena, "type_idx: %u,", inline_site->type_idx); String8 owner_type_idx = push_str8f(scratch.arena, "owner_type_idx: %u,", inline_site->owner_type_idx); String8 line_table_idx = push_str8f(scratch.arena, "line_table_idx: %u,", inline_site->line_table_idx); String8 name = push_str8f(scratch.arena, "'%S'", str8_from_rdi_string_idx(rdi, inline_site->name_string_idx)); dumpf("\n { %-25S %-25S %-25S name: %-64S } // %S", type_idx, owner_type_idx, line_table_idx, name, inline_site_idx); scratch_end(scratch); } if(lane_idx() == lane_count()-1) { dumpf("\n"); } } ////////////////////////////// //- rjf: dump name maps // DumpSubset(NameMaps) { Temp scratch = scratch_begin(&arena, 1); U64 count = 0; RDI_NameMap *v = rdi_table_from_name(rdi, NameMaps, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { RDI_ParsedNameMap name_map = {0}; rdi_parsed_from_name_map(rdi, &v[idx], &name_map); dumpf("\n // name_map[%I64u] (%S)\n {\n", idx, rdi_string_from_name_map_kind(idx)); for EachIndex(bucket_idx, name_map.bucket_count) { if(name_map.buckets[bucket_idx].node_count == 0) { continue; } dumpf(" %I64u:\n {\n", bucket_idx, bucket_idx); RDI_NameMapNode *node_ptr = name_map.nodes + name_map.buckets[bucket_idx].first_node; RDI_NameMapNode *node_opl = node_ptr + name_map.buckets[bucket_idx].node_count; for(;node_ptr < node_opl; node_ptr += 1) { Temp temp = temp_begin(scratch.arena); String8 str = str8_from_rdi_string_idx(rdi, node_ptr->string_idx); String8 indices = {0}; if(node_ptr->match_count == 1) { indices = push_str8f(temp.arena, "%u", node_ptr->match_idx_or_idx_run_first); } else { U32 idx_count = 0; U32 *idx_array = rdi_idx_run_from_first_count(rdi, node_ptr->match_idx_or_idx_run_first, node_ptr->match_count, &idx_count); String8List idx_strings = {0}; for(U32 idx_i = 0; idx_i < idx_count; idx_i += 1) { U32 idx = idx_array[idx_i]; str8_list_pushf(temp.arena, &idx_strings, "%u", idx); } String8 extra = push_str8f(temp.arena, " // idx_run[%u]", node_ptr->match_idx_or_idx_run_first); indices = str8_list_join(scratch.arena, &idx_strings, &(StringJoin){.sep = str8_lit(", "), .post = extra}); } dumpf(" \"%S\": %S\n", str, indices); temp_end(temp); } dumpf(" }\n"); } dumpf(" }\n"); } scratch_end(scratch); } ////////////////////////////// //- rjf: dump strings // DumpSubset(Strings) { U64 count = 0; U32 *v = rdi_table_from_name(rdi, StringTable, &count); Rng1U64 range = lane_range(count); for EachInRange(idx, range) { dumpf("\n \"%S\" // string[%I64u]", str8_from_rdi_string_idx(rdi, idx), idx); } if(lane_idx() == lane_count()-1) { dumpf("\n"); } } ////////////////////////////// //- rjf: join results // lane_sync(); if(lane_idx() == 0) { for EachNode(n, DumpSubsetOutputNode, first_output_node) { String8List subset_strings = {0}; for EachIndex(idx, lane_count()) { str8_list_concat_in_place(&subset_strings, &n->lane_strings[idx]); } if(subset_strings.total_size != 0) { str8_list_pushf(arena, &result_strings, "////////////////////////////////\n//~ %S\n\n%S:\n{", rdi_name_title_from_dump_subset_table[n->subset], rdi_name_lowercase_from_dump_subset_table[n->subset]); str8_list_concat_in_place(&result_strings, &subset_strings); str8_list_pushf(arena, &result_strings, "}\n\n"); } } } lane_sync(); #undef DumpSubset #undef dumpf #undef dump scratch_end(scratch); ProfEnd(); return result_strings; } ================================================ FILE: src/rdi/rdi_local.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FORMAT_LOCAL_H #define RDI_FORMAT_LOCAL_H #include "lib_rdi/rdi.h" #include "lib_rdi/rdi_parse.h" //////////////////////////////// //~ rjf: RDI Dumping Flags #define RDI_DumpSubset_XList \ X(DataSections, data_sections, "DATA SECTIONS")\ X(TopLevelInfo, top_level_info, "TOP LEVEL INFO")\ X(BinarySections, binary_sections, "BINARY SECTIONS")\ X(FilePaths, file_paths, "FILE PATHS")\ X(SourceFiles, source_files, "SOURCE FILES")\ X(LineTables, line_tables, "LINE TABLES")\ X(SourceLineMaps, source_line_maps, "SOURCE LINE MAPS")\ X(Units, units, "UNITS")\ X(UnitVMap, unit_vmap, "UNIT VMAP")\ X(TypeNodes, type_nodes, "TYPE NODES")\ X(UserDefinedTypes, user_defined_types, "USER DEFINED TYPES")\ X(GlobalVariables, global_variables, "GLOBAL VARIABLES")\ X(GlobalVariablesVMap, global_variables_vmap, "GLOBAL VARIABLE VMAP")\ X(ThreadVariables, thread_variables, "THREAD VARIABLES")\ X(Constants, constants, "CONSTANTS")\ X(Procedures, procedures, "PROCEDURES")\ X(Scopes, scopes, "SCOPES")\ X(ScopeVMap, scope_vmap, "SCOPE VMAP")\ X(InlineSites, inline_sites, "INLINE SITES")\ X(NameMaps, name_maps, "NAME MAPS")\ X(Strings, strings, "STRINGS")\ typedef enum RDI_DumpSubset { #define X(name, name_lower, title) RDI_DumpSubset_##name, RDI_DumpSubset_XList #undef X } RDI_DumpSubset; typedef U32 RDI_DumpSubsetFlags; enum { #define X(name, name_lower, title) RDI_DumpSubsetFlag_##name = (1< Base Enum internal Arch arch_from_rdi_arch(RDI_Arch arch); //////////////////////////////// //~ rjf: Lookup Helpers internal String8 str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx); //////////////////////////////// //~ rjf: String <=> Enum internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v); internal String8 rdi_string_from_arch (Arena *arena, RDI_Arch v); internal String8 rdi_string_from_language (Arena *arena, RDI_Language v); internal String8 rdi_string_from_local_kind (Arena *arena, RDI_LocalKind v); #if 0 // TODO(rjf): conflicts with RDI... internal String8 rdi_string_from_type_kind (Arena *arena, RDI_TypeKind v); #endif internal String8 rdi_string_from_member_kind (Arena *arena, RDI_MemberKind v); internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind); internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags); internal String8 rdi_string_from_type_modifier (Arena *arena, RDI_TypeModifierFlags flags); internal String8 rdi_string_from_udt_flags (Arena *arena, RDI_UDTFlags flags); internal String8 rdi_string_from_link_flags (Arena *arena, RDI_LinkFlags flags); internal String8 rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc); internal String8List rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range); //////////////////////////////// //~ rjf: RDI Dumping internal String8List rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags); #endif // RDI_FORMAT_LOCAL_H ================================================ FILE: src/rdi_from_coff/rdi_from_coff.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDI_Arch c2r_rdi_arch_from_coff_machine(COFF_MachineType machine) { switch (machine) { case COFF_MachineType_X86: return RDI_Arch_X86; case COFF_MachineType_X64: return RDI_Arch_X64; case COFF_MachineType_Unknown: case COFF_MachineType_Am33: case COFF_MachineType_Arm: case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: case COFF_MachineType_Ebc: case COFF_MachineType_Ia64: case COFF_MachineType_M32R: case COFF_MachineType_Mips16: case COFF_MachineType_MipsFpu: case COFF_MachineType_MipsFpu16: case COFF_MachineType_PowerPc: case COFF_MachineType_PowerPcFp: case COFF_MachineType_R4000: case COFF_MachineType_RiscV32: case COFF_MachineType_RiscV64: case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp: case COFF_MachineType_Sh4: case COFF_MachineType_Sh5: case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2: NotImplemented; default: return RDI_Arch_NULL; } } internal RDI_BinarySectionFlags c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) { RDI_BinarySectionFlags result = 0; if(flags & COFF_SectionFlag_MemRead) { result |= RDI_BinarySectionFlag_Read; } if(flags & COFF_SectionFlag_MemWrite) { result |= RDI_BinarySectionFlag_Write; } if(flags & COFF_SectionFlag_MemExecute) { result |= RDI_BinarySectionFlag_Execute; } return(result); } internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab) { RDIM_BinarySectionList binary_sections = {0}; for EachIndex(idx, sectab_count) { COFF_SectionHeader *coff_sec = §ab[idx]; RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); sec->name = coff_name_from_section_header(string_table, coff_sec); sec->flags = c2r_rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags); sec->voff_first = coff_sec->voff; sec->voff_opl = coff_sec->voff + coff_sec->vsize; sec->foff_first = coff_sec->foff; sec->foff_opl = coff_sec->foff + coff_sec->fsize; } return binary_sections; } ================================================ FILE: src/rdi_from_coff/rdi_from_coff.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FROM_COFF_H #define RDI_FROM_COFF_H internal RDI_Arch c2r_rdi_arch_from_coff_machine(COFF_MachineType machine); internal RDI_BinarySectionFlags c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags); internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab); #endif // RDI_FROM_COFF_H ================================================ FILE: src/rdi_from_dwarf/rdi_from_dwarf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO: // // [ ] Currently converter relies on clang's -gdwarf-aranges to generate compile unit ranges, // however it is optional and in case it is missing converter has to generate the ranges from scopes. // [ ] Error handling //////////////////////////////// static const U64 UNIT_CHUNK_CAP = 256; static const U64 UDT_CHUNK_CAP = 256; static const U64 TYPE_CHUNK_CAP = 256; static const U64 SRC_FILE_CAP = 256; static const U64 LINE_TABLE_CAP = 256; static const U64 LOCATIONS_CAP = 256; static const U64 GVAR_CHUNK_CAP = 256; static const U64 TVAR_CHUNK_CAP = 256; static const U64 PROC_CHUNK_CAP = 256; static const U64 SCOPE_CHUNK_CAP = 256; static const U64 INLINE_SITE_CHUNK_CAP = 256; RDIM_TopLevelInfo top_level_info = {0}; RDIM_BinarySectionList binary_sections = {0}; RDIM_UnitChunkList units = {0}; RDIM_UDTChunkList udts = {0}; RDIM_TypeChunkList types = {0}; RDIM_SrcFileChunkList src_files = {0}; RDIM_LineTableChunkList line_tables = {0}; RDIM_LocationChunkList locations = {0}; RDIM_SymbolChunkList gvars = {0}; RDIM_SymbolChunkList tvars = {0}; RDIM_SymbolChunkList procs = {0}; RDIM_ScopeChunkList scopes = {0}; RDIM_InlineSiteChunkList inline_sites = {0}; //////////////////////////////// //~ rjf: Enum Conversion Helpers internal RDI_Language d2r_rdi_language_from_dw_language(DW_Language v) { RDI_Language result = RDI_Language_NULL; switch(v) { default:{}break; case DW_Language_C89: case DW_Language_C99: case DW_Language_C11: case DW_Language_C: { result = RDI_Language_C; }break; case DW_Language_CPlusPlus03: case DW_Language_CPlusPlus11: case DW_Language_CPlusPlus14: case DW_Language_CPlusPlus: { result = RDI_Language_CPlusPlus; }break; } return result; } internal RDI_RegCodeX86 d2r_rdi_reg_code_from_dw_reg_x86(DW_RegX86 v) { RDI_RegCodeX86 result = RDI_RegCode_nil; switch(v) { default:{}break; #define X(reg_dw, val_dw, reg_rdi, ...) case DW_RegX86_##reg_dw:{result = RDI_RegCodeX86_##reg_rdi;}break; DW_Regs_X86_XList(X) #undef X } return result; } internal RDI_RegCodeX64 d2r_rdi_reg_code_from_dw_reg_x64(DW_RegX64 v) { RDI_RegCodeX64 result = RDI_RegCode_nil; switch(v) { default:{}break; #define X(reg_dw, val_dw, reg_rdi, off, size) case DW_RegX64_##reg_dw:{result = RDI_RegCodeX64_##reg_rdi;}break; DW_Regs_X64_XList(X) #undef X } return result; } internal RDI_RegCode d2r_rdi_reg_code_from_dw_reg(Arch arch, DW_Reg v) { RDI_RegCode result = RDI_RegCode_nil; switch(arch) { default: case Arch_Null: {}break; case Arch_x86:{result = d2r_rdi_reg_code_from_dw_reg_x86(v);}break; case Arch_x64:{result = d2r_rdi_reg_code_from_dw_reg_x64(v);}break; } return result; } //////////////////////////////// //~ rjf: Type Conversion Helpers internal RDIM_Type * d2r_create_type(Arena *arena, D2R_TypeTable *type_table) { RDIM_Type *type = rdim_type_chunk_list_push(arena, type_table->types, type_table->type_chunk_cap); return type; } internal RDIM_Type * d2r_create_type_from_offset(Arena *arena, D2R_TypeTable *type_table, U64 info_off) { RDIM_Type *type = d2r_create_type(arena, type_table); Assert(hash_table_search_u64_raw(type_table->ht, info_off) == 0); hash_table_push_u64_raw(arena, type_table->ht, info_off, type); return type; } internal RDIM_Type * d2r_type_from_offset(D2R_TypeTable *type_table, U64 info_off) { RDIM_Type *type = hash_table_search_u64_raw(type_table->ht, info_off); if (type == 0) { type = type_table->builtin_types[RDI_TypeKind_NULL]; } return type; } internal RDIM_Type * d2r_type_from_attrib(D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { RDIM_Type *type = type_table->builtin_types[RDI_TypeKind_Void]; // find attrib DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); // does tag have this attribute? if (attrib->attrib_kind == kind) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); if (value_class == DW_AttribClass_Reference) { // resolve reference DW_Reference ref = dw_ref_from_attrib(input, cu, attrib); // TODO: support for external compile unit references AssertAlways(ref.cu == cu); // find type type = d2r_type_from_offset(type_table, ref.info_off); } else { Assert(!"unexpected attrib class"); } } return type; } internal Rng1U64List d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 image_base, DW_Tag tag) { // collect non-contiguous range Rng1U64List raw_ranges = dw_rnglist_from_tag_attrib_kind(arena, input, cu, tag, DW_AttribKind_Ranges); // exclude invalid ranges caused by linker optimizations Rng1U64List ranges = {0}; for (Rng1U64Node *n = raw_ranges.first, *next = 0; n != 0; n = next) { next = n->next; if (n->v.min < image_base || n->v.min > n->v.max) { continue; } rng1u64_list_push_node(&ranges, n); } // debase ranges for EachNode(r, Rng1U64Node, ranges.first) { r->v.min -= image_base; r->v.max -= image_base; } // collect contiguous range { DW_Attrib *lo_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_LowPc); DW_Attrib *hi_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_HighPc); if (lo_pc_attrib->attrib_kind != DW_AttribKind_Null && hi_pc_attrib->attrib_kind != DW_AttribKind_Null) { U64 lo_pc = dw_address_from_attrib(input, cu, lo_pc_attrib); U64 hi_pc = 0; DW_AttribClass hi_pc_class = dw_value_class_from_attrib(cu, hi_pc_attrib); if (hi_pc_class == DW_AttribClass_Address) { hi_pc = dw_address_from_attrib(input, cu, hi_pc_attrib); } else if (hi_pc_class == DW_AttribClass_Const) { hi_pc = dw_const_u64_from_attrib(input, cu, hi_pc_attrib); hi_pc += lo_pc; } else { AssertAlways(!"unexpected attribute encoding"); } if (lo_pc >= image_base && hi_pc >= image_base) { if (lo_pc < hi_pc) { rng1u64_list_push(arena, &ranges, rng_1u64(lo_pc - image_base, hi_pc - image_base)); } else { // TODO: error handling } } else { // invalid low and hi PC are likely are caused by an optimization pass during linking } } else if ((lo_pc_attrib->attrib_kind == DW_AttribKind_Null && hi_pc_attrib->attrib_kind != DW_AttribKind_Null) || (lo_pc_attrib->attrib_kind != DW_AttribKind_Null && hi_pc_attrib->attrib_kind == DW_AttribKind_Null)) { // TODO: error handling } } return ranges; } internal RDIM_Type ** d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_TagNode *cur_node, U64 *param_count_out) { Temp scratch = scratch_begin(&arena, 1); RDIM_TypeList list = {0}; B32 has_vargs = 0; for (DW_TagNode *i = cur_node->first_child; i != 0; i = i->sibling) { if (i->tag.kind == DW_TagKind_FormalParameter) { RDIM_TypeNode *n = push_array(scratch.arena, RDIM_TypeNode, 1); n->v = d2r_type_from_attrib(type_table, input, cu, i->tag, DW_AttribKind_Type); SLLQueuePush(list.first, list.last, n); ++list.count; } else if (i->tag.kind == DW_TagKind_UnspecifiedParameters) { has_vargs = 1; } } if (has_vargs) { RDIM_TypeNode *n = push_array(scratch.arena, RDIM_TypeNode, 1); n->v = type_table->builtin_types[RDI_TypeKind_Variadic]; SLLQueuePush(list.first, list.last, n); ++list.count; } // collect params *param_count_out = list.count; RDIM_Type **params = rdim_array_from_type_list(arena, list); scratch_end(scratch); return params; } //////////////////////////////// //~ RDIM Bytecode Helpers internal B32 rdim_is_eval_bytecode_static(RDIM_EvalBytecode bc) { B32 is_static = 1; RDI_EvalOp dynamic_ops[] = { RDI_EvalOp_MemRead, RDI_EvalOp_RegRead, RDI_EvalOp_RegReadDyn, RDI_EvalOp_CFA }; for EachNode(n, RDIM_EvalBytecodeOp, bc.first_op) { for EachIndex(i, ArrayCount(dynamic_ops)) { if (dynamic_ops[i] == n->op) { is_static = 0; goto exit; } } } exit:; return is_static; } internal U64 rdim_virt_off_from_eval_bytecode(RDIM_EvalBytecode bc, U64 image_base) { Temp scratch = scratch_begin(0,0); typedef union { U16 u16; U32 u32; U64 u64; S64 s64; F32 f32; F64 f64; } Value; U64 stack_cap = 128, stack_count = 0; Value *stack = push_array(scratch.arena, Value, stack_cap); for EachNode(opcode_n, RDIM_EvalBytecodeOp, bc.first_op) { // pop values from stack Value *svals = 0; { U32 pop_count = RDI_POPN_FROM_CTRLBITS(rdi_eval_op_ctrlbits_table[opcode_n->op]); if (pop_count > stack_count) { // TODO: report error Assert(!"malformed byte code"); break; } stack_count -= pop_count; svals = stack + stack_count; } Value imm = { .u64 = opcode_n->p }; Value nval = {0}; switch (opcode_n->op) { case RDI_EvalOp_Stop: { opcode_n = bc.last_op; } break; case RDI_EvalOp_Noop: {} break; case RDI_EvalOp_Cond: { NotImplemented; } break; case RDI_EvalOp_Skip: { NotImplemented; } break; case RDI_EvalOp_MemRead: { InvalidPath; } break; case RDI_EvalOp_RegRead: { NotImplemented; } break; case RDI_EvalOp_RegReadDyn: { NotImplemented; } break; case RDI_EvalOp_FrameOff: { NotImplemented; } break; case RDI_EvalOp_ModuleOff: { nval.u64 = image_base + imm.u64; } break; case RDI_EvalOp_TLSOff: { nval.u64 = image_base; } break; case RDI_EvalOp_ConstU8: case RDI_EvalOp_ConstU16: case RDI_EvalOp_ConstU32: case RDI_EvalOp_ConstU64: case RDI_EvalOp_ConstU128: { nval = imm; } break; case RDI_EvalOp_ConstString: { NotImplemented; } break; case RDI_EvalOp_Abs: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: case RDI_EvalTypeGroup_S: { nval.s64 = abs_s64(svals[0].s64); } break; case RDI_EvalTypeGroup_F32: { nval.f32 = abs_f32(svals[0].f32); } break; case RDI_EvalTypeGroup_F64: { nval.f64 = abs_f64(svals[0].f64); } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Neg: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: case RDI_EvalTypeGroup_S: { nval.u64 = ~svals[0].u64 + 1; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = -svals[0].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = -svals[0].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Add: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 + svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 + svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 + svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 + svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Sub: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 - svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[1].s64 - svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 - svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 - svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Mul: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 * svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 * svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 * svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 * svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Div: { B32 is_div_by_zero = 0; switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { is_div_by_zero = svals[1].u64 == 0; } break; case RDI_EvalTypeGroup_S: { is_div_by_zero = svals[1].s64 == 0; } break; case RDI_EvalTypeGroup_F32: { is_div_by_zero = svals[1].f32 == 0.0f; } break; case RDI_EvalTypeGroup_F64: { is_div_by_zero = svals[1].f64 == 0.0; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } // TODO: report error AssertAlways(!is_div_by_zero); switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 / svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 / svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 / svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 / svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Mod: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 % svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 % svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 MOD is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 MOD is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_LShift: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 << svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 << svals[1].u64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 LShift is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 LShift is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_RShift: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 >> svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[1].s64 >> svals[1].u64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 RShift is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 RShift is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_BitAnd: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 | svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].u64 | svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 bitwise AND is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 bitwise AND is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_BitXor: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 ^ svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].u64 ^ svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 XOR is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 XOR is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_BitNot: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = ~svals[0].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = ~svals[0].u64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 bitwise NOT is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 bitwise NOT is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_LogAnd: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 && svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].u64 && svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 AND is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 AND is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_LogOr: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 || svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].u64 || svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 OR is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 OR is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_LogNot: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = !svals[0].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = !svals[0].u64; } break; case RDI_EvalTypeGroup_F32: { AssertAlways(!"F32 NOT is not supported"); } break; // TODO: report error case RDI_EvalTypeGroup_F64: { AssertAlways(!"F64 NOT is not supported"); } break; // TODO: report error default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_EqEq: { nval.u64 = !!MemoryMatch(&svals[0], &svals[1], sizeof(*svals)); } break; case RDI_EvalOp_NtEq: { nval.u64 = !MemoryMatch(&svals[0], &svals[1], sizeof(*svals)); } break; case RDI_EvalOp_LsEq: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 <= svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 <= svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 <= svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 <= svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_GrEq: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 >= svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 >= svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 >= svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 >= svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Less: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 < svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 < svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 < svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 < svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Grtr: { switch (imm.u64) { case RDI_EvalTypeGroup_Other: {} break; case RDI_EvalTypeGroup_U: { nval.u64 = svals[0].u64 > svals[1].u64; } break; case RDI_EvalTypeGroup_S: { nval.s64 = svals[0].s64 > svals[1].s64; } break; case RDI_EvalTypeGroup_F32: { nval.f32 = svals[0].f32 > svals[1].f32; } break; case RDI_EvalTypeGroup_F64: { nval.f64 = svals[0].f64 > svals[1].f64; } break; default: { AssertAlways(!"unexpected eval type group"); } break; // report error } } break; case RDI_EvalOp_Trunc: { if (0 < imm.u64 && imm.u64 < 64) { U64 mask = max_U64 >> (64 - imm.u64); nval.u64 = svals[0].u64 & (max_U64 >> (64 - imm.u64)); } else if (imm.u64 > 64) { // TODO: report error AssertAlways(!"malformed bytecode"); } } break; case RDI_EvalOp_TruncSigned: { if (0 < imm.u64 && imm.u64 < 64) { U64 mask = max_U64 >> (64 - imm.u64); nval.u64 = svals[0].u64 & (max_U64 >> (64 - imm.u64)); U64 high = 0; if (svals[0].u64 & (1 << (imm.u64 - 1))) { high = ~mask; } nval.u64 = high | (svals[0].u64 & mask); } else if (imm.u64 > 64) { // TODO: report error AssertAlways(!"malformed bytecode"); } } break; case RDI_EvalOp_Convert: { U32 in = imm.u64 & 0xff; U32 out = (imm.u64 >> 8) & 0xff; if (in != out) { switch (in + out*RDI_EvalTypeGroup_COUNT) { case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT: { nval.u64 = (U64)svals[0].f32; } break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_U*RDI_EvalTypeGroup_COUNT: { nval.u64 = (U64)svals[0].f64; } break; case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT: { nval.s64 = (S64)svals[0].f32; } break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_S*RDI_EvalTypeGroup_COUNT: { nval.s64 = (S64)svals[0].f64; } break; case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].u64; } break; case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].s64; } break; case RDI_EvalTypeGroup_F64 + RDI_EvalTypeGroup_F32*RDI_EvalTypeGroup_COUNT: { nval.f32 = (F32)svals[0].f64; } break; case RDI_EvalTypeGroup_U + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].u64; } break; case RDI_EvalTypeGroup_S + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].s64; } break; case RDI_EvalTypeGroup_F32 + RDI_EvalTypeGroup_F64*RDI_EvalTypeGroup_COUNT: { nval.f64 = (F64)svals[0].f32; } break; default: { Assert(!"unexpected conversion case"); } break; // report error } } } break; case RDI_EvalOp_Pick: { if (stack_count > imm.u64) { nval = stack[stack_count - imm.u64 - 1]; } else { // TODO: report error AssertAlways(!"malformed bytecode"); } } break; case RDI_EvalOp_Pop: {} break; case RDI_EvalOp_Insert: { if (stack_count > imm.u64) { Value tval = stack[stack_count-1]; Value *dst = stack + stack_count - 1 - imm.u64; Value *shift = dst + 1; MemoryCopy(shift, dst, imm.u64 * sizeof(Value)); *dst = tval; } else { // TODO: report error AssertAlways(!"malformed bytecode"); } } break; case RDI_EvalOp_ValueRead: { U64 bytes_to_read = imm.u64; U64 offset = svals[0].u64; if (offset + bytes_to_read <= sizeof(Value)) { Value src_val = svals[1]; MemoryCopy(&nval, (U8 *)&src_val + offset, bytes_to_read); } } break; case RDI_EvalOp_ByteSwap: { switch (imm.u64) { case 0: {} break; case 1: {} break; case 2: { nval.u16 = bswap_u16(svals[0].u16); } break; case 4: { nval.u32 = bswap_u16(svals[0].u32); } break; case 8: { nval.u64 = bswap_u16(svals[0].u64); } break; default: { AssertAlways(!"malformed bytecode"); } break; // TODO: report error } } break; case RDI_EvalOp_Swap: { NotImplemented; } break; default: { Assert(!"unknown op type"); } break; } // push computed value to the stack { U64 push_count = RDI_PUSHN_FROM_CTRLBITS(rdi_eval_op_ctrlbits_table[opcode_n->op]); if (push_count == 1) { if (stack_count < stack_cap) { stack[stack_count] = nval; stack_count += 1; } else { AssertAlways(!"stack overflow"); // TODO: report error } } } } U64 result = 0; if (stack_count >= 1) { result = stack[0].u64 - image_base; } scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Bytecode Conversion Helpers internal D2R_ValueTypeNode * d2r_value_type_stack_push(Arena *arena, D2R_ValueTypeStack *stack, D2R_ValueType type) { D2R_ValueTypeNode *n; if (stack->free_list) { n = stack->free_list; SLLStackPop(stack->free_list); } else { n = push_array(arena, D2R_ValueTypeNode, 1); } n->type = type; SLLStackPush(stack->top, n); stack->count += 1; return n; } internal D2R_ValueType d2r_value_type_stack_pop(D2R_ValueTypeStack *stack) { D2R_ValueType result = D2R_ValueType_Generic; if (stack->top) { D2R_ValueTypeNode *n = stack->top; result = n->type; SLLStackPop(stack->top); SLLStackPush(stack->free_list, n); stack->count -= 1; } return result; } internal D2R_ValueType d2r_value_type_stack_peek(D2R_ValueTypeStack *stack) { return stack->top ? stack->top->type : D2R_ValueType_Generic; } internal D2R_ValueType d2r_unsigned_value_type_from_bit_size(U64 bit_size) { switch (bit_size) { case 8: return D2R_ValueType_U8; case 16: return D2R_ValueType_U16; case 32: return D2R_ValueType_U32; case 64: return D2R_ValueType_U64; case 128: return D2R_ValueType_U128; case 256: return D2R_ValueType_U256; case 512: return D2R_ValueType_U512; } AssertAlways(!"no suitable unsigned type was found for the specified size"); return D2R_ValueType_Generic; } internal D2R_ValueType d2r_signed_value_type_from_bit_size(U64 bit_size) { switch (bit_size) { case 8: return D2R_ValueType_S8; case 16: return D2R_ValueType_S16; case 32: return D2R_ValueType_S32; case 64: return D2R_ValueType_S64; case 128: return D2R_ValueType_S128; case 256: return D2R_ValueType_S256; case 512: return D2R_ValueType_S512; } AssertAlways(!"no suitable signed type was found for the specified size"); return D2R_ValueType_Generic; } internal D2R_ValueType d2r_float_type_from_bit_size(U64 bit_size) { switch (bit_size) { case 4: return D2R_ValueType_F32; case 8: return D2R_ValueType_F64; } AssertAlways(!"no suitable type was found for the specified size"); return D2R_ValueType_Generic; } internal RDI_EvalTypeGroup d2r_value_type_to_rdi(D2R_ValueType v) { RDI_EvalTypeGroup result = RDI_EvalTypeGroup_Other; switch(v) { case D2R_ValueType_Generic: {result = RDI_EvalTypeGroup_Other;}break; case D2R_ValueType_U8: case D2R_ValueType_U16: case D2R_ValueType_U32: case D2R_ValueType_U64: {result = RDI_EvalTypeGroup_U;}break; case D2R_ValueType_S8: case D2R_ValueType_S16: case D2R_ValueType_S32: case D2R_ValueType_S64: {result = RDI_EvalTypeGroup_S;}break; case D2R_ValueType_F32: {result = RDI_EvalTypeGroup_F32;}break; case D2R_ValueType_F64: {result = RDI_EvalTypeGroup_F64;}break; case D2R_ValueType_Address: {result = RDI_EvalTypeGroup_U;}break; default: case D2R_ValueType_ImplicitValue: {AssertAlways(!"unable to convert value type to RDI equivalent");}break; } return result; } internal U64 d2r_size_from_value_type(U64 addr_size, D2R_ValueType value_type) { switch (value_type) { case D2R_ValueType_Address: return addr_size; case D2R_ValueType_U8: return 1; case D2R_ValueType_U16: return 2; case D2R_ValueType_U32: return 4; case D2R_ValueType_U64: return 8; case D2R_ValueType_U128: return 16; case D2R_ValueType_U256: return 32; case D2R_ValueType_U512: return 64; case D2R_ValueType_S8: return 1; case D2R_ValueType_S16: return 2; case D2R_ValueType_S32: return 4; case D2R_ValueType_S64: return 8; case D2R_ValueType_S128: return 16; case D2R_ValueType_S256: return 32; case D2R_ValueType_S512: return 64; case D2R_ValueType_F32: return 4; case D2R_ValueType_F64: return 8; default: return 0; } } internal D2R_ValueType d2r_pick_common_value_type(D2R_ValueType lhs, D2R_ValueType rhs) { if (lhs == rhs) { return lhs; } // unsigned vs unsigned else if (D2R_ValueType_IsUnsigned(lhs) && D2R_ValueType_IsUnsigned(rhs)) { return Max(lhs, rhs); } // signed vs signed else if (D2R_ValueType_IsSigned(lhs) && D2R_ValueType_IsSigned(rhs)) { return Max(lhs, rhs); } // (unsigned vs signed) || (signed vs unsigned) else if ((D2R_ValueType_IsUnsigned(lhs) && D2R_ValueType_IsSigned(rhs)) || (D2R_ValueType_IsSigned(lhs) && D2R_ValueType_IsUnsigned(rhs))) { U64 lhs_size = d2r_size_from_value_type(0, lhs); U64 rhs_size = d2r_size_from_value_type(0, rhs); if (lhs_size < rhs_size) { return rhs; } else if (lhs > rhs_size) { return lhs; } else { return d2r_unsigned_value_type_from_bit_size(lhs_size * 8); } } // float vs int else if (D2R_ValueType_IsFloat(lhs) && D2R_ValueType_IsInt(rhs)) { return lhs; } // int vs float else if (D2R_ValueType_IsInt(lhs) && D2R_ValueType_IsFloat(rhs)) { return rhs; } // float vs float else if (D2R_ValueType_IsFloat(lhs) && D2R_ValueType_IsFloat(rhs)) { return Max(lhs, rhs); } // address vs int else if (lhs == D2R_ValueType_Address && D2R_ValueType_IsInt(rhs)) { return D2R_ValueType_Address; } // int vs address else if (D2R_ValueType_IsInt(lhs) && rhs == D2R_ValueType_Address) { return D2R_ValueType_Address; } // address vs float else if (lhs == D2R_ValueType_Address && D2R_ValueType_IsFloat(rhs)) { return D2R_ValueType_Generic; } // float vs address else if (D2R_ValueType_IsFloat(lhs) && rhs == D2R_ValueType_Address) { return D2R_ValueType_Generic; } // no conversion for implicit value else if (lhs == D2R_ValueType_ImplicitValue || rhs == D2R_ValueType_ImplicitValue) { return D2R_ValueType_Generic; } AssertAlways(!"undefined conversion case"); return D2R_ValueType_Generic; } internal D2R_ValueType d2r_apply_usual_arithmetic_conversions(Arena *arena, D2R_ValueType lhs, D2R_ValueType rhs, RDIM_EvalBytecode *bc) { D2R_ValueType common_type = d2r_pick_common_value_type(lhs, rhs); if (rhs != common_type) { rdim_bytecode_push_convert(arena, bc, d2r_value_type_to_rdi(rhs), d2r_value_type_to_rdi(common_type)); } if (lhs != common_type) { rdim_bytecode_push_op(arena, bc, RDI_EvalOp_Swap, 0); rdim_bytecode_push_convert(arena, bc, d2r_value_type_to_rdi(lhs), d2r_value_type_to_rdi(common_type)); } return common_type; } internal void d2r_push_arithmetic_op(Arena *arena, D2R_ValueTypeStack *stack, RDIM_EvalBytecode *bc, RDI_EvalOp op) { D2R_ValueType rhs = d2r_value_type_stack_pop(stack); D2R_ValueType lhs = d2r_value_type_stack_pop(stack); D2R_ValueType common_type = d2r_apply_usual_arithmetic_conversions(arena, lhs, rhs, bc); rdim_bytecode_push_op(arena, bc, op, d2r_value_type_to_rdi(common_type)); d2r_value_type_stack_push(0, stack, common_type); } internal void d2r_push_relational_op(Arena *arena, D2R_ValueTypeStack *stack, RDIM_EvalBytecode *bc, RDI_EvalOp op) { D2R_ValueType rhs = d2r_value_type_stack_pop(stack); D2R_ValueType lhs = d2r_value_type_stack_pop(stack); D2R_ValueType common_type; if (D2R_ValueType_IsInt(lhs) && rhs == D2R_ValueType_Address) { rdim_bytecode_push_op(arena, bc, RDI_EvalOp_Swap, 0); rdim_bytecode_push_convert(arena, bc, d2r_value_type_to_rdi(lhs), RDI_EvalTypeGroup_U); rdim_bytecode_push_op(arena, bc, RDI_EvalOp_Swap, 0); common_type = D2R_ValueType_Address; } else if (lhs == D2R_ValueType_Address && D2R_ValueType_IsInt(rhs)) { rdim_bytecode_push_convert(arena, bc, d2r_value_type_to_rdi(rhs), RDI_EvalTypeGroup_U); common_type = D2R_ValueType_Address; } else { common_type = d2r_apply_usual_arithmetic_conversions(arena, lhs, rhs, bc); } rdim_bytecode_push_op(arena, bc, RDI_EvalOp_EqEq, d2r_value_type_to_rdi(common_type)); d2r_value_type_stack_push(0, stack, D2R_ValueType_Bool); } internal RDIM_EvalBytecode d2r_bytecode_from_expression(Arena *arena, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, String8 raw_expr, DW_CompUnit *cu, D2R_ValueType *result_type_out) { Temp scratch = scratch_begin(&arena, 1); Temp arena_restore_point = temp_begin(arena); RDIM_EvalBytecode bc = {0}; DW_Expr expr = dw_expr_from_data(scratch.arena, cu->format, address_size, raw_expr); D2R_ValueTypeStack *stack = push_array(scratch.arena, D2R_ValueTypeStack, 1); RDIM_EvalBytecodeOp **converted_insts = push_array(scratch.arena, RDIM_EvalBytecodeOp *, expr.count); B32 is_ok = 1; U64 inst_idx = 0; for EachNode(inst, DW_ExprInst, expr.first) { RDIM_EvalBytecodeOp *last_op = bc.last_op; U64 pop_count = dw_pop_count_from_expr_op(inst->opcode); if (pop_count > stack->count) { // TODO: report error Assert(!"not enough values on the stack to evaluate instruction"); is_ok = 0; break; } switch (inst->opcode) { case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { U64 lit = inst->opcode - DW_ExprOp_Lit0; rdim_bytecode_push_uconst(arena, &bc, lit); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U8); } break; case DW_ExprOp_Const1U: { rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u8); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U8); } break; case DW_ExprOp_Const2U: { rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u16); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U16); } break; case DW_ExprOp_Const4U: { rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u32); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U32); } break; case DW_ExprOp_Const8U: { rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u32); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U64); } break; case DW_ExprOp_Const1S: { rdim_bytecode_push_sconst(arena, &bc, inst->operands[0].s8); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_S8); } break; case DW_ExprOp_Const2S: { rdim_bytecode_push_sconst(arena, &bc, inst->operands[0].s16); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_S16); } break; case DW_ExprOp_Const4S: { rdim_bytecode_push_sconst(arena, &bc, inst->operands[0].s32); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_S32); } break; case DW_ExprOp_Const8S: { rdim_bytecode_push_sconst(arena, &bc, inst->operands[0].s64); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_S64); } break; case DW_ExprOp_ConstU: { rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u64); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_U64); } break; case DW_ExprOp_ConstS: { rdim_bytecode_push_sconst(arena, &bc, inst->operands[0].s64); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_S64); } break; case DW_ExprOp_Addr: { if (inst->operands[0].u64 >= image_base) { U64 voff = inst->operands[0].u64 - image_base; rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } else { is_ok = 0; } } break; case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { U64 reg_code_dw = inst->opcode - DW_ExprOp_Reg0; U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); RDI_RegCode reg_code_rdi = d2r_rdi_reg_code_from_dw_reg(arch, reg_code_dw); U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); d2r_value_type_stack_push(scratch.arena, stack, d2r_unsigned_value_type_from_bit_size(reg_size)); } break; case DW_ExprOp_RegX: { U64 reg_size = dw_reg_size_from_code(arch, inst->operands[0].u64); U64 reg_pos = dw_reg_pos_from_code(arch, inst->operands[0].u64); RDI_RegCode reg_code_rdi = d2r_rdi_reg_code_from_dw_reg(arch, inst->operands[0].u64); U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); d2r_value_type_stack_push(scratch.arena, stack, d2r_unsigned_value_type_from_bit_size(reg_size)); } break; case DW_ExprOp_ImplicitValue: { if (inst->operands[0].block.size <= sizeof(U64)) { U64 implicit_value; MemoryCopyStr8(&implicit_value, inst->operands[0].block); rdim_bytecode_push_uconst(arena, &bc, implicit_value); d2r_value_type_stack_push(scratch.arena, stack, d2r_unsigned_value_type_from_bit_size(inst->operands[0].block.size * 8)); } else { // TODO: currenlty no way to encode string in RDIM_EvalBytecodeOp NotImplemented; } } break; case DW_ExprOp_Piece: { U64 partial_value_size32 = safe_cast_u32(inst->operands[0].u64); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValue, partial_value_size32); } break; case DW_ExprOp_BitPiece: { U32 piece_bit_size32 = safe_cast_u32(inst->operands[0].u64); U32 piece_bit_off32 = safe_cast_u32(inst->operands[1].u64); U64 partial_value = Compose64Bit(piece_bit_size32, piece_bit_off32); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValueBit, partial_value); } break; case DW_ExprOp_Pick: { U64 idx = 0; D2R_ValueTypeNode *n; for (n = stack->top; n != 0 || idx == inst->operands[0].u64; n = n->next, idx += 1) { } if (idx == inst->operands[0].u64) { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, inst->operands[0].u64); d2r_value_type_stack_push(scratch.arena, stack, n->type); } else { // TODO: report error AssertAlways(!"out of bounds pick"); } } break; case DW_ExprOp_Over: { if (stack->top && stack->top->next) { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 1); d2r_value_type_stack_push(scratch.arena, stack, stack->top->next->type); } else { // TODO: report error AssertAlways(!"out of bounds over"); } } break; case DW_ExprOp_PlusUConst: { D2R_ValueType lhs = d2r_value_type_stack_pop(stack); D2R_ValueType common_type = d2r_pick_common_value_type(lhs, D2R_ValueType_U64); rdim_bytecode_push_uconst(arena, &bc, inst->operands[0].u64); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, d2r_value_type_to_rdi(common_type)); d2r_value_type_stack_push(scratch.arena, stack, common_type); } break; case DW_ExprOp_Skip: { B32 skip_fwd = inst->operands[0].s16 >= 0; U16 delta = abs_s64(inst->operands[0].s16); U16 cursor = 0; U64 inst_count = 0; for (DW_ExprInst *i = skip_fwd ? inst : inst->prev; i != 0 && cursor < delta; i = skip_fwd ? inst->next : inst->prev) { cursor += inst->size; inst_count += 1; } // TODO: report error (skip does not land on first byte of an instruction) AssertAlways(cursor == delta); // TODO: report overflow AssertAlways(inst_count <= min_S16); AssertAlways(inst_idx <= max_U32); U64 imm = Compose64Bit(inst_idx, skip_fwd ? (S16)inst_count : -(S16)inst_count); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Skip, imm); } break; case DW_ExprOp_Bra: { NotImplemented; } break; case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { U64 reg_code_dw = inst->opcode - DW_ExprOp_BReg0; S64 reg_off = inst->operands[0].s64; RDI_RegCode reg_code_rdi = d2r_rdi_reg_code_from_dw_reg(arch, reg_code_dw); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, reg_code_rdi); if (reg_off > 0) { rdim_bytecode_push_sconst(arena, &bc, reg_off); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); } d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } break; case DW_ExprOp_BRegX: { U64 reg_code_dw = inst->operands[0].u64; S64 reg_off = inst->operands[1].s64; RDI_RegCode reg_code_rdi = d2r_rdi_reg_code_from_dw_reg(arch, reg_code_dw); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); if (reg_off > 0) { rdim_bytecode_push_sconst(arena, &bc, reg_off); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); } d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } break; case DW_ExprOp_FBReg: { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, inst->operands[0].s64); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } break; case DW_ExprOp_Deref: { D2R_ValueType address_type = d2r_value_type_stack_pop(stack); if (address_type != D2R_ValueType_Address && !D2R_ValueType_IsInt(address_type)) { // TODO: report error Assert(!"value must be of integral type"); break; } rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, address_size); d2r_value_type_stack_push(scratch.arena, stack, address_type); } break; case DW_ExprOp_DerefSize: { D2R_ValueType address_type = d2r_value_type_stack_pop(stack); if (!D2R_ValueType_IsInt(address_type) && address_type != D2R_ValueType_Address ) { // TODO: report error Assert(!"value must be of integral type"); break; } U8 deref_size_in_bytes = inst->operands[0].u64; if (0 < deref_size_in_bytes && deref_size_in_bytes <= address_size) { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, deref_size_in_bytes); } else { // TODO: error handling AssertAlways(!"ill formed expression"); } d2r_value_type_stack_push(scratch.arena, stack, address_type); } break; case DW_ExprOp_XDeref: { // TODO: error handling AssertAlways(!"multiple address spaces are not supported"); } break; // TODO: error handling case DW_ExprOp_XDerefSize: { AssertAlways(!"no suitable conversion"); } break; case DW_ExprOp_Call2: case DW_ExprOp_Call4: case DW_ExprOp_CallRef: { // TODO: error handling AssertAlways(!"calls are not supported"); } break; case DW_ExprOp_ImplicitPointer: case DW_ExprOp_GNU_ImplicitPointer: { // TODO: AssertAlways(!"sample"); } break; case DW_ExprOp_Convert: case DW_ExprOp_GNU_Convert: { D2R_ValueType out = D2R_ValueType_Generic; if (inst->operands[0].u64 == 0) { // // 2.5.1 // Instead of a base type, elements can have a generic type, // which is an integral type that has the size of an address // on the target machine and unspecified signedness. // out = D2R_ValueType_Generic; } else { // find ref tag DW_TagNode *tag_node = dw_tag_node_from_info_off(cu, inst->operands[0].u64); DW_Tag tag = tag_node->tag; if (tag.kind == DW_TagKind_BaseType) { // extract encoding attribute DW_ATE encoding = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Encoding); // DW_ATE -> RDI_EvalTypeGroup switch (encoding) { case DW_ATE_Null: { out = D2R_ValueType_Generic; } break; case DW_ATE_Address: { out = D2R_ValueType_Address; } break; case DW_ATE_Boolean: { out = D2R_ValueType_S8; } break; case DW_ATE_SignedChar: case DW_ATE_Signed: { U64 byte_size = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ByteSize); out = d2r_signed_value_type_from_bit_size(byte_size * 8); } break; case DW_ATE_UnsignedChar: case DW_ATE_Unsigned: { U64 byte_size = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ByteSize); out = d2r_unsigned_value_type_from_bit_size(byte_size * 8); } break; case DW_ATE_Float: { U64 byte_size = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ByteSize); out = d2r_float_type_from_bit_size(byte_size * 8); } break; default: InvalidPath; break; } } else { AssertAlways(!"unexpected tag"); // TODO: error handling } } D2R_ValueType in = d2r_value_type_stack_pop(stack); d2r_value_type_stack_push(scratch.arena, stack, out); rdim_bytecode_push_convert(arena, &bc, d2r_value_type_to_rdi(in), d2r_value_type_to_rdi(out)); } break; // TODO: case DW_ExprOp_GNU_ParameterRef: { AssertAlways(!"sample"); } break; // TODO: case DW_ExprOp_DerefType: case DW_ExprOp_GNU_DerefType: { AssertAlways(!"sample"); } break; // TODO: case DW_ExprOp_ConstType: case DW_ExprOp_GNU_ConstType: { AssertAlways(!"sample"); } break; // TODO: case DW_ExprOp_RegvalType: { AssertAlways(!"sample"); } break; case DW_ExprOp_EntryValue: case DW_ExprOp_GNU_EntryValue: { D2R_ValueType call_site_result_type = 0; RDIM_EvalBytecode call_site_bc = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, inst->operands[0].block, cu, &call_site_result_type); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_CallSiteValue, safe_cast_u32(call_site_bc.encoded_size)); rdim_bytecode_concat_in_place(&bc, &call_site_bc); d2r_value_type_stack_push(scratch.arena, stack, call_site_result_type); } break; case DW_ExprOp_Addrx: { U64 addr = dw_addr_from_list_unit(addr_lu, inst->operands[0].u64); if (addr != max_U64) { if (addr >= image_base) { U64 voff = addr - image_base; rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } else { // TODO: error handling AssertAlways(!"unable to relocate address"); } } else { // TODO: error handling AssertAlways(!"out of bounds index"); } } break; case DW_ExprOp_CallFrameCfa: { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, 0); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } break; case DW_ExprOp_FormTlsAddress: { // TODO: AssertAlways(!"RDI_EvalOp_TLSOff accepts immediate"); } break; case DW_ExprOp_PushObjectAddress: { AssertAlways(!"sample"); } break; case DW_ExprOp_Nop: {} break; case DW_ExprOp_Eq: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_EqEq); } break; case DW_ExprOp_Ge: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_GrEq); } break; case DW_ExprOp_Gt: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_Grtr); } break; case DW_ExprOp_Le: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_LsEq); } break; case DW_ExprOp_Lt: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_Less); } break; case DW_ExprOp_Ne: { d2r_push_relational_op(arena, stack, &bc, RDI_EvalOp_NtEq); } break; case DW_ExprOp_Div: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_Div); } break; case DW_ExprOp_Minus: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_Sub); } break; case DW_ExprOp_Mul: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_Mul); } break; case DW_ExprOp_Plus: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_Add); } break; case DW_ExprOp_Xor: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_BitXor); } break; case DW_ExprOp_And: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_BitAnd); } break; case DW_ExprOp_Or: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_BitOr); } break; case DW_ExprOp_Shl: { d2r_push_arithmetic_op(arena, stack, &bc, RDI_EvalOp_LShift); } break; case DW_ExprOp_Shr: { D2R_ValueType rhs = d2r_value_type_stack_pop(stack); D2R_ValueType lhs = d2r_value_type_stack_pop(stack); if (D2R_ValueType_IsInt(rhs) && D2R_ValueType_IsInt(lhs)) { D2R_ValueType common_type = d2r_pick_common_value_type(lhs, rhs); D2R_ValueType result_type = d2r_unsigned_value_type_from_bit_size(d2r_size_from_value_type((address_size), common_type) * 8); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, d2r_value_type_to_rdi(result_type)); d2r_value_type_stack_push(scratch.arena, stack, result_type); } else { // TODO: report error AssertAlways(!"operands must be of integral type"); } } break; case DW_ExprOp_Shra: { D2R_ValueType rhs = d2r_value_type_stack_pop(stack); D2R_ValueType lhs = d2r_value_type_stack_pop(stack); if (D2R_ValueType_IsInt(lhs) && D2R_ValueType_IsInt(rhs)) { D2R_ValueType common_type = d2r_pick_common_value_type(lhs, rhs); D2R_ValueType result_type = d2r_signed_value_type_from_bit_size(d2r_size_from_value_type((address_size), common_type) * 8); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, d2r_value_type_to_rdi(result_type)); d2r_value_type_stack_push(scratch.arena, stack, result_type); } else { // TODO: report error AssertAlways(!"operands must be of integral type"); } } break; case DW_ExprOp_Mod: { D2R_ValueType rhs = d2r_value_type_stack_pop(stack); D2R_ValueType lhs = d2r_value_type_stack_pop(stack); if (!D2R_ValueType_IsInt(rhs) || !D2R_ValueType_IsInt(lhs)) { // TODO: report error AssertAlways(!"operands must be of integral type"); is_ok = 0; break; } D2R_ValueType common_type = d2r_pick_common_value_type(lhs, rhs); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mod, d2r_value_type_to_rdi(common_type)); d2r_value_type_stack_push(scratch.arena, stack, common_type); } break; case DW_ExprOp_Abs: { if (!D2R_ValueType_IsInt(d2r_value_type_stack_peek(stack)) && !D2R_ValueType_IsFloat(d2r_value_type_stack_peek(stack))) { // TODO: report error AssertAlways(!"operand must be of integral type or float"); is_ok = 0; break; } rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Abs, d2r_value_type_to_rdi(d2r_value_type_stack_peek(stack))); } break; case DW_ExprOp_Neg: { if (!D2R_ValueType_IsInt(d2r_value_type_stack_peek(stack))) { // TODO: report error AssertAlways(!"operand must be of integral type"); is_ok = 0; break; } rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Neg, d2r_value_type_to_rdi(d2r_value_type_stack_peek(stack))); } break; case DW_ExprOp_Not: { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitNot, d2r_value_type_to_rdi(d2r_value_type_stack_peek(stack))); } break; case DW_ExprOp_Dup: { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 0); d2r_value_type_stack_push(scratch.arena, stack, d2r_value_type_stack_peek(stack)); } break; case DW_ExprOp_Rot: { AssertAlways(!"no suitable conversion"); } break; case DW_ExprOp_Swap: { AssertAlways(!"no suitable conversion"); } break; case DW_ExprOp_Drop: { AssertAlways(!"no suitable conversion"); } break; case DW_ExprOp_StackValue: { rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Stop, 0); if (stack->top->type == D2R_ValueType_Address) { stack->top->type = d2r_unsigned_value_type_from_bit_size(address_size * 8); } } break; case DW_ExprOp_GNU_PushTlsAddress: { D2R_ValueType lhs = d2r_value_type_stack_pop(stack); if (!D2R_ValueType_IsInt(lhs)) { // TODO: report error AssertAlways(!"lhs must be of integral type"); } rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_TLSOff, 0); rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, d2r_value_type_to_rdi(lhs)); d2r_value_type_stack_push(scratch.arena, stack, D2R_ValueType_Address); } break; default: InvalidPath; break; } if (!is_ok) { break; } // store converted instruction if (last_op != bc.last_op) { RDIM_EvalBytecodeOp *first_converted_op = last_op ? last_op->next : bc.first_op; converted_insts[inst_idx] = first_converted_op; } inst_idx += 1; } if (is_ok) { // fixup bytecode for EachNode(op, RDIM_EvalBytecodeOp, bc.first_op) { if (op->op == RDI_EvalOp_Skip) { // unpack skip info U32 inst_idx = Extract32(op->p, 0); S16 skip_count_signed = (S16)Extract32(op->p, 1); U16 skip_count = abs_s64(skip_count_signed); B32 skip_fwd = skip_count_signed > 0; // setup being/end links RDIM_EvalBytecodeOp *begin = 0, *end = 0; if (skip_fwd) { if (inst_idx + skip_count <= expr.count) { begin = converted_insts[inst_idx]; end = (inst_idx + skip_count) < expr.count ? converted_insts[inst_idx + skip_count] : 0; } else { // TODO: report error AssertAlways(!"out of bounds skip"); } } else { if (skip_count <= inst_idx) { begin = converted_insts[inst_idx - skip_count]; end = converted_insts[inst_idx]; } else { // TODO: report error AssertAlways(!"out of bounds skip"); } } // compute skip delta U64 skip_delta = 0; for (RDIM_EvalBytecodeOp *n = begin; n != end; n = n->next) { skip_delta += n->p_size; } // rewrite skip operand with byte delta AssertAlways(skip_delta <= max_S16); op->p = skip_fwd ? (S16)skip_delta : -(S16)skip_delta; } } if (result_type_out) { *result_type_out = d2r_value_type_stack_peek(stack); } } else { MemoryZeroStruct(&bc); temp_end(arena_restore_point); } scratch_end(scratch); return bc; } internal RDIM_Location * d2r_transpile_expression(Arena *arena, RDIM_LocationChunkList *locations, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, DW_CompUnit *cu, String8 expr) { RDIM_Location *loc = 0; if (expr.size) { D2R_ValueType result_type = 0; RDIM_EvalBytecode bytecode = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, expr, cu, &result_type); RDIM_LocationInfo *loc_info = push_array(arena, RDIM_LocationInfo, 1); loc_info->kind = result_type == D2R_ValueType_Address ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream; loc_info->bytecode = bytecode; loc = rdim_location_chunk_list_push_new(arena, locations, LOCATIONS_CAP, loc_info); } return loc; } internal RDIM_LocationCaseList d2r_locset_from_attrib(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind) { RDIM_LocationCaseList locset = {0}; // extract attrib from tag DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); DW_AttribClass attrib_class = dw_value_class_from_attrib(cu, attrib); if (attrib_class == DW_AttribClass_LocList || attrib_class == DW_AttribClass_LocListPtr) { Temp scratch = scratch_begin(&arena, 1); // extract location list from attrib DW_LocList loclist = dw_loclist_from_attrib(scratch.arena, input, cu, attrib); // convert location list to RDIM location set for EachNode(loc_n, DW_LocNode, loclist.first) { RDIM_Location *location = d2r_transpile_expression(arena, locations, input, image_base, cu->address_size, arch, cu->addr_lu, cu, loc_n->v.expr); RDIM_Rng1U64 voff_range = { .min = loc_n->v.range.min - image_base, .max = loc_n->v.range.max - image_base }; rdim_push_location_case(arena, scopes, &locset, location, voff_range); } scratch_end(scratch); } else if (attrib_class == DW_AttribClass_ExprLoc) { // extract expression from attrib String8 expr = dw_exprloc_from_attrib(input, cu, attrib); // convert expression and inherit life-time ranges from enclosed scope RDIM_Location *location = d2r_transpile_expression(arena, locations, input, image_base, cu->address_size, arch, cu->addr_lu, cu, expr); for EachNode(range_n, RDIM_Rng1U64Node, curr_scope->voff_ranges.first) { rdim_push_location_case(arena, scopes, &locset, location, range_n->v); } } else if (attrib_class != DW_AttribClass_Null) { AssertAlways(!"unexpected attrib class"); } return locset; } internal RDIM_LocationCaseList d2r_var_locset_from_tag(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag) { RDIM_LocationCaseList locset = {0}; B32 has_const_value = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ConstValue); B32 has_location = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Location); if (has_const_value && has_location) { // TODO: error handling AssertAlways(!"unexpected variable encoding"); } if (has_const_value) { // extract const value U64 const_value = dw_u64_from_attrib(input, cu, tag, DW_AttribKind_ConstValue); // make value byte code RDIM_EvalBytecode bc = {0}; rdim_bytecode_push_uconst(arena, &bc, const_value); // fill out location RDIM_LocationInfo *loc_info = push_array(arena, RDIM_LocationInfo, 1); loc_info->kind = RDI_LocationKind_ValBytecodeStream; loc_info->bytecode = bc; RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, locations, LOCATIONS_CAP, loc_info); // push location cases for EachNode(range_n, RDIM_Rng1U64Node, curr_scope->voff_ranges.first) { rdim_push_location_case(arena, scopes, &locset, loc, range_n->v); } } else if (has_location) { locset = d2r_locset_from_attrib(arena, scopes, curr_scope, locations, input, cu, image_base, arch, tag, DW_AttribKind_Location); } return locset; } //////////////////////////////// //~ rjf: Compilation Unit / Scope Conversion Helpers internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off) { RDIM_Rng1U64ChunkList voff_ranges = {0}; U64 voff_list_idx = u64_array_bsearch(map.info_off_arr, map.count, info_off); if (voff_list_idx < map.count) { voff_ranges = map.voff_range_arr[voff_list_idx]; } return voff_ranges; } internal RDIM_Scope * d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D2R_TagFrame *tag_stack, Rng1U64List ranges) { // fill out scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, scopes, scope_chunk_cap); // push ranges for EachNode(i, Rng1U64Node, ranges.first) { rdim_scope_push_voff_range(arena, scopes, scope, (RDIM_Rng1U64){.min = i->v.min, i->v.max}); } // associate scope with tag tag_stack->scope = scope; // update scope hierarchy DW_TagKind parent_tag_kind = tag_stack->next->node->tag.kind; if (parent_tag_kind == DW_TagKind_SubProgram || parent_tag_kind == DW_TagKind_InlinedSubroutine || parent_tag_kind == DW_TagKind_LexicalBlock) { RDIM_Scope *parent = tag_stack->next->scope; scope->parent_scope = parent; scope->symbol = parent->symbol; if (parent->last_child) { parent->last_child->next_sibling = scope; } SLLQueuePush_N(parent->first_child, parent->last_child, scope, next_sibling); } return scope; } //////////////////////////////// //~ Tag Iterator internal D2R_TagIter * d2r_tag_iter_init(Arena *arena, DW_TagNode *root) { D2R_TagIter *iter = push_array(arena, D2R_TagIter, 1); iter->free_list = 0; iter->stack = push_array(arena, D2R_TagFrame, 1); iter->stack->node = push_array(arena, DW_TagNode, 1); if(root != 0) { *iter->stack->node = *root; } iter->stack->node->sibling = 0; iter->visit_children = 1; iter->tag_node = root; iter->root = root; return iter; } internal void d2r_tag_iter_next(Arena *arena, D2R_TagIter *iter) { // descend to first child if (iter->visit_children) { if (iter->stack->node->first_child) { D2R_TagFrame *f = iter->free_list; if (f) { SLLStackPop(iter->free_list); MemoryZeroStruct(f); } else { f = push_array(arena, D2R_TagFrame, 1); } f->node = iter->stack->node->first_child; SLLStackPush(iter->stack, f); goto exit; } } while (iter->stack) { // go to sibling iter->stack->node = iter->stack->node->sibling; if (iter->stack->node) { break; } // no more siblings, go up D2R_TagFrame *f = iter->stack; SLLStackPop(iter->stack); SLLStackPush(iter->free_list, f); } exit:; // update iterator iter->visit_children = 1; iter->tag_node = iter->stack ? iter->stack->node : 0; // rjf: exit on root if(iter->tag_node == iter->root) { iter->tag_node = 0; } } internal void d2r_tag_iter_skip_children(D2R_TagIter *iter) { iter->visit_children = 0; } internal DW_TagNode * d2r_tag_iter_parent_tag_node(D2R_TagIter *iter) { return iter->stack->next->node; } internal DW_Tag d2r_tag_iter_parent_tag(D2R_TagIter *iter) { DW_TagNode *tag_node = d2r_tag_iter_parent_tag_node(iter); return tag_node->tag; } //////////////////////////////// //~ Type/UDT/Symbol Conversion internal void d2r_flag_converted_tag(DW_TagNode *tag_node) { tag_node->tag.v[0] = 1; } internal B8 d2r_is_tag_converted(DW_TagNode *tag_node) { return tag_node->tag.v[0]; } internal RDIM_Type * d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_Tag tag, DW_AttribKind kind) { RDIM_Type *type = type_table->builtin_types[RDI_TypeKind_Void]; // find attrib DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); // does tag have this attribute? if (attrib->attrib_kind == kind) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); if (value_class == DW_AttribClass_Reference) { // resolve reference DW_Reference ref = dw_ref_from_attrib(input, cu, attrib); // TODO: support for external compile unit references AssertAlways(ref.cu == cu); // find type type = d2r_type_from_offset(type_table, ref.info_off); // was type converted? if (type == 0) { // issue type conversion DW_TagNode *ref_node = dw_tag_node_from_info_off(cu, ref.info_off); d2r_convert_types(arena, type_table, input, cu, cu_lang, arch_addr_size, ref_node); // if we do not have a converted type at this point then debug info is malformed type = d2r_type_from_offset(type_table, ref.info_off); if(type == 0) { type = type_table->builtin_types[RDI_TypeKind_NULL]; } } } else { Assert(!"unexpected attrib class"); } } return type; } internal void d2r_convert_types(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); for(D2R_TagIter *it = d2r_tag_iter_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iter_next(scratch.arena, it)) { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; // skip converted tags if(d2r_is_tag_converted(tag_node)) { d2r_tag_iter_skip_children(it); continue; } // mark the tag as converted here, because during conversion we may recurse on the same tag d2r_flag_converted_tag(tag_node); switch(tag.kind) { case DW_TagKind_ClassType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if(is_decl) { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_IncompleteClass; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); d2r_tag_iter_skip_children(it); } else { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Class; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); type->direct_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); } }break; case DW_TagKind_StructureType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if(is_decl) { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteStruct; d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Struct; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); } }break; case DW_TagKind_UnionType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if(is_decl) { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteUnion; d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Union; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); } }break; case DW_TagKind_EnumerationType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if(is_decl) { RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_IncompleteEnum; d2r_tag_iter_skip_children(it); } else { RDIM_Type *enum_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->kind = RDI_TypeKind_Enum; type->byte_size = dw_byte_size_32_from_tag(input, cu, tag); type->direct_type = enum_base_type; } }break; case DW_TagKind_SubroutineType: { RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); // collect parameters RDIM_TypeList param_list = {0}; for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { if (n->tag.kind == DW_TagKind_FormalParameter) { RDIM_Type *param_type = d2r_type_from_attrib(type_table, input, cu, n->tag, DW_AttribKind_Type); rdim_type_list_push(scratch.arena, ¶m_list, param_type); } else if (n->tag.kind == DW_TagKind_UnspecifiedParameters) { rdim_type_list_push(scratch.arena, ¶m_list, type_table->builtin_types[RDI_TypeKind_Variadic]); } else { // TODO: error handling AssertAlways(!"unexpected tag"); } } // init proceudre type RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Function; type->byte_size = arch_addr_size; type->direct_type = ret_type; type->count = param_list.count; type->param_types = rdim_array_from_type_list(arena, param_list); d2r_tag_iter_skip_children(it); }break; case DW_TagKind_Typedef: { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Alias; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->direct_type = direct_type; for (RDIM_Type *n = direct_type; n != 0; n = n->direct_type) { if (n->byte_size) { type->byte_size = n->byte_size; break; } } }break; case DW_TagKind_BaseType: { DW_ATE encoding = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Encoding); U64 byte_size = dw_byte_size_from_tag(input, cu, tag); // rjf: attribute type encoding -> RDI type kind RDI_TypeKind kind = RDI_TypeKind_NULL; switch(encoding) { default:{}break; case DW_ATE_Null: {kind = RDI_TypeKind_NULL;}break; case DW_ATE_Boolean: {kind = RDI_TypeKind_Bool;}break; case DW_ATE_ComplexFloat: switch(byte_size) { case 4: {kind = RDI_TypeKind_ComplexF32;}break; case 8: {kind = RDI_TypeKind_ComplexF64;}break; case 10: {kind = RDI_TypeKind_ComplexF80;}break; case 16: {kind = RDI_TypeKind_ComplexF128;}break; default: {log_infof("Unsupported complex float size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_Float: switch(byte_size) { case 2: {kind = RDI_TypeKind_F16; }break; case 4: {kind = RDI_TypeKind_F32; }break; case 6: {kind = RDI_TypeKind_F48; }break; case 8: {kind = RDI_TypeKind_F64; }break; case 16: {kind = RDI_TypeKind_F128;}break; default: {log_infof("Unsupported float size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_Signed: switch(byte_size) { case 1: {kind = RDI_TypeKind_S8; }break; case 2: {kind = RDI_TypeKind_S16; }break; case 4: {kind = RDI_TypeKind_S32; }break; case 8: {kind = RDI_TypeKind_S64; }break; case 16: {kind = RDI_TypeKind_S128;}break; case 32: {kind = RDI_TypeKind_S256;}break; case 64: {kind = RDI_TypeKind_S512;}break; default: {log_infof("Unsupported signed integer size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_SignedChar: switch(byte_size) { case 1: {kind = RDI_TypeKind_Char8; }break; case 2: {kind = RDI_TypeKind_Char16;}break; case 4: {kind = RDI_TypeKind_Char32;}break; default:{log_infof("Unsupported signed character size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_Address: case DW_ATE_Unsigned: switch(byte_size) { case 1: {kind = RDI_TypeKind_U8; }break; case 2: {kind = RDI_TypeKind_U16; }break; case 4: {kind = RDI_TypeKind_U32; }break; case 8: {kind = RDI_TypeKind_U64; }break; case 16: {kind = RDI_TypeKind_U128;}break; case 32: {kind = RDI_TypeKind_U256;}break; case 64: {kind = RDI_TypeKind_U512;}break; default:{log_infof("Unsupported unsigned integer size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_UnsignedChar: switch(byte_size) { case 1: {kind = RDI_TypeKind_UChar8; }break; case 2: {kind = RDI_TypeKind_UChar16;}break; case 4: {kind = RDI_TypeKind_UChar32;}break; default:{log_infof("Unsupported unsigned character size (%I64u) at 0x%I64x.\n", byte_size, tag.info_off);}break; }break; case DW_ATE_ImaginaryFloat: case DW_ATE_PackedDecimal: case DW_ATE_NumericString: case DW_ATE_Edited: case DW_ATE_SignedFixed: case DW_ATE_UnsignedFixed: case DW_ATE_DecimalFloat: case DW_ATE_Utf: case DW_ATE_Ucs: case DW_ATE_Ascii: { // TODO(rjf): not implemented }break; } // rjf: build RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Alias; type->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); type->direct_type = type_table->builtin_types[kind]; type->byte_size = byte_size; }break; case DW_TagKind_PointerType: { RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Allocated)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Associated)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); // TODO(rjf): this is not an invalid case; it shows up in `mule_main` pointer types // Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_AddressClass)); U64 byte_size = arch_addr_size; dw_try_byte_size_from_tag(input, cu, tag, &byte_size); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Ptr; type->byte_size = byte_size; type->direct_type = direct_type; }break; case DW_TagKind_RestrictType: { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Restrict; type->direct_type = direct_type; }break; case DW_TagKind_VolatileType: { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Volatile; type->direct_type = direct_type; }break; case DW_TagKind_ConstType: { // TODO: Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Name)); Assert(!dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Alignment)); RDIM_Type *direct_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); type->kind = RDI_TypeKind_Modifier; type->byte_size = arch_addr_size; type->flags = RDI_TypeModifierFlag_Const; type->direct_type = direct_type; }break; case DW_TagKind_ArrayType: { // * DWARF vs RDI Array Type Graph * // // For example lets take following decl: // // int (*foo[2])[3]; // // This compiles to in DWARF: // // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] // \ // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] // \ // -> (B1) DW_TAG_BaseType (int) // // RDI expects: // // foo -> Array[2] -> Pointer -> Array[3] -> int // // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from // B to A. struct SubrangeNode { struct SubrangeNode *next; U64 count; }; struct SubrangeNode *subrange_stack = 0; for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) { if (n->tag.kind != DW_TagKind_SubrangeType) { // TODO: error handling AssertAlways(!"unexpected tag"); continue; } // resolve lower bound U64 lower_bound = 0; if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_LowerBound)) { lower_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_LowerBound); } else { lower_bound = dw_pick_default_lower_bound(cu_lang); } // resolve upper bound U64 upper_bound = 0; if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_Count)) { U64 count = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_Count); upper_bound = lower_bound + count; } else if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_UpperBound)) { upper_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_UpperBound); // turn upper bound into exclusive range upper_bound += 1; } else { // zero sized array } struct SubrangeNode *s = push_array(scratch.arena, struct SubrangeNode, 1); s->count = upper_bound - lower_bound; SLLStackPush(subrange_stack, s); } RDIM_Type *array_base_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_Type *direct_type = array_base_type; U64 size_cursor = array_base_type->byte_size; for EachNode(s, struct SubrangeNode, subrange_stack) { size_cursor *= s->count; RDIM_Type *t; if (s->next) { t = d2r_create_type(arena, type_table); } else { t = d2r_create_type_from_offset(arena, type_table, tag.info_off); } t->kind = RDI_TypeKind_Array; t->direct_type = direct_type; t->byte_size = size_cursor; t->count = s->count; direct_type = t; } d2r_tag_iter_skip_children(it); }break; case DW_TagKind_SubrangeType: { // TODO: error handling AssertAlways(!"unexpected tag"); }break; case DW_TagKind_Inheritance: { DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if (parent_tag.kind != DW_TagKind_StructureType && parent_tag.kind != DW_TagKind_ClassType) { // TODO: error handling AssertAlways(!"unexpected parent tag"); } RDIM_Type *parent = d2r_type_from_offset(type_table, parent_tag.info_off); if(parent->udt != 0) { RDIM_Type *type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch_addr_size, tag, DW_AttribKind_Type); RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); member->kind = RDI_MemberKind_Base; member->type = type; member->off = safe_cast_u32(dw_const_u32_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation)); } }break; } } scratch_end(scratch); } internal void d2r_convert_udts(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); for(D2R_TagIter *it = d2r_tag_iter_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iter_next(scratch.arena, it)) { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; switch (tag.kind) { case DW_TagKind_ClassType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if (is_decl) { d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); udt->self_type = type; type->udt = udt; } } break; case DW_TagKind_StructureType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if (is_decl) { d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); udt->self_type = type; type->udt = udt; } } break; case DW_TagKind_UnionType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if (is_decl) { d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); udt->self_type = type; type->udt = udt; } } break; case DW_TagKind_EnumerationType: { B32 is_decl = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Declaration); if (is_decl) { d2r_tag_iter_skip_children(it); } else { RDIM_Type *type = d2r_type_from_offset(type_table, tag.info_off); RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); udt->self_type = type; type->udt = udt; } } break; case DW_TagKind_Member: { DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); B32 is_parent_udt = parent_tag.kind == DW_TagKind_StructureType || parent_tag.kind == DW_TagKind_ClassType || parent_tag.kind == DW_TagKind_UnionType; if (is_parent_udt) { DW_Attrib *data_member_location = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_DataMemberLocation); DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); if (data_member_location_class == DW_AttribClass_LocList) { AssertAlways(!"UDT member with multiple locations are not supported"); } RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); RDIM_UDTMember *udt_member = rdim_udt_push_member(arena, &udts, parent_type->udt); udt_member->kind = RDI_MemberKind_DataField; udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); udt_member->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); udt_member->off = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_DataMemberLocation); } else { // TODO: error handling AssertAlways(!"unexpected parent tag"); } } break; case DW_TagKind_Enumerator: { DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if (parent_tag.kind == DW_TagKind_EnumerationType) { RDIM_Type *parent_type = d2r_type_from_offset(type_table, parent_tag.info_off); RDIM_UDTEnumVal *udt_member = rdim_udt_push_enum_val(arena, &udts, parent_type->udt); udt_member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); udt_member->val = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ConstValue); } else { // TODO: error handling AssertAlways(!"unexpected parent tag"); } } break; } } scratch_end(scratch); } internal void d2r_convert_symbols(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, U64 image_base, Arch arch, DW_TagNode *root) { Temp scratch = scratch_begin(&arena, 1); for(D2R_TagIter *it = d2r_tag_iter_init(scratch.arena, root); it->tag_node != 0; d2r_tag_iter_next(scratch.arena, it)) { DW_TagNode *tag_node = it->tag_node; DW_Tag tag = tag_node->tag; switch(tag.kind) { case DW_TagKind_Null:{}break; case DW_TagKind_ClassType: case DW_TagKind_StructureType: case DW_TagKind_UnionType: { // TODO(rjf): visit children to collect methods and variables }break; case DW_TagKind_EnumerationType: case DW_TagKind_SubroutineType: case DW_TagKind_Typedef: case DW_TagKind_BaseType: case DW_TagKind_PointerType: case DW_TagKind_RestrictType: case DW_TagKind_VolatileType: case DW_TagKind_ConstType: case DW_TagKind_ArrayType: case DW_TagKind_SubrangeType: case DW_TagKind_Inheritance: case DW_TagKind_Enumerator: case DW_TagKind_Member: { d2r_tag_iter_skip_children(it); }break; case DW_TagKind_SubProgram: { DW_InlKind inl = DW_Inl_NotInlined; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Inline)) { inl = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Inline); } switch(inl) { case DW_Inl_NotInlined: { U64 param_count = 0; RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); // get return type RDIM_Type *ret_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); // fill out proc type RDIM_Type *proc_type = d2r_create_type(arena, type_table); proc_type->kind = RDI_TypeKind_Function; proc_type->byte_size = arch_addr_size; proc_type->direct_type = ret_type; proc_type->count = param_count; proc_type->param_types = params; // get container type RDIM_Type *container_type = 0; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { container_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); } // get frame base expression String8 frame_base_expr = dw_exprloc_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_FrameBase); // get proc container symbol RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP); // make scope Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); root_scope->symbol = proc; // fill out proc proc->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); proc->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); proc->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); proc->type = proc_type; proc->container_symbol = 0; proc->container_type = container_type; proc->root_scope = root_scope; proc->location_cases = d2r_locset_from_attrib(arena, &scopes, root_scope, &locations, input, cu, image_base, arch, tag, DW_AttribKind_FrameBase); // sub program with user-defined parent tag is a method DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if (parent_tag.kind == DW_TagKind_ClassType || parent_tag.kind == DW_TagKind_StructureType) { RDI_MemberKind member_kind = RDI_MemberKind_NULL; DW_VirtualityKind virtuality = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Virtuality); switch (virtuality) { case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal //default: InvalidPath; break; } RDIM_Type *type = d2r_type_from_offset(type_table, parent_tag.info_off); RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); member->kind = member_kind; member->type = type; member->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); } else if (parent_tag.kind != DW_TagKind_CompileUnit) { //AssertAlways(!"unexpected tag"); } it->stack->scope = root_scope; }break; case DW_Inl_DeclaredNotInlined: case DW_Inl_DeclaredInlined: case DW_Inl_Inlined: { d2r_tag_iter_skip_children(it); }break; default:{}break; } }break; case DW_TagKind_InlinedSubroutine: { U64 param_count = 0; RDIM_Type **params = d2r_collect_proc_params(arena, type_table, input, cu, tag_node, ¶m_count); // get return type RDIM_Type *ret_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); // fill out proc type RDIM_Type *proc_type = d2r_create_type(arena, type_table); proc_type->kind = RDI_TypeKind_Function; proc_type->byte_size = arch_addr_size; proc_type->direct_type = ret_type; proc_type->count = param_count; proc_type->param_types = params; // get container type RDIM_Type *owner = 0; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { owner = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); } // fill out inline site RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); inline_site->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); inline_site->type = proc_type; inline_site->owner = owner; inline_site->line_table = 0; // make scope Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); root_scope->inline_site = inline_site; }break; case DW_TagKind_Variable: { String8 name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); RDIM_Type *type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if (parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine || parent_tag.kind == DW_TagKind_LexicalBlock) { RDIM_Scope *scope = it->stack->next->scope; RDIM_Local *local = rdim_scope_push_local(arena, &scopes, scope); local->kind = RDI_LocalKind_Variable; local->name = name; local->type = type; local->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); } else { // NOTE: due to a bug in clang in stb_sprint.h local variables // are declared in global scope without a name if (name.size == 0) { break; } U64 voff = max_U64; B32 is_thread_var = 0; { DW_Attrib *loc_attrib = dw_attrib_from_tag(input, cu, tag, DW_AttribKind_Location); DW_AttribClass loc_class = dw_value_class_from_attrib(cu, loc_attrib); if (loc_class == DW_AttribClass_ExprLoc) { Temp temp = temp_begin(scratch.arena); String8 expr = dw_exprloc_from_attrib(input, cu, loc_attrib); D2R_ValueType expr_type = 0; RDIM_EvalBytecode bc = d2r_bytecode_from_expression(temp.arena, input, image_base, arch_addr_size, arch, cu->addr_lu, expr, cu, &expr_type); // evaluate bytecode to virutal offset if possible if (expr_type == D2R_ValueType_Address) { B32 is_static = rdim_is_eval_bytecode_static(bc); if (is_static) { voff = rdim_virt_off_from_eval_bytecode(bc, image_base); } } // is this a thread variable? is_thread_var = rdim_is_bytecode_tls_dependent(bc); temp_end(temp); } } RDIM_SymbolChunkList *var_chunks; U64 var_chunks_cap; if (is_thread_var) { var_chunks = &tvars; var_chunks_cap = TVAR_CHUNK_CAP; } else { var_chunks = &gvars; var_chunks_cap = GVAR_CHUNK_CAP; } RDIM_Symbol *var = rdim_symbol_chunk_list_push(arena, var_chunks, var_chunks_cap); var->is_extern = dw_flag_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_External); var->name = name; var->link_name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_LinkageName); var->type = type; var->offset = voff; var->container_symbol = 0; var->container_type = 0; // TODO: NotImplemented; } }break; case DW_TagKind_FormalParameter: { DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if (parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine) { RDIM_Scope *scope = it->stack->next->scope; RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); param->kind = RDI_LocalKind_Parameter; param->name = dw_string_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Name); param->type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_Type); param->location_cases = d2r_var_locset_from_tag(arena, &scopes, scope, &locations, input, cu, image_base, arch, tag); } else { // TODO: error handling; this is a local variable } }break; case DW_TagKind_LexicalBlock: { DW_Tag parent_tag = d2r_tag_iter_parent_tag(it); if(parent_tag.kind == DW_TagKind_SubProgram || parent_tag.kind == DW_TagKind_InlinedSubroutine || parent_tag.kind == DW_TagKind_LexicalBlock) { Rng1U64List ranges = d2r_range_list_from_tag(scratch.arena, input, cu, image_base, tag); d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, it->stack, ranges); } }break; case DW_TagKind_CallSite: { // TODO }break; case DW_TagKind_CallSiteParameter: { // TODO }break; case DW_TagKind_Label: case DW_TagKind_CompileUnit: case DW_TagKind_UnspecifiedParameters: case DW_TagKind_Namespace: case DW_TagKind_ImportedDeclaration: case DW_TagKind_PtrToMemberType: case DW_TagKind_TemplateTypeParameter: case DW_TagKind_ReferenceType: { // TODO }break; default: { // NotImplemented; }break; } } scratch_end(scratch); } //////////////////////////////// //~ rjf: Main Conversion Entry Point internal RDIM_BakeParams d2r_convert(Arena *arena, D2R_ConvertParams *params) { Temp scratch = scratch_begin(&arena, 1); if(lane_idx() == 0) { //////////////////////////// //- rjf: compute exe hash // ProfBegin("compute exe hash"); U64 exe_hash = rdi_hash(params->exe_data.str, params->exe_data.size); ProfEnd(); //////////////////////////// //- rjf: unpack input image info // Arch arch = Arch_Null; U64 image_base = 0; DW_Input input = {0}; PathStyle path_style = PathStyle_Null; switch(params->exe_kind) { default:{}break; case ExecutableImageKind_CoffPe: { PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(raw_sections, 0, sizeof(COFF_SectionHeader) * pe.section_count); String8 string_table = str8_substr(params->exe_data, pe.string_table_range); arch = pe.arch; image_base = pe.image_base; binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, pe.section_count, section_table); input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, pe.section_count, section_table); path_style = PathStyle_WindowsAbsolute; }break; case ExecutableImageKind_Elf32: case ExecutableImageKind_Elf64: { ELF_Bin bin = elf_bin_from_data(scratch.arena, params->dbg_data); arch = arch_from_elf_machine(bin.hdr.e_machine); image_base = (bin.hdr.e_type == ELF_Type_Dyn ? 0 : elf_base_addr_from_bin(&bin)); binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, params->dbg_data, &bin, bin.shdrs); input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); path_style = PathStyle_UnixAbsolute; }break; } U64 arch_addr_size = rdi_addr_size_from_arch(arch); //////////////////////////// //- rjf: determine acceptable address range // // in many cases, linkers seem to trample over addresses in various DWARF sections, // potentially due to optimizations. we'd like to filter out those busted addresses // from our final debug info - a good enough heuristic is to disqualify them by // whether or not they actually fall into the ranges covered by the binary sections. // Rng1U64 acceptable_vaddr_range = {0}; { acceptable_vaddr_range.min = max_U64; acceptable_vaddr_range.max = 0; for EachNode(n, RDIM_BinarySectionNode, binary_sections.first) { acceptable_vaddr_range.min = Min(n->v.voff_first, acceptable_vaddr_range.min); acceptable_vaddr_range.max = Max(n->v.voff_opl, acceptable_vaddr_range.max); } } //////////////////////////// //- rjf: unpack input image info // { // rjf: base arch -> rdi RDI_Arch arch_rdi = RDI_Arch_NULL; switch(arch) { case Arch_Null: case Arch_arm64: case Arch_arm32: case Arch_COUNT: {}break; case Arch_x64:{arch_rdi = RDI_Arch_X64;}break; case Arch_x86:{arch_rdi = RDI_Arch_X86;}break; } // rjf: binary sections -> voff max U64 exe_voff_max = 0; for EachNode(sect_n, RDIM_BinarySectionNode, binary_sections.first) { exe_voff_max = Max(exe_voff_max, sect_n->v.voff_opl); } // rjf: fill top_level_info.arch = arch_rdi; top_level_info.exe_name = params->exe_name; top_level_info.exe_hash = exe_hash; top_level_info.voff_max = exe_voff_max; if(!params->deterministic) { // TODO(rjf): top_level_info.guid = ...; top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); } } //////////////////////////// //- rjf: parse unit contribution map // D2R_CompUnitContribMap cu_contrib_map = {0}; ProfScope("parse unit contribution map") { String8 aranges_data = input.sec[DW_Section_ARanges].data; if(aranges_data.size != 0) { Temp scratch = scratch_begin(&arena, 1); //- rjf: unpack input Rng1U64List unit_range_list = dw_unit_ranges_from_data(scratch.arena, aranges_data); //- rjf: set up map cu_contrib_map.info_off_arr = push_array(arena, U64, unit_range_list.count); cu_contrib_map.voff_range_arr = push_array(arena, RDIM_Rng1U64ChunkList, unit_range_list.count); //- rjf: convert all units for EachNode(range_n, Rng1U64Node, unit_range_list.first) { //- rjf: unpack unit String8 unit_data = str8_substr(aranges_data, range_n->v); U64 unit_cursor = 0; //- rjf: read unit data length U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, unit_cursor, &unit_length); B32 unit_length_good = (unit_length_size != 0); unit_cursor += unit_length_size; DW_Format unit_format = DW_FormatFromSize(unit_length); //- rjf: read unit version DW_Version version = 0; U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); B32 version_good = (version_size != 0); unit_cursor += version_size; //- rjf: parse section by version switch(version) { //- rjf: unsupported versions default: { log_infof("Unknown .debug_aranges version (%i).\n", version); }break; //- rjf: version 2 case DW_Version_2: { // rjf: unpack & read unit header info U64 unit_info_off = 0; U8 unit_address_size = 0; U8 unit_segment_selector_size = 0; B32 unit_good = 0; { U64 unit_info_off_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, unit_format, &unit_info_off); unit_cursor += unit_info_off_size; U64 unit_address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &unit_address_size); unit_cursor += unit_address_size_size; U64 unit_segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &unit_segment_selector_size); unit_cursor += unit_segment_selector_size_size; unit_good = (unit_info_off_size != 0 && unit_address_size_size != 0 && unit_segment_selector_size_size != 0); } U64 tuple_size = unit_address_size * 2 + unit_segment_selector_size; // rjf: align cursor to be divisible by the tuple size (see the February 13, 2017 spec) { U64 bytes_too_far_past_boundary = unit_cursor % tuple_size; if(bytes_too_far_past_boundary > 0) { unit_cursor += tuple_size - bytes_too_far_past_boundary; } } // rjf: read all ranges RDIM_Rng1U64ChunkList voff_ranges = {0}; if(unit_segment_selector_size == 0) { for(;unit_cursor + unit_address_size*2 <= unit_data.size;) { U64 segment = 0; U64 address = 0; U64 length = 0; unit_cursor += str8_deserial_read(unit_data, unit_cursor, &segment, unit_segment_selector_size, Max(unit_segment_selector_size, 1)); unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, unit_address_size, unit_address_size); unit_cursor += str8_deserial_read(unit_data, unit_cursor, &length, unit_address_size, unit_address_size); if((segment != 0 || address != 0 || length != 0) && (contains_1u64(acceptable_vaddr_range, address) || contains_1u64(acceptable_vaddr_range, address + length))) { RDIM_Rng1U64 range = { address - image_base, address - image_base + length, }; rdim_rng1u64_chunk_list_push(arena, &voff_ranges, 256, range); } else { break; } } } else { log_infof("Segment-relative addressing detected in .debug_aranges; this is not currently supported.\n"); } // rjf: store record U64 map_idx = cu_contrib_map.count; cu_contrib_map.info_off_arr[map_idx] = unit_info_off; cu_contrib_map.voff_range_arr[map_idx] = voff_ranges; cu_contrib_map.count += 1; }break; } } scratch_end(scratch); } } //////////////////////////// //- rjf: parse list of comp units // DW_ListUnitInput lu_input = {0}; ProfScope("parse list of comp units") { lu_input = dw_list_unit_input_from_input(scratch.arena, &input); } //////////////////////////// //- rjf: parse comp unit ranges // Rng1U64Array cu_ranges = {0}; ProfScope("parse comp unit ranges") { Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input.sec[DW_Section_Info].data); cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); } //////////////////////////// //- rjf: parse comp unit headers // DW_CompUnit *cu_arr = 0; ProfScope("parse comp unit headers") { // TODO(rjf): parse should always be relaxed. any verification checks we do // should just be logged via log_info(...), and then the caller of this // converter can collect those & display as necessary. B32 is_parse_relaxed = 1; cu_arr = push_array(scratch.arena, DW_CompUnit, cu_ranges.count); for EachIndex(cu_idx, cu_ranges.count) { cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, &input, lu_input, cu_ranges.v[cu_idx].min, is_parse_relaxed); } } //////////////////////////// //- rjf: parse line tables // DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); ProfScope("parse line tables") { for EachIndex(cu_idx, cu_ranges.count) { DW_CompUnit *cu = &cu_arr[cu_idx]; String8 cu_stmt_list = dw_line_ptr_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_StmtList); String8 cu_dir = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_CompDir); String8 cu_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Name); cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); } } //////////////////////////// //- rjf: convert line tables // RDIM_LineTable **cu_line_tables_rdi = 0; ProfScope("convert line tables") { HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); for EachIndex(cu_idx, cu_ranges.count) { cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; RDIM_SrcFile **src_file_map = push_array(scratch.arena, RDIM_SrcFile *, file_table->count); for EachIndex(file_idx, file_table->count) { DW_LineFile *file = &file_table->v[file_idx]; String8 file_path = dw_path_from_file_idx(scratch.arena, &line_table->vm_header, file_idx); String8List file_path_split = str8_split_path(scratch.arena, file_path); str8_path_list_resolve_dots_in_place(&file_path_split, path_style); String8 file_path_resolved = str8_path_list_join_by_style(scratch.arena, &file_path_split, path_style); RDIM_SrcFile *src_file = hash_table_search_path_raw(source_file_ht, file_path_resolved); if(src_file == 0) { src_file = rdim_src_file_chunk_list_push(arena, &src_files, SRC_FILE_CAP); src_file->path = push_str8_copy(arena, file_path_resolved); hash_table_push_path_raw(scratch.arena, source_file_ht, src_file->path, src_file); } src_file_map[file_idx] = src_file; } for EachNode(line_seq, DW_LineSeqNode, line_table->first_seq) { if(line_seq->count == 0) {continue;} U64 *voffs = push_array(arena, U64, line_seq->count); U32 *line_nums = push_array(arena, U32, line_seq->count); U16 *col_nums = 0; U64 line_idx = 0; DW_LineNode *file_line_n = line_seq->first; U64 file_line_count = 0; for EachNode(line_n, DW_LineNode, file_line_n) { if(file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; U64 lines_written = 0; U64 prev_ln = max_U64; DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; for(; file_line_n != sentinel; file_line_n = file_line_n->next) { if(file_line_n->v.line != prev_ln) { if(file_line_n->v.address == 0) {continue;} voffs[line_idx] = file_line_n->v.address; line_nums[line_idx] = file_line_n->v.line; lines_written += 1; line_idx += 1; prev_ln = file_line_n->v.line; } } RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); file_line_count = 1; } else { file_line_count += 1; } } // handle last line if(file_line_n) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; for(;file_line_n != 0; file_line_n = file_line_n->next, line_idx += 1) { // NOTE(rjf): DWARF encodes line info as "relocatable addresses"; we do *not* // need to translate from 'addresses' to 'voffs' with the image base here. voffs[line_idx] = file_line_n->v.address; line_nums[line_idx] = file_line_n->v.line; } RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); } } } } //////////////////////////// //- rjf: build built-in basic types // RDIM_Type *builtin_types[RDI_TypeKind_Count] = {0}; ProfScope("build built-in basic types") { for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) { RDIM_Type *type = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); type->kind = type_kind; type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size); type->byte_size = rdi_size_from_basic_type_kind(type_kind); builtin_types[type_kind] = type; } builtin_types[RDI_TypeKind_Handle]->byte_size = arch_addr_size; builtin_types[RDI_TypeKind_Variadic] = rdim_type_chunk_list_push(arena, &types, TYPE_CHUNK_CAP); builtin_types[RDI_TypeKind_Variadic]->kind = RDI_TypeKind_Variadic; } //////////////////////////// //- rjf: convert units // ProfScope("convert units") { for EachIndex(cu_idx, cu_ranges.count) { Temp comp_temp = temp_begin(scratch.arena); DW_CompUnit *cu = &cu_arr[cu_idx]; // parse and build tag tree DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); // skip DWO { if (cu->dwo_id) { goto next_cu; } String8 dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_DwoName); if (dwo_name.size) { goto next_cu; } String8 gnu_dwo_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_GNU_DwoName); if (gnu_dwo_name.size) { goto next_cu; } } // build (info offset -> tag) hash table to resolve tags with abstract origin cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); // extract compile unit info String8 cu_name = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Name); String8 cu_dir = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_CompDir); String8 cu_prod = dw_string_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Producer); DW_Language cu_lang = dw_const_u64_from_tag_attrib_kind(&input, cu, cu->tag, DW_AttribKind_Language); // init type table D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); type_table->ht = hash_table_init(comp_temp.arena, 0x4000); type_table->types = &types; type_table->type_chunk_cap = TYPE_CHUNK_CAP; type_table->builtin_types = builtin_types; // convert debug info d2r_convert_types(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); d2r_convert_udts(arena, type_table, &input, cu, cu_lang, arch_addr_size, tag_tree.root); d2r_convert_symbols(arena, type_table, &input, cu, cu_lang, arch_addr_size, image_base, arch, tag_tree.root); RDIM_Rng1U64ChunkList cu_voff_ranges = {0}; if(cu_idx < cu_contrib_map.count) { cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); } else { Rng1U64List range_list = d2r_range_list_from_tag(scratch.arena, &input, cu, image_base, cu->tag); for EachNode(n, Rng1U64Node, range_list.first) { rdim_rng1u64_chunk_list_push(arena, &cu_voff_ranges, 512, (RDIM_Rng1U64){ .min = n->v.min, .max = n->v.max }); } } // convert compile unit { RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); unit->unit_name = cu_name; unit->compiler_name = cu_prod; unit->source_file = str8_zero(); // TODO unit->object_file = str8_zero(); // TODO unit->archive_file = str8_zero(); // TODO unit->build_path = cu_dir; unit->language = d2r_rdi_language_from_dw_language(cu_lang); unit->line_table = cu_line_tables_rdi[cu_idx]; unit->voff_ranges = cu_voff_ranges; } next_cu:; temp_end(comp_temp); } } } lane_sync(); RDIM_BakeParams bake_params = {0}; bake_params.subset_flags = params->subset_flags; bake_params.top_level_info = top_level_info; bake_params.binary_sections = binary_sections; bake_params.units = units; bake_params.types = types; bake_params.udts = udts; bake_params.src_files = src_files; bake_params.line_tables = line_tables; bake_params.locations = locations; bake_params.global_variables = gvars; bake_params.thread_variables = tvars; bake_params.procedures = procs; bake_params.scopes = scopes; bake_params.inline_sites = inline_sites; scratch_end(scratch); return bake_params; } ================================================ FILE: src/rdi_from_dwarf/rdi_from_dwarf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FROM_DWARF_H #define RDI_FROM_DWARF_H //////////////////////////////// //~ rjf: Conversion Stage Inputs typedef struct D2R_ConvertParams D2R_ConvertParams; struct D2R_ConvertParams { String8 dbg_name; String8 dbg_data; String8 exe_name; String8 exe_data; ExecutableImageKind exe_kind; RDIM_SubsetFlags subset_flags; B32 deterministic; }; //////////////////////////////// //~ rjf: Conversion Helper Types typedef struct D2R_TypeTable D2R_TypeTable; struct D2R_TypeTable { HashTable *ht; RDIM_TypeChunkList *types; U64 type_chunk_cap; RDIM_Type **builtin_types; }; typedef struct D2R_TagFrame D2R_TagFrame; struct D2R_TagFrame { DW_TagNode *node; RDIM_Scope *scope; struct D2R_TagFrame *next; }; typedef struct D2R_TagIter D2R_TagIter; struct D2R_TagIter { D2R_TagFrame *free_list; D2R_TagFrame *stack; DW_TagNode *tag_node; DW_TagNode *root; B32 visit_children; }; typedef struct D2R_CompUnitContribMap D2R_CompUnitContribMap; struct D2R_CompUnitContribMap { U64 count; U64 *info_off_arr; RDIM_Rng1U64ChunkList *voff_range_arr; }; #define D2R_ValueType_IsSigned(x) ((x) == D2R_ValueType_S8 || (x) == D2R_ValueType_S16 || (x) == D2R_ValueType_S32 || (x) == D2R_ValueType_S64 || (x) == D2R_ValueType_S128 || (x) == D2R_ValueType_S256 || (x) == D2R_ValueType_S512) #define D2R_ValueType_IsUnsigned(x) ((x) == D2R_ValueType_U8 || (x) == D2R_ValueType_U16 || (x) == D2R_ValueType_U32 || (x) == D2R_ValueType_U64 || (x) == D2R_ValueType_U128 || (x) == D2R_ValueType_U256 || (x) == D2R_ValueType_U512) #define D2R_ValueType_IsFloat(x) ((x) == D2R_ValueType_F32 || (x) == D2R_ValueType_F64) #define D2R_ValueType_IsInt(x) (D2R_ValueType_IsSigned(x) || D2R_ValueType_IsUnsigned(x) || (x) == D2R_ValueType_Address) typedef enum D2R_ValueType { D2R_ValueType_Generic, D2R_ValueType_U8, D2R_ValueType_U16, D2R_ValueType_U32, D2R_ValueType_U64, D2R_ValueType_U128, D2R_ValueType_U256, D2R_ValueType_U512, D2R_ValueType_S8, D2R_ValueType_S16, D2R_ValueType_S32, D2R_ValueType_S64, D2R_ValueType_S128, D2R_ValueType_S256, D2R_ValueType_S512, D2R_ValueType_F32, D2R_ValueType_F64, D2R_ValueType_Address, D2R_ValueType_ImplicitValue, D2R_ValueType_Bool = D2R_ValueType_S8, } D2R_ValueType; typedef struct D2R_ValueTypeNode { D2R_ValueType type; struct D2R_ValueTypeNode *next; } D2R_ValueTypeNode; typedef struct D2R_ValueTypeStack { U64 count; D2R_ValueTypeNode *top; D2R_ValueTypeNode *free_list; } D2R_ValueTypeStack; //////////////////////////////// //~ rjf: Enum Conversion Helpers internal RDI_Language d2r_rdi_language_from_dw_language(DW_Language v); internal RDI_RegCodeX86 d2r_rdi_reg_code_from_dw_reg_x86(DW_RegX86 v); internal RDI_RegCodeX64 d2r_rdi_reg_code_from_dw_reg_x64(DW_RegX64 v); internal RDI_RegCode d2r_rdi_reg_code_from_dw_reg(Arch arch, DW_Reg v); //////////////////////////////// //~ rjf: Type Conversion Helpers internal RDIM_Type * d2r_create_type(Arena *arena, D2R_TypeTable *type_table); internal RDIM_Type * d2r_create_type_from_offset(Arena *arena, D2R_TypeTable *type_table, U64 info_off); internal RDIM_Type * d2r_type_from_offset(D2R_TypeTable *type_table, U64 info_off); internal RDIM_Type * d2r_type_from_attrib(D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind); internal Rng1U64List d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 image_base, DW_Tag tag); internal RDIM_Type ** d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_TagNode *cur_node, U64 *param_count_out); //////////////////////////////// //~ RDIM Bytecode Helpers internal B32 rdim_is_eval_bytecode_static(RDIM_EvalBytecode bc); internal U64 rdim_virt_off_from_eval_bytecode(RDIM_EvalBytecode bc, U64 image_base); //////////////////////////////// //~ rjf: Bytecode Conversion Helpers internal D2R_ValueTypeNode * d2r_value_type_stack_push(Arena *arena, D2R_ValueTypeStack *stack, D2R_ValueType type); internal D2R_ValueType d2r_value_type_stack_pop(D2R_ValueTypeStack *stack); internal D2R_ValueType d2r_value_type_stack_peek(D2R_ValueTypeStack *stack); internal D2R_ValueType d2r_unsigned_value_type_from_bit_size(U64 bit_size); internal D2R_ValueType d2r_signed_value_type_from_bit_size(U64 bit_size); internal D2R_ValueType d2r_float_type_from_bit_size(U64 bit_size); internal RDI_EvalTypeGroup d2r_value_type_to_rdi(D2R_ValueType v); internal U64 d2r_size_from_value_type(U64 addr_size, D2R_ValueType value_type); internal D2R_ValueType d2r_pick_common_value_type(D2R_ValueType lhs, D2R_ValueType rhs); internal D2R_ValueType d2r_apply_usual_arithmetic_conversions(Arena *arena, D2R_ValueType lhs, D2R_ValueType rhs, RDIM_EvalBytecode *bc); internal void d2r_push_arithmetic_op(Arena *arena, D2R_ValueTypeStack *stack, RDIM_EvalBytecode *bc, RDI_EvalOp op); internal void d2r_push_relational_op(Arena *arena, D2R_ValueTypeStack *stack, RDIM_EvalBytecode *bc, RDI_EvalOp op); internal RDIM_EvalBytecode d2r_bytecode_from_expression(Arena *arena, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, String8 expr, DW_CompUnit *cu, D2R_ValueType *result_type_out); internal RDIM_Location * d2r_transpile_expression(Arena *arena, RDIM_LocationChunkList *locations, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, DW_CompUnit *cu, String8 expr); internal RDIM_LocationCaseList d2r_locset_from_attrib(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind); internal RDIM_LocationCaseList d2r_var_locset_from_tag(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, RDIM_LocationChunkList *locations, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag); //////////////////////////////// //~ rjf: Compilation Unit / Scope Conversion Helpers internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off); internal RDIM_Scope *d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D2R_TagFrame *tag_stack, Rng1U64List ranges); //////////////////////////////// //~ Tag Iterator internal D2R_TagIter *d2r_tag_iter_init(Arena *arena, DW_TagNode *root); internal void d2r_tag_iter_next(Arena *arena, D2R_TagIter *iter); internal void d2r_tag_iter_skip_children(D2R_TagIter *iter); internal DW_TagNode * d2r_tag_iter_parent_tag_node(D2R_TagIter *iter); internal DW_Tag d2r_tag_iter_parent_tag(D2R_TagIter *iter); //////////////////////////////// //~ Type/UDT/Symbol Conversion internal void d2r_flag_converted_tag(DW_TagNode *tag_node); internal B8 d2r_is_tag_converted(DW_TagNode *tag_node); internal RDIM_Type *d2r_find_or_convert_type(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_Tag tag, DW_AttribKind kind); internal void d2r_convert_types(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root); internal void d2r_convert_udts(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, DW_TagNode *root); internal void d2r_convert_symbols(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Language cu_lang, U64 arch_addr_size, U64 image_base, Arch arch, DW_TagNode *root); //////////////////////////////// //~ rjf: Main Conversion Entry Point internal RDIM_BakeParams d2r_convert(Arena *arena, D2R_ConvertParams *params); #endif // RDI_FROM_DWARF_H ================================================ FILE: src/rdi_from_elf/rdi_from_elf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDI_BinarySectionFlags e2r_rdi_binary_section_flags_from_elf(ELF_SectionFlags f) { RDI_BinarySectionFlags result = RDI_BinarySectionFlag_Read; if(f & ELF_Shf_Write) { result |= RDI_BinarySectionFlag_Write; } if(f & ELF_Shf_ExecInstr) { result |= RDI_BinarySectionFlag_Execute; } return result; } internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array shdrs) { RDIM_BinarySectionList result = {0}; U64 base_vaddr = elf_base_addr_from_bin(bin); for EachIndex(idx, shdrs.count) { ELF_Shdr64 *src = &shdrs.v[idx]; RDIM_BinarySection *dst = rdim_binary_section_list_push(arena, &result); dst->name = elf_name_from_shdr64(data, bin, src); dst->flags = e2r_rdi_binary_section_flags_from_elf(src->sh_flags); dst->voff_first = src->sh_addr - base_vaddr; dst->voff_opl = dst->voff_first + src->sh_size; dst->foff_first = src->sh_offset; dst->foff_opl = dst->foff_first + src->sh_size; } return result; } ================================================ FILE: src/rdi_from_elf/rdi_from_elf.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FROM_ELF_H #define RDI_FROM_ELF_H internal RDI_BinarySectionFlags e2r_rdi_binary_section_flags_from_elf(ELF_SectionFlags f); internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array shdrs); #endif // RDI_FROM_ELF_H ================================================ FILE: src/rdi_from_pdb/rdi_from_pdb.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO(rjf): eliminate redundant null checks, just always allocate // empty results, and have nulls gracefully fall through // // (search for != 0 instances, inserted to prevent prior crashes) //////////////////////////////// //~ rjf: Basic Helpers internal U64 p2r_end_of_cplusplus_container_name(String8 str) { // NOTE: This finds the index one past the last "::" contained in str. // if no "::" is contained in str, then the returned index is 0. // The intent is that [0,clamp_bot(0,result - 2)) gives the // "container name" and [result,str.size) gives the leaf name. U64 result = 0; if(str.size >= 2) { for(U64 i = str.size; i >= 2; i -= 1) { if(str.str[i - 2] == ':' && str.str[i - 1] == ':') { result = i; break; } } } return(result); } internal U64 p2r_hash_from_voff(U64 voff) { U64 hash = (voff >> 3) ^ ((7 & voff) << 6); return hash; } //////////////////////////////// //~ rjf: COFF <-> RDI Canonical Conversions internal RDI_BinarySectionFlags p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) { RDI_BinarySectionFlags result = 0; if(flags & COFF_SectionFlag_MemRead) { result |= RDI_BinarySectionFlag_Read; } if(flags & COFF_SectionFlag_MemWrite) { result |= RDI_BinarySectionFlag_Write; } if(flags & COFF_SectionFlag_MemExecute) { result |= RDI_BinarySectionFlag_Execute; } return(result); } //////////////////////////////// //~ rjf: CodeView <-> RDI Canonical Conversions internal RDI_Arch p2r_rdi_arch_from_cv_arch(CV_Arch cv_arch) { RDI_Arch result = 0; switch(cv_arch) { case CV_Arch_8086: result = RDI_Arch_X86; break; case CV_Arch_X64: result = RDI_Arch_X64; break; //case CV_Arch_8080: break; //case CV_Arch_80286: break; //case CV_Arch_80386: break; //case CV_Arch_80486: break; //case CV_Arch_PENTIUM: break; //case CV_Arch_PENTIUMII: break; //case CV_Arch_PENTIUMIII: break; //case CV_Arch_MIPS: break; //case CV_Arch_MIPS16: break; //case CV_Arch_MIPS32: break; //case CV_Arch_MIPS64: break; //case CV_Arch_MIPSI: break; //case CV_Arch_MIPSII: break; //case CV_Arch_MIPSIII: break; //case CV_Arch_MIPSIV: break; //case CV_Arch_MIPSV: break; //case CV_Arch_M68000: break; //case CV_Arch_M68010: break; //case CV_Arch_M68020: break; //case CV_Arch_M68030: break; //case CV_Arch_M68040: break; //case CV_Arch_ALPHA: break; //case CV_Arch_ALPHA_21164: break; //case CV_Arch_ALPHA_21164A: break; //case CV_Arch_ALPHA_21264: break; //case CV_Arch_ALPHA_21364: break; //case CV_Arch_PPC601: break; //case CV_Arch_PPC603: break; //case CV_Arch_PPC604: break; //case CV_Arch_PPC620: break; //case CV_Arch_PPCFP: break; //case CV_Arch_PPCBE: break; //case CV_Arch_SH3: break; //case CV_Arch_SH3E: break; //case CV_Arch_SH3DSP: break; //case CV_Arch_SH4: break; //case CV_Arch_SHMEDIA: break; //case CV_Arch_ARM3: break; //case CV_Arch_ARM4: break; //case CV_Arch_ARM4T: break; //case CV_Arch_ARM5: break; //case CV_Arch_ARM5T: break; //case CV_Arch_ARM6: break; //case CV_Arch_ARM_XMAC: break; //case CV_Arch_ARM_WMMX: break; //case CV_Arch_ARM7: break; //case CV_Arch_OMNI: break; //case CV_Arch_IA64_1: break; //case CV_Arch_IA64_2: break; //case CV_Arch_CEE: break; //case CV_Arch_AM33: break; //case CV_Arch_M32R: break; //case CV_Arch_TRICORE: break; //case CV_Arch_EBC: break; //case CV_Arch_THUMB: break; //case CV_Arch_ARMNT: break; //case CV_Arch_ARM64: break; //case CV_Arch_D3D11_SHADER: break; } return(result); } internal RDI_RegCode p2r_rdi_reg_code_from_cv_reg_code(RDI_Arch arch, CV_Reg reg_code) { RDI_RegCode result = 0; switch(arch) { case RDI_Arch_X86: { switch(reg_code) { #define X(CVN,C,RDN,BP,BZ) case C: result = RDI_RegCodeX86_##RDN; break; CV_Reg_X86_XList(X) #undef X } }break; case RDI_Arch_X64: { switch(reg_code) { #define X(CVN,C,RDN,BP,BZ) case C: result = RDI_RegCodeX64_##RDN; break; CV_Reg_X64_XList(X) #undef X } }break; } return(result); } internal RDI_Language p2r_rdi_language_from_cv_language(CV_Language cv_language) { RDI_Language result = 0; switch(cv_language) { case CV_Language_C: result = RDI_Language_C; break; case CV_Language_CXX: result = RDI_Language_CPlusPlus; break; //case CV_Language_FORTRAN: result = ; break; //case CV_Language_MASM: result = ; break; //case CV_Language_PASCAL: result = ; break; //case CV_Language_BASIC: result = ; break; //case CV_Language_COBOL: result = ; break; //case CV_Language_LINK: result = ; break; //case CV_Language_CVTRES: result = ; break; //case CV_Language_CVTPGD: result = ; break; //case CV_Language_CSHARP: result = ; break; //case CV_Language_VB: result = ; break; //case CV_Language_ILASM: result = ; break; //case CV_Language_JAVA: result = ; break; //case CV_Language_JSCRIPT: result = ; break; //case CV_Language_MSIL: result = ; break; //case CV_Language_HLSL: result = ; break; } return(result); } internal RDI_TypeKind p2r_rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type) { RDI_TypeKind result = RDI_TypeKind_NULL; switch(basic_type) { case CV_BasicType_VOID: {result = RDI_TypeKind_Void;}break; case CV_BasicType_HRESULT: {result = RDI_TypeKind_HResult;}break; case CV_BasicType_RCHAR: case CV_BasicType_CHAR: case CV_BasicType_CHAR8: {result = RDI_TypeKind_Char8;}break; case CV_BasicType_UCHAR: {result = RDI_TypeKind_UChar8;}break; case CV_BasicType_WCHAR: {result = RDI_TypeKind_UChar16;}break; case CV_BasicType_CHAR16: {result = RDI_TypeKind_Char16;}break; case CV_BasicType_CHAR32: {result = RDI_TypeKind_Char32;}break; case CV_BasicType_BOOL8: case CV_BasicType_INT8: {result = RDI_TypeKind_S8;}break; case CV_BasicType_BOOL16: case CV_BasicType_INT16: case CV_BasicType_SHORT: {result = RDI_TypeKind_S16;}break; case CV_BasicType_BOOL32: case CV_BasicType_INT32: case CV_BasicType_LONG: {result = RDI_TypeKind_S32;}break; case CV_BasicType_BOOL64: case CV_BasicType_INT64: case CV_BasicType_QUAD: {result = RDI_TypeKind_S64;}break; case CV_BasicType_INT128: case CV_BasicType_OCT: {result = RDI_TypeKind_S128;}break; case CV_BasicType_UINT8: {result = RDI_TypeKind_U8;}break; case CV_BasicType_UINT16: case CV_BasicType_USHORT: {result = RDI_TypeKind_U16;}break; case CV_BasicType_UINT32: case CV_BasicType_ULONG: {result = RDI_TypeKind_U32;}break; case CV_BasicType_UINT64: case CV_BasicType_UQUAD: {result = RDI_TypeKind_U64;}break; case CV_BasicType_UINT128: case CV_BasicType_UOCT: {result = RDI_TypeKind_U128;}break; case CV_BasicType_FLOAT16:{result = RDI_TypeKind_F16;}break; case CV_BasicType_FLOAT32:{result = RDI_TypeKind_F32;}break; case CV_BasicType_FLOAT32PP:{result = RDI_TypeKind_F32PP;}break; case CV_BasicType_FLOAT48:{result = RDI_TypeKind_F48;}break; case CV_BasicType_FLOAT64:{result = RDI_TypeKind_F64;}break; case CV_BasicType_FLOAT80:{result = RDI_TypeKind_F80;}break; case CV_BasicType_FLOAT128:{result = RDI_TypeKind_F128;}break; case CV_BasicType_COMPLEX32:{result = RDI_TypeKind_ComplexF32;}break; case CV_BasicType_COMPLEX64:{result = RDI_TypeKind_ComplexF64;}break; case CV_BasicType_COMPLEX80:{result = RDI_TypeKind_ComplexF80;}break; case CV_BasicType_COMPLEX128:{result = RDI_TypeKind_ComplexF128;}break; case CV_BasicType_PTR:{result = RDI_TypeKind_Handle;}break; } return result; } internal RDI_ChecksumKind p2r_rdi_from_cv_c13_checksum_kind(CV_C13ChecksumKind k) { RDI_ChecksumKind result = RDI_ChecksumKind_NULL; switch((CV_C13ChecksumKindEnum)k) { case CV_C13ChecksumKind_Null: {result = RDI_ChecksumKind_NULL;}break; case CV_C13ChecksumKind_MD5: {result = RDI_ChecksumKind_MD5;}break; case CV_C13ChecksumKind_SHA1: {result = RDI_ChecksumKind_SHA1;}break; case CV_C13ChecksumKind_SHA256:{result = RDI_ChecksumKind_SHA256;}break; } return result; } //////////////////////////////// //~ rjf: Location Info Building Helpers internal RDI_RegCode p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg) { RDI_RegCode result = 0; switch(arch) { case RDI_Arch_X86: { switch(encoded_reg) { case CV_EncodedFramePtrReg_StackPtr: { // TODO(allen): support CV_AllReg_VFRAME // TODO(allen): error }break; case CV_EncodedFramePtrReg_FramePtr: { result = RDI_RegCodeX86_ebp; }break; case CV_EncodedFramePtrReg_BasePtr: { result = RDI_RegCodeX86_ebx; }break; } }break; case RDI_Arch_X64: { switch(encoded_reg) { case CV_EncodedFramePtrReg_StackPtr: { result = RDI_RegCodeX64_rsp; }break; case CV_EncodedFramePtrReg_FramePtr: { result = RDI_RegCodeX64_rbp; }break; case CV_EncodedFramePtrReg_BasePtr: { result = RDI_RegCodeX64_r13; }break; } }break; } return(result); } internal RDIM_LocationInfo p2r_location_info_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 extra_indirection) { RDIM_LocationInfo result = {0}; if(0 <= offset && offset <= (S64)max_U16) { if(extra_indirection) { result.kind = RDI_LocationKind_AddrAddrRegPlusU16; result.reg_code = reg_code; result.offset = offset; } else { result.kind = RDI_LocationKind_AddrRegPlusU16; result.reg_code = reg_code; result.offset = offset; } } else { RDIM_EvalBytecode bytecode = {0}; U32 regread_param = RDI_EncodeRegReadParam(reg_code, reg_byte_size, reg_byte_pos); rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_RegRead, regread_param); rdim_bytecode_push_sconst(arena, &bytecode, offset); rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_Add, 0); if(extra_indirection) { U64 addr_size = rdi_addr_size_from_arch(arch); rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_MemRead, addr_size); } result.kind = RDI_LocationKind_AddrBytecodeStream; result.bytecode = bytecode; } return result; } internal void p2r_local_push_location_cases_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Local *local, RDIM_Location *loc, CV_LvarAddrRange *range, COFF_SectionHeader *section, CV_LvarAddrGap *gaps, U64 gap_count) { //- rjf: extract range info U64 voff_first = 0; U64 voff_opl = 0; if(section != 0) { voff_first = section->voff + range->off; voff_opl = voff_first + range->len; } //- rjf: emit location for ranges not coverd by gaps CV_LvarAddrGap *gap_ptr = gaps; U64 voff_cursor = voff_first; for(U64 i = 0; i < gap_count; i += 1, gap_ptr += 1) { U64 voff_gap_first = voff_first + gap_ptr->off; U64 voff_gap_opl = voff_gap_first + gap_ptr->len; if(voff_cursor < voff_gap_first) { RDIM_Rng1U64 voff_range = {voff_cursor, voff_gap_first}; rdim_local_push_location_case(arena, scopes, local, loc, voff_range); } voff_cursor = voff_gap_opl; } //- rjf: emit remaining range if(voff_cursor < voff_opl) { RDIM_Rng1U64 voff_range = {voff_cursor, voff_opl}; rdim_local_push_location_case(arena, scopes, local, loc, voff_range); } } //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point internal RDIM_BakeParams p2r_convert(Arena *arena, P2R_ConvertParams *params) { Temp scratch = scratch_begin(&arena, 1); ////////////////////////////////////////////////////////////// //- rjf: do base MSF parse // MSF_Parsed *msf = 0; { Temp scratch2 = scratch_begin(&scratch.arena, 1); // rjf: setup output buckets MSF_RawStreamTable *msf_raw_stream_table = 0; if(lane_idx() == 0) { msf_raw_stream_table = msf_raw_stream_table_from_data(scratch2.arena, params->input_pdb_data); msf = push_array(scratch.arena, MSF_Parsed, 1); msf->page_size = msf_raw_stream_table->page_size; msf->page_count = msf_raw_stream_table->total_page_count; msf->stream_count = msf_raw_stream_table->stream_count; msf->streams = push_array(scratch.arena, String8, msf->stream_count); } lane_sync_u64(&msf, 0); lane_sync_u64(&msf_raw_stream_table, 0); // rjf: do wide fill { U64 msf_stream_take_counter = 0; U64 *msf_stream_take_counter_ptr = &msf_stream_take_counter; lane_sync_u64(&msf_stream_take_counter_ptr, 0); for(;;) { U64 stream_idx = ins_atomic_u64_inc_eval(msf_stream_take_counter_ptr) - 1; if(stream_idx >= msf->stream_count) { break; } msf->streams[stream_idx] = msf_data_from_stream_number(arena, params->input_pdb_data, msf_raw_stream_table, stream_idx); } } lane_sync(); scratch_end(scratch2); } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: do top-level MSF/PDB extraction // PDB_Info *pdb_info = 0; PDB_NamedStreamTable *named_streams = 0; ProfScope("do top-level MSF/PDB extraction") if(lane_idx() == 0) { ProfScope("parse PDB info") { String8 info_data = msf_data_from_stream(msf, PDB_FixedStream_Info); pdb_info = pdb_info_from_data(scratch.arena, info_data); if(pdb_info->features & PDB_FeatureFlag_MINIMAL_DBG_INFO) { log_user_error(str8_lit("PDB was linked with /DEBUG:FASTLINK; partial debug info is not supported. Please relink using /DEBUG:FULL.")); } } ProfScope("parse named streams table") { named_streams = pdb_named_stream_table_from_info(scratch.arena, pdb_info); } } lane_sync_u64(&pdb_info, 0); lane_sync_u64(&named_streams, 0); ////////////////////////////////////////////////////////////// //- rjf: parse PDB strtbl & top-level streams // PDB_Strtbl *strtbl = 0; String8 raw_strtbl = {0}; PDB_DbiParsed *dbi = 0; PDB_TpiParsed *tpi = 0; PDB_TpiParsed *ipi = 0; ProfScope("parse PDB strtbl & top-level streams") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("parse PDB strtbl") { MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable]; String8 strtbl_data = msf_data_from_stream(msf, strtbl_sn); strtbl = pdb_strtbl_from_data(scratch.arena, strtbl_data); raw_strtbl = str8_substr(strtbl_data, rng_1u64(strtbl->strblock_min, strtbl->strblock_max)); } if(lane_idx() == lane_from_task_idx(1)) ProfScope("parse DBI") { String8 dbi_data = msf_data_from_stream(msf, PDB_FixedStream_Dbi); dbi = pdb_dbi_from_data(scratch.arena, dbi_data); } if(lane_idx() == lane_from_task_idx(2)) ProfScope("parse TPI") { String8 tpi_data = msf_data_from_stream(msf, PDB_FixedStream_Tpi); tpi = pdb_tpi_from_data(scratch.arena, tpi_data); } if(lane_idx() == lane_from_task_idx(3)) ProfScope("parse IPI") { String8 ipi_data = msf_data_from_stream(msf, PDB_FixedStream_Ipi); ipi = pdb_tpi_from_data(scratch.arena, ipi_data); } } lane_sync_u64(&strtbl, lane_from_task_idx(0)); lane_sync_u64(&raw_strtbl.size, lane_from_task_idx(0)); lane_sync_u64(&raw_strtbl.str, lane_from_task_idx(0)); lane_sync_u64(&dbi, lane_from_task_idx(1)); lane_sync_u64(&tpi, lane_from_task_idx(2)); lane_sync_u64(&ipi, lane_from_task_idx(3)); ////////////////////////////////////////////////////////////// //- rjf: unpack DBI // COFF_SectionHeaderArray coff_sections = {0}; PDB_GsiParsed *gsi = 0; PDB_GsiParsed *psi_gsi_part = 0; ProfScope("unpack DBI") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("parse COFF sections") { MSF_StreamNumber section_stream = dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER]; String8 section_data = msf_data_from_stream(msf, section_stream); coff_sections = pdb_coff_section_array_from_data(scratch.arena, section_data); } if(lane_idx() == lane_from_task_idx(1)) ProfScope("parse GSI") { String8 gsi_data = msf_data_from_stream(msf, dbi->gsi_sn); gsi = pdb_gsi_from_data(scratch.arena, gsi_data); } if(lane_idx() == lane_from_task_idx(2)) ProfScope("parse GSI part of PSI") { String8 psi_data = msf_data_from_stream(msf, dbi->psi_sn); String8 psi_data_gsi_part = str8_range(psi_data.str + sizeof(PDB_PsiHeader), psi_data.str + psi_data.size); psi_gsi_part = pdb_gsi_from_data(scratch.arena, psi_data_gsi_part); } } lane_sync_u64(&coff_sections.v, lane_from_task_idx(0)); lane_sync_u64(&coff_sections.count, lane_from_task_idx(0)); lane_sync_u64(&gsi, lane_from_task_idx(1)); lane_sync_u64(&psi_gsi_part, lane_from_task_idx(2)); ////////////////////////////////////////////////////////////// //- rjf: hash EXE, parse TPI/IPI hash/leaf & global symbol stream & comp units // U64 exe_hash = 0; PDB_TpiHashParsed *tpi_hash = 0; CV_LeafParsed *tpi_leaf = 0; PDB_TpiHashParsed *ipi_hash = 0; CV_LeafParsed *ipi_leaf = 0; PDB_CompUnitArray *comp_units = 0; PDB_CompUnitContributionArray *comp_unit_contributions = 0; ProfScope("hash EXE, parse TPI/IPI hash/leaf & global symbol stream & comp units") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("hash EXE") { exe_hash = rdi_hash(params->input_exe_data.str, params->input_exe_data.size); } if(lane_idx() == lane_from_task_idx(1)) ProfScope("parse TPI hash") { String8 hash_data = msf_data_from_stream(msf, tpi->hash_sn); String8 aux_data = msf_data_from_stream(msf, tpi->hash_sn_aux); if(!(params->subset_flags & (RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs))) { hash_data = aux_data = str8_zero(); } tpi_hash = pdb_tpi_hash_from_data(scratch.arena, strtbl, tpi, hash_data, aux_data); } if(lane_idx() == lane_from_task_idx(2)) ProfScope("parse TPI leaf") { String8 leaf_data = pdb_leaf_data_from_tpi(tpi); tpi_leaf = cv_leaf_from_data(scratch.arena, leaf_data, tpi->itype_first); } if(lane_idx() == lane_from_task_idx(3)) ProfScope("parse IPI hash") { String8 hash_data = msf_data_from_stream(msf, ipi->hash_sn); String8 aux_data = msf_data_from_stream(msf, ipi->hash_sn_aux); if(!(params->subset_flags & (RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs))) { hash_data = aux_data = str8_zero(); } ipi_hash = pdb_tpi_hash_from_data(scratch.arena, strtbl, ipi, hash_data, aux_data); } if(lane_idx() == lane_from_task_idx(4)) ProfScope("parse IPI leaf") { String8 leaf_data = pdb_leaf_data_from_tpi(ipi); ipi_leaf = cv_leaf_from_data(scratch.arena, leaf_data, ipi->itype_first); } if(lane_idx() == lane_from_task_idx(5)) ProfScope("parse compilation units") { String8 comp_units_data = pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo); comp_units = pdb_comp_unit_array_from_data(scratch.arena, comp_units_data); } if(lane_idx() == lane_from_task_idx(6)) ProfScope("parse compilation unit contributions") { String8 contribs_data = pdb_data_from_dbi_range(dbi, PDB_DbiRange_SecCon); comp_unit_contributions = push_array(scratch.arena, PDB_CompUnitContributionArray, 1); comp_unit_contributions[0] = pdb_comp_unit_contribution_array_from_data(scratch.arena, contribs_data, coff_sections); } } lane_sync_u64(&exe_hash, lane_from_task_idx(0)); lane_sync_u64(&tpi_hash, lane_from_task_idx(1)); lane_sync_u64(&tpi_leaf, lane_from_task_idx(2)); lane_sync_u64(&ipi_hash, lane_from_task_idx(3)); lane_sync_u64(&ipi_leaf, lane_from_task_idx(4)); lane_sync_u64(&comp_units, lane_from_task_idx(5)); lane_sync_u64(&comp_unit_contributions, lane_from_task_idx(6)); ////////////////////////////////////////////////////////////// //- rjf: bucket compilation unit contributions // RDIM_Rng1U64ChunkList *unit_ranges = 0; ProfScope("bucket compilation unit contributions") if(lane_idx() == 0) { unit_ranges = push_array(scratch.arena, RDIM_Rng1U64ChunkList, comp_units->count); for(U64 idx = 0; idx < comp_unit_contributions->count; idx += 1) { PDB_CompUnitContribution *contribution = &comp_unit_contributions->contributions[idx]; if(contribution->mod < comp_units->count) { RDIM_Rng1U64 r = {contribution->voff_first, contribution->voff_opl}; rdim_rng1u64_chunk_list_push(arena, &unit_ranges[contribution->mod], 256, r); } } } lane_sync_u64(&unit_ranges, 0); ////////////////////////////////////////////////////////////// //- rjf: parse all syms & c13 line info streams // U64 all_syms_count = 0; CV_SymParsed **all_syms = 0; CV_C13Parsed **all_c13s = 0; ProfScope("parse all syms & c13 line info streams") { //- rjf: setup outputs if(lane_idx() == 0) { all_syms_count = comp_units->count+1; // +1 for global symbol stream from DBI all_syms = push_array(scratch.arena, CV_SymParsed *, all_syms_count); all_c13s = push_array(scratch.arena, CV_C13Parsed *, all_syms_count); } lane_sync_u64(&all_syms_count, 0); lane_sync_u64(&all_syms, 0); lane_sync_u64(&all_c13s, 0); //- rjf: wide fill { U64 task_counter = 0; U64 *task_counter_ptr = &task_counter; lane_sync_u64(&task_counter_ptr, 0); U64 task_count = all_syms_count; for(;;) { U64 task_idx = ins_atomic_u64_inc_eval(task_counter_ptr) - 1; if(task_idx >= task_count) { break; } if(task_idx > 0) { PDB_CompUnit *unit = comp_units->units[task_idx-1]; String8 unit_sym_data = pdb_data_from_unit_range(msf, unit, PDB_DbiCompUnitRange_Symbols); String8 unit_c13_data = pdb_data_from_unit_range(msf, unit, PDB_DbiCompUnitRange_C13); all_syms[task_idx] = cv_sym_from_data(arena, unit_sym_data, 4); all_c13s[task_idx] = cv_c13_parsed_from_data(arena, unit_c13_data, raw_strtbl, coff_sections); } else { String8 global_sym_data = msf_data_from_stream(msf, dbi->sym_sn); all_syms[task_idx] = cv_sym_from_data(arena, global_sym_data, 4); } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: calculate EXE's max voff // U64 exe_voff_max = 0; { Temp scratch2 = scratch_begin(&scratch.arena, 1); // rjf: set up U64 *lane_voff_maxes = 0; if(lane_idx() == 0) { lane_voff_maxes = push_array(scratch2.arena, U64, lane_count()); } lane_sync_u64(&lane_voff_maxes, 0); // rjf: compute each lane's max { U64 lane_voff_max = 0; COFF_SectionHeader *sections = coff_sections.v; Rng1U64 range = lane_range(coff_sections.count); for EachInRange(idx, range) { lane_voff_max = Max(lane_voff_max, sections[idx].voff + sections[idx].vsize); } lane_voff_maxes[lane_idx()] = lane_voff_max; } lane_sync(); // rjf: find max from all lanes U64 exe_voff_max = 0; for EachIndex(l_idx, lane_count()) { exe_voff_max = Max(exe_voff_max, lane_voff_maxes[l_idx]); } lane_sync(); scratch_end(scratch2); } ////////////////////////////////////////////////////////////// //- rjf: determine architecture // RDI_Arch arch = RDI_Arch_NULL; U64 arch_addr_size = 0; { // // TODO(rjf): in some cases, the first compilation unit has a zero // architecture, as it's sometimes used as a "nil" unit. this causes bugs // in later stages of conversion - particularly, this was detected via // busted location info. so i've converted this to a scan-until-we-find-an- // architecture. however, this may still be fundamentally insufficient, // because Nick has informed me that x86 units can be linked with x64 // units, meaning the appropriate architecture at any point in time is not // a top-level concept, and is rather dependent on to which compilation // unit particular symbols belong. so in the future, to support that (odd) // case, we'll need to not only have this be a top-level "contextual" piece // of info, but to use the appropriate compilation unit's architecture when // possible. assuming, of course, that we care about supporting that case. // for EachIndex(idx, all_syms_count) { arch = p2r_rdi_arch_from_cv_arch(all_syms[idx]->info.arch); if(arch != RDI_Arch_NULL) { break; } } arch_addr_size = rdi_addr_size_from_arch(arch); } ////////////////////////////////////////////////////////////// //- rjf: predict total symbol count // U64 symbol_count_prediction = 0; { U64 *symbol_count_prediction_ptr = &symbol_count_prediction; lane_sync_u64(&symbol_count_prediction_ptr, 0); U64 lane_sym_count = 0; Rng1U64 range = lane_range(all_syms_count); for EachInRange(idx, range) { lane_sym_count += all_syms[idx]->sym_ranges.count; } ins_atomic_u64_add_eval(symbol_count_prediction_ptr, lane_sym_count); lane_sync(); symbol_count_prediction = *symbol_count_prediction_ptr; } ////////////////////////////////////////////////////////////// //- rjf: build link name map // P2R_LinkNameMap *link_name_map = 0; ProfScope("build link name map") if(all_syms_count != 0 && lane_idx() == 0) { // rjf: set up { link_name_map = push_array(scratch.arena, P2R_LinkNameMap, 1); link_name_map->buckets_count = Max(1, symbol_count_prediction); link_name_map->buckets = push_array(scratch.arena, P2R_LinkNameNode *, link_name_map->buckets_count); } // rjf: fill if(params->subset_flags & RDIM_SubsetFlag_Procedures) { CV_SymParsed *sym = all_syms[0]; CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges; CV_RecRange *rec_ranges_opl = sym->sym_ranges.ranges + sym->sym_ranges.count; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) { //- rjf: unpack symbol range info CV_SymKind kind = rec_range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_sym_kind(kind); U8 *sym_first = sym->data.str + rec_range->off + 2; U8 *sym_opl = sym_first + rec_range->hdr.size; //- rjf: skip bad ranges if(sym_opl > sym->data.str + sym->data.size || sym_first + header_struct_size > sym->data.str + sym->data.size) { continue; } //- rjf: consume symbol switch(kind) { default:{}break; case CV_SymKind_PUB32: { // rjf: unpack sym CV_SymPub32 *pub32 = (CV_SymPub32 *)sym_first; String8 name = str8_cstring_capped(pub32+1, sym_opl); COFF_SectionHeader *section = (0 < pub32->sec && pub32->sec <= coff_sections.count) ? &coff_sections.v[pub32->sec-1] : 0; U64 voff = 0; if(section != 0) { voff = section->voff + pub32->off; } // rjf: commit to link name map U64 hash = p2r_hash_from_voff(voff); U64 bucket_idx = hash%link_name_map->buckets_count; P2R_LinkNameNode *node = push_array(scratch.arena, P2R_LinkNameNode, 1); SLLStackPush(link_name_map->buckets[bucket_idx], node); node->voff = voff; node->name = name; }break; } } } } lane_sync_u64(&link_name_map, 0); ////////////////////////////////////////////////////////////// //- rjf: gather all file paths // P2R_SrcFileStubArray *unit_file_stubs = 0; U64Array *unit_file_paths_hashes = 0; ProfScope("gather all file paths") { //- rjf: prep outputs ProfScope("prep outputs") if(lane_idx() == 0) { unit_file_stubs = push_array(scratch.arena, P2R_SrcFileStubArray, comp_units->count); unit_file_paths_hashes = push_array(scratch.arena, U64Array, comp_units->count); } lane_sync_u64(&unit_file_stubs, 0); lane_sync_u64(&unit_file_paths_hashes, 0); //- rjf: do wide gather ProfScope("do wide gather") { Temp scratch2 = scratch_begin(&scratch.arena, 1); //- rjf: build local hash table to dedup files within this lane U64 hit_path_slots_count = 4096; String8Node **hit_path_slots = push_array(scratch2.arena, String8Node *, hit_path_slots_count); //- rjf: take units across lanes, find all file paths U64 sym_take_counter = 0; U64 *sym_take_counter_ptr = &sym_take_counter; lane_sync_u64(&sym_take_counter_ptr, 0); ProfScope("take units across lanes, find all file paths") for(;;) { //- rjf: take next unit U64 unit_idx = ins_atomic_u64_inc_eval(sym_take_counter_ptr) - 1; if(unit_idx >= comp_units->count) { break; } //- rjf: unpack unit PDB_CompUnit *unit = comp_units->units[unit_idx]; CV_SymParsed *sym = all_syms[unit_idx+1]; CV_C13Parsed *c13 = all_c13s[unit_idx+1]; CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges; CV_RecRange *rec_ranges_opl = sym->sym_ranges.ranges + sym->sym_ranges.count; //- rjf: produce obj name/path String8 obj_name = unit->obj_name; { if(str8_match(obj_name, str8_lit("* Linker *"), 0) || str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) { MemoryZeroStruct(&obj_name); } } String8 obj_folder_path = backslashed_from_str8(scratch2.arena, str8_chop_last_slash(obj_name)); //- rjf: find all inline site symbols & gather file stubs P2R_SrcFileStubNode *first_src_file_stub = 0; P2R_SrcFileStubNode *last_src_file_stub = 0; U64 src_file_stub_count = 0; U64 base_voff = 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) { //- rjf: rec range -> symbol info range U64 sym_off_first = rec_range->off + 2; U64 sym_off_opl = rec_range->off + rec_range->hdr.size; //- rjf: skip invalid ranges if(sym_off_opl > sym->data.size || sym_off_first > sym->data.size || sym_off_first > sym_off_opl) { continue; } //- rjf: unpack symbol info CV_SymKind kind = rec_range->hdr.kind; U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); void *sym_header_struct_base = sym->data.str + sym_off_first; void *sym_data_opl = sym->data.str + sym_off_opl; //- rjf: skip bad sizes if(sym_off_first + sym_header_struct_size > sym_off_opl) { continue; } //- rjf: process symbol switch(kind) { default:{}break; //- rjf: LPROC32/GPROC32 (gather base address) case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= coff_sections.count) ? &coff_sections.v[proc32->sec-1] : 0; if(section != 0) { base_voff = section->voff + proc32->off; } }break; //- rjf: INLINESITE case CV_SymKind_INLINESITE: { // rjf: unpack sym CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); // rjf: map inlinee -> parsed cv c13 inlinee line info CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; { U64 hash = cv_hash_from_item_id(sym->inlinee); U64 slot_idx = hash%c13->inlinee_lines_parsed_slots_count; for(CV_C13InlineeLinesParsedNode *n = c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) { if(n->v.inlinee == sym->inlinee) { inlinee_lines_parsed = &n->v; break; } } } // rjf: build line table, fill with parsed binary annotations if(inlinee_lines_parsed != 0) { // rjf: grab checksums sub-section CV_C13SubSectionNode *file_chksms = c13->file_chksms_sub_section; // rjf: gathered lines U32 last_file_off = max_U32; U32 curr_file_off = max_U32; U64 line_count = 0; CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); for(;;) { // rjf: step & update CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) { last_file_off = curr_file_off; curr_file_off = step.file_off; } if(step.flags == 0 && line_count > 0) { last_file_off = curr_file_off; curr_file_off = max_U32; } // rjf: file updated -> gather new file name if(last_file_off != max_U32 && last_file_off != curr_file_off) { String8 seq_file_name = {0}; CV_C13ChecksumKind checksum_kind = CV_C13ChecksumKind_Null; String8 checksum_value = {0}; if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { CV_C13Checksum *checksum = (CV_C13Checksum *)(c13->data.str + file_chksms->off + last_file_off); U32 name_off = checksum->name_off; seq_file_name = pdb_strtbl_string_from_off(strtbl, name_off); checksum_kind = checksum->kind; checksum_value = str8_skip(c13->data, file_chksms->off + last_file_off + sizeof(*checksum)); checksum_value.size = Min(checksum->len, checksum_value.size); } // rjf: file name -> sanitized file path String8 file_path = seq_file_name; String8 file_path_sanitized = str8_copy(scratch2.arena, str8_skip_chop_whitespace(file_path)); { PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); String8List file_path_sanitized_parts = str8_split_path(scratch2.arena, file_path_sanitized); if(file_path_sanitized_style == PathStyle_Relative) { String8List obj_folder_path_parts = str8_split_path(scratch2.arena, obj_folder_path); str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); file_path_sanitized_parts = obj_folder_path_parts; file_path_sanitized_style = path_style_from_str8(obj_folder_path); } str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); file_path_sanitized = str8_path_list_join_by_style(scratch2.arena, &file_path_sanitized_parts, file_path_sanitized_style); } // rjf: sanitized file path -> source file node U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); U64 hit_path_slot = file_path_sanitized_hash%hit_path_slots_count; String8Node *hit_path_node = 0; for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next) { if(str8_match(n->string, file_path_sanitized, 0)) { hit_path_node = n; break; } } if(hit_path_node == 0) { hit_path_node = push_array(scratch2.arena, String8Node, 1); SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node); hit_path_node->string = file_path_sanitized; P2R_SrcFileStubNode *stub_n = push_array(scratch2.arena, P2R_SrcFileStubNode, 1); SLLQueuePush(first_src_file_stub, last_src_file_stub, stub_n); src_file_stub_count += 1; stub_n->v.file_path = str8_copy(scratch.arena, file_path_sanitized); stub_n->v.checksum_kind = checksum_kind; stub_n->v.checksum = str8_copy(scratch.arena, checksum_value); } line_count = 0; } // rjf: count lines if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) { line_count += 1; } // rjf: no more flags -> done if(step.flags == 0) { break; } } } }break; } } // rjf: find all files in this unit's (non-inline) line info ProfScope("find all files in this unit's (non-inline) line info") for(CV_C13SubSectionNode *node = c13->first_sub_section; node != 0; node = node->next) { if(node->kind == CV_C13SubSectionKind_Lines) { for(CV_C13LinesParsedNode *lines_n = node->lines_first; lines_n != 0; lines_n = lines_n->next) { // rjf: file name -> sanitized file path String8 file_path = lines_n->v.file_name; String8 file_path_sanitized = str8_copy(scratch2.arena, str8_skip_chop_whitespace(file_path)); { PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); String8List file_path_sanitized_parts = str8_split_path(scratch2.arena, file_path_sanitized); if(file_path_sanitized_style == PathStyle_Relative) { String8List obj_folder_path_parts = str8_split_path(scratch2.arena, obj_folder_path); str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); file_path_sanitized_parts = obj_folder_path_parts; file_path_sanitized_style = path_style_from_str8(obj_folder_path); } str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); file_path_sanitized = str8_path_list_join_by_style(scratch2.arena, &file_path_sanitized_parts, file_path_sanitized_style); } // rjf: sanitized file path -> source file node U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); U64 hit_path_slot = file_path_sanitized_hash%hit_path_slots_count; String8Node *hit_path_node = 0; for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next) { if(str8_match(n->string, file_path_sanitized, 0)) { hit_path_node = n; break; } } if(hit_path_node == 0) { hit_path_node = push_array(scratch2.arena, String8Node, 1); SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node); hit_path_node->string = file_path_sanitized; P2R_SrcFileStubNode *stub_n = push_array(scratch2.arena, P2R_SrcFileStubNode, 1); SLLQueuePush(first_src_file_stub, last_src_file_stub, stub_n); src_file_stub_count += 1; stub_n->v.file_path = str8_copy(scratch.arena, file_path_sanitized); stub_n->v.checksum_kind = lines_n->v.checksum_kind; stub_n->v.checksum = str8_copy(scratch.arena, lines_n->v.checksum); } } } } //- rjf: merge into array for this unit unit_file_stubs[unit_idx].count = src_file_stub_count; unit_file_stubs[unit_idx].v = push_array_no_zero(scratch.arena, P2R_SrcFileStub, unit_file_stubs[unit_idx].count); { U64 idx = 0; for EachNode(n, P2R_SrcFileStubNode, first_src_file_stub) { unit_file_stubs[unit_idx].v[idx] = n->v; idx += 1; } } //- rjf: hash this unit's file paths U64Array hashes = {0}; hashes.count = unit_file_stubs[unit_idx].count; hashes.v = push_array(scratch.arena, U64, hashes.count); for EachIndex(idx, unit_file_stubs[unit_idx].count) { hashes.v[idx] = rdi_hash(unit_file_stubs[unit_idx].v[idx].file_path.str, unit_file_stubs[unit_idx].v[idx].file_path.size); } unit_file_paths_hashes[unit_idx] = hashes; } lane_sync(); scratch_end(scratch2); } } ////////////////////////////////////////////////////////////// //- rjf: build unified collection & map for source files // RDIM_SrcFileChunkList *all_src_files__sequenceless = 0; P2R_SrcFileMap *src_file_map = 0; if(lane_idx() == 0 && params->subset_flags & (RDIM_SubsetFlag_NormalSourcePathNameMap| RDIM_SubsetFlag_LineInfo| RDIM_SubsetFlag_InlineLineInfo)) { //- rjf: set up table U64 total_path_count = 0; ProfScope("set up table") { all_src_files__sequenceless = push_array(scratch.arena, RDIM_SrcFileChunkList, 1); src_file_map = push_array(scratch.arena, P2R_SrcFileMap, 1); for EachIndex(idx, comp_units->count) { total_path_count += unit_file_stubs[idx].count; } src_file_map->slots_count = total_path_count + total_path_count/2 + 1; src_file_map->slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map->slots_count); } //- rjf: fill table ProfScope("fill table") { for EachIndex(idx, comp_units->count) { P2R_SrcFileStubArray stubs = unit_file_stubs[idx]; U64Array hashes = unit_file_paths_hashes[idx]; for EachIndex(stub_idx, stubs.count) { String8 file_path_sanitized = stubs.v[stub_idx].file_path; CV_C13ChecksumKind c13_checksum_kind = stubs.v[stub_idx].checksum_kind; String8 checksum = stubs.v[stub_idx].checksum; U64 file_path_sanitized_hash = hashes.v[stub_idx]; U64 src_file_slot = file_path_sanitized_hash%src_file_map->slots_count; P2R_SrcFileNode *src_file_node = 0; for(P2R_SrcFileNode *n = src_file_map->slots[src_file_slot]; n != 0; n = n->next) { if(str8_match(n->src_file->path, file_path_sanitized, 0)) { src_file_node = n; break; } } if(src_file_node == 0) { src_file_node = push_array(arena, P2R_SrcFileNode, 1); SLLStackPush(src_file_map->slots[src_file_slot], src_file_node); src_file_node->src_file = rdim_src_file_chunk_list_push(arena, all_src_files__sequenceless, total_path_count); src_file_node->src_file->path = str8_copy(arena, file_path_sanitized); src_file_node->src_file->checksum_kind = p2r_rdi_from_cv_c13_checksum_kind(c13_checksum_kind); src_file_node->src_file->checksum = str8_copy(arena, checksum); } } } } } lane_sync_u64(&all_src_files__sequenceless, 0); lane_sync_u64(&src_file_map, 0); ////////////////////////////////////////////////////////////// //- rjf: convert unit info // RDIM_UnitChunkList *all_units_ptr = 0; RDIM_LineTableChunkList *units_line_tables = 0; RDIM_LineTable **units_first_inline_site_line_tables = 0; ProfScope("convert unit info") { //- rjf: set up outputs ProfScope("set up outputs") if(lane_idx() == 0) { all_units_ptr = push_array(scratch.arena, RDIM_UnitChunkList, 1); if(params->subset_flags & RDIM_SubsetFlag_Units) { for EachIndex(idx, comp_units->count) { rdim_unit_chunk_list_push(arena, all_units_ptr, comp_units->count); } } units_line_tables = push_array(scratch.arena, RDIM_LineTableChunkList, comp_units->count); units_first_inline_site_line_tables = push_array(scratch.arena, RDIM_LineTable *, comp_units->count); } lane_sync_u64(&all_units_ptr, 0); lane_sync_u64(&units_line_tables, 0); lane_sync_u64(&units_first_inline_site_line_tables, 0); RDIM_Unit *units = all_units_ptr->first ? all_units_ptr->first->v : 0; U64 units_count = all_units_ptr->first ? all_units_ptr->first->count : 0; Assert(units_count == comp_units->count); //- rjf: do per-lane work if(params->subset_flags & (RDIM_SubsetFlag_Units| RDIM_SubsetFlag_NormalSourcePathNameMap| RDIM_SubsetFlag_LineInfo| RDIM_SubsetFlag_InlineLineInfo)) { U64 sym_take_counter = 0; U64 *sym_take_counter_ptr = &sym_take_counter; lane_sync_u64(&sym_take_counter_ptr, 0); ProfScope("wide fill") for(;;) { //- rjf: take next unit U64 unit_idx = ins_atomic_u64_inc_eval(sym_take_counter_ptr) - 1; if(unit_idx >= comp_units->count) { break; } Temp scratch = scratch_begin(&arena, 1); RDIM_LineTableChunkList *dst_line_tables = &units_line_tables[unit_idx]; PDB_CompUnit *src_unit = comp_units->units[unit_idx]; CV_SymParsed *src_unit_sym = all_syms[unit_idx+1]; CV_C13Parsed *src_unit_c13 = all_c13s[unit_idx+1]; RDIM_Unit *dst_unit = 0; if(params->subset_flags & RDIM_SubsetFlag_Units) { dst_unit = &units[unit_idx]; } // rjf: extract unit name String8 unit_name = src_unit->obj_name; if(unit_name.size != 0) { String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); if(unit_name_past_last_slash.size != 0) { unit_name = unit_name_past_last_slash; } } // rjf: produce obj name/path String8 obj_name = src_unit->obj_name; if(str8_match(obj_name, str8_lit("* Linker *"), 0) || str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) { MemoryZeroStruct(&obj_name); } String8 obj_folder_path = backslashed_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); //- rjf: main unit line table conversion if(params->subset_flags & RDIM_SubsetFlag_LineInfo) ProfScope("main unit line table conversion") { RDIM_LineTable *line_table = 0; for(CV_C13SubSectionNode *node = src_unit_c13->first_sub_section; node != 0; node = node->next) { if(node->kind == CV_C13SubSectionKind_Lines) { for(CV_C13LinesParsedNode *lines_n = node->lines_first; lines_n != 0; lines_n = lines_n->next) { CV_C13LinesParsed *lines = &lines_n->v; // rjf: file name -> sanitized file path String8 file_path = lines->file_name; String8 file_path_sanitized = str8_copy(scratch.arena, str8_skip_chop_whitespace(file_path)); { PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); String8List file_path_sanitized_parts = str8_split_path(scratch.arena, file_path_sanitized); if(file_path_sanitized_style == PathStyle_Relative) { String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); file_path_sanitized_parts = obj_folder_path_parts; file_path_sanitized_style = path_style_from_str8(obj_folder_path); } str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); file_path_sanitized = str8_path_list_join_by_style(scratch.arena, &file_path_sanitized_parts, file_path_sanitized_style); } // rjf: sanitized file path -> source file node U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); U64 src_file_slot = file_path_sanitized_hash%src_file_map->slots_count; P2R_SrcFileNode *src_file_node = 0; if(lines->line_count != 0) { for(P2R_SrcFileNode *n = src_file_map->slots[src_file_slot]; n != 0; n = n->next) { if(str8_match(n->src_file->path, file_path_sanitized, 0)) { src_file_node = n; break; } } } // rjf: push sequence into both line table & source file's line map if(src_file_node != 0) { if(line_table == 0) { line_table = rdim_line_table_chunk_list_push(arena, dst_line_tables, 256); } RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, dst_line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); } } } } // rjf: fill unit if(dst_unit != 0) { dst_unit->unit_name = unit_name; dst_unit->compiler_name = src_unit_sym->info.compiler_name; dst_unit->object_file = obj_name; dst_unit->archive_file = src_unit->group_name; dst_unit->language = p2r_rdi_language_from_cv_language(src_unit_sym->info.language); dst_unit->line_table = line_table; dst_unit->voff_ranges = unit_ranges[unit_idx]; } } //- rjf: build per-inline-site line tables if(params->subset_flags & RDIM_SubsetFlag_InlineLineInfo) ProfScope("build per-inline-site line tables") { CV_RecRange *rec_ranges_first = src_unit_sym->sym_ranges.ranges; CV_RecRange *rec_ranges_opl = src_unit_sym->sym_ranges.ranges + src_unit_sym->sym_ranges.count; U64 base_voff = 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) { //- rjf: rec range -> symbol info range U64 sym_off_first = rec_range->off + 2; U64 sym_off_opl = rec_range->off + rec_range->hdr.size; //- rjf: skip invalid ranges if(sym_off_opl > src_unit_sym->data.size || sym_off_first > src_unit_sym->data.size || sym_off_first > sym_off_opl) { continue; } //- rjf: unpack symbol info CV_SymKind kind = rec_range->hdr.kind; U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); void *sym_header_struct_base = src_unit_sym->data.str + sym_off_first; void *sym_data_opl = src_unit_sym->data.str + sym_off_opl; //- rjf: skip bad sizes if(sym_off_first + sym_header_struct_size > sym_off_opl) { continue; } //- rjf: process symbol switch(kind) { default:{}break; //- rjf: LPROC32/GPROC32 (gather base address) case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= coff_sections.count) ? &coff_sections.v[proc32->sec-1] : 0; if(section != 0) { base_voff = section->voff + proc32->off; } }break; //- rjf: INLINESITE case CV_SymKind_INLINESITE: { // rjf: unpack sym CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); // rjf: map inlinee -> parsed cv c13 inlinee line info CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; { U64 hash = cv_hash_from_item_id(sym->inlinee); U64 slot_idx = hash%src_unit_c13->inlinee_lines_parsed_slots_count; for(CV_C13InlineeLinesParsedNode *n = src_unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) { if(n->v.inlinee == sym->inlinee) { inlinee_lines_parsed = &n->v; break; } } } // rjf: build line table, fill with parsed binary annotations if(inlinee_lines_parsed != 0) { // rjf: grab checksums sub-section CV_C13SubSectionNode *file_chksms = src_unit_c13->file_chksms_sub_section; // rjf: gathered lines typedef struct LineChunk LineChunk; struct LineChunk { LineChunk *next; U64 cap; U64 count; U64 *voffs; // [line_count + 1] (sorted) U32 *line_nums; // [line_count] U16 *col_nums; // [2*line_count] }; LineChunk *first_line_chunk = 0; LineChunk *last_line_chunk = 0; U64 total_line_chunk_line_count = 0; U32 last_file_off = max_U32; U32 curr_file_off = max_U32; RDIM_LineTable* line_table = 0; CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); for(;;) { // rjf: step & update CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) { last_file_off = curr_file_off; curr_file_off = step.file_off; } if(step.flags == 0 && total_line_chunk_line_count > 0) { last_file_off = curr_file_off; curr_file_off = max_U32; } // rjf: file updated -> push line chunks gathered for this file if(last_file_off != max_U32 && last_file_off != curr_file_off) { String8 seq_file_name = {0}; if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { CV_C13Checksum *checksum = (CV_C13Checksum*)(src_unit_c13->data.str + file_chksms->off + last_file_off); U32 name_off = checksum->name_off; seq_file_name = pdb_strtbl_string_from_off(strtbl, name_off); } // rjf: file name -> sanitized file path String8 file_path = seq_file_name; String8 file_path_sanitized = str8_copy(scratch.arena, str8_skip_chop_whitespace(file_path)); { PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized); String8List file_path_sanitized_parts = str8_split_path(scratch.arena, file_path_sanitized); if(file_path_sanitized_style == PathStyle_Relative) { String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts); file_path_sanitized_parts = obj_folder_path_parts; file_path_sanitized_style = path_style_from_str8(obj_folder_path); } str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style); file_path_sanitized = str8_path_list_join_by_style(scratch.arena, &file_path_sanitized_parts, file_path_sanitized_style); } // rjf: sanitized file path -> source file node U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size); U64 src_file_slot = file_path_sanitized_hash%src_file_map->slots_count; P2R_SrcFileNode *src_file_node = 0; for(P2R_SrcFileNode *n = src_file_map->slots[src_file_slot]; n != 0; n = n->next) { if(str8_match(n->src_file->path, file_path_sanitized, 0)) { src_file_node = n; break; } } // rjf: gather all lines RDI_U64 *voffs = 0; RDI_U32 *line_nums = 0; RDI_U64 line_count = 0; if(src_file_node != 0) { voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); line_count = total_line_chunk_line_count; U64 dst_idx = 0; for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) { MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*(chunk->count+1)); MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); dst_idx += chunk->count; } } // rjf: push if(line_count != 0) { if(line_table == 0) { line_table = rdim_line_table_chunk_list_push(arena, dst_line_tables, 256); if(units_first_inline_site_line_tables[unit_idx] == 0) { units_first_inline_site_line_tables[unit_idx] = line_table; } } rdim_line_table_push_sequence(arena, dst_line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); } // rjf: clear line chunks for subsequent sequences first_line_chunk = last_line_chunk = 0; total_line_chunk_line_count = 0; } // rjf: new line -> emit to chunk if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) { LineChunk *chunk = last_line_chunk; if(chunk == 0 || chunk->count+1 >= chunk->cap) { chunk = push_array(scratch.arena, LineChunk, 1); SLLQueuePush(first_line_chunk, last_line_chunk, chunk); chunk->cap = 8; chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); } chunk->voffs[chunk->count] = step.line_voff; chunk->voffs[chunk->count+1] = step.line_voff_end; chunk->line_nums[chunk->count] = step.ln; chunk->count += 1; total_line_chunk_line_count += 1; } // rjf: no more flags -> done if(step.flags == 0) { break; } } } }break; } } } scratch_end(scratch); } } } lane_sync(); RDIM_UnitChunkList all_units = *all_units_ptr; ////////////////////////////////////////////////////////////// //- rjf: join all line tables // RDIM_LineTableChunkList all_line_tables = {0}; RDIM_LineTableChunkList *all_line_tables_ptr = &all_line_tables; ProfScope("join all line tables") if(lane_idx() == 0) { for EachIndex(idx, comp_units->count) { rdim_line_table_chunk_list_concat_in_place(&all_line_tables, &units_line_tables[idx]); } } lane_sync_u64(&all_line_tables_ptr, 0); all_line_tables = *all_line_tables_ptr; ////////////////////////////////////////////////////////////// //- rjf: equip source files with line sequences // ProfScope("equip source files with line sequences") if(lane_idx() == 0) { for(RDIM_LineTableChunkNode *line_table_chunk_n = all_line_tables.first; line_table_chunk_n != 0; line_table_chunk_n = line_table_chunk_n->next) { for EachIndex(chunk_line_table_idx, line_table_chunk_n->count) { RDIM_LineTable *line_table = &line_table_chunk_n->v[chunk_line_table_idx]; for(RDIM_LineSequenceNode *s = line_table->first_seq; s != 0; s = s->next) { rdim_src_file_push_line_sequence(arena, all_src_files__sequenceless, s->v.src_file, &s->v); } } } } lane_sync(); RDIM_SrcFileChunkList all_src_files = *all_src_files__sequenceless; ////////////////////////////////////////////////////////////// //- rjf: types pass 1: produce type forward resolution map // // this map is used to resolve usage of "incomplete structs" in codeview's // type info. this often happens when e.g. "struct Foo" is used to refer to // a later-defined "Foo", which actually contains members and so on. we want // to hook types up to their actual destination complete types wherever // possible, and so this map can be used to do that in subsequent stages. // CV_TypeId *itype_fwd_map = 0; CV_TypeId itype_first = 0; CV_TypeId itype_opl = 0; ProfScope("types pass 1: produce type forward resolution map") { //- rjf: allocate forward resolution map if(lane_idx() == 0) { itype_first = tpi_leaf->itype_first; itype_opl = tpi_leaf->itype_opl; itype_fwd_map = push_array(scratch.arena, CV_TypeId, (U64)itype_opl); } lane_sync_u64(&itype_first, 0); lane_sync_u64(&itype_opl, 0); lane_sync_u64(&itype_fwd_map, 0); //- rjf: do wide fill if(params->subset_flags & RDIM_SubsetFlag_Types) { Rng1U64 range = lane_range(itype_opl); for EachInRange(idx, range) { CV_TypeId itype = (CV_TypeId)idx; if(itype < itype_first) { continue; } //- rjf: determine if this itype resolves to another CV_TypeId itype_fwd = 0; CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-tpi_leaf->itype_first]; CV_LeafKind kind = range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); if(range->off+range->hdr.size <= tpi_leaf->data.size && range->off+2+header_struct_size <= tpi_leaf->data.size && range->hdr.size >= 2) { U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; switch(kind) { default:{}break; //- rjf: CLASS/STRUCTURE case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { // rjf: unpack leaf header CV_LeafStruct *lf_struct = (CV_LeafStruct *)itype_leaf_first; // rjf: has fwd ref flag -> lookup itype that this itype resolves to if(lf_struct->props & CV_TypeProp_FwdRef) { // rjf: unpack rest of leaf U8 *numeric_ptr = (U8 *)(lf_struct + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); // rjf: lookup B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); } }break; //- rjf: CLASS2/STRUCT2 case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { // rjf: unpack leaf header CV_LeafStruct2 *lf_struct = (CV_LeafStruct2 *)itype_leaf_first; // rjf: has fwd ref flag -> lookup itype that this itype resolves to if(lf_struct->props & CV_TypeProp_FwdRef) { // rjf: unpack rest of leaf U8 *numeric_ptr = (U8 *)(lf_struct + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U8 *name_ptr = (U8 *)numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); // rjf: lookup B32 do_unique_name_lookup = (((lf_struct->props & CV_TypeProp_Scoped) != 0) && ((lf_struct->props & CV_TypeProp_HasUniqueName) != 0)); itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); } }break; //- rjf: UNION case CV_LeafKind_UNION: { // rjf: unpack leaf CV_LeafUnion *lf_union = (CV_LeafUnion *)itype_leaf_first; U8 *numeric_ptr = (U8 *)(lf_union + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); // rjf: has fwd ref flag -> lookup itype that this itype resolves tos if(lf_union->props & CV_TypeProp_FwdRef) { B32 do_unique_name_lookup = (((lf_union->props & CV_TypeProp_Scoped) != 0) && ((lf_union->props & CV_TypeProp_HasUniqueName) != 0)); itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); } }break; //- rjf: ENUM case CV_LeafKind_ENUM: { // rjf: unpack leaf CV_LeafEnum *lf_enum = (CV_LeafEnum*)itype_leaf_first; U8 *name_ptr = (U8 *)(lf_enum + 1); String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); U8 *unique_name_ptr = name_ptr + name.size + 1; String8 unique_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); // rjf: has fwd ref flag -> lookup itype that this itype resolves to if(lf_enum->props & CV_TypeProp_FwdRef) { B32 do_unique_name_lookup = (((lf_enum->props & CV_TypeProp_Scoped) != 0) && ((lf_enum->props & CV_TypeProp_HasUniqueName) != 0)); itype_fwd = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, do_unique_name_lookup?unique_name:name, do_unique_name_lookup); } }break; } } //- rjf: if the forwarded itype is nonzero & in TPI range -> save to map if(itype_fwd != 0 && itype_fwd < tpi_leaf->itype_opl) { itype_fwd_map[itype] = itype_fwd; } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: types pass 2: produce per-itype itype chain // // this pass is to ensure that subsequent passes always produce types for // dependent itypes first - guaranteeing rdi's "only reference backward" // rule (which eliminates cycles). each itype slot gets a list of itypes, // starting with the deepest dependency - when types are produced per-itype, // this chain is walked, so that deeper dependencies are built first, and // as such, always show up *earlier* in the actually built types. // P2R_TypeIdChain **itype_chains = 0; ProfScope("types pass 2: produce per-itype itype chain (for producing dependent types first)") { //- rjf: allocate itype chain table if(lane_idx() == 0) { itype_chains = push_array(scratch.arena, P2R_TypeIdChain *, (U64)itype_opl); } lane_sync_u64(&itype_chains, 0); //- rjf: do wide fill if(params->subset_flags & RDIM_SubsetFlag_Types) { Rng1U64 range = lane_range(itype_opl); for EachInRange(idx, range) { CV_TypeId itype = (CV_TypeId)idx; //- rjf: push initial itype - should be final-visited-itype for this itype { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = itype; SLLStackPush(itype_chains[itype], c); } //- rjf: skip basic types for dependency walk if(itype < tpi_leaf->itype_first) { continue; } //- rjf: walk dependent types, push to chain Temp scratch2 = scratch_begin(&scratch.arena, 1); P2R_TypeIdChain start_walk_task = {0, itype}; P2R_TypeIdChain *first_walk_task = &start_walk_task; P2R_TypeIdChain *last_walk_task = &start_walk_task; for(P2R_TypeIdChain *walk_task = first_walk_task; walk_task != 0; walk_task = walk_task->next) { CV_TypeId walk_itype = itype_fwd_map[walk_task->itype] ? itype_fwd_map[walk_task->itype] : walk_task->itype; if(walk_itype < tpi_leaf->itype_first) { continue; } CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[walk_itype-tpi_leaf->itype_first]; CV_LeafKind kind = range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); if(range->off+range->hdr.size <= tpi_leaf->data.size && range->off+2+header_struct_size <= tpi_leaf->data.size && range->hdr.size >= 2) { U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; switch(kind) { default:{}break; //- rjf: MODIFIER case CV_LeafKind_MODIFIER: { CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; // rjf: push dependent itype to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itype { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: POINTER case CV_LeafKind_POINTER: { CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; // rjf: push dependent itype to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itype { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: PROCEDURE case CV_LeafKind_PROCEDURE: { CV_LeafProcedure *lf = (CV_LeafProcedure *)itype_leaf_first; // rjf: push return itypes to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->ret_itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk return itype { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->ret_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } // rjf: unpack arglist range CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-tpi_leaf->itype_first]; if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || arglist_range->hdr.size<2 || arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) { break; } U8 *arglist_first = tpi_leaf->data.str + arglist_range->off + 2; U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) { break; } // rjf: unpack arglist info CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); U32 arglist_itypes_count = arglist->count; // rjf: push arg types to chain for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = arglist_itypes_base[idx]; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk arg types for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = arglist_itypes_base[idx]; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: MFUNCTION case CV_LeafKind_MFUNCTION: { CV_LeafMFunction *lf = (CV_LeafMFunction *)itype_leaf_first; // rjf: push dependent itypes to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->ret_itype; SLLStackPush(itype_chains[itype], c); } { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->arg_itype; SLLStackPush(itype_chains[itype], c); } { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->this_itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itypes { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->ret_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->arg_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->this_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } // rjf: unpack arglist range CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-tpi_leaf->itype_first]; if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || arglist_range->hdr.size<2 || arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) { break; } U8 *arglist_first = tpi_leaf->data.str + arglist_range->off + 2; U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) { break; } // rjf: unpack arglist info CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); U32 arglist_itypes_count = arglist->count; // rjf: push arg types to chain for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = arglist_itypes_base[idx]; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk arg types for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = arglist_itypes_base[idx]; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: BITFIELD case CV_LeafKind_BITFIELD: { CV_LeafBitField *lf = (CV_LeafBitField *)itype_leaf_first; // rjf: push dependent itype to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itype { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->itype; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: ARRAY case CV_LeafKind_ARRAY: { CV_LeafArray *lf = (CV_LeafArray *)itype_leaf_first; // rjf: push dependent itypes to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->entry_itype; SLLStackPush(itype_chains[itype], c); } { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->index_itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itypes { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->entry_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->index_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; //- rjf: ENUM case CV_LeafKind_ENUM: { CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; // rjf: push dependent itypes to chain { P2R_TypeIdChain *c = push_array(scratch.arena, P2R_TypeIdChain, 1); c->itype = lf->base_itype; SLLStackPush(itype_chains[itype], c); } // rjf: push task to walk dependency itypes { P2R_TypeIdChain *c = push_array(scratch2.arena, P2R_TypeIdChain, 1); c->itype = lf->base_itype; SLLQueuePush(first_walk_task, last_walk_task, c); } }break; } } } scratch_end(scratch2); } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: types pass 3: construct all types from TPI // // this doesn't gather struct/class/union/enum members, which is done by // subsequent passes, to build RDI "UDT" information, which is distinct // from regular type info. // RDIM_TypeChunkList all_types__pre_typedefs = {0}; RDIM_TypeChunkList *all_types__pre_typedefs_ptr = &all_types__pre_typedefs; RDIM_Type **itype_type_ptrs = 0; RDIM_Type **basic_type_ptrs = 0; if(lane_idx() == 0) ProfScope("types pass 3: construct all root/stub types from TPI") { #define p2r_builtin_type_ptr_from_kind(kind) ((basic_type_ptrs && RDI_TypeKind_FirstBuiltIn <= (kind) && (kind) <= RDI_TypeKind_LastBuiltIn) ? (basic_type_ptrs[(kind) - RDI_TypeKind_FirstBuiltIn]) : 0) #define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0) itype_type_ptrs = push_array(scratch.arena, RDIM_Type *, (U64)(itype_opl)); basic_type_ptrs = push_array(scratch.arena, RDIM_Type *, (RDI_TypeKind_LastBuiltIn - RDI_TypeKind_FirstBuiltIn + 1)); //////////////////////////// //- rjf: build basic types // if(params->subset_flags & RDIM_SubsetFlag_Types) { for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1) { RDIM_Type *type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, 512); type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size); type->kind = type_kind; type->byte_size = rdi_size_from_basic_type_kind(type_kind); basic_type_ptrs[type_kind - RDI_TypeKind_FirstBuiltIn] = type; } } //////////////////////////// //- rjf: build basic type aliases // if(params->subset_flags & RDIM_SubsetFlag_Types) { RDIM_DataModel data_model = rdim_data_model_from_os_arch(OperatingSystem_Windows, arch); RDI_TypeKind short_type = rdim_short_type_kind_from_data_model(data_model); RDI_TypeKind ushort_type = rdim_unsigned_short_type_kind_from_data_model(data_model); RDI_TypeKind long_type = rdim_long_type_kind_from_data_model(data_model); RDI_TypeKind ulong_type = rdim_unsigned_long_type_kind_from_data_model(data_model); RDI_TypeKind long_long_type = rdim_long_long_type_kind_from_data_model(data_model); RDI_TypeKind ulong_long_type = rdim_unsigned_long_long_type_kind_from_data_model(data_model); RDI_TypeKind ptr_type = rdim_pointer_size_t_type_kind_from_data_model(data_model); struct { char * name; RDI_TypeKind kind_rdi; CV_LeafKind kind_cv; } table[] = { { "signed char" , RDI_TypeKind_Char8 , CV_BasicType_CHAR }, { "short" , short_type , CV_BasicType_SHORT }, { "long" , long_type , CV_BasicType_LONG }, { "long long" , long_long_type , CV_BasicType_QUAD }, { "__int128" , RDI_TypeKind_S128 , CV_BasicType_OCT }, // Clang type { "unsigned char" , RDI_TypeKind_UChar8 , CV_BasicType_UCHAR }, { "unsigned short" , ushort_type , CV_BasicType_USHORT }, { "unsigned long" , ulong_type , CV_BasicType_ULONG }, { "unsigned long long" , ulong_long_type , CV_BasicType_UQUAD }, { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UOCT }, // Clang type { "bool" , RDI_TypeKind_S8 , CV_BasicType_BOOL8 }, { "__bool16" , RDI_TypeKind_S16 , CV_BasicType_BOOL16 }, // not real C type { "__bool32" , RDI_TypeKind_S32 , CV_BasicType_BOOL32 }, // not real C type { "float" , RDI_TypeKind_F32 , CV_BasicType_FLOAT32 }, { "double" , RDI_TypeKind_F64 , CV_BasicType_FLOAT64 }, { "long double" , RDI_TypeKind_F80 , CV_BasicType_FLOAT80 }, { "__float128" , RDI_TypeKind_F128 , CV_BasicType_FLOAT128 }, // Clang type { "__float48" , RDI_TypeKind_F48 , CV_BasicType_FLOAT48 }, // not real C type { "__float32pp" , RDI_TypeKind_F32PP , CV_BasicType_FLOAT32PP }, // not real C type { "__float16" , RDI_TypeKind_F16 , CV_BasicType_FLOAT16 }, { "_Complex float" , RDI_TypeKind_ComplexF32 , CV_BasicType_COMPLEX32 }, { "_Complex double" , RDI_TypeKind_ComplexF64 , CV_BasicType_COMPLEX64 }, { "_Complex long double" , RDI_TypeKind_ComplexF80 , CV_BasicType_COMPLEX80 }, { "_Complex __float128" , RDI_TypeKind_ComplexF128, CV_BasicType_COMPLEX128 }, { "__int8" , RDI_TypeKind_S8 , CV_BasicType_INT8 }, { "__uint8" , RDI_TypeKind_U8 , CV_BasicType_UINT8 }, { "__int16" , RDI_TypeKind_S16 , CV_BasicType_INT16 }, { "__uint16" , RDI_TypeKind_U16 , CV_BasicType_UINT16 }, { "int" , RDI_TypeKind_S32 , CV_BasicType_INT32 }, { "int32" , RDI_TypeKind_S32 , CV_BasicType_INT32 }, { "uint32" , RDI_TypeKind_U32 , CV_BasicType_UINT32 }, { "__int64" , RDI_TypeKind_S64 , CV_BasicType_INT64 }, { "__uint64" , RDI_TypeKind_U64 , CV_BasicType_UINT64 }, { "__int128" , RDI_TypeKind_S128 , CV_BasicType_INT128 }, { "__uint128" , RDI_TypeKind_U128 , CV_BasicType_UINT128 }, { "char" , RDI_TypeKind_Char8 , CV_BasicType_RCHAR }, // always ASCII { "wchar_t" , RDI_TypeKind_UChar16 , CV_BasicType_WCHAR }, // on windows always UTF-16 { "char8_t" , RDI_TypeKind_Char8 , CV_BasicType_CHAR8 }, // always UTF-8 { "char16_t" , RDI_TypeKind_Char16 , CV_BasicType_CHAR16 }, // always UTF-16 { "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 }, // always UTF-32 { "__pointer" , ptr_type , CV_BasicType_PTR } }; for EachElement(idx, table) { RDIM_Type *builtin_alias = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, tpi_leaf->itype_opl); builtin_alias->kind = RDI_TypeKind_Alias; builtin_alias->name = str8_cstring(table[idx].name); builtin_alias->direct_type = p2r_builtin_type_ptr_from_kind(table[idx].kind_rdi); builtin_alias->byte_size = rdi_size_from_basic_type_kind(table[idx].kind_rdi); itype_type_ptrs[table[idx].kind_cv] = builtin_alias; } itype_type_ptrs[CV_BasicType_HRESULT] = basic_type_ptrs[RDI_TypeKind_HResult - RDI_TypeKind_FirstBuiltIn]; itype_type_ptrs[CV_BasicType_VOID] = basic_type_ptrs[RDI_TypeKind_Void - RDI_TypeKind_FirstBuiltIn]; } //////////////////////////// //- rjf: build types from TPI // if(params->subset_flags & RDIM_SubsetFlag_Types) { for(CV_TypeId root_itype = 0; root_itype < itype_opl; root_itype += 1) { for(P2R_TypeIdChain *itype_chain = itype_chains[root_itype]; itype_chain != 0; itype_chain = itype_chain->next) { CV_TypeId itype = (root_itype != itype_chain->itype && itype_chain->itype < itype_opl && itype_fwd_map[itype_chain->itype]) ? itype_fwd_map[itype_chain->itype] : itype_chain->itype; B32 itype_is_basic = (itype < tpi->itype_first); ////////////////////////// //- rjf: skip forward-reference itypes - all future resolutions will // reference whatever this itype resolves to, and so there is no point // in filling out this slot // if(itype_fwd_map[root_itype] != 0) { continue; } ////////////////////////// //- rjf: skip already produced dependencies // if(itype_type_ptrs[itype] != 0) { continue; } ////////////////////////// //- rjf: build basic type // if(itype_is_basic) { RDIM_Type *dst_type = 0; // rjf: unpack itype CV_BasicPointerKind cv_basic_ptr_kind = CV_BasicPointerKindFromTypeId(itype); CV_BasicType cv_basic_type_code = CV_BasicTypeFromTypeId(itype); // rjf: get basic type slot, fill if unfilled RDIM_Type *basic_type = itype_type_ptrs[cv_basic_type_code]; if(basic_type == 0) { RDI_TypeKind type_kind = p2r_rdi_type_kind_from_cv_basic_type(cv_basic_type_code); U32 byte_size = rdi_size_from_basic_type_kind(type_kind); basic_type = dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); if(byte_size == 0xffffffff) { byte_size = arch_addr_size; } basic_type->kind = type_kind; basic_type->name = cv_type_name_from_basic_type(cv_basic_type_code); basic_type->byte_size = byte_size; } // rjf: nonzero ptr kind -> form ptr type to basic tpye if(cv_basic_ptr_kind != 0) { dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Ptr; dst_type->byte_size = arch_addr_size; dst_type->direct_type = basic_type; } // rjf: fill this itype's slot with the finished type itype_type_ptrs[itype] = dst_type; } ////////////////////////// //- rjf: build non-basic type // if(!itype_is_basic && itype >= itype_first) { RDIM_Type *dst_type = 0; CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-itype_first]; CV_LeafKind kind = range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); if(range->off+range->hdr.size <= tpi_leaf->data.size && range->off+2+header_struct_size <= tpi_leaf->data.size && range->hdr.size >= 2) { U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; switch(kind) { //- rjf: MODIFIER case CV_LeafKind_MODIFIER: { // rjf: unpack leaf CV_LeafModifier *lf = (CV_LeafModifier *)itype_leaf_first; // rjf: cv -> rdi flags RDI_TypeModifierFlags flags = 0; if(lf->flags & CV_ModifierFlag_Const) {flags |= RDI_TypeModifierFlag_Const;} if(lf->flags & CV_ModifierFlag_Volatile) {flags |= RDI_TypeModifierFlag_Volatile;} // rjf: fill type if(flags == 0) { dst_type = p2r_type_ptr_from_itype(lf->itype); } else { dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Modifier; dst_type->flags = flags; dst_type->direct_type = p2r_type_ptr_from_itype(lf->itype); dst_type->byte_size = dst_type->direct_type ? dst_type->direct_type->byte_size : 0; } }break; //- rjf: POINTER case CV_LeafKind_POINTER: { // TODO(rjf): if ptr_mode in {PtrMem, PtrMethod} then output a member pointer instead // rjf: unpack leaf CV_LeafPointer *lf = (CV_LeafPointer *)itype_leaf_first; RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->itype); CV_PointerKind ptr_kind = CV_PointerAttribs_Extract_Kind(lf->attribs); CV_PointerMode ptr_mode = CV_PointerAttribs_Extract_Mode(lf->attribs); U32 ptr_size = CV_PointerAttribs_Extract_Size(lf->attribs); // rjf: cv -> rdi modifier flags RDI_TypeModifierFlags modifier_flags = 0; if(lf->attribs & CV_PointerAttrib_Const) {modifier_flags |= RDI_TypeModifierFlag_Const;} if(lf->attribs & CV_PointerAttrib_Volatile) {modifier_flags |= RDI_TypeModifierFlag_Volatile;} if(lf->attribs & CV_PointerAttrib_Restricted) {modifier_flags |= RDI_TypeModifierFlag_Restrict;} // rjf: cv info -> rdi pointer type kind RDI_TypeKind type_kind = RDI_TypeKind_Ptr; { if(lf->attribs & CV_PointerAttrib_LRef) { type_kind = RDI_TypeKind_LRef; } else if(lf->attribs & CV_PointerAttrib_RRef) { type_kind = RDI_TypeKind_RRef; } if(ptr_mode == CV_PointerMode_LRef) { type_kind = RDI_TypeKind_LRef; } else if(ptr_mode == CV_PointerMode_RRef) { type_kind = RDI_TypeKind_RRef; } } // rjf: fill type if(modifier_flags != 0) { RDIM_Type *pointer_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Modifier; dst_type->flags = modifier_flags; dst_type->direct_type = pointer_type; dst_type->byte_size = arch_addr_size; pointer_type->kind = type_kind; pointer_type->byte_size = arch_addr_size; pointer_type->direct_type = direct_type; } else { dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = type_kind; dst_type->byte_size = arch_addr_size; dst_type->direct_type = direct_type; } }break; //- rjf: PROCEDURE case CV_LeafKind_PROCEDURE: { // TODO(rjf): handle call_kind & attribs // rjf: unpack leaf CV_LeafProcedure *lf = (CV_LeafProcedure *)itype_leaf_first; RDIM_Type *ret_type = p2r_type_ptr_from_itype(lf->ret_itype); // rjf: fill type's basics dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Function; dst_type->byte_size = arch_addr_size; dst_type->direct_type = ret_type; // rjf: unpack arglist range CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-itype_first]; if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || arglist_range->hdr.size<2 || arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) { break; } U8 *arglist_first = tpi_leaf->data.str + arglist_range->off + 2; U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) { break; } // rjf: unpack arglist info CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); U32 arglist_itypes_count = arglist->count; // rjf: build param type array RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count); for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { params[idx] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); } // rjf: fill dst type dst_type->count = arglist_itypes_count; dst_type->param_types = params; }break; //- rjf: MFUNCTION case CV_LeafKind_MFUNCTION: { // TODO(rjf): handle call_kind & attribs // TODO(rjf): preserve "this_adjust" // rjf: unpack leaf CV_LeafMFunction *lf = (CV_LeafMFunction *)itype_leaf_first; RDIM_Type *ret_type = p2r_type_ptr_from_itype(lf->ret_itype); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = (lf->this_itype != 0) ? RDI_TypeKind_Method : RDI_TypeKind_Function; dst_type->byte_size = arch_addr_size; dst_type->direct_type = ret_type; // rjf: unpack arglist range CV_RecRange *arglist_range = &tpi_leaf->leaf_ranges.ranges[lf->arg_itype-itype_first]; if(arglist_range->hdr.kind != CV_LeafKind_ARGLIST || arglist_range->hdr.size<2 || arglist_range->off + arglist_range->hdr.size > tpi_leaf->data.size) { break; } U8 *arglist_first = tpi_leaf->data.str + arglist_range->off + 2; U8 *arglist_opl = arglist_first+arglist_range->hdr.size-2; if(arglist_first + sizeof(CV_LeafArgList) > arglist_opl) { break; } // rjf: unpack arglist info CV_LeafArgList *arglist = (CV_LeafArgList*)arglist_first; CV_TypeId *arglist_itypes_base = (CV_TypeId *)(arglist+1); U32 arglist_itypes_count = arglist->count; // rjf: build param type array U64 num_this_extras = 1; if(lf->this_itype == 0) { num_this_extras = 0; } RDIM_Type **params = push_array(arena, RDIM_Type *, arglist_itypes_count+num_this_extras); for(U32 idx = 0; idx < arglist_itypes_count; idx += 1) { params[idx+num_this_extras] = p2r_type_ptr_from_itype(arglist_itypes_base[idx]); } if(lf->this_itype != 0) { params[0] = p2r_type_ptr_from_itype(lf->this_itype); } // rjf: fill dst type dst_type->count = arglist_itypes_count+num_this_extras; dst_type->param_types = params; }break; //- rjf: BITFIELD case CV_LeafKind_BITFIELD: { // rjf: unpack leaf CV_LeafBitField *lf = (CV_LeafBitField *)itype_leaf_first; RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->itype); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Bitfield; dst_type->off = lf->pos; dst_type->count = lf->len; dst_type->byte_size = direct_type?direct_type->byte_size:0; dst_type->direct_type = direct_type; }break; //- rjf: ARRAY case CV_LeafKind_ARRAY: { // rjf: unpack leaf CV_LeafArray *lf = (CV_LeafArray *)itype_leaf_first; RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->entry_itype); U8 *numeric_ptr = (U8*)(lf + 1); CV_NumericParsed array_count = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U64 full_size = cv_u64_from_numeric(&array_count); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); dst_type->kind = RDI_TypeKind_Array; dst_type->direct_type = direct_type; dst_type->byte_size = full_size; dst_type->count = (direct_type && direct_type->byte_size) ? (dst_type->byte_size/direct_type->byte_size) : 0; }break; //- rjf: CLASS/STRUCTURE case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { // TODO(rjf): handle props // rjf: unpack leaf CV_LeafStruct *lf = (CV_LeafStruct *)itype_leaf_first; U8 *numeric_ptr = (U8*)(lf + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U64 size_u64 = cv_u64_from_numeric(&size); U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); if(lf->props & CV_TypeProp_FwdRef) { dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); dst_type->name = name; } else { dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct); dst_type->byte_size = (U32)size_u64; dst_type->name = name; } }break; //- rjf: CLASS2/STRUCT2 case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { // TODO(rjf): handle props // rjf: unpack leaf CV_LeafStruct2 *lf = (CV_LeafStruct2 *)itype_leaf_first; U8 *numeric_ptr = (U8*)(lf + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U64 size_u64 = cv_u64_from_numeric(&size); U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); if(lf->props & CV_TypeProp_FwdRef) { dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_IncompleteClass : RDI_TypeKind_IncompleteStruct); dst_type->name = name; } else { dst_type->kind = (kind == CV_LeafKind_CLASS2 ? RDI_TypeKind_Class : RDI_TypeKind_Struct); dst_type->byte_size = (U32)size_u64; dst_type->name = name; } }break; //- rjf: UNION case CV_LeafKind_UNION: { // TODO(rjf): handle props // rjf: unpack leaf CV_LeafUnion *lf = (CV_LeafUnion *)itype_leaf_first; U8 *numeric_ptr = (U8*)(lf + 1); CV_NumericParsed size = cv_numeric_from_data_range(numeric_ptr, itype_leaf_opl); U64 size_u64 = cv_u64_from_numeric(&size); U8 *name_ptr = numeric_ptr + size.encoded_size; String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); if(lf->props & CV_TypeProp_FwdRef) { dst_type->kind = RDI_TypeKind_IncompleteUnion; dst_type->name = name; } else { dst_type->kind = RDI_TypeKind_Union; dst_type->byte_size = (U32)size_u64; dst_type->name = name; } }break; //- rjf: ENUM case CV_LeafKind_ENUM: { // TODO(rjf): handle props // rjf: unpack leaf CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; RDIM_Type *direct_type = p2r_type_ptr_from_itype(lf->base_itype); U8 *name_ptr = (U8 *)(lf + 1); String8 name = str8_cstring_capped(name_ptr, itype_leaf_opl); // rjf: fill type dst_type = rdim_type_chunk_list_push(arena, all_types__pre_typedefs_ptr, (U64)itype_opl); if(lf->props & CV_TypeProp_FwdRef) { dst_type->kind = RDI_TypeKind_IncompleteEnum; dst_type->name = name; } else { dst_type->kind = RDI_TypeKind_Enum; dst_type->direct_type = direct_type; dst_type->byte_size = direct_type ? direct_type->byte_size : 0; dst_type->name = name; } }break; } } //- rjf: store finalized type to this itype's slot itype_type_ptrs[itype] = dst_type; } } } } #undef p2r_type_ptr_from_itype #undef p2r_builtin_type_ptr_from_kind } lane_sync_u64(&itype_type_ptrs, 0); lane_sync_u64(&basic_type_ptrs, 0); lane_sync_u64(&all_types__pre_typedefs_ptr, 0); all_types__pre_typedefs = *all_types__pre_typedefs_ptr; ////////////////////////////////////////////////////////////// //- rjf: types pass 4: build UDTs // RDIM_UDTChunkList *lanes_udts = 0; ProfScope("types pass 4: build UDTs") { #define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < tpi_leaf->itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0) //- rjf: gather this lane's UDTs RDIM_UDTChunkList lane_udts = {0}; if(params->subset_flags & RDIM_SubsetFlag_Types && params->subset_flags & RDIM_SubsetFlag_UDTs) { U64 udts_chunk_cap = 4096; RDIM_UDTChunkList *udts = &lane_udts; Rng1U64 range = lane_range(itype_opl); for EachInRange(idx, range) { //- rjf: skip basics CV_TypeId itype = (CV_TypeId)idx; if(itype < itype_first) { continue; } //- rjf: grab type for this itype - skip if empty RDIM_Type *dst_type = itype_type_ptrs[itype]; if(dst_type == 0) { continue; } //- rjf: unpack itype leaf range - skip if out-of-range CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-tpi_leaf->itype_first]; CV_LeafKind kind = range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); U8 *itype_leaf_first = tpi_leaf->data.str + range->off+2; U8 *itype_leaf_opl = itype_leaf_first + range->hdr.size-2; if(range->off+range->hdr.size > tpi_leaf->data.size || range->off+2+header_struct_size > tpi_leaf->data.size || range->hdr.size < 2) { continue; } //- rjf: build UDT CV_TypeId field_itype = 0; switch(kind) { default:{}break; //////////////////////// //- rjf: structs/unions/classes -> equip members // case CV_LeafKind_CLASS: case CV_LeafKind_STRUCTURE: { CV_LeafStruct *lf = (CV_LeafStruct *)itype_leaf_first; if(lf->props & CV_TypeProp_FwdRef) { break; } field_itype = lf->field_itype; }goto equip_members; case CV_LeafKind_UNION: { CV_LeafUnion *lf = (CV_LeafUnion *)itype_leaf_first; if(lf->props & CV_TypeProp_FwdRef) { break; } field_itype = lf->field_itype; }goto equip_members; case CV_LeafKind_CLASS2: case CV_LeafKind_STRUCT2: { CV_LeafStruct2 *lf = (CV_LeafStruct2 *)itype_leaf_first; if(lf->props & CV_TypeProp_FwdRef) { break; } field_itype = lf->field_itype; }goto equip_members; equip_members: { Temp scratch = scratch_begin(&arena, 1); //- rjf: grab UDT info RDIM_UDT *dst_udt = dst_type->udt; if(dst_udt == 0) { dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap); dst_udt->self_type = dst_type; } //- rjf: gather all fields typedef struct FieldListTask FieldListTask; struct FieldListTask { FieldListTask *next; CV_TypeId itype; }; FieldListTask start_fl_task = {0, field_itype}; FieldListTask *fl_todo_stack = &start_fl_task; FieldListTask *fl_done_stack = 0; for(;fl_todo_stack != 0;) { //- rjf: take & unpack task FieldListTask *fl_task = fl_todo_stack; SLLStackPop(fl_todo_stack); SLLStackPush(fl_done_stack, fl_task); CV_TypeId field_list_itype = fl_task->itype; //- rjf: skip bad itypes if(field_list_itype < tpi_leaf->itype_first || tpi_leaf->itype_opl <= field_list_itype) { continue; } //- rjf: field list itype -> range CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-tpi_leaf->itype_first]; //- rjf: skip bad headers if(range->off+range->hdr.size > tpi_leaf->data.size || range->hdr.size < 2 || range->hdr.kind != CV_LeafKind_FIELDLIST) { continue; } //- rjf: loop over all fields { U8 *field_list_first = tpi_leaf->data.str+range->off+2; U8 *field_list_opl = field_list_first+range->hdr.size-2; for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; read_ptr < field_list_opl; read_ptr = next_read_ptr) { // rjf: unpack field CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); U8 *field_leaf_first = read_ptr+2; U8 *field_leaf_opl = field_list_opl; next_read_ptr = field_leaf_opl; // rjf: skip out-of-bounds fields if(field_leaf_first+field_leaf_header_size > field_list_opl) { continue; } // rjf: process field switch(field_kind) { //- rjf: unhandled/invalid cases default: { // TODO(rjf): log }break; //- rjf: INDEX case CV_LeafKind_INDEX: { // rjf: unpack leaf CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; CV_TypeId new_itype = lf->itype; // rjf: bump next read pointer past header next_read_ptr = (U8 *)(lf+1); // rjf: determine if index itype is new B32 is_new = 1; for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) { if(t->itype == new_itype) { is_new = 0; break; } } // rjf: if new -> push task to follow new itype if(is_new) { FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); SLLStackPush(fl_todo_stack, new_task); new_task->itype = new_itype; } }break; //- rjf: MEMBER case CV_LeafKind_MEMBER: { // TODO(rjf): log on bad offset // rjf: unpack leaf CV_LeafMember *lf = (CV_LeafMember *)field_leaf_first; U8 *offset_ptr = (U8 *)(lf+1); CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); U64 offset64 = cv_u64_from_numeric(&offset); U8 *name_ptr = offset_ptr + offset.encoded_size; String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_DataField; mem->name = name; mem->type = p2r_type_ptr_from_itype(lf->itype); mem->off = (U32)offset64; }break; //- rjf: STMEMBER case CV_LeafKind_STMEMBER: { // TODO(rjf): handle attribs // rjf: unpack leaf CV_LeafStMember *lf = (CV_LeafStMember *)field_leaf_first; U8 *name_ptr = (U8 *)(lf+1); String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_StaticData; mem->name = name; mem->type = p2r_type_ptr_from_itype(lf->itype); }break; //- rjf: METHOD case CV_LeafKind_METHOD: { // rjf: unpack leaf CV_LeafMethod *lf = (CV_LeafMethod *)field_leaf_first; U8 *name_ptr = (U8 *)(lf+1); String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; //- rjf: method list itype -> range CV_RecRange *method_list_range = &tpi_leaf->leaf_ranges.ranges[lf->list_itype-tpi_leaf->itype_first]; //- rjf: skip bad method lists if(method_list_range->off+method_list_range->hdr.size > tpi_leaf->data.size || method_list_range->hdr.size < 2 || method_list_range->hdr.kind != CV_LeafKind_METHODLIST) { break; } //- rjf: loop through all methods & emit members U8 *method_list_first = tpi_leaf->data.str + method_list_range->off + 2; U8 *method_list_opl = method_list_first + method_list_range->hdr.size-2; for(U8 *method_read_ptr = method_list_first, *next_method_read_ptr = method_list_opl; method_read_ptr < method_list_opl; method_read_ptr = next_method_read_ptr) { CV_LeafMethodListMember *method = (CV_LeafMethodListMember*)method_read_ptr; CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(method->attribs); RDIM_Type *method_type = p2r_type_ptr_from_itype(method->itype); next_method_read_ptr = (U8 *)(method+1); // TODO(allen): PROBLEM // We only get offsets for virtual functions (the "vbaseoff") from // "Intro" and "PureIntro". In C++ inheritance, when we have a chain // of inheritance (let's just talk single inheritance for now) the // first class in the chain that introduces a new virtual function // has this "Intro" method. If a later class in the chain redefines // the virtual function it only has a "Virtual" method which does // not update the offset. There is a "Virtual" and "PureVirtual" // variant of "Virtual". The "Pure" in either case means there // is no concrete procedure. When there is no "Pure" the method // should have a corresponding procedure symbol id. // // The issue is we will want to mark all of our virtual methods as // virtual and give them an offset, but that means we have to do // some extra figuring to propogate offsets from "Intro" methods // to "Virtual" methods in inheritance trees. That is - IF we want // to start preserving the offsets of virtuals. There is room in // the method struct to make this work, but for now I've just // decided to drop this information. It is not urgently useful to // us and greatly complicates matters. // rjf: read vbaseoff U32 vbaseoff = 0; if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { if(next_method_read_ptr+4 <= method_list_opl) { vbaseoff = *(U32 *)next_method_read_ptr; } next_method_read_ptr += 4; } // rjf: emit method switch(prop) { default: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_Method; mem->name = name; mem->type = method_type; }break; case CV_MethodProp_Static: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_StaticMethod; mem->name = name; mem->type = method_type; }break; case CV_MethodProp_Virtual: case CV_MethodProp_PureVirtual: case CV_MethodProp_Intro: case CV_MethodProp_PureIntro: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_VirtualMethod; mem->name = name; mem->type = method_type; }break; } } }break; //- rjf: ONEMETHOD case CV_LeafKind_ONEMETHOD: { // TODO(rjf): handle attribs // rjf: unpack leaf CV_LeafOneMethod *lf = (CV_LeafOneMethod *)field_leaf_first; CV_MethodProp prop = CV_FieldAttribs_Extract_MethodProp(lf->attribs); U8 *vbaseoff_ptr = (U8 *)(lf+1); U8 *vbaseoff_opl_ptr = vbaseoff_ptr; U32 vbaseoff = 0; if(prop == CV_MethodProp_Intro || prop == CV_MethodProp_PureIntro) { vbaseoff = *(U32 *)(vbaseoff_ptr); vbaseoff_opl_ptr += sizeof(U32); } U8 *name_ptr = vbaseoff_opl_ptr; String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); RDIM_Type *method_type = p2r_type_ptr_from_itype(lf->itype); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit method switch(prop) { default: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_Method; mem->name = name; mem->type = method_type; }break; case CV_MethodProp_Static: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_StaticMethod; mem->name = name; mem->type = method_type; }break; case CV_MethodProp_Virtual: case CV_MethodProp_PureVirtual: case CV_MethodProp_Intro: case CV_MethodProp_PureIntro: { RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_VirtualMethod; mem->name = name; mem->type = method_type; }break; } }break; //- rjf: NESTTYPE case CV_LeafKind_NESTTYPE: { // rjf: unpack leaf CV_LeafNestType *lf = (CV_LeafNestType *)field_leaf_first; U8 *name_ptr = (U8 *)(lf+1); String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_NestedType; mem->name = name; mem->type = p2r_type_ptr_from_itype(lf->itype); }break; //- rjf: NESTTYPEEX case CV_LeafKind_NESTTYPEEX: { // TODO(rjf): handle attribs // rjf: unpack leaf CV_LeafNestTypeEx *lf = (CV_LeafNestTypeEx *)field_leaf_first; U8 *name_ptr = (U8 *)(lf+1); String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_NestedType; mem->name = name; mem->type = p2r_type_ptr_from_itype(lf->itype); }break; //- rjf: BCLASS case CV_LeafKind_BCLASS: { // TODO(rjf): log on bad offset // rjf: unpack leaf CV_LeafBClass *lf = (CV_LeafBClass *)field_leaf_first; U8 *offset_ptr = (U8 *)(lf+1); CV_NumericParsed offset = cv_numeric_from_data_range(offset_ptr, field_leaf_opl); U64 offset64 = cv_u64_from_numeric(&offset); // rjf: bump next read pointer past variable length parts next_read_ptr = offset_ptr+offset.encoded_size; // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_Base; mem->type = p2r_type_ptr_from_itype(lf->itype); mem->off = (U32)offset64; }break; //- rjf: VBCLASS/IVBCLASS case CV_LeafKind_VBCLASS: case CV_LeafKind_IVBCLASS: { // TODO(rjf): log on bad offsets // TODO(rjf): handle attribs // TODO(rjf): offsets? // rjf: unpack leaf CV_LeafVBClass *lf = (CV_LeafVBClass *)field_leaf_first; U8 *num1_ptr = (U8 *)(lf+1); CV_NumericParsed num1 = cv_numeric_from_data_range(num1_ptr, field_leaf_opl); U8 *num2_ptr = num1_ptr + num1.encoded_size; CV_NumericParsed num2 = cv_numeric_from_data_range(num2_ptr, field_leaf_opl); // rjf: bump next read pointer past header next_read_ptr = (U8 *)(lf+1); // rjf: emit member RDIM_UDTMember *mem = rdim_udt_push_member(arena, udts, dst_udt); mem->kind = RDI_MemberKind_VirtualBase; mem->type = p2r_type_ptr_from_itype(lf->itype); }break; //- rjf: VFUNCTAB case CV_LeafKind_VFUNCTAB: { CV_LeafVFuncTab *lf = (CV_LeafVFuncTab *)field_leaf_first; // rjf: bump next read pointer past header next_read_ptr = (U8 *)(lf+1); // NOTE(rjf): currently no-op this case (void)lf; }break; } // rjf: align-up next field next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); } } } scratch_end(scratch); }break; //////////////////////// //- rjf: enums -> equip enumerates // case CV_LeafKind_ENUM: { CV_LeafEnum *lf = (CV_LeafEnum *)itype_leaf_first; if(lf->props & CV_TypeProp_FwdRef) { break; } field_itype = lf->field_itype; }goto equip_enum_vals; equip_enum_vals:; { Temp scratch = scratch_begin(&arena, 1); //- rjf: grab UDT info RDIM_UDT *dst_udt = dst_type->udt; if(dst_udt == 0) { dst_udt = dst_type->udt = rdim_udt_chunk_list_push(arena, udts, udts_chunk_cap); dst_udt->self_type = dst_type; } //- rjf: gather all fields typedef struct FieldListTask FieldListTask; struct FieldListTask { FieldListTask *next; CV_TypeId itype; }; FieldListTask start_fl_task = {0, field_itype}; FieldListTask *fl_todo_stack = &start_fl_task; FieldListTask *fl_done_stack = 0; for(;fl_todo_stack != 0;) { //- rjf: take & unpack task FieldListTask *fl_task = fl_todo_stack; SLLStackPop(fl_todo_stack); SLLStackPush(fl_done_stack, fl_task); CV_TypeId field_list_itype = fl_task->itype; //- rjf: skip bad itypes if(field_list_itype < tpi_leaf->itype_first || tpi_leaf->itype_opl <= field_list_itype) { continue; } //- rjf: field list itype -> range CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[field_list_itype-tpi_leaf->itype_first]; //- rjf: skip bad headers if(range->off+range->hdr.size > tpi_leaf->data.size || range->hdr.size < 2 || range->hdr.kind != CV_LeafKind_FIELDLIST) { continue; } //- rjf: loop over all fields { U8 *field_list_first = tpi_leaf->data.str+range->off+2; U8 *field_list_opl = field_list_first+range->hdr.size-2; for(U8 *read_ptr = field_list_first, *next_read_ptr = field_list_opl; read_ptr < field_list_opl; read_ptr = next_read_ptr) { // rjf: unpack field CV_LeafKind field_kind = *(CV_LeafKind *)read_ptr; U64 field_leaf_header_size = cv_header_struct_size_from_leaf_kind(field_kind); U8 *field_leaf_first = read_ptr+2; U8 *field_leaf_opl = field_leaf_first+range->hdr.size-2; next_read_ptr = field_leaf_opl; // rjf: skip out-of-bounds fields if(field_leaf_first+field_leaf_header_size > field_list_opl) { continue; } // rjf: process field switch(field_kind) { //- rjf: unhandled/invalid cases default: { // TODO(rjf): log }break; //- rjf: INDEX case CV_LeafKind_INDEX: { // rjf: unpack leaf CV_LeafIndex *lf = (CV_LeafIndex *)field_leaf_first; CV_TypeId new_itype = lf->itype; // rjf: determine if index itype is new B32 is_new = 1; for(FieldListTask *t = fl_done_stack; t != 0; t = t->next) { if(t->itype == new_itype) { is_new = 0; break; } } // rjf: if new -> push task to follow new itype if(is_new) { FieldListTask *new_task = push_array(scratch.arena, FieldListTask, 1); SLLStackPush(fl_todo_stack, new_task); new_task->itype = new_itype; } }break; //- rjf: ENUMERATE case CV_LeafKind_ENUMERATE: { // TODO(rjf): attribs // rjf: unpack leaf CV_LeafEnumerate *lf = (CV_LeafEnumerate *)field_leaf_first; U8 *val_ptr = (U8 *)(lf+1); CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, field_leaf_opl); U64 val64 = cv_u64_from_numeric(&val); U8 *name_ptr = val_ptr + val.encoded_size; String8 name = str8_cstring_capped(name_ptr, field_leaf_opl); // rjf: bump next read pointer past variable length parts next_read_ptr = name.str+name.size+1; // rjf: emit member RDIM_UDTEnumVal *enum_val = rdim_udt_push_enum_val(arena, udts, dst_udt); enum_val->name = name; enum_val->val = val64; }break; } // rjf: align-up next field next_read_ptr = (U8 *)AlignPow2((U64)next_read_ptr, 4); } } } scratch_end(scratch); }break; } } } //- rjf: collect all lanes if(lane_idx() == 0) { lanes_udts = push_array(scratch.arena, RDIM_UDTChunkList, lane_count()); } lane_sync_u64(&lanes_udts, 0); lanes_udts[lane_idx()] = lane_udts; #undef p2r_type_ptr_from_itype } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: join all UDTs // RDIM_UDTChunkList all_udts = {0}; ProfScope("join all UDTs") if(lane_idx() == 0) { for EachIndex(idx, lane_count()) { rdim_udt_chunk_list_concat_in_place(&all_udts, &lanes_udts[idx]); } } lane_sync(); RDIM_UDTChunkList *all_udts_ptr = &all_udts; lane_sync_u64(&all_udts_ptr, 0); all_udts = *all_udts_ptr; ////////////////////////////////////////////////////////////// //- rjf: produce symbols from all streams // RDIM_LocationChunkList *syms_locations = 0; RDIM_SymbolChunkList *syms_procedures = 0; RDIM_SymbolChunkList *syms_global_variables = 0; RDIM_SymbolChunkList *syms_thread_variables = 0; RDIM_SymbolChunkList *syms_constants = 0; RDIM_ScopeChunkList *syms_scopes = 0; RDIM_InlineSiteChunkList *syms_inline_sites = 0; RDIM_TypeChunkList *syms_typedefs = 0; ProfScope("produce symbols from all streams") { #define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0) //////////////////////////// //- rjf: set up // if(lane_idx() == 0) { syms_locations = push_array(arena, RDIM_LocationChunkList, all_syms_count); syms_procedures = push_array(arena, RDIM_SymbolChunkList, all_syms_count); syms_global_variables = push_array(arena, RDIM_SymbolChunkList, all_syms_count); syms_thread_variables = push_array(arena, RDIM_SymbolChunkList, all_syms_count); syms_constants = push_array(arena, RDIM_SymbolChunkList, all_syms_count); syms_scopes = push_array(arena, RDIM_ScopeChunkList, all_syms_count); syms_inline_sites = push_array(arena, RDIM_InlineSiteChunkList, all_syms_count); syms_typedefs = push_array(arena, RDIM_TypeChunkList, all_syms_count); } lane_sync_u64(&syms_locations, 0); lane_sync_u64(&syms_procedures, 0); lane_sync_u64(&syms_global_variables, 0); lane_sync_u64(&syms_thread_variables, 0); lane_sync_u64(&syms_constants, 0); lane_sync_u64(&syms_scopes, 0); lane_sync_u64(&syms_inline_sites, 0); lane_sync_u64(&syms_typedefs, 0); //////////////////////////// //- rjf: fill outputs for all unit sym blocks in this lane // if(params->subset_flags & (RDIM_SubsetFlag_Procedures| RDIM_SubsetFlag_GlobalVariables| RDIM_SubsetFlag_ThreadVariables| RDIM_SubsetFlag_Scopes| RDIM_SubsetFlag_Locals| RDIM_SubsetFlag_GlobalVariableNameMap| RDIM_SubsetFlag_ThreadVariableNameMap| RDIM_SubsetFlag_ProcedureNameMap| RDIM_SubsetFlag_ConstantNameMap| RDIM_SubsetFlag_LinkNameProcedureNameMap| RDIM_SubsetFlag_Types)) { U64 sym_take_counter = 0; U64 *sym_take_counter_ptr = &sym_take_counter; lane_sync_u64(&sym_take_counter_ptr, 0); for(;;) { //- rjf: take next sym U64 sym_idx = ins_atomic_u64_inc_eval(sym_take_counter_ptr) - 1; if(sym_idx >= all_syms_count) { break; } //- rjf: unpack sym Temp scratch = scratch_begin(&arena, 1); CV_SymParsed *sym = all_syms[sym_idx]; Rng1U64 sym_rec_range = r1u64(0, sym->sym_ranges.count); U64 sym_locations_chunk_cap = 4096; U64 sym_procedures_chunk_cap = 2048; U64 sym_global_variables_chunk_cap = 2048; U64 sym_thread_variables_chunk_cap = 2048; U64 sym_constants_chunk_cap = 2048; U64 sym_scopes_chunk_cap = 4096; U64 sym_inline_sites_chunk_cap = 2048; RDIM_LocationChunkList *sym_locations = &syms_locations[sym_idx]; RDIM_SymbolChunkList *sym_procedures = &syms_procedures[sym_idx]; RDIM_SymbolChunkList *sym_global_variables = &syms_global_variables[sym_idx]; RDIM_SymbolChunkList *sym_thread_variables = &syms_thread_variables[sym_idx]; RDIM_SymbolChunkList *sym_constants = &syms_constants[sym_idx]; RDIM_ScopeChunkList *sym_scopes = &syms_scopes[sym_idx]; RDIM_InlineSiteChunkList *sym_inline_sites = &syms_inline_sites[sym_idx]; RDIM_TypeChunkList *typedefs = &syms_typedefs[sym_idx]; ////////////////////////// //- rjf: symbols pass 1: produce procedure frame info map (procedure -> frame info) // U64 procedure_frameprocs_count = 0; U64 procedure_frameprocs_cap = dim_1u64(sym_rec_range); CV_SymFrameproc **procedure_frameprocs = push_array_no_zero(scratch.arena, CV_SymFrameproc *, procedure_frameprocs_cap); ProfScope("symbols pass 1: produce procedure frame info map (procedure -> frame info)") { U64 procedure_num = 0; CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges + sym_rec_range.min; CV_RecRange *rec_ranges_opl = sym->sym_ranges.ranges + sym_rec_range.max; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) { //- rjf: rec range -> symbol info range U64 sym_off_first = rec_range->off + 2; U64 sym_off_opl = rec_range->off + rec_range->hdr.size; //- rjf: skip invalid ranges if(sym_off_opl > sym->data.size || sym_off_first > sym->data.size || sym_off_first > sym_off_opl) { continue; } //- rjf: unpack symbol info CV_SymKind kind = rec_range->hdr.kind; U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); void *sym_header_struct_base = sym->data.str + sym_off_first; //- rjf: skip bad sizes if(sym_off_first + sym_header_struct_size > sym_off_opl) { continue; } //- rjf: consume symbol based on kind switch(kind) { default:{}break; //- rjf: FRAMEPROC case CV_SymKind_FRAMEPROC: { if(procedure_num == 0) { break; } if(procedure_num > procedure_frameprocs_cap) { break; } CV_SymFrameproc *frameproc = (CV_SymFrameproc*)sym_header_struct_base; procedure_frameprocs[procedure_num-1] = frameproc; procedure_frameprocs_count = Max(procedure_frameprocs_count, procedure_num); }break; //- rjf: LPROC32/GPROC32 case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { procedure_num += 1; }break; } } U64 scratch_overkill = sizeof(procedure_frameprocs[0])*(procedure_frameprocs_cap-procedure_frameprocs_count); arena_pop(scratch.arena, scratch_overkill); } ////////////////////////// //- rjf: symbols pass 2: construct all symbols, given procedure frame info map // ProfScope("symbols pass 2: construct all symbols, given procedure frame info map") { RDIM_Local *defrange_target = 0; B32 defrange_target_is_param = 0; U64 procedure_num = 0; U64 procedure_base_voff = 0; CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges + sym_rec_range.min; CV_RecRange *rec_ranges_opl = sym->sym_ranges.ranges + sym_rec_range.max; typedef struct P2R_ScopeNode P2R_ScopeNode; struct P2R_ScopeNode { P2R_ScopeNode *next; RDIM_Scope *scope; }; P2R_ScopeNode *top_scope_node = 0; P2R_ScopeNode *free_scope_node = 0; RDIM_LineTable *inline_site_line_table = sym_idx > 0 ? units_first_inline_site_line_tables[sym_idx-1] : 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) { //- rjf: rec range -> symbol info range U64 sym_off_first = rec_range->off + 2; U64 sym_off_opl = rec_range->off + rec_range->hdr.size; //- rjf: skip invalid ranges if(sym_off_opl > sym->data.size || sym_off_first > sym->data.size || sym_off_first > sym_off_opl) { continue; } //- rjf: unpack symbol info CV_SymKind kind = rec_range->hdr.kind; U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); void *sym_header_struct_base = sym->data.str + sym_off_first; void *sym_data_opl = sym->data.str + sym_off_opl; //- rjf: skip bad sizes if(sym_off_first + sym_header_struct_size > sym_off_opl) { continue; } //- rjf: consume symbol based on kind switch(kind) { default:{}break; //- rjf: END case CV_SymKind_END: { P2R_ScopeNode *n = top_scope_node; if(n != 0) { SLLStackPop(top_scope_node); SLLStackPush(free_scope_node, n); } defrange_target = 0; defrange_target_is_param = 0; }break; //- rjf: BLOCK32 case CV_SymKind_BLOCK32: { // rjf: unpack sym CV_SymBlock32 *block32 = (CV_SymBlock32 *)sym_header_struct_base; // rjf: build scope, insert into current parent scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, sym_scopes, sym_scopes_chunk_cap); { if(top_scope_node == 0) { // TODO(rjf): log } if(top_scope_node != 0) { RDIM_Scope *top_scope = top_scope_node->scope; SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); scope->parent_scope = top_scope; scope->symbol = top_scope->symbol; } COFF_SectionHeader *section = (0 < block32->sec && block32->sec <= coff_sections.count) ? &coff_sections.v[block32->sec-1] : 0; if(section != 0) { U64 voff_first = section->voff + block32->off; U64 voff_last = voff_first + block32->len; RDIM_Rng1U64 voff_range = {voff_first, voff_last}; rdim_scope_push_voff_range(arena, sym_scopes, scope, voff_range); } } // rjf: push this scope to scope stack { P2R_ScopeNode *node = free_scope_node; if(node != 0) { SLLStackPop(free_scope_node); } else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } node->scope = scope; SLLStackPush(top_scope_node, node); } }break; //- rjf: LDATA32/GDATA32 case CV_SymKind_LDATA32: case CV_SymKind_GDATA32: { // rjf: unpack sym CV_SymData32 *data32 = (CV_SymData32 *)sym_header_struct_base; String8 name = str8_cstring_capped(data32+1, sym_data_opl); COFF_SectionHeader *section = (0 < data32->sec && data32->sec <= coff_sections.count) ? &coff_sections.v[data32->sec-1] : 0; U64 voff = (section ? section->voff : 0) + data32->off; // rjf: determine if this is an exact duplicate global // // PDB likes to have duplicates of these spread across different // symbol streams so we deduplicate across the entire translation // context. // B32 is_duplicate = 0; { // TODO(rjf): @important global symbol dedup } // rjf: is not duplicate -> push new global if(!is_duplicate) { // rjf: unpack global variable's type RDIM_Type *type = p2r_type_ptr_from_itype(data32->itype); // rjf: unpack global's container type RDIM_Type *container_type = 0; U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); if(container_name_opl > 2) { String8 container_name = str8(name.str, container_name_opl - 2); CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, container_name, 0); container_type = p2r_type_ptr_from_itype(cv_type_id); } // rjf: unpack global's container symbol RDIM_Symbol *container_symbol = 0; if(container_type == 0 && top_scope_node != 0) { container_symbol = top_scope_node->scope->symbol; } // rjf: build symbol RDIM_Symbol *symbol = rdim_symbol_chunk_list_push(arena, sym_global_variables, sym_global_variables_chunk_cap); symbol->is_extern = (kind == CV_SymKind_GDATA32); symbol->name = name; symbol->type = type; symbol->offset = voff; symbol->container_symbol = container_symbol; symbol->container_type = container_type; } }break; //- rjf: UDT (typedefs) case CV_SymKind_UDT: if(sym == all_syms[0] && top_scope_node == 0) { if(params->subset_flags & (RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs|RDIM_SubsetFlag_TypeNameMap)) { CV_SymUDT *udt = (CV_SymUDT *)sym_header_struct_base; String8 name = str8_cstring_capped(udt+1, sym_data_opl); RDIM_Type *type = rdim_type_chunk_list_push(arena, typedefs, 4096); type->kind = RDI_TypeKind_Alias; type->name = name; type->direct_type = p2r_type_ptr_from_itype(udt->itype); if(type->direct_type != 0) { type->byte_size = type->direct_type->byte_size; } } }break; //- rjf: LPROC32/GPROC32 case CV_SymKind_LPROC32: case CV_SymKind_GPROC32: { // rjf: unpack sym CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; String8 name = str8_cstring_capped(proc32+1, sym_data_opl); RDIM_Type *type = p2r_type_ptr_from_itype(proc32->itype); // rjf: unpack proc's container type RDIM_Type *container_type = 0; U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); if(container_name_opl > 2 && tpi_hash != 0 && tpi_leaf != 0) { String8 container_name = str8(name.str, container_name_opl - 2); CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, container_name, 0); container_type = p2r_type_ptr_from_itype(cv_type_id); } // rjf: unpack proc's container symbol RDIM_Symbol *container_symbol = 0; if(container_type == 0 && top_scope_node != 0) { container_symbol = top_scope_node->scope->symbol; } // rjf: build procedure's root scope // // NOTE: even if there could be a containing scope at this point (which should be // illegal in C/C++ but not necessarily in another language) we would not use // it here because these scopes refer to the ranges of code that make up a // procedure *not* the namespaces, so a procedure's root scope always has // no parent. RDIM_Scope *procedure_root_scope = 0; if(params->subset_flags & RDIM_SubsetFlag_Scopes) { procedure_root_scope = rdim_scope_chunk_list_push(arena, sym_scopes, sym_scopes_chunk_cap); COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= coff_sections.count) ? &coff_sections.v[proc32->sec-1] : 0; if(section != 0) { U64 voff_first = section->voff + proc32->off; U64 voff_last = voff_first + proc32->len; RDIM_Rng1U64 voff_range = {voff_first, voff_last}; rdim_scope_push_voff_range(arena, sym_scopes, procedure_root_scope, voff_range); procedure_base_voff = voff_first; } } // rjf: root scope voff minimum range -> link name String8 link_name = {0}; if(procedure_root_scope && procedure_root_scope->voff_ranges.min != 0) { U64 voff = procedure_root_scope->voff_ranges.min; U64 hash = p2r_hash_from_voff(voff); U64 bucket_idx = hash%link_name_map->buckets_count; P2R_LinkNameNode *node = 0; for(P2R_LinkNameNode *n = link_name_map->buckets[bucket_idx]; n != 0; n = n->next) { if(n->voff == voff) { link_name = n->name; break; } } } // rjf: build procedure symbol if(params->subset_flags & (RDIM_SubsetFlag_Procedures|RDIM_SubsetFlag_ProcedureNameMap)) { RDIM_Symbol *procedure_symbol = rdim_symbol_chunk_list_push(arena, sym_procedures, sym_procedures_chunk_cap); procedure_symbol->is_extern = (kind == CV_SymKind_GPROC32); procedure_symbol->name = name; procedure_symbol->link_name = link_name; procedure_symbol->type = type; procedure_symbol->container_symbol = container_symbol; procedure_symbol->container_type = container_type; procedure_symbol->root_scope = procedure_root_scope; if(procedure_root_scope != 0) { procedure_root_scope->symbol = procedure_symbol; } } // rjf: push scope to scope stack if(procedure_root_scope) { P2R_ScopeNode *node = free_scope_node; if(node != 0) { SLLStackPop(free_scope_node); } else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } node->scope = procedure_root_scope; SLLStackPush(top_scope_node, node); } // rjf: increment procedure counter procedure_num += 1; }break; //- rjf: REGREL32 case CV_SymKind_REGREL32: if(params->subset_flags & RDIM_SubsetFlag_Locals) { // TODO(rjf): apparently some of the information here may end up being // redundant with "better" information from CV_SymKind_LOCAL record. // we don't currently handle this, but if those cases arise then it // will obviously be better to prefer the better information from both // records. // rjf: no containing scope? -> malformed data; locals cannot be produced // outside of a containing scope if(top_scope_node == 0) { break; } // rjf: unpack sym CV_SymRegrel32 *regrel32 = (CV_SymRegrel32 *)sym_header_struct_base; String8 name = str8_cstring_capped(regrel32+1, sym_data_opl); RDIM_Type *type = p2r_type_ptr_from_itype(regrel32->itype); CV_Reg cv_reg = regrel32->reg; U32 var_off = regrel32->reg_off; // rjf: determine if this is a parameter RDI_LocalKind local_kind = RDI_LocalKind_Variable; { B32 is_stack_reg = 0; switch(arch) { default:{}break; case RDI_Arch_X86:{is_stack_reg = (cv_reg == CV_Regx86_ESP || cv_reg == CV_Regx86_EBP);}break; case RDI_Arch_X64:{is_stack_reg = (cv_reg == CV_Regx64_RSP || cv_reg == CV_Regx64_RBP);}break; } if(is_stack_reg) { U32 frame_size = 0xFFFFFFFF; if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num <= procedure_frameprocs_count) { CV_SymFrameproc *frameproc = procedure_frameprocs[procedure_num-1]; frame_size = frameproc->frame_size; } if(var_off > frame_size) { local_kind = RDI_LocalKind_Parameter; } } } // TODO(rjf): is this correct? // rjf: redirect type, if 0, and if outside frame, to the return type of the // containing procedure if(local_kind == RDI_LocalKind_Parameter && regrel32->itype == 0 && top_scope_node->scope->symbol != 0 && top_scope_node->scope->symbol->type != 0) { type = top_scope_node->scope->symbol->type->direct_type; } // rjf: build local RDIM_Scope *scope = top_scope_node->scope; RDIM_Local *local = rdim_scope_push_local(arena, sym_scopes, scope); local->kind = local_kind; local->name = name; local->type = type; // rjf: add location info to local if(type != 0) { // rjf: determine if we need an extra indirection to the value B32 extra_indirection_to_value = 0; switch(arch) { case RDI_Arch_X86: { extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 4 || !IsPow2OrZero(type->byte_size))); }break; case RDI_Arch_X64: { extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 8 || !IsPow2OrZero(type->byte_size))); }break; } // rjf: get raddbg register code RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(arch, cv_reg); // TODO(rjf): real byte_size & byte_pos from cv_reg goes here U32 byte_size = 8; U32 byte_pos = 0; // rjf: build location RDIM_LocationInfo loc_info = p2r_location_info_from_addr_reg_off(arena, arch, reg_code, byte_size, byte_pos, (S64)(S32)var_off, extra_indirection_to_value); RDIM_Location *loc2 = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &loc_info); RDIM_Rng1U64 voff_range = {0, max_U64}; rdim_local_push_location_case(arena, sym_scopes, local, loc2, voff_range); } }break; //- rjf: LTHREAD32/GTHREAD32 case CV_SymKind_LTHREAD32: case CV_SymKind_GTHREAD32: if(params->subset_flags & (RDIM_SubsetFlag_ThreadVariables|RDIM_SubsetFlag_ThreadVariableNameMap)) { // rjf: unpack sym CV_SymThread32 *thread32 = (CV_SymThread32 *)sym_header_struct_base; String8 name = str8_cstring_capped(thread32+1, sym_data_opl); U32 tls_off = thread32->tls_off; RDIM_Type *type = p2r_type_ptr_from_itype(thread32->itype); // rjf: unpack thread variable's container type RDIM_Type *container_type = 0; U64 container_name_opl = p2r_end_of_cplusplus_container_name(name); if(container_name_opl > 2) { String8 container_name = str8(name.str, container_name_opl - 2); CV_TypeId cv_type_id = pdb_tpi_first_itype_from_name(tpi_hash, tpi_leaf, container_name, 0); container_type = p2r_type_ptr_from_itype(cv_type_id); } // rjf: unpack thread variable's container symbol RDIM_Symbol *container_symbol = 0; if(container_type == 0 && top_scope_node != 0) { container_symbol = top_scope_node->scope->symbol; } // rjf: build symbol RDIM_Symbol *tvar = rdim_symbol_chunk_list_push(arena, sym_thread_variables, sym_thread_variables_chunk_cap); tvar->name = name; tvar->type = type; tvar->is_extern = (kind == CV_SymKind_GTHREAD32); tvar->offset = tls_off; tvar->container_type = container_type; tvar->container_symbol = container_symbol; }break; //- rjf: LOCAL case CV_SymKind_LOCAL: if(params->subset_flags & (RDIM_SubsetFlag_Locals)) { // rjf: no containing scope? -> malformed data; locals cannot be produced // outside of a containing scope if(top_scope_node == 0) { break; } // rjf: unpack sym CV_SymLocal *slocal = (CV_SymLocal *)sym_header_struct_base; String8 name = str8_cstring_capped(slocal+1, sym_data_opl); RDIM_Type *type = p2r_type_ptr_from_itype(slocal->itype); // rjf: determine if this symbol encodes the beginning of a global modification B32 is_global_modification = 0; if((slocal->flags & CV_LocalFlag_Global) || (slocal->flags & CV_LocalFlag_Static)) { is_global_modification = 1; } // rjf: is global modification -> emit global modification symbol if(is_global_modification) { // TODO(rjf): add global modification symbols defrange_target = 0; defrange_target_is_param = 0; } // rjf: is not a global modification -> emit a local variable if(!is_global_modification) { // rjf: determine local kind RDI_LocalKind local_kind = RDI_LocalKind_Variable; if(slocal->flags & CV_LocalFlag_Param) { local_kind = RDI_LocalKind_Parameter; } // rjf: build local RDIM_Scope *scope = top_scope_node->scope; RDIM_Local *local = rdim_scope_push_local(arena, sym_scopes, scope); local->kind = local_kind; local->name = name; local->type = type; // rjf: save defrange target, for subsequent defrange symbols defrange_target = local; defrange_target_is_param = (local_kind == RDI_LocalKind_Parameter); } }break; //- rjf: DEFRANGE_REGISTER case CV_SymKind_DEFRANGE_REGISTER: { // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing // a local - break immediately if(defrange_target == 0) { break; } // rjf: unpack sym CV_SymDefrangeRegister *defrange_register = (CV_SymDefrangeRegister*)sym_header_struct_base; CV_Reg cv_reg = defrange_register->reg; CV_LvarAddrRange *range = &defrange_register->range; COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections.count) ? &coff_sections.v[range->sec-1] : 0; CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register+1); U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(arch, cv_reg); // rjf: build location RDIM_LocationInfo loc_info = {RDI_LocationKind_ValReg, reg_code}; RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &loc_info); // rjf: emit locations over ranges p2r_local_push_location_cases_over_lvar_addr_range(arena, sym_scopes, defrange_target, loc, range, range_section, gaps, gap_count); }break; //- rjf: DEFRANGE_FRAMEPOINTER_REL case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL: { // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing // a local - break immediately if(defrange_target == 0) { break; } // rjf: find current procedure's frameproc CV_SymFrameproc *frameproc = 0; if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) { frameproc = procedure_frameprocs[procedure_num-1]; } // rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange // without having an actually active procedure - break if(frameproc == 0) { break; } // rjf: unpack sym CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel*)sym_header_struct_base; CV_LvarAddrRange *range = &defrange_fprel->range; COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections.count) ? &coff_sections.v[range->sec-1] : 0; CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_fprel + 1); U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); // rjf: select frame pointer register CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(frameproc, defrange_target_is_param); RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(arch, encoded_fp_reg); // rjf: build location B32 extra_indirection = 0; U32 byte_size = rdi_addr_size_from_arch(arch); U32 byte_pos = 0; S64 var_off = (S64)defrange_fprel->off; RDIM_LocationInfo location_info = p2r_location_info_from_addr_reg_off(arena, arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection); RDIM_Location *location = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &location_info); // rjf: emit locations over ranges p2r_local_push_location_cases_over_lvar_addr_range(arena, sym_scopes, defrange_target, location, range, range_section, gaps, gap_count); }break; //- rjf: DEFRANGE_SUBFIELD_REGISTER case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER: { // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing // a local - break immediately if(defrange_target == 0) { break; } // rjf: unpack sym CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister*)sym_header_struct_base; CV_Reg cv_reg = defrange_subfield_register->reg; CV_LvarAddrRange *range = &defrange_subfield_register->range; COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections.count) ? &coff_sections.v[range->sec-1] : 0; CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_subfield_register + 1); U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(arch, cv_reg); // rjf: skip "subfield" location info - currently not supported if(defrange_subfield_register->field_offset != 0) { break; } // rjf: build location RDIM_LocationInfo loc_info = {RDI_LocationKind_ValReg, reg_code}; RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &loc_info); // rjf: emit locations over ranges p2r_local_push_location_cases_over_lvar_addr_range(arena, sym_scopes, defrange_target, loc, range, range_section, gaps, gap_count); }break; //- rjf: DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: { // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing // a local - break immediately if(defrange_target == 0) { break; } // rjf: find current procedure's frameproc CV_SymFrameproc *frameproc = 0; if(procedure_num != 0 && procedure_num <= procedure_frameprocs_count && procedure_frameprocs[procedure_num-1] != 0) { frameproc = procedure_frameprocs[procedure_num-1]; } // rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange // without having an actually active procedure - break if(frameproc == 0) { break; } // rjf: unpack sym CV_SymDefrangeFramepointerRelFullScope *defrange_fprel_full_scope = (CV_SymDefrangeFramepointerRelFullScope*)sym_header_struct_base; CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(frameproc, defrange_target_is_param); RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(arch, encoded_fp_reg); // rjf: build location B32 extra_indirection = 0; U32 byte_size = rdi_addr_size_from_arch(arch); U32 byte_pos = 0; S64 var_off = (S64)defrange_fprel_full_scope->off; RDIM_LocationInfo loc_info = p2r_location_info_from_addr_reg_off(arena, arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection); RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &loc_info); // rjf: emit location over ranges RDIM_Rng1U64 voff_range = {0, max_U64}; rdim_local_push_location_case(arena, sym_scopes, defrange_target, loc, voff_range); }break; //- rjf: DEFRANGE_REGISTER_REL case CV_SymKind_DEFRANGE_REGISTER_REL: { // rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing // a local - break immediately if(defrange_target == 0) { break; } // rjf: unpack sym CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel*)sym_header_struct_base; CV_Reg cv_reg = defrange_register_rel->reg; RDI_RegCode reg_code = p2r_rdi_reg_code_from_cv_reg_code(arch, cv_reg); CV_LvarAddrRange *range = &defrange_register_rel->range; COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections.count) ? &coff_sections.v[range->sec-1] : 0; CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register_rel + 1); U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps); // rjf: build location // TODO(rjf): offset & size from cv_reg code U32 byte_size = rdi_addr_size_from_arch(arch); U32 byte_pos = 0; B32 extra_indirection_to_value = 0; S64 var_off = defrange_register_rel->reg_off; RDIM_LocationInfo loc_info = p2r_location_info_from_addr_reg_off(arena, arch, reg_code, byte_size, byte_pos, var_off, extra_indirection_to_value); RDIM_Location *loc = rdim_location_chunk_list_push_new(arena, sym_locations, sym_locations_chunk_cap, &loc_info); // rjf: emit locations over ranges p2r_local_push_location_cases_over_lvar_addr_range(arena, sym_scopes, defrange_target, loc, range, range_section, gaps, gap_count); }break; //- rjf: FILESTATIC case CV_SymKind_FILESTATIC: { CV_SymFileStatic *file_static = (CV_SymFileStatic*)sym_header_struct_base; String8 name = str8_cstring_capped(file_static+1, sym_data_opl); RDIM_Type *type = p2r_type_ptr_from_itype(file_static->itype); // TODO(rjf): emit a global modifier symbol defrange_target = 0; defrange_target_is_param = 0; }break; //- rjf: INLINESITE case CV_SymKind_INLINESITE: if(params->subset_flags & (RDIM_SubsetFlag_Scopes)) { // rjf: unpack sym CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); // rjf: extract external info about inline site String8 name = str8_zero(); RDIM_Type *type = 0; RDIM_Type *owner = 0; if(ipi_leaf != 0 && ipi_leaf->itype_first <= sym->inlinee && sym->inlinee < ipi_leaf->itype_opl) { CV_RecRange rec_range = ipi_leaf->leaf_ranges.ranges[sym->inlinee - ipi_leaf->itype_first]; String8 rec_data = str8_substr(ipi_leaf->data, rng_1u64(rec_range.off, rec_range.off + rec_range.hdr.size)); void *raw_leaf = rec_data.str + sizeof(U16); // rjf: extract method inline info if(rec_range.hdr.kind == CV_LeafKind_MFUNC_ID && rec_range.hdr.size >= sizeof(CV_LeafMFuncId)) { CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId*)raw_leaf; name = str8_cstring_capped(mfunc_id + 1, rec_data.str + rec_data.size); type = p2r_type_ptr_from_itype(mfunc_id->itype); owner = mfunc_id->owner_itype != 0 ? p2r_type_ptr_from_itype(mfunc_id->owner_itype) : 0; } // rjf: extract non-method function inline info else if(rec_range.hdr.kind == CV_LeafKind_FUNC_ID && rec_range.hdr.size >= sizeof(CV_LeafFuncId)) { CV_LeafFuncId *func_id = (CV_LeafFuncId*)raw_leaf; name = str8_cstring_capped(func_id + 1, rec_data.str + rec_data.size); type = p2r_type_ptr_from_itype(func_id->itype); owner = func_id->scope_string_id != 0 ? p2r_type_ptr_from_itype(func_id->scope_string_id) : 0; } } // rjf: build inline site RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, sym_inline_sites, sym_inline_sites_chunk_cap); inline_site->name = name; inline_site->type = type; inline_site->owner = owner; inline_site->line_table = inline_site_line_table; // rjf: increment to next inline site line table in this unit if(inline_site_line_table != 0 && inline_site_line_table->chunk != 0) { RDIM_LineTableChunkNode *chunk = inline_site_line_table->chunk; U64 current_idx = (U64)(inline_site_line_table - chunk->v); if(current_idx+1 < chunk->count) { inline_site_line_table += 1; } else { chunk = chunk->next; inline_site_line_table = 0; if(chunk != 0) { inline_site_line_table = chunk->v; } } } // rjf: build scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, sym_scopes, sym_scopes_chunk_cap); scope->inline_site = inline_site; if(top_scope_node == 0) { // TODO(rjf): log } if(top_scope_node != 0) { RDIM_Scope *top_scope = top_scope_node->scope; SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); scope->parent_scope = top_scope; scope->symbol = top_scope->symbol; } // rjf: push this scope to scope stack { P2R_ScopeNode *node = free_scope_node; if(node != 0) { SLLStackPop(free_scope_node); } else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } node->scope = scope; SLLStackPush(top_scope_node, node); } // rjf: parse offset ranges of this inline site - attach to scope { CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(0, 0, procedure_base_voff); for(;;) { CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitRange) { // rjf: build new range & add to scope RDIM_Rng1U64 voff_range = { step.range.min, step.range.max }; rdim_scope_push_voff_range(arena, sym_scopes, scope, voff_range); } if(step.flags & CV_C13InlineSiteDecoderStepFlag_ExtendLastRange) { if(scope->voff_ranges.last != 0) { scope->voff_ranges.last->v.max = step.range.max; } } if(step.flags == 0) { break; } } } }break; //- rjf: INLINESITE_END case CV_SymKind_INLINESITE_END: { P2R_ScopeNode *n = top_scope_node; if(n != 0) { SLLStackPop(top_scope_node); SLLStackPush(free_scope_node, n); } defrange_target = 0; defrange_target_is_param = 0; }break; //- rjf: CONSTANT case CV_SymKind_CONSTANT: if(params->subset_flags & RDIM_SubsetFlag_Constants) { // rjf: unpack CV_SymConstant *sym = (CV_SymConstant *)sym_header_struct_base; RDIM_Type *type = p2r_type_ptr_from_itype(sym->itype); U8 *val_ptr = (U8 *)(sym+1); CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, sym_data_opl); U64 val64 = cv_u64_from_numeric(&val); U8 *name_ptr = val_ptr + val.encoded_size; String8 name = str8_cstring_capped(name_ptr, sym_data_opl); String8 val_data = str8_struct(&val64); U64 container_name_opl = 0; if(type != 0) { container_name_opl = p2r_end_of_cplusplus_container_name(type->name); } String8 name_qualified = name; if(container_name_opl != 0) { name_qualified = push_str8f(arena, "%S%S", str8_prefix(type->name, container_name_opl), name); } // rjf: build constant symbol if(name_qualified.size != 0) { RDIM_Symbol *cnst = rdim_symbol_chunk_list_push(arena, sym_constants, sym_constants_chunk_cap); cnst->name = name_qualified; cnst->type = type; rdim_symbol_push_value_data(arena, sym_constants, cnst, val_data); } }break; } } } scratch_end(scratch); } } #undef p2r_type_ptr_from_itype } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: join all lane symbols // RDIM_LocationChunkList *all_locations = 0; RDIM_SymbolChunkList *all_procedures = 0; RDIM_SymbolChunkList *all_global_variables = 0; RDIM_SymbolChunkList *all_thread_variables = 0; RDIM_SymbolChunkList *all_constants = 0; RDIM_ScopeChunkList *all_scopes = 0; RDIM_InlineSiteChunkList *all_inline_sites = 0; RDIM_TypeChunkList *all_types = 0; { if(lane_idx() == 0) { all_locations = push_array(scratch.arena, RDIM_LocationChunkList, 1); all_procedures = push_array(scratch.arena, RDIM_SymbolChunkList, 1); all_global_variables = push_array(scratch.arena, RDIM_SymbolChunkList, 1); all_thread_variables = push_array(scratch.arena, RDIM_SymbolChunkList, 1); all_constants = push_array(scratch.arena, RDIM_SymbolChunkList, 1); all_scopes = push_array(scratch.arena, RDIM_ScopeChunkList, 1); all_inline_sites = push_array(scratch.arena, RDIM_InlineSiteChunkList, 1); all_types = push_array(scratch.arena, RDIM_TypeChunkList, 1); } lane_sync_u64(&all_locations, 0); lane_sync_u64(&all_procedures, 0); lane_sync_u64(&all_global_variables, 0); lane_sync_u64(&all_thread_variables, 0); lane_sync_u64(&all_constants, 0); lane_sync_u64(&all_scopes, 0); lane_sync_u64(&all_inline_sites, 0); lane_sync_u64(&all_types, 0); if(lane_idx() == lane_from_task_idx(0)) ProfScope("join locations") { for EachIndex(idx, all_syms_count) { rdim_location_chunk_list_concat_in_place(all_locations, &syms_locations[idx]); } } if(lane_idx() == lane_from_task_idx(1)) ProfScope("join procedures") { for EachIndex(idx, all_syms_count) { rdim_symbol_chunk_list_concat_in_place(all_procedures, &syms_procedures[idx]); } } if(lane_idx() == lane_from_task_idx(2)) ProfScope("join global variables") { for EachIndex(idx, all_syms_count) { rdim_symbol_chunk_list_concat_in_place(all_global_variables, &syms_global_variables[idx]); } } if(lane_idx() == lane_from_task_idx(3)) ProfScope("join thread variables") { for EachIndex(idx, all_syms_count) { rdim_symbol_chunk_list_concat_in_place(all_thread_variables, &syms_thread_variables[idx]); } } if(lane_idx() == lane_from_task_idx(4)) ProfScope("join constants") { for EachIndex(idx, all_syms_count) { rdim_symbol_chunk_list_concat_in_place(all_constants, &syms_constants[idx]); } } if(lane_idx() == lane_from_task_idx(5)) ProfScope("join scopes") { for EachIndex(idx, all_syms_count) { rdim_scope_chunk_list_concat_in_place(all_scopes, &syms_scopes[idx]); } } if(lane_idx() == lane_from_task_idx(6)) ProfScope("join inline sites") { for EachIndex(idx, all_syms_count) { rdim_inline_site_chunk_list_concat_in_place(all_inline_sites, &syms_inline_sites[idx]); } } if(lane_idx() == lane_from_task_idx(7)) ProfScope("join typedefs") { for EachIndex(idx, all_syms_count) { rdim_type_chunk_list_concat_in_place(&all_types__pre_typedefs, &syms_typedefs[idx]); } *all_types = all_types__pre_typedefs; } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: bundle all outputs // RDIM_BakeParams result = {0}; { //- rjf: produce top-level-info RDIM_TopLevelInfo top_level_info = {0}; { top_level_info.arch = arch; top_level_info.exe_name = str8_skip_last_slash(params->input_exe_name); top_level_info.exe_hash = exe_hash; top_level_info.voff_max = exe_voff_max; if(!params->deterministic) { MemoryCopy(&top_level_info.guid.u8[0], &pdb_info->auth_guid.v[0], Min(sizeof top_level_info.guid.u8, sizeof pdb_info->auth_guid.v)); top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); } } //- rjf: build binary sections list RDIM_BinarySectionList binary_sections = {0}; if(params->subset_flags & RDIM_SubsetFlag_BinarySections) ProfScope("build binary section list") { COFF_SectionHeader *coff_ptr = coff_sections.v; COFF_SectionHeader *coff_opl = coff_ptr + coff_sections.count; for(;coff_ptr < coff_opl; coff_ptr += 1) { char *name_first = (char *)coff_ptr->name; char *name_opl = name_first + sizeof(coff_ptr->name); RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); sec->name = str8_cstring_capped(name_first, name_opl); sec->flags = p2r_rdi_binary_section_flags_from_coff_section_flags(coff_ptr->flags); sec->voff_first = coff_ptr->voff; sec->voff_opl = coff_ptr->voff+coff_ptr->vsize; sec->foff_first = coff_ptr->foff; sec->foff_opl = coff_ptr->foff+coff_ptr->fsize; } } //- rjf: fill result.subset_flags = params->subset_flags; result.top_level_info = top_level_info; result.binary_sections = binary_sections; result.units = all_units; result.types = *all_types; result.udts = all_udts; result.src_files = all_src_files; result.line_tables = all_line_tables; result.locations = *all_locations; result.global_variables = *all_global_variables; result.thread_variables = *all_thread_variables; result.constants = *all_constants; result.procedures = *all_procedures; result.scopes = *all_scopes; result.inline_sites = *all_inline_sites; } scratch_end(scratch); return result; } ================================================ FILE: src/rdi_from_pdb/rdi_from_pdb.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FROM_PDB_H #define RDI_FROM_PDB_H //////////////////////////////// //~ rjf: Conversion Stage Inputs typedef struct P2R_ConvertParams P2R_ConvertParams; struct P2R_ConvertParams { String8 input_pdb_name; String8 input_pdb_data; String8 input_exe_name; String8 input_exe_data; RDIM_SubsetFlags subset_flags; B32 deterministic; }; //////////////////////////////// //~ rjf: Conversion Helper Types //- rjf: link name map (voff -> string) typedef struct P2R_LinkNameNode P2R_LinkNameNode; struct P2R_LinkNameNode { P2R_LinkNameNode *next; U64 voff; String8 name; }; typedef struct P2R_LinkNameMap P2R_LinkNameMap; struct P2R_LinkNameMap { P2R_LinkNameNode **buckets; U64 buckets_count; U64 bucket_collision_count; U64 link_name_count; }; //- rjf: normalized file path -> source file map typedef struct P2R_SrcFileStub P2R_SrcFileStub; struct P2R_SrcFileStub { String8 file_path; CV_C13ChecksumKind checksum_kind; String8 checksum; }; typedef struct P2R_SrcFileStubArray P2R_SrcFileStubArray; struct P2R_SrcFileStubArray { P2R_SrcFileStub *v; U64 count; }; typedef struct P2R_SrcFileStubNode P2R_SrcFileStubNode; struct P2R_SrcFileStubNode { P2R_SrcFileStubNode *next; P2R_SrcFileStub v; }; typedef struct P2R_SrcFileNode P2R_SrcFileNode; struct P2R_SrcFileNode { P2R_SrcFileNode *next; RDIM_SrcFile *src_file; }; typedef struct P2R_SrcFileMap P2R_SrcFileMap; struct P2R_SrcFileMap { P2R_SrcFileNode **slots; U64 slots_count; }; //- rjf: itype chains typedef struct P2R_TypeIdChain P2R_TypeIdChain; struct P2R_TypeIdChain { P2R_TypeIdChain *next; CV_TypeId itype; }; //////////////////////////////// //~ rjf: Basic Helpers internal U64 p2r_end_of_cplusplus_container_name(String8 str); internal U64 p2r_hash_from_voff(U64 voff); //////////////////////////////// //~ rjf: COFF => RDI Canonical Conversions internal RDI_BinarySectionFlags p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags); //////////////////////////////// //~ rjf: CodeView => RDI Canonical Conversions internal RDI_Arch p2r_rdi_arch_from_cv_arch(CV_Arch arch); internal RDI_RegCode p2r_rdi_reg_code_from_cv_reg_code(RDI_Arch arch, CV_Reg reg_code); internal RDI_Language p2r_rdi_language_from_cv_language(CV_Language language); internal RDI_TypeKind p2r_rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type); internal RDI_ChecksumKind p2r_rdi_from_cv_c13_checksum_kind(CV_C13ChecksumKind k); //////////////////////////////// //~ rjf: Location Info Building Helpers internal RDI_RegCode p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg); internal RDIM_LocationInfo p2r_location_info_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 extra_indirection); internal void p2r_local_push_location_cases_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Local *local, RDIM_Location *loc, CV_LvarAddrRange *range, COFF_SectionHeader *section, CV_LvarAddrGap *gaps, U64 gap_count); //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point internal RDIM_BakeParams p2r_convert(Arena *arena, P2R_ConvertParams *params); #endif // RDI_FROM_PDB_H ================================================ FILE: src/rdi_make/rdi_make_local.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "lib_rdi_make/rdi_make.c" internal RDIM_DataModel rdim_data_model_from_os_arch(OperatingSystem os, RDI_Arch arch) { RDIM_DataModel data_model = RDIM_DataModel_Null; #define Case(os_name, arch_name, model_name) if(os == OperatingSystem_##os_name && arch == Arch_##arch_name) { data_model = RDIM_DataModel_##model_name; } Case(Windows, x86, LLP64); Case(Windows, x64, LLP64); Case(Linux, x86, ILP32); Case(Linux, x64, LLP64); Case(Mac, x64, LP64); #undef Case return data_model; } internal RDIM_BakeResults rdim_bake(Arena *arena, RDIM_BakeParams *params) { ////////////////////////////////////////////////////////////// //- rjf: set up shared state // if(lane_idx() == 0) { rdim_shared = push_array(arena, RDIM_Shared, 1); } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake vmaps // ProfScope("bake vmaps") { Temp scratch = scratch_begin(&arena, 1); #pragma pack(push, 1) typedef struct VMapRecord VMapRecord; struct VMapRecord { union { struct { U32 negative_size; U64 voff; }; U8 digits[12]; } key; U32 idx; }; #pragma pack(pop) //////////////////////////// //- rjf: gather unsorted scope vmap records // VMapRecord *scope_vmap_records = 0; U64 scope_vmap_records_count = 0; ProfScope("gather unsorted scope vmap records") { //- rjf: calculate per-lane-chunk counts U64 *lane_chunk_range_counts = 0; if(lane_idx() == 0) { lane_chunk_range_counts = push_array(scratch.arena, U64, params->scopes.chunk_count * lane_count()); } lane_sync_u64(&lane_chunk_range_counts, 0); { U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { U64 slot_idx = lane_idx()*params->scopes.chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { lane_chunk_range_counts[slot_idx] += n->v[n_idx].voff_ranges.count; } chunk_idx += 1; } } lane_sync(); //- rjf: calculate per-lane-chunk offsets U64 *lane_chunk_range_offs = 0; U64 total_range_count = 0; if(lane_idx() == 0) { lane_chunk_range_offs = push_array(scratch.arena, U64, params->scopes.chunk_count * lane_count()); U64 off = 0; U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->scopes.chunk_count + chunk_idx; lane_chunk_range_offs[slot_idx] = off; off += lane_chunk_range_counts[slot_idx]; } chunk_idx += 1; } total_range_count = off; } lane_sync_u64(&lane_chunk_range_offs, 0); lane_sync_u64(&total_range_count, 0); //- rjf: allocate records if(lane_idx() == 0) { scope_vmap_records_count = total_range_count; scope_vmap_records = push_array_no_zero(scratch.arena, VMapRecord, scope_vmap_records_count); } lane_sync_u64(&scope_vmap_records, 0); lane_sync_u64(&scope_vmap_records_count, 0); //- rjf: fill records { U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { U64 slot_idx = lane_idx()*params->scopes.chunk_count + chunk_idx; U64 off = lane_chunk_range_offs[slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDI_U32 scope_idx = (RDI_U32)rdim_idx_from_scope(&n->v[n_idx]); // TODO(rjf): @u64_to_u32 for EachNode(rng_n, RDIM_Rng1U64Node, n->v[n_idx].voff_ranges.first) { scope_vmap_records[off].key.voff = rng_n->v.min; scope_vmap_records[off].key.negative_size = -(RDI_U32)(rng_n->v.max - rng_n->v.min); scope_vmap_records[off].idx = scope_idx; off += 1; } } chunk_idx += 1; } } } lane_sync(); //////////////////////////// //- rjf: gather unsorted global vmap records // VMapRecord *global_vmap_records = 0; U64 global_vmap_records_count = 0; ProfScope("gather unsorted global vmap records") { //- rjf: calculate per-lane-chunk counts U64 *lane_chunk_range_counts = 0; if(lane_idx() == 0) { lane_chunk_range_counts = push_array(scratch.arena, U64, params->global_variables.chunk_count * lane_count()); } lane_sync_u64(&lane_chunk_range_counts, 0); { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->global_variables.first) { U64 slot_idx = lane_idx()*params->global_variables.chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); lane_chunk_range_counts[slot_idx] += dim_1u64(range); chunk_idx += 1; } } lane_sync(); //- rjf: calculate per-lane-chunk offsets U64 *lane_chunk_range_offs = 0; U64 total_range_count = 0; if(lane_idx() == 0) { lane_chunk_range_offs = push_array(scratch.arena, U64, params->global_variables.chunk_count * lane_count()); U64 off = 0; U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->global_variables.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->global_variables.chunk_count + chunk_idx; lane_chunk_range_offs[slot_idx] = off; off += lane_chunk_range_counts[slot_idx]; } chunk_idx += 1; } total_range_count = off; } lane_sync_u64(&lane_chunk_range_offs, 0); lane_sync_u64(&total_range_count, 0); //- rjf: allocate records if(lane_idx() == 0) { global_vmap_records_count = total_range_count; global_vmap_records = push_array_no_zero(scratch.arena, VMapRecord, global_vmap_records_count); } lane_sync_u64(&global_vmap_records, 0); lane_sync_u64(&global_vmap_records_count, 0); //- rjf: fill records { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->global_variables.first) { U64 slot_idx = lane_idx()*params->global_variables.chunk_count + chunk_idx; U64 off = lane_chunk_range_offs[slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDI_U32 global_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[n_idx]); // TODO(rjf): @u64_to_u32 RDI_U32 global_size = (RDI_U32)(n->v[n_idx].type ? n->v[n_idx].type->byte_size : 1); RDI_U64 global_voff = n->v[n_idx].offset; global_vmap_records[off].key.voff = global_voff; global_vmap_records[off].key.negative_size = -global_size; global_vmap_records[off].idx = global_idx; off += 1; } chunk_idx += 1; } } } lane_sync(); //////////////////////////// //- rjf: gather unsorted unit vmap records // VMapRecord *unit_vmap_records = 0; U64 unit_vmap_records_count = 0; ProfScope("gather unsorted unit vmap records") { //- rjf: calculate per-lane-chunk counts U64 *lane_chunk_range_counts = 0; if(lane_idx() == 0) { lane_chunk_range_counts = push_array(scratch.arena, U64, params->units.chunk_count * lane_count()); } lane_sync_u64(&lane_chunk_range_counts, 0); { U64 chunk_idx = 0; for EachNode(n, RDIM_UnitChunkNode, params->units.first) { U64 slot_idx = lane_idx()*params->units.chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { lane_chunk_range_counts[slot_idx] += n->v[n_idx].voff_ranges.total_count; } chunk_idx += 1; } } lane_sync(); //- rjf: calculate per-lane-chunk offsets U64 *lane_chunk_range_offs = 0; U64 total_range_count = 0; if(lane_idx() == 0) { lane_chunk_range_offs = push_array(scratch.arena, U64, params->units.chunk_count * lane_count()); U64 off = 0; U64 chunk_idx = 0; for EachNode(n, RDIM_UnitChunkNode, params->units.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->units.chunk_count + chunk_idx; lane_chunk_range_offs[slot_idx] = off; off += lane_chunk_range_counts[slot_idx]; } chunk_idx += 1; } total_range_count = off; } lane_sync_u64(&lane_chunk_range_offs, 0); lane_sync_u64(&total_range_count, 0); //- rjf: allocate records if(lane_idx() == 0) { unit_vmap_records_count = total_range_count; unit_vmap_records = push_array_no_zero(scratch.arena, VMapRecord, unit_vmap_records_count); } lane_sync_u64(&unit_vmap_records, 0); lane_sync_u64(&unit_vmap_records_count, 0); //- rjf: fill records { U64 chunk_idx = 0; for EachNode(n, RDIM_UnitChunkNode, params->units.first) { U64 slot_idx = lane_idx()*params->units.chunk_count + chunk_idx; U64 off = lane_chunk_range_offs[slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDI_U32 unit_idx = (RDI_U32)rdim_idx_from_unit(&n->v[n_idx]); // TODO(rjf): @u64_to_u32 for EachNode(rng_n, RDIM_Rng1U64ChunkNode, n->v[n_idx].voff_ranges.first) { for EachIndex(rng_n_idx, rng_n->count) { unit_vmap_records[off].key.voff = rng_n->v[rng_n_idx].min; unit_vmap_records[off].key.negative_size = -(RDI_U32)(rng_n->v[rng_n_idx].max - rng_n->v[rng_n_idx].min); unit_vmap_records[off].idx = unit_idx; off += 1; } } } chunk_idx += 1; } } } lane_sync(); //////////////////////////// //- rjf: sort & bake all vmaps // struct { String8 name; VMapRecord *records; U64 records_count; RDI_VMapEntry **vmap_out; U32 *vmap_count_out; } vmap_tasks[] = { {str8_lit_comp("scopes"), scope_vmap_records, scope_vmap_records_count, &rdim_shared->baked_scope_vmap.vmap.vmap, &rdim_shared->baked_scope_vmap.vmap.count}, {str8_lit_comp("globals"), global_vmap_records, global_vmap_records_count, &rdim_shared->baked_global_vmap.vmap.vmap, &rdim_shared->baked_global_vmap.vmap.count}, {str8_lit_comp("units"), unit_vmap_records, unit_vmap_records_count, &rdim_shared->baked_unit_vmap.vmap.vmap, &rdim_shared->baked_unit_vmap.vmap.count}, }; ProfScope("sort & bake all vmaps") { for EachElement(vmap_task_idx, vmap_tasks) ProfScope("sort & bake vmap for %.*s", str8_varg(vmap_tasks[vmap_task_idx].name)) { VMapRecord *records = vmap_tasks[vmap_task_idx].records; U64 records_count = vmap_tasks[vmap_task_idx].records_count; //////////////////////// //- rjf: sort // ProfScope("sort") { //- rjf: set up constants U64 bytes_per_digit = 1; U64 num_possible_values_per_digit = 1<<(bytes_per_digit*8); U64 digits_count = sizeof(((VMapRecord *)0)->key)/bytes_per_digit; //- rjf: set up swap buffer / lane counters VMapRecord *records__swap = 0; U32 **lane_digit_counts = 0; U32 **lane_digit_offs = 0; if(lane_idx() == 0) { records__swap = push_array_no_zero(scratch.arena, VMapRecord, records_count); lane_digit_counts = push_array_no_zero(scratch.arena, U32 *, lane_count()); lane_digit_offs = push_array_no_zero(scratch.arena, U32 *, lane_count()); } lane_sync_u64(&records__swap, 0); lane_sync_u64(&lane_digit_counts, 0); lane_sync_u64(&lane_digit_offs, 0); lane_digit_counts[lane_idx()] = push_array_no_zero(scratch.arena, U32, num_possible_values_per_digit); lane_digit_offs[lane_idx()] = push_array_no_zero(scratch.arena, U32, num_possible_values_per_digit); //- rjf: do all sort passes { VMapRecord *src = records; VMapRecord *dst = records__swap; for EachIndex(digit_idx, digits_count) { // rjf: count digit value occurrences per-lane { U32 *digit_counts = lane_digit_counts[lane_idx()]; MemoryZero(digit_counts, sizeof(digit_counts[0])*num_possible_values_per_digit); Rng1U64 range = lane_range(records_count); for EachInRange(idx, range) { VMapRecord *rec = &src[idx]; U16 digit_value = (U16)rec->key.digits[digit_idx]; digit_counts[digit_value] += 1; } } lane_sync(); // rjf: compute thread * digit value *relative* offset table { Rng1U64 range = lane_range(num_possible_values_per_digit); for EachInRange(value_idx, range) { U64 layout_off = 0; for EachIndex(lane_idx, lane_count()) { lane_digit_offs[lane_idx][value_idx] = layout_off; layout_off += lane_digit_counts[lane_idx][value_idx]; } } } lane_sync(); // rjf: convert relative offsets -> absolute offsets if(lane_idx() == 0) { U64 last_off = 0; U64 num_of_nonzero_digit = 0; for EachIndex(value_idx, num_possible_values_per_digit) { for EachIndex(lane_idx, lane_count()) { lane_digit_offs[lane_idx][value_idx] += last_off; } last_off = lane_digit_offs[lane_count()-1][value_idx] + lane_digit_counts[lane_count()-1][value_idx]; } // NOTE(rjf): required that: (last_off == element_count) } lane_sync(); // rjf: move { U32 *lane_digit_offsets = lane_digit_offs[lane_idx()]; Rng1U64 range = lane_range(records_count); for EachInRange(idx, range) { VMapRecord *src_rec = &src[idx]; U16 digit_value = (U16)src_rec->key.digits[digit_idx]; U64 dst_off = lane_digit_offsets[digit_value]; lane_digit_offsets[digit_value] += 1; MemoryCopyStruct(&dst[dst_off], src_rec); } } lane_sync(); // rjf: swap source with destination for next pass Swap(VMapRecord *, src, dst); } } } lane_sync(); //////////////////////// //- rjf: bake // RDI_VMapEntry *vmap = 0; RDI_U64 vmap_count = 0; { //- rjf: allocate vmap RDI_U64 vmap_count__cap = records_count*2 + 1; if(lane_idx() == 0) { vmap = push_array(arena, RDI_VMapEntry, vmap_count__cap); } lane_sync_u64(&vmap, 0); //- rjf: bake if(lane_idx() == 0) { typedef struct RangeNode RangeNode; struct RangeNode { RangeNode *next; Rng1U64 voff_range; U64 idx; }; RDI_VMapEntry *vmap_ptr = vmap; RDI_VMapEntry *vmap_opl = vmap + vmap_count__cap; RangeNode *top_range = 0; RangeNode *free_range = 0; U64 last_recorded_voff = 0; for(U64 record_idx = 0; record_idx <= records_count; record_idx += 1) { // rjf: get next voff range and index Rng1U64 voff_range = r1u64(max_U64, max_U64); U64 idx = 0; if(record_idx < records_count) { VMapRecord *record = &records[record_idx]; voff_range = r1u64(record->key.voff, record->key.voff + -record->key.negative_size); idx = (U64)record->idx; } // rjf: pop nodes we've advanced past { for(RangeNode *n = top_range, *next = 0; n != 0; n = next) { next = n->next; if(n->voff_range.max <= voff_range.min) { SLLStackPop(top_range); SLLStackPush(free_range, n); if(n->voff_range.max != last_recorded_voff) { vmap_ptr += 1; } vmap_ptr->voff = n->voff_range.max; vmap_ptr->idx = next ? next->idx : 0; last_recorded_voff = vmap_ptr->voff; } else { break; } } } // rjf: push this node if(record_idx < records_count) { RangeNode *r = free_range; if(r) { SLLStackPop(free_range); } else { r = push_array(scratch.arena, RangeNode, 1); } SLLStackPush(top_range, r); r->voff_range = voff_range; r->idx = idx; if(voff_range.min != last_recorded_voff || (vmap_ptr->idx != idx && vmap_ptr->idx != 0)) { vmap_ptr += 1; } vmap_ptr->voff = voff_range.min; vmap_ptr->idx = idx; last_recorded_voff = voff_range.min; } } if(last_recorded_voff != 0) { vmap_ptr += 1; } vmap_count = (vmap_ptr - vmap); } lane_sync_u64(&vmap_count, 0); } lane_sync(); //////////////////////// //- rjf: store // if(lane_idx() == 0) { vmap_tasks[vmap_task_idx].vmap_out[0] = vmap; vmap_tasks[vmap_task_idx].vmap_count_out[0] = vmap_count; } } } scratch_end(scratch); } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage build interned path tree // if(lane_idx() == 0) ProfScope("build interned path tree") { //- rjf: set up tree RDIM_BakePathTree *tree = rdim_push_array(arena, RDIM_BakePathTree, 1); rdim_bake_path_tree_insert(arena, tree, rdim_str8_lit("")); //- rjf: bake unit file paths RDIM_ProfScope("bake unit file paths") { for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { rdim_bake_path_tree_insert(arena, tree, n->v[idx].source_file); rdim_bake_path_tree_insert(arena, tree, n->v[idx].object_file); rdim_bake_path_tree_insert(arena, tree, n->v[idx].archive_file); rdim_bake_path_tree_insert(arena, tree, n->v[idx].build_path); } } } //- rjf: bake source file paths RDIM_ProfScope("bake source file paths") { for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDIM_BakePathNode *node = rdim_bake_path_tree_insert(arena, tree, n->v[idx].path); node->src_file = &n->v[idx]; } } } rdim_shared->path_tree = tree; } lane_sync(); RDIM_BakePathTree *path_tree = rdim_shared->path_tree; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage gather all unsorted, joined, line table info; & sort // ProfScope("gather all unsorted, joined, line table info; & sort") { //- rjf: set up outputs ProfScope("set up outputs") { // rjf: calculate header info if(lane_idx() == 0) { rdim_shared->line_tables_count = params->line_tables.total_count; rdim_shared->src_line_tables = push_array(arena, RDIM_LineTable *, rdim_shared->line_tables_count); ProfScope("flatten chunk list") { U64 joined_idx = 0; for(RDIM_LineTableChunkNode *n = params->line_tables.first; n != 0; n = n->next) { for EachIndex(idx, n->count) { rdim_shared->src_line_tables[joined_idx] = &n->v[idx]; joined_idx += 1; } } } rdim_shared->baked_line_tables.line_tables_count = params->line_tables.total_count + 1; rdim_shared->baked_line_tables.line_table_voffs_count = params->line_tables.total_line_count + 2*params->line_tables.total_seq_count; rdim_shared->baked_line_tables.line_table_lines_count = params->line_tables.total_line_count + params->line_tables.total_seq_count; rdim_shared->baked_line_tables.line_table_columns_count= 1; rdim_shared->line_table_block_take_counter = 0; } lane_sync(); // rjf: allocate outputs ProfScope("allocate outputs") { if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->unsorted_joined_line_tables = push_array(arena, RDIM_UnsortedJoinedLineTable, rdim_shared->line_tables_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->sorted_line_table_keys = push_array(arena, RDIM_SortKey *, rdim_shared->line_tables_count); } if(lane_idx() == lane_from_task_idx(2)) { rdim_shared->baked_line_tables.line_tables = push_array(arena, RDI_LineTable, rdim_shared->baked_line_tables.line_tables_count); ProfScope("lay out line tables") { U64 voffs_base_idx = 0; U64 lines_base_idx = 0; U64 cols_base_idx = 0; for EachIndex(idx, rdim_shared->line_tables_count) { U64 final_idx = idx+1; // NOTE(rjf): +1, to reserve [0] for nil RDIM_LineTable *src = rdim_shared->src_line_tables[idx]; RDI_LineTable *dst = &rdim_shared->baked_line_tables.line_tables[final_idx]; dst->voffs_base_idx = voffs_base_idx; // TODO(rjf): @u64_to_u32 dst->lines_base_idx = lines_base_idx; // TODO(rjf): @u64_to_u32 dst->cols_base_idx = cols_base_idx; // TODO(rjf): @u64_to_u32 dst->lines_count = src->line_count + src->seq_count; // TODO(rjf): @u64_to_u32 voffs_base_idx += src->line_count + 2*src->seq_count; lines_base_idx += src->line_count + 1*src->seq_count; } } } if(lane_idx() == lane_from_task_idx(3)) { rdim_shared->baked_line_tables.line_table_voffs = push_array(arena, RDI_U64, rdim_shared->baked_line_tables.line_table_voffs_count); } if(lane_idx() == lane_from_task_idx(4)) { rdim_shared->baked_line_tables.line_table_lines = push_array(arena, RDI_Line, rdim_shared->baked_line_tables.line_table_lines_count); } if(lane_idx() == lane_from_task_idx(5)) { rdim_shared->baked_line_tables.line_table_columns = push_array(arena, RDI_Column, rdim_shared->baked_line_tables.line_table_columns_count); } } } lane_sync(); //- rjf: wide bake ProfScope("wide bake") { U64 line_table_block_size = 4096; U64 line_table_block_count = (rdim_shared->line_tables_count + line_table_block_size - 1) / line_table_block_size; for(;;) { U64 line_table_block_num = ins_atomic_u64_inc_eval(&rdim_shared->line_table_block_take_counter); if(0 == line_table_block_num || line_table_block_count < line_table_block_num) { break; } U64 line_table_block_idx = line_table_block_num-1; Rng1U64 line_table_range = r1u64(line_table_block_idx*line_table_block_size, (line_table_block_idx+1)*line_table_block_size); line_table_range.max = Min(rdim_shared->line_tables_count, line_table_range.max); for EachInRange(line_table_idx, line_table_range) { RDIM_LineTable *src = rdim_shared->src_line_tables[line_table_idx]; RDIM_UnsortedJoinedLineTable *dst = &rdim_shared->unsorted_joined_line_tables[line_table_idx]; //- rjf: gather dst->line_count = src->line_count; dst->seq_count = src->seq_count; dst->key_count = dst->line_count + dst->seq_count; dst->line_keys = rdim_push_array_no_zero(arena, RDIM_SortKey, dst->key_count); dst->line_recs = rdim_push_array_no_zero(arena, RDIM_LineRec, dst->line_count); { RDIM_SortKey *key_ptr = dst->line_keys; RDIM_LineRec *rec_ptr = dst->line_recs; for(RDIM_LineSequenceNode *seq_n = src->first_seq; seq_n != 0; seq_n = seq_n->next) { RDIM_LineSequence *seq = &seq_n->v; for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) { key_ptr->key = seq->voffs[line_idx]; key_ptr->val = rec_ptr; key_ptr += 1; rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 rec_ptr->line_num = seq->line_nums[line_idx]; if(seq->col_nums != 0) { rec_ptr->col_first = seq->col_nums[line_idx*2]; rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; } rec_ptr += 1; } key_ptr->key = seq->voffs[seq->line_count]; key_ptr->val = 0; key_ptr += 1; } } //- rjf: sort rdim_shared->sorted_line_table_keys[line_table_idx] = rdim_sort_key_array(arena, rdim_shared->unsorted_joined_line_tables[line_table_idx].line_keys, rdim_shared->unsorted_joined_line_tables[line_table_idx].key_count); //- rjf: fill RDIM_SortKey *sorted_line_keys = rdim_shared->sorted_line_table_keys[line_table_idx]; U64 sorted_line_keys_count = rdim_shared->unsorted_joined_line_tables[line_table_idx].key_count; RDI_LineTable *dst_line_table = &rdim_shared->baked_line_tables.line_tables[line_table_idx+1]; U64 *arranged_voffs = rdim_shared->baked_line_tables.line_table_voffs + dst_line_table->voffs_base_idx; RDI_Line *arranged_lines = rdim_shared->baked_line_tables.line_table_lines + dst_line_table->lines_base_idx; RDI_Column *arranged_cols = rdim_shared->baked_line_tables.line_table_columns + dst_line_table->cols_base_idx; { for EachIndex(idx, sorted_line_keys_count) { arranged_voffs[idx] = sorted_line_keys[idx].key; } arranged_voffs[sorted_line_keys_count] = ~0ull; for EachIndex(idx, sorted_line_keys_count) { RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[idx].val; if(rec != 0) { arranged_lines[idx].file_idx = rec->file_id; arranged_lines[idx].line_num = rec->line_num; } else { arranged_lines[idx].file_idx = 0; arranged_lines[idx].line_num = 0; } } } } } } } lane_sync(); RDI_U64 line_tables_count = rdim_shared->line_tables_count; RDIM_LineTable **src_line_tables = rdim_shared->src_line_tables; RDIM_UnsortedJoinedLineTable *unsorted_joined_line_tables = rdim_shared->unsorted_joined_line_tables; RDIM_SortKey **sorted_line_table_keys = rdim_shared->sorted_line_table_keys; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage build string map // ProfScope("build string map") { Temp scratch = scratch_begin(&arena, 1); //- rjf: set up per-lane outputs RDIM_BakeStringMapTopology *top = 0; RDIM_BakeStringMapLoose **lane_maps__loose = 0; RDIM_BakeStringMapLoose *map__loose = 0; if(lane_idx() == 0) ProfScope("set up per-lane outputs") { top = push_array(scratch.arena, RDIM_BakeStringMapTopology, 1); top->slots_count = (64 + params->procedures.total_count*1 + params->global_variables.total_count*1 + params->thread_variables.total_count*1 + params->types.total_count/2); lane_maps__loose = push_array(scratch.arena, RDIM_BakeStringMapLoose *, lane_count()); map__loose = rdim_bake_string_map_loose_make(scratch.arena, top); } lane_sync_u64(&top, 0); lane_sync_u64(&lane_maps__loose, 0); lane_sync_u64(&map__loose, 0); //- rjf: set up this lane's map ProfScope("set up this lane's map") { lane_maps__loose[lane_idx()] = rdim_bake_string_map_loose_make(scratch.arena, top); } RDIM_BakeStringMapLoose *lane_map = lane_maps__loose[lane_idx()]; //- rjf: push all strings into this lane's map ProfScope("push all strings into this lane's map") { // rjf: push small top-level strings if(lane_idx() == 0) ProfScope("push small top-level strings") { rdim_bake_string_map_loose_insert(arena, top, lane_map, 1, params->top_level_info.exe_name); rdim_bake_string_map_loose_insert(arena, top, lane_map, 1, params->top_level_info.producer_name); for(RDIM_BinarySectionNode *n = params->binary_sections.first; n != 0; n = n->next) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 1, n->v.name); } for(RDIM_BakePathNode *n = path_tree->first; n != 0; n = n->next_order) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 1, n->name); } } // rjf: push strings from source files ProfScope("src files") { for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_String8 normalized_path = rdim_lower_from_str8(arena, n->v[n_idx].path); rdim_bake_string_map_loose_insert(arena, top, lane_map, 1, normalized_path); } } } // rjf: push strings from units ProfScope("units") { for EachNode(n, RDIM_UnitChunkNode, params->units.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].unit_name); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].compiler_name); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].source_file); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].object_file); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].archive_file); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].build_path); } } } // rjf: push strings from types ProfScope("types") { for EachNode(n, RDIM_TypeChunkNode, params->types.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].name); } } } // rjf: push strings from udts ProfScope("udts") { for EachNode(n, RDIM_UDTChunkNode, params->udts.first) { Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { for EachNode(mem, RDIM_UDTMember, n->v[idx].first_member) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, mem->name); } for EachNode(enum_val, RDIM_UDTEnumVal, n->v[idx].first_enum_val) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, enum_val->name); } } } } // rjf: push strings from symbols RDIM_SymbolChunkList *symbol_lists[] = { ¶ms->global_variables, ¶ms->thread_variables, ¶ms->procedures, ¶ms->constants, }; ProfScope("symbols") { for EachElement(list_idx, symbol_lists) { for EachNode(n, RDIM_SymbolChunkNode, symbol_lists[list_idx]->first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].name); rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].link_name); } } } } //- rjf: push strings from inline sites ProfScope("inline sites") { for EachNode(n, RDIM_InlineSiteChunkNode, params->inline_sites.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, n->v[n_idx].name); } } } //- rjf: push strings from scopes ProfScope("scopes") { for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { for EachNode(local, RDIM_Local, n->v[n_idx].first_local) { rdim_bake_string_map_loose_insert(arena, top, lane_map, 4, local->name); } } } } } lane_sync(); //- rjf: join ProfScope("join") { Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { for EachIndex(src_lane_idx, lane_count()) { RDIM_BakeStringMapLoose *src_map = lane_maps__loose[src_lane_idx]; RDIM_BakeStringMapLoose *dst_map = map__loose; if(dst_map->slots[slot_idx] == 0 && src_map->slots[slot_idx] != 0) { dst_map->slots[slot_idx] = src_map->slots[slot_idx]; } else if(dst_map->slots[slot_idx] != 0 && src_map->slots[slot_idx] != 0) { rdim_bake_string_chunk_list_concat_in_place(dst_map->slots[slot_idx], src_map->slots[slot_idx]); } } } } lane_sync(); //- rjf: sort ProfScope("sort") { RDIM_BakeStringMapLoose *map = map__loose; Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { if(map->slots[slot_idx] != 0) { *map->slots[slot_idx] = rdim_bake_string_chunk_list_sorted_from_unsorted(arena, map->slots[slot_idx]); } } } lane_sync(); //- rjf: tighten string table ProfScope("tighten string table") { RDIM_BakeStringMapLoose *map = map__loose; if(lane_idx() == 0) ProfScope("calc base indices, set up tight map") { RDIM_BakeStringMapBaseIndices bake_string_map_base_indices = rdim_bake_string_map_base_indices_from_map_loose(arena, top, map); rdim_shared->bake_strings.slots_count = top->slots_count; rdim_shared->bake_strings.slots = rdim_push_array(arena, RDIM_BakeStringChunkList, rdim_shared->bake_strings.slots_count); rdim_shared->bake_strings.slots_base_idxs = bake_string_map_base_indices.slots_base_idxs; rdim_shared->bake_strings.total_count = rdim_shared->bake_strings.slots_base_idxs[rdim_shared->bake_strings.slots_count]; } lane_sync(); ProfScope("fill tight map") { Rng1U64 slot_range = lane_range(rdim_shared->bake_strings.slots_count); for EachInRange(idx, slot_range) { if(map->slots[idx] != 0) { rdim_memcpy_struct(&rdim_shared->bake_strings.slots[idx], map->slots[idx]); } } } } scratch_end(scratch); } lane_sync(); RDIM_BakeStringMapTight *bake_strings = &rdim_shared->bake_strings; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage build name maps // B32 name_maps_need_build[RDI_NameMapKind_COUNT] = {0}; { name_maps_need_build[RDI_NameMapKind_GlobalVariables] = !!(params->subset_flags & RDIM_SubsetFlag_GlobalVariableNameMap); name_maps_need_build[RDI_NameMapKind_ThreadVariables] = !!(params->subset_flags & RDIM_SubsetFlag_ThreadVariableNameMap); name_maps_need_build[RDI_NameMapKind_Constants] = !!(params->subset_flags & RDIM_SubsetFlag_ConstantNameMap); name_maps_need_build[RDI_NameMapKind_Procedures] = !!(params->subset_flags & RDIM_SubsetFlag_ProcedureNameMap); name_maps_need_build[RDI_NameMapKind_Types] = !!(params->subset_flags & RDIM_SubsetFlag_TypeNameMap); name_maps_need_build[RDI_NameMapKind_LinkNameProcedures] = !!(params->subset_flags & RDIM_SubsetFlag_LinkNameProcedureNameMap); name_maps_need_build[RDI_NameMapKind_NormalSourcePaths] = !!(params->subset_flags & RDIM_SubsetFlag_NormalSourcePathNameMap); } RDIM_BakeNameMapTopology *bake_name_maps_tops = 0; RDIM_BakeNameMap **bake_name_maps = 0; ProfScope("build name maps") { Temp scratch = scratch_begin(&arena, 1); //- rjf: set up RDIM_BakeNameMap ***lane_maps = 0; if(lane_idx() == 0) { bake_name_maps_tops = push_array(arena, RDIM_BakeNameMapTopology, RDI_NameMapKind_COUNT); bake_name_maps = push_array(arena, RDIM_BakeNameMap *, RDI_NameMapKind_COUNT); lane_maps = push_array(scratch.arena, RDIM_BakeNameMap **, RDI_NameMapKind_COUNT); for EachNonZeroEnumVal(RDI_NameMapKind, k) { U64 slot_count = 0; switch((RDI_NameMapKindEnum)k) { case RDI_NameMapKind_NULL: case RDI_NameMapKind_COUNT: {}break; #define Case(name, total_count) case RDI_NameMapKind_##name:{slot_count = ((total_count) + (total_count)/4);}break Case(GlobalVariables, params->global_variables.total_count); Case(ThreadVariables, params->thread_variables.total_count); Case(Constants, params->constants.total_count); Case(Procedures, params->procedures.total_count); Case(LinkNameProcedures, params->procedures.total_count); Case(Types, params->types.total_count); Case(NormalSourcePaths, params->src_files.total_count); #undef Case } lane_maps[k] = push_array(arena, RDIM_BakeNameMap *, lane_count()); bake_name_maps_tops[k].slots_count = slot_count; } } lane_sync_u64(&bake_name_maps_tops, 0); lane_sync_u64(&bake_name_maps, 0); lane_sync_u64(&lane_maps, 0); //- rjf: wide build for EachNonZeroEnumVal(RDI_NameMapKind, k) ProfScope("name map build %.*s", str8_varg(rdi_string_from_name_map_kind(k))) { if(!name_maps_need_build[k]) { continue; } RDIM_BakeNameMapTopology *top = &bake_name_maps_tops[k]; lane_maps[k][lane_idx()] = rdim_bake_name_map_make(scratch.arena, top); RDIM_BakeNameMap *map = lane_maps[k][lane_idx()]; B32 link_names = 0; RDIM_SymbolChunkList *symbols = 0; switch((RDI_NameMapKindEnum)k) { case RDI_NameMapKind_NULL: case RDI_NameMapKind_COUNT: {}break; case RDI_NameMapKind_GlobalVariables: {symbols = ¶ms->global_variables;}goto symbol_name_map_build; case RDI_NameMapKind_ThreadVariables: {symbols = ¶ms->thread_variables;}goto symbol_name_map_build; case RDI_NameMapKind_Constants: {symbols = ¶ms->constants;}goto symbol_name_map_build; case RDI_NameMapKind_Procedures: {symbols = ¶ms->procedures;}goto symbol_name_map_build; case RDI_NameMapKind_LinkNameProcedures:{symbols = ¶ms->procedures; link_names = 1;}goto symbol_name_map_build; symbol_name_map_build:; { for EachNode(n, RDIM_SymbolChunkNode, symbols->first) { Rng1U64 n_range = lane_range(n->count); for EachInRange(n_idx, n_range) { RDIM_Symbol *symbol = &n->v[n_idx]; rdim_bake_name_map_insert(scratch.arena, top, map, 4, link_names ? symbol->link_name : symbol->name, rdim_idx_from_symbol(symbol)); } } }break; case RDI_NameMapKind_Types: { RDIM_TypeChunkList *types = ¶ms->types; for EachNode(n, RDIM_TypeChunkNode, types->first) { Rng1U64 n_range = lane_range(n->count); for EachInRange(n_idx, n_range) { RDIM_Type *type = &n->v[n_idx]; rdim_bake_name_map_insert(scratch.arena, top, map, 4, type->name, rdim_idx_from_type(type)); } } }break; case RDI_NameMapKind_NormalSourcePaths: { RDIM_SrcFileChunkList *src_files = ¶ms->src_files; for EachNode(n, RDIM_SrcFileChunkNode, src_files->first) { Rng1U64 n_range = lane_range(n->count); for EachInRange(n_idx, n_range) { RDIM_SrcFile *src_file = &n->v[n_idx]; RDIM_String8 normalized_path = rdim_lower_from_str8(arena, src_file->path); rdim_bake_name_map_insert(scratch.arena, top, map, 4, normalized_path, rdim_idx_from_src_file(src_file)); } } }break; } } lane_sync(); //- rjf: join & sort if(lane_idx() == 0) { for EachNonZeroEnumVal(RDI_NameMapKind, k) { if(!name_maps_need_build[k]) { continue; } bake_name_maps[k] = rdim_bake_name_map_make(arena, &bake_name_maps_tops[k]); } } lane_sync(); for EachNonZeroEnumVal(RDI_NameMapKind, k) ProfScope("name map join & sort %.*s", str8_varg(rdi_string_from_name_map_kind(k))) { if(!name_maps_need_build[k]) { continue; } RDIM_BakeNameMapTopology *top = &bake_name_maps_tops[k]; RDIM_BakeNameMap *map = bake_name_maps[k]; //- rjf: join ProfScope("join") { Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { for EachIndex(src_lane_idx, lane_count()) { RDIM_BakeNameMap *src_map = lane_maps[k][src_lane_idx]; RDIM_BakeNameMap *dst_map = map; if(dst_map->slots[slot_idx] == 0 && src_map->slots[slot_idx] != 0) { dst_map->slots[slot_idx] = src_map->slots[slot_idx]; } else if(dst_map->slots[slot_idx] != 0 && src_map->slots[slot_idx] != 0) { rdim_bake_name_chunk_list_concat_in_place(dst_map->slots[slot_idx], src_map->slots[slot_idx]); } } } } //- rjf: sort ProfScope("sort") { Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { if(map->slots[slot_idx] != 0) { RDIM_BakeNameChunkList *scratch_og_unsorted = map->slots[slot_idx]; map->slots[slot_idx] = push_array(arena, RDIM_BakeNameChunkList, 1); *map->slots[slot_idx] = rdim_bake_name_chunk_list_sorted_from_unsorted(arena, scratch_og_unsorted); } } } } lane_sync(); scratch_end(scratch); } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage build index runs // B32 need_index_runs = (!!(params->subset_flags & RDIM_SubsetFlag_NameMaps) || !!(params->subset_flags & RDIM_SubsetFlag_Types)); if(need_index_runs) ProfScope("build index runs") { Temp scratch = scratch_begin(&arena, 1); //- rjf: set up per-lane outputs RDIM_BakeIdxRunMapTopology *top = 0; RDIM_BakeIdxRunMapLoose **lane_maps__loose = 0; RDIM_BakeIdxRunMapLoose *map__loose = 0; if(lane_idx() == 0) ProfScope("set up per-lane outputs") { top = push_array(scratch.arena, RDIM_BakeIdxRunMapTopology, 1); top->slots_count = 64 + ((params->procedures.total_count + params->global_variables.total_count + params->thread_variables.total_count + params->udts.total_count) * 3) / 4; lane_maps__loose = push_array(scratch.arena, RDIM_BakeIdxRunMapLoose *, lane_count()); map__loose = rdim_bake_idx_run_map_loose_make(scratch.arena, top); } lane_sync_u64(&top, 0); lane_sync_u64(&lane_maps__loose, 0); lane_sync_u64(&map__loose, 0); //- rjf: set up this lane's map ProfScope("set up this lane's map") { lane_maps__loose[lane_idx()] = rdim_bake_idx_run_map_loose_make(scratch.arena, top); } RDIM_BakeIdxRunMapLoose *lane_map = lane_maps__loose[lane_idx()]; //- rjf: wide fill of all index runs ProfScope("fill all lane index run maps") { //- rjf: bake runs of function-type parameter lists ProfScope("bake runs of function-type parameter lists") { for EachNode(n, RDIM_TypeChunkNode, params->types.first) { Rng1U64 range = lane_range(n->count); ProfScope("[%I64u, %I64u)", range.min, range.max) for EachInRange(n_idx, range) { RDIM_Type *type = &n->v[n_idx]; if(type->count == 0) { continue; } if(type->kind == RDI_TypeKind_Function || type->kind == RDI_TypeKind_Method) { RDI_U32 param_idx_run_count = type->count; RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) { param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(type->param_types[idx]); // TODO(rjf): @u64_to_u32 } rdim_bake_idx_run_map_loose_insert(scratch.arena, top, lane_map, 4, param_idx_run, param_idx_run_count); } } } } //- rjf: bake runs of name map match lists for EachNonZeroEnumVal(RDI_NameMapKind, k) ProfScope("bake runs of name map match lists (%.*s)", str8_varg(rdi_string_from_name_map_kind(k))) { if(!name_maps_need_build[k]) { continue; } RDIM_BakeNameMapTopology *name_map_top = &bake_name_maps_tops[k]; RDIM_BakeNameMap *name_map = bake_name_maps[k]; Rng1U64 slot_idx_range = lane_range(name_map_top->slots_count); for EachInRange(slot_idx, slot_idx_range) { RDIM_BakeNameChunkList *slot = name_map->slots[slot_idx]; if(slot != 0) { typedef struct IdxRunNode IdxRunNode; struct IdxRunNode { IdxRunNode *next; RDI_U64 idx; }; IdxRunNode *first_idx_run_node = 0; IdxRunNode *last_idx_run_node = 0; U64 active_idx_count = 0; String8 active_string = {0}; RDIM_BakeNameChunkNode *n = slot->first; U64 n_idx = 0; for(;;) { // rjf: advance chunk if(n != 0 && n_idx >= n->count) { n = n->next; n_idx = 0; } // rjf: grab next element String8 string = {0}; U64 idx = 0; if(n != 0) { string = n->v[n_idx].string; idx = n->v[n_idx].idx; } // rjf: next element hash doesn't match the active? -> push index run, clear active list, start new list if(!str8_match(string, active_string, 0)) { if(active_idx_count > 1) { RDI_U64 idxs_count = active_idx_count; RDI_U32 *idxs = rdim_push_array(arena, RDI_U32, idxs_count); { U64 write_idx = 0; for EachNode(idx_run_n, IdxRunNode, first_idx_run_node) { idxs[write_idx] = (RDI_U32)idx_run_n->idx; // TODO(rjf): @u64_to_u32 write_idx += 1; } } rdim_bake_idx_run_map_loose_insert(scratch.arena, top, lane_map, 4, idxs, idxs_count); } active_string = string; first_idx_run_node = 0; last_idx_run_node = 0; active_idx_count = 0; } // rjf: new element matches the active list -> push if(active_string.size != 0 && str8_match(string, active_string, 0)) { IdxRunNode *idx_run_n = push_array(scratch.arena, IdxRunNode, 1); idx_run_n->idx = idx; SLLQueuePush(first_idx_run_node, last_idx_run_node, idx_run_n); active_idx_count += 1; } // rjf: advance index n_idx += 1; // rjf: end on zero node if(n == 0) { break; } } } } } } lane_sync(); //- rjf: join ProfScope("join") { Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { for EachIndex(src_lane_idx, lane_count()) { RDIM_BakeIdxRunMapLoose *src_map = lane_maps__loose[src_lane_idx]; RDIM_BakeIdxRunMapLoose *dst_map = map__loose; dst_map->slots_idx_counts[slot_idx] += src_map->slots_idx_counts[slot_idx]; if(dst_map->slots[slot_idx] == 0 && src_map->slots[slot_idx] != 0) { dst_map->slots[slot_idx] = src_map->slots[slot_idx]; } else if(dst_map->slots[slot_idx] != 0 && src_map->slots[slot_idx] != 0) { rdim_bake_idx_run_chunk_list_concat_in_place(dst_map->slots[slot_idx], src_map->slots[slot_idx]); } } } } lane_sync(); //- rjf: sort ProfScope("sort") { RDIM_BakeIdxRunMapLoose *map = map__loose; Rng1U64 slot_range = lane_range(top->slots_count); for EachInRange(slot_idx, slot_range) { if(map->slots[slot_idx] != 0) { *map->slots[slot_idx] = rdim_bake_idx_run_chunk_list_sorted_from_unsorted(arena, map->slots[slot_idx]); map->slots_idx_counts[slot_idx] = 0; for EachNode(n, RDIM_BakeIdxRunChunkNode, map->slots[slot_idx]->first) { for EachIndex(idx, n->count) { map->slots_idx_counts[slot_idx] += n->v[idx].count; } } } } } lane_sync(); //- rjf: tighten idx run table ProfScope("tighten idx run table") { RDIM_BakeIdxRunMapLoose *map = map__loose; if(lane_idx() == 0) ProfScope("calc base indices, set up tight map") { rdim_shared->bake_idx_runs.slots_count = top->slots_count; rdim_shared->bake_idx_runs.slots = rdim_push_array(arena, RDIM_BakeIdxRunChunkList, rdim_shared->bake_idx_runs.slots_count); rdim_shared->bake_idx_runs.slots_base_idxs = rdim_push_array(arena, RDI_U64, rdim_shared->bake_idx_runs.slots_count+1); RDI_U64 encoding_idx_off = 0; for(RDI_U64 slot_idx = 0; slot_idx < top->slots_count; slot_idx += 1) { rdim_shared->bake_idx_runs.slots_base_idxs[slot_idx] = encoding_idx_off; if(map->slots[slot_idx] != 0) { encoding_idx_off += map->slots_idx_counts[slot_idx]; } } rdim_shared->bake_idx_runs.slots_base_idxs[top->slots_count] = encoding_idx_off; } lane_sync(); ProfScope("fill tight map") { Rng1U64 slot_range = lane_range(rdim_shared->bake_idx_runs.slots_count); for EachInRange(idx, slot_range) { if(map->slots[idx] != 0) { rdim_memcpy_struct(&rdim_shared->bake_idx_runs.slots[idx], map->slots[idx]); } } } } lane_sync(); scratch_end(scratch); } lane_sync(); RDIM_BakeIdxRunMap *bake_idx_runs = &rdim_shared->bake_idx_runs; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake strings // ProfScope("bake strings") { // rjf: set up if(lane_idx() == 0) ProfScope("set up; lay out strings") { rdim_shared->baked_strings.string_offs_count = bake_strings->total_count + 1; rdim_shared->baked_strings.string_offs = rdim_push_array(arena, RDI_U32, rdim_shared->baked_strings.string_offs_count); RDI_U64 off_cursor = 0; for EachIndex(slot_idx, bake_strings->slots_count) { for EachNode(n, RDIM_BakeStringChunkNode, bake_strings->slots[slot_idx].first) { for EachIndex(n_idx, n->count) { RDIM_BakeString *src = &n->v[n_idx]; U64 dst_idx = bake_strings->slots_base_idxs[slot_idx] + n->base_idx + n_idx + 1; rdim_shared->baked_strings.string_offs[dst_idx] = off_cursor; off_cursor += src->string.size; } } } rdim_shared->baked_strings.string_data_size = off_cursor; rdim_shared->baked_strings.string_data = rdim_push_array(arena, RDI_U8, rdim_shared->baked_strings.string_data_size); } lane_sync(); // rjf: wide fill string data ProfScope("wide fill") { Rng1U64 slot_idx_range = lane_range(bake_strings->slots_count); for EachInRange(slot_idx, slot_idx_range) { for EachNode(n, RDIM_BakeStringChunkNode, bake_strings->slots[slot_idx].first) { for EachIndex(n_idx, n->count) { RDIM_BakeString *src = &n->v[n_idx]; U64 dst_idx = bake_strings->slots_base_idxs[slot_idx] + n->base_idx + n_idx + 1; U64 dst_off = rdim_shared->baked_strings.string_offs[dst_idx]; rdim_memcpy(rdim_shared->baked_strings.string_data + dst_off, src->string.str, src->string.size); } } } } } lane_sync(); RDIM_StringBakeResult baked_strings = rdim_shared->baked_strings; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake idx runs // if(need_index_runs) ProfScope("bake idx runs") { // rjf: set up if(lane_idx() == 0) { rdim_shared->baked_idx_runs.idx_count = bake_idx_runs->slots_base_idxs[bake_idx_runs->slots_count]; rdim_shared->baked_idx_runs.idx_runs = push_array(arena, RDI_U32, rdim_shared->baked_idx_runs.idx_count); } lane_sync(); // rjf: wide fill { Rng1U64 range = lane_range(bake_idx_runs->slots_count); for EachInRange(slot_idx, range) { RDI_U64 off = bake_idx_runs->slots_base_idxs[slot_idx]; for EachNode(n, RDIM_BakeIdxRunChunkNode, bake_idx_runs->slots[slot_idx].first) { StaticAssert(sizeof(rdim_shared->baked_idx_runs.idx_runs[0]) == sizeof(n->v[0].idxes[0]), idx_run_size_check); for EachIndex(n_idx, n->count) { rdim_memcpy(rdim_shared->baked_idx_runs.idx_runs + off, n->v[n_idx].idxes, sizeof(n->v[n_idx].idxes[0]) * n->v[n_idx].count); off += n->v[n_idx].count; } } } } } lane_sync(); RDIM_IndexRunBakeResult baked_idx_runs = rdim_shared->baked_idx_runs; ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake name maps // ProfScope("bake name maps") { // rjf: count unique names in all name maps; lay out baked nodes ProfScope("count unique names in all name maps; lay out baked nodes") { if(lane_idx() == 0) { for EachNonZeroEnumVal(RDI_NameMapKind, k) { rdim_shared->lane_name_map_node_counts[k] = push_array(arena, U64, lane_count()); rdim_shared->lane_name_map_node_offs[k] = push_array(arena, U64, lane_count()); } } lane_sync(); for EachNonZeroEnumVal(RDI_NameMapKind, k) { if(!name_maps_need_build[k]) { continue; } RDIM_BakeNameMapTopology *top = &bake_name_maps_tops[k]; RDIM_BakeNameMap *map = bake_name_maps[k]; Rng1U64 range = lane_range(top->slots_count); for EachInRange(idx, range) { if(map->slots[idx] != 0) { U64 total_unique_name_count = 0; U64 last_hash = 0; for EachNode(n, RDIM_BakeNameChunkNode, map->slots[idx]->first) { for EachIndex(n_idx, n->count) { if(n->v[n_idx].hash != last_hash) { total_unique_name_count += 1; last_hash = n->v[n_idx].hash; } } } rdim_shared->lane_name_map_node_counts[k][lane_idx()] += total_unique_name_count; } } } lane_sync(); if(lane_idx() == 0) { for EachNonZeroEnumVal(RDI_NameMapKind, k) { RDI_U64 node_off = 0; for EachIndex(l_idx, lane_count()) { rdim_shared->name_map_node_counts[k] += rdim_shared->lane_name_map_node_counts[k][l_idx]; rdim_shared->lane_name_map_node_offs[k][l_idx] = node_off; node_off += rdim_shared->lane_name_map_node_counts[k][l_idx]; } rdim_shared->total_name_map_node_count += rdim_shared->name_map_node_counts[k]; } } } lane_sync(); // rjf: setup ProfScope("setup") { if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->baked_top_level_name_maps.name_maps_count = RDI_NameMapKind_COUNT; rdim_shared->baked_top_level_name_maps.name_maps = push_array(arena, RDI_NameMap, rdim_shared->baked_top_level_name_maps.name_maps_count); RDI_U32 bucket_off = 0; RDI_U32 node_off = 0; for EachNonZeroEnumVal(RDI_NameMapKind, k) { rdim_shared->baked_top_level_name_maps.name_maps[k].bucket_base_idx = bucket_off; rdim_shared->baked_top_level_name_maps.name_maps[k].node_base_idx = node_off; rdim_shared->baked_top_level_name_maps.name_maps[k].bucket_count = (RDI_U32)bake_name_maps_tops[k].slots_count; // TODO(rjf): @u64_to_u32 rdim_shared->baked_top_level_name_maps.name_maps[k].node_count = (RDI_U32)rdim_shared->name_map_node_counts[k]; // TODO(rjf): @u64_to_u32 bucket_off += rdim_shared->baked_top_level_name_maps.name_maps[k].bucket_count; node_off += rdim_shared->baked_top_level_name_maps.name_maps[k].node_count; } rdim_shared->baked_name_maps.buckets_count = bucket_off; rdim_shared->baked_name_maps.buckets = push_array(arena, RDI_NameMapBucket, rdim_shared->baked_name_maps.buckets_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->baked_name_maps.nodes_count = rdim_shared->total_name_map_node_count; rdim_shared->baked_name_maps.nodes = push_array(arena, RDI_NameMapNode, rdim_shared->baked_name_maps.nodes_count); } } lane_sync(); // rjf: wide fill baked name maps ProfScope("wide fill baked name maps") { for EachNonZeroEnumVal(RDI_NameMapKind, k) ProfScope("wide fill (%.*s)", str8_varg(rdi_string_from_name_map_kind(k))) { if(!name_maps_need_build[k]) { continue; } RDI_U64 write_node_off = rdim_shared->lane_name_map_node_offs[k][lane_idx()]; RDIM_BakeNameMapTopology *top = &bake_name_maps_tops[k]; U64 slots_count = top->slots_count; RDIM_BakeNameMap *src_map = bake_name_maps[k]; RDI_NameMap *dst_map = &rdim_shared->baked_top_level_name_maps.name_maps[k]; RDI_NameMapBucket *dst_buckets = rdim_shared->baked_name_maps.buckets + dst_map->bucket_base_idx; RDI_NameMapNode *dst_nodes = rdim_shared->baked_name_maps.nodes + dst_map->node_base_idx; Rng1U64 slot_range = lane_range(slots_count); for EachInRange(slot_idx, slot_range) { RDIM_BakeNameChunkList *src_slot = src_map->slots[slot_idx]; if(src_slot == 0) { continue; } RDI_NameMapBucket *dst_bucket = &dst_buckets[slot_idx]; dst_bucket->first_node = write_node_off; { Temp scratch = scratch_begin(&arena, 1); typedef struct IdxRunNode IdxRunNode; struct IdxRunNode { IdxRunNode *next; RDI_U64 idx; }; IdxRunNode *first_idx_run_node = 0; IdxRunNode *last_idx_run_node = 0; U64 active_idx_count = 0; String8 active_string = {0}; RDIM_BakeNameChunkNode *n = src_slot->first; U64 n_idx = 0; for(;;) { // rjf: advance chunk if(n != 0 && n_idx >= n->count) { n = n->next; n_idx = 0; } // rjf: grab next element U64 idx = 0; String8 string = {0}; if(n != 0) { idx = n->v[n_idx].idx; string = n->v[n_idx].string; } // rjf: next element doesn't match the active list? -> push index run, clear active list, start new list if(!str8_match(active_string, string, 0)) { // rjf: has active run -> flatten & serialize if(active_string.size != 0) { // rjf: flatten idxes RDI_U64 idxs_count = active_idx_count; RDI_U32 *idxs = rdim_push_array(scratch.arena, RDI_U32, idxs_count); { U64 write_idx = 0; for EachNode(idx_run_n, IdxRunNode, first_idx_run_node) { idxs[write_idx] = (RDI_U32)idx_run_n->idx; // TODO(rjf): @u64_to_u32 write_idx += 1; } } // rjf: serialize node RDI_NameMapNode *dst_node = &dst_nodes[write_node_off]; dst_node->string_idx = rdim_bake_idx_from_string(bake_strings, active_string); dst_node->match_count = idxs_count; if(dst_node->match_count == 1) { dst_node->match_idx_or_idx_run_first = idxs[0]; } else if(dst_node->match_count > 1) { dst_node->match_idx_or_idx_run_first = rdim_bake_idx_from_idx_run(bake_idx_runs, idxs, idxs_count); } dst_bucket->node_count += 1; write_node_off += 1; } // rjf: start new list active_string = string; first_idx_run_node = 0; last_idx_run_node = 0; active_idx_count = 0; temp_end(scratch); } // rjf: hash matches the active list -> push if(active_string.size != 0 && str8_match(active_string, string, 0)) { IdxRunNode *idx_run_n = push_array(scratch.arena, IdxRunNode, 1); idx_run_n->idx = idx; SLLQueuePush(first_idx_run_node, last_idx_run_node, idx_run_n); active_idx_count += 1; } // rjf: advance index n_idx += 1; // rjf: end on zero node if(n == 0) { break; } } scratch_end(scratch); } } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage gather line-bucketed src line map data // ProfScope("gather line-bucketed src line map data") { if(lane_idx() == 0) { rdim_shared->bake_src_line_maps = push_array(arena, RDIM_BakeSrcLineMap, params->src_files.total_count); } lane_sync(); { for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { U64 file_idx = n->base_idx + n_idx; RDIM_BakeSrcLineMap *map = &rdim_shared->bake_src_line_maps[file_idx]; // rjf: set up map map->slots_count = n->v[n_idx].total_line_count; map->slots = push_array(arena, RDIM_BakeSrcLineMapSlot, map->slots_count); // rjf: gather line-bucketed info for EachNode(frag, RDIM_SrcFileLineMapFragment, n->v[n_idx].first_line_map_fragment) { RDIM_LineSequence *seq = frag->seq; for EachIndex(idx, seq->line_count) { RDI_U32 line_num = seq->line_nums[idx]; RDI_U64 voff_first = seq->voffs[idx]; RDI_U64 voff_opl = seq->voffs[idx+1]; RDI_U64 slot_idx = line_num%map->slots_count; // rjf: find existing line node RDIM_BakeSrcLineMapNode *line_node = 0; { for EachNode(line_n, RDIM_BakeSrcLineMapNode, map->slots[slot_idx].first) { if(line_n->line_num == line_num) { line_node = line_n; break; } } } // rjf: construct new node if unseen if(line_node == 0) { line_node = push_array(arena, RDIM_BakeSrcLineMapNode, 1); SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, line_node); line_node->line_num = line_num; map->line_count += 1; } // rjf: push this voff range RDIM_Rng1U64 voff_range = {voff_first, voff_opl}; rdim_rng1u64_list_push(arena, &line_node->voff_ranges, voff_range); map->voff_range_count += 1; } } } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage sort line-bucketed src line map data // ProfScope("sort line-bucketed src line map data") { U64 map_count = params->src_files.total_count; if(lane_idx() == 0) { rdim_shared->bake_src_line_map_keys = push_array(arena, RDIM_SortKey *, map_count); } lane_sync(); for(;;) { U64 map_num = ins_atomic_u64_inc_eval(&rdim_shared->bake_src_line_map_take_counter); if(map_num < 1 || map_count < map_num) { break; } U64 map_idx = map_num-1; RDIM_BakeSrcLineMap *map = &rdim_shared->bake_src_line_maps[map_idx]; // rjf: gather keys rdim_shared->bake_src_line_map_keys[map_idx] = push_array_no_zero(arena, RDIM_SortKey, map->line_count); RDIM_SortKey *keys = rdim_shared->bake_src_line_map_keys[map_idx]; { U64 key_idx = 0; for EachIndex(slot_idx, map->slots_count) { for EachNode(n, RDIM_BakeSrcLineMapNode, map->slots[slot_idx].first) { keys[key_idx].key = n->line_num; keys[key_idx].val = n; key_idx += 1; } } } // rjf: sort keys { radsort(keys, map->line_count, rdim_sort_key_is_before); } } } ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage compute src file / src file line map layout // ProfScope("compute src file / src file line map layout") { // rjf: set up if(lane_idx() == 0) { rdim_shared->lane_chunk_src_file_num_counts = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_voff_counts = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_map_counts = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_num_offs = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_voff_offs = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_map_offs = push_array(arena, U64, lane_count()*params->src_files.chunk_count); for EachEnumVal(RDI_ChecksumKind, k) { rdim_shared->lane_chunk_src_file_checksum_counts[k] = push_array(arena, U64, lane_count()*params->src_files.chunk_count); rdim_shared->lane_chunk_src_file_checksum_offs[k] = push_array(arena, U64, lane_count()*params->src_files.chunk_count); } } lane_sync(); // rjf: wide count { U64 chunk_idx = 0; for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { Rng1U64 range = lane_range(n->count); U64 slot_idx = lane_idx()*params->src_files.chunk_count + chunk_idx; for EachInRange(idx, range) { RDIM_BakeSrcLineMap *map = &rdim_shared->bake_src_line_maps[n->base_idx + idx]; rdim_shared->lane_chunk_src_file_num_counts[slot_idx] += map->line_count; rdim_shared->lane_chunk_src_file_voff_counts[slot_idx] += map->voff_range_count; rdim_shared->lane_chunk_src_file_map_counts[slot_idx] += !!map->line_count; RDI_ChecksumKind k = n->v[idx].checksum_kind; String8 val = n->v[idx].checksum; if(RDI_ChecksumKind_NULL < k && k < RDI_ChecksumKind_COUNT && val.size != 0) { rdim_shared->lane_chunk_src_file_checksum_counts[k][slot_idx] += 1; } } chunk_idx += 1; } } lane_sync(); // rjf: layout if(lane_idx() == 0) { U64 chunk_idx = 0; U64 num_layout_off = 0; U64 voff_layout_off = 0; U64 map_layout_off = 1; U64 checksum_layout_offs[RDI_ChecksumKind_COUNT] = {0}; for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->src_files.chunk_count + chunk_idx; rdim_shared->lane_chunk_src_file_num_offs[slot_idx] = num_layout_off; rdim_shared->lane_chunk_src_file_voff_offs[slot_idx] = voff_layout_off; rdim_shared->lane_chunk_src_file_map_offs[slot_idx] = map_layout_off; num_layout_off += rdim_shared->lane_chunk_src_file_num_counts[slot_idx]; voff_layout_off += rdim_shared->lane_chunk_src_file_voff_counts[slot_idx]; map_layout_off += rdim_shared->lane_chunk_src_file_map_counts[slot_idx]; for EachEnumVal(RDI_ChecksumKind, k) { rdim_shared->lane_chunk_src_file_checksum_offs[k][slot_idx] = checksum_layout_offs[k]; checksum_layout_offs[k] += rdim_shared->lane_chunk_src_file_checksum_counts[k][slot_idx]; } } chunk_idx += 1; } rdim_shared->total_src_map_line_count = num_layout_off; rdim_shared->total_src_map_voff_count = voff_layout_off; for EachEnumVal(RDI_ChecksumKind, k) { rdim_shared->total_checksum_counts[k] = checksum_layout_offs[k]; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake src files // ProfScope("bake src files") { //- rjf: set up if(lane_idx() == 0) { rdim_shared->baked_src_files.source_files_count = params->src_files.total_count+1; rdim_shared->baked_src_files.source_files = push_array(arena, RDI_SourceFile, rdim_shared->baked_src_files.source_files_count); rdim_shared->baked_src_files.source_line_maps_count = params->src_files.source_line_map_count+1; rdim_shared->baked_src_files.source_line_maps = push_array(arena, RDI_SourceLineMap, rdim_shared->baked_src_files.source_line_maps_count); rdim_shared->baked_src_files.source_line_map_nums_count = rdim_shared->total_src_map_line_count; rdim_shared->baked_src_files.source_line_map_nums = push_array(arena, RDI_U32, rdim_shared->baked_src_files.source_line_map_nums_count); rdim_shared->baked_src_files.source_line_map_rngs_count = rdim_shared->total_src_map_line_count + rdim_shared->baked_src_files.source_line_maps_count; rdim_shared->baked_src_files.source_line_map_rngs = push_array(arena, RDI_U32, rdim_shared->baked_src_files.source_line_map_rngs_count); rdim_shared->baked_src_files.source_line_map_voffs_count = rdim_shared->total_src_map_voff_count; rdim_shared->baked_src_files.source_line_map_voffs = push_array(arena, RDI_U64, rdim_shared->baked_src_files.source_line_map_voffs_count); } lane_sync(); //- rjf: bake U64 chunk_idx = 0; for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { Rng1U64 range = lane_range(n->count); U64 slot_idx = lane_idx()*params->src_files.chunk_count + chunk_idx; U64 dst_num_off = rdim_shared->lane_chunk_src_file_num_offs[slot_idx]; U64 dst_map_off = rdim_shared->lane_chunk_src_file_map_offs[slot_idx]; U64 dst_voff_off = rdim_shared->lane_chunk_src_file_voff_offs[slot_idx]; U64 dst_rng_off = dst_num_off + dst_map_off; U64 dst_checksums_off[RDI_ChecksumKind_COUNT] = {0}; for EachEnumVal(RDI_ChecksumKind, k) { dst_checksums_off[k] = 1 + rdim_shared->lane_chunk_src_file_checksum_offs[k][slot_idx]; } for EachInRange(idx, range) { RDIM_BakeSrcLineMap *map = &rdim_shared->bake_src_line_maps[n->base_idx + idx]; RDIM_SortKey *sorted_map_keys = rdim_shared->bake_src_line_map_keys[n->base_idx + idx]; RDIM_SrcFile *src = &n->v[idx]; RDI_SourceFile *dst = &rdim_shared->baked_src_files.source_files[n->base_idx + idx + 1]; RDI_SourceLineMap *dst_map = &rdim_shared->baked_src_files.source_line_maps[dst_map_off]; RDI_U32 *dst_nums = &rdim_shared->baked_src_files.source_line_map_nums[dst_num_off]; RDI_U32 *dst_rngs = &rdim_shared->baked_src_files.source_line_map_rngs[dst_rng_off]; RDI_U64 *dst_voffs = &rdim_shared->baked_src_files.source_line_map_voffs[dst_voff_off]; //- rjf: fill file info Temp scratch = scratch_begin(&arena, 1); String8 normalized_path = rdim_lower_from_str8(scratch.arena, src->path); B32 has_checksum = (RDI_ChecksumKind_NULL < src->checksum_kind && src->checksum_kind < RDI_ChecksumKind_COUNT && src->checksum.size != 0); dst->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src->path); dst->normal_full_path_string_idx = rdim_bake_idx_from_string(bake_strings, normalized_path); dst->source_line_map_idx = src->total_line_count ? dst_map_off : 0; dst->checksum_kind = src->checksum_kind; dst->checksum_idx = has_checksum ? dst_checksums_off[dst->checksum_kind] : 0; scratch_end(scratch); //- rjf: advance checksum offset for this kind if(has_checksum) { dst_checksums_off[dst->checksum_kind] += 1; } //- rjf: fill map info if(src->total_line_count != 0) { dst_map->line_count = (RDI_U32)map->line_count; // TODO(rjf): @u64_to_u32 dst_map->voff_count = (RDI_U32)map->voff_range_count; // TODO(rjf): @u64_to_u32 dst_map->line_map_nums_base_idx = (RDI_U32)dst_num_off; // TODO(rjf): @u64_to_u32 dst_map->line_map_range_base_idx = (RDI_U32)dst_rng_off; // TODO(rjf): @u64_to_u32 dst_map->line_map_voff_base_idx = (RDI_U32)dst_voff_off; // TODO(rjf): @u64_to_u32 dst_map_off += 1; } //- rjf: fill nums/ranges/voffs info if(src->total_line_count != 0) { U64 *dst_voff_ptr = dst_voffs; for EachIndex(line_num_idx, map->line_count) { dst_nums[line_num_idx] = (RDI_U32)sorted_map_keys[line_num_idx].key; // TODO(rjf): @u64_to_u32 dst_rngs[line_num_idx] = (RDI_U32)(dst_voff_ptr - dst_voffs); // TODO(rjf): @u64_to_u32 RDIM_BakeSrcLineMapNode *node = (RDIM_BakeSrcLineMapNode *)sorted_map_keys[line_num_idx].val; for EachNode(rng_n, RDIM_Rng1U64Node, node->voff_ranges.first) { dst_voff_ptr[0] = rng_n->v.min; dst_voff_ptr += 1; } } dst_rngs[map->line_count] = (RDI_U32)map->voff_range_count; // TODO(rjf): @u64_to_u32 dst_num_off += map->line_count; dst_rng_off += map->line_count+1; dst_voff_off += map->voff_range_count; } } chunk_idx += 1; } } ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake checksums // ProfScope("bake checksums") { // rjf: allocate if(lane_idx() == 0) { rdim_shared->baked_checksums.md5s_count = rdim_shared->total_checksum_counts[RDI_ChecksumKind_MD5] + 1; rdim_shared->baked_checksums.sha1s_count = rdim_shared->total_checksum_counts[RDI_ChecksumKind_SHA1] + 1; rdim_shared->baked_checksums.sha256s_count = rdim_shared->total_checksum_counts[RDI_ChecksumKind_SHA256] + 1; rdim_shared->baked_checksums.timestamps_count = rdim_shared->total_checksum_counts[RDI_ChecksumKind_Timestamp] + 1; rdim_shared->baked_checksums.md5s = push_array(arena, RDI_MD5, rdim_shared->baked_checksums.md5s_count); rdim_shared->baked_checksums.sha1s = push_array(arena, RDI_SHA1, rdim_shared->baked_checksums.sha1s_count); rdim_shared->baked_checksums.sha256s = push_array(arena, RDI_SHA256, rdim_shared->baked_checksums.sha256s_count); rdim_shared->baked_checksums.timestamps = push_array(arena, RDI_U64, rdim_shared->baked_checksums.timestamps_count); } lane_sync(); // rjf: fill { U64 chunk_idx = 0; for EachNode(n, RDIM_SrcFileChunkNode, params->src_files.first) { Rng1U64 range = lane_range(n->count); U64 slot_idx = lane_idx()*params->src_files.chunk_count + chunk_idx; U64 dst_offs[RDI_ChecksumKind_COUNT] = {0}; for EachEnumVal(RDI_ChecksumKind, k) { dst_offs[k] = 1 + rdim_shared->lane_chunk_src_file_checksum_offs[k][slot_idx]; } for EachInRange(n_idx, range) { RDI_ChecksumKind k = n->v[n_idx].checksum_kind; String8 val = n->v[n_idx].checksum; if(RDI_ChecksumKind_NULL < k && k < RDI_ChecksumKind_COUNT && val.size != 0) { switch((RDI_ChecksumKindEnum)k) { case RDI_ChecksumKind_NULL: case RDI_ChecksumKind_COUNT: {}break; #define Case(name, table_name) case RDI_ChecksumKind_##name:{MemoryCopy(&rdim_shared->baked_checksums.table_name[dst_offs[k]], val.str, Min(val.size, sizeof(rdim_shared->baked_checksums.table_name[0])));}break Case(MD5, md5s); Case(SHA1, sha1s); Case(SHA256, sha256s); Case(Timestamp, timestamps); #undef Case } dst_offs[k] += 1; } } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage compute lane UDT member/enum-val layouts // ProfScope("compute lane UDT member/enum-val layouts") { // rjf: allocate if(lane_idx() == 0) { rdim_shared->member_chunk_lane_counts = push_array(arena, U64, lane_count() * params->udts.chunk_count); rdim_shared->member_chunk_lane_offs = push_array(arena, U64, lane_count() * params->udts.chunk_count); rdim_shared->enum_val_chunk_lane_counts = push_array(arena, U64, lane_count() * params->udts.chunk_count); rdim_shared->enum_val_chunk_lane_offs = push_array(arena, U64, lane_count() * params->udts.chunk_count); } lane_sync(); // rjf: count { U64 chunk_idx = 0; for EachNode(n, RDIM_UDTChunkNode, params->udts.first) { Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { U64 slot_idx = lane_idx()*params->udts.chunk_count + chunk_idx; rdim_shared->member_chunk_lane_counts[slot_idx] += n->v[idx].member_count; rdim_shared->enum_val_chunk_lane_counts[slot_idx] += n->v[idx].enum_val_count; } chunk_idx += 1; } } lane_sync(); // rjf: layout if(lane_idx() == 0) { U64 member_layout_off = 1; U64 enum_val_layout_off = 1; U64 chunk_idx = 0; for EachNode(n, RDIM_UDTChunkNode, params->udts.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->udts.chunk_count + chunk_idx; rdim_shared->member_chunk_lane_offs[slot_idx] = member_layout_off; rdim_shared->enum_val_chunk_lane_offs[slot_idx] = enum_val_layout_off; member_layout_off += rdim_shared->member_chunk_lane_counts[slot_idx]; enum_val_layout_off += rdim_shared->enum_val_chunk_lane_counts[slot_idx]; } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake UDTs // ProfScope("bake UDTs") { //- rjf: set up ProfScope("set up") { if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->baked_udts.udts_count = params->udts.total_count+1; rdim_shared->baked_udts.udts = push_array(arena, RDI_UDT, rdim_shared->baked_udts.udts_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->baked_udts.members_count = params->udts.total_member_count+1; rdim_shared->baked_udts.members = push_array(arena, RDI_Member, rdim_shared->baked_udts.members_count); } if(lane_idx() == lane_from_task_idx(2)) { rdim_shared->baked_udts.enum_members_count = params->udts.total_enum_val_count+1; rdim_shared->baked_udts.enum_members = push_array(arena, RDI_EnumMember, rdim_shared->baked_udts.enum_members_count); } } lane_sync(); //- rjf: bake UDTs ProfScope("bake UDTs") { U64 chunk_idx = 0; for EachNode(n, RDIM_UDTChunkNode, params->udts.first) { Rng1U64 range = lane_range(n->count); U64 layout_slot_idx = lane_idx()*params->udts.chunk_count + chunk_idx; U64 member_layout_off = rdim_shared->member_chunk_lane_offs[layout_slot_idx]; U64 enum_val_layout_off = rdim_shared->enum_val_chunk_lane_offs[layout_slot_idx]; for EachInRange(n_idx, range) { RDIM_UDT *src_udt = &n->v[n_idx]; RDI_UDT *dst_udt = &rdim_shared->baked_udts.udts[n->base_idx + n_idx + 1]; //- rjf: fill basics dst_udt->self_type_idx = (RDI_U32)rdim_idx_from_type(src_udt->self_type); // TODO(rjf): @u64_to_u32 dst_udt->file_idx = (RDI_U32)rdim_idx_from_src_file(src_udt->src_file); // TODO(rjf): @u64_to_u32 dst_udt->line = src_udt->line; dst_udt->col = src_udt->col; //- rjf: fill member info if(src_udt->first_member != 0) { U64 member_off_first = member_layout_off; for EachNode(src_member, RDIM_UDTMember, src_udt->first_member) { RDI_Member *dst_member = &rdim_shared->baked_udts.members[member_layout_off]; dst_member->kind = src_member->kind; dst_member->name_string_idx = rdim_bake_idx_from_string(bake_strings, src_member->name); dst_member->type_idx = (RDI_U32)rdim_idx_from_type(src_member->type); // TODO(rjf): @u64_to_u32 dst_member->off = src_member->off; member_layout_off += 1; } U64 member_off_opl = member_layout_off; dst_udt->member_first = (RDI_U32)member_off_first; // TODO(rjf): @u64_to_u32 dst_udt->member_count = (RDI_U32)(member_off_opl - member_off_first); // TODO(rjf): @u64_to_u32 } //- rjf: fill enum val info else if(src_udt->first_enum_val != 0) { U64 enum_val_off_first = enum_val_layout_off; for EachNode(src_enum_val, RDIM_UDTEnumVal, src_udt->first_enum_val) { RDI_EnumMember *dst_member = &rdim_shared->baked_udts.enum_members[enum_val_layout_off]; dst_member->name_string_idx = rdim_bake_idx_from_string(bake_strings, src_enum_val->name); dst_member->val = src_enum_val->val; enum_val_layout_off += 1; } U64 enum_val_off_opl = enum_val_layout_off; dst_udt->flags |= RDI_UDTFlag_EnumMembers; dst_udt->member_first = (RDI_U32)enum_val_off_first; // TODO(rjf): @u64_to_u32 dst_udt->member_count = (RDI_U32)(enum_val_off_opl - enum_val_off_first); // TODO(rjf): @u64_to_u32 } } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage compute lane location block layout // U64 total_location_case_chunk_count = (params->scopes.chunk_count + params->procedures.chunk_count); ProfScope("compute lane location block layout") { // rjf: set up if(lane_idx() == 0) { rdim_shared->location_case_chunk_lane_counts = push_array(arena, RDI_U64, lane_count() * total_location_case_chunk_count); rdim_shared->location_case_chunk_lane_offs = push_array(arena, RDI_U64, lane_count() * total_location_case_chunk_count); } lane_sync(); // rjf: per-chunk-lane count of location cases { // rjf: count location cases in scopes U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { U64 slot_idx = lane_idx() * total_location_case_chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { for EachNode(local, RDIM_Local, n->v[idx].first_local) { rdim_shared->location_case_chunk_lane_counts[slot_idx] += local->location_cases.count; } } chunk_idx += 1; } // rjf: count location cases in procedures for EachNode(n, RDIM_SymbolChunkNode, params->procedures.first) { U64 slot_idx = lane_idx() * total_location_case_chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { rdim_shared->location_case_chunk_lane_counts[slot_idx] += n->v[idx].location_cases.count; } chunk_idx += 1; } } lane_sync(); // rjf: lay out location case offsets if(lane_idx() == 0) { U64 chunk_idx = 0; U64 location_case_layout_off = 1; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx * total_location_case_chunk_count + chunk_idx; rdim_shared->location_case_chunk_lane_offs[slot_idx] = location_case_layout_off; location_case_layout_off += rdim_shared->location_case_chunk_lane_counts[slot_idx]; } chunk_idx += 1; } for EachNode(n, RDIM_SymbolChunkNode, params->procedures.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx * total_location_case_chunk_count + chunk_idx; rdim_shared->location_case_chunk_lane_offs[slot_idx] = location_case_layout_off; location_case_layout_off += rdim_shared->location_case_chunk_lane_counts[slot_idx]; } chunk_idx += 1; } rdim_shared->total_location_case_count = location_case_layout_off; } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake location blocks // ProfScope("bake location blocks") { // rjf: set up if(lane_idx() == 0) { rdim_shared->baked_location_blocks.location_blocks_count = rdim_shared->total_location_case_count; rdim_shared->baked_location_blocks.location_blocks = push_array(arena, RDI_LocationBlock, rdim_shared->baked_location_blocks.location_blocks_count); } lane_sync(); // rjf: wide fill from scopes U64 chunk_idx = 0; ProfScope("wide fill from scopes") { for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { U64 layout_slot_idx = lane_idx() * total_location_case_chunk_count + chunk_idx; U64 layout_off = rdim_shared->location_case_chunk_lane_offs[layout_slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { for EachNode(local, RDIM_Local, n->v[idx].first_local) { for EachNode(src, RDIM_LocationCase, local->location_cases.first) { RDI_LocationBlock *dst = &rdim_shared->baked_location_blocks.location_blocks[layout_off]; dst->scope_off_first = (RDI_U32)src->voff_range.min; // TODO(rjf): @u64_to_u32 dst->scope_off_opl = (RDI_U32)src->voff_range.max; // TODO(rjf): @u64_to_u32 dst->location_data_off = (RDI_U32)rdim_off_from_location(src->location); // TODO(rjf): @u64_to_u32 layout_off += 1; } } } chunk_idx += 1; } } // rjf: wide fill from procedures ProfScope("wide fill from procedures") { for EachNode(n, RDIM_SymbolChunkNode, params->procedures.first) { U64 layout_slot_idx = lane_idx() * total_location_case_chunk_count + chunk_idx; U64 layout_off = rdim_shared->location_case_chunk_lane_offs[layout_slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { for EachNode(src, RDIM_LocationCase, n->v[idx].location_cases.first) { RDI_LocationBlock *dst = &rdim_shared->baked_location_blocks.location_blocks[layout_off]; dst->scope_off_first = (RDI_U32)src->voff_range.min; // TODO(rjf): @u64_to_u32 dst->scope_off_opl = (RDI_U32)src->voff_range.max; // TODO(rjf): @u64_to_u32 dst->location_data_off = (RDI_U32)rdim_off_from_location(src->location); // TODO(rjf): @u64_to_u32 layout_off += 1; } } chunk_idx += 1; } } } ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake locations // ProfScope("bake locations") { if(lane_idx() == 0) { rdim_shared->baked_locations.location_data_size = params->locations.total_encoded_size+1; rdim_shared->baked_locations.location_data = push_array(arena, RDI_U8, rdim_shared->baked_locations.location_data_size); } lane_sync(); for EachNode(n, RDIM_LocationChunkNode, params->locations.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Location *loc = &n->v[n_idx]; RDI_U8 *dst = &rdim_shared->baked_locations.location_data[n->base_encoding_off + loc->relative_encoding_off + 1]; switch((RDI_LocationKindEnum)loc->info.kind) { case RDI_LocationKind_NULL:{}break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { MemoryCopy(dst+0, &loc->info.kind, sizeof(loc->info.kind)); RDI_U64 write_off = sizeof(loc->info.kind); for EachNode(op_node, RDIM_EvalBytecodeOp, loc->info.bytecode.first_op) { MemoryCopy(dst + write_off, &op_node->op, 1); write_off += 1; MemoryCopy(dst + write_off, &op_node->p, op_node->p_size); write_off += op_node->p_size; } dst[write_off] = 0; }break; case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { RDI_LocationRegPlusU16 baked = {loc->info.kind, loc->info.reg_code, loc->info.offset}; MemoryCopy(dst, &baked, sizeof(baked)); }break; case RDI_LocationKind_ValReg: { RDI_LocationReg baked = {loc->info.kind, loc->info.reg_code}; MemoryCopy(dst, &baked, sizeof(baked)); }break; } } } } ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage compute layout for scope sub-lists (locals / voffs) // ProfScope("compute layout for scope sub-lists (locals / voffs)") { // rjf: set up if(lane_idx() == 0) { rdim_shared->scope_local_chunk_lane_counts = push_array(arena, RDI_U64, lane_count() * params->scopes.chunk_count); rdim_shared->scope_local_chunk_lane_offs = push_array(arena, RDI_U64, lane_count() * params->scopes.chunk_count); rdim_shared->scope_voff_chunk_lane_counts = push_array(arena, RDI_U64, lane_count() * params->scopes.chunk_count); rdim_shared->scope_voff_chunk_lane_offs = push_array(arena, RDI_U64, lane_count() * params->scopes.chunk_count); } lane_sync(); // rjf: count per-lane-chunk { U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { U64 num_locals_in_this_lane_and_node = 0; U64 num_voffs_in_this_lane_and_node = 0; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { num_locals_in_this_lane_and_node += n->v[n_idx].local_count; num_voffs_in_this_lane_and_node += n->v[n_idx].voff_ranges.count*2; } rdim_shared->scope_local_chunk_lane_counts[lane_idx()*params->scopes.chunk_count + chunk_idx] = num_locals_in_this_lane_and_node; rdim_shared->scope_voff_chunk_lane_counts[lane_idx()*params->scopes.chunk_count + chunk_idx] = num_voffs_in_this_lane_and_node; chunk_idx += 1; } } lane_sync(); // rjf: lay out each lane's range if(lane_idx() == 0) { U64 local_layout_off = 1; U64 voff_layout_off = 1; U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->scopes.chunk_count + chunk_idx; rdim_shared->scope_local_chunk_lane_offs[slot_idx] = local_layout_off; rdim_shared->scope_voff_chunk_lane_offs[slot_idx] = voff_layout_off; local_layout_off += rdim_shared->scope_local_chunk_lane_counts[slot_idx]; voff_layout_off += rdim_shared->scope_voff_chunk_lane_counts[slot_idx]; } chunk_idx += 1; } } lane_sync(); } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake scopes // ProfScope("bake scopes") { //- rjf: setup outputs if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->baked_scopes.scopes_count = params->scopes.total_count+1; rdim_shared->baked_scopes.scopes = push_array(arena, RDI_Scope, rdim_shared->baked_scopes.scopes_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->baked_scopes.scope_voffs_count = params->scopes.scope_voff_count+1; rdim_shared->baked_scopes.scope_voffs = push_array(arena, RDI_U64, rdim_shared->baked_scopes.scope_voffs_count); } if(lane_idx() == lane_from_task_idx(2)) { rdim_shared->baked_scopes.locals_count = params->scopes.local_count+1; rdim_shared->baked_scopes.locals = push_array(arena, RDI_Local, rdim_shared->baked_scopes.locals_count); } lane_sync(); //- rjf: wide fill { U64 chunk_idx = 0; for EachNode(n, RDIM_ScopeChunkNode, params->scopes.first) { Rng1U64 range = lane_range(n->count); U64 scope_chunk_lane_slot_idx = lane_idx()*params->scopes.chunk_count + chunk_idx; U64 chunk_local_off = rdim_shared->scope_local_chunk_lane_offs[scope_chunk_lane_slot_idx]; U64 chunk_voff_off = rdim_shared->scope_voff_chunk_lane_offs[scope_chunk_lane_slot_idx]; U64 location_block_chunk_lane_slot_idx = lane_idx() * total_location_case_chunk_count + chunk_idx; U64 chunk_location_block_off = rdim_shared->location_case_chunk_lane_offs[location_block_chunk_lane_slot_idx]; for EachInRange(n_idx, range) { U64 dst_idx = 1 + n->base_idx + n_idx; RDIM_Scope *src_scope = &n->v[n_idx]; RDI_Scope *dst_scope = &rdim_shared->baked_scopes.scopes[dst_idx]; //- rjf: fill voff ranges U64 voff_idx_first = chunk_voff_off; for EachNode(rng_n, RDIM_Rng1U64Node, src_scope->voff_ranges.first) { rdim_shared->baked_scopes.scope_voffs[chunk_voff_off+0] = rng_n->v.min; rdim_shared->baked_scopes.scope_voffs[chunk_voff_off+1] = rng_n->v.max; chunk_voff_off += 2; } U64 voff_idx_opl = chunk_voff_off; //- rjf: fill locals U64 local_idx_first = chunk_local_off; for EachNode(src_local, RDIM_Local, src_scope->first_local) { RDI_Local *dst_local = &rdim_shared->baked_scopes.locals[chunk_local_off]; dst_local->kind = src_local->kind; dst_local->name_string_idx = rdim_bake_idx_from_string(bake_strings, src_local->name); dst_local->type_idx = (RDI_U32)rdim_idx_from_type(src_local->type); // TODO(rjf): @u64_to_u32 if(src_local->location_cases.count != 0) { dst_local->location_first = chunk_location_block_off; dst_local->location_opl = chunk_location_block_off + src_local->location_cases.count; chunk_location_block_off += src_local->location_cases.count; } chunk_local_off += 1; } U64 local_idx_opl = chunk_local_off; //- rjf: fill scope dst_scope->proc_idx = (RDI_U32)rdim_idx_from_symbol(src_scope->symbol); // TODO(rjf): @u64_to_u32 dst_scope->parent_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->parent_scope); // TODO(rjf): @u64_to_u32 dst_scope->first_child_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->first_child); // TODO(rjf): @u64_to_u32 dst_scope->next_sibling_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->next_sibling); // TODO(rjf): @u64_to_u32 dst_scope->voff_range_first = (RDI_U32)voff_idx_first; // TODO(rjf): @u64_to_u32 dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 dst_scope->inline_site_idx = (RDI_U32)rdim_idx_from_inline_site(src_scope->inline_site); // TODO(rjf): @u64_to_u32 } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake procedures // ProfScope("bake procedures") { if(lane_idx() == 0) { rdim_shared->baked_procedures.procedures_count = params->procedures.total_count+1; rdim_shared->baked_procedures.procedures = push_array(arena, RDI_Procedure, rdim_shared->baked_procedures.procedures_count); } lane_sync(); { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->procedures.first) { U64 location_block_layout_slot_idx = lane_idx()*total_location_case_chunk_count + params->scopes.chunk_count + chunk_idx; U64 location_block_off = rdim_shared->location_case_chunk_lane_offs[location_block_layout_slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Symbol *src = &n->v[n_idx]; RDI_Procedure *dst = &rdim_shared->baked_procedures.procedures[n->base_idx + n_idx + 1]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->link_name_string_idx = rdim_bake_idx_from_string(bake_strings, src->link_name); if(src->is_extern) { dst->link_flags |= RDI_LinkFlag_External; } if(src->container_type != 0) { dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 } else if(src->container_symbol != 0) { dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 } dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 if(src->location_cases.count != 0) { dst->frame_base_location_first = location_block_off; dst->frame_base_location_opl = location_block_off + src->location_cases.count; location_block_off += src->location_cases.count; } } chunk_idx += 1; } } } ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage compute layout for constant data // ProfScope("compute layout for constant data") { // rjf: set up if(lane_idx() == 0) { rdim_shared->constant_data_chunk_lane_counts = push_array(arena, U64, lane_count() * params->constants.chunk_count); rdim_shared->constant_data_chunk_lane_offs = push_array(arena, U64, lane_count() * params->constants.chunk_count); } lane_sync(); // rjf: count { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->constants.first) { U64 slot_idx = lane_idx()*params->constants.chunk_count + chunk_idx; Rng1U64 range = lane_range(n->count); for EachInRange(idx, range) { rdim_shared->constant_data_chunk_lane_counts[slot_idx] += n->v[idx].value_data.size; } chunk_idx += 1; } } lane_sync(); // rjf: layout if(lane_idx() == 0) { U64 chunk_idx = 0; U64 layout_off = 0; for EachNode(n, RDIM_SymbolChunkNode, params->constants.first) { for EachIndex(l_idx, lane_count()) { U64 slot_idx = l_idx*params->constants.chunk_count + chunk_idx; rdim_shared->constant_data_chunk_lane_offs[slot_idx] = layout_off; layout_off += rdim_shared->constant_data_chunk_lane_counts[slot_idx]; } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake constants // ProfScope("bake constants") { // rjf: set up if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->baked_constants.constant_values_count = params->constants.total_count+1; rdim_shared->baked_constants.constant_values = push_array(arena, RDI_U32, rdim_shared->baked_constants.constant_values_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->baked_constants.constant_value_data_size = params->constants.total_value_data_size; rdim_shared->baked_constants.constant_value_data = push_array(arena, RDI_U8, rdim_shared->baked_constants.constant_value_data_size); } if(lane_idx() == lane_from_task_idx(2)) { rdim_shared->baked_constants.constants_count = params->constants.total_count+1; rdim_shared->baked_constants.constants = push_array(arena, RDI_Constant, rdim_shared->baked_constants.constants_count); } lane_sync(); // rjf: wide bake { U64 chunk_idx = 0; for EachNode(n, RDIM_SymbolChunkNode, params->constants.first) { U64 slot_idx = lane_idx()*params->constants.chunk_count + chunk_idx; U64 value_data_off = rdim_shared->constant_data_chunk_lane_offs[slot_idx]; Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Symbol *src = &n->v[n_idx]; RDI_Constant *dst = &rdim_shared->baked_constants.constants[1 + n->base_idx + n_idx]; RDI_U32 *dst_value_off = &rdim_shared->baked_constants.constant_values[1 + n->base_idx + n_idx]; RDI_U8 *dst_value_data = rdim_shared->baked_constants.constant_value_data + value_data_off; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 dst->constant_value_idx = 1 + n->base_idx + n_idx; dst_value_off[0] = (RDI_U32)value_data_off; // TODO(rjf): @u64_to_u32 rdim_memcpy(dst_value_data, src->value_data.str, src->value_data.size); value_data_off += src->value_data.size; } chunk_idx += 1; } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake units, symbols, types, UDTs // { //- rjf: setup outputs if(lane_idx() == lane_from_task_idx(0)) { rdim_shared->baked_units.units_count = params->units.total_count+1; rdim_shared->baked_units.units = push_array(arena, RDI_Unit, rdim_shared->baked_units.units_count); } if(lane_idx() == lane_from_task_idx(1)) { rdim_shared->baked_type_nodes.type_nodes_count = params->types.total_count+1; rdim_shared->baked_type_nodes.type_nodes = push_array(arena, RDI_TypeNode, rdim_shared->baked_type_nodes.type_nodes_count); } if(lane_idx() == lane_from_task_idx(2)) { rdim_shared->baked_global_variables.global_variables_count = params->global_variables.total_count+1; rdim_shared->baked_global_variables.global_variables = push_array(arena, RDI_GlobalVariable, rdim_shared->baked_global_variables.global_variables_count); } if(lane_idx() == lane_from_task_idx(3)) { rdim_shared->baked_thread_variables.thread_variables_count = params->thread_variables.total_count+1; rdim_shared->baked_thread_variables.thread_variables = push_array(arena, RDI_ThreadVariable, rdim_shared->baked_thread_variables.thread_variables_count); } if(lane_idx() == lane_from_task_idx(4)) { rdim_shared->baked_inline_sites.inline_sites_count = params->inline_sites.total_count+1; rdim_shared->baked_inline_sites.inline_sites = push_array(arena, RDI_InlineSite, rdim_shared->baked_inline_sites.inline_sites_count); } lane_sync(); //- rjf: bake units ProfScope("bake units") { for EachNode(n, RDIM_UnitChunkNode, params->units.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Unit *src = &n->v[n_idx]; RDI_Unit *dst = &rdim_shared->baked_units.units[n->base_idx + n_idx + 1]; dst->unit_name_string_idx = rdim_bake_idx_from_string(bake_strings, src->unit_name); dst->compiler_name_string_idx = rdim_bake_idx_from_string(bake_strings, src->compiler_name); dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); dst->language = src->language; dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 } } } //- rjf: bake type nodes ProfScope("bake type nodes") { for EachNode(n, RDIM_TypeChunkNode, params->types.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Type *src = &n->v[n_idx]; RDI_TypeNode *dst = &rdim_shared->baked_type_nodes.type_nodes[n->base_idx + n_idx + 1]; //- rjf: fill shared type node info dst->kind = src->kind; dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 dst->byte_size = src->byte_size; //- rjf: fill built-in-only type node info if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) { dst->built_in.name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); } //- rjf: fill array sizes else if(dst->kind == RDI_TypeKind_Array) { U64 direct_byte_size = 1; if(src->direct_type && src->direct_type->byte_size > 0) { direct_byte_size = src->direct_type->byte_size; } dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); dst->constructed.count = src->byte_size / direct_byte_size; } //- rjf: fill constructed type node info else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) { dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 dst->constructed.count = src->count; if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) { RDI_U32 param_idx_run_count = src->count; RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) { param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 } dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(bake_idx_runs, param_idx_run, param_idx_run_count); } else if(dst->kind == RDI_TypeKind_MemberPtr) { // TODO(rjf): member pointers not currently supported. } } //- rjf: fill user-defined-type info else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) { dst->user_defined.name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 } //- rjf: fill bitfield info else if(dst->kind == RDI_TypeKind_Bitfield) { dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 dst->bitfield.off = src->off; dst->bitfield.size = src->count; } } } } //- rjf: bake global variables ProfScope("bake global variables") { for EachNode(n, RDIM_SymbolChunkNode, params->global_variables.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Symbol *src = &n->v[n_idx]; RDI_GlobalVariable *dst = &rdim_shared->baked_global_variables.global_variables[n->base_idx + n_idx + 1]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->voff = src->offset; dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 if(src->is_extern) { dst->link_flags |= RDI_LinkFlag_External; } if(src->container_type != 0) { dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 } else if(src->container_symbol != 0) { dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 } } } } //- rjf: bake thread variables ProfScope("bake thread variables") { for EachNode(n, RDIM_SymbolChunkNode, params->thread_variables.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDIM_Symbol *src = &n->v[n_idx]; RDI_ThreadVariable *dst = &rdim_shared->baked_thread_variables.thread_variables[n->base_idx + n_idx + 1]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); if(src->is_extern) { dst->link_flags |= RDI_LinkFlag_External; } if(src->container_type != 0) { dst->link_flags |= RDI_LinkFlag_TypeScoped; dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 } else if(src->container_symbol != 0) { dst->link_flags |= RDI_LinkFlag_ProcScoped; dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 } } } } //- rjf: bake inline sites ProfScope("bake inline sites") { for EachNode(n, RDIM_InlineSiteChunkNode, params->inline_sites.first) { Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { RDI_InlineSite *dst = &rdim_shared->baked_inline_sites.inline_sites[n->base_idx + n_idx + 1]; RDIM_InlineSite *src = &n->v[n_idx]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage bake file paths // ProfScope("bake file paths") { // rjf: set up if(lane_idx() == 0) { rdim_shared->baked_file_paths.nodes_count = path_tree->count; rdim_shared->baked_file_paths.nodes = push_array(arena, RDI_FilePathNode, rdim_shared->baked_file_paths.nodes_count); rdim_shared->baked_file_path_src_nodes = push_array(arena, RDIM_BakePathNode *, rdim_shared->baked_file_paths.nodes_count); { U64 idx = 0; for(RDIM_BakePathNode *n = path_tree->first; n != 0; n = n->next_order) { rdim_shared->baked_file_path_src_nodes[idx] = n; idx += 1; } } } lane_sync(); // rjf: fill { Rng1U64 range = lane_range(rdim_shared->baked_file_paths.nodes_count); for EachInRange(idx, range) { RDIM_BakePathNode *src = rdim_shared->baked_file_path_src_nodes[idx]; RDI_FilePathNode *dst = &rdim_shared->baked_file_paths.nodes[idx]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->source_file_idx = rdim_idx_from_src_file(src->src_file); if(src->parent != 0) { dst->parent_path_node = src->parent->idx; } if(src->first_child != 0) { dst->first_child = src->first_child->idx; } if(src->next_sibling != 0) { dst->next_sibling = src->next_sibling->idx; } } } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage do small final baking tasks // ProfScope("do small final baking tasks") { if(lane_idx() == lane_from_task_idx(0)) ProfScope("bake top level info") { rdim_shared->baked_top_level_info.top_level_info.arch = params->top_level_info.arch; rdim_shared->baked_top_level_info.top_level_info.exe_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.exe_name); rdim_shared->baked_top_level_info.top_level_info.exe_hash = params->top_level_info.exe_hash; rdim_shared->baked_top_level_info.top_level_info.voff_max = params->top_level_info.voff_max; rdim_shared->baked_top_level_info.top_level_info.guid = params->top_level_info.guid; rdim_shared->baked_top_level_info.top_level_info.producer_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.producer_name); } if(lane_idx() == lane_from_task_idx(1)) ProfScope("bake binary sections") { RDIM_BinarySectionList *src = ¶ms->binary_sections; RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src->count+1); U64 dst_idx = 1; for(RDIM_BinarySectionNode *src_n = src->first; src_n != 0; src_n = src_n->next, dst_idx += 1) { RDIM_BinarySection *src = &src_n->v; RDI_BinarySection *dst = &dst_base[dst_idx]; dst->name_string_idx = rdim_bake_idx_from_string(bake_strings, src->name); dst->flags = src->flags; dst->voff_first = src->voff_first; dst->voff_opl = src->voff_opl; dst->foff_first = src->foff_first; dst->foff_opl = src->foff_opl; } rdim_shared->baked_binary_sections.binary_sections = dst_base; rdim_shared->baked_binary_sections.binary_sections_count = dst_idx; } } lane_sync(); ////////////////////////////////////////////////////////////// //- rjf: @rdim_bake_stage package results // RDIM_BakeResults result = {0}; { result.top_level_info = rdim_shared->baked_top_level_info; result.binary_sections = rdim_shared->baked_binary_sections; result.units = rdim_shared->baked_units; result.unit_vmap = rdim_shared->baked_unit_vmap; result.src_files = rdim_shared->baked_src_files; result.checksums = rdim_shared->baked_checksums; result.line_tables = rdim_shared->baked_line_tables; result.type_nodes = rdim_shared->baked_type_nodes; result.udts = rdim_shared->baked_udts; result.global_variables = rdim_shared->baked_global_variables; result.global_vmap = rdim_shared->baked_global_vmap; result.thread_variables = rdim_shared->baked_thread_variables; result.constants = rdim_shared->baked_constants; result.procedures = rdim_shared->baked_procedures; result.scopes = rdim_shared->baked_scopes; result.inline_sites = rdim_shared->baked_inline_sites; result.scope_vmap = rdim_shared->baked_scope_vmap; result.top_level_name_maps = rdim_shared->baked_top_level_name_maps; result.name_maps = rdim_shared->baked_name_maps; result.file_paths = rdim_shared->baked_file_paths; result.strings = rdim_shared->baked_strings; result.idx_runs = rdim_shared->baked_idx_runs; result.locations = rdim_shared->baked_locations; result.location_blocks = rdim_shared->baked_location_blocks; } return result; } internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in) { Temp scratch = scratch_begin(&arena, 1); RDIM_SerializedSectionBundle out_ = {0}; RDIM_SerializedSectionBundle *out = &out_; lane_sync_u64(&out, 0); //- rjf: set up compression context rr_lzb_simple_context ctx = {0}; ctx.m_tableSizeBits = 14; ctx.m_hashTable = push_array(scratch.arena, U16, 1<sections[k]; RDIM_SerializedSection *dst = &out->sections[k]; MemoryCopyStruct(dst, src); if(src->encoded_size != 0) { MemoryZero(ctx.m_hashTable, sizeof(U16)*(1<data = push_array_no_zero(arena, U8, src->encoded_size); dst->encoded_size = rr_lzb_simple_encode_veryfast(&ctx, src->data, src->encoded_size, dst->data); dst->unpacked_size = src->encoded_size; dst->encoding = RDI_SectionEncoding_LZB; } } lane_sync(); scratch_end(scratch); return *out; } ================================================ FILE: src/rdi_make/rdi_make_local.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_MAKE_LOCAL_H #define RDI_MAKE_LOCAL_H //- rjf: base layer memory ops #define RDIM_MEMSET_OVERRIDE #define RDIM_MEMCPY_OVERRIDE #define rdim_memset MemorySet #define rdim_memcpy MemoryCopy //- rjf: base layer string overrides #define RDI_STRING8_OVERRIDE #define RDIM_String8 String8 #define RDIM_String8_BaseMember str #define RDIM_String8_SizeMember size #define RDI_STRING8LIST_OVERRIDE #define RDIM_String8Node String8Node #define RDIM_String8Node_NextPtrMember next #define RDIM_String8Node_StringMember string #define RDIM_String8List String8List #define RDIM_String8List_FirstMember first #define RDIM_String8List_LastMember last #define RDIM_String8List_NodeCountMember node_count #define RDIM_String8List_TotalSizeMember total_size //- rjf: base layer arena overrides #define RDIM_ARENA_OVERRIDE #define RDIM_Arena Arena #define rdim_arena_alloc arena_alloc #define rdim_arena_release arena_release #define rdim_arena_pos arena_pos #define rdim_arena_push arena_push #define rdim_arena_pop_to arena_pop_to //- rjf: base layer scratch arena overrides #define RDIM_SCRATCH_OVERRIDE #define RDIM_Temp Temp #define rdim_temp_arena(t) ((t).arena) #define rdim_scratch_begin scratch_begin #define rdim_scratch_end scratch_end //- rjf: base layer profiling markup overrides #define RDIM_ProfBegin(...) ProfBeginDynamic(__VA_ARGS__) #define RDIM_ProfEnd(...) ProfEnd() //- rjf: main library #include "lib_rdi_make/rdi_make.h" //- rjf: unsorted joined line table info typedef struct RDIM_UnsortedJoinedLineTable RDIM_UnsortedJoinedLineTable; struct RDIM_UnsortedJoinedLineTable { RDI_U64 line_count; RDI_U64 seq_count; RDI_U64 key_count; RDIM_SortKey *line_keys; RDIM_LineRec *line_recs; }; //- rjf: shared state bundle typedef struct RDIM_Shared RDIM_Shared; struct RDIM_Shared { RDIM_ScopeVMapBakeResult baked_scope_vmap; RDIM_UnitVMapBakeResult baked_unit_vmap; RDIM_GlobalVMapBakeResult baked_global_vmap; RDIM_BakePathTree *path_tree; RDI_U64 line_tables_count; RDI_U64 line_table_block_take_counter; RDIM_LineTable **src_line_tables; RDIM_UnsortedJoinedLineTable *unsorted_joined_line_tables; RDIM_SortKey **sorted_line_table_keys; RDIM_LineTableBakeResult baked_line_tables; RDIM_BakeStringMapTight bake_strings; RDIM_BakeIdxRunMap bake_idx_runs; RDIM_StringBakeResult baked_strings; RDIM_IndexRunBakeResult baked_idx_runs; RDI_U64 *lane_name_map_node_counts[RDI_NameMapKind_COUNT]; RDI_U64 *lane_name_map_node_offs[RDI_NameMapKind_COUNT]; RDI_U64 name_map_node_counts[RDI_NameMapKind_COUNT]; RDI_U64 total_name_map_node_count; RDIM_TopLevelNameMapBakeResult baked_top_level_name_maps; RDIM_NameMapBakeResult baked_name_maps; RDIM_BakeSrcLineMap *bake_src_line_maps; RDI_U64 bake_src_line_map_take_counter; RDIM_SortKey **bake_src_line_map_keys; RDI_U64 *lane_chunk_src_file_num_counts; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_voff_counts; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_map_counts; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_num_offs; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_voff_offs; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_map_offs; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_checksum_counts[RDI_ChecksumKind_COUNT]; // [lane_count * src_file_chunk_count] RDI_U64 *lane_chunk_src_file_checksum_offs[RDI_ChecksumKind_COUNT]; // [lane_count * src_file_chunk_count] U64 total_checksum_counts[RDI_ChecksumKind_COUNT]; RDI_U64 total_src_map_line_count; RDI_U64 total_src_map_voff_count; RDIM_ChecksumBakeResult baked_checksums; RDIM_SrcFileBakeResult baked_src_files; RDI_U64 *member_chunk_lane_counts; // [lane_count * udt_chunk_count] RDI_U64 *member_chunk_lane_offs; // [lane_count * udt_chunk_count] RDI_U64 *enum_val_chunk_lane_counts; // [lane_count * udt_chunk_count] RDI_U64 *enum_val_chunk_lane_offs; // [lane_count * udt_chunk_count] RDIM_UDTBakeResult baked_udts; RDI_U64 *location_case_chunk_lane_counts; // [lane_count * (scope_chunk_count + procedure_chunk_count) RDI_U64 *location_case_chunk_lane_offs; // [lane_count * (scope_chunk_count + procedure_chunk_count) RDI_U64 total_location_case_count; RDIM_LocationBlockBakeResult baked_location_blocks; RDIM_LocationBakeResult baked_locations; RDI_U64 *scope_local_chunk_lane_counts; // [lane_count * scope_chunk_count] RDI_U64 *scope_local_chunk_lane_offs; // [lane_count * scope_chunk_count] RDI_U64 *scope_voff_chunk_lane_counts; // [lane_count * scope_chunk_count] RDI_U64 *scope_voff_chunk_lane_offs; // [lane_count * scope_chunk_count] RDIM_ScopeBakeResult baked_scopes; RDIM_ProcedureBakeResult baked_procedures; RDI_U64 *constant_data_chunk_lane_counts; // [lane_count * constant_chunk_count] RDI_U64 *constant_data_chunk_lane_offs; // [lane_count * constant_chunk_count] RDIM_ConstantsBakeResult baked_constants; RDIM_UnitBakeResult baked_units; RDIM_TypeNodeBakeResult baked_type_nodes; RDIM_GlobalVariableBakeResult baked_global_variables; RDIM_ThreadVariableBakeResult baked_thread_variables; RDIM_InlineSiteBakeResult baked_inline_sites; RDIM_BakePathNode **baked_file_path_src_nodes; RDIM_FilePathBakeResult baked_file_paths; RDIM_TopLevelInfoBakeResult baked_top_level_info; RDIM_BinarySectionBakeResult baked_binary_sections; }; global RDIM_Shared *rdim_shared = 0; internal RDIM_DataModel rdim_data_model_from_os_arch(OperatingSystem os, RDI_Arch arch); internal RDIM_BakeResults rdim_bake(Arena *arena, RDIM_BakeParams *params); internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in); #endif // RDI_MAKE_LOCAL_H ================================================ FILE: src/regs/generated/regs.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE internal U64 regs_block_size_from_arch(Arch arch) { U64 result = 8; switch(arch) { default:{}break; case Arch_x64:{result = sizeof(REGS_RegBlockX64);}break; case Arch_x86:{result = sizeof(REGS_RegBlockX86);}break; } return result; } internal U64 regs_reg_code_count_from_arch(Arch arch) { U64 result = 0; switch(arch) { default:{}break; case Arch_x64:{result = REGS_RegCodeX64_COUNT;}break; case Arch_x86:{result = REGS_RegCodeX86_COUNT;}break; } return result; } internal U64 regs_alias_code_count_from_arch(Arch arch) { U64 result = 0; switch(arch) { default:{}break; case Arch_x64:{result = REGS_AliasCodeX64_COUNT;}break; case Arch_x86:{result = REGS_AliasCodeX86_COUNT;}break; } return result; } internal String8 *regs_reg_code_string_table_from_arch(Arch arch) { String8 *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_reg_code_x64_string_table;}break; case Arch_x86:{result = regs_g_reg_code_x86_string_table;}break; } return result; } internal String8 *regs_alias_code_string_table_from_arch(Arch arch) { String8 *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_alias_code_x64_string_table;}break; case Arch_x86:{result = regs_g_alias_code_x86_string_table;}break; } return result; } internal REGS_Rng *regs_reg_code_rng_table_from_arch(Arch arch) { REGS_Rng *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_reg_code_x64_rng_table;}break; case Arch_x86:{result = regs_g_reg_code_x86_rng_table;}break; } return result; } internal REGS_Slice *regs_alias_code_slice_table_from_arch(Arch arch) { REGS_Slice *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_alias_code_x64_slice_table;}break; case Arch_x86:{result = regs_g_alias_code_x86_slice_table;}break; } return result; } internal REGS_UsageKind *regs_reg_code_usage_kind_table_from_arch(Arch arch) { REGS_UsageKind *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_reg_code_x64_usage_kind_table;}break; case Arch_x86:{result = regs_g_reg_code_x86_usage_kind_table;}break; } return result; } internal REGS_UsageKind *regs_alias_code_usage_kind_table_from_arch(Arch arch) { REGS_UsageKind *result = 0; switch(arch) { default:{}break; case Arch_x64:{result = regs_g_alias_code_x64_usage_kind_table;}break; case Arch_x86:{result = regs_g_alias_code_x86_usage_kind_table;}break; } return result; } C_LINKAGE_BEGIN REGS_UsageKind regs_g_reg_code_x64_usage_kind_table[105] = { REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, }; REGS_UsageKind regs_g_alias_code_x64_usage_kind_table[96] = { REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, }; String8 regs_g_reg_code_x64_string_table[105] = { str8_lit_comp(""), str8_lit_comp("rax"), str8_lit_comp("rcx"), str8_lit_comp("rdx"), str8_lit_comp("rbx"), str8_lit_comp("rsp"), str8_lit_comp("rbp"), str8_lit_comp("rsi"), str8_lit_comp("rdi"), str8_lit_comp("r8"), str8_lit_comp("r9"), str8_lit_comp("r10"), str8_lit_comp("r11"), str8_lit_comp("r12"), str8_lit_comp("r13"), str8_lit_comp("r14"), str8_lit_comp("r15"), str8_lit_comp("fsbase"), str8_lit_comp("gsbase"), str8_lit_comp("rip"), str8_lit_comp("rflags"), str8_lit_comp("dr0"), str8_lit_comp("dr1"), str8_lit_comp("dr2"), str8_lit_comp("dr3"), str8_lit_comp("dr4"), str8_lit_comp("dr5"), str8_lit_comp("dr6"), str8_lit_comp("dr7"), str8_lit_comp("fpr0"), str8_lit_comp("fpr1"), str8_lit_comp("fpr2"), str8_lit_comp("fpr3"), str8_lit_comp("fpr4"), str8_lit_comp("fpr5"), str8_lit_comp("fpr6"), str8_lit_comp("fpr7"), str8_lit_comp("st0"), str8_lit_comp("st1"), str8_lit_comp("st2"), str8_lit_comp("st3"), str8_lit_comp("st4"), str8_lit_comp("st5"), str8_lit_comp("st6"), str8_lit_comp("st7"), str8_lit_comp("fcw"), str8_lit_comp("fsw"), str8_lit_comp("ftw"), str8_lit_comp("fop"), str8_lit_comp("fcs"), str8_lit_comp("fds"), str8_lit_comp("fip"), str8_lit_comp("fdp"), str8_lit_comp("mxcsr"), str8_lit_comp("mxcsr_mask"), str8_lit_comp("ss"), str8_lit_comp("cs"), str8_lit_comp("ds"), str8_lit_comp("es"), str8_lit_comp("fs"), str8_lit_comp("gs"), str8_lit_comp("zmm0"), str8_lit_comp("zmm1"), str8_lit_comp("zmm2"), str8_lit_comp("zmm3"), str8_lit_comp("zmm4"), str8_lit_comp("zmm5"), str8_lit_comp("zmm6"), str8_lit_comp("zmm7"), str8_lit_comp("zmm8"), str8_lit_comp("zmm9"), str8_lit_comp("zmm10"), str8_lit_comp("zmm11"), str8_lit_comp("zmm12"), str8_lit_comp("zmm13"), str8_lit_comp("zmm14"), str8_lit_comp("zmm15"), str8_lit_comp("zmm16"), str8_lit_comp("zmm17"), str8_lit_comp("zmm18"), str8_lit_comp("zmm19"), str8_lit_comp("zmm20"), str8_lit_comp("zmm21"), str8_lit_comp("zmm22"), str8_lit_comp("zmm23"), str8_lit_comp("zmm24"), str8_lit_comp("zmm25"), str8_lit_comp("zmm26"), str8_lit_comp("zmm27"), str8_lit_comp("zmm28"), str8_lit_comp("zmm29"), str8_lit_comp("zmm30"), str8_lit_comp("zmm31"), str8_lit_comp("k0"), str8_lit_comp("k1"), str8_lit_comp("k2"), str8_lit_comp("k3"), str8_lit_comp("k4"), str8_lit_comp("k5"), str8_lit_comp("k6"), str8_lit_comp("k7"), str8_lit_comp("cetmsr"), str8_lit_comp("cetssp"), str8_lit_comp("tr"), str8_lit_comp("ldtr"), }; String8 regs_g_alias_code_x64_string_table[96] = { str8_lit_comp(""), str8_lit_comp("eax"), str8_lit_comp("ecx"), str8_lit_comp("edx"), str8_lit_comp("ebx"), str8_lit_comp("esp"), str8_lit_comp("ebp"), str8_lit_comp("esi"), str8_lit_comp("edi"), str8_lit_comp("r8d"), str8_lit_comp("r9d"), str8_lit_comp("r10d"), str8_lit_comp("r11d"), str8_lit_comp("r12d"), str8_lit_comp("r13d"), str8_lit_comp("r14d"), str8_lit_comp("r15d"), str8_lit_comp("eip"), str8_lit_comp("eflags"), str8_lit_comp("ax"), str8_lit_comp("cx"), str8_lit_comp("dx"), str8_lit_comp("bx"), str8_lit_comp("si"), str8_lit_comp("di"), str8_lit_comp("sp"), str8_lit_comp("bp"), str8_lit_comp("ip"), str8_lit_comp("r8w"), str8_lit_comp("r9w"), str8_lit_comp("r10w"), str8_lit_comp("r11w"), str8_lit_comp("r12w"), str8_lit_comp("r13w"), str8_lit_comp("r14w"), str8_lit_comp("r15w"), str8_lit_comp("al"), str8_lit_comp("cl"), str8_lit_comp("dl"), str8_lit_comp("bl"), str8_lit_comp("sil"), str8_lit_comp("dil"), str8_lit_comp("bpl"), str8_lit_comp("spl"), str8_lit_comp("r8b"), str8_lit_comp("r9b"), str8_lit_comp("r10b"), str8_lit_comp("r11b"), str8_lit_comp("r12b"), str8_lit_comp("r13b"), str8_lit_comp("r14b"), str8_lit_comp("r15b"), str8_lit_comp("ah"), str8_lit_comp("ch"), str8_lit_comp("dh"), str8_lit_comp("bh"), str8_lit_comp("xmm0"), str8_lit_comp("xmm1"), str8_lit_comp("xmm2"), str8_lit_comp("xmm3"), str8_lit_comp("xmm4"), str8_lit_comp("xmm5"), str8_lit_comp("xmm6"), str8_lit_comp("xmm7"), str8_lit_comp("xmm8"), str8_lit_comp("xmm9"), str8_lit_comp("xmm10"), str8_lit_comp("xmm11"), str8_lit_comp("xmm12"), str8_lit_comp("xmm13"), str8_lit_comp("xmm14"), str8_lit_comp("xmm15"), str8_lit_comp("ymm0"), str8_lit_comp("ymm1"), str8_lit_comp("ymm2"), str8_lit_comp("ymm3"), str8_lit_comp("ymm4"), str8_lit_comp("ymm5"), str8_lit_comp("ymm6"), str8_lit_comp("ymm7"), str8_lit_comp("ymm8"), str8_lit_comp("ymm9"), str8_lit_comp("ymm10"), str8_lit_comp("ymm11"), str8_lit_comp("ymm12"), str8_lit_comp("ymm13"), str8_lit_comp("ymm14"), str8_lit_comp("ymm15"), str8_lit_comp("mm0"), str8_lit_comp("mm1"), str8_lit_comp("mm2"), str8_lit_comp("mm3"), str8_lit_comp("mm4"), str8_lit_comp("mm5"), str8_lit_comp("mm6"), str8_lit_comp("mm7"), }; REGS_Rng regs_g_reg_code_x64_rng_table[105] = { {0}, {(U16)OffsetOf(REGS_RegBlockX64, rax), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rcx), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rdx), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rbx), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rsp), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rbp), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rsi), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rdi), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r8), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r9), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r10), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r11), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r12), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r13), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r14), 8}, {(U16)OffsetOf(REGS_RegBlockX64, r15), 8}, {(U16)OffsetOf(REGS_RegBlockX64, fsbase), 8}, {(U16)OffsetOf(REGS_RegBlockX64, gsbase), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rip), 8}, {(U16)OffsetOf(REGS_RegBlockX64, rflags), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr0), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr1), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr2), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr3), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr4), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr5), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr6), 8}, {(U16)OffsetOf(REGS_RegBlockX64, dr7), 8}, {(U16)OffsetOf(REGS_RegBlockX64, fpr0), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr1), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr2), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr3), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr4), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr5), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr6), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fpr7), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st0), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st1), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st2), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st3), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st4), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st5), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st6), 10}, {(U16)OffsetOf(REGS_RegBlockX64, st7), 10}, {(U16)OffsetOf(REGS_RegBlockX64, fcw), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fsw), 2}, {(U16)OffsetOf(REGS_RegBlockX64, ftw), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fop), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fcs), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fds), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fip), 8}, {(U16)OffsetOf(REGS_RegBlockX64, fdp), 8}, {(U16)OffsetOf(REGS_RegBlockX64, mxcsr), 4}, {(U16)OffsetOf(REGS_RegBlockX64, mxcsr_mask), 4}, {(U16)OffsetOf(REGS_RegBlockX64, ss), 2}, {(U16)OffsetOf(REGS_RegBlockX64, cs), 2}, {(U16)OffsetOf(REGS_RegBlockX64, ds), 2}, {(U16)OffsetOf(REGS_RegBlockX64, es), 2}, {(U16)OffsetOf(REGS_RegBlockX64, fs), 2}, {(U16)OffsetOf(REGS_RegBlockX64, gs), 2}, {(U16)OffsetOf(REGS_RegBlockX64, zmm0), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm1), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm2), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm3), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm4), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm5), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm6), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm7), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm8), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm9), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm10), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm11), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm12), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm13), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm14), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm15), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm16), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm17), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm18), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm19), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm20), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm21), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm22), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm23), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm24), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm25), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm26), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm27), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm28), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm29), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm30), 64}, {(U16)OffsetOf(REGS_RegBlockX64, zmm31), 64}, {(U16)OffsetOf(REGS_RegBlockX64, k0), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k1), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k2), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k3), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k4), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k5), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k6), 8}, {(U16)OffsetOf(REGS_RegBlockX64, k7), 8}, {(U16)OffsetOf(REGS_RegBlockX64, cetmsr), 8}, {(U16)OffsetOf(REGS_RegBlockX64, cetssp), 8}, {(U16)OffsetOf(REGS_RegBlockX64, tr), 2}, {(U16)OffsetOf(REGS_RegBlockX64, ldtr), 2}, }; REGS_Slice regs_g_alias_code_x64_slice_table[96] = { {0}, {REGS_RegCodeX64_rax, 0, 4}, {REGS_RegCodeX64_rcx, 0, 4}, {REGS_RegCodeX64_rdx, 0, 4}, {REGS_RegCodeX64_rbx, 0, 4}, {REGS_RegCodeX64_rsp, 0, 4}, {REGS_RegCodeX64_rbp, 0, 4}, {REGS_RegCodeX64_rsi, 0, 4}, {REGS_RegCodeX64_rdi, 0, 4}, {REGS_RegCodeX64_r8, 0, 4}, {REGS_RegCodeX64_r9, 0, 4}, {REGS_RegCodeX64_r10, 0, 4}, {REGS_RegCodeX64_r11, 0, 4}, {REGS_RegCodeX64_r12, 0, 4}, {REGS_RegCodeX64_r13, 0, 4}, {REGS_RegCodeX64_r14, 0, 4}, {REGS_RegCodeX64_r15, 0, 4}, {REGS_RegCodeX64_rip, 0, 4}, {REGS_RegCodeX64_rflags, 0, 4}, {REGS_RegCodeX64_rax, 0, 2}, {REGS_RegCodeX64_rcx, 0, 2}, {REGS_RegCodeX64_rdx, 0, 2}, {REGS_RegCodeX64_rbx, 0, 2}, {REGS_RegCodeX64_rsi, 0, 2}, {REGS_RegCodeX64_rdi, 0, 2}, {REGS_RegCodeX64_rsp, 0, 2}, {REGS_RegCodeX64_rbp, 0, 2}, {REGS_RegCodeX64_rip, 0, 2}, {REGS_RegCodeX64_r8, 0, 2}, {REGS_RegCodeX64_r9, 0, 2}, {REGS_RegCodeX64_r10, 0, 2}, {REGS_RegCodeX64_r11, 0, 2}, {REGS_RegCodeX64_r12, 0, 2}, {REGS_RegCodeX64_r13, 0, 2}, {REGS_RegCodeX64_r14, 0, 2}, {REGS_RegCodeX64_r15, 0, 2}, {REGS_RegCodeX64_rax, 0, 1}, {REGS_RegCodeX64_rcx, 0, 1}, {REGS_RegCodeX64_rdx, 0, 1}, {REGS_RegCodeX64_rbx, 0, 1}, {REGS_RegCodeX64_rsi, 0, 1}, {REGS_RegCodeX64_rdi, 0, 1}, {REGS_RegCodeX64_rbp, 0, 1}, {REGS_RegCodeX64_rsp, 0, 1}, {REGS_RegCodeX64_r8, 0, 1}, {REGS_RegCodeX64_r9, 0, 1}, {REGS_RegCodeX64_r10, 0, 1}, {REGS_RegCodeX64_r11, 0, 1}, {REGS_RegCodeX64_r12, 0, 1}, {REGS_RegCodeX64_r13, 0, 1}, {REGS_RegCodeX64_r14, 0, 1}, {REGS_RegCodeX64_r15, 0, 1}, {REGS_RegCodeX64_rax, 1, 1}, {REGS_RegCodeX64_rcx, 1, 1}, {REGS_RegCodeX64_rdx, 1, 1}, {REGS_RegCodeX64_rbx, 1, 1}, {REGS_RegCodeX64_zmm0, 0, 16}, {REGS_RegCodeX64_zmm1, 0, 16}, {REGS_RegCodeX64_zmm2, 0, 16}, {REGS_RegCodeX64_zmm3, 0, 16}, {REGS_RegCodeX64_zmm4, 0, 16}, {REGS_RegCodeX64_zmm5, 0, 16}, {REGS_RegCodeX64_zmm6, 0, 16}, {REGS_RegCodeX64_zmm7, 0, 16}, {REGS_RegCodeX64_zmm8, 0, 16}, {REGS_RegCodeX64_zmm9, 0, 16}, {REGS_RegCodeX64_zmm10, 0, 16}, {REGS_RegCodeX64_zmm11, 0, 16}, {REGS_RegCodeX64_zmm12, 0, 16}, {REGS_RegCodeX64_zmm13, 0, 16}, {REGS_RegCodeX64_zmm14, 0, 16}, {REGS_RegCodeX64_zmm15, 0, 16}, {REGS_RegCodeX64_zmm0, 0, 32}, {REGS_RegCodeX64_zmm1, 0, 32}, {REGS_RegCodeX64_zmm2, 0, 32}, {REGS_RegCodeX64_zmm3, 0, 32}, {REGS_RegCodeX64_zmm4, 0, 32}, {REGS_RegCodeX64_zmm5, 0, 32}, {REGS_RegCodeX64_zmm6, 0, 32}, {REGS_RegCodeX64_zmm7, 0, 32}, {REGS_RegCodeX64_zmm8, 0, 32}, {REGS_RegCodeX64_zmm9, 0, 32}, {REGS_RegCodeX64_zmm10, 0, 32}, {REGS_RegCodeX64_zmm11, 0, 32}, {REGS_RegCodeX64_zmm12, 0, 32}, {REGS_RegCodeX64_zmm13, 0, 32}, {REGS_RegCodeX64_zmm14, 0, 32}, {REGS_RegCodeX64_zmm15, 0, 32}, {REGS_RegCodeX64_fpr0, 0, 8}, {REGS_RegCodeX64_fpr1, 0, 8}, {REGS_RegCodeX64_fpr2, 0, 8}, {REGS_RegCodeX64_fpr3, 0, 8}, {REGS_RegCodeX64_fpr4, 0, 8}, {REGS_RegCodeX64_fpr5, 0, 8}, {REGS_RegCodeX64_fpr6, 0, 8}, {REGS_RegCodeX64_fpr7, 0, 8}, }; REGS_UsageKind regs_g_reg_code_x86_usage_kind_table[63] = { REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, }; REGS_UsageKind regs_g_alias_code_x86_usage_kind_table[36] = { REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Normal, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, REGS_UsageKind_Vector, }; String8 regs_g_reg_code_x86_string_table[63] = { str8_lit_comp(""), str8_lit_comp("eax"), str8_lit_comp("ecx"), str8_lit_comp("edx"), str8_lit_comp("ebx"), str8_lit_comp("esp"), str8_lit_comp("ebp"), str8_lit_comp("esi"), str8_lit_comp("edi"), str8_lit_comp("fsbase"), str8_lit_comp("gsbase"), str8_lit_comp("eflags"), str8_lit_comp("eip"), str8_lit_comp("dr0"), str8_lit_comp("dr1"), str8_lit_comp("dr2"), str8_lit_comp("dr3"), str8_lit_comp("dr4"), str8_lit_comp("dr5"), str8_lit_comp("dr6"), str8_lit_comp("dr7"), str8_lit_comp("fpr0"), str8_lit_comp("fpr1"), str8_lit_comp("fpr2"), str8_lit_comp("fpr3"), str8_lit_comp("fpr4"), str8_lit_comp("fpr5"), str8_lit_comp("fpr6"), str8_lit_comp("fpr7"), str8_lit_comp("st0"), str8_lit_comp("st1"), str8_lit_comp("st2"), str8_lit_comp("st3"), str8_lit_comp("st4"), str8_lit_comp("st5"), str8_lit_comp("st6"), str8_lit_comp("st7"), str8_lit_comp("fcw"), str8_lit_comp("fsw"), str8_lit_comp("ftw"), str8_lit_comp("fop"), str8_lit_comp("fcs"), str8_lit_comp("fds"), str8_lit_comp("fip"), str8_lit_comp("fdp"), str8_lit_comp("mxcsr"), str8_lit_comp("mxcsr_mask"), str8_lit_comp("ss"), str8_lit_comp("cs"), str8_lit_comp("ds"), str8_lit_comp("es"), str8_lit_comp("fs"), str8_lit_comp("gs"), str8_lit_comp("tr"), str8_lit_comp("ldtr"), str8_lit_comp("ymm0"), str8_lit_comp("ymm1"), str8_lit_comp("ymm2"), str8_lit_comp("ymm3"), str8_lit_comp("ymm4"), str8_lit_comp("ymm5"), str8_lit_comp("ymm6"), str8_lit_comp("ymm7"), }; String8 regs_g_alias_code_x86_string_table[36] = { str8_lit_comp(""), str8_lit_comp("ax"), str8_lit_comp("cx"), str8_lit_comp("bx"), str8_lit_comp("dx"), str8_lit_comp("sp"), str8_lit_comp("bp"), str8_lit_comp("si"), str8_lit_comp("di"), str8_lit_comp("ip"), str8_lit_comp("ah"), str8_lit_comp("ch"), str8_lit_comp("dh"), str8_lit_comp("bh"), str8_lit_comp("al"), str8_lit_comp("cl"), str8_lit_comp("dl"), str8_lit_comp("bl"), str8_lit_comp("bpl"), str8_lit_comp("spl"), str8_lit_comp("xmm0"), str8_lit_comp("xmm1"), str8_lit_comp("xmm2"), str8_lit_comp("xmm3"), str8_lit_comp("xmm4"), str8_lit_comp("xmm5"), str8_lit_comp("xmm6"), str8_lit_comp("xmm7"), str8_lit_comp("mm0"), str8_lit_comp("mm1"), str8_lit_comp("mm2"), str8_lit_comp("mm3"), str8_lit_comp("mm4"), str8_lit_comp("mm5"), str8_lit_comp("mm6"), str8_lit_comp("mm7"), }; REGS_Rng regs_g_reg_code_x86_rng_table[63] = { {0}, {(U16)OffsetOf(REGS_RegBlockX86, eax), 4}, {(U16)OffsetOf(REGS_RegBlockX86, ecx), 4}, {(U16)OffsetOf(REGS_RegBlockX86, edx), 4}, {(U16)OffsetOf(REGS_RegBlockX86, ebx), 4}, {(U16)OffsetOf(REGS_RegBlockX86, esp), 4}, {(U16)OffsetOf(REGS_RegBlockX86, ebp), 4}, {(U16)OffsetOf(REGS_RegBlockX86, esi), 4}, {(U16)OffsetOf(REGS_RegBlockX86, edi), 4}, {(U16)OffsetOf(REGS_RegBlockX86, fsbase), 4}, {(U16)OffsetOf(REGS_RegBlockX86, gsbase), 4}, {(U16)OffsetOf(REGS_RegBlockX86, eflags), 4}, {(U16)OffsetOf(REGS_RegBlockX86, eip), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr0), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr1), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr2), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr3), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr4), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr5), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr6), 4}, {(U16)OffsetOf(REGS_RegBlockX86, dr7), 4}, {(U16)OffsetOf(REGS_RegBlockX86, fpr0), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr1), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr2), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr3), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr4), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr5), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr6), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fpr7), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st0), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st1), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st2), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st3), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st4), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st5), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st6), 10}, {(U16)OffsetOf(REGS_RegBlockX86, st7), 10}, {(U16)OffsetOf(REGS_RegBlockX86, fcw), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fsw), 2}, {(U16)OffsetOf(REGS_RegBlockX86, ftw), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fop), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fcs), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fds), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fip), 4}, {(U16)OffsetOf(REGS_RegBlockX86, fdp), 4}, {(U16)OffsetOf(REGS_RegBlockX86, mxcsr), 4}, {(U16)OffsetOf(REGS_RegBlockX86, mxcsr_mask), 4}, {(U16)OffsetOf(REGS_RegBlockX86, ss), 2}, {(U16)OffsetOf(REGS_RegBlockX86, cs), 2}, {(U16)OffsetOf(REGS_RegBlockX86, ds), 2}, {(U16)OffsetOf(REGS_RegBlockX86, es), 2}, {(U16)OffsetOf(REGS_RegBlockX86, fs), 2}, {(U16)OffsetOf(REGS_RegBlockX86, gs), 2}, {(U16)OffsetOf(REGS_RegBlockX86, tr), 2}, {(U16)OffsetOf(REGS_RegBlockX86, ldtr), 2}, {(U16)OffsetOf(REGS_RegBlockX86, ymm0), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm1), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm2), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm3), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm4), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm5), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm6), 32}, {(U16)OffsetOf(REGS_RegBlockX86, ymm7), 32}, }; REGS_Slice regs_g_alias_code_x86_slice_table[36] = { {0}, {REGS_RegCodeX86_eax, 0, 2}, {REGS_RegCodeX86_ecx, 0, 2}, {REGS_RegCodeX86_ebx, 0, 2}, {REGS_RegCodeX86_edx, 0, 2}, {REGS_RegCodeX86_esp, 0, 2}, {REGS_RegCodeX86_ebp, 0, 2}, {REGS_RegCodeX86_esi, 0, 2}, {REGS_RegCodeX86_edi, 0, 2}, {REGS_RegCodeX86_eip, 0, 2}, {REGS_RegCodeX86_eax, 1, 1}, {REGS_RegCodeX86_ecx, 1, 1}, {REGS_RegCodeX86_edx, 1, 1}, {REGS_RegCodeX86_ebx, 1, 1}, {REGS_RegCodeX86_eax, 0, 1}, {REGS_RegCodeX86_ecx, 0, 1}, {REGS_RegCodeX86_edx, 0, 1}, {REGS_RegCodeX86_ebx, 0, 1}, {REGS_RegCodeX86_ebp, 0, 1}, {REGS_RegCodeX86_esp, 0, 1}, {REGS_RegCodeX86_ymm0, 0, 16}, {REGS_RegCodeX86_ymm1, 0, 16}, {REGS_RegCodeX86_ymm2, 0, 16}, {REGS_RegCodeX86_ymm3, 0, 16}, {REGS_RegCodeX86_ymm4, 0, 16}, {REGS_RegCodeX86_ymm5, 0, 16}, {REGS_RegCodeX86_ymm6, 0, 16}, {REGS_RegCodeX86_ymm7, 0, 16}, {REGS_RegCodeX86_fpr0, 0, 8}, {REGS_RegCodeX86_fpr1, 0, 8}, {REGS_RegCodeX86_fpr2, 0, 8}, {REGS_RegCodeX86_fpr3, 0, 8}, {REGS_RegCodeX86_fpr4, 0, 8}, {REGS_RegCodeX86_fpr5, 0, 8}, {REGS_RegCodeX86_fpr6, 0, 8}, {REGS_RegCodeX86_fpr7, 0, 8}, }; C_LINKAGE_END ================================================ FILE: src/regs/generated/regs.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef REGS_META_H #define REGS_META_H typedef enum REGS_RegCodeX64 { REGS_RegCodeX64_NULL, REGS_RegCodeX64_rax, REGS_RegCodeX64_rcx, REGS_RegCodeX64_rdx, REGS_RegCodeX64_rbx, REGS_RegCodeX64_rsp, REGS_RegCodeX64_rbp, REGS_RegCodeX64_rsi, REGS_RegCodeX64_rdi, REGS_RegCodeX64_r8, REGS_RegCodeX64_r9, REGS_RegCodeX64_r10, REGS_RegCodeX64_r11, REGS_RegCodeX64_r12, REGS_RegCodeX64_r13, REGS_RegCodeX64_r14, REGS_RegCodeX64_r15, REGS_RegCodeX64_fsbase, REGS_RegCodeX64_gsbase, REGS_RegCodeX64_rip, REGS_RegCodeX64_rflags, REGS_RegCodeX64_dr0, REGS_RegCodeX64_dr1, REGS_RegCodeX64_dr2, REGS_RegCodeX64_dr3, REGS_RegCodeX64_dr4, REGS_RegCodeX64_dr5, REGS_RegCodeX64_dr6, REGS_RegCodeX64_dr7, REGS_RegCodeX64_fpr0, REGS_RegCodeX64_fpr1, REGS_RegCodeX64_fpr2, REGS_RegCodeX64_fpr3, REGS_RegCodeX64_fpr4, REGS_RegCodeX64_fpr5, REGS_RegCodeX64_fpr6, REGS_RegCodeX64_fpr7, REGS_RegCodeX64_st0, REGS_RegCodeX64_st1, REGS_RegCodeX64_st2, REGS_RegCodeX64_st3, REGS_RegCodeX64_st4, REGS_RegCodeX64_st5, REGS_RegCodeX64_st6, REGS_RegCodeX64_st7, REGS_RegCodeX64_fcw, REGS_RegCodeX64_fsw, REGS_RegCodeX64_ftw, REGS_RegCodeX64_fop, REGS_RegCodeX64_fcs, REGS_RegCodeX64_fds, REGS_RegCodeX64_fip, REGS_RegCodeX64_fdp, REGS_RegCodeX64_mxcsr, REGS_RegCodeX64_mxcsr_mask, REGS_RegCodeX64_ss, REGS_RegCodeX64_cs, REGS_RegCodeX64_ds, REGS_RegCodeX64_es, REGS_RegCodeX64_fs, REGS_RegCodeX64_gs, REGS_RegCodeX64_zmm0, REGS_RegCodeX64_zmm1, REGS_RegCodeX64_zmm2, REGS_RegCodeX64_zmm3, REGS_RegCodeX64_zmm4, REGS_RegCodeX64_zmm5, REGS_RegCodeX64_zmm6, REGS_RegCodeX64_zmm7, REGS_RegCodeX64_zmm8, REGS_RegCodeX64_zmm9, REGS_RegCodeX64_zmm10, REGS_RegCodeX64_zmm11, REGS_RegCodeX64_zmm12, REGS_RegCodeX64_zmm13, REGS_RegCodeX64_zmm14, REGS_RegCodeX64_zmm15, REGS_RegCodeX64_zmm16, REGS_RegCodeX64_zmm17, REGS_RegCodeX64_zmm18, REGS_RegCodeX64_zmm19, REGS_RegCodeX64_zmm20, REGS_RegCodeX64_zmm21, REGS_RegCodeX64_zmm22, REGS_RegCodeX64_zmm23, REGS_RegCodeX64_zmm24, REGS_RegCodeX64_zmm25, REGS_RegCodeX64_zmm26, REGS_RegCodeX64_zmm27, REGS_RegCodeX64_zmm28, REGS_RegCodeX64_zmm29, REGS_RegCodeX64_zmm30, REGS_RegCodeX64_zmm31, REGS_RegCodeX64_k0, REGS_RegCodeX64_k1, REGS_RegCodeX64_k2, REGS_RegCodeX64_k3, REGS_RegCodeX64_k4, REGS_RegCodeX64_k5, REGS_RegCodeX64_k6, REGS_RegCodeX64_k7, REGS_RegCodeX64_cetmsr, REGS_RegCodeX64_cetssp, REGS_RegCodeX64_tr, REGS_RegCodeX64_ldtr, REGS_RegCodeX64_COUNT, } REGS_RegCodeX64; typedef enum REGS_AliasCodeX64 { REGS_AliasCodeX64_NULL, REGS_AliasCodeX64_eax, REGS_AliasCodeX64_ecx, REGS_AliasCodeX64_edx, REGS_AliasCodeX64_ebx, REGS_AliasCodeX64_esp, REGS_AliasCodeX64_ebp, REGS_AliasCodeX64_esi, REGS_AliasCodeX64_edi, REGS_AliasCodeX64_r8d, REGS_AliasCodeX64_r9d, REGS_AliasCodeX64_r10d, REGS_AliasCodeX64_r11d, REGS_AliasCodeX64_r12d, REGS_AliasCodeX64_r13d, REGS_AliasCodeX64_r14d, REGS_AliasCodeX64_r15d, REGS_AliasCodeX64_eip, REGS_AliasCodeX64_eflags, REGS_AliasCodeX64_ax, REGS_AliasCodeX64_cx, REGS_AliasCodeX64_dx, REGS_AliasCodeX64_bx, REGS_AliasCodeX64_si, REGS_AliasCodeX64_di, REGS_AliasCodeX64_sp, REGS_AliasCodeX64_bp, REGS_AliasCodeX64_ip, REGS_AliasCodeX64_r8w, REGS_AliasCodeX64_r9w, REGS_AliasCodeX64_r10w, REGS_AliasCodeX64_r11w, REGS_AliasCodeX64_r12w, REGS_AliasCodeX64_r13w, REGS_AliasCodeX64_r14w, REGS_AliasCodeX64_r15w, REGS_AliasCodeX64_al, REGS_AliasCodeX64_cl, REGS_AliasCodeX64_dl, REGS_AliasCodeX64_bl, REGS_AliasCodeX64_sil, REGS_AliasCodeX64_dil, REGS_AliasCodeX64_bpl, REGS_AliasCodeX64_spl, REGS_AliasCodeX64_r8b, REGS_AliasCodeX64_r9b, REGS_AliasCodeX64_r10b, REGS_AliasCodeX64_r11b, REGS_AliasCodeX64_r12b, REGS_AliasCodeX64_r13b, REGS_AliasCodeX64_r14b, REGS_AliasCodeX64_r15b, REGS_AliasCodeX64_ah, REGS_AliasCodeX64_ch, REGS_AliasCodeX64_dh, REGS_AliasCodeX64_bh, REGS_AliasCodeX64_xmm0, REGS_AliasCodeX64_xmm1, REGS_AliasCodeX64_xmm2, REGS_AliasCodeX64_xmm3, REGS_AliasCodeX64_xmm4, REGS_AliasCodeX64_xmm5, REGS_AliasCodeX64_xmm6, REGS_AliasCodeX64_xmm7, REGS_AliasCodeX64_xmm8, REGS_AliasCodeX64_xmm9, REGS_AliasCodeX64_xmm10, REGS_AliasCodeX64_xmm11, REGS_AliasCodeX64_xmm12, REGS_AliasCodeX64_xmm13, REGS_AliasCodeX64_xmm14, REGS_AliasCodeX64_xmm15, REGS_AliasCodeX64_ymm0, REGS_AliasCodeX64_ymm1, REGS_AliasCodeX64_ymm2, REGS_AliasCodeX64_ymm3, REGS_AliasCodeX64_ymm4, REGS_AliasCodeX64_ymm5, REGS_AliasCodeX64_ymm6, REGS_AliasCodeX64_ymm7, REGS_AliasCodeX64_ymm8, REGS_AliasCodeX64_ymm9, REGS_AliasCodeX64_ymm10, REGS_AliasCodeX64_ymm11, REGS_AliasCodeX64_ymm12, REGS_AliasCodeX64_ymm13, REGS_AliasCodeX64_ymm14, REGS_AliasCodeX64_ymm15, REGS_AliasCodeX64_mm0, REGS_AliasCodeX64_mm1, REGS_AliasCodeX64_mm2, REGS_AliasCodeX64_mm3, REGS_AliasCodeX64_mm4, REGS_AliasCodeX64_mm5, REGS_AliasCodeX64_mm6, REGS_AliasCodeX64_mm7, REGS_AliasCodeX64_COUNT, } REGS_AliasCodeX64; typedef enum REGS_RegCodeX86 { REGS_RegCodeX86_NULL, REGS_RegCodeX86_eax, REGS_RegCodeX86_ecx, REGS_RegCodeX86_edx, REGS_RegCodeX86_ebx, REGS_RegCodeX86_esp, REGS_RegCodeX86_ebp, REGS_RegCodeX86_esi, REGS_RegCodeX86_edi, REGS_RegCodeX86_fsbase, REGS_RegCodeX86_gsbase, REGS_RegCodeX86_eflags, REGS_RegCodeX86_eip, REGS_RegCodeX86_dr0, REGS_RegCodeX86_dr1, REGS_RegCodeX86_dr2, REGS_RegCodeX86_dr3, REGS_RegCodeX86_dr4, REGS_RegCodeX86_dr5, REGS_RegCodeX86_dr6, REGS_RegCodeX86_dr7, REGS_RegCodeX86_fpr0, REGS_RegCodeX86_fpr1, REGS_RegCodeX86_fpr2, REGS_RegCodeX86_fpr3, REGS_RegCodeX86_fpr4, REGS_RegCodeX86_fpr5, REGS_RegCodeX86_fpr6, REGS_RegCodeX86_fpr7, REGS_RegCodeX86_st0, REGS_RegCodeX86_st1, REGS_RegCodeX86_st2, REGS_RegCodeX86_st3, REGS_RegCodeX86_st4, REGS_RegCodeX86_st5, REGS_RegCodeX86_st6, REGS_RegCodeX86_st7, REGS_RegCodeX86_fcw, REGS_RegCodeX86_fsw, REGS_RegCodeX86_ftw, REGS_RegCodeX86_fop, REGS_RegCodeX86_fcs, REGS_RegCodeX86_fds, REGS_RegCodeX86_fip, REGS_RegCodeX86_fdp, REGS_RegCodeX86_mxcsr, REGS_RegCodeX86_mxcsr_mask, REGS_RegCodeX86_ss, REGS_RegCodeX86_cs, REGS_RegCodeX86_ds, REGS_RegCodeX86_es, REGS_RegCodeX86_fs, REGS_RegCodeX86_gs, REGS_RegCodeX86_tr, REGS_RegCodeX86_ldtr, REGS_RegCodeX86_ymm0, REGS_RegCodeX86_ymm1, REGS_RegCodeX86_ymm2, REGS_RegCodeX86_ymm3, REGS_RegCodeX86_ymm4, REGS_RegCodeX86_ymm5, REGS_RegCodeX86_ymm6, REGS_RegCodeX86_ymm7, REGS_RegCodeX86_COUNT, } REGS_RegCodeX86; typedef enum REGS_AliasCodeX86 { REGS_AliasCodeX86_NULL, REGS_AliasCodeX86_ax, REGS_AliasCodeX86_cx, REGS_AliasCodeX86_bx, REGS_AliasCodeX86_dx, REGS_AliasCodeX86_sp, REGS_AliasCodeX86_bp, REGS_AliasCodeX86_si, REGS_AliasCodeX86_di, REGS_AliasCodeX86_ip, REGS_AliasCodeX86_ah, REGS_AliasCodeX86_ch, REGS_AliasCodeX86_dh, REGS_AliasCodeX86_bh, REGS_AliasCodeX86_al, REGS_AliasCodeX86_cl, REGS_AliasCodeX86_dl, REGS_AliasCodeX86_bl, REGS_AliasCodeX86_bpl, REGS_AliasCodeX86_spl, REGS_AliasCodeX86_xmm0, REGS_AliasCodeX86_xmm1, REGS_AliasCodeX86_xmm2, REGS_AliasCodeX86_xmm3, REGS_AliasCodeX86_xmm4, REGS_AliasCodeX86_xmm5, REGS_AliasCodeX86_xmm6, REGS_AliasCodeX86_xmm7, REGS_AliasCodeX86_mm0, REGS_AliasCodeX86_mm1, REGS_AliasCodeX86_mm2, REGS_AliasCodeX86_mm3, REGS_AliasCodeX86_mm4, REGS_AliasCodeX86_mm5, REGS_AliasCodeX86_mm6, REGS_AliasCodeX86_mm7, REGS_AliasCodeX86_COUNT, } REGS_AliasCodeX86; typedef struct REGS_RegBlockX64 REGS_RegBlockX64; struct REGS_RegBlockX64 { REGS_Reg64 rax; REGS_Reg64 rcx; REGS_Reg64 rdx; REGS_Reg64 rbx; REGS_Reg64 rsp; REGS_Reg64 rbp; REGS_Reg64 rsi; REGS_Reg64 rdi; REGS_Reg64 r8; REGS_Reg64 r9; REGS_Reg64 r10; REGS_Reg64 r11; REGS_Reg64 r12; REGS_Reg64 r13; REGS_Reg64 r14; REGS_Reg64 r15; REGS_Reg64 fsbase; REGS_Reg64 gsbase; REGS_Reg64 rip; REGS_Reg64 rflags; REGS_Reg64 dr0; REGS_Reg64 dr1; REGS_Reg64 dr2; REGS_Reg64 dr3; REGS_Reg64 dr4; REGS_Reg64 dr5; REGS_Reg64 dr6; REGS_Reg64 dr7; REGS_Reg80 fpr0; REGS_Reg80 fpr1; REGS_Reg80 fpr2; REGS_Reg80 fpr3; REGS_Reg80 fpr4; REGS_Reg80 fpr5; REGS_Reg80 fpr6; REGS_Reg80 fpr7; REGS_Reg80 st0; REGS_Reg80 st1; REGS_Reg80 st2; REGS_Reg80 st3; REGS_Reg80 st4; REGS_Reg80 st5; REGS_Reg80 st6; REGS_Reg80 st7; REGS_Reg16 fcw; REGS_Reg16 fsw; REGS_Reg16 ftw; REGS_Reg16 fop; REGS_Reg16 fcs; REGS_Reg16 fds; REGS_Reg64 fip; REGS_Reg64 fdp; REGS_Reg32 mxcsr; REGS_Reg32 mxcsr_mask; REGS_Reg16 ss; REGS_Reg16 cs; REGS_Reg16 ds; REGS_Reg16 es; REGS_Reg16 fs; REGS_Reg16 gs; REGS_Reg512 zmm0; REGS_Reg512 zmm1; REGS_Reg512 zmm2; REGS_Reg512 zmm3; REGS_Reg512 zmm4; REGS_Reg512 zmm5; REGS_Reg512 zmm6; REGS_Reg512 zmm7; REGS_Reg512 zmm8; REGS_Reg512 zmm9; REGS_Reg512 zmm10; REGS_Reg512 zmm11; REGS_Reg512 zmm12; REGS_Reg512 zmm13; REGS_Reg512 zmm14; REGS_Reg512 zmm15; REGS_Reg512 zmm16; REGS_Reg512 zmm17; REGS_Reg512 zmm18; REGS_Reg512 zmm19; REGS_Reg512 zmm20; REGS_Reg512 zmm21; REGS_Reg512 zmm22; REGS_Reg512 zmm23; REGS_Reg512 zmm24; REGS_Reg512 zmm25; REGS_Reg512 zmm26; REGS_Reg512 zmm27; REGS_Reg512 zmm28; REGS_Reg512 zmm29; REGS_Reg512 zmm30; REGS_Reg512 zmm31; REGS_Reg64 k0; REGS_Reg64 k1; REGS_Reg64 k2; REGS_Reg64 k3; REGS_Reg64 k4; REGS_Reg64 k5; REGS_Reg64 k6; REGS_Reg64 k7; REGS_Reg64 cetmsr; REGS_Reg64 cetssp; REGS_Reg16 tr; REGS_Reg16 ldtr; }; typedef struct REGS_RegBlockX86 REGS_RegBlockX86; struct REGS_RegBlockX86 { REGS_Reg32 eax; REGS_Reg32 ecx; REGS_Reg32 edx; REGS_Reg32 ebx; REGS_Reg32 esp; REGS_Reg32 ebp; REGS_Reg32 esi; REGS_Reg32 edi; REGS_Reg32 fsbase; REGS_Reg32 gsbase; REGS_Reg32 eflags; REGS_Reg32 eip; REGS_Reg32 dr0; REGS_Reg32 dr1; REGS_Reg32 dr2; REGS_Reg32 dr3; REGS_Reg32 dr4; REGS_Reg32 dr5; REGS_Reg32 dr6; REGS_Reg32 dr7; REGS_Reg80 fpr0; REGS_Reg80 fpr1; REGS_Reg80 fpr2; REGS_Reg80 fpr3; REGS_Reg80 fpr4; REGS_Reg80 fpr5; REGS_Reg80 fpr6; REGS_Reg80 fpr7; REGS_Reg80 st0; REGS_Reg80 st1; REGS_Reg80 st2; REGS_Reg80 st3; REGS_Reg80 st4; REGS_Reg80 st5; REGS_Reg80 st6; REGS_Reg80 st7; REGS_Reg16 fcw; REGS_Reg16 fsw; REGS_Reg16 ftw; REGS_Reg16 fop; REGS_Reg16 fcs; REGS_Reg16 fds; REGS_Reg32 fip; REGS_Reg32 fdp; REGS_Reg32 mxcsr; REGS_Reg32 mxcsr_mask; REGS_Reg16 ss; REGS_Reg16 cs; REGS_Reg16 ds; REGS_Reg16 es; REGS_Reg16 fs; REGS_Reg16 gs; REGS_Reg16 tr; REGS_Reg16 ldtr; REGS_Reg256 ymm0; REGS_Reg256 ymm1; REGS_Reg256 ymm2; REGS_Reg256 ymm3; REGS_Reg256 ymm4; REGS_Reg256 ymm5; REGS_Reg256 ymm6; REGS_Reg256 ymm7; }; C_LINKAGE_BEGIN extern REGS_UsageKind regs_g_reg_code_x64_usage_kind_table[105]; extern REGS_UsageKind regs_g_alias_code_x64_usage_kind_table[96]; extern String8 regs_g_reg_code_x64_string_table[105]; extern String8 regs_g_alias_code_x64_string_table[96]; extern REGS_Rng regs_g_reg_code_x64_rng_table[105]; extern REGS_Slice regs_g_alias_code_x64_slice_table[96]; extern REGS_UsageKind regs_g_reg_code_x86_usage_kind_table[63]; extern REGS_UsageKind regs_g_alias_code_x86_usage_kind_table[36]; extern String8 regs_g_reg_code_x86_string_table[63]; extern String8 regs_g_alias_code_x86_string_table[36]; extern REGS_Rng regs_g_reg_code_x86_rng_table[63]; extern REGS_Slice regs_g_alias_code_x86_slice_table[36]; C_LINKAGE_END #endif // REGS_META_H ================================================ FILE: src/regs/rdi/generated/regs_rdi.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE internal RDI_RegCode regs_rdi_code_from_arch_reg_code(Arch arch, REGS_RegCode code) { RDI_RegCode result = 0; switch(arch) { default:{}break; case Arch_x64: { switch(code) { default:{}break; case REGS_RegCodeX64_rax:{result = RDI_RegCodeX64_rax;}break; case REGS_RegCodeX64_rcx:{result = RDI_RegCodeX64_rcx;}break; case REGS_RegCodeX64_rdx:{result = RDI_RegCodeX64_rdx;}break; case REGS_RegCodeX64_rbx:{result = RDI_RegCodeX64_rbx;}break; case REGS_RegCodeX64_rsp:{result = RDI_RegCodeX64_rsp;}break; case REGS_RegCodeX64_rbp:{result = RDI_RegCodeX64_rbp;}break; case REGS_RegCodeX64_rsi:{result = RDI_RegCodeX64_rsi;}break; case REGS_RegCodeX64_rdi:{result = RDI_RegCodeX64_rdi;}break; case REGS_RegCodeX64_r8:{result = RDI_RegCodeX64_r8;}break; case REGS_RegCodeX64_r9:{result = RDI_RegCodeX64_r9;}break; case REGS_RegCodeX64_r10:{result = RDI_RegCodeX64_r10;}break; case REGS_RegCodeX64_r11:{result = RDI_RegCodeX64_r11;}break; case REGS_RegCodeX64_r12:{result = RDI_RegCodeX64_r12;}break; case REGS_RegCodeX64_r13:{result = RDI_RegCodeX64_r13;}break; case REGS_RegCodeX64_r14:{result = RDI_RegCodeX64_r14;}break; case REGS_RegCodeX64_r15:{result = RDI_RegCodeX64_r15;}break; case REGS_RegCodeX64_fsbase:{result = RDI_RegCodeX64_fsbase;}break; case REGS_RegCodeX64_gsbase:{result = RDI_RegCodeX64_gsbase;}break; case REGS_RegCodeX64_rip:{result = RDI_RegCodeX64_rip;}break; case REGS_RegCodeX64_rflags:{result = RDI_RegCodeX64_rflags;}break; case REGS_RegCodeX64_dr0:{result = RDI_RegCodeX64_dr0;}break; case REGS_RegCodeX64_dr1:{result = RDI_RegCodeX64_dr1;}break; case REGS_RegCodeX64_dr2:{result = RDI_RegCodeX64_dr2;}break; case REGS_RegCodeX64_dr3:{result = RDI_RegCodeX64_dr3;}break; case REGS_RegCodeX64_dr4:{result = RDI_RegCodeX64_dr4;}break; case REGS_RegCodeX64_dr5:{result = RDI_RegCodeX64_dr5;}break; case REGS_RegCodeX64_dr6:{result = RDI_RegCodeX64_dr6;}break; case REGS_RegCodeX64_dr7:{result = RDI_RegCodeX64_dr7;}break; case REGS_RegCodeX64_fpr0:{result = RDI_RegCodeX64_fpr0;}break; case REGS_RegCodeX64_fpr1:{result = RDI_RegCodeX64_fpr1;}break; case REGS_RegCodeX64_fpr2:{result = RDI_RegCodeX64_fpr2;}break; case REGS_RegCodeX64_fpr3:{result = RDI_RegCodeX64_fpr3;}break; case REGS_RegCodeX64_fpr4:{result = RDI_RegCodeX64_fpr4;}break; case REGS_RegCodeX64_fpr5:{result = RDI_RegCodeX64_fpr5;}break; case REGS_RegCodeX64_fpr6:{result = RDI_RegCodeX64_fpr6;}break; case REGS_RegCodeX64_fpr7:{result = RDI_RegCodeX64_fpr7;}break; case REGS_RegCodeX64_st0:{result = RDI_RegCodeX64_st0;}break; case REGS_RegCodeX64_st1:{result = RDI_RegCodeX64_st1;}break; case REGS_RegCodeX64_st2:{result = RDI_RegCodeX64_st2;}break; case REGS_RegCodeX64_st3:{result = RDI_RegCodeX64_st3;}break; case REGS_RegCodeX64_st4:{result = RDI_RegCodeX64_st4;}break; case REGS_RegCodeX64_st5:{result = RDI_RegCodeX64_st5;}break; case REGS_RegCodeX64_st6:{result = RDI_RegCodeX64_st6;}break; case REGS_RegCodeX64_st7:{result = RDI_RegCodeX64_st7;}break; case REGS_RegCodeX64_fcw:{result = RDI_RegCodeX64_fcw;}break; case REGS_RegCodeX64_fsw:{result = RDI_RegCodeX64_fsw;}break; case REGS_RegCodeX64_ftw:{result = RDI_RegCodeX64_ftw;}break; case REGS_RegCodeX64_fop:{result = RDI_RegCodeX64_fop;}break; case REGS_RegCodeX64_fcs:{result = RDI_RegCodeX64_fcs;}break; case REGS_RegCodeX64_fds:{result = RDI_RegCodeX64_fds;}break; case REGS_RegCodeX64_fip:{result = RDI_RegCodeX64_fip;}break; case REGS_RegCodeX64_fdp:{result = RDI_RegCodeX64_fdp;}break; case REGS_RegCodeX64_mxcsr:{result = RDI_RegCodeX64_mxcsr;}break; case REGS_RegCodeX64_mxcsr_mask:{result = RDI_RegCodeX64_mxcsr_mask;}break; case REGS_RegCodeX64_ss:{result = RDI_RegCodeX64_ss;}break; case REGS_RegCodeX64_cs:{result = RDI_RegCodeX64_cs;}break; case REGS_RegCodeX64_ds:{result = RDI_RegCodeX64_ds;}break; case REGS_RegCodeX64_es:{result = RDI_RegCodeX64_es;}break; case REGS_RegCodeX64_fs:{result = RDI_RegCodeX64_fs;}break; case REGS_RegCodeX64_gs:{result = RDI_RegCodeX64_gs;}break; case REGS_RegCodeX64_zmm0:{result = RDI_RegCodeX64_zmm0;}break; case REGS_RegCodeX64_zmm1:{result = RDI_RegCodeX64_zmm1;}break; case REGS_RegCodeX64_zmm2:{result = RDI_RegCodeX64_zmm2;}break; case REGS_RegCodeX64_zmm3:{result = RDI_RegCodeX64_zmm3;}break; case REGS_RegCodeX64_zmm4:{result = RDI_RegCodeX64_zmm4;}break; case REGS_RegCodeX64_zmm5:{result = RDI_RegCodeX64_zmm5;}break; case REGS_RegCodeX64_zmm6:{result = RDI_RegCodeX64_zmm6;}break; case REGS_RegCodeX64_zmm7:{result = RDI_RegCodeX64_zmm7;}break; case REGS_RegCodeX64_zmm8:{result = RDI_RegCodeX64_zmm8;}break; case REGS_RegCodeX64_zmm9:{result = RDI_RegCodeX64_zmm9;}break; case REGS_RegCodeX64_zmm10:{result = RDI_RegCodeX64_zmm10;}break; case REGS_RegCodeX64_zmm11:{result = RDI_RegCodeX64_zmm11;}break; case REGS_RegCodeX64_zmm12:{result = RDI_RegCodeX64_zmm12;}break; case REGS_RegCodeX64_zmm13:{result = RDI_RegCodeX64_zmm13;}break; case REGS_RegCodeX64_zmm14:{result = RDI_RegCodeX64_zmm14;}break; case REGS_RegCodeX64_zmm15:{result = RDI_RegCodeX64_zmm15;}break; case REGS_RegCodeX64_zmm16:{result = RDI_RegCodeX64_zmm16;}break; case REGS_RegCodeX64_zmm17:{result = RDI_RegCodeX64_zmm17;}break; case REGS_RegCodeX64_zmm18:{result = RDI_RegCodeX64_zmm18;}break; case REGS_RegCodeX64_zmm19:{result = RDI_RegCodeX64_zmm19;}break; case REGS_RegCodeX64_zmm20:{result = RDI_RegCodeX64_zmm20;}break; case REGS_RegCodeX64_zmm21:{result = RDI_RegCodeX64_zmm21;}break; case REGS_RegCodeX64_zmm22:{result = RDI_RegCodeX64_zmm22;}break; case REGS_RegCodeX64_zmm23:{result = RDI_RegCodeX64_zmm23;}break; case REGS_RegCodeX64_zmm24:{result = RDI_RegCodeX64_zmm24;}break; case REGS_RegCodeX64_zmm25:{result = RDI_RegCodeX64_zmm25;}break; case REGS_RegCodeX64_zmm26:{result = RDI_RegCodeX64_zmm26;}break; case REGS_RegCodeX64_zmm27:{result = RDI_RegCodeX64_zmm27;}break; case REGS_RegCodeX64_zmm28:{result = RDI_RegCodeX64_zmm28;}break; case REGS_RegCodeX64_zmm29:{result = RDI_RegCodeX64_zmm29;}break; case REGS_RegCodeX64_zmm30:{result = RDI_RegCodeX64_zmm30;}break; case REGS_RegCodeX64_zmm31:{result = RDI_RegCodeX64_zmm31;}break; case REGS_RegCodeX64_k0:{result = RDI_RegCodeX64_k0;}break; case REGS_RegCodeX64_k1:{result = RDI_RegCodeX64_k1;}break; case REGS_RegCodeX64_k2:{result = RDI_RegCodeX64_k2;}break; case REGS_RegCodeX64_k3:{result = RDI_RegCodeX64_k3;}break; case REGS_RegCodeX64_k4:{result = RDI_RegCodeX64_k4;}break; case REGS_RegCodeX64_k5:{result = RDI_RegCodeX64_k5;}break; case REGS_RegCodeX64_k6:{result = RDI_RegCodeX64_k6;}break; case REGS_RegCodeX64_k7:{result = RDI_RegCodeX64_k7;}break; case REGS_RegCodeX64_cetmsr:{result = RDI_RegCodeX64_cetmsr;}break; case REGS_RegCodeX64_cetssp:{result = RDI_RegCodeX64_cetssp;}break; case REGS_RegCodeX64_tr:{result = RDI_RegCodeX64_tr;}break; case REGS_RegCodeX64_ldtr:{result = RDI_RegCodeX64_ldtr;}break; } }break; case Arch_x86: { switch(code) { default:{}break; case REGS_RegCodeX86_eax:{result = RDI_RegCodeX86_eax;}break; case REGS_RegCodeX86_ecx:{result = RDI_RegCodeX86_ecx;}break; case REGS_RegCodeX86_edx:{result = RDI_RegCodeX86_edx;}break; case REGS_RegCodeX86_ebx:{result = RDI_RegCodeX86_ebx;}break; case REGS_RegCodeX86_esp:{result = RDI_RegCodeX86_esp;}break; case REGS_RegCodeX86_ebp:{result = RDI_RegCodeX86_ebp;}break; case REGS_RegCodeX86_esi:{result = RDI_RegCodeX86_esi;}break; case REGS_RegCodeX86_edi:{result = RDI_RegCodeX86_edi;}break; case REGS_RegCodeX86_fsbase:{result = RDI_RegCodeX86_fsbase;}break; case REGS_RegCodeX86_gsbase:{result = RDI_RegCodeX86_gsbase;}break; case REGS_RegCodeX86_eflags:{result = RDI_RegCodeX86_eflags;}break; case REGS_RegCodeX86_eip:{result = RDI_RegCodeX86_eip;}break; case REGS_RegCodeX86_dr0:{result = RDI_RegCodeX86_dr0;}break; case REGS_RegCodeX86_dr1:{result = RDI_RegCodeX86_dr1;}break; case REGS_RegCodeX86_dr2:{result = RDI_RegCodeX86_dr2;}break; case REGS_RegCodeX86_dr3:{result = RDI_RegCodeX86_dr3;}break; case REGS_RegCodeX86_dr4:{result = RDI_RegCodeX86_dr4;}break; case REGS_RegCodeX86_dr5:{result = RDI_RegCodeX86_dr5;}break; case REGS_RegCodeX86_dr6:{result = RDI_RegCodeX86_dr6;}break; case REGS_RegCodeX86_dr7:{result = RDI_RegCodeX86_dr7;}break; case REGS_RegCodeX86_fpr0:{result = RDI_RegCodeX86_fpr0;}break; case REGS_RegCodeX86_fpr1:{result = RDI_RegCodeX86_fpr1;}break; case REGS_RegCodeX86_fpr2:{result = RDI_RegCodeX86_fpr2;}break; case REGS_RegCodeX86_fpr3:{result = RDI_RegCodeX86_fpr3;}break; case REGS_RegCodeX86_fpr4:{result = RDI_RegCodeX86_fpr4;}break; case REGS_RegCodeX86_fpr5:{result = RDI_RegCodeX86_fpr5;}break; case REGS_RegCodeX86_fpr6:{result = RDI_RegCodeX86_fpr6;}break; case REGS_RegCodeX86_fpr7:{result = RDI_RegCodeX86_fpr7;}break; case REGS_RegCodeX86_st0:{result = RDI_RegCodeX86_st0;}break; case REGS_RegCodeX86_st1:{result = RDI_RegCodeX86_st1;}break; case REGS_RegCodeX86_st2:{result = RDI_RegCodeX86_st2;}break; case REGS_RegCodeX86_st3:{result = RDI_RegCodeX86_st3;}break; case REGS_RegCodeX86_st4:{result = RDI_RegCodeX86_st4;}break; case REGS_RegCodeX86_st5:{result = RDI_RegCodeX86_st5;}break; case REGS_RegCodeX86_st6:{result = RDI_RegCodeX86_st6;}break; case REGS_RegCodeX86_st7:{result = RDI_RegCodeX86_st7;}break; case REGS_RegCodeX86_fcw:{result = RDI_RegCodeX86_fcw;}break; case REGS_RegCodeX86_fsw:{result = RDI_RegCodeX86_fsw;}break; case REGS_RegCodeX86_ftw:{result = RDI_RegCodeX86_ftw;}break; case REGS_RegCodeX86_fop:{result = RDI_RegCodeX86_fop;}break; case REGS_RegCodeX86_fcs:{result = RDI_RegCodeX86_fcs;}break; case REGS_RegCodeX86_fds:{result = RDI_RegCodeX86_fds;}break; case REGS_RegCodeX86_fip:{result = RDI_RegCodeX86_fip;}break; case REGS_RegCodeX86_fdp:{result = RDI_RegCodeX86_fdp;}break; case REGS_RegCodeX86_mxcsr:{result = RDI_RegCodeX86_mxcsr;}break; case REGS_RegCodeX86_mxcsr_mask:{result = RDI_RegCodeX86_mxcsr_mask;}break; case REGS_RegCodeX86_ss:{result = RDI_RegCodeX86_ss;}break; case REGS_RegCodeX86_cs:{result = RDI_RegCodeX86_cs;}break; case REGS_RegCodeX86_ds:{result = RDI_RegCodeX86_ds;}break; case REGS_RegCodeX86_es:{result = RDI_RegCodeX86_es;}break; case REGS_RegCodeX86_fs:{result = RDI_RegCodeX86_fs;}break; case REGS_RegCodeX86_gs:{result = RDI_RegCodeX86_gs;}break; case REGS_RegCodeX86_tr:{result = RDI_RegCodeX86_tr;}break; case REGS_RegCodeX86_ldtr:{result = RDI_RegCodeX86_ldtr;}break; case REGS_RegCodeX86_ymm0:{result = RDI_RegCodeX86_ymm0;}break; case REGS_RegCodeX86_ymm1:{result = RDI_RegCodeX86_ymm1;}break; case REGS_RegCodeX86_ymm2:{result = RDI_RegCodeX86_ymm2;}break; case REGS_RegCodeX86_ymm3:{result = RDI_RegCodeX86_ymm3;}break; case REGS_RegCodeX86_ymm4:{result = RDI_RegCodeX86_ymm4;}break; case REGS_RegCodeX86_ymm5:{result = RDI_RegCodeX86_ymm5;}break; case REGS_RegCodeX86_ymm6:{result = RDI_RegCodeX86_ymm6;}break; case REGS_RegCodeX86_ymm7:{result = RDI_RegCodeX86_ymm7;}break; } }break; } return result; } internal REGS_RegCode regs_reg_code_from_arch_rdi_code(Arch arch, RDI_RegCode code) { REGS_RegCode result = 0; switch(arch) { default:{}break; case Arch_x64: { switch(code) { default:{}break; case RDI_RegCodeX64_rax:{result = REGS_RegCodeX64_rax;}break; case RDI_RegCodeX64_rcx:{result = REGS_RegCodeX64_rcx;}break; case RDI_RegCodeX64_rdx:{result = REGS_RegCodeX64_rdx;}break; case RDI_RegCodeX64_rbx:{result = REGS_RegCodeX64_rbx;}break; case RDI_RegCodeX64_rsp:{result = REGS_RegCodeX64_rsp;}break; case RDI_RegCodeX64_rbp:{result = REGS_RegCodeX64_rbp;}break; case RDI_RegCodeX64_rsi:{result = REGS_RegCodeX64_rsi;}break; case RDI_RegCodeX64_rdi:{result = REGS_RegCodeX64_rdi;}break; case RDI_RegCodeX64_r8:{result = REGS_RegCodeX64_r8;}break; case RDI_RegCodeX64_r9:{result = REGS_RegCodeX64_r9;}break; case RDI_RegCodeX64_r10:{result = REGS_RegCodeX64_r10;}break; case RDI_RegCodeX64_r11:{result = REGS_RegCodeX64_r11;}break; case RDI_RegCodeX64_r12:{result = REGS_RegCodeX64_r12;}break; case RDI_RegCodeX64_r13:{result = REGS_RegCodeX64_r13;}break; case RDI_RegCodeX64_r14:{result = REGS_RegCodeX64_r14;}break; case RDI_RegCodeX64_r15:{result = REGS_RegCodeX64_r15;}break; case RDI_RegCodeX64_fsbase:{result = REGS_RegCodeX64_fsbase;}break; case RDI_RegCodeX64_gsbase:{result = REGS_RegCodeX64_gsbase;}break; case RDI_RegCodeX64_rip:{result = REGS_RegCodeX64_rip;}break; case RDI_RegCodeX64_rflags:{result = REGS_RegCodeX64_rflags;}break; case RDI_RegCodeX64_dr0:{result = REGS_RegCodeX64_dr0;}break; case RDI_RegCodeX64_dr1:{result = REGS_RegCodeX64_dr1;}break; case RDI_RegCodeX64_dr2:{result = REGS_RegCodeX64_dr2;}break; case RDI_RegCodeX64_dr3:{result = REGS_RegCodeX64_dr3;}break; case RDI_RegCodeX64_dr4:{result = REGS_RegCodeX64_dr4;}break; case RDI_RegCodeX64_dr5:{result = REGS_RegCodeX64_dr5;}break; case RDI_RegCodeX64_dr6:{result = REGS_RegCodeX64_dr6;}break; case RDI_RegCodeX64_dr7:{result = REGS_RegCodeX64_dr7;}break; case RDI_RegCodeX64_fpr0:{result = REGS_RegCodeX64_fpr0;}break; case RDI_RegCodeX64_fpr1:{result = REGS_RegCodeX64_fpr1;}break; case RDI_RegCodeX64_fpr2:{result = REGS_RegCodeX64_fpr2;}break; case RDI_RegCodeX64_fpr3:{result = REGS_RegCodeX64_fpr3;}break; case RDI_RegCodeX64_fpr4:{result = REGS_RegCodeX64_fpr4;}break; case RDI_RegCodeX64_fpr5:{result = REGS_RegCodeX64_fpr5;}break; case RDI_RegCodeX64_fpr6:{result = REGS_RegCodeX64_fpr6;}break; case RDI_RegCodeX64_fpr7:{result = REGS_RegCodeX64_fpr7;}break; case RDI_RegCodeX64_st0:{result = REGS_RegCodeX64_st0;}break; case RDI_RegCodeX64_st1:{result = REGS_RegCodeX64_st1;}break; case RDI_RegCodeX64_st2:{result = REGS_RegCodeX64_st2;}break; case RDI_RegCodeX64_st3:{result = REGS_RegCodeX64_st3;}break; case RDI_RegCodeX64_st4:{result = REGS_RegCodeX64_st4;}break; case RDI_RegCodeX64_st5:{result = REGS_RegCodeX64_st5;}break; case RDI_RegCodeX64_st6:{result = REGS_RegCodeX64_st6;}break; case RDI_RegCodeX64_st7:{result = REGS_RegCodeX64_st7;}break; case RDI_RegCodeX64_fcw:{result = REGS_RegCodeX64_fcw;}break; case RDI_RegCodeX64_fsw:{result = REGS_RegCodeX64_fsw;}break; case RDI_RegCodeX64_ftw:{result = REGS_RegCodeX64_ftw;}break; case RDI_RegCodeX64_fop:{result = REGS_RegCodeX64_fop;}break; case RDI_RegCodeX64_fcs:{result = REGS_RegCodeX64_fcs;}break; case RDI_RegCodeX64_fds:{result = REGS_RegCodeX64_fds;}break; case RDI_RegCodeX64_fip:{result = REGS_RegCodeX64_fip;}break; case RDI_RegCodeX64_fdp:{result = REGS_RegCodeX64_fdp;}break; case RDI_RegCodeX64_mxcsr:{result = REGS_RegCodeX64_mxcsr;}break; case RDI_RegCodeX64_mxcsr_mask:{result = REGS_RegCodeX64_mxcsr_mask;}break; case RDI_RegCodeX64_ss:{result = REGS_RegCodeX64_ss;}break; case RDI_RegCodeX64_cs:{result = REGS_RegCodeX64_cs;}break; case RDI_RegCodeX64_ds:{result = REGS_RegCodeX64_ds;}break; case RDI_RegCodeX64_es:{result = REGS_RegCodeX64_es;}break; case RDI_RegCodeX64_fs:{result = REGS_RegCodeX64_fs;}break; case RDI_RegCodeX64_gs:{result = REGS_RegCodeX64_gs;}break; case RDI_RegCodeX64_zmm0:{result = REGS_RegCodeX64_zmm0;}break; case RDI_RegCodeX64_zmm1:{result = REGS_RegCodeX64_zmm1;}break; case RDI_RegCodeX64_zmm2:{result = REGS_RegCodeX64_zmm2;}break; case RDI_RegCodeX64_zmm3:{result = REGS_RegCodeX64_zmm3;}break; case RDI_RegCodeX64_zmm4:{result = REGS_RegCodeX64_zmm4;}break; case RDI_RegCodeX64_zmm5:{result = REGS_RegCodeX64_zmm5;}break; case RDI_RegCodeX64_zmm6:{result = REGS_RegCodeX64_zmm6;}break; case RDI_RegCodeX64_zmm7:{result = REGS_RegCodeX64_zmm7;}break; case RDI_RegCodeX64_zmm8:{result = REGS_RegCodeX64_zmm8;}break; case RDI_RegCodeX64_zmm9:{result = REGS_RegCodeX64_zmm9;}break; case RDI_RegCodeX64_zmm10:{result = REGS_RegCodeX64_zmm10;}break; case RDI_RegCodeX64_zmm11:{result = REGS_RegCodeX64_zmm11;}break; case RDI_RegCodeX64_zmm12:{result = REGS_RegCodeX64_zmm12;}break; case RDI_RegCodeX64_zmm13:{result = REGS_RegCodeX64_zmm13;}break; case RDI_RegCodeX64_zmm14:{result = REGS_RegCodeX64_zmm14;}break; case RDI_RegCodeX64_zmm15:{result = REGS_RegCodeX64_zmm15;}break; case RDI_RegCodeX64_zmm16:{result = REGS_RegCodeX64_zmm16;}break; case RDI_RegCodeX64_zmm17:{result = REGS_RegCodeX64_zmm17;}break; case RDI_RegCodeX64_zmm18:{result = REGS_RegCodeX64_zmm18;}break; case RDI_RegCodeX64_zmm19:{result = REGS_RegCodeX64_zmm19;}break; case RDI_RegCodeX64_zmm20:{result = REGS_RegCodeX64_zmm20;}break; case RDI_RegCodeX64_zmm21:{result = REGS_RegCodeX64_zmm21;}break; case RDI_RegCodeX64_zmm22:{result = REGS_RegCodeX64_zmm22;}break; case RDI_RegCodeX64_zmm23:{result = REGS_RegCodeX64_zmm23;}break; case RDI_RegCodeX64_zmm24:{result = REGS_RegCodeX64_zmm24;}break; case RDI_RegCodeX64_zmm25:{result = REGS_RegCodeX64_zmm25;}break; case RDI_RegCodeX64_zmm26:{result = REGS_RegCodeX64_zmm26;}break; case RDI_RegCodeX64_zmm27:{result = REGS_RegCodeX64_zmm27;}break; case RDI_RegCodeX64_zmm28:{result = REGS_RegCodeX64_zmm28;}break; case RDI_RegCodeX64_zmm29:{result = REGS_RegCodeX64_zmm29;}break; case RDI_RegCodeX64_zmm30:{result = REGS_RegCodeX64_zmm30;}break; case RDI_RegCodeX64_zmm31:{result = REGS_RegCodeX64_zmm31;}break; case RDI_RegCodeX64_k0:{result = REGS_RegCodeX64_k0;}break; case RDI_RegCodeX64_k1:{result = REGS_RegCodeX64_k1;}break; case RDI_RegCodeX64_k2:{result = REGS_RegCodeX64_k2;}break; case RDI_RegCodeX64_k3:{result = REGS_RegCodeX64_k3;}break; case RDI_RegCodeX64_k4:{result = REGS_RegCodeX64_k4;}break; case RDI_RegCodeX64_k5:{result = REGS_RegCodeX64_k5;}break; case RDI_RegCodeX64_k6:{result = REGS_RegCodeX64_k6;}break; case RDI_RegCodeX64_k7:{result = REGS_RegCodeX64_k7;}break; case RDI_RegCodeX64_cetmsr:{result = REGS_RegCodeX64_cetmsr;}break; case RDI_RegCodeX64_cetssp:{result = REGS_RegCodeX64_cetssp;}break; case RDI_RegCodeX64_tr:{result = REGS_RegCodeX64_tr;}break; case RDI_RegCodeX64_ldtr:{result = REGS_RegCodeX64_ldtr;}break; } }break; case Arch_x86: { switch(code) { default:{}break; case RDI_RegCodeX86_eax:{result = REGS_RegCodeX86_eax;}break; case RDI_RegCodeX86_ecx:{result = REGS_RegCodeX86_ecx;}break; case RDI_RegCodeX86_edx:{result = REGS_RegCodeX86_edx;}break; case RDI_RegCodeX86_ebx:{result = REGS_RegCodeX86_ebx;}break; case RDI_RegCodeX86_esp:{result = REGS_RegCodeX86_esp;}break; case RDI_RegCodeX86_ebp:{result = REGS_RegCodeX86_ebp;}break; case RDI_RegCodeX86_esi:{result = REGS_RegCodeX86_esi;}break; case RDI_RegCodeX86_edi:{result = REGS_RegCodeX86_edi;}break; case RDI_RegCodeX86_fsbase:{result = REGS_RegCodeX86_fsbase;}break; case RDI_RegCodeX86_gsbase:{result = REGS_RegCodeX86_gsbase;}break; case RDI_RegCodeX86_eflags:{result = REGS_RegCodeX86_eflags;}break; case RDI_RegCodeX86_eip:{result = REGS_RegCodeX86_eip;}break; case RDI_RegCodeX86_dr0:{result = REGS_RegCodeX86_dr0;}break; case RDI_RegCodeX86_dr1:{result = REGS_RegCodeX86_dr1;}break; case RDI_RegCodeX86_dr2:{result = REGS_RegCodeX86_dr2;}break; case RDI_RegCodeX86_dr3:{result = REGS_RegCodeX86_dr3;}break; case RDI_RegCodeX86_dr4:{result = REGS_RegCodeX86_dr4;}break; case RDI_RegCodeX86_dr5:{result = REGS_RegCodeX86_dr5;}break; case RDI_RegCodeX86_dr6:{result = REGS_RegCodeX86_dr6;}break; case RDI_RegCodeX86_dr7:{result = REGS_RegCodeX86_dr7;}break; case RDI_RegCodeX86_fpr0:{result = REGS_RegCodeX86_fpr0;}break; case RDI_RegCodeX86_fpr1:{result = REGS_RegCodeX86_fpr1;}break; case RDI_RegCodeX86_fpr2:{result = REGS_RegCodeX86_fpr2;}break; case RDI_RegCodeX86_fpr3:{result = REGS_RegCodeX86_fpr3;}break; case RDI_RegCodeX86_fpr4:{result = REGS_RegCodeX86_fpr4;}break; case RDI_RegCodeX86_fpr5:{result = REGS_RegCodeX86_fpr5;}break; case RDI_RegCodeX86_fpr6:{result = REGS_RegCodeX86_fpr6;}break; case RDI_RegCodeX86_fpr7:{result = REGS_RegCodeX86_fpr7;}break; case RDI_RegCodeX86_st0:{result = REGS_RegCodeX86_st0;}break; case RDI_RegCodeX86_st1:{result = REGS_RegCodeX86_st1;}break; case RDI_RegCodeX86_st2:{result = REGS_RegCodeX86_st2;}break; case RDI_RegCodeX86_st3:{result = REGS_RegCodeX86_st3;}break; case RDI_RegCodeX86_st4:{result = REGS_RegCodeX86_st4;}break; case RDI_RegCodeX86_st5:{result = REGS_RegCodeX86_st5;}break; case RDI_RegCodeX86_st6:{result = REGS_RegCodeX86_st6;}break; case RDI_RegCodeX86_st7:{result = REGS_RegCodeX86_st7;}break; case RDI_RegCodeX86_fcw:{result = REGS_RegCodeX86_fcw;}break; case RDI_RegCodeX86_fsw:{result = REGS_RegCodeX86_fsw;}break; case RDI_RegCodeX86_ftw:{result = REGS_RegCodeX86_ftw;}break; case RDI_RegCodeX86_fop:{result = REGS_RegCodeX86_fop;}break; case RDI_RegCodeX86_fcs:{result = REGS_RegCodeX86_fcs;}break; case RDI_RegCodeX86_fds:{result = REGS_RegCodeX86_fds;}break; case RDI_RegCodeX86_fip:{result = REGS_RegCodeX86_fip;}break; case RDI_RegCodeX86_fdp:{result = REGS_RegCodeX86_fdp;}break; case RDI_RegCodeX86_mxcsr:{result = REGS_RegCodeX86_mxcsr;}break; case RDI_RegCodeX86_mxcsr_mask:{result = REGS_RegCodeX86_mxcsr_mask;}break; case RDI_RegCodeX86_ss:{result = REGS_RegCodeX86_ss;}break; case RDI_RegCodeX86_cs:{result = REGS_RegCodeX86_cs;}break; case RDI_RegCodeX86_ds:{result = REGS_RegCodeX86_ds;}break; case RDI_RegCodeX86_es:{result = REGS_RegCodeX86_es;}break; case RDI_RegCodeX86_fs:{result = REGS_RegCodeX86_fs;}break; case RDI_RegCodeX86_gs:{result = REGS_RegCodeX86_gs;}break; case RDI_RegCodeX86_tr:{result = REGS_RegCodeX86_tr;}break; case RDI_RegCodeX86_ldtr:{result = REGS_RegCodeX86_ldtr;}break; case RDI_RegCodeX86_ymm0:{result = REGS_RegCodeX86_ymm0;}break; case RDI_RegCodeX86_ymm1:{result = REGS_RegCodeX86_ymm1;}break; case RDI_RegCodeX86_ymm2:{result = REGS_RegCodeX86_ymm2;}break; case RDI_RegCodeX86_ymm3:{result = REGS_RegCodeX86_ymm3;}break; case RDI_RegCodeX86_ymm4:{result = REGS_RegCodeX86_ymm4;}break; case RDI_RegCodeX86_ymm5:{result = REGS_RegCodeX86_ymm5;}break; case RDI_RegCodeX86_ymm6:{result = REGS_RegCodeX86_ymm6;}break; case RDI_RegCodeX86_ymm7:{result = REGS_RegCodeX86_ymm7;}break; } }break; } return result; } ================================================ FILE: src/regs/rdi/generated/regs_rdi.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef REGS_RDI_META_H #define REGS_RDI_META_H #endif // REGS_RDI_META_H ================================================ FILE: src/regs/rdi/regs_rdi.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "regs/rdi/generated/regs_rdi.meta.c" ================================================ FILE: src/regs/rdi/regs_rdi.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef REGS_RDI_H #define REGS_RDI_H internal RDI_RegCode regs_rdi_code_from_arch_reg_code(Arch arch, REGS_RegCode code); internal REGS_RegCode regs_reg_code_from_arch_rdi_code(Arch arch, RDI_RegCode reg); #endif //REGS_RDI_H ================================================ FILE: src/regs/rdi/regs_rdi.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: RADDBG Converter Helper Implementation Generators @gen @c_file { `internal RDI_RegCode regs_rdi_code_from_arch_reg_code(Arch arch, REGS_RegCode code)`; `{`; `RDI_RegCode result = 0;`; `switch(arch)`; `{`; `default:{}break;`; `case Arch_x64:`; `{`; `switch(code)` `{`; `default:{}break;`; @expand(REGS_RegTableX64 a) `case REGS_RegCodeX64_$(a.name):{result = RDI_RegCodeX64_$(a.name);}break;`; `}`; `}break;`; `case Arch_x86:`; `{`; `switch(code)` `{`; `default:{}break;`; @expand(REGS_RegTableX86 a) `case REGS_RegCodeX86_$(a.name):{result = RDI_RegCodeX86_$(a.name);}break;`; `}`; `}break;`; `}`; `return result;`; `}`; } @gen @c_file { `internal REGS_RegCode regs_reg_code_from_arch_rdi_code(Arch arch, RDI_RegCode code)`; `{`; `REGS_RegCode result = 0;`; `switch(arch)`; `{`; `default:{}break;`; `case Arch_x64:`; `{`; `switch(code)` `{`; `default:{}break;`; @expand(REGS_RegTableX64 a) `case RDI_RegCodeX64_$(a.name):{result = REGS_RegCodeX64_$(a.name);}break;`; `}`; `}break;`; `case Arch_x86:`; `{`; `switch(code)` `{`; `default:{}break;`; @expand(REGS_RegTableX86 a) `case RDI_RegCodeX86_$(a.name):{result = REGS_RegCodeX86_$(a.name);}break;`; `}`; `}break;`; `}`; `return result;`; `}`; } ================================================ FILE: src/regs/regs.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "regs/generated/regs.meta.c" //////////////////////////////// //~ rjf: Helpers internal REGS_RegCode regs_reg_code_from_name(Arch arch, String8 name) { String8 *name_table = regs_reg_code_string_table_from_arch(arch); U64 name_count = regs_reg_code_count_from_arch(arch); for EachIndex(i, name_count) { if(str8_match(name_table[i], name, StringMatchFlag_CaseInsensitive)) { return (REGS_RegCode)i; } } return 0; } internal REGS_AliasCode regs_alias_code_from_name(Arch arch, String8 name) { String8 *alias_table = regs_alias_code_string_table_from_arch(arch); U64 alias_count = regs_alias_code_count_from_arch(arch); for EachIndex(i, alias_count) { if(str8_match(alias_table[i], name, StringMatchFlag_CaseInsensitive)) { return (REGS_RegCode)i; } } return 0; } internal Rng1U64 regs_range_from_code(Arch arch, B32 is_alias, U64 reg_code) { Rng1U64 range = {0}; if(is_alias) { REGS_Slice slice = regs_alias_code_slice_table_from_arch(arch)[reg_code]; REGS_Rng rng = regs_reg_code_rng_table_from_arch(arch)[reg_code]; range = r1u64(rng.byte_off + slice.byte_off, rng.byte_off + slice.byte_off + slice.byte_size); } else { REGS_Rng rng = regs_reg_code_rng_table_from_arch(arch)[reg_code]; range = r1u64(rng.byte_off, rng.byte_off + rng.byte_size); } return range; } internal U64 regs_rip_from_arch_block(Arch arch, void *block) { U64 result = 0; if(block != 0) switch(arch) { default:{}break; case Arch_x64:{result = ((REGS_RegBlockX64 *)block)->rip.u64;}break; case Arch_x86:{result = (U64)((REGS_RegBlockX86 *)block)->eip.u32;}break; } return result; } internal U64 regs_rsp_from_arch_block(Arch arch, void *block) { U64 result = 0; if(block != 0) switch(arch) { default:{}break; case Arch_x64:{result = ((REGS_RegBlockX64 *)block)->rsp.u64;}break; case Arch_x86:{result = (U64)((REGS_RegBlockX86 *)block)->esp.u32;}break; } return result; } internal void regs_arch_block_write_rip(Arch arch, void *block, U64 rip) { if(block != 0) switch(arch) { default:{}break; case Arch_x64:{((REGS_RegBlockX64 *)block)->rip.u64 = rip;}break; case Arch_x86:{((REGS_RegBlockX86 *)block)->eip.u32 = (U32)rip;}break; } } internal void regs_arch_block_write_rsp(Arch arch, void *block, U64 rsp) { if(block != 0) switch(arch) { default:{}break; case Arch_x64:{((REGS_RegBlockX64 *)block)->rsp.u64 = rsp;}break; case Arch_x86:{((REGS_RegBlockX86 *)block)->esp.u32 = (U32)rsp;}break; } } ================================================ FILE: src/regs/regs.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef REGS_H #define REGS_H //////////////////////////////// //~ rjf: Register Usage Kinds typedef enum REGS_UsageKind { REGS_UsageKind_Normal, REGS_UsageKind_Vector, } REGS_UsageKind; //////////////////////////////// //~ rjf: Register Types typedef U8 REGS_RegCode; typedef U8 REGS_AliasCode; typedef union REGS_Reg16 REGS_Reg16; union REGS_Reg16 { U8 v[2]; U16 u16; }; typedef union REGS_Reg32 REGS_Reg32; union REGS_Reg32 { U8 v[4]; U32 u32; F32 f32; }; typedef union REGS_Reg64 REGS_Reg64; union REGS_Reg64 { U8 v[8]; U64 u64; F64 f64; }; #pragma pack(push, 1) typedef struct REGS_Reg80 REGS_Reg80; struct REGS_Reg80 { U64 int1_frac63; U16 sign1_exp15; }; #pragma pack(pop) typedef union REGS_Reg128 REGS_Reg128; union REGS_Reg128 { U8 v[16]; U32 u32[4]; F32 f32[4]; U64 u64[2]; F64 f64[2]; }; typedef union REGS_Reg256 REGS_Reg256; union REGS_Reg256 { U8 v[32]; U32 u32[8]; F32 f32[8]; U64 u64[4]; F64 f64[4]; }; typedef union REGS_Reg512 REGS_Reg512; union REGS_Reg512 { U8 v[64]; U32 u32[16]; F32 f32[16]; U64 u64[8]; F64 f64[8]; }; //////////////////////////////// //~ rjf: Register Slicing Types typedef struct REGS_Rng REGS_Rng; struct REGS_Rng { U16 byte_off; U16 byte_size; }; typedef struct REGS_Slice REGS_Slice; struct REGS_Slice { U16 code; U8 byte_off; U8 byte_size; }; //////////////////////////////// //~ rjf: Generated Code #include "regs/generated/regs.meta.h" //////////////////////////////// //~ rjf: Helpers internal REGS_RegCode regs_reg_code_from_name(Arch arch, String8 name); internal REGS_AliasCode regs_alias_code_from_name(Arch arch, String8 name); internal Rng1U64 regs_range_from_code(Arch arch, B32 is_alias, U64 reg_code); internal U64 regs_block_size_from_arch(Arch arch); internal U64 regs_reg_code_count_from_arch(Arch arch); internal U64 regs_alias_code_count_from_arch(Arch arch); internal String8 *regs_reg_code_string_table_from_arch(Arch arch); internal String8 *regs_alias_code_string_table_from_arch(Arch arch); internal REGS_Rng *regs_reg_code_rng_table_from_arch(Arch arch); internal REGS_Slice *regs_alias_code_slice_table_from_arch(Arch arch); internal REGS_UsageKind *regs_reg_code_usage_kind_table_from_arch(Arch arch); internal REGS_UsageKind *regs_alias_code_usage_kind_table_from_arch(Arch arch); internal U64 regs_rip_from_arch_block(Arch arch, void *block); internal U64 regs_rsp_from_arch_block(Arch arch, void *block); internal void regs_arch_block_write_rip(Arch arch, void *block, U64 rip); internal void regs_arch_block_write_rsp(Arch arch, void *block, U64 rsp); #endif // REGS_H ================================================ FILE: src/regs/regs.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: X64 Tables @table(name size usage) REGS_RegTableX64: { {rax 64 Normal} {rcx 64 Normal} {rdx 64 Normal} {rbx 64 Normal} {rsp 64 Normal} {rbp 64 Normal} {rsi 64 Normal} {rdi 64 Normal} {r8 64 Normal} {r9 64 Normal} {r10 64 Normal} {r11 64 Normal} {r12 64 Normal} {r13 64 Normal} {r14 64 Normal} {r15 64 Normal} {fsbase 64 Normal} {gsbase 64 Normal} {rip 64 Normal} {rflags 64 Normal} {dr0 64 Normal} {dr1 64 Normal} {dr2 64 Normal} {dr3 64 Normal} {dr4 64 Normal} {dr5 64 Normal} {dr6 64 Normal} {dr7 64 Normal} {fpr0 80 Normal} {fpr1 80 Normal} {fpr2 80 Normal} {fpr3 80 Normal} {fpr4 80 Normal} {fpr5 80 Normal} {fpr6 80 Normal} {fpr7 80 Normal} {st0 80 Normal} {st1 80 Normal} {st2 80 Normal} {st3 80 Normal} {st4 80 Normal} {st5 80 Normal} {st6 80 Normal} {st7 80 Normal} {fcw 16 Normal} {fsw 16 Normal} {ftw 16 Normal} {fop 16 Normal} {fcs 16 Normal} {fds 16 Normal} {fip 64 Normal} {fdp 64 Normal} {mxcsr 32 Normal} {mxcsr_mask 32 Normal} {ss 16 Normal} {cs 16 Normal} {ds 16 Normal} {es 16 Normal} {fs 16 Normal} {gs 16 Normal} {zmm0 512 Vector} {zmm1 512 Vector} {zmm2 512 Vector} {zmm3 512 Vector} {zmm4 512 Vector} {zmm5 512 Vector} {zmm6 512 Vector} {zmm7 512 Vector} {zmm8 512 Vector} {zmm9 512 Vector} {zmm10 512 Vector} {zmm11 512 Vector} {zmm12 512 Vector} {zmm13 512 Vector} {zmm14 512 Vector} {zmm15 512 Vector} {zmm16 512 Vector} {zmm17 512 Vector} {zmm18 512 Vector} {zmm19 512 Vector} {zmm20 512 Vector} {zmm21 512 Vector} {zmm22 512 Vector} {zmm23 512 Vector} {zmm24 512 Vector} {zmm25 512 Vector} {zmm26 512 Vector} {zmm27 512 Vector} {zmm28 512 Vector} {zmm29 512 Vector} {zmm30 512 Vector} {zmm31 512 Vector} {k0 64 Normal} {k1 64 Normal} {k2 64 Normal} {k3 64 Normal} {k4 64 Normal} {k5 64 Normal} {k6 64 Normal} {k7 64 Normal} {cetmsr 64 Normal} {cetssp 64 Normal} {tr 16 Normal} {ldtr 16 Normal} } @table(name base off size usage) REGS_AliasTableX64: { {eax rax 0 32 Normal} {ecx rcx 0 32 Normal} {edx rdx 0 32 Normal} {ebx rbx 0 32 Normal} {esp rsp 0 32 Normal} {ebp rbp 0 32 Normal} {esi rsi 0 32 Normal} {edi rdi 0 32 Normal} {r8d r8 0 32 Normal} {r9d r9 0 32 Normal} {r10d r10 0 32 Normal} {r11d r11 0 32 Normal} {r12d r12 0 32 Normal} {r13d r13 0 32 Normal} {r14d r14 0 32 Normal} {r15d r15 0 32 Normal} // TODO(allen): figure this one out; visual studio disagrees {eip rip 0 32 Normal} {eflags rflags 0 32 Normal} {ax rax 0 16 Normal} {cx rcx 0 16 Normal} {dx rdx 0 16 Normal} {bx rbx 0 16 Normal} {si rsi 0 16 Normal} {di rdi 0 16 Normal} {sp rsp 0 16 Normal} {bp rbp 0 16 Normal} {ip rip 0 16 Normal} {r8w r8 0 16 Normal} {r9w r9 0 16 Normal} {r10w r10 0 16 Normal} {r11w r11 0 16 Normal} {r12w r12 0 16 Normal} {r13w r13 0 16 Normal} {r14w r14 0 16 Normal} {r15w r15 0 16 Normal} {al rax 0 8 Normal} {cl rcx 0 8 Normal} {dl rdx 0 8 Normal} {bl rbx 0 8 Normal} {sil rsi 0 8 Normal} {dil rdi 0 8 Normal} {bpl rbp 0 8 Normal} {spl rsp 0 8 Normal} {r8b r8 0 8 Normal} {r9b r9 0 8 Normal} {r10b r10 0 8 Normal} {r11b r11 0 8 Normal} {r12b r12 0 8 Normal} {r13b r13 0 8 Normal} {r14b r14 0 8 Normal} {r15b r15 0 8 Normal} {ah rax 8 8 Normal} {ch rcx 8 8 Normal} {dh rdx 8 8 Normal} {bh rbx 8 8 Normal} {xmm0 zmm0 0 128 Vector} {xmm1 zmm1 0 128 Vector} {xmm2 zmm2 0 128 Vector} {xmm3 zmm3 0 128 Vector} {xmm4 zmm4 0 128 Vector} {xmm5 zmm5 0 128 Vector} {xmm6 zmm6 0 128 Vector} {xmm7 zmm7 0 128 Vector} {xmm8 zmm8 0 128 Vector} {xmm9 zmm9 0 128 Vector} {xmm10 zmm10 0 128 Vector} {xmm11 zmm11 0 128 Vector} {xmm12 zmm12 0 128 Vector} {xmm13 zmm13 0 128 Vector} {xmm14 zmm14 0 128 Vector} {xmm15 zmm15 0 128 Vector} {ymm0 zmm0 0 256 Vector} {ymm1 zmm1 0 256 Vector} {ymm2 zmm2 0 256 Vector} {ymm3 zmm3 0 256 Vector} {ymm4 zmm4 0 256 Vector} {ymm5 zmm5 0 256 Vector} {ymm6 zmm6 0 256 Vector} {ymm7 zmm7 0 256 Vector} {ymm8 zmm8 0 256 Vector} {ymm9 zmm9 0 256 Vector} {ymm10 zmm10 0 256 Vector} {ymm11 zmm11 0 256 Vector} {ymm12 zmm12 0 256 Vector} {ymm13 zmm13 0 256 Vector} {ymm14 zmm14 0 256 Vector} {ymm15 zmm15 0 256 Vector} {mm0 fpr0 0 64 Vector} {mm1 fpr1 0 64 Vector} {mm2 fpr2 0 64 Vector} {mm3 fpr3 0 64 Vector} {mm4 fpr4 0 64 Vector} {mm5 fpr5 0 64 Vector} {mm6 fpr6 0 64 Vector} {mm7 fpr7 0 64 Vector} } //////////////////////////////// //~ rjf: X86 Tables @table(name size usage) REGS_RegTableX86: { {eax 32 Normal} {ecx 32 Normal} {edx 32 Normal} {ebx 32 Normal} {esp 32 Normal} {ebp 32 Normal} {esi 32 Normal} {edi 32 Normal} {fsbase 32 Normal} {gsbase 32 Normal} {eflags 32 Normal} {eip 32 Normal} {dr0 32 Normal} {dr1 32 Normal} {dr2 32 Normal} {dr3 32 Normal} {dr4 32 Normal} {dr5 32 Normal} {dr6 32 Normal} {dr7 32 Normal} // FSave registers // TODO(allen): I am suspicious of this stuff here. // Are fpr0-7 and st0-7 actually different things? Visual studio doesn't show // frp0-7. Not sure if the mm0-7 aliases are setup the right way either. {fpr0 80 Normal} {fpr1 80 Normal} {fpr2 80 Normal} {fpr3 80 Normal} {fpr4 80 Normal} {fpr5 80 Normal} {fpr6 80 Normal} {fpr7 80 Normal} {st0 80 Normal} {st1 80 Normal} {st2 80 Normal} {st3 80 Normal} {st4 80 Normal} {st5 80 Normal} {st6 80 Normal} {st7 80 Normal} {fcw 16 Normal} {fsw 16 Normal} {ftw 16 Normal} {fop 16 Normal} {fcs 16 Normal} {fds 16 Normal} {fip 32 Normal} {fdp 32 Normal} {mxcsr 32 Normal} // TODO(allen): I don't think this is really a "register" - think about this... {mxcsr_mask 32 Normal} {ss 16 Normal} {cs 16 Normal} {ds 16 Normal} {es 16 Normal} {fs 16 Normal} {gs 16 Normal} {tr 16 Normal} {ldtr 16 Normal} // SIMD REGISTERS {ymm0 256 Vector} {ymm1 256 Vector} {ymm2 256 Vector} {ymm3 256 Vector} {ymm4 256 Vector} {ymm5 256 Vector} {ymm6 256 Vector} {ymm7 256 Vector} } @table(name base off size usage) REGS_AliasTableX86: { {ax eax 0 16 Normal} {cx ecx 0 16 Normal} {bx ebx 0 16 Normal} {dx edx 0 16 Normal} {sp esp 0 16 Normal} {bp ebp 0 16 Normal} {si esi 0 16 Normal} {di edi 0 16 Normal} {ip eip 0 16 Normal} {ah eax 8 8 Normal} {ch ecx 8 8 Normal} {dh edx 8 8 Normal} {bh ebx 8 8 Normal} {al eax 0 8 Normal} {cl ecx 0 8 Normal} {dl edx 0 8 Normal} {bl ebx 0 8 Normal} {bpl ebp 0 8 Normal} {spl esp 0 8 Normal} {xmm0 ymm0 0 128 Vector} {xmm1 ymm1 0 128 Vector} {xmm2 ymm2 0 128 Vector} {xmm3 ymm3 0 128 Vector} {xmm4 ymm4 0 128 Vector} {xmm5 ymm5 0 128 Vector} {xmm6 ymm6 0 128 Vector} {xmm7 ymm7 0 128 Vector} {mm0 fpr0 0 64 Vector} {mm1 fpr1 0 64 Vector} {mm2 fpr2 0 64 Vector} {mm3 fpr3 0 64 Vector} {mm4 fpr4 0 64 Vector} {mm5 fpr5 0 64 Vector} {mm6 fpr6 0 64 Vector} {mm7 fpr7 0 64 Vector} } //////////////////////////////// //~ rjf: Architecture Tables @table(name, name_lower) REGS_ArchTable: { {X64 x64} {X86 x86} } //////////////////////////////// //~ rjf: X64 Generators @enum REGS_RegCodeX64: { NULL, @expand(REGS_RegTableX64 a) `$(a.name)`, COUNT, } @enum REGS_AliasCodeX64: { NULL, @expand(REGS_AliasTableX64 a) `$(a.name)`, COUNT, } @struct REGS_RegBlockX64: { @expand(REGS_RegTableX64 a) `REGS_Reg$(a.size) $(a.name)`, } @data(REGS_UsageKind) regs_g_reg_code_x64_usage_kind_table: { `REGS_UsageKind_Normal`; @expand(REGS_RegTableX64 a) `REGS_UsageKind_$(a.usage)`; } @data(REGS_UsageKind) regs_g_alias_code_x64_usage_kind_table: { `REGS_UsageKind_Normal`; @expand(REGS_AliasTableX64 a) `REGS_UsageKind_$(a.usage)`; } @data(String8) regs_g_reg_code_x64_string_table: { `str8_lit_comp("")`; @expand(REGS_RegTableX64 a) `str8_lit_comp("$(a.name)")`; } @data(String8) regs_g_alias_code_x64_string_table: { `str8_lit_comp("")`; @expand(REGS_AliasTableX64 a) `str8_lit_comp("$(a.name)")`; } @data(REGS_Rng) regs_g_reg_code_x64_rng_table: { `{0}`; @expand(REGS_RegTableX64 a) `{(U16)OffsetOf(REGS_RegBlockX64, $(a.name)), $(a.size/8)}`, } @data(REGS_Slice) regs_g_alias_code_x64_slice_table: { `{0}`; @expand(REGS_AliasTableX64 a) `{REGS_RegCodeX64_$(a.base), $(a.off/8), $(a.size/8)}`, } //////////////////////////////// //~ rjf: X86 Generators @enum REGS_RegCodeX86: { NULL, @expand(REGS_RegTableX86 a) `$(a.name)`, COUNT, } @enum REGS_AliasCodeX86: { NULL, @expand(REGS_AliasTableX86 a) `$(a.name)`, COUNT, } @struct REGS_RegBlockX86: { @expand(REGS_RegTableX86 a) `REGS_Reg$(a.size) $(a.name)`, } @data(REGS_UsageKind) regs_g_reg_code_x86_usage_kind_table: { `REGS_UsageKind_Normal`; @expand(REGS_RegTableX86 a) `REGS_UsageKind_$(a.usage)`; } @data(REGS_UsageKind) regs_g_alias_code_x86_usage_kind_table: { `REGS_UsageKind_Normal`; @expand(REGS_AliasTableX86 a) `REGS_UsageKind_$(a.usage)`; } @data(String8) regs_g_reg_code_x86_string_table: { `str8_lit_comp("")`; @expand(REGS_RegTableX86 a) `str8_lit_comp("$(a.name)")`; } @data(String8) regs_g_alias_code_x86_string_table: { `str8_lit_comp("")`; @expand(REGS_AliasTableX86 a) `str8_lit_comp("$(a.name)")`; } @data(REGS_Rng) regs_g_reg_code_x86_rng_table: { `{0}`; @expand(REGS_RegTableX86 a) `{(U16)OffsetOf(REGS_RegBlockX86, $(a.name)), $(a.size/8)}`, } @data(REGS_Slice) regs_g_alias_code_x86_slice_table: { `{0}`; @expand(REGS_AliasTableX86 a) `{REGS_RegCodeX86_$(a.base), $(a.off/8), $(a.size/8)}`, } //////////////////////////////// //~ rjf: Architecture-Dynamic Helper Implementation Generators @c_file @gen { `internal U64 regs_block_size_from_arch(Arch arch)`; `{`; `U64 result = 8;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = sizeof(REGS_RegBlock$(a.name));}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal U64 regs_reg_code_count_from_arch(Arch arch)`; `{`; `U64 result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = REGS_RegCode$(a.name)_COUNT;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal U64 regs_alias_code_count_from_arch(Arch arch)`; `{`; `U64 result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = REGS_AliasCode$(a.name)_COUNT;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal String8 *regs_reg_code_string_table_from_arch(Arch arch)`; `{`; `String8 *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_reg_code_$(a.name_lower)_string_table;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal String8 *regs_alias_code_string_table_from_arch(Arch arch)`; `{`; `String8 *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_alias_code_$(a.name_lower)_string_table;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal REGS_Rng *regs_reg_code_rng_table_from_arch(Arch arch)`; `{`; `REGS_Rng *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_reg_code_$(a.name_lower)_rng_table;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal REGS_Slice *regs_alias_code_slice_table_from_arch(Arch arch)`; `{`; `REGS_Slice *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_alias_code_$(a.name_lower)_slice_table;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal REGS_UsageKind *regs_reg_code_usage_kind_table_from_arch(Arch arch)`; `{`; `REGS_UsageKind *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_reg_code_$(a.name_lower)_usage_kind_table;}break;`; `}`; `return result;`; `}`; } @c_file @gen { `internal REGS_UsageKind *regs_alias_code_usage_kind_table_from_arch(Arch arch)`; `{`; `REGS_UsageKind *result = 0;`; `switch(arch)`; `{`; `default:{}break;`; @expand(REGS_ArchTable a) `case Arch_$(a.name_lower):{result = regs_g_alias_code_$(a.name_lower)_usage_kind_table;}break;`; `}`; `return result;`; `}`; } ================================================ FILE: src/render/d3d11/generated/render_d3d11.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8* r_d3d11_g_vshad_kind_source_table[5] = { &r_d3d11_g_rect_shader_src, &r_d3d11_g_blur_shader_src, &r_d3d11_g_mesh_shader_src, &r_d3d11_g_geo3dcomposite_shader_src, &r_d3d11_g_finalize_shader_src, }; String8 r_d3d11_g_vshad_kind_source_name_table[5] = { str8_lit_comp("r_d3d11_g_rect_shader_src"), str8_lit_comp("r_d3d11_g_blur_shader_src"), str8_lit_comp("r_d3d11_g_mesh_shader_src"), str8_lit_comp("r_d3d11_g_geo3dcomposite_shader_src"), str8_lit_comp("r_d3d11_g_finalize_shader_src"), }; D3D11_INPUT_ELEMENT_DESC * r_d3d11_g_vshad_kind_elements_ptr_table[5] = { r_d3d11_g_rect_ilay_elements, 0, r_d3d11_g_mesh_ilay_elements, 0, 0, }; U64 r_d3d11_g_vshad_kind_elements_count_table[5] = { ArrayCount(r_d3d11_g_rect_ilay_elements) , 0, ArrayCount(r_d3d11_g_mesh_ilay_elements) , 0, 0, }; String8* r_d3d11_g_pshad_kind_source_table[5] = { &r_d3d11_g_rect_shader_src, &r_d3d11_g_blur_shader_src, &r_d3d11_g_mesh_shader_src, &r_d3d11_g_geo3dcomposite_shader_src, &r_d3d11_g_finalize_shader_src, }; String8 r_d3d11_g_pshad_kind_source_name_table[5] = { str8_lit_comp("r_d3d11_g_rect_shader_src"), str8_lit_comp("r_d3d11_g_blur_shader_src"), str8_lit_comp("r_d3d11_g_mesh_shader_src"), str8_lit_comp("r_d3d11_g_geo3dcomposite_shader_src"), str8_lit_comp("r_d3d11_g_finalize_shader_src"), }; U64 r_d3d11_g_uniform_type_kind_size_table[3] = { sizeof(R_D3D11_Uniforms_Rect), sizeof(R_D3D11_Uniforms_Blur), sizeof(R_D3D11_Uniforms_Mesh), }; C_LINKAGE_END ================================================ FILE: src/render/d3d11/generated/render_d3d11.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef RENDER_D3D11_META_H #define RENDER_D3D11_META_H typedef enum R_D3D11_VShadKind { R_D3D11_VShadKind_Rect, R_D3D11_VShadKind_Blur, R_D3D11_VShadKind_Mesh, R_D3D11_VShadKind_Geo3DComposite, R_D3D11_VShadKind_Finalize, R_D3D11_VShadKind_COUNT, } R_D3D11_VShadKind; typedef enum R_D3D11_PShadKind { R_D3D11_PShadKind_Rect, R_D3D11_PShadKind_Blur, R_D3D11_PShadKind_Mesh, R_D3D11_PShadKind_Geo3DComposite, R_D3D11_PShadKind_Finalize, R_D3D11_PShadKind_COUNT, } R_D3D11_PShadKind; typedef enum R_D3D11_UniformTypeKind { R_D3D11_UniformTypeKind_Rect, R_D3D11_UniformTypeKind_Blur, R_D3D11_UniformTypeKind_Mesh, R_D3D11_UniformTypeKind_COUNT, } R_D3D11_UniformTypeKind; C_LINKAGE_BEGIN read_only global String8 r_d3d11_g_rect_shader_src = str8_lit_comp( "" "\n" "cbuffer Globals : register(b0)\n" "{\n" " float2 viewport_size_px;\n" " float opacity;\n" " row_major float4x4 texture_sample_channel_map;\n" " float2 texture_t2d_size_px;\n" " row_major float3x3 xform;\n" " float2 xform_scale;\n" "}\n" "\n" "struct CPU2Vertex\n" "{\n" " float4 dst_rect_px : POS;\n" " float4 src_rect_px : TEX;\n" " float4 color00 : COL0;\n" " float4 color01 : COL1;\n" " float4 color10 : COL2;\n" " float4 color11 : COL3;\n" " float4 corner_radii_px : CRAD;\n" " float4 style_params : STY; // x: border_thickness_px, y: softness_px, z: omit_texture, w: shear\n" " uint vertex_id : SV_VertexID;\n" "};\n" "\n" "struct Vertex2Pixel\n" "{\n" " float4 position : SV_POSITION;\n" " nointerpolation float2 rect_half_size_px : PSIZE;\n" " float2 texcoord_pct : TEX;\n" " float2 sdf_sample_pos : SDF;\n" " float4 tint : TINT;\n" " float corner_radius_px : CRAD;\n" " nointerpolation float border_thickness_px : BTHC;\n" " nointerpolation float softness_px : SFT;\n" " nointerpolation float omit_texture : OTX;\n" "};\n" "\n" "Texture2D main_t2d : register(t0);\n" "SamplerState main_sampler : register(s0);\n" "\n" "float rect_sdf(float2 sample_pos, float2 rect_half_size, float r)\n" "{\n" " return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" "}\n" "\n" "float linear_from_srgb_f32(float x)\n" "{\n" " return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);\n" "}\n" "\n" "float4 linear_from_srgba(float4 v)\n" "{\n" " float4 result = float4(linear_from_srgb_f32(v.x),\n" " linear_from_srgb_f32(v.y),\n" " linear_from_srgb_f32(v.z),\n" " v.w);\n" " return result;\n" "}\n" "\n" "//- rjf: vertex shader\n" "\n" "Vertex2Pixel\n" "vs_main(CPU2Vertex cpu2vertex)\n" "{\n" " //- rjf: unpack & xform rectangle src/dst vertices\n" " float2 dst_p0_px = cpu2vertex.dst_rect_px.xy;\n" " float2 dst_p1_px = cpu2vertex.dst_rect_px.zw;\n" " float2 src_p0_px = cpu2vertex.src_rect_px.xy;\n" " float2 src_p1_px = cpu2vertex.src_rect_px.zw;\n" " float2 dst_size_px = abs(dst_p1_px - dst_p0_px);\n" " \n" " //- rjf: unpack style params\n" " float border_thickness_px = cpu2vertex.style_params.x;\n" " float softness_px = cpu2vertex.style_params.y;\n" " float omit_texture = cpu2vertex.style_params.z;\n" " float shear_px = cpu2vertex.style_params.w;\n" " \n" " //- rjf: prep per-vertex arrays to sample from (p: position, t: texcoord, c: colorcoord, r: cornerradius)\n" " float2 dst_p_verts_px[] =\n" " {\n" " float2(dst_p0_px.x, dst_p1_px.y),\n" " float2(dst_p0_px.x, dst_p0_px.y),\n" " float2(dst_p1_px.x, dst_p1_px.y + shear_px),\n" " float2(dst_p1_px.x, dst_p0_px.y + shear_px),\n" " };\n" " float2 src_p_verts_px[] =\n" " {\n" " float2(src_p0_px.x, src_p1_px.y),\n" " float2(src_p0_px.x, src_p0_px.y),\n" " float2(src_p1_px.x, src_p1_px.y),\n" " float2(src_p1_px.x, src_p0_px.y),\n" " };\n" " float dst_r_verts_px[] =\n" " {\n" " cpu2vertex.corner_radii_px.y,\n" " cpu2vertex.corner_radii_px.x,\n" " cpu2vertex.corner_radii_px.w,\n" " cpu2vertex.corner_radii_px.z,\n" " };\n" " float4 src_color[] =\n" " {\n" " cpu2vertex.color01,\n" " cpu2vertex.color00,\n" " cpu2vertex.color11,\n" " cpu2vertex.color10,\n" " };\n" " float2 dst_verts_pct = float2((cpu2vertex.vertex_id >> 1) ? 1.f : 0.f,\n" " (cpu2vertex.vertex_id & 1) ? 0.f : 1.f);\n" " \n" " // rjf: fill vertex -> pixel data\n" " Vertex2Pixel vertex2pixel;\n" " {\n" " float2 xformed_pos = mul(xform, float3(dst_p_verts_px[cpu2vertex.vertex_id], 1.f)).xy;\n" " xformed_pos.y = viewport_size_px.y - xformed_pos.y;\n" " vertex2pixel.position.xy = 2.f * xformed_pos/viewport_size_px - 1.f;\n" " vertex2pixel.position.z = 0.f;\n" " vertex2pixel.position.w = 1.f;\n" " vertex2pixel.rect_half_size_px = dst_size_px / 2.f * xform_scale;\n" " vertex2pixel.texcoord_pct = src_p_verts_px[cpu2vertex.vertex_id] / texture_t2d_size_px;\n" " vertex2pixel.sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * vertex2pixel.rect_half_size_px;\n" " vertex2pixel.tint = src_color[cpu2vertex.vertex_id];\n" " vertex2pixel.corner_radius_px = dst_r_verts_px[cpu2vertex.vertex_id];\n" " vertex2pixel.border_thickness_px = border_thickness_px;\n" " vertex2pixel.softness_px = softness_px;\n" " vertex2pixel.omit_texture = omit_texture;\n" " }\n" " return vertex2pixel;\n" "}\n" "\n" "//- rjf: pixel shader\n" "\n" "float4\n" "ps_main(Vertex2Pixel vertex2pixel) : SV_TARGET\n" "{\n" " // rjf: blend corner colors to produce final tint\n" " float4 tint = vertex2pixel.tint;\n" " \n" " // rjf: sample texture\n" " float4 albedo_sample = float4(1, 1, 1, 1);\n" " if(vertex2pixel.omit_texture < 1)\n" " {\n" " albedo_sample = mul(main_t2d.Sample(main_sampler, vertex2pixel.texcoord_pct), texture_sample_channel_map);\n" " albedo_sample = linear_from_srgba(albedo_sample);\n" " }\n" " \n" " // rjf: determine SDF sample position\n" " float2 sdf_sample_pos = vertex2pixel.sdf_sample_pos;\n" " \n" " // rjf: sample for borders\n" " float border_sdf_t = 1;\n" " if(vertex2pixel.border_thickness_px > 0)\n" " {\n" " float border_sdf_s = rect_sdf(sdf_sample_pos,\n" " vertex2pixel.rect_half_size_px - float2(vertex2pixel.softness_px*2.f, vertex2pixel.softness_px*2.f) - vertex2pixel.border_thickness_px,\n" " max(vertex2pixel.corner_radius_px-vertex2pixel.border_thickness_px, 0));\n" " border_sdf_t = smoothstep(0, 2*vertex2pixel.softness_px, border_sdf_s);\n" " }\n" " if(border_sdf_t < 0.001f)\n" " {\n" " discard;\n" " }\n" " \n" " // rjf: sample for corners\n" " float corner_sdf_t = 1;\n" " if(vertex2pixel.corner_radius_px > 0 || vertex2pixel.softness_px > 0.75f)\n" " {\n" " float corner_sdf_s = rect_sdf(sdf_sample_pos,\n" " vertex2pixel.rect_half_size_px - float2(vertex2pixel.softness_px*2.f, vertex2pixel.softness_px*2.f),\n" " vertex2pixel.corner_radius_px);\n" " corner_sdf_t = 1-smoothstep(0, 2*vertex2pixel.softness_px, corner_sdf_s);\n" " }\n" " \n" " // rjf: form+return final color\n" " float4 final_color = albedo_sample;\n" " final_color *= tint;\n" " final_color.a *= opacity;\n" " final_color.a *= corner_sdf_t;\n" " final_color.a *= border_sdf_t;\n" " return final_color;\n" "}\n" "" ); read_only global String8 r_d3d11_g_blur_shader_src = str8_lit_comp( "" "\n" "cbuffer Globals : register(b0)\n" "{\n" " float4 rect;\n" " float4 corner_radii_px;\n" " float2 direction;\n" " float2 viewport_size;\n" " uint blur_count;\n" "}\n" "\n" "cbuffer Kernel : register(b1)\n" "{\n" " float4 kernel[32];\n" "}\n" "\n" "struct CPU2Vertex\n" "{\n" " uint vertex_id : SV_VertexID;\n" "};\n" "\n" "struct Vertex2Pixel\n" "{\n" " float4 position : SV_POSITION;\n" " float2 texcoord : TEX;\n" " float2 sdf_sample_pos : SDF;\n" " nointerpolation float2 rect_half_size : RHS;\n" " float corner_radius : RAD;\n" "};\n" "\n" "Texture2D stage_t2d : register(t0);\n" "SamplerState stage_sampler : register(s0);\n" "\n" "float rect_sdf(float2 sample_pos, float2 rect_half_size, float r)\n" "{\n" " return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" "}\n" "\n" "//- rjf: vertex shader\n" "\n" "Vertex2Pixel\n" "vs_main(CPU2Vertex c2v)\n" "{\n" " float2 vertex_positions__scrn[] =\n" " {\n" " rect.xw,\n" " rect.xy,\n" " rect.zw,\n" " rect.zy,\n" " };\n" " float corner_radii__px[] =\n" " {\n" " corner_radii_px.y,\n" " corner_radii_px.x,\n" " corner_radii_px.w,\n" " corner_radii_px.z,\n" " };\n" " float2 cornercoords__pct = float2((c2v.vertex_id >> 1) ? 1.f : 0.f,\n" " (c2v.vertex_id & 1) ? 0.f : 1.f);\n" " \n" " float2 vertex_position__pct = vertex_positions__scrn[c2v.vertex_id] / viewport_size;\n" " float2 vertex_position__scr = 2.f * vertex_position__pct - 1.f;\n" " \n" " float2 rect_half_size = float2((rect.z-rect.x)/2, (rect.w-rect.y)/2);\n" " \n" " Vertex2Pixel v2p;\n" " {\n" " v2p.position = float4(vertex_position__scr.x, -vertex_position__scr.y, 0.f, 1.f);\n" " v2p.texcoord = vertex_position__pct;\n" " v2p.sdf_sample_pos = (2.f * cornercoords__pct - 1.f) * rect_half_size;\n" " v2p.rect_half_size = rect_half_size - 2.f;\n" " v2p.corner_radius = corner_radii__px[c2v.vertex_id];\n" " }\n" " return v2p;\n" "}\n" "\n" "//- rjf: pixel shader\n" "\n" "float4\n" "ps_main(Vertex2Pixel v2p) : SV_TARGET\n" "{\n" " // rjf: blend weighted texture samples into color\n" " float3 color = kernel[0].x * stage_t2d.Sample(stage_sampler, v2p.texcoord).rgb;\n" " \n" " for(uint i = 1; i < blur_count; i += 1)\n" " {\n" " float weight = kernel[i].x;\n" " float offset = kernel[i].y;\n" " color += weight * stage_t2d.Sample(stage_sampler, v2p.texcoord - offset * direction).rgb;\n" " color += weight * stage_t2d.Sample(stage_sampler, v2p.texcoord + offset * direction).rgb;\n" " }\n" " \n" " // rjf: sample for corners\n" " float corner_sdf_s = rect_sdf(v2p.sdf_sample_pos, v2p.rect_half_size, v2p.corner_radius);\n" " float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s);\n" " \n" " // rjf: weight output color by sdf\n" " // this is doing alpha testing, leave blurring only where mostly opaque pixels are\n" " if (corner_sdf_t < 0.9f)\n" " {\n" " discard;\n" " }\n" " \n" " return float4(color, 1.f);\n" "}\n" "" ); read_only global String8 r_d3d11_g_mesh_shader_src = str8_lit_comp( "" "\n" "cbuffer Uniforms : register(b0)\n" "{\n" " row_major float4x4 xform;\n" "}\n" "\n" "struct CPU2Vertex\n" "{\n" " float3 position : POS;\n" " float3 normal : NOR;\n" " float2 texcoord : TEX;\n" " float3 color : COL;\n" "};\n" "\n" "struct Vertex2Pixel\n" "{\n" " float4 position : SV_POSITION;\n" " float2 texcoord : TEX;\n" " float4 color : COL;\n" "};\n" "\n" "Vertex2Pixel vs_main(CPU2Vertex c2v)\n" "{\n" " Vertex2Pixel v2p;\n" " v2p.position = mul(float4(c2v.position, 1.f), xform);\n" " v2p.texcoord = c2v.texcoord;\n" " v2p.color = float4(c2v.color, 1.f);\n" " return v2p;\n" "}\n" "\n" "float4 ps_main(Vertex2Pixel v2p) : SV_TARGET\n" "{\n" " return v2p.color;\n" "}\n" "" ); read_only global String8 r_d3d11_g_geo3dcomposite_shader_src = str8_lit_comp( "" "\n" "struct CPU2Vertex\n" "{\n" " uint vertex_id : SV_VertexID;\n" "};\n" "\n" "struct Vertex2Pixel\n" "{\n" " float4 position : SV_POSITION;\n" " float2 texcoord : TEX;\n" "};\n" "\n" "Texture2D stage_t2d : register(t0);\n" "SamplerState stage_sampler : register(s0);\n" "\n" "//- rjf: vertex shader\n" "\n" "Vertex2Pixel\n" "vs_main(CPU2Vertex c2v)\n" "{\n" " float4 vertex_positions__modl[] =\n" " {\n" " float4(0, 0, 0, 1),\n" " float4(0, 1, 0, 1),\n" " float4(1, 0, 0, 1),\n" " float4(1, 1, 0, 1),\n" " };\n" " float4 vertex_position__modl = vertex_positions__modl[c2v.vertex_id];\n" " float4 vertex_position__clip = float4(2*vertex_position__modl.x - 1, 2*vertex_position__modl.y - 1, 0, 1);\n" " float2 texcoord = float2(vertex_position__modl.x, vertex_position__modl.y);\n" " texcoord.y = 1-texcoord.y;\n" " Vertex2Pixel v2p;\n" " {\n" " v2p.position = vertex_position__clip;\n" " v2p.texcoord = texcoord;\n" " }\n" " return v2p;\n" "}\n" "\n" "//- rjf: pixel shader\n" "\n" "float4\n" "ps_main(Vertex2Pixel v2p) : SV_TARGET\n" "{\n" " float4 final_color = stage_t2d.Sample(stage_sampler, v2p.texcoord);\n" " return final_color;\n" "}\n" "" ); read_only global String8 r_d3d11_g_finalize_shader_src = str8_lit_comp( "" "\n" "struct CPU2Vertex\n" "{\n" " uint vertex_id : SV_VertexID;\n" "};\n" "\n" "struct Vertex2Pixel\n" "{\n" " float4 position : SV_POSITION;\n" " float2 texcoord : TEX;\n" "};\n" "\n" "Texture2D stage_t2d : register(t0);\n" "SamplerState stage_sampler : register(s0);\n" "\n" "//- rjf: vertex shader\n" "\n" "Vertex2Pixel\n" "vs_main(CPU2Vertex c2v)\n" "{\n" " float4 vertex_positions__modl[] =\n" " {\n" " float4(0, 0, 0, 1),\n" " float4(0, 1, 0, 1),\n" " float4(1, 0, 0, 1),\n" " float4(1, 1, 0, 1),\n" " };\n" " float4 vertex_position__modl = vertex_positions__modl[c2v.vertex_id];\n" " float4 vertex_position__clip = float4(2*vertex_position__modl.x - 1, 2*vertex_position__modl.y - 1, 0, 1);\n" " float2 texcoord = float2(vertex_position__modl.x, vertex_position__modl.y);\n" " texcoord.y = 1-texcoord.y;\n" " Vertex2Pixel v2p;\n" " {\n" " v2p.position = vertex_position__clip;\n" " v2p.texcoord = texcoord;\n" " }\n" " return v2p;\n" "}\n" "\n" "//- rjf: pixel shader\n" "\n" "float4\n" "ps_main(Vertex2Pixel v2p) : SV_TARGET\n" "{\n" " float4 final_color = stage_t2d.Sample(stage_sampler, v2p.texcoord);\n" " final_color.a = 1;\n" " return final_color;\n" "}\n" "" ); C_LINKAGE_END #endif // RENDER_D3D11_META_H ================================================ FILE: src/render/d3d11/render_d3d11.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Input Layout Element Tables global D3D11_INPUT_ELEMENT_DESC r_d3d11_g_rect_ilay_elements[] = { { "POS", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "TEX", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "COL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "COL", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "COL", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "COL", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "CRAD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, { "STY", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 }, }; global D3D11_INPUT_ELEMENT_DESC r_d3d11_g_mesh_ilay_elements[] = { { "POS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEX", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; //////////////////////////////// //~ rjf: Generated Code #include "generated/render_d3d11.meta.c" //////////////////////////////// //~ rjf: Helpers internal R_D3D11_Window * r_d3d11_window_from_handle(R_Handle handle) { R_D3D11_Window *window = (R_D3D11_Window *)handle.u64[0]; if(window == 0) { window = &r_d3d11_window_nil; } return window; } internal R_Handle r_d3d11_handle_from_window(R_D3D11_Window *window) { R_Handle handle = {0}; handle.u64[0] = (U64)window; return handle; } internal R_D3D11_Tex2D * r_d3d11_tex2d_from_handle(R_Handle handle) { R_D3D11_Tex2D *texture = (R_D3D11_Tex2D *)handle.u64[0]; if(texture == 0) { texture = &r_d3d11_tex2d_nil; } return texture; } internal R_Handle r_d3d11_handle_from_tex2d(R_D3D11_Tex2D *texture) { R_Handle handle = {0}; handle.u64[0] = (U64)texture; return handle; } internal R_D3D11_Buffer * r_d3d11_buffer_from_handle(R_Handle handle) { R_D3D11_Buffer *buffer = (R_D3D11_Buffer *)handle.u64[0]; if(buffer == 0) { buffer = &r_d3d11_buffer_nil; } return buffer; } internal R_Handle r_d3d11_handle_from_buffer(R_D3D11_Buffer *buffer) { R_Handle handle = {0}; handle.u64[0] = (U64)buffer; return handle; } internal ID3D11Buffer * r_d3d11_instance_buffer_from_size(U64 size) { ID3D11Buffer *buffer = r_d3d11_state->instance_scratch_buffer_64kb; if(size > KB(64)) { U64 flushed_buffer_size = size; flushed_buffer_size += MB(1)-1; flushed_buffer_size -= flushed_buffer_size%MB(1); // rjf: build buffer { D3D11_BUFFER_DESC desc = {0}; { desc.ByteWidth = flushed_buffer_size; desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; } HRESULT error = r_d3d11_state->device->lpVtbl->CreateBuffer(r_d3d11_state->device, &desc, 0, &buffer); } // rjf: push buffer to flush list R_D3D11_FlushBuffer *n = push_array(r_d3d11_state->buffer_flush_arena, R_D3D11_FlushBuffer, 1); n->buffer = buffer; SLLQueuePush(r_d3d11_state->first_buffer_to_flush, r_d3d11_state->last_buffer_to_flush, n); } return buffer; } internal void r_usage_access_flags_from_resource_kind(R_ResourceKind kind, D3D11_USAGE *out_d3d11_usage, UINT *out_cpu_access_flags) { switch(kind) { case R_ResourceKind_Static: { *out_d3d11_usage = D3D11_USAGE_IMMUTABLE; *out_cpu_access_flags = 0; }break; case R_ResourceKind_Dynamic: { *out_d3d11_usage = D3D11_USAGE_DEFAULT; *out_cpu_access_flags = 0; }break; case R_ResourceKind_Stream: { *out_d3d11_usage = D3D11_USAGE_DYNAMIC; *out_cpu_access_flags = D3D11_CPU_ACCESS_WRITE; }break; default: { InvalidPath; } } } //////////////////////////////// //~ rjf: Backend Hook Implementations //- rjf: top-level layer initialization r_hook void r_init(CmdLine *cmdln) { ProfBeginFunction(); HRESULT error = 0; Arena *arena = arena_alloc(); r_d3d11_state = push_array(arena, R_D3D11_State, 1); r_d3d11_state->arena = arena; r_d3d11_state->device_rw_mutex = rw_mutex_alloc(); //- rjf: create base device ProfBegin("create base device"); UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if BUILD_DEBUG if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug"))) { creation_flags |= D3D11_CREATE_DEVICE_DEBUG; } #endif D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_0 }; D3D_DRIVER_TYPE driver_type = D3D_DRIVER_TYPE_HARDWARE; if(cmd_line_has_flag(cmdln, str8_lit("force_d3d11_software"))) { driver_type = D3D_DRIVER_TYPE_WARP; } error = D3D11CreateDevice(0, driver_type, 0, creation_flags, feature_levels, ArrayCount(feature_levels), D3D11_SDK_VERSION, &r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx); if(FAILED(error) && driver_type == D3D_DRIVER_TYPE_HARDWARE) { // try with WARP driver as backup solution in case HW device is not available error = D3D11CreateDevice(0, D3D_DRIVER_TYPE_WARP, 0, creation_flags, feature_levels, ArrayCount(feature_levels), D3D11_SDK_VERSION, &r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx); } if(FAILED(error)) { char buffer[256] = {0}; raddbg_snprintf(buffer, sizeof(buffer), "D3D11 device creation failure (%lx). The process is terminating.", error); os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer)); os_abort(1); } ProfEnd(); //- rjf: enable break-on-error #if BUILD_DEBUG if(cmd_line_has_flag(cmdln, str8_lit("d3d11_debug"))) ProfScope("enable break-on-error") { ID3D11InfoQueue *info = 0; error = r_d3d11_state->base_device->lpVtbl->QueryInterface(r_d3d11_state->base_device, &IID_ID3D11InfoQueue, (void **)(&info)); if(SUCCEEDED(error)) { error = info->lpVtbl->SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE); error = info->lpVtbl->SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_ERROR, TRUE); info->lpVtbl->Release(info); } } #endif //- rjf: get main device ProfBegin("get main device"); error = r_d3d11_state->base_device->lpVtbl->QueryInterface(r_d3d11_state->base_device, &IID_ID3D11Device1, (void **)(&r_d3d11_state->device)); error = r_d3d11_state->base_device_ctx->lpVtbl->QueryInterface(r_d3d11_state->base_device_ctx, &IID_ID3D11DeviceContext1, (void **)(&r_d3d11_state->device_ctx)); ProfEnd(); //- rjf: get dxgi device/adapter/factory ProfBegin("get dxgi device/adapter/factory"); error = r_d3d11_state->device->lpVtbl->QueryInterface(r_d3d11_state->device, &IID_IDXGIDevice1, (void **)(&r_d3d11_state->dxgi_device)); error = r_d3d11_state->dxgi_device->lpVtbl->GetAdapter(r_d3d11_state->dxgi_device, &r_d3d11_state->dxgi_adapter); error = r_d3d11_state->dxgi_adapter->lpVtbl->GetParent(r_d3d11_state->dxgi_adapter, &IID_IDXGIFactory2, (void **)(&r_d3d11_state->dxgi_factory)); error = r_d3d11_state->dxgi_device->lpVtbl->SetMaximumFrameLatency(r_d3d11_state->dxgi_device, 1); ProfEnd(); //- rjf: create main rasterizer ProfScope("create main rasterizer") { D3D11_RASTERIZER_DESC1 desc = {D3D11_FILL_SOLID}; { desc.FillMode = D3D11_FILL_SOLID; desc.CullMode = D3D11_CULL_BACK; desc.ScissorEnable = 1; } error = r_d3d11_state->device->lpVtbl->CreateRasterizerState1(r_d3d11_state->device, &desc, &r_d3d11_state->main_rasterizer); } //- rjf: create main blend state ProfScope("create main blend state") { D3D11_BLEND_DESC desc = {0}; { desc.RenderTarget[0].BlendEnable = 1; desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; } error = r_d3d11_state->device->lpVtbl->CreateBlendState(r_d3d11_state->device, &desc, &r_d3d11_state->main_blend_state); } //- rjf: create empty blend state ProfScope("create empty blend state") { D3D11_BLEND_DESC desc = {0}; { desc.RenderTarget[0].BlendEnable = FALSE; desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; } error = r_d3d11_state->device->lpVtbl->CreateBlendState(r_d3d11_state->device, &desc, &r_d3d11_state->no_blend_state); } //- rjf: create nearest-neighbor sampler ProfScope("create nearest-neighbor sampler") { D3D11_SAMPLER_DESC desc = zero_struct; { desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.ComparisonFunc = D3D11_COMPARISON_NEVER; } error = r_d3d11_state->device->lpVtbl->CreateSamplerState(r_d3d11_state->device, &desc, &r_d3d11_state->samplers[R_Tex2DSampleKind_Nearest]); } //- rjf: create bilinear sampler ProfScope("create bilinear sampler") { D3D11_SAMPLER_DESC desc = zero_struct; { desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.ComparisonFunc = D3D11_COMPARISON_NEVER; } error = r_d3d11_state->device->lpVtbl->CreateSamplerState(r_d3d11_state->device, &desc, &r_d3d11_state->samplers[R_Tex2DSampleKind_Linear]); } //- rjf: create noop depth/stencil state ProfScope("create noop depth/stencil state") { D3D11_DEPTH_STENCIL_DESC desc = {0}; { desc.DepthEnable = FALSE; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS; } error = r_d3d11_state->device->lpVtbl->CreateDepthStencilState(r_d3d11_state->device, &desc, &r_d3d11_state->noop_depth_stencil); } //- rjf: create plain depth/stencil state ProfScope("create plain depth/stencil state") { D3D11_DEPTH_STENCIL_DESC desc = {0}; { desc.DepthEnable = TRUE; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS; } error = r_d3d11_state->device->lpVtbl->CreateDepthStencilState(r_d3d11_state->device, &desc, &r_d3d11_state->plain_depth_stencil); } //- rjf: create buffers ProfScope("create buffers") { D3D11_BUFFER_DESC desc = {0}; { desc.ByteWidth = KB(64); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; } error = r_d3d11_state->device->lpVtbl->CreateBuffer(r_d3d11_state->device, &desc, 0, &r_d3d11_state->instance_scratch_buffer_64kb); } //- rjf: build vertex shaders & input layouts ProfScope("build vertex shaders & input layouts") for(R_D3D11_VShadKind kind = (R_D3D11_VShadKind)0; kind < R_D3D11_VShadKind_COUNT; kind = (R_D3D11_VShadKind)(kind+1)) { String8 source = *r_d3d11_g_vshad_kind_source_table[kind]; String8 source_name = r_d3d11_g_vshad_kind_source_name_table[kind]; D3D11_INPUT_ELEMENT_DESC *ilay_elements = r_d3d11_g_vshad_kind_elements_ptr_table[kind]; U64 ilay_elements_count = r_d3d11_g_vshad_kind_elements_count_table[kind]; // rjf: compile vertex shader ID3DBlob *vshad_source_blob = 0; ID3DBlob *vshad_source_errors = 0; ID3D11VertexShader *vshad = 0; ProfScope("compile vertex shader") { error = D3DCompile(source.str, source.size, (char *)source_name.str, 0, 0, "vs_main", "vs_5_0", 0, 0, &vshad_source_blob, &vshad_source_errors); String8 errors = {0}; if(FAILED(error)) { errors = str8((U8 *)vshad_source_errors->lpVtbl->GetBufferPointer(vshad_source_errors), (U64)vshad_source_errors->lpVtbl->GetBufferSize(vshad_source_errors)); os_graphical_message(1, str8_lit("Vertex Shader Compilation Failure"), errors); } else { error = r_d3d11_state->device->lpVtbl->CreateVertexShader(r_d3d11_state->device, vshad_source_blob->lpVtbl->GetBufferPointer(vshad_source_blob), vshad_source_blob->lpVtbl->GetBufferSize(vshad_source_blob), 0, &vshad); } } // rjf: make input layout ID3D11InputLayout *ilay = 0; if(ilay_elements != 0) { error = r_d3d11_state->device->lpVtbl->CreateInputLayout(r_d3d11_state->device, ilay_elements, ilay_elements_count, vshad_source_blob->lpVtbl->GetBufferPointer(vshad_source_blob), vshad_source_blob->lpVtbl->GetBufferSize(vshad_source_blob), &ilay); } vshad_source_blob->lpVtbl->Release(vshad_source_blob); // rjf: store r_d3d11_state->vshads[kind] = vshad; r_d3d11_state->ilays[kind] = ilay; } //- rjf: build pixel shaders for(R_D3D11_PShadKind kind = (R_D3D11_PShadKind)0; kind < R_D3D11_PShadKind_COUNT; kind = (R_D3D11_PShadKind)(kind+1)) { String8 source = *r_d3d11_g_pshad_kind_source_table[kind]; String8 source_name = r_d3d11_g_pshad_kind_source_name_table[kind]; // rjf: compile pixel shader ID3DBlob *pshad_source_blob = 0; ID3DBlob *pshad_source_errors = 0; ID3D11PixelShader *pshad = 0; ProfScope("compile pixel shader") { error = D3DCompile(source.str, source.size, (char *)source_name.str, 0, 0, "ps_main", "ps_5_0", 0, 0, &pshad_source_blob, &pshad_source_errors); String8 errors = {0}; if(FAILED(error)) { errors = str8((U8 *)pshad_source_errors->lpVtbl->GetBufferPointer(pshad_source_errors), (U64)pshad_source_errors->lpVtbl->GetBufferSize(pshad_source_errors)); os_graphical_message(1, str8_lit("Pixel Shader Compilation Failure"), errors); } else { error = r_d3d11_state->device->lpVtbl->CreatePixelShader(r_d3d11_state->device, pshad_source_blob->lpVtbl->GetBufferPointer(pshad_source_blob), pshad_source_blob->lpVtbl->GetBufferSize(pshad_source_blob), 0, &pshad); } } pshad_source_blob->lpVtbl->Release(pshad_source_blob); // rjf: store r_d3d11_state->pshads[kind] = pshad; } //- rjf: build uniform type buffers ProfScope("build uniform type buffers") for(R_D3D11_UniformTypeKind kind = (R_D3D11_UniformTypeKind)0; kind < R_D3D11_UniformTypeKind_COUNT; kind = (R_D3D11_UniformTypeKind)(kind+1)) { ID3D11Buffer *buffer = 0; { D3D11_BUFFER_DESC desc = {0}; { desc.ByteWidth = r_d3d11_g_uniform_type_kind_size_table[kind]; desc.ByteWidth += 15; desc.ByteWidth -= desc.ByteWidth % 16; desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; } r_d3d11_state->device->lpVtbl->CreateBuffer(r_d3d11_state->device, &desc, 0, &buffer); } r_d3d11_state->uniform_type_kind_buffers[kind] = buffer; } //- rjf: create backup texture ProfScope("create backup texture") { U32 backup_texture_data[] = { 0xff00ffff, 0x330033ff, 0x330033ff, 0xff00ffff, }; r_d3d11_state->backup_texture = r_tex2d_alloc(R_ResourceKind_Static, v2s32(2, 2), R_Tex2DFormat_RGBA8, backup_texture_data); } //- rjf: initialize buffer flush state { r_d3d11_state->buffer_flush_arena = arena_alloc(); } ProfEnd(); } //- rjf: window setup/teardown r_hook R_Handle r_window_equip(OS_Handle handle) { ProfBeginFunction(); R_Handle result = {0}; MutexScopeW(r_d3d11_state->device_rw_mutex) { //- rjf: allocate per-window-state R_D3D11_Window *window = r_d3d11_state->first_free_window; { if(window == 0) { window = push_array(r_d3d11_state->arena, R_D3D11_Window, 1); } else { U64 gen = window->generation; SLLStackPop(r_d3d11_state->first_free_window); MemoryZeroStruct(window); window->generation = gen; } window->generation += 1; } //- rjf: map os window handle -> hwnd HWND hwnd = {0}; { OS_W32_Window *w32_layer_window = os_w32_window_from_handle(handle); hwnd = os_w32_hwnd_from_window(w32_layer_window); } //- rjf: create swapchain DXGI_SWAP_CHAIN_DESC1 swapchain_desc = {0}; { swapchain_desc.Width = 0; // NOTE(rjf): use window width swapchain_desc.Height = 0; // NOTE(rjf): use window height swapchain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swapchain_desc.Stereo = FALSE; swapchain_desc.SampleDesc.Count = 1; swapchain_desc.SampleDesc.Quality = 0; swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapchain_desc.BufferCount = 2; swapchain_desc.Scaling = DXGI_SCALING_NONE; swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; swapchain_desc.Flags = 0; } HRESULT error = r_d3d11_state->dxgi_factory->lpVtbl->CreateSwapChainForHwnd(r_d3d11_state->dxgi_factory, (IUnknown *)r_d3d11_state->device, hwnd, &swapchain_desc, 0, 0, &window->swapchain); if(FAILED(error)) { char buffer[256] = {0}; raddbg_snprintf(buffer, sizeof(buffer), "DXGI swap chain creation failure (%lx). The process is terminating.", error); os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer)); os_abort(1); } r_d3d11_state->dxgi_factory->lpVtbl->MakeWindowAssociation(r_d3d11_state->dxgi_factory, hwnd, DXGI_MWA_NO_ALT_ENTER); //- rjf: create framebuffer & view D3D11_RENDER_TARGET_VIEW_DESC framebuffer_rtv_desc = {0}; framebuffer_rtv_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; framebuffer_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; window->swapchain->lpVtbl->GetBuffer(window->swapchain, 0, &IID_ID3D11Texture2D, (void **)(&window->framebuffer)); r_d3d11_state->device->lpVtbl->CreateRenderTargetView(r_d3d11_state->device, (ID3D11Resource *)window->framebuffer, &framebuffer_rtv_desc, &window->framebuffer_rtv); result = r_d3d11_handle_from_window(window); r_d3d11_state->window_count += 1; r_d3d11_state->dxgi_device->lpVtbl->SetMaximumFrameLatency(r_d3d11_state->dxgi_device, Clamp(1, r_d3d11_state->window_count, 16)); } ProfEnd(); return result; } r_hook void r_window_unequip(OS_Handle handle, R_Handle equip_handle) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Window *window = r_d3d11_window_from_handle(equip_handle); window->stage_color_srv->lpVtbl->Release(window->stage_color_srv); window->stage_color_rtv->lpVtbl->Release(window->stage_color_rtv); window->stage_color->lpVtbl->Release(window->stage_color); window->stage_scratch_color_srv->lpVtbl->Release(window->stage_scratch_color_srv); window->stage_scratch_color_rtv->lpVtbl->Release(window->stage_scratch_color_rtv); window->stage_scratch_color->lpVtbl->Release(window->stage_scratch_color); window->framebuffer_rtv->lpVtbl->Release(window->framebuffer_rtv); window->framebuffer->lpVtbl->Release(window->framebuffer); window->swapchain->lpVtbl->Release(window->swapchain); window->generation += 1; SLLStackPush(r_d3d11_state->first_free_window, window); r_d3d11_state->window_count -= 1; r_d3d11_state->dxgi_device->lpVtbl->SetMaximumFrameLatency(r_d3d11_state->dxgi_device, Clamp(1, r_d3d11_state->window_count, 16)); } ProfEnd(); } //- rjf: textures r_hook R_Handle r_tex2d_alloc(R_ResourceKind kind, Vec2S32 size, R_Tex2DFormat format, void *data) { ProfBeginFunction(); //- rjf: allocate R_D3D11_Tex2D *texture = 0; MutexScopeW(r_d3d11_state->device_rw_mutex) { texture = r_d3d11_state->first_free_tex2d; if(texture == 0) { texture = push_array(r_d3d11_state->arena, R_D3D11_Tex2D, 1); } else { U64 gen = texture->generation; SLLStackPop(r_d3d11_state->first_free_tex2d); MemoryZeroStruct(texture); texture->generation = gen; } texture->generation += 1; } D3D11_USAGE d3d11_usage = D3D11_USAGE_DEFAULT; UINT cpu_access_flags = 0; r_usage_access_flags_from_resource_kind(kind, &d3d11_usage, &cpu_access_flags); if (kind == R_ResourceKind_Static) { Assert(data != 0 && "static texture must have initial data provided"); } //- rjf: format -> dxgi format DXGI_FORMAT dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM; { switch(format) { default:{}break; case R_Tex2DFormat_R8: {dxgi_format = DXGI_FORMAT_R8_UNORM;}break; case R_Tex2DFormat_RG8: {dxgi_format = DXGI_FORMAT_R8G8_UNORM;}break; case R_Tex2DFormat_RGBA8: {dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM;}break; case R_Tex2DFormat_BGRA8: {dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;}break; case R_Tex2DFormat_R16: {dxgi_format = DXGI_FORMAT_R16_UNORM;}break; case R_Tex2DFormat_RGBA16:{dxgi_format = DXGI_FORMAT_R16G16B16A16_UNORM;}break; case R_Tex2DFormat_R32: {dxgi_format = DXGI_FORMAT_R32_FLOAT;}break; case R_Tex2DFormat_RG32: {dxgi_format = DXGI_FORMAT_R32G32_FLOAT;}break; case R_Tex2DFormat_RGBA32:{dxgi_format = DXGI_FORMAT_R32G32B32A32_FLOAT;}break; } } //- rjf: prep initial data, if passed D3D11_SUBRESOURCE_DATA initial_data_ = {0}; D3D11_SUBRESOURCE_DATA *initial_data = 0; if(data != 0) { initial_data = &initial_data_; initial_data->pSysMem = data; initial_data->SysMemPitch = r_tex2d_format_bytes_per_pixel_table[format] * size.x; } //- rjf: create texture D3D11_TEXTURE2D_DESC texture_desc = {0}; { texture_desc.Width = size.x; texture_desc.Height = size.y; texture_desc.MipLevels = 1; texture_desc.ArraySize = 1; texture_desc.Format = dxgi_format; texture_desc.SampleDesc.Count = 1; texture_desc.Usage = d3d11_usage; texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; texture_desc.CPUAccessFlags = cpu_access_flags; } r_d3d11_state->device->lpVtbl->CreateTexture2D(r_d3d11_state->device, &texture_desc, initial_data, &texture->texture); //- rjf: create texture srv r_d3d11_state->device->lpVtbl->CreateShaderResourceView(r_d3d11_state->device, (ID3D11Resource *)texture->texture, 0, &texture->view); //- rjf: fill basics { texture->kind = kind; texture->size = size; texture->format = format; } R_Handle result = r_d3d11_handle_from_tex2d(texture); ProfEnd(); return result; } r_hook void r_tex2d_release(R_Handle handle) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle); if(texture != &r_d3d11_tex2d_nil) { SLLStackPush(r_d3d11_state->first_to_free_tex2d, texture); } } ProfEnd(); } r_hook R_ResourceKind r_kind_from_tex2d(R_Handle handle) { R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle); return texture->kind; } r_hook Vec2S32 r_size_from_tex2d(R_Handle handle) { R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle); return texture->size; } r_hook R_Tex2DFormat r_format_from_tex2d(R_Handle handle) { R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle); return texture->format; } r_hook void r_fill_tex2d_region(R_Handle handle, Rng2S32 subrect, void *data) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(handle); if(texture != &r_d3d11_tex2d_nil) { Assert(texture->kind == R_ResourceKind_Dynamic && "only dynamic texture can update region"); U64 bytes_per_pixel = r_tex2d_format_bytes_per_pixel_table[texture->format]; Vec2S32 dim = v2s32(subrect.x1 - subrect.x0, subrect.y1 - subrect.y0); D3D11_BOX dst_box = { (UINT)subrect.x0, (UINT)subrect.y0, 0, (UINT)subrect.x1, (UINT)subrect.y1, 1, }; r_d3d11_state->device_ctx->lpVtbl->UpdateSubresource(r_d3d11_state->device_ctx, (ID3D11Resource *)texture->texture, 0, &dst_box, data, dim.x*bytes_per_pixel, 0); } } ProfEnd(); } //- rjf: buffers r_hook R_Handle r_buffer_alloc(R_ResourceKind kind, U64 size, void *data) { ProfBeginFunction(); //- rjf: allocate R_D3D11_Buffer *buffer = 0; MutexScopeW(r_d3d11_state->device_rw_mutex) { buffer = r_d3d11_state->first_free_buffer; if(buffer == 0) { buffer = push_array(r_d3d11_state->arena, R_D3D11_Buffer, 1); } else { U64 gen = buffer->generation; SLLStackPop(r_d3d11_state->first_free_buffer); MemoryZeroStruct(buffer); buffer->generation = gen; } buffer->generation += 1; } D3D11_USAGE d3d11_usage = D3D11_USAGE_DEFAULT; UINT cpu_access_flags = 0; r_usage_access_flags_from_resource_kind(kind, &d3d11_usage, &cpu_access_flags); if (kind == R_ResourceKind_Static) { Assert(data != 0 && "static buffer must have initial data provided"); } //- rjf: prep initial data, if passed D3D11_SUBRESOURCE_DATA initial_data_ = {0}; D3D11_SUBRESOURCE_DATA *initial_data = 0; if(data != 0) { initial_data = &initial_data_; initial_data->pSysMem = data; } //- rjf: create buffer D3D11_BUFFER_DESC desc = {0}; { desc.ByteWidth = size; desc.Usage = d3d11_usage; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER|D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = cpu_access_flags; } r_d3d11_state->device->lpVtbl->CreateBuffer(r_d3d11_state->device, &desc, initial_data, &buffer->buffer); //- rjf: fill basics { buffer->kind = kind; buffer->size = size; } R_Handle result = r_d3d11_handle_from_buffer(buffer); ProfEnd(); return result; } r_hook void r_buffer_release(R_Handle handle) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Buffer *buffer = r_d3d11_buffer_from_handle(handle); if(buffer != &r_d3d11_buffer_nil) { SLLStackPush(r_d3d11_state->first_to_free_buffer, buffer); } } ProfEnd(); } //- rjf: frame markers r_hook void r_begin_frame(void) { MutexScopeW(r_d3d11_state->device_rw_mutex) { // NOTE(rjf): no-op } } r_hook void r_end_frame(void) { MutexScopeW(r_d3d11_state->device_rw_mutex) { for(R_D3D11_FlushBuffer *buffer = r_d3d11_state->first_buffer_to_flush; buffer != 0; buffer = buffer->next) { buffer->buffer->lpVtbl->Release(buffer->buffer); } for(R_D3D11_Tex2D *tex = r_d3d11_state->first_to_free_tex2d, *next = 0; tex != 0; tex = next) { next = tex->next; if(tex->view != 0) { tex->view->lpVtbl->Release(tex->view); } if(tex->texture != 0) { tex->texture->lpVtbl->Release(tex->texture); } tex->view = 0; tex->texture = 0; tex->generation += 1; SLLStackPush(r_d3d11_state->first_free_tex2d, tex); } for(R_D3D11_Buffer *buf = r_d3d11_state->first_to_free_buffer, *next = 0; buf != 0; buf = next) { next = buf->next; if(buf->buffer != 0) { buf->buffer->lpVtbl->Release(buf->buffer); } buf->generation += 1; buf->buffer = 0; SLLStackPush(r_d3d11_state->first_free_buffer, buf); } arena_clear(r_d3d11_state->buffer_flush_arena); r_d3d11_state->first_buffer_to_flush = r_d3d11_state->last_buffer_to_flush = 0; r_d3d11_state->first_to_free_tex2d = 0; r_d3d11_state->first_to_free_buffer = 0; } } r_hook void r_window_begin_frame(OS_Handle window, R_Handle window_equip) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Window *wnd = r_d3d11_window_from_handle(window_equip); ID3D11DeviceContext1 *d_ctx = r_d3d11_state->device_ctx; //- rjf: get resolution Rng2F32 client_rect = os_client_rect_from_window(window); Vec2S32 resolution = {(S32)(client_rect.x1 - client_rect.x0), (S32)(client_rect.y1 - client_rect.y0)}; //- rjf: resolution change B32 resize_done = 0; if(wnd->last_resolution.x != resolution.x || wnd->last_resolution.y != resolution.y) { resize_done = 1; wnd->last_resolution = resolution; // rjf: release screen-sized render target resources, if there if(wnd->stage_scratch_color_srv){wnd->stage_scratch_color_srv->lpVtbl->Release(wnd->stage_scratch_color_srv);} if(wnd->stage_scratch_color_rtv){wnd->stage_scratch_color_rtv->lpVtbl->Release(wnd->stage_scratch_color_rtv);} if(wnd->stage_scratch_color) {wnd->stage_scratch_color->lpVtbl->Release(wnd->stage_scratch_color);} if(wnd->stage_color_srv) {wnd->stage_color_srv->lpVtbl->Release(wnd->stage_color_srv);} if(wnd->stage_color_rtv) {wnd->stage_color_rtv->lpVtbl->Release(wnd->stage_color_rtv);} if(wnd->stage_color) {wnd->stage_color->lpVtbl->Release(wnd->stage_color);} if(wnd->geo3d_color_srv) {wnd->geo3d_color_srv->lpVtbl->Release(wnd->geo3d_color_srv);} if(wnd->geo3d_color_rtv) {wnd->geo3d_color_rtv->lpVtbl->Release(wnd->geo3d_color_rtv);} if(wnd->geo3d_color) {wnd->geo3d_color->lpVtbl->Release(wnd->geo3d_color);} if(wnd->geo3d_depth_srv) {wnd->geo3d_depth_srv->lpVtbl->Release(wnd->geo3d_depth_srv);} if(wnd->geo3d_depth_dsv) {wnd->geo3d_depth_dsv->lpVtbl->Release(wnd->geo3d_depth_dsv);} if(wnd->geo3d_depth) {wnd->geo3d_depth->lpVtbl->Release(wnd->geo3d_depth);} // rjf: resize swapchain & main framebuffer wnd->framebuffer_rtv->lpVtbl->Release(wnd->framebuffer_rtv); wnd->framebuffer->lpVtbl->Release(wnd->framebuffer); wnd->swapchain->lpVtbl->ResizeBuffers(wnd->swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); wnd->swapchain->lpVtbl->GetBuffer(wnd->swapchain, 0, &IID_ID3D11Texture2D, (void **)(&wnd->framebuffer)); D3D11_RENDER_TARGET_VIEW_DESC framebuffer_rtv_desc = {0}; framebuffer_rtv_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; framebuffer_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; r_d3d11_state->device->lpVtbl->CreateRenderTargetView(r_d3d11_state->device, (ID3D11Resource *)wnd->framebuffer, &framebuffer_rtv_desc, &wnd->framebuffer_rtv); // rjf: create stage color targets { D3D11_TEXTURE2D_DESC color_desc = zero_struct; { wnd->framebuffer->lpVtbl->GetDesc(wnd->framebuffer, &color_desc); color_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; color_desc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE; } D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = zero_struct; { rtv_desc.Format = color_desc.Format; rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; } D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = zero_struct; { srv_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MipLevels = -1; } r_d3d11_state->device->lpVtbl->CreateTexture2D(r_d3d11_state->device, &color_desc, 0, &wnd->stage_color); r_d3d11_state->device->lpVtbl->CreateRenderTargetView(r_d3d11_state->device, (ID3D11Resource *)wnd->stage_color, &rtv_desc, &wnd->stage_color_rtv); r_d3d11_state->device->lpVtbl->CreateShaderResourceView(r_d3d11_state->device, (ID3D11Resource *)wnd->stage_color, &srv_desc, &wnd->stage_color_srv); r_d3d11_state->device->lpVtbl->CreateTexture2D(r_d3d11_state->device, &color_desc, 0, &wnd->stage_scratch_color); r_d3d11_state->device->lpVtbl->CreateRenderTargetView(r_d3d11_state->device, (ID3D11Resource *)wnd->stage_scratch_color, &rtv_desc, &wnd->stage_scratch_color_rtv); r_d3d11_state->device->lpVtbl->CreateShaderResourceView(r_d3d11_state->device, (ID3D11Resource *)wnd->stage_scratch_color, &srv_desc, &wnd->stage_scratch_color_srv); } // rjf: create geo3d targets { D3D11_TEXTURE2D_DESC color_desc = zero_struct; { wnd->framebuffer->lpVtbl->GetDesc(wnd->framebuffer, &color_desc); color_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; color_desc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE; } D3D11_RENDER_TARGET_VIEW_DESC color_rtv_desc = zero_struct; { color_rtv_desc.Format = color_desc.Format; color_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; } D3D11_SHADER_RESOURCE_VIEW_DESC color_srv_desc = zero_struct; { color_srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; color_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; color_srv_desc.Texture2D.MipLevels = -1; } D3D11_TEXTURE2D_DESC depth_desc = zero_struct; { wnd->framebuffer->lpVtbl->GetDesc(wnd->framebuffer, &depth_desc); depth_desc.Format = DXGI_FORMAT_R24G8_TYPELESS; depth_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE; } D3D11_DEPTH_STENCIL_VIEW_DESC depth_dsv_desc = zero_struct; { depth_dsv_desc.Flags = 0; depth_dsv_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depth_dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depth_dsv_desc.Texture2D.MipSlice = 0; } D3D11_SHADER_RESOURCE_VIEW_DESC depth_srv_desc = zero_struct; { depth_srv_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; depth_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; depth_srv_desc.Texture2D.MostDetailedMip = 0; depth_srv_desc.Texture2D.MipLevels = -1; } r_d3d11_state->device->lpVtbl->CreateTexture2D(r_d3d11_state->device, &color_desc, 0, &wnd->geo3d_color); r_d3d11_state->device->lpVtbl->CreateRenderTargetView(r_d3d11_state->device, (ID3D11Resource *)wnd->geo3d_color, &color_rtv_desc, &wnd->geo3d_color_rtv); r_d3d11_state->device->lpVtbl->CreateShaderResourceView(r_d3d11_state->device, (ID3D11Resource *)wnd->geo3d_color, &color_srv_desc, &wnd->geo3d_color_srv); r_d3d11_state->device->lpVtbl->CreateTexture2D(r_d3d11_state->device, &depth_desc, 0, &wnd->geo3d_depth); r_d3d11_state->device->lpVtbl->CreateDepthStencilView(r_d3d11_state->device, (ID3D11Resource *)wnd->geo3d_depth, &depth_dsv_desc, &wnd->geo3d_depth_dsv); r_d3d11_state->device->lpVtbl->CreateShaderResourceView(r_d3d11_state->device, (ID3D11Resource *)wnd->geo3d_depth, &depth_srv_desc, &wnd->geo3d_depth_srv); } } //- rjf: clear framebuffers Vec4F32 clear_color = {0, 0, 0, 0}; d_ctx->lpVtbl->ClearRenderTargetView(d_ctx, wnd->framebuffer_rtv, clear_color.v); d_ctx->lpVtbl->ClearRenderTargetView(d_ctx, wnd->stage_color_rtv, clear_color.v); if(resize_done) { d_ctx->lpVtbl->Flush(d_ctx); } } ProfEnd(); } r_hook void r_window_end_frame(OS_Handle window, R_Handle window_equip) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { R_D3D11_Window *wnd = r_d3d11_window_from_handle(window_equip); ID3D11DeviceContext1 *d_ctx = r_d3d11_state->device_ctx; //////////////////////////// //- rjf: finalize, by writing staging buffer out to window framebuffer // { ID3D11SamplerState *sampler = r_d3d11_state->samplers[R_Tex2DSampleKind_Nearest]; ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Finalize]; ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Finalize]; // rjf: setup output merger d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->framebuffer_rtv, 0); d_ctx->lpVtbl->OMSetDepthStencilState(d_ctx, r_d3d11_state->noop_depth_stencil, 0); d_ctx->lpVtbl->OMSetBlendState(d_ctx, r_d3d11_state->main_blend_state, 0, 0xffffffff); // rjf: set up rasterizer Vec2S32 resolution = wnd->last_resolution; D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f }; d_ctx->lpVtbl->RSSetViewports(d_ctx, 1, &viewport); d_ctx->lpVtbl->RSSetState(d_ctx, (ID3D11RasterizerState *)r_d3d11_state->main_rasterizer); // rjf: setup input assembly d_ctx->lpVtbl->IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); d_ctx->lpVtbl->IASetInputLayout(d_ctx, 0); // rjf: setup shaders d_ctx->lpVtbl->VSSetShader(d_ctx, vshad, 0, 0); d_ctx->lpVtbl->PSSetShader(d_ctx, pshad, 0, 0); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &wnd->stage_color_srv); d_ctx->lpVtbl->PSSetSamplers(d_ctx, 0, 1, &sampler); // rjf: setup scissor rect { D3D11_RECT rect = {0}; rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: draw d_ctx->lpVtbl->Draw(d_ctx, 4, 0); } //////////////////////////// //- rjf: present // HRESULT error = wnd->swapchain->lpVtbl->Present(wnd->swapchain, 1, 0); if(FAILED(error)) { char buffer[256] = {0}; raddbg_snprintf(buffer, sizeof(buffer), "D3D11 present failure (%lx). The process is terminating.", error); os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer)); os_abort(1); } d_ctx->lpVtbl->ClearState(d_ctx); } ProfEnd(); } //- rjf: render pass submission r_hook void r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes) { ProfBeginFunction(); MutexScopeW(r_d3d11_state->device_rw_mutex) { //////////////////////////// //- rjf: unpack arguments // R_D3D11_Window *wnd = r_d3d11_window_from_handle(window_equip); ID3D11DeviceContext1 *d_ctx = r_d3d11_state->device_ctx; //////////////////////////// //- rjf: do passes // for(R_PassNode *pass_n = passes->first; pass_n != 0; pass_n = pass_n->next) { R_Pass *pass = &pass_n->v; switch(pass->kind) { default:{}break; //////////////////////// //- rjf: ui rendering pass // case R_PassKind_UI: { //- rjf: unpack params R_PassParams_UI *params = pass->params_ui; R_BatchGroup2DList *rect_batch_groups = ¶ms->rects; //- rjf: set up rasterizer Vec2S32 resolution = wnd->last_resolution; D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f }; d_ctx->lpVtbl->RSSetViewports(d_ctx, 1, &viewport); d_ctx->lpVtbl->RSSetState(d_ctx, (ID3D11RasterizerState *)r_d3d11_state->main_rasterizer); //- rjf: draw each batch group for(R_BatchGroup2DNode *group_n = rect_batch_groups->first; group_n != 0; group_n = group_n->next) { R_BatchList *batches = &group_n->batches; R_BatchGroup2DParams *group_params = &group_n->params; // rjf: unpack pipeline info ID3D11SamplerState *sampler = r_d3d11_state->samplers[group_params->tex_sample_kind]; ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Rect]; ID3D11InputLayout *ilay = r_d3d11_state->ilays[R_D3D11_VShadKind_Rect]; ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Rect]; ID3D11Buffer *uniforms_buffer = r_d3d11_state->uniform_type_kind_buffers[R_D3D11_UniformTypeKind_Rect]; // rjf: get & fill buffer ID3D11Buffer *buffer = r_d3d11_instance_buffer_from_size(batches->byte_count); { D3D11_MAPPED_SUBRESOURCE sub_rsrc = {0}; d_ctx->lpVtbl->Map(d_ctx, (ID3D11Resource *)buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sub_rsrc); U8 *dst_ptr = (U8 *)sub_rsrc.pData; U64 off = 0; for(R_BatchNode *batch_n = batches->first; batch_n != 0; batch_n = batch_n->next) { MemoryCopy(dst_ptr+off, batch_n->v.v, batch_n->v.byte_count); off += batch_n->v.byte_count; } d_ctx->lpVtbl->Unmap(d_ctx, (ID3D11Resource *)buffer, 0); } // rjf: get texture R_Handle texture_handle = group_params->tex; if(r_handle_match(texture_handle, r_handle_zero())) { texture_handle = r_d3d11_state->backup_texture; } R_D3D11_Tex2D *texture = r_d3d11_tex2d_from_handle(texture_handle); // rjf: get texture sample map matrix, based on format Mat4x4F32 texture_sample_channel_map = r_sample_channel_map_from_tex2dformat(texture->format); // rjf: upload uniforms R_D3D11_Uniforms_Rect uniforms = {0}; { uniforms.viewport_size = v2f32(resolution.x, resolution.y); uniforms.opacity = 1-group_params->transparency; uniforms.texture_sample_channel_map = texture_sample_channel_map; uniforms.texture_t2d_size = v2f32(texture->size.x, texture->size.y); uniforms.xform[0] = v4f32(group_params->xform.v[0][0], group_params->xform.v[1][0], group_params->xform.v[2][0], 0); uniforms.xform[1] = v4f32(group_params->xform.v[0][1], group_params->xform.v[1][1], group_params->xform.v[2][1], 0); uniforms.xform[2] = v4f32(group_params->xform.v[0][2], group_params->xform.v[1][2], group_params->xform.v[2][2], 0); Vec2F32 xform_2x2_col0 = v2f32(uniforms.xform[0].x, uniforms.xform[1].x); Vec2F32 xform_2x2_col1 = v2f32(uniforms.xform[0].y, uniforms.xform[1].y); uniforms.xform_scale.x = length_2f32(xform_2x2_col0); uniforms.xform_scale.y = length_2f32(xform_2x2_col1); } { D3D11_MAPPED_SUBRESOURCE sub_rsrc = {0}; d_ctx->lpVtbl->Map(d_ctx, (ID3D11Resource *)uniforms_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sub_rsrc); MemoryCopy((U8 *)sub_rsrc.pData, &uniforms, sizeof(uniforms)); d_ctx->lpVtbl->Unmap(d_ctx, (ID3D11Resource *)uniforms_buffer, 0); } // rjf: setup output merger d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->stage_color_rtv, 0); d_ctx->lpVtbl->OMSetDepthStencilState(d_ctx, r_d3d11_state->noop_depth_stencil, 0); d_ctx->lpVtbl->OMSetBlendState(d_ctx, r_d3d11_state->main_blend_state, 0, 0xffffffff); // rjf: setup input assembly U32 stride = batches->bytes_per_inst; U32 offset = 0; d_ctx->lpVtbl->IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); d_ctx->lpVtbl->IASetInputLayout(d_ctx, ilay); d_ctx->lpVtbl->IASetVertexBuffers(d_ctx, 0, 1, &buffer, &stride, &offset); // rjf: setup shaders d_ctx->lpVtbl->VSSetShader(d_ctx, vshad, 0, 0); d_ctx->lpVtbl->VSSetConstantBuffers(d_ctx, 0, 1, &uniforms_buffer); d_ctx->lpVtbl->PSSetShader(d_ctx, pshad, 0, 0); d_ctx->lpVtbl->PSSetConstantBuffers(d_ctx, 0, 1, &uniforms_buffer); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &texture->view); d_ctx->lpVtbl->PSSetSamplers(d_ctx, 0, 1, &sampler); // rjf: setup scissor rect { Rng2F32 clip = group_params->clip; D3D11_RECT rect = {0}; { if(clip.x0 == 0 && clip.y0 == 0 && clip.x1 == 0 && clip.y1 == 0) { rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; } else if(clip.x0 > clip.x1 || clip.y0 > clip.y1) { rect.left = 0; rect.right = 0; rect.top = 0; rect.bottom = 0; } else { rect.left = (LONG)clip.x0; rect.right = (LONG)clip.x1; rect.top = (LONG)clip.y0; rect.bottom = (LONG)clip.y1; } } d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: draw d_ctx->lpVtbl->DrawInstanced(d_ctx, 4, batches->byte_count / batches->bytes_per_inst, 0, 0); } }break; //////////////////////// //- rjf: blur rendering pass // case R_PassKind_Blur: { R_PassParams_Blur *params = pass->params_blur; ID3D11SamplerState *sampler = r_d3d11_state->samplers[R_Tex2DSampleKind_Linear]; ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Blur]; ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Blur]; ID3D11Buffer *uniforms_buffer = r_d3d11_state->uniform_type_kind_buffers[R_D3D11_VShadKind_Blur]; // rjf: setup output merger d_ctx->lpVtbl->OMSetDepthStencilState(d_ctx, r_d3d11_state->noop_depth_stencil, 0); d_ctx->lpVtbl->OMSetBlendState(d_ctx, r_d3d11_state->no_blend_state, 0, 0xffffffff); // rjf: set up viewport Vec2S32 resolution = wnd->last_resolution; D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f }; d_ctx->lpVtbl->RSSetViewports(d_ctx, 1, &viewport); d_ctx->lpVtbl->RSSetState(d_ctx, (ID3D11RasterizerState *)r_d3d11_state->main_rasterizer); // rjf: setup input assembly d_ctx->lpVtbl->IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); d_ctx->lpVtbl->IASetInputLayout(d_ctx, 0); // rjf: setup shaders d_ctx->lpVtbl->VSSetShader(d_ctx, vshad, 0, 0); d_ctx->lpVtbl->VSSetConstantBuffers(d_ctx, 0, 1, &uniforms_buffer); d_ctx->lpVtbl->PSSetShader(d_ctx, pshad, 0, 0); d_ctx->lpVtbl->PSSetSamplers(d_ctx, 0, 1, &sampler); // rjf: setup scissor rect { D3D11_RECT rect = { 0 }; rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: set up uniforms R_D3D11_Uniforms_Blur uniforms = { 0 }; { F32 weights[ArrayCount(uniforms.kernel)*2] = {0}; F32 blur_size = Min(params->blur_size, ArrayCount(weights)); U64 blur_count = (U64)round_f32(blur_size); F32 stdev = (blur_size-1.f)/2.f; F32 one_over_root_2pi_stdev2 = 1/sqrt_f32(2*pi32*stdev*stdev); F32 euler32 = 2.718281828459045f; weights[0] = 1.f; if(stdev > 0.f) { for(U64 idx = 0; idx < blur_count; idx += 1) { F32 kernel_x = (F32)idx; weights[idx] = one_over_root_2pi_stdev2*pow_f32(euler32, -kernel_x*kernel_x/(2.f*stdev*stdev)); } } if(weights[0] > 1.f) { MemoryZeroArray(weights); weights[0] = 1.f; } else { // prepare weights & offsets for bilinear lookup // blur filter wants to calculate w0*pixel[pos] + w1*pixel[pos+1] + ... // with bilinear filter we can do this calulation by doing only w*sample(pos+t) = w*((1-t)*pixel[pos] + t*pixel[pos+1]) // we can see w0=w*(1-t) and w1=w*t // thus w=w0+w1 and t=w1/w for (U64 idx = 1; idx < blur_count; idx += 2) { F32 w0 = weights[idx + 0]; F32 w1 = weights[idx + 1]; F32 w = w0 + w1; F32 t = w1 / w; // each kernel element is float2(weight, offset) // weights & offsets are adjusted for bilinear sampling // zw elements are not used, a bit of waste but it allows for simpler shader code uniforms.kernel[(idx+1)/2] = v4f32(w, (F32)idx + t, 0, 0); } } uniforms.kernel[0].x = weights[0]; // technically we need just direction be different // but there are 256 bytes of usable space anyway for each constant buffer chunk uniforms.passes[Axis2_X].viewport_size = v2f32(resolution.x, resolution.y); uniforms.passes[Axis2_X].rect = params->rect; uniforms.passes[Axis2_X].direction = v2f32(1.f / resolution.x, 0); uniforms.passes[Axis2_X].blur_count = 1 + blur_count / 2; // 2x smaller because of bilinear sampling MemoryCopyArray(uniforms.passes[Axis2_X].corner_radii.v, params->corner_radii); uniforms.passes[Axis2_Y].viewport_size = v2f32(resolution.x, resolution.y); uniforms.passes[Axis2_Y].rect = params->rect; uniforms.passes[Axis2_Y].direction = v2f32(0, 1.f / resolution.y); uniforms.passes[Axis2_Y].blur_count = 1 + blur_count / 2; // 2x smaller because of bilinear sampling MemoryCopyArray(uniforms.passes[Axis2_Y].corner_radii.v, params->corner_radii); D3D11_MAPPED_SUBRESOURCE sub_rsrc = {0}; d_ctx->lpVtbl->Map(d_ctx, (ID3D11Resource *)uniforms_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sub_rsrc); MemoryCopy((U8 *)sub_rsrc.pData, &uniforms, sizeof(uniforms)); d_ctx->lpVtbl->Unmap(d_ctx, (ID3D11Resource *)uniforms_buffer, 0); } ID3D11Buffer *uniforms_buffers[] = { uniforms_buffer, uniforms_buffer }; U32 uniform_offset[Axis2_COUNT][2] = { { 0 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 }, { 1 * sizeof(R_D3D11_Uniforms_BlurPass) / 16, (U32)OffsetOf(R_D3D11_Uniforms_Blur, kernel) / 16 }, }; U32 uniform_count[Axis2_COUNT][2] = { { sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 }, { sizeof(R_D3D11_Uniforms_BlurPass) / 16, sizeof(uniforms.kernel) / 16 }, }; // rjf: setup scissor rect { Rng2F32 clip = params->clip; D3D11_RECT rect = {0}; { if(clip.x0 == 0 && clip.y0 == 0 && clip.x1 == 0 && clip.y1 == 0) { rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; } else if(clip.x0 > clip.x1 || clip.y0 > clip.y1) { rect.left = 0; rect.right = 0; rect.top = 0; rect.bottom = 0; } else { rect.left = (LONG)clip.x0; rect.right = (LONG)clip.x1; rect.top = (LONG)clip.y0; rect.bottom = (LONG)clip.y1; } } d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: for unsetting srv ID3D11ShaderResourceView* srv = 0; // horizontal pass d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->stage_scratch_color_rtv, 0); d_ctx->lpVtbl->PSSetConstantBuffers1(d_ctx, 0, ArrayCount(uniforms_buffers), uniforms_buffers, uniform_offset[Axis2_X], uniform_count[Axis2_X]); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &wnd->stage_color_srv); d_ctx->lpVtbl->Draw(d_ctx, 4, 0); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &srv); // vertical pass d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->stage_color_rtv, 0); d_ctx->lpVtbl->PSSetConstantBuffers1(d_ctx, 0, ArrayCount(uniforms_buffers), uniforms_buffers, uniform_offset[Axis2_Y], uniform_count[Axis2_Y]); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &wnd->stage_scratch_color_srv); d_ctx->lpVtbl->Draw(d_ctx, 4, 0); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &srv); }break; //////////////////////// //- rjf: 3d geometry rendering pass // case R_PassKind_Geo3D: { //- rjf: unpack params R_PassParams_Geo3D *params = pass->params_geo3d; R_BatchGroup3DMap *mesh_group_map = ¶ms->mesh_batches; //- rjf: set up rasterizer Vec2F32 viewport_dim = dim_2f32(params->viewport); D3D11_VIEWPORT viewport = { params->viewport.x0, params->viewport.y0, viewport_dim.x, viewport_dim.y, 0.f, 1.f }; d_ctx->lpVtbl->RSSetViewports(d_ctx, 1, &viewport); d_ctx->lpVtbl->RSSetState(d_ctx, (ID3D11RasterizerState *)r_d3d11_state->main_rasterizer); //- rjf: clear render targets { Vec4F32 bg_color = v4f32(0, 0, 0, 0); d_ctx->lpVtbl->ClearRenderTargetView(d_ctx, wnd->geo3d_color_rtv, bg_color.v); d_ctx->lpVtbl->ClearDepthStencilView(d_ctx, wnd->geo3d_depth_dsv, D3D11_CLEAR_DEPTH, 1.f, 0); } //- rjf: draw mesh batches { // rjf: grab pipeline info ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Mesh]; ID3D11InputLayout *ilay = r_d3d11_state->ilays[R_D3D11_VShadKind_Mesh]; ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Mesh]; ID3D11Buffer *uniforms_buffer = r_d3d11_state->uniform_type_kind_buffers[R_D3D11_VShadKind_Mesh]; // rjf: setup output merger d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->geo3d_color_rtv, wnd->geo3d_depth_dsv); d_ctx->lpVtbl->OMSetDepthStencilState(d_ctx, r_d3d11_state->plain_depth_stencil, 0); d_ctx->lpVtbl->OMSetBlendState(d_ctx, r_d3d11_state->main_blend_state, 0, 0xffffffff); // rjf: draw all batches for(U64 slot_idx = 0; slot_idx < mesh_group_map->slots_count; slot_idx += 1) { for(R_BatchGroup3DMapNode *n = mesh_group_map->slots[slot_idx]; n != 0; n = n->next) { // rjf: unpack group params R_BatchList *batches = &n->batches; R_BatchGroup3DParams *group_params = &n->params; R_D3D11_Buffer *mesh_vertices = r_d3d11_buffer_from_handle(group_params->mesh_vertices); R_D3D11_Buffer *mesh_indices = r_d3d11_buffer_from_handle(group_params->mesh_indices); // rjf: setup input assembly U32 stride = 11 * sizeof(F32); U32 offset = 0; d_ctx->lpVtbl->IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); d_ctx->lpVtbl->IASetInputLayout(d_ctx, ilay); d_ctx->lpVtbl->IASetVertexBuffers(d_ctx, 0, 1, &mesh_vertices->buffer, &stride, &offset); d_ctx->lpVtbl->IASetIndexBuffer(d_ctx, mesh_indices->buffer, DXGI_FORMAT_R32_UINT, 0); // rjf: setup uniforms buffer R_D3D11_Uniforms_Mesh uniforms = {0}; { uniforms.xform = mul_4x4f32(params->projection, params->view); } { D3D11_MAPPED_SUBRESOURCE sub_rsrc = {0}; d_ctx->lpVtbl->Map(d_ctx, (ID3D11Resource *)uniforms_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sub_rsrc); MemoryCopy((U8 *)sub_rsrc.pData, &uniforms, sizeof(uniforms)); d_ctx->lpVtbl->Unmap(d_ctx, (ID3D11Resource *)uniforms_buffer, 0); } // rjf: setup shaders d_ctx->lpVtbl->VSSetShader(d_ctx, vshad, 0, 0); d_ctx->lpVtbl->VSSetConstantBuffers(d_ctx, 0, 1, &uniforms_buffer); d_ctx->lpVtbl->PSSetShader(d_ctx, pshad, 0, 0); d_ctx->lpVtbl->PSSetConstantBuffers(d_ctx, 0, 1, &uniforms_buffer); // rjf: setup scissor rect { D3D11_RECT rect = {0}; { rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; } d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: draw d_ctx->lpVtbl->DrawIndexed(d_ctx, mesh_indices->size/sizeof(U32), 0, 0); } } } //- rjf: composite to main staging buffer { ID3D11SamplerState *sampler = r_d3d11_state->samplers[R_Tex2DSampleKind_Nearest]; ID3D11VertexShader *vshad = r_d3d11_state->vshads[R_D3D11_VShadKind_Geo3DComposite]; ID3D11PixelShader *pshad = r_d3d11_state->pshads[R_D3D11_PShadKind_Geo3DComposite]; // rjf: setup output merger d_ctx->lpVtbl->OMSetRenderTargets(d_ctx, 1, &wnd->stage_color_rtv, 0); d_ctx->lpVtbl->OMSetDepthStencilState(d_ctx, r_d3d11_state->noop_depth_stencil, 0); d_ctx->lpVtbl->OMSetBlendState(d_ctx, r_d3d11_state->main_blend_state, 0, 0xffffffff); // rjf: set up rasterizer Vec2S32 resolution = wnd->last_resolution; D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (F32)resolution.x, (F32)resolution.y, 0.0f, 1.0f }; d_ctx->lpVtbl->RSSetViewports(d_ctx, 1, &viewport); d_ctx->lpVtbl->RSSetState(d_ctx, (ID3D11RasterizerState *)r_d3d11_state->main_rasterizer); // rjf: setup input assembly d_ctx->lpVtbl->IASetPrimitiveTopology(d_ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); d_ctx->lpVtbl->IASetInputLayout(d_ctx, 0); // rjf: setup shaders d_ctx->lpVtbl->VSSetShader(d_ctx, vshad, 0, 0); d_ctx->lpVtbl->PSSetShader(d_ctx, pshad, 0, 0); d_ctx->lpVtbl->PSSetShaderResources(d_ctx, 0, 1, &wnd->geo3d_color_srv); d_ctx->lpVtbl->PSSetSamplers(d_ctx, 0, 1, &sampler); // rjf: setup scissor rect { D3D11_RECT rect = {0}; Rng2F32 clip = params->clip; if(clip.x0 == 0 && clip.y0 == 0 && clip.x1 == 0 && clip.y1 == 0) { rect.left = 0; rect.right = (LONG)wnd->last_resolution.x; rect.top = 0; rect.bottom = (LONG)wnd->last_resolution.y; } else if(clip.x0 > clip.x1 || clip.y0 > clip.y1) { rect.left = 0; rect.right = 0; rect.top = 0; rect.bottom = 0; } else { rect.left = (LONG)clip.x0; rect.right = (LONG)clip.x1; rect.top = (LONG)clip.y0; rect.bottom = (LONG)clip.y1; } d_ctx->lpVtbl->RSSetScissorRects(d_ctx, 1, &rect); } // rjf: draw d_ctx->lpVtbl->Draw(d_ctx, 4, 0); } }break; } } } ProfEnd(); } ================================================ FILE: src/render/d3d11/render_d3d11.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_D3D11_H #define RENDER_D3D11_H #include #include #include #include #include #include #pragma comment(lib, "user32") #pragma comment(lib, "d3d11") #pragma comment(lib, "d3dcompiler") //////////////////////////////// //~ rjf: Generated Code #include "generated/render_d3d11.meta.h" //////////////////////////////// //~ rjf: C-side Shader Types typedef struct R_D3D11_Uniforms_Rect R_D3D11_Uniforms_Rect; struct R_D3D11_Uniforms_Rect { Vec2F32 viewport_size; F32 opacity; F32 _padding0_; Mat4x4F32 texture_sample_channel_map; Vec2F32 texture_t2d_size; Vec2F32 translate; Vec4F32 xform[3]; Vec2F32 xform_scale; }; typedef struct R_D3D11_Uniforms_BlurPass R_D3D11_Uniforms_BlurPass; struct R_D3D11_Uniforms_BlurPass { Rng2F32 rect; Vec4F32 corner_radii; Vec2F32 direction; Vec2F32 viewport_size; U32 blur_count; U8 _padding0_[204]; }; StaticAssert(sizeof(R_D3D11_Uniforms_BlurPass) % 256 == 0, NotAligned); // constant count/offset must be aligned to 256 bytes typedef struct R_D3D11_Uniforms_Blur R_D3D11_Uniforms_Blur; struct R_D3D11_Uniforms_Blur { R_D3D11_Uniforms_BlurPass passes[Axis2_COUNT]; Vec4F32 kernel[32]; }; typedef struct R_D3D11_Uniforms_Mesh R_D3D11_Uniforms_Mesh; struct R_D3D11_Uniforms_Mesh { Mat4x4F32 xform; }; //////////////////////////////// //~ rjf: Main State Types typedef struct R_D3D11_Tex2D R_D3D11_Tex2D; struct R_D3D11_Tex2D { R_D3D11_Tex2D *next; U64 generation; ID3D11Texture2D *texture; ID3D11ShaderResourceView *view; R_ResourceKind kind; Vec2S32 size; R_Tex2DFormat format; }; typedef struct R_D3D11_Buffer R_D3D11_Buffer; struct R_D3D11_Buffer { R_D3D11_Buffer *next; U64 generation; ID3D11Buffer *buffer; R_ResourceKind kind; U64 size; }; typedef struct R_D3D11_Window R_D3D11_Window; struct R_D3D11_Window { R_D3D11_Window *next; U64 generation; // rjf: swapchain/framebuffer IDXGISwapChain1 *swapchain; ID3D11Texture2D *framebuffer; ID3D11RenderTargetView *framebuffer_rtv; // rjf: staging buffer ID3D11Texture2D *stage_color; ID3D11RenderTargetView *stage_color_rtv; ID3D11ShaderResourceView *stage_color_srv; ID3D11Texture2D *stage_scratch_color; ID3D11RenderTargetView *stage_scratch_color_rtv; ID3D11ShaderResourceView *stage_scratch_color_srv; // rjf: geo3d buffer ID3D11Texture2D *geo3d_color; ID3D11RenderTargetView *geo3d_color_rtv; ID3D11ShaderResourceView *geo3d_color_srv; ID3D11Texture2D *geo3d_depth; ID3D11DepthStencilView *geo3d_depth_dsv; ID3D11ShaderResourceView *geo3d_depth_srv; // rjf: last state Vec2S32 last_resolution; }; typedef struct R_D3D11_FlushBuffer R_D3D11_FlushBuffer; struct R_D3D11_FlushBuffer { R_D3D11_FlushBuffer *next; ID3D11Buffer *buffer; }; typedef struct R_D3D11_State R_D3D11_State; struct R_D3D11_State { // rjf: state Arena *arena; U64 window_count; R_D3D11_Window *first_free_window; R_D3D11_Tex2D *first_free_tex2d; R_D3D11_Buffer *first_free_buffer; R_D3D11_Tex2D *first_to_free_tex2d; R_D3D11_Buffer *first_to_free_buffer; RWMutex device_rw_mutex; // rjf: base d3d11 objects ID3D11Device *base_device; ID3D11DeviceContext *base_device_ctx; ID3D11Device1 *device; ID3D11DeviceContext1 *device_ctx; IDXGIDevice1 *dxgi_device; IDXGIAdapter *dxgi_adapter; IDXGIFactory2 *dxgi_factory; ID3D11RasterizerState1 *main_rasterizer; ID3D11BlendState *main_blend_state; ID3D11BlendState *no_blend_state; ID3D11SamplerState *samplers[R_Tex2DSampleKind_COUNT]; ID3D11DepthStencilState *noop_depth_stencil; ID3D11DepthStencilState *plain_depth_stencil; ID3D11Buffer *instance_scratch_buffer_64kb; // rjf: backups R_Handle backup_texture; // rjf: vertex shaders ID3D11VertexShader *vshads[R_D3D11_VShadKind_COUNT]; ID3D11InputLayout *ilays[R_D3D11_VShadKind_COUNT]; ID3D11PixelShader *pshads[R_D3D11_PShadKind_COUNT]; ID3D11Buffer *uniform_type_kind_buffers[R_D3D11_UniformTypeKind_COUNT]; // rjf: buffers to flush at subsequent frame Arena *buffer_flush_arena; R_D3D11_FlushBuffer *first_buffer_to_flush; R_D3D11_FlushBuffer *last_buffer_to_flush; }; //////////////////////////////// //~ rjf: Globals global R_D3D11_State *r_d3d11_state = 0; global read_only R_D3D11_Window r_d3d11_window_nil = {&r_d3d11_window_nil}; global read_only R_D3D11_Tex2D r_d3d11_tex2d_nil = {&r_d3d11_tex2d_nil}; global read_only R_D3D11_Buffer r_d3d11_buffer_nil = {&r_d3d11_buffer_nil}; //////////////////////////////// //~ rjf: Helpers internal R_D3D11_Window *r_d3d11_window_from_handle(R_Handle handle); internal R_Handle r_d3d11_handle_from_window(R_D3D11_Window *window); internal R_D3D11_Tex2D *r_d3d11_tex2d_from_handle(R_Handle handle); internal R_Handle r_d3d11_handle_from_tex2d(R_D3D11_Tex2D *texture); internal R_D3D11_Buffer *r_d3d11_buffer_from_handle(R_Handle handle); internal R_Handle r_d3d11_handle_from_buffer(R_D3D11_Buffer *buffer); internal ID3D11Buffer *r_d3d11_instance_buffer_from_size(U64 size); internal void r_usage_access_flags_from_resource_kind(R_ResourceKind kind, D3D11_USAGE *out_d3d11_usage, UINT *out_cpu_access_flags); #endif // RENDER_D3D11_H ================================================ FILE: src/render/d3d11/render_d3d11.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Pipeline Tables @table(name, source, ilay_table) R_D3D11_VShadTable: { {Rect r_d3d11_g_rect_shader_src r_d3d11_g_rect_ilay_elements } {Blur r_d3d11_g_blur_shader_src 0 } {Mesh r_d3d11_g_mesh_shader_src r_d3d11_g_mesh_ilay_elements } {Geo3DComposite r_d3d11_g_geo3dcomposite_shader_src 0 } {Finalize r_d3d11_g_finalize_shader_src 0 } } @table(name, source) R_D3D11_PShadTable: { {Rect r_d3d11_g_rect_shader_src } {Blur r_d3d11_g_blur_shader_src } {Mesh r_d3d11_g_mesh_shader_src } {Geo3DComposite r_d3d11_g_geo3dcomposite_shader_src } {Finalize r_d3d11_g_finalize_shader_src } } @table(name) R_D3D11_UniformTypeTable: { {Rect} {Blur} {Mesh} } //////////////////////////////// //~ rjf: UI Rectangle Shaders @embed_string r_d3d11_g_rect_shader_src: """ cbuffer Globals : register(b0) { float2 viewport_size_px; float opacity; row_major float4x4 texture_sample_channel_map; float2 texture_t2d_size_px; row_major float3x3 xform; float2 xform_scale; } struct CPU2Vertex { float4 dst_rect_px : POS; float4 src_rect_px : TEX; float4 color00 : COL0; float4 color01 : COL1; float4 color10 : COL2; float4 color11 : COL3; float4 corner_radii_px : CRAD; float4 style_params : STY; // x: border_thickness_px, y: softness_px, z: omit_texture, w: shear uint vertex_id : SV_VertexID; }; struct Vertex2Pixel { float4 position : SV_POSITION; nointerpolation float2 rect_half_size_px : PSIZE; float2 texcoord_pct : TEX; float2 sdf_sample_pos : SDF; float4 tint : TINT; float corner_radius_px : CRAD; nointerpolation float border_thickness_px : BTHC; nointerpolation float softness_px : SFT; nointerpolation float omit_texture : OTX; }; Texture2D main_t2d : register(t0); SamplerState main_sampler : register(s0); float rect_sdf(float2 sample_pos, float2 rect_half_size, float r) { return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r; } float linear_from_srgb_f32(float x) { return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4); } float4 linear_from_srgba(float4 v) { float4 result = float4(linear_from_srgb_f32(v.x), linear_from_srgb_f32(v.y), linear_from_srgb_f32(v.z), v.w); return result; } //- rjf: vertex shader Vertex2Pixel vs_main(CPU2Vertex cpu2vertex) { //- rjf: unpack & xform rectangle src/dst vertices float2 dst_p0_px = cpu2vertex.dst_rect_px.xy; float2 dst_p1_px = cpu2vertex.dst_rect_px.zw; float2 src_p0_px = cpu2vertex.src_rect_px.xy; float2 src_p1_px = cpu2vertex.src_rect_px.zw; float2 dst_size_px = abs(dst_p1_px - dst_p0_px); //- rjf: unpack style params float border_thickness_px = cpu2vertex.style_params.x; float softness_px = cpu2vertex.style_params.y; float omit_texture = cpu2vertex.style_params.z; float shear_px = cpu2vertex.style_params.w; //- rjf: prep per-vertex arrays to sample from (p: position, t: texcoord, c: colorcoord, r: cornerradius) float2 dst_p_verts_px[] = { float2(dst_p0_px.x, dst_p1_px.y), float2(dst_p0_px.x, dst_p0_px.y), float2(dst_p1_px.x, dst_p1_px.y + shear_px), float2(dst_p1_px.x, dst_p0_px.y + shear_px), }; float2 src_p_verts_px[] = { float2(src_p0_px.x, src_p1_px.y), float2(src_p0_px.x, src_p0_px.y), float2(src_p1_px.x, src_p1_px.y), float2(src_p1_px.x, src_p0_px.y), }; float dst_r_verts_px[] = { cpu2vertex.corner_radii_px.y, cpu2vertex.corner_radii_px.x, cpu2vertex.corner_radii_px.w, cpu2vertex.corner_radii_px.z, }; float4 src_color[] = { cpu2vertex.color01, cpu2vertex.color00, cpu2vertex.color11, cpu2vertex.color10, }; float2 dst_verts_pct = float2((cpu2vertex.vertex_id >> 1) ? 1.f : 0.f, (cpu2vertex.vertex_id & 1) ? 0.f : 1.f); // rjf: fill vertex -> pixel data Vertex2Pixel vertex2pixel; { float2 xformed_pos = mul(xform, float3(dst_p_verts_px[cpu2vertex.vertex_id], 1.f)).xy; xformed_pos.y = viewport_size_px.y - xformed_pos.y; vertex2pixel.position.xy = 2.f * xformed_pos/viewport_size_px - 1.f; vertex2pixel.position.z = 0.f; vertex2pixel.position.w = 1.f; vertex2pixel.rect_half_size_px = dst_size_px / 2.f * xform_scale; vertex2pixel.texcoord_pct = src_p_verts_px[cpu2vertex.vertex_id] / texture_t2d_size_px; vertex2pixel.sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * vertex2pixel.rect_half_size_px; vertex2pixel.tint = src_color[cpu2vertex.vertex_id]; vertex2pixel.corner_radius_px = dst_r_verts_px[cpu2vertex.vertex_id]; vertex2pixel.border_thickness_px = border_thickness_px; vertex2pixel.softness_px = softness_px; vertex2pixel.omit_texture = omit_texture; } return vertex2pixel; } //- rjf: pixel shader float4 ps_main(Vertex2Pixel vertex2pixel) : SV_TARGET { // rjf: blend corner colors to produce final tint float4 tint = vertex2pixel.tint; // rjf: sample texture float4 albedo_sample = float4(1, 1, 1, 1); if(vertex2pixel.omit_texture < 1) { albedo_sample = mul(main_t2d.Sample(main_sampler, vertex2pixel.texcoord_pct), texture_sample_channel_map); albedo_sample = linear_from_srgba(albedo_sample); } // rjf: determine SDF sample position float2 sdf_sample_pos = vertex2pixel.sdf_sample_pos; // rjf: sample for borders float border_sdf_t = 1; if(vertex2pixel.border_thickness_px > 0) { float border_sdf_s = rect_sdf(sdf_sample_pos, vertex2pixel.rect_half_size_px - float2(vertex2pixel.softness_px*2.f, vertex2pixel.softness_px*2.f) - vertex2pixel.border_thickness_px, max(vertex2pixel.corner_radius_px-vertex2pixel.border_thickness_px, 0)); border_sdf_t = smoothstep(0, 2*vertex2pixel.softness_px, border_sdf_s); } if(border_sdf_t < 0.001f) { discard; } // rjf: sample for corners float corner_sdf_t = 1; if(vertex2pixel.corner_radius_px > 0 || vertex2pixel.softness_px > 0.75f) { float corner_sdf_s = rect_sdf(sdf_sample_pos, vertex2pixel.rect_half_size_px - float2(vertex2pixel.softness_px*2.f, vertex2pixel.softness_px*2.f), vertex2pixel.corner_radius_px); corner_sdf_t = 1-smoothstep(0, 2*vertex2pixel.softness_px, corner_sdf_s); } // rjf: form+return final color float4 final_color = albedo_sample; final_color *= tint; final_color.a *= opacity; final_color.a *= corner_sdf_t; final_color.a *= border_sdf_t; return final_color; } """ //////////////////////////////// //~ rjf: Blur Shaders @embed_string r_d3d11_g_blur_shader_src: """ cbuffer Globals : register(b0) { float4 rect; float4 corner_radii_px; float2 direction; float2 viewport_size; uint blur_count; } cbuffer Kernel : register(b1) { float4 kernel[32]; } struct CPU2Vertex { uint vertex_id : SV_VertexID; }; struct Vertex2Pixel { float4 position : SV_POSITION; float2 texcoord : TEX; float2 sdf_sample_pos : SDF; nointerpolation float2 rect_half_size : RHS; float corner_radius : RAD; }; Texture2D stage_t2d : register(t0); SamplerState stage_sampler : register(s0); float rect_sdf(float2 sample_pos, float2 rect_half_size, float r) { return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r; } //- rjf: vertex shader Vertex2Pixel vs_main(CPU2Vertex c2v) { float2 vertex_positions__scrn[] = { rect.xw, rect.xy, rect.zw, rect.zy, }; float corner_radii__px[] = { corner_radii_px.y, corner_radii_px.x, corner_radii_px.w, corner_radii_px.z, }; float2 cornercoords__pct = float2((c2v.vertex_id >> 1) ? 1.f : 0.f, (c2v.vertex_id & 1) ? 0.f : 1.f); float2 vertex_position__pct = vertex_positions__scrn[c2v.vertex_id] / viewport_size; float2 vertex_position__scr = 2.f * vertex_position__pct - 1.f; float2 rect_half_size = float2((rect.z-rect.x)/2, (rect.w-rect.y)/2); Vertex2Pixel v2p; { v2p.position = float4(vertex_position__scr.x, -vertex_position__scr.y, 0.f, 1.f); v2p.texcoord = vertex_position__pct; v2p.sdf_sample_pos = (2.f * cornercoords__pct - 1.f) * rect_half_size; v2p.rect_half_size = rect_half_size - 2.f; v2p.corner_radius = corner_radii__px[c2v.vertex_id]; } return v2p; } //- rjf: pixel shader float4 ps_main(Vertex2Pixel v2p) : SV_TARGET { // rjf: blend weighted texture samples into color float3 color = kernel[0].x * stage_t2d.Sample(stage_sampler, v2p.texcoord).rgb; for(uint i = 1; i < blur_count; i += 1) { float weight = kernel[i].x; float offset = kernel[i].y; color += weight * stage_t2d.Sample(stage_sampler, v2p.texcoord - offset * direction).rgb; color += weight * stage_t2d.Sample(stage_sampler, v2p.texcoord + offset * direction).rgb; } // rjf: sample for corners float corner_sdf_s = rect_sdf(v2p.sdf_sample_pos, v2p.rect_half_size, v2p.corner_radius); float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s); // rjf: weight output color by sdf // this is doing alpha testing, leave blurring only where mostly opaque pixels are if (corner_sdf_t < 0.9f) { discard; } return float4(color, 1.f); } """ //////////////////////////////// //~ rjf: Mesh Shaders @embed_string r_d3d11_g_mesh_shader_src: """ cbuffer Uniforms : register(b0) { row_major float4x4 xform; } struct CPU2Vertex { float3 position : POS; float3 normal : NOR; float2 texcoord : TEX; float3 color : COL; }; struct Vertex2Pixel { float4 position : SV_POSITION; float2 texcoord : TEX; float4 color : COL; }; Vertex2Pixel vs_main(CPU2Vertex c2v) { Vertex2Pixel v2p; v2p.position = mul(float4(c2v.position, 1.f), xform); v2p.texcoord = c2v.texcoord; v2p.color = float4(c2v.color, 1.f); return v2p; } float4 ps_main(Vertex2Pixel v2p) : SV_TARGET { return v2p.color; } """; //////////////////////////////// //~ rjf: Geo3D Composition Shaders @embed_string r_d3d11_g_geo3dcomposite_shader_src: """ struct CPU2Vertex { uint vertex_id : SV_VertexID; }; struct Vertex2Pixel { float4 position : SV_POSITION; float2 texcoord : TEX; }; Texture2D stage_t2d : register(t0); SamplerState stage_sampler : register(s0); //- rjf: vertex shader Vertex2Pixel vs_main(CPU2Vertex c2v) { float4 vertex_positions__modl[] = { float4(0, 0, 0, 1), float4(0, 1, 0, 1), float4(1, 0, 0, 1), float4(1, 1, 0, 1), }; float4 vertex_position__modl = vertex_positions__modl[c2v.vertex_id]; float4 vertex_position__clip = float4(2*vertex_position__modl.x - 1, 2*vertex_position__modl.y - 1, 0, 1); float2 texcoord = float2(vertex_position__modl.x, vertex_position__modl.y); texcoord.y = 1-texcoord.y; Vertex2Pixel v2p; { v2p.position = vertex_position__clip; v2p.texcoord = texcoord; } return v2p; } //- rjf: pixel shader float4 ps_main(Vertex2Pixel v2p) : SV_TARGET { float4 final_color = stage_t2d.Sample(stage_sampler, v2p.texcoord); return final_color; } """ //////////////////////////////// //~ rjf: Finalize Shaders @embed_string r_d3d11_g_finalize_shader_src: """ struct CPU2Vertex { uint vertex_id : SV_VertexID; }; struct Vertex2Pixel { float4 position : SV_POSITION; float2 texcoord : TEX; }; Texture2D stage_t2d : register(t0); SamplerState stage_sampler : register(s0); //- rjf: vertex shader Vertex2Pixel vs_main(CPU2Vertex c2v) { float4 vertex_positions__modl[] = { float4(0, 0, 0, 1), float4(0, 1, 0, 1), float4(1, 0, 0, 1), float4(1, 1, 0, 1), }; float4 vertex_position__modl = vertex_positions__modl[c2v.vertex_id]; float4 vertex_position__clip = float4(2*vertex_position__modl.x - 1, 2*vertex_position__modl.y - 1, 0, 1); float2 texcoord = float2(vertex_position__modl.x, vertex_position__modl.y); texcoord.y = 1-texcoord.y; Vertex2Pixel v2p; { v2p.position = vertex_position__clip; v2p.texcoord = texcoord; } return v2p; } //- rjf: pixel shader float4 ps_main(Vertex2Pixel v2p) : SV_TARGET { float4 final_color = stage_t2d.Sample(stage_sampler, v2p.texcoord); final_color.a = 1; return final_color; } """ //////////////////////////////// //~ rjf: Table Generators @enum R_D3D11_VShadKind: { @expand(R_D3D11_VShadTable a) `$(a.name)`, COUNT, } @enum R_D3D11_PShadKind: { @expand(R_D3D11_PShadTable a) `$(a.name)`, COUNT, } @enum R_D3D11_UniformTypeKind: { @expand(R_D3D11_UniformTypeTable a) `$(a.name)`, COUNT, } @c_file @data(`String8*`) r_d3d11_g_vshad_kind_source_table: { @expand(R_D3D11_VShadTable a) `&$(a.source)`; } @c_file @data(String8) r_d3d11_g_vshad_kind_source_name_table: { @expand(R_D3D11_VShadTable a) `str8_lit_comp("$(a.source)")`; } @c_file @data(`D3D11_INPUT_ELEMENT_DESC *`) r_d3d11_g_vshad_kind_elements_ptr_table: { @expand(R_D3D11_VShadTable a) `$(a.ilay_table)`; } @c_file @data(U64) r_d3d11_g_vshad_kind_elements_count_table: { @expand(R_D3D11_VShadTable a) `$(a.ilay_table != 0 -> "ArrayCount("..a.ilay_table..")") $(a.ilay_table == 0 -> "0")`; } @c_file @data(`String8*`) r_d3d11_g_pshad_kind_source_table: { @expand(R_D3D11_PShadTable a) `&$(a.source)`; } @c_file @data(String8) r_d3d11_g_pshad_kind_source_name_table: { @expand(R_D3D11_PShadTable a) `str8_lit_comp("$(a.source)")`; } @c_file @data(U64) r_d3d11_g_uniform_type_kind_size_table: { @expand(R_D3D11_UniformTypeTable a) `sizeof(R_D3D11_Uniforms_$(a.name))`; } ================================================ FILE: src/render/generated/render.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 r_tex2d_format_display_string_table[9] = { str8_lit_comp("R8"), str8_lit_comp("RG8"), str8_lit_comp("RGBA8"), str8_lit_comp("BGRA8"), str8_lit_comp("R16"), str8_lit_comp("RGBA16"), str8_lit_comp("R32"), str8_lit_comp("RG32"), str8_lit_comp("RGBA32"), }; U8 r_tex2d_format_bytes_per_pixel_table[9] = { 1, 2, 4, 4, 2, 8, 4, 8, 16, }; String8 r_resource_kind_display_string_table[3] = { str8_lit_comp("Static"), str8_lit_comp("Dynamic"), str8_lit_comp("Stream "), }; String8 r_tex2d_sample_kind_display_string_table[2] = { str8_lit_comp("Nearest"), str8_lit_comp("Linear"), }; String8 r_pass_kind_display_string_table[3] = { str8_lit_comp("UI"), str8_lit_comp("Blur"), str8_lit_comp("Geo3D"), }; U8 r_pass_kind_batch_table[3] = { 1, 0, 1, }; U64 r_pass_kind_params_size_table[3] = { sizeof(R_PassParams_UI), sizeof(R_PassParams_Blur), sizeof(R_PassParams_Geo3D), }; C_LINKAGE_END ================================================ FILE: src/render/generated/render.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef RENDER_META_H #define RENDER_META_H typedef enum R_Tex2DFormat { R_Tex2DFormat_R8, R_Tex2DFormat_RG8, R_Tex2DFormat_RGBA8, R_Tex2DFormat_BGRA8, R_Tex2DFormat_R16, R_Tex2DFormat_RGBA16, R_Tex2DFormat_R32, R_Tex2DFormat_RG32, R_Tex2DFormat_RGBA32, R_Tex2DFormat_COUNT, } R_Tex2DFormat; typedef enum R_ResourceKind { R_ResourceKind_Static, R_ResourceKind_Dynamic, R_ResourceKind_Stream, R_ResourceKind_COUNT, } R_ResourceKind; typedef enum R_Tex2DSampleKind { R_Tex2DSampleKind_Nearest, R_Tex2DSampleKind_Linear, R_Tex2DSampleKind_COUNT, } R_Tex2DSampleKind; typedef enum R_GeoTopologyKind { R_GeoTopologyKind_Lines, R_GeoTopologyKind_LineStrip, R_GeoTopologyKind_Triangles, R_GeoTopologyKind_TriangleStrip, R_GeoTopologyKind_COUNT, } R_GeoTopologyKind; typedef enum R_PassKind { R_PassKind_UI, R_PassKind_Blur, R_PassKind_Geo3D, R_PassKind_COUNT, } R_PassKind; C_LINKAGE_BEGIN extern String8 r_tex2d_format_display_string_table[9]; extern U8 r_tex2d_format_bytes_per_pixel_table[9]; extern String8 r_resource_kind_display_string_table[3]; extern String8 r_tex2d_sample_kind_display_string_table[2]; extern String8 r_pass_kind_display_string_table[3]; extern U8 r_pass_kind_batch_table[3]; C_LINKAGE_END #endif // RENDER_META_H ================================================ FILE: src/render/opengl/generated/render_opengl.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 r_ogl_shader_kind_name_table[2] = { str8_lit_comp("rect"), str8_lit_comp("blur"), }; String8 * r_ogl_shader_kind_vshad_src_table[2] = { &r_ogl_rect_vshad_src, &r_ogl_blur_vshad_src, }; String8 * r_ogl_shader_kind_pshad_src_table[2] = { &r_ogl_rect_pshad_src, &r_ogl_blur_pshad_src, }; R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2] = { { r_ogl_rect_input_attributes, ArrayCount(r_ogl_rect_input_attributes) }, { 0, }, }; R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2] = { { r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, { r_ogl_single_color_output_attributes, ArrayCount(r_ogl_single_color_output_attributes) }, }; C_LINKAGE_END ================================================ FILE: src/render/opengl/generated/render_opengl.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef RENDER_OPENGL_META_H #define RENDER_OPENGL_META_H typedef enum R_OGL_ShaderKind { R_OGL_ShaderKind_Rect, R_OGL_ShaderKind_Blur, R_OGL_ShaderKind_COUNT, } R_OGL_ShaderKind; C_LINKAGE_BEGIN extern String8 r_ogl_shader_kind_name_table[2]; extern String8 * r_ogl_shader_kind_vshad_src_table[2]; extern String8 * r_ogl_shader_kind_pshad_src_table[2]; extern R_OGL_AttributeArray r_ogl_shader_kind_input_attributes_table[2]; extern R_OGL_AttributeArray r_ogl_shader_kind_output_attributes_table[2]; read_only global String8 r_ogl_rect_vshad_src = str8_lit_comp( "" "\n" "#version 330 core\n" "\n" "in vec4 c2v_dst_rect;\n" "in vec4 c2v_src_rect;\n" "in vec4 c2v_colors_0;\n" "in vec4 c2v_colors_1;\n" "in vec4 c2v_colors_2;\n" "in vec4 c2v_colors_3;\n" "in vec4 c2v_corner_radii;\n" "in vec4 c2v_style; // x: border_thickness_px, y: softness_px, z: omit_texture, w: shear\n" "\n" "out vec2 v2p_sdf_sample_pos;\n" "out vec2 v2p_texcoord_pct;\n" "out vec2 v2p_rect_half_size_px;\n" "out vec4 v2p_tint;\n" "out float v2p_corner_radius;\n" "out float v2p_border_thickness;\n" "out float v2p_softness;\n" "out float v2p_omit_texture;\n" "\n" "uniform sampler2D u_tex_color;\n" "uniform vec2 u_viewport_size_px;\n" "\n" "void main(void)\n" "{\n" " // rjf: constants\n" " vec2 vertices[] = vec2[](vec2(-1, -1), vec2(-1, +1), vec2(+1, -1), vec2(+1, +1));\n" " \n" " // rjf: unpack shears\n" " float shears[] = float[](0, 0, c2v_style.w, c2v_style.w);\n" " \n" " // rjf: find dst position\n" " vec2 dst_half_size = (c2v_dst_rect.zw - c2v_dst_rect.xy) / 2;\n" " vec2 dst_center = (c2v_dst_rect.zw + c2v_dst_rect.xy) / 2;\n" " vec2 dst_position = vertices[gl_VertexID] * dst_half_size + dst_center;\n" " dst_position.y += shears[gl_VertexID];\n" " \n" " // rjf: find src position\n" " vec2 src_half_size = (c2v_src_rect.zw - c2v_src_rect.xy) / 2;\n" " vec2 src_center = (c2v_src_rect.zw + c2v_src_rect.xy) / 2;\n" " vec2 src_position = vertices[gl_VertexID] * src_half_size + src_center;\n" " \n" " // rjf: find color\n" " vec4 colors[] = vec4[](c2v_colors_0, c2v_colors_1, c2v_colors_2, c2v_colors_3);\n" " vec4 color = colors[gl_VertexID];\n" " \n" " // rjf: find corner radius\n" " float corner_radii[] = float[](c2v_corner_radii.x, c2v_corner_radii.y, c2v_corner_radii.z, c2v_corner_radii.w);\n" " float corner_radius = corner_radii[gl_VertexID];\n" " \n" " // rjf: fill outputs\n" " vec2 dst_verts_pct = vec2(((gl_VertexID >> 1) != 1) ? 1.f : 0.f,\n" " ((gl_VertexID & 1) != 0) ? 0.f : 1.f);\n" " ivec2 u_tex_color_size_i = textureSize(u_tex_color, 0);\n" " vec2 u_tex_color_size = vec2(float(u_tex_color_size_i.x), float(u_tex_color_size_i.y));\n" " {\n" " gl_Position = vec4(2 * dst_position.x / u_viewport_size_px.x - 1,\n" " 2 * (1 - dst_position.y / u_viewport_size_px.y) - 1,\n" " 0.0, 1.0);\n" " v2p_sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * dst_half_size;\n" " v2p_texcoord_pct = src_position / u_tex_color_size;\n" " v2p_rect_half_size_px = dst_half_size;\n" " v2p_tint = color;\n" " v2p_corner_radius = corner_radius;\n" " v2p_border_thickness = c2v_style.x;\n" " v2p_softness = c2v_style.y;\n" " v2p_omit_texture = c2v_style.z;\n" " }\n" "}\n" "" ); read_only global String8 r_ogl_rect_pshad_src = str8_lit_comp( "" "\n" "#version 330 core\n" "\n" "in vec2 v2p_sdf_sample_pos;\n" "in vec2 v2p_texcoord_pct;\n" "in vec2 v2p_rect_half_size_px;\n" "in vec4 v2p_tint;\n" "in float v2p_corner_radius;\n" "in float v2p_border_thickness;\n" "in float v2p_softness;\n" "in float v2p_omit_texture;\n" "\n" "out vec4 final_color;\n" "\n" "uniform float u_opacity;\n" "uniform sampler2D u_tex_color;\n" "uniform mat4 u_texture_sample_channel_map;\n" "\n" "float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" "{\n" " return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" "}\n" "\n" "float linear_from_srgb_f32(float x)\n" "{\n" " return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4);\n" "}\n" "\n" "vec4 linear_from_srgba(vec4 v)\n" "{\n" " vec4 result = vec4(linear_from_srgb_f32(v.x),\n" " linear_from_srgb_f32(v.y),\n" " linear_from_srgb_f32(v.z),\n" " v.w);\n" " return result;\n" "}\n" "\n" "void main(void)\n" "{\n" " // rjf: sample texture\n" " vec4 albedo_sample = vec4(1, 1, 1, 1);\n" " if(v2p_omit_texture < 1)\n" " {\n" " albedo_sample = u_texture_sample_channel_map * texture(u_tex_color, v2p_texcoord_pct);\n" " albedo_sample = linear_from_srgba(albedo_sample);\n" " }\n" " \n" " // rjf: sample for borders\n" " float border_sdf_t = 1;\n" " if(v2p_border_thickness > 0)\n" " {\n" " float border_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" " v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f) - v2p_border_thickness,\n" " max(v2p_corner_radius-v2p_border_thickness, 0));\n" " border_sdf_t = smoothstep(0, 2*v2p_softness, border_sdf_s);\n" " }\n" " if(border_sdf_t < 0.001f)\n" " {\n" " discard;\n" " }\n" " \n" " // rjf: sample for corners\n" " float corner_sdf_t = 1;\n" " if(v2p_corner_radius > 0 || v2p_softness > 0.75f)\n" " {\n" " float corner_sdf_s = rect_sdf(v2p_sdf_sample_pos,\n" " v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f),\n" " v2p_corner_radius);\n" " corner_sdf_t = 1-smoothstep(0, 2*v2p_softness, corner_sdf_s);\n" " }\n" " \n" " // rjf: form+return final color\n" " final_color = albedo_sample;\n" " final_color *= v2p_tint;\n" " final_color.a *= u_opacity;\n" " final_color.a *= corner_sdf_t;\n" " final_color.a *= border_sdf_t;\n" "}\n" "" ); read_only global String8 r_ogl_blur_vshad_src = str8_lit_comp( "" "\n" "#version 330 core\n" "\n" "uniform vec4 rect;\n" "uniform vec4 corner_radii_px;\n" "uniform vec2 viewport_size;\n" "uniform uint blur_count;\n" "\n" "out vec2 texcoord;\n" "out vec2 sdf_sample_pos;\n" "out vec2 rect_half_size;\n" "out float corner_radius;\n" "\n" "void main(void)\n" "{\n" " vec2 vertex_positions_scrn[] = vec2[](rect.xw,\n" " rect.xy,\n" " rect.zw,\n" " rect.zy);\n" " float corner_radii_px[] = float[](corner_radii_px.y,\n" " corner_radii_px.x,\n" " corner_radii_px.w,\n" " corner_radii_px.z);\n" " vec2 cornercoords_pct = vec2((gl_VertexID >> 1) != 0 ? 1.f : 0.f,\n" " (gl_VertexID & 1) != 0 ? 0.f : 1.f);\n" " \n" " vec2 vertex_position_pct = vertex_positions_scrn[gl_VertexID] / viewport_size;\n" " vec2 vertex_position_scr = 2.f * vertex_position_pct - 1.f;\n" " \n" " vec2 rect_half_size = vec2((rect.z-rect.x)/2, (rect.w-rect.y)/2);\n" " \n" " gl_Position = vec4(vertex_position_scr.x, -vertex_position_scr.y, 0.f, 1.f);\n" " texcoord = vertex_position_pct;\n" " sdf_sample_pos = (2.f * cornercoords_pct - 1.f) * rect_half_size;\n" " rect_half_size = rect_half_size - 2.f;\n" " corner_radius = corner_radii_px[gl_VertexID];\n" "}\n" "" ); read_only global String8 r_ogl_blur_pshad_src = str8_lit_comp( "" "\n" "#version 330 core\n" "\n" "uniform sampler2D tex;\n" "uniform vec4 kernel[32];\n" "uniform int blur_count;\n" "uniform vec2 direction;\n" "\n" "in vec2 texcoord;\n" "in vec2 sdf_sample_pos;\n" "in vec2 rect_half_size;\n" "in float corner_radius;\n" "\n" "out vec4 final_color;\n" "\n" "float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r)\n" "{\n" " return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r;\n" "}\n" "\n" "void main(void)\n" "{\n" " // rjf: blend weighted texture samples into color\n" " vec3 color = kernel[0].x * texture(tex, texcoord).rgb;\n" " \n" " for(int i = 1; i < blur_count; i += 1)\n" " {\n" " float weight = kernel[i].x;\n" " float offset = kernel[i].y;\n" " color += weight * texture(tex, texcoord - offset * direction).rgb;\n" " color += weight * texture(tex, texcoord + offset * direction).rgb;\n" " }\n" " \n" " // rjf: sample for corners\n" " float corner_sdf_s = rect_sdf(sdf_sample_pos, rect_half_size, corner_radius);\n" " float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s);\n" " \n" " // rjf: weight output color by sdf\n" " // this is doing alpha testing, leave blurring only where mostly opaque pixels are\n" " if(corner_sdf_t < 0.9f)\n" " {\n" " discard;\n" " }\n" " \n" " final_color = vec4(color, 1.f);\n" "}\n" "" ); C_LINKAGE_END #endif // RENDER_OPENGL_META_H ================================================ FILE: src/render/opengl/linux/egl/render_opengl_linux_egl.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * r_ogl_os_load_procedure(char *name) { VoidProc *result = (VoidProc *)eglGetProcAddress(name); return result; } internal void r_ogl_os_init(CmdLine *cmdln) { //- rjf: set up state { Arena *arena = arena_alloc(); r_ogl_lnx_state = push_array(arena, R_OGL_LNX_State, 1); r_ogl_lnx_state->arena = arena; } //- rjf: get EGL display { r_ogl_lnx_state->display = eglGetDisplay((EGLNativeDisplayType)os_lnx_gfx_state->display); if(r_ogl_lnx_state->display == EGL_NO_DISPLAY) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Failed to get EGL display.")); os_abort(1); } } //- rjf: initialize GL version EGLint egl_version_major = 0; EGLint egl_version_minor = 0; if(!eglInitialize(r_ogl_lnx_state->display, &egl_version_major, &egl_version_minor)) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't initialize EGL display.")); os_abort(1); } if(egl_version_major < 1 || (egl_version_major == 1 && egl_version_minor < 5)) { Temp scratch = scratch_begin(0, 0); String8 message = push_str8f(scratch.arena, "Unsupported EGL version (%i.%i, need at least 1.5)", egl_version_major, egl_version_minor); os_graphical_message(1, str8_lit("Fatal Error"), message); os_abort(1); scratch_end(scratch); } //- rjf: pick GL API if(!eglBindAPI(EGL_OPENGL_API)) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't initialize EGL API to OpenGL.")); os_abort(1); } //- rjf: construct context { B32 debug_mode = cmd_line_has_flag(cmdln, str8_lit("opengl_debug")); #if BUILD_DEBUG debug_mode = 1; #endif EGLint options[] = { EGL_CONTEXT_MAJOR_VERSION, 3, EGL_CONTEXT_MINOR_VERSION, 3, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, debug_mode ? EGL_CONTEXT_OPENGL_DEBUG : EGL_NONE, EGL_TRUE, EGL_NONE, }; r_ogl_lnx_state->context = eglCreateContext(r_ogl_lnx_state->display, 0, EGL_NO_CONTEXT, options); if(r_ogl_lnx_state->context == EGL_NO_CONTEXT) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't create OpenGL context with EGL.")); os_abort(1); } } eglMakeCurrent(r_ogl_lnx_state->display, 0, 0, r_ogl_lnx_state->context); glDrawBuffer(GL_BACK); } internal R_Handle r_ogl_os_window_equip(OS_Handle window) { OS_LNX_Window *window_os = (OS_LNX_Window *)window.u64[0]; R_OGL_LNX_Window *w = r_ogl_lnx_state->free_window; if(w != 0) { SLLStackPop(r_ogl_lnx_state->free_window); } else { w = push_array(r_ogl_lnx_state->arena, R_OGL_LNX_Window, 1); } { EGLint surface_options[] = { EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB, EGL_NONE, }; if(r_ogl_lnx_state->config == 0) { //- rjf: get all EGL configs EGLConfig configs[256] = {0}; EGLint configs_count = 0; { EGLint options[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_CONFORMANT, EGL_OPENGL_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8, EGL_NONE, }; if(!eglChooseConfig(r_ogl_lnx_state->display, options, configs, ArrayCount(configs), &configs_count) || configs_count == 0) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't choose EGL configuration.")); os_abort(1); } } //- rjf: actually choose the egl config { EGLint config_options[] = { EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB, EGL_NONE, }; for(U32 idx = 0; idx < configs_count; idx += 1) { w->surface = eglCreateWindowSurface(r_ogl_lnx_state->display, configs[idx], window_os->window, config_options); if(w->surface != EGL_NO_SURFACE) { r_ogl_lnx_state->config = configs[idx]; break; } } if(r_ogl_lnx_state->config == 0) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't find a suitable EGL configuration.")); os_abort(1); } } } else { w->surface = eglCreateWindowSurface(r_ogl_lnx_state->display, r_ogl_lnx_state->config, window_os->window, surface_options); } if(w->surface == EGL_NO_SURFACE) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Couldn't create EGL surface.")); os_abort(1); } } R_Handle result = {(U64)w}; return result; } internal void r_ogl_os_window_unequip(OS_Handle os, R_Handle r) { R_OGL_LNX_Window *w = (R_OGL_LNX_Window *)r.u64[0]; { } SLLStackPush(r_ogl_lnx_state->free_window, w); } internal void r_ogl_os_select_window(OS_Handle os, R_Handle r) { OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0]; R_OGL_LNX_Window *w_r = (R_OGL_LNX_Window *)r.u64[0]; eglMakeCurrent(r_ogl_lnx_state->display, w_r->surface, w_r->surface, r_ogl_lnx_state->context); } internal void r_ogl_os_window_swap(OS_Handle os, R_Handle r) { OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0]; R_OGL_LNX_Window *w_r = (R_OGL_LNX_Window *)r.u64[0]; eglSwapBuffers(r_ogl_lnx_state->display, w_r->surface); } ================================================ FILE: src/render/opengl/linux/egl/render_opengl_linux_egl.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_EGL_H #define RENDER_OPENGL_LINUX_EGL_H #define glTexImage3D glTexImage3D__static #define glTexSubImage3D glTexSubImage3D__static #define glActiveTexture glActiveTexture__static #include #include #undef glTexImage3D #undef glTexSubImage3D #undef glActiveTexture typedef struct R_OGL_LNX_Window R_OGL_LNX_Window; struct R_OGL_LNX_Window { R_OGL_LNX_Window *next; EGLSurface *surface; }; typedef struct R_OGL_LNX_State R_OGL_LNX_State; struct R_OGL_LNX_State { Arena *arena; EGLDisplay *display; EGLConfig config; EGLContext *context; R_OGL_LNX_Window *free_window; }; global R_OGL_LNX_State *r_ogl_lnx_state = 0; #endif // RENDER_OPENGL_LINUX_EGL_H ================================================ FILE: src/render/opengl/linux/glx/render_opengl_linux_glx.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * r_ogl_os_load_procedure(char *name) { VoidProc *result = (VoidProc *)glXGetProcAddressARB((U8 *)name); return result; } internal void r_ogl_os_init(CmdLine *cmdln) { //- rjf: require GLX 1.3+ int glx_version_major = 0; int glx_version_minor = 0; if(!glXQueryVersion(os_lnx_gfx_state->display, &glx_version_major, &glx_version_minor) || (glx_version_major == 1 && glx_version_minor < 3) || glx_version_major < 1) { Temp scratch = scratch_begin(0, 0); String8 message = push_str8f(scratch.arena, "Unsupported GLX version (%i.%i, need at least 1.3)", glx_version_major, glx_version_minor); os_graphical_message(1, str8_lit("Fatal Error"), message); os_abort(1); scratch_end(scratch); } //- rjf: get frame buffer configs local_persist int framebuffer_config_options[] = { GLX_X_RENDERABLE, 1, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_DOUBLEBUFFER, 1, None }; int framebuffer_configs_count = 0; GLXFBConfig *framebuffer_configs = glXChooseFBConfig(os_lnx_gfx_state->display, DefaultScreen(os_lnx_gfx_state->display), framebuffer_config_options, &framebuffer_configs_count); if(framebuffer_configs == 0) { os_graphical_message(1, str8_lit("Fatal Error"), str8_lit("Could not find a suitable framebuffer configuration.")); os_abort(1); } GLXFBConfig framebuffer_config = framebuffer_configs[0]; XFree(framebuffer_configs); //- rjf: construct set-window-attributes XSetWindowAttributes set_window_attributes = {0}; set_window_attributes.background_pixmap = None; set_window_attributes.border_pixel = 0; set_window_attributes.event_mask = StructureNotifyMask; //- rjf: construct context { B32 debug_mode = cmd_line_has_flag(cmdln, str8_lit("opengl_debug")); #if BUILD_DEBUG debug_mode = 1; #endif glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((U8 *)"glXCreateContextAttribsARB"); int context_options[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3, GLX_CONTEXT_FLAGS_ARB, !!debug_mode*GLX_CONTEXT_DEBUG_BIT_ARB, None }; r_ogl_lnx_ctx = glXCreateContextAttribsARB(os_lnx_gfx_state->display, framebuffer_config, 0, 1, context_options); } glXMakeCurrent(os_lnx_gfx_state->display, 0, r_ogl_lnx_ctx); } internal R_Handle r_ogl_os_window_equip(OS_Handle window) { R_Handle result = {0}; return result; } internal void r_ogl_os_window_unequip(OS_Handle os, R_Handle r) { } internal void r_ogl_os_select_window(OS_Handle os, R_Handle r) { OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0]; glXMakeCurrent(os_lnx_gfx_state->display, w->window, r_ogl_lnx_ctx); } internal void r_ogl_os_window_swap(OS_Handle os, R_Handle r) { OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0]; glXSwapBuffers(os_lnx_gfx_state->display, w->window); } ================================================ FILE: src/render/opengl/linux/glx/render_opengl_linux_glx.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_GLX_H #define RENDER_OPENGL_LINUX_GLX_H #define glTexImage3D glTexImage3D__static #define glTexSubImage3D glTexSubImage3D__static #define glActiveTexture glActiveTexture__static #include #include #undef glTexImage3D #undef glTexSubImage3D #undef glActiveTexture #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 #define GLX_CONTEXT_FLAGS_ARB 0x2094 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); global GLXContext r_ogl_lnx_ctx = 0; #endif // RENDER_OPENGL_LINUX_GLX_H ================================================ FILE: src/render/opengl/linux/render_opengl_linux.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Backend Includes #if R_OPENGL_LINUX_BACKEND == R_OPENGL_LINUX_BACKEND_GLX # include "glx/render_opengl_linux_glx.c" #elif R_OPENGL_LINUX_BACKEND == R_OPENGL_LINUX_BACKEND_EGL # include "egl/render_opengl_linux_egl.c" #else # error Linux OpenGL backend not specified. #endif ================================================ FILE: src/render/opengl/linux/render_opengl_linux.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_H #define RENDER_OPENGL_LINUX_H //////////////////////////////// //~ rjf: Backend Constants #define R_OPENGL_LINUX_BACKEND_GLX 0 #define R_OPENGL_LINUX_BACKEND_EGL 1 //////////////////////////////// //~ rjf: Decide On Backend #if !defined(R_OPENGL_LINUX_BACKEND) # define R_OPENGL_LINUX_BACKEND R_OPENGL_LINUX_BACKEND_EGL #endif //////////////////////////////// //~ rjf: Backend Includes #if R_OPENGL_LINUX_BACKEND == R_OPENGL_LINUX_BACKEND_GLX # include "glx/render_opengl_linux_glx.h" #elif R_OPENGL_LINUX_BACKEND == R_OPENGL_LINUX_BACKEND_EGL # include "egl/render_opengl_linux_egl.h" #else # error Linux OpenGL backend not specified. #endif #endif // RENDER_OPENGL_LINUX_H ================================================ FILE: src/render/opengl/render_opengl.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: OS Portion Includes #if OS_WINDOWS # include "render/opengl/win32/render_opengl_win32.c" #elif OS_LINUX # include "render/opengl/linux/render_opengl_linux.c" #else # error OS portion of OpenGL rendering backend not defined. #endif //////////////////////////////// //~ rjf: Attribute Tables global read_only R_OGL_Attribute r_ogl_rect_input_attributes[] = { {0, str8_lit_comp("c2v_dst_rect"), GL_FLOAT, 4}, {1, str8_lit_comp("c2v_src_rect"), GL_FLOAT, 4}, {2, str8_lit_comp("c2v_colors_0"), GL_FLOAT, 4}, {3, str8_lit_comp("c2v_colors_1"), GL_FLOAT, 4}, {4, str8_lit_comp("c2v_colors_2"), GL_FLOAT, 4}, {5, str8_lit_comp("c2v_colors_3"), GL_FLOAT, 4}, {6, str8_lit_comp("c2v_corner_radii"), GL_FLOAT, 4}, {7, str8_lit_comp("c2v_style"), GL_FLOAT, 4}, }; global read_only R_OGL_Attribute r_ogl_single_color_output_attributes[] = { {0, str8_lit_comp("final_color")}, }; //////////////////////////////// //~ rjf: Generated Code #include "render/opengl/generated/render_opengl.meta.c" //////////////////////////////// //~ rjf: Helpers internal R_Handle r_ogl_handle_from_tex2d(R_OGL_Tex2D *t) { R_Handle h = {(U64)t}; return h; } internal R_OGL_Tex2D * r_ogl_tex2d_from_handle(R_Handle h) { R_OGL_Tex2D *t = (R_OGL_Tex2D *)h.u64[0]; return t; } internal R_OGL_FormatInfo r_ogl_format_info_from_tex2dformat(R_Tex2DFormat fmt) { R_OGL_FormatInfo result; result.internal_format = GL_RGBA; result.format = GL_RGBA; result.base_type = GL_UNSIGNED_BYTE; // TODO(rjf) return result; } internal GLuint r_ogl_instance_buffer_from_size(U64 size) { GLuint buffer = r_ogl_state->scratch_buffer_64kb; if(size > KB(64)) { // rjf: build buffer U64 flushed_buffer_size = size; flushed_buffer_size += MB(1)-1; flushed_buffer_size -= flushed_buffer_size%MB(1); glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, flushed_buffer_size, 0, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // rjf: push buffer to flush list R_OGL_FlushBuffer *n = push_array(r_ogl_state->buffer_flush_arena, R_OGL_FlushBuffer, 1); n->id = buffer; SLLQueuePush(r_ogl_state->first_buffer_to_flush, r_ogl_state->last_buffer_to_flush, n); } return buffer; } internal void r_ogl_debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) { raddbg_log("[OpenGL] %.*s\n", (int)length, message); fprintf(stderr, "[OpenGL] %.*s\n", (int)length, message); } //////////////////////////////// //~ rjf: Backend Hooks //- rjf: top-level layer initialization r_hook void r_init(CmdLine *cmdln) { //- rjf: do os-specific portion of work r_ogl_os_init(cmdln); //- rjf: top-level initialization Arena *arena = arena_alloc(); r_ogl_state = push_array(arena, R_OGL_State, 1); r_ogl_state->arena = arena; //- rjf: load gl procedures #define X(name, r, p) name = (name##_FunctionType *)r_ogl_os_load_procedure(#name); R_OGL_ProcedureXList #undef X //- rjf: build all shaders for EachEnumVal(R_OGL_ShaderKind, k) { // rjf: compile struct {GLenum type; String8 *src; GLuint out; String8 errors;} stages[] = { {GL_VERTEX_SHADER, r_ogl_shader_kind_vshad_src_table[k]}, {GL_FRAGMENT_SHADER, r_ogl_shader_kind_pshad_src_table[k]}, }; for EachElement(idx, stages) { stages[idx].out = glCreateShader(stages[idx].type); GLint src_size = stages[idx].src->size; glShaderSource(stages[idx].out, 1, (char **)&stages[idx].src->str, &src_size); glCompileShader(stages[idx].out); GLint info_log_length = 0; GLint status = 0; glGetShaderiv(stages[idx].out, GL_COMPILE_STATUS, &status); glGetShaderiv(stages[idx].out, GL_INFO_LOG_LENGTH, &info_log_length); if(info_log_length != 0) { stages[idx].errors.str = push_array(r_ogl_state->arena, U8, info_log_length+1); stages[idx].errors.size = info_log_length; glGetShaderInfoLog(stages[idx].out, info_log_length, 0, (char *)stages[idx].errors.str); } raddbg_pin(text(stages[idx].errors.str)); } // rjf: attach compilations to program GLuint program = glCreateProgram(); for EachElement(idx, stages) { glAttachShader(program, stages[idx].out); } // rjf: bind inputs R_OGL_AttributeArray inputs = r_ogl_shader_kind_input_attributes_table[k]; for EachIndex(idx, inputs.count) { glBindAttribLocation(program, inputs.v[idx].index, (char *)inputs.v[idx].name.str); } // rjf: bind outputs R_OGL_AttributeArray outputs = r_ogl_shader_kind_output_attributes_table[k]; for EachIndex(idx, outputs.count) { glBindFragDataLocation(program, outputs.v[idx].index, (char *)outputs.v[idx].name.str); } // rjf: link / validate / store glLinkProgram(program); glValidateProgram(program); r_ogl_state->shaders[k] = program; } //- rjf: set up built-in resources glGenVertexArrays(1, &r_ogl_state->all_purpose_vao); glGenBuffers(1, &r_ogl_state->scratch_buffer_64kb); glBindBuffer(GL_ARRAY_BUFFER, r_ogl_state->scratch_buffer_64kb); glBufferData(GL_ARRAY_BUFFER, KB(64), 0, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenTextures(1, &r_ogl_state->white_texture); glBindTexture(GL_TEXTURE_2D, r_ogl_state->white_texture); U32 white_pixel = 0xffffffff; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &white_pixel); glEnable(GL_FRAMEBUFFER_SRGB); //- rjf: set up buffer flush state r_ogl_state->buffer_flush_arena = arena_alloc(); //- rjf: set up debug callback B32 debug_mode = cmd_line_has_flag(cmdln, str8_lit("opengl_debug")); #if BUILD_DEBUG debug_mode = 1; #endif if(debug_mode) { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallback(r_ogl_debug_message_callback, 0); } } //- rjf: window setup/teardown r_hook R_Handle r_window_equip(OS_Handle window) { R_Handle result = r_ogl_os_window_equip(window); return result; } r_hook void r_window_unequip(OS_Handle window, R_Handle window_equip) { r_ogl_os_window_unequip(window, window_equip); } //- rjf: textures r_hook R_Handle r_tex2d_alloc(R_ResourceKind kind, Vec2S32 size, R_Tex2DFormat format, void *data) { //- rjf: allocate texture record R_OGL_Tex2D *tex2d = r_ogl_state->free_tex2d; if(tex2d) { SLLStackPop(r_ogl_state->free_tex2d); } else { tex2d = push_array(r_ogl_state->arena, R_OGL_Tex2D, 1); } //- rjf: map kind/format -> gl counterparts R_OGL_FormatInfo gl_fmt_info = r_ogl_format_info_from_tex2dformat(format); //- rjf: allocate GL texture { glGenTextures(1, &tex2d->id); glBindTexture(GL_TEXTURE_2D, tex2d->id); glTexImage2D(GL_TEXTURE_2D, 0, gl_fmt_info.internal_format, size.x, size.y, 0, gl_fmt_info.format, gl_fmt_info.base_type, data); glBindTexture(GL_TEXTURE_2D, 0); } //- rjf: fill tex2d->resource_kind = kind; tex2d->fmt = format; tex2d->size = size; //- rjf: bundle & return R_Handle result = r_ogl_handle_from_tex2d(tex2d); return result; } r_hook void r_tex2d_release(R_Handle texture) { R_OGL_Tex2D *t = r_ogl_tex2d_from_handle(texture); if(t != 0) { glDeleteTextures(1, &t->id); SLLStackPush(r_ogl_state->free_tex2d, t); } } r_hook R_ResourceKind r_kind_from_tex2d(R_Handle texture) { R_ResourceKind result = R_ResourceKind_Static; R_OGL_Tex2D *t = r_ogl_tex2d_from_handle(texture); if(t) { result = t->resource_kind; } return result; } r_hook Vec2S32 r_size_from_tex2d(R_Handle texture) { Vec2S32 result = {0, 0}; R_OGL_Tex2D *t = r_ogl_tex2d_from_handle(texture); if(t) { result = t->size; } return result; } r_hook R_Tex2DFormat r_format_from_tex2d(R_Handle texture) { R_Tex2DFormat result = R_Tex2DFormat_RGBA8; R_OGL_Tex2D *t = r_ogl_tex2d_from_handle(texture); if(t) { result = t->fmt; } return result; } r_hook void r_fill_tex2d_region(R_Handle texture, Rng2S32 subrect, void *data) { R_OGL_Tex2D *t = r_ogl_tex2d_from_handle(texture); if(t) { R_OGL_FormatInfo fmt_info = r_ogl_format_info_from_tex2dformat(t->fmt); glBindTexture(GL_TEXTURE_2D, t->id); Vec2S32 rect_size = dim_2s32(subrect); glTexSubImage2D(GL_TEXTURE_2D, 0, subrect.x0, subrect.y0, rect_size.x, rect_size.y, fmt_info.format, fmt_info.base_type, data); glBindTexture(GL_TEXTURE_2D, 0); } } //- rjf: buffers r_hook R_Handle r_buffer_alloc(R_ResourceKind kind, U64 size, void *data) { R_Handle result = {0}; return result; } r_hook void r_buffer_release(R_Handle buffer) { // TODO(rjf) } //- rjf: frame markers r_hook void r_begin_frame(void) { // TODO(rjf) } r_hook void r_end_frame(void) { // TODO(rjf) } r_hook void r_window_begin_frame(OS_Handle os, R_Handle r) { r_ogl_os_select_window(os, r); //- rjf: unpack window viewport info Rng2F32 client_rect = os_client_rect_from_window(os); Vec2F32 client_rect_dim = dim_2f32(client_rect); //- rjf: clear and reset state glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, (S32)client_rect_dim.x, (S32)client_rect_dim.y); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } r_hook void r_window_end_frame(OS_Handle os, R_Handle r) { for(R_OGL_FlushBuffer *flush_buffer = r_ogl_state->first_buffer_to_flush; flush_buffer != 0; flush_buffer = flush_buffer->next) { glDeleteBuffers(1, &flush_buffer->id); } arena_clear(r_ogl_state->buffer_flush_arena); r_ogl_state->first_buffer_to_flush = r_ogl_state->last_buffer_to_flush = 0; r_ogl_os_window_swap(os, r); } //- rjf: render pass submission r_hook void r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes) { Rng2F32 viewport_rect = os_client_rect_from_window(window); Vec2F32 viewport_dim = dim_2f32(viewport_rect); for(R_PassNode *pass_n = passes->first; pass_n != 0; pass_n = pass_n->next) { R_Pass *pass = &pass_n->v; switch(pass->kind) { default:{}break; //////////////////////// //- rjf: ui rendering pass // case R_PassKind_UI: { //- rjf: unpack params R_PassParams_UI *params = pass->params_ui; R_BatchGroup2DList *rect_batch_groups = ¶ms->rects; //- rjf: draw each batch group GLuint shader = r_ogl_state->shaders[R_OGL_ShaderKind_Rect]; glBindVertexArrayScope(r_ogl_state->all_purpose_vao) glUseProgramScope(shader) { for(R_BatchGroup2DNode *group_n = rect_batch_groups->first; group_n != 0; group_n = group_n->next) { R_BatchList *batches = &group_n->batches; R_BatchGroup2DParams *group_params = &group_n->params; //- rjf: unpack texture R_Tex2DFormat texture_fmt = R_Tex2DFormat_RGBA8; GLuint texture_id = r_ogl_state->white_texture; { R_OGL_Tex2D *tex = r_ogl_tex2d_from_handle(group_params->tex); if(tex != 0) { texture_id = tex->id; texture_fmt = tex->fmt; } } //- rjf: get & fill buffer GLuint buffer = r_ogl_instance_buffer_from_size(batches->byte_count); { glBindBuffer(GL_ARRAY_BUFFER, buffer); U64 off = 0; for(R_BatchNode *batch_n = batches->first; batch_n != 0; batch_n = batch_n->next) { glBufferSubData(GL_ARRAY_BUFFER, off, batch_n->v.byte_count, batch_n->v.v); off += batch_n->v.byte_count; } } //- rjf: bind input attributes { R_OGL_AttributeArray inputs = r_ogl_shader_kind_input_attributes_table[R_OGL_ShaderKind_Rect]; U64 off = 0; for EachIndex(idx, inputs.count) { glEnableVertexAttribArray(inputs.v[idx].index); glVertexAttribDivisor(inputs.v[idx].index, 1); glVertexAttribPointer(inputs.v[idx].index, inputs.v[idx].count, inputs.v[idx].type, GL_FALSE, sizeof(R_Rect2DInst), (void *)(off)); // TODO(rjf): this is not correct if type != GL_FLOAT off += inputs.v[idx].count*sizeof(F32); } } //- rjf: bind texture { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); switch(group_params->tex_sample_kind) { default: case R_Tex2DSampleKind_Nearest: { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); }break; case R_Tex2DSampleKind_Linear: { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }break; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glUniform1i(glGetUniformLocation(shader, "u_tex_color"), 0); } //- rjf: upload misc. uniforms { Mat4x4F32 texture_sample_channel_map = r_sample_channel_map_from_tex2dformat(texture_fmt); glUniformMatrix4fv(glGetUniformLocation(shader, "u_texture_sample_channel_map"), 1, 0, &texture_sample_channel_map.v[0][0]); glUniform2f(glGetUniformLocation(shader, "u_viewport_size_px"), viewport_dim.x, viewport_dim.y); glUniform1f(glGetUniformLocation(shader, "u_opacity"), 1.f - group_params->transparency); } //- rjf: set up scissor if(group_params->clip.x0 != 0 || group_params->clip.x1 != 0 || group_params->clip.y0 != 0 || group_params->clip.y1 != 0) { Rng2F32 clip = group_params->clip; glScissor(clip.x0, viewport_dim.y - clip.y1, (clip.x1-clip.x0) + 1, (clip.y1-clip.y0)+1); glEnable(GL_SCISSOR_TEST); } //- rjf: draw { glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, batches->byte_count / batches->bytes_per_inst); } //- rjf: unset scissor glDisable(GL_SCISSOR_TEST); } } }break; //////////////////////// //- rjf: blur rendering pass // case R_PassKind_Blur: { R_PassParams_Blur *params = pass->params_blur; GLuint shader = r_ogl_state->shaders[R_OGL_ShaderKind_Blur]; // TODO(rjf): glBindVertexArrayScope(r_ogl_state->all_purpose_vao) glUseProgramScope(shader) { // TODO(rjf) } }break; //////////////////////// //- rjf: 3d geometry rendering pass // case R_PassKind_Geo3D: { //- rjf: unpack params R_PassParams_Geo3D *params = pass->params_geo3d; R_BatchGroup3DMap *mesh_group_map = ¶ms->mesh_batches; // TODO(rjf) }break; } } } ================================================ FILE: src/render/opengl/render_opengl.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_H #define RENDER_OPENGL_H //////////////////////////////// //~ rjf: Defines typedef char GLchar; typedef ptrdiff_t GLsizeiptr; typedef ptrdiff_t GLintptr; #define GL_FRAMEBUFFER_SRGB 0x8DB9 #define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_R8 0x8229 #define GL_ARRAY_BUFFER 0x8892 #define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_READ 0x88E1 #define GL_STREAM_COPY 0x88E2 #define GL_STATIC_DRAW 0x88E4 #define GL_STATIC_READ 0x88E5 #define GL_STATIC_COPY 0x88E6 #define GL_DYNAMIC_DRAW 0x88E8 #define GL_DYNAMIC_READ 0x88E9 #define GL_DYNAMIC_COPY 0x88EA #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_TESS_EVALUATION_SHADER 0x8E87 #define GL_TESS_CONTROL_SHADER 0x8E88 #define GL_INFO_LOG_LENGTH 0x8B84 #define GL_TEXTURE_2D_ARRAY 0x8C1A #define GL_COMPILE_STATUS 0x8B81 #define GL_TEXTURE0 0x84C0 #define GL_TEXTURE1 0x84C1 #define GL_TEXTURE2 0x84C2 #define GL_TEXTURE3 0x84C3 #define GL_TEXTURE4 0x84C4 #define GL_TEXTURE5 0x84C5 #define GL_TEXTURE6 0x84C6 #define GL_TEXTURE7 0x84C7 #define GL_TEXTURE8 0x84C8 #define GL_TEXTURE9 0x84C9 #define GL_TEXTURE10 0x84CA #define GL_TEXTURE11 0x84CB #define GL_TEXTURE12 0x84CC #define GL_TEXTURE13 0x84CD #define GL_TEXTURE14 0x84CE #define GL_TEXTURE15 0x84CF #define GL_TEXTURE16 0x84D0 #define GL_TEXTURE17 0x84D1 #define GL_TEXTURE18 0x84D2 #define GL_TEXTURE19 0x84D3 #define GL_TEXTURE20 0x84D4 #define GL_TEXTURE21 0x84D5 #define GL_TEXTURE22 0x84D6 #define GL_TEXTURE23 0x84D7 #define GL_TEXTURE24 0x84D8 #define GL_TEXTURE25 0x84D9 #define GL_TEXTURE26 0x84DA #define GL_TEXTURE27 0x84DB #define GL_TEXTURE28 0x84DC #define GL_TEXTURE29 0x84DD #define GL_TEXTURE30 0x84DE #define GL_TEXTURE31 0x84DF #define GL_DEBUG_OUTPUT 0x92E0 #define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 //////////////////////////////// //~ rjf: OS Backend Includes #if OS_WINDOWS # include "render/opengl/win32/render_opengl_win32.h" #elif OS_LINUX # include "render/opengl/linux/render_opengl_linux.h" #else # error OS portion of OpenGL rendering backend not defined. #endif //////////////////////////////// //~ rjf: Shader Metadata Types typedef struct R_OGL_Attribute R_OGL_Attribute; struct R_OGL_Attribute { U64 index; String8 name; GLenum type; U64 count; }; typedef struct R_OGL_AttributeArray R_OGL_AttributeArray; struct R_OGL_AttributeArray { R_OGL_Attribute *v; U64 count; }; //////////////////////////////// //~ rjf: Generated Code #include "render/opengl/generated/render_opengl.meta.h" //////////////////////////////// //~ rjf: OpenGL Procedure List #define R_OGL_ProcedureXList \ X(glGenBuffers, void, (GLsizei n, GLuint *buffers))\ X(glBindBuffer, void, (GLenum target, GLuint buffer))\ X(glDeleteBuffers, void, (GLsizei n, GLuint *buffers))\ X(glGenVertexArrays, void, (GLsizei n, GLuint *arrays))\ X(glBindVertexArray, void, (GLuint array))\ X(glCreateProgram, GLuint, (void))\ X(glCreateShader, GLuint, (GLenum type))\ X(glShaderSource, void, (GLuint shader, GLsizei count, char **string, GLint *length))\ X(glCompileShader, void, (GLuint shader))\ X(glGetShaderiv, void, (GLuint shader, GLenum pname, GLint *params))\ X(glGetShaderInfoLog, void, (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog))\ X(glGetProgramiv, void, (GLuint program, GLenum pname, GLint *params))\ X(glGetProgramInfoLog, void, (GLuint program, GLsizei bufSize, GLsizei *length, char *infoLog))\ X(glAttachShader, void, (GLuint program, GLuint shader))\ X(glLinkProgram, void, (GLuint program))\ X(glValidateProgram, void, (GLuint program))\ X(glDeleteShader, void, (GLuint shader))\ X(glUseProgram, void, (GLuint program))\ X(glGetUniformLocation, GLint, (GLuint program, char *name))\ X(glGetAttribLocation, GLint, (GLuint program, char *name))\ X(glEnableVertexAttribArray, void, (GLuint index))\ X(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer))\ X(glBufferData, void, (GLenum target, ptrdiff_t size, void *data, GLenum usage))\ X(glBufferSubData, void, (GLenum target, ptrdiff_t offset, ptrdiff_t size, const void *data))\ X(glBlendFuncSeparate, void, (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha))\ X(glUniform1f, void, (GLint location, GLfloat v0))\ X(glUniform2f, void, (GLint location, GLfloat v0, GLfloat v1))\ X(glUniform3f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2))\ X(glUniform4f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3))\ X(glUniformMatrix4fv, void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value))\ X(glUniform1i, void, (GLint location, GLint v0))\ X(glTexImage3D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels))\ X(glTexSubImage3D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels))\ X(glGenerateMipmap, void, (GLenum target))\ X(glBindAttribLocation, void, (GLuint programObj, GLuint index, char *name))\ X(glBindFragDataLocation, void, (GLuint program, GLuint color, char *name))\ X(glActiveTexture, void, (GLenum texture))\ X(glVertexAttribDivisor, void, (GLuint index, GLuint divisor))\ X(glDrawArraysInstanced, void, (GLenum mode, GLint first, GLsizei count, GLsizei instancecount))\ X(glDebugMessageCallback, void, (void (*)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam), void *user_data))\ #define X(name, r, p) typedef r name##_FunctionType p; R_OGL_ProcedureXList #undef X #define X(name, r, p) global name##_FunctionType *name = 0; R_OGL_ProcedureXList #undef X //////////////////////////////// //~ rjf: State Types typedef struct R_OGL_FormatInfo R_OGL_FormatInfo; struct R_OGL_FormatInfo { GLint internal_format; GLenum format; GLenum base_type; }; typedef struct R_OGL_Tex2D R_OGL_Tex2D; struct R_OGL_Tex2D { R_OGL_Tex2D *next; GLuint id; R_ResourceKind resource_kind; R_Tex2DFormat fmt; Vec2S32 size; }; typedef struct R_OGL_FlushBuffer R_OGL_FlushBuffer; struct R_OGL_FlushBuffer { R_OGL_FlushBuffer *next; GLuint id; }; typedef struct R_OGL_State R_OGL_State; struct R_OGL_State { Arena *arena; R_OGL_Tex2D *free_tex2d; GLuint shaders[R_OGL_ShaderKind_COUNT]; GLuint all_purpose_vao; GLuint scratch_buffer_64kb; GLuint white_texture; Arena *buffer_flush_arena; R_OGL_FlushBuffer *first_buffer_to_flush; R_OGL_FlushBuffer *last_buffer_to_flush; }; //////////////////////////////// //~ rjf: Globals global R_OGL_State *r_ogl_state = 0; //////////////////////////////// //~ rjf: Helpers internal R_Handle r_ogl_handle_from_tex2d(R_OGL_Tex2D *t); internal R_OGL_Tex2D *r_ogl_tex2d_from_handle(R_Handle h); internal R_OGL_FormatInfo r_ogl_format_info_from_tex2dformat(R_Tex2DFormat fmt); internal GLuint r_ogl_instance_buffer_from_size(U64 size); internal void r_ogl_debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam); #define glUseProgramScope(...) DeferLoop(glUseProgram(__VA_ARGS__), glUseProgram(0)) #define glBindVertexArrayScope(...) DeferLoop(glBindVertexArray(__VA_ARGS__), glBindVertexArray(0)) //////////////////////////////// //~ rjf: OS-Specific Hooks internal VoidProc *r_ogl_os_load_procedure(char *name); internal void r_ogl_os_init(CmdLine *cmdln); internal R_Handle r_ogl_os_window_equip(OS_Handle window); internal void r_ogl_os_window_unequip(OS_Handle os, R_Handle r); internal void r_ogl_os_select_window(OS_Handle os, R_Handle r); internal void r_ogl_os_window_swap(OS_Handle os, R_Handle r); #endif // RENDER_OPENGL_H ================================================ FILE: src/render/opengl/render_opengl.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Shader Table @table(name name_lower input_atts output_atts) R_OGL_ShaderTable: { {Rect rect r_ogl_rect_input_attributes r_ogl_single_color_output_attributes} {Blur blur 0 r_ogl_single_color_output_attributes} } @enum R_OGL_ShaderKind: { @expand(R_OGL_ShaderTable a) `$(a.name)`, COUNT } @data(String8) r_ogl_shader_kind_name_table: { @expand(R_OGL_ShaderTable a) `str8_lit_comp("$(a.name_lower)")`, } @data(`String8 *`) r_ogl_shader_kind_vshad_src_table: { @expand(R_OGL_ShaderTable a) `&r_ogl_$(a.name_lower)_vshad_src`, } @data(`String8 *`) r_ogl_shader_kind_pshad_src_table: { @expand(R_OGL_ShaderTable a) `&r_ogl_$(a.name_lower)_pshad_src`, } @data(R_OGL_AttributeArray) r_ogl_shader_kind_input_attributes_table: { @expand(R_OGL_ShaderTable a) `{ $(a.input_atts), $(a.input_atts != 0 -> "ArrayCount(" .. a.input_atts .. ")") }`, } @data(R_OGL_AttributeArray) r_ogl_shader_kind_output_attributes_table: { @expand(R_OGL_ShaderTable a) `{ $(a.output_atts), ArrayCount($(a.output_atts)) }`, } //////////////////////////////// //~ rjf: UI Rectangle Shaders //- rjf: vertex @embed_string r_ogl_rect_vshad_src: ``` #version 330 core in vec4 c2v_dst_rect; in vec4 c2v_src_rect; in vec4 c2v_colors_0; in vec4 c2v_colors_1; in vec4 c2v_colors_2; in vec4 c2v_colors_3; in vec4 c2v_corner_radii; in vec4 c2v_style; // x: border_thickness_px, y: softness_px, z: omit_texture, w: shear out vec2 v2p_sdf_sample_pos; out vec2 v2p_texcoord_pct; out vec2 v2p_rect_half_size_px; out vec4 v2p_tint; out float v2p_corner_radius; out float v2p_border_thickness; out float v2p_softness; out float v2p_omit_texture; uniform sampler2D u_tex_color; uniform vec2 u_viewport_size_px; void main(void) { // rjf: constants vec2 vertices[] = vec2[](vec2(-1, -1), vec2(-1, +1), vec2(+1, -1), vec2(+1, +1)); // rjf: unpack shears float shears[] = float[](0, 0, c2v_style.w, c2v_style.w); // rjf: find dst position vec2 dst_half_size = (c2v_dst_rect.zw - c2v_dst_rect.xy) / 2; vec2 dst_center = (c2v_dst_rect.zw + c2v_dst_rect.xy) / 2; vec2 dst_position = vertices[gl_VertexID] * dst_half_size + dst_center; dst_position.y += shears[gl_VertexID]; // rjf: find src position vec2 src_half_size = (c2v_src_rect.zw - c2v_src_rect.xy) / 2; vec2 src_center = (c2v_src_rect.zw + c2v_src_rect.xy) / 2; vec2 src_position = vertices[gl_VertexID] * src_half_size + src_center; // rjf: find color vec4 colors[] = vec4[](c2v_colors_0, c2v_colors_1, c2v_colors_2, c2v_colors_3); vec4 color = colors[gl_VertexID]; // rjf: find corner radius float corner_radii[] = float[](c2v_corner_radii.x, c2v_corner_radii.y, c2v_corner_radii.z, c2v_corner_radii.w); float corner_radius = corner_radii[gl_VertexID]; // rjf: fill outputs vec2 dst_verts_pct = vec2(((gl_VertexID >> 1) != 1) ? 1.f : 0.f, ((gl_VertexID & 1) != 0) ? 0.f : 1.f); ivec2 u_tex_color_size_i = textureSize(u_tex_color, 0); vec2 u_tex_color_size = vec2(float(u_tex_color_size_i.x), float(u_tex_color_size_i.y)); { gl_Position = vec4(2 * dst_position.x / u_viewport_size_px.x - 1, 2 * (1 - dst_position.y / u_viewport_size_px.y) - 1, 0.0, 1.0); v2p_sdf_sample_pos = (2.f * dst_verts_pct - 1.f) * dst_half_size; v2p_texcoord_pct = src_position / u_tex_color_size; v2p_rect_half_size_px = dst_half_size; v2p_tint = color; v2p_corner_radius = corner_radius; v2p_border_thickness = c2v_style.x; v2p_softness = c2v_style.y; v2p_omit_texture = c2v_style.z; } } ``` //- rjf: pixel @embed_string r_ogl_rect_pshad_src: ``` #version 330 core in vec2 v2p_sdf_sample_pos; in vec2 v2p_texcoord_pct; in vec2 v2p_rect_half_size_px; in vec4 v2p_tint; in float v2p_corner_radius; in float v2p_border_thickness; in float v2p_softness; in float v2p_omit_texture; out vec4 final_color; uniform float u_opacity; uniform sampler2D u_tex_color; uniform mat4 u_texture_sample_channel_map; float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r) { return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r; } float linear_from_srgb_f32(float x) { return x < 0.0404482362771082 ? x / 12.92 : pow((x + 0.055) / 1.055, 2.4); } vec4 linear_from_srgba(vec4 v) { vec4 result = vec4(linear_from_srgb_f32(v.x), linear_from_srgb_f32(v.y), linear_from_srgb_f32(v.z), v.w); return result; } void main(void) { // rjf: sample texture vec4 albedo_sample = vec4(1, 1, 1, 1); if(v2p_omit_texture < 1) { albedo_sample = u_texture_sample_channel_map * texture(u_tex_color, v2p_texcoord_pct); albedo_sample = linear_from_srgba(albedo_sample); } // rjf: sample for borders float border_sdf_t = 1; if(v2p_border_thickness > 0) { float border_sdf_s = rect_sdf(v2p_sdf_sample_pos, v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f) - v2p_border_thickness, max(v2p_corner_radius-v2p_border_thickness, 0)); border_sdf_t = smoothstep(0, 2*v2p_softness, border_sdf_s); } if(border_sdf_t < 0.001f) { discard; } // rjf: sample for corners float corner_sdf_t = 1; if(v2p_corner_radius > 0 || v2p_softness > 0.75f) { float corner_sdf_s = rect_sdf(v2p_sdf_sample_pos, v2p_rect_half_size_px - vec2(v2p_softness*2.f, v2p_softness*2.f), v2p_corner_radius); corner_sdf_t = 1-smoothstep(0, 2*v2p_softness, corner_sdf_s); } // rjf: form+return final color final_color = albedo_sample; final_color *= v2p_tint; final_color.a *= u_opacity; final_color.a *= corner_sdf_t; final_color.a *= border_sdf_t; } ``` //////////////////////////////// //~ rjf: Blur Shaders //- rjf: vertex @embed_string r_ogl_blur_vshad_src: ``` #version 330 core uniform vec4 rect; uniform vec4 corner_radii_px; uniform vec2 viewport_size; uniform uint blur_count; out vec2 texcoord; out vec2 sdf_sample_pos; out vec2 rect_half_size; out float corner_radius; void main(void) { vec2 vertex_positions_scrn[] = vec2[](rect.xw, rect.xy, rect.zw, rect.zy); float corner_radii_px[] = float[](corner_radii_px.y, corner_radii_px.x, corner_radii_px.w, corner_radii_px.z); vec2 cornercoords_pct = vec2((gl_VertexID >> 1) != 0 ? 1.f : 0.f, (gl_VertexID & 1) != 0 ? 0.f : 1.f); vec2 vertex_position_pct = vertex_positions_scrn[gl_VertexID] / viewport_size; vec2 vertex_position_scr = 2.f * vertex_position_pct - 1.f; vec2 rect_half_size = vec2((rect.z-rect.x)/2, (rect.w-rect.y)/2); gl_Position = vec4(vertex_position_scr.x, -vertex_position_scr.y, 0.f, 1.f); texcoord = vertex_position_pct; sdf_sample_pos = (2.f * cornercoords_pct - 1.f) * rect_half_size; rect_half_size = rect_half_size - 2.f; corner_radius = corner_radii_px[gl_VertexID]; } ``` //- rjf: pixel @embed_string r_ogl_blur_pshad_src: ``` #version 330 core uniform sampler2D tex; uniform vec4 kernel[32]; uniform int blur_count; uniform vec2 direction; in vec2 texcoord; in vec2 sdf_sample_pos; in vec2 rect_half_size; in float corner_radius; out vec4 final_color; float rect_sdf(vec2 sample_pos, vec2 rect_half_size, float r) { return length(max(abs(sample_pos) - rect_half_size + r, 0.0)) - r; } void main(void) { // rjf: blend weighted texture samples into color vec3 color = kernel[0].x * texture(tex, texcoord).rgb; for(int i = 1; i < blur_count; i += 1) { float weight = kernel[i].x; float offset = kernel[i].y; color += weight * texture(tex, texcoord - offset * direction).rgb; color += weight * texture(tex, texcoord + offset * direction).rgb; } // rjf: sample for corners float corner_sdf_s = rect_sdf(sdf_sample_pos, rect_half_size, corner_radius); float corner_sdf_t = 1-smoothstep(0, 2, corner_sdf_s); // rjf: weight output color by sdf // this is doing alpha testing, leave blurring only where mostly opaque pixels are if(corner_sdf_t < 0.9f) { discard; } final_color = vec4(color, 1.f); } ``` ================================================ FILE: src/render/opengl/win32/render_opengl_win32.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * r_ogl_os_load_procedure(char *name) { VoidProc *p = (VoidProc*)wglGetProcAddress(name); if(p == (VoidProc*)1 || p == (VoidProc*)2 || p == (VoidProc*)3 || p == (VoidProc*)-1) { p = 0; } return p; } internal void r_ogl_os_init(CmdLine *cmdline) { //- rjf: create bootstrapping window HWND bootstrap_hwnd = 0; { WNDCLASSEXW wndclass = { sizeof(wndclass) }; wndclass.lpfnWndProc = DefWindowProcW; wndclass.hInstance = GetModuleHandle(0); wndclass.lpszClassName = L"bootstrap-window"; ATOM wndatom = RegisterClassExW(&wndclass); bootstrap_hwnd = CreateWindowExW(0, L"bootstrap-window", L"", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wndclass.hInstance, 0); } //- rjf: grab dc HDC dc = GetDC(bootstrap_hwnd); //- rjf: build pixel format descriptor int pf = 0; { PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)}; pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 24; pfd.cStencilBits = 8; pfd.iLayerType = PFD_MAIN_PLANE; pf = ChoosePixelFormat(dc, &pfd); BOOL describe = DescribePixelFormat(dc, pf, sizeof(pfd), &pfd); BOOL set_pf = SetPixelFormat(dc, pf, &pfd); } //- rjf: make bootstrap ctx + make current HGLRC bootstrap_ctx = wglCreateContext(dc); wglMakeCurrent(dc, bootstrap_ctx); //- rjf: load modern extensions wglChoosePixelFormatARB = (FNWGLCHOOSEPIXELFORMATARBPROC*) r_ogl_os_load_procedure("wglChoosePixelFormatARB"); wglCreateContextAttribsARB = (FNWGLCREATECONTEXTATTRIBSARBPROC*)r_ogl_os_load_procedure("wglCreateContextAttribsARB"); wglSwapIntervalEXT = (FNWGLSWAPINTERVALEXTPROC*) r_ogl_os_load_procedure("wglSwapIntervalEXT"); //- rjf: set up real pixel format { int pf_attribs_i[] = { WGL_DRAW_TO_WINDOW_ARB, 1, WGL_SUPPORT_OPENGL_ARB, 1, WGL_DOUBLE_BUFFER_ARB, 1, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_COLOR_BITS_ARB, 32, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 8, 0 }; UINT num_formats = 0; wglChoosePixelFormatARB(dc, pf_attribs_i, 0, 1, &pf, &num_formats); } //- rjf: make real gl ctx HGLRC real_ctx = 0; if(pf) { B32 debug_mode = cmd_line_has_flag(cmdline, str8_lit("opengl_debug")); #if BUILD_DEBUG debug_mode = 1; #endif int context_attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 3, WGL_CONTEXT_FLAGS_ARB, !!debug_mode*WGL_CONTEXT_DEBUG_BIT_ARB, 0 }; real_ctx = wglCreateContextAttribsARB(dc, bootstrap_ctx, context_attribs); r_ogl_w32_hglrc = real_ctx; } //- rjf: clean up bootstrap context wglMakeCurrent(dc, 0); wglDeleteContext(bootstrap_ctx); wglMakeCurrent(dc, real_ctx); wglSwapIntervalEXT(1); } internal R_Handle r_ogl_os_window_equip(OS_Handle window) { //- rjf: unpack window OS_W32_Window *w = os_w32_window_from_handle(window); HWND hwnd = w->hwnd; HDC hdc = w->hdc; //- rjf: select in ctx wglMakeCurrent(hdc, r_ogl_w32_hglrc); //- rjf: setup real pixel format int pixel_format = 0; UINT num_formats = 0; int pf_attribs_i[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_COLOR_BITS_ARB, 32, WGL_DEPTH_BITS_ARB, 24, WGL_STENCIL_BITS_ARB, 8, 0 }; wglChoosePixelFormatARB(hdc, pf_attribs_i, 0, 1, &pixel_format, &num_formats); // NOTE(rjf): This doesn't seem to be necessary for SetPixelFormat, we can // just pass 0 for it, and SetPixelFormat needs to be called here, but the // docs don't seem to suggest that 0 is an acceptable value, so I am just // filling this out with the same attribs as that for the wgl function, // and passing it. PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)}; pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; pfd.cDepthBits = 24; pfd.cStencilBits = 8; pfd.iLayerType = PFD_MAIN_PLANE; //- rjf: set pixel format SetPixelFormat(hdc, pixel_format, &pfd); //- rjf: release hdc R_Handle result = {0}; return result; } internal void r_ogl_os_window_unequip(OS_Handle os, R_Handle r) { } internal void r_ogl_os_select_window(OS_Handle os, R_Handle r) { OS_W32_Window *w = os_w32_window_from_handle(os); if(w != 0) { HWND hwnd = w->hwnd; HDC hdc = w->hdc; wglMakeCurrent(hdc, r_ogl_w32_hglrc); } } internal void r_ogl_os_window_swap(OS_Handle os, R_Handle r) { OS_W32_Window *w = os_w32_window_from_handle(os); if(w != 0) { HDC dc = w->hdc; SwapBuffers(dc); } } ================================================ FILE: src/render/opengl/win32/render_opengl_win32.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_WIN32_H #define RENDER_OPENGL_WIN32_H #include #pragma comment(lib, "opengl32") #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_FLAGS_ARB 0x2094 typedef BOOL WINAPI FNWGLCHOOSEPIXELFORMATARBPROC(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); typedef HGLRC WINAPI FNWGLCREATECONTEXTATTRIBSARBPROC(HDC hDC, HGLRC hShareContext, const int *attribList); typedef BOOL WINAPI FNWGLSWAPINTERVALEXTPROC(int interval); FNWGLCHOOSEPIXELFORMATARBPROC *wglChoosePixelFormatARB; FNWGLCREATECONTEXTATTRIBSARBPROC *wglCreateContextAttribsARB; FNWGLSWAPINTERVALEXTPROC *wglSwapIntervalEXT; global HGLRC r_ogl_w32_hglrc = 0; #endif // RENDER_OPENGL_WIN32_H ================================================ FILE: src/render/render_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Generated Code #include "generated/render.meta.c" //////////////////////////////// //~ rjf: Helpers internal U64 r_bytes_per_pixel_from_tex2dfmt(R_Tex2DFmt fmt) { U64 num_bits = 0; for EachIndex(channel_idx, 4) { R_ChannelSizeKind size_kind = r_size_kind_from_tex2dfmt_channel(fmt, channel_idx); switch(size_kind) { default:{}break; case R_ChannelSizeKind_2: {num_bits += 2;}break; case R_ChannelSizeKind_8: {num_bits += 8;}break; case R_ChannelSizeKind_10:{num_bits += 10;}break; case R_ChannelSizeKind_11:{num_bits += 11;}break; case R_ChannelSizeKind_16:{num_bits += 16;}break; case R_ChannelSizeKind_24:{num_bits += 24;}break; case R_ChannelSizeKind_32:{num_bits += 32;}break; } } U64 num_bits_rounded = num_bits+7; num_bits_rounded -= num_bits_rounded%8; U64 num_bytes = num_bits_rounded/8; return num_bytes; } internal Mat4x4F32 r_sample_channel_map_from_tex2dfmt(R_Tex2DFmt fmt) { Mat4x4F32 result = { { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, } }; return result; } internal Mat4x4F32 r_sample_channel_map_from_tex2dformat(R_Tex2DFormat fmt) { Mat4x4F32 result = { { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}, } }; switch(fmt) { default:{}break; case R_Tex2DFormat_R8: { MemoryZeroArray(result.v[0]); result.v[0][0] = result.v[0][1] = result.v[0][2] = result.v[0][3] = 1.f; }break; } return result; } //////////////////////////////// //~ rjf: Basic Type Functions internal R_Handle r_handle_zero(void) { R_Handle handle = {0}; return handle; } internal B32 r_handle_match(R_Handle a, R_Handle b) { return MemoryMatchStruct(&a, &b); } //////////////////////////////// //~ rjf: Batch Type Functions internal R_BatchList r_batch_list_make(U64 instance_size) { R_BatchList list = {0}; list.bytes_per_inst = instance_size; return list; } internal void * r_batch_list_push_inst(Arena *arena, R_BatchList *list, U64 batch_inst_cap) { void *inst = 0; { R_BatchNode *n = list->last; if(n == 0 || n->v.byte_count+list->bytes_per_inst > n->v.byte_cap) { n = push_array(arena, R_BatchNode, 1); n->v.byte_cap = batch_inst_cap*list->bytes_per_inst; n->v.v = push_array_no_zero(arena, U8, n->v.byte_cap); SLLQueuePush(list->first, list->last, n); list->batch_count += 1; } inst = n->v.v + n->v.byte_count; n->v.byte_count += list->bytes_per_inst; list->byte_count += list->bytes_per_inst; } return inst; } //////////////////////////////// //~ rjf: Pass Type Functions internal R_Pass * r_pass_from_kind(Arena *arena, R_PassList *list, R_PassKind kind) { R_PassNode *n = list->last; if(!r_pass_kind_batch_table[kind]) { n = 0; } if(n == 0 || n->v.kind != kind) { n = push_array(arena, R_PassNode, 1); SLLQueuePush(list->first, list->last, n); list->count += 1; n->v.kind = kind; n->v.params = push_array(arena, U8, r_pass_kind_params_size_table[kind]); } return &n->v; } ================================================ FILE: src/render/render_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_CORE_H #define RENDER_CORE_H #define r_hook C_LINKAGE //////////////////////////////// //~ rjf: Generated Code #include "generated/render.meta.h" //////////////////////////////// //~ rjf: Enums typedef U8 R_ChannelCode; // 3 bits typedef enum R_ChannelCodeEnum { R_ChannelCode_Null, R_ChannelCode_R, R_ChannelCode_G, R_ChannelCode_B, R_ChannelCode_A, } R_ChannelCodeEnum; typedef U8 R_ChannelSizeKind; // 3 bits typedef enum R_ChannelSizeKindEnum { R_ChannelSizeKind_Null, R_ChannelSizeKind_2, R_ChannelSizeKind_8, R_ChannelSizeKind_10, R_ChannelSizeKind_11, R_ChannelSizeKind_16, R_ChannelSizeKind_24, R_ChannelSizeKind_32, } R_ChannelSizeKindEnum; typedef U8 R_ChannelTypeKind; // 3 bits typedef enum R_ChannelTypeKindEnum { R_ChannelTypeKind_Null, R_ChannelTypeKind_UInt, R_ChannelTypeKind_SInt, R_ChannelTypeKind_UNorm, R_ChannelTypeKind_SNorm, R_ChannelTypeKind_Float, } R_ChannelTypeKindEnum; typedef U64 R_Tex2DFmt; // // set of channels, each channel including {code, size, type kind}, 3 bits each: // [0, 3) -> channel code // [3, 6) -> channel size // [6, 9) -> channel type kind // // 9 bits per channel, * number of channels, e.g. 4 channels -> 36 bits #define R_Channel(channel_idx, code_name, size_kind_name, type_kind_name) ((((U64)(R_ChannelCode_##code_name & 0x7)) | ((U64)(R_ChannelSizeKind_##size_kind_name & 0x7) << 3) | ((U64)(R_ChannelTypeKind_##type_kind_name & 0x7) << 6)) << ((channel_idx)*9)) #define r_code_from_tex2dfmt_channel(fmt, channel_idx) ((R_ChannelCode)(((fmt) & (0x7<<((channel_idx)*9))) >> ((channel_idx)*9))) #define r_size_kind_from_tex2dfmt_channel(fmt, channel_idx) ((R_ChannelSizeKind)(((fmt) & (0x38<<((channel_idx)*9))) >> ((channel_idx)*9 + 3))) #define r_type_kind_from_tex2dfmt_channel(fmt, channel_idx) ((R_ChannelTypeKind)(((fmt) & (0x1c0<<((channel_idx)*9))) >> ((channel_idx)*9 + 6))) #define R_Tex2DFmt_R8 (R_Channel(0, R, 8, UInt)) #define R_Tex2DFmt_RG8 (R_Channel(0, R, 8, UInt) | R_Channel(1, G, 8, UInt)) #define R_Tex2DFmt_RGB8 (R_Channel(0, R, 8, UInt) | R_Channel(1, G, 8, UInt) | R_Channel(2, B, 8, UInt)) #define R_Tex2DFmt_RGBA8 (R_Channel(0, R, 8, UInt) | R_Channel(1, G, 8, UInt) | R_Channel(2, B, 8, UInt) | R_Channel(3, A, 8, UInt)) typedef U32 R_GeoVertexFlags; enum { R_GeoVertexFlag_TexCoord = (1<<0), R_GeoVertexFlag_Normals = (1<<1), R_GeoVertexFlag_RGB = (1<<2), R_GeoVertexFlag_RGBA = (1<<3), }; //////////////////////////////// //~ rjf: Handle Type typedef union R_Handle R_Handle; union R_Handle { U64 u64[1]; U32 u32[2]; U16 u16[4]; }; //////////////////////////////// //~ rjf: Instance Types typedef struct R_Rect2DInst R_Rect2DInst; struct R_Rect2DInst { Rng2F32 dst; Rng2F32 src; Vec4F32 colors[Corner_COUNT]; F32 corner_radii[Corner_COUNT]; F32 border_thickness; F32 edge_softness; F32 white_texture_override; F32 shear; }; typedef struct R_Mesh3DInst R_Mesh3DInst; struct R_Mesh3DInst { Mat4x4F32 xform; }; //////////////////////////////// //~ rjf: Batch Types typedef struct R_Batch R_Batch; struct R_Batch { U8 *v; U64 byte_count; U64 byte_cap; }; typedef struct R_BatchNode R_BatchNode; struct R_BatchNode { R_BatchNode *next; R_Batch v; }; typedef struct R_BatchList R_BatchList; struct R_BatchList { R_BatchNode *first; R_BatchNode *last; U64 batch_count; U64 byte_count; U64 bytes_per_inst; }; typedef struct R_BatchGroup2DParams R_BatchGroup2DParams; struct R_BatchGroup2DParams { R_Handle tex; R_Tex2DSampleKind tex_sample_kind; Mat3x3F32 xform; Rng2F32 clip; F32 transparency; }; typedef struct R_BatchGroup2DNode R_BatchGroup2DNode; struct R_BatchGroup2DNode { R_BatchGroup2DNode *next; R_BatchList batches; R_BatchGroup2DParams params; }; typedef struct R_BatchGroup2DList R_BatchGroup2DList; struct R_BatchGroup2DList { R_BatchGroup2DNode *first; R_BatchGroup2DNode *last; U64 count; }; typedef struct R_BatchGroup3DParams R_BatchGroup3DParams; struct R_BatchGroup3DParams { R_Handle mesh_vertices; R_Handle mesh_indices; R_GeoTopologyKind mesh_geo_topology; R_GeoVertexFlags mesh_geo_vertex_flags; R_Handle albedo_tex; R_Tex2DSampleKind albedo_tex_sample_kind; Mat4x4F32 xform; }; typedef struct R_BatchGroup3DMapNode R_BatchGroup3DMapNode; struct R_BatchGroup3DMapNode { R_BatchGroup3DMapNode *next; U64 hash; R_BatchList batches; R_BatchGroup3DParams params; }; typedef struct R_BatchGroup3DMap R_BatchGroup3DMap; struct R_BatchGroup3DMap { R_BatchGroup3DMapNode **slots; U64 slots_count; }; //////////////////////////////// //~ rjf: Pass Types typedef struct R_PassParams_UI R_PassParams_UI; struct R_PassParams_UI { R_BatchGroup2DList rects; }; typedef struct R_PassParams_Blur R_PassParams_Blur; struct R_PassParams_Blur { Rng2F32 rect; Rng2F32 clip; F32 blur_size; F32 corner_radii[Corner_COUNT]; }; typedef struct R_PassParams_Geo3D R_PassParams_Geo3D; struct R_PassParams_Geo3D { Rng2F32 viewport; Rng2F32 clip; Mat4x4F32 view; Mat4x4F32 projection; R_BatchGroup3DMap mesh_batches; }; typedef struct R_Pass R_Pass; struct R_Pass { R_PassKind kind; union { void *params; R_PassParams_UI *params_ui; R_PassParams_Blur *params_blur; R_PassParams_Geo3D *params_geo3d; }; }; typedef struct R_PassNode R_PassNode; struct R_PassNode { R_PassNode *next; R_Pass v; }; typedef struct R_PassList R_PassList; struct R_PassList { R_PassNode *first; R_PassNode *last; U64 count; }; //////////////////////////////// //~ rjf: Helpers internal U64 r_bytes_per_pixel_from_tex2dfmt(R_Tex2DFmt fmt); internal Mat4x4F32 r_sample_channel_map_from_tex2dfmt(R_Tex2DFmt fmt); internal Mat4x4F32 r_sample_channel_map_from_tex2dformat(R_Tex2DFormat fmt); //////////////////////////////// //~ rjf: Handle Type Functions internal R_Handle r_handle_zero(void); internal B32 r_handle_match(R_Handle a, R_Handle b); //////////////////////////////// //~ rjf: Batch Type Functions internal R_BatchList r_batch_list_make(U64 instance_size); internal void *r_batch_list_push_inst(Arena *arena, R_BatchList *list, U64 batch_inst_cap); //////////////////////////////// //~ rjf: Pass Type Functions internal R_Pass *r_pass_from_kind(Arena *arena, R_PassList *list, R_PassKind kind); //////////////////////////////// //~ rjf: Backend Hooks //- rjf: top-level layer initialization r_hook void r_init(CmdLine *cmdln); //- rjf: window setup/teardown r_hook R_Handle r_window_equip(OS_Handle window); r_hook void r_window_unequip(OS_Handle window, R_Handle window_equip); //- rjf: textures r_hook R_Handle r_tex2d_alloc(R_ResourceKind kind, Vec2S32 size, R_Tex2DFormat format, void *data); r_hook void r_tex2d_release(R_Handle texture); r_hook R_ResourceKind r_kind_from_tex2d(R_Handle texture); r_hook Vec2S32 r_size_from_tex2d(R_Handle texture); r_hook R_Tex2DFormat r_format_from_tex2d(R_Handle texture); r_hook void r_fill_tex2d_region(R_Handle texture, Rng2S32 subrect, void *data); //- rjf: buffers r_hook R_Handle r_buffer_alloc(R_ResourceKind kind, U64 size, void *data); r_hook void r_buffer_release(R_Handle buffer); //- rjf: frame markers r_hook void r_begin_frame(void); r_hook void r_end_frame(void); r_hook void r_window_begin_frame(OS_Handle window, R_Handle window_equip); r_hook void r_window_end_frame(OS_Handle window, R_Handle window_equip); //- rjf: render pass submission r_hook void r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes); #endif // RENDER_CORE_H ================================================ FILE: src/render/render_core.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Tables @table(name, display_string, bytes_per_pixel) R_Tex2DFormatTable: { {R8 "R8" 1} {RG8 "RG8" 2} {RGBA8 "RGBA8" 4} {BGRA8 "BGRA8" 4} {R16 "R16" 2} {RGBA16 "RGBA16" 8} {R32 "R32" 4} {RG32 "RG32" 8} {RGBA32 "RGBA32" 16} } @table(name, display_string) R_ResourceKindTable: { // static resource is immutable // initial data must be provided at creation time // GPU can read the resource // CPU is not allowed to read or write {Static "Static" } // dynamic resource allows resource to be modified // GPU can read & write to it // CPU can write to it using UpdateSubresource {Dynamic "Dynamic"} // stream resource will be often updated fully overwriting previous data // GPU can only read it // CPU can update via Map (with WRITE_DISCARD flag) + Unmap {Stream "Stream "} } @table(name, display_string) R_Tex2DSampleKindTable: { {Nearest "Nearest" } {Linear "Linear" } } @table(name, display_string) R_GeoTopologyKindTable: { {Lines "Lines" } {LineStrip "Line Strip" } {Triangles "Triangles" } {TriangleStrip "Triangle Strip" } } @table(name, batch, display_string) R_PassKindTable: { {UI 1 "UI" } {Blur 0 "Blur" } {Geo3D 1 "Geo3D" } } //////////////////////////////// //~ rjf: Generators @enum R_Tex2DFormat: { @expand(R_Tex2DFormatTable a) `$(a.name)`, COUNT, } @enum R_ResourceKind: { @expand(R_ResourceKindTable a) `$(a.name)`, COUNT, } @enum R_Tex2DSampleKind: { @expand(R_Tex2DSampleKindTable a) `$(a.name)`, COUNT, } @enum R_GeoTopologyKind: { @expand(R_GeoTopologyKindTable a) `$(a.name)`, COUNT, } @enum R_PassKind: { @expand(R_PassKindTable a) `$(a.name)`, COUNT, } @data(String8) r_tex2d_format_display_string_table: { @expand(R_Tex2DFormatTable a) `str8_lit_comp("$(a.display_string)")`; } @data(U8) r_tex2d_format_bytes_per_pixel_table: { @expand(R_Tex2DFormatTable a) `$(a.bytes_per_pixel)`; } @data(String8) r_resource_kind_display_string_table: { @expand(R_ResourceKindTable a) `str8_lit_comp("$(a.display_string)")`; } @data(String8) r_tex2d_sample_kind_display_string_table: { @expand(R_Tex2DSampleKindTable a) `str8_lit_comp("$(a.display_string)")`; } @data(String8) r_pass_kind_display_string_table: { @expand(R_PassKindTable a) `str8_lit_comp("$(a.display_string)")`; } @data(U8) r_pass_kind_batch_table: { @expand(R_PassKindTable a) `$(a.batch)`; } @data(U64) @c_file r_pass_kind_params_size_table: { @expand(R_PassKindTable a) `sizeof(R_PassParams_$(a.name))`; } ================================================ FILE: src/render/render_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xc22121ff #include "render_core.c" #if R_BACKEND == R_BACKEND_STUB # include "stub/render_stub.c" #elif R_BACKEND == R_BACKEND_D3D11 # include "d3d11/render_d3d11.c" #elif R_BACKEND == R_BACKEND_OPENGL # include "opengl/render_opengl.c" #else # error Renderer backend not specified. #endif ================================================ FILE: src/render/render_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_INC_H #define RENDER_INC_H //////////////////////////////// //~ rjf: Backend Constants #define R_BACKEND_STUB 0 #define R_BACKEND_D3D11 1 #define R_BACKEND_OPENGL 2 //////////////////////////////// //~ rjf: Decide On Backend #if !defined(R_BACKEND) && OS_WINDOWS # define R_BACKEND R_BACKEND_D3D11 #elif !defined(R_BACKEND) && OS_LINUX # define R_BACKEND R_BACKEND_OPENGL #endif //////////////////////////////// //~ rjf: Main Includes #include "render_core.h" //////////////////////////////// //~ rjf: Backend Includes #if R_BACKEND == R_BACKEND_STUB # include "stub/render_stub.h" #elif R_BACKEND == R_BACKEND_D3D11 # include "d3d11/render_d3d11.h" #elif R_BACKEND == R_BACKEND_OPENGL # include "opengl/render_opengl.h" #else # error Renderer backend not specified. #endif #endif // RENDER_INC_H ================================================ FILE: src/render/stub/render_stub.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- rjf: top-level layer initialization r_hook void r_init(CmdLine *cmdln) { } //- rjf: window setup/teardown r_hook R_Handle r_window_equip(OS_Handle window) { R_Handle handle = {0}; handle.u64[0] = 1; return handle; } r_hook void r_window_unequip(OS_Handle window, R_Handle window_equip) { } //- rjf: textures r_hook R_Handle r_tex2d_alloc(R_ResourceKind kind, Vec2S32 size, R_Tex2DFormat format, void *data) { R_Handle handle = {0}; handle.u64[0] = 1; return handle; } r_hook void r_tex2d_release(R_Handle texture) { } r_hook R_ResourceKind r_kind_from_tex2d(R_Handle texture) { return R_ResourceStatic; } r_hook Vec2S32 r_size_from_tex2d(R_Handle texture) { return v2s32(1, 1); } r_hook R_Tex2DFormat r_format_from_tex2d(R_Handle texture) { return R_Tex2DFormat_RGBA8; } r_hook void r_fill_tex2d_region(R_Handle texture, Rng2S32 subrect, void *data) { } //- rjf: buffers r_hook R_Handle r_buffer_alloc(R_ResourceKind kind, U64 size, void *data) { R_Handle handle = {0}; handle.u64[0] = 1; return handle; } r_hook void r_buffer_release(R_Handle buffer) { } //- rjf: frame markers r_hook void r_begin_frame(void) { } r_hook void r_end_frame(void) { } r_hook void r_window_begin_frame(OS_Handle window, R_Handle window_equip) { } r_hook void r_window_end_frame(OS_Handle window, R_Handle window_equip) { } //- rjf: render pass submission r_hook void r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes) { } ================================================ FILE: src/render/stub/render_stub.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_STUB_H #define RENDER_STUB_H #endif // RENDER_STUB_H ================================================ FILE: src/scratch/debugstringperf.c ================================================ #include DWORD thread_entry_point(void *p) { for(int i = 0; i < 100000; i += 1) { OutputDebugString("this is a test\n"); } return 0; } int main(int argc, char **argv) { HANDLE threads[] = { CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), CreateThread(0, 0, thread_entry_point, 0, 0, 0), }; for(int i = 0; i < sizeof(threads)/sizeof(threads[0]); i += 1) { WaitForSingleObject(threads[i], INFINITE); } return 0; } ================================================ FILE: src/scratch/eval_scratch.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "rdi_format/rdi_format_local.h" #include "regs/regs.h" #include "regs/rdi/regs_rdi.h" #include "eval/eval_inc.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "rdi_format/rdi_format_local.c" #include "regs/regs.c" #include "regs/rdi/regs_rdi.c" #include "eval/eval_inc.c" //////////////////////////////// //~ rjf: Entry Point internal void entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); E_TypeCtx *type_ctx = push_array(arena, E_TypeCtx, 1); e_select_type_ctx(type_ctx); E_ParseCtx *parse_ctx = push_array(arena, E_ParseCtx, 1); e_select_parse_ctx(parse_ctx); E_IRCtx *ir_ctx = push_array(arena, E_IRCtx, 1); e_select_ir_ctx(ir_ctx); E_InterpretCtx *interpret_ctx = push_array(arena, E_InterpretCtx, 1); e_select_interpret_ctx(interpret_ctx, 0, 0); String8 exprs[] = { str8_lit("123"), str8_lit("1 + 2"), str8_lit("foo"), str8_lit("foo(bar)"), str8_lit("foo(bar(baz))"), }; for EachElement(idx, exprs) { String8 debug_string = e_debug_log_from_expr_string(arena, exprs[idx]); raddbg_log("%S", debug_string); } } ================================================ FILE: src/scratch/parse_inline_sites.c ================================================ #define BUILD_CONSOLE_INTERFACE 1 #include "base/base_inc.h" #include "os/os_inc.h" #include "coff/coff.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" #include "msf/msf_parse.h" #include "pdb/pdb.h" #include "pdb/pdb_parse.h" #include "pdb/pdb_stringize.h" #include "base/base_inc.c" #include "os/os_inc.c" #include "coff/coff.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c" #include "msf/msf_parse.c" #include "pdb/pdb.c" #include "pdb/pdb_parse.c" #include "pdb/pdb_stringize.c" //////////////////////////////// #include "linker/base_ext/base_blake3.h" #include "linker/base_ext/base_blake3.c" #include "third_party/md5/md5.c" #include "third_party/md5/md5.h" #include "third_party/xxHash/xxhash.c" #include "third_party/xxHash/xxhash.h" #include "linker/base_ext/base_inc.h" #include "linker/hash_table.h" #include "linker/thread_pool/thread_pool.h" #include "linker/codeview_ext/codeview.h" #include "linker/base_ext/base_inc.c" #include "linker/hash_table.c" #include "linker/thread_pool/thread_pool.c" #include "linker/codeview_ext/codeview.c" internal void print_inline_binary_annotations(String8 binary_annots) { U32 code_offset = 0; S32 line_offset = 0; for (U64 cursor = 0; cursor < binary_annots.size; ) { U64 op_offset = cursor; CV_InlineBinaryAnnotation op = CV_InlineBinaryAnnotation_Null; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &op); fprintf(stdout, "\t\t[%04llX] ", op_offset); switch (op) { case CV_InlineBinaryAnnotation_Null: { fprintf(stdout, "End"); cursor = binary_annots.size; } break; case CV_InlineBinaryAnnotation_CodeOffset: { U32 value = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &value); code_offset += value; fprintf(stdout, "CodeOffset: 0x%X; Code 0x%X", value, code_offset); } break; case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: { U32 delta; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &delta); code_offset += delta; fprintf(stdout, "ChangeCodeOffsetBase: 0x%X; Code 0x%X", delta, code_offset); } break; case CV_InlineBinaryAnnotation_ChangeCodeOffset: { U32 delta = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &delta); code_offset += delta; fprintf(stdout, "ChangeCodeOffset: 0x%X; Code 0x%X", delta, code_offset); } break; case CV_InlineBinaryAnnotation_ChangeCodeLength: { U32 delta = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &delta); code_offset += delta; fprintf(stdout, "ChangeCodeLength: 0x%X; Code End 0x%X", delta, code_offset); } break; case CV_InlineBinaryAnnotation_ChangeFile: { U32 file_id = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &file_id); fprintf(stdout, "ChangeFile: 0x%X", file_id); } break; case CV_InlineBinaryAnnotation_ChangeLineOffset: { S32 delta = 0; cursor += cv_decode_inline_annot_s32(binary_annots, cursor, &delta); line_offset += delta; fprintf(stdout, "ChangeLineOffset: %d; Line %d", delta, line_offset); } break; case CV_InlineBinaryAnnotation_ChangeLineEndDelta: { S32 end_delta = 0; cursor += cv_decode_inline_annot_s32(binary_annots, cursor, &end_delta); line_offset += end_delta; fprintf(stdout, "ChangeLineEndDelta: %d; Line %d", end_delta, line_offset); } break; case CV_InlineBinaryAnnotation_ChangeRangeKind: { CV_InlineRangeKind range_kind = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &range_kind); String8 range_kind_str = cv_string_from_inline_range_kind(range_kind); fprintf(stdout, "ChangeRangeKind: %.*s (%u)", str8_varg(range_kind_str), range_kind); } break; case CV_InlineBinaryAnnotation_ChangeColumnStart: { S32 delta = 0; cursor += cv_decode_inline_annot_s32(binary_annots, cursor, &delta); fprintf(stdout, "ChangeColumnStart: %d", delta); } break; case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: { U32 code_offset_and_line_offset = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &code_offset_and_line_offset); S32 line_delta = cv_inline_annot_signed_from_unsigned_operand(code_offset_and_line_offset >> 4); U32 code_delta = code_offset_and_line_offset & 0xF; line_offset += line_delta; code_offset += code_delta; fprintf(stdout, "ChnageCodeOffsetAndLineOffset: 0x%X %d; Code 0x%X Line %d", code_delta, line_delta, code_offset, line_offset); } break; case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: { U32 code_length_delta = 0; U32 code_offset_delta = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &code_length_delta); cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &code_offset_delta); code_offset += code_offset_delta; fprintf(stdout, "ChangeCodeLengthAndCodeOffset: %u 0x%X; Code 0x%X Code End 0x%X", code_length_delta, code_offset_delta, code_offset, code_offset + code_length_delta); code_offset += code_length_delta; } break; case CV_InlineBinaryAnnotation_ChangeColumnEnd: { U32 column_end = 0; cursor += cv_decode_inline_annot_u32(binary_annots, cursor, &column_end); fprintf(stdout, "ChangeColumnEnd: %u", column_end); } break; default: { fprintf(stdout, "Unknown Inline Binary Annotation Op Code: 0x%X", op); } break; } fprintf(stdout, "\n"); } } internal void entry_point(CmdLine *cmdl) { Arena *arena = arena_alloc(); B32 do_help = cmd_line_has_flag(cmdl, str8_lit("help")) || cmd_line_has_flag(cmdl, str8_lit("h")) || (cmdl->inputs.node_count == 0 && cmdl->options.count == 0); if (do_help) { fprintf(stdout, "Parse Inline Sites\n" "\t-pdb:\n" "\t-comp_unit=\n" "\t-base_addr=\n" "\t-help\n"); return; } // -comp_unit U64 single_comp_unit_idx = max_U64; B32 single_comp_unit_mode = cmd_line_has_argument(cmdl, str8_lit("comp_unit")); if (single_comp_unit_mode) { String8 comp_unit_str = cmd_line_string(cmdl, str8_lit("comp_unit")); if (!try_u64_from_str8_c_rules(comp_unit_str, &single_comp_unit_idx)) { fprintf(stderr, "ERROR: unable to parse -comp_unit=%.*s\n", str8_varg(comp_unit_str)); return; } } // -base_addr U64 base_addr = 0; String8 base_str = cmd_line_string(cmdl, str8_lit("base_addr")); try_u64_from_str8_c_rules(base_str, &base_addr); // -pdb String8 pdb_name; if (cmd_line_has_argument(cmdl, str8_lit("pdb"))) { pdb_name = cmd_line_string(cmdl, str8_lit("pdb")); if (pdb_name.size == 0) { fprintf(stderr, "ERROR: missing -pdb:\n"); return; } } else { if (cmdl->inputs.node_count == 1) { pdb_name = cmdl->inputs.first->string; } else if (cmdl->inputs.node_count == 0) { fprintf(stderr, "ERROR: no input PDB!\n"); return; } else if (cmdl->inputs.node_count > 1) { fprintf(stderr, "ERROR: too many inputs\n"); return; } } // read PDB from disk String8 pdb_data = os_data_from_file_path(arena, pdb_name); if (pdb_data.size == 0) { fprintf(stderr, "ERROR: unable to load %.*s from disk\n", str8_varg(pdb_name)); return; } // parse msf MSF_Parsed *msf = msf_parsed_from_data(arena, pdb_data); if (!msf) { fprintf(stderr, "ERROR: unable to parse MSF\n"); return; } // find dbi String8 dbi_data = msf_data_from_stream(msf, PDB_FixedStream_Dbi); PDB_DbiParsed *dbi = pdb_dbi_from_data(arena, dbi_data); if (!dbi) { fprintf(stderr, "ERROR: unable to parse DBI\n"); return; } // find info stream String8 info_data = msf_data_from_stream(msf, PDB_FixedStream_Info); PDB_Info *info = pdb_info_from_data(arena, info_data); if (!info) { fprintf(stderr, "ERROR: unable to parse INFO\n"); } // parse named streams PDB_NamedStreamTable *named_streams = pdb_named_stream_table_from_info(arena, info); if (!named_streams) { fprintf(stderr, "ERROR: unable to parse named streams\n"); return; } // find string table MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable]; String8 strtbl_data = msf_data_from_stream(msf, strtbl_sn); PDB_Strtbl *strtbl = pdb_strtbl_from_data(arena, strtbl_data); if (!strtbl) { fprintf(stderr, "ERROR: unable to parse string table\n"); return; } // find IPI String8 ipi_data = msf_data_from_stream(msf, PDB_FixedStream_Ipi); PDB_TpiParsed *ipi = pdb_tpi_from_data(arena, ipi_data); String8 ipi_leaf_data = pdb_leaf_data_from_tpi(ipi); CV_LeafParsed *ipi_leaf_parsed = cv_leaf_from_data(arena, ipi_leaf_data, ipi->itype_first); // find sections MSF_StreamNumber section_stream = dbi->dbg_streams[PDB_DbiStream_SECTION_HEADER]; String8 section_data = msf_data_from_stream(msf, section_stream); COFF_SectionHeaderArray sections = pdb_coff_section_array_from_data(arena, section_data); // find comp units String8 comp_units_data = pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo); PDB_CompUnitArray *comp_units = pdb_comp_unit_array_from_data(arena, comp_units_data); if (single_comp_unit_mode) { if (single_comp_unit_idx >= comp_units->count) { fprintf(stderr, "comp unit idx %llu is out of bounds, PDB has %llu comp unit(s)\n", single_comp_unit_idx, comp_units->count); return; } } #if 0 // print run info DateTime now_time_universal = os_now_universal_time(); DateTime now_time_local = os_local_time_from_universal_time(&now_time_universal); String8 now_time_str = string_from_date_time(arena, &now_time_local); fprintf(stdout, "Time: %.*s\n", str8_varg(now_time_str)); fprintf(stdout, "File: %.*s\n", str8_varg(pdb_name)); fprintf(stdout, "Size: %llu (bytes)\n", pdb_data.size); fprintf(stdout, "\n"); #endif // prepare iterator U64 comp_unit_idx; U64 comp_unit_count; if (single_comp_unit_mode) { comp_unit_idx = single_comp_unit_idx; comp_unit_count = single_comp_unit_idx + 1; } else { comp_unit_idx = 0; comp_unit_count = comp_units->count; } for (; comp_unit_idx < comp_unit_count; ++comp_unit_idx) { PDB_CompUnit *comp_unit = comp_units->units[comp_unit_idx]; String8 symbol_data = pdb_data_from_unit_range(msf, comp_unit, PDB_DbiCompUnitRange_Symbols); String8 c13_data = pdb_data_from_unit_range(msf, comp_unit, PDB_DbiCompUnitRange_C13); // parse $$ CV_DebugS debug_s = cv_parse_debug_s_c13(arena, c13_data); // find $$FILE_CKSMS String8 file_chksms = cv_file_chksms_from_debug_s(debug_s); // parse $$INLINEE_LINES String8List ss_inlinee_lines = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_InlineeLines); CV_C13InlineeLinesParsedList inlinee_lines_parsed = cv_c13_inlinee_lines_from_sub_sections(arena, ss_inlinee_lines); // parse $$LINES U64 c13_lines_count = 0; CV_LineArray *c13_lines = 0; { String8List raw_lines_list = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Lines); for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { Temp temp = temp_begin(arena); CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(temp.arena, raw_lines_node->string, rng_1u64(0, raw_lines_node->string.size)); c13_lines_count += parsed_list.count; temp_end(temp); } c13_lines = push_array_no_zero(arena, CV_LineArray, c13_lines_count); U64 c13_lines_idx = 0; for (String8Node *raw_lines_node = raw_lines_list.first; raw_lines_node != 0; raw_lines_node = raw_lines_node->next) { String8 raw_lines = raw_lines_node->string; CV_C13LinesHeaderList parsed_list = cv_c13_lines_from_sub_sections(arena, raw_lines, rng_1u64(0, raw_lines.size)); for(CV_C13LinesHeaderNode *header_node = parsed_list.first; header_node != 0; header_node = header_node->next) { if (0 < header_node->v.sec_idx && header_node->v.sec_idx <= sections.count) { Assert(c13_lines_idx < c13_lines_count); U64 sec_voff = sections.v[header_node->v.sec_idx - 1].voff; c13_lines[c13_lines_idx++] = cv_c13_line_array_from_data(arena, raw_lines, sec_voff, header_node->v); } else { Assert(!"error: out of bounds section index"); } } } } String8List raw_inlinee_lines = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_InlineeLines); CV_C13InlineeLinesParsedList inlinee_lines = cv_c13_inlinee_lines_from_sub_sections(arena, raw_inlinee_lines); CV_InlineeLinesAccel *inlinee_lines_accel = cv_c13_make_inlinee_lines_accel(arena, inlinee_lines); CV_LinesAccel *lines_accel = cv_c13_make_lines_accel(arena, c13_lines_count, c13_lines); fprintf(stdout, "[%llu] %.*s\n", comp_unit_idx, str8_varg(comp_unit->obj_name)); U64 scope_level = 0; U64 parent_voff = 0; String8 parent_name = str8_lit("???"); CV_SymbolList symbol_list = {0}; cv_parse_symbol_sub_section(arena, &symbol_list, 0, symbol_data, CV_SymbolAlign); for (CV_SymbolNode *symbol_n = symbol_list.first; symbol_n != 0; symbol_n = symbol_n->next) { CV_Symbol symbol = symbol_n->data; void *rec_raw = symbol.data.str; void *rec_opl = symbol.data.str + symbol.data.size; if (symbol.kind == CV_SymKind_LPROC32 || symbol.kind == CV_SymKind_GPROC32) { CV_SymProc32 *proc32 = rec_raw; parent_voff = sections.v[proc32->sec-1].voff + proc32->off; parent_name = str8_cstring_capped(proc32+1, rec_opl); scope_level += 1; } else if (symbol.kind == CV_SymKind_BLOCK32) { scope_level += 1; } else if (symbol.kind == CV_SymKind_END) { if (parent_voff) { Assert(scope_level > 0); scope_level -= 1; if (scope_level == 0) { parent_voff = 0; parent_name = str8_lit("???"); } } } else if (symbol.kind == CV_SymKind_INLINESITE) { CV_SymInlineSite *inline_site = rec_raw; String8 binary_annots = str8_skip(symbol.data, sizeof(*inline_site)); CV_C13InlineeLinesParsed *inlinee_parsed = cv_c13_inlinee_lines_accel_find(inlinee_lines_accel, inline_site->inlinee); CV_InlineBinaryAnnotsParsed binary_annots_parse = cv_c13_parse_inline_binary_annots(arena, parent_voff, inlinee_parsed, binary_annots); String8 inlinee_name = str8_lit("???"); if (ipi->itype_first <= inline_site->inlinee && inline_site->inlinee < ipi->itype_opl) { CV_RecRange inlinee_rec = ipi_leaf_parsed->leaf_ranges.ranges[inline_site->inlinee - ipi->itype_first]; void *leaf_raw = ipi_leaf_data.str + inlinee_rec.off + sizeof(CV_LeafKind); void *leaf_opl = ipi_leaf_data.str + inlinee_rec.off + sizeof(CV_LeafKind) + inlinee_rec.hdr.size; if (inlinee_rec.hdr.kind == CV_LeafKind_MFUNC_ID) { CV_LeafMFuncId *mfunc_id = leaf_raw; inlinee_name = str8_cstring_capped(mfunc_id + 1, leaf_opl); } else if (inlinee_rec.hdr.kind == CV_LeafKind_FUNC_ID) { CV_LeafFuncId *func_id = leaf_raw; inlinee_name = str8_cstring_capped(func_id + 1, leaf_opl); } } String8 first_ln = str8_lit("???"); String8 file_off = str8_lit("???"); if (inlinee_parsed) { first_ln = push_str8f(arena, "%u", inlinee_parsed->first_source_ln); file_off = push_str8f(arena, "0x%X", inlinee_parsed->file_off); } fprintf(stdout, "\tInline site @ %06llX, Parent VOFF: 0x%llX (%.*s), Inlinee: 0x%X (%.*s), First LN: %.*s, File Off: %.*s\n", (symbol.offset + sizeof(symbol.kind)), parent_voff, str8_varg(parent_name), inline_site->inlinee, str8_varg(inlinee_name), str8_varg(first_ln), str8_varg(file_off)); fprintf(stdout, "\t\tOpcodes:\n"); print_inline_binary_annotations(binary_annots); fprintf(stdout, "\n"); fprintf(stdout, "\t\tLines:\n"); for (U64 lines_idx = 0; lines_idx < binary_annots_parse.lines_count; lines_idx += 1) { CV_LineArray lines = binary_annots_parse.lines[lines_idx]; CV_C13Checksum checksum = {0}; str8_deserial_read_struct(file_chksms, lines.file_off, &checksum); String8 file_name = pdb_strtbl_string_from_off(strtbl, checksum.name_off); fprintf(stdout, "\t\t%.*s\n", str8_varg(file_name)); for (U64 line_idx = 0; line_idx < lines.line_count; ++line_idx) { char *pre = (line_idx % 4) == 0 ? "\t\t\t" : "\t"; char *post = (line_idx % 4) == 3 || ((line_idx + 1) == lines.line_count) ? "\n" : ""; fprintf(stdout, "%s%08llX %04u%s", pre, base_addr + lines.voffs[line_idx], lines.line_nums[line_idx], post); } } fprintf(stdout, "\n"); fprintf(stdout, "\t\tCode Ranges:\n"); U64 range_idx = 0; for (Rng1U64Node *range_n = binary_annots_parse.code_ranges.first; range_n != 0; range_n = range_n->next, ++range_idx) { char *pre = (range_idx % 4) == 0 ? "\t\t\t" : "\t"; char *post = (range_idx % 4) == 3 || ((range_idx + 1) == binary_annots_parse.code_ranges.count) ? "\n" : ""; fprintf(stdout, "%s%08llX-%08llX%s", pre, base_addr + range_n->v.min, base_addr + range_n->v.max, post); } fprintf(stdout, "\n"); } } } } ================================================ FILE: src/scratch/ryan_scratch.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Build Options #define BUILD_TITLE "ryan_scratch" #define BUILD_CONSOLE_INTERFACE 1 //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "content/content.h" #include "artifact_cache/artifact_cache.h" #include "file_stream/file_stream.h" #include "rdi/rdi_local.h" #include "dbg_info/dbg_info.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "content/content.c" #include "artifact_cache/artifact_cache.c" #include "file_stream/file_stream.c" #include "rdi/rdi_local.c" #include "dbg_info/dbg_info.c" //////////////////////////////// //~ rjf: Entry Point internal void entry_point(CmdLine *cmdline) { local_persist char *pdb_paths[] = { "C:/devel/raddebugger/build/raddbg.pdb", // #include "fn_debug_infos.inc" }; DI_Key keys[ArrayCount(pdb_paths)] = {0}; for EachElement(idx, pdb_paths) { String8 path = str8_cstring(pdb_paths[idx]); keys[idx] = di_key_from_path_timestamp(path, 0); di_open(keys[idx]); } for(;;) { Access *access = access_open(); B32 got_all_rdis = 1; U64 num_rdis_loaded = 0; for EachElement(idx, pdb_paths) { RDI_Parsed *rdi = di_rdi_from_key(access, keys[idx], 1, 0); if(rdi == &rdi_parsed_nil) { got_all_rdis = 0; } else { num_rdis_loaded += 1; } } printf("\rloaded [%I64u/%I64u], %I64u active threads, %I64u active processes", num_rdis_loaded, ArrayCount(pdb_paths), di_shared->conversion_thread_count, di_shared->conversion_process_count); access_close(access); if(got_all_rdis) { Access *access = access_open(); String8 search_query = str8_lit("rd_"); DI_SearchItemArray items = di_search_item_array_from_target_query(access, RDI_SectionKind_Procedures, search_query, max_U64); printf("\n"); printf("fuzzy searched for %.*s, found %I64u items\n", str8_varg(search_query), items.count); access_close(access); String8 match_query = str8_lit("rd_frame"); DI_Match match = di_match_from_string(match_query, 0, max_U64); printf("searched for %.*s, found at %i in [%I64x:%I64x]\n", str8_varg(match_query), match.idx, match.key.u64[0], match.key.u64[1]); break; } } } ================================================ FILE: src/scratch/textperf.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Build Options #define BUILD_TITLE "textperf" #define OS_FEATURE_GRAPHICAL 1 //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "render/render_inc.h" #include "font_provider/font_provider_inc.h" #include "font_cache/font_cache.h" #include "draw/draw.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "render/render_inc.c" #include "font_provider/font_provider_inc.c" #include "font_cache/font_cache.c" #include "draw/draw.c" //////////////////////////////// //~ rjf: Globals global OS_Handle os_window = {0}; global R_Handle r_window = {0}; //////////////////////////////// //~ rjf: Entry Points internal B32 frame(void) { ProfBeginFunction(); B32 quit = 0; Temp scratch = scratch_begin(0, 0); OS_EventList events = os_get_events(scratch.arena, 0); for(OS_Event *evt = events.first; evt != 0; evt = evt->next) { if(evt->kind == OS_EventKind_WindowClose) { quit = 1; break; } } r_begin_frame(); dr_begin_frame(fnt_tag_zero()); r_window_begin_frame(os_window, r_window); DR_Bucket *bucket = dr_bucket_make(); DR_BucketScope(bucket) ProfScope("draw") { Vec2F32 mouse = os_mouse_from_window(os_window); FNT_Tag font = fnt_tag_from_path(str8_lit("C:/devel/raddebugger/data/Inconsolata-Regular.ttf")); for(F32 x = 0; x < 500; x += 5.f) { for(F32 y = 0; y < 500; y += 5.f) { dr_text(font, 16.f, 0, 0, FNT_RasterFlag_Smooth|FNT_RasterFlag_Hinted, v2f32(30 + x + mouse.x, 30 + y + mouse.y), v4f32(1, 1, 1, 1), str8_lit("This is a test.")); } } } r_window_submit(os_window, r_window, &bucket->passes); r_window_end_frame(os_window, r_window); r_end_frame(); scratch_end(scratch); ProfEnd(); return quit; } internal void entry_point(CmdLine *cmdline) { os_window = os_window_open(r2f32p(0, 0, 1600, 900), OS_WindowFlag_UseDefaultPosition, str8_lit("textperf")); r_window = r_window_equip(os_window); os_window_first_paint(os_window); for(;!update();); } ================================================ FILE: src/stap/stap_parse.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 stap_is_scale_valid(U64 scale) { return IsPow2(scale) && scale <= 8; } internal U64 stap_parse_digit(U8 *begin, U8 *end, U64 *digit_out) { U8 *ptr = begin; if (ptr < end && *ptr == '-') { ptr += 1; } for (;ptr < end; ptr += 1) { if (!char_is_digit(*ptr, 10)) { break; } } String8 digit_str = str8(begin, (U64)(ptr - begin)); if (digit_out) { *digit_out = u64_from_str8(digit_str, 10); } return digit_str.size; } internal U64 stap_skip_whitespace(U8 *begin, U8 *end) { U8 *ptr = begin; for (; ptr < end && *ptr == ' '; ptr += 1); U64 size = (U64)(ptr - begin); return size; } internal U64 stap_parse_ident(U8 *begin, U8 *end, String8 *ident_out) { U8 *ptr = begin; for (; ptr < end; ptr += 1) { if (!char_is_alpha(*ptr) && !char_is_digit(*ptr, 10)) { break; } } String8 ident = str8(begin, (U64)(ptr - begin)); if (ident_out) { *ident_out = ident; } return ident.size; } internal U64 stap_size_from_arg(String8 string) { U64 tag_sep = str8_find_needle(string, 0, str8_lit("@"), 0); U64 next_tag_sep = str8_find_needle(string, tag_sep + 1, str8_lit("@"), 0); U64 arg_end = str8_find_needle_reverse(string, string.size - next_tag_sep, str8_lit(" "), 0); return arg_end == 0 ? string.size : arg_end; } internal String8List stap_list_from_string(Arena *arena, String8 string) { String8List result = {0}; for (U64 cursor = 0, arg_size; cursor < string.size; cursor += arg_size) { arg_size = stap_size_from_arg(str8_skip(string, cursor)); String8 arg = str8_substr(string, r1u64(cursor, cursor + arg_size)); str8_list_push(arena, &result, arg); } return result; } internal String8 stap_parse_args_x64(String8 string, STAP_Arg *arg_out) { String8 error = str8_lit("unknown parse error"); U64 sep_pos = str8_find_needle(string, 0, str8_lit("@"), 0); if (sep_pos < string.size) { STAP_Arg arg = {0}; String8 tag = str8_prefix(string, sep_pos + 1); String8 oper = str8_skip(string, tag.size); STAP_ArgValueType arg_value_type = STAP_ArgValueType_Null; U64 arg_value_size = 0; B32 infer_arg_value_size = 1; U64 tag_size = 0; { U8 *ptr = tag.str, *end = tag.str + tag.size; // is signed? if (ptr >= end) { goto operand_parse_exit; } if (*ptr == '-') { arg_value_type = STAP_ArgValueType_S; ptr += 1; } // parse optional size if (ptr >= end) { goto operand_parse_exit; } if (char_is_digit(*ptr, 10)) { arg_value_size = *ptr - '0'; if (!stap_is_scale_valid(arg_value_size)) { error = str8_lit("invalid operand size"); goto operand_parse_exit; } ptr += 1; infer_arg_value_size = 0; } // is this float? if (ptr >= end) { goto operand_parse_exit; } if (*ptr == 'f') { if (arg_value_type != STAP_ArgValueType_Null) { error = str8_lit("illegal combination of modifiers '-' and 'f'"); goto operand_parse_exit; } ptr += 1; arg_value_type = STAP_ArgValueType_F; } // assume default value type to be unsigned if (arg_value_type == STAP_ArgValueType_Null) { arg_value_type = STAP_ArgValueType_U; } if (ptr >= end) { goto operand_parse_exit; } if (*ptr != '@') { error = str8_lit("failed to find @"); goto operand_parse_exit; } ptr += 1; tag_size = (U64)(ptr - tag.str); } U64 memory_ref_start = str8_find_needle_reverse(oper, 0, str8_lit("("), 0); // memory operand if (memory_ref_start > 0 && memory_ref_start < oper.size) { // // Expected syntax for memory operand: { [Disp] (Base [',' Index [',' Scale]]) } | { $IMM } | { %reg } // // Disp: { [+|-]Digits } | { Expr } // Base: %reg // Index: %reg // Scale: 1|2|4|8 // Expr: A small C-like infix expression // // find closing ')' U64 memory_ref_end = str8_find_needle(oper, memory_ref_start+1, str8_lit(")"), 0); if (memory_ref_end > oper.size) { error = str8_lit("missing closing ')'"); goto operand_parse_exit; } if (memory_ref_end >= oper.size) { error = str8_lit("expression does not terminate after ')'"); goto operand_parse_exit; } // parse displacement String8 disp_str = str8_skip_chop_whitespace(str8_prefix(oper, memory_ref_start-1)); if (disp_str.size > 0 && !str8_is_integer_signed(disp_str, 10)) { error = str8_lit("displacement is too complicated, only integral displacement is supported"); goto operand_parse_exit; } S64 disp = s64_from_str8(disp_str, 10); // parse base, index, scale String8 base_index_scale = str8_skip_chop_whitespace(str8_substr(oper, r1u64(memory_ref_start, memory_ref_end))); U64 first_comma = str8_find_needle(base_index_scale, 0, str8_lit(","), 0); U64 second_comma = str8_find_needle(base_index_scale, first_comma+1, str8_lit(","), 0); String8 base_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(0, first_comma))); String8 index_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(first_comma + 1, second_comma))); String8 scale_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(second_comma + 1, memory_ref_end))); // syntax check if(first_comma >= base_index_scale.size && base_str.size == 0) { error = str8_lit("missing base register"); goto operand_parse_exit; } if (first_comma < base_index_scale.size && index_str.size == 0) { error = str8_lit("missing index register"); goto operand_parse_exit; } if (second_comma < base_index_scale.size && scale_str.size == 0) { error = str8_lit("missing scale"); goto operand_parse_exit; } if (base_str.size > 0 && !str8_match(str8_lit("%"), base_str, StringMatchFlag_RightSideSloppy)) { error = str8_lit("invalid base register"); goto operand_parse_exit; } if (first_comma < base_index_scale.size && (index_str.size < 2 || !str8_match(str8_lit("%"), index_str, StringMatchFlag_RightSideSloppy))) { error = str8_lit("invalid index register"); goto operand_parse_exit; } if (second_comma < base_index_scale.size && (scale_str.size > 0 && !str8_is_integer(scale_str, 10))) { error = str8_lit("invalid of scale (expected unsigned integral type)"); goto operand_parse_exit; } // stip '%' prefix base_str = str8_skip(base_str, 1); index_str = str8_skip(index_str, 1); // parse base B8 base_is_alias = 0; U32 base_reg_code = 0; if (base_str.size) { base_reg_code = regs_reg_code_from_name(Arch_x64, base_str); if (base_reg_code == 0) { base_reg_code = regs_alias_code_from_name(Arch_x64, base_str); base_is_alias = base_reg_code != 0; } if (base_reg_code == 0) { error = str8_lit("unknown base register"); goto operand_parse_exit; } } // parse index B8 index_is_alias = 0; U32 index_reg_code = 0; if (index_str.size) { index_reg_code = regs_reg_code_from_name(Arch_x64, index_str); if (index_reg_code == 0) { index_reg_code = regs_alias_code_from_name(Arch_x64, index_str); index_is_alias = index_reg_code != 0; } if (index_reg_code == 0) { error = str8_lit("unknown index register"); } } // parse scale U64 scale = 1; if (scale_str.size) { scale = u64_from_str8(scale_str, 10); if (!stap_is_scale_valid(scale)) { error = str8_lit("invalid scale value (expected 1/2/4/8)"); goto operand_parse_exit; } } if (infer_arg_value_size) { error = str8_lit("memory operands must have a sice"); goto operand_parse_exit; } // fill out memory ref portion arg.type = STAP_ArgType_MemoryRef; arg.memory_ref.disp = disp; arg.memory_ref.base.reg_code = base_reg_code; arg.memory_ref.base.is_alias = base_is_alias; arg.memory_ref.index.reg_code = index_reg_code; arg.memory_ref.index.is_alias = index_is_alias; arg.memory_ref.scale = scale; } // $imm else if (str8_match(str8_lit("$"), oper, StringMatchFlag_RightSideSloppy)) { String8 imm_str = str8_skip(oper, 1); U64 imm_size = str8_find_needle(imm_str, 0, str8_lit(" "), 0); if (imm_size > imm_str.size ) { imm_size = imm_str.size; } imm_str = str8_prefix(imm_str, imm_size); if (imm_str.size == 0) { goto operand_parse_exit; } U64 imm = 0; B32 is_parsed = 0; switch (arg_value_type) { case STAP_ArgValueType_Null: case STAP_ArgValueType_U: case STAP_ArgValueType_F: { is_parsed = try_u64_from_str8_c_rules(imm_str, &imm); } break; case STAP_ArgValueType_S: { is_parsed = try_s64_from_str8_c_rules(imm_str, (S64 *)&imm); } break; default: { InvalidPath; } break; } if (!is_parsed) { error = str8_lit("failed to parse immediate"); goto operand_parse_exit; } arg.type = STAP_ArgType_Imm; arg.imm = imm; } // %reg else if (str8_match(str8_lit("%"), oper, StringMatchFlag_RightSideSloppy)) { // skip % and strip white space String8 reg_str = str8_skip_chop_whitespace(str8_skip(oper, 1)); if (reg_str.size == 0) { goto operand_parse_exit; } B8 is_reg_alias = 0; U32 reg_code = regs_reg_code_from_name(Arch_x64, reg_str); if (reg_code == 0) { reg_code = regs_alias_code_from_name(Arch_x64, reg_str); is_reg_alias = reg_code != 0; } if (reg_code == 0) { error = str8_lit("invalid register name"); goto operand_parse_exit; } arg.type = STAP_ArgType_Reg; arg.reg.is_alias = is_reg_alias; arg.reg.reg_code = reg_code; } else { goto operand_parse_exit; } // fill out value portion arg.value_type = arg_value_type == STAP_ArgValueType_Null ? STAP_ArgValueType_U : arg_value_type; arg.value_size = arg_value_size; // write output if (arg_out) { *arg_out = arg; } // clear error tracker error = str8_zero(); operand_parse_exit:; } else { error = str8_lit("invalid argument string"); } return error; } internal STAP_ArgArray stap_arg_array_from_string(Arena *arena, Arch arch, String8 string) { Temp scratch = scratch_begin(&arena, 1); String8List arg_strings = stap_list_from_string(scratch.arena, string); STAP_ArgArray result = {0}; result.v = push_array(arena, STAP_Arg, arg_strings.node_count); for EachNode(n, String8Node, arg_strings.first) { STAP_Arg *arg = &result.v[result.count++]; switch (arch) { case Arch_Null: {} break; case Arch_x64: { stap_parse_args_x64(n->string, arg); } break; case Arch_x86: case Arch_arm32: case Arch_arm64: { NotImplemented; } break; default: { InvalidPath; } break; } } scratch_end(scratch); return result; } internal B32 stap_read_arg(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, void *raw_value) { AssertAlways(arg.value_size <= 8); B32 is_value_read = 0; switch (arg.type) { case STAP_ArgType_Null: break; case STAP_ArgType_Imm: { MemoryCopy(raw_value, &arg.imm, arg.value_size); is_value_read = 1; } break; case STAP_ArgType_Reg: { Rng1U64 range = regs_range_from_code(arch, arg.reg.is_alias, arg.reg.reg_code); U64 copy_size = Min(arg.value_size, dim_1u64(range)); MemoryCopy(raw_value, (U8 *)reg_block + range.min, copy_size); is_value_read = 1; } break; case STAP_ArgType_MemoryRef: { U64 base = 0; if(arg.memory_ref.base.reg_code) { Rng1U64 range = regs_range_from_code(arch, arg.memory_ref.base.is_alias, arg.memory_ref.base.reg_code); U64 copy_size = Min(sizeof(base), dim_1u64(range)); MemoryCopy(&base, (U8 *)reg_block + range.min, copy_size); } U64 index = 0; if(arg.memory_ref.index.reg_code) { Rng1U64 range = regs_range_from_code(arch, arg.memory_ref.index.is_alias, arg.memory_ref.index.reg_code); U64 copy_size = Min(sizeof(base), dim_1u64(range)); MemoryCopy(&index, (U8 *)reg_block + range.min, copy_size); } U64 addr = arg.memory_ref.disp + (base + index * arg.memory_ref.scale); if (memory_read(addr, raw_value, arg.value_size, memory_read_ctx)) { is_value_read = 1; } } break; default: { InvalidPath; } break; } if (arg.value_size < 8) { if (arg.value_type == STAP_ArgValueType_S) { *(U64 *)raw_value = extend_sign64(*(U64 *)raw_value, arg.value_size); } else if (arg.value_type == STAP_ArgValueType_F) { Assert(arg.value_size == 4); *(F64 *)raw_value = *(F32 *)raw_value; } } return is_value_read; } internal B32 stap_read_arg_u(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, U64 *u_out) { return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, u_out); } internal B32 stap_read_arg_s(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, S64 *s_out) { return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, s_out); } internal B32 stap_read_arg_f(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, F64 *f_out) { return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, f_out); } ================================================ FILE: src/stap/stap_parse.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef STAP_PARSE_H #define STAP_PARSE_H typedef enum STAP_ArgType { STAP_ArgType_Null, STAP_ArgType_Imm, STAP_ArgType_Reg, STAP_ArgType_MemoryRef, } STAP_ArgType; typedef enum STAP_ArgValueType { STAP_ArgValueType_Null, STAP_ArgValueType_U, STAP_ArgValueType_S, STAP_ArgValueType_F, } STAP_ArgValueType; typedef struct STAP_Arg { STAP_ArgValueType value_type; U64 value_size; STAP_ArgType type; union { U64 imm; struct { U32 reg_code; B8 is_alias; } reg; struct { S64 disp; struct { U32 reg_code; B8 is_alias; } base; struct { U32 reg_code; B8 is_alias; } index; U64 scale; } memory_ref; }; } STAP_Arg; typedef struct STAP_ArgArray { U64 count; STAP_Arg *v; } STAP_ArgArray; typedef struct STAP_ArgValue { STAP_ArgValueType value_type; U8 value_size; void *raw_ptr; } STAP_ArgValue; typedef struct STAP_ArgValueArray { U64 count; STAP_ArgValue *v; } STAP_ArgValueArray; #define STAP_MEMORY_READ(name) B32 name(U64 addr, void *buffer, U64 read_size, void *raw_ctx) typedef STAP_MEMORY_READ(STAP_MemoryRead); //////////////////////////////// internal String8 stap_parse_args_x64(String8 string, STAP_Arg *arg_out); internal STAP_ArgArray stap_arg_array_from_string(Arena *arena, Arch arch, String8 string); internal B32 stap_read_arg(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, void *raw_value); internal B32 stap_read_arg_u(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, U64 *u_out); internal B32 stap_read_arg_s(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, S64 *s_out); internal B32 stap_read_arg_f(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, F64 *f_out); #endif // STAP_PARSE_H ================================================ FILE: src/stap/stap_test.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #define BUILD_TITLE "STAP Parser Test" #define BUILD_CONSOLE_INTERFACE 1 #include "base/base_inc.h" #include "os/os_inc.h" #include "regs/regs.h" #include "stap/stap_parse.h" #include "base/base_inc.c" #include "os/os_inc.c" #include "regs/regs.c" #include "stap/stap_parse.c" internal void entry_point(CmdLine *cmd_line) { B32 passed = 0; STAP_Arg arg = {0}; String8 error = {0}; String8 string = {0}; string = str8_lit("-2@$-123"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_type == STAP_ArgValueType_S); AssertAlways(arg.value_size == 2); AssertAlways(arg.type == STAP_ArgType_Imm); AssertAlways((S64)arg.imm == -123); string = str8_lit("1@$43"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.value_size == 1); AssertAlways(arg.type == STAP_ArgType_Imm); AssertAlways((S64)arg.imm == 43); string = str8_lit("4f@%eax"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_type == STAP_ArgValueType_F); AssertAlways(arg.value_size == 4); AssertAlways(arg.type == STAP_ArgType_Reg); AssertAlways(arg.reg.is_alias == 1); AssertAlways(arg.reg.reg_code == REGS_AliasCodeX64_eax); string = str8_lit("4@(%rdi)"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_size == 4); AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.type == STAP_ArgType_MemoryRef); AssertAlways(arg.memory_ref.disp == 0); AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi); AssertAlways(!arg.memory_ref.base.is_alias); AssertAlways(arg.memory_ref.index.reg_code == 0); AssertAlways(arg.memory_ref.index.is_alias == 0); AssertAlways(arg.memory_ref.scale == 1); string = str8_lit("4@-22(%rdi)"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_size == 4); AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.type == STAP_ArgType_MemoryRef); AssertAlways(arg.memory_ref.disp == -22); AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi); AssertAlways(!arg.memory_ref.base.is_alias); AssertAlways(arg.memory_ref.index.reg_code == 0); AssertAlways(arg.memory_ref.index.is_alias == 0); AssertAlways(arg.memory_ref.scale == 1); string = str8_lit("4@32(%rax,%rsi,8)"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_size == 4); AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.memory_ref.disp == 32); AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rax); AssertAlways(arg.memory_ref.base.is_alias == 0); AssertAlways(arg.memory_ref.index.reg_code == REGS_RegCodeX64_rsi); AssertAlways(arg.memory_ref.index.is_alias == 0); AssertAlways(arg.memory_ref.scale == 8); string = str8_lit("4@32(,%rsi,8)"); error = stap_parse_args_x64(string, &arg); if (error.size != 0) { goto exit; } AssertAlways(arg.value_size == 4); AssertAlways(arg.value_type == STAP_ArgValueType_U); AssertAlways(arg.memory_ref.disp == 32); AssertAlways(arg.memory_ref.base.reg_code == 0); AssertAlways(arg.memory_ref.index.reg_code == REGS_RegCodeX64_rsi); AssertAlways(arg.memory_ref.scale == 8); error = stap_parse_args_x64(str8_lit("4@(,,)"), &arg); if (error.size == 0) { goto exit; } error = stap_parse_args_x64(str8_lit("4@()"), &arg); if (error.size == 0) { goto exit; } error = stap_parse_args_x64(str8_lit("4@(%rdi, %rsi, 8"), &arg); if (error.size == 0) { goto exit; } error = stap_parse_args_x64(str8_lit("4@( ,, 8"), &arg); if (error.size == 0) { goto exit; } passed = 1; exit:; AssertAlways(passed); } ================================================ FILE: src/strip_lib_debug/strip_lib_debug.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #define BUILD_TITLE "Epic Games Tools (R) Lib Strip Debug" #define BUILD_CONSOLE_INTERFACE 1 //////////////////////////////// // Headers #include "base/base_inc.h" #include "os/os_inc.h" #include "coff/coff.h" #include "coff/coff_parse.h" //////////////////////////////// // Implementations #include "base/base_inc.c" #include "os/os_inc.c" #include "coff/coff.c" #include "coff/coff_parse.c" internal void sld_main(CmdLine *cmdl) { B32 do_help = cmd_line_has_flag(cmdl, str8_lit("help")) || cmd_line_has_flag(cmdl, str8_lit("h")) || cmd_line_has_flag(cmdl, str8_lit("?")) || cmdl->argc == 1; if (do_help) { fprintf(stderr, "--- Help ---------------------------------------------------------------------\n"); fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL); fprintf(stderr, " Usage: strip_lib_debug [Options]\n\n"); fprintf(stderr, " Options:\n"); fprintf(stderr, " -in: Path to input lib file\n"); fprintf(stderr, " -out: Path to output lib file\n"); os_abort(0); } Temp scratch = scratch_begin(0,0); String8 in_lib_path = cmd_line_string(cmdl, str8_lit("in")); String8 out_lib_path = cmd_line_string(cmdl, str8_lit("out")); if (in_lib_path.size == 0) { fprintf(stderr, "ERROR: please provide an input path via -in:\n"); os_abort(1); } if (out_lib_path.size == 0) { fprintf(stderr, "ERROR: please provide an output path via -out:\n"); os_abort(1); } String8 in_lib = os_data_from_file_path(scratch.arena, in_lib_path); if (in_lib.size == 0) { fprintf(stderr, "ERROR: unable to read file %.*s\n", str8_varg(in_lib_path)); os_abort(1); } if (!coff_is_regular_archive(in_lib)) { fprintf(stderr, "ERROR: input lib is not COFF archive\n"); os_abort(1); } // read & parse lib String8 out_lib = push_str8_copy(scratch.arena, in_lib); COFF_ArchiveParse parse = coff_archive_parse_from_data(out_lib); // was parse successful? if (parse.error.size) { fprintf(stderr, "ERROR: %.*s: %.*s\n", str8_varg(in_lib_path), str8_varg(parse.error)); os_abort(1); } // convert big endian offsets U32 member_offsets_count = parse.first_member.symbol_count; U32 *member_offsets = push_array(scratch.arena, U32, parse.first_member.member_offset_count); for (U32 offset_idx = 0; offset_idx < member_offsets_count; offset_idx += 1) { member_offsets[offset_idx] = from_be_u32(parse.first_member.member_offsets[offset_idx]); } // fixup sections for (U64 member_idx = 0; member_idx < member_offsets_count; member_idx += 1) { COFF_ParsedArchiveMemberHeader member_header = {0}; coff_parse_archive_member_header(out_lib, member_offsets[member_idx], &member_header); String8 member_data = str8_substr(out_lib, member_header.data_range); COFF_DataType member_type = coff_data_type_from_data(member_data); if (member_type == COFF_DataType_BigObj || member_type == COFF_DataType_Obj) { COFF_FileHeaderInfo file_header_info = coff_file_header_info_from_data(member_data); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(member_data, file_header_info.section_table_range).str; String8 string_table = str8_substr(member_data, file_header_info.string_table_range); for (U64 sect_idx = 0; sect_idx < file_header_info.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; String8 name = coff_name_from_section_header(string_table, sect_header); if (str8_match(str8_lit(".debug$S"), name, 0) || str8_match(str8_lit(".debug$T"), name, 0)) { sect_header->flags = COFF_SectionFlag_LnkRemove; MemorySet(sect_header->name, 'x', sizeof(sect_header->name)); } } } } // wirte modified library if (!os_write_data_to_file_path(out_lib_path, out_lib)) { fprintf(stderr, "ERROR: unable to write output file to %.*s\n", str8_varg(out_lib_path)); os_abort(1); } scratch_end(scratch); } internal void entry_point(CmdLine *cmdl) { sld_main(cmdl); } ================================================ FILE: src/tester/tester_main.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Build Options #define BUILD_TITLE "tester" #define BUILD_CONSOLE_INTERFACE 1 #define OS_FEATURE_GRAPHICAL 1 //////////////////////////////// //~ rjf: Includes //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "content/content.h" #include "rdi_format/rdi_format_local.h" #include "regs/regs.h" #include "regs/rdi/regs_rdi.h" #include "eval/eval_inc.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "content/content.c" #include "rdi_format/rdi_format_local.c" #include "regs/regs.c" #include "regs/rdi/regs_rdi.c" #include "eval/eval_inc.c" //////////////////////////////// //~ rjf: Entry Points internal B32 frame(void) { return 0; } internal void entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); E_Cache *eval_cache = e_cache_alloc(); e_select_cache(eval_cache); E_BaseCtx *base_ctx = push_array(arena, E_BaseCtx, 1); e_select_base_ctx(base_ctx); E_IRCtx *ir_ctx = push_array(arena, E_IRCtx, 1); e_select_ir_ctx(ir_ctx); E_InterpretCtx *interpret_ctx = push_array(arena, E_InterpretCtx, 1); e_select_interpret_ctx(interpret_ctx, 0, 0); ////////////////////////////// //- rjf: unpack command line // String8 test_data_folder_path = cmd_line_string(cmdline, str8_lit("test_data")); if(test_data_folder_path.size == 0) { fprintf(stderr, "error(input): The test data folder path was not specified. Specify the path when running the program, like: %.*s --test_data:C:/foo/bar/baz\n", str8_varg(cmdline->exe_name)); os_abort(1); } ////////////////////////////// //- rjf: make artifacts directory // String8 artifacts_path = path_normalized_from_string(arena, str8_lit("./tester_artifacts")); os_make_directory(artifacts_path); ////////////////////////////// //- rjf: set up list of test artifacts // typedef struct Test Test; struct Test { Test *next; String8 name; String8List out; B32 good; }; Test *first_test = 0; Test *last_test = 0; #define Test(name_identifier) \ Test *test_##name_identifier = push_array(arena, Test, 1);\ test_##name_identifier->name = str8_lit(#name_identifier);\ test_##name_identifier->good = 1;\ SLLQueuePush(first_test, last_test, test_##name_identifier);\ for(Test *test = test_##name_identifier; test != 0; test = 0) ////////////////////////////// //- rjf: PDB -> RDI determinism // Test(pdb2rdi_determinism) { U64 num_repeats_per_pdb = 32; String8 pdb_paths[] = { push_str8f(arena, "%S/mule_main/mule_main.pdb", test_data_folder_path), push_str8f(arena, "%S/mule_main/mule_module.pdb", test_data_folder_path), }; for EachElement(pdb_idx, pdb_paths) { // rjf: unpack paths, make output directory String8 pdb_path = path_normalized_from_string(arena, pdb_paths[pdb_idx]); String8 repeat_folder = push_str8f(arena, "%S/%S", artifacts_path, test->name); os_make_directory(repeat_folder); // rjf: generate all RDIs String8List rdi_paths = {0}; String8List dump_paths = {0}; { OS_HandleList processes = {0}; for EachIndex(repeat_idx, num_repeats_per_pdb) { String8 rdi_path = push_str8f(arena, "%S/repeat_%I64u.rdi", repeat_folder, repeat_idx); str8_list_push(arena, &rdi_paths, rdi_path); os_handle_list_push(arena, &processes, os_cmd_line_launchf("rdi_from_pdb --deterministic --pdb:%S --out:%S", pdb_path, rdi_path)); } for(OS_HandleNode *n = processes.first; n != 0; n = n->next) { os_process_join(n->v, max_U64, 0); } } // rjf: generate all dumps { OS_HandleList processes = {0}; for(String8Node *n = rdi_paths.first; n != 0; n = n->next) { String8 rdi_path = n->string; String8 dump_path = push_str8f(arena, "%S.dump", rdi_path); str8_list_push(arena, &dump_paths, dump_path); os_handle_list_push(arena, &processes, os_cmd_line_launchf("rdi_dump %S > %S", rdi_path, dump_path)); } for(OS_HandleNode *n = processes.first; n != 0; n = n->next) { os_process_join(n->v, max_U64, 0); } } // rjf: gather all hashes/paths U64 rdi_hashes_count = rdi_paths.node_count; U128 *rdi_hashes = push_array(arena, U128, rdi_hashes_count); String8 *rdi_paths_array = push_array(arena, String8, rdi_hashes_count); U64 dump_hashes_count = dump_paths.node_count; U128 *dump_hashes = push_array(arena, U128, dump_hashes_count); String8 *dump_paths_array = push_array(arena, String8, dump_hashes_count); { U64 idx = 0; for(String8Node *n = rdi_paths.first; n != 0; n = n->next, idx += 1) { Temp scratch = scratch_begin(0, 0); String8 path = n->string; String8 data = os_data_from_file_path(scratch.arena, path); rdi_hashes[idx] = u128_hash_from_str8(data); rdi_paths_array[idx] = path; scratch_end(scratch); } } { U64 idx = 0; for(String8Node *n = dump_paths.first; n != 0; n = n->next, idx += 1) { Temp scratch = scratch_begin(0, 0); String8 path = n->string; String8 data = os_data_from_file_path(scratch.arena, path); dump_hashes[idx] = u128_hash_from_str8(data); dump_paths_array[idx] = path; scratch_end(scratch); } } // rjf: determine if all hashes match B32 matches = 1; for EachIndex(idx, rdi_hashes_count) { if(!u128_match(rdi_hashes[idx], rdi_hashes[0])) { matches = 0; break; } } for EachIndex(idx, dump_hashes_count) { if(!u128_match(dump_hashes[idx], dump_hashes[0])) { matches = 0; break; } } // rjf: output bad case info if(!matches) { test->good = 0; str8_list_pushf(arena, &test->out, " pdb[%I64u] \"%S\"\n", pdb_idx, pdb_path); for EachIndex(idx, rdi_hashes_count) { str8_list_pushf(arena, &test->out, " rdi[%I64u] \"%S\": 0x%I64x:%I64x\n", idx, rdi_paths_array[idx], rdi_hashes[idx].u64[0], rdi_hashes[idx].u64[1]); } for EachIndex(idx, dump_hashes_count) { str8_list_pushf(arena, &test->out, " dump[%I64u] \"%S\": 0x%I64x:%I64x\n", idx, dump_paths_array[idx], dump_hashes[idx].u64[0], dump_hashes[idx].u64[1]); } } } } ////////////////////////////// //- rjf: eval compiler basics // Test(eval_compiler_basics) { String8 exprs[] = { str8_lit("123"), str8_lit("1 + 2"), str8_lit("foo"), str8_lit("foo(bar)"), str8_lit("foo(bar(baz))"), }; String8List logs = {0}; for EachElement(idx, exprs) { String8 log = e_debug_log_from_expr_string(arena, exprs[idx]); str8_list_push(arena, &logs, log); } String8 log = str8_list_join(arena, &logs, 0); String8 test_artifacts_path = push_str8f(arena, "%S/%S", artifacts_path, test->name); os_make_directory(test_artifacts_path); String8 current_file_path = push_str8f(arena, "%S/current.txt", test_artifacts_path); String8 correct_file_path = push_str8f(arena, "%S/%S/correct.txt", test_data_folder_path, test->name); os_write_data_to_file_path(current_file_path, log); String8 current_file_data = log; String8 correct_file_data = os_data_from_file_path(arena, correct_file_path); test->good = str8_match(correct_file_data, current_file_data, 0); } ////////////////////////////// //- rjf: dump results // B32 all_good = 1; for(Test *t = first_test; t != 0; t = t->next) { if(!t->good) { all_good = 0; break; } } fprintf(stderr, "[%s]\n", all_good ? "." : "X"); for(Test *t = first_test; t != 0; t = t->next) { fprintf(stderr, " [%s] \"%.*s\"\n", t->good ? "." : "X", str8_varg(t->name)); if(!t->good) { for(String8Node *n = t->out.first; n != 0; n = n->next) { fprintf(stderr, " %.*s", str8_varg(n->string)); } } } } ================================================ FILE: src/text/generated/text.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN String8 txt_lang_kind_ext_table[8] = { str8_lit_comp("null"), str8_lit_comp("c"), str8_lit_comp("cpp"), str8_lit_comp("odin"), str8_lit_comp("jai"), str8_lit_comp("zig"), str8_lit_comp("rs"), str8_lit_comp("disasm_x64_intel"), }; struct {String8 ext; TXT_LangKind kind;} txt_ext_lang_kind_table[24] = { {str8_lit_comp("null"), TXT_LangKind_Null}, {str8_lit_comp("c"), TXT_LangKind_C}, {str8_lit_comp("cpp"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("odin"), TXT_LangKind_Odin}, {str8_lit_comp("jai"), TXT_LangKind_Jai}, {str8_lit_comp("zig"), TXT_LangKind_Zig}, {str8_lit_comp("rs"), TXT_LangKind_Rust}, {str8_lit_comp("disasm_x64_intel"), TXT_LangKind_DisasmX64Intel}, {str8_lit_comp("h"), TXT_LangKind_C}, {str8_lit_comp("cxx"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("cc"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("c++"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("ixx"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("cxxm"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("c++m"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("ccm"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("cppm"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("mpp"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("C"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("hpp"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("hxx"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("hh"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("h++"), TXT_LangKind_CPlusPlus}, {str8_lit_comp("H"), TXT_LangKind_CPlusPlus}, }; String8Array txt_keywords_from_lang_kind_table[8] = { {txt_keywords__null, ArrayCount(txt_keywords__null)}, {txt_keywords__c, ArrayCount(txt_keywords__c)}, {txt_keywords__cpp, ArrayCount(txt_keywords__cpp)}, {txt_keywords__odin, ArrayCount(txt_keywords__odin)}, {txt_keywords__jai, ArrayCount(txt_keywords__jai)}, {txt_keywords__zig, ArrayCount(txt_keywords__zig)}, {txt_keywords__rust, ArrayCount(txt_keywords__rust)}, {txt_keywords__null, ArrayCount(txt_keywords__null)}, }; String8Array txt_multichar_symbols_from_lang_kind_table[8] = { {txt_multichar_symbols__null, ArrayCount(txt_multichar_symbols__null)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__c, ArrayCount(txt_multichar_symbols__c)}, {txt_multichar_symbols__null, ArrayCount(txt_multichar_symbols__null)}, }; TXT_TokenizerRuleArray txt_tokenizer_rules_from_lang_kind_table[8] = { {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, {txt_tokenizer_rules__c, ArrayCount(txt_tokenizer_rules__c)}, {txt_tokenizer_rules__c, ArrayCount(txt_tokenizer_rules__c)}, {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, {txt_tokenizer_rules__null, ArrayCount(txt_tokenizer_rules__null)}, }; String8 txt_keywords__null[1] = { {0}, }; String8 txt_multichar_symbols__null[1] = { {0}, }; TXT_TokenizerRule txt_tokenizer_rules__null[1] = { {TXT_TokenKind_Null}, }; String8 txt_keywords__c[32] = { str8_lit_comp("auto"), str8_lit_comp("break"), str8_lit_comp("case"), str8_lit_comp("char"), str8_lit_comp("const"), str8_lit_comp("continue"), str8_lit_comp("default"), str8_lit_comp("do"), str8_lit_comp("double"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("extern"), str8_lit_comp("float"), str8_lit_comp("for"), str8_lit_comp("goto"), str8_lit_comp("if"), str8_lit_comp("int"), str8_lit_comp("long"), str8_lit_comp("register"), str8_lit_comp("return"), str8_lit_comp("short"), str8_lit_comp("signed"), str8_lit_comp("sizeof"), str8_lit_comp("static"), str8_lit_comp("struct"), str8_lit_comp("switch"), str8_lit_comp("typedef"), str8_lit_comp("union"), str8_lit_comp("unsigned"), str8_lit_comp("void"), str8_lit_comp("volatile"), str8_lit_comp("while"), }; String8 txt_multichar_symbols__c[20] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; TXT_TokenizerRule txt_tokenizer_rules__c[7] = { {TXT_TokenKind_Comment, str8_lit_comp("//"), str8_lit_comp("\n"), 0, 0, 1, 0}, {TXT_TokenKind_Comment, str8_lit_comp("/*"), str8_lit_comp("*/"), 2, 0, 0, 0}, {TXT_TokenKind_Meta, str8_lit_comp("#"), str8_lit_comp("\n"), 0, 0, 1, 0}, {TXT_TokenKind_String, str8_lit_comp("\""), str8_lit_comp("\""), 1, 0, 1, 0}, {TXT_TokenKind_String, str8_lit_comp("'"), str8_lit_comp("'"), 1, 0, 1, 0}, {TXT_TokenKind_String, str8_lit_comp("\""), str8_lit_comp("\""), 1, 0, 1, 3}, {TXT_TokenKind_String, str8_lit_comp("<"), str8_lit_comp(">"), 1, 0, 1, 3}, }; String8 txt_keywords__cpp[97] = { str8_lit_comp("alignas"), str8_lit_comp("alignof"), str8_lit_comp("and"), str8_lit_comp("and_eq"), str8_lit_comp("asm"), str8_lit_comp("atomic_cancel"), str8_lit_comp("atomic_commit"), str8_lit_comp("atomic_noexcept"), str8_lit_comp("auto"), str8_lit_comp("bitand"), str8_lit_comp("bitor"), str8_lit_comp("bool"), str8_lit_comp("break"), str8_lit_comp("case"), str8_lit_comp("catch"), str8_lit_comp("char"), str8_lit_comp("char8_t"), str8_lit_comp("char16_t"), str8_lit_comp("char32_t"), str8_lit_comp("class"), str8_lit_comp("compl"), str8_lit_comp("concept"), str8_lit_comp("const"), str8_lit_comp("consteval"), str8_lit_comp("constexpr"), str8_lit_comp("constinit"), str8_lit_comp("const_cast"), str8_lit_comp("continue"), str8_lit_comp("co_await"), str8_lit_comp("co_return"), str8_lit_comp("co_yield"), str8_lit_comp("decltype"), str8_lit_comp("default"), str8_lit_comp("delete"), str8_lit_comp("do"), str8_lit_comp("double"), str8_lit_comp("dynamic_cast"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("explicit"), str8_lit_comp("export"), str8_lit_comp("extern"), str8_lit_comp("false"), str8_lit_comp("float"), str8_lit_comp("for"), str8_lit_comp("friend"), str8_lit_comp("goto"), str8_lit_comp("if"), str8_lit_comp("inline"), str8_lit_comp("int"), str8_lit_comp("long"), str8_lit_comp("mutable"), str8_lit_comp("namespace"), str8_lit_comp("new"), str8_lit_comp("noexcept"), str8_lit_comp("not"), str8_lit_comp("not_eq"), str8_lit_comp("nullptr"), str8_lit_comp("operator"), str8_lit_comp("or"), str8_lit_comp("or_eq"), str8_lit_comp("private"), str8_lit_comp("protected"), str8_lit_comp("public"), str8_lit_comp("reflexpr"), str8_lit_comp("register"), str8_lit_comp("reinterpret_cast"), str8_lit_comp("requires"), str8_lit_comp("return"), str8_lit_comp("short"), str8_lit_comp("signed"), str8_lit_comp("sizeof"), str8_lit_comp("static"), str8_lit_comp("static_assert"), str8_lit_comp("static_cast"), str8_lit_comp("struct"), str8_lit_comp("switch"), str8_lit_comp("synchronized"), str8_lit_comp("template"), str8_lit_comp("this"), str8_lit_comp("thread_local"), str8_lit_comp("throw"), str8_lit_comp("true"), str8_lit_comp("try"), str8_lit_comp("typedef"), str8_lit_comp("typeid"), str8_lit_comp("typename"), str8_lit_comp("union"), str8_lit_comp("unsigned"), str8_lit_comp("using"), str8_lit_comp("virtual"), str8_lit_comp("void"), str8_lit_comp("volatile"), str8_lit_comp("wchar_t"), str8_lit_comp("while"), str8_lit_comp("xor"), str8_lit_comp("xor_eq"), }; String8 txt_keywords__odin[40] = { str8_lit_comp("align_of"), str8_lit_comp("asm"), str8_lit_comp("auto_cast"), str8_lit_comp("bit_set"), str8_lit_comp("break"), str8_lit_comp("case"), str8_lit_comp("cast"), str8_lit_comp("context"), str8_lit_comp("continue"), str8_lit_comp("defer"), str8_lit_comp("distinct"), str8_lit_comp("do"), str8_lit_comp("dynamic"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("fallthrough"), str8_lit_comp("for"), str8_lit_comp("foreign"), str8_lit_comp("if"), str8_lit_comp("in"), str8_lit_comp("map"), str8_lit_comp("matrix"), str8_lit_comp("not_in"), str8_lit_comp("or_break"), str8_lit_comp("or_continue"), str8_lit_comp("or_else"), str8_lit_comp("or_return"), str8_lit_comp("package"), str8_lit_comp("proc"), str8_lit_comp("return"), str8_lit_comp("size_of"), str8_lit_comp("struct"), str8_lit_comp("switch"), str8_lit_comp("transmute"), str8_lit_comp("typeid"), str8_lit_comp("union"), str8_lit_comp("using"), str8_lit_comp("when"), str8_lit_comp("where"), str8_lit_comp("import"), }; String8 txt_keywords__jai[39] = { str8_lit_comp("bool"), str8_lit_comp("true"), str8_lit_comp("false"), str8_lit_comp("int"), str8_lit_comp("s8"), str8_lit_comp("u8"), str8_lit_comp("s16"), str8_lit_comp("u16"), str8_lit_comp("s32"), str8_lit_comp("u32"), str8_lit_comp("s64"), str8_lit_comp("u64"), str8_lit_comp("s128"), str8_lit_comp("u128"), str8_lit_comp("float"), str8_lit_comp("float32"), str8_lit_comp("float64"), str8_lit_comp("void"), str8_lit_comp("enum"), str8_lit_comp("enum_flags"), str8_lit_comp("size_of"), str8_lit_comp("string"), str8_lit_comp("type_of"), str8_lit_comp("cast"), str8_lit_comp("if"), str8_lit_comp("ifs"), str8_lit_comp("then"), str8_lit_comp("else"), str8_lit_comp("case"), str8_lit_comp("for"), str8_lit_comp("while"), str8_lit_comp("break"), str8_lit_comp("continue"), str8_lit_comp("remove"), str8_lit_comp("return"), str8_lit_comp("inline"), str8_lit_comp("null"), str8_lit_comp("defer"), str8_lit_comp("xx"), }; String8 txt_keywords__zig[49] = { str8_lit_comp("addrspace"), str8_lit_comp("align"), str8_lit_comp("allowzero"), str8_lit_comp("and"), str8_lit_comp("anyframe"), str8_lit_comp("anytype"), str8_lit_comp("asm"), str8_lit_comp("async"), str8_lit_comp("await"), str8_lit_comp("break"), str8_lit_comp("callconv"), str8_lit_comp("catch"), str8_lit_comp("comptime"), str8_lit_comp("const"), str8_lit_comp("continue"), str8_lit_comp("defer"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("errdefer"), str8_lit_comp("error"), str8_lit_comp("export"), str8_lit_comp("extern"), str8_lit_comp("fn"), str8_lit_comp("for"), str8_lit_comp("if"), str8_lit_comp("inline"), str8_lit_comp("noalias"), str8_lit_comp("nosuspend"), str8_lit_comp("noinline"), str8_lit_comp("opaque"), str8_lit_comp("or"), str8_lit_comp("orelse"), str8_lit_comp("packed"), str8_lit_comp("pub"), str8_lit_comp("resume"), str8_lit_comp("return"), str8_lit_comp("linksection"), str8_lit_comp("struct"), str8_lit_comp("suspend"), str8_lit_comp("switch"), str8_lit_comp("test"), str8_lit_comp("threadlocal"), str8_lit_comp("try"), str8_lit_comp("union"), str8_lit_comp("unreachable"), str8_lit_comp("usingnamespace"), str8_lit_comp("var"), str8_lit_comp("volatile"), str8_lit_comp("while"), }; String8 txt_keywords__rust[43] = { str8_lit_comp("as"), str8_lit_comp("break"), str8_lit_comp("const"), str8_lit_comp("continue"), str8_lit_comp("crate"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("extern"), str8_lit_comp("false"), str8_lit_comp("fn"), str8_lit_comp("for"), str8_lit_comp("if"), str8_lit_comp("impl"), str8_lit_comp("in"), str8_lit_comp("let"), str8_lit_comp("loop"), str8_lit_comp("match"), str8_lit_comp("mod"), str8_lit_comp("move"), str8_lit_comp("mut"), str8_lit_comp("pub"), str8_lit_comp("ref"), str8_lit_comp("return"), str8_lit_comp("self"), str8_lit_comp("Self"), str8_lit_comp("static"), str8_lit_comp("struct"), str8_lit_comp("super"), str8_lit_comp("trait"), str8_lit_comp("true"), str8_lit_comp("type"), str8_lit_comp("unsafe"), str8_lit_comp("use"), str8_lit_comp("where"), str8_lit_comp("while"), str8_lit_comp("yield"), str8_lit_comp("async"), str8_lit_comp("await"), str8_lit_comp("dyn"), str8_lit_comp("macro_rules"), str8_lit_comp("raw"), str8_lit_comp("safe"), str8_lit_comp("union"), }; C_LINKAGE_END ================================================ FILE: src/text/generated/text.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef TEXT_META_H #define TEXT_META_H typedef enum TXT_LangKind { TXT_LangKind_Null, TXT_LangKind_C, TXT_LangKind_CPlusPlus, TXT_LangKind_Odin, TXT_LangKind_Jai, TXT_LangKind_Zig, TXT_LangKind_Rust, TXT_LangKind_DisasmX64Intel, TXT_LangKind_COUNT, } TXT_LangKind; C_LINKAGE_BEGIN extern String8 txt_lang_kind_ext_table[8]; extern String8Array txt_keywords_from_lang_kind_table[8]; extern String8Array txt_multichar_symbols_from_lang_kind_table[8]; extern TXT_TokenizerRuleArray txt_tokenizer_rules_from_lang_kind_table[8]; extern String8 txt_keywords__null[1]; extern String8 txt_multichar_symbols__null[1]; extern TXT_TokenizerRule txt_tokenizer_rules__null[1]; extern String8 txt_keywords__c[32]; extern String8 txt_multichar_symbols__c[20]; extern TXT_TokenizerRule txt_tokenizer_rules__c[7]; extern String8 txt_keywords__cpp[97]; extern String8 txt_keywords__odin[40]; extern String8 txt_keywords__jai[39]; extern String8 txt_keywords__zig[49]; extern String8 txt_keywords__rust[43]; C_LINKAGE_END #endif // TEXT_META_H ================================================ FILE: src/text/text.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xe34cd4ff //////////////////////////////// //~ rjf: Generated Code #include "generated/text.meta.c" //////////////////////////////// //~ rjf: Basic Helpers internal TXT_LangKind txt_lang_kind_from_extension(String8 extension) { TXT_LangKind kind = TXT_LangKind_Null; for EachElement(idx, txt_ext_lang_kind_table) { if(str8_match(extension, txt_ext_lang_kind_table[idx].ext, 0)) { kind = txt_ext_lang_kind_table[idx].kind; break; } } return kind; } internal String8 txt_extension_from_lang_kind(TXT_LangKind kind) { String8 result = txt_lang_kind_ext_table[kind]; return result; } internal TXT_LangKind txt_lang_kind_from_arch(Arch arch) { TXT_LangKind kind = TXT_LangKind_Null; switch(arch) { default:{}break; case Arch_x64:{kind = TXT_LangKind_DisasmX64Intel;}break; } return kind; } internal TXT_LangLexFunctionType * txt_lex_function_from_lang_kind(TXT_LangKind kind) { TXT_LangLexFunctionType *fn = 0; switch(kind) { default:{}break; case TXT_LangKind_C: {fn = txt_token_array_from_string__c_cpp;}break; case TXT_LangKind_CPlusPlus: {fn = txt_token_array_from_string__c_cpp;}break; case TXT_LangKind_Odin: {fn = txt_token_array_from_string__odin;}break; case TXT_LangKind_Jai: {fn = txt_token_array_from_string__jai;}break; case TXT_LangKind_Zig: {fn = txt_token_array_from_string__zig;}break; case TXT_LangKind_Rust: {fn = txt_token_array_from_string__rust;}break; case TXT_LangKind_DisasmX64Intel:{fn = txt_token_array_from_string__disasm_x64_intel;}break; } return fn; } //////////////////////////////// //~ rjf: Token Type Functions internal void txt_token_chunk_list_push(Arena *arena, TXT_TokenChunkList *list, U64 cap, TXT_Token *token) { TXT_TokenChunkNode *node = list->last; if(node == 0 || node->count >= node->cap) { node = push_array(arena, TXT_TokenChunkNode, 1); SLLQueuePush(list->first, list->last, node); node->cap = cap; node->v = push_array_no_zero(arena, TXT_Token, node->cap); list->chunk_count += 1; } MemoryCopyStruct(&node->v[node->count], token); node->count += 1; list->token_count += 1; } internal void txt_token_list_push(Arena *arena, TXT_TokenList *list, TXT_Token *token) { TXT_TokenNode *node = push_array(arena, TXT_TokenNode, 1); MemoryCopyStruct(&node->v, token); SLLQueuePush(list->first, list->last, node); list->count += 1; } internal TXT_TokenArray txt_token_array_from_chunk_list(Arena *arena, TXT_TokenChunkList *list) { TXT_TokenArray array = {0}; array.count = list->token_count; array.v = push_array_no_zero(arena, TXT_Token, array.count); U64 idx = 0; for(TXT_TokenChunkNode *n = list->first; n != 0; n = n->next) { MemoryCopy(array.v+idx, n->v, n->count*sizeof(TXT_Token)); idx += n->count; } return array; } internal TXT_TokenArray txt_token_array_from_list(Arena *arena, TXT_TokenList *list) { TXT_TokenArray array = {0}; array.count = list->count; array.v = push_array_no_zero(arena, TXT_Token, array.count); U64 idx = 0; for(TXT_TokenNode *n = list->first; n != 0; n = n->next) { MemoryCopyStruct(array.v+idx, &n->v); idx += 1; } return array; } //////////////////////////////// //~ rjf: Lexing Functions internal TXT_TokenArray txt_token_array_from_lang_kind_string(Arena *arena, TXT_LangKind lang_kind, String8 string) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 chunk_size = Clamp(8, string.size/8, 4096); //- rjf: gather keywords U64 keyword_slots_count = txt_keywords_from_lang_kind_table[lang_kind].count; String8Node **keyword_slots = push_array(scratch.arena, String8Node *, keyword_slots_count); for EachIndex(idx, txt_keywords_from_lang_kind_table[lang_kind].count) { String8 keyword = txt_keywords_from_lang_kind_table[lang_kind].v[idx]; U64 hash = u64_hash_from_str8(keyword); U64 slot_idx = hash%keyword_slots_count; String8Node *n = push_array(scratch.arena, String8Node, 1); SLLStackPush(keyword_slots[slot_idx], n); n->string = keyword; } //- rjf: gather multichar symbols String8Array multichar_symbols = txt_multichar_symbols_from_lang_kind_table[lang_kind]; //- rjf: gather rules U64 tokenizer_rule_slots_count = txt_tokenizer_rules_from_lang_kind_table[lang_kind].count; TXT_TokenizerRulePtrNode **tokenizer_rule_opener_slots = push_array(scratch.arena, TXT_TokenizerRulePtrNode *, tokenizer_rule_slots_count); TXT_TokenizerRulePtrNode **tokenizer_rule_closer_slots = push_array(scratch.arena, TXT_TokenizerRulePtrNode *, tokenizer_rule_slots_count); { TXT_TokenizerRuleArray rules = txt_tokenizer_rules_from_lang_kind_table[lang_kind]; for EachIndex(idx, rules.count) { TXT_TokenizerRule *r = &rules.v[idx]; U64 open_hash = u64_hash_from_str8(r->open_string); U64 close_hash = u64_hash_from_str8(r->close_string); U64 open_slot_idx = open_hash%tokenizer_rule_slots_count; U64 close_slot_idx = close_hash%tokenizer_rule_slots_count; TXT_TokenizerRulePtrNode *open_n = push_array(scratch.arena, TXT_TokenizerRulePtrNode, 1); TXT_TokenizerRulePtrNode *close_n = push_array(scratch.arena, TXT_TokenizerRulePtrNode, 1); open_n->v = r; close_n->v = r; SLLStackPush(tokenizer_rule_opener_slots[open_slot_idx], open_n); SLLStackPush(tokenizer_rule_closer_slots[close_slot_idx], close_n); } } //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { typedef struct TokenTask TokenTask; struct TokenTask { TokenTask *next; TXT_TokenizerRule *rule; TXT_TokenKind kind; U64 start_idx; }; TXT_TokenizerRule *nil_rule = &txt_tokenizer_rules__null[0]; TokenTask *top_task = 0; TokenTask *free_task = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: unpack next bytes U8 next_bytes[] = {byte, next_byte}; String8 string_1byte = str8(next_bytes, 1); String8 string_2byte = str8(next_bytes, 2); // rjf: update counter if((idx-byte_process_start_idx) >= 1000 || idx == string.size) { add_progress(idx - byte_process_start_idx); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take token starters B32 new_token_needed = (top_task == 0); TXT_TokenizerRule *new_rule = nil_rule; TXT_TokenKind new_token_kind = TXT_TokenKind_Null; { // rjf: use next bytes to look up a rule from the table { TXT_TokenizerRule *active_rule = top_task ? top_task->rule : nil_rule; U64 hash_1byte = u64_hash_from_str8(string_1byte); U64 hash_2byte = u64_hash_from_str8(string_2byte); U64 slot_1byte = hash_1byte%tokenizer_rule_slots_count; U64 slot_2byte = hash_2byte%tokenizer_rule_slots_count; if(new_rule == nil_rule) { for EachNode(n, TXT_TokenizerRulePtrNode, tokenizer_rule_opener_slots[slot_2byte]) { TXT_TokenizerRule *n_parent_rule = nil_rule; if(0 < n->v->parent_num && n->v->parent_num <= txt_tokenizer_rules_from_lang_kind_table[lang_kind].count) { n_parent_rule = &txt_tokenizer_rules_from_lang_kind_table[lang_kind].v[n->v->parent_num-1]; } if(str8_match(n->v->open_string, string_2byte, 0) && active_rule == n_parent_rule) { new_rule = n->v; break; } } } if(new_rule == nil_rule) { for EachNode(n, TXT_TokenizerRulePtrNode, tokenizer_rule_opener_slots[slot_1byte]) { TXT_TokenizerRule *n_parent_rule = nil_rule; if(0 < n->v->parent_num && n->v->parent_num <= txt_tokenizer_rules_from_lang_kind_table[lang_kind].count) { n_parent_rule = &txt_tokenizer_rules_from_lang_kind_table[lang_kind].v[n->v->parent_num-1]; } if(str8_match(n->v->open_string, string_1byte, 0) && active_rule == n_parent_rule) { new_rule = n->v; break; } } } if(new_rule != nil_rule) { new_token_kind = new_rule->token_kind; } } // rjf: use next bytes to start a new token based on fallback rules if(top_task == 0 && new_rule == nil_rule) { if(0){} else if(char_is_space(byte)) { new_token_kind = TXT_TokenKind_Whitespace; } else if(byte == '_' || byte == '$' || char_is_alpha(byte)) { new_token_kind = TXT_TokenKind_Identifier; } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { new_token_kind = TXT_TokenKind_Numeric; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { new_token_kind = TXT_TokenKind_Symbol; } } } // rjf: look for ender based on rule's closing symbol U64 ender_pad = 0; B32 ender_found = 0; if(top_task != 0 && idx > top_task->start_idx) { TXT_TokenKind active_token_kind = top_task->kind; TXT_TokenizerRule *active_rule = top_task->rule; U64 active_token_start_idx = top_task->start_idx; if(idx == string.size) { ender_pad = 0; ender_found = 1; } else if(active_rule != nil_rule && (str8_match(string_1byte, active_rule->close_string, 0) || str8_match(string_2byte, active_rule->close_string, 0))) { ender_found = 1; ender_pad = active_rule->close_advance; } else switch(active_token_kind) { default:{}break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|'); }break; } } // rjf: if we have a new token to start, but we have an active token, then // end the current token (but keep the same stack) B32 keep_top_task = 0; if(top_task != 0 && new_token_kind != TXT_TokenKind_Null && idx > top_task->start_idx) { keep_top_task = (!ender_found); ender_found = 1; } // rjf: if we have an ender => emit token(s) for current task if(ender_found) { TXT_Token token = {top_task->kind, r1u64(top_task->start_idx, idx+ender_pad)}; if(!keep_top_task) { TokenTask *popped = top_task; SLLStackPop(top_task); SLLStackPush(free_task, popped); if(top_task != 0) { top_task->start_idx = idx+ender_pad; } } else { top_task->start_idx = idx+ender_pad; } // rjf: trim \r's off of end { String8 token_string = str8_substr(string, token.range); if(token_string.size != 0 && token_string.str[token_string.size-1] == '\r') { token.range.max -= 1; ender_pad += 1; } } // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { String8 token_string = str8_substr(string, token.range); U64 hash = u64_hash_from_str8(token_string); U64 slot_idx = hash%keyword_slots_count; for EachNode(n, String8Node, keyword_slots[slot_idx]) { if(str8_match(token_string, n->string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { String8 token_string = str8_substr(string, token.range); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < multichar_symbols.count; idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+multichar_symbols.v[idx].size)), multichar_symbols.v[idx], 0)) { found = 1; next_off = off + Max(1, multichar_symbols.v[idx].size); TXT_Token sub_token = {TXT_TokenKind_Symbol, r1u64(token.range.min+off, token.range.min+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &sub_token); break; } } if(!found) { next_off = off+1; TXT_Token sub_token = {TXT_TokenKind_Symbol, r1u64(token.range.min+off, token.range.min+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &sub_token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } } // rjf: start new token if(new_token_kind != TXT_TokenKind_Null) { TokenTask *task = free_task; if(task != 0) { SLLStackPop(free_task); } else { task = push_array(scratch.arena, TokenTask, 1); } SLLStackPush(top_task, task); top_task->rule = new_rule; top_task->kind = new_token_kind; top_task->start_idx = idx; } // rjf: invalid token kind -> emit error else if(new_token_needed) { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } // rjf: advance by ender padding idx += ender_pad; // rjf: advance escaping escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); ProfEnd(); return result; } internal TXT_TokenArray txt_token_array_from_string__c_cpp(Arena *arena, U64 *bytes_processed_counter, String8 string) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); U64 chunk_size = Clamp(8, string.size/8, 4096); //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { B32 comment_is_single_line = 0; B32 string_is_char = 0; TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_idx = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: update counter if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size)) { ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx)); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take starter, determine active token kind if(active_token_kind == TXT_TokenKind_Null) { // rjf: use next bytes to start a new token if(0){} else if(char_is_space(byte)) { active_token_kind = TXT_TokenKind_Whitespace; } else if(byte == '_' || byte == '$' || char_is_alpha(byte)) { active_token_kind = TXT_TokenKind_Identifier; } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { active_token_kind = TXT_TokenKind_Numeric; } else if(byte == '"') { active_token_kind = TXT_TokenKind_String; string_is_char = 0; } else if(byte == '\'') { active_token_kind = TXT_TokenKind_String; string_is_char = 1; } else if(byte == '/' && next_byte == '/') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 1; } else if(byte == '/' && next_byte == '*') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 0; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { active_token_kind = TXT_TokenKind_Symbol; } else if(byte == '#') { active_token_kind = TXT_TokenKind_Meta; } // rjf: start new token if(active_token_kind != TXT_TokenKind_Null) { active_token_start_idx = idx; } // rjf: invalid token kind -> emit error else { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } } // rjf: look for ender U64 ender_pad = 0; B32 ender_found = 0; if(active_token_kind != TXT_TokenKind_Null && idx>active_token_start_idx) { if(idx == string.size) { ender_pad = 0; ender_found = 1; } else switch(active_token_kind) { default:break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_String: { ender_found = (!escaped && ((!string_is_char && byte == '"') || (string_is_char && byte == '\''))); ender_pad += 1; }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|'); }break; case TXT_TokenKind_Comment: { if(comment_is_single_line) { ender_found = (!escaped && (byte == '\r' || byte == '\n')); } else { ender_found = (active_token_start_idx+1 < idx && byte == '*' && next_byte == '/'); ender_pad += 2; } }break; case TXT_TokenKind_Meta: { ender_found = (!escaped && (byte == '\r' || byte == '\n')); }break; } } // rjf: next byte is ender => emit token if(ender_found) { TXT_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)}; active_token_kind = TXT_TokenKind_Null; // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { read_only local_persist String8 cpp_keywords[] = { str8_lit_comp("alignas"), str8_lit_comp("alignof"), str8_lit_comp("and"), str8_lit_comp("and_eq"), str8_lit_comp("asm"), str8_lit_comp("atomic_cancel"), str8_lit_comp("atomic_commit"), str8_lit_comp("atomic_noexcept"), str8_lit_comp("auto"), str8_lit_comp("bitand"), str8_lit_comp("bitor"), str8_lit_comp("bool"), str8_lit_comp("break"), str8_lit_comp("case"), str8_lit_comp("catch"), str8_lit_comp("char"), str8_lit_comp("char8_t"), str8_lit_comp("char16_t"), str8_lit_comp("char32_t"), str8_lit_comp("class"), str8_lit_comp("compl"), str8_lit_comp("concept"), str8_lit_comp("const"), str8_lit_comp("consteval"), str8_lit_comp("constexpr"), str8_lit_comp("constinit"), str8_lit_comp("const_cast"), str8_lit_comp("continue"), str8_lit_comp("co_await"), str8_lit_comp("co_return"), str8_lit_comp("co_yield"), str8_lit_comp("decltype"), str8_lit_comp("default"), str8_lit_comp("delete"), str8_lit_comp("do"), str8_lit_comp("double"), str8_lit_comp("dynamic_cast"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("explicit"), str8_lit_comp("export"), str8_lit_comp("extern"), str8_lit_comp("false"), str8_lit_comp("float"), str8_lit_comp("for"), str8_lit_comp("friend"), str8_lit_comp("goto"), str8_lit_comp("if"), str8_lit_comp("inline"), str8_lit_comp("int"), str8_lit_comp("long"), str8_lit_comp("mutable"), str8_lit_comp("namespace"), str8_lit_comp("new"), str8_lit_comp("noexcept"), str8_lit_comp("not"), str8_lit_comp("not_eq"), str8_lit_comp("nullptr"), str8_lit_comp("operator"), str8_lit_comp("or"), str8_lit_comp("or_eq"), str8_lit_comp("private"), str8_lit_comp("protected"), str8_lit_comp("public"), str8_lit_comp("reflexpr"), str8_lit_comp("register"), str8_lit_comp("reinterpret_cast"), str8_lit_comp("requires"), str8_lit_comp("return"), str8_lit_comp("short"), str8_lit_comp("signed"), str8_lit_comp("sizeof"), str8_lit_comp("static"), str8_lit_comp("static_assert"), str8_lit_comp("static_cast"), str8_lit_comp("struct"), str8_lit_comp("switch"), str8_lit_comp("synchronized"), str8_lit_comp("template"), str8_lit_comp("this"), str8_lit_comp("thread_local"), str8_lit_comp("throw"), str8_lit_comp("true"), str8_lit_comp("try"), str8_lit_comp("typedef"), str8_lit_comp("typeid"), str8_lit_comp("typename"), str8_lit_comp("union"), str8_lit_comp("unsigned"), str8_lit_comp("using"), str8_lit_comp("virtual"), str8_lit_comp("void"), str8_lit_comp("volatile"), str8_lit_comp("wchar_t"), str8_lit_comp("while"), str8_lit_comp("xor"), str8_lit_comp("xor_eq"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 keyword_idx = 0; keyword_idx < ArrayCount(cpp_keywords); keyword_idx += 1) { if(str8_match(cpp_keywords[keyword_idx], token_string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { read_only local_persist String8 c_cpp_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < ArrayCount(c_cpp_multichar_symbol_strings); idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+c_cpp_multichar_symbol_strings[idx].size)), c_cpp_multichar_symbol_strings[idx], 0)) { found = 1; next_off = off + c_cpp_multichar_symbol_strings[idx].size; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); break; } } if(!found) { next_off = off+1; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, chunk_size, &token); } // rjf: increment by ender padding idx += ender_pad; } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); ProfEnd(); return result; } internal TXT_TokenArray txt_token_array_from_string__odin(Arena *arena, U64 *bytes_processed_counter, String8 string) { Temp scratch = scratch_begin(&arena, 1); //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { B32 comment_is_single_line = 0; B32 string_is_char = 0; TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_idx = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: update counter if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size)) { ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx)); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take starter, determine active token kind if(active_token_kind == TXT_TokenKind_Null) { // rjf: use next bytes to start a new token if(0){} else if(char_is_space(byte)) { active_token_kind = TXT_TokenKind_Whitespace; } else if(byte == '_' || byte == '$' || char_is_alpha(byte)) { active_token_kind = TXT_TokenKind_Identifier; } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { active_token_kind = TXT_TokenKind_Numeric; } else if(byte == '"') { active_token_kind = TXT_TokenKind_String; string_is_char = 0; } else if(byte == '\'') { active_token_kind = TXT_TokenKind_String; string_is_char = 1; } else if(byte == '/' && next_byte == '/') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 1; } else if(byte == '/' && next_byte == '*') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 0; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { active_token_kind = TXT_TokenKind_Symbol; } else if(byte == '#') { active_token_kind = TXT_TokenKind_Meta; } // rjf: start new token if(active_token_kind != TXT_TokenKind_Null) { active_token_start_idx = idx; } // rjf: invalid token kind -> emit error else { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } // rjf: look for ender U64 ender_pad = 0; B32 ender_found = 0; if(active_token_kind != TXT_TokenKind_Null && idx>active_token_start_idx) { if(idx == string.size) { ender_pad = 0; ender_found = 1; } else switch(active_token_kind) { default:break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_String: { ender_found = (!escaped && ((!string_is_char && byte == '"') || (string_is_char && byte == '\''))); ender_pad += 1; }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|'); }break; case TXT_TokenKind_Comment: { if(comment_is_single_line) { ender_found = (!escaped && (byte == '\r' || byte == '\n')); } else { ender_found = (active_token_start_idx+1 < idx && byte == '*' && next_byte == '/'); ender_pad += 2; } }break; case TXT_TokenKind_Meta: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$'); }break; } } // rjf: next byte is ender => emit token if(ender_found) { TXT_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)}; active_token_kind = TXT_TokenKind_Null; // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { read_only local_persist String8 odin_keywords[] = { str8_lit_comp("align_of"), str8_lit_comp("asm"), str8_lit_comp("auto_cast"), str8_lit_comp("bit_set"), str8_lit_comp("break"), str8_lit_comp("case"), str8_lit_comp("cast"), str8_lit_comp("context"), str8_lit_comp("continue"), str8_lit_comp("defer"), str8_lit_comp("distinct"), str8_lit_comp("do"), str8_lit_comp("dynamic"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("fallthrough"), str8_lit_comp("for"), str8_lit_comp("foreign"), str8_lit_comp("if"), str8_lit_comp("in"), str8_lit_comp("map"), str8_lit_comp("matrix"), str8_lit_comp("not_in"), str8_lit_comp("or_break"), str8_lit_comp("or_continue"), str8_lit_comp("or_else"), str8_lit_comp("or_return"), str8_lit_comp("package"), str8_lit_comp("proc"), str8_lit_comp("return"), str8_lit_comp("size_of"), str8_lit_comp("struct"), str8_lit_comp("switch"), str8_lit_comp("transmute"), str8_lit_comp("typeid"), str8_lit_comp("union"), str8_lit_comp("using"), str8_lit_comp("when"), str8_lit_comp("where"), str8_lit_comp("import"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 keyword_idx = 0; keyword_idx < ArrayCount(odin_keywords); keyword_idx += 1) { if(str8_match(odin_keywords[keyword_idx], token_string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { read_only local_persist String8 odin_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < ArrayCount(odin_multichar_symbol_strings); idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+odin_multichar_symbol_strings[idx].size)), odin_multichar_symbol_strings[idx], 0)) { found = 1; next_off = off + odin_multichar_symbol_strings[idx].size; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); break; } } if(!found) { next_off = off+1; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: increment by ender padding idx += ender_pad; } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return result; } internal TXT_TokenArray txt_token_array_from_string__jai(Arena *arena, U64 *bytes_processed_counter, String8 string) { Temp scratch = scratch_begin(&arena, 1); //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { B32 comment_is_single_line = 0; B32 string_is_char = 0; TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_idx = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: update counter if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size)) { ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx)); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take starter, determine active token kind if(active_token_kind == TXT_TokenKind_Null) { // rjf: use next bytes to start a new token if(0){} else if(char_is_space(byte)) { active_token_kind = TXT_TokenKind_Whitespace; } else if(byte == '_' || byte == '$' || char_is_alpha(byte)) { active_token_kind = TXT_TokenKind_Identifier; } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { active_token_kind = TXT_TokenKind_Numeric; } else if(byte == '"') { active_token_kind = TXT_TokenKind_String; string_is_char = 0; } else if(byte == '\'') { active_token_kind = TXT_TokenKind_String; string_is_char = 1; } else if(byte == '/' && next_byte == '/') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 1; } else if(byte == '/' && next_byte == '*') { active_token_kind = TXT_TokenKind_Comment; comment_is_single_line = 0; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { active_token_kind = TXT_TokenKind_Symbol; } else if(byte == '#') { active_token_kind = TXT_TokenKind_Meta; } // rjf: start new token if(active_token_kind != TXT_TokenKind_Null) { active_token_start_idx = idx; } // rjf: invalid token kind -> emit error else { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } // rjf: look for ender U64 ender_pad = 0; B32 ender_found = 0; if(active_token_kind != TXT_TokenKind_Null && idx>active_token_start_idx) { if(idx == string.size) { ender_pad = 0; ender_found = 1; } else switch(active_token_kind) { default:break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_String: { ender_found = (!escaped && ((!string_is_char && byte == '"') || (string_is_char && byte == '\''))); ender_pad += 1; }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|'); }break; case TXT_TokenKind_Comment: { if(comment_is_single_line) { ender_found = (!escaped && (byte == '\r' || byte == '\n')); } else { ender_found = (active_token_start_idx+1 < idx && byte == '*' && next_byte == '/'); ender_pad += 2; } }break; case TXT_TokenKind_Meta: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$'); }break; } } // rjf: next byte is ender => emit token if(ender_found) { TXT_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)}; active_token_kind = TXT_TokenKind_Null; // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { read_only local_persist String8 jai_keywords[] = { str8_lit_comp("bool"), str8_lit_comp("true"), str8_lit_comp("false"), str8_lit_comp("int"), str8_lit_comp("s8"), str8_lit_comp("u8"), str8_lit_comp("s16"), str8_lit_comp("u16"), str8_lit_comp("s32"), str8_lit_comp("u32"), str8_lit_comp("s64"), str8_lit_comp("u64"), str8_lit_comp("s128"), str8_lit_comp("u128"), str8_lit_comp("float"), str8_lit_comp("float32"), str8_lit_comp("float64"), str8_lit_comp("void"), str8_lit_comp("enum"), str8_lit_comp("enum_flags"), str8_lit_comp("size_of"), str8_lit_comp("string"), str8_lit_comp("type_of"), str8_lit_comp("cast"), str8_lit_comp("if"), str8_lit_comp("ifs"), str8_lit_comp("then"), str8_lit_comp("else"), str8_lit_comp("case"), str8_lit_comp("for"), str8_lit_comp("while"), str8_lit_comp("break"), str8_lit_comp("continue"), str8_lit_comp("remove"), str8_lit_comp("return"), str8_lit_comp("inline"), str8_lit_comp("null"), str8_lit_comp("defer"), str8_lit_comp("xx"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 keyword_idx = 0; keyword_idx < ArrayCount(jai_keywords); keyword_idx += 1) { if(str8_match(jai_keywords[keyword_idx], token_string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { read_only local_persist String8 jai_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < ArrayCount(jai_multichar_symbol_strings); idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+jai_multichar_symbol_strings[idx].size)), jai_multichar_symbol_strings[idx], 0)) { found = 1; next_off = off + jai_multichar_symbol_strings[idx].size; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); break; } } if(!found) { next_off = off+1; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: increment by ender padding idx += ender_pad; } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return result; } internal TXT_TokenArray txt_token_array_from_string__zig(Arena *arena, U64 *bytes_processed_counter, String8 string) { Temp scratch = scratch_begin(&arena, 1); //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { B32 string_is_char = 0; B32 string_is_line = 0; TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_idx = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: update counter if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size)) { ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx)); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take starter, determine active token kind if(active_token_kind == TXT_TokenKind_Null) { // rjf: use next bytes to start a new token if(0){} else if(char_is_space(byte)) { active_token_kind = TXT_TokenKind_Whitespace; } else if(byte == '_' || char_is_alpha(byte)) { active_token_kind = TXT_TokenKind_Identifier; } else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { active_token_kind = TXT_TokenKind_Numeric; } else if(byte == '"') { active_token_kind = TXT_TokenKind_String; string_is_char = 0; } else if(byte == '\'') { active_token_kind = TXT_TokenKind_String; string_is_char = 1; } else if(byte == '\\' && next_byte == '\\') { active_token_kind = TXT_TokenKind_String; string_is_line = 1; } else if(byte == '/' && next_byte == '/') { active_token_kind = TXT_TokenKind_Comment; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|' || byte == 'c') { active_token_kind = TXT_TokenKind_Symbol; } // rjf: start new token if(active_token_kind != TXT_TokenKind_Null) { active_token_start_idx = idx; } // rjf: invalid token kind -> emit error else { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } // rjf: look for ender U64 ender_pad = 0; B32 ender_found = 0; if(active_token_kind != TXT_TokenKind_Null && idx>active_token_start_idx) { if(idx == string.size) { ender_pad = 0; ender_found = 1; } else switch(active_token_kind) { default:break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_String: { if (string_is_line) { ender_found = (!escaped && (byte == '\r' || byte == '\n')); } else { ender_found = (!escaped && ((!string_is_char && byte == '"') || (string_is_char && byte == '\''))); ender_pad += 1; } }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|' && byte != 'c'); }break; case TXT_TokenKind_Comment: { ender_found = (!escaped && (byte == '\r' || byte == '\n')); }break; } } // rjf: next byte is ender => emit token if(ender_found) { TXT_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)}; active_token_kind = TXT_TokenKind_Null; // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { read_only local_persist String8 zig_keywords[] = { str8_lit_comp("addrspace"), str8_lit_comp("align"), str8_lit_comp("allowzero"), str8_lit_comp("and"), str8_lit_comp("anyframe"), str8_lit_comp("anytype"), str8_lit_comp("asm"), str8_lit_comp("async"), str8_lit_comp("await"), str8_lit_comp("break"), str8_lit_comp("callconv"), str8_lit_comp("catch"), str8_lit_comp("comptime"), str8_lit_comp("const"), str8_lit_comp("continue"), str8_lit_comp("defer"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("errdefer"), str8_lit_comp("error"), str8_lit_comp("export"), str8_lit_comp("extern"), str8_lit_comp("fn"), str8_lit_comp("for"), str8_lit_comp("if"), str8_lit_comp("inline"), str8_lit_comp("noalias"), str8_lit_comp("nosuspend"), str8_lit_comp("noinline"), str8_lit_comp("opaque"), str8_lit_comp("or"), str8_lit_comp("orelse"), str8_lit_comp("packed"), str8_lit_comp("pub"), str8_lit_comp("resume"), str8_lit_comp("return"), str8_lit_comp("linksection"), str8_lit_comp("struct"), str8_lit_comp("suspend"), str8_lit_comp("switch"), str8_lit_comp("test"), str8_lit_comp("threadlocal"), str8_lit_comp("try"), str8_lit_comp("union"), str8_lit_comp("unreachable"), str8_lit_comp("usingnamespace"), str8_lit_comp("var"), str8_lit_comp("volatile"), str8_lit_comp("while"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 keyword_idx = 0; keyword_idx < ArrayCount(zig_keywords); keyword_idx += 1) { if(str8_match(zig_keywords[keyword_idx], token_string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { read_only local_persist String8 zig_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < ArrayCount(zig_multichar_symbol_strings); idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+zig_multichar_symbol_strings[idx].size)), zig_multichar_symbol_strings[idx], 0)) { found = 1; next_off = off + zig_multichar_symbol_strings[idx].size; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); break; } } if(!found) { next_off = off+1; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: increment by ender padding idx += ender_pad; } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return result; } internal TXT_TokenArray txt_token_array_from_string__rust(Arena *arena, U64 *bytes_processed_counter, String8 string) { // NOTE(spey): Rust supports unicode identifiers. They are not handled in any way here, // but it might be worth looking into in the future. Temp scratch = scratch_begin(&arena, 1); //- rjf: generate token list TXT_TokenChunkList tokens = {0}; { S32 multiline_comment_nesting_level = 0; S32 raw_string_nesting_level = 0; S32 raw_string_ender_nesting_level = 0; // NOTE(spey): Rust's syntax is designed in such a way that we can't be sure what a token // is immediately from the first character, so we have to keep track of some possibilities. B32 token_may_be_char = 0; B32 token_may_be_lifetime = 0; B32 token_may_be_string = 0; TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_idx = 0; B32 escaped = 0; B32 next_escaped = 0; U64 byte_process_start_idx = 0; for(U64 idx = 0; idx <= string.size;) { U8 byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; U8 next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: update counter if(bytes_processed_counter != 0 && ((idx-byte_process_start_idx) >= 1000 || idx == string.size)) { ins_atomic_u64_add_eval(bytes_processed_counter, (idx-byte_process_start_idx)); byte_process_start_idx = idx; } // rjf: escaping if(escaped && (byte != '\r' && byte != '\n')) { next_escaped = 0; } else if(!escaped && byte == '\\') { next_escaped = 1; } // rjf: take starter, determine active token kind U64 starter_pad = 0; // spey: special case of starter for nested comments if(active_token_kind == TXT_TokenKind_Comment) { if(byte == '/' && next_byte == '*') { active_token_kind = TXT_TokenKind_Comment; multiline_comment_nesting_level++; starter_pad = 1; } } // spey: special case of starter for raw string literals else if(active_token_kind == TXT_TokenKind_Identifier && token_may_be_string) { if(0){} else if(byte == 'r' && next_byte == '#') {} // spey: still an identifier that may be a string (this branch triggers for raw byte/C string literals) else if(byte == '#' && next_byte == '"') { active_token_kind = TXT_TokenKind_String; token_may_be_string = 0; token_may_be_char = 0; raw_string_nesting_level++; starter_pad = 2; } else if(byte == '#' && next_byte == '#') { raw_string_nesting_level++; } else { token_may_be_string = 0; token_may_be_char = 0; raw_string_nesting_level = 0; } // spey: confirmed raw identifier } // spey: regular cases else if(active_token_kind == TXT_TokenKind_Null) { // rjf: use next bytes to start a new token if(0){} else if(char_is_space(byte)) { active_token_kind = TXT_TokenKind_Whitespace; } else if(byte == 'r' && next_byte == '#') { active_token_kind = TXT_TokenKind_Identifier; token_may_be_string = 1; } // spey: either raw identifiers or raw string literals else if(char_is_digit(byte, 10) || (byte == '.' && char_is_digit(next_byte, 10))) { active_token_kind = TXT_TokenKind_Numeric; } else if(byte == '"') { active_token_kind = TXT_TokenKind_String; token_may_be_char = 0; } else if((byte == 'c' || byte == 'b') && next_byte == '"') { active_token_kind = TXT_TokenKind_String; token_may_be_char = 0; starter_pad = 1; } else if((byte == 'c' || byte == 'b') && next_byte == 'r') { active_token_kind = TXT_TokenKind_Identifier; token_may_be_string = 1; } else if(byte == '_' || char_is_alpha(byte)) { active_token_kind = TXT_TokenKind_Identifier; } else if(byte == '/' && next_byte == '/') { active_token_kind = TXT_TokenKind_Comment; starter_pad = 1; } else if(byte == '/' && next_byte == '*') { active_token_kind = TXT_TokenKind_Comment; starter_pad = 1; multiline_comment_nesting_level++; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ':' || byte == ';' || byte == ',' || byte == '.' || byte == '<' || byte == '>' || byte == '/' || byte == '?' || byte == '|') { active_token_kind = TXT_TokenKind_Symbol; } else if(byte == '\'') { active_token_kind = TXT_TokenKind_String; token_may_be_char = 1; token_may_be_lifetime = 1; } else if((byte == 'c' || byte == 'b') && next_byte == '\'') { active_token_kind = TXT_TokenKind_String; token_may_be_char = 1; starter_pad = 1; } // rjf: start new token if(active_token_kind != TXT_TokenKind_Null) { active_token_start_idx = idx; } // rjf: invalid token kind -> emit error else { TXT_Token token = {TXT_TokenKind_Error, r1u64(idx, idx+1)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } B32 is_on_starter = idx <= active_token_start_idx || token_may_be_string; // spey: advance by starter padding byte(s) and reset byte/next_byte values idx += starter_pad; byte = (idx+0 < string.size) ? (string.str[idx+0]) : 0; next_byte = (idx+1 < string.size) ? (string.str[idx+1]) : 0; // rjf: look for ender U64 ender_pad = 0; B32 ender_found = 0; if(active_token_kind != TXT_TokenKind_Null && !is_on_starter) { if(idx == string.size) { ender_pad = 0; ender_found = 1; } else switch(active_token_kind) { default:break; case TXT_TokenKind_Whitespace: { ender_found = !char_is_space(byte); }break; case TXT_TokenKind_Identifier: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '$' && byte != '#' && byte != '!' && byte < 128); }break; case TXT_TokenKind_Numeric: { ender_found = (!char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte != '.' && byte != '\''); }break; case TXT_TokenKind_String: { if(!escaped) { if(token_may_be_char) { if(byte == '\'') { // spey: char ending ender_found = 1; } else if(token_may_be_lifetime && !char_is_alpha(byte) && !char_is_digit(byte, 10) && byte != '_' && byte < 128) { // spey: lifetime ending ender_found = 1; } } else { if(0){} // spey: regular string else if(raw_string_nesting_level == 0) { ender_found = byte == '"'; } // spey: raw string else if(byte == '"' && next_byte == '#' && raw_string_ender_nesting_level == 0) { raw_string_ender_nesting_level++; } else if(byte == '#' && next_byte != '#' && raw_string_ender_nesting_level == raw_string_nesting_level && raw_string_ender_nesting_level >= 0) { ender_found = 1; raw_string_nesting_level = 0; raw_string_ender_nesting_level = 0; } else if(byte == '#' && next_byte != '#' && raw_string_ender_nesting_level >= 0) { raw_string_ender_nesting_level = 0; } else if(byte == '#' && raw_string_ender_nesting_level >= 0) { raw_string_ender_nesting_level++; } } } ender_pad += 1; }break; case TXT_TokenKind_Symbol: { ender_found = (byte != '~' && byte != '!' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ':' && byte != ';' && byte != ',' && byte != '.' && byte != '<' && byte != '>' && byte != '/' && byte != '?' && byte != '|'); }break; case TXT_TokenKind_Comment: { if(multiline_comment_nesting_level == 0) { ender_found = (byte == '\r' || byte == '\n'); } else { if (byte == '*' && next_byte == '/') multiline_comment_nesting_level--; ender_found = (active_token_start_idx+1 < idx && multiline_comment_nesting_level == 0); ender_pad += 2; } }break; } } // rjf: next byte is ender => emit token if(ender_found) { TXT_Token token = {active_token_kind, r1u64(active_token_start_idx, idx+ender_pad)}; active_token_kind = TXT_TokenKind_Null; // rjf: identifier -> keyword in special cases if(token.kind == TXT_TokenKind_Identifier) { read_only local_persist String8 rust_keywords[] = { str8_lit_comp("as"), str8_lit_comp("break"), str8_lit_comp("const"), str8_lit_comp("continue"), str8_lit_comp("crate"), str8_lit_comp("else"), str8_lit_comp("enum"), str8_lit_comp("extern"), str8_lit_comp("false"), str8_lit_comp("fn"), str8_lit_comp("for"), str8_lit_comp("if"), str8_lit_comp("impl"), str8_lit_comp("in"), str8_lit_comp("let"), str8_lit_comp("loop"), str8_lit_comp("match"), str8_lit_comp("mod"), str8_lit_comp("move"), str8_lit_comp("mut"), str8_lit_comp("pub"), str8_lit_comp("ref"), str8_lit_comp("return"), str8_lit_comp("self"), str8_lit_comp("Self"), str8_lit_comp("static"), str8_lit_comp("struct"), str8_lit_comp("super"), str8_lit_comp("trait"), str8_lit_comp("true"), str8_lit_comp("type"), str8_lit_comp("unsafe"), str8_lit_comp("use"), str8_lit_comp("where"), str8_lit_comp("while"), str8_lit_comp("yield"), str8_lit_comp("async"), str8_lit_comp("await"), str8_lit_comp("dyn"), // weak keywords str8_lit_comp("macro_rules"), str8_lit_comp("raw"), str8_lit_comp("safe"), str8_lit_comp("union"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 keyword_idx = 0; keyword_idx < ArrayCount(rust_keywords); keyword_idx += 1) { if(str8_match(rust_keywords[keyword_idx], token_string, 0)) { token.kind = TXT_TokenKind_Keyword; break; } } txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: split symbols by maximum-munch-rule else if(token.kind == TXT_TokenKind_Symbol) { read_only local_persist String8 rust_multichar_symbol_strings[] = { str8_lit_comp("<<"), str8_lit_comp(">>"), str8_lit_comp("<="), str8_lit_comp(">="), str8_lit_comp("=="), str8_lit_comp("!="), str8_lit_comp("&&"), str8_lit_comp("||"), str8_lit_comp("|="), str8_lit_comp("&="), str8_lit_comp("^="), str8_lit_comp("~="), str8_lit_comp("+="), str8_lit_comp("-="), str8_lit_comp("*="), str8_lit_comp("/="), str8_lit_comp("%="), str8_lit_comp("<<="), str8_lit_comp(">>="), str8_lit_comp("->"), }; String8 token_string = str8_substr(string, r1u64(active_token_start_idx, idx+ender_pad)); for(U64 off = 0, next_off = token_string.size; off < token_string.size; off = next_off) { B32 found = 0; for(U64 idx = 0; idx < ArrayCount(rust_multichar_symbol_strings); idx += 1) { if(str8_match(str8_substr(token_string, r1u64(off, off+rust_multichar_symbol_strings[idx].size)), rust_multichar_symbol_strings[idx], 0)) { found = 1; next_off = off + rust_multichar_symbol_strings[idx].size; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); break; } } if(!found) { next_off = off+1; TXT_Token token = {TXT_TokenKind_Symbol, r1u64(active_token_start_idx+off, active_token_start_idx+next_off)}; txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } } } // rjf: all other tokens else { txt_token_chunk_list_push(scratch.arena, &tokens, 4096, &token); } // rjf: increment by starter and ender padding idx += ender_pad; } // rjf: advance by 1 byte if we haven't found an ender if(!ender_found) { idx += 1; } escaped = next_escaped; } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return result; } internal TXT_TokenArray txt_token_array_from_string__disasm_x64_intel(Arena *arena, U64 *bytes_processed_counter, String8 string) { Temp scratch = scratch_begin(&arena, 1); //- rjf: parse tokens TXT_TokenChunkList tokens = {0}; { TXT_TokenKind active_token_kind = TXT_TokenKind_Null; U64 active_token_start_off = 0; U64 off = 0; B32 escaped = 0; B32 string_is_char = 0; S32 brace_nest = 0; S32 paren_nest = 0; S32 string_tick_nest = 0; for(U64 advance = 0; off <= string.size; off += advance) { U8 byte = (off+0 < string.size) ? string.str[off+0] : 0; U8 next_byte = (off+1 < string.size) ? string.str[off+1] : 0; B32 ender_found = 0; advance = (active_token_kind != TXT_TokenKind_Null ? 1 : 0); if(off == string.size && active_token_kind != TXT_TokenKind_Null) { ender_found = 1; advance = 1; } switch(active_token_kind) { default: case TXT_TokenKind_Null: { if(byte == ' ' || byte == '\t' || byte == '\v' || byte == '\f' || byte == '\r' || byte == '\n') { active_token_start_off = off; active_token_kind = TXT_TokenKind_Whitespace; advance = 1; } else if(byte == '>' && brace_nest == 0 && paren_nest == 0) { active_token_start_off = off; active_token_kind = TXT_TokenKind_Comment; advance = 1; } else if(('a' <= byte && byte <= 'z') || ('A' <= byte && byte <= 'Z') || byte == '_') { active_token_start_off = off; active_token_kind = TXT_TokenKind_Keyword; advance = 1; } else if(byte == '\'') { active_token_start_off = off; active_token_kind = TXT_TokenKind_String; advance = 1; string_is_char = 1; } else if(byte == '"') { active_token_start_off = off; active_token_kind = TXT_TokenKind_String; advance = 1; string_is_char = 0; } else if(byte == '`') { active_token_start_off = off; active_token_kind = TXT_TokenKind_String; advance = 1; string_tick_nest += 1; } else if(('0' <= byte && byte <= '9') || (byte == '.' && '0' <= next_byte && next_byte <= '9')) { active_token_start_off = off; active_token_kind = TXT_TokenKind_Numeric; advance = 1; } else if(byte == '~' || byte == '!' || byte == '%' || byte == '^' || byte == '&' || byte == '*' || byte == '(' || byte == ')' || byte == '-' || byte == '=' || byte == '+' || byte == '[' || byte == ']' || byte == '{' || byte == '}' || byte == ';' || byte == ':' || byte == '?' || byte == '/' || byte == '<' || byte == '>' || byte == ',' || byte == '.') { active_token_start_off = off; active_token_kind = TXT_TokenKind_Symbol; advance = 1; if(byte == '{') { brace_nest += 1; } else if(byte == '}') { brace_nest -= 1; } if(byte == '(') { paren_nest += 1; } else if(byte == ')') { paren_nest -= 1; } } else { active_token_start_off = off; active_token_kind = TXT_TokenKind_Error; advance = 1; } }break; case TXT_TokenKind_Whitespace: if(byte != ' ' && byte != '\t' && byte != '\v' && byte != '\f') { ender_found = 1; advance = 0; }break; case TXT_TokenKind_Keyword: if((byte < 'a' || 'z' < byte) && (byte < 'A' || 'Z' < byte) && (byte < '0' || '9' < byte) && byte != '_') { ender_found = 1; advance = 0; }break; case TXT_TokenKind_String: { U8 ender_byte = (string_tick_nest > 0 ? '\'' : string_is_char ? '\'' : '"'); if(!escaped && byte == ender_byte) { if(string_tick_nest > 0) { string_tick_nest -= 1; } if(string_tick_nest == 0) { ender_found = 1; advance = 1; } } else if(escaped) { escaped = 0; advance = 1; } else if(byte == '\\') { escaped = 1; advance = 1; } else if(string_tick_nest > 0 && byte == '`') { string_tick_nest += 1; } else { U8 byte_class = utf8_class[byte>>3]; if(byte_class > 1) { advance = (U64)byte_class; } } }break; case TXT_TokenKind_Numeric: if((byte < 'a' || 'z' < byte) && (byte < 'A' || 'Z' < byte) && (byte < '0' || '9' < byte) && byte != '.') { ender_found = 1; advance = 0; }break; case TXT_TokenKind_Symbol: if(1) { // NOTE(rjf): avoiding maximum munch rule for now ender_found = 1; advance = 0; } else if(byte != '~' && byte != '!' && byte != '#' && byte != '%' && byte != '^' && byte != '&' && byte != '*' && byte != '(' && byte != ')' && byte != '-' && byte != '=' && byte != '+' && byte != '[' && byte != ']' && byte != '{' && byte != '}' && byte != ';' && byte != ':' && byte != '?' && byte != '/' && byte != '<' && byte != '>' && byte != ',' && byte != '.') { ender_found = 1; advance = 0; }break; case TXT_TokenKind_Error: { ender_found = 1; advance = 0; }break; case TXT_TokenKind_Comment: if(byte == '\n') { ender_found = 1; advance = 1; }break; } if(ender_found != 0) { if(brace_nest != 0 && active_token_kind == TXT_TokenKind_Keyword) { active_token_kind = TXT_TokenKind_Numeric; } if(paren_nest != 0 && active_token_kind == TXT_TokenKind_Keyword) { active_token_kind = TXT_TokenKind_Identifier; } TXT_Token token = {active_token_kind, r1u64(active_token_start_off, off+advance)}; txt_token_chunk_list_push(arena, &tokens, 1024, &token); active_token_kind = TXT_TokenKind_Null; active_token_start_off = token.range.max; } } } //- rjf: token list -> token array TXT_TokenArray result = txt_token_array_from_chunk_list(arena, &tokens); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Text Info Extractor Helpers internal U64 txt_off_from_info_pt(TXT_TextInfo *info, TxtPt pt) { U64 off = 0; if(1 <= pt.line && pt.line <= info->lines_count) { Rng1U64 line_range = info->lines_ranges[pt.line-1]; off = line_range.min + (pt.column-1); } return off; } internal TxtPt txt_pt_from_info_off__linear_scan(TXT_TextInfo *info, U64 off) { TxtPt pt = {0}; { for(U64 line_idx = 0; line_idx < info->lines_count; line_idx += 1) { if(contains_1u64(info->lines_ranges[line_idx], off)) { pt.line = (S64)line_idx + 1; pt.column = (S64)(off - info->lines_ranges[line_idx].min) + 1; } } } return pt; } internal TXT_TokenArray txt_token_array_from_info_line_num__linear_scan(TXT_TextInfo *info, S64 line_num) { TXT_TokenArray line_tokens = {0}; if(1 <= line_num && line_num <= info->lines_count) { Rng1U64 line_range = info->lines_ranges[line_num-1]; for(U64 token_idx = 0; token_idx < info->tokens.count; token_idx += 1) { Rng1U64 token_range = info->tokens.v[token_idx].range; Rng1U64 token_x_line = intersect_1u64(token_range, line_range); if(token_x_line.max > token_x_line.min) { if(line_tokens.v == 0) { line_tokens.v = info->tokens.v+token_idx; } line_tokens.count += 1; } else if(line_tokens.v != 0) { break; } } } return line_tokens; } internal Rng1U64 txt_expr_off_range_from_line_off_range_string_tokens(U64 off, Rng1U64 line_range, String8 line_text, TXT_TokenArray *line_tokens) { Rng1U64 result = {0}; Temp scratch = scratch_begin(0, 0); { // rjf: unpack line info TXT_Token *line_tokens_first = line_tokens->v; TXT_Token *line_tokens_opl = line_tokens->v+line_tokens->count; // rjf: find token containing `off` TXT_Token *pt_token = 0; for(TXT_Token *token = line_tokens_first; token < line_tokens_opl; token += 1) { if(contains_1u64(token->range, off)) { Rng1U64 token_range_clamped = intersect_1u64(line_range, token->range); String8 token_string = str8_substr(line_text, r1u64(token_range_clamped.max - line_range.min, token_range_clamped.max - line_range.min)); B32 token_ender = 0; switch(token->kind) { default:{}break; case TXT_TokenKind_Symbol: { token_ender = (str8_match(token_string, str8_lit("]"), 0)); }break; case TXT_TokenKind_Identifier: case TXT_TokenKind_Keyword: case TXT_TokenKind_Meta: { token_ender = 1; }break; } if(token_ender) { pt_token = token; } break; } } // rjf: found token containing `off`? -> mark that as our initial range if(pt_token != 0) { result = pt_token->range; } // rjf: walk back from pt_token - try to find plausible start of expression if(pt_token != 0) { B32 walkback_done = 0; S32 nest = 0; for(TXT_Token *wb_token = pt_token; wb_token >= line_tokens_first && walkback_done == 0; wb_token -= 1) { Rng1U64 wb_token_range_clamped = intersect_1u64(line_range, wb_token->range); String8 wb_token_string = str8_substr(line_text, r1u64(wb_token_range_clamped.min - line_range.min, wb_token_range_clamped.max - line_range.min)); B32 include_wb_token = 0; switch(wb_token->kind) { default:{}break; case TXT_TokenKind_Symbol: { B32 is_scope_resolution = str8_match(wb_token_string, str8_lit("::"), 0); B32 is_dot = str8_match(wb_token_string, str8_lit("."), 0); B32 is_arrow = str8_match(wb_token_string, str8_lit("->"), 0); B32 is_open_bracket = str8_match(wb_token_string, str8_lit("["), 0); B32 is_close_bracket = str8_match(wb_token_string, str8_lit("]"), 0); nest -= !!(is_open_bracket); nest += !!(is_close_bracket); if(is_scope_resolution || is_dot || is_arrow || is_open_bracket|| is_close_bracket) { include_wb_token = 1; } }break; case TXT_TokenKind_Identifier: { include_wb_token = 1; }break; } if(include_wb_token) { result = union_1u64(result, wb_token->range); } else if(nest == 0) { walkback_done = 1; } } } } scratch_end(scratch); return result; } internal Rng1U64 txt_expr_off_range_from_info_data_pt(TXT_TextInfo *info, String8 data, TxtPt pt) { Rng1U64 result = {0}; Temp scratch = scratch_begin(0, 0); if(1 <= pt.line && pt.line <= info->lines_count) { // rjf: unpack line info Rng1U64 line_range = info->lines_ranges[pt.line-1]; String8 line_text = str8_substr(data, line_range); TXT_LineTokensSlice line_tokens_slice = txt_line_tokens_slice_from_info_data_line_range(scratch.arena, info, data, r1s64(pt.line, pt.line)); TXT_TokenArray line_tokens = line_tokens_slice.line_tokens[0]; TXT_Token *line_tokens_first = line_tokens.v; TXT_Token *line_tokens_opl = line_tokens.v+line_tokens.count; U64 pt_off = line_range.min + (pt.column-1); // rjf: grab offset range of expression result = txt_expr_off_range_from_line_off_range_string_tokens(pt_off, line_range, line_text, &line_tokens); } scratch_end(scratch); return result; } internal String8 txt_string_from_info_data_txt_rng(TXT_TextInfo *info, String8 data, TxtRng rng) { Rng1U64 rng_off = r1u64(txt_off_from_info_pt(info, rng.min), txt_off_from_info_pt(info, rng.max)); String8 result = str8_substr(data, rng_off); return result; } internal String8 txt_string_from_info_data_line_num(TXT_TextInfo *info, String8 data, S64 line_num) { String8 result = {0}; if(1 <= line_num && line_num <= info->lines_count) { result = str8_substr(data, info->lines_ranges[line_num-1]); } return result; } internal TXT_LineTokensSlice txt_line_tokens_slice_from_info_data_line_range(Arena *arena, TXT_TextInfo *info, String8 data, Rng1S64 line_range) { TXT_LineTokensSlice result = {0}; Temp scratch = scratch_begin(&arena, 1); if(info->lines_count != 0) { Rng1S64 line_range_clamped = r1s64(Clamp(1, line_range.min, (S64)info->lines_count), Clamp(1, line_range.max, (S64)info->lines_count)); U64 line_count = (U64)dim_1s64(line_range_clamped)+1; // rjf: allocate output arrays result.line_tokens = push_array(arena, TXT_TokenArray, line_count); // rjf: binary search to find first token TXT_Token *tokens_first = 0; ProfScope("binary search to find first token") { Rng1U64 slice_range = r1u64(info->lines_ranges[line_range_clamped.min-1].min, info->lines_ranges[line_range_clamped.max-1].max); U64 min_idx = 0; U64 opl_idx = info->tokens.count; for(;;) { U64 mid_idx = (opl_idx+min_idx)/2; if(mid_idx >= opl_idx) { break; } TXT_Token *mid_token = &info->tokens.v[mid_idx]; if(mid_token->range.min > slice_range.max) { opl_idx = mid_idx; } else if(mid_token->range.max < slice_range.min) { min_idx = mid_idx; } else if(tokens_first == 0 || mid_token->range.min < tokens_first->range.min) { tokens_first = mid_token; opl_idx = mid_idx; } if(mid_idx == min_idx && mid_idx+1 == opl_idx) { break; } } } // rjf: grab per-line tokens TXT_TokenList *line_tokens_lists = push_array(scratch.arena, TXT_TokenList, line_count); if(tokens_first != 0) ProfScope("grab per-line tokens") { TXT_Token *tokens_opl = info->tokens.v+info->tokens.count; U64 line_slice_idx = 0; for(TXT_Token *token = tokens_first; token < tokens_opl && line_slice_idx < line_count;) { if(token->range.min < info->lines_ranges[line_slice_idx+line_range.min-1].max) { if(token->range.max > info->lines_ranges[line_slice_idx+line_range.min-1].min) { txt_token_list_push(scratch.arena, &line_tokens_lists[line_slice_idx], token); } B32 need_token_advance = 0; B32 need_line_advance = 0; if(token->range.max >= info->lines_ranges[line_slice_idx+line_range.min-1].max) { need_line_advance = 1; } if(token->range.max <= info->lines_ranges[line_slice_idx+line_range.min-1].max) { need_token_advance += 1; } if(need_line_advance) { line_slice_idx += 1; } if(need_token_advance) { token += 1; } } else { line_slice_idx += 1; } } } // rjf: bake per-line tokens to arrays for(U64 line_slice_idx = 0; line_slice_idx < line_count; line_slice_idx += 1) { result.line_tokens[line_slice_idx] = txt_token_array_from_list(arena, &line_tokens_lists[line_slice_idx]); } } scratch_end(scratch); return result; } internal TXT_ScopeNode * txt_scope_node_from_info_num(TXT_TextInfo *info, U64 num) { TXT_ScopeNode *result = &txt_scope_node_nil; if(1 <= num && num <= info->scope_nodes.count) { result = &info->scope_nodes.v[num-1]; } return result; } internal TXT_ScopeNode * txt_scope_node_from_info_off(TXT_TextInfo *info, U64 off) { TXT_ScopeNode *result = &txt_scope_node_nil; if(info->scope_pts.count != 0) { U64 first = 0; U64 opl = info->scope_pts.count; for(;;) { U64 mid = (first + opl) / 2; U64 mid_off = info->tokens.v[info->scope_pts.v[mid].token_idx].range.min; if(mid_off < off) { first = mid; } else if(off < mid_off) { opl = mid; } else { first = mid; break; } if(opl - first <= 1) { break; } } TXT_ScopeNode *closest_node = &info->scope_nodes.v[info->scope_pts.v[first].scope_idx]; for(TXT_ScopeNode *scope_n = closest_node; scope_n != &txt_scope_node_nil; scope_n = txt_scope_node_from_info_num(info, scope_n->parent_num)) { if(info->tokens.v[scope_n->token_idx_range.min].range.min <= off && off < info->tokens.v[scope_n->token_idx_range.max].range.max) { result = scope_n; break; } } } return result; } internal TXT_ScopeNode * txt_scope_node_from_info_pt(TXT_TextInfo *info, TxtPt pt) { U64 off = txt_off_from_info_pt(info, pt); TXT_ScopeNode *result = txt_scope_node_from_info_off(info, off); return result; } //////////////////////////////// //~ rjf: Artifact Cache Hooks / Lookups typedef struct TXT_Artifact TXT_Artifact; struct TXT_Artifact { Arena *arena; U128 data_hash; TXT_TextInfo info; }; typedef struct TXT_ArtifactCreateShared TXT_ArtifactCreateShared; struct TXT_ArtifactCreateShared { Arena *arena; TXT_TextInfo info; TXT_Artifact *artifact; }; internal AC_Artifact txt_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); Access *access = access_open(); //- rjf: get shared state TXT_ArtifactCreateShared *shared = 0; if(lane_idx() == 0) { shared = push_array(scratch.arena, TXT_ArtifactCreateShared, 1); } lane_sync_u64(&shared, 0); //- rjf: unpack key U128 hash = {0}; TXT_LangKind lang = TXT_LangKind_Null; str8_deserial_read_struct(key, 0, &hash); str8_deserial_read_struct(key, sizeof(hash), &lang); String8 data = c_data_from_hash(access, hash); TXT_LangLexFunctionType *lex_function = txt_lex_function_from_lang_kind(lang); //- rjf: data -> text info if(!u128_match(hash, u128_zero())) { if(lane_idx() == 0) { shared->arena = arena_alloc(); } //- rjf: set # of bytes to process // (line ending calc) (line counting) (line measuring) (lexing) set_progress_target(Min(data.size, 1024) + data.size + data.size + data.size*(lang != TXT_LangKind_Null)); //- rjf: detect line end kind TXT_LineEndKind line_end_kind = TXT_LineEndKind_Null; if(lane_idx() == 0) { U64 lf_count = 0; U64 cr_count = 0; for(U64 idx = 0; idx < data.size && idx < 1024; idx += 1) { if(data.str[idx] == '\r') { cr_count += 1; } if(data.str[idx] == '\n') { lf_count += 1; } } if(cr_count >= lf_count/2 && lf_count >= 1) { line_end_kind = TXT_LineEndKind_CRLF; } else if(lf_count >= 1) { line_end_kind = TXT_LineEndKind_LF; } shared->info.line_end_kind = line_end_kind; } lane_sync(); set_progress(Min(data.size, 1024)); //- rjf: count # of lines U64 lane_line_count = 0; if(lane_idx() == 0) { lane_line_count = 1; } { Rng1U64 range = lane_range(data.size); for EachInRange(idx, range) { if(data.str[idx] == '\n') { lane_line_count += 1; } if(idx && idx%1000 == 0) { add_progress(1000); } } } ins_atomic_u64_add_eval(&shared->info.lines_count, lane_line_count); lane_sync(); set_progress(Min(data.size, 1024) + data.size); //- rjf: allocate & store line ranges if(lane_idx() == 0) { shared->info.lines_ranges = push_array_no_zero(shared->arena, Rng1U64, shared->info.lines_count); U64 line_idx = 0; U64 line_start_idx = 0; for(U64 idx = 0; idx <= data.size; idx += 1) { if(idx == data.size || data.str[idx] == '\n') { Rng1U64 line_range = r1u64(line_start_idx, idx); if(idx > 0 && data.str[idx-1] == '\r' && line_range.max > line_range.min) { line_range.max -= 1; } U64 line_size = dim_1u64(line_range); shared->info.lines_ranges[line_idx] = line_range; shared->info.lines_max_size = Max(shared->info.lines_max_size, line_size); line_idx += 1; line_start_idx = idx+1; } if(idx && idx%1000 == 0) { add_progress(1000); } } } lane_sync(); set_progress(Min(data.size, 1024) + data.size + data.size); //- rjf: lex function * data -> tokens #if 1 if(lane_idx() == 0 && lex_function != 0) { shared->info.tokens = lex_function(shared->arena, 0, data); } #else if(lane_idx() == 0) { shared->info.tokens = txt_token_array_from_lang_kind_string(shared->arena, lang, data); } #endif lane_sync(); set_progress(Min(data.size, 1024) + data.size + data.size + data.size*(lex_function != 0)); TXT_TokenArray tokens = shared->info.tokens; //- rjf: count scope points { U64 lane_scope_pt_opener_count = 0; U64 lane_scope_pt_count = 0; Rng1U64 range = lane_range(tokens.count); for EachInRange(idx, range) { if(tokens.v[idx].kind == TXT_TokenKind_Symbol) { String8 token_string = str8_substr(data, tokens.v[idx].range); B32 is_opener = (token_string.str[0] == '{' || token_string.str[0] == '(' || token_string.str[0] == '['); B32 is_closer = (token_string.str[0] == '}' || token_string.str[0] == ')' || token_string.str[0] == ']'); if(token_string.size == 1 && (is_opener || is_closer)) { lane_scope_pt_count += 1; lane_scope_pt_opener_count += !!is_opener; } } } ins_atomic_u64_add_eval(&shared->info.scope_pts.count, lane_scope_pt_count); ins_atomic_u64_add_eval(&shared->info.scope_nodes.count, lane_scope_pt_opener_count); } lane_sync(); //- rjf: allocate & fill scope data if(lane_idx() == 0) { shared->info.scope_pts.v = push_array_no_zero(shared->arena, TXT_ScopePt, shared->info.scope_pts.count); shared->info.scope_nodes.v = push_array_no_zero(shared->arena, TXT_ScopeNode, shared->info.scope_nodes.count); { typedef struct ScopeTask ScopeTask; struct ScopeTask { ScopeTask *next; U64 scope_idx; }; Temp scratch = scratch_begin(0, 0); ScopeTask *top_scope_task = 0; ScopeTask *free_scope_task = 0; U64 pt_idx = 0; U64 scope_idx = 0; for EachIndex(token_idx, tokens.count) { if(tokens.v[token_idx].kind == TXT_TokenKind_Symbol) { String8 token_string = str8_substr(data, tokens.v[token_idx].range); B32 is_opener = (token_string.str[0] == '{' || token_string.str[0] == '(' || token_string.str[0] == '['); B32 is_closer = (token_string.str[0] == '}' || token_string.str[0] == ')' || token_string.str[0] == ']'); // rjf: opener symbols -> push scope if(is_opener) { // rjf: insert into scope tree TXT_ScopeNode *new_scope = &shared->info.scope_nodes.v[scope_idx]; new_scope->token_idx_range.min = token_idx; if(top_scope_task) { U64 new_scope_num = scope_idx+1; TXT_ScopeNode *parent = &shared->info.scope_nodes.v[top_scope_task->scope_idx]; if(parent->first_num == 0) { parent->first_num = new_scope_num; } if(parent->last_num != 0) { TXT_ScopeNode *prev_scope = &shared->info.scope_nodes.v[parent->last_num-1]; prev_scope->next_num = new_scope_num; } parent->last_num = new_scope_num; new_scope->parent_num = top_scope_task->scope_idx+1; } // rjf: push onto scope stack ScopeTask *scope_task = free_scope_task; if(scope_task) { SLLStackPop(free_scope_task); } else { scope_task = push_array(scratch.arena, ScopeTask, 1); } scope_task->scope_idx = scope_idx; scope_idx += 1; SLLStackPush(top_scope_task, scope_task); } // rjf: opener or closer -> fill endpoint if(top_scope_task && (is_opener || is_closer)) { shared->info.scope_pts.v[pt_idx].token_idx = token_idx; shared->info.scope_pts.v[pt_idx].scope_idx = top_scope_task->scope_idx; pt_idx += 1; } // rjf: closer symbols -> pop if(is_closer && top_scope_task != 0) { ScopeTask *popped = top_scope_task; shared->info.scope_nodes.v[popped->scope_idx].token_idx_range.max = token_idx; SLLStackPop(top_scope_task); SLLStackPush(free_scope_task, popped); } } } scratch_end(scratch); } } lane_sync(); } //- rjf: mark dependency on hash c_hash_downstream_inc(hash); //- rjf: package as artifact if(lane_idx() == 0 && shared->arena != 0) { shared->artifact = push_array(shared->arena, TXT_Artifact, 1); shared->artifact->arena = shared->arena; shared->artifact->data_hash = hash; shared->artifact->info = shared->info; } lane_sync(); access_close(access); scratch_end(scratch); ProfEnd(); AC_Artifact result = {0}; result.u64[0] = (U64)shared->artifact; return result; } internal void txt_artifact_destroy(AC_Artifact artifact) { TXT_Artifact *txt_artifact = (TXT_Artifact *)artifact.u64[0]; if(txt_artifact == 0) { return; } c_hash_downstream_dec(txt_artifact->data_hash); arena_release(txt_artifact->arena); } internal TXT_TextInfo txt_text_info_from_hash_lang(Access *access, U128 hash, TXT_LangKind lang) { #pragma pack(push, 1) struct { U128 hash; TXT_LangKind lang; } key = {hash, lang}; #pragma pack(pop) String8 key_string = str8_struct(&key); AC_Artifact artifact = ac_artifact_from_key(access, key_string, txt_artifact_create, txt_artifact_destroy, 0, .flags = AC_Flag_Wide); TXT_Artifact *txt_artifact = (TXT_Artifact *)artifact.u64[0]; TXT_TextInfo info = {0}; if(txt_artifact != 0) { info = txt_artifact->info; } return info; } internal TXT_TextInfo txt_text_info_from_key_lang(Access *access, C_Key key, TXT_LangKind lang, U128 *hash_out) { TXT_TextInfo result = {0}; for(U64 rewind_idx = 0; rewind_idx < C_KEY_HASH_HISTORY_COUNT; rewind_idx += 1) { U128 hash = c_hash_from_key(key, rewind_idx); result = txt_text_info_from_hash_lang(access, hash, lang); if(result.lines_count != 0) { if(hash_out) { *hash_out = hash; } break; } } return result; } ================================================ FILE: src/text/text.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef TEXT_H #define TEXT_H //////////////////////////////// //~ rjf: Value Types typedef enum TXT_LineEndKind { TXT_LineEndKind_Null, TXT_LineEndKind_LF, TXT_LineEndKind_CRLF, TXT_LineEndKind_COUNT } TXT_LineEndKind; typedef enum TXT_TokenKind { TXT_TokenKind_Null, TXT_TokenKind_Error, TXT_TokenKind_Whitespace, TXT_TokenKind_Keyword, TXT_TokenKind_Identifier, TXT_TokenKind_Numeric, TXT_TokenKind_String, TXT_TokenKind_Symbol, TXT_TokenKind_Comment, TXT_TokenKind_Meta, // preprocessor, etc. TXT_TokenKind_COUNT } TXT_TokenKind; typedef struct TXT_TokenizerRule TXT_TokenizerRule; struct TXT_TokenizerRule { TXT_TokenKind token_kind; String8 open_string; String8 close_string; U32 close_advance; B32 nesting; B32 escaping; U32 parent_num; }; typedef struct TXT_TokenizerRulePtrNode TXT_TokenizerRulePtrNode; struct TXT_TokenizerRulePtrNode { TXT_TokenizerRulePtrNode *next; TXT_TokenizerRule *v; }; typedef struct TXT_TokenizerRuleArray TXT_TokenizerRuleArray; struct TXT_TokenizerRuleArray { TXT_TokenizerRule *v; U64 count; }; typedef struct TXT_Token TXT_Token; struct TXT_Token { TXT_TokenKind kind; Rng1U64 range; }; typedef struct TXT_TokenChunkNode TXT_TokenChunkNode; struct TXT_TokenChunkNode { TXT_TokenChunkNode *next; U64 count; U64 cap; TXT_Token *v; }; typedef struct TXT_TokenChunkList TXT_TokenChunkList; struct TXT_TokenChunkList { TXT_TokenChunkNode *first; TXT_TokenChunkNode *last; U64 chunk_count; U64 token_count; }; typedef struct TXT_TokenNode TXT_TokenNode; struct TXT_TokenNode { TXT_TokenNode *next; TXT_Token v; }; typedef struct TXT_TokenList TXT_TokenList; struct TXT_TokenList { TXT_TokenNode *first; TXT_TokenNode *last; U64 count; }; typedef struct TXT_TokenArray TXT_TokenArray; struct TXT_TokenArray { U64 count; TXT_Token *v; }; typedef struct TXT_TokenArrayArray TXT_TokenArrayArray; struct TXT_TokenArrayArray { U64 count; TXT_TokenArray *v; }; typedef struct TXT_ScopeNode TXT_ScopeNode; struct TXT_ScopeNode { U64 first_num; U64 last_num; U64 next_num; U64 parent_num; Rng1U64 token_idx_range; }; typedef struct TXT_ScopeNodeArray TXT_ScopeNodeArray; struct TXT_ScopeNodeArray { TXT_ScopeNode *v; U64 count; }; typedef struct TXT_ScopePt TXT_ScopePt; struct TXT_ScopePt { U64 token_idx; U64 scope_idx; }; typedef struct TXT_ScopePtArray TXT_ScopePtArray; struct TXT_ScopePtArray { TXT_ScopePt *v; U64 count; }; typedef struct TXT_TextInfo TXT_TextInfo; struct TXT_TextInfo { U64 lines_count; Rng1U64 *lines_ranges; U64 lines_max_size; TXT_LineEndKind line_end_kind; TXT_TokenArray tokens; TXT_ScopePtArray scope_pts; TXT_ScopeNodeArray scope_nodes; U64 bytes_processed; U64 bytes_to_process; }; typedef struct TXT_LineTokensSlice TXT_LineTokensSlice; struct TXT_LineTokensSlice { TXT_TokenArray *line_tokens; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/text.meta.h" //////////////////////////////// //~ rjf: Language Kind Types typedef TXT_TokenArray TXT_LangLexFunctionType(Arena *arena, U64 *bytes_processed_counter, String8 string); //////////////////////////////// //~ rjf: Globals read_only global TXT_ScopeNode txt_scope_node_nil = {0}; //////////////////////////////// //~ rjf: Basic Helpers internal TXT_LangKind txt_lang_kind_from_extension(String8 extension); internal String8 txt_extension_from_lang_kind(TXT_LangKind kind); internal TXT_LangKind txt_lang_kind_from_arch(Arch arch); internal TXT_LangLexFunctionType *txt_lex_function_from_lang_kind(TXT_LangKind kind); //////////////////////////////// //~ rjf: Token Type Functions internal void txt_token_chunk_list_push(Arena *arena, TXT_TokenChunkList *list, U64 cap, TXT_Token *token); internal void txt_token_list_push(Arena *arena, TXT_TokenList *list, TXT_Token *token); internal TXT_TokenArray txt_token_array_from_chunk_list(Arena *arena, TXT_TokenChunkList *list); internal TXT_TokenArray txt_token_array_from_list(Arena *arena, TXT_TokenList *list); //////////////////////////////// //~ rjf: Lexing Functions internal TXT_TokenArray txt_token_array_from_lang_kind_string(Arena *arena, TXT_LangKind lang_kind, String8 string); internal TXT_TokenArray txt_token_array_from_string__c_cpp(Arena *arena, U64 *bytes_processed_counter, String8 string); internal TXT_TokenArray txt_token_array_from_string__odin(Arena *arena, U64 *bytes_processed_counter, String8 string); internal TXT_TokenArray txt_token_array_from_string__jai(Arena *arena, U64 *bytes_processed_counter, String8 string); internal TXT_TokenArray txt_token_array_from_string__zig(Arena *arena, U64 *bytes_processed_counter, String8 string); internal TXT_TokenArray txt_token_array_from_string__rust(Arena *arena, U64 *bytes_processed_counter, String8 string); internal TXT_TokenArray txt_token_array_from_string__disasm_x64_intel(Arena *arena, U64 *bytes_processed_counter, String8 string); //////////////////////////////// //~ rjf: Text Info Extractor Helpers internal U64 txt_off_from_info_pt(TXT_TextInfo *info, TxtPt pt); internal TxtPt txt_pt_from_info_off__linear_scan(TXT_TextInfo *info, U64 off); internal TXT_TokenArray txt_token_array_from_info_line_num__linear_scan(TXT_TextInfo *info, S64 line_num); internal Rng1U64 txt_expr_off_range_from_line_off_range_string_tokens(U64 off, Rng1U64 line_range, String8 line_text, TXT_TokenArray *line_tokens); internal Rng1U64 txt_expr_off_range_from_info_data_pt(TXT_TextInfo *info, String8 data, TxtPt pt); internal String8 txt_string_from_info_data_txt_rng(TXT_TextInfo *info, String8 data, TxtRng rng); internal String8 txt_string_from_info_data_line_num(TXT_TextInfo *info, String8 data, S64 line_num); internal TXT_LineTokensSlice txt_line_tokens_slice_from_info_data_line_range(Arena *arena, TXT_TextInfo *info, String8 data, Rng1S64 line_range); internal TXT_ScopeNode *txt_scope_node_from_info_num(TXT_TextInfo *info, U64 num); internal TXT_ScopeNode *txt_scope_node_from_info_off(TXT_TextInfo *info, U64 off); internal TXT_ScopeNode *txt_scope_node_from_info_pt(TXT_TextInfo *info, TxtPt pt); //////////////////////////////// //~ rjf: Artifact Cache Hooks / Lookups internal AC_Artifact txt_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *gen_out); internal void txt_artifact_destroy(AC_Artifact artifact); internal TXT_TextInfo txt_text_info_from_hash_lang(Access *access, U128 hash, TXT_LangKind lang); internal TXT_TextInfo txt_text_info_from_key_lang(Access *access, C_Key key, TXT_LangKind lang, U128 *hash_out); #endif // TEXT_H ================================================ FILE: src/text/text.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name ext keywords_table multichar_symbol_table tokenizer_rules_table) TXT_LangKindTable: { { Null null null null null} { C c c c c } { CPlusPlus cpp cpp c c } { Odin odin odin c null} { Jai jai jai c null} { Zig zig zig c null} { Rust rs rust c null} { DisasmX64Intel disasm_x64_intel null null null} } @table(string kind) TXT_LangKindExtTable: { {"h" C } {"cxx" CPlusPlus} {"cc" CPlusPlus} {"c++" CPlusPlus} {"ixx" CPlusPlus} {"cxxm" CPlusPlus} {"c++m" CPlusPlus} {"ccm" CPlusPlus} {"cppm" CPlusPlus} {"mpp" CPlusPlus} {"C" CPlusPlus} {"hpp" CPlusPlus} {"hxx" CPlusPlus} {"hh" CPlusPlus} {"h++" CPlusPlus} {"H" CPlusPlus} } @enum TXT_LangKind: { @expand(TXT_LangKindTable a) `$(a.name)`, COUNT } @data(String8) txt_lang_kind_ext_table: { @expand(TXT_LangKindTable a) `str8_lit_comp("$(a.ext)")` } @data(`struct {String8 ext; TXT_LangKind kind;}`) @c_file txt_ext_lang_kind_table: { @expand(TXT_LangKindTable a) `{str8_lit_comp("$(a.ext)"), TXT_LangKind_$(a.name)}`, @expand(TXT_LangKindExtTable a) `{str8_lit_comp("$(a.string)"), TXT_LangKind_$(a.kind)}`, } @data(String8Array) txt_keywords_from_lang_kind_table: { @expand(TXT_LangKindTable a) `{txt_keywords__$(a.keywords_table), ArrayCount(txt_keywords__$(a.keywords_table))}` } @data(String8Array) txt_multichar_symbols_from_lang_kind_table: { @expand(TXT_LangKindTable a) `{txt_multichar_symbols__$(a.multichar_symbol_table), ArrayCount(txt_multichar_symbols__$(a.multichar_symbol_table))}` } @data(TXT_TokenizerRuleArray) txt_tokenizer_rules_from_lang_kind_table: { @expand(TXT_LangKindTable a) `{txt_tokenizer_rules__$(a.tokenizer_rules_table), ArrayCount(txt_tokenizer_rules__$(a.tokenizer_rules_table))}` } @data(String8) txt_keywords__null:{`{0}`} @data(String8) txt_multichar_symbols__null:{`{0}`} @data(TXT_TokenizerRule) txt_tokenizer_rules__null:{`{TXT_TokenKind_Null}`} //////////////////////////////// //~ rjf: C @table(string) txt_keywords__c: { {"auto"} {"break"} {"case"} {"char"} {"const"} {"continue"} {"default"} {"do"} {"double"} {"else"} {"enum"} {"extern"} {"float"} {"for"} {"goto"} {"if"} {"int"} {"long"} {"register"} {"return"} {"short"} {"signed"} {"sizeof"} {"static"} {"struct"} {"switch"} {"typedef"} {"union"} {"unsigned"} {"void"} {"volatile"} {"while"} } @data(String8) txt_keywords__c: {@expand(txt_keywords__c a) `str8_lit_comp("$(a.string)")`} @table(string) txt_multichar_symbols__c: { {"<<"} {">>"} {"<="} {">="} {"=="} {"!="} {"&&"} {"||"} {"|="} {"&="} {"^="} {"~="} {"+="} {"-="} {"*="} {"/="} {"%="} {"<<="} {">>="} {"->"} } @data(String8) txt_multichar_symbols__c: {@expand(txt_multichar_symbols__c a) `str8_lit_comp("$(a.string)")`} @table(token_kind open_string close_string close_advance nesting escaping parent_num) txt_tokenizer_rules__c: { {Comment "//" "\\n" 0 0 1 0} {Comment "/*" "*/" 2 0 0 0} {Meta "#" "\\n" 0 0 1 0} {String '\\"' '\\"' 1 0 1 0} {String "'" "'" 1 0 1 0} {String '\\"' '\\"' 1 0 1 3} {String "<" ">" 1 0 1 3} } @data(TXT_TokenizerRule) txt_tokenizer_rules__c: { @expand(txt_tokenizer_rules__c a) `{TXT_TokenKind_$(a.token_kind), str8_lit_comp("$(a.open_string)"), str8_lit_comp("$(a.close_string)"), $(a.close_advance), $(a.nesting), $(a.escaping), $(a.parent_num)}` } //////////////////////////////// //~ rjf: C++ @table(string) txt_keywords__cpp: { {"alignas"} {"alignof"} {"and"} {"and_eq"} {"asm"} {"atomic_cancel"} {"atomic_commit"} {"atomic_noexcept"} {"auto"} {"bitand"} {"bitor"} {"bool"} {"break"} {"case"} {"catch"} {"char"} {"char8_t"} {"char16_t"} {"char32_t"} {"class"} {"compl"} {"concept"} {"const"} {"consteval"} {"constexpr"} {"constinit"} {"const_cast"} {"continue"} {"co_await"} {"co_return"} {"co_yield"} {"decltype"} {"default"} {"delete"} {"do"} {"double"} {"dynamic_cast"} {"else"} {"enum"} {"explicit"} {"export"} {"extern"} {"false"} {"float"} {"for"} {"friend"} {"goto"} {"if"} {"inline"} {"int"} {"long"} {"mutable"} {"namespace"} {"new"} {"noexcept"} {"not"} {"not_eq"} {"nullptr"} {"operator"} {"or"} {"or_eq"} {"private"} {"protected"} {"public"} {"reflexpr"} {"register"} {"reinterpret_cast"} {"requires"} {"return"} {"short"} {"signed"} {"sizeof"} {"static"} {"static_assert"} {"static_cast"} {"struct"} {"switch"} {"synchronized"} {"template"} {"this"} {"thread_local"} {"throw"} {"true"} {"try"} {"typedef"} {"typeid"} {"typename"} {"union"} {"unsigned"} {"using"} {"virtual"} {"void"} {"volatile"} {"wchar_t"} {"while"} {"xor"} {"xor_eq"} } @data(String8) txt_keywords__cpp: {@expand(txt_keywords__cpp a) `str8_lit_comp("$(a.string)")`} //////////////////////////////// //~ rjf: Odin @table(string) txt_keywords__odin: { {"align_of"} {"asm"} {"auto_cast"} {"bit_set"} {"break"} {"case"} {"cast"} {"context"} {"continue"} {"defer"} {"distinct"} {"do"} {"dynamic"} {"else"} {"enum"} {"fallthrough"} {"for"} {"foreign"} {"if"} {"in"} {"map"} {"matrix"} {"not_in"} {"or_break"} {"or_continue"} {"or_else"} {"or_return"} {"package"} {"proc"} {"return"} {"size_of"} {"struct"} {"switch"} {"transmute"} {"typeid"} {"union"} {"using"} {"when"} {"where"} {"import"} } @data(String8) txt_keywords__odin: {@expand(txt_keywords__odin a) `str8_lit_comp("$(a.string)")`} //////////////////////////////// //~ rjf: Jai @table(string) txt_keywords__jai: { {"bool"} {"true"} {"false"} {"int"} {"s8"} {"u8"} {"s16"} {"u16"} {"s32"} {"u32"} {"s64"} {"u64"} {"s128"} {"u128"} {"float"} {"float32"} {"float64"} {"void"} {"enum"} {"enum_flags"} {"size_of"} {"string"} {"type_of"} {"cast"} {"if"} {"ifs"} {"then"} {"else"} {"case"} {"for"} {"while"} {"break"} {"continue"} {"remove"} {"return"} {"inline"} {"null"} {"defer"} {"xx"} } @data(String8) txt_keywords__jai: {@expand(txt_keywords__jai a) `str8_lit_comp("$(a.string)")`} //////////////////////////////// //~ rjf: Zig @table(string) txt_keywords__zig: { {"addrspace"} {"align"} {"allowzero"} {"and"} {"anyframe"} {"anytype"} {"asm"} {"async"} {"await"} {"break"} {"callconv"} {"catch"} {"comptime"} {"const"} {"continue"} {"defer"} {"else"} {"enum"} {"errdefer"} {"error"} {"export"} {"extern"} {"fn"} {"for"} {"if"} {"inline"} {"noalias"} {"nosuspend"} {"noinline"} {"opaque"} {"or"} {"orelse"} {"packed"} {"pub"} {"resume"} {"return"} {"linksection"} {"struct"} {"suspend"} {"switch"} {"test"} {"threadlocal"} {"try"} {"union"} {"unreachable"} {"usingnamespace"} {"var"} {"volatile"} {"while"} } @data(String8) txt_keywords__zig: {@expand(txt_keywords__zig a) `str8_lit_comp("$(a.string)")`} //////////////////////////////// //~ rjf: Rust @table(string) txt_keywords__rust: { {"as"} {"break"} {"const"} {"continue"} {"crate"} {"else"} {"enum"} {"extern"} {"false"} {"fn"} {"for"} {"if"} {"impl"} {"in"} {"let"} {"loop"} {"match"} {"mod"} {"move"} {"mut"} {"pub"} {"ref"} {"return"} {"self"} {"Self"} {"static"} {"struct"} {"super"} {"trait"} {"true"} {"type"} {"unsafe"} {"use"} {"where"} {"while"} {"yield"} {"async"} {"await"} {"dyn"} {"macro_rules"} {"raw"} {"safe"} {"union"} } @data(String8) txt_keywords__rust: {@expand(txt_keywords__rust a) `str8_lit_comp("$(a.string)")`} ================================================ FILE: src/third_party/blake3/asm/LICENSE ================================================ This work is released into the public domain with CC0 1.0. Alternatively, it is licensed under the Apache License 2.0. ------------------------------------------------------------------------------- Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ------------------------------------------------------------------------------- Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2019 Jack O'Connor and Samuel Neves Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: src/third_party/blake3/asm/blake3.c ================================================ #include #include #include #include "blake3.h" #include "blake3_impl.h" const char *blake3_version(void) { return BLAKE3_VERSION_STRING; } INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8], uint8_t flags) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; self->blocks_compressed = 0; self->flags = flags; } INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8], uint64_t chunk_counter) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = chunk_counter; self->blocks_compressed = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; } INLINE size_t chunk_state_len(const blake3_chunk_state *self) { return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) + ((size_t)self->buf_len); } INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len); if (take > input_len) { take = input_len; } uint8_t *dest = self->buf + ((size_t)self->buf_len); memcpy(dest, input, take); self->buf_len += (uint8_t)take; return take; } INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) { if (self->blocks_compressed == 0) { return CHUNK_START; } else { return 0; } } typedef struct { uint32_t input_cv[8]; uint64_t counter; uint8_t block[BLAKE3_BLOCK_LEN]; uint8_t block_len; uint8_t flags; } output_t; INLINE output_t make_output(const uint32_t input_cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { output_t ret; memcpy(ret.input_cv, input_cv, 32); memcpy(ret.block, block, BLAKE3_BLOCK_LEN); ret.block_len = block_len; ret.counter = counter; ret.flags = flags; return ret; } // Chaining values within a given chunk (specifically the compress_in_place // interface) are represented as words. This avoids unnecessary bytes<->words // conversion overhead in the portable implementation. However, the hash_many // interface handles both user input and parent node blocks, so it accepts // bytes. For that reason, chaining values in the CV stack are represented as // bytes. INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) { uint32_t cv_words[8]; memcpy(cv_words, self->input_cv, 32); blake3_compress_in_place(cv_words, self->block, self->block_len, self->counter, self->flags); store_cv_words(cv, cv_words); } INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out, size_t out_len) { uint64_t output_block_counter = seek / 64; size_t offset_within_block = seek % 64; uint8_t wide_buf[64]; while (out_len > 0) { blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf); size_t available_bytes = 64 - offset_within_block; size_t memcpy_len; if (out_len > available_bytes) { memcpy_len = available_bytes; } else { memcpy_len = out_len; } memcpy(out, wide_buf + offset_within_block, memcpy_len); out += memcpy_len; out_len -= memcpy_len; output_block_counter += 1; offset_within_block = 0; } } INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { if (self->buf_len > 0) { size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; if (input_len > 0) { blake3_compress_in_place( self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; self->buf_len = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); } } while (input_len > BLAKE3_BLOCK_LEN) { blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; input += BLAKE3_BLOCK_LEN; input_len -= BLAKE3_BLOCK_LEN; } size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; } INLINE output_t chunk_state_output(const blake3_chunk_state *self) { uint8_t block_flags = self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END; return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter, block_flags); } INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN], const uint32_t key[8], uint8_t flags) { return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT); } // Given some input larger than one chunk, return the number of bytes that // should go in the left subtree. This is the largest power-of-2 number of // chunks that leaves at least 1 byte for the right subtree. INLINE size_t left_len(size_t content_len) { // Subtract 1 to reserve at least one byte for the right side. content_len // should always be greater than BLAKE3_CHUNK_LEN. size_t full_chunks = (content_len - 1) / BLAKE3_CHUNK_LEN; return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN; } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time // on a single thread. Write out the chunk chaining values and return the // number of chunks hashed. These chunks are never the root and never empty; // those cases use a different codepath. INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(0 < input_len); assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN); #endif const uint8_t *chunks_array[MAX_SIMD_DEGREE]; size_t input_position = 0; size_t chunks_array_len = 0; while (input_len - input_position >= BLAKE3_CHUNK_LEN) { chunks_array[chunks_array_len] = &input[input_position]; input_position += BLAKE3_CHUNK_LEN; chunks_array_len += 1; } blake3_hash_many(chunks_array, chunks_array_len, BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter, true, flags, CHUNK_START, CHUNK_END, out); // Hash the remaining partial chunk, if there is one. Note that the empty // chunk (meaning the empty message) is a different codepath. if (input_len > input_position) { uint64_t counter = chunk_counter + (uint64_t)chunks_array_len; blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, key, flags); chunk_state.chunk_counter = counter; chunk_state_update(&chunk_state, &input[input_position], input_len - input_position); output_t output = chunk_state_output(&chunk_state); output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]); return chunks_array_len + 1; } else { return chunks_array_len; } } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time // on a single thread. Write out the parent chaining values and return the // number of parents hashed. (If there's an odd input chaining value left over, // return it as an additional output.) These parents are never the root and // never empty; those cases use a different codepath. INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values, size_t num_chaining_values, const uint32_t key[8], uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(2 <= num_chaining_values); assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2); #endif const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2]; size_t parents_array_len = 0; while (num_chaining_values - (2 * parents_array_len) >= 2) { parents_array[parents_array_len] = &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; parents_array_len += 1; } blake3_hash_many(parents_array, parents_array_len, 1, key, 0, // Parents always use counter 0. false, flags | PARENT, 0, // Parents have no start flags. 0, // Parents have no end flags. out); // If there's an odd child left over, it becomes an output. if (num_chaining_values > 2 * parents_array_len) { memcpy(&out[parents_array_len * BLAKE3_OUT_LEN], &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN], BLAKE3_OUT_LEN); return parents_array_len + 1; } else { return parents_array_len; } } // The wide helper function returns (writes out) an array of chaining values // and returns the length of that array. The number of chaining values returned // is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer, // if the input is shorter than that many chunks. The reason for maintaining a // wide array of chaining values going back up the tree, is to allow the // implementation to hash as many parents in parallel as possible. // // As a special case when the SIMD degree is 1, this function will still return // at least 2 outputs. This guarantees that this function doesn't perform the // root compression. (If it did, it would use the wrong flags, and also we // wouldn't be able to implement extendable output.) Note that this function is // not used when the whole input is only 1 chunk long; that's a different // codepath. // // Why not just have the caller split the input on the first update(), instead // of implementing this special rule? Because we don't want to limit SIMD or // multi-threading parallelism for that update(). static size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { // Note that the single chunk case does *not* bump the SIMD degree up to 2 // when it is 1. If this implementation adds multi-threading in the future, // this gives us the option of multi-threading even the 2-chunk case, which // can help performance on smaller platforms. if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) { return compress_chunks_parallel(input, input_len, key, chunk_counter, flags, out); } // With more than simd_degree chunks, we need to recurse. Start by dividing // the input into left and right subtrees. (Note that this is only optimal // as long as the SIMD degree is a power of 2. If we ever get a SIMD degree // of 3 or something, we'll need a more complicated strategy.) size_t left_input_len = left_len(input_len); size_t right_input_len = input_len - left_input_len; const uint8_t *right_input = &input[left_input_len]; uint64_t right_chunk_counter = chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN); // Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to // account for the special case of returning 2 outputs when the SIMD degree // is 1. uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t degree = blake3_simd_degree(); if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) { // The special case: We always use a degree of at least two, to make // sure there are two outputs. Except, as noted above, at the chunk // level, where we allow degree=1. (Note that the 1-chunk-input case is // a different codepath.) degree = 2; } uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; // Recurse! If this implementation adds multi-threading support in the // future, this is where it will go. size_t left_n = blake3_compress_subtree_wide(input, left_input_len, key, chunk_counter, flags, cv_array); size_t right_n = blake3_compress_subtree_wide( right_input, right_input_len, key, right_chunk_counter, flags, right_cvs); // The special case again. If simd_degree=1, then we'll have left_n=1 and // right_n=1. Rather than compressing them into a single output, return // them directly, to make sure we always have at least two outputs. if (left_n == 1) { memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); return 2; } // Otherwise, do one layer of parent node compression. size_t num_chaining_values = left_n + right_n; return compress_parents_parallel(cv_array, num_chaining_values, key, flags, out); } // Hash a subtree with compress_subtree_wide(), and then condense the resulting // list of chaining values down to a single parent node. Don't compress that // last parent node, however. Instead, return its message bytes (the // concatenated chaining values of its children). This is necessary when the // first call to update() supplies a complete subtree, because the topmost // parent node of that subtree could end up being the root. It's also necessary // for extended output in the general case. // // As with compress_subtree_wide(), this function is not used on inputs of 1 // chunk or less. That's a different codepath. INLINE void compress_subtree_to_parent_node( const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN]) { #if defined(BLAKE3_TESTING) assert(input_len > BLAKE3_CHUNK_LEN); #endif uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key, chunk_counter, flags, cv_array); assert(num_cvs <= MAX_SIMD_DEGREE_OR_2); // If MAX_SIMD_DEGREE is greater than 2 and there's enough input, // compress_subtree_wide() returns more than 2 chaining values. Condense // them into 2 by forming parent nodes repeatedly. uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2]; // The second half of this loop condition is always true, and we just // asserted it above. But GCC can't tell that it's always true, and if NDEBUG // is set on platforms where MAX_SIMD_DEGREE_OR_2 == 2, GCC emits spurious // warnings here. GCC 8.5 is particularly sensitive, so if you're changing // this code, test it against that version. while (num_cvs > 2 && num_cvs <= MAX_SIMD_DEGREE_OR_2) { num_cvs = compress_parents_parallel(cv_array, num_cvs, key, flags, out_array); memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); } memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); } INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8], uint8_t flags) { memcpy(self->key, key, BLAKE3_KEY_LEN); chunk_state_init(&self->chunk, key, flags); self->cv_stack_len = 0; } void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); } void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]) { uint32_t key_words[8]; load_key_words(key, key_words); hasher_init_base(self, key_words, KEYED_HASH); } void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len) { blake3_hasher context_hasher; hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT); blake3_hasher_update(&context_hasher, context, context_len); uint8_t context_key[BLAKE3_KEY_LEN]; blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN); uint32_t context_key_words[8]; load_key_words(context_key, context_key_words); hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL); } void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) { blake3_hasher_init_derive_key_raw(self, context, strlen(context)); } // As described in hasher_push_cv() below, we do "lazy merging", delaying // merges until right before the next CV is about to be added. This is // different from the reference implementation. Another difference is that we // aren't always merging 1 chunk at a time. Instead, each CV might represent // any power-of-two number of chunks, as long as the smaller-above-larger stack // order is maintained. Instead of the "count the trailing 0-bits" algorithm // described in the spec, we use a "count the total number of 1-bits" variant // that doesn't require us to retain the subtree size of the CV on top of the // stack. The principle is the same: each CV that should remain in the stack is // represented by a 1-bit in the total number of chunks (or bytes) so far. INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) { size_t post_merge_stack_len = (size_t)popcnt(total_len); while (self->cv_stack_len > post_merge_stack_len) { uint8_t *parent_node = &self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN]; output_t output = parent_output(parent_node, self->key, self->chunk.flags); output_chaining_value(&output, parent_node); self->cv_stack_len -= 1; } } // In reference_impl.rs, we merge the new CV with existing CVs from the stack // before pushing it. We can do that because we know more input is coming, so // we know none of the merges are root. // // This setting is different. We want to feed as much input as possible to // compress_subtree_wide(), without setting aside anything for the chunk_state. // If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once // as a single subtree, if at all possible. // // This leads to two problems: // 1) This 64 KiB input might be the only call that ever gets made to update. // In this case, the root node of the 64 KiB subtree would be the root node // of the whole tree, and it would need to be ROOT finalized. We can't // compress it until we know. // 2) This 64 KiB input might complete a larger tree, whose root node is // similarly going to be the the root of the whole tree. For example, maybe // we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the // node at the root of the 256 KiB subtree until we know how to finalize it. // // The second problem is solved with "lazy merging". That is, when we're about // to add a CV to the stack, we don't merge it with anything first, as the // reference impl does. Instead we do merges using the *previous* CV that was // added, which is sitting on top of the stack, and we put the new CV // (unmerged) on top of the stack afterwards. This guarantees that we never // merge the root node until finalize(). // // Solving the first problem requires an additional tool, // compress_subtree_to_parent_node(). That function always returns the top // *two* chaining values of the subtree it's compressing. We then do lazy // merging with each of them separately, so that the second CV will always // remain unmerged. (That also helps us support extendable output when we're // hashing an input all-at-once.) INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN], uint64_t chunk_counter) { hasher_merge_cv_stack(self, chunk_counter); memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv, BLAKE3_OUT_LEN); self->cv_stack_len += 1; } void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_update(&hasher, v.data(), v.size()); if (input_len == 0) { return; } const uint8_t *input_bytes = (const uint8_t *)input; // If we have some partial chunk bytes in the internal chunk_state, we need // to finish that chunk first. if (chunk_state_len(&self->chunk) > 0) { size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk); if (take > input_len) { take = input_len; } chunk_state_update(&self->chunk, input_bytes, take); input_bytes += take; input_len -= take; // If we've filled the current chunk and there's more coming, finalize this // chunk and proceed. In this case we know it's not the root. if (input_len > 0) { output_t output = chunk_state_output(&self->chunk); uint8_t chunk_cv[32]; output_chaining_value(&output, chunk_cv); hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter); chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1); } else { return; } } // Now the chunk_state is clear, and we have more input. If there's more than // a single chunk (so, definitely not the root chunk), hash the largest whole // subtree we can, with the full benefits of SIMD (and maybe in the future, // multi-threading) parallelism. Two restrictions: // - The subtree has to be a power-of-2 number of chunks. Only subtrees along // the right edge can be incomplete, and we don't know where the right edge // is going to be until we get to finalize(). // - The subtree must evenly divide the total number of chunks up until this // point (if total is not 0). If the current incomplete subtree is only // waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have // to complete the current subtree first. // Because we might need to break up the input to form powers of 2, or to // evenly divide what we already have, this part runs in a loop. while (input_len > BLAKE3_CHUNK_LEN) { size_t subtree_len = round_down_to_power_of_2(input_len); uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN; // Shrink the subtree_len until it evenly divides the count so far. We know // that subtree_len itself is a power of 2, so we can use a bitmasking // trick instead of an actual remainder operation. (Note that if the caller // consistently passes power-of-2 inputs of the same size, as is hopefully // typical, this loop condition will always fail, and subtree_len will // always be the full length of the input.) // // An aside: We don't have to shrink subtree_len quite this much. For // example, if count_so_far is 1, we could pass 2 chunks to // compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still // get the right answer in the end, and we might get to use 2-way SIMD // parallelism. The problem with this optimization, is that it gets us // stuck always hashing 2 chunks. The total number of chunks will remain // odd, and we'll never graduate to higher degrees of parallelism. See // https://github.com/BLAKE3-team/BLAKE3/issues/69. while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) { subtree_len /= 2; } // The shrunken subtree_len might now be 1 chunk long. If so, hash that one // chunk by itself. Otherwise, compress the subtree into a pair of CVs. uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; if (subtree_len <= BLAKE3_CHUNK_LEN) { blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, self->key, self->chunk.flags); chunk_state.chunk_counter = self->chunk.chunk_counter; chunk_state_update(&chunk_state, input_bytes, subtree_len); output_t output = chunk_state_output(&chunk_state); uint8_t cv[BLAKE3_OUT_LEN]; output_chaining_value(&output, cv); hasher_push_cv(self, cv, chunk_state.chunk_counter); } else { // This is the high-performance happy path, though getting here depends // on the caller giving us a long enough input. uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; compress_subtree_to_parent_node(input_bytes, subtree_len, self->key, self->chunk.chunk_counter, self->chunk.flags, cv_pair); hasher_push_cv(self, cv_pair, self->chunk.chunk_counter); hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN], self->chunk.chunk_counter + (subtree_chunks / 2)); } self->chunk.chunk_counter += subtree_chunks; input_bytes += subtree_len; input_len -= subtree_len; } // If there's any remaining input less than a full chunk, add it to the chunk // state. In that case, also do a final merge loop to make sure the subtree // stack doesn't contain any unmerged pairs. The remaining input means we // know these merges are non-root. This merge loop isn't strictly necessary // here, because hasher_push_chunk_cv already does its own merge loop, but it // simplifies blake3_hasher_finalize below. if (input_len > 0) { chunk_state_update(&self->chunk, input_bytes, input_len); hasher_merge_cv_stack(self, self->chunk.chunk_counter); } } void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len) { blake3_hasher_finalize_seek(self, 0, out, out_len); } void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_finalize(&hasher, v.data(), v.size()); if (out_len == 0) { return; } // If the subtree stack is empty, then the current chunk is the root. if (self->cv_stack_len == 0) { output_t output = chunk_state_output(&self->chunk); output_root_bytes(&output, seek, out, out_len); return; } // If there are any bytes in the chunk state, finalize that chunk and do a // roll-up merge between that chunk hash and every subtree in the stack. In // this case, the extra merge loop at the end of blake3_hasher_update // guarantees that none of the subtrees in the stack need to be merged with // each other first. Otherwise, if there are no bytes in the chunk state, // then the top of the stack is a chunk hash, and we start the merge from // that. output_t output; size_t cvs_remaining; if (chunk_state_len(&self->chunk) > 0) { cvs_remaining = self->cv_stack_len; output = chunk_state_output(&self->chunk); } else { // There are always at least 2 CVs in the stack in this case. cvs_remaining = self->cv_stack_len - 2; output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key, self->chunk.flags); } while (cvs_remaining > 0) { cvs_remaining -= 1; uint8_t parent_block[BLAKE3_BLOCK_LEN]; memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32); output_chaining_value(&output, &parent_block[32]); output = parent_output(parent_block, self->key, self->chunk.flags); } output_root_bytes(&output, seek, out, out_len); } void blake3_hasher_reset(blake3_hasher *self) { chunk_state_reset(&self->chunk, self->key, 0); self->cv_stack_len = 0; } ================================================ FILE: src/third_party/blake3/asm/blake3.h ================================================ #ifndef BLAKE3_H #define BLAKE3_H #include #include #if !defined(BLAKE3_API) # if defined(_WIN32) || defined(__CYGWIN__) # if defined(BLAKE3_DLL) # if defined(BLAKE3_DLL_EXPORTS) # define BLAKE3_API __declspec(dllexport) # else # define BLAKE3_API __declspec(dllimport) # endif # define BLAKE3_PRIVATE # else # define BLAKE3_API # define BLAKE3_PRIVATE # endif # elif __GNUC__ >= 4 # define BLAKE3_API __attribute__((visibility("default"))) # define BLAKE3_PRIVATE __attribute__((visibility("hidden"))) # else # define BLAKE3_API # define BLAKE3_PRIVATE # endif #endif #ifdef __cplusplus extern "C" { #endif #define BLAKE3_VERSION_STRING "1.5.0" #define BLAKE3_KEY_LEN 32 #define BLAKE3_OUT_LEN 32 #define BLAKE3_BLOCK_LEN 64 #define BLAKE3_CHUNK_LEN 1024 #define BLAKE3_MAX_DEPTH 54 // This struct is a private implementation detail. It has to be here because // it's part of blake3_hasher below. typedef struct { uint32_t cv[8]; uint64_t chunk_counter; uint8_t buf[BLAKE3_BLOCK_LEN]; uint8_t buf_len; uint8_t blocks_compressed; uint8_t flags; } blake3_chunk_state; typedef struct { uint32_t key[8]; blake3_chunk_state chunk; uint8_t cv_stack_len; // The stack size is MAX_DEPTH + 1 because we do lazy merging. For example, // with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk // requires a 4th entry, rather than merging everything down to 1, because we // don't know whether more input is coming. This is different from how the // reference implementation does things. uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN]; } blake3_hasher; BLAKE3_API const char *blake3_version(void); BLAKE3_API void blake3_hasher_init(blake3_hasher *self); BLAKE3_API void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]); BLAKE3_API void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context); BLAKE3_API void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len); BLAKE3_API void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len); BLAKE3_API void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len); BLAKE3_API void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len); BLAKE3_API void blake3_hasher_reset(blake3_hasher *self); #ifdef __cplusplus } #endif #endif /* BLAKE3_H */ ================================================ FILE: src/third_party/blake3/asm/blake3_avx2_x86-64_unix.S ================================================ #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif #if defined(__ELF__) && defined(__CET__) && defined(__has_include) #if __has_include() #include #endif #endif #if !defined(_CET_ENDBR) #define _CET_ENDBR #endif .intel_syntax noprefix .global _blake3_hash_many_avx2 .global blake3_hash_many_avx2 #ifdef __APPLE__ .text #else .section .text #endif .p2align 6 _blake3_hash_many_avx2: blake3_hash_many_avx2: _CET_ENDBR push r15 push r14 push r13 push r12 push rbx push rbp mov rbp, rsp sub rsp, 680 and rsp, 0xFFFFFFFFFFFFFFC0 neg r9d vmovd xmm0, r9d vpbroadcastd ymm0, xmm0 vmovdqa ymmword ptr [rsp+0x280], ymm0 vpand ymm1, ymm0, ymmword ptr [ADD0+rip] vpand ymm2, ymm0, ymmword ptr [ADD1+rip] vmovdqa ymmword ptr [rsp+0x220], ymm2 vmovd xmm2, r8d vpbroadcastd ymm2, xmm2 vpaddd ymm2, ymm2, ymm1 vmovdqa ymmword ptr [rsp+0x240], ymm2 vpxor ymm1, ymm1, ymmword ptr [CMP_MSB_MASK+rip] vpxor ymm2, ymm2, ymmword ptr [CMP_MSB_MASK+rip] vpcmpgtd ymm2, ymm1, ymm2 shr r8, 32 vmovd xmm3, r8d vpbroadcastd ymm3, xmm3 vpsubd ymm3, ymm3, ymm2 vmovdqa ymmword ptr [rsp+0x260], ymm3 shl rdx, 6 mov qword ptr [rsp+0x2A0], rdx cmp rsi, 8 jc 3f 2: vpbroadcastd ymm0, dword ptr [rcx] vpbroadcastd ymm1, dword ptr [rcx+0x4] vpbroadcastd ymm2, dword ptr [rcx+0x8] vpbroadcastd ymm3, dword ptr [rcx+0xC] vpbroadcastd ymm4, dword ptr [rcx+0x10] vpbroadcastd ymm5, dword ptr [rcx+0x14] vpbroadcastd ymm6, dword ptr [rcx+0x18] vpbroadcastd ymm7, dword ptr [rcx+0x1C] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] mov r12, qword ptr [rdi+0x20] mov r13, qword ptr [rdi+0x28] mov r14, qword ptr [rdi+0x30] mov r15, qword ptr [rdi+0x38] movzx eax, byte ptr [rbp+0x38] movzx ebx, byte ptr [rbp+0x40] or eax, ebx xor edx, edx .p2align 5 9: movzx ebx, byte ptr [rbp+0x48] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+0x2A0] cmove eax, ebx mov dword ptr [rsp+0x200], eax vmovups xmm8, xmmword ptr [r8+rdx-0x40] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x40], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x40] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x40], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x40] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x40], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x40] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x40], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+0x20], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+0x40], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+0x60], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-0x30] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x30], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x30] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x30], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x30] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x30], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x30] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x30], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+0x80], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+0xA0], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+0xC0], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+0xE0], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-0x20] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x20], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x20] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x20], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x20] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x20], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x20] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x20], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+0x100], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+0x120], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+0x140], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+0x160], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-0x10] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x10], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x10] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x10], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x10] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x10], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x10] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x10], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+0x180], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+0x1A0], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+0x1C0], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+0x1E0], ymm11 vpbroadcastd ymm15, dword ptr [rsp+0x200] prefetcht0 [r8+rdx+0x80] prefetcht0 [r12+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r13+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r14+rdx+0x80] prefetcht0 [r11+rdx+0x80] prefetcht0 [r15+rdx+0x80] vpaddd ymm0, ymm0, ymmword ptr [rsp] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x40] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x80] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xC0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm0, ymmword ptr [rsp+0x240] vpxor ymm13, ymm1, ymmword ptr [rsp+0x260] vpxor ymm14, ymm2, ymmword ptr [BLAKE3_BLOCK_LEN+rip] vpxor ymm15, ymm3, ymm15 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [BLAKE3_IV_0+rip] vpaddd ymm9, ymm13, ymmword ptr [BLAKE3_IV_1+rip] vpaddd ymm10, ymm14, ymmword ptr [BLAKE3_IV_2+rip] vpaddd ymm11, ymm15, ymmword ptr [BLAKE3_IV_3+rip] vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x20] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x60] vpaddd ymm2, ymm2, ymmword ptr [rsp+0xA0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xE0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x100] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x140] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x180] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1C0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x120] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x160] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1A0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1E0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x40] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x60] vpaddd ymm2, ymm2, ymmword ptr [rsp+0xE0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x80] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0xC0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x140] vpaddd ymm2, ymm2, ymmword ptr [rsp] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1A0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x20] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x180] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x120] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1E0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x160] vpaddd ymm1, ymm1, ymmword ptr [rsp+0xA0] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1C0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x100] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x60] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x140] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1A0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xE0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x80] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x180] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x40] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1C0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0xC0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x120] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x160] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x100] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0xA0] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1E0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x20] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x140] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x180] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1C0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1A0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0xE0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x120] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x60] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1E0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x80] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x160] vpaddd ymm2, ymm2, ymmword ptr [rsp+0xA0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x20] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x40] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x100] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xC0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x180] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x120] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x1E0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1C0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x1A0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x160] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x140] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x100] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0xE0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0xA0] vpaddd ymm2, ymm2, ymmword ptr [rsp] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xC0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x40] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x60] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x20] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x80] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x120] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x160] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x100] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1E0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x1C0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0xA0] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x180] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x20] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x1A0] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x40] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x80] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x60] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x140] vpaddd ymm2, ymm2, ymmword ptr [rsp+0xC0] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xE0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x160] vpaddd ymm1, ymm1, ymmword ptr [rsp+0xA0] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x20] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x100] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x1E0] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x120] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xC0] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x1C0] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x40] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x60] vpaddd ymm3, ymm3, ymmword ptr [rsp+0xE0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+0x200], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0x140] vpaddd ymm1, ymm1, ymmword ptr [rsp+0x180] vpaddd ymm2, ymm2, ymmword ptr [rsp+0x80] vpaddd ymm3, ymm3, ymmword ptr [rsp+0x1A0] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8+rip] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+0x200] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vpxor ymm0, ymm0, ymm8 vpxor ymm1, ymm1, ymm9 vpxor ymm2, ymm2, ymm10 vpxor ymm3, ymm3, ymm11 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpxor ymm4, ymm4, ymm12 vpxor ymm5, ymm5, ymm13 vpxor ymm6, ymm6, ymm14 vpxor ymm7, ymm7, ymm15 movzx eax, byte ptr [rbp+0x38] jne 9b mov rbx, qword ptr [rbp+0x50] vunpcklps ymm8, ymm0, ymm1 vunpcklps ymm9, ymm2, ymm3 vunpckhps ymm10, ymm0, ymm1 vunpcklps ymm11, ymm4, ymm5 vunpcklps ymm0, ymm6, ymm7 vshufps ymm12, ymm8, ymm9, 78 vblendps ymm1, ymm8, ymm12, 0xCC vshufps ymm8, ymm11, ymm0, 78 vunpckhps ymm13, ymm2, ymm3 vblendps ymm2, ymm11, ymm8, 0xCC vblendps ymm3, ymm12, ymm9, 0xCC vperm2f128 ymm12, ymm1, ymm2, 0x20 vmovups ymmword ptr [rbx], ymm12 vunpckhps ymm14, ymm4, ymm5 vblendps ymm4, ymm8, ymm0, 0xCC vunpckhps ymm15, ymm6, ymm7 vperm2f128 ymm7, ymm3, ymm4, 0x20 vmovups ymmword ptr [rbx+0x20], ymm7 vshufps ymm5, ymm10, ymm13, 78 vblendps ymm6, ymm5, ymm13, 0xCC vshufps ymm13, ymm14, ymm15, 78 vblendps ymm10, ymm10, ymm5, 0xCC vblendps ymm14, ymm14, ymm13, 0xCC vperm2f128 ymm8, ymm10, ymm14, 0x20 vmovups ymmword ptr [rbx+0x40], ymm8 vblendps ymm15, ymm13, ymm15, 0xCC vperm2f128 ymm13, ymm6, ymm15, 0x20 vmovups ymmword ptr [rbx+0x60], ymm13 vperm2f128 ymm9, ymm1, ymm2, 0x31 vperm2f128 ymm11, ymm3, ymm4, 0x31 vmovups ymmword ptr [rbx+0x80], ymm9 vperm2f128 ymm14, ymm10, ymm14, 0x31 vperm2f128 ymm15, ymm6, ymm15, 0x31 vmovups ymmword ptr [rbx+0xA0], ymm11 vmovups ymmword ptr [rbx+0xC0], ymm14 vmovups ymmword ptr [rbx+0xE0], ymm15 vmovdqa ymm0, ymmword ptr [rsp+0x220] vpaddd ymm1, ymm0, ymmword ptr [rsp+0x240] vmovdqa ymmword ptr [rsp+0x240], ymm1 vpxor ymm0, ymm0, ymmword ptr [CMP_MSB_MASK+rip] vpxor ymm2, ymm1, ymmword ptr [CMP_MSB_MASK+rip] vpcmpgtd ymm2, ymm0, ymm2 vmovdqa ymm0, ymmword ptr [rsp+0x260] vpsubd ymm2, ymm0, ymm2 vmovdqa ymmword ptr [rsp+0x260], ymm2 add rdi, 64 add rbx, 256 mov qword ptr [rbp+0x50], rbx sub rsi, 8 cmp rsi, 8 jnc 2b test rsi, rsi jnz 3f 4: vzeroupper mov rsp, rbp pop rbp pop rbx pop r12 pop r13 pop r14 pop r15 ret .p2align 5 3: mov rbx, qword ptr [rbp+0x50] mov r15, qword ptr [rsp+0x2A0] movzx r13d, byte ptr [rbp+0x38] movzx r12d, byte ptr [rbp+0x48] test rsi, 0x4 je 3f vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+0x10] vmovdqa ymm8, ymm0 vmovdqa ymm9, ymm1 vbroadcasti128 ymm12, xmmword ptr [rsp+0x240] vbroadcasti128 ymm13, xmmword ptr [rsp+0x260] vpunpckldq ymm14, ymm12, ymm13 vpunpckhdq ymm15, ymm12, ymm13 vpermq ymm14, ymm14, 0x50 vpermq ymm15, ymm15, 0x50 vbroadcasti128 ymm12, xmmword ptr [BLAKE3_BLOCK_LEN+rip] vpblendd ymm14, ymm14, ymm12, 0x44 vpblendd ymm15, ymm15, ymm12, 0x44 vmovdqa ymmword ptr [rsp], ymm14 vmovdqa ymmword ptr [rsp+0x20], ymm15 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+0x200], eax vmovups ymm2, ymmword ptr [r8+rdx-0x40] vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-0x40], 0x01 vmovups ymm3, ymmword ptr [r8+rdx-0x30] vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-0x30], 0x01 vshufps ymm4, ymm2, ymm3, 136 vshufps ymm5, ymm2, ymm3, 221 vmovups ymm2, ymmword ptr [r8+rdx-0x20] vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-0x20], 0x01 vmovups ymm3, ymmword ptr [r8+rdx-0x10] vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-0x10], 0x01 vshufps ymm6, ymm2, ymm3, 136 vshufps ymm7, ymm2, ymm3, 221 vpshufd ymm6, ymm6, 0x93 vpshufd ymm7, ymm7, 0x93 vmovups ymm10, ymmword ptr [r10+rdx-0x40] vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-0x40], 0x01 vmovups ymm11, ymmword ptr [r10+rdx-0x30] vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-0x30], 0x01 vshufps ymm12, ymm10, ymm11, 136 vshufps ymm13, ymm10, ymm11, 221 vmovups ymm10, ymmword ptr [r10+rdx-0x20] vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-0x20], 0x01 vmovups ymm11, ymmword ptr [r10+rdx-0x10] vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-0x10], 0x01 vshufps ymm14, ymm10, ymm11, 136 vshufps ymm15, ymm10, ymm11, 221 vpshufd ymm14, ymm14, 0x93 vpshufd ymm15, ymm15, 0x93 prefetcht0 [r8+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r11+rdx+0x80] vpbroadcastd ymm2, dword ptr [rsp+0x200] vmovdqa ymm3, ymmword ptr [rsp] vmovdqa ymm11, ymmword ptr [rsp+0x20] vpblendd ymm3, ymm3, ymm2, 0x88 vpblendd ymm11, ymm11, ymm2, 0x88 vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip] vmovdqa ymm10, ymm2 mov al, 7 9: vpaddd ymm0, ymm0, ymm4 vpaddd ymm8, ymm8, ymm12 vmovdqa ymmword ptr [rsp+0x40], ymm4 nop vmovdqa ymmword ptr [rsp+0x60], ymm12 nop vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT16+rip] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 12 vpslld ymm9, ymm9, 20 vpor ymm9, ymm9, ymm4 vpaddd ymm0, ymm0, ymm5 vpaddd ymm8, ymm8, ymm13 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vmovdqa ymmword ptr [rsp+0x80], ymm5 vmovdqa ymmword ptr [rsp+0xA0], ymm13 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT8+rip] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 7 vpslld ymm9, ymm9, 25 vpor ymm9, ymm9, ymm4 vpshufd ymm0, ymm0, 0x93 vpshufd ymm8, ymm8, 0x93 vpshufd ymm3, ymm3, 0x4E vpshufd ymm11, ymm11, 0x4E vpshufd ymm2, ymm2, 0x39 vpshufd ymm10, ymm10, 0x39 vpaddd ymm0, ymm0, ymm6 vpaddd ymm8, ymm8, ymm14 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT16+rip] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 12 vpslld ymm9, ymm9, 20 vpor ymm9, ymm9, ymm4 vpaddd ymm0, ymm0, ymm7 vpaddd ymm8, ymm8, ymm15 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT8+rip] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 7 vpslld ymm9, ymm9, 25 vpor ymm9, ymm9, ymm4 vpshufd ymm0, ymm0, 0x39 vpshufd ymm8, ymm8, 0x39 vpshufd ymm3, ymm3, 0x4E vpshufd ymm11, ymm11, 0x4E vpshufd ymm2, ymm2, 0x93 vpshufd ymm10, ymm10, 0x93 dec al je 9f vmovdqa ymm4, ymmword ptr [rsp+0x40] vmovdqa ymm5, ymmword ptr [rsp+0x80] vshufps ymm12, ymm4, ymm5, 214 vpshufd ymm13, ymm4, 0x0F vpshufd ymm4, ymm12, 0x39 vshufps ymm12, ymm6, ymm7, 250 vpblendd ymm13, ymm13, ymm12, 0xAA vpunpcklqdq ymm12, ymm7, ymm5 vpblendd ymm12, ymm12, ymm6, 0x88 vpshufd ymm12, ymm12, 0x78 vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 0x1E vmovdqa ymmword ptr [rsp+0x40], ymm13 vmovdqa ymmword ptr [rsp+0x80], ymm12 vmovdqa ymm12, ymmword ptr [rsp+0x60] vmovdqa ymm13, ymmword ptr [rsp+0xA0] vshufps ymm5, ymm12, ymm13, 214 vpshufd ymm6, ymm12, 0x0F vpshufd ymm12, ymm5, 0x39 vshufps ymm5, ymm14, ymm15, 250 vpblendd ymm6, ymm6, ymm5, 0xAA vpunpcklqdq ymm5, ymm15, ymm13 vpblendd ymm5, ymm5, ymm14, 0x88 vpshufd ymm5, ymm5, 0x78 vpunpckhdq ymm13, ymm13, ymm15 vpunpckldq ymm14, ymm14, ymm13 vpshufd ymm15, ymm14, 0x1E vmovdqa ymm13, ymm6 vmovdqa ymm14, ymm5 vmovdqa ymm5, ymmword ptr [rsp+0x40] vmovdqa ymm6, ymmword ptr [rsp+0x80] jmp 9b 9: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 vpxor ymm8, ymm8, ymm10 vpxor ymm9, ymm9, ymm11 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 vextracti128 xmmword ptr [rbx+0x20], ymm0, 0x01 vextracti128 xmmword ptr [rbx+0x30], ymm1, 0x01 vmovdqu xmmword ptr [rbx+0x40], xmm8 vmovdqu xmmword ptr [rbx+0x50], xmm9 vextracti128 xmmword ptr [rbx+0x60], ymm8, 0x01 vextracti128 xmmword ptr [rbx+0x70], ymm9, 0x01 vmovaps xmm8, xmmword ptr [rsp+0x280] vmovaps xmm0, xmmword ptr [rsp+0x240] vmovaps xmm1, xmmword ptr [rsp+0x250] vmovaps xmm2, xmmword ptr [rsp+0x260] vmovaps xmm3, xmmword ptr [rsp+0x270] vblendvps xmm0, xmm0, xmm1, xmm8 vblendvps xmm2, xmm2, xmm3, xmm8 vmovaps xmmword ptr [rsp+0x240], xmm0 vmovaps xmmword ptr [rsp+0x260], xmm2 add rbx, 128 add rdi, 32 sub rsi, 4 3: test rsi, 0x2 je 3f vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+0x10] vmovd xmm13, dword ptr [rsp+0x240] vpinsrd xmm13, xmm13, dword ptr [rsp+0x260], 1 vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vmovd xmm14, dword ptr [rsp+0x244] vpinsrd xmm14, xmm14, dword ptr [rsp+0x264], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vinserti128 ymm13, ymm13, xmm14, 0x01 vbroadcasti128 ymm14, xmmword ptr [ROT16+rip] vbroadcasti128 ymm15, xmmword ptr [ROT8+rip] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+0x200], eax vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip] vpbroadcastd ymm8, dword ptr [rsp+0x200] vpblendd ymm3, ymm13, ymm8, 0x88 vmovups ymm8, ymmword ptr [r8+rdx-0x40] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-0x40], 0x01 vmovups ymm9, ymmword ptr [r8+rdx-0x30] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-0x30], 0x01 vshufps ymm4, ymm8, ymm9, 136 vshufps ymm5, ymm8, ymm9, 221 vmovups ymm8, ymmword ptr [r8+rdx-0x20] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-0x20], 0x01 vmovups ymm9, ymmword ptr [r8+rdx-0x10] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-0x10], 0x01 vshufps ymm6, ymm8, ymm9, 136 vshufps ymm7, ymm8, ymm9, 221 vpshufd ymm6, ymm6, 0x93 vpshufd ymm7, ymm7, 0x93 mov al, 7 9: vpaddd ymm0, ymm0, ymm4 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm14 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm8 vpaddd ymm0, ymm0, ymm5 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm15 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm8 vpshufd ymm0, ymm0, 0x93 vpshufd ymm3, ymm3, 0x4E vpshufd ymm2, ymm2, 0x39 vpaddd ymm0, ymm0, ymm6 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm14 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm8 vpaddd ymm0, ymm0, ymm7 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm15 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm8 vpshufd ymm0, ymm0, 0x39 vpshufd ymm3, ymm3, 0x4E vpshufd ymm2, ymm2, 0x93 dec al jz 9f vshufps ymm8, ymm4, ymm5, 214 vpshufd ymm9, ymm4, 0x0F vpshufd ymm4, ymm8, 0x39 vshufps ymm8, ymm6, ymm7, 250 vpblendd ymm9, ymm9, ymm8, 0xAA vpunpcklqdq ymm8, ymm7, ymm5 vpblendd ymm8, ymm8, ymm6, 0x88 vpshufd ymm8, ymm8, 0x78 vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 0x1E vmovdqa ymm5, ymm9 vmovdqa ymm6, ymm8 jmp 9b 9: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 vextracti128 xmmword ptr [rbx+0x20], ymm0, 0x01 vextracti128 xmmword ptr [rbx+0x30], ymm1, 0x01 vmovaps ymm8, ymmword ptr [rsp+0x280] vmovaps ymm0, ymmword ptr [rsp+0x240] vmovups ymm1, ymmword ptr [rsp+0x248] vmovaps ymm2, ymmword ptr [rsp+0x260] vmovups ymm3, ymmword ptr [rsp+0x268] vblendvps ymm0, ymm0, ymm1, ymm8 vblendvps ymm2, ymm2, ymm3, ymm8 vmovaps ymmword ptr [rsp+0x240], ymm0 vmovaps ymmword ptr [rsp+0x260], ymm2 add rbx, 64 add rdi, 16 sub rsi, 2 3: test rsi, 0x1 je 4b vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+0x10] vmovd xmm3, dword ptr [rsp+0x240] vpinsrd xmm3, xmm3, dword ptr [rsp+0x260], 1 vpinsrd xmm13, xmm3, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vmovdqa xmm14, xmmword ptr [ROT16+rip] vmovdqa xmm15, xmmword ptr [ROT8+rip] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d vmovdqa xmm2, xmmword ptr [BLAKE3_IV+rip] vmovdqa xmm3, xmm13 vpinsrd xmm3, xmm3, eax, 3 vmovups xmm8, xmmword ptr [r8+rdx-0x40] vmovups xmm9, xmmword ptr [r8+rdx-0x30] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [r8+rdx-0x20] vmovups xmm9, xmmword ptr [r8+rdx-0x10] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 0x93 vpshufd xmm7, xmm7, 0x93 mov al, 7 9: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm14 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 12 vpslld xmm1, xmm1, 20 vpor xmm1, xmm1, xmm8 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm15 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 7 vpslld xmm1, xmm1, 25 vpor xmm1, xmm1, xmm8 vpshufd xmm0, xmm0, 0x93 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x39 vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm14 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 12 vpslld xmm1, xmm1, 20 vpor xmm1, xmm1, xmm8 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm15 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 7 vpslld xmm1, xmm1, 25 vpor xmm1, xmm1, xmm8 vpshufd xmm0, xmm0, 0x39 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x93 dec al jz 9f vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0x0F vpshufd xmm4, xmm8, 0x39 vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0xAA vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 0x88 vpshufd xmm8, xmm8, 0x78 vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 0x1E vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp 9b 9: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 jmp 4b #ifdef __APPLE__ .static_data #else .section .rodata #endif .p2align 6 ADD0: .long 0, 1, 2, 3, 4, 5, 6, 7 ADD1: .long 8, 8, 8, 8, 8, 8, 8, 8 BLAKE3_IV_0: .long 0x6A09E667, 0x6A09E667, 0x6A09E667, 0x6A09E667 .long 0x6A09E667, 0x6A09E667, 0x6A09E667, 0x6A09E667 BLAKE3_IV_1: .long 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, 0xBB67AE85 .long 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, 0xBB67AE85 BLAKE3_IV_2: .long 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, 0x3C6EF372 .long 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, 0x3C6EF372 BLAKE3_IV_3: .long 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, 0xA54FF53A .long 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, 0xA54FF53A BLAKE3_BLOCK_LEN: .long 0x00000040, 0x00000040, 0x00000040, 0x00000040 .long 0x00000040, 0x00000040, 0x00000040, 0x00000040 ROT16: .byte 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 ROT8: .byte 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 CMP_MSB_MASK: .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 BLAKE3_IV: .long 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A ================================================ FILE: src/third_party/blake3/asm/blake3_avx2_x86-64_windows_msvc.asm ================================================ public _blake3_hash_many_avx2 public blake3_hash_many_avx2 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 blake3_hash_many_avx2 PROC _blake3_hash_many_avx2 PROC push r15 push r14 push r13 push r12 push rsi push rdi push rbx push rbp mov rbp, rsp sub rsp, 880 and rsp, 0FFFFFFFFFFFFFFC0H vmovdqa xmmword ptr [rsp+2D0H], xmm6 vmovdqa xmmword ptr [rsp+2E0H], xmm7 vmovdqa xmmword ptr [rsp+2F0H], xmm8 vmovdqa xmmword ptr [rsp+300H], xmm9 vmovdqa xmmword ptr [rsp+310H], xmm10 vmovdqa xmmword ptr [rsp+320H], xmm11 vmovdqa xmmword ptr [rsp+330H], xmm12 vmovdqa xmmword ptr [rsp+340H], xmm13 vmovdqa xmmword ptr [rsp+350H], xmm14 vmovdqa xmmword ptr [rsp+360H], xmm15 mov rdi, rcx mov rsi, rdx mov rdx, r8 mov rcx, r9 mov r8, qword ptr [rbp+68H] movzx r9, byte ptr [rbp+70H] neg r9d vmovd xmm0, r9d vpbroadcastd ymm0, xmm0 vmovdqa ymmword ptr [rsp+260H], ymm0 vpand ymm1, ymm0, ymmword ptr [ADD0] vpand ymm2, ymm0, ymmword ptr [ADD1] vmovdqa ymmword ptr [rsp+2A0H], ymm2 vmovd xmm2, r8d vpbroadcastd ymm2, xmm2 vpaddd ymm2, ymm2, ymm1 vmovdqa ymmword ptr [rsp+220H], ymm2 vpxor ymm1, ymm1, ymmword ptr [CMP_MSB_MASK] vpxor ymm2, ymm2, ymmword ptr [CMP_MSB_MASK] vpcmpgtd ymm2, ymm1, ymm2 shr r8, 32 vmovd xmm3, r8d vpbroadcastd ymm3, xmm3 vpsubd ymm3, ymm3, ymm2 vmovdqa ymmword ptr [rsp+240H], ymm3 shl rdx, 6 mov qword ptr [rsp+2C0H], rdx cmp rsi, 8 jc final7blocks outerloop8: vpbroadcastd ymm0, dword ptr [rcx] vpbroadcastd ymm1, dword ptr [rcx+4H] vpbroadcastd ymm2, dword ptr [rcx+8H] vpbroadcastd ymm3, dword ptr [rcx+0CH] vpbroadcastd ymm4, dword ptr [rcx+10H] vpbroadcastd ymm5, dword ptr [rcx+14H] vpbroadcastd ymm6, dword ptr [rcx+18H] vpbroadcastd ymm7, dword ptr [rcx+1CH] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] mov r12, qword ptr [rdi+20H] mov r13, qword ptr [rdi+28H] mov r14, qword ptr [rdi+30H] mov r15, qword ptr [rdi+38H] movzx eax, byte ptr [rbp+78H] movzx ebx, byte ptr [rbp+80H] or eax, ebx xor edx, edx ALIGN 16 innerloop8: movzx ebx, byte ptr [rbp+88H] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+2C0H] cmove eax, ebx mov dword ptr [rsp+200H], eax vmovups xmm8, xmmword ptr [r8+rdx-40H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H vmovups xmm9, xmmword ptr [r9+rdx-40H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-40H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H vmovups xmm11, xmmword ptr [r11+rdx-40H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+20H], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+40H], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+60H], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-30H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H vmovups xmm9, xmmword ptr [r9+rdx-30H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-30H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H vmovups xmm11, xmmword ptr [r11+rdx-30H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+80H], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+0A0H], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+0C0H], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+0E0H], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-20H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H vmovups xmm9, xmmword ptr [r9+rdx-20H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-20H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H vmovups xmm11, xmmword ptr [r11+rdx-20H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+100H], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+120H], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+140H], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+160H], ymm11 vmovups xmm8, xmmword ptr [r8+rdx-10H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H vmovups xmm9, xmmword ptr [r9+rdx-10H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-10H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H vmovups xmm11, xmmword ptr [r11+rdx-10H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm8, ymm12, ymm14, 136 vmovaps ymmword ptr [rsp+180H], ymm8 vshufps ymm9, ymm12, ymm14, 221 vmovaps ymmword ptr [rsp+1A0H], ymm9 vshufps ymm10, ymm13, ymm15, 136 vmovaps ymmword ptr [rsp+1C0H], ymm10 vshufps ymm11, ymm13, ymm15, 221 vmovaps ymmword ptr [rsp+1E0H], ymm11 vpbroadcastd ymm15, dword ptr [rsp+200H] prefetcht0 byte ptr [r8+rdx+80H] prefetcht0 byte ptr [r12+rdx+80H] prefetcht0 byte ptr [r9+rdx+80H] prefetcht0 byte ptr [r13+rdx+80H] prefetcht0 byte ptr [r10+rdx+80H] prefetcht0 byte ptr [r14+rdx+80H] prefetcht0 byte ptr [r11+rdx+80H] prefetcht0 byte ptr [r15+rdx+80H] vpaddd ymm0, ymm0, ymmword ptr [rsp] vpaddd ymm1, ymm1, ymmword ptr [rsp+40H] vpaddd ymm2, ymm2, ymmword ptr [rsp+80H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm0, ymmword ptr [rsp+220H] vpxor ymm13, ymm1, ymmword ptr [rsp+240H] vpxor ymm14, ymm2, ymmword ptr [BLAKE3_BLOCK_LEN] vpxor ymm15, ymm3, ymm15 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [BLAKE3_IV_0] vpaddd ymm9, ymm13, ymmword ptr [BLAKE3_IV_1] vpaddd ymm10, ymm14, ymmword ptr [BLAKE3_IV_2] vpaddd ymm11, ymm15, ymmword ptr [BLAKE3_IV_3] vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+20H] vpaddd ymm1, ymm1, ymmword ptr [rsp+60H] vpaddd ymm2, ymm2, ymmword ptr [rsp+0A0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+100H] vpaddd ymm1, ymm1, ymmword ptr [rsp+140H] vpaddd ymm2, ymm2, ymmword ptr [rsp+180H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+120H] vpaddd ymm1, ymm1, ymmword ptr [rsp+160H] vpaddd ymm2, ymm2, ymmword ptr [rsp+1A0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+40H] vpaddd ymm1, ymm1, ymmword ptr [rsp+60H] vpaddd ymm2, ymm2, ymmword ptr [rsp+0E0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+80H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0C0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+140H] vpaddd ymm2, ymm2, ymmword ptr [rsp] vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+20H] vpaddd ymm1, ymm1, ymmword ptr [rsp+180H] vpaddd ymm2, ymm2, ymmword ptr [rsp+120H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+160H] vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H] vpaddd ymm2, ymm2, ymmword ptr [rsp+1C0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+100H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+60H] vpaddd ymm1, ymm1, ymmword ptr [rsp+140H] vpaddd ymm2, ymm2, ymmword ptr [rsp+1A0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+80H] vpaddd ymm1, ymm1, ymmword ptr [rsp+180H] vpaddd ymm2, ymm2, ymmword ptr [rsp+40H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0C0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+120H] vpaddd ymm2, ymm2, ymmword ptr [rsp+160H] vpaddd ymm3, ymm3, ymmword ptr [rsp+100H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0A0H] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+1E0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+20H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+140H] vpaddd ymm1, ymm1, ymmword ptr [rsp+180H] vpaddd ymm2, ymm2, ymmword ptr [rsp+1C0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0E0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+120H] vpaddd ymm2, ymm2, ymmword ptr [rsp+60H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+80H] vpaddd ymm1, ymm1, ymmword ptr [rsp+160H] vpaddd ymm2, ymm2, ymmword ptr [rsp+0A0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+20H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp] vpaddd ymm1, ymm1, ymmword ptr [rsp+40H] vpaddd ymm2, ymm2, ymmword ptr [rsp+100H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+180H] vpaddd ymm1, ymm1, ymmword ptr [rsp+120H] vpaddd ymm2, ymm2, ymmword ptr [rsp+1E0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1C0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+1A0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+160H] vpaddd ymm2, ymm2, ymmword ptr [rsp+140H] vpaddd ymm3, ymm3, ymmword ptr [rsp+100H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+0E0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H] vpaddd ymm2, ymm2, ymmword ptr [rsp] vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+40H] vpaddd ymm1, ymm1, ymmword ptr [rsp+60H] vpaddd ymm2, ymm2, ymmword ptr [rsp+20H] vpaddd ymm3, ymm3, ymmword ptr [rsp+80H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+120H] vpaddd ymm1, ymm1, ymmword ptr [rsp+160H] vpaddd ymm2, ymm2, ymmword ptr [rsp+100H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1E0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+1C0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H] vpaddd ymm2, ymm2, ymmword ptr [rsp+180H] vpaddd ymm3, ymm3, ymmword ptr [rsp+20H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+1A0H] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+40H] vpaddd ymm3, ymm3, ymmword ptr [rsp+80H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+60H] vpaddd ymm1, ymm1, ymmword ptr [rsp+140H] vpaddd ymm2, ymm2, ymmword ptr [rsp+0C0H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+160H] vpaddd ymm1, ymm1, ymmword ptr [rsp+0A0H] vpaddd ymm2, ymm2, ymmword ptr [rsp+20H] vpaddd ymm3, ymm3, ymmword ptr [rsp+100H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+1E0H] vpaddd ymm1, ymm1, ymmword ptr [rsp] vpaddd ymm2, ymm2, ymmword ptr [rsp+120H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0C0H] vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxor ymm12, ymm12, ymm0 vpxor ymm13, ymm13, ymm1 vpxor ymm14, ymm14, ymm2 vpxor ymm15, ymm15, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpshufb ymm15, ymm15, ymm8 vpaddd ymm8, ymm12, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxor ymm4, ymm4, ymm8 vpxor ymm5, ymm5, ymm9 vpxor ymm6, ymm6, ymm10 vpxor ymm7, ymm7, ymm11 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+1C0H] vpaddd ymm1, ymm1, ymmword ptr [rsp+40H] vpaddd ymm2, ymm2, ymmword ptr [rsp+60H] vpaddd ymm3, ymm3, ymmword ptr [rsp+0E0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT16] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vmovdqa ymmword ptr [rsp+200H], ymm8 vpsrld ymm8, ymm5, 12 vpslld ymm5, ymm5, 20 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 12 vpslld ymm6, ymm6, 20 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 12 vpslld ymm7, ymm7, 20 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 12 vpslld ymm4, ymm4, 20 vpor ymm4, ymm4, ymm8 vpaddd ymm0, ymm0, ymmword ptr [rsp+140H] vpaddd ymm1, ymm1, ymmword ptr [rsp+180H] vpaddd ymm2, ymm2, ymmword ptr [rsp+80H] vpaddd ymm3, ymm3, ymmword ptr [rsp+1A0H] vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxor ymm15, ymm15, ymm0 vpxor ymm12, ymm12, ymm1 vpxor ymm13, ymm13, ymm2 vpxor ymm14, ymm14, ymm3 vbroadcasti128 ymm8, xmmword ptr [ROT8] vpshufb ymm15, ymm15, ymm8 vpshufb ymm12, ymm12, ymm8 vpshufb ymm13, ymm13, ymm8 vpshufb ymm14, ymm14, ymm8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm13, ymmword ptr [rsp+200H] vpaddd ymm9, ymm9, ymm14 vpxor ymm5, ymm5, ymm10 vpxor ymm6, ymm6, ymm11 vpxor ymm7, ymm7, ymm8 vpxor ymm4, ymm4, ymm9 vpxor ymm0, ymm0, ymm8 vpxor ymm1, ymm1, ymm9 vpxor ymm2, ymm2, ymm10 vpxor ymm3, ymm3, ymm11 vpsrld ymm8, ymm5, 7 vpslld ymm5, ymm5, 25 vpor ymm5, ymm5, ymm8 vpsrld ymm8, ymm6, 7 vpslld ymm6, ymm6, 25 vpor ymm6, ymm6, ymm8 vpsrld ymm8, ymm7, 7 vpslld ymm7, ymm7, 25 vpor ymm7, ymm7, ymm8 vpsrld ymm8, ymm4, 7 vpslld ymm4, ymm4, 25 vpor ymm4, ymm4, ymm8 vpxor ymm4, ymm4, ymm12 vpxor ymm5, ymm5, ymm13 vpxor ymm6, ymm6, ymm14 vpxor ymm7, ymm7, ymm15 movzx eax, byte ptr [rbp+78H] jne innerloop8 mov rbx, qword ptr [rbp+90H] vunpcklps ymm8, ymm0, ymm1 vunpcklps ymm9, ymm2, ymm3 vunpckhps ymm10, ymm0, ymm1 vunpcklps ymm11, ymm4, ymm5 vunpcklps ymm0, ymm6, ymm7 vshufps ymm12, ymm8, ymm9, 78 vblendps ymm1, ymm8, ymm12, 0CCH vshufps ymm8, ymm11, ymm0, 78 vunpckhps ymm13, ymm2, ymm3 vblendps ymm2, ymm11, ymm8, 0CCH vblendps ymm3, ymm12, ymm9, 0CCH vperm2f128 ymm12, ymm1, ymm2, 20H vmovups ymmword ptr [rbx], ymm12 vunpckhps ymm14, ymm4, ymm5 vblendps ymm4, ymm8, ymm0, 0CCH vunpckhps ymm15, ymm6, ymm7 vperm2f128 ymm7, ymm3, ymm4, 20H vmovups ymmword ptr [rbx+20H], ymm7 vshufps ymm5, ymm10, ymm13, 78 vblendps ymm6, ymm5, ymm13, 0CCH vshufps ymm13, ymm14, ymm15, 78 vblendps ymm10, ymm10, ymm5, 0CCH vblendps ymm14, ymm14, ymm13, 0CCH vperm2f128 ymm8, ymm10, ymm14, 20H vmovups ymmword ptr [rbx+40H], ymm8 vblendps ymm15, ymm13, ymm15, 0CCH vperm2f128 ymm13, ymm6, ymm15, 20H vmovups ymmword ptr [rbx+60H], ymm13 vperm2f128 ymm9, ymm1, ymm2, 31H vperm2f128 ymm11, ymm3, ymm4, 31H vmovups ymmword ptr [rbx+80H], ymm9 vperm2f128 ymm14, ymm10, ymm14, 31H vperm2f128 ymm15, ymm6, ymm15, 31H vmovups ymmword ptr [rbx+0A0H], ymm11 vmovups ymmword ptr [rbx+0C0H], ymm14 vmovups ymmword ptr [rbx+0E0H], ymm15 vmovdqa ymm0, ymmword ptr [rsp+2A0H] vpaddd ymm1, ymm0, ymmword ptr [rsp+220H] vmovdqa ymmword ptr [rsp+220H], ymm1 vpxor ymm0, ymm0, ymmword ptr [CMP_MSB_MASK] vpxor ymm2, ymm1, ymmword ptr [CMP_MSB_MASK] vpcmpgtd ymm2, ymm0, ymm2 vmovdqa ymm0, ymmword ptr [rsp+240H] vpsubd ymm2, ymm0, ymm2 vmovdqa ymmword ptr [rsp+240H], ymm2 add rdi, 64 add rbx, 256 mov qword ptr [rbp+90H], rbx sub rsi, 8 cmp rsi, 8 jnc outerloop8 test rsi, rsi jnz final7blocks unwind: vzeroupper vmovdqa xmm6, xmmword ptr [rsp+2D0H] vmovdqa xmm7, xmmword ptr [rsp+2E0H] vmovdqa xmm8, xmmword ptr [rsp+2F0H] vmovdqa xmm9, xmmword ptr [rsp+300H] vmovdqa xmm10, xmmword ptr [rsp+310H] vmovdqa xmm11, xmmword ptr [rsp+320H] vmovdqa xmm12, xmmword ptr [rsp+330H] vmovdqa xmm13, xmmword ptr [rsp+340H] vmovdqa xmm14, xmmword ptr [rsp+350H] vmovdqa xmm15, xmmword ptr [rsp+360H] mov rsp, rbp pop rbp pop rbx pop rdi pop rsi pop r12 pop r13 pop r14 pop r15 ret ALIGN 16 final7blocks: mov rbx, qword ptr [rbp+90H] mov r15, qword ptr [rsp+2C0H] movzx r13d, byte ptr [rbp+78H] movzx r12d, byte ptr [rbp+88H] test rsi, 4H je final3blocks vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+10H] vmovdqa ymm8, ymm0 vmovdqa ymm9, ymm1 vbroadcasti128 ymm12, xmmword ptr [rsp+220H] vbroadcasti128 ymm13, xmmword ptr [rsp+240H] vpunpckldq ymm14, ymm12, ymm13 vpunpckhdq ymm15, ymm12, ymm13 vpermq ymm14, ymm14, 50H vpermq ymm15, ymm15, 50H vbroadcasti128 ymm12, xmmword ptr [BLAKE3_BLOCK_LEN] vpblendd ymm14, ymm14, ymm12, 44H vpblendd ymm15, ymm15, ymm12, 44H vmovdqa ymmword ptr [rsp], ymm14 vmovdqa ymmword ptr [rsp+20H], ymm15 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop4: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+200H], eax vmovups ymm2, ymmword ptr [r8+rdx-40H] vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-40H], 01H vmovups ymm3, ymmword ptr [r8+rdx-30H] vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-30H], 01H vshufps ymm4, ymm2, ymm3, 136 vshufps ymm5, ymm2, ymm3, 221 vmovups ymm2, ymmword ptr [r8+rdx-20H] vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-20H], 01H vmovups ymm3, ymmword ptr [r8+rdx-10H] vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-10H], 01H vshufps ymm6, ymm2, ymm3, 136 vshufps ymm7, ymm2, ymm3, 221 vpshufd ymm6, ymm6, 93H vpshufd ymm7, ymm7, 93H vmovups ymm10, ymmword ptr [r10+rdx-40H] vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-40H], 01H vmovups ymm11, ymmword ptr [r10+rdx-30H] vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-30H], 01H vshufps ymm12, ymm10, ymm11, 136 vshufps ymm13, ymm10, ymm11, 221 vmovups ymm10, ymmword ptr [r10+rdx-20H] vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-20H], 01H vmovups ymm11, ymmword ptr [r10+rdx-10H] vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-10H], 01H vshufps ymm14, ymm10, ymm11, 136 vshufps ymm15, ymm10, ymm11, 221 vpshufd ymm14, ymm14, 93H vpshufd ymm15, ymm15, 93H vpbroadcastd ymm2, dword ptr [rsp+200H] vmovdqa ymm3, ymmword ptr [rsp] vmovdqa ymm11, ymmword ptr [rsp+20H] vpblendd ymm3, ymm3, ymm2, 88H vpblendd ymm11, ymm11, ymm2, 88H vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV] vmovdqa ymm10, ymm2 mov al, 7 roundloop4: vpaddd ymm0, ymm0, ymm4 vpaddd ymm8, ymm8, ymm12 vmovdqa ymmword ptr [rsp+40H], ymm4 nop vmovdqa ymmword ptr [rsp+60H], ymm12 nop vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT16] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 12 vpslld ymm9, ymm9, 20 vpor ymm9, ymm9, ymm4 vpaddd ymm0, ymm0, ymm5 vpaddd ymm8, ymm8, ymm13 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vmovdqa ymmword ptr [rsp+80H], ymm5 vmovdqa ymmword ptr [rsp+0A0H], ymm13 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT8] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 7 vpslld ymm9, ymm9, 25 vpor ymm9, ymm9, ymm4 vpshufd ymm0, ymm0, 93H vpshufd ymm8, ymm8, 93H vpshufd ymm3, ymm3, 4EH vpshufd ymm11, ymm11, 4EH vpshufd ymm2, ymm2, 39H vpshufd ymm10, ymm10, 39H vpaddd ymm0, ymm0, ymm6 vpaddd ymm8, ymm8, ymm14 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT16] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 12 vpslld ymm9, ymm9, 20 vpor ymm9, ymm9, ymm4 vpaddd ymm0, ymm0, ymm7 vpaddd ymm8, ymm8, ymm15 vpaddd ymm0, ymm0, ymm1 vpaddd ymm8, ymm8, ymm9 vpxor ymm3, ymm3, ymm0 vpxor ymm11, ymm11, ymm8 vbroadcasti128 ymm4, xmmword ptr [ROT8] vpshufb ymm3, ymm3, ymm4 vpshufb ymm11, ymm11, ymm4 vpaddd ymm2, ymm2, ymm3 vpaddd ymm10, ymm10, ymm11 vpxor ymm1, ymm1, ymm2 vpxor ymm9, ymm9, ymm10 vpsrld ymm4, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm4 vpsrld ymm4, ymm9, 7 vpslld ymm9, ymm9, 25 vpor ymm9, ymm9, ymm4 vpshufd ymm0, ymm0, 39H vpshufd ymm8, ymm8, 39H vpshufd ymm3, ymm3, 4EH vpshufd ymm11, ymm11, 4EH vpshufd ymm2, ymm2, 93H vpshufd ymm10, ymm10, 93H dec al je endroundloop4 vmovdqa ymm4, ymmword ptr [rsp+40H] vmovdqa ymm5, ymmword ptr [rsp+80H] vshufps ymm12, ymm4, ymm5, 214 vpshufd ymm13, ymm4, 0FH vpshufd ymm4, ymm12, 39H vshufps ymm12, ymm6, ymm7, 250 vpblendd ymm13, ymm13, ymm12, 0AAH vpunpcklqdq ymm12, ymm7, ymm5 vpblendd ymm12, ymm12, ymm6, 88H vpshufd ymm12, ymm12, 78H vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 1EH vmovdqa ymmword ptr [rsp+40H], ymm13 vmovdqa ymmword ptr [rsp+80H], ymm12 vmovdqa ymm12, ymmword ptr [rsp+60H] vmovdqa ymm13, ymmword ptr [rsp+0A0H] vshufps ymm5, ymm12, ymm13, 214 vpshufd ymm6, ymm12, 0FH vpshufd ymm12, ymm5, 39H vshufps ymm5, ymm14, ymm15, 250 vpblendd ymm6, ymm6, ymm5, 0AAH vpunpcklqdq ymm5, ymm15, ymm13 vpblendd ymm5, ymm5, ymm14, 88H vpshufd ymm5, ymm5, 78H vpunpckhdq ymm13, ymm13, ymm15 vpunpckldq ymm14, ymm14, ymm13 vpshufd ymm15, ymm14, 1EH vmovdqa ymm13, ymm6 vmovdqa ymm14, ymm5 vmovdqa ymm5, ymmword ptr [rsp+40H] vmovdqa ymm6, ymmword ptr [rsp+80H] jmp roundloop4 endroundloop4: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 vpxor ymm8, ymm8, ymm10 vpxor ymm9, ymm9, ymm11 mov eax, r13d cmp rdx, r15 jne innerloop4 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 vextracti128 xmmword ptr [rbx+20H], ymm0, 01H vextracti128 xmmword ptr [rbx+30H], ymm1, 01H vmovdqu xmmword ptr [rbx+40H], xmm8 vmovdqu xmmword ptr [rbx+50H], xmm9 vextracti128 xmmword ptr [rbx+60H], ymm8, 01H vextracti128 xmmword ptr [rbx+70H], ymm9, 01H vmovaps xmm8, xmmword ptr [rsp+260H] vmovaps xmm0, xmmword ptr [rsp+220H] vmovaps xmm1, xmmword ptr [rsp+230H] vmovaps xmm2, xmmword ptr [rsp+240H] vmovaps xmm3, xmmword ptr [rsp+250H] vblendvps xmm0, xmm0, xmm1, xmm8 vblendvps xmm2, xmm2, xmm3, xmm8 vmovaps xmmword ptr [rsp+220H], xmm0 vmovaps xmmword ptr [rsp+240H], xmm2 add rbx, 128 add rdi, 32 sub rsi, 4 final3blocks: test rsi, 2H je final1blocks vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+10H] vmovd xmm13, dword ptr [rsp+220H] vpinsrd xmm13, xmm13, dword ptr [rsp+240H], 1 vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2 vmovd xmm14, dword ptr [rsp+224H] vpinsrd xmm14, xmm14, dword ptr [rsp+244H], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2 vinserti128 ymm13, ymm13, xmm14, 01H vbroadcasti128 ymm14, xmmword ptr [ROT16] vbroadcasti128 ymm15, xmmword ptr [ROT8] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+200H], eax vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV] vpbroadcastd ymm8, dword ptr [rsp+200H] vpblendd ymm3, ymm13, ymm8, 88H vmovups ymm8, ymmword ptr [r8+rdx-40H] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H vmovups ymm9, ymmword ptr [r8+rdx-30H] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H vshufps ymm4, ymm8, ymm9, 136 vshufps ymm5, ymm8, ymm9, 221 vmovups ymm8, ymmword ptr [r8+rdx-20H] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H vmovups ymm9, ymmword ptr [r8+rdx-10H] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H vshufps ymm6, ymm8, ymm9, 136 vshufps ymm7, ymm8, ymm9, 221 vpshufd ymm6, ymm6, 93H vpshufd ymm7, ymm7, 93H mov al, 7 roundloop2: vpaddd ymm0, ymm0, ymm4 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm14 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm8 vpaddd ymm0, ymm0, ymm5 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm15 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm8 vpshufd ymm0, ymm0, 93H vpshufd ymm3, ymm3, 4EH vpshufd ymm2, ymm2, 39H vpaddd ymm0, ymm0, ymm6 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm14 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 12 vpslld ymm1, ymm1, 20 vpor ymm1, ymm1, ymm8 vpaddd ymm0, ymm0, ymm7 vpaddd ymm0, ymm0, ymm1 vpxor ymm3, ymm3, ymm0 vpshufb ymm3, ymm3, ymm15 vpaddd ymm2, ymm2, ymm3 vpxor ymm1, ymm1, ymm2 vpsrld ymm8, ymm1, 7 vpslld ymm1, ymm1, 25 vpor ymm1, ymm1, ymm8 vpshufd ymm0, ymm0, 39H vpshufd ymm3, ymm3, 4EH vpshufd ymm2, ymm2, 93H dec al jz endroundloop2 vshufps ymm8, ymm4, ymm5, 214 vpshufd ymm9, ymm4, 0FH vpshufd ymm4, ymm8, 39H vshufps ymm8, ymm6, ymm7, 250 vpblendd ymm9, ymm9, ymm8, 0AAH vpunpcklqdq ymm8, ymm7, ymm5 vpblendd ymm8, ymm8, ymm6, 88H vpshufd ymm8, ymm8, 78H vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 1EH vmovdqa ymm5, ymm9 vmovdqa ymm6, ymm8 jmp roundloop2 endroundloop2: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 mov eax, r13d cmp rdx, r15 jne innerloop2 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 vextracti128 xmmword ptr [rbx+20H], ymm0, 01H vextracti128 xmmword ptr [rbx+30H], ymm1, 01H vmovaps ymm8, ymmword ptr [rsp+260H] vmovaps ymm0, ymmword ptr [rsp+220H] vmovups ymm1, ymmword ptr [rsp+228H] vmovaps ymm2, ymmword ptr [rsp+240H] vmovups ymm3, ymmword ptr [rsp+248H] vblendvps ymm0, ymm0, ymm1, ymm8 vblendvps ymm2, ymm2, ymm3, ymm8 vmovaps ymmword ptr [rsp+220H], ymm0 vmovaps ymmword ptr [rsp+240H], ymm2 add rbx, 64 add rdi, 16 sub rsi, 2 final1blocks: test rsi, 1H je unwind vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+10H] vmovd xmm3, dword ptr [rsp+220H] vpinsrd xmm3, xmm3, dword ptr [rsp+240H], 1 vpinsrd xmm13, xmm3, dword ptr [BLAKE3_BLOCK_LEN], 2 vmovdqa xmm14, xmmword ptr [ROT16] vmovdqa xmm15, xmmword ptr [ROT8] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop1: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d vmovdqa xmm2, xmmword ptr [BLAKE3_IV] vmovdqa xmm3, xmm13 vpinsrd xmm3, xmm3, eax, 3 vmovups xmm8, xmmword ptr [r8+rdx-40H] vmovups xmm9, xmmword ptr [r8+rdx-30H] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [r8+rdx-20H] vmovups xmm9, xmmword ptr [r8+rdx-10H] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 93H vpshufd xmm7, xmm7, 93H mov al, 7 roundloop1: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm14 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 12 vpslld xmm1, xmm1, 20 vpor xmm1, xmm1, xmm8 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm15 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 7 vpslld xmm1, xmm1, 25 vpor xmm1, xmm1, xmm8 vpshufd xmm0, xmm0, 93H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 39H vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm14 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 12 vpslld xmm1, xmm1, 20 vpor xmm1, xmm1, xmm8 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxor xmm3, xmm3, xmm0 vpshufb xmm3, xmm3, xmm15 vpaddd xmm2, xmm2, xmm3 vpxor xmm1, xmm1, xmm2 vpsrld xmm8, xmm1, 7 vpslld xmm1, xmm1, 25 vpor xmm1, xmm1, xmm8 vpshufd xmm0, xmm0, 39H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 93H dec al jz endroundloop1 vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0FH vpshufd xmm4, xmm8, 39H vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0AAH vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 88H vpshufd xmm8, xmm8, 78H vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 1EH vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp roundloop1 endroundloop1: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne innerloop1 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 jmp unwind _blake3_hash_many_avx2 ENDP blake3_hash_many_avx2 ENDP _TEXT ENDS _RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST' ALIGN 64 ADD0: dd 0, 1, 2, 3, 4, 5, 6, 7 ADD1: dd 8 dup (8) BLAKE3_IV_0: dd 8 dup (6A09E667H) BLAKE3_IV_1: dd 8 dup (0BB67AE85H) BLAKE3_IV_2: dd 8 dup (3C6EF372H) BLAKE3_IV_3: dd 8 dup (0A54FF53AH) BLAKE3_BLOCK_LEN: dd 8 dup (64) ROT16: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 ROT8: db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 CMP_MSB_MASK: dd 8 dup(80000000H) BLAKE3_IV: dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH _RDATA ENDS END ================================================ FILE: src/third_party/blake3/asm/blake3_avx512_x86-64_unix.S ================================================ #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif #if defined(__ELF__) && defined(__CET__) && defined(__has_include) #if __has_include() #include #endif #endif #if !defined(_CET_ENDBR) #define _CET_ENDBR #endif .intel_syntax noprefix .global _blake3_hash_many_avx512 .global blake3_hash_many_avx512 .global blake3_compress_in_place_avx512 .global _blake3_compress_in_place_avx512 .global blake3_compress_xof_avx512 .global _blake3_compress_xof_avx512 #ifdef __APPLE__ .text #else .section .text #endif .p2align 6 _blake3_hash_many_avx512: blake3_hash_many_avx512: _CET_ENDBR push r15 push r14 push r13 push r12 push rbx push rbp mov rbp, rsp sub rsp, 144 and rsp, 0xFFFFFFFFFFFFFFC0 neg r9 kmovw k1, r9d vmovd xmm0, r8d vpbroadcastd ymm0, xmm0 shr r8, 32 vmovd xmm1, r8d vpbroadcastd ymm1, xmm1 vmovdqa ymm4, ymm1 vmovdqa ymm5, ymm1 vpaddd ymm2, ymm0, ymmword ptr [ADD0+rip] vpaddd ymm3, ymm0, ymmword ptr [ADD0+32+rip] vpcmpltud k2, ymm2, ymm0 vpcmpltud k3, ymm3, ymm0 vpaddd ymm4 {k2}, ymm4, dword ptr [ADD1+rip] {1to8} vpaddd ymm5 {k3}, ymm5, dword ptr [ADD1+rip] {1to8} knotw k2, k1 vmovdqa32 ymm2 {k2}, ymm0 vmovdqa32 ymm3 {k2}, ymm0 vmovdqa32 ymm4 {k2}, ymm1 vmovdqa32 ymm5 {k2}, ymm1 vmovdqa ymmword ptr [rsp], ymm2 vmovdqa ymmword ptr [rsp+0x1*0x20], ymm3 vmovdqa ymmword ptr [rsp+0x2*0x20], ymm4 vmovdqa ymmword ptr [rsp+0x3*0x20], ymm5 shl rdx, 6 mov qword ptr [rsp+0x80], rdx cmp rsi, 16 jc 3f 2: vpbroadcastd zmm0, dword ptr [rcx] vpbroadcastd zmm1, dword ptr [rcx+0x1*0x4] vpbroadcastd zmm2, dword ptr [rcx+0x2*0x4] vpbroadcastd zmm3, dword ptr [rcx+0x3*0x4] vpbroadcastd zmm4, dword ptr [rcx+0x4*0x4] vpbroadcastd zmm5, dword ptr [rcx+0x5*0x4] vpbroadcastd zmm6, dword ptr [rcx+0x6*0x4] vpbroadcastd zmm7, dword ptr [rcx+0x7*0x4] movzx eax, byte ptr [rbp+0x38] movzx ebx, byte ptr [rbp+0x40] or eax, ebx xor edx, edx .p2align 5 9: movzx ebx, byte ptr [rbp+0x48] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+0x80] cmove eax, ebx mov dword ptr [rsp+0x88], eax mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] mov r12, qword ptr [rdi+0x40] mov r13, qword ptr [rdi+0x48] mov r14, qword ptr [rdi+0x50] mov r15, qword ptr [rdi+0x58] vmovdqu32 ymm16, ymmword ptr [rdx+r8-0x2*0x20] vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-0x2*0x20], 0x01 vmovdqu32 ymm17, ymmword ptr [rdx+r9-0x2*0x20] vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-0x2*0x20], 0x01 vpunpcklqdq zmm8, zmm16, zmm17 vpunpckhqdq zmm9, zmm16, zmm17 vmovdqu32 ymm18, ymmword ptr [rdx+r10-0x2*0x20] vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-0x2*0x20], 0x01 vmovdqu32 ymm19, ymmword ptr [rdx+r11-0x2*0x20] vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-0x2*0x20], 0x01 vpunpcklqdq zmm10, zmm18, zmm19 vpunpckhqdq zmm11, zmm18, zmm19 mov r8, qword ptr [rdi+0x20] mov r9, qword ptr [rdi+0x28] mov r10, qword ptr [rdi+0x30] mov r11, qword ptr [rdi+0x38] mov r12, qword ptr [rdi+0x60] mov r13, qword ptr [rdi+0x68] mov r14, qword ptr [rdi+0x70] mov r15, qword ptr [rdi+0x78] vmovdqu32 ymm16, ymmword ptr [rdx+r8-0x2*0x20] vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-0x2*0x20], 0x01 vmovdqu32 ymm17, ymmword ptr [rdx+r9-0x2*0x20] vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-0x2*0x20], 0x01 vpunpcklqdq zmm12, zmm16, zmm17 vpunpckhqdq zmm13, zmm16, zmm17 vmovdqu32 ymm18, ymmword ptr [rdx+r10-0x2*0x20] vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-0x2*0x20], 0x01 vmovdqu32 ymm19, ymmword ptr [rdx+r11-0x2*0x20] vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-0x2*0x20], 0x01 vpunpcklqdq zmm14, zmm18, zmm19 vpunpckhqdq zmm15, zmm18, zmm19 vmovdqa32 zmm27, zmmword ptr [INDEX0+rip] vmovdqa32 zmm31, zmmword ptr [INDEX1+rip] vshufps zmm16, zmm8, zmm10, 136 vshufps zmm17, zmm12, zmm14, 136 vmovdqa32 zmm20, zmm16 vpermt2d zmm16, zmm27, zmm17 vpermt2d zmm20, zmm31, zmm17 vshufps zmm17, zmm8, zmm10, 221 vshufps zmm30, zmm12, zmm14, 221 vmovdqa32 zmm21, zmm17 vpermt2d zmm17, zmm27, zmm30 vpermt2d zmm21, zmm31, zmm30 vshufps zmm18, zmm9, zmm11, 136 vshufps zmm8, zmm13, zmm15, 136 vmovdqa32 zmm22, zmm18 vpermt2d zmm18, zmm27, zmm8 vpermt2d zmm22, zmm31, zmm8 vshufps zmm19, zmm9, zmm11, 221 vshufps zmm8, zmm13, zmm15, 221 vmovdqa32 zmm23, zmm19 vpermt2d zmm19, zmm27, zmm8 vpermt2d zmm23, zmm31, zmm8 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] mov r12, qword ptr [rdi+0x40] mov r13, qword ptr [rdi+0x48] mov r14, qword ptr [rdi+0x50] mov r15, qword ptr [rdi+0x58] vmovdqu32 ymm24, ymmword ptr [r8+rdx-0x1*0x20] vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-0x1*0x20], 0x01 vmovdqu32 ymm25, ymmword ptr [r9+rdx-0x1*0x20] vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-0x1*0x20], 0x01 vpunpcklqdq zmm8, zmm24, zmm25 vpunpckhqdq zmm9, zmm24, zmm25 vmovdqu32 ymm24, ymmword ptr [r10+rdx-0x1*0x20] vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-0x1*0x20], 0x01 vmovdqu32 ymm25, ymmword ptr [r11+rdx-0x1*0x20] vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-0x1*0x20], 0x01 vpunpcklqdq zmm10, zmm24, zmm25 vpunpckhqdq zmm11, zmm24, zmm25 prefetcht0 [r8+rdx+0x80] prefetcht0 [r12+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r13+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r14+rdx+0x80] prefetcht0 [r11+rdx+0x80] prefetcht0 [r15+rdx+0x80] mov r8, qword ptr [rdi+0x20] mov r9, qword ptr [rdi+0x28] mov r10, qword ptr [rdi+0x30] mov r11, qword ptr [rdi+0x38] mov r12, qword ptr [rdi+0x60] mov r13, qword ptr [rdi+0x68] mov r14, qword ptr [rdi+0x70] mov r15, qword ptr [rdi+0x78] vmovdqu32 ymm24, ymmword ptr [r8+rdx-0x1*0x20] vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-0x1*0x20], 0x01 vmovdqu32 ymm25, ymmword ptr [r9+rdx-0x1*0x20] vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-0x1*0x20], 0x01 vpunpcklqdq zmm12, zmm24, zmm25 vpunpckhqdq zmm13, zmm24, zmm25 vmovdqu32 ymm24, ymmword ptr [r10+rdx-0x1*0x20] vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-0x1*0x20], 0x01 vmovdqu32 ymm25, ymmword ptr [r11+rdx-0x1*0x20] vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-0x1*0x20], 0x01 vpunpcklqdq zmm14, zmm24, zmm25 vpunpckhqdq zmm15, zmm24, zmm25 prefetcht0 [r8+rdx+0x80] prefetcht0 [r12+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r13+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r14+rdx+0x80] prefetcht0 [r11+rdx+0x80] prefetcht0 [r15+rdx+0x80] vshufps zmm24, zmm8, zmm10, 136 vshufps zmm30, zmm12, zmm14, 136 vmovdqa32 zmm28, zmm24 vpermt2d zmm24, zmm27, zmm30 vpermt2d zmm28, zmm31, zmm30 vshufps zmm25, zmm8, zmm10, 221 vshufps zmm30, zmm12, zmm14, 221 vmovdqa32 zmm29, zmm25 vpermt2d zmm25, zmm27, zmm30 vpermt2d zmm29, zmm31, zmm30 vshufps zmm26, zmm9, zmm11, 136 vshufps zmm8, zmm13, zmm15, 136 vmovdqa32 zmm30, zmm26 vpermt2d zmm26, zmm27, zmm8 vpermt2d zmm30, zmm31, zmm8 vshufps zmm8, zmm9, zmm11, 221 vshufps zmm10, zmm13, zmm15, 221 vpermi2d zmm27, zmm8, zmm10 vpermi2d zmm31, zmm8, zmm10 vpbroadcastd zmm8, dword ptr [BLAKE3_IV_0+rip] vpbroadcastd zmm9, dword ptr [BLAKE3_IV_1+rip] vpbroadcastd zmm10, dword ptr [BLAKE3_IV_2+rip] vpbroadcastd zmm11, dword ptr [BLAKE3_IV_3+rip] vmovdqa32 zmm12, zmmword ptr [rsp] vmovdqa32 zmm13, zmmword ptr [rsp+0x1*0x40] vpbroadcastd zmm14, dword ptr [BLAKE3_BLOCK_LEN+rip] vpbroadcastd zmm15, dword ptr [rsp+0x22*0x4] vpaddd zmm0, zmm0, zmm16 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm20 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm17 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm21 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm24 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm28 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm25 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm29 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm18 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm23 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm22 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm16 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm17 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm25 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm27 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm30 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm19 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm29 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm20 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm18 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm22 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm27 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm21 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm31 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm26 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm30 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm23 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm19 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm20 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm21 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm16 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm24 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm28 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm31 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm29 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm26 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm23 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm16 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm18 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm17 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm25 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm24 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm30 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm28 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm29 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm18 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm19 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm22 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm27 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm17 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm31 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm25 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm30 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm19 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm26 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm20 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpxord zmm0, zmm0, zmm8 vpxord zmm1, zmm1, zmm9 vpxord zmm2, zmm2, zmm10 vpxord zmm3, zmm3, zmm11 vpxord zmm4, zmm4, zmm12 vpxord zmm5, zmm5, zmm13 vpxord zmm6, zmm6, zmm14 vpxord zmm7, zmm7, zmm15 movzx eax, byte ptr [rbp+0x38] jne 9b mov rbx, qword ptr [rbp+0x50] vpunpckldq zmm16, zmm0, zmm1 vpunpckhdq zmm17, zmm0, zmm1 vpunpckldq zmm18, zmm2, zmm3 vpunpckhdq zmm19, zmm2, zmm3 vpunpckldq zmm20, zmm4, zmm5 vpunpckhdq zmm21, zmm4, zmm5 vpunpckldq zmm22, zmm6, zmm7 vpunpckhdq zmm23, zmm6, zmm7 vpunpcklqdq zmm0, zmm16, zmm18 vpunpckhqdq zmm1, zmm16, zmm18 vpunpcklqdq zmm2, zmm17, zmm19 vpunpckhqdq zmm3, zmm17, zmm19 vpunpcklqdq zmm4, zmm20, zmm22 vpunpckhqdq zmm5, zmm20, zmm22 vpunpcklqdq zmm6, zmm21, zmm23 vpunpckhqdq zmm7, zmm21, zmm23 vshufi32x4 zmm16, zmm0, zmm4, 0x88 vshufi32x4 zmm17, zmm1, zmm5, 0x88 vshufi32x4 zmm18, zmm2, zmm6, 0x88 vshufi32x4 zmm19, zmm3, zmm7, 0x88 vshufi32x4 zmm20, zmm0, zmm4, 0xDD vshufi32x4 zmm21, zmm1, zmm5, 0xDD vshufi32x4 zmm22, zmm2, zmm6, 0xDD vshufi32x4 zmm23, zmm3, zmm7, 0xDD vshufi32x4 zmm0, zmm16, zmm17, 0x88 vshufi32x4 zmm1, zmm18, zmm19, 0x88 vshufi32x4 zmm2, zmm20, zmm21, 0x88 vshufi32x4 zmm3, zmm22, zmm23, 0x88 vshufi32x4 zmm4, zmm16, zmm17, 0xDD vshufi32x4 zmm5, zmm18, zmm19, 0xDD vshufi32x4 zmm6, zmm20, zmm21, 0xDD vshufi32x4 zmm7, zmm22, zmm23, 0xDD vmovdqu32 zmmword ptr [rbx], zmm0 vmovdqu32 zmmword ptr [rbx+0x1*0x40], zmm1 vmovdqu32 zmmword ptr [rbx+0x2*0x40], zmm2 vmovdqu32 zmmword ptr [rbx+0x3*0x40], zmm3 vmovdqu32 zmmword ptr [rbx+0x4*0x40], zmm4 vmovdqu32 zmmword ptr [rbx+0x5*0x40], zmm5 vmovdqu32 zmmword ptr [rbx+0x6*0x40], zmm6 vmovdqu32 zmmword ptr [rbx+0x7*0x40], zmm7 vmovdqa32 zmm0, zmmword ptr [rsp] vmovdqa32 zmm1, zmmword ptr [rsp+0x1*0x40] vmovdqa32 zmm2, zmm0 vpaddd zmm2{k1}, zmm0, dword ptr [ADD16+rip] {1to16} vpcmpltud k2, zmm2, zmm0 vpaddd zmm1 {k2}, zmm1, dword ptr [ADD1+rip] {1to16} vmovdqa32 zmmword ptr [rsp], zmm2 vmovdqa32 zmmword ptr [rsp+0x1*0x40], zmm1 add rdi, 128 add rbx, 512 mov qword ptr [rbp+0x50], rbx sub rsi, 16 cmp rsi, 16 jnc 2b test rsi, rsi jnz 3f 4: vzeroupper mov rsp, rbp pop rbp pop rbx pop r12 pop r13 pop r14 pop r15 ret .p2align 6 3: test esi, 0x8 je 3f vpbroadcastd ymm0, dword ptr [rcx] vpbroadcastd ymm1, dword ptr [rcx+0x4] vpbroadcastd ymm2, dword ptr [rcx+0x8] vpbroadcastd ymm3, dword ptr [rcx+0xC] vpbroadcastd ymm4, dword ptr [rcx+0x10] vpbroadcastd ymm5, dword ptr [rcx+0x14] vpbroadcastd ymm6, dword ptr [rcx+0x18] vpbroadcastd ymm7, dword ptr [rcx+0x1C] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] mov r12, qword ptr [rdi+0x20] mov r13, qword ptr [rdi+0x28] mov r14, qword ptr [rdi+0x30] mov r15, qword ptr [rdi+0x38] movzx eax, byte ptr [rbp+0x38] movzx ebx, byte ptr [rbp+0x40] or eax, ebx xor edx, edx 2: movzx ebx, byte ptr [rbp+0x48] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+0x80] cmove eax, ebx mov dword ptr [rsp+0x88], eax vmovups xmm8, xmmword ptr [r8+rdx-0x40] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x40], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x40] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x40], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x40] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x40], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x40] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x40], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm16, ymm12, ymm14, 136 vshufps ymm17, ymm12, ymm14, 221 vshufps ymm18, ymm13, ymm15, 136 vshufps ymm19, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-0x30] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x30], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x30] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x30], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x30] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x30], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x30] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x30], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm20, ymm12, ymm14, 136 vshufps ymm21, ymm12, ymm14, 221 vshufps ymm22, ymm13, ymm15, 136 vshufps ymm23, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-0x20] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x20], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x20] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x20], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x20] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x20], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x20] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x20], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm24, ymm12, ymm14, 136 vshufps ymm25, ymm12, ymm14, 221 vshufps ymm26, ymm13, ymm15, 136 vshufps ymm27, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-0x10] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-0x10], 0x01 vmovups xmm9, xmmword ptr [r9+rdx-0x10] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-0x10], 0x01 vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-0x10] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-0x10], 0x01 vmovups xmm11, xmmword ptr [r11+rdx-0x10] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-0x10], 0x01 vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm28, ymm12, ymm14, 136 vshufps ymm29, ymm12, ymm14, 221 vshufps ymm30, ymm13, ymm15, 136 vshufps ymm31, ymm13, ymm15, 221 vpbroadcastd ymm8, dword ptr [BLAKE3_IV_0+rip] vpbroadcastd ymm9, dword ptr [BLAKE3_IV_1+rip] vpbroadcastd ymm10, dword ptr [BLAKE3_IV_2+rip] vpbroadcastd ymm11, dword ptr [BLAKE3_IV_3+rip] vmovdqa ymm12, ymmword ptr [rsp] vmovdqa ymm13, ymmword ptr [rsp+0x40] vpbroadcastd ymm14, dword ptr [BLAKE3_BLOCK_LEN+rip] vpbroadcastd ymm15, dword ptr [rsp+0x88] vpaddd ymm0, ymm0, ymm16 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm20 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm17 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm21 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm24 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm28 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm25 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm29 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm18 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm23 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm22 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm16 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm17 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm25 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm27 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm30 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm19 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm29 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm20 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm18 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm22 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm27 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm21 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm31 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm26 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm30 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm23 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm19 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm20 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm21 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm16 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm24 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm28 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm31 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm29 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm26 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm23 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm16 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm18 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm17 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm25 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm24 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm30 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm28 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm29 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm18 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm19 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm22 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm27 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm17 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm31 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm25 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm30 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm19 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm26 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm20 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpxor ymm0, ymm0, ymm8 vpxor ymm1, ymm1, ymm9 vpxor ymm2, ymm2, ymm10 vpxor ymm3, ymm3, ymm11 vpxor ymm4, ymm4, ymm12 vpxor ymm5, ymm5, ymm13 vpxor ymm6, ymm6, ymm14 vpxor ymm7, ymm7, ymm15 movzx eax, byte ptr [rbp+0x38] jne 2b mov rbx, qword ptr [rbp+0x50] vunpcklps ymm8, ymm0, ymm1 vunpcklps ymm9, ymm2, ymm3 vunpckhps ymm10, ymm0, ymm1 vunpcklps ymm11, ymm4, ymm5 vunpcklps ymm0, ymm6, ymm7 vshufps ymm12, ymm8, ymm9, 78 vblendps ymm1, ymm8, ymm12, 0xCC vshufps ymm8, ymm11, ymm0, 78 vunpckhps ymm13, ymm2, ymm3 vblendps ymm2, ymm11, ymm8, 0xCC vblendps ymm3, ymm12, ymm9, 0xCC vperm2f128 ymm12, ymm1, ymm2, 0x20 vmovups ymmword ptr [rbx], ymm12 vunpckhps ymm14, ymm4, ymm5 vblendps ymm4, ymm8, ymm0, 0xCC vunpckhps ymm15, ymm6, ymm7 vperm2f128 ymm7, ymm3, ymm4, 0x20 vmovups ymmword ptr [rbx+0x20], ymm7 vshufps ymm5, ymm10, ymm13, 78 vblendps ymm6, ymm5, ymm13, 0xCC vshufps ymm13, ymm14, ymm15, 78 vblendps ymm10, ymm10, ymm5, 0xCC vblendps ymm14, ymm14, ymm13, 0xCC vperm2f128 ymm8, ymm10, ymm14, 0x20 vmovups ymmword ptr [rbx+0x40], ymm8 vblendps ymm15, ymm13, ymm15, 0xCC vperm2f128 ymm13, ymm6, ymm15, 0x20 vmovups ymmword ptr [rbx+0x60], ymm13 vperm2f128 ymm9, ymm1, ymm2, 0x31 vperm2f128 ymm11, ymm3, ymm4, 0x31 vmovups ymmword ptr [rbx+0x80], ymm9 vperm2f128 ymm14, ymm10, ymm14, 0x31 vperm2f128 ymm15, ymm6, ymm15, 0x31 vmovups ymmword ptr [rbx+0xA0], ymm11 vmovups ymmword ptr [rbx+0xC0], ymm14 vmovups ymmword ptr [rbx+0xE0], ymm15 vmovdqa ymm0, ymmword ptr [rsp] vmovdqa ymm2, ymmword ptr [rsp+0x2*0x20] vmovdqa32 ymm0 {k1}, ymmword ptr [rsp+0x1*0x20] vmovdqa32 ymm2 {k1}, ymmword ptr [rsp+0x3*0x20] vmovdqa ymmword ptr [rsp], ymm0 vmovdqa ymmword ptr [rsp+0x2*0x20], ymm2 add rbx, 256 mov qword ptr [rbp+0x50], rbx add rdi, 64 sub rsi, 8 3: mov rbx, qword ptr [rbp+0x50] mov r15, qword ptr [rsp+0x80] movzx r13, byte ptr [rbp+0x38] movzx r12, byte ptr [rbp+0x48] test esi, 0x4 je 3f vbroadcasti32x4 zmm0, xmmword ptr [rcx] vbroadcasti32x4 zmm1, xmmword ptr [rcx+0x1*0x10] vmovdqa xmm12, xmmword ptr [rsp] vmovdqa xmm13, xmmword ptr [rsp+0x4*0x10] vpunpckldq xmm14, xmm12, xmm13 vpunpckhdq xmm15, xmm12, xmm13 vpermq ymm14, ymm14, 0xDC vpermq ymm15, ymm15, 0xDC vpbroadcastd zmm12, dword ptr [BLAKE3_BLOCK_LEN+rip] vinserti64x4 zmm13, zmm14, ymm15, 0x01 mov eax, 17476 kmovw k2, eax vpblendmd zmm13 {k2}, zmm13, zmm12 vbroadcasti32x4 zmm15, xmmword ptr [BLAKE3_IV+rip] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] mov eax, 43690 kmovw k3, eax mov eax, 34952 kmovw k4, eax movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+0x88], eax vmovdqa32 zmm2, zmm15 vpbroadcastd zmm8, dword ptr [rsp+0x22*0x4] vpblendmd zmm3 {k4}, zmm13, zmm8 vmovups zmm8, zmmword ptr [r8+rdx-0x1*0x40] vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-0x4*0x10], 0x01 vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-0x4*0x10], 0x02 vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-0x4*0x10], 0x03 vmovups zmm9, zmmword ptr [r8+rdx-0x30] vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-0x3*0x10], 0x01 vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-0x3*0x10], 0x02 vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-0x3*0x10], 0x03 vshufps zmm4, zmm8, zmm9, 136 vshufps zmm5, zmm8, zmm9, 221 vmovups zmm8, zmmword ptr [r8+rdx-0x20] vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-0x2*0x10], 0x01 vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-0x2*0x10], 0x02 vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-0x2*0x10], 0x03 vmovups zmm9, zmmword ptr [r8+rdx-0x10] vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-0x1*0x10], 0x01 vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-0x1*0x10], 0x02 vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-0x1*0x10], 0x03 vshufps zmm6, zmm8, zmm9, 136 vshufps zmm7, zmm8, zmm9, 221 vpshufd zmm6, zmm6, 0x93 vpshufd zmm7, zmm7, 0x93 mov al, 7 9: vpaddd zmm0, zmm0, zmm4 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 16 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 12 vpaddd zmm0, zmm0, zmm5 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 8 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 7 vpshufd zmm0, zmm0, 0x93 vpshufd zmm3, zmm3, 0x4E vpshufd zmm2, zmm2, 0x39 vpaddd zmm0, zmm0, zmm6 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 16 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 12 vpaddd zmm0, zmm0, zmm7 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 8 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 7 vpshufd zmm0, zmm0, 0x39 vpshufd zmm3, zmm3, 0x4E vpshufd zmm2, zmm2, 0x93 dec al jz 9f vshufps zmm8, zmm4, zmm5, 214 vpshufd zmm9, zmm4, 0x0F vpshufd zmm4, zmm8, 0x39 vshufps zmm8, zmm6, zmm7, 250 vpblendmd zmm9 {k3}, zmm9, zmm8 vpunpcklqdq zmm8, zmm7, zmm5 vpblendmd zmm8 {k4}, zmm8, zmm6 vpshufd zmm8, zmm8, 0x78 vpunpckhdq zmm5, zmm5, zmm7 vpunpckldq zmm6, zmm6, zmm5 vpshufd zmm7, zmm6, 0x1E vmovdqa32 zmm5, zmm9 vmovdqa32 zmm6, zmm8 jmp 9b 9: vpxord zmm0, zmm0, zmm2 vpxord zmm1, zmm1, zmm3 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 vextracti128 xmmword ptr [rbx+0x20], ymm0, 0x01 vextracti128 xmmword ptr [rbx+0x30], ymm1, 0x01 vextracti32x4 xmmword ptr [rbx+0x4*0x10], zmm0, 0x02 vextracti32x4 xmmword ptr [rbx+0x5*0x10], zmm1, 0x02 vextracti32x4 xmmword ptr [rbx+0x6*0x10], zmm0, 0x03 vextracti32x4 xmmword ptr [rbx+0x7*0x10], zmm1, 0x03 vmovdqa xmm0, xmmword ptr [rsp] vmovdqa xmm2, xmmword ptr [rsp+0x40] vmovdqa32 xmm0 {k1}, xmmword ptr [rsp+0x1*0x10] vmovdqa32 xmm2 {k1}, xmmword ptr [rsp+0x5*0x10] vmovdqa xmmword ptr [rsp], xmm0 vmovdqa xmmword ptr [rsp+0x40], xmm2 add rbx, 128 add rdi, 32 sub rsi, 4 3: test esi, 0x2 je 3f vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+0x10] vmovd xmm13, dword ptr [rsp] vpinsrd xmm13, xmm13, dword ptr [rsp+0x40], 1 vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vmovd xmm14, dword ptr [rsp+0x4] vpinsrd xmm14, xmm14, dword ptr [rsp+0x44], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vinserti128 ymm13, ymm13, xmm14, 0x01 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+0x88], eax vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV+rip] vpbroadcastd ymm8, dword ptr [rsp+0x88] vpblendd ymm3, ymm13, ymm8, 0x88 vmovups ymm8, ymmword ptr [r8+rdx-0x40] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-0x40], 0x01 vmovups ymm9, ymmword ptr [r8+rdx-0x30] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-0x30], 0x01 vshufps ymm4, ymm8, ymm9, 136 vshufps ymm5, ymm8, ymm9, 221 vmovups ymm8, ymmword ptr [r8+rdx-0x20] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-0x20], 0x01 vmovups ymm9, ymmword ptr [r8+rdx-0x10] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-0x10], 0x01 vshufps ymm6, ymm8, ymm9, 136 vshufps ymm7, ymm8, ymm9, 221 vpshufd ymm6, ymm6, 0x93 vpshufd ymm7, ymm7, 0x93 mov al, 7 9: vpaddd ymm0, ymm0, ymm4 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 16 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 12 vpaddd ymm0, ymm0, ymm5 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 8 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 7 vpshufd ymm0, ymm0, 0x93 vpshufd ymm3, ymm3, 0x4E vpshufd ymm2, ymm2, 0x39 vpaddd ymm0, ymm0, ymm6 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 16 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 12 vpaddd ymm0, ymm0, ymm7 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 8 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 7 vpshufd ymm0, ymm0, 0x39 vpshufd ymm3, ymm3, 0x4E vpshufd ymm2, ymm2, 0x93 dec al jz 9f vshufps ymm8, ymm4, ymm5, 214 vpshufd ymm9, ymm4, 0x0F vpshufd ymm4, ymm8, 0x39 vshufps ymm8, ymm6, ymm7, 250 vpblendd ymm9, ymm9, ymm8, 0xAA vpunpcklqdq ymm8, ymm7, ymm5 vpblendd ymm8, ymm8, ymm6, 0x88 vpshufd ymm8, ymm8, 0x78 vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 0x1E vmovdqa ymm5, ymm9 vmovdqa ymm6, ymm8 jmp 9b 9: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 vextracti128 xmmword ptr [rbx+0x20], ymm0, 0x01 vextracti128 xmmword ptr [rbx+0x30], ymm1, 0x01 vmovdqa xmm0, xmmword ptr [rsp] vmovdqa xmm2, xmmword ptr [rsp+0x4*0x10] vmovdqu32 xmm0 {k1}, xmmword ptr [rsp+0x8] vmovdqu32 xmm2 {k1}, xmmword ptr [rsp+0x48] vmovdqa xmmword ptr [rsp], xmm0 vmovdqa xmmword ptr [rsp+0x4*0x10], xmm2 add rbx, 64 add rdi, 16 sub rsi, 2 3: test esi, 0x1 je 4b vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+0x10] vmovd xmm14, dword ptr [rsp] vpinsrd xmm14, xmm14, dword ptr [rsp+0x40], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 vmovdqa xmm15, xmmword ptr [BLAKE3_IV+rip] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx .p2align 5 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d vpinsrd xmm3, xmm14, eax, 3 vmovdqa xmm2, xmm15 vmovups xmm8, xmmword ptr [r8+rdx-0x40] vmovups xmm9, xmmword ptr [r8+rdx-0x30] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [r8+rdx-0x20] vmovups xmm9, xmmword ptr [r8+rdx-0x10] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 0x93 vpshufd xmm7, xmm7, 0x93 mov al, 7 9: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x93 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x39 vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x39 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x93 dec al jz 9f vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0x0F vpshufd xmm4, xmm8, 0x39 vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0xAA vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 0x88 vpshufd xmm8, xmm8, 0x78 vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 0x1E vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp 9b 9: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne 2b vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+0x10], xmm1 jmp 4b .p2align 6 _blake3_compress_in_place_avx512: blake3_compress_in_place_avx512: _CET_ENDBR vmovdqu xmm0, xmmword ptr [rdi] vmovdqu xmm1, xmmword ptr [rdi+0x10] movzx eax, r8b movzx edx, dl shl rax, 32 add rdx, rax vmovq xmm3, rcx vmovq xmm4, rdx vpunpcklqdq xmm3, xmm3, xmm4 vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip] vmovups xmm8, xmmword ptr [rsi] vmovups xmm9, xmmword ptr [rsi+0x10] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [rsi+0x20] vmovups xmm9, xmmword ptr [rsi+0x30] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 0x93 vpshufd xmm7, xmm7, 0x93 mov al, 7 9: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x93 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x39 vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x39 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x93 dec al jz 9f vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0x0F vpshufd xmm4, xmm8, 0x39 vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0xAA vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 0x88 vpshufd xmm8, xmm8, 0x78 vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 0x1E vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp 9b 9: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 vmovdqu xmmword ptr [rdi], xmm0 vmovdqu xmmword ptr [rdi+0x10], xmm1 ret .p2align 6 _blake3_compress_xof_avx512: blake3_compress_xof_avx512: _CET_ENDBR vmovdqu xmm0, xmmword ptr [rdi] vmovdqu xmm1, xmmword ptr [rdi+0x10] movzx eax, r8b movzx edx, dl shl rax, 32 add rdx, rax vmovq xmm3, rcx vmovq xmm4, rdx vpunpcklqdq xmm3, xmm3, xmm4 vmovaps xmm2, xmmword ptr [BLAKE3_IV+rip] vmovups xmm8, xmmword ptr [rsi] vmovups xmm9, xmmword ptr [rsi+0x10] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [rsi+0x20] vmovups xmm9, xmmword ptr [rsi+0x30] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 0x93 vpshufd xmm7, xmm7, 0x93 mov al, 7 9: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x93 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x39 vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 0x39 vpshufd xmm3, xmm3, 0x4E vpshufd xmm2, xmm2, 0x93 dec al jz 9f vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0x0F vpshufd xmm4, xmm8, 0x39 vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0xAA vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 0x88 vpshufd xmm8, xmm8, 0x78 vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 0x1E vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp 9b 9: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 vpxor xmm2, xmm2, [rdi] vpxor xmm3, xmm3, [rdi+0x10] vmovdqu xmmword ptr [r9], xmm0 vmovdqu xmmword ptr [r9+0x10], xmm1 vmovdqu xmmword ptr [r9+0x20], xmm2 vmovdqu xmmword ptr [r9+0x30], xmm3 ret #ifdef __APPLE__ .static_data #else .section .rodata #endif .p2align 6 INDEX0: .long 0, 1, 2, 3, 16, 17, 18, 19 .long 8, 9, 10, 11, 24, 25, 26, 27 INDEX1: .long 4, 5, 6, 7, 20, 21, 22, 23 .long 12, 13, 14, 15, 28, 29, 30, 31 ADD0: .long 0, 1, 2, 3, 4, 5, 6, 7 .long 8, 9, 10, 11, 12, 13, 14, 15 ADD1: .long 1 ADD16: .long 16 BLAKE3_BLOCK_LEN: .long 64 .p2align 6 BLAKE3_IV: BLAKE3_IV_0: .long 0x6A09E667 BLAKE3_IV_1: .long 0xBB67AE85 BLAKE3_IV_2: .long 0x3C6EF372 BLAKE3_IV_3: .long 0xA54FF53A ================================================ FILE: src/third_party/blake3/asm/blake3_avx512_x86-64_windows_msvc.asm ================================================ public _blake3_hash_many_avx512 public blake3_hash_many_avx512 public blake3_compress_in_place_avx512 public _blake3_compress_in_place_avx512 public blake3_compress_xof_avx512 public _blake3_compress_xof_avx512 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 blake3_hash_many_avx512 PROC _blake3_hash_many_avx512 PROC push r15 push r14 push r13 push r12 push rdi push rsi push rbx push rbp mov rbp, rsp sub rsp, 304 and rsp, 0FFFFFFFFFFFFFFC0H vmovdqa xmmword ptr [rsp+90H], xmm6 vmovdqa xmmword ptr [rsp+0A0H], xmm7 vmovdqa xmmword ptr [rsp+0B0H], xmm8 vmovdqa xmmword ptr [rsp+0C0H], xmm9 vmovdqa xmmword ptr [rsp+0D0H], xmm10 vmovdqa xmmword ptr [rsp+0E0H], xmm11 vmovdqa xmmword ptr [rsp+0F0H], xmm12 vmovdqa xmmword ptr [rsp+100H], xmm13 vmovdqa xmmword ptr [rsp+110H], xmm14 vmovdqa xmmword ptr [rsp+120H], xmm15 mov rdi, rcx mov rsi, rdx mov rdx, r8 mov rcx, r9 mov r8, qword ptr [rbp+68H] movzx r9, byte ptr [rbp+70H] neg r9 kmovw k1, r9d vmovd xmm0, r8d vpbroadcastd ymm0, xmm0 shr r8, 32 vmovd xmm1, r8d vpbroadcastd ymm1, xmm1 vmovdqa ymm4, ymm1 vmovdqa ymm5, ymm1 vpaddd ymm2, ymm0, ymmword ptr [ADD0] vpaddd ymm3, ymm0, ymmword ptr [ADD0+32] vpcmpud k2, ymm2, ymm0, 1 vpcmpud k3, ymm3, ymm0, 1 ; XXX: ml64.exe does not currently understand the syntax. We use a workaround. vpbroadcastd ymm6, dword ptr [ADD1] vpaddd ymm4 {k2}, ymm4, ymm6 vpaddd ymm5 {k3}, ymm5, ymm6 ; vpaddd ymm4 {k2}, ymm4, dword ptr [ADD1] {1to8} ; vpaddd ymm5 {k3}, ymm5, dword ptr [ADD1] {1to8} knotw k2, k1 vmovdqa32 ymm2 {k2}, ymm0 vmovdqa32 ymm3 {k2}, ymm0 vmovdqa32 ymm4 {k2}, ymm1 vmovdqa32 ymm5 {k2}, ymm1 vmovdqa ymmword ptr [rsp], ymm2 vmovdqa ymmword ptr [rsp+20H], ymm3 vmovdqa ymmword ptr [rsp+40H], ymm4 vmovdqa ymmword ptr [rsp+60H], ymm5 shl rdx, 6 mov qword ptr [rsp+80H], rdx cmp rsi, 16 jc final15blocks outerloop16: vpbroadcastd zmm0, dword ptr [rcx] vpbroadcastd zmm1, dword ptr [rcx+1H*4H] vpbroadcastd zmm2, dword ptr [rcx+2H*4H] vpbroadcastd zmm3, dword ptr [rcx+3H*4H] vpbroadcastd zmm4, dword ptr [rcx+4H*4H] vpbroadcastd zmm5, dword ptr [rcx+5H*4H] vpbroadcastd zmm6, dword ptr [rcx+6H*4H] vpbroadcastd zmm7, dword ptr [rcx+7H*4H] movzx eax, byte ptr [rbp+78H] movzx ebx, byte ptr [rbp+80H] or eax, ebx xor edx, edx ALIGN 16 innerloop16: movzx ebx, byte ptr [rbp+88H] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+80H] cmove eax, ebx mov dword ptr [rsp+88H], eax mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] mov r12, qword ptr [rdi+40H] mov r13, qword ptr [rdi+48H] mov r14, qword ptr [rdi+50H] mov r15, qword ptr [rdi+58H] vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H] vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H] vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H vpunpcklqdq zmm8, zmm16, zmm17 vpunpckhqdq zmm9, zmm16, zmm17 vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H] vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H] vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H vpunpcklqdq zmm10, zmm18, zmm19 vpunpckhqdq zmm11, zmm18, zmm19 mov r8, qword ptr [rdi+20H] mov r9, qword ptr [rdi+28H] mov r10, qword ptr [rdi+30H] mov r11, qword ptr [rdi+38H] mov r12, qword ptr [rdi+60H] mov r13, qword ptr [rdi+68H] mov r14, qword ptr [rdi+70H] mov r15, qword ptr [rdi+78H] vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H] vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H] vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H vpunpcklqdq zmm12, zmm16, zmm17 vpunpckhqdq zmm13, zmm16, zmm17 vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H] vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H] vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H vpunpcklqdq zmm14, zmm18, zmm19 vpunpckhqdq zmm15, zmm18, zmm19 vmovdqa32 zmm27, zmmword ptr [INDEX0] vmovdqa32 zmm31, zmmword ptr [INDEX1] vshufps zmm16, zmm8, zmm10, 136 vshufps zmm17, zmm12, zmm14, 136 vmovdqa32 zmm20, zmm16 vpermt2d zmm16, zmm27, zmm17 vpermt2d zmm20, zmm31, zmm17 vshufps zmm17, zmm8, zmm10, 221 vshufps zmm30, zmm12, zmm14, 221 vmovdqa32 zmm21, zmm17 vpermt2d zmm17, zmm27, zmm30 vpermt2d zmm21, zmm31, zmm30 vshufps zmm18, zmm9, zmm11, 136 vshufps zmm8, zmm13, zmm15, 136 vmovdqa32 zmm22, zmm18 vpermt2d zmm18, zmm27, zmm8 vpermt2d zmm22, zmm31, zmm8 vshufps zmm19, zmm9, zmm11, 221 vshufps zmm8, zmm13, zmm15, 221 vmovdqa32 zmm23, zmm19 vpermt2d zmm19, zmm27, zmm8 vpermt2d zmm23, zmm31, zmm8 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] mov r12, qword ptr [rdi+40H] mov r13, qword ptr [rdi+48H] mov r14, qword ptr [rdi+50H] mov r15, qword ptr [rdi+58H] vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H] vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H] vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H vpunpcklqdq zmm8, zmm24, zmm25 vpunpckhqdq zmm9, zmm24, zmm25 vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H] vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H] vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H vpunpcklqdq zmm10, zmm24, zmm25 vpunpckhqdq zmm11, zmm24, zmm25 prefetcht0 byte ptr [r8+rdx+80H] prefetcht0 byte ptr [r12+rdx+80H] prefetcht0 byte ptr [r9+rdx+80H] prefetcht0 byte ptr [r13+rdx+80H] prefetcht0 byte ptr [r10+rdx+80H] prefetcht0 byte ptr [r14+rdx+80H] prefetcht0 byte ptr [r11+rdx+80H] prefetcht0 byte ptr [r15+rdx+80H] mov r8, qword ptr [rdi+20H] mov r9, qword ptr [rdi+28H] mov r10, qword ptr [rdi+30H] mov r11, qword ptr [rdi+38H] mov r12, qword ptr [rdi+60H] mov r13, qword ptr [rdi+68H] mov r14, qword ptr [rdi+70H] mov r15, qword ptr [rdi+78H] vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H] vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H] vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H vpunpcklqdq zmm12, zmm24, zmm25 vpunpckhqdq zmm13, zmm24, zmm25 vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H] vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H] vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H vpunpcklqdq zmm14, zmm24, zmm25 vpunpckhqdq zmm15, zmm24, zmm25 prefetcht0 byte ptr [r8+rdx+80H] prefetcht0 byte ptr [r12+rdx+80H] prefetcht0 byte ptr [r9+rdx+80H] prefetcht0 byte ptr [r13+rdx+80H] prefetcht0 byte ptr [r10+rdx+80H] prefetcht0 byte ptr [r14+rdx+80H] prefetcht0 byte ptr [r11+rdx+80H] prefetcht0 byte ptr [r15+rdx+80H] vshufps zmm24, zmm8, zmm10, 136 vshufps zmm30, zmm12, zmm14, 136 vmovdqa32 zmm28, zmm24 vpermt2d zmm24, zmm27, zmm30 vpermt2d zmm28, zmm31, zmm30 vshufps zmm25, zmm8, zmm10, 221 vshufps zmm30, zmm12, zmm14, 221 vmovdqa32 zmm29, zmm25 vpermt2d zmm25, zmm27, zmm30 vpermt2d zmm29, zmm31, zmm30 vshufps zmm26, zmm9, zmm11, 136 vshufps zmm8, zmm13, zmm15, 136 vmovdqa32 zmm30, zmm26 vpermt2d zmm26, zmm27, zmm8 vpermt2d zmm30, zmm31, zmm8 vshufps zmm8, zmm9, zmm11, 221 vshufps zmm10, zmm13, zmm15, 221 vpermi2d zmm27, zmm8, zmm10 vpermi2d zmm31, zmm8, zmm10 vpbroadcastd zmm8, dword ptr [BLAKE3_IV_0] vpbroadcastd zmm9, dword ptr [BLAKE3_IV_1] vpbroadcastd zmm10, dword ptr [BLAKE3_IV_2] vpbroadcastd zmm11, dword ptr [BLAKE3_IV_3] vmovdqa32 zmm12, zmmword ptr [rsp] vmovdqa32 zmm13, zmmword ptr [rsp+1H*40H] vpbroadcastd zmm14, dword ptr [BLAKE3_BLOCK_LEN] vpbroadcastd zmm15, dword ptr [rsp+22H*4H] vpaddd zmm0, zmm0, zmm16 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm20 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm17 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm21 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm24 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm28 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm25 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm29 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm18 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm23 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm22 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm16 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm17 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm25 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm27 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm30 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm19 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm29 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm20 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm18 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm22 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm27 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm21 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm31 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm26 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm30 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm23 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm19 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm20 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm21 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm16 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm24 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm28 vpaddd zmm1, zmm1, zmm25 vpaddd zmm2, zmm2, zmm31 vpaddd zmm3, zmm3, zmm30 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm29 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm26 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm23 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm16 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm18 vpaddd zmm1, zmm1, zmm19 vpaddd zmm2, zmm2, zmm17 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm25 vpaddd zmm1, zmm1, zmm27 vpaddd zmm2, zmm2, zmm24 vpaddd zmm3, zmm3, zmm31 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm30 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm28 vpaddd zmm3, zmm3, zmm17 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm29 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm18 vpaddd zmm3, zmm3, zmm20 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm19 vpaddd zmm1, zmm1, zmm26 vpaddd zmm2, zmm2, zmm22 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpaddd zmm0, zmm0, zmm27 vpaddd zmm1, zmm1, zmm21 vpaddd zmm2, zmm2, zmm17 vpaddd zmm3, zmm3, zmm24 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vprord zmm15, zmm15, 16 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 12 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vpaddd zmm0, zmm0, zmm31 vpaddd zmm1, zmm1, zmm16 vpaddd zmm2, zmm2, zmm25 vpaddd zmm3, zmm3, zmm22 vpaddd zmm0, zmm0, zmm4 vpaddd zmm1, zmm1, zmm5 vpaddd zmm2, zmm2, zmm6 vpaddd zmm3, zmm3, zmm7 vpxord zmm12, zmm12, zmm0 vpxord zmm13, zmm13, zmm1 vpxord zmm14, zmm14, zmm2 vpxord zmm15, zmm15, zmm3 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vprord zmm15, zmm15, 8 vpaddd zmm8, zmm8, zmm12 vpaddd zmm9, zmm9, zmm13 vpaddd zmm10, zmm10, zmm14 vpaddd zmm11, zmm11, zmm15 vpxord zmm4, zmm4, zmm8 vpxord zmm5, zmm5, zmm9 vpxord zmm6, zmm6, zmm10 vpxord zmm7, zmm7, zmm11 vprord zmm4, zmm4, 7 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vpaddd zmm0, zmm0, zmm30 vpaddd zmm1, zmm1, zmm18 vpaddd zmm2, zmm2, zmm19 vpaddd zmm3, zmm3, zmm23 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 16 vprord zmm12, zmm12, 16 vprord zmm13, zmm13, 16 vprord zmm14, zmm14, 16 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 12 vprord zmm6, zmm6, 12 vprord zmm7, zmm7, 12 vprord zmm4, zmm4, 12 vpaddd zmm0, zmm0, zmm26 vpaddd zmm1, zmm1, zmm28 vpaddd zmm2, zmm2, zmm20 vpaddd zmm3, zmm3, zmm29 vpaddd zmm0, zmm0, zmm5 vpaddd zmm1, zmm1, zmm6 vpaddd zmm2, zmm2, zmm7 vpaddd zmm3, zmm3, zmm4 vpxord zmm15, zmm15, zmm0 vpxord zmm12, zmm12, zmm1 vpxord zmm13, zmm13, zmm2 vpxord zmm14, zmm14, zmm3 vprord zmm15, zmm15, 8 vprord zmm12, zmm12, 8 vprord zmm13, zmm13, 8 vprord zmm14, zmm14, 8 vpaddd zmm10, zmm10, zmm15 vpaddd zmm11, zmm11, zmm12 vpaddd zmm8, zmm8, zmm13 vpaddd zmm9, zmm9, zmm14 vpxord zmm5, zmm5, zmm10 vpxord zmm6, zmm6, zmm11 vpxord zmm7, zmm7, zmm8 vpxord zmm4, zmm4, zmm9 vprord zmm5, zmm5, 7 vprord zmm6, zmm6, 7 vprord zmm7, zmm7, 7 vprord zmm4, zmm4, 7 vpxord zmm0, zmm0, zmm8 vpxord zmm1, zmm1, zmm9 vpxord zmm2, zmm2, zmm10 vpxord zmm3, zmm3, zmm11 vpxord zmm4, zmm4, zmm12 vpxord zmm5, zmm5, zmm13 vpxord zmm6, zmm6, zmm14 vpxord zmm7, zmm7, zmm15 movzx eax, byte ptr [rbp+78H] jne innerloop16 mov rbx, qword ptr [rbp+90H] vpunpckldq zmm16, zmm0, zmm1 vpunpckhdq zmm17, zmm0, zmm1 vpunpckldq zmm18, zmm2, zmm3 vpunpckhdq zmm19, zmm2, zmm3 vpunpckldq zmm20, zmm4, zmm5 vpunpckhdq zmm21, zmm4, zmm5 vpunpckldq zmm22, zmm6, zmm7 vpunpckhdq zmm23, zmm6, zmm7 vpunpcklqdq zmm0, zmm16, zmm18 vpunpckhqdq zmm1, zmm16, zmm18 vpunpcklqdq zmm2, zmm17, zmm19 vpunpckhqdq zmm3, zmm17, zmm19 vpunpcklqdq zmm4, zmm20, zmm22 vpunpckhqdq zmm5, zmm20, zmm22 vpunpcklqdq zmm6, zmm21, zmm23 vpunpckhqdq zmm7, zmm21, zmm23 vshufi32x4 zmm16, zmm0, zmm4, 88H vshufi32x4 zmm17, zmm1, zmm5, 88H vshufi32x4 zmm18, zmm2, zmm6, 88H vshufi32x4 zmm19, zmm3, zmm7, 88H vshufi32x4 zmm20, zmm0, zmm4, 0DDH vshufi32x4 zmm21, zmm1, zmm5, 0DDH vshufi32x4 zmm22, zmm2, zmm6, 0DDH vshufi32x4 zmm23, zmm3, zmm7, 0DDH vshufi32x4 zmm0, zmm16, zmm17, 88H vshufi32x4 zmm1, zmm18, zmm19, 88H vshufi32x4 zmm2, zmm20, zmm21, 88H vshufi32x4 zmm3, zmm22, zmm23, 88H vshufi32x4 zmm4, zmm16, zmm17, 0DDH vshufi32x4 zmm5, zmm18, zmm19, 0DDH vshufi32x4 zmm6, zmm20, zmm21, 0DDH vshufi32x4 zmm7, zmm22, zmm23, 0DDH vmovdqu32 zmmword ptr [rbx], zmm0 vmovdqu32 zmmword ptr [rbx+1H*40H], zmm1 vmovdqu32 zmmword ptr [rbx+2H*40H], zmm2 vmovdqu32 zmmword ptr [rbx+3H*40H], zmm3 vmovdqu32 zmmword ptr [rbx+4H*40H], zmm4 vmovdqu32 zmmword ptr [rbx+5H*40H], zmm5 vmovdqu32 zmmword ptr [rbx+6H*40H], zmm6 vmovdqu32 zmmword ptr [rbx+7H*40H], zmm7 vmovdqa32 zmm0, zmmword ptr [rsp] vmovdqa32 zmm1, zmmword ptr [rsp+1H*40H] vmovdqa32 zmm2, zmm0 ; XXX: ml64.exe does not currently understand the syntax. We use a workaround. vpbroadcastd zmm4, dword ptr [ADD16] vpbroadcastd zmm5, dword ptr [ADD1] vpaddd zmm2{k1}, zmm0, zmm4 ; vpaddd zmm2{k1}, zmm0, dword ptr [ADD16] ; {1to16} vpcmpud k2, zmm2, zmm0, 1 vpaddd zmm1 {k2}, zmm1, zmm5 ; vpaddd zmm1 {k2}, zmm1, dword ptr [ADD1] ; {1to16} vmovdqa32 zmmword ptr [rsp], zmm2 vmovdqa32 zmmword ptr [rsp+1H*40H], zmm1 add rdi, 128 add rbx, 512 mov qword ptr [rbp+90H], rbx sub rsi, 16 cmp rsi, 16 jnc outerloop16 test rsi, rsi jne final15blocks unwind: vzeroupper vmovdqa xmm6, xmmword ptr [rsp+90H] vmovdqa xmm7, xmmword ptr [rsp+0A0H] vmovdqa xmm8, xmmword ptr [rsp+0B0H] vmovdqa xmm9, xmmword ptr [rsp+0C0H] vmovdqa xmm10, xmmword ptr [rsp+0D0H] vmovdqa xmm11, xmmword ptr [rsp+0E0H] vmovdqa xmm12, xmmword ptr [rsp+0F0H] vmovdqa xmm13, xmmword ptr [rsp+100H] vmovdqa xmm14, xmmword ptr [rsp+110H] vmovdqa xmm15, xmmword ptr [rsp+120H] mov rsp, rbp pop rbp pop rbx pop rsi pop rdi pop r12 pop r13 pop r14 pop r15 ret ALIGN 16 final15blocks: test esi, 8H je final7blocks vpbroadcastd ymm0, dword ptr [rcx] vpbroadcastd ymm1, dword ptr [rcx+4H] vpbroadcastd ymm2, dword ptr [rcx+8H] vpbroadcastd ymm3, dword ptr [rcx+0CH] vpbroadcastd ymm4, dword ptr [rcx+10H] vpbroadcastd ymm5, dword ptr [rcx+14H] vpbroadcastd ymm6, dword ptr [rcx+18H] vpbroadcastd ymm7, dword ptr [rcx+1CH] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] mov r12, qword ptr [rdi+20H] mov r13, qword ptr [rdi+28H] mov r14, qword ptr [rdi+30H] mov r15, qword ptr [rdi+38H] movzx eax, byte ptr [rbp+78H] movzx ebx, byte ptr [rbp+80H] or eax, ebx xor edx, edx innerloop8: movzx ebx, byte ptr [rbp+88H] or ebx, eax add rdx, 64 cmp rdx, qword ptr [rsp+80H] cmove eax, ebx mov dword ptr [rsp+88H], eax vmovups xmm8, xmmword ptr [r8+rdx-40H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H vmovups xmm9, xmmword ptr [r9+rdx-40H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-40H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H vmovups xmm11, xmmword ptr [r11+rdx-40H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm16, ymm12, ymm14, 136 vshufps ymm17, ymm12, ymm14, 221 vshufps ymm18, ymm13, ymm15, 136 vshufps ymm19, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-30H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H vmovups xmm9, xmmword ptr [r9+rdx-30H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-30H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H vmovups xmm11, xmmword ptr [r11+rdx-30H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm20, ymm12, ymm14, 136 vshufps ymm21, ymm12, ymm14, 221 vshufps ymm22, ymm13, ymm15, 136 vshufps ymm23, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-20H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H vmovups xmm9, xmmword ptr [r9+rdx-20H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-20H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H vmovups xmm11, xmmword ptr [r11+rdx-20H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm24, ymm12, ymm14, 136 vshufps ymm25, ymm12, ymm14, 221 vshufps ymm26, ymm13, ymm15, 136 vshufps ymm27, ymm13, ymm15, 221 vmovups xmm8, xmmword ptr [r8+rdx-10H] vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H vmovups xmm9, xmmword ptr [r9+rdx-10H] vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H vunpcklpd ymm12, ymm8, ymm9 vunpckhpd ymm13, ymm8, ymm9 vmovups xmm10, xmmword ptr [r10+rdx-10H] vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H vmovups xmm11, xmmword ptr [r11+rdx-10H] vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H vunpcklpd ymm14, ymm10, ymm11 vunpckhpd ymm15, ymm10, ymm11 vshufps ymm28, ymm12, ymm14, 136 vshufps ymm29, ymm12, ymm14, 221 vshufps ymm30, ymm13, ymm15, 136 vshufps ymm31, ymm13, ymm15, 221 vpbroadcastd ymm8, dword ptr [BLAKE3_IV_0] vpbroadcastd ymm9, dword ptr [BLAKE3_IV_1] vpbroadcastd ymm10, dword ptr [BLAKE3_IV_2] vpbroadcastd ymm11, dword ptr [BLAKE3_IV_3] vmovdqa ymm12, ymmword ptr [rsp] vmovdqa ymm13, ymmword ptr [rsp+40H] vpbroadcastd ymm14, dword ptr [BLAKE3_BLOCK_LEN] vpbroadcastd ymm15, dword ptr [rsp+88H] vpaddd ymm0, ymm0, ymm16 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm20 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm17 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm21 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm24 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm28 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm25 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm29 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm18 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm23 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm22 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm16 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm17 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm25 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm27 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm30 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm19 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm29 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm20 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm18 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm22 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm27 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm21 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm31 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm26 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm30 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm23 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm19 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm20 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm21 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm16 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm24 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm28 vpaddd ymm1, ymm1, ymm25 vpaddd ymm2, ymm2, ymm31 vpaddd ymm3, ymm3, ymm30 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm29 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm26 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm23 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm16 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm18 vpaddd ymm1, ymm1, ymm19 vpaddd ymm2, ymm2, ymm17 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm25 vpaddd ymm1, ymm1, ymm27 vpaddd ymm2, ymm2, ymm24 vpaddd ymm3, ymm3, ymm31 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm30 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm28 vpaddd ymm3, ymm3, ymm17 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm29 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm18 vpaddd ymm3, ymm3, ymm20 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm19 vpaddd ymm1, ymm1, ymm26 vpaddd ymm2, ymm2, ymm22 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpaddd ymm0, ymm0, ymm27 vpaddd ymm1, ymm1, ymm21 vpaddd ymm2, ymm2, ymm17 vpaddd ymm3, ymm3, ymm24 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vprord ymm15, ymm15, 16 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 12 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vpaddd ymm0, ymm0, ymm31 vpaddd ymm1, ymm1, ymm16 vpaddd ymm2, ymm2, ymm25 vpaddd ymm3, ymm3, ymm22 vpaddd ymm0, ymm0, ymm4 vpaddd ymm1, ymm1, ymm5 vpaddd ymm2, ymm2, ymm6 vpaddd ymm3, ymm3, ymm7 vpxord ymm12, ymm12, ymm0 vpxord ymm13, ymm13, ymm1 vpxord ymm14, ymm14, ymm2 vpxord ymm15, ymm15, ymm3 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vprord ymm15, ymm15, 8 vpaddd ymm8, ymm8, ymm12 vpaddd ymm9, ymm9, ymm13 vpaddd ymm10, ymm10, ymm14 vpaddd ymm11, ymm11, ymm15 vpxord ymm4, ymm4, ymm8 vpxord ymm5, ymm5, ymm9 vpxord ymm6, ymm6, ymm10 vpxord ymm7, ymm7, ymm11 vprord ymm4, ymm4, 7 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vpaddd ymm0, ymm0, ymm30 vpaddd ymm1, ymm1, ymm18 vpaddd ymm2, ymm2, ymm19 vpaddd ymm3, ymm3, ymm23 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 16 vprord ymm12, ymm12, 16 vprord ymm13, ymm13, 16 vprord ymm14, ymm14, 16 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 12 vprord ymm6, ymm6, 12 vprord ymm7, ymm7, 12 vprord ymm4, ymm4, 12 vpaddd ymm0, ymm0, ymm26 vpaddd ymm1, ymm1, ymm28 vpaddd ymm2, ymm2, ymm20 vpaddd ymm3, ymm3, ymm29 vpaddd ymm0, ymm0, ymm5 vpaddd ymm1, ymm1, ymm6 vpaddd ymm2, ymm2, ymm7 vpaddd ymm3, ymm3, ymm4 vpxord ymm15, ymm15, ymm0 vpxord ymm12, ymm12, ymm1 vpxord ymm13, ymm13, ymm2 vpxord ymm14, ymm14, ymm3 vprord ymm15, ymm15, 8 vprord ymm12, ymm12, 8 vprord ymm13, ymm13, 8 vprord ymm14, ymm14, 8 vpaddd ymm10, ymm10, ymm15 vpaddd ymm11, ymm11, ymm12 vpaddd ymm8, ymm8, ymm13 vpaddd ymm9, ymm9, ymm14 vpxord ymm5, ymm5, ymm10 vpxord ymm6, ymm6, ymm11 vpxord ymm7, ymm7, ymm8 vpxord ymm4, ymm4, ymm9 vprord ymm5, ymm5, 7 vprord ymm6, ymm6, 7 vprord ymm7, ymm7, 7 vprord ymm4, ymm4, 7 vpxor ymm0, ymm0, ymm8 vpxor ymm1, ymm1, ymm9 vpxor ymm2, ymm2, ymm10 vpxor ymm3, ymm3, ymm11 vpxor ymm4, ymm4, ymm12 vpxor ymm5, ymm5, ymm13 vpxor ymm6, ymm6, ymm14 vpxor ymm7, ymm7, ymm15 movzx eax, byte ptr [rbp+78H] jne innerloop8 mov rbx, qword ptr [rbp+90H] vunpcklps ymm8, ymm0, ymm1 vunpcklps ymm9, ymm2, ymm3 vunpckhps ymm10, ymm0, ymm1 vunpcklps ymm11, ymm4, ymm5 vunpcklps ymm0, ymm6, ymm7 vshufps ymm12, ymm8, ymm9, 78 vblendps ymm1, ymm8, ymm12, 0CCH vshufps ymm8, ymm11, ymm0, 78 vunpckhps ymm13, ymm2, ymm3 vblendps ymm2, ymm11, ymm8, 0CCH vblendps ymm3, ymm12, ymm9, 0CCH vperm2f128 ymm12, ymm1, ymm2, 20H vmovups ymmword ptr [rbx], ymm12 vunpckhps ymm14, ymm4, ymm5 vblendps ymm4, ymm8, ymm0, 0CCH vunpckhps ymm15, ymm6, ymm7 vperm2f128 ymm7, ymm3, ymm4, 20H vmovups ymmword ptr [rbx+20H], ymm7 vshufps ymm5, ymm10, ymm13, 78 vblendps ymm6, ymm5, ymm13, 0CCH vshufps ymm13, ymm14, ymm15, 78 vblendps ymm10, ymm10, ymm5, 0CCH vblendps ymm14, ymm14, ymm13, 0CCH vperm2f128 ymm8, ymm10, ymm14, 20H vmovups ymmword ptr [rbx+40H], ymm8 vblendps ymm15, ymm13, ymm15, 0CCH vperm2f128 ymm13, ymm6, ymm15, 20H vmovups ymmword ptr [rbx+60H], ymm13 vperm2f128 ymm9, ymm1, ymm2, 31H vperm2f128 ymm11, ymm3, ymm4, 31H vmovups ymmword ptr [rbx+80H], ymm9 vperm2f128 ymm14, ymm10, ymm14, 31H vperm2f128 ymm15, ymm6, ymm15, 31H vmovups ymmword ptr [rbx+0A0H], ymm11 vmovups ymmword ptr [rbx+0C0H], ymm14 vmovups ymmword ptr [rbx+0E0H], ymm15 vmovdqa ymm0, ymmword ptr [rsp] vmovdqa ymm2, ymmword ptr [rsp+40H] vmovdqa32 ymm0 {k1}, ymmword ptr [rsp+1H*20H] vmovdqa32 ymm2 {k1}, ymmword ptr [rsp+3H*20H] vmovdqa ymmword ptr [rsp], ymm0 vmovdqa ymmword ptr [rsp+40H], ymm2 add rbx, 256 mov qword ptr [rbp+90H], rbx add rdi, 64 sub rsi, 8 final7blocks: mov rbx, qword ptr [rbp+90H] mov r15, qword ptr [rsp+80H] movzx r13, byte ptr [rbp+78H] movzx r12, byte ptr [rbp+88H] test esi, 4H je final3blocks vbroadcasti32x4 zmm0, xmmword ptr [rcx] vbroadcasti32x4 zmm1, xmmword ptr [rcx+1H*10H] vmovdqa xmm12, xmmword ptr [rsp] vmovdqa xmm13, xmmword ptr [rsp+40H] vpunpckldq xmm14, xmm12, xmm13 vpunpckhdq xmm15, xmm12, xmm13 vpermq ymm14, ymm14, 0DCH vpermq ymm15, ymm15, 0DCH vpbroadcastd zmm12, dword ptr [BLAKE3_BLOCK_LEN] vinserti64x4 zmm13, zmm14, ymm15, 01H mov eax, 17476 kmovw k2, eax vpblendmd zmm13 {k2}, zmm13, zmm12 vbroadcasti32x4 zmm15, xmmword ptr [BLAKE3_IV] mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] mov eax, 43690 kmovw k3, eax mov eax, 34952 kmovw k4, eax movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop4: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+88H], eax vmovdqa32 zmm2, zmm15 vpbroadcastd zmm8, dword ptr [rsp+22H*4H] vpblendmd zmm3 {k4}, zmm13, zmm8 vmovups zmm8, zmmword ptr [r8+rdx-1H*40H] vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-4H*10H], 01H vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-4H*10H], 02H vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-4H*10H], 03H vmovups zmm9, zmmword ptr [r8+rdx-30H] vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-3H*10H], 01H vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-3H*10H], 02H vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-3H*10H], 03H vshufps zmm4, zmm8, zmm9, 136 vshufps zmm5, zmm8, zmm9, 221 vmovups zmm8, zmmword ptr [r8+rdx-20H] vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-2H*10H], 01H vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-2H*10H], 02H vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-2H*10H], 03H vmovups zmm9, zmmword ptr [r8+rdx-10H] vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-1H*10H], 01H vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-1H*10H], 02H vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-1H*10H], 03H vshufps zmm6, zmm8, zmm9, 136 vshufps zmm7, zmm8, zmm9, 221 vpshufd zmm6, zmm6, 93H vpshufd zmm7, zmm7, 93H mov al, 7 roundloop4: vpaddd zmm0, zmm0, zmm4 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 16 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 12 vpaddd zmm0, zmm0, zmm5 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 8 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 7 vpshufd zmm0, zmm0, 93H vpshufd zmm3, zmm3, 4EH vpshufd zmm2, zmm2, 39H vpaddd zmm0, zmm0, zmm6 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 16 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 12 vpaddd zmm0, zmm0, zmm7 vpaddd zmm0, zmm0, zmm1 vpxord zmm3, zmm3, zmm0 vprord zmm3, zmm3, 8 vpaddd zmm2, zmm2, zmm3 vpxord zmm1, zmm1, zmm2 vprord zmm1, zmm1, 7 vpshufd zmm0, zmm0, 39H vpshufd zmm3, zmm3, 4EH vpshufd zmm2, zmm2, 93H dec al jz endroundloop4 vshufps zmm8, zmm4, zmm5, 214 vpshufd zmm9, zmm4, 0FH vpshufd zmm4, zmm8, 39H vshufps zmm8, zmm6, zmm7, 250 vpblendmd zmm9 {k3}, zmm9, zmm8 vpunpcklqdq zmm8, zmm7, zmm5 vpblendmd zmm8 {k4}, zmm8, zmm6 vpshufd zmm8, zmm8, 78H vpunpckhdq zmm5, zmm5, zmm7 vpunpckldq zmm6, zmm6, zmm5 vpshufd zmm7, zmm6, 1EH vmovdqa32 zmm5, zmm9 vmovdqa32 zmm6, zmm8 jmp roundloop4 endroundloop4: vpxord zmm0, zmm0, zmm2 vpxord zmm1, zmm1, zmm3 mov eax, r13d cmp rdx, r15 jne innerloop4 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 vextracti128 xmmword ptr [rbx+20H], ymm0, 01H vextracti128 xmmword ptr [rbx+30H], ymm1, 01H vextracti32x4 xmmword ptr [rbx+4H*10H], zmm0, 02H vextracti32x4 xmmword ptr [rbx+5H*10H], zmm1, 02H vextracti32x4 xmmword ptr [rbx+6H*10H], zmm0, 03H vextracti32x4 xmmword ptr [rbx+7H*10H], zmm1, 03H vmovdqa xmm0, xmmword ptr [rsp] vmovdqa xmm2, xmmword ptr [rsp+40H] vmovdqa32 xmm0 {k1}, xmmword ptr [rsp+1H*10H] vmovdqa32 xmm2 {k1}, xmmword ptr [rsp+5H*10H] vmovdqa xmmword ptr [rsp], xmm0 vmovdqa xmmword ptr [rsp+40H], xmm2 add rbx, 128 add rdi, 32 sub rsi, 4 final3blocks: test esi, 2H je final1block vbroadcasti128 ymm0, xmmword ptr [rcx] vbroadcasti128 ymm1, xmmword ptr [rcx+10H] vmovd xmm13, dword ptr [rsp] vpinsrd xmm13, xmm13, dword ptr [rsp+40H], 1 vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2 vmovd xmm14, dword ptr [rsp+4H] vpinsrd xmm14, xmm14, dword ptr [rsp+44H], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2 vinserti128 ymm13, ymm13, xmm14, 01H mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d mov dword ptr [rsp+88H], eax vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV] vpbroadcastd ymm8, dword ptr [rsp+88H] vpblendd ymm3, ymm13, ymm8, 88H vmovups ymm8, ymmword ptr [r8+rdx-40H] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H vmovups ymm9, ymmword ptr [r8+rdx-30H] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H vshufps ymm4, ymm8, ymm9, 136 vshufps ymm5, ymm8, ymm9, 221 vmovups ymm8, ymmword ptr [r8+rdx-20H] vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H vmovups ymm9, ymmword ptr [r8+rdx-10H] vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H vshufps ymm6, ymm8, ymm9, 136 vshufps ymm7, ymm8, ymm9, 221 vpshufd ymm6, ymm6, 93H vpshufd ymm7, ymm7, 93H mov al, 7 roundloop2: vpaddd ymm0, ymm0, ymm4 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 16 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 12 vpaddd ymm0, ymm0, ymm5 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 8 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 7 vpshufd ymm0, ymm0, 93H vpshufd ymm3, ymm3, 4EH vpshufd ymm2, ymm2, 39H vpaddd ymm0, ymm0, ymm6 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 16 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 12 vpaddd ymm0, ymm0, ymm7 vpaddd ymm0, ymm0, ymm1 vpxord ymm3, ymm3, ymm0 vprord ymm3, ymm3, 8 vpaddd ymm2, ymm2, ymm3 vpxord ymm1, ymm1, ymm2 vprord ymm1, ymm1, 7 vpshufd ymm0, ymm0, 39H vpshufd ymm3, ymm3, 4EH vpshufd ymm2, ymm2, 93H dec al jz endroundloop2 vshufps ymm8, ymm4, ymm5, 214 vpshufd ymm9, ymm4, 0FH vpshufd ymm4, ymm8, 39H vshufps ymm8, ymm6, ymm7, 250 vpblendd ymm9, ymm9, ymm8, 0AAH vpunpcklqdq ymm8, ymm7, ymm5 vpblendd ymm8, ymm8, ymm6, 88H vpshufd ymm8, ymm8, 78H vpunpckhdq ymm5, ymm5, ymm7 vpunpckldq ymm6, ymm6, ymm5 vpshufd ymm7, ymm6, 1EH vmovdqa ymm5, ymm9 vmovdqa ymm6, ymm8 jmp roundloop2 endroundloop2: vpxor ymm0, ymm0, ymm2 vpxor ymm1, ymm1, ymm3 mov eax, r13d cmp rdx, r15 jne innerloop2 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 vextracti128 xmmword ptr [rbx+20H], ymm0, 01H vextracti128 xmmword ptr [rbx+30H], ymm1, 01H vmovdqa xmm0, xmmword ptr [rsp] vmovdqa xmm2, xmmword ptr [rsp+40H] vmovdqu32 xmm0 {k1}, xmmword ptr [rsp+8H] vmovdqu32 xmm2 {k1}, xmmword ptr [rsp+48H] vmovdqa xmmword ptr [rsp], xmm0 vmovdqa xmmword ptr [rsp+40H], xmm2 add rbx, 64 add rdi, 16 sub rsi, 2 final1block: test esi, 1H je unwind vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+10H] vmovd xmm14, dword ptr [rsp] vpinsrd xmm14, xmm14, dword ptr [rsp+40H], 1 vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2 vmovdqa xmm15, xmmword ptr [BLAKE3_IV] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx ALIGN 16 innerloop1: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d vpinsrd xmm3, xmm14, eax, 3 vmovdqa xmm2, xmm15 vmovups xmm8, xmmword ptr [r8+rdx-40H] vmovups xmm9, xmmword ptr [r8+rdx-30H] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [r8+rdx-20H] vmovups xmm9, xmmword ptr [r8+rdx-10H] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 93H vpshufd xmm7, xmm7, 93H mov al, 7 roundloop1: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 93H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 39H vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 39H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 93H dec al jz endroundloop1 vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0FH vpshufd xmm4, xmm8, 39H vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0AAH vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 88H vpshufd xmm8, xmm8, 78H vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 1EH vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp roundloop1 endroundloop1: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne innerloop1 vmovdqu xmmword ptr [rbx], xmm0 vmovdqu xmmword ptr [rbx+10H], xmm1 jmp unwind _blake3_hash_many_avx512 ENDP blake3_hash_many_avx512 ENDP ALIGN 16 blake3_compress_in_place_avx512 PROC _blake3_compress_in_place_avx512 PROC sub rsp, 72 vmovdqa xmmword ptr [rsp], xmm6 vmovdqa xmmword ptr [rsp+10H], xmm7 vmovdqa xmmword ptr [rsp+20H], xmm8 vmovdqa xmmword ptr [rsp+30H], xmm9 vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+10H] movzx eax, byte ptr [rsp+70H] movzx r8d, r8b shl rax, 32 add r8, rax vmovq xmm3, r9 vmovq xmm4, r8 vpunpcklqdq xmm3, xmm3, xmm4 vmovaps xmm2, xmmword ptr [BLAKE3_IV] vmovups xmm8, xmmword ptr [rdx] vmovups xmm9, xmmword ptr [rdx+10H] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [rdx+20H] vmovups xmm9, xmmword ptr [rdx+30H] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 93H vpshufd xmm7, xmm7, 93H mov al, 7 @@: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 93H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 39H vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 39H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 93H dec al jz @F vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0FH vpshufd xmm4, xmm8, 39H vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0AAH vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 88H vpshufd xmm8, xmm8, 78H vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 1EH vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp @B @@: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 vmovdqu xmmword ptr [rcx], xmm0 vmovdqu xmmword ptr [rcx+10H], xmm1 vmovdqa xmm6, xmmword ptr [rsp] vmovdqa xmm7, xmmword ptr [rsp+10H] vmovdqa xmm8, xmmword ptr [rsp+20H] vmovdqa xmm9, xmmword ptr [rsp+30H] add rsp, 72 ret _blake3_compress_in_place_avx512 ENDP blake3_compress_in_place_avx512 ENDP ALIGN 16 blake3_compress_xof_avx512 PROC _blake3_compress_xof_avx512 PROC sub rsp, 72 vmovdqa xmmword ptr [rsp], xmm6 vmovdqa xmmword ptr [rsp+10H], xmm7 vmovdqa xmmword ptr [rsp+20H], xmm8 vmovdqa xmmword ptr [rsp+30H], xmm9 vmovdqu xmm0, xmmword ptr [rcx] vmovdqu xmm1, xmmword ptr [rcx+10H] movzx eax, byte ptr [rsp+70H] movzx r8d, r8b mov r10, qword ptr [rsp+78H] shl rax, 32 add r8, rax vmovq xmm3, r9 vmovq xmm4, r8 vpunpcklqdq xmm3, xmm3, xmm4 vmovaps xmm2, xmmword ptr [BLAKE3_IV] vmovups xmm8, xmmword ptr [rdx] vmovups xmm9, xmmword ptr [rdx+10H] vshufps xmm4, xmm8, xmm9, 136 vshufps xmm5, xmm8, xmm9, 221 vmovups xmm8, xmmword ptr [rdx+20H] vmovups xmm9, xmmword ptr [rdx+30H] vshufps xmm6, xmm8, xmm9, 136 vshufps xmm7, xmm8, xmm9, 221 vpshufd xmm6, xmm6, 93H vpshufd xmm7, xmm7, 93H mov al, 7 @@: vpaddd xmm0, xmm0, xmm4 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm5 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 93H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 39H vpaddd xmm0, xmm0, xmm6 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 16 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 12 vpaddd xmm0, xmm0, xmm7 vpaddd xmm0, xmm0, xmm1 vpxord xmm3, xmm3, xmm0 vprord xmm3, xmm3, 8 vpaddd xmm2, xmm2, xmm3 vpxord xmm1, xmm1, xmm2 vprord xmm1, xmm1, 7 vpshufd xmm0, xmm0, 39H vpshufd xmm3, xmm3, 4EH vpshufd xmm2, xmm2, 93H dec al jz @F vshufps xmm8, xmm4, xmm5, 214 vpshufd xmm9, xmm4, 0FH vpshufd xmm4, xmm8, 39H vshufps xmm8, xmm6, xmm7, 250 vpblendd xmm9, xmm9, xmm8, 0AAH vpunpcklqdq xmm8, xmm7, xmm5 vpblendd xmm8, xmm8, xmm6, 88H vpshufd xmm8, xmm8, 78H vpunpckhdq xmm5, xmm5, xmm7 vpunpckldq xmm6, xmm6, xmm5 vpshufd xmm7, xmm6, 1EH vmovdqa xmm5, xmm9 vmovdqa xmm6, xmm8 jmp @B @@: vpxor xmm0, xmm0, xmm2 vpxor xmm1, xmm1, xmm3 vpxor xmm2, xmm2, xmmword ptr [rcx] vpxor xmm3, xmm3, xmmword ptr [rcx+10H] vmovdqu xmmword ptr [r10], xmm0 vmovdqu xmmword ptr [r10+10H], xmm1 vmovdqu xmmword ptr [r10+20H], xmm2 vmovdqu xmmword ptr [r10+30H], xmm3 vmovdqa xmm6, xmmword ptr [rsp] vmovdqa xmm7, xmmword ptr [rsp+10H] vmovdqa xmm8, xmmword ptr [rsp+20H] vmovdqa xmm9, xmmword ptr [rsp+30H] add rsp, 72 ret _blake3_compress_xof_avx512 ENDP blake3_compress_xof_avx512 ENDP _TEXT ENDS _RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST' ALIGN 64 INDEX0: dd 0, 1, 2, 3, 16, 17, 18, 19 dd 8, 9, 10, 11, 24, 25, 26, 27 INDEX1: dd 4, 5, 6, 7, 20, 21, 22, 23 dd 12, 13, 14, 15, 28, 29, 30, 31 ADD0: dd 0, 1, 2, 3, 4, 5, 6, 7 dd 8, 9, 10, 11, 12, 13, 14, 15 ADD1: dd 1 ADD16: dd 16 BLAKE3_BLOCK_LEN: dd 64 ALIGN 64 BLAKE3_IV: BLAKE3_IV_0: dd 06A09E667H BLAKE3_IV_1: dd 0BB67AE85H BLAKE3_IV_2: dd 03C6EF372H BLAKE3_IV_3: dd 0A54FF53AH _RDATA ENDS END ================================================ FILE: src/third_party/blake3/asm/blake3_dispatch.c ================================================ #include #include #include #include "blake3_impl.h" #if defined(IS_X86) #if defined(_MSC_VER) #include #elif defined(__GNUC__) #include #else #undef IS_X86 /* Unimplemented! */ #endif #endif #define MAYBE_UNUSED(x) (void)((x)) #if defined(IS_X86) static uint64_t xgetbv(void) { #if defined(_MSC_VER) return _xgetbv(0); #else uint32_t eax = 0, edx = 0; __asm__ __volatile__("xgetbv\n" : "=a"(eax), "=d"(edx) : "c"(0)); return ((uint64_t)edx << 32) | eax; #endif } static void cpuid(uint32_t out[4], uint32_t id) { #if defined(_MSC_VER) __cpuid((int *)out, id); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #endif } static void cpuidex(uint32_t out[4], uint32_t id, uint32_t sid) { #if defined(_MSC_VER) __cpuidex((int *)out, id, sid); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #endif } #endif enum cpu_feature { SSE2 = 1 << 0, SSSE3 = 1 << 1, SSE41 = 1 << 2, AVX = 1 << 3, AVX2 = 1 << 4, AVX512F = 1 << 5, AVX512VL = 1 << 6, /* ... */ UNDEFINED = 1 << 30 }; #if !defined(BLAKE3_TESTING) static /* Allow the variable to be controlled manually for testing */ #endif volatile int g_cpu_features = UNDEFINED; #if !defined(BLAKE3_TESTING) static #endif enum cpu_feature get_cpu_features(void) { /* If TSAN detects a data race here, try compiling with -DBLAKE3_ATOMICS=1 */ long features = g_cpu_features; if (features != UNDEFINED) { return (enum cpu_feature)features; } else { #if defined(IS_X86) uint32_t regs[4] = {0}; uint32_t *eax = ®s[0], *ebx = ®s[1], *ecx = ®s[2], *edx = ®s[3]; (void)edx; features = 0; cpuid(regs, 0); const int max_id = *eax; cpuid(regs, 1); #if defined(__amd64__) || defined(_M_X64) features |= SSE2; #else if (*edx & (1UL << 26)) features |= SSE2; #endif if (*ecx & (1UL << 9)) features |= SSSE3; if (*ecx & (1UL << 19)) features |= SSE41; if (*ecx & (1UL << 27)) { // OSXSAVE const uint64_t mask = xgetbv(); if ((mask & 6) == 6) { // SSE and AVX states if (*ecx & (1UL << 28)) features |= AVX; if (max_id >= 7) { cpuidex(regs, 7, 0); if (*ebx & (1UL << 5)) features |= AVX2; if ((mask & 224) == 224) { // Opmask, ZMM_Hi256, Hi16_Zmm if (*ebx & (1UL << 31)) features |= AVX512VL; if (*ebx & (1UL << 16)) features |= AVX512F; } } } } g_cpu_features = features; return (enum cpu_feature)features; #else /* How to detect NEON? */ return 0; #endif } } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_in_place_avx512(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_in_place_sse41(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_in_place_sse2(cv, block, block_len, counter, flags); return; } #endif #endif blake3_compress_in_place_portable(cv, block, block_len, counter, flags); } void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_xof_avx512(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_xof_sse41(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_xof_sse2(cv, block, block_len, counter, flags, out); return; } #endif #endif blake3_compress_xof_portable(cv, block, block_len, counter, flags, out); } void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #endif #if BLAKE3_USE_NEON == 1 blake3_hash_many_neon(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; #endif blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); } // The dynamically detected SIMD degree of the current platform. size_t blake3_simd_degree(void) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { return 16; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { return 8; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { return 4; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { return 4; } #endif #endif #if BLAKE3_USE_NEON == 1 return 4; #endif return 1; } ================================================ FILE: src/third_party/blake3/asm/blake3_impl.h ================================================ #ifndef BLAKE3_IMPL_H #define BLAKE3_IMPL_H #include #include #include #include #include #include "blake3.h" // internal flags enum blake3_flags { CHUNK_START = 1 << 0, CHUNK_END = 1 << 1, PARENT = 1 << 2, ROOT = 1 << 3, KEYED_HASH = 1 << 4, DERIVE_KEY_CONTEXT = 1 << 5, DERIVE_KEY_MATERIAL = 1 << 6, }; // This C implementation tries to support recent versions of GCC, Clang, and // MSVC. #if defined(_MSC_VER) #define INLINE static __forceinline #else #define INLINE static inline __attribute__((always_inline)) #endif #if defined(__x86_64__) || defined(_M_X64) #define IS_X86 #define IS_X86_64 #endif #if defined(__i386__) || defined(_M_IX86) #define IS_X86 #define IS_X86_32 #endif #if defined(__aarch64__) || defined(_M_ARM64) #define IS_AARCH64 #endif #if defined(IS_X86) #if defined(_MSC_VER) #include #endif #endif #if !defined(BLAKE3_USE_NEON) // If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness #if defined(IS_AARCH64) #if defined(__ARM_BIG_ENDIAN) #define BLAKE3_USE_NEON 0 #else #define BLAKE3_USE_NEON 1 #endif #else #define BLAKE3_USE_NEON 0 #endif #endif #if defined(IS_X86) #define MAX_SIMD_DEGREE 16 #elif BLAKE3_USE_NEON == 1 #define MAX_SIMD_DEGREE 4 #else #define MAX_SIMD_DEGREE 1 #endif // There are some places where we want a static size that's equal to the // MAX_SIMD_DEGREE, but also at least 2. #define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2) static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL}; static const uint8_t MSG_SCHEDULE[7][16] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}, }; /* Find index of the highest set bit */ /* x is assumed to be nonzero. */ static unsigned int highest_one(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return 63 ^ (unsigned int)__builtin_clzll(x); #elif defined(_MSC_VER) && defined(IS_X86_64) unsigned long index; _BitScanReverse64(&index, x); return index; #elif defined(_MSC_VER) && defined(IS_X86_32) if(x >> 32) { unsigned long index; _BitScanReverse(&index, (unsigned long)(x >> 32)); return 32 + index; } else { unsigned long index; _BitScanReverse(&index, (unsigned long)x); return index; } #else unsigned int c = 0; if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; } if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; } if(x & 0x000000000000ff00ULL) { x >>= 8; c += 8; } if(x & 0x00000000000000f0ULL) { x >>= 4; c += 4; } if(x & 0x000000000000000cULL) { x >>= 2; c += 2; } if(x & 0x0000000000000002ULL) { c += 1; } return c; #endif } // Count the number of 1 bits. INLINE unsigned int popcnt(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return (unsigned int)__builtin_popcountll(x); #else unsigned int count = 0; while (x != 0) { count += 1; x &= x - 1; } return count; #endif } // Largest power of two less than or equal to x. As a special case, returns 1 // when x is 0. INLINE uint64_t round_down_to_power_of_2(uint64_t x) { return 1ULL << highest_one(x | 1); } INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; } INLINE uint32_t counter_high(uint64_t counter) { return (uint32_t)(counter >> 32); } INLINE uint32_t load32(const void *src) { const uint8_t *p = (const uint8_t *)src; return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); } INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], uint32_t key_words[8]) { key_words[0] = load32(&key[0 * 4]); key_words[1] = load32(&key[1 * 4]); key_words[2] = load32(&key[2 * 4]); key_words[3] = load32(&key[3 * 4]); key_words[4] = load32(&key[4 * 4]); key_words[5] = load32(&key[5 * 4]); key_words[6] = load32(&key[6 * 4]); key_words[7] = load32(&key[7 * 4]); } INLINE void store32(void *dst, uint32_t w) { uint8_t *p = (uint8_t *)dst; p[0] = (uint8_t)(w >> 0); p[1] = (uint8_t)(w >> 8); p[2] = (uint8_t)(w >> 16); p[3] = (uint8_t)(w >> 24); } INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) { store32(&bytes_out[0 * 4], cv_words[0]); store32(&bytes_out[1 * 4], cv_words[1]); store32(&bytes_out[2 * 4], cv_words[2]); store32(&bytes_out[3 * 4], cv_words[3]); store32(&bytes_out[4 * 4], cv_words[4]); store32(&bytes_out[5 * 4], cv_words[5]); store32(&bytes_out[6 * 4], cv_words[6]); store32(&bytes_out[7 * 4], cv_words[7]); } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); size_t blake3_simd_degree(void); // Declarations for implementation-specific functions. void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #if defined(IS_X86) #if !defined(BLAKE3_NO_SSE2) void blake3_compress_in_place_sse2(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse2(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_SSE41) void blake3_compress_in_place_sse41(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse41(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX2) void blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX512) void blake3_compress_in_place_avx512(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_avx512(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif #if BLAKE3_USE_NEON == 1 void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif /* BLAKE3_IMPL_H */ ================================================ FILE: src/third_party/blake3/asm/blake3_neon.c ================================================ #include "blake3_impl.h" #include #ifdef __ARM_BIG_ENDIAN #error "This implementation only supports little-endian ARM." // It might be that all we need for big-endian support here is to get the loads // and stores right, but step zero would be finding a way to test it in CI. #endif INLINE uint32x4_t loadu_128(const uint8_t src[16]) { // vld1q_u32 has alignment requirements. Don't use it. uint32x4_t x; memcpy(&x, src, 16); return x; } INLINE void storeu_128(uint32x4_t src, uint8_t dest[16]) { // vst1q_u32 has alignment requirements. Don't use it. memcpy(dest, &src, 16); } INLINE uint32x4_t add_128(uint32x4_t a, uint32x4_t b) { return vaddq_u32(a, b); } INLINE uint32x4_t xor_128(uint32x4_t a, uint32x4_t b) { return veorq_u32(a, b); } INLINE uint32x4_t set1_128(uint32_t x) { return vld1q_dup_u32(&x); } INLINE uint32x4_t set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { uint32_t array[4] = {a, b, c, d}; return vld1q_u32(array); } INLINE uint32x4_t rot16_128(uint32x4_t x) { // The straightfoward implementation would be two shifts and an or, but that's // slower on microarchitectures we've tested. See // https://github.com/BLAKE3-team/BLAKE3/pull/319. // return vorrq_u32(vshrq_n_u32(x, 16), vshlq_n_u32(x, 32 - 16)); return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(x))); } INLINE uint32x4_t rot12_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 12), vshlq_n_u32(x, 32 - 12)); return vsriq_n_u32(vshlq_n_u32(x, 32-12), x, 12); } INLINE uint32x4_t rot8_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 8), vshlq_n_u32(x, 32 - 8)); #if defined(__clang__) return vreinterpretq_u32_u8(__builtin_shufflevector(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12)); #elif __GNUC__ * 10000 + __GNUC_MINOR__ * 100 >=40700 static const uint8x16_t r8 = {1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12}; return vreinterpretq_u32_u8(__builtin_shuffle(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), r8)); #else return vsriq_n_u32(vshlq_n_u32(x, 32-8), x, 8); #endif } INLINE uint32x4_t rot7_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 7), vshlq_n_u32(x, 32 - 7)); return vsriq_n_u32(vshlq_n_u32(x, 32-7), x, 7); } // TODO: compress_neon // TODO: hash2_neon /* * ---------------------------------------------------------------------------- * hash4_neon * ---------------------------------------------------------------------------- */ INLINE void round_fn4(uint32x4_t v[16], uint32x4_t m[16], size_t r) { v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[15] = rot16_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot12_128(v[4]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[15] = rot8_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot7_128(v[4]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot16_128(v[15]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[4] = rot12_128(v[4]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot8_128(v[15]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[4] = rot7_128(v[4]); } INLINE void transpose_vecs_128(uint32x4_t vecs[4]) { // Individually transpose the four 2x2 sub-matrices in each corner. uint32x4x2_t rows01 = vtrnq_u32(vecs[0], vecs[1]); uint32x4x2_t rows23 = vtrnq_u32(vecs[2], vecs[3]); // Swap the top-right and bottom-left 2x2s (which just got transposed). vecs[0] = vcombine_u32(vget_low_u32(rows01.val[0]), vget_low_u32(rows23.val[0])); vecs[1] = vcombine_u32(vget_low_u32(rows01.val[1]), vget_low_u32(rows23.val[1])); vecs[2] = vcombine_u32(vget_high_u32(rows01.val[0]), vget_high_u32(rows23.val[0])); vecs[3] = vcombine_u32(vget_high_u32(rows01.val[1]), vget_high_u32(rows23.val[1])); } INLINE void transpose_msg_vecs4(const uint8_t *const *inputs, size_t block_offset, uint32x4_t out[16]) { out[0] = loadu_128(&inputs[0][block_offset + 0 * sizeof(uint32x4_t)]); out[1] = loadu_128(&inputs[1][block_offset + 0 * sizeof(uint32x4_t)]); out[2] = loadu_128(&inputs[2][block_offset + 0 * sizeof(uint32x4_t)]); out[3] = loadu_128(&inputs[3][block_offset + 0 * sizeof(uint32x4_t)]); out[4] = loadu_128(&inputs[0][block_offset + 1 * sizeof(uint32x4_t)]); out[5] = loadu_128(&inputs[1][block_offset + 1 * sizeof(uint32x4_t)]); out[6] = loadu_128(&inputs[2][block_offset + 1 * sizeof(uint32x4_t)]); out[7] = loadu_128(&inputs[3][block_offset + 1 * sizeof(uint32x4_t)]); out[8] = loadu_128(&inputs[0][block_offset + 2 * sizeof(uint32x4_t)]); out[9] = loadu_128(&inputs[1][block_offset + 2 * sizeof(uint32x4_t)]); out[10] = loadu_128(&inputs[2][block_offset + 2 * sizeof(uint32x4_t)]); out[11] = loadu_128(&inputs[3][block_offset + 2 * sizeof(uint32x4_t)]); out[12] = loadu_128(&inputs[0][block_offset + 3 * sizeof(uint32x4_t)]); out[13] = loadu_128(&inputs[1][block_offset + 3 * sizeof(uint32x4_t)]); out[14] = loadu_128(&inputs[2][block_offset + 3 * sizeof(uint32x4_t)]); out[15] = loadu_128(&inputs[3][block_offset + 3 * sizeof(uint32x4_t)]); transpose_vecs_128(&out[0]); transpose_vecs_128(&out[4]); transpose_vecs_128(&out[8]); transpose_vecs_128(&out[12]); } INLINE void load_counters4(uint64_t counter, bool increment_counter, uint32x4_t *out_low, uint32x4_t *out_high) { uint64_t mask = (increment_counter ? ~0 : 0); *out_low = set4( counter_low(counter + (mask & 0)), counter_low(counter + (mask & 1)), counter_low(counter + (mask & 2)), counter_low(counter + (mask & 3))); *out_high = set4( counter_high(counter + (mask & 0)), counter_high(counter + (mask & 1)), counter_high(counter + (mask & 2)), counter_high(counter + (mask & 3))); } void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { uint32x4_t h_vecs[8] = { set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]), set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]), }; uint32x4_t counter_low_vec, counter_high_vec; load_counters4(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } uint32x4_t block_len_vec = set1_128(BLAKE3_BLOCK_LEN); uint32x4_t block_flags_vec = set1_128(block_flags); uint32x4_t msg_vecs[16]; transpose_msg_vecs4(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); uint32x4_t v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_128(IV[0]), set1_128(IV[1]), set1_128(IV[2]), set1_128(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn4(v, msg_vecs, 0); round_fn4(v, msg_vecs, 1); round_fn4(v, msg_vecs, 2); round_fn4(v, msg_vecs, 3); round_fn4(v, msg_vecs, 4); round_fn4(v, msg_vecs, 5); round_fn4(v, msg_vecs, 6); h_vecs[0] = xor_128(v[0], v[8]); h_vecs[1] = xor_128(v[1], v[9]); h_vecs[2] = xor_128(v[2], v[10]); h_vecs[3] = xor_128(v[3], v[11]); h_vecs[4] = xor_128(v[4], v[12]); h_vecs[5] = xor_128(v[5], v[13]); h_vecs[6] = xor_128(v[6], v[14]); h_vecs[7] = xor_128(v[7], v[15]); block_flags = flags; } transpose_vecs_128(&h_vecs[0]); transpose_vecs_128(&h_vecs[4]); // The first four vecs now contain the first half of each output, and the // second four vecs contain the second half of each output. storeu_128(h_vecs[0], &out[0 * sizeof(uint32x4_t)]); storeu_128(h_vecs[4], &out[1 * sizeof(uint32x4_t)]); storeu_128(h_vecs[1], &out[2 * sizeof(uint32x4_t)]); storeu_128(h_vecs[5], &out[3 * sizeof(uint32x4_t)]); storeu_128(h_vecs[2], &out[4 * sizeof(uint32x4_t)]); storeu_128(h_vecs[6], &out[5 * sizeof(uint32x4_t)]); storeu_128(h_vecs[3], &out[6 * sizeof(uint32x4_t)]); storeu_128(h_vecs[7], &out[7 * sizeof(uint32x4_t)]); } /* * ---------------------------------------------------------------------------- * hash_many_neon * ---------------------------------------------------------------------------- */ void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); INLINE void hash_one_neon(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } // TODO: Implement compress_neon. However note that according to // https://github.com/BLAKE2/BLAKE2/commit/7965d3e6e1b4193438b8d3a656787587d2579227, // compress_neon might not be any faster than compress_portable. blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } memcpy(out, cv, BLAKE3_OUT_LEN); } void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= 4) { blake3_hash4_neon(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 4; } inputs += 4; num_inputs -= 4; out = &out[4 * BLAKE3_OUT_LEN]; } while (num_inputs > 0) { hash_one_neon(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/asm/blake3_portable.c ================================================ #include "blake3_impl.h" #include INLINE uint32_t rotr32(uint32_t w, uint32_t c) { return (w >> c) | (w << (32 - c)); } INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y) { state[a] = state[a] + state[b] + x; state[d] = rotr32(state[d] ^ state[a], 16); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 12); state[a] = state[a] + state[b] + y; state[d] = rotr32(state[d] ^ state[a], 8); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 7); } INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) { // Select the message schedule based on the round. const uint8_t *schedule = MSG_SCHEDULE[round]; // Mix the columns. g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); // Mix the rows. g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); } INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t block_words[16]; block_words[0] = load32(block + 4 * 0); block_words[1] = load32(block + 4 * 1); block_words[2] = load32(block + 4 * 2); block_words[3] = load32(block + 4 * 3); block_words[4] = load32(block + 4 * 4); block_words[5] = load32(block + 4 * 5); block_words[6] = load32(block + 4 * 6); block_words[7] = load32(block + 4 * 7); block_words[8] = load32(block + 4 * 8); block_words[9] = load32(block + 4 * 9); block_words[10] = load32(block + 4 * 10); block_words[11] = load32(block + 4 * 11); block_words[12] = load32(block + 4 * 12); block_words[13] = load32(block + 4 * 13); block_words[14] = load32(block + 4 * 14); block_words[15] = load32(block + 4 * 15); state[0] = cv[0]; state[1] = cv[1]; state[2] = cv[2]; state[3] = cv[3]; state[4] = cv[4]; state[5] = cv[5]; state[6] = cv[6]; state[7] = cv[7]; state[8] = IV[0]; state[9] = IV[1]; state[10] = IV[2]; state[11] = IV[3]; state[12] = counter_low(counter); state[13] = counter_high(counter); state[14] = (uint32_t)block_len; state[15] = (uint32_t)flags; round_fn(state, &block_words[0], 0); round_fn(state, &block_words[0], 1); round_fn(state, &block_words[0], 2); round_fn(state, &block_words[0], 3); round_fn(state, &block_words[0], 4); round_fn(state, &block_words[0], 5); round_fn(state, &block_words[0], 6); } void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); cv[0] = state[0] ^ state[8]; cv[1] = state[1] ^ state[9]; cv[2] = state[2] ^ state[10]; cv[3] = state[3] ^ state[11]; cv[4] = state[4] ^ state[12]; cv[5] = state[5] ^ state[13]; cv[6] = state[6] ^ state[14]; cv[7] = state[7] ^ state[15]; } void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); store32(&out[0 * 4], state[0] ^ state[8]); store32(&out[1 * 4], state[1] ^ state[9]); store32(&out[2 * 4], state[2] ^ state[10]); store32(&out[3 * 4], state[3] ^ state[11]); store32(&out[4 * 4], state[4] ^ state[12]); store32(&out[5 * 4], state[5] ^ state[13]); store32(&out[6 * 4], state[6] ^ state[14]); store32(&out[7 * 4], state[7] ^ state[15]); store32(&out[8 * 4], state[8] ^ cv[0]); store32(&out[9 * 4], state[9] ^ cv[1]); store32(&out[10 * 4], state[10] ^ cv[2]); store32(&out[11 * 4], state[11] ^ cv[3]); store32(&out[12 * 4], state[12] ^ cv[4]); store32(&out[13 * 4], state[13] ^ cv[5]); store32(&out[14 * 4], state[14] ^ cv[6]); store32(&out[15 * 4], state[15] ^ cv[7]); } INLINE void hash_one_portable(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } store_cv_words(out, cv); } void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs > 0) { hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/asm/blake3_sse2_x86-64_unix.S ================================================ #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif #if defined(__ELF__) && defined(__CET__) && defined(__has_include) #if __has_include() #include #endif #endif #if !defined(_CET_ENDBR) #define _CET_ENDBR #endif .intel_syntax noprefix .global blake3_hash_many_sse2 .global _blake3_hash_many_sse2 .global blake3_compress_in_place_sse2 .global _blake3_compress_in_place_sse2 .global blake3_compress_xof_sse2 .global _blake3_compress_xof_sse2 #ifdef __APPLE__ .text #else .section .text #endif .p2align 6 _blake3_hash_many_sse2: blake3_hash_many_sse2: _CET_ENDBR push r15 push r14 push r13 push r12 push rbx push rbp mov rbp, rsp sub rsp, 360 and rsp, 0xFFFFFFFFFFFFFFC0 neg r9d movd xmm0, r9d pshufd xmm0, xmm0, 0x00 movdqa xmmword ptr [rsp+0x130], xmm0 movdqa xmm1, xmm0 pand xmm1, xmmword ptr [ADD0+rip] pand xmm0, xmmword ptr [ADD1+rip] movdqa xmmword ptr [rsp+0x150], xmm0 movd xmm0, r8d pshufd xmm0, xmm0, 0x00 paddd xmm0, xmm1 movdqa xmmword ptr [rsp+0x110], xmm0 pxor xmm0, xmmword ptr [CMP_MSB_MASK+rip] pxor xmm1, xmmword ptr [CMP_MSB_MASK+rip] pcmpgtd xmm1, xmm0 shr r8, 32 movd xmm2, r8d pshufd xmm2, xmm2, 0x00 psubd xmm2, xmm1 movdqa xmmword ptr [rsp+0x120], xmm2 mov rbx, qword ptr [rbp+0x50] mov r15, rdx shl r15, 6 movzx r13d, byte ptr [rbp+0x38] movzx r12d, byte ptr [rbp+0x48] cmp rsi, 4 jc 3f 2: movdqu xmm3, xmmword ptr [rcx] pshufd xmm0, xmm3, 0x00 pshufd xmm1, xmm3, 0x55 pshufd xmm2, xmm3, 0xAA pshufd xmm3, xmm3, 0xFF movdqu xmm7, xmmword ptr [rcx+0x10] pshufd xmm4, xmm7, 0x00 pshufd xmm5, xmm7, 0x55 pshufd xmm6, xmm7, 0xAA pshufd xmm7, xmm7, 0xFF mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 9: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movdqu xmm8, xmmword ptr [r8+rdx-0x40] movdqu xmm9, xmmword ptr [r9+rdx-0x40] movdqu xmm10, xmmword ptr [r10+rdx-0x40] movdqu xmm11, xmmword ptr [r11+rdx-0x40] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp], xmm8 movdqa xmmword ptr [rsp+0x10], xmm9 movdqa xmmword ptr [rsp+0x20], xmm12 movdqa xmmword ptr [rsp+0x30], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x30] movdqu xmm9, xmmword ptr [r9+rdx-0x30] movdqu xmm10, xmmword ptr [r10+rdx-0x30] movdqu xmm11, xmmword ptr [r11+rdx-0x30] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0x40], xmm8 movdqa xmmword ptr [rsp+0x50], xmm9 movdqa xmmword ptr [rsp+0x60], xmm12 movdqa xmmword ptr [rsp+0x70], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x20] movdqu xmm9, xmmword ptr [r9+rdx-0x20] movdqu xmm10, xmmword ptr [r10+rdx-0x20] movdqu xmm11, xmmword ptr [r11+rdx-0x20] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0x80], xmm8 movdqa xmmword ptr [rsp+0x90], xmm9 movdqa xmmword ptr [rsp+0xA0], xmm12 movdqa xmmword ptr [rsp+0xB0], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x10] movdqu xmm9, xmmword ptr [r9+rdx-0x10] movdqu xmm10, xmmword ptr [r10+rdx-0x10] movdqu xmm11, xmmword ptr [r11+rdx-0x10] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0xC0], xmm8 movdqa xmmword ptr [rsp+0xD0], xmm9 movdqa xmmword ptr [rsp+0xE0], xmm12 movdqa xmmword ptr [rsp+0xF0], xmm13 movdqa xmm9, xmmword ptr [BLAKE3_IV_1+rip] movdqa xmm10, xmmword ptr [BLAKE3_IV_2+rip] movdqa xmm11, xmmword ptr [BLAKE3_IV_3+rip] movdqa xmm12, xmmword ptr [rsp+0x110] movdqa xmm13, xmmword ptr [rsp+0x120] movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN+rip] movd xmm15, eax pshufd xmm15, xmm15, 0x00 prefetcht0 [r8+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r11+rdx+0x80] paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x40] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [BLAKE3_IV_0+rip] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x10] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x50] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x80] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0xC0] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x90] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0xD0] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x20] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x70] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x60] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x10] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x90] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xB0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0xE0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x30] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0xD0] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x40] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x20] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x60] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0xB0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x50] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0xF0] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xA0] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0xE0] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x70] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0x30] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x40] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0x50] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x80] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xC0] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0xF0] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xD0] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0xA0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x70] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x20] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x10] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x90] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0x80] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xE0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0xC0] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xD0] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0x20] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x30] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0x60] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xB0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0x10] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xF0] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0x90] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xE0] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x30] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0xB1 pshufhw xmm15, xmm15, 0xB1 pshuflw xmm12, xmm12, 0xB1 pshufhw xmm12, xmm12, 0xB1 pshuflw xmm13, xmm13, 0xB1 pshufhw xmm13, xmm13, 0xB1 pshuflw xmm14, xmm14, 0xB1 pshufhw xmm14, xmm14, 0xB1 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xA0] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x40] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 pxor xmm0, xmm8 pxor xmm1, xmm9 pxor xmm2, xmm10 pxor xmm3, xmm11 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 mov eax, r13d jne 9b movdqa xmm9, xmm0 punpckldq xmm0, xmm1 punpckhdq xmm9, xmm1 movdqa xmm11, xmm2 punpckldq xmm2, xmm3 punpckhdq xmm11, xmm3 movdqa xmm1, xmm0 punpcklqdq xmm0, xmm2 punpckhqdq xmm1, xmm2 movdqa xmm3, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm3, xmm11 movdqu xmmword ptr [rbx], xmm0 movdqu xmmword ptr [rbx+0x20], xmm1 movdqu xmmword ptr [rbx+0x40], xmm9 movdqu xmmword ptr [rbx+0x60], xmm3 movdqa xmm9, xmm4 punpckldq xmm4, xmm5 punpckhdq xmm9, xmm5 movdqa xmm11, xmm6 punpckldq xmm6, xmm7 punpckhdq xmm11, xmm7 movdqa xmm5, xmm4 punpcklqdq xmm4, xmm6 punpckhqdq xmm5, xmm6 movdqa xmm7, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm7, xmm11 movdqu xmmword ptr [rbx+0x10], xmm4 movdqu xmmword ptr [rbx+0x30], xmm5 movdqu xmmword ptr [rbx+0x50], xmm9 movdqu xmmword ptr [rbx+0x70], xmm7 movdqa xmm1, xmmword ptr [rsp+0x110] movdqa xmm0, xmm1 paddd xmm1, xmmword ptr [rsp+0x150] movdqa xmmword ptr [rsp+0x110], xmm1 pxor xmm0, xmmword ptr [CMP_MSB_MASK+rip] pxor xmm1, xmmword ptr [CMP_MSB_MASK+rip] pcmpgtd xmm0, xmm1 movdqa xmm1, xmmword ptr [rsp+0x120] psubd xmm1, xmm0 movdqa xmmword ptr [rsp+0x120], xmm1 add rbx, 128 add rdi, 32 sub rsi, 4 cmp rsi, 4 jnc 2b test rsi, rsi jnz 3f 4: mov rsp, rbp pop rbp pop rbx pop r12 pop r13 pop r14 pop r15 ret .p2align 5 3: test esi, 0x2 je 3f movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+0x10] movaps xmm8, xmm0 movaps xmm9, xmm1 movd xmm13, dword ptr [rsp+0x110] movd xmm14, dword ptr [rsp+0x120] punpckldq xmm13, xmm14 movaps xmmword ptr [rsp], xmm13 movd xmm14, dword ptr [rsp+0x114] movd xmm13, dword ptr [rsp+0x124] punpckldq xmm14, xmm13 movaps xmmword ptr [rsp+0x10], xmm14 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV+rip] movaps xmm10, xmm2 movups xmm4, xmmword ptr [r8+rdx-0x40] movups xmm5, xmmword ptr [r8+rdx-0x30] movaps xmm3, xmm4 shufps xmm4, xmm5, 136 shufps xmm3, xmm5, 221 movaps xmm5, xmm3 movups xmm6, xmmword ptr [r8+rdx-0x20] movups xmm7, xmmword ptr [r8+rdx-0x10] movaps xmm3, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm3, xmm7, 221 pshufd xmm7, xmm3, 0x93 movups xmm12, xmmword ptr [r9+rdx-0x40] movups xmm13, xmmword ptr [r9+rdx-0x30] movaps xmm11, xmm12 shufps xmm12, xmm13, 136 shufps xmm11, xmm13, 221 movaps xmm13, xmm11 movups xmm14, xmmword ptr [r9+rdx-0x20] movups xmm15, xmmword ptr [r9+rdx-0x10] movaps xmm11, xmm14 shufps xmm14, xmm15, 136 pshufd xmm14, xmm14, 0x93 shufps xmm11, xmm15, 221 pshufd xmm15, xmm11, 0x93 shl rax, 0x20 or rax, 0x40 movq xmm3, rax movdqa xmmword ptr [rsp+0x20], xmm3 movaps xmm3, xmmword ptr [rsp] movaps xmm11, xmmword ptr [rsp+0x10] punpcklqdq xmm3, xmmword ptr [rsp+0x20] punpcklqdq xmm11, xmmword ptr [rsp+0x20] mov al, 7 9: paddd xmm0, xmm4 paddd xmm8, xmm12 movaps xmmword ptr [rsp+0x20], xmm4 movaps xmmword ptr [rsp+0x30], xmm12 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 pshuflw xmm11, xmm11, 0xB1 pshufhw xmm11, xmm11, 0xB1 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm5 paddd xmm8, xmm13 movaps xmmword ptr [rsp+0x40], xmm5 movaps xmmword ptr [rsp+0x50], xmm13 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movdqa xmm13, xmm3 psrld xmm3, 8 pslld xmm13, 24 pxor xmm3, xmm13 movdqa xmm13, xmm11 psrld xmm11, 8 pslld xmm13, 24 pxor xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 0x93 pshufd xmm8, xmm8, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm11, xmm11, 0x4E pshufd xmm2, xmm2, 0x39 pshufd xmm10, xmm10, 0x39 paddd xmm0, xmm6 paddd xmm8, xmm14 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 pshuflw xmm11, xmm11, 0xB1 pshufhw xmm11, xmm11, 0xB1 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm7 paddd xmm8, xmm15 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movdqa xmm13, xmm3 psrld xmm3, 8 pslld xmm13, 24 pxor xmm3, xmm13 movdqa xmm13, xmm11 psrld xmm11, 8 pslld xmm13, 24 pxor xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 0x39 pshufd xmm8, xmm8, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm11, xmm11, 0x4E pshufd xmm2, xmm2, 0x93 pshufd xmm10, xmm10, 0x93 dec al je 9f movdqa xmm12, xmmword ptr [rsp+0x20] movdqa xmm5, xmmword ptr [rsp+0x40] pshufd xmm13, xmm12, 0x0F shufps xmm12, xmm5, 214 pshufd xmm4, xmm12, 0x39 movdqa xmm12, xmm6 shufps xmm12, xmm7, 250 pand xmm13, xmmword ptr [PBLENDW_0x33_MASK+rip] pand xmm12, xmmword ptr [PBLENDW_0xCC_MASK+rip] por xmm13, xmm12 movdqa xmmword ptr [rsp+0x20], xmm13 movdqa xmm12, xmm7 punpcklqdq xmm12, xmm5 movdqa xmm13, xmm6 pand xmm12, xmmword ptr [PBLENDW_0x3F_MASK+rip] pand xmm13, xmmword ptr [PBLENDW_0xC0_MASK+rip] por xmm12, xmm13 pshufd xmm12, xmm12, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmmword ptr [rsp+0x40], xmm12 movdqa xmm5, xmmword ptr [rsp+0x30] movdqa xmm13, xmmword ptr [rsp+0x50] pshufd xmm6, xmm5, 0x0F shufps xmm5, xmm13, 214 pshufd xmm12, xmm5, 0x39 movdqa xmm5, xmm14 shufps xmm5, xmm15, 250 pand xmm6, xmmword ptr [PBLENDW_0x33_MASK+rip] pand xmm5, xmmword ptr [PBLENDW_0xCC_MASK+rip] por xmm6, xmm5 movdqa xmm5, xmm15 punpcklqdq xmm5, xmm13 movdqa xmmword ptr [rsp+0x30], xmm2 movdqa xmm2, xmm14 pand xmm5, xmmword ptr [PBLENDW_0x3F_MASK+rip] pand xmm2, xmmword ptr [PBLENDW_0xC0_MASK+rip] por xmm5, xmm2 movdqa xmm2, xmmword ptr [rsp+0x30] pshufd xmm5, xmm5, 0x78 punpckhdq xmm13, xmm15 punpckldq xmm14, xmm13 pshufd xmm15, xmm14, 0x1E movdqa xmm13, xmm6 movdqa xmm14, xmm5 movdqa xmm5, xmmword ptr [rsp+0x20] movdqa xmm6, xmmword ptr [rsp+0x40] jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm8, xmm10 pxor xmm9, xmm11 mov eax, r13d cmp rdx, r15 jne 2b movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+0x10], xmm1 movups xmmword ptr [rbx+0x20], xmm8 movups xmmword ptr [rbx+0x30], xmm9 mov eax, dword ptr [rsp+0x130] neg eax mov r10d, dword ptr [rsp+0x110+8*rax] mov r11d, dword ptr [rsp+0x120+8*rax] mov dword ptr [rsp+0x110], r10d mov dword ptr [rsp+0x120], r11d add rdi, 16 add rbx, 64 sub rsi, 2 3: test esi, 0x1 je 4b movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+0x10] movd xmm13, dword ptr [rsp+0x110] movd xmm14, dword ptr [rsp+0x120] punpckldq xmm13, xmm14 mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV+rip] shl rax, 32 or rax, 64 movq xmm12, rax movdqa xmm3, xmm13 punpcklqdq xmm3, xmm12 movups xmm4, xmmword ptr [r8+rdx-0x40] movups xmm5, xmmword ptr [r8+rdx-0x30] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [r8+rdx-0x20] movups xmm7, xmmword ptr [r8+rdx-0x10] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK+rip] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK+rip] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm10, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK+rip] pand xmm10, xmmword ptr [PBLENDW_0xC0_MASK+rip] por xmm8, xmm10 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne 2b movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+0x10], xmm1 jmp 4b .p2align 6 blake3_compress_in_place_sse2: _blake3_compress_in_place_sse2: _CET_ENDBR movups xmm0, xmmword ptr [rdi] movups xmm1, xmmword ptr [rdi+0x10] movaps xmm2, xmmword ptr [BLAKE3_IV+rip] shl r8, 32 add rdx, r8 movq xmm3, rcx movq xmm4, rdx punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rsi] movups xmm5, xmmword ptr [rsi+0x10] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rsi+0x20] movups xmm7, xmmword ptr [rsi+0x30] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK+rip] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK+rip] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm10, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK+rip] pand xmm10, xmmword ptr [PBLENDW_0xC0_MASK+rip] por xmm8, xmm10 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 movups xmmword ptr [rdi], xmm0 movups xmmword ptr [rdi+0x10], xmm1 ret .p2align 6 blake3_compress_xof_sse2: _blake3_compress_xof_sse2: _CET_ENDBR movups xmm0, xmmword ptr [rdi] movups xmm1, xmmword ptr [rdi+0x10] movaps xmm2, xmmword ptr [BLAKE3_IV+rip] movzx eax, r8b movzx edx, dl shl rax, 32 add rdx, rax movq xmm3, rcx movq xmm4, rdx punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rsi] movups xmm5, xmmword ptr [rsi+0x10] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rsi+0x20] movups xmm7, xmmword ptr [rsi+0x30] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0xB1 pshufhw xmm3, xmm3, 0xB1 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK+rip] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK+rip] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm10, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK+rip] pand xmm10, xmmword ptr [PBLENDW_0xC0_MASK+rip] por xmm8, xmm10 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: movdqu xmm4, xmmword ptr [rdi] movdqu xmm5, xmmword ptr [rdi+0x10] pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm2, xmm4 pxor xmm3, xmm5 movups xmmword ptr [r9], xmm0 movups xmmword ptr [r9+0x10], xmm1 movups xmmword ptr [r9+0x20], xmm2 movups xmmword ptr [r9+0x30], xmm3 ret #ifdef __APPLE__ .static_data #else .section .rodata #endif .p2align 6 BLAKE3_IV: .long 0x6A09E667, 0xBB67AE85 .long 0x3C6EF372, 0xA54FF53A ADD0: .long 0, 1, 2, 3 ADD1: .long 4, 4, 4, 4 BLAKE3_IV_0: .long 0x6A09E667, 0x6A09E667, 0x6A09E667, 0x6A09E667 BLAKE3_IV_1: .long 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, 0xBB67AE85 BLAKE3_IV_2: .long 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, 0x3C6EF372 BLAKE3_IV_3: .long 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, 0xA54FF53A BLAKE3_BLOCK_LEN: .long 64, 64, 64, 64 CMP_MSB_MASK: .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 PBLENDW_0x33_MASK: .long 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 PBLENDW_0xCC_MASK: .long 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF PBLENDW_0x3F_MASK: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 PBLENDW_0xC0_MASK: .long 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF ================================================ FILE: src/third_party/blake3/asm/blake3_sse2_x86-64_windows_msvc.asm ================================================ public _blake3_hash_many_sse2 public blake3_hash_many_sse2 public blake3_compress_in_place_sse2 public _blake3_compress_in_place_sse2 public blake3_compress_xof_sse2 public _blake3_compress_xof_sse2 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 blake3_hash_many_sse2 PROC _blake3_hash_many_sse2 PROC push r15 push r14 push r13 push r12 push rsi push rdi push rbx push rbp mov rbp, rsp sub rsp, 528 and rsp, 0FFFFFFFFFFFFFFC0H movdqa xmmword ptr [rsp+170H], xmm6 movdqa xmmword ptr [rsp+180H], xmm7 movdqa xmmword ptr [rsp+190H], xmm8 movdqa xmmword ptr [rsp+1A0H], xmm9 movdqa xmmword ptr [rsp+1B0H], xmm10 movdqa xmmword ptr [rsp+1C0H], xmm11 movdqa xmmword ptr [rsp+1D0H], xmm12 movdqa xmmword ptr [rsp+1E0H], xmm13 movdqa xmmword ptr [rsp+1F0H], xmm14 movdqa xmmword ptr [rsp+200H], xmm15 mov rdi, rcx mov rsi, rdx mov rdx, r8 mov rcx, r9 mov r8, qword ptr [rbp+68H] movzx r9, byte ptr [rbp+70H] neg r9d movd xmm0, r9d pshufd xmm0, xmm0, 00H movdqa xmmword ptr [rsp+130H], xmm0 movdqa xmm1, xmm0 pand xmm1, xmmword ptr [ADD0] pand xmm0, xmmword ptr [ADD1] movdqa xmmword ptr [rsp+150H], xmm0 movd xmm0, r8d pshufd xmm0, xmm0, 00H paddd xmm0, xmm1 movdqa xmmword ptr [rsp+110H], xmm0 pxor xmm0, xmmword ptr [CMP_MSB_MASK] pxor xmm1, xmmword ptr [CMP_MSB_MASK] pcmpgtd xmm1, xmm0 shr r8, 32 movd xmm2, r8d pshufd xmm2, xmm2, 00H psubd xmm2, xmm1 movdqa xmmword ptr [rsp+120H], xmm2 mov rbx, qword ptr [rbp+90H] mov r15, rdx shl r15, 6 movzx r13d, byte ptr [rbp+78H] movzx r12d, byte ptr [rbp+88H] cmp rsi, 4 jc final3blocks outerloop4: movdqu xmm3, xmmword ptr [rcx] pshufd xmm0, xmm3, 00H pshufd xmm1, xmm3, 55H pshufd xmm2, xmm3, 0AAH pshufd xmm3, xmm3, 0FFH movdqu xmm7, xmmword ptr [rcx+10H] pshufd xmm4, xmm7, 00H pshufd xmm5, xmm7, 55H pshufd xmm6, xmm7, 0AAH pshufd xmm7, xmm7, 0FFH mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop4: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movdqu xmm8, xmmword ptr [r8+rdx-40H] movdqu xmm9, xmmword ptr [r9+rdx-40H] movdqu xmm10, xmmword ptr [r10+rdx-40H] movdqu xmm11, xmmword ptr [r11+rdx-40H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp], xmm8 movdqa xmmword ptr [rsp+10H], xmm9 movdqa xmmword ptr [rsp+20H], xmm12 movdqa xmmword ptr [rsp+30H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-30H] movdqu xmm9, xmmword ptr [r9+rdx-30H] movdqu xmm10, xmmword ptr [r10+rdx-30H] movdqu xmm11, xmmword ptr [r11+rdx-30H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+40H], xmm8 movdqa xmmword ptr [rsp+50H], xmm9 movdqa xmmword ptr [rsp+60H], xmm12 movdqa xmmword ptr [rsp+70H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-20H] movdqu xmm9, xmmword ptr [r9+rdx-20H] movdqu xmm10, xmmword ptr [r10+rdx-20H] movdqu xmm11, xmmword ptr [r11+rdx-20H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+80H], xmm8 movdqa xmmword ptr [rsp+90H], xmm9 movdqa xmmword ptr [rsp+0A0H], xmm12 movdqa xmmword ptr [rsp+0B0H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-10H] movdqu xmm9, xmmword ptr [r9+rdx-10H] movdqu xmm10, xmmword ptr [r10+rdx-10H] movdqu xmm11, xmmword ptr [r11+rdx-10H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0C0H], xmm8 movdqa xmmword ptr [rsp+0D0H], xmm9 movdqa xmmword ptr [rsp+0E0H], xmm12 movdqa xmmword ptr [rsp+0F0H], xmm13 movdqa xmm9, xmmword ptr [BLAKE3_IV_1] movdqa xmm10, xmmword ptr [BLAKE3_IV_2] movdqa xmm11, xmmword ptr [BLAKE3_IV_3] movdqa xmm12, xmmword ptr [rsp+110H] movdqa xmm13, xmmword ptr [rsp+120H] movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN] movd xmm15, eax pshufd xmm15, xmm15, 00H prefetcht0 byte ptr [r8+rdx+80H] prefetcht0 byte ptr [r9+rdx+80H] prefetcht0 byte ptr [r10+rdx+80H] prefetcht0 byte ptr [r11+rdx+80H] paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+40H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [BLAKE3_IV_0] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+10H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+50H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+80H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+0C0H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+90H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+0D0H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+20H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+70H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+60H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+10H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+90H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0B0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+0E0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+30H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+0D0H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+40H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+20H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+60H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+0B0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+50H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0F0H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0A0H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+0E0H] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+70H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+30H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+40H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+50H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+80H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0C0H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+0F0H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0D0H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+0A0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+70H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+20H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+10H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+90H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+80H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0E0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+0C0H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0D0H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+20H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+30H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+60H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0B0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+10H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0F0H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+90H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0E0H] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+30H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 pshuflw xmm15, xmm15, 0B1H pshufhw xmm15, xmm15, 0B1H pshuflw xmm12, xmm12, 0B1H pshufhw xmm12, xmm12, 0B1H pshuflw xmm13, xmm13, 0B1H pshufhw xmm13, xmm13, 0B1H pshuflw xmm14, xmm14, 0B1H pshufhw xmm14, xmm14, 0B1H paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0A0H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+40H] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmm15 psrld xmm15, 8 pslld xmm8, 24 pxor xmm15, xmm8 movdqa xmm8, xmm12 psrld xmm12, 8 pslld xmm8, 24 pxor xmm12, xmm8 movdqa xmm8, xmm13 psrld xmm13, 8 pslld xmm8, 24 pxor xmm13, xmm8 movdqa xmm8, xmm14 psrld xmm14, 8 pslld xmm8, 24 pxor xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 pxor xmm0, xmm8 pxor xmm1, xmm9 pxor xmm2, xmm10 pxor xmm3, xmm11 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 mov eax, r13d jne innerloop4 movdqa xmm9, xmm0 punpckldq xmm0, xmm1 punpckhdq xmm9, xmm1 movdqa xmm11, xmm2 punpckldq xmm2, xmm3 punpckhdq xmm11, xmm3 movdqa xmm1, xmm0 punpcklqdq xmm0, xmm2 punpckhqdq xmm1, xmm2 movdqa xmm3, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm3, xmm11 movdqu xmmword ptr [rbx], xmm0 movdqu xmmword ptr [rbx+20H], xmm1 movdqu xmmword ptr [rbx+40H], xmm9 movdqu xmmword ptr [rbx+60H], xmm3 movdqa xmm9, xmm4 punpckldq xmm4, xmm5 punpckhdq xmm9, xmm5 movdqa xmm11, xmm6 punpckldq xmm6, xmm7 punpckhdq xmm11, xmm7 movdqa xmm5, xmm4 punpcklqdq xmm4, xmm6 punpckhqdq xmm5, xmm6 movdqa xmm7, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm7, xmm11 movdqu xmmword ptr [rbx+10H], xmm4 movdqu xmmword ptr [rbx+30H], xmm5 movdqu xmmword ptr [rbx+50H], xmm9 movdqu xmmword ptr [rbx+70H], xmm7 movdqa xmm1, xmmword ptr [rsp+110H] movdqa xmm0, xmm1 paddd xmm1, xmmword ptr [rsp+150H] movdqa xmmword ptr [rsp+110H], xmm1 pxor xmm0, xmmword ptr [CMP_MSB_MASK] pxor xmm1, xmmword ptr [CMP_MSB_MASK] pcmpgtd xmm0, xmm1 movdqa xmm1, xmmword ptr [rsp+120H] psubd xmm1, xmm0 movdqa xmmword ptr [rsp+120H], xmm1 add rbx, 128 add rdi, 32 sub rsi, 4 cmp rsi, 4 jnc outerloop4 test rsi, rsi jne final3blocks unwind: movdqa xmm6, xmmword ptr [rsp+170H] movdqa xmm7, xmmword ptr [rsp+180H] movdqa xmm8, xmmword ptr [rsp+190H] movdqa xmm9, xmmword ptr [rsp+1A0H] movdqa xmm10, xmmword ptr [rsp+1B0H] movdqa xmm11, xmmword ptr [rsp+1C0H] movdqa xmm12, xmmword ptr [rsp+1D0H] movdqa xmm13, xmmword ptr [rsp+1E0H] movdqa xmm14, xmmword ptr [rsp+1F0H] movdqa xmm15, xmmword ptr [rsp+200H] mov rsp, rbp pop rbp pop rbx pop rdi pop rsi pop r12 pop r13 pop r14 pop r15 ret ALIGN 16 final3blocks: test esi, 2H je final1block movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm8, xmm0 movaps xmm9, xmm1 movd xmm13, dword ptr [rsp+110H] movd xmm14, dword ptr [rsp+120H] punpckldq xmm13, xmm14 movaps xmmword ptr [rsp], xmm13 movd xmm14, dword ptr [rsp+114H] movd xmm13, dword ptr [rsp+124H] punpckldq xmm14, xmm13 movaps xmmword ptr [rsp+10H], xmm14 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV] movaps xmm10, xmm2 movups xmm4, xmmword ptr [r8+rdx-40H] movups xmm5, xmmword ptr [r8+rdx-30H] movaps xmm3, xmm4 shufps xmm4, xmm5, 136 shufps xmm3, xmm5, 221 movaps xmm5, xmm3 movups xmm6, xmmword ptr [r8+rdx-20H] movups xmm7, xmmword ptr [r8+rdx-10H] movaps xmm3, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm3, xmm7, 221 pshufd xmm7, xmm3, 93H movups xmm12, xmmword ptr [r9+rdx-40H] movups xmm13, xmmword ptr [r9+rdx-30H] movaps xmm11, xmm12 shufps xmm12, xmm13, 136 shufps xmm11, xmm13, 221 movaps xmm13, xmm11 movups xmm14, xmmword ptr [r9+rdx-20H] movups xmm15, xmmword ptr [r9+rdx-10H] movaps xmm11, xmm14 shufps xmm14, xmm15, 136 pshufd xmm14, xmm14, 93H shufps xmm11, xmm15, 221 pshufd xmm15, xmm11, 93H shl rax, 20H or rax, 40H movd xmm3, rax movdqa xmmword ptr [rsp+20H], xmm3 movaps xmm3, xmmword ptr [rsp] movaps xmm11, xmmword ptr [rsp+10H] punpcklqdq xmm3, xmmword ptr [rsp+20H] punpcklqdq xmm11, xmmword ptr [rsp+20H] mov al, 7 roundloop2: paddd xmm0, xmm4 paddd xmm8, xmm12 movaps xmmword ptr [rsp+20H], xmm4 movaps xmmword ptr [rsp+30H], xmm12 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H pshuflw xmm11, xmm11, 0B1H pshufhw xmm11, xmm11, 0B1H paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm5 paddd xmm8, xmm13 movaps xmmword ptr [rsp+40H], xmm5 movaps xmmword ptr [rsp+50H], xmm13 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movdqa xmm13, xmm3 psrld xmm3, 8 pslld xmm13, 24 pxor xmm3, xmm13 movdqa xmm13, xmm11 psrld xmm11, 8 pslld xmm13, 24 pxor xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 93H pshufd xmm8, xmm8, 93H pshufd xmm3, xmm3, 4EH pshufd xmm11, xmm11, 4EH pshufd xmm2, xmm2, 39H pshufd xmm10, xmm10, 39H paddd xmm0, xmm6 paddd xmm8, xmm14 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H pshuflw xmm11, xmm11, 0B1H pshufhw xmm11, xmm11, 0B1H paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm7 paddd xmm8, xmm15 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movdqa xmm13, xmm3 psrld xmm3, 8 pslld xmm13, 24 pxor xmm3, xmm13 movdqa xmm13, xmm11 psrld xmm11, 8 pslld xmm13, 24 pxor xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 39H pshufd xmm8, xmm8, 39H pshufd xmm3, xmm3, 4EH pshufd xmm11, xmm11, 4EH pshufd xmm2, xmm2, 93H pshufd xmm10, xmm10, 93H dec al je endroundloop2 movdqa xmm12, xmmword ptr [rsp+20H] movdqa xmm5, xmmword ptr [rsp+40H] pshufd xmm13, xmm12, 0FH shufps xmm12, xmm5, 214 pshufd xmm4, xmm12, 39H movdqa xmm12, xmm6 shufps xmm12, xmm7, 250 pand xmm13, xmmword ptr [PBLENDW_0x33_MASK] pand xmm12, xmmword ptr [PBLENDW_0xCC_MASK] por xmm13, xmm12 movdqa xmmword ptr [rsp+20H], xmm13 movdqa xmm12, xmm7 punpcklqdq xmm12, xmm5 movdqa xmm13, xmm6 pand xmm12, xmmword ptr [PBLENDW_0x3F_MASK] pand xmm13, xmmword ptr [PBLENDW_0xC0_MASK] por xmm12, xmm13 pshufd xmm12, xmm12, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmmword ptr [rsp+40H], xmm12 movdqa xmm5, xmmword ptr [rsp+30H] movdqa xmm13, xmmword ptr [rsp+50H] pshufd xmm6, xmm5, 0FH shufps xmm5, xmm13, 214 pshufd xmm12, xmm5, 39H movdqa xmm5, xmm14 shufps xmm5, xmm15, 250 pand xmm6, xmmword ptr [PBLENDW_0x33_MASK] pand xmm5, xmmword ptr [PBLENDW_0xCC_MASK] por xmm6, xmm5 movdqa xmm5, xmm15 punpcklqdq xmm5, xmm13 movdqa xmmword ptr [rsp+30H], xmm2 movdqa xmm2, xmm14 pand xmm5, xmmword ptr [PBLENDW_0x3F_MASK] pand xmm2, xmmword ptr [PBLENDW_0xC0_MASK] por xmm5, xmm2 movdqa xmm2, xmmword ptr [rsp+30H] pshufd xmm5, xmm5, 78H punpckhdq xmm13, xmm15 punpckldq xmm14, xmm13 pshufd xmm15, xmm14, 1EH movdqa xmm13, xmm6 movdqa xmm14, xmm5 movdqa xmm5, xmmword ptr [rsp+20H] movdqa xmm6, xmmword ptr [rsp+40H] jmp roundloop2 endroundloop2: pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm8, xmm10 pxor xmm9, xmm11 mov eax, r13d cmp rdx, r15 jne innerloop2 movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 movups xmmword ptr [rbx+20H], xmm8 movups xmmword ptr [rbx+30H], xmm9 mov eax, dword ptr [rsp+130H] neg eax mov r10d, dword ptr [rsp+110H+8*rax] mov r11d, dword ptr [rsp+120H+8*rax] mov dword ptr [rsp+110H], r10d mov dword ptr [rsp+120H], r11d add rdi, 16 add rbx, 64 sub rsi, 2 final1block: test esi, 1H je unwind movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movd xmm13, dword ptr [rsp+110H] movd xmm14, dword ptr [rsp+120H] punpckldq xmm13, xmm14 mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop1: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV] shl rax, 32 or rax, 64 movd xmm12, rax movdqa xmm3, xmm13 punpcklqdq xmm3, xmm12 movups xmm4, xmmword ptr [r8+rdx-40H] movups xmm5, xmmword ptr [r8+rdx-30H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [r8+rdx-20H] movups xmm7, xmmword ptr [r8+rdx-10H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H mov al, 7 roundloop1: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz endroundloop1 movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm10, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK] pand xmm10, xmmword ptr [PBLENDW_0xC0_MASK] por xmm8, xmm10 pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp roundloop1 endroundloop1: pxor xmm0, xmm2 pxor xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne innerloop1 movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 jmp unwind _blake3_hash_many_sse2 ENDP blake3_hash_many_sse2 ENDP blake3_compress_in_place_sse2 PROC _blake3_compress_in_place_sse2 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 movdqa xmmword ptr [rsp+20H], xmm8 movdqa xmmword ptr [rsp+30H], xmm9 movdqa xmmword ptr [rsp+40H], xmm11 movdqa xmmword ptr [rsp+50H], xmm14 movdqa xmmword ptr [rsp+60H], xmm15 movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm2, xmmword ptr [BLAKE3_IV] movzx eax, byte ptr [rsp+0A0H] movzx r8d, r8b shl rax, 32 add r8, rax movd xmm3, r9 movd xmm4, r8 punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rdx] movups xmm5, xmmword ptr [rdx+10H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rdx+20H] movups xmm7, xmmword ptr [rdx+30H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H mov al, 7 @@: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz @F movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm14, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK] pand xmm14, xmmword ptr [PBLENDW_0xC0_MASK] por xmm8, xmm14 pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp @B @@: pxor xmm0, xmm2 pxor xmm1, xmm3 movups xmmword ptr [rcx], xmm0 movups xmmword ptr [rcx+10H], xmm1 movdqa xmm6, xmmword ptr [rsp] movdqa xmm7, xmmword ptr [rsp+10H] movdqa xmm8, xmmword ptr [rsp+20H] movdqa xmm9, xmmword ptr [rsp+30H] movdqa xmm11, xmmword ptr [rsp+40H] movdqa xmm14, xmmword ptr [rsp+50H] movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret _blake3_compress_in_place_sse2 ENDP blake3_compress_in_place_sse2 ENDP ALIGN 16 blake3_compress_xof_sse2 PROC _blake3_compress_xof_sse2 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 movdqa xmmword ptr [rsp+20H], xmm8 movdqa xmmword ptr [rsp+30H], xmm9 movdqa xmmword ptr [rsp+40H], xmm11 movdqa xmmword ptr [rsp+50H], xmm14 movdqa xmmword ptr [rsp+60H], xmm15 movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm2, xmmword ptr [BLAKE3_IV] movzx eax, byte ptr [rsp+0A0H] movzx r8d, r8b mov r10, qword ptr [rsp+0A8H] shl rax, 32 add r8, rax movd xmm3, r9 movd xmm4, r8 punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rdx] movups xmm5, xmmword ptr [rdx+10H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rdx+20H] movups xmm7, xmmword ptr [rdx+30H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H mov al, 7 @@: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshuflw xmm3, xmm3, 0B1H pshufhw xmm3, xmm3, 0B1H paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 movdqa xmm14, xmm3 psrld xmm3, 8 pslld xmm14, 24 pxor xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz @F movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pand xmm9, xmmword ptr [PBLENDW_0x33_MASK] pand xmm8, xmmword ptr [PBLENDW_0xCC_MASK] por xmm9, xmm8 movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 movdqa xmm14, xmm6 pand xmm8, xmmword ptr [PBLENDW_0x3F_MASK] pand xmm14, xmmword ptr [PBLENDW_0xC0_MASK] por xmm8, xmm14 pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp @B @@: movdqu xmm4, xmmword ptr [rcx] movdqu xmm5, xmmword ptr [rcx+10H] pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm2, xmm4 pxor xmm3, xmm5 movups xmmword ptr [r10], xmm0 movups xmmword ptr [r10+10H], xmm1 movups xmmword ptr [r10+20H], xmm2 movups xmmword ptr [r10+30H], xmm3 movdqa xmm6, xmmword ptr [rsp] movdqa xmm7, xmmword ptr [rsp+10H] movdqa xmm8, xmmword ptr [rsp+20H] movdqa xmm9, xmmword ptr [rsp+30H] movdqa xmm11, xmmword ptr [rsp+40H] movdqa xmm14, xmmword ptr [rsp+50H] movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret _blake3_compress_xof_sse2 ENDP blake3_compress_xof_sse2 ENDP _TEXT ENDS _RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST' ALIGN 64 BLAKE3_IV: dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH ADD0: dd 0, 1, 2, 3 ADD1: dd 4 dup (4) BLAKE3_IV_0: dd 4 dup (6A09E667H) BLAKE3_IV_1: dd 4 dup (0BB67AE85H) BLAKE3_IV_2: dd 4 dup (3C6EF372H) BLAKE3_IV_3: dd 4 dup (0A54FF53AH) BLAKE3_BLOCK_LEN: dd 4 dup (64) CMP_MSB_MASK: dd 8 dup(80000000H) PBLENDW_0x33_MASK: dd 0FFFFFFFFH, 000000000H, 0FFFFFFFFH, 000000000H PBLENDW_0xCC_MASK: dd 000000000H, 0FFFFFFFFH, 000000000H, 0FFFFFFFFH PBLENDW_0x3F_MASK: dd 0FFFFFFFFH, 0FFFFFFFFH, 0FFFFFFFFH, 000000000H PBLENDW_0xC0_MASK: dd 000000000H, 000000000H, 000000000H, 0FFFFFFFFH _RDATA ENDS END ================================================ FILE: src/third_party/blake3/asm/blake3_sse41_x86-64_unix.S ================================================ #if defined(__ELF__) && defined(__linux__) .section .note.GNU-stack,"",%progbits #endif #if defined(__ELF__) && defined(__CET__) && defined(__has_include) #if __has_include() #include #endif #endif #if !defined(_CET_ENDBR) #define _CET_ENDBR #endif .intel_syntax noprefix .global blake3_hash_many_sse41 .global _blake3_hash_many_sse41 .global blake3_compress_in_place_sse41 .global _blake3_compress_in_place_sse41 .global blake3_compress_xof_sse41 .global _blake3_compress_xof_sse41 #ifdef __APPLE__ .text #else .section .text #endif .p2align 6 _blake3_hash_many_sse41: blake3_hash_many_sse41: _CET_ENDBR push r15 push r14 push r13 push r12 push rbx push rbp mov rbp, rsp sub rsp, 360 and rsp, 0xFFFFFFFFFFFFFFC0 neg r9d movd xmm0, r9d pshufd xmm0, xmm0, 0x00 movdqa xmmword ptr [rsp+0x130], xmm0 movdqa xmm1, xmm0 pand xmm1, xmmword ptr [ADD0+rip] pand xmm0, xmmword ptr [ADD1+rip] movdqa xmmword ptr [rsp+0x150], xmm0 movd xmm0, r8d pshufd xmm0, xmm0, 0x00 paddd xmm0, xmm1 movdqa xmmword ptr [rsp+0x110], xmm0 pxor xmm0, xmmword ptr [CMP_MSB_MASK+rip] pxor xmm1, xmmword ptr [CMP_MSB_MASK+rip] pcmpgtd xmm1, xmm0 shr r8, 32 movd xmm2, r8d pshufd xmm2, xmm2, 0x00 psubd xmm2, xmm1 movdqa xmmword ptr [rsp+0x120], xmm2 mov rbx, qword ptr [rbp+0x50] mov r15, rdx shl r15, 6 movzx r13d, byte ptr [rbp+0x38] movzx r12d, byte ptr [rbp+0x48] cmp rsi, 4 jc 3f 2: movdqu xmm3, xmmword ptr [rcx] pshufd xmm0, xmm3, 0x00 pshufd xmm1, xmm3, 0x55 pshufd xmm2, xmm3, 0xAA pshufd xmm3, xmm3, 0xFF movdqu xmm7, xmmword ptr [rcx+0x10] pshufd xmm4, xmm7, 0x00 pshufd xmm5, xmm7, 0x55 pshufd xmm6, xmm7, 0xAA pshufd xmm7, xmm7, 0xFF mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] mov r10, qword ptr [rdi+0x10] mov r11, qword ptr [rdi+0x18] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 9: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movdqu xmm8, xmmword ptr [r8+rdx-0x40] movdqu xmm9, xmmword ptr [r9+rdx-0x40] movdqu xmm10, xmmword ptr [r10+rdx-0x40] movdqu xmm11, xmmword ptr [r11+rdx-0x40] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp], xmm8 movdqa xmmword ptr [rsp+0x10], xmm9 movdqa xmmword ptr [rsp+0x20], xmm12 movdqa xmmword ptr [rsp+0x30], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x30] movdqu xmm9, xmmword ptr [r9+rdx-0x30] movdqu xmm10, xmmword ptr [r10+rdx-0x30] movdqu xmm11, xmmword ptr [r11+rdx-0x30] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0x40], xmm8 movdqa xmmword ptr [rsp+0x50], xmm9 movdqa xmmword ptr [rsp+0x60], xmm12 movdqa xmmword ptr [rsp+0x70], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x20] movdqu xmm9, xmmword ptr [r9+rdx-0x20] movdqu xmm10, xmmword ptr [r10+rdx-0x20] movdqu xmm11, xmmword ptr [r11+rdx-0x20] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0x80], xmm8 movdqa xmmword ptr [rsp+0x90], xmm9 movdqa xmmword ptr [rsp+0xA0], xmm12 movdqa xmmword ptr [rsp+0xB0], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-0x10] movdqu xmm9, xmmword ptr [r9+rdx-0x10] movdqu xmm10, xmmword ptr [r10+rdx-0x10] movdqu xmm11, xmmword ptr [r11+rdx-0x10] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0xC0], xmm8 movdqa xmmword ptr [rsp+0xD0], xmm9 movdqa xmmword ptr [rsp+0xE0], xmm12 movdqa xmmword ptr [rsp+0xF0], xmm13 movdqa xmm9, xmmword ptr [BLAKE3_IV_1+rip] movdqa xmm10, xmmword ptr [BLAKE3_IV_2+rip] movdqa xmm11, xmmword ptr [BLAKE3_IV_3+rip] movdqa xmm12, xmmword ptr [rsp+0x110] movdqa xmm13, xmmword ptr [rsp+0x120] movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN+rip] movd xmm15, eax pshufd xmm15, xmm15, 0x00 prefetcht0 [r8+rdx+0x80] prefetcht0 [r9+rdx+0x80] prefetcht0 [r10+rdx+0x80] prefetcht0 [r11+rdx+0x80] paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x40] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [BLAKE3_IV_0+rip] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x10] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x50] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x80] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0xC0] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x90] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0xD0] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x20] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x70] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x60] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x10] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x90] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xB0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0xE0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x30] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0xD0] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x40] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x20] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x60] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0xB0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x50] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0xF0] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xA0] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0xE0] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x70] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0x30] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x40] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0x50] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x80] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xC0] paddd xmm1, xmmword ptr [rsp+0x90] paddd xmm2, xmmword ptr [rsp+0xF0] paddd xmm3, xmmword ptr [rsp+0xE0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xD0] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0xA0] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0x70] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x20] paddd xmm1, xmmword ptr [rsp+0x30] paddd xmm2, xmmword ptr [rsp+0x10] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x90] paddd xmm1, xmmword ptr [rsp+0xB0] paddd xmm2, xmmword ptr [rsp+0x80] paddd xmm3, xmmword ptr [rsp+0xF0] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xE0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0xC0] paddd xmm3, xmmword ptr [rsp+0x10] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xD0] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0x20] paddd xmm3, xmmword ptr [rsp+0x40] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0x30] paddd xmm1, xmmword ptr [rsp+0xA0] paddd xmm2, xmmword ptr [rsp+0x60] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xB0] paddd xmm1, xmmword ptr [rsp+0x50] paddd xmm2, xmmword ptr [rsp+0x10] paddd xmm3, xmmword ptr [rsp+0x80] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xF0] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0x90] paddd xmm3, xmmword ptr [rsp+0x60] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0xE0] paddd xmm1, xmmword ptr [rsp+0x20] paddd xmm2, xmmword ptr [rsp+0x30] paddd xmm3, xmmword ptr [rsp+0x70] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+0x100], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0xA0] paddd xmm1, xmmword ptr [rsp+0xC0] paddd xmm2, xmmword ptr [rsp+0x40] paddd xmm3, xmmword ptr [rsp+0xD0] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8+rip] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+0x100] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 pxor xmm0, xmm8 pxor xmm1, xmm9 pxor xmm2, xmm10 pxor xmm3, xmm11 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 mov eax, r13d jne 9b movdqa xmm9, xmm0 punpckldq xmm0, xmm1 punpckhdq xmm9, xmm1 movdqa xmm11, xmm2 punpckldq xmm2, xmm3 punpckhdq xmm11, xmm3 movdqa xmm1, xmm0 punpcklqdq xmm0, xmm2 punpckhqdq xmm1, xmm2 movdqa xmm3, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm3, xmm11 movdqu xmmword ptr [rbx], xmm0 movdqu xmmword ptr [rbx+0x20], xmm1 movdqu xmmword ptr [rbx+0x40], xmm9 movdqu xmmword ptr [rbx+0x60], xmm3 movdqa xmm9, xmm4 punpckldq xmm4, xmm5 punpckhdq xmm9, xmm5 movdqa xmm11, xmm6 punpckldq xmm6, xmm7 punpckhdq xmm11, xmm7 movdqa xmm5, xmm4 punpcklqdq xmm4, xmm6 punpckhqdq xmm5, xmm6 movdqa xmm7, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm7, xmm11 movdqu xmmword ptr [rbx+0x10], xmm4 movdqu xmmword ptr [rbx+0x30], xmm5 movdqu xmmword ptr [rbx+0x50], xmm9 movdqu xmmword ptr [rbx+0x70], xmm7 movdqa xmm1, xmmword ptr [rsp+0x110] movdqa xmm0, xmm1 paddd xmm1, xmmword ptr [rsp+0x150] movdqa xmmword ptr [rsp+0x110], xmm1 pxor xmm0, xmmword ptr [CMP_MSB_MASK+rip] pxor xmm1, xmmword ptr [CMP_MSB_MASK+rip] pcmpgtd xmm0, xmm1 movdqa xmm1, xmmword ptr [rsp+0x120] psubd xmm1, xmm0 movdqa xmmword ptr [rsp+0x120], xmm1 add rbx, 128 add rdi, 32 sub rsi, 4 cmp rsi, 4 jnc 2b test rsi, rsi jnz 3f 4: mov rsp, rbp pop rbp pop rbx pop r12 pop r13 pop r14 pop r15 ret .p2align 5 3: test esi, 0x2 je 3f movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+0x10] movaps xmm8, xmm0 movaps xmm9, xmm1 movd xmm13, dword ptr [rsp+0x110] pinsrd xmm13, dword ptr [rsp+0x120], 1 pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 movaps xmmword ptr [rsp], xmm13 movd xmm14, dword ptr [rsp+0x114] pinsrd xmm14, dword ptr [rsp+0x124], 1 pinsrd xmm14, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 movaps xmmword ptr [rsp+0x10], xmm14 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+0x8] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV+rip] movaps xmm10, xmm2 movups xmm4, xmmword ptr [r8+rdx-0x40] movups xmm5, xmmword ptr [r8+rdx-0x30] movaps xmm3, xmm4 shufps xmm4, xmm5, 136 shufps xmm3, xmm5, 221 movaps xmm5, xmm3 movups xmm6, xmmword ptr [r8+rdx-0x20] movups xmm7, xmmword ptr [r8+rdx-0x10] movaps xmm3, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm3, xmm7, 221 pshufd xmm7, xmm3, 0x93 movups xmm12, xmmword ptr [r9+rdx-0x40] movups xmm13, xmmword ptr [r9+rdx-0x30] movaps xmm11, xmm12 shufps xmm12, xmm13, 136 shufps xmm11, xmm13, 221 movaps xmm13, xmm11 movups xmm14, xmmword ptr [r9+rdx-0x20] movups xmm15, xmmword ptr [r9+rdx-0x10] movaps xmm11, xmm14 shufps xmm14, xmm15, 136 pshufd xmm14, xmm14, 0x93 shufps xmm11, xmm15, 221 pshufd xmm15, xmm11, 0x93 movaps xmm3, xmmword ptr [rsp] movaps xmm11, xmmword ptr [rsp+0x10] pinsrd xmm3, eax, 3 pinsrd xmm11, eax, 3 mov al, 7 9: paddd xmm0, xmm4 paddd xmm8, xmm12 movaps xmmword ptr [rsp+0x20], xmm4 movaps xmmword ptr [rsp+0x30], xmm12 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movaps xmm12, xmmword ptr [ROT16+rip] pshufb xmm3, xmm12 pshufb xmm11, xmm12 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm5 paddd xmm8, xmm13 movaps xmmword ptr [rsp+0x40], xmm5 movaps xmmword ptr [rsp+0x50], xmm13 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movaps xmm13, xmmword ptr [ROT8+rip] pshufb xmm3, xmm13 pshufb xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 0x93 pshufd xmm8, xmm8, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm11, xmm11, 0x4E pshufd xmm2, xmm2, 0x39 pshufd xmm10, xmm10, 0x39 paddd xmm0, xmm6 paddd xmm8, xmm14 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshufb xmm3, xmm12 pshufb xmm11, xmm12 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm7 paddd xmm8, xmm15 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshufb xmm3, xmm13 pshufb xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 0x39 pshufd xmm8, xmm8, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm11, xmm11, 0x4E pshufd xmm2, xmm2, 0x93 pshufd xmm10, xmm10, 0x93 dec al je 9f movdqa xmm12, xmmword ptr [rsp+0x20] movdqa xmm5, xmmword ptr [rsp+0x40] pshufd xmm13, xmm12, 0x0F shufps xmm12, xmm5, 214 pshufd xmm4, xmm12, 0x39 movdqa xmm12, xmm6 shufps xmm12, xmm7, 250 pblendw xmm13, xmm12, 0xCC movdqa xmm12, xmm7 punpcklqdq xmm12, xmm5 pblendw xmm12, xmm6, 0xC0 pshufd xmm12, xmm12, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmmword ptr [rsp+0x20], xmm13 movdqa xmmword ptr [rsp+0x40], xmm12 movdqa xmm5, xmmword ptr [rsp+0x30] movdqa xmm13, xmmword ptr [rsp+0x50] pshufd xmm6, xmm5, 0x0F shufps xmm5, xmm13, 214 pshufd xmm12, xmm5, 0x39 movdqa xmm5, xmm14 shufps xmm5, xmm15, 250 pblendw xmm6, xmm5, 0xCC movdqa xmm5, xmm15 punpcklqdq xmm5, xmm13 pblendw xmm5, xmm14, 0xC0 pshufd xmm5, xmm5, 0x78 punpckhdq xmm13, xmm15 punpckldq xmm14, xmm13 pshufd xmm15, xmm14, 0x1E movdqa xmm13, xmm6 movdqa xmm14, xmm5 movdqa xmm5, xmmword ptr [rsp+0x20] movdqa xmm6, xmmword ptr [rsp+0x40] jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm8, xmm10 pxor xmm9, xmm11 mov eax, r13d cmp rdx, r15 jne 2b movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+0x10], xmm1 movups xmmword ptr [rbx+0x20], xmm8 movups xmmword ptr [rbx+0x30], xmm9 movdqa xmm0, xmmword ptr [rsp+0x130] movdqa xmm1, xmmword ptr [rsp+0x110] movdqa xmm2, xmmword ptr [rsp+0x120] movdqu xmm3, xmmword ptr [rsp+0x118] movdqu xmm4, xmmword ptr [rsp+0x128] blendvps xmm1, xmm3, xmm0 blendvps xmm2, xmm4, xmm0 movdqa xmmword ptr [rsp+0x110], xmm1 movdqa xmmword ptr [rsp+0x120], xmm2 add rdi, 16 add rbx, 64 sub rsi, 2 3: test esi, 0x1 je 4b movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+0x10] movd xmm13, dword ptr [rsp+0x110] pinsrd xmm13, dword ptr [rsp+0x120], 1 pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN+rip], 2 movaps xmm14, xmmword ptr [ROT8+rip] movaps xmm15, xmmword ptr [ROT16+rip] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+0x40] or eax, r13d xor edx, edx 2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV+rip] movaps xmm3, xmm13 pinsrd xmm3, eax, 3 movups xmm4, xmmword ptr [r8+rdx-0x40] movups xmm5, xmmword ptr [r8+rdx-0x30] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [r8+rdx-0x20] movups xmm7, xmmword ptr [r8+rdx-0x10] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0xCC movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0xC0 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne 2b movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+0x10], xmm1 jmp 4b .p2align 6 blake3_compress_in_place_sse41: _blake3_compress_in_place_sse41: _CET_ENDBR movups xmm0, xmmword ptr [rdi] movups xmm1, xmmword ptr [rdi+0x10] movaps xmm2, xmmword ptr [BLAKE3_IV+rip] shl r8, 32 add rdx, r8 movq xmm3, rcx movq xmm4, rdx punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rsi] movups xmm5, xmmword ptr [rsi+0x10] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rsi+0x20] movups xmm7, xmmword ptr [rsi+0x30] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 movaps xmm14, xmmword ptr [ROT8+rip] movaps xmm15, xmmword ptr [ROT16+rip] mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0xCC movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0xC0 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: pxor xmm0, xmm2 pxor xmm1, xmm3 movups xmmword ptr [rdi], xmm0 movups xmmword ptr [rdi+0x10], xmm1 ret .p2align 6 blake3_compress_xof_sse41: _blake3_compress_xof_sse41: _CET_ENDBR movups xmm0, xmmword ptr [rdi] movups xmm1, xmmword ptr [rdi+0x10] movaps xmm2, xmmword ptr [BLAKE3_IV+rip] movzx eax, r8b movzx edx, dl shl rax, 32 add rdx, rax movq xmm3, rcx movq xmm4, rdx punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rsi] movups xmm5, xmmword ptr [rsi+0x10] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rsi+0x20] movups xmm7, xmmword ptr [rsi+0x30] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 0x93 shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 0x93 movaps xmm14, xmmword ptr [ROT8+rip] movaps xmm15, xmmword ptr [ROT16+rip] mov al, 7 9: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x93 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x39 paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 0x39 pshufd xmm3, xmm3, 0x4E pshufd xmm2, xmm2, 0x93 dec al jz 9f movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0x0F pshufd xmm4, xmm8, 0x39 movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0xCC movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0xC0 pshufd xmm8, xmm8, 0x78 punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 0x1E movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp 9b 9: movdqu xmm4, xmmword ptr [rdi] movdqu xmm5, xmmword ptr [rdi+0x10] pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm2, xmm4 pxor xmm3, xmm5 movups xmmword ptr [r9], xmm0 movups xmmword ptr [r9+0x10], xmm1 movups xmmword ptr [r9+0x20], xmm2 movups xmmword ptr [r9+0x30], xmm3 ret #ifdef __APPLE__ .static_data #else .section .rodata #endif .p2align 6 BLAKE3_IV: .long 0x6A09E667, 0xBB67AE85 .long 0x3C6EF372, 0xA54FF53A ROT16: .byte 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 ROT8: .byte 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 ADD0: .long 0, 1, 2, 3 ADD1: .long 4, 4, 4, 4 BLAKE3_IV_0: .long 0x6A09E667, 0x6A09E667, 0x6A09E667, 0x6A09E667 BLAKE3_IV_1: .long 0xBB67AE85, 0xBB67AE85, 0xBB67AE85, 0xBB67AE85 BLAKE3_IV_2: .long 0x3C6EF372, 0x3C6EF372, 0x3C6EF372, 0x3C6EF372 BLAKE3_IV_3: .long 0xA54FF53A, 0xA54FF53A, 0xA54FF53A, 0xA54FF53A BLAKE3_BLOCK_LEN: .long 64, 64, 64, 64 CMP_MSB_MASK: .long 0x80000000, 0x80000000, 0x80000000, 0x80000000 ================================================ FILE: src/third_party/blake3/asm/blake3_sse41_x86-64_windows_msvc.asm ================================================ public _blake3_hash_many_sse41 public blake3_hash_many_sse41 public blake3_compress_in_place_sse41 public _blake3_compress_in_place_sse41 public blake3_compress_xof_sse41 public _blake3_compress_xof_sse41 _TEXT SEGMENT ALIGN(16) 'CODE' ALIGN 16 blake3_hash_many_sse41 PROC _blake3_hash_many_sse41 PROC push r15 push r14 push r13 push r12 push rsi push rdi push rbx push rbp mov rbp, rsp sub rsp, 528 and rsp, 0FFFFFFFFFFFFFFC0H movdqa xmmword ptr [rsp+170H], xmm6 movdqa xmmword ptr [rsp+180H], xmm7 movdqa xmmword ptr [rsp+190H], xmm8 movdqa xmmword ptr [rsp+1A0H], xmm9 movdqa xmmword ptr [rsp+1B0H], xmm10 movdqa xmmword ptr [rsp+1C0H], xmm11 movdqa xmmword ptr [rsp+1D0H], xmm12 movdqa xmmword ptr [rsp+1E0H], xmm13 movdqa xmmword ptr [rsp+1F0H], xmm14 movdqa xmmword ptr [rsp+200H], xmm15 mov rdi, rcx mov rsi, rdx mov rdx, r8 mov rcx, r9 mov r8, qword ptr [rbp+68H] movzx r9, byte ptr [rbp+70H] neg r9d movd xmm0, r9d pshufd xmm0, xmm0, 00H movdqa xmmword ptr [rsp+130H], xmm0 movdqa xmm1, xmm0 pand xmm1, xmmword ptr [ADD0] pand xmm0, xmmword ptr [ADD1] movdqa xmmword ptr [rsp+150H], xmm0 movd xmm0, r8d pshufd xmm0, xmm0, 00H paddd xmm0, xmm1 movdqa xmmword ptr [rsp+110H], xmm0 pxor xmm0, xmmword ptr [CMP_MSB_MASK] pxor xmm1, xmmword ptr [CMP_MSB_MASK] pcmpgtd xmm1, xmm0 shr r8, 32 movd xmm2, r8d pshufd xmm2, xmm2, 00H psubd xmm2, xmm1 movdqa xmmword ptr [rsp+120H], xmm2 mov rbx, qword ptr [rbp+90H] mov r15, rdx shl r15, 6 movzx r13d, byte ptr [rbp+78H] movzx r12d, byte ptr [rbp+88H] cmp rsi, 4 jc final3blocks outerloop4: movdqu xmm3, xmmword ptr [rcx] pshufd xmm0, xmm3, 00H pshufd xmm1, xmm3, 55H pshufd xmm2, xmm3, 0AAH pshufd xmm3, xmm3, 0FFH movdqu xmm7, xmmword ptr [rcx+10H] pshufd xmm4, xmm7, 00H pshufd xmm5, xmm7, 55H pshufd xmm6, xmm7, 0AAH pshufd xmm7, xmm7, 0FFH mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] mov r10, qword ptr [rdi+10H] mov r11, qword ptr [rdi+18H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop4: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movdqu xmm8, xmmword ptr [r8+rdx-40H] movdqu xmm9, xmmword ptr [r9+rdx-40H] movdqu xmm10, xmmword ptr [r10+rdx-40H] movdqu xmm11, xmmword ptr [r11+rdx-40H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp], xmm8 movdqa xmmword ptr [rsp+10H], xmm9 movdqa xmmword ptr [rsp+20H], xmm12 movdqa xmmword ptr [rsp+30H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-30H] movdqu xmm9, xmmword ptr [r9+rdx-30H] movdqu xmm10, xmmword ptr [r10+rdx-30H] movdqu xmm11, xmmword ptr [r11+rdx-30H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+40H], xmm8 movdqa xmmword ptr [rsp+50H], xmm9 movdqa xmmword ptr [rsp+60H], xmm12 movdqa xmmword ptr [rsp+70H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-20H] movdqu xmm9, xmmword ptr [r9+rdx-20H] movdqu xmm10, xmmword ptr [r10+rdx-20H] movdqu xmm11, xmmword ptr [r11+rdx-20H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+80H], xmm8 movdqa xmmword ptr [rsp+90H], xmm9 movdqa xmmword ptr [rsp+0A0H], xmm12 movdqa xmmword ptr [rsp+0B0H], xmm13 movdqu xmm8, xmmword ptr [r8+rdx-10H] movdqu xmm9, xmmword ptr [r9+rdx-10H] movdqu xmm10, xmmword ptr [r10+rdx-10H] movdqu xmm11, xmmword ptr [r11+rdx-10H] movdqa xmm12, xmm8 punpckldq xmm8, xmm9 punpckhdq xmm12, xmm9 movdqa xmm14, xmm10 punpckldq xmm10, xmm11 punpckhdq xmm14, xmm11 movdqa xmm9, xmm8 punpcklqdq xmm8, xmm10 punpckhqdq xmm9, xmm10 movdqa xmm13, xmm12 punpcklqdq xmm12, xmm14 punpckhqdq xmm13, xmm14 movdqa xmmword ptr [rsp+0C0H], xmm8 movdqa xmmword ptr [rsp+0D0H], xmm9 movdqa xmmword ptr [rsp+0E0H], xmm12 movdqa xmmword ptr [rsp+0F0H], xmm13 movdqa xmm9, xmmword ptr [BLAKE3_IV_1] movdqa xmm10, xmmword ptr [BLAKE3_IV_2] movdqa xmm11, xmmword ptr [BLAKE3_IV_3] movdqa xmm12, xmmword ptr [rsp+110H] movdqa xmm13, xmmword ptr [rsp+120H] movdqa xmm14, xmmword ptr [BLAKE3_BLOCK_LEN] movd xmm15, eax pshufd xmm15, xmm15, 00H prefetcht0 byte ptr [r8+rdx+80H] prefetcht0 byte ptr [r9+rdx+80H] prefetcht0 byte ptr [r10+rdx+80H] prefetcht0 byte ptr [r11+rdx+80H] paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+40H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [BLAKE3_IV_0] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+10H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+50H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+80H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+0C0H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+90H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+0D0H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+20H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+70H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+60H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+10H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+90H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0B0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+0E0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+30H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+0D0H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+40H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+20H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+60H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+0B0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+50H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+0F0H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0A0H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+0E0H] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+70H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+30H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+40H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+50H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+80H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0C0H] paddd xmm1, xmmword ptr [rsp+90H] paddd xmm2, xmmword ptr [rsp+0F0H] paddd xmm3, xmmword ptr [rsp+0E0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0D0H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+0A0H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+70H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+20H] paddd xmm1, xmmword ptr [rsp+30H] paddd xmm2, xmmword ptr [rsp+10H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+90H] paddd xmm1, xmmword ptr [rsp+0B0H] paddd xmm2, xmmword ptr [rsp+80H] paddd xmm3, xmmword ptr [rsp+0F0H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0E0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+0C0H] paddd xmm3, xmmword ptr [rsp+10H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0D0H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+20H] paddd xmm3, xmmword ptr [rsp+40H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+30H] paddd xmm1, xmmword ptr [rsp+0A0H] paddd xmm2, xmmword ptr [rsp+60H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0B0H] paddd xmm1, xmmword ptr [rsp+50H] paddd xmm2, xmmword ptr [rsp+10H] paddd xmm3, xmmword ptr [rsp+80H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0F0H] paddd xmm1, xmmword ptr [rsp] paddd xmm2, xmmword ptr [rsp+90H] paddd xmm3, xmmword ptr [rsp+60H] paddd xmm0, xmm4 paddd xmm1, xmm5 paddd xmm2, xmm6 paddd xmm3, xmm7 pxor xmm12, xmm0 pxor xmm13, xmm1 pxor xmm14, xmm2 pxor xmm15, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 pshufb xmm15, xmm8 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm12 paddd xmm9, xmm13 paddd xmm10, xmm14 paddd xmm11, xmm15 pxor xmm4, xmm8 pxor xmm5, xmm9 pxor xmm6, xmm10 pxor xmm7, xmm11 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 paddd xmm0, xmmword ptr [rsp+0E0H] paddd xmm1, xmmword ptr [rsp+20H] paddd xmm2, xmmword ptr [rsp+30H] paddd xmm3, xmmword ptr [rsp+70H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT16] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 movdqa xmmword ptr [rsp+100H], xmm8 movdqa xmm8, xmm5 psrld xmm8, 12 pslld xmm5, 20 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 12 pslld xmm6, 20 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 12 pslld xmm7, 20 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 12 pslld xmm4, 20 por xmm4, xmm8 paddd xmm0, xmmword ptr [rsp+0A0H] paddd xmm1, xmmword ptr [rsp+0C0H] paddd xmm2, xmmword ptr [rsp+40H] paddd xmm3, xmmword ptr [rsp+0D0H] paddd xmm0, xmm5 paddd xmm1, xmm6 paddd xmm2, xmm7 paddd xmm3, xmm4 pxor xmm15, xmm0 pxor xmm12, xmm1 pxor xmm13, xmm2 pxor xmm14, xmm3 movdqa xmm8, xmmword ptr [ROT8] pshufb xmm15, xmm8 pshufb xmm12, xmm8 pshufb xmm13, xmm8 pshufb xmm14, xmm8 paddd xmm10, xmm15 paddd xmm11, xmm12 movdqa xmm8, xmmword ptr [rsp+100H] paddd xmm8, xmm13 paddd xmm9, xmm14 pxor xmm5, xmm10 pxor xmm6, xmm11 pxor xmm7, xmm8 pxor xmm4, xmm9 pxor xmm0, xmm8 pxor xmm1, xmm9 pxor xmm2, xmm10 pxor xmm3, xmm11 movdqa xmm8, xmm5 psrld xmm8, 7 pslld xmm5, 25 por xmm5, xmm8 movdqa xmm8, xmm6 psrld xmm8, 7 pslld xmm6, 25 por xmm6, xmm8 movdqa xmm8, xmm7 psrld xmm8, 7 pslld xmm7, 25 por xmm7, xmm8 movdqa xmm8, xmm4 psrld xmm8, 7 pslld xmm4, 25 por xmm4, xmm8 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 mov eax, r13d jne innerloop4 movdqa xmm9, xmm0 punpckldq xmm0, xmm1 punpckhdq xmm9, xmm1 movdqa xmm11, xmm2 punpckldq xmm2, xmm3 punpckhdq xmm11, xmm3 movdqa xmm1, xmm0 punpcklqdq xmm0, xmm2 punpckhqdq xmm1, xmm2 movdqa xmm3, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm3, xmm11 movdqu xmmword ptr [rbx], xmm0 movdqu xmmword ptr [rbx+20H], xmm1 movdqu xmmword ptr [rbx+40H], xmm9 movdqu xmmword ptr [rbx+60H], xmm3 movdqa xmm9, xmm4 punpckldq xmm4, xmm5 punpckhdq xmm9, xmm5 movdqa xmm11, xmm6 punpckldq xmm6, xmm7 punpckhdq xmm11, xmm7 movdqa xmm5, xmm4 punpcklqdq xmm4, xmm6 punpckhqdq xmm5, xmm6 movdqa xmm7, xmm9 punpcklqdq xmm9, xmm11 punpckhqdq xmm7, xmm11 movdqu xmmword ptr [rbx+10H], xmm4 movdqu xmmword ptr [rbx+30H], xmm5 movdqu xmmword ptr [rbx+50H], xmm9 movdqu xmmword ptr [rbx+70H], xmm7 movdqa xmm1, xmmword ptr [rsp+110H] movdqa xmm0, xmm1 paddd xmm1, xmmword ptr [rsp+150H] movdqa xmmword ptr [rsp+110H], xmm1 pxor xmm0, xmmword ptr [CMP_MSB_MASK] pxor xmm1, xmmword ptr [CMP_MSB_MASK] pcmpgtd xmm0, xmm1 movdqa xmm1, xmmword ptr [rsp+120H] psubd xmm1, xmm0 movdqa xmmword ptr [rsp+120H], xmm1 add rbx, 128 add rdi, 32 sub rsi, 4 cmp rsi, 4 jnc outerloop4 test rsi, rsi jne final3blocks unwind: movdqa xmm6, xmmword ptr [rsp+170H] movdqa xmm7, xmmword ptr [rsp+180H] movdqa xmm8, xmmword ptr [rsp+190H] movdqa xmm9, xmmword ptr [rsp+1A0H] movdqa xmm10, xmmword ptr [rsp+1B0H] movdqa xmm11, xmmword ptr [rsp+1C0H] movdqa xmm12, xmmword ptr [rsp+1D0H] movdqa xmm13, xmmword ptr [rsp+1E0H] movdqa xmm14, xmmword ptr [rsp+1F0H] movdqa xmm15, xmmword ptr [rsp+200H] mov rsp, rbp pop rbp pop rbx pop rdi pop rsi pop r12 pop r13 pop r14 pop r15 ret ALIGN 16 final3blocks: test esi, 2H je final1block movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm8, xmm0 movaps xmm9, xmm1 movd xmm13, dword ptr [rsp+110H] pinsrd xmm13, dword ptr [rsp+120H], 1 pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2 movaps xmmword ptr [rsp], xmm13 movd xmm14, dword ptr [rsp+114H] pinsrd xmm14, dword ptr [rsp+124H], 1 pinsrd xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2 movaps xmmword ptr [rsp+10H], xmm14 mov r8, qword ptr [rdi] mov r9, qword ptr [rdi+8H] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop2: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV] movaps xmm10, xmm2 movups xmm4, xmmword ptr [r8+rdx-40H] movups xmm5, xmmword ptr [r8+rdx-30H] movaps xmm3, xmm4 shufps xmm4, xmm5, 136 shufps xmm3, xmm5, 221 movaps xmm5, xmm3 movups xmm6, xmmword ptr [r8+rdx-20H] movups xmm7, xmmword ptr [r8+rdx-10H] movaps xmm3, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm3, xmm7, 221 pshufd xmm7, xmm3, 93H movups xmm12, xmmword ptr [r9+rdx-40H] movups xmm13, xmmword ptr [r9+rdx-30H] movaps xmm11, xmm12 shufps xmm12, xmm13, 136 shufps xmm11, xmm13, 221 movaps xmm13, xmm11 movups xmm14, xmmword ptr [r9+rdx-20H] movups xmm15, xmmword ptr [r9+rdx-10H] movaps xmm11, xmm14 shufps xmm14, xmm15, 136 pshufd xmm14, xmm14, 93H shufps xmm11, xmm15, 221 pshufd xmm15, xmm11, 93H movaps xmm3, xmmword ptr [rsp] movaps xmm11, xmmword ptr [rsp+10H] pinsrd xmm3, eax, 3 pinsrd xmm11, eax, 3 mov al, 7 roundloop2: paddd xmm0, xmm4 paddd xmm8, xmm12 movaps xmmword ptr [rsp+20H], xmm4 movaps xmmword ptr [rsp+30H], xmm12 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movaps xmm12, xmmword ptr [ROT16] pshufb xmm3, xmm12 pshufb xmm11, xmm12 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm5 paddd xmm8, xmm13 movaps xmmword ptr [rsp+40H], xmm5 movaps xmmword ptr [rsp+50H], xmm13 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 movaps xmm13, xmmword ptr [ROT8] pshufb xmm3, xmm13 pshufb xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 93H pshufd xmm8, xmm8, 93H pshufd xmm3, xmm3, 4EH pshufd xmm11, xmm11, 4EH pshufd xmm2, xmm2, 39H pshufd xmm10, xmm10, 39H paddd xmm0, xmm6 paddd xmm8, xmm14 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshufb xmm3, xmm12 pshufb xmm11, xmm12 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 20 psrld xmm4, 12 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 20 psrld xmm4, 12 por xmm9, xmm4 paddd xmm0, xmm7 paddd xmm8, xmm15 paddd xmm0, xmm1 paddd xmm8, xmm9 pxor xmm3, xmm0 pxor xmm11, xmm8 pshufb xmm3, xmm13 pshufb xmm11, xmm13 paddd xmm2, xmm3 paddd xmm10, xmm11 pxor xmm1, xmm2 pxor xmm9, xmm10 movdqa xmm4, xmm1 pslld xmm1, 25 psrld xmm4, 7 por xmm1, xmm4 movdqa xmm4, xmm9 pslld xmm9, 25 psrld xmm4, 7 por xmm9, xmm4 pshufd xmm0, xmm0, 39H pshufd xmm8, xmm8, 39H pshufd xmm3, xmm3, 4EH pshufd xmm11, xmm11, 4EH pshufd xmm2, xmm2, 93H pshufd xmm10, xmm10, 93H dec al je endroundloop2 movdqa xmm12, xmmword ptr [rsp+20H] movdqa xmm5, xmmword ptr [rsp+40H] pshufd xmm13, xmm12, 0FH shufps xmm12, xmm5, 214 pshufd xmm4, xmm12, 39H movdqa xmm12, xmm6 shufps xmm12, xmm7, 250 pblendw xmm13, xmm12, 0CCH movdqa xmm12, xmm7 punpcklqdq xmm12, xmm5 pblendw xmm12, xmm6, 0C0H pshufd xmm12, xmm12, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmmword ptr [rsp+20H], xmm13 movdqa xmmword ptr [rsp+40H], xmm12 movdqa xmm5, xmmword ptr [rsp+30H] movdqa xmm13, xmmword ptr [rsp+50H] pshufd xmm6, xmm5, 0FH shufps xmm5, xmm13, 214 pshufd xmm12, xmm5, 39H movdqa xmm5, xmm14 shufps xmm5, xmm15, 250 pblendw xmm6, xmm5, 0CCH movdqa xmm5, xmm15 punpcklqdq xmm5, xmm13 pblendw xmm5, xmm14, 0C0H pshufd xmm5, xmm5, 78H punpckhdq xmm13, xmm15 punpckldq xmm14, xmm13 pshufd xmm15, xmm14, 1EH movdqa xmm13, xmm6 movdqa xmm14, xmm5 movdqa xmm5, xmmword ptr [rsp+20H] movdqa xmm6, xmmword ptr [rsp+40H] jmp roundloop2 endroundloop2: pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm8, xmm10 pxor xmm9, xmm11 mov eax, r13d cmp rdx, r15 jne innerloop2 movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 movups xmmword ptr [rbx+20H], xmm8 movups xmmword ptr [rbx+30H], xmm9 movdqa xmm0, xmmword ptr [rsp+130H] movdqa xmm1, xmmword ptr [rsp+110H] movdqa xmm2, xmmword ptr [rsp+120H] movdqu xmm3, xmmword ptr [rsp+118H] movdqu xmm4, xmmword ptr [rsp+128H] blendvps xmm1, xmm3, xmm0 blendvps xmm2, xmm4, xmm0 movdqa xmmword ptr [rsp+110H], xmm1 movdqa xmmword ptr [rsp+120H], xmm2 add rdi, 16 add rbx, 64 sub rsi, 2 final1block: test esi, 1H je unwind movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movd xmm13, dword ptr [rsp+110H] pinsrd xmm13, dword ptr [rsp+120H], 1 pinsrd xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2 movaps xmm14, xmmword ptr [ROT8] movaps xmm15, xmmword ptr [ROT16] mov r8, qword ptr [rdi] movzx eax, byte ptr [rbp+80H] or eax, r13d xor edx, edx innerloop1: mov r14d, eax or eax, r12d add rdx, 64 cmp rdx, r15 cmovne eax, r14d movaps xmm2, xmmword ptr [BLAKE3_IV] movaps xmm3, xmm13 pinsrd xmm3, eax, 3 movups xmm4, xmmword ptr [r8+rdx-40H] movups xmm5, xmmword ptr [r8+rdx-30H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [r8+rdx-20H] movups xmm7, xmmword ptr [r8+rdx-10H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H mov al, 7 roundloop1: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz endroundloop1 movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0CCH movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0C0H pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp roundloop1 endroundloop1: pxor xmm0, xmm2 pxor xmm1, xmm3 mov eax, r13d cmp rdx, r15 jne innerloop1 movups xmmword ptr [rbx], xmm0 movups xmmword ptr [rbx+10H], xmm1 jmp unwind _blake3_hash_many_sse41 ENDP blake3_hash_many_sse41 ENDP blake3_compress_in_place_sse41 PROC _blake3_compress_in_place_sse41 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 movdqa xmmword ptr [rsp+20H], xmm8 movdqa xmmword ptr [rsp+30H], xmm9 movdqa xmmword ptr [rsp+40H], xmm11 movdqa xmmword ptr [rsp+50H], xmm14 movdqa xmmword ptr [rsp+60H], xmm15 movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm2, xmmword ptr [BLAKE3_IV] movzx eax, byte ptr [rsp+0A0H] movzx r8d, r8b shl rax, 32 add r8, rax movd xmm3, r9 movd xmm4, r8 punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rdx] movups xmm5, xmmword ptr [rdx+10H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rdx+20H] movups xmm7, xmmword ptr [rdx+30H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H movaps xmm14, xmmword ptr [ROT8] movaps xmm15, xmmword ptr [ROT16] mov al, 7 @@: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz @F movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0CCH movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0C0H pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp @B @@: pxor xmm0, xmm2 pxor xmm1, xmm3 movups xmmword ptr [rcx], xmm0 movups xmmword ptr [rcx+10H], xmm1 movdqa xmm6, xmmword ptr [rsp] movdqa xmm7, xmmword ptr [rsp+10H] movdqa xmm8, xmmword ptr [rsp+20H] movdqa xmm9, xmmword ptr [rsp+30H] movdqa xmm11, xmmword ptr [rsp+40H] movdqa xmm14, xmmword ptr [rsp+50H] movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret _blake3_compress_in_place_sse41 ENDP blake3_compress_in_place_sse41 ENDP ALIGN 16 blake3_compress_xof_sse41 PROC _blake3_compress_xof_sse41 PROC sub rsp, 120 movdqa xmmword ptr [rsp], xmm6 movdqa xmmword ptr [rsp+10H], xmm7 movdqa xmmword ptr [rsp+20H], xmm8 movdqa xmmword ptr [rsp+30H], xmm9 movdqa xmmword ptr [rsp+40H], xmm11 movdqa xmmword ptr [rsp+50H], xmm14 movdqa xmmword ptr [rsp+60H], xmm15 movups xmm0, xmmword ptr [rcx] movups xmm1, xmmword ptr [rcx+10H] movaps xmm2, xmmword ptr [BLAKE3_IV] movzx eax, byte ptr [rsp+0A0H] movzx r8d, r8b mov r10, qword ptr [rsp+0A8H] shl rax, 32 add r8, rax movd xmm3, r9 movd xmm4, r8 punpcklqdq xmm3, xmm4 movups xmm4, xmmword ptr [rdx] movups xmm5, xmmword ptr [rdx+10H] movaps xmm8, xmm4 shufps xmm4, xmm5, 136 shufps xmm8, xmm5, 221 movaps xmm5, xmm8 movups xmm6, xmmword ptr [rdx+20H] movups xmm7, xmmword ptr [rdx+30H] movaps xmm8, xmm6 shufps xmm6, xmm7, 136 pshufd xmm6, xmm6, 93H shufps xmm8, xmm7, 221 pshufd xmm7, xmm8, 93H movaps xmm14, xmmword ptr [ROT8] movaps xmm15, xmmword ptr [ROT16] mov al, 7 @@: paddd xmm0, xmm4 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm5 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 93H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 39H paddd xmm0, xmm6 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm15 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 20 psrld xmm11, 12 por xmm1, xmm11 paddd xmm0, xmm7 paddd xmm0, xmm1 pxor xmm3, xmm0 pshufb xmm3, xmm14 paddd xmm2, xmm3 pxor xmm1, xmm2 movdqa xmm11, xmm1 pslld xmm1, 25 psrld xmm11, 7 por xmm1, xmm11 pshufd xmm0, xmm0, 39H pshufd xmm3, xmm3, 4EH pshufd xmm2, xmm2, 93H dec al jz @F movdqa xmm8, xmm4 shufps xmm8, xmm5, 214 pshufd xmm9, xmm4, 0FH pshufd xmm4, xmm8, 39H movdqa xmm8, xmm6 shufps xmm8, xmm7, 250 pblendw xmm9, xmm8, 0CCH movdqa xmm8, xmm7 punpcklqdq xmm8, xmm5 pblendw xmm8, xmm6, 0C0H pshufd xmm8, xmm8, 78H punpckhdq xmm5, xmm7 punpckldq xmm6, xmm5 pshufd xmm7, xmm6, 1EH movdqa xmm5, xmm9 movdqa xmm6, xmm8 jmp @B @@: movdqu xmm4, xmmword ptr [rcx] movdqu xmm5, xmmword ptr [rcx+10H] pxor xmm0, xmm2 pxor xmm1, xmm3 pxor xmm2, xmm4 pxor xmm3, xmm5 movups xmmword ptr [r10], xmm0 movups xmmword ptr [r10+10H], xmm1 movups xmmword ptr [r10+20H], xmm2 movups xmmword ptr [r10+30H], xmm3 movdqa xmm6, xmmword ptr [rsp] movdqa xmm7, xmmword ptr [rsp+10H] movdqa xmm8, xmmword ptr [rsp+20H] movdqa xmm9, xmmword ptr [rsp+30H] movdqa xmm11, xmmword ptr [rsp+40H] movdqa xmm14, xmmword ptr [rsp+50H] movdqa xmm15, xmmword ptr [rsp+60H] add rsp, 120 ret _blake3_compress_xof_sse41 ENDP blake3_compress_xof_sse41 ENDP _TEXT ENDS _RDATA SEGMENT READONLY PAGE ALIAS(".rdata") 'CONST' ALIGN 64 BLAKE3_IV: dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH ADD0: dd 0, 1, 2, 3 ADD1: dd 4 dup (4) BLAKE3_IV_0: dd 4 dup (6A09E667H) BLAKE3_IV_1: dd 4 dup (0BB67AE85H) BLAKE3_IV_2: dd 4 dup (3C6EF372H) BLAKE3_IV_3: dd 4 dup (0A54FF53AH) BLAKE3_BLOCK_LEN: dd 4 dup (64) ROT16: db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 ROT8: db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 CMP_MSB_MASK: dd 8 dup(80000000H) _RDATA ENDS END ================================================ FILE: src/third_party/blake3/c/LICENSE ================================================ This work is released into the public domain with CC0 1.0. Alternatively, it is licensed under the Apache License 2.0. ------------------------------------------------------------------------------- Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ------------------------------------------------------------------------------- Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2019 Jack O'Connor and Samuel Neves Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: src/third_party/blake3/c/blake3.c ================================================ #include #include #include #include "blake3.h" #include "blake3_impl.h" const char *blake3_version(void) { return BLAKE3_VERSION_STRING; } INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8], uint8_t flags) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; self->blocks_compressed = 0; self->flags = flags; } INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8], uint64_t chunk_counter) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = chunk_counter; self->blocks_compressed = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; } INLINE size_t chunk_state_len(const blake3_chunk_state *self) { return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) + ((size_t)self->buf_len); } INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len); if (take > input_len) { take = input_len; } uint8_t *dest = self->buf + ((size_t)self->buf_len); memcpy(dest, input, take); self->buf_len += (uint8_t)take; return take; } INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) { if (self->blocks_compressed == 0) { return CHUNK_START; } else { return 0; } } typedef struct { uint32_t input_cv[8]; uint64_t counter; uint8_t block[BLAKE3_BLOCK_LEN]; uint8_t block_len; uint8_t flags; } output_t; INLINE output_t make_output(const uint32_t input_cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { output_t ret; memcpy(ret.input_cv, input_cv, 32); memcpy(ret.block, block, BLAKE3_BLOCK_LEN); ret.block_len = block_len; ret.counter = counter; ret.flags = flags; return ret; } // Chaining values within a given chunk (specifically the compress_in_place // interface) are represented as words. This avoids unnecessary bytes<->words // conversion overhead in the portable implementation. However, the hash_many // interface handles both user input and parent node blocks, so it accepts // bytes. For that reason, chaining values in the CV stack are represented as // bytes. INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) { uint32_t cv_words[8]; memcpy(cv_words, self->input_cv, 32); blake3_compress_in_place(cv_words, self->block, self->block_len, self->counter, self->flags); store_cv_words(cv, cv_words); } INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out, size_t out_len) { uint64_t output_block_counter = seek / 64; size_t offset_within_block = seek % 64; uint8_t wide_buf[64]; while (out_len > 0) { blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf); size_t available_bytes = 64 - offset_within_block; size_t memcpy_len; if (out_len > available_bytes) { memcpy_len = available_bytes; } else { memcpy_len = out_len; } memcpy(out, wide_buf + offset_within_block, memcpy_len); out += memcpy_len; out_len -= memcpy_len; output_block_counter += 1; offset_within_block = 0; } } INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { if (self->buf_len > 0) { size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; if (input_len > 0) { blake3_compress_in_place( self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; self->buf_len = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); } } while (input_len > BLAKE3_BLOCK_LEN) { blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; input += BLAKE3_BLOCK_LEN; input_len -= BLAKE3_BLOCK_LEN; } size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; } INLINE output_t chunk_state_output(const blake3_chunk_state *self) { uint8_t block_flags = self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END; return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter, block_flags); } INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN], const uint32_t key[8], uint8_t flags) { return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT); } // Given some input larger than one chunk, return the number of bytes that // should go in the left subtree. This is the largest power-of-2 number of // chunks that leaves at least 1 byte for the right subtree. INLINE size_t left_len(size_t content_len) { // Subtract 1 to reserve at least one byte for the right side. content_len // should always be greater than BLAKE3_CHUNK_LEN. size_t full_chunks = (content_len - 1) / BLAKE3_CHUNK_LEN; return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN; } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time // on a single thread. Write out the chunk chaining values and return the // number of chunks hashed. These chunks are never the root and never empty; // those cases use a different codepath. INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(0 < input_len); assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN); #endif const uint8_t *chunks_array[MAX_SIMD_DEGREE]; size_t input_position = 0; size_t chunks_array_len = 0; while (input_len - input_position >= BLAKE3_CHUNK_LEN) { chunks_array[chunks_array_len] = &input[input_position]; input_position += BLAKE3_CHUNK_LEN; chunks_array_len += 1; } blake3_hash_many(chunks_array, chunks_array_len, BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter, true, flags, CHUNK_START, CHUNK_END, out); // Hash the remaining partial chunk, if there is one. Note that the empty // chunk (meaning the empty message) is a different codepath. if (input_len > input_position) { uint64_t counter = chunk_counter + (uint64_t)chunks_array_len; blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, key, flags); chunk_state.chunk_counter = counter; chunk_state_update(&chunk_state, &input[input_position], input_len - input_position); output_t output = chunk_state_output(&chunk_state); output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]); return chunks_array_len + 1; } else { return chunks_array_len; } } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time // on a single thread. Write out the parent chaining values and return the // number of parents hashed. (If there's an odd input chaining value left over, // return it as an additional output.) These parents are never the root and // never empty; those cases use a different codepath. INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values, size_t num_chaining_values, const uint32_t key[8], uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(2 <= num_chaining_values); assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2); #endif const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2]; size_t parents_array_len = 0; while (num_chaining_values - (2 * parents_array_len) >= 2) { parents_array[parents_array_len] = &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; parents_array_len += 1; } blake3_hash_many(parents_array, parents_array_len, 1, key, 0, // Parents always use counter 0. false, flags | PARENT, 0, // Parents have no start flags. 0, // Parents have no end flags. out); // If there's an odd child left over, it becomes an output. if (num_chaining_values > 2 * parents_array_len) { memcpy(&out[parents_array_len * BLAKE3_OUT_LEN], &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN], BLAKE3_OUT_LEN); return parents_array_len + 1; } else { return parents_array_len; } } // The wide helper function returns (writes out) an array of chaining values // and returns the length of that array. The number of chaining values returned // is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer, // if the input is shorter than that many chunks. The reason for maintaining a // wide array of chaining values going back up the tree, is to allow the // implementation to hash as many parents in parallel as possible. // // As a special case when the SIMD degree is 1, this function will still return // at least 2 outputs. This guarantees that this function doesn't perform the // root compression. (If it did, it would use the wrong flags, and also we // wouldn't be able to implement extendable output.) Note that this function is // not used when the whole input is only 1 chunk long; that's a different // codepath. // // Why not just have the caller split the input on the first update(), instead // of implementing this special rule? Because we don't want to limit SIMD or // multi-threading parallelism for that update(). static size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { // Note that the single chunk case does *not* bump the SIMD degree up to 2 // when it is 1. If this implementation adds multi-threading in the future, // this gives us the option of multi-threading even the 2-chunk case, which // can help performance on smaller platforms. if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) { return compress_chunks_parallel(input, input_len, key, chunk_counter, flags, out); } // With more than simd_degree chunks, we need to recurse. Start by dividing // the input into left and right subtrees. (Note that this is only optimal // as long as the SIMD degree is a power of 2. If we ever get a SIMD degree // of 3 or something, we'll need a more complicated strategy.) size_t left_input_len = left_len(input_len); size_t right_input_len = input_len - left_input_len; const uint8_t *right_input = &input[left_input_len]; uint64_t right_chunk_counter = chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN); // Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to // account for the special case of returning 2 outputs when the SIMD degree // is 1. uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t degree = blake3_simd_degree(); if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) { // The special case: We always use a degree of at least two, to make // sure there are two outputs. Except, as noted above, at the chunk // level, where we allow degree=1. (Note that the 1-chunk-input case is // a different codepath.) degree = 2; } uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; // Recurse! If this implementation adds multi-threading support in the // future, this is where it will go. size_t left_n = blake3_compress_subtree_wide(input, left_input_len, key, chunk_counter, flags, cv_array); size_t right_n = blake3_compress_subtree_wide( right_input, right_input_len, key, right_chunk_counter, flags, right_cvs); // The special case again. If simd_degree=1, then we'll have left_n=1 and // right_n=1. Rather than compressing them into a single output, return // them directly, to make sure we always have at least two outputs. if (left_n == 1) { memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); return 2; } // Otherwise, do one layer of parent node compression. size_t num_chaining_values = left_n + right_n; return compress_parents_parallel(cv_array, num_chaining_values, key, flags, out); } // Hash a subtree with compress_subtree_wide(), and then condense the resulting // list of chaining values down to a single parent node. Don't compress that // last parent node, however. Instead, return its message bytes (the // concatenated chaining values of its children). This is necessary when the // first call to update() supplies a complete subtree, because the topmost // parent node of that subtree could end up being the root. It's also necessary // for extended output in the general case. // // As with compress_subtree_wide(), this function is not used on inputs of 1 // chunk or less. That's a different codepath. INLINE void compress_subtree_to_parent_node( const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN]) { #if defined(BLAKE3_TESTING) assert(input_len > BLAKE3_CHUNK_LEN); #endif uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key, chunk_counter, flags, cv_array); assert(num_cvs <= MAX_SIMD_DEGREE_OR_2); // If MAX_SIMD_DEGREE is greater than 2 and there's enough input, // compress_subtree_wide() returns more than 2 chaining values. Condense // them into 2 by forming parent nodes repeatedly. uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2]; // The second half of this loop condition is always true, and we just // asserted it above. But GCC can't tell that it's always true, and if NDEBUG // is set on platforms where MAX_SIMD_DEGREE_OR_2 == 2, GCC emits spurious // warnings here. GCC 8.5 is particularly sensitive, so if you're changing // this code, test it against that version. while (num_cvs > 2 && num_cvs <= MAX_SIMD_DEGREE_OR_2) { num_cvs = compress_parents_parallel(cv_array, num_cvs, key, flags, out_array); memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); } memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); } INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8], uint8_t flags) { memcpy(self->key, key, BLAKE3_KEY_LEN); chunk_state_init(&self->chunk, key, flags); self->cv_stack_len = 0; } void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); } void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]) { uint32_t key_words[8]; load_key_words(key, key_words); hasher_init_base(self, key_words, KEYED_HASH); } void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len) { blake3_hasher context_hasher; hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT); blake3_hasher_update(&context_hasher, context, context_len); uint8_t context_key[BLAKE3_KEY_LEN]; blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN); uint32_t context_key_words[8]; load_key_words(context_key, context_key_words); hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL); } void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) { blake3_hasher_init_derive_key_raw(self, context, strlen(context)); } // As described in hasher_push_cv() below, we do "lazy merging", delaying // merges until right before the next CV is about to be added. This is // different from the reference implementation. Another difference is that we // aren't always merging 1 chunk at a time. Instead, each CV might represent // any power-of-two number of chunks, as long as the smaller-above-larger stack // order is maintained. Instead of the "count the trailing 0-bits" algorithm // described in the spec, we use a "count the total number of 1-bits" variant // that doesn't require us to retain the subtree size of the CV on top of the // stack. The principle is the same: each CV that should remain in the stack is // represented by a 1-bit in the total number of chunks (or bytes) so far. INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) { size_t post_merge_stack_len = (size_t)popcnt(total_len); while (self->cv_stack_len > post_merge_stack_len) { uint8_t *parent_node = &self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN]; output_t output = parent_output(parent_node, self->key, self->chunk.flags); output_chaining_value(&output, parent_node); self->cv_stack_len -= 1; } } // In reference_impl.rs, we merge the new CV with existing CVs from the stack // before pushing it. We can do that because we know more input is coming, so // we know none of the merges are root. // // This setting is different. We want to feed as much input as possible to // compress_subtree_wide(), without setting aside anything for the chunk_state. // If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once // as a single subtree, if at all possible. // // This leads to two problems: // 1) This 64 KiB input might be the only call that ever gets made to update. // In this case, the root node of the 64 KiB subtree would be the root node // of the whole tree, and it would need to be ROOT finalized. We can't // compress it until we know. // 2) This 64 KiB input might complete a larger tree, whose root node is // similarly going to be the the root of the whole tree. For example, maybe // we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the // node at the root of the 256 KiB subtree until we know how to finalize it. // // The second problem is solved with "lazy merging". That is, when we're about // to add a CV to the stack, we don't merge it with anything first, as the // reference impl does. Instead we do merges using the *previous* CV that was // added, which is sitting on top of the stack, and we put the new CV // (unmerged) on top of the stack afterwards. This guarantees that we never // merge the root node until finalize(). // // Solving the first problem requires an additional tool, // compress_subtree_to_parent_node(). That function always returns the top // *two* chaining values of the subtree it's compressing. We then do lazy // merging with each of them separately, so that the second CV will always // remain unmerged. (That also helps us support extendable output when we're // hashing an input all-at-once.) INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN], uint64_t chunk_counter) { hasher_merge_cv_stack(self, chunk_counter); memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv, BLAKE3_OUT_LEN); self->cv_stack_len += 1; } void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_update(&hasher, v.data(), v.size()); if (input_len == 0) { return; } const uint8_t *input_bytes = (const uint8_t *)input; // If we have some partial chunk bytes in the internal chunk_state, we need // to finish that chunk first. if (chunk_state_len(&self->chunk) > 0) { size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk); if (take > input_len) { take = input_len; } chunk_state_update(&self->chunk, input_bytes, take); input_bytes += take; input_len -= take; // If we've filled the current chunk and there's more coming, finalize this // chunk and proceed. In this case we know it's not the root. if (input_len > 0) { output_t output = chunk_state_output(&self->chunk); uint8_t chunk_cv[32]; output_chaining_value(&output, chunk_cv); hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter); chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1); } else { return; } } // Now the chunk_state is clear, and we have more input. If there's more than // a single chunk (so, definitely not the root chunk), hash the largest whole // subtree we can, with the full benefits of SIMD (and maybe in the future, // multi-threading) parallelism. Two restrictions: // - The subtree has to be a power-of-2 number of chunks. Only subtrees along // the right edge can be incomplete, and we don't know where the right edge // is going to be until we get to finalize(). // - The subtree must evenly divide the total number of chunks up until this // point (if total is not 0). If the current incomplete subtree is only // waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have // to complete the current subtree first. // Because we might need to break up the input to form powers of 2, or to // evenly divide what we already have, this part runs in a loop. while (input_len > BLAKE3_CHUNK_LEN) { size_t subtree_len = round_down_to_power_of_2(input_len); uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN; // Shrink the subtree_len until it evenly divides the count so far. We know // that subtree_len itself is a power of 2, so we can use a bitmasking // trick instead of an actual remainder operation. (Note that if the caller // consistently passes power-of-2 inputs of the same size, as is hopefully // typical, this loop condition will always fail, and subtree_len will // always be the full length of the input.) // // An aside: We don't have to shrink subtree_len quite this much. For // example, if count_so_far is 1, we could pass 2 chunks to // compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still // get the right answer in the end, and we might get to use 2-way SIMD // parallelism. The problem with this optimization, is that it gets us // stuck always hashing 2 chunks. The total number of chunks will remain // odd, and we'll never graduate to higher degrees of parallelism. See // https://github.com/BLAKE3-team/BLAKE3/issues/69. while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) { subtree_len /= 2; } // The shrunken subtree_len might now be 1 chunk long. If so, hash that one // chunk by itself. Otherwise, compress the subtree into a pair of CVs. uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; if (subtree_len <= BLAKE3_CHUNK_LEN) { blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, self->key, self->chunk.flags); chunk_state.chunk_counter = self->chunk.chunk_counter; chunk_state_update(&chunk_state, input_bytes, subtree_len); output_t output = chunk_state_output(&chunk_state); uint8_t cv[BLAKE3_OUT_LEN]; output_chaining_value(&output, cv); hasher_push_cv(self, cv, chunk_state.chunk_counter); } else { // This is the high-performance happy path, though getting here depends // on the caller giving us a long enough input. uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; compress_subtree_to_parent_node(input_bytes, subtree_len, self->key, self->chunk.chunk_counter, self->chunk.flags, cv_pair); hasher_push_cv(self, cv_pair, self->chunk.chunk_counter); hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN], self->chunk.chunk_counter + (subtree_chunks / 2)); } self->chunk.chunk_counter += subtree_chunks; input_bytes += subtree_len; input_len -= subtree_len; } // If there's any remaining input less than a full chunk, add it to the chunk // state. In that case, also do a final merge loop to make sure the subtree // stack doesn't contain any unmerged pairs. The remaining input means we // know these merges are non-root. This merge loop isn't strictly necessary // here, because hasher_push_chunk_cv already does its own merge loop, but it // simplifies blake3_hasher_finalize below. if (input_len > 0) { chunk_state_update(&self->chunk, input_bytes, input_len); hasher_merge_cv_stack(self, self->chunk.chunk_counter); } } void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len) { blake3_hasher_finalize_seek(self, 0, out, out_len); } void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_finalize(&hasher, v.data(), v.size()); if (out_len == 0) { return; } // If the subtree stack is empty, then the current chunk is the root. if (self->cv_stack_len == 0) { output_t output = chunk_state_output(&self->chunk); output_root_bytes(&output, seek, out, out_len); return; } // If there are any bytes in the chunk state, finalize that chunk and do a // roll-up merge between that chunk hash and every subtree in the stack. In // this case, the extra merge loop at the end of blake3_hasher_update // guarantees that none of the subtrees in the stack need to be merged with // each other first. Otherwise, if there are no bytes in the chunk state, // then the top of the stack is a chunk hash, and we start the merge from // that. output_t output; size_t cvs_remaining; if (chunk_state_len(&self->chunk) > 0) { cvs_remaining = self->cv_stack_len; output = chunk_state_output(&self->chunk); } else { // There are always at least 2 CVs in the stack in this case. cvs_remaining = self->cv_stack_len - 2; output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key, self->chunk.flags); } while (cvs_remaining > 0) { cvs_remaining -= 1; uint8_t parent_block[BLAKE3_BLOCK_LEN]; memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32); output_chaining_value(&output, &parent_block[32]); output = parent_output(parent_block, self->key, self->chunk.flags); } output_root_bytes(&output, seek, out, out_len); } void blake3_hasher_reset(blake3_hasher *self) { chunk_state_reset(&self->chunk, self->key, 0); self->cv_stack_len = 0; } ================================================ FILE: src/third_party/blake3/c/blake3.h ================================================ #ifndef BLAKE3_H #define BLAKE3_H #include #include #if !defined(BLAKE3_API) # if defined(_WIN32) || defined(__CYGWIN__) # if defined(BLAKE3_DLL) # if defined(BLAKE3_DLL_EXPORTS) # define BLAKE3_API __declspec(dllexport) # else # define BLAKE3_API __declspec(dllimport) # endif # define BLAKE3_PRIVATE # else # define BLAKE3_API # define BLAKE3_PRIVATE # endif # elif __GNUC__ >= 4 # define BLAKE3_API __attribute__((visibility("default"))) # define BLAKE3_PRIVATE __attribute__((visibility("hidden"))) # else # define BLAKE3_API # define BLAKE3_PRIVATE # endif #endif #ifdef __cplusplus extern "C" { #endif #define BLAKE3_VERSION_STRING "1.5.0" #define BLAKE3_KEY_LEN 32 #define BLAKE3_OUT_LEN 32 #define BLAKE3_BLOCK_LEN 64 #define BLAKE3_CHUNK_LEN 1024 #define BLAKE3_MAX_DEPTH 54 // This struct is a private implementation detail. It has to be here because // it's part of blake3_hasher below. typedef struct { uint32_t cv[8]; uint64_t chunk_counter; uint8_t buf[BLAKE3_BLOCK_LEN]; uint8_t buf_len; uint8_t blocks_compressed; uint8_t flags; } blake3_chunk_state; typedef struct { uint32_t key[8]; blake3_chunk_state chunk; uint8_t cv_stack_len; // The stack size is MAX_DEPTH + 1 because we do lazy merging. For example, // with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk // requires a 4th entry, rather than merging everything down to 1, because we // don't know whether more input is coming. This is different from how the // reference implementation does things. uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN]; } blake3_hasher; BLAKE3_API const char *blake3_version(void); BLAKE3_API void blake3_hasher_init(blake3_hasher *self); BLAKE3_API void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]); BLAKE3_API void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context); BLAKE3_API void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len); BLAKE3_API void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len); BLAKE3_API void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len); BLAKE3_API void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len); BLAKE3_API void blake3_hasher_reset(blake3_hasher *self); #ifdef __cplusplus } #endif #endif /* BLAKE3_H */ ================================================ FILE: src/third_party/blake3/c/blake3_avx2.c ================================================ #include "blake3_impl.h" #include #define DEGREE 8 INLINE __m256i loadu(const uint8_t src[32]) { return _mm256_loadu_si256((const __m256i *)src); } INLINE void storeu(__m256i src, uint8_t dest[16]) { _mm256_storeu_si256((__m256i *)dest, src); } INLINE __m256i addv(__m256i a, __m256i b) { return _mm256_add_epi32(a, b); } // Note that clang-format doesn't like the name "xor" for some reason. INLINE __m256i xorv(__m256i a, __m256i b) { return _mm256_xor_si256(a, b); } INLINE __m256i set1(uint32_t x) { return _mm256_set1_epi32((int32_t)x); } INLINE __m256i rot16(__m256i x) { return _mm256_shuffle_epi8( x, _mm256_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)); } INLINE __m256i rot12(__m256i x) { return _mm256_or_si256(_mm256_srli_epi32(x, 12), _mm256_slli_epi32(x, 32 - 12)); } INLINE __m256i rot8(__m256i x) { return _mm256_shuffle_epi8( x, _mm256_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1, 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)); } INLINE __m256i rot7(__m256i x) { return _mm256_or_si256(_mm256_srli_epi32(x, 7), _mm256_slli_epi32(x, 32 - 7)); } INLINE void round_fn(__m256i v[16], __m256i m[16], size_t r) { v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[15] = rot16(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot12(v[4]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[15] = rot8(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot7(v[4]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot16(v[15]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[4] = rot12(v[4]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot8(v[15]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[4] = rot7(v[4]); } INLINE void transpose_vecs(__m256i vecs[DEGREE]) { // Interleave 32-bit lanes. The low unpack is lanes 00/11/44/55, and the high // is 22/33/66/77. __m256i ab_0145 = _mm256_unpacklo_epi32(vecs[0], vecs[1]); __m256i ab_2367 = _mm256_unpackhi_epi32(vecs[0], vecs[1]); __m256i cd_0145 = _mm256_unpacklo_epi32(vecs[2], vecs[3]); __m256i cd_2367 = _mm256_unpackhi_epi32(vecs[2], vecs[3]); __m256i ef_0145 = _mm256_unpacklo_epi32(vecs[4], vecs[5]); __m256i ef_2367 = _mm256_unpackhi_epi32(vecs[4], vecs[5]); __m256i gh_0145 = _mm256_unpacklo_epi32(vecs[6], vecs[7]); __m256i gh_2367 = _mm256_unpackhi_epi32(vecs[6], vecs[7]); // Interleave 64-bit lanes. The low unpack is lanes 00/22 and the high is // 11/33. __m256i abcd_04 = _mm256_unpacklo_epi64(ab_0145, cd_0145); __m256i abcd_15 = _mm256_unpackhi_epi64(ab_0145, cd_0145); __m256i abcd_26 = _mm256_unpacklo_epi64(ab_2367, cd_2367); __m256i abcd_37 = _mm256_unpackhi_epi64(ab_2367, cd_2367); __m256i efgh_04 = _mm256_unpacklo_epi64(ef_0145, gh_0145); __m256i efgh_15 = _mm256_unpackhi_epi64(ef_0145, gh_0145); __m256i efgh_26 = _mm256_unpacklo_epi64(ef_2367, gh_2367); __m256i efgh_37 = _mm256_unpackhi_epi64(ef_2367, gh_2367); // Interleave 128-bit lanes. vecs[0] = _mm256_permute2x128_si256(abcd_04, efgh_04, 0x20); vecs[1] = _mm256_permute2x128_si256(abcd_15, efgh_15, 0x20); vecs[2] = _mm256_permute2x128_si256(abcd_26, efgh_26, 0x20); vecs[3] = _mm256_permute2x128_si256(abcd_37, efgh_37, 0x20); vecs[4] = _mm256_permute2x128_si256(abcd_04, efgh_04, 0x31); vecs[5] = _mm256_permute2x128_si256(abcd_15, efgh_15, 0x31); vecs[6] = _mm256_permute2x128_si256(abcd_26, efgh_26, 0x31); vecs[7] = _mm256_permute2x128_si256(abcd_37, efgh_37, 0x31); } INLINE void transpose_msg_vecs(const uint8_t *const *inputs, size_t block_offset, __m256i out[16]) { out[0] = loadu(&inputs[0][block_offset + 0 * sizeof(__m256i)]); out[1] = loadu(&inputs[1][block_offset + 0 * sizeof(__m256i)]); out[2] = loadu(&inputs[2][block_offset + 0 * sizeof(__m256i)]); out[3] = loadu(&inputs[3][block_offset + 0 * sizeof(__m256i)]); out[4] = loadu(&inputs[4][block_offset + 0 * sizeof(__m256i)]); out[5] = loadu(&inputs[5][block_offset + 0 * sizeof(__m256i)]); out[6] = loadu(&inputs[6][block_offset + 0 * sizeof(__m256i)]); out[7] = loadu(&inputs[7][block_offset + 0 * sizeof(__m256i)]); out[8] = loadu(&inputs[0][block_offset + 1 * sizeof(__m256i)]); out[9] = loadu(&inputs[1][block_offset + 1 * sizeof(__m256i)]); out[10] = loadu(&inputs[2][block_offset + 1 * sizeof(__m256i)]); out[11] = loadu(&inputs[3][block_offset + 1 * sizeof(__m256i)]); out[12] = loadu(&inputs[4][block_offset + 1 * sizeof(__m256i)]); out[13] = loadu(&inputs[5][block_offset + 1 * sizeof(__m256i)]); out[14] = loadu(&inputs[6][block_offset + 1 * sizeof(__m256i)]); out[15] = loadu(&inputs[7][block_offset + 1 * sizeof(__m256i)]); for (size_t i = 0; i < 8; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs(&out[0]); transpose_vecs(&out[8]); } INLINE void load_counters(uint64_t counter, bool increment_counter, __m256i *out_lo, __m256i *out_hi) { const __m256i mask = _mm256_set1_epi32(-(int32_t)increment_counter); const __m256i add0 = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0); const __m256i add1 = _mm256_and_si256(mask, add0); __m256i l = _mm256_add_epi32(_mm256_set1_epi32((int32_t)counter), add1); __m256i carry = _mm256_cmpgt_epi32(_mm256_xor_si256(add1, _mm256_set1_epi32(0x80000000)), _mm256_xor_si256( l, _mm256_set1_epi32(0x80000000))); __m256i h = _mm256_sub_epi32(_mm256_set1_epi32((int32_t)(counter >> 32)), carry); *out_lo = l; *out_hi = h; } static void blake3_hash8_avx2(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m256i h_vecs[8] = { set1(key[0]), set1(key[1]), set1(key[2]), set1(key[3]), set1(key[4]), set1(key[5]), set1(key[6]), set1(key[7]), }; __m256i counter_low_vec, counter_high_vec; load_counters(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m256i block_len_vec = set1(BLAKE3_BLOCK_LEN); __m256i block_flags_vec = set1(block_flags); __m256i msg_vecs[16]; transpose_msg_vecs(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m256i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1(IV[0]), set1(IV[1]), set1(IV[2]), set1(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn(v, msg_vecs, 0); round_fn(v, msg_vecs, 1); round_fn(v, msg_vecs, 2); round_fn(v, msg_vecs, 3); round_fn(v, msg_vecs, 4); round_fn(v, msg_vecs, 5); round_fn(v, msg_vecs, 6); h_vecs[0] = xorv(v[0], v[8]); h_vecs[1] = xorv(v[1], v[9]); h_vecs[2] = xorv(v[2], v[10]); h_vecs[3] = xorv(v[3], v[11]); h_vecs[4] = xorv(v[4], v[12]); h_vecs[5] = xorv(v[5], v[13]); h_vecs[6] = xorv(v[6], v[14]); h_vecs[7] = xorv(v[7], v[15]); block_flags = flags; } transpose_vecs(h_vecs); storeu(h_vecs[0], &out[0 * sizeof(__m256i)]); storeu(h_vecs[1], &out[1 * sizeof(__m256i)]); storeu(h_vecs[2], &out[2 * sizeof(__m256i)]); storeu(h_vecs[3], &out[3 * sizeof(__m256i)]); storeu(h_vecs[4], &out[4 * sizeof(__m256i)]); storeu(h_vecs[5], &out[5 * sizeof(__m256i)]); storeu(h_vecs[6], &out[6 * sizeof(__m256i)]); storeu(h_vecs[7], &out[7 * sizeof(__m256i)]); } void blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= DEGREE) { blake3_hash8_avx2(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += DEGREE; } inputs += DEGREE; num_inputs -= DEGREE; out = &out[DEGREE * BLAKE3_OUT_LEN]; } #if !defined(BLAKE3_NO_SSE41) blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); #else blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); #endif } ================================================ FILE: src/third_party/blake3/c/blake3_avx512.c ================================================ #include "blake3_impl.h" #include #define _mm_shuffle_ps2(a, b, c) \ (_mm_castps_si128( \ _mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), (c)))) INLINE __m128i loadu_128(const uint8_t src[16]) { return _mm_loadu_si128((const __m128i *)src); } INLINE __m256i loadu_256(const uint8_t src[32]) { return _mm256_loadu_si256((const __m256i *)src); } INLINE __m512i loadu_512(const uint8_t src[64]) { return _mm512_loadu_si512((const __m512i *)src); } INLINE void storeu_128(__m128i src, uint8_t dest[16]) { _mm_storeu_si128((__m128i *)dest, src); } INLINE void storeu_256(__m256i src, uint8_t dest[16]) { _mm256_storeu_si256((__m256i *)dest, src); } INLINE __m128i add_128(__m128i a, __m128i b) { return _mm_add_epi32(a, b); } INLINE __m256i add_256(__m256i a, __m256i b) { return _mm256_add_epi32(a, b); } INLINE __m512i add_512(__m512i a, __m512i b) { return _mm512_add_epi32(a, b); } INLINE __m128i xor_128(__m128i a, __m128i b) { return _mm_xor_si128(a, b); } INLINE __m256i xor_256(__m256i a, __m256i b) { return _mm256_xor_si256(a, b); } INLINE __m512i xor_512(__m512i a, __m512i b) { return _mm512_xor_si512(a, b); } INLINE __m128i set1_128(uint32_t x) { return _mm_set1_epi32((int32_t)x); } INLINE __m256i set1_256(uint32_t x) { return _mm256_set1_epi32((int32_t)x); } INLINE __m512i set1_512(uint32_t x) { return _mm512_set1_epi32((int32_t)x); } INLINE __m128i set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { return _mm_setr_epi32((int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d); } INLINE __m128i rot16_128(__m128i x) { return _mm_ror_epi32(x, 16); } INLINE __m256i rot16_256(__m256i x) { return _mm256_ror_epi32(x, 16); } INLINE __m512i rot16_512(__m512i x) { return _mm512_ror_epi32(x, 16); } INLINE __m128i rot12_128(__m128i x) { return _mm_ror_epi32(x, 12); } INLINE __m256i rot12_256(__m256i x) { return _mm256_ror_epi32(x, 12); } INLINE __m512i rot12_512(__m512i x) { return _mm512_ror_epi32(x, 12); } INLINE __m128i rot8_128(__m128i x) { return _mm_ror_epi32(x, 8); } INLINE __m256i rot8_256(__m256i x) { return _mm256_ror_epi32(x, 8); } INLINE __m512i rot8_512(__m512i x) { return _mm512_ror_epi32(x, 8); } INLINE __m128i rot7_128(__m128i x) { return _mm_ror_epi32(x, 7); } INLINE __m256i rot7_256(__m256i x) { return _mm256_ror_epi32(x, 7); } INLINE __m512i rot7_512(__m512i x) { return _mm512_ror_epi32(x, 7); } /* * ---------------------------------------------------------------------------- * compress_avx512 * ---------------------------------------------------------------------------- */ INLINE void g1(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = add_128(add_128(*row0, m), *row1); *row3 = xor_128(*row3, *row0); *row3 = rot16_128(*row3); *row2 = add_128(*row2, *row3); *row1 = xor_128(*row1, *row2); *row1 = rot12_128(*row1); } INLINE void g2(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = add_128(add_128(*row0, m), *row1); *row3 = xor_128(*row3, *row0); *row3 = rot8_128(*row3); *row2 = add_128(*row2, *row3); *row1 = xor_128(*row1, *row2); *row1 = rot7_128(*row1); } // Note the optimization here of leaving row1 as the unrotated row, rather than // row0. All the message loads below are adjusted to compensate for this. See // discussion at https://github.com/sneves/blake2-avx2/pull/4 INLINE void diagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(2, 1, 0, 3)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(0, 3, 2, 1)); } INLINE void undiagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(0, 3, 2, 1)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(2, 1, 0, 3)); } INLINE void compress_pre(__m128i rows[4], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { rows[0] = loadu_128((uint8_t *)&cv[0]); rows[1] = loadu_128((uint8_t *)&cv[4]); rows[2] = set4(IV[0], IV[1], IV[2], IV[3]); rows[3] = set4(counter_low(counter), counter_high(counter), (uint32_t)block_len, (uint32_t)flags); __m128i m0 = loadu_128(&block[sizeof(__m128i) * 0]); __m128i m1 = loadu_128(&block[sizeof(__m128i) * 1]); __m128i m2 = loadu_128(&block[sizeof(__m128i) * 2]); __m128i m3 = loadu_128(&block[sizeof(__m128i) * 3]); __m128i t0, t1, t2, t3, tt; // Round 1. The first round permutes the message words from the original // input order, into the groups that get mixed in parallel. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(2, 0, 2, 0)); // 6 4 2 0 g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 3, 1)); // 7 5 3 1 g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(2, 0, 2, 0)); // 14 12 10 8 t2 = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2, 1, 0, 3)); // 12 10 8 14 g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 1, 3, 1)); // 15 13 11 9 t3 = _mm_shuffle_epi32(t3, _MM_SHUFFLE(2, 1, 0, 3)); // 13 11 9 15 g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 2. This round and all following rounds apply a fixed permutation // to the message words from the round before. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 3 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 4 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 5 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 6 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 7 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); } void blake3_compress_xof_avx512(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu_128(xor_128(rows[0], rows[2]), &out[0]); storeu_128(xor_128(rows[1], rows[3]), &out[16]); storeu_128(xor_128(rows[2], loadu_128((uint8_t *)&cv[0])), &out[32]); storeu_128(xor_128(rows[3], loadu_128((uint8_t *)&cv[4])), &out[48]); } void blake3_compress_in_place_avx512(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu_128(xor_128(rows[0], rows[2]), (uint8_t *)&cv[0]); storeu_128(xor_128(rows[1], rows[3]), (uint8_t *)&cv[4]); } /* * ---------------------------------------------------------------------------- * hash4_avx512 * ---------------------------------------------------------------------------- */ INLINE void round_fn4(__m128i v[16], __m128i m[16], size_t r) { v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[15] = rot16_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot12_128(v[4]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[15] = rot8_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot7_128(v[4]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot16_128(v[15]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[4] = rot12_128(v[4]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot8_128(v[15]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[4] = rot7_128(v[4]); } INLINE void transpose_vecs_128(__m128i vecs[4]) { // Interleave 32-bit lanes. The low unpack is lanes 00/11 and the high is // 22/33. Note that this doesn't split the vector into two lanes, as the // AVX2 counterparts do. __m128i ab_01 = _mm_unpacklo_epi32(vecs[0], vecs[1]); __m128i ab_23 = _mm_unpackhi_epi32(vecs[0], vecs[1]); __m128i cd_01 = _mm_unpacklo_epi32(vecs[2], vecs[3]); __m128i cd_23 = _mm_unpackhi_epi32(vecs[2], vecs[3]); // Interleave 64-bit lanes. __m128i abcd_0 = _mm_unpacklo_epi64(ab_01, cd_01); __m128i abcd_1 = _mm_unpackhi_epi64(ab_01, cd_01); __m128i abcd_2 = _mm_unpacklo_epi64(ab_23, cd_23); __m128i abcd_3 = _mm_unpackhi_epi64(ab_23, cd_23); vecs[0] = abcd_0; vecs[1] = abcd_1; vecs[2] = abcd_2; vecs[3] = abcd_3; } INLINE void transpose_msg_vecs4(const uint8_t *const *inputs, size_t block_offset, __m128i out[16]) { out[0] = loadu_128(&inputs[0][block_offset + 0 * sizeof(__m128i)]); out[1] = loadu_128(&inputs[1][block_offset + 0 * sizeof(__m128i)]); out[2] = loadu_128(&inputs[2][block_offset + 0 * sizeof(__m128i)]); out[3] = loadu_128(&inputs[3][block_offset + 0 * sizeof(__m128i)]); out[4] = loadu_128(&inputs[0][block_offset + 1 * sizeof(__m128i)]); out[5] = loadu_128(&inputs[1][block_offset + 1 * sizeof(__m128i)]); out[6] = loadu_128(&inputs[2][block_offset + 1 * sizeof(__m128i)]); out[7] = loadu_128(&inputs[3][block_offset + 1 * sizeof(__m128i)]); out[8] = loadu_128(&inputs[0][block_offset + 2 * sizeof(__m128i)]); out[9] = loadu_128(&inputs[1][block_offset + 2 * sizeof(__m128i)]); out[10] = loadu_128(&inputs[2][block_offset + 2 * sizeof(__m128i)]); out[11] = loadu_128(&inputs[3][block_offset + 2 * sizeof(__m128i)]); out[12] = loadu_128(&inputs[0][block_offset + 3 * sizeof(__m128i)]); out[13] = loadu_128(&inputs[1][block_offset + 3 * sizeof(__m128i)]); out[14] = loadu_128(&inputs[2][block_offset + 3 * sizeof(__m128i)]); out[15] = loadu_128(&inputs[3][block_offset + 3 * sizeof(__m128i)]); for (size_t i = 0; i < 4; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs_128(&out[0]); transpose_vecs_128(&out[4]); transpose_vecs_128(&out[8]); transpose_vecs_128(&out[12]); } INLINE void load_counters4(uint64_t counter, bool increment_counter, __m128i *out_lo, __m128i *out_hi) { uint64_t mask = (increment_counter ? ~0 : 0); __m256i mask_vec = _mm256_set1_epi64x(mask); __m256i deltas = _mm256_setr_epi64x(0, 1, 2, 3); deltas = _mm256_and_si256(mask_vec, deltas); __m256i counters = _mm256_add_epi64(_mm256_set1_epi64x((int64_t)counter), deltas); *out_lo = _mm256_cvtepi64_epi32(counters); *out_hi = _mm256_cvtepi64_epi32(_mm256_srli_epi64(counters, 32)); } static void blake3_hash4_avx512(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m128i h_vecs[8] = { set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]), set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]), }; __m128i counter_low_vec, counter_high_vec; load_counters4(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m128i block_len_vec = set1_128(BLAKE3_BLOCK_LEN); __m128i block_flags_vec = set1_128(block_flags); __m128i msg_vecs[16]; transpose_msg_vecs4(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m128i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_128(IV[0]), set1_128(IV[1]), set1_128(IV[2]), set1_128(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn4(v, msg_vecs, 0); round_fn4(v, msg_vecs, 1); round_fn4(v, msg_vecs, 2); round_fn4(v, msg_vecs, 3); round_fn4(v, msg_vecs, 4); round_fn4(v, msg_vecs, 5); round_fn4(v, msg_vecs, 6); h_vecs[0] = xor_128(v[0], v[8]); h_vecs[1] = xor_128(v[1], v[9]); h_vecs[2] = xor_128(v[2], v[10]); h_vecs[3] = xor_128(v[3], v[11]); h_vecs[4] = xor_128(v[4], v[12]); h_vecs[5] = xor_128(v[5], v[13]); h_vecs[6] = xor_128(v[6], v[14]); h_vecs[7] = xor_128(v[7], v[15]); block_flags = flags; } transpose_vecs_128(&h_vecs[0]); transpose_vecs_128(&h_vecs[4]); // The first four vecs now contain the first half of each output, and the // second four vecs contain the second half of each output. storeu_128(h_vecs[0], &out[0 * sizeof(__m128i)]); storeu_128(h_vecs[4], &out[1 * sizeof(__m128i)]); storeu_128(h_vecs[1], &out[2 * sizeof(__m128i)]); storeu_128(h_vecs[5], &out[3 * sizeof(__m128i)]); storeu_128(h_vecs[2], &out[4 * sizeof(__m128i)]); storeu_128(h_vecs[6], &out[5 * sizeof(__m128i)]); storeu_128(h_vecs[3], &out[6 * sizeof(__m128i)]); storeu_128(h_vecs[7], &out[7 * sizeof(__m128i)]); } /* * ---------------------------------------------------------------------------- * hash8_avx512 * ---------------------------------------------------------------------------- */ INLINE void round_fn8(__m256i v[16], __m256i m[16], size_t r) { v[0] = add_256(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = add_256(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = add_256(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = add_256(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = add_256(v[0], v[4]); v[1] = add_256(v[1], v[5]); v[2] = add_256(v[2], v[6]); v[3] = add_256(v[3], v[7]); v[12] = xor_256(v[12], v[0]); v[13] = xor_256(v[13], v[1]); v[14] = xor_256(v[14], v[2]); v[15] = xor_256(v[15], v[3]); v[12] = rot16_256(v[12]); v[13] = rot16_256(v[13]); v[14] = rot16_256(v[14]); v[15] = rot16_256(v[15]); v[8] = add_256(v[8], v[12]); v[9] = add_256(v[9], v[13]); v[10] = add_256(v[10], v[14]); v[11] = add_256(v[11], v[15]); v[4] = xor_256(v[4], v[8]); v[5] = xor_256(v[5], v[9]); v[6] = xor_256(v[6], v[10]); v[7] = xor_256(v[7], v[11]); v[4] = rot12_256(v[4]); v[5] = rot12_256(v[5]); v[6] = rot12_256(v[6]); v[7] = rot12_256(v[7]); v[0] = add_256(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = add_256(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = add_256(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = add_256(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = add_256(v[0], v[4]); v[1] = add_256(v[1], v[5]); v[2] = add_256(v[2], v[6]); v[3] = add_256(v[3], v[7]); v[12] = xor_256(v[12], v[0]); v[13] = xor_256(v[13], v[1]); v[14] = xor_256(v[14], v[2]); v[15] = xor_256(v[15], v[3]); v[12] = rot8_256(v[12]); v[13] = rot8_256(v[13]); v[14] = rot8_256(v[14]); v[15] = rot8_256(v[15]); v[8] = add_256(v[8], v[12]); v[9] = add_256(v[9], v[13]); v[10] = add_256(v[10], v[14]); v[11] = add_256(v[11], v[15]); v[4] = xor_256(v[4], v[8]); v[5] = xor_256(v[5], v[9]); v[6] = xor_256(v[6], v[10]); v[7] = xor_256(v[7], v[11]); v[4] = rot7_256(v[4]); v[5] = rot7_256(v[5]); v[6] = rot7_256(v[6]); v[7] = rot7_256(v[7]); v[0] = add_256(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = add_256(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = add_256(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = add_256(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = add_256(v[0], v[5]); v[1] = add_256(v[1], v[6]); v[2] = add_256(v[2], v[7]); v[3] = add_256(v[3], v[4]); v[15] = xor_256(v[15], v[0]); v[12] = xor_256(v[12], v[1]); v[13] = xor_256(v[13], v[2]); v[14] = xor_256(v[14], v[3]); v[15] = rot16_256(v[15]); v[12] = rot16_256(v[12]); v[13] = rot16_256(v[13]); v[14] = rot16_256(v[14]); v[10] = add_256(v[10], v[15]); v[11] = add_256(v[11], v[12]); v[8] = add_256(v[8], v[13]); v[9] = add_256(v[9], v[14]); v[5] = xor_256(v[5], v[10]); v[6] = xor_256(v[6], v[11]); v[7] = xor_256(v[7], v[8]); v[4] = xor_256(v[4], v[9]); v[5] = rot12_256(v[5]); v[6] = rot12_256(v[6]); v[7] = rot12_256(v[7]); v[4] = rot12_256(v[4]); v[0] = add_256(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = add_256(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = add_256(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = add_256(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = add_256(v[0], v[5]); v[1] = add_256(v[1], v[6]); v[2] = add_256(v[2], v[7]); v[3] = add_256(v[3], v[4]); v[15] = xor_256(v[15], v[0]); v[12] = xor_256(v[12], v[1]); v[13] = xor_256(v[13], v[2]); v[14] = xor_256(v[14], v[3]); v[15] = rot8_256(v[15]); v[12] = rot8_256(v[12]); v[13] = rot8_256(v[13]); v[14] = rot8_256(v[14]); v[10] = add_256(v[10], v[15]); v[11] = add_256(v[11], v[12]); v[8] = add_256(v[8], v[13]); v[9] = add_256(v[9], v[14]); v[5] = xor_256(v[5], v[10]); v[6] = xor_256(v[6], v[11]); v[7] = xor_256(v[7], v[8]); v[4] = xor_256(v[4], v[9]); v[5] = rot7_256(v[5]); v[6] = rot7_256(v[6]); v[7] = rot7_256(v[7]); v[4] = rot7_256(v[4]); } INLINE void transpose_vecs_256(__m256i vecs[8]) { // Interleave 32-bit lanes. The low unpack is lanes 00/11/44/55, and the high // is 22/33/66/77. __m256i ab_0145 = _mm256_unpacklo_epi32(vecs[0], vecs[1]); __m256i ab_2367 = _mm256_unpackhi_epi32(vecs[0], vecs[1]); __m256i cd_0145 = _mm256_unpacklo_epi32(vecs[2], vecs[3]); __m256i cd_2367 = _mm256_unpackhi_epi32(vecs[2], vecs[3]); __m256i ef_0145 = _mm256_unpacklo_epi32(vecs[4], vecs[5]); __m256i ef_2367 = _mm256_unpackhi_epi32(vecs[4], vecs[5]); __m256i gh_0145 = _mm256_unpacklo_epi32(vecs[6], vecs[7]); __m256i gh_2367 = _mm256_unpackhi_epi32(vecs[6], vecs[7]); // Interleave 64-bit lanes. The low unpack is lanes 00/22 and the high is // 11/33. __m256i abcd_04 = _mm256_unpacklo_epi64(ab_0145, cd_0145); __m256i abcd_15 = _mm256_unpackhi_epi64(ab_0145, cd_0145); __m256i abcd_26 = _mm256_unpacklo_epi64(ab_2367, cd_2367); __m256i abcd_37 = _mm256_unpackhi_epi64(ab_2367, cd_2367); __m256i efgh_04 = _mm256_unpacklo_epi64(ef_0145, gh_0145); __m256i efgh_15 = _mm256_unpackhi_epi64(ef_0145, gh_0145); __m256i efgh_26 = _mm256_unpacklo_epi64(ef_2367, gh_2367); __m256i efgh_37 = _mm256_unpackhi_epi64(ef_2367, gh_2367); // Interleave 128-bit lanes. vecs[0] = _mm256_permute2x128_si256(abcd_04, efgh_04, 0x20); vecs[1] = _mm256_permute2x128_si256(abcd_15, efgh_15, 0x20); vecs[2] = _mm256_permute2x128_si256(abcd_26, efgh_26, 0x20); vecs[3] = _mm256_permute2x128_si256(abcd_37, efgh_37, 0x20); vecs[4] = _mm256_permute2x128_si256(abcd_04, efgh_04, 0x31); vecs[5] = _mm256_permute2x128_si256(abcd_15, efgh_15, 0x31); vecs[6] = _mm256_permute2x128_si256(abcd_26, efgh_26, 0x31); vecs[7] = _mm256_permute2x128_si256(abcd_37, efgh_37, 0x31); } INLINE void transpose_msg_vecs8(const uint8_t *const *inputs, size_t block_offset, __m256i out[16]) { out[0] = loadu_256(&inputs[0][block_offset + 0 * sizeof(__m256i)]); out[1] = loadu_256(&inputs[1][block_offset + 0 * sizeof(__m256i)]); out[2] = loadu_256(&inputs[2][block_offset + 0 * sizeof(__m256i)]); out[3] = loadu_256(&inputs[3][block_offset + 0 * sizeof(__m256i)]); out[4] = loadu_256(&inputs[4][block_offset + 0 * sizeof(__m256i)]); out[5] = loadu_256(&inputs[5][block_offset + 0 * sizeof(__m256i)]); out[6] = loadu_256(&inputs[6][block_offset + 0 * sizeof(__m256i)]); out[7] = loadu_256(&inputs[7][block_offset + 0 * sizeof(__m256i)]); out[8] = loadu_256(&inputs[0][block_offset + 1 * sizeof(__m256i)]); out[9] = loadu_256(&inputs[1][block_offset + 1 * sizeof(__m256i)]); out[10] = loadu_256(&inputs[2][block_offset + 1 * sizeof(__m256i)]); out[11] = loadu_256(&inputs[3][block_offset + 1 * sizeof(__m256i)]); out[12] = loadu_256(&inputs[4][block_offset + 1 * sizeof(__m256i)]); out[13] = loadu_256(&inputs[5][block_offset + 1 * sizeof(__m256i)]); out[14] = loadu_256(&inputs[6][block_offset + 1 * sizeof(__m256i)]); out[15] = loadu_256(&inputs[7][block_offset + 1 * sizeof(__m256i)]); for (size_t i = 0; i < 8; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs_256(&out[0]); transpose_vecs_256(&out[8]); } INLINE void load_counters8(uint64_t counter, bool increment_counter, __m256i *out_lo, __m256i *out_hi) { uint64_t mask = (increment_counter ? ~0 : 0); __m512i mask_vec = _mm512_set1_epi64(mask); __m512i deltas = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7); deltas = _mm512_and_si512(mask_vec, deltas); __m512i counters = _mm512_add_epi64(_mm512_set1_epi64((int64_t)counter), deltas); *out_lo = _mm512_cvtepi64_epi32(counters); *out_hi = _mm512_cvtepi64_epi32(_mm512_srli_epi64(counters, 32)); } static void blake3_hash8_avx512(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m256i h_vecs[8] = { set1_256(key[0]), set1_256(key[1]), set1_256(key[2]), set1_256(key[3]), set1_256(key[4]), set1_256(key[5]), set1_256(key[6]), set1_256(key[7]), }; __m256i counter_low_vec, counter_high_vec; load_counters8(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m256i block_len_vec = set1_256(BLAKE3_BLOCK_LEN); __m256i block_flags_vec = set1_256(block_flags); __m256i msg_vecs[16]; transpose_msg_vecs8(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m256i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_256(IV[0]), set1_256(IV[1]), set1_256(IV[2]), set1_256(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn8(v, msg_vecs, 0); round_fn8(v, msg_vecs, 1); round_fn8(v, msg_vecs, 2); round_fn8(v, msg_vecs, 3); round_fn8(v, msg_vecs, 4); round_fn8(v, msg_vecs, 5); round_fn8(v, msg_vecs, 6); h_vecs[0] = xor_256(v[0], v[8]); h_vecs[1] = xor_256(v[1], v[9]); h_vecs[2] = xor_256(v[2], v[10]); h_vecs[3] = xor_256(v[3], v[11]); h_vecs[4] = xor_256(v[4], v[12]); h_vecs[5] = xor_256(v[5], v[13]); h_vecs[6] = xor_256(v[6], v[14]); h_vecs[7] = xor_256(v[7], v[15]); block_flags = flags; } transpose_vecs_256(h_vecs); storeu_256(h_vecs[0], &out[0 * sizeof(__m256i)]); storeu_256(h_vecs[1], &out[1 * sizeof(__m256i)]); storeu_256(h_vecs[2], &out[2 * sizeof(__m256i)]); storeu_256(h_vecs[3], &out[3 * sizeof(__m256i)]); storeu_256(h_vecs[4], &out[4 * sizeof(__m256i)]); storeu_256(h_vecs[5], &out[5 * sizeof(__m256i)]); storeu_256(h_vecs[6], &out[6 * sizeof(__m256i)]); storeu_256(h_vecs[7], &out[7 * sizeof(__m256i)]); } /* * ---------------------------------------------------------------------------- * hash16_avx512 * ---------------------------------------------------------------------------- */ INLINE void round_fn16(__m512i v[16], __m512i m[16], size_t r) { v[0] = add_512(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = add_512(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = add_512(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = add_512(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = add_512(v[0], v[4]); v[1] = add_512(v[1], v[5]); v[2] = add_512(v[2], v[6]); v[3] = add_512(v[3], v[7]); v[12] = xor_512(v[12], v[0]); v[13] = xor_512(v[13], v[1]); v[14] = xor_512(v[14], v[2]); v[15] = xor_512(v[15], v[3]); v[12] = rot16_512(v[12]); v[13] = rot16_512(v[13]); v[14] = rot16_512(v[14]); v[15] = rot16_512(v[15]); v[8] = add_512(v[8], v[12]); v[9] = add_512(v[9], v[13]); v[10] = add_512(v[10], v[14]); v[11] = add_512(v[11], v[15]); v[4] = xor_512(v[4], v[8]); v[5] = xor_512(v[5], v[9]); v[6] = xor_512(v[6], v[10]); v[7] = xor_512(v[7], v[11]); v[4] = rot12_512(v[4]); v[5] = rot12_512(v[5]); v[6] = rot12_512(v[6]); v[7] = rot12_512(v[7]); v[0] = add_512(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = add_512(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = add_512(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = add_512(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = add_512(v[0], v[4]); v[1] = add_512(v[1], v[5]); v[2] = add_512(v[2], v[6]); v[3] = add_512(v[3], v[7]); v[12] = xor_512(v[12], v[0]); v[13] = xor_512(v[13], v[1]); v[14] = xor_512(v[14], v[2]); v[15] = xor_512(v[15], v[3]); v[12] = rot8_512(v[12]); v[13] = rot8_512(v[13]); v[14] = rot8_512(v[14]); v[15] = rot8_512(v[15]); v[8] = add_512(v[8], v[12]); v[9] = add_512(v[9], v[13]); v[10] = add_512(v[10], v[14]); v[11] = add_512(v[11], v[15]); v[4] = xor_512(v[4], v[8]); v[5] = xor_512(v[5], v[9]); v[6] = xor_512(v[6], v[10]); v[7] = xor_512(v[7], v[11]); v[4] = rot7_512(v[4]); v[5] = rot7_512(v[5]); v[6] = rot7_512(v[6]); v[7] = rot7_512(v[7]); v[0] = add_512(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = add_512(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = add_512(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = add_512(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = add_512(v[0], v[5]); v[1] = add_512(v[1], v[6]); v[2] = add_512(v[2], v[7]); v[3] = add_512(v[3], v[4]); v[15] = xor_512(v[15], v[0]); v[12] = xor_512(v[12], v[1]); v[13] = xor_512(v[13], v[2]); v[14] = xor_512(v[14], v[3]); v[15] = rot16_512(v[15]); v[12] = rot16_512(v[12]); v[13] = rot16_512(v[13]); v[14] = rot16_512(v[14]); v[10] = add_512(v[10], v[15]); v[11] = add_512(v[11], v[12]); v[8] = add_512(v[8], v[13]); v[9] = add_512(v[9], v[14]); v[5] = xor_512(v[5], v[10]); v[6] = xor_512(v[6], v[11]); v[7] = xor_512(v[7], v[8]); v[4] = xor_512(v[4], v[9]); v[5] = rot12_512(v[5]); v[6] = rot12_512(v[6]); v[7] = rot12_512(v[7]); v[4] = rot12_512(v[4]); v[0] = add_512(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = add_512(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = add_512(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = add_512(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = add_512(v[0], v[5]); v[1] = add_512(v[1], v[6]); v[2] = add_512(v[2], v[7]); v[3] = add_512(v[3], v[4]); v[15] = xor_512(v[15], v[0]); v[12] = xor_512(v[12], v[1]); v[13] = xor_512(v[13], v[2]); v[14] = xor_512(v[14], v[3]); v[15] = rot8_512(v[15]); v[12] = rot8_512(v[12]); v[13] = rot8_512(v[13]); v[14] = rot8_512(v[14]); v[10] = add_512(v[10], v[15]); v[11] = add_512(v[11], v[12]); v[8] = add_512(v[8], v[13]); v[9] = add_512(v[9], v[14]); v[5] = xor_512(v[5], v[10]); v[6] = xor_512(v[6], v[11]); v[7] = xor_512(v[7], v[8]); v[4] = xor_512(v[4], v[9]); v[5] = rot7_512(v[5]); v[6] = rot7_512(v[6]); v[7] = rot7_512(v[7]); v[4] = rot7_512(v[4]); } // 0b10001000, or lanes a0/a2/b0/b2 in little-endian order #define LO_IMM8 0x88 INLINE __m512i unpack_lo_128(__m512i a, __m512i b) { return _mm512_shuffle_i32x4(a, b, LO_IMM8); } // 0b11011101, or lanes a1/a3/b1/b3 in little-endian order #define HI_IMM8 0xdd INLINE __m512i unpack_hi_128(__m512i a, __m512i b) { return _mm512_shuffle_i32x4(a, b, HI_IMM8); } INLINE void transpose_vecs_512(__m512i vecs[16]) { // Interleave 32-bit lanes. The _0 unpack is lanes // 0/0/1/1/4/4/5/5/8/8/9/9/12/12/13/13, and the _2 unpack is lanes // 2/2/3/3/6/6/7/7/10/10/11/11/14/14/15/15. __m512i ab_0 = _mm512_unpacklo_epi32(vecs[0], vecs[1]); __m512i ab_2 = _mm512_unpackhi_epi32(vecs[0], vecs[1]); __m512i cd_0 = _mm512_unpacklo_epi32(vecs[2], vecs[3]); __m512i cd_2 = _mm512_unpackhi_epi32(vecs[2], vecs[3]); __m512i ef_0 = _mm512_unpacklo_epi32(vecs[4], vecs[5]); __m512i ef_2 = _mm512_unpackhi_epi32(vecs[4], vecs[5]); __m512i gh_0 = _mm512_unpacklo_epi32(vecs[6], vecs[7]); __m512i gh_2 = _mm512_unpackhi_epi32(vecs[6], vecs[7]); __m512i ij_0 = _mm512_unpacklo_epi32(vecs[8], vecs[9]); __m512i ij_2 = _mm512_unpackhi_epi32(vecs[8], vecs[9]); __m512i kl_0 = _mm512_unpacklo_epi32(vecs[10], vecs[11]); __m512i kl_2 = _mm512_unpackhi_epi32(vecs[10], vecs[11]); __m512i mn_0 = _mm512_unpacklo_epi32(vecs[12], vecs[13]); __m512i mn_2 = _mm512_unpackhi_epi32(vecs[12], vecs[13]); __m512i op_0 = _mm512_unpacklo_epi32(vecs[14], vecs[15]); __m512i op_2 = _mm512_unpackhi_epi32(vecs[14], vecs[15]); // Interleave 64-bit lanes. The _0 unpack is lanes // 0/0/0/0/4/4/4/4/8/8/8/8/12/12/12/12, the _1 unpack is lanes // 1/1/1/1/5/5/5/5/9/9/9/9/13/13/13/13, the _2 unpack is lanes // 2/2/2/2/6/6/6/6/10/10/10/10/14/14/14/14, and the _3 unpack is lanes // 3/3/3/3/7/7/7/7/11/11/11/11/15/15/15/15. __m512i abcd_0 = _mm512_unpacklo_epi64(ab_0, cd_0); __m512i abcd_1 = _mm512_unpackhi_epi64(ab_0, cd_0); __m512i abcd_2 = _mm512_unpacklo_epi64(ab_2, cd_2); __m512i abcd_3 = _mm512_unpackhi_epi64(ab_2, cd_2); __m512i efgh_0 = _mm512_unpacklo_epi64(ef_0, gh_0); __m512i efgh_1 = _mm512_unpackhi_epi64(ef_0, gh_0); __m512i efgh_2 = _mm512_unpacklo_epi64(ef_2, gh_2); __m512i efgh_3 = _mm512_unpackhi_epi64(ef_2, gh_2); __m512i ijkl_0 = _mm512_unpacklo_epi64(ij_0, kl_0); __m512i ijkl_1 = _mm512_unpackhi_epi64(ij_0, kl_0); __m512i ijkl_2 = _mm512_unpacklo_epi64(ij_2, kl_2); __m512i ijkl_3 = _mm512_unpackhi_epi64(ij_2, kl_2); __m512i mnop_0 = _mm512_unpacklo_epi64(mn_0, op_0); __m512i mnop_1 = _mm512_unpackhi_epi64(mn_0, op_0); __m512i mnop_2 = _mm512_unpacklo_epi64(mn_2, op_2); __m512i mnop_3 = _mm512_unpackhi_epi64(mn_2, op_2); // Interleave 128-bit lanes. The _0 unpack is // 0/0/0/0/8/8/8/8/0/0/0/0/8/8/8/8, the _1 unpack is // 1/1/1/1/9/9/9/9/1/1/1/1/9/9/9/9, and so on. __m512i abcdefgh_0 = unpack_lo_128(abcd_0, efgh_0); __m512i abcdefgh_1 = unpack_lo_128(abcd_1, efgh_1); __m512i abcdefgh_2 = unpack_lo_128(abcd_2, efgh_2); __m512i abcdefgh_3 = unpack_lo_128(abcd_3, efgh_3); __m512i abcdefgh_4 = unpack_hi_128(abcd_0, efgh_0); __m512i abcdefgh_5 = unpack_hi_128(abcd_1, efgh_1); __m512i abcdefgh_6 = unpack_hi_128(abcd_2, efgh_2); __m512i abcdefgh_7 = unpack_hi_128(abcd_3, efgh_3); __m512i ijklmnop_0 = unpack_lo_128(ijkl_0, mnop_0); __m512i ijklmnop_1 = unpack_lo_128(ijkl_1, mnop_1); __m512i ijklmnop_2 = unpack_lo_128(ijkl_2, mnop_2); __m512i ijklmnop_3 = unpack_lo_128(ijkl_3, mnop_3); __m512i ijklmnop_4 = unpack_hi_128(ijkl_0, mnop_0); __m512i ijklmnop_5 = unpack_hi_128(ijkl_1, mnop_1); __m512i ijklmnop_6 = unpack_hi_128(ijkl_2, mnop_2); __m512i ijklmnop_7 = unpack_hi_128(ijkl_3, mnop_3); // Interleave 128-bit lanes again for the final outputs. vecs[0] = unpack_lo_128(abcdefgh_0, ijklmnop_0); vecs[1] = unpack_lo_128(abcdefgh_1, ijklmnop_1); vecs[2] = unpack_lo_128(abcdefgh_2, ijklmnop_2); vecs[3] = unpack_lo_128(abcdefgh_3, ijklmnop_3); vecs[4] = unpack_lo_128(abcdefgh_4, ijklmnop_4); vecs[5] = unpack_lo_128(abcdefgh_5, ijklmnop_5); vecs[6] = unpack_lo_128(abcdefgh_6, ijklmnop_6); vecs[7] = unpack_lo_128(abcdefgh_7, ijklmnop_7); vecs[8] = unpack_hi_128(abcdefgh_0, ijklmnop_0); vecs[9] = unpack_hi_128(abcdefgh_1, ijklmnop_1); vecs[10] = unpack_hi_128(abcdefgh_2, ijklmnop_2); vecs[11] = unpack_hi_128(abcdefgh_3, ijklmnop_3); vecs[12] = unpack_hi_128(abcdefgh_4, ijklmnop_4); vecs[13] = unpack_hi_128(abcdefgh_5, ijklmnop_5); vecs[14] = unpack_hi_128(abcdefgh_6, ijklmnop_6); vecs[15] = unpack_hi_128(abcdefgh_7, ijklmnop_7); } INLINE void transpose_msg_vecs16(const uint8_t *const *inputs, size_t block_offset, __m512i out[16]) { out[0] = loadu_512(&inputs[0][block_offset]); out[1] = loadu_512(&inputs[1][block_offset]); out[2] = loadu_512(&inputs[2][block_offset]); out[3] = loadu_512(&inputs[3][block_offset]); out[4] = loadu_512(&inputs[4][block_offset]); out[5] = loadu_512(&inputs[5][block_offset]); out[6] = loadu_512(&inputs[6][block_offset]); out[7] = loadu_512(&inputs[7][block_offset]); out[8] = loadu_512(&inputs[8][block_offset]); out[9] = loadu_512(&inputs[9][block_offset]); out[10] = loadu_512(&inputs[10][block_offset]); out[11] = loadu_512(&inputs[11][block_offset]); out[12] = loadu_512(&inputs[12][block_offset]); out[13] = loadu_512(&inputs[13][block_offset]); out[14] = loadu_512(&inputs[14][block_offset]); out[15] = loadu_512(&inputs[15][block_offset]); for (size_t i = 0; i < 16; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs_512(out); } INLINE void load_counters16(uint64_t counter, bool increment_counter, __m512i *out_lo, __m512i *out_hi) { const __m512i mask = _mm512_set1_epi32(-(int32_t)increment_counter); const __m512i deltas = _mm512_set_epi32(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); const __m512i masked_deltas = _mm512_and_si512(deltas, mask); const __m512i low_words = _mm512_add_epi32( _mm512_set1_epi32((int32_t)counter), masked_deltas); // The carry bit is 1 if the high bit of the word was 1 before addition and is // 0 after. // NOTE: It would be a bit more natural to use _mm512_cmp_epu32_mask to // compute the carry bits here, and originally we did, but that intrinsic is // broken under GCC 5.4. See https://github.com/BLAKE3-team/BLAKE3/issues/271. const __m512i carries = _mm512_srli_epi32( _mm512_andnot_si512( low_words, // 0 after (gets inverted by andnot) _mm512_set1_epi32((int32_t)counter)), // and 1 before 31); const __m512i high_words = _mm512_add_epi32( _mm512_set1_epi32((int32_t)(counter >> 32)), carries); *out_lo = low_words; *out_hi = high_words; } static void blake3_hash16_avx512(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m512i h_vecs[8] = { set1_512(key[0]), set1_512(key[1]), set1_512(key[2]), set1_512(key[3]), set1_512(key[4]), set1_512(key[5]), set1_512(key[6]), set1_512(key[7]), }; __m512i counter_low_vec, counter_high_vec; load_counters16(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m512i block_len_vec = set1_512(BLAKE3_BLOCK_LEN); __m512i block_flags_vec = set1_512(block_flags); __m512i msg_vecs[16]; transpose_msg_vecs16(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m512i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_512(IV[0]), set1_512(IV[1]), set1_512(IV[2]), set1_512(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn16(v, msg_vecs, 0); round_fn16(v, msg_vecs, 1); round_fn16(v, msg_vecs, 2); round_fn16(v, msg_vecs, 3); round_fn16(v, msg_vecs, 4); round_fn16(v, msg_vecs, 5); round_fn16(v, msg_vecs, 6); h_vecs[0] = xor_512(v[0], v[8]); h_vecs[1] = xor_512(v[1], v[9]); h_vecs[2] = xor_512(v[2], v[10]); h_vecs[3] = xor_512(v[3], v[11]); h_vecs[4] = xor_512(v[4], v[12]); h_vecs[5] = xor_512(v[5], v[13]); h_vecs[6] = xor_512(v[6], v[14]); h_vecs[7] = xor_512(v[7], v[15]); block_flags = flags; } // transpose_vecs_512 operates on a 16x16 matrix of words, but we only have 8 // state vectors. Pad the matrix with zeros. After transposition, store the // lower half of each vector. __m512i padded[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_512(0), set1_512(0), set1_512(0), set1_512(0), set1_512(0), set1_512(0), set1_512(0), set1_512(0), }; transpose_vecs_512(padded); _mm256_mask_storeu_epi32(&out[0 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[0])); _mm256_mask_storeu_epi32(&out[1 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[1])); _mm256_mask_storeu_epi32(&out[2 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[2])); _mm256_mask_storeu_epi32(&out[3 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[3])); _mm256_mask_storeu_epi32(&out[4 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[4])); _mm256_mask_storeu_epi32(&out[5 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[5])); _mm256_mask_storeu_epi32(&out[6 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[6])); _mm256_mask_storeu_epi32(&out[7 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[7])); _mm256_mask_storeu_epi32(&out[8 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[8])); _mm256_mask_storeu_epi32(&out[9 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[9])); _mm256_mask_storeu_epi32(&out[10 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[10])); _mm256_mask_storeu_epi32(&out[11 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[11])); _mm256_mask_storeu_epi32(&out[12 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[12])); _mm256_mask_storeu_epi32(&out[13 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[13])); _mm256_mask_storeu_epi32(&out[14 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[14])); _mm256_mask_storeu_epi32(&out[15 * sizeof(__m256i)], (__mmask8)-1, _mm512_castsi512_si256(padded[15])); } /* * ---------------------------------------------------------------------------- * hash_many_avx512 * ---------------------------------------------------------------------------- */ INLINE void hash_one_avx512(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_avx512(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } memcpy(out, cv, BLAKE3_OUT_LEN); } void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= 16) { blake3_hash16_avx512(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 16; } inputs += 16; num_inputs -= 16; out = &out[16 * BLAKE3_OUT_LEN]; } while (num_inputs >= 8) { blake3_hash8_avx512(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 8; } inputs += 8; num_inputs -= 8; out = &out[8 * BLAKE3_OUT_LEN]; } while (num_inputs >= 4) { blake3_hash4_avx512(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 4; } inputs += 4; num_inputs -= 4; out = &out[4 * BLAKE3_OUT_LEN]; } while (num_inputs > 0) { hash_one_avx512(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/c/blake3_dispatch.c ================================================ #include #include #include #include "blake3_impl.h" #if defined(IS_X86) #if defined(_MSC_VER) #include #elif defined(__GNUC__) #include #else #undef IS_X86 /* Unimplemented! */ #endif #endif #if !defined(BLAKE3_ATOMICS) #if defined(__has_include) #if __has_include() && !defined(_MSC_VER) #define BLAKE3_ATOMICS 1 #else #define BLAKE3_ATOMICS 0 #endif /* __has_include() && !defined(_MSC_VER) */ #else #define BLAKE3_ATOMICS 0 #endif /* defined(__has_include) */ #endif /* BLAKE3_ATOMICS */ #if BLAKE3_ATOMICS #define ATOMIC_INT _Atomic int #define ATOMIC_LOAD(x) x #define ATOMIC_STORE(x, y) x = y #elif defined(_MSC_VER) #define ATOMIC_INT long #define ATOMIC_LOAD(x) _InterlockedOr(&x, 0) #define ATOMIC_STORE(x, y) _InterlockedExchange(&x, y) #else #define ATOMIC_INT int #define ATOMIC_LOAD(x) x #define ATOMIC_STORE(x, y) x = y #endif #define MAYBE_UNUSED(x) (void)((x)) #if defined(IS_X86) static uint64_t xgetbv(void) { #if defined(_MSC_VER) return _xgetbv(0); #else uint32_t eax = 0, edx = 0; __asm__ __volatile__("xgetbv\n" : "=a"(eax), "=d"(edx) : "c"(0)); return ((uint64_t)edx << 32) | eax; #endif } static void cpuid(uint32_t out[4], uint32_t id) { #if defined(_MSC_VER) __cpuid((int *)out, id); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #endif } static void cpuidex(uint32_t out[4], uint32_t id, uint32_t sid) { #if defined(_MSC_VER) __cpuidex((int *)out, id, sid); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #endif } #endif enum cpu_feature { SSE2 = 1 << 0, SSSE3 = 1 << 1, SSE41 = 1 << 2, AVX = 1 << 3, AVX2 = 1 << 4, AVX512F = 1 << 5, AVX512VL = 1 << 6, /* ... */ UNDEFINED = 1 << 30 }; #if !defined(BLAKE3_TESTING) static /* Allow the variable to be controlled manually for testing */ #endif ATOMIC_INT g_cpu_features = UNDEFINED; #if !defined(BLAKE3_TESTING) static #endif enum cpu_feature get_cpu_features(void) { /* If TSAN detects a data race here, try compiling with -DBLAKE3_ATOMICS=1 */ long features = ATOMIC_LOAD(g_cpu_features); if (features != UNDEFINED) { return (enum cpu_feature)features; } else { #if defined(IS_X86) uint32_t regs[4] = {0}; uint32_t *eax = ®s[0], *ebx = ®s[1], *ecx = ®s[2], *edx = ®s[3]; (void)edx; features = 0; cpuid(regs, 0); const int max_id = *eax; cpuid(regs, 1); #if defined(__amd64__) || defined(_M_X64) features |= SSE2; #else if (*edx & (1UL << 26)) features |= SSE2; #endif if (*ecx & (1UL << 9)) features |= SSSE3; if (*ecx & (1UL << 19)) features |= SSE41; if (*ecx & (1UL << 27)) { // OSXSAVE const uint64_t mask = xgetbv(); if ((mask & 6) == 6) { // SSE and AVX states if (*ecx & (1UL << 28)) features |= AVX; if (max_id >= 7) { cpuidex(regs, 7, 0); if (*ebx & (1UL << 5)) features |= AVX2; if ((mask & 224) == 224) { // Opmask, ZMM_Hi256, Hi16_Zmm if (*ebx & (1UL << 31)) features |= AVX512VL; if (*ebx & (1UL << 16)) features |= AVX512F; } } } } ATOMIC_STORE(g_cpu_features, features); return (enum cpu_feature)features; #else /* How to detect NEON? */ return 0; #endif } } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_in_place_avx512(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_in_place_sse41(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_in_place_sse2(cv, block, block_len, counter, flags); return; } #endif #endif blake3_compress_in_place_portable(cv, block, block_len, counter, flags); } void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_xof_avx512(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_xof_sse41(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_xof_sse2(cv, block, block_len, counter, flags, out); return; } #endif #endif blake3_compress_xof_portable(cv, block, block_len, counter, flags, out); } void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #endif #if BLAKE3_USE_NEON == 1 blake3_hash_many_neon(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; #endif blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); } // The dynamically detected SIMD degree of the current platform. size_t blake3_simd_degree(void) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { return 16; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { return 8; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { return 4; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { return 4; } #endif #endif #if BLAKE3_USE_NEON == 1 return 4; #endif return 1; } ================================================ FILE: src/third_party/blake3/c/blake3_impl.h ================================================ #ifndef BLAKE3_IMPL_H #define BLAKE3_IMPL_H #include #include #include #include #include #include "blake3.h" // internal flags enum blake3_flags { CHUNK_START = 1 << 0, CHUNK_END = 1 << 1, PARENT = 1 << 2, ROOT = 1 << 3, KEYED_HASH = 1 << 4, DERIVE_KEY_CONTEXT = 1 << 5, DERIVE_KEY_MATERIAL = 1 << 6, }; // This C implementation tries to support recent versions of GCC, Clang, and // MSVC. #if defined(_MSC_VER) #define INLINE static __forceinline #else #define INLINE static inline __attribute__((always_inline)) #endif #if defined(__x86_64__) || defined(_M_X64) #define IS_X86 #define IS_X86_64 #endif #if defined(__i386__) || defined(_M_IX86) #define IS_X86 #define IS_X86_32 #endif #if defined(__aarch64__) || defined(_M_ARM64) #define IS_AARCH64 #endif #if defined(IS_X86) #if defined(_MSC_VER) #include #endif #endif #if !defined(BLAKE3_USE_NEON) // If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness #if defined(IS_AARCH64) #if defined(__ARM_BIG_ENDIAN) #define BLAKE3_USE_NEON 0 #else #define BLAKE3_USE_NEON 1 #endif #else #define BLAKE3_USE_NEON 0 #endif #endif #if defined(IS_X86) #define MAX_SIMD_DEGREE 16 #elif BLAKE3_USE_NEON == 1 #define MAX_SIMD_DEGREE 4 #else #define MAX_SIMD_DEGREE 1 #endif // There are some places where we want a static size that's equal to the // MAX_SIMD_DEGREE, but also at least 2. #define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2) static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL}; static const uint8_t MSG_SCHEDULE[7][16] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}, }; /* Find index of the highest set bit */ /* x is assumed to be nonzero. */ static unsigned int highest_one(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return 63 ^ (unsigned int)__builtin_clzll(x); #elif defined(_MSC_VER) && defined(IS_X86_64) unsigned long index; _BitScanReverse64(&index, x); return index; #elif defined(_MSC_VER) && defined(IS_X86_32) if(x >> 32) { unsigned long index; _BitScanReverse(&index, (unsigned long)(x >> 32)); return 32 + index; } else { unsigned long index; _BitScanReverse(&index, (unsigned long)x); return index; } #else unsigned int c = 0; if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; } if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; } if(x & 0x000000000000ff00ULL) { x >>= 8; c += 8; } if(x & 0x00000000000000f0ULL) { x >>= 4; c += 4; } if(x & 0x000000000000000cULL) { x >>= 2; c += 2; } if(x & 0x0000000000000002ULL) { c += 1; } return c; #endif } // Count the number of 1 bits. INLINE unsigned int popcnt(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return (unsigned int)__builtin_popcountll(x); #else unsigned int count = 0; while (x != 0) { count += 1; x &= x - 1; } return count; #endif } // Largest power of two less than or equal to x. As a special case, returns 1 // when x is 0. INLINE uint64_t round_down_to_power_of_2(uint64_t x) { return 1ULL << highest_one(x | 1); } INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; } INLINE uint32_t counter_high(uint64_t counter) { return (uint32_t)(counter >> 32); } INLINE uint32_t load32(const void *src) { const uint8_t *p = (const uint8_t *)src; return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); } INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], uint32_t key_words[8]) { key_words[0] = load32(&key[0 * 4]); key_words[1] = load32(&key[1 * 4]); key_words[2] = load32(&key[2 * 4]); key_words[3] = load32(&key[3 * 4]); key_words[4] = load32(&key[4 * 4]); key_words[5] = load32(&key[5 * 4]); key_words[6] = load32(&key[6 * 4]); key_words[7] = load32(&key[7 * 4]); } INLINE void store32(void *dst, uint32_t w) { uint8_t *p = (uint8_t *)dst; p[0] = (uint8_t)(w >> 0); p[1] = (uint8_t)(w >> 8); p[2] = (uint8_t)(w >> 16); p[3] = (uint8_t)(w >> 24); } INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) { store32(&bytes_out[0 * 4], cv_words[0]); store32(&bytes_out[1 * 4], cv_words[1]); store32(&bytes_out[2 * 4], cv_words[2]); store32(&bytes_out[3 * 4], cv_words[3]); store32(&bytes_out[4 * 4], cv_words[4]); store32(&bytes_out[5 * 4], cv_words[5]); store32(&bytes_out[6 * 4], cv_words[6]); store32(&bytes_out[7 * 4], cv_words[7]); } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); size_t blake3_simd_degree(void); // Declarations for implementation-specific functions. void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #if defined(IS_X86) #if !defined(BLAKE3_NO_SSE2) void blake3_compress_in_place_sse2(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse2(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_SSE41) void blake3_compress_in_place_sse41(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse41(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX2) void blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX512) void blake3_compress_in_place_avx512(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_avx512(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif #if BLAKE3_USE_NEON == 1 void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif /* BLAKE3_IMPL_H */ ================================================ FILE: src/third_party/blake3/c/blake3_neon.c ================================================ #include "blake3_impl.h" #include #ifdef __ARM_BIG_ENDIAN #error "This implementation only supports little-endian ARM." // It might be that all we need for big-endian support here is to get the loads // and stores right, but step zero would be finding a way to test it in CI. #endif INLINE uint32x4_t loadu_128(const uint8_t src[16]) { // vld1q_u32 has alignment requirements. Don't use it. uint32x4_t x; memcpy(&x, src, 16); return x; } INLINE void storeu_128(uint32x4_t src, uint8_t dest[16]) { // vst1q_u32 has alignment requirements. Don't use it. memcpy(dest, &src, 16); } INLINE uint32x4_t add_128(uint32x4_t a, uint32x4_t b) { return vaddq_u32(a, b); } INLINE uint32x4_t xor_128(uint32x4_t a, uint32x4_t b) { return veorq_u32(a, b); } INLINE uint32x4_t set1_128(uint32_t x) { return vld1q_dup_u32(&x); } INLINE uint32x4_t set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { uint32_t array[4] = {a, b, c, d}; return vld1q_u32(array); } INLINE uint32x4_t rot16_128(uint32x4_t x) { // The straightfoward implementation would be two shifts and an or, but that's // slower on microarchitectures we've tested. See // https://github.com/BLAKE3-team/BLAKE3/pull/319. // return vorrq_u32(vshrq_n_u32(x, 16), vshlq_n_u32(x, 32 - 16)); return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(x))); } INLINE uint32x4_t rot12_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 12), vshlq_n_u32(x, 32 - 12)); return vsriq_n_u32(vshlq_n_u32(x, 32-12), x, 12); } INLINE uint32x4_t rot8_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 8), vshlq_n_u32(x, 32 - 8)); #if defined(__clang__) return vreinterpretq_u32_u8(__builtin_shufflevector(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12)); #elif __GNUC__ * 10000 + __GNUC_MINOR__ * 100 >=40700 static const uint8x16_t r8 = {1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12}; return vreinterpretq_u32_u8(__builtin_shuffle(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), r8)); #else return vsriq_n_u32(vshlq_n_u32(x, 32-8), x, 8); #endif } INLINE uint32x4_t rot7_128(uint32x4_t x) { // See comment in rot16_128. // return vorrq_u32(vshrq_n_u32(x, 7), vshlq_n_u32(x, 32 - 7)); return vsriq_n_u32(vshlq_n_u32(x, 32-7), x, 7); } // TODO: compress_neon // TODO: hash2_neon /* * ---------------------------------------------------------------------------- * hash4_neon * ---------------------------------------------------------------------------- */ INLINE void round_fn4(uint32x4_t v[16], uint32x4_t m[16], size_t r) { v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[15] = rot16_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot12_128(v[4]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = add_128(v[0], v[4]); v[1] = add_128(v[1], v[5]); v[2] = add_128(v[2], v[6]); v[3] = add_128(v[3], v[7]); v[12] = xor_128(v[12], v[0]); v[13] = xor_128(v[13], v[1]); v[14] = xor_128(v[14], v[2]); v[15] = xor_128(v[15], v[3]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[15] = rot8_128(v[15]); v[8] = add_128(v[8], v[12]); v[9] = add_128(v[9], v[13]); v[10] = add_128(v[10], v[14]); v[11] = add_128(v[11], v[15]); v[4] = xor_128(v[4], v[8]); v[5] = xor_128(v[5], v[9]); v[6] = xor_128(v[6], v[10]); v[7] = xor_128(v[7], v[11]); v[4] = rot7_128(v[4]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot16_128(v[15]); v[12] = rot16_128(v[12]); v[13] = rot16_128(v[13]); v[14] = rot16_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot12_128(v[5]); v[6] = rot12_128(v[6]); v[7] = rot12_128(v[7]); v[4] = rot12_128(v[4]); v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = add_128(v[0], v[5]); v[1] = add_128(v[1], v[6]); v[2] = add_128(v[2], v[7]); v[3] = add_128(v[3], v[4]); v[15] = xor_128(v[15], v[0]); v[12] = xor_128(v[12], v[1]); v[13] = xor_128(v[13], v[2]); v[14] = xor_128(v[14], v[3]); v[15] = rot8_128(v[15]); v[12] = rot8_128(v[12]); v[13] = rot8_128(v[13]); v[14] = rot8_128(v[14]); v[10] = add_128(v[10], v[15]); v[11] = add_128(v[11], v[12]); v[8] = add_128(v[8], v[13]); v[9] = add_128(v[9], v[14]); v[5] = xor_128(v[5], v[10]); v[6] = xor_128(v[6], v[11]); v[7] = xor_128(v[7], v[8]); v[4] = xor_128(v[4], v[9]); v[5] = rot7_128(v[5]); v[6] = rot7_128(v[6]); v[7] = rot7_128(v[7]); v[4] = rot7_128(v[4]); } INLINE void transpose_vecs_128(uint32x4_t vecs[4]) { // Individually transpose the four 2x2 sub-matrices in each corner. uint32x4x2_t rows01 = vtrnq_u32(vecs[0], vecs[1]); uint32x4x2_t rows23 = vtrnq_u32(vecs[2], vecs[3]); // Swap the top-right and bottom-left 2x2s (which just got transposed). vecs[0] = vcombine_u32(vget_low_u32(rows01.val[0]), vget_low_u32(rows23.val[0])); vecs[1] = vcombine_u32(vget_low_u32(rows01.val[1]), vget_low_u32(rows23.val[1])); vecs[2] = vcombine_u32(vget_high_u32(rows01.val[0]), vget_high_u32(rows23.val[0])); vecs[3] = vcombine_u32(vget_high_u32(rows01.val[1]), vget_high_u32(rows23.val[1])); } INLINE void transpose_msg_vecs4(const uint8_t *const *inputs, size_t block_offset, uint32x4_t out[16]) { out[0] = loadu_128(&inputs[0][block_offset + 0 * sizeof(uint32x4_t)]); out[1] = loadu_128(&inputs[1][block_offset + 0 * sizeof(uint32x4_t)]); out[2] = loadu_128(&inputs[2][block_offset + 0 * sizeof(uint32x4_t)]); out[3] = loadu_128(&inputs[3][block_offset + 0 * sizeof(uint32x4_t)]); out[4] = loadu_128(&inputs[0][block_offset + 1 * sizeof(uint32x4_t)]); out[5] = loadu_128(&inputs[1][block_offset + 1 * sizeof(uint32x4_t)]); out[6] = loadu_128(&inputs[2][block_offset + 1 * sizeof(uint32x4_t)]); out[7] = loadu_128(&inputs[3][block_offset + 1 * sizeof(uint32x4_t)]); out[8] = loadu_128(&inputs[0][block_offset + 2 * sizeof(uint32x4_t)]); out[9] = loadu_128(&inputs[1][block_offset + 2 * sizeof(uint32x4_t)]); out[10] = loadu_128(&inputs[2][block_offset + 2 * sizeof(uint32x4_t)]); out[11] = loadu_128(&inputs[3][block_offset + 2 * sizeof(uint32x4_t)]); out[12] = loadu_128(&inputs[0][block_offset + 3 * sizeof(uint32x4_t)]); out[13] = loadu_128(&inputs[1][block_offset + 3 * sizeof(uint32x4_t)]); out[14] = loadu_128(&inputs[2][block_offset + 3 * sizeof(uint32x4_t)]); out[15] = loadu_128(&inputs[3][block_offset + 3 * sizeof(uint32x4_t)]); transpose_vecs_128(&out[0]); transpose_vecs_128(&out[4]); transpose_vecs_128(&out[8]); transpose_vecs_128(&out[12]); } INLINE void load_counters4(uint64_t counter, bool increment_counter, uint32x4_t *out_low, uint32x4_t *out_high) { uint64_t mask = (increment_counter ? ~0 : 0); *out_low = set4( counter_low(counter + (mask & 0)), counter_low(counter + (mask & 1)), counter_low(counter + (mask & 2)), counter_low(counter + (mask & 3))); *out_high = set4( counter_high(counter + (mask & 0)), counter_high(counter + (mask & 1)), counter_high(counter + (mask & 2)), counter_high(counter + (mask & 3))); } void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { uint32x4_t h_vecs[8] = { set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]), set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]), }; uint32x4_t counter_low_vec, counter_high_vec; load_counters4(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } uint32x4_t block_len_vec = set1_128(BLAKE3_BLOCK_LEN); uint32x4_t block_flags_vec = set1_128(block_flags); uint32x4_t msg_vecs[16]; transpose_msg_vecs4(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); uint32x4_t v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1_128(IV[0]), set1_128(IV[1]), set1_128(IV[2]), set1_128(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn4(v, msg_vecs, 0); round_fn4(v, msg_vecs, 1); round_fn4(v, msg_vecs, 2); round_fn4(v, msg_vecs, 3); round_fn4(v, msg_vecs, 4); round_fn4(v, msg_vecs, 5); round_fn4(v, msg_vecs, 6); h_vecs[0] = xor_128(v[0], v[8]); h_vecs[1] = xor_128(v[1], v[9]); h_vecs[2] = xor_128(v[2], v[10]); h_vecs[3] = xor_128(v[3], v[11]); h_vecs[4] = xor_128(v[4], v[12]); h_vecs[5] = xor_128(v[5], v[13]); h_vecs[6] = xor_128(v[6], v[14]); h_vecs[7] = xor_128(v[7], v[15]); block_flags = flags; } transpose_vecs_128(&h_vecs[0]); transpose_vecs_128(&h_vecs[4]); // The first four vecs now contain the first half of each output, and the // second four vecs contain the second half of each output. storeu_128(h_vecs[0], &out[0 * sizeof(uint32x4_t)]); storeu_128(h_vecs[4], &out[1 * sizeof(uint32x4_t)]); storeu_128(h_vecs[1], &out[2 * sizeof(uint32x4_t)]); storeu_128(h_vecs[5], &out[3 * sizeof(uint32x4_t)]); storeu_128(h_vecs[2], &out[4 * sizeof(uint32x4_t)]); storeu_128(h_vecs[6], &out[5 * sizeof(uint32x4_t)]); storeu_128(h_vecs[3], &out[6 * sizeof(uint32x4_t)]); storeu_128(h_vecs[7], &out[7 * sizeof(uint32x4_t)]); } /* * ---------------------------------------------------------------------------- * hash_many_neon * ---------------------------------------------------------------------------- */ void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); INLINE void hash_one_neon(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } // TODO: Implement compress_neon. However note that according to // https://github.com/BLAKE2/BLAKE2/commit/7965d3e6e1b4193438b8d3a656787587d2579227, // compress_neon might not be any faster than compress_portable. blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } memcpy(out, cv, BLAKE3_OUT_LEN); } void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= 4) { blake3_hash4_neon(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 4; } inputs += 4; num_inputs -= 4; out = &out[4 * BLAKE3_OUT_LEN]; } while (num_inputs > 0) { hash_one_neon(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/c/blake3_portable.c ================================================ #include "blake3_impl.h" #include INLINE uint32_t rotr32(uint32_t w, uint32_t c) { return (w >> c) | (w << (32 - c)); } INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y) { state[a] = state[a] + state[b] + x; state[d] = rotr32(state[d] ^ state[a], 16); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 12); state[a] = state[a] + state[b] + y; state[d] = rotr32(state[d] ^ state[a], 8); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 7); } INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) { // Select the message schedule based on the round. const uint8_t *schedule = MSG_SCHEDULE[round]; // Mix the columns. g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); // Mix the rows. g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); } INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t block_words[16]; block_words[0] = load32(block + 4 * 0); block_words[1] = load32(block + 4 * 1); block_words[2] = load32(block + 4 * 2); block_words[3] = load32(block + 4 * 3); block_words[4] = load32(block + 4 * 4); block_words[5] = load32(block + 4 * 5); block_words[6] = load32(block + 4 * 6); block_words[7] = load32(block + 4 * 7); block_words[8] = load32(block + 4 * 8); block_words[9] = load32(block + 4 * 9); block_words[10] = load32(block + 4 * 10); block_words[11] = load32(block + 4 * 11); block_words[12] = load32(block + 4 * 12); block_words[13] = load32(block + 4 * 13); block_words[14] = load32(block + 4 * 14); block_words[15] = load32(block + 4 * 15); state[0] = cv[0]; state[1] = cv[1]; state[2] = cv[2]; state[3] = cv[3]; state[4] = cv[4]; state[5] = cv[5]; state[6] = cv[6]; state[7] = cv[7]; state[8] = IV[0]; state[9] = IV[1]; state[10] = IV[2]; state[11] = IV[3]; state[12] = counter_low(counter); state[13] = counter_high(counter); state[14] = (uint32_t)block_len; state[15] = (uint32_t)flags; round_fn(state, &block_words[0], 0); round_fn(state, &block_words[0], 1); round_fn(state, &block_words[0], 2); round_fn(state, &block_words[0], 3); round_fn(state, &block_words[0], 4); round_fn(state, &block_words[0], 5); round_fn(state, &block_words[0], 6); } void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); cv[0] = state[0] ^ state[8]; cv[1] = state[1] ^ state[9]; cv[2] = state[2] ^ state[10]; cv[3] = state[3] ^ state[11]; cv[4] = state[4] ^ state[12]; cv[5] = state[5] ^ state[13]; cv[6] = state[6] ^ state[14]; cv[7] = state[7] ^ state[15]; } void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); store32(&out[0 * 4], state[0] ^ state[8]); store32(&out[1 * 4], state[1] ^ state[9]); store32(&out[2 * 4], state[2] ^ state[10]); store32(&out[3 * 4], state[3] ^ state[11]); store32(&out[4 * 4], state[4] ^ state[12]); store32(&out[5 * 4], state[5] ^ state[13]); store32(&out[6 * 4], state[6] ^ state[14]); store32(&out[7 * 4], state[7] ^ state[15]); store32(&out[8 * 4], state[8] ^ cv[0]); store32(&out[9 * 4], state[9] ^ cv[1]); store32(&out[10 * 4], state[10] ^ cv[2]); store32(&out[11 * 4], state[11] ^ cv[3]); store32(&out[12 * 4], state[12] ^ cv[4]); store32(&out[13 * 4], state[13] ^ cv[5]); store32(&out[14 * 4], state[14] ^ cv[6]); store32(&out[15 * 4], state[15] ^ cv[7]); } INLINE void hash_one_portable(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } store_cv_words(out, cv); } void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs > 0) { hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/c/blake3_sse2.c ================================================ #include "blake3_impl.h" #include #define DEGREE 4 #define _mm_shuffle_ps2(a, b, c) \ (_mm_castps_si128( \ _mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), (c)))) INLINE __m128i loadu(const uint8_t src[16]) { return _mm_loadu_si128((const __m128i *)src); } INLINE void storeu(__m128i src, uint8_t dest[16]) { _mm_storeu_si128((__m128i *)dest, src); } INLINE __m128i addv(__m128i a, __m128i b) { return _mm_add_epi32(a, b); } // Note that clang-format doesn't like the name "xor" for some reason. INLINE __m128i xorv(__m128i a, __m128i b) { return _mm_xor_si128(a, b); } INLINE __m128i set1(uint32_t x) { return _mm_set1_epi32((int32_t)x); } INLINE __m128i set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { return _mm_setr_epi32((int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d); } INLINE __m128i rot16(__m128i x) { return _mm_shufflehi_epi16(_mm_shufflelo_epi16(x, 0xB1), 0xB1); } INLINE __m128i rot12(__m128i x) { return xorv(_mm_srli_epi32(x, 12), _mm_slli_epi32(x, 32 - 12)); } INLINE __m128i rot8(__m128i x) { return xorv(_mm_srli_epi32(x, 8), _mm_slli_epi32(x, 32 - 8)); } INLINE __m128i rot7(__m128i x) { return xorv(_mm_srli_epi32(x, 7), _mm_slli_epi32(x, 32 - 7)); } INLINE void g1(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = addv(addv(*row0, m), *row1); *row3 = xorv(*row3, *row0); *row3 = rot16(*row3); *row2 = addv(*row2, *row3); *row1 = xorv(*row1, *row2); *row1 = rot12(*row1); } INLINE void g2(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = addv(addv(*row0, m), *row1); *row3 = xorv(*row3, *row0); *row3 = rot8(*row3); *row2 = addv(*row2, *row3); *row1 = xorv(*row1, *row2); *row1 = rot7(*row1); } // Note the optimization here of leaving row1 as the unrotated row, rather than // row0. All the message loads below are adjusted to compensate for this. See // discussion at https://github.com/sneves/blake2-avx2/pull/4 INLINE void diagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(2, 1, 0, 3)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(0, 3, 2, 1)); } INLINE void undiagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(0, 3, 2, 1)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(2, 1, 0, 3)); } INLINE __m128i blend_epi16(__m128i a, __m128i b, const int16_t imm8) { const __m128i bits = _mm_set_epi16(0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01); __m128i mask = _mm_set1_epi16(imm8); mask = _mm_and_si128(mask, bits); mask = _mm_cmpeq_epi16(mask, bits); return _mm_or_si128(_mm_and_si128(mask, b), _mm_andnot_si128(mask, a)); } INLINE void compress_pre(__m128i rows[4], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { rows[0] = loadu((uint8_t *)&cv[0]); rows[1] = loadu((uint8_t *)&cv[4]); rows[2] = set4(IV[0], IV[1], IV[2], IV[3]); rows[3] = set4(counter_low(counter), counter_high(counter), (uint32_t)block_len, (uint32_t)flags); __m128i m0 = loadu(&block[sizeof(__m128i) * 0]); __m128i m1 = loadu(&block[sizeof(__m128i) * 1]); __m128i m2 = loadu(&block[sizeof(__m128i) * 2]); __m128i m3 = loadu(&block[sizeof(__m128i) * 3]); __m128i t0, t1, t2, t3, tt; // Round 1. The first round permutes the message words from the original // input order, into the groups that get mixed in parallel. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(2, 0, 2, 0)); // 6 4 2 0 g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 3, 1)); // 7 5 3 1 g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(2, 0, 2, 0)); // 14 12 10 8 t2 = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2, 1, 0, 3)); // 12 10 8 14 g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 1, 3, 1)); // 15 13 11 9 t3 = _mm_shuffle_epi32(t3, _MM_SHUFFLE(2, 1, 0, 3)); // 13 11 9 15 g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 2. This round and all following rounds apply a fixed permutation // to the message words from the round before. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 3 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 4 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 5 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 6 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 7 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); } void blake3_compress_in_place_sse2(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu(xorv(rows[0], rows[2]), (uint8_t *)&cv[0]); storeu(xorv(rows[1], rows[3]), (uint8_t *)&cv[4]); } void blake3_compress_xof_sse2(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu(xorv(rows[0], rows[2]), &out[0]); storeu(xorv(rows[1], rows[3]), &out[16]); storeu(xorv(rows[2], loadu((uint8_t *)&cv[0])), &out[32]); storeu(xorv(rows[3], loadu((uint8_t *)&cv[4])), &out[48]); } INLINE void round_fn(__m128i v[16], __m128i m[16], size_t r) { v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[15] = rot16(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot12(v[4]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[15] = rot8(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot7(v[4]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot16(v[15]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[4] = rot12(v[4]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot8(v[15]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[4] = rot7(v[4]); } INLINE void transpose_vecs(__m128i vecs[DEGREE]) { // Interleave 32-bit lanes. The low unpack is lanes 00/11 and the high is // 22/33. Note that this doesn't split the vector into two lanes, as the // AVX2 counterparts do. __m128i ab_01 = _mm_unpacklo_epi32(vecs[0], vecs[1]); __m128i ab_23 = _mm_unpackhi_epi32(vecs[0], vecs[1]); __m128i cd_01 = _mm_unpacklo_epi32(vecs[2], vecs[3]); __m128i cd_23 = _mm_unpackhi_epi32(vecs[2], vecs[3]); // Interleave 64-bit lanes. __m128i abcd_0 = _mm_unpacklo_epi64(ab_01, cd_01); __m128i abcd_1 = _mm_unpackhi_epi64(ab_01, cd_01); __m128i abcd_2 = _mm_unpacklo_epi64(ab_23, cd_23); __m128i abcd_3 = _mm_unpackhi_epi64(ab_23, cd_23); vecs[0] = abcd_0; vecs[1] = abcd_1; vecs[2] = abcd_2; vecs[3] = abcd_3; } INLINE void transpose_msg_vecs(const uint8_t *const *inputs, size_t block_offset, __m128i out[16]) { out[0] = loadu(&inputs[0][block_offset + 0 * sizeof(__m128i)]); out[1] = loadu(&inputs[1][block_offset + 0 * sizeof(__m128i)]); out[2] = loadu(&inputs[2][block_offset + 0 * sizeof(__m128i)]); out[3] = loadu(&inputs[3][block_offset + 0 * sizeof(__m128i)]); out[4] = loadu(&inputs[0][block_offset + 1 * sizeof(__m128i)]); out[5] = loadu(&inputs[1][block_offset + 1 * sizeof(__m128i)]); out[6] = loadu(&inputs[2][block_offset + 1 * sizeof(__m128i)]); out[7] = loadu(&inputs[3][block_offset + 1 * sizeof(__m128i)]); out[8] = loadu(&inputs[0][block_offset + 2 * sizeof(__m128i)]); out[9] = loadu(&inputs[1][block_offset + 2 * sizeof(__m128i)]); out[10] = loadu(&inputs[2][block_offset + 2 * sizeof(__m128i)]); out[11] = loadu(&inputs[3][block_offset + 2 * sizeof(__m128i)]); out[12] = loadu(&inputs[0][block_offset + 3 * sizeof(__m128i)]); out[13] = loadu(&inputs[1][block_offset + 3 * sizeof(__m128i)]); out[14] = loadu(&inputs[2][block_offset + 3 * sizeof(__m128i)]); out[15] = loadu(&inputs[3][block_offset + 3 * sizeof(__m128i)]); for (size_t i = 0; i < 4; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs(&out[0]); transpose_vecs(&out[4]); transpose_vecs(&out[8]); transpose_vecs(&out[12]); } INLINE void load_counters(uint64_t counter, bool increment_counter, __m128i *out_lo, __m128i *out_hi) { const __m128i mask = _mm_set1_epi32(-(int32_t)increment_counter); const __m128i add0 = _mm_set_epi32(3, 2, 1, 0); const __m128i add1 = _mm_and_si128(mask, add0); __m128i l = _mm_add_epi32(_mm_set1_epi32((int32_t)counter), add1); __m128i carry = _mm_cmpgt_epi32(_mm_xor_si128(add1, _mm_set1_epi32(0x80000000)), _mm_xor_si128( l, _mm_set1_epi32(0x80000000))); __m128i h = _mm_sub_epi32(_mm_set1_epi32((int32_t)(counter >> 32)), carry); *out_lo = l; *out_hi = h; } static void blake3_hash4_sse2(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m128i h_vecs[8] = { set1(key[0]), set1(key[1]), set1(key[2]), set1(key[3]), set1(key[4]), set1(key[5]), set1(key[6]), set1(key[7]), }; __m128i counter_low_vec, counter_high_vec; load_counters(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m128i block_len_vec = set1(BLAKE3_BLOCK_LEN); __m128i block_flags_vec = set1(block_flags); __m128i msg_vecs[16]; transpose_msg_vecs(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m128i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1(IV[0]), set1(IV[1]), set1(IV[2]), set1(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn(v, msg_vecs, 0); round_fn(v, msg_vecs, 1); round_fn(v, msg_vecs, 2); round_fn(v, msg_vecs, 3); round_fn(v, msg_vecs, 4); round_fn(v, msg_vecs, 5); round_fn(v, msg_vecs, 6); h_vecs[0] = xorv(v[0], v[8]); h_vecs[1] = xorv(v[1], v[9]); h_vecs[2] = xorv(v[2], v[10]); h_vecs[3] = xorv(v[3], v[11]); h_vecs[4] = xorv(v[4], v[12]); h_vecs[5] = xorv(v[5], v[13]); h_vecs[6] = xorv(v[6], v[14]); h_vecs[7] = xorv(v[7], v[15]); block_flags = flags; } transpose_vecs(&h_vecs[0]); transpose_vecs(&h_vecs[4]); // The first four vecs now contain the first half of each output, and the // second four vecs contain the second half of each output. storeu(h_vecs[0], &out[0 * sizeof(__m128i)]); storeu(h_vecs[4], &out[1 * sizeof(__m128i)]); storeu(h_vecs[1], &out[2 * sizeof(__m128i)]); storeu(h_vecs[5], &out[3 * sizeof(__m128i)]); storeu(h_vecs[2], &out[4 * sizeof(__m128i)]); storeu(h_vecs[6], &out[5 * sizeof(__m128i)]); storeu(h_vecs[3], &out[6 * sizeof(__m128i)]); storeu(h_vecs[7], &out[7 * sizeof(__m128i)]); } INLINE void hash_one_sse2(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_sse2(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } memcpy(out, cv, BLAKE3_OUT_LEN); } void blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= DEGREE) { blake3_hash4_sse2(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += DEGREE; } inputs += DEGREE; num_inputs -= DEGREE; out = &out[DEGREE * BLAKE3_OUT_LEN]; } while (num_inputs > 0) { hash_one_sse2(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/blake3/c/blake3_sse41.c ================================================ #include "blake3_impl.h" #include #define DEGREE 4 #define _mm_shuffle_ps2(a, b, c) \ (_mm_castps_si128( \ _mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), (c)))) INLINE __m128i loadu(const uint8_t src[16]) { return _mm_loadu_si128((const __m128i *)src); } INLINE void storeu(__m128i src, uint8_t dest[16]) { _mm_storeu_si128((__m128i *)dest, src); } INLINE __m128i addv(__m128i a, __m128i b) { return _mm_add_epi32(a, b); } // Note that clang-format doesn't like the name "xor" for some reason. INLINE __m128i xorv(__m128i a, __m128i b) { return _mm_xor_si128(a, b); } INLINE __m128i set1(uint32_t x) { return _mm_set1_epi32((int32_t)x); } INLINE __m128i set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { return _mm_setr_epi32((int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d); } INLINE __m128i rot16(__m128i x) { return _mm_shuffle_epi8( x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)); } INLINE __m128i rot12(__m128i x) { return xorv(_mm_srli_epi32(x, 12), _mm_slli_epi32(x, 32 - 12)); } INLINE __m128i rot8(__m128i x) { return _mm_shuffle_epi8( x, _mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)); } INLINE __m128i rot7(__m128i x) { return xorv(_mm_srli_epi32(x, 7), _mm_slli_epi32(x, 32 - 7)); } INLINE void g1(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = addv(addv(*row0, m), *row1); *row3 = xorv(*row3, *row0); *row3 = rot16(*row3); *row2 = addv(*row2, *row3); *row1 = xorv(*row1, *row2); *row1 = rot12(*row1); } INLINE void g2(__m128i *row0, __m128i *row1, __m128i *row2, __m128i *row3, __m128i m) { *row0 = addv(addv(*row0, m), *row1); *row3 = xorv(*row3, *row0); *row3 = rot8(*row3); *row2 = addv(*row2, *row3); *row1 = xorv(*row1, *row2); *row1 = rot7(*row1); } // Note the optimization here of leaving row1 as the unrotated row, rather than // row0. All the message loads below are adjusted to compensate for this. See // discussion at https://github.com/sneves/blake2-avx2/pull/4 INLINE void diagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(2, 1, 0, 3)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(0, 3, 2, 1)); } INLINE void undiagonalize(__m128i *row0, __m128i *row2, __m128i *row3) { *row0 = _mm_shuffle_epi32(*row0, _MM_SHUFFLE(0, 3, 2, 1)); *row3 = _mm_shuffle_epi32(*row3, _MM_SHUFFLE(1, 0, 3, 2)); *row2 = _mm_shuffle_epi32(*row2, _MM_SHUFFLE(2, 1, 0, 3)); } INLINE void compress_pre(__m128i rows[4], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { rows[0] = loadu((uint8_t *)&cv[0]); rows[1] = loadu((uint8_t *)&cv[4]); rows[2] = set4(IV[0], IV[1], IV[2], IV[3]); rows[3] = set4(counter_low(counter), counter_high(counter), (uint32_t)block_len, (uint32_t)flags); __m128i m0 = loadu(&block[sizeof(__m128i) * 0]); __m128i m1 = loadu(&block[sizeof(__m128i) * 1]); __m128i m2 = loadu(&block[sizeof(__m128i) * 2]); __m128i m3 = loadu(&block[sizeof(__m128i) * 3]); __m128i t0, t1, t2, t3, tt; // Round 1. The first round permutes the message words from the original // input order, into the groups that get mixed in parallel. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(2, 0, 2, 0)); // 6 4 2 0 g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 3, 1)); // 7 5 3 1 g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(2, 0, 2, 0)); // 14 12 10 8 t2 = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2, 1, 0, 3)); // 12 10 8 14 g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 1, 3, 1)); // 15 13 11 9 t3 = _mm_shuffle_epi32(t3, _MM_SHUFFLE(2, 1, 0, 3)); // 13 11 9 15 g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 2. This round and all following rounds apply a fixed permutation // to the message words from the round before. t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 3 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 4 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 5 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 6 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); m0 = t0; m1 = t1; m2 = t2; m3 = t3; // Round 7 t0 = _mm_shuffle_ps2(m0, m1, _MM_SHUFFLE(3, 1, 1, 2)); t0 = _mm_shuffle_epi32(t0, _MM_SHUFFLE(0, 3, 2, 1)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t0); t1 = _mm_shuffle_ps2(m2, m3, _MM_SHUFFLE(3, 3, 2, 2)); tt = _mm_shuffle_epi32(m0, _MM_SHUFFLE(0, 0, 3, 3)); t1 = _mm_blend_epi16(tt, t1, 0xCC); g2(&rows[0], &rows[1], &rows[2], &rows[3], t1); diagonalize(&rows[0], &rows[2], &rows[3]); t2 = _mm_unpacklo_epi64(m3, m1); tt = _mm_blend_epi16(t2, m2, 0xC0); t2 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(1, 3, 2, 0)); g1(&rows[0], &rows[1], &rows[2], &rows[3], t2); t3 = _mm_unpackhi_epi32(m1, m3); tt = _mm_unpacklo_epi32(m2, t3); t3 = _mm_shuffle_epi32(tt, _MM_SHUFFLE(0, 1, 3, 2)); g2(&rows[0], &rows[1], &rows[2], &rows[3], t3); undiagonalize(&rows[0], &rows[2], &rows[3]); } void blake3_compress_in_place_sse41(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu(xorv(rows[0], rows[2]), (uint8_t *)&cv[0]); storeu(xorv(rows[1], rows[3]), (uint8_t *)&cv[4]); } void blake3_compress_xof_sse41(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { __m128i rows[4]; compress_pre(rows, cv, block, block_len, counter, flags); storeu(xorv(rows[0], rows[2]), &out[0]); storeu(xorv(rows[1], rows[3]), &out[16]); storeu(xorv(rows[2], loadu((uint8_t *)&cv[0])), &out[32]); storeu(xorv(rows[3], loadu((uint8_t *)&cv[4])), &out[48]); } INLINE void round_fn(__m128i v[16], __m128i m[16], size_t r) { v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][0]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][2]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][4]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][6]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[15] = rot16(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot12(v[4]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][1]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][3]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][5]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][7]]); v[0] = addv(v[0], v[4]); v[1] = addv(v[1], v[5]); v[2] = addv(v[2], v[6]); v[3] = addv(v[3], v[7]); v[12] = xorv(v[12], v[0]); v[13] = xorv(v[13], v[1]); v[14] = xorv(v[14], v[2]); v[15] = xorv(v[15], v[3]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[15] = rot8(v[15]); v[8] = addv(v[8], v[12]); v[9] = addv(v[9], v[13]); v[10] = addv(v[10], v[14]); v[11] = addv(v[11], v[15]); v[4] = xorv(v[4], v[8]); v[5] = xorv(v[5], v[9]); v[6] = xorv(v[6], v[10]); v[7] = xorv(v[7], v[11]); v[4] = rot7(v[4]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][8]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][10]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][12]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][14]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot16(v[15]); v[12] = rot16(v[12]); v[13] = rot16(v[13]); v[14] = rot16(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot12(v[5]); v[6] = rot12(v[6]); v[7] = rot12(v[7]); v[4] = rot12(v[4]); v[0] = addv(v[0], m[(size_t)MSG_SCHEDULE[r][9]]); v[1] = addv(v[1], m[(size_t)MSG_SCHEDULE[r][11]]); v[2] = addv(v[2], m[(size_t)MSG_SCHEDULE[r][13]]); v[3] = addv(v[3], m[(size_t)MSG_SCHEDULE[r][15]]); v[0] = addv(v[0], v[5]); v[1] = addv(v[1], v[6]); v[2] = addv(v[2], v[7]); v[3] = addv(v[3], v[4]); v[15] = xorv(v[15], v[0]); v[12] = xorv(v[12], v[1]); v[13] = xorv(v[13], v[2]); v[14] = xorv(v[14], v[3]); v[15] = rot8(v[15]); v[12] = rot8(v[12]); v[13] = rot8(v[13]); v[14] = rot8(v[14]); v[10] = addv(v[10], v[15]); v[11] = addv(v[11], v[12]); v[8] = addv(v[8], v[13]); v[9] = addv(v[9], v[14]); v[5] = xorv(v[5], v[10]); v[6] = xorv(v[6], v[11]); v[7] = xorv(v[7], v[8]); v[4] = xorv(v[4], v[9]); v[5] = rot7(v[5]); v[6] = rot7(v[6]); v[7] = rot7(v[7]); v[4] = rot7(v[4]); } INLINE void transpose_vecs(__m128i vecs[DEGREE]) { // Interleave 32-bit lanes. The low unpack is lanes 00/11 and the high is // 22/33. Note that this doesn't split the vector into two lanes, as the // AVX2 counterparts do. __m128i ab_01 = _mm_unpacklo_epi32(vecs[0], vecs[1]); __m128i ab_23 = _mm_unpackhi_epi32(vecs[0], vecs[1]); __m128i cd_01 = _mm_unpacklo_epi32(vecs[2], vecs[3]); __m128i cd_23 = _mm_unpackhi_epi32(vecs[2], vecs[3]); // Interleave 64-bit lanes. __m128i abcd_0 = _mm_unpacklo_epi64(ab_01, cd_01); __m128i abcd_1 = _mm_unpackhi_epi64(ab_01, cd_01); __m128i abcd_2 = _mm_unpacklo_epi64(ab_23, cd_23); __m128i abcd_3 = _mm_unpackhi_epi64(ab_23, cd_23); vecs[0] = abcd_0; vecs[1] = abcd_1; vecs[2] = abcd_2; vecs[3] = abcd_3; } INLINE void transpose_msg_vecs(const uint8_t *const *inputs, size_t block_offset, __m128i out[16]) { out[0] = loadu(&inputs[0][block_offset + 0 * sizeof(__m128i)]); out[1] = loadu(&inputs[1][block_offset + 0 * sizeof(__m128i)]); out[2] = loadu(&inputs[2][block_offset + 0 * sizeof(__m128i)]); out[3] = loadu(&inputs[3][block_offset + 0 * sizeof(__m128i)]); out[4] = loadu(&inputs[0][block_offset + 1 * sizeof(__m128i)]); out[5] = loadu(&inputs[1][block_offset + 1 * sizeof(__m128i)]); out[6] = loadu(&inputs[2][block_offset + 1 * sizeof(__m128i)]); out[7] = loadu(&inputs[3][block_offset + 1 * sizeof(__m128i)]); out[8] = loadu(&inputs[0][block_offset + 2 * sizeof(__m128i)]); out[9] = loadu(&inputs[1][block_offset + 2 * sizeof(__m128i)]); out[10] = loadu(&inputs[2][block_offset + 2 * sizeof(__m128i)]); out[11] = loadu(&inputs[3][block_offset + 2 * sizeof(__m128i)]); out[12] = loadu(&inputs[0][block_offset + 3 * sizeof(__m128i)]); out[13] = loadu(&inputs[1][block_offset + 3 * sizeof(__m128i)]); out[14] = loadu(&inputs[2][block_offset + 3 * sizeof(__m128i)]); out[15] = loadu(&inputs[3][block_offset + 3 * sizeof(__m128i)]); for (size_t i = 0; i < 4; ++i) { _mm_prefetch((const char *)&inputs[i][block_offset + 256], _MM_HINT_T0); } transpose_vecs(&out[0]); transpose_vecs(&out[4]); transpose_vecs(&out[8]); transpose_vecs(&out[12]); } INLINE void load_counters(uint64_t counter, bool increment_counter, __m128i *out_lo, __m128i *out_hi) { const __m128i mask = _mm_set1_epi32(-(int32_t)increment_counter); const __m128i add0 = _mm_set_epi32(3, 2, 1, 0); const __m128i add1 = _mm_and_si128(mask, add0); __m128i l = _mm_add_epi32(_mm_set1_epi32((int32_t)counter), add1); __m128i carry = _mm_cmpgt_epi32(_mm_xor_si128(add1, _mm_set1_epi32(0x80000000)), _mm_xor_si128( l, _mm_set1_epi32(0x80000000))); __m128i h = _mm_sub_epi32(_mm_set1_epi32((int32_t)(counter >> 32)), carry); *out_lo = l; *out_hi = h; } static void blake3_hash4_sse41(const uint8_t *const *inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { __m128i h_vecs[8] = { set1(key[0]), set1(key[1]), set1(key[2]), set1(key[3]), set1(key[4]), set1(key[5]), set1(key[6]), set1(key[7]), }; __m128i counter_low_vec, counter_high_vec; load_counters(counter, increment_counter, &counter_low_vec, &counter_high_vec); uint8_t block_flags = flags | flags_start; for (size_t block = 0; block < blocks; block++) { if (block + 1 == blocks) { block_flags |= flags_end; } __m128i block_len_vec = set1(BLAKE3_BLOCK_LEN); __m128i block_flags_vec = set1(block_flags); __m128i msg_vecs[16]; transpose_msg_vecs(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs); __m128i v[16] = { h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7], set1(IV[0]), set1(IV[1]), set1(IV[2]), set1(IV[3]), counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec, }; round_fn(v, msg_vecs, 0); round_fn(v, msg_vecs, 1); round_fn(v, msg_vecs, 2); round_fn(v, msg_vecs, 3); round_fn(v, msg_vecs, 4); round_fn(v, msg_vecs, 5); round_fn(v, msg_vecs, 6); h_vecs[0] = xorv(v[0], v[8]); h_vecs[1] = xorv(v[1], v[9]); h_vecs[2] = xorv(v[2], v[10]); h_vecs[3] = xorv(v[3], v[11]); h_vecs[4] = xorv(v[4], v[12]); h_vecs[5] = xorv(v[5], v[13]); h_vecs[6] = xorv(v[6], v[14]); h_vecs[7] = xorv(v[7], v[15]); block_flags = flags; } transpose_vecs(&h_vecs[0]); transpose_vecs(&h_vecs[4]); // The first four vecs now contain the first half of each output, and the // second four vecs contain the second half of each output. storeu(h_vecs[0], &out[0 * sizeof(__m128i)]); storeu(h_vecs[4], &out[1 * sizeof(__m128i)]); storeu(h_vecs[1], &out[2 * sizeof(__m128i)]); storeu(h_vecs[5], &out[3 * sizeof(__m128i)]); storeu(h_vecs[2], &out[4 * sizeof(__m128i)]); storeu(h_vecs[6], &out[5 * sizeof(__m128i)]); storeu(h_vecs[3], &out[6 * sizeof(__m128i)]); storeu(h_vecs[7], &out[7 * sizeof(__m128i)]); } INLINE void hash_one_sse41(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_sse41(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } memcpy(out, cv, BLAKE3_OUT_LEN); } void blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs >= DEGREE) { blake3_hash4_sse41(inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += DEGREE; } inputs += DEGREE; num_inputs -= DEGREE; out = &out[DEGREE * BLAKE3_OUT_LEN]; } while (num_inputs > 0) { hash_one_sse41(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } ================================================ FILE: src/third_party/martins_hash/md5.h ================================================ #pragma once // https://www.rfc-editor.org/rfc/rfc1321.html #include #include // // interface // #define MD5_DIGEST_SIZE 16 #define MD5_BLOCK_SIZE 64 typedef struct { uint8_t buffer[MD5_BLOCK_SIZE]; uint64_t count; uint32_t state[4]; } md5_ctx; static inline void md5_init(md5_ctx* ctx); static inline void md5_update(md5_ctx* ctx, const void* data, size_t size); static inline void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE]); // // implementation // #include // memcpy, memset #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wcast-align" # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" # pragma clang diagnostic ignored "-Wlanguage-extension-token" # pragma clang diagnostic ignored "-Wdeclaration-after-statement" #endif #if defined(__clang__) # define MD5_ROL32(x,n) __builtin_rotateleft32(x, n) #elif defined(_MSC_VER) # include # define MD5_ROL32(x,n) _rotl(x, n) #else # define MD5_ROL32(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif #if defined(_MSC_VER) # define MD5_GET32LE(ptr) *((const __unaligned uint32_t*)(ptr)) # define MD5_SET32LE(ptr,x) *((__unaligned uint32_t*)(ptr)) = (x) # define MD5_SET64LE(ptr,x) *((__unaligned uint64_t*)(ptr)) = (x) #else # define MD5_GET32LE(ptr) \ ( \ ((ptr)[0] << 0) | \ ((ptr)[1] << 8) | \ ((ptr)[2] << 16) | \ ((ptr)[3] << 24) \ ) # define MD5_SET32LE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 0); \ (ptr)[1] = (uint8_t)((x) >> 8); \ (ptr)[2] = (uint8_t)((x) >> 16); \ (ptr)[3] = (uint8_t)((x) >> 24); \ } \ while (0) # define MD5_SET64LE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 0); \ (ptr)[1] = (uint8_t)((x) >> 8); \ (ptr)[2] = (uint8_t)((x) >> 16); \ (ptr)[3] = (uint8_t)((x) >> 24); \ (ptr)[4] = (uint8_t)((x) >> 32); \ (ptr)[5] = (uint8_t)((x) >> 40); \ (ptr)[6] = (uint8_t)((x) >> 48); \ (ptr)[7] = (uint8_t)((x) >> 56); \ } \ while (0) #endif // MD5_COMPILER_BARRIER forces clang to do better codegen without spilling registers to stack too much #if defined(__clang__) || defined(__GNUC__) # define MD5_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") #else # define MD5_COMPILER_BARRIER() #endif #if defined(__x86_64__) || defined(_M_AMD64) #if defined(__clang__) || defined(__GNUC__) # include # define MD5_TARGET(str) __attribute__((target(str))) # define MD5_CPUID_EX(x, y, info) __cpuid_count(x, y, info[0], info[1], info[2], info[3]) # define MD5_ANDN_U32(x,y) (~(x) & (y)) #else # include # define MD5_TARGET(str) # define MD5_CPUID_EX(x, y, info) __cpuidex(info, x, y) # define MD5_ANDN_U32(x,y) _andn_u32(x,y) #endif #if defined(__clang__) # define MD5_RORX_U32(x,n) __builtin_rotateright32(x, n) #elif defined(_MSC_VER) # define MD5_RORX_U32(x,n) _rorx_u32(x,n) #else # define MD5_RORX_U32(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) #endif #define MD5_CPUID_INIT (1 << 0) #define MD5_CPUID_BMI2 (1 << 1) static inline int md5_cpuid(void) { static int cpuid; int result = cpuid; if (result == 0) { int info[4]; MD5_CPUID_EX(7, 0, info); int has_bmi = info[1] & (1 << 3); int has_bmi2 = info[1] & (1 << 8); result |= MD5_CPUID_INIT; if (has_bmi && has_bmi2) { result |= MD5_CPUID_BMI2; } cpuid = result; } #if defined(MD5_CPUID_MASK) result &= MD5_CPUID_MASK; #endif return result; } MD5_TARGET("bmi,bmi2,tune=znver1") static void md5_process_bmi2(uint32_t* state, const uint8_t* block, size_t count) { // "tune=znver1" allows clang to use LEA with [reg+reg+imm] operand which helps performance on modern CPU's // -1 in I will get folded together with constant k #define F(x,y,z) (x & y) + MD5_ANDN_U32(x, z) #define G(x,y,z) (x & z) + MD5_ANDN_U32(z, y) #define H(x,y,z) (x ^ y ^ z) #define I(x,y,z) 0 - 1 - (y ^ MD5_ANDN_U32(x, z)) #define X(i) MD5_GET32LE(block + i*sizeof(uint32_t)) #define ROUND(F, a, b, c, d, x, k, r) do { \ a += (k) + F(b, c, d) + (x); \ a = MD5_RORX_U32(a, 32-r) + b; \ } while (0) #define QROUND_F(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(F, a, b, c, d, X(x0), k0, 7); \ ROUND(F, d, a, b, c, X(x1), k1, 12); \ ROUND(F, c, d, a, b, X(x2), k2, 17); \ ROUND(F, b, c, d, a, X(x3), k3, 22); \ } while (0) #define QROUND_G(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(G, a, b, c, d, X(x0), k0, 5); \ ROUND(G, d, a, b, c, X(x1), k1, 9); \ ROUND(G, c, d, a, b, X(x2), k2, 14); \ ROUND(G, b, c, d, a, X(x3), k3, 20); \ } while (0) #define QROUND_H(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(H, a, b, c, d, X(x0), k0, 4); \ ROUND(H, d, a, b, c, X(x1), k1, 11); \ ROUND(H, c, d, a, b, X(x2), k2, 16); \ ROUND(H, b, c, d, a, X(x3), k3, 23); \ } while (0) #define QROUND_I(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(I, a, b, c, d, X(x0), k0, 6); \ ROUND(I, d, a, b, c, X(x1), k1, 10); \ ROUND(I, c, d, a, b, X(x2), k2, 15); \ ROUND(I, b, c, d, a, X(x3), k3, 21); \ } while (0) uint32_t a = state[0]; uint32_t b = state[1]; uint32_t c = state[2]; uint32_t d = state[3]; do { uint32_t last_a = a; uint32_t last_b = b; uint32_t last_c = c; uint32_t last_d = d; QROUND_F( 0, 1, 2, 3, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee); QROUND_F( 4, 5, 6, 7, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501); QROUND_F( 8, 9, 10, 11, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be); QROUND_F(12, 13, 14, 15, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821); MD5_COMPILER_BARRIER(); QROUND_G( 1, 6, 11, 0, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa); QROUND_G( 5, 10, 15, 4, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8); QROUND_G( 9, 14, 3, 8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed); QROUND_G(13, 2, 7, 12, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a); MD5_COMPILER_BARRIER(); QROUND_H( 5, 8, 11, 14, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c); QROUND_H( 1, 4, 7, 10, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70); QROUND_H(13, 0, 3, 6, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05); QROUND_H( 9, 12, 15, 2, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665); MD5_COMPILER_BARRIER(); QROUND_I( 0, 7, 14, 5, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039); QROUND_I(12, 3, 10, 1, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1); QROUND_I( 8, 15, 6, 13, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1); QROUND_I( 4, 11, 2, 9, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391); MD5_COMPILER_BARRIER(); a += last_a; b += last_b; c += last_c; d += last_d; block += MD5_BLOCK_SIZE; } while (--count); state[0] = a; state[1] = b; state[2] = c; state[3] = d; #undef QROUND_F #undef QROUND_G #undef QROUND_H #undef QROUND_I #undef ROUND #undef X #undef F #undef G #undef H #undef I } #endif // defined(__x86_64__) || defined(_M_AMD64) static void md5_process(uint32_t* state, const uint8_t* block, size_t count) { #if defined(__x86_64__) || defined(_M_AMD64) int cpuid = md5_cpuid(); if (cpuid & MD5_CPUID_BMI2) { md5_process_bmi2(state, block, count); return; } #endif // F function uses 3 operations instead of 4 when "bit select" instruction is not available // (x & y) | (~x & z) == (z ^ (x & (y ^ z)) // G function uses + instead of | for better ILP // #define F(x,y,z) ((x & y) | (~x & z)) #define F(x,y,z) (z ^ (x & (y ^ z))) #define G(x,y,z) (x & z) + (y & ~z) #define H(x,y,z) (x ^ y ^ z) #define I(x,y,z) (y ^ (x | ~z)) #define X(i) MD5_GET32LE(block + i*sizeof(uint32_t)) #define ROUND(F, a, b, c, d, x, k, r) do { \ a += F(b, c, d) + (x) + (k); \ a = MD5_ROL32(a, r) + b; \ } while (0) #define QROUND_F(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(F, a, b, c, d, X(x0), k0, 7); \ ROUND(F, d, a, b, c, X(x1), k1, 12); \ ROUND(F, c, d, a, b, X(x2), k2, 17); \ ROUND(F, b, c, d, a, X(x3), k3, 22); \ } while (0) #define QROUND_G(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(G, a, b, c, d, X(x0), k0, 5); \ ROUND(G, d, a, b, c, X(x1), k1, 9); \ ROUND(G, c, d, a, b, X(x2), k2, 14); \ ROUND(G, b, c, d, a, X(x3), k3, 20); \ } while (0) #define QROUND_H(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(H, a, b, c, d, X(x0), k0, 4); \ ROUND(H, d, a, b, c, X(x1), k1, 11); \ ROUND(H, c, d, a, b, X(x2), k2, 16); \ ROUND(H, b, c, d, a, X(x3), k3, 23); \ } while (0) #define QROUND_I(x0, x1, x2, x3, k0, k1, k2, k3) do { \ ROUND(I, a, b, c, d, X(x0), k0, 6); \ ROUND(I, d, a, b, c, X(x1), k1, 10); \ ROUND(I, c, d, a, b, X(x2), k2, 15); \ ROUND(I, b, c, d, a, X(x3), k3, 21); \ } while (0) uint32_t a = state[0]; uint32_t b = state[1]; uint32_t c = state[2]; uint32_t d = state[3]; do { uint32_t last_a = a; uint32_t last_b = b; uint32_t last_c = c; uint32_t last_d = d; QROUND_F( 0, 1, 2, 3, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee); QROUND_F( 4, 5, 6, 7, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501); QROUND_F( 8, 9, 10, 11, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be); QROUND_F(12, 13, 14, 15, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821); MD5_COMPILER_BARRIER(); QROUND_G( 1, 6, 11, 0, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa); QROUND_G( 5, 10, 15, 4, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8); QROUND_G( 9, 14, 3, 8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed); QROUND_G(13, 2, 7, 12, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a); MD5_COMPILER_BARRIER(); QROUND_H( 5, 8, 11, 14, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c); QROUND_H( 1, 4, 7, 10, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70); QROUND_H(13, 0, 3, 6, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05); QROUND_H( 9, 12, 15, 2, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665); MD5_COMPILER_BARRIER(); QROUND_I( 0, 7, 14, 5, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039); QROUND_I(12, 3, 10, 1, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1); QROUND_I( 8, 15, 6, 13, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1); QROUND_I( 4, 11, 2, 9, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391); MD5_COMPILER_BARRIER(); a += last_a; b += last_b; c += last_c; d += last_d; block += MD5_BLOCK_SIZE; } while (--count); state[0] = a; state[1] = b; state[2] = c; state[3] = d; #undef QROUND_F #undef QROUND_G #undef QROUND_H #undef QROUND_I #undef ROUND #undef X #undef F #undef G #undef H #undef I } void md5_init(md5_ctx* ctx) { ctx->count = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; } void md5_update(md5_ctx* ctx, const void* data, size_t size) { const uint8_t* buffer = (const uint8_t*)data; size_t pending = ctx->count % MD5_BLOCK_SIZE; ctx->count += size; size_t available = MD5_BLOCK_SIZE - pending; if (pending && size >= available) { memcpy(ctx->buffer + pending, buffer, available); md5_process(ctx->state, ctx->buffer, 1); buffer += available; size -= available; pending = 0; } size_t count = size / MD5_BLOCK_SIZE; if (count) { md5_process(ctx->state, buffer, count); buffer += count * MD5_BLOCK_SIZE; size -= count * MD5_BLOCK_SIZE; } memcpy(ctx->buffer + pending, buffer, size); } void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE]) { uint64_t count = ctx->count; uint64_t bitcount = count * 8; size_t pending = count % MD5_BLOCK_SIZE; size_t blocks = pending < MD5_BLOCK_SIZE - sizeof(bitcount) ? 1 : 2; ctx->buffer[pending++] = 0x80; uint8_t padding[2 * MD5_BLOCK_SIZE]; memcpy(padding, ctx->buffer, MD5_BLOCK_SIZE); memset(padding + pending, 0, MD5_BLOCK_SIZE); MD5_SET64LE(padding + blocks * MD5_BLOCK_SIZE - sizeof(bitcount), bitcount); md5_process(ctx->state, padding, blocks); for (size_t i=0; i<4; i++) { MD5_SET32LE(digest + i*sizeof(uint32_t), ctx->state[i]); } } #if defined(__clang__) # pragma clang diagnostic pop #endif ================================================ FILE: src/third_party/martins_hash/sha1.h ================================================ #pragma once // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf #include #include // // interface // #define SHA1_DIGEST_SIZE 20 #define SHA1_BLOCK_SIZE 64 typedef struct { uint8_t buffer[SHA1_BLOCK_SIZE]; uint64_t count; uint32_t state[5]; } sha1_ctx; static inline void sha1_init(sha1_ctx* ctx); static inline void sha1_update(sha1_ctx* ctx, const void* data, size_t size); static inline void sha1_finish(sha1_ctx* ctx, uint8_t digest[SHA1_DIGEST_SIZE]); // // implementation // #include // memcpy, memset #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wcast-align" # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" # pragma clang diagnostic ignored "-Wlanguage-extension-token" # pragma clang diagnostic ignored "-Wdeclaration-after-statement" #elif defined(_MSC_VER) # pragma warning (push) # pragma warning (disable : 4127) #endif #if defined(__clang__) # define SHA1_ROL32(x,n) __builtin_rotateleft32(x, n) #elif defined(_MSC_VER) # include # define SHA1_ROL32(x,n) _rotl(x, n) #else # define SHA1_ROL32(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif #if defined(_MSC_VER) # include # define SHA1_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) ) # define SHA1_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x) # define SHA1_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x) #else # define SHA1_GET32BE(ptr) \ ( \ ((ptr)[0] << 24) | \ ((ptr)[1] << 16) | \ ((ptr)[2] << 8) | \ ((ptr)[3] << 0) \ ) # define SHA1_SET32BE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 24); \ (ptr)[1] = (uint8_t)((x) >> 16); \ (ptr)[2] = (uint8_t)((x) >> 8); \ (ptr)[3] = (uint8_t)((x) >> 0); \ } \ while (0) # define SHA1_SET64BE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 56); \ (ptr)[1] = (uint8_t)((x) >> 48); \ (ptr)[2] = (uint8_t)((x) >> 40); \ (ptr)[3] = (uint8_t)((x) >> 32); \ (ptr)[4] = (uint8_t)((x) >> 24); \ (ptr)[5] = (uint8_t)((x) >> 16); \ (ptr)[6] = (uint8_t)((x) >> 8); \ (ptr)[7] = (uint8_t)((x) >> 0); \ } \ while (0) #endif #if defined(__x86_64__) || defined(_M_AMD64) #include // SSSE3 #include // SHANI #if defined(__clang__) || defined(__GNUC__) # include # define SHA1_TARGET(str) __attribute__((target(str))) # define SHA1_CPUID(x, info) __cpuid(x, info[0], info[1], info[2], info[3]) # define SHA1_CPUID_EX(x, y, info) __cpuid_count(x, y, info[0], info[1], info[2], info[3]) #else # include # define SHA1_TARGET(str) # define SHA1_CPUID(x, info) __cpuid(info, x) # define SHA1_CPUID_EX(x, y, info) __cpuidex(info, x, y) #endif #define SHA1_CPUID_INIT (1 << 0) #define SHA1_CPUID_SHANI (1 << 1) static inline int sha1_cpuid(void) { static int cpuid; int result = cpuid; if (result == 0) { int info[4]; SHA1_CPUID(1, info); int has_ssse3 = info[3] & (1 << 9); SHA1_CPUID_EX(7, 0, info); int has_shani = info[1] & (1 << 29); result |= SHA1_CPUID_INIT; if (has_ssse3 && has_shani) { result |= SHA1_CPUID_SHANI; } cpuid = result; } #if defined(SHA1_CPUID_MASK) result &= SHA1_CPUID_MASK; #endif return result; } SHA1_TARGET("ssse3,sha") static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t count) { // in SHA1 each round has two parts: // 1) calculate message schedule dwords in w[i] // 2) do round functions to update a/b/c/d/e state values using w[i] // w[i] in first 16 rounds is just loaded from block bytes, as 32-bit big-endian load // for next rounds it is done as: // w[i] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) // where ROL(x) = 32-bit rotate left by 1 // this means it is possible to keep just the last 16 of w's in circular buffer // and every new w calculated will need to update 1 to 3 previous w's // unrolling round calculations by 4 we get: // w[i+0] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) // w[i+1] = ROL(w[i-2] ^ w[i-7] ^ w[i-13] ^ w[i-15]) // w[i+2] = ROL(w[i-1] ^ w[i-6] ^ w[i-12] ^ w[i-14]) // w[i+3] = ROL(w[i+0] ^ w[i-5] ^ w[i-11] ^ w[i-13]) // now if you store 4 w[..] values in 128-bit SSE register, then // W(i) = ROL( r0 ^ r1 ^ r2 ^ r3 ) // with caveat that r0 lane 3 depends on W(i) lane 0 // [3] [2] [1] [0] // lanes // r0 = [ special, w[i-1], w[i-2], w[i-3] ] // r1 = [ w[i-5], w[i-6], w[i-7], w[i-8] ] // r2 = [ w[i-11], w[i-12], w[i-13], w[i-14] ] // r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ] // in each 4-round i'th step it is possible to incrementally update new W(..) value when // keeping W(i) values in 4 xmm element circular buffer // rounds i>0: W(i-1) = r2 ^ r3 = _mm_sha1msg1_epu32(W(i-1), W(i)) // rounds i>1: W(i-2) = W(i-2) ^ r1 = _mm_xor_si128 (W(i-2), W(i)) // rounds i>2: W(i-3) = ROL(W(i-3) ^ r0) = _mm_sha1msg2_epu32(W(i-3), W(i)) // then the new W(i) can be used in round function calculations // _mm_sha1msg2_epu32 correctly handles r0 lane 3 dependency on W(i) lane 0 // to perform round functions on two SIMD registers with state as: // abcd = [a,b,c,d] // e0 = [e,0,0,0] // use the following code to get next abcd/e0 state 4 rounds at a time: // tmp = _mm_sha1nexte_epu32(e0, W(i)) // rotates e0 and adds message dwords // abcd_next = _mm_sha1rnds4_epu32(abcd, tmp, Fn) // with Fn = 0..3 round function selection // e0_next = abcd // sha1nexte is not needed on first round, just regular add32(e0, W(i)) should be used // after last round need to do extra rotation, which sha1nexte takes care when adding to last_e0 #define W(i) w[(i)%4] // 4 wide round calculations #define QROUND(i) do { \ /* first 4 rounds load input block */ \ if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \ /* update message schedule */ \ if (i > 0 && i < 17) W(i-1) = _mm_sha1msg1_epu32(W(i-1), W(i)); \ if (i > 1 && i < 18) W(i-2) = _mm_xor_si128 (W(i-2), W(i)); \ if (i > 2 && i < 19) W(i-3) = _mm_sha1msg2_epu32(W(i-3), W(i)); \ /* calculate E plus message schedule */ \ if (i == 0) tmp = _mm_add_epi32 (e0, W(i)); \ if (i != 0) tmp = _mm_sha1nexte_epu32(e0, W(i)); \ /* 4 round functions */ \ e0 = abcd; \ abcd = _mm_sha1rnds4_epu32(abcd, tmp, i/5); \ } while(0) const __m128i* buffer = (const __m128i*)block; // for performing two operations in one: // 1) dwords need to be loaded as big-endian // 2) order of dwords need to be reversed for sha1 instructions: [0,1,2,3] -> [3,2,1,0] const __m128i bswap = _mm_setr_epi8(15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0); // load initial state __m128i abcd = _mm_loadu_si128((const __m128i*)state); // [d,c,b,a] __m128i e0 = _mm_loadu_si32(&state[4]); // [0,0,0,e] // flip dword order, to what sha1 instructions use abcd = _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] where a is in the top lane e0 = _mm_slli_si128(e0, 12); // [e,0,0,0] where e is in top lane do { // remember current state __m128i last_abcd = abcd; __m128i last_e0 = e0; __m128i tmp, w[4]; QROUND(0); QROUND(1); QROUND(2); QROUND(3); QROUND(4); QROUND(5); QROUND(6); QROUND(7); QROUND(8); QROUND(9); QROUND(10); QROUND(11); QROUND(12); QROUND(13); QROUND(14); QROUND(15); QROUND(16); QROUND(17); QROUND(18); QROUND(19); // update next state abcd = _mm_add_epi32(abcd, last_abcd); e0 = _mm_sha1nexte_epu32(e0, last_e0); buffer += 4; } while (--count); // restore dword order abcd = _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3)); e0 = _mm_shuffle_epi32(e0, _MM_SHUFFLE(0,1,2,3)); // save the new state _mm_storeu_si128((__m128i*)state, abcd); _mm_storeu_si32(&state[4], e0); #undef QROUND #undef W } #endif // defined(__x86_64__) || defined(_M_AMD64) #if defined(__aarch64__) || defined(_M_ARM64) #if defined(__clang__) # define SHA1_TARGET __attribute__((target("sha2"))) #elif defined(__GNUC__) # define SHA1_TARGET __attribute__((target("+sha2"))) #elif defined(_MSC_VER) # define SHA1_TARGET #endif #include #if defined(_WIN32) # include #elif defined(__linux__) # include # include #elif defined(__APPLE__) # include #endif #define SHA1_CPUID_INIT (1 << 0) #define SHA1_CPUID_ARM64 (1 << 1) static inline int sha1_cpuid(void) { #if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2) int result = SHA1_CPUID_ARM64; #else static int cpuid; int result = cpuid; if (result == 0) { #if defined(_WIN32) int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); #elif defined(__linux__) unsigned long hwcap = getauxval(AT_HWCAP); int has_arm64 = hwcap & HWCAP_SHA1; #elif defined(__APPLE__) int value = 0; size_t valuelen = sizeof(value); int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA1", &value, &valuelen, NULL, 0) == 0 && value != 0; #else #error unknown platform #endif result |= SHA1_CPUID_INIT; if (has_arm64) { result |= SHA1_CPUID_ARM64; } cpuid = result; } #endif #if defined(SHA1_CPUID_MASK) result &= SHA1_CPUID_MASK; #endif return result; } SHA1_TARGET static void sha1_process_arm64(uint32_t* state, const uint8_t* block, size_t count) { // code here is similar to x64 shani implementation // message array is 16 element circular buffer // each iteration updates 4 rounds at the same time #define W(i) w[(i)%4] #define QROUND(i,F,k) do { \ /* update message schedule */ \ if (i >= 4) W(i) = vsha1su0q_u32(W(i), W(i-3), W(i-2)); \ if (i >= 4) W(i) = vsha1su1q_u32(W(i), W(i-1)); \ /* add round constant */ \ uint32x4_t tmp = vaddq_u32(W(i), k); \ /* 4 round functions */ \ uint32_t x = e0; \ e0 = vsha1h_u32(vgetq_lane_u32(abcd, 0)); \ abcd = F(abcd, x, tmp); \ } while (0) const uint32x4_t k0 = vdupq_n_u32(0x5a827999); const uint32x4_t k1 = vdupq_n_u32(0x6ed9eba1); const uint32x4_t k2 = vdupq_n_u32(0x8f1bbcdc); const uint32x4_t k3 = vdupq_n_u32(0xca62c1d6); // load state - a,b,c,d,e uint32x4_t abcd = vld1q_u32(state); uint32_t e0 = state[4]; do { // remember current state uint32x4_t last_abcd = abcd; uint32_t last_e0 = e0; // load 64-byte block and advance pointer to next block uint8x16x4_t msg = vld1q_u8_x4(block); block += SHA1_BLOCK_SIZE; uint32x4_t w[4]; // for first 16 w's reverse the byte order in each 32-bit lane W(0) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[0])); W(1) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[1])); W(2) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[2])); W(3) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[3])); QROUND( 0, vsha1cq_u32, k0); QROUND( 1, vsha1cq_u32, k0); QROUND( 2, vsha1cq_u32, k0); QROUND( 3, vsha1cq_u32, k0); QROUND( 4, vsha1cq_u32, k0); QROUND( 5, vsha1pq_u32, k1); QROUND( 6, vsha1pq_u32, k1); QROUND( 7, vsha1pq_u32, k1); QROUND( 8, vsha1pq_u32, k1); QROUND( 9, vsha1pq_u32, k1); QROUND(10, vsha1mq_u32, k2); QROUND(11, vsha1mq_u32, k2); QROUND(12, vsha1mq_u32, k2); QROUND(13, vsha1mq_u32, k2); QROUND(14, vsha1mq_u32, k2); QROUND(15, vsha1pq_u32, k3); QROUND(16, vsha1pq_u32, k3); QROUND(17, vsha1pq_u32, k3); QROUND(18, vsha1pq_u32, k3); QROUND(19, vsha1pq_u32, k3); // update next state abcd = vaddq_u32(abcd, last_abcd); e0 += last_e0; } while (--count); // save state vst1q_u32(state, abcd); state[4] = e0; #undef QROUND #undef W } #endif // defined(__aarch64__) || defined(_M_ARM64) static void sha1_process(uint32_t* state, const uint8_t* block, size_t count) { #if defined(__x86_64__) || defined(_M_AMD64) int cpuid = sha1_cpuid(); if (cpuid & SHA1_CPUID_SHANI) { sha1_process_shani(state, block, count); return; } #endif #if defined(__aarch64__) || defined(_M_ARM64) int cpuid = sha1_cpuid(); if (cpuid & SHA1_CPUID_ARM64) { sha1_process_arm64(state, block, count); return; } #endif #define F1(x,y,z) (0x5a827999 + ((x & (y ^ z)) ^ z)) #define F2(x,y,z) (0x6ed9eba1 + (x ^ y ^ z)) #define F3(x,y,z) (0x8f1bbcdc + ((x & y) | (z & (x | y)))) #define F4(x,y,z) (0xca62c1d6 + (x ^ y ^ z)) #define W(i) w[(i)%16] #define ROUND(i,a,b,c,d,e,F) do \ { \ uint32_t w0; \ if (i < 16) W(i) = w0 = SHA1_GET32BE(block + i*sizeof(uint32_t)); \ if (i >= 16) W(i) = w0 = SHA1_ROL32(W(i-3) ^ W(i-8) ^ W(i-14) ^ W(i-16), 1); \ \ e += SHA1_ROL32(a,5) + F(b,c,d) + w0; \ b = SHA1_ROL32(b,30); \ } while (0) uint32_t a = state[0]; uint32_t b = state[1]; uint32_t c = state[2]; uint32_t d = state[3]; uint32_t e = state[4]; do { uint32_t last_a = a; uint32_t last_b = b; uint32_t last_c = c; uint32_t last_d = d; uint32_t last_e = e; uint32_t w[16]; ROUND( 0, a, b, c, d, e, F1); ROUND( 1, e, a, b, c, d, F1); ROUND( 2, d, e, a, b, c, F1); ROUND( 3, c, d, e, a, b, F1); ROUND( 4, b, c, d, e, a, F1); ROUND( 5, a, b, c, d, e, F1); ROUND( 6, e, a, b, c, d, F1); ROUND( 7, d, e, a, b, c, F1); ROUND( 8, c, d, e, a, b, F1); ROUND( 9, b, c, d, e, a, F1); ROUND(10, a, b, c, d, e, F1); ROUND(11, e, a, b, c, d, F1); ROUND(12, d, e, a, b, c, F1); ROUND(13, c, d, e, a, b, F1); ROUND(14, b, c, d, e, a, F1); ROUND(15, a, b, c, d, e, F1); ROUND(16, e, a, b, c, d, F1); ROUND(17, d, e, a, b, c, F1); ROUND(18, c, d, e, a, b, F1); ROUND(19, b, c, d, e, a, F1); ROUND(20, a, b, c, d, e, F2); ROUND(21, e, a, b, c, d, F2); ROUND(22, d, e, a, b, c, F2); ROUND(23, c, d, e, a, b, F2); ROUND(24, b, c, d, e, a, F2); ROUND(25, a, b, c, d, e, F2); ROUND(26, e, a, b, c, d, F2); ROUND(27, d, e, a, b, c, F2); ROUND(28, c, d, e, a, b, F2); ROUND(29, b, c, d, e, a, F2); ROUND(30, a, b, c, d, e, F2); ROUND(31, e, a, b, c, d, F2); ROUND(32, d, e, a, b, c, F2); ROUND(33, c, d, e, a, b, F2); ROUND(34, b, c, d, e, a, F2); ROUND(35, a, b, c, d, e, F2); ROUND(36, e, a, b, c, d, F2); ROUND(37, d, e, a, b, c, F2); ROUND(38, c, d, e, a, b, F2); ROUND(39, b, c, d, e, a, F2); ROUND(40, a, b, c, d, e, F3); ROUND(41, e, a, b, c, d, F3); ROUND(42, d, e, a, b, c, F3); ROUND(43, c, d, e, a, b, F3); ROUND(44, b, c, d, e, a, F3); ROUND(45, a, b, c, d, e, F3); ROUND(46, e, a, b, c, d, F3); ROUND(47, d, e, a, b, c, F3); ROUND(48, c, d, e, a, b, F3); ROUND(49, b, c, d, e, a, F3); ROUND(50, a, b, c, d, e, F3); ROUND(51, e, a, b, c, d, F3); ROUND(52, d, e, a, b, c, F3); ROUND(53, c, d, e, a, b, F3); ROUND(54, b, c, d, e, a, F3); ROUND(55, a, b, c, d, e, F3); ROUND(56, e, a, b, c, d, F3); ROUND(57, d, e, a, b, c, F3); ROUND(58, c, d, e, a, b, F3); ROUND(59, b, c, d, e, a, F3); ROUND(60, a, b, c, d, e, F4); ROUND(61, e, a, b, c, d, F4); ROUND(62, d, e, a, b, c, F4); ROUND(63, c, d, e, a, b, F4); ROUND(64, b, c, d, e, a, F4); ROUND(65, a, b, c, d, e, F4); ROUND(66, e, a, b, c, d, F4); ROUND(67, d, e, a, b, c, F4); ROUND(68, c, d, e, a, b, F4); ROUND(69, b, c, d, e, a, F4); ROUND(70, a, b, c, d, e, F4); ROUND(71, e, a, b, c, d, F4); ROUND(72, d, e, a, b, c, F4); ROUND(73, c, d, e, a, b, F4); ROUND(74, b, c, d, e, a, F4); ROUND(75, a, b, c, d, e, F4); ROUND(76, e, a, b, c, d, F4); ROUND(77, d, e, a, b, c, F4); ROUND(78, c, d, e, a, b, F4); ROUND(79, b, c, d, e, a, F4); a += last_a; b += last_b; c += last_c; d += last_d; e += last_e; block += SHA1_BLOCK_SIZE; } while (--count); state[0] = a; state[1] = b; state[2] = c; state[3] = d; state[4] = e; #undef ROUND #undef W #undef F1 #undef F2 #undef F3 #undef F4 } void sha1_init(sha1_ctx* ctx) { ctx->count = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; ctx->state[4] = 0xc3d2e1f0; } void sha1_update(sha1_ctx* ctx, const void* data, size_t size) { const uint8_t* buffer = (const uint8_t*)data; size_t pending = ctx->count % SHA1_BLOCK_SIZE; ctx->count += size; size_t available = SHA1_BLOCK_SIZE - pending; if (pending && size >= available) { memcpy(ctx->buffer + pending, buffer, available); sha1_process(ctx->state, ctx->buffer, 1); buffer += available; size -= available; pending = 0; } size_t count = size / SHA1_BLOCK_SIZE; if (count) { sha1_process(ctx->state, buffer, count); buffer += count * SHA1_BLOCK_SIZE; size -= count * SHA1_BLOCK_SIZE; } memcpy(ctx->buffer + pending, buffer, size); } void sha1_finish(sha1_ctx* ctx, uint8_t digest[SHA1_DIGEST_SIZE]) { uint64_t count = ctx->count; uint64_t bitcount = count * 8; size_t pending = count % SHA1_BLOCK_SIZE; size_t blocks = pending < SHA1_BLOCK_SIZE - sizeof(bitcount) ? 1 : 2; ctx->buffer[pending++] = 0x80; uint8_t padding[2 * SHA1_BLOCK_SIZE]; memcpy(padding, ctx->buffer, SHA1_BLOCK_SIZE); memset(padding + pending, 0, SHA1_BLOCK_SIZE); SHA1_SET64BE(padding + blocks * SHA1_BLOCK_SIZE - sizeof(bitcount), bitcount); sha1_process(ctx->state, padding, blocks); for (size_t i=0; i<5; i++) { SHA1_SET32BE(digest + i*sizeof(uint32_t), ctx->state[i]); } } #if defined(__clang__) # pragma clang diagnostic pop #elif defined(_MSC_VER) # pragma warning (pop) #endif ================================================ FILE: src/third_party/martins_hash/sha256.h ================================================ #pragma once // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf // https://www.rfc-editor.org/rfc/rfc6234 #include #include // // interface // #define SHA224_DIGEST_SIZE 28 #define SHA256_DIGEST_SIZE 32 #define SHA256_BLOCK_SIZE 64 typedef struct { uint8_t buffer[SHA256_BLOCK_SIZE]; uint64_t count; uint32_t state[8]; } sha256_ctx; typedef sha256_ctx sha224_ctx; static inline void sha256_init(sha256_ctx* ctx); static inline void sha256_update(sha256_ctx* ctx, const void* data, size_t size); static inline void sha256_finish(sha256_ctx* ctx, uint8_t digest[SHA256_DIGEST_SIZE]); static inline void sha224_init(sha224_ctx* ctx); static inline void sha224_update(sha224_ctx* ctx, const void* data, size_t size); static inline void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_SIZE]); // // implementation // #include // memcpy, memset #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wcast-align" # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" # pragma clang diagnostic ignored "-Wlanguage-extension-token" # pragma clang diagnostic ignored "-Wdeclaration-after-statement" #elif defined(_MSC_VER) # pragma warning (push) # pragma warning (disable : 4127) #endif #if defined(__clang__) # define SHA256_ROR32(x,n) __builtin_rotateright32(x, n) #elif defined(_MSC_VER) # include # define SHA256_ROR32(x,n) _rotr(x, n) #else # define SHA256_ROR32(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) #endif #if defined(_MSC_VER) # include # define SHA256_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) ) # define SHA256_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x) # define SHA256_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x) #else # define SHA256_GET32BE(ptr) \ ( \ ((ptr)[0] << 24) | \ ((ptr)[1] << 16) | \ ((ptr)[2] << 8) | \ ((ptr)[3] << 0) \ ) # define SHA256_SET32BE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 24); \ (ptr)[1] = (uint8_t)((x) >> 16); \ (ptr)[2] = (uint8_t)((x) >> 8); \ (ptr)[3] = (uint8_t)((x) >> 0); \ } \ while (0) # define SHA256_SET64BE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 56); \ (ptr)[1] = (uint8_t)((x) >> 48); \ (ptr)[2] = (uint8_t)((x) >> 40); \ (ptr)[3] = (uint8_t)((x) >> 32); \ (ptr)[4] = (uint8_t)((x) >> 24); \ (ptr)[5] = (uint8_t)((x) >> 16); \ (ptr)[6] = (uint8_t)((x) >> 8); \ (ptr)[7] = (uint8_t)((x) >> 0); \ } \ while (0) #endif static const uint32_t SHA256_K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, }; #if defined(__x86_64__) || defined(_M_AMD64) #include // SSSE3 #include // SHANI #if defined(__clang__) || defined(__GNUC__) # include # define SHA256_TARGET(str) __attribute__((target(str))) # define SHA256_CPUID(x, info) __cpuid(x, info[0], info[1], info[2], info[3]) # define SHA256_CPUID_EX(x, y, info) __cpuid_count(x, y, info[0], info[1], info[2], info[3]) #else # include # define SHA256_TARGET(str) # define SHA256_CPUID(x, info) __cpuid(info, x) # define SHA256_CPUID_EX(x, y, info) __cpuidex(info, x, y) #endif #define SHA256_CPUID_INIT (1 << 0) #define SHA256_CPUID_SHANI (1 << 1) static inline int sha256_cpuid(void) { static int cpuid; int result = cpuid; if (result == 0) { int info[4]; SHA256_CPUID(1, info); int has_ssse3 = info[3] & (1 << 9); SHA256_CPUID_EX(7, 0, info); int has_shani = info[1] & (1 << 29); result |= SHA256_CPUID_INIT; if (has_ssse3 && has_shani) { result |= SHA256_CPUID_SHANI; } cpuid = result; } #if defined(SHA256_CPUID_MASK) result &= SHA256_CPUID_MASK; #endif return result; } SHA256_TARGET("ssse3,sha") static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t count) { // similar way how sha1 works in with shani // first 16 rounds loads message schedule dwords as 32-bit big endian values // for next rounds message schedule is prepared as: // w[i] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16] // unrolled by 4: // w[i+0] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16] // w[i+1] = SSig1(w[i-1]) + w[i-6] + SSig0(w[i-14]) + w[i-15] // w[i+2] = SSig1(w[i+0]) + w[i-5] + SSig0(w[i-13]) + w[i-14] // w[i+3] = SSig1(w[i+1]) + w[i-4] + SSig0(w[i-12]) + w[i-13] // there is tricky dependency for lanes 2 and 3 on result of lanes 0 and 1, but sha256msg2 op takes care of that // by storing W[i] word in 128-bit simd register, the message schedule becomes: // W(i) = SSig1(r0) + r1 + SSig0(r2) + r3 // where + is 32-bit lane addition // [3] [2] [1] [0] // lanes // r0 = [ special, special, w[i-1], w[i-2] ] // r1 = [ w[i-4], w[i-5], w[i-6], w[i-7] ] // r2 = [ w[i-12], w[i-13], w[i-14], w[i-15] ] // r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ] // rN's can be calculated from previous W(..) values: // r0 from W(i) // r1 from _mm_alignr_epi8(W(i), W(i-1), 4) // r2 from W(i-1) and W(i) // r3 from W(i-1) // rounds i>2: W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32( W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4) ), W(i)) // rounds i>0: W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i)) // round functions are done with _mm_sha256rnds2_epu32 which performs it for 2 rounds // thus repeat it two times, as input use W(i) + K(i) - message schedule added with sha256 constants #define W(i) w[(i)%4] // 4 wide round calculations #define QROUND(i) do { \ /* first 4 rounds load input block */ \ if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \ /* update message schedule */ \ if (i > 2 && i < 15) W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32(W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4)), W(i)); \ if (i > 0 && i < 13) W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i)); \ /* add round constants */ \ __m128i tmp = _mm_add_epi32(W(i), _mm_loadu_si128((const __m128i*)&SHA256_K[4*i])); \ /* 4 round functions */ \ state1 = _mm_sha256rnds2_epu32(state1, state0, tmp); \ state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(tmp, _MM_SHUFFLE(0,0,3,2))); \ } while(0) const __m128i* buffer = (const __m128i*)block; // to byteswap when doing big-ending load for message dwords const __m128i bswap = _mm_setr_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12); // load initial state __m128i abcd = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[0]), _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] __m128i efgh = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[4]), _MM_SHUFFLE(0,1,2,3)); // [e,f,g,h] // dword order for sha256rnds2 instruction __m128i state0 = _mm_unpackhi_epi64(efgh, abcd); // [a,b,e,f] __m128i state1 = _mm_unpacklo_epi64(efgh, abcd); // [c,d,g,h] do { // remember current state __m128i last0 = state0; __m128i last1 = state1; __m128i w[4]; QROUND( 0); QROUND( 1); QROUND( 2); QROUND( 3); QROUND( 4); QROUND( 5); QROUND( 6); QROUND( 7); QROUND( 8); QROUND( 9); QROUND(10); QROUND(11); QROUND(12); QROUND(13); QROUND(14); QROUND(15); // update next state state0 = _mm_add_epi32(state0, last0); state1 = _mm_add_epi32(state1, last1); buffer += 4; } while (--count); // restore dword order abcd = _mm_unpackhi_epi64(state1, state0); efgh = _mm_unpacklo_epi64(state1, state0); // save the new state _mm_storeu_si128((__m128i*)&state[0], _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3))); _mm_storeu_si128((__m128i*)&state[4], _mm_shuffle_epi32(efgh, _MM_SHUFFLE(0,1,2,3))); #undef QROUND #undef W } #endif // defined(__x86_64__) || defined(_M_AMD64) #if defined(__aarch64__) || defined(_M_ARM64) #if defined(__clang__) # define SHA256_TARGET __attribute__((target("sha2"))) #elif defined(__GNUC__) # define SHA256_TARGET __attribute__((target("+sha2"))) #elif defined(_MSC_VER) # define SHA256_TARGET #endif #include #if defined(_WIN32) # include #elif defined(__linux__) # include # include #elif defined(__APPLE__) # include #endif #define SHA256_CPUID_INIT (1 << 0) #define SHA256_CPUID_ARM64 (1 << 1) static inline int sha256_cpuid(void) { #if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2) int result = SHA256_CPUID_ARM64; #else static int cpuid; int result = cpuid; if (result == 0) { #if defined(_WIN32) int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); #elif defined(__linux__) unsigned long hwcap = getauxval(AT_HWCAP); int has_arm64 = hwcap & HWCAP_SHA2; #elif defined(__APPLE__) int value = 0; size_t valuelen = sizeof(value); int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA256", &value, &valuelen, NULL, 0) == 0 && value != 0; #else #error unknown platform #endif result |= SHA256_CPUID_INIT; if (has_arm64) { result |= SHA256_CPUID_ARM64; } cpuid = result; } #endif #if defined(SHA256_CPUID_MASK) result &= SHA256_CPUID_MASK; #endif return result; } SHA256_TARGET static void sha256_process_arm64(uint32_t* state, const uint8_t* block, size_t count) { // code here is similar to x64 shani implementation #define W(i) w[(i)%4] #define QROUND(i) do { \ /* load 16 round constants */ \ if ((i % 4) == 0) rk = vld1q_u32_x4(&SHA256_K[4*i]); \ /* first 4 rounds reverse byte order in each 32-bit lane of input block */ \ if (i < 4) W(i) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[i])); \ /* update message schedule */ \ if (i >= 4) W(i) = vsha256su0q_u32(W(i), W(i-3)); \ if (i >= 4) W(i) = vsha256su1q_u32(W(i), W(i-2), W(i-1)); \ /* add round constants */ \ uint32x4_t tmp = vaddq_u32(W(i), rk.val[i%4]); \ /* 4 round functions */ \ uint32x4_t x = vstate.val[0]; \ vstate.val[0] = vsha256hq_u32(vstate.val[0], vstate.val[1], tmp); \ vstate.val[1] = vsha256h2q_u32(vstate.val[1], x, tmp); \ } while (0) // load initial state uint32x4x2_t vstate = vld1q_u32_x2(state); do { // remember current state uint32x4x2_t vlast = vstate; // load 64-byte block uint8x16x4_t msg = vld1q_u8_x4(block); uint32x4x4_t rk; uint32x4_t w[4]; QROUND( 0); QROUND( 1); QROUND( 2); QROUND( 3); QROUND( 4); QROUND( 5); QROUND( 6); QROUND( 7); QROUND( 8); QROUND( 9); QROUND(10); QROUND(11); QROUND(12); QROUND(13); QROUND(14); QROUND(15); // update next state vstate.val[0] = vaddq_u32(vstate.val[0], vlast.val[0]); vstate.val[1] = vaddq_u32(vstate.val[1], vlast.val[1]); block += SHA256_BLOCK_SIZE; } while (--count); // save the new state vst1q_u32_x2(state, vstate); #undef QROUND #undef W } #endif // defined(__aarch64__) || defined(_M_ARM64) static void sha256_process(uint32_t* state, const uint8_t* block, size_t count) { #if defined(__x86_64__) || defined(_M_AMD64) int cpuid = sha256_cpuid(); if (cpuid & SHA256_CPUID_SHANI) { sha256_process_shani(state, block, count); return; } #endif #if defined(__aarch64__) || defined(_M_ARM64) int cpuid = sha256_cpuid(); if (cpuid & SHA256_CPUID_ARM64) { sha256_process_arm64(state, block, count); return; } #endif #define Ch(x,y,z) ((x & (y ^ z)) ^ z) #define Maj(x,y,z) ((x & y) | (z & (x | y))) #define BSig0(x) (SHA256_ROR32(x, 2) ^ SHA256_ROR32(x, 13) ^ SHA256_ROR32(x, 22)) #define BSig1(x) (SHA256_ROR32(x, 6) ^ SHA256_ROR32(x, 11) ^ SHA256_ROR32(x, 25)) #define SSig0(x) (SHA256_ROR32(x, 7) ^ SHA256_ROR32(x, 18) ^ (x >> 3)) #define SSig1(x) (SHA256_ROR32(x, 17) ^ SHA256_ROR32(x, 19) ^ (x >> 10)) #define W(i) w[(i+16)%16] #define ROUND(i,a,b,c,d,e,f,g,h) do \ { \ uint32_t w0; \ if (i < 16) W(i) = w0 = SHA256_GET32BE(block + i*sizeof(uint32_t)); \ if (i >= 16) W(i) = w0 = SSig1(W(i-2)) + W(i-7) + SSig0(W(i-15)) + W(i-16); \ \ uint32_t t1 = h + BSig1(e) + Ch(e,f,g) + SHA256_K[i] + w0; \ uint32_t t2 = BSig0(a) + Maj(a,b,c); \ d += t1; \ h = t1 + t2; \ } while (0) do { uint32_t a = state[0]; uint32_t b = state[1]; uint32_t c = state[2]; uint32_t d = state[3]; uint32_t e = state[4]; uint32_t f = state[5]; uint32_t g = state[6]; uint32_t h = state[7]; uint32_t w[16]; ROUND( 0, a, b, c, d, e, f, g, h); ROUND( 1, h, a, b, c, d, e, f, g); ROUND( 2, g, h, a, b, c, d, e, f); ROUND( 3, f, g, h, a, b, c, d, e); ROUND( 4, e, f, g, h, a, b, c, d); ROUND( 5, d, e, f, g, h, a, b, c); ROUND( 6, c, d, e, f, g, h, a, b); ROUND( 7, b, c, d, e, f, g, h, a); ROUND( 8, a, b, c, d, e, f, g, h); ROUND( 9, h, a, b, c, d, e, f, g); ROUND(10, g, h, a, b, c, d, e, f); ROUND(11, f, g, h, a, b, c, d, e); ROUND(12, e, f, g, h, a, b, c, d); ROUND(13, d, e, f, g, h, a, b, c); ROUND(14, c, d, e, f, g, h, a, b); ROUND(15, b, c, d, e, f, g, h, a); ROUND(16, a, b, c, d, e, f, g, h); ROUND(17, h, a, b, c, d, e, f, g); ROUND(18, g, h, a, b, c, d, e, f); ROUND(19, f, g, h, a, b, c, d, e); ROUND(20, e, f, g, h, a, b, c, d); ROUND(21, d, e, f, g, h, a, b, c); ROUND(22, c, d, e, f, g, h, a, b); ROUND(23, b, c, d, e, f, g, h, a); ROUND(24, a, b, c, d, e, f, g, h); ROUND(25, h, a, b, c, d, e, f, g); ROUND(26, g, h, a, b, c, d, e, f); ROUND(27, f, g, h, a, b, c, d, e); ROUND(28, e, f, g, h, a, b, c, d); ROUND(29, d, e, f, g, h, a, b, c); ROUND(30, c, d, e, f, g, h, a, b); ROUND(31, b, c, d, e, f, g, h, a); ROUND(32, a, b, c, d, e, f, g, h); ROUND(33, h, a, b, c, d, e, f, g); ROUND(34, g, h, a, b, c, d, e, f); ROUND(35, f, g, h, a, b, c, d, e); ROUND(36, e, f, g, h, a, b, c, d); ROUND(37, d, e, f, g, h, a, b, c); ROUND(38, c, d, e, f, g, h, a, b); ROUND(39, b, c, d, e, f, g, h, a); ROUND(40, a, b, c, d, e, f, g, h); ROUND(41, h, a, b, c, d, e, f, g); ROUND(42, g, h, a, b, c, d, e, f); ROUND(43, f, g, h, a, b, c, d, e); ROUND(44, e, f, g, h, a, b, c, d); ROUND(45, d, e, f, g, h, a, b, c); ROUND(46, c, d, e, f, g, h, a, b); ROUND(47, b, c, d, e, f, g, h, a); ROUND(48, a, b, c, d, e, f, g, h); ROUND(49, h, a, b, c, d, e, f, g); ROUND(50, g, h, a, b, c, d, e, f); ROUND(51, f, g, h, a, b, c, d, e); ROUND(52, e, f, g, h, a, b, c, d); ROUND(53, d, e, f, g, h, a, b, c); ROUND(54, c, d, e, f, g, h, a, b); ROUND(55, b, c, d, e, f, g, h, a); ROUND(56, a, b, c, d, e, f, g, h); ROUND(57, h, a, b, c, d, e, f, g); ROUND(58, g, h, a, b, c, d, e, f); ROUND(59, f, g, h, a, b, c, d, e); ROUND(60, e, f, g, h, a, b, c, d); ROUND(61, d, e, f, g, h, a, b, c); ROUND(62, c, d, e, f, g, h, a, b); ROUND(63, b, c, d, e, f, g, h, a); state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; block += SHA256_BLOCK_SIZE; } while (--count); #undef ROUND #undef W #undef Ch #undef Maj #undef BSig0 #undef BSig1 #undef SSig0 #undef SSig1 } void sha256_init(sha256_ctx* ctx) { ctx->count = 0; ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; } void sha256_update(sha256_ctx* ctx, const void* data, size_t size) { const uint8_t* buffer = (const uint8_t*)data; size_t pending = ctx->count % SHA256_BLOCK_SIZE; ctx->count += size; size_t available = SHA256_BLOCK_SIZE - pending; if (pending && size >= available) { memcpy(ctx->buffer + pending, buffer, available); sha256_process(ctx->state, ctx->buffer, 1); buffer += available; size -= available; pending = 0; } size_t count = size / SHA256_BLOCK_SIZE; if (count) { sha256_process(ctx->state, buffer, count); buffer += count * SHA256_BLOCK_SIZE; size -= count * SHA256_BLOCK_SIZE; } memcpy(ctx->buffer + pending, buffer, size); } void sha256_finish(sha256_ctx* ctx, uint8_t digest[SHA256_DIGEST_SIZE]) { uint64_t count = ctx->count; uint64_t bitcount = count * 8; size_t pending = count % SHA256_BLOCK_SIZE; size_t blocks = pending < SHA256_BLOCK_SIZE - sizeof(bitcount) ? 1 : 2; ctx->buffer[pending++] = 0x80; uint8_t padding[2 * SHA256_BLOCK_SIZE]; memcpy(padding, ctx->buffer, SHA256_BLOCK_SIZE); memset(padding + pending, 0, SHA256_BLOCK_SIZE); SHA256_SET64BE(padding + blocks * SHA256_BLOCK_SIZE - sizeof(bitcount), bitcount); sha256_process(ctx->state, padding, blocks); for (size_t i=0; i<8; i++) { SHA256_SET32BE(digest + i*sizeof(uint32_t), ctx->state[i]); } } void sha224_init(sha224_ctx* ctx) { ctx->count = 0; ctx->state[0] = 0xc1059ed8; ctx->state[1] = 0x367cd507; ctx->state[2] = 0x3070dd17; ctx->state[3] = 0xf70e5939; ctx->state[4] = 0xffc00b31; ctx->state[5] = 0x68581511; ctx->state[6] = 0x64f98fa7; ctx->state[7] = 0xbefa4fa4; } void sha224_update(sha224_ctx* ctx, const void* data, size_t size) { sha256_update(ctx, data, size); } void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_SIZE]) { uint8_t temp[SHA256_DIGEST_SIZE]; sha256_finish(ctx, temp); memcpy(digest, temp, SHA224_DIGEST_SIZE); } #if defined(__clang__) # pragma clang diagnostic pop #elif defined(_MSC_VER) # pragma warning (pop) #endif ================================================ FILE: src/third_party/martins_hash/sha512.h ================================================ #pragma once // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf // https://www.rfc-editor.org/rfc/rfc6234 #include #include // // interface // #define SHA384_DIGEST_SIZE 48 #define SHA512_DIGEST_SIZE 64 #define SHA512_BLOCK_SIZE 128 typedef struct { uint8_t buffer[SHA512_BLOCK_SIZE]; uint64_t count[2]; uint64_t state[8]; } sha512_ctx; typedef sha512_ctx sha384_ctx; static inline void sha512_init(sha512_ctx* ctx); static inline void sha512_update(sha512_ctx* ctx, const void* data, size_t size); static inline void sha512_finish(sha512_ctx* ctx, uint8_t digest[SHA512_DIGEST_SIZE]); static inline void sha384_init(sha384_ctx* ctx); static inline void sha384_update(sha384_ctx* ctx, const void* data, size_t size); static inline void sha384_finish(sha384_ctx* ctx, uint8_t digest[SHA384_DIGEST_SIZE]); // // implementation // #include // memcpy, memset #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wcast-align" # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" # pragma clang diagnostic ignored "-Wlanguage-extension-token" # pragma clang diagnostic ignored "-Wdeclaration-after-statement" #elif defined(_MSC_VER) # pragma warning (push) # pragma warning (disable : 4127) #endif #if defined(__clang__) # define SHA512_ROR64(x,n) __builtin_rotateright64(x, n) #elif defined(_MSC_VER) # include # define SHA512_ROR64(x,n) _rotr64(x, n) #else # define SHA512_ROR64(x,n) ( ((x) >> (n)) | ((x) << (64-(n))) ) #endif #if defined(_MSC_VER) # include # define SHA512_GET64BE(ptr) _byteswap_uint64( *((const __unaligned uint64_t*)(ptr)) ) # define SHA512_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x) #else # define SHA512_GET64BE(ptr) \ ( \ ((uint64_t)((ptr)[0]) << 56) | \ ((uint64_t)((ptr)[1]) << 48) | \ ((uint64_t)((ptr)[2]) << 40) | \ ((uint64_t)((ptr)[3]) << 32) | \ ((uint64_t)((ptr)[4]) << 24) | \ ((uint64_t)((ptr)[5]) << 16) | \ ((uint64_t)((ptr)[6]) << 8) | \ ((uint64_t)((ptr)[7]) << 0) \ ) # define SHA512_SET64BE(ptr, x) do \ { \ (ptr)[0] = (uint8_t)((x) >> 56); \ (ptr)[1] = (uint8_t)((x) >> 48); \ (ptr)[2] = (uint8_t)((x) >> 40); \ (ptr)[3] = (uint8_t)((x) >> 32); \ (ptr)[4] = (uint8_t)((x) >> 24); \ (ptr)[5] = (uint8_t)((x) >> 16); \ (ptr)[6] = (uint8_t)((x) >> 8); \ (ptr)[7] = (uint8_t)((x) >> 0); \ } \ while (0) #endif static const uint64_t SHA512_K[80] = { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, }; #if defined(__x86_64__) || defined(_M_AMD64) #include // AVX2 + SHA512 #if defined(__clang__) || defined(__GNUC__) # include # define SHA512_TARGET(str) __attribute__((target(str))) # define SHA512_CPUID(x, info) __cpuid(x, info[0], info[1], info[2], info[3]) # define SHA512_CPUID_EX(x, y, info) __cpuid_count(x, y, info[0], info[1], info[2], info[3]) # define SHA512_XGETBV(x) __builtin_ia32_xgetbv(x) #else # include # define SHA512_TARGET(str) # define SHA512_CPUID(x, info) __cpuid(info, x) # define SHA512_CPUID_EX(x, y, info) __cpuidex(info, x, y) # define SHA512_XGETBV(x) _xgetbv(x) #endif #define SHA512_CPUID_INIT (1 << 0) #define SHA512_CPUID_VSHA512 (1 << 1) SHA512_TARGET("xsave") static inline int sha512_cpuid(void) { static int cpuid; int result = cpuid; if (result == 0) { int info[4]; SHA512_CPUID(1, info); int has_xsave = info[2] & (1 << 26); int has_ymm = 0; if (has_xsave) { uint64_t xcr0 = SHA512_XGETBV(0); has_ymm = xcr0 & (1 << 2); } SHA512_CPUID_EX(7, 0, info); int has_avx2 = info[1] & (1 << 5); SHA512_CPUID_EX(7, 1, info); int has_sha512 = info[0] & (1 << 0); result |= SHA512_CPUID_INIT; if (has_ymm && has_avx2 && has_sha512) { result |= SHA512_CPUID_VSHA512; } cpuid = result; } #if defined(SHA512_CPUID_MASK) result &= SHA512_CPUID_MASK; #endif return result; } SHA512_TARGET("avx2,sha512") static void sha512_process_vsha512(uint64_t* state, const uint8_t* block, size_t count) { // pretty much same way how sha256 works, only with avx2 registers and 64-bit additions // state is kept as two 256-bit ymm registers (8 qwords) // message qwords are loaded as 64-bit big-endian values #define W(i) w[(i)%4] // 4 wide round calculations #define QROUND(i) do { \ /* first 4 rounds load input block */ \ if (i < 4) W(i) = _mm256_shuffle_epi8(_mm256_loadu_si256(&buffer[i]), bswap); \ /* update message schedule */ \ if (i > 2 && i < 19) W(i-3) = _mm256_sha512msg2_epi64(_mm256_add_epi64(W(i-3), _mm256_permute4x64_epi64(_mm256_blend_epi32(W(i-1), W(i), 3), _MM_SHUFFLE(0,3,2,1))), W(i)); \ if (i > 0 && i < 17) W(i-1) = _mm256_sha512msg1_epi64(W(i-1), _mm256_castsi256_si128(W(i))); \ /* add round constants */ \ __m256i tmp = _mm256_add_epi64(W(i), _mm256_loadu_si256((const __m256i*)&SHA512_K[4*i])); \ /* round functions */ \ state1 = _mm256_sha512rnds2_epi64(state1, state0, _mm256_castsi256_si128(tmp)); \ state0 = _mm256_sha512rnds2_epi64(state0, state1, _mm256_extracti128_si256(tmp, 1)); \ } while(0) const __m256i* buffer = (const __m256i*)block; // to byteswap when doing big-ending load for message qwords const __m256i bswap = _mm256_broadcastsi128_si256(_mm_setr_epi8(7,6,5,4,3,2,1,0, 15,14,13,12,11,10,9,8)); // load initial state __m256i abcd = _mm256_permute4x64_epi64(_mm256_loadu_si256((const __m256i*)&state[0]), _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] __m256i efgh = _mm256_permute4x64_epi64(_mm256_loadu_si256((const __m256i*)&state[4]), _MM_SHUFFLE(0,1,2,3)); // [e,f,g,h] // qword order for vsha512rnds2 instruction __m256i state0 = _mm256_permute2x128_si256(efgh, abcd, (3 << 4) | 1); // [a,b,e,f] __m256i state1 = _mm256_permute2x128_si256(efgh, abcd, (2 << 4) | 0); // [c,d,g,h] do { // remember current state __m256i last0 = state0; __m256i last1 = state1; __m256i w[4]; QROUND(0); QROUND(1); QROUND(2); QROUND(3); QROUND(4); QROUND(5); QROUND(6); QROUND(7); QROUND(8); QROUND(9); QROUND(10); QROUND(11); QROUND(12); QROUND(13); QROUND(14); QROUND(15); QROUND(16); QROUND(17); QROUND(18); QROUND(19); // update next state state0 = _mm256_add_epi64(state0, last0); state1 = _mm256_add_epi64(state1, last1); buffer += 4; } while (--count); // restore qword order abcd = _mm256_permute2x128_si256(state1, state0, (3 << 4) | 1); efgh = _mm256_permute2x128_si256(state1, state0, (2 << 4) | 0); // save the new state _mm256_storeu_si256((__m256i*)&state[0], _mm256_permute4x64_epi64(abcd, _MM_SHUFFLE(0,1,2,3))); _mm256_storeu_si256((__m256i*)&state[4], _mm256_permute4x64_epi64(efgh, _MM_SHUFFLE(0,1,2,3))); #undef QROUND #undef W } #endif // defined(__x86_64__) || defined(_M_AMD64) #if defined(__aarch64__) || defined(_M_ARM64) #if defined(__clang__) # define SHA512_TARGET __attribute__((target("sha3"))) #elif defined(__GNUC__) # define SHA512_TARGET __attribute__((target("+sha3"))) #elif defined(_MSC_VER) # define SHA512_TARGET #endif #include #if defined(_WIN32) # include # pragma comment (lib, "advapi32") #elif defined(__linux__) # include # include #elif defined(__APPLE__) # include #endif #define SHA512_CPUID_INIT (1 << 0) #define SHA512_CPUID_ARM64 (1 << 1) #if defined(_WIN32) #endif static inline int sha512_cpuid(void) { #if defined(__ARM_FEATURE_SHA512) int result = SHA512_CPUID_ARM64; #else static int cpuid; int result = cpuid; if (result == 0) { #if defined(_WIN32) // no sha512 bit in IsProcessorFeaturePresent function :( uint64_t bits; DWORD bitsize = sizeof(bits); RegGetValueA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "CP 4030", RRF_RT_QWORD | RRF_ZEROONFAILURE, NULL, &bits, &bitsize); // bits from ID_AA64ISAR0_EL1 int has_arm64 = ((bits >> 12) & 0xf) == 0x2; #elif defined(__linux__) unsigned long hwcap = getauxval(AT_HWCAP); int has_arm64 = hwcap & HWCAP_SHA512; #elif defined(__APPLE__) int value = 0; size_t valuelen = sizeof(value); int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA512", &value, &valuelen, NULL, 0) == 0 && value != 0; #else #error unknown platform #endif result |= SHA512_CPUID_INIT; if (has_arm64) { result |= SHA512_CPUID_ARM64; } cpuid = result; } #endif #if defined(SHA512_CPUID_MASK) result &= SHA512_CPUID_MASK; #endif return result; } SHA512_TARGET static void sha512_process_arm64(uint64_t* state, const uint8_t* block, size_t count) { #define W(i) w[(i)%8] #define S(i) vstate.val[3-(i)%4] #define DROUND(i) do { \ /* load 8 round constants */ \ if ((i % 4) == 0) rk = vld1q_u64_x4(&SHA512_K[2*i]); \ /* first 8 rounds reverse byte order in each 64-bit lane of input block */ \ if (i < 8) W(i) = vreinterpretq_u64_u8(vrev64q_u8(msg[(i/4)%2].val[i%4])); \ /* update message schedule for next rounds */ \ if (i >= 8) W(i) = vsha512su1q_u64(vsha512su0q_u64(W(i), W(i-7)), W(i-1), vextq_u64(W(i-4), W(i-3), 1)); \ /* add round constants */ \ uint64x2_t tmp = vaddq_u64(W(i), rk.val[i%4]); \ /* 2 round functions */ \ uint64x2_t x0 = vaddq_u64(vextq_u64(tmp, tmp, 1), S(i+0)); \ uint64x2_t x1 = vsha512hq_u64(x0, vextq_u64(S(i+1), S(i+0), 1), vextq_u64(S(i+2), S(i+1), 1)); \ S(i+0) = vsha512h2q_u64(x1, S(i+2), S(i+3)); \ S(i+2) = vaddq_u64(S(i+2), x1); \ } while (0) // load initial state uint64x2x4_t vstate = vld1q_u64_x4(state); do { // remember current state uint64x2x4_t vlast = vstate; // load 128-byte block uint8x16x4_t msg[2] = { vld1q_u8_x4(block + 0 * 16), vld1q_u8_x4(block + 4 * 16), }; uint64x2x4_t rk; uint64x2_t w[8]; DROUND( 0); DROUND( 1); DROUND( 2); DROUND( 3); DROUND( 4); DROUND( 5); DROUND( 6); DROUND( 7); DROUND( 8); DROUND( 9); DROUND(10); DROUND(11); DROUND(12); DROUND(13); DROUND(14); DROUND(15); DROUND(16); DROUND(17); DROUND(18); DROUND(19); DROUND(20); DROUND(21); DROUND(22); DROUND(23); DROUND(24); DROUND(25); DROUND(26); DROUND(27); DROUND(28); DROUND(29); DROUND(30); DROUND(31); DROUND(32); DROUND(33); DROUND(34); DROUND(35); DROUND(36); DROUND(37); DROUND(38); DROUND(39); // update next state vstate.val[0] = vaddq_u64(vstate.val[0], vlast.val[0]); vstate.val[1] = vaddq_u64(vstate.val[1], vlast.val[1]); vstate.val[2] = vaddq_u64(vstate.val[2], vlast.val[2]); vstate.val[3] = vaddq_u64(vstate.val[3], vlast.val[3]); block += SHA512_BLOCK_SIZE; } while (--count); // save the new state vst1q_u64_x4(state, vstate); #undef DROUND #undef S #undef W } #endif // defined(__aarch64__) || defined(_M_ARM64) static void sha512_process(uint64_t* state, const uint8_t* block, size_t count) { #if defined(__x86_64__) || defined(_M_AMD64) int cpuid = sha512_cpuid(); if (cpuid & SHA512_CPUID_VSHA512) { sha512_process_vsha512(state, block, count); return; } #endif #if defined(__aarch64__) || defined(_M_ARM64) int cpuid = sha512_cpuid(); if (cpuid & SHA512_CPUID_ARM64) { sha512_process_arm64(state, block, count); return; } #endif #define Ch(x,y,z) ((x & (y ^ z)) ^ z) #define Maj(x,y,z) ((x & y) | (z & (x | y))) #define BSig0(x) (SHA512_ROR64(x, 28) ^ SHA512_ROR64(x, 34) ^ SHA512_ROR64(x, 39)) #define BSig1(x) (SHA512_ROR64(x, 14) ^ SHA512_ROR64(x, 18) ^ SHA512_ROR64(x, 41)) #define SSig0(x) (SHA512_ROR64(x, 1) ^ SHA512_ROR64(x, 8) ^ (x >> 7)) #define SSig1(x) (SHA512_ROR64(x, 19) ^ SHA512_ROR64(x, 61) ^ (x >> 6)) #define W(i) w[(i+16)%16] #define ROUND(i,a,b,c,d,e,f,g,h) do \ { \ uint64_t w0; \ if (i < 16) W(i) = w0 = SHA512_GET64BE(block + i*sizeof(uint64_t)); \ if (i >= 16) W(i) = w0 = SSig1(W(i-2)) + W(i-7) + SSig0(W(i-15)) + W(i-16); \ \ uint64_t t1 = h + BSig1(e) + Ch(e,f,g) + SHA512_K[i] + w0; \ uint64_t t2 = BSig0(a) + Maj(a,b,c); \ d += t1; \ h = t1 + t2; \ } while (0) do { uint64_t a = state[0]; uint64_t b = state[1]; uint64_t c = state[2]; uint64_t d = state[3]; uint64_t e = state[4]; uint64_t f = state[5]; uint64_t g = state[6]; uint64_t h = state[7]; uint64_t w[16]; ROUND( 0, a, b, c, d, e, f, g, h); ROUND( 1, h, a, b, c, d, e, f, g); ROUND( 2, g, h, a, b, c, d, e, f); ROUND( 3, f, g, h, a, b, c, d, e); ROUND( 4, e, f, g, h, a, b, c, d); ROUND( 5, d, e, f, g, h, a, b, c); ROUND( 6, c, d, e, f, g, h, a, b); ROUND( 7, b, c, d, e, f, g, h, a); ROUND( 8, a, b, c, d, e, f, g, h); ROUND( 9, h, a, b, c, d, e, f, g); ROUND(10, g, h, a, b, c, d, e, f); ROUND(11, f, g, h, a, b, c, d, e); ROUND(12, e, f, g, h, a, b, c, d); ROUND(13, d, e, f, g, h, a, b, c); ROUND(14, c, d, e, f, g, h, a, b); ROUND(15, b, c, d, e, f, g, h, a); ROUND(16, a, b, c, d, e, f, g, h); ROUND(17, h, a, b, c, d, e, f, g); ROUND(18, g, h, a, b, c, d, e, f); ROUND(19, f, g, h, a, b, c, d, e); ROUND(20, e, f, g, h, a, b, c, d); ROUND(21, d, e, f, g, h, a, b, c); ROUND(22, c, d, e, f, g, h, a, b); ROUND(23, b, c, d, e, f, g, h, a); ROUND(24, a, b, c, d, e, f, g, h); ROUND(25, h, a, b, c, d, e, f, g); ROUND(26, g, h, a, b, c, d, e, f); ROUND(27, f, g, h, a, b, c, d, e); ROUND(28, e, f, g, h, a, b, c, d); ROUND(29, d, e, f, g, h, a, b, c); ROUND(30, c, d, e, f, g, h, a, b); ROUND(31, b, c, d, e, f, g, h, a); ROUND(32, a, b, c, d, e, f, g, h); ROUND(33, h, a, b, c, d, e, f, g); ROUND(34, g, h, a, b, c, d, e, f); ROUND(35, f, g, h, a, b, c, d, e); ROUND(36, e, f, g, h, a, b, c, d); ROUND(37, d, e, f, g, h, a, b, c); ROUND(38, c, d, e, f, g, h, a, b); ROUND(39, b, c, d, e, f, g, h, a); ROUND(40, a, b, c, d, e, f, g, h); ROUND(41, h, a, b, c, d, e, f, g); ROUND(42, g, h, a, b, c, d, e, f); ROUND(43, f, g, h, a, b, c, d, e); ROUND(44, e, f, g, h, a, b, c, d); ROUND(45, d, e, f, g, h, a, b, c); ROUND(46, c, d, e, f, g, h, a, b); ROUND(47, b, c, d, e, f, g, h, a); ROUND(48, a, b, c, d, e, f, g, h); ROUND(49, h, a, b, c, d, e, f, g); ROUND(50, g, h, a, b, c, d, e, f); ROUND(51, f, g, h, a, b, c, d, e); ROUND(52, e, f, g, h, a, b, c, d); ROUND(53, d, e, f, g, h, a, b, c); ROUND(54, c, d, e, f, g, h, a, b); ROUND(55, b, c, d, e, f, g, h, a); ROUND(56, a, b, c, d, e, f, g, h); ROUND(57, h, a, b, c, d, e, f, g); ROUND(58, g, h, a, b, c, d, e, f); ROUND(59, f, g, h, a, b, c, d, e); ROUND(60, e, f, g, h, a, b, c, d); ROUND(61, d, e, f, g, h, a, b, c); ROUND(62, c, d, e, f, g, h, a, b); ROUND(63, b, c, d, e, f, g, h, a); ROUND(64, a, b, c, d, e, f, g, h); ROUND(65, h, a, b, c, d, e, f, g); ROUND(66, g, h, a, b, c, d, e, f); ROUND(67, f, g, h, a, b, c, d, e); ROUND(68, e, f, g, h, a, b, c, d); ROUND(69, d, e, f, g, h, a, b, c); ROUND(70, c, d, e, f, g, h, a, b); ROUND(71, b, c, d, e, f, g, h, a); ROUND(72, a, b, c, d, e, f, g, h); ROUND(73, h, a, b, c, d, e, f, g); ROUND(74, g, h, a, b, c, d, e, f); ROUND(75, f, g, h, a, b, c, d, e); ROUND(76, e, f, g, h, a, b, c, d); ROUND(77, d, e, f, g, h, a, b, c); ROUND(78, c, d, e, f, g, h, a, b); ROUND(79, b, c, d, e, f, g, h, a); state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; state[5] += f; state[6] += g; state[7] += h; block += SHA512_BLOCK_SIZE; } while (--count); #undef ROUND #undef W #undef Ch #undef Maj #undef BSig0 #undef BSig1 #undef SSig0 #undef SSig1 } void sha512_init(sha512_ctx* ctx) { ctx->count[0] = 0; ctx->count[1] = 0; ctx->state[0] = 0x6a09e667f3bcc908; ctx->state[1] = 0xbb67ae8584caa73b; ctx->state[2] = 0x3c6ef372fe94f82b; ctx->state[3] = 0xa54ff53a5f1d36f1; ctx->state[4] = 0x510e527fade682d1; ctx->state[5] = 0x9b05688c2b3e6c1f; ctx->state[6] = 0x1f83d9abfb41bd6b; ctx->state[7] = 0x5be0cd19137e2179; } void sha512_update(sha512_ctx* ctx, const void* data, size_t size) { const uint8_t* buffer = (const uint8_t*)data; size_t pending = ctx->count[0] % SHA512_BLOCK_SIZE; ctx->count[0] += size; ctx->count[1] += size > ctx->count[0]; size_t available = SHA512_BLOCK_SIZE - pending; if (pending && size >= available) { memcpy(ctx->buffer + pending, buffer, available); sha512_process(ctx->state, ctx->buffer, 1); buffer += available; size -= available; pending = 0; } size_t count = size / SHA512_BLOCK_SIZE; if (count) { sha512_process(ctx->state, buffer, count); buffer += count * SHA512_BLOCK_SIZE; size -= count * SHA512_BLOCK_SIZE; } memcpy(ctx->buffer + pending, buffer, size); } void sha512_finish(sha512_ctx* ctx, uint8_t digest[SHA512_DIGEST_SIZE]) { uint64_t count0 = ctx->count[0]; uint64_t count1 = ctx->count[1]; uint64_t bitcount[2] = { (count0 << 3), (count1 << 3) | (count0 >> 61) }; size_t pending = count0 % SHA512_BLOCK_SIZE; size_t blocks = pending < SHA512_BLOCK_SIZE - sizeof(bitcount) ? 1 : 2; ctx->buffer[pending++] = 0x80; uint8_t padding[2 * SHA512_BLOCK_SIZE]; memcpy(padding, ctx->buffer, SHA512_BLOCK_SIZE); memset(padding + pending, 0, SHA512_BLOCK_SIZE); SHA512_SET64BE(padding + blocks * SHA512_BLOCK_SIZE - 2*sizeof(uint64_t), bitcount[1]); SHA512_SET64BE(padding + blocks * SHA512_BLOCK_SIZE - 1*sizeof(uint64_t), bitcount[0]); sha512_process(ctx->state, padding, blocks); for (size_t i=0; i<8; i++) { SHA512_SET64BE(digest + i*sizeof(uint64_t), ctx->state[i]); } } void sha384_init(sha384_ctx* ctx) { ctx->count[0] = 0; ctx->count[1] = 0; ctx->state[0] = 0xcbbb9d5dc1059ed8; ctx->state[1] = 0x629a292a367cd507; ctx->state[2] = 0x9159015a3070dd17; ctx->state[3] = 0x152fecd8f70e5939; ctx->state[4] = 0x67332667ffc00b31; ctx->state[5] = 0x8eb44a8768581511; ctx->state[6] = 0xdb0c2e0d64f98fa7; ctx->state[7] = 0x47b5481dbefa4fa4; } void sha384_update(sha512_ctx* ctx, const void* data, size_t size) { sha512_update(ctx, data, size); } void sha384_finish(sha384_ctx* ctx, uint8_t digest[SHA384_DIGEST_SIZE]) { uint8_t temp[SHA512_DIGEST_SIZE]; sha512_finish(ctx, temp); memcpy(digest, temp, SHA384_DIGEST_SIZE); } #if defined(__clang__) # pragma clang diagnostic pop #elif defined(_MSC_VER) # pragma warning (pop) #endif ================================================ FILE: src/third_party/rad_lzb_simple/rad_lzb_simple.c ================================================ #include //------------------------------------------------- // UINTr = int the size of a register #ifdef __RAD64REGS__ #define RAD_UINTr RAD_U64 #define RAD_SINTr RAD_S64 #define readR read64 #define writeR write64 #define rrClzBytesR rrClzBytes64 #define rrCtzBytesR rrCtzBytes64 #else #define RAD_UINTr RAD_U32 #define RAD_SINTr RAD_S32 #define readR read32 #define writeR write32 #define rrClzBytesR rrClzBytes32 #define rrCtzBytesR rrCtzBytes32 #endif typedef RAD_SINTr SINTr; typedef RAD_UINTr UINTr; #define OOINLINE RADFORCEINLINE #define if_unlikely(exp) if ( RAD_UNLIKELY( exp ) ) #define if_likely( exp) if ( RAD_LIKELY( exp ) ) // Raw byte IO #if defined(__RADARM__) && !defined(__RAD64__) && defined(__GNUC__) // older GCCs don't turn the memcpy variant into loads/stores, but // they do support this: typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unaligned_type; static inline U16 read16(const void *ptr) { return ((const unaligned_type *)ptr)->u16; } static inline void write16(void *ptr, U16 x) { ((unaligned_type *)ptr)->u16 = x; } static inline U32 read32(const void *ptr) { return ((const unaligned_type *)ptr)->u32; } static inline void write32(void *ptr, U32 x) { ((unaligned_type *)ptr)->u32 = x; } static inline U64 read64(const void *ptr) { return ((const unaligned_type *)ptr)->u64; } static inline void write64(void *ptr, U64 x) { ((unaligned_type *)ptr)->u64 = x; } #else // most C compilers we target are smart enough to turn this into single loads/stores static inline U16 read16(const void *ptr) { U16 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write16(void *ptr, U16 x) { memcpy(ptr, &x, sizeof(x)); } static inline U32 read32(const void *ptr) { U32 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write32(void *ptr, U32 x) { memcpy(ptr, &x, sizeof(x)); } static inline U64 read64(const void *ptr) { U64 x; memcpy(&x, ptr, sizeof(x)); return x; } static inline void write64(void *ptr, U64 x) { memcpy(ptr, &x, sizeof(x)); } #endif #define RR_PUT16_LE_UNALIGNED(ptr,val) RR_PUT16_LE(ptr,val) #define RR_PUT16_LE_UNALIGNED_OFFSET(ptr,val,offset) RR_PUT16_LE_OFFSET(ptr,val,offset) //=========================================================================== static RADINLINE SINTa rrPtrDiffV(void * end, void *start) { return (SINTa)( ((char *)(end)) - ((char *)(start)) ); } // helper function to show I really am intending to put a pointer difference in an int : static RADINLINE SINTa rrPtrDiff(SINTa val) { return val; } static RADINLINE S32 rrPtrDiff32(SINTa val) { S32 ret = (S32) val; RR_ASSERT( (SINTa)ret == val ); return ret; } static RADINLINE SINTr rrPtrDiffR(SINTa val) { SINTr ret = (SINTr) val; RR_ASSERT( (SINTa)ret == val ); return ret; } //================================================================= #define LZB_LRL_BITS 4 #define LZB_LRL_ESCAPE 15 #define LZB_ML_BITS 4 #define LZB_MLCONTROL_ESCAPE 15 #define LZB_SLIDING_WINDOW_POW2 16 #define LZB_SLIDING_WINDOW_SIZE (1<>= 6; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; \ if ( val < 128 ) *cp++ = (U8) val; \ else { val -= 128; *cp++ = 128 + (U8) ( val&0x7F); val >>= 7; *cp++ = (U8) val; } } } } \ } while(0) // max bytes consumed: 5 #define LZB_AddExcessBW(cp,val) do { U32 b = *cp++; \ if ( b < 192 ) val += b; \ else { val += 192; val += (b-192); b = *cp++; \ val += (b<<6); if ( b >= 128 ) { b = *cp++; \ val += (b<<13); if ( b >= 128 ) { b = *cp++; \ val += (b<<20); if ( b >= 128 ) { b = *cp++; \ val += (b<<27); } } } } \ } while(0) #define LZB_PutExcessLRL(cp,val) LZB_PutExcessBW(cp,val) #define LZB_PutExcessML(cp,val) LZB_PutExcessBW(cp,val) #define LZB_AddExcessLRL(cp,val) LZB_AddExcessBW(cp,val) #define LZB_AddExcessML(cp,val) LZB_AddExcessBW(cp,val) //============================================================================= // match copies : // used for LRL : static OOINLINE void copy_no_overlap_long(U8 * to, const U8 * from, SINTr length) { for(int i=0;i= LZB_MML && ml < LZB_MATCHLEN_ESCAPE ); // overlap // @@ err not awesome to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to[4] = from[4]; to[5] = from[5]; to[6] = from[6]; to[7] = from[7]; if ( ml > 8 ) { to += 8; from += 8; ml -= 8; // max of 10 more while(ml--) { *to++ = *from++; } } } static OOINLINE void copy_match_memset(U8 * to, int c, SINTr ml) { RR_ASSERT( ml >= 4 ); U32 four = c * 0x01010101; U8 * end = to + ml; write32(to, four); to += 4; while(to>4); // copy 4 literals speculatively : write32( rp , read32(cp) ); //RR_ASSERT( lrl >= 8 || ml_control >= 8 ); if ( lrl > 4 ) { // if lrl was <= 8 we did it, else need this : if_unlikely ( lrl > 8 ) { if_unlikely ( lrl >= LZB_LRL_ESCAPE ) { LZB_AddExcessLRL( cp, lrl ); // hide the EOF check here ? // has to be after the GetExcess if_unlikely ( rp+lrl >= rpEnd ) { RR_ASSERT( rp+lrl == rpEnd ); copy_no_overlap_nooverrun(rp,cp,lrl); rp += lrl; cp += lrl; break; } else { // total undo of the previous copy copy_no_overlap_long(rp,cp,lrl); } } else // > 8 but not 0xF { // hide the EOF check here ? if_unlikely ( rp+lrl >= rpEnd ) { if ( lrl == 9 ) { // may be a false 9 lrl = rrPtrDiff32( rpEnd - rp ); } RR_ASSERT( rp+lrl == rpEnd ); copy_no_overlap_nooverrun(rp,cp,lrl); rp += lrl; cp += lrl; break; } else { write32( rp+4 , read32(cp+4) ); // put 8 more : write64( (rp+8) , read64((cp+8)) ); } } } else { write32( rp+4 , read32(cp+4) ); } } rp += lrl; cp += lrl; RR_ASSERT( rp+LZB_MML <= rpEnd ); UINTr ml = ml_control + LZB_MML; // speculatively grab offset but don't advance cp yet UINTr off = RR_GET16_LE_UNALIGNED(cp); if ( ml_control <= 8 ) { cp += 2; // consume offset const U8 * match = rp - off; RR_ASSERT( ml <= 12 ); write64( rp , read64(match) ); write32( rp+8 , read32(match+8) ); rp += ml; continue; } else { if_likely( ml_control < LZB_MLCONTROL_ESCAPE ) // short match { cp += 2; // consume offset const U8 * match = rp - off; RR_ASSERT( off >= 8 || ml <= off ); write64( rp , read64(match) ); write64( rp+8 , read64(match+8) ); if ( ml > 16 ) { write16( rp+16, read16(match+16) ); } } else { // get 1-byte excess code UINTr excesslow = off&127; cp++; // consume 1 //if ( excess1 >= 128 ) if ( off & 128 ) { ml_control = excesslow >> 3; ml = ml_control + LZB_MML; if ( ml_control == 0xF ) { // get more ml LZB_AddExcessML( cp, ml ); } UINTr myoff = off & 7; // low offset, can't do 8-byte grabs if ( myoff == 1 ) { int c = rp[-1]; copy_match_memset(rp,c,ml); } else { // shit but whatever, very rare for(UINTr i=0;i>13); return h; } #define HashMatchFinder_Hash32 hmf_hash4_32 //================================================================================= #define LZB_Hash4 hmf_hash4_32 static RADINLINE U32 LZB_SecondHash4(U32 be4) { const U32 m = 0x5bd1e995; U32 h = be4 * m; h += (h>>11); return h; } //============================================= static int RADFORCEINLINE GetNumBytesZeroNeverAllR(UINTr x) { RR_ASSERT( x != 0 ); #if defined(__RADBIGENDIAN__) // big endian, so earlier bytes are at the top int nb = (int)rrClzBytesR(x); #elif defined(__RADLITTLEENDIAN__) // little endian, so earlier bytes are at the bottom int nb = (int)rrCtzBytesR(x); #else #error wtf no endian set #endif RR_ASSERT( nb >= 0 && nb < (int)sizeof(UINTr) ); return nb; } //=============================== static RADFORCEINLINE U8 * LZB_Output(U8 * cp, S32 lrl, const U8 * literals, S32 matchlen , S32 mo ) { RR_ASSERT( lrl >= 0 ); RR_ASSERT( matchlen >= LZB_MML ); RR_ASSERT( mo > 0 && mo <= LZB_MAX_OFFSET ); //rrprintf("[%3d][%3d][%7d]\n",lrl,ml,mo); S32 sendml = matchlen - LZB_MML; U32 ml_in_control = RR_MIN(sendml,LZB_MLCONTROL_ESCAPE); if ( mo >= 8 ) // no overlap { if ( lrl < LZB_LRL_ESCAPE ) { U32 control = lrl | (ml_in_control<<4); *cp++ = (U8) control; write64(cp, read64(literals)); if ( lrl > 8 ) { write64(cp+8, read64(literals+8)); } cp += lrl; } else { U32 control = LZB_LRL_ESCAPE | (ml_in_control<<4); *cp++ = (U8) control; U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); // @@ ? is this okay for overrun ? lz_copysteptoend_overrunok(cp,literals,lrl); } if ( ml_in_control < LZB_MLCONTROL_ESCAPE ) { RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; } else { U32 ml_excess = sendml - LZB_MLCONTROL_ESCAPE; // put special first byte, then offset, then remainder if ( ml_excess < 127 ) { *cp++ = (U8)ml_excess; RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; } else { *cp++ = (U8)127; RR_ASSERT( (U16)(mo) == mo ); RR_PUT16_LE_UNALIGNED(cp,(U16)(mo)); cp += 2; ml_excess -= 127; LZB_PutExcessML(cp,ml_excess); } } } else { U32 lrl_in_control = RR_MIN(lrl,LZB_LRL_ESCAPE); // overlap case U32 control = (lrl_in_control) | (LZB_MLCONTROL_ESCAPE<<4); *cp++ = (U8) control; if ( lrl_in_control == LZB_LRL_ESCAPE ) { U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); } lz_copysteptoend_overrunok(cp,literals,lrl); //cp += lrl; // special excess1 : UINTr excess1 = 128 + (ml_in_control<<3) + mo; RR_ASSERT( excess1 < 256 ); *cp++ = (U8)excess1; if ( ml_in_control == LZB_MLCONTROL_ESCAPE ) { U32 ml_excess = sendml - LZB_MLCONTROL_ESCAPE; LZB_PutExcessML(cp,ml_excess); } } return cp; } #if LZB_FORCELASTLRL9 static RADINLINE U8 * LZB_OutputLast(U8 * cp, S32 lrl, const U8 * literals ) { RR_ASSERT( lrl >= 0 ); //U32 ml = 0; //U32 mo = 0; U32 lrl_in_control = RR_MIN(lrl,LZB_LRL_ESCAPE); #if LZB_END_WITH_LITERALS // lrl_in_control must be at least 9 lrl_in_control = RR_MAX(lrl_in_control,9); #endif U32 control = lrl_in_control; *cp++ = (U8) control; if ( lrl_in_control == LZB_LRL_ESCAPE ) { U32 lrl_excess = lrl - LZB_LRL_ESCAPE; LZB_PutExcessLRL(cp,lrl_excess); } memmove(cp,literals,lrl); cp += lrl; return cp; } #else static RADINLINE U8 * LZB_OutputLast(U8 * cp, S32 lrl, const U8 * literals ) { cp = LZB_Output(cp,lrl,literals,LZB_MML,1); // remove the offset we put : cp -= 2; return cp; } #endif //=============================================================== static void rr_lzb_simple_context_init(rr_lzb_simple_context * ctx) //, const void * base) { RR_ASSERT( ctx->m_tableSizeBits >= 12 && ctx->m_tableSizeBits <= 24 ); memset(ctx->m_hashTable,0,sizeof(U16)*((SINTa)1<m_tableSizeBits)); } //=============================================================== /* #define FAST_HASH_DEPTH_SHIFT (1) // more depth = more & more compression, #define DO_FAST_2ND_HASH // rate= 30.69 mb/s , 15451369 <- turning this off is the best way to get more speed and less compression /*/ #define FAST_HASH_DEPTH_SHIFT (0) #define DO_FAST_2ND_HASH /**/ // lzt99, 24700820, 15475520, 16677179 //encode only : 0.880 seconds, 1.62 b/hc, rate= 28.08 mb/s //#define FAST_HASH_DEPTH_SHIFT (1) // more depth = more & more compression, but slower #define DO_FAST_UPDATE_MATCH_HASHES 1 // helps compression a lot , like 0.30 //#define DO_FAST_UPDATE_MATCH_HASHES 2 // helps compression a lot , like 0.30 #define DO_FAST_LAZY_MATCH // also helps a lot , like 0.15 #define DO_FAST_HASH_DWORD 1 #define FAST_MULTISTEP_LITERALS_SHIFT (5) //----------------------- // derived : /* #define FAST_HASH_BITS (FAST_HASH_TOTAL_BITS-FAST_HASH_DEPTH_SHIFT) #define FAST_HASH_SIZE (1< 1 #define FAST_HASH_INDEX(h,d) ( ((h)< 1 int hashCycle = 0; #endif U16 * hashTable16 = fh->m_hashTable; int hashTableSizeBits = fh->m_tableSizeBits; U32 hash_table_mask = (U32)((1UL<<(hashTableSizeBits - FAST_HASH_DEPTH_SHIFT)) - 1); const U8 * zeroPosPtr = (const U8 *)raw; // first byte is always a literal rp++; for(;;) { S32 matchOff; UINTr failedMatches = (1<= 0 ); #ifdef DO_FAST_2ND_HASH hash2 = ( LZB_SecondHash4(rp32) ) & hash_table_mask; #endif #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); hashrp = rp - matchOff; //if ( matchOff <= LZB_MAX_OFFSET ) RR_ASSERT( matchOff <= LZB_MAX_OFFSET ); { const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } } } #ifdef DO_FAST_2ND_HASH #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); hashrp = rp - matchOff; RR_ASSERT( matchOff <= LZB_MAX_OFFSET ); { const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } } } #endif //--------------------------- // update hash : hashTable16[ FAST_HASH_INDEX(hash,hashCycle) ] = (U16) curpos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! //hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; hashTable16[ FAST_HASH_INDEX(hash2,hashCycle) ] = (U16) curpos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif UINTr stepLiterals = (failedMatches>>FAST_MULTISTEP_LITERALS_SHIFT); RR_ASSERT( stepLiterals >= 1 ); ++failedMatches; rp += stepLiterals; if ( rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } //------------------------------- found_match: // found something //------------------------- // update hash now so lazy can see it : #if 1 // pretty important to compression hashTable16[ FAST_HASH_INDEX(hash,hashCycle) ] = (U16) curpos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! //hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; hashTable16[ FAST_HASH_INDEX(hash2,hashCycle) ] = (U16) curpos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif #endif //----------------------------------- const U8 * match_start = rp; rp += 4; while( rp < rpEndSafe ) { UINTr big1 = readR(rp); UINTr big2 = readR(rp-matchOff); if ( big1 == big2 ) { rp += RAD_PTRBYTES; continue; } else { rp += GetNumBytesZeroNeverAllR(big1^big2); break; } } rp = RR_MIN(rp,rpMatchEnd); //------------------------------- // rp is now at the *end* of the match //------------------------------- // check lazy match too #ifdef DO_FAST_LAZY_MATCH if (rp< rpEndSafe) { const U8 * lazyrp = match_start + 1; //SINTa lazypos = rrPtrDiff(lazyrp - zeroPosPtr); SINTa lazypos = curpos + 1; RR_ASSERT( lazypos == rrPtrDiff(lazyrp - zeroPosPtr) ); U32 lazyrp32 = read32(lazyrp); const U8 * lazyhashrp; SINTa lazymatchOff; U32 lazyHash = FAST_HASH_FUNC(lazyrp, lazyrp32 ); #ifdef DO_FAST_2ND_HASH U32 lazyhash2 = LZB_SecondHash4(lazyrp32) & hash_table_mask; #endif #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); RR_ASSERT( lazymatchOff <= LZB_MAX_OFFSET ); { lazyhashrp = lazyrp - lazymatchOff; const U32 hashrp32 = read32(lazyhashrp); if ( lazyrp32 == hashrp32 && lazymatchOff != 0 ) { goto lazy_found_match; } } } #ifdef DO_FAST_2ND_HASH #if FAST_HASH_DEPTH > 1 for(int d=0;d= 0 ); RR_ASSERT( lazymatchOff <= LZB_MAX_OFFSET ); { lazyhashrp = lazyrp - lazymatchOff; const U32 hashrp32 = read32(lazyhashrp); if ( lazyrp32 == hashrp32 && lazymatchOff != 0 ) { goto lazy_found_match; } } } #endif if ( 0 ) { lazy_found_match: lazyrp += 4; while( lazyrp < rpEndSafe ) { UINTr big1 = readR(lazyrp); UINTr big2 = readR(lazyrp-lazymatchOff); if ( big1 == big2 ) { lazyrp += RAD_PTRBYTES; continue; } else { lazyrp += GetNumBytesZeroNeverAllR(big1^big2); break; } } lazyrp = RR_MIN(lazyrp,rpMatchEnd); //S32 lazymatchLen = rrPtrDiff32( lazyrp - (match_start+1) ); //RR_ASSERT( lazymatchLen >= 4 ); if ( lazyrp >= rp+3 ) { // yes take the lazy match // put a literal : match_start++; // I had a bug where lazypos was set wrong for the hash fill // it set it to the *end* of the normal match // and for some reason that helped compression WTF WTF //SINTa lazypos = rrPtrDiff(rp - zeroPosPtr); // 233647528 // with correct lazypos : 233651228 // really this shouldn't be necessary at all // because I do an update of hash at all positions in the match including first! #if 1 // with update disabled - 233690274 hashTable16[ FAST_HASH_INDEX(lazyHash,hashCycle) ] = (U16) lazypos; #ifdef DO_FAST_2ND_HASH // do NOT step hashCycle ! hashTable16[ FAST_HASH_INDEX(lazyhash2,hashCycle) ] = (U16) lazypos; #endif #if FAST_HASH_DEPTH > 1 hashCycle = (hashCycle+1)&FAST_HASH_CYCLE_MASK; #endif #endif // and then drop out and do the lazy match : //matchLen = lazymatchLen; matchOff = (S32)lazymatchOff; rp = lazyrp; hashrp = lazyhashrp; } } } #endif //--------------------------------------------------- // back up start of match that we missed due to stepLiterals ! // make sure we don't read off the start of the array // this costs a little speed and gains a little compression // 15662162 at 121.58 mb/s // 15776473 at 127.92 mb/s #if 1 /* lzbf : 24,700,820 ->15,963,503 = 5.170 bpb = 1.547 to 1 encode : 0.171 seconds, 83.60 b/kc, rate= 144.54 M/s decode : 0.014 seconds, 1002.64 b/kc, rate= 1733.57 M/s */ { // 144 M/s // back up start of match that we missed // make sure we don't read off the start of the array const U8 * rpm1 = match_start-1; if ( rpm1 >= literals_start && hashrp > zeroPosPtr && rpm1[0] == hashrp[-1] ) { rpm1--; hashrp-= 2; while ( rpm1 >= literals_start && hashrp >= zeroPosPtr && rpm1[0] == *hashrp ) { rpm1--; hashrp--; } match_start = rpm1+1; //rp = RR_MAX(rp,literals_start); RR_ASSERT( match_start >= literals_start ); } } #endif S32 matchLen = rrPtrDiff32( rp - match_start ); RR_ASSERT( matchLen >= 4 ); //=============================================== // chose a match // output LRL (if any) and match S32 cur_lrl = rrPtrDiff32(match_start - literals_start); // catch expansion while writing : if_unlikely ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_Output(cp,cur_lrl,literals_start,matchLen,matchOff); // skip the match : literals_start = rp; if ( rp >= rpEndSafe ) break; // step & update hashes : // (I already did cur pos) #ifdef DO_FAST_UPDATE_MATCH_HASHES // don't bother if it takes us to the end : // (this check is not for speed it's to avoid the access violation) const U8 * ptr = match_start+1; U16 pos16 = (U16) rrPtrDiff( ptr - zeroPosPtr ); for(;ptr 0 ); #endif if ( cur_lrl > 0 ) { // catch expansion while writing : if ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_OutputLast(cp,cur_lrl,literals_start); } SINTa compLen = rrPtrDiff( cp - (U8 *)comp ); return compLen; } SINTa rr_lzb_simple_encode_fast(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { rr_lzb_simple_context_init(fh); //,raw); SINTa comp_len = rr_lzb_simple_encode_fast_sub(fh,raw,rawLen,comp); if ( comp_len >= rawLen ) { memcpy(comp,raw,rawLen); return rawLen; } return comp_len; } #undef FAST_HASH_DEPTH_SHIFT #undef DO_FAST_UPDATE_MATCH_HASHES #undef DO_FAST_LAZY_MATCH #undef DO_FAST_2ND_HASH //===================================================== #define FAST_HASH_DEPTH_SHIFT (0) #undef FAST_MULTISTEP_LITERALS_SHIFT #define FAST_MULTISTEP_LITERALS_SHIFT (4) //----------------------- // derived : RR_COMPILER_ASSERT( FAST_HASH_DEPTH_SHIFT == 0 ); #undef FAST_HASH_FUNC //#define FAST_HASH_FUNC(ptr,dword) ( LZB_Hash4(dword) & hash_table_mask ) #define FAST_HASH_FUNC(ptr,dword) ( (((dword)*2654435761U)>>16) & hash_table_mask ) // @@@@ ???? #define LZBVF_DO_BACKUP 0 //#define LZBVF_DO_BACKUP 1 static SINTa rr_lzb_simple_encode_veryfast_sub(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { //SIMPLEPROFILE_SCOPE_N(lzbfast_sub,rawLen); //THREADPROFILEFUNC(); U8 * cp = (U8 *)comp; U8 * compExpandedPtr = cp + rawLen - 8; const U8 * rp = (const U8 *)raw; const U8 * rpEnd = rp+rawLen; // we can match up to rpEnd // but matches can't start past rpEndSafe const U8 * rpMatchEnd = rpEnd - LZB_END_OF_BLOCK_NO_MATCH_ZONE; const U8 * rpEndSafe = rpMatchEnd - LZB_MML; if ( rpEndSafe <= (U8 *)raw ) { // can't compress return rawLen+1; } const U8 * literals_start = rp; U16 * hashTable16 = fh->m_hashTable; int hashTableSizeBits = fh->m_tableSizeBits; U32 hash_table_mask = (U32)((1UL<<(hashTableSizeBits)) - 1); const U8 * zeroPosPtr = (const U8 *)raw; // first byte is always a literal rp++; for(;;) { U32 rp32 = read32(rp); U32 hash = FAST_HASH_FUNC(rp, rp32 ); const U8 * hashrp; S32 matchOff; UINTr failedMatches; // loop while no match found : // first loop with step = 1 // @@ //int step1count = (1<= 0 ); U16 hashpos16 = hashTable16[hash]; hashTable16[ hash ] = (U16) curpos; matchOff = (U16)(curpos - hashpos16); RR_ASSERT( matchOff >= 0 && matchOff <= LZB_MAX_OFFSET ); hashrp = rp - matchOff; const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } if ( ++rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } // step starts at 2 : failedMatches = (2<= 0 ); U16 hashpos16 = hashTable16[hash]; hashTable16[ hash ] = (U16) curpos; matchOff = (U16)(curpos - hashpos16); RR_ASSERT( matchOff >= 0 && matchOff <= LZB_MAX_OFFSET ); hashrp = rp - matchOff; const U32 hashrp32 = read32(hashrp); if ( rp32 == hashrp32 && matchOff != 0 ) { goto found_match; } UINTr stepLiterals = (failedMatches>>FAST_MULTISTEP_LITERALS_SHIFT); RR_ASSERT( stepLiterals >= 1 ); ++failedMatches; rp += stepLiterals; if ( rp >= rpEndSafe ) goto done; rp32 = read32(rp); hash = FAST_HASH_FUNC(rp, rp32 ); } //------------------------------- found_match:; // found something #if LZBVF_DO_BACKUP // alternative backup using counter : S32 cur_lrl = rrPtrDiff32(rp - literals_start); int neg_max_backup = - RR_MIN(cur_lrl , rrPtrDiff32(hashrp - zeroPosPtr) ); int neg_backup = -1; if( neg_backup >= neg_max_backup && rp[neg_backup] == hashrp[neg_backup] ) { neg_backup--; while( neg_backup >= neg_max_backup && rp[neg_backup] == hashrp[neg_backup] ) { neg_backup--; } neg_backup++; rp += neg_backup; cur_lrl += neg_backup; RR_ASSERT( cur_lrl >= 0 ); RR_ASSERT( cur_lrl == rrPtrDiff32(rp - literals_start) ); } #else S32 cur_lrl = rrPtrDiff32(rp - literals_start); #endif // catch expansion while writing : if_unlikely ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } RR_ASSERT( matchOff >= 1 ); //--------------------------------------- // find rest of match len // save pointer to start of match // walk rp ahead to end of match const U8 * match_start = rp; rp += 4; while( rp < rpEndSafe ) { UINTr big1 = readR(rp); UINTr big2 = readR(rp-matchOff); if ( big1 == big2 ) { rp += RAD_PTRBYTES; continue; } else { rp += GetNumBytesZeroNeverAllR(big1^big2); break; } } rp = RR_MIN(rp,rpMatchEnd); S32 matchLen = rrPtrDiff32( rp - match_start ); //=============================================== // chose a match // output LRL (if any) and match cp = LZB_Output(cp,cur_lrl,literals_start,matchLen,matchOff); // skip the match : literals_start = rp; if ( rp >= rpEndSafe ) goto done; } done:; int cur_lrl = rrPtrDiff32(rpEnd - literals_start); #if LZB_END_WITH_LITERALS RR_ASSERT_ALWAYS(cur_lrl > 0 ); #endif if ( cur_lrl > 0 ) { // catch expansion while writing : if ( cp+cur_lrl >= compExpandedPtr ) { return rawLen+1; } cp = LZB_OutputLast(cp,cur_lrl,literals_start); } SINTa compLen = rrPtrDiff( cp - (U8 *)comp ); return compLen; } SINTa rr_lzb_simple_encode_veryfast(rr_lzb_simple_context * fh, const void * raw, SINTa rawLen, void * comp) { rr_lzb_simple_context_init(fh); //,raw); SINTa comp_len = rr_lzb_simple_encode_veryfast_sub(fh,raw,rawLen,comp); if ( comp_len >= rawLen ) { memcpy(comp,raw,rawLen); return rawLen; } return comp_len; } #undef FAST_HASH_DEPTH_SHIFT #undef DO_FAST_UPDATE_MATCH_HASHES #undef DO_FAST_LAZY_MATCH #undef DO_FAST_2ND_HASH //===================================================== // vim:noet:sw=4:ts=4 ================================================ FILE: src/third_party/rad_lzb_simple/rad_lzb_simple.h ================================================ #ifndef _RAD_LZB_SIMPLE_H_ #define _RAD_LZB_SIMPLE_H_ /*====================================================== To encode : Set up an rr_lzb_simple_context fill out m_tableSizeBits (14-16 is typical) allocate m_hashTable rr_lzb_simple_context c; c.m_tableSizeBits = 14; c.m_hashTable = OODLE_MALLOC_ARRAY(U16,RR_ONE_SA< typedef uint8_t U8; typedef uint16_t U16; typedef uint32_t U32; typedef uint64_t U64; typedef int8_t S8; typedef int16_t S16; typedef int32_t S32; typedef int64_t S64; typedef S64 SINTa; typedef U64 RAD_U64; typedef S64 RAD_S64; typedef U32 RAD_U32; typedef S32 RAD_S32; #define RADINLINE __inline #if defined(_MSC_VER) # define RADFORCEINLINE __forceinline #elif defined(__clang__) || defined(__GNUC__) # define RADFORCEINLINE __attribute__((always_inline)) #else # error need force inline for this compiler #endif #if _MSC_VER # define RADLZB_TRAP() __debugbreak() #elif __clang__ || __GNUC__ # define RADLZB_TRAP() __builtin_trap() #else # error Unknown trap intrinsic for this compiler. #endif #define RR_STRING_JOIN(arg1, arg2) RR_STRING_JOIN_DELAY(arg1, arg2) #define RR_STRING_JOIN_DELAY(arg1, arg2) RR_STRING_JOIN_IMMEDIATE(arg1, arg2) #define RR_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 #ifdef _MSC_VER #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__COUNTER__) #else #define RR_NUMBERNAME(name) RR_STRING_JOIN(name,__LINE__) #endif #define RR_COMPILER_ASSERT(exp) typedef char RR_NUMBERNAME(_dummy_array) [ (exp) ? 1 : -1 ] #if defined(__clang__) # define Expect(expr, val) __builtin_expect((expr), (val)) #else # define Expect(expr, val) (expr) #endif #define RAD_LIKELY(expr) Expect(expr,1) #define RAD_UNLIKELY(expr) Expect(expr,0) #define __RADLITTLEENDIAN__ 1 #define RAD_PTRBYTES 8 #define RR_MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define RR_MAX(a,b) ( (a) > (b) ? (a) : (b) ) #define RR_ASSERT_ALWAYS(c) do{if(!(c)) {RADLZB_TRAP();}}while(0) #define RR_ASSERT(c) RR_ASSERT_ALWAYS(c) #define RR_PUT16_LE(ptr,val) *((U16 *)(ptr)) = (U16)(val) #define RR_GET16_LE_UNALIGNED(ptr) *((const U16 *)(ptr)) static RADINLINE U32 rrCtzBytes32(U32 val) { // Don't get fancy here. Assumes val != 0. if (val & 0x000000ffu) return 0; if (val & 0x0000ff00u) return 1; if (val & 0x00ff0000u) return 2; return 3; } static RADINLINE U32 rrCtzBytes64(U64 val) { U32 lo = (U32) val; return lo ? rrCtzBytes32(lo) : 4 + rrCtzBytes32((U32) (val >> 32)); } //~ //--------------------- typedef struct rr_lzb_simple_context rr_lzb_simple_context; struct rr_lzb_simple_context { U16 * m_hashTable; // must be allocated to sizeof(U16)*(1< // for size_t #ifdef _MSC_VER #define RSFORCEINLINE __forceinline __declspec(safebuffers) #define CompilerReset(ptr) __assume(ptr) #else #define RSFORCEINLINE __attribute__((always_inline)) #define CompilerReset(ptr) #endif #if defined(_x86_64) || defined( __x86_64__ ) || defined( _M_X64 ) || defined(__x86_64) || defined(_M_AMD64) || defined(__SSE__) || defined(__SSE2__) || defined(USE_SSE) #include #define RS_PREFETCH( addr ) _mm_prefetch( (addr), 0 ) #endif // nonsense to make adding pointers a more convenient #define rsadd_ptr( ptr, ind ) (((char*)(ptr))+(ptrdiff_t)(ind)) #define rssub_ptr( ptr, ind ) (((char*)(ptr))-(ptrdiff_t)(ind)) #define rsadd_ptr_elements( ptr, ind ) rsadd_ptr( ptr, (ptrdiff_t)(ind)*(ptrdiff_t)element_size ) #define rsdiff_ptr_elements( ptra, ptrb ) ( (size_t)(((char*)(ptra))-((char*)(ptrb))) / (size_t)element_size ) // this is the maximum size of struct that we treat as a "simple" struct typedef struct RS_MAX_SIMPLE_BUF { char b[32]; } RS_MAX_SIMPLE_BUF; // todo, 64-bit // ============================================================================================================== // swap and move utility functions typedef struct bytes64 { char b[64]; } bytes64; // copying with this turns into m512 moves (when arch is set) typedef struct bytes32 { char b[32]; } bytes32; // copying with this turns into m256 moves (when arch is set) typedef struct bytes16 { char b[16]; } bytes16; // copying with this turns into m128 moves typedef struct bytes8 { char b[8]; } bytes8; static RSFORCEINLINE void radsortswapper( void * a, void * b, size_t size ) { #define RSSWAPMEM(type) ( size >= sizeof(type) ) { type v = *(type const*)a; *(type*)a = *(type const*)b; *(type*)b = v; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } while RSSWAPMEM(bytes64); if RSSWAPMEM(bytes32); if RSSWAPMEM(bytes16); if RSSWAPMEM(bytes8); if RSSWAPMEM(int); if RSSWAPMEM(short); if RSSWAPMEM(char); #undef RSSWAPMEM } // since size is always constant, this big function compiles down to 4 to 12 instructions (for normal structs 4-6) static RSFORCEINLINE void radsortmover( void * a, void * b, size_t size ) { #define RSMOVEMEM(type) ( size >= sizeof(type) ) { *(type*)a = *(type const*)b; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } while RSMOVEMEM(bytes64); if RSMOVEMEM(bytes32); if RSMOVEMEM(bytes16); if RSMOVEMEM(bytes8); if RSMOVEMEM(int); if RSMOVEMEM(short); if RSMOVEMEM(char); #undef RSMOVEMEM } // these macros generate tiny move/swap routines that don't go through the generic function above (mostly for debug build performance) #define RS_SIMPLE_SIZES _X(1) _X(2) _X(4) _X(8) _X(12) _X(16) #define rsmoverfunc( num ) static RSFORCEINLINE void radsortmover##num ( void * dest, void * src, size_t element_size ) { typedef struct rs { char x[num]; } rs; *(rs*)dest = *(rs*)src; } #define rsswapperfunc( num ) static RSFORCEINLINE void radsortswapper##num( void * a, void * b, size_t element_size ) { typedef struct rs { char x[num]; } rs; rs temp; temp = *(rs*)a; *(rs*)a = *(rs*)b; *(rs*)b = temp; } #define _X rsmoverfunc RS_SIMPLE_SIZES #undef _X #define _X rsswapperfunc RS_SIMPLE_SIZES #undef _X #undef RS_SIMPLE_SIZES #undef rsmoverfunc #undef rsswapperfunc // ============================================================================================================== typedef int is_before_func( void * elementa, void * elementb ); typedef void swap_func( void * elementa, void * elementb, size_t element_size ); typedef void move_func( void * dest, void * src, size_t size ); typedef void rs_small_sort_func( void * left, size_t n, size_t element_size, is_before_func * is_before, move_func * mover, void * tmp ); #define radsortswapsize( size ) ( ( size == 1 ) ? radsortswapper1 : ( ( size == 2 ) ? radsortswapper2 : ( ( size == 4 ) ? radsortswapper4 : ( ( size == 8 ) ? radsortswapper8 : ( ( size == 12 ) ? radsortswapper12 : ( ( size == 16 ) ? radsortswapper16 : radsortswapper ) ) ) ) ) ) #define radsortmovesize( size ) ( ( size == 1 ) ? radsortmover1 : ( ( size == 2 ) ? radsortmover2 : ( ( size == 4 ) ? radsortmover4 : ( ( size == 8 ) ? radsortmover8 : ( ( size == 12 ) ? radsortmover12 : ( ( size == 16 ) ? radsortmover16 : radsortmover ) ) ) ) ) ) // todo - maybe no bubble at all? #define RS_SMALL_FLIP_TO_INSERTION_GT_SIZE sizeof( size_t ) typedef struct RS_MAX_BUBBLE_BUF { char b[RS_SMALL_FLIP_TO_INSERTION_GT_SIZE]; } RS_MAX_BUBBLE_BUF; #define radsort( start, len, is_before_func ) \ do { \ char __rs_tmp[ sizeof( (start)[0] ) ]; \ radsortinternal( start, len, sizeof( (start)[0] ), \ is_before_func, \ radsortswapsize( sizeof( (start)[0] ) ), \ radsortmovesize( sizeof( (start)[0] ) ), \ ( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? radinsertionsort : radbubble2sort, \ ( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? RSS_FLIP_TO_SMALL_SORT_INSERTION : RSS_FLIP_TO_SMALL_SORT_BUBBLE2, \ &__rs_tmp \ ); \ } while (0) #define radheapsort( start, len, is_before_func ) do { radheapsortinteral( start, len, sizeof( ((start)[0]) ), is_before_func, radsortswapsize( sizeof( ((start)[0]) ) ) ); } while (0) //=================================================================================================== // small heap sort - this sort is around 200 bytes compiled - can use directly when size is important RSFORCEINLINE void radheapsortinteral( void * start, size_t len, size_t element_size, is_before_func * is_before, swap_func * swapper ) { void * left; void * right; size_t length; left = start; right = rsadd_ptr_elements( start, len - 1 ); length = len; if ( length > 1 ) { // unusual small in-place heap sort void * i; void * ind; void * v; void * n; size_t s, k; s = length >> 1; i = rsadd_ptr_elements( left, s ); for(;;) { --s; i = rsadd_ptr_elements( i, -1 ); ind = i; k = ( s << 1 ) + 1; for(;;) { v = rsadd_ptr_elements( left, k ); n = rsadd_ptr_elements( v, 1 ); if ( ( ( n <= right ) ) && ( is_before( v, n ) ) ) { ++k; v = n; } if ( is_before( ind, v ) ) { swapper( ind, v, element_size ); ind = v; k = ( k << 1 ) + 1; if ( k < length ) continue; } // if s is non-zero, we are still building the heap! if ( s ) break; swapper( left, right, element_size ); right = rsadd_ptr_elements( right, -1 ); ind = left; k = 1; --length; if ( length <= 1 ) return; } } } } //=================================================================================================== // median routines #define rsswapsmaller( X, Y ) { RS_MAX_SIMPLE_BUF tmp; int cond; cond = is_before( &Y, &X); mover( &tmp, &X, element_size ); if ( cond ) mover( &X, &Y, element_size ); if ( cond ) mover( &Y, &tmp, element_size ); } static RSFORCEINLINE void radsortgetmedian5( void * output, void * left, void * right, size_t length, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { RS_MAX_SIMPLE_BUF mb0,mb1,mb2,mb3,mb4; mover( &mb0, left, element_size ); mover( &mb1, rsadd_ptr_elements( left, length >> 2 ), element_size ); mover( &mb2, rsadd_ptr_elements( left, length >> 1 ), element_size ); mover( &mb3, rsadd_ptr_elements( left, length - (length >> 2) ), element_size ); mover( &mb4, right, element_size ); // Basically, for simple compares, and for simple in-register types, this funcion // must turn info 7 compares and then 5-7 movs, and 12 cmovs. Any // compiler *should* do this - if this doesn't happen, then the compiler is // hosing you. You can put int 3s at the start and end of this function to check. rsswapsmaller( mb0, mb1 ); rsswapsmaller( mb2, mb3 ); rsswapsmaller( mb0, mb2 ); rsswapsmaller( mb1, mb3 ); rsswapsmaller( mb1, mb4 ); rsswapsmaller( mb1, mb2 ); mover( output, &mb2, element_size ); if ( is_before( &mb4, &mb2 ) ) mover( output, &mb4, element_size ); } static RSFORCEINLINE void radsortgetmedian9( void * output, void * left, void * right, size_t length, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { RS_MAX_SIMPLE_BUF mb0,mb1,mb2,mb3,mb4,mb5,mb6,mb7,mb8; // todo, temp mem! #ifdef RS_PREFETCH RS_PREFETCH( left ); RS_PREFETCH( right ); RS_PREFETCH( rsadd_ptr_elements( left, length >> 3 ) ); RS_PREFETCH( rsadd_ptr_elements( left, length >> 2 ) ); RS_PREFETCH( rsadd_ptr_elements( left, (length >> 1) - (length >> 3) ) ); RS_PREFETCH( rsadd_ptr_elements( left, length >> 1 ) ); RS_PREFETCH( rsadd_ptr_elements( left, (length >> 1) + (0 >> 3) ) ); RS_PREFETCH( rsadd_ptr_elements( left, length - (length >> 2) ) ); RS_PREFETCH( rsadd_ptr_elements( left, length - (length >> 3) ) ); #endif mover( &mb0, left, element_size ); mover( &mb1, rsadd_ptr_elements( left, length >> 3 ), element_size ); mover( &mb2, rsadd_ptr_elements( left, length >> 2 ), element_size ); mover( &mb3, rsadd_ptr_elements( left, (length >> 1) - (length >> 3) ), element_size ); mover( &mb4, rsadd_ptr_elements( left, length >> 1 ), element_size ); mover( &mb5, rsadd_ptr_elements( left, (length >> 1) + (length >> 3) ), element_size ); mover( &mb6, rsadd_ptr_elements( left, length - (length >> 2) ), element_size ); mover( &mb7, rsadd_ptr_elements( left, length - (length >> 3) ), element_size ); mover( &mb8, right, element_size ); // Basically, for simple compares, and for simple in-register types, this funcion // should turn info 19 compares and then 15-19 movs, and 36 cmovs. However, // most compilers can only so-so job at this, and you'll end up with 3-4 jumps. // We just need cmov intrinsics. rsswapsmaller( mb0, mb7 ); rsswapsmaller( mb1, mb2 ); rsswapsmaller( mb3, mb5 ); rsswapsmaller( mb4, mb8 ); rsswapsmaller( mb0, mb2 ); rsswapsmaller( mb1, mb5 ); rsswapsmaller( mb3, mb8 ); rsswapsmaller( mb4, mb7 ); rsswapsmaller( mb0, mb3 ); rsswapsmaller( mb1, mb4 ); rsswapsmaller( mb2, mb8 ); rsswapsmaller( mb5, mb7 ); rsswapsmaller( mb3, mb4 ); rsswapsmaller( mb5, mb6 ); rsswapsmaller( mb2, mb5 ); rsswapsmaller( mb4, mb6 ); rsswapsmaller( mb2, mb3 ); rsswapsmaller( mb4, mb5 ); mover( output, &mb3, element_size ); if ( is_before( &mb4, &mb3 ) ) mover( output, &mb4, element_size ); } #define RSS_USE_MEDIAN_9 1024 static RSFORCEINLINE void radsortgetmedian( void * output, void * left, void * right, size_t length, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { // get the median into copy if ( length >= RSS_USE_MEDIAN_9 ) radsortgetmedian9( output, left, right, length, element_size, is_before, swapper, mover ); else radsortgetmedian5( output, left, right, length, element_size, is_before, swapper, mover ); } //=================================================================================================== // bubble 2 routines - for partitions <= 16 count // from Gerben Stavenga - bubble sort moving two values through at once // for ints, this compiles down to 38 instructions #define RSS_FLIP_TO_SMALL_SORT_BUBBLE2 16 static RSFORCEINLINE void radbubble2sort( void * left, size_t n, size_t element_size, is_before_func * is_before, move_func * mover, void * tmp ) { void * i; // todo - test with bigger blocks void * s = rsadd_ptr_elements( left, 2 ); RS_MAX_BUBBLE_BUF x, y, z; #define rsbubbleswap( X, Y ) { int cond; cond = is_before( &Y, &X); mover( tmp, &X, element_size ); if ( cond ) mover( &X, &Y, element_size ); if ( cond ) mover( &Y, tmp, element_size ); } for ( i = rsadd_ptr_elements( left, (int)n - 1 ) ; i > left ; i = rsadd_ptr_elements( i, -2 ) ) { void * j, * jm2; // load x & y mover( &x, left, element_size ); mover( &y, rsadd_ptr_elements( left, 1 ), element_size ); // swap x & y, so that x is smaller than y rsbubbleswap( x, y ); // for ints, this loop needs to be 4 cmps, 6 cmovs, and 5 movs // anything else will kill performance jm2 = left; for ( j = s ; j <= i ; j = rsadd_ptr_elements( j, 1 ) ) { // make z smaller than x and y, and the dump it to the left mover( &z, j, element_size ); rsbubbleswap( z, x ); rsbubbleswap( z, y ); rsbubbleswap( x, y ); mover( jm2, &z, element_size ); jm2 = rsadd_ptr_elements( jm2, 1 ); } mover( rsadd_ptr_elements( i, -1 ), &x, element_size ); mover( i, &y, element_size ); } } #define RSS_FLIP_TO_SMALL_SORT_INSERTION 28 static RSFORCEINLINE void radinsertionsort(void * start, size_t len, size_t element_size, is_before_func * is_before, move_func * mover, void * tmp ) { void * cur; void * prev; cur = rsadd_ptr_elements( start, 1 ); --len; prev = start; do { void * comp = cur; if ( is_before( comp, prev ) ) { mover( tmp, comp, element_size ); do { mover( comp, prev, element_size ); comp = rsadd_ptr_elements( comp, -1 ); if ( comp == start ) break; prev = rsadd_ptr_elements( prev, -1 ); } while ( is_before( tmp, prev ) ); mover( comp, tmp, element_size ); } prev = cur; cur = rsadd_ptr_elements( cur, 1 ); } while( --len ); } /* todo static void * rs_start; static is_before_func * rs_ib; static size_t rs_es; static RSFORCEINLINE int rss_byte_is_before_func( void * elementa, void * elementb ) { unsigned char a = *(unsigned char*)elementa; unsigned char b = *(unsigned char*)elementb; size_t element_size = rs_es; return rs_ib( rsadd_ptr_elements( rs_start, a ), rsadd_ptr_elements( rs_start, b ) ); } // do bubble sort of offsets, and THEN do all the swaps - faster on biy structures static RSFORCEINLINE void radsortbubble2offsets( void * left, size_t n, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { static unsigned char init[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; unsigned char offsets[16]; unsigned char swap[16]; radsortmover16( offsets, init, 16 ); radsortmover16( swap, init, 16 ); rs_start = left; rs_ib = is_before; rs_es = element_size; // sort the byte offsets radsortbubble2( offsets, n, 1, rss_byte_is_before_func, radsortmover1 ); // now reorder the data { unsigned char i; void * ip = left; for( i = 0 ; i < (unsigned char)n ; i++ ) { unsigned char j = swap[ offsets[ i ] ]; if ( i != j ) { swapper( ip, rsadd_ptr_elements( left, j ), element_size ); swap[ j ] = swap[ i ]; } ip = rsadd_ptr_elements( ip, 1 ); } } } */ //=================================================================================================== #undef rsswapsmaller #define RSS_MAX_RECURSE 128 RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover, rs_small_sort_func * small_sort, size_t small_sort_thres, void * tmp ) { void * left; size_t length; if ( len <= 1 ) return; #if _DEBUG if ( element_size > sizeof( RS_MAX_SIMPLE_BUF ) ) __debugbreak(); #endif // stack for no recursion typedef struct stks { void * left; size_t len; } stks; stks stk[ RSS_MAX_RECURSE ]; stks * stk_ptr = stk + RSS_MAX_RECURSE; // we use the stk_ptr to tell when to flip to heap. // when we hit the end of the stack, we heap it, so // back the start of the stack to log1.5 of len length = len; do { --stk_ptr; if ( stk_ptr == stk ) { stk_ptr = stk+1; break; } length = ( length >> 1 ) + ( length >> 2 ); } while ( length ); stk_ptr[ -1 ].len = 0; left = start; length = len; do { for(;;) { // if tiny, hand with insertion if ( length <= small_sort_thres ) { CompilerReset(left); // we reset the compiler before each major sort small_sort( left, length, element_size, is_before, mover, tmp ); break; } else { // if we have hit end of our recursion stack, flip to using a heap (this prevents N^2 behavior) if ( stk_ptr >= stk + RSS_MAX_RECURSE ) { CompilerReset(left); // we reset the compiler before each major sort //printf("heap: %d\n",(int)length); radheapsortinteral( left, length, element_size, is_before, swapper ); break; } else { // partition void * rightequalpiv; size_t leftlen; void * scan, * piv, * rend, * right; CompilerReset(left); // we reset the compiler before each major sort right = rsadd_ptr_elements( left, length - 1 ); // check for and correct inverted blocks scan = left; rend = right; while ( is_before( rend, scan ) ) { swapper( rend, scan, element_size ); scan = rsadd_ptr_elements( scan, 1 ); rend = rsadd_ptr_elements( rend, -1 ); if ( scan >= rend ) break; } // scan to see if the block is in order (or all the same) scan = left; do { void * next = rsadd_ptr( scan, element_size ); if ( is_before( next, scan ) ) goto doqsort; scan = next; } while ( scan < right ); // if we get out of the loop cleanly, this block is already sorted, so just fall out and do next block break; doqsort: // get the median into copy radsortgetmedian( tmp, left, right, length, element_size, is_before, swapper, mover ); // if scan != left, then we have a few in order, so we can skip them all if the final is under the copy if ( !is_before( scan, tmp ) ) scan = left; // this loop should be 3 instructions // skip values below the pivot at the start of the segment while( is_before( scan, tmp ) ) // the pivot will stop this loop scan = rsadd_ptr( scan, element_size ); // skip values above and equal to the pivot at the end of the segment rend = right; if ( left == start ) { // we have to use this loop to check that we don't read off the front of // the array this loop should be 5 instructions while( rend > scan ) { if ( !is_before( tmp, rend ) ) break; rend = rsadd_ptr_elements( rend, -1 ); } } else { // if we're not at the very start of the entire buffer, then we // can use this loop, which is only 3 instructions while( is_before( tmp, rend ) ) // the pivot will stop this loop rend = rsadd_ptr_elements( rend, -1 ); } // finally, do actual partitioning nanosort style - 65-70% of the // total time will be in this loop, for ints, this should be // 4 movs, 2 cmps, 1 cmov, 2 add, 1 jmp - 10 instructions // compilers getting this wrong is a 50-100% slowdown! You can // check the output by putting int 3s around this loop. CompilerReset(scan); piv = scan; while( scan <= rend ) { int adv = is_before( scan, tmp ); swapper( piv, scan, element_size ); if ( adv ) piv = rsadd_ptr( piv, element_size ); // needs to be a cmov scan = rsadd_ptr( scan, element_size ); } // now move the right side to skip over all of the equal values... // this loop should be 5 instructions rightequalpiv = piv; while ( rightequalpiv < right ) { if ( is_before( tmp, rightequalpiv ) ) break; rightequalpiv = rsadd_ptr_elements( rightequalpiv, 1 ); } // ok, now get the size of each half and prepare to descend leftlen = rsdiff_ptr_elements( piv, left ); length -= rsdiff_ptr_elements( rightequalpiv, left ); // put the smaller segment on the stack if ( length < leftlen ) { // put small right on stack stk_ptr->left = rightequalpiv; stk_ptr->len = length; stk_ptr += ( length > 1 ); length = leftlen; } else { // put small left on stack stk_ptr->left = left; stk_ptr->len = leftlen; stk_ptr += ( leftlen > 1 ); left = rightequalpiv; if ( length <= 1 ) break; } } } } --stk_ptr; left = stk_ptr->left; length = stk_ptr->len; } while ( length ); } #undef rsadd_ptr #undef rsadd_ptr_elements #undef rsdiff_ptr_elements #endif // RADSORT_H ================================================ FILE: src/third_party/sinfl/sinfl.h ================================================ // NOTE: // - updated library to handle 64-bit inputs // - fixed a bug where on decomp would exit on blocks with zero length /* # Small Deflate `sdefl` is a small bare bone lossless compression library in ANSI C (ISO C90) which implements the Deflate (RFC 1951) compressed data format specification standard. It is mainly tuned to get as much speed and compression ratio from as little code as needed to keep the implementation as concise as possible. ## Features - Portable single header and source file duo written in ANSI C (ISO C90) - Dual license with either MIT or public domain - Small implementation - Deflate: 525 LoC - Inflate: 500 LoC - Webassembly: - Deflate ~3.7 KB (~2.2KB compressed) - Inflate ~3.6 KB (~2.2KB compressed) ## Usage: This file behaves differently depending on what symbols you define before including it. Header-File mode: If you do not define `SINFL_IMPLEMENTATION` before including this file, it will operate in header only mode. In this mode it declares all used structs and the API of the library without including the implementation of the library. Implementation mode: If you define `SINFL_IMPLEMENTATION` before including this file, it will compile the implementation. Make sure that you only include this file implementation in *one* C or C++ file to prevent collisions. ### Benchmark | Compressor name | Compression| Decompress.| Compr. size | Ratio | | ------------------------| -----------| -----------| ----------- | ----- | | miniz 1.0 -1 | 122 MB/s | 208 MB/s | 48510028 | 48.51 | | miniz 1.0 -6 | 27 MB/s | 260 MB/s | 36513697 | 36.51 | | miniz 1.0 -9 | 23 MB/s | 261 MB/s | 36460101 | 36.46 | | zlib 1.2.11 -1 | 72 MB/s | 307 MB/s | 42298774 | 42.30 | | zlib 1.2.11 -6 | 24 MB/s | 313 MB/s | 36548921 | 36.55 | | zlib 1.2.11 -9 | 20 MB/s | 314 MB/s | 36475792 | 36.48 | | sdefl 1.0 -0 | 127 MB/s | 355 MB/s | 40004116 | 39.88 | | sdefl 1.0 -1 | 111 MB/s | 413 MB/s | 38940674 | 38.82 | | sdefl 1.0 -5 | 45 MB/s | 436 MB/s | 36577183 | 36.46 | | sdefl 1.0 -7 | 38 MB/s | 432 MB/s | 36523781 | 36.41 | | libdeflate 1.3 -1 | 147 MB/s | 667 MB/s | 39597378 | 39.60 | | libdeflate 1.3 -6 | 69 MB/s | 689 MB/s | 36648318 | 36.65 | | libdeflate 1.3 -9 | 13 MB/s | 672 MB/s | 35197141 | 35.20 | | libdeflate 1.3 -12 | 8.13 MB/s | 670 MB/s | 35100568 | 35.10 | ### Compression Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia): | File | Original | `sdefl 0` | `sdefl 5` | `sdefl 7` | | --------| -----------| -------------| ---------- | ------------| | dickens | 10.192.446 | 4,260,187 | 3,845,261 | 3,833,657 | | mozilla | 51.220.480 | 20,774,706 | 19,607,009 | 19,565,867 | | mr | 9.970.564 | 3,860,531 | 3,673,460 | 3,665,627 | | nci | 33.553.445 | 4,030,283 | 3,094,526 | 3,006,075 | | ooffice | 6.152.192 | 3,320,063 | 3,186,373 | 3,183,815 | | osdb | 10.085.684 | 3,919,646 | 3,649,510 | 3,649,477 | | reymont | 6.627.202 | 2,263,378 | 1,857,588 | 1,827,237 | | samba | 21.606.400 | 6,121,797 | 5,462,670 | 5,450,762 | | sao | 7.251.944 | 5,612,421 | 5,485,380 | 5,481,765 | | webster | 41.458.703 | 13,972,648 | 12,059,432 | 11,991,421 | | xml | 5.345.280 | 886,620 | 674,009 | 662,141 | | x-ray | 8.474.240 | 6,304,655 | 6,244,779 | 6,244,779 | ## License ``` ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2020-2023 Micha Mettke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ``` */ #ifndef SINFL_H_INCLUDED #define SINFL_H_INCLUDED #ifdef __cplusplus extern "C" { #endif #define SINFL_PRE_TBL_SIZE 128 #define SINFL_LIT_TBL_SIZE 1334 #define SINFL_OFF_TBL_SIZE 402 struct sinfl { const unsigned char *bitptr; const unsigned char *bitend; unsigned long long bitbuf; int bitcnt; unsigned lits[SINFL_LIT_TBL_SIZE]; unsigned dsts[SINFL_OFF_TBL_SIZE]; }; extern size_t sinflate(void *out, size_t cap, const void *in, size_t size); extern size_t zsinflate(void *out, size_t cap, const void *in, size_t size); #ifdef __cplusplus } #endif #endif /* SINFL_H_INCLUDED */ #ifdef SINFL_IMPLEMENTATION #include /* memcpy, memset */ #include /* assert */ #if defined(__GNUC__) || defined(__clang__) #define sinfl_likely(x) __builtin_expect((x),1) #define sinfl_unlikely(x) __builtin_expect((x),0) #else #define sinfl_likely(x) (x) #define sinfl_unlikely(x) (x) #endif #ifndef SINFL_NO_SIMD #if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) #include #define sinfl_char16 uint8x16_t #define sinfl_char16_ld(p) vld1q_u8((const unsigned char*)(p)) #define sinfl_char16_str(d, v) vst1q_u8((unsigned char*)(d), v) #define sinfl_char16_char(c) vdupq_n_u8(c) #elif defined(__x86_64__) || defined(_WIN32) || defined(_WIN64) #include #define sinfl_char16 __m128i #define sinfl_char16_ld(p) _mm_loadu_si128((const __m128i *)(void*)(p)) #define sinfl_char16_str(d,v) _mm_storeu_si128((__m128i*)(void*)(d), v) #define sinfl_char16_char(c) _mm_set1_epi8(c) #else #define SINFL_NO_SIMD #endif #endif static int sinfl_bsr(unsigned n) { #ifdef _MSC_VER unsigned long r = 0; _BitScanReverse(&r, n); return (int)r; #elif defined(__GNUC__) || defined(__clang__) return 31 - __builtin_clz(n); #endif } static unsigned long long sinfl_read64(const void *p) { unsigned long long n; memcpy(&n, p, 8); return n; } static void sinfl_copy64(unsigned char **dst, unsigned char **src) { unsigned long long n; memcpy(&n, *src, 8); memcpy(*dst, &n, 8); *dst += 8, *src += 8; } static unsigned char* sinfl_write64(unsigned char *dst, unsigned long long w) { memcpy(dst, &w, 8); return dst + 8; } #ifndef SINFL_NO_SIMD static unsigned char* sinfl_write128(unsigned char *dst, sinfl_char16 w) { sinfl_char16_str(dst, w); return dst + 8; } static void sinfl_copy128(unsigned char **dst, unsigned char **src) { sinfl_char16 n = sinfl_char16_ld(*src); sinfl_char16_str(*dst, n); *dst += 16, *src += 16; } #endif static void sinfl_refill(struct sinfl *s) { if (s->bitend - s->bitptr >= 8) { // @raysan5: original code, only those 3 lines s->bitbuf |= sinfl_read64(s->bitptr) << s->bitcnt; s->bitptr += (63 - s->bitcnt) >> 3; s->bitcnt |= 56; /* bitcount in range [56,63] */ } else { // @raysan5: added this case when bits remaining < 8 int bitswant = 63 - s->bitcnt; int byteswant = bitswant >> 3; int bytesuse = s->bitend - s->bitptr <= byteswant ? (int)(s->bitend - s->bitptr) : byteswant; unsigned long long n = 0; memcpy(&n, s->bitptr, bytesuse); s->bitbuf |= n << s->bitcnt; s->bitptr += bytesuse; s->bitcnt += bytesuse << 3; } } static int sinfl_peek(struct sinfl *s, int cnt) { assert(cnt >= 0 && cnt <= 56); assert(cnt <= s->bitcnt); return s->bitbuf & ((1ull << cnt) - 1); } static void sinfl_eat(struct sinfl *s, int cnt) { assert(cnt <= s->bitcnt); s->bitbuf >>= cnt; s->bitcnt -= cnt; } static int sinfl__get(struct sinfl *s, int cnt) { int res = sinfl_peek(s, cnt); sinfl_eat(s, cnt); return res; } static int sinfl_get(struct sinfl *s, int cnt) { sinfl_refill(s); return sinfl__get(s, cnt); } struct sinfl_gen { int len; int cnt; int word; short* sorted; }; static int sinfl_build_tbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, const int *cnt) { int tbl_end = 0; while (!(gen->cnt = cnt[gen->len])) { ++gen->len; } tbl_end = 1 << gen->len; while (gen->len <= tbl_bits) { do {unsigned bit = 0; tbl[gen->word] = (*gen->sorted++ << 16) | gen->len; if (gen->word == tbl_end - 1) { for (; gen->len < tbl_bits; gen->len++) { memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); tbl_end <<= 1; } return 1; } bit = 1 << sinfl_bsr((unsigned)(gen->word ^ (tbl_end - 1))); gen->word &= bit - 1; gen->word |= bit; } while (--gen->cnt); do { if (++gen->len <= tbl_bits) { memcpy(&tbl[tbl_end], tbl, (size_t)tbl_end * sizeof(tbl[0])); tbl_end <<= 1; } } while (!(gen->cnt = cnt[gen->len])); } return 0; } static void sinfl_build_subtbl(struct sinfl_gen *gen, unsigned *tbl, int tbl_bits, const int *cnt) { int sub_bits = 0; int sub_start = 0; int sub_prefix = -1; int tbl_end = 1 << tbl_bits; while (1) { unsigned entry; int bit, stride, i; /* start new sub-table */ if ((gen->word & ((1 << tbl_bits)-1)) != sub_prefix) { int used = 0; sub_prefix = gen->word & ((1 << tbl_bits)-1); sub_start = tbl_end; sub_bits = gen->len - tbl_bits; used = gen->cnt; while (used < (1 << sub_bits)) { sub_bits++; used = (used << 1) + cnt[tbl_bits + sub_bits]; } tbl_end = sub_start + (1 << sub_bits); tbl[sub_prefix] = (sub_start << 16) | 0x10 | (sub_bits & 0xf); } /* fill sub-table */ entry = (*gen->sorted << 16) | ((gen->len - tbl_bits) & 0xf); gen->sorted++; i = sub_start + (gen->word >> tbl_bits); stride = 1 << (gen->len - tbl_bits); do { tbl[i] = entry; i += stride; } while (i < tbl_end); if (gen->word == (1 << gen->len)-1) { return; } bit = 1 << sinfl_bsr(gen->word ^ ((1 << gen->len) - 1)); gen->word &= bit - 1; gen->word |= bit; gen->cnt--; while (!gen->cnt) { gen->cnt = cnt[++gen->len]; } } } static void sinfl_build(unsigned *tbl, unsigned char *lens, int tbl_bits, int maxlen, int symcnt) { int i, used = 0; short sort[288]; int cnt[16] = {0}, off[16]= {0}; struct sinfl_gen gen = {0}; gen.sorted = sort; gen.len = 1; for (i = 0; i < symcnt; ++i) cnt[lens[i]]++; off[1] = cnt[0]; for (i = 1; i < maxlen; ++i) { off[i + 1] = off[i] + cnt[i]; used = (used << 1) + cnt[i]; } used = (used << 1) + cnt[i]; for (i = 0; i < symcnt; ++i) gen.sorted[off[lens[i]]++] = (short)i; gen.sorted += off[0]; if (used < (1 << maxlen)){ for (i = 0; i < 1 << tbl_bits; ++i) tbl[i] = (0 << 16u) | 1; return; } if (!sinfl_build_tbl(&gen, tbl, tbl_bits, cnt)){ sinfl_build_subtbl(&gen, tbl, tbl_bits, cnt); } } static int sinfl_decode(struct sinfl *s, const unsigned *tbl, int bit_len) { int idx = sinfl_peek(s, bit_len); unsigned key = tbl[idx]; if (key & 0x10) { /* sub-table lookup */ int len = key & 0x0f; sinfl_eat(s, bit_len); idx = sinfl_peek(s, len); key = tbl[((key >> 16) & 0xffff) + (unsigned)idx]; } sinfl_eat(s, key & 0x0f); return (key >> 16) & 0x0fff; } static size_t sinfl_decompress(unsigned char *out, size_t cap, const unsigned char *in, size_t size) { static const unsigned char order[] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; static const short dbase[30+2] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577}; static const unsigned char dbits[30+2] = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9, 10,10,11,11,12,12,13,13,0,0}; static const short lbase[29+2] = {3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35, 43,51,59,67,83,99,115,131,163,195,227,258,0,0}; static const unsigned char lbits[29+2] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4, 4,4,4,5,5,5,5,0,0,0}; const unsigned char *oe = out + cap; const unsigned char *e = in + size, *o = out; enum sinfl_states {hdr,stored,fixed,dyn,blk}; enum sinfl_states state = hdr; struct sinfl s = {0}; int last = 0; s.bitptr = in; s.bitend = e; while (1) { switch (state) { case hdr: { /* block header */ int type = 0; sinfl_refill(&s); last = sinfl__get(&s,1); type = sinfl__get(&s,2); switch (type) {default: return (size_t)(out-o); case 0x00: state = stored; break; case 0x01: state = fixed; break; case 0x02: state = dyn; break;} } break; case stored: { /* uncompressed block */ unsigned len, nlen; sinfl__get(&s,s.bitcnt & 7); len = (unsigned short)sinfl__get(&s,16); nlen = (unsigned short)sinfl__get(&s,16); s.bitptr -= s.bitcnt / 8; s.bitbuf = s.bitcnt = 0; if ((unsigned short)len != (unsigned short)~nlen) return (size_t)(out-o); if (len > (e - s.bitptr)) return (size_t)(out-o); memcpy(out, s.bitptr, (size_t)len); s.bitptr += len, out += len; if (last) return (size_t)(out-o); state = hdr; } break; case fixed: { /* fixed huffman codes */ int n; unsigned char lens[288+32]; for (n = 0; n <= 143; n++) lens[n] = 8; for (n = 144; n <= 255; n++) lens[n] = 9; for (n = 256; n <= 279; n++) lens[n] = 7; for (n = 280; n <= 287; n++) lens[n] = 8; for (n = 0; n < 32; n++) lens[288+n] = 5; /* build lit/dist tables */ sinfl_build(s.lits, lens, 10, 15, 288); sinfl_build(s.dsts, lens + 288, 8, 15, 32); state = blk; } break; case dyn: { /* dynamic huffman codes */ int n, i; unsigned hlens[SINFL_PRE_TBL_SIZE]; unsigned char nlens[19] = {0}, lens[288+32]; sinfl_refill(&s); {int nlit = 257 + sinfl__get(&s,5); int ndist = 1 + sinfl__get(&s,5); int nlen = 4 + sinfl__get(&s,4); for (n = 0; n < nlen; n++) nlens[order[n]] = (unsigned char)sinfl_get(&s,3); sinfl_build(hlens, nlens, 7, 7, 19); /* decode code lengths */ for (n = 0; n < nlit + ndist;) { int sym = 0; sinfl_refill(&s); sym = sinfl_decode(&s, hlens, 7); switch (sym) {default: lens[n++] = (unsigned char)sym; break; case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break; case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break; case 18: for (i=11+sinfl_get(&s,7);i;i--,n++) lens[n]=0; break;} } /* build lit/dist tables */ sinfl_build(s.lits, lens, 10, 15, nlit); sinfl_build(s.dsts, lens + nlit, 8, 15, ndist); state = blk;} } break; case blk: { /* decompress block */ while (1) { int sym; sinfl_refill(&s); sym = sinfl_decode(&s, s.lits, 10); if (sym < 256) { /* literal */ if (sinfl_unlikely(out >= oe)) { return (size_t)(out-o); } *out++ = (unsigned char)sym; sym = sinfl_decode(&s, s.lits, 10); if (sym < 256) { *out++ = (unsigned char)sym; continue; } } if (sinfl_unlikely(sym == 256)) { /* end of block */ if (last) return (size_t)(out-o); state = hdr; break; } /* match */ if (sym >= 286) { /* length codes 286 and 287 must not appear in compressed data */ return (size_t)(out-o); } sym -= 257; {int len = sinfl__get(&s, lbits[sym]) + lbase[sym]; int dsym = sinfl_decode(&s, s.dsts, 8); int offs = sinfl__get(&s, dbits[dsym]) + dbase[dsym]; unsigned char *dst = out, *src = out - offs; if (sinfl_unlikely(offs > (size_t)(out-o))) { return (size_t)(out-o); } out = out + len; #ifndef SINFL_NO_SIMD if (sinfl_likely(oe - out >= 16 * 3)) { if (offs >= 16) { /* simd copy match */ sinfl_copy128(&dst, &src); sinfl_copy128(&dst, &src); do sinfl_copy128(&dst, &src); while (dst < out); } else if (offs >= 8) { /* word copy match */ sinfl_copy64(&dst, &src); sinfl_copy64(&dst, &src); do sinfl_copy64(&dst, &src); while (dst < out); } else if (offs == 1) { /* rle match copying */ sinfl_char16 w = sinfl_char16_char(src[0]); dst = sinfl_write128(dst, w); dst = sinfl_write128(dst, w); do dst = sinfl_write128(dst, w); while (dst < out); } else { /* byte copy match */ *dst++ = *src++; *dst++ = *src++; do *dst++ = *src++; while (dst < out); } } #else if (sinfl_likely(oe - out >= 3 * 8 - 3)) { if (offs >= 8) { /* word copy match */ sinfl_copy64(&dst, &src); sinfl_copy64(&dst, &src); do sinfl_copy64(&dst, &src); while (dst < out); } else if (offs == 1) { /* rle match copying */ unsigned int c = src[0]; unsigned int hw = (c << 24u) | (c << 16u) | (c << 8u) | (unsigned)c; unsigned long long w = (unsigned long long)hw << 32llu | hw; dst = sinfl_write64(dst, w); dst = sinfl_write64(dst, w); do dst = sinfl_write64(dst, w); while (dst < out); } else { /* byte copy match */ *dst++ = *src++; *dst++ = *src++; do *dst++ = *src++; while (dst < out); } } #endif else { *dst++ = *src++; *dst++ = *src++; do *dst++ = *src++; while (dst < out); }} } } break;} } return (size_t)(out-o); } extern size_t sinflate(void *out, size_t cap, const void *in, size_t size) { return sinfl_decompress((unsigned char*)out, cap, (const unsigned char*)in, size); } static unsigned sinfl_adler32(unsigned adler32, const unsigned char *in, size_t in_len) { const unsigned ADLER_MOD = 65521; unsigned s1 = adler32 & 0xffff; unsigned s2 = adler32 >> 16; size_t blk_len, i; blk_len = in_len % 5552; while (in_len) { for (i=0; i + 7 < blk_len; i += 8) { s1 += in[0]; s2 += s1; s1 += in[1]; s2 += s1; s1 += in[2]; s2 += s1; s1 += in[3]; s2 += s1; s1 += in[4]; s2 += s1; s1 += in[5]; s2 += s1; s1 += in[6]; s2 += s1; s1 += in[7]; s2 += s1; in += 8; } for (; i < blk_len; ++i) s1 += *in++, s2 += s1; s1 %= ADLER_MOD; s2 %= ADLER_MOD; in_len -= blk_len; blk_len = 5552; } return (unsigned)(s2 << 16) + (unsigned)s1; } extern size_t zsinflate(void *out, size_t cap, const void *mem, size_t size) { const unsigned char *in = (const unsigned char*)mem; if (size >= 6) { const unsigned char *eob = in + size - 4; size_t n = sinfl_decompress((unsigned char*)out, cap, in + 2u, size); unsigned a = sinfl_adler32(1u, (unsigned char*)out, n); unsigned h = eob[0] << 24 | eob[1] << 16 | eob[2] << 8 | eob[3] << 0; return a == h ? n : -1; } else { return -1; } } #endif ================================================ FILE: src/third_party/stb/stb_image.h ================================================ /* stb_image - v2.29 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. // i.e. it should look like this: #include ... #include ... #include ... #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free QUICK NOTES: Primarily of interest to game developers and other people who can avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE PSD (composited view only, no extra channels, 8/16 bit-per-channel) GIF (*comp always reports as 4-channel) HDR (radiance rgbE format) PIC (Softimage PIC) PNM (PPM and PGM binary only) Animated GIF still needs a proper API, but here's one way to do it: http://gist.github.com/urraka/685d9a6340b26b830d49 - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - decode from arbitrary I/O callbacks - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) Full documentation under "DOCUMENTATION" below. LICENSE See end of file for license information. RECENT REVISION HISTORY: 2.29 (2023-05-xx) optimizations 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically 2.23 (2019-08-11) fix clang static analysis warning 2.22 (2019-03-04) gif fixes, fix warnings 2.21 (2019-02-25) fix typo in comment 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; allocate large structures on the stack; correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED See end of file for full revision history. ============================ Contributors ========================= Image formats Extensions, features Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) Arseny Kapoulkine Simon Breuss (16-bit PNM) John-Mark Allen Carmelo J Fdez-Aguera Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski Phil Jordan Dave Moore Roy Eltham Hayaki Saito Nathan Reed Won Chun Luke Graham Johan Duparc Nick Verigakis the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh Janez Zemva John Bartholomew Michal Cichon github:romigrou Jonathan Blow Ken Hamada Tero Hanninen github:svdijk Eugene Golushkov Laurent Gomila Cort Stratton github:snagar Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Brad Weinberger Matvey Cherevko github:mosra Luca Sas Alexander Veselov Zack Middleton [reserved] Ryan C. Gordon [reserved] [reserved] DO NOT ADD YOUR NAME HERE Jacko Dirks To add your name to the credits, pick a random blank space in the middle and fill it. 80% of merge conflicts on stb PRs are due to people adding their name at the end of the credits. */ #ifndef STBI_INCLUDE_STB_IMAGE_H #define STBI_INCLUDE_STB_IMAGE_H // DOCUMENTATION // // Limitations: // - no 12-bit-per-channel JPEG // - no JPEGs with arithmetic coding // - GIF always returns *comp=4 // // Basic usage (see HDR discussion below for HDR usage): // int x,y,n; // unsigned char *data = stbi_load(filename, &x, &y, &n, 0); // // ... process data if not NULL ... // // ... x = width, y = height, n = # 8-bit components per pixel ... // // ... replace '0' with '1'..'4' to force that many components per pixel // // ... but 'n' will always be the number that it would have been if you said 0 // stbi_image_free(data); // // Standard parameters: // int *x -- outputs image width in pixels // int *y -- outputs image height in pixels // int *channels_in_file -- outputs # of image components in image file // int desired_channels -- if non-zero, # of image components requested in result // // The return value from an image loader is an 'unsigned char *' which points // to the pixel data, or NULL on an allocation failure or if the image is // corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, // with each pixel consisting of N interleaved 8-bit components; the first // pixel pointed to is top-left-most in the image. There is no padding between // image scanlines or between pixels, regardless of format. The number of // components N is 'desired_channels' if desired_channels is non-zero, or // *channels_in_file otherwise. If desired_channels is non-zero, // *channels_in_file has the number of components that _would_ have been // output otherwise. E.g. if you set desired_channels to 4, you will always // get RGBA output, but you can check *channels_in_file to see if it's trivially // opaque because e.g. there were only 3 channels in the source image. // // An output image with N components has the following components interleaved // in this order in each pixel: // // N=#comp components // 1 grey // 2 grey, alpha // 3 red, green, blue // 4 red, green, blue, alpha // // If image loading fails for any reason, the return value will be NULL, // and *x, *y, *channels_in_file will be unchanged. The function // stbi_failure_reason() can be queried for an extremely brief, end-user // unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS // to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly // more user-friendly ones. // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. // // To query the width, height and component count of an image without having to // decode the full file, you can use the stbi_info family of functions: // // int x,y,n,ok; // ok = stbi_info(filename, &x, &y, &n); // // returns ok=1 and sets x, y, n if image is a supported format, // // 0 otherwise. // // Note that stb_image pervasively uses ints in its public API for sizes, // including sizes of memory buffers. This is now part of the API and thus // hard to change without causing breakage. As a result, the various image // loaders all have certain limits on image size; these differ somewhat // by format but generally boil down to either just under 2GB or just under // 1GB. When the decoded image would be larger than this, stb_image decoding // will fail. // // Additionally, stb_image will reject image files that have any of their // dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, // which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, // the only way to have an image with such dimensions load correctly // is for it to have a rather extreme aspect ratio. Either way, the // assumption here is that such larger images are likely to be malformed // or malicious. If you do need to load an image with individual dimensions // larger than that, and it still fits in the overall size limit, you can // #define STBI_MAX_DIMENSIONS on your own to be something larger. // // =========================================================================== // // UNICODE: // // If compiling for Windows and you wish to use Unicode filenames, compile // with // #define STBI_WINDOWS_UTF8 // and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert // Windows wchar_t filenames to utf8. // // =========================================================================== // // Philosophy // // stb libraries are designed with the following priorities: // // 1. easy to use // 2. easy to maintain // 3. good performance // // Sometimes I let "good performance" creep up in priority over "easy to maintain", // and for best performance I may provide less-easy-to-use APIs that give higher // performance, in addition to the easy-to-use ones. Nevertheless, it's important // to keep in mind that from the standpoint of you, a client of this library, // all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // // Some secondary priorities arise directly from the first two, some of which // provide more explicit reasons why performance can't be emphasized. // // - Portable ("ease of use") // - Small source code footprint ("easy to maintain") // - No dependencies ("ease of use") // // =========================================================================== // // I/O callbacks // // I/O callbacks allow you to read from arbitrary sources, like packaged // files or some other source. Data read from callbacks are processed // through a small internal buffer (currently 128 bytes) to try to reduce // overhead. // // The three functions you must define are "read" (reads some bytes of data), // "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). // // =========================================================================== // // SIMD support // // The JPEG decoder will try to automatically use SIMD kernels on x86 when // supported by the compiler. For ARM Neon support, you must explicitly // request it. // // (The old do-it-yourself SIMD API is no longer supported in the current // code.) // // On x86, SSE2 will automatically be used when available based on a run-time // test; if not, the generic C versions are used as a fall-back. On ARM targets, // the typical path is to have separate builds for NEON and non-NEON devices // (at least this is true for iOS and Android). Therefore, the NEON support is // toggled by a build flag: define STBI_NEON to get NEON loops. // // If for some reason you do not want to use any of SIMD code, or if // you have issues compiling it, you can disable it entirely by // defining STBI_NO_SIMD. // // =========================================================================== // // HDR image support (disable by defining STBI_NO_HDR) // // stb_image supports loading HDR images in general, and currently the Radiance // .HDR file format specifically. You can still load any file through the existing // interface; if you attempt to load an HDR file, it will be automatically remapped // to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; // both of these constants can be reconfigured through this interface: // // stbi_hdr_to_ldr_gamma(2.2f); // stbi_hdr_to_ldr_scale(1.0f); // // (note, do not use _inverse_ constants; stbi_image will invert them // appropriately). // // Additionally, there is a new, parallel interface for loading files as // (linear) floats to preserve the full dynamic range: // // float *data = stbi_loadf(filename, &x, &y, &n, 0); // // If you load LDR images through this interface, those images will // be promoted to floating point values, run through the inverse of // constants corresponding to the above: // // stbi_ldr_to_hdr_scale(1.0f); // stbi_ldr_to_hdr_gamma(2.2f); // // Finally, given a filename (or an open file or memory block--see header // file for details) containing image data, you can query for the "most // appropriate" interface to use (that is, whether the image is HDR or // not), using: // // stbi_is_hdr(char *filename); // // =========================================================================== // // iPhone PNG support: // // We optionally support converting iPhone-formatted PNGs (which store // premultiplied BGRA) back to RGB, even though they're internally encoded // differently. To enable this conversion, call // stbi_convert_iphone_png_to_rgb(1). // // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per // pixel to remove any premultiplied alpha *only* if the image file explicitly // says there's premultiplied data (currently only happens in iPhone images, // and only if iPhone convert-to-rgb processing is on). // // =========================================================================== // // ADDITIONAL CONFIGURATION // // - You can suppress implementation of any of the decoders to reduce // your code footprint by #defining one or more of the following // symbols before creating the implementation. // // STBI_NO_JPEG // STBI_NO_PNG // STBI_NO_BMP // STBI_NO_PSD // STBI_NO_TGA // STBI_NO_GIF // STBI_NO_HDR // STBI_NO_PIC // STBI_NO_PNM (.ppm and .pgm) // // - You can request *only* certain decoders and suppress all other ones // (this will be more forward-compatible, as addition of new decoders // doesn't require you to disable them explicitly): // // STBI_ONLY_JPEG // STBI_ONLY_PNG // STBI_ONLY_BMP // STBI_ONLY_PSD // STBI_ONLY_TGA // STBI_ONLY_GIF // STBI_ONLY_HDR // STBI_ONLY_PIC // STBI_ONLY_PNM (.ppm and .pgm) // // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // // - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater // than that size (in either width or height) without further processing. // This is to let programs in the wild set an upper bound to prevent // denial-of-service attacks on untrusted data, as one could generate a // valid image of gigantic dimensions and force stb_image to allocate a // huge block of memory and spend disproportionate time decoding it. By // default this is set to (1 << 24), which is 16777216, but that's still // very big. #ifndef STBI_NO_STDIO #include #endif // STBI_NO_STDIO #define STBI_VERSION 1 enum { STBI_default = 0, // only used for desired_channels STBI_grey = 1, STBI_grey_alpha = 2, STBI_rgb = 3, STBI_rgb_alpha = 4 }; #include typedef unsigned char stbi_uc; typedef unsigned short stbi_us; #ifdef __cplusplus extern "C" { #endif #ifndef STBIDEF #ifdef STB_IMAGE_STATIC #define STBIDEF static #else #define STBIDEF extern #endif #endif ////////////////////////////////////////////////////////////////////////////// // // PRIMARY API - works on images of any type // // // load image by filename, open file, or memory buffer // typedef struct { int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative int (*eof) (void *user); // returns nonzero if we are at end of file/data } stbi_io_callbacks; //////////////////////////////////// // // 8-bits-per-channel interface // STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif #ifndef STBI_NO_GIF STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); #endif #ifdef STBI_WINDOWS_UTF8 STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); #endif //////////////////////////////////// // // 16-bits-per-channel interface // STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif //////////////////////////////////// // // float-per-channel interface // #ifndef STBI_NO_LINEAR STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif #endif #ifndef STBI_NO_HDR STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); STBIDEF void stbi_hdr_to_ldr_scale(float scale); #endif // STBI_NO_HDR #ifndef STBI_NO_LINEAR STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); STBIDEF void stbi_ldr_to_hdr_scale(float scale); #endif // STBI_NO_LINEAR // stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); #ifndef STBI_NO_STDIO STBIDEF int stbi_is_hdr (char const *filename); STBIDEF int stbi_is_hdr_from_file(FILE *f); #endif // STBI_NO_STDIO // get a VERY brief reason for failure // on most compilers (and ALL modern mainstream compilers) this is threadsafe STBIDEF const char *stbi_failure_reason (void); // free the loaded image -- this is just free() STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); STBIDEF int stbi_is_16_bit (char const *filename); STBIDEF int stbi_is_16_bit_from_file(FILE *f); #endif // for image formats that explicitly notate that they have premultiplied alpha, // we just return the colors as stored in the file. set this flag to force // unpremultiplication. results are undefined if the unpremultiply overflow. STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); // indicate whether we should process iphone images back to canonical format, // or just pass them through "as-is" STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); // flip the image vertically, so the first pixel in the output array is the bottom left STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); // as above, but only applies to images loaded on the thread that calls the function // this function is only available if your compiler supports thread-local variables; // calling it will fail to link if your compiler doesn't STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); // ZLIB client - used by PNG, available for other purposes STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); #ifdef __cplusplus } #endif // // //// end header file ///////////////////////////////////////////////////// #endif // STBI_INCLUDE_STB_IMAGE_H #ifdef STB_IMAGE_IMPLEMENTATION #if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ || defined(STBI_ONLY_ZLIB) #ifndef STBI_ONLY_JPEG #define STBI_NO_JPEG #endif #ifndef STBI_ONLY_PNG #define STBI_NO_PNG #endif #ifndef STBI_ONLY_BMP #define STBI_NO_BMP #endif #ifndef STBI_ONLY_PSD #define STBI_NO_PSD #endif #ifndef STBI_ONLY_TGA #define STBI_NO_TGA #endif #ifndef STBI_ONLY_GIF #define STBI_NO_GIF #endif #ifndef STBI_ONLY_HDR #define STBI_NO_HDR #endif #ifndef STBI_ONLY_PIC #define STBI_NO_PIC #endif #ifndef STBI_ONLY_PNM #define STBI_NO_PNM #endif #endif #if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) #define STBI_NO_ZLIB #endif #include #include // ptrdiff_t on osx #include #include #include #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) #include // ldexp, pow #endif #ifndef STBI_NO_STDIO #include #endif #ifndef STBI_ASSERT #include #define STBI_ASSERT(x) assert(x) #endif #ifdef __cplusplus #define STBI_EXTERN extern "C" #else #define STBI_EXTERN extern #endif #ifndef _MSC_VER #ifdef __cplusplus #define stbi_inline inline #else #define stbi_inline #endif #else #define stbi_inline __forceinline #endif #ifndef STBI_NO_THREAD_LOCALS #if defined(__cplusplus) && __cplusplus >= 201103L #define STBI_THREAD_LOCAL thread_local #elif defined(__GNUC__) && __GNUC__ < 5 #define STBI_THREAD_LOCAL __thread #elif defined(_MSC_VER) #define STBI_THREAD_LOCAL __declspec(thread) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) #define STBI_THREAD_LOCAL _Thread_local #endif #ifndef STBI_THREAD_LOCAL #if defined(__GNUC__) #define STBI_THREAD_LOCAL __thread #endif #endif #endif #if defined(_MSC_VER) || defined(__SYMBIAN32__) typedef unsigned short stbi__uint16; typedef signed short stbi__int16; typedef unsigned int stbi__uint32; typedef signed int stbi__int32; #else #include typedef uint16_t stbi__uint16; typedef int16_t stbi__int16; typedef uint32_t stbi__uint32; typedef int32_t stbi__int32; #endif // should produce compiler error if size is wrong typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #ifdef _MSC_VER #define STBI_NOTUSED(v) (void)(v) #else #define STBI_NOTUSED(v) (void)sizeof(v) #endif #ifdef _MSC_VER #define STBI_HAS_LROTL #endif #ifdef STBI_HAS_LROTL #define stbi_lrot(x,y) _lrotl(x,y) #else #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) #endif #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) // ok #elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) // ok #else #error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." #endif #ifndef STBI_MALLOC #define STBI_MALLOC(sz) malloc(sz) #define STBI_REALLOC(p,newsz) realloc(p,newsz) #define STBI_FREE(p) free(p) #endif #ifndef STBI_REALLOC_SIZED #define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) #endif // x86/x64 detection #if defined(__x86_64__) || defined(_M_X64) #define STBI__X64_TARGET #elif defined(__i386) || defined(_M_IX86) #define STBI__X86_TARGET #endif #if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // which in turn means it gets to use SSE2 everywhere. This is unfortunate, // but previous attempts to provide the SSE2 functions with runtime // detection caused numerous issues. The way architecture extensions are // exposed in GCC/Clang is, sadly, not really suited for one-file libs. // New behavior: if compiled with -msse2, we use SSE2 without any // detection; if not, we don't use it at all. #define STBI_NO_SIMD #endif #if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) // Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET // // 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the // Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. // As a result, enabling SSE2 on 32-bit MinGW is dangerous when not // simultaneously enabling "-mstackrealign". // // See https://github.com/nothings/stb/issues/81 for more information. // // So default to no SSE2 on 32-bit MinGW. If you've read this far and added // -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. #define STBI_NO_SIMD #endif #if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) #define STBI_SSE2 #include #if !defined(__clang__) && defined(_MSC_VER) #if _MSC_VER >= 1400 // not VC6 #include // __cpuid static int stbi__cpuid3(void) { int info[4]; __cpuid(info,1); return info[3]; } #else static int stbi__cpuid3(void) { int res; __asm { mov eax,1 cpuid mov res,edx } return res; } #endif #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name #if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) static int stbi__sse2_available(void) { int info3 = stbi__cpuid3(); return ((info3 >> 26) & 1) != 0; } #endif #else // assume GCC-style if not VC++ #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) static int stbi__sse2_available(void) { // If we're even attempting to compile this on GCC/Clang, that means // -msse2 is on, which means the compiler is allowed to use SSE2 // instructions at will, and so are we. return 1; } #endif #endif #endif // ARM NEON #if defined(STBI_NO_SIMD) && defined(STBI_NEON) #undef STBI_NEON #endif #ifdef STBI_NEON #include #ifdef _MSC_VER #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name #else #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif #endif #ifndef STBI_SIMD_ALIGN #define STBI_SIMD_ALIGN(type, name) type name #endif #ifndef STBI_MAX_DIMENSIONS #define STBI_MAX_DIMENSIONS (1 << 24) #endif /////////////////////////////////////////////// // // stbi__context struct and start_xxx functions // stbi__context structure is our basic context used by all images, so it // contains all the IO context, plus some basic image information typedef struct { stbi__uint32 img_x, img_y; int img_n, img_out_n; stbi_io_callbacks io; void *io_user_data; int read_from_callbacks; int buflen; stbi_uc buffer_start[128]; int callback_already_read; stbi_uc *img_buffer, *img_buffer_end; stbi_uc *img_buffer_original, *img_buffer_original_end; } stbi__context; static void stbi__refill_buffer(stbi__context *s); // initialize a memory-decode context static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) { s->io.read = NULL; s->read_from_callbacks = 0; s->callback_already_read = 0; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; } // initialize a callback-based context static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) { s->io = *c; s->io_user_data = user; s->buflen = sizeof(s->buffer_start); s->read_from_callbacks = 1; s->callback_already_read = 0; s->img_buffer = s->img_buffer_original = s->buffer_start; stbi__refill_buffer(s); s->img_buffer_original_end = s->img_buffer_end; } #ifndef STBI_NO_STDIO static int stbi__stdio_read(void *user, char *data, int size) { return (int) fread(data,1,size,(FILE*) user); } static void stbi__stdio_skip(void *user, int n) { int ch; fseek((FILE*) user, n, SEEK_CUR); ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ if (ch != EOF) { ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ } } static int stbi__stdio_eof(void *user) { return feof((FILE*) user) || ferror((FILE *) user); } static stbi_io_callbacks stbi__stdio_callbacks = { stbi__stdio_read, stbi__stdio_skip, stbi__stdio_eof, }; static void stbi__start_file(stbi__context *s, FILE *f) { stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); } //static void stop_file(stbi__context *s) { } #endif // !STBI_NO_STDIO static void stbi__rewind(stbi__context *s) { // conceptually rewind SHOULD rewind to the beginning of the stream, // but we just rewind to the beginning of the initial buffer, because // we only use it after doing 'test', which only ever looks at at most 92 bytes s->img_buffer = s->img_buffer_original; s->img_buffer_end = s->img_buffer_original_end; } enum { STBI_ORDER_RGB, STBI_ORDER_BGR }; typedef struct { int bits_per_channel; int num_channels; int channel_order; } stbi__result_info; #ifndef STBI_NO_JPEG static int stbi__jpeg_test(stbi__context *s); static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNG static int stbi__png_test(stbi__context *s); static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__png_is16(stbi__context *s); #endif #ifndef STBI_NO_BMP static int stbi__bmp_test(stbi__context *s); static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_TGA static int stbi__tga_test(stbi__context *s); static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s); static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__psd_is16(stbi__context *s); #endif #ifndef STBI_NO_HDR static int stbi__hdr_test(stbi__context *s); static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PIC static int stbi__pic_test(stbi__context *s); static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_GIF static int stbi__gif_test(stbi__context *s); static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s); static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_is16(stbi__context *s); #endif static #ifdef STBI_THREAD_LOCAL STBI_THREAD_LOCAL #endif const char *stbi__g_failure_reason; STBIDEF const char *stbi_failure_reason(void) { return stbi__g_failure_reason; } #ifndef STBI_NO_FAILURE_STRINGS static int stbi__err(const char *str) { stbi__g_failure_reason = str; return 0; } #endif static void *stbi__malloc(size_t size) { return STBI_MALLOC(size); } // stb_image uses ints pervasively, including for offset calculations. // therefore the largest decoded image size we can support with the // current code, even on 64-bit targets, is INT_MAX. this is not a // significant limitation for the intended use case. // // we do, however, need to make sure our size calculations don't // overflow. hence a few helper functions for size calculations that // multiply integers together, making sure that they're non-negative // and no overflow occurs. // return 1 if the sum is valid, 0 on overflow. // negative terms are considered invalid. static int stbi__addsizes_valid(int a, int b) { if (b < 0) return 0; // now 0 <= b <= INT_MAX, hence also // 0 <= INT_MAX - b <= INTMAX. // And "a + b <= INT_MAX" (which might overflow) is the // same as a <= INT_MAX - b (no overflow) return a <= INT_MAX - b; } // returns 1 if the product is valid, 0 on overflow. // negative factors are considered invalid. static int stbi__mul2sizes_valid(int a, int b) { if (a < 0 || b < 0) return 0; if (b == 0) return 1; // mul-by-0 is always safe // portable way to check for no overflows in a*b return a <= INT_MAX/b; } #if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow static int stbi__mad2sizes_valid(int a, int b, int add) { return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); } #endif // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow static int stbi__mad3sizes_valid(int a, int b, int c, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && stbi__addsizes_valid(a*b*c, add); } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); } #endif #if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // mallocs with size overflow checking static void *stbi__malloc_mad2(int a, int b, int add) { if (!stbi__mad2sizes_valid(a, b, add)) return NULL; return stbi__malloc(a*b + add); } #endif static void *stbi__malloc_mad3(int a, int b, int c, int add) { if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; return stbi__malloc(a*b*c + add); } #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) { if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; return stbi__malloc(a*b*c*d + add); } #endif // returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. static int stbi__addints_valid(int a, int b) { if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. return a <= INT_MAX - b; } // returns 1 if the product of two ints fits in a signed short, 0 on overflow. static int stbi__mul2shorts_valid(int a, int b) { if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN return a >= SHRT_MIN / b; } // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char #ifdef STBI_NO_FAILURE_STRINGS #define stbi__err(x,y) 0 #elif defined(STBI_FAILURE_USERMSG) #define stbi__err(x,y) stbi__err(y) #else #define stbi__err(x,y) stbi__err(x) #endif #define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) #define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) STBIDEF void stbi_image_free(void *retval_from_stbi_load) { STBI_FREE(retval_from_stbi_load); } #ifndef STBI_NO_LINEAR static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); #endif #ifndef STBI_NO_HDR static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); #endif static int stbi__vertically_flip_on_load_global = 0; STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) { stbi__vertically_flip_on_load_global = flag_true_if_should_flip; } #ifndef STBI_THREAD_LOCAL #define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global #else static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) { stbi__vertically_flip_on_load_local = flag_true_if_should_flip; stbi__vertically_flip_on_load_set = 1; } #define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ ? stbi__vertically_flip_on_load_local \ : stbi__vertically_flip_on_load_global) #endif // STBI_THREAD_LOCAL static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order ri->num_channels = 0; // test the formats with a very explicit header first (at least a FOURCC // or distinctive magic number first) #ifndef STBI_NO_PNG if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_BMP if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_GIF if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PSD if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); #else STBI_NOTUSED(bpc); #endif #ifndef STBI_NO_PIC if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif // then the formats that can end up attempting to load with just 1 or 2 // bytes matching expectations; these are prone to false positives, so // try them later #ifndef STBI_NO_JPEG if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNM if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif #ifndef STBI_NO_TGA // test tga last because it's a crappy test! if (stbi__tga_test(s)) return stbi__tga_load(s,x,y,comp,req_comp, ri); #endif return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); } static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) { int i; int img_len = w * h * channels; stbi_uc *reduced; reduced = (stbi_uc *) stbi__malloc(img_len); if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling STBI_FREE(orig); return reduced; } static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) { int i; int img_len = w * h * channels; stbi__uint16 *enlarged; enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); for (i = 0; i < img_len; ++i) enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff STBI_FREE(orig); return enlarged; } static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) { int row; size_t bytes_per_row = (size_t)w * bytes_per_pixel; stbi_uc temp[2048]; stbi_uc *bytes = (stbi_uc *)image; for (row = 0; row < (h>>1); row++) { stbi_uc *row0 = bytes + row*bytes_per_row; stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; // swap row0 with row1 size_t bytes_left = bytes_per_row; while (bytes_left) { size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); memcpy(temp, row0, bytes_copy); memcpy(row0, row1, bytes_copy); memcpy(row1, temp, bytes_copy); row0 += bytes_copy; row1 += bytes_copy; bytes_left -= bytes_copy; } } } #ifndef STBI_NO_GIF static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) { int slice; int slice_size = w * h * bytes_per_pixel; stbi_uc *bytes = (stbi_uc *)image; for (slice = 0; slice < z; ++slice) { stbi__vertical_flip(bytes, w, h, bytes_per_pixel); bytes += slice_size; } } #endif static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); if (result == NULL) return NULL; // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); if (ri.bits_per_channel != 8) { result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 8; } // @TODO: move stbi__convert_format to here if (stbi__vertically_flip_on_load) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); } return (unsigned char *) result; } static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); if (result == NULL) return NULL; // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); if (ri.bits_per_channel != 16) { result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 16; } // @TODO: move stbi__convert_format16 to here // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision if (stbi__vertically_flip_on_load) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); } return (stbi__uint16 *) result; } #if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); } } #endif #ifndef STBI_NO_STDIO #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); #endif #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif static FILE *stbi__fopen(char const *filename, char const *mode) { FILE *f; #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else f = _wfopen(wFilename, wMode); #endif #elif defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != fopen_s(&f, filename, mode)) f=0; #else f = fopen(filename, mode); #endif return f; } STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) { FILE *f = stbi__fopen(filename, "rb"); unsigned char *result; if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); result = stbi_load_from_file(f,x,y,comp,req_comp); fclose(f); return result; } STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { unsigned char *result; stbi__context s; stbi__start_file(&s,f); result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) { stbi__uint16 *result; stbi__context s; stbi__start_file(&s,f); result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) { FILE *f = stbi__fopen(filename, "rb"); stbi__uint16 *result; if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); result = stbi_load_from_file_16(f,x,y,comp,req_comp); fclose(f); return result; } #endif //!STBI_NO_STDIO STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); } STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); } STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } #ifndef STBI_NO_GIF STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { unsigned char *result; stbi__context s; stbi__start_mem(&s,buffer,len); result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); if (stbi__vertically_flip_on_load) { stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); } return result; } #endif #ifndef STBI_NO_LINEAR static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { unsigned char *data; #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { stbi__result_info ri; float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); if (hdr_data) stbi__float_postprocess(hdr_data,x,y,comp,req_comp); return hdr_data; } #endif data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); if (data) return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); } STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__loadf_main(&s,x,y,comp,req_comp); } STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__loadf_main(&s,x,y,comp,req_comp); } #ifndef STBI_NO_STDIO STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) { float *result; FILE *f = stbi__fopen(filename, "rb"); if (!f) return stbi__errpf("can't fopen", "Unable to open file"); result = stbi_loadf_from_file(f,x,y,comp,req_comp); fclose(f); return result; } STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_file(&s,f); return stbi__loadf_main(&s,x,y,comp,req_comp); } #endif // !STBI_NO_STDIO #endif // !STBI_NO_LINEAR // these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is // defined, for API simplicity; if STBI_NO_LINEAR is defined, it always // reports false! STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) { #ifndef STBI_NO_HDR stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__hdr_test(&s); #else STBI_NOTUSED(buffer); STBI_NOTUSED(len); return 0; #endif } #ifndef STBI_NO_STDIO STBIDEF int stbi_is_hdr (char const *filename) { FILE *f = stbi__fopen(filename, "rb"); int result=0; if (f) { result = stbi_is_hdr_from_file(f); fclose(f); } return result; } STBIDEF int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR long pos = ftell(f); int res; stbi__context s; stbi__start_file(&s,f); res = stbi__hdr_test(&s); fseek(f, pos, SEEK_SET); return res; #else STBI_NOTUSED(f); return 0; #endif } #endif // !STBI_NO_STDIO STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) { #ifndef STBI_NO_HDR stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__hdr_test(&s); #else STBI_NOTUSED(clbk); STBI_NOTUSED(user); return 0; #endif } #ifndef STBI_NO_LINEAR static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } #endif static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } ////////////////////////////////////////////////////////////////////////////// // // Common code used by all image loaders // enum { STBI__SCAN_load=0, STBI__SCAN_type, STBI__SCAN_header }; static void stbi__refill_buffer(stbi__context *s) { int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); if (n == 0) { // at end of file, treat same as if from memory, but need to handle case // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file s->read_from_callbacks = 0; s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start+1; *s->img_buffer = 0; } else { s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start + n; } } stbi_inline static stbi_uc stbi__get8(stbi__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; if (s->read_from_callbacks) { stbi__refill_buffer(s); return *s->img_buffer++; } return 0; } #if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else stbi_inline static int stbi__at_eof(stbi__context *s) { if (s->io.read) { if (!(s->io.eof)(s->io_user_data)) return 0; // if feof() is true, check if buffer = end // special case: we've only got the special 0 character at the end if (s->read_from_callbacks == 0) return 1; } return s->img_buffer >= s->img_buffer_end; } #endif #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) // nothing #else static void stbi__skip(stbi__context *s, int n) { if (n == 0) return; // already there! if (n < 0) { s->img_buffer = s->img_buffer_end; return; } if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { s->img_buffer = s->img_buffer_end; (s->io.skip)(s->io_user_data, n - blen); return; } } s->img_buffer += n; } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) // nothing #else static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) { if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { int res, count; memcpy(buffer, s->img_buffer, blen); count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); res = (count == (n-blen)); s->img_buffer = s->img_buffer_end; return res; } } if (s->img_buffer+n <= s->img_buffer_end) { memcpy(buffer, s->img_buffer, n); s->img_buffer += n; return 1; } else return 0; } #endif #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) // nothing #else static int stbi__get16be(stbi__context *s) { int z = stbi__get8(s); return (z << 8) + stbi__get8(s); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) // nothing #else static stbi__uint32 stbi__get32be(stbi__context *s) { stbi__uint32 z = stbi__get16be(s); return (z << 16) + stbi__get16be(s); } #endif #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) // nothing #else static int stbi__get16le(stbi__context *s) { int z = stbi__get8(s); return z + (stbi__get8(s) << 8); } #endif #ifndef STBI_NO_BMP static stbi__uint32 stbi__get32le(stbi__context *s) { stbi__uint32 z = stbi__get16le(s); z += (stbi__uint32)stbi__get16le(s) << 16; return z; } #endif #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else ////////////////////////////////////////////////////////////////////////////// // // generic converter from built-in img_n to req_comp // individual types do this automatically as much as possible (e.g. jpeg // does all cases internally since it needs to colorspace convert anyway, // and it never has alpha, so very few cases ). png can automatically // interleave an alpha=255 channel, but falls back to this for other cases // // assume data buffer is malloced, so malloc a new one and free that one // only failure mode is malloc failing static stbi_uc stbi__compute_y(int r, int g, int b) { return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; unsigned char *good; if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); if (good == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } for (j=0; j < (int) y; ++j) { unsigned char *src = data + j * x * img_n ; unsigned char *dest = good + j * x * req_comp; #define STBI__COMBO(a,b) ((a)*8+(b)) #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } STBI_FREE(data); return good; } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) // nothing #else static stbi__uint16 stbi__compute_y_16(int r, int g, int b) { return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) // nothing #else static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; stbi__uint16 *good; if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); if (good == NULL) { STBI_FREE(data); return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); } for (j=0; j < (int) y; ++j) { stbi__uint16 *src = data + j * x * img_n ; stbi__uint16 *dest = good + j * x * req_comp; #define STBI__COMBO(a,b) ((a)*8+(b)) #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } STBI_FREE(data); return good; } #endif #ifndef STBI_NO_LINEAR static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) { int i,k,n; float *output; if (!data) return NULL; output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; for (i=0; i < x*y; ++i) { for (k=0; k < n; ++k) { output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); } } if (n < comp) { for (i=0; i < x*y; ++i) { output[i*comp + n] = data[i*comp + n]/255.0f; } } STBI_FREE(data); return output; } #endif #ifndef STBI_NO_HDR #define stbi__float2int(x) ((int) (x)) static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) { int i,k,n; stbi_uc *output; if (!data) return NULL; output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; for (i=0; i < x*y; ++i) { for (k=0; k < n; ++k) { float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; if (z < 0) z = 0; if (z > 255) z = 255; output[i*comp + k] = (stbi_uc) stbi__float2int(z); } if (k < comp) { float z = data[i*comp+k] * 255 + 0.5f; if (z < 0) z = 0; if (z > 255) z = 255; output[i*comp + k] = (stbi_uc) stbi__float2int(z); } } STBI_FREE(data); return output; } #endif ////////////////////////////////////////////////////////////////////////////// // // "baseline" JPEG/JFIF decoder // // simple implementation // - doesn't support delayed output of y-dimension // - simple interface (only one output format: 8-bit interleaved RGB) // - doesn't try to recover corrupt jpegs // - doesn't allow partial loading, loading multiple at once // - still fast on x86 (copying globals into locals doesn't help x86) // - allocates lots of intermediate memory (full size of all components) // - non-interleaved case requires this anyway // - allows good upsampling (see next) // high-quality // - upsampled channels are bilinearly interpolated, even across blocks // - quality integer IDCT derived from IJG's 'slow' // performance // - fast huffman; reasonable integer IDCT // - some SIMD kernels for common paths on targets with SSE2/NEON // - uses a lot of intermediate memory, could cache poorly #ifndef STBI_NO_JPEG // huffman decoding acceleration #define FAST_BITS 9 // larger handles more cases; smaller stomps less cache typedef struct { stbi_uc fast[1 << FAST_BITS]; // weirdly, repacking this into AoS is a 10% speed loss, instead of a win stbi__uint16 code[256]; stbi_uc values[256]; stbi_uc size[257]; unsigned int maxcode[18]; int delta[17]; // old 'firstsymbol' - old 'firstcode' } stbi__huffman; typedef struct { stbi__context *s; stbi__huffman huff_dc[4]; stbi__huffman huff_ac[4]; stbi__uint16 dequant[4][64]; stbi__int16 fast_ac[4][1 << FAST_BITS]; // sizes for components, interleaved MCUs int img_h_max, img_v_max; int img_mcu_x, img_mcu_y; int img_mcu_w, img_mcu_h; // definition of jpeg image component struct { int id; int h,v; int tq; int hd,ha; int dc_pred; int x,y,w2,h2; stbi_uc *data; void *raw_data, *raw_coeff; stbi_uc *linebuf; short *coeff; // progressive only int coeff_w, coeff_h; // number of 8x8 coefficient blocks } img_comp[4]; stbi__uint32 code_buffer; // jpeg entropy-coded buffer int code_bits; // number of valid bits unsigned char marker; // marker seen while filling entropy buffer int nomore; // flag if we saw a marker so must stop int progressive; int spec_start; int spec_end; int succ_high; int succ_low; int eob_run; int jfif; int app14_color_transform; // Adobe APP14 tag int rgb; int scan_n, order[4]; int restart_interval, todo; // kernels void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); } stbi__jpeg; static int stbi__build_huffman(stbi__huffman *h, int *count) { int i,j,k=0; unsigned int code; // build size list for each symbol (from JPEG spec) for (i=0; i < 16; ++i) { for (j=0; j < count[i]; ++j) { h->size[k++] = (stbi_uc) (i+1); if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); } } h->size[k] = 0; // compute actual symbols (from jpeg spec) code = 0; k = 0; for(j=1; j <= 16; ++j) { // compute delta to add to code to compute symbol id h->delta[j] = k - code; if (h->size[k] == j) { while (h->size[k] == j) h->code[k++] = (stbi__uint16) (code++); if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); } // compute largest code + 1 for this size, preshifted as needed later h->maxcode[j] = code << (16-j); code <<= 1; } h->maxcode[j] = 0xffffffff; // build non-spec acceleration table; 255 is flag for not-accelerated memset(h->fast, 255, 1 << FAST_BITS); for (i=0; i < k; ++i) { int s = h->size[i]; if (s <= FAST_BITS) { int c = h->code[i] << (FAST_BITS-s); int m = 1 << (FAST_BITS-s); for (j=0; j < m; ++j) { h->fast[c+j] = (stbi_uc) i; } } } return 1; } // build a table that decodes both magnitude and value of small ACs in // one go. static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) { int i; for (i=0; i < (1 << FAST_BITS); ++i) { stbi_uc fast = h->fast[i]; fast_ac[i] = 0; if (fast < 255) { int rs = h->values[fast]; int run = (rs >> 4) & 15; int magbits = rs & 15; int len = h->size[fast]; if (magbits && len + magbits <= FAST_BITS) { // magnitude code followed by receive_extend code int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); if (k < m) k += (~0U << magbits) + 1; // if the result is small enough, we can fit it in fast_ac table if (k >= -128 && k <= 127) fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); } } } } static void stbi__grow_buffer_unsafe(stbi__jpeg *j) { do { unsigned int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; return; } } j->code_buffer |= b << (24 - j->code_bits); j->code_bits += 8; } while (j->code_bits <= 24); } // (1 << n) - 1 static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; // decode a jpeg huffman value from the bitstream stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) { unsigned int temp; int c,k; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); // look at the top FAST_BITS and determine what symbol ID it is, // if the code is <= FAST_BITS c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); k = h->fast[c]; if (k < 255) { int s = h->size[k]; if (s > j->code_bits) return -1; j->code_buffer <<= s; j->code_bits -= s; return h->values[k]; } // naive test is to shift the code_buffer down so k bits are // valid, then test against maxcode. To speed this up, we've // preshifted maxcode left so that it has (16-k) 0s at the // end; in other words, regardless of the number of bits, it // wants to be compared against something shifted to have 16; // that way we don't need to shift inside the loop. temp = j->code_buffer >> 16; for (k=FAST_BITS+1 ; ; ++k) if (temp < h->maxcode[k]) break; if (k == 17) { // error! code not found j->code_bits -= 16; return -1; } if (k > j->code_bits) return -1; // convert the huffman code to the symbol id c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; if(c < 0 || c >= 256) // symbol id out of bounds! return -1; STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); // convert the id to a symbol j->code_bits -= k; j->code_buffer <<= k; return h->values[c]; } // bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; return k + (stbi__jbias[n] & (sgn - 1)); } // get some unsigned bits stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) { unsigned int k; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; return k; } stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) { unsigned int k; if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing k = j->code_buffer; j->code_buffer <<= 1; --j->code_bits; return k & 0x80000000; } // given a value that's at position X in the zigzag stream, // where does it appear in the 8x8 matrix coded as row-major? static const stbi_uc stbi__jpeg_dezigzag[64+15] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, // let corrupt input sample past end 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }; // decode one 64-entry block-- static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) { int diff,dc,k; int t; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); t = stbi__jpeg_huff_decode(j, hdc); if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); // 0 all the ac values now so we can do it 32-bits at a time memset(data,0,64*sizeof(data[0])); diff = t ? stbi__extend_receive(j, t) : 0; if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * dequant[0]); // decode AC components, see JPEG spec k = 1; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; // decode into unzigzag'd location zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) * dequant[zig]); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (rs != 0xf0) break; // end block k += 16; } else { k += r; // decode into unzigzag'd location zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); } } } while (k < 64); return 1; } static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) { int diff,dc; int t; if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); if (j->succ_high == 0) { // first scan for DC coefficient, must be first memset(data,0,64*sizeof(data[0])); // 0 all the ac values now t = stbi__jpeg_huff_decode(j, hdc); if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * (1 << j->succ_low)); } else { // refinement scan for DC coefficient if (stbi__jpeg_get_bit(j)) data[0] += (short) (1 << j->succ_low); } return 1; } // @OPTIMIZE: store non-zigzagged during the decode passes, // and only de-zigzag when dequantizing static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) { int k; if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); if (j->succ_high == 0) { int shift = j->succ_low; if (j->eob_run) { --j->eob_run; return 1; } k = j->spec_start; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) * (1 << shift)); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r); if (r) j->eob_run += stbi__jpeg_get_bits(j, r); --j->eob_run; break; } k += 16; } else { k += r; zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); } } } while (k <= j->spec_end); } else { // refinement scan for these AC coefficients short bit = (short) (1 << j->succ_low); if (j->eob_run) { --j->eob_run; for (k = j->spec_start; k <= j->spec_end; ++k) { short *p = &data[stbi__jpeg_dezigzag[k]]; if (*p != 0) if (stbi__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } } else { k = j->spec_start; do { int r,s; int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r) - 1; if (r) j->eob_run += stbi__jpeg_get_bits(j, r); r = 64; // force end of block } else { // r=15 s=0 should write 16 0s, so we just do // a run of 15 0s and then write s (which is 0), // so we don't have to do anything special here } } else { if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); // sign bit if (stbi__jpeg_get_bit(j)) s = bit; else s = -bit; } // advance by r while (k <= j->spec_end) { short *p = &data[stbi__jpeg_dezigzag[k++]]; if (*p != 0) { if (stbi__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } else { if (r == 0) { *p = (short) s; break; } --r; } } } while (k <= j->spec_end); } } return 1; } // take a -128..127 value and stbi__clamp it and convert to 0..255 stbi_inline static stbi_uc stbi__clamp(int x) { // trick to use a single test to catch both cases if ((unsigned int) x > 255) { if (x < 0) return 0; if (x > 255) return 255; } return (stbi_uc) x; } #define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) #define stbi__fsh(x) ((x) * 4096) // derived from jidctint -- DCT_ISLOW #define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ p2 = s2; \ p3 = s6; \ p1 = (p2+p3) * stbi__f2f(0.5411961f); \ t2 = p1 + p3*stbi__f2f(-1.847759065f); \ t3 = p1 + p2*stbi__f2f( 0.765366865f); \ p2 = s0; \ p3 = s4; \ t0 = stbi__fsh(p2+p3); \ t1 = stbi__fsh(p2-p3); \ x0 = t0+t3; \ x3 = t0-t3; \ x1 = t1+t2; \ x2 = t1-t2; \ t0 = s7; \ t1 = s5; \ t2 = s3; \ t3 = s1; \ p3 = t0+t2; \ p4 = t1+t3; \ p1 = t0+t3; \ p2 = t1+t2; \ p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ t0 = t0*stbi__f2f( 0.298631336f); \ t1 = t1*stbi__f2f( 2.053119869f); \ t2 = t2*stbi__f2f( 3.072711026f); \ t3 = t3*stbi__f2f( 1.501321110f); \ p1 = p5 + p1*stbi__f2f(-0.899976223f); \ p2 = p5 + p2*stbi__f2f(-2.562915447f); \ p3 = p3*stbi__f2f(-1.961570560f); \ p4 = p4*stbi__f2f(-0.390180644f); \ t3 += p1+p4; \ t2 += p2+p3; \ t1 += p2+p4; \ t0 += p1+p3; static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) { int i,val[64],*v=val; stbi_uc *o; short *d = data; // columns for (i=0; i < 8; ++i,++d, ++v) { // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 && d[40]==0 && d[48]==0 && d[56]==0) { // no shortcut 0 seconds // (1|2|3|4|5|6|7)==0 0 seconds // all separate -0.047 seconds // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds int dcterm = d[0]*4; v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; } else { STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) // constants scaled things up by 1<<12; let's bring them back // down, but keep 2 extra bits of precision x0 += 512; x1 += 512; x2 += 512; x3 += 512; v[ 0] = (x0+t3) >> 10; v[56] = (x0-t3) >> 10; v[ 8] = (x1+t2) >> 10; v[48] = (x1-t2) >> 10; v[16] = (x2+t1) >> 10; v[40] = (x2-t1) >> 10; v[24] = (x3+t0) >> 10; v[32] = (x3-t0) >> 10; } } for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { // no fast case since the first 1D IDCT spread components out STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) // constants scaled things up by 1<<12, plus we had 1<<2 from first // loop, plus horizontal and vertical each scale by sqrt(8) so together // we've got an extra 1<<3, so 1<<17 total we need to remove. // so we want to round that, which means adding 0.5 * 1<<17, // aka 65536. Also, we'll end up with -128 to 127 that we want // to encode as 0..255 by adding 128, so we'll add that before the shift x0 += 65536 + (128<<17); x1 += 65536 + (128<<17); x2 += 65536 + (128<<17); x3 += 65536 + (128<<17); // tried computing the shifts into temps, or'ing the temps to see // if any were out of range, but that was slower o[0] = stbi__clamp((x0+t3) >> 17); o[7] = stbi__clamp((x0-t3) >> 17); o[1] = stbi__clamp((x1+t2) >> 17); o[6] = stbi__clamp((x1-t2) >> 17); o[2] = stbi__clamp((x2+t1) >> 17); o[5] = stbi__clamp((x2-t1) >> 17); o[3] = stbi__clamp((x3+t0) >> 17); o[4] = stbi__clamp((x3-t0) >> 17); } } #ifdef STBI_SSE2 // sse2 integer IDCT. not the fastest possible implementation but it // produces bit-identical results to the generic C version so it's // fully "transparent". static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) { // This is constructed to match our regular (generic) integer IDCT exactly. __m128i row0, row1, row2, row3, row4, row5, row6, row7; __m128i tmp; // dot product constant: even elems=x, odd elems=y #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) // out(1) = c1[even]*x + c1[odd]*y #define dct_rot(out0,out1, x,y,c0,c1) \ __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) // out = in << 12 (in 16-bit, out 32-bit) #define dct_widen(out, in) \ __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) // wide add #define dct_wadd(out, a, b) \ __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_add_epi32(a##_h, b##_h) // wide sub #define dct_wsub(out, a, b) \ __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) // butterfly a/b, add bias, then shift by "s" and pack #define dct_bfly32o(out0, out1, a,b,bias,s) \ { \ __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ dct_wadd(sum, abiased, b); \ dct_wsub(dif, abiased, b); \ out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ } // 8-bit interleave step (for transposes) #define dct_interleave8(a, b) \ tmp = a; \ a = _mm_unpacklo_epi8(a, b); \ b = _mm_unpackhi_epi8(tmp, b) // 16-bit interleave step (for transposes) #define dct_interleave16(a, b) \ tmp = a; \ a = _mm_unpacklo_epi16(a, b); \ b = _mm_unpackhi_epi16(tmp, b) #define dct_pass(bias,shift) \ { \ /* even part */ \ dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ __m128i sum04 = _mm_add_epi16(row0, row4); \ __m128i dif04 = _mm_sub_epi16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ __m128i sum17 = _mm_add_epi16(row1, row7); \ __m128i sum35 = _mm_add_epi16(row3, row5); \ dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ dct_wadd(x4, y0o, y4o); \ dct_wadd(x5, y1o, y5o); \ dct_wadd(x6, y2o, y5o); \ dct_wadd(x7, y3o, y4o); \ dct_bfly32o(row0,row7, x0,x7,bias,shift); \ dct_bfly32o(row1,row6, x1,x6,bias,shift); \ dct_bfly32o(row2,row5, x2,x5,bias,shift); \ dct_bfly32o(row3,row4, x3,x4,bias,shift); \ } __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); // rounding biases in column/row passes, see stbi__idct_block for explanation. __m128i bias_0 = _mm_set1_epi32(512); __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); // load row0 = _mm_load_si128((const __m128i *) (data + 0*8)); row1 = _mm_load_si128((const __m128i *) (data + 1*8)); row2 = _mm_load_si128((const __m128i *) (data + 2*8)); row3 = _mm_load_si128((const __m128i *) (data + 3*8)); row4 = _mm_load_si128((const __m128i *) (data + 4*8)); row5 = _mm_load_si128((const __m128i *) (data + 5*8)); row6 = _mm_load_si128((const __m128i *) (data + 6*8)); row7 = _mm_load_si128((const __m128i *) (data + 7*8)); // column pass dct_pass(bias_0, 10); { // 16bit 8x8 transpose pass 1 dct_interleave16(row0, row4); dct_interleave16(row1, row5); dct_interleave16(row2, row6); dct_interleave16(row3, row7); // transpose pass 2 dct_interleave16(row0, row2); dct_interleave16(row1, row3); dct_interleave16(row4, row6); dct_interleave16(row5, row7); // transpose pass 3 dct_interleave16(row0, row1); dct_interleave16(row2, row3); dct_interleave16(row4, row5); dct_interleave16(row6, row7); } // row pass dct_pass(bias_1, 17); { // pack __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 __m128i p1 = _mm_packus_epi16(row2, row3); __m128i p2 = _mm_packus_epi16(row4, row5); __m128i p3 = _mm_packus_epi16(row6, row7); // 8bit 8x8 transpose pass 1 dct_interleave8(p0, p2); // a0e0a1e1... dct_interleave8(p1, p3); // c0g0c1g1... // transpose pass 2 dct_interleave8(p0, p1); // a0c0e0g0... dct_interleave8(p2, p3); // b0d0f0h0... // transpose pass 3 dct_interleave8(p0, p2); // a0b0c0d0... dct_interleave8(p1, p3); // a4b4c4d4... // store _mm_storel_epi64((__m128i *) out, p0); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p2); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p1); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p3); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); } #undef dct_const #undef dct_rot #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_interleave8 #undef dct_interleave16 #undef dct_pass } #endif // STBI_SSE2 #ifdef STBI_NEON // NEON integer IDCT. should produce bit-identical // results to the generic C version. static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) { int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); #define dct_long_mul(out, inq, coeff) \ int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) #define dct_long_mac(out, acc, inq, coeff) \ int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) #define dct_widen(out, inq) \ int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) // wide add #define dct_wadd(out, a, b) \ int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ int32x4_t out##_h = vaddq_s32(a##_h, b##_h) // wide sub #define dct_wsub(out, a, b) \ int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ int32x4_t out##_h = vsubq_s32(a##_h, b##_h) // butterfly a/b, then shift using "shiftop" by "s" and pack #define dct_bfly32o(out0,out1, a,b,shiftop,s) \ { \ dct_wadd(sum, a, b); \ dct_wsub(dif, a, b); \ out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ } #define dct_pass(shiftop, shift) \ { \ /* even part */ \ int16x8_t sum26 = vaddq_s16(row2, row6); \ dct_long_mul(p1e, sum26, rot0_0); \ dct_long_mac(t2e, p1e, row6, rot0_1); \ dct_long_mac(t3e, p1e, row2, rot0_2); \ int16x8_t sum04 = vaddq_s16(row0, row4); \ int16x8_t dif04 = vsubq_s16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ int16x8_t sum15 = vaddq_s16(row1, row5); \ int16x8_t sum17 = vaddq_s16(row1, row7); \ int16x8_t sum35 = vaddq_s16(row3, row5); \ int16x8_t sum37 = vaddq_s16(row3, row7); \ int16x8_t sumodd = vaddq_s16(sum17, sum35); \ dct_long_mul(p5o, sumodd, rot1_0); \ dct_long_mac(p1o, p5o, sum17, rot1_1); \ dct_long_mac(p2o, p5o, sum35, rot1_2); \ dct_long_mul(p3o, sum37, rot2_0); \ dct_long_mul(p4o, sum15, rot2_1); \ dct_wadd(sump13o, p1o, p3o); \ dct_wadd(sump24o, p2o, p4o); \ dct_wadd(sump23o, p2o, p3o); \ dct_wadd(sump14o, p1o, p4o); \ dct_long_mac(x4, sump13o, row7, rot3_0); \ dct_long_mac(x5, sump24o, row5, rot3_1); \ dct_long_mac(x6, sump23o, row3, rot3_2); \ dct_long_mac(x7, sump14o, row1, rot3_3); \ dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ } // load row0 = vld1q_s16(data + 0*8); row1 = vld1q_s16(data + 1*8); row2 = vld1q_s16(data + 2*8); row3 = vld1q_s16(data + 3*8); row4 = vld1q_s16(data + 4*8); row5 = vld1q_s16(data + 5*8); row6 = vld1q_s16(data + 6*8); row7 = vld1q_s16(data + 7*8); // add DC bias row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); // column pass dct_pass(vrshrn_n_s32, 10); // 16bit 8x8 transpose { // these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. // whether compilers actually get this is another story, sadly. #define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } #define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } // pass 1 dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 dct_trn16(row2, row3); dct_trn16(row4, row5); dct_trn16(row6, row7); // pass 2 dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 dct_trn32(row1, row3); dct_trn32(row4, row6); dct_trn32(row5, row7); // pass 3 dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 dct_trn64(row1, row5); dct_trn64(row2, row6); dct_trn64(row3, row7); #undef dct_trn16 #undef dct_trn32 #undef dct_trn64 } // row pass // vrshrn_n_s32 only supports shifts up to 16, we need // 17. so do a non-rounding shift of 16 first then follow // up with a rounding shift by 1. dct_pass(vshrn_n_s32, 16); { // pack and round uint8x8_t p0 = vqrshrun_n_s16(row0, 1); uint8x8_t p1 = vqrshrun_n_s16(row1, 1); uint8x8_t p2 = vqrshrun_n_s16(row2, 1); uint8x8_t p3 = vqrshrun_n_s16(row3, 1); uint8x8_t p4 = vqrshrun_n_s16(row4, 1); uint8x8_t p5 = vqrshrun_n_s16(row5, 1); uint8x8_t p6 = vqrshrun_n_s16(row6, 1); uint8x8_t p7 = vqrshrun_n_s16(row7, 1); // again, these can translate into one instruction, but often don't. #define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } #define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } // sadly can't use interleaved stores here since we only write // 8 bytes to each scan line! // 8x8 8-bit transpose pass 1 dct_trn8_8(p0, p1); dct_trn8_8(p2, p3); dct_trn8_8(p4, p5); dct_trn8_8(p6, p7); // pass 2 dct_trn8_16(p0, p2); dct_trn8_16(p1, p3); dct_trn8_16(p4, p6); dct_trn8_16(p5, p7); // pass 3 dct_trn8_32(p0, p4); dct_trn8_32(p1, p5); dct_trn8_32(p2, p6); dct_trn8_32(p3, p7); // store vst1_u8(out, p0); out += out_stride; vst1_u8(out, p1); out += out_stride; vst1_u8(out, p2); out += out_stride; vst1_u8(out, p3); out += out_stride; vst1_u8(out, p4); out += out_stride; vst1_u8(out, p5); out += out_stride; vst1_u8(out, p6); out += out_stride; vst1_u8(out, p7); #undef dct_trn8_8 #undef dct_trn8_16 #undef dct_trn8_32 } #undef dct_long_mul #undef dct_long_mac #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_pass } #endif // STBI_NEON #define STBI__MARKER_none 0xff // if there's a pending marker from the entropy stream, return that // otherwise, fetch from the stream and get a marker. if there's no // marker, return 0xff, which is never a valid marker value static stbi_uc stbi__get_marker(stbi__jpeg *j) { stbi_uc x; if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } x = stbi__get8(j->s); if (x != 0xff) return STBI__MARKER_none; while (x == 0xff) x = stbi__get8(j->s); // consume repeated 0xff fill bytes return x; } // in each scan, we'll have scan_n components, and the order // of the components is specified by order[] #define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) // after a restart interval, stbi__jpeg_reset the entropy decoder and // the dc prediction static void stbi__jpeg_reset(stbi__jpeg *j) { j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, // since we don't even allow 1<<30 pixels } static int stbi__parse_entropy_coded_data(stbi__jpeg *z) { stbi__jpeg_reset(z); if (!z->progressive) { if (z->scan_n == 1) { int i,j; STBI_SIMD_ALIGN(short, data[64]); int n = z->order[0]; // non-interleaved data, we just need to process one block at a time, // in trivial scanline order // number of blocks to do just depends on how many actual "pixels" this // component has, independent of interleaved MCU blocking and such int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); // every data block is an MCU, so countdown the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); // if it's NOT a restart, then just bail, so we get corrupt data // rather than no data if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } else { // interleaved int i,j,k,x,y; STBI_SIMD_ALIGN(short, data[64]); for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { // scan an interleaved mcu... process scan_n components in order for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; // scan out an mcu's worth of this component; that's just determined // by the basic H and V specified for the component for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x)*8; int y2 = (j*z->img_comp[n].v + y)*8; int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); } } } // after all interleaved components, that's an interleaved MCU, // so now count down the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } } else { if (z->scan_n == 1) { int i,j; int n = z->order[0]; // non-interleaved data, we just need to process one block at a time, // in trivial scanline order // number of blocks to do just depends on how many actual "pixels" this // component has, independent of interleaved MCU blocking and such int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); if (z->spec_start == 0) { if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } else { int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) return 0; } // every data block is an MCU, so countdown the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } else { // interleaved int i,j,k,x,y; for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { // scan an interleaved mcu... process scan_n components in order for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; // scan out an mcu's worth of this component; that's just determined // by the basic H and V specified for the component for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x); int y2 = (j*z->img_comp[n].v + y); short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } } } // after all interleaved components, that's an interleaved MCU, // so now count down the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } } } static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) { int i; for (i=0; i < 64; ++i) data[i] *= dequant[i]; } static void stbi__jpeg_finish(stbi__jpeg *z) { if (z->progressive) { // dequantize and idct the data int i,j,n; for (n=0; n < z->s->img_n; ++n) { int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); } } } } } static int stbi__process_marker(stbi__jpeg *z, int m) { int L; switch (m) { case STBI__MARKER_none: // no marker found return stbi__err("expected marker","Corrupt JPEG"); case 0xDD: // DRI - specify restart interval if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); z->restart_interval = stbi__get16be(z->s); return 1; case 0xDB: // DQT - define quantization table L = stbi__get16be(z->s)-2; while (L > 0) { int q = stbi__get8(z->s); int p = q >> 4, sixteen = (p != 0); int t = q & 15,i; if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); L -= (sixteen ? 129 : 65); } return L==0; case 0xC4: // DHT - define huffman table L = stbi__get16be(z->s)-2; while (L > 0) { stbi_uc *v; int sizes[16],i,n=0; int q = stbi__get8(z->s); int tc = q >> 4; int th = q & 15; if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); for (i=0; i < 16; ++i) { sizes[i] = stbi__get8(z->s); n += sizes[i]; } if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! L -= 17; if (tc == 0) { if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; v = z->huff_dc[th].values; } else { if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; v = z->huff_ac[th].values; } for (i=0; i < n; ++i) v[i] = stbi__get8(z->s); if (tc != 0) stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); L -= n; } return L==0; } // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { L = stbi__get16be(z->s); if (L < 2) { if (m == 0xFE) return stbi__err("bad COM len","Corrupt JPEG"); else return stbi__err("bad APP len","Corrupt JPEG"); } L -= 2; if (m == 0xE0 && L >= 5) { // JFIF APP0 segment static const unsigned char tag[5] = {'J','F','I','F','\0'}; int ok = 1; int i; for (i=0; i < 5; ++i) if (stbi__get8(z->s) != tag[i]) ok = 0; L -= 5; if (ok) z->jfif = 1; } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; int ok = 1; int i; for (i=0; i < 6; ++i) if (stbi__get8(z->s) != tag[i]) ok = 0; L -= 6; if (ok) { stbi__get8(z->s); // version stbi__get16be(z->s); // flags0 stbi__get16be(z->s); // flags1 z->app14_color_transform = stbi__get8(z->s); // color transform L -= 6; } } stbi__skip(z->s, L); return 1; } return stbi__err("unknown marker","Corrupt JPEG"); } // after we see SOS static int stbi__process_scan_header(stbi__jpeg *z) { int i; int Ls = stbi__get16be(z->s); z->scan_n = stbi__get8(z->s); if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); for (i=0; i < z->scan_n; ++i) { int id = stbi__get8(z->s), which; int q = stbi__get8(z->s); for (which = 0; which < z->s->img_n; ++which) if (z->img_comp[which].id == id) break; if (which == z->s->img_n) return 0; // no match z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); z->order[i] = which; } { int aa; z->spec_start = stbi__get8(z->s); z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 aa = stbi__get8(z->s); z->succ_high = (aa >> 4); z->succ_low = (aa & 15); if (z->progressive) { if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) return stbi__err("bad SOS", "Corrupt JPEG"); } else { if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); z->spec_end = 63; } } return 1; } static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) { int i; for (i=0; i < ncomp; ++i) { if (z->img_comp[i].raw_data) { STBI_FREE(z->img_comp[i].raw_data); z->img_comp[i].raw_data = NULL; z->img_comp[i].data = NULL; } if (z->img_comp[i].raw_coeff) { STBI_FREE(z->img_comp[i].raw_coeff); z->img_comp[i].raw_coeff = 0; z->img_comp[i].coeff = 0; } if (z->img_comp[i].linebuf) { STBI_FREE(z->img_comp[i].linebuf); z->img_comp[i].linebuf = NULL; } } return why; } static int stbi__process_frame_header(stbi__jpeg *z, int scan) { stbi__context *s = z->s; int Lf,p,i,q, h_max=1,v_max=1,c; Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); c = stbi__get8(s); if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; z->img_comp[i].linebuf = NULL; } if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); z->rgb = 0; for (i=0; i < s->img_n; ++i) { static const unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); } if (scan != STBI__SCAN_load) return 1; if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); for (i=0; i < s->img_n; ++i) { if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; } // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios // and I've never seen a non-corrupted JPEG file actually use them for (i=0; i < s->img_n; ++i) { if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); } // compute interleaved mcu info z->img_h_max = h_max; z->img_v_max = v_max; z->img_mcu_w = h_max * 8; z->img_mcu_h = v_max * 8; // these sizes can't be more than 17 bits z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; for (i=0; i < s->img_n; ++i) { // number of effective pixels (e.g. for non-interleaved MCU) z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; // to simplify generation, we'll allocate enough memory to decode // the bogus oversized data from using interleaved MCUs and their // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't // discard the extra data until colorspace conversion // // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) // so these muls can't overflow with 32-bit ints (which we require) z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; z->img_comp[i].coeff = 0; z->img_comp[i].raw_coeff = 0; z->img_comp[i].linebuf = NULL; z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); if (z->img_comp[i].raw_data == NULL) return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); // align blocks for idct using mmx/sse z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); if (z->progressive) { // w2, h2 are multiples of 8 (see above) z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); if (z->img_comp[i].raw_coeff == NULL) return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); } } return 1; } // use comparisons since in some cases we handle more than one case (e.g. SOF) #define stbi__DNL(x) ((x) == 0xdc) #define stbi__SOI(x) ((x) == 0xd8) #define stbi__EOI(x) ((x) == 0xd9) #define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) #define stbi__SOS(x) ((x) == 0xda) #define stbi__SOF_progressive(x) ((x) == 0xc2) static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; z->jfif = 0; z->app14_color_transform = -1; // valid values are 0,1,2 z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); if (scan == STBI__SCAN_type) return 1; m = stbi__get_marker(z); while (!stbi__SOF(m)) { if (!stbi__process_marker(z,m)) return 0; m = stbi__get_marker(z); while (m == STBI__MARKER_none) { // some files have extra padding after their blocks, so ok, we'll scan if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); m = stbi__get_marker(z); } } z->progressive = stbi__SOF_progressive(m); if (!stbi__process_frame_header(z, scan)) return 0; return 1; } static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) { // some JPEGs have junk at end, skip over it but if we find what looks // like a valid marker, resume there while (!stbi__at_eof(j->s)) { stbi_uc x = stbi__get8(j->s); while (x == 0xff) { // might be a marker if (stbi__at_eof(j->s)) return STBI__MARKER_none; x = stbi__get8(j->s); if (x != 0x00 && x != 0xff) { // not a stuffed zero or lead-in to another marker, looks // like an actual marker, return it return x; } // stuffed zero has x=0 now which ends the loop, meaning we go // back to regular scan loop. // repeated 0xff keeps trying to read the next byte of the marker. } } return STBI__MARKER_none; } // decode image to YCbCr format static int stbi__decode_jpeg_image(stbi__jpeg *j) { int m; for (m = 0; m < 4; m++) { j->img_comp[m].raw_data = NULL; j->img_comp[m].raw_coeff = NULL; } j->restart_interval = 0; if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; m = stbi__get_marker(j); while (!stbi__EOI(m)) { if (stbi__SOS(m)) { if (!stbi__process_scan_header(j)) return 0; if (!stbi__parse_entropy_coded_data(j)) return 0; if (j->marker == STBI__MARKER_none ) { j->marker = stbi__skip_jpeg_junk_at_end(j); // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } m = stbi__get_marker(j); if (STBI__RESTART(m)) m = stbi__get_marker(j); } else if (stbi__DNL(m)) { int Ld = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); m = stbi__get_marker(j); } else { if (!stbi__process_marker(j, m)) return 1; m = stbi__get_marker(j); } } if (j->progressive) stbi__jpeg_finish(j); return 1; } // static jfif-centered resampling (across block boundaries) typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, int w, int hs); #define stbi__div4(x) ((stbi_uc) ((x) >> 2)) static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { STBI_NOTUSED(out); STBI_NOTUSED(in_far); STBI_NOTUSED(w); STBI_NOTUSED(hs); return in_near; } static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate two samples vertically for every one in input int i; STBI_NOTUSED(hs); for (i=0; i < w; ++i) out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); return out; } static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate two samples horizontally for every one in input int i; stbi_uc *input = in_near; if (w == 1) { // if only one sample, can't do any interpolation out[0] = out[1] = input[0]; return out; } out[0] = input[0]; out[1] = stbi__div4(input[0]*3 + input[1] + 2); for (i=1; i < w-1; ++i) { int n = 3*input[i]+2; out[i*2+0] = stbi__div4(n+input[i-1]); out[i*2+1] = stbi__div4(n+input[i+1]); } out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); out[i*2+1] = input[w-1]; STBI_NOTUSED(in_far); STBI_NOTUSED(hs); return out; } #define stbi__div16(x) ((stbi_uc) ((x) >> 4)) static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate 2x2 samples for every one in input int i,t0,t1; if (w == 1) { out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; out[0] = stbi__div4(t1+2); for (i=1; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = stbi__div16(3*t0 + t1 + 8); out[i*2 ] = stbi__div16(3*t1 + t0 + 8); } out[w*2-1] = stbi__div4(t1+2); STBI_NOTUSED(hs); return out; } #if defined(STBI_SSE2) || defined(STBI_NEON) static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate 2x2 samples for every one in input int i=0,t0,t1; if (w == 1) { out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; // process groups of 8 pixels for as long as we can. // note we can't handle the last pixel in a row in this loop // because we need to handle the filter boundary conditions. for (; i < ((w-1) & ~7); i += 8) { #if defined(STBI_SSE2) // load and perform the vertical filtering pass // this uses 3*x + y = 4*x + (y - x) __m128i zero = _mm_setzero_si128(); __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); __m128i farw = _mm_unpacklo_epi8(farb, zero); __m128i nearw = _mm_unpacklo_epi8(nearb, zero); __m128i diff = _mm_sub_epi16(farw, nearw); __m128i nears = _mm_slli_epi16(nearw, 2); __m128i curr = _mm_add_epi16(nears, diff); // current row // horizontal filter works the same based on shifted vers of current // row. "prev" is current row shifted right by 1 pixel; we need to // insert the previous pixel value (from t1). // "next" is current row shifted left by 1 pixel, with first pixel // of next block of 8 pixels added in. __m128i prv0 = _mm_slli_si128(curr, 2); __m128i nxt0 = _mm_srli_si128(curr, 2); __m128i prev = _mm_insert_epi16(prv0, t1, 0); __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); // horizontal filter, polyphase implementation since it's convenient: // even pixels = 3*cur + prev = cur*4 + (prev - cur) // odd pixels = 3*cur + next = cur*4 + (next - cur) // note the shared term. __m128i bias = _mm_set1_epi16(8); __m128i curs = _mm_slli_epi16(curr, 2); __m128i prvd = _mm_sub_epi16(prev, curr); __m128i nxtd = _mm_sub_epi16(next, curr); __m128i curb = _mm_add_epi16(curs, bias); __m128i even = _mm_add_epi16(prvd, curb); __m128i odd = _mm_add_epi16(nxtd, curb); // interleave even and odd pixels, then undo scaling. __m128i int0 = _mm_unpacklo_epi16(even, odd); __m128i int1 = _mm_unpackhi_epi16(even, odd); __m128i de0 = _mm_srli_epi16(int0, 4); __m128i de1 = _mm_srli_epi16(int1, 4); // pack and write output __m128i outv = _mm_packus_epi16(de0, de1); _mm_storeu_si128((__m128i *) (out + i*2), outv); #elif defined(STBI_NEON) // load and perform the vertical filtering pass // this uses 3*x + y = 4*x + (y - x) uint8x8_t farb = vld1_u8(in_far + i); uint8x8_t nearb = vld1_u8(in_near + i); int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); int16x8_t curr = vaddq_s16(nears, diff); // current row // horizontal filter works the same based on shifted vers of current // row. "prev" is current row shifted right by 1 pixel; we need to // insert the previous pixel value (from t1). // "next" is current row shifted left by 1 pixel, with first pixel // of next block of 8 pixels added in. int16x8_t prv0 = vextq_s16(curr, curr, 7); int16x8_t nxt0 = vextq_s16(curr, curr, 1); int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); // horizontal filter, polyphase implementation since it's convenient: // even pixels = 3*cur + prev = cur*4 + (prev - cur) // odd pixels = 3*cur + next = cur*4 + (next - cur) // note the shared term. int16x8_t curs = vshlq_n_s16(curr, 2); int16x8_t prvd = vsubq_s16(prev, curr); int16x8_t nxtd = vsubq_s16(next, curr); int16x8_t even = vaddq_s16(curs, prvd); int16x8_t odd = vaddq_s16(curs, nxtd); // undo scaling and round, then store with even/odd phases interleaved uint8x8x2_t o; o.val[0] = vqrshrun_n_s16(even, 4); o.val[1] = vqrshrun_n_s16(odd, 4); vst2_u8(out + i*2, o); #endif // "previous" value for next iter t1 = 3*in_near[i+7] + in_far[i+7]; } t0 = t1; t1 = 3*in_near[i] + in_far[i]; out[i*2] = stbi__div16(3*t1 + t0 + 8); for (++i; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = stbi__div16(3*t0 + t1 + 8); out[i*2 ] = stbi__div16(3*t1 + t0 + 8); } out[w*2-1] = stbi__div4(t1+2); STBI_NOTUSED(hs); return out; } #endif static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // resample with nearest-neighbor int i,j; STBI_NOTUSED(in_far); for (i=0; i < w; ++i) for (j=0; j < hs; ++j) out[i*hs+j] = in_near[i]; return out; } // this is a reduced-precision calculation of YCbCr-to-RGB introduced // to make sure the code produces the same results in both SIMD and scalar #define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) { int i; for (i=0; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); // rounding int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; r = y_fixed + cr* stbi__float2fixed(1.40200f); g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } out[0] = (stbi_uc)r; out[1] = (stbi_uc)g; out[2] = (stbi_uc)b; out[3] = 255; out += step; } } #if defined(STBI_SSE2) || defined(STBI_NEON) static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) { int i = 0; #ifdef STBI_SSE2 // step == 3 is pretty ugly on the final interleave, and i'm not convinced // it's useful in practice (you wouldn't use it for textures, for example). // so just accelerate step == 4 case. if (step == 4) { // this is a fairly straightforward implementation and not super-optimized. __m128i signflip = _mm_set1_epi8(-0x80); __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); __m128i xw = _mm_set1_epi16(255); // alpha channel for (; i+7 < count; i += 8) { // load __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 // unpack to short (and left-shift cr, cb by 8) __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); // color transform __m128i yws = _mm_srli_epi16(yw, 4); __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); __m128i rws = _mm_add_epi16(cr0, yws); __m128i gwt = _mm_add_epi16(cb0, yws); __m128i bws = _mm_add_epi16(yws, cb1); __m128i gws = _mm_add_epi16(gwt, cr1); // descale __m128i rw = _mm_srai_epi16(rws, 4); __m128i bw = _mm_srai_epi16(bws, 4); __m128i gw = _mm_srai_epi16(gws, 4); // back to byte, set up for transpose __m128i brb = _mm_packus_epi16(rw, bw); __m128i gxb = _mm_packus_epi16(gw, xw); // transpose to interleave channels __m128i t0 = _mm_unpacklo_epi8(brb, gxb); __m128i t1 = _mm_unpackhi_epi8(brb, gxb); __m128i o0 = _mm_unpacklo_epi16(t0, t1); __m128i o1 = _mm_unpackhi_epi16(t0, t1); // store _mm_storeu_si128((__m128i *) (out + 0), o0); _mm_storeu_si128((__m128i *) (out + 16), o1); out += 32; } } #endif #ifdef STBI_NEON // in this version, step=3 support would be easy to add. but is there demand? if (step == 4) { // this is a fairly straightforward implementation and not super-optimized. uint8x8_t signflip = vdup_n_u8(0x80); int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); for (; i+7 < count; i += 8) { // load uint8x8_t y_bytes = vld1_u8(y + i); uint8x8_t cr_bytes = vld1_u8(pcr + i); uint8x8_t cb_bytes = vld1_u8(pcb + i); int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); // expand to s16 int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); int16x8_t crw = vshll_n_s8(cr_biased, 7); int16x8_t cbw = vshll_n_s8(cb_biased, 7); // color transform int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); int16x8_t rws = vaddq_s16(yws, cr0); int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); int16x8_t bws = vaddq_s16(yws, cb1); // undo scaling, round, convert to byte uint8x8x4_t o; o.val[0] = vqrshrun_n_s16(rws, 4); o.val[1] = vqrshrun_n_s16(gws, 4); o.val[2] = vqrshrun_n_s16(bws, 4); o.val[3] = vdup_n_u8(255); // store, interleaving r/g/b/a vst4_u8(out, o); out += 8*4; } } #endif for (; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); // rounding int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; r = y_fixed + cr* stbi__float2fixed(1.40200f); g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } out[0] = (stbi_uc)r; out[1] = (stbi_uc)g; out[2] = (stbi_uc)b; out[3] = 255; out += step; } } #endif // set up the kernels static void stbi__setup_jpeg(stbi__jpeg *j) { j->idct_block_kernel = stbi__idct_block; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; #ifdef STBI_SSE2 if (stbi__sse2_available()) { j->idct_block_kernel = stbi__idct_simd; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; } #endif #ifdef STBI_NEON j->idct_block_kernel = stbi__idct_simd; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; #endif } // clean up the temporary component buffers static void stbi__cleanup_jpeg(stbi__jpeg *j) { stbi__free_jpeg_components(j, j->s->img_n, 0); } typedef struct { resample_row_func resample; stbi_uc *line0,*line1; int hs,vs; // expansion factor in each axis int w_lores; // horizontal pixels pre-expansion int ystep; // how far through vertical expansion we are int ypos; // which pre-expansion row we're on } stbi__resample; // fast 0..255 * 0..255 => 0..255 rounded multiplication static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) { unsigned int t = x*y + 128; return (stbi_uc) ((t + (t >>8)) >> 8); } static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n, is_rgb; z->s->img_n = 0; // make stbi__cleanup_jpeg safe // validate req_comp if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); // load a jpeg image from whichever source, but leave in YCbCr format if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; else decode_n = z->s->img_n; // nothing to do if no components requested; check this now to avoid // accessing uninitialized coutput[0] later if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } // resample and color-convert { int k; unsigned int i,j; stbi_uc *output; stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; stbi__resample res_comp[4]; for (k=0; k < decode_n; ++k) { stbi__resample *r = &res_comp[k]; // allocate line buffer big enough for upsampling off the edges // with upsample factor of 4 z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } r->hs = z->img_h_max / z->img_comp[k].h; r->vs = z->img_v_max / z->img_comp[k].v; r->ystep = r->vs >> 1; r->w_lores = (z->s->img_x + r->hs-1) / r->hs; r->ypos = 0; r->line0 = r->line1 = z->img_comp[k].data; if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; else r->resample = stbi__resample_row_generic; } // can't error after this so, this is safe output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } // now go ahead and resample for (j=0; j < z->s->img_y; ++j) { stbi_uc *out = output + n * z->s->img_x * j; for (k=0; k < decode_n; ++k) { stbi__resample *r = &res_comp[k]; int y_bot = r->ystep >= (r->vs >> 1); coutput[k] = r->resample(z->img_comp[k].linebuf, y_bot ? r->line1 : r->line0, y_bot ? r->line0 : r->line1, r->w_lores, r->hs); if (++r->ystep >= r->vs) { r->ystep = 0; r->line0 = r->line1; if (++r->ypos < z->img_comp[k].y) r->line1 += z->img_comp[k].w2; } } if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { if (is_rgb) { for (i=0; i < z->s->img_x; ++i) { out[0] = y[i]; out[1] = coutput[1][i]; out[2] = coutput[2][i]; out[3] = 255; out += n; } } else { z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } } else if (z->s->img_n == 4) { if (z->app14_color_transform == 0) { // CMYK for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; out[0] = stbi__blinn_8x8(coutput[0][i], m); out[1] = stbi__blinn_8x8(coutput[1][i], m); out[2] = stbi__blinn_8x8(coutput[2][i], m); out[3] = 255; out += n; } } else if (z->app14_color_transform == 2) { // YCCK z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; out[0] = stbi__blinn_8x8(255 - out[0], m); out[1] = stbi__blinn_8x8(255 - out[1], m); out[2] = stbi__blinn_8x8(255 - out[2], m); out += n; } } else { // YCbCr + alpha? Ignore the fourth channel for now z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; out[3] = 255; // not used if n==3 out += n; } } else { if (is_rgb) { if (n == 1) for (i=0; i < z->s->img_x; ++i) *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); else { for (i=0; i < z->s->img_x; ++i, out += 2) { out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); out[1] = 255; } } } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); out[0] = stbi__compute_y(r, g, b); out[1] = 255; out += n; } } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { for (i=0; i < z->s->img_x; ++i) { out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); out[1] = 255; out += n; } } else { stbi_uc *y = coutput[0]; if (n == 1) for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; else for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } } } } stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__errpuc("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); result = load_jpeg_image(j, x,y,comp,req_comp); STBI_FREE(j); return result; } static int stbi__jpeg_test(stbi__context *s) { int r; stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__err("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); j->s = s; stbi__setup_jpeg(j); r = stbi__decode_jpeg_header(j, STBI__SCAN_type); stbi__rewind(s); STBI_FREE(j); return r; } static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) { if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { stbi__rewind( j->s ); return 0; } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; } static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { int result; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); if (!j) return stbi__err("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); j->s = s; result = stbi__jpeg_info_raw(j, x, y, comp); STBI_FREE(j); return result; } #endif // public domain zlib decode v0.2 Sean Barrett 2006-11-18 // simple implementation // - all input must be provided in an upfront buffer // - all output is written to a single output buffer (can malloc/realloc) // performance // - fast huffman #ifndef STBI_NO_ZLIB // fast-way is faster to check than jpeg huffman, but slow way is slower #define STBI__ZFAST_BITS 9 // accelerate all cases in default tables #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) #define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet // zlib-style huffman encoding // (jpegs packs from left, zlib from right, so can't share code) typedef struct { stbi__uint16 fast[1 << STBI__ZFAST_BITS]; stbi__uint16 firstcode[16]; int maxcode[17]; stbi__uint16 firstsymbol[16]; stbi_uc size[STBI__ZNSYMS]; stbi__uint16 value[STBI__ZNSYMS]; } stbi__zhuffman; stbi_inline static int stbi__bitreverse16(int n) { n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); return n; } stbi_inline static int stbi__bit_reverse(int v, int bits) { STBI_ASSERT(bits <= 16); // to bit reverse n bits, reverse 16 and shift // e.g. 11 bits, bit reverse and shift away 5 return stbi__bitreverse16(v) >> (16-bits); } static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; // DEFLATE spec for generating codes memset(sizes, 0, sizeof(sizes)); memset(z->fast, 0, sizeof(z->fast)); for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; for (i=1; i < 16; ++i) if (sizes[i] > (1 << i)) return stbi__err("bad sizes", "Corrupt PNG"); code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; z->firstcode[i] = (stbi__uint16) code; z->firstsymbol[i] = (stbi__uint16) k; code = (code + sizes[i]); if (sizes[i]) if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); z->maxcode[i] = code << (16-i); // preshift for inner loop code <<= 1; k += sizes[i]; } z->maxcode[16] = 0x10000; // sentinel for (i=0; i < num; ++i) { int s = sizelist[i]; if (s) { int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); z->size [c] = (stbi_uc ) s; z->value[c] = (stbi__uint16) i; if (s <= STBI__ZFAST_BITS) { int j = stbi__bit_reverse(next_code[s],s); while (j < (1 << STBI__ZFAST_BITS)) { z->fast[j] = fastv; j += (1 << s); } } ++next_code[s]; } } return 1; } // zlib-from-memory implementation for PNG reading // because PNG allows splitting the zlib stream arbitrarily, // and it's annoying structurally to have PNG call ZLIB call PNG, // we require PNG read all the IDATs and combine them into a single // memory buffer typedef struct { stbi_uc *zbuffer, *zbuffer_end; int num_bits; int hit_zeof_once; stbi__uint32 code_buffer; char *zout; char *zout_start; char *zout_end; int z_expandable; stbi__zhuffman z_length, z_distance; } stbi__zbuf; stbi_inline static int stbi__zeof(stbi__zbuf *z) { return (z->zbuffer >= z->zbuffer_end); } stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) { return stbi__zeof(z) ? 0 : *z->zbuffer++; } static void stbi__fill_bits(stbi__zbuf *z) { do { if (z->code_buffer >= (1U << z->num_bits)) { z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ return; } z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); } stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) { unsigned int k; if (z->num_bits < n) stbi__fill_bits(z); k = z->code_buffer & ((1 << n) - 1); z->code_buffer >>= n; z->num_bits -= n; return k; } static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) { int b,s,k; // not resolved by fast table, so compute it the slow way // use jpeg approach, which requires MSbits at top k = stbi__bit_reverse(a->code_buffer, 16); for (s=STBI__ZFAST_BITS+1; ; ++s) if (k < z->maxcode[s]) break; if (s >= 16) return -1; // invalid code! // code size is s, so: b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. a->code_buffer >>= s; a->num_bits -= s; return z->value[b]; } stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) { int b,s; if (a->num_bits < 16) { if (stbi__zeof(a)) { if (!a->hit_zeof_once) { // This is the first time we hit eof, insert 16 extra padding btis // to allow us to keep going; if we actually consume any of them // though, that is invalid data. This is caught later. a->hit_zeof_once = 1; a->num_bits += 16; // add 16 implicit zero bits } else { // We already inserted our extra 16 padding bits and are again // out, this stream is actually prematurely terminated. return -1; } } else { stbi__fill_bits(a); } } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { s = b >> 9; a->code_buffer >>= s; a->num_bits -= s; return b & 511; } return stbi__zhuffman_decode_slowpath(a, z); } static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes { char *q; unsigned int cur, limit, old_limit; z->zout = zout; if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); cur = (unsigned int) (z->zout - z->zout_start); limit = old_limit = (unsigned) (z->zout_end - z->zout_start); if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); while (cur + n > limit) { if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); limit *= 2; } q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); STBI_NOTUSED(old_limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; return 1; } static const int stbi__zlength_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; static const int stbi__zlength_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; static const int stbi__zdist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static int stbi__parse_huffman_block(stbi__zbuf *a) { char *zout = a->zout; for(;;) { int z = stbi__zhuffman_decode(a, &a->z_length); if (z < 256) { if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes if (zout >= a->zout_end) { if (!stbi__zexpand(a, zout, 1)) return 0; zout = a->zout; } *zout++ = (char) z; } else { stbi_uc *p; int len,dist; if (z == 256) { a->zout = zout; if (a->hit_zeof_once && a->num_bits < 16) { // The first time we hit zeof, we inserted 16 extra zero bits into our bit // buffer so the decoder can just do its speculative decoding. But if we // actually consumed any of those bits (which is the case when num_bits < 16), // the stream actually read past the end so it is malformed. return stbi__err("unexpected end","Corrupt PNG"); } return 1; } if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); z = stbi__zhuffman_decode(a, &a->z_distance); if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); if (len > a->zout_end - zout) { if (!stbi__zexpand(a, zout, len)) return 0; zout = a->zout; } p = (stbi_uc *) (zout - dist); if (dist == 1) { // run of one byte; common in images. stbi_uc v = *p; if (len) { do *zout++ = v; while (--len); } } else { if (len) { do *zout++ = *p++; while (--len); } } } } } static int stbi__compute_huffman_codes(stbi__zbuf *a) { static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; stbi__zhuffman z_codelength; stbi_uc lencodes[286+32+137];//padding for maximum single op stbi_uc codelength_sizes[19]; int i,n; int hlit = stbi__zreceive(a,5) + 257; int hdist = stbi__zreceive(a,5) + 1; int hclen = stbi__zreceive(a,4) + 4; int ntot = hlit + hdist; memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { int s = stbi__zreceive(a,3); codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; } if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; n = 0; while (n < ntot) { int c = stbi__zhuffman_decode(a, &z_codelength); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; else { stbi_uc fill = 0; if (c == 16) { c = stbi__zreceive(a,2)+3; if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); fill = lencodes[n-1]; } else if (c == 17) { c = stbi__zreceive(a,3)+3; } else if (c == 18) { c = stbi__zreceive(a,7)+11; } else { return stbi__err("bad codelengths", "Corrupt PNG"); } if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); memset(lencodes+n, fill, c); n += c; } } if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; return 1; } static int stbi__parse_uncompressed_block(stbi__zbuf *a) { stbi_uc header[4]; int len,nlen,k; if (a->num_bits & 7) stbi__zreceive(a, a->num_bits & 7); // discard // drain the bit-packed data into header k = 0; while (a->num_bits > 0) { header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check a->code_buffer >>= 8; a->num_bits -= 8; } if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); // now fill header the normal way while (k < 4) header[k++] = stbi__zget8(a); len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); if (a->zout + len > a->zout_end) if (!stbi__zexpand(a, a->zout, len)) return 0; memcpy(a->zout, a->zbuffer, len); a->zbuffer += len; a->zout += len; return 1; } static int stbi__parse_zlib_header(stbi__zbuf *a) { int cmf = stbi__zget8(a); int cm = cmf & 15; /* int cinfo = cmf >> 4; */ int flg = stbi__zget8(a); if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png // window = 1 << (8 + cinfo)... but who cares, we fully buffer output return 1; } static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 }; static const stbi_uc stbi__zdefault_distance[32] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }; /* Init algorithm: { int i; // use <= to match clearly with spec for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; } */ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) { int final, type; if (parse_header) if (!stbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; a->hit_zeof_once = 0; do { final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); if (type == 0) { if (!stbi__parse_uncompressed_block(a)) return 0; } else if (type == 3) { return 0; } else { if (type == 1) { // use fixed code lengths if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { if (!stbi__compute_huffman_codes(a)) return 0; } if (!stbi__parse_huffman_block(a)) return 0; } } while (!final); return 1; } static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) { a->zout_start = obuf; a->zout = obuf; a->zout_end = obuf + olen; a->z_expandable = exp; return stbi__parse_zlib(a, parse_header); } STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) { stbi__zbuf a; char *p = (char *) stbi__malloc(initial_size); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer + len; if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) { return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); } STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) { stbi__zbuf a; char *p = (char *) stbi__malloc(initial_size); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer + len; if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) { stbi__zbuf a; a.zbuffer = (stbi_uc *) ibuffer; a.zbuffer_end = (stbi_uc *) ibuffer + ilen; if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) return (int) (a.zout - a.zout_start); else return -1; } STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) { stbi__zbuf a; char *p = (char *) stbi__malloc(16384); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer+len; if (stbi__do_zlib(&a, p, 16384, 1, 0)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) { stbi__zbuf a; a.zbuffer = (stbi_uc *) ibuffer; a.zbuffer_end = (stbi_uc *) ibuffer + ilen; if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) return (int) (a.zout - a.zout_start); else return -1; } #endif // public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 // simple implementation // - only 8-bit samples // - no CRC checking // - allocates lots of intermediate memory // - avoids problem of streaming data between subsystems // - avoids explicit window management // performance // - uses stb_zlib, a PD zlib implementation with fast huffman decoding #ifndef STBI_NO_PNG typedef struct { stbi__uint32 length; stbi__uint32 type; } stbi__pngchunk; static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) { stbi__pngchunk c; c.length = stbi__get32be(s); c.type = stbi__get32be(s); return c; } static int stbi__check_png_header(stbi__context *s) { static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); return 1; } typedef struct { stbi__context *s; stbi_uc *idata, *expanded, *out; int depth; } stbi__png; enum { STBI__F_none=0, STBI__F_sub=1, STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, // synthetic filter used for first scanline to avoid needing a dummy row of 0s STBI__F_avg_first }; static stbi_uc first_row_filter[5] = { STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub }; static int stbi__paeth(int a, int b, int c) { // This formulation looks very different from the reference in the PNG spec, but is // actually equivalent and has favorable data dependencies and admits straightforward // generation of branch-free code, which helps performance significantly. int thresh = c*3 - (a + b); int lo = a < b ? a : b; int hi = a < b ? b : a; int t0 = (hi <= thresh) ? lo : c; int t1 = (thresh <= lo) ? hi : t0; return t1; } static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; // adds an extra all-255 alpha channel // dest == src is legal // img_n must be 1 or 3 static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) { int i; // must process data backwards since we allow dest==src if (img_n == 1) { for (i=x-1; i >= 0; --i) { dest[i*2+1] = 255; dest[i*2+0] = src[i]; } } else { STBI_ASSERT(img_n == 3); for (i=x-1; i >= 0; --i) { dest[i*4+3] = 255; dest[i*4+2] = src[i*3+2]; dest[i*4+1] = src[i*3+1]; dest[i*4+0] = src[i*3+0]; } } } // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { int bytes = (depth == 16 ? 2 : 1); stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; stbi_uc *filter_buf; int all_ok = 1; int k; int img_n = s->img_n; // copy it into a local for later int output_bytes = out_n*bytes; int filter_bytes = img_n*bytes; int width = x; STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); // note: error exits here don't need to clean up a->out individually, // stbi__do_png always does on error. if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); img_len = (img_width_bytes + 1) * y; // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), // so just check for raw_len < img_len always. if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); // Allocate two scan lines worth of filter workspace buffer. filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); if (!filter_buf) return stbi__err("outofmem", "Out of memory"); // Filtering for low-bit-depth images if (depth < 8) { filter_bytes = 1; width = img_width_bytes; } for (j=0; j < y; ++j) { // cur/prior filter buffers alternate stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; stbi_uc *dest = a->out + stride*j; int nk = width * filter_bytes; int filter = *raw++; // check filter type if (filter > 4) { all_ok = stbi__err("invalid filter","Corrupt PNG"); break; } // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; // perform actual filtering switch (filter) { case STBI__F_none: memcpy(cur, raw, nk); break; case STBI__F_sub: memcpy(cur, raw, filter_bytes); for (k = filter_bytes; k < nk; ++k) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; case STBI__F_up: for (k = 0; k < nk; ++k) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; case STBI__F_avg: for (k = 0; k < filter_bytes; ++k) cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); for (k = filter_bytes; k < nk; ++k) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; case STBI__F_paeth: for (k = 0; k < filter_bytes; ++k) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) for (k = filter_bytes; k < nk; ++k) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); break; case STBI__F_avg_first: memcpy(cur, raw, filter_bytes); for (k = filter_bytes; k < nk; ++k) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; } raw += nk; // expand decoded bits in cur to dest, also adding an extra alpha channel if desired if (depth < 8) { stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range stbi_uc *in = cur; stbi_uc *out = dest; stbi_uc inb = 0; stbi__uint32 nsmp = x*img_n; // expand bits to bytes first if (depth == 4) { for (i=0; i < nsmp; ++i) { if ((i & 1) == 0) inb = *in++; *out++ = scale * (inb >> 4); inb <<= 4; } } else if (depth == 2) { for (i=0; i < nsmp; ++i) { if ((i & 3) == 0) inb = *in++; *out++ = scale * (inb >> 6); inb <<= 2; } } else { STBI_ASSERT(depth == 1); for (i=0; i < nsmp; ++i) { if ((i & 7) == 0) inb = *in++; *out++ = scale * (inb >> 7); inb <<= 1; } } // insert alpha=255 values if desired if (img_n != out_n) stbi__create_png_alpha_expand8(dest, dest, x, img_n); } else if (depth == 8) { if (img_n == out_n) memcpy(dest, cur, x*img_n); else stbi__create_png_alpha_expand8(dest, cur, x, img_n); } else if (depth == 16) { // convert the image data from big-endian to platform-native stbi__uint16 *dest16 = (stbi__uint16*)dest; stbi__uint32 nsmp = x*img_n; if (img_n == out_n) { for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) *dest16 = (cur[0] << 8) | cur[1]; } else { STBI_ASSERT(img_n+1 == out_n); if (img_n == 1) { for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { dest16[0] = (cur[0] << 8) | cur[1]; dest16[1] = 0xffff; } } else { STBI_ASSERT(img_n == 3); for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { dest16[0] = (cur[0] << 8) | cur[1]; dest16[1] = (cur[2] << 8) | cur[3]; dest16[2] = (cur[4] << 8) | cur[5]; dest16[3] = 0xffff; } } } } } STBI_FREE(filter_buf); if (!all_ok) return 0; return 1; } static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { int bytes = (depth == 16 ? 2 : 1); int out_bytes = out_n * bytes; stbi_uc *final; int p; if (!interlaced) return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); // de-interlacing final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); if (!final) return stbi__err("outofmem", "Out of memory"); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; int xspc[] = { 8,8,4,4,2,2,1 }; int yspc[] = { 8,8,8,4,4,2,2 }; int i,j,x,y; // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; if (x && y) { stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { STBI_FREE(final); return 0; } for (j=0; j < y; ++j) { for (i=0; i < x; ++i) { int out_y = j*yspc[p]+yorig[p]; int out_x = i*xspc[p]+xorig[p]; memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, a->out + (j*x+i)*out_bytes, out_bytes); } } STBI_FREE(a->out); image_data += img_len; image_data_len -= img_len; } } a->out = final; return 1; } static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi_uc *p = z->out; // compute color-based transparency, assuming we've // already got 255 as the alpha value in the output STBI_ASSERT(out_n == 2 || out_n == 4); if (out_n == 2) { for (i=0; i < pixel_count; ++i) { p[1] = (p[0] == tc[0] ? 0 : 255); p += 2; } } else { for (i=0; i < pixel_count; ++i) { if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) p[3] = 0; p += 4; } } return 1; } static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi__uint16 *p = (stbi__uint16*) z->out; // compute color-based transparency, assuming we've // already got 65535 as the alpha value in the output STBI_ASSERT(out_n == 2 || out_n == 4); if (out_n == 2) { for (i = 0; i < pixel_count; ++i) { p[1] = (p[0] == tc[0] ? 0 : 65535); p += 2; } } else { for (i = 0; i < pixel_count; ++i) { if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) p[3] = 0; p += 4; } } return 1; } static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) { stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; stbi_uc *p, *temp_out, *orig = a->out; p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); if (p == NULL) return stbi__err("outofmem", "Out of memory"); // between here and free(out) below, exitting would leak temp_out = p; if (pal_img_n == 3) { for (i=0; i < pixel_count; ++i) { int n = orig[i]*4; p[0] = palette[n ]; p[1] = palette[n+1]; p[2] = palette[n+2]; p += 3; } } else { for (i=0; i < pixel_count; ++i) { int n = orig[i]*4; p[0] = palette[n ]; p[1] = palette[n+1]; p[2] = palette[n+2]; p[3] = palette[n+3]; p += 4; } } STBI_FREE(a->out); a->out = temp_out; STBI_NOTUSED(len); return 1; } static int stbi__unpremultiply_on_load_global = 0; static int stbi__de_iphone_flag_global = 0; STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; } STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) { stbi__de_iphone_flag_global = flag_true_if_should_convert; } #ifndef STBI_THREAD_LOCAL #define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global #define stbi__de_iphone_flag stbi__de_iphone_flag_global #else static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; stbi__unpremultiply_on_load_set = 1; } STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) { stbi__de_iphone_flag_local = flag_true_if_should_convert; stbi__de_iphone_flag_set = 1; } #define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ ? stbi__unpremultiply_on_load_local \ : stbi__unpremultiply_on_load_global) #define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ ? stbi__de_iphone_flag_local \ : stbi__de_iphone_flag_global) #endif // STBI_THREAD_LOCAL static void stbi__de_iphone(stbi__png *z) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi_uc *p = z->out; if (s->img_out_n == 3) { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { stbi_uc t = p[0]; p[0] = p[2]; p[2] = t; p += 3; } } else { STBI_ASSERT(s->img_out_n == 4); if (stbi__unpremultiply_on_load) { // convert bgr to rgb and unpremultiply for (i=0; i < pixel_count; ++i) { stbi_uc a = p[3]; stbi_uc t = p[0]; if (a) { stbi_uc half = a / 2; p[0] = (p[2] * 255 + half) / a; p[1] = (p[1] * 255 + half) / a; p[2] = ( t * 255 + half) / a; } else { p[0] = p[2]; p[2] = t; } p += 4; } } else { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { stbi_uc t = p[0]; p[0] = p[2]; p[2] = t; p += 4; } } } } #define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]={0}; stbi__uint16 tc16[3]; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; int first=1,k,interlace=0, color=0, is_iphone=0; stbi__context *s = z->s; z->expanded = NULL; z->idata = NULL; z->out = NULL; if (!stbi__check_png_header(s)) return 0; if (scan == STBI__SCAN_type) return 1; for (;;) { stbi__pngchunk c = stbi__get_chunk_header(s); switch (c.type) { case STBI__PNG_TYPE('C','g','B','I'): is_iphone = 1; stbi__skip(s, c.length); break; case STBI__PNG_TYPE('I','H','D','R'): { int comp,filter; if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); first = 0; if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); s->img_x = stbi__get32be(s); s->img_y = stbi__get32be(s); if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); if (!pal_img_n) { s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); } else { // if paletted, then pal_n is our final components, and // img_n is # components to decompress/filter. s->img_n = 1; if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); } // even with SCAN_header, have to scan to see if we have a tRNS break; } case STBI__PNG_TYPE('P','L','T','E'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); pal_len = c.length / 3; if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); for (i=0; i < pal_len; ++i) { palette[i*4+0] = stbi__get8(s); palette[i*4+1] = stbi__get8(s); palette[i*4+2] = stbi__get8(s); palette[i*4+3] = 255; } break; } case STBI__PNG_TYPE('t','R','N','S'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); if (pal_img_n) { if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); pal_img_n = 4; for (i=0; i < c.length; ++i) palette[i*4+3] = stbi__get8(s); } else { if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (z->depth == 16) { for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger } } break; } case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); if (scan == STBI__SCAN_header) { // header scan definitely stops at first IDAT if (pal_img_n) s->img_n = pal_img_n; return 1; } if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { stbi__uint32 idata_limit_old = idata_limit; stbi_uc *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; STBI_NOTUSED(idata_limit_old); p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); ioff += c.length; break; } case STBI__PNG_TYPE('I','E','N','D'): { stbi__uint32 raw_len, bpl; if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (scan != STBI__SCAN_load) return 1; if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); // initial guess for decoded data size to avoid unnecessary reallocs bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); if (z->expanded == NULL) return 0; // zlib should set error STBI_FREE(z->idata); z->idata = NULL; if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; if (has_trans) { if (z->depth == 16) { if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; } else { if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; } } if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) stbi__de_iphone(z); if (pal_img_n) { // pal_img_n == 3 or 4 s->img_n = pal_img_n; // record the actual colors we had s->img_out_n = pal_img_n; if (req_comp >= 3) s->img_out_n = req_comp; if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) return 0; } else if (has_trans) { // non-paletted image with tRNS -> source image has (constant) alpha ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; // end of PNG chunk, read and skip CRC stbi__get32be(s); return 1; } default: // if critical, fail if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if ((c.type & (1 << 29)) == 0) { #ifndef STBI_NO_FAILURE_STRINGS // not threadsafe static char invalid_chunk[] = "XXXX PNG chunk not known"; invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); #endif return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); } stbi__skip(s, c.length); break; } // end of PNG chunk, read and skip CRC stbi__get32be(s); } } static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) { void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { if (p->depth <= 8) ri->bits_per_channel = 8; else if (p->depth == 16) ri->bits_per_channel = 16; else return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { if (ri->bits_per_channel == 8) result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); else result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); p->s->img_out_n = req_comp; if (result == NULL) return result; } *x = p->s->img_x; *y = p->s->img_y; if (n) *n = p->s->img_n; } STBI_FREE(p->out); p->out = NULL; STBI_FREE(p->expanded); p->expanded = NULL; STBI_FREE(p->idata); p->idata = NULL; return result; } static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi__png p; p.s = s; return stbi__do_png(&p, x,y,comp,req_comp, ri); } static int stbi__png_test(stbi__context *s) { int r; r = stbi__check_png_header(s); stbi__rewind(s); return r; } static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) { if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { stbi__rewind( p->s ); return 0; } if (x) *x = p->s->img_x; if (y) *y = p->s->img_y; if (comp) *comp = p->s->img_n; return 1; } static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) { stbi__png p; p.s = s; return stbi__png_info_raw(&p, x, y, comp); } static int stbi__png_is16(stbi__context *s) { stbi__png p; p.s = s; if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) return 0; if (p.depth != 16) { stbi__rewind(p.s); return 0; } return 1; } #endif // Microsoft/Windows BMP image #ifndef STBI_NO_BMP static int stbi__bmp_test_raw(stbi__context *s) { int r; int sz; if (stbi__get8(s) != 'B') return 0; if (stbi__get8(s) != 'M') return 0; stbi__get32le(s); // discard filesize stbi__get16le(s); // discard reserved stbi__get16le(s); // discard reserved stbi__get32le(s); // discard data offset sz = stbi__get32le(s); r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); return r; } static int stbi__bmp_test(stbi__context *s) { int r = stbi__bmp_test_raw(s); stbi__rewind(s); return r; } // returns 0..31 for the highest set bit static int stbi__high_bit(unsigned int z) { int n=0; if (z == 0) return -1; if (z >= 0x10000) { n += 16; z >>= 16; } if (z >= 0x00100) { n += 8; z >>= 8; } if (z >= 0x00010) { n += 4; z >>= 4; } if (z >= 0x00004) { n += 2; z >>= 2; } if (z >= 0x00002) { n += 1;/* >>= 1;*/ } return n; } static int stbi__bitcount(unsigned int a) { a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits a = (a + (a >> 8)); // max 16 per 8 bits a = (a + (a >> 16)); // max 32 per 8 bits return a & 0xff; } // extract an arbitrarily-aligned N-bit value (N=bits) // from v, and then make it 8-bits long and fractionally // extend it to full full range. static int stbi__shiftsigned(unsigned int v, int shift, int bits) { static unsigned int mul_table[9] = { 0, 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, }; static unsigned int shift_table[9] = { 0, 0,0,1,0,2,4,6,0, }; if (shift < 0) v <<= -shift; else v >>= shift; STBI_ASSERT(v < 256); v >>= (8-bits); STBI_ASSERT(bits >= 0 && bits <= 8); return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } typedef struct { int bpp, offset, hsz; unsigned int mr,mg,mb,ma, all_a; int extra_read; } stbi__bmp_data; static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) { // BI_BITFIELDS specifies masks explicitly, don't override if (compress == 3) return 1; if (compress == 0) { if (info->bpp == 16) { info->mr = 31u << 10; info->mg = 31u << 5; info->mb = 31u << 0; } else if (info->bpp == 32) { info->mr = 0xffu << 16; info->mg = 0xffu << 8; info->mb = 0xffu << 0; info->ma = 0xffu << 24; info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 } else { // otherwise, use defaults, which is all-0 info->mr = info->mg = info->mb = info->ma = 0; } return 1; } return 0; // error } static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) { int hsz; if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); stbi__get32le(s); // discard filesize stbi__get16le(s); // discard reserved stbi__get16le(s); // discard reserved info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; info->extra_read = 14; if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); s->img_y = stbi__get16le(s); } else { s->img_x = stbi__get32le(s); s->img_y = stbi__get32le(s); } if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); info->bpp = stbi__get16le(s); if (hsz != 12) { int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel stbi__get32le(s); // discard sizeof stbi__get32le(s); // discard hres stbi__get32le(s); // discard vres stbi__get32le(s); // discard colorsused stbi__get32le(s); // discard max important if (hsz == 40 || hsz == 56) { if (hsz == 56) { stbi__get32le(s); stbi__get32le(s); stbi__get32le(s); stbi__get32le(s); } if (info->bpp == 16 || info->bpp == 32) { if (compress == 0) { stbi__bmp_set_mask_defaults(info, compress); } else if (compress == 3) { info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->extra_read += 12; // not documented, but generated by photoshop and handled by mspaint if (info->mr == info->mg && info->mg == info->mb) { // ?!?!? return stbi__errpuc("bad BMP", "bad BMP"); } } else return stbi__errpuc("bad BMP", "bad BMP"); } } else { // V4/V5 header int i; if (hsz != 108 && hsz != 124) return stbi__errpuc("bad BMP", "bad BMP"); info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->ma = stbi__get32le(s); if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs stbi__bmp_set_mask_defaults(info, compress); stbi__get32le(s); // discard color space for (i=0; i < 12; ++i) stbi__get32le(s); // discard color space parameters if (hsz == 124) { stbi__get32le(s); // discard rendering intent stbi__get32le(s); // discard offset of profile data stbi__get32le(s); // discard size of profile data stbi__get32le(s); // discard reserved } } } return (void *) 1; } static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; unsigned int mr=0,mg=0,mb=0,ma=0, all_a; stbi_uc pal[256][4]; int psize=0,i,j,width; int flip_vertically, pad, target; stbi__bmp_data info; STBI_NOTUSED(ri); info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) return NULL; // error code already set flip_vertically = ((int) s->img_y) > 0; s->img_y = abs((int) s->img_y); if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); mr = info.mr; mg = info.mg; mb = info.mb; ma = info.ma; all_a = info.all_a; if (info.hsz == 12) { if (info.bpp < 24) psize = (info.offset - info.extra_read - 24) / 3; } else { if (info.bpp < 16) psize = (info.offset - info.extra_read - info.hsz) >> 2; } if (psize == 0) { // accept some number of extra bytes after the header, but if the offset points either to before // the header ends or implies a large amount of extra data, reject the file as malformed int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); int header_limit = 1024; // max we actually read is below 256 bytes currently. int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { return stbi__errpuc("bad header", "Corrupt BMP"); } // we established that bytes_read_so_far is positive and sensible. // the first half of this test rejects offsets that are either too small positives, or // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn // ensures the number computed in the second half of the test can't overflow. if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { return stbi__errpuc("bad offset", "Corrupt BMP"); } else { stbi__skip(s, info.offset - bytes_read_so_far); } } if (info.bpp == 24 && ma == 0xff000000) s->img_n = 3; else s->img_n = ma ? 4 : 3; if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 target = req_comp; else target = s->img_n; // if they want monochrome, we'll post-convert // sanity-check size if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) return stbi__errpuc("too large", "Corrupt BMP"); out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (info.bpp < 16) { int z=0; if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } for (i=0; i < psize; ++i) { pal[i][2] = stbi__get8(s); pal[i][1] = stbi__get8(s); pal[i][0] = stbi__get8(s); if (info.hsz != 12) stbi__get8(s); pal[i][3] = 255; } stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); if (info.bpp == 1) width = (s->img_x + 7) >> 3; else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 8) width = s->img_x; else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } pad = (-width)&3; if (info.bpp == 1) { for (j=0; j < (int) s->img_y; ++j) { int bit_offset = 7, v = stbi__get8(s); for (i=0; i < (int) s->img_x; ++i) { int color = (v>>bit_offset)&0x1; out[z++] = pal[color][0]; out[z++] = pal[color][1]; out[z++] = pal[color][2]; if (target == 4) out[z++] = 255; if (i+1 == (int) s->img_x) break; if((--bit_offset) < 0) { bit_offset = 7; v = stbi__get8(s); } } stbi__skip(s, pad); } } else { for (j=0; j < (int) s->img_y; ++j) { for (i=0; i < (int) s->img_x; i += 2) { int v=stbi__get8(s),v2=0; if (info.bpp == 4) { v2 = v & 15; v >>= 4; } out[z++] = pal[v][0]; out[z++] = pal[v][1]; out[z++] = pal[v][2]; if (target == 4) out[z++] = 255; if (i+1 == (int) s->img_x) break; v = (info.bpp == 8) ? stbi__get8(s) : v2; out[z++] = pal[v][0]; out[z++] = pal[v][1]; out[z++] = pal[v][2]; if (target == 4) out[z++] = 255; } stbi__skip(s, pad); } } } else { int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int z = 0; int easy=0; stbi__skip(s, info.offset - info.extra_read - info.hsz); if (info.bpp == 24) width = 3 * s->img_x; else if (info.bpp == 16) width = 2*s->img_x; else /* bpp = 32 and pad = 0 */ width=0; pad = (-width) & 3; if (info.bpp == 24) { easy = 1; } else if (info.bpp == 32) { if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) easy = 2; } if (!easy) { if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } // right shift amt to put high bit in position #7 rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } } for (j=0; j < (int) s->img_y; ++j) { if (easy) { for (i=0; i < (int) s->img_x; ++i) { unsigned char a; out[z+2] = stbi__get8(s); out[z+1] = stbi__get8(s); out[z+0] = stbi__get8(s); z += 3; a = (easy == 2 ? stbi__get8(s) : 255); all_a |= a; if (target == 4) out[z++] = a; } } else { int bpp = info.bpp; for (i=0; i < (int) s->img_x; ++i) { stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); unsigned int a; out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); all_a |= a; if (target == 4) out[z++] = STBI__BYTECAST(a); } } stbi__skip(s, pad); } } // if alpha channel is all 0s, replace with all 255s if (target == 4 && all_a == 0) for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) out[i] = 255; if (flip_vertically) { stbi_uc t; for (j=0; j < (int) s->img_y>>1; ++j) { stbi_uc *p1 = out + j *s->img_x*target; stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; for (i=0; i < (int) s->img_x*target; ++i) { t = p1[i]; p1[i] = p2[i]; p2[i] = t; } } } if (req_comp && req_comp != target) { out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); if (out == NULL) return out; // stbi__convert_format frees input on failure } *x = s->img_x; *y = s->img_y; if (comp) *comp = s->img_n; return out; } #endif // Targa Truevision - TGA // by Jonathan Dummer #ifndef STBI_NO_TGA // returns STBI_rgb or whatever, 0 on error static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) { // only RGB or RGBA (incl. 16bit) or grey allowed if (is_rgb16) *is_rgb16 = 0; switch(bits_per_pixel) { case 8: return STBI_grey; case 16: if(is_grey) return STBI_grey_alpha; // fallthrough case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb; case 24: // fallthrough case 32: return bits_per_pixel/8; default: return 0; } } static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) { int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; int sz, tga_colormap_type; stbi__get8(s); // discard Offset tga_colormap_type = stbi__get8(s); // colormap type if( tga_colormap_type > 1 ) { stbi__rewind(s); return 0; // only RGB or indexed allowed } tga_image_type = stbi__get8(s); // image type if ( tga_colormap_type == 1 ) { // colormapped (paletted) image if (tga_image_type != 1 && tga_image_type != 9) { stbi__rewind(s); return 0; } stbi__skip(s,4); // skip index of first colormap entry and number of entries sz = stbi__get8(s); // check bits per palette color entry if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { stbi__rewind(s); return 0; } stbi__skip(s,4); // skip image x and y origin tga_colormap_bpp = sz; } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { stbi__rewind(s); return 0; // only RGB or grey allowed, +/- RLE } stbi__skip(s,9); // skip colormap specification and image x/y origin tga_colormap_bpp = 0; } tga_w = stbi__get16le(s); if( tga_w < 1 ) { stbi__rewind(s); return 0; // test width } tga_h = stbi__get16le(s); if( tga_h < 1 ) { stbi__rewind(s); return 0; // test height } tga_bits_per_pixel = stbi__get8(s); // bits per pixel stbi__get8(s); // ignore alpha bits if (tga_colormap_bpp != 0) { if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { // when using a colormap, tga_bits_per_pixel is the size of the indexes // I don't think anything but 8 or 16bit indexes makes sense stbi__rewind(s); return 0; } tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); } else { tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); } if(!tga_comp) { stbi__rewind(s); return 0; } if (x) *x = tga_w; if (y) *y = tga_h; if (comp) *comp = tga_comp; return 1; // seems to have passed everything } static int stbi__tga_test(stbi__context *s) { int res = 0; int sz, tga_color_type; stbi__get8(s); // discard Offset tga_color_type = stbi__get8(s); // color type if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed sz = stbi__get8(s); // image type if ( tga_color_type == 1 ) { // colormapped (paletted) image if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 stbi__skip(s,4); // skip index of first colormap entry and number of entries sz = stbi__get8(s); // check bits per palette color entry if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; stbi__skip(s,4); // skip image x and y origin } else { // "normal" image w/o colormap if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE stbi__skip(s,9); // skip colormap specification and image x/y origin } if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height sz = stbi__get8(s); // bits per pixel if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; res = 1; // if we got this far, everything's good and we can return 1 instead of 0 errorEnd: stbi__rewind(s); return res; } // read 16bit value and convert to 24bit RGB static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { stbi__uint16 px = (stbi__uint16)stbi__get16le(s); stbi__uint16 fiveBitMask = 31; // we have 3 channels with 5bits each int r = (px >> 10) & fiveBitMask; int g = (px >> 5) & fiveBitMask; int b = px & fiveBitMask; // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later out[0] = (stbi_uc)((r * 255)/31); out[1] = (stbi_uc)((g * 255)/31); out[2] = (stbi_uc)((b * 255)/31); // some people claim that the most significant bit might be used for alpha // (possibly if an alpha-bit is set in the "image descriptor byte") // but that only made 16bit test images completely translucent.. // so let's treat all 15 and 16bit TGAs as RGB with no alpha. } static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { // read in the TGA header stuff int tga_offset = stbi__get8(s); int tga_indexed = stbi__get8(s); int tga_image_type = stbi__get8(s); int tga_is_RLE = 0; int tga_palette_start = stbi__get16le(s); int tga_palette_len = stbi__get16le(s); int tga_palette_bits = stbi__get8(s); int tga_x_origin = stbi__get16le(s); int tga_y_origin = stbi__get16le(s); int tga_width = stbi__get16le(s); int tga_height = stbi__get16le(s); int tga_bits_per_pixel = stbi__get8(s); int tga_comp, tga_rgb16=0; int tga_inverted = stbi__get8(s); // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; unsigned char raw_data[4] = {0}; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; STBI_NOTUSED(ri); STBI_NOTUSED(tga_x_origin); // @TODO STBI_NOTUSED(tga_y_origin); // @TODO if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); // do a tiny bit of precessing if ( tga_image_type >= 8 ) { tga_image_type -= 8; tga_is_RLE = 1; } tga_inverted = 1 - ((tga_inverted >> 5) & 1); // If I'm paletted, then I'll use the number of bits from the palette if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); // tga info *x = tga_width; *y = tga_height; if (comp) *comp = tga_comp; if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) return stbi__errpuc("too large", "Corrupt TGA"); tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) stbi__skip(s, tga_offset ); if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { for (i=0; i < tga_height; ++i) { int row = tga_inverted ? tga_height -i - 1 : i; stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; stbi__getn(s, tga_row, tga_width * tga_comp); } } else { // do I need to load a palette? if ( tga_indexed) { if (tga_palette_len == 0) { /* you have to have at least one entry! */ STBI_FREE(tga_data); return stbi__errpuc("bad palette", "Corrupt TGA"); } // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); if (!tga_palette) { STBI_FREE(tga_data); return stbi__errpuc("outofmem", "Out of memory"); } if (tga_rgb16) { stbi_uc *pal_entry = tga_palette; STBI_ASSERT(tga_comp == STBI_rgb); for (i=0; i < tga_palette_len; ++i) { stbi__tga_read_rgb16(s, pal_entry); pal_entry += tga_comp; } } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { STBI_FREE(tga_data); STBI_FREE(tga_palette); return stbi__errpuc("bad palette", "Corrupt TGA"); } } // load the data for (i=0; i < tga_width * tga_height; ++i) { // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? if ( tga_is_RLE ) { if ( RLE_count == 0 ) { // yep, get the next byte as a RLE command int RLE_cmd = stbi__get8(s); RLE_count = 1 + (RLE_cmd & 127); RLE_repeating = RLE_cmd >> 7; read_next_pixel = 1; } else if ( !RLE_repeating ) { read_next_pixel = 1; } } else { read_next_pixel = 1; } // OK, if I need to read a pixel, do it now if ( read_next_pixel ) { // load however much data we did have if ( tga_indexed ) { // read in index, then perform the lookup int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); if ( pal_idx >= tga_palette_len ) { // invalid index pal_idx = 0; } pal_idx *= tga_comp; for (j = 0; j < tga_comp; ++j) { raw_data[j] = tga_palette[pal_idx+j]; } } else if(tga_rgb16) { STBI_ASSERT(tga_comp == STBI_rgb); stbi__tga_read_rgb16(s, raw_data); } else { // read in the data raw for (j = 0; j < tga_comp; ++j) { raw_data[j] = stbi__get8(s); } } // clear the reading flag for the next pixel read_next_pixel = 0; } // end of reading a pixel // copy data for (j = 0; j < tga_comp; ++j) tga_data[i*tga_comp+j] = raw_data[j]; // in case we're in RLE mode, keep counting down --RLE_count; } // do I need to invert the image? if ( tga_inverted ) { for (j = 0; j*2 < tga_height; ++j) { int index1 = j * tga_width * tga_comp; int index2 = (tga_height - 1 - j) * tga_width * tga_comp; for (i = tga_width * tga_comp; i > 0; --i) { unsigned char temp = tga_data[index1]; tga_data[index1] = tga_data[index2]; tga_data[index2] = temp; ++index1; ++index2; } } } // clear my palette, if I had one if ( tga_palette != NULL ) { STBI_FREE( tga_palette ); } } // swap RGB - if the source data was RGB16, it already is in the right order if (tga_comp >= 3 && !tga_rgb16) { unsigned char* tga_pixel = tga_data; for (i=0; i < tga_width * tga_height; ++i) { unsigned char temp = tga_pixel[0]; tga_pixel[0] = tga_pixel[2]; tga_pixel[2] = temp; tga_pixel += tga_comp; } } // convert to target component count if (req_comp && req_comp != tga_comp) tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); // the things I do to get rid of an error message, and yet keep // Microsoft's C compilers happy... [8^( tga_palette_start = tga_palette_len = tga_palette_bits = tga_x_origin = tga_y_origin = 0; STBI_NOTUSED(tga_palette_start); // OK, done return tga_data; } #endif // ************************************************************************************************* // Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s) { int r = (stbi__get32be(s) == 0x38425053); stbi__rewind(s); return r; } static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) { int count, nleft, len; count = 0; while ((nleft = pixelCount - count) > 0) { len = stbi__get8(s); if (len == 128) { // No-op. } else if (len < 128) { // Copy next len+1 bytes literally. len++; if (len > nleft) return 0; // corrupt data count += len; while (len) { *p = stbi__get8(s); p += 4; len--; } } else if (len > 128) { stbi_uc val; // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len = 257 - len; if (len > nleft) return 0; // corrupt data val = stbi__get8(s); count += len; while (len) { *p = val; p += 4; len--; } } } return 1; } static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { int pixelCount; int channelCount, compression; int channel, i; int bitdepth; int w,h; stbi_uc *out; STBI_NOTUSED(ri); // Check identifier if (stbi__get32be(s) != 0x38425053) // "8BPS" return stbi__errpuc("not PSD", "Corrupt PSD image"); // Check file type version. if (stbi__get16be(s) != 1) return stbi__errpuc("wrong version", "Unsupported version of PSD image"); // Skip 6 reserved bytes. stbi__skip(s, 6 ); // Read the number of channels (R, G, B, A, etc). channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); // Read the rows and columns of the image. h = stbi__get32be(s); w = stbi__get32be(s); if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); // Make sure the depth is 8 bits. bitdepth = stbi__get16be(s); if (bitdepth != 8 && bitdepth != 16) return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); // Make sure the color mode is RGB. // Valid options are: // 0: Bitmap // 1: Grayscale // 2: Indexed color // 3: RGB color // 4: CMYK color // 7: Multichannel // 8: Duotone // 9: Lab color if (stbi__get16be(s) != 3) return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) stbi__skip(s,stbi__get32be(s) ); // Skip the image resources. (resolution, pen tool paths, etc) stbi__skip(s, stbi__get32be(s) ); // Skip the reserved data. stbi__skip(s, stbi__get32be(s) ); // Find out if the data is compressed. // Known values: // 0: no compression // 1: RLE compressed compression = stbi__get16be(s); if (compression > 1) return stbi__errpuc("bad compression", "PSD has an unknown compression format"); // Check size if (!stbi__mad3sizes_valid(4, w, h, 0)) return stbi__errpuc("too large", "Corrupt PSD"); // Create the destination image. if (!compression && bitdepth == 16 && bpc == 16) { out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); ri->bits_per_channel = 16; } else out = (stbi_uc *) stbi__malloc(4 * w*h); if (!out) return stbi__errpuc("outofmem", "Out of memory"); pixelCount = w*h; // Initialize the data to zero. //memset( out, 0, pixelCount * 4 ); // Finally, the image data. if (compression) { // RLE as used by .PSD and .TIFF // Loop until you get the number of unpacked bytes you are expecting: // Read the next source byte into n. // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. // Else if n is 128, noop. // Endloop // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, // which we're going to just skip. stbi__skip(s, h * channelCount * 2 ); // Read the RLE data by channel. for (channel = 0; channel < 4; channel++) { stbi_uc *p; p = out+channel; if (channel >= channelCount) { // Fill this channel with default data. for (i = 0; i < pixelCount; i++, p += 4) *p = (channel == 3 ? 255 : 0); } else { // Read the RLE data. if (!stbi__psd_decode_rle(s, p, pixelCount)) { STBI_FREE(out); return stbi__errpuc("corrupt", "bad RLE data"); } } } } else { // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. // Read the data by channel. for (channel = 0; channel < 4; channel++) { if (channel >= channelCount) { // Fill this channel with default data. if (bitdepth == 16 && bpc == 16) { stbi__uint16 *q = ((stbi__uint16 *) out) + channel; stbi__uint16 val = channel == 3 ? 65535 : 0; for (i = 0; i < pixelCount; i++, q += 4) *q = val; } else { stbi_uc *p = out+channel; stbi_uc val = channel == 3 ? 255 : 0; for (i = 0; i < pixelCount; i++, p += 4) *p = val; } } else { if (ri->bits_per_channel == 16) { // output bpc stbi__uint16 *q = ((stbi__uint16 *) out) + channel; for (i = 0; i < pixelCount; i++, q += 4) *q = (stbi__uint16) stbi__get16be(s); } else { stbi_uc *p = out+channel; if (bitdepth == 16) { // input bpc for (i = 0; i < pixelCount; i++, p += 4) *p = (stbi_uc) (stbi__get16be(s) >> 8); } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); } } } } } // remove weird white matte from PSD if (channelCount >= 4) { if (ri->bits_per_channel == 16) { for (i=0; i < w*h; ++i) { stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; if (pixel[3] != 0 && pixel[3] != 65535) { float a = pixel[3] / 65535.0f; float ra = 1.0f / a; float inv_a = 65535.0f * (1 - ra); pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); } } } else { for (i=0; i < w*h; ++i) { unsigned char *pixel = out + 4*i; if (pixel[3] != 0 && pixel[3] != 255) { float a = pixel[3] / 255.0f; float ra = 1.0f / a; float inv_a = 255.0f * (1 - ra); pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); } } } } // convert to desired output format if (req_comp && req_comp != 4) { if (ri->bits_per_channel == 16) out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); else out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure } if (comp) *comp = 4; *y = h; *x = w; return out; } #endif // ************************************************************************************************* // Softimage PIC loader // by Tom Seddon // // See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format // See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ #ifndef STBI_NO_PIC static int stbi__pic_is4(stbi__context *s,const char *str) { int i; for (i=0; i<4; ++i) if (stbi__get8(s) != (stbi_uc)str[i]) return 0; return 1; } static int stbi__pic_test_core(stbi__context *s) { int i; if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) return 0; for(i=0;i<84;++i) stbi__get8(s); if (!stbi__pic_is4(s,"PICT")) return 0; return 1; } typedef struct { stbi_uc size,type,channel; } stbi__pic_packet; static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) { int mask=0x80, i; for (i=0; i<4; ++i, mask>>=1) { if (channel & mask) { if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); dest[i]=stbi__get8(s); } } return dest; } static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) { int mask=0x80,i; for (i=0;i<4; ++i, mask>>=1) if (channel&mask) dest[i]=src[i]; } static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) { int act_comp=0,num_packets=0,y,chained; stbi__pic_packet packets[10]; // this will (should...) cater for even some bizarre stuff like having data // for the same channel in multiple packets. do { stbi__pic_packet *packet; if (num_packets==sizeof(packets)/sizeof(packets[0])) return stbi__errpuc("bad format","too many packets"); packet = &packets[num_packets++]; chained = stbi__get8(s); packet->size = stbi__get8(s); packet->type = stbi__get8(s); packet->channel = stbi__get8(s); act_comp |= packet->channel; if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); } while (chained); *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? for(y=0; ytype) { default: return stbi__errpuc("bad format","packet has bad compression type"); case 0: {//uncompressed int x; for(x=0;xchannel,dest)) return 0; break; } case 1://Pure RLE { int left=width, i; while (left>0) { stbi_uc count,value[4]; count=stbi__get8(s); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); if (count > left) count = (stbi_uc) left; if (!stbi__readval(s,packet->channel,value)) return 0; for(i=0; ichannel,dest,value); left -= count; } } break; case 2: {//Mixed RLE int left=width; while (left>0) { int count = stbi__get8(s), i; if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); if (count >= 128) { // Repeated stbi_uc value[4]; if (count==128) count = stbi__get16be(s); else count -= 127; if (count > left) return stbi__errpuc("bad file","scanline overrun"); if (!stbi__readval(s,packet->channel,value)) return 0; for(i=0;ichannel,dest,value); } else { // Raw ++count; if (count>left) return stbi__errpuc("bad file","scanline overrun"); for(i=0;ichannel,dest)) return 0; } left-=count; } break; } } } } return result; } static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; int i, x,y, internal_comp; STBI_NOTUSED(ri); if (!comp) comp = &internal_comp; for (i=0; i<92; ++i) stbi__get8(s); x = stbi__get16be(s); y = stbi__get16be(s); if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); stbi__get32be(s); //skip `ratio' stbi__get16be(s); //skip `fields' stbi__get16be(s); //skip `pad' // intermediate buffer is RGBA result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); if (!result) return stbi__errpuc("outofmem", "Out of memory"); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { STBI_FREE(result); result=0; } *px = x; *py = y; if (req_comp == 0) req_comp = *comp; result=stbi__convert_format(result,4,req_comp,x,y); return result; } static int stbi__pic_test(stbi__context *s) { int r = stbi__pic_test_core(s); stbi__rewind(s); return r; } #endif // ************************************************************************************************* // GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb #ifndef STBI_NO_GIF typedef struct { stbi__int16 prefix; stbi_uc first; stbi_uc suffix; } stbi__gif_lzw; typedef struct { int w,h; stbi_uc *out; // output buffer (always 4 components) stbi_uc *background; // The current "background" as far as a gif is concerned stbi_uc *history; int flags, bgindex, ratio, transparent, eflags; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; stbi__gif_lzw codes[8192]; stbi_uc *color_table; int parse, step; int lflags; int start_x, start_y; int max_x, max_y; int cur_x, cur_y; int line_size; int delay; } stbi__gif; static int stbi__gif_test_raw(stbi__context *s) { int sz; if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; sz = stbi__get8(s); if (sz != '9' && sz != '7') return 0; if (stbi__get8(s) != 'a') return 0; return 1; } static int stbi__gif_test(stbi__context *s) { int r = stbi__gif_test_raw(s); stbi__rewind(s); return r; } static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) { int i; for (i=0; i < num_entries; ++i) { pal[i][2] = stbi__get8(s); pal[i][1] = stbi__get8(s); pal[i][0] = stbi__get8(s); pal[i][3] = transp == i ? 0 : 255; } } static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) { stbi_uc version; if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return stbi__err("not GIF", "Corrupt GIF"); version = stbi__get8(s); if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); stbi__g_failure_reason = ""; g->w = stbi__get16le(s); g->h = stbi__get16le(s); g->flags = stbi__get8(s); g->bgindex = stbi__get8(s); g->ratio = stbi__get8(s); g->transparent = -1; if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments if (is_info) return 1; if (g->flags & 0x80) stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); return 1; } static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); if (!g) return stbi__err("outofmem", "Out of memory"); if (!stbi__gif_header(s, g, comp, 1)) { STBI_FREE(g); stbi__rewind( s ); return 0; } if (x) *x = g->w; if (y) *y = g->h; STBI_FREE(g); return 1; } static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) { stbi_uc *p, *c; int idx; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty if (g->codes[code].prefix >= 0) stbi__out_gif_code(g, g->codes[code].prefix); if (g->cur_y >= g->max_y) return; idx = g->cur_x + g->cur_y; p = &g->out[idx]; g->history[idx / 4] = 1; c = &g->color_table[g->codes[code].suffix * 4]; if (c[3] > 128) { // don't render transparent pixels; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; p[3] = c[3]; } g->cur_x += 4; if (g->cur_x >= g->max_x) { g->cur_x = g->start_x; g->cur_y += g->step; while (g->cur_y >= g->max_y && g->parse > 0) { g->step = (1 << g->parse) * g->line_size; g->cur_y = g->start_y + (g->step >> 1); --g->parse; } } } static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) { stbi_uc lzw_cs; stbi__int32 len, init_code; stbi__uint32 first; stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; stbi__gif_lzw *p; lzw_cs = stbi__get8(s); if (lzw_cs > 12) return NULL; clear = 1 << lzw_cs; first = 1; codesize = lzw_cs + 1; codemask = (1 << codesize) - 1; bits = 0; valid_bits = 0; for (init_code = 0; init_code < clear; init_code++) { g->codes[init_code].prefix = -1; g->codes[init_code].first = (stbi_uc) init_code; g->codes[init_code].suffix = (stbi_uc) init_code; } // support no starting clear code avail = clear+2; oldcode = -1; len = 0; for(;;) { if (valid_bits < codesize) { if (len == 0) { len = stbi__get8(s); // start new block if (len == 0) return g->out; } --len; bits |= (stbi__int32) stbi__get8(s) << valid_bits; valid_bits += 8; } else { stbi__int32 code = bits & codemask; bits >>= codesize; valid_bits -= codesize; // @OPTIMIZE: is there some way we can accelerate the non-clear path? if (code == clear) { // clear code codesize = lzw_cs + 1; codemask = (1 << codesize) - 1; avail = clear + 2; oldcode = -1; first = 0; } else if (code == clear + 1) { // end of stream code stbi__skip(s, len); while ((len = stbi__get8(s)) > 0) stbi__skip(s,len); return g->out; } else if (code <= avail) { if (first) { return stbi__errpuc("no clear code", "Corrupt GIF"); } if (oldcode >= 0) { p = &g->codes[avail++]; if (avail > 8192) { return stbi__errpuc("too many codes", "Corrupt GIF"); } p->prefix = (stbi__int16) oldcode; p->first = g->codes[oldcode].first; p->suffix = (code == avail) ? p->first : g->codes[code].first; } else if (code == avail) return stbi__errpuc("illegal code in raster", "Corrupt GIF"); stbi__out_gif_code(g, (stbi__uint16) code); if ((avail & codemask) == 0 && avail <= 0x0FFF) { codesize++; codemask = (1 << codesize) - 1; } oldcode = code; } else { return stbi__errpuc("illegal code in raster", "Corrupt GIF"); } } } } // this function is designed to support animated gifs, although stb_image doesn't support it // two back is the image from two frames ago, used for a very specific disposal format static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) { int dispose; int first_frame; int pi; int pcount; STBI_NOTUSED(req_comp); // on first frame, any non-written pixels get the background colour (non-transparent) first_frame = 0; if (g->out == 0) { if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) return stbi__errpuc("too large", "GIF image is too large"); pcount = g->w * g->h; g->out = (stbi_uc *) stbi__malloc(4 * pcount); g->background = (stbi_uc *) stbi__malloc(4 * pcount); g->history = (stbi_uc *) stbi__malloc(pcount); if (!g->out || !g->background || !g->history) return stbi__errpuc("outofmem", "Out of memory"); // image is treated as "transparent" at the start - ie, nothing overwrites the current background; // background colour is only used for pixels that are not rendered first frame, after that "background" // color refers to the color that was there the previous frame. memset(g->out, 0x00, 4 * pcount); memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) memset(g->history, 0x00, pcount); // pixels that were affected previous frame first_frame = 1; } else { // second frame - how do we dispose of the previous one? dispose = (g->eflags & 0x1C) >> 2; pcount = g->w * g->h; if ((dispose == 3) && (two_back == 0)) { dispose = 2; // if I don't have an image to revert back to, default to the old background } if (dispose == 3) { // use previous graphic for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); } } } else if (dispose == 2) { // restore what was changed last frame to background before that frame; for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); } } } else { // This is a non-disposal case eithe way, so just // leave the pixels as is, and they will become the new background // 1: do not dispose // 0: not specified. } // background is what out is after the undoing of the previou frame; memcpy( g->background, g->out, 4 * g->w * g->h ); } // clear my history; memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame for (;;) { int tag = stbi__get8(s); switch (tag) { case 0x2C: /* Image Descriptor */ { stbi__int32 x, y, w, h; stbi_uc *o; x = stbi__get16le(s); y = stbi__get16le(s); w = stbi__get16le(s); h = stbi__get16le(s); if (((x + w) > (g->w)) || ((y + h) > (g->h))) return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); g->line_size = g->w * 4; g->start_x = x * 4; g->start_y = y * g->line_size; g->max_x = g->start_x + w * 4; g->max_y = g->start_y + h * g->line_size; g->cur_x = g->start_x; g->cur_y = g->start_y; // if the width of the specified rectangle is 0, that means // we may not see *any* pixels or the image is malformed; // to make sure this is caught, move the current y down to // max_y (which is what out_gif_code checks). if (w == 0) g->cur_y = g->max_y; g->lflags = stbi__get8(s); if (g->lflags & 0x40) { g->step = 8 * g->line_size; // first interlaced spacing g->parse = 3; } else { g->step = g->line_size; g->parse = 0; } if (g->lflags & 0x80) { stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); g->color_table = (stbi_uc *) g->lpal; } else if (g->flags & 0x80) { g->color_table = (stbi_uc *) g->pal; } else return stbi__errpuc("missing color table", "Corrupt GIF"); o = stbi__process_gif_raster(s, g); if (!o) return NULL; // if this was the first frame, pcount = g->w * g->h; if (first_frame && (g->bgindex > 0)) { // if first frame, any pixel not drawn to gets the background color for (pi = 0; pi < pcount; ++pi) { if (g->history[pi] == 0) { g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); } } } return o; } case 0x21: // Comment Extension. { int len; int ext = stbi__get8(s); if (ext == 0xF9) { // Graphic Control Extension. len = stbi__get8(s); if (len == 4) { g->eflags = stbi__get8(s); g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. // unset old transparent if (g->transparent >= 0) { g->pal[g->transparent][3] = 255; } if (g->eflags & 0x01) { g->transparent = stbi__get8(s); if (g->transparent >= 0) { g->pal[g->transparent][3] = 0; } } else { // don't need transparent stbi__skip(s, 1); g->transparent = -1; } } else { stbi__skip(s, len); break; } } while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); } break; } case 0x3B: // gif stream termination code return (stbi_uc *) s; // using '1' causes warning on some compilers default: return stbi__errpuc("unknown code", "Corrupt GIF"); } } } static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) { STBI_FREE(g->out); STBI_FREE(g->history); STBI_FREE(g->background); if (out) STBI_FREE(out); if (delays && *delays) STBI_FREE(*delays); return stbi__errpuc("outofmem", "Out of memory"); } static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { if (stbi__gif_test(s)) { int layers = 0; stbi_uc *u = 0; stbi_uc *out = 0; stbi_uc *two_back = 0; stbi__gif g; int stride; int out_size = 0; int delays_size = 0; STBI_NOTUSED(out_size); STBI_NOTUSED(delays_size); memset(&g, 0, sizeof(g)); if (delays) { *delays = 0; } do { u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { *x = g.w; *y = g.h; ++layers; stride = g.w * g.h * 4; if (out) { void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); if (!tmp) return stbi__load_gif_main_outofmem(&g, out, delays); else { out = (stbi_uc*) tmp; out_size = layers * stride; } if (delays) { int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); if (!new_delays) return stbi__load_gif_main_outofmem(&g, out, delays); *delays = new_delays; delays_size = layers * sizeof(int); } } else { out = (stbi_uc*)stbi__malloc( layers * stride ); if (!out) return stbi__load_gif_main_outofmem(&g, out, delays); out_size = layers * stride; if (delays) { *delays = (int*) stbi__malloc( layers * sizeof(int) ); if (!*delays) return stbi__load_gif_main_outofmem(&g, out, delays); delays_size = layers * sizeof(int); } } memcpy( out + ((layers - 1) * stride), u, stride ); if (layers >= 2) { two_back = out - 2 * stride; } if (delays) { (*delays)[layers - 1U] = g.delay; } } } while (u != 0); // free temp buffer; STBI_FREE(g.out); STBI_FREE(g.history); STBI_FREE(g.background); // do the final conversion after loading everything; if (req_comp && req_comp != 4) out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); *z = layers; return out; } else { return stbi__errpuc("not GIF", "Image was not as a gif type."); } } static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *u = 0; stbi__gif g; memset(&g, 0, sizeof(g)); STBI_NOTUSED(ri); u = stbi__gif_load_next(s, &g, comp, req_comp, 0); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { *x = g.w; *y = g.h; // moved conversion to after successful load so that the same // can be done for multiple frames. if (req_comp && req_comp != 4) u = stbi__convert_format(u, 4, req_comp, g.w, g.h); } else if (g.out) { // if there was an error and we allocated an image buffer, free it! STBI_FREE(g.out); } // free buffers needed for multiple frame loading; STBI_FREE(g.history); STBI_FREE(g.background); return u; } static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) { return stbi__gif_info_raw(s,x,y,comp); } #endif // ************************************************************************************************* // Radiance RGBE HDR loader // originally by Nicolas Schulz #ifndef STBI_NO_HDR static int stbi__hdr_test_core(stbi__context *s, const char *signature) { int i; for (i=0; signature[i]; ++i) if (stbi__get8(s) != signature[i]) return 0; stbi__rewind(s); return 1; } static int stbi__hdr_test(stbi__context* s) { int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); stbi__rewind(s); if(!r) { r = stbi__hdr_test_core(s, "#?RGBE\n"); stbi__rewind(s); } return r; } #define STBI__HDR_BUFLEN 1024 static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) { int len=0; char c = '\0'; c = (char) stbi__get8(z); while (!stbi__at_eof(z) && c != '\n') { buffer[len++] = c; if (len == STBI__HDR_BUFLEN-1) { // flush to end of line while (!stbi__at_eof(z) && stbi__get8(z) != '\n') ; break; } c = (char) stbi__get8(z); } buffer[len] = 0; return buffer; } static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) { if ( input[3] != 0 ) { float f1; // Exponent f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); if (req_comp <= 2) output[0] = (input[0] + input[1] + input[2]) * f1 / 3; else { output[0] = input[0] * f1; output[1] = input[1] * f1; output[2] = input[2] * f1; } if (req_comp == 2) output[1] = 1; if (req_comp == 4) output[3] = 1; } else { switch (req_comp) { case 4: output[3] = 1; /* fallthrough */ case 3: output[0] = output[1] = output[2] = 0; break; case 2: output[1] = 1; /* fallthrough */ case 1: output[0] = 0; break; } } } static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; int width, height; stbi_uc *scanline; float *hdr_data; int len; unsigned char count, value; int i, j, k, c1,c2, z; const char *headerToken; STBI_NOTUSED(ri); // Check identifier headerToken = stbi__hdr_gettoken(s,buffer); if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) return stbi__errpf("not HDR", "Corrupt HDR image"); // Parse header for(;;) { token = stbi__hdr_gettoken(s,buffer); if (token[0] == 0) break; if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; } if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); // Parse width and height // can't use sscanf() if we're not using stdio! token = stbi__hdr_gettoken(s,buffer); if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); token += 3; height = (int) strtol(token, &token, 10); while (*token == ' ') ++token; if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); token += 3; width = (int) strtol(token, NULL, 10); if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); *x = width; *y = height; if (comp) *comp = 3; if (req_comp == 0) req_comp = 3; if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) return stbi__errpf("too large", "HDR image is too large"); // Read data hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); if (!hdr_data) return stbi__errpf("outofmem", "Out of memory"); // Load image data // image data is stored as some number of sca if ( width < 8 || width >= 32768) { // Read flat data for (j=0; j < height; ++j) { for (i=0; i < width; ++i) { stbi_uc rgbe[4]; main_decode_loop: stbi__getn(s, rgbe, 4); stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); } } } else { // Read RLE-encoded data scanline = NULL; for (j = 0; j < height; ++j) { c1 = stbi__get8(s); c2 = stbi__get8(s); len = stbi__get8(s); if (c1 != 2 || c2 != 2 || (len & 0x80)) { // not run-length encoded, so we have to actually use THIS data as a decoded // pixel (note this can't be a valid pixel--one of RGB must be >= 128) stbi_uc rgbe[4]; rgbe[0] = (stbi_uc) c1; rgbe[1] = (stbi_uc) c2; rgbe[2] = (stbi_uc) len; rgbe[3] = (stbi_uc) stbi__get8(s); stbi__hdr_convert(hdr_data, rgbe, req_comp); i = 1; j = 0; STBI_FREE(scanline); goto main_decode_loop; // yes, this makes no sense } len <<= 8; len |= stbi__get8(s); if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } if (scanline == NULL) { scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); if (!scanline) { STBI_FREE(hdr_data); return stbi__errpf("outofmem", "Out of memory"); } } for (k = 0; k < 4; ++k) { int nleft; i = 0; while ((nleft = width - i) > 0) { count = stbi__get8(s); if (count > 128) { // Run value = stbi__get8(s); count -= 128; if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } } } for (i=0; i < width; ++i) stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); } if (scanline) STBI_FREE(scanline); } return hdr_data; } static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) { char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; int dummy; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); return 0; } for(;;) { token = stbi__hdr_gettoken(s,buffer); if (token[0] == 0) break; if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; } if (!valid) { stbi__rewind( s ); return 0; } token = stbi__hdr_gettoken(s,buffer); if (strncmp(token, "-Y ", 3)) { stbi__rewind( s ); return 0; } token += 3; *y = (int) strtol(token, &token, 10); while (*token == ' ') ++token; if (strncmp(token, "+X ", 3)) { stbi__rewind( s ); return 0; } token += 3; *x = (int) strtol(token, NULL, 10); *comp = 3; return 1; } #endif // STBI_NO_HDR #ifndef STBI_NO_BMP static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) { void *p; stbi__bmp_data info; info.all_a = 255; p = stbi__bmp_parse_header(s, &info); if (p == NULL) { stbi__rewind( s ); return 0; } if (x) *x = s->img_x; if (y) *y = s->img_y; if (comp) { if (info.bpp == 24 && info.ma == 0xff000000) *comp = 3; else *comp = info.ma ? 4 : 3; } return 1; } #endif #ifndef STBI_NO_PSD static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) { int channelCount, dummy, depth; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 1) { stbi__rewind( s ); return 0; } stbi__skip(s, 6); channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) { stbi__rewind( s ); return 0; } *y = stbi__get32be(s); *x = stbi__get32be(s); depth = stbi__get16be(s); if (depth != 8 && depth != 16) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 3) { stbi__rewind( s ); return 0; } *comp = 4; return 1; } static int stbi__psd_is16(stbi__context *s) { int channelCount, depth; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 1) { stbi__rewind( s ); return 0; } stbi__skip(s, 6); channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) { stbi__rewind( s ); return 0; } STBI_NOTUSED(stbi__get32be(s)); STBI_NOTUSED(stbi__get32be(s)); depth = stbi__get16be(s); if (depth != 16) { stbi__rewind( s ); return 0; } return 1; } #endif #ifndef STBI_NO_PIC static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) { int act_comp=0,num_packets=0,chained,dummy; stbi__pic_packet packets[10]; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { stbi__rewind(s); return 0; } stbi__skip(s, 88); *x = stbi__get16be(s); *y = stbi__get16be(s); if (stbi__at_eof(s)) { stbi__rewind( s); return 0; } if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { stbi__rewind( s ); return 0; } stbi__skip(s, 8); do { stbi__pic_packet *packet; if (num_packets==sizeof(packets)/sizeof(packets[0])) return 0; packet = &packets[num_packets++]; chained = stbi__get8(s); packet->size = stbi__get8(s); packet->type = stbi__get8(s); packet->channel = stbi__get8(s); act_comp |= packet->channel; if (stbi__at_eof(s)) { stbi__rewind( s ); return 0; } if (packet->size != 8) { stbi__rewind( s ); return 0; } } while (chained); *comp = (act_comp & 0x10 ? 4 : 3); return 1; } #endif // ************************************************************************************************* // Portable Gray Map and Portable Pixel Map loader // by Ken Miller // // PGM: http://netpbm.sourceforge.net/doc/pgm.html // PPM: http://netpbm.sourceforge.net/doc/ppm.html // // Known limitations: // Does not support comments in the header section // Does not support ASCII image data (formats P2 and P3) #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s) { char p, t; p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { stbi__rewind( s ); return 0; } return 1; } static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; STBI_NOTUSED(ri); ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); if (ri->bits_per_channel == 0) return 0; if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); *x = s->img_x; *y = s->img_y; if (comp) *comp = s->img_n; if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) return stbi__errpuc("too large", "PNM too large"); out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { STBI_FREE(out); return stbi__errpuc("bad PNM", "PNM file truncated"); } if (req_comp && req_comp != s->img_n) { if (ri->bits_per_channel == 16) { out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); } else { out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); } if (out == NULL) return out; // stbi__convert_format frees input on failure } return out; } static int stbi__pnm_isspace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; } static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) { for (;;) { while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) *c = (char) stbi__get8(s); if (stbi__at_eof(s) || *c != '#') break; while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) *c = (char) stbi__get8(s); } } static int stbi__pnm_isdigit(char c) { return c >= '0' && c <= '9'; } static int stbi__pnm_getinteger(stbi__context *s, char *c) { int value = 0; while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { value = value*10 + (*c - '0'); *c = (char) stbi__get8(s); if((value > 214748364) || (value == 214748364 && *c > '7')) return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); } return value; } static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) { int maxv, dummy; char c, p, t; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; stbi__rewind(s); // Get identifier p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { stbi__rewind(s); return 0; } *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm c = (char) stbi__get8(s); stbi__pnm_skip_whitespace(s, &c); *x = stbi__pnm_getinteger(s, &c); // read width if(*x == 0) return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); *y = stbi__pnm_getinteger(s, &c); // read height if (*y == 0) return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); maxv = stbi__pnm_getinteger(s, &c); // read max value if (maxv > 65535) return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); else if (maxv > 255) return 16; else return 8; } static int stbi__pnm_is16(stbi__context *s) { if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) return 1; return 0; } #endif static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) { #ifndef STBI_NO_JPEG if (stbi__jpeg_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PNG if (stbi__png_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_GIF if (stbi__gif_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_BMP if (stbi__bmp_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PSD if (stbi__psd_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PIC if (stbi__pic_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PNM if (stbi__pnm_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_HDR if (stbi__hdr_info(s, x, y, comp)) return 1; #endif // test tga last because it's a crappy test! #ifndef STBI_NO_TGA if (stbi__tga_info(s, x, y, comp)) return 1; #endif return stbi__err("unknown image type", "Image not of any known type, or corrupt"); } static int stbi__is_16_main(stbi__context *s) { #ifndef STBI_NO_PNG if (stbi__png_is16(s)) return 1; #endif #ifndef STBI_NO_PSD if (stbi__psd_is16(s)) return 1; #endif #ifndef STBI_NO_PNM if (stbi__pnm_is16(s)) return 1; #endif return 0; } #ifndef STBI_NO_STDIO STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); result = stbi_info_from_file(f, x, y, comp); fclose(f); return result; } STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) { int r; stbi__context s; long pos = ftell(f); stbi__start_file(&s, f); r = stbi__info_main(&s,x,y,comp); fseek(f,pos,SEEK_SET); return r; } STBIDEF int stbi_is_16_bit(char const *filename) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); result = stbi_is_16_bit_from_file(f); fclose(f); return result; } STBIDEF int stbi_is_16_bit_from_file(FILE *f) { int r; stbi__context s; long pos = ftell(f); stbi__start_file(&s, f); r = stbi__is_16_main(&s); fseek(f,pos,SEEK_SET); return r; } #endif // !STBI_NO_STDIO STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__info_main(&s,x,y,comp); } STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); return stbi__info_main(&s,x,y,comp); } STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__is_16_main(&s); } STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); return stbi__is_16_main(&s); } #endif // STB_IMAGE_IMPLEMENTATION /* revision history: 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug 1-bit BMP *_is_16_bit api avoid warnings 2.16 (2017-07-23) all functions have 16-bit variants; STBI_NO_STDIO works again; compilation fixes; fix rounding in unpremultiply; optimize vertical flip; disable raw_len validation; documentation fixes 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; warning fixes; disable run-time SSE detection on gcc; uniform handling of optional "return" values; thread-safe initialization of zlib tables 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack remove white matting for transparent PSD fix reported channel count for PNG & BMP re-enable SSE2 in non-gcc 64-bit support RGB-formatted JPEG read 16-bit PNGs (only as 8-bit) 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) info() for TGA could break due to .hdr handling info() for BMP to shares code instead of sloppy parse can use STBI_REALLOC_SIZED if allocator doesn't support realloc code cleanup 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support limited 16-bpc PSD support #ifdef unused functions bug with < 92 byte PIC,PNM,HDR,TGA 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit 2.03 (2015-04-12) extra corruption checking (mmozeiko) stbi_set_flip_vertically_on_load (nguillemot) fix NEON support; fix mingw support 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) progressive JPEG (stb) PGM/PPM support (Ken Miller) STBI_MALLOC,STBI_REALLOC,STBI_FREE GIF bugfix -- seemingly never worked STBI_NO_*, STBI_ONLY_* 1.48 (2014-12-14) fix incorrectly-named assert() 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) optimize PNG (ryg) fix bug in interlaced PNG with user-specified channel count (stb) 1.46 (2014-08-26) fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG 1.45 (2014-08-16) fix MSVC-ARM internal compiler error by wrapping malloc 1.44 (2014-08-07) various warning fixes from Ronny Chevalier 1.43 (2014-07-15) fix MSVC-only compiler problem in code changed in 1.42 1.42 (2014-07-09) don't define _CRT_SECURE_NO_WARNINGS (affects user code) fixes to stbi__cleanup_jpeg path added STBI_ASSERT to avoid requiring assert.h 1.41 (2014-06-25) fix search&replace from 1.36 that messed up comments/error messages 1.40 (2014-06-22) fix gcc struct-initialization warning 1.39 (2014-06-15) fix to TGA optimization when req_comp != number of components in TGA; fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) add support for BMP version 5 (more ignored fields) 1.38 (2014-06-06) suppress MSVC warnings on integer casts truncating values fix accidental rename of 'skip' field of I/O 1.37 (2014-06-04) remove duplicate typedef 1.36 (2014-06-03) convert to header file single-file library if de-iphone isn't set, load iphone images color-swapped instead of returning NULL 1.35 (2014-05-27) various warnings fix broken STBI_SIMD path fix bug where stbi_load_from_file no longer left file pointer in correct place fix broken non-easy path for 32-bit BMP (possibly never used) TGA optimization by Arseny Kapoulkine 1.34 (unknown) use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case 1.33 (2011-07-14) make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements 1.32 (2011-07-13) support for "info" function for all supported filetypes (SpartanJ) 1.31 (2011-06-20) a few more leak fixes, bug in PNG handling (SpartanJ) 1.30 (2011-06-11) added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) removed deprecated format-specific test/load functions removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) fix inefficiency in decoding 32-bit BMP (David Woo) 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) 1.27 (2010-08-01) cast-to-stbi_uc to fix warnings 1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ 1.25 (2010-07-17) refix trans_data warning (Won Chun) 1.24 (2010-07-12) perf improvements reading from files on platforms with lock-heavy fgetc() minor perf improvements for jpeg deprecated type-specific functions so we'll get feedback if they're needed attempt to fix trans_data warning (Won Chun) 1.23 fixed bug in iPhone support 1.22 (2010-07-10) removed image *writing* support stbi_info support from Jetro Lauha GIF support from Jean-Marc Lienher iPhone PNG-extensions from James Brown warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) 1.21 fix use of 'stbi_uc' in header (reported by jon blow) 1.20 added support for Softimage PIC, by Tom Seddon 1.19 bug in interlaced PNG corruption check (found by ryg) 1.18 (2008-08-02) fix a threading bug (local mutable static) 1.17 support interlaced PNG 1.16 major bugfix - stbi__convert_format converted one too many pixels 1.15 initialize some fields for thread safety 1.14 fix threadsafe conversion bug header-file-only version (#define STBI_HEADER_FILE_ONLY before including) 1.13 threadsafe 1.12 const qualifiers in the API 1.11 Support installable IDCT, colorspace conversion routines 1.10 Fixes for 64-bit (don't use "unsigned long") optimized upsampling by Fabian "ryg" Giesen 1.09 Fix format-conversion for PSD code (bad global variables!) 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz 1.07 attempt to fix C++ warning/errors again 1.06 attempt to fix C++ warning/errors again 1.05 fix TGA loading to return correct *comp and use good luminance calc 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR 1.02 support for (subset of) HDR files, float interface for preferred access to them 1.01 fix bug: possible bug in handling right-side up bmps... not sure fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all 1.00 interface to zlib that skips zlib header 0.99 correct handling of alpha in palette 0.98 TGA loader by lonesock; dynamically add loaders (untested) 0.97 jpeg errors on too large a file; also catch another malloc failure 0.96 fix detection of invalid v value - particleman@mollyrocket forum 0.95 during header scan, seek to markers in case of padding 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same 0.93 handle jpegtran output; verbose errors 0.92 read 4,8,16,24,32-bit BMP files of several formats 0.91 output 24-bit Windows 3.0 BMP files 0.90 fix a few more warnings; bump version number to approach 1.0 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd 0.60 fix compiling as c++ 0.59 fix warnings: merge Dave Moore's -Wall fixes 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available 0.56 fix bug: zlib uncompressed mode len vs. nlen 0.55 fix bug: restart_interval not initialized to 0 0.54 allow NULL for 'int *comp' 0.53 fix bug in png 3->4; speedup png decoding 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments 0.51 obey req_comp requests, 1-component jpegs return as 1-component, on 'test' only check type, not whether we support this variant 0.50 (2006-11-19) first released version */ /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ ================================================ FILE: src/third_party/stb/stb_sprintf.h ================================================ // ---------------------------------------------------------------------------- // // NOTE(rjf): This has been modified to support extra format specifiers // for the debugger project - this is *not* an unmodified copy of the original // stb_sprintf v1.10 code. // // ---------------------------------------------------------------------------- // stb_sprintf - v1.10 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb // // allowed types: sc uidBboXx p AaGgEef n // lengths : hh h ll j z t I64 I32 I // // Contributors: // Fabian "ryg" Giesen (reformatting) // github:aganm (attribute format) // // Contributors (bugfixes): // github:d26435 // github:trex78 // github:account-login // Jari Komppa (SI suffixes) // Rohit Nirmal // Marcin Wojdyr // Leonard Ritter // Stefano Zanotti // Adam Allison // Arvid Gerstmann // Markus Kolb // // LICENSE: // // See end of file for license information. #ifndef STB_SPRINTF_H_INCLUDE #define STB_SPRINTF_H_INCLUDE /* Single file sprintf replacement. Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. Hereby placed in public domain. This is a full sprintf replacement that supports everything that the C runtime sprintfs support, including float/double, 64-bit integers, hex floats, field parameters (%*.*d stuff), length reads backs, etc. Why would you need this if sprintf already exists? Well, first off, it's *much* faster (see below). It's also much smaller than the CRT versions code-space-wise. We've also added some simple improvements that are super handy (commas in thousands, callbacks at buffer full, for example). Finally, the format strings for MSVC and GCC differ for 64-bit integers (among other small things), so this lets you use the same format strings in cross platform code. It uses the standard single file trick of being both the header file and the source itself. If you just include it normally, you just get the header file function definitions. To get the code, you include it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. It only uses va_args macros from the C runtime to do it's work. It does cast doubles to S64s and shifts and divides U64s, which does drag in CRT code on most platforms. It compiles to roughly 8K with float support, and 4K without. As a comparison, when using MSVC static libs, calling sprintf drags in 16K. API: ==== int stbsp_sprintf( char * buf, char const * fmt, ... ) int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) Convert an arg list into a buffer. stbsp_snprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns a zero-terminated string (unlike regular snprintf). int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); Convert into a buffer, calling back every STB_SPRINTF_MIN chars. Your callback can then copy the chars out, print them or whatever. This function is actually the workhorse for everything else. The buffer you pass in must hold at least STB_SPRINTF_MIN characters. // you return the next buffer to use or 0 to stop converting void stbsp_set_separators( char comma, char period ) Set the comma and period characters to use. FLOATS/DOUBLES: =============== This code uses a internal float->ascii conversion method that uses doubles with error correction (double-doubles, for ~105 bits of precision). This conversion is round-trip perfect - that is, an atof of the values output here will give you the bit-exact double back. One difference is that our insignificant digits will be different than with MSVC or GCC (but they don't match each other either). We also don't attempt to find the minimum length matching float (pre-MSVC15 doesn't either). If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT and you'll save 4K of code space. 64-BIT INTS: ============ This library also supports 64-bit integers and you can use MSVC style or GCC style indicators (%I64d or %lld). It supports the C99 specifiers for size_t and ptr_diff_t (%jd %zd) as well. EXTRAS: ======= Like some GCCs, for integers and floats, you can use a ' (single quote) specifier and commas will be inserted on the thousands: "%'d" on 12345 would print 12,345. For integers and floats, you can use a "$" specifier and the number will be converted to float and then divided to get kilo, mega, giga or tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is "2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn 2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three $:s: "%$$$d" -> "2.42 M". To remove the space between the number and the suffix, add "_" specifier: "%_$d" -> "2.53M". In addition to octal and hexadecimal conversions, you can print integers in binary: "%b" for 256 would print 100. PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): =================================================================== "%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) "%24d" across all 32-bit ints (4.5x/4.2x faster) "%x" across all 32-bit ints (4.5x/3.8x faster) "%08x" across all 32-bit ints (4.3x/3.8x faster) "%f" across e-10 to e+10 floats (7.3x/6.0x faster) "%e" across e-10 to e+10 floats (8.1x/6.0x faster) "%g" across e-10 to e+10 floats (10.0x/7.1x faster) "%f" for values near e-300 (7.9x/6.5x faster) "%f" for values near e+300 (10.0x/9.1x faster) "%e" for values near e-300 (10.1x/7.0x faster) "%e" for values near e+300 (9.2x/6.0x faster) "%.320f" for values near e-300 (12.6x/11.2x faster) "%a" for random values (8.6x/4.3x faster) "%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) "%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) "%s%s%s" for 64 char strings (7.1x/7.3x faster) "...512 char string..." ( 35.0x/32.5x faster!) */ #if defined(__clang__) # if defined(__has_feature) && defined(__has_attribute) # if __has_feature(address_sanitizer) # if __has_attribute(__no_sanitize__) # define STBSP__ASAN __attribute__((__no_sanitize__("address"))) # elif __has_attribute(__no_sanitize_address__) # define STBSP__ASAN __attribute__((__no_sanitize_address__)) # elif __has_attribute(__no_address_safety_analysis__) # define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) # endif # endif # endif #elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) # if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ # define STBSP__ASAN __attribute__((__no_sanitize_address__)) # endif #elif defined(_MSC_VER) # if defined(__SANITIZE_ADDRESS__) # define STBSP__ASAN __declspec(no_sanitize_address) # endif #endif #ifndef STBSP__ASAN #define STBSP__ASAN #endif #ifdef STB_SPRINTF_STATIC #define STBSP__PUBLICDEC static STBSP__ASAN #define STBSP__PUBLICDEF static STBSP__ASAN #else #ifdef __cplusplus #define STBSP__PUBLICDEC extern "C" STBSP__ASAN #define STBSP__PUBLICDEF extern "C" STBSP__ASAN #else #define STBSP__PUBLICDEC extern STBSP__ASAN #define STBSP__PUBLICDEF STBSP__ASAN #endif #endif #if defined(__has_attribute) #if __has_attribute(format) #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) #endif #endif #ifndef STBSP__ATTRIBUTE_FORMAT #define STBSP__ATTRIBUTE_FORMAT(fmt,va) #endif #ifdef _MSC_VER #define STBSP__NOTUSED(v) (void)(v) #else #define STBSP__NOTUSED(v) (void)sizeof(v) #endif #include // for va_arg(), va_list() #include // size_t, ptrdiff_t #ifndef STB_SPRINTF_MIN #define STB_SPRINTF_MIN 512 // how many characters per callback #endif typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); #ifndef STB_SPRINTF_DECORATE #define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names #endif STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); #endif // STB_SPRINTF_H_INCLUDE #ifdef STB_SPRINTF_IMPLEMENTATION #define stbsp__uint32 unsigned int #define stbsp__int32 signed int #ifdef _MSC_VER #define stbsp__uint64 unsigned __int64 #define stbsp__int64 signed __int64 #else #define stbsp__uint64 unsigned long long #define stbsp__int64 signed long long #endif #define stbsp__uint16 unsigned short #ifndef stbsp__uintptr #if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) #define stbsp__uintptr stbsp__uint64 #else #define stbsp__uintptr stbsp__uint32 #endif #endif #ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) #if defined(_MSC_VER) && (_MSC_VER < 1900) #define STB_SPRINTF_MSVC_MODE #endif #endif #ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses #define STBSP__UNALIGNED(code) #else #define STBSP__UNALIGNED(code) code #endif #ifndef STB_SPRINTF_NOFLOAT // internal float utility functions static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); #define STBSP__SPECIAL 0x7000 #endif static char stbsp__period = '.'; static char stbsp__comma = ','; static struct { short temp; // force next field to be 2-byte aligned char pair[201]; } stbsp__digitpair = { 0, "00010203040506070809101112131415161718192021222324" "25262728293031323334353637383940414243444546474849" "50515253545556575859606162636465666768697071727374" "75767778798081828384858687888990919293949596979899" }; STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) { stbsp__period = pperiod; stbsp__comma = pcomma; } #define STBSP__LEFTJUST 1 #define STBSP__LEADINGPLUS 2 #define STBSP__LEADINGSPACE 4 #define STBSP__LEADING_0X 8 #define STBSP__LEADINGZERO 16 #define STBSP__INTMAX 32 #define STBSP__TRIPLET_COMMA 64 #define STBSP__NEGATIVE 128 #define STBSP__METRIC_SUFFIX 256 #define STBSP__HALFWIDTH 512 #define STBSP__METRIC_NOSPACE 1024 #define STBSP__METRIC_1024 2048 #define STBSP__METRIC_JEDEC 4096 static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) { sign[0] = 0; if (fl & STBSP__NEGATIVE) { sign[0] = 1; sign[1] = '-'; } else if (fl & STBSP__LEADINGSPACE) { sign[0] = 1; sign[1] = ' '; } else if (fl & STBSP__LEADINGPLUS) { sign[0] = 1; sign[1] = '+'; } } static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) { char const * sn = s; // get up to 4-byte alignment for (;;) { if (((stbsp__uintptr)sn & 3) == 0) break; if (!limit || *sn == 0) return (stbsp__uint32)(sn - s); ++sn; --limit; } // scan over 4 bytes at a time to find terminating 0 // this will intentionally scan up to 3 bytes past the end of buffers, // but becase it works 4B aligned, it will never cross page boundaries // (hence the STBSP__ASAN markup; the over-read here is intentional // and harmless) while (limit >= 4) { stbsp__uint32 v = *(stbsp__uint32 *)sn; // bit hack to find if there's a 0 byte in there if ((v - 0x01010101) & (~v) & 0x80808080UL) break; sn += 4; limit -= 4; } // handle the last few characters to find actual size while (limit && *sn) { ++sn; --limit; } return (stbsp__uint32)(sn - s); } STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) { static char hex[] = "0123456789abcdefxp"; static char hexu[] = "0123456789ABCDEFXP"; char *bf; char const *f; int tlen = 0; bf = buf; f = fmt; for (;;) { stbsp__int32 fw, pr, tz; stbsp__uint32 fl; // macros for the callback buffer stuff #define stbsp__chk_cb_bufL(bytes) \ { \ int len = (int)(bf - buf); \ if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ tlen += len; \ if (0 == (bf = buf = callback(buf, user, len))) \ goto done; \ } \ } #define stbsp__chk_cb_buf(bytes) \ { \ if (callback) { \ stbsp__chk_cb_bufL(bytes); \ } \ } #define stbsp__flush_cb() \ { \ stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ } // flush if there is even one byte in the buffer #define stbsp__cb_buf_clamp(cl, v) \ cl = v; \ if (callback) { \ int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ if (cl > lg) \ cl = lg; \ } // fast copy everything up to the next % (or end of string) for (;;) { while (((stbsp__uintptr)f) & 3) { schk1: if (f[0] == '%') goto scandd; schk2: if (f[0] == 0) goto endfmt; stbsp__chk_cb_buf(1); *bf++ = f[0]; ++f; } for (;;) { // Check if the next 4 bytes contain %(0x25) or end of string. // Using the 'hasless' trick: // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord stbsp__uint32 v, c; v = *(stbsp__uint32 *)f; c = (~v) & 0x80808080; if (((v ^ 0x25252525) - 0x01010101) & c) goto schk1; if ((v - 0x01010101) & c) goto schk2; if (callback) if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) goto schk1; #ifdef STB_SPRINTF_NOUNALIGNED if(((stbsp__uintptr)bf) & 3) { bf[0] = f[0]; bf[1] = f[1]; bf[2] = f[2]; bf[3] = f[3]; } else #endif { *(stbsp__uint32 *)bf = v; } bf += 4; f += 4; } } scandd: ++f; // ok, we have a percent, read the modifiers first fw = 0; pr = -1; fl = 0; tz = 0; // flags for (;;) { switch (f[0]) { // if we have left justify case '-': fl |= STBSP__LEFTJUST; ++f; continue; // if we have leading plus case '+': fl |= STBSP__LEADINGPLUS; ++f; continue; // if we have leading space case ' ': fl |= STBSP__LEADINGSPACE; ++f; continue; // if we have leading 0x case '#': fl |= STBSP__LEADING_0X; ++f; continue; // if we have thousand commas case '\'': fl |= STBSP__TRIPLET_COMMA; ++f; continue; // if we have kilo marker (none->kilo->kibi->jedec) case '$': if (fl & STBSP__METRIC_SUFFIX) { if (fl & STBSP__METRIC_1024) { fl |= STBSP__METRIC_JEDEC; } else { fl |= STBSP__METRIC_1024; } } else { fl |= STBSP__METRIC_SUFFIX; } ++f; continue; // if we don't want space between metric suffix and number case '_': fl |= STBSP__METRIC_NOSPACE; ++f; continue; // if we have leading zero case '0': fl |= STBSP__LEADINGZERO; ++f; goto flags_done; default: goto flags_done; } } flags_done: // get the field width if (f[0] == '*') { fw = va_arg(va, stbsp__uint32); ++f; } else { while ((f[0] >= '0') && (f[0] <= '9')) { fw = fw * 10 + f[0] - '0'; f++; } } // get the precision if (f[0] == '.') { ++f; if (f[0] == '*') { pr = va_arg(va, stbsp__uint32); ++f; } else { pr = 0; while ((f[0] >= '0') && (f[0] <= '9')) { pr = pr * 10 + f[0] - '0'; f++; } } } // handle integer size overrides switch (f[0]) { // are we halfwidth? case 'h': fl |= STBSP__HALFWIDTH; ++f; if (f[0] == 'h') ++f; // QUARTERWIDTH break; // are we 64-bit (unix style) case 'l': fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); ++f; if (f[0] == 'l') { fl |= STBSP__INTMAX; ++f; } break; // are we 64-bit on intmax? (c99) case 'j': fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; ++f; break; // are we 64-bit on size_t or ptrdiff_t? (c99) case 'z': fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; ++f; break; case 't': fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; ++f; break; // are we 64-bit (msft style) case 'I': if ((f[1] == '6') && (f[2] == '4')) { fl |= STBSP__INTMAX; f += 3; } else if ((f[1] == '3') && (f[2] == '2')) { f += 3; } else { fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); ++f; } break; default: break; } // handle each replacement switch (f[0]) { #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 char num[STBSP__NUMSZ]; char lead[8]; char tail[8]; char *s; char const *h; stbsp__uint32 l, n, cs; stbsp__uint64 n64; #ifndef STB_SPRINTF_NOFLOAT double fv; #endif stbsp__int32 dp; char const *sn; case 's': // get the string s = va_arg(va, char *); if (s == 0) s = (char *)"null"; // get the length, limited to desired precision // always limit to ~0u chars since our counts are 32b l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); lead[0] = 0; tail[0] = 0; pr = 0; dp = 0; cs = 0; // copy the string in goto scopy; //- //- //- // NOTE(rjf): DEBUGGER PROJECT ADDITION vvv // // The following additions are for using the debugger project's base layer // types in format strings. // case 'S': { String8 string = va_arg(va, String8); s = (char *)string.str; l = (U32)string.size; lead[0] = 0; tail[0] = 0; pr = 0; dp = 0; cs = 0; }goto scopy; case 'm': case 'M': { static const U64 one_kib = 1ull * 1024; static const U64 one_mib = 1ull * 1024 * 1024; static const U64 one_gib = 1ull * 1024 * 1024 * 1024; static const U64 one_tib = 1ull * 1024 * 1024 * 1024 * 1024; U64 size; if(f[0] == 'M') { size = va_arg(va, U64); } else { size = va_arg(va, U32); } U64 lo = 0; U64 hi = 0; char *units = ""; if(size < one_kib) { hi = size; units = "Bytes"; } else if(size < one_mib) { hi = size / one_kib; lo = ((size * 100) / one_kib) % 100; units = "KiB"; } else if(size < one_gib) { hi = size / one_mib; lo = ((size * 100) / one_mib) % 100; units = "MiB"; } else if(size < one_tib) { hi = size / one_gib; lo = ((size * 100) / one_gib) % 100; units = "GiB"; } else { Assert(size <= max_U64/100ull); hi = size / one_tib; lo = ((size * 100) / one_tib) % 100; units = "TiB"; } // format high part if(hi > 0) { s = num; for(U64 n = hi; n > 0; n /= 10ull) { *s = (char)(n % 10ull) + '0'; ++s; } for(S64 i = (S64)(s-num)-1; i >= 0; --i) { *bf = num[i]; ++bf; } } else { *bf = '0'; ++bf; } // format low part if(lo > 0) { *bf = '.'; ++bf; s = num; for(U64 n = lo; n > 0; n /= 10ull) { *s = (char)(n % 10ull) + '0'; ++s; } U64 lead_zero_count = 3 - (U64)(s-num); for(U64 i = 1; i < lead_zero_count; ++i) { *bf = '0'; ++bf; } for(S64 i = (S64)(s-num)-1; i >= 0; --i) { *bf = num[i]; ++bf; } } *bf = ' '; ++bf; // copy units for(U64 i = 0; units[i] != 0; ++i) { *bf = units[i]; ++bf; } }break; case 'r': { Rng1U64 range = va_arg(va, Rng1U64); *bf = '['; ++bf; U8 buffer[ARENA_HEADER_SIZE + 128]; Arena *arena = arena_alloc_(&(ArenaParams){ .flags = ArenaFlag_NoChain, .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer }); String8 min = str8_from_u64(arena, range.min, 16, 0, 0); MemoryCopy(bf, min.str, min.size); bf += min.size; *bf = ','; ++bf; *bf = ' '; ++bf; arena_clear(arena); String8 max = str8_from_u64(arena, range.max, 16, 0, 0); MemoryCopy(bf, max.str, max.size); bf += max.size; *bf = ')'; ++bf; }break; // // NOTE(rjf): DEBUGGER PROJECT ADDITION ^^^ //- //- //- case 'c': // char // get the character s = num + STBSP__NUMSZ - 1; *s = (char)va_arg(va, int); l = 1; lead[0] = 0; tail[0] = 0; pr = 0; dp = 0; cs = 0; goto scopy; case 'n': // weird write-bytes specifier { int *d = va_arg(va, int *); *d = tlen + (int)(bf - buf); } break; #ifdef STB_SPRINTF_NOFLOAT case 'A': // float case 'a': // hex float case 'G': // float case 'g': // float case 'E': // float case 'e': // float case 'f': // float va_arg(va, double); // eat it s = (char *)"No float"; l = 8; lead[0] = 0; tail[0] = 0; pr = 0; cs = 0; STBSP__NOTUSED(dp); goto scopy; #else case 'A': // hex float case 'a': // hex float h = (f[0] == 'A') ? hexu : hex; fv = va_arg(va, double); if (pr == -1) pr = 6; // default is 6 // read the double into a string if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) fl |= STBSP__NEGATIVE; s = num + 64; stbsp__lead_sign(fl, lead); if (dp == -1023) dp = (n64) ? -1022 : 0; else n64 |= (((stbsp__uint64)1) << 52); n64 <<= (64 - 56); if (pr < 15) n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); // add leading chars #ifdef STB_SPRINTF_MSVC_MODE *s++ = '0'; *s++ = 'x'; #else lead[1 + lead[0]] = '0'; lead[2 + lead[0]] = 'x'; lead[0] += 2; #endif *s++ = h[(n64 >> 60) & 15]; n64 <<= 4; if (pr) *s++ = stbsp__period; sn = s; // print the bits n = pr; if (n > 13) n = 13; if (pr > (stbsp__int32)n) tz = pr - n; pr = 0; while (n--) { *s++ = h[(n64 >> 60) & 15]; n64 <<= 4; } // print the expo tail[1] = h[17]; if (dp < 0) { tail[2] = '-'; dp = -dp; } else tail[2] = '+'; n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); tail[0] = (char)n; for (;;) { tail[n] = '0' + dp % 10; if (n <= 3) break; --n; dp /= 10; } dp = (int)(s - sn); l = (int)(s - (num + 64)); s = num + 64; cs = 1 + (3 << 24); goto scopy; case 'G': // float case 'g': // float h = (f[0] == 'G') ? hexu : hex; fv = va_arg(va, double); if (pr == -1) pr = 6; else if (pr == 0) pr = 1; // default is 6 // read the double into a string if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) fl |= STBSP__NEGATIVE; // clamp the precision and delete extra zeros after clamp n = pr; if (l > (stbsp__uint32)pr) l = pr; while ((l > 1) && (pr) && (sn[l - 1] == '0')) { --pr; --l; } // should we use %e if ((dp <= -4) || (dp > (stbsp__int32)n)) { if (pr > (stbsp__int32)l) pr = l - 1; else if (pr) --pr; // when using %e, there is one digit before the decimal goto doexpfromg; } // this is the insane action to get the pr to match %g semantics for %f if (dp > 0) { pr = (dp < (stbsp__int32)l) ? l - dp : 0; } else { pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr); } goto dofloatfromg; case 'E': // float case 'e': // float h = (f[0] == 'E') ? hexu : hex; fv = va_arg(va, double); if (pr == -1) pr = 6; // default is 6 // read the double into a string if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) fl |= STBSP__NEGATIVE; doexpfromg: tail[0] = 0; stbsp__lead_sign(fl, lead); if (dp == STBSP__SPECIAL) { s = (char *)sn; cs = 0; pr = 0; goto scopy; } s = num + 64; // handle leading chars *s++ = sn[0]; if (pr) *s++ = stbsp__period; // handle after decimal if ((l - 1) > (stbsp__uint32)pr) l = pr + 1; for (n = 1; n < l; n++) *s++ = sn[n]; // trailing zeros tz = pr - (l - 1); pr = 0; // dump expo tail[1] = h[0xe]; dp -= 1; if (dp < 0) { tail[2] = '-'; dp = -dp; } else tail[2] = '+'; #ifdef STB_SPRINTF_MSVC_MODE n = 5; #else n = (dp >= 100) ? 5 : 4; #endif tail[0] = (char)n; for (;;) { tail[n] = '0' + dp % 10; if (n <= 3) break; --n; dp /= 10; } cs = 1 + (3 << 24); // how many tens goto flt_lead; case 'f': // float fv = va_arg(va, double); doafloat: // do kilos if (fl & STBSP__METRIC_SUFFIX) { double divisor; divisor = 1000.0f; if (fl & STBSP__METRIC_1024) divisor = 1024.0; while (fl < 0x4000000) { if ((fv < divisor) && (fv > -divisor)) break; fv /= divisor; fl += 0x1000000; } } if (pr == -1) pr = 6; // default is 6 // read the double into a string if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) fl |= STBSP__NEGATIVE; dofloatfromg: tail[0] = 0; stbsp__lead_sign(fl, lead); if (dp == STBSP__SPECIAL) { s = (char *)sn; cs = 0; pr = 0; goto scopy; } s = num + 64; // handle the three decimal varieties if (dp <= 0) { stbsp__int32 i; // handle 0.000*000xxxx *s++ = '0'; if (pr) *s++ = stbsp__period; n = -dp; if ((stbsp__int32)n > pr) n = pr; i = n; while (i) { if ((((stbsp__uintptr)s) & 3) == 0) break; *s++ = '0'; --i; } while (i >= 4) { *(stbsp__uint32 *)s = 0x30303030; s += 4; i -= 4; } while (i) { *s++ = '0'; --i; } if ((stbsp__int32)(l + n) > pr) l = pr - n; i = l; while (i) { *s++ = *sn++; --i; } tz = pr - (n + l); cs = 1 + (3 << 24); // how many tens did we write (for commas below) } else { cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; if ((stbsp__uint32)dp >= l) { // handle xxxx000*000.0 n = 0; for (;;) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { cs = 0; *s++ = stbsp__comma; } else { *s++ = sn[n]; ++n; if (n >= l) break; } } if (n < (stbsp__uint32)dp) { n = dp - n; if ((fl & STBSP__TRIPLET_COMMA) == 0) { while (n) { if ((((stbsp__uintptr)s) & 3) == 0) break; *s++ = '0'; --n; } while (n >= 4) { *(stbsp__uint32 *)s = 0x30303030; s += 4; n -= 4; } } while (n) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { cs = 0; *s++ = stbsp__comma; } else { *s++ = '0'; --n; } } } cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens if (pr) { *s++ = stbsp__period; tz = pr; } } else { // handle xxxxx.xxxx000*000 n = 0; for (;;) { if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { cs = 0; *s++ = stbsp__comma; } else { *s++ = sn[n]; ++n; if (n >= (stbsp__uint32)dp) break; } } cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens if (pr) *s++ = stbsp__period; if ((l - dp) > (stbsp__uint32)pr) l = pr + dp; while (n < l) { *s++ = sn[n]; ++n; } tz = pr - (l - dp); } } pr = 0; // handle k,m,g,t if (fl & STBSP__METRIC_SUFFIX) { char idx; idx = 1; if (fl & STBSP__METRIC_NOSPACE) idx = 0; tail[0] = idx; tail[1] = ' '; { if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. if (fl & STBSP__METRIC_1024) tail[idx + 1] = "_KMGT"[fl >> 24]; else tail[idx + 1] = "_kMGT"[fl >> 24]; idx++; // If printing kibits and not in jedec, add the 'i'. if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { tail[idx + 1] = 'i'; idx++; } tail[0] = idx; } } }; flt_lead: // get the length that we copied l = (stbsp__uint32)(s - (num + 64)); s = num + 64; goto scopy; #endif case 'B': // upper binary case 'b': // lower binary h = (f[0] == 'B') ? hexu : hex; lead[0] = 0; if (fl & STBSP__LEADING_0X) { lead[0] = 2; lead[1] = '0'; lead[2] = h[0xb]; } l = (8 << 4) | (1 << 8); goto radixnum; case 'o': // octal h = hexu; lead[0] = 0; if (fl & STBSP__LEADING_0X) { lead[0] = 1; lead[1] = '0'; } l = (3 << 4) | (3 << 8); goto radixnum; case 'p': // pointer fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; pr = sizeof(void *) * 2; fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros // fall through - to X case 'X': // upper hex case 'x': // lower hex h = (f[0] == 'X') ? hexu : hex; l = (4 << 4) | (4 << 8); lead[0] = 0; if (fl & STBSP__LEADING_0X) { lead[0] = 2; lead[1] = '0'; lead[2] = h[16]; } radixnum: // get the number if (fl & STBSP__INTMAX) n64 = va_arg(va, stbsp__uint64); else n64 = va_arg(va, stbsp__uint32); s = num + STBSP__NUMSZ; dp = 0; // clear tail, and clear leading if value is zero tail[0] = 0; if (n64 == 0) { lead[0] = 0; if (pr == 0) { l = 0; cs = 0; goto scopy; } } // convert to string for (;;) { *--s = h[n64 & ((1 << (l >> 8)) - 1)]; n64 >>= (l >> 8); if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) break; if (fl & STBSP__TRIPLET_COMMA) { ++l; if ((l & 15) == ((l >> 4) & 15)) { l &= ~15; *--s = stbsp__comma; } } }; // get the tens and the comma pos cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); // get the length that we copied l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); // copy it goto scopy; case 'u': // unsigned case 'i': case 'd': // integer // get the integer and abs it if (fl & STBSP__INTMAX) { stbsp__int64 i64 = va_arg(va, stbsp__int64); n64 = (stbsp__uint64)i64; if ((f[0] != 'u') && (i64 < 0)) { n64 = (stbsp__uint64)-i64; fl |= STBSP__NEGATIVE; } } else { stbsp__int32 i = va_arg(va, stbsp__int32); n64 = (stbsp__uint32)i; if ((f[0] != 'u') && (i < 0)) { n64 = (stbsp__uint32)-i; fl |= STBSP__NEGATIVE; } } #ifndef STB_SPRINTF_NOFLOAT if (fl & STBSP__METRIC_SUFFIX) { if (n64 < 1024) pr = 0; else if (pr == -1) pr = 1; fv = (double)(stbsp__int64)n64; goto doafloat; } #endif // convert to string s = num + STBSP__NUMSZ; l = 0; for (;;) { // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) char *o = s - 8; if (n64 >= 100000000) { n = (stbsp__uint32)(n64 % 100000000); n64 /= 100000000; } else { n = (stbsp__uint32)n64; n64 = 0; } if ((fl & STBSP__TRIPLET_COMMA) == 0) { do { s -= 2; *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; n /= 100; } while (n); } while (n) { if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { l = 0; *--s = stbsp__comma; --o; } else { *--s = (char)(n % 10) + '0'; n /= 10; } } if (n64 == 0) { if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) ++s; break; } while (s != o) if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { l = 0; *--s = stbsp__comma; --o; } else { *--s = '0'; } } tail[0] = 0; stbsp__lead_sign(fl, lead); // get the length that we copied l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); if (l == 0) { *--s = '0'; l = 1; } cs = l + (3 << 24); if (pr < 0) pr = 0; scopy: // get fw=leading/trailing space, pr=leading zeros if (pr < (stbsp__int32)l) pr = l; n = pr + lead[0] + tail[0] + tz; if (fw < (stbsp__int32)n) fw = n; fw -= n; pr -= l; // handle right justify and leading zeros if ((fl & STBSP__LEFTJUST) == 0) { if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr { pr = (fw > pr) ? fw : pr; fw = 0; } else { fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas } } // copy the spaces and/or zeros if (fw + pr) { stbsp__int32 i; stbsp__uint32 c; // copy leading spaces (or when doing %8.4d stuff) if ((fl & STBSP__LEFTJUST) == 0) while (fw > 0) { stbsp__cb_buf_clamp(i, fw); fw -= i; while (i) { if ((((stbsp__uintptr)bf) & 3) == 0) break; *bf++ = ' '; --i; } while (i >= 4) { *(stbsp__uint32 *)bf = 0x20202020; bf += 4; i -= 4; } while (i) { *bf++ = ' '; --i; } stbsp__chk_cb_buf(1); } // copy leader sn = lead + 1; while (lead[0]) { stbsp__cb_buf_clamp(i, lead[0]); lead[0] -= (char)i; while (i) { *bf++ = *sn++; --i; } stbsp__chk_cb_buf(1); } // copy leading zeros c = cs >> 24; cs &= 0xffffff; cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; while (pr > 0) { stbsp__cb_buf_clamp(i, pr); pr -= i; if ((fl & STBSP__TRIPLET_COMMA) == 0) { while (i) { if ((((stbsp__uintptr)bf) & 3) == 0) break; *bf++ = '0'; --i; } while (i >= 4) { *(stbsp__uint32 *)bf = 0x30303030; bf += 4; i -= 4; } } while (i) { if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { cs = 0; *bf++ = stbsp__comma; } else *bf++ = '0'; --i; } stbsp__chk_cb_buf(1); } } // copy leader if there is still one sn = lead + 1; while (lead[0]) { stbsp__int32 i; stbsp__cb_buf_clamp(i, lead[0]); lead[0] -= (char)i; while (i) { *bf++ = *sn++; --i; } stbsp__chk_cb_buf(1); } // copy the string n = l; while (n) { stbsp__int32 i; stbsp__cb_buf_clamp(i, n); n -= i; STBSP__UNALIGNED(while (i >= 4) { *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; bf += 4; s += 4; i -= 4; }) while (i) { *bf++ = *s++; --i; } stbsp__chk_cb_buf(1); } // copy trailing zeros while (tz) { stbsp__int32 i; stbsp__cb_buf_clamp(i, tz); tz -= i; while (i) { if ((((stbsp__uintptr)bf) & 3) == 0) break; *bf++ = '0'; --i; } while (i >= 4) { *(stbsp__uint32 *)bf = 0x30303030; bf += 4; i -= 4; } while (i) { *bf++ = '0'; --i; } stbsp__chk_cb_buf(1); } // copy tail if there is one sn = tail + 1; while (tail[0]) { stbsp__int32 i; stbsp__cb_buf_clamp(i, tail[0]); tail[0] -= (char)i; while (i) { *bf++ = *sn++; --i; } stbsp__chk_cb_buf(1); } // handle the left justify if (fl & STBSP__LEFTJUST) if (fw > 0) { while (fw) { stbsp__int32 i; stbsp__cb_buf_clamp(i, fw); fw -= i; while (i) { if ((((stbsp__uintptr)bf) & 3) == 0) break; *bf++ = ' '; --i; } while (i >= 4) { *(stbsp__uint32 *)bf = 0x20202020; bf += 4; i -= 4; } while (i--) *bf++ = ' '; stbsp__chk_cb_buf(1); } } break; default: // unknown, just copy code s = num + STBSP__NUMSZ - 1; *s = f[0]; l = 1; fw = fl = 0; lead[0] = 0; tail[0] = 0; pr = 0; dp = 0; cs = 0; goto scopy; } ++f; } endfmt: if (!callback) *bf = 0; else stbsp__flush_cb(); done: return tlen + (int)(bf - buf); } // cleanup #undef STBSP__LEFTJUST #undef STBSP__LEADINGPLUS #undef STBSP__LEADINGSPACE #undef STBSP__LEADING_0X #undef STBSP__LEADINGZERO #undef STBSP__INTMAX #undef STBSP__TRIPLET_COMMA #undef STBSP__NEGATIVE #undef STBSP__METRIC_SUFFIX #undef STBSP__NUMSZ #undef stbsp__chk_cb_bufL #undef stbsp__chk_cb_buf #undef stbsp__flush_cb #undef stbsp__cb_buf_clamp // ============================================================================ // wrapper functions STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) { int result; va_list va; va_start(va, fmt); result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); va_end(va); return result; } typedef struct stbsp__context { char *buf; int count; int length; char tmp[STB_SPRINTF_MIN]; } stbsp__context; static char *stbsp__clamp_callback(const char *buf, void *user, int len) { stbsp__context *c = (stbsp__context *)user; c->length += len; if (len > c->count) len = c->count; if (len) { if (buf != c->buf) { const char *s, *se; char *d; d = c->buf; s = buf; se = buf + len; do { *d++ = *s++; } while (s < se); } c->buf += len; c->count -= len; } if (c->count <= 0) return c->tmp; return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can } static char * stbsp__count_clamp_callback( const char * buf, void * user, int len ) { stbsp__context * c = (stbsp__context*)user; (void) sizeof(buf); c->length += len; return c->tmp; // go direct into buffer if you can } STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) { stbsp__context c; if ( (count == 0) && !buf ) { c.length = 0; STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); } else { int l; c.buf = buf; c.count = count; c.length = 0; STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); // zero-terminate l = (int)( c.buf - buf ); if ( l >= count ) // should never be greater, only equal (or less) than count l = count - 1; buf[l] = 0; } return c.length; } STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) { int result; va_list va; va_start(va, fmt); result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); va_end(va); return result; } STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) { return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); } // ======================================================================= // low level float utility functions #ifndef STB_SPRINTF_NOFLOAT // copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) #define STBSP__COPYFP(dest, src) \ { \ int cn; \ for (cn = 0; cn < 8; cn++) \ ((char *)&dest)[cn] = ((char *)&src)[cn]; \ } // get float info static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) { double d; stbsp__int64 b = 0; // load value and round at the frac_digits d = value; STBSP__COPYFP(b, d); *bits = b & ((((stbsp__uint64)1) << 52) - 1); *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); return (stbsp__int32)((stbsp__uint64) b >> 63); } static double const stbsp__bot[23] = { 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022 }; static double const stbsp__negbot[22] = { 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022 }; static double const stbsp__negboterr[22] = { -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039 }; static double const stbsp__top[13] = { 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299 }; static double const stbsp__negtop[13] = { 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299 }; static double const stbsp__toperr[13] = { 8388608, 6.8601809640529717e+028, -7.253143638152921e+052, -4.3377296974619174e+075, -1.5559416129466825e+098, -3.2841562489204913e+121, -3.7745893248228135e+144, -1.7356668416969134e+167, -3.8893577551088374e+190, -9.9566444326005119e+213, 6.3641293062232429e+236, -5.2069140800249813e+259, -5.2504760255204387e+282 }; static double const stbsp__negtoperr[13] = { 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, 8.0970921678014997e-317 }; #if defined(_MSC_VER) && (_MSC_VER <= 1200) static stbsp__uint64 const stbsp__powten[20] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000U }; #define stbsp__tento19th ((stbsp__uint64)1000000000000000000) #else static stbsp__uint64 const stbsp__powten[20] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000ULL, 100000000000ULL, 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, 10000000000000000000ULL }; #define stbsp__tento19th (1000000000000000000ULL) #endif #define stbsp__ddmulthi(oh, ol, xh, yh) \ { \ double ahi = 0, alo, bhi = 0, blo; \ stbsp__int64 bt; \ oh = xh * yh; \ STBSP__COPYFP(bt, xh); \ bt &= ((~(stbsp__uint64)0) << 27); \ STBSP__COPYFP(ahi, bt); \ alo = xh - ahi; \ STBSP__COPYFP(bt, yh); \ bt &= ((~(stbsp__uint64)0) << 27); \ STBSP__COPYFP(bhi, bt); \ blo = yh - bhi; \ ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ } #define stbsp__ddtoS64(ob, xh, xl) \ { \ double ahi = 0, alo, vh, t; \ ob = (stbsp__int64)xh; \ vh = (double)ob; \ ahi = (xh - vh); \ t = (ahi - xh); \ alo = (xh - (ahi - t)) - (vh + t); \ ob += (stbsp__int64)(ahi + alo + xl); \ } #define stbsp__ddrenorm(oh, ol) \ { \ double s; \ s = oh + ol; \ ol = ol - (s - oh); \ oh = s; \ } #define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); #define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 { double ph, pl; if ((power >= 0) && (power <= 22)) { stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); } else { stbsp__int32 e, et, eb; double p2h, p2l; e = power; if (power < 0) e = -e; et = (e * 0x2c9) >> 14; /* %23 */ if (et > 13) et = 13; eb = e - (et * 23); ph = d; pl = 0.0; if (power < 0) { if (eb) { --eb; stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); } if (et) { stbsp__ddrenorm(ph, pl); --et; stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); ph = p2h; pl = p2l; } } else { if (eb) { e = eb; if (eb > 22) eb = 22; e -= eb; stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); if (e) { stbsp__ddrenorm(ph, pl); stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); ph = p2h; pl = p2l; } } if (et) { stbsp__ddrenorm(ph, pl); --et; stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); ph = p2h; pl = p2l; } } } stbsp__ddrenorm(ph, pl); *ohi = ph; *olo = pl; } // given a float value, returns the significant bits in bits, and the position of the // decimal point in decimal_pos. +/-INF and NAN are specified by special values // returned in the decimal_pos parameter. // frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) { double d; stbsp__int64 bits = 0; stbsp__int32 expo, e, ng, tens; d = value; STBSP__COPYFP(bits, d); expo = (stbsp__int32)((bits >> 52) & 2047); ng = (stbsp__int32)((stbsp__uint64) bits >> 63); if (ng) d = -d; if (expo == 2047) // is nan or inf? { *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; *decimal_pos = STBSP__SPECIAL; *len = 3; return ng; } if (expo == 0) // is zero or denormal { if (((stbsp__uint64) bits << 1) == 0) // do zero { *decimal_pos = 1; *start = out; out[0] = '0'; *len = 1; return ng; } // find the right expo for denormals { stbsp__int64 v = ((stbsp__uint64)1) << 51; while ((bits & v) == 0) { --expo; v >>= 1; } } } // find the decimal exponent as well as the decimal bits of the value { double ph, pl; // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 tens = expo - 1023; tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); // move the significant bits into position and stick them into an int stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); // get full as much precision from double-double as possible stbsp__ddtoS64(bits, ph, pl); // check if we undershot if (((stbsp__uint64)bits) >= stbsp__tento19th) ++tens; } // now do the rounding in integer land frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); if ((frac_digits < 24)) { stbsp__uint32 dg = 1; if ((stbsp__uint64)bits >= stbsp__powten[9]) dg = 10; while ((stbsp__uint64)bits >= stbsp__powten[dg]) { ++dg; if (dg == 20) goto noround; } if (frac_digits < dg) { stbsp__uint64 r; // add 0.5 at the right position and round e = dg - frac_digits; if ((stbsp__uint32)e >= 24) goto noround; r = stbsp__powten[e]; bits = bits + (r / 2); if ((stbsp__uint64)bits >= stbsp__powten[dg]) ++tens; bits /= r; } noround:; } // kill long trailing runs of zeros if (bits) { stbsp__uint32 n; for (;;) { if (bits <= 0xffffffff) break; if (bits % 1000) goto donez; bits /= 1000; } n = (stbsp__uint32)bits; while ((n % 1000) == 0) n /= 1000; bits = n; donez:; } // convert to string out += 64; e = 0; for (;;) { stbsp__uint32 n; char *o = out - 8; // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) if (bits >= 100000000) { n = (stbsp__uint32)(bits % 100000000); bits /= 100000000; } else { n = (stbsp__uint32)bits; bits = 0; } while (n) { out -= 2; *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; n /= 100; e += 2; } if (bits == 0) { if ((e) && (out[0] == '0')) { ++out; --e; } break; } while (out != o) { *--out = '0'; ++e; } } *decimal_pos = tens; *start = out; *len = e; return ng; } #undef stbsp__ddmulthi #undef stbsp__ddrenorm #undef stbsp__ddmultlo #undef stbsp__ddmultlos #undef STBSP__SPECIAL #undef STBSP__COPYFP #endif // STB_SPRINTF_NOFLOAT // clean up #undef stbsp__uint16 #undef stbsp__uint32 #undef stbsp__int32 #undef stbsp__uint64 #undef stbsp__int64 #undef STBSP__UNALIGNED #endif // STB_SPRINTF_IMPLEMENTATION /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ ================================================ FILE: src/third_party/xxHash/LICENSE ================================================ xxHash Library Copyright (c) 2012-2021 Yann Collet All rights reserved. BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: src/third_party/xxHash/README.md ================================================ xxHash - Extremely fast hash algorithm ====================================== xxHash is an Extremely fast Hash algorithm, processing at RAM speed limits. Code is highly portable, and produces hashes identical across all platforms (little / big endian). The library includes the following algorithms : - XXH32 : generates 32-bit hashes, using 32-bit arithmetic - XXH64 : generates 64-bit hashes, using 64-bit arithmetic - XXH3 (since `v0.8.0`): generates 64 or 128-bit hashes, using vectorized arithmetic. The 128-bit variant is called XXH128. All variants successfully complete the [SMHasher](https://code.google.com/p/smhasher/wiki/SMHasher) test suite which evaluates the quality of hash functions (collision, dispersion and randomness). Additional tests, which evaluate more thoroughly speed and collision properties of 64-bit hashes, [are also provided](https://github.com/Cyan4973/xxHash/tree/dev/tests). |Branch |Status | |------------|---------| |release | [![Build Status](https://github.com/Cyan4973/xxHash/actions/workflows/ci.yml/badge.svg?branch=release)](https://github.com/Cyan4973/xxHash/actions?query=branch%3Arelease+) | |dev | [![Build Status](https://github.com/Cyan4973/xxHash/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/Cyan4973/xxHash/actions?query=branch%3Adev+) | Benchmarks ------------------------- The benchmarked reference system uses an Intel i7-9700K cpu, and runs Ubuntu x64 20.04. The [open source benchmark program] is compiled with `clang` v10.0 using `-O3` flag. | Hash Name | Width | Bandwidth (GB/s) | Small Data Velocity | Quality | Comment | | --------- | ----- | ---------------- | ----- | --- | --- | | __XXH3__ (SSE2) | 64 | 31.5 GB/s | 133.1 | 10 | __XXH128__ (SSE2) | 128 | 29.6 GB/s | 118.1 | 10 | _RAM sequential read_ | N/A | 28.0 GB/s | N/A | N/A | _for reference_ | City64 | 64 | 22.0 GB/s | 76.6 | 10 | T1ha2 | 64 | 22.0 GB/s | 99.0 | 9 | Slightly worse [collisions] | City128 | 128 | 21.7 GB/s | 57.7 | 10 | __XXH64__ | 64 | 19.4 GB/s | 71.0 | 10 | SpookyHash | 64 | 19.3 GB/s | 53.2 | 10 | Mum | 64 | 18.0 GB/s | 67.0 | 9 | Slightly worse [collisions] | __XXH32__ | 32 | 9.7 GB/s | 71.9 | 10 | City32 | 32 | 9.1 GB/s | 66.0 | 10 | Murmur3 | 32 | 3.9 GB/s | 56.1 | 10 | SipHash | 64 | 3.0 GB/s | 43.2 | 10 | FNV64 | 64 | 1.2 GB/s | 62.7 | 5 | Poor avalanche properties | Blake2 | 256 | 1.1 GB/s | 5.1 | 10 | Cryptographic | SHA1 | 160 | 0.8 GB/s | 5.6 | 10 | Cryptographic but broken | MD5 | 128 | 0.6 GB/s | 7.8 | 10 | Cryptographic but broken [open source benchmark program]: https://github.com/Cyan4973/xxHash/tree/release/tests/bench [collisions]: https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison#collision-study note 1: Small data velocity is a _rough_ evaluation of algorithm's efficiency on small data. For more detailed analysis, please refer to next paragraph. note 2: some algorithms feature _faster than RAM_ speed. In which case, they can only reach their full speed potential when input is already in CPU cache (L3 or better). Otherwise, they max out on RAM speed limit. ### Small data Performance on large data is only one part of the picture. Hashing is also very useful in constructions like hash tables and bloom filters. In these use cases, it's frequent to hash a lot of small data (starting at a few bytes). Algorithm's performance can be very different for such scenarios, since parts of the algorithm, such as initialization or finalization, become fixed cost. The impact of branch mis-prediction also becomes much more present. XXH3 has been designed for excellent performance on both long and small inputs, which can be observed in the following graph: ![XXH3, latency, random size](https://user-images.githubusercontent.com/750081/61976089-aedeab00-af9f-11e9-9239-e5375d6c080f.png) For a more detailed analysis, please visit the wiki : https://github.com/Cyan4973/xxHash/wiki/Performance-comparison#benchmarks-concentrating-on-small-data- Quality ------------------------- Speed is not the only property that matters. Produced hash values must respect excellent dispersion and randomness properties, so that any sub-section of it can be used to maximally spread out a table or index, as well as reduce the amount of collisions to the minimal theoretical level, following the [birthday paradox]. `xxHash` has been tested with Austin Appleby's excellent SMHasher test suite, and passes all tests, ensuring reasonable quality levels. It also passes extended tests from [newer forks of SMHasher], featuring additional scenarios and conditions. Finally, xxHash provides its own [massive collision tester](https://github.com/Cyan4973/xxHash/tree/dev/tests/collisions), able to generate and compare billions of hashes to test the limits of 64-bit hash algorithms. On this front too, xxHash features good results, in line with the [birthday paradox]. A more detailed analysis is documented [in the wiki](https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison). [birthday paradox]: https://en.wikipedia.org/wiki/Birthday_problem [newer forks of SMHasher]: https://github.com/rurban/smhasher ### Build modifiers The following macros can be set at compilation time to modify libxxhash's behavior. They are generally disabled by default. - `XXH_INLINE_ALL`: Make all functions `inline`, with implementations being directly included within `xxhash.h`. Inlining functions is beneficial for speed on small keys. It's _extremely effective_ when key length is expressed as _a compile time constant_, with performance improvements observed in the +200% range . See [this article](https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html) for details. - `XXH_PRIVATE_API`: same outcome as `XXH_INLINE_ALL`. Still available for legacy support. The name underlines that `XXH_*` symbol names will not be exported. - `XXH_NAMESPACE`: Prefixes all symbols with the value of `XXH_NAMESPACE`. This macro can only use compilable character set. Useful to evade symbol naming collisions, in case of multiple inclusions of xxHash's source code. Client applications still use the regular function names, as symbols are automatically translated through `xxhash.h`. - `XXH_FORCE_ALIGN_CHECK`: Use a faster direct read path when input is aligned. This option can result in dramatic performance improvement when input to hash is aligned on 32 or 64-bit boundaries, when running on architectures unable to load memory from unaligned addresses, or suffering a performance penalty from it. It is (slightly) detrimental on platform with good unaligned memory access performance (same instruction for both aligned and unaligned accesses). This option is automatically disabled on `x86`, `x64` and `aarch64`, and enabled on all other platforms. - `XXH_FORCE_MEMORY_ACCESS`: The default method `0` uses a portable `memcpy()` notation. Method `1` uses a gcc-specific `packed` attribute, which can provide better performance for some targets. Method `2` forces unaligned reads, which is not standard compliant, but might sometimes be the only way to extract better read performance. Method `3` uses a byteshift operation, which is best for old compilers which don't inline `memcpy()` or big-endian systems without a byteswap instruction. - `XXH_VECTOR` : manually select a vector instruction set (default: auto-selected at compilation time). Available instruction sets are `XXH_SCALAR`, `XXH_SSE2`, `XXH_AVX2`, `XXH_AVX512`, `XXH_NEON` and `XXH_VSX`. Compiler may require additional flags to ensure proper support (for example, `gcc` on linux will require `-mavx2` for `AVX2`, and `-mavx512f` for `AVX512`). - `XXH_NO_PREFETCH` : disable prefetching. Some platforms or situations may perform better without prefetching. XXH3 only. - `XXH_PREFETCH_DIST` : select prefetching distance. For close-to-metal adaptation to specific hardware platforms. XXH3 only. - `XXH_NO_STREAM`: Disables the streaming API, limiting it to single shot variants only. - `XXH_SIZE_OPT`: `0`: default, optimize for speed `1`: default for `-Os` and `-Oz`: disables some speed hacks for size optimization `2`: makes code as small as possible, performance may cry - `XXH_NO_INLINE_HINTS`: By default, xxHash uses `__attribute__((always_inline))` and `__forceinline` to improve performance at the cost of code size. Defining this macro to 1 will mark all internal functions as `static`, allowing the compiler to decide whether to inline a function or not. This is very useful when optimizing for smallest binary size, and is automatically defined when compiling with `-O0`, `-Os`, `-Oz`, or `-fno-inline` on GCC and Clang. This may also increase performance depending on compiler and architecture. - `XXH32_ENDJMP`: Switch multi-branch finalization stage of XXH32 by a single jump. This is generally undesirable for performance, especially when hashing inputs of random sizes. But depending on exact architecture and compiler, a jump might provide slightly better performance on small inputs. Disabled by default. - `XXH_NO_STDLIB`: Disable invocation of `` functions, notably `malloc()` and `free()`. `libxxhash`'s `XXH*_createState()` will always fail and return `NULL`. But one-shot hashing (like `XXH32()`) or streaming using statically allocated states still work as expected. This build flag is useful for embedded environments without dynamic allocation. - `XXH_STATIC_LINKING_ONLY`: gives access to internal state declaration, required for static allocation. Incompatible with dynamic linking, due to risks of ABI changes. - `XXH_NO_XXH3` : removes symbols related to `XXH3` (both 64 & 128 bits) from generated binary. Useful to reduce binary size, notably for applications which do not employ `XXH3`. - `XXH_NO_LONG_LONG`: removes compilation of algorithms relying on 64-bit types (`XXH3` and `XXH64`). Only `XXH32` will be compiled. Useful for targets (architectures and compilers) without 64-bit support. - `XXH_IMPORT`: MSVC specific: should only be defined for dynamic linking, as it prevents linkage errors. - `XXH_CPU_LITTLE_ENDIAN`: By default, endianness is determined by a runtime test resolved at compile time. If, for some reason, the compiler cannot simplify the runtime test, it can cost performance. It's possible to skip auto-detection and simply state that the architecture is little-endian by setting this macro to 1. Setting it to 0 states big-endian. - `XXH_DEBUGLEVEL` : When set to any value >= 1, enables `assert()` statements. This (slightly) slows down execution, but may help finding bugs during debugging sessions. When compiling the Command Line Interface `xxhsum` using `make`, the following environment variables can also be set : - `DISPATCH=1` : use `xxh_x86dispatch.c`, to automatically select between `scalar`, `sse2`, `avx2` or `avx512` instruction set at runtime, depending on local host. This option is only valid for `x86`/`x64` systems. - `XXH_1ST_SPEED_TARGET` : select an initial speed target, expressed in MB/s, for the first speed test in benchmark mode. Benchmark will adjust the target at subsequent iterations, but the first test is made "blindly" by targeting this speed. Currently conservatively set to 10 MB/s, to support very slow (emulated) platforms. - `NODE_JS=1` : When compiling `xxhsum` for Node.js with Emscripten, this links the `NODERAWFS` library for unrestricted filesystem access and patches `isatty` to make the command line utility correctly detect the terminal. This does make the binary specific to Node.js. ### Building xxHash - Using vcpkg You can download and install xxHash using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install xxhash The xxHash port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. ### Example The simplest example calls xxhash 64-bit variant as a one-shot function generating a hash value from a single buffer, and invoked from a C/C++ program: ```C #include "xxhash.h" (...) XXH64_hash_t hash = XXH64(buffer, size, seed); } ``` Streaming variant is more involved, but makes it possible to provide data incrementally: ```C #include "stdlib.h" /* abort() */ #include "xxhash.h" XXH64_hash_t calcul_hash_streaming(FileHandler fh) { /* create a hash state */ XXH64_state_t* const state = XXH64_createState(); if (state==NULL) abort(); size_t const bufferSize = SOME_SIZE; void* const buffer = malloc(bufferSize); if (buffer==NULL) abort(); /* Initialize state with selected seed */ XXH64_hash_t const seed = 0; /* or any other value */ if (XXH64_reset(state, seed) == XXH_ERROR) abort(); /* Feed the state with input data, any size, any number of times */ (...) while ( /* some data left */ ) { size_t const length = get_more_data(buffer, bufferSize, fh); if (XXH64_update(state, buffer, length) == XXH_ERROR) abort(); (...) } (...) /* Produce the final hash value */ XXH64_hash_t const hash = XXH64_digest(state); /* State could be re-used; but in this example, it is simply freed */ free(buffer); XXH64_freeState(state); return hash; } ``` ### License The library files `xxhash.c` and `xxhash.h` are BSD licensed. The utility `xxhsum` is GPL licensed. ### Other programming languages Beyond the C reference version, xxHash is also available from many different programming languages, thanks to great contributors. They are [listed here](http://www.xxhash.com/#other-languages). ### Packaging status Many distributions bundle a package manager which allows easy xxhash installation as both a `libxxhash` library and `xxhsum` command line interface. [![Packaging status](https://repology.org/badge/vertical-allrepos/xxhash.svg)](https://repology.org/project/xxhash/versions) ### Special Thanks - Takayuki Matsuoka, aka @t-mat, for creating `xxhsum -c` and great support during early xxh releases - Mathias Westerdahl, aka @JCash, for introducing the first version of `XXH64` - Devin Hussey, aka @easyaspi314, for incredible low-level optimizations on `XXH3` and `XXH128` ================================================ FILE: src/third_party/xxHash/SECURITY.md ================================================ # Security Policy ## Supported Versions Security updates are applied only to the latest release. ## Reporting a Vulnerability If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. Please disclose it at [security advisory](https://github.com/Cyan4973/xxHash/security/advisories/new). This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. ================================================ FILE: src/third_party/xxHash/doc/README.md ================================================ xxHash Specification ======================= This directory contains material defining the xxHash algorithm. It's described in [this specification document](xxhash_spec.md). The algorithm is also be illustrated by a [simple educational library](https://github.com/easyaspi314/xxhash-clean), written by @easyaspi314 and designed for readability (as opposed to the reference library which is designed for speed). ================================================ FILE: src/third_party/xxHash/doc/xxhash.cry ================================================ module xxhash where /** * The 32-bit variant of xxHash. The first argument is the sequence * of L bytes to hash. The second argument is a seed value. */ XXH32 : {L} (fin L) => [L][8] -> [32] -> [32] XXH32 input seed = XXH32_avalanche acc1 where (stripes16 # stripes4 # stripes1) = input accR = foldl XXH32_rounds (XXH32_init seed) (split stripes16 : [L/16][16][8]) accL = `(L % 2^^32) + if (`L:Integer) < 16 then seed + PRIME32_5 else XXH32_converge accR acc4 = foldl XXH32_digest4 accL (split stripes4 : [(L%16)/4][4][8]) acc1 = foldl XXH32_digest1 acc4 (stripes1 : [L%4][8]) /** * The 64-bit variant of xxHash. The first argument is the sequence * of L bytes to hash. The second argument is a seed value. */ XXH64 : {L} (fin L) => [L][8] -> [64] -> [64] XXH64 input seed = XXH64_avalanche acc1 where (stripes32 # stripes8 # stripes4 # stripes1) = input accR = foldl XXH64_rounds (XXH64_init seed) (split stripes32 : [L/32][32][8]) accL = `(L % 2^^64) + if (`L:Integer) < 32 then seed + PRIME64_5 else XXH64_converge accR acc8 = foldl XXH64_digest8 accL (split stripes8 : [(L%32)/8][8][8]) acc4 = foldl XXH64_digest4 acc8 (split stripes4 : [(L%8)/4][4][8]) acc1 = foldl XXH64_digest1 acc4 (stripes1 : [L%4][8]) private //Utility functions /** * Combines a sequence of bytes into a word using the little-endian * convention. */ toLE bytes = join (reverse bytes) //32-bit xxHash helper functions //32-bit prime number constants PRIME32_1 = 0x9E3779B1 : [32] PRIME32_2 = 0x85EBCA77 : [32] PRIME32_3 = 0xC2B2AE3D : [32] PRIME32_4 = 0x27D4EB2F : [32] PRIME32_5 = 0x165667B1 : [32] /** * The property shows that the hexadecimal representation of the * PRIME32 constants is the same as the binary representation. */ property PRIME32s_as_bits_correct = (PRIME32_1 == 0b10011110001101110111100110110001) /\ (PRIME32_2 == 0b10000101111010111100101001110111) /\ (PRIME32_3 == 0b11000010101100101010111000111101) /\ (PRIME32_4 == 0b00100111110101001110101100101111) /\ (PRIME32_5 == 0b00010110010101100110011110110001) /** * This function initializes the four internal accumulators of XXH32. */ XXH32_init : [32] -> [4][32] XXH32_init seed = [acc1, acc2, acc3, acc4] where acc1 = seed + PRIME32_1 + PRIME32_2 acc2 = seed + PRIME32_2 acc3 = seed + 0 acc4 = seed - PRIME32_1 /** * This processes a single lane of the main round function of XXH32. */ XXH32_round : [32] -> [32] -> [32] XXH32_round accN laneN = ((accN + laneN * PRIME32_2) <<< 13) * PRIME32_1 /** * This is the main round function of XXH32 and processes a stripe, * i.e. 4 lanes with 4 bytes each. */ XXH32_rounds : [4][32] -> [16][8] -> [4][32] XXH32_rounds accs stripe = [ XXH32_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ] /** * This function combines the four lane accumulators into a single * 32-bit value. */ XXH32_converge : [4][32] -> [32] XXH32_converge [acc1, acc2, acc3, acc4] = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18) /** * This function digests a four byte lane */ XXH32_digest4 : [32] -> [4][8] -> [32] XXH32_digest4 acc lane = ((acc + toLE lane * PRIME32_3) <<< 17) * PRIME32_4 /** * This function digests a single byte lane */ XXH32_digest1 : [32] -> [8] -> [32] XXH32_digest1 acc lane = ((acc + (0 # lane) * PRIME32_5) <<< 11) * PRIME32_1 /** * This function ensures that all input bits have a chance to impact * any bit in the output digest, resulting in an unbiased * distribution. */ XXH32_avalanche : [32] -> [32] XXH32_avalanche acc0 = acc5 where acc1 = acc0 ^ (acc0 >> 15) acc2 = acc1 * PRIME32_2 acc3 = acc2 ^ (acc2 >> 13) acc4 = acc3 * PRIME32_3 acc5 = acc4 ^ (acc4 >> 16) //64-bit xxHash helper functions //64-bit prime number constants PRIME64_1 = 0x9E3779B185EBCA87 : [64] PRIME64_2 = 0xC2B2AE3D27D4EB4F : [64] PRIME64_3 = 0x165667B19E3779F9 : [64] PRIME64_4 = 0x85EBCA77C2B2AE63 : [64] PRIME64_5 = 0x27D4EB2F165667C5 : [64] /** * The property shows that the hexadecimal representation of the * PRIME64 constants is the same as the binary representation. */ property PRIME64s_as_bits_correct = (PRIME64_1 == 0b1001111000110111011110011011000110000101111010111100101010000111) /\ (PRIME64_2 == 0b1100001010110010101011100011110100100111110101001110101101001111) /\ (PRIME64_3 == 0b0001011001010110011001111011000110011110001101110111100111111001) /\ (PRIME64_4 == 0b1000010111101011110010100111011111000010101100101010111001100011) /\ (PRIME64_5 == 0b0010011111010100111010110010111100010110010101100110011111000101) /** * This function initializes the four internal accumulators of XXH64. */ XXH64_init : [64] -> [4][64] XXH64_init seed = [acc1, acc2, acc3, acc4] where acc1 = seed + PRIME64_1 + PRIME64_2 acc2 = seed + PRIME64_2 acc3 = seed + 0 acc4 = seed - PRIME64_1 /** * This processes a single lane of the main round function of XXH64. */ XXH64_round : [64] -> [64] -> [64] XXH64_round accN laneN = ((accN + laneN * PRIME64_2) <<< 31) * PRIME64_1 /** * This is the main round function of XXH64 and processes a stripe, * i.e. 4 lanes with 8 bytes each. */ XXH64_rounds : [4][64] -> [32][8] -> [4][64] XXH64_rounds accs stripe = [ XXH64_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ] /** * This is a helper function, used to merge the four lane accumulators. */ mergeAccumulator : [64] -> [64] -> [64] mergeAccumulator acc accN = (acc ^ XXH64_round 0 accN) * PRIME64_1 + PRIME64_4 /** * This function combines the four lane accumulators into a single * 64-bit value. */ XXH64_converge : [4][64] -> [64] XXH64_converge [acc1, acc2, acc3, acc4] = foldl mergeAccumulator ((acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18)) [acc1, acc2, acc3, acc4] /** * This function digests an eight byte lane */ XXH64_digest8 : [64] -> [8][8] -> [64] XXH64_digest8 acc lane = ((acc ^ XXH64_round 0 (toLE lane)) <<< 27) * PRIME64_1 + PRIME64_4 /** * This function digests a four byte lane */ XXH64_digest4 : [64] -> [4][8] -> [64] XXH64_digest4 acc lane = ((acc ^ (0 # toLE lane) * PRIME64_1) <<< 23) * PRIME64_2 + PRIME64_3 /** * This function digests a single byte lane */ XXH64_digest1 : [64] -> [8] -> [64] XXH64_digest1 acc lane = ((acc ^ (0 # lane) * PRIME64_5) <<< 11) * PRIME64_1 /** * This function ensures that all input bits have a chance to impact * any bit in the output digest, resulting in an unbiased * distribution. */ XXH64_avalanche : [64] -> [64] XXH64_avalanche acc0 = acc5 where acc1 = acc0 ^ (acc0 >> 33) acc2 = acc1 * PRIME64_2 acc3 = acc2 ^ (acc2 >> 29) acc4 = acc3 * PRIME64_3 acc5 = acc4 ^ (acc4 >> 32) ================================================ FILE: src/third_party/xxHash/doc/xxhash_spec.md ================================================ xxHash fast digest algorithm ====================== ### Notices Copyright (c) Yann Collet Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. Distribution of this document is unlimited. ### Version 0.2.0 (29/06/23) Table of Contents --------------------- - [Introduction](#introduction) - [XXH32 algorithm description](#xxh32-algorithm-description) - [XXH64 algorithm description](#xxh64-algorithm-description) - [XXH3 algorithm description](#xxh3-algorithm-overview) - [Small inputs](#xxh3-algorithm-description-for-small-inputs) - [Medium inputs](#xxh3-algorithm-description-for-medium-inputs) - [Large inputs](#xxh3-algorithm-description-for-large-inputs) - [Performance considerations](#performance-considerations) - [Reference Implementation](#reference-implementation) Introduction ---------------- This document describes the xxHash digest algorithm for both 32-bit and 64-bit variants, named `XXH32` and `XXH64`. The algorithm takes an input a message of arbitrary length and an optional seed value, then produces an output of 32 or 64-bit as "fingerprint" or "digest". xxHash is primarily designed for speed. It is labeled non-cryptographic, and is not meant to avoid intentional collisions (same digest for 2 different messages), or to prevent producing a message with a predefined digest. XXH32 is designed to be fast on 32-bit machines. XXH64 is designed to be fast on 64-bit machines. Both variants produce different output. However, a given variant shall produce exactly the same output, irrespective of the cpu / os used. In particular, the result remains identical whatever the endianness and width of the cpu is. ### Operation notations All operations are performed modulo {32,64} bits. Arithmetic overflows are expected. `XXH32` uses 32-bit modular operations. `XXH64` and `XXH3` use 64-bit modular operations. When an operation ingests input or secret as multi-bytes values, it reads it using little-endian convention. - `+`: denotes modular addition - `-`: denotes modular subtraction - `*`: denotes modular multiplication - **Exception:** In `XXH3`, if it is in the form `(u128)x * (u128)y`, it denotes 64-bit by 64-bit normal multiplication into a full 128-bit result. - `X <<< s`: denotes the value obtained by circularly shifting (rotating) `X` left by `s` bit positions. - `X >> s`: denotes the value obtained by shifting `X` right by s bit positions. Upper `s` bits become `0`. - `X << s`: denotes the value obtained by shifting `X` left by s bit positions. Lower `s` bits become `0`. - `X xor Y`: denotes the bit-wise XOR of `X` and `Y` (same width). - `X | Y`: denotes the bit-wise OR of `X` and `Y` (same width). - `~X`: denotes the bit-wise negation of `X`. XXH32 Algorithm Description ------------------------------------- ### Overview We begin by supposing that we have a message of any length `L` as input, and that we wish to find its digest. Here `L` is an arbitrary nonnegative integer; `L` may be zero. The following steps are performed to compute the digest of the message. The algorithm collect and transform input in _stripes_ of 16 bytes. The transforms are stored inside 4 "accumulators", each one storing an unsigned 32-bit value. Each accumulator can be processed independently in parallel, speeding up processing for cpu with multiple execution units. The algorithm uses 32-bits addition, multiplication, rotate, shift and xor operations. Many operations require some 32-bits prime number constants, all defined below: ```c static const u32 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001 static const u32 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111 static const u32 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101 static const u32 PRIME32_4 = 0x27D4EB2FU; // 0b00100111110101001110101100101111 static const u32 PRIME32_5 = 0x165667B1U; // 0b00010110010101100110011110110001 ``` These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities. ### Step 1. Initialize internal accumulators Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`. ```c u32 acc1 = seed + PRIME32_1 + PRIME32_2; u32 acc2 = seed + PRIME32_2; u32 acc3 = seed + 0; u32 acc4 = seed - PRIME32_1; ``` #### Special case: input is less than 16 bytes When the input is too small (< 16 bytes), the algorithm will not process any stripes. Consequently, it will not make use of parallel accumulators. In this case, a simplified initialization is performed, using a single accumulator: ```c u32 acc = seed + PRIME32_5; ``` The algorithm then proceeds directly to step 4. ### Step 2. Process stripes A stripe is a contiguous segment of 16 bytes. It is evenly divided into 4 _lanes_, of 4 bytes each. The first lane is used to update accumulator 1, the second lane is used to update accumulator 2, and so on. Each lane read its associated 32-bit value using __little-endian__ convention. For each {lane, accumulator}, the update process is called a _round_, and applies the following formula: ```c accN = accN + (laneN * PRIME32_2); accN = accN <<< 13; accN = accN * PRIME32_1; ``` This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^32. Input is consumed one full stripe at a time. Step 2 is looped as many times as necessary to consume the whole input, except for the last remaining bytes which cannot form a stripe (< 16 bytes). When that happens, move to step 3. ### Step 3. Accumulator convergence All 4 lane accumulators from the previous steps are merged to produce a single remaining accumulator of the same width (32-bit). The associated formula is as follows: ```c acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18); ``` ### Step 4. Add input length The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing. ```c acc = acc + (u32)inputLength; ``` Note that, if input length is so large that it requires more than 32-bits, only the lower 32-bits are added to the accumulator. ### Step 5. Consume remaining input There may be up to 15 bytes remaining to consume from the input. The final stage will digest them according to following pseudo-code: ```c while (remainingLength >= 4) { lane = read_32bit_little_endian(input_ptr); acc = acc + lane * PRIME32_3; acc = (acc <<< 17) * PRIME32_4; input_ptr += 4; remainingLength -= 4; } while (remainingLength >= 1) { lane = read_byte(input_ptr); acc = acc + lane * PRIME32_5; acc = (acc <<< 11) * PRIME32_1; input_ptr += 1; remainingLength -= 1; } ``` This process ensures that all input bytes are present in the final mix. ### Step 6. Final mix (avalanche) The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect. ```c acc = acc xor (acc >> 15); acc = acc * PRIME32_2; acc = acc xor (acc >> 13); acc = acc * PRIME32_3; acc = acc xor (acc >> 16); ``` ### Step 7. Output The `XXH32()` function produces an unsigned 32-bit value as output. For systems which require to store and/or display the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence follows __big-endian__ convention (most significant byte first). XXH64 Algorithm Description ------------------------------------- ### Overview `XXH64`'s algorithm structure is very similar to `XXH32` one. The major difference is that `XXH64` uses 64-bit arithmetic, speeding up memory transfer for 64-bit compliant systems, but also relying on cpu capability to efficiently perform 64-bit operations. The algorithm collects and transforms input in _stripes_ of 32 bytes. The transforms are stored inside 4 "accumulators", each one storing an unsigned 64-bit value. Each accumulator can be processed independently in parallel, speeding up processing for cpu with multiple execution units. The algorithm uses 64-bit addition, multiplication, rotate, shift and xor operations. Many operations require some 64-bit prime number constants, all defined below: ```c static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111 static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111 static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001 static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011 static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101 ``` These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities. ### Step 1. Initialize internal accumulators Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`. ```c u64 acc1 = seed + PRIME64_1 + PRIME64_2; u64 acc2 = seed + PRIME64_2; u64 acc3 = seed + 0; u64 acc4 = seed - PRIME64_1; ``` #### Special case: input is less than 32 bytes When the input is too small (< 32 bytes), the algorithm will not process any stripes. Consequently, it will not make use of parallel accumulators. In this case, a simplified initialization is performed, using a single accumulator: ```c u64 acc = seed + PRIME64_5; ``` The algorithm then proceeds directly to step 4. ### Step 2. Process stripes A stripe is a contiguous segment of 32 bytes. It is evenly divided into 4 _lanes_, of 8 bytes each. The first lane is used to update accumulator 1, the second lane is used to update accumulator 2, and so on. Each lane read its associated 64-bit value using __little-endian__ convention. For each {lane, accumulator}, the update process is called a _round_, and applies the following formula: ```c round(accN,laneN): accN = accN + (laneN * PRIME64_2); accN = accN <<< 31; return accN * PRIME64_1; ``` This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^64. Input is consumed one full stripe at a time. Step 2 is looped as many times as necessary to consume the whole input, except for the last remaining bytes which cannot form a stripe (< 32 bytes). When that happens, move to step 3. ### Step 3. Accumulator convergence All 4 lane accumulators from previous steps are merged to produce a single remaining accumulator of same width (64-bit). The associated formula is as follows. Note that accumulator convergence is more complex than 32-bit variant, and requires to define another function called _mergeAccumulator()_: ```c mergeAccumulator(acc,accN): acc = acc xor round(0, accN); acc = acc * PRIME64_1; return acc + PRIME64_4; ``` which is then used in the convergence formula: ```c acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18); acc = mergeAccumulator(acc, acc1); acc = mergeAccumulator(acc, acc2); acc = mergeAccumulator(acc, acc3); acc = mergeAccumulator(acc, acc4); ``` ### Step 4. Add input length The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing. ```c acc = acc + inputLength; ``` ### Step 5. Consume remaining input There may be up to 31 bytes remaining to consume from the input. The final stage will digest them according to following pseudo-code: ```c while (remainingLength >= 8) { lane = read_64bit_little_endian(input_ptr); acc = acc xor round(0, lane); acc = (acc <<< 27) * PRIME64_1; acc = acc + PRIME64_4; input_ptr += 8; remainingLength -= 8; } if (remainingLength >= 4) { lane = read_32bit_little_endian(input_ptr); acc = acc xor (lane * PRIME64_1); acc = (acc <<< 23) * PRIME64_2; acc = acc + PRIME64_3; input_ptr += 4; remainingLength -= 4; } while (remainingLength >= 1) { lane = read_byte(input_ptr); acc = acc xor (lane * PRIME64_5); acc = (acc <<< 11) * PRIME64_1; input_ptr += 1; remainingLength -= 1; } ``` This process ensures that all input bytes are present in the final mix. ### Step 6. Final mix (avalanche) The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect. ```c acc = acc xor (acc >> 33); acc = acc * PRIME64_2; acc = acc xor (acc >> 29); acc = acc * PRIME64_3; acc = acc xor (acc >> 32); ``` ### Step 7. Output The `XXH64()` function produces an unsigned 64-bit value as output. For systems which require to store and/or display the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence follows __big-endian__ convention (most significant byte first). XXH3 Algorithm Overview ------------------------------------- XXH3 comes in two different versions: XXH3-64 and XXH3-128 (or XXH128), producing 64 and 128 bits of output, respectively. XXH3 uses different algorithms for small (0-16 bytes), medium (17-240 bytes), and large (241+ bytes) inputs. The algorithms for small and medium inputs are optimized for performance. The three algorithms are described in the following sections. Many operations require some 64-bit prime number constants, which are mostly the same constants used in XXH32 and XXH64, all defined below: ```c static const u64 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001 static const u64 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111 static const u64 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101 static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111 static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111 static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001 static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011 static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101 static const u64 PRIME_MX1 = 0x165667919E3779F9ULL; // 0b0001011001010110011001111001000110011110001101110111100111111001 static const u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; // 0b1001111110110010000111000110010100011110100110001101111100100101 ``` The `XXH3_64bits()` function produces an unsigned 64-bit value. The `XXH3_128bits()` function produces a `XXH128_hash_t` struct containing `low64` and `high64` - the lower and higher 64-bit half values of the result, respectively. For systems requiring storing and/or displaying the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence following **big-endian** convention (most significant byte first). ### Seed and Secret XXH3 provides seeded hashing by introducing two configurable constants used in the hashing process: the seed and the secret. The seed is an unsigned 64-bit value, and the secret is an array of bytes that is at least 136 bytes in size. The default seed is 0, and the default secret is the following 192-byte value: ```c static const u8 defaultSecret[192] = { 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, }; ``` The seed and the secret can be optionally specified using the `*_withSecret` and `*_withSeed` versions of the hash function. The seed and the secret cannot be specified simultaneously (`*_withSecretAndSeed` is actually `*_withSeed` for short and medium inputs <= 240 bytes, and `*_withSecret` for large inputs). When one is specified, the other one uses the default value. There is one exception though: when input is large (> 240 bytes) and a seed is given, a secret is derived from the seed value and the default secret using the following procedure: ```c deriveSecret(u64 seed): u64 derivedSecret[24] = defaultSecret[0:192]; for (i = 0; i < 12; i++) { derivedSecret[i*2] += seed; derivedSecret[i*2+1] -= seed; } return derivedSecret; // convert to u8[192] (little-endian) ``` The derivation treats the secrets as 24 64-bit values. In XXH3 algorithms, the secret is always read similarly by treating a contiguous segment of the array as one or more 32-bit or 64-bit values. **The secret values are always read using little-endian convention**. ### Final Mixing Step (avalanche) To make sure that all input bits have a chance to impact any bit in the output digest (avalanche effect), the final step of the XXH3 algorithm is usually one of the two fixed operations that mix the bits in a 64-bit value. These operations are denoted `avalanche()` and `avalanche_XXH64()` in the following XXH3 description. ```c avalanche(u64 x): x = x xor (x >> 37); x = x * PRIME_MX1; x = x xor (x >> 32); return x; avalanche_XXH64(u64 x): x = x xor (x >> 33); x = x * PRIME64_2; x = x xor (x >> 29); x = x * PRIME64_3; x = x xor (x >> 32); return x; ``` XXH3 Algorithm Description (for small inputs) ------------------------------------- The algorithm for small inputs (0-16 bytes of input) is further divided into 4 cases: empty, 1-3 bytes, 4-8 bytes, and 9-16 bytes of input. The algorithm uses byte-swap operations. The byte-swap operation reverses the byte order in a 32-bit or 64-bit value. It is denoted `bswap32` and `bswap64` for its 32-bit and 64-bit versions, respectively. ### Empty input The hash of empty input is calculated from the seed and a segment of the secret: ```c XXH3_64_empty(): u64 secretWords[2] = secret[56:72]; return avalanche_XXH64(seed xor secretWords[0] xor secretWords[1]); XXH3_128_empty(): u64 secretWords[4] = secret[64:96]; return {avalanche_XXH64(seed xor secretWords[0] xor secretWords[1]), // lower half avalanche_XXH64(seed xor secretWords[2] xor secretWords[3])}; // higher half ``` ### 1-3 bytes of input The algorithm starts from a single 32-bit value combining the input bytes and its length: ```c u32 combined = (u32)input[inputLength-1] | ((u32)inputLength << 8) | ((u32)input[0] << 16) | ((u32)input[inputLength>>1] << 24); // LSB 8 16 24 MSB // | last byte | length | first byte | middle-or-last byte | ``` Then the final output is calculated from the value and the first 8 bytes (XXH3-64) or 16 bytes (XXH3-128) of the secret to produce the final result. The secret here is read as 32-bit values instead of the usual 64-bit values. ```c XXH3_64_1to3(): u32 secretWords[2] = secret[0:8]; u64 value = ((u64)(secretWords[0] xor secretWords[1]) + seed) xor (u64)combined; return avalanche_XXH64(value); XXH3_128_1to3(): u32 secretWords[4] = secret[0:16]; u64 low = ((u64)(secretWords[0] xor secretWords[1]) + seed) xor (u64)combined; u64 high = ((u64)(secretWords[2] xor secretWords[3]) - seed) xor (u64)(bswap32(combined) <<< 13); // note that the bswap32(combined) <<< 13 above is 32-bit rotate return {avalanche_XXH64(low), // lower half avalanche_XXH64(high)}; // higher half ``` Note that the XXH3-64 result is the lower half of XXH3-128 result. ### 4-8 bytes of input The algorithm starts from reading the first and last 4 bytes of the input as little-endian 32-bit values, and a modified seed: ```c u32 inputFirst = input[0:4]; u32 inputLast = input[inputLength-4:inputLength]; u64 modifiedSeed = seed xor ((u64)bswap32((u32)lowerHalf(seed)) << 32); ``` Again, these values are combined with a segment of the secret to produce the final value. ```c XXH3_64_4to8(): u64 secretWords[2] = secret[8:24]; u64 combined = (u64)inputLast | ((u64)inputFirst << 32); u64 value = ((secretWords[0] xor secretWords[1]) - modifiedSeed) xor combined; value = value xor (value <<< 49) xor (value <<< 24); value = value * PRIME_MX2; value = value xor ((value >> 35) + inputLength); value = value * PRIME_MX2; value = value xor (value >> 28); return value; XXH3_128_4to8(): u64 secretWords[2] = secret[16:32]; u64 combined = (u64)inputFirst | ((u64)inputLast << 32); u64 value = ((secretWords[0] xor secretWords[1]) + modifiedSeed) xor combined; u128 mulResult = (u128)value * (u128)(PRIME64_1 + (inputLength << 2)); u64 high = higherHalf(mulResult); // mulResult >> 64 u64 low = lowerHalf(mulResult); // mulResult & 0xFFFFFFFFFFFFFFFF high = high + (low << 1); low = low xor (high >> 3); low = low xor (low >> 35); low = low * PRIME_MX2; low = low xor (low >> 28); high = avalanche(high); return {low, high}; ``` ### 9-16 bytes of input The algorithm starts from reading the first and last 8 bytes of the input as little-endian 64-bit values: ```c u64 inputFirst = input[0:8]; u64 inputLast = input[inputLength-8:inputLength]; ``` Once again, these values are combined with a segment of the secret to produce the final value. ```c XXH3_64_9to16(): u64 secretWords[4] = secret[24:56]; u64 low = ((secretWords[0] xor secretWords[1]) + seed) xor inputFirst; u64 high = ((secretWords[2] xor secretWords[3]) - seed) xor inputLast; u128 mulResult = (u128)low * (u128)high; u64 value = inputLength + bswap64(low) + high + (u64)(lowerHalf(mulResult) xor higherHalf(mulResult)); return avalanche(value); XXH3_128_9to16(): u64 secretWords[4] = secret[32:64]; u64 val1 = ((secretWords[0] xor secretWords[1]) - seed) xor inputFirst xor inputLast; u64 val2 = ((secretWords[2] xor secretWords[3]) + seed) xor inputLast; u128 mulResult = (u128)val1 * (u128)PRIME64_1; u64 low = lowerHalf(mulResult) + ((u64)(inputLength - 1) << 54); u64 high = higherHalf(mulResult) + ((u64)higherHalf(val2) << 32) + (u64)lowerHalf(val2) * PRIME32_2; // the above line can also be simplified to higherHalf(mulResult) + val2 + (u64)lowerHalf(val2) * (PRIME32_2 - 1); low = low xor bswap64(high); // the following three lines are in fact a 128x64 -> 128 multiplication ({low,high} = (u128){low,high} * PRIME64_2) u128 mulResult2 = (u128)low * (u128)PRIME64_2; low = lowerHalf(mulResult2); high = higherHalf(mulResult2) + high * PRIME64_2; return {avalanche(low), // lower half avalanche(high)}; // higher half ``` XXH3 Algorithm Description (for medium inputs) ------------------------------------- This algorithm is used for medium inputs (17-240 bytes of input). Its internal hash state is stored inside 1 (XXH3-64) or 2 (XXH3-128) "accumulators", each storing an unsigned 64-bit value. ### Step 1. Initialize internal accumulators The accumulator(s) are initialized based on the input length. ```c // For XXH3-64 u64 acc = inputLength * PRIME64_1; // For XXH3-128 u64 acc[2] = {inputLength * PRIME64_1, 0}; ``` ### Step 2. Process the input This step is further divided into two cases: one for 17-128 bytes of input, and one for 129-240 bytes of input. #### Mixing operation This step uses a mixing operation that mixes a 16-byte segment of data, a 16-byte segment of secret and the seed into a 64-bit value as a building block. This operation treat the segment of data and secret as little-endian 64-bit values. ```c mixStep(u8 data[16], size secretOffset, u64 seed): u64 dataWords[2] = data[0:16]; u64 secretWords[2] = secret[secretOffset:secretOffset+16]; u128 mulResult = (u128)(dataWords[0] xor (secretWords[0] + seed)) * (u128)(dataWords[1] xor (secretWords[1] - seed)); return lowerHalf(mulResult) xor higherHalf(mulResult); ``` The mixing operation is always invoked in groups of two in XXH3-128, where two 16-byte segments of data are mixed with a 32-byte segment of secret, and the accumulators are updated accordingly. ```c mixTwoChunks(u8 data1[16], u8 data2[16], size secretOffset, u64 seed): u64 dataWords1[2] = data1[0:16]; // again, little-endian conversion u64 dataWords2[2] = data2[0:16]; acc[0] = acc[0] + mixStep(data1, secretOffset, seed); acc[1] = acc[1] + mixStep(data2, secretOffset + 16, seed); acc[0] = acc[0] xor (dataWords2[0] + dataWords2[1]); acc[1] = acc[1] xor (dataWords1[0] + dataWords1[1]); ``` The input is split into several 16-byte chunks and mixed, and the result is added to the accumulator(s). #### 17-128 bytes of input The input is read as *N* 16-byte chunks starting from the beginning and *N* chunks starting from the end, where *N* is the smallest number that these 2*N* chunks cover the whole input. These chunks are paired up and mixed, and the results are accumulated to the accumulator(s). ```c // the loop variable `i` should be signed to avoid underflow in implementation processInput_XXH3_64_17to128(): u64 numRounds = ((inputLength - 1) >> 5) + 1; for (i = numRounds - 1; i >= 0; i--) { size offsetStart = i*16; size offsetEnd = inputLength - i*16 - 16; acc += mixStep(input[offsetStart:offsetStart+16], i*32, seed); acc += mixStep(input[offsetEnd:offsetEnd+16], i*32+16, seed); } processInput_XXH3_128_17to128(): u64 numRounds = ((inputLength - 1) >> 5) + 1; for (i = numRounds - 1; i >= 0; i--) { size offsetStart = i*16; size offsetEnd = inputLength - i*16 - 16; mixTwoChunks(input[offsetStart:offsetStart+16], input[offsetEnd:offsetEnd+16], i*32, seed); } ``` #### 129-240 bytes of input The input is split into 16-byte (XXH3-64) or 32-byte (XXH3-128) chunks. The first 128 bytes are first mixed chunk by chunk, followed by an intermediate avalanche operation. Then the remaining full chunks are processed, and finally the last 16/32 bytes are treated as a chunk to process. ```c processInput_XXH3_64_129to240(): u64 numChunks = inputLength >> 4; for (i = 0; i < 8; i++) { acc += mixStep(input[i*16:i*16+16], i*16, seed); } acc = avalanche(acc); for (i = 8; i < numChunks; i++) { acc += mixStep(input[i*16:i*16+16], (i-8)*16 + 3, seed); } acc += mixStep(input[inputLength-16:inputLength], 119, seed); processInput_XXH3_128_129to240(): u64 numChunks = inputLength >> 5; for (i = 0; i < 4; i++) { mixTwoChunks(input[i*32:i*32+16], input[i*32+16:i*32+32], i*32, seed); } acc[0] = avalanche(acc[0]); acc[1] = avalanche(acc[1]); for (i = 4; i < numChunks; i++) { mixTwoChunks(input[i*32:i*32+16], input[i*32+16:i*32+32], (i-4)*32 + 3, seed); } // note that the half-chunk order and the seed is different here mixTwoChunks(input[inputLength-16:inputLength], input[inputLength-32:inputLength-16], 103, (u64)0 - seed); ``` ### Step 3. Finalization The final result is extracted from the accumulator(s). ```c XXH3_64_17to240(): return avalanche(acc); XXH3_128_17to240(): u64 low = acc[0] + acc[1]; u64 high = (acc[0] * PRIME64_1) + (acc[1] * PRIME64_4) + (((u64)inputLength - seed) * PRIME64_2); return {avalanche(low), // lower half (u64)0 - avalanche(high)}; // higher half ``` XXH3 Algorithm Description (for large inputs) ------------------------------------- This algorithm is used for inputs larger than 240 bytes. The internal hash state is stored inside 8 "accumulators", each one storing an unsigned 64-bit value. ### Step 1. Initialize internal accumulators The accumulators are initialized to fixed constants: ```c u64 acc[8] = { PRIME32_3, PRIME64_1, PRIME64_2, PRIME64_3, PRIME64_4, PRIME32_2, PRIME64_5, PRIME32_1}; ``` ### Step 2. Process blocks The input is consumed and processed one full block at a time. The size of the block depends on the length of the secret. Specifically, a block consists of several 64-byte stripes. The number of stripes per block is `floor((secretLength-64)/8)` . For the default 192-byte secret, there are 16 stripes in a block, and thus the block size is 1024 bytes. ```c secretLength = lengthInBytes(secret); // default 192; at least 136 stripesPerBlock = (secretLength-64) / 8; // default 16; at least 9 blockSize = 64 * stripesPerBlock; // default 1024; at least 576 ``` The process of processing a full block is called a *round*. It consists of the following two sub-steps: #### Step 2-1. Process stripes in the block A stripe is evenly divided into 8 lanes, of 8 bytes each. In an accumulation step, one stripe and a 64-byte contiguous segment of the secret are used to update the accumulators. Each lane reads its associated 64-bit value using little-endian convention. The accumulation step applies the following procedure: ```c accumulate(u64 stripe[8], size secretOffset): u64 secretWords[8] = secret[secretOffset:secretOffset+64]; for (i = 0; i < 8; i++) { u64 value = stripe[i] xor secretWords[i]; acc[i xor 1] = acc[i xor 1] + stripe[i]; acc[i] = acc[i] + (u64)lowerHalf(value) * (u64)higherHalf(value); // (value and 0xFFFFFFFF) * (value >> 32) } ``` The accumulation step is repeated for all stripes in a block, using different segments of the secret, starting from the first 64 bytes for the first stripe, and offset by 8 bytes for each following round: ```c round_accumulate(u8 block[blockSize]): for (n = 0; n < stripesPerBlock; n++) { u64 stripe[8] = block[n*64:n*64+64]; // 64 bytes = 8 u64s accumulate(stripe, n*8); } ``` #### Step 2-2. Scramble accumulators After the accumulation steps are finished for all stripes in the block, the accumulators are scrambled using the last 64 bytes of the secret. ```c round_scramble(): u64 secretWords[8] = secret[secretLength-64:secretLength]; for (i = 0; i < 8; i++) { acc[i] = acc[i] xor (acc[i] >> 47); acc[i] = acc[i] xor secretWords[i]; acc[i] = acc[i] * PRIME32_1; } ``` A round is thus a `round_accumulate` followed by a `round_scramble`: ```c round(u8 block[blockSize]): round_accumulate(block); round_scramble(); ``` Step 2 is looped to consume the input until there are less than or equal to `blockSize` bytes of input left. Note that we leave the last block to the next step even if it is a full block. ### Step 3. Process the last block and the last 64 bytes Accumulation steps are run for the stripes in the last block, except for the last stripe (whether it is full or not). After that, run a final accumulation step by treating the last 64 bytes as a stripe. Note that the last 64 bytes might overlap with the second-to-last block. ```c // len is the size of the last block (1 <= len <= blockSize) lastRound(u8 block[], size len, u64 lastStripe[8]): size nFullStripes = (len-1)/64; for (n = 0; n < nFullStripes; n++) { u64 stripe[8] = block[n*64:n*64+64]; accumulate(stripe, n * 8); } accumulate(lastStripe, secretLength - 71); ``` ### Step 4. Finalization In the finalization step, a merging procedure is used to extract a single 64-bit value from the accumulators, using an initial seed value and a 64-byte segment of the secret. ```c finalMerge(u64 initValue, size secretOffset): u64 secretWords[8] = secret[secretOffset:secretOffset+64]; u64 result = initValue; for (i = 0; i < 4; i++) { // 64-bit by 64-bit multiplication to 128-bit full result u128 mulResult = (u128)(acc[i*2] xor secretWords[i*2]) * (u128)(acc[i*2+1] xor secretWords[i*2+1]); result = result + (lowerHalf(mulResult) xor higherHalf(mulResult)); // (mulResult and 0xFFFFFFFFFFFFFFFF) xor (mulResult >> 64) } return avalanche(result); ``` XXH3-128 runs the merging procedure twice for the two halves of the result, using different secret segments and different initial values derived from the total input length. The XXH3-64 result is just the lower half of the XXH3-128 result. ```c XXH3_64_large(): return finalMerge((u64)inputLength * PRIME64_1, 11); XXH3_128_large(): return {finalMerge((u64)inputLength * PRIME64_1, 11), // lower half finalMerge(~((u64)inputLength * PRIME64_2), secretLength - 75)}; // higher half ``` Performance considerations ---------------------------------- The xxHash algorithms are simple and compact to implement. They provide a system independent "fingerprint" or digest of a message of arbitrary length. The algorithm allows input to be streamed and processed in multiple steps. In such case, an internal buffer is needed to ensure data is presented to the algorithm in full stripes. On 64-bit systems, the 64-bit variant `XXH64` is generally faster to compute, so it is a recommended variant, even when only 32-bit are needed. On 32-bit systems though, positions are reversed: `XXH64` performance is reduced, due to its usage of 64-bit arithmetic. `XXH32` becomes a faster variant. Finally, when vector operations are possible, `XXH3` is likely the faster variant. Reference Implementation ---------------------------------------- A reference library written in C is available at https://www.xxhash.com. The web page also links to multiple other implementations written in many different languages. It links to the [github project page](https://github.com/Cyan4973/xxHash) where an [issue board](https://github.com/Cyan4973/xxHash/issues) can be used for further public discussions on the topic. Version changes -------------------- v0.2.0: added XXH3 specification, by Adrien Wu v0.1.1: added a note on rationale for selection of constants v0.1.0: initial release ================================================ FILE: src/third_party/xxHash/xxh3.h ================================================ /* * xxHash - Extremely Fast Hash algorithm * Development source file for `xxh3` * Copyright (C) 2019-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /* * Note: This file used to host the source code of XXH3_* variants. * during the development period. * The source code is now properly integrated within xxhash.h. * * xxh3.h is no longer useful, * but it is still provided for compatibility with source code * which used to include it directly. * * Programs are now highly discouraged to include xxh3.h. * Include `xxhash.h` instead, which is the officially supported interface. * * In the future, xxh3.h will start to generate warnings, then errors, * then it will be removed from source package and from include directory. */ /* Simulate the same impact as including the old xxh3.h source file */ #define XXH_INLINE_ALL #include "xxhash.h" ================================================ FILE: src/third_party/xxHash/xxh_x86dispatch.c ================================================ /* * xxHash - Extremely Fast Hash algorithm * Copyright (C) 2020-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /*! * @file xxh_x86dispatch.c * * Automatic dispatcher code for the @ref XXH3_family on x86-based targets. * * Optional add-on. * * **Compile this file with the default flags for your target.** Do not compile * with flags like `-mavx*`, `-march=native`, or `/arch:AVX*`, there will be * an error. See @ref XXH_X86DISPATCH_ALLOW_AVX for details. * * @defgroup dispatch x86 Dispatcher * @{ */ #if defined (__cplusplus) extern "C" { #endif #if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)) # error "Dispatching is currently only supported on x86 and x86_64." #endif /*! @cond Doxygen ignores this part */ #ifndef XXH_HAS_INCLUDE # ifdef __has_include # define XXH_HAS_INCLUDE(x) __has_include(x) # else # define XXH_HAS_INCLUDE(x) 0 # endif #endif /*! @endcond */ /*! * @def XXH_X86DISPATCH_ALLOW_AVX * @brief Disables the AVX sanity check. * * xxh_x86dispatch.c is intended to be compiled for the minimum target, and * it selectively enables SSE2, AVX2, and AVX512 when it is needed. * * Compiling with options like `-mavx*`, `-march=native`, or `/arch:AVX*` * _globally_ will always enable this feature, and therefore makes it * undefined behavior to execute on any CPU without said feature. * * Even if the source code isn't directly using AVX intrinsics in a function, * the compiler can still generate AVX code from autovectorization and by * "upgrading" SSE2 intrinsics to use the VEX prefixes (a.k.a. AVX128). * * Define XXH_X86DISPATCH_ALLOW_AVX to ignore this check, * thus accepting that the produced binary will not work correctly * on any CPU with less features than the ones stated at compilation time. */ #ifdef XXH_DOXYGEN # define XXH_X86DISPATCH_ALLOW_AVX #endif #if defined(__AVX__) && !defined(XXH_X86DISPATCH_ALLOW_AVX) # error "Error: if xxh_x86dispatch.c is compiled with AVX enabled, the resulting binary will crash on sse2-only cpus !! " \ "If you nonetheless want to do that, please enable the XXH_X86DISPATCH_ALLOW_AVX build variable" #endif /*! * @def XXH_DISPATCH_SCALAR * @brief Enables/dispatching the scalar code path. * * If this is defined to 0, SSE2 support is assumed. This reduces code size * when the scalar path is not needed. * * This is automatically defined to 0 when... * - SSE2 support is enabled in the compiler * - Targeting x86_64 * - Targeting Android x86 * - Targeting macOS */ #ifndef XXH_DISPATCH_SCALAR # if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \ || defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \ || defined(__ANDROID__) || defined(__APPLE__) /* Android or macOS */ # define XXH_DISPATCH_SCALAR 0 /* disable */ # else # define XXH_DISPATCH_SCALAR 1 # endif #endif /*! * @def XXH_DISPATCH_AVX2 * @brief Enables/disables dispatching for AVX2. * * This is automatically detected if it is not defined. * - GCC 4.7 and later are known to support AVX2, but >4.9 is required for * to get the AVX2 intrinsics and typedefs without -mavx -mavx2. * - Visual Studio 2013 Update 2 and later are known to support AVX2. * - The GCC/Clang internal header `` is detected. While this is * not allowed to be included directly, it still appears in the builtin * include path and is detectable with `__has_include`. * * @see XXH_AVX2 */ #ifndef XXH_DISPATCH_AVX2 # if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \ || (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \ || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \ || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ # define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */ # else # define XXH_DISPATCH_AVX2 0 # endif #endif /* XXH_DISPATCH_AVX2 */ /*! * @def XXH_DISPATCH_AVX512 * @brief Enables/disables dispatching for AVX512. * * Automatically detected if one of the following conditions is met: * - GCC 4.9 and later are known to support AVX512. * - Visual Studio 2017 and later are known to support AVX2. * - The GCC/Clang internal header `` is detected. While this * is not allowed to be included directly, it still appears in the builtin * include path and is detectable with `__has_include`. * * @see XXH_AVX512 */ #ifndef XXH_DISPATCH_AVX512 # if (defined(__GNUC__) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \ || (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \ || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ # define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */ # else # define XXH_DISPATCH_AVX512 0 # endif #endif /* XXH_DISPATCH_AVX512 */ /*! * @def XXH_TARGET_SSE2 * @brief Allows a function to be compiled with SSE2 intrinsics. * * Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used * even with `-mno-sse2`. * * @def XXH_TARGET_AVX2 * @brief Like @ref XXH_TARGET_SSE2, but for AVX2. * * @def XXH_TARGET_AVX512 * @brief Like @ref XXH_TARGET_SSE2, but for AVX512. * */ #if defined(__GNUC__) # include /* SSE2 */ # if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 # include /* AVX2, AVX512F */ # endif # define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) # define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) # define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) #elif defined(__clang__) && defined(_MSC_VER) /* clang-cl.exe */ # include /* SSE2 */ # if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 # include /* AVX2, AVX512F */ # include # include # include # include # endif # define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) # define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) # define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) #elif defined(_MSC_VER) # include # define XXH_TARGET_SSE2 # define XXH_TARGET_AVX2 # define XXH_TARGET_AVX512 #else # error "Dispatching is currently not supported for your compiler." #endif /*! @cond Doxygen ignores this part */ #ifdef XXH_DISPATCH_DEBUG /* debug logging */ # include # define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); } #else # define XXH_debugPrint(str) ((void)0) # undef NDEBUG /* avoid redefinition */ # define NDEBUG #endif /*! @endcond */ #include #ifndef XXH_DOXYGEN #define XXH_INLINE_ALL #define XXH_X86DISPATCH #include "xxhash.h" #endif /*! @cond Doxygen ignores this part */ #ifndef XXH_HAS_ATTRIBUTE # ifdef __has_attribute # define XXH_HAS_ATTRIBUTE(...) __has_attribute(__VA_ARGS__) # else # define XXH_HAS_ATTRIBUTE(...) 0 # endif #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ #if XXH_HAS_ATTRIBUTE(constructor) # define XXH_CONSTRUCTOR __attribute__((constructor)) # define XXH_DISPATCH_MAYBE_NULL 0 #else # define XXH_CONSTRUCTOR # define XXH_DISPATCH_MAYBE_NULL 1 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * Support both AT&T and Intel dialects * * GCC doesn't convert AT&T syntax to Intel syntax, and will error out if * compiled with -masm=intel. Instead, it supports dialect switching with * curly braces: { AT&T syntax | Intel syntax } * * Clang's integrated assembler automatically converts AT&T syntax to Intel if * needed, making the dialect switching useless (it isn't even supported). * * Note: Comments are written in the inline assembly itself. */ #ifdef __clang__ # define XXH_I_ATT(intel, att) att "\n\t" #else # define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t" #endif /*! @endcond */ /*! * @private * @brief Runs CPUID. * * @param eax , ecx The parameters to pass to CPUID, %eax and %ecx respectively. * @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }` */ static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd) { #if defined(_MSC_VER) __cpuidex((int*)abcd, eax, ecx); #else xxh_u32 ebx, edx; # if defined(__i386__) && defined(__PIC__) __asm__( "# Call CPUID\n\t" "#\n\t" "# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t" "# EBX, so we use EDI instead.\n\t" XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi") XXH_I_ATT("cpuid", "cpuid" ) XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi") : "=D" (ebx), # else __asm__( "# Call CPUID\n\t" XXH_I_ATT("cpuid", "cpuid") : "=b" (ebx), # endif "+a" (eax), "+c" (ecx), "=d" (edx)); abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx; #endif } /* * Modified version of Intel's guide * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family */ #if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 /*! * @private * @brief Runs `XGETBV`. * * While the CPU may support AVX2, the operating system might not properly save * the full YMM/ZMM registers. * * xgetbv is used for detecting this: Any compliant operating system will define * a set of flags in the xcr0 register indicating how it saves the AVX registers. * * You can manually disable this flag on Windows by running, as admin: * * bcdedit.exe /set xsavedisable 1 * * and rebooting. Run the same command with 0 to re-enable it. */ static xxh_u64 XXH_xgetbv(void) { #if defined(_MSC_VER) return _xgetbv(0); /* min VS2010 SP1 compiler is required */ #else xxh_u32 xcr0_lo, xcr0_hi; __asm__( "# Call XGETBV\n\t" "#\n\t" "# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t" "# the XGETBV opcode, so we encode it by hand instead.\n\t" "# See for details.\n\t" ".byte 0x0f, 0x01, 0xd0\n\t" : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); return xcr0_lo | ((xxh_u64)xcr0_hi << 32); #endif } #endif /*! @cond Doxygen ignores this part */ #define XXH_SSE2_CPUID_MASK (1 << 26) #define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27)) #define XXH_AVX2_CPUID_MASK (1 << 5) #define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1)) #define XXH_AVX512F_CPUID_MASK (1 << 16) #define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1)) /*! @endcond */ /*! * @private * @brief Returns the best XXH3 implementation. * * Runs various CPUID/XGETBV tests to try and determine the best implementation. * * @return The best @ref XXH_VECTOR implementation. * @see XXH_VECTOR_TYPES */ static int XXH_featureTest(void) { xxh_u32 abcd[4]; xxh_u32 max_leaves; int best = XXH_SCALAR; #if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 xxh_u64 xgetbv_val; #endif #if defined(__GNUC__) && defined(__i386__) xxh_u32 cpuid_supported; __asm__( "# For the sake of ruthless backwards compatibility, check if CPUID\n\t" "# is supported in the EFLAGS on i386.\n\t" "# This is not necessary on x86_64 - CPUID is mandatory.\n\t" "# The ID flag (bit 21) in the EFLAGS register indicates support\n\t" "# for the CPUID instruction. If a software procedure can set and\n\t" "# clear this flag, the processor executing the procedure supports\n\t" "# the CPUID instruction.\n\t" "# \n\t" "#\n\t" "# Routine is from .\n\t" "# Save EFLAGS\n\t" XXH_I_ATT("pushfd", "pushfl" ) "# Store EFLAGS\n\t" XXH_I_ATT("pushfd", "pushfl" ) "# Invert the ID bit in stored EFLAGS\n\t" XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)") "# Load stored EFLAGS (with ID bit inverted)\n\t" XXH_I_ATT("popfd", "popfl" ) "# Store EFLAGS again (ID bit may or not be inverted)\n\t" XXH_I_ATT("pushfd", "pushfl" ) "# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t" XXH_I_ATT("pop eax", "popl %%eax" ) "# eax = whichever bits were changed\n\t" XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" ) "# Restore original EFLAGS\n\t" XXH_I_ATT("popfd", "popfl" ) "# eax = zero if ID bit can't be changed, else non-zero\n\t" XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" ) : "=a" (cpuid_supported) :: "cc"); if (XXH_unlikely(!cpuid_supported)) { XXH_debugPrint("CPUID support is not detected!"); return best; } #endif /* Check how many CPUID pages we have */ XXH_cpuid(0, 0, abcd); max_leaves = abcd[0]; /* Shouldn't happen on hardware, but happens on some QEMU configs. */ if (XXH_unlikely(max_leaves == 0)) { XXH_debugPrint("Max CPUID leaves == 0!"); return best; } /* Check for SSE2, OSXSAVE and xgetbv */ XXH_cpuid(1, 0, abcd); /* * Test for SSE2. The check is redundant on x86_64, but it doesn't hurt. */ if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK)) return best; XXH_debugPrint("SSE2 support detected."); best = XXH_SSE2; #if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 /* Make sure we have enough leaves */ if (XXH_unlikely(max_leaves < 7)) return best; /* Test for OSXSAVE and XGETBV */ if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK) return best; /* CPUID check for AVX features */ XXH_cpuid(7, 0, abcd); xgetbv_val = XXH_xgetbv(); #if XXH_DISPATCH_AVX2 /* Validate that AVX2 is supported by the CPU */ if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK) return best; /* Validate that the OS supports YMM registers */ if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) { XXH_debugPrint("AVX2 supported by the CPU, but not the OS."); return best; } /* AVX2 supported */ XXH_debugPrint("AVX2 support detected."); best = XXH_AVX2; #endif #if XXH_DISPATCH_AVX512 /* Check if AVX512F is supported by the CPU */ if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) { XXH_debugPrint("AVX512F not supported by CPU"); return best; } /* Validate that the OS supports ZMM registers */ if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) { XXH_debugPrint("AVX512F supported by the CPU, but not the OS."); return best; } /* AVX512F supported */ XXH_debugPrint("AVX512F support detected."); best = XXH_AVX512; #endif #endif return best; } /* === Vector implementations === */ /*! @cond PRIVATE */ /*! * @private * @brief Defines the various dispatch functions. * * TODO: Consolidate? * * @param suffix The suffix for the functions, e.g. sse2 or scalar * @param target XXH_TARGET_* or empty. */ #define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \ \ /* === XXH3, default variants === */ \ \ XXH_NO_INLINE target XXH64_hash_t \ XXHL64_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ size_t len) \ { \ return XXH3_hashLong_64b_internal( \ input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ ); \ } \ \ /* === XXH3, Seeded variants === */ \ \ XXH_NO_INLINE target XXH64_hash_t \ XXHL64_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len, \ XXH64_hash_t seed) \ { \ return XXH3_hashLong_64b_withSeed_internal( \ input, len, seed, XXH3_accumulate_##suffix, \ XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \ ); \ } \ \ /* === XXH3, Secret variants === */ \ \ XXH_NO_INLINE target XXH64_hash_t \ XXHL64_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ size_t len, XXH_NOESCAPE const void* secret, \ size_t secretLen) \ { \ return XXH3_hashLong_64b_internal( \ input, len, secret, secretLen, \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ ); \ } \ \ /* === XXH3 update variants === */ \ \ XXH_NO_INLINE target XXH_errorcode \ XXH3_update_##suffix(XXH_NOESCAPE XXH3_state_t* state, \ XXH_NOESCAPE const void* input, size_t len) \ { \ return XXH3_update(state, (const xxh_u8*)input, len, \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ } \ \ /* === XXH128 default variants === */ \ \ XXH_NO_INLINE target XXH128_hash_t \ XXHL128_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ size_t len) \ { \ return XXH3_hashLong_128b_internal( \ input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ ); \ } \ \ /* === XXH128 Secret variants === */ \ \ XXH_NO_INLINE target XXH128_hash_t \ XXHL128_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ size_t len, \ XXH_NOESCAPE const void* XXH_RESTRICT secret, \ size_t secretLen) \ { \ return XXH3_hashLong_128b_internal( \ input, len, (const xxh_u8*)secret, secretLen, \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ } \ \ /* === XXH128 Seeded variants === */ \ \ XXH_NO_INLINE target XXH128_hash_t \ XXHL128_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len,\ XXH64_hash_t seed) \ { \ return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \ XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix, \ XXH3_initCustomSecret_##suffix); \ } /*! @endcond */ /* End XXH_DEFINE_DISPATCH_FUNCS */ /*! @cond Doxygen ignores this part */ #if XXH_DISPATCH_SCALAR XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */) #endif XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2) #if XXH_DISPATCH_AVX2 XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2) #endif #if XXH_DISPATCH_AVX512 XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512) #endif #undef XXH_DEFINE_DISPATCH_FUNCS /*! @endcond */ /* ==== Dispatchers ==== */ /*! @cond Doxygen ignores this part */ typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t); typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH_NOESCAPE XXH3_state_t*, XXH_NOESCAPE const void*, size_t); typedef struct { XXH3_dispatchx86_hashLong64_default hashLong64_default; XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed; XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret; XXH3_dispatchx86_update update; } XXH_dispatchFunctions_s; #define XXH_NB_DISPATCHES 4 /*! @endcond */ /*! * @private * @brief Table of dispatchers for @ref XXH3_64bits(). * * @pre The indices must match @ref XXH_VECTOR_TYPE. */ static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = { #if XXH_DISPATCH_SCALAR /* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar }, #else /* Scalar */ { NULL, NULL, NULL, NULL }, #endif /* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 }, #if XXH_DISPATCH_AVX2 /* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 }, #else /* AVX2 */ { NULL, NULL, NULL, NULL }, #endif #if XXH_DISPATCH_AVX512 /* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 } #else /* AVX512 */ { NULL, NULL, NULL, NULL } #endif }; /*! * @private * @brief The selected dispatch table for @ref XXH3_64bits(). */ static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL }; /*! @cond Doxygen ignores this part */ typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); typedef struct { XXH3_dispatchx86_hashLong128_default hashLong128_default; XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed; XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret; XXH3_dispatchx86_update update; } XXH_dispatch128Functions_s; /*! @endcond */ /*! * @private * @brief Table of dispatchers for @ref XXH3_128bits(). * * @pre The indices must match @ref XXH_VECTOR_TYPE. */ static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = { #if XXH_DISPATCH_SCALAR /* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar }, #else /* Scalar */ { NULL, NULL, NULL, NULL }, #endif /* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 }, #if XXH_DISPATCH_AVX2 /* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 }, #else /* AVX2 */ { NULL, NULL, NULL, NULL }, #endif #if XXH_DISPATCH_AVX512 /* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 } #else /* AVX512 */ { NULL, NULL, NULL, NULL } #endif }; /*! * @private * @brief The selected dispatch table for @ref XXH3_64bits(). */ static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL }; /*! * @private * @brief Runs a CPUID check and sets the correct dispatch tables. */ static XXH_CONSTRUCTOR void XXH_setDispatch(void) { int vecID = XXH_featureTest(); XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1); assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512); #if !XXH_DISPATCH_SCALAR assert(vecID != XXH_SCALAR); #endif #if !XXH_DISPATCH_AVX512 assert(vecID != XXH_AVX512); #endif #if !XXH_DISPATCH_AVX2 assert(vecID != XXH_AVX2); #endif XXH_g_dispatch = XXH_kDispatch[vecID]; XXH_g_dispatch128 = XXH_kDispatch128[vecID]; } /* ==== XXH3 public functions ==== */ /*! @cond Doxygen ignores this part */ static XXH64_hash_t XXH3_hashLong_64b_defaultSecret_selection(const void* input, size_t len, XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_default == NULL) XXH_setDispatch(); return XXH_g_dispatch.hashLong64_default(input, len); } XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len) { return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection); } static XXH64_hash_t XXH3_hashLong_64b_withSeed_selection(const void* input, size_t len, XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) { (void)secret; (void)secretLen; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_seed == NULL) XXH_setDispatch(); return XXH_g_dispatch.hashLong64_seed(input, len, seed64); } XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection); } static XXH64_hash_t XXH3_hashLong_64b_withSecret_selection(const void* input, size_t len, XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) { (void)seed64; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_secret == NULL) XXH_setDispatch(); return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen); } XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) { return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection); } XXH_errorcode XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.update == NULL) XXH_setDispatch(); return XXH_g_dispatch.update(state, (const xxh_u8*)input, len); } /*! @endcond */ /* ==== XXH128 public functions ==== */ /*! @cond Doxygen ignores this part */ static XXH128_hash_t XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len, XXH64_hash_t seed64, const void* secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_default == NULL) XXH_setDispatch(); return XXH_g_dispatch128.hashLong128_default(input, len); } XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len) { return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection); } static XXH128_hash_t XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len, XXH64_hash_t seed64, const void* secret, size_t secretLen) { (void)secret; (void)secretLen; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_seed == NULL) XXH_setDispatch(); return XXH_g_dispatch128.hashLong128_seed(input, len, seed64); } XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection); } static XXH128_hash_t XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len, XXH64_hash_t seed64, const void* secret, size_t secretLen) { (void)seed64; if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_secret == NULL) XXH_setDispatch(); return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen); } XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) { return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection); } XXH_errorcode XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.update == NULL) XXH_setDispatch(); return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len); } /*! @endcond */ #if defined (__cplusplus) } #endif /*! @} */ ================================================ FILE: src/third_party/xxHash/xxh_x86dispatch.h ================================================ /* * xxHash - XXH3 Dispatcher for x86-based targets * Copyright (C) 2020-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ #ifndef XXH_X86DISPATCH_H_13563687684 #define XXH_X86DISPATCH_H_13563687684 #include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */ #if defined (__cplusplus) extern "C" { #endif XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len); XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len); XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); #if defined (__cplusplus) } #endif /* automatic replacement of XXH3 functions. * can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */ #ifndef XXH_DISPATCH_DISABLE_REPLACE # undef XXH3_64bits # define XXH3_64bits XXH3_64bits_dispatch # undef XXH3_64bits_withSeed # define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch # undef XXH3_64bits_withSecret # define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch # undef XXH3_64bits_update # define XXH3_64bits_update XXH3_64bits_update_dispatch # undef XXH128 # define XXH128 XXH3_128bits_withSeed_dispatch # undef XXH3_128bits # define XXH3_128bits XXH3_128bits_dispatch # undef XXH3_128bits_withSeed # define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch # undef XXH3_128bits_withSecret # define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch # undef XXH3_128bits_update # define XXH3_128bits_update XXH3_128bits_update_dispatch #endif /* XXH_DISPATCH_DISABLE_REPLACE */ #endif /* XXH_X86DISPATCH_H_13563687684 */ ================================================ FILE: src/third_party/xxHash/xxhash.c ================================================ /* * xxHash - Extremely Fast Hash algorithm * Copyright (C) 2012-2021 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /* * xxhash.c instantiates functions defined in xxhash.h */ #define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ #define XXH_IMPLEMENTATION /* access definitions */ #include "xxhash.h" ================================================ FILE: src/third_party/xxHash/xxhash.h ================================================ /* * xxHash - Extremely Fast Hash algorithm * Header File * Copyright (C) 2012-2023 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You can contact the author at: * - xxHash homepage: https://www.xxhash.com * - xxHash source repository: https://github.com/Cyan4973/xxHash */ /*! * @mainpage xxHash * * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed * limits. * * It is proposed in four flavors, in three families: * 1. @ref XXH32_family * - Classic 32-bit hash function. Simple, compact, and runs on almost all * 32-bit and 64-bit systems. * 2. @ref XXH64_family * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most * 64-bit systems (but _not_ 32-bit systems). * 3. @ref XXH3_family * - Modern 64-bit and 128-bit hash function family which features improved * strength and performance across the board, especially on smaller data. * It benefits greatly from SIMD and 64-bit without requiring it. * * Benchmarks * --- * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. * The open source benchmark program is compiled with clang v10.0 using -O3 flag. * * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | * | -------------------- | ------- | ----: | ---------------: | ------------------: | * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | * | RAM sequential read | | N/A | 28.0 GB/s | N/A | * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | * | City64 | | 64 | 22.0 GB/s | 76.6 | * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | * | City128 | | 128 | 21.7 GB/s | 57.7 | * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | * | XXH64() | | 64 | 19.4 GB/s | 71.0 | * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | * | Mum | | 64 | 18.0 GB/s | 67.0 | * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | * | XXH32() | | 32 | 9.7 GB/s | 71.9 | * | City32 | | 32 | 9.1 GB/s | 66.0 | * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | * | SipHash* | | 64 | 3.0 GB/s | 43.2 | * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | * | FNV64 | | 64 | 1.2 GB/s | 62.7 | * | Blake2* | | 256 | 1.1 GB/s | 5.1 | * | SHA1* | | 160 | 0.8 GB/s | 5.6 | * | MD5* | | 128 | 0.6 GB/s | 7.8 | * @note * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, * even though it is mandatory on x64. * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic * by modern standards. * - Small data velocity is a rough average of algorithm's efficiency for small * data. For more accurate information, see the wiki. * - More benchmarks and strength tests are found on the wiki: * https://github.com/Cyan4973/xxHash/wiki * * Usage * ------ * All xxHash variants use a similar API. Changing the algorithm is a trivial * substitution. * * @pre * For functions which take an input and length parameter, the following * requirements are assumed: * - The range from [`input`, `input + length`) is valid, readable memory. * - The only exception is if the `length` is `0`, `input` may be `NULL`. * - For C++, the objects must have the *TriviallyCopyable* property, as the * functions access bytes directly as if it was an array of `unsigned char`. * * @anchor single_shot_example * **Single Shot** * * These functions are stateless functions which hash a contiguous block of memory, * immediately returning the result. They are the easiest and usually the fastest * option. * * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() * * @code{.c} * #include * #include "xxhash.h" * * // Example for a function which hashes a null terminated string with XXH32(). * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) * { * // NULL pointers are only valid if the length is zero * size_t length = (string == NULL) ? 0 : strlen(string); * return XXH32(string, length, seed); * } * @endcode * * @anchor streaming_example * **Streaming** * * These groups of functions allow incremental hashing of unknown size, even * more than what would fit in a size_t. * * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() * * @code{.c} * #include * #include * #include "xxhash.h" * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). * XXH64_hash_t hashFile(FILE* f) * { * // Allocate a state struct. Do not just use malloc() or new. * XXH3_state_t* state = XXH3_createState(); * assert(state != NULL && "Out of memory!"); * // Reset the state to start a new hashing session. * XXH3_64bits_reset(state); * char buffer[4096]; * size_t count; * // Read the file in chunks * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { * // Run update() as many times as necessary to process the data * XXH3_64bits_update(state, buffer, count); * } * // Retrieve the finalized hash. This will not change the state. * XXH64_hash_t result = XXH3_64bits_digest(state); * // Free the state. Do not use free(). * XXH3_freeState(state); * return result; * } * @endcode * * @file xxhash.h * xxHash prototypes and implementation */ #if defined (__cplusplus) extern "C" { #endif /* **************************** * INLINE mode ******************************/ /*! * @defgroup public Public API * Contains details on the public xxHash functions. * @{ */ #ifdef XXH_DOXYGEN /*! * @brief Gives access to internal state declaration, required for static allocation. * * Incompatible with dynamic linking, due to risks of ABI changes. * * Usage: * @code{.c} * #define XXH_STATIC_LINKING_ONLY * #include "xxhash.h" * @endcode */ # define XXH_STATIC_LINKING_ONLY /* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ /*! * @brief Gives access to internal definitions. * * Usage: * @code{.c} * #define XXH_STATIC_LINKING_ONLY * #define XXH_IMPLEMENTATION * #include "xxhash.h" * @endcode */ # define XXH_IMPLEMENTATION /* Do not undef XXH_IMPLEMENTATION for Doxygen */ /*! * @brief Exposes the implementation and marks all functions as `inline`. * * Use these build macros to inline xxhash into the target unit. * Inlining improves performance on small inputs, especially when the length is * expressed as a compile-time constant: * * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html * * It also keeps xxHash symbols private to the unit, so they are not exported. * * Usage: * @code{.c} * #define XXH_INLINE_ALL * #include "xxhash.h" * @endcode * Do not compile and link xxhash.o as a separate object, as it is not useful. */ # define XXH_INLINE_ALL # undef XXH_INLINE_ALL /*! * @brief Exposes the implementation without marking functions as inline. */ # define XXH_PRIVATE_API # undef XXH_PRIVATE_API /*! * @brief Emulate a namespace by transparently prefixing all symbols. * * If you want to include _and expose_ xxHash functions from within your own * library, but also want to avoid symbol collisions with other libraries which * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE * (therefore, avoid empty or numeric values). * * Note that no change is required within the calling program as long as it * includes `xxhash.h`: Regular symbol names will be automatically translated * by this header. */ # define XXH_NAMESPACE /* YOUR NAME HERE */ # undef XXH_NAMESPACE #endif #if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ && !defined(XXH_INLINE_ALL_31684351384) /* this section should be traversed only once */ # define XXH_INLINE_ALL_31684351384 /* give access to the advanced API, required to compile implementations */ # undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ # define XXH_STATIC_LINKING_ONLY /* make all functions private */ # undef XXH_PUBLIC_API # if defined(__GNUC__) # define XXH_PUBLIC_API static __inline __attribute__((unused)) # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) # define XXH_PUBLIC_API static inline # elif defined(_MSC_VER) # define XXH_PUBLIC_API static __inline # else /* note: this version may generate warnings for unused static functions */ # define XXH_PUBLIC_API static # endif /* * This part deals with the special case where a unit wants to inline xxHash, * but "xxhash.h" has previously been included without XXH_INLINE_ALL, * such as part of some previously included *.h header file. * Without further action, the new include would just be ignored, * and functions would effectively _not_ be inlined (silent failure). * The following macros solve this situation by prefixing all inlined names, * avoiding naming collision with previous inclusions. */ /* Before that, we unconditionally #undef all symbols, * in case they were already defined with XXH_NAMESPACE. * They will then be redefined for XXH_INLINE_ALL */ # undef XXH_versionNumber /* XXH32 */ # undef XXH32 # undef XXH32_createState # undef XXH32_freeState # undef XXH32_reset # undef XXH32_update # undef XXH32_digest # undef XXH32_copyState # undef XXH32_canonicalFromHash # undef XXH32_hashFromCanonical /* XXH64 */ # undef XXH64 # undef XXH64_createState # undef XXH64_freeState # undef XXH64_reset # undef XXH64_update # undef XXH64_digest # undef XXH64_copyState # undef XXH64_canonicalFromHash # undef XXH64_hashFromCanonical /* XXH3_64bits */ # undef XXH3_64bits # undef XXH3_64bits_withSecret # undef XXH3_64bits_withSeed # undef XXH3_64bits_withSecretandSeed # undef XXH3_createState # undef XXH3_freeState # undef XXH3_copyState # undef XXH3_64bits_reset # undef XXH3_64bits_reset_withSeed # undef XXH3_64bits_reset_withSecret # undef XXH3_64bits_update # undef XXH3_64bits_digest # undef XXH3_generateSecret /* XXH3_128bits */ # undef XXH128 # undef XXH3_128bits # undef XXH3_128bits_withSeed # undef XXH3_128bits_withSecret # undef XXH3_128bits_reset # undef XXH3_128bits_reset_withSeed # undef XXH3_128bits_reset_withSecret # undef XXH3_128bits_reset_withSecretandSeed # undef XXH3_128bits_update # undef XXH3_128bits_digest # undef XXH128_isEqual # undef XXH128_cmp # undef XXH128_canonicalFromHash # undef XXH128_hashFromCanonical /* Finally, free the namespace itself */ # undef XXH_NAMESPACE /* employ the namespace for XXH_INLINE_ALL */ # define XXH_NAMESPACE XXH_INLINE_ /* * Some identifiers (enums, type names) are not symbols, * but they must nonetheless be renamed to avoid redeclaration. * Alternative solution: do not redeclare them. * However, this requires some #ifdefs, and has a more dispersed impact. * Meanwhile, renaming can be achieved in a single place. */ # define XXH_IPREF(Id) XXH_NAMESPACE ## Id # define XXH_OK XXH_IPREF(XXH_OK) # define XXH_ERROR XXH_IPREF(XXH_ERROR) # define XXH_errorcode XXH_IPREF(XXH_errorcode) # define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) # define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) # define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) # define XXH32_state_s XXH_IPREF(XXH32_state_s) # define XXH32_state_t XXH_IPREF(XXH32_state_t) # define XXH64_state_s XXH_IPREF(XXH64_state_s) # define XXH64_state_t XXH_IPREF(XXH64_state_t) # define XXH3_state_s XXH_IPREF(XXH3_state_s) # define XXH3_state_t XXH_IPREF(XXH3_state_t) # define XXH128_hash_t XXH_IPREF(XXH128_hash_t) /* Ensure the header is parsed again, even if it was previously included */ # undef XXHASH_H_5627135585666179 # undef XXHASH_H_STATIC_13879238742 #endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ /* **************************************************************** * Stable API *****************************************************************/ #ifndef XXHASH_H_5627135585666179 #define XXHASH_H_5627135585666179 1 /*! @brief Marks a global symbol. */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) # if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT # define XXH_PUBLIC_API __declspec(dllimport) # endif # else # define XXH_PUBLIC_API /* do nothing */ # endif #endif #ifdef XXH_NAMESPACE # define XXH_CAT(A,B) A##B # define XXH_NAME2(A,B) XXH_CAT(A,B) # define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) /* XXH32 */ # define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) # define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) # define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) # define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) # define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) # define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) # define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) # define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) # define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) /* XXH64 */ # define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) # define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) # define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) # define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) # define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) # define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) # define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) # define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) # define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) /* XXH3_64bits */ # define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) # define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) # define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) # define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) # define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) # define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) # define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) # define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) # define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) # define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) # define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) # define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) # define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) # define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) # define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) /* XXH3_128bits */ # define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) # define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) # define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) # define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) # define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) # define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) # define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) # define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) # define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) # define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) # define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) # define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) # define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) # define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) # define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) #endif /* ************************************* * Compiler specifics ***************************************/ /* specific declaration modes for Windows */ #if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) # if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) # ifdef XXH_EXPORT # define XXH_PUBLIC_API __declspec(dllexport) # elif XXH_IMPORT # define XXH_PUBLIC_API __declspec(dllimport) # endif # else # define XXH_PUBLIC_API /* do nothing */ # endif #endif #if defined (__GNUC__) # define XXH_CONSTF __attribute__((const)) # define XXH_PUREF __attribute__((pure)) # define XXH_MALLOCF __attribute__((malloc)) #else # define XXH_CONSTF /* disable */ # define XXH_PUREF # define XXH_MALLOCF #endif /* ************************************* * Version ***************************************/ #define XXH_VERSION_MAJOR 0 #define XXH_VERSION_MINOR 8 #define XXH_VERSION_RELEASE 2 /*! @brief Version number, encoded as two digits each */ #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) /*! * @brief Obtains the xxHash version. * * This is mostly useful when xxHash is compiled as a shared library, * since the returned value comes from the library, as opposed to header file. * * @return @ref XXH_VERSION_NUMBER of the invoked library. */ XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); /* **************************** * Common basic types ******************************/ #include /* size_t */ /*! * @brief Exit code for the streaming API. */ typedef enum { XXH_OK = 0, /*!< OK */ XXH_ERROR /*!< Error */ } XXH_errorcode; /*-********************************************************************** * 32-bit hash ************************************************************************/ #if defined(XXH_DOXYGEN) /* Don't show include */ /*! * @brief An unsigned 32-bit integer. * * Not necessarily defined to `uint32_t` but functionally equivalent. */ typedef uint32_t XXH32_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint32_t XXH32_hash_t; #else # include # if UINT_MAX == 0xFFFFFFFFUL typedef unsigned int XXH32_hash_t; # elif ULONG_MAX == 0xFFFFFFFFUL typedef unsigned long XXH32_hash_t; # else # error "unsupported platform: need a 32-bit type" # endif #endif /*! * @} * * @defgroup XXH32_family XXH32 family * @ingroup public * Contains functions used in the classic 32-bit xxHash algorithm. * * @note * XXH32 is useful for older platforms, with no or poor 64-bit performance. * Note that the @ref XXH3_family provides competitive speed for both 32-bit * and 64-bit systems, and offers true 64/128 bit hash results. * * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families * @see @ref XXH32_impl for implementation details * @{ */ /*! * @brief Calculates the 32-bit hash of @p input using xxHash32. * * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s * * See @ref single_shot_example "Single Shot Example" for an example. * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 32-bit seed to alter the hash's output predictably. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 32-bit hash value. * * @see * XXH64(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): * Direct equivalents for the other variants of xxHash. * @see * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version. */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); #ifndef XXH_NO_STREAM /*! * Streaming functions generate the xxHash value from an incremental input. * This method is slower than single-call functions, due to state management. * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. * * An XXH state must first be allocated using `XXH*_createState()`. * * Start a new hash by initializing the state with a seed using `XXH*_reset()`. * * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. * * The function returns an error code, with 0 meaning OK, and any other value * meaning there is an error. * * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. * This function returns the nn-bits hash as an int or long long. * * It's still possible to continue inserting input into the hash state after a * digest, and generate new hash values later on by invoking `XXH*_digest()`. * * When done, release the state using `XXH*_freeState()`. * * @see streaming_example at the top of @ref xxhash.h for an example. */ /*! * @typedef struct XXH32_state_s XXH32_state_t * @brief The opaque state struct for the XXH32 streaming API. * * @see XXH32_state_s for details. */ typedef struct XXH32_state_s XXH32_state_t; /*! * @brief Allocates an @ref XXH32_state_t. * * Must be freed with XXH32_freeState(). * @return An allocated XXH32_state_t on success, `NULL` on failure. */ XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); /*! * @brief Frees an @ref XXH32_state_t. * * Must be allocated with XXH32_createState(). * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). * @return XXH_OK. */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); /*! * @brief Copies one @ref XXH32_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); /*! * @brief Resets an @ref XXH32_state_t to begin a new hash. * * This function resets and seeds a state. Call it before @ref XXH32_update(). * * @param statePtr The state struct to reset. * @param seed The 32-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH32_state_t. * * Call this to incrementally consume blocks of data. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH32_state_t. * * @note * Calling XXH32_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated xxHash32 value from that state. */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /* * The default return values from XXH functions are unsigned 32 and 64 bit * integers. * This the simplest and fastest format for further post-processing. * * However, this leaves open the question of what is the order on the byte level, * since little and big endian conventions will store the same number differently. * * The canonical representation settles this issue by mandating big-endian * convention, the same convention as human-readable numbers (large digits first). * * When writing hash values to storage, sending them over a network, or printing * them, it's highly recommended to use the canonical representation to ensure * portability across a wider range of systems, present and future. * * The following functions allow transformation of hash values to and from * canonical format. */ /*! * @brief Canonical (big endian) representation of @ref XXH32_hash_t. */ typedef struct { unsigned char digest[4]; /*!< Hash bytes, big endian */ } XXH32_canonical_t; /*! * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. * * @param dst The @ref XXH32_canonical_t pointer to be stored to. * @param hash The @ref XXH32_hash_t to be converted. * * @pre * @p dst must not be `NULL`. */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); /*! * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. * * @param src The @ref XXH32_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. */ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); /*! @cond Doxygen ignores this part */ #ifdef __has_attribute # define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) #else # define XXH_HAS_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * C23 __STDC_VERSION__ number hasn't been specified yet. For now * leave as `201711L` (C17 + 1). * TODO: Update to correct value when its been specified. */ #define XXH_C23_VN 201711L /*! @endcond */ /*! @cond Doxygen ignores this part */ /* C-language Attributes are added in C23. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) # define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) #else # define XXH_HAS_C_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ #if defined(__cplusplus) && defined(__has_cpp_attribute) # define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else # define XXH_HAS_CPP_ATTRIBUTE(x) 0 #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute * introduced in CPP17 and C23. * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough */ #if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) # define XXH_FALLTHROUGH [[fallthrough]] #elif XXH_HAS_ATTRIBUTE(__fallthrough__) # define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) #else # define XXH_FALLTHROUGH /* fallthrough */ #endif /*! @endcond */ /*! @cond Doxygen ignores this part */ /* * Define XXH_NOESCAPE for annotated pointers in public API. * https://clang.llvm.org/docs/AttributeReference.html#noescape * As of writing this, only supported by clang. */ #if XXH_HAS_ATTRIBUTE(noescape) # define XXH_NOESCAPE __attribute__((noescape)) #else # define XXH_NOESCAPE #endif /*! @endcond */ /*! * @} * @ingroup public * @{ */ #ifndef XXH_NO_LONG_LONG /*-********************************************************************** * 64-bit hash ************************************************************************/ #if defined(XXH_DOXYGEN) /* don't include */ /*! * @brief An unsigned 64-bit integer. * * Not necessarily defined to `uint64_t` but functionally equivalent. */ typedef uint64_t XXH64_hash_t; #elif !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint64_t XXH64_hash_t; #else # include # if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL /* LP64 ABI says uint64_t is unsigned long */ typedef unsigned long XXH64_hash_t; # else /* the following type must have a width of 64-bit */ typedef unsigned long long XXH64_hash_t; # endif #endif /*! * @} * * @defgroup XXH64_family XXH64 family * @ingroup public * @{ * Contains functions used in the classic 64-bit xxHash algorithm. * * @note * XXH3 provides competitive speed for both 32-bit and 64-bit systems, * and offers true 64/128 bit hash results. * It provides better speed for systems with vector processing capabilities. */ /*! * @brief Calculates the 64-bit hash of @p input using xxHash64. * * This function usually runs faster on 64-bit systems, but slower on 32-bit * systems (see benchmark). * * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * @param seed The 64-bit seed to alter the hash's output predictably. * * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return The calculated 64-bit hash. * * @see * XXH32(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): * Direct equivalents for the other variants of xxHash. * @see * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /******* Streaming *******/ #ifndef XXH_NO_STREAM /*! * @brief The opaque state struct for the XXH64 streaming API. * * @see XXH64_state_s for details. */ typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ /*! * @brief Allocates an @ref XXH64_state_t. * * Must be freed with XXH64_freeState(). * @return An allocated XXH64_state_t on success, `NULL` on failure. */ XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); /*! * @brief Frees an @ref XXH64_state_t. * * Must be allocated with XXH64_createState(). * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). * @return XXH_OK. */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); /*! * @brief Copies one @ref XXH64_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); /*! * @brief Resets an @ref XXH64_state_t to begin a new hash. * * This function resets and seeds a state. Call it before @ref XXH64_update(). * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the hash result predictably. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); /*! * @brief Consumes a block of @p input to an @ref XXH64_state_t. * * Call this to incrementally consume blocks of data. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated hash value from an @ref XXH64_state_t. * * @note * Calling XXH64_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated xxHash64 value from that state. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! * @brief Canonical (big endian) representation of @ref XXH64_hash_t. */ typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; /*! * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. * * @param dst The @ref XXH64_canonical_t pointer to be stored to. * @param hash The @ref XXH64_hash_t to be converted. * * @pre * @p dst must not be `NULL`. */ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); /*! * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. * * @param src The @ref XXH64_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); #ifndef XXH_NO_XXH3 /*! * @} * ************************************************************************ * @defgroup XXH3_family XXH3 family * @ingroup public * @{ * * XXH3 is a more recent hash algorithm featuring: * - Improved speed for both small and large inputs * - True 64-bit and 128-bit outputs * - SIMD acceleration * - Improved 32-bit viability * * Speed analysis methodology is explained here: * * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html * * Compared to XXH64, expect XXH3 to run approximately * ~2x faster on large inputs and >3x faster on small ones, * exact differences vary depending on platform. * * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, * but does not require it. * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 * at competitive speeds, even without vector support. Further details are * explained in the implementation. * * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD * implementations for many common platforms: * - AVX512 * - AVX2 * - SSE2 * - ARM NEON * - WebAssembly SIMD128 * - POWER8 VSX * - s390x ZVector * This can be controlled via the @ref XXH_VECTOR macro, but it automatically * selects the best version according to predefined macros. For the x86 family, an * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. * * XXH3 implementation is portable: * it has a generic C90 formulation that can be compiled on any platform, * all implementations generate exactly the same hash value on all platforms. * Starting from v0.8.0, it's also labelled "stable", meaning that * any future version will also generate the same hash value. * * XXH3 offers 2 variants, _64bits and _128bits. * * When only 64 bits are needed, prefer invoking the _64bits variant, as it * reduces the amount of mixing, resulting in faster speed on small inputs. * It's also generally simpler to manipulate a scalar return type than a struct. * * The API supports one-shot hashing, streaming mode, and custom secrets. */ /*-********************************************************************** * XXH3 64-bit variant ************************************************************************/ /*! * @brief 64-bit unseeded variant of XXH3. * * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of 0, however * it may have slightly better performance due to constant propagation of the * defaults. * * @see * XXH32(), XXH64(), XXH3_128bits(): equivalent for the other xxHash algorithms * @see * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants * @see * XXH3_64bits_reset(), XXH3_64bits_update(), XXH3_64bits_digest(): Streaming version. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); /*! * @brief 64-bit seeded variant of XXH3 * * This variant generates a custom secret on the fly based on default secret * altered using the `seed` value. * * While this operation is decently fast, note that it's not completely free. * * @note * seed == 0 produces the same results as @ref XXH3_64bits(). * * @param input The data to hash * @param length The length * @param seed The 64-bit seed to alter the state. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); /*! * The bare minimum size for a custom secret. * * @see * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). */ #define XXH3_SECRET_SIZE_MIN 136 /*! * @brief 64-bit variant of XXH3 with a custom "secret". * * It's possible to provide any blob of bytes as a "secret" to generate the hash. * This makes it more difficult for an external actor to prepare an intentional collision. * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN). * However, the quality of the secret impacts the dispersion of the hash algorithm. * Therefore, the secret _must_ look like a bunch of random bytes. * Avoid "trivial" or structured data such as repeated sequences or a text document. * Whenever in doubt about the "randomness" of the blob of bytes, * consider employing "XXH3_generateSecret()" instead (see below). * It will generate a proper high entropy secret derived from the blob of bytes. * Another advantage of using XXH3_generateSecret() is that * it guarantees that all bits within the initial blob of bytes * will impact every bit of the output. * This is not necessarily the case when using the blob of bytes directly * because, when hashing _small_ inputs, only a portion of the secret is employed. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ #ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. * As a consequence, streaming is slower than one-shot hashing. * For better performance, prefer one-shot functions whenever applicable. */ /*! * @brief The state struct for the XXH3 streaming API. * * @see XXH3_state_s for details. */ typedef struct XXH3_state_s XXH3_state_t; XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); /*! * @brief Copies one @ref XXH3_state_t to another. * * @param dst_state The state to copy to. * @param src_state The state to copy from. * @pre * @p dst_state and @p src_state must not be `NULL` and must not overlap. */ XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_64bits_update(). * Digest will be equivalent to `XXH3_64bits()`. * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_64bits_update(). * Digest will be equivalent to `XXH3_64bits_withSeed()`. * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the state. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. * */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); /*! * XXH3_64bits_reset_withSecret(): * `secret` is referenced, it _must outlive_ the hash streaming session. * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`, * and the quality of produced hash values depends on secret's entropy * (secret's content should look like a bunch of random bytes). * When in doubt about the randomness of a candidate `secret`, * consider employing `XXH3_generateSecret()` instead (see below). */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! * @brief Consumes a block of @p input to an @ref XXH3_state_t. * * Call this to incrementally consume blocks of data. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. * * @note * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 64-bit hash value from that state. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /* note : canonical representation of XXH3 is the same as XXH64 * since they both produce XXH64_hash_t values */ /*-********************************************************************** * XXH3 128-bit variant ************************************************************************/ /*! * @brief The return value from 128-bit hashes. * * Stored in little endian order, although the fields themselves are in native * endianness. */ typedef struct { XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ XXH64_hash_t high64; /*!< `value >> 64` */ } XXH128_hash_t; /*! * @brief Unseeded 128-bit variant of XXH3 * * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead * for shorter inputs. * * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of 0, however * it may have slightly better performance due to constant propagation of the * defaults. * * @see * XXH32(), XXH64(), XXH3_64bits(): equivalent for the other xxHash algorithms * @see * XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants * @see * XXH3_128bits_reset(), XXH3_128bits_update(), XXH3_128bits_digest(): Streaming version. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); /*! @brief Seeded 128-bit variant of XXH3. @see XXH3_64bits_withSeed(). */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); /*! @brief Custom secret 128-bit variant of XXH3. @see XXH3_64bits_withSecret(). */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); /******* Streaming *******/ #ifndef XXH_NO_STREAM /* * Streaming requires state maintenance. * This operation costs memory and CPU. * As a consequence, streaming is slower than one-shot hashing. * For better performance, prefer one-shot functions whenever applicable. * * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). * Use already declared XXH3_createState() and XXH3_freeState(). * * All reset and streaming functions have same meaning as their 64-bit counterpart. */ /*! * @brief Resets an @ref XXH3_state_t to begin a new hash. * * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_128bits_update(). * Digest will be equivalent to `XXH3_128bits()`. * * @param statePtr The state struct to reset. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. * */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); /*! * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. * * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_128bits_update(). * Digest will be equivalent to `XXH3_128bits_withSeed()`. * * @param statePtr The state struct to reset. * @param seed The 64-bit seed to alter the state. * * @pre * @p statePtr must not be `NULL`. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. * */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); /*! @brief Custom secret 128-bit variant of XXH3. @see XXH_64bits_reset_withSecret(). */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); /*! * @brief Consumes a block of @p input to an @ref XXH3_state_t. * * Call this to incrementally consume blocks of data. * * @param statePtr The state struct to update. * @param input The block of data to be hashed, at least @p length bytes in size. * @param length The length of @p input, in bytes. * * @pre * @p statePtr must not be `NULL`. * @pre * The memory between @p input and @p input + @p length must be valid, * readable, contiguous memory. However, if @p length is `0`, @p input may be * `NULL`. In C++, this also must be *TriviallyCopyable*. * * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); /*! * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. * * @note * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, * digest, and update again. * * @param statePtr The state struct to calculate the hash from. * * @pre * @p statePtr must not be `NULL`. * * @return The calculated XXH3 128-bit hash value from that state. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); #endif /* !XXH_NO_STREAM */ /* Following helper functions make it possible to compare XXH128_hast_t values. * Since XXH128_hash_t is a structure, this capability is not offered by the language. * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ /*! * XXH128_isEqual(): * Return: 1 if `h1` and `h2` are equal, 0 if they are not. */ XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); /*! * @brief Compares two @ref XXH128_hash_t * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. * * @return: >0 if *h128_1 > *h128_2 * =0 if *h128_1 == *h128_2 * <0 if *h128_1 < *h128_2 */ XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); /******* Canonical representation *******/ typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; /*! * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. * * @param dst The @ref XXH128_canonical_t pointer to be stored to. * @param hash The @ref XXH128_hash_t to be converted. * * @pre * @p dst must not be `NULL`. */ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); /*! * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. * * @param src The @ref XXH128_canonical_t to convert. * * @pre * @p src must not be `NULL`. * * @return The converted hash. */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); #endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ /*! * @} */ #endif /* XXHASH_H_5627135585666179 */ #if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) #define XXHASH_H_STATIC_13879238742 /* **************************************************************************** * This section contains declarations which are not guaranteed to remain stable. * They may change in future versions, becoming incompatible with a different * version of the library. * These declarations should only be used with static linking. * Never use them in association with dynamic linking! ***************************************************************************** */ /* * These definitions are only present to allow static allocation * of XXH states, on stack or in a struct, for example. * Never **ever** access their members directly. */ /*! * @internal * @brief Structure for XXH32 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is * an opaque type. This allows fields to safely be changed. * * Typedef'd to @ref XXH32_state_t. * Do not access the members of this struct directly. * @see XXH64_state_s, XXH3_state_s */ struct XXH32_state_s { XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ XXH32_hash_t v[4]; /*!< Accumulator lanes */ XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ }; /* typedef'd to XXH32_state_t */ #ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ /*! * @internal * @brief Structure for XXH64 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is * an opaque type. This allows fields to safely be changed. * * Typedef'd to @ref XXH64_state_t. * Do not access the members of this struct directly. * @see XXH32_state_s, XXH3_state_s */ struct XXH64_state_s { XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ XXH64_hash_t v[4]; /*!< Accumulator lanes */ XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ }; /* typedef'd to XXH64_state_t */ #ifndef XXH_NO_XXH3 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ # include # define XXH_ALIGN(n) alignas(n) #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ /* In C++ alignas() is a keyword */ # define XXH_ALIGN(n) alignas(n) #elif defined(__GNUC__) # define XXH_ALIGN(n) __attribute__ ((aligned(n))) #elif defined(_MSC_VER) # define XXH_ALIGN(n) __declspec(align(n)) #else # define XXH_ALIGN(n) /* disabled */ #endif /* Old GCC versions only accept the attribute after the type in structures. */ #if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ && defined(__GNUC__) # define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) #else # define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type #endif /*! * @brief The size of the internal XXH3 buffer. * * This is the optimal update size for incremental hashing. * * @see XXH3_64b_update(), XXH3_128b_update(). */ #define XXH3_INTERNALBUFFER_SIZE 256 /*! * @internal * @brief Default size of the secret buffer (and @ref XXH3_kSecret). * * This is the size used in @ref XXH3_kSecret and the seeded functions. * * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. */ #define XXH3_SECRET_DEFAULT_SIZE 192 /*! * @internal * @brief Structure for XXH3 streaming API. * * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. * Otherwise it is an opaque type. * Never use this definition in combination with dynamic library. * This allows fields to safely be changed in the future. * * @note ** This structure has a strict alignment requirement of 64 bytes!! ** * Do not allocate this with `malloc()` or `new`, * it will not be sufficiently aligned. * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. * * Typedef'd to @ref XXH3_state_t. * Do never access the members of this struct directly. * * @see XXH3_INITSTATE() for stack initialization. * @see XXH3_createState(), XXH3_freeState(). * @see XXH32_state_s, XXH64_state_s */ struct XXH3_state_s { XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); /*!< Used to store a custom secret generated from a seed. */ XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); /*!< The internal buffer. @see XXH32_state_s::mem32 */ XXH32_hash_t bufferedSize; /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ XXH32_hash_t useSeed; /*!< Reserved field. Needed for padding on 64-bit. */ size_t nbStripesSoFar; /*!< Number or stripes processed. */ XXH64_hash_t totalLen; /*!< Total length hashed. 64-bit even on 32-bit targets. */ size_t nbStripesPerBlock; /*!< Number of stripes per block. */ size_t secretLimit; /*!< Size of @ref customSecret or @ref extSecret */ XXH64_hash_t seed; /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ XXH64_hash_t reserved64; /*!< Reserved field. */ const unsigned char* extSecret; /*!< Reference to an external secret for the _withSecret variants, NULL * for other variants. */ /* note: there may be some padding at the end due to alignment on 64 bytes */ }; /* typedef'd to XXH3_state_t */ #undef XXH_ALIGN_MEMBER /*! * @brief Initializes a stack-allocated `XXH3_state_s`. * * When the @ref XXH3_state_t structure is merely emplaced on stack, * it should be initialized with XXH3_INITSTATE() or a memset() * in case its first reset uses XXH3_NNbits_reset_withSeed(). * This init can be omitted if the first reset uses default or _withSecret mode. * This operation isn't necessary when the state is created with XXH3_createState(). * Note that this doesn't prepare the state for a streaming operation, * it's still necessary to use XXH3_NNbits_reset*() afterwards. */ #define XXH3_INITSTATE(XXH3_state_ptr) \ do { \ XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ tmp_xxh3_state_ptr->seed = 0; \ tmp_xxh3_state_ptr->extSecret = NULL; \ } while(0) /*! * simple alias to pre-selected XXH3_128bits variant */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); /* === Experimental API === */ /* Symbols defined below must be considered tied to a specific library version. */ /*! * XXH3_generateSecret(): * * Derive a high-entropy secret from any user-defined content, named customSeed. * The generated secret can be used in combination with `*_withSecret()` functions. * The `_withSecret()` variants are useful to provide a higher level of protection * than 64-bit seed, as it becomes much more difficult for an external actor to * guess how to impact the calculation logic. * * The function accepts as input a custom seed of any length and any content, * and derives from it a high-entropy secret of length @p secretSize into an * already allocated buffer @p secretBuffer. * * The generated secret can then be used with any `*_withSecret()` variant. * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() * are part of this list. They all accept a `secret` parameter * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) * _and_ feature very high entropy (consist of random-looking bytes). * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can * be employed to ensure proper quality. * * @p customSeed can be anything. It can have any size, even small ones, * and its content can be anything, even "poor entropy" sources such as a bunch * of zeroes. The resulting `secret` will nonetheless provide all required qualities. * * @pre * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. * * Example code: * @code{.c} * #include * #include * #include * #define XXH_STATIC_LINKING_ONLY // expose unstable API * #include "xxhash.h" * // Hashes argv[2] using the entropy from argv[1]. * int main(int argc, char* argv[]) * { * char secret[XXH3_SECRET_SIZE_MIN]; * if (argv != 3) { return 1; } * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); * XXH64_hash_t h = XXH3_64bits_withSecret( * argv[2], strlen(argv[2]), * secret, sizeof(secret) * ); * printf("%016llx\n", (unsigned long long) h); * } * @endcode */ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); /*! * @brief Generate the same secret as the _withSeed() variants. * * The generated secret can be used in combination with *`*_withSecret()` and `_withSecretandSeed()` variants. * * Example C++ `std::string` hash class: * @code{.cpp} * #include * #define XXH_STATIC_LINKING_ONLY // expose unstable API * #include "xxhash.h" * // Slow, seeds each time * class HashSlow { * XXH64_hash_t seed; * public: * HashSlow(XXH64_hash_t s) : seed{s} {} * size_t operator()(const std::string& x) const { * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; * } * }; * // Fast, caches the seeded secret for future uses. * class HashFast { * unsigned char secret[XXH3_SECRET_SIZE_MIN]; * public: * HashFast(XXH64_hash_t s) { * XXH3_generateSecret_fromSeed(secret, seed); * } * size_t operator()(const std::string& x) const { * return size_t{ * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) * }; * } * }; * @endcode * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes * @param seed The seed to seed the state. */ XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); /*! * These variants generate hash values using either * @p seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes) * or @p secret for "large" keys (>= XXH3_MIDSIZE_MAX). * * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. * `_withSeed()` has to generate the secret on the fly for "large" keys. * It's fast, but can be perceptible for "not so large" keys (< 1 KB). * `_withSecret()` has to generate the masks on the fly for "small" keys, * which requires more instructions than _withSeed() variants. * Therefore, _withSecretandSeed variant combines the best of both worlds. * * When @p secret has been generated by XXH3_generateSecret_fromSeed(), * this variant produces *exactly* the same results as `_withSeed()` variant, * hence offering only a pure speed benefit on "large" input, * by skipping the need to regenerate the secret for every large input. * * Another usage scenario is to hash the secret to a 64-bit hash value, * for example with XXH3_64bits(), which then becomes the seed, * and then employ both the seed and the secret in _withSecretandSeed(). * On top of speed, an added benefit is that each bit in the secret * has a 50% chance to swap each bit in the output, via its impact to the seed. * * This is not guaranteed when using the secret directly in "small data" scenarios, * because only portions of the secret are employed for small data. */ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed); /*! @copydoc XXH3_64bits_withSecretandSeed() */ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); #ifndef XXH_NO_STREAM /*! @copydoc XXH3_64bits_withSecretandSeed() */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); /*! @copydoc XXH3_64bits_withSecretandSeed() */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64); #endif /* !XXH_NO_STREAM */ #endif /* !XXH_NO_XXH3 */ #endif /* XXH_NO_LONG_LONG */ #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) # define XXH_IMPLEMENTATION #endif #endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ /* ======================================================================== */ /* ======================================================================== */ /* ======================================================================== */ /*-********************************************************************** * xxHash implementation *-********************************************************************** * xxHash's implementation used to be hosted inside xxhash.c. * * However, inlining requires implementation to be visible to the compiler, * hence be included alongside the header. * Previously, implementation was hosted inside xxhash.c, * which was then #included when inlining was activated. * This construction created issues with a few build and install systems, * as it required xxhash.c to be stored in /include directory. * * xxHash implementation is now directly integrated within xxhash.h. * As a consequence, xxhash.c is no longer needed in /include. * * xxhash.c is still available and is still useful. * In a "normal" setup, when xxhash is not inlined, * xxhash.h only exposes the prototypes and public symbols, * while xxhash.c can be built into an object file xxhash.o * which can then be linked into the final binary. ************************************************************************/ #if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) # define XXH_IMPLEM_13a8737387 /* ************************************* * Tuning parameters ***************************************/ /*! * @defgroup tuning Tuning parameters * @{ * * Various macros to control xxHash's behavior. */ #ifdef XXH_DOXYGEN /*! * @brief Define this to disable 64-bit code. * * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. */ # define XXH_NO_LONG_LONG # undef XXH_NO_LONG_LONG /* don't actually */ /*! * @brief Controls how unaligned memory is accessed. * * By default, access to unaligned memory is controlled by `memcpy()`, which is * safe and portable. * * Unfortunately, on some target/compiler combinations, the generated assembly * is sub-optimal. * * The below switch allow selection of a different access method * in the search for improved performance. * * @par Possible options: * * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` * @par * Use `memcpy()`. Safe and portable. Note that most modern compilers will * eliminate the function call and treat it as an unaligned access. * * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` * @par * Depends on compiler extensions and is therefore not portable. * This method is safe _if_ your compiler supports it, * and *generally* as fast or faster than `memcpy`. * * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast * @par * Casts directly and dereferences. This method doesn't depend on the * compiler, but it violates the C standard as it directly dereferences an * unaligned pointer. It can generate buggy code on targets which do not * support unaligned memory accesses, but in some circumstances, it's the * only known way to get the most performance. * * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift * @par * Also portable. This can generate the best code on old compilers which don't * inline small `memcpy()` calls, and it might also be faster on big-endian * systems which lack a native byteswap instruction. However, some compilers * will emit literal byteshifts even if the target supports unaligned access. * * * @warning * Methods 1 and 2 rely on implementation-defined behavior. Use these with * care, as what works on one compiler/platform/optimization level may cause * another to read garbage data or even crash. * * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. * * Prefer these methods in priority order (0 > 3 > 1 > 2) */ # define XXH_FORCE_MEMORY_ACCESS 0 /*! * @def XXH_SIZE_OPT * @brief Controls how much xxHash optimizes for size. * * xxHash, when compiled, tends to result in a rather large binary size. This * is mostly due to heavy usage to forced inlining and constant folding of the * @ref XXH3_family to increase performance. * * However, some developers prefer size over speed. This option can * significantly reduce the size of the generated code. When using the `-Os` * or `-Oz` options on GCC or Clang, this is defined to 1 by default, * otherwise it is defined to 0. * * Most of these size optimizations can be controlled manually. * * This is a number from 0-2. * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed * comes first. * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more * conservative and disables hacks that increase code size. It implies the * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, * and @ref XXH3_NEON_LANES == 8 if they are not already defined. * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. * Performance may cry. For example, the single shot functions just use the * streaming API. */ # define XXH_SIZE_OPT 0 /*! * @def XXH_FORCE_ALIGN_CHECK * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() * and XXH64() only). * * This is an important performance trick for architectures without decent * unaligned memory access performance. * * It checks for input alignment, and when conditions are met, uses a "fast * path" employing direct 32-bit/64-bit reads, resulting in _dramatically * faster_ read speed. * * The check costs one initial branch per hash, which is generally negligible, * but not zero. * * Moreover, it's not useful to generate an additional code path if memory * access uses the same instruction for both aligned and unaligned * addresses (e.g. x86 and aarch64). * * In these cases, the alignment check can be removed by setting this macro to 0. * Then the code will always use unaligned memory access. * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips * which are platforms known to offer good unaligned memory accesses performance. * * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. * * This option does not affect XXH3 (only XXH32 and XXH64). */ # define XXH_FORCE_ALIGN_CHECK 0 /*! * @def XXH_NO_INLINE_HINTS * @brief When non-zero, sets all functions to `static`. * * By default, xxHash tries to force the compiler to inline almost all internal * functions. * * This can usually improve performance due to reduced jumping and improved * constant folding, but significantly increases the size of the binary which * might not be favorable. * * Additionally, sometimes the forced inlining can be detrimental to performance, * depending on the architecture. * * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the * compiler full control on whether to inline or not. * * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. */ # define XXH_NO_INLINE_HINTS 0 /*! * @def XXH3_INLINE_SECRET * @brief Determines whether to inline the XXH3 withSecret code. * * When the secret size is known, the compiler can improve the performance * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret(). * * However, if the secret size is not known, it doesn't have any benefit. This * happens when xxHash is compiled into a global symbol. Therefore, if * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0. * * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers * that are *sometimes* force inline on -Og, and it is impossible to automatically * detect this optimization level. */ # define XXH3_INLINE_SECRET 0 /*! * @def XXH32_ENDJMP * @brief Whether to use a jump for `XXH32_finalize`. * * For performance, `XXH32_finalize` uses multiple branches in the finalizer. * This is generally preferable for performance, * but depending on exact architecture, a jmp may be preferable. * * This setting is only possibly making a difference for very small inputs. */ # define XXH32_ENDJMP 0 /*! * @internal * @brief Redefines old internal names. * * For compatibility with code that uses xxHash's internals before the names * were changed to improve namespacing. There is no other reason to use this. */ # define XXH_OLD_NAMES # undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ /*! * @def XXH_NO_STREAM * @brief Disables the streaming API. * * When xxHash is not inlined and the streaming functions are not used, disabling * the streaming functions can improve code size significantly, especially with * the @ref XXH3_family which tends to make constant folded copies of itself. */ # define XXH_NO_STREAM # undef XXH_NO_STREAM /* don't actually */ #endif /* XXH_DOXYGEN */ /*! * @} */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ /* prefer __packed__ structures (method 1) for GCC * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy * which for some reason does unaligned loads. */ # if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) # define XXH_FORCE_MEMORY_ACCESS 1 # endif #endif #ifndef XXH_SIZE_OPT /* default to 1 for -Os or -Oz */ # if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) # define XXH_SIZE_OPT 1 # else # define XXH_SIZE_OPT 0 # endif #endif #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ # if XXH_SIZE_OPT >= 1 || \ defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ # define XXH_FORCE_ALIGN_CHECK 0 # else # define XXH_FORCE_ALIGN_CHECK 1 # endif #endif #ifndef XXH_NO_INLINE_HINTS # if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ # define XXH_NO_INLINE_HINTS 1 # else # define XXH_NO_INLINE_HINTS 0 # endif #endif #ifndef XXH3_INLINE_SECRET # if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \ || !defined(XXH_INLINE_ALL) # define XXH3_INLINE_SECRET 0 # else # define XXH3_INLINE_SECRET 1 # endif #endif #ifndef XXH32_ENDJMP /* generally preferable for performance */ # define XXH32_ENDJMP 0 #endif /*! * @defgroup impl Implementation * @{ */ /* ************************************* * Includes & Memory related functions ***************************************/ #if defined(XXH_NO_STREAM) /* nothing */ #elif defined(XXH_NO_STDLIB) /* When requesting to disable any mention of stdlib, * the library loses the ability to invoked malloc / free. * In practice, it means that functions like `XXH*_createState()` * will always fail, and return NULL. * This flag is useful in situations where * xxhash.h is integrated into some kernel, embedded or limited environment * without access to dynamic allocation. */ static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } static void XXH_free(void* p) { (void)p; } #else /* * Modify the local functions below should you wish to use * different memory routines for malloc() and free() */ #include /*! * @internal * @brief Modify this function to use a different routine than malloc(). */ static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } /*! * @internal * @brief Modify this function to use a different routine than free(). */ static void XXH_free(void* p) { free(p); } #endif /* XXH_NO_STDLIB */ #include /*! * @internal * @brief Modify this function to use a different routine than memcpy(). */ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } #include /* ULLONG_MAX */ /* ************************************* * Compiler Specific Options ***************************************/ #ifdef _MSC_VER /* Visual Studio warning fix */ # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ #endif #if XXH_NO_INLINE_HINTS /* disable inlining hints */ # if defined(__GNUC__) || defined(__clang__) # define XXH_FORCE_INLINE static __attribute__((unused)) # else # define XXH_FORCE_INLINE static # endif # define XXH_NO_INLINE static /* enable inlining hints */ #elif defined(__GNUC__) || defined(__clang__) # define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) # define XXH_NO_INLINE static __attribute__((noinline)) #elif defined(_MSC_VER) /* Visual Studio */ # define XXH_FORCE_INLINE static __forceinline # define XXH_NO_INLINE static __declspec(noinline) #elif defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ # define XXH_FORCE_INLINE static inline # define XXH_NO_INLINE static #else # define XXH_FORCE_INLINE static # define XXH_NO_INLINE static #endif #if XXH3_INLINE_SECRET # define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE #else # define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE #endif /* ************************************* * Debug ***************************************/ /*! * @ingroup tuning * @def XXH_DEBUGLEVEL * @brief Sets the debugging level. * * XXH_DEBUGLEVEL is expected to be defined externally, typically via the * compiler's command line options. The value must be a number. */ #ifndef XXH_DEBUGLEVEL # ifdef DEBUGLEVEL /* backwards compat */ # define XXH_DEBUGLEVEL DEBUGLEVEL # else # define XXH_DEBUGLEVEL 0 # endif #endif #if (XXH_DEBUGLEVEL>=1) # include /* note: can still be disabled with NDEBUG */ # define XXH_ASSERT(c) assert(c) #else # if defined(__INTEL_COMPILER) # define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) # else # define XXH_ASSERT(c) XXH_ASSUME(c) # endif #endif /* note: use after variable declarations */ #ifndef XXH_STATIC_ASSERT # if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) # elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) # else # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) # endif # define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) #endif /*! * @internal * @def XXH_COMPILER_GUARD(var) * @brief Used to prevent unwanted optimizations for @p var. * * It uses an empty GCC inline assembly statement with a register constraint * which forces @p var into a general purpose register (eg eax, ebx, ecx * on x86) and marks it as modified. * * This is used in a few places to avoid unwanted autovectorization (e.g. * XXH32_round()). All vectorization we want is explicit via intrinsics, * and _usually_ isn't wanted elsewhere. * * We also use it to prevent unwanted constant folding for AArch64 in * XXH3_initCustomSecret_scalar(). */ #if defined(__GNUC__) || defined(__clang__) # define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) #else # define XXH_COMPILER_GUARD(var) ((void)0) #endif /* Specifically for NEON vectors which use the "w" constraint, on * Clang. */ #if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) # define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) #else # define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) #endif /* ************************************* * Basic Types ***************************************/ #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) # include typedef uint8_t xxh_u8; #else typedef unsigned char xxh_u8; #endif typedef XXH32_hash_t xxh_u32; #ifdef XXH_OLD_NAMES # warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" # define BYTE xxh_u8 # define U8 xxh_u8 # define U32 xxh_u32 #endif /* *** Memory access *** */ /*! * @internal * @fn xxh_u32 XXH_read32(const void* ptr) * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit native endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readLE32(const void* ptr) * @brief Reads an unaligned 32-bit little endian integer from @p ptr. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit little endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readBE32(const void* ptr) * @brief Reads an unaligned 32-bit big endian integer from @p ptr. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * * @param ptr The pointer to read from. * @return The 32-bit big endian integer from the bytes at @p ptr. */ /*! * @internal * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. * * Affected by @ref XXH_FORCE_MEMORY_ACCESS. * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is * always @ref XXH_alignment::XXH_unaligned. * * @param ptr The pointer to read from. * @param align Whether @p ptr is aligned. * @pre * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte * aligned. * @return The 32-bit little endian integer from the bytes at @p ptr. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) /* * Manual byteshift. Best for old compilers which don't inline memcpy. * We actually directly use XXH_readLE32 and XXH_readBE32. */ #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* * Force direct memory access. Only works on CPU which support unaligned memory * access in hardware. */ static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* * __attribute__((aligned(1))) is supported by gcc and clang. Originally the * documentation claimed that it only increased the alignment, but actually it * can decrease it on gcc, clang, and icc: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; #endif static xxh_u32 XXH_read32(const void* ptr) { typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; return *((const xxh_unalign32*)ptr); } #else /* * Portable and safe solution. Generally efficient. * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u32 XXH_read32(const void* memPtr) { xxh_u32 val; XXH_memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ /* *** Endianness *** */ /*! * @ingroup tuning * @def XXH_CPU_LITTLE_ENDIAN * @brief Whether the target is little endian. * * Defined to 1 if the target is little endian, or 0 if it is big endian. * It can be defined externally, for example on the compiler command line. * * If it is not defined, * a runtime check (which is usually constant folded) is used instead. * * @note * This is not necessarily defined to an integer constant. * * @see XXH_isLittleEndian() for the runtime check. */ #ifndef XXH_CPU_LITTLE_ENDIAN /* * Try to detect endianness automatically, to avoid the nonstandard behavior * in `XXH_isLittleEndian()` */ # if defined(_WIN32) /* Windows is always little endian */ \ || defined(__LITTLE_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) # define XXH_CPU_LITTLE_ENDIAN 1 # elif defined(__BIG_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define XXH_CPU_LITTLE_ENDIAN 0 # else /*! * @internal * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. * * Most compilers will constant fold this. */ static int XXH_isLittleEndian(void) { /* * Portable and well-defined behavior. * Don't use static: it is detrimental to performance. */ const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; return one.c[0]; } # define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() # endif #endif /* **************************************** * Compiler-specific Functions and Macros ******************************************/ #define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) #ifdef __has_builtin # define XXH_HAS_BUILTIN(x) __has_builtin(x) #else # define XXH_HAS_BUILTIN(x) 0 #endif /* * C23 and future versions have standard "unreachable()". * Once it has been implemented reliably we can add it as an * additional case: * * ``` * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) * # include * # ifdef unreachable * # define XXH_UNREACHABLE() unreachable() * # endif * #endif * ``` * * Note C++23 also has std::unreachable() which can be detected * as follows: * ``` * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) * # include * # define XXH_UNREACHABLE() std::unreachable() * #endif * ``` * NB: `__cpp_lib_unreachable` is defined in the `` header. * We don't use that as including `` in `extern "C"` blocks * doesn't work on GCC12 */ #if XXH_HAS_BUILTIN(__builtin_unreachable) # define XXH_UNREACHABLE() __builtin_unreachable() #elif defined(_MSC_VER) # define XXH_UNREACHABLE() __assume(0) #else # define XXH_UNREACHABLE() #endif #if XXH_HAS_BUILTIN(__builtin_assume) # define XXH_ASSUME(c) __builtin_assume(c) #else # define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } #endif /*! * @internal * @def XXH_rotl32(x,r) * @brief 32-bit rotate left. * * @param x The 32-bit integer to be rotated. * @param r The number of bits to rotate. * @pre * @p r > 0 && @p r < 32 * @note * @p x and @p r may be evaluated multiple times. * @return The rotated result. */ #if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ && XXH_HAS_BUILTIN(__builtin_rotateleft64) # define XXH_rotl32 __builtin_rotateleft32 # define XXH_rotl64 __builtin_rotateleft64 /* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ #elif defined(_MSC_VER) # define XXH_rotl32(x,r) _rotl(x,r) # define XXH_rotl64(x,r) _rotl64(x,r) #else # define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) # define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) #endif /*! * @internal * @fn xxh_u32 XXH_swap32(xxh_u32 x) * @brief A 32-bit byteswap. * * @param x The 32-bit integer to byteswap. * @return @p x, byteswapped. */ #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap32 _byteswap_ulong #elif XXH_GCC_VERSION >= 403 # define XXH_swap32 __builtin_bswap32 #else static xxh_u32 XXH_swap32 (xxh_u32 x) { return ((x << 24) & 0xff000000 ) | ((x << 8) & 0x00ff0000 ) | ((x >> 8) & 0x0000ff00 ) | ((x >> 24) & 0x000000ff ); } #endif /* *************************** * Memory reads *****************************/ /*! * @internal * @brief Enum to indicate whether a pointer is aligned. */ typedef enum { XXH_aligned, /*!< Aligned */ XXH_unaligned /*!< Possibly unaligned */ } XXH_alignment; /* * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. * * This is ideal for older compilers which don't inline memcpy. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[0] | ((xxh_u32)bytePtr[1] << 8) | ((xxh_u32)bytePtr[2] << 16) | ((xxh_u32)bytePtr[3] << 24); } XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[3] | ((xxh_u32)bytePtr[2] << 8) | ((xxh_u32)bytePtr[1] << 16) | ((xxh_u32)bytePtr[0] << 24); } #else XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); } static xxh_u32 XXH_readBE32(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); } #endif XXH_FORCE_INLINE xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) { if (align==XXH_unaligned) { return XXH_readLE32(ptr); } else { return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); } } /* ************************************* * Misc ***************************************/ /*! @ingroup public */ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } /* ******************************************************************* * 32-bit hash functions *********************************************************************/ /*! * @} * @defgroup XXH32_impl XXH32 implementation * @ingroup impl * * Details on the XXH32 implementation. * @{ */ /* #define instead of static const, to be used as initializers */ #define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ #define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ #define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ #define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ #define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ #ifdef XXH_OLD_NAMES # define PRIME32_1 XXH_PRIME32_1 # define PRIME32_2 XXH_PRIME32_2 # define PRIME32_3 XXH_PRIME32_3 # define PRIME32_4 XXH_PRIME32_4 # define PRIME32_5 XXH_PRIME32_5 #endif /*! * @internal * @brief Normal stripe processing routine. * * This shuffles the bits so that any bit from @p input impacts several bits in * @p acc. * * @param acc The accumulator lane. * @param input The stripe of input to mix. * @return The mixed accumulator lane. */ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) { acc += input * XXH_PRIME32_2; acc = XXH_rotl32(acc, 13); acc *= XXH_PRIME32_1; #if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) /* * UGLY HACK: * A compiler fence is the only thing that prevents GCC and Clang from * autovectorizing the XXH32 loop (pragmas and attributes don't work for some * reason) without globally disabling SSE4.1. * * The reason we want to avoid vectorization is because despite working on * 4 integers at a time, there are multiple factors slowing XXH32 down on * SSE4: * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on * newer chips!) making it slightly slower to multiply four integers at * once compared to four integers independently. Even when pmulld was * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE * just to multiply unless doing a long operation. * * - Four instructions are required to rotate, * movqda tmp, v // not required with VEX encoding * pslld tmp, 13 // tmp <<= 13 * psrld v, 19 // x >>= 19 * por v, tmp // x |= tmp * compared to one for scalar: * roll v, 13 // reliably fast across the board * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason * * - Instruction level parallelism is actually more beneficial here because * the SIMD actually serializes this operation: While v1 is rotating, v2 * can load data, while v3 can multiply. SSE forces them to operate * together. * * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing * the loop. NEON is only faster on the A53, and with the newer cores, it is less * than half the speed. * * Additionally, this is used on WASM SIMD128 because it JITs to the same * SIMD instructions and has the same issue. */ XXH_COMPILER_GUARD(acc); #endif return acc; } /*! * @internal * @brief Mixes all bits to finalize the hash. * * The final mix ensures that all input bits have a chance to impact any bit in * the output digest, resulting in an unbiased distribution. * * @param hash The hash to avalanche. * @return The avalanched hash. */ static xxh_u32 XXH32_avalanche(xxh_u32 hash) { hash ^= hash >> 15; hash *= XXH_PRIME32_2; hash ^= hash >> 13; hash *= XXH_PRIME32_3; hash ^= hash >> 16; return hash; } #define XXH_get32bits(p) XXH_readLE32_align(p, align) /*! * @internal * @brief Processes the last 0-15 bytes of @p ptr. * * There may be up to 15 bytes remaining to consume from the input. * This final stage will digest them to ensure that all input bytes are present * in the final mix. * * @param hash The hash to finalize. * @param ptr The pointer to the remaining input. * @param len The remaining length, modulo 16. * @param align Whether @p ptr is aligned. * @return The finalized hash. * @see XXH64_finalize(). */ static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { #define XXH_PROCESS1 do { \ hash += (*ptr++) * XXH_PRIME32_5; \ hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ } while (0) #define XXH_PROCESS4 do { \ hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ ptr += 4; \ hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ } while (0) if (ptr==NULL) XXH_ASSERT(len == 0); /* Compact rerolled version; generally faster */ if (!XXH32_ENDJMP) { len &= 15; while (len >= 4) { XXH_PROCESS4; len -= 4; } while (len > 0) { XXH_PROCESS1; --len; } return XXH32_avalanche(hash); } else { switch(len&15) /* or switch(bEnd - p) */ { case 12: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 8: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 4: XXH_PROCESS4; return XXH32_avalanche(hash); case 13: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 9: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 5: XXH_PROCESS4; XXH_PROCESS1; return XXH32_avalanche(hash); case 14: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 10: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 6: XXH_PROCESS4; XXH_PROCESS1; XXH_PROCESS1; return XXH32_avalanche(hash); case 15: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 11: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 7: XXH_PROCESS4; XXH_FALLTHROUGH; /* fallthrough */ case 3: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 2: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 1: XXH_PROCESS1; XXH_FALLTHROUGH; /* fallthrough */ case 0: return XXH32_avalanche(hash); } XXH_ASSERT(0); return hash; /* reaching this point is deemed impossible */ } } #ifdef XXH_OLD_NAMES # define PROCESS1 XXH_PROCESS1 # define PROCESS4 XXH_PROCESS4 #else # undef XXH_PROCESS1 # undef XXH_PROCESS4 #endif /*! * @internal * @brief The implementation for @ref XXH32(). * * @param input , len , seed Directly passed from @ref XXH32(). * @param align Whether @p input is aligned. * @return The calculated hash. */ XXH_FORCE_INLINE XXH_PUREF xxh_u32 XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) { xxh_u32 h32; if (input==NULL) XXH_ASSERT(len == 0); if (len>=16) { const xxh_u8* const bEnd = input + len; const xxh_u8* const limit = bEnd - 15; xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; xxh_u32 v2 = seed + XXH_PRIME32_2; xxh_u32 v3 = seed + 0; xxh_u32 v4 = seed - XXH_PRIME32_1; do { v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; } while (input < limit); h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); } else { h32 = seed + XXH_PRIME32_5; } h32 += (xxh_u32)len; return XXH32_finalize(h32, input, len&15, align); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) { #if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH32_state_t state; XXH32_reset(&state, seed); XXH32_update(&state, (const xxh_u8*)input, len); return XXH32_digest(&state); #else if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); } } return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); #endif } /******* Hash streaming *******/ #ifndef XXH_NO_STREAM /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) { return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) { XXH_ASSERT(statePtr != NULL); memset(statePtr, 0, sizeof(*statePtr)); statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; statePtr->v[1] = seed + XXH_PRIME32_2; statePtr->v[2] = seed + 0; statePtr->v[3] = seed - XXH_PRIME32_1; return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t* state, const void* input, size_t len) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } { const xxh_u8* p = (const xxh_u8*)input; const xxh_u8* const bEnd = p + len; state->total_len_32 += (XXH32_hash_t)len; state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); if (state->memsize + len < 16) { /* fill in tmp buffer */ XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); state->memsize += (XXH32_hash_t)len; return XXH_OK; } if (state->memsize) { /* some data left from previous update */ XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); { const xxh_u32* p32 = state->mem32; state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++; state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++; state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++; state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32)); } p += 16-state->memsize; state->memsize = 0; } if (p <= bEnd-16) { const xxh_u8* const limit = bEnd - 16; do { state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4; state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4; state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4; state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4; } while (p<=limit); } if (p < bEnd) { XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); state->memsize = (unsigned)(bEnd-p); } } return XXH_OK; } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) { xxh_u32 h32; if (state->large_len) { h32 = XXH_rotl32(state->v[0], 1) + XXH_rotl32(state->v[1], 7) + XXH_rotl32(state->v[2], 12) + XXH_rotl32(state->v[3], 18); } else { h32 = state->v[2] /* == seed */ + XXH_PRIME32_5; } h32 += state->total_len_32; return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); } #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! * @ingroup XXH32_family * The default return values from XXH functions are unsigned 32 and 64 bit * integers. * * The canonical representation uses big endian convention, the same convention * as human-readable numbers (large digits first). * * This way, hash values can be written into a file or buffer, remaining * comparable across different systems. * * The following functions allow transformation of hash values to and from their * canonical format. */ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } /*! @ingroup XXH32_family */ XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) { return XXH_readBE32(src); } #ifndef XXH_NO_LONG_LONG /* ******************************************************************* * 64-bit hash functions *********************************************************************/ /*! * @} * @ingroup impl * @{ */ /******* Memory access *******/ typedef XXH64_hash_t xxh_u64; #ifdef XXH_OLD_NAMES # define U64 xxh_u64 #endif #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) /* * Manual byteshift. Best for old compilers which don't inline memcpy. * We actually directly use XXH_readLE64 and XXH_readBE64. */ #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ static xxh_u64 XXH_read64(const void* memPtr) { return *(const xxh_u64*) memPtr; } #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) /* * __attribute__((aligned(1))) is supported by gcc and clang. Originally the * documentation claimed that it only increased the alignment, but actually it * can decrease it on gcc, clang, and icc: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, * https://gcc.godbolt.org/z/xYez1j67Y. */ #ifdef XXH_OLD_NAMES typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; #endif static xxh_u64 XXH_read64(const void* ptr) { typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; return *((const xxh_unalign64*)ptr); } #else /* * Portable and safe solution. Generally efficient. * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html */ static xxh_u64 XXH_read64(const void* memPtr) { xxh_u64 val; XXH_memcpy(&val, memPtr, sizeof(val)); return val; } #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ #if defined(_MSC_VER) /* Visual Studio */ # define XXH_swap64 _byteswap_uint64 #elif XXH_GCC_VERSION >= 403 # define XXH_swap64 __builtin_bswap64 #else static xxh_u64 XXH_swap64(xxh_u64 x) { return ((x << 56) & 0xff00000000000000ULL) | ((x << 40) & 0x00ff000000000000ULL) | ((x << 24) & 0x0000ff0000000000ULL) | ((x << 8) & 0x000000ff00000000ULL) | ((x >> 8) & 0x00000000ff000000ULL) | ((x >> 24) & 0x0000000000ff0000ULL) | ((x >> 40) & 0x000000000000ff00ULL) | ((x >> 56) & 0x00000000000000ffULL); } #endif /* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[0] | ((xxh_u64)bytePtr[1] << 8) | ((xxh_u64)bytePtr[2] << 16) | ((xxh_u64)bytePtr[3] << 24) | ((xxh_u64)bytePtr[4] << 32) | ((xxh_u64)bytePtr[5] << 40) | ((xxh_u64)bytePtr[6] << 48) | ((xxh_u64)bytePtr[7] << 56); } XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) { const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; return bytePtr[7] | ((xxh_u64)bytePtr[6] << 8) | ((xxh_u64)bytePtr[5] << 16) | ((xxh_u64)bytePtr[4] << 24) | ((xxh_u64)bytePtr[3] << 32) | ((xxh_u64)bytePtr[2] << 40) | ((xxh_u64)bytePtr[1] << 48) | ((xxh_u64)bytePtr[0] << 56); } #else XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); } static xxh_u64 XXH_readBE64(const void* ptr) { return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); } #endif XXH_FORCE_INLINE xxh_u64 XXH_readLE64_align(const void* ptr, XXH_alignment align) { if (align==XXH_unaligned) return XXH_readLE64(ptr); else return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); } /******* xxh64 *******/ /*! * @} * @defgroup XXH64_impl XXH64 implementation * @ingroup impl * * Details on the XXH64 implementation. * @{ */ /* #define rather that static const, to be used as initializers */ #define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ #define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ #define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ #define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ #define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ #ifdef XXH_OLD_NAMES # define PRIME64_1 XXH_PRIME64_1 # define PRIME64_2 XXH_PRIME64_2 # define PRIME64_3 XXH_PRIME64_3 # define PRIME64_4 XXH_PRIME64_4 # define PRIME64_5 XXH_PRIME64_5 #endif /*! @copydoc XXH32_round */ static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) { acc += input * XXH_PRIME64_2; acc = XXH_rotl64(acc, 31); acc *= XXH_PRIME64_1; return acc; } static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) { val = XXH64_round(0, val); acc ^= val; acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; return acc; } /*! @copydoc XXH32_avalanche */ static xxh_u64 XXH64_avalanche(xxh_u64 hash) { hash ^= hash >> 33; hash *= XXH_PRIME64_2; hash ^= hash >> 29; hash *= XXH_PRIME64_3; hash ^= hash >> 32; return hash; } #define XXH_get64bits(p) XXH_readLE64_align(p, align) /*! * @internal * @brief Processes the last 0-31 bytes of @p ptr. * * There may be up to 31 bytes remaining to consume from the input. * This final stage will digest them to ensure that all input bytes are present * in the final mix. * * @param hash The hash to finalize. * @param ptr The pointer to the remaining input. * @param len The remaining length, modulo 32. * @param align Whether @p ptr is aligned. * @return The finalized hash * @see XXH32_finalize(). */ static XXH_PUREF xxh_u64 XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) { if (ptr==NULL) XXH_ASSERT(len == 0); len &= 31; while (len >= 8) { xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); ptr += 8; hash ^= k1; hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; len -= 8; } if (len >= 4) { hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; ptr += 4; hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; len -= 4; } while (len > 0) { hash ^= (*ptr++) * XXH_PRIME64_5; hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; --len; } return XXH64_avalanche(hash); } #ifdef XXH_OLD_NAMES # define PROCESS1_64 XXH_PROCESS1_64 # define PROCESS4_64 XXH_PROCESS4_64 # define PROCESS8_64 XXH_PROCESS8_64 #else # undef XXH_PROCESS1_64 # undef XXH_PROCESS4_64 # undef XXH_PROCESS8_64 #endif /*! * @internal * @brief The implementation for @ref XXH64(). * * @param input , len , seed Directly passed from @ref XXH64(). * @param align Whether @p input is aligned. * @return The calculated hash. */ XXH_FORCE_INLINE XXH_PUREF xxh_u64 XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) { xxh_u64 h64; if (input==NULL) XXH_ASSERT(len == 0); if (len>=32) { const xxh_u8* const bEnd = input + len; const xxh_u8* const limit = bEnd - 31; xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; xxh_u64 v2 = seed + XXH_PRIME64_2; xxh_u64 v3 = seed + 0; xxh_u64 v4 = seed - XXH_PRIME64_1; do { v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; } while (input= 2 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ XXH64_state_t state; XXH64_reset(&state, seed); XXH64_update(&state, (const xxh_u8*)input, len); return XXH64_digest(&state); #else if (XXH_FORCE_ALIGN_CHECK) { if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); } } return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); #endif } /******* Hash Streaming *******/ #ifndef XXH_NO_STREAM /*! @ingroup XXH64_family*/ XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) { return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) { XXH_free(statePtr); return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) { XXH_memcpy(dstState, srcState, sizeof(*dstState)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) { XXH_ASSERT(statePtr != NULL); memset(statePtr, 0, sizeof(*statePtr)); statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; statePtr->v[1] = seed + XXH_PRIME64_2; statePtr->v[2] = seed + 0; statePtr->v[3] = seed - XXH_PRIME64_1; return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } { const xxh_u8* p = (const xxh_u8*)input; const xxh_u8* const bEnd = p + len; state->total_len += len; if (state->memsize + len < 32) { /* fill in tmp buffer */ XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); state->memsize += (xxh_u32)len; return XXH_OK; } if (state->memsize) { /* tmp buffer is full */ XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0)); state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1)); state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2)); state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3)); p += 32 - state->memsize; state->memsize = 0; } if (p+32 <= bEnd) { const xxh_u8* const limit = bEnd - 32; do { state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8; state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8; state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8; state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8; } while (p<=limit); } if (p < bEnd) { XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); state->memsize = (unsigned)(bEnd-p); } } return XXH_OK; } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) { xxh_u64 h64; if (state->total_len >= 32) { h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18); h64 = XXH64_mergeRound(h64, state->v[0]); h64 = XXH64_mergeRound(h64, state->v[1]); h64 = XXH64_mergeRound(h64, state->v[2]); h64 = XXH64_mergeRound(h64, state->v[3]); } else { h64 = state->v[2] /*seed*/ + XXH_PRIME64_5; } h64 += (xxh_u64) state->total_len; return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); } #endif /* !XXH_NO_STREAM */ /******* Canonical representation *******/ /*! @ingroup XXH64_family */ XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); XXH_memcpy(dst, &hash, sizeof(*dst)); } /*! @ingroup XXH64_family */ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) { return XXH_readBE64(src); } #ifndef XXH_NO_XXH3 /* ********************************************************************* * XXH3 * New generation hash designed for speed on small keys and vectorization ************************************************************************ */ /*! * @} * @defgroup XXH3_impl XXH3 implementation * @ingroup impl * @{ */ /* === Compiler specifics === */ #if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ # define XXH_RESTRICT /* disable */ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ # define XXH_RESTRICT restrict #elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ || (defined (__clang__)) \ || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) /* * There are a LOT more compilers that recognize __restrict but this * covers the major ones. */ # define XXH_RESTRICT __restrict #else # define XXH_RESTRICT /* disable */ #endif #if (defined(__GNUC__) && (__GNUC__ >= 3)) \ || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ || defined(__clang__) # define XXH_likely(x) __builtin_expect(x, 1) # define XXH_unlikely(x) __builtin_expect(x, 0) #else # define XXH_likely(x) (x) # define XXH_unlikely(x) (x) #endif #ifndef XXH_HAS_INCLUDE # ifdef __has_include # define XXH_HAS_INCLUDE(x) __has_include(x) # else # define XXH_HAS_INCLUDE(x) 0 # endif #endif #if defined(__GNUC__) || defined(__clang__) # if defined(__ARM_FEATURE_SVE) # include # endif # if defined(__ARM_NEON__) || defined(__ARM_NEON) \ || (defined(_M_ARM) && _M_ARM >= 7) \ || defined(_M_ARM64) || defined(_M_ARM64EC) \ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ # define inline __inline__ /* circumvent a clang bug */ # include # undef inline # elif defined(__AVX2__) # include # elif defined(__SSE2__) # include # endif #endif #if defined(_MSC_VER) # include #endif /* * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while * remaining a true 64-bit/128-bit hash function. * * This is done by prioritizing a subset of 64-bit operations that can be * emulated without too many steps on the average 32-bit machine. * * For example, these two lines seem similar, and run equally fast on 64-bit: * * xxh_u64 x; * x ^= (x >> 47); // good * x ^= (x >> 13); // bad * * However, to a 32-bit machine, there is a major difference. * * x ^= (x >> 47) looks like this: * * x.lo ^= (x.hi >> (47 - 32)); * * while x ^= (x >> 13) looks like this: * * // note: funnel shifts are not usually cheap. * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); * x.hi ^= (x.hi >> 13); * * The first one is significantly faster than the second, simply because the * shift is larger than 32. This means: * - All the bits we need are in the upper 32 bits, so we can ignore the lower * 32 bits in the shift. * - The shift result will always fit in the lower 32 bits, and therefore, * we can ignore the upper 32 bits in the xor. * * Thanks to this optimization, XXH3 only requires these features to be efficient: * * - Usable unaligned access * - A 32-bit or 64-bit ALU * - If 32-bit, a decent ADC instruction * - A 32 or 64-bit multiply with a 64-bit result * - For the 128-bit variant, a decent byteswap helps short inputs. * * The first two are already required by XXH32, and almost all 32-bit and 64-bit * platforms which can run XXH32 can run XXH3 efficiently. * * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one * notable exception. * * First of all, Thumb-1 lacks support for the UMULL instruction which * performs the important long multiply. This means numerous __aeabi_lmul * calls. * * Second of all, the 8 functional registers are just not enough. * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need * Lo registers, and this shuffling results in thousands more MOVs than A32. * * A32 and T32 don't have this limitation. They can access all 14 registers, * do a 32->64 multiply with UMULL, and the flexible operand allowing free * shifts is helpful, too. * * Therefore, we do a quick sanity check. * * If compiling Thumb-1 for a target which supports ARM instructions, we will * emit a warning, as it is not a "sane" platform to compile for. * * Usually, if this happens, it is because of an accident and you probably need * to specify -march, as you likely meant to compile for a newer architecture. * * Credit: large sections of the vectorial and asm source code paths * have been contributed by @easyaspi314 */ #if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) # warning "XXH3 is highly inefficient without ARM or Thumb-2." #endif /* ========================================== * Vectorization detection * ========================================== */ #ifdef XXH_DOXYGEN /*! * @ingroup tuning * @brief Overrides the vectorization implementation chosen for XXH3. * * Can be defined to 0 to disable SIMD or any of the values mentioned in * @ref XXH_VECTOR_TYPE. * * If this is not defined, it uses predefined macros to determine the best * implementation. */ # define XXH_VECTOR XXH_SCALAR /*! * @ingroup tuning * @brief Possible values for @ref XXH_VECTOR. * * Note that these are actually implemented as macros. * * If this is not defined, it is detected automatically. * internal macro XXH_X86DISPATCH overrides this. */ enum XXH_VECTOR_TYPE /* fake enum */ { XXH_SCALAR = 0, /*!< Portable scalar version */ XXH_SSE2 = 1, /*!< * SSE2 for Pentium 4, Opteron, all x86_64. * * @note SSE2 is also guaranteed on Windows 10, macOS, and * Android x86. */ XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ XXH_NEON = 4, /*!< * NEON for most ARMv7-A, all AArch64, and WASM SIMD128 * via the SIMDeverywhere polyfill provided with the * Emscripten SDK. */ XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */ }; /*! * @ingroup tuning * @brief Selects the minimum alignment for XXH3's accumulators. * * When using SIMD, this should match the alignment required for said vector * type, so, for example, 32 for AVX2. * * Default: Auto detected. */ # define XXH_ACC_ALIGN 8 #endif /* Actual definition */ #ifndef XXH_DOXYGEN # define XXH_SCALAR 0 # define XXH_SSE2 1 # define XXH_AVX2 2 # define XXH_AVX512 3 # define XXH_NEON 4 # define XXH_VSX 5 # define XXH_SVE 6 #endif #ifndef XXH_VECTOR /* can be defined on command line */ # if defined(__ARM_FEATURE_SVE) # define XXH_VECTOR XXH_SVE # elif ( \ defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ ) && ( \ defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ ) # define XXH_VECTOR XXH_NEON # elif defined(__AVX512F__) # define XXH_VECTOR XXH_AVX512 # elif defined(__AVX2__) # define XXH_VECTOR XXH_AVX2 # elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) # define XXH_VECTOR XXH_SSE2 # elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ || (defined(__s390x__) && defined(__VEC__)) \ && defined(__GNUC__) /* TODO: IBM XL */ # define XXH_VECTOR XXH_VSX # else # define XXH_VECTOR XXH_SCALAR # endif #endif /* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ #if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) # ifdef _MSC_VER # pragma warning(once : 4606) # else # warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." # endif # undef XXH_VECTOR # define XXH_VECTOR XXH_SCALAR #endif /* * Controls the alignment of the accumulator, * for compatibility with aligned vector loads, which are usually faster. */ #ifndef XXH_ACC_ALIGN # if defined(XXH_X86DISPATCH) # define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ # elif XXH_VECTOR == XXH_SCALAR /* scalar */ # define XXH_ACC_ALIGN 8 # elif XXH_VECTOR == XXH_SSE2 /* sse2 */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_AVX2 /* avx2 */ # define XXH_ACC_ALIGN 32 # elif XXH_VECTOR == XXH_NEON /* neon */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_VSX /* vsx */ # define XXH_ACC_ALIGN 16 # elif XXH_VECTOR == XXH_AVX512 /* avx512 */ # define XXH_ACC_ALIGN 64 # elif XXH_VECTOR == XXH_SVE /* sve */ # define XXH_ACC_ALIGN 64 # endif #endif #if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 # define XXH_SEC_ALIGN XXH_ACC_ALIGN #elif XXH_VECTOR == XXH_SVE # define XXH_SEC_ALIGN XXH_ACC_ALIGN #else # define XXH_SEC_ALIGN 8 #endif #if defined(__GNUC__) || defined(__clang__) # define XXH_ALIASING __attribute__((may_alias)) #else # define XXH_ALIASING /* nothing */ #endif /* * UGLY HACK: * GCC usually generates the best code with -O3 for xxHash. * * However, when targeting AVX2, it is overzealous in its unrolling resulting * in code roughly 3/4 the speed of Clang. * * There are other issues, such as GCC splitting _mm256_loadu_si256 into * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which * only applies to Sandy and Ivy Bridge... which don't even support AVX2. * * That is why when compiling the AVX2 version, it is recommended to use either * -O2 -mavx2 -march=haswell * or * -O2 -mavx2 -mno-avx256-split-unaligned-load * for decent performance, or to use Clang instead. * * Fortunately, we can control the first one with a pragma that forces GCC into * -O2, but the other one we can't control without "failed to inline always * inline function due to target mismatch" warnings. */ #if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ # pragma GCC push_options # pragma GCC optimize("-O2") #endif #if XXH_VECTOR == XXH_NEON /* * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 * optimizes out the entire hashLong loop because of the aliasing violation. * * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, * so the only option is to mark it as aliasing. */ typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; /*! * @internal * @brief `vld1q_u64` but faster and alignment-safe. * * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). * * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it * prohibits load-store optimizations. Therefore, a direct dereference is used. * * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe * unaligned load. */ #if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ { return *(xxh_aliasing_uint64x2_t const *)ptr; } #else XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) { return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); } #endif /*! * @internal * @brief `vmlal_u32` on low and high halves of a vector. * * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` * with `vmlal_u32`. */ #if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 XXH_FORCE_INLINE uint64x2_t XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { /* Inline assembly is the only way */ __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); return acc; } XXH_FORCE_INLINE uint64x2_t XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { /* This intrinsic works as expected */ return vmlal_high_u32(acc, lhs, rhs); } #else /* Portable intrinsic versions */ XXH_FORCE_INLINE uint64x2_t XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); } /*! @copydoc XXH_vmlal_low_u32 * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ XXH_FORCE_INLINE uint64x2_t XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) { return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); } #endif /*! * @ingroup tuning * @brief Controls the NEON to scalar ratio for XXH3 * * This can be set to 2, 4, 6, or 8. * * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. * * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU * bandwidth. * * This is even more noticeable on the more advanced cores like the Cortex-A76 which * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. * * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes * and 2 scalar lanes, which is chosen by default. * * This does not apply to Apple processors or 32-bit processors, which run better with * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. * * This change benefits CPUs with large micro-op buffers without negatively affecting * most other CPUs: * * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | * |:----------------------|:--------------------|----------:|-----------:|------:| * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | * * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. * * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning * it effectively becomes worse 4. * * @see XXH3_accumulate_512_neon() */ # ifndef XXH3_NEON_LANES # if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 # define XXH3_NEON_LANES 6 # else # define XXH3_NEON_LANES XXH_ACC_NB # endif # endif #endif /* XXH_VECTOR == XXH_NEON */ /* * VSX and Z Vector helpers. * * This is very messy, and any pull requests to clean this up are welcome. * * There are a lot of problems with supporting VSX and s390x, due to * inconsistent intrinsics, spotty coverage, and multiple endiannesses. */ #if XXH_VECTOR == XXH_VSX /* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, * and `pixel`. This is a problem for obvious reasons. * * These keywords are unnecessary; the spec literally says they are * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd * after including the header. * * We use pragma push_macro/pop_macro to keep the namespace clean. */ # pragma push_macro("bool") # pragma push_macro("vector") # pragma push_macro("pixel") /* silence potential macro redefined warnings */ # undef bool # undef vector # undef pixel # if defined(__s390x__) # include # else # include # endif /* Restore the original macro values, if applicable. */ # pragma pop_macro("pixel") # pragma pop_macro("vector") # pragma pop_macro("bool") typedef __vector unsigned long long xxh_u64x2; typedef __vector unsigned char xxh_u8x16; typedef __vector unsigned xxh_u32x4; /* * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. */ typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; # ifndef XXH_VSX_BE # if defined(__BIG_ENDIAN__) \ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) # define XXH_VSX_BE 1 # elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ # warning "-maltivec=be is not recommended. Please use native endianness." # define XXH_VSX_BE 1 # else # define XXH_VSX_BE 0 # endif # endif /* !defined(XXH_VSX_BE) */ # if XXH_VSX_BE # if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) # define XXH_vec_revb vec_revb # else /*! * A polyfill for POWER9's vec_revb(). */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) { xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; return vec_perm(val, val, vByteSwap); } # endif # endif /* XXH_VSX_BE */ /*! * Performs an unaligned vector load and byte swaps it on big endian. */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) { xxh_u64x2 ret; XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); # if XXH_VSX_BE ret = XXH_vec_revb(ret); # endif return ret; } /* * vec_mulo and vec_mule are very problematic intrinsics on PowerPC * * These intrinsics weren't added until GCC 8, despite existing for a while, * and they are endian dependent. Also, their meaning swap depending on version. * */ # if defined(__s390x__) /* s390x is always big endian, no issue on this platform */ # define XXH_vec_mulo vec_mulo # define XXH_vec_mule vec_mule # elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) /* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ # define XXH_vec_mulo __builtin_altivec_vmulouw # define XXH_vec_mule __builtin_altivec_vmuleuw # else /* gcc needs inline assembly */ /* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) { xxh_u64x2 result; __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); return result; } XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) { xxh_u64x2 result; __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); return result; } # endif /* XXH_vec_mulo, XXH_vec_mule */ #endif /* XXH_VECTOR == XXH_VSX */ #if XXH_VECTOR == XXH_SVE #define ACCRND(acc, offset) \ do { \ svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ acc = svadd_u64_x(mask, acc, mul); \ } while (0) #endif /* XXH_VECTOR == XXH_SVE */ /* prefetch * can be disabled, by declaring XXH_NO_PREFETCH build macro */ #if defined(XXH_NO_PREFETCH) # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ #else # if XXH_SIZE_OPT >= 1 # define XXH_PREFETCH(ptr) (void)(ptr) # elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # else # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ # endif #endif /* XXH_NO_PREFETCH */ /* ========================================== * XXH3 default settings * ========================================== */ #define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ #if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) # error "default keyset is not large enough" #endif /*! Pseudorandom secret taken directly from FARSH. */ XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, }; static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ #ifdef XXH_OLD_NAMES # define kSecret XXH3_kSecret #endif #ifdef XXH_DOXYGEN /*! * @brief Calculates a 32-bit to 64-bit long multiply. * * Implemented as a macro. * * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't * need to (but it shouldn't need to anyways, it is about 7 instructions to do * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we * use that instead of the normal method. * * If you are compiling for platforms like Thumb-1 and don't have a better option, * you may also want to write your own long multiply routine here. * * @param x, y Numbers to be multiplied * @return 64-bit product of the low 32 bits of @p x and @p y. */ XXH_FORCE_INLINE xxh_u64 XXH_mult32to64(xxh_u64 x, xxh_u64 y) { return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); } #elif defined(_MSC_VER) && defined(_M_IX86) # define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) #else /* * Downcast + upcast is usually better than masking on older compilers like * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. * * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands * and perform a full 64x64 multiply -- entirely redundant on 32-bit. */ # define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) #endif /*! * @brief Calculates a 64->128-bit long multiply. * * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar * version. * * @param lhs , rhs The 64-bit integers to be multiplied * @return The 128-bit result represented in an @ref XXH128_hash_t. */ static XXH128_hash_t XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) { /* * GCC/Clang __uint128_t method. * * On most 64-bit targets, GCC and Clang define a __uint128_t type. * This is usually the best way as it usually uses a native long 64-bit * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. * * Usually. * * Despite being a 32-bit platform, Clang (and emscripten) define this type * despite not having the arithmetic for it. This results in a laggy * compiler builtin call which calculates a full 128-bit multiply. * In that case it is best to use the portable one. * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 */ #if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ && defined(__SIZEOF_INT128__) \ || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; XXH128_hash_t r128; r128.low64 = (xxh_u64)(product); r128.high64 = (xxh_u64)(product >> 64); return r128; /* * MSVC for x64's _umul128 method. * * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); * * This compiles to single operand MUL on x64. */ #elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(_umul128) #endif xxh_u64 product_high; xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); XXH128_hash_t r128; r128.low64 = product_low; r128.high64 = product_high; return r128; /* * MSVC for ARM64's __umulh method. * * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. */ #elif defined(_M_ARM64) || defined(_M_ARM64EC) #ifndef _MSC_VER # pragma intrinsic(__umulh) #endif XXH128_hash_t r128; r128.low64 = lhs * rhs; r128.high64 = __umulh(lhs, rhs); return r128; #else /* * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. * * This is a fast and simple grade school multiply, which is shown below * with base 10 arithmetic instead of base 0x100000000. * * 9 3 // D2 lhs = 93 * x 7 5 // D2 rhs = 75 * ---------- * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 * --------- * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 * --------- * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 * * The reasons for adding the products like this are: * 1. It avoids manual carry tracking. Just like how * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. * This avoids a lot of complexity. * * 2. It hints for, and on Clang, compiles to, the powerful UMAAL * instruction available in ARM's Digital Signal Processing extension * in 32-bit ARMv6 and later, which is shown below: * * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) * { * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); * *RdHi = (xxh_u32)(product >> 32); * } * * This instruction was designed for efficient long multiplication, and * allows this to be calculated in only 4 instructions at speeds * comparable to some 64-bit ALUs. * * 3. It isn't terrible on other platforms. Usually this will be a couple * of 32-bit ADD/ADCs. */ /* First calculate all of the cross products. */ xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); /* Now add the products together. These will never overflow. */ xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); XXH128_hash_t r128; r128.low64 = lower; r128.high64 = upper; return r128; #endif } /*! * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. * * The reason for the separate function is to prevent passing too many structs * around by value. This will hopefully inline the multiply, but we don't force it. * * @param lhs , rhs The 64-bit integers to multiply * @return The low 64 bits of the product XOR'd by the high 64 bits. * @see XXH_mult64to128() */ static xxh_u64 XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) { XXH128_hash_t product = XXH_mult64to128(lhs, rhs); return product.low64 ^ product.high64; } /*! Seems to produce slightly better code on GCC for some reason. */ XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) { XXH_ASSERT(0 <= shift && shift < 64); return v64 ^ (v64 >> shift); } /* * This is a fast avalanche stage, * suitable when input bits are already partially mixed */ static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) { h64 = XXH_xorshift64(h64, 37); h64 *= PRIME_MX1; h64 = XXH_xorshift64(h64, 32); return h64; } /* * This is a stronger avalanche, * inspired by Pelle Evensen's rrmxmx * preferable when input has not been previously mixed */ static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) { /* this mix is inspired by Pelle Evensen's rrmxmx */ h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); h64 *= PRIME_MX2; h64 ^= (h64 >> 35) + len ; h64 *= PRIME_MX2; return XXH_xorshift64(h64, 28); } /* ========================================== * Short keys * ========================================== * One of the shortcomings of XXH32 and XXH64 was that their performance was * sub-optimal on short lengths. It used an iterative algorithm which strongly * favored lengths that were a multiple of 4 or 8. * * Instead of iterating over individual inputs, we use a set of single shot * functions which piece together a range of lengths and operate in constant time. * * Additionally, the number of multiplies has been significantly reduced. This * reduces latency, especially when emulating 64-bit multiplies on 32-bit. * * Depending on the platform, this may or may not be faster than XXH32, but it * is almost guaranteed to be faster than XXH64. */ /* * At very short lengths, there isn't enough input to fully hide secrets, or use * the entire secret. * * There is also only a limited amount of mixing we can do before significantly * impacting performance. * * Therefore, we use different sections of the secret and always mix two secret * samples with an XOR. This should have no effect on performance on the * seedless or withSeed variants because everything _should_ be constant folded * by modern compilers. * * The XOR mixing hides individual parts of the secret and increases entropy. * * This adds an extra layer of strength for custom secrets. */ XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(1 <= len && len <= 3); XXH_ASSERT(secret != NULL); /* * len = 1: combined = { input[0], 0x01, input[0], input[0] } * len = 2: combined = { input[1], 0x02, input[0], input[1] } * len = 3: combined = { input[2], 0x03, input[0], input[1] } */ { xxh_u8 const c1 = input[0]; xxh_u8 const c2 = input[len >> 1]; xxh_u8 const c3 = input[len - 1]; xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; return XXH64_avalanche(keyed); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(4 <= len && len <= 8); seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; { xxh_u32 const input1 = XXH_readLE32(input); xxh_u32 const input2 = XXH_readLE32(input + len - 4); xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); xxh_u64 const keyed = input64 ^ bitflip; return XXH3_rrmxmx(keyed, len); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(9 <= len && len <= 16); { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; xxh_u64 const acc = len + XXH_swap64(input_lo) + input_hi + XXH3_mul128_fold64(input_lo, input_hi); return XXH3_avalanche(acc); } } XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); if (len) return XXH3_len_1to3_64b(input, len, secret, seed); return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); } } /* * DISCLAIMER: There are known *seed-dependent* multicollisions here due to * multiplication by zero, affecting hashes of lengths 17 to 240. * * However, they are very unlikely. * * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all * unseeded non-cryptographic hashes, it does not attempt to defend itself * against specially crafted inputs, only random inputs. * * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes * cancelling out the secret is taken an arbitrary number of times (addressed * in XXH3_accumulate_512), this collision is very unlikely with random inputs * and/or proper seeding: * * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a * function that is only called up to 16 times per hash with up to 240 bytes of * input. * * This is not too bad for a non-cryptographic hash function, especially with * only 64 bit outputs. * * The 128-bit variant (which trades some speed for strength) is NOT affected * by this, although it is always a good idea to use a proper seed if you care * about strength. */ XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) { #if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ /* * UGLY HACK: * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in * slower code. * * By forcing seed64 into a register, we disrupt the cost model and * cause it to scalarize. See `XXH32_round()` * * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on * GCC 9.2, despite both emitting scalar code. * * GCC generates much better scalar code than Clang for the rest of XXH3, * which is why finding a more optimal codepath is an interest. */ XXH_COMPILER_GUARD(seed64); #endif { xxh_u64 const input_lo = XXH_readLE64(input); xxh_u64 const input_hi = XXH_readLE64(input+8); return XXH3_mul128_fold64( input_lo ^ (XXH_readLE64(secret) + seed64), input_hi ^ (XXH_readLE64(secret+8) - seed64) ); } } /* For mid range keys, XXH3 uses a Mum-hash variant. */ XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(16 < len && len <= 128); { xxh_u64 acc = len * XXH_PRIME64_1; #if XXH_SIZE_OPT >= 1 /* Smaller and cleaner, but slightly slower. */ unsigned int i = (unsigned int)(len - 1) / 32; do { acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); } while (i-- != 0); #else if (len > 32) { if (len > 64) { if (len > 96) { acc += XXH3_mix16B(input+48, secret+96, seed); acc += XXH3_mix16B(input+len-64, secret+112, seed); } acc += XXH3_mix16B(input+32, secret+64, seed); acc += XXH3_mix16B(input+len-48, secret+80, seed); } acc += XXH3_mix16B(input+16, secret+32, seed); acc += XXH3_mix16B(input+len-32, secret+48, seed); } acc += XXH3_mix16B(input+0, secret+0, seed); acc += XXH3_mix16B(input+len-16, secret+16, seed); #endif return XXH3_avalanche(acc); } } #define XXH3_MIDSIZE_MAX 240 XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); #define XXH3_MIDSIZE_STARTOFFSET 3 #define XXH3_MIDSIZE_LASTOFFSET 17 { xxh_u64 acc = len * XXH_PRIME64_1; xxh_u64 acc_end; unsigned int const nbRounds = (unsigned int)len / 16; unsigned int i; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); for (i=0; i<8; i++) { acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); } /* last bytes */ acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); XXH_ASSERT(nbRounds >= 8); acc = XXH3_avalanche(acc); #if defined(__clang__) /* Clang */ \ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ /* * UGLY HACK: * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. * In everywhere else, it uses scalar code. * * For 64->128-bit multiplies, even if the NEON was 100% optimal, it * would still be slower than UMAAL (see XXH_mult64to128). * * Unfortunately, Clang doesn't handle the long multiplies properly and * converts them to the nonexistent "vmulq_u64" intrinsic, which is then * scalarized into an ugly mess of VMOV.32 instructions. * * This mess is difficult to avoid without turning autovectorization * off completely, but they are usually relatively minor and/or not * worth it to fix. * * This loop is the easiest to fix, as unlike XXH32, this pragma * _actually works_ because it is a loop vectorization instead of an * SLP vectorization. */ #pragma clang loop vectorize(disable) #endif for (i=8 ; i < nbRounds; i++) { /* * Prevents clang for unrolling the acc loop and interleaving with this one. */ XXH_COMPILER_GUARD(acc); acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); } return XXH3_avalanche(acc + acc_end); } } /* ======= Long Keys ======= */ #define XXH_STRIPE_LEN 64 #define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ #define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) #ifdef XXH_OLD_NAMES # define STRIPE_LEN XXH_STRIPE_LEN # define ACC_NB XXH_ACC_NB #endif #ifndef XXH_PREFETCH_DIST # ifdef __clang__ # define XXH_PREFETCH_DIST 320 # else # if (XXH_VECTOR == XXH_AVX512) # define XXH_PREFETCH_DIST 512 # else # define XXH_PREFETCH_DIST 384 # endif # endif /* __clang__ */ #endif /* XXH_PREFETCH_DIST */ /* * These macros are to generate an XXH3_accumulate() function. * The two arguments select the name suffix and target attribute. * * The name of this symbol is XXH3_accumulate_() and it calls * XXH3_accumulate_512_(). * * It may be useful to hand implement this function if the compiler fails to * optimize the inline function. */ #define XXH3_ACCUMULATE_TEMPLATE(name) \ void \ XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ const xxh_u8* XXH_RESTRICT input, \ const xxh_u8* XXH_RESTRICT secret, \ size_t nbStripes) \ { \ size_t n; \ for (n = 0; n < nbStripes; n++ ) { \ const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ XXH3_accumulate_512_##name( \ acc, \ in, \ secret + n*XXH_SECRET_CONSUME_RATE); \ } \ } XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) { if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); XXH_memcpy(dst, &v64, sizeof(v64)); } /* Several intrinsic functions below are supposed to accept __int64 as argument, * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . * However, several environments do not define __int64 type, * requiring a workaround. */ #if !defined (__VMS) \ && (defined (__cplusplus) \ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) typedef int64_t xxh_i64; #else /* the following type must have a width of 64-bit */ typedef long long xxh_i64; #endif /* * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. * * It is a hardened version of UMAC, based off of FARSH's implementation. * * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD * implementations, and it is ridiculously fast. * * We harden it by mixing the original input to the accumulators as well as the product. * * This means that in the (relatively likely) case of a multiply by zero, the * original input is preserved. * * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve * cross-pollination, as otherwise the upper and lower halves would be * essentially independent. * * This doesn't matter on 64-bit hashes since they all get merged together in * the end, so we skip the extra step. * * Both XXH3_64bits and XXH3_128bits use this subroutine. */ #if (XXH_VECTOR == XXH_AVX512) \ || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) #ifndef XXH_TARGET_AVX512 # define XXH_TARGET_AVX512 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { __m512i* const xacc = (__m512i *) acc; XXH_ASSERT((((size_t)acc) & 63) == 0); XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); { /* data_vec = input[0]; */ __m512i const data_vec = _mm512_loadu_si512 (input); /* key_vec = secret[0]; */ __m512i const key_vec = _mm512_loadu_si512 (secret); /* data_key = data_vec ^ key_vec; */ __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); /* xacc[0] += swap(data_vec); */ __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); __m512i const sum = _mm512_add_epi64(*xacc, data_swap); /* xacc[0] += product; */ *xacc = _mm512_add_epi64(product, sum); } } XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) /* * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. * * Multiplication isn't perfect, as explained by Google in HighwayHash: * * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to * // varying degrees. In descending order of goodness, bytes * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. * // As expected, the upper and lower bytes are much worse. * * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 * * Since our algorithm uses a pseudorandom secret to add some variance into the * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. * * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid * extraction. * * Both XXH3_64bits and XXH3_128bits use this subroutine. */ XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 63) == 0); XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); { __m512i* const xacc = (__m512i*) acc; const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); /* xacc[0] ^= (xacc[0] >> 47) */ __m512i const acc_vec = *xacc; __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); /* xacc[0] ^= secret; */ __m512i const key_vec = _mm512_loadu_si512 (secret); __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); /* xacc[0] *= XXH_PRIME32_1; */ __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); } } XXH_FORCE_INLINE XXH_TARGET_AVX512 void XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); XXH_ASSERT(((size_t)customSecret & 63) == 0); (void)(&XXH_writeLE64); { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); __m512i* const dest = ( __m512i*) customSecret; int i; XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ XXH_ASSERT(((size_t)dest & 63) == 0); for (i=0; i < nbRounds; ++i) { dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); } } } #endif #if (XXH_VECTOR == XXH_AVX2) \ || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) #ifndef XXH_TARGET_AVX2 # define XXH_TARGET_AVX2 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 31) == 0); { __m256i* const xacc = (__m256i *) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xinput = (const __m256i *) input; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xsecret = (const __m256i *) secret; size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { /* data_vec = xinput[i]; */ __m256i const data_vec = _mm256_loadu_si256 (xinput+i); /* key_vec = xsecret[i]; */ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); /* data_key = data_vec ^ key_vec; */ __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); /* xacc[i] += product; */ xacc[i] = _mm256_add_epi64(product, sum); } } } XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 31) == 0); { __m256i* const xacc = (__m256i*) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ const __m256i* const xsecret = (const __m256i *) secret; const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { /* xacc[i] ^= (xacc[i] >> 47) */ __m256i const acc_vec = xacc[i]; __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); /* xacc[i] ^= xsecret; */ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); } } } XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); (void)(&XXH_writeLE64); XXH_PREFETCH(customSecret); { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); __m256i* dest = ( __m256i*) customSecret; # if defined(__GNUC__) || defined(__clang__) /* * On GCC & Clang, marking 'dest' as modified will cause the compiler: * - do not extract the secret from sse registers in the internal loop * - use less common registers, and avoid pushing these reg into stack */ XXH_COMPILER_GUARD(dest); # endif XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ XXH_ASSERT(((size_t)dest & 31) == 0); /* GCC -O2 need unroll loop manually */ dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); } } #endif /* x86dispatch always generates SSE2 */ #if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) #ifndef XXH_TARGET_SSE2 # define XXH_TARGET_SSE2 /* disable attribute target */ #endif XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { /* SSE2 is just a half-scale version of the AVX2 version. */ XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i *) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xinput = (const __m128i *) input; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xsecret = (const __m128i *) secret; size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { /* data_vec = xinput[i]; */ __m128i const data_vec = _mm_loadu_si128 (xinput+i); /* key_vec = xsecret[i]; */ __m128i const key_vec = _mm_loadu_si128 (xsecret+i); /* data_key = data_vec ^ key_vec; */ __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); /* data_key_lo = data_key >> 32; */ __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); /* xacc[i] += swap(data_vec); */ __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); __m128i const sum = _mm_add_epi64(xacc[i], data_swap); /* xacc[i] += product; */ xacc[i] = _mm_add_epi64(product, sum); } } } XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { __m128i* const xacc = (__m128i*) acc; /* Unaligned. This is mainly for pointer arithmetic, and because * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ const __m128i* const xsecret = (const __m128i *) secret; const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); size_t i; for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { /* xacc[i] ^= (xacc[i] >> 47) */ __m128i const acc_vec = xacc[i]; __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ __m128i const key_vec = _mm_loadu_si128 (xsecret+i); __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1; */ __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); } } } XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); (void)(&XXH_writeLE64); { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); # if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); # else __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); # endif int i; const void* const src16 = XXH3_kSecret; __m128i* dst16 = (__m128i*) customSecret; # if defined(__GNUC__) || defined(__clang__) /* * On GCC & Clang, marking 'dest' as modified will cause the compiler: * - do not extract the secret from sse registers in the internal loop * - use less common registers, and avoid pushing these reg into stack */ XXH_COMPILER_GUARD(dst16); # endif XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ XXH_ASSERT(((size_t)dst16 & 15) == 0); for (i=0; i < nbRounds; ++i) { dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); } } } #endif #if (XXH_VECTOR == XXH_NEON) /* forward declarations for the scalar routines */ XXH_FORCE_INLINE void XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, void const* XXH_RESTRICT secret, size_t lane); XXH_FORCE_INLINE void XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT secret, size_t lane); /*! * @internal * @brief The bulk processing loop for NEON and WASM SIMD128. * * The NEON code path is actually partially scalar when running on AArch64. This * is to optimize the pipelining and can have up to 15% speedup depending on the * CPU, and it also mitigates some GCC codegen issues. * * @see XXH3_NEON_LANES for configuring this and details about this optimization. * * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit * integers instead of the other platforms which mask full 64-bit vectors, * so the setup is more complicated than just shifting right. * * Additionally, there is an optimization for 4 lanes at once noted below. * * Since, as stated, the most optimal amount of lanes for Cortexes is 6, * there needs to be *three* versions of the accumulate operation used * for the remaining 2 lanes. * * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap * nearly perfectly. */ XXH_FORCE_INLINE void XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); { /* GCC for darwin arm64 does not like aliasing here */ xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ uint8_t const* xinput = (const uint8_t *) input; uint8_t const* xsecret = (const uint8_t *) secret; size_t i; #ifdef __wasm_simd128__ /* * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret * is constant propagated, which results in it converting it to this * inside the loop: * * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) * ... * * This requires a full 32-bit address immediate (and therefore a 6 byte * instruction) as well as an add for each offset. * * Putting an asm guard prevents it from folding (at the cost of losing * the alignment hint), and uses the free offset in `v128.load` instead * of adding secret_offset each time which overall reduces code size by * about a kilobyte and improves performance. */ XXH_COMPILER_GUARD(xsecret); #endif /* Scalar lanes use the normal scalarRound routine */ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { XXH3_scalarRound(acc, input, secret, i); } i = 0; /* 4 NEON lanes at a time. */ for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { /* data_vec = xinput[i]; */ uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); /* key_vec = xsecret[i]; */ uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); /* data_swap = swap(data_vec) */ uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); /* data_key = data_vec ^ key_vec; */ uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); /* * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to * get one vector with the low 32 bits of each lane, and one vector * with the high 32 bits of each lane. * * The intrinsic returns a double vector because the original ARMv7-a * instruction modified both arguments in place. AArch64 and SIMD128 emit * two instructions from this intrinsic. * * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] */ uint32x4x2_t unzipped = vuzpq_u32( vreinterpretq_u32_u64(data_key_1), vreinterpretq_u32_u64(data_key_2) ); /* data_key_lo = data_key & 0xFFFFFFFF */ uint32x4_t data_key_lo = unzipped.val[0]; /* data_key_hi = data_key >> 32 */ uint32x4_t data_key_hi = unzipped.val[1]; /* * Then, we can split the vectors horizontally and multiply which, as for most * widening intrinsics, have a variant that works on both high half vectors * for free on AArch64. A similar instruction is available on SIMD128. * * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi */ uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); /* * Clang reorders * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s * c += a; // add acc.2d, acc.2d, swap.2d * to * c += a; // add acc.2d, acc.2d, swap.2d * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s * * While it would make sense in theory since the addition is faster, * for reasons likely related to umlal being limited to certain NEON * pipelines, this is worse. A compiler guard fixes this. */ XXH_COMPILER_GUARD_CLANG_NEON(sum_1); XXH_COMPILER_GUARD_CLANG_NEON(sum_2); /* xacc[i] = acc_vec + sum; */ xacc[i] = vaddq_u64(xacc[i], sum_1); xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); } /* Operate on the remaining NEON lanes 2 at a time. */ for (; i < XXH3_NEON_LANES / 2; i++) { /* data_vec = xinput[i]; */ uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); /* key_vec = xsecret[i]; */ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); /* acc_vec_2 = swap(data_vec) */ uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); /* data_key = data_vec ^ key_vec; */ uint64x2_t data_key = veorq_u64(data_vec, key_vec); /* For two lanes, just use VMOVN and VSHRN. */ /* data_key_lo = data_key & 0xFFFFFFFF; */ uint32x2_t data_key_lo = vmovn_u64(data_key); /* data_key_hi = data_key >> 32; */ uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); /* Same Clang workaround as before */ XXH_COMPILER_GUARD_CLANG_NEON(sum); /* xacc[i] = acc_vec + sum; */ xacc[i] = vaddq_u64 (xacc[i], sum); } } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) XXH_FORCE_INLINE void XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; uint8_t const* xsecret = (uint8_t const*) secret; size_t i; /* WASM uses operator overloads and doesn't need these. */ #ifndef __wasm_simd128__ /* { prime32_1, prime32_1 } */ uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); /* { 0, prime32_1, 0, prime32_1 } */ uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); #endif /* AArch64 uses both scalar and neon at the same time */ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { XXH3_scalarScrambleRound(acc, secret, i); } for (i=0; i < XXH3_NEON_LANES / 2; i++) { /* xacc[i] ^= (xacc[i] >> 47); */ uint64x2_t acc_vec = xacc[i]; uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); uint64x2_t data_vec = veorq_u64(acc_vec, shifted); /* xacc[i] ^= xsecret[i]; */ uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); uint64x2_t data_key = veorq_u64(data_vec, key_vec); /* xacc[i] *= XXH_PRIME32_1 */ #ifdef __wasm_simd128__ /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ xacc[i] = data_key * XXH_PRIME32_1; #else /* * Expanded version with portable NEON intrinsics * * lo(x) * lo(y) + (hi(x) * lo(y) << 32) * * prod_hi = hi(data_key) * lo(prime) << 32 * * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits * and avoid the shift. */ uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); /* Extract low bits for vmlal_u32 */ uint32x2_t data_key_lo = vmovn_u64(data_key); /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); #endif } } } #endif #if (XXH_VECTOR == XXH_VSX) XXH_FORCE_INLINE void XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { /* presumed aligned */ xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ xxh_u64x2 const v32 = { 32, 32 }; size_t i; for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { /* data_vec = xinput[i]; */ xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); /* key_vec = xsecret[i]; */ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* shuffled = (data_key << 32) | (data_key >> 32); */ xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); /* acc_vec = xacc[i]; */ xxh_u64x2 acc_vec = xacc[i]; acc_vec += product; /* swap high and low halves */ #ifdef __s390x__ acc_vec += vec_permi(data_vec, data_vec, 2); #else acc_vec += vec_xxpermdi(data_vec, data_vec, 2); #endif xacc[i] = acc_vec; } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) XXH_FORCE_INLINE void XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { XXH_ASSERT((((size_t)acc) & 15) == 0); { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; const xxh_u8* const xsecret = (const xxh_u8*) secret; /* constants */ xxh_u64x2 const v32 = { 32, 32 }; xxh_u64x2 const v47 = { 47, 47 }; xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; size_t i; for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { /* xacc[i] ^= (xacc[i] >> 47); */ xxh_u64x2 const acc_vec = xacc[i]; xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); /* xacc[i] ^= xsecret[i]; */ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); xxh_u64x2 const data_key = data_vec ^ key_vec; /* xacc[i] *= XXH_PRIME32_1 */ /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); xacc[i] = prod_odd + (prod_even << v32); } } } #endif #if (XXH_VECTOR == XXH_SVE) XXH_FORCE_INLINE void XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { uint64_t *xacc = (uint64_t *)acc; const uint64_t *xinput = (const uint64_t *)(const void *)input; const uint64_t *xsecret = (const uint64_t *)(const void *)secret; svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); uint64_t element_count = svcntd(); if (element_count >= 8) { svbool_t mask = svptrue_pat_b64(SV_VL8); svuint64_t vacc = svld1_u64(mask, xacc); ACCRND(vacc, 0); svst1_u64(mask, xacc, vacc); } else if (element_count == 2) { /* sve128 */ svbool_t mask = svptrue_pat_b64(SV_VL2); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 2); svuint64_t acc2 = svld1_u64(mask, xacc + 4); svuint64_t acc3 = svld1_u64(mask, xacc + 6); ACCRND(acc0, 0); ACCRND(acc1, 2); ACCRND(acc2, 4); ACCRND(acc3, 6); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 2, acc1); svst1_u64(mask, xacc + 4, acc2); svst1_u64(mask, xacc + 6, acc3); } else { svbool_t mask = svptrue_pat_b64(SV_VL4); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 4); ACCRND(acc0, 0); ACCRND(acc1, 4); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 4, acc1); } } XXH_FORCE_INLINE void XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT input, const xxh_u8* XXH_RESTRICT secret, size_t nbStripes) { if (nbStripes != 0) { uint64_t *xacc = (uint64_t *)acc; const uint64_t *xinput = (const uint64_t *)(const void *)input; const uint64_t *xsecret = (const uint64_t *)(const void *)secret; svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); uint64_t element_count = svcntd(); if (element_count >= 8) { svbool_t mask = svptrue_pat_b64(SV_VL8); svuint64_t vacc = svld1_u64(mask, xacc + 0); do { /* svprfd(svbool_t, void *, enum svfprop); */ svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(vacc, 0); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, vacc); } else if (element_count == 2) { /* sve128 */ svbool_t mask = svptrue_pat_b64(SV_VL2); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 2); svuint64_t acc2 = svld1_u64(mask, xacc + 4); svuint64_t acc3 = svld1_u64(mask, xacc + 6); do { svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(acc0, 0); ACCRND(acc1, 2); ACCRND(acc2, 4); ACCRND(acc3, 6); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 2, acc1); svst1_u64(mask, xacc + 4, acc2); svst1_u64(mask, xacc + 6, acc3); } else { svbool_t mask = svptrue_pat_b64(SV_VL4); svuint64_t acc0 = svld1_u64(mask, xacc + 0); svuint64_t acc1 = svld1_u64(mask, xacc + 4); do { svprfd(mask, xinput + 128, SV_PLDL1STRM); ACCRND(acc0, 0); ACCRND(acc1, 4); xinput += 8; xsecret += 1; nbStripes--; } while (nbStripes != 0); svst1_u64(mask, xacc + 0, acc0); svst1_u64(mask, xacc + 4, acc1); } } } #endif /* scalar variants - universal */ #if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) /* * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they * emit an excess mask and a full 64-bit multiply-add (MADD X-form). * * While this might not seem like much, as AArch64 is a 64-bit architecture, only * big Cortex designs have a full 64-bit multiplier. * * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit * multiplies expand to 2-3 multiplies in microcode. This has a major penalty * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. * * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does * not have this penalty and does the mask automatically. */ XXH_FORCE_INLINE xxh_u64 XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) { xxh_u64 ret; /* note: %x = 64-bit register, %w = 32-bit register */ __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); return ret; } #else XXH_FORCE_INLINE xxh_u64 XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) { return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; } #endif /*! * @internal * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). * * This is extracted to its own function because the NEON path uses a combination * of NEON and scalar. */ XXH_FORCE_INLINE void XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, void const* XXH_RESTRICT secret, size_t lane) { xxh_u64* xacc = (xxh_u64*) acc; xxh_u8 const* xinput = (xxh_u8 const*) input; xxh_u8 const* xsecret = (xxh_u8 const*) secret; XXH_ASSERT(lane < XXH_ACC_NB); XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); { xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); } } /*! * @internal * @brief Processes a 64 byte block of data using the scalar path. */ XXH_FORCE_INLINE void XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT input, const void* XXH_RESTRICT secret) { size_t i; /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ #if defined(__GNUC__) && !defined(__clang__) \ && (defined(__arm__) || defined(__thumb2__)) \ && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ && XXH_SIZE_OPT <= 0 # pragma GCC unroll 8 #endif for (i=0; i < XXH_ACC_NB; i++) { XXH3_scalarRound(acc, input, secret, i); } } XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) /*! * @internal * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). * * This is extracted to its own function because the NEON path uses a combination * of NEON and scalar. */ XXH_FORCE_INLINE void XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT secret, size_t lane) { xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); XXH_ASSERT(lane < XXH_ACC_NB); { xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); xxh_u64 acc64 = xacc[lane]; acc64 = XXH_xorshift64(acc64, 47); acc64 ^= key64; acc64 *= XXH_PRIME32_1; xacc[lane] = acc64; } } /*! * @internal * @brief Scrambles the accumulators after a large chunk has been read */ XXH_FORCE_INLINE void XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) { size_t i; for (i=0; i < XXH_ACC_NB; i++) { XXH3_scalarScrambleRound(acc, secret, i); } } XXH_FORCE_INLINE void XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) { /* * We need a separate pointer for the hack below, * which requires a non-const pointer. * Any decent compiler will optimize this out otherwise. */ const xxh_u8* kSecretPtr = XXH3_kSecret; XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); #if defined(__GNUC__) && defined(__aarch64__) /* * UGLY HACK: * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are * placed sequentially, in order, at the top of the unrolled loop. * * While MOVK is great for generating constants (2 cycles for a 64-bit * constant compared to 4 cycles for LDR), it fights for bandwidth with * the arithmetic instructions. * * I L S * MOVK * MOVK * MOVK * MOVK * ADD * SUB STR * STR * By forcing loads from memory (as the asm line causes the compiler to assume * that XXH3_kSecretPtr has been changed), the pipelines are used more * efficiently: * I L S * LDR * ADD LDR * SUB STR * STR * * See XXH3_NEON_LANES for details on the pipsline. * * XXH3_64bits_withSeed, len == 256, Snapdragon 835 * without hack: 2654.4 MB/s * with hack: 3202.9 MB/s */ XXH_COMPILER_GUARD(kSecretPtr); #endif { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; int i; for (i=0; i < nbRounds; i++) { /* * The asm hack causes the compiler to assume that kSecretPtr aliases with * customSecret, and on aarch64, this prevented LDP from merging two * loads together for free. Putting the loads together before the stores * properly generates LDP. */ xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); } } } typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); #if (XXH_VECTOR == XXH_AVX512) #define XXH3_accumulate_512 XXH3_accumulate_512_avx512 #define XXH3_accumulate XXH3_accumulate_avx512 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 #elif (XXH_VECTOR == XXH_AVX2) #define XXH3_accumulate_512 XXH3_accumulate_512_avx2 #define XXH3_accumulate XXH3_accumulate_avx2 #define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 #define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 #elif (XXH_VECTOR == XXH_SSE2) #define XXH3_accumulate_512 XXH3_accumulate_512_sse2 #define XXH3_accumulate XXH3_accumulate_sse2 #define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 #define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 #elif (XXH_VECTOR == XXH_NEON) #define XXH3_accumulate_512 XXH3_accumulate_512_neon #define XXH3_accumulate XXH3_accumulate_neon #define XXH3_scrambleAcc XXH3_scrambleAcc_neon #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_VSX) #define XXH3_accumulate_512 XXH3_accumulate_512_vsx #define XXH3_accumulate XXH3_accumulate_vsx #define XXH3_scrambleAcc XXH3_scrambleAcc_vsx #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #elif (XXH_VECTOR == XXH_SVE) #define XXH3_accumulate_512 XXH3_accumulate_512_sve #define XXH3_accumulate XXH3_accumulate_sve #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #else /* scalar */ #define XXH3_accumulate_512 XXH3_accumulate_512_scalar #define XXH3_accumulate XXH3_accumulate_scalar #define XXH3_scrambleAcc XXH3_scrambleAcc_scalar #define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #endif #if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ # undef XXH3_initCustomSecret # define XXH3_initCustomSecret XXH3_initCustomSecret_scalar #endif XXH_FORCE_INLINE void XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; size_t const nb_blocks = (len - 1) / block_len; size_t n; XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); for (n = 0; n < nb_blocks; n++) { f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); } /* last partial block */ XXH_ASSERT(len > XXH_STRIPE_LEN); { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); /* last stripe */ { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; #define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); } } } XXH_FORCE_INLINE xxh_u64 XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) { return XXH3_mul128_fold64( acc[0] ^ XXH_readLE64(secret), acc[1] ^ XXH_readLE64(secret+8) ); } static XXH64_hash_t XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) { xxh_u64 result64 = start; size_t i = 0; for (i = 0; i < 4; i++) { result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); #if defined(__clang__) /* Clang */ \ && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ /* * UGLY HACK: * Prevent autovectorization on Clang ARMv7-a. Exact same problem as * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. * XXH3_64bits, len == 256, Snapdragon 835: * without hack: 2063.7 MB/s * with hack: 2560.7 MB/s */ XXH_COMPILER_GUARD(result64); #endif } return XXH3_avalanche(result64); } #define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, const void* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); /* do not align on 8, so that the secret is different from the accumulator */ #define XXH_SECRET_MERGEACCS_START 11 XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); } /* * It's important for performance to transmit secret's size (when it's static) * so that the compiler can properly optimize the vectorized loop. * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH64_hash_t XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); } /* * It's preferable for performance that XXH3_hashLong is not inlined, * as it results in a smaller function for small data, easier to the instruction cache. * Note that inside this no_inline function, we do inline the internal loop, * and provide a statically defined secret size to allow optimization of vector loop. */ XXH_NO_INLINE XXH_PUREF XXH64_hash_t XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); } /* * XXH3_hashLong_64b_withSeed(): * Generate a custom key based on alteration of default XXH3_kSecret with the seed, * and then use this key for long mode hashing. * * This operation is decently fast but nonetheless costs a little bit of time. * Try to avoid it whenever possible (typically when seed==0). * * It's important for performance that XXH3_hashLong is not inlined. Not sure * why (uop cache maybe?), but the difference is large and easily measurable. */ XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, XXH64_hash_t seed, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { #if XXH_SIZE_OPT <= 0 if (seed == 0) return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), f_acc, f_scramble); #endif { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed); return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), f_acc, f_scramble); } } /* * It's important for performance that XXH3_hashLong is not inlined. */ XXH_NO_INLINE XXH64_hash_t XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) { (void)secret; (void)secretLen; return XXH3_hashLong_64b_withSeed_internal(input, len, seed, XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); XXH_FORCE_INLINE XXH64_hash_t XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, XXH3_hashLong64_f f_hashLong) { XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); /* * If an action is to be taken if `secretLen` condition is not respected, * it should be done here. * For now, it's a contract pre-condition. * Adding a check and a branch here would cost performance at every hash. * Also, note that function signature doesn't offer room to return an error. */ if (len <= 16) return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); if (len <= 128) return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); if (len <= XXH3_MIDSIZE_MAX) return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); } /* === Public entry point === */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) { return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) { return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); } XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { if (length <= XXH3_MIDSIZE_MAX) return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); } /* === XXH3 streaming === */ #ifndef XXH_NO_STREAM /* * Malloc's a pointer that is always aligned to align. * * This must be freed with `XXH_alignedFree()`. * * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. * * This underalignment previously caused a rather obvious crash which went * completely unnoticed due to XXH3_createState() not actually being tested. * Credit to RedSpah for noticing this bug. * * The alignment is done manually: Functions like posix_memalign or _mm_malloc * are avoided: To maintain portability, we would have to write a fallback * like this anyways, and besides, testing for the existence of library * functions without relying on external build tools is impossible. * * The method is simple: Overallocate, manually align, and store the offset * to the original behind the returned pointer. * * Align must be a power of 2 and 8 <= align <= 128. */ static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) { XXH_ASSERT(align <= 128 && align >= 8); /* range check */ XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ { /* Overallocate to make room for manual realignment and an offset byte */ xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); if (base != NULL) { /* * Get the offset needed to align this pointer. * * Even if the returned pointer is aligned, there will always be * at least one byte to store the offset to the original pointer. */ size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ /* Add the offset for the now-aligned pointer */ xxh_u8* ptr = base + offset; XXH_ASSERT((size_t)ptr % align == 0); /* Store the offset immediately before the returned pointer. */ ptr[-1] = (xxh_u8)offset; return ptr; } return NULL; } } /* * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. */ static void XXH_alignedFree(void* p) { if (p != NULL) { xxh_u8* ptr = (xxh_u8*)p; /* Get the offset byte we added in XXH_malloc. */ xxh_u8 offset = ptr[-1]; /* Free the original malloc'd pointer */ xxh_u8* base = ptr - offset; XXH_free(base); } } /*! @ingroup XXH3_family */ /*! * @brief Allocate an @ref XXH3_state_t. * * Must be freed with XXH3_freeState(). * @return An allocated XXH3_state_t on success, `NULL` on failure. */ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) { XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); if (state==NULL) return NULL; XXH3_INITSTATE(state); return state; } /*! @ingroup XXH3_family */ /*! * @brief Frees an @ref XXH3_state_t. * * Must be allocated with XXH3_createState(). * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). * @return XXH_OK. */ XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) { XXH_alignedFree(statePtr); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) { XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); } static void XXH3_reset_internal(XXH3_state_t* statePtr, XXH64_hash_t seed, const void* secret, size_t secretSize) { size_t const initStart = offsetof(XXH3_state_t, bufferedSize); size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); XXH_ASSERT(statePtr != NULL); /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ memset((char*)statePtr + initStart, 0, initLength); statePtr->acc[0] = XXH_PRIME32_3; statePtr->acc[1] = XXH_PRIME64_1; statePtr->acc[2] = XXH_PRIME64_2; statePtr->acc[3] = XXH_PRIME64_3; statePtr->acc[4] = XXH_PRIME64_4; statePtr->acc[5] = XXH_PRIME32_2; statePtr->acc[6] = XXH_PRIME64_5; statePtr->acc[7] = XXH_PRIME32_1; statePtr->seed = seed; statePtr->useSeed = (seed != 0); statePtr->extSecret = (const unsigned char*)secret; XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { if (statePtr == NULL) return XXH_ERROR; XXH3_reset_internal(statePtr, 0, secret, secretSize); if (secret == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { if (statePtr == NULL) return XXH_ERROR; if (seed==0) return XXH3_64bits_reset(statePtr); if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) XXH3_initCustomSecret(statePtr->customSecret, seed); XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) { if (statePtr == NULL) return XXH_ERROR; if (secret == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; XXH3_reset_internal(statePtr, seed64, secret, secretSize); statePtr->useSeed = 1; /* always, even if seed64==0 */ return XXH_OK; } /*! * @internal * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). * * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. * * @param acc Pointer to the 8 accumulator lanes * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* * @param nbStripesPerBlock Number of stripes in a block * @param input Input pointer * @param nbStripes Number of stripes to process * @param secret Secret pointer * @param secretLimit Offset of the last block in @p secret * @param f_acc Pointer to an XXH3_accumulate implementation * @param f_scramble Pointer to an XXH3_scrambleAcc implementation * @return Pointer past the end of @p input after processing */ XXH_FORCE_INLINE const xxh_u8 * XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, const xxh_u8* XXH_RESTRICT input, size_t nbStripes, const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; /* Process full blocks */ if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { /* Process the initial partial block... */ size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; do { /* Accumulate and scramble */ f_acc(acc, input, initialSecret, nbStripesThisIter); f_scramble(acc, secret + secretLimit); input += nbStripesThisIter * XXH_STRIPE_LEN; nbStripes -= nbStripesThisIter; /* Then continue the loop with the full block size */ nbStripesThisIter = nbStripesPerBlock; initialSecret = secret; } while (nbStripes >= nbStripesPerBlock); *nbStripesSoFarPtr = 0; } /* Process a partial block */ if (nbStripes > 0) { f_acc(acc, input, initialSecret, nbStripes); input += nbStripes * XXH_STRIPE_LEN; *nbStripesSoFarPtr += nbStripes; } /* Return end pointer */ return input; } #ifndef XXH3_STREAM_USE_STACK # if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ # define XXH3_STREAM_USE_STACK 1 # endif #endif /* * Both XXH3_64bits_update and XXH3_128bits_update use this routine. */ XXH_FORCE_INLINE XXH_errorcode XXH3_update(XXH3_state_t* XXH_RESTRICT const state, const xxh_u8* XXH_RESTRICT input, size_t len, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { if (input==NULL) { XXH_ASSERT(len == 0); return XXH_OK; } XXH_ASSERT(state != NULL); { const xxh_u8* const bEnd = input + len; const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; #if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 /* For some reason, gcc and MSVC seem to suffer greatly * when operating accumulators directly into state. * Operating into stack space seems to enable proper optimization. * clang, on the other hand, doesn't seem to need this trick */ XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; XXH_memcpy(acc, state->acc, sizeof(acc)); #else xxh_u64* XXH_RESTRICT const acc = state->acc; #endif state->totalLen += len; XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); /* small input : just fill in tmp buffer */ if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { XXH_memcpy(state->buffer + state->bufferedSize, input, len); state->bufferedSize += (XXH32_hash_t)len; return XXH_OK; } /* total input is now > XXH3_INTERNALBUFFER_SIZE */ #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ /* * Internal buffer is partially filled (always, except at beginning) * Complete it, then consume it. */ if (state->bufferedSize) { size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); input += loadSize; XXH3_consumeStripes(acc, &state->nbStripesSoFar, state->nbStripesPerBlock, state->buffer, XXH3_INTERNALBUFFER_STRIPES, secret, state->secretLimit, f_acc, f_scramble); state->bufferedSize = 0; } XXH_ASSERT(input < bEnd); if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; input = XXH3_consumeStripes(acc, &state->nbStripesSoFar, state->nbStripesPerBlock, input, nbStripes, secret, state->secretLimit, f_acc, f_scramble); XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); } /* Some remaining input (always) : buffer it */ XXH_ASSERT(input < bEnd); XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); XXH_ASSERT(state->bufferedSize == 0); XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); state->bufferedSize = (XXH32_hash_t)(bEnd-input); #if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 /* save stack accumulators into state */ XXH_memcpy(state->acc, acc, sizeof(acc)); #endif } return XXH_OK; } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { return XXH3_update(state, (const xxh_u8*)input, len, XXH3_accumulate, XXH3_scrambleAcc); } XXH_FORCE_INLINE void XXH3_digest_long (XXH64_hash_t* acc, const XXH3_state_t* state, const unsigned char* secret) { xxh_u8 lastStripe[XXH_STRIPE_LEN]; const xxh_u8* lastStripePtr; /* * Digest on a local copy. This way, the state remains unaltered, and it can * continue ingesting more input afterwards. */ XXH_memcpy(acc, state->acc, sizeof(state->acc)); if (state->bufferedSize >= XXH_STRIPE_LEN) { /* Consume remaining stripes then point to remaining data in buffer */ size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; size_t nbStripesSoFar = state->nbStripesSoFar; XXH3_consumeStripes(acc, &nbStripesSoFar, state->nbStripesPerBlock, state->buffer, nbStripes, secret, state->secretLimit, XXH3_accumulate, XXH3_scrambleAcc); lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; } else { /* bufferedSize < XXH_STRIPE_LEN */ /* Copy to temp buffer */ size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); lastStripePtr = lastStripe; } /* Last stripe */ XXH3_accumulate_512(acc, lastStripePtr, secret + state->secretLimit - XXH_SECRET_LASTACC_START); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)state->totalLen * XXH_PRIME64_1); } /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ if (state->useSeed) return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } #endif /* !XXH_NO_STREAM */ /* ========================================== * XXH3 128 bits (a.k.a XXH128) * ========================================== * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, * even without counting the significantly larger output size. * * For example, extra steps are taken to avoid the seed-dependent collisions * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). * * This strength naturally comes at the cost of some speed, especially on short * lengths. Note that longer hashes are about as fast as the 64-bit version * due to it using only a slight modification of the 64-bit loop. * * XXH128 is also more oriented towards 64-bit machines. It is still extremely * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). */ XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { /* A doubled version of 1to3_64b with different constants. */ XXH_ASSERT(input != NULL); XXH_ASSERT(1 <= len && len <= 3); XXH_ASSERT(secret != NULL); /* * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } */ { xxh_u8 const c1 = input[0]; xxh_u8 const c2 = input[len >> 1]; xxh_u8 const c3 = input[len - 1]; xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; XXH128_hash_t h128; h128.low64 = XXH64_avalanche(keyed_lo); h128.high64 = XXH64_avalanche(keyed_hi); return h128; } } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(4 <= len && len <= 8); seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; { xxh_u32 const input_lo = XXH_readLE32(input); xxh_u32 const input_hi = XXH_readLE32(input + len - 4); xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; xxh_u64 const keyed = input_64 ^ bitflip; /* Shift len to the left to ensure it is even, this avoids even multiplies. */ XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); m128.high64 += (m128.low64 << 1); m128.low64 ^= (m128.high64 >> 3); m128.low64 = XXH_xorshift64(m128.low64, 35); m128.low64 *= PRIME_MX2; m128.low64 = XXH_xorshift64(m128.low64, 28); m128.high64 = XXH3_avalanche(m128.high64); return m128; } } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(input != NULL); XXH_ASSERT(secret != NULL); XXH_ASSERT(9 <= len && len <= 16); { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; xxh_u64 const input_lo = XXH_readLE64(input); xxh_u64 input_hi = XXH_readLE64(input + len - 8); XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); /* * Put len in the middle of m128 to ensure that the length gets mixed to * both the low and high bits in the 128x64 multiply below. */ m128.low64 += (xxh_u64)(len - 1) << 54; input_hi ^= bitfliph; /* * Add the high 32 bits of input_hi to the high 32 bits of m128, then * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to * the high 64 bits of m128. * * The best approach to this operation is different on 32-bit and 64-bit. */ if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ /* * 32-bit optimized version, which is more readable. * * On 32-bit, it removes an ADC and delays a dependency between the two * halves of m128.high64, but it generates an extra mask on 64-bit. */ m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); } else { /* * 64-bit optimized (albeit more confusing) version. * * Uses some properties of addition and multiplication to remove the mask: * * Let: * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) * c = XXH_PRIME32_2 * * a + (b * c) * Inverse Property: x + y - x == y * a + (b * (1 + c - 1)) * Distributive Property: x * (y + z) == (x * y) + (x * z) * a + (b * 1) + (b * (c - 1)) * Identity Property: x * 1 == x * a + b + (b * (c - 1)) * * Substitute a, b, and c: * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) * * Since input_hi.hi + input_hi.lo == input_hi, we get this: * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) */ m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); } /* m128 ^= XXH_swap64(m128 >> 64); */ m128.low64 ^= XXH_swap64(m128.high64); { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); h128.high64 += m128.high64 * XXH_PRIME64_2; h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = XXH3_avalanche(h128.high64); return h128; } } } /* * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN */ XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) { XXH_ASSERT(len <= 16); { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); if (len) return XXH3_len_1to3_128b(input, len, secret, seed); { XXH128_hash_t h128; xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); h128.low64 = XXH64_avalanche(seed ^ bitflipl); h128.high64 = XXH64_avalanche( seed ^ bitfliph); return h128; } } } /* * A bit slower than XXH3_mix16B, but handles multiply by zero better. */ XXH_FORCE_INLINE XXH128_hash_t XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, const xxh_u8* secret, XXH64_hash_t seed) { acc.low64 += XXH3_mix16B (input_1, secret+0, seed); acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); acc.high64 += XXH3_mix16B (input_2, secret+16, seed); acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); return acc; } XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(16 < len && len <= 128); { XXH128_hash_t acc; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; #if XXH_SIZE_OPT >= 1 { /* Smaller, but slightly slower. */ unsigned int i = (unsigned int)(len - 1) / 32; do { acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); } while (i-- != 0); } #else if (len > 32) { if (len > 64) { if (len > 96) { acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); } acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); } acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); } acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); #endif { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; h128.high64 = (acc.low64 * XXH_PRIME64_1) + (acc.high64 * XXH_PRIME64_4) + ((len - seed) * XXH_PRIME64_2); h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); return h128; } } } XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH64_hash_t seed) { XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); { XXH128_hash_t acc; unsigned i; acc.low64 = len * XXH_PRIME64_1; acc.high64 = 0; /* * We set as `i` as offset + 32. We do this so that unchanged * `len` can be used as upper bound. This reaches a sweet spot * where both x86 and aarch64 get simple agen and good codegen * for the loop. */ for (i = 32; i < 160; i += 32) { acc = XXH128_mix32B(acc, input + i - 32, input + i - 16, secret + i - 32, seed); } acc.low64 = XXH3_avalanche(acc.low64); acc.high64 = XXH3_avalanche(acc.high64); /* * NB: `i <= len` will duplicate the last 32-bytes if * len % 32 was zero. This is an unfortunate necessity to keep * the hash result stable. */ for (i=160; i <= len; i += 32) { acc = XXH128_mix32B(acc, input + i - 32, input + i - 16, secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, seed); } /* last bytes */ acc = XXH128_mix32B(acc, input + len - 16, input + len - 32, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, (XXH64_hash_t)0 - seed); { XXH128_hash_t h128; h128.low64 = acc.low64 + acc.high64; h128.high64 = (acc.low64 * XXH_PRIME64_1) + (acc.high64 * XXH_PRIME64_4) + ((len - seed) * XXH_PRIME64_2); h128.low64 = XXH3_avalanche(h128.low64); h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); return h128; } } } XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble) { XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); /* converge into final hash */ XXH_STATIC_ASSERT(sizeof(acc) == 64); XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); { XXH128_hash_t h128; h128.low64 = XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); h128.high64 = XXH3_mergeAccs(acc, secret + secretSize - sizeof(acc) - XXH_SECRET_MERGEACCS_START, ~((xxh_u64)len * XXH_PRIME64_2)); return h128; } } /* * It's important for performance that XXH3_hashLong() is not inlined. */ XXH_NO_INLINE XXH_PUREF XXH128_hash_t XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; (void)secret; (void)secretLen; return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); } /* * It's important for performance to pass @p secretLen (when it's static) * to the compiler, so that it can properly optimize the vectorized loop. * * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE * breaks -Og, this is XXH_NO_INLINE. */ XXH3_WITH_SECRET_INLINE XXH128_hash_t XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)seed64; return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); } XXH_FORCE_INLINE XXH128_hash_t XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, XXH64_hash_t seed64, XXH3_f_accumulate f_acc, XXH3_f_scrambleAcc f_scramble, XXH3_f_initCustomSecret f_initSec) { if (seed64 == 0) return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), f_acc, f_scramble); { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; f_initSec(secret, seed64); return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), f_acc, f_scramble); } } /* * It's important for performance that XXH3_hashLong is not inlined. */ XXH_NO_INLINE XXH128_hash_t XXH3_hashLong_128b_withSeed(const void* input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) { (void)secret; (void)secretLen; return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); } typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, XXH64_hash_t, const void* XXH_RESTRICT, size_t); XXH_FORCE_INLINE XXH128_hash_t XXH3_128bits_internal(const void* input, size_t len, XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, XXH3_hashLong128_f f_hl128) { XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); /* * If an action is to be taken if `secret` conditions are not respected, * it should be done here. * For now, it's a contract pre-condition. * Adding a check and a branch here would cost performance at every hash. */ if (len <= 16) return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); if (len <= 128) return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); if (len <= XXH3_MIDSIZE_MAX) return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); return f_hl128(input, len, seed64, secret, secretLen); } /* === Public XXH128 API === */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) { return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_default); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_128bits_internal(input, len, 0, (const xxh_u8*)secret, secretSize, XXH3_hashLong_128b_withSecret); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { if (len <= XXH3_MIDSIZE_MAX) return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) { return XXH3_128bits_withSeed(input, len, seed); } /* === XXH3 128-bit streaming === */ #ifndef XXH_NO_STREAM /* * All initialization and update functions are identical to 64-bit streaming variant. * The only difference is the finalization routine. */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) { return XXH3_64bits_reset(statePtr); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) { return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) { return XXH3_64bits_reset_withSeed(statePtr, seed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) { return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) { return XXH3_64bits_update(state, input, len); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) { const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; if (state->totalLen > XXH3_MIDSIZE_MAX) { XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; XXH3_digest_long(acc, state, secret); XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); { XXH128_hash_t h128; h128.low64 = XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)state->totalLen * XXH_PRIME64_1); h128.high64 = XXH3_mergeAccs(acc, secret + state->secretLimit + XXH_STRIPE_LEN - sizeof(acc) - XXH_SECRET_MERGEACCS_START, ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); return h128; } } /* len <= XXH3_MIDSIZE_MAX : short code */ if (state->seed) return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), secret, state->secretLimit + XXH_STRIPE_LEN); } #endif /* !XXH_NO_STREAM */ /* 128-bit utility functions */ #include /* memcmp, memcpy */ /* return : 1 is equal, 0 if different */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) { /* note : XXH128_hash_t is compact, it has no padding byte */ return !(memcmp(&h1, &h2, sizeof(h1))); } /* This prototype is compatible with stdlib's qsort(). * @return : >0 if *h128_1 > *h128_2 * <0 if *h128_1 < *h128_2 * =0 if *h128_1 == *h128_2 */ /*! @ingroup XXH3_family */ XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) { XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); /* note : bets that, in most cases, hash values are different */ if (hcmp) return hcmp; return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); } /*====== Canonical representation ======*/ /*! @ingroup XXH3_family */ XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) { hash.high64 = XXH_swap64(hash.high64); hash.low64 = XXH_swap64(hash.low64); } XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) { XXH128_hash_t h; h.high64 = XXH_readBE64(src); h.low64 = XXH_readBE64(src->digest + 8); return h; } /* ========================================== * Secret generators * ========================================== */ #define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) { XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); } /*! @ingroup XXH3_family */ XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) { #if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(secretBuffer != NULL); XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); #else /* production mode, assert() are disabled */ if (secretBuffer == NULL) return XXH_ERROR; if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; #endif if (customSeedSize == 0) { customSeed = XXH3_kSecret; customSeedSize = XXH_SECRET_DEFAULT_SIZE; } #if (XXH_DEBUGLEVEL >= 1) XXH_ASSERT(customSeed != NULL); #else if (customSeed == NULL) return XXH_ERROR; #endif /* Fill secretBuffer with a copy of customSeed - repeat as needed */ { size_t pos = 0; while (pos < secretSize) { size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); memcpy((char*)secretBuffer + pos, customSeed, toCopy); pos += toCopy; } } { size_t const nbSeg16 = secretSize / 16; size_t n; XXH128_canonical_t scrambler; XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); for (n=0; n # define ZYAN_ASSERT(condition) NT_ASSERT(condition) #else # include # define ZYAN_ASSERT(condition) assert(condition) #endif /** * Compiler-time assertion. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus) # define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x) #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \ (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \ (defined (_MSC_VER) && (_MSC_VER >= 1800)) # define ZYAN_STATIC_ASSERT(x) static_assert(x, #x) #else # define ZYAN_STATIC_ASSERT(x) \ typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1] #endif /** * Marks the current code path as unreachable. */ #if defined(ZYAN_RELEASE) # if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs. # if __has_builtin(__builtin_unreachable) # define ZYAN_UNREACHABLE __builtin_unreachable() # else # define ZYAN_UNREACHABLE for(;;) # endif # elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4) # define ZYAN_UNREACHABLE __builtin_unreachable() # elif defined(ZYAN_ICC) # ifdef ZYAN_WINDOWS # include // "missing return statement" workaround # define ZYAN_UNREACHABLE __assume(0); (void)abort() # else # define ZYAN_UNREACHABLE __builtin_unreachable() # endif # elif defined(ZYAN_MSVC) # define ZYAN_UNREACHABLE __assume(0) # else # define ZYAN_UNREACHABLE for(;;) # endif #elif defined(ZYAN_NO_LIBC) # define ZYAN_UNREACHABLE for(;;) #elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) # define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} } #else # include # define ZYAN_UNREACHABLE { assert(0); abort(); } #endif /* ============================================================================================== */ /* Utils */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* General purpose */ /* ---------------------------------------------------------------------------------------------- */ /** * Marks the specified parameter as unused. * * @param x The name of the unused parameter. */ #define ZYAN_UNUSED(x) (void)(x) /** * Intentional fallthrough. */ #if defined(ZYAN_GCC) && __GNUC__ >= 7 # define ZYAN_FALLTHROUGH ; __attribute__((__fallthrough__)) #else # define ZYAN_FALLTHROUGH #endif /** * Declares a bitfield. * * @param x The size (in bits) of the bitfield. */ #define ZYAN_BITFIELD(x) : x /** * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`). */ #define ZYAN_REQUIRES_LIBC /** * Decorator for `printf`-style functions. * * @param format_index The 1-based index of the format string parameter. * @param first_to_check The 1-based index of the format arguments parameter. */ #if defined(__RESHARPER__) # define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ [[gnu::format(printf, format_index, first_to_check)]] #elif defined(ZYAN_GCC) # define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ __attribute__((format(printf, format_index, first_to_check))) #else # define ZYAN_PRINTF_ATTR(format_index, first_to_check) #endif /** * Decorator for `wprintf`-style functions. * * @param format_index The 1-based index of the format string parameter. * @param first_to_check The 1-based index of the format arguments parameter. */ #if defined(__RESHARPER__) # define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \ [[rscpp::format(wprintf, format_index, first_to_check)]] #else # define ZYAN_WPRINTF_ATTR(format_index, first_to_check) #endif /* ---------------------------------------------------------------------------------------------- */ /* Arrays */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the length (number of elements) of an array. * * @param a The name of the array. * * @return The number of elements of the given array. */ #define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) /* ---------------------------------------------------------------------------------------------- */ /* Arithmetic */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the smaller value of `a` or `b`. * * @param a The first value. * @param b The second value. * * @return The smaller value of `a` or `b`. */ #define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b)) /** * Returns the bigger value of `a` or `b`. * * @param a The first value. * @param b The second value. * * @return The bigger value of `a` or `b`. */ #define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b)) /** * Returns the absolute value of `a`. * * @param a The value. * * @return The absolute value of `a`. */ #define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a)) /** * Checks, if the given value is a power of 2. * * @param x The value. * * @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not. * * Note that this macro always returns `ZYAN_TRUE` for `x == 0`. */ #define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) /** * Checks, if the given value is properly aligned. * * Note that this macro only works for powers of 2. */ #define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0) /** * Aligns the value to the nearest given alignment boundary (by rounding it up). * * @param x The value. * @param align The desired alignment. * * @return The aligned value. * * Note that this macro only works for powers of 2. */ #define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) /** * Aligns the value to the nearest given alignment boundary (by rounding it down). * * @param x The value. * @param align The desired alignment. * * @return The aligned value. * * Note that this macro only works for powers of 2. */ #define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1)) /** * Divide the 64bit integer value by the given divisor. * * @param n Variable containing the dividend that will be updated with the result of the * division. * @param divisor The divisor. */ #if defined(ZYAN_LINUX) && defined(ZYAN_KERNEL) # include /* do_div */ # define ZYAN_DIV64(n, divisor) do_div(n, divisor) #else # define ZYAN_DIV64(n, divisor) (n /= divisor) #endif /* ---------------------------------------------------------------------------------------------- */ /* Bit operations */ /* ---------------------------------------------------------------------------------------------- */ /* * Checks, if the bit at index `b` is required to present the ordinal value `n`. * * @param n The ordinal value. * @param b The bit index. * * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or * `ZYAN_FALSE`, if not. * * Note that this macro always returns `ZYAN_FALSE` for `n == 0`. */ #define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0) /* * Returns the number of bits required to represent the ordinal value `n`. * * @param n The ordinal value. * * @return The number of bits required to represent the ordinal value `n`. * * Note that this macro returns `0` for `n == 0`. */ #define ZYAN_BITS_TO_REPRESENT(n) \ ( \ ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \ ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \ ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \ ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \ ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \ ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \ ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \ ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \ ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \ ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \ ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \ ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \ ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \ ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \ ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \ ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \ ) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #endif /* ZYCORE_DEFINES_H */ // // Header: Zycore/Types.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Core Library (Zyan-C) Original Author : Florian Bernd, Joel Hoener * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Includes and defines some default data types. */ #ifndef ZYCORE_TYPES_H #define ZYCORE_TYPES_H /* ============================================================================================== */ /* Integer types */ /* ============================================================================================== */ #if defined(ZYAN_NO_LIBC) || \ (defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h. // No LibC mode, use compiler built-in types / macros. # if defined(ZYAN_MSVC) || defined(ZYAN_ICC) typedef unsigned __int8 ZyanU8; typedef unsigned __int16 ZyanU16; typedef unsigned __int32 ZyanU32; typedef unsigned __int64 ZyanU64; typedef signed __int8 ZyanI8; typedef signed __int16 ZyanI16; typedef signed __int32 ZyanI32; typedef signed __int64 ZyanI64; # if _WIN64 typedef ZyanU64 ZyanUSize; typedef ZyanI64 ZyanISize; typedef ZyanU64 ZyanUPointer; typedef ZyanI64 ZyanIPointer; # else typedef ZyanU32 ZyanUSize; typedef ZyanI32 ZyanISize; typedef ZyanU32 ZyanUPointer; typedef ZyanI32 ZyanIPointer; # endif # elif defined(ZYAN_GNUC) # ifdef __UINT8_TYPE__ typedef __UINT8_TYPE__ ZyanU8; # else typedef unsigned char ZyanU8; # endif # ifdef __UINT16_TYPE__ typedef __UINT16_TYPE__ ZyanU16; # else typedef unsigned short int ZyanU16; # endif # ifdef __UINT32_TYPE__ typedef __UINT32_TYPE__ ZyanU32; # else typedef unsigned int ZyanU32; # endif # ifdef __UINT64_TYPE__ typedef __UINT64_TYPE__ ZyanU64; # else # if defined(__x86_64__) && !defined(__ILP32__) typedef unsigned long int ZyanU64; # else typedef unsigned long long int ZyanU64; # endif # endif # ifdef __INT8_TYPE__ typedef __INT8_TYPE__ ZyanI8; # else typedef signed char ZyanI8; # endif # ifdef __INT16_TYPE__ typedef __INT16_TYPE__ ZyanI16; # else typedef signed short int ZyanI16; # endif # ifdef __INT32_TYPE__ typedef __INT32_TYPE__ ZyanI32; # else typedef signed int ZyanI32; # endif # ifdef __INT64_TYPE__ typedef __INT64_TYPE__ ZyanI64; # else # if defined(__x86_64__) && !defined( __ILP32__) typedef signed long int ZyanI64; # else typedef signed long long int ZyanI64; # endif # endif # ifdef __SIZE_TYPE__ typedef __SIZE_TYPE__ ZyanUSize; # else typedef long unsigned int ZyanUSize; # endif # ifdef __PTRDIFF_TYPE__ typedef __PTRDIFF_TYPE__ ZyanISize; # else typedef long int ZyanISize; # endif # ifdef __UINTPTR_TYPE__ typedef __UINTPTR_TYPE__ ZyanUPointer; # else # if defined(__x86_64__) && !defined( __ILP32__) typedef unsigned long int ZyanUPointer; # else typedef unsigned int ZyanUPointer; # endif # endif # ifdef __INTPTR_TYPE__ typedef __INTPTR_TYPE__ ZyanIPointer; # else # if defined(__x86_64__) && !defined( __ILP32__) typedef long int ZyanIPointer; # else typedef int ZyanIPointer; # endif # endif # else # error "Unsupported compiler for no-libc mode." # endif # if defined(ZYAN_MSVC) # define ZYAN_INT8_MIN (-127i8 - 1) # define ZYAN_INT16_MIN (-32767i16 - 1) # define ZYAN_INT32_MIN (-2147483647i32 - 1) # define ZYAN_INT64_MIN (-9223372036854775807i64 - 1) # define ZYAN_INT8_MAX 127i8 # define ZYAN_INT16_MAX 32767i16 # define ZYAN_INT32_MAX 2147483647i32 # define ZYAN_INT64_MAX 9223372036854775807i64 # define ZYAN_UINT8_MAX 0xffui8 # define ZYAN_UINT16_MAX 0xffffui16 # define ZYAN_UINT32_MAX 0xffffffffui32 # define ZYAN_UINT64_MAX 0xffffffffffffffffui64 # else # ifdef __INT8_MAX__ # define ZYAN_INT8_MAX __INT8_MAX__ # else # define ZYAN_INT8_MAX (127) # endif # define ZYAN_INT8_MIN (-ZYAN_INT8_MAX - 1) # ifdef __INT16_MAX__ # define ZYAN_INT16_MAX __INT16_MAX__ # else # define ZYAN_INT16_MAX (32767) # endif # define ZYAN_INT16_MIN (-ZYAN_INT16_MAX - 1) # ifdef __INT32_MAX__ # define ZYAN_INT32_MAX __INT32_MAX__ # else # define ZYAN_INT32_MAX (2147483647) # endif # define ZYAN_INT32_MIN (-ZYAN_INT32_MAX - 1) # ifdef __INT64_MAX__ # define ZYAN_INT64_MAX __INT64_MAX__ # else # if defined(__x86_64__) && !defined( __ILP32__) # define ZYAN_INT64_MAX (9223372036854775807L) # else # define ZYAN_INT64_MAX (9223372036854775807LL) # endif # endif # define ZYAN_INT64_MIN (-ZYAN_INT64_MAX - 1) # ifdef __UINT8_MAX__ # define ZYAN_UINT8_MAX __UINT8_MAX__ # else # define ZYAN_UINT8_MAX (255) # endif # ifdef __UINT16_MAX__ # define ZYAN_UINT16_MAX __UINT16_MAX__ # else # define ZYAN_UINT16_MAX (65535) # endif # ifdef __UINT32_MAX__ # define ZYAN_UINT32_MAX __UINT32_MAX__ # else # define ZYAN_UINT32_MAX (4294967295U) # endif # ifdef __UINT64_MAX__ # define ZYAN_UINT64_MAX __UINT64_MAX__ # else # if defined(__x86_64__) && !defined( __ILP32__) # define ZYAN_UINT64_MAX (18446744073709551615UL) # else # define ZYAN_UINT64_MAX (18446744073709551615ULL) # endif # endif # endif #else // If is LibC present, we use stdint types. # include # include typedef uint8_t ZyanU8; typedef uint16_t ZyanU16; typedef uint32_t ZyanU32; typedef uint64_t ZyanU64; typedef int8_t ZyanI8; typedef int16_t ZyanI16; typedef int32_t ZyanI32; typedef int64_t ZyanI64; typedef size_t ZyanUSize; typedef ptrdiff_t ZyanISize; typedef uintptr_t ZyanUPointer; typedef intptr_t ZyanIPointer; # define ZYAN_INT8_MIN INT8_MIN # define ZYAN_INT16_MIN INT16_MIN # define ZYAN_INT32_MIN INT32_MIN # define ZYAN_INT64_MIN INT64_MIN # define ZYAN_INT8_MAX INT8_MAX # define ZYAN_INT16_MAX INT16_MAX # define ZYAN_INT32_MAX INT32_MAX # define ZYAN_INT64_MAX INT64_MAX # define ZYAN_UINT8_MAX UINT8_MAX # define ZYAN_UINT16_MAX UINT16_MAX # define ZYAN_UINT32_MAX UINT32_MAX # define ZYAN_UINT64_MAX UINT64_MAX #endif // Verify size assumptions. ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 ); ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 ); ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 ); ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 ); ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 ); ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 ); ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 ); ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 ); ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect! ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect! ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*)); ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*)); // Verify signedness assumptions (relies on size checks above). ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1)); ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1)); ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1)); ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1)); /* ============================================================================================== */ /* Pointer */ /* ============================================================================================== */ /** * Defines the `ZyanVoidPointer` data-type. */ typedef void* ZyanVoidPointer; /** * Defines the `ZyanConstVoidPointer` data-type. */ typedef const void* ZyanConstVoidPointer; #define ZYAN_NULL ((void*)0) /* ============================================================================================== */ /* Logic types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Boolean */ /* ---------------------------------------------------------------------------------------------- */ #define ZYAN_FALSE 0u #define ZYAN_TRUE 1u /** * Defines the `ZyanBool` data-type. * * Represents a default boolean data-type where `0` is interpreted as `false` and all other values * as `true`. */ typedef ZyanU8 ZyanBool; /* ---------------------------------------------------------------------------------------------- */ /* Ternary */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZyanTernary` data-type. * * The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`, * `false` and an indeterminate third value. */ typedef ZyanI8 ZyanTernary; #define ZYAN_TERNARY_FALSE (-1) #define ZYAN_TERNARY_UNKNOWN 0x00 #define ZYAN_TERNARY_TRUE 0x01 /* ============================================================================================== */ /* String types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* C-style strings */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZyanCharPointer` data-type. * * This type is most often used to represent null-terminated strings aka. C-style strings. */ typedef char* ZyanCharPointer; /** * Defines the `ZyanConstCharPointer` data-type. * * This type is most often used to represent null-terminated strings aka. C-style strings. */ typedef const char* ZyanConstCharPointer; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #endif /* ZYCORE_TYPES_H */ #if !defined(ZYDIS_DISABLE_DECODER) // // Header: Zydis/Decoder.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Functions for decoding instructions. */ #ifndef ZYDIS_DECODER_H #define ZYDIS_DECODER_H // // Header: Zydis/DecoderTypes.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Defines the basic `ZydisDecodedInstruction` and `ZydisDecodedOperand` structs. */ #ifndef ZYDIS_INSTRUCTIONINFO_H #define ZYDIS_INSTRUCTIONINFO_H // // Header: Zydis/MetaInfo.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * @brief */ #ifndef ZYDIS_METAINFO_H #define ZYDIS_METAINFO_H // // Header: Zydis/Defines.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/MetaInfo.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Joel Hoener * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Import/export defines for MSVC builds. */ #ifndef ZYDIS_DEFINES_H #define ZYDIS_DEFINES_H // This is a cut-down version of what CMake's `GenerateExportHeader` would usually generate. To // simplify builds without CMake, we define these things manually instead of relying on CMake // to generate the header. // // For static builds, our CMakeList will define `ZYDIS_STATIC_BUILD`. For shared library builds, // our CMake will define `ZYDIS_SHOULD_EXPORT` depending on whether the target is being imported or // exported. If CMake isn't used, users can manually define these to fit their use-case. // Backward compatibility: CMake would previously generate these variables names. However, because // they have pretty cryptic names, we renamed them when we got rid of `GenerateExportHeader`. For // backward compatibility for users that don't use CMake and previously manually defined these, we // translate the old defines here and print a warning. #if defined(ZYDIS_STATIC_DEFINE) # pragma message("ZYDIS_STATIC_DEFINE was renamed to ZYDIS_STATIC_BUILD.") # define ZYDIS_STATIC_BUILD #endif #if defined(Zydis_EXPORTS) # pragma message("Zydis_EXPORTS was renamed to ZYDIS_SHOULD_EXPORT.") # define ZYDIS_SHOULD_EXPORT #endif /** * Symbol is exported in shared library builds. */ // NOTE(rjf): @rjf #define ZYDIS_EXPORT static #if 0 #if defined(ZYDIS_STATIC_BUILD) # define ZYDIS_EXPORT #else # if defined(ZYDIS_SHOULD_EXPORT) # define ZYDIS_EXPORT ZYAN_DLLEXPORT # else # define ZYDIS_EXPORT ZYAN_DLLIMPORT # endif #endif #endif /** * Symbol is not exported and for internal use only. */ #define ZYDIS_NO_EXPORT #endif // ZYDIS_DEFINES_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ // // Header: Zydis/Generated/EnumInstructionCategory.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/MetaInfo.h // /** * Defines the `ZydisInstructionCategory` enum. */ typedef enum ZydisInstructionCategory_ { ZYDIS_CATEGORY_INVALID, ZYDIS_CATEGORY_ADOX_ADCX, ZYDIS_CATEGORY_AES, ZYDIS_CATEGORY_AMD3DNOW, ZYDIS_CATEGORY_AMX_TILE, ZYDIS_CATEGORY_AVX, ZYDIS_CATEGORY_AVX2, ZYDIS_CATEGORY_AVX2GATHER, ZYDIS_CATEGORY_AVX512, ZYDIS_CATEGORY_AVX512_4FMAPS, ZYDIS_CATEGORY_AVX512_4VNNIW, ZYDIS_CATEGORY_AVX512_BITALG, ZYDIS_CATEGORY_AVX512_VBMI, ZYDIS_CATEGORY_AVX512_VP2INTERSECT, ZYDIS_CATEGORY_AVX_IFMA, ZYDIS_CATEGORY_BINARY, ZYDIS_CATEGORY_BITBYTE, ZYDIS_CATEGORY_BLEND, ZYDIS_CATEGORY_BMI1, ZYDIS_CATEGORY_BMI2, ZYDIS_CATEGORY_BROADCAST, ZYDIS_CATEGORY_CALL, ZYDIS_CATEGORY_CET, ZYDIS_CATEGORY_CLDEMOTE, ZYDIS_CATEGORY_CLFLUSHOPT, ZYDIS_CATEGORY_CLWB, ZYDIS_CATEGORY_CLZERO, ZYDIS_CATEGORY_CMOV, ZYDIS_CATEGORY_COMPRESS, ZYDIS_CATEGORY_COND_BR, ZYDIS_CATEGORY_CONFLICT, ZYDIS_CATEGORY_CONVERT, ZYDIS_CATEGORY_DATAXFER, ZYDIS_CATEGORY_DECIMAL, ZYDIS_CATEGORY_ENQCMD, ZYDIS_CATEGORY_EXPAND, ZYDIS_CATEGORY_FCMOV, ZYDIS_CATEGORY_FLAGOP, ZYDIS_CATEGORY_FMA4, ZYDIS_CATEGORY_FP16, ZYDIS_CATEGORY_GATHER, ZYDIS_CATEGORY_GFNI, ZYDIS_CATEGORY_HRESET, ZYDIS_CATEGORY_IFMA, ZYDIS_CATEGORY_INTERRUPT, ZYDIS_CATEGORY_IO, ZYDIS_CATEGORY_IOSTRINGOP, ZYDIS_CATEGORY_KEYLOCKER, ZYDIS_CATEGORY_KEYLOCKER_WIDE, ZYDIS_CATEGORY_KMASK, ZYDIS_CATEGORY_KNC, ZYDIS_CATEGORY_KNCMASK, ZYDIS_CATEGORY_KNCSCALAR, ZYDIS_CATEGORY_LEGACY, ZYDIS_CATEGORY_LOGICAL, ZYDIS_CATEGORY_LOGICAL_FP, ZYDIS_CATEGORY_LZCNT, ZYDIS_CATEGORY_MISC, ZYDIS_CATEGORY_MMX, ZYDIS_CATEGORY_MOVDIR, ZYDIS_CATEGORY_MPX, ZYDIS_CATEGORY_MSRLIST, ZYDIS_CATEGORY_NOP, ZYDIS_CATEGORY_PADLOCK, ZYDIS_CATEGORY_PBNDKB, ZYDIS_CATEGORY_PCLMULQDQ, ZYDIS_CATEGORY_PCOMMIT, ZYDIS_CATEGORY_PCONFIG, ZYDIS_CATEGORY_PKU, ZYDIS_CATEGORY_POP, ZYDIS_CATEGORY_PREFETCH, ZYDIS_CATEGORY_PREFETCHWT1, ZYDIS_CATEGORY_PT, ZYDIS_CATEGORY_PUSH, ZYDIS_CATEGORY_RDPID, ZYDIS_CATEGORY_RDPRU, ZYDIS_CATEGORY_RDRAND, ZYDIS_CATEGORY_RDSEED, ZYDIS_CATEGORY_RDWRFSGS, ZYDIS_CATEGORY_RET, ZYDIS_CATEGORY_ROTATE, ZYDIS_CATEGORY_SCATTER, ZYDIS_CATEGORY_SEGOP, ZYDIS_CATEGORY_SEMAPHORE, ZYDIS_CATEGORY_SERIALIZE, ZYDIS_CATEGORY_SETCC, ZYDIS_CATEGORY_SGX, ZYDIS_CATEGORY_SHA, ZYDIS_CATEGORY_SHA512, ZYDIS_CATEGORY_SHIFT, ZYDIS_CATEGORY_SMAP, ZYDIS_CATEGORY_SSE, ZYDIS_CATEGORY_STRINGOP, ZYDIS_CATEGORY_STTNI, ZYDIS_CATEGORY_SYSCALL, ZYDIS_CATEGORY_SYSRET, ZYDIS_CATEGORY_SYSTEM, ZYDIS_CATEGORY_TBM, ZYDIS_CATEGORY_TSX_LDTRK, ZYDIS_CATEGORY_UFMA, ZYDIS_CATEGORY_UINTR, ZYDIS_CATEGORY_UNCOND_BR, ZYDIS_CATEGORY_VAES, ZYDIS_CATEGORY_VBMI2, ZYDIS_CATEGORY_VEX, ZYDIS_CATEGORY_VFMA, ZYDIS_CATEGORY_VPCLMULQDQ, ZYDIS_CATEGORY_VTX, ZYDIS_CATEGORY_WAITPKG, ZYDIS_CATEGORY_WIDENOP, ZYDIS_CATEGORY_WRMSRNS, ZYDIS_CATEGORY_X87_ALU, ZYDIS_CATEGORY_XOP, ZYDIS_CATEGORY_XSAVE, ZYDIS_CATEGORY_XSAVEOPT, /** * Maximum value of this enum. */ ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE) } ZydisInstructionCategory; // // Header: Zydis/Generated/EnumISASet.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/MetaInfo.h // /** * Defines the `ZydisISASet` enum. */ typedef enum ZydisISASet_ { ZYDIS_ISA_SET_INVALID, ZYDIS_ISA_SET_ADOX_ADCX, ZYDIS_ISA_SET_AES, ZYDIS_ISA_SET_AMD, ZYDIS_ISA_SET_AMD3DNOW, ZYDIS_ISA_SET_AMD_INVLPGB, ZYDIS_ISA_SET_AMX_BF16, ZYDIS_ISA_SET_AMX_FP16, ZYDIS_ISA_SET_AMX_INT8, ZYDIS_ISA_SET_AMX_TILE, ZYDIS_ISA_SET_AVX, ZYDIS_ISA_SET_AVX2, ZYDIS_ISA_SET_AVX2GATHER, ZYDIS_ISA_SET_AVX512BW_128, ZYDIS_ISA_SET_AVX512BW_128N, ZYDIS_ISA_SET_AVX512BW_256, ZYDIS_ISA_SET_AVX512BW_512, ZYDIS_ISA_SET_AVX512BW_KOP, ZYDIS_ISA_SET_AVX512CD_128, ZYDIS_ISA_SET_AVX512CD_256, ZYDIS_ISA_SET_AVX512CD_512, ZYDIS_ISA_SET_AVX512DQ_128, ZYDIS_ISA_SET_AVX512DQ_128N, ZYDIS_ISA_SET_AVX512DQ_256, ZYDIS_ISA_SET_AVX512DQ_512, ZYDIS_ISA_SET_AVX512DQ_KOP, ZYDIS_ISA_SET_AVX512DQ_SCALAR, ZYDIS_ISA_SET_AVX512ER_512, ZYDIS_ISA_SET_AVX512ER_SCALAR, ZYDIS_ISA_SET_AVX512F_128, ZYDIS_ISA_SET_AVX512F_128N, ZYDIS_ISA_SET_AVX512F_256, ZYDIS_ISA_SET_AVX512F_512, ZYDIS_ISA_SET_AVX512F_KOP, ZYDIS_ISA_SET_AVX512F_SCALAR, ZYDIS_ISA_SET_AVX512PF_512, ZYDIS_ISA_SET_AVX512_4FMAPS_512, ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR, ZYDIS_ISA_SET_AVX512_4VNNIW_512, ZYDIS_ISA_SET_AVX512_BF16_128, ZYDIS_ISA_SET_AVX512_BF16_256, ZYDIS_ISA_SET_AVX512_BF16_512, ZYDIS_ISA_SET_AVX512_BITALG_128, ZYDIS_ISA_SET_AVX512_BITALG_256, ZYDIS_ISA_SET_AVX512_BITALG_512, ZYDIS_ISA_SET_AVX512_FP16_128, ZYDIS_ISA_SET_AVX512_FP16_128N, ZYDIS_ISA_SET_AVX512_FP16_256, ZYDIS_ISA_SET_AVX512_FP16_512, ZYDIS_ISA_SET_AVX512_FP16_SCALAR, ZYDIS_ISA_SET_AVX512_GFNI_128, ZYDIS_ISA_SET_AVX512_GFNI_256, ZYDIS_ISA_SET_AVX512_GFNI_512, ZYDIS_ISA_SET_AVX512_IFMA_128, ZYDIS_ISA_SET_AVX512_IFMA_256, ZYDIS_ISA_SET_AVX512_IFMA_512, ZYDIS_ISA_SET_AVX512_VAES_128, ZYDIS_ISA_SET_AVX512_VAES_256, ZYDIS_ISA_SET_AVX512_VAES_512, ZYDIS_ISA_SET_AVX512_VBMI2_128, ZYDIS_ISA_SET_AVX512_VBMI2_256, ZYDIS_ISA_SET_AVX512_VBMI2_512, ZYDIS_ISA_SET_AVX512_VBMI_128, ZYDIS_ISA_SET_AVX512_VBMI_256, ZYDIS_ISA_SET_AVX512_VBMI_512, ZYDIS_ISA_SET_AVX512_VNNI_128, ZYDIS_ISA_SET_AVX512_VNNI_256, ZYDIS_ISA_SET_AVX512_VNNI_512, ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128, ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256, ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512, ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128, ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256, ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512, ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128, ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256, ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512, ZYDIS_ISA_SET_AVXAES, ZYDIS_ISA_SET_AVX_GFNI, ZYDIS_ISA_SET_AVX_IFMA, ZYDIS_ISA_SET_AVX_NE_CONVERT, ZYDIS_ISA_SET_AVX_VNNI, ZYDIS_ISA_SET_AVX_VNNI_INT16, ZYDIS_ISA_SET_AVX_VNNI_INT8, ZYDIS_ISA_SET_BMI1, ZYDIS_ISA_SET_BMI2, ZYDIS_ISA_SET_CET, ZYDIS_ISA_SET_CLDEMOTE, ZYDIS_ISA_SET_CLFLUSHOPT, ZYDIS_ISA_SET_CLFSH, ZYDIS_ISA_SET_CLWB, ZYDIS_ISA_SET_CLZERO, ZYDIS_ISA_SET_CMOV, ZYDIS_ISA_SET_CMPXCHG16B, ZYDIS_ISA_SET_ENQCMD, ZYDIS_ISA_SET_F16C, ZYDIS_ISA_SET_FAT_NOP, ZYDIS_ISA_SET_FCMOV, ZYDIS_ISA_SET_FCOMI, ZYDIS_ISA_SET_FMA, ZYDIS_ISA_SET_FMA4, ZYDIS_ISA_SET_FXSAVE, ZYDIS_ISA_SET_FXSAVE64, ZYDIS_ISA_SET_GFNI, ZYDIS_ISA_SET_HRESET, ZYDIS_ISA_SET_I186, ZYDIS_ISA_SET_I286PROTECTED, ZYDIS_ISA_SET_I286REAL, ZYDIS_ISA_SET_I386, ZYDIS_ISA_SET_I486, ZYDIS_ISA_SET_I486REAL, ZYDIS_ISA_SET_I86, ZYDIS_ISA_SET_ICACHE_PREFETCH, ZYDIS_ISA_SET_INVPCID, ZYDIS_ISA_SET_KEYLOCKER, ZYDIS_ISA_SET_KEYLOCKER_WIDE, ZYDIS_ISA_SET_KNCE, ZYDIS_ISA_SET_KNCJKBR, ZYDIS_ISA_SET_KNCSTREAM, ZYDIS_ISA_SET_KNCV, ZYDIS_ISA_SET_KNC_MISC, ZYDIS_ISA_SET_KNC_PF_HINT, ZYDIS_ISA_SET_LAHF, ZYDIS_ISA_SET_LONGMODE, ZYDIS_ISA_SET_LWP, ZYDIS_ISA_SET_LZCNT, ZYDIS_ISA_SET_MCOMMIT, ZYDIS_ISA_SET_MONITOR, ZYDIS_ISA_SET_MONITORX, ZYDIS_ISA_SET_MOVBE, ZYDIS_ISA_SET_MOVDIR, ZYDIS_ISA_SET_MPX, ZYDIS_ISA_SET_MSRLIST, ZYDIS_ISA_SET_PADLOCK_ACE, ZYDIS_ISA_SET_PADLOCK_PHE, ZYDIS_ISA_SET_PADLOCK_PMM, ZYDIS_ISA_SET_PADLOCK_RNG, ZYDIS_ISA_SET_PAUSE, ZYDIS_ISA_SET_PBNDKB, ZYDIS_ISA_SET_PCLMULQDQ, ZYDIS_ISA_SET_PCOMMIT, ZYDIS_ISA_SET_PCONFIG, ZYDIS_ISA_SET_PENTIUMMMX, ZYDIS_ISA_SET_PENTIUMREAL, ZYDIS_ISA_SET_PKU, ZYDIS_ISA_SET_POPCNT, ZYDIS_ISA_SET_PPRO, ZYDIS_ISA_SET_PREFETCHWT1, ZYDIS_ISA_SET_PREFETCH_NOP, ZYDIS_ISA_SET_PT, ZYDIS_ISA_SET_RAO_INT, ZYDIS_ISA_SET_RDPID, ZYDIS_ISA_SET_RDPMC, ZYDIS_ISA_SET_RDPRU, ZYDIS_ISA_SET_RDRAND, ZYDIS_ISA_SET_RDSEED, ZYDIS_ISA_SET_RDTSCP, ZYDIS_ISA_SET_RDWRFSGS, ZYDIS_ISA_SET_RTM, ZYDIS_ISA_SET_SERIALIZE, ZYDIS_ISA_SET_SGX, ZYDIS_ISA_SET_SGX_ENCLV, ZYDIS_ISA_SET_SHA, ZYDIS_ISA_SET_SHA512, ZYDIS_ISA_SET_SM3, ZYDIS_ISA_SET_SM4, ZYDIS_ISA_SET_SMAP, ZYDIS_ISA_SET_SMX, ZYDIS_ISA_SET_SNP, ZYDIS_ISA_SET_SSE, ZYDIS_ISA_SET_SSE2, ZYDIS_ISA_SET_SSE2MMX, ZYDIS_ISA_SET_SSE3, ZYDIS_ISA_SET_SSE3X87, ZYDIS_ISA_SET_SSE4, ZYDIS_ISA_SET_SSE42, ZYDIS_ISA_SET_SSE4A, ZYDIS_ISA_SET_SSEMXCSR, ZYDIS_ISA_SET_SSE_PREFETCH, ZYDIS_ISA_SET_SSSE3, ZYDIS_ISA_SET_SSSE3MMX, ZYDIS_ISA_SET_SVM, ZYDIS_ISA_SET_TBM, ZYDIS_ISA_SET_TDX, ZYDIS_ISA_SET_TSX_LDTRK, ZYDIS_ISA_SET_UINTR, ZYDIS_ISA_SET_VAES, ZYDIS_ISA_SET_VMFUNC, ZYDIS_ISA_SET_VPCLMULQDQ, ZYDIS_ISA_SET_VTX, ZYDIS_ISA_SET_WAITPKG, ZYDIS_ISA_SET_WRMSRNS, ZYDIS_ISA_SET_X87, ZYDIS_ISA_SET_XOP, ZYDIS_ISA_SET_XSAVE, ZYDIS_ISA_SET_XSAVEC, ZYDIS_ISA_SET_XSAVEOPT, ZYDIS_ISA_SET_XSAVES, /** * Maximum value of this enum. */ ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE) } ZydisISASet; // // Header: Zydis/Generated/EnumISAExt.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/MetaInfo.h // /** * Defines the `ZydisISAExt` enum. */ typedef enum ZydisISAExt_ { ZYDIS_ISA_EXT_INVALID, ZYDIS_ISA_EXT_ADOX_ADCX, ZYDIS_ISA_EXT_AES, ZYDIS_ISA_EXT_AMD3DNOW, ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH, ZYDIS_ISA_EXT_AMD_INVLPGB, ZYDIS_ISA_EXT_AMX_BF16, ZYDIS_ISA_EXT_AMX_FP16, ZYDIS_ISA_EXT_AMX_INT8, ZYDIS_ISA_EXT_AMX_TILE, ZYDIS_ISA_EXT_AVX, ZYDIS_ISA_EXT_AVX2, ZYDIS_ISA_EXT_AVX2GATHER, ZYDIS_ISA_EXT_AVX512EVEX, ZYDIS_ISA_EXT_AVX512VEX, ZYDIS_ISA_EXT_AVXAES, ZYDIS_ISA_EXT_AVX_IFMA, ZYDIS_ISA_EXT_AVX_NE_CONVERT, ZYDIS_ISA_EXT_AVX_VNNI, ZYDIS_ISA_EXT_AVX_VNNI_INT16, ZYDIS_ISA_EXT_AVX_VNNI_INT8, ZYDIS_ISA_EXT_BASE, ZYDIS_ISA_EXT_BMI1, ZYDIS_ISA_EXT_BMI2, ZYDIS_ISA_EXT_CET, ZYDIS_ISA_EXT_CLDEMOTE, ZYDIS_ISA_EXT_CLFLUSHOPT, ZYDIS_ISA_EXT_CLFSH, ZYDIS_ISA_EXT_CLWB, ZYDIS_ISA_EXT_CLZERO, ZYDIS_ISA_EXT_ENQCMD, ZYDIS_ISA_EXT_F16C, ZYDIS_ISA_EXT_FMA, ZYDIS_ISA_EXT_FMA4, ZYDIS_ISA_EXT_GFNI, ZYDIS_ISA_EXT_HRESET, ZYDIS_ISA_EXT_ICACHE_PREFETCH, ZYDIS_ISA_EXT_INVPCID, ZYDIS_ISA_EXT_KEYLOCKER, ZYDIS_ISA_EXT_KEYLOCKER_WIDE, ZYDIS_ISA_EXT_KNC, ZYDIS_ISA_EXT_KNCE, ZYDIS_ISA_EXT_KNCV, ZYDIS_ISA_EXT_LONGMODE, ZYDIS_ISA_EXT_LZCNT, ZYDIS_ISA_EXT_MCOMMIT, ZYDIS_ISA_EXT_MMX, ZYDIS_ISA_EXT_MONITOR, ZYDIS_ISA_EXT_MONITORX, ZYDIS_ISA_EXT_MOVBE, ZYDIS_ISA_EXT_MOVDIR, ZYDIS_ISA_EXT_MPX, ZYDIS_ISA_EXT_MSRLIST, ZYDIS_ISA_EXT_PADLOCK, ZYDIS_ISA_EXT_PAUSE, ZYDIS_ISA_EXT_PBNDKB, ZYDIS_ISA_EXT_PCLMULQDQ, ZYDIS_ISA_EXT_PCOMMIT, ZYDIS_ISA_EXT_PCONFIG, ZYDIS_ISA_EXT_PKU, ZYDIS_ISA_EXT_PREFETCHWT1, ZYDIS_ISA_EXT_PT, ZYDIS_ISA_EXT_RAO_INT, ZYDIS_ISA_EXT_RDPID, ZYDIS_ISA_EXT_RDPRU, ZYDIS_ISA_EXT_RDRAND, ZYDIS_ISA_EXT_RDSEED, ZYDIS_ISA_EXT_RDTSCP, ZYDIS_ISA_EXT_RDWRFSGS, ZYDIS_ISA_EXT_RTM, ZYDIS_ISA_EXT_SERIALIZE, ZYDIS_ISA_EXT_SGX, ZYDIS_ISA_EXT_SGX_ENCLV, ZYDIS_ISA_EXT_SHA, ZYDIS_ISA_EXT_SHA512, ZYDIS_ISA_EXT_SM3, ZYDIS_ISA_EXT_SM4, ZYDIS_ISA_EXT_SMAP, ZYDIS_ISA_EXT_SMX, ZYDIS_ISA_EXT_SNP, ZYDIS_ISA_EXT_SSE, ZYDIS_ISA_EXT_SSE2, ZYDIS_ISA_EXT_SSE3, ZYDIS_ISA_EXT_SSE4, ZYDIS_ISA_EXT_SSE4A, ZYDIS_ISA_EXT_SSSE3, ZYDIS_ISA_EXT_SVM, ZYDIS_ISA_EXT_TBM, ZYDIS_ISA_EXT_TDX, ZYDIS_ISA_EXT_TSX_LDTRK, ZYDIS_ISA_EXT_UINTR, ZYDIS_ISA_EXT_VAES, ZYDIS_ISA_EXT_VMFUNC, ZYDIS_ISA_EXT_VPCLMULQDQ, ZYDIS_ISA_EXT_VTX, ZYDIS_ISA_EXT_WAITPKG, ZYDIS_ISA_EXT_WRMSRNS, ZYDIS_ISA_EXT_X87, ZYDIS_ISA_EXT_XOP, ZYDIS_ISA_EXT_XSAVE, ZYDIS_ISA_EXT_XSAVEC, ZYDIS_ISA_EXT_XSAVEOPT, ZYDIS_ISA_EXT_XSAVES, /** * Maximum value of this enum. */ ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE) } ZydisISAExt; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * Returns the specified instruction category string. * * @param category The instruction category. * * @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed. */ ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category); /** * Returns the specified isa-set string. * * @param isa_set The isa-set. * * @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed. */ ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set); /** * Returns the specified isa-extension string. * * @param isa_ext The isa-extension. * * @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed. */ ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext); /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_METAINFO_H */ // // Header: Zydis/Mnemonic.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Mnemonic constant definitions and helper functions. */ #ifndef ZYDIS_MNEMONIC_H #define ZYDIS_MNEMONIC_H // // Header: Zydis/ShortString.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/Mnemonic.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Defines the immutable and storage-efficient `ZydisShortString` struct, which * is used to store strings in the generated tables. */ #ifndef ZYDIS_SHORTSTRING_H #define ZYDIS_SHORTSTRING_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ #if !defined(ZYAN_APPLE) # pragma pack(push, 1) #endif /** * Defines the `ZydisShortString` struct. * * This compact struct is mainly used for internal string-tables to save up some bytes. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZydisShortString_ { /** * The buffer that contains the actual (null-terminated) string. */ const char* data; /** * The length (number of characters) of the string (without 0-termination). */ ZyanU8 size; } ZydisShortString; #if !defined(ZYAN_APPLE) # pragma pack(pop) #endif /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /** * Declares a `ZydisShortString` from a static C-style string. * * @param string The C-string constant. */ #define ZYDIS_MAKE_SHORTSTRING(string) \ { string, sizeof(string) - 1 } /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_SHORTSTRING_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ // // Header: Zydis/Generated/EnumMnemonic.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/Mnemonic.h // /** * Defines the `ZydisMnemonic` enum. */ typedef enum ZydisMnemonic_ { ZYDIS_MNEMONIC_INVALID, ZYDIS_MNEMONIC_AAA, ZYDIS_MNEMONIC_AAD, ZYDIS_MNEMONIC_AADD, ZYDIS_MNEMONIC_AAM, ZYDIS_MNEMONIC_AAND, ZYDIS_MNEMONIC_AAS, ZYDIS_MNEMONIC_ADC, ZYDIS_MNEMONIC_ADCX, ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_ADDPD, ZYDIS_MNEMONIC_ADDPS, ZYDIS_MNEMONIC_ADDSD, ZYDIS_MNEMONIC_ADDSS, ZYDIS_MNEMONIC_ADDSUBPD, ZYDIS_MNEMONIC_ADDSUBPS, ZYDIS_MNEMONIC_ADOX, ZYDIS_MNEMONIC_AESDEC, ZYDIS_MNEMONIC_AESDEC128KL, ZYDIS_MNEMONIC_AESDEC256KL, ZYDIS_MNEMONIC_AESDECLAST, ZYDIS_MNEMONIC_AESDECWIDE128KL, ZYDIS_MNEMONIC_AESDECWIDE256KL, ZYDIS_MNEMONIC_AESENC, ZYDIS_MNEMONIC_AESENC128KL, ZYDIS_MNEMONIC_AESENC256KL, ZYDIS_MNEMONIC_AESENCLAST, ZYDIS_MNEMONIC_AESENCWIDE128KL, ZYDIS_MNEMONIC_AESENCWIDE256KL, ZYDIS_MNEMONIC_AESIMC, ZYDIS_MNEMONIC_AESKEYGENASSIST, ZYDIS_MNEMONIC_AND, ZYDIS_MNEMONIC_ANDN, ZYDIS_MNEMONIC_ANDNPD, ZYDIS_MNEMONIC_ANDNPS, ZYDIS_MNEMONIC_ANDPD, ZYDIS_MNEMONIC_ANDPS, ZYDIS_MNEMONIC_AOR, ZYDIS_MNEMONIC_ARPL, ZYDIS_MNEMONIC_AXOR, ZYDIS_MNEMONIC_BEXTR, ZYDIS_MNEMONIC_BLCFILL, ZYDIS_MNEMONIC_BLCI, ZYDIS_MNEMONIC_BLCIC, ZYDIS_MNEMONIC_BLCMSK, ZYDIS_MNEMONIC_BLCS, ZYDIS_MNEMONIC_BLENDPD, ZYDIS_MNEMONIC_BLENDPS, ZYDIS_MNEMONIC_BLENDVPD, ZYDIS_MNEMONIC_BLENDVPS, ZYDIS_MNEMONIC_BLSFILL, ZYDIS_MNEMONIC_BLSI, ZYDIS_MNEMONIC_BLSIC, ZYDIS_MNEMONIC_BLSMSK, ZYDIS_MNEMONIC_BLSR, ZYDIS_MNEMONIC_BNDCL, ZYDIS_MNEMONIC_BNDCN, ZYDIS_MNEMONIC_BNDCU, ZYDIS_MNEMONIC_BNDLDX, ZYDIS_MNEMONIC_BNDMK, ZYDIS_MNEMONIC_BNDMOV, ZYDIS_MNEMONIC_BNDSTX, ZYDIS_MNEMONIC_BOUND, ZYDIS_MNEMONIC_BSF, ZYDIS_MNEMONIC_BSR, ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BT, ZYDIS_MNEMONIC_BTC, ZYDIS_MNEMONIC_BTR, ZYDIS_MNEMONIC_BTS, ZYDIS_MNEMONIC_BZHI, ZYDIS_MNEMONIC_CALL, ZYDIS_MNEMONIC_CBW, ZYDIS_MNEMONIC_CDQ, ZYDIS_MNEMONIC_CDQE, ZYDIS_MNEMONIC_CLAC, ZYDIS_MNEMONIC_CLC, ZYDIS_MNEMONIC_CLD, ZYDIS_MNEMONIC_CLDEMOTE, ZYDIS_MNEMONIC_CLEVICT0, ZYDIS_MNEMONIC_CLEVICT1, ZYDIS_MNEMONIC_CLFLUSH, ZYDIS_MNEMONIC_CLFLUSHOPT, ZYDIS_MNEMONIC_CLGI, ZYDIS_MNEMONIC_CLI, ZYDIS_MNEMONIC_CLRSSBSY, ZYDIS_MNEMONIC_CLTS, ZYDIS_MNEMONIC_CLUI, ZYDIS_MNEMONIC_CLWB, ZYDIS_MNEMONIC_CLZERO, ZYDIS_MNEMONIC_CMC, ZYDIS_MNEMONIC_CMOVB, ZYDIS_MNEMONIC_CMOVBE, ZYDIS_MNEMONIC_CMOVL, ZYDIS_MNEMONIC_CMOVLE, ZYDIS_MNEMONIC_CMOVNB, ZYDIS_MNEMONIC_CMOVNBE, ZYDIS_MNEMONIC_CMOVNL, ZYDIS_MNEMONIC_CMOVNLE, ZYDIS_MNEMONIC_CMOVNO, ZYDIS_MNEMONIC_CMOVNP, ZYDIS_MNEMONIC_CMOVNS, ZYDIS_MNEMONIC_CMOVNZ, ZYDIS_MNEMONIC_CMOVO, ZYDIS_MNEMONIC_CMOVP, ZYDIS_MNEMONIC_CMOVS, ZYDIS_MNEMONIC_CMOVZ, ZYDIS_MNEMONIC_CMP, ZYDIS_MNEMONIC_CMPPD, ZYDIS_MNEMONIC_CMPPS, ZYDIS_MNEMONIC_CMPSB, ZYDIS_MNEMONIC_CMPSD, ZYDIS_MNEMONIC_CMPSQ, ZYDIS_MNEMONIC_CMPSS, ZYDIS_MNEMONIC_CMPSW, ZYDIS_MNEMONIC_CMPXCHG, ZYDIS_MNEMONIC_CMPXCHG16B, ZYDIS_MNEMONIC_CMPXCHG8B, ZYDIS_MNEMONIC_COMISD, ZYDIS_MNEMONIC_COMISS, ZYDIS_MNEMONIC_CPUID, ZYDIS_MNEMONIC_CQO, ZYDIS_MNEMONIC_CRC32, ZYDIS_MNEMONIC_CVTDQ2PD, ZYDIS_MNEMONIC_CVTDQ2PS, ZYDIS_MNEMONIC_CVTPD2DQ, ZYDIS_MNEMONIC_CVTPD2PI, ZYDIS_MNEMONIC_CVTPD2PS, ZYDIS_MNEMONIC_CVTPI2PD, ZYDIS_MNEMONIC_CVTPI2PS, ZYDIS_MNEMONIC_CVTPS2DQ, ZYDIS_MNEMONIC_CVTPS2PD, ZYDIS_MNEMONIC_CVTPS2PI, ZYDIS_MNEMONIC_CVTSD2SI, ZYDIS_MNEMONIC_CVTSD2SS, ZYDIS_MNEMONIC_CVTSI2SD, ZYDIS_MNEMONIC_CVTSI2SS, ZYDIS_MNEMONIC_CVTSS2SD, ZYDIS_MNEMONIC_CVTSS2SI, ZYDIS_MNEMONIC_CVTTPD2DQ, ZYDIS_MNEMONIC_CVTTPD2PI, ZYDIS_MNEMONIC_CVTTPS2DQ, ZYDIS_MNEMONIC_CVTTPS2PI, ZYDIS_MNEMONIC_CVTTSD2SI, ZYDIS_MNEMONIC_CVTTSS2SI, ZYDIS_MNEMONIC_CWD, ZYDIS_MNEMONIC_CWDE, ZYDIS_MNEMONIC_DAA, ZYDIS_MNEMONIC_DAS, ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_DELAY, ZYDIS_MNEMONIC_DIV, ZYDIS_MNEMONIC_DIVPD, ZYDIS_MNEMONIC_DIVPS, ZYDIS_MNEMONIC_DIVSD, ZYDIS_MNEMONIC_DIVSS, ZYDIS_MNEMONIC_DPPD, ZYDIS_MNEMONIC_DPPS, ZYDIS_MNEMONIC_EMMS, ZYDIS_MNEMONIC_ENCLS, ZYDIS_MNEMONIC_ENCLU, ZYDIS_MNEMONIC_ENCLV, ZYDIS_MNEMONIC_ENCODEKEY128, ZYDIS_MNEMONIC_ENCODEKEY256, ZYDIS_MNEMONIC_ENDBR32, ZYDIS_MNEMONIC_ENDBR64, ZYDIS_MNEMONIC_ENQCMD, ZYDIS_MNEMONIC_ENQCMDS, ZYDIS_MNEMONIC_ENTER, ZYDIS_MNEMONIC_EXTRACTPS, ZYDIS_MNEMONIC_EXTRQ, ZYDIS_MNEMONIC_F2XM1, ZYDIS_MNEMONIC_FABS, ZYDIS_MNEMONIC_FADD, ZYDIS_MNEMONIC_FADDP, ZYDIS_MNEMONIC_FBLD, ZYDIS_MNEMONIC_FBSTP, ZYDIS_MNEMONIC_FCHS, ZYDIS_MNEMONIC_FCMOVB, ZYDIS_MNEMONIC_FCMOVBE, ZYDIS_MNEMONIC_FCMOVE, ZYDIS_MNEMONIC_FCMOVNB, ZYDIS_MNEMONIC_FCMOVNBE, ZYDIS_MNEMONIC_FCMOVNE, ZYDIS_MNEMONIC_FCMOVNU, ZYDIS_MNEMONIC_FCMOVU, ZYDIS_MNEMONIC_FCOM, ZYDIS_MNEMONIC_FCOMI, ZYDIS_MNEMONIC_FCOMIP, ZYDIS_MNEMONIC_FCOMP, ZYDIS_MNEMONIC_FCOMPP, ZYDIS_MNEMONIC_FCOS, ZYDIS_MNEMONIC_FDECSTP, ZYDIS_MNEMONIC_FDISI8087_NOP, ZYDIS_MNEMONIC_FDIV, ZYDIS_MNEMONIC_FDIVP, ZYDIS_MNEMONIC_FDIVR, ZYDIS_MNEMONIC_FDIVRP, ZYDIS_MNEMONIC_FEMMS, ZYDIS_MNEMONIC_FENI8087_NOP, ZYDIS_MNEMONIC_FFREE, ZYDIS_MNEMONIC_FFREEP, ZYDIS_MNEMONIC_FIADD, ZYDIS_MNEMONIC_FICOM, ZYDIS_MNEMONIC_FICOMP, ZYDIS_MNEMONIC_FIDIV, ZYDIS_MNEMONIC_FIDIVR, ZYDIS_MNEMONIC_FILD, ZYDIS_MNEMONIC_FIMUL, ZYDIS_MNEMONIC_FINCSTP, ZYDIS_MNEMONIC_FIST, ZYDIS_MNEMONIC_FISTP, ZYDIS_MNEMONIC_FISTTP, ZYDIS_MNEMONIC_FISUB, ZYDIS_MNEMONIC_FISUBR, ZYDIS_MNEMONIC_FLD, ZYDIS_MNEMONIC_FLD1, ZYDIS_MNEMONIC_FLDCW, ZYDIS_MNEMONIC_FLDENV, ZYDIS_MNEMONIC_FLDL2E, ZYDIS_MNEMONIC_FLDL2T, ZYDIS_MNEMONIC_FLDLG2, ZYDIS_MNEMONIC_FLDLN2, ZYDIS_MNEMONIC_FLDPI, ZYDIS_MNEMONIC_FLDZ, ZYDIS_MNEMONIC_FMUL, ZYDIS_MNEMONIC_FMULP, ZYDIS_MNEMONIC_FNCLEX, ZYDIS_MNEMONIC_FNINIT, ZYDIS_MNEMONIC_FNOP, ZYDIS_MNEMONIC_FNSAVE, ZYDIS_MNEMONIC_FNSTCW, ZYDIS_MNEMONIC_FNSTENV, ZYDIS_MNEMONIC_FNSTSW, ZYDIS_MNEMONIC_FPATAN, ZYDIS_MNEMONIC_FPREM, ZYDIS_MNEMONIC_FPREM1, ZYDIS_MNEMONIC_FPTAN, ZYDIS_MNEMONIC_FRNDINT, ZYDIS_MNEMONIC_FRSTOR, ZYDIS_MNEMONIC_FSCALE, ZYDIS_MNEMONIC_FSETPM287_NOP, ZYDIS_MNEMONIC_FSIN, ZYDIS_MNEMONIC_FSINCOS, ZYDIS_MNEMONIC_FSQRT, ZYDIS_MNEMONIC_FST, ZYDIS_MNEMONIC_FSTP, ZYDIS_MNEMONIC_FSTPNCE, ZYDIS_MNEMONIC_FSUB, ZYDIS_MNEMONIC_FSUBP, ZYDIS_MNEMONIC_FSUBR, ZYDIS_MNEMONIC_FSUBRP, ZYDIS_MNEMONIC_FTST, ZYDIS_MNEMONIC_FUCOM, ZYDIS_MNEMONIC_FUCOMI, ZYDIS_MNEMONIC_FUCOMIP, ZYDIS_MNEMONIC_FUCOMP, ZYDIS_MNEMONIC_FUCOMPP, ZYDIS_MNEMONIC_FWAIT, ZYDIS_MNEMONIC_FXAM, ZYDIS_MNEMONIC_FXCH, ZYDIS_MNEMONIC_FXRSTOR, ZYDIS_MNEMONIC_FXRSTOR64, ZYDIS_MNEMONIC_FXSAVE, ZYDIS_MNEMONIC_FXSAVE64, ZYDIS_MNEMONIC_FXTRACT, ZYDIS_MNEMONIC_FYL2X, ZYDIS_MNEMONIC_FYL2XP1, ZYDIS_MNEMONIC_GETSEC, ZYDIS_MNEMONIC_GF2P8AFFINEINVQB, ZYDIS_MNEMONIC_GF2P8AFFINEQB, ZYDIS_MNEMONIC_GF2P8MULB, ZYDIS_MNEMONIC_HADDPD, ZYDIS_MNEMONIC_HADDPS, ZYDIS_MNEMONIC_HLT, ZYDIS_MNEMONIC_HRESET, ZYDIS_MNEMONIC_HSUBPD, ZYDIS_MNEMONIC_HSUBPS, ZYDIS_MNEMONIC_IDIV, ZYDIS_MNEMONIC_IMUL, ZYDIS_MNEMONIC_IN, ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_INCSSPD, ZYDIS_MNEMONIC_INCSSPQ, ZYDIS_MNEMONIC_INSB, ZYDIS_MNEMONIC_INSD, ZYDIS_MNEMONIC_INSERTPS, ZYDIS_MNEMONIC_INSERTQ, ZYDIS_MNEMONIC_INSW, ZYDIS_MNEMONIC_INT, ZYDIS_MNEMONIC_INT1, ZYDIS_MNEMONIC_INT3, ZYDIS_MNEMONIC_INTO, ZYDIS_MNEMONIC_INVD, ZYDIS_MNEMONIC_INVEPT, ZYDIS_MNEMONIC_INVLPG, ZYDIS_MNEMONIC_INVLPGA, ZYDIS_MNEMONIC_INVLPGB, ZYDIS_MNEMONIC_INVPCID, ZYDIS_MNEMONIC_INVVPID, ZYDIS_MNEMONIC_IRET, ZYDIS_MNEMONIC_IRETD, ZYDIS_MNEMONIC_IRETQ, ZYDIS_MNEMONIC_JB, ZYDIS_MNEMONIC_JBE, ZYDIS_MNEMONIC_JCXZ, ZYDIS_MNEMONIC_JECXZ, ZYDIS_MNEMONIC_JKNZD, ZYDIS_MNEMONIC_JKZD, ZYDIS_MNEMONIC_JL, ZYDIS_MNEMONIC_JLE, ZYDIS_MNEMONIC_JMP, ZYDIS_MNEMONIC_JNB, ZYDIS_MNEMONIC_JNBE, ZYDIS_MNEMONIC_JNL, ZYDIS_MNEMONIC_JNLE, ZYDIS_MNEMONIC_JNO, ZYDIS_MNEMONIC_JNP, ZYDIS_MNEMONIC_JNS, ZYDIS_MNEMONIC_JNZ, ZYDIS_MNEMONIC_JO, ZYDIS_MNEMONIC_JP, ZYDIS_MNEMONIC_JRCXZ, ZYDIS_MNEMONIC_JS, ZYDIS_MNEMONIC_JZ, ZYDIS_MNEMONIC_KADDB, ZYDIS_MNEMONIC_KADDD, ZYDIS_MNEMONIC_KADDQ, ZYDIS_MNEMONIC_KADDW, ZYDIS_MNEMONIC_KAND, ZYDIS_MNEMONIC_KANDB, ZYDIS_MNEMONIC_KANDD, ZYDIS_MNEMONIC_KANDN, ZYDIS_MNEMONIC_KANDNB, ZYDIS_MNEMONIC_KANDND, ZYDIS_MNEMONIC_KANDNQ, ZYDIS_MNEMONIC_KANDNR, ZYDIS_MNEMONIC_KANDNW, ZYDIS_MNEMONIC_KANDQ, ZYDIS_MNEMONIC_KANDW, ZYDIS_MNEMONIC_KCONCATH, ZYDIS_MNEMONIC_KCONCATL, ZYDIS_MNEMONIC_KEXTRACT, ZYDIS_MNEMONIC_KMERGE2L1H, ZYDIS_MNEMONIC_KMERGE2L1L, ZYDIS_MNEMONIC_KMOV, ZYDIS_MNEMONIC_KMOVB, ZYDIS_MNEMONIC_KMOVD, ZYDIS_MNEMONIC_KMOVQ, ZYDIS_MNEMONIC_KMOVW, ZYDIS_MNEMONIC_KNOT, ZYDIS_MNEMONIC_KNOTB, ZYDIS_MNEMONIC_KNOTD, ZYDIS_MNEMONIC_KNOTQ, ZYDIS_MNEMONIC_KNOTW, ZYDIS_MNEMONIC_KOR, ZYDIS_MNEMONIC_KORB, ZYDIS_MNEMONIC_KORD, ZYDIS_MNEMONIC_KORQ, ZYDIS_MNEMONIC_KORTEST, ZYDIS_MNEMONIC_KORTESTB, ZYDIS_MNEMONIC_KORTESTD, ZYDIS_MNEMONIC_KORTESTQ, ZYDIS_MNEMONIC_KORTESTW, ZYDIS_MNEMONIC_KORW, ZYDIS_MNEMONIC_KSHIFTLB, ZYDIS_MNEMONIC_KSHIFTLD, ZYDIS_MNEMONIC_KSHIFTLQ, ZYDIS_MNEMONIC_KSHIFTLW, ZYDIS_MNEMONIC_KSHIFTRB, ZYDIS_MNEMONIC_KSHIFTRD, ZYDIS_MNEMONIC_KSHIFTRQ, ZYDIS_MNEMONIC_KSHIFTRW, ZYDIS_MNEMONIC_KTESTB, ZYDIS_MNEMONIC_KTESTD, ZYDIS_MNEMONIC_KTESTQ, ZYDIS_MNEMONIC_KTESTW, ZYDIS_MNEMONIC_KUNPCKBW, ZYDIS_MNEMONIC_KUNPCKDQ, ZYDIS_MNEMONIC_KUNPCKWD, ZYDIS_MNEMONIC_KXNOR, ZYDIS_MNEMONIC_KXNORB, ZYDIS_MNEMONIC_KXNORD, ZYDIS_MNEMONIC_KXNORQ, ZYDIS_MNEMONIC_KXNORW, ZYDIS_MNEMONIC_KXOR, ZYDIS_MNEMONIC_KXORB, ZYDIS_MNEMONIC_KXORD, ZYDIS_MNEMONIC_KXORQ, ZYDIS_MNEMONIC_KXORW, ZYDIS_MNEMONIC_LAHF, ZYDIS_MNEMONIC_LAR, ZYDIS_MNEMONIC_LDDQU, ZYDIS_MNEMONIC_LDMXCSR, ZYDIS_MNEMONIC_LDS, ZYDIS_MNEMONIC_LDTILECFG, ZYDIS_MNEMONIC_LEA, ZYDIS_MNEMONIC_LEAVE, ZYDIS_MNEMONIC_LES, ZYDIS_MNEMONIC_LFENCE, ZYDIS_MNEMONIC_LFS, ZYDIS_MNEMONIC_LGDT, ZYDIS_MNEMONIC_LGS, ZYDIS_MNEMONIC_LIDT, ZYDIS_MNEMONIC_LLDT, ZYDIS_MNEMONIC_LLWPCB, ZYDIS_MNEMONIC_LMSW, ZYDIS_MNEMONIC_LOADIWKEY, ZYDIS_MNEMONIC_LODSB, ZYDIS_MNEMONIC_LODSD, ZYDIS_MNEMONIC_LODSQ, ZYDIS_MNEMONIC_LODSW, ZYDIS_MNEMONIC_LOOP, ZYDIS_MNEMONIC_LOOPE, ZYDIS_MNEMONIC_LOOPNE, ZYDIS_MNEMONIC_LSL, ZYDIS_MNEMONIC_LSS, ZYDIS_MNEMONIC_LTR, ZYDIS_MNEMONIC_LWPINS, ZYDIS_MNEMONIC_LWPVAL, ZYDIS_MNEMONIC_LZCNT, ZYDIS_MNEMONIC_MASKMOVDQU, ZYDIS_MNEMONIC_MASKMOVQ, ZYDIS_MNEMONIC_MAXPD, ZYDIS_MNEMONIC_MAXPS, ZYDIS_MNEMONIC_MAXSD, ZYDIS_MNEMONIC_MAXSS, ZYDIS_MNEMONIC_MCOMMIT, ZYDIS_MNEMONIC_MFENCE, ZYDIS_MNEMONIC_MINPD, ZYDIS_MNEMONIC_MINPS, ZYDIS_MNEMONIC_MINSD, ZYDIS_MNEMONIC_MINSS, ZYDIS_MNEMONIC_MONITOR, ZYDIS_MNEMONIC_MONITORX, ZYDIS_MNEMONIC_MONTMUL, ZYDIS_MNEMONIC_MOV, ZYDIS_MNEMONIC_MOVAPD, ZYDIS_MNEMONIC_MOVAPS, ZYDIS_MNEMONIC_MOVBE, ZYDIS_MNEMONIC_MOVD, ZYDIS_MNEMONIC_MOVDDUP, ZYDIS_MNEMONIC_MOVDIR64B, ZYDIS_MNEMONIC_MOVDIRI, ZYDIS_MNEMONIC_MOVDQ2Q, ZYDIS_MNEMONIC_MOVDQA, ZYDIS_MNEMONIC_MOVDQU, ZYDIS_MNEMONIC_MOVHLPS, ZYDIS_MNEMONIC_MOVHPD, ZYDIS_MNEMONIC_MOVHPS, ZYDIS_MNEMONIC_MOVLHPS, ZYDIS_MNEMONIC_MOVLPD, ZYDIS_MNEMONIC_MOVLPS, ZYDIS_MNEMONIC_MOVMSKPD, ZYDIS_MNEMONIC_MOVMSKPS, ZYDIS_MNEMONIC_MOVNTDQ, ZYDIS_MNEMONIC_MOVNTDQA, ZYDIS_MNEMONIC_MOVNTI, ZYDIS_MNEMONIC_MOVNTPD, ZYDIS_MNEMONIC_MOVNTPS, ZYDIS_MNEMONIC_MOVNTQ, ZYDIS_MNEMONIC_MOVNTSD, ZYDIS_MNEMONIC_MOVNTSS, ZYDIS_MNEMONIC_MOVQ, ZYDIS_MNEMONIC_MOVQ2DQ, ZYDIS_MNEMONIC_MOVSB, ZYDIS_MNEMONIC_MOVSD, ZYDIS_MNEMONIC_MOVSHDUP, ZYDIS_MNEMONIC_MOVSLDUP, ZYDIS_MNEMONIC_MOVSQ, ZYDIS_MNEMONIC_MOVSS, ZYDIS_MNEMONIC_MOVSW, ZYDIS_MNEMONIC_MOVSX, ZYDIS_MNEMONIC_MOVSXD, ZYDIS_MNEMONIC_MOVUPD, ZYDIS_MNEMONIC_MOVUPS, ZYDIS_MNEMONIC_MOVZX, ZYDIS_MNEMONIC_MPSADBW, ZYDIS_MNEMONIC_MUL, ZYDIS_MNEMONIC_MULPD, ZYDIS_MNEMONIC_MULPS, ZYDIS_MNEMONIC_MULSD, ZYDIS_MNEMONIC_MULSS, ZYDIS_MNEMONIC_MULX, ZYDIS_MNEMONIC_MWAIT, ZYDIS_MNEMONIC_MWAITX, ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NOP, ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_OR, ZYDIS_MNEMONIC_ORPD, ZYDIS_MNEMONIC_ORPS, ZYDIS_MNEMONIC_OUT, ZYDIS_MNEMONIC_OUTSB, ZYDIS_MNEMONIC_OUTSD, ZYDIS_MNEMONIC_OUTSW, ZYDIS_MNEMONIC_PABSB, ZYDIS_MNEMONIC_PABSD, ZYDIS_MNEMONIC_PABSW, ZYDIS_MNEMONIC_PACKSSDW, ZYDIS_MNEMONIC_PACKSSWB, ZYDIS_MNEMONIC_PACKUSDW, ZYDIS_MNEMONIC_PACKUSWB, ZYDIS_MNEMONIC_PADDB, ZYDIS_MNEMONIC_PADDD, ZYDIS_MNEMONIC_PADDQ, ZYDIS_MNEMONIC_PADDSB, ZYDIS_MNEMONIC_PADDSW, ZYDIS_MNEMONIC_PADDUSB, ZYDIS_MNEMONIC_PADDUSW, ZYDIS_MNEMONIC_PADDW, ZYDIS_MNEMONIC_PALIGNR, ZYDIS_MNEMONIC_PAND, ZYDIS_MNEMONIC_PANDN, ZYDIS_MNEMONIC_PAUSE, ZYDIS_MNEMONIC_PAVGB, ZYDIS_MNEMONIC_PAVGUSB, ZYDIS_MNEMONIC_PAVGW, ZYDIS_MNEMONIC_PBLENDVB, ZYDIS_MNEMONIC_PBLENDW, ZYDIS_MNEMONIC_PBNDKB, ZYDIS_MNEMONIC_PCLMULQDQ, ZYDIS_MNEMONIC_PCMPEQB, ZYDIS_MNEMONIC_PCMPEQD, ZYDIS_MNEMONIC_PCMPEQQ, ZYDIS_MNEMONIC_PCMPEQW, ZYDIS_MNEMONIC_PCMPESTRI, ZYDIS_MNEMONIC_PCMPESTRM, ZYDIS_MNEMONIC_PCMPGTB, ZYDIS_MNEMONIC_PCMPGTD, ZYDIS_MNEMONIC_PCMPGTQ, ZYDIS_MNEMONIC_PCMPGTW, ZYDIS_MNEMONIC_PCMPISTRI, ZYDIS_MNEMONIC_PCMPISTRM, ZYDIS_MNEMONIC_PCOMMIT, ZYDIS_MNEMONIC_PCONFIG, ZYDIS_MNEMONIC_PDEP, ZYDIS_MNEMONIC_PEXT, ZYDIS_MNEMONIC_PEXTRB, ZYDIS_MNEMONIC_PEXTRD, ZYDIS_MNEMONIC_PEXTRQ, ZYDIS_MNEMONIC_PEXTRW, ZYDIS_MNEMONIC_PF2ID, ZYDIS_MNEMONIC_PF2IW, ZYDIS_MNEMONIC_PFACC, ZYDIS_MNEMONIC_PFADD, ZYDIS_MNEMONIC_PFCMPEQ, ZYDIS_MNEMONIC_PFCMPGE, ZYDIS_MNEMONIC_PFCMPGT, ZYDIS_MNEMONIC_PFCPIT1, ZYDIS_MNEMONIC_PFMAX, ZYDIS_MNEMONIC_PFMIN, ZYDIS_MNEMONIC_PFMUL, ZYDIS_MNEMONIC_PFNACC, ZYDIS_MNEMONIC_PFPNACC, ZYDIS_MNEMONIC_PFRCP, ZYDIS_MNEMONIC_PFRCPIT2, ZYDIS_MNEMONIC_PFRSQIT1, ZYDIS_MNEMONIC_PFSQRT, ZYDIS_MNEMONIC_PFSUB, ZYDIS_MNEMONIC_PFSUBR, ZYDIS_MNEMONIC_PHADDD, ZYDIS_MNEMONIC_PHADDSW, ZYDIS_MNEMONIC_PHADDW, ZYDIS_MNEMONIC_PHMINPOSUW, ZYDIS_MNEMONIC_PHSUBD, ZYDIS_MNEMONIC_PHSUBSW, ZYDIS_MNEMONIC_PHSUBW, ZYDIS_MNEMONIC_PI2FD, ZYDIS_MNEMONIC_PI2FW, ZYDIS_MNEMONIC_PINSRB, ZYDIS_MNEMONIC_PINSRD, ZYDIS_MNEMONIC_PINSRQ, ZYDIS_MNEMONIC_PINSRW, ZYDIS_MNEMONIC_PMADDUBSW, ZYDIS_MNEMONIC_PMADDWD, ZYDIS_MNEMONIC_PMAXSB, ZYDIS_MNEMONIC_PMAXSD, ZYDIS_MNEMONIC_PMAXSW, ZYDIS_MNEMONIC_PMAXUB, ZYDIS_MNEMONIC_PMAXUD, ZYDIS_MNEMONIC_PMAXUW, ZYDIS_MNEMONIC_PMINSB, ZYDIS_MNEMONIC_PMINSD, ZYDIS_MNEMONIC_PMINSW, ZYDIS_MNEMONIC_PMINUB, ZYDIS_MNEMONIC_PMINUD, ZYDIS_MNEMONIC_PMINUW, ZYDIS_MNEMONIC_PMOVMSKB, ZYDIS_MNEMONIC_PMOVSXBD, ZYDIS_MNEMONIC_PMOVSXBQ, ZYDIS_MNEMONIC_PMOVSXBW, ZYDIS_MNEMONIC_PMOVSXDQ, ZYDIS_MNEMONIC_PMOVSXWD, ZYDIS_MNEMONIC_PMOVSXWQ, ZYDIS_MNEMONIC_PMOVZXBD, ZYDIS_MNEMONIC_PMOVZXBQ, ZYDIS_MNEMONIC_PMOVZXBW, ZYDIS_MNEMONIC_PMOVZXDQ, ZYDIS_MNEMONIC_PMOVZXWD, ZYDIS_MNEMONIC_PMOVZXWQ, ZYDIS_MNEMONIC_PMULDQ, ZYDIS_MNEMONIC_PMULHRSW, ZYDIS_MNEMONIC_PMULHRW, ZYDIS_MNEMONIC_PMULHUW, ZYDIS_MNEMONIC_PMULHW, ZYDIS_MNEMONIC_PMULLD, ZYDIS_MNEMONIC_PMULLW, ZYDIS_MNEMONIC_PMULUDQ, ZYDIS_MNEMONIC_POP, ZYDIS_MNEMONIC_POPA, ZYDIS_MNEMONIC_POPAD, ZYDIS_MNEMONIC_POPCNT, ZYDIS_MNEMONIC_POPF, ZYDIS_MNEMONIC_POPFD, ZYDIS_MNEMONIC_POPFQ, ZYDIS_MNEMONIC_POR, ZYDIS_MNEMONIC_PREFETCH, ZYDIS_MNEMONIC_PREFETCHIT0, ZYDIS_MNEMONIC_PREFETCHIT1, ZYDIS_MNEMONIC_PREFETCHNTA, ZYDIS_MNEMONIC_PREFETCHT0, ZYDIS_MNEMONIC_PREFETCHT1, ZYDIS_MNEMONIC_PREFETCHT2, ZYDIS_MNEMONIC_PREFETCHW, ZYDIS_MNEMONIC_PREFETCHWT1, ZYDIS_MNEMONIC_PSADBW, ZYDIS_MNEMONIC_PSHUFB, ZYDIS_MNEMONIC_PSHUFD, ZYDIS_MNEMONIC_PSHUFHW, ZYDIS_MNEMONIC_PSHUFLW, ZYDIS_MNEMONIC_PSHUFW, ZYDIS_MNEMONIC_PSIGNB, ZYDIS_MNEMONIC_PSIGND, ZYDIS_MNEMONIC_PSIGNW, ZYDIS_MNEMONIC_PSLLD, ZYDIS_MNEMONIC_PSLLDQ, ZYDIS_MNEMONIC_PSLLQ, ZYDIS_MNEMONIC_PSLLW, ZYDIS_MNEMONIC_PSMASH, ZYDIS_MNEMONIC_PSRAD, ZYDIS_MNEMONIC_PSRAW, ZYDIS_MNEMONIC_PSRLD, ZYDIS_MNEMONIC_PSRLDQ, ZYDIS_MNEMONIC_PSRLQ, ZYDIS_MNEMONIC_PSRLW, ZYDIS_MNEMONIC_PSUBB, ZYDIS_MNEMONIC_PSUBD, ZYDIS_MNEMONIC_PSUBQ, ZYDIS_MNEMONIC_PSUBSB, ZYDIS_MNEMONIC_PSUBSW, ZYDIS_MNEMONIC_PSUBUSB, ZYDIS_MNEMONIC_PSUBUSW, ZYDIS_MNEMONIC_PSUBW, ZYDIS_MNEMONIC_PSWAPD, ZYDIS_MNEMONIC_PTEST, ZYDIS_MNEMONIC_PTWRITE, ZYDIS_MNEMONIC_PUNPCKHBW, ZYDIS_MNEMONIC_PUNPCKHDQ, ZYDIS_MNEMONIC_PUNPCKHQDQ, ZYDIS_MNEMONIC_PUNPCKHWD, ZYDIS_MNEMONIC_PUNPCKLBW, ZYDIS_MNEMONIC_PUNPCKLDQ, ZYDIS_MNEMONIC_PUNPCKLQDQ, ZYDIS_MNEMONIC_PUNPCKLWD, ZYDIS_MNEMONIC_PUSH, ZYDIS_MNEMONIC_PUSHA, ZYDIS_MNEMONIC_PUSHAD, ZYDIS_MNEMONIC_PUSHF, ZYDIS_MNEMONIC_PUSHFD, ZYDIS_MNEMONIC_PUSHFQ, ZYDIS_MNEMONIC_PVALIDATE, ZYDIS_MNEMONIC_PXOR, ZYDIS_MNEMONIC_RCL, ZYDIS_MNEMONIC_RCPPS, ZYDIS_MNEMONIC_RCPSS, ZYDIS_MNEMONIC_RCR, ZYDIS_MNEMONIC_RDFSBASE, ZYDIS_MNEMONIC_RDGSBASE, ZYDIS_MNEMONIC_RDMSR, ZYDIS_MNEMONIC_RDMSRLIST, ZYDIS_MNEMONIC_RDPID, ZYDIS_MNEMONIC_RDPKRU, ZYDIS_MNEMONIC_RDPMC, ZYDIS_MNEMONIC_RDPRU, ZYDIS_MNEMONIC_RDRAND, ZYDIS_MNEMONIC_RDSEED, ZYDIS_MNEMONIC_RDSSPD, ZYDIS_MNEMONIC_RDSSPQ, ZYDIS_MNEMONIC_RDTSC, ZYDIS_MNEMONIC_RDTSCP, ZYDIS_MNEMONIC_RET, ZYDIS_MNEMONIC_RMPADJUST, ZYDIS_MNEMONIC_RMPUPDATE, ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_RORX, ZYDIS_MNEMONIC_ROUNDPD, ZYDIS_MNEMONIC_ROUNDPS, ZYDIS_MNEMONIC_ROUNDSD, ZYDIS_MNEMONIC_ROUNDSS, ZYDIS_MNEMONIC_RSM, ZYDIS_MNEMONIC_RSQRTPS, ZYDIS_MNEMONIC_RSQRTSS, ZYDIS_MNEMONIC_RSTORSSP, ZYDIS_MNEMONIC_SAHF, ZYDIS_MNEMONIC_SALC, ZYDIS_MNEMONIC_SAR, ZYDIS_MNEMONIC_SARX, ZYDIS_MNEMONIC_SAVEPREVSSP, ZYDIS_MNEMONIC_SBB, ZYDIS_MNEMONIC_SCASB, ZYDIS_MNEMONIC_SCASD, ZYDIS_MNEMONIC_SCASQ, ZYDIS_MNEMONIC_SCASW, ZYDIS_MNEMONIC_SEAMCALL, ZYDIS_MNEMONIC_SEAMOPS, ZYDIS_MNEMONIC_SEAMRET, ZYDIS_MNEMONIC_SENDUIPI, ZYDIS_MNEMONIC_SERIALIZE, ZYDIS_MNEMONIC_SETB, ZYDIS_MNEMONIC_SETBE, ZYDIS_MNEMONIC_SETL, ZYDIS_MNEMONIC_SETLE, ZYDIS_MNEMONIC_SETNB, ZYDIS_MNEMONIC_SETNBE, ZYDIS_MNEMONIC_SETNL, ZYDIS_MNEMONIC_SETNLE, ZYDIS_MNEMONIC_SETNO, ZYDIS_MNEMONIC_SETNP, ZYDIS_MNEMONIC_SETNS, ZYDIS_MNEMONIC_SETNZ, ZYDIS_MNEMONIC_SETO, ZYDIS_MNEMONIC_SETP, ZYDIS_MNEMONIC_SETS, ZYDIS_MNEMONIC_SETSSBSY, ZYDIS_MNEMONIC_SETZ, ZYDIS_MNEMONIC_SFENCE, ZYDIS_MNEMONIC_SGDT, ZYDIS_MNEMONIC_SHA1MSG1, ZYDIS_MNEMONIC_SHA1MSG2, ZYDIS_MNEMONIC_SHA1NEXTE, ZYDIS_MNEMONIC_SHA1RNDS4, ZYDIS_MNEMONIC_SHA256MSG1, ZYDIS_MNEMONIC_SHA256MSG2, ZYDIS_MNEMONIC_SHA256RNDS2, ZYDIS_MNEMONIC_SHL, ZYDIS_MNEMONIC_SHLD, ZYDIS_MNEMONIC_SHLX, ZYDIS_MNEMONIC_SHR, ZYDIS_MNEMONIC_SHRD, ZYDIS_MNEMONIC_SHRX, ZYDIS_MNEMONIC_SHUFPD, ZYDIS_MNEMONIC_SHUFPS, ZYDIS_MNEMONIC_SIDT, ZYDIS_MNEMONIC_SKINIT, ZYDIS_MNEMONIC_SLDT, ZYDIS_MNEMONIC_SLWPCB, ZYDIS_MNEMONIC_SMSW, ZYDIS_MNEMONIC_SPFLT, ZYDIS_MNEMONIC_SQRTPD, ZYDIS_MNEMONIC_SQRTPS, ZYDIS_MNEMONIC_SQRTSD, ZYDIS_MNEMONIC_SQRTSS, ZYDIS_MNEMONIC_STAC, ZYDIS_MNEMONIC_STC, ZYDIS_MNEMONIC_STD, ZYDIS_MNEMONIC_STGI, ZYDIS_MNEMONIC_STI, ZYDIS_MNEMONIC_STMXCSR, ZYDIS_MNEMONIC_STOSB, ZYDIS_MNEMONIC_STOSD, ZYDIS_MNEMONIC_STOSQ, ZYDIS_MNEMONIC_STOSW, ZYDIS_MNEMONIC_STR, ZYDIS_MNEMONIC_STTILECFG, ZYDIS_MNEMONIC_STUI, ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_SUBPD, ZYDIS_MNEMONIC_SUBPS, ZYDIS_MNEMONIC_SUBSD, ZYDIS_MNEMONIC_SUBSS, ZYDIS_MNEMONIC_SWAPGS, ZYDIS_MNEMONIC_SYSCALL, ZYDIS_MNEMONIC_SYSENTER, ZYDIS_MNEMONIC_SYSEXIT, ZYDIS_MNEMONIC_SYSRET, ZYDIS_MNEMONIC_T1MSKC, ZYDIS_MNEMONIC_TDCALL, ZYDIS_MNEMONIC_TDPBF16PS, ZYDIS_MNEMONIC_TDPBSSD, ZYDIS_MNEMONIC_TDPBSUD, ZYDIS_MNEMONIC_TDPBUSD, ZYDIS_MNEMONIC_TDPBUUD, ZYDIS_MNEMONIC_TDPFP16PS, ZYDIS_MNEMONIC_TEST, ZYDIS_MNEMONIC_TESTUI, ZYDIS_MNEMONIC_TILELOADD, ZYDIS_MNEMONIC_TILELOADDT1, ZYDIS_MNEMONIC_TILERELEASE, ZYDIS_MNEMONIC_TILESTORED, ZYDIS_MNEMONIC_TILEZERO, ZYDIS_MNEMONIC_TLBSYNC, ZYDIS_MNEMONIC_TPAUSE, ZYDIS_MNEMONIC_TZCNT, ZYDIS_MNEMONIC_TZCNTI, ZYDIS_MNEMONIC_TZMSK, ZYDIS_MNEMONIC_UCOMISD, ZYDIS_MNEMONIC_UCOMISS, ZYDIS_MNEMONIC_UD0, ZYDIS_MNEMONIC_UD1, ZYDIS_MNEMONIC_UD2, ZYDIS_MNEMONIC_UIRET, ZYDIS_MNEMONIC_UMONITOR, ZYDIS_MNEMONIC_UMWAIT, ZYDIS_MNEMONIC_UNPCKHPD, ZYDIS_MNEMONIC_UNPCKHPS, ZYDIS_MNEMONIC_UNPCKLPD, ZYDIS_MNEMONIC_UNPCKLPS, ZYDIS_MNEMONIC_V4FMADDPS, ZYDIS_MNEMONIC_V4FMADDSS, ZYDIS_MNEMONIC_V4FNMADDPS, ZYDIS_MNEMONIC_V4FNMADDSS, ZYDIS_MNEMONIC_VADDNPD, ZYDIS_MNEMONIC_VADDNPS, ZYDIS_MNEMONIC_VADDPD, ZYDIS_MNEMONIC_VADDPH, ZYDIS_MNEMONIC_VADDPS, ZYDIS_MNEMONIC_VADDSD, ZYDIS_MNEMONIC_VADDSETSPS, ZYDIS_MNEMONIC_VADDSH, ZYDIS_MNEMONIC_VADDSS, ZYDIS_MNEMONIC_VADDSUBPD, ZYDIS_MNEMONIC_VADDSUBPS, ZYDIS_MNEMONIC_VAESDEC, ZYDIS_MNEMONIC_VAESDECLAST, ZYDIS_MNEMONIC_VAESENC, ZYDIS_MNEMONIC_VAESENCLAST, ZYDIS_MNEMONIC_VAESIMC, ZYDIS_MNEMONIC_VAESKEYGENASSIST, ZYDIS_MNEMONIC_VALIGND, ZYDIS_MNEMONIC_VALIGNQ, ZYDIS_MNEMONIC_VANDNPD, ZYDIS_MNEMONIC_VANDNPS, ZYDIS_MNEMONIC_VANDPD, ZYDIS_MNEMONIC_VANDPS, ZYDIS_MNEMONIC_VBCSTNEBF162PS, ZYDIS_MNEMONIC_VBCSTNESH2PS, ZYDIS_MNEMONIC_VBLENDMPD, ZYDIS_MNEMONIC_VBLENDMPS, ZYDIS_MNEMONIC_VBLENDPD, ZYDIS_MNEMONIC_VBLENDPS, ZYDIS_MNEMONIC_VBLENDVPD, ZYDIS_MNEMONIC_VBLENDVPS, ZYDIS_MNEMONIC_VBROADCASTF128, ZYDIS_MNEMONIC_VBROADCASTF32X2, ZYDIS_MNEMONIC_VBROADCASTF32X4, ZYDIS_MNEMONIC_VBROADCASTF32X8, ZYDIS_MNEMONIC_VBROADCASTF64X2, ZYDIS_MNEMONIC_VBROADCASTF64X4, ZYDIS_MNEMONIC_VBROADCASTI128, ZYDIS_MNEMONIC_VBROADCASTI32X2, ZYDIS_MNEMONIC_VBROADCASTI32X4, ZYDIS_MNEMONIC_VBROADCASTI32X8, ZYDIS_MNEMONIC_VBROADCASTI64X2, ZYDIS_MNEMONIC_VBROADCASTI64X4, ZYDIS_MNEMONIC_VBROADCASTSD, ZYDIS_MNEMONIC_VBROADCASTSS, ZYDIS_MNEMONIC_VCMPPD, ZYDIS_MNEMONIC_VCMPPH, ZYDIS_MNEMONIC_VCMPPS, ZYDIS_MNEMONIC_VCMPSD, ZYDIS_MNEMONIC_VCMPSH, ZYDIS_MNEMONIC_VCMPSS, ZYDIS_MNEMONIC_VCOMISD, ZYDIS_MNEMONIC_VCOMISH, ZYDIS_MNEMONIC_VCOMISS, ZYDIS_MNEMONIC_VCOMPRESSPD, ZYDIS_MNEMONIC_VCOMPRESSPS, ZYDIS_MNEMONIC_VCVTDQ2PD, ZYDIS_MNEMONIC_VCVTDQ2PH, ZYDIS_MNEMONIC_VCVTDQ2PS, ZYDIS_MNEMONIC_VCVTFXPNTDQ2PS, ZYDIS_MNEMONIC_VCVTFXPNTPD2DQ, ZYDIS_MNEMONIC_VCVTFXPNTPD2UDQ, ZYDIS_MNEMONIC_VCVTFXPNTPS2DQ, ZYDIS_MNEMONIC_VCVTFXPNTPS2UDQ, ZYDIS_MNEMONIC_VCVTFXPNTUDQ2PS, ZYDIS_MNEMONIC_VCVTNE2PS2BF16, ZYDIS_MNEMONIC_VCVTNEEBF162PS, ZYDIS_MNEMONIC_VCVTNEEPH2PS, ZYDIS_MNEMONIC_VCVTNEOBF162PS, ZYDIS_MNEMONIC_VCVTNEOPH2PS, ZYDIS_MNEMONIC_VCVTNEPS2BF16, ZYDIS_MNEMONIC_VCVTPD2DQ, ZYDIS_MNEMONIC_VCVTPD2PH, ZYDIS_MNEMONIC_VCVTPD2PS, ZYDIS_MNEMONIC_VCVTPD2QQ, ZYDIS_MNEMONIC_VCVTPD2UDQ, ZYDIS_MNEMONIC_VCVTPD2UQQ, ZYDIS_MNEMONIC_VCVTPH2DQ, ZYDIS_MNEMONIC_VCVTPH2PD, ZYDIS_MNEMONIC_VCVTPH2PS, ZYDIS_MNEMONIC_VCVTPH2PSX, ZYDIS_MNEMONIC_VCVTPH2QQ, ZYDIS_MNEMONIC_VCVTPH2UDQ, ZYDIS_MNEMONIC_VCVTPH2UQQ, ZYDIS_MNEMONIC_VCVTPH2UW, ZYDIS_MNEMONIC_VCVTPH2W, ZYDIS_MNEMONIC_VCVTPS2DQ, ZYDIS_MNEMONIC_VCVTPS2PD, ZYDIS_MNEMONIC_VCVTPS2PH, ZYDIS_MNEMONIC_VCVTPS2PHX, ZYDIS_MNEMONIC_VCVTPS2QQ, ZYDIS_MNEMONIC_VCVTPS2UDQ, ZYDIS_MNEMONIC_VCVTPS2UQQ, ZYDIS_MNEMONIC_VCVTQQ2PD, ZYDIS_MNEMONIC_VCVTQQ2PH, ZYDIS_MNEMONIC_VCVTQQ2PS, ZYDIS_MNEMONIC_VCVTSD2SH, ZYDIS_MNEMONIC_VCVTSD2SI, ZYDIS_MNEMONIC_VCVTSD2SS, ZYDIS_MNEMONIC_VCVTSD2USI, ZYDIS_MNEMONIC_VCVTSH2SD, ZYDIS_MNEMONIC_VCVTSH2SI, ZYDIS_MNEMONIC_VCVTSH2SS, ZYDIS_MNEMONIC_VCVTSH2USI, ZYDIS_MNEMONIC_VCVTSI2SD, ZYDIS_MNEMONIC_VCVTSI2SH, ZYDIS_MNEMONIC_VCVTSI2SS, ZYDIS_MNEMONIC_VCVTSS2SD, ZYDIS_MNEMONIC_VCVTSS2SH, ZYDIS_MNEMONIC_VCVTSS2SI, ZYDIS_MNEMONIC_VCVTSS2USI, ZYDIS_MNEMONIC_VCVTTPD2DQ, ZYDIS_MNEMONIC_VCVTTPD2QQ, ZYDIS_MNEMONIC_VCVTTPD2UDQ, ZYDIS_MNEMONIC_VCVTTPD2UQQ, ZYDIS_MNEMONIC_VCVTTPH2DQ, ZYDIS_MNEMONIC_VCVTTPH2QQ, ZYDIS_MNEMONIC_VCVTTPH2UDQ, ZYDIS_MNEMONIC_VCVTTPH2UQQ, ZYDIS_MNEMONIC_VCVTTPH2UW, ZYDIS_MNEMONIC_VCVTTPH2W, ZYDIS_MNEMONIC_VCVTTPS2DQ, ZYDIS_MNEMONIC_VCVTTPS2QQ, ZYDIS_MNEMONIC_VCVTTPS2UDQ, ZYDIS_MNEMONIC_VCVTTPS2UQQ, ZYDIS_MNEMONIC_VCVTTSD2SI, ZYDIS_MNEMONIC_VCVTTSD2USI, ZYDIS_MNEMONIC_VCVTTSH2SI, ZYDIS_MNEMONIC_VCVTTSH2USI, ZYDIS_MNEMONIC_VCVTTSS2SI, ZYDIS_MNEMONIC_VCVTTSS2USI, ZYDIS_MNEMONIC_VCVTUDQ2PD, ZYDIS_MNEMONIC_VCVTUDQ2PH, ZYDIS_MNEMONIC_VCVTUDQ2PS, ZYDIS_MNEMONIC_VCVTUQQ2PD, ZYDIS_MNEMONIC_VCVTUQQ2PH, ZYDIS_MNEMONIC_VCVTUQQ2PS, ZYDIS_MNEMONIC_VCVTUSI2SD, ZYDIS_MNEMONIC_VCVTUSI2SH, ZYDIS_MNEMONIC_VCVTUSI2SS, ZYDIS_MNEMONIC_VCVTUW2PH, ZYDIS_MNEMONIC_VCVTW2PH, ZYDIS_MNEMONIC_VDBPSADBW, ZYDIS_MNEMONIC_VDIVPD, ZYDIS_MNEMONIC_VDIVPH, ZYDIS_MNEMONIC_VDIVPS, ZYDIS_MNEMONIC_VDIVSD, ZYDIS_MNEMONIC_VDIVSH, ZYDIS_MNEMONIC_VDIVSS, ZYDIS_MNEMONIC_VDPBF16PS, ZYDIS_MNEMONIC_VDPPD, ZYDIS_MNEMONIC_VDPPS, ZYDIS_MNEMONIC_VERR, ZYDIS_MNEMONIC_VERW, ZYDIS_MNEMONIC_VEXP223PS, ZYDIS_MNEMONIC_VEXP2PD, ZYDIS_MNEMONIC_VEXP2PS, ZYDIS_MNEMONIC_VEXPANDPD, ZYDIS_MNEMONIC_VEXPANDPS, ZYDIS_MNEMONIC_VEXTRACTF128, ZYDIS_MNEMONIC_VEXTRACTF32X4, ZYDIS_MNEMONIC_VEXTRACTF32X8, ZYDIS_MNEMONIC_VEXTRACTF64X2, ZYDIS_MNEMONIC_VEXTRACTF64X4, ZYDIS_MNEMONIC_VEXTRACTI128, ZYDIS_MNEMONIC_VEXTRACTI32X4, ZYDIS_MNEMONIC_VEXTRACTI32X8, ZYDIS_MNEMONIC_VEXTRACTI64X2, ZYDIS_MNEMONIC_VEXTRACTI64X4, ZYDIS_MNEMONIC_VEXTRACTPS, ZYDIS_MNEMONIC_VFCMADDCPH, ZYDIS_MNEMONIC_VFCMADDCSH, ZYDIS_MNEMONIC_VFCMULCPH, ZYDIS_MNEMONIC_VFCMULCSH, ZYDIS_MNEMONIC_VFIXUPIMMPD, ZYDIS_MNEMONIC_VFIXUPIMMPS, ZYDIS_MNEMONIC_VFIXUPIMMSD, ZYDIS_MNEMONIC_VFIXUPIMMSS, ZYDIS_MNEMONIC_VFIXUPNANPD, ZYDIS_MNEMONIC_VFIXUPNANPS, ZYDIS_MNEMONIC_VFMADD132PD, ZYDIS_MNEMONIC_VFMADD132PH, ZYDIS_MNEMONIC_VFMADD132PS, ZYDIS_MNEMONIC_VFMADD132SD, ZYDIS_MNEMONIC_VFMADD132SH, ZYDIS_MNEMONIC_VFMADD132SS, ZYDIS_MNEMONIC_VFMADD213PD, ZYDIS_MNEMONIC_VFMADD213PH, ZYDIS_MNEMONIC_VFMADD213PS, ZYDIS_MNEMONIC_VFMADD213SD, ZYDIS_MNEMONIC_VFMADD213SH, ZYDIS_MNEMONIC_VFMADD213SS, ZYDIS_MNEMONIC_VFMADD231PD, ZYDIS_MNEMONIC_VFMADD231PH, ZYDIS_MNEMONIC_VFMADD231PS, ZYDIS_MNEMONIC_VFMADD231SD, ZYDIS_MNEMONIC_VFMADD231SH, ZYDIS_MNEMONIC_VFMADD231SS, ZYDIS_MNEMONIC_VFMADD233PS, ZYDIS_MNEMONIC_VFMADDCPH, ZYDIS_MNEMONIC_VFMADDCSH, ZYDIS_MNEMONIC_VFMADDPD, ZYDIS_MNEMONIC_VFMADDPS, ZYDIS_MNEMONIC_VFMADDSD, ZYDIS_MNEMONIC_VFMADDSS, ZYDIS_MNEMONIC_VFMADDSUB132PD, ZYDIS_MNEMONIC_VFMADDSUB132PH, ZYDIS_MNEMONIC_VFMADDSUB132PS, ZYDIS_MNEMONIC_VFMADDSUB213PD, ZYDIS_MNEMONIC_VFMADDSUB213PH, ZYDIS_MNEMONIC_VFMADDSUB213PS, ZYDIS_MNEMONIC_VFMADDSUB231PD, ZYDIS_MNEMONIC_VFMADDSUB231PH, ZYDIS_MNEMONIC_VFMADDSUB231PS, ZYDIS_MNEMONIC_VFMADDSUBPD, ZYDIS_MNEMONIC_VFMADDSUBPS, ZYDIS_MNEMONIC_VFMSUB132PD, ZYDIS_MNEMONIC_VFMSUB132PH, ZYDIS_MNEMONIC_VFMSUB132PS, ZYDIS_MNEMONIC_VFMSUB132SD, ZYDIS_MNEMONIC_VFMSUB132SH, ZYDIS_MNEMONIC_VFMSUB132SS, ZYDIS_MNEMONIC_VFMSUB213PD, ZYDIS_MNEMONIC_VFMSUB213PH, ZYDIS_MNEMONIC_VFMSUB213PS, ZYDIS_MNEMONIC_VFMSUB213SD, ZYDIS_MNEMONIC_VFMSUB213SH, ZYDIS_MNEMONIC_VFMSUB213SS, ZYDIS_MNEMONIC_VFMSUB231PD, ZYDIS_MNEMONIC_VFMSUB231PH, ZYDIS_MNEMONIC_VFMSUB231PS, ZYDIS_MNEMONIC_VFMSUB231SD, ZYDIS_MNEMONIC_VFMSUB231SH, ZYDIS_MNEMONIC_VFMSUB231SS, ZYDIS_MNEMONIC_VFMSUBADD132PD, ZYDIS_MNEMONIC_VFMSUBADD132PH, ZYDIS_MNEMONIC_VFMSUBADD132PS, ZYDIS_MNEMONIC_VFMSUBADD213PD, ZYDIS_MNEMONIC_VFMSUBADD213PH, ZYDIS_MNEMONIC_VFMSUBADD213PS, ZYDIS_MNEMONIC_VFMSUBADD231PD, ZYDIS_MNEMONIC_VFMSUBADD231PH, ZYDIS_MNEMONIC_VFMSUBADD231PS, ZYDIS_MNEMONIC_VFMSUBADDPD, ZYDIS_MNEMONIC_VFMSUBADDPS, ZYDIS_MNEMONIC_VFMSUBPD, ZYDIS_MNEMONIC_VFMSUBPS, ZYDIS_MNEMONIC_VFMSUBSD, ZYDIS_MNEMONIC_VFMSUBSS, ZYDIS_MNEMONIC_VFMULCPH, ZYDIS_MNEMONIC_VFMULCSH, ZYDIS_MNEMONIC_VFNMADD132PD, ZYDIS_MNEMONIC_VFNMADD132PH, ZYDIS_MNEMONIC_VFNMADD132PS, ZYDIS_MNEMONIC_VFNMADD132SD, ZYDIS_MNEMONIC_VFNMADD132SH, ZYDIS_MNEMONIC_VFNMADD132SS, ZYDIS_MNEMONIC_VFNMADD213PD, ZYDIS_MNEMONIC_VFNMADD213PH, ZYDIS_MNEMONIC_VFNMADD213PS, ZYDIS_MNEMONIC_VFNMADD213SD, ZYDIS_MNEMONIC_VFNMADD213SH, ZYDIS_MNEMONIC_VFNMADD213SS, ZYDIS_MNEMONIC_VFNMADD231PD, ZYDIS_MNEMONIC_VFNMADD231PH, ZYDIS_MNEMONIC_VFNMADD231PS, ZYDIS_MNEMONIC_VFNMADD231SD, ZYDIS_MNEMONIC_VFNMADD231SH, ZYDIS_MNEMONIC_VFNMADD231SS, ZYDIS_MNEMONIC_VFNMADDPD, ZYDIS_MNEMONIC_VFNMADDPS, ZYDIS_MNEMONIC_VFNMADDSD, ZYDIS_MNEMONIC_VFNMADDSS, ZYDIS_MNEMONIC_VFNMSUB132PD, ZYDIS_MNEMONIC_VFNMSUB132PH, ZYDIS_MNEMONIC_VFNMSUB132PS, ZYDIS_MNEMONIC_VFNMSUB132SD, ZYDIS_MNEMONIC_VFNMSUB132SH, ZYDIS_MNEMONIC_VFNMSUB132SS, ZYDIS_MNEMONIC_VFNMSUB213PD, ZYDIS_MNEMONIC_VFNMSUB213PH, ZYDIS_MNEMONIC_VFNMSUB213PS, ZYDIS_MNEMONIC_VFNMSUB213SD, ZYDIS_MNEMONIC_VFNMSUB213SH, ZYDIS_MNEMONIC_VFNMSUB213SS, ZYDIS_MNEMONIC_VFNMSUB231PD, ZYDIS_MNEMONIC_VFNMSUB231PH, ZYDIS_MNEMONIC_VFNMSUB231PS, ZYDIS_MNEMONIC_VFNMSUB231SD, ZYDIS_MNEMONIC_VFNMSUB231SH, ZYDIS_MNEMONIC_VFNMSUB231SS, ZYDIS_MNEMONIC_VFNMSUBPD, ZYDIS_MNEMONIC_VFNMSUBPS, ZYDIS_MNEMONIC_VFNMSUBSD, ZYDIS_MNEMONIC_VFNMSUBSS, ZYDIS_MNEMONIC_VFPCLASSPD, ZYDIS_MNEMONIC_VFPCLASSPH, ZYDIS_MNEMONIC_VFPCLASSPS, ZYDIS_MNEMONIC_VFPCLASSSD, ZYDIS_MNEMONIC_VFPCLASSSH, ZYDIS_MNEMONIC_VFPCLASSSS, ZYDIS_MNEMONIC_VFRCZPD, ZYDIS_MNEMONIC_VFRCZPS, ZYDIS_MNEMONIC_VFRCZSD, ZYDIS_MNEMONIC_VFRCZSS, ZYDIS_MNEMONIC_VGATHERDPD, ZYDIS_MNEMONIC_VGATHERDPS, ZYDIS_MNEMONIC_VGATHERPF0DPD, ZYDIS_MNEMONIC_VGATHERPF0DPS, ZYDIS_MNEMONIC_VGATHERPF0HINTDPD, ZYDIS_MNEMONIC_VGATHERPF0HINTDPS, ZYDIS_MNEMONIC_VGATHERPF0QPD, ZYDIS_MNEMONIC_VGATHERPF0QPS, ZYDIS_MNEMONIC_VGATHERPF1DPD, ZYDIS_MNEMONIC_VGATHERPF1DPS, ZYDIS_MNEMONIC_VGATHERPF1QPD, ZYDIS_MNEMONIC_VGATHERPF1QPS, ZYDIS_MNEMONIC_VGATHERQPD, ZYDIS_MNEMONIC_VGATHERQPS, ZYDIS_MNEMONIC_VGETEXPPD, ZYDIS_MNEMONIC_VGETEXPPH, ZYDIS_MNEMONIC_VGETEXPPS, ZYDIS_MNEMONIC_VGETEXPSD, ZYDIS_MNEMONIC_VGETEXPSH, ZYDIS_MNEMONIC_VGETEXPSS, ZYDIS_MNEMONIC_VGETMANTPD, ZYDIS_MNEMONIC_VGETMANTPH, ZYDIS_MNEMONIC_VGETMANTPS, ZYDIS_MNEMONIC_VGETMANTSD, ZYDIS_MNEMONIC_VGETMANTSH, ZYDIS_MNEMONIC_VGETMANTSS, ZYDIS_MNEMONIC_VGF2P8AFFINEINVQB, ZYDIS_MNEMONIC_VGF2P8AFFINEQB, ZYDIS_MNEMONIC_VGF2P8MULB, ZYDIS_MNEMONIC_VGMAXABSPS, ZYDIS_MNEMONIC_VGMAXPD, ZYDIS_MNEMONIC_VGMAXPS, ZYDIS_MNEMONIC_VGMINPD, ZYDIS_MNEMONIC_VGMINPS, ZYDIS_MNEMONIC_VHADDPD, ZYDIS_MNEMONIC_VHADDPS, ZYDIS_MNEMONIC_VHSUBPD, ZYDIS_MNEMONIC_VHSUBPS, ZYDIS_MNEMONIC_VINSERTF128, ZYDIS_MNEMONIC_VINSERTF32X4, ZYDIS_MNEMONIC_VINSERTF32X8, ZYDIS_MNEMONIC_VINSERTF64X2, ZYDIS_MNEMONIC_VINSERTF64X4, ZYDIS_MNEMONIC_VINSERTI128, ZYDIS_MNEMONIC_VINSERTI32X4, ZYDIS_MNEMONIC_VINSERTI32X8, ZYDIS_MNEMONIC_VINSERTI64X2, ZYDIS_MNEMONIC_VINSERTI64X4, ZYDIS_MNEMONIC_VINSERTPS, ZYDIS_MNEMONIC_VLDDQU, ZYDIS_MNEMONIC_VLDMXCSR, ZYDIS_MNEMONIC_VLOADUNPACKHD, ZYDIS_MNEMONIC_VLOADUNPACKHPD, ZYDIS_MNEMONIC_VLOADUNPACKHPS, ZYDIS_MNEMONIC_VLOADUNPACKHQ, ZYDIS_MNEMONIC_VLOADUNPACKLD, ZYDIS_MNEMONIC_VLOADUNPACKLPD, ZYDIS_MNEMONIC_VLOADUNPACKLPS, ZYDIS_MNEMONIC_VLOADUNPACKLQ, ZYDIS_MNEMONIC_VLOG2PS, ZYDIS_MNEMONIC_VMASKMOVDQU, ZYDIS_MNEMONIC_VMASKMOVPD, ZYDIS_MNEMONIC_VMASKMOVPS, ZYDIS_MNEMONIC_VMAXPD, ZYDIS_MNEMONIC_VMAXPH, ZYDIS_MNEMONIC_VMAXPS, ZYDIS_MNEMONIC_VMAXSD, ZYDIS_MNEMONIC_VMAXSH, ZYDIS_MNEMONIC_VMAXSS, ZYDIS_MNEMONIC_VMCALL, ZYDIS_MNEMONIC_VMCLEAR, ZYDIS_MNEMONIC_VMFUNC, ZYDIS_MNEMONIC_VMINPD, ZYDIS_MNEMONIC_VMINPH, ZYDIS_MNEMONIC_VMINPS, ZYDIS_MNEMONIC_VMINSD, ZYDIS_MNEMONIC_VMINSH, ZYDIS_MNEMONIC_VMINSS, ZYDIS_MNEMONIC_VMLAUNCH, ZYDIS_MNEMONIC_VMLOAD, ZYDIS_MNEMONIC_VMMCALL, ZYDIS_MNEMONIC_VMOVAPD, ZYDIS_MNEMONIC_VMOVAPS, ZYDIS_MNEMONIC_VMOVD, ZYDIS_MNEMONIC_VMOVDDUP, ZYDIS_MNEMONIC_VMOVDQA, ZYDIS_MNEMONIC_VMOVDQA32, ZYDIS_MNEMONIC_VMOVDQA64, ZYDIS_MNEMONIC_VMOVDQU, ZYDIS_MNEMONIC_VMOVDQU16, ZYDIS_MNEMONIC_VMOVDQU32, ZYDIS_MNEMONIC_VMOVDQU64, ZYDIS_MNEMONIC_VMOVDQU8, ZYDIS_MNEMONIC_VMOVHLPS, ZYDIS_MNEMONIC_VMOVHPD, ZYDIS_MNEMONIC_VMOVHPS, ZYDIS_MNEMONIC_VMOVLHPS, ZYDIS_MNEMONIC_VMOVLPD, ZYDIS_MNEMONIC_VMOVLPS, ZYDIS_MNEMONIC_VMOVMSKPD, ZYDIS_MNEMONIC_VMOVMSKPS, ZYDIS_MNEMONIC_VMOVNRAPD, ZYDIS_MNEMONIC_VMOVNRAPS, ZYDIS_MNEMONIC_VMOVNRNGOAPD, ZYDIS_MNEMONIC_VMOVNRNGOAPS, ZYDIS_MNEMONIC_VMOVNTDQ, ZYDIS_MNEMONIC_VMOVNTDQA, ZYDIS_MNEMONIC_VMOVNTPD, ZYDIS_MNEMONIC_VMOVNTPS, ZYDIS_MNEMONIC_VMOVQ, ZYDIS_MNEMONIC_VMOVSD, ZYDIS_MNEMONIC_VMOVSH, ZYDIS_MNEMONIC_VMOVSHDUP, ZYDIS_MNEMONIC_VMOVSLDUP, ZYDIS_MNEMONIC_VMOVSS, ZYDIS_MNEMONIC_VMOVUPD, ZYDIS_MNEMONIC_VMOVUPS, ZYDIS_MNEMONIC_VMOVW, ZYDIS_MNEMONIC_VMPSADBW, ZYDIS_MNEMONIC_VMPTRLD, ZYDIS_MNEMONIC_VMPTRST, ZYDIS_MNEMONIC_VMREAD, ZYDIS_MNEMONIC_VMRESUME, ZYDIS_MNEMONIC_VMRUN, ZYDIS_MNEMONIC_VMSAVE, ZYDIS_MNEMONIC_VMULPD, ZYDIS_MNEMONIC_VMULPH, ZYDIS_MNEMONIC_VMULPS, ZYDIS_MNEMONIC_VMULSD, ZYDIS_MNEMONIC_VMULSH, ZYDIS_MNEMONIC_VMULSS, ZYDIS_MNEMONIC_VMWRITE, ZYDIS_MNEMONIC_VMXOFF, ZYDIS_MNEMONIC_VMXON, ZYDIS_MNEMONIC_VORPD, ZYDIS_MNEMONIC_VORPS, ZYDIS_MNEMONIC_VP2INTERSECTD, ZYDIS_MNEMONIC_VP2INTERSECTQ, ZYDIS_MNEMONIC_VP4DPWSSD, ZYDIS_MNEMONIC_VP4DPWSSDS, ZYDIS_MNEMONIC_VPABSB, ZYDIS_MNEMONIC_VPABSD, ZYDIS_MNEMONIC_VPABSQ, ZYDIS_MNEMONIC_VPABSW, ZYDIS_MNEMONIC_VPACKSSDW, ZYDIS_MNEMONIC_VPACKSSWB, ZYDIS_MNEMONIC_VPACKSTOREHD, ZYDIS_MNEMONIC_VPACKSTOREHPD, ZYDIS_MNEMONIC_VPACKSTOREHPS, ZYDIS_MNEMONIC_VPACKSTOREHQ, ZYDIS_MNEMONIC_VPACKSTORELD, ZYDIS_MNEMONIC_VPACKSTORELPD, ZYDIS_MNEMONIC_VPACKSTORELPS, ZYDIS_MNEMONIC_VPACKSTORELQ, ZYDIS_MNEMONIC_VPACKUSDW, ZYDIS_MNEMONIC_VPACKUSWB, ZYDIS_MNEMONIC_VPADCD, ZYDIS_MNEMONIC_VPADDB, ZYDIS_MNEMONIC_VPADDD, ZYDIS_MNEMONIC_VPADDQ, ZYDIS_MNEMONIC_VPADDSB, ZYDIS_MNEMONIC_VPADDSETCD, ZYDIS_MNEMONIC_VPADDSETSD, ZYDIS_MNEMONIC_VPADDSW, ZYDIS_MNEMONIC_VPADDUSB, ZYDIS_MNEMONIC_VPADDUSW, ZYDIS_MNEMONIC_VPADDW, ZYDIS_MNEMONIC_VPALIGNR, ZYDIS_MNEMONIC_VPAND, ZYDIS_MNEMONIC_VPANDD, ZYDIS_MNEMONIC_VPANDN, ZYDIS_MNEMONIC_VPANDND, ZYDIS_MNEMONIC_VPANDNQ, ZYDIS_MNEMONIC_VPANDQ, ZYDIS_MNEMONIC_VPAVGB, ZYDIS_MNEMONIC_VPAVGW, ZYDIS_MNEMONIC_VPBLENDD, ZYDIS_MNEMONIC_VPBLENDMB, ZYDIS_MNEMONIC_VPBLENDMD, ZYDIS_MNEMONIC_VPBLENDMQ, ZYDIS_MNEMONIC_VPBLENDMW, ZYDIS_MNEMONIC_VPBLENDVB, ZYDIS_MNEMONIC_VPBLENDW, ZYDIS_MNEMONIC_VPBROADCASTB, ZYDIS_MNEMONIC_VPBROADCASTD, ZYDIS_MNEMONIC_VPBROADCASTMB2Q, ZYDIS_MNEMONIC_VPBROADCASTMW2D, ZYDIS_MNEMONIC_VPBROADCASTQ, ZYDIS_MNEMONIC_VPBROADCASTW, ZYDIS_MNEMONIC_VPCLMULQDQ, ZYDIS_MNEMONIC_VPCMOV, ZYDIS_MNEMONIC_VPCMPB, ZYDIS_MNEMONIC_VPCMPD, ZYDIS_MNEMONIC_VPCMPEQB, ZYDIS_MNEMONIC_VPCMPEQD, ZYDIS_MNEMONIC_VPCMPEQQ, ZYDIS_MNEMONIC_VPCMPEQW, ZYDIS_MNEMONIC_VPCMPESTRI, ZYDIS_MNEMONIC_VPCMPESTRM, ZYDIS_MNEMONIC_VPCMPGTB, ZYDIS_MNEMONIC_VPCMPGTD, ZYDIS_MNEMONIC_VPCMPGTQ, ZYDIS_MNEMONIC_VPCMPGTW, ZYDIS_MNEMONIC_VPCMPISTRI, ZYDIS_MNEMONIC_VPCMPISTRM, ZYDIS_MNEMONIC_VPCMPLTD, ZYDIS_MNEMONIC_VPCMPQ, ZYDIS_MNEMONIC_VPCMPUB, ZYDIS_MNEMONIC_VPCMPUD, ZYDIS_MNEMONIC_VPCMPUQ, ZYDIS_MNEMONIC_VPCMPUW, ZYDIS_MNEMONIC_VPCMPW, ZYDIS_MNEMONIC_VPCOMB, ZYDIS_MNEMONIC_VPCOMD, ZYDIS_MNEMONIC_VPCOMPRESSB, ZYDIS_MNEMONIC_VPCOMPRESSD, ZYDIS_MNEMONIC_VPCOMPRESSQ, ZYDIS_MNEMONIC_VPCOMPRESSW, ZYDIS_MNEMONIC_VPCOMQ, ZYDIS_MNEMONIC_VPCOMUB, ZYDIS_MNEMONIC_VPCOMUD, ZYDIS_MNEMONIC_VPCOMUQ, ZYDIS_MNEMONIC_VPCOMUW, ZYDIS_MNEMONIC_VPCOMW, ZYDIS_MNEMONIC_VPCONFLICTD, ZYDIS_MNEMONIC_VPCONFLICTQ, ZYDIS_MNEMONIC_VPDPBSSD, ZYDIS_MNEMONIC_VPDPBSSDS, ZYDIS_MNEMONIC_VPDPBSUD, ZYDIS_MNEMONIC_VPDPBSUDS, ZYDIS_MNEMONIC_VPDPBUSD, ZYDIS_MNEMONIC_VPDPBUSDS, ZYDIS_MNEMONIC_VPDPBUUD, ZYDIS_MNEMONIC_VPDPBUUDS, ZYDIS_MNEMONIC_VPDPWSSD, ZYDIS_MNEMONIC_VPDPWSSDS, ZYDIS_MNEMONIC_VPDPWSUD, ZYDIS_MNEMONIC_VPDPWSUDS, ZYDIS_MNEMONIC_VPDPWUSD, ZYDIS_MNEMONIC_VPDPWUSDS, ZYDIS_MNEMONIC_VPDPWUUD, ZYDIS_MNEMONIC_VPDPWUUDS, ZYDIS_MNEMONIC_VPERM2F128, ZYDIS_MNEMONIC_VPERM2I128, ZYDIS_MNEMONIC_VPERMB, ZYDIS_MNEMONIC_VPERMD, ZYDIS_MNEMONIC_VPERMF32X4, ZYDIS_MNEMONIC_VPERMI2B, ZYDIS_MNEMONIC_VPERMI2D, ZYDIS_MNEMONIC_VPERMI2PD, ZYDIS_MNEMONIC_VPERMI2PS, ZYDIS_MNEMONIC_VPERMI2Q, ZYDIS_MNEMONIC_VPERMI2W, ZYDIS_MNEMONIC_VPERMIL2PD, ZYDIS_MNEMONIC_VPERMIL2PS, ZYDIS_MNEMONIC_VPERMILPD, ZYDIS_MNEMONIC_VPERMILPS, ZYDIS_MNEMONIC_VPERMPD, ZYDIS_MNEMONIC_VPERMPS, ZYDIS_MNEMONIC_VPERMQ, ZYDIS_MNEMONIC_VPERMT2B, ZYDIS_MNEMONIC_VPERMT2D, ZYDIS_MNEMONIC_VPERMT2PD, ZYDIS_MNEMONIC_VPERMT2PS, ZYDIS_MNEMONIC_VPERMT2Q, ZYDIS_MNEMONIC_VPERMT2W, ZYDIS_MNEMONIC_VPERMW, ZYDIS_MNEMONIC_VPEXPANDB, ZYDIS_MNEMONIC_VPEXPANDD, ZYDIS_MNEMONIC_VPEXPANDQ, ZYDIS_MNEMONIC_VPEXPANDW, ZYDIS_MNEMONIC_VPEXTRB, ZYDIS_MNEMONIC_VPEXTRD, ZYDIS_MNEMONIC_VPEXTRQ, ZYDIS_MNEMONIC_VPEXTRW, ZYDIS_MNEMONIC_VPGATHERDD, ZYDIS_MNEMONIC_VPGATHERDQ, ZYDIS_MNEMONIC_VPGATHERQD, ZYDIS_MNEMONIC_VPGATHERQQ, ZYDIS_MNEMONIC_VPHADDBD, ZYDIS_MNEMONIC_VPHADDBQ, ZYDIS_MNEMONIC_VPHADDBW, ZYDIS_MNEMONIC_VPHADDD, ZYDIS_MNEMONIC_VPHADDDQ, ZYDIS_MNEMONIC_VPHADDSW, ZYDIS_MNEMONIC_VPHADDUBD, ZYDIS_MNEMONIC_VPHADDUBQ, ZYDIS_MNEMONIC_VPHADDUBW, ZYDIS_MNEMONIC_VPHADDUDQ, ZYDIS_MNEMONIC_VPHADDUWD, ZYDIS_MNEMONIC_VPHADDUWQ, ZYDIS_MNEMONIC_VPHADDW, ZYDIS_MNEMONIC_VPHADDWD, ZYDIS_MNEMONIC_VPHADDWQ, ZYDIS_MNEMONIC_VPHMINPOSUW, ZYDIS_MNEMONIC_VPHSUBBW, ZYDIS_MNEMONIC_VPHSUBD, ZYDIS_MNEMONIC_VPHSUBDQ, ZYDIS_MNEMONIC_VPHSUBSW, ZYDIS_MNEMONIC_VPHSUBW, ZYDIS_MNEMONIC_VPHSUBWD, ZYDIS_MNEMONIC_VPINSRB, ZYDIS_MNEMONIC_VPINSRD, ZYDIS_MNEMONIC_VPINSRQ, ZYDIS_MNEMONIC_VPINSRW, ZYDIS_MNEMONIC_VPLZCNTD, ZYDIS_MNEMONIC_VPLZCNTQ, ZYDIS_MNEMONIC_VPMACSDD, ZYDIS_MNEMONIC_VPMACSDQH, ZYDIS_MNEMONIC_VPMACSDQL, ZYDIS_MNEMONIC_VPMACSSDD, ZYDIS_MNEMONIC_VPMACSSDQH, ZYDIS_MNEMONIC_VPMACSSDQL, ZYDIS_MNEMONIC_VPMACSSWD, ZYDIS_MNEMONIC_VPMACSSWW, ZYDIS_MNEMONIC_VPMACSWD, ZYDIS_MNEMONIC_VPMACSWW, ZYDIS_MNEMONIC_VPMADCSSWD, ZYDIS_MNEMONIC_VPMADCSWD, ZYDIS_MNEMONIC_VPMADD231D, ZYDIS_MNEMONIC_VPMADD233D, ZYDIS_MNEMONIC_VPMADD52HUQ, ZYDIS_MNEMONIC_VPMADD52LUQ, ZYDIS_MNEMONIC_VPMADDUBSW, ZYDIS_MNEMONIC_VPMADDWD, ZYDIS_MNEMONIC_VPMASKMOVD, ZYDIS_MNEMONIC_VPMASKMOVQ, ZYDIS_MNEMONIC_VPMAXSB, ZYDIS_MNEMONIC_VPMAXSD, ZYDIS_MNEMONIC_VPMAXSQ, ZYDIS_MNEMONIC_VPMAXSW, ZYDIS_MNEMONIC_VPMAXUB, ZYDIS_MNEMONIC_VPMAXUD, ZYDIS_MNEMONIC_VPMAXUQ, ZYDIS_MNEMONIC_VPMAXUW, ZYDIS_MNEMONIC_VPMINSB, ZYDIS_MNEMONIC_VPMINSD, ZYDIS_MNEMONIC_VPMINSQ, ZYDIS_MNEMONIC_VPMINSW, ZYDIS_MNEMONIC_VPMINUB, ZYDIS_MNEMONIC_VPMINUD, ZYDIS_MNEMONIC_VPMINUQ, ZYDIS_MNEMONIC_VPMINUW, ZYDIS_MNEMONIC_VPMOVB2M, ZYDIS_MNEMONIC_VPMOVD2M, ZYDIS_MNEMONIC_VPMOVDB, ZYDIS_MNEMONIC_VPMOVDW, ZYDIS_MNEMONIC_VPMOVM2B, ZYDIS_MNEMONIC_VPMOVM2D, ZYDIS_MNEMONIC_VPMOVM2Q, ZYDIS_MNEMONIC_VPMOVM2W, ZYDIS_MNEMONIC_VPMOVMSKB, ZYDIS_MNEMONIC_VPMOVQ2M, ZYDIS_MNEMONIC_VPMOVQB, ZYDIS_MNEMONIC_VPMOVQD, ZYDIS_MNEMONIC_VPMOVQW, ZYDIS_MNEMONIC_VPMOVSDB, ZYDIS_MNEMONIC_VPMOVSDW, ZYDIS_MNEMONIC_VPMOVSQB, ZYDIS_MNEMONIC_VPMOVSQD, ZYDIS_MNEMONIC_VPMOVSQW, ZYDIS_MNEMONIC_VPMOVSWB, ZYDIS_MNEMONIC_VPMOVSXBD, ZYDIS_MNEMONIC_VPMOVSXBQ, ZYDIS_MNEMONIC_VPMOVSXBW, ZYDIS_MNEMONIC_VPMOVSXDQ, ZYDIS_MNEMONIC_VPMOVSXWD, ZYDIS_MNEMONIC_VPMOVSXWQ, ZYDIS_MNEMONIC_VPMOVUSDB, ZYDIS_MNEMONIC_VPMOVUSDW, ZYDIS_MNEMONIC_VPMOVUSQB, ZYDIS_MNEMONIC_VPMOVUSQD, ZYDIS_MNEMONIC_VPMOVUSQW, ZYDIS_MNEMONIC_VPMOVUSWB, ZYDIS_MNEMONIC_VPMOVW2M, ZYDIS_MNEMONIC_VPMOVWB, ZYDIS_MNEMONIC_VPMOVZXBD, ZYDIS_MNEMONIC_VPMOVZXBQ, ZYDIS_MNEMONIC_VPMOVZXBW, ZYDIS_MNEMONIC_VPMOVZXDQ, ZYDIS_MNEMONIC_VPMOVZXWD, ZYDIS_MNEMONIC_VPMOVZXWQ, ZYDIS_MNEMONIC_VPMULDQ, ZYDIS_MNEMONIC_VPMULHD, ZYDIS_MNEMONIC_VPMULHRSW, ZYDIS_MNEMONIC_VPMULHUD, ZYDIS_MNEMONIC_VPMULHUW, ZYDIS_MNEMONIC_VPMULHW, ZYDIS_MNEMONIC_VPMULLD, ZYDIS_MNEMONIC_VPMULLQ, ZYDIS_MNEMONIC_VPMULLW, ZYDIS_MNEMONIC_VPMULTISHIFTQB, ZYDIS_MNEMONIC_VPMULUDQ, ZYDIS_MNEMONIC_VPOPCNTB, ZYDIS_MNEMONIC_VPOPCNTD, ZYDIS_MNEMONIC_VPOPCNTQ, ZYDIS_MNEMONIC_VPOPCNTW, ZYDIS_MNEMONIC_VPOR, ZYDIS_MNEMONIC_VPORD, ZYDIS_MNEMONIC_VPORQ, ZYDIS_MNEMONIC_VPPERM, ZYDIS_MNEMONIC_VPREFETCH0, ZYDIS_MNEMONIC_VPREFETCH1, ZYDIS_MNEMONIC_VPREFETCH2, ZYDIS_MNEMONIC_VPREFETCHE0, ZYDIS_MNEMONIC_VPREFETCHE1, ZYDIS_MNEMONIC_VPREFETCHE2, ZYDIS_MNEMONIC_VPREFETCHENTA, ZYDIS_MNEMONIC_VPREFETCHNTA, ZYDIS_MNEMONIC_VPROLD, ZYDIS_MNEMONIC_VPROLQ, ZYDIS_MNEMONIC_VPROLVD, ZYDIS_MNEMONIC_VPROLVQ, ZYDIS_MNEMONIC_VPRORD, ZYDIS_MNEMONIC_VPRORQ, ZYDIS_MNEMONIC_VPRORVD, ZYDIS_MNEMONIC_VPRORVQ, ZYDIS_MNEMONIC_VPROTB, ZYDIS_MNEMONIC_VPROTD, ZYDIS_MNEMONIC_VPROTQ, ZYDIS_MNEMONIC_VPROTW, ZYDIS_MNEMONIC_VPSADBW, ZYDIS_MNEMONIC_VPSBBD, ZYDIS_MNEMONIC_VPSBBRD, ZYDIS_MNEMONIC_VPSCATTERDD, ZYDIS_MNEMONIC_VPSCATTERDQ, ZYDIS_MNEMONIC_VPSCATTERQD, ZYDIS_MNEMONIC_VPSCATTERQQ, ZYDIS_MNEMONIC_VPSHAB, ZYDIS_MNEMONIC_VPSHAD, ZYDIS_MNEMONIC_VPSHAQ, ZYDIS_MNEMONIC_VPSHAW, ZYDIS_MNEMONIC_VPSHLB, ZYDIS_MNEMONIC_VPSHLD, ZYDIS_MNEMONIC_VPSHLDD, ZYDIS_MNEMONIC_VPSHLDQ, ZYDIS_MNEMONIC_VPSHLDVD, ZYDIS_MNEMONIC_VPSHLDVQ, ZYDIS_MNEMONIC_VPSHLDVW, ZYDIS_MNEMONIC_VPSHLDW, ZYDIS_MNEMONIC_VPSHLQ, ZYDIS_MNEMONIC_VPSHLW, ZYDIS_MNEMONIC_VPSHRDD, ZYDIS_MNEMONIC_VPSHRDQ, ZYDIS_MNEMONIC_VPSHRDVD, ZYDIS_MNEMONIC_VPSHRDVQ, ZYDIS_MNEMONIC_VPSHRDVW, ZYDIS_MNEMONIC_VPSHRDW, ZYDIS_MNEMONIC_VPSHUFB, ZYDIS_MNEMONIC_VPSHUFBITQMB, ZYDIS_MNEMONIC_VPSHUFD, ZYDIS_MNEMONIC_VPSHUFHW, ZYDIS_MNEMONIC_VPSHUFLW, ZYDIS_MNEMONIC_VPSIGNB, ZYDIS_MNEMONIC_VPSIGND, ZYDIS_MNEMONIC_VPSIGNW, ZYDIS_MNEMONIC_VPSLLD, ZYDIS_MNEMONIC_VPSLLDQ, ZYDIS_MNEMONIC_VPSLLQ, ZYDIS_MNEMONIC_VPSLLVD, ZYDIS_MNEMONIC_VPSLLVQ, ZYDIS_MNEMONIC_VPSLLVW, ZYDIS_MNEMONIC_VPSLLW, ZYDIS_MNEMONIC_VPSRAD, ZYDIS_MNEMONIC_VPSRAQ, ZYDIS_MNEMONIC_VPSRAVD, ZYDIS_MNEMONIC_VPSRAVQ, ZYDIS_MNEMONIC_VPSRAVW, ZYDIS_MNEMONIC_VPSRAW, ZYDIS_MNEMONIC_VPSRLD, ZYDIS_MNEMONIC_VPSRLDQ, ZYDIS_MNEMONIC_VPSRLQ, ZYDIS_MNEMONIC_VPSRLVD, ZYDIS_MNEMONIC_VPSRLVQ, ZYDIS_MNEMONIC_VPSRLVW, ZYDIS_MNEMONIC_VPSRLW, ZYDIS_MNEMONIC_VPSUBB, ZYDIS_MNEMONIC_VPSUBD, ZYDIS_MNEMONIC_VPSUBQ, ZYDIS_MNEMONIC_VPSUBRD, ZYDIS_MNEMONIC_VPSUBRSETBD, ZYDIS_MNEMONIC_VPSUBSB, ZYDIS_MNEMONIC_VPSUBSETBD, ZYDIS_MNEMONIC_VPSUBSW, ZYDIS_MNEMONIC_VPSUBUSB, ZYDIS_MNEMONIC_VPSUBUSW, ZYDIS_MNEMONIC_VPSUBW, ZYDIS_MNEMONIC_VPTERNLOGD, ZYDIS_MNEMONIC_VPTERNLOGQ, ZYDIS_MNEMONIC_VPTEST, ZYDIS_MNEMONIC_VPTESTMB, ZYDIS_MNEMONIC_VPTESTMD, ZYDIS_MNEMONIC_VPTESTMQ, ZYDIS_MNEMONIC_VPTESTMW, ZYDIS_MNEMONIC_VPTESTNMB, ZYDIS_MNEMONIC_VPTESTNMD, ZYDIS_MNEMONIC_VPTESTNMQ, ZYDIS_MNEMONIC_VPTESTNMW, ZYDIS_MNEMONIC_VPUNPCKHBW, ZYDIS_MNEMONIC_VPUNPCKHDQ, ZYDIS_MNEMONIC_VPUNPCKHQDQ, ZYDIS_MNEMONIC_VPUNPCKHWD, ZYDIS_MNEMONIC_VPUNPCKLBW, ZYDIS_MNEMONIC_VPUNPCKLDQ, ZYDIS_MNEMONIC_VPUNPCKLQDQ, ZYDIS_MNEMONIC_VPUNPCKLWD, ZYDIS_MNEMONIC_VPXOR, ZYDIS_MNEMONIC_VPXORD, ZYDIS_MNEMONIC_VPXORQ, ZYDIS_MNEMONIC_VRANGEPD, ZYDIS_MNEMONIC_VRANGEPS, ZYDIS_MNEMONIC_VRANGESD, ZYDIS_MNEMONIC_VRANGESS, ZYDIS_MNEMONIC_VRCP14PD, ZYDIS_MNEMONIC_VRCP14PS, ZYDIS_MNEMONIC_VRCP14SD, ZYDIS_MNEMONIC_VRCP14SS, ZYDIS_MNEMONIC_VRCP23PS, ZYDIS_MNEMONIC_VRCP28PD, ZYDIS_MNEMONIC_VRCP28PS, ZYDIS_MNEMONIC_VRCP28SD, ZYDIS_MNEMONIC_VRCP28SS, ZYDIS_MNEMONIC_VRCPPH, ZYDIS_MNEMONIC_VRCPPS, ZYDIS_MNEMONIC_VRCPSH, ZYDIS_MNEMONIC_VRCPSS, ZYDIS_MNEMONIC_VREDUCEPD, ZYDIS_MNEMONIC_VREDUCEPH, ZYDIS_MNEMONIC_VREDUCEPS, ZYDIS_MNEMONIC_VREDUCESD, ZYDIS_MNEMONIC_VREDUCESH, ZYDIS_MNEMONIC_VREDUCESS, ZYDIS_MNEMONIC_VRNDFXPNTPD, ZYDIS_MNEMONIC_VRNDFXPNTPS, ZYDIS_MNEMONIC_VRNDSCALEPD, ZYDIS_MNEMONIC_VRNDSCALEPH, ZYDIS_MNEMONIC_VRNDSCALEPS, ZYDIS_MNEMONIC_VRNDSCALESD, ZYDIS_MNEMONIC_VRNDSCALESH, ZYDIS_MNEMONIC_VRNDSCALESS, ZYDIS_MNEMONIC_VROUNDPD, ZYDIS_MNEMONIC_VROUNDPS, ZYDIS_MNEMONIC_VROUNDSD, ZYDIS_MNEMONIC_VROUNDSS, ZYDIS_MNEMONIC_VRSQRT14PD, ZYDIS_MNEMONIC_VRSQRT14PS, ZYDIS_MNEMONIC_VRSQRT14SD, ZYDIS_MNEMONIC_VRSQRT14SS, ZYDIS_MNEMONIC_VRSQRT23PS, ZYDIS_MNEMONIC_VRSQRT28PD, ZYDIS_MNEMONIC_VRSQRT28PS, ZYDIS_MNEMONIC_VRSQRT28SD, ZYDIS_MNEMONIC_VRSQRT28SS, ZYDIS_MNEMONIC_VRSQRTPH, ZYDIS_MNEMONIC_VRSQRTPS, ZYDIS_MNEMONIC_VRSQRTSH, ZYDIS_MNEMONIC_VRSQRTSS, ZYDIS_MNEMONIC_VSCALEFPD, ZYDIS_MNEMONIC_VSCALEFPH, ZYDIS_MNEMONIC_VSCALEFPS, ZYDIS_MNEMONIC_VSCALEFSD, ZYDIS_MNEMONIC_VSCALEFSH, ZYDIS_MNEMONIC_VSCALEFSS, ZYDIS_MNEMONIC_VSCALEPS, ZYDIS_MNEMONIC_VSCATTERDPD, ZYDIS_MNEMONIC_VSCATTERDPS, ZYDIS_MNEMONIC_VSCATTERPF0DPD, ZYDIS_MNEMONIC_VSCATTERPF0DPS, ZYDIS_MNEMONIC_VSCATTERPF0HINTDPD, ZYDIS_MNEMONIC_VSCATTERPF0HINTDPS, ZYDIS_MNEMONIC_VSCATTERPF0QPD, ZYDIS_MNEMONIC_VSCATTERPF0QPS, ZYDIS_MNEMONIC_VSCATTERPF1DPD, ZYDIS_MNEMONIC_VSCATTERPF1DPS, ZYDIS_MNEMONIC_VSCATTERPF1QPD, ZYDIS_MNEMONIC_VSCATTERPF1QPS, ZYDIS_MNEMONIC_VSCATTERQPD, ZYDIS_MNEMONIC_VSCATTERQPS, ZYDIS_MNEMONIC_VSHA512MSG1, ZYDIS_MNEMONIC_VSHA512MSG2, ZYDIS_MNEMONIC_VSHA512RNDS2, ZYDIS_MNEMONIC_VSHUFF32X4, ZYDIS_MNEMONIC_VSHUFF64X2, ZYDIS_MNEMONIC_VSHUFI32X4, ZYDIS_MNEMONIC_VSHUFI64X2, ZYDIS_MNEMONIC_VSHUFPD, ZYDIS_MNEMONIC_VSHUFPS, ZYDIS_MNEMONIC_VSM3MSG1, ZYDIS_MNEMONIC_VSM3MSG2, ZYDIS_MNEMONIC_VSM3RNDS2, ZYDIS_MNEMONIC_VSM4KEY4, ZYDIS_MNEMONIC_VSM4RNDS4, ZYDIS_MNEMONIC_VSQRTPD, ZYDIS_MNEMONIC_VSQRTPH, ZYDIS_MNEMONIC_VSQRTPS, ZYDIS_MNEMONIC_VSQRTSD, ZYDIS_MNEMONIC_VSQRTSH, ZYDIS_MNEMONIC_VSQRTSS, ZYDIS_MNEMONIC_VSTMXCSR, ZYDIS_MNEMONIC_VSUBPD, ZYDIS_MNEMONIC_VSUBPH, ZYDIS_MNEMONIC_VSUBPS, ZYDIS_MNEMONIC_VSUBRPD, ZYDIS_MNEMONIC_VSUBRPS, ZYDIS_MNEMONIC_VSUBSD, ZYDIS_MNEMONIC_VSUBSH, ZYDIS_MNEMONIC_VSUBSS, ZYDIS_MNEMONIC_VTESTPD, ZYDIS_MNEMONIC_VTESTPS, ZYDIS_MNEMONIC_VUCOMISD, ZYDIS_MNEMONIC_VUCOMISH, ZYDIS_MNEMONIC_VUCOMISS, ZYDIS_MNEMONIC_VUNPCKHPD, ZYDIS_MNEMONIC_VUNPCKHPS, ZYDIS_MNEMONIC_VUNPCKLPD, ZYDIS_MNEMONIC_VUNPCKLPS, ZYDIS_MNEMONIC_VXORPD, ZYDIS_MNEMONIC_VXORPS, ZYDIS_MNEMONIC_VZEROALL, ZYDIS_MNEMONIC_VZEROUPPER, ZYDIS_MNEMONIC_WBINVD, ZYDIS_MNEMONIC_WRFSBASE, ZYDIS_MNEMONIC_WRGSBASE, ZYDIS_MNEMONIC_WRMSR, ZYDIS_MNEMONIC_WRMSRLIST, ZYDIS_MNEMONIC_WRMSRNS, ZYDIS_MNEMONIC_WRPKRU, ZYDIS_MNEMONIC_WRSSD, ZYDIS_MNEMONIC_WRSSQ, ZYDIS_MNEMONIC_WRUSSD, ZYDIS_MNEMONIC_WRUSSQ, ZYDIS_MNEMONIC_XABORT, ZYDIS_MNEMONIC_XADD, ZYDIS_MNEMONIC_XBEGIN, ZYDIS_MNEMONIC_XCHG, ZYDIS_MNEMONIC_XCRYPT_CBC, ZYDIS_MNEMONIC_XCRYPT_CFB, ZYDIS_MNEMONIC_XCRYPT_CTR, ZYDIS_MNEMONIC_XCRYPT_ECB, ZYDIS_MNEMONIC_XCRYPT_OFB, ZYDIS_MNEMONIC_XEND, ZYDIS_MNEMONIC_XGETBV, ZYDIS_MNEMONIC_XLAT, ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XORPD, ZYDIS_MNEMONIC_XORPS, ZYDIS_MNEMONIC_XRESLDTRK, ZYDIS_MNEMONIC_XRSTOR, ZYDIS_MNEMONIC_XRSTOR64, ZYDIS_MNEMONIC_XRSTORS, ZYDIS_MNEMONIC_XRSTORS64, ZYDIS_MNEMONIC_XSAVE, ZYDIS_MNEMONIC_XSAVE64, ZYDIS_MNEMONIC_XSAVEC, ZYDIS_MNEMONIC_XSAVEC64, ZYDIS_MNEMONIC_XSAVEOPT, ZYDIS_MNEMONIC_XSAVEOPT64, ZYDIS_MNEMONIC_XSAVES, ZYDIS_MNEMONIC_XSAVES64, ZYDIS_MNEMONIC_XSETBV, ZYDIS_MNEMONIC_XSHA1, ZYDIS_MNEMONIC_XSHA256, ZYDIS_MNEMONIC_XSTORE, ZYDIS_MNEMONIC_XSUSLDTRK, ZYDIS_MNEMONIC_XTEST, /** * Maximum value of this enum. */ ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE) } ZydisMnemonic; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup mnemonic Mnemonic * Functions for retrieving mnemonic names. * @{ */ /** * Returns the specified instruction mnemonic string. * * @param mnemonic The mnemonic. * * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. */ ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); /** * Returns the specified instruction mnemonic as `ZydisShortString`. * * @param mnemonic The mnemonic. * * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. * * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. */ ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic); /** * @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_MNEMONIC_H */ // // Header: Zydis/Register.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Utility functions and constants for registers. */ #ifndef ZYDIS_REGISTER_H #define ZYDIS_REGISTER_H // // Header: Zydis/SharedTypes.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/Register.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Defines decoder/encoder-shared macros and types. */ #ifndef ZYDIS_SHAREDTYPES_H #define ZYDIS_SHAREDTYPES_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constants */ /* ---------------------------------------------------------------------------------------------- */ #define ZYDIS_MAX_INSTRUCTION_LENGTH 15 #define ZYDIS_MAX_OPERAND_COUNT 10 // TODO: Auto generate #define ZYDIS_MAX_OPERAND_COUNT_VISIBLE 5 // TODO: Auto generate /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Machine mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisMachineMode` enum. */ typedef enum ZydisMachineMode_ { /** * 64 bit mode. */ ZYDIS_MACHINE_MODE_LONG_64, /** * 32 bit protected mode. */ ZYDIS_MACHINE_MODE_LONG_COMPAT_32, /** * 16 bit protected mode. */ ZYDIS_MACHINE_MODE_LONG_COMPAT_16, /** * 32 bit protected mode. */ ZYDIS_MACHINE_MODE_LEGACY_32, /** * 16 bit protected mode. */ ZYDIS_MACHINE_MODE_LEGACY_16, /** * 16 bit real mode. */ ZYDIS_MACHINE_MODE_REAL_16, /** * Maximum value of this enum. */ ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_MACHINE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MACHINE_MODE_MAX_VALUE) } ZydisMachineMode; /* ---------------------------------------------------------------------------------------------- */ /* Stack width */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisStackWidth` enum. */ typedef enum ZydisStackWidth_ { ZYDIS_STACK_WIDTH_16, ZYDIS_STACK_WIDTH_32, ZYDIS_STACK_WIDTH_64, /** * Maximum value of this enum. */ ZYDIS_STACK_WIDTH_MAX_VALUE = ZYDIS_STACK_WIDTH_64, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_STACK_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_STACK_WIDTH_MAX_VALUE) } ZydisStackWidth; /* ---------------------------------------------------------------------------------------------- */ /* Element type */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisElementType` enum. */ typedef enum ZydisElementType_ { ZYDIS_ELEMENT_TYPE_INVALID, /** * A struct type. */ ZYDIS_ELEMENT_TYPE_STRUCT, /** * Unsigned integer value. */ ZYDIS_ELEMENT_TYPE_UINT, /** * Signed integer value. */ ZYDIS_ELEMENT_TYPE_INT, /** * 16-bit floating point value (`half`). */ ZYDIS_ELEMENT_TYPE_FLOAT16, /** * 32-bit floating point value (`single`). */ ZYDIS_ELEMENT_TYPE_FLOAT32, /** * 64-bit floating point value (`double`). */ ZYDIS_ELEMENT_TYPE_FLOAT64, /** * 80-bit floating point value (`extended`). */ ZYDIS_ELEMENT_TYPE_FLOAT80, /** * 16-bit brain floating point value. */ ZYDIS_ELEMENT_TYPE_BFLOAT16, /** * Binary coded decimal value. */ ZYDIS_ELEMENT_TYPE_LONGBCD, /** * A condition code (e.g. used by `CMPPD`, `VCMPPD`, ...). */ ZYDIS_ELEMENT_TYPE_CC, /** * Maximum value of this enum. */ ZYDIS_ELEMENT_TYPE_MAX_VALUE = ZYDIS_ELEMENT_TYPE_CC, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ELEMENT_TYPE_MAX_VALUE) } ZydisElementType; /* ---------------------------------------------------------------------------------------------- */ /* Element size */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisElementSize` datatype. */ typedef ZyanU16 ZydisElementSize; /* ---------------------------------------------------------------------------------------------- */ /* Operand type */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOperandType` enum. */ typedef enum ZydisOperandType_ { /** * The operand is not used. */ ZYDIS_OPERAND_TYPE_UNUSED, /** * The operand is a register operand. */ ZYDIS_OPERAND_TYPE_REGISTER, /** * The operand is a memory operand. */ ZYDIS_OPERAND_TYPE_MEMORY, /** * The operand is a pointer operand with a segment:offset lvalue. */ ZYDIS_OPERAND_TYPE_POINTER, /** * The operand is an immediate operand. */ ZYDIS_OPERAND_TYPE_IMMEDIATE, /** * Maximum value of this enum. */ ZYDIS_OPERAND_TYPE_MAX_VALUE = ZYDIS_OPERAND_TYPE_IMMEDIATE, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_OPERAND_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_TYPE_MAX_VALUE) } ZydisOperandType; // If asserts are failing here remember to update encoder table generator before fixing asserts ZYAN_STATIC_ASSERT(ZYAN_BITS_TO_REPRESENT( ZYDIS_OPERAND_TYPE_MAX_VALUE - ZYDIS_OPERAND_TYPE_REGISTER) == 2); /* ---------------------------------------------------------------------------------------------- */ /* Operand encoding */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOperandEncoding` enum. */ typedef enum ZydisOperandEncoding_ { ZYDIS_OPERAND_ENCODING_NONE, ZYDIS_OPERAND_ENCODING_MODRM_REG, ZYDIS_OPERAND_ENCODING_MODRM_RM, ZYDIS_OPERAND_ENCODING_OPCODE, ZYDIS_OPERAND_ENCODING_NDSNDD, ZYDIS_OPERAND_ENCODING_IS4, ZYDIS_OPERAND_ENCODING_MASK, ZYDIS_OPERAND_ENCODING_DISP8, ZYDIS_OPERAND_ENCODING_DISP16, ZYDIS_OPERAND_ENCODING_DISP32, ZYDIS_OPERAND_ENCODING_DISP64, ZYDIS_OPERAND_ENCODING_DISP16_32_64, ZYDIS_OPERAND_ENCODING_DISP32_32_64, ZYDIS_OPERAND_ENCODING_DISP16_32_32, ZYDIS_OPERAND_ENCODING_UIMM8, ZYDIS_OPERAND_ENCODING_UIMM16, ZYDIS_OPERAND_ENCODING_UIMM32, ZYDIS_OPERAND_ENCODING_UIMM64, ZYDIS_OPERAND_ENCODING_UIMM16_32_64, ZYDIS_OPERAND_ENCODING_UIMM32_32_64, ZYDIS_OPERAND_ENCODING_UIMM16_32_32, ZYDIS_OPERAND_ENCODING_SIMM8, ZYDIS_OPERAND_ENCODING_SIMM16, ZYDIS_OPERAND_ENCODING_SIMM32, ZYDIS_OPERAND_ENCODING_SIMM64, ZYDIS_OPERAND_ENCODING_SIMM16_32_64, ZYDIS_OPERAND_ENCODING_SIMM32_32_64, ZYDIS_OPERAND_ENCODING_SIMM16_32_32, ZYDIS_OPERAND_ENCODING_JIMM8, ZYDIS_OPERAND_ENCODING_JIMM16, ZYDIS_OPERAND_ENCODING_JIMM32, ZYDIS_OPERAND_ENCODING_JIMM64, ZYDIS_OPERAND_ENCODING_JIMM16_32_64, ZYDIS_OPERAND_ENCODING_JIMM32_32_64, ZYDIS_OPERAND_ENCODING_JIMM16_32_32, /** * Maximum value of this enum. */ ZYDIS_OPERAND_ENCODING_MAX_VALUE = ZYDIS_OPERAND_ENCODING_JIMM16_32_32, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_OPERAND_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ENCODING_MAX_VALUE) } ZydisOperandEncoding; /* ---------------------------------------------------------------------------------------------- */ /* Operand visibility */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOperandVisibility` enum. */ typedef enum ZydisOperandVisibility_ { ZYDIS_OPERAND_VISIBILITY_INVALID, /** * The operand is explicitly encoded in the instruction. */ ZYDIS_OPERAND_VISIBILITY_EXPLICIT, /** * The operand is part of the opcode, but listed as an operand. */ ZYDIS_OPERAND_VISIBILITY_IMPLICIT, /** * The operand is part of the opcode, and not typically listed as an operand. */ ZYDIS_OPERAND_VISIBILITY_HIDDEN, /** * Maximum value of this enum. */ ZYDIS_OPERAND_VISIBILITY_MAX_VALUE = ZYDIS_OPERAND_VISIBILITY_HIDDEN, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_VISIBILITY_MAX_VALUE) } ZydisOperandVisibility; /* ---------------------------------------------------------------------------------------------- */ /* Operand action */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOperandAction` enum. */ typedef enum ZydisOperandAction_ { /* ------------------------------------------------------------------------------------------ */ /* Elemental actions */ /* ------------------------------------------------------------------------------------------ */ /** * The operand is read by the instruction. */ ZYDIS_OPERAND_ACTION_READ = 0x01, /** * The operand is written by the instruction (must write). */ ZYDIS_OPERAND_ACTION_WRITE = 0x02, /** * The operand is conditionally read by the instruction. */ ZYDIS_OPERAND_ACTION_CONDREAD = 0x04, /** * The operand is conditionally written by the instruction (may write). */ ZYDIS_OPERAND_ACTION_CONDWRITE = 0x08, /* ------------------------------------------------------------------------------------------ */ /* Combined actions */ /* ------------------------------------------------------------------------------------------ */ /** * The operand is read (must read) and written by the instruction (must write). */ ZYDIS_OPERAND_ACTION_READWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_WRITE, /** * The operand is conditionally read (may read) and conditionally written by * the instruction (may write). */ ZYDIS_OPERAND_ACTION_CONDREAD_CONDWRITE = ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_CONDWRITE, /** * The operand is read (must read) and conditionally written by the * instruction (may write). */ ZYDIS_OPERAND_ACTION_READ_CONDWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDWRITE, /** * The operand is written (must write) and conditionally read by the * instruction (may read). */ ZYDIS_OPERAND_ACTION_CONDREAD_WRITE = ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_WRITE, /** * Mask combining all reading access flags. */ ZYDIS_OPERAND_ACTION_MASK_READ = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDREAD, /** * Mask combining all writing access flags. */ ZYDIS_OPERAND_ACTION_MASK_WRITE = ZYDIS_OPERAND_ACTION_WRITE | ZYDIS_OPERAND_ACTION_CONDWRITE, /* ------------------------------------------------------------------------------------------ */ /** * The minimum number of bits required to represent all values of this bitset. */ ZYDIS_OPERAND_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ACTION_CONDWRITE) } ZydisOperandAction; /** * Defines the `ZydisOperandActions` data-type. */ typedef ZyanU8 ZydisOperandActions; /* ---------------------------------------------------------------------------------------------- */ /* Instruction encoding */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisInstructionEncoding` enum. */ typedef enum ZydisInstructionEncoding_ { /** * The instruction uses the legacy encoding. */ ZYDIS_INSTRUCTION_ENCODING_LEGACY, /** * The instruction uses the AMD 3DNow-encoding. */ ZYDIS_INSTRUCTION_ENCODING_3DNOW, /** * The instruction uses the AMD XOP-encoding. */ ZYDIS_INSTRUCTION_ENCODING_XOP, /** * The instruction uses the VEX-encoding. */ ZYDIS_INSTRUCTION_ENCODING_VEX, /** * The instruction uses the EVEX-encoding. */ ZYDIS_INSTRUCTION_ENCODING_EVEX, /** * The instruction uses the MVEX-encoding. */ ZYDIS_INSTRUCTION_ENCODING_MVEX, /** * Maximum value of this enum. */ ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE = ZYDIS_INSTRUCTION_ENCODING_MVEX, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_INSTRUCTION_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE) } ZydisInstructionEncoding; /* ---------------------------------------------------------------------------------------------- */ /* Opcode map */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOpcodeMap` enum. */ typedef enum ZydisOpcodeMap_ { ZYDIS_OPCODE_MAP_DEFAULT, ZYDIS_OPCODE_MAP_0F, ZYDIS_OPCODE_MAP_0F38, ZYDIS_OPCODE_MAP_0F3A, ZYDIS_OPCODE_MAP_MAP4, // not used ZYDIS_OPCODE_MAP_MAP5, ZYDIS_OPCODE_MAP_MAP6, ZYDIS_OPCODE_MAP_MAP7, // not used ZYDIS_OPCODE_MAP_0F0F, ZYDIS_OPCODE_MAP_XOP8, ZYDIS_OPCODE_MAP_XOP9, ZYDIS_OPCODE_MAP_XOPA, /** * Maximum value of this enum. */ ZYDIS_OPCODE_MAP_MAX_VALUE = ZYDIS_OPCODE_MAP_XOPA, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_OPCODE_MAP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPCODE_MAP_MAX_VALUE) } ZydisOpcodeMap; /* ---------------------------------------------------------------------------------------------- */ /* Instruction attributes */ /* ---------------------------------------------------------------------------------------------- */ /** * @defgroup instruction_attributes Instruction attributes * * Constants describing various properties of an instruction. Used in the * @ref ZydisDecodedInstruction.attributes and @ref ZydisEncoderRequest.prefixes fields. * * @{ */ /** * Defines the `ZydisInstructionAttributes` data-type. */ typedef ZyanU64 ZydisInstructionAttributes; /** * The instruction has the `ModRM` byte. */ #define ZYDIS_ATTRIB_HAS_MODRM (1ULL << 0) /** * The instruction has the `SIB` byte. */ #define ZYDIS_ATTRIB_HAS_SIB (1ULL << 1) /** * The instruction has the `REX` prefix. */ #define ZYDIS_ATTRIB_HAS_REX (1ULL << 2) /** * The instruction has the `XOP` prefix. */ #define ZYDIS_ATTRIB_HAS_XOP (1ULL << 3) /** * The instruction has the `VEX` prefix. */ #define ZYDIS_ATTRIB_HAS_VEX (1ULL << 4) /** * The instruction has the `EVEX` prefix. */ #define ZYDIS_ATTRIB_HAS_EVEX (1ULL << 5) /** * The instruction has the `MVEX` prefix. */ #define ZYDIS_ATTRIB_HAS_MVEX (1ULL << 6) /** * The instruction has one or more operands with position-relative offsets. */ #define ZYDIS_ATTRIB_IS_RELATIVE (1ULL << 7) /** * The instruction is privileged. * * Privileged instructions are any instructions that require a current ring level below 3. */ #define ZYDIS_ATTRIB_IS_PRIVILEGED (1ULL << 8) /** * The instruction accesses one or more CPU-flags. */ #define ZYDIS_ATTRIB_CPUFLAG_ACCESS (1ULL << 9) /** * The instruction may conditionally read the general CPU state. */ #define ZYDIS_ATTRIB_CPU_STATE_CR (1ULL << 10) /** * The instruction may conditionally write the general CPU state. */ #define ZYDIS_ATTRIB_CPU_STATE_CW (1ULL << 11) /** * The instruction may conditionally read the FPU state (X87, MMX). */ #define ZYDIS_ATTRIB_FPU_STATE_CR (1ULL << 12) /** * The instruction may conditionally write the FPU state (X87, MMX). */ #define ZYDIS_ATTRIB_FPU_STATE_CW (1ULL << 13) /** * The instruction may conditionally read the XMM state (AVX, AVX2, AVX-512). */ #define ZYDIS_ATTRIB_XMM_STATE_CR (1ULL << 14) /** * The instruction may conditionally write the XMM state (AVX, AVX2, AVX-512). */ #define ZYDIS_ATTRIB_XMM_STATE_CW (1ULL << 15) /** * The instruction accepts the `LOCK` prefix (`0xF0`). */ #define ZYDIS_ATTRIB_ACCEPTS_LOCK (1ULL << 16) /** * The instruction accepts the `REP` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_ACCEPTS_REP (1ULL << 17) /** * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_ACCEPTS_REPE (1ULL << 18) /** * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_ACCEPTS_REPZ ZYDIS_ATTRIB_ACCEPTS_REPE /** * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_ACCEPTS_REPNE (1ULL << 19) /** * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_ACCEPTS_REPNZ ZYDIS_ATTRIB_ACCEPTS_REPNE /** * The instruction accepts the `BND` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_ACCEPTS_BND (1ULL << 20) /** * The instruction accepts the `XACQUIRE` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_ACCEPTS_XACQUIRE (1ULL << 21) /** * The instruction accepts the `XRELEASE` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_ACCEPTS_XRELEASE (1ULL << 22) /** * The instruction accepts the `XACQUIRE`/`XRELEASE` prefixes (`0xF2`, `0xF3`) * without the `LOCK` prefix (`0x0F`). */ #define ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK (1ULL << 23) /** * The instruction accepts branch hints (0x2E, 0x3E). */ #define ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS (1ULL << 24) /** * The instruction accepts the `CET` `no-track` prefix (`0x3E`). */ #define ZYDIS_ATTRIB_ACCEPTS_NOTRACK (1ULL << 25) /** * The instruction accepts segment prefixes (`0x2E`, `0x36`, `0x3E`, `0x26`, * `0x64`, `0x65`). */ #define ZYDIS_ATTRIB_ACCEPTS_SEGMENT (1ULL << 26) /** * The instruction has the `LOCK` prefix (`0xF0`). */ #define ZYDIS_ATTRIB_HAS_LOCK (1ULL << 27) /** * The instruction has the `REP` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_HAS_REP (1ULL << 28) /** * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_HAS_REPE (1ULL << 29) /** * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_HAS_REPZ ZYDIS_ATTRIB_HAS_REPE /** * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_HAS_REPNE (1ULL << 30) /** * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_HAS_REPNZ ZYDIS_ATTRIB_HAS_REPNE /** * The instruction has the `BND` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_HAS_BND (1ULL << 31) /** * The instruction has the `XACQUIRE` prefix (`0xF2`). */ #define ZYDIS_ATTRIB_HAS_XACQUIRE (1ULL << 32) /** * The instruction has the `XRELEASE` prefix (`0xF3`). */ #define ZYDIS_ATTRIB_HAS_XRELEASE (1ULL << 33) /** * The instruction has the branch-not-taken hint (`0x2E`). */ #define ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN (1ULL << 34) /** * The instruction has the branch-taken hint (`0x3E`). */ #define ZYDIS_ATTRIB_HAS_BRANCH_TAKEN (1ULL << 35) /** * The instruction has the `CET` `no-track` prefix (`0x3E`). */ #define ZYDIS_ATTRIB_HAS_NOTRACK (1ULL << 36) /** * The instruction has the `CS` segment modifier (`0x2E`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_CS (1ULL << 37) /** * The instruction has the `SS` segment modifier (`0x36`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_SS (1ULL << 38) /** * The instruction has the `DS` segment modifier (`0x3E`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_DS (1ULL << 39) /** * The instruction has the `ES` segment modifier (`0x26`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_ES (1ULL << 40) /** * The instruction has the `FS` segment modifier (`0x64`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_FS (1ULL << 41) /** * The instruction has the `GS` segment modifier (`0x65`). */ #define ZYDIS_ATTRIB_HAS_SEGMENT_GS (1ULL << 42) /** * The instruction has a segment modifier. */ #define ZYDIS_ATTRIB_HAS_SEGMENT (ZYDIS_ATTRIB_HAS_SEGMENT_CS | \ ZYDIS_ATTRIB_HAS_SEGMENT_SS | \ ZYDIS_ATTRIB_HAS_SEGMENT_DS | \ ZYDIS_ATTRIB_HAS_SEGMENT_ES | \ ZYDIS_ATTRIB_HAS_SEGMENT_FS | \ ZYDIS_ATTRIB_HAS_SEGMENT_GS) /** * The instruction has the operand-size override prefix (`0x66`). */ #define ZYDIS_ATTRIB_HAS_OPERANDSIZE (1ULL << 43) // TODO: rename /** * The instruction has the address-size override prefix (`0x67`). */ #define ZYDIS_ATTRIB_HAS_ADDRESSSIZE (1ULL << 44) // TODO: rename /** * The instruction has the `EVEX.b` bit set. * * This attribute is mainly used by the encoder. */ #define ZYDIS_ATTRIB_HAS_EVEX_B (1ULL << 45) // TODO: rename /** * @} */ /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_SHAREDTYPES_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Registers */ /* ---------------------------------------------------------------------------------------------- */ // // Header: Zydis/Generated/EnumRegister.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/DecoderTypes.h // - Zydis/Register.h // /** * Defines the `ZydisRegister` enum. */ typedef enum ZydisRegister_ { ZYDIS_REGISTER_NONE, // General purpose registers 8-bit ZYDIS_REGISTER_AL, ZYDIS_REGISTER_CL, ZYDIS_REGISTER_DL, ZYDIS_REGISTER_BL, ZYDIS_REGISTER_AH, ZYDIS_REGISTER_CH, ZYDIS_REGISTER_DH, ZYDIS_REGISTER_BH, ZYDIS_REGISTER_SPL, ZYDIS_REGISTER_BPL, ZYDIS_REGISTER_SIL, ZYDIS_REGISTER_DIL, ZYDIS_REGISTER_R8B, ZYDIS_REGISTER_R9B, ZYDIS_REGISTER_R10B, ZYDIS_REGISTER_R11B, ZYDIS_REGISTER_R12B, ZYDIS_REGISTER_R13B, ZYDIS_REGISTER_R14B, ZYDIS_REGISTER_R15B, // General purpose registers 16-bit ZYDIS_REGISTER_AX, ZYDIS_REGISTER_CX, ZYDIS_REGISTER_DX, ZYDIS_REGISTER_BX, ZYDIS_REGISTER_SP, ZYDIS_REGISTER_BP, ZYDIS_REGISTER_SI, ZYDIS_REGISTER_DI, ZYDIS_REGISTER_R8W, ZYDIS_REGISTER_R9W, ZYDIS_REGISTER_R10W, ZYDIS_REGISTER_R11W, ZYDIS_REGISTER_R12W, ZYDIS_REGISTER_R13W, ZYDIS_REGISTER_R14W, ZYDIS_REGISTER_R15W, // General purpose registers 32-bit ZYDIS_REGISTER_EAX, ZYDIS_REGISTER_ECX, ZYDIS_REGISTER_EDX, ZYDIS_REGISTER_EBX, ZYDIS_REGISTER_ESP, ZYDIS_REGISTER_EBP, ZYDIS_REGISTER_ESI, ZYDIS_REGISTER_EDI, ZYDIS_REGISTER_R8D, ZYDIS_REGISTER_R9D, ZYDIS_REGISTER_R10D, ZYDIS_REGISTER_R11D, ZYDIS_REGISTER_R12D, ZYDIS_REGISTER_R13D, ZYDIS_REGISTER_R14D, ZYDIS_REGISTER_R15D, // General purpose registers 64-bit ZYDIS_REGISTER_RAX, ZYDIS_REGISTER_RCX, ZYDIS_REGISTER_RDX, ZYDIS_REGISTER_RBX, ZYDIS_REGISTER_RSP, ZYDIS_REGISTER_RBP, ZYDIS_REGISTER_RSI, ZYDIS_REGISTER_RDI, ZYDIS_REGISTER_R8, ZYDIS_REGISTER_R9, ZYDIS_REGISTER_R10, ZYDIS_REGISTER_R11, ZYDIS_REGISTER_R12, ZYDIS_REGISTER_R13, ZYDIS_REGISTER_R14, ZYDIS_REGISTER_R15, // Floating point legacy registers ZYDIS_REGISTER_ST0, ZYDIS_REGISTER_ST1, ZYDIS_REGISTER_ST2, ZYDIS_REGISTER_ST3, ZYDIS_REGISTER_ST4, ZYDIS_REGISTER_ST5, ZYDIS_REGISTER_ST6, ZYDIS_REGISTER_ST7, ZYDIS_REGISTER_X87CONTROL, ZYDIS_REGISTER_X87STATUS, ZYDIS_REGISTER_X87TAG, // Floating point multimedia registers ZYDIS_REGISTER_MM0, ZYDIS_REGISTER_MM1, ZYDIS_REGISTER_MM2, ZYDIS_REGISTER_MM3, ZYDIS_REGISTER_MM4, ZYDIS_REGISTER_MM5, ZYDIS_REGISTER_MM6, ZYDIS_REGISTER_MM7, // Floating point vector registers 128-bit ZYDIS_REGISTER_XMM0, ZYDIS_REGISTER_XMM1, ZYDIS_REGISTER_XMM2, ZYDIS_REGISTER_XMM3, ZYDIS_REGISTER_XMM4, ZYDIS_REGISTER_XMM5, ZYDIS_REGISTER_XMM6, ZYDIS_REGISTER_XMM7, ZYDIS_REGISTER_XMM8, ZYDIS_REGISTER_XMM9, ZYDIS_REGISTER_XMM10, ZYDIS_REGISTER_XMM11, ZYDIS_REGISTER_XMM12, ZYDIS_REGISTER_XMM13, ZYDIS_REGISTER_XMM14, ZYDIS_REGISTER_XMM15, ZYDIS_REGISTER_XMM16, ZYDIS_REGISTER_XMM17, ZYDIS_REGISTER_XMM18, ZYDIS_REGISTER_XMM19, ZYDIS_REGISTER_XMM20, ZYDIS_REGISTER_XMM21, ZYDIS_REGISTER_XMM22, ZYDIS_REGISTER_XMM23, ZYDIS_REGISTER_XMM24, ZYDIS_REGISTER_XMM25, ZYDIS_REGISTER_XMM26, ZYDIS_REGISTER_XMM27, ZYDIS_REGISTER_XMM28, ZYDIS_REGISTER_XMM29, ZYDIS_REGISTER_XMM30, ZYDIS_REGISTER_XMM31, // Floating point vector registers 256-bit ZYDIS_REGISTER_YMM0, ZYDIS_REGISTER_YMM1, ZYDIS_REGISTER_YMM2, ZYDIS_REGISTER_YMM3, ZYDIS_REGISTER_YMM4, ZYDIS_REGISTER_YMM5, ZYDIS_REGISTER_YMM6, ZYDIS_REGISTER_YMM7, ZYDIS_REGISTER_YMM8, ZYDIS_REGISTER_YMM9, ZYDIS_REGISTER_YMM10, ZYDIS_REGISTER_YMM11, ZYDIS_REGISTER_YMM12, ZYDIS_REGISTER_YMM13, ZYDIS_REGISTER_YMM14, ZYDIS_REGISTER_YMM15, ZYDIS_REGISTER_YMM16, ZYDIS_REGISTER_YMM17, ZYDIS_REGISTER_YMM18, ZYDIS_REGISTER_YMM19, ZYDIS_REGISTER_YMM20, ZYDIS_REGISTER_YMM21, ZYDIS_REGISTER_YMM22, ZYDIS_REGISTER_YMM23, ZYDIS_REGISTER_YMM24, ZYDIS_REGISTER_YMM25, ZYDIS_REGISTER_YMM26, ZYDIS_REGISTER_YMM27, ZYDIS_REGISTER_YMM28, ZYDIS_REGISTER_YMM29, ZYDIS_REGISTER_YMM30, ZYDIS_REGISTER_YMM31, // Floating point vector registers 512-bit ZYDIS_REGISTER_ZMM0, ZYDIS_REGISTER_ZMM1, ZYDIS_REGISTER_ZMM2, ZYDIS_REGISTER_ZMM3, ZYDIS_REGISTER_ZMM4, ZYDIS_REGISTER_ZMM5, ZYDIS_REGISTER_ZMM6, ZYDIS_REGISTER_ZMM7, ZYDIS_REGISTER_ZMM8, ZYDIS_REGISTER_ZMM9, ZYDIS_REGISTER_ZMM10, ZYDIS_REGISTER_ZMM11, ZYDIS_REGISTER_ZMM12, ZYDIS_REGISTER_ZMM13, ZYDIS_REGISTER_ZMM14, ZYDIS_REGISTER_ZMM15, ZYDIS_REGISTER_ZMM16, ZYDIS_REGISTER_ZMM17, ZYDIS_REGISTER_ZMM18, ZYDIS_REGISTER_ZMM19, ZYDIS_REGISTER_ZMM20, ZYDIS_REGISTER_ZMM21, ZYDIS_REGISTER_ZMM22, ZYDIS_REGISTER_ZMM23, ZYDIS_REGISTER_ZMM24, ZYDIS_REGISTER_ZMM25, ZYDIS_REGISTER_ZMM26, ZYDIS_REGISTER_ZMM27, ZYDIS_REGISTER_ZMM28, ZYDIS_REGISTER_ZMM29, ZYDIS_REGISTER_ZMM30, ZYDIS_REGISTER_ZMM31, // Matrix registers ZYDIS_REGISTER_TMM0, ZYDIS_REGISTER_TMM1, ZYDIS_REGISTER_TMM2, ZYDIS_REGISTER_TMM3, ZYDIS_REGISTER_TMM4, ZYDIS_REGISTER_TMM5, ZYDIS_REGISTER_TMM6, ZYDIS_REGISTER_TMM7, // Flags registers ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_RFLAGS, // Instruction-pointer registers ZYDIS_REGISTER_IP, ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_RIP, // Segment registers ZYDIS_REGISTER_ES, ZYDIS_REGISTER_CS, ZYDIS_REGISTER_SS, ZYDIS_REGISTER_DS, ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS, // Table registers ZYDIS_REGISTER_GDTR, ZYDIS_REGISTER_LDTR, ZYDIS_REGISTER_IDTR, ZYDIS_REGISTER_TR, // Test registers ZYDIS_REGISTER_TR0, ZYDIS_REGISTER_TR1, ZYDIS_REGISTER_TR2, ZYDIS_REGISTER_TR3, ZYDIS_REGISTER_TR4, ZYDIS_REGISTER_TR5, ZYDIS_REGISTER_TR6, ZYDIS_REGISTER_TR7, // Control registers ZYDIS_REGISTER_CR0, ZYDIS_REGISTER_CR1, ZYDIS_REGISTER_CR2, ZYDIS_REGISTER_CR3, ZYDIS_REGISTER_CR4, ZYDIS_REGISTER_CR5, ZYDIS_REGISTER_CR6, ZYDIS_REGISTER_CR7, ZYDIS_REGISTER_CR8, ZYDIS_REGISTER_CR9, ZYDIS_REGISTER_CR10, ZYDIS_REGISTER_CR11, ZYDIS_REGISTER_CR12, ZYDIS_REGISTER_CR13, ZYDIS_REGISTER_CR14, ZYDIS_REGISTER_CR15, // Debug registers ZYDIS_REGISTER_DR0, ZYDIS_REGISTER_DR1, ZYDIS_REGISTER_DR2, ZYDIS_REGISTER_DR3, ZYDIS_REGISTER_DR4, ZYDIS_REGISTER_DR5, ZYDIS_REGISTER_DR6, ZYDIS_REGISTER_DR7, ZYDIS_REGISTER_DR8, ZYDIS_REGISTER_DR9, ZYDIS_REGISTER_DR10, ZYDIS_REGISTER_DR11, ZYDIS_REGISTER_DR12, ZYDIS_REGISTER_DR13, ZYDIS_REGISTER_DR14, ZYDIS_REGISTER_DR15, // Mask registers ZYDIS_REGISTER_K0, ZYDIS_REGISTER_K1, ZYDIS_REGISTER_K2, ZYDIS_REGISTER_K3, ZYDIS_REGISTER_K4, ZYDIS_REGISTER_K5, ZYDIS_REGISTER_K6, ZYDIS_REGISTER_K7, // Bound registers ZYDIS_REGISTER_BND0, ZYDIS_REGISTER_BND1, ZYDIS_REGISTER_BND2, ZYDIS_REGISTER_BND3, ZYDIS_REGISTER_BNDCFG, ZYDIS_REGISTER_BNDSTATUS, // Uncategorized ZYDIS_REGISTER_MXCSR, ZYDIS_REGISTER_PKRU, ZYDIS_REGISTER_XCR0, ZYDIS_REGISTER_UIF, /** * Maximum value of this enum. */ ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_UIF, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE) } ZydisRegister; /* ---------------------------------------------------------------------------------------------- */ /* Register kinds */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisRegisterKind` enum. * * Please note that this enum does not contain a matching entry for all values of the * `ZydisRegister` enum, but only for those registers where it makes sense to logically group them * for decoding/encoding purposes. * * These are mainly the registers that can be identified by an id within their corresponding * register-class. */ typedef enum ZydisRegisterKind_ { ZYDIS_REGKIND_INVALID, ZYDIS_REGKIND_GPR, ZYDIS_REGKIND_X87, ZYDIS_REGKIND_MMX, ZYDIS_REGKIND_VR, ZYDIS_REGKIND_TMM, ZYDIS_REGKIND_SEGMENT, ZYDIS_REGKIND_TEST, ZYDIS_REGKIND_CONTROL, ZYDIS_REGKIND_DEBUG, ZYDIS_REGKIND_MASK, ZYDIS_REGKIND_BOUND, /** * Maximum value of this enum. */ ZYDIS_REGKIND_MAX_VALUE = ZYDIS_REGKIND_BOUND, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_REGKIND_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGKIND_MAX_VALUE) } ZydisRegisterKind; /* ---------------------------------------------------------------------------------------------- */ /* Register classes */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisRegisterClass` enum. * * Please note that this enum does not contain a matching entry for all values of the * `ZydisRegister` enum, but only for those registers where it makes sense to logically group them * for decoding/encoding purposes. * * These are mainly the registers that can be identified by an id within their corresponding * register-class. The `IP` and `FLAGS` values are exceptions to this rule. */ typedef enum ZydisRegisterClass_ { ZYDIS_REGCLASS_INVALID, /** * 8-bit general-purpose registers. */ ZYDIS_REGCLASS_GPR8, /** * 16-bit general-purpose registers. */ ZYDIS_REGCLASS_GPR16, /** * 32-bit general-purpose registers. */ ZYDIS_REGCLASS_GPR32, /** * 64-bit general-purpose registers. */ ZYDIS_REGCLASS_GPR64, /** * Floating point legacy registers. */ ZYDIS_REGCLASS_X87, /** * Floating point multimedia registers. */ ZYDIS_REGCLASS_MMX, /** * 128-bit vector registers. */ ZYDIS_REGCLASS_XMM, /** * 256-bit vector registers. */ ZYDIS_REGCLASS_YMM, /** * 512-bit vector registers. */ ZYDIS_REGCLASS_ZMM, /** * Matrix registers. */ ZYDIS_REGCLASS_TMM, /* * Flags registers. */ ZYDIS_REGCLASS_FLAGS, /** * Instruction-pointer registers. */ ZYDIS_REGCLASS_IP, /** * Segment registers. */ ZYDIS_REGCLASS_SEGMENT, /** * Table registers. */ ZYDIS_REGCLASS_TABLE, /** * Test registers. */ ZYDIS_REGCLASS_TEST, /** * Control registers. */ ZYDIS_REGCLASS_CONTROL, /** * Debug registers. */ ZYDIS_REGCLASS_DEBUG, /** * Mask registers. */ ZYDIS_REGCLASS_MASK, /** * Bound registers. */ ZYDIS_REGCLASS_BOUND, /** * Maximum value of this enum. */ ZYDIS_REGCLASS_MAX_VALUE = ZYDIS_REGCLASS_BOUND, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_REGCLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGCLASS_MAX_VALUE) } ZydisRegisterClass; /* ---------------------------------------------------------------------------------------------- */ /* Register width */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisRegisterWidth` data-type. */ typedef ZyanU16 ZydisRegisterWidth; /* ---------------------------------------------------------------------------------------------- */ /* Register context */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisRegisterContext` struct. */ typedef struct ZydisRegisterContext_ { /** * The values stored in the register context. */ ZyanU64 values[ZYDIS_REGISTER_MAX_VALUE + 1]; } ZydisRegisterContext; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup register Register * Functions allowing retrieval of information about registers. * @{ */ /* ---------------------------------------------------------------------------------------------- */ /* Register */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the register specified by the `register_class` and `id` tuple. * * @param register_class The register class. * @param id The register id. * * @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`, * if an invalid parameter was passed. */ ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id); /** * Returns the id of the specified register. * * @param reg The register. * * @return The id of the specified register, or -1 if an invalid parameter was passed. */ ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg); /** * Returns the register-class of the specified register. * * @param reg The register. * * @return The register-class of the specified register. */ ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); /** * Returns the width of the specified register. * * @param mode The active machine mode. * @param reg The register. * * @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is * invalid for the active machine-mode. */ ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg); /** * Returns the largest enclosing register of the given register. * * @param mode The active machine mode. * @param reg The register. * * @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the * register is invalid for the active machine-mode. */ ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegister reg); /** * Returns the specified register string. * * @param reg The register. * * @return The register string or `ZYAN_NULL`, if an invalid register was passed. */ ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg); /** * Returns the specified register string as `ZydisShortString`. * * @param reg The register. * * @return The register string or `ZYAN_NULL`, if an invalid register was passed. * * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. */ ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg); /* ---------------------------------------------------------------------------------------------- */ /* Register class */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the width of the specified register-class. * * @param mode The active machine mode. * @param register_class The register class. * * @return The width of the specified register. */ ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, ZydisRegisterClass register_class); /* ---------------------------------------------------------------------------------------------- */ /** * @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_REGISTER_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Decoded operand */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Operand attributes */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisOperandAttributes` data-type. */ typedef ZyanU8 ZydisOperandAttributes; /** * The operand is a `MULTISOURCE4` register operand. * * This is a special register operand-type used by `4FMAPS` instructions where the given register * points to the first register of a register range (4 registers in total). * * Example: ZMM3 -> [ZMM3..ZMM6] */ #define ZYDIS_OATTRIB_IS_MULTISOURCE4 0x01 // (1 << 0) /* ---------------------------------------------------------------------------------------------- */ /* Memory type */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisMemoryOperandType` enum. */ typedef enum ZydisMemoryOperandType_ { ZYDIS_MEMOP_TYPE_INVALID, /** * Normal memory operand. */ ZYDIS_MEMOP_TYPE_MEM, /** * The memory operand is only used for address-generation. No real memory-access is * caused. */ ZYDIS_MEMOP_TYPE_AGEN, /** * A memory operand using `SIB` addressing form, where the index register is not used * in address calculation and scale is ignored. No real memory-access is caused. */ ZYDIS_MEMOP_TYPE_MIB, /** * A vector `SIB` memory addressing operand (`VSIB`). */ ZYDIS_MEMOP_TYPE_VSIB, /** * Maximum value of this enum. */ ZYDIS_MEMOP_TYPE_MAX_VALUE = ZYDIS_MEMOP_TYPE_VSIB, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_MEMOP_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MEMOP_TYPE_MAX_VALUE) } ZydisMemoryOperandType; /* ---------------------------------------------------------------------------------------------- */ /* Decoded operand */ /* ---------------------------------------------------------------------------------------------- */ /** * Extended info for register-operands. */ typedef struct ZydisDecodedOperandReg_ { /** * The register value. */ ZydisRegister value; } ZydisDecodedOperandReg; /** * Extended info for memory-operands. */ typedef struct ZydisDecodedOperandMem_ { /** * The type of the memory operand. */ ZydisMemoryOperandType type; /** * The segment register. */ ZydisRegister segment; /** * The base register. */ ZydisRegister base; /** * The index register. */ ZydisRegister index; /** * The scale factor. */ ZyanU8 scale; /** * Extended info for memory-operands with displacement. */ struct ZydisDecodedOperandMemDisp_ { /** * Signals, if the displacement value is used. */ ZyanBool has_displacement; /** * The displacement value */ ZyanI64 value; } disp; } ZydisDecodedOperandMem; /** * Extended info for pointer-operands. */ typedef struct ZydisDecodedOperandPtr_ { ZyanU16 segment; ZyanU32 offset; } ZydisDecodedOperandPtr; /** * Extended info for immediate-operands. */ typedef struct ZydisDecodedOperandImm_ { /** * Signals, if the immediate value is signed. */ ZyanBool is_signed; /** * Signals, if the immediate value contains a relative offset. You can use * `ZydisCalcAbsoluteAddress` to determine the absolute address value. */ ZyanBool is_relative; /** * The immediate value. */ union ZydisDecodedOperandImmValue_ { ZyanU64 u; ZyanI64 s; } value; } ZydisDecodedOperandImm; /** * Defines the `ZydisDecodedOperand` struct. */ typedef struct ZydisDecodedOperand_ { /** * The operand-id. */ ZyanU8 id; /** * The visibility of the operand. */ ZydisOperandVisibility visibility; /** * The operand-actions. */ ZydisOperandActions actions; /** * The operand-encoding. */ ZydisOperandEncoding encoding; /** * The logical size of the operand (in bits). */ ZyanU16 size; /** * The element-type. */ ZydisElementType element_type; /** * The size of a single element. */ ZydisElementSize element_size; /** * The number of elements. */ ZyanU16 element_count; /* * Additional operand attributes. */ ZydisOperandAttributes attributes; /** * The type of the operand. */ ZydisOperandType type; /* * Operand type specific information. * * The enabled union variant is determined by the `type` field. */ union { ZydisDecodedOperandReg reg; ZydisDecodedOperandMem mem; ZydisDecodedOperandPtr ptr; ZydisDecodedOperandImm imm; }; } ZydisDecodedOperand; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Decoded instruction */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* CPU/FPU flags */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisAccessedFlagsMask` data-type. */ typedef ZyanU32 ZydisAccessedFlagsMask; /** * @defgroup decoder_cpu_flags CPU flags * @ingroup decoder * * Constants used for testing CPU flags accessed by an instruction. * * @{ */ /** * Carry flag. */ #define ZYDIS_CPUFLAG_CF (1ul << 0) /** * Parity flag. */ #define ZYDIS_CPUFLAG_PF (1ul << 2) /** * Adjust flag. */ #define ZYDIS_CPUFLAG_AF (1ul << 4) /** * Zero flag. */ #define ZYDIS_CPUFLAG_ZF (1ul << 6) /** * Sign flag. */ #define ZYDIS_CPUFLAG_SF (1ul << 7) /** * Trap flag. */ #define ZYDIS_CPUFLAG_TF (1ul << 8) /** * Interrupt enable flag. */ #define ZYDIS_CPUFLAG_IF (1ul << 9) /** * Direction flag. */ #define ZYDIS_CPUFLAG_DF (1ul << 10) /** * Overflow flag. */ #define ZYDIS_CPUFLAG_OF (1ul << 11) /** * I/O privilege level flag. */ #define ZYDIS_CPUFLAG_IOPL (1ul << 12) /** * Nested task flag. */ #define ZYDIS_CPUFLAG_NT (1ul << 14) /** * Resume flag. */ #define ZYDIS_CPUFLAG_RF (1ul << 16) /** * Virtual 8086 mode flag. */ #define ZYDIS_CPUFLAG_VM (1ul << 17) /** * Alignment check. */ #define ZYDIS_CPUFLAG_AC (1ul << 18) /** * Virtual interrupt flag. */ #define ZYDIS_CPUFLAG_VIF (1ul << 19) /** * Virtual interrupt pending. */ #define ZYDIS_CPUFLAG_VIP (1ul << 20) /** * Able to use CPUID instruction. */ #define ZYDIS_CPUFLAG_ID (1ul << 21) /** * @} */ /** * @defgroup decoder_fpu_flags FPU flags * @ingroup decoder * * Constants used for testing FPU flags accessed by an instruction. * * @{ */ /** * FPU condition-code flag 0. */ #define ZYDIS_FPUFLAG_C0 (1ul << 0) /** * FPU condition-code flag 1. */ #define ZYDIS_FPUFLAG_C1 (1ul << 1) /** * FPU condition-code flag 2. */ #define ZYDIS_FPUFLAG_C2 (1ul << 2) /** * FPU condition-code flag 3. */ #define ZYDIS_FPUFLAG_C3 (1ul << 3) /** * @} */ /* * Information about CPU/FPU flags accessed by the instruction. */ typedef struct ZydisAccessedFlags_ { /* * As mask containing the flags `TESTED` by the instruction. */ ZydisAccessedFlagsMask tested; /* * As mask containing the flags `MODIFIED` by the instruction. */ ZydisAccessedFlagsMask modified; /* * As mask containing the flags `SET_0` by the instruction. */ ZydisAccessedFlagsMask set_0; /* * As mask containing the flags `SET_1` by the instruction. */ ZydisAccessedFlagsMask set_1; /* * As mask containing the flags `UNDEFINED` by the instruction. */ ZydisAccessedFlagsMask undefined; } ZydisAccessedFlags; /* ---------------------------------------------------------------------------------------------- */ /* Branch types */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisBranchType` enum. */ typedef enum ZydisBranchType_ { /** * The instruction is not a branch instruction. */ ZYDIS_BRANCH_TYPE_NONE, /** * The instruction is a short (8-bit) branch instruction. */ ZYDIS_BRANCH_TYPE_SHORT, /** * The instruction is a near (16-bit or 32-bit) branch instruction. */ ZYDIS_BRANCH_TYPE_NEAR, /** * The instruction is a far (inter-segment) branch instruction. */ ZYDIS_BRANCH_TYPE_FAR, /** * Maximum value of this enum. */ ZYDIS_BRANCH_TYPE_MAX_VALUE = ZYDIS_BRANCH_TYPE_FAR, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_BRANCH_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BRANCH_TYPE_MAX_VALUE) } ZydisBranchType; /* ---------------------------------------------------------------------------------------------- */ /* SSE/AVX exception-class */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisExceptionClass` enum. */ typedef enum ZydisExceptionClass_ { ZYDIS_EXCEPTION_CLASS_NONE, // TODO: FP Exceptions ZYDIS_EXCEPTION_CLASS_SSE1, ZYDIS_EXCEPTION_CLASS_SSE2, ZYDIS_EXCEPTION_CLASS_SSE3, ZYDIS_EXCEPTION_CLASS_SSE4, ZYDIS_EXCEPTION_CLASS_SSE5, ZYDIS_EXCEPTION_CLASS_SSE7, ZYDIS_EXCEPTION_CLASS_AVX1, ZYDIS_EXCEPTION_CLASS_AVX2, ZYDIS_EXCEPTION_CLASS_AVX3, ZYDIS_EXCEPTION_CLASS_AVX4, ZYDIS_EXCEPTION_CLASS_AVX5, ZYDIS_EXCEPTION_CLASS_AVX6, ZYDIS_EXCEPTION_CLASS_AVX7, ZYDIS_EXCEPTION_CLASS_AVX8, ZYDIS_EXCEPTION_CLASS_AVX11, ZYDIS_EXCEPTION_CLASS_AVX12, ZYDIS_EXCEPTION_CLASS_E1, ZYDIS_EXCEPTION_CLASS_E1NF, ZYDIS_EXCEPTION_CLASS_E2, ZYDIS_EXCEPTION_CLASS_E2NF, ZYDIS_EXCEPTION_CLASS_E3, ZYDIS_EXCEPTION_CLASS_E3NF, ZYDIS_EXCEPTION_CLASS_E4, ZYDIS_EXCEPTION_CLASS_E4NF, ZYDIS_EXCEPTION_CLASS_E5, ZYDIS_EXCEPTION_CLASS_E5NF, ZYDIS_EXCEPTION_CLASS_E6, ZYDIS_EXCEPTION_CLASS_E6NF, ZYDIS_EXCEPTION_CLASS_E7NM, ZYDIS_EXCEPTION_CLASS_E7NM128, ZYDIS_EXCEPTION_CLASS_E9NF, ZYDIS_EXCEPTION_CLASS_E10, ZYDIS_EXCEPTION_CLASS_E10NF, ZYDIS_EXCEPTION_CLASS_E11, ZYDIS_EXCEPTION_CLASS_E11NF, ZYDIS_EXCEPTION_CLASS_E12, ZYDIS_EXCEPTION_CLASS_E12NP, ZYDIS_EXCEPTION_CLASS_K20, ZYDIS_EXCEPTION_CLASS_K21, ZYDIS_EXCEPTION_CLASS_AMXE1, ZYDIS_EXCEPTION_CLASS_AMXE2, ZYDIS_EXCEPTION_CLASS_AMXE3, ZYDIS_EXCEPTION_CLASS_AMXE4, ZYDIS_EXCEPTION_CLASS_AMXE5, ZYDIS_EXCEPTION_CLASS_AMXE6, /** * Maximum value of this enum. */ ZYDIS_EXCEPTION_CLASS_MAX_VALUE = ZYDIS_EXCEPTION_CLASS_AMXE6, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EXCEPTION_CLASS_MAX_VALUE) } ZydisExceptionClass; /* ---------------------------------------------------------------------------------------------- */ /* AVX mask mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisMaskMode` enum. */ typedef enum ZydisMaskMode_ { ZYDIS_MASK_MODE_INVALID, /** * Masking is disabled for the current instruction (`K0` register is used). */ ZYDIS_MASK_MODE_DISABLED, /** * The embedded mask register is used as a merge-mask. */ ZYDIS_MASK_MODE_MERGING, /** * The embedded mask register is used as a zero-mask. */ ZYDIS_MASK_MODE_ZEROING, /** * The embedded mask register is used as a control-mask (element selector). */ ZYDIS_MASK_MODE_CONTROL, /** * The embedded mask register is used as a zeroing control-mask (element selector). */ ZYDIS_MASK_MODE_CONTROL_ZEROING, /** * Maximum value of this enum. */ ZYDIS_MASK_MODE_MAX_VALUE = ZYDIS_MASK_MODE_CONTROL_ZEROING, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_MASK_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_MODE_MAX_VALUE) } ZydisMaskMode; /* ---------------------------------------------------------------------------------------------- */ /* AVX broadcast-mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisBroadcastMode` enum. */ typedef enum ZydisBroadcastMode_ { ZYDIS_BROADCAST_MODE_INVALID, ZYDIS_BROADCAST_MODE_1_TO_2, ZYDIS_BROADCAST_MODE_1_TO_4, ZYDIS_BROADCAST_MODE_1_TO_8, ZYDIS_BROADCAST_MODE_1_TO_16, ZYDIS_BROADCAST_MODE_1_TO_32, ZYDIS_BROADCAST_MODE_1_TO_64, ZYDIS_BROADCAST_MODE_2_TO_4, ZYDIS_BROADCAST_MODE_2_TO_8, ZYDIS_BROADCAST_MODE_2_TO_16, ZYDIS_BROADCAST_MODE_4_TO_8, ZYDIS_BROADCAST_MODE_4_TO_16, ZYDIS_BROADCAST_MODE_8_TO_16, /** * Maximum value of this enum. */ ZYDIS_BROADCAST_MODE_MAX_VALUE = ZYDIS_BROADCAST_MODE_8_TO_16, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_BROADCAST_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BROADCAST_MODE_MAX_VALUE) } ZydisBroadcastMode; /* ---------------------------------------------------------------------------------------------- */ /* AVX rounding-mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisRoundingMode` enum. */ typedef enum ZydisRoundingMode_ { ZYDIS_ROUNDING_MODE_INVALID, /** * Round to nearest. */ ZYDIS_ROUNDING_MODE_RN, /** * Round down. */ ZYDIS_ROUNDING_MODE_RD, /** * Round up. */ ZYDIS_ROUNDING_MODE_RU, /** * Round towards zero. */ ZYDIS_ROUNDING_MODE_RZ, /** * Maximum value of this enum. */ ZYDIS_ROUNDING_MODE_MAX_VALUE = ZYDIS_ROUNDING_MODE_RZ, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ROUNDING_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ROUNDING_MODE_MAX_VALUE) } ZydisRoundingMode; /* ---------------------------------------------------------------------------------------------- */ /* KNC swizzle-mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisSwizzleMode` enum. */ typedef enum ZydisSwizzleMode_ { ZYDIS_SWIZZLE_MODE_INVALID, ZYDIS_SWIZZLE_MODE_DCBA, ZYDIS_SWIZZLE_MODE_CDAB, ZYDIS_SWIZZLE_MODE_BADC, ZYDIS_SWIZZLE_MODE_DACB, ZYDIS_SWIZZLE_MODE_AAAA, ZYDIS_SWIZZLE_MODE_BBBB, ZYDIS_SWIZZLE_MODE_CCCC, ZYDIS_SWIZZLE_MODE_DDDD, /** * Maximum value of this enum. */ ZYDIS_SWIZZLE_MODE_MAX_VALUE = ZYDIS_SWIZZLE_MODE_DDDD, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_SWIZZLE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SWIZZLE_MODE_MAX_VALUE) } ZydisSwizzleMode; /* ---------------------------------------------------------------------------------------------- */ /* KNC conversion-mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisConversionMode` enum. */ typedef enum ZydisConversionMode_ { ZYDIS_CONVERSION_MODE_INVALID, ZYDIS_CONVERSION_MODE_FLOAT16, ZYDIS_CONVERSION_MODE_SINT8, ZYDIS_CONVERSION_MODE_UINT8, ZYDIS_CONVERSION_MODE_SINT16, ZYDIS_CONVERSION_MODE_UINT16, /** * Maximum value of this enum. */ ZYDIS_CONVERSION_MODE_MAX_VALUE = ZYDIS_CONVERSION_MODE_UINT16, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_CONVERSION_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CONVERSION_MODE_MAX_VALUE) } ZydisConversionMode; /* ---------------------------------------------------------------------------------------------- */ /* Legacy prefix type */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisPrefixType` enum. */ typedef enum ZydisPrefixType_ { /** * The prefix is ignored by the instruction. * * This applies to all prefixes that are not accepted by the instruction in general or the * ones that are overwritten by a prefix of the same group closer to the instruction opcode. */ ZYDIS_PREFIX_TYPE_IGNORED, /** * The prefix is effectively used by the instruction. */ ZYDIS_PREFIX_TYPE_EFFECTIVE, /** * The prefix is used as a mandatory prefix. * * A mandatory prefix is interpreted as an opcode extension and has no further effect on the * instruction. */ ZYDIS_PREFIX_TYPE_MANDATORY, /** * Maximum value of this enum. */ ZYDIS_PREFIX_TYPE_MAX_VALUE = ZYDIS_PREFIX_TYPE_MANDATORY, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_PREFIX_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PREFIX_TYPE_MAX_VALUE) } ZydisPrefixType; // TODO: Check effective for 66/67 prefixes (currently defaults to EFFECTIVE) /* ---------------------------------------------------------------------------------------------- */ /* Decoded instruction */ /* ---------------------------------------------------------------------------------------------- */ /** * Detailed info about the `REX` prefix. */ typedef struct ZydisDecodedInstructionRawRex_ { /** * 64-bit operand-size promotion. */ ZyanU8 W; /** * Extension of the `ModRM.reg` field. */ ZyanU8 R; /** * Extension of the `SIB.index` field. */ ZyanU8 X; /** * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field. */ ZyanU8 B; /** * The offset of the effective `REX` byte, relative to the beginning of the * instruction, in bytes. * * This offset always points to the "effective" `REX` prefix (the one closest to the * instruction opcode), if multiple `REX` prefixes are present. * * Note that the `REX` byte can be the first byte of the instruction, which would lead * to an offset of `0`. Please refer to the instruction attributes to check for the * presence of the `REX` prefix. */ ZyanU8 offset; } ZydisDecodedInstructionRawRex; /** * Detailed info about the `XOP` prefix. */ typedef struct ZydisDecodedInstructionRawXop_ { /** * Extension of the `ModRM.reg` field (inverted). */ ZyanU8 R; /** * Extension of the `SIB.index` field (inverted). */ ZyanU8 X; /** * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). */ ZyanU8 B; /** * Opcode-map specifier. */ ZyanU8 m_mmmm; /** * 64-bit operand-size promotion or opcode-extension. */ ZyanU8 W; /** * `NDS`/`NDD` (non-destructive-source/destination) register * specifier (inverted). */ ZyanU8 vvvv; /** * Vector-length specifier. */ ZyanU8 L; /** * Compressed legacy prefix. */ ZyanU8 pp; /** * The offset of the first xop byte, relative to the beginning of * the instruction, in bytes. */ ZyanU8 offset; } ZydisDecodedInstructionRawXop; /** * Detailed info about the `VEX` prefix. */ typedef struct ZydisDecodedInstructionRawVex_ { /** * Extension of the `ModRM.reg` field (inverted). */ ZyanU8 R; /** * Extension of the `SIB.index` field (inverted). */ ZyanU8 X; /** * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). */ ZyanU8 B; /** * Opcode-map specifier. */ ZyanU8 m_mmmm; /** * 64-bit operand-size promotion or opcode-extension. */ ZyanU8 W; /** * `NDS`/`NDD` (non-destructive-source/destination) register specifier * (inverted). */ ZyanU8 vvvv; /** * Vector-length specifier. */ ZyanU8 L; /** * Compressed legacy prefix. */ ZyanU8 pp; /** * The offset of the first `VEX` byte, relative to the beginning of the instruction, in * bytes. */ ZyanU8 offset; /** * The size of the `VEX` prefix, in bytes. */ ZyanU8 size; } ZydisDecodedInstructionRawVex; /** * Detailed info about the `EVEX` prefix. */ typedef struct ZydisDecodedInstructionRawEvex { /** * Extension of the `ModRM.reg` field (inverted). */ ZyanU8 R; /** * Extension of the `SIB.index/vidx` field (inverted). */ ZyanU8 X; /** * Extension of the `ModRM.rm` or `SIB.base` field (inverted). */ ZyanU8 B; /** * High-16 register specifier modifier (inverted). */ ZyanU8 R2; /** * Opcode-map specifier. */ ZyanU8 mmm; /** * 64-bit operand-size promotion or opcode-extension. */ ZyanU8 W; /** * `NDS`/`NDD` (non-destructive-source/destination) register specifier * (inverted). */ ZyanU8 vvvv; /** * Compressed legacy prefix. */ ZyanU8 pp; /** * Zeroing/Merging. */ ZyanU8 z; /** * Vector-length specifier or rounding-control (most significant bit). */ ZyanU8 L2; /** * Vector-length specifier or rounding-control (least significant bit). */ ZyanU8 L; /** * Broadcast/RC/SAE context. */ ZyanU8 b; /** * High-16 `NDS`/`VIDX` register specifier. */ ZyanU8 V2; /** * Embedded opmask register specifier. */ ZyanU8 aaa; /** * The offset of the first evex byte, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } ZydisDecodedInstructionRawEvex; /** * Detailed info about the `MVEX` prefix. */ typedef struct ZydisDecodedInstructionRawMvex_ { /** * Extension of the `ModRM.reg` field (inverted). */ ZyanU8 R; /** * Extension of the `SIB.index/vidx` field (inverted). */ ZyanU8 X; /** * Extension of the `ModRM.rm` or `SIB.base` field (inverted). */ ZyanU8 B; /** * High-16 register specifier modifier (inverted). */ ZyanU8 R2; /** * Opcode-map specifier. */ ZyanU8 mmmm; /** * 64-bit operand-size promotion or opcode-extension. */ ZyanU8 W; /** * `NDS`/`NDD` (non-destructive-source/destination) register specifier * (inverted). */ ZyanU8 vvvv; /** * Compressed legacy prefix. */ ZyanU8 pp; /** * Non-temporal/eviction hint. */ ZyanU8 E; /** * Swizzle/broadcast/up-convert/down-convert/static-rounding controls. */ ZyanU8 SSS; /** * High-16 `NDS`/`VIDX` register specifier. */ ZyanU8 V2; /** * Embedded opmask register specifier. */ ZyanU8 kkk; /** * The offset of the first mvex byte, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } ZydisDecodedInstructionRawMvex; /** * Extended info for `AVX` instructions. */ typedef struct ZydisDecodedInstructionAvx_ { /** * The `AVX` vector-length. */ ZyanU16 vector_length; /** * Info about the embedded writemask-register (`AVX-512` and `KNC` only). */ struct ZydisDecodedInstructionAvxMask_ { /** * The masking mode. */ ZydisMaskMode mode; /** * The mask register. */ ZydisRegister reg; } mask; /** * Contains info about the `AVX` broadcast. */ struct ZydisDecodedInstructionAvxBroadcast_ { /** * Signals, if the broadcast is a static broadcast. * * This is the case for instructions with inbuilt broadcast functionality, which is * always active and not controlled by the `EVEX/MVEX.RC` bits. */ ZyanBool is_static; /** * The `AVX` broadcast-mode. */ ZydisBroadcastMode mode; } broadcast; /** * Contains info about the `AVX` rounding. */ struct ZydisDecodedInstructionAvxRounding_ { /** * The `AVX` rounding-mode. */ ZydisRoundingMode mode; } rounding; /** * Contains info about the `AVX` register-swizzle (`KNC` only). */ struct ZydisDecodedInstructionAvxSwizzle_ { /** * The `AVX` register-swizzle mode. */ ZydisSwizzleMode mode; } swizzle; /** * Contains info about the `AVX` data-conversion (`KNC` only). */ struct ZydisDecodedInstructionAvxConversion_ { /** * The `AVX` data-conversion mode. */ ZydisConversionMode mode; } conversion; /** * Signals, if the `SAE` (suppress-all-exceptions) functionality is * enabled for the instruction. */ ZyanBool has_sae; /** * Signals, if the instruction has a memory-eviction-hint (`KNC` only). */ ZyanBool has_eviction_hint; // TODO: publish EVEX tuple-type and MVEX functionality } ZydisDecodedInstructionAvx; /** * Instruction meta info. */ typedef struct ZydisDecodedInstructionMeta_ { /** * The instruction category. */ ZydisInstructionCategory category; /** * The ISA-set. */ ZydisISASet isa_set; /** * The ISA-set extension. */ ZydisISAExt isa_ext; /** * The branch type. */ ZydisBranchType branch_type; /** * The exception class. */ ZydisExceptionClass exception_class; } ZydisDecodedInstructionMeta; /** * Detailed info about different instruction-parts like `ModRM`, `SIB` or * encoding-prefixes. */ typedef struct ZydisDecodedInstructionRaw_ { /** * The number of legacy prefixes. */ ZyanU8 prefix_count; /** * Detailed info about the legacy prefixes (including `REX`). */ struct ZydisDecodedInstructionRawPrefixes_ { /** * The prefix type. */ ZydisPrefixType type; /** * The prefix byte. */ ZyanU8 value; } prefixes[ZYDIS_MAX_INSTRUCTION_LENGTH]; /* * Copy of the `encoding` field. * * This is here to allow the Rust bindings to treat the following union as an `enum`, * sparing us a lot of unsafe code. Prefer using the regular `encoding` field in C/C++ code. */ ZydisInstructionEncoding encoding2; /* * Union for things from various mutually exclusive encodings. */ union { ZydisDecodedInstructionRawRex rex; ZydisDecodedInstructionRawXop xop; ZydisDecodedInstructionRawVex vex; ZydisDecodedInstructionRawEvex evex; ZydisDecodedInstructionRawMvex mvex; }; /** * Detailed info about the `ModRM` byte. */ struct ZydisDecodedInstructionModRm_ { /** * The addressing mode. */ ZyanU8 mod; /** * Register specifier or opcode-extension. */ ZyanU8 reg; /** * Register specifier or opcode-extension. */ ZyanU8 rm; /** * The offset of the `ModRM` byte, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } modrm; /** * Detailed info about the `SIB` byte. */ struct ZydisDecodedInstructionRawSib_ { /** * The scale factor. */ ZyanU8 scale; /** * The index-register specifier. */ ZyanU8 index; /** * The base-register specifier. */ ZyanU8 base; /** * The offset of the `SIB` byte, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } sib; /** * Detailed info about displacement-bytes. */ struct ZydisDecodedInstructionRawDisp_ { /** * The displacement value */ ZyanI64 value; /** * The physical displacement size, in bits. */ ZyanU8 size; // TODO: publish cd8 scale /** * The offset of the displacement data, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } disp; /** * Detailed info about immediate-bytes. */ struct ZydisDecodedInstructionRawImm_ { /** * Signals, if the immediate value is signed. */ ZyanBool is_signed; /** * Signals, if the immediate value contains a relative offset. You can use * `ZydisCalcAbsoluteAddress` to determine the absolute address value. */ ZyanBool is_relative; /** * The immediate value. */ union ZydisDecodedInstructionRawImmValue_ { ZyanU64 u; ZyanI64 s; } value; /** * The physical immediate size, in bits. */ ZyanU8 size; /** * The offset of the immediate data, relative to the beginning of the * instruction, in bytes. */ ZyanU8 offset; } imm[2]; } ZydisDecodedInstructionRaw; /** * Information about a decoded instruction. */ typedef struct ZydisDecodedInstruction_ { /** * The machine mode used to decode this instruction. */ ZydisMachineMode machine_mode; /** * The instruction-mnemonic. */ ZydisMnemonic mnemonic; /** * The length of the decoded instruction. */ ZyanU8 length; /** * The instruction-encoding (`LEGACY`, `3DNOW`, `VEX`, `EVEX`, `XOP`). */ ZydisInstructionEncoding encoding; /** * The opcode-map. */ ZydisOpcodeMap opcode_map; /** * The instruction-opcode. */ ZyanU8 opcode; /** * The stack width. */ ZyanU8 stack_width; /** * The effective operand width. */ ZyanU8 operand_width; /** * The effective address width. */ ZyanU8 address_width; /** * The number of instruction-operands. * * Explicit and implicit operands are guaranteed to be in the front and ordered as they are * printed by the formatter in `Intel` mode. No assumptions can be made about the order of * hidden operands, except that they always located behind the explicit and implicit operands. */ ZyanU8 operand_count; /** * The number of explicit (visible) instruction-operands. * * Explicit and implicit operands are guaranteed to be in the front and ordered as they are * printed by the formatter in `Intel` mode. */ ZyanU8 operand_count_visible; /** * See @ref instruction_attributes. */ ZydisInstructionAttributes attributes; /** * Information about CPU flags accessed by the instruction. * * The bits in the masks correspond to the actual bits in the `FLAGS/EFLAGS/RFLAGS` * register. See @ref decoder_cpu_flags. */ const ZydisAccessedFlags* cpu_flags; /** * Information about FPU flags accessed by the instruction. * * See @ref decoder_fpu_flags. */ const ZydisAccessedFlags* fpu_flags; /** * Extended info for `AVX` instructions. */ ZydisDecodedInstructionAvx avx; /** * Meta info. */ ZydisDecodedInstructionMeta meta; /** * Detailed info about different instruction-parts like `ModRM`, `SIB` or * encoding-prefixes. */ ZydisDecodedInstructionRaw raw; } ZydisDecodedInstruction; /* ---------------------------------------------------------------------------------------------- */ /* Decoder context */ /* ---------------------------------------------------------------------------------------------- */ /** * The decoder context is used to preserve some internal state between subsequent decode * operations for THE SAME instruction. * * The context is initialized by @c ZydisDecoderDecodeInstruction and required by e.g. * @c ZydisDecoderDecodeOperands. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. * * This struct is neither ABI nor API stable! */ typedef struct ZydisDecoderContext_ { /** * A pointer to the internal instruction definition. */ const void* definition; /** * Contains the effective operand-size index. * * 0 = 16 bit, 1 = 32 bit, 2 = 64 bit */ ZyanU8 eosz_index; /** * Contains the effective address-size index. * * 0 = 16 bit, 1 = 32 bit, 2 = 64 bit */ ZyanU8 easz_index; /** * Contains some cached REX/XOP/VEX/EVEX/MVEX values to provide uniform access. */ struct { ZyanU8 W; ZyanU8 R; ZyanU8 X; ZyanU8 B; ZyanU8 L; ZyanU8 LL; ZyanU8 R2; ZyanU8 V2; ZyanU8 vvvv; ZyanU8 mask; } vector_unified; /** * Information about encoded operand registers. */ struct { /** * Signals if the `modrm.mod == 3` or `reg` form is forced for the instruction. */ ZyanBool is_mod_reg; /** * The final register id for the `reg` encoded register. */ ZyanU8 id_reg; /** * The final register id for the `rm` encoded register. * * This value is only set, if a register is encoded in `modrm.rm`. */ ZyanU8 id_rm; /** * The final register id for the `ndsndd` (`.vvvv`) encoded register. */ ZyanU8 id_ndsndd; /** * The final register id for the base register. * * This value is only set, if a memory operand is encoded in `modrm.rm`. */ ZyanU8 id_base; /** * The final register id for the index register. * * This value is only set, if a memory operand is encoded in `modrm.rm` and the `SIB` byte * is present. */ ZyanU8 id_index; } reg_info; /** * Internal EVEX-specific information. */ struct { /** * The EVEX tuple-type. */ ZyanU8 tuple_type; /** * The EVEX element-size. */ ZyanU8 element_size; } evex; /** * Internal MVEX-specific information. */ struct { /** * The MVEX functionality. */ ZyanU8 functionality; } mvex; /** * The scale factor for EVEX/MVEX compressed 8-bit displacement values. */ ZyanU8 cd8_scale; // TODO: Could make sense to expose this in the ZydisDecodedInstruction } ZydisDecoderContext; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_INSTRUCTIONINFO_H */ // // Header: Zydis/Status.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Status code definitions and check macros. */ #ifndef ZYDIS_STATUS_H #define ZYDIS_STATUS_H // // Header: Zycore/Status.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Decoder.h // - Zydis/Status.h // /*************************************************************************************************** Zyan Core Library (Zyan-C) Original Author : Florian Bernd, Joel Hoener * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Status code definitions and check macros. */ #ifndef ZYCORE_STATUS_H #define ZYCORE_STATUS_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZyanStatus` data type. */ typedef ZyanU32 ZyanStatus; /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Definition */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines a zyan status code. * * @param error `1`, if the status code signals an error or `0`, if not. * @param module The module id. * @param code The actual code. * * @return The zyan status code. */ #define ZYAN_MAKE_STATUS(error, module, code) \ (ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu)) /* ---------------------------------------------------------------------------------------------- */ /* Checks */ /* ---------------------------------------------------------------------------------------------- */ /** * Checks if a zyan operation was successful. * * @param status The zyan status-code to check. * * @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not. */ #define ZYAN_SUCCESS(status) \ (!((status) & 0x80000000u)) /** * Checks if a zyan operation failed. * * @param status The zyan status-code to check. * * @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not. */ #define ZYAN_FAILED(status) \ ((status) & 0x80000000u) /** * Checks if a zyan operation was successful and returns with the status-code, if not. * * @param status The zyan status-code to check. */ #define ZYAN_CHECK(status) \ do \ { \ const ZyanStatus status_047620348 = (status); \ if (!ZYAN_SUCCESS(status_047620348)) \ { \ return status_047620348; \ } \ } while (0) /* ---------------------------------------------------------------------------------------------- */ /* Information */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the module id of a zyan status-code. * * @param status The zyan status-code. * * @return The module id of the zyan status-code. */ #define ZYAN_STATUS_MODULE(status) \ (((status) >> 20) & 0x7FFu) /** * Returns the code of a zyan status-code. * * @param status The zyan status-code. * * @return The code of the zyan status-code. */ #define ZYAN_STATUS_CODE(status) \ ((status) & 0xFFFFFu) /* ============================================================================================== */ /* Status codes */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Module IDs */ /* ---------------------------------------------------------------------------------------------- */ /** * The zycore generic module id. */ #define ZYAN_MODULE_ZYCORE 0x001u /** * The zycore arg-parse submodule id. */ #define ZYAN_MODULE_ARGPARSE 0x003u /** * The base module id for user-defined status codes. */ #define ZYAN_MODULE_USER 0x3FFu /* ---------------------------------------------------------------------------------------------- */ /* Status codes (general purpose) */ /* ---------------------------------------------------------------------------------------------- */ /** * The operation completed successfully. */ #define ZYAN_STATUS_SUCCESS \ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u) /** * The operation failed with an generic error. */ #define ZYAN_STATUS_FAILED \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u) /** * The operation completed successfully and returned `ZYAN_TRUE`. */ #define ZYAN_STATUS_TRUE \ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u) /** * The operation completed successfully and returned `ZYAN_FALSE`. */ #define ZYAN_STATUS_FALSE \ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u) /** * An invalid argument was passed to a function. */ #define ZYAN_STATUS_INVALID_ARGUMENT \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u) /** * An attempt was made to perform an invalid operation. */ #define ZYAN_STATUS_INVALID_OPERATION \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u) /** * Insufficient privileges to perform the requested operation. */ #define ZYAN_STATUS_ACCESS_DENIED \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u) /** * The requested entity was not found. */ #define ZYAN_STATUS_NOT_FOUND \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u) /** * An index passed to a function was out of bounds. */ #define ZYAN_STATUS_OUT_OF_RANGE \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u) /** * A buffer passed to a function was too small to complete the requested operation. */ #define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u) /** * Insufficient memory to perform the operation. */ #define ZYAN_STATUS_NOT_ENOUGH_MEMORY \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au) /** * An unknown error occurred during a system function call. */ #define ZYAN_STATUS_BAD_SYSTEMCALL \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu) /** * The process ran out of resources while performing an operation. */ #define ZYAN_STATUS_OUT_OF_RESOURCES \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu) /** * A dependency library was not found or does have an unexpected version number or * feature-set. */ #define ZYAN_STATUS_MISSING_DEPENDENCY \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du) /* ---------------------------------------------------------------------------------------------- */ /* Status codes (arg parse) */ /* ---------------------------------------------------------------------------------------------- */ /** * Argument was not expected. */ #define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u) /** * Too few arguments were provided. */ #define ZYAN_STATUS_TOO_FEW_ARGS \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u) /** * Too many arguments were provided. */ #define ZYAN_STATUS_TOO_MANY_ARGS \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u) /** * An argument that expected a value misses its value. */ #define ZYAN_STATUS_ARG_MISSES_VALUE \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u) /** * A required argument is missing. */ #define ZYAN_STATUS_REQUIRED_ARG_MISSING \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYCORE_STATUS_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Status codes */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Module IDs */ /* ---------------------------------------------------------------------------------------------- */ /** * The zydis module id. */ #define ZYAN_MODULE_ZYDIS 0x002u /* ---------------------------------------------------------------------------------------------- */ /* Status codes */ /* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */ /* Decoder */ /* ---------------------------------------------------------------------------------------------- */ /** * An attempt was made to read data from an input data-source that has no more * data available. */ #define ZYDIS_STATUS_NO_MORE_DATA \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x00u) /** * An general error occured while decoding the current instruction. The * instruction might be undefined. */ #define ZYDIS_STATUS_DECODING_ERROR \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x01u) /** * The instruction exceeded the maximum length of 15 bytes. */ #define ZYDIS_STATUS_INSTRUCTION_TOO_LONG \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x02u) /** * The instruction encoded an invalid register. */ #define ZYDIS_STATUS_BAD_REGISTER \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x03u) /** * A lock-prefix (F0) was found while decoding an instruction that does not * support locking. */ #define ZYDIS_STATUS_ILLEGAL_LOCK \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x04u) /** * A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX * instruction. */ #define ZYDIS_STATUS_ILLEGAL_LEGACY_PFX \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x05u) /** * A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction. */ #define ZYDIS_STATUS_ILLEGAL_REX \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x06u) /** * An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix. */ #define ZYDIS_STATUS_INVALID_MAP \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x07u) /** * An error occured while decoding the EVEX-prefix. */ #define ZYDIS_STATUS_MALFORMED_EVEX \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x08u) /** * An error occured while decoding the MVEX-prefix. */ #define ZYDIS_STATUS_MALFORMED_MVEX \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x09u) /** * An invalid write-mask was specified for an EVEX/MVEX instruction. */ #define ZYDIS_STATUS_INVALID_MASK \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Au) /* ---------------------------------------------------------------------------------------------- */ /* Formatter */ /* ---------------------------------------------------------------------------------------------- */ /** * Returning this status code in some specified formatter callbacks will cause * the formatter to omit the corresponding token. * * Valid callbacks: * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` */ #define ZYDIS_STATUS_SKIP_TOKEN \ ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYDIS, 0x0Bu) /* ---------------------------------------------------------------------------------------------- */ /* Encoder */ /* ---------------------------------------------------------------------------------------------- */ #define ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION \ ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Cu) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_STATUS_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Decoder mode */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisDecoderMode` enum. */ typedef enum ZydisDecoderMode_ { /** * Enables minimal instruction decoding without semantic analysis. * * This mode provides access to the mnemonic, the instruction-length, the effective * operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`) * and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct. * * Operands, most attributes and other specific information (like `AVX` info) are not * accessible in this mode. * * This mode is NOT enabled by default. */ ZYDIS_DECODER_MODE_MINIMAL, /** * Enables the `AMD`-branch mode. * * Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit * immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode. * In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the * immediate to 16-bit. * * This mode is NOT enabled by default. */ ZYDIS_DECODER_MODE_AMD_BRANCHES, /** * Enables `KNC` compatibility-mode. * * `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions. * Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..). * * This mode is NOT enabled by default. */ ZYDIS_DECODER_MODE_KNC, /** * Enables the `MPX` mode. * * The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_MPX, /** * Enables the `CET` mode. * * The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_CET, /** * Enables the `LZCNT` mode. * * The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_LZCNT, /** * Enables the `TZCNT` mode. * * The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_TZCNT, /** * Enables the `WBNOINVD` mode. * * The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is * used. * * This mode is disabled by default. */ ZYDIS_DECODER_MODE_WBNOINVD, /** * Enables the `CLDEMOTE` mode. * * The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_CLDEMOTE, /** * Enables the `IPREFETCH` mode. * * The `IPREFETCH` isa-extension reuses (overrides) some of the widenop instruction opcodes. * * This mode is enabled by default. */ ZYDIS_DECODER_MODE_IPREFETCH, /** * Enables the `UD0` compatibility mode. * * Some processors decode the `UD0` instruction without a ModR/M byte. Enable this decoder mode * to mimic this behavior. * * This mode is disabled by default. */ ZYDIS_DECODER_MODE_UD0_COMPAT, /** * Maximum value of this enum. */ ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_UD0_COMPAT, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE) } ZydisDecoderMode; /* ---------------------------------------------------------------------------------------------- */ /* Decoder struct */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisDecoder` struct. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZydisDecoder_ { /** * The machine mode. */ ZydisMachineMode machine_mode; /** * The stack width. */ ZydisStackWidth stack_width; /** * The decoder mode bitmap. */ ZyanU32 decoder_mode; } ZydisDecoder; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup decoder Decoder * Functions allowing decoding of instruction bytes to a machine interpretable struct. * @{ */ /** * Initializes the given `ZydisDecoder` instance. * * @param decoder A pointer to the `ZydisDecoder` instance. * @param machine_mode The machine mode. * @param stack_width The stack width. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode, ZydisStackWidth stack_width); /** * Enables or disables the specified decoder-mode. * * @param decoder A pointer to the `ZydisDecoder` instance. * @param mode The decoder mode. * @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, ZyanBool enabled); /** * Decodes the instruction in the given input `buffer` and returns all details (e.g. operands). * * @param decoder A pointer to the `ZydisDecoder` instance. * @param buffer A pointer to the input buffer. * @param length The length of the input buffer. Note that this can be bigger than the * actual size of the instruction -- you don't have to know the size up * front. This length is merely used to prevent Zydis from doing * out-of-bounds reads on your buffer. * @param instruction A pointer to the `ZydisDecodedInstruction` struct receiving the details * about the decoded instruction. * @param operands A pointer to an array with `ZYDIS_MAX_OPERAND_COUNT` entries that * receives the decoded operands. The number of operands decoded is * determined by the `instruction.operand_count` field. Excess entries are * zeroed. * * This is a convenience function that combines the following functions into one call: * * - `ZydisDecoderDecodeInstruction` * - `ZydisDecoderDecodeOperands` * * Please refer to `ZydisDecoderDecodeInstruction` if operand decoding is not required or should * be done separately (`ZydisDecoderDecodeOperands`). * * This function is not available in MINIMAL_MODE. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeFull(const ZydisDecoder* decoder, const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction, ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]); /** * Decodes the instruction in the given input `buffer`. * * @param decoder A pointer to the `ZydisDecoder` instance. * @param context A pointer to a decoder context struct which is required for further * decoding (e.g. operand decoding using `ZydisDecoderDecodeOperands`) or * `ZYAN_NULL` if not needed. * @param buffer A pointer to the input buffer. * @param length The length of the input buffer. Note that this can be bigger than the * actual size of the instruction -- you don't have to know the size up * front. This length is merely used to prevent Zydis from doing * out-of-bounds reads on your buffer. * @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the * details about the decoded instruction. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeInstruction(const ZydisDecoder* decoder, ZydisDecoderContext* context, const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction); /** * Decodes the instruction operands. * * @param decoder A pointer to the `ZydisDecoder` instance. * @param context A pointer to the `ZydisDecoderContext` struct. * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operands The array that receives the decoded operands. * Refer to `ZYDIS_MAX_OPERAND_COUNT` or `ZYDIS_MAX_OPERAND_COUNT_VISIBLE` * when allocating space for the array to ensure that the buffer size is * sufficient to always fit all instruction operands. * Refer to `instruction.operand_count` or * `instruction.operand_count_visible' when allocating space for the array * to ensure that the buffer size is sufficient to fit all operands of * the given instruction. * @param operand_count The length of the `operands` array. * This argument as well limits the maximum amount of operands to decode. * If this value is `0`, no operands will be decoded and `ZYAN_NULL` will * be accepted for the `operands` argument. * * This function fails, if `operand_count` is larger than the total number of operands for the * given instruction (`instruction.operand_count`). * * This function is not available in MINIMAL_MODE. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeOperands(const ZydisDecoder* decoder, const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operands, ZyanU8 operand_count); /** @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_DECODER_H */ #endif #if !defined(ZYDIS_DISABLE_ENCODER) // // Header: Zydis/Encoder.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Mappa * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Functions for encoding instructions. */ #ifndef ZYDIS_ENCODER_H #define ZYDIS_ENCODER_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constants */ /* ---------------------------------------------------------------------------------------------- */ /** * Maximum number of encodable (explicit and implicit) operands */ #define ZYDIS_ENCODER_MAX_OPERANDS 5 // If asserts are failing here remember to update encoder table generator before fixing asserts ZYAN_STATIC_ASSERT(ZYAN_BITS_TO_REPRESENT(ZYDIS_ENCODER_MAX_OPERANDS) == 3); /** * Combination of all user-encodable prefixes */ #define ZYDIS_ENCODABLE_PREFIXES (ZYDIS_ATTRIB_HAS_LOCK | \ ZYDIS_ATTRIB_HAS_REP | \ ZYDIS_ATTRIB_HAS_REPE | \ ZYDIS_ATTRIB_HAS_REPNE | \ ZYDIS_ATTRIB_HAS_BND | \ ZYDIS_ATTRIB_HAS_XACQUIRE | \ ZYDIS_ATTRIB_HAS_XRELEASE | \ ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | \ ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | \ ZYDIS_ATTRIB_HAS_NOTRACK | \ ZYDIS_ATTRIB_HAS_SEGMENT_CS | \ ZYDIS_ATTRIB_HAS_SEGMENT_SS | \ ZYDIS_ATTRIB_HAS_SEGMENT_DS | \ ZYDIS_ATTRIB_HAS_SEGMENT_ES | \ ZYDIS_ATTRIB_HAS_SEGMENT_FS | \ ZYDIS_ATTRIB_HAS_SEGMENT_GS) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines possible physical instruction encodings as bit flags, so multiple acceptable encodings * can be specified simultaneously. */ typedef enum ZydisEncodableEncoding_ { ZYDIS_ENCODABLE_ENCODING_DEFAULT = 0x00000000, ZYDIS_ENCODABLE_ENCODING_LEGACY = 0x00000001, ZYDIS_ENCODABLE_ENCODING_3DNOW = 0x00000002, ZYDIS_ENCODABLE_ENCODING_XOP = 0x00000004, ZYDIS_ENCODABLE_ENCODING_VEX = 0x00000008, ZYDIS_ENCODABLE_ENCODING_EVEX = 0x00000010, ZYDIS_ENCODABLE_ENCODING_MVEX = 0x00000020, /** * Maximum value of this enum. */ ZYDIS_ENCODABLE_ENCODING_MAX_VALUE = (ZYDIS_ENCODABLE_ENCODING_MVEX | (ZYDIS_ENCODABLE_ENCODING_MVEX - 1)), /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ENCODABLE_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ENCODABLE_ENCODING_MAX_VALUE) } ZydisEncodableEncoding; /** * Defines encodable physical/effective sizes of relative immediate operands. See * `ZydisEncoderRequest.branch_width` for more details. */ typedef enum ZydisBranchWidth_ { ZYDIS_BRANCH_WIDTH_NONE, ZYDIS_BRANCH_WIDTH_8, ZYDIS_BRANCH_WIDTH_16, ZYDIS_BRANCH_WIDTH_32, ZYDIS_BRANCH_WIDTH_64, /** * Maximum value of this enum. */ ZYDIS_BRANCH_WIDTH_MAX_VALUE = ZYDIS_BRANCH_WIDTH_64, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_BRANCH_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BRANCH_WIDTH_MAX_VALUE) } ZydisBranchWidth; /** * Defines possible values for address size hints. See `ZydisEncoderRequest` for more information * about address size hints. */ typedef enum ZydisAddressSizeHint_ { ZYDIS_ADDRESS_SIZE_HINT_NONE, ZYDIS_ADDRESS_SIZE_HINT_16, ZYDIS_ADDRESS_SIZE_HINT_32, ZYDIS_ADDRESS_SIZE_HINT_64, /** * Maximum value of this enum. */ ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE = ZYDIS_ADDRESS_SIZE_HINT_64, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_ADDRESS_SIZE_HINT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_SIZE_HINT_MAX_VALUE) } ZydisAddressSizeHint; /** * Defines possible values for operand size hints. See `ZydisEncoderRequest` for more information * about operand size hints. */ typedef enum ZydisOperandSizeHint_ { ZYDIS_OPERAND_SIZE_HINT_NONE, ZYDIS_OPERAND_SIZE_HINT_8, ZYDIS_OPERAND_SIZE_HINT_16, ZYDIS_OPERAND_SIZE_HINT_32, ZYDIS_OPERAND_SIZE_HINT_64, /** * Maximum value of this enum. */ ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE = ZYDIS_OPERAND_SIZE_HINT_64, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_OPERAND_SIZE_HINT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_SIZE_HINT_MAX_VALUE) } ZydisOperandSizeHint; /** * Describes explicit or implicit instruction operand. */ typedef struct ZydisEncoderOperand_ { /** * The type of the operand. */ ZydisOperandType type; /** * Extended info for register-operands. */ struct ZydisEncoderOperandReg_ { /** * The register value. */ ZydisRegister value; /** * Is this 4th operand (`VEX`/`XOP`). Despite its name, `is4` encoding can sometimes be * applied to 3rd operand instead of 4th. This field is used to resolve such ambiguities. * For all other operands it should be set to `ZYAN_FALSE`. */ ZyanBool is4; } reg; /** * Extended info for memory-operands. */ struct ZydisEncoderOperandMem_ { /** * The base register. */ ZydisRegister base; /** * The index register. */ ZydisRegister index; /** * The scale factor. */ ZyanU8 scale; /** * The displacement value. This value is always treated as 64-bit signed integer, so it's * important to take this into account when specifying absolute addresses. For example * to specify a 16-bit address 0x8000 in 16-bit mode it should be sign extended to * `0xFFFFFFFFFFFF8000`. See `address_size_hint` for more information about absolute * addresses. */ ZyanI64 displacement; /** * Size of this operand in bytes. */ ZyanU16 size; } mem; /** * Extended info for pointer-operands. */ struct ZydisEncoderOperandPtr_ { /** * The segment value. */ ZyanU16 segment; /** * The offset value. */ ZyanU32 offset; } ptr; /** * Extended info for immediate-operands. */ union ZydisEncoderOperandImm_ { /** * The unsigned immediate value. */ ZyanU64 u; /** * The signed immediate value. */ ZyanI64 s; } imm; } ZydisEncoderOperand; /** * Main structure consumed by the encoder. It represents full semantics of an instruction. */ typedef struct ZydisEncoderRequest_ { /** * The machine mode used to encode this instruction. */ ZydisMachineMode machine_mode; /** * This optional field can be used to restrict allowed physical encodings for desired * instruction. Some mnemonics can be supported by more than one encoding, so this field can * resolve ambiguities e.g. you can disable `AVX-512` extensions by prohibiting usage of `EVEX` * prefix and allow only `VEX` variants. */ ZydisEncodableEncoding allowed_encodings; /** * The instruction-mnemonic. */ ZydisMnemonic mnemonic; /** * A combination of requested encodable prefixes (`ZYDIS_ATTRIB_HAS_*` flags) for desired * instruction. See `ZYDIS_ENCODABLE_PREFIXES` for list of available prefixes. */ ZydisInstructionAttributes prefixes; /** * Branch type (required for branching instructions only). Use `ZYDIS_BRANCH_TYPE_NONE` to let * encoder pick size-optimal branch type automatically (`short` and `near` are prioritized over * `far`). */ ZydisBranchType branch_type; /** * Specifies physical size for relative immediate operands. Use `ZYDIS_BRANCH_WIDTH_NONE` to * let encoder pick size-optimal branch width automatically. For segment:offset `far` branches * this field applies to physical size of the offset part. For branching instructions without * relative operands this field affects effective operand size attribute. */ ZydisBranchWidth branch_width; /** * Optional address size hint used to resolve ambiguities for some instructions. Generally * encoder deduces address size from `ZydisEncoderOperand` structures that represent * explicit and implicit operands. This hint resolves conflicts when instruction's hidden * operands scale with address size attribute. * * This hint is also used for instructions with absolute memory addresses (memory operands with * displacement and no registers). Since displacement field is a 64-bit signed integer it's not * possible to determine actual size of the address value in all situations. This hint * specifies size of the address value provided inside encoder request rather than desired * address size attribute of encoded instruction. Use `ZYDIS_ADDRESS_SIZE_HINT_NONE` to assume * address size default for specified machine mode. */ ZydisAddressSizeHint address_size_hint; /** * Optional operand size hint used to resolve ambiguities for some instructions. Generally * encoder deduces operand size from `ZydisEncoderOperand` structures that represent * explicit and implicit operands. This hint resolves conflicts when instruction's hidden * operands scale with operand size attribute. */ ZydisOperandSizeHint operand_size_hint; /** * The number of instruction-operands. */ ZyanU8 operand_count; /** * Detailed info for all explicit and implicit instruction operands. */ ZydisEncoderOperand operands[ZYDIS_ENCODER_MAX_OPERANDS]; /** * Extended info for `EVEX` instructions. */ struct ZydisEncoderRequestEvexFeatures_ { /** * The broadcast-mode. Specify `ZYDIS_BROADCAST_MODE_INVALID` for instructions with * static broadcast functionality. */ ZydisBroadcastMode broadcast; /** * The rounding-mode. */ ZydisRoundingMode rounding; /** * Signals, if the `SAE` (suppress-all-exceptions) functionality should be enabled for * the instruction. */ ZyanBool sae; /** * Signals, if the zeroing-mask functionality should be enabled for the instruction. * Specify `ZYAN_TRUE` for instructions with forced zeroing mask. */ ZyanBool zeroing_mask; } evex; /** * Extended info for `MVEX` instructions. */ struct ZydisEncoderRequestMvexFeatures_ { /** * The broadcast-mode. */ ZydisBroadcastMode broadcast; /** * The data-conversion mode. */ ZydisConversionMode conversion; /** * The rounding-mode. */ ZydisRoundingMode rounding; /** * The `AVX` register-swizzle mode. */ ZydisSwizzleMode swizzle; /** * Signals, if the `SAE` (suppress-all-exceptions) functionality is enabled for * the instruction. */ ZyanBool sae; /** * Signals, if the instruction has a memory-eviction-hint (`KNC` only). */ ZyanBool eviction_hint; } mvex; } ZydisEncoderRequest; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup encoder Encoder * Functions allowing encoding of instruction bytes from a machine interpretable struct. * @{ */ /** * Encodes instruction with semantics specified in encoder request structure. * * @param request A pointer to the `ZydisEncoderRequest` struct. * @param buffer A pointer to the output buffer receiving encoded instruction. * @param length A pointer to the variable containing length of the output buffer. Upon * successful return this variable receives length of the encoded instruction. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstruction(const ZydisEncoderRequest *request, void *buffer, ZyanUSize *length); /** * Encodes instruction with semantics specified in encoder request structure. This function expects * absolute addresses inside encoder request instead of `EIP`/`RIP`-relative values. Function * predicts final instruction length prior to encoding and writes back calculated relative operands * to provided encoder request. * * @param request A pointer to the `ZydisEncoderRequest` struct. * @param buffer A pointer to the output buffer receiving encoded instruction. * @param length A pointer to the variable containing length of the output buffer. Upon * successful return this variable receives length of the encoded * instruction. * @param runtime_address The runtime address of the instruction. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstructionAbsolute(ZydisEncoderRequest *request, void *buffer, ZyanUSize *length, ZyanU64 runtime_address); /** * Converts decoded instruction to encoder request that can be passed to * `ZydisEncoderEncodeInstruction`. * * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operands A pointer to the decoded operands. * @param operand_count The operand count. * @param request A pointer to the `ZydisEncoderRequest` struct, that receives * information necessary for encoder to re-encode the instruction. * * This function performs simple structure conversion and does minimal sanity checks on the * input. There's no guarantee that produced request will be accepted by * `ZydisEncoderEncodeInstruction` if malformed `ZydisDecodedInstruction` or malformed * `ZydisDecodedOperands` is passed to this function. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisEncoderDecodedInstructionToEncoderRequest( const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands, ZyanU8 operand_count, ZydisEncoderRequest* request); /** * Fills provided buffer with `NOP` instructions using longest possible multi-byte instructions. * * @param buffer A pointer to the output buffer receiving encoded instructions. * @param length Size of the output buffer. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisEncoderNopFill(void *buffer, ZyanUSize length); /** @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_ENCODER_H */ #endif #if !defined(ZYDIS_DISABLE_FORMATTER) // // Header: Zydis/Formatter.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Functions for formatting instructions to human-readable text. */ #ifndef ZYDIS_FORMATTER_H #define ZYDIS_FORMATTER_H // // Header: Zycore/String.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // /*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Implements a string type. */ #ifndef ZYCORE_STRING_H #define ZYCORE_STRING_H // // Header: Zycore/Allocator.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // - Zycore/String.h // /*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * @brief */ #ifndef ZYCORE_ALLOCATOR_H #define ZYCORE_ALLOCATOR_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ struct ZyanAllocator_; /** * Defines the `ZyanAllocatorAllocate` function prototype. * * @param allocator A pointer to the `ZyanAllocator` instance. * @param p Receives a pointer to the first memory block sufficient to hold an * array of `n` elements with a size of `element_size`. * @param element_size The size of a single element. * @param n The number of elements to allocate storage for. * * @return A zyan status code. * * This prototype is used for the `allocate()` and `reallocate()` functions. * * The result of the `reallocate()` function is undefined, if `p` does not point to a memory block * previously obtained by `(re-)allocate()`. */ typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p, ZyanUSize element_size, ZyanUSize n); /** * Defines the `ZyanAllocatorDeallocate` function prototype. * * @param allocator A pointer to the `ZyanAllocator` instance. * @param p The pointer obtained from `(re-)allocate()`. * @param element_size The size of a single element. * @param n The number of elements earlier passed to `(re-)allocate()`. * * @return A zyan status code. */ typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p, ZyanUSize element_size, ZyanUSize n); /** * Defines the `ZyanAllocator` struct. * * This is the base class for all custom allocator implementations. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZyanAllocator_ { /** * The allocate function. */ ZyanAllocatorAllocate allocate; /** * The reallocate function. */ ZyanAllocatorAllocate reallocate; /** * The deallocate function. */ ZyanAllocatorDeallocate deallocate; } ZyanAllocator; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * Initializes the given `ZyanAllocator` instance. * * @param allocator A pointer to the `ZyanAllocator` instance. * @param allocate The allocate function. * @param reallocate The reallocate function. * @param deallocate The deallocate function. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate, ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate); #ifndef ZYAN_NO_LIBC /** * Returns the default `ZyanAllocator` instance. * * @return A pointer to the default `ZyanAllocator` instance. * * The default allocator uses the default memory manager to allocate memory on the heap. * * You should in no case modify the returned allocator instance to avoid unexpected behavior. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void); #endif // ZYAN_NO_LIBC /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYCORE_ALLOCATOR_H */ // // Header: Zycore/Vector.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // - Zycore/String.h // /*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Implements the vector container class. */ #ifndef ZYCORE_VECTOR_H #define ZYCORE_VECTOR_H // // Header: Zycore/Comparison.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // - Zycore/String.h // - Zycore/Vector.h // /*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Defines prototypes of general-purpose comparison functions. */ #ifndef ZYCORE_COMPARISON_H #define ZYCORE_COMPARISON_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZyanEqualityComparison` function prototype. * * @param left A pointer to the first element. * @param right A pointer to the second element. * * @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one * or `ZYAN_FALSE`, if not. */ typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right); /** * Defines the `ZyanComparison` function prototype. * * @param left A pointer to the first element. * @param right A pointer to the second element. * * @return This function should return values in the following range: * `left == right -> result == 0` * `left < right -> result < 0` * `left > right -> result > 0` */ typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right); /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Equality comparison functions */ /* ---------------------------------------------------------------------------------------------- */ /** * Declares a generic equality comparison function for an integral data-type. * * @param name The name of the function. * @param type The name of the integral data-type. */ #define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \ ZyanBool name(const type* left, const type* right) \ { \ ZYAN_ASSERT(left); \ ZYAN_ASSERT(right); \ \ return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \ } /** * Declares a generic equality comparison function that compares a single integral * data-type field of a struct. * * @param name The name of the function. * @param type The name of the integral data-type. * @param field_name The name of the struct field. */ #define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \ ZyanBool name(const type* left, const type* right) \ { \ ZYAN_ASSERT(left); \ ZYAN_ASSERT(right); \ \ return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \ } /* ---------------------------------------------------------------------------------------------- */ /* Comparison functions */ /* ---------------------------------------------------------------------------------------------- */ /** * Declares a generic comparison function for an integral data-type. * * @param name The name of the function. * @param type The name of the integral data-type. */ #define ZYAN_DECLARE_COMPARISON(name, type) \ ZyanI32 name(const type* left, const type* right) \ { \ ZYAN_ASSERT(left); \ ZYAN_ASSERT(right); \ \ if (*left < *right) \ { \ return -1; \ } \ if (*left > *right) \ { \ return 1; \ } \ return 0; \ } /** * Declares a generic comparison function that compares a single integral data-type field * of a struct. * * @param name The name of the function. * @param type The name of the integral data-type. * @param field_name The name of the struct field. */ #define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \ ZyanI32 name(const type* left, const type* right) \ { \ ZYAN_ASSERT(left); \ ZYAN_ASSERT(right); \ \ if (left->field_name < right->field_name) \ { \ return -1; \ } \ if (left->field_name > right->field_name) \ { \ return 1; \ } \ return 0; \ } /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Default equality comparison functions */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines a default equality comparison function for pointer values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const) /** * Defines a default equality comparison function for `ZyanBool` values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool) /** * Defines a default equality comparison function for 8-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8) /** * Defines a default equality comparison function for 16-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16) /** * Defines a default equality comparison function for 32-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32) /** * Defines a default equality comparison function for 64-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if * not. */ ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64) /* ---------------------------------------------------------------------------------------------- */ /* Default comparison functions */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines a default comparison function for pointer values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const) /** * Defines a default comparison function for `ZyanBool` values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool) /** * Defines a default comparison function for 8-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8) /** * Defines a default comparison function for 16-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16) /** * Defines a default comparison function for 32-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32) /** * Defines a default comparison function for 64-bit numeric values. * * @param left A pointer to the first value. * @param right A pointer to the second value. * * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is * less than the `right` one, or `1` if the `left` value is greater than the `right` one. */ ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYCORE_COMPARISON_H */ // // Header: Zycore/Object.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // - Zycore/String.h // - Zycore/Vector.h // /*************************************************************************************************** Zyan Core Library (Zycore-C) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Defines some generic object-related datatypes. */ #ifndef ZYCORE_OBJECT_H #define ZYCORE_OBJECT_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZyanMemberProcedure` function prototype. * * @param object A pointer to the object. */ typedef void (*ZyanMemberProcedure)(void* object); /** * Defines the `ZyanConstMemberProcedure` function prototype. * * @param object A pointer to the object. */ typedef void (*ZyanConstMemberProcedure)(const void* object); /** * Defines the `ZyanMemberFunction` function prototype. * * @param object A pointer to the object. * * @return A zyan status code. */ typedef ZyanStatus (*ZyanMemberFunction)(void* object); /** * Defines the `ZyanConstMemberFunction` function prototype. * * @param object A pointer to the object. * * @return A zyan status code. */ typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object); /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYCORE_OBJECT_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Constants */ /* ============================================================================================== */ /** * The initial minimum capacity (number of elements) for all dynamically allocated vector * instances. */ #define ZYAN_VECTOR_MIN_CAPACITY 1 /** * The default growth factor for all vector instances. */ #define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2 /** * The default shrink threshold for all vector instances. */ #define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 4 /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZyanVector` struct. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZyanVector_ { /** * The memory allocator. */ ZyanAllocator* allocator; /** * The growth factor. */ ZyanU8 growth_factor; /** * The shrink threshold. */ ZyanU8 shrink_threshold; /** * The current number of elements in the vector. */ ZyanUSize size; /** * The maximum capacity (number of elements). */ ZyanUSize capacity; /** * The size of a single element in bytes. */ ZyanUSize element_size; /** * The element destructor callback. */ ZyanMemberProcedure destructor; /** * The data pointer. */ void* data; } ZyanVector; /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* General */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines an uninitialized `ZyanVector` instance. */ #define ZYAN_VECTOR_INITIALIZER \ { \ /* allocator */ ZYAN_NULL, \ /* growth_factor */ 0, \ /* shrink_threshold */ 0, \ /* size */ 0, \ /* capacity */ 0, \ /* element_size */ 0, \ /* destructor */ ZYAN_NULL, \ /* data */ ZYAN_NULL \ } /* ---------------------------------------------------------------------------------------------- */ /* Helper macros */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the value of the element at the given `index`. * * @param type The desired value type. * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * * @result The value of the desired element in the vector. * * Note that this function is unsafe and might dereference a null-pointer. */ #ifdef __cplusplus #define ZYAN_VECTOR_GET(type, vector, index) \ (*reinterpret_cast(ZyanVectorGet(vector, index))) #else #define ZYAN_VECTOR_GET(type, vector, index) \ (*(const type*)ZyanVectorGet(vector, index)) #endif /** * Loops through all elements of the vector. * * @param type The desired value type. * @param vector A pointer to the `ZyanVector` instance. * @param item_name The name of the iterator item. * @param body The body to execute for each item in the vector. */ #define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \ { \ const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ { \ const type item_name = ZYAN_VECTOR_GET(type, vector, \ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ body \ } \ } /** * Loops through all elements of the vector. * * @param type The desired value type. * @param vector A pointer to the `ZyanVector` instance. * @param item_name The name of the iterator item. * @param body The body to execute for each item in the vector. */ #define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \ { \ const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ { \ type* const item_name = ZyanVectorGetMutable(vector, \ ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ body \ } \ } /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constructor and destructor */ /* ---------------------------------------------------------------------------------------------- */ #ifndef ZYAN_NO_LIBC /** * Initializes the given `ZyanVector` instance. * * @param vector A pointer to the `ZyanVector` instance. * @param element_size The size of a single element in bytes. * @param capacity The initial capacity (number of elements). * @param destructor A destructor callback that is invoked every time an item is deleted, or * `ZYAN_NULL` if not needed. * * @return A zyan status code. * * The memory for the vector elements is dynamically allocated by the default allocator using the * default growth factor and the default shrink threshold. * * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor); #endif // ZYAN_NO_LIBC /** * Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory * allocation/deallocation parameters. * * @param vector A pointer to the `ZyanVector` instance. * @param element_size The size of a single element in bytes. * @param capacity The initial capacity (number of elements). * @param destructor A destructor callback that is invoked every time an item is deleted, * or `ZYAN_NULL` if not needed. * @param allocator A pointer to a `ZyanAllocator` instance. * @param growth_factor The growth factor. * @param shrink_threshold The shrink threshold. * * @return A zyan status code. * * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables * dynamic shrinking. * * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); /** * Initializes the given `ZyanVector` instance and configures it to use a custom user * defined buffer with a fixed size. * * @param vector A pointer to the `ZyanVector` instance. * @param element_size The size of a single element in bytes. * @param buffer A pointer to the buffer that is used as storage for the elements. * @param capacity The maximum capacity (number of elements) of the buffer. * @param destructor A destructor callback that is invoked every time an item is deleted, or * `ZYAN_NULL` if not needed. * * @return A zyan status code. * * Finalization is not required for instances created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size, void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor); /** * Destroys the given `ZyanVector` instance. * * @param vector A pointer to the `ZyanVector` instance.. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector); /* ---------------------------------------------------------------------------------------------- */ /* Duplication */ /* ---------------------------------------------------------------------------------------------- */ #ifndef ZYAN_NO_LIBC /** * Initializes a new `ZyanVector` instance by duplicating an existing vector. * * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. * @param source A pointer to the source vector. * @param capacity The initial capacity (number of elements). * * This value is automatically adjusted to the size of the source vector, if * a smaller value was passed. * * @return A zyan status code. * * The memory for the vector is dynamically allocated by the default allocator using the default * growth factor and the default shrink threshold. * * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, const ZyanVector* source, ZyanUSize capacity); #endif // ZYAN_NO_LIBC /** * Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a * custom `allocator` and memory allocation/deallocation parameters. * * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. * @param source A pointer to the source vector. * @param capacity The initial capacity (number of elements). * This value is automatically adjusted to the size of the source * vector, if a smaller value was passed. * @param allocator A pointer to a `ZyanAllocator` instance. * @param growth_factor The growth factor. * @param shrink_threshold The shrink threshold. * * @return A zyan status code. * * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables * dynamic shrinking. * * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); /** * Initializes a new `ZyanVector` instance by duplicating an existing vector and * configures it to use a custom user defined buffer with a fixed size. * * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. * @param source A pointer to the source vector. * @param buffer A pointer to the buffer that is used as storage for the elements. * @param capacity The maximum capacity (number of elements) of the buffer. * This function will fail, if the capacity of the buffer is less than the * size of the source vector. * * @return A zyan status code. * * Finalization is not required for instances created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, const ZyanVector* source, void* buffer, ZyanUSize capacity); /* ---------------------------------------------------------------------------------------------- */ /* Element access */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns a constant pointer to the element at the given `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * * @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error * occurred. * * Note that the returned pointer might get invalid when the vector is resized by either a manual * call to the memory-management functions or implicitly by inserting or removing elements. * * Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status * code. */ ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index); /** * Returns a mutable pointer to the element at the given `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * * @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error * occurred. * * Note that the returned pointer might get invalid when the vector is resized by either a manual * call to the memory-management functions or implicitly by inserting or removing elements. * * Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a * zyan status code. */ ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index); /** * Returns a constant pointer to the element at the given `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * @param value Receives a constant pointer to the desired element in the vector. * * Note that the returned pointer might get invalid when the vector is resized by either a manual * call to the memory-management functions or implicitly by inserting or removing elements. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, const void** value); /** * Returns a mutable pointer to the element at the given `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * @param value Receives a mutable pointer to the desired element in the vector. * * Note that the returned pointer might get invalid when the vector is resized by either a manual * call to the memory-management functions or implicitly by inserting or removing elements. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, void** value); /** * Assigns a new value to the element at the given `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The value index. * @param value The value to assign. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, const void* value); /* ---------------------------------------------------------------------------------------------- */ /* Insertion */ /* ---------------------------------------------------------------------------------------------- */ /** * Adds a new `element` to the end of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param element A pointer to the element to add. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element); /** * Inserts an `element` at the given `index` of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param index The insert index. * @param element A pointer to the element to insert. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, const void* element); /** * Inserts multiple `elements` at the given `index` of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param index The insert index. * @param elements A pointer to the first element. * @param count The number of elements to insert. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, const void* elements, ZyanUSize count); /** * Constructs an `element` in-place at the end of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param element Receives a pointer to the new element. * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in * undefined state, if no constructor was passed. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, ZyanMemberFunction constructor); /** * Constructs an `element` in-place and inserts it at the given `index` of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param index The insert index. * @param element Receives a pointer to the new element. * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in * undefined state, if no constructor was passed. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, void** element, ZyanMemberFunction constructor); /* ---------------------------------------------------------------------------------------------- */ /* Utils */ /* ---------------------------------------------------------------------------------------------- */ /** * Swaps the element at `index_first` with the element at `index_second`. * * @param vector A pointer to the `ZyanVector` instance. * @param index_first The index of the first element. * @param index_second The index of the second element. * * @return A zyan status code. * * This function requires the vector to have spare capacity for one temporary element. Call * `ZyanVectorReserve` before this function to increase capacity, if needed. */ ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, ZyanUSize index_second); /* ---------------------------------------------------------------------------------------------- */ /* Deletion */ /* ---------------------------------------------------------------------------------------------- */ /** * Deletes the element at the given `index` of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param index The element index. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index); /** * Deletes multiple elements from the given vector, starting at `index`. * * @param vector A pointer to the `ZyanVector` instance. * @param index The index of the first element to delete. * @param count The number of elements to delete. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, ZyanUSize count); /** * Removes the last element of the vector. * * @param vector A pointer to the `ZyanVector` instance. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector); /** * Erases all elements of the given vector. * * @param vector A pointer to the `ZyanVector` instance. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector); /* ---------------------------------------------------------------------------------------------- */ /* Searching */ /* ---------------------------------------------------------------------------------------------- */ /** * Sequentially searches for the first occurrence of `element` in the given vector. * * @param vector A pointer to the `ZyanVector` instance. * @param element A pointer to the element to search for. * @param found_index A pointer to a variable that receives the index of the found element. * @param comparison The comparison function to use. * * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic * zyan status code if an error occurred. * * The `found_index` is set to `-1`, if the element was not found. */ ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, ZyanISize* found_index, ZyanEqualityComparison comparison); /** * Sequentially searches for the first occurrence of `element` in the given vector. * * @param vector A pointer to the `ZyanVector` instance. * @param element A pointer to the element to search for. * @param found_index A pointer to a variable that receives the index of the found element. * @param comparison The comparison function to use. * @param index The start index. * @param count The maximum number of elements to iterate, beginning from the start `index`. * * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic * zyan status code if an error occurred. * * The `found_index` is set to `-1`, if the element was not found. */ ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count); /** * Searches for the first occurrence of `element` in the given vector using a binary- * search algorithm. * * @param vector A pointer to the `ZyanVector` instance. * @param element A pointer to the element to search for. * @param found_index A pointer to a variable that receives the index of the found element. * @param comparison The comparison function to use. * * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic * zyan status code if an error occurred. * * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` * contains the index of the first entry larger than `element`. * * This function requires all elements in the vector to be strictly ordered (sorted). */ ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element, ZyanUSize* found_index, ZyanComparison comparison); /** * Searches for the first occurrence of `element` in the given vector using a binary- * search algorithm. * * @param vector A pointer to the `ZyanVector` instance. * @param element A pointer to the element to search for. * @param found_index A pointer to a variable that receives the index of the found element. * @param comparison The comparison function to use. * @param index The start index. * @param count The maximum number of elements to iterate, beginning from the start `index`. * * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic * zyan status code if an error occurred. * * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` * contains the index of the first entry larger than `element`. * * This function requires all elements in the vector to be strictly ordered (sorted). */ ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element, ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count); /* ---------------------------------------------------------------------------------------------- */ /* Memory management */ /* ---------------------------------------------------------------------------------------------- */ /** * Resizes the given `ZyanVector` instance. * * @param vector A pointer to the `ZyanVector` instance. * @param size The new size of the vector. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size); /** * Resizes the given `ZyanVector` instance. * * @param vector A pointer to the `ZyanVector` instance. * @param size The new size of the vector. * @param initializer A pointer to a value to be used as initializer for new items. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, const void* initializer); /** * Changes the capacity of the given `ZyanVector` instance. * * @param vector A pointer to the `ZyanVector` instance. * @param capacity The new minimum capacity of the vector. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity); /** * Shrinks the capacity of the given vector to match it's size. * * @param vector A pointer to the `ZyanVector` instance. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector); /* ---------------------------------------------------------------------------------------------- */ /* Information */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the current capacity of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param capacity Receives the size of the vector. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity); /** * Returns the current size of the vector. * * @param vector A pointer to the `ZyanVector` instance. * @param size Receives the size of the vector. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size); /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYCORE_VECTOR_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Constants */ /* ============================================================================================== */ /** * The initial minimum capacity (number of characters) for all dynamically allocated * string instances - not including the terminating '\0'-character. */ #define ZYAN_STRING_MIN_CAPACITY 32 /** * The default growth factor for all string instances. */ #define ZYAN_STRING_DEFAULT_GROWTH_FACTOR 2 /** * The default shrink threshold for all string instances. */ #define ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD 4 /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* String flags */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZyanStringFlags` data-type. */ typedef ZyanU8 ZyanStringFlags; /** * The string uses a custom user-defined buffer with a fixed capacity. */ #define ZYAN_STRING_HAS_FIXED_CAPACITY 0x01 // (1 << 0) /* ---------------------------------------------------------------------------------------------- */ /* String */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZyanString` struct. * * The `ZyanString` type is implemented as a size-prefixed string - which allows for a lot of * performance optimizations. * Nevertheless null-termination is guaranteed at all times to provide maximum compatibility with * default C-style strings (use `ZyanStringGetData` to access the C-style string). * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZyanString_ { /** * String flags. */ ZyanStringFlags flags; /** * The vector that contains the actual string. */ ZyanVector vector; } ZyanString; /* ---------------------------------------------------------------------------------------------- */ /* View */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZyanStringView` struct. * * The `ZyanStringView` type provides a view inside a string (`ZyanString` instances, null- * terminated C-style strings, or even not-null-terminated custom strings). A view is immutable * by design and can't be directly converted to a C-style string. * * Views might become invalid (e.g. pointing to invalid memory), if the underlying string gets * destroyed or resized. * * The `ZYAN_STRING_TO_VIEW` macro can be used to cast a `ZyanString` to a `ZyanStringView` pointer * without any runtime overhead. * Casting a view to a normal string is not supported and will lead to unexpected behavior (use * `ZyanStringDuplicate` to create a deep-copy instead). * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZyanStringView_ { /** * The string data. * * The view internally re-uses the normal string struct to allow casts without any runtime * overhead. */ ZyanString string; } ZyanStringView; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* General */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines an uninitialized `ZyanString` instance. */ #define ZYAN_STRING_INITIALIZER \ { \ /* flags */ 0, \ /* vector */ ZYAN_VECTOR_INITIALIZER \ } /* ---------------------------------------------------------------------------------------------- */ /* Helper macros */ /* ---------------------------------------------------------------------------------------------- */ /** * Casts a `ZyanString` pointer to a constant `ZyanStringView` pointer. */ #define ZYAN_STRING_TO_VIEW(string) (const ZyanStringView*)(string) /** * Defines a `ZyanStringView` struct that provides a view into a static C-style string. * * @param string The C-style string. */ #define ZYAN_DEFINE_STRING_VIEW(string) \ { \ /* string */ \ { \ /* flags */ 0, \ /* vector */ \ { \ /* allocator */ ZYAN_NULL, \ /* growth_factor */ 1, \ /* shrink_threshold */ 0, \ /* size */ sizeof(string), \ /* capacity */ sizeof(string), \ /* element_size */ sizeof(char), \ /* destructor */ ZYAN_NULL, \ /* data */ (char*)(string) \ } \ } \ } /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constructor and destructor */ /* ---------------------------------------------------------------------------------------------- */ #ifndef ZYAN_NO_LIBC /** * Initializes the given `ZyanString` instance. * * @param string A pointer to the `ZyanString` instance. * @param capacity The initial capacity (number of characters). * * @return A zyan status code. * * The memory for the string is dynamically allocated by the default allocator using the default * growth factor and the default shrink threshold. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity); #endif // ZYAN_NO_LIBC /** * Initializes the given `ZyanString` instance and sets a custom `allocator` and memory * allocation/deallocation parameters. * * @param string A pointer to the `ZyanString` instance. * @param capacity The initial capacity (number of characters). * @param allocator A pointer to a `ZyanAllocator` instance. * @param growth_factor The growth factor. * @param shrink_threshold The shrink threshold. * * @return A zyan status code. * * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables * dynamic shrinking. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); /** * Initializes the given `ZyanString` instance and configures it to use a custom user * defined buffer with a fixed size. * * @param string A pointer to the `ZyanString` instance. * @param buffer A pointer to the buffer that is used as storage for the string. * @param capacity The maximum capacity (number of characters) of the buffer, including * the terminating '\0'. * * @return A zyan status code. * * Finalization is not required for strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer, ZyanUSize capacity); /** * Destroys the given `ZyanString` instance. * * @param string A pointer to the `ZyanString` instance. * * @return A zyan status code. * */ ZYCORE_EXPORT ZyanStatus ZyanStringDestroy(ZyanString* string); /* ---------------------------------------------------------------------------------------------- */ /* Duplication */ /* ---------------------------------------------------------------------------------------------- */ #ifndef ZYAN_NO_LIBC /** * Initializes a new `ZyanString` instance by duplicating an existing string. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * @param source A pointer to the source string. * @param capacity The initial capacity (number of characters). * * This value is automatically adjusted to the size of the source string, if * a smaller value was passed. * * @return A zyan status code. * * The behavior of this function is undefined, if `source` is a view into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * The memory for the string is dynamically allocated by the default allocator using the default * growth factor and the default shrink threshold. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringDuplicate(ZyanString* destination, const ZyanStringView* source, ZyanUSize capacity); #endif // ZYAN_NO_LIBC /** * Initializes a new `ZyanString` instance by duplicating an existing string and sets a * custom `allocator` and memory allocation/deallocation parameters. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * @param source A pointer to the source string. * @param capacity The initial capacity (number of characters). * This value is automatically adjusted to the size of the source * string, if a smaller value was passed. * @param allocator A pointer to a `ZyanAllocator` instance. * @param growth_factor The growth factor. * @param shrink_threshold The shrink threshold. * * @return A zyan status code. * * The behavior of this function is undefined, if `source` is a view into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables * dynamic shrinking. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateEx(ZyanString* destination, const ZyanStringView* source, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); /** * Initializes a new `ZyanString` instance by duplicating an existing string and * configures it to use a custom user defined buffer with a fixed size. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * @param source A pointer to the source string. * @param buffer A pointer to the buffer that is used as storage for the string. * @param capacity The maximum capacity (number of characters) of the buffer, including the * terminating '\0'. * This function will fail, if the capacity of the buffer is less or equal to * the size of the source string. * * @return A zyan status code. * * The behavior of this function is undefined, if `source` is a view into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * Finalization is not required for strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination, const ZyanStringView* source, char* buffer, ZyanUSize capacity); /* ---------------------------------------------------------------------------------------------- */ /* Concatenation */ /* ---------------------------------------------------------------------------------------------- */ #ifndef ZYAN_NO_LIBC /** * Initializes a new `ZyanString` instance by concatenating two existing strings. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * * This function will fail, if the destination `ZyanString` instance equals * one of the source strings. * @param s1 A pointer to the first source string. * @param s2 A pointer to the second source string. * @param capacity The initial capacity (number of characters). * This value is automatically adjusted to the combined size of the source * strings, if a smaller value was passed. * * @return A zyan status code. * * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * The memory for the string is dynamically allocated by the default allocator using the default * growth factor and the default shrink threshold. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringConcat(ZyanString* destination, const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity); #endif // ZYAN_NO_LIBC /** * Initializes a new `ZyanString` instance by concatenating two existing strings and sets * a custom `allocator` and memory allocation/deallocation parameters. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * * This function will fail, if the destination `ZyanString` instance * equals one of the source strings. * @param s1 A pointer to the first source string. * @param s2 A pointer to the second source string. * @param capacity The initial capacity (number of characters). * * This value is automatically adjusted to the combined size of the * source strings, if a smaller value was passed. * @param allocator A pointer to a `ZyanAllocator` instance. * @param growth_factor The growth factor. * @param shrink_threshold The shrink threshold. * * @return A zyan status code. * * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables * dynamic shrinking. * * The allocated buffer will be at least one character larger than the given `capacity`, to reserve * space for the terminating '\0'. * * Finalization with `ZyanStringDestroy` is required for all strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold); /** * Initializes a new `ZyanString` instance by concatenating two existing strings and * configures it to use a custom user defined buffer with a fixed size. * * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. * * This function will fail, if the destination `ZyanString` instance equals * one of the source strings. * @param s1 A pointer to the first source string. * @param s2 A pointer to the second source string. * @param buffer A pointer to the buffer that is used as storage for the string. * @param capacity The maximum capacity (number of characters) of the buffer. * * This function will fail, if the capacity of the buffer is less or equal to * the combined size of the source strings. * * @return A zyan status code. * * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` * string or `destination` points to an already initialized `ZyanString` instance. * * Finalization is not required for strings created by this function. */ ZYCORE_EXPORT ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination, const ZyanStringView* s1, const ZyanStringView* s2, char* buffer, ZyanUSize capacity); /* ---------------------------------------------------------------------------------------------- */ /* Views */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns a view inside an existing view/string. * * @param view A pointer to the `ZyanStringView` instance. * @param source A pointer to the source string. * * @return A zyan status code. * * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the * `source` string. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideView(ZyanStringView* view, const ZyanStringView* source); /** * Returns a view inside an existing view/string starting from the given `index`. * * @param view A pointer to the `ZyanStringView` instance. * @param source A pointer to the source string. * @param index The start index. * @param count The number of characters. * * @return A zyan status code. * * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the * `source` string. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view, const ZyanStringView* source, ZyanUSize index, ZyanUSize count); /** * Returns a view inside a null-terminated C-style string. * * @param view A pointer to the `ZyanStringView` instance. * @param string The C-style string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string); /** * Returns a view inside a character buffer with custom length. * * @param view A pointer to the `ZyanStringView` instance. * @param buffer A pointer to the buffer containing the string characters. * @param length The length of the string (number of characters). * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer, ZyanUSize length); /** * Returns the size (number of characters) of the view. * * @param view A pointer to the `ZyanStringView` instance. * @param size Receives the size (number of characters) of the view. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size); /** * Returns the C-style string of the given `ZyanString` instance. * * @warning The string is not guaranteed to be null terminated! * * @param view A pointer to the `ZyanStringView` instance. * @param buffer Receives a pointer to the C-style string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer); /* ---------------------------------------------------------------------------------------------- */ /* Character access */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the character at the given `index`. * * @param string A pointer to the `ZyanStringView` instance. * @param index The character index. * @param value Receives the desired character of the string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index, char* value); /** * Returns a pointer to the character at the given `index`. * * @param string A pointer to the `ZyanString` instance. * @param index The character index. * @param value Receives a pointer to the desired character in the string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index, char** value); /** * Assigns a new value to the character at the given `index`. * * @param string A pointer to the `ZyanString` instance. * @param index The character index. * @param value The character to assign. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value); /* ---------------------------------------------------------------------------------------------- */ /* Insertion */ /* ---------------------------------------------------------------------------------------------- */ /** * Inserts the content of the source string in the destination string at the given `index`. * * @param destination The destination string. * @param index The insert index. * @param source The source string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index, const ZyanStringView* source); /** * Inserts `count` characters of the source string in the destination string at the given * `index`. * * @param destination The destination string. * @param destination_index The insert index. * @param source The source string. * @param source_index The index of the first character to be inserted from the source * string. * @param count The number of chars to insert from the source string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index, const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count); /* ---------------------------------------------------------------------------------------------- */ /* Appending */ /* ---------------------------------------------------------------------------------------------- */ /** * Appends the content of the source string to the end of the destination string. * * @param destination The destination string. * @param source The source string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source); /** * Appends `count` characters of the source string to the end of the destination string. * * @param destination The destination string. * @param source The source string. * @param source_index The index of the first character to be appended from the source string. * @param count The number of chars to append from the source string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count); /* ---------------------------------------------------------------------------------------------- */ /* Deletion */ /* ---------------------------------------------------------------------------------------------- */ /** * Deletes characters from the given string, starting at `index`. * * @param string A pointer to the `ZyanString` instance. * @param index The index of the first character to delete. * @param count The number of characters to delete. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count); /** * Deletes all remaining characters from the given string, starting at `index`. * * @param string A pointer to the `ZyanString` instance. * @param index The index of the first character to delete. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index); /** * Erases the given string. * * @param string A pointer to the `ZyanString` instance. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringClear(ZyanString* string); /* ---------------------------------------------------------------------------------------------- */ /* Searching */ /* ---------------------------------------------------------------------------------------------- */ /** * Searches for the first occurrence of `needle` in the given `haystack` starting from the * left. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occured. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringLPos(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index); /** * Searches for the first occurrence of `needle` in the given `haystack` starting from the * left. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * @param index The start index. * @param count The maximum number of characters to iterate, beginning from the start * `index`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occured. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); /** * Performs a case-insensitive search for the first occurrence of `needle` in the given * `haystack` starting from the left. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occured. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index); /** * Performs a case-insensitive search for the first occurrence of `needle` in the given * `haystack` starting from the left. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * @param index The start index. * @param count The maximum number of characters to iterate, beginning from the start * `index`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); /** * Searches for the first occurrence of `needle` in the given `haystack` starting from the * right. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringRPos(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index); /** * Searches for the first occurrence of `needle` in the given `haystack` starting from the * right. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * @param index The start index. * @param count The maximum number of characters to iterate, beginning from the start * `index`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); /** * Performs a case-insensitive search for the first occurrence of `needle` in the given * `haystack` starting from the right. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index); /** * Performs a case-insensitive search for the first occurrence of `needle` in the given * `haystack` starting from the right. * * @param haystack The string to search in. * @param needle The sub-string to search for. * @param found_index A pointer to a variable that receives the index of the first occurrence of * `needle`. * @param index The start index. * @param count The maximum number of characters to iterate, beginning from the start * `index`. * * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. * * The `found_index` is set to `-1`, if the needle was not found. */ ZYCORE_EXPORT ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack, const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); /* ---------------------------------------------------------------------------------------------- */ /* Comparing */ /* ---------------------------------------------------------------------------------------------- */ /** * Compares two strings. * * @param s1 The first string * @param s2 The second string. * @param result Receives the comparison result. * * Values: * - `result < 0` -> The first character that does not match has a lower value * in `s1` than in `s2`. * - `result == 0` -> The contents of both strings are equal. * - `result > 0` -> The first character that does not match has a greater value * in `s1` than in `s2`. * * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. */ ZYCORE_EXPORT ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2, ZyanI32* result); /** * Performs a case-insensitive comparison of two strings. * * @param s1 The first string * @param s2 The second string. * @param result Receives the comparison result. * * Values: * - `result < 0` -> The first character that does not match has a lower value * in `s1` than in `s2`. * - `result == 0` -> The contents of both strings are equal. * - `result > 0` -> The first character that does not match has a greater value * in `s1` than in `s2`. * * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another * zyan status code, if an error occurred. */ ZYCORE_EXPORT ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2, ZyanI32* result); /* ---------------------------------------------------------------------------------------------- */ /* Case conversion */ /* ---------------------------------------------------------------------------------------------- */ /** * Converts the given string to lowercase letters. * * @param string A pointer to the `ZyanString` instance. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCase(ZyanString* string); /** * Converts `count` characters of the given string to lowercase letters. * * @param string A pointer to the `ZyanString` instance. * @param index The start index. * @param count The number of characters to convert, beginning from the start `index`. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index, ZyanUSize count); /** * Converts the given string to uppercase letters. * * @param string A pointer to the `ZyanString` instance. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCase(ZyanString* string); /** * Converts `count` characters of the given string to uppercase letters. * * @param string A pointer to the `ZyanString` instance. * @param index The start index. * @param count The number of characters to convert, beginning from the start `index`. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index, ZyanUSize count); /* ---------------------------------------------------------------------------------------------- */ /* Memory management */ /* ---------------------------------------------------------------------------------------------- */ /** * Resizes the given `ZyanString` instance. * * @param string A pointer to the `ZyanString` instance. * @param size The new size of the string. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size); /** * Changes the capacity of the given `ZyanString` instance. * * @param string A pointer to the `ZyanString` instance. * @param capacity The new minimum capacity of the string. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity); /** * Shrinks the capacity of the given string to match it's size. * * @param string A pointer to the `ZyanString` instance. * * @return A zyan status code. * * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified * `ZyanString` instance. */ ZYCORE_EXPORT ZyanStatus ZyanStringShrinkToFit(ZyanString* string); /* ---------------------------------------------------------------------------------------------- */ /* Information */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the current capacity of the string. * * @param string A pointer to the `ZyanString` instance. * @param capacity Receives the size of the string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity); /** * Returns the current size (number of characters) of the string (excluding the * terminating zero character). * * @param string A pointer to the `ZyanString` instance. * @param size Receives the size (number of characters) of the string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size); /** * Returns the C-style string of the given `ZyanString` instance. * * @param string A pointer to the `ZyanString` instance. * @param value Receives a pointer to the C-style string. * * @return A zyan status code. */ ZYCORE_EXPORT ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value); /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif // ZYCORE_STRING_H // // Header: Zydis/FormatterBuffer.h // // Include stack: // - Zydis/Zydis.h // - Zydis/Formatter.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Implements the `ZydisFormatterToken` type and provides functions to use it. */ #ifndef ZYDIS_FORMATTER_TOKEN_H #define ZYDIS_FORMATTER_TOKEN_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Constants */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Token types */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisTokenType` data-type. */ typedef ZyanU8 ZydisTokenType; #define ZYDIS_TOKEN_INVALID 0x00 /** * A whitespace character. */ #define ZYDIS_TOKEN_WHITESPACE 0x01 /** * A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`). */ #define ZYDIS_TOKEN_DELIMITER 0x02 /** * An opening parenthesis character (like `'('`, `'['`, `'{'`). */ #define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03 /** * A closing parenthesis character (like `')'`, `']'`, `'}'`). */ #define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04 /** * A prefix literal (like `"LOCK"`, `"REP"`). */ #define ZYDIS_TOKEN_PREFIX 0x05 /** * A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`). */ #define ZYDIS_TOKEN_MNEMONIC 0x06 /** * A register literal (like `"RAX"`, `"DS"`, `"%ECX"`). */ #define ZYDIS_TOKEN_REGISTER 0x07 /** * An absolute address literal (like `0x00400000`). */ #define ZYDIS_TOKEN_ADDRESS_ABS 0x08 /** * A relative address literal (like `-0x100`). */ #define ZYDIS_TOKEN_ADDRESS_REL 0x09 /** * A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`). */ #define ZYDIS_TOKEN_DISPLACEMENT 0x0A /** * An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`). */ #define ZYDIS_TOKEN_IMMEDIATE 0x0B /** * A typecast literal (like `DWORD PTR`). */ #define ZYDIS_TOKEN_TYPECAST 0x0C /** * A decorator literal (like `"Z"`, `"1TO4"`). */ #define ZYDIS_TOKEN_DECORATOR 0x0D /** * A symbol literal. */ #define ZYDIS_TOKEN_SYMBOL 0x0E /** * The base for user-defined token types. */ #define ZYDIS_TOKEN_USER 0x80 /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Token */ /* ---------------------------------------------------------------------------------------------- */ #pragma pack(push, 1) /** * Defines the `ZydisFormatterToken` struct. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. */ typedef struct ZydisFormatterToken_ { /** * The token type. */ ZydisTokenType type; /** * An offset to the next token, or `0`. */ ZyanU8 next; } ZydisFormatterToken; #pragma pack(pop) /** * Defines the `ZydisFormatterTokenConst` data-type. */ typedef const ZydisFormatterToken ZydisFormatterTokenConst; /* ---------------------------------------------------------------------------------------------- */ /* Buffer */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisFormatterBuffer` struct. * * All fields in this struct should be considered as "private". Any changes may * lead to unexpected behavior. */ typedef struct ZydisFormatterBuffer_ { /** * `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it * contains a simple string. */ ZyanBool is_token_list; /** * The remaining capacity of the buffer. */ ZyanUSize capacity; /** * The `ZyanString` instance that refers to the literal value of the most * recently added token. */ ZyanString string; } ZydisFormatterBuffer; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Token */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the `type` and the string `value` of the given `token`. * * @param token A pointer to the `ZydisFormatterToken` struct. * @param type Receives the token type. * @param value Receives a pointer to the string value of the token. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, ZydisTokenType* type, ZyanConstCharPointer* value); /** * Obtains the next `token` linked to the passed one. * * @param token Receives a pointer to the next `ZydisFormatterToken` struct * linked to the passed one. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token); /* ---------------------------------------------------------------------------------------------- */ /* Buffer */ /* ---------------------------------------------------------------------------------------------- */ /** * Returns the current (most recently added) token. * * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param token Receives a pointer to the current token. * * @return A zyan status code. * * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least * one token. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, ZydisFormatterTokenConst** token); /** * Returns the `ZyanString` instance associated with the given buffer. * * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param string Receives a pointer to the `ZyanString` instance associated with the given * buffer. * * @return A zyan status code. * * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least * one token. * * The returned string always refers to the literal value of the current (most recently added) * token and will remain valid until the buffer is destroyed. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, ZyanString** string); /** * Appends a new token to the `buffer`. * * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param type The type of the new token. * * @return A zyan status code. * * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will * automatically be updated by calling this function. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, ZydisTokenType type); /** * Returns a snapshot of the buffer-state. * * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param state Receives a snapshot of the buffer-state. * * @return A zyan status code. * * Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon * as the buffer gets overwritten or destroyed. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, ZyanUPointer* state); /** * Restores a previously saved buffer-state. * * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param state The buffer-state to restore. * * @return A zyan status code. * * All tokens added after obtaining the given `state` snapshot will be removed. This function * does NOT restore any string content. * * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will * automatically be updated by calling this function. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointer state); /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_FORMATTER_TOKEN_H */ #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Constants */ /* ============================================================================================== */ /** * Use this constant as value for `runtime_address` in `ZydisFormatterFormatInstruction(Ex)` * or `ZydisFormatterFormatOperand(Ex)` to print relative values for all addresses. */ #define ZYDIS_RUNTIME_ADDRESS_NONE (ZyanU64)(-1) /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Formatter style */ /* ---------------------------------------------------------------------------------------------- */ /** * Enum selecting the syntax to format the disassembly in. */ typedef enum ZydisFormatterStyle_ { /** * Generates `AT&T`-style disassembly. */ ZYDIS_FORMATTER_STYLE_ATT, /** * Generates `Intel`-style disassembly. */ ZYDIS_FORMATTER_STYLE_INTEL, /** * Generates `MASM`-style disassembly that is directly accepted as input for * the `MASM` assembler. * * The runtime-address is ignored in this mode. */ ZYDIS_FORMATTER_STYLE_INTEL_MASM, /** * Maximum value of this enum. */ ZYDIS_FORMATTER_STYLE_MAX_VALUE = ZYDIS_FORMATTER_STYLE_INTEL_MASM, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_FORMATTER_STYLE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_STYLE_MAX_VALUE) } ZydisFormatterStyle; /* ---------------------------------------------------------------------------------------------- */ /* Properties */ /* ---------------------------------------------------------------------------------------------- */ /** * Enum selecting a property of the formatter. */ typedef enum ZydisFormatterProperty_ { /* ---------------------------------------------------------------------------------------- */ /* General */ /* ---------------------------------------------------------------------------------------- */ /** * Controls the printing of effective operand-size suffixes (`AT&T`) or operand-sizes * of memory operands (`INTEL`). * * Pass `ZYAN_TRUE` as value to force the formatter to always print the size, or `ZYAN_FALSE` * to only print it if needed. */ ZYDIS_FORMATTER_PROP_FORCE_SIZE, /** * Controls the printing of segment prefixes. * * Pass `ZYAN_TRUE` as value to force the formatter to always print the segment register of * memory-operands or `ZYAN_FALSE` to omit implicit `DS`/`SS` segments. */ ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, /** * Controls the printing of the scale-factor component for memory operands. * * Pass `ZYAN_TRUE` as value to force the formatter to always print the scale-factor component * of memory operands or `ZYAN_FALSE` to omit the scale factor for values of `1`. */ ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE, /** * Controls the printing of branch addresses. * * Pass `ZYAN_TRUE` as value to force the formatter to always print relative branch addresses * or `ZYAN_FALSE` to use absolute addresses, if a runtime-address different to * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. */ ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES, /** * Controls the printing of `EIP`/`RIP`-relative addresses. * * Pass `ZYAN_TRUE` as value to force the formatter to always print relative addresses for * `EIP`/`RIP`-relative operands or `ZYAN_FALSE` to use absolute addresses, if a runtime- * address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. */ ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL, /** * Controls the printing of branch-instructions sizes. * * Pass `ZYAN_TRUE` as value to print the size (`short`, `near`) of branch * instructions or `ZYAN_FALSE` to hide it. * * Note that the `far`/`l` modifier is always printed. */ ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE, /** * Controls the printing of instruction prefixes. * * Pass `ZYAN_TRUE` as value to print all instruction-prefixes (even ignored or duplicate * ones) or `ZYAN_FALSE` to only print prefixes that are effectively used by the instruction. */ ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES, /* ---------------------------------------------------------------------------------------- */ /* Numeric values */ /* ---------------------------------------------------------------------------------------- */ /** * Controls the base of address values. */ ZYDIS_FORMATTER_PROP_ADDR_BASE, /** * Controls the signedness of relative addresses. Absolute addresses are * always unsigned. */ ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS, /** * Controls the padding of absolute address values. * * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to pad all * addresses to the current address width (hexadecimal only), or any other integer value for * custom padding. */ ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE, /** * Controls the padding of relative address values. * * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to pad all * addresses to the current address width (hexadecimal only), or any other integer value for * custom padding. */ ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE, /* ---------------------------------------------------------------------------------------- */ /** * Controls the base of displacement values. */ ZYDIS_FORMATTER_PROP_DISP_BASE, /** * Controls the signedness of displacement values. */ ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS, /** * Controls the padding of displacement values. * * Pass `ZYDIS_PADDING_DISABLED` to disable padding, or any other integer value for custom * padding. */ ZYDIS_FORMATTER_PROP_DISP_PADDING, /* ---------------------------------------------------------------------------------------- */ /** * Controls the base of immediate values. */ ZYDIS_FORMATTER_PROP_IMM_BASE, /** * Controls the signedness of immediate values. * * Pass `ZYDIS_SIGNEDNESS_AUTO` to automatically choose the most suitable mode based on the * operands `ZydisDecodedOperand.imm.is_signed` attribute. */ ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS, /** * Controls the padding of immediate values. * * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all * immediates to the operand-width (hexadecimal only), or any other integer value for custom * padding. */ ZYDIS_FORMATTER_PROP_IMM_PADDING, /* ---------------------------------------------------------------------------------------- */ /* Text formatting */ /* ---------------------------------------------------------------------------------------- */ /** * Controls the letter-case for prefixes. * * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. */ ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES, /** * Controls the letter-case for the mnemonic. * * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. */ ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC, /** * Controls the letter-case for registers. * * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. */ ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS, /** * Controls the letter-case for typecasts. * * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. */ ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS, /** * Controls the letter-case for decorators. * * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. * * WARNING: this is currently not implemented (ignored). */ ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS, /* ---------------------------------------------------------------------------------------- */ /* Number formatting */ /* ---------------------------------------------------------------------------------------- */ /** * Controls the prefix for decimal values. * * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters * to set a custom prefix, or `ZYAN_NULL` to disable it. * * The string is deep-copied into an internal buffer. */ ZYDIS_FORMATTER_PROP_DEC_PREFIX, /** * Controls the suffix for decimal values. * * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters * to set a custom suffix, or `ZYAN_NULL` to disable it. * * The string is deep-copied into an internal buffer. */ ZYDIS_FORMATTER_PROP_DEC_SUFFIX, /* ---------------------------------------------------------------------------------------- */ /** * Controls the letter-case of hexadecimal values. * * Pass `ZYAN_TRUE` as value to format in uppercase and `ZYAN_FALSE` to format in lowercase. * * The default value is `ZYAN_TRUE`. */ ZYDIS_FORMATTER_PROP_HEX_UPPERCASE, /** * Controls whether to prepend hexadecimal values with a leading zero if the first character * is non-numeric. * * Pass `ZYAN_TRUE` to prepend a leading zero if the first character is non-numeric or * `ZYAN_FALSE` to disable this functionality. * * The default value is `ZYAN_FALSE`. */ ZYDIS_FORMATTER_PROP_HEX_FORCE_LEADING_NUMBER, /** * Controls the prefix for hexadecimal values. * * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters * to set a custom prefix, or `ZYAN_NULL` to disable it. * * The string is deep-copied into an internal buffer. */ ZYDIS_FORMATTER_PROP_HEX_PREFIX, /** * Controls the suffix for hexadecimal values. * * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters * to set a custom suffix, or `ZYAN_NULL` to disable it. * * The string is deep-copied into an internal buffer. */ ZYDIS_FORMATTER_PROP_HEX_SUFFIX, /* ---------------------------------------------------------------------------------------- */ /** * Maximum value of this enum. */ ZYDIS_FORMATTER_PROP_MAX_VALUE = ZYDIS_FORMATTER_PROP_HEX_SUFFIX, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_FORMATTER_PROP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_PROP_MAX_VALUE) } ZydisFormatterProperty; /* ---------------------------------------------------------------------------------------------- */ /** * Enum defining different mantissae to be used during formatting. */ typedef enum ZydisNumericBase_ { /** * Decimal system. */ ZYDIS_NUMERIC_BASE_DEC, /** * Hexadecimal system. */ ZYDIS_NUMERIC_BASE_HEX, /** * Maximum value of this enum. */ ZYDIS_NUMERIC_BASE_MAX_VALUE = ZYDIS_NUMERIC_BASE_HEX, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_NUMERIC_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_NUMERIC_BASE_MAX_VALUE) } ZydisNumericBase; /* ---------------------------------------------------------------------------------------------- */ /** * Enum defining the signeness of integers to be used during formatting. */ typedef enum ZydisSignedness_ { /** * Automatically choose the most suitable mode based on the operands * ZydisDecodedOperand.imm.is_signed` attribute. */ ZYDIS_SIGNEDNESS_AUTO, /** * Force signed values. */ ZYDIS_SIGNEDNESS_SIGNED, /** * Force unsigned values. */ ZYDIS_SIGNEDNESS_UNSIGNED, /** * Maximum value of this enum. */ ZYDIS_SIGNEDNESS_MAX_VALUE = ZYDIS_SIGNEDNESS_UNSIGNED, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_SIGNEDNESS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SIGNEDNESS_MAX_VALUE) } ZydisSignedness; /* ---------------------------------------------------------------------------------------------- */ /** * Enum definining magic values that receive special treatment when used as padding properties * of the formatter. */ typedef enum ZydisPadding_ { /** * Disables padding. */ ZYDIS_PADDING_DISABLED = 0, /** * Padds the value to the current stack-width for addresses, or to the * operand-width for immediate values (hexadecimal only). */ ZYDIS_PADDING_AUTO = (-1), /** * Maximum value of this enum. */ ZYDIS_PADDING_MAX_VALUE = ZYDIS_PADDING_AUTO, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_PADDING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PADDING_MAX_VALUE) } ZydisPadding; /* ---------------------------------------------------------------------------------------------- */ /* Function types */ /* ---------------------------------------------------------------------------------------------- */ /** * Enum selecting a formatter function to be replaced with hooks. * * Do NOT change the order of the values this enum or the function fields inside the * `ZydisFormatter` struct. */ typedef enum ZydisFormatterFunction_ { /* ---------------------------------------------------------------------------------------- */ /* Instruction */ /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked before the formatter formats an instruction. */ ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION, /** * This function is invoked after the formatter formatted an instruction. */ ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION, /* ---------------------------------------------------------------------------------------- */ /** * This function refers to the main formatting function. * * Replacing this function allows for complete custom formatting, but indirectly disables all * other hooks except for `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` and * `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION`. */ ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION, /* ---------------------------------------------------------------------------------------- */ /* Operands */ /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked before the formatter formats an operand. */ ZYDIS_FORMATTER_FUNC_PRE_OPERAND, /** * This function is invoked after the formatter formatted an operand. */ ZYDIS_FORMATTER_FUNC_POST_OPERAND, /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked to format a register operand. */ ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG, /** * This function is invoked to format a memory operand. * * Replacing this function might indirectly disable some specific calls to the * `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST`, `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT`, * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` and `ZYDIS_FORMATTER_FUNC_PRINT_DISP` functions. */ ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM, /** * This function is invoked to format a pointer operand. */ ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR, /** * This function is invoked to format an immediate operand. * * Replacing this function might indirectly disable some specific calls to the * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS`, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` and * `ZYDIS_FORMATTER_FUNC_PRINT_IMM` functions. */ ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM, /* ---------------------------------------------------------------------------------------- */ /* Elemental tokens */ /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked to print the instruction mnemonic. */ ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC, /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked to print a register. */ ZYDIS_FORMATTER_FUNC_PRINT_REGISTER, /** * This function is invoked to print absolute addresses. * * Conditionally invoked, if a runtime-address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was * passed: * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) * - `MEM` operands with `EIP`/`RIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) * * Always invoked for: * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) */ ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, /** * This function is invoked to print relative addresses. * * Conditionally invoked, if `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as runtime-address: * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) */ ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL, /** * This function is invoked to print a memory displacement value. * * If the memory displacement contains an address and a runtime-address different to * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called * instead. */ ZYDIS_FORMATTER_FUNC_PRINT_DISP, /** * This function is invoked to print an immediate value. * * If the immediate contains an address and a runtime-address different to * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called * instead. * * If the immediate contains an address and `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as * runtime-address, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` is called instead. */ ZYDIS_FORMATTER_FUNC_PRINT_IMM, /* ---------------------------------------------------------------------------------------- */ /* Optional tokens */ /* ---------------------------------------------------------------------------------------- */ /** * This function is invoked to print the size of a memory operand (`INTEL` only). */ ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST, /** * This function is invoked to print the segment-register of a memory operand. */ ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT, /** * This function is invoked to print the instruction prefixes. */ ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES, /** * This function is invoked after formatting an operand to print a `EVEX`/`MVEX` * decorator. */ ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, /* ---------------------------------------------------------------------------------------- */ /** * Maximum value of this enum. */ ZYDIS_FORMATTER_FUNC_MAX_VALUE = ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_FORMATTER_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_FUNC_MAX_VALUE) } ZydisFormatterFunction; /* ---------------------------------------------------------------------------------------------- */ /* Decorator types */ /* ---------------------------------------------------------------------------------------------- */ /** * Enum of all decorator types. */ typedef enum ZydisDecorator_ { ZYDIS_DECORATOR_INVALID, /** * The embedded-mask decorator. */ ZYDIS_DECORATOR_MASK, /** * The broadcast decorator. */ ZYDIS_DECORATOR_BC, /** * The rounding-control decorator. */ ZYDIS_DECORATOR_RC, /** * The suppress-all-exceptions decorator. */ ZYDIS_DECORATOR_SAE, /** * The register-swizzle decorator. */ ZYDIS_DECORATOR_SWIZZLE, /** * The conversion decorator. */ ZYDIS_DECORATOR_CONVERSION, /** * The eviction-hint decorator. */ ZYDIS_DECORATOR_EH, /** * Maximum value of this enum. */ ZYDIS_DECORATOR_MAX_VALUE = ZYDIS_DECORATOR_EH, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_DECORATOR_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECORATOR_MAX_VALUE) } ZydisDecorator; /* ---------------------------------------------------------------------------------------------- */ /* Formatter context */ /* ---------------------------------------------------------------------------------------------- */ typedef struct ZydisFormatter_ ZydisFormatter; /** * Context structure that that is passed to all formatter. */ typedef struct ZydisFormatterContext_ { /** * A pointer to the `ZydisDecodedInstruction` struct. */ const ZydisDecodedInstruction* instruction; /** * A pointer to the first `ZydisDecodedOperand` struct of the instruction. */ const ZydisDecodedOperand* operands; /** * A pointer to the `ZydisDecodedOperand` struct. */ const ZydisDecodedOperand* operand; /** * The runtime address of the instruction. */ ZyanU64 runtime_address; /** * A pointer to user-defined data. * * This is the value that was previously passed as the `user_data` argument to * @ref ZydisFormatterFormatInstruction or @ref ZydisFormatterTokenizeOperand. */ void* user_data; } ZydisFormatterContext; /* ---------------------------------------------------------------------------------------------- */ /* Function prototypes */ /* ---------------------------------------------------------------------------------------------- */ /** * Defines the `ZydisFormatterFunc` function prototype. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param context A pointer to the `ZydisFormatterContext` struct. * * @return A zyan status code. * * Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the formatting * process to fail (see exceptions below). * * Returning `ZYDIS_STATUS_SKIP_TOKEN` is valid for functions of the following types and will * instruct the formatter to omit the whole operand: * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` * * This function prototype is used by functions of the following types: * - `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` * - `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` * - `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` * - `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC` * - `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` * - `ZYDIS_FORMATTER_FUNC_PRINT_DISP` * - `ZYDIS_FORMATTER_FUNC_PRINT_IMM` * - `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` * - `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` */ typedef ZyanStatus (*ZydisFormatterFunc)(const ZydisFormatter* formatter, ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); /** * Defines the `ZydisFormatterRegisterFunc` function prototype. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param context A pointer to the `ZydisFormatterContext` struct. * @param reg The register. * * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the * formatting process to fail. * * This function prototype is used by functions of the following types: * - `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER`. */ typedef ZyanStatus (*ZydisFormatterRegisterFunc)(const ZydisFormatter* formatter, ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); /** * Defines the `ZydisFormatterDecoratorFunc` function prototype. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param buffer A pointer to the `ZydisFormatterBuffer` struct. * @param context A pointer to the `ZydisFormatterContext` struct. * @param decorator The decorator type. * * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the * formatting process to fail. * * This function type is used for: * - `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` */ typedef ZyanStatus (*ZydisFormatterDecoratorFunc)(const ZydisFormatter* formatter, ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator); /* ---------------------------------------------------------------------------------------------- */ /* Formatter struct */ /* ---------------------------------------------------------------------------------------------- */ /** * Context structure keeping track of internal state of the formatter. * * All fields in this struct should be considered as "private". Any changes may lead to unexpected * behavior. * * Do NOT change the order of the function fields or the values of the `ZydisFormatterFunction` * enum. */ struct ZydisFormatter_ { /** * The formatter style. */ ZydisFormatterStyle style; /** * The `ZYDIS_FORMATTER_PROP_FORCE_SIZE` property. */ ZyanBool force_memory_size; /** * The `ZYDIS_FORMATTER_PROP_FORCE_SEGMENT` property. */ ZyanBool force_memory_segment; /** * The `ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE` property. */ ZyanBool force_memory_scale; /** * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES` property. */ ZyanBool force_relative_branches; /** * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL` property. */ ZyanBool force_relative_riprel; /** * The `ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE` property. */ ZyanBool print_branch_size; /** * The `ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES` property. */ ZyanBool detailed_prefixes; /** * The `ZYDIS_FORMATTER_PROP_ADDR_BASE` property. */ ZydisNumericBase addr_base; /** * The `ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS` property. */ ZydisSignedness addr_signedness; /** * The `ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE` property. */ ZydisPadding addr_padding_absolute; /** * The `ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE` property. */ ZydisPadding addr_padding_relative; /** * The `ZYDIS_FORMATTER_PROP_DISP_BASE` property. */ ZydisNumericBase disp_base; /** * The `ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS` property. */ ZydisSignedness disp_signedness; /** * The `ZYDIS_FORMATTER_PROP_DISP_PADDING` property. */ ZydisPadding disp_padding; /** * The `ZYDIS_FORMATTER_PROP_IMM_BASE` property. */ ZydisNumericBase imm_base; /** * The `ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS` property. */ ZydisSignedness imm_signedness; /** * The `ZYDIS_FORMATTER_PROP_IMM_PADDING` property. */ ZydisPadding imm_padding; /** * The `ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES` property. */ ZyanI32 case_prefixes; /** * The `ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC` property. */ ZyanI32 case_mnemonic; /** * The `ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS` property. */ ZyanI32 case_registers; /** * The `ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS` property. */ ZyanI32 case_typecasts; /** * The `ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS` property. */ ZyanI32 case_decorators; /** * The `ZYDIS_FORMATTER_PROP_HEX_UPPERCASE` property. */ ZyanBool hex_uppercase; /** * The `ZYDIS_FORMATTER_PROP_HEX_FORCE_LEADING_NUMBER` property. */ ZyanBool hex_force_leading_number; /** * The number formats for all numeric bases. * * Index 0 = prefix * Index 1 = suffix */ struct { /** * A pointer to the `ZyanStringView` to use as prefix/suffix. */ const ZyanStringView* string; /** * The `ZyanStringView` to use as prefix/suffix */ ZyanStringView string_data; /** * The actual string data. */ char buffer[11]; } number_format[ZYDIS_NUMERIC_BASE_MAX_VALUE + 1][2]; /** * The `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` function. */ ZydisFormatterFunc func_pre_instruction; /** * The `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` function. */ ZydisFormatterFunc func_post_instruction; /** * The `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` function. */ ZydisFormatterFunc func_format_instruction; /** * The `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` function. */ ZydisFormatterFunc func_pre_operand; /** * The `ZYDIS_FORMATTER_FUNC_POST_OPERAND` function. */ ZydisFormatterFunc func_post_operand; /** * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` function. */ ZydisFormatterFunc func_format_operand_reg; /** * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` function. */ ZydisFormatterFunc func_format_operand_mem; /** * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` function. */ ZydisFormatterFunc func_format_operand_ptr; /** * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` function. */ ZydisFormatterFunc func_format_operand_imm; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC function. */ ZydisFormatterFunc func_print_mnemonic; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER` function. */ ZydisFormatterRegisterFunc func_print_register; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function. */ ZydisFormatterFunc func_print_address_abs; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` function. */ ZydisFormatterFunc func_print_address_rel; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_DISP` function. */ ZydisFormatterFunc func_print_disp; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_IMM` function. */ ZydisFormatterFunc func_print_imm; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` function. */ ZydisFormatterFunc func_print_typecast; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` function. */ ZydisFormatterFunc func_print_segment; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` function. */ ZydisFormatterFunc func_print_prefixes; /** * The `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` function. */ ZydisFormatterDecoratorFunc func_print_decorator; }; /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup formatter Formatter * Functions allowing formatting of previously decoded instructions to human readable text. * @{ */ /* ---------------------------------------------------------------------------------------------- */ /* Initialization */ /* ---------------------------------------------------------------------------------------------- */ /** * Initializes the given `ZydisFormatter` instance. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param style The base formatter style (either `AT&T` or `Intel` style). * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style); /* ---------------------------------------------------------------------------------------------- */ /* Setter */ /* ---------------------------------------------------------------------------------------------- */ /** * Changes the value of the specified formatter `property`. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param property The id of the formatter-property. * @param value The new value. * * @return A zyan status code. * * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a property can't be changed for the * current formatter-style. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, ZydisFormatterProperty property, ZyanUPointer value); /** * Replaces a formatter function with a custom callback and/or retrieves the currently * used function. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param type The formatter function-type. * @param callback A pointer to a variable that contains the pointer of the callback function * and receives the pointer of the currently used function. * * @return A zyan status code. * * Call this function with `callback` pointing to a `ZYAN_NULL` value to retrieve the currently * used function without replacing it. * * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a function can't be replaced for the * current formatter-style. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type, const void** callback); /* ---------------------------------------------------------------------------------------------- */ /* Formatting */ /* ---------------------------------------------------------------------------------------------- */ /** * Formats the given instruction and writes it into the output buffer. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operands A pointer to the decoded operands array. * @param operand_count The length of the `operands` array. Must be equal to or greater than * the value of `instruction->operand_count_visible`. * @param buffer A pointer to the output buffer. * @param length The length of the output buffer (in characters). * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` * to print relative addresses. * @param user_data A pointer to user-defined data which can be used in custom formatter * callbacks. Can be `ZYAN_NULL`. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands, ZyanU8 operand_count, char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data); /** * Formats the given operand and writes it into the output buffer. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operand A pointer to the `ZydisDecodedOperand` struct of the operand to format. * @param buffer A pointer to the output buffer. * @param length The length of the output buffer (in characters). * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` * to print relative addresses. * @param user_data A pointer to user-defined data which can be used in custom formatter * callbacks. Can be `ZYAN_NULL`. * * @return A zyan status code. * * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a * complete instruction. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data); /* ---------------------------------------------------------------------------------------------- */ /* Tokenizing */ /* ---------------------------------------------------------------------------------------------- */ /** * Tokenizes the given instruction and writes it into the output buffer. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operands A pointer to the decoded operands array. * @param operand_count The length of the `operands` array. Must be equal to or greater than * the value of `instruction->operand_count_visible`. * @param buffer A pointer to the output buffer. * @param length The length of the output buffer (in bytes). * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` * to print relative addresses. * @param token Receives a pointer to the first token in the output buffer. * @param user_data A pointer to user-defined data which can be used in custom formatter * callbacks. Can be `ZYAN_NULL`. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands, ZyanU8 operand_count, void* buffer, ZyanUSize length, ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); /** * Tokenizes the given operand and writes it into the output buffer. * * @param formatter A pointer to the `ZydisFormatter` instance. * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operand A pointer to the `ZydisDecodedOperand` struct of the operand to format. * @param buffer A pointer to the output buffer. * @param length The length of the output buffer (in bytes). * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` * to print relative addresses. * @param token Receives a pointer to the first token in the output buffer. * @param user_data A pointer to user-defined data which can be used in custom formatter * callbacks. Can be `ZYAN_NULL`. * * @return A zyan status code. * * Use `ZydisFormatterTokenizeInstruction` to tokenize a complete instruction. */ ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, void* buffer, ZyanUSize length, ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); /* ---------------------------------------------------------------------------------------------- */ /** * @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_FORMATTER_H */ #endif #if !defined(ZYDIS_DISABLE_SEGMENT) // // Header: Zydis/Segment.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Functions and types providing encoding information about individual instruction bytes. */ #ifndef ZYDIS_SEGMENT_H #define ZYDIS_SEGMENT_H #ifdef __cplusplus extern "C" { #endif /** * @addtogroup segment Segment * Functions and types providing encoding information about individual instruction bytes. * @{ */ /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constants */ /* ---------------------------------------------------------------------------------------------- */ #define ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT 9 /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZydisInstructionSegment` struct. */ typedef enum ZydisInstructionSegment_ { ZYDIS_INSTR_SEGMENT_NONE, /** * The legacy prefixes (including ignored `REX` prefixes). */ ZYDIS_INSTR_SEGMENT_PREFIXES, /** * The effective `REX` prefix byte. */ ZYDIS_INSTR_SEGMENT_REX, /** * The `XOP` prefix bytes. */ ZYDIS_INSTR_SEGMENT_XOP, /** * The `VEX` prefix bytes. */ ZYDIS_INSTR_SEGMENT_VEX, /** * The `EVEX` prefix bytes. */ ZYDIS_INSTR_SEGMENT_EVEX, /** * The `MVEX` prefix bytes. */ ZYDIS_INSTR_SEGMENT_MVEX, /** * The opcode bytes. */ ZYDIS_INSTR_SEGMENT_OPCODE, /** * The `ModRM` byte. */ ZYDIS_INSTR_SEGMENT_MODRM, /** * The `SIB` byte. */ ZYDIS_INSTR_SEGMENT_SIB, /** * The displacement bytes. */ ZYDIS_INSTR_SEGMENT_DISPLACEMENT, /** * The immediate bytes. */ ZYDIS_INSTR_SEGMENT_IMMEDIATE, /** * Maximum value of this enum. */ ZYDIS_INSTR_SEGMENT_MAX_VALUE = ZYDIS_INSTR_SEGMENT_IMMEDIATE, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_INSTR_SEGMENT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTR_SEGMENT_MAX_VALUE) } ZydisInstructionSegment; /** * Defines the `ZydisInstructionSegments` struct. */ typedef struct ZydisInstructionSegments_ { /** * The number of logical instruction segments. */ ZyanU8 count; struct { /** * The type of the segment. */ ZydisInstructionSegment type; /** * The offset of the segment relative to the start of the instruction (in bytes). */ ZyanU8 offset; /** * The size of the segment, in bytes. */ ZyanU8 size; } segments[ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT]; } ZydisInstructionSegments; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * Returns offsets and sizes of all logical instruction segments (e.g. `OPCODE`, * `MODRM`, ...). * * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param segments Receives the instruction segments information. * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, ZydisInstructionSegments* segments); /* ============================================================================================== */ /** * @} */ #ifdef __cplusplus } #endif #endif /* ZYDIS_SEGMENT_H */ #endif #if !defined(ZYDIS_DISABLE_DECODER) && !defined(ZYDIS_DISABLE_FORMATTER) // // Header: Zydis/Disassembler.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Joel Hoener * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * All-in-one convenience function providing the simplest possible way to use Zydis. */ #ifndef ZYDIS_DISASSEMBLER_H #define ZYDIS_DISASSEMBLER_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Types */ /* ============================================================================================== */ /** * All commonly used information about a decoded instruction that Zydis can provide. * * This structure is filled in by calling `ZydisDisassembleIntel` or `ZydisDisassembleATT`. */ typedef struct ZydisDisassembledInstruction_ { /** * The runtime address that was passed when disassembling the instruction. */ ZyanU64 runtime_address; /** * General information about the decoded instruction in machine-readable format. */ ZydisDecodedInstruction info; /** * The operands of the decoded instruction in a machine-readable format. * * The amount of actual operands can be determined by inspecting the corresponding fields * in the `info` member of this struct. Inspect `operand_count_visible` if you care about * visible operands (those that are printed by the formatter) or `operand_count` if you're * also interested in implicit operands (for example the registers implicitly accessed by * `pushad`). Unused entries are zeroed. */ ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; /** * The textual, human-readable representation of the instruction. * * Guaranteed to be zero-terminated. */ char text[96]; } ZydisDisassembledInstruction; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * Disassemble an instruction and format it to human-readable text in a single step (Intel syntax). * * @param machine_mode The machine mode to assume when disassembling. When in doubt, pass * `ZYDIS_MACHINE_MODE_LONG_64` for what is typically referred to as * "64-bit mode" or `ZYDIS_MACHINE_MODE_LEGACY_32` for "32-bit mode". * @param runtime_address The program counter (`eip` / `rip`) to assume when formatting the * instruction. Many instructions behave differently depending on the * address they are located at. * @param buffer A pointer to the raw instruction bytes that you wish to decode. * @param length The length of the input buffer. Note that this can be bigger than the * actual size of the instruction -- you don't have to know the size up * front. This length is merely used to prevent Zydis from doing * out-of-bounds reads on your buffer. * @param instruction A pointer to receive the decoded instruction information. Can be * uninitialized and reused on later calls. * * This is a convenience function intended as a quick path for getting started with using Zydis. * It internally calls a range of other more advanced functions to obtain all commonly needed * information about the instruction. It is likely that you won't need most of this information in * practice, so it is advisable to instead call these more advanced functions directly if you're * concerned about performance. * * This function essentially combines the following more advanced functions into a single call: * * - `ZydisDecoderInit` * - `ZydisDecoderDecodeInstruction` * - `ZydisDecoderDecodeOperands` * - `ZydisFormatterInit` * - `ZydisFormatterFormatInstruction` * * @return A zyan status code. */ ZYDIS_EXPORT ZyanStatus ZydisDisassembleIntel(ZydisMachineMode machine_mode, ZyanU64 runtime_address, const void* buffer, ZyanUSize length, ZydisDisassembledInstruction *instruction); /** * Disassemble an instruction and format it to human-readable text in a single step (AT&T syntax). * * @copydetails ZydisDisassembleIntel */ ZYDIS_EXPORT ZyanStatus ZydisDisassembleATT(ZydisMachineMode machine_mode, ZyanU64 runtime_address, const void* buffer, ZyanUSize length, ZydisDisassembledInstruction *instruction); /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_DISASSEMBLER_H */ #endif // // Header: Zydis/Utils.h // // Include stack: // - Zydis/Zydis.h // /*************************************************************************************************** Zyan Disassembler Library (Zydis) Original Author : Florian Bernd * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************************************/ /** * @file * Other utility functions. */ #ifndef ZYDIS_UTILS_H #define ZYDIS_UTILS_H #ifdef __cplusplus extern "C" { #endif /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * @addtogroup utils Utils * Miscellaneous utility functions. Address translation and other helpers. * @{ */ /* ---------------------------------------------------------------------------------------------- */ /* Address calculation */ /* ---------------------------------------------------------------------------------------------- */ // TODO: Provide a function that works in minimal-mode and does not require a operand parameter /** * Calculates the absolute address value for the given instruction operand. * * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operand A pointer to the `ZydisDecodedOperand` struct. * @param runtime_address The runtime address of the instruction. * @param result_address A pointer to the memory that receives the absolute address. * * @return A zyan status code. * * You should use this function in the following cases: * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) * - `MEM` operands with `RIP`/`EIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) * - The displacement needs to get truncated and zero extended */ ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address); /** * Calculates the absolute address value for the given instruction operand. * * @param instruction A pointer to the `ZydisDecodedInstruction` struct. * @param operand A pointer to the `ZydisDecodedOperand` struct. * @param runtime_address The runtime address of the instruction. * @param register_context A pointer to the `ZydisRegisterContext` struct. * @param result_address A pointer to the memory that receives the absolute target-address. * * @return A zyan status code. * * This function behaves like `ZydisCalcAbsoluteAddress` but takes an additional register-context * argument to allow calculation of addresses depending on runtime register values. * * Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed * runtime-address. */ ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, ZyanU64 runtime_address, const ZydisRegisterContext* register_context, ZyanU64* result_address); /* ---------------------------------------------------------------------------------------------- */ /** * @} */ /* ============================================================================================== */ #ifdef __cplusplus } #endif #endif /* ZYDIS_UTILS_H */ #ifdef __cplusplus extern "C" { #endif /** * @addtogroup version Version * * Functions for checking the library version and build options. * * @{ */ /* ============================================================================================== */ /* Macros */ /* ============================================================================================== */ /* ---------------------------------------------------------------------------------------------- */ /* Constants */ /* ---------------------------------------------------------------------------------------------- */ /** * A macro that defines the zydis version. */ #define ZYDIS_VERSION (ZyanU64)0x0004000100000000 /* ---------------------------------------------------------------------------------------------- */ /* Helper macros */ /* ---------------------------------------------------------------------------------------------- */ /** * Extracts the major-part of the zydis version. * * @param version The zydis version value */ #define ZYDIS_VERSION_MAJOR(version) (ZyanU16)(((version) & 0xFFFF000000000000) >> 48) /** * Extracts the minor-part of the zydis version. * * @param version The zydis version value */ #define ZYDIS_VERSION_MINOR(version) (ZyanU16)(((version) & 0x0000FFFF00000000) >> 32) /** * Extracts the patch-part of the zydis version. * * @param version The zydis version value */ #define ZYDIS_VERSION_PATCH(version) (ZyanU16)(((version) & 0x00000000FFFF0000) >> 16) /** * Extracts the build-part of the zydis version. * * @param version The zydis version value */ #define ZYDIS_VERSION_BUILD(version) (ZyanU16)((version) & 0x000000000000FFFF) /* ---------------------------------------------------------------------------------------------- */ /* ============================================================================================== */ /* Enums and types */ /* ============================================================================================== */ /** * Defines the `ZydisFeature` enum. */ typedef enum ZydisFeature_ { ZYDIS_FEATURE_DECODER, ZYDIS_FEATURE_ENCODER, ZYDIS_FEATURE_FORMATTER, ZYDIS_FEATURE_AVX512, ZYDIS_FEATURE_KNC, ZYDIS_FEATURE_SEGMENT, /** * Maximum value of this enum. */ ZYDIS_FEATURE_MAX_VALUE = ZYDIS_FEATURE_SEGMENT, /** * The minimum number of bits required to represent all values of this enum. */ ZYDIS_FEATURE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FEATURE_MAX_VALUE) } ZydisFeature; /* ============================================================================================== */ /* Exported functions */ /* ============================================================================================== */ /** * Returns the zydis version. * * @return The zydis version. * * Use the macros provided in this file to extract the major, minor, patch and build part from the * returned version value. */ ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void); /** * Checks, if the specified feature is enabled in the current zydis library instance. * * @param feature The feature. * * @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another * zyan status code, if an error occured. */ ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature); /* ============================================================================================== */ /** * @} */ #ifdef __cplusplus } #endif #endif /* ZYDIS_H */ ================================================ FILE: src/torture/torture.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// // Build Options #define BUILD_CONSOLE_INTERFACE 1 #define BUILD_TITLE "TORTURE" //////////////////////////////// #include "third_party/xxHash/xxhash.c" #include "third_party/xxHash/xxhash.h" #include "third_party/radsort/radsort.h" //////////////////////////////// #include "base/base_inc.h" #include "os/os_inc.h" #include "coff/coff.h" #include "coff/coff_parse.h" #include "coff/coff_obj_writer.h" #include "coff/coff_lib_writer.h" #include "pe/pe.h" #include "pe/pe_section_flags.h" #include "linker/base_ext/base_core.h" #include "linker/base_ext/base_arena.h" #include "linker/base_ext/base_arrays.h" #include "linker/hash_table.h" #include "base/base_inc.c" #include "os/os_inc.c" #include "coff/coff.c" #include "coff/coff_parse.c" #include "coff/coff_obj_writer.c" #include "coff/coff_lib_writer.c" #include "pe/pe.c" #include "linker/hash_table.c" #include "linker/base_ext/base_core.c" #include "linker/base_ext/base_arena.c" #include "linker/base_ext/base_arrays.c" #include "linker/lnk_cmd_line.h" #include "linker/lnk_cmd_line.c" #include "linker/lnk_error.h" //////////////////////////////// typedef enum { T_Result_Fail, T_Result_Crash, T_Result_Pass, } T_Result; typedef T_Result (*T_Run)(void); internal char * t_string_from_result(T_Result v) { switch (v) { case T_Result_Fail: return "FAIL"; case T_Result_Crash: return "CRASH"; case T_Result_Pass: return "PASS"; } return 0; } global String8 g_stdout_file_name = str8_lit_comp("torture.out"); global U64 g_linker_time_out; global String8 g_linker; global String8 g_wdir; global String8 g_out = str8_lit_comp("torture"); global B32 g_verbose; global B32 g_redirect_stdout = 1; #define T_LINKER_TIME_OUT_EXIT_CODE 999999 typedef enum { T_Linker_Null, T_Linker_RAD, T_Linker_MSVC, T_Linker_LLVM } T_Linker; internal T_Linker t_ident_linker(void) { String8 name = g_linker; name = str8_skip_last_slash(name); name = str8_chop_last_dot(name); if (str8_match(name, str8_lit("radlink"), StringMatchFlag_CaseInsensitive)) { return T_Linker_RAD; } if (str8_match(name, str8_lit("link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_MSVC; } if (str8_match(name, str8_lit("lld-link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_LLVM; } return T_Linker_Null; } internal int t_invoke_linker_with_time_out(U64 time_out, String8 cmdline) { Temp scratch = scratch_begin(0,0); OS_Handle output_redirect = {0}; if (g_redirect_stdout) { output_redirect = os_file_open(OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, g_stdout_file_name); } // // Build Launch Options // OS_ProcessLaunchParams launch_opts = {0}; launch_opts.path = g_wdir; launch_opts.inherit_env = 1; launch_opts.stdout_file = output_redirect; launch_opts.stderr_file = output_redirect; str8_list_push(scratch.arena, &launch_opts.cmd_line, g_linker); str8_list_push(scratch.arena, &launch_opts.cmd_line, str8_lit("/nologo")); { String8List parsed_cmdline = lnk_arg_list_parse_windows_rules(scratch.arena, cmdline); str8_list_concat_in_place(&launch_opts.cmd_line, &parsed_cmdline); } // // Invoke Linker // int exit_code = -1; { if (g_verbose) { String8 full_cmd_line = str8_list_join(scratch.arena, &launch_opts.cmd_line, &(StringJoin){ .sep = str8_lit(" ") }); fprintf(stdout, "Command Line: %.*s\n", str8_varg(full_cmd_line)); fprintf(stdout, "Working Dir: %.*s\n", str8_varg(g_wdir)); } OS_Handle linker_handle = os_process_launch(&launch_opts); if (os_handle_match(linker_handle, os_handle_zero())) { fprintf(stderr, "unable to start process: %.*s\n", str8_varg(g_linker)); } else { U64 exit_code_u64 = 0; B32 was_joined = os_process_join(linker_handle, time_out, &exit_code_u64); exit_code = (int)exit_code_u64; if (!was_joined) { os_process_kill(linker_handle); exit_code = T_LINKER_TIME_OUT_EXIT_CODE; } os_process_detach(linker_handle); } } if (g_redirect_stdout) { os_file_close(output_redirect); } scratch_end(scratch); return exit_code; } internal int t_invoke_linker(String8 cmdline) { return t_invoke_linker_with_time_out(max_U64, cmdline); } internal int t_invoke_linkerf(char *fmt, ...) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 cmdline = push_str8fv(scratch.arena, fmt, args); int exit_code = t_invoke_linker(cmdline); va_end(args); scratch_end(scratch); return exit_code; } internal int t_invoke_linker_with_time_outf(U64 time_out, char *fmt, ...) { Temp scratch = scratch_begin(0,0); va_list args; va_start(args, fmt); String8 cmdline = push_str8fv(scratch.arena, fmt, args); int exit_code = t_invoke_linker_with_time_out(time_out, cmdline); va_end(args); scratch_end(scratch); return exit_code; } internal String8 t_make_file_path(Arena *arena, String8 name) { return push_str8f(arena, "%S\\%S", g_wdir, name); } internal B32 t_write_file_list(String8 name, String8List data) { Temp scratch = scratch_begin(0,0); String8 path = t_make_file_path(scratch.arena, name); B32 is_written = os_write_data_list_to_file_path(path, data); scratch_end(scratch); return is_written; } internal B32 t_write_file(String8 name, String8 data) { String8Node temp_node = {0}; temp_node.string = data; String8List temp_list = {0}; str8_list_push_node(&temp_list, &temp_node); return t_write_file_list(name, temp_list); } internal String8 t_read_file(Arena *arena, String8 name) { Temp scratch = scratch_begin(&arena,1); String8 path = t_make_file_path(scratch.arena, name); String8 data = os_data_from_file_path(arena, path); scratch_end(scratch); return data; } typedef struct { T_Run run; T_Result result; } T_RunCtx; internal void t_run_caller(void *raw_ctx) { T_RunCtx *ctx = raw_ctx; ctx->result = ctx->run(); } internal void t_run_fail_handler(void *raw_ctx) { T_RunCtx *ctx = raw_ctx; ctx->result = T_Result_Crash; } internal T_Result t_run(T_Run run) { T_RunCtx ctx = {0}; ctx.run = run; os_safe_call(t_run_caller, t_run_fail_handler, &ctx); return ctx.result; } internal COFF_SectionHeader * t_coff_section_header_from_name(String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name) { for (U64 sect_idx = 0; sect_idx < section_count; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 section_name = coff_name_from_section_header(string_table, section_header); if (str8_match(section_name, name, 0)) { return section_header; } } return 0; } internal COFF_SectionHeaderArray t_coff_section_header_array_from_name(Arena *arena, String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name) { U64 match_count = 0; for (U64 sect_idx = 0; sect_idx < section_count; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 section_name = coff_name_from_section_header(string_table, section_header); if (str8_match(section_name, name, 0)) { match_count += 1; } } COFF_SectionHeader *matches = push_array(arena, COFF_SectionHeader, match_count); for (U64 sect_idx = 0, match_idx = 0; sect_idx < section_count; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 section_name = coff_name_from_section_header(string_table, section_header); if (str8_match(section_name, name, 0)) { matches[match_idx++] = *section_header; } } COFF_SectionHeaderArray result = {0}; result.count = match_count; result.v = matches; return result; } //////////////////////////////////////////////////////////////// typedef enum { T_MsvcLinkExitCode_UnresolvedExternals = 1120, T_MsvcLinkExitCode_CorruptOrInvalidSymbolTable = 1235, T_MsvcLinkExitCode_SectionsFoundWithDifferentAttributes = 4078, } T_MsvcLinkExitCode; internal COFF_ObjSection * t_push_text_section(COFF_ObjWriter *obj_writer, String8 data) { return coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS | COFF_SectionFlag_Align1Bytes, data); } internal COFF_ObjSection * t_push_data_section(COFF_ObjWriter *obj_writer, String8 data) { return coff_obj_writer_push_section(obj_writer, str8_lit(".data"), PE_DATA_SECTION_FLAGS, data); } internal COFF_ObjSection * t_push_rdata_section(COFF_ObjWriter *obj_writer, String8 data) { return coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS, data); } internal void t_write_entry_obj(void) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xc3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(obj_writer->arena, obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { AssertAlways(!"unable to write entry obj"); } coff_obj_writer_release(&obj_writer); } //////////////////////////////// internal T_Result t_machine_compat_check(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown); t_push_data_section(obj_writer, str8_lit("unknown")); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("unknown.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); t_push_data_section(obj_writer, str8_lit("x64")); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("x64.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Arm64); t_push_data_section(obj_writer, str8_lit("arm64")); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("arm64.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xC3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code; linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe entry.obj unknown.obj x64.obj"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe entry.obj unknown.obj x64.obj arm64.obj"); if (linker_exit_code == 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe /machine:amd64 arm64.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_out_of_bounds_section_number(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *foo = coff_obj_writer_push_section(obj_writer, str8_lit(".foo"), PE_DATA_SECTION_FLAGS, str8_lit("foo")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("foo"), 0, foo); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); { COFF_FileHeaderInfo header = coff_file_header_info_from_data(obj); String8 string_table = str8_substr(obj, header.string_table_range); String8 symbol_table = str8_substr(obj, header.symbol_table_range); COFF_ParsedSymbol symbol = coff_parse_symbol(header, string_table, symbol_table, 0); COFF_Symbol16 *symbol16 = symbol.raw_symbol; symbol16->section_number = 123; } if (!t_write_file(str8_lit("bad.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("foo")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj bad.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && linker_exit_code != LNK_Error_IllData) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_merge(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_section(obj_writer, str8_lit(".test"), PE_DATA_SECTION_FLAGS, str8_lit("hello, world")); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("test.obj"), obj)) { goto exit; } } t_write_entry_obj(); int linker_exit_code; // circular merge linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.test entry.obj test.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_CircularMerge) { goto exit; } } // circular merge with extra link linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.data /merge:.data=.test entry.obj test.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_CircularMerge) { goto exit; } } // merge with non-defined section { linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.qwe entry.obj test.obj"); if (linker_exit_code != 0) { goto exit; } // make sure linker created .qwe and merged .test into it String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".qwe")); if (sect == 0) { goto exit; } if (sect->flags != PE_DATA_SECTION_FLAGS) { goto exit; } String8 qwe = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(qwe, str8_lit("hello, world"),0)) { goto exit; } } // illegal merge with .reloc linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.reloc entry.obj test.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_IllegalSectionMerge) { goto exit; } } // illegal merge with .rsrc linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.rsrc entry.obj test.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_IllegalSectionMerge) { goto exit; } } // merge non-defined section with defined section linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.qwe=.test entry.obj test.obj"); if (linker_exit_code != 0) { goto exit; } // merge .test -> .qwe -> .data { linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.qwe /merge:.qwe=.data entry.obj test.obj"); if (linker_exit_code != 0) { goto exit; } // make sure linker merged .test into .data String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".data")); if (sect == 0) { goto exit; } if (sect->flags != PE_DATA_SECTION_FLAGS) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("hello, world"),0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_simple_link_test(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; U8 text_payload[] = { 0xC3 }; String8 main_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text_payload)); coff_obj_writer_push_section(obj_writer, str8_lit(".data"), PE_DATA_SECTION_FLAGS, str8_lit("qwe")); coff_obj_writer_push_section(obj_writer, str8_lit(".zero"), PE_BSS_SECTION_FLAGS, str8(0, 5)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 main_obj_name = str8_lit("main.obj"); if (!t_write_file(main_obj_name, main_obj)) { goto exit; } int file_align = 512; int virt_align = 4096; String8 out_name = str8_lit("a.exe"); int linker_exit_code = t_invoke_linkerf("/entry:my_entry /subsystem:console /fixed /filealign:%d /align:%d /out:%S %S", file_align, virt_align, out_name, main_obj_name); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, out_name); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); if (pe.is_pe32) { goto exit; } if (pe.section_count != 3) { goto exit; } if (pe.arch != Arch_x64) { goto exit; } if (pe.subsystem != PE_WindowsSubsystem_WINDOWS_CUI) { goto exit; } if (pe.virt_section_align != virt_align) { goto exit; } if (pe.file_section_align != file_align) { goto exit; } if (pe.symbol_count != 0) { goto exit; } if (pe.data_dir_count != PE_DataDirectoryIndex_COUNT) { goto exit; } // check section alignment for (U64 sect_idx = 0; sect_idx < pe.section_count; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if (AlignPadPow2(sect_header->fsize, file_align) != 0) { goto exit; } if (AlignPadPow2(sect_header->voff, virt_align) != 0) { goto exit; } } COFF_SectionHeader *text_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (!text_section) { goto exit; } if (text_section->foff != file_align) { goto exit; } if (pe.entry_point != text_section->voff) { goto exit; } COFF_SectionHeader *data_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (data_section == 0) { goto exit; } COFF_SectionHeader *zero_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".zero")); if (zero_section == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_section->foff, text_section->foff + text_section->vsize)); if (!str8_match(text_data, str8_array_fixed(text_payload), 0)) { goto exit; } PE_OptionalHeader32Plus *opt = str8_deserial_get_raw_ptr(exe, pe.optional_header_off, sizeof(*opt)); if (opt->sizeof_code != text_section->fsize) { goto exit; } if (opt->sizeof_inited_data != text_section->fsize + data_section->fsize) { goto exit; } if (opt->sizeof_uninited_data != 0x200) { goto exit; } if (opt->code_base != 0x1000) { goto exit; } if (opt->image_base != 0x140000000) { goto exit; } if (opt->major_os_ver != 6) { goto exit; } if (opt->minor_os_ver != 0) { goto exit; } if (opt->major_img_ver != 0) { goto exit; } if (opt->minor_img_ver != 0) { goto exit; } if (opt->major_subsystem_ver != 6) { goto exit; } if (opt->minor_subsystem_ver != 0) { goto exit; } if (opt->win32_version_value != 0) { goto exit; } if (opt->sizeof_image != 0x4000) { goto exit; } if (opt->sizeof_headers != 0x200) { goto exit; } if (opt->dll_characteristics != 0x8120) { goto exit; } if (opt->loader_flags != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_link_undef(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 undef_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("undef")); undef_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("undef")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("undef.obj"), undef_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // try linking unresolved symbol and see if linker picks up on that int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj undef.obj"); if (linker_exit_code != LNK_Error_UnresolvedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_link_unref_undef(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 undef_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("undef")); undef_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xc3 }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("undef.obj"), undef_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // try linking unreferenced unresolved symbol, this must link int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj undef.obj"); if (linker_exit_code == 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_lib_vs_weak_lib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code; // linker must pick weak symbol from a.obj linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x111; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } // linker must pick weak symbol from entry.obj linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_lib_vs_weak_nolib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from entry.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_lib_vs_weak_alias(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from entry.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_lib_vs_weak_antidep(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from a.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_alias_vs_weak_alias(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *qwe = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("qwe"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("sym"), COFF_WeakExt_SearchAlias, qwe); a = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 b; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *ewq = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("ewq"), 0x222, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("sym"), COFF_WeakExt_SearchAlias, ewq); b = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("sym")); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a)) { goto exit; } if (!t_write_file(str8_lit("b.obj"), b)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj"); if (linker_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_alias_vs_weak_lib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from entry.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_alias_vs_weak_nolib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from entry.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_alias_vs_weak_antidep(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } // linker must pick weak symbol from entry.obj int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_nolib_vs_weak_nolib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_nolib_vs_weak_lib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_nolib_vs_weak_alias(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_nolib_vs_weak_antidep(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_antidep_vs_weak_antidep(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code; // linker must pick weak symbol from a.obj linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x111; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } // linker must pick weak symbol from entry.obj linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_antidep_vs_weak_nolib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_NoLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_antidep_vs_weak_lib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x222; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_antidep_vs_weak_alias(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("q"), 0x111, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchAlias, q); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *e = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("e"), 0x222, COFF_SymStorageClass_External); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_AntiDependency, e); coff_obj_writer_section_push_reloc_addr32(obj_writer, sect, 3, sym); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj"); if (linker_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); String8 imm = str8_substr(text_data, rng_1u64(3, 7)); U32 expected = 0x111; if (!str8_match(imm, str8_struct(&expected), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_vs_common(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 weak_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS, str8_lit("a")); COFF_ObjSymbol *sect_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("_a"), 0, sect); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("w"), COFF_WeakExt_SearchLibrary, sect_symbol); weak_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 common_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_common(obj_writer, str8_lit("w"), 2); common_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("w")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("weak.obj"), weak_obj)) { goto exit; } if (!t_write_file(str8_lit("common.obj"), common_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code; linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe common.obj weak.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe weak.obj common.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *bss = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".bss")); if (!bss) { goto exit; } if (bss->fsize != 0) { goto exit; } if (bss->vsize != 2) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_abs_vs_weak(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; U32 abs_value = 0x123; U8 text_code[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3 }; String8 abs_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("foo"), abs_value, COFF_SymStorageClass_External); abs_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 text_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *mydata = coff_obj_writer_push_section(obj_writer, str8_lit(".mydata"), COFF_SectionFlag_CntCode|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_Align1Bytes, str8_lit("mydata")); COFF_ObjSymbol *tag = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("mydata"), 0, mydata); COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("foo"), COFF_WeakExt_NoLibrary, tag); COFF_ObjSection *text = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), COFF_SectionFlag_CntCode|COFF_SectionFlag_MemExecute|COFF_SectionFlag_MemRead|COFF_SectionFlag_Align1Bytes, str8_array_fixed(text_code)); coff_obj_writer_section_push_reloc(obj_writer, text, 2, foo, COFF_Reloc_X64_Addr64); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text); text_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("abs.obj"), abs_obj)) { goto exit; } if (!t_write_file(str8_lit("text.obj"), text_obj)) { goto exit; } int abs_vs_weak_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe abs.obj text.obj")); if (abs_vs_weak_exit_code != 0) { goto exit; } int weak_vs_abs_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe text.obj abs.obj")); if (weak_vs_abs_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_section == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_section->foff, text_section->foff + text_section->fsize)); String8 inst = str8_prefix(text_data, 2); if (!str8_match(inst, str8_array(text_code, 2), 0)) { goto exit; } String8 imm = str8_prefix(str8_skip(text_data, 2), 8); U64 expected_imm = abs_value; if (!str8_match(imm, str8_struct(&expected_imm), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_abs_vs_regular(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 shared_symbol_name = str8_lit("foo"); U8 regular_payload[] = { 0xC0, 0xFF, 0xEE }; String8 regular_obj_name = str8_lit("regular.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8_array_fixed(regular_payload)); coff_obj_writer_push_symbol_extern(obj_writer, shared_symbol_name, 0, data_sect); String8 regular_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(regular_obj_name, regular_obj)) { goto exit; } } String8 abs_obj_name = str8_lit("abs.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, shared_symbol_name, 0x1234, COFF_SymStorageClass_External); String8 abs_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(abs_obj_name, abs_obj)) { goto exit; } } U8 entry_text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); COFF_ObjSymbol *shared_symbol = coff_obj_writer_push_symbol_undef(obj_writer, shared_symbol_name); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 3, shared_symbol, COFF_Reloc_X64_Addr32Nb); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } // TODO: validate that linker issues multiply defined symbol error int abs_vs_regular_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe abs.obj regular.obj entry.obj"); if (abs_vs_regular_exit_code == 0) { // linker should complain about multiply defined symbol goto exit; } int regular_vs_abs_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe regular.obj abs.obj entry.obj"); if (regular_vs_abs_exit_code == 0) { // linker should complain even in case regular is before abs goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_abs_vs_common(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 shared_symbol_name = str8_lit("foo"); String8 common_obj_name = str8_lit("common.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_common(obj_writer, shared_symbol_name, 321); String8 common_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(common_obj_name, common_obj)) { goto exit; } } String8 abs_obj_name = str8_lit("abs.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, shared_symbol_name, 0x1234, COFF_SymStorageClass_External); String8 abs_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(abs_obj_name, abs_obj)) { goto exit; } } U8 entry_text[] = { 0xC3 }; String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe abs.obj common.obj entry.obj"); if (linker_exit_code == 0) { // TODO: validate that linker issues multiply defined symbol error int common_vs_abs = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe common.obj abs.obj entry.obj"); if (t_ident_linker() == T_Linker_RAD) { if (common_vs_abs == LNK_Error_MultiplyDefinedSymbol) { result = T_Result_Pass; } } else { if (common_vs_abs != 0) { result = T_Result_Pass; } } } exit:; scratch_end(scratch); return result; } internal T_Result t_abs_vs_abs(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("foo"), 'a', COFF_SymStorageClass_External); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 b_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("foo"), 'b', COFF_SymStorageClass_External); b_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("b.obj"), b_obj)) { goto exit; } t_write_entry_obj(); int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj"); if (linker_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_undef_weak_lib(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 weak; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSymbol *b = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("b"), 0xc3000000, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("a"), COFF_WeakExt_SearchLibrary, b); weak = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSymbol *sym = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("a")); U8 text[4] = {0}; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, sym); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); entry = coff_obj_writer_serialize(scratch.arena, obj_writer); } if (!t_write_file(str8_lit("weak.obj"), weak)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry)) { goto exit; } // undefined symbol must always replace weak symbol with search library int linker_exit_code = t_invoke_linkerf("/subsystem:console /out:a.exe /entry:entry entry.obj weak.obj"); if (linker_exit_code != LNK_Error_UnresolvedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_undef_weak_search_alias(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 weak_obj; { U8 weak_payload[] = { 0xDE, 0xAD, 0xBE, 0xEF }; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *weak_sect = t_push_data_section(obj_writer, str8_array_fixed(weak_payload)); COFF_ObjSymbol *tag = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("ptr")); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("foo"), COFF_WeakExt_SearchAlias, tag); weak_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 ptr_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *tag = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("entry")); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("ptr"), COFF_WeakExt_SearchAlias, tag); ptr_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 undef_obj; { U8 undef_obj_payload[] = { 0x00, 0x00, 0x00, 0x00 }; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *undef_sect = t_push_data_section(obj_writer, str8_array_fixed(undef_obj_payload)); COFF_ObjSymbol *undef_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("foo")); coff_obj_writer_section_push_reloc(obj_writer, undef_sect, 0, undef_symbol, COFF_Reloc_X64_Addr32Nb); undef_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { U8 entry_payload[] = {0xC3}; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_payload)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("weak.obj"), weak_obj)) { goto exit; } if (!t_write_file(str8_lit("ptr.obj"), ptr_obj)) { goto exit; } if (!t_write_file(str8_lit("undef.obj"), undef_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe weak.obj entry.obj ptr.obj undef.obj"); if (linker_exit_code != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_weak_cycle(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 ab_obj_name = str8_lit("ab.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *b = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("B")); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("A"), COFF_WeakExt_SearchAlias, b); String8 ab_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(ab_obj_name, ab_obj)) { goto exit; } } String8 ba_obj_name = str8_lit("ba.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *a = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("A")); coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("B"), COFF_WeakExt_SearchAlias, a); String8 ba_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(ba_obj_name, ba_obj)) { goto exit; } } String8 entry_obj_name = str8_lit("entry.obj"); U8 entry_payload[] = { 0xC3 }; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_payload)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } U64 time_out = os_now_microseconds() + 3 * 1000 * 1000; // give a generous 3 seconds int linker_exit_code = t_invoke_linker_with_time_outf(time_out, "/subsystem:console /entry:my_entry %S %S %S", entry_obj_name, ab_obj_name, ba_obj_name); if (linker_exit_code != T_LINKER_TIME_OUT_EXIT_CODE) { if (t_ident_linker() == T_Linker_MSVC) { if (linker_exit_code == T_MsvcLinkExitCode_UnresolvedExternals) { result = T_Result_Pass; } } else { result = T_Result_Pass; } } exit:; scratch_end(scratch); return result; } internal T_Result t_weak_tag(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; U32 weak_tag_expected_value = 0x12345678; String8 weak_tag_obj_name = str8_lit("weak_tag.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *tag_symbol = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("abs"), weak_tag_expected_value, COFF_SymStorageClass_Static); COFF_ObjSymbol *weak_first = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("strong_first"), COFF_WeakExt_SearchAlias, tag_symbol); COFF_ObjSymbol *weak_second = coff_obj_writer_push_symbol_weak(obj_writer, str8_lit("strong_second"), COFF_WeakExt_SearchAlias, weak_first); U8 sect_data[4] = {0}; COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_array_fixed(sect_data)); coff_obj_writer_section_push_reloc(obj_writer, sect, 0, weak_second, COFF_Reloc_X64_Addr32); String8 weak_tag_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(weak_tag_obj_name, weak_tag_obj)) { goto exit; } } String8 entry_name = str8_lit("my_entry"); U8 entry_text[] = { 0xC3 }; String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); coff_obj_writer_push_symbol_extern(obj_writer, entry_name, 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe %S %S", weak_tag_obj_name, entry_obj_name); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *data_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); String8 data = str8_substr(exe, rng_1u64(data_section->foff, data_section->foff + data_section->vsize)); if (!data_section) { goto exit; } if (data_section->vsize != 4) { goto exit; } if (!str8_match(data, str8_struct(&weak_tag_expected_value), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal String8 t_make_sec_defn_obj(Arena *arena, String8 payload) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *mysect_section = coff_obj_writer_push_section(obj_writer, str8_lit(".mysect"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_Align1Bytes, payload); coff_obj_writer_push_symbol_secdef(obj_writer, mysect_section, COFF_ComdatSelect_Null); String8 obj = coff_obj_writer_serialize(arena, obj_writer); coff_obj_writer_release(&obj_writer); return obj; } internal T_Result t_undef_section(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 main_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 data[] = { 0, 0, 0, 0 }; COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data)); COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".mysect"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead); coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr32Nb); U8 text[] = { 0xC3 }; COFF_ObjSection *text_section = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section); main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } U8 payload[] = { 1, 2, 3 }; String8 sec_defn_obj = t_make_sec_defn_obj(scratch.arena, str8_array_fixed(payload)); t_write_file(str8_lit("main.obj"), main_obj); t_write_file(str8_lit("sec_defn.obj"), sec_defn_obj); int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj sec_defn.obj")); if (linker_exit_code == 0) { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *data_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); COFF_SectionHeader *mysect_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".mysect")); if (data_section && mysect_section) { if (data_section->vsize == 4 && mysect_section->vsize == 3) { String8 addr32nb = str8_substr(exe, rng_1u64(data_section->foff, data_section->foff + data_section->vsize)); String8 expected_voff = str8_struct(&mysect_section->voff); if (str8_match(addr32nb, expected_voff, 0)) { result = T_Result_Pass; } } } } scratch_end(scratch); return result; } internal T_Result t_sect_symbol(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 sect_payload = str8_lit("hello, world"); String8 sect_obj_name = str8_lit("sect.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".mysect$1"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, sect_payload); coff_obj_writer_push_directive(obj_writer, str8_lit("/merge:.mysect=.data")); String8 sect_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(sect_obj_name, sect_obj)) { goto exit; } } String8 main_obj_name = str8_lit("main.obj"); { U8 data[8] = {0}; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_array_fixed(data)); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".mysect$2222"), PE_DATA_SECTION_FLAGS); coff_obj_writer_section_push_reloc_addr(obj_writer, sect, 0, symbol); U8 text[] = { 0xC3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(main_obj_name, main_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe main.obj sect.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (!sect) { goto exit; } String8 sect_data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); String8 addr_data = str8_substr(sect_data, rng_1u64(0, sizeof(U64))); if (addr_data.size != sizeof(U64)) { goto exit; } U64 addr = *(U64 *)addr_data.str; if (addr - (pe.image_base + sect->voff) != 8) { goto exit; } String8 payload_got = str8_substr(sect_data, rng_1u64(8, sect_data.size)); if (!str8_match(payload_got, sect_payload, 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_undef_reloc_section(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 main_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xC3 }; COFF_ObjSection *text_section = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); COFF_ObjSymbol *my_entry_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section); U8 data[8] = { 0 }; COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data)); COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".reloc"), PE_RELOC_SECTION_FLAGS); coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr64); main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } U8 payload[] = { 1, 2, 3 }; String8 sec_defn_obj = t_make_sec_defn_obj(scratch.arena, str8_array_fixed(payload)); t_write_file(str8_lit("main.obj"), main_obj); t_write_file(str8_lit("sec_defn.obj"), sec_defn_obj); int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj sec_defn.obj")); if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_SectRefsDiscardedMemory) { goto exit; } } else if (linker_exit_code == 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_find_merged_pdata(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; U8 foobar_payload[] = { 0x40, 0x57, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x84, 0x24, 0xF0, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x04, 0x24, 0x48, 0x8B, 0xF8, 0x33, 0xC0, 0xB9, 0xEC, 0x01, 0x00, 0x00, 0xF3, 0xAA, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x02, 0x8B, 0x04, 0x04, 0x48, 0x8B, 0x8C, 0x24, 0xF0, 0x01, 0x00, 0x00, 0x48, 0x33, 0xCC, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xC4, 0x00, 0x02, 0x00, 0x00, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3 }; U8 xdata_payload[] = { 0x19, 0x1B, 0x03, 0x00, 0x09, 0x01, 0x40, 0x00, 0x02, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, 0x00, 0x00 }; PE_IntelPdata intel_pdata = {0}; U8 text_payload[] = { 0xC3 }; String8 main_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *xdata = coff_obj_writer_push_section(obj_writer, str8_lit(".xdata"), COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_Align4Bytes, str8_array_fixed(xdata_payload)); COFF_ObjSection *pdata = coff_obj_writer_push_section(obj_writer, str8_lit(".pdata"), COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_Align4Bytes, str8_struct(&intel_pdata)); COFF_ObjSection *foobar = coff_obj_writer_push_section(obj_writer, str8_lit(".foobar"), COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_CntCode|COFF_SectionFlag_Align1Bytes, str8_array_fixed(foobar_payload)); COFF_ObjSection *text = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_CntCode|COFF_SectionFlag_Align1Bytes, str8_array_fixed(text_payload)); COFF_ObjSymbol *foobar_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("foobar"), 0, foobar); coff_obj_writer_push_symbol_secdef(obj_writer, xdata, COFF_ComdatSelect_Null); COFF_ObjSymbol *unwind_foobar = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("$unwind$foobar"), 0, xdata); coff_obj_writer_push_symbol_secdef(obj_writer, pdata, COFF_ComdatSelect_Null); coff_obj_writer_push_symbol_static(obj_writer, str8_lit("$pdata$foobar"), 0, pdata); coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_unwind_info), unwind_foobar, COFF_Reloc_X64_Addr32Nb); coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_first), foobar_symbol, COFF_Reloc_X64_Addr32Nb); coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_one_past_last), foobar_symbol, COFF_Reloc_X64_Addr32Nb); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text); main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } t_write_file(str8_lit("main.obj"), main_obj); int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj /merge:.pdata=.rdata")); if (linker_exit_code == 0) { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); if (dim_1u64(pe.data_dir_franges[PE_DataDirectoryIndex_EXCEPTIONS]) == 0xC) { result = T_Result_Pass; } } scratch_end(scratch); return result; } internal T_Result t_section_sort(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 data_obj_name = str8_lit("data.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_SectionFlags data_flags = COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemRead|COFF_SectionFlag_Align1Bytes; coff_obj_writer_push_section(obj_writer, str8_lit(".data$z"), data_flags, str8_lit("five")); coff_obj_writer_push_section(obj_writer, str8_lit(".data$a"), data_flags, str8_lit("three")); coff_obj_writer_push_section(obj_writer, str8_lit(".data$bbbbb"), data_flags, str8_lit("four")); coff_obj_writer_push_section(obj_writer, str8_lit(".data$"), data_flags, str8_lit("two")); coff_obj_writer_push_section(obj_writer, str8_lit(".data"), data_flags, str8_lit("one")); String8 data_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(data_obj_name, data_obj)) { goto exit; } } String8 entry_obj_name = str8_lit("entry.obj"); U8 entry_text[] = { 0xC3 }; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe data.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *data_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (!data_section) { goto exit; } String8 data = str8_substr(exe, rng_1u64(data_section->foff, data_section->foff + data_section->vsize)); String8 expected_data = str8_lit("onetwothreefourfive"); if (!str8_match(data, expected_data, 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_flag_conf(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; COFF_SectionFlags my_sect0_flags = COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute; COFF_SectionFlags my_sect1_flags = COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite; String8 conf_obj_name = str8_lit("conf.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *a_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".mysect"), my_sect0_flags, str8_lit("one")); COFF_ObjSection *b_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".mysect"), my_sect1_flags, str8_lit("two")); String8 conf_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(conf_obj_name, conf_obj)) { goto exit; } } U8 entry_text[] = { 0xC3 }; String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe conf.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeaderArray my_sects = t_coff_section_header_array_from_name(scratch.arena, string_table, section_table, pe.section_count, str8_lit(".mysect")); if (my_sects.count != 2) { goto exit; } COFF_SectionHeader *my_sect0 = &my_sects.v[0]; COFF_SectionHeader *my_sect1 = &my_sects.v[1]; if (my_sect0->flags != my_sect0_flags) { goto exit; } if (my_sect1->flags != my_sect1_flags) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_invalid_bss(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; COFF_SectionFlags bss_flags = COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead; String8 bss_obj_name = str8_lit("bss.obj"); String8 bss_data = str8_lit("Hello, World"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_section(obj_writer, str8_lit(".bss"), bss_flags, bss_data); String8 bss_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(bss_obj_name, bss_obj)) { goto exit; } } String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xC3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe bss.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *bss_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".bss")); if (bss_sect == 0) { goto exit; } if (bss_sect->vsize != 0xC) { goto exit; } if (bss_sect->flags != bss_flags) { goto exit; } String8 data = str8_substr(exe, rng_1u64(bss_sect->foff, bss_sect->foff + bss_sect->vsize)); if (!str8_match(data, bss_data, 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_common_block(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 a_obj_name = str8_lit("a.obj"); U8 a_data[6] = {0}; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_common(obj_writer, str8_lit("A"), 3); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8_array_fixed(a_data)); data_sect->flags |= COFF_SectionFlag_Align1Bytes; coff_obj_writer_push_section(obj_writer, str8_lit(".bss"), PE_BSS_SECTION_FLAGS, str8(0, 1)); // shift common block's initial position coff_obj_writer_section_push_reloc(obj_writer, data_sect, 0, symbol, COFF_Reloc_X64_Addr32); String8 a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(a_obj_name, a_obj)) { goto exit; } } String8 b_obj_name = str8_lit("b.obj"); U8 b_data[9] = { 0 }; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8_array_fixed(b_data)); data_sect->flags |= COFF_SectionFlag_Align1Bytes; COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_common(obj_writer, str8_lit("B"), 6); coff_obj_writer_section_push_reloc(obj_writer, data_sect, 0, symbol, COFF_Reloc_X64_Addr64); String8 b_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(b_obj_name, b_obj)) { goto exit; } } String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0xC3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe /fixed /largeaddressaware:no /merge:.bss=.comm a.obj b.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; COFF_SectionHeader *comm_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".comm")); COFF_SectionHeader *data_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (comm_sect == 0) { goto exit; } if (data_sect == 0) { goto exit; } // blocks must be sorted in descending order to reduce alignment padding if (comm_sect->vsize != 0x13) { goto exit; } // ensure linker correctly patched addresses for symbols pointing into common block String8 data = str8_substr(exe, rng_1u64(data_sect->foff, data_sect->foff + data_sect->fsize)); U32 *a_addr = (U32 *)data.str; U64 *b_addr = (U64 *)(data.str + sizeof(a_data)); if (*a_addr != (pe.image_base + comm_sect->voff + 0x10)) { goto exit; } if (*b_addr != (pe.image_base + comm_sect->voff + 0x8)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_base_relocs(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; // main.obj String8 entry_name = str8_lit("my_entry"); U64 mov_func_name64 = 2; U64 mov_func_name32 = 16; U8 main_text[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, func_name 0xff, 0xd0, // call rax 0x48, 0x31, 0xc0, // xor rax, rax 0xb8, 0x00, 0x00, 0x00, 0x00, // mov eax, func_name 0xff, 0xd0, // call rax 0xc3 // ret }; // func.obj String8 func_name = str8_lit("foo"); U8 func_text[] = { 0xc3 }; String8 main_obj_name = str8_lit("main.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(main_text)); COFF_ObjSymbol *func_undef = coff_obj_writer_push_symbol_undef(obj_writer, func_name); coff_obj_writer_section_push_reloc(obj_writer, text_sect, mov_func_name64, func_undef, COFF_Reloc_X64_Addr64); coff_obj_writer_section_push_reloc(obj_writer, text_sect, mov_func_name32, func_undef, COFF_Reloc_X64_Addr32); // linker must not produce base relocations for absolute symbol U8 data[4] = {0}; COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8_array_fixed(data)); COFF_ObjSymbol *abs_symbol = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("abs"), 0x12345678, COFF_SymStorageClass_Static); coff_obj_writer_section_push_reloc(obj_writer, data_sect, 0, abs_symbol, COFF_Reloc_X64_Addr32); coff_obj_writer_push_symbol_extern(obj_writer, entry_name, 0, text_sect); String8 main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(main_obj_name, main_obj)) { goto exit; } } String8 func_obj_name = str8_lit("func.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(func_text)); coff_obj_writer_push_symbol_extern(obj_writer, func_name, 0, text_sect); String8 func_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(func_obj_name, func_obj)) { goto exit; } } String8 out_name = str8_lit("a.exe"); int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /dynamicbase /largeaddressaware:no /out:a.exe main.obj func.obj"); if (linker_exit_code != 0) { goto exit; } // it is illegal to merge .reloc with other sections linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /dynamicbase /largeaddressaware:no /out:a.exe /merge:.reloc=.rdata main.obj func.obj"); if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_IllegalSectionMerge) { goto exit; } } else { if (linker_exit_code == 0) { goto exit; } } // the other way around is illegal too linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /dynamicbase /largeaddressaware:no /out:a.exe /merge:.rdata=.reloc main.obj func.obj"); if (t_ident_linker() == T_Linker_RAD) { if (linker_exit_code != LNK_Error_IllegalSectionMerge) { goto exit; } } else { if (linker_exit_code == 0) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_simple_lib_test(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 test_payload = str8_lit("The quick brown fox jumps over the lazy dog"); String8 test_obj = {0}; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_Unknown); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8(test_payload.str, test_payload.size+1)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("test"), 0, data_sect); test_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 test_lib_name = str8_lit("test.lib"); { COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); coff_lib_writer_push_obj(lib_writer, str8_lit("test.obj"), test_obj); String8 test_lib = coff_lib_writer_serialize(scratch.arena, lib_writer, 0, 0, 1); coff_lib_writer_release(&lib_writer); if (!t_write_file(test_lib_name, test_lib)) { goto exit; } } U8 entry_text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xC3 }; String8 entry_obj_name = str8_lit("entry.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(entry_text)); COFF_ObjSymbol *test_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("test")); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 3, test_symbol, COFF_Reloc_X64_Addr32Nb); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 7, text_sect); String8 entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(entry_obj_name, entry_obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe entry.obj test.lib"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); COFF_SectionHeader *data_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->fsize)); String8 data_data = str8_substr(exe, rng_1u64(data_sect->foff, data_sect->foff + data_sect->fsize)); // was test payload linked? String8 data_string = str8_cstring_capped(data_data.str, data_data.str + data_data.size); if (!str8_match(data_string, test_payload, 0)) { goto exit; } // do we have enough bytes to read text? if (text_data.size < sizeof(entry_text)) { goto exit; } // linker must pull-in test.obj and patch relocation for "test" symbol U32 *data_addr32nb = (U32 *)(text_data.str+3); if (*data_addr32nb != data_sect->voff) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_import_export(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { String8 export_obj_name = str8_lit("export.obj"); String8 export_obj_payload = str8_lit("test"); U8 export_text[] = { 0xC3 }; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, export_obj_payload); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("foo"), 0, data_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("ord"), 0, data_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("ord2"), 0, data_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("ord3"), 0, data_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("ord4"), 0, data_sect); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:foo=foo")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:bar=foo")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:ord,@5")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:ord2,@6,DATA")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:ord3,@7,NONAME,PRIVATE")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:ord4,@8,NONAME,DATA")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:baz=baz.qwe")); //coff_obj_writer_push_directive(obj_writer, str8_lit("/export:baf=baz.#1")); String8 export_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(export_obj_name, export_obj)) { goto exit; } } { String8 import_obj_name = str8_lit("import.obj"); U8 import_payload[1024] = {0}; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *data_sect = t_push_data_section(obj_writer, str8_array_fixed(import_payload)); char *import_symbols[] = { "__imp_foo", "__imp_bar", "__imp_baz", "__imp_baf", "__imp_ord", //"__imp_ord2", //"__imp_ord4", "bar", //"baf", //"baz", "foo", "ord", }; for (U64 i = 0; i < ArrayCount(import_symbols); ++i) { COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_cstring(import_symbols[i])); coff_obj_writer_section_push_reloc_voff(obj_writer, data_sect, i * 4, symbol); } String8 import_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(import_obj_name, import_obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *s1 = coff_obj_writer_push_section(obj_writer, str8_lit(".s1"), PE_DATA_SECTION_FLAGS, str8_lit("s1")); COFF_ObjSection *s2 = coff_obj_writer_push_section(obj_writer, str8_lit(".s2"), PE_DATA_SECTION_FLAGS, str8_lit("s2")); COFF_ObjSection *text_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed((U8[]){ 0xC3 })); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("_DllMainCRTStartup"), 0, text_sect); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("s1"), 0, s1); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("s2"), 0, s2); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("baz.obj"), obj)) { goto exit; } } t_write_entry_obj(); // // link export.dll // int lib_link_exit_code = t_invoke_linkerf("/dll /out:export.dll libcmt.lib export.obj"); if (lib_link_exit_code != 0) { goto exit; } // // link baz.dll // int baz_link_exit_code = t_invoke_linkerf("/dll /out:baz.dll /export:s1,@1,NONAME /export:qwe=s2 baz.obj"); if (baz_link_exit_code != 0) { goto exit; } // // check export.dll export table // if (0) { String8 dll = t_read_file(scratch.arena, str8_lit("export.dll")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, dll); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(dll, pe.section_table_range).str; String8 string_table = str8_substr(dll, pe.string_table_range); PE_ParsedExportTable export_table = pe_exports_from_data(scratch.arena, pe.section_count, section_table, dll, pe.data_dir_franges[PE_DataDirectoryIndex_EXPORT], pe.data_dir_vranges[PE_DataDirectoryIndex_EXPORT]); if (export_table.export_count != 6) { goto exit; } { String8 expected_symbols[] = { str8_lit_comp("foo"), str8_lit_comp("bar"), //str8_lit_comp("baz"), //str8_lit_comp("baf"), str8_lit_comp("ord"), str8_lit_comp("ord2") }; U64 match_count = 0; for (U64 i = 0; i < export_table.export_count; i += 1) { for (U64 k = 0; k < ArrayCount(expected_symbols); k += 1) { if (str8_match(export_table.exports[i].name, expected_symbols[k], 0)) { match_count += 1; } } } if (match_count != ArrayCount(expected_symbols)) { goto exit; } } if (0) { String8 expected_forwarders[] = { str8_lit_comp("baz.qwe"), str8_lit_comp("baz.#1"), }; U64 match_count = 0; for (U64 i = 0; i < export_table.export_count; i += 1) { for (U64 k = 0; k < ArrayCount(expected_forwarders); k += 1) { if (str8_match(export_table.exports[i].forwarder, expected_forwarders[k], 0)) { match_count += 1; } } } if (match_count != ArrayCount(expected_forwarders)) { goto exit; } } } #if OS_WINDOWS BOOL is_dir_set = SetDllDirectoryA((LPCSTR)g_wdir.str); AssertAlways(is_dir_set); HANDLE export_dll = LoadLibrary("export.dll"); DWORD last_error = GetLastError(); if (export_dll == 0) { goto exit; } char *export_dll_procs[] = { "foo", "bar", "baz", "baf" }; for (U64 i = 0; i < ArrayCount(export_dll_procs); ++i) { void *proc = GetProcAddress(export_dll, export_dll_procs[i]); if (proc == 0) { goto exit; } } U16 export_dll_ordinals[] = { 5 }; for (U64 i = 0; i < ArrayCount(export_dll_ordinals); ++i) { void *proc = GetProcAddress(export_dll, MAKEINTRESOURCE(export_dll_ordinals[i])); if (proc == 0) { goto exit; } } #endif int import_link_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /delayload:export.dll /export:entry kernel32.Lib delayimp.lib libcmt.lib export.lib import.obj entry.obj"); if (import_link_exit_code != 0) { goto exit; } // TODO: check import table result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_image_base(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 obj_name = str8_lit("image_base.obj"); { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0x8D, 0x0D, 0x00, 0x00, 0x00, 0x00, // lea rcx, [__ImageBase] 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, __ImageBase 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, __ImageBase 0xC3 // ret }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); COFF_ObjSymbol *image_base_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__ImageBase")); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 3, image_base_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 9, image_base_symbol, COFF_Reloc_X64_Addr64); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 18, image_base_symbol, COFF_Reloc_X64_Addr32Nb); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(obj_name, obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /base:0x2000000140000000 /out:a.exe image_base.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_section = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (!text_section) { goto exit; } U8 expected_text[] = { 0x48, 0x8D, 0x0D, 0xF9, 0xEF, 0xFF, 0xFF, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x20, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xC3 }; String8 text_data = str8_substr(exe, rng_1u64(text_section->foff, text_section->foff + sizeof(expected_text))); if (!str8_match(text_data, str8_array_fixed(expected_text), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_any(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".test$mn"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("1")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Any); COFF_ObjSymbol *test = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); test->type.u.msb = COFF_SymDType_Func; String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("1.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".test$mn"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("2")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Any); COFF_ObjSymbol *test = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("2.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } { int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:1.exe 1.obj 2.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("1.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".test")); String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("1"), 0)) { goto exit; } } { int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:2.exe 2.obj 1.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("2.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".test")); String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("2"), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_no_duplicates(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 test_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *test_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".test"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("a")); coff_obj_writer_push_symbol_secdef(obj_writer, test_sect, COFF_ComdatSelect_NoDuplicates); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("a"), 0, test_sect); test_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("a")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } if (!t_write_file(str8_lit("a.obj"), test_obj)) { goto exit; } if (!t_write_file(str8_lit("b.obj"), test_obj)) { goto exit; } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } int duplicates_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj"); if (duplicates_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && duplicates_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } int good_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe a.obj entry.obj"); if (good_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("b.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".test")); if (!sect) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("a"), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_same_size(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("a")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_SameSize); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".b"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("b")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_SameSize); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".c"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("cc")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_SameSize); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("c.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int same_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj"); if (same_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a")); if (sect == 0) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("a"), 0)) { goto exit; } } int not_same_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe a.obj b.obj c.obj entry.obj"); if (not_same_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && not_same_exit_code != LNK_Error_MultiplyDefinedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_exact_match(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("a")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_ExactMatch); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".a2"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("a")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_ExactMatch); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a2.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".b"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("b")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_ExactMatch); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int not_exact_match = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj b.obj"); if (not_exact_match == 0) { goto exit; } int exact_match = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe entry.obj a2.obj a.obj"); if (exact_match != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("b.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a2")); if (sect == 0) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("a"), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_largest(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("a")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".b"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("bb")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".c"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("c")); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("c.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int largest_exit_code = t_invoke_linkerf("/subsystem:console /out:a.exe /entry:entry entry.obj a.obj b.obj"); if (largest_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *discard_sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a")); if (discard_sect != 0) { goto exit; } COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".b")); if (sect == 0) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("bb"), 0)) { goto exit; } } int same_size_exit_code = t_invoke_linkerf("/subsystem:console /out:b.exe /entry:entry entry.obj c.obj a.obj"); if (same_size_exit_code != 0) { goto exit; } { String8 exe = t_read_file(scratch.arena, str8_lit("b.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".c")); if (sect == 0) { goto exit; } String8 data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); if (!str8_match(data, str8_lit("c"), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_associative(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSection *a = coff_obj_writer_push_section(obj_writer, str8_lit("a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("a")); COFF_ObjSection *aa = coff_obj_writer_push_section(obj_writer, str8_lit("aa"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("aa")); coff_obj_writer_push_symbol_secdef(obj_writer, a, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, a); coff_obj_writer_push_symbol_associative(obj_writer, aa, a); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSection *bb = coff_obj_writer_push_section(obj_writer, str8_lit("bb"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("bb")); COFF_ObjSection *b = coff_obj_writer_push_section(obj_writer, str8_lit("b"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("b")); COFF_ObjSection *bbb = coff_obj_writer_push_section(obj_writer, str8_lit("bbb"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("bbb")); coff_obj_writer_push_symbol_secdef(obj_writer, bb, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_associative(obj_writer, b, bb); coff_obj_writer_push_symbol_associative(obj_writer, bbb, bb); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, bb); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj b.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *a = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit("a")); COFF_SectionHeader *aa = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit("aa")); COFF_SectionHeader *b = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit("b")); COFF_SectionHeader *bb = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit("bb")); COFF_SectionHeader *bbb = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit("bbb")); if (a != 0) { goto exit; } if (aa != 0) { goto exit; } if (b == 0) { goto exit; } if (bb == 0) { goto exit; } if (bbb == 0) { goto exit; } String8 b_data = str8_substr(exe, rng_1u64(b->foff, b->foff + b->vsize)); String8 bb_data = str8_substr(exe, rng_1u64(bb->foff, bb->foff + bb->vsize)); String8 bbb_data = str8_substr(exe, rng_1u64(bbb->foff, bbb->foff + bbb->vsize)); if (!str8_match(b_data, str8_lit("b"), 0)) { goto exit; } if (!str8_match(bb_data, str8_lit("bb"), 0)) { goto exit; } if (!str8_match(bbb_data, str8_lit("bbb"), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_associative_loop(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *aaaa = coff_obj_writer_push_section(obj_writer, str8_lit(".aaaa"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("aaaa")); COFF_ObjSection *aa = coff_obj_writer_push_section(obj_writer, str8_lit(".aa"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("aa")); COFF_ObjSection *a = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("a")); COFF_ObjSection *aaa = coff_obj_writer_push_section(obj_writer, str8_lit(".aaa"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT|COFF_SectionFlag_Align1Bytes, str8_lit("aaa")); coff_obj_writer_push_symbol_associative(obj_writer, aaa, aa); coff_obj_writer_push_symbol_associative(obj_writer, aaaa, aaa); coff_obj_writer_push_symbol_associative(obj_writer, a, aa); coff_obj_writer_push_symbol_associative(obj_writer, aa, a); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("loop.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe loop.obj entry.obj"); if (exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && exit_code != LNK_Error_AssociativeLoop) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_associative_non_comdat(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *a = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS, str8_lit("a")); COFF_ObjSection *b = coff_obj_writer_push_section(obj_writer, str8_lit(".b"), PE_DATA_SECTION_FLAGS, str8_lit("b")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, a); coff_obj_writer_push_symbol_associative(obj_writer, b, a); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("test.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj test.obj"); if (exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *a = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a")); COFF_SectionHeader *b = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".b")); if (a == 0) { goto exit; } if (b == 0) { goto exit; } String8 a_data = str8_substr(exe, rng_1u64(a->foff, a->foff + a->vsize)); String8 b_data = str8_substr(exe, rng_1u64(b->foff, b->foff + b->vsize)); if (!str8_match(a_data, str8_lit("a"), 0)) { goto exit; } if (!str8_match(b_data, str8_lit("b"), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_associative_out_of_bounds(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSection *a = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("a")); COFF_ObjSection *aa = coff_obj_writer_push_section(obj_writer, str8_lit(".aa"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_lit("aa")); coff_obj_writer_push_symbol_secdef(obj_writer, a, COFF_ComdatSelect_Any); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, a); coff_obj_writer_push_symbol_associative(obj_writer, aa, a); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); { COFF_FileHeaderInfo header = coff_file_header_info_from_data(obj); String8 string_table = str8_substr(obj, header.string_table_range); String8 symbol_table = str8_substr(obj, header.symbol_table_range); COFF_ParsedSymbol symbol = coff_parse_symbol(header, string_table, symbol_table, 3); AssertAlways(str8_match(symbol.name, str8_lit(".aa"), 0)); AssertAlways(symbol.aux_symbol_count == 1); COFF_Symbol16 *symbol16 = symbol.raw_symbol; COFF_SymbolSecDef *secdef = (COFF_SymbolSecDef *)(symbol16 + 1); secdef->number_lo = 321; } coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("bad.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj bad.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && linker_exit_code != LNK_Error_IllData) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_comdat_with_offset(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 a[] = "1Hello, World!"; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(a)); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 1, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 a[] = "Hello, World!"; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(a)); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 1, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 3, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_reloc_against_removed_comdat(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 a[] = "1Hello, World!"; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(a)); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 1, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 a[] = "H"; COFF_ObjSection *comdat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS|COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(a)); coff_obj_writer_push_symbol_secdef(obj_writer, comdat_sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 1, comdat_sect); COFF_ObjSymbol *static_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("STATIC"), 2, comdat_sect); U8 rdata[4] = {0}; COFF_ObjSection *regular_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), PE_RDATA_SECTION_FLAGS, str8_array_fixed(rdata)); coff_obj_writer_section_push_reloc_voff(obj_writer, regular_sect, 0, static_symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 3, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj c.obj entry.obj"); if (linker_exit_code != LNK_Error_RelocationAgainstRemovedSection) { goto exit; } exit:; result = T_Result_Pass; scratch_end(scratch); return result; } internal T_Result t_sect_align(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect_align_shift = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS, str8_lit("q")); COFF_ObjSection *sect_align_none = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS, str8_lit("abc")); COFF_ObjSection *sect_align_1 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_lit("wr")); COFF_ObjSection *sect_align_2 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_lit("e")); COFF_ObjSection *sect_align_4 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_lit("ttttt")); COFF_ObjSection *sect_align_8 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align8Bytes, str8_lit("g")); COFF_ObjSection *sect_align_16 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align16Bytes, str8_lit("o")); COFF_ObjSection *sect_align_32 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align32Bytes, str8_lit("p")); COFF_ObjSection *sect_align_64 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align64Bytes, str8_lit("f")); COFF_ObjSection *sect_align_128 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align128Bytes, str8_lit("x")); COFF_ObjSection *sect_align_256 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align256Bytes, str8_lit("c")); COFF_ObjSection *sect_align_512 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align512Bytes, str8_lit("v")); COFF_ObjSection *sect_align_1024 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align1024Bytes, str8_lit("b")); COFF_ObjSection *sect_align_2048 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align2048Bytes, str8_lit("n")); COFF_ObjSection *sect_align_4096 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4096Bytes, str8_lit("m")); COFF_ObjSection *sect_align_8192 = coff_obj_writer_push_section(obj_writer, str8_lit(".a"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align8192Bytes, str8_lit("z")); U8 text[] = { 0xC3 }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("test.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe /align:8192 test.obj"); String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".a")); if (!sect) { goto exit; } String8 sect_data = str8_substr(exe, rng_1u64(sect->foff, sect->foff + sect->vsize)); String8 shift = str8_substr(sect_data, rng_1u64(0, 1)); if (!str8_match(shift, str8_lit("q"), 0)) { goto exit; } String8 a_none = str8_substr(sect_data, rng_1u64(16, 16 + 3)); if (!str8_match(a_none, str8_lit("abc"), 0)) { goto exit; } String8 a_1 = str8_substr(sect_data, rng_1u64(19, 21)); if (!str8_match(a_1, str8_lit("wr"), 0)) { goto exit; } String8 a_2 = str8_substr(sect_data, rng_1u64(22, 23)); if (!str8_match(a_2, str8_lit("e"), 0)) { goto exit; } String8 a_4 = str8_substr(sect_data, rng_1u64(24, 29)); if (!str8_match(a_4, str8_lit("ttttt"), 0)) { goto exit; } String8 a_8 = str8_substr(sect_data, rng_1u64(32, 33)); if (!str8_match(a_8, str8_lit("g"), 0)) { goto exit; } String8 a_16 = str8_substr(sect_data, rng_1u64(48, 49)); if (!str8_match(a_16, str8_lit("o"), 0)) { goto exit; } String8 a_32 = str8_substr(sect_data, rng_1u64(64, 65)); if (!str8_match(a_32, str8_lit("p"), 0)) { goto exit; } String8 a_64 = str8_substr(sect_data, rng_1u64(128, 129)); if (!str8_match(a_64, str8_lit("f"), 0)) { goto exit; } String8 a_128 = str8_substr(sect_data, rng_1u64(256, 257)); if (!str8_match(a_128, str8_lit("x"), 0)) { goto exit; } String8 a_256 = str8_substr(sect_data, rng_1u64(512, 513)); if (!str8_match(a_256, str8_lit("c"), 0)) { goto exit; } String8 a_512 = str8_substr(sect_data, rng_1u64(1024, 1025)); if (!str8_match(a_512, str8_lit("v"), 0)) { goto exit; } String8 a_1024 = str8_substr(sect_data, rng_1u64(2048, 2049)); if (!str8_match(a_1024, str8_lit("b"), 0)) { goto exit; } String8 a_2048 = str8_substr(sect_data, rng_1u64(4096, 4097)); if (!str8_match(a_2048, str8_lit("n"), 0)) { goto exit; } String8 a_4096 = str8_substr(sect_data, rng_1u64(8192, 8193)); if (!str8_match(a_4096, str8_lit("m"), 0)) { goto exit; } String8 a_8192 = str8_substr(sect_data, rng_1u64(16384, 16385)); if (!str8_match(a_8192, str8_lit("z"), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_alt_name(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_lit("test")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("test"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("test.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_lit("foo")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("foo"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("foo.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("foo")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code; // basic alternate name test linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /alternatename:foo=test test.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } // linker should not chase alt name links linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe /alternatename:foo=bar /alternatename:bar=test test.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // alt name conflict linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:c.exe /alternatename:foo=test /alternatename:foo=qwe test.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:d.exe /alternatename:foo foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:e.exe /alternatename:foo-oof foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /alternatename:foo=test=bar foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /alternatename:foo= foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /alternatename:= foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // syntax error linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /alternatename: foo.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } // TODO: check that RAD Linker prints these warnings // warn about alt name to self alt name? linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:f.exe /alternatename:foo=foo foo.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } // warn about alt name to unknown symbol? linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:g.exe /alternatename:qwe=ewq foo.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_include(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_lit("foo")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("foo"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("include.obj"), obj)) { goto exit; } COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); coff_lib_writer_push_obj(lib_writer, str8_lit("include.obj"), obj); String8 lib = coff_lib_writer_serialize(scratch.arena, lib_writer, 0, 0, 1); coff_lib_writer_release(&lib_writer); if (!t_write_file(str8_lit("include.lib"), lib)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code; // simple include test linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /include:foo entry.obj include.lib"); if (linker_exit_code != 0) { goto exit; } // validate that linker pulled-in include.obj { String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *foo_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (foo_sect == 0) { goto exit; } String8 foo_data = str8_substr(exe, rng_1u64(foo_sect->foff, foo_sect->foff + foo_sect->vsize)); if (!str8_match(foo_data, str8_lit("foo"), 0)) { goto exit; } } // test unresolved include linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /include:ewq entry.obj"); if (linker_exit_code == 0) { goto exit; } if (t_ident_linker() == T_Linker_RAD && linker_exit_code != LNK_Error_UnresolvedSymbol) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_communal_var_vs_regular(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_common(obj_writer, str8_lit("TEST"), 1); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("communal.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_lit("test")); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("defn.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } // linker should replace communal TEST with .data TEST int linker_exit_code; linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe communal.obj defn.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe defn.obj communal.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } char *exes[] = { "a.exe", "b.exe" }; for (U64 i = 0; i < ArrayCount(exes); i += 1) { String8 exe = t_read_file(scratch.arena, str8_cstring(exes[i])); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *data_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (!data_sect) { goto exit; } String8 data = str8_substr(exe, rng_1u64(data_sect->foff, data_sect->foff + data_sect->vsize)); if (!str8_match(data, str8_lit("test"), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_communal_var_vs_regular_comdat(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_common(obj_writer, str8_lit("TEST"), 1); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("communal.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *sect = t_push_data_section(obj_writer, str8_lit("test")); sect->flags |= COFF_SectionFlag_LnkCOMDAT; coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("large.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } // linker should replace communal TEST with .data TEST int linker_exit_code; linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe communal.obj large.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe large.obj communal.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } char *exes[] = { "a.exe", "b.exe" }; for (U64 i = 0; i < ArrayCount(exes); i += 1) { String8 exe = t_read_file(scratch.arena, str8_cstring(exes[i])); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *data_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".data")); if (!data_sect) { goto exit; } String8 data = str8_substr(exe, rng_1u64(data_sect->foff, data_sect->foff + data_sect->vsize)); if (!str8_match(data, str8_lit("test"), 0)) { goto exit; } } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_import_kernel32(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 data[] = "test"; U8 text[] = { 0x48, 0x83, 0xec, 0x68, // sub rsp,68h ; alloc space on stack 0xc7, 0x44, 0x24, 0x48, 0x18, 0x00, 0x00, 0x00, // mov dword ptr [rsp+48h],18h ; SECURITY_ATTRIBUTES.nLength 0x48, 0xc7, 0x44, 0x24, 0x50, 0x00, 0x00, 0x00, 0x00, // mov qword ptr [rsp+50h],0 ; SECURITY_ATTRIBUTES.lpSecurityDescriptor 0xc7, 0x44, 0x24, 0x58, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [rsp+58h],0 ; SECURITY_ATTRIBUTES.bInheritHandle 0x48, 0xc7, 0x44, 0x24, 0x30, 0x00, 0x00, 0x00, 0x00, // mov qword ptr [rsp+30h],0 ; hTemplateFile 0xc7, 0x44, 0x24, 0x28, 0x80, 0x00, 0x00, 0x00, // mov dword ptr [rsp+28h],80h ; dwFlagsAndAttributes 0xc7, 0x44, 0x24, 0x20, 0x02, 0x00, 0x00, 0x00, // mov dword ptr [rsp+20h],2 ; dwCreationDisposition 0x4c, 0x8d, 0x4c, 0x24, 0x48, // lea r9,[rsp+48h] ; lpSecurityAttributes 0x45, 0x33, 0xc0, // xor r8d,r8d ; dwShareMode 0xba, 0x00, 0x00, 0x00, 0x40, // mov edx,40000000h ; dwDesiredAccess 0x48, 0x8d, 0x0d, 0x00, 0x00, 0x00, 0x00, // lea rcx,[test] ; lpFileName 0xff, 0x15, 0x00, 0x00, 0x00, 0x00, // call qword ptr [__imp_CreateFileA] ; call CreateFileA 0x48, 0x89, 0xc1, // mov rcx,rax ; hObject 0xff, 0x15, 0x00, 0x00, 0x00, 0x00, // call qword ptr [__imp_CloseHandle] ; call CloseHandle 0x33, 0xc0, // xor eax,eax ; clear result 0x48, 0x83, 0xc4, 0x68, // add rsp,68h ; dealloc stack 0xc3 // ret ; return }; COFF_ObjSection *data_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data"), PE_DATA_SECTION_FLAGS, str8_array_fixed(data)); COFF_ObjSection *text_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); COFF_ObjSymbol *data_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("test"), 0, data_sect); COFF_ObjSymbol *entry_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); COFF_ObjSymbol *create_file_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__imp_CreateFileA")); COFF_ObjSymbol *close_handle_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__imp_CloseHandle")); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 70, data_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 76, create_file_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 85, close_handle_symbol, COFF_Reloc_X64_Rel32); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("import.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /fixed import.obj kernel32.lib"); if (linker_exit_code != 0) { goto exit; } #if OS_WINDOWS { String8 test_file_path = push_str8f(scratch.arena, "%S/test", g_wdir); os_delete_file_at_path(test_file_path); OS_ProcessLaunchParams launch_opts = {0}; launch_opts.inherit_env = 0; launch_opts.path = g_wdir; str8_list_pushf(scratch.arena, &launch_opts.cmd_line, "%S/a.exe", g_wdir); OS_Handle handle = os_process_launch(&launch_opts); AssertAlways(!os_handle_match(handle, os_handle_zero())); U64 exit_code = max_U64; os_process_join(handle, max_U64, &exit_code); os_process_detach(handle); if (exit_code != 0) { goto exit; } if (!os_file_path_exists(test_file_path)) { goto exit; } } #endif result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_delay_import(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 return_0[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, 0 0xc3 // ret }; U8 return_1[] = { 0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, // mov rax, 1 0xc3 // ret }; U8 return_2[] = { 0x48, 0xC7, 0xC0, 0x02, 0x00, 0x00, 0x00, // mov rax, 2 0xc3 // ret }; COFF_ObjSection *return_0_sect = t_push_text_section(obj_writer, str8_array_fixed(return_0)); COFF_ObjSection *return_1_sect = t_push_text_section(obj_writer, str8_array_fixed(return_1)); COFF_ObjSection *return_2_sect = t_push_text_section(obj_writer, str8_array_fixed(return_2)); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("return_1"), 0, return_1_sect); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("return_2"), 0, return_2_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("a.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 return_0[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, 0 0xc3 // ret }; U8 return_123[] = { 0x48, 0xC7, 0xC0, 0x7B, 0x00, 0x00, 0x00, // mov rax, 123 0xc3 // ret }; U8 return_321[] = { 0x48, 0xC7, 0xC0, 0x41, 0x01, 0x00, 0x00, // mov rax, 321 0xc3 // ret }; COFF_ObjSection *return_0_sect = t_push_text_section(obj_writer, str8_array_fixed(return_0)); COFF_ObjSection *return_123_sect = t_push_text_section(obj_writer, str8_array_fixed(return_123)); COFF_ObjSection *return_321_sect = t_push_text_section(obj_writer, str8_array_fixed(return_321)); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("return_123"), 0, return_123_sect); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("return_321"), 0, return_321_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("b.obj"), obj)) { goto exit; } } { U8 text[] = { 0x56, // push rsi 0x57, // push rdi 0x48, 0x83, 0xEC, 0x28, // sub rsp,28h 0xE8, 0x00, 0x00, 0x00, 0x00, // call return_1 0x89, 0xC6, // mov esi,eax 0xE8, 0x00, 0x00, 0x00, 0x00, // call return_2 0x89, 0xC7, // mov edi,eax 0x01, 0xF7, // add edi,esi 0xE8, 0x00, 0x00, 0x00, 0x00, // call return_123 0x89, 0xC6, // mov esi,eax 0xE8, 0x00, 0x00, 0x00, 0x00, // call return_321 0x01, 0xF0, // add eax,esi 0x01, 0xF8, // add eax,edi 0x48, 0x83, 0xC4, 0x28, // add rsp,28h 0x5F, // pop rdi 0x5E, // pop rsi 0xC3, // ret }; COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_X64); COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); COFF_ObjSymbol *return_1_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("return_1")); COFF_ObjSymbol *return_2_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("return_2")); COFF_ObjSymbol *return_123_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("return_123")); COFF_ObjSymbol *return_321_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("return_321")); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 7, return_1_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 14, return_2_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 23, return_123_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 30, return_321_symbol, COFF_Reloc_X64_Rel32); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("main.obj"), obj)) { goto exit; } } int linker_exit_code; linker_exit_code = t_invoke_linkerf("/dll /implib:a.lib /export:return_1 /export:return_2 a.obj libcmt.lib"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/dll /implib:b.lib /export:return_123 /export:return_321 b.obj libcmt.lib"); if (linker_exit_code != 0) { goto exit; } linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /fixed /debug:full main.obj a.lib b.lib kernel32.lib delayimp.lib libcmt.lib /delayload:a.dll /delayload:b.dll"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); PE_ParsedDelayImportTable delay_import_table = pe_delay_imports_from_data(scratch.arena, pe.is_pe32, pe.section_count, section_table, exe, pe.data_dir_franges[PE_DataDirectoryIndex_DELAY_IMPORT]); PE_ParsedDelayDLLImport *a_import = &delay_import_table.v[0]; if (a_import->attributes != 1) { goto exit; } if (!str8_match(a_import->name, str8_lit("a.dll"), 0)) { goto exit; } if (a_import->module_handle_voff == 0) { goto exit; } if (a_import->name_table_voff == 0) { goto exit; } if (a_import->bound_table_voff != 0) { goto exit; } if (a_import->unload_table_voff != 0) { goto exit; } if (a_import->time_stamp != 0) { goto exit; } if (a_import->bound_table_count != 0) { goto exit; } if (a_import->unload_table_count != 0) { goto exit; } if (a_import->import_count != 2) { goto exit; } PE_ParsedImport *return_1 = &a_import->imports[0]; if (return_1->type != PE_ParsedImport_Name) { goto exit; } if (!str8_match(return_1->u.name.string, str8_lit("return_1"), 0)) { goto exit; } if (return_1->u.name.hint != 0) { goto exit; } PE_ParsedImport *return_2 = &a_import->imports[1]; if (return_2->type != PE_ParsedImport_Name) { goto exit; } if (!str8_match(return_2->u.name.string, str8_lit("return_2"), 0)) { goto exit; } if (return_2->u.name.hint != 1) { goto exit; } PE_ParsedDelayDLLImport *b_import = &delay_import_table.v[1]; if (b_import->attributes != 1) { goto exit; } if (!str8_match(b_import->name, str8_lit("b.dll"), 0)) { goto exit; } if (b_import->module_handle_voff == 0) { goto exit; } if (b_import->name_table_voff == 0) { goto exit; } if (b_import->bound_table_voff != 0) { goto exit; } if (b_import->unload_table_voff != 0) { goto exit; } if (b_import->time_stamp != 0) { goto exit; } if (b_import->bound_table_count != 0) { goto exit; } if (b_import->unload_table_count != 0) { goto exit; } if (b_import->import_count != 2) { goto exit; } PE_ParsedImport *return_123 = &b_import->imports[0]; if (return_123->type != PE_ParsedImport_Name) { goto exit; } if (!str8_match(return_123->u.name.string, str8_lit("return_123"), 0)) { goto exit; } if (return_123->u.name.hint != 0) { goto exit; } PE_ParsedImport *return_321 = &b_import->imports[1]; if (return_321->type != PE_ParsedImport_Name) { goto exit; } if (!str8_match(return_321->u.name.string, str8_lit("return_321"), 0)) { goto exit; } if (return_321->u.name.hint != 1) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_delay_import_user32(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *data_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".str"), PE_DATA_SECTION_FLAGS, str8_zero()); U64 msg_off = data_sect->data.total_size; str8_list_pushf(obj_writer->arena, &data_sect->data, "test\0"); U64 caption_off = data_sect->data.total_size; str8_list_pushf(obj_writer->arena, &data_sect->data, "foo\0"); COFF_ObjSymbol *msg_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("msg"), msg_off, data_sect); COFF_ObjSymbol *caption_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("caption"), caption_off, data_sect); U8 text[] = { 0x48, 0x83, 0xEC, 0x28, // sub rsp,28h 0x45, 0x33, 0xC9, // xor r9d,r9d 0x4C, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00, // lea r8,[msg] 0x48, 0x8D, 0x15, 0x00, 0x00, 0x00, 0x00, // lea rdx,[caption] 0x33, 0xC9, // xor ecx,ecx 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call qword ptr [__imp_MessageBoxA] 0x33, 0xC0, // xor eax,eax 0x48, 0x83, 0xC4, 0x28, // add rsp,28h 0xC3, // ret }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); COFF_ObjSymbol *text_symbol = coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); COFF_ObjSymbol *message_box_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__imp_MessageBoxA")); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 10, msg_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 17, caption_symbol, COFF_Reloc_X64_Rel32); coff_obj_writer_section_push_reloc(obj_writer, text_sect, 25, message_box_symbol, COFF_Reloc_X64_Rel32); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("delay_import.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /out:a.exe /entry:entry /fixed /delayload:user32.dll kernel32.lib user32.lib libcmt.lib delayimp.lib delay_import.obj /debug:full"); if (linker_exit_code != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_empty_section(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); COFF_ObjSection *test = coff_obj_writer_push_section(obj_writer, str8_lit(".test"), PE_TEXT_SECTION_FLAGS, str8(0,0)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, test); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("empty_section.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); COFF_ObjSymbol *test_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, text_sect, 3, test_symbol); // relocation against removed section coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe empty_section.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_removed_section(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 test_text[] = { 0xc3 }; COFF_ObjSection *test_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".test"), PE_TEXT_SECTION_FLAGS | COFF_SectionFlag_LnkRemove, str8_array_fixed(test_text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("TEST"), 0, test_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("test.obj"), obj)) { goto exit; } } { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(text)); COFF_ObjSymbol *test_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("TEST")); coff_obj_writer_section_push_reloc_voff(obj_writer, text_sect, 3, test_symbol); // relocation against removed section coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, text_sect); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("entry.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe test.obj entry.obj"); if (linker_exit_code == 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_function_pad_min(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 ret[] = { 0xc3 }; COFF_ObjSection *text_sect_0 = t_push_text_section(obj_writer, str8_array_fixed(ret)); COFF_ObjSection *text_sect_1 = t_push_text_section(obj_writer, str8_array_fixed(ret)); COFF_ObjSection *text_sect_2 = t_push_text_section(obj_writer, str8_array_fixed(ret)); text_sect_0->flags |= COFF_SectionFlag_Align4Bytes; text_sect_1->flags |= COFF_SectionFlag_Align2Bytes; coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("A"), 0, text_sect_0); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("B"), 0, text_sect_1); coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("C"), 0, text_sect_2); String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); if (!t_write_file(str8_lit("funcs.obj"), obj)) { goto exit; } } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:A /functionpadmin:1 /out:a.exe funcs.obj"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text")); if (text_sect == 0) { goto exit; } String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize)); U8 expected_text[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xc3, 0xcc, 0xcc, 0xcc, 0xc3, 0xcc, 0xc3, }; if (!str8_match(text_data, str8_array_fixed(expected_text), 0)) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_first_member_header(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("8"), 0x8, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("1"), 0x1, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("9"), 0x9, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("7"), 0x7, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("4"), 0x4, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("5"), 0x5, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("2"), 0x2, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("3"), 0x3, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("6"), 0x6, COFF_SymStorageClass_External); obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 lib; { COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); coff_lib_writer_push_obj(lib_writer, str8_lit("obj.obj"), obj); lib = coff_lib_writer_serialize(scratch.arena, lib_writer, 0, 0, 0); coff_lib_writer_release(&lib_writer); } t_write_file(str8_lit("test.lib"), lib); t_write_entry_obj(); int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe test.lib entry.obj /include:1 /include:2 /include:3 /include:4 /include:5 /include:6 /include:7 /include:8 /include:9"); if (linker_exit_code != 0) goto exit; result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_second_member_header(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("8"), 0x8, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("1"), 0x1, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("9"), 0x9, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("7"), 0x7, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("4"), 0x4, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("5"), 0x5, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("2"), 0x2, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("3"), 0x3, COFF_SymStorageClass_External); coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("6"), 0x6, COFF_SymStorageClass_External); obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 lib; { COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); coff_lib_writer_push_obj(lib_writer, str8_lit("obj.obj"), obj); lib = coff_lib_writer_serialize(scratch.arena, lib_writer, 0, 0, 1); coff_lib_writer_release(&lib_writer); } t_write_file(str8_lit("test.lib"), lib); t_write_entry_obj(); int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe test.lib entry.obj /include:1 /include:2 /include:3 /include:4 /include:5 /include:6 /include:7 /include:8 /include:9"); if (linker_exit_code != 0) goto exit; result = T_Result_Pass; exit:; scratch_end(scratch); return result; } internal T_Result t_opt_ref_dangling_section(void) { Temp scratch = scratch_begin(0,0); T_Result result = T_Result_Fail; String8 entry_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 text[] = { 0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00, // mov rax, $imm 0xC3 // ret }; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_array_fixed(text)); COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("f")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, symbol); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("entry"), 0, sect); entry_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 a_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 data[] = "A0000"; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data"), PE_DATA_SECTION_FLAGS | COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(data)); COFF_ObjSymbol *q = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("q")); coff_obj_writer_section_push_reloc_voff(obj_writer, sect, 0, q); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("f"), 0, sect); a_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 b_obj; { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 q[] = { 1,2,3,4}; COFF_ObjSection *q_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".q"), PE_DATA_SECTION_FLAGS, str8_array_fixed(q)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("q"), 0, q_sect); U8 data[] = "BBBBBBBBBBBBBBB"; COFF_ObjSection *sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data"), PE_DATA_SECTION_FLAGS | COFF_SectionFlag_LnkCOMDAT, str8_array_fixed(data)); coff_obj_writer_push_symbol_secdef(obj_writer, sect, COFF_ComdatSelect_Largest); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("f"), 0, sect); b_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); coff_obj_writer_release(&obj_writer); } String8 b_lib; { COFF_LibWriter *lib_writer = coff_lib_writer_alloc(); coff_lib_writer_push_obj(lib_writer, str8_lit("b.obj"), b_obj); b_lib = coff_lib_writer_serialize(scratch.arena, lib_writer, 0, 0, 1); coff_lib_writer_release(&lib_writer); } if (!t_write_file(str8_lit("entry.obj"), entry_obj)) { goto exit; } if (!t_write_file(str8_lit("a.obj"), a_obj)) { goto exit; } if (!t_write_file(str8_lit("b.lib"), b_lib)) { goto exit; } int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj a.obj b.lib"); if (linker_exit_code != 0) { goto exit; } String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str; String8 string_table = str8_substr(exe, pe.string_table_range); COFF_SectionHeader *sect = t_coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".q")); if (sect != 0) { goto exit; } result = T_Result_Pass; exit:; scratch_end(scratch); return result; } //////////////////////////////////////////////////////////////// internal void entry_point(CmdLine *cmdline) { Temp scratch = scratch_begin(0,0); // // Test Targets // static struct { char *label; T_Result (*r)(void); } target_array[] = { { "simple_link_test", t_simple_link_test }, { "machine_compat_check", t_machine_compat_check }, { "out_of_bounds_section_number", t_out_of_bounds_section_number }, { "merge", t_merge }, { "undef_section", t_undef_section }, { "undef_reloc_section", t_undef_reloc_section }, { "link_undef", t_link_undef }, { "link_unref_undef", t_link_unref_undef }, { "weak_lib_vs_weak_lib", t_weak_lib_vs_weak_lib }, { "weak_lib_vs_weak_nolib", t_weak_lib_vs_weak_nolib }, { "weak_lib_vs_weak_alias", t_weak_lib_vs_weak_alias }, { "weak_lib_vs_weak_antidep", t_weak_lib_vs_weak_antidep }, { "weak_alias_vs_weak_alias", t_weak_alias_vs_weak_alias }, { "weak_alias_vs_weak_lib", t_weak_alias_vs_weak_lib }, { "weak_alias_vs_weak_nolib", t_weak_alias_vs_weak_nolib }, { "weak_alias_vs_weak_antidep", t_weak_alias_vs_weak_antidep }, { "weak_nolib_vs_weak_nolib", t_weak_nolib_vs_weak_nolib }, { "weak_nolib_vs_weak_lib", t_weak_nolib_vs_weak_lib }, { "weak_nolib_vs_weak_alias", t_weak_nolib_vs_weak_alias }, { "weak_nolib_vs_weak_antidep", t_weak_nolib_vs_weak_antidep }, { "weak_antidep_vs_weak_antidep", t_weak_antidep_vs_weak_antidep }, { "weak_antidep_vs_weak_nolib", t_weak_antidep_vs_weak_nolib }, { "weak_antidep_vs_weak_lib", t_weak_antidep_vs_weak_lib }, { "weak_antidep_vs_weak_alias", t_weak_antidep_vs_weak_alias }, { "weak_vs_common", t_weak_vs_common }, { "abs_vs_weak", t_abs_vs_weak }, { "abs_vs_regular", t_abs_vs_regular }, { "abs_vs_common", t_abs_vs_common }, { "abs_vs_abs", t_abs_vs_abs }, { "undef_weak_lib", t_undef_weak_lib }, { "undef_weak_search_alias", t_undef_weak_search_alias }, { "sect_symbol", t_sect_symbol }, { "weak_cycle", t_weak_cycle }, { "weak_tag", t_weak_tag }, { "find_merged_pdata", t_find_merged_pdata }, { "section_sort", t_section_sort }, { "flag_conf", t_flag_conf }, { "invalid_bss", t_invalid_bss }, { "common_block", t_common_block }, { "base_relocs", t_base_relocs }, { "simple_lib_test", t_simple_lib_test }, { "sect_align", t_sect_align }, { "image_base", t_image_base }, { "comdat_any", t_comdat_any }, { "comdat_no_duplicates", t_comdat_no_duplicates }, { "comdat_same_size", t_comdat_same_size }, { "comdat_exact_match", t_comdat_exact_match }, { "comdat_largest", t_comdat_largest }, { "comdat_associative", t_comdat_associative }, { "comdat_associative_loop", t_comdat_associative_loop }, { "comdat_associative_non_comdat", t_comdat_associative_non_comdat }, { "comdat_associative_out_of_bounds", t_comdat_associative_out_of_bounds }, { "comdat_with_offset", t_comdat_with_offset }, { "reloc_against_removed_comdat", t_reloc_against_removed_comdat }, { "alt_name", t_alt_name }, { "include", t_include }, { "communal_var_vs_regular_comdat", t_communal_var_vs_regular_comdat }, { "communal_var_vs_regular", t_communal_var_vs_regular }, { "import_kernel32", t_import_kernel32 }, { "delay_import_user32", t_delay_import_user32 }, { "delay_import", t_delay_import }, { "empty_section", t_empty_section }, { "removed_section", t_removed_section }, { "function_pad_min", t_function_pad_min }, { "first_member_header", t_first_member_header }, { "second_member_header", t_second_member_header }, }; // // Handle -help // { B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) || cmd_line_has_flag(cmdline, str8_lit("h")); if (print_help) { fprintf(stderr, "--- Help -----------------------------------------------------------------------\n"); fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL); fprintf(stderr, " Usage: torture [Options] [Files]\n\n"); fprintf(stderr, " Options:\n"); fprintf(stderr, " -linker:{path} Path to PE/COFF linker\n"); fprintf(stderr, " -target:{name[,name]} Selects targets to test\n"); fprintf(stderr, " -list Print available test targets and exit\n"); fprintf(stderr, " -out:{path} Directory path for test outputs (default \"%.*s\")\n", str8_varg(g_out)); fprintf(stderr, " -verbose Enable verbose mode\n"); fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n"); fprintf(stderr, " -help Print help menu and exit\n"); os_abort(0); } } // // Handle -list // { if (cmd_line_has_flag(cmdline, str8_lit("list"))) { fprintf(stdout, "--- Targets --------------------------------------------------------------------\n"); for (U64 i = 0; i < ArrayCount(target_array); i += 1) { fprintf(stdout, " %s\n", target_array[i].label); } os_abort(0); } } // // Handle -linker // { CmdLineOpt *linker_opt = cmd_line_opt_from_string(cmdline, str8_lit("linker")); if (linker_opt == 0) { linker_opt = cmd_line_opt_from_string(cmdline, str8_lit("l")); } if (linker_opt) { if (linker_opt->value_strings.node_count == 1) { g_linker = linker_opt->value_string; } else { fprintf(stderr, "ERROR: -linker has invalid number of arguments\n"); os_abort(1); } } else { // assume default linker g_linker = str8_lit("radlink"); } } // // Handle optional -target // String8List target = cmdline->inputs; { CmdLineOpt *target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target")); if (target_opt == 0) { target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t")); } if (target_opt) { if (target_opt->value_strings.node_count > 0) { str8_list_concat_in_place(&target, &target_opt->value_strings); } else { fprintf(stderr, "ERROR: -target has invalid number of arguments\n"); } } } // // Handle -out // { CmdLineOpt *out_opt = cmd_line_opt_from_string(cmdline, str8_lit("out")); if (out_opt) { if (out_opt->value_strings.node_count == 1) { g_out = out_opt->value_string; } else { fprintf(stderr, "ERROR: -out invalid number of arguments"); } } } // // Handle -verbose // { g_verbose = cmd_line_has_flag(cmdline, str8_lit("verbose")); } // // Handle -print_stdout // { g_redirect_stdout = !cmd_line_has_flag(cmdline, str8_lit("print_stdout")); } // // Make Output Directory // os_make_directory(g_out); if (!os_folder_path_exists(g_out)) { fprintf(stderr, "ERROR: unable to create output directory \"%.*s\"\n", str8_varg(g_out)); os_abort(1); } // // Clean up output from previous run // os_delete_file_at_path(g_stdout_file_name); // // Run Test Targets // { U64 max_label_size = 0; for (U64 i = 0; i < ArrayCount(target_array); i += 1) { max_label_size = Max(max_label_size, cstring8_length((U8*)target_array[i].label)); } U64 dots_min = 10; U64 dots_size = max_label_size+dots_min; U8 *dots = push_array(scratch.arena, U8, dots_size); MemorySet(dots, '.', dots_size); U64 target_indices_count; U64 *target_indices; if (target.node_count == 0) { target_indices_count = ArrayCount(target_array); target_indices = push_array(scratch.arena, U64, ArrayCount(target_array)); for (U64 i = 0; i < target_indices_count; i += 1) { target_indices[i] = i; } } else { target_indices_count = 0; target_indices = push_array(scratch.arena, U64, target.node_count); for (String8Node *target_n = target.first; target_n != 0; target_n = target_n->next) { B32 is_target_unknown = 1; for (U64 i = 0; i < ArrayCount(target_array); i += 1) { if (str8_match(str8_cstring(target_array[i].label), target_n->string, 0)) { target_indices[target_indices_count++] = i; is_target_unknown = 0; break; } } if (is_target_unknown) { fprintf(stderr, "ERROR: unknown target \"%.*s\"\n", str8_varg(target_n->string)); } } } U64 pass_count = 0; U64 fail_count = 0; U64 crash_count = 0; for (U64 i = 0; i < target_indices_count; i += 1) { U64 target_idx = target_indices[i]; g_wdir = push_str8f(scratch.arena, "%S\\%s", g_out, target_array[target_idx].label); g_wdir = os_full_path_from_path(scratch.arena, g_wdir); os_make_directory(g_wdir); if (!os_folder_path_exists(g_out)) { fprintf(stderr, "ERROR: unable to create output directory for test run %.*s\n", str8_varg(g_wdir)); continue; } T_Result result = t_run(target_array[target_idx].r); U64 dots_count = (max_label_size - cstring8_length((U8*)target_array[target_idx].label)) + dots_min; String8 msg = push_str8f(scratch.arena, "%s%.*s%s", target_array[target_idx].label, dots_count, dots, t_string_from_result(result)); // run progress fprintf(stdout, "[%2llu/%2llu] ", i+1, target_indices_count); if (result == T_Result_Pass) { fprintf(stdout, "\x1b[32m" "%.*s" "\x1b[0m" "\n", str8_varg(msg)); pass_count += 1; } else if (result == T_Result_Fail) { fprintf(stdout, "\x1b[31m" "%.*s" "\x1b[0m" "\n", str8_varg(msg)); fail_count += 1; } else if (result == T_Result_Crash) { fprintf(stdout, "\x1b[33m" "%.*s" "\x1b[0m" "\n", str8_varg(msg)); crash_count += 1; } } fprintf(stdout, "--- Report ---------------------------------------------------------------------\n"); fprintf(stdout, " Passed: %llu\n", pass_count); fprintf(stdout, " Failed: %llu\n", fail_count); fprintf(stdout, " Crashed: %llu\n", crash_count); if (fail_count + crash_count != 0) { fflush(stdout); os_abort(fail_count + crash_count); } } scratch_end(scratch); } ================================================ FILE: src/ui/generated/ui.meta.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #if 0 #define UI_Parent(v) DeferLoop(ui_push_parent(v), ui_pop_parent()) #define UI_ChildLayoutAxis(v) DeferLoop(ui_push_child_layout_axis(v), ui_pop_child_layout_axis()) #define UI_FixedX(v) DeferLoop(ui_push_fixed_x(v), ui_pop_fixed_x()) #define UI_FixedY(v) DeferLoop(ui_push_fixed_y(v), ui_pop_fixed_y()) #define UI_FixedWidth(v) DeferLoop(ui_push_fixed_width(v), ui_pop_fixed_width()) #define UI_FixedHeight(v) DeferLoop(ui_push_fixed_height(v), ui_pop_fixed_height()) #define UI_PrefWidth(v) DeferLoop(ui_push_pref_width(v), ui_pop_pref_width()) #define UI_PrefHeight(v) DeferLoop(ui_push_pref_height(v), ui_pop_pref_height()) #define UI_MinWidth(v) DeferLoop(ui_push_min_width(v), ui_pop_min_width()) #define UI_MinHeight(v) DeferLoop(ui_push_min_height(v), ui_pop_min_height()) #define UI_PermissionFlags(v) DeferLoop(ui_push_permission_flags(v), ui_pop_permission_flags()) #define UI_Flags(v) DeferLoop(ui_push_flags(v), ui_pop_flags()) #define UI_OmitFlags(v) DeferLoop(ui_push_omit_flags(v), ui_pop_omit_flags()) #define UI_FocusHot(v) DeferLoop(ui_push_focus_hot(v), ui_pop_focus_hot()) #define UI_FocusActive(v) DeferLoop(ui_push_focus_active(v), ui_pop_focus_active()) #define UI_FastpathCodepoint(v) DeferLoop(ui_push_fastpath_codepoint(v), ui_pop_fastpath_codepoint()) #define UI_GroupKey(v) DeferLoop(ui_push_group_key(v), ui_pop_group_key()) #define UI_Transparency(v) DeferLoop(ui_push_transparency(v), ui_pop_transparency()) #define UI_Tag(v) DeferLoop(ui_push_tag(v), ui_pop_tag()) #define UI_BackgroundColor(v) DeferLoop(ui_push_background_color(v), ui_pop_background_color()) #define UI_TextColor(v) DeferLoop(ui_push_text_color(v), ui_pop_text_color()) #define UI_BorderColor(v) DeferLoop(ui_push_border_color(v), ui_pop_border_color()) #define UI_Squish(v) DeferLoop(ui_push_squish(v), ui_pop_squish()) #define UI_HoverCursor(v) DeferLoop(ui_push_hover_cursor(v), ui_pop_hover_cursor()) #define UI_Font(v) DeferLoop(ui_push_font(v), ui_pop_font()) #define UI_FontSize(v) DeferLoop(ui_push_font_size(v), ui_pop_font_size()) #define UI_TextRasterFlags(v) DeferLoop(ui_push_text_raster_flags(v), ui_pop_text_raster_flags()) #define UI_TabSize(v) DeferLoop(ui_push_tab_size(v), ui_pop_tab_size()) #define UI_CornerRadius00(v) DeferLoop(ui_push_corner_radius_00(v), ui_pop_corner_radius_00()) #define UI_CornerRadius01(v) DeferLoop(ui_push_corner_radius_01(v), ui_pop_corner_radius_01()) #define UI_CornerRadius10(v) DeferLoop(ui_push_corner_radius_10(v), ui_pop_corner_radius_10()) #define UI_CornerRadius11(v) DeferLoop(ui_push_corner_radius_11(v), ui_pop_corner_radius_11()) #define UI_BlurSize(v) DeferLoop(ui_push_blur_size(v), ui_pop_blur_size()) #define UI_TextPadding(v) DeferLoop(ui_push_text_padding(v), ui_pop_text_padding()) #define UI_TextAlignment(v) DeferLoop(ui_push_text_alignment(v), ui_pop_text_alignment()) #endif internal UI_Box * ui_top_parent(void) { UI_StackTopImpl(ui_state, Parent, parent) } internal Axis2 ui_top_child_layout_axis(void) { UI_StackTopImpl(ui_state, ChildLayoutAxis, child_layout_axis) } internal F32 ui_top_fixed_x(void) { UI_StackTopImpl(ui_state, FixedX, fixed_x) } internal F32 ui_top_fixed_y(void) { UI_StackTopImpl(ui_state, FixedY, fixed_y) } internal F32 ui_top_fixed_width(void) { UI_StackTopImpl(ui_state, FixedWidth, fixed_width) } internal F32 ui_top_fixed_height(void) { UI_StackTopImpl(ui_state, FixedHeight, fixed_height) } internal UI_Size ui_top_pref_width(void) { UI_StackTopImpl(ui_state, PrefWidth, pref_width) } internal UI_Size ui_top_pref_height(void) { UI_StackTopImpl(ui_state, PrefHeight, pref_height) } internal F32 ui_top_min_width(void) { UI_StackTopImpl(ui_state, MinWidth, min_width) } internal F32 ui_top_min_height(void) { UI_StackTopImpl(ui_state, MinHeight, min_height) } internal UI_PermissionFlags ui_top_permission_flags(void) { UI_StackTopImpl(ui_state, PermissionFlags, permission_flags) } internal UI_BoxFlags ui_top_flags(void) { UI_StackTopImpl(ui_state, Flags, flags) } internal UI_BoxFlags ui_top_omit_flags(void) { UI_StackTopImpl(ui_state, OmitFlags, omit_flags) } internal UI_FocusKind ui_top_focus_hot(void) { UI_StackTopImpl(ui_state, FocusHot, focus_hot) } internal UI_FocusKind ui_top_focus_active(void) { UI_StackTopImpl(ui_state, FocusActive, focus_active) } internal U32 ui_top_fastpath_codepoint(void) { UI_StackTopImpl(ui_state, FastpathCodepoint, fastpath_codepoint) } internal UI_Key ui_top_group_key(void) { UI_StackTopImpl(ui_state, GroupKey, group_key) } internal F32 ui_top_transparency(void) { UI_StackTopImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_top_background_color(void) { UI_StackTopImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_top_text_color(void) { UI_StackTopImpl(ui_state, TextColor, text_color) } internal Vec4F32 ui_top_border_color(void) { UI_StackTopImpl(ui_state, BorderColor, border_color) } internal F32 ui_top_squish(void) { UI_StackTopImpl(ui_state, Squish, squish) } internal OS_Cursor ui_top_hover_cursor(void) { UI_StackTopImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_top_font(void) { UI_StackTopImpl(ui_state, Font, font) } internal F32 ui_top_font_size(void) { UI_StackTopImpl(ui_state, FontSize, font_size) } internal FNT_RasterFlags ui_top_text_raster_flags(void) { UI_StackTopImpl(ui_state, TextRasterFlags, text_raster_flags) } internal F32 ui_top_tab_size(void) { UI_StackTopImpl(ui_state, TabSize, tab_size) } internal F32 ui_top_corner_radius_00(void) { UI_StackTopImpl(ui_state, CornerRadius00, corner_radius_00) } internal F32 ui_top_corner_radius_01(void) { UI_StackTopImpl(ui_state, CornerRadius01, corner_radius_01) } internal F32 ui_top_corner_radius_10(void) { UI_StackTopImpl(ui_state, CornerRadius10, corner_radius_10) } internal F32 ui_top_corner_radius_11(void) { UI_StackTopImpl(ui_state, CornerRadius11, corner_radius_11) } internal F32 ui_top_blur_size(void) { UI_StackTopImpl(ui_state, BlurSize, blur_size) } internal F32 ui_top_text_padding(void) { UI_StackTopImpl(ui_state, TextPadding, text_padding) } internal UI_TextAlign ui_top_text_alignment(void) { UI_StackTopImpl(ui_state, TextAlignment, text_alignment) } internal UI_Box * ui_bottom_parent(void) { UI_StackBottomImpl(ui_state, Parent, parent) } internal Axis2 ui_bottom_child_layout_axis(void) { UI_StackBottomImpl(ui_state, ChildLayoutAxis, child_layout_axis) } internal F32 ui_bottom_fixed_x(void) { UI_StackBottomImpl(ui_state, FixedX, fixed_x) } internal F32 ui_bottom_fixed_y(void) { UI_StackBottomImpl(ui_state, FixedY, fixed_y) } internal F32 ui_bottom_fixed_width(void) { UI_StackBottomImpl(ui_state, FixedWidth, fixed_width) } internal F32 ui_bottom_fixed_height(void) { UI_StackBottomImpl(ui_state, FixedHeight, fixed_height) } internal UI_Size ui_bottom_pref_width(void) { UI_StackBottomImpl(ui_state, PrefWidth, pref_width) } internal UI_Size ui_bottom_pref_height(void) { UI_StackBottomImpl(ui_state, PrefHeight, pref_height) } internal F32 ui_bottom_min_width(void) { UI_StackBottomImpl(ui_state, MinWidth, min_width) } internal F32 ui_bottom_min_height(void) { UI_StackBottomImpl(ui_state, MinHeight, min_height) } internal UI_PermissionFlags ui_bottom_permission_flags(void) { UI_StackBottomImpl(ui_state, PermissionFlags, permission_flags) } internal UI_BoxFlags ui_bottom_flags(void) { UI_StackBottomImpl(ui_state, Flags, flags) } internal UI_BoxFlags ui_bottom_omit_flags(void) { UI_StackBottomImpl(ui_state, OmitFlags, omit_flags) } internal UI_FocusKind ui_bottom_focus_hot(void) { UI_StackBottomImpl(ui_state, FocusHot, focus_hot) } internal UI_FocusKind ui_bottom_focus_active(void) { UI_StackBottomImpl(ui_state, FocusActive, focus_active) } internal U32 ui_bottom_fastpath_codepoint(void) { UI_StackBottomImpl(ui_state, FastpathCodepoint, fastpath_codepoint) } internal UI_Key ui_bottom_group_key(void) { UI_StackBottomImpl(ui_state, GroupKey, group_key) } internal F32 ui_bottom_transparency(void) { UI_StackBottomImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_bottom_background_color(void) { UI_StackBottomImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_bottom_text_color(void) { UI_StackBottomImpl(ui_state, TextColor, text_color) } internal Vec4F32 ui_bottom_border_color(void) { UI_StackBottomImpl(ui_state, BorderColor, border_color) } internal F32 ui_bottom_squish(void) { UI_StackBottomImpl(ui_state, Squish, squish) } internal OS_Cursor ui_bottom_hover_cursor(void) { UI_StackBottomImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_bottom_font(void) { UI_StackBottomImpl(ui_state, Font, font) } internal F32 ui_bottom_font_size(void) { UI_StackBottomImpl(ui_state, FontSize, font_size) } internal FNT_RasterFlags ui_bottom_text_raster_flags(void) { UI_StackBottomImpl(ui_state, TextRasterFlags, text_raster_flags) } internal F32 ui_bottom_tab_size(void) { UI_StackBottomImpl(ui_state, TabSize, tab_size) } internal F32 ui_bottom_corner_radius_00(void) { UI_StackBottomImpl(ui_state, CornerRadius00, corner_radius_00) } internal F32 ui_bottom_corner_radius_01(void) { UI_StackBottomImpl(ui_state, CornerRadius01, corner_radius_01) } internal F32 ui_bottom_corner_radius_10(void) { UI_StackBottomImpl(ui_state, CornerRadius10, corner_radius_10) } internal F32 ui_bottom_corner_radius_11(void) { UI_StackBottomImpl(ui_state, CornerRadius11, corner_radius_11) } internal F32 ui_bottom_blur_size(void) { UI_StackBottomImpl(ui_state, BlurSize, blur_size) } internal F32 ui_bottom_text_padding(void) { UI_StackBottomImpl(ui_state, TextPadding, text_padding) } internal UI_TextAlign ui_bottom_text_alignment(void) { UI_StackBottomImpl(ui_state, TextAlignment, text_alignment) } internal UI_Box * ui_push_parent(UI_Box * v) { UI_StackPushImpl(ui_state, Parent, parent, UI_Box *, v) } internal Axis2 ui_push_child_layout_axis(Axis2 v) { UI_StackPushImpl(ui_state, ChildLayoutAxis, child_layout_axis, Axis2, v) } internal F32 ui_push_fixed_x(F32 v) { UI_StackPushImpl(ui_state, FixedX, fixed_x, F32, v) } internal F32 ui_push_fixed_y(F32 v) { UI_StackPushImpl(ui_state, FixedY, fixed_y, F32, v) } internal F32 ui_push_fixed_width(F32 v) { UI_StackPushImpl(ui_state, FixedWidth, fixed_width, F32, v) } internal F32 ui_push_fixed_height(F32 v) { UI_StackPushImpl(ui_state, FixedHeight, fixed_height, F32, v) } internal UI_Size ui_push_pref_width(UI_Size v) { UI_StackPushImpl(ui_state, PrefWidth, pref_width, UI_Size, v) } internal UI_Size ui_push_pref_height(UI_Size v) { UI_StackPushImpl(ui_state, PrefHeight, pref_height, UI_Size, v) } internal F32 ui_push_min_width(F32 v) { UI_StackPushImpl(ui_state, MinWidth, min_width, F32, v) } internal F32 ui_push_min_height(F32 v) { UI_StackPushImpl(ui_state, MinHeight, min_height, F32, v) } internal UI_PermissionFlags ui_push_permission_flags(UI_PermissionFlags v) { UI_StackPushImpl(ui_state, PermissionFlags, permission_flags, UI_PermissionFlags, v) } internal UI_BoxFlags ui_push_flags(UI_BoxFlags v) { UI_StackPushImpl(ui_state, Flags, flags, UI_BoxFlags, v) } internal UI_BoxFlags ui_push_omit_flags(UI_BoxFlags v) { UI_StackPushImpl(ui_state, OmitFlags, omit_flags, UI_BoxFlags, v) } internal UI_FocusKind ui_push_focus_hot(UI_FocusKind v) { UI_StackPushImpl(ui_state, FocusHot, focus_hot, UI_FocusKind, v) } internal UI_FocusKind ui_push_focus_active(UI_FocusKind v) { UI_StackPushImpl(ui_state, FocusActive, focus_active, UI_FocusKind, v) } internal U32 ui_push_fastpath_codepoint(U32 v) { UI_StackPushImpl(ui_state, FastpathCodepoint, fastpath_codepoint, U32, v) } internal UI_Key ui_push_group_key(UI_Key v) { UI_StackPushImpl(ui_state, GroupKey, group_key, UI_Key, v) } internal F32 ui_push_transparency(F32 v) { UI_StackPushImpl(ui_state, Transparency, transparency, F32, v) } internal Vec4F32 ui_push_background_color(Vec4F32 v) { UI_StackPushImpl(ui_state, BackgroundColor, background_color, Vec4F32, v) } internal Vec4F32 ui_push_text_color(Vec4F32 v) { UI_StackPushImpl(ui_state, TextColor, text_color, Vec4F32, v) } internal Vec4F32 ui_push_border_color(Vec4F32 v) { UI_StackPushImpl(ui_state, BorderColor, border_color, Vec4F32, v) } internal F32 ui_push_squish(F32 v) { UI_StackPushImpl(ui_state, Squish, squish, F32, v) } internal OS_Cursor ui_push_hover_cursor(OS_Cursor v) { UI_StackPushImpl(ui_state, HoverCursor, hover_cursor, OS_Cursor, v) } internal FNT_Tag ui_push_font(FNT_Tag v) { UI_StackPushImpl(ui_state, Font, font, FNT_Tag, v) } internal F32 ui_push_font_size(F32 v) { UI_StackPushImpl(ui_state, FontSize, font_size, F32, v) } internal FNT_RasterFlags ui_push_text_raster_flags(FNT_RasterFlags v) { UI_StackPushImpl(ui_state, TextRasterFlags, text_raster_flags, FNT_RasterFlags, v) } internal F32 ui_push_tab_size(F32 v) { UI_StackPushImpl(ui_state, TabSize, tab_size, F32, v) } internal F32 ui_push_corner_radius_00(F32 v) { UI_StackPushImpl(ui_state, CornerRadius00, corner_radius_00, F32, v) } internal F32 ui_push_corner_radius_01(F32 v) { UI_StackPushImpl(ui_state, CornerRadius01, corner_radius_01, F32, v) } internal F32 ui_push_corner_radius_10(F32 v) { UI_StackPushImpl(ui_state, CornerRadius10, corner_radius_10, F32, v) } internal F32 ui_push_corner_radius_11(F32 v) { UI_StackPushImpl(ui_state, CornerRadius11, corner_radius_11, F32, v) } internal F32 ui_push_blur_size(F32 v) { UI_StackPushImpl(ui_state, BlurSize, blur_size, F32, v) } internal F32 ui_push_text_padding(F32 v) { UI_StackPushImpl(ui_state, TextPadding, text_padding, F32, v) } internal UI_TextAlign ui_push_text_alignment(UI_TextAlign v) { UI_StackPushImpl(ui_state, TextAlignment, text_alignment, UI_TextAlign, v) } internal UI_Box * ui_pop_parent(void) { UI_StackPopImpl(ui_state, Parent, parent) } internal Axis2 ui_pop_child_layout_axis(void) { UI_StackPopImpl(ui_state, ChildLayoutAxis, child_layout_axis) } internal F32 ui_pop_fixed_x(void) { UI_StackPopImpl(ui_state, FixedX, fixed_x) } internal F32 ui_pop_fixed_y(void) { UI_StackPopImpl(ui_state, FixedY, fixed_y) } internal F32 ui_pop_fixed_width(void) { UI_StackPopImpl(ui_state, FixedWidth, fixed_width) } internal F32 ui_pop_fixed_height(void) { UI_StackPopImpl(ui_state, FixedHeight, fixed_height) } internal UI_Size ui_pop_pref_width(void) { UI_StackPopImpl(ui_state, PrefWidth, pref_width) } internal UI_Size ui_pop_pref_height(void) { UI_StackPopImpl(ui_state, PrefHeight, pref_height) } internal F32 ui_pop_min_width(void) { UI_StackPopImpl(ui_state, MinWidth, min_width) } internal F32 ui_pop_min_height(void) { UI_StackPopImpl(ui_state, MinHeight, min_height) } internal UI_PermissionFlags ui_pop_permission_flags(void) { UI_StackPopImpl(ui_state, PermissionFlags, permission_flags) } internal UI_BoxFlags ui_pop_flags(void) { UI_StackPopImpl(ui_state, Flags, flags) } internal UI_BoxFlags ui_pop_omit_flags(void) { UI_StackPopImpl(ui_state, OmitFlags, omit_flags) } internal UI_FocusKind ui_pop_focus_hot(void) { UI_StackPopImpl(ui_state, FocusHot, focus_hot) } internal UI_FocusKind ui_pop_focus_active(void) { UI_StackPopImpl(ui_state, FocusActive, focus_active) } internal U32 ui_pop_fastpath_codepoint(void) { UI_StackPopImpl(ui_state, FastpathCodepoint, fastpath_codepoint) } internal UI_Key ui_pop_group_key(void) { UI_StackPopImpl(ui_state, GroupKey, group_key) } internal F32 ui_pop_transparency(void) { UI_StackPopImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_pop_background_color(void) { UI_StackPopImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_pop_text_color(void) { UI_StackPopImpl(ui_state, TextColor, text_color) } internal Vec4F32 ui_pop_border_color(void) { UI_StackPopImpl(ui_state, BorderColor, border_color) } internal F32 ui_pop_squish(void) { UI_StackPopImpl(ui_state, Squish, squish) } internal OS_Cursor ui_pop_hover_cursor(void) { UI_StackPopImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_pop_font(void) { UI_StackPopImpl(ui_state, Font, font) } internal F32 ui_pop_font_size(void) { UI_StackPopImpl(ui_state, FontSize, font_size) } internal FNT_RasterFlags ui_pop_text_raster_flags(void) { UI_StackPopImpl(ui_state, TextRasterFlags, text_raster_flags) } internal F32 ui_pop_tab_size(void) { UI_StackPopImpl(ui_state, TabSize, tab_size) } internal F32 ui_pop_corner_radius_00(void) { UI_StackPopImpl(ui_state, CornerRadius00, corner_radius_00) } internal F32 ui_pop_corner_radius_01(void) { UI_StackPopImpl(ui_state, CornerRadius01, corner_radius_01) } internal F32 ui_pop_corner_radius_10(void) { UI_StackPopImpl(ui_state, CornerRadius10, corner_radius_10) } internal F32 ui_pop_corner_radius_11(void) { UI_StackPopImpl(ui_state, CornerRadius11, corner_radius_11) } internal F32 ui_pop_blur_size(void) { UI_StackPopImpl(ui_state, BlurSize, blur_size) } internal F32 ui_pop_text_padding(void) { UI_StackPopImpl(ui_state, TextPadding, text_padding) } internal UI_TextAlign ui_pop_text_alignment(void) { UI_StackPopImpl(ui_state, TextAlignment, text_alignment) } internal UI_Box * ui_set_next_parent(UI_Box * v) { UI_StackSetNextImpl(ui_state, Parent, parent, UI_Box *, v) } internal Axis2 ui_set_next_child_layout_axis(Axis2 v) { UI_StackSetNextImpl(ui_state, ChildLayoutAxis, child_layout_axis, Axis2, v) } internal F32 ui_set_next_fixed_x(F32 v) { UI_StackSetNextImpl(ui_state, FixedX, fixed_x, F32, v) } internal F32 ui_set_next_fixed_y(F32 v) { UI_StackSetNextImpl(ui_state, FixedY, fixed_y, F32, v) } internal F32 ui_set_next_fixed_width(F32 v) { UI_StackSetNextImpl(ui_state, FixedWidth, fixed_width, F32, v) } internal F32 ui_set_next_fixed_height(F32 v) { UI_StackSetNextImpl(ui_state, FixedHeight, fixed_height, F32, v) } internal UI_Size ui_set_next_pref_width(UI_Size v) { UI_StackSetNextImpl(ui_state, PrefWidth, pref_width, UI_Size, v) } internal UI_Size ui_set_next_pref_height(UI_Size v) { UI_StackSetNextImpl(ui_state, PrefHeight, pref_height, UI_Size, v) } internal F32 ui_set_next_min_width(F32 v) { UI_StackSetNextImpl(ui_state, MinWidth, min_width, F32, v) } internal F32 ui_set_next_min_height(F32 v) { UI_StackSetNextImpl(ui_state, MinHeight, min_height, F32, v) } internal UI_PermissionFlags ui_set_next_permission_flags(UI_PermissionFlags v) { UI_StackSetNextImpl(ui_state, PermissionFlags, permission_flags, UI_PermissionFlags, v) } internal UI_BoxFlags ui_set_next_flags(UI_BoxFlags v) { UI_StackSetNextImpl(ui_state, Flags, flags, UI_BoxFlags, v) } internal UI_BoxFlags ui_set_next_omit_flags(UI_BoxFlags v) { UI_StackSetNextImpl(ui_state, OmitFlags, omit_flags, UI_BoxFlags, v) } internal UI_FocusKind ui_set_next_focus_hot(UI_FocusKind v) { UI_StackSetNextImpl(ui_state, FocusHot, focus_hot, UI_FocusKind, v) } internal UI_FocusKind ui_set_next_focus_active(UI_FocusKind v) { UI_StackSetNextImpl(ui_state, FocusActive, focus_active, UI_FocusKind, v) } internal U32 ui_set_next_fastpath_codepoint(U32 v) { UI_StackSetNextImpl(ui_state, FastpathCodepoint, fastpath_codepoint, U32, v) } internal UI_Key ui_set_next_group_key(UI_Key v) { UI_StackSetNextImpl(ui_state, GroupKey, group_key, UI_Key, v) } internal F32 ui_set_next_transparency(F32 v) { UI_StackSetNextImpl(ui_state, Transparency, transparency, F32, v) } internal Vec4F32 ui_set_next_background_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, BackgroundColor, background_color, Vec4F32, v) } internal Vec4F32 ui_set_next_text_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, TextColor, text_color, Vec4F32, v) } internal Vec4F32 ui_set_next_border_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, BorderColor, border_color, Vec4F32, v) } internal F32 ui_set_next_squish(F32 v) { UI_StackSetNextImpl(ui_state, Squish, squish, F32, v) } internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v) { UI_StackSetNextImpl(ui_state, HoverCursor, hover_cursor, OS_Cursor, v) } internal FNT_Tag ui_set_next_font(FNT_Tag v) { UI_StackSetNextImpl(ui_state, Font, font, FNT_Tag, v) } internal F32 ui_set_next_font_size(F32 v) { UI_StackSetNextImpl(ui_state, FontSize, font_size, F32, v) } internal FNT_RasterFlags ui_set_next_text_raster_flags(FNT_RasterFlags v) { UI_StackSetNextImpl(ui_state, TextRasterFlags, text_raster_flags, FNT_RasterFlags, v) } internal F32 ui_set_next_tab_size(F32 v) { UI_StackSetNextImpl(ui_state, TabSize, tab_size, F32, v) } internal F32 ui_set_next_corner_radius_00(F32 v) { UI_StackSetNextImpl(ui_state, CornerRadius00, corner_radius_00, F32, v) } internal F32 ui_set_next_corner_radius_01(F32 v) { UI_StackSetNextImpl(ui_state, CornerRadius01, corner_radius_01, F32, v) } internal F32 ui_set_next_corner_radius_10(F32 v) { UI_StackSetNextImpl(ui_state, CornerRadius10, corner_radius_10, F32, v) } internal F32 ui_set_next_corner_radius_11(F32 v) { UI_StackSetNextImpl(ui_state, CornerRadius11, corner_radius_11, F32, v) } internal F32 ui_set_next_blur_size(F32 v) { UI_StackSetNextImpl(ui_state, BlurSize, blur_size, F32, v) } internal F32 ui_set_next_text_padding(F32 v) { UI_StackSetNextImpl(ui_state, TextPadding, text_padding, F32, v) } internal UI_TextAlign ui_set_next_text_alignment(UI_TextAlign v) { UI_StackSetNextImpl(ui_state, TextAlignment, text_alignment, UI_TextAlign, v) } ================================================ FILE: src/ui/generated/ui.meta.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE #ifndef UI_META_H #define UI_META_H typedef struct UI_ParentNode UI_ParentNode; struct UI_ParentNode{UI_ParentNode *next; UI_Box * v;}; typedef struct UI_ChildLayoutAxisNode UI_ChildLayoutAxisNode; struct UI_ChildLayoutAxisNode{UI_ChildLayoutAxisNode *next; Axis2 v;}; typedef struct UI_FixedXNode UI_FixedXNode; struct UI_FixedXNode{UI_FixedXNode *next; F32 v;}; typedef struct UI_FixedYNode UI_FixedYNode; struct UI_FixedYNode{UI_FixedYNode *next; F32 v;}; typedef struct UI_FixedWidthNode UI_FixedWidthNode; struct UI_FixedWidthNode{UI_FixedWidthNode *next; F32 v;}; typedef struct UI_FixedHeightNode UI_FixedHeightNode; struct UI_FixedHeightNode{UI_FixedHeightNode *next; F32 v;}; typedef struct UI_PrefWidthNode UI_PrefWidthNode; struct UI_PrefWidthNode{UI_PrefWidthNode *next; UI_Size v;}; typedef struct UI_PrefHeightNode UI_PrefHeightNode; struct UI_PrefHeightNode{UI_PrefHeightNode *next; UI_Size v;}; typedef struct UI_MinWidthNode UI_MinWidthNode; struct UI_MinWidthNode{UI_MinWidthNode *next; F32 v;}; typedef struct UI_MinHeightNode UI_MinHeightNode; struct UI_MinHeightNode{UI_MinHeightNode *next; F32 v;}; typedef struct UI_PermissionFlagsNode UI_PermissionFlagsNode; struct UI_PermissionFlagsNode{UI_PermissionFlagsNode *next; UI_PermissionFlags v;}; typedef struct UI_FlagsNode UI_FlagsNode; struct UI_FlagsNode{UI_FlagsNode *next; UI_BoxFlags v;}; typedef struct UI_OmitFlagsNode UI_OmitFlagsNode; struct UI_OmitFlagsNode{UI_OmitFlagsNode *next; UI_BoxFlags v;}; typedef struct UI_FocusHotNode UI_FocusHotNode; struct UI_FocusHotNode{UI_FocusHotNode *next; UI_FocusKind v;}; typedef struct UI_FocusActiveNode UI_FocusActiveNode; struct UI_FocusActiveNode{UI_FocusActiveNode *next; UI_FocusKind v;}; typedef struct UI_FastpathCodepointNode UI_FastpathCodepointNode; struct UI_FastpathCodepointNode{UI_FastpathCodepointNode *next; U32 v;}; typedef struct UI_GroupKeyNode UI_GroupKeyNode; struct UI_GroupKeyNode{UI_GroupKeyNode *next; UI_Key v;}; typedef struct UI_TransparencyNode UI_TransparencyNode; struct UI_TransparencyNode{UI_TransparencyNode *next; F32 v;}; typedef struct UI_TagNode UI_TagNode; struct UI_TagNode{UI_TagNode *next; String8 v;}; typedef struct UI_BackgroundColorNode UI_BackgroundColorNode; struct UI_BackgroundColorNode{UI_BackgroundColorNode *next; Vec4F32 v;}; typedef struct UI_TextColorNode UI_TextColorNode; struct UI_TextColorNode{UI_TextColorNode *next; Vec4F32 v;}; typedef struct UI_BorderColorNode UI_BorderColorNode; struct UI_BorderColorNode{UI_BorderColorNode *next; Vec4F32 v;}; typedef struct UI_SquishNode UI_SquishNode; struct UI_SquishNode{UI_SquishNode *next; F32 v;}; typedef struct UI_HoverCursorNode UI_HoverCursorNode; struct UI_HoverCursorNode{UI_HoverCursorNode *next; OS_Cursor v;}; typedef struct UI_FontNode UI_FontNode; struct UI_FontNode{UI_FontNode *next; FNT_Tag v;}; typedef struct UI_FontSizeNode UI_FontSizeNode; struct UI_FontSizeNode{UI_FontSizeNode *next; F32 v;}; typedef struct UI_TextRasterFlagsNode UI_TextRasterFlagsNode; struct UI_TextRasterFlagsNode{UI_TextRasterFlagsNode *next; FNT_RasterFlags v;}; typedef struct UI_TabSizeNode UI_TabSizeNode; struct UI_TabSizeNode{UI_TabSizeNode *next; F32 v;}; typedef struct UI_CornerRadius00Node UI_CornerRadius00Node; struct UI_CornerRadius00Node{UI_CornerRadius00Node *next; F32 v;}; typedef struct UI_CornerRadius01Node UI_CornerRadius01Node; struct UI_CornerRadius01Node{UI_CornerRadius01Node *next; F32 v;}; typedef struct UI_CornerRadius10Node UI_CornerRadius10Node; struct UI_CornerRadius10Node{UI_CornerRadius10Node *next; F32 v;}; typedef struct UI_CornerRadius11Node UI_CornerRadius11Node; struct UI_CornerRadius11Node{UI_CornerRadius11Node *next; F32 v;}; typedef struct UI_BlurSizeNode UI_BlurSizeNode; struct UI_BlurSizeNode{UI_BlurSizeNode *next; F32 v;}; typedef struct UI_TextPaddingNode UI_TextPaddingNode; struct UI_TextPaddingNode{UI_TextPaddingNode *next; F32 v;}; typedef struct UI_TextAlignmentNode UI_TextAlignmentNode; struct UI_TextAlignmentNode{UI_TextAlignmentNode *next; UI_TextAlign v;}; #define UI_DeclStackNils \ struct\ {\ UI_ParentNode parent_nil_stack_top;\ UI_ChildLayoutAxisNode child_layout_axis_nil_stack_top;\ UI_FixedXNode fixed_x_nil_stack_top;\ UI_FixedYNode fixed_y_nil_stack_top;\ UI_FixedWidthNode fixed_width_nil_stack_top;\ UI_FixedHeightNode fixed_height_nil_stack_top;\ UI_PrefWidthNode pref_width_nil_stack_top;\ UI_PrefHeightNode pref_height_nil_stack_top;\ UI_MinWidthNode min_width_nil_stack_top;\ UI_MinHeightNode min_height_nil_stack_top;\ UI_PermissionFlagsNode permission_flags_nil_stack_top;\ UI_FlagsNode flags_nil_stack_top;\ UI_OmitFlagsNode omit_flags_nil_stack_top;\ UI_FocusHotNode focus_hot_nil_stack_top;\ UI_FocusActiveNode focus_active_nil_stack_top;\ UI_FastpathCodepointNode fastpath_codepoint_nil_stack_top;\ UI_GroupKeyNode group_key_nil_stack_top;\ UI_TransparencyNode transparency_nil_stack_top;\ UI_TagNode tag_nil_stack_top;\ UI_BackgroundColorNode background_color_nil_stack_top;\ UI_TextColorNode text_color_nil_stack_top;\ UI_BorderColorNode border_color_nil_stack_top;\ UI_SquishNode squish_nil_stack_top;\ UI_HoverCursorNode hover_cursor_nil_stack_top;\ UI_FontNode font_nil_stack_top;\ UI_FontSizeNode font_size_nil_stack_top;\ UI_TextRasterFlagsNode text_raster_flags_nil_stack_top;\ UI_TabSizeNode tab_size_nil_stack_top;\ UI_CornerRadius00Node corner_radius_00_nil_stack_top;\ UI_CornerRadius01Node corner_radius_01_nil_stack_top;\ UI_CornerRadius10Node corner_radius_10_nil_stack_top;\ UI_CornerRadius11Node corner_radius_11_nil_stack_top;\ UI_BlurSizeNode blur_size_nil_stack_top;\ UI_TextPaddingNode text_padding_nil_stack_top;\ UI_TextAlignmentNode text_alignment_nil_stack_top;\ } #define UI_InitStackNils(state) \ state->parent_nil_stack_top.v = &ui_nil_box;\ state->child_layout_axis_nil_stack_top.v = Axis2_X;\ state->fixed_x_nil_stack_top.v = 0;\ state->fixed_y_nil_stack_top.v = 0;\ state->fixed_width_nil_stack_top.v = 0;\ state->fixed_height_nil_stack_top.v = 0;\ state->pref_width_nil_stack_top.v = ui_px(250.f, 1.f);\ state->pref_height_nil_stack_top.v = ui_px(30.f, 1.f);\ state->min_width_nil_stack_top.v = 0;\ state->min_height_nil_stack_top.v = 0;\ state->permission_flags_nil_stack_top.v = UI_PermissionFlag_All;\ state->flags_nil_stack_top.v = 0;\ state->omit_flags_nil_stack_top.v = 0;\ state->focus_hot_nil_stack_top.v = UI_FocusKind_Null;\ state->focus_active_nil_stack_top.v = UI_FocusKind_Null;\ state->fastpath_codepoint_nil_stack_top.v = 0;\ state->group_key_nil_stack_top.v = ui_key_zero();\ state->transparency_nil_stack_top.v = 0;\ state->tag_nil_stack_top.v = str8_lit("");\ state->background_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ state->text_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ state->border_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ state->squish_nil_stack_top.v = 0;\ state->hover_cursor_nil_stack_top.v = OS_Cursor_Pointer;\ state->font_nil_stack_top.v = fnt_tag_zero();\ state->font_size_nil_stack_top.v = 24.f;\ state->text_raster_flags_nil_stack_top.v = FNT_RasterFlag_Hinted;\ state->tab_size_nil_stack_top.v = 24.f*4.f;\ state->corner_radius_00_nil_stack_top.v = 0;\ state->corner_radius_01_nil_stack_top.v = 0;\ state->corner_radius_10_nil_stack_top.v = 0;\ state->corner_radius_11_nil_stack_top.v = 0;\ state->blur_size_nil_stack_top.v = 0;\ state->text_padding_nil_stack_top.v = 0;\ state->text_alignment_nil_stack_top.v = UI_TextAlign_Left;\ #define UI_DeclStacks \ struct\ {\ struct { UI_ParentNode *top; UI_Box * bottom_val; UI_ParentNode *free; U64 gen; B32 auto_pop; } parent_stack;\ struct { UI_ChildLayoutAxisNode *top; Axis2 bottom_val; UI_ChildLayoutAxisNode *free; U64 gen; B32 auto_pop; } child_layout_axis_stack;\ struct { UI_FixedXNode *top; F32 bottom_val; UI_FixedXNode *free; U64 gen; B32 auto_pop; } fixed_x_stack;\ struct { UI_FixedYNode *top; F32 bottom_val; UI_FixedYNode *free; U64 gen; B32 auto_pop; } fixed_y_stack;\ struct { UI_FixedWidthNode *top; F32 bottom_val; UI_FixedWidthNode *free; U64 gen; B32 auto_pop; } fixed_width_stack;\ struct { UI_FixedHeightNode *top; F32 bottom_val; UI_FixedHeightNode *free; U64 gen; B32 auto_pop; } fixed_height_stack;\ struct { UI_PrefWidthNode *top; UI_Size bottom_val; UI_PrefWidthNode *free; U64 gen; B32 auto_pop; } pref_width_stack;\ struct { UI_PrefHeightNode *top; UI_Size bottom_val; UI_PrefHeightNode *free; U64 gen; B32 auto_pop; } pref_height_stack;\ struct { UI_MinWidthNode *top; F32 bottom_val; UI_MinWidthNode *free; U64 gen; B32 auto_pop; } min_width_stack;\ struct { UI_MinHeightNode *top; F32 bottom_val; UI_MinHeightNode *free; U64 gen; B32 auto_pop; } min_height_stack;\ struct { UI_PermissionFlagsNode *top; UI_PermissionFlags bottom_val; UI_PermissionFlagsNode *free; U64 gen; B32 auto_pop; } permission_flags_stack;\ struct { UI_FlagsNode *top; UI_BoxFlags bottom_val; UI_FlagsNode *free; U64 gen; B32 auto_pop; } flags_stack;\ struct { UI_OmitFlagsNode *top; UI_BoxFlags bottom_val; UI_OmitFlagsNode *free; U64 gen; B32 auto_pop; } omit_flags_stack;\ struct { UI_FocusHotNode *top; UI_FocusKind bottom_val; UI_FocusHotNode *free; U64 gen; B32 auto_pop; } focus_hot_stack;\ struct { UI_FocusActiveNode *top; UI_FocusKind bottom_val; UI_FocusActiveNode *free; U64 gen; B32 auto_pop; } focus_active_stack;\ struct { UI_FastpathCodepointNode *top; U32 bottom_val; UI_FastpathCodepointNode *free; U64 gen; B32 auto_pop; } fastpath_codepoint_stack;\ struct { UI_GroupKeyNode *top; UI_Key bottom_val; UI_GroupKeyNode *free; U64 gen; B32 auto_pop; } group_key_stack;\ struct { UI_TransparencyNode *top; F32 bottom_val; UI_TransparencyNode *free; U64 gen; B32 auto_pop; } transparency_stack;\ struct { UI_TagNode *top; String8 bottom_val; UI_TagNode *free; U64 gen; B32 auto_pop; } tag_stack;\ struct { UI_BackgroundColorNode *top; Vec4F32 bottom_val; UI_BackgroundColorNode *free; U64 gen; B32 auto_pop; } background_color_stack;\ struct { UI_TextColorNode *top; Vec4F32 bottom_val; UI_TextColorNode *free; U64 gen; B32 auto_pop; } text_color_stack;\ struct { UI_BorderColorNode *top; Vec4F32 bottom_val; UI_BorderColorNode *free; U64 gen; B32 auto_pop; } border_color_stack;\ struct { UI_SquishNode *top; F32 bottom_val; UI_SquishNode *free; U64 gen; B32 auto_pop; } squish_stack;\ struct { UI_HoverCursorNode *top; OS_Cursor bottom_val; UI_HoverCursorNode *free; U64 gen; B32 auto_pop; } hover_cursor_stack;\ struct { UI_FontNode *top; FNT_Tag bottom_val; UI_FontNode *free; U64 gen; B32 auto_pop; } font_stack;\ struct { UI_FontSizeNode *top; F32 bottom_val; UI_FontSizeNode *free; U64 gen; B32 auto_pop; } font_size_stack;\ struct { UI_TextRasterFlagsNode *top; FNT_RasterFlags bottom_val; UI_TextRasterFlagsNode *free; U64 gen; B32 auto_pop; } text_raster_flags_stack;\ struct { UI_TabSizeNode *top; F32 bottom_val; UI_TabSizeNode *free; U64 gen; B32 auto_pop; } tab_size_stack;\ struct { UI_CornerRadius00Node *top; F32 bottom_val; UI_CornerRadius00Node *free; U64 gen; B32 auto_pop; } corner_radius_00_stack;\ struct { UI_CornerRadius01Node *top; F32 bottom_val; UI_CornerRadius01Node *free; U64 gen; B32 auto_pop; } corner_radius_01_stack;\ struct { UI_CornerRadius10Node *top; F32 bottom_val; UI_CornerRadius10Node *free; U64 gen; B32 auto_pop; } corner_radius_10_stack;\ struct { UI_CornerRadius11Node *top; F32 bottom_val; UI_CornerRadius11Node *free; U64 gen; B32 auto_pop; } corner_radius_11_stack;\ struct { UI_BlurSizeNode *top; F32 bottom_val; UI_BlurSizeNode *free; U64 gen; B32 auto_pop; } blur_size_stack;\ struct { UI_TextPaddingNode *top; F32 bottom_val; UI_TextPaddingNode *free; U64 gen; B32 auto_pop; } text_padding_stack;\ struct { UI_TextAlignmentNode *top; UI_TextAlign bottom_val; UI_TextAlignmentNode *free; U64 gen; B32 auto_pop; } text_alignment_stack;\ } #define UI_InitStacks(state) \ state->parent_stack.top = &state->parent_nil_stack_top; state->parent_stack.bottom_val = &ui_nil_box; state->parent_stack.free = 0; state->parent_stack.auto_pop = 0;\ state->child_layout_axis_stack.top = &state->child_layout_axis_nil_stack_top; state->child_layout_axis_stack.bottom_val = Axis2_X; state->child_layout_axis_stack.free = 0; state->child_layout_axis_stack.auto_pop = 0;\ state->fixed_x_stack.top = &state->fixed_x_nil_stack_top; state->fixed_x_stack.bottom_val = 0; state->fixed_x_stack.free = 0; state->fixed_x_stack.auto_pop = 0;\ state->fixed_y_stack.top = &state->fixed_y_nil_stack_top; state->fixed_y_stack.bottom_val = 0; state->fixed_y_stack.free = 0; state->fixed_y_stack.auto_pop = 0;\ state->fixed_width_stack.top = &state->fixed_width_nil_stack_top; state->fixed_width_stack.bottom_val = 0; state->fixed_width_stack.free = 0; state->fixed_width_stack.auto_pop = 0;\ state->fixed_height_stack.top = &state->fixed_height_nil_stack_top; state->fixed_height_stack.bottom_val = 0; state->fixed_height_stack.free = 0; state->fixed_height_stack.auto_pop = 0;\ state->pref_width_stack.top = &state->pref_width_nil_stack_top; state->pref_width_stack.bottom_val = ui_px(250.f, 1.f); state->pref_width_stack.free = 0; state->pref_width_stack.auto_pop = 0;\ state->pref_height_stack.top = &state->pref_height_nil_stack_top; state->pref_height_stack.bottom_val = ui_px(30.f, 1.f); state->pref_height_stack.free = 0; state->pref_height_stack.auto_pop = 0;\ state->min_width_stack.top = &state->min_width_nil_stack_top; state->min_width_stack.bottom_val = 0; state->min_width_stack.free = 0; state->min_width_stack.auto_pop = 0;\ state->min_height_stack.top = &state->min_height_nil_stack_top; state->min_height_stack.bottom_val = 0; state->min_height_stack.free = 0; state->min_height_stack.auto_pop = 0;\ state->permission_flags_stack.top = &state->permission_flags_nil_stack_top; state->permission_flags_stack.bottom_val = UI_PermissionFlag_All; state->permission_flags_stack.free = 0; state->permission_flags_stack.auto_pop = 0;\ state->flags_stack.top = &state->flags_nil_stack_top; state->flags_stack.bottom_val = 0; state->flags_stack.free = 0; state->flags_stack.auto_pop = 0;\ state->omit_flags_stack.top = &state->omit_flags_nil_stack_top; state->omit_flags_stack.bottom_val = 0; state->omit_flags_stack.free = 0; state->omit_flags_stack.auto_pop = 0;\ state->focus_hot_stack.top = &state->focus_hot_nil_stack_top; state->focus_hot_stack.bottom_val = UI_FocusKind_Null; state->focus_hot_stack.free = 0; state->focus_hot_stack.auto_pop = 0;\ state->focus_active_stack.top = &state->focus_active_nil_stack_top; state->focus_active_stack.bottom_val = UI_FocusKind_Null; state->focus_active_stack.free = 0; state->focus_active_stack.auto_pop = 0;\ state->fastpath_codepoint_stack.top = &state->fastpath_codepoint_nil_stack_top; state->fastpath_codepoint_stack.bottom_val = 0; state->fastpath_codepoint_stack.free = 0; state->fastpath_codepoint_stack.auto_pop = 0;\ state->group_key_stack.top = &state->group_key_nil_stack_top; state->group_key_stack.bottom_val = ui_key_zero(); state->group_key_stack.free = 0; state->group_key_stack.auto_pop = 0;\ state->transparency_stack.top = &state->transparency_nil_stack_top; state->transparency_stack.bottom_val = 0; state->transparency_stack.free = 0; state->transparency_stack.auto_pop = 0;\ state->tag_stack.top = &state->tag_nil_stack_top; state->tag_stack.bottom_val = str8_lit(""); state->tag_stack.free = 0; state->tag_stack.auto_pop = 0;\ state->background_color_stack.top = &state->background_color_nil_stack_top; state->background_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->background_color_stack.free = 0; state->background_color_stack.auto_pop = 0;\ state->text_color_stack.top = &state->text_color_nil_stack_top; state->text_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->text_color_stack.free = 0; state->text_color_stack.auto_pop = 0;\ state->border_color_stack.top = &state->border_color_nil_stack_top; state->border_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->border_color_stack.free = 0; state->border_color_stack.auto_pop = 0;\ state->squish_stack.top = &state->squish_nil_stack_top; state->squish_stack.bottom_val = 0; state->squish_stack.free = 0; state->squish_stack.auto_pop = 0;\ state->hover_cursor_stack.top = &state->hover_cursor_nil_stack_top; state->hover_cursor_stack.bottom_val = OS_Cursor_Pointer; state->hover_cursor_stack.free = 0; state->hover_cursor_stack.auto_pop = 0;\ state->font_stack.top = &state->font_nil_stack_top; state->font_stack.bottom_val = fnt_tag_zero(); state->font_stack.free = 0; state->font_stack.auto_pop = 0;\ state->font_size_stack.top = &state->font_size_nil_stack_top; state->font_size_stack.bottom_val = 24.f; state->font_size_stack.free = 0; state->font_size_stack.auto_pop = 0;\ state->text_raster_flags_stack.top = &state->text_raster_flags_nil_stack_top; state->text_raster_flags_stack.bottom_val = FNT_RasterFlag_Hinted; state->text_raster_flags_stack.free = 0; state->text_raster_flags_stack.auto_pop = 0;\ state->tab_size_stack.top = &state->tab_size_nil_stack_top; state->tab_size_stack.bottom_val = 24.f*4.f; state->tab_size_stack.free = 0; state->tab_size_stack.auto_pop = 0;\ state->corner_radius_00_stack.top = &state->corner_radius_00_nil_stack_top; state->corner_radius_00_stack.bottom_val = 0; state->corner_radius_00_stack.free = 0; state->corner_radius_00_stack.auto_pop = 0;\ state->corner_radius_01_stack.top = &state->corner_radius_01_nil_stack_top; state->corner_radius_01_stack.bottom_val = 0; state->corner_radius_01_stack.free = 0; state->corner_radius_01_stack.auto_pop = 0;\ state->corner_radius_10_stack.top = &state->corner_radius_10_nil_stack_top; state->corner_radius_10_stack.bottom_val = 0; state->corner_radius_10_stack.free = 0; state->corner_radius_10_stack.auto_pop = 0;\ state->corner_radius_11_stack.top = &state->corner_radius_11_nil_stack_top; state->corner_radius_11_stack.bottom_val = 0; state->corner_radius_11_stack.free = 0; state->corner_radius_11_stack.auto_pop = 0;\ state->blur_size_stack.top = &state->blur_size_nil_stack_top; state->blur_size_stack.bottom_val = 0; state->blur_size_stack.free = 0; state->blur_size_stack.auto_pop = 0;\ state->text_padding_stack.top = &state->text_padding_nil_stack_top; state->text_padding_stack.bottom_val = 0; state->text_padding_stack.free = 0; state->text_padding_stack.auto_pop = 0;\ state->text_alignment_stack.top = &state->text_alignment_nil_stack_top; state->text_alignment_stack.bottom_val = UI_TextAlign_Left; state->text_alignment_stack.free = 0; state->text_alignment_stack.auto_pop = 0;\ #define UI_AutoPopStacks(state) \ if(state->parent_stack.auto_pop) { ui_pop_parent(); state->parent_stack.auto_pop = 0; }\ if(state->child_layout_axis_stack.auto_pop) { ui_pop_child_layout_axis(); state->child_layout_axis_stack.auto_pop = 0; }\ if(state->fixed_x_stack.auto_pop) { ui_pop_fixed_x(); state->fixed_x_stack.auto_pop = 0; }\ if(state->fixed_y_stack.auto_pop) { ui_pop_fixed_y(); state->fixed_y_stack.auto_pop = 0; }\ if(state->fixed_width_stack.auto_pop) { ui_pop_fixed_width(); state->fixed_width_stack.auto_pop = 0; }\ if(state->fixed_height_stack.auto_pop) { ui_pop_fixed_height(); state->fixed_height_stack.auto_pop = 0; }\ if(state->pref_width_stack.auto_pop) { ui_pop_pref_width(); state->pref_width_stack.auto_pop = 0; }\ if(state->pref_height_stack.auto_pop) { ui_pop_pref_height(); state->pref_height_stack.auto_pop = 0; }\ if(state->min_width_stack.auto_pop) { ui_pop_min_width(); state->min_width_stack.auto_pop = 0; }\ if(state->min_height_stack.auto_pop) { ui_pop_min_height(); state->min_height_stack.auto_pop = 0; }\ if(state->permission_flags_stack.auto_pop) { ui_pop_permission_flags(); state->permission_flags_stack.auto_pop = 0; }\ if(state->flags_stack.auto_pop) { ui_pop_flags(); state->flags_stack.auto_pop = 0; }\ if(state->omit_flags_stack.auto_pop) { ui_pop_omit_flags(); state->omit_flags_stack.auto_pop = 0; }\ if(state->focus_hot_stack.auto_pop) { ui_pop_focus_hot(); state->focus_hot_stack.auto_pop = 0; }\ if(state->focus_active_stack.auto_pop) { ui_pop_focus_active(); state->focus_active_stack.auto_pop = 0; }\ if(state->fastpath_codepoint_stack.auto_pop) { ui_pop_fastpath_codepoint(); state->fastpath_codepoint_stack.auto_pop = 0; }\ if(state->group_key_stack.auto_pop) { ui_pop_group_key(); state->group_key_stack.auto_pop = 0; }\ if(state->transparency_stack.auto_pop) { ui_pop_transparency(); state->transparency_stack.auto_pop = 0; }\ if(state->tag_stack.auto_pop) { ui_pop_tag(); state->tag_stack.auto_pop = 0; }\ if(state->background_color_stack.auto_pop) { ui_pop_background_color(); state->background_color_stack.auto_pop = 0; }\ if(state->text_color_stack.auto_pop) { ui_pop_text_color(); state->text_color_stack.auto_pop = 0; }\ if(state->border_color_stack.auto_pop) { ui_pop_border_color(); state->border_color_stack.auto_pop = 0; }\ if(state->squish_stack.auto_pop) { ui_pop_squish(); state->squish_stack.auto_pop = 0; }\ if(state->hover_cursor_stack.auto_pop) { ui_pop_hover_cursor(); state->hover_cursor_stack.auto_pop = 0; }\ if(state->font_stack.auto_pop) { ui_pop_font(); state->font_stack.auto_pop = 0; }\ if(state->font_size_stack.auto_pop) { ui_pop_font_size(); state->font_size_stack.auto_pop = 0; }\ if(state->text_raster_flags_stack.auto_pop) { ui_pop_text_raster_flags(); state->text_raster_flags_stack.auto_pop = 0; }\ if(state->tab_size_stack.auto_pop) { ui_pop_tab_size(); state->tab_size_stack.auto_pop = 0; }\ if(state->corner_radius_00_stack.auto_pop) { ui_pop_corner_radius_00(); state->corner_radius_00_stack.auto_pop = 0; }\ if(state->corner_radius_01_stack.auto_pop) { ui_pop_corner_radius_01(); state->corner_radius_01_stack.auto_pop = 0; }\ if(state->corner_radius_10_stack.auto_pop) { ui_pop_corner_radius_10(); state->corner_radius_10_stack.auto_pop = 0; }\ if(state->corner_radius_11_stack.auto_pop) { ui_pop_corner_radius_11(); state->corner_radius_11_stack.auto_pop = 0; }\ if(state->blur_size_stack.auto_pop) { ui_pop_blur_size(); state->blur_size_stack.auto_pop = 0; }\ if(state->text_padding_stack.auto_pop) { ui_pop_text_padding(); state->text_padding_stack.auto_pop = 0; }\ if(state->text_alignment_stack.auto_pop) { ui_pop_text_alignment(); state->text_alignment_stack.auto_pop = 0; }\ internal UI_Box * ui_top_parent(void); internal Axis2 ui_top_child_layout_axis(void); internal F32 ui_top_fixed_x(void); internal F32 ui_top_fixed_y(void); internal F32 ui_top_fixed_width(void); internal F32 ui_top_fixed_height(void); internal UI_Size ui_top_pref_width(void); internal UI_Size ui_top_pref_height(void); internal F32 ui_top_min_width(void); internal F32 ui_top_min_height(void); internal UI_PermissionFlags ui_top_permission_flags(void); internal UI_BoxFlags ui_top_flags(void); internal UI_BoxFlags ui_top_omit_flags(void); internal UI_FocusKind ui_top_focus_hot(void); internal UI_FocusKind ui_top_focus_active(void); internal U32 ui_top_fastpath_codepoint(void); internal UI_Key ui_top_group_key(void); internal F32 ui_top_transparency(void); internal String8 ui_top_tag(void); internal Vec4F32 ui_top_background_color(void); internal Vec4F32 ui_top_text_color(void); internal Vec4F32 ui_top_border_color(void); internal F32 ui_top_squish(void); internal OS_Cursor ui_top_hover_cursor(void); internal FNT_Tag ui_top_font(void); internal F32 ui_top_font_size(void); internal FNT_RasterFlags ui_top_text_raster_flags(void); internal F32 ui_top_tab_size(void); internal F32 ui_top_corner_radius_00(void); internal F32 ui_top_corner_radius_01(void); internal F32 ui_top_corner_radius_10(void); internal F32 ui_top_corner_radius_11(void); internal F32 ui_top_blur_size(void); internal F32 ui_top_text_padding(void); internal UI_TextAlign ui_top_text_alignment(void); internal UI_Box * ui_bottom_parent(void); internal Axis2 ui_bottom_child_layout_axis(void); internal F32 ui_bottom_fixed_x(void); internal F32 ui_bottom_fixed_y(void); internal F32 ui_bottom_fixed_width(void); internal F32 ui_bottom_fixed_height(void); internal UI_Size ui_bottom_pref_width(void); internal UI_Size ui_bottom_pref_height(void); internal F32 ui_bottom_min_width(void); internal F32 ui_bottom_min_height(void); internal UI_PermissionFlags ui_bottom_permission_flags(void); internal UI_BoxFlags ui_bottom_flags(void); internal UI_BoxFlags ui_bottom_omit_flags(void); internal UI_FocusKind ui_bottom_focus_hot(void); internal UI_FocusKind ui_bottom_focus_active(void); internal U32 ui_bottom_fastpath_codepoint(void); internal UI_Key ui_bottom_group_key(void); internal F32 ui_bottom_transparency(void); internal String8 ui_bottom_tag(void); internal Vec4F32 ui_bottom_background_color(void); internal Vec4F32 ui_bottom_text_color(void); internal Vec4F32 ui_bottom_border_color(void); internal F32 ui_bottom_squish(void); internal OS_Cursor ui_bottom_hover_cursor(void); internal FNT_Tag ui_bottom_font(void); internal F32 ui_bottom_font_size(void); internal FNT_RasterFlags ui_bottom_text_raster_flags(void); internal F32 ui_bottom_tab_size(void); internal F32 ui_bottom_corner_radius_00(void); internal F32 ui_bottom_corner_radius_01(void); internal F32 ui_bottom_corner_radius_10(void); internal F32 ui_bottom_corner_radius_11(void); internal F32 ui_bottom_blur_size(void); internal F32 ui_bottom_text_padding(void); internal UI_TextAlign ui_bottom_text_alignment(void); internal UI_Box * ui_push_parent(UI_Box * v); internal Axis2 ui_push_child_layout_axis(Axis2 v); internal F32 ui_push_fixed_x(F32 v); internal F32 ui_push_fixed_y(F32 v); internal F32 ui_push_fixed_width(F32 v); internal F32 ui_push_fixed_height(F32 v); internal UI_Size ui_push_pref_width(UI_Size v); internal UI_Size ui_push_pref_height(UI_Size v); internal F32 ui_push_min_width(F32 v); internal F32 ui_push_min_height(F32 v); internal UI_PermissionFlags ui_push_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_push_flags(UI_BoxFlags v); internal UI_BoxFlags ui_push_omit_flags(UI_BoxFlags v); internal UI_FocusKind ui_push_focus_hot(UI_FocusKind v); internal UI_FocusKind ui_push_focus_active(UI_FocusKind v); internal U32 ui_push_fastpath_codepoint(U32 v); internal UI_Key ui_push_group_key(UI_Key v); internal F32 ui_push_transparency(F32 v); internal String8 ui_push_tag(String8 v); internal Vec4F32 ui_push_background_color(Vec4F32 v); internal Vec4F32 ui_push_text_color(Vec4F32 v); internal Vec4F32 ui_push_border_color(Vec4F32 v); internal F32 ui_push_squish(F32 v); internal OS_Cursor ui_push_hover_cursor(OS_Cursor v); internal FNT_Tag ui_push_font(FNT_Tag v); internal F32 ui_push_font_size(F32 v); internal FNT_RasterFlags ui_push_text_raster_flags(FNT_RasterFlags v); internal F32 ui_push_tab_size(F32 v); internal F32 ui_push_corner_radius_00(F32 v); internal F32 ui_push_corner_radius_01(F32 v); internal F32 ui_push_corner_radius_10(F32 v); internal F32 ui_push_corner_radius_11(F32 v); internal F32 ui_push_blur_size(F32 v); internal F32 ui_push_text_padding(F32 v); internal UI_TextAlign ui_push_text_alignment(UI_TextAlign v); internal UI_Box * ui_pop_parent(void); internal Axis2 ui_pop_child_layout_axis(void); internal F32 ui_pop_fixed_x(void); internal F32 ui_pop_fixed_y(void); internal F32 ui_pop_fixed_width(void); internal F32 ui_pop_fixed_height(void); internal UI_Size ui_pop_pref_width(void); internal UI_Size ui_pop_pref_height(void); internal F32 ui_pop_min_width(void); internal F32 ui_pop_min_height(void); internal UI_PermissionFlags ui_pop_permission_flags(void); internal UI_BoxFlags ui_pop_flags(void); internal UI_BoxFlags ui_pop_omit_flags(void); internal UI_FocusKind ui_pop_focus_hot(void); internal UI_FocusKind ui_pop_focus_active(void); internal U32 ui_pop_fastpath_codepoint(void); internal UI_Key ui_pop_group_key(void); internal F32 ui_pop_transparency(void); internal String8 ui_pop_tag(void); internal Vec4F32 ui_pop_background_color(void); internal Vec4F32 ui_pop_text_color(void); internal Vec4F32 ui_pop_border_color(void); internal F32 ui_pop_squish(void); internal OS_Cursor ui_pop_hover_cursor(void); internal FNT_Tag ui_pop_font(void); internal F32 ui_pop_font_size(void); internal FNT_RasterFlags ui_pop_text_raster_flags(void); internal F32 ui_pop_tab_size(void); internal F32 ui_pop_corner_radius_00(void); internal F32 ui_pop_corner_radius_01(void); internal F32 ui_pop_corner_radius_10(void); internal F32 ui_pop_corner_radius_11(void); internal F32 ui_pop_blur_size(void); internal F32 ui_pop_text_padding(void); internal UI_TextAlign ui_pop_text_alignment(void); internal UI_Box * ui_set_next_parent(UI_Box * v); internal Axis2 ui_set_next_child_layout_axis(Axis2 v); internal F32 ui_set_next_fixed_x(F32 v); internal F32 ui_set_next_fixed_y(F32 v); internal F32 ui_set_next_fixed_width(F32 v); internal F32 ui_set_next_fixed_height(F32 v); internal UI_Size ui_set_next_pref_width(UI_Size v); internal UI_Size ui_set_next_pref_height(UI_Size v); internal F32 ui_set_next_min_width(F32 v); internal F32 ui_set_next_min_height(F32 v); internal UI_PermissionFlags ui_set_next_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_set_next_flags(UI_BoxFlags v); internal UI_BoxFlags ui_set_next_omit_flags(UI_BoxFlags v); internal UI_FocusKind ui_set_next_focus_hot(UI_FocusKind v); internal UI_FocusKind ui_set_next_focus_active(UI_FocusKind v); internal U32 ui_set_next_fastpath_codepoint(U32 v); internal UI_Key ui_set_next_group_key(UI_Key v); internal F32 ui_set_next_transparency(F32 v); internal String8 ui_set_next_tag(String8 v); internal Vec4F32 ui_set_next_background_color(Vec4F32 v); internal Vec4F32 ui_set_next_text_color(Vec4F32 v); internal Vec4F32 ui_set_next_border_color(Vec4F32 v); internal F32 ui_set_next_squish(F32 v); internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v); internal FNT_Tag ui_set_next_font(FNT_Tag v); internal F32 ui_set_next_font_size(F32 v); internal FNT_RasterFlags ui_set_next_text_raster_flags(FNT_RasterFlags v); internal F32 ui_set_next_tab_size(F32 v); internal F32 ui_set_next_corner_radius_00(F32 v); internal F32 ui_set_next_corner_radius_01(F32 v); internal F32 ui_set_next_corner_radius_10(F32 v); internal F32 ui_set_next_corner_radius_11(F32 v); internal F32 ui_set_next_blur_size(F32 v); internal F32 ui_set_next_text_padding(F32 v); internal UI_TextAlign ui_set_next_text_alignment(UI_TextAlign v); #endif // UI_META_H ================================================ FILE: src/ui/ui.mdesk ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- rjf: stack table @table(name, name_lower, type, default, manual_impl) UI_StackTable: { //- rjf: parents { Parent parent `UI_Box *` `&ui_nil_box` } //- rjf: layout params { ChildLayoutAxis child_layout_axis Axis2 `Axis2_X` } //- rjf: size/position { FixedX fixed_x F32 0 } { FixedY fixed_y F32 0 } { FixedWidth fixed_width F32 0 } { FixedHeight fixed_height F32 0 } { PrefWidth pref_width UI_Size `ui_px(250.f, 1.f)` } { PrefHeight pref_height UI_Size `ui_px(30.f, 1.f)` } { MinWidth min_width F32 0 } { MinHeight min_height F32 0 } //- rjf: flags { PermissionFlags permission_flags UI_PermissionFlags UI_PermissionFlag_All } { Flags flags UI_BoxFlags 0 } { OmitFlags omit_flags UI_BoxFlags 0 } //- rjf: interaction { FocusHot focus_hot UI_FocusKind UI_FocusKind_Null } { FocusActive focus_active UI_FocusKind UI_FocusKind_Null } { FastpathCodepoint fastpath_codepoint U32 0 } { GroupKey group_key UI_Key `ui_key_zero()` } //- rjf: colors { Transparency transparency F32 0 } { Tag tag String8 `str8_lit("")` 1 } { BackgroundColor background_color Vec4F32 `v4f32(0, 0, 0, 0)` } { TextColor text_color Vec4F32 `v4f32(0, 0, 0, 0)` } { BorderColor border_color Vec4F32 `v4f32(0, 0, 0, 0)` } //- rjf: squish { Squish squish F32 0 } //- rjf: hover cursor { HoverCursor hover_cursor OS_Cursor OS_Cursor_Pointer } //- rjf: font { Font font FNT_Tag `fnt_tag_zero()` } { FontSize font_size F32 24.f } { TextRasterFlags text_raster_flags FNT_RasterFlags FNT_RasterFlag_Hinted } { TabSize tab_size F32 `24.f*4.f` } //- rjf: corner radii { CornerRadius00 corner_radius_00 F32 0 } { CornerRadius01 corner_radius_01 F32 0 } { CornerRadius10 corner_radius_10 F32 0 } { CornerRadius11 corner_radius_11 F32 0 } //- rjf: blur size { BlurSize blur_size F32 0 } //- rjf: text parameters { TextPadding text_padding F32 0 } { TextAlignment text_alignment UI_TextAlign UI_TextAlign_Left } } //- rjf: declaring stack node types @gen { @expand(UI_StackTable a) `typedef struct UI_$(a.name)Node UI_$(a.name)Node; struct UI_$(a.name)Node{UI_$(a.name)Node *next; $(a.type) v;};` } //- rjf: declaring all default stack tops @gen { `#define UI_DeclStackNils \\`; `struct\\`; `{\\`; @expand(UI_StackTable a) `UI_$(a.name)Node $(a.name_lower)_nil_stack_top;\\`; `}`; } //- rjf: initializing all default stack tops @gen { `#define UI_InitStackNils(state) \\`; @expand(UI_StackTable a) `state->$(a.name_lower)_nil_stack_top.v = $(a.default);\\`; ``; } //- rjf: declaring all stack nodes & free lists @gen { `#define UI_DeclStacks \\`; `struct\\`; `{\\`; @expand(UI_StackTable a) `struct { UI_$(a.name)Node *top; $(a.type) bottom_val; UI_$(a.name)Node *free; U64 gen; B32 auto_pop; } $(a.name_lower)_stack;\\`; `}`; } //- rjf: initing all stack nodes @gen { `#define UI_InitStacks(state) \\`; @expand(UI_StackTable a) `state->$(a.name_lower)_stack.top = &state->$(a.name_lower)_nil_stack_top; state->$(a.name_lower)_stack.bottom_val = $(a.default); state->$(a.name_lower)_stack.free = 0; state->$(a.name_lower)_stack.auto_pop = 0;\\`; ``; } //- rjf: auto-popping all stacks @gen { `#define UI_AutoPopStacks(state) \\` @expand(UI_StackTable a) `if(state->$(a.name_lower)_stack.auto_pop) { ui_pop_$(a.name_lower)(); state->$(a.name_lower)_stack.auto_pop = 0; }\\`; ``; } //- rjf: decls for the stack function operation headers @gen { @expand(UI_StackTable a) `internal $(a.type) $(=>35) ui_top_$(a.name_lower)(void);` @expand(UI_StackTable a) `internal $(a.type) $(=>35) ui_bottom_$(a.name_lower)(void);` @expand(UI_StackTable a) `internal $(a.type) $(=>35) ui_push_$(a.name_lower)($(a.type) v);` @expand(UI_StackTable a) `internal $(a.type) $(=>35) ui_pop_$(a.name_lower)(void);` @expand(UI_StackTable a) `internal $(a.type) $(=>35) ui_set_next_$(a.name_lower)($(a.type) v);` } //- rjf: defer-loop helpers @gen @c_file { `#if 0`; @expand(UI_StackTable a) `#define UI_$(a.name)(v) DeferLoop(ui_push_$(a.name_lower)(v), ui_pop_$(a.name_lower)())` `#endif`; } //- rjf: decls for the stack operation implementations @gen @c_file { @expand(UI_StackTable a) `$(a.manual_impl == "" -> "internal " .. a.type .. " ui_top_" .. a.name_lower .. "(void) { UI_StackTopImpl(ui_state, " .. a.name .. ", " .. a.name_lower .. ") }")`; @expand(UI_StackTable a) `$(a.manual_impl == "" -> "internal " .. a.type .. " ui_bottom_" .. a.name_lower .. "(void) { UI_StackBottomImpl(ui_state, " .. a.name .. ", " .. a.name_lower .. ") }")`; @expand(UI_StackTable a) `$(a.manual_impl == "" -> "internal " .. a.type .. " ui_push_" .. a.name_lower .. "(" .. a.type .. " v) { UI_StackPushImpl(ui_state, " .. a.name .. ", " .. a.name_lower .. ", " .. a.type .. ", v) }")`; @expand(UI_StackTable a) `$(a.manual_impl == "" -> "internal " .. a.type .. " ui_pop_" .. a.name_lower .. "(void) { UI_StackPopImpl(ui_state, " .. a.name .. ", " .. a.name_lower .. ") }")`; @expand(UI_StackTable a) `$(a.manual_impl == "" -> "internal " .. a.type .. " ui_set_next_" .. a.name_lower .. "(" .. a.type .. " v) { UI_StackSetNextImpl(ui_state, " .. a.name .. ", " .. a.name_lower .. ", " .. a.type .. ", v) }")`; } ================================================ FILE: src/ui/ui_basic_widgets.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Basic Widgets internal void ui_divider(UI_Size size) { UI_Box *parent = ui_top_parent(); ui_set_next_pref_size(parent->child_layout_axis, size); ui_set_next_child_layout_axis(parent->child_layout_axis); UI_Box *box = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(box) UI_Padding(ui_pct(0.5f, 0.5f)) UI_PrefSize(parent->child_layout_axis, ui_em(0.1f, 1.f)) UI_BackgroundColor(ui_color_from_name(str8_lit("border"))) { ui_set_next_child_layout_axis(axis2_flip(parent->child_layout_axis)); UI_Box *spacing_parent = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(spacing_parent) UI_Padding(ui_em(1.f, 1.f)) UI_PrefSize(axis2_flip(parent->child_layout_axis), ui_pct(1, 0)) { ui_build_box_from_key(UI_BoxFlag_DrawBackground, ui_key_zero()); } } } internal UI_Signal ui_label(String8 string) { UI_Box *box = ui_build_box_from_string(UI_BoxFlag_DrawText, str8_zero()); ui_box_equip_display_string(box, string); UI_Signal interact = ui_signal_from_box(box); return interact; } internal UI_Signal ui_labelf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal result = ui_label(string); scratch_end(scratch); return result; } internal void ui_label_multiline(F32 max, String8 string) { Temp scratch = scratch_begin(0, 0); ui_set_next_child_layout_axis(Axis2_Y); ui_set_next_pref_height(ui_children_sum(1)); UI_Box *box = ui_build_box_from_key(0, ui_key_zero()); String8List lines = fnt_wrapped_string_lines_from_font_size_string_max(scratch.arena, ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), string, max); for(String8Node *n = lines.first; n != 0; n = n->next) { ui_label(n->string); } scratch_end(scratch); } internal void ui_label_multilinef(F32 max, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); ui_label_multiline(max, string); scratch_end(scratch); } internal UI_Signal ui_button(String8 string) { UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable| UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawText| UI_BoxFlag_DrawHotEffects| UI_BoxFlag_DrawActiveEffects, string); UI_Signal interact = ui_signal_from_box(box); return interact; } internal UI_Signal ui_buttonf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal result = ui_button(string); scratch_end(scratch); return result; } internal UI_Signal ui_hover_label(String8 string) { UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, string); UI_Signal interact = ui_signal_from_box(box); if(ui_hovering(interact)) { box->flags |= UI_BoxFlag_DrawBorder; } return interact; } internal UI_Signal ui_hover_labelf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_hover_label(string); scratch_end(scratch); return sig; } typedef struct UI_LineEditDrawData UI_LineEditDrawData; struct UI_LineEditDrawData { String8 edited_string; TxtPt cursor; TxtPt mark; B32 trail; }; internal UI_BOX_CUSTOM_DRAW(ui_line_edit_draw) { UI_LineEditDrawData *draw_data = (UI_LineEditDrawData *)user_data; FNT_Tag font = box->font; F32 font_size = box->font_size; F32 tab_size = box->tab_size; Vec4F32 cursor_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("cursor")); cursor_color.w *= box->parent->parent->focus_active_t; Vec4F32 select_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("selection")); select_color.w *= (box->parent->parent->focus_active_t*0.2f + 0.8f); Vec4F32 trail_color = cursor_color; trail_color.w *= 0.25f; Vec2F32 text_position = ui_box_text_position(box); String8 edited_string = draw_data->edited_string; TxtPt cursor = draw_data->cursor; TxtPt mark = draw_data->mark; F32 cursor_pixel_off = fnt_dim_from_tag_size_string(font, font_size, 0, tab_size, str8_prefix(edited_string, cursor.column-1)).x; F32 cursor_pixel_off__animated = ui_anim(ui_key_from_stringf(box->key, "cursor_off_px"), cursor_pixel_off); F32 mark_pixel_off = fnt_dim_from_tag_size_string(font, font_size, 0, tab_size, str8_prefix(edited_string, mark.column-1)).x; F32 cursor_thickness = ClampBot(1.f, floor_f32(font_size/10.f)); Rng2F32 cursor_rect = { text_position.x + cursor_pixel_off, box->parent->parent->rect.y0+ui_top_font_size()*0.5f, text_position.x + cursor_pixel_off + cursor_thickness, box->parent->parent->rect.y1-ui_top_font_size()*0.5f, }; Rng1F32 trail_off_span = r1f32(cursor_pixel_off, cursor_pixel_off__animated); Rng2F32 trail_rect = { text_position.x + trail_off_span.min, cursor_rect.y0, text_position.x + trail_off_span.max, cursor_rect.y1, }; Rng2F32 mark_rect = { text_position.x + mark_pixel_off - cursor_thickness, box->parent->parent->rect.y0+ui_top_font_size()*0.5f, text_position.x + mark_pixel_off + cursor_thickness, box->parent->parent->rect.y1-ui_top_font_size()*0.5f, }; Rng2F32 select_rect = union_2f32(cursor_rect, mark_rect); dr_rect(select_rect, select_color, font_size/2.f, 0, 1.f); dr_rect(cursor_rect, cursor_color, 0.f, 0, 0.f); if(draw_data->trail) { R_Rect2DInst *trail_inst = dr_rect(trail_rect, trail_color, ui_top_font_size()*0.2f, 0, 1.f); if(cursor_pixel_off > cursor_pixel_off__animated) { trail_inst->colors[Corner_00].w *= 0.1f; trail_inst->colors[Corner_01].w *= 0.1f; } else { trail_inst->colors[Corner_10].w *= 0.1f; trail_inst->colors[Corner_11].w *= 0.1f; } } } internal UI_Signal ui_line_edit(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, String8 pre_edit_value, String8 string) { //- rjf: make key UI_Key key = ui_key_from_string(ui_active_seed_key(), string); //- rjf: calculate focus B32 is_auto_focus_hot = ui_is_key_auto_focus_hot(key); B32 is_auto_focus_active = ui_is_key_auto_focus_active(key); ui_push_focus_hot(is_auto_focus_hot ? UI_FocusKind_On : UI_FocusKind_Null); ui_push_focus_active(is_auto_focus_active ? UI_FocusKind_On : UI_FocusKind_Null); B32 is_focus_hot = ui_is_focus_hot(); B32 is_focus_active = ui_is_focus_active(); B32 is_focus_hot_disabled = (!is_focus_hot && ui_top_focus_hot() == UI_FocusKind_On); B32 is_focus_active_disabled = (!is_focus_active && ui_top_focus_active() == UI_FocusKind_On); //- rjf: build top-level box ui_set_next_hover_cursor(is_focus_active ? OS_Cursor_IBar : OS_Cursor_Pointer); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawBackground| UI_BoxFlag_DrawBorder| UI_BoxFlag_MouseClickable| UI_BoxFlag_ClickToFocus| ((is_auto_focus_hot || is_auto_focus_active)*UI_BoxFlag_KeyboardClickable)| UI_BoxFlag_DrawHotEffects| (is_focus_active || is_focus_active_disabled)*(UI_BoxFlag_Clip|UI_BoxFlag_AllowOverflowX|UI_BoxFlag_ViewClamp), key); //- rjf: take navigation actions for editing B32 changes_made = 0; if(is_focus_active) { Temp scratch = scratch_begin(0, 0); for(UI_Event *evt = 0; ui_next_event(&evt);) { String8 edit_string = str8(edit_buffer, edit_string_size_out[0]); // rjf: do not consume anything that doesn't fit a single-line's operations if((evt->kind != UI_EventKind_Edit && evt->kind != UI_EventKind_Navigate && evt->kind != UI_EventKind_Text) || evt->delta_2s32.y != 0) { continue; } // rjf: map this action to an op UI_TxtOp op = ui_single_line_txt_op_from_event(scratch.arena, evt, edit_string, *cursor, *mark); // rjf: perform replace range if(!txt_pt_match(op.range.min, op.range.max) || op.replace.size != 0) { String8 new_string = ui_push_string_replace_range(scratch.arena, edit_string, r1s64(op.range.min.column, op.range.max.column), op.replace); new_string.size = Min(edit_buffer_size, new_string.size); MemoryCopy(edit_buffer, new_string.str, new_string.size); edit_string_size_out[0] = new_string.size; } // rjf: perform copy if(op.flags & UI_TxtOpFlag_Copy) { os_set_clipboard_text(op.copy); } // rjf: commit op's changed cursor & mark to caller-provided state *cursor = op.cursor; *mark = op.mark; // rjf: consume event { ui_eat_event(evt); changes_made = 1; } } scratch_end(scratch); } //- rjf: build contents TxtPt mouse_pt = {0}; F32 cursor_off = 0; UI_Parent(box) { String8 edit_string = str8(edit_buffer, edit_string_size_out[0]); if(!is_focus_active && !is_focus_active_disabled) { String8 display_string = ui_display_part_from_key_string(string); if(pre_edit_value.size != 0) { display_string = pre_edit_value; } ui_label(display_string); } else { F32 total_text_width = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), edit_string).x; ui_set_next_pref_width(ui_px(total_text_width+ui_top_font_size()*5, 1.f)); UI_Box *editstr_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_DisableTextTrunc, "###editstr"); UI_LineEditDrawData *draw_data = push_array(ui_build_arena(), UI_LineEditDrawData, 1); draw_data->edited_string = push_str8_copy(ui_build_arena(), edit_string); draw_data->cursor = *cursor; draw_data->mark = *mark; draw_data->trail = 1; ui_box_equip_display_string(editstr_box, edit_string); ui_box_equip_custom_draw(editstr_box, ui_line_edit_draw, draw_data); mouse_pt = txt_pt(1, 1+ui_box_char_pos_from_xy(editstr_box, ui_mouse())); cursor_off = fnt_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), str8_prefix(edit_string, cursor->column-1)).x; } } //- rjf: interact UI_Signal sig = ui_signal_from_box(box); if(!is_focus_active && sig.f&(UI_SignalFlag_DoubleClicked|UI_SignalFlag_KeyboardPressed)) { String8 edit_string = pre_edit_value; edit_string.size = Min(edit_buffer_size, pre_edit_value.size); MemoryCopy(edit_buffer, edit_string.str, edit_string.size); edit_string_size_out[0] = edit_string.size; ui_set_auto_focus_active_key(key); ui_kill_action(); *cursor = txt_pt(1, edit_string.size+1); *mark = txt_pt(1, 1); } if(is_focus_active && sig.f&UI_SignalFlag_KeyboardPressed) { ui_set_auto_focus_active_key(ui_key_zero()); sig.f |= UI_SignalFlag_Commit; } if(is_focus_active && ui_dragging(sig)) { if(ui_pressed(sig)) { *mark = mouse_pt; } *cursor = mouse_pt; } //- rjf: focus cursor { Rng1F32 cursor_range_px = r1f32(cursor_off-ui_top_font_size()*2.f, cursor_off+ui_top_font_size()*2.f); Rng1F32 visible_range_px = r1f32(box->view_off_target.x, box->view_off_target.x + dim_2f32(box->rect).x); cursor_range_px.min = ClampBot(0, cursor_range_px.min); cursor_range_px.max = ClampBot(0, cursor_range_px.max); F32 min_delta = cursor_range_px.min-visible_range_px.min; F32 max_delta = cursor_range_px.max-visible_range_px.max; min_delta = Min(min_delta, 0); max_delta = Max(max_delta, 0); box->view_off_target.x += min_delta; box->view_off_target.x += max_delta; } //- rjf: pop focus ui_pop_focus_hot(); ui_pop_focus_active(); return sig; } internal UI_Signal ui_line_editf(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, String8 pre_edit_value, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal result = ui_line_edit(cursor, mark, edit_buffer, edit_buffer_size, edit_string_size_out, pre_edit_value, string); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Images typedef struct UI_ImageDrawData UI_ImageDrawData; struct UI_ImageDrawData { R_Handle texture; R_Tex2DSampleKind sample_kind; Rng2F32 region; Vec4F32 tint; F32 blur; }; internal UI_BOX_CUSTOM_DRAW(ui_image_draw) { UI_ImageDrawData *draw_data = (UI_ImageDrawData *)user_data; if(r_handle_match(draw_data->texture, r_handle_zero())) { R_Rect2DInst *inst = dr_rect(box->rect, v4f32(0, 0, 0, 0), 0, 0, 1.f); MemoryCopyArray(inst->corner_radii, box->corner_radii); } else DR_Tex2DSampleKindScope(draw_data->sample_kind) { R_Rect2DInst *inst = dr_img(box->rect, draw_data->region, draw_data->texture, draw_data->tint, 0, 0, 0); MemoryCopyArray(inst->corner_radii, box->corner_radii); } if(draw_data->blur > 0.01f) { Rng2F32 clip = box->rect; for(UI_Box *b = box->parent; !ui_box_is_nil(b); b = b->parent) { if(b->flags & UI_BoxFlag_Clip) { clip = intersect_2f32(b->rect, clip); } } R_PassParams_Blur *blur = dr_blur(intersect_2f32(clip, box->rect), draw_data->blur, 0); MemoryCopyArray(blur->corner_radii, box->corner_radii); } } internal UI_Signal ui_image(R_Handle texture, R_Tex2DSampleKind sample_kind, Rng2F32 region, Vec4F32 tint, F32 blur, String8 string) { UI_Box *box = ui_build_box_from_string(0, string); UI_ImageDrawData *draw_data = push_array(ui_build_arena(), UI_ImageDrawData, 1); draw_data->texture = texture; draw_data->sample_kind = sample_kind; draw_data->region = region; draw_data->tint = tint; draw_data->blur = blur; ui_box_equip_custom_draw(box, ui_image_draw, draw_data); UI_Signal sig = ui_signal_from_box(box); return sig; } internal UI_Signal ui_imagef(R_Handle texture, R_Tex2DSampleKind sample_kind, Rng2F32 region, Vec4F32 tint, F32 blur, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal result = ui_image(texture, sample_kind, region, tint, blur, string); scratch_end(scratch); return result; } //////////////////////////////// //~ rjf: Special Buttons internal UI_Signal ui_expander(B32 is_expanded, String8 string) { ui_set_next_hover_cursor(OS_Cursor_HandPoint); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_font(ui_icon_font()); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, string); ui_box_equip_display_string(box, is_expanded ? str8_lit("v") : str8_lit(">")); UI_Signal sig = ui_signal_from_box(box); return sig; } internal UI_Signal ui_expanderf(B32 is_expanded, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_expander(is_expanded, string); scratch_end(scratch); return sig; } internal UI_Signal ui_sort_header(B32 sorting, B32 ascending, String8 string) { ui_set_next_child_layout_axis(Axis2_X); ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, string); ui_push_parent(box); // rjf: make icon if(sorting) { ui_set_next_pref_width(ui_em(1.8f, 1.f)); ui_set_next_text_alignment(UI_TextAlign_Center); ui_set_next_font(ui_icon_font()); UI_Box *icon = ui_build_box_from_string(UI_BoxFlag_DrawText, str8_lit("")); ui_box_equip_display_string(icon, ascending ? str8_lit("^") : str8_lit("v")); } // rjf: make text { ui_label(string); } ui_pop_parent(); UI_Signal interact = ui_signal_from_box(box); return interact; } internal UI_Signal ui_sort_headerf(B32 sorting, B32 ascending, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_sort_header(sorting, ascending, string); scratch_end(scratch); return sig; } //////////////////////////////// //~ rjf: Color Pickers //- rjf: tooltips internal void ui_do_color_tooltip_hsv(Vec3F32 hsv) { Vec3F32 rgb = rgb_from_hsv(hsv); UI_Tooltip UI_Padding(ui_em(2.f, 1.f)) { UI_PrefWidth(ui_em(22.f, 1.f)) UI_PrefHeight(ui_em(6.f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) { UI_BackgroundColor(linear_from_srgba(v4f32(rgb.x, rgb.y, rgb.z, 1.f))) UI_CornerRadius(4.f) UI_PrefWidth(ui_em(6.f, 1.f)) UI_PrefHeight(ui_em(6.f, 1.f)) ui_build_box_from_string(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, str8_lit("")); } ui_spacer(ui_em(0.3f, 1.f)); UI_PrefWidth(ui_em(22.f, 1.f)) UI_TextAlignment(UI_TextAlign_Center) { ui_labelf("Hex: #%02x%02x%02x", (U8)(rgb.x*255.f), (U8)(rgb.y*255.f), (U8)(rgb.z*255.f)); } ui_spacer(ui_em(0.3f, 1.f)); UI_PrefWidth(ui_em(22.f, 1.f)) UI_PrefHeight(ui_children_sum(1)) UI_Row { UI_WidthFill UI_Column UI_PrefHeight(ui_em(1.8f, 1.f)) { ui_labelf("Red: %.2f", rgb.x); ui_labelf("Green: %.2f", rgb.y); ui_labelf("Blue: %.2f", rgb.z); } UI_WidthFill UI_Column UI_PrefHeight(ui_em(1.8f, 1.f)) { ui_labelf("Hue: %.2f", hsv.x); ui_labelf("Sat: %.2f", hsv.y); ui_labelf("Val: %.2f", hsv.z); } } } } internal void ui_do_color_tooltip_hsva(Vec4F32 hsva) { Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z); Vec3F32 rgb = rgb_from_hsv(hsv); Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w); UI_Tooltip UI_Padding(ui_em(2.f, 1.f)) { UI_PrefWidth(ui_em(22.f, 1.f)) UI_PrefHeight(ui_em(6.f, 1.f)) UI_Row UI_Padding(ui_pct(1, 0)) { UI_BackgroundColor(linear_from_srgba(rgba)) UI_CornerRadius(4.f) UI_PrefWidth(ui_em(6.f, 1.f)) UI_PrefHeight(ui_em(6.f, 1.f)) ui_build_box_from_string(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, str8_lit("")); } ui_spacer(ui_em(0.3f, 1.f)); UI_PrefWidth(ui_em(22.f, 1.f)) UI_TextAlignment(UI_TextAlign_Center) { ui_labelf("Hex: #%02x%02x%02x%02x", (U8)(rgba.x*255.f), (U8)(rgba.y*255.f), (U8)(rgba.z*255.f), (U8)(rgba.w*255.f)); } ui_spacer(ui_em(0.3f, 1.f)); UI_PrefWidth(ui_em(22.f, 1.f)) UI_PrefHeight(ui_children_sum(1)) UI_Row { UI_WidthFill UI_Column UI_PrefHeight(ui_em(1.8f, 1.f)) { ui_labelf("Red: %.2f", rgba.x); ui_labelf("Green: %.2f", rgba.y); ui_labelf("Blue: %.2f", rgba.z); ui_labelf("Alpha: %.2f", rgba.w); } UI_WidthFill UI_Column UI_PrefHeight(ui_em(1.8f, 1.f)) { ui_labelf("Hue: %.2f", hsva.x); ui_labelf("Sat: %.2f", hsva.y); ui_labelf("Val: %.2f", hsva.z); ui_labelf("Alpha: %.2f", hsva.w); } } } } //- rjf: saturation/value picker typedef struct UI_SatValDrawData UI_SatValDrawData; struct UI_SatValDrawData { F32 hue; F32 sat; F32 val; }; internal UI_BOX_CUSTOM_DRAW(ui_sat_val_picker_draw) { UI_SatValDrawData *data = (UI_SatValDrawData *)user_data; // rjf: hue => rgb Vec3F32 hue_rgb = rgb_from_hsv(v3f32(data->hue, 1, 1)); Vec3F32 hue_rgb_linear = linear_from_srgb(hue_rgb); // rjf: rgb background { dr_rect(pad_2f32(box->rect, -1.f), v4f32(hue_rgb_linear.x, hue_rgb_linear.y, hue_rgb_linear.z, 1), 4.f, 0, 1.f); } // rjf: white gradient overlay { R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, -1.f), v4f32(hue_rgb_linear.x, hue_rgb_linear.y, hue_rgb_linear.z, 0), 4.f, 0, 1.f); inst->colors[Corner_00] = inst->colors[Corner_01] = v4f32(1, 1, 1, 1); } // rjf: black gradient overlay pt. 1 { R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, -1.f), v4f32(0, 0, 0, 0), 4.f, 0, 1.f); inst->colors[Corner_01] = v4f32(0, 0, 0, 1.f); inst->colors[Corner_11] = v4f32(0, 0, 0, 1.f); } // rjf: black gradient overlay pt. 2 { R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, -1.f), v4f32(0, 0, 0, 0), 4.f, 0, 1.f); inst->colors[Corner_01] = v4f32(0, 0, 0, 1); inst->colors[Corner_11] = v4f32(0, 0, 0, 1); } // rjf: black gradient overlay pt. 3 { R_Rect2DInst *inst = dr_rect(pad_2f32(box->rect, -1.f), v4f32(0, 0, 0, 0), 4.f, 0, 1.f); inst->colors[Corner_01] = v4f32(0, 0, 0, 0.2f); inst->colors[Corner_11] = v4f32(0, 0, 0, 0.2f); } // rjf: indicator { Vec2F32 box_rect_dim = dim_2f32(box->rect); Vec2F32 center = v2f32(box->rect.x0 + data->sat*box_rect_dim.x, box->rect.y0 + (1-data->val)*box_rect_dim.y); F32 half_size = box->font_size * (0.5f + box->active_t*0.2f); Rng2F32 rect = r2f32p(center.x - half_size, center.y - half_size, center.x + half_size, center.y + half_size); dr_rect(rect, v4f32(1, 1, 1, 1), half_size/2.f, 2.f, 1.f); } } internal UI_Signal ui_sat_val_picker(F32 hue, F32 *out_sat, F32 *out_val, String8 string) { // rjf: build & interact ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable, string); UI_SatValDrawData *user = push_array(ui_build_arena(), UI_SatValDrawData, 1); ui_box_equip_custom_draw(box, ui_sat_val_picker_draw, user); UI_Signal sig = ui_signal_from_box(box); // rjf: click+draw behavior if(ui_dragging(sig)) { Vec2F32 dim = dim_2f32(box->rect); *out_sat = (ui_mouse().x - box->rect.x0) / dim.x; *out_val = 1 - (ui_mouse().y - box->rect.y0) / dim.y; *out_sat = Clamp(0, *out_sat, 1); *out_val = Clamp(0, *out_val, 1); ui_do_color_tooltip_hsv(v3f32(hue, *out_sat, *out_val)); if(ui_pressed(sig)) { Vec2F32 data = v2f32(*out_sat, *out_val); ui_store_drag_struct(&data); } if(ui_slot_press(UI_EventActionSlot_Cancel)) { Vec2F32 data = *ui_get_drag_struct(Vec2F32); *out_sat = data.x; *out_val = data.y; ui_kill_action(); } } // rjf: fill draw data { user->hue = hue; user->sat = *out_sat; user->val = *out_val; } return sig; } internal UI_Signal ui_sat_val_pickerf(F32 hue, F32 *out_sat, F32 *out_val, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_sat_val_picker(hue, out_sat, out_val, string); scratch_end(scratch); return sig; } //- rjf: hue picker typedef struct UI_HueDrawData UI_HueDrawData; struct UI_HueDrawData { F32 hue; F32 sat; F32 val; }; internal UI_BOX_CUSTOM_DRAW(ui_hue_picker_draw) { UI_HueDrawData *data = (UI_HueDrawData *)user_data; Vec2F32 dim = dim_2f32(box->rect); F32 segment_dim = floor_f32(dim.y/6.f); Rng2F32 hue_cycle_rect = box->rect; Vec2F32 hue_cycle_center = center_2f32(hue_cycle_rect); hue_cycle_rect.x0 += (hue_cycle_center.x - hue_cycle_rect.x0) * 0.3f; hue_cycle_rect.x1 += (hue_cycle_center.x - hue_cycle_rect.x1) * 0.3f; Rng2F32 rect = r2f32p(hue_cycle_rect.x0, hue_cycle_rect.y0, hue_cycle_rect.x1, hue_cycle_rect.y0 + segment_dim); for(int seg = 0; seg < 6; seg += 1) { F32 hue0 = (F32)(seg)/6; F32 hue1 = (F32)(seg+1)/6; Vec3F32 rgb0 = rgb_from_hsv(v3f32(hue0, 1, 1)); Vec3F32 rgb1 = rgb_from_hsv(v3f32(hue1, 1, 1)); Vec4F32 rgba0_linear = linear_from_srgba(v4f32(rgb0.x, rgb0.y, rgb0.z, 1)); Vec4F32 rgba1_linear = linear_from_srgba(v4f32(rgb1.x, rgb1.y, rgb1.z, 1)); R_Rect2DInst *inst = dr_rect(rect, v4f32(0, 0, 0, 0), 0, 0, 0.f); inst->colors[Corner_00] = rgba0_linear; inst->colors[Corner_01] = rgba1_linear; inst->colors[Corner_10] = rgba0_linear; inst->colors[Corner_11] = rgba1_linear; rect.y0 += segment_dim; rect.y1 += segment_dim; } // rjf: indicator { Vec2F32 box_rect_dim = dim_2f32(box->rect); Vec2F32 center = v2f32((box->rect.x0+box->rect.x1)/2, box->rect.y0 + (data->hue)*box_rect_dim.y); F32 half_size = box_rect_dim.x * (0.52f + 0.02f * box->active_t); Rng2F32 rect = r2f32p(center.x - half_size, center.y - box->font_size * (0.5f + 0.1f * box->active_t), center.x + half_size, center.y + box->font_size * (0.5f + 0.1f * box->active_t)); dr_rect(rect, v4f32(1, 1, 1, 1), 1.f, 2.f, 1.f); } } internal UI_Signal ui_hue_picker(F32 *out_hue, F32 sat, F32 val, String8 string) { // rjf: build & interact ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable, string); UI_HueDrawData *user = push_array(ui_build_arena(), UI_HueDrawData, 1); ui_box_equip_custom_draw(box, ui_hue_picker_draw, user); UI_Signal sig = ui_signal_from_box(box); // rjf: click+draw behavior if(ui_dragging(sig)) { Vec2F32 dim = dim_2f32(box->rect); *out_hue = (ui_mouse().y - box->rect.y0) / dim.y; *out_hue = Clamp(0, *out_hue, 1); ui_do_color_tooltip_hsv(v3f32(*out_hue, sat, val)); if(ui_pressed(sig)) { ui_store_drag_struct(out_hue); } if(ui_slot_press(UI_EventActionSlot_Cancel)) { *out_hue = *ui_get_drag_struct(F32); ui_kill_action(); } } // rjf: fill draw data { user->hue = *out_hue; user->sat = sat; user->val = val; } return sig; } internal UI_Signal ui_hue_pickerf(F32 *out_hue, F32 sat, F32 val, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_hue_picker(out_hue, sat, val, string); scratch_end(scratch); return sig; } //- rjf: alpha picker typedef struct UI_AlphaDrawData UI_AlphaDrawData; struct UI_AlphaDrawData { F32 alpha; }; internal UI_BOX_CUSTOM_DRAW(ui_alpha_picker_draw) { UI_AlphaDrawData *data = (UI_AlphaDrawData *)user_data; Vec2F32 dim = dim_2f32(box->rect); // rjf: build gradient { Rng2F32 rect = box->rect; Vec2F32 center = center_2f32(rect); rect.x0 += (center.x - rect.x0) * 0.3f; rect.x1 += (center.x - rect.x1) * 0.3f; R_Rect2DInst *inst = dr_rect(rect, v4f32(0, 0, 0, 0), 0, 0, 0); inst->colors[Corner_00] = inst->colors[Corner_10] = v4f32(1, 1, 1, 1); } // rjf: indicator { Vec2F32 box_rect_dim = dim_2f32(box->rect); Vec2F32 center = v2f32((box->rect.x0+box->rect.x1)/2, box->rect.y0 + (1-data->alpha)*box_rect_dim.y); F32 half_size = box_rect_dim.x * (0.52f + 0.02f * box->active_t); Rng2F32 rect = r2f32p(center.x - half_size, center.y - box->font_size * (0.5f + 0.1f * box->active_t), center.x + half_size, center.y + box->font_size * (0.5f + 0.1f * box->active_t)); dr_rect(rect, v4f32(1, 1, 1, 1), 1.f, 2.f, 1.f); } } internal UI_Signal ui_alpha_picker(F32 *out_alpha, String8 string) { // rjf: build & interact ui_set_next_hover_cursor(OS_Cursor_HandPoint); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable, string); UI_AlphaDrawData *user = push_array(ui_build_arena(), UI_AlphaDrawData, 1); ui_box_equip_custom_draw(box, ui_alpha_picker_draw, user); UI_Signal sig = ui_signal_from_box(box); // rjf: click+draw behavior if(ui_dragging(sig)) { Vec2F32 dim = dim_2f32(box->rect); F32 drag_pct = (ui_mouse().y - box->rect.y0) / dim.y; drag_pct = Clamp(0, drag_pct, 1); *out_alpha = 1-drag_pct; if(ui_pressed(sig)) { ui_store_drag_struct(out_alpha); } if(ui_slot_press(UI_EventActionSlot_Cancel)) { *out_alpha = *ui_get_drag_struct(F32); ui_kill_action(); } } // rjf: fill draw data { user->alpha = *out_alpha; } return sig; } internal UI_Signal ui_alpha_pickerf(F32 *out_alpha, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Signal sig = ui_alpha_picker(out_alpha, string); scratch_end(scratch); return sig; } //////////////////////////////// //~ rjf: Simple Layout Widgets internal UI_Box *ui_row_begin(void) { return ui_named_row_begin(str8_lit("")); } internal UI_Signal ui_row_end(void) { return ui_named_row_end(); } internal UI_Box *ui_column_begin(void) { return ui_named_column_begin(str8_lit("")); } internal UI_Signal ui_column_end(void) { return ui_named_column_end(); } internal UI_Box * ui_named_row_begin(String8 string) { ui_set_next_child_layout_axis(Axis2_X); UI_Box *box = ui_build_box_from_string(0, string); ui_push_parent(box); return box; } internal UI_Signal ui_named_row_end(void) { UI_Box *box = ui_pop_parent(); UI_Signal sig = ui_signal_from_box(box); return sig; } internal UI_Box * ui_named_column_begin(String8 string) { ui_set_next_child_layout_axis(Axis2_Y); UI_Box *box = ui_build_box_from_string(0, string); ui_push_parent(box); return box; } internal UI_Signal ui_named_column_end(void) { UI_Box *box = ui_pop_parent(); UI_Signal sig = ui_signal_from_box(box); return sig; } //////////////////////////////// //~ rjf: Floating Panes internal UI_Box * ui_pane_begin(Rng2F32 rect, String8 string) { ui_push_rect(rect); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *box = ui_build_box_from_string(UI_BoxFlag_Clickable|UI_BoxFlag_Clip|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground, string); ui_pop_rect(); ui_push_parent(box); ui_push_pref_width(ui_pct(1, 0)); return box; } internal UI_Box * ui_pane_beginf(Rng2F32 rect, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Box *box = ui_pane_begin(rect, string); scratch_end(scratch); return box; } internal UI_Signal ui_pane_end(void) { ui_pop_pref_width(); UI_Box *box = ui_pop_parent(); UI_Signal sig = ui_signal_from_box(box); return sig; } //////////////////////////////// //~ rjf: Tables thread_static U64 ui_ts_col_pct_count = 0; thread_static F32 *ui_ts_col_pcts_stable = 0; thread_static U64 ui_ts_vector_idx = 0; thread_static U64 ui_ts_cell_idx = 0; internal void ui_table_begin(U64 column_pct_count, F32 **column_pcts, String8 string) { //- rjf: store off persistent, user-provided column info ui_ts_col_pct_count = column_pct_count; //- rjf: build main table parent ui_set_next_pref_height(ui_children_sum(1)); ui_set_next_child_layout_axis(Axis2_Y); UI_Box *table = ui_build_box_from_string(0, string); ui_push_parent(table); //- rjf: build column boundaries F32 x_off = (ui_ts_col_pct_count > 0 ? *column_pcts[0] : 0) * dim_2f32(table->rect).x; for(U64 column_idx = 1; column_idx < ui_ts_col_pct_count; column_idx += 1) { // rjf: build base rectangle Rng2F32 rect = {0}; { rect.x0 = x_off-3.f; rect.y0 = 0; rect.x1 = x_off+3.f; rect.y1 = dim_2f32(table->rect).y; x_off += *column_pcts[column_idx] * dim_2f32(table->rect).x; } // rjf: make column boundary widget UI_Rect(rect) { ui_set_next_hover_cursor(OS_Cursor_LeftRight); UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "###%S_boundary_%I64u", table->string, column_idx); F32 *left_pct_ptr = column_idx < ui_ts_col_pct_count ? column_pcts[column_idx-1] : 0; F32 *right_pct_ptr = column_idx < ui_ts_col_pct_count ? column_pcts[column_idx] : 0; // rjf: boundary dragging UI_Signal interact = ui_signal_from_box(box); if(ui_dragging(interact)) { if(ui_pressed(interact)) { Vec2F32 v = v2f32(*left_pct_ptr, *right_pct_ptr); ui_store_drag_struct(&v); } // rjf: calculate how much space we're dividing amongst the columns that // the user can resize F32 adjustable_table_dim = 0; if(table->child_layout_axis == Axis2_Y) { adjustable_table_dim = dim_2f32(table->rect).x; } else { U64 child_idx = 0; for(UI_Box *v = table->first; !ui_box_is_nil(v); v = v->next, child_idx += 1) { U64 column_idx = (child_idx+1); if(column_idx < ui_ts_col_pct_count) { adjustable_table_dim += dim_2f32(v->rect).x; } else { break; } } } // rjf: calculate diff F32 min_size = 30.f; F32 left_pct__before = ui_get_drag_struct(Vec2F32)->x; F32 left_pixels__before = left_pct__before * adjustable_table_dim; F32 left_pixels__after = left_pixels__before + ui_drag_delta().x; // rjf: clamp left side if(left_pixels__after < min_size) { left_pixels__after = min_size; } // rjf: calculate right side F32 left_pct__after = left_pixels__after / adjustable_table_dim; F32 pct_delta = left_pct__after - left_pct__before; F32 right_pct__before = ui_get_drag_struct(Vec2F32)->y; F32 right_pct__after = right_pct__before - pct_delta; F32 right_pixels__after = right_pct__after * adjustable_table_dim; // rjf: clamp right side & back-solve if(right_pixels__after < min_size) { right_pixels__after = min_size; right_pct__after = right_pixels__after/adjustable_table_dim; pct_delta = -(right_pct__after-right_pct__before); left_pct__after = left_pct__before+pct_delta; } // rjf: commit new percentages *left_pct_ptr = left_pct__after; *right_pct_ptr = right_pct__after; } } } //- rjf: form stable pcts ui_ts_col_pcts_stable = push_array(ui_build_arena(), F32, ui_ts_col_pct_count); for(U64 idx = 0; idx < column_pct_count; idx += 1) { ui_ts_col_pcts_stable[idx] = *column_pcts[idx]; } ui_ts_vector_idx = 0; } internal void ui_table_beginf(U64 column_pct_count, F32 **column_pcts, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); ui_table_begin(column_pct_count, column_pcts, string); scratch_end(scratch); } internal void ui_table_end(void) { ui_pop_parent(); } internal UI_Box * ui_named_table_vector_begin(String8 string) { ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_child_layout_axis(Axis2_X); UI_Box *vector = ui_build_box_from_string(UI_BoxFlag_DrawSideBottom, string); ui_ts_vector_idx += 1; ui_ts_cell_idx = 0; ui_push_parent(vector); return vector; } internal UI_Box * ui_named_table_vector_beginf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Box *vector = ui_named_table_vector_begin(string); scratch_end(scratch); return vector; } internal UI_Box * ui_table_vector_begin(void) { UI_Box *table = ui_top_parent(); UI_Box *vector = ui_named_table_vector_beginf("###tbl_vec_%p_%I64u", table, ui_ts_vector_idx); return vector; } internal UI_Signal ui_table_vector_end(void) { UI_Box *box = ui_pop_parent(); return ui_signal_from_box(box); } internal UI_Box * ui_table_cell_begin(void) { U64 column_idx = ui_ts_cell_idx; F32 width_pct = column_idx < ui_ts_col_pct_count ? ui_ts_col_pcts_stable[column_idx] : 1.f; return ui_table_cell_sized_begin(ui_pct(width_pct, 0)); } internal UI_Signal ui_table_cell_end(void) { UI_Box *cell = ui_pop_parent(); return ui_signal_from_box(cell); } internal UI_Box * ui_table_cell_sized_begin(UI_Size size) { UI_Box *vector = ui_top_parent(); U64 column_idx = ui_ts_cell_idx; ui_ts_cell_idx += 1; ui_set_next_pref_width(size); ui_set_next_child_layout_axis(Axis2_X); UI_Box *cell = ui_build_box_from_stringf((column_idx > 0 ? UI_BoxFlag_DrawSideLeft : 0), "###tbl_cell_%p_%I64u", vector, ui_ts_cell_idx); ui_push_parent(cell); return cell; } //////////////////////////////// //~ rjf: Scroll Regions internal void ui_scroll_list_row_block_chunk_list_push(Arena *arena, UI_ScrollListRowBlockChunkList *list, U64 cap, UI_ScrollListRowBlock *block) { UI_ScrollListRowBlockChunkNode *n = list->last; if(n == 0 || n->count >= n->cap) { n = push_array(arena, UI_ScrollListRowBlockChunkNode, 1); n->cap = cap; n->v = push_array_no_zero(arena, UI_ScrollListRowBlock, n->cap); SLLQueuePush(list->first, list->last, n); list->chunk_count += 1; } MemoryCopyStruct(&n->v[n->count], block); n->count += 1; list->total_count += 1; } internal UI_ScrollListRowBlockArray ui_scroll_list_row_block_array_from_chunk_list(Arena *arena, UI_ScrollListRowBlockChunkList *list) { UI_ScrollListRowBlockArray array = {0}; array.count = list->total_count; array.v = push_array_no_zero(arena, UI_ScrollListRowBlock, array.count); U64 idx = 0; for(UI_ScrollListRowBlockChunkNode *n = list->first; n != 0; n = n->next) { MemoryCopy(array.v+idx, n->v, sizeof(n->v[0])*n->count); idx += n->count; } return array; } internal U64 ui_scroll_list_row_from_item(UI_ScrollListRowBlockArray *blocks, U64 item) { U64 result = 0; { U64 row_idx = 0; U64 item_idx = 0; for(U64 block_idx = 0; block_idx < blocks->count; block_idx += 1) { UI_ScrollListRowBlock *block = &blocks->v[block_idx]; U64 next_row_idx = row_idx + block->row_count; U64 next_item_idx= item_idx+ block->item_count; if(item_idx <= item && item < next_item_idx) { U64 item_off_rows = (item-item_idx) * (block->row_count/block->item_count); result = row_idx + item_off_rows; break; } row_idx = next_row_idx; item_idx = next_item_idx; } } return result; } internal U64 ui_scroll_list_item_from_row(UI_ScrollListRowBlockArray *blocks, U64 row) { U64 result = 0; { U64 row_idx = 0; U64 item_idx = 0; for(U64 block_idx = 0; block_idx < blocks->count; block_idx += 1) { UI_ScrollListRowBlock *block = &blocks->v[block_idx]; U64 next_row_idx = row_idx + block->row_count; U64 next_item_idx= item_idx+ block->item_count; if(row_idx <= row && row < next_row_idx) { result = item_idx; break; } row_idx = next_row_idx; item_idx = next_item_idx; } } return result; } internal UI_ScrollPt ui_scroll_bar(Axis2 axis, UI_Size off_axis_size, UI_ScrollPt pt, Rng1S64 idx_range, S64 view_num_indices) { ui_push_tag(str8_lit("scroll_bar")); ui_push_font_size(ui_bottom_font_size()*0.65f); //- rjf: unpack S64 idx_range_dim = Max(dim_1s64(idx_range), 1); //- rjf: produce extra flags for cases in which scrolling is disabled UI_BoxFlags disabled_flags = 0; if(idx_range.min == idx_range.max) { disabled_flags |= UI_BoxFlag_Disabled; } //- rjf: build main container ui_set_next_pref_size(axis2_flip(axis), off_axis_size); ui_set_next_child_layout_axis(axis); UI_Box *container_box = ui_build_box_from_key(UI_BoxFlag_DrawBorder, ui_key_zero()); //- rjf: build scroll-min button UI_Signal min_scroll_sig = {0}; UI_Parent(container_box) UI_PrefSize(axis, off_axis_size) UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags) UI_TextAlignment(UI_TextAlign_Center) UI_Font(ui_icon_font()) { String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_LeftArrow : UI_IconKind_UpArrow); min_scroll_sig = ui_buttonf("%S##_min_scroll_%i", arrow_string, axis); } //- rjf: main scroller area UI_Signal space_before_sig = {0}; UI_Signal space_after_sig = {0}; UI_Signal scroller_sig = {0}; UI_Box *scroll_area_box = &ui_nil_box; UI_Box *scroller_box = &ui_nil_box; UI_Parent(container_box) { ui_set_next_pref_size(axis, ui_pct(1, 0)); ui_set_next_child_layout_axis(axis); scroll_area_box = ui_build_box_from_stringf(0, "##_scroll_area_%i", axis); UI_Parent(scroll_area_box) { // rjf: space before if(idx_range.max != idx_range.min) { ui_set_next_pref_size(axis, ui_pct((F32)((F64)(pt.idx-idx_range.min)/(F64)idx_range_dim), 0)); UI_Box *space_before_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "##scroll_area_before"); space_before_sig = ui_signal_from_box(space_before_box); } // rjf: scroller UI_Flags(disabled_flags) UI_PrefSize(axis, ui_pct(Clamp(0.05f, (F32)((F64)Max(view_num_indices, 1)/(F64)idx_range_dim), 1.f), 0.f)) { scroller_sig = ui_buttonf("##_scroller_%i", axis); scroller_box = scroller_sig.box; } // rjf: space after if(idx_range.max != idx_range.min) { ui_set_next_pref_size(axis, ui_pct(1.f - (F32)((F64)(pt.idx-idx_range.min)/(F64)idx_range_dim), 0)); UI_Box *space_after_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable, "##scroll_area_after"); space_after_sig = ui_signal_from_box(space_after_box); } } } //- rjf: build scroll-max button UI_Signal max_scroll_sig = {0}; UI_Parent(container_box) UI_PrefSize(axis, off_axis_size) UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags) UI_TextAlignment(UI_TextAlign_Center) UI_Font(ui_icon_font()) { String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_RightArrow : UI_IconKind_DownArrow); max_scroll_sig = ui_buttonf("%S##_max_scroll_%i", arrow_string, axis); } //- rjf: pt * signals -> new pt UI_ScrollPt new_pt = pt; { typedef struct UI_ScrollBarDragData UI_ScrollBarDragData; struct UI_ScrollBarDragData { UI_ScrollPt start_pt; F32 scroll_space_px; }; if(ui_dragging(scroller_sig)) { if(ui_pressed(scroller_sig)) { UI_ScrollBarDragData drag_data = {pt, (floor_f32(dim_2f32(scroll_area_box->rect).v[axis])-floor_f32(dim_2f32(scroller_box->rect).v[axis]))}; ui_store_drag_struct(&drag_data); } UI_ScrollBarDragData *drag_data = ui_get_drag_struct(UI_ScrollBarDragData); UI_ScrollPt original_pt = drag_data->start_pt; F32 drag_delta = ui_drag_delta().v[axis]; F32 drag_pct = drag_delta / drag_data->scroll_space_px; S64 new_idx = original_pt.idx + drag_pct*idx_range_dim; new_idx = Clamp(idx_range.min, new_idx, idx_range.max); ui_scroll_pt_target_idx(&new_pt, new_idx); new_pt.off = 0; } if(ui_dragging(min_scroll_sig) || ui_dragging(space_before_sig)) { S64 new_idx = new_pt.idx-1; new_idx = Clamp(idx_range.min, new_idx, idx_range.max); ui_scroll_pt_target_idx(&new_pt, new_idx); } if(ui_dragging(max_scroll_sig) || ui_dragging(space_after_sig)) { S64 new_idx = new_pt.idx+1; new_idx = Clamp(idx_range.min, new_idx, idx_range.max); ui_scroll_pt_target_idx(&new_pt, new_idx); } } ui_pop_font_size(); ui_pop_tag(); return new_pt; } thread_static UI_ScrollPt *ui_scroll_list_scroll_pt_ptr = 0; thread_static F32 ui_scroll_list_scroll_bar_dim_px = 0; thread_static Vec2F32 ui_scroll_list_dim_px = {0}; thread_static Rng1S64 ui_scroll_list_scroll_idx_rng = {0}; internal void ui_scroll_list_begin(UI_ScrollListParams *params, UI_ScrollPt *scroll_pt, Vec2S64 *cursor_out, Vec2S64 *mark_out, Rng1S64 *visible_row_range_out, UI_ScrollListSignal *signal_out) { //- rjf: unpack arguments Rng1S64 scroll_row_idx_range = r1s64(params->item_range.min, ClampBot(params->item_range.min, params->item_range.max-1)); S64 num_possible_visible_rows = (S64)(params->dim_px.y/params->row_height_px); //- rjf: do keyboard navigation B32 moved = 0; if(params->flags & UI_ScrollListFlag_Nav && cursor_out != 0 && ui_is_focus_active()) { Vec2S64 cursor = *cursor_out; Vec2S64 mark = mark_out ? *mark_out : cursor; for(UI_Event *evt = 0; ui_next_event(&evt);) { if((evt->delta_2s32.x == 0 && evt->delta_2s32.y == 0) || evt->flags & UI_EventFlag_Delete) { continue; } ui_eat_event(evt); moved = 1; switch(evt->delta_unit) { default:{moved = 0;}break; case UI_EventDeltaUnit_Char: { for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis+1)) { cursor.v[axis] += evt->delta_2s32.v[axis]; if(cursor.v[axis] < params->cursor_range.min.v[axis]) { cursor.v[axis] = params->cursor_range.max.v[axis]; } if(cursor.v[axis] > params->cursor_range.max.v[axis]) { cursor.v[axis] = params->cursor_range.min.v[axis]; } cursor.v[axis] = clamp_1s64(r1s64(params->cursor_range.min.v[axis], params->cursor_range.max.v[axis]), cursor.v[axis]); } }break; case UI_EventDeltaUnit_Word: case UI_EventDeltaUnit_Line: case UI_EventDeltaUnit_Page: { cursor.x = (evt->delta_2s32.x>0 ? params->cursor_range.max.x : evt->delta_2s32.x<0 ? params->cursor_range.min.x + !!params->cursor_min_is_empty_selection[Axis2_X] : cursor.x); cursor.y += ((evt->delta_2s32.y>0 ? +(num_possible_visible_rows-3) : evt->delta_2s32.y<0 ? -(num_possible_visible_rows-3) : 0)); cursor.y = clamp_1s64(r1s64(params->cursor_range.min.y + !!params->cursor_min_is_empty_selection[Axis2_Y], params->cursor_range.max.y), cursor.y); }break; case UI_EventDeltaUnit_Whole: { for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis+1)) { cursor.v[axis] = (evt->delta_2s32.v[axis]>0 ? params->cursor_range.max.v[axis] : evt->delta_2s32.v[axis]<0 ? params->cursor_range.min.v[axis] + !!params->cursor_min_is_empty_selection[axis] : cursor.v[axis]); } }break; } if(!(evt->flags & UI_EventFlag_KeepMark)) { mark = cursor; } } if(moved) { *cursor_out = cursor; if(mark_out) { *mark_out = mark; } } } //- rjf: moved -> snap if(params->flags & UI_ScrollListFlag_Snap && moved) { S64 cursor_item_idx = cursor_out->y-1; if(params->item_range.min <= cursor_item_idx && cursor_item_idx <= params->item_range.max) { //- rjf: compute visible row range Rng1S64 visible_row_range = r1s64(scroll_pt->idx + 0 - !!(scroll_pt->off < 0), scroll_pt->idx + 0 + num_possible_visible_rows + 1); //- rjf: compute cursor row range from cursor item Rng1S64 cursor_visibility_row_range = {0}; if(params->row_blocks.count == 0) { cursor_visibility_row_range = r1s64(cursor_item_idx-1, cursor_item_idx+3); } else { cursor_visibility_row_range.min = (S64)ui_scroll_list_row_from_item(¶ms->row_blocks, (U64)cursor_item_idx); cursor_visibility_row_range.max = cursor_visibility_row_range.min + 4; } //- rjf: compute deltas & apply S64 min_delta = Min(0, cursor_visibility_row_range.min-visible_row_range.min); S64 max_delta = Max(0, cursor_visibility_row_range.max-visible_row_range.max); S64 new_idx = scroll_pt->idx+min_delta+max_delta; new_idx = clamp_1s64(scroll_row_idx_range, new_idx); ui_scroll_pt_target_idx(scroll_pt, new_idx); } } //- rjf: output signal if(signal_out != 0) { signal_out->cursor_moved = moved; } //- rjf: determine ranges & limits Rng1S64 visible_row_range = r1s64(scroll_pt->idx + (S64)(scroll_pt->off) + 0 - !!(scroll_pt->off < 0), scroll_pt->idx + (S64)(scroll_pt->off) + 0 + num_possible_visible_rows + 1); visible_row_range.min = clamp_1s64(params->item_range, visible_row_range.min); visible_row_range.max = clamp_1s64(params->item_range, visible_row_range.max); *visible_row_range_out = visible_row_range; //- rjf: store thread-locals ui_scroll_list_scroll_bar_dim_px = ui_bottom_font_size()*1.5f; ui_scroll_list_scroll_pt_ptr = scroll_pt; ui_scroll_list_dim_px = params->dim_px; ui_scroll_list_scroll_idx_rng = scroll_row_idx_range; //- rjf: build top-level container UI_Box *container_box = &ui_nil_box; UI_FixedWidth(params->dim_px.x) UI_FixedHeight(params->dim_px.y) UI_ChildLayoutAxis(Axis2_X) { container_box = ui_build_box_from_key(0, ui_key_zero()); } //- rjf: build scrollable container UI_Box *scrollable_container_box = &ui_nil_box; UI_Parent(container_box) UI_ChildLayoutAxis(Axis2_Y) UI_FixedWidth(params->dim_px.x-ui_scroll_list_scroll_bar_dim_px) UI_FixedHeight(params->dim_px.y) { scrollable_container_box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_AllowOverflowY|UI_BoxFlag_Scroll, "###sp"); scrollable_container_box->view_off.y = scrollable_container_box->view_off_target.y = params->row_height_px*mod_f32(scroll_pt->off, 1.f) + params->row_height_px*(scroll_pt->off < 0) - params->row_height_px*(scroll_pt->off == -1.f && scroll_pt->idx == 1); } //- rjf: build vertical scroll bar UI_Parent(container_box) UI_Focus(UI_FocusKind_Null) { ui_set_next_fixed_width(ui_scroll_list_scroll_bar_dim_px); ui_set_next_fixed_height(ui_scroll_list_dim_px.y); *ui_scroll_list_scroll_pt_ptr = ui_scroll_bar(Axis2_Y, ui_px(ui_scroll_list_scroll_bar_dim_px, 1.f), *ui_scroll_list_scroll_pt_ptr, scroll_row_idx_range, num_possible_visible_rows); } //- rjf: begin scrollable region ui_push_parent(container_box); ui_push_parent(scrollable_container_box); ui_push_pref_height(ui_px(params->row_height_px, 1.f)); } internal void ui_scroll_list_end(void) { ui_pop_pref_height(); UI_Box *scrollable_container_box = ui_pop_parent(); UI_Box *container_box = ui_pop_parent(); //- rjf: scroll { UI_Signal sig = ui_signal_from_box(scrollable_container_box); if(sig.scroll.y != 0) { S64 new_idx = ui_scroll_list_scroll_pt_ptr->idx + sig.scroll.y; new_idx = clamp_1s64(ui_scroll_list_scroll_idx_rng, new_idx); ui_scroll_pt_target_idx(ui_scroll_list_scroll_pt_ptr, new_idx); } ui_scroll_pt_clamp_idx(ui_scroll_list_scroll_pt_ptr, ui_scroll_list_scroll_idx_rng); } } ================================================ FILE: src/ui/ui_basic_widgets.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_BASIC_WIDGETS_H #define UI_BASIC_WIDGETS_H //////////////////////////////// //~ rjf: Scroll List Types typedef U32 UI_ScrollListFlags; enum { UI_ScrollListFlag_Nav = (1<<0), UI_ScrollListFlag_Snap = (1<<1), UI_ScrollListFlag_All = 0xffffffff, }; typedef struct UI_ScrollListRowBlock UI_ScrollListRowBlock; struct UI_ScrollListRowBlock { U64 row_count; U64 item_count; }; typedef struct UI_ScrollListRowBlockChunkNode UI_ScrollListRowBlockChunkNode; struct UI_ScrollListRowBlockChunkNode { UI_ScrollListRowBlockChunkNode *next; UI_ScrollListRowBlock *v; U64 count; U64 cap; }; typedef struct UI_ScrollListRowBlockChunkList UI_ScrollListRowBlockChunkList; struct UI_ScrollListRowBlockChunkList { UI_ScrollListRowBlockChunkNode *first; UI_ScrollListRowBlockChunkNode *last; U64 chunk_count; U64 total_count; }; typedef struct UI_ScrollListRowBlockArray UI_ScrollListRowBlockArray; struct UI_ScrollListRowBlockArray { UI_ScrollListRowBlock *v; U64 count; }; typedef struct UI_ScrollListParams UI_ScrollListParams; struct UI_ScrollListParams { UI_ScrollListFlags flags; Vec2F32 dim_px; F32 row_height_px; UI_ScrollListRowBlockArray row_blocks; Rng2S64 cursor_range; Rng1S64 item_range; B32 cursor_min_is_empty_selection[Axis2_COUNT]; }; typedef struct UI_ScrollListSignal UI_ScrollListSignal; struct UI_ScrollListSignal { B32 cursor_moved; }; //////////////////////////////// //~ rjf: Basic Widgets internal void ui_divider(UI_Size size); internal UI_Signal ui_label(String8 string); internal UI_Signal ui_labelf(char *fmt, ...); internal void ui_label_multiline(F32 max, String8 string); internal void ui_label_multilinef(F32 max, char *fmt, ...); internal UI_Signal ui_button(String8 string); internal UI_Signal ui_buttonf(char *fmt, ...); internal UI_Signal ui_hover_label(String8 string); internal UI_Signal ui_hover_labelf(char *fmt, ...); internal UI_Signal ui_line_edit(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, String8 pre_edit_value, String8 string); internal UI_Signal ui_line_editf(TxtPt *cursor, TxtPt *mark, U8 *edit_buffer, U64 edit_buffer_size, U64 *edit_string_size_out, String8 pre_edit_value, char *fmt, ...); //////////////////////////////// //~ rjf: Images internal UI_Signal ui_image(R_Handle texture, R_Tex2DSampleKind sample_kind, Rng2F32 region, Vec4F32 tint, F32 blur, String8 string); internal UI_Signal ui_imagef(R_Handle texture, R_Tex2DSampleKind sample_kind, Rng2F32 region, Vec4F32 tint, F32 blur, char *fmt, ...); //////////////////////////////// //~ rjf: Special Buttons internal UI_Signal ui_expander(B32 is_expanded, String8 string); internal UI_Signal ui_expanderf(B32 is_expanded, char *fmt, ...); internal UI_Signal ui_sort_header(B32 sorting, B32 ascending, String8 string); internal UI_Signal ui_sort_headerf(B32 sorting, B32 ascending, char *fmt, ...); //////////////////////////////// //~ rjf: Color Pickers //- rjf: tooltips internal void ui_do_color_tooltip_hsv(Vec3F32 hsv); internal void ui_do_color_tooltip_hsva(Vec4F32 hsva); //- rjf: saturation/value picker internal UI_Signal ui_sat_val_picker(F32 hue, F32 *out_sat, F32 *out_val, String8 string); internal UI_Signal ui_sat_val_pickerf(F32 hue, F32 *out_sat, F32 *out_val, char *fmt, ...); //- rjf: hue picker internal UI_Signal ui_hue_picker(F32 *out_hue, F32 sat, F32 val, String8 string); internal UI_Signal ui_hue_pickerf(F32 *out_hue, F32 sat, F32 val, char *fmt, ...); //- rjf: alpha picker internal UI_Signal ui_alpha_picker(F32 *out_alpha, String8 string); internal UI_Signal ui_alpha_pickerf(F32 *out_alpha, char *fmt, ...); //////////////////////////////// //~ rjf: Simple Layout Widgets internal UI_Box *ui_row_begin(void); internal UI_Signal ui_row_end(void); internal UI_Box *ui_column_begin(void); internal UI_Signal ui_column_end(void); internal UI_Box *ui_named_row_begin(String8 string); internal UI_Signal ui_named_row_end(void); internal UI_Box *ui_named_column_begin(String8 string); internal UI_Signal ui_named_column_end(void); //////////////////////////////// //~ rjf: Floating Panes internal UI_Box *ui_pane_begin(Rng2F32 rect, String8 string); internal UI_Box *ui_pane_beginf(Rng2F32 rect, char *fmt, ...); internal UI_Signal ui_pane_end(void); //////////////////////////////// //~ rjf: Tables internal void ui_table_begin(U64 column_pct_count, F32 **column_pcts, String8 string); internal void ui_table_beginf(U64 column_pct_count, F32 **column_pcts, char *fmt, ...); internal void ui_table_end(void); internal UI_Box * ui_named_table_vector_begin(String8 string); internal UI_Box * ui_named_table_vector_beginf(char *fmt, ...); internal UI_Box * ui_table_vector_begin(void); internal UI_Signal ui_table_vector_end(void); internal UI_Box * ui_table_cell_begin(void); internal UI_Signal ui_table_cell_end(void); internal UI_Box * ui_table_cell_sized_begin(UI_Size size); //////////////////////////////// //~ rjf: Scroll Regions internal void ui_scroll_list_row_block_chunk_list_push(Arena *arena, UI_ScrollListRowBlockChunkList *list, U64 cap, UI_ScrollListRowBlock *block); internal UI_ScrollListRowBlockArray ui_scroll_list_row_block_array_from_chunk_list(Arena *arena, UI_ScrollListRowBlockChunkList *list); internal U64 ui_scroll_list_row_from_item(UI_ScrollListRowBlockArray *blocks, U64 item); internal U64 ui_scroll_list_item_from_row(UI_ScrollListRowBlockArray *blocks, U64 row); internal UI_ScrollPt ui_scroll_bar(Axis2 axis, UI_Size off_axis_size, UI_ScrollPt pt, Rng1S64 idx_range, S64 view_num_indices); internal void ui_scroll_list_begin(UI_ScrollListParams *params, UI_ScrollPt *scroll_pt_out, Vec2S64 *cursor_out, Vec2S64 *mark_out, Rng1S64 *visible_row_range_out, UI_ScrollListSignal *signal_out); internal void ui_scroll_list_end(void); //////////////////////////////// //~ rjf: Macro Loop Wrappers #define UI_Row DeferLoop(ui_row_begin(), ui_row_end()) #define UI_Column DeferLoop(ui_column_begin(), ui_column_end()) #define UI_NamedRow(s) DeferLoop(ui_named_row_begin(s), ui_named_row_end()) #define UI_NamedColumn(s) DeferLoop(ui_named_column_begin(s), ui_named_column_end()) #define UI_Pane(r, s) DeferLoop(ui_pane_begin(r, s), ui_pane_end()) #define UI_PaneF(r, ...) DeferLoop(ui_pane_beginf(r, __VA_ARGS__), ui_pane_end()) #define UI_Padding(size) DeferLoop(ui_spacer(size), ui_spacer(size)) #define UI_Center UI_Padding(ui_pct(1, 0)) #define UI_Table(col_pct_count, col_pcts, s) DeferLoop(ui_table_begin(col_pct_count, col_pcts, s), ui_table_end()) #define UI_TableF(col_pct_count, col_pcts, ...) DeferLoop(ui_table_beginf(col_pct_count, col_pcts, __VA_ARGS__), ui_table_end()) #define UI_NamedTableVector(s) DeferLoop(ui_named_table_vector_begin(s), ui_table_vector_end()) #define UI_NamedTableVectorF(...) DeferLoop(ui_named_table_vector_beginf(__VA_ARGS__), ui_table_vector_end()) #define UI_TableVector DeferLoop(ui_table_vector_begin(), ui_table_vector_end()) #define UI_TableCell DeferLoop(ui_table_cell_begin(), ui_table_cell_end()) #define UI_TableCellSized(size) DeferLoop(ui_table_cell_sized_begin(size), ui_table_cell_end()) #define UI_ScrollList(params, scroll_pt_out, cursor_out, mark_out, visible_row_range_out, signal_out) DeferLoop(ui_scroll_list_begin((params), (scroll_pt_out), (cursor_out), (mark_out), (visible_row_range_out), (signal_out)), ui_scroll_list_end()) #endif // UI_BASIC_WIDGETS_H ================================================ FILE: src/ui/ui_core.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// //~ rjf: Globals thread_static UI_State *ui_state = 0; //////////////////////////////// //~ rjf: Basic Type Functions internal String8 ui_hash_part_from_key_string(String8 string) { String8 result = string; // rjf: look for ### patterns, which can replace the entirety of the part of // the string that is hashed. U64 hash_replace_signifier_pos = str8_find_needle(string, 0, str8_lit("###"), 0); if(hash_replace_signifier_pos < string.size) { result = str8_skip(string, hash_replace_signifier_pos); } return result; } internal String8 ui_display_part_from_key_string(String8 string) { U64 hash_pos = str8_find_needle(string, 0, str8_lit("##"), 0); string.size = hash_pos; return string; } internal UI_Key ui_key_zero(void) { UI_Key result = {0}; return result; } internal UI_Key ui_key_make(U64 v) { UI_Key result = {v}; return result; } internal UI_Key ui_key_from_string(UI_Key seed_key, String8 string) { UI_Key result = {0}; if(string.size != 0) { String8 hash_part = ui_hash_part_from_key_string(string); result.u64[0] = u64_hash_from_seed_str8(seed_key.u64[0], hash_part); } return result; } internal UI_Key ui_key_from_stringf(UI_Key seed_key, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Key key = ui_key_from_string(seed_key, string); scratch_end(scratch); return key; } internal B32 ui_key_match(UI_Key a, UI_Key b) { return a.u64[0] == b.u64[0]; } //////////////////////////////// //~ rjf: Event Type Functions internal UI_EventNode * ui_event_list_push(Arena *arena, UI_EventList *list, UI_Event *v) { UI_EventNode *n = push_array(arena, UI_EventNode, 1); MemoryCopyStruct(&n->v, v); n->v.string = push_str8_copy(arena, n->v.string); DLLPushBack(list->first, list->last, n); list->count += 1; return n; } internal void ui_eat_event_node(UI_EventList *list, UI_EventNode *node) { DLLRemove(list->first, list->last, node); list->count -= 1; } //////////////////////////////// //~ rjf: Text Operation Functions internal B32 ui_char_is_scan_boundary(U8 c) { return (char_is_alpha(c) || char_is_digit(c, 10) || c == '_'); } internal S64 ui_scanned_column_from_column(String8 string, S64 start_column, Side side) { S64 new_column = start_column; S64 delta = (!!side)*2 - 1; B32 found_text = 0; B32 found_non_space = 0; S64 start_off = delta < 0 ? delta : 0; for(S64 col = start_column+start_off; 1 <= col && col <= string.size+1; col += delta) { U8 byte = (col <= string.size) ? string.str[col-1] : 0; B32 is_non_space = !char_is_space(byte); B32 is_name = ui_char_is_scan_boundary(byte); if(((side == Side_Min) && (col == 1)) || ((side == Side_Max) && (col == string.size+1)) || (found_non_space && !is_non_space) || (found_text && !is_name)) { new_column = col + (!side && col != 1); break; } else if (!found_text && is_name) { found_text = 1; } else if (!found_non_space && is_non_space) { found_non_space = 1; } } return new_column; } internal UI_TxtOp ui_single_line_txt_op_from_event(Arena *arena, UI_Event *event, String8 string, TxtPt cursor, TxtPt mark) { TxtPt next_cursor = cursor; TxtPt next_mark = mark; TxtRng range = {0}; String8 replace = {0}; String8 copy = {0}; UI_TxtOpFlags flags = 0; Vec2S32 delta = event->delta_2s32; Vec2S32 original_delta = delta; //- rjf: resolve high-level delta into byte delta, based on unit switch(event->delta_unit) { default:{}break; case UI_EventDeltaUnit_Char: { // TODO(rjf): this should account for multi-byte characters in UTF-8... for now, just assume ASCII and // no-op }break; case UI_EventDeltaUnit_Word: { delta.x = (S32)ui_scanned_column_from_column(string, cursor.column, delta.x > 0 ? Side_Max : Side_Min) - cursor.column; }break; case UI_EventDeltaUnit_Line: case UI_EventDeltaUnit_Whole: case UI_EventDeltaUnit_Page: { S64 first_nonwhitespace_column = 1; for(U64 idx = 0; idx < string.size; idx += 1) { if(!char_is_space(string.str[idx])) { first_nonwhitespace_column = (S64)idx + 1; break; } } S64 home_dest_column = (cursor.column == first_nonwhitespace_column) ? 1 : first_nonwhitespace_column; delta.x = (delta.x > 0) ? ((S64)string.size+1 - cursor.column) : (home_dest_column - cursor.column); }break; } //- rjf: zero delta if(!txt_pt_match(cursor, mark) && event->flags & UI_EventFlag_ZeroDeltaOnSelect) { delta = v2s32(0, 0); } //- rjf: form next cursor if(txt_pt_match(cursor, mark) || !(event->flags & UI_EventFlag_ZeroDeltaOnSelect)) { next_cursor.column += delta.x; } //- rjf: cap at line if(event->flags & UI_EventFlag_CapAtLine) { next_cursor.column = Clamp(1, next_cursor.column, (S64)(string.size+1)); } //- rjf: in some cases, we want to pick a selection side based on the delta if(!txt_pt_match(cursor, mark) && event->flags & UI_EventFlag_PickSelectSide) { if(original_delta.x < 0 || original_delta.y < 0) { next_cursor = next_mark = txt_pt_min(cursor, mark); } else if(original_delta.x > 0 || original_delta.y > 0) { next_cursor = next_mark = txt_pt_max(cursor, mark); } } //- rjf: copying if(event->flags & UI_EventFlag_Copy) { if(cursor.line == mark.line) { copy = str8_substr(string, r1u64(cursor.column-1, mark.column-1)); flags |= UI_TxtOpFlag_Copy; } else { flags |= UI_TxtOpFlag_Invalid; } } //- rjf: pasting if(event->flags & UI_EventFlag_Paste) { range = txt_rng(cursor, mark); replace = os_get_clipboard_text(arena); next_cursor = next_mark = txt_pt(cursor.line, cursor.column+replace.size); } //- rjf: deletion if(event->flags & UI_EventFlag_Delete) { TxtPt new_pos = txt_pt_min(next_cursor, next_mark); range = txt_rng(next_cursor, next_mark); replace = str8_lit(""); next_cursor = next_mark = new_pos; } //- rjf: stick mark to cursor, when we don't want to keep it in the same spot if(!(event->flags & UI_EventFlag_KeepMark)) { next_mark = next_cursor; } //- rjf: insertion if(event->string.size != 0) { range = txt_rng(cursor, mark); replace = push_str8_copy(arena, event->string); next_cursor = next_mark = txt_pt(range.min.line, range.min.column + event->string.size); } //- rjf: determine if this event should be taken, based on bounds of cursor { if(next_cursor.column > string.size+1 || 1 > next_cursor.column || event->delta_2s32.y != 0) { flags |= UI_TxtOpFlag_Invalid; } next_cursor.column = Clamp(1, next_cursor.column, string.size+replace.size+1); next_mark.column = Clamp(1, next_mark.column, string.size+replace.size+1); } //- rjf: build+fill UI_TxtOp op = {0}; { op.flags = flags; op.replace = replace; op.copy = copy; op.range = range; op.cursor = next_cursor; op.mark = next_mark; } return op; } internal String8 ui_push_string_replace_range(Arena *arena, String8 string, Rng1S64 col_range, String8 replace) { //- rjf: convert to offset range Rng1U64 range = { (U64)(col_range.min-1), (U64)(col_range.max-1), }; //- rjf: clamp range if(range.min > string.size) { range.min = 0; } if(range.max > string.size) { range.max = string.size; } //- rjf: calculate new size U64 old_size = string.size; U64 new_size = old_size - (range.max - range.min) + replace.size; //- rjf: push+fill new string storage U8 *push_base = push_array(arena, U8, new_size); { MemoryCopy(push_base+0, string.str, range.min); MemoryCopy(push_base+range.min+replace.size, string.str+range.max, string.size-range.max); if(replace.str != 0) { MemoryCopy(push_base+range.min, replace.str, replace.size); } } String8 result = str8(push_base, new_size); return result; } //////////////////////////////// //~ rjf: Sizes internal UI_Size ui_size(UI_SizeKind kind, F32 value, F32 strictness) { UI_Size size = {kind, value, strictness}; return size; } //////////////////////////////// //~ rjf: Scroll Point Type Functions internal UI_ScrollPt ui_scroll_pt(S64 idx, F32 off) { UI_ScrollPt pt = {idx, off}; return pt; } internal void ui_scroll_pt_target_idx(UI_ScrollPt *v, S64 idx) { v->off = mod_f32(v->off, 1.f) + (F32)(v->idx+(S64)v->off - idx); v->idx = idx; } internal void ui_scroll_pt_clamp_idx(UI_ScrollPt *v, Rng1S64 range) { if(v->idx < range.min || range.max < v->idx) { S64 clamped = range.min; ui_scroll_pt_target_idx(v, clamped); } } //////////////////////////////// //~ rjf: Boxes internal B32 ui_box_is_nil(UI_Box *box) { return box == 0 || box == &ui_nil_box; } internal UI_BoxRec ui_box_rec_df(UI_Box *box, UI_Box *root, U64 sib_member_off, U64 child_member_off) { UI_BoxRec result = {0}; result.next = &ui_nil_box; if(!ui_box_is_nil(*MemberFromOffset(UI_Box **, box, child_member_off))) { result.next = *MemberFromOffset(UI_Box **, box, child_member_off); result.push_count = 1; } else for(UI_Box *p = box; !ui_box_is_nil(p) && p != root; p = p->parent) { if(!ui_box_is_nil(*MemberFromOffset(UI_Box **, p, sib_member_off))) { result.next = *MemberFromOffset(UI_Box **, p, sib_member_off); break; } result.pop_count += 1; } return result; } internal void ui_box_list_push(Arena *arena, UI_BoxList *list, UI_Box *box) { UI_BoxNode *n = push_array(arena, UI_BoxNode, 1); n->box = box; SLLQueuePush(list->first, list->last, n); list->count += 1; } //////////////////////////////// //~ rjf: State Building / Selecting internal UI_State * ui_state_alloc(void) { Arena *arena = arena_alloc(); UI_State *ui = push_array(arena, UI_State, 1); ui->arena = arena; ui->external_key = ui_key_from_string(ui_key_zero(), str8_lit("###external_interaction_key###")); ui->build_arenas[0] = arena_alloc(); ui->build_arenas[1] = arena_alloc(); ui->drag_state_arena = arena_alloc(); ui->string_hover_arena = arena_alloc(); ui->box_table_size = 4096; ui->box_table = push_array(arena, UI_BoxHashSlot, ui->box_table_size); ui->anim_slots_count = 4096; ui->anim_slots = push_array(arena, UI_AnimSlot, ui->anim_slots_count); ui->theme_pattern_cache_slots_count = 1024; ui->theme_pattern_cache_slots = push_array(arena, UI_ThemePatternCacheSlot, ui->theme_pattern_cache_slots_count); UI_InitStackNils(ui); return ui; } internal void ui_state_release(UI_State *state) { arena_release(state->string_hover_arena); arena_release(state->drag_state_arena); for(int i = 0; i < ArrayCount(state->build_arenas); i += 1) { arena_release(state->build_arenas[i]); } arena_release(state->arena); } internal UI_Box * ui_root_from_state(UI_State *state) { return state->root; } internal B32 ui_animating_from_state(UI_State *state) { return state->is_animating; } internal void ui_select_state(UI_State *state) { ui_state = state; } internal UI_State * ui_get_selected_state(void) { return ui_state; } //////////////////////////////// //~ rjf: Implicit State Accessors/Mutators //- rjf: per-frame info internal Arena * ui_build_arena(void) { Arena *result = ui_state->build_arenas[ui_state->build_index%ArrayCount(ui_state->build_arenas)]; return result; } internal OS_Handle ui_window(void) { return ui_state->window; } internal Vec2F32 ui_mouse(void) { return ui_state->mouse; } internal FNT_Tag ui_icon_font(void) { return ui_state->icon_info.icon_font; } internal String8 ui_icon_string_from_kind(UI_IconKind icon_kind) { return ui_state->icon_info.icon_kind_text_map[icon_kind]; } internal F32 ui_dt(void) { return ui_state->animation_dt; } //- rjf: event pumping internal B32 ui_next_event(UI_Event **ev) { UI_EventList *events = ui_state->events; UI_EventNode *start_node = events->first; if(ev[0] != 0) { start_node = CastFromMember(UI_EventNode, v, ev[0]); start_node = start_node->next; ev[0] = 0; } if(start_node != 0) { UI_PermissionFlags perms = ui_top_permission_flags(); for(UI_EventNode *n = start_node; n != 0; n = n->next) { B32 good = 1; if(!(perms & UI_PermissionFlag_ClicksLeft) && (n->v.kind == UI_EventKind_Press || n->v.kind == UI_EventKind_Release) && (n->v.key == OS_Key_LeftMouseButton)) { good = 0; } if(!(perms & UI_PermissionFlag_ClicksMiddle) && (n->v.kind == UI_EventKind_Press || n->v.kind == UI_EventKind_Release) && (n->v.key == OS_Key_MiddleMouseButton)) { good = 0; } if(!(perms & UI_PermissionFlag_ClicksRight) && (n->v.kind == UI_EventKind_Press || n->v.kind == UI_EventKind_Release) && (n->v.key == OS_Key_RightMouseButton)) { good = 0; } if(!(perms & UI_PermissionFlag_ScrollX) && (n->v.kind == UI_EventKind_Scroll) && (n->v.delta_2f32.x != 0 || n->v.modifiers == OS_Modifier_Shift)) { good = 0; } if(!(perms & UI_PermissionFlag_ScrollY) && (n->v.kind == UI_EventKind_Scroll) && n->v.delta_2f32.y != 0 && n->v.modifiers == 0) { good = 0; } if((n->v.kind == UI_EventKind_Press || n->v.kind == UI_EventKind_Release || n->v.kind == UI_EventKind_Navigate || n->v.kind == UI_EventKind_Edit) && (n->v.key != OS_Key_LeftMouseButton && n->v.key != OS_Key_MiddleMouseButton && n->v.key != OS_Key_RightMouseButton)) { if((perms & UI_PermissionFlag_Keyboard) == UI_PermissionFlag_KeyboardSecondary) { good = !!(n->v.flags & UI_EventFlag_Secondary); } else if(!(perms & UI_PermissionFlag_Keyboard)) { good = 0; } } else if(!(perms & UI_PermissionFlag_Text) && (n->v.kind == UI_EventKind_Text)) { good = 0; } if(good) { ev[0] = &n->v; break; } } } B32 result = !!ev[0]; return result; } internal void ui_eat_event(UI_Event *ev) { if(ev != 0) { UI_EventNode *n = CastFromMember(UI_EventNode, v, ev); ui_eat_event_node(ui_state->events, n); } } //- rjf: event consumption helpers internal B32 ui_key_press(OS_Modifiers mods, OS_Key key) { B32 result = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && evt->key == key && evt->modifiers == mods) { result = 1; ui_eat_event(evt); break; } } return result; } internal B32 ui_key_release(OS_Modifiers mods, OS_Key key) { B32 result = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Release && evt->key == key && evt->modifiers == mods) { result = 1; ui_eat_event(evt); break; } } return result; } internal B32 ui_text(U32 character) { B32 result = 0; Temp scratch = scratch_begin(0, 0); String8 character_text = str8_from_32(scratch.arena, str32(&character, 1)); for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Text && str8_match(character_text, evt->string, 0)) { result = 1; ui_eat_event(evt); break; } } scratch_end(scratch); return result; } internal B32 ui_slot_press(UI_EventActionSlot slot) { B32 result = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && evt->slot == slot) { result = 1; ui_eat_event(evt); break; } } return result; } //- rjf: autocomplete info internal void ui_set_autocomplete_string(String8 string) { ui_state->autocomplete_string = push_str8_copy(ui_build_arena(), string); } internal String8 ui_autocomplete_string(void) { return ui_state->autocomplete_string; } internal String8 ui_autocomplete(void) { String8 result = ui_state->autocomplete_string; MemoryZeroStruct(&ui_state->autocomplete_string); return result; } //- rjf: drag data internal Vec2F32 ui_drag_start_mouse(void) { return ui_state->drag_start_mouse; } internal Vec2F32 ui_drag_delta(void) { return sub_2f32(ui_mouse(), ui_state->drag_start_mouse); } internal void ui_store_drag_data(String8 string) { arena_clear(ui_state->drag_state_arena); ui_state->drag_state_data = push_str8_copy(ui_state->drag_state_arena, string); } internal String8 ui_get_drag_data(U64 min_required_size) { if(ui_state->drag_state_data.size < min_required_size) { Temp scratch = scratch_begin(0, 0); String8 str = {push_array(scratch.arena, U8, min_required_size), min_required_size}; ui_store_drag_data(str); scratch_end(scratch); } return ui_state->drag_state_data; } //- rjf: hovered string info internal B32 ui_string_hover_active(void) { return (ui_state->build_index > 0 && ui_state->string_hover_build_index >= ui_state->build_index-1 && os_now_microseconds() >= ui_state->string_hover_begin_us + 500000); } internal U64 ui_string_hover_begin_time_us(void) { return ui_state->string_hover_begin_us; } internal DR_FStrList ui_string_hover_fstrs(Arena *arena) { DR_FStrList result = dr_fstrs_copy(arena, &ui_state->string_hover_fstrs); return result; } //- rjf: interaction keys internal UI_Key ui_hot_key(void) { return ui_state->hot_box_key; } internal UI_Key ui_active_key(UI_MouseButtonKind button_kind) { return ui_state->active_box_key[button_kind]; } internal UI_Key ui_drop_hot_key(void) { return ui_state->drop_hot_box_key; } //- rjf: controls over interaction internal void ui_kill_action(void) { for EachEnumVal(UI_MouseButtonKind, k) { ui_state->active_box_key[k] = ui_key_zero(); } } //- rjf: box cache lookup internal UI_Box * ui_box_from_key(UI_Key key) { ProfBeginFunction(); UI_Box *result = &ui_nil_box; if(!ui_key_match(key, ui_key_zero())) { U64 slot = key.u64[0] % ui_state->box_table_size; for(UI_Box *b = ui_state->box_table[slot].hash_first; !ui_box_is_nil(b); b = b->hash_next) { if(ui_key_match(b->key, key)) { result = b; break; } } } ProfEnd(); return result; } //////////////////////////////// //~ rjf: Top-Level Building API internal void ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, UI_Theme *theme, UI_AnimationInfo *animation_info, F32 real_dt, F32 animation_dt) { //- rjf: reset per-build ui state { UI_InitStacks(ui_state); ui_state->root = &ui_nil_box; ui_state->ctx_menu_touched_this_frame = 0; ui_state->is_animating = 0; ui_state->clipboard_copy_key = ui_key_zero(); ui_state->last_build_box_count = ui_state->build_box_count; ui_state->build_box_count = 0; ui_state->tooltip_open = 0; ui_state->ctx_menu_changed = 0; ui_state->default_animation_rate = 1 - pow_f32(2, (-60.f * ui_state->animation_dt)); ui_state->tooltip_can_overflow_window = 0; ui_state->tooltip_anchor_key = ui_key_zero(); ui_state->tags_key_stack_top = ui_state->tags_key_stack_free = 0; ui_state->tags_cache_slots_count = 512; ui_state->tags_cache_slots = push_array(ui_build_arena(), UI_TagsCacheSlot, ui_state->tags_cache_slots_count); ui_state->autocomplete_string = str8_zero(); } //- rjf: prune unused animation nodes ProfScope("ui prune unused animation nodes") { for(UI_AnimNode *n = ui_state->lru_anim_node, *next = &ui_nil_anim_node; n != &ui_nil_anim_node && n != 0; n = next) { next = n->lru_next; if(n->last_touched_build_index+2 < ui_state->build_index) { U64 slot_idx = n->key.u64[0]%ui_state->anim_slots_count; UI_AnimSlot *slot = &ui_state->anim_slots[slot_idx]; DLLRemove_NPZ(&ui_nil_anim_node, slot->first, slot->last, n, slot_next, slot_prev);; DLLRemove_NPZ(&ui_nil_anim_node, ui_state->lru_anim_node, ui_state->mru_anim_node, n, lru_next, lru_prev); SLLStackPush_N(ui_state->free_anim_node, n, slot_next); } else { break; } } } //- rjf: prune unused theme pattern cache nodes ProfScope("ui prune unused theme pattern cache") { for(UI_ThemePatternCacheNode *n = ui_state->lru_theme_pattern_cache_node, *next = 0; n != 0; n = next) { next = n->lru_next; if(n->last_build_index_accessed+2 < ui_state->build_index) { U64 slot_idx = n->key.u64[0]%ui_state->theme_pattern_cache_slots_count; UI_ThemePatternCacheSlot *slot = &ui_state->theme_pattern_cache_slots[slot_idx]; DLLRemove_NP(slot->first, slot->last, n, slot_next, slot_prev); DLLRemove_NP(ui_state->lru_theme_pattern_cache_node, ui_state->mru_theme_pattern_cache_node, n, lru_next, lru_prev); SLLStackPush_N(ui_state->theme_pattern_cache_node_free, n, slot_next); } else { break; } } } //- rjf: detect mouse-moves for(UI_EventNode *n = events->first; n != 0; n = n->next) { if(n->v.kind == UI_EventKind_MouseMove) { ui_state->last_time_mousemoved_us = os_now_microseconds(); } } //- rjf: detect external press & holds for EachEnumVal(UI_MouseButtonKind, k) { if(ui_key_match(ui_state->active_box_key[k], ui_key_zero()) && os_key_is_down(OS_Key_LeftMouseButton+k)) { ui_state->active_box_key[k] = ui_state->external_key; } else if(ui_key_match(ui_state->active_box_key[k], ui_state->external_key) && !os_key_is_down(OS_Key_LeftMouseButton+k)) { ui_state->active_box_key[k] = ui_key_zero(); } } //- rjf: fill build phase parameters { ui_state->theme = theme; ui_state->events = events; ui_state->window = window; ui_state->mouse = (os_window_is_focused(window) || ui_state->last_time_mousemoved_us+500000 >= os_now_microseconds()) ? os_mouse_from_window(window) : v2f32(-100, -100); ui_state->animation_dt = animation_dt; MemoryZeroStruct(&ui_state->icon_info); ui_state->icon_info.icon_font = icon_info->icon_font; for(UI_IconKind icon_kind = UI_IconKind_Null; icon_kind < UI_IconKind_COUNT; icon_kind = (UI_IconKind)(icon_kind + 1)) { ui_state->icon_info.icon_kind_text_map[icon_kind] = push_str8_copy(ui_build_arena(), icon_info->icon_kind_text_map[icon_kind]); } MemoryCopyStruct(&ui_state->animation_info, animation_info); } //- rjf: do default navigation { Temp scratch = scratch_begin(0, 0); if(!ui_key_match(ui_state->default_nav_root_key, ui_key_zero())) { UI_Box *nav_root = ui_box_from_key(ui_state->default_nav_root_key); if(!ui_box_is_nil(nav_root)) { //- rjf: no child has the active focus -> do navigation at this layer if(ui_key_match(ui_key_zero(), nav_root->default_nav_focus_active_key)) { for(;;) { B32 moved = 0; UI_Box *focus_box = ui_box_from_key(nav_root->default_nav_focus_next_hot_key); UI_BoxList next_focus_box_candidates = {0}; // rjf: gather & consume events & nav actions B32 nav_next = 0; B32 nav_prev = 0; Axis2 axis_lock = Axis2_Invalid; if(ui_key_press(0, OS_Key_Tab)) { nav_next = 1; } if(ui_key_press(OS_Modifier_Shift, OS_Key_Tab)) { nav_prev = 1; } for(UI_EventNode *node = events->first, *next = 0; node != 0; node = next) { next = node->next; B32 taken = 0; if(node->v.delta_2s32.x == 0 && node->v.delta_2s32.y == 0) { continue; } if(((node->v.delta_2s32.x > 0 && nav_root->flags & UI_BoxFlag_DefaultFocusNavX) || node->v.delta_2s32.x == 0) && ((node->v.delta_2s32.y > 0 && nav_root->flags & UI_BoxFlag_DefaultFocusNavY) || node->v.delta_2s32.y == 0)) { taken = 1; nav_next = 1; } if(((node->v.delta_2s32.x < 0 && nav_root->flags & UI_BoxFlag_DefaultFocusNavX) || node->v.delta_2s32.x == 0) && ((node->v.delta_2s32.y < 0 && nav_root->flags & UI_BoxFlag_DefaultFocusNavY) || node->v.delta_2s32.y == 0)) { taken = 1; nav_prev = 1; } if(node->v.flags & UI_EventFlag_ExplicitDirectional) { axis_lock = node->v.delta_2s32.x != 0 ? Axis2_X : Axis2_Y; } if(taken) { ui_eat_event_node(events, node); } } // rjf: [+] directional movement if(nav_next) { UI_Box *search_start = ui_box_is_nil(focus_box) ? nav_root : focus_box; U64 moved_in_axis[Axis2_COUNT] = {0}; moved = 1; for(UI_Box *box = search_start;;) { if(box != search_start && !(box->flags & UI_BoxFlag_FocusNavSkip) && (box->flags & UI_BoxFlag_Clickable || ui_box_is_nil(box)) && (axis_lock == Axis2_Invalid || moved_in_axis[axis_lock] > 0)) { ui_box_list_push(scratch.arena, &next_focus_box_candidates, box); if(axis_lock == Axis2_Invalid || moved_in_axis[axis_lock] > 1) { break; } } UI_Box *last_box = box; if(!ui_box_is_nil(box->first)) { moved_in_axis[box->child_layout_axis] += 1; box = box->first; } else for(UI_Box *p = box; !ui_box_is_nil(p) && p != nav_root; p = p->parent) { if(!ui_box_is_nil(p->next)) { moved_in_axis[p->parent->child_layout_axis] += 1; box = p->next; break; } } if(last_box == box) { ui_box_list_push(scratch.arena, &next_focus_box_candidates, &ui_nil_box); break; } } } // rjf: [-] directional movement if(nav_prev) { UI_Box *search_start = ui_box_is_nil(focus_box) ? nav_root : focus_box; U64 moved_in_axis[Axis2_COUNT] = {0}; moved = 1; for(UI_Box *box = search_start;;) { if(box != search_start && !(box->flags & UI_BoxFlag_FocusNavSkip) && (box->flags & UI_BoxFlag_Clickable || ui_box_is_nil(box)) && (axis_lock == Axis2_Invalid || moved_in_axis[axis_lock] > 0)) { ui_box_list_push(scratch.arena, &next_focus_box_candidates, box); if(axis_lock == Axis2_Invalid || moved_in_axis[axis_lock] > 1) { break; } } UI_Box *last_box = box; UI_Box *root_descendant = &ui_nil_box; if(box == nav_root && box == search_start) { for(UI_Box *d = box->last; !ui_box_is_nil(d); d = d->last) { moved_in_axis[d->parent->child_layout_axis] += 1; root_descendant = d; } } UI_Box *prev_descendant = &ui_nil_box; for(UI_Box *d = box->prev; !ui_box_is_nil(d); d = d->last) { moved_in_axis[d->parent->child_layout_axis] += 1; prev_descendant = d; } if(!ui_box_is_nil(root_descendant)) { box = root_descendant; } else if(!ui_box_is_nil(prev_descendant)) { box = prev_descendant; } else if(box->parent != nav_root) { moved_in_axis[box->parent->child_layout_axis] += 1; box = box->parent; } if(box == last_box) { ui_box_list_push(scratch.arena, &next_focus_box_candidates, &ui_nil_box); break; } } } // rjf: scan candidates and grab next focus box UI_Box *next_focus_box = focus_box; F32 best_distance_from_start = 1000000; for(UI_BoxNode *n = next_focus_box_candidates.first; n != 0; n = n->next) { UI_Box *box = n->box; F32 distance_from_start = 0; if(axis_lock != Axis2_Invalid) { distance_from_start = abs_f32(center_2f32(box->rect).v[axis2_flip(axis_lock)] - center_2f32(focus_box->rect).v[axis2_flip(axis_lock)]); } if(distance_from_start < best_distance_from_start && box != focus_box) { next_focus_box = box; best_distance_from_start = distance_from_start; } } // rjf: commit next focus box nav_root->default_nav_focus_next_hot_key = next_focus_box->key; // rjf: no movement -> break if(moved == 0) { break; } } } //- rjf: some child has the active focus -> accept escape keys to pop from the active key stack if(!ui_key_match(ui_key_zero(), nav_root->default_nav_focus_active_key)) { for(;ui_slot_press(UI_EventActionSlot_Cancel);) { UI_Box *prev_focus_root = nav_root; for(UI_Box *focus_root = ui_box_from_key(nav_root->default_nav_focus_active_key); !ui_box_is_nil(focus_root);) { UI_Box *next_focus_root = ui_box_from_key(focus_root->default_nav_focus_active_key); if(ui_box_is_nil(next_focus_root)) { prev_focus_root->default_nav_focus_next_active_key = ui_key_zero(); break; } else { prev_focus_root = focus_root; focus_root = next_focus_root; } } } } } } ui_state->default_nav_root_key = ui_key_zero(); scratch_end(scratch); } //- rjf: next-default-nav-focus keys -> current-default-nav-focus-keys for(U64 slot_idx = 0; slot_idx < ui_state->box_table_size; slot_idx += 1) { for(UI_Box *box = ui_state->box_table[slot_idx].hash_first; !ui_box_is_nil(box); box = box->hash_next) { box->default_nav_focus_hot_key = box->default_nav_focus_next_hot_key; box->default_nav_focus_active_key = box->default_nav_focus_next_active_key; } } //- rjf: build top-level root { Rng2F32 window_rect = os_client_rect_from_window(window); Vec2F32 window_rect_size = dim_2f32(window_rect); ui_set_next_fixed_width(window_rect_size.x); ui_set_next_fixed_height(window_rect_size.y); ui_set_next_child_layout_axis(Axis2_X); UI_Box *root = ui_build_box_from_stringf(0, "###%I64x", window.u64[0]); ui_push_parent(root); ui_state->root = root; } //- rjf: setup parent box for tooltip UI_FixedX(ui_state->mouse.x+15.f) UI_FixedY(ui_state->mouse.y+15.f) UI_PrefWidth(ui_children_sum(1.f)) UI_PrefHeight(ui_children_sum(1.f)) { ui_set_next_child_layout_axis(Axis2_Y); ui_state->tooltip_root = ui_build_box_from_stringf(0, "###tooltip_%I64x", window.u64[0]); } //- rjf: setup parent box for context menu ui_state->ctx_menu_open = ui_state->next_ctx_menu_open; ui_state->ctx_menu_anchor_key = ui_state->next_ctx_menu_anchor_key; { UI_Box *anchor_box = ui_box_from_key(ui_state->ctx_menu_anchor_key); if(!ui_box_is_nil(anchor_box)) { ui_state->ctx_menu_anchor_box_last_pos = anchor_box->rect.p0; } Vec2F32 anchor = add_2f32(ui_state->ctx_menu_anchor_box_last_pos, ui_state->ctx_menu_anchor_off); UI_FixedX(anchor.x) UI_FixedY(anchor.y) UI_PrefWidth(ui_children_sum(1.f)) UI_PrefHeight(ui_children_sum(1.f)) UI_Focus(UI_FocusKind_On) UI_Squish(0.1f-ui_state->ctx_menu_open_t*0.1f) UI_Transparency(1-ui_state->ctx_menu_open_t) { ui_set_next_child_layout_axis(Axis2_Y); ui_state->ctx_menu_root = ui_build_box_from_stringf(UI_BoxFlag_Clickable| UI_BoxFlag_SquishAnchored| UI_BoxFlag_DrawDropShadow| (ui_state->ctx_menu_open*UI_BoxFlag_DefaultFocusNavY), "###ctx_menu_%I64x", window.u64[0]); } } //- rjf: reset hot if we don't have an active widget { B32 has_active = 0; for EachEnumVal(UI_MouseButtonKind, k) { if(!ui_key_match(ui_state->active_box_key[k], ui_key_zero())) { has_active = 1; } } if(!has_active) { ui_state->hot_box_key = ui_key_zero(); } } //- rjf: reset drop-hot key { ui_state->drop_hot_box_key = ui_key_zero(); } //- rjf: reset active if our active box is disabled for EachEnumVal(UI_MouseButtonKind, k) { if(!ui_key_match(ui_state->active_box_key[k], ui_key_zero())) { UI_Box *box = ui_box_from_key(ui_state->active_box_key[k]); if(!ui_box_is_nil(box) && box->flags & UI_BoxFlag_Disabled) { ui_state->active_box_key[k] = ui_key_zero(); } } } //- rjf: reset active keys if they have been pruned for EachEnumVal(UI_MouseButtonKind, k) { UI_Box *box = ui_box_from_key(ui_state->active_box_key[k]); if(ui_box_is_nil(box)) { ui_state->active_box_key[k] = ui_key_zero(); } } //- rjf: escape -> close context menu if(ui_any_ctx_menu_is_open() && ui_slot_press(UI_EventActionSlot_Cancel)) { ui_ctx_menu_close(); } } internal void ui_end_build(void) { ProfBeginFunction(); //- rjf: prune untouched or transient boxes in the cache ProfScope("ui prune unused boxes") { for(U64 slot_idx = 0; slot_idx < ui_state->box_table_size; slot_idx += 1) { for(UI_Box *box = ui_state->box_table[slot_idx].hash_first, *next = 0; !ui_box_is_nil(box); box = next) { next = box->hash_next; if(box->last_touched_build_index < ui_state->build_index || ui_key_match(box->key, ui_key_zero())) { DLLRemove_NPZ(&ui_nil_box, ui_state->box_table[slot_idx].hash_first, ui_state->box_table[slot_idx].hash_last, box, hash_next, hash_prev); SLLStackPush(ui_state->first_free_box, box); } } } } //- rjf: layout box tree ProfScope("ui box tree layout") { for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1)) { ui_layout_root(ui_state->root, axis); } } //- rjf: close ctx menu if untouched if(!ui_state->ctx_menu_touched_this_frame) { ui_ctx_menu_close(); } //- rjf: stick ctx menu to anchor if(ui_state->ctx_menu_touched_this_frame && !ui_state->ctx_menu_changed) { UI_Box *anchor_box = ui_box_from_key(ui_state->ctx_menu_anchor_key); if(!ui_box_is_nil(anchor_box)) { Rng2F32 root_rect = ui_state->ctx_menu_root->rect; Vec2F32 pos = { anchor_box->rect.x0 + ui_state->ctx_menu_anchor_off.x, anchor_box->rect.y0 + ui_state->ctx_menu_anchor_off.y, }; Vec2F32 shift = sub_2f32(pos, root_rect.p0); Rng2F32 new_root_rect = shift_2f32(root_rect, shift); ui_state->ctx_menu_root->fixed_position = new_root_rect.p0; ui_state->ctx_menu_root->fixed_size = dim_2f32(new_root_rect); ui_state->ctx_menu_root->rect = new_root_rect; } } //- rjf: anchor tooltips if(!ui_key_match(ui_state->tooltip_anchor_key, ui_key_zero())) { UI_Box *anchor_box = ui_box_from_key(ui_state->tooltip_anchor_key); if(!ui_box_is_nil(anchor_box)) { Vec2F32 dim = dim_2f32(ui_state->tooltip_root->rect); ui_state->tooltip_root->fixed_position.x = ui_state->tooltip_root->rect.x0 = anchor_box->rect.x0; ui_state->tooltip_root->fixed_position.y = ui_state->tooltip_root->rect.y0 = anchor_box->rect.y1 + anchor_box->font_size*0.5f; ui_state->tooltip_root->rect.x1 = ui_state->tooltip_root->rect.x0 + dim.x; ui_state->tooltip_root->rect.y1 = ui_state->tooltip_root->rect.y0 + dim.y; } else { ui_state->tooltip_root->rect.x0 = 10000; ui_state->tooltip_root->rect.y0 = 10000; } } //- rjf: ensure special floating roots are within screen bounds UI_Box *floating_roots[] = {ui_state->tooltip_root, ui_state->ctx_menu_root}; B32 force_contain[] = { !ui_state->tooltip_can_overflow_window, 1, }; for(U64 idx = 0; idx < ArrayCount(floating_roots); idx += 1) { UI_Box *root = floating_roots[idx]; if(!ui_box_is_nil(root)) { Rng2F32 window_rect = os_client_rect_from_window(ui_window()); Vec2F32 window_dim = dim_2f32(window_rect); Rng2F32 root_rect = root->rect; Vec2F32 shift_down = { -ClampBot(0, root_rect.x1 - window_rect.x1) * (force_contain[idx]), -ClampBot(0, root_rect.y1 - window_rect.y1) * (force_contain[idx]), }; Rng2F32 new_root_rect = shift_2f32(root_rect, shift_down); Vec2F32 shift_up = { ClampBot(0, window_rect.x0 - new_root_rect.x0) * (force_contain[idx]), ClampBot(0, window_rect.y0 - new_root_rect.y0) * (force_contain[idx]), }; new_root_rect = shift_2f32(new_root_rect, shift_up); root->fixed_position = new_root_rect.p0; root->fixed_size = dim_2f32(new_root_rect); root->rect = new_root_rect; for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1)) { ui_calc_sizes_standalone__in_place(root, axis); ui_calc_sizes_upwards_dependent__in_place(root, axis); ui_calc_sizes_downwards_dependent__in_place(root, axis); ui_layout_enforce_constraints__in_place(root, axis); ui_layout_position__in_place(root, axis); } } } //- rjf: enforce child-rounding { for(U64 slot_idx = 0; slot_idx < ui_state->box_table_size; slot_idx += 1) { for(UI_Box *box = ui_state->box_table[slot_idx].hash_first; !ui_box_is_nil(box); box = box->hash_next) { if(box->flags & UI_BoxFlag_RoundChildrenByParent) { for(UI_Box *b = box; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, box).next) { if(floor_f32(b->rect.x0) <= floor_f32(box->rect.x0) && floor_f32(b->rect.y0) <= floor_f32(box->rect.y0)) { b->corner_radii[Corner_00] = box->corner_radii[Corner_00]; } if(floor_f32(b->rect.x1) >= floor_f32(box->rect.x1) && floor_f32(b->rect.y0) <= floor_f32(box->rect.y0)) { b->corner_radii[Corner_10] = box->corner_radii[Corner_10]; } if(floor_f32(b->rect.x0) <= floor_f32(box->rect.x0) && floor_f32(b->rect.y1) >= floor_f32(box->rect.y1)) { b->corner_radii[Corner_01] = box->corner_radii[Corner_01]; } if(floor_f32(b->rect.x1) >= floor_f32(box->rect.x1) && floor_f32(b->rect.y1) >= floor_f32(box->rect.y1)) { b->corner_radii[Corner_11] = box->corner_radii[Corner_11]; } } box->first->corner_radii[Corner_00] = box->corner_radii[Corner_00]; box->first->corner_radii[Corner_10] = box->corner_radii[Corner_10]; box->last->corner_radii[Corner_01] = box->corner_radii[Corner_01]; box->last->corner_radii[Corner_11] = box->corner_radii[Corner_11]; } } } } //- rjf: animate ProfScope("animate") { for(U64 slot_idx = 0; slot_idx < ui_state->anim_slots_count; slot_idx += 1) { for(UI_AnimNode *n = ui_state->anim_slots[slot_idx].first; n != &ui_nil_anim_node && n != 0; n = n->slot_next) { n->current += (n->params.target - n->current) * n->params.rate; ui_state->is_animating = (ui_state->is_animating || abs_f32(n->params.target - n->current) > n->params.epsilon); } } F32 fast_rate = ui_state->default_animation_rate; F32 slow_rate = 1 - pow_f32(2, (-30.f * ui_state->animation_dt)); for(U64 slot_idx = 0; slot_idx < ui_state->theme_pattern_cache_slots_count; slot_idx += 1) { for(UI_ThemePatternCacheNode *n = ui_state->theme_pattern_cache_slots[slot_idx].first; n != 0; n = n->slot_next) { for EachIndex(idx, 4) { n->current_rgba.v[idx] += (n->target_rgba.v[idx] - n->current_rgba.v[idx]) * slow_rate; ui_state->is_animating = (ui_state->is_animating || abs_f32(n->target_rgba.v[idx] - n->current_rgba.v[idx]) > 0.001f); } } } ui_state->ctx_menu_open_t += ((F32)!!ui_state->ctx_menu_open - ui_state->ctx_menu_open_t) * ui_state->animation_info.menu_animation_rate; ui_state->is_animating = (ui_state->is_animating || abs_f32((F32)!!ui_state->ctx_menu_open - ui_state->ctx_menu_open_t) > 0.01f); if(ui_state->ctx_menu_open_t >= 0.99f && ui_state->ctx_menu_open) { ui_state->ctx_menu_open_t = 1.f; } ui_state->tooltip_open_t += ((F32)!!ui_state->tooltip_open - ui_state->tooltip_open_t) * ui_state->animation_info.tooltip_animation_rate; ui_state->is_animating = (ui_state->is_animating || abs_f32((F32)!!ui_state->tooltip_open - ui_state->tooltip_open_t) > 0.01f); if(ui_state->tooltip_open_t >= 0.99f && ui_state->tooltip_open) { ui_state->tooltip_open_t = 1.f; } for(U64 slot_idx = 0; slot_idx < ui_state->box_table_size; slot_idx += 1) { for(UI_Box *box = ui_state->box_table[slot_idx].hash_first; !ui_box_is_nil(box); box = box->hash_next) { // rjf: grab states informing animation B32 is_hot = (ui_key_match(box->key, ui_state->hot_box_key) || ui_key_match(box->key, ui_state->drop_hot_box_key)); B32 is_active = ui_key_match(box->key, ui_state->active_box_key[UI_MouseButtonKind_Left]); B32 is_disabled = !!(box->flags & UI_BoxFlag_Disabled) && (box->first_disabled_build_index+2 < ui_state->build_index || box->first_touched_build_index == box->first_disabled_build_index); B32 is_focus_hot = !!(box->flags & UI_BoxFlag_FocusHot) && !(box->flags & UI_BoxFlag_FocusHotDisabled); B32 is_focus_active = !!(box->flags & UI_BoxFlag_FocusActive) && !(box->flags & UI_BoxFlag_FocusActiveDisabled); B32 is_focus_active_disabled = !!(box->flags & UI_BoxFlag_FocusActiveDisabled); // rjf: determine rates F32 hot_rate = ui_state->animation_info.hot_animation_rate; F32 active_rate = ui_state->animation_info.active_animation_rate; F32 disabled_rate = slow_rate; F32 focus_rate = ui_state->animation_info.focus_animation_rate; // rjf: determine animating status B32 box_is_animating = 0; box_is_animating = (box_is_animating || abs_f32((F32)is_hot - box->hot_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32((F32)is_active - box->active_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32((F32)is_disabled - box->disabled_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32((F32)is_focus_hot - box->focus_hot_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32((F32)is_focus_active - box->focus_active_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32((F32)is_focus_active_disabled - box->focus_active_disabled_t) > 0.01f); box_is_animating = (box_is_animating || abs_f32(box->view_off_target.x - box->view_off.x) > 0.5f); box_is_animating = (box_is_animating || abs_f32(box->view_off_target.y - box->view_off.y) > 0.5f); if(box->flags & UI_BoxFlag_AnimatePosX) { box_is_animating = (box_is_animating || abs_f32(box->fixed_position_animated.x - box->fixed_position.x) > 0.5f); } if(box->flags & UI_BoxFlag_AnimatePosY) { box_is_animating = (box_is_animating || abs_f32(box->fixed_position_animated.y - box->fixed_position.y) > 0.5f); } ui_state->is_animating = (ui_state->is_animating || box_is_animating); #if 0 // NOTE(rjf): enable to debug animation-causing-frames (or not) if(box_is_animating) { box->overlay_color = v4f32(1, 0, 0, 0.1f); box->flags |= UI_BoxFlag_DrawOverlay; } #endif // rjf: animate interaction transition states box->hot_t += hot_rate * ((F32)is_hot - box->hot_t); box->active_t = is_active ? 1.f : box->active_t + (active_rate * ((F32)is_active - box->active_t)); box->disabled_t += disabled_rate * ((F32)is_disabled - box->disabled_t); box->focus_hot_t += focus_rate * ((F32)is_focus_hot - box->focus_hot_t); box->focus_active_t += focus_rate * ((F32)is_focus_active - box->focus_active_t); box->focus_active_disabled_t += focus_rate * ((F32)is_focus_active_disabled - box->focus_active_disabled_t); // rjf: animate positions { box->fixed_position_animated.x += fast_rate * (box->fixed_position.x - box->fixed_position_animated.x); box->fixed_position_animated.y += fast_rate * (box->fixed_position.y - box->fixed_position_animated.y); if(abs_f32(box->fixed_position.x - box->fixed_position_animated.x) < 1) { box->fixed_position_animated.x = box->fixed_position.x; } if(abs_f32(box->fixed_position.y - box->fixed_position_animated.y) < 1) { box->fixed_position_animated.y = box->fixed_position.y; } } // rjf: clamp view if(box->flags & UI_BoxFlag_ViewClamp) { Vec2F32 max_view_off_target = { ClampBot(0, box->view_bounds.x - box->fixed_size.x), ClampBot(0, box->view_bounds.y - box->fixed_size.y), }; if(box->flags & UI_BoxFlag_ViewClampX) { box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x); } if(box->flags & UI_BoxFlag_ViewClampY) { box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y); } } // rjf: animate view offset { box->view_off.x += ui_state->animation_info.scroll_animation_rate * (box->view_off_target.x - box->view_off.x); box->view_off.y += ui_state->animation_info.scroll_animation_rate * (box->view_off_target.y - box->view_off.y); if(abs_f32(box->view_off.x - box->view_off_target.x) < 2) { box->view_off.x = box->view_off_target.x; } if(abs_f32(box->view_off.y - box->view_off_target.y) < 2) { box->view_off.y = box->view_off_target.y; } } } } } //- rjf: use group keys for box animation data if possible for(UI_Box *b = ui_state->root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, ui_state->root).next) { if(ui_key_match(b->key, ui_key_zero()) && !ui_key_match(b->group_key, ui_key_zero())) { UI_Box *group_box = ui_box_from_key(b->group_key); b->hot_t = group_box->hot_t; } } //- rjf: fall-through interact with context menu if(ui_state->ctx_menu_open) { ui_signal_from_box(ui_state->ctx_menu_root); } //- rjf: close ctx menu if unconsumed clicks { for(UI_Event *evt = 0; ui_next_event(&evt);) { if(evt->kind == UI_EventKind_Press && (evt->key == OS_Key_LeftMouseButton || evt->key == OS_Key_RightMouseButton)) { ui_ctx_menu_close(); } } } //- rjf: hover cursor if(!ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_state->external_key)) { UI_Box *hot = ui_box_from_key(ui_state->hot_box_key); UI_Box *active = ui_box_from_key(ui_state->active_box_key[UI_MouseButtonKind_Left]); UI_Box *box = ui_box_is_nil(active) ? hot : active; OS_Cursor cursor = box->hover_cursor; if(box->flags & UI_BoxFlag_Disabled && box->flags & UI_BoxFlag_Clickable) { cursor = OS_Cursor_Disabled; } if(os_window_is_focused(ui_state->window) || !ui_box_is_nil(active)) { os_set_cursor(cursor); } } //- rjf: clipboard commits { UI_Box *box = ui_box_from_key(ui_state->clipboard_copy_key); if(!ui_box_is_nil(box)) { Temp scratch = scratch_begin(0, 0); String8List strs = {0}; UI_BoxRec rec = {0}; for(UI_Box *b = box; !ui_box_is_nil(b); rec = ui_box_rec_df_pre(b, box), b = rec.next) { if(b->flags & UI_BoxFlag_DrawText && b->flags & UI_BoxFlag_HasDisplayString && !fnt_tag_match(b->font, ui_icon_font())) { String8 display_string = ui_box_display_string(b); str8_list_push(scratch.arena, &strs, display_string); } } if(strs.node_count != 0) { StringJoin join = {0}; join.sep = str8_lit(" "); String8 string = str8_list_join(scratch.arena, &strs, &join); os_set_clipboard_text(string); } scratch_end(scratch); } } //- rjf: hovering possibly-truncated drawn text -> store text { B32 inactive = 1; for EachEnumVal(UI_MouseButtonKind, k) { if(!ui_key_match(ui_key_zero(), ui_state->active_box_key[k])) { inactive = 0; break; } } if(inactive) { B32 found = 0; for(UI_Box *box = ui_state->root, *next = 0; !ui_box_is_nil(box); box = next) { UI_BoxRec rec = ui_box_rec_df_pre(box, ui_state->root); next = rec.next; S32 pop_idx = 0; for(UI_Box *b = box; !ui_box_is_nil(b) && pop_idx <= rec.pop_count; b = b->parent, pop_idx += 1) { if(b->flags & UI_BoxFlag_DrawText && !(b->flags & UI_BoxFlag_DisableTextTrunc)) { Rng2F32 rect = b->rect; for(UI_Box *p = b->parent; !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_Clip) { rect = intersect_2f32(rect, p->rect); } } String8 box_display_string = ui_box_display_string(b); Vec2F32 text_pos = ui_box_text_position(b); Vec2F32 drawn_text_dim = {0}; { Temp scratch = scratch_begin(0, 0); DR_FRunList fruns = dr_fruns_from_fstrs(scratch.arena, b->tab_size, &b->display_fstrs); drawn_text_dim = fruns.dim; scratch_end(scratch); } B32 text_is_truncated = (drawn_text_dim.x + text_pos.x > rect.x1); B32 mouse_is_hovering = contains_2f32(r2f32p(text_pos.x, rect.y0, Min(text_pos.x+drawn_text_dim.x, rect.x1), rect.y1), ui_state->mouse); if(text_is_truncated && mouse_is_hovering && !(b->flags & UI_BoxFlag_DisableTruncatedHover)) { if(!str8_match(box_display_string, ui_state->string_hover_string, 0) || box->font_size != ui_state->string_hover_size) { arena_clear(ui_state->string_hover_arena); ui_state->string_hover_string = push_str8_copy(ui_state->string_hover_arena, box_display_string); ui_state->string_hover_size = box->font_size; ui_state->string_hover_fstrs = dr_fstrs_copy(ui_state->string_hover_arena, &b->display_fstrs); ui_state->string_hover_begin_us = os_now_microseconds(); } ui_state->string_hover_build_index = ui_state->build_index; found = 1; goto break_all_hover_string; } } if(b != box && ui_key_match(b->key, ui_hot_key())) { goto break_all_hover_string; } if(b != box && contains_2f32(b->rect, ui_state->mouse) && b->flags & UI_BoxFlag_DrawText) { goto break_all_hover_string; } } } break_all_hover_string:; if(!found) { arena_clear(ui_state->string_hover_arena); ui_state->string_hover_build_index = 0; MemoryZeroStruct(&ui_state->string_hover_string); } if(found && !ui_string_hover_active()) { ui_state->is_animating = 1; } } } ui_state->build_index += 1; arena_clear(ui_build_arena()); ProfEnd(); } internal void ui_calc_sizes_standalone__in_place(UI_Box *root, Axis2 axis) { ProfBeginFunction(); for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next) { switch(b->pref_size[axis].kind) { default:{}break; case UI_SizeKind_Pixels: { b->fixed_size.v[axis] = b->pref_size[axis].value; }break; case UI_SizeKind_TextContent: { F32 padding = b->pref_size[axis].value; F32 text_size = b->display_fruns.dim.x; b->fixed_size.v[axis] = padding + text_size + b->text_padding*2; }break; } } ProfEnd(); } internal void ui_calc_sizes_upwards_dependent__in_place(UI_Box *root, Axis2 axis) { ProfBeginFunction(); for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next) { switch(b->pref_size[axis].kind) { default:{}break; case UI_SizeKind_ParentPct: { // rjf: find parent that has a fixed size UI_Box *fixed_parent = &ui_nil_box; for(UI_Box *p = b->parent; !ui_box_is_nil(p); p = p->parent) { if(p->flags & (UI_BoxFlag_FixedWidth<pref_size[axis].kind == UI_SizeKind_Pixels || p->pref_size[axis].kind == UI_SizeKind_TextContent || p->pref_size[axis].kind == UI_SizeKind_ParentPct) { fixed_parent = p; break; } } // rjf: figure out box's size on this axis F32 size = fixed_parent->fixed_size.v[axis] * b->pref_size[axis].value; // rjf: mutate box to have this size b->fixed_size.v[axis] = size; }break; } } ProfEnd(); } internal void ui_calc_sizes_downwards_dependent__in_place(UI_Box *root, Axis2 axis) { ProfBeginFunction(); UI_BoxRec rec = {0}; for(UI_Box *box = root; !ui_box_is_nil(box); box = rec.next) { rec = ui_box_rec_df_pre(box, root); S32 pop_idx = 0; for(UI_Box *b = box; !ui_box_is_nil(b) && pop_idx <= rec.pop_count; b = b->parent, pop_idx += 1) { if(b->pref_size[axis].kind == UI_SizeKind_ChildrenSum) { F32 sum = 0; for(UI_Box *child = b->first; !ui_box_is_nil(child); child = child->next) { if(!(child->flags & (UI_BoxFlag_FloatingX<child_layout_axis) { sum += child->fixed_size.v[axis]; } else { sum = Max(sum, child->fixed_size.v[axis]); } } } b->fixed_size.v[axis] = sum; } } } ProfEnd(); } internal void ui_layout_enforce_constraints__in_place(UI_Box *root, Axis2 axis) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next) { //- rjf: fixup children sizes (if we're solving along the *non-layout* axis) if(axis != box->child_layout_axis && !(box->flags & (UI_BoxFlag_AllowOverflowX << axis))) { F32 allowed_size = box->fixed_size.v[axis]; for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next) { if(!(child->flags & (UI_BoxFlag_FloatingX<fixed_size.v[axis]; F32 violation = child_size - allowed_size; F32 max_fixup = child_size; F32 fixup = Clamp(0, violation, max_fixup); if(fixup > 0) { child->fixed_size.v[axis] -= fixup; } } } } //- rjf: fixup children sizes (in the direction of the layout axis) if(axis == box->child_layout_axis && !(box->flags & (UI_BoxFlag_AllowOverflowX << axis))) { // rjf: figure out total allowed size & total size F32 total_allowed_size = box->fixed_size.v[axis]; F32 total_size = 0; F32 total_weighted_size = 0; for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next) { if(!(child->flags & (UI_BoxFlag_FloatingX<fixed_size.v[axis]; total_weighted_size += child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness); } } // rjf: if we have a violation, we need to subtract some amount from all children F32 violation = total_size - total_allowed_size; if(violation > 0 && total_weighted_size > 0) { Temp temp = temp_begin(scratch.arena); // rjf: figure out how much we can take in totality F32 child_fixup_sum = 0; F32 *child_fixups = push_array(temp.arena, F32, box->child_count); { U64 child_idx = 0; for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next, child_idx += 1) { if(!(child->flags & (UI_BoxFlag_FloatingX<fixed_size.v[axis] * (1-child->pref_size[axis].strictness); fixup_size_this_child = ClampBot(0, fixup_size_this_child); child_fixups[child_idx] = fixup_size_this_child; child_fixup_sum += fixup_size_this_child; } } } // rjf: fixup child sizes { U64 child_idx = 0; for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next, child_idx += 1) { if(!(child->flags & (UI_BoxFlag_FloatingX<fixed_size.v[axis] -= child_fixups[child_idx] * fixup_pct; } } } temp_end(temp); } } //- rjf: fixup upwards-relative sizes if(box->flags & (UI_BoxFlag_AllowOverflowX << axis)) { for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next) { if(child->pref_size[axis].kind == UI_SizeKind_ParentPct) { child->fixed_size.v[axis] = box->fixed_size.v[axis] * child->pref_size[axis].value; } } } //- rjf: enforce clamps for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next) { child->fixed_size.v[axis] = Max(child->fixed_size.v[axis], child->min_size.v[axis]); } } scratch_end(scratch); ProfEnd(); } internal void ui_layout_position__in_place(UI_Box *root, Axis2 axis) { ProfBeginFunction(); for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next) { F32 layout_position = 0; //- rjf: lay out children F32 bounds = 0; for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next) { // rjf: grab original position F32 original_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]); // rjf: calculate fixed position & size if(!(child->flags & (UI_BoxFlag_FloatingX<fixed_position.v[axis] = layout_position; if(box->child_layout_axis == axis) { layout_position += child->fixed_size.v[axis]; bounds += child->fixed_size.v[axis]; } else { bounds = Max(bounds, child->fixed_size.v[axis]); } } // rjf: determine final rect for child, given fixed_position & size if(child->flags & (UI_BoxFlag_AnimatePosX<first_touched_build_index == child->last_touched_build_index) { child->fixed_position_animated = child->fixed_position; } child->rect.p0.v[axis] = box->rect.p0.v[axis] + child->fixed_position_animated.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<view_off.v[axis]); } else { child->rect.p0.v[axis] = box->rect.p0.v[axis] + child->fixed_position.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<view_off.v[axis]); } child->rect.p1.v[axis] = child->rect.p0.v[axis] + child->fixed_size.v[axis]; child->rect.p0.x = floor_f32(child->rect.p0.x); child->rect.p0.y = floor_f32(child->rect.p0.y); child->rect.p1.x = floor_f32(child->rect.p1.x); child->rect.p1.y = floor_f32(child->rect.p1.y); // rjf: grab new position F32 new_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]); // rjf: store position delta child->position_delta.v[axis] = new_position - original_position; } //- rjf: store view bounds { box->view_bounds.v[axis] = bounds; } } ProfEnd(); } internal void ui_layout_root(UI_Box *root, Axis2 axis) { ProfBegin("ui layout pass (%s)", axis == Axis2_X ? "x" : "y"); ui_calc_sizes_standalone__in_place(root, axis); ui_calc_sizes_upwards_dependent__in_place(root, axis); ui_calc_sizes_downwards_dependent__in_place(root, axis); ui_layout_enforce_constraints__in_place(root, axis); ui_layout_position__in_place(root, axis); ProfEnd(); } //////////////////////////////// //~ rjf: Box Building API //- rjf: spacers internal UI_Signal ui_spacer(UI_Size size) { UI_Box *parent = ui_top_parent(); ui_set_next_pref_size(parent->child_layout_axis, size); UI_Box *box = ui_build_box_from_key(0, ui_key_zero()); UI_Signal interact = ui_signal_from_box(box); return interact; } //- rjf: tooltips internal void ui_tooltip_begin_base(void) { ui_state->tooltip_open = 1; ui_push_parent(ui_root_from_state(ui_state)); ui_push_parent(ui_state->tooltip_root); ui_push_flags(0); ui_push_text_raster_flags(ui_bottom_text_raster_flags()); ui_push_font_size(ui_bottom_font_size()); ui_push_tag(str8_lit(".")); ui_push_tag(str8_lit("floating")); } internal void ui_tooltip_end_base(void) { ui_pop_tag(); ui_pop_tag(); ui_pop_font_size(); ui_pop_text_raster_flags(); ui_pop_flags(); ui_pop_parent(); ui_pop_parent(); } internal void ui_tooltip_begin(void) { ui_tooltip_begin_base(); ui_set_next_squish(0.1f-ui_state->tooltip_open_t*0.1f); ui_set_next_transparency(1-ui_state->tooltip_open_t); UI_Flags(UI_BoxFlag_Floating|UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBackgroundBlur|UI_BoxFlag_DrawDropShadow|UI_BoxFlag_SquishAnchored) UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_children_sum(1)) UI_CornerRadius(ui_top_font_size()*0.25f) ui_column_begin(); UI_PrefWidth(ui_px(0, 1)) ui_spacer(ui_em(1.f, 1.f)); UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_children_sum(1)) ui_row_begin(); UI_PrefHeight(ui_px(0, 1)) ui_spacer(ui_em(1.f, 1.f)); UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_children_sum(1)) ui_column_begin(); ui_push_pref_width(ui_text_dim(10.f, 1.f)); ui_push_pref_height(ui_em(2.f, 1.f)); ui_push_text_alignment(UI_TextAlign_Center); } internal void ui_tooltip_end(void) { ui_pop_text_alignment(); ui_pop_pref_width(); ui_pop_pref_height(); ui_column_end(); UI_PrefHeight(ui_px(0, 1)) ui_spacer(ui_em(1.f, 1.f)); ui_row_end(); UI_PrefWidth(ui_px(0, 1)) ui_spacer(ui_em(1.f, 1.f)); ui_column_end(); ui_tooltip_end_base(); } //- rjf: context menus internal void ui_ctx_menu_open(UI_Key key, UI_Key anchor_box_key, Vec2F32 anchor_off) { anchor_off.x = (F32)(int)anchor_off.x; anchor_off.y = (F32)(int)anchor_off.y; ui_state->next_ctx_menu_open = 1; ui_state->ctx_menu_changed = 1; ui_state->ctx_menu_open_t = 0; ui_state->ctx_menu_key = key; ui_state->next_ctx_menu_anchor_key = anchor_box_key; ui_state->ctx_menu_anchor_off = anchor_off; ui_state->ctx_menu_touched_this_frame = 1; ui_state->ctx_menu_anchor_box_last_pos = v2f32(0, 0); ui_state->ctx_menu_root->default_nav_focus_active_key = ui_key_zero(); ui_state->ctx_menu_root->default_nav_focus_next_active_key = ui_key_zero(); } internal void ui_ctx_menu_close(void) { ui_state->next_ctx_menu_open = 0; } internal B32 ui_begin_ctx_menu(UI_Key key) { ui_push_parent(ui_root_from_state(ui_state)); ui_push_parent(ui_state->ctx_menu_root); ui_push_pref_width(ui_bottom_pref_width()); ui_push_pref_height(ui_bottom_pref_height()); ui_push_focus_hot(UI_FocusKind_Root); ui_push_focus_active(UI_FocusKind_Root); ui_push_tag(str8_lit(".")); B32 is_open = ui_key_match(key, ui_state->ctx_menu_key) && ui_state->ctx_menu_open; if(is_open != 0) UI_TagF("floating") { ui_state->ctx_menu_touched_this_frame = 1; ui_state->ctx_menu_root->flags |= UI_BoxFlag_RoundChildrenByParent; ui_state->ctx_menu_root->flags |= UI_BoxFlag_DrawBackgroundBlur; ui_state->ctx_menu_root->flags |= UI_BoxFlag_DrawBackground; ui_state->ctx_menu_root->flags |= UI_BoxFlag_DisableFocusOverlay; ui_state->ctx_menu_root->flags |= UI_BoxFlag_DrawBorder; ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clip; ui_state->ctx_menu_root->flags |= UI_BoxFlag_Clickable; ui_state->ctx_menu_root->corner_radii[Corner_00] = ui_state->ctx_menu_root->corner_radii[Corner_01] = ui_state->ctx_menu_root->corner_radii[Corner_10] = ui_state->ctx_menu_root->corner_radii[Corner_11] = ui_top_font_size()*0.25f; ui_state->ctx_menu_root->tags_key = ui_top_tags_key(); ui_state->ctx_menu_root->blur_size = ui_top_blur_size(); ui_state->ctx_menu_root->text_color = ui_color_from_name(str8_lit("text")); ui_state->ctx_menu_root->background_color = ui_color_from_name(str8_lit("background")); ui_spacer(ui_em(1.f, 1.f)); } ui_state->is_in_open_ctx_menu = is_open; return is_open; } internal void ui_end_ctx_menu(void) { if(ui_state->is_in_open_ctx_menu) { ui_state->is_in_open_ctx_menu = 0; ui_spacer(ui_em(1.f, 1.f)); } ui_pop_tag(); ui_pop_focus_active(); ui_pop_focus_hot(); ui_pop_pref_width(); ui_pop_pref_height(); ui_pop_parent(); ui_pop_parent(); } internal B32 ui_ctx_menu_is_open(UI_Key key) { return (ui_state->ctx_menu_open && ui_key_match(key, ui_state->ctx_menu_key)); } internal B32 ui_any_ctx_menu_is_open(void) { return ui_state->ctx_menu_open; } //- rjf: focus tree coloring internal B32 ui_is_focus_hot(void) { B32 result = (ui_state->focus_hot_stack.top->v == UI_FocusKind_On); if(result) { for(UI_FocusHotNode *n = ui_state->focus_hot_stack.top; n != 0; n = n->next) { if(n->v == UI_FocusKind_Root) { break; } if(n->v == UI_FocusKind_Off) { result = 0; break; } } } return result; } internal B32 ui_is_focus_active(void) { B32 result = (ui_state->focus_active_stack.top->v == UI_FocusKind_On); if(result) { for(UI_FocusActiveNode *n = ui_state->focus_active_stack.top; n != 0; n = n->next) { if(n->v == UI_FocusKind_Root) { break; } if(n->v == UI_FocusKind_Off) { result = 0; break; } } } return result; } //- rjf: implicit auto-managed tree-based focus state internal B32 ui_is_key_auto_focus_active(UI_Key key) { B32 result = 0; if(!ui_key_match(ui_key_zero(), key)) { for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_FocusActive && ui_key_match(key, p->default_nav_focus_active_key)) { result = 1; break; } } } return result; } internal B32 ui_is_key_auto_focus_hot(UI_Key key) { B32 result = 0; if(!ui_key_match(ui_key_zero(), key)) { for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_FocusHot && ((!(p->flags & UI_BoxFlag_FocusHotDisabled) && ui_key_match(key, p->default_nav_focus_hot_key)) || ui_key_match(key, p->default_nav_focus_active_key))) { result = 1; break; } } } return result; } internal void ui_set_auto_focus_active_key(UI_Key key) { for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_DefaultFocusNav) { p->default_nav_focus_next_active_key = key; break; } } } internal void ui_set_auto_focus_hot_key(UI_Key key) { for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_DefaultFocusNav) { p->default_nav_focus_next_hot_key = key; break; } } } //- rjf: current style tags key internal UI_Key ui_top_tags_key(void) { UI_Key key = ui_key_zero(); if(ui_state->tags_key_stack_top != 0) { key = ui_state->tags_key_stack_top->key; } return key; } //- rjf: theme color lookups internal Vec4F32 ui_color_from_name(String8 name) { Vec4F32 result = ui_color_from_tags_key_name(ui_top_tags_key(), name); return result; } internal Vec4F32 ui_color_from_tags_key_extras(UI_Key key, String8Array extras) { Vec4F32 result = {0}; if(ui_state->theme_pattern_cache_slots_count && extras.count > 0) { //- rjf: compute final key, mixing (tags_key, extras) UI_Key final_key = key; for EachIndex(idx, extras.count) { final_key = ui_key_from_string(final_key, extras.v[idx]); } //- rjf: map to existing node U64 slot_idx = final_key.u64[0]%ui_state->theme_pattern_cache_slots_count; UI_ThemePatternCacheSlot *slot = &ui_state->theme_pattern_cache_slots[slot_idx]; UI_ThemePatternCacheNode *node = 0; for(UI_ThemePatternCacheNode *n = slot->first; n != 0; n = n->slot_next) { if(ui_key_match(n->key, final_key)) { node = n; } } //- rjf: no node, or this node is stale? create and/or update if(node == 0 || node->last_build_index_accessed < ui_state->build_index) { // rjf: map tags_key (without name) -> full list of tags String8Array tags = {0}; { U64 tags_cache_slot_idx = key.u64[0]%ui_state->tags_cache_slots_count; UI_TagsCacheSlot *tags_cache_slot = &ui_state->tags_cache_slots[tags_cache_slot_idx]; for(UI_TagsCacheNode *n = tags_cache_slot->first; n != 0; n = n->next) { if(ui_key_match(n->key, key)) { tags = n->tags; break; } } } // rjf: map tags to theme pattern UI_Theme *theme = ui_state->theme; UI_ThemePattern *pattern = 0; U64 best_match_count = 0; for(U64 idx = 0; idx < theme->patterns_count; idx += 1) { UI_ThemePattern *p = &theme->patterns[idx]; U64 match_count = 0; B32 name_matches = 0; B32 all_p_tags_in_key = 1; for EachIndex(p_tags_idx, p->tags.count) { B32 p_tag_in_key = 0; for EachIndex(key_tags_idx, tags.count + extras.count) { String8 key_string = key_tags_idx < tags.count ? tags.v[key_tags_idx] : extras.v[key_tags_idx - tags.count]; if(str8_match(p->tags.v[p_tags_idx], key_string, 0)) { if(key_tags_idx == tags.count + extras.count - 1) { name_matches = 1; } p_tag_in_key = 1; match_count += 1; break; } } if(!p_tag_in_key) { all_p_tags_in_key = 0; break; } } if(name_matches && all_p_tags_in_key && match_count > best_match_count) { pattern = p; best_match_count = match_count; } if(match_count == tags.count + extras.count) { break; } } // rjf: store in (key, name) -> (pattern) cache B32 node_is_new = 0; if(node == 0) { node_is_new = 1; node = ui_state->theme_pattern_cache_node_free; if(node != 0) { SLLStackPop_N(ui_state->theme_pattern_cache_node_free, slot_next); } else { node = push_array(ui_state->arena, UI_ThemePatternCacheNode, 1); } DLLPushBack_NP(slot->first, slot->last, node, slot_next, slot_prev); DLLPushBack_NP(ui_state->lru_theme_pattern_cache_node, ui_state->mru_theme_pattern_cache_node, node, lru_next, lru_prev); node->key = final_key; } // rjf: update node's target color if(pattern != 0) { node->target_rgba = pattern->linear; if(node_is_new) { node->current_rgba = node->target_rgba; } } } //- rjf: mark this node as most-recently-used if(node != 0 && node->last_build_index_accessed < ui_state->build_index) { node->last_build_index_accessed = ui_state->build_index; DLLRemove_NP(ui_state->lru_theme_pattern_cache_node, ui_state->mru_theme_pattern_cache_node, node, lru_next, lru_prev); DLLPushBack_NP(ui_state->lru_theme_pattern_cache_node, ui_state->mru_theme_pattern_cache_node, node, lru_next, lru_prev); } //- rjf: grab resultant color if(node != 0) { result = node->current_rgba; } } return result; } internal Vec4F32 ui_color_from_tags_key_name(UI_Key key, String8 name) { String8Array extras = {&name, 1}; Vec4F32 result = ui_color_from_tags_key_extras(key, extras); return result; } //- rjf: box node construction internal UI_Box * ui_build_box_from_key(UI_BoxFlags flags, UI_Key key) { ui_state->build_box_count += 1; //- rjf: grab active parent UI_Box *parent = ui_top_parent(); //- rjf: try to get box UI_BoxFlags last_flags = 0; UI_Box *box = ui_box_from_key(key); B32 box_first_frame = ui_box_is_nil(box); last_flags = box->flags; //- rjf: zero key on duplicate if(!box_first_frame && box->last_touched_build_index == ui_state->build_index) { box = &ui_nil_box; key = ui_key_zero(); box_first_frame = 1; } //- rjf: gather info from box B32 box_is_transient = ui_key_match(key, ui_key_zero()); //- rjf: allocate box if it doesn't yet exist if(box_first_frame) { box = !box_is_transient ? ui_state->first_free_box : 0; ui_state->is_animating = ui_state->is_animating || !box_is_transient; if(!ui_box_is_nil(box)) { SLLStackPop(ui_state->first_free_box); } else { box = push_array_no_zero(box_is_transient ? ui_build_arena() : ui_state->arena, UI_Box, 1); } MemoryZeroStruct(box); } //- rjf: zero out per-frame state { box->first = box->last = box->next = box->prev = box->parent = &ui_nil_box; box->child_count = 0; box->flags = 0; box->hover_cursor = OS_Cursor_Pointer; MemoryZeroArray(box->pref_size); MemoryZeroStruct(&box->draw_bucket); } //- rjf: hook into persistent state table if(box_first_frame && !box_is_transient) { U64 slot = key.u64[0] % ui_state->box_table_size; DLLInsert_NPZ(&ui_nil_box, ui_state->box_table[slot].hash_first, ui_state->box_table[slot].hash_last, ui_state->box_table[slot].hash_last, box, hash_next, hash_prev); } //- rjf: hook into per-frame tree structure if(!ui_box_is_nil(parent)) { DLLPushBack_NPZ(&ui_nil_box, parent->first, parent->last, box, next, prev); parent->child_count += 1; box->parent = parent; } //- rjf: fill box { box->key = key; box->flags = (flags | ui_state->flags_stack.top->v) & ~ui_state->omit_flags_stack.top->v; box->fastpath_codepoint = ui_state->fastpath_codepoint_stack.top->v; box->group_key = ui_state->group_key_stack.top->v; if(ui_is_focus_active() && (box->flags & UI_BoxFlag_DefaultFocusNav) && ui_key_match(ui_state->default_nav_root_key, ui_key_zero())) { ui_state->default_nav_root_key = box->key; } if(box_first_frame) { box->first_touched_build_index = ui_state->build_index; box->disabled_t = (F32)!!(box->flags & UI_BoxFlag_Disabled); } box->last_touched_build_index = ui_state->build_index; if(box->flags & UI_BoxFlag_Disabled && (!(last_flags & UI_BoxFlag_Disabled) || box_first_frame)) { box->first_disabled_build_index = ui_state->build_index; } if(ui_state->fixed_x_stack.top != &ui_state->fixed_x_nil_stack_top) { box->flags |= UI_BoxFlag_FloatingX; box->fixed_position.x = ui_state->fixed_x_stack.top->v; } if(ui_state->fixed_y_stack.top != &ui_state->fixed_y_nil_stack_top) { box->flags |= UI_BoxFlag_FloatingY; box->fixed_position.y = ui_state->fixed_y_stack.top->v; } if(ui_state->fixed_width_stack.top != &ui_state->fixed_width_nil_stack_top) { box->flags |= UI_BoxFlag_FixedWidth; box->fixed_size.x = ui_state->fixed_width_stack.top->v; } else { box->pref_size[Axis2_X] = ui_state->pref_width_stack.top->v; } if(ui_state->fixed_height_stack.top != &ui_state->fixed_height_nil_stack_top) { box->flags |= UI_BoxFlag_FixedHeight; box->fixed_size.y = ui_state->fixed_height_stack.top->v; } else { box->pref_size[Axis2_Y] = ui_state->pref_height_stack.top->v; } box->min_size.v[Axis2_X] = ui_state->min_width_stack.top->v; box->min_size.v[Axis2_Y] = ui_state->min_height_stack.top->v; B32 is_auto_focus_active = ui_is_key_auto_focus_active(key); B32 is_auto_focus_hot = ui_is_key_auto_focus_hot(key); if(is_auto_focus_active) { ui_set_next_focus_active(UI_FocusKind_On); } if(is_auto_focus_hot) { ui_set_next_focus_hot(UI_FocusKind_On); } box->flags |= UI_BoxFlag_FocusHot * (ui_state->focus_hot_stack.top->v == UI_FocusKind_On); box->flags |= UI_BoxFlag_FocusActive * (ui_state->focus_active_stack.top->v == UI_FocusKind_On); if(box->flags & UI_BoxFlag_FocusHot && !ui_is_focus_hot()) { box->flags |= UI_BoxFlag_FocusHotDisabled; } if(box->flags & UI_BoxFlag_FocusActive && !ui_is_focus_active()) { box->flags |= UI_BoxFlag_FocusActiveDisabled; } box->text_align = ui_state->text_alignment_stack.top->v; box->child_layout_axis = ui_state->child_layout_axis_stack.top->v; box->font = ui_state->font_stack.top->v; box->font_size = ui_state->font_size_stack.top->v; box->tab_size = ui_state->tab_size_stack.top->v; box->text_raster_flags = ui_state->text_raster_flags_stack.top->v; box->corner_radii[Corner_00] = ui_state->corner_radius_00_stack.top->v; box->corner_radii[Corner_01] = ui_state->corner_radius_01_stack.top->v; box->corner_radii[Corner_10] = ui_state->corner_radius_10_stack.top->v; box->corner_radii[Corner_11] = ui_state->corner_radius_11_stack.top->v; box->blur_size = ui_state->blur_size_stack.top->v; box->transparency = ui_state->transparency_stack.top->v; box->squish = ui_state->squish_stack.top->v; box->text_padding = ui_state->text_padding_stack.top->v; box->hover_cursor = ui_state->hover_cursor_stack.top->v; box->custom_draw = 0; box->tags_key = ui_key_zero(); if(ui_state->tags_key_stack_top != 0) { box->tags_key = ui_state->tags_key_stack_top->key; } if(box->flags & UI_BoxFlag_DrawBackground) { if(ui_state->background_color_stack.top != &ui_state->background_color_nil_stack_top) { box->background_color = ui_state->background_color_stack.top->v; } else { box->background_color = ui_color_from_name(str8_lit("background")); } } if(box->flags & UI_BoxFlag_DrawText) { if(ui_state->text_color_stack.top != &ui_state->text_color_nil_stack_top) { box->text_color = ui_state->text_color_stack.top->v; } else { box->text_color = ui_color_from_name(str8_lit("text")); } } if(box->flags & (UI_BoxFlag_DrawBorder| UI_BoxFlag_DrawSideRight| UI_BoxFlag_DrawSideLeft| UI_BoxFlag_DrawSideTop| UI_BoxFlag_DrawSideBottom)) { if(ui_state->border_color_stack.top != &ui_state->border_color_nil_stack_top) { box->border_color = ui_state->border_color_stack.top->v; } else { box->border_color = ui_color_from_name(str8_lit("border")); } } } //- rjf: auto-pop all stacks { UI_AutoPopStacks(ui_state); } //- rjf: return return box; } internal UI_Key ui_active_seed_key(void) { UI_Box *keyed_ancestor = &ui_nil_box; { for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(!ui_key_match(ui_key_zero(), p->key)) { keyed_ancestor = p; break; } } } return keyed_ancestor->key; } internal UI_Box * ui_build_box_from_string(UI_BoxFlags flags, String8 string) { //- rjf: grab active parent UI_Box *parent = ui_top_parent(); //- rjf: figure out key UI_Key key = ui_key_from_string(ui_active_seed_key(), string); //- rjf: build box from key, equip passed string UI_Box *box = ui_build_box_from_key(flags, key); if(flags & UI_BoxFlag_DrawText) { ui_box_equip_display_string(box, string); } //- rjf: return return box; } internal UI_Box * ui_build_box_from_stringf(UI_BoxFlags flags, char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); va_end(args); UI_Box *box = ui_build_box_from_string(flags, string); scratch_end(scratch); return box; } //- rjf: box node equipment internal void ui_box_equip_display_string(UI_Box *box, String8 string) { box->string = push_str8_copy(ui_build_arena(), string); box->flags |= UI_BoxFlag_HasDisplayString; Vec4F32 text_color = box->text_color; if(box->flags & UI_BoxFlag_DrawText && (box->fastpath_codepoint == 0 || !(box->flags & UI_BoxFlag_DrawTextFastpathCodepoint))) { String8 display_string = ui_box_display_string(box); DR_FStrNode fstr_n = {0, {display_string, {box->font, box->text_raster_flags, text_color, box->font_size, 0, 0}}}; DR_FStrList fstrs = {&fstr_n, &fstr_n, 1}; box->display_fstrs = dr_fstrs_copy(ui_build_arena(), &fstrs); box->display_fruns = dr_fruns_from_fstrs(ui_build_arena(), box->tab_size, &box->display_fstrs); } else if(box->flags & UI_BoxFlag_DrawText && box->flags & UI_BoxFlag_DrawTextFastpathCodepoint && box->fastpath_codepoint != 0) { Temp scratch = scratch_begin(0, 0); String8 display_string = ui_box_display_string(box); String32 fpcp32 = str32(&box->fastpath_codepoint, 1); String8 fpcp = str8_from_32(scratch.arena, fpcp32); U64 fpcp_pos = str8_find_needle(display_string, 0, fpcp, StringMatchFlag_CaseInsensitive); if(fpcp_pos < display_string.size) { DR_FStrNode pst_fstr_n = {0, {str8_skip(display_string, fpcp_pos+fpcp.size), {box->font, box->text_raster_flags, text_color, box->font_size, 0, 0}}}; DR_FStrNode cdp_fstr_n = {&pst_fstr_n, {str8_substr(display_string, r1u64(fpcp_pos, fpcp_pos+fpcp.size)), {box->font, box->text_raster_flags, text_color, box->font_size, 3.f, 0}}}; DR_FStrNode pre_fstr_n = {&cdp_fstr_n, {str8_prefix(display_string, fpcp_pos), {box->font, box->text_raster_flags, text_color, box->font_size, 0, 0}}}; DR_FStrList fstrs = {&pre_fstr_n, &pst_fstr_n, 3}; box->display_fstrs = dr_fstrs_copy(ui_build_arena(), &fstrs); box->display_fruns = dr_fruns_from_fstrs(ui_build_arena(), box->tab_size, &box->display_fstrs); } else { DR_FStrNode fstr_n = {0, {display_string, {box->font, box->text_raster_flags, text_color, box->font_size, 0, 0}}}; DR_FStrList fstrs = {&fstr_n, &fstr_n, 1}; box->display_fstrs = dr_fstrs_copy(ui_build_arena(), &fstrs); box->display_fruns = dr_fruns_from_fstrs(ui_build_arena(), box->tab_size, &box->display_fstrs); } scratch_end(scratch); } } internal void ui_box_equip_display_fstrs(UI_Box *box, DR_FStrList *strings) { box->flags |= UI_BoxFlag_HasDisplayString; box->string = dr_string_from_fstrs(ui_build_arena(), strings); box->display_fstrs = dr_fstrs_copy(ui_build_arena(), strings); box->display_fruns = dr_fruns_from_fstrs(ui_build_arena(), box->tab_size, &box->display_fstrs); } internal inline void ui_box_equip_fuzzy_match_ranges(UI_Box *box, FuzzyMatchRangeList *matches) { box->flags |= UI_BoxFlag_HasFuzzyMatchRanges; box->fuzzy_match_ranges = fuzzy_match_range_list_copy(ui_build_arena(), matches); } internal void ui_box_equip_draw_bucket(UI_Box *box, DR_Bucket *bucket) { box->flags |= UI_BoxFlag_DrawBucket; if(box->draw_bucket != 0) { DR_BucketScope(box->draw_bucket) dr_sub_bucket(bucket); } else { box->draw_bucket = bucket; } } internal void ui_box_equip_custom_draw(UI_Box *box, UI_BoxCustomDrawFunctionType *custom_draw, void *user_data) { box->custom_draw = custom_draw; box->custom_draw_user_data = user_data; } //- rjf: box accessors / queries internal String8 ui_box_display_string(UI_Box *box) { String8 result = box->string; if(!(box->flags & UI_BoxFlag_DisableIDString)) { result = ui_display_part_from_key_string(result); } return result; } internal Vec2F32 ui_box_text_position(UI_Box *box) { Vec2F32 result = {0}; FNT_Tag font = box->font; F32 font_size = box->font_size; FNT_Metrics font_metrics = fnt_metrics_from_tag_size(font, font_size); result.y = floor_f32((box->rect.p0.y + box->rect.p1.y)/2.f + font_metrics.ascent/2.f - font_metrics.descent/2.f); switch(box->text_align) { default: case UI_TextAlign_Left: { result.x = box->rect.p0.x + box->text_padding; }break; case UI_TextAlign_Center: { Vec2F32 text_dim = box->display_fruns.dim; result.x = round_f32((box->rect.p0.x + box->rect.p1.x)/2 - text_dim.x/2); result.x = ClampBot(result.x, box->rect.x0); }break; case UI_TextAlign_Right: { Vec2F32 text_dim = box->display_fruns.dim; result.x = round_f32((box->rect.p1.x) - text_dim.x - box->text_padding); result.x = ClampBot(result.x, box->rect.x0); }break; } result.x = floor_f32(result.x); return result; } internal U64 ui_box_char_pos_from_xy(UI_Box *box, Vec2F32 xy) { FNT_Tag font = box->font; F32 font_size = box->font_size; String8 line = ui_box_display_string(box); U64 result = fnt_char_pos_from_tag_size_string_p(font, font_size, 0, box->tab_size, line, xy.x - ui_box_text_position(box).x); return result; } //////////////////////////////// //~ rjf: Box Interaction internal UI_Signal ui_signal_from_box(UI_Box *box) { B32 is_focus_hot = box->flags & UI_BoxFlag_FocusHot && !(box->flags & UI_BoxFlag_FocusHotDisabled); UI_Signal sig = {box}; sig.event_flags |= os_get_modifiers(); ////////////////////////////// //- rjf: calculate possibly-clipped box rectangle // Rng2F32 rect = box->rect; for(UI_Box *b = box->parent; !ui_box_is_nil(b); b = b->parent) { if(b->flags & UI_BoxFlag_Clip) { rect = intersect_2f32(rect, b->rect); } } ////////////////////////////// //- rjf: determine if we're under the context menu or not // B32 ctx_menu_is_ancestor = 0; { for(UI_Box *parent = box; !ui_box_is_nil(parent); parent = parent->parent) { if(parent == ui_state->ctx_menu_root) { ctx_menu_is_ancestor = 1; break; } } } ////////////////////////////// //- rjf: calculate blacklist rectangles // Rng2F32 blacklist_rect = {0}; if(!ctx_menu_is_ancestor && ui_state->ctx_menu_open) { blacklist_rect = ui_state->ctx_menu_root->rect; } ////////////////////////////// //- rjf: process events related to this box // B32 view_scrolled = 0; for(UI_Event *evt = 0; ui_next_event(&evt);) { B32 taken = 0; //- rjf: unpack event Vec2F32 evt_mouse = evt->pos; B32 evt_mouse_in_bounds = !contains_2f32(blacklist_rect, evt_mouse) && contains_2f32(rect, evt_mouse); UI_MouseButtonKind evt_mouse_button_kind = (evt->key == OS_Key_LeftMouseButton ? UI_MouseButtonKind_Left : evt->key == OS_Key_MiddleMouseButton ? UI_MouseButtonKind_Middle : evt->key == OS_Key_RightMouseButton ? UI_MouseButtonKind_Right : UI_MouseButtonKind_Left); B32 evt_key_is_mouse = (evt->key == OS_Key_LeftMouseButton || evt->key == OS_Key_MiddleMouseButton || evt->key == OS_Key_RightMouseButton); sig.event_flags |= evt->modifiers; //- rjf: mouse presses in box -> set hot/active; mark signal accordingly if(box->flags & UI_BoxFlag_MouseClickable && evt->kind == UI_EventKind_Press && evt_mouse_in_bounds && evt_key_is_mouse) { ui_state->hot_box_key = box->key; ui_state->active_box_key[evt_mouse_button_kind] = box->key; sig.f |= (UI_SignalFlag_LeftPressed<drag_start_mouse = evt->pos; if(ui_key_match(box->key, ui_state->press_key_history[evt_mouse_button_kind][0]) && evt->timestamp_us-ui_state->press_timestamp_history_us[evt_mouse_button_kind][0] <= 1000000*os_get_gfx_info()->double_click_time) { sig.f |= (UI_SignalFlag_LeftDoubleClicked<key, ui_state->press_key_history[evt_mouse_button_kind][0]) && ui_key_match(box->key, ui_state->press_key_history[evt_mouse_button_kind][1]) && evt->timestamp_us-ui_state->press_timestamp_history_us[evt_mouse_button_kind][0] <= 1000000*os_get_gfx_info()->double_click_time && ui_state->press_timestamp_history_us[evt_mouse_button_kind][0] - ui_state->press_timestamp_history_us[evt_mouse_button_kind][1] <= 1000000*os_get_gfx_info()->double_click_time) { sig.f |= (UI_SignalFlag_LeftTripleClicked<press_timestamp_history_us[evt_mouse_button_kind][1], &ui_state->press_timestamp_history_us[evt_mouse_button_kind][0], sizeof(ui_state->press_timestamp_history_us[evt_mouse_button_kind][0]) * ArrayCount(ui_state->press_timestamp_history_us[evt_mouse_button_kind])-1); MemoryCopy(&ui_state->press_key_history[evt_mouse_button_kind][1], &ui_state->press_key_history[evt_mouse_button_kind][0], sizeof(ui_state->press_key_history[evt_mouse_button_kind][0]) * ArrayCount(ui_state->press_key_history[evt_mouse_button_kind])-1); MemoryCopy(&ui_state->press_pos_history[evt_mouse_button_kind][1], &ui_state->press_pos_history[evt_mouse_button_kind][0], sizeof(ui_state->press_pos_history[evt_mouse_button_kind][0]) * ArrayCount(ui_state->press_pos_history[evt_mouse_button_kind])-1); ui_state->press_timestamp_history_us[evt_mouse_button_kind][0] = evt->timestamp_us; ui_state->press_key_history[evt_mouse_button_kind][0] = box->key; ui_state->press_pos_history[evt_mouse_button_kind][0] = evt_mouse; taken = 1; } //- rjf: mouse releases in active box -> unset active; mark signal accordingly if(box->flags & UI_BoxFlag_MouseClickable && evt->kind == UI_EventKind_Release && ui_key_match(ui_state->active_box_key[evt_mouse_button_kind], box->key) && evt_mouse_in_bounds && evt_key_is_mouse) { ui_state->active_box_key[evt_mouse_button_kind] = ui_key_zero(); sig.f |= (UI_SignalFlag_LeftReleased< unset hot/active if(box->flags & UI_BoxFlag_MouseClickable && evt->kind == UI_EventKind_Release && ui_key_match(ui_state->active_box_key[evt_mouse_button_kind], box->key) && !evt_mouse_in_bounds && evt_key_is_mouse) { ui_state->hot_box_key = ui_key_zero(); ui_state->active_box_key[evt_mouse_button_kind] = ui_key_zero(); sig.f |= (UI_SignalFlag_LeftReleased< mark signal if(box->flags & UI_BoxFlag_KeyboardClickable && is_focus_hot && evt->kind == UI_EventKind_Press && evt->slot == UI_EventActionSlot_Accept) { sig.f |= UI_SignalFlag_KeyboardPressed; taken = 1; } //- rjf: focus is hot & copy event -> remember to copy this box tree's text content if(is_focus_hot && evt->flags & UI_EventFlag_Copy && !(evt->flags & UI_EventFlag_Delete) && !ui_key_match(ui_key_zero(), box->key)) { ui_state->clipboard_copy_key = box->key; taken = 1; } //- rjf: ancestor is focused & fastpath codepoint pressed -> press if(box->flags & UI_BoxFlag_Clickable && box->fastpath_codepoint != 0 && evt->string.size != 0) { B32 ancestor_is_focused = 0; for(UI_Box *parent = box->parent; !ui_box_is_nil(parent); parent = parent->parent) { if(parent->flags & UI_BoxFlag_FocusActive) { ancestor_is_focused = 1; if(parent->flags & UI_BoxFlag_FocusActiveDisabled || !ui_key_match(parent->default_nav_focus_active_key, ui_key_zero())) { ancestor_is_focused = 0; break; } } } if(ancestor_is_focused) { Temp scratch = scratch_begin(0, 0); String32 insertion32 = str32_from_8(scratch.arena, evt->string); if(insertion32.size == 1 && insertion32.str[0] == box->fastpath_codepoint) { taken = 1; sig.f |= UI_SignalFlag_Clicked|UI_SignalFlag_Pressed; } scratch_end(scratch); } } //- rjf: scrolling if(box->flags & UI_BoxFlag_Scroll && evt->kind == UI_EventKind_Scroll && (evt->modifiers == 0 || evt->modifiers == OS_Modifier_Shift) && evt_mouse_in_bounds) { Vec2F32 delta = evt->delta_2f32; if(evt->modifiers & OS_Modifier_Shift) { Swap(F32, delta.x, delta.y); } Vec2S16 delta16 = v2s16((S16)(delta.x/30.f), (S16)(delta.y/30.f)); if(delta.x > 0 && delta16.x == 0) { delta16.x = +1; } if(delta.x < 0 && delta16.x == 0) { delta16.x = -1; } if(delta.y > 0 && delta16.y == 0) { delta16.y = +1; } if(delta.y < 0 && delta16.y == 0) { delta16.y = -1; } sig.scroll.x += delta16.x; sig.scroll.y += delta16.y; taken = 1; } //- rjf: view scrolling if(box->flags & UI_BoxFlag_ViewScroll && box->first_touched_build_index != box->last_touched_build_index && evt->kind == UI_EventKind_Scroll && (evt->modifiers == 0 || evt->modifiers == OS_Modifier_Shift) && evt_mouse_in_bounds) { Vec2F32 delta = evt->delta_2f32; if(evt->modifiers & OS_Modifier_Shift) { Swap(F32, delta.x, delta.y); } if(!(box->flags & UI_BoxFlag_ViewScrollX)) { if(delta.y == 0) { delta.y = delta.x; } delta.x = 0; } if(!(box->flags & UI_BoxFlag_ViewScrollY)) { if(delta.x == 0) { delta.x = delta.y; } delta.y = 0; } box->view_off_target.x += delta.x; box->view_off_target.y += delta.y; view_scrolled = 1; taken = 1; } //- rjf: taken -> eat event if(taken) { ui_eat_event(evt); } } ////////////////////////////// //- rjf: clamp view scrolling // if(view_scrolled && box->flags & UI_BoxFlag_ViewClamp) { Vec2F32 max_view_off_target = { ClampBot(0, box->view_bounds.x - box->fixed_size.x), ClampBot(0, box->view_bounds.y - box->fixed_size.y), }; if(box->flags & UI_BoxFlag_ViewClampX) { box->view_off_target.x = Clamp(0, box->view_off_target.x, max_view_off_target.x); } if(box->flags & UI_BoxFlag_ViewClampY) { box->view_off_target.y = Clamp(0, box->view_off_target.y, max_view_off_target.y); } } ////////////////////////////// //- rjf: active -> dragging // if(box->flags & UI_BoxFlag_MouseClickable) { for EachEnumVal(UI_MouseButtonKind, k) { if(ui_key_match(ui_state->active_box_key[k], box->key) || sig.f & (UI_SignalFlag_LeftPressed< double-dragging // if(box->flags & UI_BoxFlag_MouseClickable) { for EachEnumVal(UI_MouseButtonKind, k) { if(sig.f & (UI_SignalFlag_LeftDragging<press_key_history[k][0], box->key) && ui_key_match(ui_state->press_key_history[k][1], box->key) && ui_state->press_timestamp_history_us[k][0] - ui_state->press_timestamp_history_us[k][1] <= 1000000*os_get_gfx_info()->double_click_time && length_2f32(sub_2f32(ui_state->press_pos_history[k][0], ui_state->press_pos_history[k][1])) < 10.f) { sig.f |= (UI_SignalFlag_LeftDoubleDragging< triple-dragging // if(box->flags & UI_BoxFlag_MouseClickable) { for EachEnumVal(UI_MouseButtonKind, k) { if(sig.f & (UI_SignalFlag_LeftDragging<press_key_history[k][0], box->key) && ui_key_match(ui_state->press_key_history[k][1], box->key) && ui_key_match(ui_state->press_key_history[k][2], box->key) && ui_state->press_timestamp_history_us[k][0] - ui_state->press_timestamp_history_us[k][1] <= 1000000*os_get_gfx_info()->double_click_time && ui_state->press_timestamp_history_us[k][1] - ui_state->press_timestamp_history_us[k][2] <= 1000000*os_get_gfx_info()->double_click_time && length_2f32(sub_2f32(ui_state->press_pos_history[k][0], ui_state->press_pos_history[k][1])) < 10.f && length_2f32(sub_2f32(ui_state->press_pos_history[k][1], ui_state->press_pos_history[k][2])) < 10.f) { sig.f |= (UI_SignalFlag_LeftTripleDragging< always mark mouse-over // { if(contains_2f32(rect, ui_state->mouse) && !contains_2f32(blacklist_rect, ui_state->mouse)) { sig.f |= UI_SignalFlag_MouseOver; } } ////////////////////////////// //- rjf: mouse is over this box's rect, no other hot key? -> set hot key, mark hovering // { if(box->flags & UI_BoxFlag_MouseClickable && contains_2f32(rect, ui_state->mouse) && !contains_2f32(blacklist_rect, ui_state->mouse) && (ui_key_match(ui_state->hot_box_key, ui_key_zero()) || ui_key_match(ui_state->hot_box_key, box->key)) && (ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], ui_key_zero()) || ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Left], box->key)) && (ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Middle], ui_key_zero()) || ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Middle], box->key)) && (ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], ui_key_zero()) || ui_key_match(ui_state->active_box_key[UI_MouseButtonKind_Right], box->key))) { ui_state->hot_box_key = box->key; sig.f |= UI_SignalFlag_Hovering; } } ////////////////////////////// //- rjf: mouse is over this box's rect, currently-active-key has the same group key? -> set hot/active key // if(box->flags & UI_BoxFlag_MouseClickable && contains_2f32(rect, ui_state->mouse) && !contains_2f32(blacklist_rect, ui_state->mouse) && !ui_key_match(ui_key_zero(), box->group_key)) { for EachEnumVal(UI_MouseButtonKind, k) { UI_Box *active_box = ui_box_from_key(ui_state->active_box_key[k]); if(ui_key_match(box->group_key, active_box->group_key)) { ui_state->hot_box_key = box->key; ui_state->active_box_key[k] = box->key; sig.f |= UI_SignalFlag_Hovering|(UI_SignalFlag_Dragging< set drop hot key // { if(box->flags & UI_BoxFlag_DropSite && contains_2f32(rect, ui_state->mouse) && !contains_2f32(blacklist_rect, ui_state->mouse) && (ui_key_match(ui_state->drop_hot_box_key, ui_key_zero()) || ui_key_match(ui_state->drop_hot_box_key, box->key))) { ui_state->drop_hot_box_key = box->key; } } ////////////////////////////// //- rjf: mouse is not over this box's rect, but this is the drop hot key? -> zero drop hot key // { if(box->flags & UI_BoxFlag_DropSite && (!contains_2f32(rect, ui_state->mouse) || contains_2f32(blacklist_rect, ui_state->mouse)) && ui_key_match(ui_state->drop_hot_box_key, box->key)) { ui_state->drop_hot_box_key = ui_key_zero(); } } ////////////////////////////// //- rjf: clicking on something outside the context menu kills the context menu // if(!ctx_menu_is_ancestor && sig.f & (UI_SignalFlag_LeftPressed|UI_SignalFlag_RightPressed|UI_SignalFlag_MiddlePressed)) { ui_ctx_menu_close(); } ////////////////////////////// //- rjf: get default nav ancestor // UI_Box *default_nav_parent = &ui_nil_box; for(UI_Box *p = ui_top_parent(); !ui_box_is_nil(p); p = p->parent) { if(p->flags & UI_BoxFlag_DefaultFocusNav) { default_nav_parent = p; break; } } ////////////////////////////// //- rjf: clicking in default nav -> set navigation state to this box // if(box->flags & UI_BoxFlag_ClickToFocus && sig.f&UI_SignalFlag_Pressed && !ui_box_is_nil(default_nav_parent)) { default_nav_parent->default_nav_focus_next_hot_key = box->key; if(!ui_key_match(default_nav_parent->default_nav_focus_active_key, box->key)) { default_nav_parent->default_nav_focus_next_active_key = ui_key_zero(); } } return sig; } //////////////////////////////// //~ rjf: Animation Cache Interaction API internal F32 ui_anim_(UI_Key key, UI_AnimParams *params) { // rjf: get animation cache node UI_AnimNode *node = &ui_nil_anim_node; if(ui_state != 0) { U64 slot_idx = key.u64[0]%ui_state->anim_slots_count; UI_AnimSlot *slot = &ui_state->anim_slots[slot_idx]; for(UI_AnimNode *n = slot->first; n != &ui_nil_anim_node && n != 0; n = n->slot_next) { if(ui_key_match(n->key, key)) { node = n; break; } } if(node == &ui_nil_anim_node) { node = ui_state->free_anim_node; if(node != 0) { SLLStackPop_N(ui_state->free_anim_node, slot_next); } else { node = push_array(ui_state->arena, UI_AnimNode, 1); } node->first_touched_build_index = ui_state->build_index; node->key = key; MemoryCopyStruct(&node->params, params); node->current = params->initial; DLLPushBack_NPZ(&ui_nil_anim_node, slot->first, slot->last, node, slot_next, slot_prev); } else { DLLRemove_NPZ(&ui_nil_anim_node, ui_state->lru_anim_node, ui_state->mru_anim_node, node, lru_next, lru_prev); } } // rjf: touch node & update parameters - grab current if(node != &ui_nil_anim_node) { node->last_touched_build_index = ui_state->build_index; DLLPushBack_NPZ(&ui_nil_anim_node, ui_state->lru_anim_node, ui_state->mru_anim_node, node, lru_next, lru_prev); if(params->reset) { node->current = params->initial; } MemoryCopyStruct(&node->params, params); if(node->params.epsilon == 0) { node->params.epsilon = 0.005f; } if(node->params.rate == 1 || abs_f32(node->current - node->params.target) < abs_f32(node->params.epsilon)) { node->current = node->params.target; } } return node->current; } //////////////////////////////// //~ rjf: Stacks #define UI_StackTopImpl(state, name_upper, name_lower) \ return state->name_lower##_stack.top->v; #define UI_StackBottomImpl(state, name_upper, name_lower) \ return state->name_lower##_stack.bottom_val; #define UI_StackPushImpl(state, name_upper, name_lower, type, new_value) \ UI_##name_upper##Node *node = state->name_lower##_stack.free;\ if(node != 0) {SLLStackPop(state->name_lower##_stack.free);}\ else {node = push_array(ui_build_arena(), UI_##name_upper##Node, 1);}\ type old_value = state->name_lower##_stack.top->v;\ node->v = new_value;\ SLLStackPush(state->name_lower##_stack.top, node);\ if(node->next == &state->name_lower##_nil_stack_top)\ {\ state->name_lower##_stack.bottom_val = (node->v);\ }\ state->name_lower##_stack.auto_pop = 0;\ state->name_lower##_stack.gen += 1;\ return old_value; #define UI_StackPopImpl(state, name_upper, name_lower) \ UI_##name_upper##Node *popped = state->name_lower##_stack.top;\ if(popped != &state->name_lower##_nil_stack_top)\ {\ SLLStackPop(state->name_lower##_stack.top);\ SLLStackPush(state->name_lower##_stack.free, popped);\ state->name_lower##_stack.auto_pop = 0;\ state->name_lower##_stack.gen += 1;\ }\ return popped->v;\ #define UI_StackSetNextImpl(state, name_upper, name_lower, type, new_value) \ UI_##name_upper##Node *node = state->name_lower##_stack.free;\ if(node != 0) {SLLStackPop(state->name_lower##_stack.free);}\ else {node = push_array(ui_build_arena(), UI_##name_upper##Node, 1);}\ type old_value = state->name_lower##_stack.top->v;\ node->v = new_value;\ SLLStackPush(state->name_lower##_stack.top, node);\ state->name_lower##_stack.auto_pop = 1;\ state->name_lower##_stack.gen += 1;\ return old_value; internal void ui__push_tags_key_from_appended_string(String8 string) { B32 is_new_root = str8_match(str8_lit("."), string, 0); // rjf: generate new key, by combining hash of this new string with the top // of the tags key stack UI_Key seed_key = {0}; if(!is_new_root && ui_state->tags_key_stack_top != 0) { seed_key = ui_state->tags_key_stack_top->key; } UI_Key key = seed_key; if(!is_new_root && string.size > 0) { key = ui_key_from_string(seed_key, string); } // rjf: push this new key onto the stack { UI_TagsKeyStackNode *node = ui_state->tags_key_stack_free; if(node != 0) { SLLStackPop(ui_state->tags_key_stack_free); } else { node = push_array(ui_build_arena(), UI_TagsKeyStackNode, 1); } SLLStackPush(ui_state->tags_key_stack_top, node); node->key = key; } // rjf: store in tags cache if(!is_new_root) { U64 slot_idx = key.u64[0] % ui_state->tags_cache_slots_count; UI_TagsCacheSlot *slot = &ui_state->tags_cache_slots[slot_idx]; UI_TagsCacheNode *node = 0; for(UI_TagsCacheNode *n = slot->first; n != 0; n = n->next) { if(ui_key_match(n->key, key)) { node = n; break; } } if(node == 0) { Temp scratch = scratch_begin(0, 0); String8List tags = {0}; if(string.size != 0) { str8_list_push(scratch.arena, &tags, push_str8_copy(ui_build_arena(), string)); } for(UI_TagNode *n = ui_state->tag_stack.top; n != 0; n = n->next) { if(n->v.size == 1 && n->v.str[0] == '.') { break; } if(n->v.size != 0) { str8_list_push(scratch.arena, &tags, push_str8_copy(ui_build_arena(), n->v)); } } node = push_array(ui_build_arena(), UI_TagsCacheNode, 1); SLLQueuePush(slot->first, slot->last, node); node->key = key; node->tags = str8_array_from_list(ui_build_arena(), &tags); scratch_end(scratch); } } } internal void ui__pop_tags_key(void) { if(ui_state->tags_key_stack_top != 0) { UI_TagsKeyStackNode *popped = ui_state->tags_key_stack_top; SLLStackPop(ui_state->tags_key_stack_top); SLLStackPush(ui_state->tags_key_stack_free, popped); } } //- rjf: manual implementations internal String8 ui_top_tag(void) { UI_StackTopImpl(ui_state, Tag, tag) } internal String8 ui_bottom_tag(void) { UI_StackBottomImpl(ui_state, Tag, tag) } internal String8 ui_push_tag(String8 v) { ui__push_tags_key_from_appended_string(v); UI_StackPushImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v)) } internal String8 ui_pop_tag(void) { ui__pop_tags_key(); UI_StackPopImpl(ui_state, Tag, tag) } internal String8 ui_set_next_tag(String8 v) { ui__push_tags_key_from_appended_string(v); UI_StackSetNextImpl(ui_state, Tag, tag, String8, push_str8_copy(ui_build_arena(), v)) } //- rjf: helpers internal Rng2F32 ui_push_rect(Rng2F32 rect) { Rng2F32 replaced = {0}; Vec2F32 size = dim_2f32(rect); replaced.x0 = ui_push_fixed_x(rect.x0); replaced.y0 = ui_push_fixed_y(rect.y0); replaced.x1 = replaced.x0 + ui_push_fixed_width(size.x); replaced.y1 = replaced.y0 + ui_push_fixed_height(size.y); return replaced; } internal Rng2F32 ui_pop_rect(void) { Rng2F32 popped = {0}; popped.x0 = ui_pop_fixed_x(); popped.y0 = ui_pop_fixed_y(); popped.x1 = popped.x0 + ui_pop_fixed_width(); popped.y1 = popped.y0 + ui_pop_fixed_height(); return popped; } internal void ui_set_next_rect(Rng2F32 rect) { Vec2F32 size = dim_2f32(rect); ui_set_next_fixed_x(rect.x0); ui_set_next_fixed_y(rect.y0); ui_set_next_fixed_width(size.x); ui_set_next_fixed_height(size.y); } internal UI_Size ui_push_pref_size(Axis2 axis, UI_Size v) { UI_Size result = zero_struct; switch(axis) { default: break; case Axis2_X: {result = ui_push_pref_width(v);}break; case Axis2_Y: {result = ui_push_pref_height(v);}break; } return result; } internal UI_Size ui_pop_pref_size(Axis2 axis) { UI_Size result = zero_struct; switch(axis) { default: break; case Axis2_X: {result = ui_pop_pref_width();}break; case Axis2_Y: {result = ui_pop_pref_height();}break; } return result; } internal UI_Size ui_set_next_pref_size(Axis2 axis, UI_Size v) { return (axis == Axis2_X ? ui_set_next_pref_width : ui_set_next_pref_height)(v); } internal void ui_push_corner_radius(F32 v) { ui_push_corner_radius_00(v); ui_push_corner_radius_01(v); ui_push_corner_radius_10(v); ui_push_corner_radius_11(v); } internal void ui_pop_corner_radius(void) { ui_pop_corner_radius_00(); ui_pop_corner_radius_01(); ui_pop_corner_radius_10(); ui_pop_corner_radius_11(); } internal void ui_push_tagf(char *fmt, ...) { Temp scratch = scratch_begin(0, 0); va_list args; va_start(args, fmt); String8 string = push_str8fv(scratch.arena, fmt, args); ui_push_tag(string); va_end(args); scratch_end(scratch); } internal F32 ui_top_px_height(void) { F32 result = ui_top_font_size(); for(UI_PrefHeightNode *n = ui_state->pref_height_stack.top; n != 0; n = n->next) { if(n->v.kind == UI_SizeKind_Pixels) { result = n->v.value; break; } } return result; } //////////////////////////////// //~ rjf: Generated Code #include "generated/ui.meta.c" ================================================ FILE: src/ui/ui_core.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_H #define UI_H //////////////////////////////// //~ rjf: Icon Info typedef enum UI_IconKind { UI_IconKind_Null, UI_IconKind_RightArrow, UI_IconKind_DownArrow, UI_IconKind_LeftArrow, UI_IconKind_UpArrow, UI_IconKind_RightCaret, UI_IconKind_DownCaret, UI_IconKind_LeftCaret, UI_IconKind_UpCaret, UI_IconKind_CheckHollow, UI_IconKind_CheckFilled, UI_IconKind_COUNT } UI_IconKind; typedef struct UI_IconInfo UI_IconInfo; struct UI_IconInfo { FNT_Tag icon_font; String8 icon_kind_text_map[UI_IconKind_COUNT]; }; //////////////////////////////// //~ rjf: Mouse Button Kinds typedef enum UI_MouseButtonKind { UI_MouseButtonKind_Left, UI_MouseButtonKind_Middle, UI_MouseButtonKind_Right, UI_MouseButtonKind_COUNT } UI_MouseButtonKind; //////////////////////////////// //~ rjf: Codepath Permissions typedef U32 UI_PermissionFlags; enum { UI_PermissionFlag_ClicksLeft = (1<<0), UI_PermissionFlag_ClicksMiddle = (1<<1), UI_PermissionFlag_ClicksRight = (1<<2), UI_PermissionFlag_ScrollX = (1<<3), UI_PermissionFlag_ScrollY = (1<<4), UI_PermissionFlag_KeyboardPrimary = (1<<5), UI_PermissionFlag_KeyboardSecondary = (1<<6), UI_PermissionFlag_Text = (1<<7), //- rjf bundles UI_PermissionFlag_Keyboard = (UI_PermissionFlag_KeyboardPrimary|UI_PermissionFlag_KeyboardSecondary), UI_PermissionFlag_Clicks = (UI_PermissionFlag_ClicksLeft|UI_PermissionFlag_ClicksMiddle|UI_PermissionFlag_ClicksRight), UI_PermissionFlag_All = 0xffffffff, }; //////////////////////////////// //~ rjf: Focus Types typedef enum UI_FocusKind { UI_FocusKind_Null, UI_FocusKind_Off, UI_FocusKind_On, UI_FocusKind_Root, UI_FocusKind_COUNT } UI_FocusKind; //////////////////////////////// //~ rjf: Events // TODO(rjf): clean all this up typedef enum UI_EventKind { UI_EventKind_Null, UI_EventKind_Press, UI_EventKind_Release, UI_EventKind_Text, UI_EventKind_Navigate, UI_EventKind_Edit, UI_EventKind_MouseMove, UI_EventKind_Scroll, UI_EventKind_FileDrop, UI_EventKind_COUNT } UI_EventKind; typedef enum UI_EventActionSlot { UI_EventActionSlot_Null, UI_EventActionSlot_Accept, UI_EventActionSlot_Cancel, UI_EventActionSlot_Edit, UI_EventActionSlot_COUNT } UI_EventActionSlot; typedef U32 UI_EventFlags; enum { UI_EventFlag_KeepMark = (1<<0), UI_EventFlag_Delete = (1<<1), UI_EventFlag_Copy = (1<<2), UI_EventFlag_Paste = (1<<3), UI_EventFlag_ZeroDeltaOnSelect = (1<<4), UI_EventFlag_PickSelectSide = (1<<5), UI_EventFlag_CapAtLine = (1<<6), UI_EventFlag_ExplicitDirectional = (1<<7), UI_EventFlag_Reorder = (1<<8), UI_EventFlag_Secondary = (1<<9), }; typedef enum UI_EventDeltaUnit { UI_EventDeltaUnit_Null, UI_EventDeltaUnit_Char, UI_EventDeltaUnit_Word, UI_EventDeltaUnit_Line, UI_EventDeltaUnit_Page, UI_EventDeltaUnit_Whole, UI_EventDeltaUnit_COUNT } UI_EventDeltaUnit; typedef struct UI_Event UI_Event; struct UI_Event { UI_EventKind kind; UI_EventActionSlot slot; UI_EventFlags flags; UI_EventDeltaUnit delta_unit; OS_Key key; OS_Modifiers modifiers; String8 string; String8List paths; Vec2F32 pos; Vec2F32 delta_2f32; Vec2S32 delta_2s32; U64 timestamp_us; }; typedef struct UI_EventNode UI_EventNode; struct UI_EventNode { UI_EventNode *next; UI_EventNode *prev; UI_Event v; }; typedef struct UI_EventList UI_EventList; struct UI_EventList { UI_EventNode *first; UI_EventNode *last; U64 count; }; //////////////////////////////// //~ rjf: Textual Operations typedef U32 UI_TxtOpFlags; enum { UI_TxtOpFlag_Invalid = (1<<0), UI_TxtOpFlag_Copy = (1<<1), }; typedef struct UI_TxtOp UI_TxtOp; struct UI_TxtOp { UI_TxtOpFlags flags; String8 replace; String8 copy; TxtRng range; TxtPt cursor; TxtPt mark; }; //////////////////////////////// //~ rjf: Keys typedef struct UI_Key UI_Key; struct UI_Key { U64 u64[1]; }; //////////////////////////////// //~ rjf: Sizes typedef enum UI_SizeKind { UI_SizeKind_Null, UI_SizeKind_Pixels, // size is computed via a preferred pixel value UI_SizeKind_TextContent, // size is computed via the dimensions of box's rendered string UI_SizeKind_ParentPct, // size is computed via a well-determined parent or grandparent size UI_SizeKind_ChildrenSum, // size is computed via summing well-determined sizes of children } UI_SizeKind; typedef struct UI_Size UI_Size; struct UI_Size { UI_SizeKind kind; F32 value; F32 strictness; }; //////////////////////////////// //~ rjf: Themes typedef struct UI_ThemePattern UI_ThemePattern; struct UI_ThemePattern { String8Array tags; Vec4F32 linear; }; typedef struct UI_Theme UI_Theme; struct UI_Theme { UI_ThemePattern *patterns; U64 patterns_count; }; //////////////////////////////// //~ rjf: Animation Info typedef struct UI_AnimationInfo UI_AnimationInfo; struct UI_AnimationInfo { F32 hot_animation_rate; F32 active_animation_rate; F32 focus_animation_rate; F32 tooltip_animation_rate; F32 menu_animation_rate; F32 scroll_animation_rate; }; //////////////////////////////// //~ rjf: Scroll Positions typedef struct UI_ScrollPt UI_ScrollPt; struct UI_ScrollPt { S64 idx; F32 off; }; typedef union UI_ScrollPt2 UI_ScrollPt2; union UI_ScrollPt2 { UI_ScrollPt v[2]; struct { UI_ScrollPt x; UI_ScrollPt y; }; }; //////////////////////////////// //~ rjf: Box Types typedef enum UI_TextAlign { UI_TextAlign_Left, UI_TextAlign_Center, UI_TextAlign_Right, UI_TextAlign_COUNT } UI_TextAlign; struct UI_Box; #define UI_BOX_CUSTOM_DRAW(name) void name(struct UI_Box *box, void *user_data) typedef UI_BOX_CUSTOM_DRAW(UI_BoxCustomDrawFunctionType); typedef U64 UI_BoxFlags; //{ //- rjf: interaction # define UI_BoxFlag_MouseClickable (UI_BoxFlags)(1ull<<0) # define UI_BoxFlag_KeyboardClickable (UI_BoxFlags)(1ull<<1) # define UI_BoxFlag_DropSite (UI_BoxFlags)(1ull<<2) # define UI_BoxFlag_ClickToFocus (UI_BoxFlags)(1ull<<3) # define UI_BoxFlag_Scroll (UI_BoxFlags)(1ull<<4) # define UI_BoxFlag_ViewScrollX (UI_BoxFlags)(1ull<<5) # define UI_BoxFlag_ViewScrollY (UI_BoxFlags)(1ull<<6) # define UI_BoxFlag_ViewClampX (UI_BoxFlags)(1ull<<7) # define UI_BoxFlag_ViewClampY (UI_BoxFlags)(1ull<<8) # define UI_BoxFlag_FocusHot (UI_BoxFlags)(1ull<<9) # define UI_BoxFlag_FocusActive (UI_BoxFlags)(1ull<<10) # define UI_BoxFlag_FocusHotDisabled (UI_BoxFlags)(1ull<<11) # define UI_BoxFlag_FocusActiveDisabled (UI_BoxFlags)(1ull<<12) # define UI_BoxFlag_DefaultFocusNavX (UI_BoxFlags)(1ull<<13) # define UI_BoxFlag_DefaultFocusNavY (UI_BoxFlags)(1ull<<14) # define UI_BoxFlag_DefaultFocusEdit (UI_BoxFlags)(1ull<<15) # define UI_BoxFlag_FocusNavSkip (UI_BoxFlags)(1ull<<16) # define UI_BoxFlag_DisableTruncatedHover (UI_BoxFlags)(1ull<<17) # define UI_BoxFlag_Disabled (UI_BoxFlags)(1ull<<18) //- rjf: layout # define UI_BoxFlag_FloatingX (UI_BoxFlags)(1ull<<19) # define UI_BoxFlag_FloatingY (UI_BoxFlags)(1ull<<20) # define UI_BoxFlag_FixedWidth (UI_BoxFlags)(1ull<<21) # define UI_BoxFlag_FixedHeight (UI_BoxFlags)(1ull<<22) # define UI_BoxFlag_AllowOverflowX (UI_BoxFlags)(1ull<<23) # define UI_BoxFlag_AllowOverflowY (UI_BoxFlags)(1ull<<24) # define UI_BoxFlag_SkipViewOffX (UI_BoxFlags)(1ull<<25) # define UI_BoxFlag_SkipViewOffY (UI_BoxFlags)(1ull<<26) //- rjf: appearance / animation # define UI_BoxFlag_DrawDropShadow (UI_BoxFlags)(1ull<<27) # define UI_BoxFlag_DrawBackgroundBlur (UI_BoxFlags)(1ull<<28) # define UI_BoxFlag_DrawBackground (UI_BoxFlags)(1ull<<29) # define UI_BoxFlag_DrawBorder (UI_BoxFlags)(1ull<<30) # define UI_BoxFlag_DrawSideTop (UI_BoxFlags)(1ull<<31) # define UI_BoxFlag_DrawSideBottom (UI_BoxFlags)(1ull<<32) # define UI_BoxFlag_DrawSideLeft (UI_BoxFlags)(1ull<<33) # define UI_BoxFlag_DrawSideRight (UI_BoxFlags)(1ull<<34) # define UI_BoxFlag_DrawText (UI_BoxFlags)(1ull<<35) # define UI_BoxFlag_DrawTextFastpathCodepoint (UI_BoxFlags)(1ull<<36) # define UI_BoxFlag_DrawTextWeak (UI_BoxFlags)(1ull<<37) # define UI_BoxFlag_DrawHotEffects (UI_BoxFlags)(1ull<<38) # define UI_BoxFlag_DrawActiveEffects (UI_BoxFlags)(1ull<<39) # define UI_BoxFlag_DrawOverlay (UI_BoxFlags)(1ull<<40) # define UI_BoxFlag_DrawBucket (UI_BoxFlags)(1ull<<41) # define UI_BoxFlag_Clip (UI_BoxFlags)(1ull<<42) # define UI_BoxFlag_AnimatePosX (UI_BoxFlags)(1ull<<43) # define UI_BoxFlag_AnimatePosY (UI_BoxFlags)(1ull<<44) # define UI_BoxFlag_DisableTextTrunc (UI_BoxFlags)(1ull<<45) # define UI_BoxFlag_DisableIDString (UI_BoxFlags)(1ull<<46) # define UI_BoxFlag_DisableFocusBorder (UI_BoxFlags)(1ull<<47) # define UI_BoxFlag_DisableFocusOverlay (UI_BoxFlags)(1ull<<48) # define UI_BoxFlag_HasDisplayString (UI_BoxFlags)(1ull<<49) # define UI_BoxFlag_HasFuzzyMatchRanges (UI_BoxFlags)(1ull<<50) # define UI_BoxFlag_RoundChildrenByParent (UI_BoxFlags)(1ull<<51) # define UI_BoxFlag_SquishAnchored (UI_BoxFlags)(1ull<<52) //- rjf: debug # define UI_BoxFlag_Debug (UI_BoxFlags)(1ull<<53) //- rjf: bundles # define UI_BoxFlag_Clickable (UI_BoxFlag_MouseClickable|UI_BoxFlag_KeyboardClickable) # define UI_BoxFlag_DefaultFocusNav (UI_BoxFlag_DefaultFocusNavX|UI_BoxFlag_DefaultFocusNavY|UI_BoxFlag_DefaultFocusEdit) # define UI_BoxFlag_Floating (UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY) # define UI_BoxFlag_FixedSize (UI_BoxFlag_FixedWidth|UI_BoxFlag_FixedHeight) # define UI_BoxFlag_AllowOverflow (UI_BoxFlag_AllowOverflowX|UI_BoxFlag_AllowOverflowY) # define UI_BoxFlag_AnimatePos (UI_BoxFlag_AnimatePosX|UI_BoxFlag_AnimatePosY) # define UI_BoxFlag_ViewScroll (UI_BoxFlag_ViewScrollX|UI_BoxFlag_ViewScrollY) # define UI_BoxFlag_ViewClamp (UI_BoxFlag_ViewClampX|UI_BoxFlag_ViewClampY) # define UI_BoxFlag_DisableFocusEffects (UI_BoxFlag_DisableFocusBorder|UI_BoxFlag_DisableFocusOverlay) //} typedef struct UI_Box UI_Box; struct UI_Box { //- rjf: persistent links UI_Box *hash_next; UI_Box *hash_prev; //- rjf: per-build links/data UI_Box *first; UI_Box *last; UI_Box *next; UI_Box *prev; UI_Box *parent; U64 child_count; //- rjf: per-build equipment UI_Key key; UI_BoxFlags flags; UI_Key tags_key; String8 string; UI_TextAlign text_align; Vec2F32 fixed_position; Vec2F32 fixed_size; Vec2F32 min_size; UI_Size pref_size[Axis2_COUNT]; Axis2 child_layout_axis; OS_Cursor hover_cursor; U32 fastpath_codepoint; UI_Key group_key; DR_Bucket *draw_bucket; UI_BoxCustomDrawFunctionType *custom_draw; void *custom_draw_user_data; Vec4F32 background_color; Vec4F32 text_color; Vec4F32 border_color; FNT_Tag font; F32 font_size; F32 tab_size; FNT_RasterFlags text_raster_flags; F32 corner_radii[Corner_COUNT]; F32 blur_size; F32 transparency; F32 squish; F32 text_padding; //- rjf: per-build artifacts DR_FStrList display_fstrs; DR_FRunList display_fruns; Rng2F32 rect; Vec2F32 fixed_position_animated; Vec2F32 position_delta; FuzzyMatchRangeList fuzzy_match_ranges; //- rjf: persistent data U64 first_touched_build_index; U64 last_touched_build_index; U64 first_disabled_build_index; F32 hot_t; F32 active_t; F32 disabled_t; F32 focus_hot_t; F32 focus_active_t; F32 focus_active_disabled_t; Vec2F32 view_off; Vec2F32 view_off_target; Vec2F32 view_bounds; UI_Key default_nav_focus_hot_key; UI_Key default_nav_focus_active_key; UI_Key default_nav_focus_next_hot_key; UI_Key default_nav_focus_next_active_key; }; typedef struct UI_BoxRec UI_BoxRec; struct UI_BoxRec { UI_Box *next; S32 push_count; S32 pop_count; }; typedef struct UI_BoxNode UI_BoxNode; struct UI_BoxNode { UI_BoxNode *next; UI_Box *box; }; typedef struct UI_BoxList UI_BoxList; struct UI_BoxList { UI_BoxNode *first; UI_BoxNode *last; U64 count; }; typedef U32 UI_SignalFlags; enum { // rjf: mouse press -> box was pressed while hovering UI_SignalFlag_LeftPressed = (1<<0), UI_SignalFlag_MiddlePressed = (1<<1), UI_SignalFlag_RightPressed = (1<<2), // rjf: dragging -> box was previously pressed, user is still holding button UI_SignalFlag_LeftDragging = (1<<3), UI_SignalFlag_MiddleDragging = (1<<4), UI_SignalFlag_RightDragging = (1<<5), // rjf: double-dragging -> box was previously double-clicked, user is still holding button UI_SignalFlag_LeftDoubleDragging = (1<<6), UI_SignalFlag_MiddleDoubleDragging= (1<<7), UI_SignalFlag_RightDoubleDragging = (1<<8), // rjf: triple-dragging -> box was previously triple-clicked, user is still holding button UI_SignalFlag_LeftTripleDragging = (1<<9), UI_SignalFlag_MiddleTripleDragging= (1<<10), UI_SignalFlag_RightTripleDragging = (1<<11), // rjf: released -> box was previously pressed & user released, in or out of bounds UI_SignalFlag_LeftReleased = (1<<12), UI_SignalFlag_MiddleReleased = (1<<13), UI_SignalFlag_RightReleased = (1<<14), // rjf: clicked -> box was previously pressed & user released, in bounds UI_SignalFlag_LeftClicked = (1<<15), UI_SignalFlag_MiddleClicked = (1<<16), UI_SignalFlag_RightClicked = (1<<17), // rjf: double clicked -> box was previously clicked, pressed again UI_SignalFlag_LeftDoubleClicked = (1<<18), UI_SignalFlag_MiddleDoubleClicked = (1<<19), UI_SignalFlag_RightDoubleClicked = (1<<20), // rjf: triple clicked -> box was previously clicked twice, pressed again UI_SignalFlag_LeftTripleClicked = (1<<21), UI_SignalFlag_MiddleTripleClicked = (1<<22), UI_SignalFlag_RightTripleClicked = (1<<23), // rjf: keyboard pressed -> box had focus, user activated via their keyboard UI_SignalFlag_KeyboardPressed = (1<<24), // rjf: passive mouse info UI_SignalFlag_Hovering = (1<<25), // hovering specifically this box UI_SignalFlag_MouseOver = (1<<26), // mouse is over, but may be occluded // rjf: committing state changes via user interaction UI_SignalFlag_Commit = (1<<27), // rjf: high-level combos UI_SignalFlag_Pressed = UI_SignalFlag_LeftPressed|UI_SignalFlag_KeyboardPressed, UI_SignalFlag_Released = UI_SignalFlag_LeftReleased, UI_SignalFlag_Clicked = UI_SignalFlag_LeftClicked|UI_SignalFlag_KeyboardPressed, UI_SignalFlag_DoubleClicked = UI_SignalFlag_LeftDoubleClicked, UI_SignalFlag_TripleClicked = UI_SignalFlag_LeftTripleClicked, UI_SignalFlag_Dragging = UI_SignalFlag_LeftDragging, }; typedef struct UI_Signal UI_Signal; struct UI_Signal { UI_Box *box; OS_Modifiers event_flags; Vec2S16 scroll; UI_SignalFlags f; }; #define ui_pressed(s) !!((s).f&UI_SignalFlag_Pressed) #define ui_clicked(s) !!((s).f&UI_SignalFlag_Clicked) #define ui_released(s) !!((s).f&UI_SignalFlag_Released) #define ui_double_clicked(s) !!((s).f&UI_SignalFlag_DoubleClicked) #define ui_triple_clicked(s) !!((s).f&UI_SignalFlag_TripleClicked) #define ui_middle_clicked(s) !!((s).f&UI_SignalFlag_MiddleClicked) #define ui_right_clicked(s) !!((s).f&UI_SignalFlag_RightClicked) #define ui_dragging(s) !!((s).f&UI_SignalFlag_Dragging) #define ui_hovering(s) !!((s).f&UI_SignalFlag_Hovering) #define ui_mouse_over(s) !!((s).f&UI_SignalFlag_MouseOver) #define ui_committed(s) !!((s).f&UI_SignalFlag_Commit) typedef struct UI_Nav UI_Nav; struct UI_Nav { B32 moved; Vec2S64 new_p; }; //////////////////////////////// //~ rjf: Animation State Types typedef struct UI_AnimParams UI_AnimParams; struct UI_AnimParams { F32 initial; F32 target; F32 rate; F32 epsilon; B32 reset; }; typedef struct UI_AnimNode UI_AnimNode; struct UI_AnimNode { UI_AnimNode *slot_next; UI_AnimNode *slot_prev; UI_AnimNode *lru_next; UI_AnimNode *lru_prev; U64 first_touched_build_index; U64 last_touched_build_index; UI_Key key; UI_AnimParams params; F32 current; }; typedef struct UI_AnimSlot UI_AnimSlot; struct UI_AnimSlot { UI_AnimNode *first; UI_AnimNode *last; }; //////////////////////////////// //~ rjf: Generated Code #include "generated/ui.meta.h" //////////////////////////////// //~ rjf: State Types //- rjf: cache for mapping 64-bit key -> array of tags typedef struct UI_TagsCacheNode UI_TagsCacheNode; struct UI_TagsCacheNode { UI_TagsCacheNode *next; UI_Key key; String8Array tags; }; typedef struct UI_TagsCacheSlot UI_TagsCacheSlot; struct UI_TagsCacheSlot { UI_TagsCacheNode *first; UI_TagsCacheNode *last; }; typedef struct UI_TagsKeyStackNode UI_TagsKeyStackNode; struct UI_TagsKeyStackNode { UI_TagsKeyStackNode *next; UI_Key key; }; //- rjf: cache for mapping 64-bit key -> theme pattern typedef struct UI_ThemePatternCacheNode UI_ThemePatternCacheNode; struct UI_ThemePatternCacheNode { UI_ThemePatternCacheNode *slot_next; UI_ThemePatternCacheNode *slot_prev; UI_ThemePatternCacheNode *lru_next; UI_ThemePatternCacheNode *lru_prev; U64 last_build_index_accessed; UI_Key key; Vec4F32 target_rgba; Vec4F32 current_rgba; }; typedef struct UI_ThemePatternCacheSlot UI_ThemePatternCacheSlot; struct UI_ThemePatternCacheSlot { UI_ThemePatternCacheNode *first; UI_ThemePatternCacheNode *last; }; //- rjf: cache for mapping 64-bit key -> box typedef struct UI_BoxHashSlot UI_BoxHashSlot; struct UI_BoxHashSlot { UI_Box *hash_first; UI_Box *hash_last; }; //- rjf: main state bundle typedef struct UI_State UI_State; struct UI_State { //- rjf: main arena Arena *arena; //- rjf: fixed keys UI_Key external_key; //- rjf: build arenas Arena *build_arenas[2]; U64 build_index; //- rjf: box cache UI_Box *first_free_box; U64 box_table_size; UI_BoxHashSlot *box_table; //- rjf: anim cache UI_AnimNode *free_anim_node; UI_AnimNode *lru_anim_node; UI_AnimNode *mru_anim_node; U64 anim_slots_count; UI_AnimSlot *anim_slots; //- rjf: build state machine state B32 is_in_open_ctx_menu; String8 autocomplete_string; B32 tooltip_can_overflow_window; UI_Key tooltip_anchor_key; String8Array current_gen_tags; U64 current_gen_tags_gen; UI_TagsKeyStackNode *tags_key_stack_top; UI_TagsKeyStackNode *tags_key_stack_free; U64 tags_cache_slots_count; UI_TagsCacheSlot *tags_cache_slots; //- rjf: theme pattern cache U64 theme_pattern_cache_slots_count; UI_ThemePatternCacheSlot *theme_pattern_cache_slots; UI_ThemePatternCacheNode *theme_pattern_cache_node_free; UI_ThemePatternCacheNode *lru_theme_pattern_cache_node; UI_ThemePatternCacheNode *mru_theme_pattern_cache_node; //- rjf: build phase output UI_Box *root; UI_Box *tooltip_root; UI_Box *ctx_menu_root; UI_Key default_nav_root_key; U64 build_box_count; U64 last_build_box_count; B32 ctx_menu_touched_this_frame; B32 is_animating; //- rjf: build parameters UI_IconInfo icon_info; UI_Theme *theme; UI_AnimationInfo animation_info; OS_Handle window; UI_EventList *events; Vec2F32 mouse; F32 animation_dt; F32 default_animation_rate; //- rjf: user interaction state UI_Key hot_box_key; UI_Key active_box_key[UI_MouseButtonKind_COUNT]; UI_Key drop_hot_box_key; UI_Key clipboard_copy_key; U64 press_timestamp_history_us[UI_MouseButtonKind_COUNT][3]; UI_Key press_key_history[UI_MouseButtonKind_COUNT][3]; Vec2F32 press_pos_history[UI_MouseButtonKind_COUNT][3]; Vec2F32 drag_start_mouse; Arena *drag_state_arena; String8 drag_state_data; Arena *string_hover_arena; String8 string_hover_string; F32 string_hover_size; DR_FStrList string_hover_fstrs; U64 string_hover_begin_us; U64 string_hover_build_index; U64 last_time_mousemoved_us; //- rjf: tooltip state F32 tooltip_open_t; B32 tooltip_open; //- rjf: context menu state UI_Key ctx_menu_anchor_key; UI_Key next_ctx_menu_anchor_key; Vec2F32 ctx_menu_anchor_box_last_pos; Vec2F32 ctx_menu_anchor_off; B32 ctx_menu_open; B32 next_ctx_menu_open; F32 ctx_menu_open_t; UI_Key ctx_menu_key; B32 ctx_menu_changed; //- rjf: build phase stacks UI_DeclStackNils; UI_DeclStacks; }; //////////////////////////////// //~ rjf: Basic Type Functions internal String8 ui_hash_part_from_key_string(String8 string); internal String8 ui_display_part_from_key_string(String8 string); internal UI_Key ui_key_zero(void); internal UI_Key ui_key_make(U64 v); internal UI_Key ui_key_from_string(UI_Key seed_key, String8 string); internal UI_Key ui_key_from_stringf(UI_Key seed_key, char *fmt, ...); internal B32 ui_key_match(UI_Key a, UI_Key b); //////////////////////////////// //~ rjf: Event Type Functions internal UI_EventNode *ui_event_list_push(Arena *arena, UI_EventList *list, UI_Event *v); internal void ui_eat_event_node(UI_EventList *list, UI_EventNode *node); //////////////////////////////// //~ rjf: Text Operation Functions internal B32 ui_char_is_scan_boundary(U8 c); internal S64 ui_scanned_column_from_column(String8 string, S64 start_column, Side side); internal UI_TxtOp ui_single_line_txt_op_from_event(Arena *arena, UI_Event *event, String8 string, TxtPt cursor, TxtPt mark); internal String8 ui_push_string_replace_range(Arena *arena, String8 string, Rng1S64 range, String8 replace); //////////////////////////////// //~ rjf: Size Type Functions internal UI_Size ui_size(UI_SizeKind kind, F32 value, F32 strictness); #define ui_px(value, strictness) ui_size(UI_SizeKind_Pixels, value, strictness) #define ui_em(value, strictness) ui_size(UI_SizeKind_Pixels, (value) * ui_top_font_size(), strictness) #define ui_text_dim(padding, strictness) ui_size(UI_SizeKind_TextContent, padding, strictness) #define ui_pct(value, strictness) ui_size(UI_SizeKind_ParentPct, value, strictness) #define ui_children_sum(strictness) ui_size(UI_SizeKind_ChildrenSum, 0.f, strictness) //////////////////////////////// //~ rjf: Scroll Point Type Functions internal UI_ScrollPt ui_scroll_pt(S64 idx, F32 off); internal void ui_scroll_pt_target_idx(UI_ScrollPt *v, S64 idx); internal void ui_scroll_pt_clamp_idx(UI_ScrollPt *v, Rng1S64 range); //////////////////////////////// //~ rjf: Box Type Functions read_only global UI_Box ui_nil_box = { &ui_nil_box, &ui_nil_box, &ui_nil_box, &ui_nil_box, &ui_nil_box, &ui_nil_box, &ui_nil_box, }; internal B32 ui_box_is_nil(UI_Box *box); internal UI_BoxRec ui_box_rec_df(UI_Box *box, UI_Box *root, U64 sib_member_off, U64 child_member_off); #define ui_box_rec_df_pre(box, root) ui_box_rec_df(box, root, OffsetOf(UI_Box, next), OffsetOf(UI_Box, first)) #define ui_box_rec_df_post(box, root) ui_box_rec_df(box, root, OffsetOf(UI_Box, prev), OffsetOf(UI_Box, last)) internal void ui_box_list_push(Arena *arena, UI_BoxList *list, UI_Box *box); //////////////////////////////// //~ rjf: State Allocating / Selection internal UI_State *ui_state_alloc(void); internal void ui_state_release(UI_State *state); internal UI_Box * ui_root_from_state(UI_State *state); internal B32 ui_animating_from_state(UI_State *state); internal void ui_select_state(UI_State *state); internal UI_State *ui_get_selected_state(void); //////////////////////////////// //~ rjf: Implicit State Accessors/Mutators //- rjf: per-frame info internal Arena * ui_build_arena(void); internal OS_Handle ui_window(void); internal Vec2F32 ui_mouse(void); internal FNT_Tag ui_icon_font(void); internal String8 ui_icon_string_from_kind(UI_IconKind icon_kind); internal F32 ui_dt(void); //- rjf: event pumping internal B32 ui_next_event(UI_Event **ev); internal void ui_eat_event(UI_Event *ev); //- rjf: event consumption helpers internal B32 ui_key_press(OS_Modifiers mods, OS_Key key); internal B32 ui_key_release(OS_Modifiers mods, OS_Key key); internal B32 ui_text(U32 character); internal B32 ui_slot_press(UI_EventActionSlot slot); //- rjf: autocomplete info internal void ui_set_autocomplete_string(String8 string); internal String8 ui_autocomplete_string(void); internal String8 ui_autocomplete(void); //- rjf: drag data internal Vec2F32 ui_drag_start_mouse(void); internal Vec2F32 ui_drag_delta(void); internal void ui_store_drag_data(String8 string); internal String8 ui_get_drag_data(U64 min_required_size); #define ui_store_drag_struct(ptr) ui_store_drag_data(str8_struct(ptr)) #define ui_get_drag_struct(type) ((type *)ui_get_drag_data(sizeof(type)).str) //- rjf: hovered string info internal B32 ui_string_hover_active(void); internal DR_FStrList ui_string_hover_fstrs(Arena *arena); //- rjf: interaction keys internal UI_Key ui_hot_key(void); internal UI_Key ui_active_key(UI_MouseButtonKind button_kind); internal UI_Key ui_drop_hot_key(void); //- rjf: controls over interaction internal void ui_kill_action(void); //- rjf: box cache lookup internal UI_Box * ui_box_from_key(UI_Key key); //////////////////////////////// //~ rjf: Top-Level Building API internal void ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, UI_Theme *theme, UI_AnimationInfo *animation_info, F32 real_dt, F32 animation_dt); internal void ui_end_build(void); internal void ui_calc_sizes_standalone__in_place(UI_Box *root, Axis2 axis); internal void ui_calc_sizes_upwards_dependent__in_place(UI_Box *root, Axis2 axis); internal void ui_calc_sizes_downwards_dependent__in_place(UI_Box *root, Axis2 axis); internal void ui_layout_enforce_constraints__in_place(UI_Box *root, Axis2 axis); internal void ui_layout_position__in_place(UI_Box *root, Axis2 axis); internal void ui_layout_root(UI_Box *root, Axis2 axis); //////////////////////////////// //~ rjf: Box Tree Building API //- rjf: spacers internal UI_Signal ui_spacer(UI_Size size); //- rjf: tooltips internal void ui_tooltip_begin_base(void); internal void ui_tooltip_end_base(void); internal void ui_tooltip_begin(void); internal void ui_tooltip_end(void); //- rjf: context menus internal void ui_ctx_menu_open(UI_Key key, UI_Key anchor_box_key, Vec2F32 anchor_off); internal void ui_ctx_menu_close(void); internal B32 ui_begin_ctx_menu(UI_Key key); internal void ui_end_ctx_menu(void); internal B32 ui_ctx_menu_is_open(UI_Key key); internal B32 ui_any_ctx_menu_is_open(void); //- rjf: focus tree coloring internal B32 ui_is_focus_hot(void); internal B32 ui_is_focus_active(void); //- rjf: implicit auto-managed tree-based focus state internal B32 ui_is_key_auto_focus_active(UI_Key key); internal B32 ui_is_key_auto_focus_hot(UI_Key key); internal void ui_set_auto_focus_active_key(UI_Key key); internal void ui_set_auto_focus_hot_key(UI_Key key); //- rjf: current style tags key internal UI_Key ui_top_tags_key(void); //- rjf: theme color lookups internal Vec4F32 ui_color_from_name(String8 name); internal Vec4F32 ui_color_from_tags_key_extras(UI_Key key, String8Array extras); internal Vec4F32 ui_color_from_tags_key_name(UI_Key key, String8 name); //- rjf: box node construction internal UI_Box * ui_build_box_from_key(UI_BoxFlags flags, UI_Key key); internal UI_Key ui_active_seed_key(void); internal UI_Box * ui_build_box_from_string(UI_BoxFlags flags, String8 string); internal UI_Box * ui_build_box_from_stringf(UI_BoxFlags flags, char *fmt, ...); //- rjf: box node equipment internal inline void ui_box_equip_display_string(UI_Box *box, String8 string); internal inline void ui_box_equip_display_fstrs(UI_Box *box, DR_FStrList *strings); internal inline void ui_box_equip_fuzzy_match_ranges(UI_Box *box, FuzzyMatchRangeList *matches); internal inline void ui_box_equip_draw_bucket(UI_Box *box, DR_Bucket *bucket); internal inline void ui_box_equip_custom_draw(UI_Box *box, UI_BoxCustomDrawFunctionType *custom_draw, void *user_data); //- rjf: box accessors / queries internal String8 ui_box_display_string(UI_Box *box); internal Vec2F32 ui_box_text_position(UI_Box *box); internal U64 ui_box_char_pos_from_xy(UI_Box *box, Vec2F32 xy); //////////////////////////////// //~ rjf: User Interaction internal UI_Signal ui_signal_from_box(UI_Box *box); //////////////////////////////// //~ rjf: Animation Cache Interaction API read_only global UI_AnimNode ui_nil_anim_node = { &ui_nil_anim_node, &ui_nil_anim_node, }; internal F32 ui_anim_(UI_Key key, UI_AnimParams *params); #define ui_anim(key, target_val, ...) ui_anim_((key), &(UI_AnimParams){.target = (target_val), .rate = (ui_state->default_animation_rate), __VA_ARGS__}) //////////////////////////////// //~ rjf: Stacks internal void ui__push_tags_key_from_appended_string(String8 string); internal void ui__pop_tags_key(void); //- rjf: base internal UI_Box * ui_top_parent(void); internal Axis2 ui_top_child_layout_axis(void); internal F32 ui_top_fixed_x(void); internal F32 ui_top_fixed_y(void); internal F32 ui_top_fixed_width(void); internal F32 ui_top_fixed_height(void); internal UI_Size ui_top_pref_width(void); internal UI_Size ui_top_pref_height(void); internal F32 ui_top_min_width(void); internal F32 ui_top_min_height(void); internal UI_PermissionFlags ui_top_permission_flags(void); internal UI_BoxFlags ui_top_flags(void); internal UI_BoxFlags ui_top_omit_flags(void); internal UI_FocusKind ui_top_focus_hot(void); internal UI_FocusKind ui_top_focus_active(void); internal U32 ui_top_fastpath_codepoint(void); internal UI_Key ui_top_group_key(void); internal F32 ui_top_transparency(void); internal String8 ui_top_tag(void); internal Vec4F32 ui_top_background_color(void); internal Vec4F32 ui_top_text_color(void); internal Vec4F32 ui_top_border_color(void); internal F32 ui_top_squish(void); internal OS_Cursor ui_top_hover_cursor(void); internal FNT_Tag ui_top_font(void); internal F32 ui_top_font_size(void); internal FNT_RasterFlags ui_top_text_raster_flags(void); internal F32 ui_top_tab_size(void); internal F32 ui_top_corner_radius_00(void); internal F32 ui_top_corner_radius_01(void); internal F32 ui_top_corner_radius_10(void); internal F32 ui_top_corner_radius_11(void); internal F32 ui_top_blur_size(void); internal F32 ui_top_text_padding(void); internal UI_TextAlign ui_top_text_alignment(void); internal UI_Box * ui_bottom_parent(void); internal Axis2 ui_bottom_child_layout_axis(void); internal F32 ui_bottom_fixed_x(void); internal F32 ui_bottom_fixed_y(void); internal F32 ui_bottom_fixed_width(void); internal F32 ui_bottom_fixed_height(void); internal UI_Size ui_bottom_pref_width(void); internal UI_Size ui_bottom_pref_height(void); internal F32 ui_bottom_min_width(void); internal F32 ui_bottom_min_height(void); internal UI_PermissionFlags ui_bottom_permission_flags(void); internal UI_BoxFlags ui_bottom_flags(void); internal UI_BoxFlags ui_bottom_omit_flags(void); internal UI_FocusKind ui_bottom_focus_hot(void); internal UI_FocusKind ui_bottom_focus_active(void); internal U32 ui_bottom_fastpath_codepoint(void); internal UI_Key ui_bottom_group_key(void); internal F32 ui_bottom_transparency(void); internal String8 ui_bottom_tag(void); internal Vec4F32 ui_bottom_background_color(void); internal Vec4F32 ui_bottom_text_color(void); internal Vec4F32 ui_bottom_border_color(void); internal F32 ui_bottom_squish(void); internal OS_Cursor ui_bottom_hover_cursor(void); internal FNT_Tag ui_bottom_font(void); internal F32 ui_bottom_font_size(void); internal FNT_RasterFlags ui_bottom_text_raster_flags(void); internal F32 ui_bottom_tab_size(void); internal F32 ui_bottom_corner_radius_00(void); internal F32 ui_bottom_corner_radius_01(void); internal F32 ui_bottom_corner_radius_10(void); internal F32 ui_bottom_corner_radius_11(void); internal F32 ui_bottom_blur_size(void); internal F32 ui_bottom_text_padding(void); internal UI_TextAlign ui_bottom_text_alignment(void); internal UI_Box * ui_push_parent(UI_Box * v); internal Axis2 ui_push_child_layout_axis(Axis2 v); internal F32 ui_push_fixed_x(F32 v); internal F32 ui_push_fixed_y(F32 v); internal F32 ui_push_fixed_width(F32 v); internal F32 ui_push_fixed_height(F32 v); internal UI_Size ui_push_pref_width(UI_Size v); internal UI_Size ui_push_pref_height(UI_Size v); internal F32 ui_push_min_width(F32 v); internal F32 ui_push_min_height(F32 v); internal UI_PermissionFlags ui_push_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_push_flags(UI_BoxFlags v); internal UI_BoxFlags ui_push_omit_flags(UI_BoxFlags v); internal UI_FocusKind ui_push_focus_hot(UI_FocusKind v); internal UI_FocusKind ui_push_focus_active(UI_FocusKind v); internal U32 ui_push_fastpath_codepoint(U32 v); internal UI_Key ui_push_group_key(UI_Key v); internal F32 ui_push_transparency(F32 v); internal String8 ui_push_tag(String8 v); internal Vec4F32 ui_push_background_color(Vec4F32 v); internal Vec4F32 ui_push_text_color(Vec4F32 v); internal Vec4F32 ui_push_border_color(Vec4F32 v); internal F32 ui_push_squish(F32 v); internal OS_Cursor ui_push_hover_cursor(OS_Cursor v); internal FNT_Tag ui_push_font(FNT_Tag v); internal F32 ui_push_font_size(F32 v); internal FNT_RasterFlags ui_push_text_raster_flags(FNT_RasterFlags v); internal F32 ui_push_tab_size(F32 v); internal F32 ui_push_corner_radius_00(F32 v); internal F32 ui_push_corner_radius_01(F32 v); internal F32 ui_push_corner_radius_10(F32 v); internal F32 ui_push_corner_radius_11(F32 v); internal F32 ui_push_blur_size(F32 v); internal F32 ui_push_text_padding(F32 v); internal UI_TextAlign ui_push_text_alignment(UI_TextAlign v); internal UI_Box * ui_pop_parent(void); internal Axis2 ui_pop_child_layout_axis(void); internal F32 ui_pop_fixed_x(void); internal F32 ui_pop_fixed_y(void); internal F32 ui_pop_fixed_width(void); internal F32 ui_pop_fixed_height(void); internal UI_Size ui_pop_pref_width(void); internal UI_Size ui_pop_pref_height(void); internal F32 ui_pop_min_width(void); internal F32 ui_pop_min_height(void); internal UI_PermissionFlags ui_pop_permission_flags(void); internal UI_BoxFlags ui_pop_flags(void); internal UI_BoxFlags ui_pop_omit_flags(void); internal UI_FocusKind ui_pop_focus_hot(void); internal UI_FocusKind ui_pop_focus_active(void); internal U32 ui_pop_fastpath_codepoint(void); internal UI_Key ui_pop_group_key(void); internal F32 ui_pop_transparency(void); internal String8 ui_pop_tag(void); internal Vec4F32 ui_pop_background_color(void); internal Vec4F32 ui_pop_text_color(void); internal Vec4F32 ui_pop_border_color(void); internal F32 ui_pop_squish(void); internal OS_Cursor ui_pop_hover_cursor(void); internal FNT_Tag ui_pop_font(void); internal F32 ui_pop_font_size(void); internal FNT_RasterFlags ui_pop_text_raster_flags(void); internal F32 ui_pop_tab_size(void); internal F32 ui_pop_corner_radius_00(void); internal F32 ui_pop_corner_radius_01(void); internal F32 ui_pop_corner_radius_10(void); internal F32 ui_pop_corner_radius_11(void); internal F32 ui_pop_blur_size(void); internal F32 ui_pop_text_padding(void); internal UI_TextAlign ui_pop_text_alignment(void); internal UI_Box * ui_set_next_parent(UI_Box * v); internal Axis2 ui_set_next_child_layout_axis(Axis2 v); internal F32 ui_set_next_fixed_x(F32 v); internal F32 ui_set_next_fixed_y(F32 v); internal F32 ui_set_next_fixed_width(F32 v); internal F32 ui_set_next_fixed_height(F32 v); internal UI_Size ui_set_next_pref_width(UI_Size v); internal UI_Size ui_set_next_pref_height(UI_Size v); internal F32 ui_set_next_min_width(F32 v); internal F32 ui_set_next_min_height(F32 v); internal UI_PermissionFlags ui_set_next_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_set_next_flags(UI_BoxFlags v); internal UI_BoxFlags ui_set_next_omit_flags(UI_BoxFlags v); internal UI_FocusKind ui_set_next_focus_hot(UI_FocusKind v); internal UI_FocusKind ui_set_next_focus_active(UI_FocusKind v); internal U32 ui_set_next_fastpath_codepoint(U32 v); internal UI_Key ui_set_next_group_key(UI_Key v); internal F32 ui_set_next_transparency(F32 v); internal String8 ui_set_next_tag(String8 v); internal Vec4F32 ui_set_next_background_color(Vec4F32 v); internal Vec4F32 ui_set_next_text_color(Vec4F32 v); internal Vec4F32 ui_set_next_border_color(Vec4F32 v); internal F32 ui_set_next_squish(F32 v); internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v); internal FNT_Tag ui_set_next_font(FNT_Tag v); internal F32 ui_set_next_font_size(F32 v); internal FNT_RasterFlags ui_set_next_text_raster_flags(FNT_RasterFlags v); internal F32 ui_set_next_tab_size(F32 v); internal F32 ui_set_next_corner_radius_00(F32 v); internal F32 ui_set_next_corner_radius_01(F32 v); internal F32 ui_set_next_corner_radius_10(F32 v); internal F32 ui_set_next_corner_radius_11(F32 v); internal F32 ui_set_next_blur_size(F32 v); internal F32 ui_set_next_text_padding(F32 v); internal UI_TextAlign ui_set_next_text_alignment(UI_TextAlign v); //- rjf: helpers internal Rng2F32 ui_push_rect(Rng2F32 rect); internal Rng2F32 ui_pop_rect(void); internal void ui_set_next_rect(Rng2F32 rect); internal UI_Size ui_push_pref_size(Axis2 axis, UI_Size v); internal UI_Size ui_pop_pref_size(Axis2 axis); internal UI_Size ui_set_next_pref_size(Axis2 axis, UI_Size v); internal void ui_push_corner_radius(F32 v); internal void ui_pop_corner_radius(void); internal void ui_push_tagf(char *fmt, ...); internal F32 ui_top_px_height(void); //////////////////////////////// //~ rjf: Macro Loop Wrappers //- rjf: stacks (base) #define UI_Parent(v) DeferLoop(ui_push_parent(v), ui_pop_parent()) #define UI_ChildLayoutAxis(v) DeferLoop(ui_push_child_layout_axis(v), ui_pop_child_layout_axis()) #define UI_FixedX(v) DeferLoop(ui_push_fixed_x(v), ui_pop_fixed_x()) #define UI_FixedY(v) DeferLoop(ui_push_fixed_y(v), ui_pop_fixed_y()) #define UI_FixedWidth(v) DeferLoop(ui_push_fixed_width(v), ui_pop_fixed_width()) #define UI_FixedHeight(v) DeferLoop(ui_push_fixed_height(v), ui_pop_fixed_height()) #define UI_PrefWidth(v) DeferLoop(ui_push_pref_width(v), ui_pop_pref_width()) #define UI_PrefHeight(v) DeferLoop(ui_push_pref_height(v), ui_pop_pref_height()) #define UI_MinWidth(v) DeferLoop(ui_push_min_width(v), ui_pop_min_width()) #define UI_MinHeight(v) DeferLoop(ui_push_min_height(v), ui_pop_min_height()) #define UI_PermissionFlags(v) DeferLoop(ui_push_permission_flags(v), ui_pop_permission_flags()) #define UI_Flags(v) DeferLoop(ui_push_flags(v), ui_pop_flags()) #define UI_OmitFlags(v) DeferLoop(ui_push_omit_flags(v), ui_pop_omit_flags()) #define UI_FocusHot(v) DeferLoop(ui_push_focus_hot(v), ui_pop_focus_hot()) #define UI_FocusActive(v) DeferLoop(ui_push_focus_active(v), ui_pop_focus_active()) #define UI_FastpathCodepoint(v) DeferLoop(ui_push_fastpath_codepoint(v), ui_pop_fastpath_codepoint()) #define UI_GroupKey(v) DeferLoop(ui_push_group_key(v), ui_pop_group_key()) #define UI_Transparency(v) DeferLoop(ui_push_transparency(v), ui_pop_transparency()) #define UI_Tag(v) DeferLoop(ui_push_tag(v), ui_pop_tag()) #define UI_BackgroundColor(v) DeferLoop(ui_push_background_color(v), ui_pop_background_color()) #define UI_TextColor(v) DeferLoop(ui_push_text_color(v), ui_pop_text_color()) #define UI_Squish(v) DeferLoop(ui_push_squish(v), ui_pop_squish()) #define UI_HoverCursor(v) DeferLoop(ui_push_hover_cursor(v), ui_pop_hover_cursor()) #define UI_Font(v) DeferLoop(ui_push_font(v), ui_pop_font()) #define UI_FontSize(v) DeferLoop(ui_push_font_size(v), ui_pop_font_size()) #define UI_TextRasterFlags(v) DeferLoop(ui_push_text_raster_flags(v), ui_pop_text_raster_flags()) #define UI_TabSize(v) DeferLoop(ui_push_tab_size(v), ui_pop_tab_size()) #define UI_CornerRadius00(v) DeferLoop(ui_push_corner_radius_00(v), ui_pop_corner_radius_00()) #define UI_CornerRadius01(v) DeferLoop(ui_push_corner_radius_01(v), ui_pop_corner_radius_01()) #define UI_CornerRadius10(v) DeferLoop(ui_push_corner_radius_10(v), ui_pop_corner_radius_10()) #define UI_CornerRadius11(v) DeferLoop(ui_push_corner_radius_11(v), ui_pop_corner_radius_11()) #define UI_BlurSize(v) DeferLoop(ui_push_blur_size(v), ui_pop_blur_size()) #define UI_TextPadding(v) DeferLoop(ui_push_text_padding(v), ui_pop_text_padding()) #define UI_TextAlignment(v) DeferLoop(ui_push_text_alignment(v), ui_pop_text_alignment()) //- rjf: stacks (compositions) #define UI_FixedPos(v) DeferLoop((ui_push_fixed_x((v).x), ui_push_fixed_y((v).y)), (ui_pop_fixed_x(), ui_pop_fixed_y())) #define UI_FixedSize(v) DeferLoop((ui_push_fixed_width((v).x), ui_push_fixed_height((v).y)), (ui_pop_fixed_width(), ui_pop_fixed_height())) #define UI_WidthFill UI_PrefWidth(ui_pct(1.f, 0.f)) #define UI_HeightFill UI_PrefHeight(ui_pct(1.f, 0.f)) #define UI_Rect(r) DeferLoop(ui_push_rect(r), ui_pop_rect()) #define UI_PrefSize(axis, v) DeferLoop(ui_push_pref_size((axis), (v)), ui_pop_pref_size(axis)) #define UI_CornerRadius(v) DeferLoop(ui_push_corner_radius(v), ui_pop_corner_radius()) #define UI_Focus(kind) DeferLoop((ui_push_focus_hot(kind), ui_push_focus_active(kind)), (ui_pop_focus_hot(), ui_pop_focus_active())) #define UI_FlagsAdd(v) DeferLoop(ui_push_flags(ui_top_flags()|(v)), ui_pop_flags()) #define UI_TagF(...) DeferLoop(ui_push_tagf(__VA_ARGS__), ui_pop_tag()) //- rjf: tooltip #define UI_TooltipBase DeferLoop(ui_tooltip_begin_base(), ui_tooltip_end_base()) #define UI_Tooltip DeferLoop(ui_tooltip_begin(), ui_tooltip_end()) //- rjf: context menu #define UI_CtxMenu(key) DeferLoopChecked(ui_begin_ctx_menu(key), ui_end_ctx_menu()) //- rjf: debug #define UI_Debug UI_FlagsAdd(UI_BoxFlag_Debug) #endif // UI_H ================================================ FILE: src/ui/ui_inc.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR #define LAYER_COLOR 0xb5438dff #include "ui_core.c" #include "ui_basic_widgets.c" ================================================ FILE: src/ui/ui_inc.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_INC_H #define UI_INC_H #include "ui_core.h" #include "ui_basic_widgets.h" #endif // UI_INC_H ================================================ FILE: src/x64/x64.c ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void x64_cpuid(U32 leaf, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx) { U32 info[4] = {0}; #if COMPILER_MSVC __cpuid(info, leaf); if (eax) { *eax = info[0]; } if (ebx) { *ebx = info[1]; } if (ecx) { *ecx = info[2]; } if (edx) { *edx = info[3]; } #elif COMPILER_CLANG || COMPILER_GCC if (!eax) { eax = &info[0]; } if (!ebx) { ebx = &info[1]; } if (!ecx) { ecx = &info[2]; } if (!edx) { edx = &info[3]; } __get_cpuid(leaf, eax, ebx, ecx, edx); #else # error "cpuid is not defined for this compiler" #endif } internal void x64_cpuid_ex(U32 leaf, U32 sub_leaf, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx) { U32 info[4]; #if COMPILER_MSVC __cpuidex(info, leaf, sub_leaf); if (eax) { *eax = info[0]; } if (ebx) { *ebx = info[1]; } if (ecx) { *ecx = info[2]; } if (edx) { *edx = info[3]; } #elif COMPILER_CLANG || COMPILER_GCC if (!eax) { eax = &info[0]; } if (!ebx) { ebx = &info[1]; } if (!ecx) { ecx = &info[2]; } if (!edx) { edx = &info[3]; } __get_cpuid_count(leaf, sub_leaf, eax, ebx, ecx, edx); #else # error "cpuid_count is not defined for this compiler" #endif } internal B32 x64_is_xsave_supported(void) { U32 ecx = 0; x64_cpuid(1, 0, 0, &ecx, 0); return !!(ecx & (1 << 26)); } internal U32 x64_get_xsave_size(void) { U32 xsave_size = 0; x64_cpuid_ex(0xd, 0, 0, &xsave_size, 0, 0); return xsave_size; } internal U16 x64_xsave_tag_word_from_real_tag_word(U16 ftw) { U16 compact = 0; for EachIndex(fpr, 8) { U32 tag = (ftw >> (fpr * 2)) & 3; if (tag != 3) { compact |= (1 << fpr); } } return compact; } internal U32 x64_xsave_offset_from_feature_flag(U64 xcr0, X64_XStateComponentIdx comp_idx) { U32 offset = 0; if (xcr0 & (1 << comp_idx)) { if(comp_idx == X64_XStateComponentIdx_FP) { offset = 0; } else if(comp_idx == X64_XStateComponentIdx_SSE) { offset = 160; } else { x64_cpuid_ex(0xd, comp_idx, 0, &offset, 0, 0); } } return offset; } internal X64_XSaveLayout x64_get_xsave_layout(U64 xcr0) { X64_XSaveLayout xsave_layout = {0}; xsave_layout.x87_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_FP); xsave_layout.sse_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_SSE); xsave_layout.avx_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_AVX); xsave_layout.bndregs_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_BNDREGS); xsave_layout.bndcfg_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_BNDCSR); xsave_layout.opmask_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_OPMASK); xsave_layout.zmm_h_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_ZMM_H); xsave_layout.zmm_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_ZMM); xsave_layout.pt_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_PT); xsave_layout.pkru_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_PKRU); xsave_layout.pasid_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_PASID); xsave_layout.cet_u_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_CETU); xsave_layout.cet_s_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_CETS); xsave_layout.hdc_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_HDC); xsave_layout.uintr_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_UINTR); xsave_layout.lbr_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_LBR); xsave_layout.hwp_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_HWP); xsave_layout.tile_cfg_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_TILECFG); xsave_layout.tile_data_offset = x64_xsave_offset_from_feature_flag(xcr0, X64_XStateComponentIdx_TILEDATA); return xsave_layout; } internal void x64_set_debug_break(U64 *drs, U64 trap_idx, U64 addr, U64 size, X64_BreakpointType bp_type, X64_DebugBreakType break_type) { // set breakpoint address switch (trap_idx) { case 0: { drs[0] = addr; } break; case 1: { drs[1] = addr; } break; case 2: { drs[2] = addr; } break; case 3: { drs[3] = addr; } break; default: { InvalidPath; } break; } // enable breakpoint drs[7] &= ~(3 << (trap_idx * 2)); switch (bp_type) { case X64_BreakpointType_Null: break; case X64_BreakpointType_Local: { drs[7] |= 1 << (trap_idx * 2); } break; case X64_BreakpointType_Global: { drs[7] |= 2 << (trap_idx * 2); } break; default: { InvalidPath; } break; } // set break access type switch (break_type) { case X64_DebugBreakType_Exec: Assert(size == 0); case X64_DebugBreakType_Null: { drs[7] &= ~((1u << 16) << (trap_idx * 4)); drs[7] &= ~((1u << 17) << (trap_idx * 4)); } break; case X64_DebugBreakType_Write: { drs[7] |= (1u << 16) << (trap_idx * 4); drs[7] &= ~((1u << 17) << (trap_idx * 4)); } break; case X64_DebugBreakType_ReadWriteIO: { drs[7] &= ~((1u << 16) << (trap_idx * 4)); drs[7] |= (1u << 17) << (trap_idx * 4); } break; case X64_DebugBreakType_ReadWriteNoFetch: { drs[7] |= (1u << 16) << (trap_idx * 4); drs[7] |= (1u << 17) << (trap_idx * 4); } break; default: { InvalidPath; } break; } // set breakpoint size switch (size) { case 0: case 1: { drs[7] &= ~((1u << 18) << (trap_idx * 4)); drs[7] &= ~((1u << 19) << (trap_idx * 4)); } break; case 2: { drs[7] |= (1 << 18) << (trap_idx * 4); drs[7] &= ~((1 << 19) << (trap_idx * 4)); } break; case 4: { drs[7] |= (1 << 18) << (trap_idx * 4); drs[7] |= (1 << 19) << (trap_idx * 4); } break; case 8: { drs[7] &= ~((1 << 18) << (trap_idx * 4)); drs[7] |= (1 << 19) << (trap_idx * 4); } break; default: { InvalidPath; } } } ================================================ FILE: src/x64/x64.h ================================================ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef X64_H #define X64_H //////////////////////////////// //~ RFlags typedef U64 X64_RFlags; enum { X64_RFlag_Carry = (1 << 0), X64_RFlag_Parity = (1 << 2), X64_RFlag_AuxCarry = (1 << 4), X64_RFlag_Zero = (1 << 6), X64_RFlag_Sign = (1 << 7), X64_RFlag_Trap = (1 << 8), X64_RFlag_Interrupt = (1 << 9), X64_RFlag_Direction = (1 << 10), X64_RFlag_Overflow = (1 << 11), X64_RFlag_IoPrivilege = (3 << 12), X64_RFlag_NT = (1 << 14), X64_RFlag_MD = (1 << 15), X64_RFlag_RF = (1 << 16), X64_RFlag_VM = (1 << 17), X64_RFlag_AC = (1 << 18), X64_RFlag_VIF = (1 << 19), X64_RFlag_VIP = (1 << 20), X64_RFlag_AES = (1 << 30), X64_RFlag_AI = (1 << 31), }; //////////////////////////////// //~ fxsave/xsave typedef struct AlignType(16) X64_FXSave { U16 fcw; U16 fsw; U16 ftw; U16 fop; union { struct { U64 fip; U64 fdp; } b64; struct { U32 fip; U16 fcs, _pad0; U32 fdp; U16 fds, _pad1; } b32; }; U32 mxcsr; U32 mxcsr_mask; U128 st_space[8]; U128 xmm_space[16]; U8 padding[96]; } X64_FXSave; StaticAssert(sizeof(X64_FXSave) == 512, g_x64_xsave_legacy_size_check); typedef struct X64_XSaveHeader { U64 xstate_bv; U64 xcomp_bv; U8 reserved[48]; } X64_XSaveHeader; StaticAssert(sizeof(X64_XSaveHeader) == 64, g_x64_xsave_header_size_check); typedef struct AlignType(64) X64_XSave { X64_FXSave fxsave; X64_XSaveHeader header; // U8 ext_area[0]; } X64_XSave; StaticAssert(sizeof(X64_XSave) == 576, g_x64_xsave_size_check); typedef U32 X64_XStateComponentIdx; enum { X64_XStateComponentIdx_FP = 0, X64_XStateComponentIdx_SSE = 1, X64_XStateComponentIdx_AVX = 2, X64_XStateComponentIdx_BNDREGS = 3, X64_XStateComponentIdx_BNDCSR = 4, X64_XStateComponentIdx_OPMASK = 5, X64_XStateComponentIdx_ZMM_H = 6, X64_XStateComponentIdx_ZMM = 7, X64_XStateComponentIdx_PT = 8, X64_XStateComponentIdx_PKRU = 9, X64_XStateComponentIdx_PASID = 10, X64_XStateComponentIdx_CETU = 11, X64_XStateComponentIdx_CETS = 12, X64_XStateComponentIdx_HDC = 13, X64_XStateComponentIdx_UINTR = 14, X64_XStateComponentIdx_LBR = 15, X64_XStateComponentIdx_HWP = 16, X64_XStateComponentIdx_TILECFG = 17, X64_XStateComponentIdx_TILEDATA = 18, }; enum { X64_XStateComponentFlag_FP = (1 << X64_XStateComponentIdx_FP), X64_XStateComponentFlag_SSE = (1 << X64_XStateComponentIdx_SSE), X64_XStateComponentFlag_AVX = (1 << X64_XStateComponentIdx_AVX), X64_XStateComponentFlag_BNDREGS = (1 << X64_XStateComponentIdx_BNDREGS), X64_XStateComponentFlag_BNDCSR = (1 << X64_XStateComponentIdx_BNDCSR), X64_XStateComponentFlag_OPMASK = (1 << X64_XStateComponentIdx_OPMASK), X64_XStateComponentFlag_ZMM_H = (1 << X64_XStateComponentIdx_ZMM_H), X64_XStateComponentFlag_ZMM = (1 << X64_XStateComponentIdx_ZMM), X64_XStateComponentFlag_PT = (1 << X64_XStateComponentIdx_PT), X64_XStateComponentFlag_PKRU = (1 << X64_XStateComponentIdx_PKRU), X64_XStateComponentFlag_PASID = (1 << X64_XStateComponentIdx_PASID), X64_XStateComponentFlag_CETU = (1 << X64_XStateComponentIdx_CETU), X64_XStateComponentFlag_CETS = (1 << X64_XStateComponentIdx_CETS), X64_XStateComponentFlag_HDC = (1 << X64_XStateComponentIdx_HDC), X64_XStateComponentFlag_UINTR = (1 << X64_XStateComponentIdx_UINTR), X64_XStateComponentFlag_LBR = (1 << X64_XStateComponentIdx_LBR), X64_XStateComponentFlag_HWP = (1 << X64_XStateComponentIdx_HWP), X64_XStateComponentFlag_TILECFG = (1 << X64_XStateComponentIdx_TILECFG), X64_XStateComponentFlag_TILEDATA = (1 << X64_XStateComponentIdx_TILEDATA), }; typedef struct { U64 x87_offset; U64 sse_offset; U64 avx_offset; U64 bndregs_offset; U64 bndcfg_offset; U64 opmask_offset; U64 zmm_h_offset; U64 zmm_offset; U64 pt_offset; U64 pkru_offset; U64 pasid_offset; U64 cet_u_offset; U64 cet_s_offset; U64 hdc_offset; U64 uintr_offset; U64 lbr_offset; U64 hwp_offset; U64 tile_cfg_offset; U64 tile_data_offset; } X64_XSaveLayout; //////////////////////////////// //~ Debug Status Register typedef enum { X64_DebugStatusFlag_B0 = (1 << 0), X64_DebugStatusFlag_B1 = (1 << 1), X64_DebugStatusFlag_B2 = (1 << 2), X64_DebugStatusFlag_B3 = (1 << 3), X64_DebugStatusFlag_BusLock = (1 << 11), X64_DebugStatusFlag_DebugRegisterAccess = (1 << 13), X64_DebugStatusFlag_SingleStep = (1 << 14), X64_DebugStatusFlag_TaskSwitch = (1 << 15), X64_DebugStatusFlag_RTM = (1 << 16), } X64_DebugStatusFlags; //////////////////////////////// //~ Debug Control Register typedef enum X64_BreakpointType { X64_BreakpointType_Null, X64_BreakpointType_Local, X64_BreakpointType_Global, } X64_BreakpointType; typedef enum X64_DebugBreakType { X64_DebugBreakType_Null, X64_DebugBreakType_Exec, X64_DebugBreakType_Write, X64_DebugBreakType_ReadWriteIO, X64_DebugBreakType_ReadWriteNoFetch, } X64_DebugBreakType; typedef enum X64_DebugControlFlags { X64_DebugControlFlag_L0 = (1 << 0), X64_DebugControlFlag_L1 = (1 << 2), X64_DebugControlFlag_L2 = (1 << 4), X64_DebugControlFlag_L3 = (1 << 6), X64_DebugControlFlag_G0 = (1 << 1), X64_DebugControlFlag_G1 = (1 << 3), X64_DebugControlFlag_G3 = (1 << 5), X64_DebugControlFlag_G4 = (1 << 7), X64_DebugControlFlag_LE = (1 << 8), X64_DebugControlFlag_GE = (1 << 9), X64_DebugControlFlag_RTM = (1 << 11), X64_DebugControlFlag_GD = (1 << 13), X64_DebugControlFlag_RW0 = (3 << 16), X64_DebugControlFlag_RW1 = (3 << 20), X64_DebugControlFlag_RW2 = (3 << 24), X64_DebugControlFlag_FW3 = (3 << 26), X64_DebugControlFlag_LEN0 = (3 << 18), X64_DebugControlFlag_LEN1 = (3 << 22), X64_DebugControlFlag_LEN2 = (3 << 26), X64_DebugControlFlag_LEN3 = (3 << 30), } X64_DebugControlFlags; //////////////////////////////// //~ cpuid internal void x64_cpuid(U32 leaf, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx); internal void x64_cpuid_ex(U32 leaf, U32 sub_leaf, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx); //////////////////////////////// //~ fxsave/xsave internal B32 x64_is_xsave_supported(void); internal U32 x64_get_xsave_size(void); internal U16 x64_xsave_tag_word_from_real_tag_word(U16 ftw); internal U32 x64_xsave_offset_from_feature_flag(U64 xcr0, X64_XStateComponentIdx comp_idx); internal X64_XSaveLayout x64_get_xsave_layout(U64 xcr0); //////////////////////////////// //~ Debug Control Register internal void x64_set_debug_break(U64 *drs, U64 trap_idx, U64 addr, U64 size, X64_BreakpointType bp_type, X64_DebugBreakType break_type); #endif // BASE_X64_H